summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/PC
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
commitf8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch)
tree26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/Devices/PC
parentInitial commit. (diff)
downloadvirtualbox-upstream.tar.xz
virtualbox-upstream.zip
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/PC')
-rw-r--r--src/VBox/Devices/PC/.scm-settings102
-rw-r--r--src/VBox/Devices/PC/ACPI/Makefile.kup0
-rw-r--r--src/VBox/Devices/PC/ACPI/VBoxAcpi.cpp466
-rw-r--r--src/VBox/Devices/PC/BIOS/Makefile.kmk200
-rw-r--r--src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.asm17427
-rw-r--r--src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.md5sum1
-rw-r--r--src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.asm17325
-rw-r--r--src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.md5sum1
-rw-r--r--src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.asm17844
-rw-r--r--src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.md5sum1
-rw-r--r--src/VBox/Devices/PC/BIOS/ahci.c1047
-rw-r--r--src/VBox/Devices/PC/BIOS/apm.c232
-rw-r--r--src/VBox/Devices/PC/BIOS/apm_pm.asm209
-rw-r--r--src/VBox/Devices/PC/BIOS/ata.c1204
-rw-r--r--src/VBox/Devices/PC/BIOS/ata.h190
-rw-r--r--src/VBox/Devices/PC/BIOS/bios.c191
-rw-r--r--src/VBox/Devices/PC/BIOS/biosint.h311
-rw-r--r--src/VBox/Devices/PC/BIOS/boot.c354
-rw-r--r--src/VBox/Devices/PC/BIOS/disk.c640
-rw-r--r--src/VBox/Devices/PC/BIOS/ebda.h382
-rw-r--r--src/VBox/Devices/PC/BIOS/eltorito.c1025
-rw-r--r--src/VBox/Devices/PC/BIOS/floppy.c1360
-rw-r--r--src/VBox/Devices/PC/BIOS/floppyt.c104
-rw-r--r--src/VBox/Devices/PC/BIOS/font8x8.inc133
-rw-r--r--src/VBox/Devices/PC/BIOS/inlines.h247
-rw-r--r--src/VBox/Devices/PC/BIOS/invop.c350
-rw-r--r--src/VBox/Devices/PC/BIOS/keyboard.c822
-rw-r--r--src/VBox/Devices/PC/BIOS/logo.c558
-rw-r--r--src/VBox/Devices/PC/BIOS/makefile72
-rw-r--r--src/VBox/Devices/PC/BIOS/notes.txt195
-rw-r--r--src/VBox/Devices/PC/BIOS/orgs.asm2069
-rw-r--r--src/VBox/Devices/PC/BIOS/parallel.c91
-rw-r--r--src/VBox/Devices/PC/BIOS/pci32.c22
-rw-r--r--src/VBox/Devices/PC/BIOS/pcibio32.asm98
-rw-r--r--src/VBox/Devices/PC/BIOS/pcibios.c408
-rw-r--r--src/VBox/Devices/PC/BIOS/pcibios.inc362
-rw-r--r--src/VBox/Devices/PC/BIOS/pcicfg.inc6
-rw-r--r--src/VBox/Devices/PC/BIOS/pciutil.c186
-rw-r--r--src/VBox/Devices/PC/BIOS/pciutil.h37
-rw-r--r--src/VBox/Devices/PC/BIOS/pirq.inc477
-rw-r--r--src/VBox/Devices/PC/BIOS/pmode.inc81
-rw-r--r--src/VBox/Devices/PC/BIOS/pmsetup.inc65
-rw-r--r--src/VBox/Devices/PC/BIOS/post.c183
-rw-r--r--src/VBox/Devices/PC/BIOS/print.c296
-rw-r--r--src/VBox/Devices/PC/BIOS/ps2mouse.c452
-rw-r--r--src/VBox/Devices/PC/BIOS/scsi.c700
-rw-r--r--src/VBox/Devices/PC/BIOS/serial.c128
-rw-r--r--src/VBox/Devices/PC/BIOS/smidmi.inc70
-rw-r--r--src/VBox/Devices/PC/BIOS/system.c941
-rw-r--r--src/VBox/Devices/PC/BIOS/timepci.c324
-rw-r--r--src/VBox/Devices/PC/BIOS/vbdmismi.inc27
-rw-r--r--src/VBox/Devices/PC/BIOS/vds.c118
-rw-r--r--src/VBox/Devices/PC/BIOS/vds.h122
-rw-r--r--src/VBox/Devices/PC/DevACPI.cpp4236
-rw-r--r--src/VBox/Devices/PC/DevDMA.cpp1178
-rw-r--r--src/VBox/Devices/PC/DevFwCommon.cpp1193
-rw-r--r--src/VBox/Devices/PC/DevFwCommon.h34
-rw-r--r--src/VBox/Devices/PC/DevHPET.cpp1492
-rw-r--r--src/VBox/Devices/PC/DevIoApic.cpp1429
-rw-r--r--src/VBox/Devices/PC/DevLpc-new.cpp442
-rw-r--r--src/VBox/Devices/PC/DevPIC.cpp1095
-rw-r--r--src/VBox/Devices/PC/DevPcArch.cpp339
-rw-r--r--src/VBox/Devices/PC/DevPcBios.cpp1850
-rw-r--r--src/VBox/Devices/PC/DevPcBios.h52
-rw-r--r--src/VBox/Devices/PC/DevPit-i8254.cpp1581
-rw-r--r--src/VBox/Devices/PC/DevRTC.cpp1299
-rw-r--r--src/VBox/Devices/PC/DrvACPI.cpp1087
-rw-r--r--src/VBox/Devices/PC/DrvAcpiCpu.cpp124
-rw-r--r--src/VBox/Devices/PC/Makefile.kup0
-rw-r--r--src/VBox/Devices/PC/ipxe/COPYING339
-rw-r--r--src/VBox/Devices/PC/ipxe/COPYRIGHTS12
-rw-r--r--src/VBox/Devices/PC/ipxe/Makefile.kmk367
-rw-r--r--src/VBox/Devices/PC/ipxe/README8
-rw-r--r--src/VBox/Devices/PC/ipxe/README.vbox8
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/README9
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/contrib/errdb/errdb.pl108
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/README62
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/bottom.php62
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/build.php306
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/customize-flags.php69
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/directions.php63
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/AUTOBOOT_CMD.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/BANNER_TIMEOUT.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMCONSOLE.html3
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMDATA.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMPARITY.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMPRESERVE.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMSPEED.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMSTOP.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CONFIG_CMD.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CONSOLE_PC_BIOS.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CONSOLE_SERIAL.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CRYPTO_80211_WEP.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CRYPTO_80211_WPA.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CRYPTO_80211_WPA2.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DHCP_CMD.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DNS_RESOLVER.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_FTP.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_HTTP.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_TFTP.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IFMGMT_CMD.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_BZIMAGE.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_CMD.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_ELF.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_MULTIBOOT.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_NBI.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_PXE.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_SCRIPT.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IWMGMT_CMD.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/NMB_RESOLVER.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/NVO_CMD.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/ROUTE_CMD.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/SANBOOT_CMD.html1
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/flag-table.php521
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/globals.php51
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/index.php47
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/top.php41
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/utils.php684
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/vm/Makefile7
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/vm/bochs-writable-ROM-patch15
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/vm/bochsrc.txt751
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/contrib/vm/cow49
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/contrib/vm/serial-console278
-rw-r--r--src/VBox/Devices/PC/ipxe/contrib/vm/serial-console.1190
-rw-r--r--src/VBox/Devices/PC/ipxe/iPxeBiosBin.rombin0 -> 54272 bytes
-rw-r--r--src/VBox/Devices/PC/ipxe/src/Makefile182
-rw-r--r--src/VBox/Devices/PC/ipxe/src/Makefile.housekeeping1254
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile99
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile.efi10
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile.linux6
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile.pcbios87
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/README.i386197
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/basemem_packet.c32
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/cpu.c73
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/dumpregs.c23
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/gdbidt.S215
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/gdbmach.c151
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/linux/linux_syscall.S45
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/linux/linuxprefix.S28
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/nulltrap.c51
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/patch_cf.S38
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/pic8259.c66
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/rdtsc_timer.c89
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/relocate.c136
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/runtime.c264
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/setjmp.S42
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/stack.S15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/stack16.S15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/timer2.c96
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/video_subr.c113
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/virtaddr.S103
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/core/x86_io.c96
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undi.c148
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undiisr.S87
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undiload.c175
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undinet.c722
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undionly.c137
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undipreload.c37
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undirom.c234
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/basemem.c46
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/bios_console.c333
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/e820mangler.S584
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/fakee820.c93
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/hidemem.c220
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/memmap.c322
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c109
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/hci/commands/pxe_cmd.c103
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/hci/commands/reboot_cmd.c66
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/image/bootsector.c119
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/image/bzimage.c551
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/image/com32.c331
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/image/comboot.c326
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/image/elfboot.c109
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/image/multiboot.c485
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/image/nbi.c428
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/image/pxe_image.c108
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/basemem.h35
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/basemem_packet.h15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bios.h11
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bios_disks.h69
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/biosint.h33
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/byteswap.h70
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/compiler.h27
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/cpu.h86
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/endian.h8
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/entropy.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/errfile.h46
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/io.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/linux_api.h6
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/nap.h15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/sanboot.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/smbios.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/stdint.h23
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/time.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/timer.h15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/uaccess.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/umalloc.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bochs.h34
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bootsector.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/bzimage.h142
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/comboot.h177
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/efi/ipxe/dhcp_arch.h41
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/fakee820.h9
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/gdbmach.h64
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/int13.h449
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_nap.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_sanboot.h29
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_smbios.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_timer.h44
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/guestrpc.h68
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/memtop_umalloc.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/rdtsc_timer.h39
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/rtc_entropy.h62
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/rtc_time.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/timer2.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/vmware.h81
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/x86_io.h153
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/kir.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/libkir.h233
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/librm.h201
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/limits.h61
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/memsizes.h19
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/multiboot.h149
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h41
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/pic8259.h73
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/pnpbios.h17
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe.h197
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe_api.h1797
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe_call.h43
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe_types.h127
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxeparent.h11
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/realmode.h127
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/registers.h198
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/rtc.h83
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/setjmp.h40
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/undi.h106
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/undiload.h35
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/undinet.h17
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/undipreload.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/undirom.h53
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/include/vga.h228
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/bios_nap.c16
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c86
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/bios_timer.c65
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/biosint.c92
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/int13.c1986
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c218
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/pcibios.c114
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c198
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/rtc_time.c137
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_call.c291
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_entry.S216
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c60
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_file.c303
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_loader.c50
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c384
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c578
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_udp.c421
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_undi.c1068
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxeparent/pxeparent.c193
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c69
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/com32_call.c207
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/com32_wrapper.S122
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/comboot_call.c707
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/comboot_resolv.c61
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/guestinfo.c281
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/guestrpc.c327
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/vmconsole.c133
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/vmware.c57
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/kir-Makefile26
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/bootpart.S218
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/dskprefix.S383
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/exeprefix.S156
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/hdprefix.S111
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/kkkpxeprefix.S19
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/kkpxeprefix.S14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/kpxeprefix.S10
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/libprefix.S929
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/lkrnprefix.S274
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/mbr.S13
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/mromprefix.S434
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/nbiprefix.S78
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/nullprefix.S13
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/pxeprefix.S766
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/romprefix.S830
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/undiloader.S54
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/unnrv2b.S184
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/unnrv2b16.S9
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/usbdisk.S23
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/scripts/i386-kir.lds200
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/scripts/i386.lds220
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/scripts/linux.lds102
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/liba20.S308
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/libkir.S256
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/libpm.S0
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/librm.S571
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/librm_mgmt.c58
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/Makefile15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/Makefile.efi28
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/Makefile.linux13
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/core/linux/linux_api.c106
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/core/linux/linux_strerror.c169
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/core/pcidirect.c47
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/core/x86_bigint.c90
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/core/x86_string.c63
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/bigint.h318
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/linux_api_platform.h6
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/pci_io.h15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/string.h252
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/include/ipxe/efi/efix86_nap.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/include/ipxe/pcibios.h135
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/include/ipxe/pcidirect.h141
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/include/linux/ipxe/dhcp_arch.h36
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/include/valgrind/memcheck.h309
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/include/valgrind/valgrind.h4536
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/interface/efi/efix86_nap.c48
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/prefix/efidrvprefix.c47
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/prefix/efiprefix.c41
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86/scripts/efi.lds108
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/Makefile41
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/Makefile.efi14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/Makefile.linux6
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/core/linux/linux_syscall.S33
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/core/linux/linuxprefix.S25
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/byteswap.h47
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/compiler.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/endian.h6
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/entropy.h12
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/errfile.h11
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/io.h10
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/linux_api.h6
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/nap.h12
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/sanboot.h12
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/smbios.h10
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/stdint.h21
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/time.h12
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/timer.h10
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/uaccess.h10
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/umalloc.h10
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h41
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/gdbmach.h51
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/limits.h59
-rw-r--r--src/VBox/Devices/PC/ipxe/src/arch/x86_64/scripts/linux.lds102
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/config.c301
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/config_ethernet.c35
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/config_fc.c40
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/config_infiniband.c32
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/config_net80211.c59
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/config_romprefix.c33
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/console.h31
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/defaults.h10
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/defaults/efi.h26
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/defaults/linux.h24
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/defaults/pcbios.h45
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/entropy.h16
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/general.h161
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/ioapi.h19
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/isa.h17
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/local/console.h0
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/local/entropy.h0
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/local/general.h0
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/local/ioapi.h0
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/local/nap.h0
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/local/sanboot.h0
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/local/serial.h0
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/local/time.h0
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/local/timer.h0
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/local/umalloc.h0
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/nap.h19
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/sanboot.h16
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/serial.h37
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/sideband.h15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/time.h16
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/timer.h19
-rw-r--r--src/VBox/Devices/PC/ipxe/src/config/umalloc.h16
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/acpi.c85
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/ansiesc.c116
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/asprintf.c49
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/assert.c30
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/base16.c106
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/base64.c155
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/basename.c64
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/bitmap.c101
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/bitops.c13
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/blockdev.c138
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/console.c135
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/cpio.c42
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/ctype.c48
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/cwuri.c48
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/debug.c192
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/debug_md5.c47
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/device.c135
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/downloader.c268
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/edd.c56
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/errno.c18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/exec.c584
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/fnrec.c202
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/gdbserial.c48
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/gdbstub.c399
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/gdbudp.c259
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/getkey.c84
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/getopt.c278
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/hw.c69
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/i82365.c656
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/image.c441
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/init.c98
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/interface.c291
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/iobuf.c96
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/job.c54
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/linebuf.c111
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/lineconsole.c66
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/log.c62
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/main.c120
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/malloc.c557
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/menu.c177
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/misc.c72
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/monojob.c115
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/null_nap.c3
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/null_sanboot.c45
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/null_time.c29
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/nvo.c320
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/open.c227
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/parseopt.c284
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/pc_kbd.c112
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/pcmcia.c269
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/posix_io.c338
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/process.c132
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/random.c41
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/refcnt.c98
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/resolv.c431
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/serial.c254
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/serial_console.c39
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/settings.c1887
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/string.c355
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/stringextra.c275
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/strtoull.c60
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/time.c137
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/timer.c42
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/uri.c500
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/uuid.c50
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/vsprintf.c439
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/xfer.c366
-rw-r--r--src/VBox/Devices/PC/ipxe/src/core/xferbuf.c117
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/aes_wrap.c123
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/arc4.c131
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/asn1.c840
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/axtls/aes.c457
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/axtls/bigint.h99
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/axtls/bigint_impl.h131
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/axtls/config.h13
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/axtls/crypto.h229
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/axtls/os_port.h54
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/axtls_aes.c159
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/bigint.c134
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/cbc.c101
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/chap.c124
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/clientcert.c182
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/cms.c704
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/crc32.c54
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/crypto_null.c136
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/drbg.c426
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/entropy.c478
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/hash_df.c137
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/hmac.c122
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/hmac_drbg.c358
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/md5.c297
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/null_entropy.c35
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/ocsp.c758
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/random_nz.c75
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/rbg.c114
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/rootcert.c132
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/rsa.c641
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/sha1.c271
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/sha1extra.c167
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/sha256.c255
-rw-r--r--src/VBox/Devices/PC/ipxe/src/crypto/x509.c1577
-rw-r--r--src/VBox/Devices/PC/ipxe/src/doc/build_sys.dox419
-rw-r--r--src/VBox/Devices/PC/ipxe/src/doc/pxe_extensions312
-rw-r--r--src/VBox/Devices/PC/ipxe/src/doxygen.cfg1486
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bitbash/bitbash.c57
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bitbash/i2c_bit.c393
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bitbash/spi_bit.c228
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/block/ata.c678
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/block/ibft.c480
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/block/scsi.c970
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/block/srp.c828
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bus/eisa.c182
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bus/isa.c173
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bus/isa_ids.c26
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bus/isapnp.c764
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bus/mca.c177
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bus/pci.c368
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bus/pcibackup.c90
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bus/pciextra.c86
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bus/pcivpd.c555
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bus/virtio-pci.c64
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/bus/virtio-ring.c136
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/MT25218_PRM.h3460
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/MT25408_PRM.h3404
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/arbel.c3096
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/arbel.h655
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/hermon.c3952
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/hermon.h953
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/linda.c2430
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/linda.h276
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/linda_fw.c1069
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/mlx_bitops.h245
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib7322.c2428
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib7322.h364
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib_7220_regs.h1762
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib_7322_regs.h7261
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib_genbits.pl116
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/linux/linux.c153
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/linux/tap.c249
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/3c503.c5
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/3c509-eisa.c48
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/3c509.c432
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/3c509.h394
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/3c515.c772
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/3c515.txt31
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/3c529.c62
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/3c595.c553
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/3c595.h437
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/3c5x9.c416
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/3c90x.c988
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/3c90x.h308
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/amd8111e.c702
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/amd8111e.h640
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath.h239
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k.c1698
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k.h1279
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_attach.c340
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_caps.c154
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_desc.c544
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_dma.c631
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_eeprom.c1760
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_gpio.c122
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_initvals.c1560
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_pcu.c534
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_phy.c2581
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_qcu.c390
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_reset.c1174
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_rfkill.c107
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/base.h145
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/desc.h332
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/eeprom.h451
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/reg.h2589
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/rfbuffer.h1181
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/rfgain.h516
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ani.h168
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar5008_initvals.h672
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9001_initvals.h1356
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9002_initvals.h3264
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9002_phy.h613
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_2p2_initvals.h1864
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_eeprom.h338
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_mac.h125
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_phy.h1124
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9340_initvals.h1525
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9485_initvals.h1161
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k.c208
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k.h521
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ani.c733
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar5008_phy.c1663
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_calib.c997
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_hw.c607
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_mac.c454
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_phy.c578
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_calib.c932
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_eeprom.c5005
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_hw.c409
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_mac.c669
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_phy.c1277
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_calib.c403
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_common.c69
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom.c551
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_4k.c1078
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_9287.c1019
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_def.c1351
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_hw.c2067
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_init.c593
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_mac.c733
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_main.c916
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_recv.c521
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_xmit.c813
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/calib.h115
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/common.h56
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/eeprom.h714
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/hw-ops.h268
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/hw.h995
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/mac.h707
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/phy.h51
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/reg.h1919
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_hw.c183
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_key.c82
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_main.c59
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_regd.c602
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/reg.h64
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/regd.h263
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ath/regd_common.h481
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/atl1e.c1749
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/atl1e.h1033
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/b44.c953
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/b44.h469
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/bnx2.c2697
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/bnx2.h4598
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/bnx2_fw.h3494
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/cs89x0.c738
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/cs89x0.h481
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/cs89x0.txt45
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/davicom.c708
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/depca.c804
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/dmfe.c1236
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/eepro.c647
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/eepro100.c1173
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/eepro100.h204
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snp.h49
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snpnet.c343
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snpnet.h35
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snponly.c129
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/epic100.c536
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/epic100.h190
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/etherfabric.c4224
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/etherfabric.h553
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/etherfabric_nic.h204
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/forcedeth.c1979
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/forcedeth.h601
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/hfa384x.h3069
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf.h377
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_defines.h1395
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_main.c955
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_mbx.c404
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_mbx.h87
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_osdep.h121
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_regs.h338
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_vf.c455
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_vf.h346
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/intel.c955
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/intel.h252
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ipoib.c795
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/jme.c1308
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/jme.h914
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/legacy.c157
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/mii.c94
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/myri10ge.c1335
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/myri10ge_mcp.h514
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/myson.c677
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/myson.h200
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/natsemi.c936
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/natsemi.h329
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ne.c6
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ne2k_isa.c375
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ns8390.c1037
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/ns8390.h240
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/p80211hdr.h301
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/pcnet32.c1161
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/pcnet32.h181
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/nx_bitops.h194
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/nxhal_nic_interface.h501
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/phantom.c2178
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/phantom.h212
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/phantom_hw.h184
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/pnic.c289
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/pnic_api.h61
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/prism2.c866
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/prism2_pci.c67
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/prism2_plx.c131
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/realtek.c1070
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/realtek.h273
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180.c17
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180_grf5101.c186
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180_max2820.c158
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180_sa2400.c217
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8185.c14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8185_rtl8225.c804
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl818x.c854
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl818x.h359
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/sis190.c1174
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/sis190.h311
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/sis900.c1303
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/sis900.h375
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/skeleton.c317
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/skeleton.h23
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/skge.c2468
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/skge.h2623
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/sky2.c2393
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/sky2.h2176
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/smc9000.c952
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/smc9000.h428
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/sundance.c907
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3.c941
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3.h3424
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3_hw.c2647
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3_phy.c1605
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/tlan.c1732
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/tlan.h500
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/tulip.c1969
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/tulip.txt54
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/via-rhine.c1447
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/via-velocity.c1935
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/via-velocity.h1932
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/virtio-net.c419
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/virtio-net.h44
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/vmxnet3.c669
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/vmxnet3.h497
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge.c18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_config.c1868
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_config.h783
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_main.c718
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_main.h230
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_reg.h4700
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_traffic.c738
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_traffic.h309
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_version.h40
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/w89c840.c973
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/wd.c6
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/net/wlan_compat.h577
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/nvs/nvs.c165
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/nvs/nvsvpd.c233
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/nvs/spi.c140
-rw-r--r--src/VBox/Devices/PC/ipxe/src/drivers/nvs/threewire.c131
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/autoboot_cmd.c57
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/config_cmd.c102
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/dhcp_cmd.c137
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/digest_cmd.c122
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/fcmgmt_cmd.c216
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/gdbstub_cmd.c110
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/ifmgmt_cmd.c181
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/image_cmd.c367
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/image_trust_cmd.c172
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/iwmgmt_cmd.c106
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/login_cmd.c72
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/lotest_cmd.c97
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/menu_cmd.c284
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/nvo_cmd.c240
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/route_cmd.c69
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/sanboot_cmd.c184
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/time_cmd.c79
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/commands/vlan_cmd.c139
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/editstring.c219
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_al.c32
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_az.c24
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_bg.c15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_by.c15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_cf.c24
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_cz.c27
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_de.c46
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_dk.c31
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_es.c29
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_et.c30
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_fi.c38
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_fr.c68
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_gr.c15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_hu.c34
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_il.c15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_it.c32
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_lt.c15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_mk.c15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_mt.c20
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_nl.c34
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_no-latin1.c34
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_no.c105
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_pl.c15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_pt.c29
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_ro.c15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_ru.c15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_sg.c41
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_sr.c35
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_th.c15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_ua.c15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_uk.c19
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_us.c15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_wo.c55
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/linux_args.c190
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/alert.c18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/ansi_screen.c86
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/clear.c90
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/colour.c66
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/cursor.h37
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/edging.c111
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/kb.c143
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/mucurses.c146
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/mucurses.h23
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/print.c86
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/print_nadv.c26
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/slk.c363
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/widgets/editbox.c102
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/winattrs.c133
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/windows.c158
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/mucurses/wininit.c37
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/readline.c324
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/shell.c137
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/strerror.c125
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/tui/login_ui.c137
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/tui/menu_ui.c364
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/tui/settings_ui.c573
-rw-r--r--src/VBox/Devices/PC/ipxe/src/hci/wireless_errors.c108
-rw-r--r--src/VBox/Devices/PC/ipxe/src/image/efi_image.c225
-rw-r--r--src/VBox/Devices/PC/ipxe/src/image/elf.c184
-rw-r--r--src/VBox/Devices/PC/ipxe/src/image/embedded.c91
-rw-r--r--src/VBox/Devices/PC/ipxe/src/image/script.c359
-rw-r--r--src/VBox/Devices/PC/ipxe/src/image/segment.c90
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/alloca.h25
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/assert.h70
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/big_bswap.h33
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/bootp.h230
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/byteswap.h59
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/coff.h73
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/compiler.h752
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/cpu.h6
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ctype.h32
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/curses.h755
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/elf.h234
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/endian.h21
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/errno.h761
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/etherboot.h43
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/fs.h41
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/getopt.h94
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/hci/ifmgmt_cmd.h37
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/hci/linux_args.h31
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/i82365.h452
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/acpi.h63
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/aes.h34
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ansiesc.h127
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/aoe.h131
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/api.h84
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/arc4.h22
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/arp.h42
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/asn1.h303
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ata.h204
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/base16.h38
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/base64.h41
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/bigint.h301
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/bitbash.h52
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/bitmap.h85
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/bitops.h230
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/blockdev.h55
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/bofm.h351
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/cbc.h100
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/chap.h53
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/clientcert.h43
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/cms.h75
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/command.h28
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/console.h163
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/cpio.h53
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/crc32.h10
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/crypto.h252
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/device.h148
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/dhcp.h678
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/dhcpopts.h43
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/dhcppkt.h71
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/dns.h92
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/downloader.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/drbg.h135
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/eapol.h113
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/edd.h193
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/editbox.h61
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/editstring.h48
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Base.h965
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/HiiFormMapMethodGuid.h27
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/HiiPlatformSetupFormset.h37
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/MdeModuleHii.h222
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/PcAnsi.h60
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/SmBios.h34
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/WinCertificate.h130
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Ia32/ProcessorBind.h280
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/IndustryStandard/Pci22.h817
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/IndustryStandard/PeImage.h757
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/LICENCE40
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiBootMode.h43
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiDependency.h49
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiDxeCis.h715
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiFirmwareFile.h482
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiFirmwareVolume.h233
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiHob.h451
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiMultiPhase.h138
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiS3BootScript.h61
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiStatusCode.h1130
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/PiDxe.h27
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/ProcessorBind.h19
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/ComponentName2.h175
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/Cpu.h300
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/CpuIo.h48
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/CpuIo2.h144
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/DebugSupport.h685
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/DevicePath.h1074
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/DriverBinding.h203
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/FormBrowser2.h177
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/HiiConfigAccess.h221
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/HiiDatabase.h519
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/LoadedImage.h90
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/NetworkInterfaceIdentifier.h93
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/PciIo.h560
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/PciRootBridgeIo.h438
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/SimpleNetwork.h664
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/SimpleTextIn.h138
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/SimpleTextOut.h406
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi.h29
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiBaseType.h287
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiGpt.h142
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h2068
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiMultiPhase.h171
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiPxe.h1772
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiSpec.h2099
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/X64/ProcessorBind.h290
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi.h148
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_driver.h49
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_hii.h140
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_io.h180
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_pci.h46
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_pci_api.h148
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_smbios.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_strings.h23
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_timer.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_uaccess.h90
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_umalloc.h18
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/include/ipxe/efi/import.pl135
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/ipxe_download.h154
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/eisa.h128
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/elf.h17
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/entropy.h224
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/errfile.h267
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/errortab.h28
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/eth_slow.h255
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ethernet.h95
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/fakedhcp.h23
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/fc.h538
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/fcels.h445
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/fcns.h217
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/fcoe.h92
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/fcp.h166
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/features.h106
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/fip.h450
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ftp.h15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/gdbserial.h21
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/gdbstub.h77
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/gdbudp.h24
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/hash_df.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/hidemem.h17
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/hmac.h32
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/hmac_drbg.h253
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/http.h24
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/i2c.h171
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_cm.h72
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_cmrc.h20
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_mad.h591
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_mcast.h48
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_mi.h135
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_packet.h160
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_pathrec.h76
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_sma.h20
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_smc.h20
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_srp.h58
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ibft.h271
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/icmp.h25
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/icmp6.h59
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ieee80211.h1161
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/if_arp.h102
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/if_ether.h39
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/image.h207
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/in.h104
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/infiniband.h705
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/init.h88
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/interface.h234
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/io.h532
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/iobuf.h229
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ip.h89
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ip6.h80
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ipoib.h58
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/isa.h95
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/isa_ids.h51
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/isapnp.h285
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/iscsi.h700
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/job.h38
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/keymap.h30
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/keys.h88
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/linebuf.h30
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/lineconsole.h36
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/linux.h144
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_entropy.h32
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_nap.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_smbios.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_time.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_timer.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_uaccess.h104
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_umalloc.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/linux_compat.h27
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/list.h463
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/login_ui.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/malloc.h81
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/mca.h106
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/md5.h73
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/menu.h49
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/mii.h86
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/monojob.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/nap.h57
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ndp.h21
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/net80211.h1207
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/net80211_err.h633
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/netdevice.h681
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/null_entropy.h52
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/null_nap.h23
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/null_sanboot.h23
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/null_time.h23
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/nvo.h52
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/nvs.h68
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/nvsvpd.h33
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/ocsp.h108
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/open.h106
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/parseopt.h129
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/pci.h448
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/pci_ids.h351
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/pci_io.h124
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/pcibackup.h33
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/pcivpd.h181
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/posix_io.h87
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/process.h205
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/profile.h80
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/random_nz.h16
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/rarp.h16
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/rbg.h43
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/rc80211.h19
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/refcnt.h114
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/resolv.h51
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/retry.h111
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/rootcert.h16
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/rotate.h33
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/rsa.h81
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/sanboot.h100
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/script.h16
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/scsi.h310
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/sec80211.h52
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/segment.h17
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/serial.h16
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/settings.h383
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/settings_ui.h16
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/sha1.h80
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/sha256.h73
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/shell.h36
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/smbios.h162
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/socket.h102
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/spi.h258
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/spi_bit.h63
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/srp.h833
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/syslog.h38
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/tables.h518
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/tcp.h352
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/tcpip.h128
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/test.h45
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/tftp.h85
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/threewire.h118
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/time.h59
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/timer.h77
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/tls.h270
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/uaccess.h345
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/udp.h45
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/umalloc.h69
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/uri.h192
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/uuid.h33
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/validator.h17
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/virtio-pci.h101
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/virtio-ring.h142
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/vlan.h69
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/vsprintf.h74
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/wpa.h503
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/x509.h373
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/xfer.h107
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/ipxe/xferbuf.h31
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/libgen.h9
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/linux_api.h72
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/little_bswap.h35
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/mii.h157
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/nic.h280
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/old_tcp.h37
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/pc_kbd.h7
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/pcmcia-opts.h23
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/pcmcia.h156
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/readline/readline.h57
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/stdarg.h38
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/stddef.h30
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/stdint.h36
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/stdio.h51
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/stdlib.h111
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/string.h51
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/strings.h65
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/sys/time.h18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/sys_info.h33
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/syslog.h100
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/time.h51
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/unistd.h43
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/usr/autoboot.h37
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/usr/dhcpmgmt.h17
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/usr/fcmgmt.h21
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/usr/ifmgmt.h19
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/usr/imgmgmt.h19
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/usr/imgtrust.h17
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/usr/iwmgmt.h17
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/usr/lotest.h15
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/usr/prompt.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/include/usr/route.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/bofm/bofm.c340
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_bofm.c402
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_console.c284
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_download.c233
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_driver.c140
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_init.c162
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_io.c217
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_pci.c529
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_smbios.c64
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_snp.c1342
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_strerror.c45
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_strings.c147
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_timer.c118
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_uaccess.c39
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/efi/efi_umalloc.c98
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/linux/linux_console.c155
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/linux/linux_entropy.c96
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/linux/linux_nap.c40
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/linux/linux_smbios.c37
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/linux/linux_time.c54
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/linux/linux_timer.c80
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/linux/linux_uaccess.c38
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/linux/linux_umalloc.c154
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/smbios/smbios.c180
-rw-r--r--src/VBox/Devices/PC/ipxe/src/interface/smbios/smbios_settings.c210
-rw-r--r--src/VBox/Devices/PC/ipxe/src/libgcc/__divdi3.c26
-rw-r--r--src/VBox/Devices/PC/ipxe/src/libgcc/__moddi3.c26
-rw-r--r--src/VBox/Devices/PC/ipxe/src/libgcc/__udivdi3.c10
-rw-r--r--src/VBox/Devices/PC/ipxe/src/libgcc/__udivmoddi4.c32
-rw-r--r--src/VBox/Devices/PC/ipxe/src/libgcc/__umoddi3.c13
-rw-r--r--src/VBox/Devices/PC/ipxe/src/libgcc/icc.c8
-rw-r--r--src/VBox/Devices/PC/ipxe/src/libgcc/libgcc.h14
-rw-r--r--src/VBox/Devices/PC/ipxe/src/libgcc/memcpy.c18
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/80211/net80211.c2829
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/80211/rc80211.c371
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/80211/sec80211.c517
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/80211/wep.c303
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/80211/wpa.c914
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/80211/wpa_ccmp.c529
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/80211/wpa_psk.c126
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/80211/wpa_tkip.c587
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/aoe.c1056
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/arp.c504
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/cachedhcp.c77
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/dhcpopts.c462
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/dhcppkt.c303
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/eapol.c87
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/eth_slow.c272
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/ethernet.c201
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/fakedhcp.c220
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/fc.c1936
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/fcels.c1338
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/fcns.c240
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/fcoe.c1228
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/fcp.c1092
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/icmp.c103
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/icmpv6.c126
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/infiniband.c993
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_cm.c495
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_cmrc.c437
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_mcast.c212
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_mi.c406
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_packet.c241
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_pathrec.c288
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_sma.c370
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_smc.c255
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_srp.c581
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/iobpad.c68
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/ipv4.c714
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/ipv6.c384
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/ndp.c180
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/netdev_settings.c140
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/netdevice.c796
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/nullnet.c60
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/rarp.c74
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/retry.c203
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/tcp.c1383
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/tcp/ftp.c470
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/tcp/http.c50
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/tcp/httpcore.c938
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/tcp/https.c51
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/tcp/iscsi.c2139
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/tcp/syslogs.c275
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/tcpip.c135
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/tls.c2409
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/udp.c447
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/udp/dhcp.c1480
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/udp/dns.c646
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/udp/slam.c756
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/udp/syslog.c211
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/udp/tftp.c1259
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/validator.c460
-rw-r--r--src/VBox/Devices/PC/ipxe/src/net/vlan.c493
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/aes_cbc_test.c180
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/bigint_test.c2436
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/bofm_test.c169
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/byteswap_test.c91
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/cbc_test.c96
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/cbc_test.h53
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/cms_test.c1437
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/comboot/shuffle-simple.asm40
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/comboot/version.asm136
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/crc32_test.c125
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/digest_test.c69
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/digest_test.h36
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/entropy_sample.c71
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/gdbstub_test.S54
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/tests/gdbstub_test.gdb116
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/hash_df_test.c897
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/hmac_drbg_test.c1385
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/linebuf_test.c35
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/list_test.c482
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/md5_test.c93
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/memcpy_test.c39
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/ocsp_test.c1534
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/pubkey_test.h175
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/rsa_test.c491
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/settings_test.c279
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/sha1_test.c98
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/sha256_test.c101
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/test.c173
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/tests.c43
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/time_test.c182
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/umalloc_test.c26
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/uri_test.c146
-rw-r--r--src/VBox/Devices/PC/ipxe/src/tests/x509_test.c947
-rw-r--r--src/VBox/Devices/PC/ipxe/src/usr/autoboot.c461
-rw-r--r--src/VBox/Devices/PC/ipxe/src/usr/dhcpmgmt.c80
-rw-r--r--src/VBox/Devices/PC/ipxe/src/usr/fcmgmt.c115
-rw-r--r--src/VBox/Devices/PC/ipxe/src/usr/ifmgmt.c151
-rw-r--r--src/VBox/Devices/PC/ipxe/src/usr/imgmgmt.c152
-rw-r--r--src/VBox/Devices/PC/ipxe/src/usr/imgtrust.c96
-rw-r--r--src/VBox/Devices/PC/ipxe/src/usr/iwmgmt.c225
-rw-r--r--src/VBox/Devices/PC/ipxe/src/usr/lotest.c249
-rw-r--r--src/VBox/Devices/PC/ipxe/src/usr/prompt.c66
-rw-r--r--src/VBox/Devices/PC/ipxe/src/usr/pxemenu.c383
-rw-r--r--src/VBox/Devices/PC/ipxe/src/usr/route.c45
-rw-r--r--src/VBox/Devices/PC/ipxe/src/util/Makefile16
-rw-r--r--src/VBox/Devices/PC/ipxe/src/util/Option/ROM.pm502
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/catrom.pl48
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/diffsize.pl101
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/disrom.pl81
-rw-r--r--src/VBox/Devices/PC/ipxe/src/util/efirom.c268
-rw-r--r--src/VBox/Devices/PC/ipxe/src/util/einfo.c168
-rw-r--r--src/VBox/Devices/PC/ipxe/src/util/elf2efi.c814
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/fixrom.pl34
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/fnrec.pl145
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/geniso72
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/genkeymap.pl237
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/genliso74
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/gensdsk65
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/get-pci-ids135
-rw-r--r--src/VBox/Devices/PC/ipxe/src/util/hijack.c628
-rw-r--r--src/VBox/Devices/PC/ipxe/src/util/iccfix.c157
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/licence.pl149
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/mergerom.pl98
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/modrom.pl226
-rw-r--r--src/VBox/Devices/PC/ipxe/src/util/mucurses_test.c63
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/niclist.pl588
-rw-r--r--src/VBox/Devices/PC/ipxe/src/util/nrv2b.c1514
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/padimg.pl44
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/parserom.pl66
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/romcheck.pl54
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/sortobjdump.pl40
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/swapdevids.pl49
-rwxr-xr-xsrc/VBox/Devices/PC/ipxe/src/util/symcheck.pl191
-rw-r--r--src/VBox/Devices/PC/ipxe/src/util/zbin.c442
-rw-r--r--src/VBox/Devices/PC/vbox-cpuhotplug.dsl194
-rw-r--r--src/VBox/Devices/PC/vbox-standard.dsl263
-rw-r--r--src/VBox/Devices/PC/vbox.dsl1938
1270 files changed, 492190 insertions, 0 deletions
diff --git a/src/VBox/Devices/PC/.scm-settings b/src/VBox/Devices/PC/.scm-settings
new file mode 100644
index 00000000..ce3db64b
--- /dev/null
+++ b/src/VBox/Devices/PC/.scm-settings
@@ -0,0 +1,102 @@
+# $Id: .scm-settings $
+## @file
+# Source code massager settings for PC devices/drivers.
+#
+
+#
+# Copyright (C) 2017-2019 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+
+
+--filter-out-files /BIOS/notes.txt
+--filter-out-files /BIOS/makefile
+--filter-out-files /BIOS/VBoxBiosAlternative*.asm
+--filter-out-files /BIOS/VBoxBiosAlternative*.md5sum
+
+# PD
+/BIOS/font8x8.inc: --external-copyright
+# ???
+/BIOS/pcicfg.inc: --external-copyright
+
+# LGPL turned GPL.
+/BIOS/ata.c: --lgpl-disclaimer
+/BIOS/ata.h: --lgpl-disclaimer
+/BIOS/bios.c: --lgpl-disclaimer
+/BIOS/biosint.h: --lgpl-disclaimer
+/BIOS/boot.c: --lgpl-disclaimer
+/BIOS/disk.c: --lgpl-disclaimer
+/BIOS/ebda.h: --lgpl-disclaimer
+/BIOS/eltorito.c: --lgpl-disclaimer
+/BIOS/floppy.c: --lgpl-disclaimer
+/BIOS/keyboard.c: --lgpl-disclaimer
+/BIOS/orgs.asm: --lgpl-disclaimer
+/BIOS/parallel.c: --lgpl-disclaimer
+/BIOS/pcibios.inc: --lgpl-disclaimer
+/BIOS/pirq.inc: --lgpl-disclaimer
+/BIOS/print.c: --lgpl-disclaimer
+/BIOS/ps2mouse.c: --lgpl-disclaimer
+/BIOS/serial.c: --lgpl-disclaimer
+/BIOS/smidmi.inc: --lgpl-disclaimer
+/BIOS/system.c: --lgpl-disclaimer
+/BIOS/timepci.c: --lgpl-disclaimer
+
+# For now don't mess up the tabs in the BIOS assembly sources.
+/BIOS/*.asm|/BIOS/*.inc: --no-convert-tabs
+
+# PXE
+/PXE/*.asm: --external-copyright --no-convert-tabs --no-strip-trailing-blanks
+/PXE/*.c: --external-copyright --no-convert-tabs --no-strip-trailing-blanks
+/PXE/*.h: --external-copyright --no-convert-tabs --no-strip-trailing-blanks --dont-set-svn-keywords --no-fix-header-guards
+/PXE/*.inc: --external-copyright --no-convert-tabs --no-strip-trailing-blanks
+/PXE/*.i: --external-copyright --no-convert-tabs --no-strip-trailing-blanks --strip-no-trailing-lines --treat-as .inc
+/PXE/*.r: --external-copyright --no-convert-tabs --no-strip-trailing-blanks --strip-no-trailing-lines --treat-as .inc
+/PXE/*makefile: --external-copyright --no-convert-tabs --no-strip-trailing-blanks --treat-as Makefile
+/PXE/romcfg: --external-copyright --no-convert-tabs --no-strip-trailing-blanks --treat-as Makefile
+/PXE/defrules: --external-copyright --no-convert-tabs --no-strip-trailing-blanks --treat-as Makefile
+/PXE/defrules: --external-copyright --no-convert-tabs --no-strip-trailing-blanks --treat-as Makefile
+/PXE/deftargs: --external-copyright --no-convert-tabs --no-strip-trailing-blanks --treat-as Makefile
+/PXE/hostcfg: --external-copyright --no-convert-tabs --no-strip-trailing-blanks --treat-as Makefile
+--filter-out-files /PXE/PXE-Intel.rom
+--filter-out-files /PXE/readme.txt
+
+# iPXE
+/ipxe/src/*: --external-copyright --lgpl-disclaimer --no-convert-tabs --no-strip-trailing-blanks --dont-set-svn-keywords --no-fix-todos --strip-no-trailing-lines --no-convert-eol
+/ipxe/contrib/*: --external-copyright --lgpl-disclaimer --no-convert-tabs --no-strip-trailing-blanks --dont-set-svn-keywords --no-fix-todos --strip-no-trailing-lines --no-convert-eol
+/ipxe/*.S: --treat-as .c
+/ipxe/*.lds: --treat-as .h
+/ipxe/*.gdb: --treat-as .sh --dont-set-svn-executable
+/ipxe/*Makefile*: --treat-as Makefile
+/ipxe/src/util/geniso: --treat-as .sh
+/ipxe/src/util/genliso: --treat-as .sh
+/ipxe/src/util/gensdsk: --treat-as .sh
+/ipxe/src/util/get-pci-ids: --treat-as .sh
+/ipxe/contrib/vm/cow: --treat-as .sh
+/ipxe/contrib/vm/serial-console: --treat-as .pl
+/ipxe/*: --no-fix-header-guards
+
+--filter-out-files /ipxe/*.txt
+--filter-out-files /ipxe/COPYING
+--filter-out-files /ipxe/COPYRIGHTS
+--filter-out-files /ipxe/ipxeBiosBin.rom
+--filter-out-files /ipxe/README
+--filter-out-files /ipxe/README.vbox
+--filter-out-files /ipxe/iPxeBiosBin.rom
+--filter-out-files /ipxe/src/arch/i386/README.i386
+--filter-out-files /ipxe/src/doxygen.cfg
+--filter-out-files /ipxe/src/doc/build_sys.dox
+--filter-out-files /ipxe/src/doc/pxe_extensions
+--filter-out-files /ipxe/src/include/ipxe/efi/LICENCE
+--filter-out-files /ipxe/contrib/README
+--filter-out-files /ipxe/contrib/vm/bochs-writable-ROM-patch
+--filter-out-files /ipxe/contrib/vm/serial-console.1
+--filter-out-dirs /ipxe/contrib/rom-o-matic/.
+
diff --git a/src/VBox/Devices/PC/ACPI/Makefile.kup b/src/VBox/Devices/PC/ACPI/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Devices/PC/ACPI/Makefile.kup
diff --git a/src/VBox/Devices/PC/ACPI/VBoxAcpi.cpp b/src/VBox/Devices/PC/ACPI/VBoxAcpi.cpp
new file mode 100644
index 00000000..4634aa06
--- /dev/null
+++ b/src/VBox/Devices/PC/ACPI/VBoxAcpi.cpp
@@ -0,0 +1,466 @@
+/* $Id: VBoxAcpi.cpp $ */
+/** @file
+ * VBoxAcpi - VirtualBox ACPI manipulation functionality.
+ */
+
+/*
+ * Copyright (C) 2009-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <iprt/cdefs.h>
+#if !defined(IN_RING3)
+# error Pure R3 code
+#endif
+
+#define LOG_GROUP LOG_GROUP_DEV_ACPI
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/vmm/pgm.h>
+#include <VBox/log.h>
+#include <VBox/param.h>
+#include <VBox/vmm/cfgm.h>
+#include <VBox/vmm/mm.h>
+#include <iprt/assert.h>
+#include <iprt/alloc.h>
+#include <iprt/string.h>
+#include <iprt/file.h>
+
+#ifdef VBOX_WITH_DYNAMIC_DSDT
+/* vbox.dsl - input to generate proper DSDT on the fly */
+# include <vboxdsl.hex>
+#else
+/* Statically compiled AML */
+# include <vboxaml.hex>
+# include <vboxssdt_standard.hex>
+# include <vboxssdt_cpuhotplug.hex>
+#endif
+
+#include "VBoxDD.h"
+
+
+#ifdef VBOX_WITH_DYNAMIC_DSDT
+
+static int prepareDynamicDsdt(PPDMDEVINS pDevIns, void **ppvPtr, size_t *pcbDsdt)
+{
+ *ppvPtr = NULL;
+ *pcbDsdt = 0;
+ return 0;
+}
+
+static int cleanupDynamicDsdt(PPDMDEVINS pDevIns, void *pvPtr)
+{
+ return 0;
+}
+
+#else /* VBOX_WITH_DYNAMIC_DSDT */
+
+static int patchAml(PPDMDEVINS pDevIns, uint8_t *pabAml, size_t cbAml)
+{
+ uint16_t cNumCpus;
+ int rc;
+
+ rc = CFGMR3QueryU16Def(pDevIns->pCfg, "NumCPUs", &cNumCpus, 1);
+
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /* Clear CPU objects at all, if needed */
+ bool fShowCpu;
+ rc = CFGMR3QueryBoolDef(pDevIns->pCfg, "ShowCpu", &fShowCpu, false);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ if (!fShowCpu)
+ cNumCpus = 0;
+
+ /**
+ * Now search AML for:
+ * AML_PROCESSOR_OP (UINT16) 0x5b83
+ * and replace whole block with
+ * AML_NOOP_OP (UINT16) 0xa3
+ * for VCPU not configured
+ */
+ for (uint32_t i = 0; i < cbAml - 7; i++)
+ {
+ /*
+ * AML_PROCESSOR_OP
+ *
+ * DefProcessor := ProcessorOp PkgLength NameString ProcID
+ PblkAddr PblkLen ObjectList
+ * ProcessorOp := ExtOpPrefix 0x83
+ * ProcID := ByteData
+ * PblkAddr := DwordData
+ * PblkLen := ByteData
+ */
+ if (pabAml[i] == 0x5b && pabAml[i+1] == 0x83)
+ {
+ if (pabAml[i+3] != 'C' || pabAml[i+4] != 'P')
+ /* false alarm, not named starting CP */
+ continue;
+
+ /* Processor ID */
+ if (pabAml[i+7] < cNumCpus)
+ continue;
+
+ /* Will fill unwanted CPU block with NOOPs */
+ /*
+ * See 18.2.4 Package Length Encoding in ACPI spec
+ * for full format
+ */
+ uint32_t cBytes = pabAml[i + 2];
+ AssertReleaseMsg((cBytes >> 6) == 0,
+ ("So far, we only understand simple package length"));
+
+ /* including AML_PROCESSOR_OP itself */
+ for (uint32_t j = 0; j < cBytes + 2; j++)
+ pabAml[i+j] = 0xa3;
+
+ /* Can increase i by cBytes + 1, but not really worth it */
+ }
+ }
+
+ /* now recompute checksum, whole file byte sum must be 0 */
+ pabAml[9] = 0;
+ uint8_t bSum = 0;
+ for (uint32_t i = 0; i < cbAml; i++)
+ bSum = bSum + pabAml[i];
+ pabAml[9] = (uint8_t)(0 - bSum);
+
+ return 0;
+}
+
+/**
+ * Patch the CPU hot-plug SSDT version to
+ * only contain the ACPI containers which may have a CPU
+ */
+static int patchAmlCpuHotPlug(PPDMDEVINS pDevIns, uint8_t *pabAml, size_t cbAml)
+{
+ uint16_t cNumCpus;
+ int rc;
+ uint32_t idxAml = 0;
+
+ rc = CFGMR3QueryU16Def(pDevIns->pCfg, "NumCPUs", &cNumCpus, 1);
+
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /**
+ * Now search AML for:
+ * AML_DEVICE_OP (UINT16) 0x5b82
+ * and replace whole block with
+ * AML_NOOP_OP (UINT16) 0xa3
+ * for VCPU not configured
+ */
+ while (idxAml < cbAml - 7)
+ {
+ /*
+ * AML_DEVICE_OP
+ *
+ * DefDevice := DeviceOp PkgLength NameString ObjectList
+ * DeviceOp := ExtOpPrefix 0x82
+ */
+ if (pabAml[idxAml] == 0x5b && pabAml[idxAml+1] == 0x82)
+ {
+ /* Check if the enclosed CPU device is configured. */
+ uint8_t *pabAmlPkgLength = &pabAml[idxAml+2];
+ uint32_t cBytes = 0;
+ uint32_t cLengthBytesFollow = pabAmlPkgLength[0] >> 6;
+
+ if (cLengthBytesFollow == 0)
+ {
+ /* Simple package length */
+ cBytes = pabAmlPkgLength[0];
+ }
+ else
+ {
+ unsigned idxLengthByte = 1;
+
+ cBytes = pabAmlPkgLength[0] & 0xF;
+
+ while (idxLengthByte <= cLengthBytesFollow)
+ {
+ cBytes |= pabAmlPkgLength[idxLengthByte] << (4*idxLengthByte);
+ idxLengthByte++;
+ }
+ }
+
+ uint8_t *pabAmlDevName = &pabAmlPkgLength[cLengthBytesFollow+1];
+ uint8_t *pabAmlCpu = &pabAmlDevName[4];
+ bool fCpuConfigured = false;
+ bool fCpuFound = false;
+
+ if ((pabAmlDevName[0] != 'S') || (pabAmlDevName[1] != 'C') || (pabAmlDevName[2] != 'K'))
+ {
+ /* false alarm, not named starting SCK */
+ idxAml++;
+ continue;
+ }
+
+ for (uint32_t idxAmlCpu = 0; idxAmlCpu < cBytes - 7; idxAmlCpu++)
+ {
+ /*
+ * AML_PROCESSOR_OP
+ *
+ * DefProcessor := ProcessorOp PkgLength NameString ProcID
+ PblkAddr PblkLen ObjectList
+ * ProcessorOp := ExtOpPrefix 0x83
+ * ProcID := ByteData
+ * PblkAddr := DwordData
+ * PblkLen := ByteData
+ */
+ if ((pabAmlCpu[idxAmlCpu] == 0x5b) && (pabAmlCpu[idxAmlCpu+1] == 0x83))
+ {
+ if ((pabAmlCpu[idxAmlCpu+4] != 'C') || (pabAmlCpu[idxAmlCpu+5] != 'P'))
+ /* false alarm, not named starting CP */
+ continue;
+
+ fCpuFound = true;
+
+ /* Processor ID */
+ uint8_t const idAmlCpu = pabAmlCpu[idxAmlCpu + 8];
+ if (idAmlCpu < cNumCpus)
+ {
+ LogFlow(("CPU %u is configured\n", idAmlCpu));
+ fCpuConfigured = true;
+ }
+ else
+ {
+ LogFlow(("CPU %u is not configured\n", idAmlCpu));
+ fCpuConfigured = false;
+ }
+ break;
+ }
+ }
+
+ Assert(fCpuFound);
+
+ if (!fCpuConfigured)
+ {
+ /* Will fill unwanted CPU block with NOOPs */
+ /*
+ * See 18.2.4 Package Length Encoding in ACPI spec
+ * for full format
+ */
+
+ /* including AML_DEVICE_OP itself */
+ for (uint32_t j = 0; j < cBytes + 2; j++)
+ pabAml[idxAml+j] = 0xa3;
+ }
+
+ idxAml++;
+ }
+ else
+ idxAml++;
+ }
+
+ /* now recompute checksum, whole file byte sum must be 0 */
+ pabAml[9] = 0;
+ uint8_t bSum = 0;
+ for (uint32_t i = 0; i < cbAml; i++)
+ bSum = bSum + pabAml[i];
+ pabAml[9] = (uint8_t)(0 - bSum);
+
+ return 0;
+}
+
+#endif /* VBOX_WITH_DYNAMIC_DSDT */
+
+/**
+ * Loads an AML file if present in CFGM
+ *
+ * @returns VBox status code
+ * @param pDevIns The device instance
+ * @param pcszCfgName The configuration key holding the file path
+ * @param pcszSignature The signature to check for
+ * @param ppabAmlCode Where to store the pointer to the AML code on success.
+ * @param pcbAmlCode Where to store the number of bytes of the AML code on success.
+ */
+static int acpiAmlLoadExternal(PPDMDEVINS pDevIns, const char *pcszCfgName, const char *pcszSignature, uint8_t **ppabAmlCode, size_t *pcbAmlCode)
+{
+ uint8_t *pabAmlCode = NULL;
+ size_t cbAmlCode = 0;
+ char *pszAmlFilePath = NULL;
+ int rc = CFGMR3QueryStringAlloc(pDevIns->pCfg, pcszCfgName, &pszAmlFilePath);
+
+ if (RT_SUCCESS(rc))
+ {
+ /* Load from file. */
+ RTFILE FileAml = NIL_RTFILE;
+
+ rc = RTFileOpen(&FileAml, pszAmlFilePath, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * An AML file contains the raw DSDT thus the size of the file
+ * is equal to the size of the DSDT.
+ */
+ uint64_t cbAmlFile = 0;
+ rc = RTFileGetSize(FileAml, &cbAmlFile);
+
+ cbAmlCode = (size_t)cbAmlFile;
+
+ /* Don't use AML files over 4GB ;) */
+ if ( RT_SUCCESS(rc)
+ && ((uint64_t)cbAmlCode == cbAmlFile))
+ {
+ pabAmlCode = (uint8_t *)RTMemAllocZ(cbAmlCode);
+ if (pabAmlCode)
+ {
+ rc = RTFileReadAt(FileAml, 0, pabAmlCode, cbAmlCode, NULL);
+
+ /*
+ * We fail if reading failed or the identifier at the
+ * beginning is wrong.
+ */
+ if ( RT_FAILURE(rc)
+ || strncmp((const char *)pabAmlCode, pcszSignature, 4))
+ {
+ RTMemFree(pabAmlCode);
+ pabAmlCode = NULL;
+
+ /* Return error if file header check failed */
+ if (RT_SUCCESS(rc))
+ rc = VERR_PARSE_ERROR;
+ }
+ else
+ {
+ *ppabAmlCode = pabAmlCode;
+ *pcbAmlCode = cbAmlCode;
+ rc = VINF_SUCCESS;
+ }
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+
+ RTFileClose(FileAml);
+ }
+ MMR3HeapFree(pszAmlFilePath);
+ }
+
+ return rc;
+}
+
+
+/** No docs, lazy coder. */
+int acpiPrepareDsdt(PPDMDEVINS pDevIns, void **ppvPtr, size_t *pcbDsdt)
+{
+#ifdef VBOX_WITH_DYNAMIC_DSDT
+ return prepareDynamicDsdt(pDevIns, ppvPtr, pcbDsdt);
+#else
+ uint8_t *pabAmlCodeDsdt = NULL;
+ size_t cbAmlCodeDsdt = 0;
+ int rc = acpiAmlLoadExternal(pDevIns, "DsdtFilePath", "DSDT", &pabAmlCodeDsdt, &cbAmlCodeDsdt);
+
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+ {
+ rc = VINF_SUCCESS;
+
+ /* Use the compiled in AML code */
+ cbAmlCodeDsdt = sizeof(AmlCode);
+ pabAmlCodeDsdt = (uint8_t *)RTMemAllocZ(cbAmlCodeDsdt);
+ if (pabAmlCodeDsdt)
+ memcpy(pabAmlCodeDsdt, AmlCode, cbAmlCodeDsdt);
+ else
+ rc = VERR_NO_MEMORY;
+ }
+ else if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"DsdtFilePath\""));
+
+ if (RT_SUCCESS(rc))
+ {
+ patchAml(pDevIns, pabAmlCodeDsdt, cbAmlCodeDsdt);
+ *ppvPtr = pabAmlCodeDsdt;
+ *pcbDsdt = cbAmlCodeDsdt;
+ }
+ return rc;
+#endif
+}
+
+/** No docs, lazy coder. */
+int acpiCleanupDsdt(PPDMDEVINS pDevIns, void *pvPtr)
+{
+#ifdef VBOX_WITH_DYNAMIC_DSDT
+ return cleanupDynamicDsdt(pDevIns, pvPtr);
+#else
+ RT_NOREF1(pDevIns);
+ if (pvPtr)
+ RTMemFree(pvPtr);
+ return VINF_SUCCESS;
+#endif
+}
+
+/** No docs, lazy coder. */
+int acpiPrepareSsdt(PPDMDEVINS pDevIns, void **ppvPtr, size_t *pcbSsdt)
+{
+ uint8_t *pabAmlCodeSsdt = NULL;
+ size_t cbAmlCodeSsdt = 0;
+ int rc = acpiAmlLoadExternal(pDevIns, "SsdtFilePath", "SSDT", &pabAmlCodeSsdt, &cbAmlCodeSsdt);
+
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+ {
+ bool fCpuHotPlug = false;
+ uint8_t *pabAmlCode = NULL;
+ rc = CFGMR3QueryBoolDef(pDevIns->pCfg, "CpuHotPlug", &fCpuHotPlug, false);
+
+ if (RT_FAILURE(rc))
+ return rc;
+
+ if (fCpuHotPlug)
+ {
+ pabAmlCode = AmlCodeSsdtCpuHotPlug;
+ cbAmlCodeSsdt = sizeof(AmlCodeSsdtCpuHotPlug);
+ }
+ else
+ {
+ pabAmlCode = AmlCodeSsdtStandard;
+ cbAmlCodeSsdt = sizeof(AmlCodeSsdtStandard);
+ }
+
+ pabAmlCodeSsdt = (uint8_t *)RTMemAllocZ(cbAmlCodeSsdt);
+ if (pabAmlCodeSsdt)
+ {
+ memcpy(pabAmlCodeSsdt, pabAmlCode, cbAmlCodeSsdt);
+
+ if (fCpuHotPlug)
+ patchAmlCpuHotPlug(pDevIns, pabAmlCodeSsdt, cbAmlCodeSsdt);
+ else
+ patchAml(pDevIns, pabAmlCodeSsdt, cbAmlCodeSsdt);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+ else if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"SsdtFilePath\""));
+
+ if (RT_SUCCESS(rc))
+ {
+ *ppvPtr = pabAmlCodeSsdt;
+ *pcbSsdt = cbAmlCodeSsdt;
+ }
+
+ return VINF_SUCCESS;
+}
+
+/** No docs, lazy coder. */
+int acpiCleanupSsdt(PPDMDEVINS pDevIns, void *pvPtr)
+{
+ RT_NOREF1(pDevIns);
+ if (pvPtr)
+ RTMemFree(pvPtr);
+ return VINF_SUCCESS;
+}
+
diff --git a/src/VBox/Devices/PC/BIOS/Makefile.kmk b/src/VBox/Devices/PC/BIOS/Makefile.kmk
new file mode 100644
index 00000000..15881995
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/Makefile.kmk
@@ -0,0 +1,200 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for the New BIOS ROM.
+#
+
+#
+# Copyright (C) 2012-2019 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+SUB_DEPTH = ../../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+
+ifdef VBOX_WITH_OPEN_WATCOM
+
+ #
+ # VBoxPcBios - The PC BIOS.
+ #
+ MISCBINS += VBoxPcBios386
+ VBoxPcBios386_TEMPLATE = VBoxBios
+ VBoxPcBios386_BLD_TYPE = release
+ VBoxPcBios386_CFLAGS = -3
+ VBoxPcBios386_DEFS = \
+ VBOX_PC_BIOS \
+ VBOX_LANBOOT_SEG=0xE200 \
+ VBOX_WITH_SCSI \
+ VBOX_WITH_AHCI \
+ VBOX_BIOS_CPU=80386
+ #VBoxPcBios386_DEFS.debug = DEBUG_ATA DEBUG_POST DEBUG_INT13
+ VBoxPcBios386_LDFLAGS = \
+ output raw offset=0xF0000 \
+ order \
+ clname DATA segaddr=0xF000 \
+ segment _DATA \
+ clname CODE \
+ segment _TEXT segaddr=0xF000 offset=0x1600 \
+ segment BIOS32 segaddr=0xF000 offset=0xDA00 \
+ segment BIOSSEG segaddr=0xF000 offset=0xE000
+ VBoxPcBios386_SOURCES = \
+ post.c \
+ bios.c \
+ print.c \
+ ata.c \
+ floppy.c \
+ floppyt.c \
+ eltorito.c \
+ boot.c \
+ keyboard.c \
+ disk.c \
+ serial.c \
+ system.c \
+ invop.c \
+ timepci.c \
+ ps2mouse.c \
+ parallel.c \
+ logo.c \
+ scsi.c \
+ ahci.c \
+ apm.c \
+ pcibios.c \
+ pciutil.c \
+ vds.c \
+ ../../BiosCommonCode/__U4M.asm \
+ ../../BiosCommonCode/__U4D.asm \
+ ../../BiosCommonCode/__U8RS.asm \
+ ../../BiosCommonCode/__U8LS.asm \
+ ../../BiosCommonCode/fmemset.asm \
+ ../../BiosCommonCode/fmemcpy.asm \
+ pcibio32.asm \
+ apm_pm.asm \
+ $(VBoxPcBios32_0_OUTDIR)/VBoxPcBios32.lib \
+ orgs.asm
+ #$(VBoxPcBios32_1_TARGET) - reference is lost when extending the target. weird.
+
+ # For 32-bit C code in PC BIOS.
+ LIBRARIES += VBoxPcBios32
+ VBoxPcBios32_TEMPLATE = VBoxBios32Lib
+ VBoxPcBios32_SOURCES = \
+ pci32.c
+
+ ../../BiosCommonCode/DoUInt32Div.c_CFLAGS = -mc # asm.h and uint32.h both require far data pointers by default.
+
+ MISCBINS += VBoxPcBios286
+ VBoxPcBios286_EXTENDS = VBoxPcBios386
+ VBoxPcBios286_CFLAGS = -2
+ VBoxPcBios286_DEFS = $(filter-out VBOX_BIOS_CPU=80386,$(VBoxPcBios386_DEFS)) VBOX_BIOS_CPU=80286
+ VBoxPcBios286_SOURCES = $(VBoxPcBios386_SOURCES) \
+ ../../BiosCommonCode/DoUInt32Div.c \
+ ../../BiosCommonCode/ASMBitLastSetU16.asm
+
+ MISCBINS += VBoxPcBios8086
+ VBoxPcBios8086_EXTENDS = VBoxPcBios386
+ VBoxPcBios8086_CFLAGS = -0
+ VBoxPcBios8086_DEFS = $(filter-out VBOX_BIOS_CPU=80386,$(VBoxPcBios386_DEFS)) VBOX_BIOS_CPU=8086
+ VBoxPcBios8086_SOURCES = $(VBoxPcBios386_SOURCES) \
+ ../../BiosCommonCode/DoUInt32Div.c \
+ ../../BiosCommonCode/ASMBitLastSetU16.asm
+
+
+ #
+ # Updates the alternative source files.
+ #
+ define def_VBoxPcBiosUpdateAltSource
+
+ $$(PATH_SUB_CURRENT)/VBoxBiosAlternative$(1).asm +| $$(PATH_SUB_CURRENT)/VBoxBiosAlternative$(1).md5sum: \
+ $$$$(VBoxPcBios$(1)_1_TARGET) \
+ $$(VBOX_MAKE_ALTERNATIVE_SOURCE) \
+ $$(VBOX_VBOXCMP)
+ if1of ($(KBUILD_TYPE), release)
+ $$(VBOX_MAKE_ALTERNATIVE_SOURCE) \
+ --bios-image $$< \
+ --bios-map $$(basename $$<).map \
+ --bios-sym $$(basename $$<).sym \
+ --bios-type system \
+ --output $$(VBoxPcBios$(1)_0_OUTDIR)/VBoxBiosAlternative$(1).asm
+ $$(QUIET)yasm -f bin -o $$(VBoxPcBios$(1)_0_OUTDIR)/VBoxBiosAlternative$(1).bin $$(VBoxPcBios$(1)_0_OUTDIR)/VBoxBiosAlternative$(1).asm
+ $$(VBOX_VBOXCMP) $$< $$(VBoxPcBios$(1)_0_OUTDIR)/VBoxBiosAlternative$(1).bin
+ $$(CP) --changed -- $$(VBoxPcBios$(1)_0_OUTDIR)/VBoxBiosAlternative$(1).asm $$(PATH_ROOT)/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative$(1).asm
+ $$(REDIRECT) -C $$(dir $$(VBoxPcBios$(1)_1_TARGET)) -- \
+ $$(MD5SUM_EXT) -bo $$(VBoxPcBios$(1)_0_OUTDIR)/VBoxBiosAlternative$(1).md5sum $$(notdir $$(VBoxPcBios$(1)_1_TARGET))
+ $$(CP) --changed -- $$(VBoxPcBios$(1)_0_OUTDIR)/VBoxBiosAlternative$(1).md5sum $$(PATH_ROOT)/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative$(1).md5sum
+ $$(RM) -f -- $$(VBoxPcBios$(1)_0_OUTDIR)/VBoxBiosAlternative$(1).asm $$(VBoxPcBios$(1)_0_OUTDIR)/VBoxBiosAlternative.bin $$(VBoxPcBios$(1)_0_OUTDIR)/VBoxBiosAlternative$(1).md5sum
+ else
+ $$(QUIET)$$(ECHO) "Fatal error: Can only update VBoxBiosAlternative$(1).asm/md5sum with a release build."
+ $$(QUIET)exit 1
+ endif
+
+ endef
+
+ $(evalcall2 def_VBoxPcBiosUpdateAltSource,386)
+ $(evalcall2 def_VBoxPcBiosUpdateAltSource,286)
+ $(evalcall2 def_VBoxPcBiosUpdateAltSource,8086)
+
+ update-pcbios-source: \
+ $(PATH_SUB_CURRENT)/VBoxBiosAlternative386.asm \
+ $(PATH_SUB_CURRENT)/VBoxBiosAlternative286.asm \
+ $(PATH_SUB_CURRENT)/VBoxBiosAlternative8086.asm
+
+endif # VBOX_WITH_OPEN_WATCOM
+
+
+#
+# The library containing the PC BIOS image.
+#
+LIBRARIES += PcBiosBin
+PcBiosBin_TEMPLATE = VBOXR3
+PcBiosBin_DEFS = IN_VBOXDD2
+
+define def_VBoxPcBiosBin
+ PcBiosBin_CLEAN += $$(PcBiosBin_0_OUTDIR)/PcBiosBin$(1).c
+ PcBiosBin_SOURCES += $$(PcBiosBin_0_OUTDIR)/PcBiosBin$(1).c
+
+ ifdef VBOX_WITH_OPEN_WATCOM
+ $$$$(PcBiosBin_0_OUTDIR)/PcBiosBin$(1).c: $$$$(VBoxPcBios$(1)_1_TARGET) $$(VBOX_BIN2C) | $$$$(dir $$$$@)
+ $$(call MSG_TOOL,bin2c,PcBiosBin,$$<,$$@)
+ $$(QUIET)$$(VBOX_BIN2C) -min 64 -max 256 -mask 0xffff -ascii -export PcBiosBinary$(1) $$< $$@
+ else
+ PcBiosBin_CLEAN += $$(PcBiosBin_0_OUTDIR)/VBoxPcBios$(1).rom
+
+ $$$$(PcBiosBin_0_OUTDIR)/PcBiosBin$(1).c + $$$$(PcBiosBin_0_OUTDIR)/VBoxPcBios$(1).rom: \
+ $$(PATH_SUB_CURRENT)/VBoxBiosAlternative$(1).asm \
+ $$(PATH_SUB_CURRENT)/VBoxBiosAlternative$(1).md5sum \
+ $$(VBOX_BIN2C) | $$$$(dir $$$$@)
+ $$(call MSG_TOOL,bin2c,PcBiosBin,$$<,$$@)
+ $$(QUIET)yasm -f bin -o $$(PcBiosBin_0_OUTDIR)/VBoxPcBios$(1).rom $$<
+ $$(QUIET)$$(REDIRECT) -C $$(PcBiosBin_0_OUTDIR) -- \
+ $$(MD5SUM_EXT) -c $$(basename $$<).md5sum
+ $$(QUIET)$$(VBOX_BIN2C) -min 64 -max 256 -mask 0xffff -ascii -export PcBiosBinary$(1) $$(PcBiosBin_0_OUTDIR)/VBoxPcBios$(1).rom $$@
+ $$(QUIET)$$(RM) -f -- $$$$(PcBiosBin_0_OUTDIR)/VBoxPcBios$(1).rom
+ endif
+endef
+$(evalcall2 def_VBoxPcBiosBin,386)
+$(evalcall2 def_VBoxPcBiosBin,286)
+$(evalcall2 def_VBoxPcBiosBin,8086)
+
+
+
+ifdef VBOX_WITH_OPEN_WATCOM
+ #
+ # Install the symbol file for the BIOS.
+ #
+ INSTALLS += VBoxPcBiosSym
+ VBoxPcBiosSym_TEMPLATE = VBoxDbgSyms
+ VBoxPcBiosSym_SOURCES = \
+ $(basename $(VBoxPcBios386_1_TARGET)).sym \
+ $(basename $(VBoxPcBios286_1_TARGET)).sym \
+ $(basename $(VBoxPcBios8086_1_TARGET)).sym
+endif
+
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.asm b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.asm
new file mode 100644
index 00000000..f212565d
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.asm
@@ -0,0 +1,17427 @@
+; $Id: VBoxBiosAlternative286.asm $
+;; @file
+; Auto Generated source file. Do not edit.
+;
+
+;
+; Source file: post.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; BIOS POST routines. Used only during initialization.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: bios.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: print.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: ata.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: floppy.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: floppyt.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; Floppy drive tables.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: eltorito.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: boot.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: keyboard.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: disk.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: serial.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: system.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: invop.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; Real mode invalid opcode handler.
+;
+;
+;
+; Copyright (C) 2013-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: timepci.c
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: ps2mouse.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: parallel.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: logo.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; Stuff for drawing the BIOS logo.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: scsi.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; SCSI host adapter driver to boot from SCSI disks
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: ahci.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; AHCI host adapter driver to boot from SATA disks.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: apm.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; APM BIOS support. Implements APM version 1.2.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: pcibios.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; PCI BIOS support.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: pciutil.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; Utility routines for calling the PCI BIOS.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: vds.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; Utility routines for calling the Virtual DMA Services.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: __U4M.asm
+;
+; $Id: VBoxBiosAlternative286.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: __U4D.asm
+;
+; $Id: VBoxBiosAlternative286.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: __U8RS.asm
+;
+; $Id: VBoxBiosAlternative286.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: __U8LS.asm
+;
+; $Id: VBoxBiosAlternative286.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: fmemset.asm
+;
+; $Id: VBoxBiosAlternative286.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: fmemcpy.asm
+;
+; $Id: VBoxBiosAlternative286.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: pcibio32.asm
+;
+; $Id: VBoxBiosAlternative286.asm $
+; BIOS32 service directory and 32-bit PCI BIOS entry point
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+
+;
+; Source file: apm_pm.asm
+;
+; $Id:
+; Protected-mode APM implementation.
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: orgs.asm
+;
+; $Id: VBoxBiosAlternative286.asm $
+; ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: DoUInt32Div.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; AHCI host adapter driver to boot from SATA disks.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: ASMBitLastSetU16.asm
+;
+; $Id: VBoxBiosAlternative286.asm $
+; BiosCommonCode - ASMBitLastSetU16() - borrowed from IPRT.
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: pci32.c
+;
+; $Id: VBoxBiosAlternative286.asm $
+; 32-bit PCI BIOS wrapper.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+
+
+
+section _DATA progbits vstart=0x0 align=1 ; size=0xb0 class=DATA group=DGROUP
+ ; disGetNextSymbol 0xf0000 LB 0xb0 -> off=0x0 cb=000000000000005b uValue=00000000000f0000 '_fd_parm'
+_fd_parm: ; 0xf0000 LB 0x5b
+ db 0dfh, 002h, 025h, 002h, 009h, 02ah, 0ffh, 050h, 0f6h, 00fh, 008h, 027h, 080h, 0dfh, 002h, 025h
+ db 002h, 009h, 02ah, 0ffh, 050h, 0f6h, 00fh, 008h, 027h, 040h, 0dfh, 002h, 025h, 002h, 00fh, 01bh
+ db 0ffh, 054h, 0f6h, 00fh, 008h, 04fh, 000h, 0dfh, 002h, 025h, 002h, 009h, 02ah, 0ffh, 050h, 0f6h
+ db 00fh, 008h, 04fh, 080h, 0afh, 002h, 025h, 002h, 012h, 01bh, 0ffh, 06ch, 0f6h, 00fh, 008h, 04fh
+ db 000h, 0afh, 002h, 025h, 002h, 024h, 01bh, 0ffh, 054h, 0f6h, 00fh, 008h, 04fh, 0c0h, 0afh, 002h
+ db 025h, 002h, 0ffh, 01bh, 0ffh, 054h, 0f6h, 00fh, 008h, 0ffh, 000h
+ ; disGetNextSymbol 0xf005b LB 0x55 -> off=0x0 cb=000000000000000f uValue=00000000000f005b '_fd_map'
+_fd_map: ; 0xf005b LB 0xf
+ db 001h, 000h, 002h, 002h, 003h, 003h, 004h, 004h, 005h, 005h, 00eh, 006h, 00fh, 006h, 000h
+ ; disGetNextSymbol 0xf006a LB 0x46 -> off=0x0 cb=000000000000000c uValue=00000000000f006a '_pktacc'
+_pktacc: ; 0xf006a LB 0xc
+ db 000h, 000h, 000h, 000h, 000h, 000h, 0f3h, 02ah, 053h, 07ch, 00dh, 08ch
+ ; disGetNextSymbol 0xf0076 LB 0x3a -> off=0x0 cb=000000000000000c uValue=00000000000f0076 '_softrst'
+_softrst: ; 0xf0076 LB 0xc
+ db 000h, 000h, 000h, 000h, 000h, 000h, 078h, 02dh, 03bh, 03bh, 03bh, 03bh
+ ; disGetNextSymbol 0xf0082 LB 0x2e -> off=0x0 cb=000000000000002e uValue=00000000000f0082 '_dskacc'
+_dskacc: ; 0xf0082 LB 0x2e
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0e3h, 029h, 098h, 02ah, 000h, 000h, 000h, 000h
+ db 093h, 07ah, 073h, 07bh, 0dfh, 08ah, 087h, 08bh, 000h, 000h, 000h, 000h, 000h, 000h, 05fh, 033h
+ db 032h, 05fh, 000h, 0dah, 00fh, 000h, 000h, 001h, 0f3h, 000h, 000h, 000h, 000h, 000h
+
+section CONST progbits vstart=0xb0 align=1 ; size=0xcde class=DATA group=DGROUP
+ ; disGetNextSymbol 0xf00b0 LB 0xcde -> off=0xcde cb=0000000000000000 uValue=00000000000f0d8e 'bios_cvs_version_string'
+ db 'NMI Handler called', 00ah, 000h
+ db 'INT18: BOOT FAILURE', 00ah, 000h
+ db '%s', 00ah, 000h, 000h
+ db 'FATAL: ', 000h
+ db 'bios_printf: unknown %ll format', 00ah, 000h
+ db 'bios_printf: unknown format', 00ah, 000h
+ db 'ata-detect: Failed to detect ATA device', 00ah, 000h
+ db 'ata%d-%d: PCHS=%u/%u/%u LCHS=%u/%u/%u', 00ah, 000h
+ db 'ata-detect: Failed to detect ATAPI device', 00ah, 000h
+ db ' slave', 000h
+ db 'master', 000h
+ db 'ata%d %s: ', 000h
+ db '%c', 000h
+ db ' ATA-%d Hard-Disk (%lu MBytes)', 00ah, 000h
+ db ' ATAPI-%d CD-ROM/DVD-ROM', 00ah, 000h
+ db ' ATAPI-%d Device', 00ah, 000h
+ db 'ata%d %s: Unknown device', 00ah, 000h
+ db 'ata_cmd_packet', 000h
+ db '%s: DATA_OUT not supported yet', 00ah, 000h
+ db 'set_diskette_current_cyl: drive > 1', 00ah, 000h
+ db 'int13_diskette_function', 000h
+ db '%s: drive>1 || head>1 ...', 00ah, 000h
+ db '%s: ctrl not ready', 00ah, 000h
+ db '%s: write error', 00ah, 000h
+ db '%s: bad floppy type', 00ah, 000h
+ db '%s: unsupported AH=%02x', 00ah, 000h, 000h
+ db 'int13_eltorito', 000h
+ db '%s: call with AX=%04x not implemented.', 00ah, 000h
+ db '%s: unsupported AH=%02x', 00ah, 000h
+ db 'int13_cdemu', 000h
+ db '%s: function %02x, emulation not active for DL= %02x', 00ah, 000h
+ db '%s: function %02x, error %02x !', 00ah, 000h
+ db '%s: function %02x. Can', 027h, 't use 64bits lba', 00ah, 000h
+ db '%s: function %02x, status %02x !', 00ah, 000h
+ db '%s: function AH=%02x unsupported, returns fail', 00ah, 000h
+ db 'int13_cdrom', 000h
+ db '%s: function %02x, ELDL out of range %02x', 00ah, 000h
+ db '%s: function %02x, unmapped device for ELDL=%02x', 00ah, 000h, 000h
+ db 'Booting from %s...', 00ah, 000h
+ db 'Boot from %s failed', 00ah, 000h
+ db 'Boot from %s %d failed', 00ah, 000h
+ db 'No bootable medium found! System halted.', 00ah, 000h
+ db 'Could not read from the boot medium! System halted.', 00ah, 000h
+ db 'CDROM boot failure code : %04x', 00ah, 000h
+ db 'Boot : bseqnr=%d, bootseq=%x', 00dh, 00ah, 000h, 000h
+ db 'Keyboard error:%u', 00ah, 000h
+ db 'KBD: int09 handler: AL=0', 00ah, 000h
+ db 'KBD: int09h_handler(): unknown scancode read: 0x%02x!', 00ah, 000h
+ db 'KBD: int09h_handler(): scancode & asciicode are zero?', 00ah, 000h
+ db 'KBD: int16h: out of keyboard input', 00ah, 000h
+ db 'KBD: unsupported int 16h function %02x', 00ah, 000h
+ db 'AX=%04x BX=%04x CX=%04x DX=%04x ', 00ah, 000h, 000h
+ db 'int13_harddisk', 000h
+ db '%s: function %02x, ELDL out of range %02x', 00ah, 000h
+ db '%s: function %02x, unmapped device for ELDL=%02x', 00ah, 000h
+ db '%s: function %02x, count out of range!', 00ah, 000h
+ db '%s: function %02x, disk %02x, parameters out of range %04x/%04x/%04x!', 00ah
+ db 000h
+ db '%s: function %02x, error %02x !', 00ah, 000h
+ db 'format disk track called', 00ah, 000h
+ db '%s: function %02xh unimplemented, returns success', 00ah, 000h
+ db '%s: function %02xh unsupported, returns fail', 00ah, 000h
+ db 'int13_harddisk_ext', 000h
+ db '%s: function %02x. LBA out of range', 00ah, 000h, 000h
+ db 'int15: Func 24h, subfunc %02xh, A20 gate control not supported', 00ah, 000h
+ db '*** int 15h function AH=bf not yet supported!', 00ah, 000h
+ db 'EISA BIOS not present', 00ah, 000h
+ db '*** int 15h function AX=%04x, BX=%04x not yet supported!', 00ah, 000h
+ db 'sendmouse', 000h
+ db 'setkbdcomm', 000h
+ db 'Mouse reset returned %02x (should be ack)', 00ah, 000h
+ db 'Mouse status returned %02x (should be ack)', 00ah, 000h
+ db 'INT 15h C2 AL=6, BH=%02x', 00ah, 000h
+ db 'INT 15h C2 default case entered', 00ah, 000h, 000h
+ db 'Key pressed: %x', 00ah, 000h
+ db 00ah, 00ah, ' AHCI controller:', 000h
+ db 00ah, ' %d) Hard disk', 000h
+ db 00ah, 00ah, ' SCSI controller:', 000h
+ db ' IDE controller:', 000h
+ db 00ah, 00ah, 'AHCI controller:', 00ah, 000h
+ db 00ah, ' %d) ', 000h
+ db 'Secondary ', 000h
+ db 'Primary ', 000h
+ db 'Slave', 000h
+ db 'Master', 000h
+ db 'No hard disks found', 000h
+ db 00ah, 000h
+ db 'Press F12 to select boot device.', 00ah, 000h
+ db 00ah, 'VirtualBox temporary boot device selection', 00ah, 00ah, 'Detected H'
+ db 'ard disks:', 00ah, 00ah, 000h
+ db 00ah, 'Other boot devices:', 00ah, ' f) Floppy', 00ah, ' c) CD-ROM', 00ah
+ db ' l) LAN', 00ah, 00ah, ' b) Continue booting', 00ah, 000h
+ db 'Delaying boot for %d seconds:', 000h
+ db ' %d', 000h, 000h
+ db 'scsi_read_sectors', 000h
+ db '%s: device_id out of range %d', 00ah, 000h
+ db 'scsi_write_sectors', 000h
+ db 'scsi_cmd_packet', 000h
+ db '%s: DATA_OUT not supported yet', 00ah, 000h
+ db 'scsi_enumerate_attached_devices', 000h
+ db '%s: SCSI_INQUIRY failed', 00ah, 000h
+ db '%s: SCSI_READ_CAPACITY failed', 00ah, 000h
+ db 'Disk %d has an unsupported sector size of %u', 00ah, 000h
+ db 'SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors', 00ah, 000h
+ db 'SCSI %d-ID#%d: CD/DVD-ROM', 00ah, 000h, 000h
+ db 'ahci_read_sectors', 000h
+ db '%s: device_id out of range %d', 00ah, 000h
+ db 'ahci_write_sectors', 000h
+ db 'ahci_cmd_packet', 000h
+ db '%s: DATA_OUT not supported yet', 00ah, 000h
+ db 'AHCI %d-P#%d: PCHS=%u/%u/%u LCHS=%u/%u/%u 0x%llx sectors', 00ah, 000h
+ db 'Standby', 000h
+ db 'Suspend', 000h
+ db 'Shutdown', 000h
+ db 'APM: Unsupported function AX=%04X BX=%04X called', 00ah, 000h, 000h
+ db 'PCI: Unsupported function AX=%04X BX=%04X called', 00ah, 000h
+
+section CONST2 progbits vstart=0xd8e align=1 ; size=0x3fa class=DATA group=DGROUP
+ ; disGetNextSymbol 0xf0d8e LB 0x3fa -> off=0x0 cb=0000000000000012 uValue=00000000000f0d8e 'bios_cvs_version_string'
+bios_cvs_version_string: ; 0xf0d8e LB 0x12
+ db 'VirtualBox 6.0.4', 000h, 000h
+ ; disGetNextSymbol 0xf0da0 LB 0x3e8 -> off=0x0 cb=0000000000000008 uValue=00000000000f0da0 '_bios_prefix_string'
+_bios_prefix_string: ; 0xf0da0 LB 0x8
+ db 'BIOS: ', 000h, 000h
+ ; disGetNextSymbol 0xf0da8 LB 0x3e0 -> off=0x0 cb=0000000000000006 uValue=00000000000f0da8 'isotag'
+isotag: ; 0xf0da8 LB 0x6
+ db 'CD001', 000h
+ ; disGetNextSymbol 0xf0dae LB 0x3da -> off=0x0 cb=0000000000000018 uValue=00000000000f0dae 'eltorito'
+eltorito: ; 0xf0dae LB 0x18
+ db 'EL TORITO SPECIFICATION', 000h
+ ; disGetNextSymbol 0xf0dc6 LB 0x3c2 -> off=0x0 cb=0000000000000028 uValue=00000000000f0dc6 'drivetypes'
+drivetypes: ; 0xf0dc6 LB 0x28
+ db 046h, 06ch, 06fh, 070h, 070h, 079h, 000h, 000h, 000h, 000h, 048h, 061h, 072h, 064h, 020h, 044h
+ db 069h, 073h, 06bh, 000h, 043h, 044h, 02dh, 052h, 04fh, 04dh, 000h, 000h, 000h, 000h, 04ch, 041h
+ db 04eh, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ ; disGetNextSymbol 0xf0dee LB 0x39a -> off=0x0 cb=000000000000037a uValue=00000000000f0dee 'scan_to_scanascii'
+scan_to_scanascii: ; 0xf0dee LB 0x37a
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 01bh, 001h, 01bh, 001h, 01bh, 001h
+ db 000h, 001h, 000h, 000h, 031h, 002h, 021h, 002h, 000h, 000h, 000h, 078h, 000h, 000h, 032h, 003h
+ db 040h, 003h, 000h, 003h, 000h, 079h, 000h, 000h, 033h, 004h, 023h, 004h, 000h, 000h, 000h, 07ah
+ db 000h, 000h, 034h, 005h, 024h, 005h, 000h, 000h, 000h, 07bh, 000h, 000h, 035h, 006h, 025h, 006h
+ db 000h, 000h, 000h, 07ch, 000h, 000h, 036h, 007h, 05eh, 007h, 01eh, 007h, 000h, 07dh, 000h, 000h
+ db 037h, 008h, 026h, 008h, 000h, 000h, 000h, 07eh, 000h, 000h, 038h, 009h, 02ah, 009h, 000h, 000h
+ db 000h, 07fh, 000h, 000h, 039h, 00ah, 028h, 00ah, 000h, 000h, 000h, 080h, 000h, 000h, 030h, 00bh
+ db 029h, 00bh, 000h, 000h, 000h, 081h, 000h, 000h, 02dh, 00ch, 05fh, 00ch, 01fh, 00ch, 000h, 082h
+ db 000h, 000h, 03dh, 00dh, 02bh, 00dh, 000h, 000h, 000h, 083h, 000h, 000h, 008h, 00eh, 008h, 00eh
+ db 07fh, 00eh, 000h, 000h, 000h, 000h, 009h, 00fh, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h
+ db 071h, 010h, 051h, 010h, 011h, 010h, 000h, 010h, 040h, 000h, 077h, 011h, 057h, 011h, 017h, 011h
+ db 000h, 011h, 040h, 000h, 065h, 012h, 045h, 012h, 005h, 012h, 000h, 012h, 040h, 000h, 072h, 013h
+ db 052h, 013h, 012h, 013h, 000h, 013h, 040h, 000h, 074h, 014h, 054h, 014h, 014h, 014h, 000h, 014h
+ db 040h, 000h, 079h, 015h, 059h, 015h, 019h, 015h, 000h, 015h, 040h, 000h, 075h, 016h, 055h, 016h
+ db 015h, 016h, 000h, 016h, 040h, 000h, 069h, 017h, 049h, 017h, 009h, 017h, 000h, 017h, 040h, 000h
+ db 06fh, 018h, 04fh, 018h, 00fh, 018h, 000h, 018h, 040h, 000h, 070h, 019h, 050h, 019h, 010h, 019h
+ db 000h, 019h, 040h, 000h, 05bh, 01ah, 07bh, 01ah, 01bh, 01ah, 000h, 000h, 000h, 000h, 05dh, 01bh
+ db 07dh, 01bh, 01dh, 01bh, 000h, 000h, 000h, 000h, 00dh, 01ch, 00dh, 01ch, 00ah, 01ch, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 061h, 01eh, 041h, 01eh
+ db 001h, 01eh, 000h, 01eh, 040h, 000h, 073h, 01fh, 053h, 01fh, 013h, 01fh, 000h, 01fh, 040h, 000h
+ db 064h, 020h, 044h, 020h, 004h, 020h, 000h, 020h, 040h, 000h, 066h, 021h, 046h, 021h, 006h, 021h
+ db 000h, 021h, 040h, 000h, 067h, 022h, 047h, 022h, 007h, 022h, 000h, 022h, 040h, 000h, 068h, 023h
+ db 048h, 023h, 008h, 023h, 000h, 023h, 040h, 000h, 06ah, 024h, 04ah, 024h, 00ah, 024h, 000h, 024h
+ db 040h, 000h, 06bh, 025h, 04bh, 025h, 00bh, 025h, 000h, 025h, 040h, 000h, 06ch, 026h, 04ch, 026h
+ db 00ch, 026h, 000h, 026h, 040h, 000h, 03bh, 027h, 03ah, 027h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 027h, 028h, 022h, 028h, 000h, 000h, 000h, 000h, 000h, 000h, 060h, 029h, 07eh, 029h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 05ch, 02bh
+ db 07ch, 02bh, 01ch, 02bh, 000h, 000h, 000h, 000h, 07ah, 02ch, 05ah, 02ch, 01ah, 02ch, 000h, 02ch
+ db 040h, 000h, 078h, 02dh, 058h, 02dh, 018h, 02dh, 000h, 02dh, 040h, 000h, 063h, 02eh, 043h, 02eh
+ db 003h, 02eh, 000h, 02eh, 040h, 000h, 076h, 02fh, 056h, 02fh, 016h, 02fh, 000h, 02fh, 040h, 000h
+ db 062h, 030h, 042h, 030h, 002h, 030h, 000h, 030h, 040h, 000h, 06eh, 031h, 04eh, 031h, 00eh, 031h
+ db 000h, 031h, 040h, 000h, 06dh, 032h, 04dh, 032h, 00dh, 032h, 000h, 032h, 040h, 000h, 02ch, 033h
+ db 03ch, 033h, 000h, 000h, 000h, 000h, 000h, 000h, 02eh, 034h, 03eh, 034h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 02fh, 035h, 03fh, 035h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 02ah, 037h, 02ah, 037h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 020h, 039h, 020h, 039h, 020h, 039h
+ db 020h, 039h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 03bh
+ db 000h, 054h, 000h, 05eh, 000h, 068h, 000h, 000h, 000h, 03ch, 000h, 055h, 000h, 05fh, 000h, 069h
+ db 000h, 000h, 000h, 03dh, 000h, 056h, 000h, 060h, 000h, 06ah, 000h, 000h, 000h, 03eh, 000h, 057h
+ db 000h, 061h, 000h, 06bh, 000h, 000h, 000h, 03fh, 000h, 058h, 000h, 062h, 000h, 06ch, 000h, 000h
+ db 000h, 040h, 000h, 059h, 000h, 063h, 000h, 06dh, 000h, 000h, 000h, 041h, 000h, 05ah, 000h, 064h
+ db 000h, 06eh, 000h, 000h, 000h, 042h, 000h, 05bh, 000h, 065h, 000h, 06fh, 000h, 000h, 000h, 043h
+ db 000h, 05ch, 000h, 066h, 000h, 070h, 000h, 000h, 000h, 044h, 000h, 05dh, 000h, 067h, 000h, 071h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 047h, 037h, 047h, 000h, 077h, 000h, 000h, 020h, 000h
+ db 000h, 048h, 038h, 048h, 000h, 000h, 000h, 000h, 020h, 000h, 000h, 049h, 039h, 049h, 000h, 084h
+ db 000h, 000h, 020h, 000h, 02dh, 04ah, 02dh, 04ah, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 04bh
+ db 034h, 04bh, 000h, 073h, 000h, 000h, 020h, 000h, 000h, 04ch, 035h, 04ch, 000h, 000h, 000h, 000h
+ db 020h, 000h, 000h, 04dh, 036h, 04dh, 000h, 074h, 000h, 000h, 020h, 000h, 02bh, 04eh, 02bh, 04eh
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 04fh, 031h, 04fh, 000h, 075h, 000h, 000h, 020h, 000h
+ db 000h, 050h, 032h, 050h, 000h, 000h, 000h, 000h, 020h, 000h, 000h, 051h, 033h, 051h, 000h, 076h
+ db 000h, 000h, 020h, 000h, 000h, 052h, 030h, 052h, 000h, 000h, 000h, 000h, 020h, 000h, 000h, 053h
+ db 02eh, 053h, 000h, 000h, 000h, 000h, 020h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 05ch, 056h, 07ch, 056h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 085h, 000h, 087h, 000h, 089h, 000h, 08bh, 000h, 000h
+ db 000h, 086h, 000h, 088h, 000h, 08ah, 000h, 08ch, 000h, 000h
+ ; disGetNextSymbol 0xf1168 LB 0x20 -> off=0x0 cb=0000000000000020 uValue=00000000000f1168 'panic_msg_keyb_buffer_full'
+panic_msg_keyb_buffer_full: ; 0xf1168 LB 0x20
+ db '%s: keyboard input buffer full', 00ah, 000h
+
+ ; Padding 0x478 bytes at 0xf1188
+ times 1144 db 0
+
+section _TEXT progbits vstart=0x1600 align=1 ; size=0x88c8 class=CODE group=AUTO
+ ; disGetNextSymbol 0xf1600 LB 0x88c8 -> off=0x0 cb=0000000000000050 uValue=00000000000f0000 'rom_scan'
+rom_scan: ; 0xf1600 LB 0x50
+ push bp ; 55 ; 0xf1600 post.c:73
+ mov bp, sp ; 89 e5 ; 0xf1601
+ push bx ; 53 ; 0xf1603
+ push cx ; 51 ; 0xf1604
+ push si ; 56 ; 0xf1605
+ push ax ; 50 ; 0xf1606
+ push ax ; 50 ; 0xf1607
+ mov bx, ax ; 89 c3 ; 0xf1608
+ mov cx, dx ; 89 d1 ; 0xf160a
+ cmp bx, cx ; 39 cb ; 0xf160c post.c:80
+ jnc short 01648h ; 73 38 ; 0xf160e
+ xor si, si ; 31 f6 ; 0xf1610 post.c:81
+ mov dx, bx ; 89 da ; 0xf1612
+ mov es, bx ; 8e c3 ; 0xf1614 post.c:83
+ cmp word [es:si], 0aa55h ; 26 81 3c 55 aa ; 0xf1616
+ jne short 01642h ; 75 25 ; 0xf161b
+ mov word [bp-008h], bx ; 89 5e f8 ; 0xf161d post.c:89
+ mov word [bp-00ah], strict word 00003h ; c7 46 f6 03 00 ; 0xf1620
+ call far [bp-00ah] ; ff 5e f6 ; 0xf1625 post.c:90
+ cli ; fa ; 0xf1628 post.c:91
+ mov es, bx ; 8e c3 ; 0xf1629 post.c:95
+ mov al, byte [es:si+002h] ; 26 8a 44 02 ; 0xf162b
+ add AL, strict byte 003h ; 04 03 ; 0xf162f
+ and AL, strict byte 0fch ; 24 fc ; 0xf1631
+ xor ah, ah ; 30 e4 ; 0xf1633 post.c:96
+ cwd ; 99 ; 0xf1635
+ sal dx, 002h ; c1 e2 02 ; 0xf1636
+ db 01bh, 0c2h
+ ; sbb ax, dx ; 1b c2 ; 0xf1639
+ sar ax, 002h ; c1 f8 02 ; 0xf163b
+ add bx, ax ; 01 c3 ; 0xf163e
+ jmp short 0160ch ; eb ca ; 0xf1640 post.c:98
+ add bx, 00080h ; 81 c3 80 00 ; 0xf1642 post.c:100
+ jmp short 0160ch ; eb c4 ; 0xf1646 post.c:102
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf1648 post.c:103
+ pop si ; 5e ; 0xf164b
+ pop cx ; 59 ; 0xf164c
+ pop bx ; 5b ; 0xf164d
+ pop bp ; 5d ; 0xf164e
+ retn ; c3 ; 0xf164f
+ ; disGetNextSymbol 0xf1650 LB 0x8878 -> off=0x0 cb=000000000000001b uValue=00000000000f0050 'inb_cmos'
+inb_cmos: ; 0xf1650 LB 0x1b
+ push bp ; 55 ; 0xf1650 bios.c:65
+ mov bp, sp ; 89 e5 ; 0xf1651
+ push dx ; 52 ; 0xf1653
+ mov AH, strict byte 070h ; b4 70 ; 0xf1654 bios.c:67
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf1656 bios.c:69
+ jc short 0165ch ; 72 02 ; 0xf1658
+ mov AH, strict byte 072h ; b4 72 ; 0xf165a bios.c:70
+ mov dl, ah ; 88 e2 ; 0xf165c bios.c:71
+ xor dh, dh ; 30 f6 ; 0xf165e
+ out DX, AL ; ee ; 0xf1660
+ inc dx ; 42 ; 0xf1661 bios.c:72
+ in AL, DX ; ec ; 0xf1662
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1663
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf1665 bios.c:73
+ pop dx ; 5a ; 0xf1668
+ pop bp ; 5d ; 0xf1669
+ retn ; c3 ; 0xf166a
+ ; disGetNextSymbol 0xf166b LB 0x885d -> off=0x0 cb=000000000000001d uValue=00000000000f006b 'outb_cmos'
+outb_cmos: ; 0xf166b LB 0x1d
+ push bp ; 55 ; 0xf166b bios.c:75
+ mov bp, sp ; 89 e5 ; 0xf166c
+ push bx ; 53 ; 0xf166e
+ mov bl, dl ; 88 d3 ; 0xf166f
+ mov AH, strict byte 070h ; b4 70 ; 0xf1671 bios.c:77
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf1673 bios.c:79
+ jc short 01679h ; 72 02 ; 0xf1675
+ mov AH, strict byte 072h ; b4 72 ; 0xf1677 bios.c:80
+ mov dl, ah ; 88 e2 ; 0xf1679 bios.c:81
+ xor dh, dh ; 30 f6 ; 0xf167b
+ out DX, AL ; ee ; 0xf167d
+ inc dx ; 42 ; 0xf167e bios.c:82
+ mov al, bl ; 88 d8 ; 0xf167f
+ out DX, AL ; ee ; 0xf1681
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf1682 bios.c:83
+ pop bx ; 5b ; 0xf1685
+ pop bp ; 5d ; 0xf1686
+ retn ; c3 ; 0xf1687
+ ; disGetNextSymbol 0xf1688 LB 0x8840 -> off=0x0 cb=0000000000000061 uValue=00000000000f0088 'dummy_isr_function'
+dummy_isr_function: ; 0xf1688 LB 0x61
+ push bp ; 55 ; 0xf1688 bios.c:85
+ mov bp, sp ; 89 e5 ; 0xf1689
+ push ax ; 50 ; 0xf168b
+ mov CL, strict byte 0ffh ; b1 ff ; 0xf168c bios.c:93
+ mov AL, strict byte 00bh ; b0 0b ; 0xf168e bios.c:95
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf1690
+ out DX, AL ; ee ; 0xf1693
+ in AL, DX ; ec ; 0xf1694 bios.c:96
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1695
+ mov bx, ax ; 89 c3 ; 0xf1697
+ mov byte [bp-002h], al ; 88 46 fe ; 0xf1699
+ test al, al ; 84 c0 ; 0xf169c bios.c:97
+ je short 016dah ; 74 3a ; 0xf169e
+ mov AL, strict byte 00bh ; b0 0b ; 0xf16a0 bios.c:98
+ mov dx, 000a0h ; ba a0 00 ; 0xf16a2
+ out DX, AL ; ee ; 0xf16a5
+ in AL, DX ; ec ; 0xf16a6 bios.c:99
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf16a7
+ mov cx, ax ; 89 c1 ; 0xf16a9
+ test al, al ; 84 c0 ; 0xf16ab bios.c:100
+ je short 016c2h ; 74 13 ; 0xf16ad
+ mov dx, 000a1h ; ba a1 00 ; 0xf16af bios.c:101
+ in AL, DX ; ec ; 0xf16b2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf16b3
+ mov bl, cl ; 88 cb ; 0xf16b5 bios.c:102
+ or al, bl ; 08 d8 ; 0xf16b7
+ out DX, AL ; ee ; 0xf16b9
+ mov AL, strict byte 020h ; b0 20 ; 0xf16ba bios.c:103
+ mov dx, 000a0h ; ba a0 00 ; 0xf16bc
+ out DX, AL ; ee ; 0xf16bf
+ jmp short 016d1h ; eb 0f ; 0xf16c0 bios.c:104
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf16c2 bios.c:105
+ in AL, DX ; ec ; 0xf16c5
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf16c6
+ and bl, 0fbh ; 80 e3 fb ; 0xf16c8 bios.c:106
+ mov byte [bp-002h], bl ; 88 5e fe ; 0xf16cb
+ or al, bl ; 08 d8 ; 0xf16ce bios.c:107
+ out DX, AL ; ee ; 0xf16d0
+ mov AL, strict byte 020h ; b0 20 ; 0xf16d1 bios.c:109
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf16d3
+ out DX, AL ; ee ; 0xf16d6
+ mov cl, byte [bp-002h] ; 8a 4e fe ; 0xf16d7 bios.c:110
+ mov bx, strict word 0006bh ; bb 6b 00 ; 0xf16da bios.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf16dd
+ mov es, ax ; 8e c0 ; 0xf16e0
+ mov byte [es:bx], cl ; 26 88 0f ; 0xf16e2
+ mov sp, bp ; 89 ec ; 0xf16e5 bios.c:113
+ pop bp ; 5d ; 0xf16e7
+ retn ; c3 ; 0xf16e8
+ ; disGetNextSymbol 0xf16e9 LB 0x87df -> off=0x0 cb=0000000000000012 uValue=00000000000f00e9 'nmi_handler_msg'
+nmi_handler_msg: ; 0xf16e9 LB 0x12
+ push bp ; 55 ; 0xf16e9 bios.c:116
+ mov bp, sp ; 89 e5 ; 0xf16ea
+ push 000b0h ; 68 b0 00 ; 0xf16ec bios.c:118
+ push strict byte 00007h ; 6a 07 ; 0xf16ef
+ call 018ffh ; e8 0b 02 ; 0xf16f1
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf16f4
+ mov sp, bp ; 89 ec ; 0xf16f7 bios.c:119
+ pop bp ; 5d ; 0xf16f9
+ retn ; c3 ; 0xf16fa
+ ; disGetNextSymbol 0xf16fb LB 0x87cd -> off=0x0 cb=0000000000000012 uValue=00000000000f00fb 'int18_panic_msg'
+int18_panic_msg: ; 0xf16fb LB 0x12
+ push bp ; 55 ; 0xf16fb bios.c:121
+ mov bp, sp ; 89 e5 ; 0xf16fc
+ push 000c4h ; 68 c4 00 ; 0xf16fe bios.c:123
+ push strict byte 00007h ; 6a 07 ; 0xf1701
+ call 018ffh ; e8 f9 01 ; 0xf1703
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf1706
+ mov sp, bp ; 89 ec ; 0xf1709 bios.c:124
+ pop bp ; 5d ; 0xf170b
+ retn ; c3 ; 0xf170c
+ ; disGetNextSymbol 0xf170d LB 0x87bb -> off=0x0 cb=0000000000000020 uValue=00000000000f010d 'log_bios_start'
+log_bios_start: ; 0xf170d LB 0x20
+ push bp ; 55 ; 0xf170d bios.c:126
+ mov bp, sp ; 89 e5 ; 0xf170e
+ mov bx, 00da0h ; bb a0 0d ; 0xf1710 bios.c:131
+ mov cx, ds ; 8c d9 ; 0xf1713
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf1715
+ call 018bch ; e8 a1 01 ; 0xf1718
+ push 00d8eh ; 68 8e 0d ; 0xf171b
+ push 000d9h ; 68 d9 00 ; 0xf171e
+ push strict byte 00004h ; 6a 04 ; 0xf1721
+ call 018ffh ; e8 d9 01 ; 0xf1723
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf1726
+ mov sp, bp ; 89 ec ; 0xf1729 bios.c:132
+ pop bp ; 5d ; 0xf172b
+ retn ; c3 ; 0xf172c
+ ; disGetNextSymbol 0xf172d LB 0x879b -> off=0x0 cb=0000000000000027 uValue=00000000000f012d 'print_bios_banner'
+print_bios_banner: ; 0xf172d LB 0x27
+ push bp ; 55 ; 0xf172d bios.c:151
+ mov bp, sp ; 89 e5 ; 0xf172e
+ mov bx, strict word 00072h ; bb 72 00 ; 0xf1730 bios.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf1733
+ mov es, ax ; 8e c0 ; 0xf1736
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf1738
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf173b bios.c:53
+ cmp ax, 01234h ; 3d 34 12 ; 0xf1740 bios.c:157
+ jne short 0174dh ; 75 08 ; 0xf1743
+ mov AL, strict byte 003h ; b0 03 ; 0xf1745 bios.c:160
+ mov AH, strict byte 000h ; b4 00 ; 0xf1747
+ int 010h ; cd 10 ; 0xf1749
+ jmp short 01750h ; eb 03 ; 0xf174b bios.c:161
+ call 0762ch ; e8 dc 5e ; 0xf174d bios.c:164
+ mov sp, bp ; 89 ec ; 0xf1750 bios.c:191
+ pop bp ; 5d ; 0xf1752
+ retn ; c3 ; 0xf1753
+ ; disGetNextSymbol 0xf1754 LB 0x8774 -> off=0x0 cb=000000000000003b uValue=00000000000f0154 'send'
+send: ; 0xf1754 LB 0x3b
+ push bp ; 55 ; 0xf1754 print.c:72
+ mov bp, sp ; 89 e5 ; 0xf1755
+ push bx ; 53 ; 0xf1757
+ push cx ; 51 ; 0xf1758
+ mov bx, ax ; 89 c3 ; 0xf1759
+ mov cl, dl ; 88 d1 ; 0xf175b
+ test AL, strict byte 008h ; a8 08 ; 0xf175d print.c:80
+ je short 01767h ; 74 06 ; 0xf175f
+ mov al, dl ; 88 d0 ; 0xf1761 print.c:81
+ mov dx, 00403h ; ba 03 04 ; 0xf1763
+ out DX, AL ; ee ; 0xf1766
+ test bl, 004h ; f6 c3 04 ; 0xf1767 print.c:82
+ je short 01772h ; 74 06 ; 0xf176a
+ mov al, cl ; 88 c8 ; 0xf176c print.c:83
+ mov dx, 00504h ; ba 04 05 ; 0xf176e
+ out DX, AL ; ee ; 0xf1771
+ test bl, 002h ; f6 c3 02 ; 0xf1772 print.c:85
+ je short 01788h ; 74 11 ; 0xf1775
+ cmp cl, 00ah ; 80 f9 0a ; 0xf1777 print.c:86
+ jne short 01782h ; 75 06 ; 0xf177a
+ mov AL, strict byte 00dh ; b0 0d ; 0xf177c print.c:87
+ mov AH, strict byte 00eh ; b4 0e ; 0xf177e
+ int 010h ; cd 10 ; 0xf1780
+ mov al, cl ; 88 c8 ; 0xf1782 print.c:88
+ mov AH, strict byte 00eh ; b4 0e ; 0xf1784
+ int 010h ; cd 10 ; 0xf1786
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf1788 print.c:90
+ pop cx ; 59 ; 0xf178b
+ pop bx ; 5b ; 0xf178c
+ pop bp ; 5d ; 0xf178d
+ retn ; c3 ; 0xf178e
+ ; disGetNextSymbol 0xf178f LB 0x8739 -> off=0x0 cb=000000000000005f uValue=00000000000f018f 'put_int'
+put_int: ; 0xf178f LB 0x5f
+ push bp ; 55 ; 0xf178f print.c:92
+ mov bp, sp ; 89 e5 ; 0xf1790
+ push si ; 56 ; 0xf1792
+ push di ; 57 ; 0xf1793
+ push ax ; 50 ; 0xf1794
+ push ax ; 50 ; 0xf1795
+ mov si, ax ; 89 c6 ; 0xf1796
+ mov word [bp-008h], dx ; 89 56 f8 ; 0xf1798
+ mov di, strict word 0000ah ; bf 0a 00 ; 0xf179b print.c:94
+ mov ax, dx ; 89 d0 ; 0xf179e
+ cwd ; 99 ; 0xf17a0
+ idiv di ; f7 ff ; 0xf17a1
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf17a3
+ test ax, ax ; 85 c0 ; 0xf17a6 print.c:95
+ je short 017b4h ; 74 0a ; 0xf17a8
+ dec bx ; 4b ; 0xf17aa print.c:96
+ mov dx, ax ; 89 c2 ; 0xf17ab
+ mov ax, si ; 89 f0 ; 0xf17ad
+ call 0178fh ; e8 dd ff ; 0xf17af
+ jmp short 017cfh ; eb 1b ; 0xf17b2 print.c:97
+ dec bx ; 4b ; 0xf17b4 print.c:98
+ test bx, bx ; 85 db ; 0xf17b5
+ jle short 017c3h ; 7e 0a ; 0xf17b7
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf17b9 print.c:99
+ mov ax, si ; 89 f0 ; 0xf17bc
+ call 01754h ; e8 93 ff ; 0xf17be
+ jmp short 017b4h ; eb f1 ; 0xf17c1
+ test cx, cx ; 85 c9 ; 0xf17c3 print.c:100
+ je short 017cfh ; 74 08 ; 0xf17c5
+ mov dx, strict word 0002dh ; ba 2d 00 ; 0xf17c7 print.c:101
+ mov ax, si ; 89 f0 ; 0xf17ca
+ call 01754h ; e8 85 ff ; 0xf17cc
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf17cf print.c:103
+ mov BL, strict byte 00ah ; b3 0a ; 0xf17d2
+ mul bl ; f6 e3 ; 0xf17d4
+ mov bl, byte [bp-008h] ; 8a 5e f8 ; 0xf17d6
+ sub bl, al ; 28 c3 ; 0xf17d9
+ add bl, 030h ; 80 c3 30 ; 0xf17db
+ xor bh, bh ; 30 ff ; 0xf17de
+ mov dx, bx ; 89 da ; 0xf17e0
+ mov ax, si ; 89 f0 ; 0xf17e2
+ call 01754h ; e8 6d ff ; 0xf17e4
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf17e7 print.c:104
+ pop di ; 5f ; 0xf17ea
+ pop si ; 5e ; 0xf17eb
+ pop bp ; 5d ; 0xf17ec
+ retn ; c3 ; 0xf17ed
+ ; disGetNextSymbol 0xf17ee LB 0x86da -> off=0x0 cb=000000000000005e uValue=00000000000f01ee 'put_uint'
+put_uint: ; 0xf17ee LB 0x5e
+ push bp ; 55 ; 0xf17ee print.c:106
+ mov bp, sp ; 89 e5 ; 0xf17ef
+ push si ; 56 ; 0xf17f1
+ push di ; 57 ; 0xf17f2
+ push ax ; 50 ; 0xf17f3
+ push ax ; 50 ; 0xf17f4
+ mov si, ax ; 89 c6 ; 0xf17f5
+ mov word [bp-008h], dx ; 89 56 f8 ; 0xf17f7
+ mov ax, dx ; 89 d0 ; 0xf17fa print.c:108
+ xor dx, dx ; 31 d2 ; 0xf17fc
+ mov di, strict word 0000ah ; bf 0a 00 ; 0xf17fe
+ div di ; f7 f7 ; 0xf1801
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf1803
+ test ax, ax ; 85 c0 ; 0xf1806 print.c:109
+ je short 01814h ; 74 0a ; 0xf1808
+ dec bx ; 4b ; 0xf180a print.c:110
+ mov dx, ax ; 89 c2 ; 0xf180b
+ mov ax, si ; 89 f0 ; 0xf180d
+ call 017eeh ; e8 dc ff ; 0xf180f
+ jmp short 0182fh ; eb 1b ; 0xf1812 print.c:111
+ dec bx ; 4b ; 0xf1814 print.c:112
+ test bx, bx ; 85 db ; 0xf1815
+ jle short 01823h ; 7e 0a ; 0xf1817
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf1819 print.c:113
+ mov ax, si ; 89 f0 ; 0xf181c
+ call 01754h ; e8 33 ff ; 0xf181e
+ jmp short 01814h ; eb f1 ; 0xf1821
+ test cx, cx ; 85 c9 ; 0xf1823 print.c:114
+ je short 0182fh ; 74 08 ; 0xf1825
+ mov dx, strict word 0002dh ; ba 2d 00 ; 0xf1827 print.c:115
+ mov ax, si ; 89 f0 ; 0xf182a
+ call 01754h ; e8 25 ff ; 0xf182c
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf182f print.c:117
+ mov DL, strict byte 00ah ; b2 0a ; 0xf1832
+ mul dl ; f6 e2 ; 0xf1834
+ mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xf1836
+ sub dl, al ; 28 c2 ; 0xf1839
+ add dl, 030h ; 80 c2 30 ; 0xf183b
+ xor dh, dh ; 30 f6 ; 0xf183e
+ mov ax, si ; 89 f0 ; 0xf1840
+ call 01754h ; e8 0f ff ; 0xf1842
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf1845 print.c:118
+ pop di ; 5f ; 0xf1848
+ pop si ; 5e ; 0xf1849
+ pop bp ; 5d ; 0xf184a
+ retn ; c3 ; 0xf184b
+ ; disGetNextSymbol 0xf184c LB 0x867c -> off=0x0 cb=0000000000000070 uValue=00000000000f024c 'put_luint'
+put_luint: ; 0xf184c LB 0x70
+ push bp ; 55 ; 0xf184c print.c:120
+ mov bp, sp ; 89 e5 ; 0xf184d
+ push si ; 56 ; 0xf184f
+ push di ; 57 ; 0xf1850
+ push ax ; 50 ; 0xf1851
+ push ax ; 50 ; 0xf1852
+ mov si, ax ; 89 c6 ; 0xf1853
+ mov word [bp-006h], bx ; 89 5e fa ; 0xf1855
+ mov di, dx ; 89 d7 ; 0xf1858
+ mov ax, bx ; 89 d8 ; 0xf185a print.c:122
+ mov dx, cx ; 89 ca ; 0xf185c
+ mov bx, strict word 0000ah ; bb 0a 00 ; 0xf185e
+ xor cx, cx ; 31 c9 ; 0xf1861
+ call 09b60h ; e8 fa 82 ; 0xf1863
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf1866
+ mov cx, dx ; 89 d1 ; 0xf1869
+ mov dx, ax ; 89 c2 ; 0xf186b print.c:123
+ or dx, cx ; 09 ca ; 0xf186d
+ je short 01880h ; 74 0f ; 0xf186f
+ push word [bp+004h] ; ff 76 04 ; 0xf1871 print.c:124
+ lea dx, [di-001h] ; 8d 55 ff ; 0xf1874
+ mov bx, ax ; 89 c3 ; 0xf1877
+ mov ax, si ; 89 f0 ; 0xf1879
+ call 0184ch ; e8 ce ff ; 0xf187b
+ jmp short 0189dh ; eb 1d ; 0xf187e print.c:125
+ dec di ; 4f ; 0xf1880 print.c:126
+ test di, di ; 85 ff ; 0xf1881
+ jle short 0188fh ; 7e 0a ; 0xf1883
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf1885 print.c:127
+ mov ax, si ; 89 f0 ; 0xf1888
+ call 01754h ; e8 c7 fe ; 0xf188a
+ jmp short 01880h ; eb f1 ; 0xf188d
+ cmp word [bp+004h], strict byte 00000h ; 83 7e 04 00 ; 0xf188f print.c:128
+ je short 0189dh ; 74 08 ; 0xf1893
+ mov dx, strict word 0002dh ; ba 2d 00 ; 0xf1895 print.c:129
+ mov ax, si ; 89 f0 ; 0xf1898
+ call 01754h ; e8 b7 fe ; 0xf189a
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf189d print.c:131
+ mov DL, strict byte 00ah ; b2 0a ; 0xf18a0
+ mul dl ; f6 e2 ; 0xf18a2
+ mov dl, byte [bp-006h] ; 8a 56 fa ; 0xf18a4
+ sub dl, al ; 28 c2 ; 0xf18a7
+ add dl, 030h ; 80 c2 30 ; 0xf18a9
+ xor dh, dh ; 30 f6 ; 0xf18ac
+ mov ax, si ; 89 f0 ; 0xf18ae
+ call 01754h ; e8 a1 fe ; 0xf18b0
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf18b3 print.c:132
+ pop di ; 5f ; 0xf18b6
+ pop si ; 5e ; 0xf18b7
+ pop bp ; 5d ; 0xf18b8
+ retn 00002h ; c2 02 00 ; 0xf18b9
+ ; disGetNextSymbol 0xf18bc LB 0x860c -> off=0x0 cb=0000000000000021 uValue=00000000000f02bc 'put_str'
+put_str: ; 0xf18bc LB 0x21
+ push bp ; 55 ; 0xf18bc print.c:134
+ mov bp, sp ; 89 e5 ; 0xf18bd
+ push dx ; 52 ; 0xf18bf
+ push si ; 56 ; 0xf18c0
+ mov si, ax ; 89 c6 ; 0xf18c1
+ mov es, cx ; 8e c1 ; 0xf18c3 print.c:138
+ mov dl, byte [es:bx] ; 26 8a 17 ; 0xf18c5
+ test dl, dl ; 84 d2 ; 0xf18c8
+ je short 018d6h ; 74 0a ; 0xf18ca
+ xor dh, dh ; 30 f6 ; 0xf18cc print.c:139
+ mov ax, si ; 89 f0 ; 0xf18ce
+ call 01754h ; e8 81 fe ; 0xf18d0
+ inc bx ; 43 ; 0xf18d3 print.c:140
+ jmp short 018c3h ; eb ed ; 0xf18d4 print.c:141
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf18d6 print.c:142
+ pop si ; 5e ; 0xf18d9
+ pop dx ; 5a ; 0xf18da
+ pop bp ; 5d ; 0xf18db
+ retn ; c3 ; 0xf18dc
+ ; disGetNextSymbol 0xf18dd LB 0x85eb -> off=0x0 cb=0000000000000022 uValue=00000000000f02dd 'put_str_near'
+put_str_near: ; 0xf18dd LB 0x22
+ push bp ; 55 ; 0xf18dd print.c:144
+ mov bp, sp ; 89 e5 ; 0xf18de
+ push bx ; 53 ; 0xf18e0
+ push cx ; 51 ; 0xf18e1
+ mov cx, ax ; 89 c1 ; 0xf18e2
+ mov bx, dx ; 89 d3 ; 0xf18e4
+ mov al, byte [bx] ; 8a 07 ; 0xf18e6 print.c:148
+ test al, al ; 84 c0 ; 0xf18e8
+ je short 018f8h ; 74 0c ; 0xf18ea
+ xor ah, ah ; 30 e4 ; 0xf18ec print.c:149
+ mov dx, ax ; 89 c2 ; 0xf18ee
+ mov ax, cx ; 89 c8 ; 0xf18f0
+ call 01754h ; e8 5f fe ; 0xf18f2
+ inc bx ; 43 ; 0xf18f5 print.c:150
+ jmp short 018e6h ; eb ee ; 0xf18f6 print.c:151
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf18f8 print.c:152
+ pop cx ; 59 ; 0xf18fb
+ pop bx ; 5b ; 0xf18fc
+ pop bp ; 5d ; 0xf18fd
+ retn ; c3 ; 0xf18fe
+ ; disGetNextSymbol 0xf18ff LB 0x85c9 -> off=0x0 cb=0000000000000339 uValue=00000000000f02ff 'bios_printf'
+bios_printf: ; 0xf18ff LB 0x339
+ push bp ; 55 ; 0xf18ff print.c:165
+ mov bp, sp ; 89 e5 ; 0xf1900
+ push bx ; 53 ; 0xf1902
+ push cx ; 51 ; 0xf1903
+ push dx ; 52 ; 0xf1904
+ push si ; 56 ; 0xf1905
+ push di ; 57 ; 0xf1906
+ sub sp, strict byte 0001ch ; 83 ec 1c ; 0xf1907
+ lea bx, [bp+008h] ; 8d 5e 08 ; 0xf190a print.c:173
+ mov word [bp-016h], bx ; 89 5e ea ; 0xf190d
+ mov [bp-014h], ss ; 8c 56 ec ; 0xf1910
+ xor cx, cx ; 31 c9 ; 0xf1913 print.c:175
+ xor di, di ; 31 ff ; 0xf1915 print.c:176
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1917 print.c:178
+ and ax, strict word 00007h ; 25 07 00 ; 0xf191a
+ cmp ax, strict word 00007h ; 3d 07 00 ; 0xf191d
+ jne short 0192dh ; 75 0b ; 0xf1920
+ push 000deh ; 68 de 00 ; 0xf1922 print.c:179
+ push strict byte 00002h ; 6a 02 ; 0xf1925
+ call 018ffh ; e8 d5 ff ; 0xf1927
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf192a
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf192d print.c:182
+ mov dl, byte [bx] ; 8a 17 ; 0xf1930
+ test dl, dl ; 84 d2 ; 0xf1932
+ je short 01991h ; 74 5b ; 0xf1934
+ cmp dl, 025h ; 80 fa 25 ; 0xf1936 print.c:183
+ jne short 01943h ; 75 08 ; 0xf1939
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf193b print.c:184
+ xor di, di ; 31 ff ; 0xf193e print.c:185
+ jmp near 01c16h ; e9 d3 02 ; 0xf1940 print.c:187
+ test cx, cx ; 85 c9 ; 0xf1943
+ je short 01994h ; 74 4d ; 0xf1945
+ cmp dl, 030h ; 80 fa 30 ; 0xf1947 print.c:188
+ jc short 01960h ; 72 14 ; 0xf194a
+ cmp dl, 039h ; 80 fa 39 ; 0xf194c
+ jnbe short 01960h ; 77 0f ; 0xf194f
+ mov al, dl ; 88 d0 ; 0xf1951 print.c:189
+ xor ah, ah ; 30 e4 ; 0xf1953
+ imul di, di, strict byte 0000ah ; 6b ff 0a ; 0xf1955
+ sub ax, strict word 00030h ; 2d 30 00 ; 0xf1958
+ add di, ax ; 01 c7 ; 0xf195b
+ jmp near 01c16h ; e9 b6 02 ; 0xf195d print.c:191
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1960 print.c:192
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1963
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1966
+ les bx, [bp-016h] ; c4 5e ea ; 0xf196a
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf196d
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf1971
+ cmp dl, 078h ; 80 fa 78 ; 0xf1974 print.c:193
+ je short 0197eh ; 74 05 ; 0xf1977
+ cmp dl, 058h ; 80 fa 58 ; 0xf1979
+ jne short 019d8h ; 75 5a ; 0xf197c
+ test di, di ; 85 ff ; 0xf197e print.c:194
+ jne short 01985h ; 75 03 ; 0xf1980
+ mov di, strict word 00004h ; bf 04 00 ; 0xf1982 print.c:195
+ cmp dl, 078h ; 80 fa 78 ; 0xf1985 print.c:196
+ jne short 01997h ; 75 0d ; 0xf1988
+ mov word [bp-012h], strict word 00061h ; c7 46 ee 61 00 ; 0xf198a print.c:197
+ jmp short 0199ch ; eb 0b ; 0xf198f print.c:198
+ jmp near 01c1ch ; e9 88 02 ; 0xf1991
+ jmp near 01c0eh ; e9 77 02 ; 0xf1994
+ mov word [bp-012h], strict word 00041h ; c7 46 ee 41 00 ; 0xf1997 print.c:199
+ lea ax, [di-001h] ; 8d 45 ff ; 0xf199c print.c:200
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf199f
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf19a2
+ test ax, ax ; 85 c0 ; 0xf19a5
+ jl short 019e9h ; 7c 40 ; 0xf19a7
+ mov cx, ax ; 89 c1 ; 0xf19a9 print.c:201
+ sal cx, 002h ; c1 e1 02 ; 0xf19ab
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf19ae
+ shr ax, CL ; d3 e8 ; 0xf19b1
+ xor ah, ah ; 30 e4 ; 0xf19b3
+ and AL, strict byte 00fh ; 24 0f ; 0xf19b5
+ cmp ax, strict word 00009h ; 3d 09 00 ; 0xf19b7 print.c:202
+ jnbe short 019c3h ; 77 07 ; 0xf19ba
+ mov dx, ax ; 89 c2 ; 0xf19bc
+ add dx, strict byte 00030h ; 83 c2 30 ; 0xf19be
+ jmp short 019cbh ; eb 08 ; 0xf19c1
+ sub ax, strict word 0000ah ; 2d 0a 00 ; 0xf19c3
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf19c6
+ add dx, ax ; 01 c2 ; 0xf19c9
+ xor dh, dh ; 30 f6 ; 0xf19cb
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf19cd
+ call 01754h ; e8 81 fd ; 0xf19d0
+ dec word [bp-00ch] ; ff 4e f4 ; 0xf19d3 print.c:203
+ jmp short 019a2h ; eb ca ; 0xf19d6
+ cmp dl, 075h ; 80 fa 75 ; 0xf19d8 print.c:205
+ jne short 019ech ; 75 0f ; 0xf19db
+ xor cx, cx ; 31 c9 ; 0xf19dd print.c:206
+ mov bx, di ; 89 fb ; 0xf19df
+ mov dx, ax ; 89 c2 ; 0xf19e1
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf19e3
+ call 017eeh ; e8 05 fe ; 0xf19e6
+ jmp near 01c0ah ; e9 1e 02 ; 0xf19e9 print.c:208
+ cmp dl, 06ch ; 80 fa 6c ; 0xf19ec
+ jne short 019f9h ; 75 08 ; 0xf19ef
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf19f1
+ cmp dl, byte [bx+001h] ; 3a 57 01 ; 0xf19f4
+ je short 019fch ; 74 03 ; 0xf19f7
+ jmp near 01acdh ; e9 d1 00 ; 0xf19f9
+ add word [bp+006h], strict byte 00002h ; 83 46 06 02 ; 0xf19fc print.c:212
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf1a00 print.c:213
+ mov dl, byte [bx] ; 8a 17 ; 0xf1a03
+ mov word [bp-026h], ax ; 89 46 da ; 0xf1a05 print.c:215
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1a08 print.c:216
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1a0b
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1a0e
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1a12
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1a15
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf1a19
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1a1c print.c:217
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1a1f
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1a22
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1a26
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1a29
+ mov word [bp-022h], ax ; 89 46 de ; 0xf1a2d
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1a30 print.c:218
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1a33
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1a36
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1a3a
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1a3d
+ mov word [bp-020h], ax ; 89 46 e0 ; 0xf1a41
+ cmp dl, 078h ; 80 fa 78 ; 0xf1a44 print.c:219
+ je short 01a4eh ; 74 05 ; 0xf1a47
+ cmp dl, 058h ; 80 fa 58 ; 0xf1a49
+ jne short 01aa8h ; 75 5a ; 0xf1a4c
+ test di, di ; 85 ff ; 0xf1a4e print.c:220
+ jne short 01a55h ; 75 03 ; 0xf1a50
+ mov di, strict word 00010h ; bf 10 00 ; 0xf1a52 print.c:221
+ cmp dl, 078h ; 80 fa 78 ; 0xf1a55 print.c:222
+ jne short 01a61h ; 75 07 ; 0xf1a58
+ mov word [bp-012h], strict word 00061h ; c7 46 ee 61 00 ; 0xf1a5a print.c:223
+ jmp short 01a66h ; eb 05 ; 0xf1a5f print.c:224
+ mov word [bp-012h], strict word 00041h ; c7 46 ee 41 00 ; 0xf1a61 print.c:225
+ lea ax, [di-001h] ; 8d 45 ff ; 0xf1a66 print.c:226
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf1a69
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf1a6c
+ test ax, ax ; 85 c0 ; 0xf1a6f
+ jl short 01acah ; 7c 57 ; 0xf1a71
+ sal ax, 002h ; c1 e0 02 ; 0xf1a73 print.c:227
+ mov word [bp-01eh], ax ; 89 46 e2 ; 0xf1a76
+ xor ax, ax ; 31 c0 ; 0xf1a79
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf1a7b
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf1a7e
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf1a81
+ mov ax, word [bp-020h] ; 8b 46 e0 ; 0xf1a84
+ mov bx, word [bp-022h] ; 8b 5e de ; 0xf1a87
+ mov cx, word [bp-024h] ; 8b 4e dc ; 0xf1a8a
+ mov dx, word [bp-026h] ; 8b 56 da ; 0xf1a8d
+ mov si, word [bp-01eh] ; 8b 76 e2 ; 0xf1a90
+ call 09b90h ; e8 fa 80 ; 0xf1a93
+ mov ax, dx ; 89 d0 ; 0xf1a96
+ xor ah, dh ; 30 f4 ; 0xf1a98
+ and AL, strict byte 00fh ; 24 0f ; 0xf1a9a
+ cmp ax, strict word 00009h ; 3d 09 00 ; 0xf1a9c print.c:228
+ jnbe short 01aaah ; 77 09 ; 0xf1a9f
+ mov dx, ax ; 89 c2 ; 0xf1aa1
+ add dx, strict byte 00030h ; 83 c2 30 ; 0xf1aa3
+ jmp short 01ab2h ; eb 0a ; 0xf1aa6
+ jmp short 01abfh ; eb 15 ; 0xf1aa8
+ sub ax, strict word 0000ah ; 2d 0a 00 ; 0xf1aaa
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf1aad
+ add dx, ax ; 01 c2 ; 0xf1ab0
+ xor dh, dh ; 30 f6 ; 0xf1ab2
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1ab4
+ call 01754h ; e8 9a fc ; 0xf1ab7
+ dec word [bp-00ch] ; ff 4e f4 ; 0xf1aba print.c:229
+ jmp short 01a6ch ; eb ad ; 0xf1abd
+ push 000e6h ; 68 e6 00 ; 0xf1abf print.c:231
+ push strict byte 00007h ; 6a 07 ; 0xf1ac2
+ call 018ffh ; e8 38 fe ; 0xf1ac4
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf1ac7
+ jmp near 01c0ah ; e9 3d 01 ; 0xf1aca print.c:234
+ lea bx, [di-001h] ; 8d 5d ff ; 0xf1acd
+ cmp dl, 06ch ; 80 fa 6c ; 0xf1ad0
+ jne short 01b29h ; 75 54 ; 0xf1ad3
+ inc word [bp+006h] ; ff 46 06 ; 0xf1ad5 print.c:235
+ mov si, word [bp+006h] ; 8b 76 06 ; 0xf1ad8 print.c:236
+ mov dl, byte [si] ; 8a 14 ; 0xf1adb
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1add print.c:237
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1ae0
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1ae3
+ les si, [bp-016h] ; c4 76 ea ; 0xf1ae7
+ mov ax, word [es:si-002h] ; 26 8b 44 fe ; 0xf1aea
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf1aee
+ cmp dl, 064h ; 80 fa 64 ; 0xf1af1 print.c:238
+ jne short 01b22h ; 75 2c ; 0xf1af4
+ test byte [bp-00dh], 080h ; f6 46 f3 80 ; 0xf1af6 print.c:239
+ je short 01b11h ; 74 15 ; 0xf1afa
+ push strict byte 00001h ; 6a 01 ; 0xf1afc print.c:240
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf1afe
+ mov cx, word [bp-00eh] ; 8b 4e f2 ; 0xf1b01
+ neg cx ; f7 d9 ; 0xf1b04
+ neg ax ; f7 d8 ; 0xf1b06
+ sbb cx, strict byte 00000h ; 83 d9 00 ; 0xf1b08
+ mov dx, bx ; 89 da ; 0xf1b0b
+ mov bx, ax ; 89 c3 ; 0xf1b0d
+ jmp short 01b1ah ; eb 09 ; 0xf1b0f print.c:241
+ push strict byte 00000h ; 6a 00 ; 0xf1b11 print.c:242
+ mov bx, word [bp-010h] ; 8b 5e f0 ; 0xf1b13
+ mov dx, di ; 89 fa ; 0xf1b16
+ mov cx, ax ; 89 c1 ; 0xf1b18
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1b1a
+ call 0184ch ; e8 2c fd ; 0xf1b1d
+ jmp short 01acah ; eb a8 ; 0xf1b20 print.c:244
+ cmp dl, 075h ; 80 fa 75 ; 0xf1b22
+ jne short 01b2bh ; 75 04 ; 0xf1b25
+ jmp short 01b11h ; eb e8 ; 0xf1b27
+ jmp short 01b91h ; eb 66 ; 0xf1b29
+ cmp dl, 078h ; 80 fa 78 ; 0xf1b2b print.c:247
+ je short 01b35h ; 74 05 ; 0xf1b2e
+ cmp dl, 058h ; 80 fa 58 ; 0xf1b30
+ jne short 01acah ; 75 95 ; 0xf1b33
+ test di, di ; 85 ff ; 0xf1b35 print.c:249
+ jne short 01b3ch ; 75 03 ; 0xf1b37
+ mov di, strict word 00008h ; bf 08 00 ; 0xf1b39 print.c:250
+ cmp dl, 078h ; 80 fa 78 ; 0xf1b3c print.c:251
+ jne short 01b48h ; 75 07 ; 0xf1b3f
+ mov word [bp-012h], strict word 00061h ; c7 46 ee 61 00 ; 0xf1b41 print.c:252
+ jmp short 01b4dh ; eb 05 ; 0xf1b46 print.c:253
+ mov word [bp-012h], strict word 00041h ; c7 46 ee 41 00 ; 0xf1b48 print.c:254
+ lea ax, [di-001h] ; 8d 45 ff ; 0xf1b4d print.c:255
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf1b50
+ cmp word [bp-00ch], strict byte 00000h ; 83 7e f4 00 ; 0xf1b53
+ jl short 01bb3h ; 7c 5a ; 0xf1b57
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf1b59 print.c:256
+ mov cx, word [bp-00ch] ; 8b 4e f4 ; 0xf1b5c
+ sal cx, 002h ; c1 e1 02 ; 0xf1b5f
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf1b62
+ jcxz 01b6dh ; e3 06 ; 0xf1b65
+ shr dx, 1 ; d1 ea ; 0xf1b67
+ rcr ax, 1 ; d1 d8 ; 0xf1b69
+ loop 01b67h ; e2 fa ; 0xf1b6b
+ and ax, strict word 0000fh ; 25 0f 00 ; 0xf1b6d
+ cmp ax, strict word 00009h ; 3d 09 00 ; 0xf1b70 print.c:257
+ jnbe short 01b7ch ; 77 07 ; 0xf1b73
+ mov dx, ax ; 89 c2 ; 0xf1b75
+ add dx, strict byte 00030h ; 83 c2 30 ; 0xf1b77
+ jmp short 01b84h ; eb 08 ; 0xf1b7a
+ sub ax, strict word 0000ah ; 2d 0a 00 ; 0xf1b7c
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf1b7f
+ add dx, ax ; 01 c2 ; 0xf1b82
+ xor dh, dh ; 30 f6 ; 0xf1b84
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1b86
+ call 01754h ; e8 c8 fb ; 0xf1b89
+ dec word [bp-00ch] ; ff 4e f4 ; 0xf1b8c print.c:258
+ jmp short 01b53h ; eb c2 ; 0xf1b8f
+ cmp dl, 064h ; 80 fa 64 ; 0xf1b91 print.c:261
+ jne short 01bb5h ; 75 1f ; 0xf1b94
+ test byte [bp-00fh], 080h ; f6 46 f1 80 ; 0xf1b96 print.c:262
+ je short 01ba6h ; 74 0a ; 0xf1b9a
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf1b9c print.c:263
+ neg dx ; f7 da ; 0xf1b9f
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf1ba1
+ jmp short 01badh ; eb 07 ; 0xf1ba4 print.c:264
+ xor cx, cx ; 31 c9 ; 0xf1ba6 print.c:265
+ mov bx, di ; 89 fb ; 0xf1ba8
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf1baa
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1bad
+ call 0178fh ; e8 dc fb ; 0xf1bb0
+ jmp short 01c0ah ; eb 55 ; 0xf1bb3 print.c:267
+ cmp dl, 073h ; 80 fa 73 ; 0xf1bb5
+ jne short 01bc7h ; 75 0d ; 0xf1bb8
+ mov cx, ds ; 8c d9 ; 0xf1bba print.c:268
+ mov bx, word [bp-010h] ; 8b 5e f0 ; 0xf1bbc
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1bbf
+ call 018bch ; e8 f7 fc ; 0xf1bc2
+ jmp short 01c0ah ; eb 43 ; 0xf1bc5 print.c:270
+ cmp dl, 053h ; 80 fa 53 ; 0xf1bc7
+ jne short 01bedh ; 75 21 ; 0xf1bca
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf1bcc print.c:271
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf1bcf
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1bd2 print.c:272
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1bd5
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1bd8
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1bdc
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1bdf
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf1be3
+ mov bx, ax ; 89 c3 ; 0xf1be6 print.c:273
+ mov cx, word [bp-00eh] ; 8b 4e f2 ; 0xf1be8
+ jmp short 01bbfh ; eb d2 ; 0xf1beb
+ cmp dl, 063h ; 80 fa 63 ; 0xf1bed print.c:275
+ jne short 01bffh ; 75 0d ; 0xf1bf0
+ mov dl, byte [bp-010h] ; 8a 56 f0 ; 0xf1bf2 print.c:276
+ xor dh, dh ; 30 f6 ; 0xf1bf5
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1bf7
+ call 01754h ; e8 57 fb ; 0xf1bfa
+ jmp short 01c0ah ; eb 0b ; 0xf1bfd print.c:278
+ push 00107h ; 68 07 01 ; 0xf1bff print.c:279
+ push strict byte 00007h ; 6a 07 ; 0xf1c02
+ call 018ffh ; e8 f8 fc ; 0xf1c04
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf1c07
+ xor cx, cx ; 31 c9 ; 0xf1c0a print.c:280
+ jmp short 01c16h ; eb 08 ; 0xf1c0c print.c:283
+ xor dh, dh ; 30 f6 ; 0xf1c0e print.c:284
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1c10
+ call 01754h ; e8 3e fb ; 0xf1c13
+ inc word [bp+006h] ; ff 46 06 ; 0xf1c16 print.c:286
+ jmp near 0192dh ; e9 11 fd ; 0xf1c19 print.c:287
+ xor ax, ax ; 31 c0 ; 0xf1c1c print.c:288
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf1c1e
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1c21
+ test byte [bp+004h], 001h ; f6 46 04 01 ; 0xf1c24 print.c:289
+ je short 01c2eh ; 74 04 ; 0xf1c28
+ cli ; fa ; 0xf1c2a print.c:291
+ hlt ; f4 ; 0xf1c2b print.c:292
+ jmp short 01c2bh ; eb fd ; 0xf1c2c
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf1c2e print.c:294
+ pop di ; 5f ; 0xf1c31
+ pop si ; 5e ; 0xf1c32
+ pop dx ; 5a ; 0xf1c33
+ pop cx ; 59 ; 0xf1c34
+ pop bx ; 5b ; 0xf1c35
+ pop bp ; 5d ; 0xf1c36
+ retn ; c3 ; 0xf1c37
+ ; disGetNextSymbol 0xf1c38 LB 0x8290 -> off=0x0 cb=00000000000000e5 uValue=00000000000f0638 'ata_init'
+ata_init: ; 0xf1c38 LB 0xe5
+ push si ; 56 ; 0xf1c38 ata.c:97
+ push bp ; 55 ; 0xf1c39
+ mov bp, sp ; 89 e5 ; 0xf1c3a
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf1c3c ata.c:48
+ mov si, strict word 00040h ; be 40 00 ; 0xf1c3f
+ mov es, si ; 8e c6 ; 0xf1c42
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf1c44
+ mov si, 00122h ; be 22 01 ; 0xf1c47 ata.c:49
+ mov dx, bx ; 89 da ; 0xf1c4a
+ xor al, al ; 30 c0 ; 0xf1c4c ata.c:105
+ jmp short 01c54h ; eb 04 ; 0xf1c4e
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf1c50
+ jnc short 01c7dh ; 73 29 ; 0xf1c52
+ mov bl, al ; 88 c3 ; 0xf1c54 ata.c:106
+ xor bh, bh ; 30 ff ; 0xf1c56
+ imul bx, bx, strict byte 00006h ; 6b db 06 ; 0xf1c58
+ mov es, dx ; 8e c2 ; 0xf1c5b
+ add bx, si ; 01 f3 ; 0xf1c5d
+ mov byte [es:bx+00204h], 000h ; 26 c6 87 04 02 00 ; 0xf1c5f
+ mov word [es:bx+00206h], strict word 00000h ; 26 c7 87 06 02 00 00 ; 0xf1c65 ata.c:107
+ mov word [es:bx+00208h], strict word 00000h ; 26 c7 87 08 02 00 00 ; 0xf1c6c ata.c:108
+ mov byte [es:bx+00205h], 000h ; 26 c6 87 05 02 00 ; 0xf1c73 ata.c:109
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf1c79 ata.c:110
+ jmp short 01c50h ; eb d3 ; 0xf1c7b
+ xor al, al ; 30 c0 ; 0xf1c7d ata.c:113
+ jmp short 01c85h ; eb 04 ; 0xf1c7f
+ cmp AL, strict byte 008h ; 3c 08 ; 0xf1c81
+ jnc short 01cech ; 73 67 ; 0xf1c83
+ mov bl, al ; 88 c3 ; 0xf1c85 ata.c:114
+ xor bh, bh ; 30 ff ; 0xf1c87
+ imul bx, bx, strict byte 0001ch ; 6b db 1c ; 0xf1c89
+ mov es, dx ; 8e c2 ; 0xf1c8c
+ add bx, si ; 01 f3 ; 0xf1c8e
+ mov word [es:bx+022h], strict word 00000h ; 26 c7 47 22 00 00 ; 0xf1c90
+ mov word [es:bx+024h], strict word 00000h ; 26 c7 47 24 00 00 ; 0xf1c96 ata.c:116
+ mov byte [es:bx+026h], 000h ; 26 c6 47 26 00 ; 0xf1c9c ata.c:118
+ mov word [es:bx+028h], 00200h ; 26 c7 47 28 00 02 ; 0xf1ca1 ata.c:119
+ mov byte [es:bx+027h], 000h ; 26 c6 47 27 00 ; 0xf1ca7 ata.c:120
+ mov word [es:bx+02ah], strict word 00000h ; 26 c7 47 2a 00 00 ; 0xf1cac ata.c:121
+ mov word [es:bx+02ch], strict word 00000h ; 26 c7 47 2c 00 00 ; 0xf1cb2 ata.c:122
+ mov word [es:bx+02eh], strict word 00000h ; 26 c7 47 2e 00 00 ; 0xf1cb8 ata.c:123
+ mov word [es:bx+030h], strict word 00000h ; 26 c7 47 30 00 00 ; 0xf1cbe ata.c:124
+ mov word [es:bx+032h], strict word 00000h ; 26 c7 47 32 00 00 ; 0xf1cc4 ata.c:125
+ mov word [es:bx+034h], strict word 00000h ; 26 c7 47 34 00 00 ; 0xf1cca ata.c:126
+ mov word [es:bx+03ch], strict word 00000h ; 26 c7 47 3c 00 00 ; 0xf1cd0 ata.c:127
+ mov word [es:bx+03ah], strict word 00000h ; 26 c7 47 3a 00 00 ; 0xf1cd6
+ mov word [es:bx+038h], strict word 00000h ; 26 c7 47 38 00 00 ; 0xf1cdc
+ mov word [es:bx+036h], strict word 00000h ; 26 c7 47 36 00 00 ; 0xf1ce2
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf1ce8 ata.c:128
+ jmp short 01c81h ; eb 95 ; 0xf1cea
+ xor al, al ; 30 c0 ; 0xf1cec ata.c:131
+ jmp short 01cf4h ; eb 04 ; 0xf1cee
+ cmp AL, strict byte 010h ; 3c 10 ; 0xf1cf0
+ jnc short 01d0ch ; 73 18 ; 0xf1cf2
+ mov bl, al ; 88 c3 ; 0xf1cf4 ata.c:132
+ xor bh, bh ; 30 ff ; 0xf1cf6
+ mov es, dx ; 8e c2 ; 0xf1cf8
+ add bx, si ; 01 f3 ; 0xf1cfa
+ mov byte [es:bx+001e3h], 010h ; 26 c6 87 e3 01 10 ; 0xf1cfc
+ mov byte [es:bx+001f4h], 010h ; 26 c6 87 f4 01 10 ; 0xf1d02 ata.c:133
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf1d08 ata.c:134
+ jmp short 01cf0h ; eb e4 ; 0xf1d0a
+ mov es, dx ; 8e c2 ; 0xf1d0c ata.c:136
+ mov byte [es:si+001e2h], 000h ; 26 c6 84 e2 01 00 ; 0xf1d0e
+ mov byte [es:si+001f3h], 000h ; 26 c6 84 f3 01 00 ; 0xf1d14 ata.c:137
+ pop bp ; 5d ; 0xf1d1a ata.c:138
+ pop si ; 5e ; 0xf1d1b
+ retn ; c3 ; 0xf1d1c
+ ; disGetNextSymbol 0xf1d1d LB 0x81ab -> off=0x0 cb=00000000000000dd uValue=00000000000f071d 'ata_reset'
+ata_reset: ; 0xf1d1d LB 0xdd
+ push bp ; 55 ; 0xf1d1d ata.c:146
+ mov bp, sp ; 89 e5 ; 0xf1d1e
+ push bx ; 53 ; 0xf1d20
+ push cx ; 51 ; 0xf1d21
+ push dx ; 52 ; 0xf1d22
+ push si ; 56 ; 0xf1d23
+ push di ; 57 ; 0xf1d24
+ push ax ; 50 ; 0xf1d25
+ push ax ; 50 ; 0xf1d26
+ push ax ; 50 ; 0xf1d27
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf1d28 ata.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf1d2b
+ mov es, ax ; 8e c0 ; 0xf1d2e
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf1d30
+ mov di, 00122h ; bf 22 01 ; 0xf1d33 ata.c:49
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf1d36
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf1d39 ata.c:155
+ shr dx, 1 ; d1 ea ; 0xf1d3c
+ mov dh, byte [bp-010h] ; 8a 76 f0 ; 0xf1d3e ata.c:156
+ and dh, 001h ; 80 e6 01 ; 0xf1d41
+ mov byte [bp-00ch], dh ; 88 76 f4 ; 0xf1d44
+ xor dh, dh ; 30 f6 ; 0xf1d47 ata.c:158
+ imul bx, dx, strict byte 00006h ; 6b da 06 ; 0xf1d49
+ mov es, ax ; 8e c0 ; 0xf1d4c
+ add bx, di ; 01 fb ; 0xf1d4e
+ mov cx, word [es:bx+00206h] ; 26 8b 8f 06 02 ; 0xf1d50
+ mov si, word [es:bx+00208h] ; 26 8b b7 08 02 ; 0xf1d55 ata.c:159
+ lea dx, [si+006h] ; 8d 54 06 ; 0xf1d5a ata.c:164
+ mov AL, strict byte 00eh ; b0 0e ; 0xf1d5d
+ out DX, AL ; ee ; 0xf1d5f
+ mov bx, 000ffh ; bb ff 00 ; 0xf1d60 ata.c:167
+ dec bx ; 4b ; 0xf1d63 ata.c:168
+ test bx, bx ; 85 db ; 0xf1d64
+ jbe short 01d74h ; 76 0c ; 0xf1d66
+ mov dx, cx ; 89 ca ; 0xf1d68 ata.c:169
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1d6a
+ in AL, DX ; ec ; 0xf1d6d
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1d6e
+ test AL, strict byte 080h ; a8 80 ; 0xf1d70 ata.c:170
+ je short 01d63h ; 74 ef ; 0xf1d72
+ lea dx, [si+006h] ; 8d 54 06 ; 0xf1d74 ata.c:175
+ mov AL, strict byte 00ah ; b0 0a ; 0xf1d77
+ out DX, AL ; ee ; 0xf1d79
+ imul bx, word [bp-010h], strict byte 0001ch ; 6b 5e f0 1c ; 0xf1d7a ata.c:177
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf1d7e
+ add bx, di ; 01 fb ; 0xf1d81
+ cmp byte [es:bx+022h], 000h ; 26 80 7f 22 00 ; 0xf1d83
+ je short 01dd6h ; 74 4c ; 0xf1d88
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf1d8a ata.c:180
+ je short 01d95h ; 74 05 ; 0xf1d8e
+ mov ax, 000b0h ; b8 b0 00 ; 0xf1d90
+ jmp short 01d98h ; eb 03 ; 0xf1d93
+ mov ax, 000a0h ; b8 a0 00 ; 0xf1d95
+ mov dx, cx ; 89 ca ; 0xf1d98
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf1d9a
+ out DX, AL ; ee ; 0xf1d9d
+ mov dx, cx ; 89 ca ; 0xf1d9e ata.c:181
+ inc dx ; 42 ; 0xf1da0
+ inc dx ; 42 ; 0xf1da1
+ in AL, DX ; ec ; 0xf1da2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1da3
+ mov bx, ax ; 89 c3 ; 0xf1da5
+ mov dx, cx ; 89 ca ; 0xf1da7 ata.c:182
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf1da9
+ in AL, DX ; ec ; 0xf1dac
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1dad
+ cmp bl, 001h ; 80 fb 01 ; 0xf1daf ata.c:184
+ jne short 01dd6h ; 75 22 ; 0xf1db2
+ cmp al, bl ; 38 d8 ; 0xf1db4
+ jne short 01dd6h ; 75 1e ; 0xf1db6
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf1db8 ata.c:186
+ dec bx ; 4b ; 0xf1dbb ata.c:187
+ test bx, bx ; 85 db ; 0xf1dbc
+ jbe short 01dd6h ; 76 16 ; 0xf1dbe
+ mov dx, cx ; 89 ca ; 0xf1dc0 ata.c:188
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1dc2
+ in AL, DX ; ec ; 0xf1dc5
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1dc6
+ test AL, strict byte 080h ; a8 80 ; 0xf1dc8 ata.c:189
+ je short 01dd6h ; 74 0a ; 0xf1dca
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf1dcc ata.c:191
+ dec ax ; 48 ; 0xf1dcf ata.c:192
+ test ax, ax ; 85 c0 ; 0xf1dd0
+ jnbe short 01dcfh ; 77 fb ; 0xf1dd2
+ jmp short 01dbbh ; eb e5 ; 0xf1dd4 ata.c:195
+ mov bx, strict word 00010h ; bb 10 00 ; 0xf1dd6 ata.c:200
+ dec bx ; 4b ; 0xf1dd9 ata.c:201
+ test bx, bx ; 85 db ; 0xf1dda
+ jbe short 01deah ; 76 0c ; 0xf1ddc
+ mov dx, cx ; 89 ca ; 0xf1dde ata.c:202
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1de0
+ in AL, DX ; ec ; 0xf1de3
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1de4
+ test AL, strict byte 040h ; a8 40 ; 0xf1de6 ata.c:203
+ je short 01dd9h ; 74 ef ; 0xf1de8
+ lea dx, [si+006h] ; 8d 54 06 ; 0xf1dea ata.c:208
+ mov AL, strict byte 008h ; b0 08 ; 0xf1ded
+ out DX, AL ; ee ; 0xf1def
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf1df0 ata.c:209
+ pop di ; 5f ; 0xf1df3
+ pop si ; 5e ; 0xf1df4
+ pop dx ; 5a ; 0xf1df5
+ pop cx ; 59 ; 0xf1df6
+ pop bx ; 5b ; 0xf1df7
+ pop bp ; 5d ; 0xf1df8
+ retn ; c3 ; 0xf1df9
+ ; disGetNextSymbol 0xf1dfa LB 0x80ce -> off=0x0 cb=00000000000002b5 uValue=00000000000f07fa 'ata_cmd_data_in'
+ata_cmd_data_in: ; 0xf1dfa LB 0x2b5
+ push bp ; 55 ; 0xf1dfa ata.c:223
+ mov bp, sp ; 89 e5 ; 0xf1dfb
+ push si ; 56 ; 0xf1dfd
+ push di ; 57 ; 0xf1dfe
+ sub sp, strict byte 00010h ; 83 ec 10 ; 0xf1dff
+ push ax ; 50 ; 0xf1e02
+ push dx ; 52 ; 0xf1e03
+ push bx ; 53 ; 0xf1e04
+ push cx ; 51 ; 0xf1e05
+ mov es, dx ; 8e c2 ; 0xf1e06 ata.c:233
+ mov bx, ax ; 89 c3 ; 0xf1e08
+ mov al, byte [es:bx+00ch] ; 26 8a 47 0c ; 0xf1e0a
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf1e0e
+ mov bl, al ; 88 c3 ; 0xf1e11 ata.c:235
+ xor bh, ah ; 30 e7 ; 0xf1e13
+ mov ax, bx ; 89 d8 ; 0xf1e15
+ cwd ; 99 ; 0xf1e17
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf1e18
+ sar ax, 1 ; d1 f8 ; 0xf1e1a
+ imul ax, ax, strict byte 00006h ; 6b c0 06 ; 0xf1e1c
+ mov di, word [bp-016h] ; 8b 7e ea ; 0xf1e1f
+ add di, ax ; 01 c7 ; 0xf1e22
+ mov ax, word [es:di+00206h] ; 26 8b 85 06 02 ; 0xf1e24
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf1e29
+ mov ax, word [es:di+00208h] ; 26 8b 85 08 02 ; 0xf1e2c ata.c:236
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf1e31
+ imul bx, bx, strict byte 0001ch ; 6b db 1c ; 0xf1e34 ata.c:238
+ add bx, word [bp-016h] ; 03 5e ea ; 0xf1e37
+ mov ax, word [es:bx+028h] ; 26 8b 47 28 ; 0xf1e3a
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf1e3e
+ test ax, ax ; 85 c0 ; 0xf1e41 ata.c:239
+ jne short 01e4ch ; 75 07 ; 0xf1e43
+ mov word [bp-00eh], 08000h ; c7 46 f2 00 80 ; 0xf1e45 ata.c:245
+ jmp short 01e4fh ; eb 03 ; 0xf1e4a ata.c:246
+ shr word [bp-00eh], 1 ; d1 6e f2 ; 0xf1e4c ata.c:252
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1e4f ata.c:255
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1e52
+ in AL, DX ; ec ; 0xf1e55
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1e56
+ test AL, strict byte 080h ; a8 80 ; 0xf1e58 ata.c:256
+ je short 01e6bh ; 74 0f ; 0xf1e5a
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf1e5c ata.c:260
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf1e5f
+ mov AL, strict byte 008h ; b0 08 ; 0xf1e62
+ out DX, AL ; ee ; 0xf1e64
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf1e65 ata.c:261
+ jmp near 020a8h ; e9 3d 02 ; 0xf1e68
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf1e6b ata.c:264
+ mov di, word [bp-016h] ; 8b 7e ea ; 0xf1e6e
+ mov di, word [es:di+008h] ; 26 8b 7d 08 ; 0xf1e71
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf1e75
+ mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xf1e78
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf1e7c
+ mov al, byte [es:bx+016h] ; 26 8a 47 16 ; 0xf1e7f ata.c:265
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf1e83
+ mov ax, word [es:bx+012h] ; 26 8b 47 12 ; 0xf1e86 ata.c:266
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf1e8a
+ mov ah, byte [es:bx+014h] ; 26 8a 67 14 ; 0xf1e8d ata.c:267
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf1e91 ata.c:270
+ test al, al ; 84 c0 ; 0xf1e94
+ je short 01e9bh ; 74 03 ; 0xf1e96
+ jmp near 01f7eh ; e9 e3 00 ; 0xf1e98
+ xor bx, bx ; 31 db ; 0xf1e9b ata.c:271
+ xor dx, dx ; 31 d2 ; 0xf1e9d
+ xor ah, ah ; 30 e4 ; 0xf1e9f
+ mov si, word [bp-016h] ; 8b 76 ea ; 0xf1ea1
+ mov cx, word [es:si] ; 26 8b 0c ; 0xf1ea4
+ add cx, word [bp-01ch] ; 03 4e e4 ; 0xf1ea7
+ mov word [bp-014h], cx ; 89 4e ec ; 0xf1eaa
+ adc bx, word [es:si+002h] ; 26 13 5c 02 ; 0xf1ead
+ adc dx, word [es:si+004h] ; 26 13 54 04 ; 0xf1eb1
+ adc ax, word [es:si+006h] ; 26 13 44 06 ; 0xf1eb5
+ test ax, ax ; 85 c0 ; 0xf1eb9
+ jnbe short 01ed0h ; 77 13 ; 0xf1ebb
+ je short 01ec2h ; 74 03 ; 0xf1ebd
+ jmp near 01f34h ; e9 72 00 ; 0xf1ebf
+ test dx, dx ; 85 d2 ; 0xf1ec2
+ jnbe short 01ed0h ; 77 0a ; 0xf1ec4
+ jne short 01f34h ; 75 6c ; 0xf1ec6
+ cmp bx, 01000h ; 81 fb 00 10 ; 0xf1ec8
+ jnbe short 01ed0h ; 77 02 ; 0xf1ecc
+ jne short 01f34h ; 75 64 ; 0xf1ece
+ mov bx, si ; 89 f3 ; 0xf1ed0 ata.c:273
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf1ed2
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf1ed6
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf1eda
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf1ede
+ mov si, strict word 00018h ; be 18 00 ; 0xf1ee1
+ call 09b90h ; e8 a9 7c ; 0xf1ee4
+ xor dh, dh ; 30 f6 ; 0xf1ee7
+ mov word [bp-014h], dx ; 89 56 ec ; 0xf1ee9
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf1eec ata.c:274
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf1eef
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf1ef3
+ mov si, word [bp-016h] ; 8b 76 ea ; 0xf1ef7
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf1efa
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf1efe
+ mov si, strict word 00020h ; be 20 00 ; 0xf1f01
+ call 09b90h ; e8 89 7c ; 0xf1f04
+ mov bx, dx ; 89 d3 ; 0xf1f07
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf1f09 ata.c:275
+ xor al, al ; 30 c0 ; 0xf1f0c
+ shr ax, 008h ; c1 e8 08 ; 0xf1f0e
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1f11
+ inc dx ; 42 ; 0xf1f14
+ inc dx ; 42 ; 0xf1f15
+ out DX, AL ; ee ; 0xf1f16
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1f17 ata.c:276
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf1f1a
+ mov al, byte [bp-014h] ; 8a 46 ec ; 0xf1f1d
+ out DX, AL ; ee ; 0xf1f20
+ mov ax, bx ; 89 d8 ; 0xf1f21 ata.c:277
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1f23
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf1f26
+ out DX, AL ; ee ; 0xf1f29
+ shr ax, 008h ; c1 e8 08 ; 0xf1f2a ata.c:278
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1f2d
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf1f30
+ out DX, AL ; ee ; 0xf1f33
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf1f34 ata.c:282
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf1f37
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf1f3a
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf1f3d
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf1f40 ata.c:283
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf1f44
+ mov si, word [bp-016h] ; 8b 76 ea ; 0xf1f48
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf1f4b
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf1f4f
+ mov si, strict word 00008h ; be 08 00 ; 0xf1f52
+ call 09b90h ; e8 38 7c ; 0xf1f55
+ mov word [bp-012h], dx ; 89 56 ee ; 0xf1f58
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf1f5b ata.c:284
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf1f5e
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf1f62
+ mov si, word [bp-016h] ; 8b 76 ea ; 0xf1f66
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf1f69
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf1f6d
+ mov si, strict word 00018h ; be 18 00 ; 0xf1f70
+ call 09b90h ; e8 1a 7c ; 0xf1f73
+ mov ah, dl ; 88 d4 ; 0xf1f76
+ and ah, 00fh ; 80 e4 0f ; 0xf1f78
+ or ah, 040h ; 80 cc 40 ; 0xf1f7b
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf1f7e ata.c:287
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf1f81
+ mov AL, strict byte 00ah ; b0 0a ; 0xf1f84
+ out DX, AL ; ee ; 0xf1f86
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1f87 ata.c:288
+ inc dx ; 42 ; 0xf1f8a
+ xor al, al ; 30 c0 ; 0xf1f8b
+ out DX, AL ; ee ; 0xf1f8d
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1f8e ata.c:289
+ inc dx ; 42 ; 0xf1f91
+ inc dx ; 42 ; 0xf1f92
+ mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xf1f93
+ out DX, AL ; ee ; 0xf1f96
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1f97 ata.c:290
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf1f9a
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf1f9d
+ out DX, AL ; ee ; 0xf1fa0
+ mov bx, word [bp-012h] ; 8b 5e ee ; 0xf1fa1 ata.c:291
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1fa4
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf1fa7
+ mov al, bl ; 88 d8 ; 0xf1faa
+ out DX, AL ; ee ; 0xf1fac
+ mov dx, bx ; 89 da ; 0xf1fad ata.c:292
+ shr dx, 008h ; c1 ea 08 ; 0xf1faf
+ mov bx, word [bp-00ah] ; 8b 5e f6 ; 0xf1fb2
+ add bx, strict byte 00005h ; 83 c3 05 ; 0xf1fb5
+ mov al, dl ; 88 d0 ; 0xf1fb8
+ mov dx, bx ; 89 da ; 0xf1fba
+ out DX, AL ; ee ; 0xf1fbc
+ test byte [bp-008h], 001h ; f6 46 f8 01 ; 0xf1fbd ata.c:293
+ je short 01fc8h ; 74 05 ; 0xf1fc1
+ mov dx, 000b0h ; ba b0 00 ; 0xf1fc3
+ jmp short 01fcbh ; eb 03 ; 0xf1fc6
+ mov dx, 000a0h ; ba a0 00 ; 0xf1fc8
+ mov al, ah ; 88 e0 ; 0xf1fcb
+ xor ah, ah ; 30 e4 ; 0xf1fcd
+ or ax, dx ; 09 d0 ; 0xf1fcf
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1fd1
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf1fd4
+ out DX, AL ; ee ; 0xf1fd7
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1fd8 ata.c:294
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1fdb
+ mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xf1fde
+ out DX, AL ; ee ; 0xf1fe1
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf1fe2 ata.c:296
+ cmp ax, 000c4h ; 3d c4 00 ; 0xf1fe5
+ je short 01fefh ; 74 05 ; 0xf1fe8
+ cmp ax, strict word 00029h ; 3d 29 00 ; 0xf1fea
+ jne short 01ff9h ; 75 0a ; 0xf1fed
+ mov si, word [bp-01ch] ; 8b 76 e4 ; 0xf1fef ata.c:297
+ mov word [bp-01ch], strict word 00001h ; c7 46 e4 01 00 ; 0xf1ff2 ata.c:298
+ jmp short 01ffch ; eb 03 ; 0xf1ff7 ata.c:299
+ mov si, strict word 00001h ; be 01 00 ; 0xf1ff9 ata.c:300
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1ffc ata.c:304
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1fff
+ in AL, DX ; ec ; 0xf2002
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2003
+ mov bl, al ; 88 c3 ; 0xf2005
+ test AL, strict byte 080h ; a8 80 ; 0xf2007 ata.c:305
+ jne short 01ffch ; 75 f1 ; 0xf2009
+ test AL, strict byte 001h ; a8 01 ; 0xf200b ata.c:309
+ je short 0201eh ; 74 0f ; 0xf200d
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf200f ata.c:312
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2012
+ mov AL, strict byte 008h ; b0 08 ; 0xf2015
+ out DX, AL ; ee ; 0xf2017
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf2018 ata.c:313
+ jmp near 020a8h ; e9 8a 00 ; 0xf201b
+ test bl, 008h ; f6 c3 08 ; 0xf201e ata.c:314
+ jne short 02032h ; 75 0f ; 0xf2021
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2023 ata.c:317
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2026
+ mov AL, strict byte 008h ; b0 08 ; 0xf2029
+ out DX, AL ; ee ; 0xf202b
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf202c ata.c:318
+ jmp near 020a8h ; e9 76 00 ; 0xf202f
+ sti ; fb ; 0xf2032 ata.c:323
+ cmp di, 0f800h ; 81 ff 00 f8 ; 0xf2033 ata.c:328
+ jc short 02046h ; 72 0d ; 0xf2037
+ sub di, 00800h ; 81 ef 00 08 ; 0xf2039 ata.c:329
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf203d
+ add ax, 00080h ; 05 80 00 ; 0xf2040
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf2043
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2046 ata.c:336
+ mov cx, word [bp-00eh] ; 8b 4e f2 ; 0xf2049
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf204c
+ rep insw ; f3 6d ; 0xf204f
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf2051 ata.c:337
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf2054
+ add word [es:bx+018h], si ; 26 01 77 18 ; 0xf2057
+ dec word [bp-01ch] ; ff 4e e4 ; 0xf205b ata.c:338
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf205e ata.c:340
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2061
+ in AL, DX ; ec ; 0xf2064
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2065
+ mov bl, al ; 88 c3 ; 0xf2067
+ test AL, strict byte 080h ; a8 80 ; 0xf2069 ata.c:341
+ jne short 0205eh ; 75 f1 ; 0xf206b
+ cmp word [bp-01ch], strict byte 00000h ; 83 7e e4 00 ; 0xf206d ata.c:344
+ jne short 02087h ; 75 14 ; 0xf2071
+ and AL, strict byte 0c9h ; 24 c9 ; 0xf2073 ata.c:345
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf2075
+ je short 0209dh ; 74 24 ; 0xf2077
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2079 ata.c:349
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf207c
+ mov AL, strict byte 008h ; b0 08 ; 0xf207f
+ out DX, AL ; ee ; 0xf2081
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf2082 ata.c:350
+ jmp short 020a8h ; eb 21 ; 0xf2085
+ mov al, bl ; 88 d8 ; 0xf2087 ata.c:355
+ and AL, strict byte 0c9h ; 24 c9 ; 0xf2089
+ cmp AL, strict byte 048h ; 3c 48 ; 0xf208b
+ je short 02033h ; 74 a4 ; 0xf208d
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf208f ata.c:359
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2092
+ mov AL, strict byte 008h ; b0 08 ; 0xf2095
+ out DX, AL ; ee ; 0xf2097
+ mov ax, strict word 00005h ; b8 05 00 ; 0xf2098 ata.c:360
+ jmp short 020a8h ; eb 0b ; 0xf209b
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf209d ata.c:366
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf20a0
+ mov AL, strict byte 008h ; b0 08 ; 0xf20a3
+ out DX, AL ; ee ; 0xf20a5
+ xor ax, ax ; 31 c0 ; 0xf20a6 ata.c:367
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf20a8 ata.c:368
+ pop di ; 5f ; 0xf20ab
+ pop si ; 5e ; 0xf20ac
+ pop bp ; 5d ; 0xf20ad
+ retn ; c3 ; 0xf20ae
+ ; disGetNextSymbol 0xf20af LB 0x7e19 -> off=0x0 cb=00000000000006aa uValue=00000000000f0aaf 'ata_detect'
+ata_detect: ; 0xf20af LB 0x6aa
+ push bp ; 55 ; 0xf20af ata.c:374
+ mov bp, sp ; 89 e5 ; 0xf20b0
+ push si ; 56 ; 0xf20b2
+ push di ; 57 ; 0xf20b3
+ sub sp, 00262h ; 81 ec 62 02 ; 0xf20b4
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf20b8 ata.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf20bb
+ mov es, ax ; 8e c0 ; 0xf20be
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf20c0
+ mov word [bp-028h], ax ; 89 46 d8 ; 0xf20c3 ata.c:49
+ mov bx, 00122h ; bb 22 01 ; 0xf20c6 ata.c:381
+ mov es, ax ; 8e c0 ; 0xf20c9
+ mov word [bp-02ch], bx ; 89 5e d4 ; 0xf20cb
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf20ce
+ mov byte [es:bx+00204h], 000h ; 26 c6 87 04 02 00 ; 0xf20d1 ata.c:384
+ mov word [es:bx+00206h], 001f0h ; 26 c7 87 06 02 f0 01 ; 0xf20d7 ata.c:385
+ mov word [es:bx+00208h], 003f0h ; 26 c7 87 08 02 f0 03 ; 0xf20de ata.c:386
+ mov byte [es:bx+00205h], 00eh ; 26 c6 87 05 02 0e ; 0xf20e5 ata.c:387
+ mov byte [es:bx+0020ah], 000h ; 26 c6 87 0a 02 00 ; 0xf20eb ata.c:390
+ mov word [es:bx+0020ch], 00170h ; 26 c7 87 0c 02 70 01 ; 0xf20f1 ata.c:391
+ mov word [es:bx+0020eh], 00370h ; 26 c7 87 0e 02 70 03 ; 0xf20f8 ata.c:392
+ mov byte [es:bx+0020bh], 00fh ; 26 c6 87 0b 02 0f ; 0xf20ff ata.c:393
+ xor al, al ; 30 c0 ; 0xf2105 ata.c:414
+ mov byte [bp-016h], al ; 88 46 ea ; 0xf2107
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf210a
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf210d ata.c:416
+ jmp near 026d9h ; e9 c6 05 ; 0xf2110
+ mov ax, 000a0h ; b8 a0 00 ; 0xf2113 ata.c:431
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf2116
+ out DX, AL ; ee ; 0xf2119
+ lea si, [bx+002h] ; 8d 77 02 ; 0xf211a ata.c:432
+ mov AL, strict byte 055h ; b0 55 ; 0xf211d
+ mov dx, si ; 89 f2 ; 0xf211f
+ out DX, AL ; ee ; 0xf2121
+ lea di, [bx+003h] ; 8d 7f 03 ; 0xf2122 ata.c:433
+ mov AL, strict byte 0aah ; b0 aa ; 0xf2125
+ mov dx, di ; 89 fa ; 0xf2127
+ out DX, AL ; ee ; 0xf2129
+ mov dx, si ; 89 f2 ; 0xf212a ata.c:434
+ out DX, AL ; ee ; 0xf212c
+ mov AL, strict byte 055h ; b0 55 ; 0xf212d ata.c:435
+ mov dx, di ; 89 fa ; 0xf212f
+ out DX, AL ; ee ; 0xf2131
+ mov dx, si ; 89 f2 ; 0xf2132 ata.c:436
+ out DX, AL ; ee ; 0xf2134
+ mov AL, strict byte 0aah ; b0 aa ; 0xf2135 ata.c:437
+ mov dx, di ; 89 fa ; 0xf2137
+ out DX, AL ; ee ; 0xf2139
+ mov dx, si ; 89 f2 ; 0xf213a ata.c:440
+ in AL, DX ; ec ; 0xf213c
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf213d
+ mov cx, ax ; 89 c1 ; 0xf213f
+ mov dx, di ; 89 fa ; 0xf2141 ata.c:441
+ in AL, DX ; ec ; 0xf2143
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2144
+ cmp cl, 055h ; 80 f9 55 ; 0xf2146 ata.c:443
+ jne short 02195h ; 75 4a ; 0xf2149
+ cmp AL, strict byte 0aah ; 3c aa ; 0xf214b
+ jne short 02195h ; 75 46 ; 0xf214d
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf214f ata.c:444
+ xor ah, ah ; 30 e4 ; 0xf2152
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf2154
+ mov es, [bp-01ch] ; 8e 46 e4 ; 0xf2157
+ mov si, word [bp-02ch] ; 8b 76 d4 ; 0xf215a
+ add si, ax ; 01 c6 ; 0xf215d
+ mov byte [es:si+022h], 001h ; 26 c6 44 22 01 ; 0xf215f
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf2164 ata.c:447
+ xor ah, ah ; 30 e4 ; 0xf2167
+ call 01d1dh ; e8 b1 fb ; 0xf2169
+ cmp byte [bp-012h], 000h ; 80 7e ee 00 ; 0xf216c ata.c:450
+ je short 02177h ; 74 05 ; 0xf2170
+ mov ax, 000b0h ; b8 b0 00 ; 0xf2172
+ jmp short 0217ah ; eb 03 ; 0xf2175
+ mov ax, 000a0h ; b8 a0 00 ; 0xf2177
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf217a
+ out DX, AL ; ee ; 0xf217d
+ lea dx, [bx+002h] ; 8d 57 02 ; 0xf217e ata.c:451
+ in AL, DX ; ec ; 0xf2181
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2182
+ mov cx, ax ; 89 c1 ; 0xf2184
+ lea dx, [bx+003h] ; 8d 57 03 ; 0xf2186 ata.c:452
+ in AL, DX ; ec ; 0xf2189
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf218a
+ cmp cl, 001h ; 80 f9 01 ; 0xf218c ata.c:453
+ jne short 021d6h ; 75 45 ; 0xf218f
+ cmp al, cl ; 38 c8 ; 0xf2191
+ je short 02197h ; 74 02 ; 0xf2193
+ jmp short 021d6h ; eb 3f ; 0xf2195
+ lea dx, [bx+004h] ; 8d 57 04 ; 0xf2197 ata.c:454
+ in AL, DX ; ec ; 0xf219a
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf219b
+ mov cx, ax ; 89 c1 ; 0xf219d
+ mov ch, al ; 88 c5 ; 0xf219f
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf21a1 ata.c:455
+ in AL, DX ; ec ; 0xf21a4
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf21a5
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf21a7
+ mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xf21aa
+ mov byte [bp-010h], al ; 88 46 f0 ; 0xf21ad
+ lea dx, [bx+007h] ; 8d 57 07 ; 0xf21b0 ata.c:456
+ in AL, DX ; ec ; 0xf21b3
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf21b4
+ cmp cl, 014h ; 80 f9 14 ; 0xf21b6 ata.c:458
+ jne short 021d8h ; 75 1d ; 0xf21b9
+ cmp byte [bp-01ah], 0ebh ; 80 7e e6 eb ; 0xf21bb
+ jne short 021d8h ; 75 17 ; 0xf21bf
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf21c1 ata.c:459
+ xor ah, ah ; 30 e4 ; 0xf21c4
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf21c6
+ mov es, [bp-01ch] ; 8e 46 e4 ; 0xf21c9
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf21cc
+ add bx, ax ; 01 c3 ; 0xf21cf
+ mov byte [es:bx+022h], 003h ; 26 c6 47 22 03 ; 0xf21d1
+ jmp short 0221ch ; eb 44 ; 0xf21d6 ata.c:460
+ test ch, ch ; 84 ed ; 0xf21d8
+ jne short 021fdh ; 75 21 ; 0xf21da
+ cmp byte [bp-010h], 000h ; 80 7e f0 00 ; 0xf21dc
+ jne short 021fdh ; 75 1b ; 0xf21e0
+ test al, al ; 84 c0 ; 0xf21e2
+ je short 021fdh ; 74 17 ; 0xf21e4
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf21e6 ata.c:461
+ xor ah, ah ; 30 e4 ; 0xf21e9
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf21eb
+ mov es, [bp-01ch] ; 8e 46 e4 ; 0xf21ee
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf21f1
+ add bx, ax ; 01 c3 ; 0xf21f4
+ mov byte [es:bx+022h], 002h ; 26 c6 47 22 02 ; 0xf21f6
+ jmp short 0221ch ; eb 1f ; 0xf21fb ata.c:462
+ cmp ch, 0ffh ; 80 fd ff ; 0xf21fd
+ jne short 0221ch ; 75 1a ; 0xf2200
+ cmp ch, byte [bp-010h] ; 3a 6e f0 ; 0xf2202
+ jne short 0221ch ; 75 15 ; 0xf2205
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf2207 ata.c:463
+ xor ah, ah ; 30 e4 ; 0xf220a
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf220c
+ mov es, [bp-01ch] ; 8e 46 e4 ; 0xf220f
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf2212
+ add bx, ax ; 01 c3 ; 0xf2215
+ mov byte [es:bx+022h], 000h ; 26 c6 47 22 00 ; 0xf2217
+ mov dx, word [bp-01eh] ; 8b 56 e2 ; 0xf221c ata.c:469
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf221f
+ mov AL, strict byte 008h ; b0 08 ; 0xf2222
+ out DX, AL ; ee ; 0xf2224
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf2225 ata.c:471
+ xor ah, ah ; 30 e4 ; 0xf2228
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf222a
+ mov es, [bp-01ch] ; 8e 46 e4 ; 0xf222d
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf2230
+ add bx, ax ; 01 c3 ; 0xf2233
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf2235
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf2239
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf223c ata.c:474
+ jne short 02289h ; 75 49 ; 0xf223e
+ mov byte [es:bx+023h], 0ffh ; 26 c6 47 23 ff ; 0xf2240 ata.c:482
+ mov byte [es:bx+026h], 000h ; 26 c6 47 26 00 ; 0xf2245 ata.c:483
+ lea dx, [bp-00266h] ; 8d 96 9a fd ; 0xf224a ata.c:484
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf224e
+ mov word [es:bx+008h], dx ; 26 89 57 08 ; 0xf2251
+ mov [es:bx+00ah], ss ; 26 8c 57 0a ; 0xf2255
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf2259 ata.c:485
+ mov byte [es:bx+00ch], al ; 26 88 47 0c ; 0xf225c
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf2260 ata.c:487
+ mov bx, 000ech ; bb ec 00 ; 0xf2263
+ mov ax, word [bp-02ch] ; 8b 46 d4 ; 0xf2266
+ mov dx, es ; 8c c2 ; 0xf2269
+ call 01dfah ; e8 8c fb ; 0xf226b
+ test ax, ax ; 85 c0 ; 0xf226e
+ je short 0227dh ; 74 0b ; 0xf2270
+ push 00124h ; 68 24 01 ; 0xf2272 ata.c:488
+ push strict byte 00007h ; 6a 07 ; 0xf2275
+ call 018ffh ; e8 85 f6 ; 0xf2277
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf227a
+ test byte [bp-00266h], 080h ; f6 86 9a fd 80 ; 0xf227d ata.c:490
+ je short 0228ch ; 74 08 ; 0xf2282
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf2284
+ jmp short 0228eh ; eb 05 ; 0xf2287
+ jmp near 024a0h ; e9 14 02 ; 0xf2289
+ xor ax, ax ; 31 c0 ; 0xf228c
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf228e
+ mov byte [bp-018h], 000h ; c6 46 e8 00 ; 0xf2291 ata.c:494
+ mov word [bp-022h], 00200h ; c7 46 de 00 02 ; 0xf2295 ata.c:496
+ mov ax, word [bp-00264h] ; 8b 86 9c fd ; 0xf229a ata.c:498
+ mov word [bp-032h], ax ; 89 46 ce ; 0xf229e
+ mov ax, word [bp-00260h] ; 8b 86 a0 fd ; 0xf22a1 ata.c:499
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf22a5
+ mov ax, word [bp-0025ah] ; 8b 86 a6 fd ; 0xf22a8 ata.c:500
+ mov word [bp-030h], ax ; 89 46 d0 ; 0xf22ac
+ mov ax, word [bp-001eeh] ; 8b 86 12 fe ; 0xf22af ata.c:502
+ mov word [bp-02eh], ax ; 89 46 d2 ; 0xf22b3
+ mov si, word [bp-001ech] ; 8b b6 14 fe ; 0xf22b6
+ xor ax, ax ; 31 c0 ; 0xf22ba
+ mov word [bp-020h], ax ; 89 46 e0 ; 0xf22bc
+ mov word [bp-026h], ax ; 89 46 da ; 0xf22bf
+ cmp si, 00fffh ; 81 fe ff 0f ; 0xf22c2 ata.c:503
+ jne short 022e7h ; 75 1f ; 0xf22c6
+ cmp word [bp-02eh], strict byte 0ffffh ; 83 7e d2 ff ; 0xf22c8
+ jne short 022e7h ; 75 19 ; 0xf22cc
+ mov ax, word [bp-00198h] ; 8b 86 68 fe ; 0xf22ce ata.c:504
+ mov word [bp-026h], ax ; 89 46 da ; 0xf22d2
+ mov ax, word [bp-0019ah] ; 8b 86 66 fe ; 0xf22d5
+ mov word [bp-020h], ax ; 89 46 e0 ; 0xf22d9
+ mov si, word [bp-0019ch] ; 8b b6 64 fe ; 0xf22dc
+ mov ax, word [bp-0019eh] ; 8b 86 62 fe ; 0xf22e0
+ mov word [bp-02eh], ax ; 89 46 d2 ; 0xf22e4
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf22e7 ata.c:505
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf22ea
+ jc short 022fah ; 72 0c ; 0xf22ec
+ jbe short 02302h ; 76 12 ; 0xf22ee
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf22f0
+ je short 0230ah ; 74 16 ; 0xf22f2
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf22f4
+ je short 02306h ; 74 0e ; 0xf22f6
+ jmp short 02344h ; eb 4a ; 0xf22f8
+ test al, al ; 84 c0 ; 0xf22fa
+ jne short 02344h ; 75 46 ; 0xf22fc
+ mov BL, strict byte 01eh ; b3 1e ; 0xf22fe ata.c:508
+ jmp short 0230ch ; eb 0a ; 0xf2300 ata.c:509
+ mov BL, strict byte 026h ; b3 26 ; 0xf2302 ata.c:511
+ jmp short 0230ch ; eb 06 ; 0xf2304 ata.c:512
+ mov BL, strict byte 067h ; b3 67 ; 0xf2306 ata.c:514
+ jmp short 0230ch ; eb 02 ; 0xf2308 ata.c:515
+ mov BL, strict byte 070h ; b3 70 ; 0xf230a ata.c:517
+ mov al, bl ; 88 d8 ; 0xf230c ata.c:524
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf230e
+ xor ah, ah ; 30 e4 ; 0xf2310
+ call 01650h ; e8 3b f3 ; 0xf2312
+ xor ah, ah ; 30 e4 ; 0xf2315
+ mov dx, ax ; 89 c2 ; 0xf2317
+ sal dx, 008h ; c1 e2 08 ; 0xf2319
+ mov al, bl ; 88 d8 ; 0xf231c
+ call 01650h ; e8 2f f3 ; 0xf231e
+ xor ah, ah ; 30 e4 ; 0xf2321
+ add ax, dx ; 01 d0 ; 0xf2323
+ mov word [bp-03ah], ax ; 89 46 c6 ; 0xf2325
+ mov al, bl ; 88 d8 ; 0xf2328 ata.c:525
+ add AL, strict byte 002h ; 04 02 ; 0xf232a
+ xor ah, ah ; 30 e4 ; 0xf232c
+ call 01650h ; e8 1f f3 ; 0xf232e
+ xor ah, ah ; 30 e4 ; 0xf2331
+ mov word [bp-03ch], ax ; 89 46 c4 ; 0xf2333
+ mov al, bl ; 88 d8 ; 0xf2336 ata.c:526
+ add AL, strict byte 007h ; 04 07 ; 0xf2338
+ call 01650h ; e8 13 f3 ; 0xf233a
+ xor ah, ah ; 30 e4 ; 0xf233d
+ mov word [bp-038h], ax ; 89 46 c8 ; 0xf233f
+ jmp short 02356h ; eb 12 ; 0xf2342 ata.c:528
+ push word [bp-026h] ; ff 76 da ; 0xf2344 ata.c:529
+ push word [bp-020h] ; ff 76 e0 ; 0xf2347
+ push si ; 56 ; 0xf234a
+ push word [bp-02eh] ; ff 76 d2 ; 0xf234b
+ mov dx, ss ; 8c d2 ; 0xf234e
+ lea ax, [bp-03ch] ; 8d 46 c4 ; 0xf2350
+ call 058b0h ; e8 5a 35 ; 0xf2353
+ mov bx, 00da0h ; bb a0 0d ; 0xf2356 ata.c:532
+ mov cx, ds ; 8c d9 ; 0xf2359
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf235b
+ call 018bch ; e8 5b f5 ; 0xf235e
+ mov ax, word [bp-038h] ; 8b 46 c8 ; 0xf2361
+ push ax ; 50 ; 0xf2364
+ mov ax, word [bp-03ch] ; 8b 46 c4 ; 0xf2365
+ push ax ; 50 ; 0xf2368
+ mov ax, word [bp-03ah] ; 8b 46 c6 ; 0xf2369
+ push ax ; 50 ; 0xf236c
+ push word [bp-030h] ; ff 76 d0 ; 0xf236d
+ push word [bp-024h] ; ff 76 dc ; 0xf2370
+ push word [bp-032h] ; ff 76 ce ; 0xf2373
+ mov al, byte [bp-012h] ; 8a 46 ee ; 0xf2376
+ xor ah, ah ; 30 e4 ; 0xf2379
+ push ax ; 50 ; 0xf237b
+ mov al, byte [bp-014h] ; 8a 46 ec ; 0xf237c
+ push ax ; 50 ; 0xf237f
+ push 0014dh ; 68 4d 01 ; 0xf2380
+ push strict byte 00004h ; 6a 04 ; 0xf2383
+ call 018ffh ; e8 77 f5 ; 0xf2385
+ add sp, strict byte 00014h ; 83 c4 14 ; 0xf2388
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf238b ata.c:534
+ xor ah, ah ; 30 e4 ; 0xf238e
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf2390
+ mov es, [bp-01ch] ; 8e 46 e4 ; 0xf2393
+ mov di, word [bp-02ch] ; 8b 7e d4 ; 0xf2396
+ add di, ax ; 01 c7 ; 0xf2399
+ mov byte [es:di+023h], 0ffh ; 26 c6 45 23 ff ; 0xf239b
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf23a0 ata.c:535
+ mov byte [es:di+024h], al ; 26 88 45 24 ; 0xf23a3
+ mov al, byte [bp-018h] ; 8a 46 e8 ; 0xf23a7 ata.c:536
+ mov byte [es:di+026h], al ; 26 88 45 26 ; 0xf23aa
+ mov ax, word [bp-022h] ; 8b 46 de ; 0xf23ae ata.c:537
+ mov word [es:di+028h], ax ; 26 89 45 28 ; 0xf23b1
+ mov ax, word [bp-024h] ; 8b 46 dc ; 0xf23b5 ata.c:538
+ mov word [es:di+030h], ax ; 26 89 45 30 ; 0xf23b8
+ mov ax, word [bp-032h] ; 8b 46 ce ; 0xf23bc ata.c:539
+ mov word [es:di+032h], ax ; 26 89 45 32 ; 0xf23bf
+ mov ax, word [bp-030h] ; 8b 46 d0 ; 0xf23c3 ata.c:540
+ mov word [es:di+034h], ax ; 26 89 45 34 ; 0xf23c6
+ mov ax, word [bp-026h] ; 8b 46 da ; 0xf23ca ata.c:541
+ mov word [es:di+03ch], ax ; 26 89 45 3c ; 0xf23cd
+ mov ax, word [bp-020h] ; 8b 46 e0 ; 0xf23d1
+ mov word [es:di+03ah], ax ; 26 89 45 3a ; 0xf23d4
+ mov word [es:di+038h], si ; 26 89 75 38 ; 0xf23d8
+ mov ax, word [bp-02eh] ; 8b 46 d2 ; 0xf23dc
+ mov word [es:di+036h], ax ; 26 89 45 36 ; 0xf23df
+ lea di, [di+02ah] ; 8d 7d 2a ; 0xf23e3 ata.c:542
+ push DS ; 1e ; 0xf23e6
+ push SS ; 16 ; 0xf23e7
+ pop DS ; 1f ; 0xf23e8
+ lea si, [bp-03ch] ; 8d 76 c4 ; 0xf23e9
+ movsw ; a5 ; 0xf23ec
+ movsw ; a5 ; 0xf23ed
+ movsw ; a5 ; 0xf23ee
+ pop DS ; 1f ; 0xf23ef
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf23f0 ata.c:543
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf23f3
+ jnc short 0246ah ; 73 73 ; 0xf23f5
+ test al, al ; 84 c0 ; 0xf23f7 ata.c:549
+ jne short 02400h ; 75 05 ; 0xf23f9
+ mov bx, strict word 0003dh ; bb 3d 00 ; 0xf23fb ata.c:550
+ jmp short 02403h ; eb 03 ; 0xf23fe ata.c:551
+ mov bx, strict word 0004dh ; bb 4d 00 ; 0xf2400 ata.c:552
+ mov cx, word [bp-028h] ; 8b 4e d8 ; 0xf2403
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf2406 ata.c:564
+ xor ah, ah ; 30 e4 ; 0xf2409
+ imul si, ax, strict byte 00005h ; 6b f0 05 ; 0xf240b
+ sal si, 002h ; c1 e6 02 ; 0xf240e
+ add si, 00104h ; 81 c6 04 01 ; 0xf2411
+ xor al, al ; 30 c0 ; 0xf2415
+ mov es, ax ; 8e c0 ; 0xf2417
+ mov word [es:si], bx ; 26 89 1c ; 0xf2419 ata.c:565
+ mov word [es:si+002h], cx ; 26 89 4c 02 ; 0xf241c
+ mov es, cx ; 8e c1 ; 0xf2420 ata.c:571
+ mov word [es:bx+00ch], strict word 00000h ; 26 c7 47 0c 00 00 ; 0xf2422
+ mov ax, word [es:bx+00ch] ; 26 8b 47 0c ; 0xf2428
+ mov word [es:bx+005h], ax ; 26 89 47 05 ; 0xf242c
+ mov word [es:bx+007h], strict word 00000h ; 26 c7 47 07 00 00 ; 0xf2430
+ mov ax, word [bp-03ah] ; 8b 46 c6 ; 0xf2436 ata.c:573
+ mov word [es:bx], ax ; 26 89 07 ; 0xf2439
+ mov al, byte [bp-03ch] ; 8a 46 c4 ; 0xf243c ata.c:574
+ mov byte [es:bx+002h], al ; 26 88 47 02 ; 0xf243f
+ mov byte [es:bx+003h], 0a0h ; 26 c6 47 03 a0 ; 0xf2443 ata.c:575
+ mov al, byte [bp-030h] ; 8a 46 d0 ; 0xf2448 ata.c:576
+ mov byte [es:bx+004h], al ; 26 88 47 04 ; 0xf244b
+ mov ax, word [bp-032h] ; 8b 46 ce ; 0xf244f ata.c:577
+ mov word [es:bx+009h], ax ; 26 89 47 09 ; 0xf2452
+ mov al, byte [bp-024h] ; 8a 46 dc ; 0xf2456 ata.c:578
+ mov byte [es:bx+00bh], al ; 26 88 47 0b ; 0xf2459
+ mov al, byte [bp-038h] ; 8a 46 c8 ; 0xf245d ata.c:579
+ mov byte [es:bx+00eh], al ; 26 88 47 0e ; 0xf2460
+ xor al, al ; 30 c0 ; 0xf2464 ata.c:580
+ xor ah, ah ; 30 e4 ; 0xf2466 ata.c:581
+ jmp short 02471h ; eb 07 ; 0xf2468
+ jmp short 0248ah ; eb 1e ; 0xf246a
+ cmp ah, 00fh ; 80 fc 0f ; 0xf246c
+ jnc short 02482h ; 73 11 ; 0xf246f
+ mov dl, ah ; 88 e2 ; 0xf2471 ata.c:582
+ xor dh, dh ; 30 f6 ; 0xf2473
+ mov es, cx ; 8e c1 ; 0xf2475
+ mov si, bx ; 89 de ; 0xf2477
+ add si, dx ; 01 d6 ; 0xf2479
+ add al, byte [es:si] ; 26 02 04 ; 0xf247b
+ db 0feh, 0c4h
+ ; inc ah ; fe c4 ; 0xf247e
+ jmp short 0246ch ; eb ea ; 0xf2480
+ neg al ; f6 d8 ; 0xf2482 ata.c:583
+ mov es, cx ; 8e c1 ; 0xf2484 ata.c:584
+ mov byte [es:bx+00fh], al ; 26 88 47 0f ; 0xf2486
+ mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xf248a ata.c:588
+ xor bh, bh ; 30 ff ; 0xf248d
+ mov es, [bp-01ch] ; 8e 46 e4 ; 0xf248f
+ add bx, word [bp-02ch] ; 03 5e d4 ; 0xf2492
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf2495
+ mov byte [es:bx+001e3h], al ; 26 88 87 e3 01 ; 0xf2498
+ inc byte [bp-00ah] ; fe 46 f6 ; 0xf249d ata.c:589
+ cmp byte [bp-008h], 003h ; 80 7e f8 03 ; 0xf24a0 ata.c:593
+ jne short 02506h ; 75 60 ; 0xf24a4
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf24a6 ata.c:598
+ xor ah, ah ; 30 e4 ; 0xf24a9
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf24ab
+ mov es, [bp-01ch] ; 8e 46 e4 ; 0xf24ae
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf24b1
+ add bx, ax ; 01 c3 ; 0xf24b4
+ mov byte [es:bx+023h], 005h ; 26 c6 47 23 05 ; 0xf24b6
+ mov byte [es:bx+026h], 000h ; 26 c6 47 26 00 ; 0xf24bb ata.c:599
+ lea dx, [bp-00266h] ; 8d 96 9a fd ; 0xf24c0 ata.c:600
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf24c4
+ mov word [es:bx+008h], dx ; 26 89 57 08 ; 0xf24c7
+ mov [es:bx+00ah], ss ; 26 8c 57 0a ; 0xf24cb
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf24cf ata.c:601
+ mov byte [es:bx+00ch], al ; 26 88 47 0c ; 0xf24d2
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf24d6 ata.c:603
+ mov bx, 000a1h ; bb a1 00 ; 0xf24d9
+ mov ax, word [bp-02ch] ; 8b 46 d4 ; 0xf24dc
+ mov dx, es ; 8c c2 ; 0xf24df
+ call 01dfah ; e8 16 f9 ; 0xf24e1
+ test ax, ax ; 85 c0 ; 0xf24e4
+ je short 024f3h ; 74 0b ; 0xf24e6
+ push 00174h ; 68 74 01 ; 0xf24e8 ata.c:604
+ push strict byte 00007h ; 6a 07 ; 0xf24eb
+ call 018ffh ; e8 0f f4 ; 0xf24ed
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf24f0
+ mov cl, byte [bp-00265h] ; 8a 8e 9b fd ; 0xf24f3 ata.c:606
+ and cl, 01fh ; 80 e1 1f ; 0xf24f7
+ test byte [bp-00266h], 080h ; f6 86 9a fd 80 ; 0xf24fa ata.c:607
+ je short 02508h ; 74 07 ; 0xf24ff
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf2501
+ jmp short 0250ah ; eb 04 ; 0xf2504
+ jmp short 02540h ; eb 38 ; 0xf2506
+ xor ax, ax ; 31 c0 ; 0xf2508
+ mov dl, byte [bp-00ch] ; 8a 56 f4 ; 0xf250a ata.c:615
+ xor dh, dh ; 30 f6 ; 0xf250d
+ imul dx, dx, strict byte 0001ch ; 6b d2 1c ; 0xf250f
+ mov es, [bp-01ch] ; 8e 46 e4 ; 0xf2512
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf2515
+ add bx, dx ; 01 d3 ; 0xf2518
+ mov byte [es:bx+023h], cl ; 26 88 4f 23 ; 0xf251a
+ mov byte [es:bx+024h], al ; 26 88 47 24 ; 0xf251e ata.c:616
+ mov byte [es:bx+026h], 000h ; 26 c6 47 26 00 ; 0xf2522 ata.c:617
+ mov word [es:bx+028h], 00800h ; 26 c7 47 28 00 08 ; 0xf2527 ata.c:618
+ mov bl, byte [bp-016h] ; 8a 5e ea ; 0xf252d ata.c:621
+ xor bh, bh ; 30 ff ; 0xf2530
+ add bx, word [bp-02ch] ; 03 5e d4 ; 0xf2532
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf2535
+ mov byte [es:bx+001f4h], al ; 26 88 87 f4 01 ; 0xf2538
+ inc byte [bp-016h] ; fe 46 ea ; 0xf253d ata.c:622
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf2540 ata.c:631
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf2543
+ je short 02577h ; 74 30 ; 0xf2545
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf2547
+ jne short 025a7h ; 75 5c ; 0xf2549
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf254b ata.c:633
+ xor ah, ah ; 30 e4 ; 0xf254e
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf2550
+ mov es, [bp-01ch] ; 8e 46 e4 ; 0xf2553
+ mov di, word [bp-02ch] ; 8b 7e d4 ; 0xf2556
+ add di, ax ; 01 c7 ; 0xf2559
+ mov ax, word [es:di+03ch] ; 26 8b 45 3c ; 0xf255b
+ mov bx, word [es:di+03ah] ; 26 8b 5d 3a ; 0xf255f
+ mov cx, word [es:di+038h] ; 26 8b 4d 38 ; 0xf2563
+ mov dx, word [es:di+036h] ; 26 8b 55 36 ; 0xf2567
+ mov si, strict word 0000bh ; be 0b 00 ; 0xf256b
+ call 09b90h ; e8 1f 76 ; 0xf256e
+ mov word [bp-02ah], dx ; 89 56 d6 ; 0xf2571
+ mov word [bp-034h], cx ; 89 4e cc ; 0xf2574
+ mov al, byte [bp-001c5h] ; 8a 86 3b fe ; 0xf2577 ata.c:636
+ xor ah, ah ; 30 e4 ; 0xf257b
+ mov dx, ax ; 89 c2 ; 0xf257d
+ sal dx, 008h ; c1 e2 08 ; 0xf257f
+ mov al, byte [bp-001c6h] ; 8a 86 3a fe ; 0xf2582
+ or ax, dx ; 09 d0 ; 0xf2586
+ mov byte [bp-006h], 00fh ; c6 46 fa 0f ; 0xf2588 ata.c:637
+ jmp short 02597h ; eb 09 ; 0xf258c
+ dec byte [bp-006h] ; fe 4e fa ; 0xf258e ata.c:640
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf2591
+ jbe short 025a3h ; 76 0c ; 0xf2595
+ mov cl, byte [bp-006h] ; 8a 4e fa ; 0xf2597
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf259a
+ sal dx, CL ; d3 e2 ; 0xf259d
+ test ax, dx ; 85 d0 ; 0xf259f
+ je short 0258eh ; 74 eb ; 0xf25a1
+ xor di, di ; 31 ff ; 0xf25a3 ata.c:643
+ jmp short 025aeh ; eb 07 ; 0xf25a5
+ jmp short 025ddh ; eb 34 ; 0xf25a7
+ cmp di, strict byte 00014h ; 83 ff 14 ; 0xf25a9
+ jnl short 025c3h ; 7d 15 ; 0xf25ac
+ mov si, di ; 89 fe ; 0xf25ae ata.c:644
+ add si, di ; 01 fe ; 0xf25b0
+ mov al, byte [bp+si-0022fh] ; 8a 82 d1 fd ; 0xf25b2
+ mov byte [bp+si-066h], al ; 88 42 9a ; 0xf25b6
+ mov al, byte [bp+si-00230h] ; 8a 82 d0 fd ; 0xf25b9 ata.c:645
+ mov byte [bp+si-065h], al ; 88 42 9b ; 0xf25bd
+ inc di ; 47 ; 0xf25c0 ata.c:646
+ jmp short 025a9h ; eb e6 ; 0xf25c1
+ mov byte [bp-03eh], 000h ; c6 46 c2 00 ; 0xf25c3 ata.c:649
+ mov di, strict word 00027h ; bf 27 00 ; 0xf25c7 ata.c:650
+ jmp short 025d1h ; eb 05 ; 0xf25ca
+ dec di ; 4f ; 0xf25cc ata.c:655
+ test di, di ; 85 ff ; 0xf25cd
+ jle short 025ddh ; 7e 0c ; 0xf25cf
+ cmp byte [bp+di-066h], 020h ; 80 7b 9a 20 ; 0xf25d1
+ jne short 025ddh ; 75 06 ; 0xf25d5
+ mov byte [bp+di-066h], 000h ; c6 43 9a 00 ; 0xf25d7
+ jmp short 025cch ; eb ef ; 0xf25db
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf25dd ata.c:662
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf25e0
+ je short 02641h ; 74 5d ; 0xf25e2
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf25e4
+ je short 025efh ; 74 07 ; 0xf25e6
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf25e8
+ je short 0264ch ; 74 60 ; 0xf25ea
+ jmp near 026d0h ; e9 e1 00 ; 0xf25ec
+ cmp byte [bp-012h], 000h ; 80 7e ee 00 ; 0xf25ef ata.c:665
+ je short 025fah ; 74 05 ; 0xf25f3
+ mov ax, 0019fh ; b8 9f 01 ; 0xf25f5
+ jmp short 025fdh ; eb 03 ; 0xf25f8
+ mov ax, 001a6h ; b8 a6 01 ; 0xf25fa
+ push ax ; 50 ; 0xf25fd
+ mov al, byte [bp-014h] ; 8a 46 ec ; 0xf25fe
+ xor ah, ah ; 30 e4 ; 0xf2601
+ push ax ; 50 ; 0xf2603
+ push 001adh ; 68 ad 01 ; 0xf2604
+ push strict byte 00002h ; 6a 02 ; 0xf2607
+ call 018ffh ; e8 f3 f2 ; 0xf2609
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf260c
+ xor di, di ; 31 ff ; 0xf260f ata.c:666
+ mov al, byte [bp+di-066h] ; 8a 43 9a ; 0xf2611 ata.c:667
+ xor ah, ah ; 30 e4 ; 0xf2614
+ inc di ; 47 ; 0xf2616
+ test ax, ax ; 85 c0 ; 0xf2617
+ je short 02629h ; 74 0e ; 0xf2619
+ push ax ; 50 ; 0xf261b ata.c:668
+ push 001b8h ; 68 b8 01 ; 0xf261c
+ push strict byte 00002h ; 6a 02 ; 0xf261f
+ call 018ffh ; e8 db f2 ; 0xf2621
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf2624
+ jmp short 02611h ; eb e8 ; 0xf2627
+ push word [bp-034h] ; ff 76 cc ; 0xf2629 ata.c:669
+ push word [bp-02ah] ; ff 76 d6 ; 0xf262c
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf262f
+ push ax ; 50 ; 0xf2632
+ push 001bbh ; 68 bb 01 ; 0xf2633
+ push strict byte 00002h ; 6a 02 ; 0xf2636
+ call 018ffh ; e8 c4 f2 ; 0xf2638
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf263b
+ jmp near 026d0h ; e9 8f 00 ; 0xf263e ata.c:670
+ cmp byte [bp-012h], 000h ; 80 7e ee 00 ; 0xf2641 ata.c:672
+ je short 0264eh ; 74 07 ; 0xf2645
+ mov ax, 0019fh ; b8 9f 01 ; 0xf2647
+ jmp short 02651h ; eb 05 ; 0xf264a
+ jmp short 026b0h ; eb 62 ; 0xf264c
+ mov ax, 001a6h ; b8 a6 01 ; 0xf264e
+ push ax ; 50 ; 0xf2651
+ mov al, byte [bp-014h] ; 8a 46 ec ; 0xf2652
+ xor ah, ah ; 30 e4 ; 0xf2655
+ push ax ; 50 ; 0xf2657
+ push 001adh ; 68 ad 01 ; 0xf2658
+ push strict byte 00002h ; 6a 02 ; 0xf265b
+ call 018ffh ; e8 9f f2 ; 0xf265d
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf2660
+ xor di, di ; 31 ff ; 0xf2663 ata.c:673
+ mov al, byte [bp+di-066h] ; 8a 43 9a ; 0xf2665 ata.c:674
+ xor ah, ah ; 30 e4 ; 0xf2668
+ inc di ; 47 ; 0xf266a
+ test ax, ax ; 85 c0 ; 0xf266b
+ je short 0267dh ; 74 0e ; 0xf266d
+ push ax ; 50 ; 0xf266f ata.c:675
+ push 001b8h ; 68 b8 01 ; 0xf2670
+ push strict byte 00002h ; 6a 02 ; 0xf2673
+ call 018ffh ; e8 87 f2 ; 0xf2675
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf2678
+ jmp short 02665h ; eb e8 ; 0xf267b
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf267d ata.c:676
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf2680
+ mov es, [bp-01ch] ; 8e 46 e4 ; 0xf2683
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf2686
+ add bx, ax ; 01 c3 ; 0xf2689
+ cmp byte [es:bx+023h], 005h ; 26 80 7f 23 05 ; 0xf268b
+ jne short 0269dh ; 75 0b ; 0xf2690
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf2692 ata.c:677
+ xor ah, ah ; 30 e4 ; 0xf2695
+ push ax ; 50 ; 0xf2697
+ push 001dbh ; 68 db 01 ; 0xf2698
+ jmp short 026a6h ; eb 09 ; 0xf269b ata.c:678
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf269d ata.c:679
+ xor ah, ah ; 30 e4 ; 0xf26a0
+ push ax ; 50 ; 0xf26a2
+ push 001f5h ; 68 f5 01 ; 0xf26a3
+ push strict byte 00002h ; 6a 02 ; 0xf26a6
+ call 018ffh ; e8 54 f2 ; 0xf26a8
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf26ab
+ jmp short 026d0h ; eb 20 ; 0xf26ae ata.c:680
+ cmp byte [bp-012h], 000h ; 80 7e ee 00 ; 0xf26b0 ata.c:682
+ je short 026bbh ; 74 05 ; 0xf26b4
+ mov ax, 0019fh ; b8 9f 01 ; 0xf26b6
+ jmp short 026beh ; eb 03 ; 0xf26b9
+ mov ax, 001a6h ; b8 a6 01 ; 0xf26bb
+ push ax ; 50 ; 0xf26be
+ mov al, byte [bp-014h] ; 8a 46 ec ; 0xf26bf
+ xor ah, ah ; 30 e4 ; 0xf26c2
+ push ax ; 50 ; 0xf26c4
+ push 00207h ; 68 07 02 ; 0xf26c5
+ push strict byte 00002h ; 6a 02 ; 0xf26c8
+ call 018ffh ; e8 32 f2 ; 0xf26ca
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf26cd
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf26d0 ata.c:687
+ cmp byte [bp-00ch], 008h ; 80 7e f4 08 ; 0xf26d3
+ jnc short 0272eh ; 73 55 ; 0xf26d7
+ mov bl, byte [bp-00ch] ; 8a 5e f4 ; 0xf26d9
+ xor bh, bh ; 30 ff ; 0xf26dc
+ mov ax, bx ; 89 d8 ; 0xf26de
+ cwd ; 99 ; 0xf26e0
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf26e1
+ sar ax, 1 ; d1 f8 ; 0xf26e3
+ mov cx, ax ; 89 c1 ; 0xf26e5
+ mov byte [bp-014h], al ; 88 46 ec ; 0xf26e7
+ mov ax, bx ; 89 d8 ; 0xf26ea
+ cwd ; 99 ; 0xf26ec
+ mov bx, strict word 00002h ; bb 02 00 ; 0xf26ed
+ idiv bx ; f7 fb ; 0xf26f0
+ mov word [bp-036h], dx ; 89 56 ca ; 0xf26f2
+ mov al, byte [bp-036h] ; 8a 46 ca ; 0xf26f5
+ mov byte [bp-012h], al ; 88 46 ee ; 0xf26f8
+ mov al, cl ; 88 c8 ; 0xf26fb
+ xor ah, ah ; 30 e4 ; 0xf26fd
+ imul ax, ax, strict byte 00006h ; 6b c0 06 ; 0xf26ff
+ mov es, [bp-01ch] ; 8e 46 e4 ; 0xf2702
+ mov si, word [bp-02ch] ; 8b 76 d4 ; 0xf2705
+ add si, ax ; 01 c6 ; 0xf2708
+ mov bx, word [es:si+00206h] ; 26 8b 9c 06 02 ; 0xf270a
+ mov ax, word [es:si+00208h] ; 26 8b 84 08 02 ; 0xf270f
+ mov word [bp-01eh], ax ; 89 46 e2 ; 0xf2714
+ mov dx, ax ; 89 c2 ; 0xf2717
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2719
+ mov AL, strict byte 00ah ; b0 0a ; 0xf271c
+ out DX, AL ; ee ; 0xf271e
+ cmp byte [bp-036h], 000h ; 80 7e ca 00 ; 0xf271f
+ jne short 02728h ; 75 03 ; 0xf2723
+ jmp near 02113h ; e9 eb f9 ; 0xf2725
+ mov ax, 000b0h ; b8 b0 00 ; 0xf2728
+ jmp near 02116h ; e9 e8 f9 ; 0xf272b
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf272e ata.c:690
+ mov es, [bp-01ch] ; 8e 46 e4 ; 0xf2731
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf2734
+ mov byte [es:bx+001e2h], al ; 26 88 87 e2 01 ; 0xf2737
+ mov al, byte [bp-016h] ; 8a 46 ea ; 0xf273c ata.c:691
+ mov byte [es:bx+001f3h], al ; 26 88 87 f3 01 ; 0xf273f
+ mov bx, strict word 00075h ; bb 75 00 ; 0xf2744 ata.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2747
+ mov es, ax ; 8e c0 ; 0xf274a
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf274c
+ mov byte [es:bx], al ; 26 88 07 ; 0xf274f
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf2752 ata.c:704
+ pop di ; 5f ; 0xf2755
+ pop si ; 5e ; 0xf2756
+ pop bp ; 5d ; 0xf2757
+ retn ; c3 ; 0xf2758
+ ; disGetNextSymbol 0xf2759 LB 0x776f -> off=0x0 cb=000000000000028a uValue=00000000000f1159 'ata_cmd_data_out'
+ata_cmd_data_out: ; 0xf2759 LB 0x28a
+ push bp ; 55 ; 0xf2759 ata.c:718
+ mov bp, sp ; 89 e5 ; 0xf275a
+ push si ; 56 ; 0xf275c
+ push di ; 57 ; 0xf275d
+ sub sp, strict byte 00020h ; 83 ec 20 ; 0xf275e
+ mov di, ax ; 89 c7 ; 0xf2761
+ mov word [bp-00ah], dx ; 89 56 f6 ; 0xf2763
+ mov word [bp-01eh], bx ; 89 5e e2 ; 0xf2766
+ mov word [bp-022h], cx ; 89 4e de ; 0xf2769
+ mov es, dx ; 8e c2 ; 0xf276c ata.c:730
+ mov al, byte [es:di+00ch] ; 26 8a 45 0c ; 0xf276e
+ xor ah, ah ; 30 e4 ; 0xf2772
+ mov dx, ax ; 89 c2 ; 0xf2774
+ shr ax, 1 ; d1 e8 ; 0xf2776 ata.c:731
+ and dl, 001h ; 80 e2 01 ; 0xf2778 ata.c:732
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf277b
+ xor ah, ah ; 30 e4 ; 0xf277e ata.c:734
+ imul ax, ax, strict byte 00006h ; 6b c0 06 ; 0xf2780
+ mov bx, di ; 89 fb ; 0xf2783
+ add bx, ax ; 01 c3 ; 0xf2785
+ mov ax, word [es:bx+00206h] ; 26 8b 87 06 02 ; 0xf2787
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf278c
+ mov ax, word [es:bx+00208h] ; 26 8b 87 08 02 ; 0xf278f ata.c:735
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf2794
+ mov word [bp-020h], 00100h ; c7 46 e0 00 01 ; 0xf2797 ata.c:743
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf279c ata.c:745
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf279f
+ in AL, DX ; ec ; 0xf27a2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf27a3
+ test AL, strict byte 080h ; a8 80 ; 0xf27a5 ata.c:746
+ je short 027b8h ; 74 0f ; 0xf27a7
+ mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xf27a9 ata.c:749
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf27ac
+ mov AL, strict byte 008h ; b0 08 ; 0xf27af
+ out DX, AL ; ee ; 0xf27b1
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf27b2 ata.c:750
+ jmp near 029dch ; e9 24 02 ; 0xf27b5
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf27b8 ata.c:753
+ mov ax, word [es:di+006h] ; 26 8b 45 06 ; 0xf27bb
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf27bf
+ mov ax, word [es:di+004h] ; 26 8b 45 04 ; 0xf27c2
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf27c6
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf27c9
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf27cd
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf27d0
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf27d3
+ mov ax, word [es:di+008h] ; 26 8b 45 08 ; 0xf27d6 ata.c:754
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf27da
+ mov ax, word [es:di+00ah] ; 26 8b 45 0a ; 0xf27dd
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf27e1
+ mov ax, word [es:di+016h] ; 26 8b 45 16 ; 0xf27e4 ata.c:755
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf27e8
+ mov ax, word [es:di+012h] ; 26 8b 45 12 ; 0xf27eb ata.c:756
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf27ef
+ mov ax, word [es:di+014h] ; 26 8b 45 14 ; 0xf27f2 ata.c:757
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf27f6
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf27f9 ata.c:760
+ test ax, ax ; 85 c0 ; 0xf27fc
+ je short 02803h ; 74 03 ; 0xf27fe
+ jmp near 028cah ; e9 c7 00 ; 0xf2800
+ xor bx, bx ; 31 db ; 0xf2803 ata.c:761
+ xor dx, dx ; 31 d2 ; 0xf2805
+ mov si, word [bp-024h] ; 8b 76 dc ; 0xf2807
+ add si, word [bp-022h] ; 03 76 de ; 0xf280a
+ adc bx, word [bp-010h] ; 13 5e f0 ; 0xf280d
+ adc ax, word [bp-00eh] ; 13 46 f2 ; 0xf2810
+ adc dx, word [bp-00ch] ; 13 56 f4 ; 0xf2813
+ test dx, dx ; 85 d2 ; 0xf2816
+ jnbe short 0282ah ; 77 10 ; 0xf2818
+ jne short 0288dh ; 75 71 ; 0xf281a
+ test ax, ax ; 85 c0 ; 0xf281c
+ jnbe short 0282ah ; 77 0a ; 0xf281e
+ jne short 0288dh ; 75 6b ; 0xf2820
+ cmp bx, 01000h ; 81 fb 00 10 ; 0xf2822
+ jnbe short 0282ah ; 77 02 ; 0xf2826
+ jne short 0288dh ; 75 63 ; 0xf2828
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf282a ata.c:763
+ mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xf282d
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf2830
+ mov dx, word [bp-024h] ; 8b 56 dc ; 0xf2833
+ mov si, strict word 00018h ; be 18 00 ; 0xf2836
+ call 09b90h ; e8 54 73 ; 0xf2839
+ xor dh, dh ; 30 f6 ; 0xf283c
+ mov word [bp-014h], dx ; 89 56 ec ; 0xf283e
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf2841 ata.c:764
+ mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xf2844
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf2847
+ mov dx, word [bp-024h] ; 8b 56 dc ; 0xf284a
+ mov si, strict word 00020h ; be 20 00 ; 0xf284d
+ call 09b90h ; e8 3d 73 ; 0xf2850
+ mov bx, dx ; 89 d3 ; 0xf2853
+ mov ax, word [bp-022h] ; 8b 46 de ; 0xf2855 ata.c:765
+ xor al, al ; 30 c0 ; 0xf2858
+ shr ax, 008h ; c1 e8 08 ; 0xf285a
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf285d
+ inc dx ; 42 ; 0xf2860
+ inc dx ; 42 ; 0xf2861
+ out DX, AL ; ee ; 0xf2862
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2863 ata.c:766
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf2866
+ mov al, byte [bp-014h] ; 8a 46 ec ; 0xf2869
+ out DX, AL ; ee ; 0xf286c
+ mov ax, bx ; 89 d8 ; 0xf286d ata.c:767
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf286f
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf2872
+ out DX, AL ; ee ; 0xf2875
+ shr ax, 008h ; c1 e8 08 ; 0xf2876 ata.c:768
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2879
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf287c
+ out DX, AL ; ee ; 0xf287f
+ xor al, al ; 30 c0 ; 0xf2880 ata.c:771
+ mov byte [bp-00fh], al ; 88 46 f1 ; 0xf2882
+ xor ah, ah ; 30 e4 ; 0xf2885
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf2887
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf288a
+ mov ax, word [bp-024h] ; 8b 46 dc ; 0xf288d ata.c:773
+ xor ah, ah ; 30 e4 ; 0xf2890
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf2892
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf2895 ata.c:774
+ mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xf2898
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf289b
+ mov dx, word [bp-024h] ; 8b 56 dc ; 0xf289e
+ mov si, strict word 00008h ; be 08 00 ; 0xf28a1
+ call 09b90h ; e8 e9 72 ; 0xf28a4
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf28a7
+ mov word [bp-00eh], bx ; 89 5e f2 ; 0xf28aa
+ mov word [bp-010h], cx ; 89 4e f0 ; 0xf28ad
+ mov word [bp-024h], dx ; 89 56 dc ; 0xf28b0
+ mov word [bp-018h], dx ; 89 56 e8 ; 0xf28b3 ata.c:775
+ mov si, strict word 00010h ; be 10 00 ; 0xf28b6 ata.c:776
+ call 09b90h ; e8 d4 72 ; 0xf28b9
+ mov word [bp-024h], dx ; 89 56 dc ; 0xf28bc
+ mov ax, dx ; 89 d0 ; 0xf28bf ata.c:777
+ xor ah, dh ; 30 f4 ; 0xf28c1
+ and AL, strict byte 00fh ; 24 0f ; 0xf28c3
+ or AL, strict byte 040h ; 0c 40 ; 0xf28c5
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf28c7
+ mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xf28ca ata.c:780
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf28cd
+ mov AL, strict byte 00ah ; b0 0a ; 0xf28d0
+ out DX, AL ; ee ; 0xf28d2
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf28d3 ata.c:781
+ inc dx ; 42 ; 0xf28d6
+ xor al, al ; 30 c0 ; 0xf28d7
+ out DX, AL ; ee ; 0xf28d9
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf28da ata.c:782
+ inc dx ; 42 ; 0xf28dd
+ inc dx ; 42 ; 0xf28de
+ mov al, byte [bp-022h] ; 8a 46 de ; 0xf28df
+ out DX, AL ; ee ; 0xf28e2
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf28e3 ata.c:783
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf28e6
+ mov al, byte [bp-014h] ; 8a 46 ec ; 0xf28e9
+ out DX, AL ; ee ; 0xf28ec
+ mov ax, word [bp-018h] ; 8b 46 e8 ; 0xf28ed ata.c:784
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf28f0
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf28f3
+ out DX, AL ; ee ; 0xf28f6
+ shr ax, 008h ; c1 e8 08 ; 0xf28f7 ata.c:785
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf28fa
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf28fd
+ out DX, AL ; ee ; 0xf2900
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf2901 ata.c:786
+ je short 0290ch ; 74 05 ; 0xf2905
+ mov ax, 000b0h ; b8 b0 00 ; 0xf2907
+ jmp short 0290fh ; eb 03 ; 0xf290a
+ mov ax, 000a0h ; b8 a0 00 ; 0xf290c
+ mov dl, byte [bp-01ch] ; 8a 56 e4 ; 0xf290f
+ xor dh, dh ; 30 f6 ; 0xf2912
+ or ax, dx ; 09 d0 ; 0xf2914
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2916
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2919
+ out DX, AL ; ee ; 0xf291c
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf291d ata.c:787
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2920
+ mov al, byte [bp-01eh] ; 8a 46 e2 ; 0xf2923
+ out DX, AL ; ee ; 0xf2926
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2927 ata.c:790
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf292a
+ in AL, DX ; ec ; 0xf292d
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf292e
+ mov bl, al ; 88 c3 ; 0xf2930
+ test AL, strict byte 080h ; a8 80 ; 0xf2932 ata.c:791
+ jne short 02927h ; 75 f1 ; 0xf2934
+ test AL, strict byte 001h ; a8 01 ; 0xf2936 ata.c:795
+ je short 02949h ; 74 0f ; 0xf2938
+ mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xf293a ata.c:798
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf293d
+ mov AL, strict byte 008h ; b0 08 ; 0xf2940
+ out DX, AL ; ee ; 0xf2942
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf2943 ata.c:799
+ jmp near 029dch ; e9 93 00 ; 0xf2946
+ test bl, 008h ; f6 c3 08 ; 0xf2949 ata.c:800
+ jne short 0295dh ; 75 0f ; 0xf294c
+ mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xf294e ata.c:803
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2951
+ mov AL, strict byte 008h ; b0 08 ; 0xf2954
+ out DX, AL ; ee ; 0xf2956
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf2957 ata.c:804
+ jmp near 029dch ; e9 7f 00 ; 0xf295a
+ sti ; fb ; 0xf295d ata.c:809
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf295e ata.c:814
+ cmp ax, 0f800h ; 3d 00 f8 ; 0xf2961
+ jc short 02976h ; 72 10 ; 0xf2964
+ sub ax, 00800h ; 2d 00 08 ; 0xf2966 ata.c:815
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf2969
+ add dx, 00080h ; 81 c2 80 00 ; 0xf296c
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf2970
+ mov word [bp-012h], dx ; 89 56 ee ; 0xf2973
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2976 ata.c:822
+ mov cx, word [bp-020h] ; 8b 4e e0 ; 0xf2979
+ mov si, word [bp-016h] ; 8b 76 ea ; 0xf297c
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf297f
+ db 0f3h, 026h, 06fh
+ ; rep es outsw ; f3 26 6f ; 0xf2982
+ mov word [bp-016h], si ; 89 76 ea ; 0xf2985
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf2988 ata.c:824
+ inc word [es:di+018h] ; 26 ff 45 18 ; 0xf298b
+ dec word [bp-022h] ; ff 4e de ; 0xf298f ata.c:825
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2992 ata.c:827
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2995
+ in AL, DX ; ec ; 0xf2998
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2999
+ mov bl, al ; 88 c3 ; 0xf299b
+ test AL, strict byte 080h ; a8 80 ; 0xf299d ata.c:828
+ jne short 02992h ; 75 f1 ; 0xf299f
+ cmp word [bp-022h], strict byte 00000h ; 83 7e de 00 ; 0xf29a1 ata.c:831
+ jne short 029bbh ; 75 14 ; 0xf29a5
+ and AL, strict byte 0e9h ; 24 e9 ; 0xf29a7 ata.c:832
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf29a9
+ je short 029d1h ; 74 24 ; 0xf29ab
+ mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xf29ad ata.c:836
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf29b0
+ mov AL, strict byte 008h ; b0 08 ; 0xf29b3
+ out DX, AL ; ee ; 0xf29b5
+ mov ax, strict word 00006h ; b8 06 00 ; 0xf29b6 ata.c:837
+ jmp short 029dch ; eb 21 ; 0xf29b9
+ mov al, bl ; 88 d8 ; 0xf29bb ata.c:842
+ and AL, strict byte 0c9h ; 24 c9 ; 0xf29bd
+ cmp AL, strict byte 048h ; 3c 48 ; 0xf29bf
+ je short 0295eh ; 74 9b ; 0xf29c1
+ mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xf29c3 ata.c:846
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf29c6
+ mov AL, strict byte 008h ; b0 08 ; 0xf29c9
+ out DX, AL ; ee ; 0xf29cb
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf29cc ata.c:847
+ jmp short 029dch ; eb 0b ; 0xf29cf
+ mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xf29d1 ata.c:853
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf29d4
+ mov AL, strict byte 008h ; b0 08 ; 0xf29d7
+ out DX, AL ; ee ; 0xf29d9
+ xor ax, ax ; 31 c0 ; 0xf29da ata.c:854
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf29dc ata.c:855
+ pop di ; 5f ; 0xf29df
+ pop si ; 5e ; 0xf29e0
+ pop bp ; 5d ; 0xf29e1
+ retn ; c3 ; 0xf29e2
+ ; disGetNextSymbol 0xf29e3 LB 0x74e5 -> off=0x0 cb=00000000000000b5 uValue=00000000000f13e3 'ata_read_sectors'
+ata_read_sectors: ; 0xf29e3 LB 0xb5
+ push bp ; 55 ; 0xf29e3 ata.c:865
+ mov bp, sp ; 89 e5 ; 0xf29e4
+ push si ; 56 ; 0xf29e6
+ push di ; 57 ; 0xf29e7
+ sub sp, strict byte 00008h ; 83 ec 08 ; 0xf29e8
+ mov si, word [bp+004h] ; 8b 76 04 ; 0xf29eb
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf29ee ata.c:871
+ mov al, byte [es:si+00ch] ; 26 8a 44 0c ; 0xf29f1
+ mov cx, word [es:si+00eh] ; 26 8b 4c 0e ; 0xf29f5 ata.c:872
+ mov dx, cx ; 89 ca ; 0xf29f9
+ sal dx, 009h ; c1 e2 09 ; 0xf29fb
+ cmp word [es:si+016h], strict byte 00000h ; 26 83 7c 16 00 ; 0xf29fe ata.c:874
+ je short 02a24h ; 74 1f ; 0xf2a03
+ xor ah, ah ; 30 e4 ; 0xf2a05 ata.c:876
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf2a07
+ mov [bp-00ch], es ; 8c 46 f4 ; 0xf2a0a
+ mov di, si ; 89 f7 ; 0xf2a0d
+ add di, ax ; 01 c7 ; 0xf2a0f
+ mov word [es:di+028h], dx ; 26 89 55 28 ; 0xf2a11
+ mov bx, 000c4h ; bb c4 00 ; 0xf2a15 ata.c:878
+ mov ax, si ; 89 f0 ; 0xf2a18
+ mov dx, es ; 8c c2 ; 0xf2a1a
+ call 01dfah ; e8 db f3 ; 0xf2a1c
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf2a1f ata.c:879
+ jmp short 02a89h ; eb 65 ; 0xf2a22 ata.c:880
+ xor bx, bx ; 31 db ; 0xf2a24 ata.c:882
+ mov word [bp-00ch], bx ; 89 5e f4 ; 0xf2a26
+ mov word [bp-006h], bx ; 89 5e fa ; 0xf2a29
+ mov di, word [es:si] ; 26 8b 3c ; 0xf2a2c
+ add di, cx ; 01 cf ; 0xf2a2f
+ mov word [bp-00ah], di ; 89 7e f6 ; 0xf2a31
+ mov di, word [es:si+002h] ; 26 8b 7c 02 ; 0xf2a34
+ adc di, bx ; 11 df ; 0xf2a38
+ mov word [bp-008h], di ; 89 7e f8 ; 0xf2a3a
+ mov bx, word [es:si+004h] ; 26 8b 5c 04 ; 0xf2a3d
+ adc bx, word [bp-00ch] ; 13 5e f4 ; 0xf2a41
+ mov di, word [es:si+006h] ; 26 8b 7c 06 ; 0xf2a44
+ adc di, word [bp-006h] ; 13 7e fa ; 0xf2a48
+ test di, di ; 85 ff ; 0xf2a4b
+ jnbe short 02a60h ; 77 11 ; 0xf2a4d
+ jne short 02a6ch ; 75 1b ; 0xf2a4f
+ test bx, bx ; 85 db ; 0xf2a51
+ jnbe short 02a60h ; 77 0b ; 0xf2a53
+ jne short 02a6ch ; 75 15 ; 0xf2a55
+ cmp word [bp-008h], 01000h ; 81 7e f8 00 10 ; 0xf2a57
+ jnbe short 02a60h ; 77 02 ; 0xf2a5c
+ jne short 02a6ch ; 75 0c ; 0xf2a5e
+ mov bx, strict word 00024h ; bb 24 00 ; 0xf2a60 ata.c:884
+ mov ax, si ; 89 f0 ; 0xf2a63
+ mov dx, es ; 8c c2 ; 0xf2a65
+ call 01dfah ; e8 90 f3 ; 0xf2a67
+ jmp short 02a8fh ; eb 23 ; 0xf2a6a ata.c:885
+ xor ah, ah ; 30 e4 ; 0xf2a6c ata.c:886
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf2a6e
+ mov [bp-006h], es ; 8c 46 fa ; 0xf2a71
+ mov di, si ; 89 f7 ; 0xf2a74
+ add di, ax ; 01 c7 ; 0xf2a76
+ mov word [es:di+028h], dx ; 26 89 55 28 ; 0xf2a78
+ mov bx, 000c4h ; bb c4 00 ; 0xf2a7c ata.c:888
+ mov ax, si ; 89 f0 ; 0xf2a7f
+ mov dx, es ; 8c c2 ; 0xf2a81
+ call 01dfah ; e8 74 f3 ; 0xf2a83
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf2a86 ata.c:889
+ mov word [es:di+028h], 00200h ; 26 c7 45 28 00 02 ; 0xf2a89
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf2a8f ata.c:893
+ pop di ; 5f ; 0xf2a92
+ pop si ; 5e ; 0xf2a93
+ pop bp ; 5d ; 0xf2a94
+ retn 00004h ; c2 04 00 ; 0xf2a95
+ ; disGetNextSymbol 0xf2a98 LB 0x7430 -> off=0x0 cb=000000000000005b uValue=00000000000f1498 'ata_write_sectors'
+ata_write_sectors: ; 0xf2a98 LB 0x5b
+ push bp ; 55 ; 0xf2a98 ata.c:902
+ mov bp, sp ; 89 e5 ; 0xf2a99
+ push si ; 56 ; 0xf2a9b
+ push di ; 57 ; 0xf2a9c
+ push ax ; 50 ; 0xf2a9d
+ les si, [bp+004h] ; c4 76 04 ; 0xf2a9e
+ mov cx, word [es:si+00eh] ; 26 8b 4c 0e ; 0xf2aa1 ata.c:906
+ cmp word [es:si+016h], strict byte 00000h ; 26 83 7c 16 00 ; 0xf2aa5 ata.c:908
+ je short 02ab8h ; 74 0c ; 0xf2aaa
+ mov bx, strict word 00030h ; bb 30 00 ; 0xf2aac ata.c:910
+ mov ax, si ; 89 f0 ; 0xf2aaf
+ mov dx, es ; 8c c2 ; 0xf2ab1
+ call 02759h ; e8 a3 fc ; 0xf2ab3
+ jmp short 02aeah ; eb 32 ; 0xf2ab6
+ xor ax, ax ; 31 c0 ; 0xf2ab8 ata.c:913
+ xor bx, bx ; 31 db ; 0xf2aba
+ xor dx, dx ; 31 d2 ; 0xf2abc
+ mov di, word [es:si] ; 26 8b 3c ; 0xf2abe
+ add di, cx ; 01 cf ; 0xf2ac1
+ mov word [bp-006h], di ; 89 7e fa ; 0xf2ac3
+ adc ax, word [es:si+002h] ; 26 13 44 02 ; 0xf2ac6
+ adc bx, word [es:si+004h] ; 26 13 5c 04 ; 0xf2aca
+ adc dx, word [es:si+006h] ; 26 13 54 06 ; 0xf2ace
+ test dx, dx ; 85 d2 ; 0xf2ad2
+ jnbe short 02ae5h ; 77 0f ; 0xf2ad4
+ jne short 02aach ; 75 d4 ; 0xf2ad6
+ test bx, bx ; 85 db ; 0xf2ad8
+ jnbe short 02ae5h ; 77 09 ; 0xf2ada
+ jne short 02aach ; 75 ce ; 0xf2adc
+ cmp ax, 01000h ; 3d 00 10 ; 0xf2ade
+ jnbe short 02ae5h ; 77 02 ; 0xf2ae1
+ jne short 02aach ; 75 c7 ; 0xf2ae3
+ mov bx, strict word 00034h ; bb 34 00 ; 0xf2ae5 ata.c:914
+ jmp short 02aafh ; eb c5 ; 0xf2ae8
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf2aea ata.c:918
+ pop di ; 5f ; 0xf2aed
+ pop si ; 5e ; 0xf2aee
+ pop bp ; 5d ; 0xf2aef
+ retn 00004h ; c2 04 00 ; 0xf2af0
+ ; disGetNextSymbol 0xf2af3 LB 0x73d5 -> off=0x0 cb=0000000000000285 uValue=00000000000f14f3 'ata_cmd_packet'
+ata_cmd_packet: ; 0xf2af3 LB 0x285
+ push bp ; 55 ; 0xf2af3 ata.c:930
+ mov bp, sp ; 89 e5 ; 0xf2af4
+ push si ; 56 ; 0xf2af6
+ push di ; 57 ; 0xf2af7
+ sub sp, strict byte 00012h ; 83 ec 12 ; 0xf2af8
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf2afb
+ mov si, bx ; 89 de ; 0xf2afe
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf2b00 ata.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf2b03
+ mov es, dx ; 8e c2 ; 0xf2b06
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf2b08
+ mov word [bp-010h], 00122h ; c7 46 f0 22 01 ; 0xf2b0b ata.c:49
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf2b10
+ mov dx, ax ; 89 c2 ; 0xf2b13 ata.c:942
+ shr dx, 1 ; d1 ea ; 0xf2b15
+ mov ah, dl ; 88 d4 ; 0xf2b17
+ and AL, strict byte 001h ; 24 01 ; 0xf2b19 ata.c:943
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf2b1b
+ cmp byte [bp+00ah], 002h ; 80 7e 0a 02 ; 0xf2b1e ata.c:946
+ jne short 02b43h ; 75 1f ; 0xf2b22
+ mov bx, 00da0h ; bb a0 0d ; 0xf2b24 ata.c:947
+ mov cx, ds ; 8c d9 ; 0xf2b27
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf2b29
+ call 018bch ; e8 8d ed ; 0xf2b2c
+ push 00221h ; 68 21 02 ; 0xf2b2f
+ push 00230h ; 68 30 02 ; 0xf2b32
+ push strict byte 00004h ; 6a 04 ; 0xf2b35
+ call 018ffh ; e8 c5 ed ; 0xf2b37
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf2b3a
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf2b3d ata.c:948
+ jmp near 02d6fh ; e9 2c 02 ; 0xf2b40
+ test byte [bp+004h], 001h ; f6 46 04 01 ; 0xf2b43 ata.c:952
+ jne short 02b3dh ; 75 f4 ; 0xf2b47
+ mov al, ah ; 88 e0 ; 0xf2b49 ata.c:957
+ xor ah, ah ; 30 e4 ; 0xf2b4b
+ imul ax, ax, strict byte 00006h ; 6b c0 06 ; 0xf2b4d
+ les bx, [bp-010h] ; c4 5e f0 ; 0xf2b50
+ add bx, ax ; 01 c3 ; 0xf2b53
+ mov ax, word [es:bx+00206h] ; 26 8b 87 06 02 ; 0xf2b55
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf2b5a
+ mov ax, word [es:bx+00208h] ; 26 8b 87 08 02 ; 0xf2b5d ata.c:958
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf2b62
+ xor ax, ax ; 31 c0 ; 0xf2b65 ata.c:960
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf2b67
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf2b6a
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf2b6d ata.c:962
+ cmp AL, strict byte 00ch ; 3c 0c ; 0xf2b70
+ jnc short 02b7ah ; 73 06 ; 0xf2b72
+ mov byte [bp-006h], 00ch ; c6 46 fa 0c ; 0xf2b74 ata.c:963
+ jmp short 02b80h ; eb 06 ; 0xf2b78
+ jbe short 02b80h ; 76 04 ; 0xf2b7a ata.c:964
+ mov byte [bp-006h], 010h ; c6 46 fa 10 ; 0xf2b7c ata.c:965
+ shr byte [bp-006h], 1 ; d0 6e fa ; 0xf2b80 ata.c:966
+ les bx, [bp-010h] ; c4 5e f0 ; 0xf2b83 ata.c:970
+ mov word [es:bx+018h], strict word 00000h ; 26 c7 47 18 00 00 ; 0xf2b86
+ mov word [es:bx+01ah], strict word 00000h ; 26 c7 47 1a 00 00 ; 0xf2b8c ata.c:971
+ mov word [es:bx+01ch], strict word 00000h ; 26 c7 47 1c 00 00 ; 0xf2b92
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2b98 ata.c:973
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2b9b
+ in AL, DX ; ec ; 0xf2b9e
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2b9f
+ test AL, strict byte 080h ; a8 80 ; 0xf2ba1 ata.c:974
+ je short 02babh ; 74 06 ; 0xf2ba3
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf2ba5 ata.c:975
+ jmp near 02d6fh ; e9 c4 01 ; 0xf2ba8
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2bab ata.c:977
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2bae
+ mov AL, strict byte 00ah ; b0 0a ; 0xf2bb1
+ out DX, AL ; ee ; 0xf2bb3
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2bb4 ata.c:981
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf2bb7
+ mov AL, strict byte 0f0h ; b0 f0 ; 0xf2bba
+ out DX, AL ; ee ; 0xf2bbc
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2bbd ata.c:982
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf2bc0
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf2bc3
+ out DX, AL ; ee ; 0xf2bc5
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf2bc6 ata.c:983
+ je short 02bd1h ; 74 05 ; 0xf2bca
+ mov ax, 000b0h ; b8 b0 00 ; 0xf2bcc
+ jmp short 02bd4h ; eb 03 ; 0xf2bcf
+ mov ax, 000a0h ; b8 a0 00 ; 0xf2bd1
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2bd4
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2bd7
+ out DX, AL ; ee ; 0xf2bda
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2bdb ata.c:984
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2bde
+ mov AL, strict byte 0a0h ; b0 a0 ; 0xf2be1
+ out DX, AL ; ee ; 0xf2be3
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2be4 ata.c:988
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2be7
+ in AL, DX ; ec ; 0xf2bea
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2beb
+ mov bl, al ; 88 c3 ; 0xf2bed
+ test AL, strict byte 080h ; a8 80 ; 0xf2bef ata.c:989
+ jne short 02be4h ; 75 f1 ; 0xf2bf1
+ test AL, strict byte 001h ; a8 01 ; 0xf2bf3 ata.c:992
+ je short 02c06h ; 74 0f ; 0xf2bf5
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2bf7 ata.c:995
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2bfa
+ mov AL, strict byte 008h ; b0 08 ; 0xf2bfd
+ out DX, AL ; ee ; 0xf2bff
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf2c00 ata.c:996
+ jmp near 02d6fh ; e9 69 01 ; 0xf2c03
+ test bl, 008h ; f6 c3 08 ; 0xf2c06 ata.c:997
+ jne short 02c1ah ; 75 0f ; 0xf2c09
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2c0b ata.c:1000
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2c0e
+ mov AL, strict byte 008h ; b0 08 ; 0xf2c11
+ out DX, AL ; ee ; 0xf2c13
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf2c14 ata.c:1001
+ jmp near 02d6fh ; e9 55 01 ; 0xf2c17
+ sti ; fb ; 0xf2c1a ata.c:1004
+ mov ax, si ; 89 f0 ; 0xf2c1b ata.c:1008
+ shr ax, 004h ; c1 e8 04 ; 0xf2c1d
+ add ax, cx ; 01 c8 ; 0xf2c20
+ and si, strict byte 0000fh ; 83 e6 0f ; 0xf2c22
+ mov cl, byte [bp-006h] ; 8a 4e fa ; 0xf2c25 ata.c:1013
+ xor ch, ch ; 30 ed ; 0xf2c28
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2c2a
+ mov es, ax ; 8e c0 ; 0xf2c2d
+ db 0f3h, 026h, 06fh
+ ; rep es outsw ; f3 26 6f ; 0xf2c2f
+ cmp byte [bp+00ah], 000h ; 80 7e 0a 00 ; 0xf2c32 ata.c:1015
+ jne short 02c43h ; 75 0b ; 0xf2c36
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2c38 ata.c:1016
+ in AL, DX ; ec ; 0xf2c3b
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2c3c
+ mov bl, al ; 88 c3 ; 0xf2c3e
+ jmp near 02d50h ; e9 0d 01 ; 0xf2c40 ata.c:1018
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2c43 ata.c:1022
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2c46
+ in AL, DX ; ec ; 0xf2c49
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2c4a
+ mov bl, al ; 88 c3 ; 0xf2c4c
+ test AL, strict byte 080h ; a8 80 ; 0xf2c4e ata.c:1023
+ jne short 02c43h ; 75 f1 ; 0xf2c50
+ test AL, strict byte 088h ; a8 88 ; 0xf2c52 ata.c:1028
+ je short 02cb6h ; 74 60 ; 0xf2c54
+ test AL, strict byte 001h ; a8 01 ; 0xf2c56 ata.c:1031
+ je short 02c65h ; 74 0b ; 0xf2c58
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2c5a ata.c:1034
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2c5d
+ mov AL, strict byte 008h ; b0 08 ; 0xf2c60
+ out DX, AL ; ee ; 0xf2c62
+ jmp short 02c00h ; eb 9b ; 0xf2c63
+ mov al, bl ; 88 d8 ; 0xf2c65 ata.c:1039
+ and AL, strict byte 0c9h ; 24 c9 ; 0xf2c67
+ cmp AL, strict byte 048h ; 3c 48 ; 0xf2c69
+ je short 02c78h ; 74 0b ; 0xf2c6b
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2c6d ata.c:1043
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2c70
+ mov AL, strict byte 008h ; b0 08 ; 0xf2c73
+ out DX, AL ; ee ; 0xf2c75
+ jmp short 02c14h ; eb 9c ; 0xf2c76
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf2c78 ata.c:1049
+ shr ax, 004h ; c1 e8 04 ; 0xf2c7b
+ add ax, word [bp+00eh] ; 03 46 0e ; 0xf2c7e
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf2c81
+ and dx, strict byte 0000fh ; 83 e2 0f ; 0xf2c84
+ mov word [bp+00ch], dx ; 89 56 0c ; 0xf2c87
+ mov word [bp+00eh], ax ; 89 46 0e ; 0xf2c8a
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2c8d ata.c:1054
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf2c90
+ in AL, DX ; ec ; 0xf2c93
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2c94
+ mov bx, ax ; 89 c3 ; 0xf2c96
+ sal bx, 008h ; c1 e3 08 ; 0xf2c98
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2c9b
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf2c9e
+ in AL, DX ; ec ; 0xf2ca1
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2ca2
+ add bx, ax ; 01 c3 ; 0xf2ca4
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf2ca6 ata.c:1057
+ cmp bx, ax ; 39 c3 ; 0xf2ca9
+ jnc short 02cb9h ; 73 0c ; 0xf2cab
+ mov cx, bx ; 89 d9 ; 0xf2cad ata.c:1058
+ sub word [bp+004h], bx ; 29 5e 04 ; 0xf2caf ata.c:1059
+ xor bx, bx ; 31 db ; 0xf2cb2 ata.c:1060
+ jmp short 02cc2h ; eb 0c ; 0xf2cb4 ata.c:1062
+ jmp near 02d50h ; e9 97 00 ; 0xf2cb6
+ mov cx, ax ; 89 c1 ; 0xf2cb9 ata.c:1063
+ mov word [bp+004h], strict word 00000h ; c7 46 04 00 00 ; 0xf2cbb ata.c:1064
+ sub bx, ax ; 29 c3 ; 0xf2cc0 ata.c:1065
+ xor ax, ax ; 31 c0 ; 0xf2cc2 ata.c:1068
+ cmp word [bp+008h], strict byte 00000h ; 83 7e 08 00 ; 0xf2cc4
+ jne short 02ce0h ; 75 16 ; 0xf2cc8
+ cmp bx, word [bp+006h] ; 3b 5e 06 ; 0xf2cca
+ jbe short 02ce0h ; 76 11 ; 0xf2ccd
+ sub bx, word [bp+006h] ; 2b 5e 06 ; 0xf2ccf ata.c:1069
+ mov word [bp-016h], bx ; 89 5e ea ; 0xf2cd2
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf2cd5 ata.c:1070
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf2cd8 ata.c:1071
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf2cdb
+ jmp short 02ce9h ; eb 09 ; 0xf2cde ata.c:1073
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf2ce0 ata.c:1074
+ sub word [bp+006h], bx ; 29 5e 06 ; 0xf2ce3 ata.c:1075
+ sbb word [bp+008h], ax ; 19 46 08 ; 0xf2ce6
+ mov si, bx ; 89 de ; 0xf2ce9 ata.c:1079
+ test cl, 003h ; f6 c1 03 ; 0xf2ceb ata.c:1086
+ test bl, 003h ; f6 c3 03 ; 0xf2cee ata.c:1088
+ test byte [bp-016h], 003h ; f6 46 ea 03 ; 0xf2cf1 ata.c:1090
+ test bl, 001h ; f6 c3 01 ; 0xf2cf5 ata.c:1094
+ je short 02d0ah ; 74 10 ; 0xf2cf8
+ inc bx ; 43 ; 0xf2cfa ata.c:1095
+ cmp word [bp-016h], strict byte 00000h ; 83 7e ea 00 ; 0xf2cfb ata.c:1096
+ jbe short 02d0ah ; 76 09 ; 0xf2cff
+ test byte [bp-016h], 001h ; f6 46 ea 01 ; 0xf2d01
+ je short 02d0ah ; 74 03 ; 0xf2d05
+ dec word [bp-016h] ; ff 4e ea ; 0xf2d07 ata.c:1097
+ shr bx, 1 ; d1 eb ; 0xf2d0a ata.c:1109
+ shr cx, 1 ; d1 e9 ; 0xf2d0c ata.c:1110
+ shr word [bp-016h], 1 ; d1 6e ea ; 0xf2d0e ata.c:1111
+ test cx, cx ; 85 c9 ; 0xf2d11 ata.c:1124
+ je short 02d1bh ; 74 06 ; 0xf2d13
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2d15 ata.c:1125
+ in ax, DX ; ed ; 0xf2d18
+ loop 02d18h ; e2 fd ; 0xf2d19
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2d1b ata.c:1126
+ mov cx, bx ; 89 d9 ; 0xf2d1e
+ les di, [bp+00ch] ; c4 7e 0c ; 0xf2d20
+ rep insw ; f3 6d ; 0xf2d23
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf2d25 ata.c:1127
+ test ax, ax ; 85 c0 ; 0xf2d28
+ je short 02d31h ; 74 05 ; 0xf2d2a
+ mov cx, ax ; 89 c1 ; 0xf2d2c ata.c:1128
+ in ax, DX ; ed ; 0xf2d2e
+ loop 02d2eh ; e2 fd ; 0xf2d2f
+ add word [bp+00ch], si ; 01 76 0c ; 0xf2d31 ata.c:1133
+ xor ax, ax ; 31 c0 ; 0xf2d34 ata.c:1136
+ add word [bp-014h], si ; 01 76 ec ; 0xf2d36
+ adc word [bp-012h], ax ; 11 46 ee ; 0xf2d39
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf2d3c ata.c:1137
+ les bx, [bp-010h] ; c4 5e f0 ; 0xf2d3f
+ mov word [es:bx+01ah], ax ; 26 89 47 1a ; 0xf2d42
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf2d46
+ mov word [es:bx+01ch], ax ; 26 89 47 1c ; 0xf2d49
+ jmp near 02c43h ; e9 f3 fe ; 0xf2d4d ata.c:1138
+ mov al, bl ; 88 d8 ; 0xf2d50 ata.c:1142
+ and AL, strict byte 0e9h ; 24 e9 ; 0xf2d52
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf2d54
+ je short 02d64h ; 74 0c ; 0xf2d56
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2d58 ata.c:1146
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2d5b
+ mov AL, strict byte 008h ; b0 08 ; 0xf2d5e
+ out DX, AL ; ee ; 0xf2d60
+ jmp near 02c14h ; e9 b0 fe ; 0xf2d61
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2d64 ata.c:1151
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2d67
+ mov AL, strict byte 008h ; b0 08 ; 0xf2d6a
+ out DX, AL ; ee ; 0xf2d6c
+ xor ax, ax ; 31 c0 ; 0xf2d6d ata.c:1152
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf2d6f ata.c:1153
+ pop di ; 5f ; 0xf2d72
+ pop si ; 5e ; 0xf2d73
+ pop bp ; 5d ; 0xf2d74
+ retn 0000ch ; c2 0c 00 ; 0xf2d75
+ ; disGetNextSymbol 0xf2d78 LB 0x7150 -> off=0x0 cb=000000000000007f uValue=00000000000f1778 'ata_soft_reset'
+ata_soft_reset: ; 0xf2d78 LB 0x7f
+ push bp ; 55 ; 0xf2d78 ata.c:1161
+ mov bp, sp ; 89 e5 ; 0xf2d79
+ push bx ; 53 ; 0xf2d7b
+ push cx ; 51 ; 0xf2d7c
+ push dx ; 52 ; 0xf2d7d
+ push ax ; 50 ; 0xf2d7e
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf2d7f ata.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf2d82
+ mov es, dx ; 8e c2 ; 0xf2d85
+ mov es, [es:bx] ; 26 8e 07 ; 0xf2d87
+ mov dx, ax ; 89 c2 ; 0xf2d8a ata.c:1170
+ shr dx, 1 ; d1 ea ; 0xf2d8c
+ and AL, strict byte 001h ; 24 01 ; 0xf2d8e ata.c:1171
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf2d90
+ mov al, dl ; 88 d0 ; 0xf2d93 ata.c:1173
+ xor ah, ah ; 30 e4 ; 0xf2d95
+ imul bx, ax, strict byte 00006h ; 6b d8 06 ; 0xf2d97
+ add bx, 00122h ; 81 c3 22 01 ; 0xf2d9a
+ mov cx, word [es:bx+00206h] ; 26 8b 8f 06 02 ; 0xf2d9e
+ mov bx, word [es:bx+00208h] ; 26 8b 9f 08 02 ; 0xf2da3 ata.c:1174
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf2da8 ata.c:1177
+ mov AL, strict byte 00ah ; b0 0a ; 0xf2dab
+ out DX, AL ; ee ; 0xf2dad
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf2dae ata.c:1178
+ je short 02db9h ; 74 05 ; 0xf2db2
+ mov ax, 000b0h ; b8 b0 00 ; 0xf2db4
+ jmp short 02dbch ; eb 03 ; 0xf2db7
+ mov ax, 000a0h ; b8 a0 00 ; 0xf2db9
+ mov dx, cx ; 89 ca ; 0xf2dbc
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2dbe
+ out DX, AL ; ee ; 0xf2dc1
+ mov dx, cx ; 89 ca ; 0xf2dc2 ata.c:1179
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2dc4
+ mov AL, strict byte 008h ; b0 08 ; 0xf2dc7
+ out DX, AL ; ee ; 0xf2dc9
+ mov dx, cx ; 89 ca ; 0xf2dca ata.c:1183
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2dcc
+ in AL, DX ; ec ; 0xf2dcf
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2dd0
+ test AL, strict byte 080h ; a8 80 ; 0xf2dd2 ata.c:1184
+ jne short 02dcah ; 75 f4 ; 0xf2dd4
+ and AL, strict byte 0e9h ; 24 e9 ; 0xf2dd6 ata.c:1188
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf2dd8
+ je short 02de7h ; 74 0b ; 0xf2dda
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf2ddc ata.c:1192
+ mov AL, strict byte 008h ; b0 08 ; 0xf2ddf
+ out DX, AL ; ee ; 0xf2de1
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf2de2 ata.c:1193
+ jmp short 02defh ; eb 08 ; 0xf2de5
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf2de7 ata.c:1197
+ mov AL, strict byte 008h ; b0 08 ; 0xf2dea
+ out DX, AL ; ee ; 0xf2dec
+ xor ax, ax ; 31 c0 ; 0xf2ded ata.c:1198
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf2def ata.c:1199
+ pop dx ; 5a ; 0xf2df2
+ pop cx ; 59 ; 0xf2df3
+ pop bx ; 5b ; 0xf2df4
+ pop bp ; 5d ; 0xf2df5
+ retn ; c3 ; 0xf2df6
+ ; disGetNextSymbol 0xf2df7 LB 0x70d1 -> off=0x0 cb=000000000000002b uValue=00000000000f17f7 'set_diskette_current_cyl'
+set_diskette_current_cyl: ; 0xf2df7 LB 0x2b
+ push bp ; 55 ; 0xf2df7 floppy.c:71
+ mov bp, sp ; 89 e5 ; 0xf2df8
+ push bx ; 53 ; 0xf2dfa
+ mov dh, al ; 88 c6 ; 0xf2dfb
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf2dfd floppy.c:73
+ jbe short 02e0ch ; 76 0b ; 0xf2dff
+ push 00250h ; 68 50 02 ; 0xf2e01 floppy.c:74
+ push strict byte 00007h ; 6a 07 ; 0xf2e04
+ call 018ffh ; e8 f6 ea ; 0xf2e06
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf2e09
+ mov bl, dh ; 88 f3 ; 0xf2e0c floppy.c:75
+ xor bh, bh ; 30 ff ; 0xf2e0e
+ add bx, 00094h ; 81 c3 94 00 ; 0xf2e10
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2e14 floppy.c:43
+ mov es, ax ; 8e c0 ; 0xf2e17
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf2e19
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf2e1c floppy.c:76
+ pop bx ; 5b ; 0xf2e1f
+ pop bp ; 5d ; 0xf2e20
+ retn ; c3 ; 0xf2e21
+ ; disGetNextSymbol 0xf2e22 LB 0x70a6 -> off=0x0 cb=0000000000000023 uValue=00000000000f1822 'floppy_wait_for_interrupt'
+floppy_wait_for_interrupt: ; 0xf2e22 LB 0x23
+ push bp ; 55 ; 0xf2e22 floppy.c:96
+ mov bp, sp ; 89 e5 ; 0xf2e23
+ push bx ; 53 ; 0xf2e25
+ cli ; fa ; 0xf2e26 floppy.c:98
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf2e27 floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2e2a
+ mov es, ax ; 8e c0 ; 0xf2e2d
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2e2f
+ test AL, strict byte 080h ; a8 80 ; 0xf2e32 floppy.c:102
+ je short 02e3ah ; 74 04 ; 0xf2e34
+ and AL, strict byte 080h ; 24 80 ; 0xf2e36 floppy.c:103
+ jmp short 02e3fh ; eb 05 ; 0xf2e38
+ sti ; fb ; 0xf2e3a floppy.c:104
+ hlt ; f4 ; 0xf2e3b
+ cli ; fa ; 0xf2e3c
+ jmp short 02e27h ; eb e8 ; 0xf2e3d floppy.c:105
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf2e3f floppy.c:106
+ pop bx ; 5b ; 0xf2e42
+ pop bp ; 5d ; 0xf2e43
+ retn ; c3 ; 0xf2e44
+ ; disGetNextSymbol 0xf2e45 LB 0x7083 -> off=0x0 cb=0000000000000038 uValue=00000000000f1845 'floppy_wait_for_interrupt_or_timeout'
+floppy_wait_for_interrupt_or_timeout: ; 0xf2e45 LB 0x38
+ push bp ; 55 ; 0xf2e45 floppy.c:116
+ mov bp, sp ; 89 e5 ; 0xf2e46
+ push bx ; 53 ; 0xf2e48
+ cli ; fa ; 0xf2e49 floppy.c:118
+ mov bx, strict word 00040h ; bb 40 00 ; 0xf2e4a floppy.c:38
+ mov es, bx ; 8e c3 ; 0xf2e4d
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2e4f
+ test al, al ; 84 c0 ; 0xf2e52 floppy.c:122
+ jne short 02e59h ; 75 03 ; 0xf2e54
+ sti ; fb ; 0xf2e56 floppy.c:123
+ jmp short 02e77h ; eb 1e ; 0xf2e57 floppy.c:124
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf2e59 floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2e5c
+ mov es, ax ; 8e c0 ; 0xf2e5f
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2e61
+ test AL, strict byte 080h ; a8 80 ; 0xf2e64 floppy.c:128
+ je short 02e72h ; 74 0a ; 0xf2e66
+ mov ah, al ; 88 c4 ; 0xf2e68 floppy.c:129
+ and ah, 07fh ; 80 e4 7f ; 0xf2e6a
+ mov byte [es:bx], ah ; 26 88 27 ; 0xf2e6d floppy.c:43
+ jmp short 02e77h ; eb 05 ; 0xf2e70 floppy.c:130
+ sti ; fb ; 0xf2e72 floppy.c:132
+ hlt ; f4 ; 0xf2e73
+ cli ; fa ; 0xf2e74
+ jmp short 02e4ah ; eb d3 ; 0xf2e75 floppy.c:133
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf2e77 floppy.c:134
+ pop bx ; 5b ; 0xf2e7a
+ pop bp ; 5d ; 0xf2e7b
+ retn ; c3 ; 0xf2e7c
+ ; disGetNextSymbol 0xf2e7d LB 0x704b -> off=0x0 cb=000000000000003f uValue=00000000000f187d 'floppy_reset_controller'
+floppy_reset_controller: ; 0xf2e7d LB 0x3f
+ push bp ; 55 ; 0xf2e7d floppy.c:138
+ mov bp, sp ; 89 e5 ; 0xf2e7e
+ push bx ; 53 ; 0xf2e80
+ push cx ; 51 ; 0xf2e81
+ push dx ; 52 ; 0xf2e82
+ mov cx, ax ; 89 c1 ; 0xf2e83
+ mov dx, 003f2h ; ba f2 03 ; 0xf2e85 floppy.c:143
+ in AL, DX ; ec ; 0xf2e88
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2e89
+ mov bx, ax ; 89 c3 ; 0xf2e8b
+ and AL, strict byte 0fbh ; 24 fb ; 0xf2e8d floppy.c:144
+ out DX, AL ; ee ; 0xf2e8f
+ mov al, bl ; 88 d8 ; 0xf2e90 floppy.c:145
+ or AL, strict byte 004h ; 0c 04 ; 0xf2e92
+ out DX, AL ; ee ; 0xf2e94
+ mov dx, 003f4h ; ba f4 03 ; 0xf2e95 floppy.c:149
+ in AL, DX ; ec ; 0xf2e98
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2e99
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf2e9b floppy.c:150
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf2e9d
+ jne short 02e95h ; 75 f4 ; 0xf2e9f
+ mov bx, cx ; 89 cb ; 0xf2ea1 floppy.c:153
+ add bx, 00090h ; 81 c3 90 00 ; 0xf2ea3
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2ea7 floppy.c:38
+ mov es, ax ; 8e c0 ; 0xf2eaa
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2eac
+ and AL, strict byte 0efh ; 24 ef ; 0xf2eaf floppy.c:154
+ mov byte [es:bx], al ; 26 88 07 ; 0xf2eb1 floppy.c:43
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf2eb4 floppy.c:157
+ pop dx ; 5a ; 0xf2eb7
+ pop cx ; 59 ; 0xf2eb8
+ pop bx ; 5b ; 0xf2eb9
+ pop bp ; 5d ; 0xf2eba
+ retn ; c3 ; 0xf2ebb
+ ; disGetNextSymbol 0xf2ebc LB 0x700c -> off=0x0 cb=0000000000000074 uValue=00000000000f18bc 'floppy_prepare_controller'
+floppy_prepare_controller: ; 0xf2ebc LB 0x74
+ push bp ; 55 ; 0xf2ebc floppy.c:159
+ mov bp, sp ; 89 e5 ; 0xf2ebd
+ push bx ; 53 ; 0xf2ebf
+ push cx ; 51 ; 0xf2ec0
+ push dx ; 52 ; 0xf2ec1
+ push ax ; 50 ; 0xf2ec2
+ mov cx, ax ; 89 c1 ; 0xf2ec3
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf2ec5 floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2ec8
+ mov es, ax ; 8e c0 ; 0xf2ecb
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2ecd
+ and AL, strict byte 07fh ; 24 7f ; 0xf2ed0 floppy.c:165
+ mov byte [es:bx], al ; 26 88 07 ; 0xf2ed2 floppy.c:43
+ mov dx, 003f2h ; ba f2 03 ; 0xf2ed5 floppy.c:169
+ in AL, DX ; ec ; 0xf2ed8
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2ed9
+ and AL, strict byte 004h ; 24 04 ; 0xf2edb
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf2edd
+ test cx, cx ; 85 c9 ; 0xf2ee0 floppy.c:170
+ je short 02ee8h ; 74 04 ; 0xf2ee2
+ mov AL, strict byte 020h ; b0 20 ; 0xf2ee4 floppy.c:171
+ jmp short 02eeah ; eb 02 ; 0xf2ee6 floppy.c:172
+ mov AL, strict byte 010h ; b0 10 ; 0xf2ee8 floppy.c:173
+ or AL, strict byte 00ch ; 0c 0c ; 0xf2eea floppy.c:174
+ or al, cl ; 08 c8 ; 0xf2eec floppy.c:175
+ mov dx, 003f2h ; ba f2 03 ; 0xf2eee floppy.c:176
+ out DX, AL ; ee ; 0xf2ef1
+ mov bx, strict word 00040h ; bb 40 00 ; 0xf2ef2 floppy.c:43
+ mov es, bx ; 8e c3 ; 0xf2ef5
+ mov byte [es:bx], 025h ; 26 c6 07 25 ; 0xf2ef7
+ mov bx, 0008bh ; bb 8b 00 ; 0xf2efb floppy.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2efe
+ shr al, 006h ; c0 e8 06 ; 0xf2f01 floppy.c:183
+ mov dx, 003f7h ; ba f7 03 ; 0xf2f04 floppy.c:184
+ out DX, AL ; ee ; 0xf2f07
+ mov dx, 003f4h ; ba f4 03 ; 0xf2f08 floppy.c:188
+ in AL, DX ; ec ; 0xf2f0b
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2f0c
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf2f0e floppy.c:189
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf2f10
+ jne short 02f08h ; 75 f4 ; 0xf2f12
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf2f14 floppy.c:191
+ jne short 02f28h ; 75 0e ; 0xf2f18
+ call 02e22h ; e8 05 ff ; 0xf2f1a floppy.c:202
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf2f1d floppy.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf2f20
+ mov es, dx ; 8e c2 ; 0xf2f23
+ mov byte [es:bx], al ; 26 88 07 ; 0xf2f25
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf2f28 floppy.c:206
+ pop dx ; 5a ; 0xf2f2b
+ pop cx ; 59 ; 0xf2f2c
+ pop bx ; 5b ; 0xf2f2d
+ pop bp ; 5d ; 0xf2f2e
+ retn ; c3 ; 0xf2f2f
+ ; disGetNextSymbol 0xf2f30 LB 0x6f98 -> off=0x0 cb=0000000000000049 uValue=00000000000f1930 'floppy_media_known'
+floppy_media_known: ; 0xf2f30 LB 0x49
+ push bx ; 53 ; 0xf2f30 floppy.c:208
+ push dx ; 52 ; 0xf2f31
+ push bp ; 55 ; 0xf2f32
+ mov bp, sp ; 89 e5 ; 0xf2f33
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf2f35 floppy.c:38
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf2f38
+ mov es, dx ; 8e c2 ; 0xf2f3b
+ mov bh, byte [es:bx] ; 26 8a 3f ; 0xf2f3d
+ mov bl, bh ; 88 fb ; 0xf2f40 floppy.c:39
+ test ax, ax ; 85 c0 ; 0xf2f42 floppy.c:214
+ je short 02f48h ; 74 02 ; 0xf2f44
+ shr bl, 1 ; d0 eb ; 0xf2f46 floppy.c:215
+ and bl, 001h ; 80 e3 01 ; 0xf2f48 floppy.c:216
+ jne short 02f51h ; 75 04 ; 0xf2f4b floppy.c:217
+ xor bh, bh ; 30 ff ; 0xf2f4d floppy.c:218
+ jmp short 02f73h ; eb 22 ; 0xf2f4f
+ mov bx, 00090h ; bb 90 00 ; 0xf2f51 floppy.c:220
+ test ax, ax ; 85 c0 ; 0xf2f54 floppy.c:221
+ je short 02f5bh ; 74 03 ; 0xf2f56
+ mov bx, 00091h ; bb 91 00 ; 0xf2f58 floppy.c:222
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2f5b floppy.c:38
+ mov es, ax ; 8e c0 ; 0xf2f5e
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2f60
+ xor ah, ah ; 30 e4 ; 0xf2f63 floppy.c:225
+ sar ax, 004h ; c1 f8 04 ; 0xf2f65
+ and AL, strict byte 001h ; 24 01 ; 0xf2f68
+ jne short 02f70h ; 75 04 ; 0xf2f6a floppy.c:226
+ xor bx, bx ; 31 db ; 0xf2f6c floppy.c:227
+ jmp short 02f73h ; eb 03 ; 0xf2f6e
+ mov bx, strict word 00001h ; bb 01 00 ; 0xf2f70 floppy.c:230
+ mov ax, bx ; 89 d8 ; 0xf2f73 floppy.c:231
+ pop bp ; 5d ; 0xf2f75
+ pop dx ; 5a ; 0xf2f76
+ pop bx ; 5b ; 0xf2f77
+ retn ; c3 ; 0xf2f78
+ ; disGetNextSymbol 0xf2f79 LB 0x6f4f -> off=0x0 cb=0000000000000052 uValue=00000000000f1979 'floppy_read_id'
+floppy_read_id: ; 0xf2f79 LB 0x52
+ push bp ; 55 ; 0xf2f79 floppy.c:233
+ mov bp, sp ; 89 e5 ; 0xf2f7a
+ push bx ; 53 ; 0xf2f7c
+ push dx ; 52 ; 0xf2f7d
+ push si ; 56 ; 0xf2f7e
+ mov bx, ax ; 89 c3 ; 0xf2f7f
+ call 02ebch ; e8 38 ff ; 0xf2f81 floppy.c:240
+ mov AL, strict byte 04ah ; b0 4a ; 0xf2f84 floppy.c:243
+ mov dx, 003f5h ; ba f5 03 ; 0xf2f86
+ out DX, AL ; ee ; 0xf2f89
+ mov al, bl ; 88 d8 ; 0xf2f8a floppy.c:244
+ out DX, AL ; ee ; 0xf2f8c
+ call 02e22h ; e8 92 fe ; 0xf2f8d floppy.c:259
+ xor bx, bx ; 31 db ; 0xf2f90 floppy.c:263
+ jmp short 02f99h ; eb 05 ; 0xf2f92
+ cmp bx, strict byte 00007h ; 83 fb 07 ; 0xf2f94
+ jnl short 02fadh ; 7d 14 ; 0xf2f97
+ mov dx, 003f5h ; ba f5 03 ; 0xf2f99 floppy.c:264
+ in AL, DX ; ec ; 0xf2f9c
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2f9d
+ lea si, [bx+042h] ; 8d 77 42 ; 0xf2f9f
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf2fa2 floppy.c:43
+ mov es, dx ; 8e c2 ; 0xf2fa5
+ mov byte [es:si], al ; 26 88 04 ; 0xf2fa7
+ inc bx ; 43 ; 0xf2faa floppy.c:264
+ jmp short 02f94h ; eb e7 ; 0xf2fab
+ mov bx, strict word 00042h ; bb 42 00 ; 0xf2fad floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2fb0
+ mov es, ax ; 8e c0 ; 0xf2fb3
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2fb5
+ test AL, strict byte 0c0h ; a8 c0 ; 0xf2fb8 floppy.c:39
+ je short 02fc0h ; 74 04 ; 0xf2fba
+ xor ax, ax ; 31 c0 ; 0xf2fbc floppy.c:267
+ jmp short 02fc3h ; eb 03 ; 0xf2fbe
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf2fc0 floppy.c:269
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf2fc3 floppy.c:270
+ pop si ; 5e ; 0xf2fc6
+ pop dx ; 5a ; 0xf2fc7
+ pop bx ; 5b ; 0xf2fc8
+ pop bp ; 5d ; 0xf2fc9
+ retn ; c3 ; 0xf2fca
+ ; disGetNextSymbol 0xf2fcb LB 0x6efd -> off=0x0 cb=0000000000000041 uValue=00000000000f19cb 'floppy_drive_recal'
+floppy_drive_recal: ; 0xf2fcb LB 0x41
+ push bp ; 55 ; 0xf2fcb floppy.c:272
+ mov bp, sp ; 89 e5 ; 0xf2fcc
+ push bx ; 53 ; 0xf2fce
+ push dx ; 52 ; 0xf2fcf
+ push si ; 56 ; 0xf2fd0
+ mov bx, ax ; 89 c3 ; 0xf2fd1
+ call 02ebch ; e8 e6 fe ; 0xf2fd3 floppy.c:277
+ mov AL, strict byte 007h ; b0 07 ; 0xf2fd6 floppy.c:280
+ mov dx, 003f5h ; ba f5 03 ; 0xf2fd8
+ out DX, AL ; ee ; 0xf2fdb
+ mov al, bl ; 88 d8 ; 0xf2fdc floppy.c:281
+ out DX, AL ; ee ; 0xf2fde
+ call 02e22h ; e8 40 fe ; 0xf2fdf floppy.c:300
+ test bx, bx ; 85 db ; 0xf2fe2 floppy.c:304
+ je short 02fedh ; 74 07 ; 0xf2fe4
+ or AL, strict byte 002h ; 0c 02 ; 0xf2fe6 floppy.c:305
+ mov bx, 00095h ; bb 95 00 ; 0xf2fe8 floppy.c:306
+ jmp short 02ff2h ; eb 05 ; 0xf2feb floppy.c:307
+ or AL, strict byte 001h ; 0c 01 ; 0xf2fed floppy.c:308
+ mov bx, 00094h ; bb 94 00 ; 0xf2fef floppy.c:309
+ mov si, strict word 0003eh ; be 3e 00 ; 0xf2ff2 floppy.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf2ff5
+ mov es, dx ; 8e c2 ; 0xf2ff8
+ mov byte [es:si], al ; 26 88 04 ; 0xf2ffa
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf2ffd floppy.c:43
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf3001 floppy.c:315
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf3004
+ pop si ; 5e ; 0xf3007
+ pop dx ; 5a ; 0xf3008
+ pop bx ; 5b ; 0xf3009
+ pop bp ; 5d ; 0xf300a
+ retn ; c3 ; 0xf300b
+ ; disGetNextSymbol 0xf300c LB 0x6ebc -> off=0x0 cb=00000000000000e6 uValue=00000000000f1a0c 'floppy_media_sense'
+floppy_media_sense: ; 0xf300c LB 0xe6
+ push bp ; 55 ; 0xf300c floppy.c:318
+ mov bp, sp ; 89 e5 ; 0xf300d
+ push bx ; 53 ; 0xf300f
+ push cx ; 51 ; 0xf3010
+ push dx ; 52 ; 0xf3011
+ push si ; 56 ; 0xf3012
+ push di ; 57 ; 0xf3013
+ mov cx, ax ; 89 c1 ; 0xf3014
+ call 02fcbh ; e8 b2 ff ; 0xf3016 floppy.c:324
+ test ax, ax ; 85 c0 ; 0xf3019
+ jne short 03022h ; 75 05 ; 0xf301b
+ xor dx, dx ; 31 d2 ; 0xf301d floppy.c:325
+ jmp near 030e6h ; e9 c4 00 ; 0xf301f
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf3022 floppy.c:360
+ call 01650h ; e8 28 e6 ; 0xf3025
+ test cx, cx ; 85 c9 ; 0xf3028 floppy.c:361
+ jne short 03033h ; 75 07 ; 0xf302a
+ mov dl, al ; 88 c2 ; 0xf302c floppy.c:362
+ shr dl, 004h ; c0 ea 04 ; 0xf302e
+ jmp short 03038h ; eb 05 ; 0xf3031 floppy.c:363
+ mov dl, al ; 88 c2 ; 0xf3033 floppy.c:364
+ and dl, 00fh ; 80 e2 0f ; 0xf3035
+ cmp dl, 001h ; 80 fa 01 ; 0xf3038 floppy.c:365
+ jne short 03046h ; 75 09 ; 0xf303b
+ xor dl, dl ; 30 d2 ; 0xf303d floppy.c:367
+ mov DH, strict byte 015h ; b6 15 ; 0xf303f floppy.c:368
+ mov bx, strict word 00001h ; bb 01 00 ; 0xf3041 floppy.c:369
+ jmp short 03084h ; eb 3e ; 0xf3044 floppy.c:371
+ cmp dl, 002h ; 80 fa 02 ; 0xf3046
+ jne short 03051h ; 75 06 ; 0xf3049
+ xor dl, dl ; 30 d2 ; 0xf304b floppy.c:373
+ mov DH, strict byte 035h ; b6 35 ; 0xf304d floppy.c:374
+ jmp short 03041h ; eb f0 ; 0xf304f
+ cmp dl, 003h ; 80 fa 03 ; 0xf3051 floppy.c:377
+ jne short 0305ch ; 75 06 ; 0xf3054
+ xor dl, dl ; 30 d2 ; 0xf3056 floppy.c:379
+ mov DH, strict byte 017h ; b6 17 ; 0xf3058 floppy.c:380
+ jmp short 03041h ; eb e5 ; 0xf305a
+ cmp dl, 004h ; 80 fa 04 ; 0xf305c floppy.c:383
+ jne short 03067h ; 75 06 ; 0xf305f
+ xor dl, dl ; 30 d2 ; 0xf3061 floppy.c:385
+ mov DH, strict byte 017h ; b6 17 ; 0xf3063 floppy.c:386
+ jmp short 03041h ; eb da ; 0xf3065
+ cmp dl, 005h ; 80 fa 05 ; 0xf3067 floppy.c:389
+ jne short 03072h ; 75 06 ; 0xf306a
+ mov DL, strict byte 0cch ; b2 cc ; 0xf306c floppy.c:391
+ mov DH, strict byte 0d7h ; b6 d7 ; 0xf306e floppy.c:392
+ jmp short 03041h ; eb cf ; 0xf3070
+ cmp dl, 00eh ; 80 fa 0e ; 0xf3072 floppy.c:396
+ je short 0307ch ; 74 05 ; 0xf3075
+ cmp dl, 00fh ; 80 fa 0f ; 0xf3077
+ jne short 0307eh ; 75 02 ; 0xf307a
+ jmp short 0306ch ; eb ee ; 0xf307c
+ xor dl, dl ; 30 d2 ; 0xf307e floppy.c:404
+ xor dh, dh ; 30 f6 ; 0xf3080 floppy.c:405
+ xor bx, bx ; 31 db ; 0xf3082 floppy.c:406
+ mov si, 0008bh ; be 8b 00 ; 0xf3084 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3087
+ mov es, ax ; 8e c0 ; 0xf308a
+ mov byte [es:si], dl ; 26 88 14 ; 0xf308c
+ mov ax, cx ; 89 c8 ; 0xf308f floppy.c:410
+ call 02f79h ; e8 e5 fe ; 0xf3091
+ test ax, ax ; 85 c0 ; 0xf3094
+ jne short 030cah ; 75 32 ; 0xf3096
+ mov al, dl ; 88 d0 ; 0xf3098 floppy.c:411
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf309a
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf309c
+ je short 030cah ; 74 2a ; 0xf309e
+ mov al, dl ; 88 d0 ; 0xf30a0 floppy.c:415
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf30a2
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xf30a4
+ je short 030b7h ; 74 0f ; 0xf30a6
+ mov ah, dl ; 88 d4 ; 0xf30a8
+ and ah, 03fh ; 80 e4 3f ; 0xf30aa
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf30ad
+ je short 030c3h ; 74 12 ; 0xf30af
+ test al, al ; 84 c0 ; 0xf30b1
+ je short 030bch ; 74 07 ; 0xf30b3
+ jmp short 03084h ; eb cd ; 0xf30b5
+ and dl, 03fh ; 80 e2 3f ; 0xf30b7 floppy.c:417
+ jmp short 03084h ; eb c8 ; 0xf30ba floppy.c:418
+ mov dl, ah ; 88 e2 ; 0xf30bc floppy.c:420
+ or dl, 040h ; 80 ca 40 ; 0xf30be
+ jmp short 03084h ; eb c1 ; 0xf30c1 floppy.c:421
+ mov dl, ah ; 88 e2 ; 0xf30c3 floppy.c:423
+ or dl, 080h ; 80 ca 80 ; 0xf30c5
+ jmp short 03084h ; eb ba ; 0xf30c8 floppy.c:427
+ test cx, cx ; 85 c9 ; 0xf30ca floppy.c:429
+ jne short 030d3h ; 75 05 ; 0xf30cc
+ mov si, 00090h ; be 90 00 ; 0xf30ce floppy.c:430
+ jmp short 030d6h ; eb 03 ; 0xf30d1 floppy.c:431
+ mov si, 00091h ; be 91 00 ; 0xf30d3 floppy.c:432
+ mov di, 0008bh ; bf 8b 00 ; 0xf30d6 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf30d9
+ mov es, ax ; 8e c0 ; 0xf30dc
+ mov byte [es:di], dl ; 26 88 15 ; 0xf30de
+ mov byte [es:si], dh ; 26 88 34 ; 0xf30e1 floppy.c:43
+ mov dx, bx ; 89 da ; 0xf30e4 floppy.c:436
+ mov ax, dx ; 89 d0 ; 0xf30e6 floppy.c:437
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf30e8
+ pop di ; 5f ; 0xf30eb
+ pop si ; 5e ; 0xf30ec
+ pop dx ; 5a ; 0xf30ed
+ pop cx ; 59 ; 0xf30ee
+ pop bx ; 5b ; 0xf30ef
+ pop bp ; 5d ; 0xf30f0
+ retn ; c3 ; 0xf30f1
+ ; disGetNextSymbol 0xf30f2 LB 0x6dd6 -> off=0x0 cb=0000000000000028 uValue=00000000000f1af2 'floppy_drive_exists'
+floppy_drive_exists: ; 0xf30f2 LB 0x28
+ push bp ; 55 ; 0xf30f2 floppy.c:440
+ mov bp, sp ; 89 e5 ; 0xf30f3
+ push dx ; 52 ; 0xf30f5
+ mov dx, ax ; 89 c2 ; 0xf30f6
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf30f8 floppy.c:446
+ call 01650h ; e8 52 e5 ; 0xf30fb
+ test dx, dx ; 85 d2 ; 0xf30fe floppy.c:447
+ jne short 03107h ; 75 05 ; 0xf3100
+ shr al, 004h ; c0 e8 04 ; 0xf3102 floppy.c:448
+ jmp short 03109h ; eb 02 ; 0xf3105 floppy.c:449
+ and AL, strict byte 00fh ; 24 0f ; 0xf3107 floppy.c:450
+ test al, al ; 84 c0 ; 0xf3109 floppy.c:451
+ je short 03112h ; 74 05 ; 0xf310b
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf310d
+ jmp short 03114h ; eb 02 ; 0xf3110
+ xor ah, ah ; 30 e4 ; 0xf3112
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf3114 floppy.c:452
+ pop dx ; 5a ; 0xf3117
+ pop bp ; 5d ; 0xf3118
+ retn ; c3 ; 0xf3119
+ ; disGetNextSymbol 0xf311a LB 0x6dae -> off=0x23 cb=00000000000009ce uValue=00000000000f1b3d 'int13_diskette_function'
+ db 018h, 017h, 016h, 015h, 008h, 005h, 004h, 003h, 002h, 001h, 000h, 0e8h, 03ah, 07bh, 031h, 0fch
+ db 031h, 01dh, 032h, 01dh, 032h, 01dh, 032h, 0d1h, 035h, 09bh, 037h, 089h, 038h, 0cbh, 038h, 0ffh
+ db 038h, 073h, 039h
+int13_diskette_function: ; 0xf313d LB 0x9ce
+ push bp ; 55 ; 0xf313d floppy.c:467
+ mov bp, sp ; 89 e5 ; 0xf313e
+ sub sp, strict byte 0000ch ; 83 ec 0c ; 0xf3140
+ or byte [bp+01dh], 002h ; 80 4e 1d 02 ; 0xf3143 floppy.c:478
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3147 floppy.c:480
+ shr ax, 008h ; c1 e8 08 ; 0xf314a
+ cmp ax, strict word 00018h ; 3d 18 00 ; 0xf314d
+ jnbe short 031aeh ; 77 5c ; 0xf3150
+ push CS ; 0e ; 0xf3152
+ pop ES ; 07 ; 0xf3153
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf3154
+ mov di, 0311ah ; bf 1a 31 ; 0xf3157
+ repne scasb ; f2 ae ; 0xf315a
+ sal cx, 1 ; d1 e1 ; 0xf315c
+ mov di, cx ; 89 cf ; 0xf315e
+ mov di, word [cs:di+03125h] ; 2e 8b bd 25 31 ; 0xf3160
+ mov dx, word [bp+016h] ; 8b 56 16 ; 0xf3165
+ xor dh, dh ; 30 f6 ; 0xf3168
+ mov ah, byte [bp+00eh] ; 8a 66 0e ; 0xf316a
+ mov cx, word [bp+01ch] ; 8b 4e 1c ; 0xf316d
+ or cl, 001h ; 80 c9 01 ; 0xf3170
+ mov si, dx ; 89 d6 ; 0xf3173
+ or si, 00100h ; 81 ce 00 01 ; 0xf3175
+ jmp di ; ff e7 ; 0xf3179
+ mov bl, byte [bp+00eh] ; 8a 5e 0e ; 0xf317b floppy.c:483
+ cmp bl, 001h ; 80 fb 01 ; 0xf317e floppy.c:484
+ jbe short 0319dh ; 76 1a ; 0xf3181
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3183 floppy.c:485
+ xor ah, ah ; 30 e4 ; 0xf3186
+ or ah, 001h ; 80 cc 01 ; 0xf3188
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf318b
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf318e floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3191
+ mov es, ax ; 8e c0 ; 0xf3194
+ mov byte [es:bx], 001h ; 26 c6 07 01 ; 0xf3196
+ jmp near 039d5h ; e9 38 08 ; 0xf319a
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf319d floppy.c:491
+ call 01650h ; e8 ad e4 ; 0xf31a0
+ test bl, bl ; 84 db ; 0xf31a3 floppy.c:492
+ jne short 031b1h ; 75 0a ; 0xf31a5
+ mov dl, al ; 88 c2 ; 0xf31a7 floppy.c:493
+ shr dl, 004h ; c0 ea 04 ; 0xf31a9
+ jmp short 031b6h ; eb 08 ; 0xf31ac floppy.c:494
+ jmp near 03ae8h ; e9 37 09 ; 0xf31ae
+ mov dl, al ; 88 c2 ; 0xf31b1 floppy.c:495
+ and dl, 00fh ; 80 e2 0f ; 0xf31b3
+ test dl, dl ; 84 d2 ; 0xf31b6 floppy.c:496
+ jne short 031d4h ; 75 1a ; 0xf31b8
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf31ba floppy.c:497
+ xor ah, ah ; 30 e4 ; 0xf31bd
+ or ah, 080h ; 80 cc 80 ; 0xf31bf
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf31c2
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf31c5 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf31c8
+ mov es, ax ; 8e c0 ; 0xf31cb
+ mov byte [es:bx], 080h ; 26 c6 07 80 ; 0xf31cd
+ jmp near 039d5h ; e9 01 08 ; 0xf31d1
+ mov si, strict word 0003eh ; be 3e 00 ; 0xf31d4 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf31d7
+ mov es, ax ; 8e c0 ; 0xf31da
+ mov byte [es:si], 000h ; 26 c6 04 00 ; 0xf31dc
+ xor al, al ; 30 c0 ; 0xf31e0 floppy.c:506
+ mov byte [bp+017h], al ; 88 46 17 ; 0xf31e2
+ mov si, strict word 00041h ; be 41 00 ; 0xf31e5 floppy.c:43
+ mov byte [es:si], al ; 26 88 04 ; 0xf31e8
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf31eb floppy.c:508
+ mov al, bl ; 88 d8 ; 0xf31ef floppy.c:509
+ xor ah, ah ; 30 e4 ; 0xf31f1
+ xor dx, dx ; 31 d2 ; 0xf31f3
+ call 02df7h ; e8 ff fb ; 0xf31f5
+ mov sp, bp ; 89 ec ; 0xf31f8 floppy.c:510
+ pop bp ; 5d ; 0xf31fa
+ retn ; c3 ; 0xf31fb
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf31fc floppy.c:513
+ mov bx, 00441h ; bb 41 04 ; 0xf3200 floppy.c:38
+ xor ax, ax ; 31 c0 ; 0xf3203
+ mov es, ax ; 8e c0 ; 0xf3205
+ mov bl, byte [es:bx] ; 26 8a 1f ; 0xf3207
+ mov al, bl ; 88 d8 ; 0xf320a floppy.c:515
+ xor ah, ah ; 30 e4 ; 0xf320c
+ sal ax, 008h ; c1 e0 08 ; 0xf320e
+ or dx, ax ; 09 c2 ; 0xf3211
+ mov word [bp+016h], dx ; 89 56 16 ; 0xf3213
+ test bl, bl ; 84 db ; 0xf3216 floppy.c:516
+ je short 031f8h ; 74 de ; 0xf3218
+ jmp near 039d5h ; e9 b8 07 ; 0xf321a
+ mov bh, byte [bp+016h] ; 8a 7e 16 ; 0xf321d floppy.c:524
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf3220 floppy.c:525
+ shr ax, 008h ; c1 e8 08 ; 0xf3223
+ mov byte [bp-004h], al ; 88 46 fc ; 0xf3226
+ mov al, byte [bp+014h] ; 8a 46 14 ; 0xf3229 floppy.c:526
+ mov byte [bp-002h], al ; 88 46 fe ; 0xf322c
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf322f floppy.c:527
+ shr ax, 008h ; c1 e8 08 ; 0xf3232
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf3235
+ mov bl, byte [bp+00eh] ; 8a 5e 0e ; 0xf3238 floppy.c:528
+ cmp bl, 001h ; 80 fb 01 ; 0xf323b floppy.c:530
+ jnbe short 0324dh ; 77 0d ; 0xf323e
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf3240
+ jnbe short 0324dh ; 77 09 ; 0xf3242
+ test bh, bh ; 84 ff ; 0xf3244
+ je short 0324dh ; 74 05 ; 0xf3246
+ cmp bh, 048h ; 80 ff 48 ; 0xf3248
+ jbe short 03280h ; 76 33 ; 0xf324b
+ mov bx, 00da0h ; bb a0 0d ; 0xf324d floppy.c:532
+ mov cx, ds ; 8c d9 ; 0xf3250
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3252
+ call 018bch ; e8 64 e6 ; 0xf3255
+ push 00275h ; 68 75 02 ; 0xf3258
+ push 0028dh ; 68 8d 02 ; 0xf325b
+ push strict byte 00004h ; 6a 04 ; 0xf325e
+ call 018ffh ; e8 9c e6 ; 0xf3260
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf3263
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3266 floppy.c:533
+ xor ah, ah ; 30 e4 ; 0xf3269
+ or ah, 001h ; 80 cc 01 ; 0xf326b
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf326e
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3271 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3274
+ mov es, ax ; 8e c0 ; 0xf3277
+ mov byte [es:bx], 001h ; 26 c6 07 01 ; 0xf3279
+ jmp near 0332ah ; e9 aa 00 ; 0xf327d
+ mov al, bl ; 88 d8 ; 0xf3280 floppy.c:535
+ xor ah, ah ; 30 e4 ; 0xf3282
+ call 030f2h ; e8 6b fe ; 0xf3284
+ test ax, ax ; 85 c0 ; 0xf3287
+ jne short 032a5h ; 75 1a ; 0xf3289
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf328b floppy.c:543
+ xor ah, ah ; 30 e4 ; 0xf328e
+ or ah, 080h ; 80 cc 80 ; 0xf3290
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3293
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3296 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3299
+ mov es, ax ; 8e c0 ; 0xf329c
+ mov byte [es:bx], 080h ; 26 c6 07 80 ; 0xf329e
+ jmp near 0332ah ; e9 85 00 ; 0xf32a2
+ mov cl, bl ; 88 d9 ; 0xf32a5 floppy.c:551
+ xor ch, ch ; 30 ed ; 0xf32a7
+ mov ax, cx ; 89 c8 ; 0xf32a9
+ call 02f30h ; e8 82 fc ; 0xf32ab
+ test ax, ax ; 85 c0 ; 0xf32ae
+ jne short 032d8h ; 75 26 ; 0xf32b0
+ mov ax, cx ; 89 c8 ; 0xf32b2 floppy.c:552
+ call 0300ch ; e8 55 fd ; 0xf32b4
+ test ax, ax ; 85 c0 ; 0xf32b7
+ jne short 032d8h ; 75 1d ; 0xf32b9
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf32bb floppy.c:554
+ xor ah, ah ; 30 e4 ; 0xf32be
+ or ah, 00ch ; 80 cc 0c ; 0xf32c0
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf32c3
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf32c6 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf32c9
+ mov es, ax ; 8e c0 ; 0xf32cc
+ mov byte [es:bx], 00ch ; 26 c6 07 0c ; 0xf32ce
+ mov byte [bp+016h], ch ; 88 6e 16 ; 0xf32d2
+ jmp near 039d5h ; e9 fd 06 ; 0xf32d5
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf32d8 floppy.c:556
+ shr ax, 008h ; c1 e8 08 ; 0xf32db
+ cmp ax, strict word 00002h ; 3d 02 00 ; 0xf32de
+ jne short 03331h ; 75 4e ; 0xf32e1
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf32e3 floppy.c:573
+ shr dx, 00ch ; c1 ea 0c ; 0xf32e6
+ mov ah, dl ; 88 d4 ; 0xf32e9
+ mov cx, word [bp+006h] ; 8b 4e 06 ; 0xf32eb floppy.c:574
+ sal cx, 004h ; c1 e1 04 ; 0xf32ee
+ mov si, word [bp+010h] ; 8b 76 10 ; 0xf32f1 floppy.c:575
+ add si, cx ; 01 ce ; 0xf32f4
+ mov word [bp-008h], si ; 89 76 f8 ; 0xf32f6
+ cmp cx, si ; 39 f1 ; 0xf32f9 floppy.c:577
+ jbe short 032ffh ; 76 02 ; 0xf32fb
+ db 0feh, 0c4h
+ ; inc ah ; fe c4 ; 0xf32fd floppy.c:579
+ mov dl, bh ; 88 fa ; 0xf32ff floppy.c:581
+ xor dh, dh ; 30 f6 ; 0xf3301
+ mov cx, dx ; 89 d1 ; 0xf3303
+ sal cx, 009h ; c1 e1 09 ; 0xf3305
+ dec cx ; 49 ; 0xf3308
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf3309 floppy.c:584
+ add dx, cx ; 01 ca ; 0xf330c
+ cmp dx, word [bp-008h] ; 3b 56 f8 ; 0xf330e floppy.c:585
+ jnc short 03334h ; 73 21 ; 0xf3311
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3313 floppy.c:586
+ xor ah, ah ; 30 e4 ; 0xf3316
+ or ah, 009h ; 80 cc 09 ; 0xf3318
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf331b
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf331e floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3321
+ mov es, ax ; 8e c0 ; 0xf3324
+ mov byte [es:bx], 009h ; 26 c6 07 09 ; 0xf3326
+ mov byte [bp+016h], 000h ; c6 46 16 00 ; 0xf332a
+ jmp near 039d5h ; e9 a4 06 ; 0xf332e
+ jmp near 03481h ; e9 4d 01 ; 0xf3331
+ mov AL, strict byte 006h ; b0 06 ; 0xf3334 floppy.c:594
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf3336
+ out DX, AL ; ee ; 0xf3339
+ xor al, al ; 30 c0 ; 0xf333a floppy.c:597
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf333c
+ out DX, AL ; ee ; 0xf333f
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf3340 floppy.c:598
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf3343
+ out DX, AL ; ee ; 0xf3346
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf3347 floppy.c:599
+ shr dx, 008h ; c1 ea 08 ; 0xf334a
+ mov al, dl ; 88 d0 ; 0xf334d
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf334f
+ out DX, AL ; ee ; 0xf3352
+ xor al, al ; 30 c0 ; 0xf3353 floppy.c:601
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3355
+ out DX, AL ; ee ; 0xf3358
+ mov al, cl ; 88 c8 ; 0xf3359 floppy.c:602
+ mov dx, strict word 00005h ; ba 05 00 ; 0xf335b
+ out DX, AL ; ee ; 0xf335e
+ shr cx, 008h ; c1 e9 08 ; 0xf335f floppy.c:603
+ mov al, cl ; 88 c8 ; 0xf3362
+ out DX, AL ; ee ; 0xf3364
+ mov AL, strict byte 046h ; b0 46 ; 0xf3365 floppy.c:611
+ mov dx, strict word 0000bh ; ba 0b 00 ; 0xf3367
+ out DX, AL ; ee ; 0xf336a
+ mov al, ah ; 88 e0 ; 0xf336b floppy.c:615
+ mov dx, 00081h ; ba 81 00 ; 0xf336d
+ out DX, AL ; ee ; 0xf3370
+ mov AL, strict byte 002h ; b0 02 ; 0xf3371 floppy.c:618
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf3373
+ out DX, AL ; ee ; 0xf3376
+ mov cl, bl ; 88 d9 ; 0xf3377 floppy.c:623
+ xor ch, ch ; 30 ed ; 0xf3379
+ mov ax, cx ; 89 c8 ; 0xf337b
+ call 02ebch ; e8 3c fb ; 0xf337d
+ mov AL, strict byte 0e6h ; b0 e6 ; 0xf3380 floppy.c:626
+ mov dx, 003f5h ; ba f5 03 ; 0xf3382
+ out DX, AL ; ee ; 0xf3385
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf3386 floppy.c:627
+ xor ah, ah ; 30 e4 ; 0xf3389
+ mov dx, ax ; 89 c2 ; 0xf338b
+ sal dx, 002h ; c1 e2 02 ; 0xf338d
+ mov al, bl ; 88 d8 ; 0xf3390
+ or ax, dx ; 09 d0 ; 0xf3392
+ mov dx, 003f5h ; ba f5 03 ; 0xf3394
+ out DX, AL ; ee ; 0xf3397
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf3398 floppy.c:628
+ out DX, AL ; ee ; 0xf339b
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf339c floppy.c:629
+ out DX, AL ; ee ; 0xf339f
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf33a0 floppy.c:630
+ out DX, AL ; ee ; 0xf33a3
+ mov AL, strict byte 002h ; b0 02 ; 0xf33a4 floppy.c:631
+ out DX, AL ; ee ; 0xf33a6
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf33a7 floppy.c:632
+ xor ah, ah ; 30 e4 ; 0xf33aa
+ mov dl, bh ; 88 fa ; 0xf33ac
+ xor dh, dh ; 30 f6 ; 0xf33ae
+ add ax, dx ; 01 d0 ; 0xf33b0
+ dec ax ; 48 ; 0xf33b2
+ mov dx, 003f5h ; ba f5 03 ; 0xf33b3
+ out DX, AL ; ee ; 0xf33b6
+ xor al, al ; 30 c0 ; 0xf33b7 floppy.c:633
+ out DX, AL ; ee ; 0xf33b9
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf33ba floppy.c:634
+ out DX, AL ; ee ; 0xf33bc
+ call 02e45h ; e8 85 fa ; 0xf33bd floppy.c:666
+ test al, al ; 84 c0 ; 0xf33c0 floppy.c:667
+ jne short 033e3h ; 75 1f ; 0xf33c2
+ mov ax, cx ; 89 c8 ; 0xf33c4 floppy.c:669
+ call 02e7dh ; e8 b4 fa ; 0xf33c6
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf33c9 floppy.c:670
+ xor ah, ah ; 30 e4 ; 0xf33cc
+ or ah, 080h ; 80 cc 80 ; 0xf33ce
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf33d1
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf33d4 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf33d7
+ mov es, ax ; 8e c0 ; 0xf33da
+ mov byte [es:bx], 080h ; 26 c6 07 80 ; 0xf33dc
+ jmp near 032d2h ; e9 ef fe ; 0xf33e0
+ mov dx, 003f4h ; ba f4 03 ; 0xf33e3 floppy.c:679
+ in AL, DX ; ec ; 0xf33e6
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf33e7
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf33e9 floppy.c:680
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xf33eb
+ je short 033fdh ; 74 0e ; 0xf33ed
+ push 00275h ; 68 75 02 ; 0xf33ef floppy.c:681
+ push 002a8h ; 68 a8 02 ; 0xf33f2
+ push strict byte 00007h ; 6a 07 ; 0xf33f5
+ call 018ffh ; e8 05 e5 ; 0xf33f7
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf33fa
+ xor cx, cx ; 31 c9 ; 0xf33fd floppy.c:684
+ jmp short 03406h ; eb 05 ; 0xf33ff
+ cmp cx, strict byte 00007h ; 83 f9 07 ; 0xf3401
+ jnl short 0341ch ; 7d 16 ; 0xf3404
+ mov dx, 003f5h ; ba f5 03 ; 0xf3406 floppy.c:685
+ in AL, DX ; ec ; 0xf3409
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf340a
+ mov si, cx ; 89 ce ; 0xf340c
+ add si, strict byte 00042h ; 83 c6 42 ; 0xf340e
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3411 floppy.c:43
+ mov es, dx ; 8e c2 ; 0xf3414
+ mov byte [es:si], al ; 26 88 04 ; 0xf3416
+ inc cx ; 41 ; 0xf3419 floppy.c:685
+ jmp short 03401h ; eb e5 ; 0xf341a
+ mov si, strict word 00042h ; be 42 00 ; 0xf341c floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf341f
+ mov es, ax ; 8e c0 ; 0xf3422
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf3424
+ test AL, strict byte 0c0h ; a8 c0 ; 0xf3427 floppy.c:39
+ je short 0344ch ; 74 21 ; 0xf3429
+ mov al, bl ; 88 d8 ; 0xf342b floppy.c:689
+ xor ah, ah ; 30 e4 ; 0xf342d
+ call 02e7dh ; e8 4b fa ; 0xf342f
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3432 floppy.c:690
+ xor ah, ah ; 30 e4 ; 0xf3435
+ or ah, 020h ; 80 cc 20 ; 0xf3437
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf343a
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf343d floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3440
+ mov es, ax ; 8e c0 ; 0xf3443
+ mov byte [es:bx], 020h ; 26 c6 07 20 ; 0xf3445
+ jmp near 0332ah ; e9 de fe ; 0xf3449
+ mov al, bh ; 88 f8 ; 0xf344c floppy.c:698
+ xor ah, ah ; 30 e4 ; 0xf344e
+ sal ax, 009h ; c1 e0 09 ; 0xf3450
+ cwd ; 99 ; 0xf3453
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf3454
+ sar ax, 1 ; d1 f8 ; 0xf3456
+ mov si, word [bp+010h] ; 8b 76 10 ; 0xf3458
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf345b
+ mov di, si ; 89 f7 ; 0xf345e
+ mov cx, ax ; 89 c1 ; 0xf3460
+ mov es, dx ; 8e c2 ; 0xf3462
+ push DS ; 1e ; 0xf3464
+ mov ds, dx ; 8e da ; 0xf3465
+ rep movsw ; f3 a5 ; 0xf3467
+ pop DS ; 1f ; 0xf3469
+ mov dl, byte [bp-004h] ; 8a 56 fc ; 0xf346a floppy.c:702
+ xor dh, dh ; 30 f6 ; 0xf346d
+ mov al, bl ; 88 d8 ; 0xf346f
+ xor ah, ah ; 30 e4 ; 0xf3471
+ call 02df7h ; e8 81 f9 ; 0xf3473
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf3476 floppy.c:704
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf347a floppy.c:705
+ jmp near 031f8h ; e9 77 fd ; 0xf347e floppy.c:706
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3481 floppy.c:707
+ shr ax, 008h ; c1 e8 08 ; 0xf3484
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf3487
+ je short 0348fh ; 74 03 ; 0xf348a
+ jmp near 035bah ; e9 2b 01 ; 0xf348c
+ mov cx, word [bp+006h] ; 8b 4e 06 ; 0xf348f floppy.c:718
+ shr cx, 00ch ; c1 e9 0c ; 0xf3492
+ mov ah, cl ; 88 cc ; 0xf3495
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf3497 floppy.c:719
+ sal dx, 004h ; c1 e2 04 ; 0xf349a
+ mov si, word [bp+010h] ; 8b 76 10 ; 0xf349d floppy.c:720
+ add si, dx ; 01 d6 ; 0xf34a0
+ mov word [bp-008h], si ; 89 76 f8 ; 0xf34a2
+ cmp dx, si ; 39 f2 ; 0xf34a5 floppy.c:722
+ jbe short 034abh ; 76 02 ; 0xf34a7
+ db 0feh, 0c4h
+ ; inc ah ; fe c4 ; 0xf34a9 floppy.c:724
+ mov dl, bh ; 88 fa ; 0xf34ab floppy.c:726
+ xor dh, dh ; 30 f6 ; 0xf34ad
+ mov cx, dx ; 89 d1 ; 0xf34af
+ sal cx, 009h ; c1 e1 09 ; 0xf34b1
+ dec cx ; 49 ; 0xf34b4
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf34b5 floppy.c:729
+ add dx, cx ; 01 ca ; 0xf34b8
+ cmp dx, word [bp-008h] ; 3b 56 f8 ; 0xf34ba floppy.c:730
+ jnc short 034c2h ; 73 03 ; 0xf34bd
+ jmp near 03313h ; e9 51 fe ; 0xf34bf
+ mov AL, strict byte 006h ; b0 06 ; 0xf34c2 floppy.c:739
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf34c4
+ out DX, AL ; ee ; 0xf34c7
+ xor al, al ; 30 c0 ; 0xf34c8 floppy.c:741
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf34ca
+ out DX, AL ; ee ; 0xf34cd
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf34ce floppy.c:742
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf34d1
+ out DX, AL ; ee ; 0xf34d4
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf34d5 floppy.c:743
+ shr dx, 008h ; c1 ea 08 ; 0xf34d8
+ mov al, dl ; 88 d0 ; 0xf34db
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf34dd
+ out DX, AL ; ee ; 0xf34e0
+ xor al, al ; 30 c0 ; 0xf34e1 floppy.c:744
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf34e3
+ out DX, AL ; ee ; 0xf34e6
+ mov al, cl ; 88 c8 ; 0xf34e7 floppy.c:745
+ mov dx, strict word 00005h ; ba 05 00 ; 0xf34e9
+ out DX, AL ; ee ; 0xf34ec
+ shr cx, 008h ; c1 e9 08 ; 0xf34ed floppy.c:746
+ mov al, cl ; 88 c8 ; 0xf34f0
+ out DX, AL ; ee ; 0xf34f2
+ mov AL, strict byte 04ah ; b0 4a ; 0xf34f3 floppy.c:753
+ mov dx, strict word 0000bh ; ba 0b 00 ; 0xf34f5
+ out DX, AL ; ee ; 0xf34f8
+ mov al, ah ; 88 e0 ; 0xf34f9 floppy.c:756
+ mov dx, 00081h ; ba 81 00 ; 0xf34fb
+ out DX, AL ; ee ; 0xf34fe
+ mov AL, strict byte 002h ; b0 02 ; 0xf34ff floppy.c:759
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf3501
+ out DX, AL ; ee ; 0xf3504
+ mov cl, bl ; 88 d9 ; 0xf3505 floppy.c:764
+ xor ch, ch ; 30 ed ; 0xf3507
+ mov ax, cx ; 89 c8 ; 0xf3509
+ call 02ebch ; e8 ae f9 ; 0xf350b
+ mov AL, strict byte 0c5h ; b0 c5 ; 0xf350e floppy.c:767
+ mov dx, 003f5h ; ba f5 03 ; 0xf3510
+ out DX, AL ; ee ; 0xf3513
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf3514 floppy.c:768
+ xor ah, ah ; 30 e4 ; 0xf3517
+ mov dx, ax ; 89 c2 ; 0xf3519
+ sal dx, 002h ; c1 e2 02 ; 0xf351b
+ mov al, bl ; 88 d8 ; 0xf351e
+ or ax, dx ; 09 d0 ; 0xf3520
+ mov dx, 003f5h ; ba f5 03 ; 0xf3522
+ out DX, AL ; ee ; 0xf3525
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf3526 floppy.c:769
+ out DX, AL ; ee ; 0xf3529
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf352a floppy.c:770
+ out DX, AL ; ee ; 0xf352d
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf352e floppy.c:771
+ out DX, AL ; ee ; 0xf3531
+ mov AL, strict byte 002h ; b0 02 ; 0xf3532 floppy.c:772
+ out DX, AL ; ee ; 0xf3534
+ mov dl, byte [bp-002h] ; 8a 56 fe ; 0xf3535 floppy.c:773
+ xor dh, dh ; 30 f6 ; 0xf3538
+ mov al, bh ; 88 f8 ; 0xf353a
+ xor ah, ah ; 30 e4 ; 0xf353c
+ add ax, dx ; 01 d0 ; 0xf353e
+ dec ax ; 48 ; 0xf3540
+ mov dx, 003f5h ; ba f5 03 ; 0xf3541
+ out DX, AL ; ee ; 0xf3544
+ xor al, al ; 30 c0 ; 0xf3545 floppy.c:774
+ out DX, AL ; ee ; 0xf3547
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf3548 floppy.c:775
+ out DX, AL ; ee ; 0xf354a
+ call 02e45h ; e8 f7 f8 ; 0xf354b floppy.c:804
+ test al, al ; 84 c0 ; 0xf354e floppy.c:805
+ jne short 03555h ; 75 03 ; 0xf3550
+ jmp near 033c4h ; e9 6f fe ; 0xf3552
+ mov dx, 003f4h ; ba f4 03 ; 0xf3555 floppy.c:816
+ in AL, DX ; ec ; 0xf3558
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf3559
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf355b floppy.c:817
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xf355d
+ je short 0356fh ; 74 0e ; 0xf355f
+ push 00275h ; 68 75 02 ; 0xf3561 floppy.c:818
+ push 002a8h ; 68 a8 02 ; 0xf3564
+ push strict byte 00007h ; 6a 07 ; 0xf3567
+ call 018ffh ; e8 93 e3 ; 0xf3569
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf356c
+ xor cx, cx ; 31 c9 ; 0xf356f floppy.c:821
+ jmp short 03578h ; eb 05 ; 0xf3571
+ cmp cx, strict byte 00007h ; 83 f9 07 ; 0xf3573
+ jnl short 0358eh ; 7d 16 ; 0xf3576
+ mov dx, 003f5h ; ba f5 03 ; 0xf3578 floppy.c:822
+ in AL, DX ; ec ; 0xf357b
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf357c
+ mov si, cx ; 89 ce ; 0xf357e
+ add si, strict byte 00042h ; 83 c6 42 ; 0xf3580
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3583 floppy.c:43
+ mov es, dx ; 8e c2 ; 0xf3586
+ mov byte [es:si], al ; 26 88 04 ; 0xf3588
+ inc cx ; 41 ; 0xf358b floppy.c:822
+ jmp short 03573h ; eb e5 ; 0xf358c
+ mov si, strict word 00042h ; be 42 00 ; 0xf358e floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3591
+ mov es, ax ; 8e c0 ; 0xf3594
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf3596
+ test AL, strict byte 0c0h ; a8 c0 ; 0xf3599 floppy.c:39
+ jne short 035a0h ; 75 03 ; 0xf359b
+ jmp near 0346ah ; e9 ca fe ; 0xf359d
+ mov bx, strict word 00043h ; bb 43 00 ; 0xf35a0 floppy.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf35a3
+ test AL, strict byte 002h ; a8 02 ; 0xf35a6 floppy.c:39
+ je short 035b2h ; 74 08 ; 0xf35a8
+ mov word [bp+016h], 00300h ; c7 46 16 00 03 ; 0xf35aa floppy.c:829
+ jmp near 039d5h ; e9 23 04 ; 0xf35af
+ mov word [bp+016h], 00100h ; c7 46 16 00 01 ; 0xf35b2 floppy.c:832
+ jmp near 039d5h ; e9 1b 04 ; 0xf35b7 floppy.c:833
+ mov dl, byte [bp-004h] ; 8a 56 fc ; 0xf35ba floppy.c:848
+ xor dh, dh ; 30 f6 ; 0xf35bd
+ mov al, bl ; 88 d8 ; 0xf35bf
+ xor ah, ah ; 30 e4 ; 0xf35c1
+ call 02df7h ; e8 31 f8 ; 0xf35c3
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf35c6 floppy.c:850
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf35ca floppy.c:851
+ jmp near 031f8h ; e9 27 fc ; 0xf35ce floppy.c:852
+ mov bh, byte [bp+016h] ; 8a 7e 16 ; 0xf35d1 floppy.c:859
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf35d4 floppy.c:860
+ shr ax, 008h ; c1 e8 08 ; 0xf35d7
+ mov byte [bp-004h], al ; 88 46 fc ; 0xf35da
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf35dd floppy.c:861
+ shr dx, 008h ; c1 ea 08 ; 0xf35e0
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf35e3
+ mov bl, byte [bp+00eh] ; 8a 5e 0e ; 0xf35e6 floppy.c:862
+ cmp bl, 001h ; 80 fb 01 ; 0xf35e9 floppy.c:864
+ jnbe short 03600h ; 77 12 ; 0xf35ec
+ cmp dl, 001h ; 80 fa 01 ; 0xf35ee
+ jnbe short 03600h ; 77 0d ; 0xf35f1
+ cmp AL, strict byte 04fh ; 3c 4f ; 0xf35f3
+ jnbe short 03600h ; 77 09 ; 0xf35f5
+ test bh, bh ; 84 ff ; 0xf35f7
+ je short 03600h ; 74 05 ; 0xf35f9
+ cmp bh, 012h ; 80 ff 12 ; 0xf35fb
+ jbe short 0361bh ; 76 1b ; 0xf35fe
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3600 floppy.c:866
+ xor ah, ah ; 30 e4 ; 0xf3603
+ or ah, 001h ; 80 cc 01 ; 0xf3605
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3608
+ mov si, strict word 00041h ; be 41 00 ; 0xf360b floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf360e
+ mov es, ax ; 8e c0 ; 0xf3611
+ mov byte [es:si], 001h ; 26 c6 04 01 ; 0xf3613
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf3617 floppy.c:868
+ mov al, bl ; 88 d8 ; 0xf361b floppy.c:872
+ xor ah, ah ; 30 e4 ; 0xf361d
+ call 030f2h ; e8 d0 fa ; 0xf361f
+ test ax, ax ; 85 c0 ; 0xf3622
+ jne short 03640h ; 75 1a ; 0xf3624
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3626 floppy.c:873
+ xor ah, ah ; 30 e4 ; 0xf3629
+ or ah, 080h ; 80 cc 80 ; 0xf362b
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf362e
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3631 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3634
+ mov es, ax ; 8e c0 ; 0xf3637
+ mov byte [es:bx], 080h ; 26 c6 07 80 ; 0xf3639
+ jmp near 039d5h ; e9 95 03 ; 0xf363d
+ mov cl, bl ; 88 d9 ; 0xf3640 floppy.c:880
+ xor ch, ch ; 30 ed ; 0xf3642
+ mov ax, cx ; 89 c8 ; 0xf3644
+ call 02f30h ; e8 e7 f8 ; 0xf3646
+ test ax, ax ; 85 c0 ; 0xf3649
+ jne short 03659h ; 75 0c ; 0xf364b
+ mov ax, cx ; 89 c8 ; 0xf364d floppy.c:881
+ call 0300ch ; e8 ba f9 ; 0xf364f
+ test ax, ax ; 85 c0 ; 0xf3652
+ jne short 03659h ; 75 03 ; 0xf3654
+ jmp near 032bbh ; e9 62 fc ; 0xf3656
+ mov cx, word [bp+006h] ; 8b 4e 06 ; 0xf3659 floppy.c:892
+ shr cx, 00ch ; c1 e9 0c ; 0xf365c
+ mov ah, cl ; 88 cc ; 0xf365f
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf3661 floppy.c:893
+ sal dx, 004h ; c1 e2 04 ; 0xf3664
+ mov si, word [bp+010h] ; 8b 76 10 ; 0xf3667 floppy.c:894
+ add si, dx ; 01 d6 ; 0xf366a
+ mov word [bp-008h], si ; 89 76 f8 ; 0xf366c
+ cmp dx, si ; 39 f2 ; 0xf366f floppy.c:896
+ jbe short 03675h ; 76 02 ; 0xf3671
+ db 0feh, 0c4h
+ ; inc ah ; fe c4 ; 0xf3673 floppy.c:898
+ mov dl, bh ; 88 fa ; 0xf3675 floppy.c:900
+ xor dh, dh ; 30 f6 ; 0xf3677
+ mov cx, dx ; 89 d1 ; 0xf3679
+ sal cx, 002h ; c1 e1 02 ; 0xf367b
+ dec cx ; 49 ; 0xf367e
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf367f floppy.c:903
+ add dx, cx ; 01 ca ; 0xf3682
+ cmp dx, word [bp-008h] ; 3b 56 f8 ; 0xf3684 floppy.c:904
+ jnc short 0368ch ; 73 03 ; 0xf3687
+ jmp near 03313h ; e9 87 fc ; 0xf3689
+ mov AL, strict byte 006h ; b0 06 ; 0xf368c floppy.c:912
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf368e
+ out DX, AL ; ee ; 0xf3691
+ xor al, al ; 30 c0 ; 0xf3692 floppy.c:913
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3694
+ out DX, AL ; ee ; 0xf3697
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf3698 floppy.c:914
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf369b
+ out DX, AL ; ee ; 0xf369e
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf369f floppy.c:915
+ shr dx, 008h ; c1 ea 08 ; 0xf36a2
+ mov al, dl ; 88 d0 ; 0xf36a5
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf36a7
+ out DX, AL ; ee ; 0xf36aa
+ xor al, al ; 30 c0 ; 0xf36ab floppy.c:916
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf36ad
+ out DX, AL ; ee ; 0xf36b0
+ mov al, cl ; 88 c8 ; 0xf36b1 floppy.c:917
+ mov dx, strict word 00005h ; ba 05 00 ; 0xf36b3
+ out DX, AL ; ee ; 0xf36b6
+ shr cx, 008h ; c1 e9 08 ; 0xf36b7 floppy.c:918
+ mov al, cl ; 88 c8 ; 0xf36ba
+ out DX, AL ; ee ; 0xf36bc
+ mov AL, strict byte 04ah ; b0 4a ; 0xf36bd floppy.c:921
+ mov dx, strict word 0000bh ; ba 0b 00 ; 0xf36bf
+ out DX, AL ; ee ; 0xf36c2
+ mov al, ah ; 88 e0 ; 0xf36c3 floppy.c:923
+ mov dx, 00081h ; ba 81 00 ; 0xf36c5
+ out DX, AL ; ee ; 0xf36c8
+ mov AL, strict byte 002h ; b0 02 ; 0xf36c9 floppy.c:924
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf36cb
+ out DX, AL ; ee ; 0xf36ce
+ mov cl, bl ; 88 d9 ; 0xf36cf floppy.c:927
+ xor ch, ch ; 30 ed ; 0xf36d1
+ mov ax, cx ; 89 c8 ; 0xf36d3
+ call 02ebch ; e8 e4 f7 ; 0xf36d5
+ mov AL, strict byte 00fh ; b0 0f ; 0xf36d8 floppy.c:930
+ mov dx, 003f5h ; ba f5 03 ; 0xf36da
+ out DX, AL ; ee ; 0xf36dd
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf36de floppy.c:931
+ xor ah, ah ; 30 e4 ; 0xf36e1
+ mov dx, ax ; 89 c2 ; 0xf36e3
+ sal dx, 002h ; c1 e2 02 ; 0xf36e5
+ mov al, bl ; 88 d8 ; 0xf36e8
+ or dx, ax ; 09 c2 ; 0xf36ea
+ mov word [bp-00ah], dx ; 89 56 f6 ; 0xf36ec
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf36ef
+ mov dx, 003f5h ; ba f5 03 ; 0xf36f2
+ out DX, AL ; ee ; 0xf36f5
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf36f6 floppy.c:932
+ out DX, AL ; ee ; 0xf36f9
+ mov AL, strict byte 04dh ; b0 4d ; 0xf36fa floppy.c:935
+ out DX, AL ; ee ; 0xf36fc
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf36fd floppy.c:936
+ out DX, AL ; ee ; 0xf3700
+ mov AL, strict byte 002h ; b0 02 ; 0xf3701 floppy.c:937
+ out DX, AL ; ee ; 0xf3703
+ mov al, bh ; 88 f8 ; 0xf3704 floppy.c:938
+ out DX, AL ; ee ; 0xf3706
+ xor al, bh ; 30 f8 ; 0xf3707 floppy.c:939
+ out DX, AL ; ee ; 0xf3709
+ mov AL, strict byte 0f6h ; b0 f6 ; 0xf370a floppy.c:940
+ out DX, AL ; ee ; 0xf370c
+ call 02e45h ; e8 35 f7 ; 0xf370d floppy.c:968
+ test al, al ; 84 c0 ; 0xf3710 floppy.c:969
+ jne short 0371ch ; 75 08 ; 0xf3712
+ mov ax, cx ; 89 c8 ; 0xf3714 floppy.c:970
+ call 02e7dh ; e8 64 f7 ; 0xf3716
+ jmp near 03626h ; e9 0a ff ; 0xf3719 floppy.c:68
+ mov dx, 003f4h ; ba f4 03 ; 0xf371c floppy.c:979
+ in AL, DX ; ec ; 0xf371f
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf3720
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf3722 floppy.c:980
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xf3724
+ je short 03736h ; 74 0e ; 0xf3726
+ push 00275h ; 68 75 02 ; 0xf3728 floppy.c:981
+ push 002a8h ; 68 a8 02 ; 0xf372b
+ push strict byte 00007h ; 6a 07 ; 0xf372e
+ call 018ffh ; e8 cc e1 ; 0xf3730
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf3733
+ xor cx, cx ; 31 c9 ; 0xf3736 floppy.c:984
+ jmp short 0373fh ; eb 05 ; 0xf3738
+ cmp cx, strict byte 00007h ; 83 f9 07 ; 0xf373a
+ jnl short 03755h ; 7d 16 ; 0xf373d
+ mov dx, 003f5h ; ba f5 03 ; 0xf373f floppy.c:985
+ in AL, DX ; ec ; 0xf3742
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf3743
+ mov si, cx ; 89 ce ; 0xf3745
+ add si, strict byte 00042h ; 83 c6 42 ; 0xf3747
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf374a floppy.c:43
+ mov es, dx ; 8e c2 ; 0xf374d
+ mov byte [es:si], al ; 26 88 04 ; 0xf374f
+ inc cx ; 41 ; 0xf3752 floppy.c:985
+ jmp short 0373ah ; eb e5 ; 0xf3753
+ mov si, strict word 00042h ; be 42 00 ; 0xf3755 floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3758
+ mov es, ax ; 8e c0 ; 0xf375b
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf375d
+ test AL, strict byte 0c0h ; a8 c0 ; 0xf3760 floppy.c:39
+ je short 0377fh ; 74 1b ; 0xf3762
+ mov si, strict word 00043h ; be 43 00 ; 0xf3764 floppy.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf3767
+ test AL, strict byte 002h ; a8 02 ; 0xf376a floppy.c:39
+ je short 03771h ; 74 03 ; 0xf376c
+ jmp near 035aah ; e9 39 fe ; 0xf376e
+ push 00275h ; 68 75 02 ; 0xf3771 floppy.c:996
+ push 002bch ; 68 bc 02 ; 0xf3774
+ push strict byte 00007h ; 6a 07 ; 0xf3777
+ call 018ffh ; e8 83 e1 ; 0xf3779
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf377c
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf377f floppy.c:1000
+ mov si, strict word 00041h ; be 41 00 ; 0xf3783 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3786
+ mov es, ax ; 8e c0 ; 0xf3789
+ mov byte [es:si], 000h ; 26 c6 04 00 ; 0xf378b
+ mov al, bl ; 88 d8 ; 0xf378f floppy.c:1002
+ xor ah, ah ; 30 e4 ; 0xf3791
+ xor dx, dx ; 31 d2 ; 0xf3793
+ call 02df7h ; e8 5f f6 ; 0xf3795
+ jmp near 0347ah ; e9 df fc ; 0xf3798
+ mov bl, ah ; 88 e3 ; 0xf379b floppy.c:1009
+ cmp ah, 001h ; 80 fc 01 ; 0xf379d floppy.c:1011
+ jbe short 037c0h ; 76 1e ; 0xf37a0
+ xor ax, ax ; 31 c0 ; 0xf37a2 floppy.c:1012
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf37a4
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf37a7 floppy.c:1013
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf37aa floppy.c:1014
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf37ad floppy.c:1015
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf37b0 floppy.c:1016
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf37b3 floppy.c:1017
+ mov al, bh ; 88 f8 ; 0xf37b6 floppy.c:1018
+ xor ah, ah ; 30 e4 ; 0xf37b8
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf37ba
+ jmp near 038dfh ; e9 1f 01 ; 0xf37bd
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf37c0 floppy.c:1019
+ call 01650h ; e8 8a de ; 0xf37c3
+ mov dl, al ; 88 c2 ; 0xf37c6
+ xor bh, bh ; 30 ff ; 0xf37c8 floppy.c:1025
+ test AL, strict byte 0f0h ; a8 f0 ; 0xf37ca floppy.c:1026
+ je short 037d0h ; 74 02 ; 0xf37cc
+ mov BH, strict byte 001h ; b7 01 ; 0xf37ce floppy.c:1027
+ test dl, 00fh ; f6 c2 0f ; 0xf37d0 floppy.c:1028
+ je short 037d7h ; 74 02 ; 0xf37d3
+ db 0feh, 0c7h
+ ; inc bh ; fe c7 ; 0xf37d5 floppy.c:1029
+ test bl, bl ; 84 db ; 0xf37d7 floppy.c:1031
+ jne short 037e0h ; 75 05 ; 0xf37d9
+ shr dl, 004h ; c0 ea 04 ; 0xf37db floppy.c:1032
+ jmp short 037e3h ; eb 03 ; 0xf37de floppy.c:1033
+ and dl, 00fh ; 80 e2 0f ; 0xf37e0 floppy.c:1034
+ mov byte [bp+011h], 000h ; c6 46 11 00 ; 0xf37e3 floppy.c:1037
+ mov al, dl ; 88 d0 ; 0xf37e7
+ xor ah, ah ; 30 e4 ; 0xf37e9
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf37eb
+ xor al, dl ; 30 d0 ; 0xf37ee floppy.c:1038
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf37f0
+ mov cx, word [bp+012h] ; 8b 4e 12 ; 0xf37f3 floppy.c:1040
+ mov cl, bh ; 88 f9 ; 0xf37f6
+ mov word [bp+012h], cx ; 89 4e 12 ; 0xf37f8
+ mov ax, cx ; 89 c8 ; 0xf37fb floppy.c:1041
+ xor ah, ch ; 30 ec ; 0xf37fd
+ or ah, 001h ; 80 cc 01 ; 0xf37ff
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf3802
+ cmp dl, 003h ; 80 fa 03 ; 0xf3805 floppy.c:1043
+ jc short 0381fh ; 72 15 ; 0xf3808
+ jbe short 03846h ; 76 3a ; 0xf380a
+ cmp dl, 005h ; 80 fa 05 ; 0xf380c
+ jc short 0384dh ; 72 3c ; 0xf380f
+ jbe short 03854h ; 76 41 ; 0xf3811
+ cmp dl, 00fh ; 80 fa 0f ; 0xf3813
+ je short 03862h ; 74 4a ; 0xf3816
+ cmp dl, 00eh ; 80 fa 0e ; 0xf3818
+ je short 0385bh ; 74 3e ; 0xf381b
+ jmp short 03869h ; eb 4a ; 0xf381d
+ cmp dl, 002h ; 80 fa 02 ; 0xf381f
+ je short 0383fh ; 74 1b ; 0xf3822
+ cmp dl, 001h ; 80 fa 01 ; 0xf3824
+ je short 03838h ; 74 0f ; 0xf3827
+ test dl, dl ; 84 d2 ; 0xf3829
+ jne short 03869h ; 75 3c ; 0xf382b
+ mov word [bp+014h], strict word 00000h ; c7 46 14 00 00 ; 0xf382d floppy.c:1045
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf3832 floppy.c:1046
+ jmp short 03877h ; eb 3f ; 0xf3836 floppy.c:1047
+ mov word [bp+014h], 02709h ; c7 46 14 09 27 ; 0xf3838 floppy.c:1050
+ jmp short 03877h ; eb 38 ; 0xf383d floppy.c:1051
+ mov word [bp+014h], 04f0fh ; c7 46 14 0f 4f ; 0xf383f floppy.c:1054
+ jmp short 03877h ; eb 31 ; 0xf3844 floppy.c:1055
+ mov word [bp+014h], 04f09h ; c7 46 14 09 4f ; 0xf3846 floppy.c:1058
+ jmp short 03877h ; eb 2a ; 0xf384b floppy.c:1059
+ mov word [bp+014h], 04f12h ; c7 46 14 12 4f ; 0xf384d floppy.c:1062
+ jmp short 03877h ; eb 23 ; 0xf3852 floppy.c:1063
+ mov word [bp+014h], 04f24h ; c7 46 14 24 4f ; 0xf3854 floppy.c:1066
+ jmp short 03877h ; eb 1c ; 0xf3859 floppy.c:1067
+ mov word [bp+014h], 0fe3fh ; c7 46 14 3f fe ; 0xf385b floppy.c:1070
+ jmp short 03877h ; eb 15 ; 0xf3860 floppy.c:1071
+ mov word [bp+014h], 0feffh ; c7 46 14 ff fe ; 0xf3862 floppy.c:1074
+ jmp short 03877h ; eb 0e ; 0xf3867 floppy.c:1075
+ push 00275h ; 68 75 02 ; 0xf3869 floppy.c:1079
+ push 002cdh ; 68 cd 02 ; 0xf386c
+ push strict byte 00007h ; 6a 07 ; 0xf386f
+ call 018ffh ; e8 8b e0 ; 0xf3871
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf3874
+ mov word [bp+006h], 0f000h ; c7 46 06 00 f0 ; 0xf3877 floppy.c:1083
+ mov al, dl ; 88 d0 ; 0xf387c floppy.c:1084
+ xor ah, ah ; 30 e4 ; 0xf387e
+ call 03b0bh ; e8 88 02 ; 0xf3880
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf3883
+ jmp near 0347ah ; e9 f1 fb ; 0xf3886
+ mov bl, ah ; 88 e3 ; 0xf3889 floppy.c:1091
+ cmp ah, 001h ; 80 fc 01 ; 0xf388b floppy.c:1092
+ jbe short 03895h ; 76 05 ; 0xf388e
+ mov word [bp+016h], dx ; 89 56 16 ; 0xf3890 floppy.c:1093
+ jmp short 038dfh ; eb 4a ; 0xf3893
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf3895 floppy.c:1099
+ call 01650h ; e8 b5 dd ; 0xf3898
+ test bl, bl ; 84 db ; 0xf389b floppy.c:1100
+ jne short 038a6h ; 75 07 ; 0xf389d
+ mov dl, al ; 88 c2 ; 0xf389f floppy.c:1101
+ shr dl, 004h ; c0 ea 04 ; 0xf38a1
+ jmp short 038abh ; eb 05 ; 0xf38a4 floppy.c:1102
+ mov dl, al ; 88 c2 ; 0xf38a6 floppy.c:1103
+ and dl, 00fh ; 80 e2 0f ; 0xf38a8
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf38ab floppy.c:1104
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf38af
+ xor ah, ah ; 30 e4 ; 0xf38b2
+ test dl, dl ; 84 d2 ; 0xf38b4 floppy.c:1105
+ je short 038c5h ; 74 0d ; 0xf38b6
+ cmp dl, 001h ; 80 fa 01 ; 0xf38b8 floppy.c:1106
+ jbe short 038c2h ; 76 05 ; 0xf38bb
+ or ah, 002h ; 80 cc 02 ; 0xf38bd floppy.c:1108
+ jmp short 038c5h ; eb 03 ; 0xf38c0 floppy.c:1109
+ or ah, 001h ; 80 cc 01 ; 0xf38c2 floppy.c:1110
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf38c5
+ jmp near 031f8h ; e9 2d f9 ; 0xf38c8 floppy.c:1113
+ cmp ah, 001h ; 80 fc 01 ; 0xf38cb floppy.c:1118
+ jbe short 038e5h ; 76 15 ; 0xf38ce
+ mov word [bp+016h], si ; 89 76 16 ; 0xf38d0 floppy.c:1119
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf38d3 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf38d6
+ mov es, ax ; 8e c0 ; 0xf38d9
+ mov byte [es:bx], 001h ; 26 c6 07 01 ; 0xf38db
+ mov word [bp+01ch], cx ; 89 4e 1c ; 0xf38df
+ jmp near 031f8h ; e9 13 f9 ; 0xf38e2
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf38e5 floppy.c:1125
+ xor ah, ah ; 30 e4 ; 0xf38e8
+ or ah, 006h ; 80 cc 06 ; 0xf38ea
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf38ed
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf38f0 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf38f3
+ mov es, ax ; 8e c0 ; 0xf38f6
+ mov byte [es:bx], 006h ; 26 c6 07 06 ; 0xf38f8
+ jmp near 039d5h ; e9 d6 00 ; 0xf38fc
+ mov bl, ah ; 88 e3 ; 0xf38ff floppy.c:1134
+ mov dl, byte [bp+016h] ; 8a 56 16 ; 0xf3901 floppy.c:1142
+ cmp ah, 001h ; 80 fc 01 ; 0xf3904 floppy.c:1146
+ jnbe short 038d0h ; 77 c7 ; 0xf3907
+ mov al, bl ; 88 d8 ; 0xf3909 floppy.c:1154
+ xor ah, ah ; 30 e4 ; 0xf390b
+ call 030f2h ; e8 e2 f7 ; 0xf390d
+ test ax, ax ; 85 c0 ; 0xf3910
+ jne short 03917h ; 75 03 ; 0xf3912
+ jmp near 03626h ; e9 0f fd ; 0xf3914
+ test bl, bl ; 84 db ; 0xf3917 floppy.c:1162
+ je short 03920h ; 74 05 ; 0xf3919
+ mov bx, 00091h ; bb 91 00 ; 0xf391b
+ jmp short 03923h ; eb 03 ; 0xf391e
+ mov bx, 00090h ; bb 90 00 ; 0xf3920
+ mov word [bp-008h], bx ; 89 5e f8 ; 0xf3923
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3926 floppy.c:38
+ mov es, ax ; 8e c0 ; 0xf3929
+ mov bl, byte [es:bx] ; 26 8a 1f ; 0xf392b
+ and bl, 00fh ; 80 e3 0f ; 0xf392e floppy.c:1166
+ cmp dl, 002h ; 80 fa 02 ; 0xf3931 floppy.c:1168
+ jc short 03945h ; 72 0f ; 0xf3934
+ jbe short 03952h ; 76 1a ; 0xf3936
+ cmp dl, 004h ; 80 fa 04 ; 0xf3938
+ je short 0394dh ; 74 10 ; 0xf393b
+ cmp dl, 003h ; 80 fa 03 ; 0xf393d
+ je short 03957h ; 74 15 ; 0xf3940
+ jmp near 03183h ; e9 3e f8 ; 0xf3942
+ cmp dl, 001h ; 80 fa 01 ; 0xf3945
+ je short 0394dh ; 74 03 ; 0xf3948
+ jmp near 03183h ; e9 36 f8 ; 0xf394a
+ or bl, 090h ; 80 cb 90 ; 0xf394d floppy.c:1171
+ jmp short 0395ah ; eb 08 ; 0xf3950 floppy.c:1172
+ or bl, 070h ; 80 cb 70 ; 0xf3952 floppy.c:1175
+ jmp short 0395ah ; eb 03 ; 0xf3955 floppy.c:1176
+ or bl, 010h ; 80 cb 10 ; 0xf3957 floppy.c:1179
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf395a floppy.c:43
+ mov es, ax ; 8e c0 ; 0xf395d
+ mov si, word [bp-008h] ; 8b 76 f8 ; 0xf395f
+ mov byte [es:si], bl ; 26 88 1c ; 0xf3962
+ xor al, al ; 30 c0 ; 0xf3965 floppy.c:1198
+ mov byte [bp+017h], al ; 88 46 17 ; 0xf3967
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf396a floppy.c:43
+ mov byte [es:bx], al ; 26 88 07 ; 0xf396d
+ jmp near 0347ah ; e9 07 fb ; 0xf3970
+ mov bl, ah ; 88 e3 ; 0xf3973 floppy.c:1208
+ mov dl, byte [bp+014h] ; 8a 56 14 ; 0xf3975 floppy.c:1210
+ mov bh, dl ; 88 d7 ; 0xf3978 floppy.c:1211
+ and bh, 03fh ; 80 e7 3f ; 0xf397a
+ sar dx, 006h ; c1 fa 06 ; 0xf397d floppy.c:1212
+ sal dx, 008h ; c1 e2 08 ; 0xf3980
+ mov word [bp-00ch], dx ; 89 56 f4 ; 0xf3983
+ mov dx, word [bp+014h] ; 8b 56 14 ; 0xf3986
+ shr dx, 008h ; c1 ea 08 ; 0xf3989
+ add dx, word [bp-00ch] ; 03 56 f4 ; 0xf398c
+ mov byte [bp-004h], dl ; 88 56 fc ; 0xf398f
+ cmp ah, 001h ; 80 fc 01 ; 0xf3992 floppy.c:1217
+ jbe short 0399ah ; 76 03 ; 0xf3995
+ jmp near 038d0h ; e9 36 ff ; 0xf3997
+ mov al, bl ; 88 d8 ; 0xf399a floppy.c:1225
+ xor ah, ah ; 30 e4 ; 0xf399c
+ call 030f2h ; e8 51 f7 ; 0xf399e
+ test ax, ax ; 85 c0 ; 0xf39a1
+ jne short 039a8h ; 75 03 ; 0xf39a3
+ jmp near 03626h ; e9 7e fc ; 0xf39a5
+ mov cl, bl ; 88 d9 ; 0xf39a8 floppy.c:1233
+ xor ch, ch ; 30 ed ; 0xf39aa
+ mov ax, cx ; 89 c8 ; 0xf39ac
+ call 02f30h ; e8 7f f5 ; 0xf39ae
+ test ax, ax ; 85 c0 ; 0xf39b1
+ jne short 039dch ; 75 27 ; 0xf39b3
+ mov ax, cx ; 89 c8 ; 0xf39b5 floppy.c:1234
+ call 0300ch ; e8 52 f6 ; 0xf39b7
+ test ax, ax ; 85 c0 ; 0xf39ba
+ jne short 039dch ; 75 1e ; 0xf39bc
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf39be floppy.c:1235
+ xor ah, ah ; 30 e4 ; 0xf39c1
+ or ah, 00ch ; 80 cc 0c ; 0xf39c3
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf39c6
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf39c9 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf39cc
+ mov es, ax ; 8e c0 ; 0xf39cf
+ mov byte [es:bx], 00ch ; 26 c6 07 0c ; 0xf39d1
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf39d5
+ jmp near 031f8h ; e9 1c f8 ; 0xf39d9
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf39dc floppy.c:1243
+ call 01650h ; e8 6e dc ; 0xf39df
+ test bl, bl ; 84 db ; 0xf39e2 floppy.c:1244
+ jne short 039edh ; 75 07 ; 0xf39e4
+ mov dl, al ; 88 c2 ; 0xf39e6 floppy.c:1245
+ shr dl, 004h ; c0 ea 04 ; 0xf39e8
+ jmp short 039f2h ; eb 05 ; 0xf39eb floppy.c:1246
+ mov dl, al ; 88 c2 ; 0xf39ed floppy.c:1247
+ and dl, 00fh ; 80 e2 0f ; 0xf39ef
+ test bl, bl ; 84 db ; 0xf39f2 floppy.c:1250
+ je short 039fbh ; 74 05 ; 0xf39f4
+ mov si, 00091h ; be 91 00 ; 0xf39f6
+ jmp short 039feh ; eb 03 ; 0xf39f9
+ mov si, 00090h ; be 90 00 ; 0xf39fb
+ mov word [bp-008h], si ; 89 76 f8 ; 0xf39fe
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3a01 floppy.c:38
+ mov es, ax ; 8e c0 ; 0xf3a04
+ mov bl, byte [es:si] ; 26 8a 1c ; 0xf3a06
+ and bl, 00fh ; 80 e3 0f ; 0xf3a09 floppy.c:39
+ cmp dl, 003h ; 80 fa 03 ; 0xf3a0c floppy.c:1256
+ jc short 03a2ch ; 72 1b ; 0xf3a0f
+ mov al, bl ; 88 d8 ; 0xf3a11
+ or AL, strict byte 090h ; 0c 90 ; 0xf3a13
+ cmp dl, 003h ; 80 fa 03 ; 0xf3a15
+ jbe short 03a68h ; 76 4e ; 0xf3a18
+ mov ah, bl ; 88 dc ; 0xf3a1a
+ or ah, 010h ; 80 cc 10 ; 0xf3a1c
+ cmp dl, 005h ; 80 fa 05 ; 0xf3a1f
+ je short 03a66h ; 74 42 ; 0xf3a22
+ cmp dl, 004h ; 80 fa 04 ; 0xf3a24
+ je short 03a75h ; 74 4c ; 0xf3a27
+ jmp near 03aadh ; e9 81 00 ; 0xf3a29
+ cmp dl, 002h ; 80 fa 02 ; 0xf3a2c
+ je short 03a46h ; 74 15 ; 0xf3a2f
+ cmp dl, 001h ; 80 fa 01 ; 0xf3a31
+ jne short 03a79h ; 75 43 ; 0xf3a34
+ cmp byte [bp-004h], 027h ; 80 7e fc 27 ; 0xf3a36 floppy.c:1258
+ jne short 03a79h ; 75 3d ; 0xf3a3a
+ cmp bh, 009h ; 80 ff 09 ; 0xf3a3c
+ jne short 03a8fh ; 75 4e ; 0xf3a3f
+ or bl, 090h ; 80 cb 90 ; 0xf3a41 floppy.c:1259
+ jmp short 03a8fh ; eb 49 ; 0xf3a44 floppy.c:1261
+ cmp byte [bp-004h], 027h ; 80 7e fc 27 ; 0xf3a46 floppy.c:1263
+ jne short 03a56h ; 75 0a ; 0xf3a4a
+ cmp bh, 009h ; 80 ff 09 ; 0xf3a4c
+ jne short 03a56h ; 75 05 ; 0xf3a4f
+ or bl, 070h ; 80 cb 70 ; 0xf3a51 floppy.c:1264
+ jmp short 03a8fh ; eb 39 ; 0xf3a54 floppy.c:1265
+ cmp byte [bp-004h], 04fh ; 80 7e fc 4f ; 0xf3a56
+ jne short 03aadh ; 75 51 ; 0xf3a5a
+ cmp bh, 00fh ; 80 ff 0f ; 0xf3a5c
+ jne short 03aadh ; 75 4c ; 0xf3a5f
+ or bl, 010h ; 80 cb 10 ; 0xf3a61 floppy.c:1266
+ jmp short 03aadh ; eb 47 ; 0xf3a64 floppy.c:1268
+ jmp short 03a91h ; eb 29 ; 0xf3a66
+ cmp byte [bp-004h], 04fh ; 80 7e fc 4f ; 0xf3a68 floppy.c:1270
+ jne short 03aadh ; 75 3f ; 0xf3a6c
+ cmp bh, 009h ; 80 ff 09 ; 0xf3a6e
+ je short 03a77h ; 74 04 ; 0xf3a71
+ jmp short 03aadh ; eb 38 ; 0xf3a73
+ jmp short 03a7bh ; eb 04 ; 0xf3a75
+ mov bl, al ; 88 c3 ; 0xf3a77 floppy.c:1271
+ jmp short 03aadh ; eb 32 ; 0xf3a79 floppy.c:1273
+ cmp byte [bp-004h], 04fh ; 80 7e fc 4f ; 0xf3a7b floppy.c:1275
+ jne short 03aadh ; 75 2c ; 0xf3a7f
+ cmp bh, 009h ; 80 ff 09 ; 0xf3a81 floppy.c:1276
+ jne short 03a88h ; 75 02 ; 0xf3a84
+ jmp short 03a77h ; eb ef ; 0xf3a86
+ cmp bh, 012h ; 80 ff 12 ; 0xf3a88 floppy.c:1277
+ jne short 03aadh ; 75 20 ; 0xf3a8b
+ mov bl, ah ; 88 e3 ; 0xf3a8d floppy.c:1279
+ jmp short 03aadh ; eb 1c ; 0xf3a8f floppy.c:1282
+ cmp byte [bp-004h], 04fh ; 80 7e fc 4f ; 0xf3a91 floppy.c:1284
+ jne short 03aadh ; 75 16 ; 0xf3a95
+ cmp bh, 009h ; 80 ff 09 ; 0xf3a97 floppy.c:1285
+ jne short 03a9eh ; 75 02 ; 0xf3a9a
+ jmp short 03a77h ; eb d9 ; 0xf3a9c
+ cmp bh, 012h ; 80 ff 12 ; 0xf3a9e floppy.c:1286
+ jne short 03aa5h ; 75 02 ; 0xf3aa1
+ jmp short 03a8dh ; eb e8 ; 0xf3aa3
+ cmp bh, 024h ; 80 ff 24 ; 0xf3aa5 floppy.c:1288
+ jne short 03aadh ; 75 03 ; 0xf3aa8
+ or bl, 0d0h ; 80 cb d0 ; 0xf3aaa floppy.c:1290
+ mov al, bl ; 88 d8 ; 0xf3aad floppy.c:1299
+ xor ah, ah ; 30 e4 ; 0xf3aaf
+ sar ax, 004h ; c1 f8 04 ; 0xf3ab1
+ test AL, strict byte 001h ; a8 01 ; 0xf3ab4
+ jne short 03abbh ; 75 03 ; 0xf3ab6
+ jmp near 039beh ; e9 03 ff ; 0xf3ab8
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3abb floppy.c:43
+ mov es, ax ; 8e c0 ; 0xf3abe
+ mov si, word [bp-008h] ; 8b 76 f8 ; 0xf3ac0
+ mov byte [es:si], bl ; 26 88 1c ; 0xf3ac3
+ mov word [bp+006h], 0f000h ; c7 46 06 00 f0 ; 0xf3ac6 floppy.c:1312
+ mov al, dl ; 88 d0 ; 0xf3acb floppy.c:1313
+ xor ah, ah ; 30 e4 ; 0xf3acd
+ call 03b0bh ; e8 39 00 ; 0xf3acf
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf3ad2
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf3ad5 floppy.c:1316
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3ad9 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3adc
+ mov es, ax ; 8e c0 ; 0xf3adf
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3ae1
+ jmp near 0347ah ; e9 92 f9 ; 0xf3ae5
+ mov bx, 00da0h ; bb a0 0d ; 0xf3ae8 floppy.c:1322
+ mov cx, ds ; 8c d9 ; 0xf3aeb
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3aed
+ call 018bch ; e8 c9 dd ; 0xf3af0
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3af3
+ shr ax, 008h ; c1 e8 08 ; 0xf3af6
+ push ax ; 50 ; 0xf3af9
+ push 00275h ; 68 75 02 ; 0xf3afa
+ push 002e2h ; 68 e2 02 ; 0xf3afd
+ push strict byte 00004h ; 6a 04 ; 0xf3b00
+ call 018ffh ; e8 fa dd ; 0xf3b02
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf3b05
+ jmp near 03183h ; e9 78 f6 ; 0xf3b08 floppy.c:68
+ ; disGetNextSymbol 0xf3b0b LB 0x63bd -> off=0x0 cb=0000000000000030 uValue=00000000000f250b 'get_floppy_dpt'
+get_floppy_dpt: ; 0xf3b0b LB 0x30
+ push bx ; 53 ; 0xf3b0b floppyt.c:94
+ push dx ; 52 ; 0xf3b0c
+ push bp ; 55 ; 0xf3b0d
+ mov bp, sp ; 89 e5 ; 0xf3b0e
+ mov dl, al ; 88 c2 ; 0xf3b10
+ xor ax, ax ; 31 c0 ; 0xf3b12 floppyt.c:98
+ jmp short 03b1ch ; eb 06 ; 0xf3b14
+ inc ax ; 40 ; 0xf3b16 floppyt.c:100
+ cmp ax, strict word 00007h ; 3d 07 00 ; 0xf3b17
+ jnc short 03b34h ; 73 18 ; 0xf3b1a
+ mov bx, ax ; 89 c3 ; 0xf3b1c
+ add bx, ax ; 01 c3 ; 0xf3b1e
+ cmp dl, byte [word bx+0005bh] ; 3a 97 5b 00 ; 0xf3b20
+ jne short 03b16h ; 75 f0 ; 0xf3b24
+ mov al, byte [word bx+0005ch] ; 8a 87 5c 00 ; 0xf3b26
+ xor ah, ah ; 30 e4 ; 0xf3b2a
+ imul ax, ax, strict byte 0000dh ; 6b c0 0d ; 0xf3b2c
+ add ax, strict word 00000h ; 05 00 00 ; 0xf3b2f
+ jmp short 03b37h ; eb 03 ; 0xf3b32
+ mov ax, strict word 00041h ; b8 41 00 ; 0xf3b34 floppyt.c:103
+ pop bp ; 5d ; 0xf3b37 floppyt.c:104
+ pop dx ; 5a ; 0xf3b38
+ pop bx ; 5b ; 0xf3b39
+ retn ; c3 ; 0xf3b3a
+ ; disGetNextSymbol 0xf3b3b LB 0x638d -> off=0x0 cb=0000000000000007 uValue=00000000000f253b 'dummy_soft_reset'
+dummy_soft_reset: ; 0xf3b3b LB 0x7
+ push bp ; 55 ; 0xf3b3b eltorito.c:126
+ mov bp, sp ; 89 e5 ; 0xf3b3c
+ xor ax, ax ; 31 c0 ; 0xf3b3e eltorito.c:129
+ pop bp ; 5d ; 0xf3b40
+ retn ; c3 ; 0xf3b41
+ ; disGetNextSymbol 0xf3b42 LB 0x6386 -> off=0x0 cb=0000000000000017 uValue=00000000000f2542 'cdemu_init'
+cdemu_init: ; 0xf3b42 LB 0x17
+ push bp ; 55 ; 0xf3b42 eltorito.c:155
+ mov bp, sp ; 89 e5 ; 0xf3b43
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3b45 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3b48
+ mov es, ax ; 8e c0 ; 0xf3b4b
+ mov es, [es:bx] ; 26 8e 07 ; 0xf3b4d
+ mov bx, 00366h ; bb 66 03 ; 0xf3b50 eltorito.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3b53
+ pop bp ; 5d ; 0xf3b57 eltorito.c:162
+ retn ; c3 ; 0xf3b58
+ ; disGetNextSymbol 0xf3b59 LB 0x636f -> off=0x0 cb=0000000000000016 uValue=00000000000f2559 'cdemu_isactive'
+cdemu_isactive: ; 0xf3b59 LB 0x16
+ push bp ; 55 ; 0xf3b59 eltorito.c:164
+ mov bp, sp ; 89 e5 ; 0xf3b5a
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3b5c eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3b5f
+ mov es, ax ; 8e c0 ; 0xf3b62
+ mov es, [es:bx] ; 26 8e 07 ; 0xf3b64
+ mov bx, 00366h ; bb 66 03 ; 0xf3b67 eltorito.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf3b6a
+ pop bp ; 5d ; 0xf3b6d eltorito.c:170
+ retn ; c3 ; 0xf3b6e
+ ; disGetNextSymbol 0xf3b6f LB 0x6359 -> off=0x0 cb=0000000000000016 uValue=00000000000f256f 'cdemu_emulated_drive'
+cdemu_emulated_drive: ; 0xf3b6f LB 0x16
+ push bp ; 55 ; 0xf3b6f eltorito.c:172
+ mov bp, sp ; 89 e5 ; 0xf3b70
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3b72 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3b75
+ mov es, ax ; 8e c0 ; 0xf3b78
+ mov es, [es:bx] ; 26 8e 07 ; 0xf3b7a
+ mov bx, 00368h ; bb 68 03 ; 0xf3b7d eltorito.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf3b80
+ pop bp ; 5d ; 0xf3b83 eltorito.c:178
+ retn ; c3 ; 0xf3b84
+ ; disGetNextSymbol 0xf3b85 LB 0x6343 -> off=0x0 cb=000000000000017b uValue=00000000000f2585 'int13_eltorito'
+int13_eltorito: ; 0xf3b85 LB 0x17b
+ push bp ; 55 ; 0xf3b85 eltorito.c:184
+ mov bp, sp ; 89 e5 ; 0xf3b86
+ push si ; 56 ; 0xf3b88
+ push di ; 57 ; 0xf3b89
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3b8a eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3b8d
+ mov es, ax ; 8e c0 ; 0xf3b90
+ mov di, word [es:bx] ; 26 8b 3f ; 0xf3b92
+ mov bx, 00366h ; bb 66 03 ; 0xf3b95 eltorito.c:190
+ mov si, word [bp+016h] ; 8b 76 16 ; 0xf3b98 eltorito.c:196
+ shr si, 008h ; c1 ee 08 ; 0xf3b9b
+ cmp si, strict byte 0004bh ; 83 fe 4b ; 0xf3b9e
+ jc short 03badh ; 72 0a ; 0xf3ba1
+ jbe short 03bd4h ; 76 2f ; 0xf3ba3
+ cmp si, strict byte 0004dh ; 83 fe 4d ; 0xf3ba5
+ jbe short 03bb2h ; 76 08 ; 0xf3ba8
+ jmp near 03cc6h ; e9 19 01 ; 0xf3baa
+ cmp si, strict byte 0004ah ; 83 fe 4a ; 0xf3bad
+ jne short 03bd1h ; 75 1f ; 0xf3bb0
+ mov bx, 00da0h ; bb a0 0d ; 0xf3bb2 eltorito.c:202
+ mov cx, ds ; 8c d9 ; 0xf3bb5
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3bb7
+ call 018bch ; e8 ff dc ; 0xf3bba
+ push word [bp+016h] ; ff 76 16 ; 0xf3bbd
+ push 002fch ; 68 fc 02 ; 0xf3bc0
+ push 0030bh ; 68 0b 03 ; 0xf3bc3
+ push strict byte 00004h ; 6a 04 ; 0xf3bc6
+ call 018ffh ; e8 34 dd ; 0xf3bc8
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf3bcb
+ jmp near 03ce1h ; e9 10 01 ; 0xf3bce eltorito.c:203
+ jmp near 03cc6h ; e9 f2 00 ; 0xf3bd1
+ mov es, [bp+004h] ; 8e 46 04 ; 0xf3bd4 eltorito.c:41
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3bd7
+ mov byte [es:si], 013h ; 26 c6 04 13 ; 0xf3bda
+ inc si ; 46 ; 0xf3bde eltorito.c:210
+ mov ax, es ; 8c c0 ; 0xf3bdf eltorito.c:41
+ mov es, di ; 8e c7 ; 0xf3be1
+ mov dl, byte [es:bx+001h] ; 26 8a 57 01 ; 0xf3be3
+ mov es, ax ; 8e c0 ; 0xf3be7 eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3be9
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3bec eltorito.c:211
+ inc si ; 46 ; 0xf3bef
+ inc si ; 46 ; 0xf3bf0
+ mov es, di ; 8e c7 ; 0xf3bf1 eltorito.c:41
+ mov dl, byte [es:bx+002h] ; 26 8a 57 02 ; 0xf3bf3
+ mov es, ax ; 8e c0 ; 0xf3bf7 eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3bf9
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3bfc eltorito.c:212
+ add si, strict byte 00003h ; 83 c6 03 ; 0xf3bff
+ mov es, di ; 8e c7 ; 0xf3c02 eltorito.c:41
+ mov dl, byte [es:bx+003h] ; 26 8a 57 03 ; 0xf3c04
+ mov es, ax ; 8e c0 ; 0xf3c08 eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3c0a
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3c0d eltorito.c:213
+ add si, strict byte 00004h ; 83 c6 04 ; 0xf3c10
+ mov es, di ; 8e c7 ; 0xf3c13 eltorito.c:61
+ mov dx, word [es:bx+008h] ; 26 8b 57 08 ; 0xf3c15
+ mov cx, word [es:bx+00ah] ; 26 8b 4f 0a ; 0xf3c19
+ mov es, ax ; 8e c0 ; 0xf3c1d eltorito.c:63
+ mov word [es:si], dx ; 26 89 14 ; 0xf3c1f
+ mov word [es:si+002h], cx ; 26 89 4c 02 ; 0xf3c22
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3c26 eltorito.c:214
+ add si, strict byte 00008h ; 83 c6 08 ; 0xf3c29
+ mov es, di ; 8e c7 ; 0xf3c2c eltorito.c:51
+ mov dx, word [es:bx+004h] ; 26 8b 57 04 ; 0xf3c2e
+ mov es, ax ; 8e c0 ; 0xf3c32 eltorito.c:53
+ mov word [es:si], dx ; 26 89 14 ; 0xf3c34
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3c37 eltorito.c:215
+ add si, strict byte 0000ah ; 83 c6 0a ; 0xf3c3a
+ mov es, di ; 8e c7 ; 0xf3c3d eltorito.c:51
+ mov dx, word [es:bx+006h] ; 26 8b 57 06 ; 0xf3c3f
+ mov es, ax ; 8e c0 ; 0xf3c43 eltorito.c:53
+ mov word [es:si], dx ; 26 89 14 ; 0xf3c45
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3c48 eltorito.c:216
+ add si, strict byte 0000ch ; 83 c6 0c ; 0xf3c4b
+ mov es, di ; 8e c7 ; 0xf3c4e eltorito.c:51
+ mov dx, word [es:bx+00ch] ; 26 8b 57 0c ; 0xf3c50
+ mov es, ax ; 8e c0 ; 0xf3c54 eltorito.c:53
+ mov word [es:si], dx ; 26 89 14 ; 0xf3c56
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3c59 eltorito.c:217
+ add si, strict byte 0000eh ; 83 c6 0e ; 0xf3c5c
+ mov es, di ; 8e c7 ; 0xf3c5f eltorito.c:51
+ mov dx, word [es:bx+00eh] ; 26 8b 57 0e ; 0xf3c61
+ mov es, ax ; 8e c0 ; 0xf3c65 eltorito.c:53
+ mov word [es:si], dx ; 26 89 14 ; 0xf3c67
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3c6a eltorito.c:218
+ add si, strict byte 00010h ; 83 c6 10 ; 0xf3c6d
+ mov es, di ; 8e c7 ; 0xf3c70 eltorito.c:41
+ mov dl, byte [es:bx+012h] ; 26 8a 57 12 ; 0xf3c72
+ mov es, ax ; 8e c0 ; 0xf3c76 eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3c78
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3c7b eltorito.c:219
+ add si, strict byte 00011h ; 83 c6 11 ; 0xf3c7e
+ mov es, di ; 8e c7 ; 0xf3c81 eltorito.c:41
+ mov dl, byte [es:bx+014h] ; 26 8a 57 14 ; 0xf3c83
+ mov es, ax ; 8e c0 ; 0xf3c87 eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3c89
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3c8c eltorito.c:220
+ add si, strict byte 00012h ; 83 c6 12 ; 0xf3c8f
+ mov dx, ax ; 89 c2 ; 0xf3c92 eltorito.c:41
+ mov es, di ; 8e c7 ; 0xf3c94
+ mov al, byte [es:bx+010h] ; 26 8a 47 10 ; 0xf3c96
+ mov es, dx ; 8e c2 ; 0xf3c9a eltorito.c:43
+ mov byte [es:si], al ; 26 88 04 ; 0xf3c9c
+ test byte [bp+016h], 0ffh ; f6 46 16 ff ; 0xf3c9f eltorito.c:223
+ jne short 03cabh ; 75 06 ; 0xf3ca3
+ mov es, di ; 8e c7 ; 0xf3ca5 eltorito.c:225
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3ca7
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf3cab eltorito.c:228
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf3caf
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3cb2
+ mov es, ax ; 8e c0 ; 0xf3cb5
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3cb7
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf3cbb
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf3cbf
+ pop di ; 5f ; 0xf3cc2
+ pop si ; 5e ; 0xf3cc3
+ pop bp ; 5d ; 0xf3cc4
+ retn ; c3 ; 0xf3cc5
+ mov bx, 00da0h ; bb a0 0d ; 0xf3cc6 eltorito.c:232
+ mov cx, ds ; 8c d9 ; 0xf3cc9
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3ccb
+ call 018bch ; e8 eb db ; 0xf3cce
+ mov bx, word [bp+016h] ; 8b 5e 16 ; 0xf3cd1
+ shr bx, 008h ; c1 eb 08 ; 0xf3cd4
+ push bx ; 53 ; 0xf3cd7
+ push 002fch ; 68 fc 02 ; 0xf3cd8
+ push 00333h ; 68 33 03 ; 0xf3cdb
+ jmp near 03bc6h ; e9 e5 fe ; 0xf3cde
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3ce1 eltorito.c:238
+ xor ah, ah ; 30 e4 ; 0xf3ce4
+ or ah, 001h ; 80 cc 01 ; 0xf3ce6
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3ce9
+ shr ax, 008h ; c1 e8 08 ; 0xf3cec eltorito.c:239
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf3cef eltorito.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3cf2
+ mov es, dx ; 8e c2 ; 0xf3cf5
+ mov byte [es:bx], al ; 26 88 07 ; 0xf3cf7
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf3cfa eltorito.c:240
+ jmp short 03cbfh ; eb bf ; 0xf3cfe eltorito.c:241
+ ; disGetNextSymbol 0xf3d00 LB 0x61c8 -> off=0x0 cb=0000000000000033 uValue=00000000000f2700 'device_is_cdrom'
+device_is_cdrom: ; 0xf3d00 LB 0x33
+ push bx ; 53 ; 0xf3d00 eltorito.c:256
+ push dx ; 52 ; 0xf3d01
+ push bp ; 55 ; 0xf3d02
+ mov bp, sp ; 89 e5 ; 0xf3d03
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3d05 eltorito.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3d08
+ mov es, dx ; 8e c2 ; 0xf3d0b
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf3d0d
+ cmp AL, strict byte 010h ; 3c 10 ; 0xf3d10 eltorito.c:262
+ jc short 03d18h ; 72 04 ; 0xf3d12
+ xor ax, ax ; 31 c0 ; 0xf3d14 eltorito.c:263
+ jmp short 03d2fh ; eb 17 ; 0xf3d16
+ xor ah, ah ; 30 e4 ; 0xf3d18 eltorito.c:268
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf3d1a
+ mov es, bx ; 8e c3 ; 0xf3d1d
+ mov bx, ax ; 89 c3 ; 0xf3d1f
+ add bx, 00122h ; 81 c3 22 01 ; 0xf3d21
+ cmp byte [es:bx+023h], 005h ; 26 80 7f 23 05 ; 0xf3d25
+ jne short 03d14h ; 75 e8 ; 0xf3d2a
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf3d2c eltorito.c:269
+ pop bp ; 5d ; 0xf3d2f eltorito.c:272
+ pop dx ; 5a ; 0xf3d30
+ pop bx ; 5b ; 0xf3d31
+ retn ; c3 ; 0xf3d32
+ ; disGetNextSymbol 0xf3d33 LB 0x6195 -> off=0x0 cb=00000000000003c1 uValue=00000000000f2733 'cdrom_boot'
+cdrom_boot: ; 0xf3d33 LB 0x3c1
+ push bp ; 55 ; 0xf3d33 eltorito.c:282
+ mov bp, sp ; 89 e5 ; 0xf3d34
+ push bx ; 53 ; 0xf3d36
+ push cx ; 51 ; 0xf3d37
+ push dx ; 52 ; 0xf3d38
+ push si ; 56 ; 0xf3d39
+ push di ; 57 ; 0xf3d3a
+ sub sp, 0081ch ; 81 ec 1c 08 ; 0xf3d3b
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3d3f eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3d42
+ mov es, ax ; 8e c0 ; 0xf3d45
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf3d47
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf3d4a eltorito.c:49
+ mov si, 00366h ; be 66 03 ; 0xf3d4d eltorito.c:295
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf3d50
+ mov word [bp-014h], 00122h ; c7 46 ec 22 01 ; 0xf3d53 eltorito.c:296
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf3d58
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf3d5b eltorito.c:299
+ jmp short 03d6ah ; eb 09 ; 0xf3d5f
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf3d61 eltorito.c:302
+ cmp byte [bp-00ch], 010h ; 80 7e f4 10 ; 0xf3d64
+ jnc short 03d76h ; 73 0c ; 0xf3d68
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3d6a
+ xor ah, ah ; 30 e4 ; 0xf3d6d
+ call 03d00h ; e8 8e ff ; 0xf3d6f
+ test ax, ax ; 85 c0 ; 0xf3d72
+ je short 03d61h ; 74 eb ; 0xf3d74
+ cmp byte [bp-00ch], 010h ; 80 7e f4 10 ; 0xf3d76 eltorito.c:305
+ jc short 03d82h ; 72 06 ; 0xf3d7a
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf3d7c eltorito.c:306
+ jmp near 040eah ; e9 68 03 ; 0xf3d7f
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf3d82 eltorito.c:309
+ xor bx, bx ; 31 db ; 0xf3d85
+ mov dx, ss ; 8c d2 ; 0xf3d87
+ lea ax, [bp-026h] ; 8d 46 da ; 0xf3d89
+ call 09bb0h ; e8 21 5e ; 0xf3d8c
+ mov word [bp-026h], strict word 00028h ; c7 46 da 28 00 ; 0xf3d8f eltorito.c:310
+ mov ax, strict word 00011h ; b8 11 00 ; 0xf3d94 eltorito.c:311
+ xor dx, dx ; 31 d2 ; 0xf3d97
+ xchg ah, al ; 86 c4 ; 0xf3d99
+ xchg dh, dl ; 86 d6 ; 0xf3d9b
+ xchg dx, ax ; 92 ; 0xf3d9d
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf3d9e
+ mov word [bp-022h], dx ; 89 56 de ; 0xf3da1
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf3da4 eltorito.c:312
+ xchg ah, al ; 86 c4 ; 0xf3da7
+ mov word [bp-01fh], ax ; 89 46 e1 ; 0xf3da9
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf3dac eltorito.c:314
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf3daf
+ mov word [es:bx+00eh], strict word 00001h ; 26 c7 47 0e 01 00 ; 0xf3db2
+ mov word [es:bx+010h], 00800h ; 26 c7 47 10 00 08 ; 0xf3db8 eltorito.c:315
+ mov byte [bp-00eh], 000h ; c6 46 f2 00 ; 0xf3dbe eltorito.c:317
+ jmp short 03dcdh ; eb 09 ; 0xf3dc2
+ inc byte [bp-00eh] ; fe 46 f2 ; 0xf3dc4 eltorito.c:322
+ cmp byte [bp-00eh], 004h ; 80 7e f2 04 ; 0xf3dc7
+ jnbe short 03e09h ; 77 3c ; 0xf3dcb
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3dcd
+ xor ah, ah ; 30 e4 ; 0xf3dd0
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf3dd2
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf3dd5
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf3dd8
+ add bx, ax ; 01 c3 ; 0xf3ddb
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf3ddd
+ xor ah, ah ; 30 e4 ; 0xf3de1
+ mov di, ax ; 89 c7 ; 0xf3de3
+ add di, ax ; 01 c7 ; 0xf3de5
+ lea dx, [bp-00826h] ; 8d 96 da f7 ; 0xf3de7
+ push SS ; 16 ; 0xf3deb
+ push dx ; 52 ; 0xf3dec
+ push strict byte 00001h ; 6a 01 ; 0xf3ded
+ push strict byte 00000h ; 6a 00 ; 0xf3def
+ push 00800h ; 68 00 08 ; 0xf3df1
+ push strict byte 00000h ; 6a 00 ; 0xf3df4
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3df6
+ mov cx, ss ; 8c d1 ; 0xf3df9
+ lea bx, [bp-026h] ; 8d 5e da ; 0xf3dfb
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3dfe
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf3e01
+ test ax, ax ; 85 c0 ; 0xf3e05
+ jne short 03dc4h ; 75 bb ; 0xf3e07
+ test ax, ax ; 85 c0 ; 0xf3e09 eltorito.c:323
+ je short 03e13h ; 74 06 ; 0xf3e0b
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf3e0d eltorito.c:324
+ jmp near 040eah ; e9 d7 02 ; 0xf3e10
+ cmp byte [bp-00826h], 000h ; 80 be da f7 00 ; 0xf3e13 eltorito.c:327
+ je short 03e20h ; 74 06 ; 0xf3e18
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3e1a eltorito.c:328
+ jmp near 040eah ; e9 ca 02 ; 0xf3e1d
+ xor di, di ; 31 ff ; 0xf3e20 eltorito.c:330
+ jmp short 03e2ah ; eb 06 ; 0xf3e22
+ inc di ; 47 ; 0xf3e24 eltorito.c:332
+ cmp di, strict byte 00005h ; 83 ff 05 ; 0xf3e25
+ jnc short 03e3ah ; 73 10 ; 0xf3e28
+ mov al, byte [bp+di-00825h] ; 8a 83 db f7 ; 0xf3e2a
+ cmp al, byte [di+00da8h] ; 3a 85 a8 0d ; 0xf3e2e
+ je short 03e24h ; 74 f0 ; 0xf3e32
+ mov ax, strict word 00005h ; b8 05 00 ; 0xf3e34
+ jmp near 040eah ; e9 b0 02 ; 0xf3e37
+ xor di, di ; 31 ff ; 0xf3e3a eltorito.c:334
+ jmp short 03e44h ; eb 06 ; 0xf3e3c
+ inc di ; 47 ; 0xf3e3e eltorito.c:336
+ cmp di, strict byte 00017h ; 83 ff 17 ; 0xf3e3f
+ jnc short 03e54h ; 73 10 ; 0xf3e42
+ mov al, byte [bp+di-0081fh] ; 8a 83 e1 f7 ; 0xf3e44
+ cmp al, byte [di+00daeh] ; 3a 85 ae 0d ; 0xf3e48
+ je short 03e3eh ; 74 f0 ; 0xf3e4c
+ mov ax, strict word 00006h ; b8 06 00 ; 0xf3e4e
+ jmp near 040eah ; e9 96 02 ; 0xf3e51
+ mov ax, word [bp-007dfh] ; 8b 86 21 f8 ; 0xf3e54 eltorito.c:339
+ mov dx, word [bp-007ddh] ; 8b 96 23 f8 ; 0xf3e58
+ mov word [bp-026h], strict word 00028h ; c7 46 da 28 00 ; 0xf3e5c eltorito.c:343
+ xchg ah, al ; 86 c4 ; 0xf3e61 eltorito.c:344
+ xchg dh, dl ; 86 d6 ; 0xf3e63
+ xchg dx, ax ; 92 ; 0xf3e65
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf3e66
+ mov word [bp-022h], dx ; 89 56 de ; 0xf3e69
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf3e6c eltorito.c:345
+ xchg ah, al ; 86 c4 ; 0xf3e6f
+ mov word [bp-01fh], ax ; 89 46 e1 ; 0xf3e71
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3e74 eltorito.c:352
+ xor ah, ah ; 30 e4 ; 0xf3e77
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf3e79
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf3e7c
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf3e7f
+ add bx, ax ; 01 c3 ; 0xf3e82
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf3e84
+ xor ah, ah ; 30 e4 ; 0xf3e88
+ mov di, ax ; 89 c7 ; 0xf3e8a
+ add di, ax ; 01 c7 ; 0xf3e8c
+ lea dx, [bp-00826h] ; 8d 96 da f7 ; 0xf3e8e
+ push SS ; 16 ; 0xf3e92
+ push dx ; 52 ; 0xf3e93
+ push strict byte 00001h ; 6a 01 ; 0xf3e94
+ push strict byte 00000h ; 6a 00 ; 0xf3e96
+ push 00800h ; 68 00 08 ; 0xf3e98
+ push strict byte 00000h ; 6a 00 ; 0xf3e9b
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3e9d
+ mov cx, ss ; 8c d1 ; 0xf3ea0
+ lea bx, [bp-026h] ; 8d 5e da ; 0xf3ea2
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3ea5
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf3ea8
+ test ax, ax ; 85 c0 ; 0xf3eac eltorito.c:353
+ je short 03eb6h ; 74 06 ; 0xf3eae
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf3eb0 eltorito.c:354
+ jmp near 040eah ; e9 34 02 ; 0xf3eb3
+ cmp byte [bp-00826h], 001h ; 80 be da f7 01 ; 0xf3eb6 eltorito.c:359
+ je short 03ec3h ; 74 06 ; 0xf3ebb
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf3ebd eltorito.c:360
+ jmp near 040eah ; e9 27 02 ; 0xf3ec0
+ cmp byte [bp-00825h], 000h ; 80 be db f7 00 ; 0xf3ec3 eltorito.c:361
+ je short 03ed0h ; 74 06 ; 0xf3ec8
+ mov ax, strict word 00009h ; b8 09 00 ; 0xf3eca eltorito.c:362
+ jmp near 040eah ; e9 1a 02 ; 0xf3ecd
+ cmp byte [bp-00808h], 055h ; 80 be f8 f7 55 ; 0xf3ed0 eltorito.c:363
+ je short 03eddh ; 74 06 ; 0xf3ed5
+ mov ax, strict word 0000ah ; b8 0a 00 ; 0xf3ed7 eltorito.c:364
+ jmp near 040eah ; e9 0d 02 ; 0xf3eda
+ cmp byte [bp-00807h], 0aah ; 80 be f9 f7 aa ; 0xf3edd eltorito.c:365
+ jne short 03ed7h ; 75 f3 ; 0xf3ee2
+ cmp byte [bp-00806h], 088h ; 80 be fa f7 88 ; 0xf3ee4 eltorito.c:366
+ je short 03ef1h ; 74 06 ; 0xf3ee9
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf3eeb eltorito.c:370
+ jmp near 040eah ; e9 f9 01 ; 0xf3eee
+ mov al, byte [bp-00805h] ; 8a 86 fb f7 ; 0xf3ef1 eltorito.c:372
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf3ef5
+ mov byte [es:si+001h], al ; 26 88 44 01 ; 0xf3ef8
+ cmp byte [bp-00805h], 000h ; 80 be fb f7 00 ; 0xf3efc eltorito.c:373
+ jne short 03f0ah ; 75 07 ; 0xf3f01
+ mov byte [es:si+002h], 0e0h ; 26 c6 44 02 e0 ; 0xf3f03 eltorito.c:376
+ jmp short 03f1dh ; eb 13 ; 0xf3f08 eltorito.c:378
+ cmp byte [bp-00805h], 004h ; 80 be fb f7 04 ; 0xf3f0a
+ jnc short 03f18h ; 73 07 ; 0xf3f0f
+ mov byte [es:si+002h], 000h ; 26 c6 44 02 00 ; 0xf3f11 eltorito.c:379
+ jmp short 03f1dh ; eb 05 ; 0xf3f16 eltorito.c:380
+ mov byte [es:si+002h], 080h ; 26 c6 44 02 80 ; 0xf3f18 eltorito.c:381
+ mov bl, byte [bp-00ch] ; 8a 5e f4 ; 0xf3f1d eltorito.c:383
+ xor bh, bh ; 30 ff ; 0xf3f20
+ mov ax, bx ; 89 d8 ; 0xf3f22
+ cwd ; 99 ; 0xf3f24
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf3f25
+ sar ax, 1 ; d1 f8 ; 0xf3f27
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf3f29
+ mov byte [es:si+003h], al ; 26 88 44 03 ; 0xf3f2c
+ mov ax, bx ; 89 d8 ; 0xf3f30 eltorito.c:384
+ cwd ; 99 ; 0xf3f32
+ mov bx, strict word 00002h ; bb 02 00 ; 0xf3f33
+ idiv bx ; f7 fb ; 0xf3f36
+ mov word [es:si+004h], dx ; 26 89 54 04 ; 0xf3f38
+ mov ax, word [bp-00804h] ; 8b 86 fc f7 ; 0xf3f3c eltorito.c:386
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf3f40
+ test ax, ax ; 85 c0 ; 0xf3f43 eltorito.c:387
+ jne short 03f4ch ; 75 05 ; 0xf3f45
+ mov word [bp-016h], 007c0h ; c7 46 ea c0 07 ; 0xf3f47 eltorito.c:388
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf3f4c eltorito.c:390
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf3f4f
+ mov word [es:si+00ch], ax ; 26 89 44 0c ; 0xf3f52
+ mov word [es:si+006h], strict word 00000h ; 26 c7 44 06 00 00 ; 0xf3f56 eltorito.c:391
+ mov di, word [bp-00800h] ; 8b be 00 f8 ; 0xf3f5c eltorito.c:393
+ mov word [es:si+00eh], di ; 26 89 7c 0e ; 0xf3f60 eltorito.c:394
+ test di, di ; 85 ff ; 0xf3f64 eltorito.c:399
+ je short 03f6eh ; 74 06 ; 0xf3f66
+ cmp di, 00400h ; 81 ff 00 04 ; 0xf3f68
+ jbe short 03f74h ; 76 06 ; 0xf3f6c
+ mov ax, strict word 0000ch ; b8 0c 00 ; 0xf3f6e eltorito.c:400
+ jmp near 040eah ; e9 76 01 ; 0xf3f71
+ mov ax, word [bp-007feh] ; 8b 86 02 f8 ; 0xf3f74 eltorito.c:402
+ mov dx, word [bp-007fch] ; 8b 96 04 f8 ; 0xf3f78
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf3f7c eltorito.c:403
+ mov word [es:si+00ah], dx ; 26 89 54 0a ; 0xf3f80
+ mov word [bp-026h], strict word 00028h ; c7 46 da 28 00 ; 0xf3f84 eltorito.c:409
+ xchg ah, al ; 86 c4 ; 0xf3f89 eltorito.c:410
+ xchg dh, dl ; 86 d6 ; 0xf3f8b
+ xchg dx, ax ; 92 ; 0xf3f8d
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf3f8e
+ mov word [bp-022h], dx ; 89 56 de ; 0xf3f91
+ lea dx, [di-001h] ; 8d 55 ff ; 0xf3f94 eltorito.c:411
+ shr dx, 002h ; c1 ea 02 ; 0xf3f97
+ inc dx ; 42 ; 0xf3f9a
+ mov ax, dx ; 89 d0 ; 0xf3f9b
+ xchg ah, al ; 86 c4 ; 0xf3f9d
+ mov word [bp-01fh], ax ; 89 46 e1 ; 0xf3f9f
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf3fa2 eltorito.c:413
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf3fa5
+ mov word [es:bx+00eh], dx ; 26 89 57 0e ; 0xf3fa8
+ mov word [es:bx+010h], 00200h ; 26 c7 47 10 00 02 ; 0xf3fac eltorito.c:414
+ mov ax, di ; 89 f8 ; 0xf3fb2 eltorito.c:416
+ sal ax, 009h ; c1 e0 09 ; 0xf3fb4
+ mov dx, 00800h ; ba 00 08 ; 0xf3fb7
+ sub dx, ax ; 29 c2 ; 0xf3fba
+ mov ax, dx ; 89 d0 ; 0xf3fbc
+ and ah, 007h ; 80 e4 07 ; 0xf3fbe
+ mov word [es:bx+020h], ax ; 26 89 47 20 ; 0xf3fc1
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3fc5 eltorito.c:418
+ xor ah, ah ; 30 e4 ; 0xf3fc8
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf3fca
+ add bx, ax ; 01 c3 ; 0xf3fcd
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf3fcf
+ xor ah, ah ; 30 e4 ; 0xf3fd3
+ add ax, ax ; 01 c0 ; 0xf3fd5
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf3fd7
+ push word [bp-016h] ; ff 76 ea ; 0xf3fda
+ push strict byte 00000h ; 6a 00 ; 0xf3fdd
+ push strict byte 00001h ; 6a 01 ; 0xf3fdf
+ mov ax, di ; 89 f8 ; 0xf3fe1
+ xor di, di ; 31 ff ; 0xf3fe3
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf3fe5
+ sal ax, 1 ; d1 e0 ; 0xf3fe8
+ rcl di, 1 ; d1 d7 ; 0xf3fea
+ loop 03fe8h ; e2 fa ; 0xf3fec
+ push di ; 57 ; 0xf3fee
+ push ax ; 50 ; 0xf3fef
+ push strict byte 00000h ; 6a 00 ; 0xf3ff0
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3ff2
+ xor ah, ah ; 30 e4 ; 0xf3ff5
+ mov cx, ss ; 8c d1 ; 0xf3ff7
+ lea bx, [bp-026h] ; 8d 5e da ; 0xf3ff9
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3ffc
+ mov di, word [bp-01ah] ; 8b 7e e6 ; 0xf3fff
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf4002
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf4006 eltorito.c:420
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf4009
+ mov word [es:bx+020h], strict word 00000h ; 26 c7 47 20 00 00 ; 0xf400c
+ test ax, ax ; 85 c0 ; 0xf4012 eltorito.c:422
+ je short 0401ch ; 74 06 ; 0xf4014
+ mov ax, strict word 0000dh ; b8 0d 00 ; 0xf4016 eltorito.c:423
+ jmp near 040eah ; e9 ce 00 ; 0xf4019
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf401c eltorito.c:428
+ mov al, byte [es:si+001h] ; 26 8a 44 01 ; 0xf401f
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf4023
+ jc short 04033h ; 72 0c ; 0xf4025
+ jbe short 0404eh ; 76 25 ; 0xf4027
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf4029
+ je short 0405eh ; 74 31 ; 0xf402b
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf402d
+ je short 04056h ; 74 25 ; 0xf402f
+ jmp short 040a2h ; eb 6f ; 0xf4031
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf4033
+ jne short 040a2h ; 75 6b ; 0xf4035
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf4037 eltorito.c:430
+ mov word [es:si+014h], strict word 0000fh ; 26 c7 44 14 0f 00 ; 0xf403a
+ mov word [es:si+012h], strict word 00050h ; 26 c7 44 12 50 00 ; 0xf4040 eltorito.c:431
+ mov word [es:si+010h], strict word 00002h ; 26 c7 44 10 02 00 ; 0xf4046 eltorito.c:432
+ jmp short 040a2h ; eb 54 ; 0xf404c eltorito.c:433
+ mov word [es:si+014h], strict word 00012h ; 26 c7 44 14 12 00 ; 0xf404e eltorito.c:435
+ jmp short 04040h ; eb ea ; 0xf4054
+ mov word [es:si+014h], strict word 00024h ; 26 c7 44 14 24 00 ; 0xf4056 eltorito.c:440
+ jmp short 04040h ; eb e2 ; 0xf405c
+ mov bx, 001c4h ; bb c4 01 ; 0xf405e eltorito.c:38
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf4061
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4064
+ and AL, strict byte 03fh ; 24 3f ; 0xf4067 eltorito.c:39
+ xor ah, ah ; 30 e4 ; 0xf4069
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf406b
+ mov word [es:si+014h], ax ; 26 89 44 14 ; 0xf406e
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf4072 eltorito.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4075
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf4078 eltorito.c:39
+ mov dx, ax ; 89 c2 ; 0xf407a
+ sal dx, 002h ; c1 e2 02 ; 0xf407c
+ mov bx, 001c5h ; bb c5 01 ; 0xf407f eltorito.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4082
+ add ax, dx ; 01 d0 ; 0xf4085 eltorito.c:39
+ inc ax ; 40 ; 0xf4087
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf4088
+ mov word [es:si+012h], ax ; 26 89 44 12 ; 0xf408b
+ mov bx, 001c3h ; bb c3 01 ; 0xf408f eltorito.c:38
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf4092
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4095
+ xor ah, ah ; 30 e4 ; 0xf4098 eltorito.c:39
+ inc ax ; 40 ; 0xf409a
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf409b
+ mov word [es:si+010h], ax ; 26 89 44 10 ; 0xf409e
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf40a2 eltorito.c:453
+ cmp byte [es:si+001h], 000h ; 26 80 7c 01 00 ; 0xf40a5
+ je short 040d0h ; 74 24 ; 0xf40aa
+ cmp byte [es:si+002h], 000h ; 26 80 7c 02 00 ; 0xf40ac eltorito.c:455
+ jne short 040c2h ; 75 0f ; 0xf40b1
+ mov bx, strict word 00010h ; bb 10 00 ; 0xf40b3 eltorito.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf40b6
+ mov es, ax ; 8e c0 ; 0xf40b9
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf40bb
+ or AL, strict byte 041h ; 0c 41 ; 0xf40be eltorito.c:39
+ jmp short 040cdh ; eb 0b ; 0xf40c0 eltorito.c:457
+ mov bx, 00304h ; bb 04 03 ; 0xf40c2 eltorito.c:38
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf40c5
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf40c8
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf40cb eltorito.c:39
+ mov byte [es:bx], al ; 26 88 07 ; 0xf40cd eltorito.c:43
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf40d0 eltorito.c:462
+ cmp byte [es:si+001h], 000h ; 26 80 7c 01 00 ; 0xf40d3
+ je short 040deh ; 74 04 ; 0xf40d8
+ mov byte [es:si], 001h ; 26 c6 04 01 ; 0xf40da eltorito.c:463
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf40de eltorito.c:466
+ mov al, byte [es:si+002h] ; 26 8a 44 02 ; 0xf40e1
+ xor ah, ah ; 30 e4 ; 0xf40e5
+ sal ax, 008h ; c1 e0 08 ; 0xf40e7
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf40ea eltorito.c:467
+ pop di ; 5f ; 0xf40ed
+ pop si ; 5e ; 0xf40ee
+ pop dx ; 5a ; 0xf40ef
+ pop cx ; 59 ; 0xf40f0
+ pop bx ; 5b ; 0xf40f1
+ pop bp ; 5d ; 0xf40f2
+ retn ; c3 ; 0xf40f3
+ ; disGetNextSymbol 0xf40f4 LB 0x5dd4 -> off=0x59 cb=00000000000005e8 uValue=00000000000f2b4d 'int13_cdemu'
+ db 050h, 04eh, 049h, 048h, 047h, 046h, 045h, 044h, 043h, 042h, 041h, 018h, 016h, 015h, 014h, 011h
+ db 010h, 00dh, 00ch, 00bh, 00ah, 009h, 008h, 005h, 004h, 003h, 002h, 001h, 000h, 018h, 047h, 0f7h
+ db 041h, 02ah, 042h, 052h, 042h, 01fh, 042h, 052h, 042h, 01fh, 042h, 06dh, 044h, 052h, 044h, 018h
+ db 047h, 018h, 047h, 052h, 044h, 052h, 044h, 052h, 044h, 052h, 044h, 052h, 044h, 014h, 045h, 052h
+ db 044h, 018h, 047h, 01dh, 045h, 030h, 045h, 018h, 047h, 030h, 045h, 018h, 047h, 018h, 047h, 030h
+ db 045h, 0ddh, 046h, 018h, 047h, 018h, 047h, 018h, 047h
+int13_cdemu: ; 0xf414d LB 0x5e8
+ push bp ; 55 ; 0xf414d eltorito.c:477
+ mov bp, sp ; 89 e5 ; 0xf414e
+ push si ; 56 ; 0xf4150
+ push di ; 57 ; 0xf4151
+ sub sp, strict byte 00038h ; 83 ec 38 ; 0xf4152
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf4155 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4158
+ mov es, ax ; 8e c0 ; 0xf415b
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf415d
+ mov dx, 00366h ; ba 66 03 ; 0xf4160 eltorito.c:493
+ mov cx, ax ; 89 c1 ; 0xf4163
+ mov bx, dx ; 89 d3 ; 0xf4165
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf4167
+ mov si, 00122h ; be 22 01 ; 0xf416a eltorito.c:494
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf416d
+ mov es, ax ; 8e c0 ; 0xf4170 eltorito.c:501
+ mov di, dx ; 89 d7 ; 0xf4172
+ mov al, byte [es:di+003h] ; 26 8a 45 03 ; 0xf4174
+ add al, al ; 00 c0 ; 0xf4178
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf417a
+ mov al, byte [es:di+004h] ; 26 8a 45 04 ; 0xf417d eltorito.c:502
+ add byte [bp-006h], al ; 00 46 fa ; 0xf4181
+ mov di, strict word 00074h ; bf 74 00 ; 0xf4184 eltorito.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4187
+ mov es, ax ; 8e c0 ; 0xf418a
+ mov byte [es:di], 000h ; 26 c6 05 00 ; 0xf418c
+ mov es, cx ; 8e c1 ; 0xf4190 eltorito.c:507
+ mov di, dx ; 89 d7 ; 0xf4192
+ cmp byte [es:di], 000h ; 26 80 3d 00 ; 0xf4194
+ je short 041a9h ; 74 0f ; 0xf4198
+ mov al, byte [es:di+002h] ; 26 8a 45 02 ; 0xf419a
+ xor ah, ah ; 30 e4 ; 0xf419e
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf41a0
+ xor dh, dh ; 30 f6 ; 0xf41a3
+ cmp ax, dx ; 39 d0 ; 0xf41a5
+ je short 041d2h ; 74 29 ; 0xf41a7
+ mov bx, 00da0h ; bb a0 0d ; 0xf41a9 eltorito.c:508
+ mov cx, ds ; 8c d9 ; 0xf41ac
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf41ae
+ call 018bch ; e8 08 d7 ; 0xf41b1
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf41b4
+ xor ah, ah ; 30 e4 ; 0xf41b7
+ push ax ; 50 ; 0xf41b9
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf41ba
+ shr ax, 008h ; c1 e8 08 ; 0xf41bd
+ push ax ; 50 ; 0xf41c0
+ push 0034ch ; 68 4c 03 ; 0xf41c1
+ push 00358h ; 68 58 03 ; 0xf41c4
+ push strict byte 00004h ; 6a 04 ; 0xf41c7
+ call 018ffh ; e8 33 d7 ; 0xf41c9
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf41cc
+ jmp near 046f5h ; e9 23 05 ; 0xf41cf eltorito.c:509
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf41d2 eltorito.c:512
+ shr ax, 008h ; c1 e8 08 ; 0xf41d5
+ cmp ax, strict word 00050h ; 3d 50 00 ; 0xf41d8
+ jnbe short 0424fh ; 77 72 ; 0xf41db
+ push CS ; 0e ; 0xf41dd
+ pop ES ; 07 ; 0xf41de
+ mov cx, strict word 0001eh ; b9 1e 00 ; 0xf41df
+ mov di, 040f4h ; bf f4 40 ; 0xf41e2
+ repne scasb ; f2 ae ; 0xf41e5
+ sal cx, 1 ; d1 e1 ; 0xf41e7
+ mov di, cx ; 89 cf ; 0xf41e9
+ mov ax, word [cs:di+04111h] ; 2e 8b 85 11 41 ; 0xf41eb
+ mov dx, word [bp+016h] ; 8b 56 16 ; 0xf41f0
+ xor dh, dh ; 30 f6 ; 0xf41f3
+ jmp ax ; ff e0 ; 0xf41f5
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf41f7 eltorito.c:515
+ xor ah, ah ; 30 e4 ; 0xf41fa
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf41fc
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf41ff
+ add si, ax ; 01 c6 ; 0xf4202
+ mov bl, byte [es:si+022h] ; 26 8a 5c 22 ; 0xf4204
+ xor bh, bh ; 30 ff ; 0xf4208
+ add bx, bx ; 01 db ; 0xf420a
+ cmp word [word bx+0006ah], strict byte 00000h ; 83 bf 6a 00 00 ; 0xf420c
+ je short 0421ch ; 74 09 ; 0xf4211
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4213 eltorito.c:517
+ xor ah, ah ; 30 e4 ; 0xf4216
+ call word [word bx+00076h] ; ff 97 76 00 ; 0xf4218
+ jmp near 04452h ; e9 33 02 ; 0xf421c eltorito.c:519
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf421f eltorito.c:535
+ xor ah, ah ; 30 e4 ; 0xf4222
+ or ah, 003h ; 80 cc 03 ; 0xf4224
+ jmp near 046fdh ; e9 d3 04 ; 0xf4227 eltorito.c:536
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf422a eltorito.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf422d
+ mov es, ax ; 8e c0 ; 0xf4230
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4232
+ mov bl, al ; 88 c3 ; 0xf4235 eltorito.c:541
+ xor bh, bh ; 30 ff ; 0xf4237
+ sal bx, 008h ; c1 e3 08 ; 0xf4239
+ or dx, bx ; 09 da ; 0xf423c
+ mov word [bp+016h], dx ; 89 56 16 ; 0xf423e
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4241 eltorito.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf4244
+ test al, al ; 84 c0 ; 0xf4248 eltorito.c:545
+ je short 042b0h ; 74 64 ; 0xf424a
+ jmp near 04711h ; e9 c2 04 ; 0xf424c eltorito.c:546
+ jmp near 04718h ; e9 c6 04 ; 0xf424f
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf4252 eltorito.c:553
+ mov ax, word [es:bx+014h] ; 26 8b 47 14 ; 0xf4255
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf4259
+ mov dx, word [es:bx+012h] ; 26 8b 57 12 ; 0xf425c eltorito.c:554
+ mov ax, word [es:bx+010h] ; 26 8b 47 10 ; 0xf4260 eltorito.c:555
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf4264
+ mov ax, word [es:bx+008h] ; 26 8b 47 08 ; 0xf4267 eltorito.c:556
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf426b
+ mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xf426e
+ mov word [bp-020h], ax ; 89 46 e0 ; 0xf4272
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf4275 eltorito.c:558
+ and ax, strict word 0003fh ; 25 3f 00 ; 0xf4278
+ mov word [bp-022h], ax ; 89 46 de ; 0xf427b
+ mov bx, word [bp+014h] ; 8b 5e 14 ; 0xf427e eltorito.c:559
+ and bx, 000c0h ; 81 e3 c0 00 ; 0xf4281
+ sal bx, 002h ; c1 e3 02 ; 0xf4285
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf4288
+ shr ax, 008h ; c1 e8 08 ; 0xf428b
+ or ax, bx ; 09 d8 ; 0xf428e
+ mov bx, word [bp+012h] ; 8b 5e 12 ; 0xf4290 eltorito.c:560
+ shr bx, 008h ; c1 eb 08 ; 0xf4293
+ mov word [bp-012h], bx ; 89 5e ee ; 0xf4296
+ mov di, word [bp+016h] ; 8b 7e 16 ; 0xf4299 eltorito.c:561
+ and di, 000ffh ; 81 e7 ff 00 ; 0xf429c
+ je short 042c9h ; 74 27 ; 0xf42a0 eltorito.c:569
+ mov bx, word [bp-022h] ; 8b 5e de ; 0xf42a2 eltorito.c:573
+ cmp bx, word [bp-00eh] ; 3b 5e f2 ; 0xf42a5
+ jnbe short 042bbh ; 77 11 ; 0xf42a8
+ cmp ax, dx ; 39 d0 ; 0xf42aa
+ jc short 042b3h ; 72 05 ; 0xf42ac
+ jmp short 042bbh ; eb 0b ; 0xf42ae
+ jmp near 04456h ; e9 a3 01 ; 0xf42b0
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf42b3
+ cmp dx, word [bp-00ch] ; 3b 56 f4 ; 0xf42b6
+ jc short 042beh ; 72 03 ; 0xf42b9
+ jmp near 046f5h ; e9 37 04 ; 0xf42bb eltorito.c:576
+ mov dx, word [bp+016h] ; 8b 56 16 ; 0xf42be eltorito.c:580
+ shr dx, 008h ; c1 ea 08 ; 0xf42c1
+ cmp dx, strict byte 00004h ; 83 fa 04 ; 0xf42c4
+ jne short 042cch ; 75 03 ; 0xf42c7
+ jmp near 04452h ; e9 86 01 ; 0xf42c9 eltorito.c:581
+ mov dx, word [bp+010h] ; 8b 56 10 ; 0xf42cc eltorito.c:583
+ shr dx, 004h ; c1 ea 04 ; 0xf42cf
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf42d2
+ add bx, dx ; 01 d3 ; 0xf42d5
+ mov word [bp-014h], bx ; 89 5e ec ; 0xf42d7
+ mov dx, word [bp+010h] ; 8b 56 10 ; 0xf42da eltorito.c:584
+ and dx, strict byte 0000fh ; 83 e2 0f ; 0xf42dd
+ mov word [bp-016h], dx ; 89 56 ea ; 0xf42e0
+ xor dl, dl ; 30 d2 ; 0xf42e3 eltorito.c:587
+ mov bx, word [bp-00ch] ; 8b 5e f4 ; 0xf42e5
+ xor cx, cx ; 31 c9 ; 0xf42e8
+ call 09b40h ; e8 53 58 ; 0xf42ea
+ xor bx, bx ; 31 db ; 0xf42ed
+ add ax, word [bp-012h] ; 03 46 ee ; 0xf42ef
+ adc dx, bx ; 11 da ; 0xf42f2
+ mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xf42f4
+ xor cx, cx ; 31 c9 ; 0xf42f7
+ call 09b40h ; e8 44 58 ; 0xf42f9
+ mov bx, dx ; 89 d3 ; 0xf42fc
+ mov dx, word [bp-022h] ; 8b 56 de ; 0xf42fe
+ dec dx ; 4a ; 0xf4301
+ mov word [bp-024h], strict word 00000h ; c7 46 dc 00 00 ; 0xf4302
+ add dx, ax ; 01 c2 ; 0xf4307
+ adc bx, word [bp-024h] ; 13 5e dc ; 0xf4309
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf430c eltorito.c:590
+ xor al, al ; 30 c0 ; 0xf430f
+ or ax, di ; 09 f8 ; 0xf4311
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf4313
+ mov word [bp-030h], dx ; 89 56 d0 ; 0xf4316 eltorito.c:593
+ mov word [bp-02eh], bx ; 89 5e d2 ; 0xf4319
+ shr word [bp-02eh], 1 ; d1 6e d2 ; 0xf431c
+ rcr word [bp-030h], 1 ; d1 5e d0 ; 0xf431f
+ shr word [bp-02eh], 1 ; d1 6e d2 ; 0xf4322
+ rcr word [bp-030h], 1 ; d1 5e d0 ; 0xf4325
+ mov ax, word [bp-02eh] ; 8b 46 d2 ; 0xf4328
+ mov word [bp-026h], ax ; 89 46 da ; 0xf432b
+ mov ax, dx ; 89 d0 ; 0xf432e eltorito.c:594
+ xor ah, dh ; 30 f4 ; 0xf4330
+ and AL, strict byte 003h ; 24 03 ; 0xf4332
+ mov word [bp-028h], ax ; 89 46 d8 ; 0xf4334
+ xor cx, cx ; 31 c9 ; 0xf4337 eltorito.c:597
+ mov ax, dx ; 89 d0 ; 0xf4339
+ add ax, di ; 01 f8 ; 0xf433b
+ mov dx, bx ; 89 da ; 0xf433d
+ adc dx, cx ; 11 ca ; 0xf433f
+ mov bx, ax ; 89 c3 ; 0xf4341
+ add bx, strict byte 0ffffh ; 83 c3 ff ; 0xf4343
+ mov ax, dx ; 89 d0 ; 0xf4346
+ adc ax, strict word 0ffffh ; 15 ff ff ; 0xf4348
+ mov word [bp-02ch], bx ; 89 5e d4 ; 0xf434b
+ mov word [bp-02ah], ax ; 89 46 d6 ; 0xf434e
+ shr word [bp-02ah], 1 ; d1 6e d6 ; 0xf4351
+ rcr word [bp-02ch], 1 ; d1 5e d4 ; 0xf4354
+ shr word [bp-02ah], 1 ; d1 6e d6 ; 0xf4357
+ rcr word [bp-02ch], 1 ; d1 5e d4 ; 0xf435a
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf435d eltorito.c:599
+ xor bx, bx ; 31 db ; 0xf4360
+ mov dx, ss ; 8c d2 ; 0xf4362
+ lea ax, [bp-03ch] ; 8d 46 c4 ; 0xf4364
+ call 09bb0h ; e8 46 58 ; 0xf4367
+ mov word [bp-03ch], strict word 00028h ; c7 46 c4 28 00 ; 0xf436a eltorito.c:600
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf436f eltorito.c:601
+ add ax, word [bp-030h] ; 03 46 d0 ; 0xf4372
+ mov dx, word [bp-020h] ; 8b 56 e0 ; 0xf4375
+ adc dx, word [bp-026h] ; 13 56 da ; 0xf4378
+ xchg ah, al ; 86 c4 ; 0xf437b
+ xchg dh, dl ; 86 d6 ; 0xf437d
+ xchg dx, ax ; 92 ; 0xf437f
+ mov word [bp-03ah], ax ; 89 46 c6 ; 0xf4380
+ mov word [bp-038h], dx ; 89 56 c8 ; 0xf4383
+ mov ax, word [bp-02ch] ; 8b 46 d4 ; 0xf4386 eltorito.c:602
+ sub ax, word [bp-030h] ; 2b 46 d0 ; 0xf4389
+ inc ax ; 40 ; 0xf438c
+ xchg ah, al ; 86 c4 ; 0xf438d
+ mov word [bp-035h], ax ; 89 46 cb ; 0xf438f
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4392 eltorito.c:604
+ mov word [es:si+00eh], di ; 26 89 7c 0e ; 0xf4395
+ mov word [es:si+010h], 00200h ; 26 c7 44 10 00 02 ; 0xf4399 eltorito.c:605
+ mov dx, word [bp-028h] ; 8b 56 d8 ; 0xf439f eltorito.c:607
+ sal dx, 009h ; c1 e2 09 ; 0xf43a2
+ mov word [es:si+01eh], dx ; 26 89 54 1e ; 0xf43a5
+ mov ax, di ; 89 f8 ; 0xf43a9 eltorito.c:608
+ xor ah, ah ; 30 e4 ; 0xf43ab
+ and AL, strict byte 003h ; 24 03 ; 0xf43ad
+ mov bx, strict word 00004h ; bb 04 00 ; 0xf43af
+ sub bx, ax ; 29 c3 ; 0xf43b2
+ mov ax, bx ; 89 d8 ; 0xf43b4
+ sub ax, word [bp-028h] ; 2b 46 d8 ; 0xf43b6
+ sal ax, 009h ; c1 e0 09 ; 0xf43b9
+ and ah, 007h ; 80 e4 07 ; 0xf43bc
+ mov word [es:si+020h], ax ; 26 89 44 20 ; 0xf43bf
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf43c3 eltorito.c:610
+ xor ah, ah ; 30 e4 ; 0xf43c6
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf43c8
+ mov bx, si ; 89 f3 ; 0xf43cb
+ add bx, ax ; 01 c3 ; 0xf43cd
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf43cf
+ xor ah, ah ; 30 e4 ; 0xf43d3
+ add ax, ax ; 01 c0 ; 0xf43d5
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf43d7
+ push word [bp-014h] ; ff 76 ec ; 0xf43da
+ push word [bp-016h] ; ff 76 ea ; 0xf43dd
+ push strict byte 00001h ; 6a 01 ; 0xf43e0
+ mov bx, di ; 89 fb ; 0xf43e2
+ xor di, di ; 31 ff ; 0xf43e4
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf43e6
+ sal bx, 1 ; d1 e3 ; 0xf43e9
+ rcl di, 1 ; d1 d7 ; 0xf43eb
+ loop 043e9h ; e2 fa ; 0xf43ed
+ push di ; 57 ; 0xf43ef
+ push bx ; 53 ; 0xf43f0
+ push dx ; 52 ; 0xf43f1
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf43f2
+ xor ah, ah ; 30 e4 ; 0xf43f5
+ mov cx, ss ; 8c d1 ; 0xf43f7
+ lea bx, [bp-03ch] ; 8d 5e c4 ; 0xf43f9
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf43fc
+ mov di, word [bp-024h] ; 8b 7e dc ; 0xf43ff
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf4402
+ mov dx, ax ; 89 c2 ; 0xf4406
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4408 eltorito.c:612
+ mov word [es:si+01eh], strict word 00000h ; 26 c7 44 1e 00 00 ; 0xf440b
+ mov word [es:si+020h], strict word 00000h ; 26 c7 44 20 00 00 ; 0xf4411 eltorito.c:613
+ test al, al ; 84 c0 ; 0xf4417 eltorito.c:615
+ je short 04452h ; 74 37 ; 0xf4419
+ mov bx, 00da0h ; bb a0 0d ; 0xf441b eltorito.c:616
+ mov cx, ds ; 8c d9 ; 0xf441e
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4420
+ call 018bch ; e8 96 d4 ; 0xf4423
+ mov al, dl ; 88 d0 ; 0xf4426
+ xor ah, ah ; 30 e4 ; 0xf4428
+ push ax ; 50 ; 0xf442a
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf442b
+ shr ax, 008h ; c1 e8 08 ; 0xf442e
+ push ax ; 50 ; 0xf4431
+ push 0034ch ; 68 4c 03 ; 0xf4432
+ push 0038eh ; 68 8e 03 ; 0xf4435
+ push strict byte 00004h ; 6a 04 ; 0xf4438
+ call 018ffh ; e8 c2 d4 ; 0xf443a
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf443d
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf4440 eltorito.c:617
+ xor ah, ah ; 30 e4 ; 0xf4443
+ or ah, 002h ; 80 cc 02 ; 0xf4445
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf4448
+ mov byte [bp+016h], 000h ; c6 46 16 00 ; 0xf444b eltorito.c:618
+ jmp near 04700h ; e9 ae 02 ; 0xf444f eltorito.c:619
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf4452
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4456
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4459
+ mov es, ax ; 8e c0 ; 0xf445c
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf445e
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf4462
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf4466
+ pop di ; 5f ; 0xf4469
+ pop si ; 5e ; 0xf446a
+ pop bp ; 5d ; 0xf446b
+ retn ; c3 ; 0xf446c
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf446d eltorito.c:626
+ mov ax, word [es:bx+014h] ; 26 8b 47 14 ; 0xf4470
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf4474
+ mov dx, word [es:bx+012h] ; 26 8b 57 12 ; 0xf4477 eltorito.c:627
+ dec dx ; 4a ; 0xf447b
+ mov ax, word [es:bx+010h] ; 26 8b 47 10 ; 0xf447c eltorito.c:628
+ dec ax ; 48 ; 0xf4480
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf4481
+ mov byte [bp+016h], 000h ; c6 46 16 00 ; 0xf4484 eltorito.c:630
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf4488 eltorito.c:631
+ xor al, al ; 30 c0 ; 0xf448b
+ mov si, word [bp+014h] ; 8b 76 14 ; 0xf448d eltorito.c:632
+ and si, 000ffh ; 81 e6 ff 00 ; 0xf4490
+ mov cx, dx ; 89 d1 ; 0xf4494
+ xor ch, dh ; 30 f5 ; 0xf4496
+ sal cx, 008h ; c1 e1 08 ; 0xf4498
+ or si, cx ; 09 ce ; 0xf449b
+ mov word [bp+014h], si ; 89 76 14 ; 0xf449d
+ mov cx, dx ; 89 d1 ; 0xf44a0 eltorito.c:633
+ shr cx, 002h ; c1 e9 02 ; 0xf44a2
+ and cl, 0c0h ; 80 e1 c0 ; 0xf44a5
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf44a8
+ and dl, 03fh ; 80 e2 3f ; 0xf44ab
+ or cl, dl ; 08 d1 ; 0xf44ae
+ mov dx, si ; 89 f2 ; 0xf44b0
+ mov dl, cl ; 88 ca ; 0xf44b2
+ mov word [bp+014h], dx ; 89 56 14 ; 0xf44b4
+ mov cx, word [bp+012h] ; 8b 4e 12 ; 0xf44b7 eltorito.c:634
+ xor ch, ch ; 30 ed ; 0xf44ba
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf44bc
+ sal dx, 008h ; c1 e2 08 ; 0xf44bf
+ or cx, dx ; 09 d1 ; 0xf44c2
+ mov word [bp+012h], cx ; 89 4e 12 ; 0xf44c4
+ mov dx, cx ; 89 ca ; 0xf44c7 eltorito.c:635
+ xor dl, cl ; 30 ca ; 0xf44c9
+ or dl, 002h ; 80 ca 02 ; 0xf44cb
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf44ce
+ mov dl, byte [es:bx+001h] ; 26 8a 57 01 ; 0xf44d1 eltorito.c:638
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf44d5
+ cmp dl, 003h ; 80 fa 03 ; 0xf44d8
+ je short 044f7h ; 74 1a ; 0xf44db
+ cmp dl, 002h ; 80 fa 02 ; 0xf44dd
+ je short 044f3h ; 74 11 ; 0xf44e0
+ cmp dl, 001h ; 80 fa 01 ; 0xf44e2
+ jne short 044fbh ; 75 14 ; 0xf44e5
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf44e7 eltorito.c:639
+ xor al, al ; 30 c0 ; 0xf44ea
+ or AL, strict byte 002h ; 0c 02 ; 0xf44ec
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf44ee
+ jmp short 044fbh ; eb 08 ; 0xf44f1
+ or AL, strict byte 004h ; 0c 04 ; 0xf44f3 eltorito.c:640
+ jmp short 044eeh ; eb f7 ; 0xf44f5
+ or AL, strict byte 005h ; 0c 05 ; 0xf44f7 eltorito.c:641
+ jmp short 044eeh ; eb f3 ; 0xf44f9
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf44fb eltorito.c:645
+ cmp byte [es:bx+001h], 004h ; 26 80 7f 01 04 ; 0xf44fe
+ jc short 04508h ; 72 03 ; 0xf4503
+ jmp near 04452h ; e9 4a ff ; 0xf4505
+ mov word [bp+008h], 0efc7h ; c7 46 08 c7 ef ; 0xf4508 eltorito.c:646
+ mov word [bp+006h], 0f000h ; c7 46 06 00 f0 ; 0xf450d eltorito.c:647
+ jmp short 04505h ; eb f1 ; 0xf4512 eltorito.c:649
+ or dh, 003h ; 80 ce 03 ; 0xf4514 eltorito.c:654
+ mov word [bp+016h], dx ; 89 56 16 ; 0xf4517
+ jmp near 04456h ; e9 39 ff ; 0xf451a eltorito.c:655
+ mov word [bp+010h], 0aa55h ; c7 46 10 55 aa ; 0xf451d eltorito.c:659
+ or dh, 030h ; 80 ce 30 ; 0xf4522 eltorito.c:660
+ mov word [bp+016h], dx ; 89 56 16 ; 0xf4525
+ mov word [bp+014h], strict word 00007h ; c7 46 14 07 00 ; 0xf4528 eltorito.c:661
+ jmp near 04456h ; e9 26 ff ; 0xf452d eltorito.c:662
+ mov di, word [bp+00ah] ; 8b 7e 0a ; 0xf4530 eltorito.c:670
+ mov es, [bp+004h] ; 8e 46 04 ; 0xf4533
+ mov word [bp-01ah], di ; 89 7e e6 ; 0xf4536
+ mov [bp-018h], es ; 8c 46 e8 ; 0xf4539
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf453c eltorito.c:672
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf4540
+ mov ax, word [es:di+006h] ; 26 8b 45 06 ; 0xf4543 eltorito.c:673
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf4547
+ mov ax, word [es:di+004h] ; 26 8b 45 04 ; 0xf454a eltorito.c:674
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf454e
+ mov ax, word [es:di+00ch] ; 26 8b 45 0c ; 0xf4551 eltorito.c:677
+ mov dx, word [es:di+00eh] ; 26 8b 55 0e ; 0xf4555
+ or ax, dx ; 09 d0 ; 0xf4559 eltorito.c:678
+ je short 04575h ; 74 18 ; 0xf455b
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf455d eltorito.c:679
+ shr ax, 008h ; c1 e8 08 ; 0xf4560
+ push ax ; 50 ; 0xf4563
+ push 0034ch ; 68 4c 03 ; 0xf4564
+ push 003afh ; 68 af 03 ; 0xf4567
+ push strict byte 00007h ; 6a 07 ; 0xf456a
+ call 018ffh ; e8 90 d3 ; 0xf456c
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf456f
+ jmp near 046f5h ; e9 80 01 ; 0xf4572 eltorito.c:680
+ les di, [bp-01ah] ; c4 7e e6 ; 0xf4575 eltorito.c:684
+ mov ax, word [es:di+008h] ; 26 8b 45 08 ; 0xf4578
+ mov dx, word [es:di+00ah] ; 26 8b 55 0a ; 0xf457c
+ mov cx, word [bp+016h] ; 8b 4e 16 ; 0xf4580 eltorito.c:687
+ shr cx, 008h ; c1 e9 08 ; 0xf4583
+ mov word [bp-01eh], cx ; 89 4e e2 ; 0xf4586
+ cmp cx, strict byte 00044h ; 83 f9 44 ; 0xf4589
+ jne short 04591h ; 75 03 ; 0xf458c
+ jmp near 04452h ; e9 c1 fe ; 0xf458e
+ cmp cx, strict byte 00047h ; 83 f9 47 ; 0xf4591
+ jne short 04598h ; 75 02 ; 0xf4594
+ jmp short 0458eh ; eb f6 ; 0xf4596 eltorito.c:688
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf4598 eltorito.c:695
+ mov cx, word [es:bx+008h] ; 26 8b 4f 08 ; 0xf459b
+ mov word [bp-01ch], cx ; 89 4e e4 ; 0xf459f
+ mov bx, word [es:bx+00ah] ; 26 8b 5f 0a ; 0xf45a2
+ mov word [bp-020h], bx ; 89 5e e0 ; 0xf45a6
+ mov word [bp-02ch], ax ; 89 46 d4 ; 0xf45a9 eltorito.c:698
+ mov word [bp-02ah], dx ; 89 56 d6 ; 0xf45ac
+ shr word [bp-02ah], 1 ; d1 6e d6 ; 0xf45af
+ rcr word [bp-02ch], 1 ; d1 5e d4 ; 0xf45b2
+ shr word [bp-02ah], 1 ; d1 6e d6 ; 0xf45b5
+ rcr word [bp-02ch], 1 ; d1 5e d4 ; 0xf45b8
+ mov bx, word [bp-02ah] ; 8b 5e d6 ; 0xf45bb
+ mov word [bp-026h], bx ; 89 5e da ; 0xf45be
+ mov di, ax ; 89 c7 ; 0xf45c1 eltorito.c:699
+ and di, strict byte 00003h ; 83 e7 03 ; 0xf45c3
+ xor bx, bx ; 31 db ; 0xf45c6 eltorito.c:702
+ add ax, word [bp-010h] ; 03 46 f0 ; 0xf45c8
+ adc dx, bx ; 11 da ; 0xf45cb
+ add ax, strict word 0ffffh ; 05 ff ff ; 0xf45cd
+ adc dx, strict byte 0ffffh ; 83 d2 ff ; 0xf45d0
+ mov word [bp-030h], ax ; 89 46 d0 ; 0xf45d3
+ mov word [bp-02eh], dx ; 89 56 d2 ; 0xf45d6
+ shr word [bp-02eh], 1 ; d1 6e d2 ; 0xf45d9
+ rcr word [bp-030h], 1 ; d1 5e d0 ; 0xf45dc
+ shr word [bp-02eh], 1 ; d1 6e d2 ; 0xf45df
+ rcr word [bp-030h], 1 ; d1 5e d0 ; 0xf45e2
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf45e5 eltorito.c:704
+ mov dx, ss ; 8c d2 ; 0xf45e8
+ lea ax, [bp-03ch] ; 8d 46 c4 ; 0xf45ea
+ call 09bb0h ; e8 c0 55 ; 0xf45ed
+ mov word [bp-03ch], strict word 00028h ; c7 46 c4 28 00 ; 0xf45f0 eltorito.c:705
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf45f5 eltorito.c:706
+ add ax, word [bp-02ch] ; 03 46 d4 ; 0xf45f8
+ mov dx, word [bp-020h] ; 8b 56 e0 ; 0xf45fb
+ adc dx, word [bp-026h] ; 13 56 da ; 0xf45fe
+ xchg ah, al ; 86 c4 ; 0xf4601
+ xchg dh, dl ; 86 d6 ; 0xf4603
+ xchg dx, ax ; 92 ; 0xf4605
+ mov word [bp-03ah], ax ; 89 46 c6 ; 0xf4606
+ mov word [bp-038h], dx ; 89 56 c8 ; 0xf4609
+ mov ax, word [bp-030h] ; 8b 46 d0 ; 0xf460c eltorito.c:707
+ sub ax, word [bp-02ch] ; 2b 46 d4 ; 0xf460f
+ inc ax ; 40 ; 0xf4612
+ xchg ah, al ; 86 c4 ; 0xf4613
+ mov word [bp-035h], ax ; 89 46 cb ; 0xf4615
+ mov dx, di ; 89 fa ; 0xf4618 eltorito.c:709
+ sal dx, 009h ; c1 e2 09 ; 0xf461a
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf461d
+ mov word [es:si+01eh], dx ; 26 89 54 1e ; 0xf4620
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf4624 eltorito.c:710
+ xor ah, ah ; 30 e4 ; 0xf4627
+ and AL, strict byte 003h ; 24 03 ; 0xf4629
+ mov bx, strict word 00004h ; bb 04 00 ; 0xf462b
+ sub bx, ax ; 29 c3 ; 0xf462e
+ mov ax, bx ; 89 d8 ; 0xf4630
+ sub ax, di ; 29 f8 ; 0xf4632
+ sal ax, 009h ; c1 e0 09 ; 0xf4634
+ and ah, 007h ; 80 e4 07 ; 0xf4637
+ mov word [es:si+020h], ax ; 26 89 44 20 ; 0xf463a
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf463e eltorito.c:712
+ xor ah, ah ; 30 e4 ; 0xf4641
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf4643
+ mov bx, si ; 89 f3 ; 0xf4646
+ add bx, ax ; 01 c3 ; 0xf4648
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf464a
+ xor ah, ah ; 30 e4 ; 0xf464e
+ add ax, ax ; 01 c0 ; 0xf4650
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf4652
+ push word [bp-014h] ; ff 76 ec ; 0xf4655
+ push word [bp-016h] ; ff 76 ea ; 0xf4658
+ push strict byte 00001h ; 6a 01 ; 0xf465b
+ mov bx, word [bp-010h] ; 8b 5e f0 ; 0xf465d
+ xor di, di ; 31 ff ; 0xf4660
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf4662
+ sal bx, 1 ; d1 e3 ; 0xf4665
+ rcl di, 1 ; d1 d7 ; 0xf4667
+ loop 04665h ; e2 fa ; 0xf4669
+ push di ; 57 ; 0xf466b
+ push bx ; 53 ; 0xf466c
+ push dx ; 52 ; 0xf466d
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf466e
+ xor ah, ah ; 30 e4 ; 0xf4671
+ mov cx, ss ; 8c d1 ; 0xf4673
+ lea bx, [bp-03ch] ; 8d 5e c4 ; 0xf4675
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf4678
+ mov di, word [bp-024h] ; 8b 7e dc ; 0xf467b
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf467e
+ mov dx, ax ; 89 c2 ; 0xf4682
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4684 eltorito.c:714
+ mov word [es:si+01eh], strict word 00000h ; 26 c7 44 1e 00 00 ; 0xf4687
+ mov word [es:si+020h], strict word 00000h ; 26 c7 44 20 00 00 ; 0xf468d eltorito.c:715
+ mov bx, word [es:si+01ah] ; 26 8b 5c 1a ; 0xf4693 eltorito.c:717
+ mov di, word [es:si+01ch] ; 26 8b 7c 1c ; 0xf4697
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf469b
+ shr di, 1 ; d1 ef ; 0xf469e
+ rcr bx, 1 ; d1 db ; 0xf46a0
+ loop 0469eh ; e2 fa ; 0xf46a2
+ les si, [bp-01ah] ; c4 76 e6 ; 0xf46a4 eltorito.c:718
+ mov word [es:si+002h], bx ; 26 89 5c 02 ; 0xf46a7
+ test al, al ; 84 c0 ; 0xf46ab eltorito.c:720
+ jne short 046b2h ; 75 03 ; 0xf46ad
+ jmp near 04452h ; e9 a0 fd ; 0xf46af
+ mov bx, 00da0h ; bb a0 0d ; 0xf46b2 eltorito.c:721
+ mov cx, ds ; 8c d9 ; 0xf46b5
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf46b7
+ call 018bch ; e8 ff d1 ; 0xf46ba
+ mov al, dl ; 88 d0 ; 0xf46bd
+ xor ah, ah ; 30 e4 ; 0xf46bf
+ push ax ; 50 ; 0xf46c1
+ push word [bp-01eh] ; ff 76 e2 ; 0xf46c2
+ push 0034ch ; 68 4c 03 ; 0xf46c5
+ push 003d8h ; 68 d8 03 ; 0xf46c8
+ push strict byte 00004h ; 6a 04 ; 0xf46cb
+ call 018ffh ; e8 2f d2 ; 0xf46cd
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf46d0
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf46d3 eltorito.c:722
+ xor ah, ah ; 30 e4 ; 0xf46d6
+ or ah, 00ch ; 80 cc 0c ; 0xf46d8
+ jmp short 046fdh ; eb 20 ; 0xf46db
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf46dd eltorito.c:730
+ xor ah, ah ; 30 e4 ; 0xf46e0
+ push ax ; 50 ; 0xf46e2
+ mov ax, word [bp+00ah] ; 8b 46 0a ; 0xf46e3
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf46e6
+ mov bx, si ; 89 f3 ; 0xf46e9
+ mov cx, word [bp-008h] ; 8b 4e f8 ; 0xf46eb
+ call 05965h ; e8 74 12 ; 0xf46ee
+ test ax, ax ; 85 c0 ; 0xf46f1
+ je short 046afh ; 74 ba ; 0xf46f3
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf46f5 eltorito.c:731
+ xor ah, ah ; 30 e4 ; 0xf46f8
+ or ah, 001h ; 80 cc 01 ; 0xf46fa
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf46fd
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf4700
+ shr ax, 008h ; c1 e8 08 ; 0xf4703
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4706
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf4709
+ mov es, dx ; 8e c2 ; 0xf470c
+ mov byte [es:bx], al ; 26 88 07 ; 0xf470e
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf4711
+ jmp near 04466h ; e9 4e fd ; 0xf4715
+ mov bx, 00da0h ; bb a0 0d ; 0xf4718 eltorito.c:747
+ mov cx, ds ; 8c d9 ; 0xf471b
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf471d
+ call 018bch ; e8 99 d1 ; 0xf4720
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf4723
+ shr ax, 008h ; c1 e8 08 ; 0xf4726
+ push ax ; 50 ; 0xf4729
+ push 0034ch ; 68 4c 03 ; 0xf472a
+ push 003fah ; 68 fa 03 ; 0xf472d
+ push strict byte 00004h ; 6a 04 ; 0xf4730
+ jmp near 0456ch ; e9 37 fe ; 0xf4732
+ ; disGetNextSymbol 0xf4735 LB 0x5793 -> off=0x59 cb=0000000000000379 uValue=00000000000f318e 'int13_cdrom'
+ db 050h, 04eh, 049h, 048h, 047h, 046h, 045h, 044h, 043h, 042h, 041h, 018h, 016h, 015h, 014h, 011h
+ db 010h, 00dh, 00ch, 00bh, 00ah, 009h, 008h, 005h, 004h, 003h, 002h, 001h, 000h, 06fh, 048h, 0ech
+ db 04ah, 034h, 048h, 06fh, 048h, 029h, 048h, 06fh, 048h, 029h, 048h, 06fh, 048h, 0ech, 04ah, 06fh
+ db 048h, 06fh, 048h, 0ech, 04ah, 0ech, 04ah, 0ech, 04ah, 0ech, 04ah, 0ech, 04ah, 056h, 048h, 0ech
+ db 04ah, 06fh, 048h, 05ch, 048h, 08bh, 048h, 029h, 048h, 08bh, 048h, 0c9h, 049h, 06fh, 04ah, 08bh
+ db 048h, 094h, 04ah, 0ach, 04ah, 0b4h, 04ah, 06fh, 048h
+int13_cdrom: ; 0xf478e LB 0x379
+ push bp ; 55 ; 0xf478e eltorito.c:772
+ mov bp, sp ; 89 e5 ; 0xf478f
+ push si ; 56 ; 0xf4791
+ push di ; 57 ; 0xf4792
+ sub sp, strict byte 00020h ; 83 ec 20 ; 0xf4793
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf4796 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4799
+ mov es, ax ; 8e c0 ; 0xf479c
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf479e
+ mov si, 00122h ; be 22 01 ; 0xf47a1 eltorito.c:782
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf47a4
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf47a7 eltorito.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf47aa
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf47ae eltorito.c:789
+ xor ah, ah ; 30 e4 ; 0xf47b1
+ cmp ax, 000e0h ; 3d e0 00 ; 0xf47b3
+ jc short 047bdh ; 72 05 ; 0xf47b6
+ cmp ax, 000f0h ; 3d f0 00 ; 0xf47b8
+ jc short 047dbh ; 72 1e ; 0xf47bb
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf47bd eltorito.c:790
+ xor ah, ah ; 30 e4 ; 0xf47c0
+ push ax ; 50 ; 0xf47c2
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf47c3
+ shr ax, 008h ; c1 e8 08 ; 0xf47c6
+ push ax ; 50 ; 0xf47c9
+ push 0042ah ; 68 2a 04 ; 0xf47ca
+ push 00436h ; 68 36 04 ; 0xf47cd
+ push strict byte 00004h ; 6a 04 ; 0xf47d0
+ call 018ffh ; e8 2a d1 ; 0xf47d2
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf47d5
+ jmp near 04acah ; e9 ef 02 ; 0xf47d8 eltorito.c:791
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf47db eltorito.c:795
+ xor ah, ah ; 30 e4 ; 0xf47de
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf47e0
+ mov bx, si ; 89 f3 ; 0xf47e3
+ add bx, ax ; 01 c3 ; 0xf47e5
+ mov dl, byte [es:bx+00114h] ; 26 8a 97 14 01 ; 0xf47e7
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf47ec
+ cmp dl, 010h ; 80 fa 10 ; 0xf47ef eltorito.c:798
+ jc short 04804h ; 72 10 ; 0xf47f2
+ push ax ; 50 ; 0xf47f4 eltorito.c:799
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf47f5
+ shr ax, 008h ; c1 e8 08 ; 0xf47f8
+ push ax ; 50 ; 0xf47fb
+ push 0042ah ; 68 2a 04 ; 0xf47fc
+ push 00461h ; 68 61 04 ; 0xf47ff
+ jmp short 047d0h ; eb cc ; 0xf4802
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4804 eltorito.c:803
+ shr ax, 008h ; c1 e8 08 ; 0xf4807
+ cmp ax, strict word 00050h ; 3d 50 00 ; 0xf480a
+ jnbe short 0486fh ; 77 60 ; 0xf480d
+ push CS ; 0e ; 0xf480f
+ pop ES ; 07 ; 0xf4810
+ mov cx, strict word 0001eh ; b9 1e 00 ; 0xf4811
+ mov di, 04735h ; bf 35 47 ; 0xf4814
+ repne scasb ; f2 ae ; 0xf4817
+ sal cx, 1 ; d1 e1 ; 0xf4819
+ mov di, cx ; 89 cf ; 0xf481b
+ mov dx, word [cs:di+04752h] ; 2e 8b 95 52 47 ; 0xf481d
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4822
+ xor ah, ah ; 30 e4 ; 0xf4825
+ jmp dx ; ff e2 ; 0xf4827
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4829 eltorito.c:821
+ xor ah, ah ; 30 e4 ; 0xf482c
+ or ah, 003h ; 80 cc 03 ; 0xf482e
+ jmp near 04ad2h ; e9 9e 02 ; 0xf4831
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4834 eltorito.c:38
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf4837
+ mov es, dx ; 8e c2 ; 0xf483a
+ mov cl, byte [es:bx] ; 26 8a 0f ; 0xf483c
+ mov dl, cl ; 88 ca ; 0xf483f eltorito.c:827
+ xor dh, dh ; 30 f6 ; 0xf4841
+ sal dx, 008h ; c1 e2 08 ; 0xf4843
+ or ax, dx ; 09 d0 ; 0xf4846
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4848
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf484b eltorito.c:43
+ test cl, cl ; 84 c9 ; 0xf484f eltorito.c:831
+ je short 0486ch ; 74 19 ; 0xf4851
+ jmp near 04ae6h ; e9 90 02 ; 0xf4853 eltorito.c:832
+ or ah, 002h ; 80 cc 02 ; 0xf4856 eltorito.c:838
+ jmp near 04ad2h ; e9 76 02 ; 0xf4859
+ mov word [bp+012h], 0aa55h ; c7 46 12 55 aa ; 0xf485c eltorito.c:843
+ or ah, 030h ; 80 cc 30 ; 0xf4861 eltorito.c:844
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4864
+ mov word [bp+016h], strict word 00007h ; c7 46 16 07 00 ; 0xf4867 eltorito.c:845
+ jmp near 04af0h ; e9 81 02 ; 0xf486c eltorito.c:846
+ mov bx, 00da0h ; bb a0 0d ; 0xf486f
+ mov cx, ds ; 8c d9 ; 0xf4872
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4874
+ call 018bch ; e8 42 d0 ; 0xf4877
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf487a
+ shr ax, 008h ; c1 e8 08 ; 0xf487d
+ push ax ; 50 ; 0xf4880
+ push 0042ah ; 68 2a 04 ; 0xf4881
+ push 00333h ; 68 33 03 ; 0xf4884
+ push strict byte 00004h ; 6a 04 ; 0xf4887
+ jmp short 048cbh ; eb 40 ; 0xf4889
+ mov bx, word [bp+00ch] ; 8b 5e 0c ; 0xf488b eltorito.c:854
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf488e
+ mov word [bp-010h], bx ; 89 5e f0 ; 0xf4891
+ mov [bp-00ch], es ; 8c 46 f4 ; 0xf4894
+ mov di, word [es:bx+002h] ; 26 8b 7f 02 ; 0xf4897 eltorito.c:856
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf489b eltorito.c:857
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf489f
+ mov ax, word [es:bx+004h] ; 26 8b 47 04 ; 0xf48a2 eltorito.c:858
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf48a6
+ mov ax, word [es:bx+00ch] ; 26 8b 47 0c ; 0xf48a9 eltorito.c:861
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf48ad
+ mov ax, word [es:bx+00eh] ; 26 8b 47 0e ; 0xf48b0
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf48b4
+ or ax, word [bp-012h] ; 0b 46 ee ; 0xf48b7 eltorito.c:862
+ je short 048d4h ; 74 18 ; 0xf48ba
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf48bc eltorito.c:863
+ shr ax, 008h ; c1 e8 08 ; 0xf48bf
+ push ax ; 50 ; 0xf48c2
+ push 0042ah ; 68 2a 04 ; 0xf48c3
+ push 003afh ; 68 af 03 ; 0xf48c6
+ push strict byte 00007h ; 6a 07 ; 0xf48c9
+ call 018ffh ; e8 31 d0 ; 0xf48cb
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf48ce
+ jmp near 04acah ; e9 f6 01 ; 0xf48d1 eltorito.c:864
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf48d4 eltorito.c:868
+ mov bx, word [bp-010h] ; 8b 5e f0 ; 0xf48d7
+ mov ax, word [es:bx+008h] ; 26 8b 47 08 ; 0xf48da
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf48de
+ mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xf48e1
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf48e5
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf48e8 eltorito.c:871
+ shr ax, 008h ; c1 e8 08 ; 0xf48eb
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf48ee
+ cmp ax, strict word 00044h ; 3d 44 00 ; 0xf48f1
+ je short 048fbh ; 74 05 ; 0xf48f4
+ cmp ax, strict word 00047h ; 3d 47 00 ; 0xf48f6
+ jne short 048feh ; 75 03 ; 0xf48f9
+ jmp near 04aech ; e9 ee 01 ; 0xf48fb eltorito.c:872
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf48fe eltorito.c:877
+ xor bx, bx ; 31 db ; 0xf4901
+ mov dx, ss ; 8c d2 ; 0xf4903
+ lea ax, [bp-024h] ; 8d 46 dc ; 0xf4905
+ call 09bb0h ; e8 a5 52 ; 0xf4908
+ mov word [bp-024h], strict word 00028h ; c7 46 dc 28 00 ; 0xf490b eltorito.c:878
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf4910 eltorito.c:879
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf4913
+ xchg ah, al ; 86 c4 ; 0xf4916
+ xchg dh, dl ; 86 d6 ; 0xf4918
+ xchg dx, ax ; 92 ; 0xf491a
+ mov word [bp-022h], ax ; 89 46 de ; 0xf491b
+ mov word [bp-020h], dx ; 89 56 e0 ; 0xf491e
+ mov ax, di ; 89 f8 ; 0xf4921 eltorito.c:880
+ xchg ah, al ; 86 c4 ; 0xf4923
+ mov word [bp-01dh], ax ; 89 46 e3 ; 0xf4925
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4928 eltorito.c:882
+ mov word [es:si+00eh], di ; 26 89 7c 0e ; 0xf492b
+ mov word [es:si+010h], 00800h ; 26 c7 44 10 00 08 ; 0xf492f eltorito.c:883
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4935 eltorito.c:885
+ xor ah, ah ; 30 e4 ; 0xf4938
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf493a
+ mov bx, si ; 89 f3 ; 0xf493d
+ add bx, ax ; 01 c3 ; 0xf493f
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf4941
+ xor ah, ah ; 30 e4 ; 0xf4945
+ add ax, ax ; 01 c0 ; 0xf4947
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf4949
+ push word [bp-016h] ; ff 76 ea ; 0xf494c
+ push word [bp-014h] ; ff 76 ec ; 0xf494f
+ push strict byte 00001h ; 6a 01 ; 0xf4952
+ mov ax, di ; 89 f8 ; 0xf4954
+ xor bx, bx ; 31 db ; 0xf4956
+ mov cx, strict word 0000bh ; b9 0b 00 ; 0xf4958
+ sal ax, 1 ; d1 e0 ; 0xf495b
+ rcl bx, 1 ; d1 d3 ; 0xf495d
+ loop 0495bh ; e2 fa ; 0xf495f
+ push bx ; 53 ; 0xf4961
+ push ax ; 50 ; 0xf4962
+ push strict byte 00000h ; 6a 00 ; 0xf4963
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4965
+ xor ah, ah ; 30 e4 ; 0xf4968
+ mov cx, ss ; 8c d1 ; 0xf496a
+ lea bx, [bp-024h] ; 8d 5e dc ; 0xf496c
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf496f
+ mov di, word [bp-018h] ; 8b 7e e8 ; 0xf4972
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf4975
+ mov dx, ax ; 89 c2 ; 0xf4979
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf497b eltorito.c:887
+ mov ax, word [es:si+01ah] ; 26 8b 44 1a ; 0xf497e
+ mov bx, word [es:si+01ch] ; 26 8b 5c 1c ; 0xf4982
+ mov cx, strict word 0000bh ; b9 0b 00 ; 0xf4986
+ shr bx, 1 ; d1 eb ; 0xf4989
+ rcr ax, 1 ; d1 d8 ; 0xf498b
+ loop 04989h ; e2 fa ; 0xf498d
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf498f eltorito.c:888
+ mov bx, word [bp-010h] ; 8b 5e f0 ; 0xf4992
+ mov word [es:bx+002h], ax ; 26 89 47 02 ; 0xf4995
+ test dl, dl ; 84 d2 ; 0xf4999 eltorito.c:890
+ je short 04a06h ; 74 69 ; 0xf499b
+ mov bx, 00da0h ; bb a0 0d ; 0xf499d eltorito.c:891
+ mov cx, ds ; 8c d9 ; 0xf49a0
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf49a2
+ call 018bch ; e8 14 cf ; 0xf49a5
+ mov al, dl ; 88 d0 ; 0xf49a8
+ xor ah, ah ; 30 e4 ; 0xf49aa
+ push ax ; 50 ; 0xf49ac
+ push word [bp-00eh] ; ff 76 f2 ; 0xf49ad
+ push 0042ah ; 68 2a 04 ; 0xf49b0
+ push 003d8h ; 68 d8 03 ; 0xf49b3
+ push strict byte 00004h ; 6a 04 ; 0xf49b6
+ call 018ffh ; e8 44 cf ; 0xf49b8
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf49bb
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf49be eltorito.c:892
+ xor ah, ah ; 30 e4 ; 0xf49c1
+ or ah, 00ch ; 80 cc 0c ; 0xf49c3
+ jmp near 04ad2h ; e9 09 01 ; 0xf49c6
+ cmp ax, strict word 00002h ; 3d 02 00 ; 0xf49c9 eltorito.c:900
+ jnbe short 04a38h ; 77 6a ; 0xf49cc
+ mov dl, byte [bp-006h] ; 8a 56 fa ; 0xf49ce eltorito.c:903
+ xor dh, dh ; 30 f6 ; 0xf49d1
+ imul dx, dx, strict byte 0001ch ; 6b d2 1c ; 0xf49d3
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf49d6
+ mov bx, si ; 89 f3 ; 0xf49d9
+ add bx, dx ; 01 d3 ; 0xf49db
+ mov bl, byte [es:bx+025h] ; 26 8a 5f 25 ; 0xf49dd
+ cmp ax, strict word 00002h ; 3d 02 00 ; 0xf49e1 eltorito.c:905
+ je short 04a3bh ; 74 55 ; 0xf49e4
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf49e6
+ je short 04a28h ; 74 3d ; 0xf49e9
+ test ax, ax ; 85 c0 ; 0xf49eb
+ jne short 04a25h ; 75 36 ; 0xf49ed
+ cmp bl, 0ffh ; 80 fb ff ; 0xf49ef eltorito.c:907
+ jne short 04a08h ; 75 14 ; 0xf49f2
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf49f4 eltorito.c:908
+ xor ah, ah ; 30 e4 ; 0xf49f7
+ or ah, 0b4h ; 80 cc b4 ; 0xf49f9
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf49fc
+ xor al, al ; 30 c0 ; 0xf49ff eltorito.c:909
+ or AL, strict byte 001h ; 0c 01 ; 0xf4a01
+ jmp near 04ad2h ; e9 cc 00 ; 0xf4a03
+ jmp short 04a25h ; eb 1d ; 0xf4a06
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4a08 eltorito.c:911
+ xor ah, ah ; 30 e4 ; 0xf4a0b
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf4a0d
+ db 0feh, 0c3h
+ ; inc bl ; fe c3 ; 0xf4a10 eltorito.c:912
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4a12
+ add si, ax ; 01 c6 ; 0xf4a15
+ mov byte [es:si+025h], bl ; 26 88 5c 25 ; 0xf4a17
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4a1b eltorito.c:913
+ xor al, al ; 30 c0 ; 0xf4a1e
+ or AL, strict byte 001h ; 0c 01 ; 0xf4a20
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4a22
+ jmp near 04aech ; e9 c4 00 ; 0xf4a25 eltorito.c:914
+ test bl, bl ; 84 db ; 0xf4a28 eltorito.c:916
+ jne short 04a3dh ; 75 11 ; 0xf4a2a
+ or ah, 0b0h ; 80 cc b0 ; 0xf4a2c eltorito.c:917
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4a2f
+ mov byte [bp+018h], bl ; 88 5e 18 ; 0xf4a32 eltorito.c:918
+ jmp near 04ad5h ; e9 9d 00 ; 0xf4a35 eltorito.c:919
+ jmp near 04acah ; e9 8f 00 ; 0xf4a38
+ jmp short 04a67h ; eb 2a ; 0xf4a3b
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4a3d eltorito.c:920
+ xor ah, ah ; 30 e4 ; 0xf4a40
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf4a42
+ db 0feh, 0cbh
+ ; dec bl ; fe cb ; 0xf4a45 eltorito.c:921
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4a47
+ add si, ax ; 01 c6 ; 0xf4a4a
+ mov byte [es:si+025h], bl ; 26 88 5c 25 ; 0xf4a4c
+ test bl, bl ; 84 db ; 0xf4a50 eltorito.c:922
+ jne short 04a58h ; 75 04 ; 0xf4a52
+ xor ax, ax ; 31 c0 ; 0xf4a54
+ jmp short 04a5bh ; eb 03 ; 0xf4a56
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf4a58
+ mov dx, word [bp+018h] ; 8b 56 18 ; 0xf4a5b
+ xor dl, dl ; 30 d2 ; 0xf4a5e
+ or dx, ax ; 09 c2 ; 0xf4a60
+ mov word [bp+018h], dx ; 89 56 18 ; 0xf4a62
+ jmp short 04a25h ; eb be ; 0xf4a65 eltorito.c:923
+ test bl, bl ; 84 db ; 0xf4a67 eltorito.c:925
+ jne short 04a58h ; 75 ed ; 0xf4a69
+ xor al, al ; 30 c0 ; 0xf4a6b
+ jmp short 04a5bh ; eb ec ; 0xf4a6d
+ mov dl, byte [bp-006h] ; 8a 56 fa ; 0xf4a6f eltorito.c:932
+ xor dh, dh ; 30 f6 ; 0xf4a72
+ imul dx, dx, strict byte 0001ch ; 6b d2 1c ; 0xf4a74
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4a77
+ mov bx, si ; 89 f3 ; 0xf4a7a
+ add bx, dx ; 01 d3 ; 0xf4a7c
+ mov bl, byte [es:bx+025h] ; 26 8a 5f 25 ; 0xf4a7e
+ test bl, bl ; 84 db ; 0xf4a82 eltorito.c:934
+ je short 04a8bh ; 74 05 ; 0xf4a84
+ or ah, 0b1h ; 80 cc b1 ; 0xf4a86 eltorito.c:935
+ jmp short 04ad2h ; eb 47 ; 0xf4a89
+ je short 04aech ; 74 5f ; 0xf4a8b eltorito.c:957
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4a8d eltorito.c:958
+ xor ah, ah ; 30 e4 ; 0xf4a90
+ jmp short 04a86h ; eb f2 ; 0xf4a92
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4a94 eltorito.c:966
+ push ax ; 50 ; 0xf4a97
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf4a98
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf4a9b
+ mov bx, si ; 89 f3 ; 0xf4a9e
+ mov cx, word [bp-008h] ; 8b 4e f8 ; 0xf4aa0
+ call 05965h ; e8 bf 0e ; 0xf4aa3
+ test ax, ax ; 85 c0 ; 0xf4aa6
+ je short 04aech ; 74 42 ; 0xf4aa8
+ jmp short 04acah ; eb 1e ; 0xf4aaa eltorito.c:967
+ or ah, 006h ; 80 cc 06 ; 0xf4aac eltorito.c:974
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4aaf
+ jmp short 04ae6h ; eb 32 ; 0xf4ab2 eltorito.c:975
+ cmp ax, strict word 00006h ; 3d 06 00 ; 0xf4ab4 eltorito.c:980
+ je short 04aech ; 74 33 ; 0xf4ab7
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf4ab9
+ jc short 04acah ; 72 0c ; 0xf4abc
+ jbe short 04aech ; 76 2c ; 0xf4abe
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf4ac0
+ jc short 04acah ; 72 05 ; 0xf4ac3
+ cmp ax, strict word 00004h ; 3d 04 00 ; 0xf4ac5
+ jbe short 04aech ; 76 22 ; 0xf4ac8
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4aca eltorito.c:1007
+ xor ah, ah ; 30 e4 ; 0xf4acd
+ or ah, 001h ; 80 cc 01 ; 0xf4acf
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4ad2
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4ad5 eltorito.c:1009
+ shr ax, 008h ; c1 e8 08 ; 0xf4ad8
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4adb eltorito.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf4ade
+ mov es, dx ; 8e c2 ; 0xf4ae1
+ mov byte [es:bx], al ; 26 88 07 ; 0xf4ae3
+ or byte [bp+01eh], 001h ; 80 4e 1e 01 ; 0xf4ae6 eltorito.c:1011
+ jmp short 04b00h ; eb 14 ; 0xf4aea eltorito.c:1012
+ mov byte [bp+019h], 000h ; c6 46 19 00 ; 0xf4aec eltorito.c:1015
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4af0 eltorito.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4af3
+ mov es, ax ; 8e c0 ; 0xf4af6
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf4af8
+ and byte [bp+01eh], 0feh ; 80 66 1e fe ; 0xf4afc eltorito.c:1018
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf4b00 eltorito.c:1020
+ pop di ; 5f ; 0xf4b03
+ pop si ; 5e ; 0xf4b04
+ pop bp ; 5d ; 0xf4b05
+ retn ; c3 ; 0xf4b06
+ ; disGetNextSymbol 0xf4b07 LB 0x53c1 -> off=0x0 cb=000000000000004b uValue=00000000000f3507 'print_boot_device'
+print_boot_device: ; 0xf4b07 LB 0x4b
+ push bp ; 55 ; 0xf4b07 boot.c:109
+ mov bp, sp ; 89 e5 ; 0xf4b08
+ push cx ; 51 ; 0xf4b0a
+ test al, al ; 84 c0 ; 0xf4b0b boot.c:117
+ je short 04b14h ; 74 05 ; 0xf4b0d
+ mov dx, strict word 00002h ; ba 02 00 ; 0xf4b0f
+ jmp short 04b2eh ; eb 1a ; 0xf4b12 boot.c:118
+ test dl, dl ; 84 d2 ; 0xf4b14
+ je short 04b1dh ; 74 05 ; 0xf4b16
+ mov dx, strict word 00003h ; ba 03 00 ; 0xf4b18
+ jmp short 04b2eh ; eb 11 ; 0xf4b1b boot.c:119
+ test bl, 080h ; f6 c3 80 ; 0xf4b1d
+ jne short 04b26h ; 75 04 ; 0xf4b20
+ xor dh, dh ; 30 f6 ; 0xf4b22
+ jmp short 04b2eh ; eb 08 ; 0xf4b24 boot.c:120
+ test bl, 080h ; f6 c3 80 ; 0xf4b26
+ je short 04b4ch ; 74 21 ; 0xf4b29
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf4b2b
+ mov bx, 00da0h ; bb a0 0d ; 0xf4b2e boot.c:123
+ mov cx, ds ; 8c d9 ; 0xf4b31
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4b33
+ call 018bch ; e8 83 cd ; 0xf4b36
+ imul dx, dx, strict byte 0000ah ; 6b d2 0a ; 0xf4b39
+ add dx, 00dc6h ; 81 c2 c6 0d ; 0xf4b3c
+ push dx ; 52 ; 0xf4b40
+ push 00494h ; 68 94 04 ; 0xf4b41
+ push strict byte 00004h ; 6a 04 ; 0xf4b44
+ call 018ffh ; e8 b6 cd ; 0xf4b46
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf4b49
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf4b4c boot.c:124
+ pop cx ; 59 ; 0xf4b4f
+ pop bp ; 5d ; 0xf4b50
+ retn ; c3 ; 0xf4b51
+ ; disGetNextSymbol 0xf4b52 LB 0x5376 -> off=0x0 cb=0000000000000096 uValue=00000000000f3552 'print_boot_failure'
+print_boot_failure: ; 0xf4b52 LB 0x96
+ push bp ; 55 ; 0xf4b52 boot.c:131
+ mov bp, sp ; 89 e5 ; 0xf4b53
+ push si ; 56 ; 0xf4b55
+ mov ah, dl ; 88 d4 ; 0xf4b56
+ mov dl, cl ; 88 ca ; 0xf4b58
+ mov cl, bl ; 88 d9 ; 0xf4b5a boot.c:134
+ and cl, 07fh ; 80 e1 7f ; 0xf4b5c
+ xor ch, ch ; 30 ed ; 0xf4b5f
+ mov si, cx ; 89 ce ; 0xf4b61
+ test al, al ; 84 c0 ; 0xf4b63 boot.c:142
+ je short 04b82h ; 74 1b ; 0xf4b65
+ mov bx, 00da0h ; bb a0 0d ; 0xf4b67 boot.c:143
+ mov cx, ds ; 8c d9 ; 0xf4b6a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4b6c
+ call 018bch ; e8 4a cd ; 0xf4b6f
+ push 00ddah ; 68 da 0d ; 0xf4b72
+ push 004a8h ; 68 a8 04 ; 0xf4b75
+ push strict byte 00004h ; 6a 04 ; 0xf4b78
+ call 018ffh ; e8 82 cd ; 0xf4b7a
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf4b7d
+ jmp short 04bc6h ; eb 44 ; 0xf4b80 boot.c:144
+ test ah, ah ; 84 e4 ; 0xf4b82
+ je short 04b96h ; 74 10 ; 0xf4b84
+ mov bx, 00da0h ; bb a0 0d ; 0xf4b86 boot.c:145
+ mov cx, ds ; 8c d9 ; 0xf4b89
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4b8b
+ call 018bch ; e8 2b cd ; 0xf4b8e
+ push 00de4h ; 68 e4 0d ; 0xf4b91
+ jmp short 04b75h ; eb df ; 0xf4b94
+ test bl, 080h ; f6 c3 80 ; 0xf4b96 boot.c:146
+ je short 04bach ; 74 11 ; 0xf4b99
+ mov bx, 00da0h ; bb a0 0d ; 0xf4b9b boot.c:147
+ mov cx, ds ; 8c d9 ; 0xf4b9e
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4ba0
+ call 018bch ; e8 16 cd ; 0xf4ba3
+ push si ; 56 ; 0xf4ba6
+ push 00dd0h ; 68 d0 0d ; 0xf4ba7
+ jmp short 04bbbh ; eb 0f ; 0xf4baa boot.c:148
+ mov bx, 00da0h ; bb a0 0d ; 0xf4bac boot.c:149
+ mov cx, ds ; 8c d9 ; 0xf4baf
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4bb1
+ call 018bch ; e8 05 cd ; 0xf4bb4
+ push si ; 56 ; 0xf4bb7
+ push 00dc6h ; 68 c6 0d ; 0xf4bb8
+ push 004bdh ; 68 bd 04 ; 0xf4bbb
+ push strict byte 00004h ; 6a 04 ; 0xf4bbe
+ call 018ffh ; e8 3c cd ; 0xf4bc0
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf4bc3
+ cmp byte [bp+004h], 001h ; 80 7e 04 01 ; 0xf4bc6 boot.c:151
+ jne short 04be0h ; 75 14 ; 0xf4bca
+ test dl, dl ; 84 d2 ; 0xf4bcc boot.c:152
+ jne short 04bd5h ; 75 05 ; 0xf4bce
+ push 004d5h ; 68 d5 04 ; 0xf4bd0 boot.c:153
+ jmp short 04bd8h ; eb 03 ; 0xf4bd3 boot.c:154
+ push 004ffh ; 68 ff 04 ; 0xf4bd5 boot.c:155
+ push strict byte 00007h ; 6a 07 ; 0xf4bd8
+ call 018ffh ; e8 22 cd ; 0xf4bda
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf4bdd
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf4be0 boot.c:157
+ pop si ; 5e ; 0xf4be3
+ pop bp ; 5d ; 0xf4be4
+ retn 00002h ; c2 02 00 ; 0xf4be5
+ ; disGetNextSymbol 0xf4be8 LB 0x52e0 -> off=0x0 cb=0000000000000027 uValue=00000000000f35e8 'print_cdromboot_failure'
+print_cdromboot_failure: ; 0xf4be8 LB 0x27
+ push bp ; 55 ; 0xf4be8 boot.c:163
+ mov bp, sp ; 89 e5 ; 0xf4be9
+ push bx ; 53 ; 0xf4beb
+ push cx ; 51 ; 0xf4bec
+ push dx ; 52 ; 0xf4bed
+ mov dx, ax ; 89 c2 ; 0xf4bee
+ mov bx, 00da0h ; bb a0 0d ; 0xf4bf0 boot.c:165
+ mov cx, ds ; 8c d9 ; 0xf4bf3
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4bf5
+ call 018bch ; e8 c1 cc ; 0xf4bf8
+ push dx ; 52 ; 0xf4bfb
+ push 00534h ; 68 34 05 ; 0xf4bfc
+ push strict byte 00004h ; 6a 04 ; 0xf4bff
+ call 018ffh ; e8 fb cc ; 0xf4c01
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf4c04
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf4c07 boot.c:167
+ pop dx ; 5a ; 0xf4c0a
+ pop cx ; 59 ; 0xf4c0b
+ pop bx ; 5b ; 0xf4c0c
+ pop bp ; 5d ; 0xf4c0d
+ retn ; c3 ; 0xf4c0e
+ ; disGetNextSymbol 0xf4c0f LB 0x52b9 -> off=0x0 cb=000000000000025b uValue=00000000000f360f 'int19_function'
+int19_function: ; 0xf4c0f LB 0x25b
+ push bp ; 55 ; 0xf4c0f boot.c:170
+ mov bp, sp ; 89 e5 ; 0xf4c10
+ push si ; 56 ; 0xf4c12
+ push di ; 57 ; 0xf4c13
+ sub sp, strict byte 0000ch ; 83 ec 0c ; 0xf4c14
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf4c17 boot.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4c1a
+ mov es, ax ; 8e c0 ; 0xf4c1d
+ mov cx, word [es:bx] ; 26 8b 0f ; 0xf4c1f
+ mov di, cx ; 89 cf ; 0xf4c22 boot.c:49
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf4c24 boot.c:181
+ mov ax, strict word 0003dh ; b8 3d 00 ; 0xf4c28 boot.c:204
+ call 01650h ; e8 22 ca ; 0xf4c2b
+ mov dl, al ; 88 c2 ; 0xf4c2e
+ xor dh, dh ; 30 f6 ; 0xf4c30
+ mov ax, strict word 00038h ; b8 38 00 ; 0xf4c32 boot.c:205
+ call 01650h ; e8 18 ca ; 0xf4c35
+ and AL, strict byte 0f0h ; 24 f0 ; 0xf4c38
+ xor ah, ah ; 30 e4 ; 0xf4c3a
+ sal ax, 004h ; c1 e0 04 ; 0xf4c3c
+ or dx, ax ; 09 c2 ; 0xf4c3f
+ mov ax, strict word 0003ch ; b8 3c 00 ; 0xf4c41 boot.c:206
+ call 01650h ; e8 09 ca ; 0xf4c44
+ and AL, strict byte 00fh ; 24 0f ; 0xf4c47
+ xor ah, ah ; 30 e4 ; 0xf4c49
+ sal ax, 00ch ; c1 e0 0c ; 0xf4c4b
+ or dx, ax ; 09 c2 ; 0xf4c4e
+ mov bx, 0037dh ; bb 7d 03 ; 0xf4c50 boot.c:38
+ mov es, cx ; 8e c1 ; 0xf4c53
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4c55
+ test al, al ; 84 c0 ; 0xf4c58 boot.c:39
+ je short 04c60h ; 74 04 ; 0xf4c5a
+ mov dl, al ; 88 c2 ; 0xf4c5c boot.c:38
+ xor dh, dh ; 30 f6 ; 0xf4c5e boot.c:39
+ cmp byte [bp+004h], 001h ; 80 7e 04 01 ; 0xf4c60 boot.c:210
+ jne short 04c76h ; 75 10 ; 0xf4c64
+ mov ax, strict word 0003ch ; b8 3c 00 ; 0xf4c66 boot.c:211
+ call 01650h ; e8 e4 c9 ; 0xf4c69
+ and AL, strict byte 0f0h ; 24 f0 ; 0xf4c6c
+ xor ah, ah ; 30 e4 ; 0xf4c6e
+ sar ax, 004h ; c1 f8 04 ; 0xf4c70
+ call 0787eh ; e8 08 2c ; 0xf4c73
+ cmp byte [bp+004h], 002h ; 80 7e 04 02 ; 0xf4c76 boot.c:213
+ jne short 04c7fh ; 75 03 ; 0xf4c7a
+ shr dx, 004h ; c1 ea 04 ; 0xf4c7c
+ cmp byte [bp+004h], 003h ; 80 7e 04 03 ; 0xf4c7f boot.c:214
+ jne short 04c88h ; 75 03 ; 0xf4c83
+ shr dx, 008h ; c1 ea 08 ; 0xf4c85
+ cmp byte [bp+004h], 004h ; 80 7e 04 04 ; 0xf4c88 boot.c:215
+ jne short 04c91h ; 75 03 ; 0xf4c8c
+ shr dx, 00ch ; c1 ea 0c ; 0xf4c8e
+ cmp dx, strict byte 00010h ; 83 fa 10 ; 0xf4c91 boot.c:216
+ jnc short 04c9ah ; 73 04 ; 0xf4c94
+ mov byte [bp-00ch], 001h ; c6 46 f4 01 ; 0xf4c96
+ xor al, al ; 30 c0 ; 0xf4c9a boot.c:217
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf4c9c
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf4c9f
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf4ca2 boot.c:218
+ mov bx, 00da0h ; bb a0 0d ; 0xf4ca5 boot.c:219
+ mov cx, ds ; 8c d9 ; 0xf4ca8
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4caa
+ call 018bch ; e8 0c cc ; 0xf4cad
+ push dx ; 52 ; 0xf4cb0
+ mov al, byte [bp+004h] ; 8a 46 04 ; 0xf4cb1
+ xor ah, ah ; 30 e4 ; 0xf4cb4
+ push ax ; 50 ; 0xf4cb6
+ push 00554h ; 68 54 05 ; 0xf4cb7
+ push strict byte 00004h ; 6a 04 ; 0xf4cba
+ call 018ffh ; e8 40 cc ; 0xf4cbc
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf4cbf
+ and dx, strict byte 0000fh ; 83 e2 0f ; 0xf4cc2 boot.c:221
+ cmp dx, strict byte 00002h ; 83 fa 02 ; 0xf4cc5
+ jc short 04cd8h ; 72 0e ; 0xf4cc8
+ jbe short 04ce7h ; 76 1b ; 0xf4cca
+ cmp dx, strict byte 00004h ; 83 fa 04 ; 0xf4ccc
+ je short 04d03h ; 74 32 ; 0xf4ccf
+ cmp dx, strict byte 00003h ; 83 fa 03 ; 0xf4cd1
+ je short 04cf9h ; 74 23 ; 0xf4cd4
+ jmp short 04d32h ; eb 5a ; 0xf4cd6
+ cmp dx, strict byte 00001h ; 83 fa 01 ; 0xf4cd8
+ jne short 04d32h ; 75 55 ; 0xf4cdb
+ xor al, al ; 30 c0 ; 0xf4cdd boot.c:223
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf4cdf
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf4ce2 boot.c:224
+ jmp short 04d47h ; eb 60 ; 0xf4ce5 boot.c:225
+ mov bx, 0037ch ; bb 7c 03 ; 0xf4ce7 boot.c:38
+ mov es, di ; 8e c7 ; 0xf4cea
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4cec
+ add AL, strict byte 080h ; 04 80 ; 0xf4cef boot.c:231
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf4cf1
+ mov byte [bp-008h], dh ; 88 76 f8 ; 0xf4cf4 boot.c:232
+ jmp short 04d47h ; eb 4e ; 0xf4cf7 boot.c:233
+ mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xf4cf9 boot.c:236
+ mov byte [bp-008h], 001h ; c6 46 f8 01 ; 0xf4cfd boot.c:237
+ jmp short 04d0dh ; eb 0a ; 0xf4d01 boot.c:238
+ mov byte [bp-00ah], 001h ; c6 46 f6 01 ; 0xf4d03 boot.c:239
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf4d07 boot.c:255
+ je short 04d47h ; 74 3a ; 0xf4d0b
+ call 03d33h ; e8 23 f0 ; 0xf4d0d boot.c:256
+ mov dx, ax ; 89 c2 ; 0xf4d10
+ test AL, strict byte 0ffh ; a8 ff ; 0xf4d12 boot.c:259
+ je short 04d39h ; 74 23 ; 0xf4d14
+ call 04be8h ; e8 cf fe ; 0xf4d16 boot.c:260
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf4d19 boot.c:261
+ xor ah, ah ; 30 e4 ; 0xf4d1c
+ push ax ; 50 ; 0xf4d1e
+ mov bl, byte [bp-006h] ; 8a 5e fa ; 0xf4d1f
+ xor bh, bh ; 30 ff ; 0xf4d22
+ mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xf4d24
+ xor dh, dh ; 30 f6 ; 0xf4d27
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf4d29
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf4d2c
+ call 04b52h ; e8 20 fe ; 0xf4d2f
+ xor ax, ax ; 31 c0 ; 0xf4d32
+ xor dx, dx ; 31 d2 ; 0xf4d34
+ jmp near 04e63h ; e9 2a 01 ; 0xf4d36
+ mov bx, 00372h ; bb 72 03 ; 0xf4d39 boot.c:48
+ mov es, di ; 8e c7 ; 0xf4d3c
+ mov si, word [es:bx] ; 26 8b 37 ; 0xf4d3e
+ shr dx, 008h ; c1 ea 08 ; 0xf4d41 boot.c:266
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf4d44
+ cmp byte [bp-00ah], 001h ; 80 7e f6 01 ; 0xf4d47 boot.c:272
+ jne short 04da2h ; 75 55 ; 0xf4d4b
+ xor si, si ; 31 f6 ; 0xf4d4d boot.c:275
+ mov ax, 0e200h ; b8 00 e2 ; 0xf4d4f
+ mov es, ax ; 8e c0 ; 0xf4d52
+ cmp word [es:si], 0aa55h ; 26 81 3c 55 aa ; 0xf4d54 boot.c:276
+ jne short 04d19h ; 75 be ; 0xf4d59
+ mov cx, ax ; 89 c1 ; 0xf4d5b boot.c:282
+ mov si, word [es:si+01ah] ; 26 8b 74 1a ; 0xf4d5d
+ cmp word [es:si+002h], 0506eh ; 26 81 7c 02 6e 50 ; 0xf4d61 boot.c:283
+ jne short 04d19h ; 75 b0 ; 0xf4d67
+ cmp word [es:si], 05024h ; 26 81 3c 24 50 ; 0xf4d69
+ jne short 04d19h ; 75 a9 ; 0xf4d6e
+ mov bx, word [es:si+00eh] ; 26 8b 5c 0e ; 0xf4d70 boot.c:285
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf4d74
+ mov ax, word [es:bx+002h] ; 26 8b 47 02 ; 0xf4d77
+ cmp ax, 06568h ; 3d 68 65 ; 0xf4d7b boot.c:286
+ jne short 04da4h ; 75 24 ; 0xf4d7e
+ cmp dx, 07445h ; 81 fa 45 74 ; 0xf4d80
+ jne short 04da4h ; 75 1e ; 0xf4d84
+ mov bl, byte [bp-006h] ; 8a 5e fa ; 0xf4d86 boot.c:288
+ xor bh, bh ; 30 ff ; 0xf4d89
+ mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xf4d8b
+ xor dh, dh ; 30 f6 ; 0xf4d8e
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf4d90
+ xor ah, ah ; 30 e4 ; 0xf4d93
+ call 04b07h ; e8 6f fd ; 0xf4d95
+ mov word [bp-010h], strict word 00006h ; c7 46 f0 06 00 ; 0xf4d98 boot.c:289
+ mov word [bp-00eh], cx ; 89 4e f2 ; 0xf4d9d
+ jmp short 04dc3h ; eb 21 ; 0xf4da0 boot.c:292
+ jmp short 04dc9h ; eb 25 ; 0xf4da2
+ mov bl, byte [bp-006h] ; 8a 5e fa ; 0xf4da4 boot.c:295
+ xor bh, bh ; 30 ff ; 0xf4da7
+ mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xf4da9
+ xor dh, dh ; 30 f6 ; 0xf4dac
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf4dae
+ xor ah, ah ; 30 e4 ; 0xf4db1
+ call 04b07h ; e8 51 fd ; 0xf4db3
+ sti ; fb ; 0xf4db6 boot.c:296
+ mov word [bp-00eh], cx ; 89 4e f2 ; 0xf4db7 boot.c:297
+ mov es, cx ; 8e c1 ; 0xf4dba
+ mov ax, word [es:si+01ah] ; 26 8b 44 1a ; 0xf4dbc
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf4dc0
+ call far [bp-010h] ; ff 5e f0 ; 0xf4dc3 boot.c:298
+ jmp near 04d19h ; e9 50 ff ; 0xf4dc6 boot.c:301
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf4dc9 boot.c:309
+ jne short 04df6h ; 75 27 ; 0xf4dcd
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf4dcf
+ jne short 04df6h ; 75 21 ; 0xf4dd3
+ mov si, 007c0h ; be c0 07 ; 0xf4dd5 boot.c:310
+ mov es, si ; 8e c6 ; 0xf4dd8 boot.c:312
+ mov dl, byte [bp-006h] ; 8a 56 fa ; 0xf4dda
+ mov ax, 00201h ; b8 01 02 ; 0xf4ddd
+ mov DH, strict byte 000h ; b6 00 ; 0xf4de0
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf4de2
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xf4de5
+ int 013h ; cd 13 ; 0xf4de7
+ mov ax, strict word 00000h ; b8 00 00 ; 0xf4de9
+ sbb ax, strict byte 00000h ; 83 d8 00 ; 0xf4dec
+ test ax, ax ; 85 c0 ; 0xf4def boot.c:313
+ je short 04df6h ; 74 03 ; 0xf4df1
+ jmp near 04d19h ; e9 23 ff ; 0xf4df3
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf4df6 boot.c:328
+ je short 04e00h ; 74 04 ; 0xf4dfa
+ xor al, al ; 30 c0 ; 0xf4dfc
+ jmp short 04e02h ; eb 02 ; 0xf4dfe boot.c:329
+ mov AL, strict byte 001h ; b0 01 ; 0xf4e00
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf4e02 boot.c:333
+ je short 04e0ah ; 74 02 ; 0xf4e06
+ mov AL, strict byte 001h ; b0 01 ; 0xf4e08 boot.c:334
+ xor bx, bx ; 31 db ; 0xf4e0a boot.c:48
+ mov es, si ; 8e c6 ; 0xf4e0c
+ mov cx, word [es:bx] ; 26 8b 0f ; 0xf4e0e
+ mov bx, strict word 00004h ; bb 04 00 ; 0xf4e11 boot.c:48
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf4e14
+ cmp cx, dx ; 39 d1 ; 0xf4e17 boot.c:49
+ je short 04e2ah ; 74 0f ; 0xf4e19
+ test al, al ; 84 c0 ; 0xf4e1b
+ jne short 04e42h ; 75 23 ; 0xf4e1d
+ mov bx, 001feh ; bb fe 01 ; 0xf4e1f boot.c:48
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf4e22
+ cmp ax, 0aa55h ; 3d 55 aa ; 0xf4e25 boot.c:49
+ je short 04e42h ; 74 18 ; 0xf4e28
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf4e2a boot.c:340
+ xor ah, ah ; 30 e4 ; 0xf4e2d
+ push ax ; 50 ; 0xf4e2f
+ mov bl, byte [bp-006h] ; 8a 5e fa ; 0xf4e30
+ xor bh, bh ; 30 ff ; 0xf4e33
+ mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xf4e35
+ xor dh, dh ; 30 f6 ; 0xf4e38
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf4e3a
+ xor cx, cx ; 31 c9 ; 0xf4e3d
+ jmp near 04d2fh ; e9 ed fe ; 0xf4e3f
+ mov bl, byte [bp-006h] ; 8a 5e fa ; 0xf4e42 boot.c:346
+ xor bh, bh ; 30 ff ; 0xf4e45
+ mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xf4e47
+ xor dh, dh ; 30 f6 ; 0xf4e4a
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf4e4c
+ xor ah, ah ; 30 e4 ; 0xf4e4f
+ call 04b07h ; e8 b3 fc ; 0xf4e51
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4e54 boot.c:352
+ xor ah, ah ; 30 e4 ; 0xf4e57
+ mov bx, ax ; 89 c3 ; 0xf4e59
+ xor dx, dx ; 31 d2 ; 0xf4e5b
+ xor al, al ; 30 c0 ; 0xf4e5d
+ add ax, si ; 01 f0 ; 0xf4e5f
+ adc dx, bx ; 11 da ; 0xf4e61
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf4e63 boot.c:353
+ pop di ; 5f ; 0xf4e66
+ pop si ; 5e ; 0xf4e67
+ pop bp ; 5d ; 0xf4e68
+ retn ; c3 ; 0xf4e69
+ ; disGetNextSymbol 0xf4e6a LB 0x505e -> off=0x0 cb=0000000000000013 uValue=00000000000f386a 'keyboard_panic'
+keyboard_panic: ; 0xf4e6a LB 0x13
+ push bp ; 55 ; 0xf4e6a keyboard.c:194
+ mov bp, sp ; 89 e5 ; 0xf4e6b
+ push ax ; 50 ; 0xf4e6d keyboard.c:199
+ push 00574h ; 68 74 05 ; 0xf4e6e
+ push strict byte 00007h ; 6a 07 ; 0xf4e71
+ call 018ffh ; e8 89 ca ; 0xf4e73
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf4e76
+ mov sp, bp ; 89 ec ; 0xf4e79 keyboard.c:200
+ pop bp ; 5d ; 0xf4e7b
+ retn ; c3 ; 0xf4e7c
+ ; disGetNextSymbol 0xf4e7d LB 0x504b -> off=0x0 cb=000000000000026a uValue=00000000000f387d 'keyboard_init'
+keyboard_init: ; 0xf4e7d LB 0x26a
+ push bp ; 55 ; 0xf4e7d keyboard.c:208
+ mov bp, sp ; 89 e5 ; 0xf4e7e
+ mov AL, strict byte 0aah ; b0 aa ; 0xf4e80 keyboard.c:214
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4e82
+ out DX, AL ; ee ; 0xf4e85
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4e86 keyboard.c:217
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4e89 keyboard.c:218
+ in AL, DX ; ec ; 0xf4e8c
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4e8d
+ test AL, strict byte 002h ; a8 02 ; 0xf4e8f
+ je short 04ea0h ; 74 0d ; 0xf4e91
+ dec bx ; 4b ; 0xf4e93
+ test bx, bx ; 85 db ; 0xf4e94
+ jbe short 04ea0h ; 76 08 ; 0xf4e96
+ xor al, al ; 30 c0 ; 0xf4e98
+ mov dx, 00080h ; ba 80 00 ; 0xf4e9a
+ out DX, AL ; ee ; 0xf4e9d
+ jmp short 04e89h ; eb e9 ; 0xf4e9e
+ test bx, bx ; 85 db ; 0xf4ea0 keyboard.c:219
+ jne short 04ea9h ; 75 05 ; 0xf4ea2
+ xor ax, ax ; 31 c0 ; 0xf4ea4
+ call 04e6ah ; e8 c1 ff ; 0xf4ea6
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4ea9 keyboard.c:222
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4eac keyboard.c:223
+ in AL, DX ; ec ; 0xf4eaf
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4eb0
+ test AL, strict byte 001h ; a8 01 ; 0xf4eb2
+ jne short 04ec3h ; 75 0d ; 0xf4eb4
+ dec bx ; 4b ; 0xf4eb6
+ test bx, bx ; 85 db ; 0xf4eb7
+ jbe short 04ec3h ; 76 08 ; 0xf4eb9
+ mov AL, strict byte 001h ; b0 01 ; 0xf4ebb
+ mov dx, 00080h ; ba 80 00 ; 0xf4ebd
+ out DX, AL ; ee ; 0xf4ec0
+ jmp short 04each ; eb e9 ; 0xf4ec1
+ test bx, bx ; 85 db ; 0xf4ec3 keyboard.c:224
+ jne short 04ecdh ; 75 06 ; 0xf4ec5
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf4ec7
+ call 04e6ah ; e8 9d ff ; 0xf4eca
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf4ecd keyboard.c:227
+ in AL, DX ; ec ; 0xf4ed0
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4ed1
+ cmp ax, strict word 00055h ; 3d 55 00 ; 0xf4ed3
+ je short 04edeh ; 74 06 ; 0xf4ed6
+ mov ax, 003dfh ; b8 df 03 ; 0xf4ed8 keyboard.c:228
+ call 04e6ah ; e8 8c ff ; 0xf4edb
+ mov AL, strict byte 0abh ; b0 ab ; 0xf4ede keyboard.c:232
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4ee0
+ out DX, AL ; ee ; 0xf4ee3
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4ee4 keyboard.c:235
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4ee7 keyboard.c:236
+ in AL, DX ; ec ; 0xf4eea
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4eeb
+ test AL, strict byte 002h ; a8 02 ; 0xf4eed
+ je short 04efeh ; 74 0d ; 0xf4eef
+ dec bx ; 4b ; 0xf4ef1
+ test bx, bx ; 85 db ; 0xf4ef2
+ jbe short 04efeh ; 76 08 ; 0xf4ef4
+ mov AL, strict byte 010h ; b0 10 ; 0xf4ef6
+ mov dx, 00080h ; ba 80 00 ; 0xf4ef8
+ out DX, AL ; ee ; 0xf4efb
+ jmp short 04ee7h ; eb e9 ; 0xf4efc
+ test bx, bx ; 85 db ; 0xf4efe keyboard.c:237
+ jne short 04f08h ; 75 06 ; 0xf4f00
+ mov ax, strict word 0000ah ; b8 0a 00 ; 0xf4f02
+ call 04e6ah ; e8 62 ff ; 0xf4f05
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4f08 keyboard.c:240
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4f0b keyboard.c:241
+ in AL, DX ; ec ; 0xf4f0e
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4f0f
+ test AL, strict byte 001h ; a8 01 ; 0xf4f11
+ jne short 04f22h ; 75 0d ; 0xf4f13
+ dec bx ; 4b ; 0xf4f15
+ test bx, bx ; 85 db ; 0xf4f16
+ jbe short 04f22h ; 76 08 ; 0xf4f18
+ mov AL, strict byte 011h ; b0 11 ; 0xf4f1a
+ mov dx, 00080h ; ba 80 00 ; 0xf4f1c
+ out DX, AL ; ee ; 0xf4f1f
+ jmp short 04f0bh ; eb e9 ; 0xf4f20
+ test bx, bx ; 85 db ; 0xf4f22 keyboard.c:242
+ jne short 04f2ch ; 75 06 ; 0xf4f24
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf4f26
+ call 04e6ah ; e8 3e ff ; 0xf4f29
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf4f2c keyboard.c:246
+ in AL, DX ; ec ; 0xf4f2f
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4f30
+ test ax, ax ; 85 c0 ; 0xf4f32
+ je short 04f3ch ; 74 06 ; 0xf4f34
+ mov ax, 003e0h ; b8 e0 03 ; 0xf4f36 keyboard.c:247
+ call 04e6ah ; e8 2e ff ; 0xf4f39
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf4f3c keyboard.c:253
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf4f3e
+ out DX, AL ; ee ; 0xf4f41
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4f42 keyboard.c:256
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4f45 keyboard.c:257
+ in AL, DX ; ec ; 0xf4f48
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4f49
+ test AL, strict byte 002h ; a8 02 ; 0xf4f4b
+ je short 04f5ch ; 74 0d ; 0xf4f4d
+ dec bx ; 4b ; 0xf4f4f
+ test bx, bx ; 85 db ; 0xf4f50
+ jbe short 04f5ch ; 76 08 ; 0xf4f52
+ mov AL, strict byte 020h ; b0 20 ; 0xf4f54
+ mov dx, 00080h ; ba 80 00 ; 0xf4f56
+ out DX, AL ; ee ; 0xf4f59
+ jmp short 04f45h ; eb e9 ; 0xf4f5a
+ test bx, bx ; 85 db ; 0xf4f5c keyboard.c:258
+ jne short 04f66h ; 75 06 ; 0xf4f5e
+ mov ax, strict word 00014h ; b8 14 00 ; 0xf4f60
+ call 04e6ah ; e8 04 ff ; 0xf4f63
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4f66 keyboard.c:261
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4f69 keyboard.c:262
+ in AL, DX ; ec ; 0xf4f6c
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4f6d
+ test AL, strict byte 001h ; a8 01 ; 0xf4f6f
+ jne short 04f80h ; 75 0d ; 0xf4f71
+ dec bx ; 4b ; 0xf4f73
+ test bx, bx ; 85 db ; 0xf4f74
+ jbe short 04f80h ; 76 08 ; 0xf4f76
+ mov AL, strict byte 021h ; b0 21 ; 0xf4f78
+ mov dx, 00080h ; ba 80 00 ; 0xf4f7a
+ out DX, AL ; ee ; 0xf4f7d
+ jmp short 04f69h ; eb e9 ; 0xf4f7e
+ test bx, bx ; 85 db ; 0xf4f80 keyboard.c:263
+ jne short 04f8ah ; 75 06 ; 0xf4f82
+ mov ax, strict word 00015h ; b8 15 00 ; 0xf4f84
+ call 04e6ah ; e8 e0 fe ; 0xf4f87
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf4f8a keyboard.c:266
+ in AL, DX ; ec ; 0xf4f8d
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4f8e
+ cmp ax, 000fah ; 3d fa 00 ; 0xf4f90
+ je short 04f9bh ; 74 06 ; 0xf4f93
+ mov ax, 003e1h ; b8 e1 03 ; 0xf4f95 keyboard.c:267
+ call 04e6ah ; e8 cf fe ; 0xf4f98
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4f9b keyboard.c:271
+ in AL, DX ; ec ; 0xf4f9e
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4f9f
+ test AL, strict byte 001h ; a8 01 ; 0xf4fa1
+ jne short 04fadh ; 75 08 ; 0xf4fa3
+ mov AL, strict byte 031h ; b0 31 ; 0xf4fa5
+ mov dx, 00080h ; ba 80 00 ; 0xf4fa7
+ out DX, AL ; ee ; 0xf4faa
+ jmp short 04f9bh ; eb ee ; 0xf4fab
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf4fad keyboard.c:273
+ in AL, DX ; ec ; 0xf4fb0
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4fb1
+ cmp ax, 000aah ; 3d aa 00 ; 0xf4fb3
+ je short 04fc6h ; 74 0e ; 0xf4fb6
+ in AL, DX ; ec ; 0xf4fb8
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4fb9
+ cmp ax, 000aah ; 3d aa 00 ; 0xf4fbb
+ je short 04fc6h ; 74 06 ; 0xf4fbe
+ mov ax, 003e2h ; b8 e2 03 ; 0xf4fc0 keyboard.c:274
+ call 04e6ah ; e8 a4 fe ; 0xf4fc3
+ mov AL, strict byte 0f5h ; b0 f5 ; 0xf4fc6 keyboard.c:278
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf4fc8
+ out DX, AL ; ee ; 0xf4fcb
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4fcc keyboard.c:281
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4fcf keyboard.c:282
+ in AL, DX ; ec ; 0xf4fd2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4fd3
+ test AL, strict byte 002h ; a8 02 ; 0xf4fd5
+ je short 04fe6h ; 74 0d ; 0xf4fd7
+ dec bx ; 4b ; 0xf4fd9
+ test bx, bx ; 85 db ; 0xf4fda
+ jbe short 04fe6h ; 76 08 ; 0xf4fdc
+ mov AL, strict byte 040h ; b0 40 ; 0xf4fde
+ mov dx, 00080h ; ba 80 00 ; 0xf4fe0
+ out DX, AL ; ee ; 0xf4fe3
+ jmp short 04fcfh ; eb e9 ; 0xf4fe4
+ test bx, bx ; 85 db ; 0xf4fe6 keyboard.c:283
+ jne short 04ff0h ; 75 06 ; 0xf4fe8
+ mov ax, strict word 00028h ; b8 28 00 ; 0xf4fea
+ call 04e6ah ; e8 7a fe ; 0xf4fed
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4ff0 keyboard.c:286
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4ff3 keyboard.c:287
+ in AL, DX ; ec ; 0xf4ff6
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4ff7
+ test AL, strict byte 001h ; a8 01 ; 0xf4ff9
+ jne short 0500ah ; 75 0d ; 0xf4ffb
+ dec bx ; 4b ; 0xf4ffd
+ test bx, bx ; 85 db ; 0xf4ffe
+ jbe short 0500ah ; 76 08 ; 0xf5000
+ mov AL, strict byte 041h ; b0 41 ; 0xf5002
+ mov dx, 00080h ; ba 80 00 ; 0xf5004
+ out DX, AL ; ee ; 0xf5007
+ jmp short 04ff3h ; eb e9 ; 0xf5008
+ test bx, bx ; 85 db ; 0xf500a keyboard.c:288
+ jne short 05014h ; 75 06 ; 0xf500c
+ mov ax, strict word 00029h ; b8 29 00 ; 0xf500e
+ call 04e6ah ; e8 56 fe ; 0xf5011
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5014 keyboard.c:291
+ in AL, DX ; ec ; 0xf5017
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5018
+ cmp ax, 000fah ; 3d fa 00 ; 0xf501a
+ je short 05025h ; 74 06 ; 0xf501d
+ mov ax, 003e3h ; b8 e3 03 ; 0xf501f keyboard.c:292
+ call 04e6ah ; e8 45 fe ; 0xf5022
+ mov AL, strict byte 060h ; b0 60 ; 0xf5025 keyboard.c:296
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5027
+ out DX, AL ; ee ; 0xf502a
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf502b keyboard.c:299
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf502e keyboard.c:300
+ in AL, DX ; ec ; 0xf5031
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5032
+ test AL, strict byte 002h ; a8 02 ; 0xf5034
+ je short 05045h ; 74 0d ; 0xf5036
+ dec bx ; 4b ; 0xf5038
+ test bx, bx ; 85 db ; 0xf5039
+ jbe short 05045h ; 76 08 ; 0xf503b
+ mov AL, strict byte 050h ; b0 50 ; 0xf503d
+ mov dx, 00080h ; ba 80 00 ; 0xf503f
+ out DX, AL ; ee ; 0xf5042
+ jmp short 0502eh ; eb e9 ; 0xf5043
+ test bx, bx ; 85 db ; 0xf5045 keyboard.c:301
+ jne short 0504fh ; 75 06 ; 0xf5047
+ mov ax, strict word 00032h ; b8 32 00 ; 0xf5049
+ call 04e6ah ; e8 1b fe ; 0xf504c
+ mov AL, strict byte 065h ; b0 65 ; 0xf504f keyboard.c:304
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5051
+ out DX, AL ; ee ; 0xf5054
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf5055 keyboard.c:307
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5058 keyboard.c:308
+ in AL, DX ; ec ; 0xf505b
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf505c
+ test AL, strict byte 002h ; a8 02 ; 0xf505e
+ je short 0506fh ; 74 0d ; 0xf5060
+ dec bx ; 4b ; 0xf5062
+ test bx, bx ; 85 db ; 0xf5063
+ jbe short 0506fh ; 76 08 ; 0xf5065
+ mov AL, strict byte 060h ; b0 60 ; 0xf5067
+ mov dx, 00080h ; ba 80 00 ; 0xf5069
+ out DX, AL ; ee ; 0xf506c
+ jmp short 05058h ; eb e9 ; 0xf506d
+ test bx, bx ; 85 db ; 0xf506f keyboard.c:309
+ jne short 05079h ; 75 06 ; 0xf5071
+ mov ax, strict word 0003ch ; b8 3c 00 ; 0xf5073
+ call 04e6ah ; e8 f1 fd ; 0xf5076
+ mov AL, strict byte 0f4h ; b0 f4 ; 0xf5079 keyboard.c:312
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf507b
+ out DX, AL ; ee ; 0xf507e
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf507f keyboard.c:315
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5082 keyboard.c:316
+ in AL, DX ; ec ; 0xf5085
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5086
+ test AL, strict byte 002h ; a8 02 ; 0xf5088
+ je short 05099h ; 74 0d ; 0xf508a
+ dec bx ; 4b ; 0xf508c
+ test bx, bx ; 85 db ; 0xf508d
+ jbe short 05099h ; 76 08 ; 0xf508f
+ mov AL, strict byte 070h ; b0 70 ; 0xf5091
+ mov dx, 00080h ; ba 80 00 ; 0xf5093
+ out DX, AL ; ee ; 0xf5096
+ jmp short 05082h ; eb e9 ; 0xf5097
+ test bx, bx ; 85 db ; 0xf5099 keyboard.c:317
+ jne short 050a3h ; 75 06 ; 0xf509b
+ mov ax, strict word 00046h ; b8 46 00 ; 0xf509d
+ call 04e6ah ; e8 c7 fd ; 0xf50a0
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf50a3 keyboard.c:320
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf50a6 keyboard.c:321
+ in AL, DX ; ec ; 0xf50a9
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf50aa
+ test AL, strict byte 001h ; a8 01 ; 0xf50ac
+ jne short 050bdh ; 75 0d ; 0xf50ae
+ dec bx ; 4b ; 0xf50b0
+ test bx, bx ; 85 db ; 0xf50b1
+ jbe short 050bdh ; 76 08 ; 0xf50b3
+ mov AL, strict byte 071h ; b0 71 ; 0xf50b5
+ mov dx, 00080h ; ba 80 00 ; 0xf50b7
+ out DX, AL ; ee ; 0xf50ba
+ jmp short 050a6h ; eb e9 ; 0xf50bb
+ test bx, bx ; 85 db ; 0xf50bd keyboard.c:322
+ jne short 050c7h ; 75 06 ; 0xf50bf
+ mov ax, strict word 00046h ; b8 46 00 ; 0xf50c1
+ call 04e6ah ; e8 a3 fd ; 0xf50c4
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf50c7 keyboard.c:325
+ in AL, DX ; ec ; 0xf50ca
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf50cb
+ cmp ax, 000fah ; 3d fa 00 ; 0xf50cd
+ je short 050d8h ; 74 06 ; 0xf50d0
+ mov ax, 003e4h ; b8 e4 03 ; 0xf50d2 keyboard.c:326
+ call 04e6ah ; e8 92 fd ; 0xf50d5
+ mov AL, strict byte 0a8h ; b0 a8 ; 0xf50d8 keyboard.c:330
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf50da
+ out DX, AL ; ee ; 0xf50dd
+ xor ax, ax ; 31 c0 ; 0xf50de keyboard.c:335
+ call 06511h ; e8 2e 14 ; 0xf50e0
+ mov sp, bp ; 89 ec ; 0xf50e3 keyboard.c:336
+ pop bp ; 5d ; 0xf50e5
+ retn ; c3 ; 0xf50e6
+ ; disGetNextSymbol 0xf50e7 LB 0x4de1 -> off=0x0 cb=0000000000000053 uValue=00000000000f3ae7 'enqueue_key'
+enqueue_key: ; 0xf50e7 LB 0x53
+ push bx ; 53 ; 0xf50e7 keyboard.c:339
+ push cx ; 51 ; 0xf50e8
+ push si ; 56 ; 0xf50e9
+ push di ; 57 ; 0xf50ea
+ push bp ; 55 ; 0xf50eb
+ mov bp, sp ; 89 e5 ; 0xf50ec
+ mov dh, al ; 88 c6 ; 0xf50ee
+ mov bx, 00080h ; bb 80 00 ; 0xf50f0 keyboard.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf50f3
+ mov es, ax ; 8e c0 ; 0xf50f6
+ mov di, word [es:bx] ; 26 8b 3f ; 0xf50f8
+ mov bx, 00082h ; bb 82 00 ; 0xf50fb keyboard.c:48
+ mov si, word [es:bx] ; 26 8b 37 ; 0xf50fe
+ mov bx, strict word 0001ah ; bb 1a 00 ; 0xf5101 keyboard.c:48
+ mov cx, word [es:bx] ; 26 8b 0f ; 0xf5104
+ mov bx, strict word 0001ch ; bb 1c 00 ; 0xf5107 keyboard.c:48
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf510a
+ mov bx, ax ; 89 c3 ; 0xf510d keyboard.c:354
+ inc ax ; 40 ; 0xf510f keyboard.c:355
+ inc ax ; 40 ; 0xf5110
+ cmp ax, si ; 39 f0 ; 0xf5111 keyboard.c:356
+ jc short 05117h ; 72 02 ; 0xf5113
+ mov ax, di ; 89 f8 ; 0xf5115 keyboard.c:357
+ cmp ax, cx ; 39 c8 ; 0xf5117 keyboard.c:359
+ jne short 0511fh ; 75 04 ; 0xf5119
+ xor ax, cx ; 31 c8 ; 0xf511b keyboard.c:360
+ jmp short 05134h ; eb 15 ; 0xf511d
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf511f keyboard.c:43
+ mov es, cx ; 8e c1 ; 0xf5122
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5124
+ inc bx ; 43 ; 0xf5127 keyboard.c:363
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf5128 keyboard.c:43
+ mov bx, strict word 0001ch ; bb 1c 00 ; 0xf512b keyboard.c:53
+ mov word [es:bx], ax ; 26 89 07 ; 0xf512e
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf5131 keyboard.c:365
+ pop bp ; 5d ; 0xf5134 keyboard.c:366
+ pop di ; 5f ; 0xf5135
+ pop si ; 5e ; 0xf5136
+ pop cx ; 59 ; 0xf5137
+ pop bx ; 5b ; 0xf5138
+ retn ; c3 ; 0xf5139
+ ; disGetNextSymbol 0xf513a LB 0x4d8e -> off=0x35 cb=00000000000003c4 uValue=00000000000f3b6f 'int09_function'
+ db 0d4h, 0c6h, 0c5h, 0bah, 0b8h, 0b6h, 0aah, 09dh, 054h, 053h, 046h, 045h, 03ah, 038h, 036h, 02ah
+ db 01dh, 0e7h, 053h, 026h, 052h, 0f4h, 051h, 0f4h, 051h, 086h, 052h, 0cfh, 051h, 0f7h, 052h, 052h
+ db 053h, 0cch, 053h, 0b1h, 053h, 055h, 052h, 0f4h, 051h, 0f4h, 051h, 0d4h, 052h, 0e6h, 051h, 03ah
+ db 053h, 09ch, 053h, 0c7h, 053h
+int09_function: ; 0xf516f LB 0x3c4
+ push bp ; 55 ; 0xf516f keyboard.c:371
+ mov bp, sp ; 89 e5 ; 0xf5170
+ push si ; 56 ; 0xf5172
+ push di ; 57 ; 0xf5173
+ push ax ; 50 ; 0xf5174
+ push ax ; 50 ; 0xf5175
+ mov al, byte [bp+014h] ; 8a 46 14 ; 0xf5176 keyboard.c:382
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf5179
+ test al, al ; 84 c0 ; 0xf517c keyboard.c:384
+ jne short 05199h ; 75 19 ; 0xf517e
+ mov bx, 00da0h ; bb a0 0d ; 0xf5180 keyboard.c:385
+ mov cx, ds ; 8c d9 ; 0xf5183
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5185
+ call 018bch ; e8 31 c7 ; 0xf5188
+ push 00587h ; 68 87 05 ; 0xf518b
+ push strict byte 00004h ; 6a 04 ; 0xf518e
+ call 018ffh ; e8 6c c7 ; 0xf5190
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf5193
+ jmp near 052cdh ; e9 34 01 ; 0xf5196 keyboard.c:386
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5199 keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf519c
+ mov es, ax ; 8e c0 ; 0xf519f
+ mov bl, byte [es:bx] ; 26 8a 1f ; 0xf51a1
+ mov dl, bl ; 88 da ; 0xf51a4 keyboard.c:39
+ mov si, 00096h ; be 96 00 ; 0xf51a6 keyboard.c:38
+ mov bh, byte [es:si] ; 26 8a 3c ; 0xf51a9
+ mov byte [bp-006h], bh ; 88 7e fa ; 0xf51ac keyboard.c:39
+ mov si, strict word 00017h ; be 17 00 ; 0xf51af keyboard.c:38
+ mov ah, byte [es:si] ; 26 8a 24 ; 0xf51b2
+ mov dh, ah ; 88 e6 ; 0xf51b5 keyboard.c:39
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf51b7 keyboard.c:394
+ push CS ; 0e ; 0xf51ba
+ pop ES ; 07 ; 0xf51bb
+ mov cx, strict word 00012h ; b9 12 00 ; 0xf51bc
+ mov di, 0513ah ; bf 3a 51 ; 0xf51bf
+ repne scasb ; f2 ae ; 0xf51c2
+ sal cx, 1 ; d1 e1 ; 0xf51c4
+ mov di, cx ; 89 cf ; 0xf51c6
+ mov cx, word [cs:di+0514bh] ; 2e 8b 8d 4b 51 ; 0xf51c8
+ jmp cx ; ff e1 ; 0xf51cd
+ xor dh, 040h ; 80 f6 40 ; 0xf51cf keyboard.c:396
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf51d2 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf51d5
+ mov es, ax ; 8e c0 ; 0xf51d8
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf51da
+ or dl, 040h ; 80 ca 40 ; 0xf51dd keyboard.c:398
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf51e0 keyboard.c:43
+ jmp near 053c1h ; e9 db 01 ; 0xf51e3
+ and dl, 0bfh ; 80 e2 bf ; 0xf51e6 keyboard.c:402
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf51e9 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf51ec
+ mov es, ax ; 8e c0 ; 0xf51ef
+ jmp near 053c1h ; e9 cd 01 ; 0xf51f1
+ test byte [bp-006h], 002h ; f6 46 fa 02 ; 0xf51f4 keyboard.c:411
+ jne short 05253h ; 75 59 ; 0xf51f8
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf51fa keyboard.c:412
+ and AL, strict byte 07fh ; 24 7f ; 0xf51fd
+ cmp AL, strict byte 02ah ; 3c 2a ; 0xf51ff
+ jne short 05208h ; 75 05 ; 0xf5201
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf5203
+ jmp short 0520bh ; eb 03 ; 0xf5206
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf5208
+ test byte [bp-008h], 080h ; f6 46 f8 80 ; 0xf520b keyboard.c:413
+ je short 05217h ; 74 06 ; 0xf520f
+ not al ; f6 d0 ; 0xf5211 keyboard.c:414
+ and dh, al ; 20 c6 ; 0xf5213
+ jmp short 05219h ; eb 02 ; 0xf5215 keyboard.c:415
+ or dh, al ; 08 c6 ; 0xf5217 keyboard.c:416
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf5219 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf521c
+ mov es, ax ; 8e c0 ; 0xf521f
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf5221
+ jmp short 05253h ; eb 2d ; 0xf5224 keyboard.c:419
+ test bh, 001h ; f6 c7 01 ; 0xf5226 keyboard.c:422
+ jne short 05284h ; 75 59 ; 0xf5229
+ or dh, 004h ; 80 ce 04 ; 0xf522b keyboard.c:423
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf522e keyboard.c:41
+ mov bx, si ; 89 f3 ; 0xf5231
+ mov es, ax ; 8e c0 ; 0xf5233 keyboard.c:43
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf5235
+ test byte [bp-006h], 002h ; f6 46 fa 02 ; 0xf5238 keyboard.c:425
+ je short 0524ah ; 74 0c ; 0xf523c
+ or byte [bp-006h], 004h ; 80 4e fa 04 ; 0xf523e keyboard.c:426
+ mov bx, 00096h ; bb 96 00 ; 0xf5242 keyboard.c:41
+ mov dl, byte [bp-006h] ; 8a 56 fa ; 0xf5245
+ jmp short 05250h ; eb 06 ; 0xf5248 keyboard.c:428
+ or dl, 001h ; 80 ca 01 ; 0xf524a keyboard.c:429
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf524d keyboard.c:41
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5250 keyboard.c:43
+ jmp short 05284h ; eb 2f ; 0xf5253 keyboard.c:433
+ test bh, 001h ; f6 c7 01 ; 0xf5255 keyboard.c:435
+ jne short 052aeh ; 75 54 ; 0xf5258
+ and dh, 0fbh ; 80 e6 fb ; 0xf525a keyboard.c:436
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf525d keyboard.c:43
+ mov es, ax ; 8e c0 ; 0xf5260
+ mov byte [es:si], dh ; 26 88 34 ; 0xf5262
+ test bh, 002h ; f6 c7 02 ; 0xf5265 keyboard.c:438
+ je short 0527bh ; 74 11 ; 0xf5268
+ and bh, 0fbh ; 80 e7 fb ; 0xf526a keyboard.c:439
+ mov byte [bp-006h], bh ; 88 7e fa ; 0xf526d
+ mov bx, 00096h ; bb 96 00 ; 0xf5270 keyboard.c:43
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf5273
+ mov byte [es:bx], al ; 26 88 07 ; 0xf5276
+ jmp short 052aeh ; eb 33 ; 0xf5279 keyboard.c:441
+ and dl, 0feh ; 80 e2 fe ; 0xf527b keyboard.c:442
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf527e keyboard.c:43
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5281
+ jmp short 052aeh ; eb 28 ; 0xf5284 keyboard.c:446
+ or dh, 008h ; 80 ce 08 ; 0xf5286 keyboard.c:449
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5289 keyboard.c:41
+ mov bx, si ; 89 f3 ; 0xf528c
+ mov es, ax ; 8e c0 ; 0xf528e keyboard.c:43
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf5290
+ test byte [bp-006h], 002h ; f6 46 fa 02 ; 0xf5293 keyboard.c:451
+ je short 052a5h ; 74 0c ; 0xf5297
+ or byte [bp-006h], 008h ; 80 4e fa 08 ; 0xf5299 keyboard.c:452
+ mov bx, 00096h ; bb 96 00 ; 0xf529d keyboard.c:41
+ mov dl, byte [bp-006h] ; 8a 56 fa ; 0xf52a0
+ jmp short 052abh ; eb 06 ; 0xf52a3 keyboard.c:454
+ or dl, 002h ; 80 ca 02 ; 0xf52a5 keyboard.c:455
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf52a8 keyboard.c:41
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf52ab keyboard.c:43
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf52ae keyboard.c:458
+ and AL, strict byte 07fh ; 24 7f ; 0xf52b1
+ cmp AL, strict byte 01dh ; 3c 1d ; 0xf52b3
+ je short 052bbh ; 74 04 ; 0xf52b5
+ and byte [bp-006h], 0feh ; 80 66 fa fe ; 0xf52b7
+ and byte [bp-006h], 0fdh ; 80 66 fa fd ; 0xf52bb
+ mov bx, 00096h ; bb 96 00 ; 0xf52bf
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf52c2
+ mov es, ax ; 8e c0 ; 0xf52c5
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf52c7
+ mov byte [es:bx], al ; 26 88 07 ; 0xf52ca
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf52cd
+ pop di ; 5f ; 0xf52d0
+ pop si ; 5e ; 0xf52d1
+ pop bp ; 5d ; 0xf52d2
+ retn ; c3 ; 0xf52d3
+ and dh, 0f7h ; 80 e6 f7 ; 0xf52d4 keyboard.c:460
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf52d7 keyboard.c:43
+ mov es, ax ; 8e c0 ; 0xf52da
+ mov byte [es:si], dh ; 26 88 34 ; 0xf52dc
+ test bh, 002h ; f6 c7 02 ; 0xf52df keyboard.c:462
+ je short 052ech ; 74 08 ; 0xf52e2
+ and bh, 0f7h ; 80 e7 f7 ; 0xf52e4 keyboard.c:463
+ mov byte [bp-006h], bh ; 88 7e fa ; 0xf52e7
+ jmp short 05270h ; eb 84 ; 0xf52ea keyboard.c:464
+ and dl, 0fdh ; 80 e2 fd ; 0xf52ec keyboard.c:466
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf52ef keyboard.c:43
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf52f2
+ jmp short 052aeh ; eb b7 ; 0xf52f5 keyboard.c:469
+ test bh, 003h ; f6 c7 03 ; 0xf52f7 keyboard.c:472
+ jne short 05310h ; 75 14 ; 0xf52fa
+ or dl, 020h ; 80 ca 20 ; 0xf52fc keyboard.c:474
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf52ff keyboard.c:41
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5302
+ mov es, ax ; 8e c0 ; 0xf5305 keyboard.c:43
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5307
+ xor dh, 020h ; 80 f6 20 ; 0xf530a keyboard.c:476
+ jmp near 05395h ; e9 85 00 ; 0xf530d keyboard.c:477
+ or dl, 008h ; 80 ca 08 ; 0xf5310 keyboard.c:480
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5313 keyboard.c:41
+ mov es, ax ; 8e c0 ; 0xf5316
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5318
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf531b keyboard.c:43
+ mov ax, 000aeh ; b8 ae 00 ; 0xf531e keyboard.c:484
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5321
+ out DX, AL ; ee ; 0xf5324
+ call 0e034h ; e8 0c 8d ; 0xf5325 keyboard.c:485
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5328 keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf532b
+ mov es, ax ; 8e c0 ; 0xf532e
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf5330
+ test AL, strict byte 008h ; a8 08 ; 0xf5333 keyboard.c:39
+ jne short 05328h ; 75 f1 ; 0xf5335
+ jmp near 052aeh ; e9 74 ff ; 0xf5337 keyboard.c:492
+ test bh, 003h ; f6 c7 03 ; 0xf533a keyboard.c:494
+ je short 05342h ; 74 03 ; 0xf533d
+ jmp near 052aeh ; e9 6c ff ; 0xf533f
+ and dl, 0dfh ; 80 e2 df ; 0xf5342 keyboard.c:495
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5345 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5348
+ mov es, ax ; 8e c0 ; 0xf534b
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf534d
+ jmp short 0533fh ; eb ed ; 0xf5350 keyboard.c:498
+ test bh, 002h ; f6 c7 02 ; 0xf5352 keyboard.c:501
+ je short 05384h ; 74 2d ; 0xf5355
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5357 keyboard.c:46
+ mov bx, strict word 0001ah ; bb 1a 00 ; 0xf535a
+ mov es, ax ; 8e c0 ; 0xf535d keyboard.c:48
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf535f
+ mov bx, strict word 0001ch ; bb 1c 00 ; 0xf5362 keyboard.c:51
+ mov word [es:bx], ax ; 26 89 07 ; 0xf5365 keyboard.c:53
+ mov bx, strict word 00071h ; bb 71 00 ; 0xf5368 keyboard.c:41
+ mov AL, strict byte 080h ; b0 80 ; 0xf536b
+ mov byte [es:bx], al ; 26 88 07 ; 0xf536d keyboard.c:43
+ mov ax, 000aeh ; b8 ae 00 ; 0xf5370 keyboard.c:506
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5373
+ out DX, AL ; ee ; 0xf5376
+ push bp ; 55 ; 0xf5377 keyboard.c:507
+ int 01bh ; cd 1b ; 0xf5378
+ pop bp ; 5d ; 0xf537a
+ xor dx, dx ; 31 d2 ; 0xf537b keyboard.c:508
+ xor ax, ax ; 31 c0 ; 0xf537d
+ call 050e7h ; e8 65 fd ; 0xf537f
+ jmp short 0533fh ; eb bb ; 0xf5382 keyboard.c:509
+ or dl, 010h ; 80 ca 10 ; 0xf5384 keyboard.c:510
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5387 keyboard.c:41
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf538a
+ mov es, ax ; 8e c0 ; 0xf538d keyboard.c:43
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf538f
+ xor dh, 010h ; 80 f6 10 ; 0xf5392 keyboard.c:512
+ mov bx, si ; 89 f3 ; 0xf5395 keyboard.c:41
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf5397 keyboard.c:43
+ jmp short 0533fh ; eb a3 ; 0xf539a keyboard.c:515
+ test bh, 002h ; f6 c7 02 ; 0xf539c keyboard.c:518
+ jne short 0533fh ; 75 9e ; 0xf539f
+ and dl, 0efh ; 80 e2 ef ; 0xf53a1 keyboard.c:519
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf53a4 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf53a7
+ mov es, ax ; 8e c0 ; 0xf53aa
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf53ac
+ jmp short 0533fh ; eb 8e ; 0xf53af keyboard.c:522
+ test bl, 004h ; f6 c3 04 ; 0xf53b1 keyboard.c:525
+ jne short 0533fh ; 75 89 ; 0xf53b4
+ or dl, 004h ; 80 ca 04 ; 0xf53b6 keyboard.c:526
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf53b9 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf53bc
+ mov es, ax ; 8e c0 ; 0xf53bf
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf53c1
+ jmp near 052aeh ; e9 e7 fe ; 0xf53c4 keyboard.c:530
+ and dl, 0fbh ; 80 e2 fb ; 0xf53c7 keyboard.c:533
+ jmp short 053b9h ; eb ed ; 0xf53ca keyboard.c:534
+ mov al, ah ; 88 e0 ; 0xf53cc keyboard.c:539
+ and AL, strict byte 00ch ; 24 0c ; 0xf53ce
+ cmp AL, strict byte 00ch ; 3c 0c ; 0xf53d0
+ jne short 053e7h ; 75 13 ; 0xf53d2
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf53d4 keyboard.c:51
+ mov bx, strict word 00072h ; bb 72 00 ; 0xf53d7
+ mov cx, 01234h ; b9 34 12 ; 0xf53da
+ mov es, ax ; 8e c0 ; 0xf53dd keyboard.c:53
+ mov word [es:bx], cx ; 26 89 0f ; 0xf53df
+ jmp far 0f000h:0e05bh ; ea 5b e0 00 f0 ; 0xf53e2 keyboard.c:542
+ test dl, 008h ; f6 c2 08 ; 0xf53e7 keyboard.c:548
+ je short 053fdh ; 74 11 ; 0xf53ea
+ and dl, 0f7h ; 80 e2 f7 ; 0xf53ec keyboard.c:550
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf53ef keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf53f2
+ mov es, ax ; 8e c0 ; 0xf53f5
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf53f7
+ jmp near 052cdh ; e9 d0 fe ; 0xf53fa keyboard.c:552
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf53fd keyboard.c:555
+ test AL, strict byte 080h ; a8 80 ; 0xf5400
+ je short 05432h ; 74 2e ; 0xf5402
+ cmp AL, strict byte 0fah ; 3c fa ; 0xf5404 keyboard.c:557
+ jne short 05418h ; 75 10 ; 0xf5406
+ mov bx, 00097h ; bb 97 00 ; 0xf5408 keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf540b
+ mov es, ax ; 8e c0 ; 0xf540e
+ mov ah, byte [es:bx] ; 26 8a 27 ; 0xf5410
+ or ah, 010h ; 80 cc 10 ; 0xf5413 keyboard.c:39
+ jmp short 0542dh ; eb 15 ; 0xf5416 keyboard.c:560
+ cmp AL, strict byte 0feh ; 3c fe ; 0xf5418
+ je short 0541fh ; 74 03 ; 0xf541a
+ jmp near 052aeh ; e9 8f fe ; 0xf541c
+ mov bx, 00097h ; bb 97 00 ; 0xf541f keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5422
+ mov es, ax ; 8e c0 ; 0xf5425
+ mov ah, byte [es:bx] ; 26 8a 27 ; 0xf5427
+ or ah, 020h ; 80 cc 20 ; 0xf542a keyboard.c:39
+ mov byte [es:bx], ah ; 26 88 27 ; 0xf542d keyboard.c:43
+ jmp short 0541ch ; eb ea ; 0xf5430 keyboard.c:564
+ cmp byte [bp-008h], 058h ; 80 7e f8 58 ; 0xf5432 keyboard.c:566
+ jbe short 05457h ; 76 1f ; 0xf5436
+ mov bx, 00da0h ; bb a0 0d ; 0xf5438 keyboard.c:567
+ mov cx, ds ; 8c d9 ; 0xf543b
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf543d
+ call 018bch ; e8 79 c4 ; 0xf5440
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf5443
+ xor ah, ah ; 30 e4 ; 0xf5446
+ push ax ; 50 ; 0xf5448
+ push 005a1h ; 68 a1 05 ; 0xf5449
+ push strict byte 00004h ; 6a 04 ; 0xf544c
+ call 018ffh ; e8 ae c4 ; 0xf544e
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf5451
+ jmp near 052cdh ; e9 76 fe ; 0xf5454 keyboard.c:568
+ test dh, 008h ; f6 c6 08 ; 0xf5457 keyboard.c:570
+ je short 0546fh ; 74 13 ; 0xf545a
+ mov bl, byte [bp-008h] ; 8a 5e f8 ; 0xf545c keyboard.c:571
+ xor bh, bh ; 30 ff ; 0xf545f
+ imul bx, bx, strict byte 0000ah ; 6b db 0a ; 0xf5461
+ mov dl, byte [bx+00df4h] ; 8a 97 f4 0d ; 0xf5464
+ mov ax, word [bx+00df4h] ; 8b 87 f4 0d ; 0xf5468 keyboard.c:572
+ jmp near 05503h ; e9 94 00 ; 0xf546c keyboard.c:573
+ test dh, 004h ; f6 c6 04 ; 0xf546f
+ je short 05487h ; 74 13 ; 0xf5472
+ mov bl, byte [bp-008h] ; 8a 5e f8 ; 0xf5474 keyboard.c:574
+ xor bh, bh ; 30 ff ; 0xf5477
+ imul bx, bx, strict byte 0000ah ; 6b db 0a ; 0xf5479
+ mov dl, byte [bx+00df2h] ; 8a 97 f2 0d ; 0xf547c
+ mov ax, word [bx+00df2h] ; 8b 87 f2 0d ; 0xf5480 keyboard.c:575
+ jmp near 05503h ; e9 7c 00 ; 0xf5484 keyboard.c:576
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf5487
+ and AL, strict byte 002h ; 24 02 ; 0xf548a
+ test al, al ; 84 c0 ; 0xf548c
+ jbe short 054a6h ; 76 16 ; 0xf548e
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf5490
+ cmp AL, strict byte 047h ; 3c 47 ; 0xf5493
+ jc short 054a6h ; 72 0f ; 0xf5495
+ cmp AL, strict byte 053h ; 3c 53 ; 0xf5497
+ jnbe short 054a6h ; 77 0b ; 0xf5499
+ mov DL, strict byte 0e0h ; b2 e0 ; 0xf549b keyboard.c:578
+ mov bl, al ; 88 c3 ; 0xf549d keyboard.c:579
+ xor bh, bh ; 30 ff ; 0xf549f
+ imul bx, bx, strict byte 0000ah ; 6b db 0a ; 0xf54a1
+ jmp short 054ffh ; eb 59 ; 0xf54a4 keyboard.c:580
+ test dh, 003h ; f6 c6 03 ; 0xf54a6
+ je short 054dbh ; 74 30 ; 0xf54a9
+ mov bl, byte [bp-008h] ; 8a 5e f8 ; 0xf54ab keyboard.c:584
+ xor bh, bh ; 30 ff ; 0xf54ae
+ imul bx, bx, strict byte 0000ah ; 6b db 0a ; 0xf54b0
+ mov cl, byte [bx+00df6h] ; 8a 8f f6 0d ; 0xf54b3
+ xor ch, ch ; 30 ed ; 0xf54b7
+ mov al, dh ; 88 f0 ; 0xf54b9
+ xor ah, ah ; 30 e4 ; 0xf54bb
+ test ax, cx ; 85 c8 ; 0xf54bd
+ je short 054cbh ; 74 0a ; 0xf54bf
+ mov dl, byte [bx+00deeh] ; 8a 97 ee 0d ; 0xf54c1 keyboard.c:585
+ mov ax, word [bx+00deeh] ; 8b 87 ee 0d ; 0xf54c5 keyboard.c:586
+ jmp short 054d3h ; eb 08 ; 0xf54c9 keyboard.c:587
+ mov dl, byte [bx+00df0h] ; 8a 97 f0 0d ; 0xf54cb keyboard.c:588
+ mov ax, word [bx+00df0h] ; 8b 87 f0 0d ; 0xf54cf keyboard.c:589
+ shr ax, 008h ; c1 e8 08 ; 0xf54d3
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf54d6
+ jmp short 05509h ; eb 2e ; 0xf54d9 keyboard.c:591
+ mov bl, byte [bp-008h] ; 8a 5e f8 ; 0xf54db keyboard.c:593
+ xor bh, bh ; 30 ff ; 0xf54de
+ imul bx, bx, strict byte 0000ah ; 6b db 0a ; 0xf54e0
+ mov al, byte [bx+00df6h] ; 8a 87 f6 0d ; 0xf54e3
+ xor ah, ah ; 30 e4 ; 0xf54e7
+ mov dl, dh ; 88 f2 ; 0xf54e9
+ xor dh, dh ; 30 f6 ; 0xf54eb
+ test dx, ax ; 85 c2 ; 0xf54ed
+ je short 054fbh ; 74 0a ; 0xf54ef
+ mov dl, byte [bx+00df0h] ; 8a 97 f0 0d ; 0xf54f1 keyboard.c:594
+ mov ax, word [bx+00df0h] ; 8b 87 f0 0d ; 0xf54f5 keyboard.c:595
+ jmp short 05503h ; eb 08 ; 0xf54f9 keyboard.c:596
+ mov dl, byte [bx+00deeh] ; 8a 97 ee 0d ; 0xf54fb keyboard.c:597
+ mov ax, word [bx+00deeh] ; 8b 87 ee 0d ; 0xf54ff keyboard.c:598
+ shr ax, 008h ; c1 e8 08 ; 0xf5503
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf5506
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf5509 keyboard.c:601
+ jne short 05529h ; 75 1a ; 0xf550d
+ test dl, dl ; 84 d2 ; 0xf550f
+ jne short 05529h ; 75 16 ; 0xf5511
+ mov bx, 00da0h ; bb a0 0d ; 0xf5513 keyboard.c:602
+ mov cx, ds ; 8c d9 ; 0xf5516
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5518
+ call 018bch ; e8 9e c3 ; 0xf551b
+ push 005d8h ; 68 d8 05 ; 0xf551e
+ push strict byte 00004h ; 6a 04 ; 0xf5521
+ call 018ffh ; e8 d9 c3 ; 0xf5523
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf5526
+ xor dh, dh ; 30 f6 ; 0xf5529 keyboard.c:604
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf552b
+ xor ah, ah ; 30 e4 ; 0xf552e
+ jmp near 0537fh ; e9 4c fe ; 0xf5530
+ ; disGetNextSymbol 0xf5533 LB 0x4995 -> off=0x0 cb=000000000000006c uValue=00000000000f3f33 'dequeue_key'
+dequeue_key: ; 0xf5533 LB 0x6c
+ push si ; 56 ; 0xf5533 keyboard.c:614
+ push di ; 57 ; 0xf5534
+ enter 00002h, 000h ; c8 02 00 00 ; 0xf5535
+ push ax ; 50 ; 0xf5539
+ push dx ; 52 ; 0xf553a
+ mov si, bx ; 89 de ; 0xf553b
+ mov bx, 00080h ; bb 80 00 ; 0xf553d keyboard.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5540
+ mov es, ax ; 8e c0 ; 0xf5543
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf5545
+ mov word [bp-002h], ax ; 89 46 fe ; 0xf5548
+ mov bx, 00082h ; bb 82 00 ; 0xf554b keyboard.c:48
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf554e
+ mov bx, strict word 0001ah ; bb 1a 00 ; 0xf5551 keyboard.c:48
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf5554
+ mov di, strict word 0001ch ; bf 1c 00 ; 0xf5557 keyboard.c:48
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf555a
+ cmp bx, ax ; 39 c3 ; 0xf555d keyboard.c:630
+ je short 05597h ; 74 36 ; 0xf555f
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf5561 keyboard.c:38
+ lea di, [bx+001h] ; 8d 7f 01 ; 0xf5564 keyboard.c:632
+ mov ah, byte [es:di] ; 26 8a 25 ; 0xf5567 keyboard.c:38
+ mov es, cx ; 8e c1 ; 0xf556a keyboard.c:633
+ mov byte [es:si], al ; 26 88 04 ; 0xf556c
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf556f keyboard.c:634
+ mov si, word [bp-004h] ; 8b 76 fc ; 0xf5572
+ mov byte [es:si], ah ; 26 88 24 ; 0xf5575
+ cmp word [bp+008h], strict byte 00000h ; 83 7e 08 00 ; 0xf5578 keyboard.c:637
+ je short 05592h ; 74 14 ; 0xf557c
+ inc bx ; 43 ; 0xf557e keyboard.c:638
+ inc bx ; 43 ; 0xf557f
+ cmp bx, dx ; 39 d3 ; 0xf5580 keyboard.c:639
+ jc short 05587h ; 72 03 ; 0xf5582
+ mov bx, word [bp-002h] ; 8b 5e fe ; 0xf5584 keyboard.c:640
+ mov si, strict word 0001ah ; be 1a 00 ; 0xf5587 keyboard.c:53
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf558a
+ mov es, ax ; 8e c0 ; 0xf558d
+ mov word [es:si], bx ; 26 89 1c ; 0xf558f
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf5592 keyboard.c:643
+ jmp short 05599h ; eb 02 ; 0xf5595
+ xor ax, ax ; 31 c0 ; 0xf5597 keyboard.c:646
+ leave ; c9 ; 0xf5599 keyboard.c:648
+ pop di ; 5f ; 0xf559a
+ pop si ; 5e ; 0xf559b
+ retn 00002h ; c2 02 00 ; 0xf559c
+ ; disGetNextSymbol 0xf559f LB 0x4929 -> off=0x23 cb=00000000000002ee uValue=00000000000f3fc2 'int16_function'
+ db 0a2h, 092h, 012h, 011h, 010h, 00ah, 009h, 005h, 002h, 001h, 000h, 0c3h, 056h, 07ah, 056h, 00dh
+ db 057h, 05ah, 057h, 06dh, 057h, 096h, 057h, 09fh, 057h, 010h, 058h, 042h, 058h, 072h, 058h, 0a5h
+ db 058h, 006h, 057h
+int16_function: ; 0xf55c2 LB 0x2ee
+ push bp ; 55 ; 0xf55c2 keyboard.c:665
+ mov bp, sp ; 89 e5 ; 0xf55c3
+ push si ; 56 ; 0xf55c5
+ push di ; 57 ; 0xf55c6
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf55c7
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf55ca keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf55cd
+ mov es, ax ; 8e c0 ; 0xf55d0
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf55d2
+ mov bl, al ; 88 c3 ; 0xf55d5 keyboard.c:39
+ mov si, 00097h ; be 97 00 ; 0xf55d7 keyboard.c:38
+ mov dl, byte [es:si] ; 26 8a 14 ; 0xf55da
+ mov bh, dl ; 88 d7 ; 0xf55dd keyboard.c:39
+ xor ah, ah ; 30 e4 ; 0xf55df keyboard.c:674
+ mov cx, ax ; 89 c1 ; 0xf55e1
+ sar cx, 004h ; c1 f9 04 ; 0xf55e3
+ and cl, 007h ; 80 e1 07 ; 0xf55e6
+ mov al, dl ; 88 d0 ; 0xf55e9
+ and AL, strict byte 007h ; 24 07 ; 0xf55eb
+ xor al, cl ; 30 c8 ; 0xf55ed
+ test ax, ax ; 85 c0 ; 0xf55ef
+ je short 0565ah ; 74 67 ; 0xf55f1
+ cli ; fa ; 0xf55f3 keyboard.c:675
+ mov AL, strict byte 0edh ; b0 ed ; 0xf55f4 keyboard.c:676
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf55f6
+ out DX, AL ; ee ; 0xf55f9
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf55fa keyboard.c:677
+ in AL, DX ; ec ; 0xf55fd
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf55fe
+ test AL, strict byte 001h ; a8 01 ; 0xf5600
+ jne short 0560ch ; 75 08 ; 0xf5602
+ mov AL, strict byte 021h ; b0 21 ; 0xf5604
+ mov dx, 00080h ; ba 80 00 ; 0xf5606
+ out DX, AL ; ee ; 0xf5609
+ jmp short 055fah ; eb ee ; 0xf560a
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf560c keyboard.c:678
+ in AL, DX ; ec ; 0xf560f
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5610
+ cmp ax, 000fah ; 3d fa 00 ; 0xf5612
+ jne short 05659h ; 75 42 ; 0xf5615
+ mov dl, bh ; 88 fa ; 0xf5617 keyboard.c:679
+ and dl, 0c8h ; 80 e2 c8 ; 0xf5619
+ mov al, bl ; 88 d8 ; 0xf561c keyboard.c:680
+ xor ah, ah ; 30 e4 ; 0xf561e
+ mov cx, ax ; 89 c1 ; 0xf5620
+ sar cx, 004h ; c1 f9 04 ; 0xf5622
+ and cl, 007h ; 80 e1 07 ; 0xf5625
+ xor dh, dh ; 30 f6 ; 0xf5628
+ mov ax, dx ; 89 d0 ; 0xf562a
+ or al, cl ; 08 c8 ; 0xf562c
+ mov bh, al ; 88 c7 ; 0xf562e
+ and AL, strict byte 007h ; 24 07 ; 0xf5630 keyboard.c:681
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5632
+ out DX, AL ; ee ; 0xf5635
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5636 keyboard.c:682
+ in AL, DX ; ec ; 0xf5639
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf563a
+ test AL, strict byte 001h ; a8 01 ; 0xf563c
+ jne short 05648h ; 75 08 ; 0xf563e
+ mov AL, strict byte 021h ; b0 21 ; 0xf5640 keyboard.c:683
+ mov dx, 00080h ; ba 80 00 ; 0xf5642
+ out DX, AL ; ee ; 0xf5645
+ jmp short 05636h ; eb ee ; 0xf5646
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5648 keyboard.c:684
+ in AL, DX ; ec ; 0xf564b
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf564c
+ mov si, 00097h ; be 97 00 ; 0xf564e keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5651
+ mov es, ax ; 8e c0 ; 0xf5654
+ mov byte [es:si], bh ; 26 88 3c ; 0xf5656
+ sti ; fb ; 0xf5659 keyboard.c:687
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf565a keyboard.c:690
+ shr ax, 008h ; c1 e8 08 ; 0xf565d
+ cmp ax, 000a2h ; 3d a2 00 ; 0xf5660
+ jnbe short 056c3h ; 77 5e ; 0xf5663
+ push CS ; 0e ; 0xf5665
+ pop ES ; 07 ; 0xf5666
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf5667
+ mov di, 0559fh ; bf 9f 55 ; 0xf566a
+ repne scasb ; f2 ae ; 0xf566d
+ sal cx, 1 ; d1 e1 ; 0xf566f
+ mov di, cx ; 89 cf ; 0xf5671
+ mov ax, word [cs:di+055aah] ; 2e 8b 85 aa 55 ; 0xf5673
+ jmp ax ; ff e0 ; 0xf5678
+ push strict byte 00001h ; 6a 01 ; 0xf567a keyboard.c:692
+ mov cx, ss ; 8c d1 ; 0xf567c
+ lea bx, [bp-006h] ; 8d 5e fa ; 0xf567e
+ mov dx, ss ; 8c d2 ; 0xf5681
+ lea ax, [bp-00ah] ; 8d 46 f6 ; 0xf5683
+ call 05533h ; e8 aa fe ; 0xf5686
+ test ax, ax ; 85 c0 ; 0xf5689
+ jne short 05698h ; 75 0b ; 0xf568b
+ push 0060fh ; 68 0f 06 ; 0xf568d keyboard.c:693
+ push strict byte 00007h ; 6a 07 ; 0xf5690
+ call 018ffh ; e8 6a c2 ; 0xf5692
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf5695
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf5698 keyboard.c:695
+ je short 056a4h ; 74 06 ; 0xf569c
+ cmp byte [bp-006h], 0f0h ; 80 7e fa f0 ; 0xf569e
+ je short 056aah ; 74 06 ; 0xf56a2
+ cmp byte [bp-006h], 0e0h ; 80 7e fa e0 ; 0xf56a4 keyboard.c:697
+ jne short 056aeh ; 75 04 ; 0xf56a8
+ mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xf56aa keyboard.c:698
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf56ae keyboard.c:699
+ xor ah, ah ; 30 e4 ; 0xf56b1
+ mov dx, ax ; 89 c2 ; 0xf56b3
+ sal dx, 008h ; c1 e2 08 ; 0xf56b5
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf56b8
+ or dx, ax ; 09 c2 ; 0xf56bb
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf56bd
+ jmp near 05706h ; e9 43 00 ; 0xf56c0 keyboard.c:700
+ mov bx, 00da0h ; bb a0 0d ; 0xf56c3
+ mov cx, ds ; 8c d9 ; 0xf56c6
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf56c8
+ call 018bch ; e8 ee c1 ; 0xf56cb
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf56ce
+ shr ax, 008h ; c1 e8 08 ; 0xf56d1
+ push ax ; 50 ; 0xf56d4
+ push 00633h ; 68 33 06 ; 0xf56d5
+ push strict byte 00004h ; 6a 04 ; 0xf56d8
+ call 018ffh ; e8 22 c2 ; 0xf56da
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf56dd
+ mov bx, 00da0h ; bb a0 0d ; 0xf56e0
+ mov cx, ds ; 8c d9 ; 0xf56e3
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf56e5
+ call 018bch ; e8 d1 c1 ; 0xf56e8
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf56eb
+ push ax ; 50 ; 0xf56ee
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf56ef
+ push ax ; 50 ; 0xf56f2
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf56f3
+ push ax ; 50 ; 0xf56f6
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf56f7
+ push ax ; 50 ; 0xf56fa
+ push 0065bh ; 68 5b 06 ; 0xf56fb
+ push strict byte 00004h ; 6a 04 ; 0xf56fe
+ call 018ffh ; e8 fc c1 ; 0xf5700
+ add sp, strict byte 0000ch ; 83 c4 0c ; 0xf5703
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf5706
+ pop di ; 5f ; 0xf5709
+ pop si ; 5e ; 0xf570a
+ pop bp ; 5d ; 0xf570b
+ retn ; c3 ; 0xf570c
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf570d keyboard.c:704
+ mov word [bp+01eh], ax ; 89 46 1e ; 0xf5710
+ push strict byte 00000h ; 6a 00 ; 0xf5713 keyboard.c:705
+ mov cx, ss ; 8c d1 ; 0xf5715
+ lea bx, [bp-006h] ; 8d 5e fa ; 0xf5717
+ mov dx, ss ; 8c d2 ; 0xf571a
+ lea ax, [bp-00ah] ; 8d 46 f6 ; 0xf571c
+ call 05533h ; e8 11 fe ; 0xf571f
+ test ax, ax ; 85 c0 ; 0xf5722
+ jne short 0572ch ; 75 06 ; 0xf5724
+ or word [bp+01eh], strict byte 00040h ; 83 4e 1e 40 ; 0xf5726 keyboard.c:706
+ jmp short 05706h ; eb da ; 0xf572a keyboard.c:707
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf572c keyboard.c:709
+ je short 05738h ; 74 06 ; 0xf5730
+ cmp byte [bp-006h], 0f0h ; 80 7e fa f0 ; 0xf5732
+ je short 0573eh ; 74 06 ; 0xf5736
+ cmp byte [bp-006h], 0e0h ; 80 7e fa e0 ; 0xf5738 keyboard.c:711
+ jne short 05742h ; 75 04 ; 0xf573c
+ mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xf573e keyboard.c:712
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf5742 keyboard.c:713
+ xor ah, ah ; 30 e4 ; 0xf5745
+ mov dx, ax ; 89 c2 ; 0xf5747
+ sal dx, 008h ; c1 e2 08 ; 0xf5749
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf574c
+ or dx, ax ; 09 c2 ; 0xf574f
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf5751
+ and word [bp+01eh], strict byte 0ffbfh ; 83 66 1e bf ; 0xf5754 keyboard.c:714
+ jmp short 05706h ; eb ac ; 0xf5758 keyboard.c:715
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf575a keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf575d
+ mov es, ax ; 8e c0 ; 0xf5760
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf5762
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf5765 keyboard.c:719
+ mov dl, al ; 88 c2 ; 0xf5768
+ jmp near 056bdh ; e9 50 ff ; 0xf576a
+ mov dl, byte [bp+010h] ; 8a 56 10 ; 0xf576d keyboard.c:723
+ xor dh, dh ; 30 f6 ; 0xf5770
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf5772
+ shr ax, 008h ; c1 e8 08 ; 0xf5775
+ xor ah, ah ; 30 e4 ; 0xf5778
+ call 050e7h ; e8 6a f9 ; 0xf577a
+ test ax, ax ; 85 c0 ; 0xf577d
+ jne short 0578eh ; 75 0d ; 0xf577f
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf5781 keyboard.c:724
+ xor al, al ; 30 c0 ; 0xf5784
+ or AL, strict byte 001h ; 0c 01 ; 0xf5786
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf5788
+ jmp near 05706h ; e9 78 ff ; 0xf578b keyboard.c:726
+ and word [bp+012h], 0ff00h ; 81 66 12 00 ff ; 0xf578e keyboard.c:727
+ jmp near 05706h ; e9 70 ff ; 0xf5793 keyboard.c:729
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf5796 keyboard.c:742
+ xor al, al ; 30 c0 ; 0xf5799
+ or AL, strict byte 030h ; 0c 30 ; 0xf579b
+ jmp short 05788h ; eb e9 ; 0xf579d
+ mov byte [bp-008h], 002h ; c6 46 f8 02 ; 0xf579f keyboard.c:746
+ xor cx, cx ; 31 c9 ; 0xf57a3 keyboard.c:747
+ cli ; fa ; 0xf57a5 keyboard.c:749
+ mov AL, strict byte 0f2h ; b0 f2 ; 0xf57a6 keyboard.c:750
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf57a8
+ out DX, AL ; ee ; 0xf57ab
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf57ac keyboard.c:752
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf57af keyboard.c:753
+ in AL, DX ; ec ; 0xf57b2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf57b3
+ test AL, strict byte 001h ; a8 01 ; 0xf57b5
+ jne short 057c6h ; 75 0d ; 0xf57b7
+ dec bx ; 4b ; 0xf57b9
+ test bx, bx ; 85 db ; 0xf57ba
+ jbe short 057c6h ; 76 08 ; 0xf57bc
+ mov dx, 00080h ; ba 80 00 ; 0xf57be keyboard.c:754
+ in AL, DX ; ec ; 0xf57c1
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf57c2
+ jmp short 057afh ; eb e9 ; 0xf57c4
+ test bx, bx ; 85 db ; 0xf57c6 keyboard.c:755
+ jbe short 0580ah ; 76 40 ; 0xf57c8
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf57ca keyboard.c:756
+ in AL, DX ; ec ; 0xf57cd
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf57ce
+ cmp ax, 000fah ; 3d fa 00 ; 0xf57d0
+ jne short 0580ah ; 75 35 ; 0xf57d3
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf57d5 keyboard.c:758
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf57d8 keyboard.c:759
+ in AL, DX ; ec ; 0xf57db
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf57dc
+ test AL, strict byte 001h ; a8 01 ; 0xf57de
+ jne short 057efh ; 75 0d ; 0xf57e0
+ dec bx ; 4b ; 0xf57e2
+ test bx, bx ; 85 db ; 0xf57e3
+ jbe short 057efh ; 76 08 ; 0xf57e5
+ mov dx, 00080h ; ba 80 00 ; 0xf57e7 keyboard.c:760
+ in AL, DX ; ec ; 0xf57ea
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf57eb
+ jmp short 057d8h ; eb e9 ; 0xf57ed
+ test bx, bx ; 85 db ; 0xf57ef keyboard.c:761
+ jbe short 05801h ; 76 0e ; 0xf57f1
+ shr cx, 008h ; c1 e9 08 ; 0xf57f3 keyboard.c:762
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf57f6 keyboard.c:763
+ in AL, DX ; ec ; 0xf57f9
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf57fa
+ sal ax, 008h ; c1 e0 08 ; 0xf57fc
+ or cx, ax ; 09 c1 ; 0xf57ff
+ dec byte [bp-008h] ; fe 4e f8 ; 0xf5801 keyboard.c:765
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf5804
+ jnbe short 057d5h ; 77 cb ; 0xf5808
+ mov word [bp+00ch], cx ; 89 4e 0c ; 0xf580a keyboard.c:768
+ jmp near 05706h ; e9 f6 fe ; 0xf580d keyboard.c:769
+ push strict byte 00001h ; 6a 01 ; 0xf5810 keyboard.c:772
+ mov cx, ss ; 8c d1 ; 0xf5812
+ lea bx, [bp-006h] ; 8d 5e fa ; 0xf5814
+ mov dx, ss ; 8c d2 ; 0xf5817
+ lea ax, [bp-00ah] ; 8d 46 f6 ; 0xf5819
+ call 05533h ; e8 14 fd ; 0xf581c
+ test ax, ax ; 85 c0 ; 0xf581f
+ jne short 0582eh ; 75 0b ; 0xf5821
+ push 0060fh ; 68 0f 06 ; 0xf5823 keyboard.c:773
+ push strict byte 00007h ; 6a 07 ; 0xf5826
+ call 018ffh ; e8 d4 c0 ; 0xf5828
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf582b
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf582e keyboard.c:775
+ jne short 05837h ; 75 03 ; 0xf5832
+ jmp near 056aeh ; e9 77 fe ; 0xf5834
+ cmp byte [bp-006h], 0f0h ; 80 7e fa f0 ; 0xf5837
+ jne short 05840h ; 75 03 ; 0xf583b
+ jmp near 056aah ; e9 6a fe ; 0xf583d
+ jmp short 05834h ; eb f2 ; 0xf5840
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf5842 keyboard.c:782
+ mov word [bp+01eh], ax ; 89 46 1e ; 0xf5845
+ push strict byte 00000h ; 6a 00 ; 0xf5848 keyboard.c:783
+ mov cx, ss ; 8c d1 ; 0xf584a
+ lea bx, [bp-006h] ; 8d 5e fa ; 0xf584c
+ mov dx, ss ; 8c d2 ; 0xf584f
+ lea ax, [bp-00ah] ; 8d 46 f6 ; 0xf5851
+ call 05533h ; e8 dc fc ; 0xf5854
+ test ax, ax ; 85 c0 ; 0xf5857
+ jne short 0585eh ; 75 03 ; 0xf5859
+ jmp near 05726h ; e9 c8 fe ; 0xf585b
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf585e keyboard.c:787
+ jne short 05867h ; 75 03 ; 0xf5862
+ jmp near 05742h ; e9 db fe ; 0xf5864
+ cmp byte [bp-006h], 0f0h ; 80 7e fa f0 ; 0xf5867
+ jne short 05870h ; 75 03 ; 0xf586b
+ jmp near 0573eh ; e9 ce fe ; 0xf586d
+ jmp short 05864h ; eb f2 ; 0xf5870
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf5872 keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5875
+ mov es, ax ; 8e c0 ; 0xf5878
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf587a
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf587d keyboard.c:795
+ mov dl, al ; 88 c2 ; 0xf5880
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf5882
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5885 keyboard.c:38
+ mov bl, byte [es:bx] ; 26 8a 1f ; 0xf5888
+ and bl, 073h ; 80 e3 73 ; 0xf588b keyboard.c:39
+ mov si, 00096h ; be 96 00 ; 0xf588e keyboard.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf5891
+ and AL, strict byte 00ch ; 24 0c ; 0xf5894 keyboard.c:39
+ or al, bl ; 08 d8 ; 0xf5896
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf5898 keyboard.c:798
+ xor dh, dh ; 30 f6 ; 0xf589b
+ xor ah, ah ; 30 e4 ; 0xf589d
+ sal ax, 008h ; c1 e0 08 ; 0xf589f
+ jmp near 056bbh ; e9 16 fe ; 0xf58a2
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf58a5 keyboard.c:803
+ xor ah, ah ; 30 e4 ; 0xf58a8
+ or ah, 080h ; 80 cc 80 ; 0xf58aa
+ jmp near 05788h ; e9 d8 fe ; 0xf58ad
+ ; disGetNextSymbol 0xf58b0 LB 0x4618 -> off=0x0 cb=00000000000000b5 uValue=00000000000f42b0 'set_geom_lba'
+set_geom_lba: ; 0xf58b0 LB 0xb5
+ push bx ; 53 ; 0xf58b0 disk.c:115
+ push cx ; 51 ; 0xf58b1
+ push si ; 56 ; 0xf58b2
+ push di ; 57 ; 0xf58b3
+ enter 00008h, 000h ; c8 08 00 00 ; 0xf58b4
+ mov di, ax ; 89 c7 ; 0xf58b8
+ mov es, dx ; 8e c2 ; 0xf58ba
+ mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xf58bc disk.c:117
+ mov word [bp-006h], strict word 0007eh ; c7 46 fa 7e 00 ; 0xf58c1
+ mov word [bp-002h], 000ffh ; c7 46 fe ff 00 ; 0xf58c6 disk.c:119
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf58cb disk.c:122
+ mov bx, word [bp+010h] ; 8b 5e 10 ; 0xf58ce
+ mov cx, word [bp+00eh] ; 8b 4e 0e ; 0xf58d1
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf58d4
+ mov si, strict word 00020h ; be 20 00 ; 0xf58d7
+ call 09b90h ; e8 b3 42 ; 0xf58da
+ test ax, ax ; 85 c0 ; 0xf58dd
+ jne short 058edh ; 75 0c ; 0xf58df
+ test bx, bx ; 85 db ; 0xf58e1
+ jne short 058edh ; 75 08 ; 0xf58e3
+ test cx, cx ; 85 c9 ; 0xf58e5
+ jne short 058edh ; 75 04 ; 0xf58e7
+ test dx, dx ; 85 d2 ; 0xf58e9
+ je short 058f4h ; 74 07 ; 0xf58eb
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf58ed
+ mov si, bx ; 89 de ; 0xf58f0
+ jmp short 058fah ; eb 06 ; 0xf58f2
+ mov bx, word [bp+00ch] ; 8b 5e 0c ; 0xf58f4
+ mov si, word [bp+00eh] ; 8b 76 0e ; 0xf58f7
+ mov word [bp-004h], bx ; 89 5e fc ; 0xf58fa
+ xor bx, bx ; 31 db ; 0xf58fd disk.c:124
+ jmp short 05906h ; eb 05 ; 0xf58ff
+ cmp bx, strict byte 00004h ; 83 fb 04 ; 0xf5901
+ jnl short 05929h ; 7d 23 ; 0xf5904
+ mov ax, word [bp-006h] ; 8b 46 fa ; 0xf5906 disk.c:125
+ cmp si, ax ; 39 c6 ; 0xf5909
+ jc short 05917h ; 72 0a ; 0xf590b
+ jne short 05920h ; 75 11 ; 0xf590d
+ mov ax, word [bp-004h] ; 8b 46 fc ; 0xf590f
+ cmp ax, word [bp-008h] ; 3b 46 f8 ; 0xf5912
+ jnbe short 05920h ; 77 09 ; 0xf5915
+ mov ax, word [bp-002h] ; 8b 46 fe ; 0xf5917 disk.c:126
+ inc ax ; 40 ; 0xf591a
+ shr ax, 1 ; d1 e8 ; 0xf591b
+ mov word [bp-002h], ax ; 89 46 fe ; 0xf591d
+ shr word [bp-006h], 1 ; d1 6e fa ; 0xf5920 disk.c:127
+ rcr word [bp-008h], 1 ; d1 5e f8 ; 0xf5923
+ inc bx ; 43 ; 0xf5926 disk.c:128
+ jmp short 05901h ; eb d8 ; 0xf5927
+ mov ax, word [bp-002h] ; 8b 46 fe ; 0xf5929 disk.c:130
+ xor dx, dx ; 31 d2 ; 0xf592c
+ mov bx, strict word 0003fh ; bb 3f 00 ; 0xf592e
+ xor cx, cx ; 31 c9 ; 0xf5931
+ call 09b40h ; e8 0a 42 ; 0xf5933
+ mov bx, ax ; 89 c3 ; 0xf5936
+ mov cx, dx ; 89 d1 ; 0xf5938
+ mov ax, word [bp-004h] ; 8b 46 fc ; 0xf593a
+ mov dx, si ; 89 f2 ; 0xf593d
+ call 09b60h ; e8 1e 42 ; 0xf593f
+ mov word [es:di+002h], ax ; 26 89 45 02 ; 0xf5942
+ cmp ax, 00400h ; 3d 00 04 ; 0xf5946 disk.c:131
+ jbe short 05951h ; 76 06 ; 0xf5949
+ mov word [es:di+002h], 00400h ; 26 c7 45 02 00 04 ; 0xf594b disk.c:132
+ mov ax, word [bp-002h] ; 8b 46 fe ; 0xf5951 disk.c:133
+ mov word [es:di], ax ; 26 89 05 ; 0xf5954
+ mov word [es:di+004h], strict word 0003fh ; 26 c7 45 04 3f 00 ; 0xf5957 disk.c:134
+ leave ; c9 ; 0xf595d disk.c:135
+ pop di ; 5f ; 0xf595e
+ pop si ; 5e ; 0xf595f
+ pop cx ; 59 ; 0xf5960
+ pop bx ; 5b ; 0xf5961
+ retn 00008h ; c2 08 00 ; 0xf5962
+ ; disGetNextSymbol 0xf5965 LB 0x4563 -> off=0x0 cb=00000000000002fc uValue=00000000000f4365 'edd_fill_dpt'
+edd_fill_dpt: ; 0xf5965 LB 0x2fc
+ push si ; 56 ; 0xf5965 disk.c:137
+ push di ; 57 ; 0xf5966
+ enter 0000ch, 000h ; c8 0c 00 00 ; 0xf5967
+ mov di, ax ; 89 c7 ; 0xf596b
+ mov word [bp-004h], dx ; 89 56 fc ; 0xf596d
+ mov word [bp-008h], bx ; 89 5e f8 ; 0xf5970
+ mov word [bp-006h], cx ; 89 4e fa ; 0xf5973
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf5976 disk.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5979
+ mov es, ax ; 8e c0 ; 0xf597c
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf597e
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf5981 disk.c:49
+ mov es, dx ; 8e c2 ; 0xf5984 disk.c:142
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf5986
+ cmp ax, strict word 0001ah ; 3d 1a 00 ; 0xf5989
+ jnc short 05994h ; 73 06 ; 0xf598c
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf598e disk.c:143
+ jmp near 05c5bh ; e9 c7 02 ; 0xf5991
+ jc short 05a05h ; 72 6f ; 0xf5994 disk.c:146
+ mov word [es:di], strict word 0001ah ; 26 c7 05 1a 00 ; 0xf5996 disk.c:149
+ mov al, byte [bp+008h] ; 8a 46 08 ; 0xf599b disk.c:150
+ xor ah, ah ; 30 e4 ; 0xf599e
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf59a0
+ mov dx, cx ; 89 ca ; 0xf59a3
+ mov bx, word [bp-008h] ; 8b 5e f8 ; 0xf59a5
+ add bx, ax ; 01 c3 ; 0xf59a8
+ mov es, cx ; 8e c1 ; 0xf59aa
+ mov ax, word [es:bx+028h] ; 26 8b 47 28 ; 0xf59ac
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf59b0
+ mov word [es:di+018h], ax ; 26 89 45 18 ; 0xf59b3
+ mov es, cx ; 8e c1 ; 0xf59b7 disk.c:152
+ cmp byte [es:bx+023h], 005h ; 26 80 7f 23 05 ; 0xf59b9
+ jne short 05a07h ; 75 47 ; 0xf59be
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf59c0 disk.c:153
+ mov word [es:di+002h], strict word 00074h ; 26 c7 45 02 74 00 ; 0xf59c3
+ mov word [es:di+004h], strict word 0ffffh ; 26 c7 45 04 ff ff ; 0xf59c9 disk.c:154
+ mov word [es:di+006h], strict word 0ffffh ; 26 c7 45 06 ff ff ; 0xf59cf
+ mov word [es:di+008h], strict word 0ffffh ; 26 c7 45 08 ff ff ; 0xf59d5 disk.c:155
+ mov word [es:di+00ah], strict word 0ffffh ; 26 c7 45 0a ff ff ; 0xf59db
+ mov word [es:di+00ch], strict word 0ffffh ; 26 c7 45 0c ff ff ; 0xf59e1 disk.c:156
+ mov word [es:di+00eh], strict word 0ffffh ; 26 c7 45 0e ff ff ; 0xf59e7
+ mov word [es:di+010h], strict word 0ffffh ; 26 c7 45 10 ff ff ; 0xf59ed disk.c:157
+ mov word [es:di+012h], strict word 0ffffh ; 26 c7 45 12 ff ff ; 0xf59f3
+ mov word [es:di+014h], strict word 0ffffh ; 26 c7 45 14 ff ff ; 0xf59f9 disk.c:158
+ mov word [es:di+016h], strict word 0ffffh ; 26 c7 45 16 ff ff ; 0xf59ff
+ jmp short 05a76h ; eb 6f ; 0xf5a05 disk.c:159
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5a07 disk.c:160
+ mov word [es:di+002h], strict word 00002h ; 26 c7 45 02 02 00 ; 0xf5a0a
+ mov es, cx ; 8e c1 ; 0xf5a10 disk.c:161
+ mov ax, word [es:bx+032h] ; 26 8b 47 32 ; 0xf5a12
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5a16
+ mov word [es:di+004h], ax ; 26 89 45 04 ; 0xf5a19
+ mov word [es:di+006h], strict word 00000h ; 26 c7 45 06 00 00 ; 0xf5a1d
+ mov es, cx ; 8e c1 ; 0xf5a23 disk.c:162
+ mov ax, word [es:bx+030h] ; 26 8b 47 30 ; 0xf5a25
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5a29
+ mov word [es:di+008h], ax ; 26 89 45 08 ; 0xf5a2c
+ mov word [es:di+00ah], strict word 00000h ; 26 c7 45 0a 00 00 ; 0xf5a30
+ mov es, cx ; 8e c1 ; 0xf5a36 disk.c:163
+ mov ax, word [es:bx+034h] ; 26 8b 47 34 ; 0xf5a38
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5a3c
+ mov word [es:di+00ch], ax ; 26 89 45 0c ; 0xf5a3f
+ mov word [es:di+00eh], strict word 00000h ; 26 c7 45 0e 00 00 ; 0xf5a43
+ mov es, cx ; 8e c1 ; 0xf5a49 disk.c:164
+ mov ax, word [es:bx+03ch] ; 26 8b 47 3c ; 0xf5a4b
+ mov si, word [es:bx+03ah] ; 26 8b 77 3a ; 0xf5a4f
+ mov cx, word [es:bx+038h] ; 26 8b 4f 38 ; 0xf5a53
+ mov dx, word [es:bx+036h] ; 26 8b 57 36 ; 0xf5a57
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5a5b disk.c:165
+ mov word [es:di+010h], dx ; 26 89 55 10 ; 0xf5a5e
+ mov word [es:di+012h], cx ; 26 89 4d 12 ; 0xf5a62
+ mov bx, si ; 89 f3 ; 0xf5a66 disk.c:166
+ mov si, strict word 00020h ; be 20 00 ; 0xf5a68
+ call 09b90h ; e8 22 41 ; 0xf5a6b
+ mov word [es:di+014h], dx ; 26 89 55 14 ; 0xf5a6e
+ mov word [es:di+016h], cx ; 26 89 4d 16 ; 0xf5a72
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5a76 disk.c:171
+ cmp word [es:di], strict byte 0001eh ; 26 83 3d 1e ; 0xf5a79
+ jc short 05aceh ; 72 4f ; 0xf5a7d
+ mov word [es:di], strict word 0001eh ; 26 c7 05 1e 00 ; 0xf5a7f disk.c:175
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf5a84 disk.c:176
+ mov word [es:di+01ch], ax ; 26 89 45 1c ; 0xf5a87
+ mov word [es:di+01ah], 00356h ; 26 c7 45 1a 56 03 ; 0xf5a8b disk.c:177
+ mov cl, byte [bp+008h] ; 8a 4e 08 ; 0xf5a91 disk.c:180
+ xor ch, ch ; 30 ed ; 0xf5a94
+ mov ax, cx ; 89 c8 ; 0xf5a96
+ cwd ; 99 ; 0xf5a98
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf5a99
+ sar ax, 1 ; d1 f8 ; 0xf5a9b
+ xor ah, ah ; 30 e4 ; 0xf5a9d disk.c:181
+ imul ax, ax, strict byte 00006h ; 6b c0 06 ; 0xf5a9f
+ les bx, [bp-008h] ; c4 5e f8 ; 0xf5aa2
+ add bx, ax ; 01 c3 ; 0xf5aa5
+ mov dx, word [es:bx+00206h] ; 26 8b 97 06 02 ; 0xf5aa7
+ mov ax, word [es:bx+00208h] ; 26 8b 87 08 02 ; 0xf5aac disk.c:182
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf5ab1
+ mov al, byte [es:bx+00205h] ; 26 8a 87 05 02 ; 0xf5ab4 disk.c:183
+ mov byte [bp-002h], al ; 88 46 fe ; 0xf5ab9
+ imul bx, cx, strict byte 0001ch ; 6b d9 1c ; 0xf5abc disk.c:185
+ add bx, word [bp-008h] ; 03 5e f8 ; 0xf5abf
+ mov cl, byte [es:bx+027h] ; 26 8a 4f 27 ; 0xf5ac2
+ test cl, cl ; 84 c9 ; 0xf5ac6 disk.c:187
+ jne short 05ad1h ; 75 07 ; 0xf5ac8
+ xor bx, bx ; 31 db ; 0xf5aca
+ jmp short 05ad4h ; eb 06 ; 0xf5acc
+ jmp near 05b8ah ; e9 b9 00 ; 0xf5ace
+ mov bx, strict word 00008h ; bb 08 00 ; 0xf5ad1
+ or bl, 010h ; 80 cb 10 ; 0xf5ad4 disk.c:188
+ mov al, byte [bp+008h] ; 8a 46 08 ; 0xf5ad7 disk.c:189
+ xor ah, ah ; 30 e4 ; 0xf5ada
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf5adc
+ les si, [bp-008h] ; c4 76 f8 ; 0xf5adf
+ add si, ax ; 01 c6 ; 0xf5ae2
+ cmp byte [es:si+023h], 005h ; 26 80 7c 23 05 ; 0xf5ae4
+ jne short 05aeeh ; 75 03 ; 0xf5ae9
+ or bl, 060h ; 80 cb 60 ; 0xf5aeb disk.c:190
+ cmp cl, 001h ; 80 f9 01 ; 0xf5aee disk.c:196
+ jne short 05af8h ; 75 05 ; 0xf5af1
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf5af3
+ jmp short 05afah ; eb 02 ; 0xf5af6
+ xor ax, ax ; 31 c0 ; 0xf5af8
+ or bx, ax ; 09 c3 ; 0xf5afa
+ cmp cl, 003h ; 80 f9 03 ; 0xf5afc disk.c:197
+ jne short 05b06h ; 75 05 ; 0xf5aff
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf5b01
+ jmp short 05b08h ; eb 02 ; 0xf5b04
+ xor ax, ax ; 31 c0 ; 0xf5b06
+ or bx, ax ; 09 c3 ; 0xf5b08
+ les si, [bp-008h] ; c4 76 f8 ; 0xf5b0a disk.c:199
+ mov word [es:si+00234h], dx ; 26 89 94 34 02 ; 0xf5b0d
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf5b12 disk.c:200
+ mov word [es:si+00236h], ax ; 26 89 84 36 02 ; 0xf5b15
+ mov al, byte [bp+008h] ; 8a 46 08 ; 0xf5b1a disk.c:201
+ xor ah, ah ; 30 e4 ; 0xf5b1d
+ cwd ; 99 ; 0xf5b1f
+ mov cx, strict word 00002h ; b9 02 00 ; 0xf5b20
+ idiv cx ; f7 f9 ; 0xf5b23
+ or dl, 00eh ; 80 ca 0e ; 0xf5b25
+ sal dx, 004h ; c1 e2 04 ; 0xf5b28
+ mov byte [es:si+00238h], dl ; 26 88 94 38 02 ; 0xf5b2b
+ mov byte [es:si+00239h], 0cbh ; 26 c6 84 39 02 cb ; 0xf5b30 disk.c:202
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf5b36 disk.c:203
+ mov byte [es:si+0023ah], al ; 26 88 84 3a 02 ; 0xf5b39
+ mov word [es:si+0023bh], strict word 00001h ; 26 c7 84 3b 02 01 00 ; 0xf5b3e disk.c:204
+ mov byte [es:si+0023dh], 000h ; 26 c6 84 3d 02 00 ; 0xf5b45 disk.c:206
+ mov word [es:si+0023eh], bx ; 26 89 9c 3e 02 ; 0xf5b4b disk.c:207
+ mov bx, si ; 89 f3 ; 0xf5b50 disk.c:208
+ mov word [es:bx+00240h], strict word 00000h ; 26 c7 87 40 02 00 00 ; 0xf5b52
+ mov byte [es:bx+00242h], 011h ; 26 c6 87 42 02 11 ; 0xf5b59 disk.c:209
+ xor bl, bl ; 30 db ; 0xf5b5f disk.c:211
+ xor bh, bh ; 30 ff ; 0xf5b61 disk.c:212
+ jmp short 05b6ah ; eb 05 ; 0xf5b63
+ cmp bh, 00fh ; 80 ff 0f ; 0xf5b65
+ jnc short 05b80h ; 73 16 ; 0xf5b68
+ mov al, bh ; 88 f8 ; 0xf5b6a disk.c:213
+ xor ah, ah ; 30 e4 ; 0xf5b6c
+ mov si, ax ; 89 c6 ; 0xf5b6e
+ add si, 00356h ; 81 c6 56 03 ; 0xf5b70
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf5b74 disk.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf5b77
+ add bl, al ; 00 c3 ; 0xf5b7a disk.c:39
+ db 0feh, 0c7h
+ ; inc bh ; fe c7 ; 0xf5b7c disk.c:213
+ jmp short 05b65h ; eb e5 ; 0xf5b7e
+ neg bl ; f6 db ; 0xf5b80 disk.c:214
+ les si, [bp-008h] ; c4 76 f8 ; 0xf5b82 disk.c:215
+ mov byte [es:si+00243h], bl ; 26 88 9c 43 02 ; 0xf5b85
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5b8a disk.c:219
+ cmp word [es:di], strict byte 00042h ; 26 83 3d 42 ; 0xf5b8d
+ jnc short 05b96h ; 73 03 ; 0xf5b91
+ jmp near 05c59h ; e9 c3 00 ; 0xf5b93
+ mov al, byte [bp+008h] ; 8a 46 08 ; 0xf5b96 disk.c:223
+ xor ah, ah ; 30 e4 ; 0xf5b99
+ cwd ; 99 ; 0xf5b9b
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf5b9c
+ sar ax, 1 ; d1 f8 ; 0xf5b9e
+ xor ah, ah ; 30 e4 ; 0xf5ba0 disk.c:224
+ imul ax, ax, strict byte 00006h ; 6b c0 06 ; 0xf5ba2
+ les bx, [bp-008h] ; c4 5e f8 ; 0xf5ba5
+ add bx, ax ; 01 c3 ; 0xf5ba8
+ mov al, byte [es:bx+00204h] ; 26 8a 87 04 02 ; 0xf5baa
+ mov dx, word [es:bx+00206h] ; 26 8b 97 06 02 ; 0xf5baf disk.c:225
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5bb4 disk.c:227
+ mov word [es:di], strict word 00042h ; 26 c7 05 42 00 ; 0xf5bb7
+ mov word [es:di+01eh], 0beddh ; 26 c7 45 1e dd be ; 0xf5bbc disk.c:228
+ mov word [es:di+020h], strict word 00024h ; 26 c7 45 20 24 00 ; 0xf5bc2 disk.c:229
+ mov word [es:di+022h], strict word 00000h ; 26 c7 45 22 00 00 ; 0xf5bc8 disk.c:231
+ test al, al ; 84 c0 ; 0xf5bce disk.c:233
+ jne short 05bdeh ; 75 0c ; 0xf5bd0
+ mov word [es:di+024h], 05349h ; 26 c7 45 24 49 53 ; 0xf5bd2 disk.c:234
+ mov word [es:di+026h], 02041h ; 26 c7 45 26 41 20 ; 0xf5bd8 disk.c:236
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5bde disk.c:242
+ mov word [es:di+028h], 05441h ; 26 c7 45 28 41 54 ; 0xf5be1
+ mov word [es:di+02ah], 02041h ; 26 c7 45 2a 41 20 ; 0xf5be7 disk.c:244
+ mov word [es:di+02ch], 02020h ; 26 c7 45 2c 20 20 ; 0xf5bed disk.c:246
+ mov word [es:di+02eh], 02020h ; 26 c7 45 2e 20 20 ; 0xf5bf3 disk.c:248
+ test al, al ; 84 c0 ; 0xf5bf9 disk.c:251
+ jne short 05c13h ; 75 16 ; 0xf5bfb
+ mov word [es:di+030h], dx ; 26 89 55 30 ; 0xf5bfd disk.c:252
+ mov word [es:di+032h], strict word 00000h ; 26 c7 45 32 00 00 ; 0xf5c01 disk.c:253
+ mov word [es:di+034h], strict word 00000h ; 26 c7 45 34 00 00 ; 0xf5c07 disk.c:254
+ mov word [es:di+036h], strict word 00000h ; 26 c7 45 36 00 00 ; 0xf5c0d
+ mov al, byte [bp+008h] ; 8a 46 08 ; 0xf5c13 disk.c:259
+ and AL, strict byte 001h ; 24 01 ; 0xf5c16
+ xor ah, ah ; 30 e4 ; 0xf5c18
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5c1a
+ mov word [es:di+038h], ax ; 26 89 45 38 ; 0xf5c1d
+ mov word [es:di+03ah], strict word 00000h ; 26 c7 45 3a 00 00 ; 0xf5c21 disk.c:260
+ mov word [es:di+03ch], strict word 00000h ; 26 c7 45 3c 00 00 ; 0xf5c27 disk.c:261
+ mov word [es:di+03eh], strict word 00000h ; 26 c7 45 3e 00 00 ; 0xf5c2d
+ xor bl, bl ; 30 db ; 0xf5c33 disk.c:263
+ mov BH, strict byte 01eh ; b7 1e ; 0xf5c35 disk.c:264
+ jmp short 05c3eh ; eb 05 ; 0xf5c37
+ cmp bh, 040h ; 80 ff 40 ; 0xf5c39
+ jnc short 05c50h ; 73 12 ; 0xf5c3c
+ mov al, bh ; 88 f8 ; 0xf5c3e disk.c:265
+ xor ah, ah ; 30 e4 ; 0xf5c40
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5c42
+ mov si, di ; 89 fe ; 0xf5c45
+ add si, ax ; 01 c6 ; 0xf5c47
+ add bl, byte [es:si] ; 26 02 1c ; 0xf5c49
+ db 0feh, 0c7h
+ ; inc bh ; fe c7 ; 0xf5c4c
+ jmp short 05c39h ; eb e9 ; 0xf5c4e
+ neg bl ; f6 db ; 0xf5c50 disk.c:266
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5c52 disk.c:267
+ mov byte [es:di+041h], bl ; 26 88 5d 41 ; 0xf5c55
+ xor ax, ax ; 31 c0 ; 0xf5c59 disk.c:269
+ leave ; c9 ; 0xf5c5b disk.c:270
+ pop di ; 5f ; 0xf5c5c
+ pop si ; 5e ; 0xf5c5d
+ retn 00002h ; c2 02 00 ; 0xf5c5e
+ ; disGetNextSymbol 0xf5c61 LB 0x4267 -> off=0x32 cb=0000000000000431 uValue=00000000000f4693 'int13_harddisk'
+ db 01fh, 05dh, 030h, 05dh, 05dh, 05dh, 05dh, 05dh, 05dh, 05dh, 04fh, 05fh, 086h, 060h, 086h, 060h
+ db 07dh, 05fh, 063h, 060h, 086h, 060h, 086h, 060h, 063h, 060h, 063h, 060h, 086h, 060h, 086h, 060h
+ db 0e8h, 05fh, 063h, 060h, 086h, 060h, 086h, 060h, 063h, 060h, 019h, 060h, 086h, 060h, 086h, 060h
+ db 086h, 060h
+int13_harddisk: ; 0xf5c93 LB 0x431
+ push bp ; 55 ; 0xf5c93 disk.c:272
+ mov bp, sp ; 89 e5 ; 0xf5c94
+ sub sp, strict byte 00010h ; 83 ec 10 ; 0xf5c96
+ or byte [bp+01dh], 002h ; 80 4e 1d 02 ; 0xf5c99 disk.c:283
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf5c9d disk.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf5ca0
+ mov es, dx ; 8e c2 ; 0xf5ca3
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf5ca5
+ mov si, 00122h ; be 22 01 ; 0xf5ca8 disk.c:49
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf5cab
+ mov bx, 0008eh ; bb 8e 00 ; 0xf5cae disk.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf5cb1
+ mov dx, word [bp+00eh] ; 8b 56 0e ; 0xf5cb5 disk.c:289
+ xor dh, dh ; 30 f6 ; 0xf5cb8
+ cmp dx, 00080h ; 81 fa 80 00 ; 0xf5cba
+ jc short 05cc6h ; 72 06 ; 0xf5cbe
+ cmp dx, 00090h ; 81 fa 90 00 ; 0xf5cc0
+ jc short 05ce4h ; 72 1e ; 0xf5cc4
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf5cc6 disk.c:290
+ xor ah, ah ; 30 e4 ; 0xf5cc9
+ push ax ; 50 ; 0xf5ccb
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5ccc
+ shr ax, 008h ; c1 e8 08 ; 0xf5ccf
+ push ax ; 50 ; 0xf5cd2
+ push 0067eh ; 68 7e 06 ; 0xf5cd3
+ push 0068dh ; 68 8d 06 ; 0xf5cd6
+ push strict byte 00004h ; 6a 04 ; 0xf5cd9
+ call 018ffh ; e8 21 bc ; 0xf5cdb
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf5cde
+ jmp near 060a1h ; e9 bd 03 ; 0xf5ce1 disk.c:291
+ mov dx, word [bp+00eh] ; 8b 56 0e ; 0xf5ce4 disk.c:295
+ xor dh, dh ; 30 f6 ; 0xf5ce7
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf5ce9
+ mov bx, si ; 89 f3 ; 0xf5cec
+ add bx, dx ; 01 d3 ; 0xf5cee
+ mov bl, byte [es:bx+00163h] ; 26 8a 9f 63 01 ; 0xf5cf0
+ mov byte [bp-002h], bl ; 88 5e fe ; 0xf5cf5
+ cmp bl, 010h ; 80 fb 10 ; 0xf5cf8 disk.c:298
+ jc short 05d0dh ; 72 10 ; 0xf5cfb
+ push dx ; 52 ; 0xf5cfd disk.c:299
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5cfe
+ shr ax, 008h ; c1 e8 08 ; 0xf5d01
+ push ax ; 50 ; 0xf5d04
+ push 0067eh ; 68 7e 06 ; 0xf5d05
+ push 006b8h ; 68 b8 06 ; 0xf5d08
+ jmp short 05cd9h ; eb cc ; 0xf5d0b
+ mov bx, word [bp+016h] ; 8b 5e 16 ; 0xf5d0d disk.c:303
+ shr bx, 008h ; c1 eb 08 ; 0xf5d10
+ cmp bx, strict byte 00018h ; 83 fb 18 ; 0xf5d13
+ jnbe short 05d5ah ; 77 42 ; 0xf5d16
+ add bx, bx ; 01 db ; 0xf5d18
+ jmp word [cs:bx+05c61h] ; 2e ff a7 61 5c ; 0xf5d1a
+ cmp byte [bp-002h], 008h ; 80 7e fe 08 ; 0xf5d1f disk.c:308
+ jnc short 05d2dh ; 73 08 ; 0xf5d23
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf5d25 disk.c:310
+ xor ah, ah ; 30 e4 ; 0xf5d28
+ call 01d1dh ; e8 f0 bf ; 0xf5d2a
+ jmp near 05f65h ; e9 35 02 ; 0xf5d2d disk.c:311
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf5d30 disk.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5d33
+ mov es, ax ; 8e c0 ; 0xf5d36
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf5d38
+ mov bx, word [bp+016h] ; 8b 5e 16 ; 0xf5d3b disk.c:316
+ xor bh, bh ; 30 ff ; 0xf5d3e
+ mov dl, al ; 88 c2 ; 0xf5d40
+ xor dh, dh ; 30 f6 ; 0xf5d42
+ sal dx, 008h ; c1 e2 08 ; 0xf5d44
+ or bx, dx ; 09 d3 ; 0xf5d47
+ mov word [bp+016h], bx ; 89 5e 16 ; 0xf5d49
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf5d4c disk.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf5d4f
+ test al, al ; 84 c0 ; 0xf5d53 disk.c:319
+ je short 05dbch ; 74 65 ; 0xf5d55
+ jmp near 060bdh ; e9 63 03 ; 0xf5d57
+ jmp near 06086h ; e9 29 03 ; 0xf5d5a
+ mov dx, word [bp+016h] ; 8b 56 16 ; 0xf5d5d disk.c:327
+ xor dh, dh ; 30 f6 ; 0xf5d60
+ mov word [bp-00ah], dx ; 89 56 f6 ; 0xf5d62
+ mov di, word [bp+014h] ; 8b 7e 14 ; 0xf5d65 disk.c:328
+ shr di, 008h ; c1 ef 08 ; 0xf5d68
+ mov dx, word [bp+014h] ; 8b 56 14 ; 0xf5d6b disk.c:329
+ xor dh, dh ; 30 f6 ; 0xf5d6e
+ sal dx, 002h ; c1 e2 02 ; 0xf5d70
+ xor dl, dl ; 30 d2 ; 0xf5d73
+ and dh, 003h ; 80 e6 03 ; 0xf5d75
+ or di, dx ; 09 d7 ; 0xf5d78
+ mov dx, word [bp+014h] ; 8b 56 14 ; 0xf5d7a disk.c:330
+ and dx, strict byte 0003fh ; 83 e2 3f ; 0xf5d7d
+ mov word [bp-004h], dx ; 89 56 fc ; 0xf5d80
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf5d83 disk.c:331
+ shr dx, 008h ; c1 ea 08 ; 0xf5d86
+ mov word [bp-006h], dx ; 89 56 fa ; 0xf5d89
+ cmp word [bp-00ah], 00080h ; 81 7e f6 80 00 ; 0xf5d8c disk.c:334
+ jnbe short 05d99h ; 77 06 ; 0xf5d91
+ cmp word [bp-00ah], strict byte 00000h ; 83 7e f6 00 ; 0xf5d93
+ jne short 05dbfh ; 75 26 ; 0xf5d97
+ mov bx, 00da0h ; bb a0 0d ; 0xf5d99 disk.c:335
+ mov cx, ds ; 8c d9 ; 0xf5d9c
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5d9e
+ call 018bch ; e8 18 bb ; 0xf5da1
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5da4
+ shr ax, 008h ; c1 e8 08 ; 0xf5da7
+ push ax ; 50 ; 0xf5daa
+ push 0067eh ; 68 7e 06 ; 0xf5dab
+ push 006eah ; 68 ea 06 ; 0xf5dae
+ push strict byte 00004h ; 6a 04 ; 0xf5db1
+ call 018ffh ; e8 49 bb ; 0xf5db3
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf5db6
+ jmp near 060a1h ; e9 e5 02 ; 0xf5db9 disk.c:336
+ jmp near 05f69h ; e9 aa 01 ; 0xf5dbc
+ mov dl, byte [bp-002h] ; 8a 56 fe ; 0xf5dbf disk.c:340
+ xor dh, dh ; 30 f6 ; 0xf5dc2
+ imul dx, dx, strict byte 0001ch ; 6b d2 1c ; 0xf5dc4
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf5dc7
+ mov bx, si ; 89 f3 ; 0xf5dca
+ add bx, dx ; 01 d3 ; 0xf5dcc
+ mov dx, word [es:bx+02ch] ; 26 8b 57 2c ; 0xf5dce
+ mov word [bp-010h], dx ; 89 56 f0 ; 0xf5dd2
+ mov cx, word [es:bx+02ah] ; 26 8b 4f 2a ; 0xf5dd5 disk.c:341
+ mov dx, word [es:bx+02eh] ; 26 8b 57 2e ; 0xf5dd9 disk.c:342
+ mov word [bp-008h], dx ; 89 56 f8 ; 0xf5ddd
+ cmp di, word [bp-010h] ; 3b 7e f0 ; 0xf5de0 disk.c:345
+ jnc short 05df2h ; 73 0d ; 0xf5de3
+ cmp cx, word [bp-006h] ; 3b 4e fa ; 0xf5de5
+ jbe short 05df2h ; 76 08 ; 0xf5de8
+ mov dx, word [bp-004h] ; 8b 56 fc ; 0xf5dea
+ cmp dx, word [bp-008h] ; 3b 56 f8 ; 0xf5ded
+ jbe short 05e22h ; 76 30 ; 0xf5df0
+ mov bx, 00da0h ; bb a0 0d ; 0xf5df2 disk.c:346
+ mov cx, ds ; 8c d9 ; 0xf5df5
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5df7
+ call 018bch ; e8 bf ba ; 0xf5dfa
+ push word [bp-004h] ; ff 76 fc ; 0xf5dfd
+ push word [bp-006h] ; ff 76 fa ; 0xf5e00
+ push di ; 57 ; 0xf5e03
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf5e04
+ xor ah, ah ; 30 e4 ; 0xf5e07
+ push ax ; 50 ; 0xf5e09
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5e0a
+ shr ax, 008h ; c1 e8 08 ; 0xf5e0d
+ push ax ; 50 ; 0xf5e10
+ push 0067eh ; 68 7e 06 ; 0xf5e11
+ push 00712h ; 68 12 07 ; 0xf5e14
+ push strict byte 00004h ; 6a 04 ; 0xf5e17
+ call 018ffh ; e8 e3 ba ; 0xf5e19
+ add sp, strict byte 00010h ; 83 c4 10 ; 0xf5e1c
+ jmp near 060a1h ; e9 7f 02 ; 0xf5e1f disk.c:347
+ mov dx, word [bp+016h] ; 8b 56 16 ; 0xf5e22 disk.c:351
+ shr dx, 008h ; c1 ea 08 ; 0xf5e25
+ cmp dx, strict byte 00004h ; 83 fa 04 ; 0xf5e28
+ je short 05e4dh ; 74 20 ; 0xf5e2b
+ mov dl, byte [bp-002h] ; 8a 56 fe ; 0xf5e2d disk.c:356
+ xor dh, dh ; 30 f6 ; 0xf5e30
+ imul dx, dx, strict byte 0001ch ; 6b d2 1c ; 0xf5e32
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf5e35
+ mov bx, si ; 89 f3 ; 0xf5e38
+ add bx, dx ; 01 d3 ; 0xf5e3a
+ cmp cx, word [es:bx+030h] ; 26 3b 4f 30 ; 0xf5e3c
+ jne short 05e56h ; 75 14 ; 0xf5e40
+ mov dx, word [es:bx+034h] ; 26 8b 57 34 ; 0xf5e42
+ cmp dx, word [bp-008h] ; 3b 56 f8 ; 0xf5e46
+ je short 05e50h ; 74 05 ; 0xf5e49
+ jmp short 05e56h ; eb 09 ; 0xf5e4b
+ jmp near 05f65h ; e9 15 01 ; 0xf5e4d
+ cmp byte [bp-002h], 008h ; 80 7e fe 08 ; 0xf5e50
+ jc short 05e85h ; 72 2f ; 0xf5e54
+ mov ax, di ; 89 f8 ; 0xf5e56 disk.c:357
+ xor dx, dx ; 31 d2 ; 0xf5e58
+ mov bx, cx ; 89 cb ; 0xf5e5a
+ xor cx, cx ; 31 c9 ; 0xf5e5c
+ call 09b40h ; e8 df 3c ; 0xf5e5e
+ xor bx, bx ; 31 db ; 0xf5e61
+ add ax, word [bp-006h] ; 03 46 fa ; 0xf5e63
+ adc dx, bx ; 11 da ; 0xf5e66
+ mov bx, word [bp-008h] ; 8b 5e f8 ; 0xf5e68
+ xor cx, cx ; 31 c9 ; 0xf5e6b
+ call 09b40h ; e8 d0 3c ; 0xf5e6d
+ xor bx, bx ; 31 db ; 0xf5e70
+ add ax, word [bp-004h] ; 03 46 fc ; 0xf5e72
+ adc dx, bx ; 11 da ; 0xf5e75
+ add ax, strict word 0ffffh ; 05 ff ff ; 0xf5e77
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf5e7a
+ mov ax, dx ; 89 d0 ; 0xf5e7d
+ adc ax, strict word 0ffffh ; 15 ff ff ; 0xf5e7f
+ mov word [bp-004h], bx ; 89 5e fc ; 0xf5e82 disk.c:358
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf5e85 disk.c:365
+ mov word [es:si+018h], strict word 00000h ; 26 c7 44 18 00 00 ; 0xf5e88
+ mov word [es:si+01ah], strict word 00000h ; 26 c7 44 1a 00 00 ; 0xf5e8e disk.c:366
+ mov word [es:si+01ch], strict word 00000h ; 26 c7 44 1c 00 00 ; 0xf5e94
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf5e9a disk.c:369
+ mov word [es:si], dx ; 26 89 14 ; 0xf5e9d
+ mov word [es:si+002h], ax ; 26 89 44 02 ; 0xf5ea0
+ mov word [es:si+004h], strict word 00000h ; 26 c7 44 04 00 00 ; 0xf5ea4
+ mov word [es:si+006h], strict word 00000h ; 26 c7 44 06 00 00 ; 0xf5eaa
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf5eb0 disk.c:370
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf5eb3
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf5eb6
+ mov word [es:si+00ah], dx ; 26 89 54 0a ; 0xf5eba
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf5ebe disk.c:371
+ mov word [es:si+00eh], ax ; 26 89 44 0e ; 0xf5ec1
+ mov word [es:si+010h], 00200h ; 26 c7 44 10 00 02 ; 0xf5ec5 disk.c:372
+ mov word [es:si+012h], di ; 26 89 7c 12 ; 0xf5ecb disk.c:373
+ mov ax, word [bp-006h] ; 8b 46 fa ; 0xf5ecf disk.c:374
+ mov word [es:si+014h], ax ; 26 89 44 14 ; 0xf5ed2
+ mov ax, word [bp-004h] ; 8b 46 fc ; 0xf5ed6 disk.c:375
+ mov word [es:si+016h], ax ; 26 89 44 16 ; 0xf5ed9
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf5edd disk.c:376
+ mov byte [es:si+00ch], al ; 26 88 44 0c ; 0xf5ee0
+ xor ah, ah ; 30 e4 ; 0xf5ee4 disk.c:378
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf5ee6
+ mov bx, si ; 89 f3 ; 0xf5ee9
+ add bx, ax ; 01 c3 ; 0xf5eeb
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf5eed
+ xor ah, ah ; 30 e4 ; 0xf5ef1
+ mov bx, ax ; 89 c3 ; 0xf5ef3
+ sal bx, 002h ; c1 e3 02 ; 0xf5ef5
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5ef8
+ shr ax, 008h ; c1 e8 08 ; 0xf5efb
+ add ax, ax ; 01 c0 ; 0xf5efe
+ add bx, ax ; 01 c3 ; 0xf5f00
+ push ES ; 06 ; 0xf5f02
+ push si ; 56 ; 0xf5f03
+ call word [word bx+0007eh] ; ff 97 7e 00 ; 0xf5f04
+ mov dx, ax ; 89 c2 ; 0xf5f08
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5f0a disk.c:381
+ xor al, al ; 30 c0 ; 0xf5f0d
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf5f0f
+ mov bx, word [es:si+018h] ; 26 8b 5c 18 ; 0xf5f12
+ or bx, ax ; 09 c3 ; 0xf5f16
+ mov word [bp+016h], bx ; 89 5e 16 ; 0xf5f18
+ test dl, dl ; 84 d2 ; 0xf5f1b disk.c:383
+ je short 05f65h ; 74 46 ; 0xf5f1d
+ mov bx, 00da0h ; bb a0 0d ; 0xf5f1f disk.c:384
+ mov cx, ds ; 8c d9 ; 0xf5f22
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5f24
+ call 018bch ; e8 92 b9 ; 0xf5f27
+ mov al, dl ; 88 d0 ; 0xf5f2a
+ xor ah, ah ; 30 e4 ; 0xf5f2c
+ push ax ; 50 ; 0xf5f2e
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5f2f
+ shr ax, 008h ; c1 e8 08 ; 0xf5f32
+ push ax ; 50 ; 0xf5f35
+ push 0067eh ; 68 7e 06 ; 0xf5f36
+ push 00759h ; 68 59 07 ; 0xf5f39
+ push strict byte 00004h ; 6a 04 ; 0xf5f3c
+ call 018ffh ; e8 be b9 ; 0xf5f3e
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf5f41
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5f44 disk.c:385
+ xor ah, ah ; 30 e4 ; 0xf5f47
+ or ah, 00ch ; 80 cc 0c ; 0xf5f49
+ jmp near 060a9h ; e9 5a 01 ; 0xf5f4c disk.c:386
+ mov bx, 00da0h ; bb a0 0d ; 0xf5f4f disk.c:393
+ mov cx, ds ; 8c d9 ; 0xf5f52
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5f54
+ call 018bch ; e8 62 b9 ; 0xf5f57
+ push 0077ah ; 68 7a 07 ; 0xf5f5a
+ push strict byte 00004h ; 6a 04 ; 0xf5f5d
+ call 018ffh ; e8 9d b9 ; 0xf5f5f
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf5f62
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf5f65 disk.c:394
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf5f69
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5f6c
+ mov es, ax ; 8e c0 ; 0xf5f6f
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf5f71
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf5f75
+ mov sp, bp ; 89 ec ; 0xf5f79
+ pop bp ; 5d ; 0xf5f7b
+ retn ; c3 ; 0xf5f7c
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf5f7d disk.c:400
+ xor ah, ah ; 30 e4 ; 0xf5f80
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf5f82
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf5f85
+ mov di, si ; 89 f7 ; 0xf5f88
+ add di, ax ; 01 c7 ; 0xf5f8a
+ mov bx, word [es:di+02ch] ; 26 8b 5d 2c ; 0xf5f8c
+ mov cx, word [es:di+02ah] ; 26 8b 4d 2a ; 0xf5f90 disk.c:401
+ mov ax, word [es:di+02eh] ; 26 8b 45 2e ; 0xf5f94 disk.c:402
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf5f98
+ mov al, byte [es:si+001e2h] ; 26 8a 84 e2 01 ; 0xf5f9b disk.c:404
+ xor ah, ah ; 30 e4 ; 0xf5fa0
+ mov byte [bp+016h], ah ; 88 66 16 ; 0xf5fa2 disk.c:407
+ mov dx, word [bp+014h] ; 8b 56 14 ; 0xf5fa5 disk.c:408
+ xor dh, dh ; 30 f6 ; 0xf5fa8
+ dec bx ; 4b ; 0xf5faa disk.c:406
+ mov si, bx ; 89 de ; 0xf5fab
+ and si, 000ffh ; 81 e6 ff 00 ; 0xf5fad
+ sal si, 008h ; c1 e6 08 ; 0xf5fb1
+ or dx, si ; 09 f2 ; 0xf5fb4
+ mov word [bp+014h], dx ; 89 56 14 ; 0xf5fb6
+ shr bx, 002h ; c1 eb 02 ; 0xf5fb9 disk.c:409
+ and bl, 0c0h ; 80 e3 c0 ; 0xf5fbc
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf5fbf
+ and dl, 03fh ; 80 e2 3f ; 0xf5fc2
+ or dl, bl ; 08 da ; 0xf5fc5
+ mov bx, word [bp+014h] ; 8b 5e 14 ; 0xf5fc7
+ mov bl, dl ; 88 d3 ; 0xf5fca
+ mov word [bp+014h], bx ; 89 5e 14 ; 0xf5fcc
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf5fcf disk.c:410
+ xor dh, dh ; 30 f6 ; 0xf5fd2
+ sal cx, 008h ; c1 e1 08 ; 0xf5fd4
+ sub cx, 00100h ; 81 e9 00 01 ; 0xf5fd7
+ or dx, cx ; 09 ca ; 0xf5fdb
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf5fdd
+ mov dl, al ; 88 c2 ; 0xf5fe0 disk.c:411
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf5fe2
+ jmp near 05f65h ; e9 7d ff ; 0xf5fe5 disk.c:416
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf5fe8 disk.c:423
+ xor ah, ah ; 30 e4 ; 0xf5feb
+ cwd ; 99 ; 0xf5fed
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf5fee
+ sar ax, 1 ; d1 f8 ; 0xf5ff0
+ imul ax, ax, strict byte 00006h ; 6b c0 06 ; 0xf5ff2
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf5ff5
+ add si, ax ; 01 c6 ; 0xf5ff8
+ mov dx, word [es:si+00206h] ; 26 8b 94 06 02 ; 0xf5ffa
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf5fff
+ in AL, DX ; ec ; 0xf6002
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6003
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf6005 disk.c:424
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf6007
+ jne short 0600eh ; 75 03 ; 0xf6009
+ jmp near 05f65h ; e9 57 ff ; 0xf600b disk.c:425
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf600e disk.c:427
+ xor ah, ah ; 30 e4 ; 0xf6011
+ or ah, 0aah ; 80 cc aa ; 0xf6013
+ jmp near 060a9h ; e9 90 00 ; 0xf6016
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf6019 disk.c:435
+ xor ah, ah ; 30 e4 ; 0xf601c
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf601e
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf6021
+ add si, ax ; 01 c6 ; 0xf6024
+ mov di, word [es:si+032h] ; 26 8b 7c 32 ; 0xf6026
+ mov ax, word [es:si+030h] ; 26 8b 44 30 ; 0xf602a disk.c:436
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf602e
+ mov ax, word [es:si+034h] ; 26 8b 44 34 ; 0xf6031 disk.c:437
+ mov word [bp-004h], ax ; 89 46 fc ; 0xf6035
+ mov ax, di ; 89 f8 ; 0xf6038 disk.c:440
+ xor dx, dx ; 31 d2 ; 0xf603a
+ mov bx, word [bp-006h] ; 8b 5e fa ; 0xf603c
+ xor cx, cx ; 31 c9 ; 0xf603f
+ call 09b40h ; e8 fc 3a ; 0xf6041
+ mov bx, word [bp-004h] ; 8b 5e fc ; 0xf6044
+ xor cx, cx ; 31 c9 ; 0xf6047
+ call 09b40h ; e8 f4 3a ; 0xf6049
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf604c
+ mov word [bp+014h], dx ; 89 56 14 ; 0xf604f disk.c:441
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf6052 disk.c:442
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6055 disk.c:444
+ xor ah, ah ; 30 e4 ; 0xf6058
+ or ah, 003h ; 80 cc 03 ; 0xf605a
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf605d
+ jmp near 05f69h ; e9 06 ff ; 0xf6060 disk.c:445
+ mov bx, 00da0h ; bb a0 0d ; 0xf6063 disk.c:453
+ mov cx, ds ; 8c d9 ; 0xf6066
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6068
+ call 018bch ; e8 4e b8 ; 0xf606b
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf606e
+ shr ax, 008h ; c1 e8 08 ; 0xf6071
+ push ax ; 50 ; 0xf6074
+ push 0067eh ; 68 7e 06 ; 0xf6075
+ push 00794h ; 68 94 07 ; 0xf6078
+ push strict byte 00004h ; 6a 04 ; 0xf607b
+ call 018ffh ; e8 7f b8 ; 0xf607d
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf6080
+ jmp near 05f65h ; e9 df fe ; 0xf6083 disk.c:454
+ mov bx, 00da0h ; bb a0 0d ; 0xf6086 disk.c:461
+ mov cx, ds ; 8c d9 ; 0xf6089
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf608b
+ call 018bch ; e8 2b b8 ; 0xf608e
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6091
+ shr ax, 008h ; c1 e8 08 ; 0xf6094
+ push ax ; 50 ; 0xf6097
+ push 0067eh ; 68 7e 06 ; 0xf6098
+ push 007c7h ; 68 c7 07 ; 0xf609b
+ jmp near 05db1h ; e9 10 fd ; 0xf609e
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf60a1 disk.c:467
+ xor ah, ah ; 30 e4 ; 0xf60a4
+ or ah, 001h ; 80 cc 01 ; 0xf60a6
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf60a9
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf60ac disk.c:469
+ shr ax, 008h ; c1 e8 08 ; 0xf60af
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf60b2 disk.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf60b5
+ mov es, dx ; 8e c2 ; 0xf60b8
+ mov byte [es:bx], al ; 26 88 07 ; 0xf60ba
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf60bd disk.c:471
+ jmp near 05f79h ; e9 b5 fe ; 0xf60c1 disk.c:472
+ ; disGetNextSymbol 0xf60c4 LB 0x3e04 -> off=0x20 cb=0000000000000297 uValue=00000000000f4ae4 'int13_harddisk_ext'
+ db 072h, 061h, 0a5h, 061h, 0a5h, 061h, 0a5h, 061h, 063h, 063h, 009h, 063h, 0a5h, 061h, 011h, 063h
+ db 063h, 063h, 08ah, 061h, 08ah, 061h, 08ah, 061h, 08ah, 061h, 02bh, 063h, 08ah, 061h, 08ah, 061h
+int13_harddisk_ext: ; 0xf60e4 LB 0x297
+ push bp ; 55 ; 0xf60e4 disk.c:482
+ mov bp, sp ; 89 e5 ; 0xf60e5
+ sub sp, strict byte 00016h ; 83 ec 16 ; 0xf60e7
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf60ea disk.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf60ed
+ mov es, ax ; 8e c0 ; 0xf60f0
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf60f2
+ mov di, 00122h ; bf 22 01 ; 0xf60f5 disk.c:49
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf60f8
+ mov bx, 0008eh ; bb 8e 00 ; 0xf60fb disk.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf60fe
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf6102 disk.c:506
+ xor ah, ah ; 30 e4 ; 0xf6105
+ cmp ax, 00080h ; 3d 80 00 ; 0xf6107
+ jc short 06111h ; 72 05 ; 0xf610a
+ cmp ax, 00090h ; 3d 90 00 ; 0xf610c
+ jc short 0612fh ; 72 1e ; 0xf610f
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf6111 disk.c:507
+ xor ah, ah ; 30 e4 ; 0xf6114
+ push ax ; 50 ; 0xf6116
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6117
+ shr ax, 008h ; c1 e8 08 ; 0xf611a
+ push ax ; 50 ; 0xf611d
+ push 007f5h ; 68 f5 07 ; 0xf611e
+ push 0068dh ; 68 8d 06 ; 0xf6121
+ push strict byte 00004h ; 6a 04 ; 0xf6124
+ call 018ffh ; e8 d6 b7 ; 0xf6126
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf6129
+ jmp near 06341h ; e9 12 02 ; 0xf612c disk.c:508
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf612f disk.c:512
+ xor ah, ah ; 30 e4 ; 0xf6132
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6134
+ mov bx, di ; 89 fb ; 0xf6137
+ add bx, ax ; 01 c3 ; 0xf6139
+ mov dl, byte [es:bx+00163h] ; 26 8a 97 63 01 ; 0xf613b
+ mov byte [bp-004h], dl ; 88 56 fc ; 0xf6140
+ cmp dl, 010h ; 80 fa 10 ; 0xf6143 disk.c:515
+ jc short 06158h ; 72 10 ; 0xf6146
+ push ax ; 50 ; 0xf6148 disk.c:516
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6149
+ shr ax, 008h ; c1 e8 08 ; 0xf614c
+ push ax ; 50 ; 0xf614f
+ push 007f5h ; 68 f5 07 ; 0xf6150
+ push 006b8h ; 68 b8 06 ; 0xf6153
+ jmp short 06124h ; eb cc ; 0xf6156
+ mov bx, word [bp+016h] ; 8b 5e 16 ; 0xf6158 disk.c:520
+ shr bx, 008h ; c1 eb 08 ; 0xf615b
+ sub bx, strict byte 00041h ; 83 eb 41 ; 0xf615e
+ cmp bx, strict byte 0000fh ; 83 fb 0f ; 0xf6161
+ jnbe short 0618ah ; 77 24 ; 0xf6164
+ add bx, bx ; 01 db ; 0xf6166
+ mov cx, word [bp+016h] ; 8b 4e 16 ; 0xf6168
+ xor ch, ch ; 30 ed ; 0xf616b
+ jmp word [cs:bx+060c4h] ; 2e ff a7 c4 60 ; 0xf616d
+ mov word [bp+010h], 0aa55h ; c7 46 10 55 aa ; 0xf6172 disk.c:522
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6177 disk.c:523
+ xor ah, ah ; 30 e4 ; 0xf617a
+ or ah, 030h ; 80 cc 30 ; 0xf617c
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf617f
+ mov word [bp+014h], strict word 00007h ; c7 46 14 07 00 ; 0xf6182 disk.c:524
+ jmp near 06367h ; e9 dd 01 ; 0xf6187 disk.c:525
+ mov bx, 00da0h ; bb a0 0d ; 0xf618a
+ mov cx, ds ; 8c d9 ; 0xf618d
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf618f
+ call 018bch ; e8 27 b7 ; 0xf6192
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6195
+ shr ax, 008h ; c1 e8 08 ; 0xf6198
+ push ax ; 50 ; 0xf619b
+ push 007f5h ; 68 f5 07 ; 0xf619c
+ push 007c7h ; 68 c7 07 ; 0xf619f
+ jmp near 06242h ; e9 9d 00 ; 0xf61a2
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf61a5 disk.c:534
+ mov word [bp-016h], bx ; 89 5e ea ; 0xf61a8
+ mov es, [bp+004h] ; 8e 46 04 ; 0xf61ab
+ mov word [bp-014h], bx ; 89 5e ec ; 0xf61ae
+ mov [bp-012h], es ; 8c 46 ee ; 0xf61b1
+ mov ax, word [es:bx+002h] ; 26 8b 47 02 ; 0xf61b4 disk.c:536
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf61b8
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf61bb disk.c:537
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf61bf
+ mov ax, word [es:bx+004h] ; 26 8b 47 04 ; 0xf61c2 disk.c:538
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf61c6
+ mov dx, word [es:bx+00ch] ; 26 8b 57 0c ; 0xf61c9 disk.c:541
+ mov cx, word [es:bx+00eh] ; 26 8b 4f 0e ; 0xf61cd
+ xor ax, ax ; 31 c0 ; 0xf61d1 disk.c:542
+ xor bx, bx ; 31 db ; 0xf61d3
+ mov si, strict word 00020h ; be 20 00 ; 0xf61d5
+ call 09ba0h ; e8 c5 39 ; 0xf61d8
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf61db
+ mov si, bx ; 89 de ; 0xf61de
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf61e0 disk.c:543
+ mov ax, word [es:bx+008h] ; 26 8b 47 08 ; 0xf61e3
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf61e7
+ mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xf61ea
+ or dx, word [bp-016h] ; 0b 56 ea ; 0xf61ee
+ or cx, ax ; 09 c1 ; 0xf61f1
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf61f3 disk.c:548
+ xor ah, ah ; 30 e4 ; 0xf61f6
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf61f8
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf61fb
+ mov bx, di ; 89 fb ; 0xf61fe
+ add bx, ax ; 01 c3 ; 0xf6200
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf6202
+ mov byte [bp-002h], al ; 88 46 fe ; 0xf6206
+ mov ax, word [bp-008h] ; 8b 46 f8 ; 0xf6209 disk.c:549
+ cmp ax, word [es:bx+03ch] ; 26 3b 47 3c ; 0xf620c
+ jnbe short 0622ah ; 77 18 ; 0xf6210
+ jne short 0624dh ; 75 39 ; 0xf6212
+ cmp si, word [es:bx+03ah] ; 26 3b 77 3a ; 0xf6214
+ jnbe short 0622ah ; 77 10 ; 0xf6218
+ jne short 0624dh ; 75 31 ; 0xf621a
+ cmp cx, word [es:bx+038h] ; 26 3b 4f 38 ; 0xf621c
+ jnbe short 0622ah ; 77 08 ; 0xf6220
+ jne short 0624dh ; 75 29 ; 0xf6222
+ cmp dx, word [es:bx+036h] ; 26 3b 57 36 ; 0xf6224
+ jc short 0624dh ; 72 23 ; 0xf6228
+ mov bx, 00da0h ; bb a0 0d ; 0xf622a disk.c:550
+ mov cx, ds ; 8c d9 ; 0xf622d
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf622f
+ call 018bch ; e8 87 b6 ; 0xf6232
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6235
+ shr ax, 008h ; c1 e8 08 ; 0xf6238
+ push ax ; 50 ; 0xf623b
+ push 007f5h ; 68 f5 07 ; 0xf623c
+ push 00808h ; 68 08 08 ; 0xf623f
+ push strict byte 00004h ; 6a 04 ; 0xf6242
+ call 018ffh ; e8 b8 b6 ; 0xf6244
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf6247
+ jmp near 06341h ; e9 f4 00 ; 0xf624a disk.c:551
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf624d disk.c:555
+ shr ax, 008h ; c1 e8 08 ; 0xf6250
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf6253
+ cmp ax, strict word 00044h ; 3d 44 00 ; 0xf6256
+ je short 06260h ; 74 05 ; 0xf6259
+ cmp ax, strict word 00047h ; 3d 47 00 ; 0xf625b
+ jne short 06263h ; 75 03 ; 0xf625e
+ jmp near 06363h ; e9 00 01 ; 0xf6260 disk.c:556
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6263 disk.c:559
+ mov word [es:di+018h], strict word 00000h ; 26 c7 45 18 00 00 ; 0xf6266
+ mov word [es:di+01ah], strict word 00000h ; 26 c7 45 1a 00 00 ; 0xf626c disk.c:560
+ mov word [es:di+01ch], strict word 00000h ; 26 c7 45 1c 00 00 ; 0xf6272
+ mov ax, word [bp-008h] ; 8b 46 f8 ; 0xf6278 disk.c:563
+ mov word [es:di+006h], ax ; 26 89 45 06 ; 0xf627b
+ mov word [es:di+004h], si ; 26 89 75 04 ; 0xf627f
+ mov word [es:di+002h], cx ; 26 89 4d 02 ; 0xf6283
+ mov word [es:di], dx ; 26 89 15 ; 0xf6287
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf628a disk.c:564
+ mov word [es:di+008h], ax ; 26 89 45 08 ; 0xf628d
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf6291
+ mov word [es:di+00ah], ax ; 26 89 45 0a ; 0xf6294
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf6298 disk.c:565
+ mov word [es:di+00eh], ax ; 26 89 45 0e ; 0xf629b
+ mov word [es:di+010h], 00200h ; 26 c7 45 10 00 02 ; 0xf629f disk.c:566
+ mov word [es:di+016h], strict word 00000h ; 26 c7 45 16 00 00 ; 0xf62a5 disk.c:567
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf62ab disk.c:568
+ mov byte [es:di+00ch], al ; 26 88 45 0c ; 0xf62ae
+ mov bx, word [bp-00ah] ; 8b 5e f6 ; 0xf62b2 disk.c:571
+ add bx, bx ; 01 db ; 0xf62b5
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf62b7
+ xor ah, ah ; 30 e4 ; 0xf62ba
+ sal ax, 002h ; c1 e0 02 ; 0xf62bc
+ add bx, ax ; 01 c3 ; 0xf62bf
+ push ES ; 06 ; 0xf62c1
+ push di ; 57 ; 0xf62c2
+ call word [word bx-00002h] ; ff 97 fe ff ; 0xf62c3
+ mov dx, ax ; 89 c2 ; 0xf62c7
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf62c9 disk.c:572
+ mov ax, word [es:di+018h] ; 26 8b 45 18 ; 0xf62cc
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf62d0
+ les bx, [bp-014h] ; c4 5e ec ; 0xf62d3 disk.c:573
+ mov word [es:bx+002h], ax ; 26 89 47 02 ; 0xf62d6
+ test dl, dl ; 84 d2 ; 0xf62da disk.c:575
+ je short 06260h ; 74 82 ; 0xf62dc
+ mov bx, 00da0h ; bb a0 0d ; 0xf62de disk.c:576
+ mov cx, ds ; 8c d9 ; 0xf62e1
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf62e3
+ call 018bch ; e8 d3 b5 ; 0xf62e6
+ mov al, dl ; 88 d0 ; 0xf62e9
+ xor ah, ah ; 30 e4 ; 0xf62eb
+ push ax ; 50 ; 0xf62ed
+ push word [bp-00ah] ; ff 76 f6 ; 0xf62ee
+ push 007f5h ; 68 f5 07 ; 0xf62f1
+ push 00759h ; 68 59 07 ; 0xf62f4
+ push strict byte 00004h ; 6a 04 ; 0xf62f7
+ call 018ffh ; e8 03 b6 ; 0xf62f9
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf62fc
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf62ff disk.c:577
+ xor ah, ah ; 30 e4 ; 0xf6302
+ or ah, 00ch ; 80 cc 0c ; 0xf6304
+ jmp short 06349h ; eb 40 ; 0xf6307 disk.c:578
+ or ch, 0b2h ; 80 cd b2 ; 0xf6309 disk.c:590
+ mov word [bp+016h], cx ; 89 4e 16 ; 0xf630c
+ jmp short 0634ch ; eb 3b ; 0xf630f disk.c:591
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf6311 disk.c:595
+ xor ah, ah ; 30 e4 ; 0xf6314
+ push ax ; 50 ; 0xf6316
+ mov ax, word [bp+00ah] ; 8b 46 0a ; 0xf6317
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf631a
+ mov bx, di ; 89 fb ; 0xf631d
+ mov cx, word [bp-006h] ; 8b 4e fa ; 0xf631f
+ call 05965h ; e8 40 f6 ; 0xf6322
+ test ax, ax ; 85 c0 ; 0xf6325
+ je short 06363h ; 74 3a ; 0xf6327
+ jmp short 06341h ; eb 16 ; 0xf6329 disk.c:596
+ cmp cx, strict byte 00006h ; 83 f9 06 ; 0xf632b disk.c:603
+ je short 06363h ; 74 33 ; 0xf632e
+ cmp cx, strict byte 00001h ; 83 f9 01 ; 0xf6330
+ jc short 06341h ; 72 0c ; 0xf6333
+ jbe short 06363h ; 76 2c ; 0xf6335
+ cmp cx, strict byte 00003h ; 83 f9 03 ; 0xf6337
+ jc short 06341h ; 72 05 ; 0xf633a
+ cmp cx, strict byte 00004h ; 83 f9 04 ; 0xf633c
+ jbe short 06363h ; 76 22 ; 0xf633f
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6341 disk.c:623
+ xor ah, ah ; 30 e4 ; 0xf6344
+ or ah, 001h ; 80 cc 01 ; 0xf6346
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf6349
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf634c disk.c:625
+ shr ax, 008h ; c1 e8 08 ; 0xf634f
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf6352 disk.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf6355
+ mov es, dx ; 8e c2 ; 0xf6358
+ mov byte [es:bx], al ; 26 88 07 ; 0xf635a
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf635d disk.c:626
+ jmp short 06377h ; eb 14 ; 0xf6361 disk.c:627
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf6363 disk.c:630
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf6367 disk.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf636a
+ mov es, ax ; 8e c0 ; 0xf636d
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf636f
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf6373 disk.c:633
+ mov sp, bp ; 89 ec ; 0xf6377 disk.c:635
+ pop bp ; 5d ; 0xf6379
+ retn ; c3 ; 0xf637a
+ ; disGetNextSymbol 0xf637b LB 0x3b4d -> off=0x0 cb=0000000000000153 uValue=00000000000f4d7b 'int14_function'
+int14_function: ; 0xf637b LB 0x153
+ push bp ; 55 ; 0xf637b serial.c:60
+ mov bp, sp ; 89 e5 ; 0xf637c
+ push si ; 56 ; 0xf637e
+ push di ; 57 ; 0xf637f
+ sti ; fb ; 0xf6380 serial.c:65
+ mov si, word [bp+00eh] ; 8b 76 0e ; 0xf6381 serial.c:67
+ add si, si ; 01 f6 ; 0xf6384
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf6386 serial.c:48
+ mov es, ax ; 8e c0 ; 0xf6389
+ mov si, word [es:si] ; 26 8b 34 ; 0xf638b
+ mov bx, si ; 89 f3 ; 0xf638e serial.c:49
+ mov di, word [bp+00eh] ; 8b 7e 0e ; 0xf6390 serial.c:68
+ add di, strict byte 0007ch ; 83 c7 7c ; 0xf6393
+ mov cl, byte [es:di] ; 26 8a 0d ; 0xf6396 serial.c:38
+ cmp word [bp+00eh], strict byte 00004h ; 83 7e 0e 04 ; 0xf6399 serial.c:69
+ jnc short 063a3h ; 73 04 ; 0xf639d
+ test si, si ; 85 f6 ; 0xf639f
+ jnbe short 063a6h ; 77 03 ; 0xf63a1
+ jmp near 064c3h ; e9 1d 01 ; 0xf63a3
+ mov al, byte [bp+013h] ; 8a 46 13 ; 0xf63a6 serial.c:70
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf63a9
+ jc short 063bah ; 72 0d ; 0xf63ab
+ jbe short 0641ah ; 76 6b ; 0xf63ad
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf63af
+ je short 06412h ; 74 5f ; 0xf63b1
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf63b3
+ je short 06415h ; 74 5e ; 0xf63b5
+ jmp near 064bdh ; e9 03 01 ; 0xf63b7
+ test al, al ; 84 c0 ; 0xf63ba
+ jne short 06417h ; 75 59 ; 0xf63bc
+ lea dx, [bx+003h] ; 8d 57 03 ; 0xf63be serial.c:72
+ in AL, DX ; ec ; 0xf63c1
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf63c2
+ or AL, strict byte 080h ; 0c 80 ; 0xf63c4
+ out DX, AL ; ee ; 0xf63c6
+ lea si, [bx+001h] ; 8d 77 01 ; 0xf63c7
+ mov al, byte [bp+012h] ; 8a 46 12 ; 0xf63ca serial.c:73
+ test AL, strict byte 0e0h ; a8 e0 ; 0xf63cd
+ jne short 063ddh ; 75 0c ; 0xf63cf
+ mov AL, strict byte 017h ; b0 17 ; 0xf63d1 serial.c:74
+ mov dx, bx ; 89 da ; 0xf63d3
+ out DX, AL ; ee ; 0xf63d5
+ mov AL, strict byte 004h ; b0 04 ; 0xf63d6 serial.c:75
+ mov dx, si ; 89 f2 ; 0xf63d8
+ out DX, AL ; ee ; 0xf63da
+ jmp short 063f4h ; eb 17 ; 0xf63db serial.c:76
+ and AL, strict byte 0e0h ; 24 e0 ; 0xf63dd serial.c:77
+ xor ah, ah ; 30 e4 ; 0xf63df
+ sar ax, 005h ; c1 f8 05 ; 0xf63e1
+ mov cl, al ; 88 c1 ; 0xf63e4
+ mov ax, 00600h ; b8 00 06 ; 0xf63e6
+ sar ax, CL ; d3 f8 ; 0xf63e9
+ mov dx, bx ; 89 da ; 0xf63eb
+ out DX, AL ; ee ; 0xf63ed
+ shr ax, 008h ; c1 e8 08 ; 0xf63ee serial.c:79
+ mov dx, si ; 89 f2 ; 0xf63f1
+ out DX, AL ; ee ; 0xf63f3
+ mov al, byte [bp+012h] ; 8a 46 12 ; 0xf63f4 serial.c:81
+ and AL, strict byte 01fh ; 24 1f ; 0xf63f7
+ lea dx, [bx+003h] ; 8d 57 03 ; 0xf63f9
+ out DX, AL ; ee ; 0xf63fc
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf63fd serial.c:82
+ in AL, DX ; ec ; 0xf6400
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6401
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf6403
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf6406 serial.c:83
+ in AL, DX ; ec ; 0xf6409
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf640a
+ mov byte [bp+012h], al ; 88 46 12 ; 0xf640c
+ jmp near 0649eh ; e9 8c 00 ; 0xf640f
+ jmp near 064ach ; e9 97 00 ; 0xf6412
+ jmp short 06465h ; eb 4e ; 0xf6415
+ jmp near 064bdh ; e9 a3 00 ; 0xf6417
+ mov si, strict word 0006ch ; be 6c 00 ; 0xf641a serial.c:48
+ mov si, word [es:si] ; 26 8b 34 ; 0xf641d
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf6420 serial.c:88
+ in AL, DX ; ec ; 0xf6423
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6424
+ and ax, strict word 00060h ; 25 60 00 ; 0xf6426
+ cmp ax, strict word 00060h ; 3d 60 00 ; 0xf6429
+ je short 06447h ; 74 19 ; 0xf642c
+ test cl, cl ; 84 c9 ; 0xf642e
+ je short 06447h ; 74 15 ; 0xf6430
+ mov di, strict word 0006ch ; bf 6c 00 ; 0xf6432 serial.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf6435
+ mov es, ax ; 8e c0 ; 0xf6438
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf643a
+ cmp ax, si ; 39 f0 ; 0xf643d serial.c:90
+ je short 06420h ; 74 df ; 0xf643f
+ mov si, ax ; 89 c6 ; 0xf6441 serial.c:91
+ db 0feh, 0c9h
+ ; dec cl ; fe c9 ; 0xf6443 serial.c:92
+ jmp short 06420h ; eb d9 ; 0xf6445 serial.c:94
+ test cl, cl ; 84 c9 ; 0xf6447 serial.c:95
+ je short 06451h ; 74 06 ; 0xf6449
+ mov al, byte [bp+012h] ; 8a 46 12 ; 0xf644b
+ mov dx, bx ; 89 da ; 0xf644e
+ out DX, AL ; ee ; 0xf6450
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf6451 serial.c:96
+ in AL, DX ; ec ; 0xf6454
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6455
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf6457
+ test cl, cl ; 84 c9 ; 0xf645a serial.c:97
+ jne short 0649eh ; 75 40 ; 0xf645c
+ or AL, strict byte 080h ; 0c 80 ; 0xf645e
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf6460
+ jmp short 0649eh ; eb 39 ; 0xf6463
+ mov si, strict word 0006ch ; be 6c 00 ; 0xf6465 serial.c:48
+ mov si, word [es:si] ; 26 8b 34 ; 0xf6468
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf646b serial.c:102
+ in AL, DX ; ec ; 0xf646e
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf646f
+ test AL, strict byte 001h ; a8 01 ; 0xf6471
+ jne short 0648eh ; 75 19 ; 0xf6473
+ test cl, cl ; 84 c9 ; 0xf6475
+ je short 0648eh ; 74 15 ; 0xf6477
+ mov di, strict word 0006ch ; bf 6c 00 ; 0xf6479 serial.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf647c
+ mov es, ax ; 8e c0 ; 0xf647f
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf6481
+ cmp ax, si ; 39 f0 ; 0xf6484 serial.c:104
+ je short 0646bh ; 74 e3 ; 0xf6486
+ mov si, ax ; 89 c6 ; 0xf6488 serial.c:105
+ db 0feh, 0c9h
+ ; dec cl ; fe c9 ; 0xf648a serial.c:106
+ jmp short 0646bh ; eb dd ; 0xf648c serial.c:108
+ test cl, cl ; 84 c9 ; 0xf648e serial.c:109
+ je short 064a4h ; 74 12 ; 0xf6490
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf6492 serial.c:110
+ mov dx, bx ; 89 da ; 0xf6496 serial.c:111
+ in AL, DX ; ec ; 0xf6498
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6499
+ mov byte [bp+012h], al ; 88 46 12 ; 0xf649b
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf649e serial.c:112
+ jmp short 064c7h ; eb 23 ; 0xf64a2
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf64a4 serial.c:113
+ in AL, DX ; ec ; 0xf64a7
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf64a8
+ jmp short 06460h ; eb b4 ; 0xf64aa
+ lea dx, [si+005h] ; 8d 54 05 ; 0xf64ac serial.c:118
+ in AL, DX ; ec ; 0xf64af
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf64b0
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf64b2
+ lea dx, [si+006h] ; 8d 54 06 ; 0xf64b5 serial.c:119
+ in AL, DX ; ec ; 0xf64b8
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf64b9
+ jmp short 0649bh ; eb de ; 0xf64bb
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf64bd serial.c:123
+ jmp short 064c7h ; eb 04 ; 0xf64c1 serial.c:125
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf64c3 serial.c:126
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf64c7 serial.c:128
+ pop di ; 5f ; 0xf64ca
+ pop si ; 5e ; 0xf64cb
+ pop bp ; 5d ; 0xf64cc
+ retn ; c3 ; 0xf64cd
+ ; disGetNextSymbol 0xf64ce LB 0x39fa -> off=0x0 cb=0000000000000043 uValue=00000000000f4ece 'timer_wait'
+timer_wait: ; 0xf64ce LB 0x43
+ push bp ; 55 ; 0xf64ce system.c:289
+ mov bp, sp ; 89 e5 ; 0xf64cf
+ push bx ; 53 ; 0xf64d1
+ push cx ; 51 ; 0xf64d2
+ push ax ; 50 ; 0xf64d3
+ mov bx, strict word 0000fh ; bb 0f 00 ; 0xf64d4 system.c:296
+ xor cx, cx ; 31 c9 ; 0xf64d7
+ call 09b60h ; e8 84 36 ; 0xf64d9
+ mov cx, ax ; 89 c1 ; 0xf64dc
+ mov bx, dx ; 89 d3 ; 0xf64de
+ mov dx, strict word 00061h ; ba 61 00 ; 0xf64e0 system.c:298
+ in AL, DX ; ec ; 0xf64e3
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf64e4
+ and AL, strict byte 010h ; 24 10 ; 0xf64e6
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf64e8
+ add cx, strict byte 0ffffh ; 83 c1 ff ; 0xf64eb system.c:299
+ adc bx, strict byte 0ffffh ; 83 d3 ff ; 0xf64ee
+ cmp bx, strict byte 0ffffh ; 83 fb ff ; 0xf64f1
+ jne short 064fbh ; 75 05 ; 0xf64f4
+ cmp cx, strict byte 0ffffh ; 83 f9 ff ; 0xf64f6
+ je short 0650ah ; 74 0f ; 0xf64f9
+ mov dx, strict word 00061h ; ba 61 00 ; 0xf64fb system.c:302
+ in AL, DX ; ec ; 0xf64fe
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf64ff
+ and AL, strict byte 010h ; 24 10 ; 0xf6501
+ cmp al, byte [bp-006h] ; 3a 46 fa ; 0xf6503 system.c:303
+ jne short 064fbh ; 75 f3 ; 0xf6506
+ jmp short 064ebh ; eb e1 ; 0xf6508 system.c:305
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf650a system.c:306
+ pop cx ; 59 ; 0xf650d
+ pop bx ; 5b ; 0xf650e
+ pop bp ; 5d ; 0xf650f
+ retn ; c3 ; 0xf6510
+ ; disGetNextSymbol 0xf6511 LB 0x39b7 -> off=0x0 cb=0000000000000030 uValue=00000000000f4f11 'set_enable_a20'
+set_enable_a20: ; 0xf6511 LB 0x30
+ push bp ; 55 ; 0xf6511 system.c:308
+ mov bp, sp ; 89 e5 ; 0xf6512
+ push bx ; 53 ; 0xf6514
+ push cx ; 51 ; 0xf6515
+ push dx ; 52 ; 0xf6516
+ mov bx, ax ; 89 c3 ; 0xf6517
+ mov dx, 00092h ; ba 92 00 ; 0xf6519 system.c:315
+ in AL, DX ; ec ; 0xf651c
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf651d
+ mov cl, al ; 88 c1 ; 0xf651f
+ test bx, bx ; 85 db ; 0xf6521 system.c:318
+ je short 0652ah ; 74 05 ; 0xf6523
+ or AL, strict byte 002h ; 0c 02 ; 0xf6525 system.c:319
+ out DX, AL ; ee ; 0xf6527
+ jmp short 0652dh ; eb 03 ; 0xf6528 system.c:320
+ and AL, strict byte 0fdh ; 24 fd ; 0xf652a system.c:321
+ out DX, AL ; ee ; 0xf652c
+ test cl, 002h ; f6 c1 02 ; 0xf652d system.c:323
+ je short 06537h ; 74 05 ; 0xf6530
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf6532
+ jmp short 06539h ; eb 02 ; 0xf6535
+ xor ax, ax ; 31 c0 ; 0xf6537
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf6539 system.c:324
+ pop dx ; 5a ; 0xf653c
+ pop cx ; 59 ; 0xf653d
+ pop bx ; 5b ; 0xf653e
+ pop bp ; 5d ; 0xf653f
+ retn ; c3 ; 0xf6540
+ ; disGetNextSymbol 0xf6541 LB 0x3987 -> off=0x3b cb=0000000000000318 uValue=00000000000f4f7c 'int15_function'
+ db 0ech, 0e9h, 0d8h, 0c7h, 0c1h, 0c0h, 0bfh, 091h, 090h, 089h, 088h, 086h, 083h, 052h, 04fh, 041h
+ db 024h, 022h, 000h, 076h, 068h, 0b7h, 065h, 017h, 068h, 0cbh, 065h, 017h, 068h, 06fh, 068h, 050h
+ db 066h, 060h, 066h, 000h, 067h, 00dh, 067h, 039h, 067h, 059h, 066h, 059h, 066h, 001h, 068h, 029h
+ db 068h, 03ch, 068h, 017h, 068h, 050h, 068h, 0c1h, 066h, 057h, 068h
+int15_function: ; 0xf657c LB 0x318
+ push bp ; 55 ; 0xf657c system.c:345
+ mov bp, sp ; 89 e5 ; 0xf657d
+ push si ; 56 ; 0xf657f
+ push di ; 57 ; 0xf6580
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf6581 system.c:352
+ shr ax, 008h ; c1 e8 08 ; 0xf6584
+ cmp ax, 000ech ; 3d ec 00 ; 0xf6587
+ jnbe short 065c1h ; 77 35 ; 0xf658a
+ push CS ; 0e ; 0xf658c
+ pop ES ; 07 ; 0xf658d
+ mov cx, strict word 00014h ; b9 14 00 ; 0xf658e
+ mov di, 06541h ; bf 41 65 ; 0xf6591
+ repne scasb ; f2 ae ; 0xf6594
+ sal cx, 1 ; d1 e1 ; 0xf6596
+ mov di, cx ; 89 cf ; 0xf6598
+ mov bx, word [cs:di+06554h] ; 2e 8b 9d 54 65 ; 0xf659a
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf659f
+ xor dh, dh ; 30 f6 ; 0xf65a2
+ mov si, word [bp+018h] ; 8b 76 18 ; 0xf65a4
+ and si, strict byte 0fffeh ; 83 e6 fe ; 0xf65a7
+ mov cx, word [bp+018h] ; 8b 4e 18 ; 0xf65aa
+ or cl, 001h ; 80 c9 01 ; 0xf65ad
+ mov ax, dx ; 89 d0 ; 0xf65b0
+ or ah, 086h ; 80 cc 86 ; 0xf65b2
+ jmp bx ; ff e3 ; 0xf65b5
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf65b7 system.c:354
+ xor ah, ah ; 30 e4 ; 0xf65ba
+ cmp ax, 000c0h ; 3d c0 00 ; 0xf65bc
+ je short 065c4h ; 74 03 ; 0xf65bf
+ jmp near 06876h ; e9 b2 02 ; 0xf65c1 system.c:355
+ or byte [bp+018h], 001h ; 80 4e 18 01 ; 0xf65c4 system.c:361
+ jmp near 06820h ; e9 55 02 ; 0xf65c8
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf65cb system.c:365
+ xor ah, ah ; 30 e4 ; 0xf65ce
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf65d0
+ jc short 065e3h ; 72 0e ; 0xf65d3
+ jbe short 065f7h ; 76 20 ; 0xf65d5
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf65d7
+ je short 06624h ; 74 48 ; 0xf65da
+ cmp ax, strict word 00002h ; 3d 02 00 ; 0xf65dc
+ je short 06607h ; 74 26 ; 0xf65df
+ jmp short 06631h ; eb 4e ; 0xf65e1
+ test ax, ax ; 85 c0 ; 0xf65e3
+ jne short 06631h ; 75 4a ; 0xf65e5
+ xor ax, ax ; 31 c0 ; 0xf65e7 system.c:367
+ call 06511h ; e8 25 ff ; 0xf65e9
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf65ec system.c:368
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf65f0 system.c:369
+ jmp near 06659h ; e9 62 00 ; 0xf65f4 system.c:370
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf65f7 system.c:372
+ call 06511h ; e8 14 ff ; 0xf65fa
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf65fd system.c:373
+ mov byte [bp+013h], dh ; 88 76 13 ; 0xf6601 system.c:374
+ jmp near 06659h ; e9 52 00 ; 0xf6604 system.c:375
+ mov dx, 00092h ; ba 92 00 ; 0xf6607 system.c:377
+ in AL, DX ; ec ; 0xf660a
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf660b
+ shr ax, 1 ; d1 e8 ; 0xf660d
+ and ax, strict word 00001h ; 25 01 00 ; 0xf660f
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf6612
+ mov dl, al ; 88 c2 ; 0xf6615
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf6617
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf661a system.c:378
+ mov byte [bp+013h], ah ; 88 66 13 ; 0xf661e system.c:379
+ jmp near 06659h ; e9 35 00 ; 0xf6621 system.c:380
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf6624 system.c:382
+ mov byte [bp+013h], dh ; 88 76 13 ; 0xf6628 system.c:383
+ mov word [bp+00ch], ax ; 89 46 0c ; 0xf662b system.c:384
+ jmp near 06659h ; e9 28 00 ; 0xf662e system.c:385
+ mov bx, 00da0h ; bb a0 0d ; 0xf6631 system.c:387
+ mov cx, ds ; 8c d9 ; 0xf6634
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6636
+ call 018bch ; e8 80 b2 ; 0xf6639
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf663c
+ xor ah, ah ; 30 e4 ; 0xf663f
+ push ax ; 50 ; 0xf6641
+ push 0082eh ; 68 2e 08 ; 0xf6642
+ push strict byte 00004h ; 6a 04 ; 0xf6645
+ call 018ffh ; e8 b5 b2 ; 0xf6647
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf664a
+ jmp near 06817h ; e9 c7 01 ; 0xf664d
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf6650 system.c:414
+ xor al, dl ; 30 d0 ; 0xf6654 system.c:415
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf6656
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf6659 system.c:416
+ pop di ; 5f ; 0xf665c
+ pop si ; 5e ; 0xf665d
+ pop bp ; 5d ; 0xf665e
+ retn ; c3 ; 0xf665f
+ test byte [bp+012h], 0ffh ; f6 46 12 ff ; 0xf6660 system.c:419
+ jne short 066c9h ; 75 63 ; 0xf6664
+ mov bx, 000a0h ; bb a0 00 ; 0xf6666 system.c:38
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf6669
+ mov es, dx ; 8e c2 ; 0xf666c
+ mov dl, byte [es:bx] ; 26 8a 17 ; 0xf666e
+ test dl, 001h ; f6 c2 01 ; 0xf6671 system.c:39
+ jne short 066c1h ; 75 4b ; 0xf6674
+ mov DL, strict byte 001h ; b2 01 ; 0xf6676 system.c:41
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf6678 system.c:43
+ mov bx, 00098h ; bb 98 00 ; 0xf667b system.c:51
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf667e
+ mov word [es:bx], ax ; 26 89 07 ; 0xf6681 system.c:53
+ mov bx, 0009ah ; bb 9a 00 ; 0xf6684 system.c:51
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf6687
+ mov word [es:bx], dx ; 26 89 17 ; 0xf668a system.c:53
+ mov bx, 0009ch ; bb 9c 00 ; 0xf668d system.c:51
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf6690
+ mov word [es:bx], ax ; 26 89 07 ; 0xf6693 system.c:53
+ mov bx, 0009eh ; bb 9e 00 ; 0xf6696 system.c:51
+ mov dx, word [bp+010h] ; 8b 56 10 ; 0xf6699
+ mov word [es:bx], dx ; 26 89 17 ; 0xf669c system.c:53
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf669f system.c:428
+ mov dx, 000a1h ; ba a1 00 ; 0xf66a3 system.c:429
+ in AL, DX ; ec ; 0xf66a6
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf66a7
+ and AL, strict byte 0feh ; 24 fe ; 0xf66a9 system.c:430
+ out DX, AL ; ee ; 0xf66ab
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf66ac system.c:431
+ call 01650h ; e8 9e af ; 0xf66af
+ mov dl, al ; 88 c2 ; 0xf66b2 system.c:432
+ or dl, 040h ; 80 ca 40 ; 0xf66b4
+ xor dh, dh ; 30 f6 ; 0xf66b7
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf66b9
+ call 0166bh ; e8 ac af ; 0xf66bc
+ jmp short 06659h ; eb 98 ; 0xf66bf system.c:433
+ mov word [bp+018h], cx ; 89 4e 18 ; 0xf66c1 system.c:436
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf66c4 system.c:437
+ jmp short 06659h ; eb 90 ; 0xf66c7 system.c:439
+ cmp dx, strict byte 00001h ; 83 fa 01 ; 0xf66c9
+ jne short 066eah ; 75 1c ; 0xf66cc
+ mov bx, 000a0h ; bb a0 00 ; 0xf66ce system.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf66d1
+ mov es, ax ; 8e c0 ; 0xf66d4
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf66d6
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf66d9 system.c:442
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf66dd system.c:443
+ call 01650h ; e8 6d af ; 0xf66e0
+ mov dl, al ; 88 c2 ; 0xf66e3 system.c:444
+ and dl, 0bfh ; 80 e2 bf ; 0xf66e5
+ jmp short 066b9h ; eb cf ; 0xf66e8
+ mov word [bp+018h], cx ; 89 4e 18 ; 0xf66ea system.c:447
+ mov bx, ax ; 89 c3 ; 0xf66ed system.c:449
+ xor bh, ah ; 30 e7 ; 0xf66ef
+ xor al, dl ; 30 d0 ; 0xf66f1
+ mov dx, ax ; 89 c2 ; 0xf66f3
+ lea ax, [bx-001h] ; 8d 47 ff ; 0xf66f5
+ or dx, ax ; 09 c2 ; 0xf66f8
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf66fa
+ jmp near 06659h ; e9 59 ff ; 0xf66fd system.c:452
+ sti ; fb ; 0xf6700 system.c:458
+ mov dx, word [bp+010h] ; 8b 56 10 ; 0xf6701 system.c:459
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf6704
+ call 064ceh ; e8 c4 fd ; 0xf6707
+ jmp near 06659h ; e9 4c ff ; 0xf670a system.c:460
+ mov ax, strict word 00031h ; b8 31 00 ; 0xf670d system.c:465
+ call 01650h ; e8 3d af ; 0xf6710
+ xor ah, ah ; 30 e4 ; 0xf6713
+ mov dx, ax ; 89 c2 ; 0xf6715
+ sal dx, 008h ; c1 e2 08 ; 0xf6717
+ mov ax, strict word 00030h ; b8 30 00 ; 0xf671a
+ call 01650h ; e8 30 af ; 0xf671d
+ xor ah, ah ; 30 e4 ; 0xf6720
+ or dx, ax ; 09 c2 ; 0xf6722
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf6724
+ cmp dx, 03c00h ; 81 fa 00 3c ; 0xf6727 system.c:476
+ jbe short 06732h ; 76 05 ; 0xf672b
+ mov word [bp+012h], 03c00h ; c7 46 12 00 3c ; 0xf672d system.c:477
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf6732 system.c:480
+ jmp near 06659h ; e9 20 ff ; 0xf6736 system.c:485
+ cli ; fa ; 0xf6739 system.c:494
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf673a system.c:496
+ call 06511h ; e8 d1 fd ; 0xf673d
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf6740 system.c:499
+ add bx, strict byte 00038h ; 83 c3 38 ; 0xf6743
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf6746 system.c:51
+ mov word [es:bx], strict word 0ffffh ; 26 c7 07 ff ff ; 0xf6749 system.c:53
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf674e system.c:500
+ add bx, strict byte 0003ah ; 83 c3 3a ; 0xf6751
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf6754 system.c:51
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf6757 system.c:53
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf675c system.c:501
+ add bx, strict byte 0003ch ; 83 c3 3c ; 0xf675f
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf6762 system.c:41
+ mov byte [es:bx], 00fh ; 26 c6 07 0f ; 0xf6765
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf6769 system.c:502
+ add bx, strict byte 0003dh ; 83 c3 3d ; 0xf676c
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf676f system.c:41
+ mov byte [es:bx], 09bh ; 26 c6 07 9b ; 0xf6772
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf6776 system.c:503
+ add bx, strict byte 0003eh ; 83 c3 3e ; 0xf6779
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf677c system.c:51
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf677f system.c:53
+ mov AL, strict byte 011h ; b0 11 ; 0xf6784 system.c:506
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf6786
+ out DX, AL ; ee ; 0xf6789
+ mov dx, 000a0h ; ba a0 00 ; 0xf678a system.c:507
+ out DX, AL ; ee ; 0xf678d
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf678e system.c:508
+ shr ax, 008h ; c1 e8 08 ; 0xf6791
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf6794
+ out DX, AL ; ee ; 0xf6797
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf6798 system.c:509
+ mov dx, 000a1h ; ba a1 00 ; 0xf679b
+ out DX, AL ; ee ; 0xf679e
+ mov AL, strict byte 004h ; b0 04 ; 0xf679f system.c:510
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf67a1
+ out DX, AL ; ee ; 0xf67a4
+ mov AL, strict byte 002h ; b0 02 ; 0xf67a5 system.c:511
+ mov dx, 000a1h ; ba a1 00 ; 0xf67a7
+ out DX, AL ; ee ; 0xf67aa
+ mov AL, strict byte 001h ; b0 01 ; 0xf67ab system.c:512
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf67ad
+ out DX, AL ; ee ; 0xf67b0
+ mov dx, 000a1h ; ba a1 00 ; 0xf67b1 system.c:513
+ out DX, AL ; ee ; 0xf67b4
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf67b5 system.c:515
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf67b7
+ out DX, AL ; ee ; 0xf67ba
+ mov dx, 000a1h ; ba a1 00 ; 0xf67bb system.c:516
+ out DX, AL ; ee ; 0xf67be
+ mov si, word [bp+006h] ; 8b 76 06 ; 0xf67bf system.c:518
+ lgdt [es:si+008h] ; 26 0f 01 54 08 ; 0xf67c2
+ lidt [es:si+010h] ; 26 0f 01 5c 10 ; 0xf67c7
+ push strict byte 00038h ; 6a 38 ; 0xf67cc
+ call 067d1h ; e8 00 00 ; 0xf67ce
+ pop ax ; 58 ; 0xf67d1
+ add ax, strict byte 0000eh ; 83 c0 0e ; 0xf67d2
+ push ax ; 50 ; 0xf67d5
+ smsw ax ; 0f 01 e0 ; 0xf67d6
+ or AL, strict byte 001h ; 0c 01 ; 0xf67d9
+ lmsw ax ; 0f 01 f0 ; 0xf67db
+ retf ; cb ; 0xf67de
+ mov ax, strict word 00018h ; b8 18 00 ; 0xf67df
+ mov ds, ax ; 8e d8 ; 0xf67e2
+ add AL, strict byte 008h ; 04 08 ; 0xf67e4
+ mov es, ax ; 8e c0 ; 0xf67e6
+ add AL, strict byte 008h ; 04 08 ; 0xf67e8
+ mov ss, ax ; 8e d0 ; 0xf67ea
+ lea ax, [bp+004h] ; 8d 46 04 ; 0xf67ec system.c:519
+ db 08bh, 0e0h
+ ; mov sp, ax ; 8b e0 ; 0xf67ef
+ popaw ; 61 ; 0xf67f1
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf67f2
+ pop cx ; 59 ; 0xf67f5
+ pop ax ; 58 ; 0xf67f6
+ pop ax ; 58 ; 0xf67f7
+ mov ax, strict word 00030h ; b8 30 00 ; 0xf67f8
+ push ax ; 50 ; 0xf67fb
+ push cx ; 51 ; 0xf67fc
+ retf ; cb ; 0xf67fd
+ jmp near 06659h ; e9 58 fe ; 0xf67fe system.c:525
+ mov bx, 00da0h ; bb a0 0d ; 0xf6801 system.c:532
+ mov cx, ds ; 8c d9 ; 0xf6804
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6806
+ call 018bch ; e8 b0 b0 ; 0xf6809
+ push 0086eh ; 68 6e 08 ; 0xf680c
+ push strict byte 00004h ; 6a 04 ; 0xf680f
+ call 018ffh ; e8 eb b0 ; 0xf6811
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf6814
+ or byte [bp+018h], 001h ; 80 4e 18 01 ; 0xf6817
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf681b
+ xor ah, ah ; 30 e4 ; 0xf681e
+ or ah, 086h ; 80 cc 86 ; 0xf6820
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf6823
+ jmp near 06659h ; e9 30 fe ; 0xf6826
+ mov word [bp+018h], si ; 89 76 18 ; 0xf6829 system.c:538
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf682c system.c:539
+ mov word [bp+00ch], 0e6f5h ; c7 46 0c f5 e6 ; 0xf682f system.c:540
+ mov word [bp+014h], 0f000h ; c7 46 14 00 f0 ; 0xf6834 system.c:541
+ jmp near 06659h ; e9 1d fe ; 0xf6839 system.c:542
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf683c system.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf683f
+ mov es, ax ; 8e c0 ; 0xf6842
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf6844
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf6847 system.c:49
+ mov word [bp+018h], si ; 89 76 18 ; 0xf684a system.c:546
+ jmp near 06659h ; e9 09 fe ; 0xf684d system.c:547
+ push 0089dh ; 68 9d 08 ; 0xf6850 system.c:550
+ push strict byte 00008h ; 6a 08 ; 0xf6853
+ jmp short 06811h ; eb ba ; 0xf6855
+ test byte [bp+012h], 0ffh ; f6 46 12 ff ; 0xf6857 system.c:562
+ jne short 06876h ; 75 19 ; 0xf685b
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf685d system.c:564
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf6860 system.c:565
+ xor ah, ah ; 30 e4 ; 0xf6863
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf6865
+ jc short 0686fh ; 72 05 ; 0xf6868
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf686a
+ jbe short 0684ah ; 76 db ; 0xf686d
+ or byte [bp+018h], 001h ; 80 4e 18 01 ; 0xf686f system.c:568
+ jmp near 06659h ; e9 e3 fd ; 0xf6873 system.c:569
+ mov bx, 00da0h ; bb a0 0d ; 0xf6876 system.c:573
+ mov cx, ds ; 8c d9 ; 0xf6879
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf687b
+ call 018bch ; e8 3b b0 ; 0xf687e
+ push word [bp+00ch] ; ff 76 0c ; 0xf6881
+ push word [bp+012h] ; ff 76 12 ; 0xf6884
+ push 008b4h ; 68 b4 08 ; 0xf6887
+ push strict byte 00004h ; 6a 04 ; 0xf688a
+ call 018ffh ; e8 70 b0 ; 0xf688c
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf688f
+ jmp short 06817h ; eb 83 ; 0xf6892
+ ; disGetNextSymbol 0xf6894 LB 0x3634 -> off=0x0 cb=0000000000000167 uValue=00000000000f5294 'int15_blkmove'
+int15_blkmove: ; 0xf6894 LB 0x167
+ push bp ; 55 ; 0xf6894 system.c:858
+ mov bp, sp ; 89 e5 ; 0xf6895
+ push si ; 56 ; 0xf6897
+ push di ; 57 ; 0xf6898
+ cli ; fa ; 0xf6899 system.c:868
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf689a system.c:870
+ call 06511h ; e8 71 fc ; 0xf689d
+ mov cx, word [bp+006h] ; 8b 4e 06 ; 0xf68a0 system.c:893
+ sal cx, 004h ; c1 e1 04 ; 0xf68a3
+ mov ax, word [bp+00ah] ; 8b 46 0a ; 0xf68a6
+ add ax, cx ; 01 c8 ; 0xf68a9
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf68ab system.c:894
+ shr bx, 00ch ; c1 eb 0c ; 0xf68ae
+ mov dl, bl ; 88 da ; 0xf68b1
+ cmp ax, cx ; 39 c8 ; 0xf68b3 system.c:895
+ jnc short 068b9h ; 73 02 ; 0xf68b5
+ db 0feh, 0c2h
+ ; inc dl ; fe c2 ; 0xf68b7 system.c:896
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf68b9 system.c:897
+ add bx, strict byte 00008h ; 83 c3 08 ; 0xf68bc
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf68bf system.c:51
+ mov word [es:bx], strict word 0002fh ; 26 c7 07 2f 00 ; 0xf68c2
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf68c7 system.c:898
+ add bx, strict byte 0000ah ; 83 c3 0a ; 0xf68ca
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf68cd system.c:51
+ mov word [es:bx], ax ; 26 89 07 ; 0xf68d0
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf68d3 system.c:899
+ add bx, strict byte 0000ch ; 83 c3 0c ; 0xf68d6
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf68d9 system.c:41
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf68dc system.c:43
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf68df system.c:900
+ add bx, strict byte 0000dh ; 83 c3 0d ; 0xf68e2
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf68e5 system.c:41
+ mov byte [es:bx], 093h ; 26 c6 07 93 ; 0xf68e8 system.c:43
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf68ec system.c:901
+ add bx, strict byte 0000eh ; 83 c3 0e ; 0xf68ef
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf68f2 system.c:51
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf68f5
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf68fa system.c:904
+ add bx, strict byte 00020h ; 83 c3 20 ; 0xf68fd
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf6900 system.c:51
+ mov word [es:bx], strict word 0ffffh ; 26 c7 07 ff ff ; 0xf6903
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6908 system.c:905
+ add bx, strict byte 00022h ; 83 c3 22 ; 0xf690b
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf690e system.c:51
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf6911
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6916 system.c:906
+ add bx, strict byte 00024h ; 83 c3 24 ; 0xf6919
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf691c system.c:41
+ mov byte [es:bx], 00fh ; 26 c6 07 0f ; 0xf691f
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6923 system.c:907
+ add bx, strict byte 00025h ; 83 c3 25 ; 0xf6926
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf6929 system.c:41
+ mov byte [es:bx], 09bh ; 26 c6 07 9b ; 0xf692c
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6930 system.c:908
+ add bx, strict byte 00026h ; 83 c3 26 ; 0xf6933
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf6936 system.c:51
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf6939
+ mov ax, ss ; 8c d0 ; 0xf693e system.c:911
+ mov dx, ax ; 89 c2 ; 0xf6940
+ sal ax, 004h ; c1 e0 04 ; 0xf6942 system.c:912
+ shr dx, 00ch ; c1 ea 0c ; 0xf6945
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6948 system.c:914
+ add bx, strict byte 00028h ; 83 c3 28 ; 0xf694b
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf694e system.c:51
+ mov word [es:bx], strict word 0ffffh ; 26 c7 07 ff ff ; 0xf6951
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6956 system.c:915
+ add bx, strict byte 0002ah ; 83 c3 2a ; 0xf6959
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf695c system.c:51
+ mov word [es:bx], ax ; 26 89 07 ; 0xf695f
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6962 system.c:916
+ add bx, strict byte 0002ch ; 83 c3 2c ; 0xf6965
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf6968 system.c:41
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf696b
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf696e system.c:917
+ add bx, strict byte 0002dh ; 83 c3 2d ; 0xf6971
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf6974 system.c:41
+ mov byte [es:bx], 093h ; 26 c6 07 93 ; 0xf6977 system.c:43
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf697b system.c:918
+ add bx, strict byte 0002eh ; 83 c3 2e ; 0xf697e
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf6981 system.c:51
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf6984
+ lea bx, [bp+004h] ; 8d 5e 04 ; 0xf6989 system.c:926
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf698c
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf698f
+ mov cx, word [bp+014h] ; 8b 4e 14 ; 0xf6992
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf6995
+ mov ds, ax ; 8e d8 ; 0xf6997
+ mov word [00467h], bx ; 89 1e 67 04 ; 0xf6999
+ mov [00469h], ss ; 8c 16 69 04 ; 0xf699d
+ lgdt [es:si+008h] ; 26 0f 01 54 08 ; 0xf69a1 system.c:928
+ lidt [cs:0efe1h] ; 2e 0f 01 1e e1 ef ; 0xf69a6
+ push strict byte 00020h ; 6a 20 ; 0xf69ac
+ call 069b1h ; e8 00 00 ; 0xf69ae
+ pop ax ; 58 ; 0xf69b1
+ add ax, strict byte 0000eh ; 83 c0 0e ; 0xf69b2
+ push ax ; 50 ; 0xf69b5
+ smsw ax ; 0f 01 e0 ; 0xf69b6
+ or AL, strict byte 001h ; 0c 01 ; 0xf69b9
+ lmsw ax ; 0f 01 f0 ; 0xf69bb
+ retf ; cb ; 0xf69be
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf69bf
+ mov ds, ax ; 8e d8 ; 0xf69c2
+ add AL, strict byte 008h ; 04 08 ; 0xf69c4
+ mov es, ax ; 8e c0 ; 0xf69c6
+ add AL, strict byte 010h ; 04 10 ; 0xf69c8
+ mov ss, ax ; 8e d0 ; 0xf69ca
+ db 033h, 0f6h
+ ; xor si, si ; 33 f6 ; 0xf69cc system.c:929
+ db 033h, 0ffh
+ ; xor di, di ; 33 ff ; 0xf69ce
+ cld ; fc ; 0xf69d0
+ rep movsw ; f3 a5 ; 0xf69d1
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf69d3 system.c:930
+ out strict byte 080h, AL ; e6 80 ; 0xf69d5
+ mov AL, strict byte 00fh ; b0 0f ; 0xf69d7
+ out strict byte 070h, AL ; e6 70 ; 0xf69d9
+ mov AL, strict byte 009h ; b0 09 ; 0xf69db
+ out strict byte 071h, AL ; e6 71 ; 0xf69dd
+ lidt [cs:0efe1h] ; 2e 0f 01 1e e1 ef ; 0xf69df
+ int3 ; cc ; 0xf69e5
+ xor ax, ax ; 31 c0 ; 0xf69e6 system.c:931
+ call 06511h ; e8 26 fb ; 0xf69e8
+ sti ; fb ; 0xf69eb system.c:936
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf69ec system.c:938
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf69f0 system.c:939
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf69f4 system.c:940
+ pop di ; 5f ; 0xf69f7
+ pop si ; 5e ; 0xf69f8
+ pop bp ; 5d ; 0xf69f9
+ retn ; c3 ; 0xf69fa
+ ; disGetNextSymbol 0xf69fb LB 0x34cd -> off=0x0 cb=000000000000019b uValue=00000000000f53fb 'inv_op_handler'
+inv_op_handler: ; 0xf69fb LB 0x19b
+ push bp ; 55 ; 0xf69fb invop.c:237
+ mov bp, sp ; 89 e5 ; 0xf69fc
+ push si ; 56 ; 0xf69fe
+ push di ; 57 ; 0xf69ff
+ push ax ; 50 ; 0xf6a00
+ push ax ; 50 ; 0xf6a01
+ les bx, [bp+018h] ; c4 5e 18 ; 0xf6a02 invop.c:239
+ cmp byte [es:bx], 0f0h ; 26 80 3f f0 ; 0xf6a05 invop.c:241
+ jne short 06a11h ; 75 06 ; 0xf6a09
+ inc word [bp+018h] ; ff 46 18 ; 0xf6a0b invop.c:243
+ jmp near 06b8fh ; e9 7e 01 ; 0xf6a0e invop.c:244
+ cmp word [es:bx], 0050fh ; 26 81 3f 0f 05 ; 0xf6a11
+ je short 06a1bh ; 74 03 ; 0xf6a16
+ jmp near 06b8bh ; e9 70 01 ; 0xf6a18
+ mov si, 00800h ; be 00 08 ; 0xf6a1b invop.c:246
+ xor ax, ax ; 31 c0 ; 0xf6a1e
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf6a20
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf6a23 invop.c:249
+ mov es, ax ; 8e c0 ; 0xf6a26 invop.c:257
+ mov bx, word [es:si+02ch] ; 26 8b 5c 2c ; 0xf6a28
+ sub bx, strict byte 00006h ; 83 eb 06 ; 0xf6a2c
+ mov dx, word [es:si+020h] ; 26 8b 54 20 ; 0xf6a2f
+ mov ax, word [es:si+01ah] ; 26 8b 44 1a ; 0xf6a33 invop.c:258
+ mov es, dx ; 8e c2 ; 0xf6a37
+ mov word [es:bx], ax ; 26 89 07 ; 0xf6a39
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6a3c invop.c:259
+ mov ax, word [es:si+022h] ; 26 8b 44 22 ; 0xf6a3f
+ mov es, dx ; 8e c2 ; 0xf6a43
+ mov word [es:bx+002h], ax ; 26 89 47 02 ; 0xf6a45
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6a49 invop.c:260
+ mov ax, word [es:si+018h] ; 26 8b 44 18 ; 0xf6a4c
+ mov es, dx ; 8e c2 ; 0xf6a50
+ mov word [es:bx+004h], ax ; 26 89 47 04 ; 0xf6a52
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6a56 invop.c:263
+ mov bl, byte [es:si+038h] ; 26 8a 5c 38 ; 0xf6a59
+ xor bh, bh ; 30 ff ; 0xf6a5d
+ mov di, word [es:si+036h] ; 26 8b 7c 36 ; 0xf6a5f
+ mov ax, word [es:si+024h] ; 26 8b 44 24 ; 0xf6a63 invop.c:264
+ xor dx, dx ; 31 d2 ; 0xf6a67
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf6a69
+ sal ax, 1 ; d1 e0 ; 0xf6a6c
+ rcl dx, 1 ; d1 d2 ; 0xf6a6e
+ loop 06a6ch ; e2 fa ; 0xf6a70
+ cmp bx, dx ; 39 d3 ; 0xf6a72
+ jne short 06a7ah ; 75 04 ; 0xf6a74
+ cmp di, ax ; 39 c7 ; 0xf6a76
+ je short 06a7fh ; 74 05 ; 0xf6a78
+ mov word [bp-008h], strict word 00001h ; c7 46 f8 01 00 ; 0xf6a7a invop.c:265
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6a7f invop.c:266
+ mov bl, byte [es:si+04ah] ; 26 8a 5c 4a ; 0xf6a82
+ xor bh, bh ; 30 ff ; 0xf6a86
+ mov di, word [es:si+048h] ; 26 8b 7c 48 ; 0xf6a88
+ mov ax, word [es:si+01eh] ; 26 8b 44 1e ; 0xf6a8c invop.c:267
+ xor dx, dx ; 31 d2 ; 0xf6a90
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf6a92
+ sal ax, 1 ; d1 e0 ; 0xf6a95
+ rcl dx, 1 ; d1 d2 ; 0xf6a97
+ loop 06a95h ; e2 fa ; 0xf6a99
+ cmp bx, dx ; 39 d3 ; 0xf6a9b
+ jne short 06aa3h ; 75 04 ; 0xf6a9d
+ cmp di, ax ; 39 c7 ; 0xf6a9f
+ je short 06aa7h ; 74 04 ; 0xf6aa1
+ or byte [bp-008h], 002h ; 80 4e f8 02 ; 0xf6aa3 invop.c:268
+ push strict byte 00000h ; 6a 00 ; 0xf6aa7 invop.c:271
+ push 00800h ; 68 00 08 ; 0xf6aa9
+ push strict byte 0001fh ; 6a 1f ; 0xf6aac
+ db 08bh, 0dch
+ ; mov bx, sp ; 8b dc ; 0xf6aae
+ lgdt [ss:bx] ; 36 0f 01 17 ; 0xf6ab0
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf6ab4
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6ab7 invop.c:274
+ mov ax, word [es:si+03ah] ; 26 8b 44 3a ; 0xf6aba
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf6abe
+ mov ax, word [es:si+036h] ; 26 8b 44 36 ; 0xf6ac2 invop.c:275
+ mov word [es:si+00ah], ax ; 26 89 44 0a ; 0xf6ac6
+ mov al, byte [es:si+039h] ; 26 8a 44 39 ; 0xf6aca invop.c:276
+ xor ah, ah ; 30 e4 ; 0xf6ace
+ mov dx, ax ; 89 c2 ; 0xf6ad0
+ sal dx, 008h ; c1 e2 08 ; 0xf6ad2
+ mov al, byte [es:si+038h] ; 26 8a 44 38 ; 0xf6ad5
+ or dx, ax ; 09 c2 ; 0xf6ad9
+ mov word [es:si+00ch], dx ; 26 89 54 0c ; 0xf6adb
+ mov word [es:si+00eh], strict word 00000h ; 26 c7 44 0e 00 00 ; 0xf6adf invop.c:277
+ mov ax, word [es:si+04ch] ; 26 8b 44 4c ; 0xf6ae5 invop.c:280
+ mov word [es:si], ax ; 26 89 04 ; 0xf6ae9
+ mov ax, word [es:si+048h] ; 26 8b 44 48 ; 0xf6aec invop.c:281
+ mov word [es:si+002h], ax ; 26 89 44 02 ; 0xf6af0
+ mov al, byte [es:si+04bh] ; 26 8a 44 4b ; 0xf6af4 invop.c:282
+ xor ah, ah ; 30 e4 ; 0xf6af8
+ mov dx, ax ; 89 c2 ; 0xf6afa
+ sal dx, 008h ; c1 e2 08 ; 0xf6afc
+ mov al, byte [es:si+04ah] ; 26 8a 44 4a ; 0xf6aff
+ or dx, ax ; 09 c2 ; 0xf6b03
+ mov word [es:si+004h], dx ; 26 89 54 04 ; 0xf6b05
+ mov al, byte [es:si+05ch] ; 26 8a 44 5c ; 0xf6b09 invop.c:285
+ mov dx, word [es:si+05ah] ; 26 8b 54 5a ; 0xf6b0d
+ push ax ; 50 ; 0xf6b11 invop.c:286
+ push dx ; 52 ; 0xf6b12
+ push word [es:si+05eh] ; 26 ff 74 5e ; 0xf6b13
+ db 08bh, 0dch
+ ; mov bx, sp ; 8b dc ; 0xf6b17
+ lidt [ss:bx] ; 36 0f 01 1f ; 0xf6b19
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf6b1d
+ mov cx, word [bp-008h] ; 8b 4e f8 ; 0xf6b20 invop.c:289
+ mov ax, 00080h ; b8 80 00 ; 0xf6b23
+ mov ss, ax ; 8e d0 ; 0xf6b26
+ mov ax, word [ss:0001eh] ; 36 a1 1e 00 ; 0xf6b28
+ mov ds, ax ; 8e d8 ; 0xf6b2c
+ mov ax, word [ss:00024h] ; 36 a1 24 00 ; 0xf6b2e
+ mov es, ax ; 8e c0 ; 0xf6b32
+ smsw ax ; 0f 01 e0 ; 0xf6b34 invop.c:290
+ inc ax ; 40 ; 0xf6b37
+ lmsw ax ; 0f 01 f0 ; 0xf6b38
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf6b3b
+ test cx, strict word 00001h ; f7 c1 01 00 ; 0xf6b3e
+ je near 06b48h ; 0f 84 02 00 ; 0xf6b42
+ mov es, ax ; 8e c0 ; 0xf6b46
+ test cx, strict word 00002h ; f7 c1 02 00 ; 0xf6b48
+ je near 06b70h ; 0f 84 20 00 ; 0xf6b4c
+ mov bx, word [word ss:00000h] ; 36 8b 1e 00 00 ; 0xf6b50
+ mov word [word ss:00008h], bx ; 36 89 1e 08 00 ; 0xf6b55
+ mov bx, word [word ss:00002h] ; 36 8b 1e 02 00 ; 0xf6b5a
+ mov word [word ss:0000ah], bx ; 36 89 1e 0a 00 ; 0xf6b5f
+ mov bx, word [word ss:00004h] ; 36 8b 1e 04 00 ; 0xf6b64
+ mov word [word ss:0000ch], bx ; 36 89 1e 0c 00 ; 0xf6b69
+ mov ds, ax ; 8e d8 ; 0xf6b6e
+ mov eax, cr0 ; 0f 20 c0 ; 0xf6b70
+ dec ax ; 48 ; 0xf6b73
+ mov cr0, eax ; 0f 22 c0 ; 0xf6b74
+ mov sp, strict word 00026h ; bc 26 00 ; 0xf6b77 invop.c:291
+ popaw ; 61 ; 0xf6b7a
+ mov sp, word [word ss:0002ch] ; 36 8b 26 2c 00 ; 0xf6b7b
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf6b80
+ mov ss, [word ss:00020h] ; 36 8e 16 20 00 ; 0xf6b83
+ iret ; cf ; 0xf6b88
+ jmp short 06b8fh ; eb 04 ; 0xf6b89 invop.c:343
+ sti ; fb ; 0xf6b8b invop.c:347
+ hlt ; f4 ; 0xf6b8c invop.c:348
+ jmp short 06b8ch ; eb fd ; 0xf6b8d
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf6b8f invop.c:350
+ pop di ; 5f ; 0xf6b92
+ pop si ; 5e ; 0xf6b93
+ pop bp ; 5d ; 0xf6b94
+ retn ; c3 ; 0xf6b95
+ ; disGetNextSymbol 0xf6b96 LB 0x3332 -> off=0x0 cb=0000000000000028 uValue=00000000000f5596 'init_rtc'
+init_rtc: ; 0xf6b96 LB 0x28
+ push bp ; 55 ; 0xf6b96 timepci.c:74
+ mov bp, sp ; 89 e5 ; 0xf6b97
+ push dx ; 52 ; 0xf6b99
+ mov dx, strict word 00026h ; ba 26 00 ; 0xf6b9a timepci.c:76
+ mov ax, strict word 0000ah ; b8 0a 00 ; 0xf6b9d
+ call 0166bh ; e8 c8 aa ; 0xf6ba0
+ mov dx, strict word 00002h ; ba 02 00 ; 0xf6ba3 timepci.c:77
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6ba6
+ call 0166bh ; e8 bf aa ; 0xf6ba9
+ mov ax, strict word 0000ch ; b8 0c 00 ; 0xf6bac timepci.c:78
+ call 01650h ; e8 9e aa ; 0xf6baf
+ mov ax, strict word 0000dh ; b8 0d 00 ; 0xf6bb2 timepci.c:79
+ call 01650h ; e8 98 aa ; 0xf6bb5
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf6bb8 timepci.c:80
+ pop dx ; 5a ; 0xf6bbb
+ pop bp ; 5d ; 0xf6bbc
+ retn ; c3 ; 0xf6bbd
+ ; disGetNextSymbol 0xf6bbe LB 0x330a -> off=0x0 cb=0000000000000021 uValue=00000000000f55be 'rtc_updating'
+rtc_updating: ; 0xf6bbe LB 0x21
+ push bp ; 55 ; 0xf6bbe timepci.c:82
+ mov bp, sp ; 89 e5 ; 0xf6bbf
+ push dx ; 52 ; 0xf6bc1
+ mov dx, 061a8h ; ba a8 61 ; 0xf6bc2 timepci.c:95
+ dec dx ; 4a ; 0xf6bc5 timepci.c:96
+ je short 06bd6h ; 74 0e ; 0xf6bc6
+ mov ax, strict word 0000ah ; b8 0a 00 ; 0xf6bc8 timepci.c:97
+ call 01650h ; e8 82 aa ; 0xf6bcb
+ test AL, strict byte 080h ; a8 80 ; 0xf6bce
+ jne short 06bc5h ; 75 f3 ; 0xf6bd0
+ xor ax, ax ; 31 c0 ; 0xf6bd2 timepci.c:98
+ jmp short 06bd9h ; eb 03 ; 0xf6bd4
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf6bd6 timepci.c:100
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf6bd9 timepci.c:101
+ pop dx ; 5a ; 0xf6bdc
+ pop bp ; 5d ; 0xf6bdd
+ retn ; c3 ; 0xf6bde
+ ; disGetNextSymbol 0xf6bdf LB 0x32e9 -> off=0x0 cb=0000000000000098 uValue=00000000000f55df 'int70_function'
+int70_function: ; 0xf6bdf LB 0x98
+ push bp ; 55 ; 0xf6bdf timepci.c:110
+ mov bp, sp ; 89 e5 ; 0xf6be0
+ push si ; 56 ; 0xf6be2
+ push ax ; 50 ; 0xf6be3
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6be4 timepci.c:116
+ call 01650h ; e8 66 aa ; 0xf6be7
+ mov bl, al ; 88 c3 ; 0xf6bea
+ mov byte [bp-004h], al ; 88 46 fc ; 0xf6bec
+ mov ax, strict word 0000ch ; b8 0c 00 ; 0xf6bef timepci.c:117
+ call 01650h ; e8 5b aa ; 0xf6bf2
+ mov dl, al ; 88 c2 ; 0xf6bf5
+ test bl, 060h ; f6 c3 60 ; 0xf6bf7 timepci.c:119
+ je short 06c57h ; 74 5b ; 0xf6bfa
+ test AL, strict byte 020h ; a8 20 ; 0xf6bfc timepci.c:120
+ je short 06c04h ; 74 04 ; 0xf6bfe
+ sti ; fb ; 0xf6c00 timepci.c:122
+ int 04ah ; cd 4a ; 0xf6c01 timepci.c:123
+ cli ; fa ; 0xf6c03 timepci.c:124
+ test dl, 040h ; f6 c2 40 ; 0xf6c04 timepci.c:126
+ je short 06c6eh ; 74 65 ; 0xf6c07
+ mov bx, 000a0h ; bb a0 00 ; 0xf6c09 timepci.c:38
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf6c0c
+ mov es, dx ; 8e c2 ; 0xf6c0f
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf6c11
+ test al, al ; 84 c0 ; 0xf6c14 timepci.c:39
+ je short 06c6eh ; 74 56 ; 0xf6c16
+ mov bx, 0009ch ; bb 9c 00 ; 0xf6c18 timepci.c:58
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf6c1b
+ mov bx, word [es:bx+002h] ; 26 8b 5f 02 ; 0xf6c1e
+ test bx, bx ; 85 db ; 0xf6c22 timepci.c:134
+ jne short 06c59h ; 75 33 ; 0xf6c24
+ cmp dx, 003d1h ; 81 fa d1 03 ; 0xf6c26
+ jnc short 06c59h ; 73 2d ; 0xf6c2a
+ mov bx, 00098h ; bb 98 00 ; 0xf6c2c timepci.c:48
+ mov cx, word [es:bx] ; 26 8b 0f ; 0xf6c2f
+ mov bx, 0009ah ; bb 9a 00 ; 0xf6c32 timepci.c:48
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf6c35
+ mov si, 000a0h ; be a0 00 ; 0xf6c38 timepci.c:43
+ mov byte [es:si], 000h ; 26 c6 04 00 ; 0xf6c3b
+ mov dl, byte [bp-004h] ; 8a 56 fc ; 0xf6c3f timepci.c:141
+ and dl, 037h ; 80 e2 37 ; 0xf6c42
+ xor dh, dh ; 30 f6 ; 0xf6c45
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6c47
+ call 0166bh ; e8 1e aa ; 0xf6c4a
+ mov es, cx ; 8e c1 ; 0xf6c4d timepci.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf6c4f
+ or AL, strict byte 080h ; 0c 80 ; 0xf6c52 timepci.c:39
+ mov byte [es:bx], al ; 26 88 07 ; 0xf6c54 timepci.c:43
+ jmp short 06c6eh ; eb 15 ; 0xf6c57 timepci.c:143
+ mov cx, dx ; 89 d1 ; 0xf6c59 timepci.c:145
+ add cx, 0fc2fh ; 81 c1 2f fc ; 0xf6c5b
+ mov dx, bx ; 89 da ; 0xf6c5f
+ adc dx, strict byte 0ffffh ; 83 d2 ff ; 0xf6c61
+ mov bx, 0009ch ; bb 9c 00 ; 0xf6c64 timepci.c:63
+ mov word [es:bx], cx ; 26 89 0f ; 0xf6c67
+ mov word [es:bx+002h], dx ; 26 89 57 02 ; 0xf6c6a
+ call 0e030h ; e8 bf 73 ; 0xf6c6e timepci.c:151
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf6c71 timepci.c:152
+ pop si ; 5e ; 0xf6c74
+ pop bp ; 5d ; 0xf6c75
+ retn ; c3 ; 0xf6c76
+ ; disGetNextSymbol 0xf6c77 LB 0x3251 -> off=0x10 cb=00000000000001d9 uValue=00000000000f5687 'int1a_function'
+ db 09dh, 06ch, 0c4h, 06ch, 0e9h, 06ch, 025h, 06dh, 077h, 06dh, 0aeh, 06dh, 0f5h, 06dh, 050h, 06eh
+int1a_function: ; 0xf6c87 LB 0x1d9
+ push bp ; 55 ; 0xf6c87 timepci.c:157
+ mov bp, sp ; 89 e5 ; 0xf6c88
+ sti ; fb ; 0xf6c8a timepci.c:163
+ mov al, byte [bp+013h] ; 8a 46 13 ; 0xf6c8b timepci.c:165
+ cmp AL, strict byte 007h ; 3c 07 ; 0xf6c8e
+ jnbe short 06cf0h ; 77 5e ; 0xf6c90
+ mov bl, al ; 88 c3 ; 0xf6c92
+ xor bh, bh ; 30 ff ; 0xf6c94
+ add bx, bx ; 01 db ; 0xf6c96
+ jmp word [cs:bx+06c77h] ; 2e ff a7 77 6c ; 0xf6c98
+ cli ; fa ; 0xf6c9d timepci.c:167
+ mov bx, 0046eh ; bb 6e 04 ; 0xf6c9e timepci.c:168
+ xor ax, ax ; 31 c0 ; 0xf6ca1
+ mov es, ax ; 8e c0 ; 0xf6ca3
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf6ca5
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf6ca8
+ mov bx, 0046ch ; bb 6c 04 ; 0xf6cab timepci.c:169
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf6cae
+ mov word [bp+00eh], ax ; 89 46 0e ; 0xf6cb1
+ mov bx, 00470h ; bb 70 04 ; 0xf6cb4 timepci.c:170
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf6cb7
+ mov byte [bp+012h], al ; 88 46 12 ; 0xf6cba
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf6cbd timepci.c:171
+ sti ; fb ; 0xf6cc1 timepci.c:172
+ jmp short 06cf0h ; eb 2c ; 0xf6cc2 timepci.c:175
+ cli ; fa ; 0xf6cc4 timepci.c:178
+ mov bx, 0046eh ; bb 6e 04 ; 0xf6cc5 timepci.c:179
+ xor ax, ax ; 31 c0 ; 0xf6cc8
+ mov es, ax ; 8e c0 ; 0xf6cca
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf6ccc
+ mov word [es:bx], ax ; 26 89 07 ; 0xf6ccf
+ mov bx, 0046ch ; bb 6c 04 ; 0xf6cd2 timepci.c:180
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf6cd5
+ mov word [es:bx], ax ; 26 89 07 ; 0xf6cd8
+ mov bx, 00470h ; bb 70 04 ; 0xf6cdb timepci.c:181
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf6cde
+ sti ; fb ; 0xf6ce2 timepci.c:182
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf6ce3 timepci.c:183
+ jmp short 06cf0h ; eb 07 ; 0xf6ce7 timepci.c:185
+ call 06bbeh ; e8 d2 fe ; 0xf6ce9 timepci.c:188
+ test ax, ax ; 85 c0 ; 0xf6cec
+ je short 06cf3h ; 74 03 ; 0xf6cee
+ jmp near 06d21h ; e9 2e 00 ; 0xf6cf0 timepci.c:190
+ xor ax, ax ; 31 c0 ; 0xf6cf3 timepci.c:193
+ call 01650h ; e8 58 a9 ; 0xf6cf5
+ mov byte [bp+00fh], al ; 88 46 0f ; 0xf6cf8
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf6cfb timepci.c:194
+ call 01650h ; e8 4f a9 ; 0xf6cfe
+ mov byte [bp+010h], al ; 88 46 10 ; 0xf6d01
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6d04 timepci.c:195
+ call 01650h ; e8 46 a9 ; 0xf6d07
+ mov dl, al ; 88 c2 ; 0xf6d0a
+ mov byte [bp+011h], al ; 88 46 11 ; 0xf6d0c
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6d0f timepci.c:196
+ call 01650h ; e8 3b a9 ; 0xf6d12
+ and AL, strict byte 001h ; 24 01 ; 0xf6d15
+ mov byte [bp+00eh], al ; 88 46 0e ; 0xf6d17
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf6d1a timepci.c:197
+ mov byte [bp+012h], dl ; 88 56 12 ; 0xf6d1e timepci.c:198
+ mov sp, bp ; 89 ec ; 0xf6d21 timepci.c:200
+ pop bp ; 5d ; 0xf6d23
+ retn ; c3 ; 0xf6d24
+ call 06bbeh ; e8 96 fe ; 0xf6d25 timepci.c:213
+ test ax, ax ; 85 c0 ; 0xf6d28
+ je short 06d2fh ; 74 03 ; 0xf6d2a
+ call 06b96h ; e8 67 fe ; 0xf6d2c timepci.c:214
+ mov dl, byte [bp+00fh] ; 8a 56 0f ; 0xf6d2f timepci.c:217
+ xor dh, dh ; 30 f6 ; 0xf6d32
+ xor ax, ax ; 31 c0 ; 0xf6d34
+ call 0166bh ; e8 32 a9 ; 0xf6d36
+ mov dl, byte [bp+010h] ; 8a 56 10 ; 0xf6d39 timepci.c:218
+ xor dh, dh ; 30 f6 ; 0xf6d3c
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf6d3e
+ call 0166bh ; e8 27 a9 ; 0xf6d41
+ mov dl, byte [bp+011h] ; 8a 56 11 ; 0xf6d44 timepci.c:219
+ xor dh, dh ; 30 f6 ; 0xf6d47
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6d49
+ call 0166bh ; e8 1c a9 ; 0xf6d4c
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6d4f timepci.c:221
+ call 01650h ; e8 fb a8 ; 0xf6d52
+ mov bl, al ; 88 c3 ; 0xf6d55
+ and bl, 060h ; 80 e3 60 ; 0xf6d57
+ or bl, 002h ; 80 cb 02 ; 0xf6d5a
+ mov al, byte [bp+00eh] ; 8a 46 0e ; 0xf6d5d
+ and AL, strict byte 001h ; 24 01 ; 0xf6d60
+ or bl, al ; 08 c3 ; 0xf6d62
+ mov dl, bl ; 88 da ; 0xf6d64 timepci.c:223
+ xor dh, dh ; 30 f6 ; 0xf6d66
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6d68
+ call 0166bh ; e8 fd a8 ; 0xf6d6b
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf6d6e timepci.c:224
+ mov byte [bp+012h], bl ; 88 5e 12 ; 0xf6d72 timepci.c:225
+ jmp short 06d21h ; eb aa ; 0xf6d75 timepci.c:227
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf6d77 timepci.c:230
+ call 06bbeh ; e8 40 fe ; 0xf6d7b timepci.c:231
+ test ax, ax ; 85 c0 ; 0xf6d7e
+ je short 06d84h ; 74 02 ; 0xf6d80
+ jmp short 06d21h ; eb 9d ; 0xf6d82 timepci.c:233
+ mov ax, strict word 00009h ; b8 09 00 ; 0xf6d84 timepci.c:235
+ call 01650h ; e8 c6 a8 ; 0xf6d87
+ mov byte [bp+010h], al ; 88 46 10 ; 0xf6d8a
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf6d8d timepci.c:236
+ call 01650h ; e8 bd a8 ; 0xf6d90
+ mov byte [bp+00fh], al ; 88 46 0f ; 0xf6d93
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf6d96 timepci.c:237
+ call 01650h ; e8 b4 a8 ; 0xf6d99
+ mov byte [bp+00eh], al ; 88 46 0e ; 0xf6d9c
+ mov ax, strict word 00032h ; b8 32 00 ; 0xf6d9f timepci.c:238
+ call 01650h ; e8 ab a8 ; 0xf6da2
+ mov byte [bp+011h], al ; 88 46 11 ; 0xf6da5
+ mov byte [bp+012h], al ; 88 46 12 ; 0xf6da8 timepci.c:239
+ jmp near 06d21h ; e9 73 ff ; 0xf6dab timepci.c:241
+ call 06bbeh ; e8 0d fe ; 0xf6dae timepci.c:254
+ test ax, ax ; 85 c0 ; 0xf6db1
+ je short 06dbbh ; 74 06 ; 0xf6db3
+ call 06b96h ; e8 de fd ; 0xf6db5 timepci.c:255
+ jmp near 06d21h ; e9 66 ff ; 0xf6db8 timepci.c:257
+ mov dl, byte [bp+010h] ; 8a 56 10 ; 0xf6dbb timepci.c:259
+ xor dh, dh ; 30 f6 ; 0xf6dbe
+ mov ax, strict word 00009h ; b8 09 00 ; 0xf6dc0
+ call 0166bh ; e8 a5 a8 ; 0xf6dc3
+ mov dl, byte [bp+00fh] ; 8a 56 0f ; 0xf6dc6 timepci.c:260
+ xor dh, dh ; 30 f6 ; 0xf6dc9
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf6dcb
+ call 0166bh ; e8 9a a8 ; 0xf6dce
+ mov dl, byte [bp+00eh] ; 8a 56 0e ; 0xf6dd1 timepci.c:261
+ xor dh, dh ; 30 f6 ; 0xf6dd4
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf6dd6
+ call 0166bh ; e8 8f a8 ; 0xf6dd9
+ mov dl, byte [bp+011h] ; 8a 56 11 ; 0xf6ddc timepci.c:262
+ xor dh, dh ; 30 f6 ; 0xf6ddf
+ mov ax, strict word 00032h ; b8 32 00 ; 0xf6de1
+ call 0166bh ; e8 84 a8 ; 0xf6de4
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6de7 timepci.c:263
+ call 01650h ; e8 63 a8 ; 0xf6dea
+ mov bl, al ; 88 c3 ; 0xf6ded
+ and bl, 07fh ; 80 e3 7f ; 0xf6def
+ jmp near 06d64h ; e9 6f ff ; 0xf6df2
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6df5 timepci.c:281
+ call 01650h ; e8 55 a8 ; 0xf6df8
+ mov bl, al ; 88 c3 ; 0xf6dfb
+ mov word [bp+012h], strict word 00000h ; c7 46 12 00 00 ; 0xf6dfd timepci.c:282
+ test AL, strict byte 020h ; a8 20 ; 0xf6e02 timepci.c:283
+ je short 06e09h ; 74 03 ; 0xf6e04
+ jmp near 06d21h ; e9 18 ff ; 0xf6e06 timepci.c:286
+ call 06bbeh ; e8 b2 fd ; 0xf6e09 timepci.c:288
+ test ax, ax ; 85 c0 ; 0xf6e0c
+ je short 06e13h ; 74 03 ; 0xf6e0e
+ call 06b96h ; e8 83 fd ; 0xf6e10 timepci.c:289
+ mov dl, byte [bp+00fh] ; 8a 56 0f ; 0xf6e13 timepci.c:292
+ xor dh, dh ; 30 f6 ; 0xf6e16
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf6e18
+ call 0166bh ; e8 4d a8 ; 0xf6e1b
+ mov dl, byte [bp+010h] ; 8a 56 10 ; 0xf6e1e timepci.c:293
+ xor dh, dh ; 30 f6 ; 0xf6e21
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf6e23
+ call 0166bh ; e8 42 a8 ; 0xf6e26
+ mov dl, byte [bp+011h] ; 8a 56 11 ; 0xf6e29 timepci.c:294
+ xor dh, dh ; 30 f6 ; 0xf6e2c
+ mov ax, strict word 00005h ; b8 05 00 ; 0xf6e2e
+ call 0166bh ; e8 37 a8 ; 0xf6e31
+ mov dx, 000a1h ; ba a1 00 ; 0xf6e34 timepci.c:295
+ in AL, DX ; ec ; 0xf6e37
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6e38
+ and AL, strict byte 0feh ; 24 fe ; 0xf6e3a
+ out DX, AL ; ee ; 0xf6e3c
+ mov dl, bl ; 88 da ; 0xf6e3d timepci.c:297
+ and dl, 05fh ; 80 e2 5f ; 0xf6e3f
+ or dl, 020h ; 80 ca 20 ; 0xf6e42
+ xor dh, dh ; 30 f6 ; 0xf6e45
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6e47
+ call 0166bh ; e8 1e a8 ; 0xf6e4a
+ jmp near 06d21h ; e9 d1 fe ; 0xf6e4d timepci.c:299
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6e50 timepci.c:312
+ call 01650h ; e8 fa a7 ; 0xf6e53
+ mov bl, al ; 88 c3 ; 0xf6e56
+ mov dl, al ; 88 c2 ; 0xf6e58 timepci.c:314
+ and dl, 057h ; 80 e2 57 ; 0xf6e5a
+ jmp near 06d66h ; e9 06 ff ; 0xf6e5d
+ ; disGetNextSymbol 0xf6e60 LB 0x3068 -> off=0x0 cb=0000000000000034 uValue=00000000000f5860 'send_to_mouse_ctrl'
+send_to_mouse_ctrl: ; 0xf6e60 LB 0x34
+ push bp ; 55 ; 0xf6e60 ps2mouse.c:77
+ mov bp, sp ; 89 e5 ; 0xf6e61
+ push bx ; 53 ; 0xf6e63
+ push dx ; 52 ; 0xf6e64
+ mov bl, al ; 88 c3 ; 0xf6e65
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf6e67 ps2mouse.c:81
+ in AL, DX ; ec ; 0xf6e6a
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6e6b
+ test AL, strict byte 002h ; a8 02 ; 0xf6e6d
+ je short 06e7fh ; 74 0e ; 0xf6e6f
+ push 008eeh ; 68 ee 08 ; 0xf6e71 ps2mouse.c:82
+ push 01168h ; 68 68 11 ; 0xf6e74
+ push strict byte 00007h ; 6a 07 ; 0xf6e77
+ call 018ffh ; e8 83 aa ; 0xf6e79
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf6e7c
+ mov AL, strict byte 0d4h ; b0 d4 ; 0xf6e7f ps2mouse.c:83
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf6e81
+ out DX, AL ; ee ; 0xf6e84
+ mov al, bl ; 88 d8 ; 0xf6e85 ps2mouse.c:84
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf6e87
+ out DX, AL ; ee ; 0xf6e8a
+ xor al, bl ; 30 d8 ; 0xf6e8b ps2mouse.c:86
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf6e8d
+ pop dx ; 5a ; 0xf6e90
+ pop bx ; 5b ; 0xf6e91
+ pop bp ; 5d ; 0xf6e92
+ retn ; c3 ; 0xf6e93
+ ; disGetNextSymbol 0xf6e94 LB 0x3034 -> off=0x0 cb=000000000000005d uValue=00000000000f5894 'get_mouse_data'
+get_mouse_data: ; 0xf6e94 LB 0x5d
+ push bp ; 55 ; 0xf6e94 ps2mouse.c:89
+ mov bp, sp ; 89 e5 ; 0xf6e95
+ push bx ; 53 ; 0xf6e97
+ push cx ; 51 ; 0xf6e98
+ push ax ; 50 ; 0xf6e99
+ mov bx, ax ; 89 c3 ; 0xf6e9a
+ mov es, dx ; 8e c2 ; 0xf6e9c
+ mov cx, 02710h ; b9 10 27 ; 0xf6e9e ps2mouse.c:91
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf6ea1 ps2mouse.c:94
+ in AL, DX ; ec ; 0xf6ea4
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6ea5
+ and ax, strict word 00021h ; 25 21 00 ; 0xf6ea7
+ cmp ax, strict word 00021h ; 3d 21 00 ; 0xf6eaa
+ je short 06ed7h ; 74 28 ; 0xf6ead
+ test cx, cx ; 85 c9 ; 0xf6eaf
+ je short 06ed7h ; 74 24 ; 0xf6eb1
+ mov dx, strict word 00061h ; ba 61 00 ; 0xf6eb3 ps2mouse.c:97
+ in AL, DX ; ec ; 0xf6eb6
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6eb7
+ and AL, strict byte 010h ; 24 10 ; 0xf6eb9
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf6ebb
+ mov dx, strict word 00061h ; ba 61 00 ; 0xf6ebe ps2mouse.c:98
+ in AL, DX ; ec ; 0xf6ec1
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6ec2
+ mov dx, ax ; 89 c2 ; 0xf6ec4
+ xor dh, ah ; 30 e6 ; 0xf6ec6
+ and dl, 010h ; 80 e2 10 ; 0xf6ec8
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf6ecb
+ xor ah, ah ; 30 e4 ; 0xf6ece
+ cmp dx, ax ; 39 c2 ; 0xf6ed0
+ je short 06ebeh ; 74 ea ; 0xf6ed2
+ dec cx ; 49 ; 0xf6ed4 ps2mouse.c:100
+ jmp short 06ea1h ; eb ca ; 0xf6ed5 ps2mouse.c:101
+ test cx, cx ; 85 c9 ; 0xf6ed7 ps2mouse.c:103
+ jne short 06edfh ; 75 04 ; 0xf6ed9
+ mov AL, strict byte 001h ; b0 01 ; 0xf6edb ps2mouse.c:104
+ jmp short 06eeah ; eb 0b ; 0xf6edd
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf6edf ps2mouse.c:106
+ in AL, DX ; ec ; 0xf6ee2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6ee3
+ mov byte [es:bx], al ; 26 88 07 ; 0xf6ee5 ps2mouse.c:107
+ xor al, al ; 30 c0 ; 0xf6ee8 ps2mouse.c:108
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf6eea ps2mouse.c:109
+ pop cx ; 59 ; 0xf6eed
+ pop bx ; 5b ; 0xf6eee
+ pop bp ; 5d ; 0xf6eef
+ retn ; c3 ; 0xf6ef0
+ ; disGetNextSymbol 0xf6ef1 LB 0x2fd7 -> off=0x0 cb=0000000000000032 uValue=00000000000f58f1 'set_kbd_command_byte'
+set_kbd_command_byte: ; 0xf6ef1 LB 0x32
+ push bp ; 55 ; 0xf6ef1 ps2mouse.c:111
+ mov bp, sp ; 89 e5 ; 0xf6ef2
+ push bx ; 53 ; 0xf6ef4
+ push dx ; 52 ; 0xf6ef5
+ mov bl, al ; 88 c3 ; 0xf6ef6
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf6ef8 ps2mouse.c:113
+ in AL, DX ; ec ; 0xf6efb
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6efc
+ test AL, strict byte 002h ; a8 02 ; 0xf6efe
+ je short 06f10h ; 74 0e ; 0xf6f00
+ push 008f8h ; 68 f8 08 ; 0xf6f02 ps2mouse.c:114
+ push 01168h ; 68 68 11 ; 0xf6f05
+ push strict byte 00007h ; 6a 07 ; 0xf6f08
+ call 018ffh ; e8 f2 a9 ; 0xf6f0a
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf6f0d
+ mov AL, strict byte 060h ; b0 60 ; 0xf6f10 ps2mouse.c:116
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf6f12
+ out DX, AL ; ee ; 0xf6f15
+ mov al, bl ; 88 d8 ; 0xf6f16 ps2mouse.c:117
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf6f18
+ out DX, AL ; ee ; 0xf6f1b
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf6f1c ps2mouse.c:118
+ pop dx ; 5a ; 0xf6f1f
+ pop bx ; 5b ; 0xf6f20
+ pop bp ; 5d ; 0xf6f21
+ retn ; c3 ; 0xf6f22
+ ; disGetNextSymbol 0xf6f23 LB 0x2fa5 -> off=0x0 cb=000000000000009e uValue=00000000000f5923 'int74_function'
+int74_function: ; 0xf6f23 LB 0x9e
+ push bp ; 55 ; 0xf6f23 ps2mouse.c:121
+ mov bp, sp ; 89 e5 ; 0xf6f24
+ push si ; 56 ; 0xf6f26
+ push ax ; 50 ; 0xf6f27
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf6f28 ps2mouse.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf6f2b
+ mov es, ax ; 8e c0 ; 0xf6f2e
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf6f30
+ mov word [bp+004h], strict word 00000h ; c7 46 04 00 00 ; 0xf6f33 ps2mouse.c:129
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf6f38 ps2mouse.c:131
+ in AL, DX ; ec ; 0xf6f3b
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6f3c
+ and AL, strict byte 021h ; 24 21 ; 0xf6f3e ps2mouse.c:132
+ cmp AL, strict byte 021h ; 3c 21 ; 0xf6f40
+ jne short 06f62h ; 75 1e ; 0xf6f42
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf6f44 ps2mouse.c:135
+ in AL, DX ; ec ; 0xf6f47
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6f48
+ mov byte [bp-004h], al ; 88 46 fc ; 0xf6f4a
+ mov si, strict word 00026h ; be 26 00 ; 0xf6f4d ps2mouse.c:38
+ mov es, bx ; 8e c3 ; 0xf6f50
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf6f52
+ mov si, strict word 00027h ; be 27 00 ; 0xf6f55 ps2mouse.c:38
+ mov ah, byte [es:si] ; 26 8a 24 ; 0xf6f58
+ mov cl, ah ; 88 e1 ; 0xf6f5b ps2mouse.c:39
+ test ah, 080h ; f6 c4 80 ; 0xf6f5d ps2mouse.c:141
+ jne short 06f64h ; 75 02 ; 0xf6f60
+ jmp short 06fbbh ; eb 57 ; 0xf6f62 ps2mouse.c:142
+ mov ch, cl ; 88 cd ; 0xf6f64 ps2mouse.c:145
+ and ch, 007h ; 80 e5 07 ; 0xf6f66
+ mov ah, al ; 88 c4 ; 0xf6f69 ps2mouse.c:146
+ and ah, 007h ; 80 e4 07 ; 0xf6f6b
+ mov dl, ah ; 88 e2 ; 0xf6f6e ps2mouse.c:147
+ xor dh, dh ; 30 f6 ; 0xf6f70
+ mov si, dx ; 89 d6 ; 0xf6f72
+ add si, strict byte 00028h ; 83 c6 28 ; 0xf6f74
+ mov es, bx ; 8e c3 ; 0xf6f77 ps2mouse.c:43
+ mov dl, byte [bp-004h] ; 8a 56 fc ; 0xf6f79
+ mov byte [es:si], dl ; 26 88 14 ; 0xf6f7c
+ cmp ah, ch ; 38 ec ; 0xf6f7f ps2mouse.c:149
+ jc short 06fb1h ; 72 2e ; 0xf6f81
+ mov si, strict word 00028h ; be 28 00 ; 0xf6f83 ps2mouse.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf6f86
+ xor ah, ah ; 30 e4 ; 0xf6f89 ps2mouse.c:39
+ mov word [bp+00ch], ax ; 89 46 0c ; 0xf6f8b
+ mov si, strict word 00029h ; be 29 00 ; 0xf6f8e ps2mouse.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf6f91
+ mov word [bp+00ah], ax ; 89 46 0a ; 0xf6f94 ps2mouse.c:39
+ mov si, strict word 0002ah ; be 2a 00 ; 0xf6f97 ps2mouse.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf6f9a
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf6f9d ps2mouse.c:39
+ xor al, al ; 30 c0 ; 0xf6fa0 ps2mouse.c:154
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf6fa2
+ test cl, 080h ; f6 c1 80 ; 0xf6fa5 ps2mouse.c:157
+ je short 06fb3h ; 74 09 ; 0xf6fa8
+ mov word [bp+004h], strict word 00001h ; c7 46 04 01 00 ; 0xf6faa ps2mouse.c:158
+ jmp short 06fb3h ; eb 02 ; 0xf6faf ps2mouse.c:160
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf6fb1 ps2mouse.c:161
+ mov si, strict word 00026h ; be 26 00 ; 0xf6fb3 ps2mouse.c:43
+ mov es, bx ; 8e c3 ; 0xf6fb6
+ mov byte [es:si], al ; 26 88 04 ; 0xf6fb8
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf6fbb ps2mouse.c:164
+ pop si ; 5e ; 0xf6fbe
+ pop bp ; 5d ; 0xf6fbf
+ retn ; c3 ; 0xf6fc0
+ ; disGetNextSymbol 0xf6fc1 LB 0x2f07 -> off=0x10 cb=000000000000036c uValue=00000000000f59d1 'int15_function_mouse'
+ db 012h, 070h, 083h, 070h, 0f6h, 070h, 088h, 071h, 0f4h, 071h, 058h, 070h, 01ch, 072h, 0e5h, 072h
+int15_function_mouse: ; 0xf6fd1 LB 0x36c
+ push bp ; 55 ; 0xf6fd1 ps2mouse.c:166
+ mov bp, sp ; 89 e5 ; 0xf6fd2
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf6fd4
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf6fd7 ps2mouse.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf6fda
+ mov es, ax ; 8e c0 ; 0xf6fdd
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf6fdf
+ cmp byte [bp+012h], 007h ; 80 7e 12 07 ; 0xf6fe2 ps2mouse.c:188
+ jbe short 06ff3h ; 76 0b ; 0xf6fe6
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf6fe8 ps2mouse.c:191
+ mov byte [bp+013h], 001h ; c6 46 13 01 ; 0xf6fec ps2mouse.c:192
+ jmp near 07339h ; e9 46 03 ; 0xf6ff0 ps2mouse.c:193
+ mov ax, strict word 00065h ; b8 65 00 ; 0xf6ff3 ps2mouse.c:197
+ call 06ef1h ; e8 f8 fe ; 0xf6ff6
+ and word [bp+018h], strict byte 0fffeh ; 83 66 18 fe ; 0xf6ff9 ps2mouse.c:198
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf6ffd ps2mouse.c:199
+ mov bl, byte [bp+012h] ; 8a 5e 12 ; 0xf7001 ps2mouse.c:201
+ cmp bl, 007h ; 80 fb 07 ; 0xf7004
+ jnbe short 07066h ; 77 5d ; 0xf7007
+ xor bh, bh ; 30 ff ; 0xf7009
+ add bx, bx ; 01 db ; 0xf700b
+ jmp word [cs:bx+06fc1h] ; 2e ff a7 c1 6f ; 0xf700d
+ cmp byte [bp+00dh], 001h ; 80 7e 0d 01 ; 0xf7012 ps2mouse.c:204
+ jnbe short 07069h ; 77 51 ; 0xf7016
+ mov bx, strict word 00027h ; bb 27 00 ; 0xf7018 ps2mouse.c:38
+ mov es, dx ; 8e c2 ; 0xf701b
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf701d
+ test AL, strict byte 080h ; a8 80 ; 0xf7020 ps2mouse.c:212
+ jne short 0702fh ; 75 0b ; 0xf7022
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf7024 ps2mouse.c:214
+ mov byte [bp+013h], 005h ; c6 46 13 05 ; 0xf7028 ps2mouse.c:215
+ jmp near 07333h ; e9 04 03 ; 0xf702c ps2mouse.c:216
+ cmp byte [bp+00dh], 000h ; 80 7e 0d 00 ; 0xf702f ps2mouse.c:218
+ jne short 07039h ; 75 04 ; 0xf7033
+ mov AL, strict byte 0f5h ; b0 f5 ; 0xf7035 ps2mouse.c:220
+ jmp short 0703bh ; eb 02 ; 0xf7037 ps2mouse.c:221
+ mov AL, strict byte 0f4h ; b0 f4 ; 0xf7039 ps2mouse.c:223
+ xor ah, ah ; 30 e4 ; 0xf703b ps2mouse.c:226
+ call 06e60h ; e8 20 fe ; 0xf703d
+ test al, al ; 84 c0 ; 0xf7040 ps2mouse.c:227
+ jne short 0706ch ; 75 28 ; 0xf7042
+ mov dx, ss ; 8c d2 ; 0xf7044 ps2mouse.c:228
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf7046
+ call 06e94h ; e8 48 fe ; 0xf7049
+ test al, al ; 84 c0 ; 0xf704c ps2mouse.c:229
+ je short 070b2h ; 74 62 ; 0xf704e
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf7050
+ jne short 0706ch ; 75 16 ; 0xf7054
+ jmp short 070b2h ; eb 5a ; 0xf7056 ps2mouse.c:231
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf7058 ps2mouse.c:242
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf705b
+ jc short 07063h ; 72 04 ; 0xf705d
+ cmp AL, strict byte 008h ; 3c 08 ; 0xf705f
+ jbe short 0706fh ; 76 0c ; 0xf7061
+ jmp near 071eah ; e9 84 01 ; 0xf7063
+ jmp near 07320h ; e9 b7 02 ; 0xf7066
+ jmp near 0732bh ; e9 bf 02 ; 0xf7069
+ jmp near 072c0h ; e9 51 02 ; 0xf706c
+ mov bx, strict word 00027h ; bb 27 00 ; 0xf706f ps2mouse.c:38
+ mov es, dx ; 8e c2 ; 0xf7072
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf7074
+ mov ah, byte [bp+00dh] ; 8a 66 0d ; 0xf7077 ps2mouse.c:248
+ db 0feh, 0cch
+ ; dec ah ; fe cc ; 0xf707a
+ and AL, strict byte 0f8h ; 24 f8 ; 0xf707c
+ or al, ah ; 08 e0 ; 0xf707e
+ mov byte [es:bx], al ; 26 88 07 ; 0xf7080 ps2mouse.c:43
+ mov bx, strict word 00026h ; bb 26 00 ; 0xf7083 ps2mouse.c:38
+ mov es, dx ; 8e c2 ; 0xf7086
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf7088
+ and AL, strict byte 0f8h ; 24 f8 ; 0xf708b ps2mouse.c:256
+ mov byte [es:bx], al ; 26 88 07 ; 0xf708d ps2mouse.c:43
+ mov ax, 000ffh ; b8 ff 00 ; 0xf7090 ps2mouse.c:258
+ call 06e60h ; e8 ca fd ; 0xf7093
+ test al, al ; 84 c0 ; 0xf7096 ps2mouse.c:259
+ jne short 0706ch ; 75 d2 ; 0xf7098
+ mov dx, ss ; 8c d2 ; 0xf709a ps2mouse.c:260
+ lea ax, [bp-004h] ; 8d 46 fc ; 0xf709c
+ call 06e94h ; e8 f2 fd ; 0xf709f
+ mov dl, al ; 88 c2 ; 0xf70a2
+ cmp byte [bp-004h], 0feh ; 80 7e fc fe ; 0xf70a4 ps2mouse.c:262
+ jne short 070b5h ; 75 0b ; 0xf70a8
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf70aa ps2mouse.c:263
+ mov byte [bp+013h], 004h ; c6 46 13 04 ; 0xf70ae ps2mouse.c:264
+ jmp near 07333h ; e9 7e 02 ; 0xf70b2 ps2mouse.c:265
+ cmp byte [bp-004h], 0fah ; 80 7e fc fa ; 0xf70b5 ps2mouse.c:267
+ je short 070cch ; 74 11 ; 0xf70b9
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf70bb ps2mouse.c:268
+ xor ah, ah ; 30 e4 ; 0xf70be
+ push ax ; 50 ; 0xf70c0
+ push 00903h ; 68 03 09 ; 0xf70c1
+ push strict byte 00007h ; 6a 07 ; 0xf70c4
+ call 018ffh ; e8 36 a8 ; 0xf70c6
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf70c9
+ test dl, dl ; 84 d2 ; 0xf70cc ps2mouse.c:269
+ jne short 0706ch ; 75 9c ; 0xf70ce
+ mov dx, ss ; 8c d2 ; 0xf70d0 ps2mouse.c:270
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf70d2
+ call 06e94h ; e8 bc fd ; 0xf70d5
+ test al, al ; 84 c0 ; 0xf70d8 ps2mouse.c:271
+ jne short 0706ch ; 75 90 ; 0xf70da
+ mov dx, ss ; 8c d2 ; 0xf70dc ps2mouse.c:272
+ lea ax, [bp-002h] ; 8d 46 fe ; 0xf70de
+ call 06e94h ; e8 b0 fd ; 0xf70e1
+ test al, al ; 84 c0 ; 0xf70e4 ps2mouse.c:273
+ jne short 0706ch ; 75 84 ; 0xf70e6
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf70e8 ps2mouse.c:275
+ mov byte [bp+00ch], al ; 88 46 0c ; 0xf70eb
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf70ee ps2mouse.c:276
+ mov byte [bp+00dh], al ; 88 46 0d ; 0xf70f1
+ jmp short 070b2h ; eb bc ; 0xf70f4 ps2mouse.c:277
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf70f6 ps2mouse.c:290
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf70f9
+ jc short 0710dh ; 72 10 ; 0xf70fb
+ jbe short 0712bh ; 76 2c ; 0xf70fd
+ cmp AL, strict byte 006h ; 3c 06 ; 0xf70ff
+ je short 0713dh ; 74 3a ; 0xf7101
+ cmp AL, strict byte 005h ; 3c 05 ; 0xf7103
+ je short 07137h ; 74 30 ; 0xf7105
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf7107
+ je short 07131h ; 74 26 ; 0xf7109
+ jmp short 07143h ; eb 36 ; 0xf710b
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf710d
+ je short 07125h ; 74 14 ; 0xf710f
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf7111
+ je short 0711fh ; 74 0a ; 0xf7113
+ test al, al ; 84 c0 ; 0xf7115
+ jne short 07143h ; 75 2a ; 0xf7117
+ mov byte [bp-006h], 00ah ; c6 46 fa 0a ; 0xf7119 ps2mouse.c:291
+ jmp short 07147h ; eb 28 ; 0xf711d
+ mov byte [bp-006h], 014h ; c6 46 fa 14 ; 0xf711f ps2mouse.c:292
+ jmp short 07147h ; eb 22 ; 0xf7123
+ mov byte [bp-006h], 028h ; c6 46 fa 28 ; 0xf7125 ps2mouse.c:293
+ jmp short 07147h ; eb 1c ; 0xf7129
+ mov byte [bp-006h], 03ch ; c6 46 fa 3c ; 0xf712b ps2mouse.c:294
+ jmp short 07147h ; eb 16 ; 0xf712f
+ mov byte [bp-006h], 050h ; c6 46 fa 50 ; 0xf7131 ps2mouse.c:295
+ jmp short 07147h ; eb 10 ; 0xf7135
+ mov byte [bp-006h], 064h ; c6 46 fa 64 ; 0xf7137 ps2mouse.c:296
+ jmp short 07147h ; eb 0a ; 0xf713b
+ mov byte [bp-006h], 0c8h ; c6 46 fa c8 ; 0xf713d ps2mouse.c:297
+ jmp short 07147h ; eb 04 ; 0xf7141
+ mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xf7143 ps2mouse.c:298
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf7147 ps2mouse.c:300
+ jbe short 0717dh ; 76 30 ; 0xf714b
+ mov ax, 000f3h ; b8 f3 00 ; 0xf714d ps2mouse.c:301
+ call 06e60h ; e8 0d fd ; 0xf7150
+ test al, al ; 84 c0 ; 0xf7153 ps2mouse.c:302
+ jne short 07172h ; 75 1b ; 0xf7155
+ mov dx, ss ; 8c d2 ; 0xf7157 ps2mouse.c:303
+ lea ax, [bp-002h] ; 8d 46 fe ; 0xf7159
+ call 06e94h ; e8 35 fd ; 0xf715c
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf715f ps2mouse.c:304
+ xor ah, ah ; 30 e4 ; 0xf7162
+ call 06e60h ; e8 f9 fc ; 0xf7164
+ mov dx, ss ; 8c d2 ; 0xf7167 ps2mouse.c:305
+ lea ax, [bp-002h] ; 8d 46 fe ; 0xf7169
+ call 06e94h ; e8 25 fd ; 0xf716c
+ jmp near 07333h ; e9 c1 01 ; 0xf716f ps2mouse.c:307
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf7172 ps2mouse.c:309
+ mov byte [bp+013h], 003h ; c6 46 13 03 ; 0xf7176 ps2mouse.c:310
+ jmp near 07333h ; e9 b6 01 ; 0xf717a ps2mouse.c:312
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf717d ps2mouse.c:314
+ mov byte [bp+013h], 002h ; c6 46 13 02 ; 0xf7181 ps2mouse.c:315
+ jmp near 07333h ; e9 ab 01 ; 0xf7185 ps2mouse.c:317
+ cmp byte [bp+00dh], 004h ; 80 7e 0d 04 ; 0xf7188 ps2mouse.c:326
+ jnc short 071eah ; 73 5c ; 0xf718c
+ mov ax, 000e8h ; b8 e8 00 ; 0xf718e ps2mouse.c:327
+ call 06e60h ; e8 cc fc ; 0xf7191
+ test al, al ; 84 c0 ; 0xf7194 ps2mouse.c:328
+ jne short 071e0h ; 75 48 ; 0xf7196
+ mov dx, ss ; 8c d2 ; 0xf7198 ps2mouse.c:329
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf719a
+ call 06e94h ; e8 f4 fc ; 0xf719d
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf71a0 ps2mouse.c:330
+ je short 071b7h ; 74 11 ; 0xf71a4
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf71a6 ps2mouse.c:331
+ xor ah, ah ; 30 e4 ; 0xf71a9
+ push ax ; 50 ; 0xf71ab
+ push 0092eh ; 68 2e 09 ; 0xf71ac
+ push strict byte 00007h ; 6a 07 ; 0xf71af
+ call 018ffh ; e8 4b a7 ; 0xf71b1
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf71b4
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf71b7 ps2mouse.c:332
+ xor ah, ah ; 30 e4 ; 0xf71ba
+ call 06e60h ; e8 a1 fc ; 0xf71bc
+ mov dx, ss ; 8c d2 ; 0xf71bf ps2mouse.c:333
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf71c1
+ call 06e94h ; e8 cd fc ; 0xf71c4
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf71c7 ps2mouse.c:334
+ je short 07219h ; 74 4c ; 0xf71cb
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf71cd ps2mouse.c:335
+ xor ah, ah ; 30 e4 ; 0xf71d0
+ push ax ; 50 ; 0xf71d2
+ push 0092eh ; 68 2e 09 ; 0xf71d3
+ push strict byte 00007h ; 6a 07 ; 0xf71d6
+ call 018ffh ; e8 24 a7 ; 0xf71d8
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf71db
+ jmp short 07219h ; eb 39 ; 0xf71de ps2mouse.c:337
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf71e0 ps2mouse.c:339
+ mov byte [bp+013h], 003h ; c6 46 13 03 ; 0xf71e4 ps2mouse.c:340
+ jmp short 07219h ; eb 2f ; 0xf71e8 ps2mouse.c:342
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf71ea ps2mouse.c:344
+ mov byte [bp+013h], 002h ; c6 46 13 02 ; 0xf71ee ps2mouse.c:345
+ jmp short 07219h ; eb 25 ; 0xf71f2 ps2mouse.c:347
+ mov ax, 000f2h ; b8 f2 00 ; 0xf71f4 ps2mouse.c:351
+ call 06e60h ; e8 66 fc ; 0xf71f7
+ test al, al ; 84 c0 ; 0xf71fa ps2mouse.c:352
+ jne short 07211h ; 75 13 ; 0xf71fc
+ mov dx, ss ; 8c d2 ; 0xf71fe ps2mouse.c:353
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf7200
+ call 06e94h ; e8 8e fc ; 0xf7203
+ mov dx, ss ; 8c d2 ; 0xf7206 ps2mouse.c:354
+ lea ax, [bp-002h] ; 8d 46 fe ; 0xf7208
+ call 06e94h ; e8 86 fc ; 0xf720b
+ jmp near 070eeh ; e9 dd fe ; 0xf720e
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf7211 ps2mouse.c:355
+ mov byte [bp+013h], 003h ; c6 46 13 03 ; 0xf7215 ps2mouse.c:360
+ jmp near 07333h ; e9 17 01 ; 0xf7219 ps2mouse.c:362
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf721c ps2mouse.c:366
+ test al, al ; 84 c0 ; 0xf721f
+ jbe short 0722ah ; 76 07 ; 0xf7221
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf7223
+ jbe short 07291h ; 76 6a ; 0xf7225
+ jmp near 072cah ; e9 a0 00 ; 0xf7227
+ mov ax, 000e9h ; b8 e9 00 ; 0xf722a ps2mouse.c:368
+ call 06e60h ; e8 30 fc ; 0xf722d
+ test al, al ; 84 c0 ; 0xf7230 ps2mouse.c:369
+ jne short 0729ah ; 75 66 ; 0xf7232
+ mov dx, ss ; 8c d2 ; 0xf7234 ps2mouse.c:370
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf7236
+ call 06e94h ; e8 58 fc ; 0xf7239
+ mov dl, al ; 88 c2 ; 0xf723c
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf723e ps2mouse.c:371
+ je short 07255h ; 74 11 ; 0xf7242
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7244 ps2mouse.c:372
+ xor ah, ah ; 30 e4 ; 0xf7247
+ push ax ; 50 ; 0xf7249
+ push 0092eh ; 68 2e 09 ; 0xf724a
+ push strict byte 00007h ; 6a 07 ; 0xf724d
+ call 018ffh ; e8 ad a6 ; 0xf724f
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7252
+ test dl, dl ; 84 d2 ; 0xf7255 ps2mouse.c:373
+ jne short 0729ah ; 75 41 ; 0xf7257
+ mov dx, ss ; 8c d2 ; 0xf7259 ps2mouse.c:374
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf725b
+ call 06e94h ; e8 33 fc ; 0xf725e
+ test al, al ; 84 c0 ; 0xf7261 ps2mouse.c:375
+ jne short 072c0h ; 75 5b ; 0xf7263
+ mov dx, ss ; 8c d2 ; 0xf7265 ps2mouse.c:376
+ lea ax, [bp-002h] ; 8d 46 fe ; 0xf7267
+ call 06e94h ; e8 27 fc ; 0xf726a
+ test al, al ; 84 c0 ; 0xf726d ps2mouse.c:377
+ jne short 072c0h ; 75 4f ; 0xf726f
+ mov dx, ss ; 8c d2 ; 0xf7271 ps2mouse.c:378
+ lea ax, [bp-004h] ; 8d 46 fc ; 0xf7273
+ call 06e94h ; e8 1b fc ; 0xf7276
+ test al, al ; 84 c0 ; 0xf7279 ps2mouse.c:379
+ jne short 072c0h ; 75 43 ; 0xf727b
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf727d ps2mouse.c:380
+ mov byte [bp+00ch], al ; 88 46 0c ; 0xf7280
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf7283 ps2mouse.c:381
+ mov byte [bp+010h], al ; 88 46 10 ; 0xf7286
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf7289 ps2mouse.c:382
+ mov byte [bp+00eh], al ; 88 46 0e ; 0xf728c
+ jmp short 07219h ; eb 88 ; 0xf728f ps2mouse.c:384
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf7291 ps2mouse.c:398
+ jne short 0729ch ; 75 07 ; 0xf7293
+ mov ax, 000e6h ; b8 e6 00 ; 0xf7295 ps2mouse.c:399
+ jmp short 0729fh ; eb 05 ; 0xf7298 ps2mouse.c:400
+ jmp short 072c0h ; eb 24 ; 0xf729a
+ mov ax, 000e7h ; b8 e7 00 ; 0xf729c ps2mouse.c:401
+ call 06e60h ; e8 be fb ; 0xf729f
+ mov dl, al ; 88 c2 ; 0xf72a2
+ test dl, dl ; 84 d2 ; 0xf72a4 ps2mouse.c:403
+ jne short 072bch ; 75 14 ; 0xf72a6
+ mov dx, ss ; 8c d2 ; 0xf72a8 ps2mouse.c:404
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf72aa
+ call 06e94h ; e8 e4 fb ; 0xf72ad
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf72b0 ps2mouse.c:405
+ je short 072bah ; 74 04 ; 0xf72b4
+ mov DL, strict byte 001h ; b2 01 ; 0xf72b6
+ jmp short 072bch ; eb 02 ; 0xf72b8
+ xor dl, dl ; 30 d2 ; 0xf72ba
+ test dl, dl ; 84 d2 ; 0xf72bc ps2mouse.c:407
+ je short 0731eh ; 74 5e ; 0xf72be
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf72c0 ps2mouse.c:409
+ mov byte [bp+013h], 003h ; c6 46 13 03 ; 0xf72c4 ps2mouse.c:410
+ jmp short 07333h ; eb 69 ; 0xf72c8 ps2mouse.c:412
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf72ca ps2mouse.c:415
+ xor ah, ah ; 30 e4 ; 0xf72cd
+ push ax ; 50 ; 0xf72cf
+ push 0095ah ; 68 5a 09 ; 0xf72d0
+ push strict byte 00007h ; 6a 07 ; 0xf72d3
+ call 018ffh ; e8 27 a6 ; 0xf72d5
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf72d8
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf72db ps2mouse.c:417
+ mov byte [bp+013h], 001h ; c6 46 13 01 ; 0xf72df ps2mouse.c:418
+ jmp short 07333h ; eb 4e ; 0xf72e3 ps2mouse.c:420
+ mov cx, word [bp+00ch] ; 8b 4e 0c ; 0xf72e5 ps2mouse.c:425
+ mov bx, strict word 00022h ; bb 22 00 ; 0xf72e8 ps2mouse.c:53
+ mov es, dx ; 8e c2 ; 0xf72eb
+ mov word [es:bx], cx ; 26 89 0f ; 0xf72ed
+ mov bx, strict word 00024h ; bb 24 00 ; 0xf72f0 ps2mouse.c:53
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf72f3
+ mov word [es:bx], ax ; 26 89 07 ; 0xf72f6
+ mov bx, strict word 00027h ; bb 27 00 ; 0xf72f9 ps2mouse.c:38
+ mov ah, byte [es:bx] ; 26 8a 27 ; 0xf72fc
+ mov al, ah ; 88 e0 ; 0xf72ff ps2mouse.c:39
+ test cx, cx ; 85 c9 ; 0xf7301 ps2mouse.c:429
+ jne short 07314h ; 75 0f ; 0xf7303
+ cmp word [bp+014h], strict byte 00000h ; 83 7e 14 00 ; 0xf7305
+ jne short 07314h ; 75 09 ; 0xf7309
+ test ah, 080h ; f6 c4 80 ; 0xf730b ps2mouse.c:431
+ je short 07316h ; 74 06 ; 0xf730e
+ and AL, strict byte 07fh ; 24 7f ; 0xf7310 ps2mouse.c:432
+ jmp short 07316h ; eb 02 ; 0xf7312 ps2mouse.c:435
+ or AL, strict byte 080h ; 0c 80 ; 0xf7314 ps2mouse.c:437
+ mov bx, strict word 00027h ; bb 27 00 ; 0xf7316 ps2mouse.c:43
+ mov es, dx ; 8e c2 ; 0xf7319
+ mov byte [es:bx], al ; 26 88 07 ; 0xf731b
+ jmp short 07333h ; eb 13 ; 0xf731e ps2mouse.c:440
+ push 00974h ; 68 74 09 ; 0xf7320 ps2mouse.c:443
+ push strict byte 00007h ; 6a 07 ; 0xf7323
+ call 018ffh ; e8 d7 a5 ; 0xf7325
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7328
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf732b ps2mouse.c:445
+ mov byte [bp+013h], 001h ; c6 46 13 01 ; 0xf732f ps2mouse.c:446
+ mov ax, strict word 00047h ; b8 47 00 ; 0xf7333 ps2mouse.c:450
+ call 06ef1h ; e8 b8 fb ; 0xf7336
+ mov sp, bp ; 89 ec ; 0xf7339 ps2mouse.c:451
+ pop bp ; 5d ; 0xf733b
+ retn ; c3 ; 0xf733c
+ ; disGetNextSymbol 0xf733d LB 0x2b8b -> off=0x0 cb=00000000000000ac uValue=00000000000f5d3d 'int17_function'
+int17_function: ; 0xf733d LB 0xac
+ push bp ; 55 ; 0xf733d parallel.c:60
+ mov bp, sp ; 89 e5 ; 0xf733e
+ push si ; 56 ; 0xf7340
+ push di ; 57 ; 0xf7341
+ push ax ; 50 ; 0xf7342
+ sti ; fb ; 0xf7343 parallel.c:65
+ mov bx, word [bp+00eh] ; 8b 5e 0e ; 0xf7344 parallel.c:67
+ add bx, bx ; 01 db ; 0xf7347
+ add bx, strict byte 00008h ; 83 c3 08 ; 0xf7349
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf734c parallel.c:48
+ mov es, ax ; 8e c0 ; 0xf734f
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf7351
+ mov si, bx ; 89 de ; 0xf7354 parallel.c:49
+ cmp byte [bp+013h], 003h ; 80 7e 13 03 ; 0xf7356 parallel.c:68
+ jnc short 07368h ; 73 0c ; 0xf735a
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf735c
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf735f
+ jnc short 07368h ; 73 04 ; 0xf7362
+ test bx, bx ; 85 db ; 0xf7364
+ jnbe short 0736bh ; 77 03 ; 0xf7366
+ jmp near 073deh ; e9 73 00 ; 0xf7368
+ mov di, ax ; 89 c7 ; 0xf736b parallel.c:69
+ add di, strict byte 00078h ; 83 c7 78 ; 0xf736d
+ mov cl, byte [es:di] ; 26 8a 0d ; 0xf7370 parallel.c:38
+ xor ch, ch ; 30 ed ; 0xf7373 parallel.c:39
+ sal cx, 008h ; c1 e1 08 ; 0xf7375
+ cmp byte [bp+013h], 000h ; 80 7e 13 00 ; 0xf7378 parallel.c:70
+ jne short 073aah ; 75 2c ; 0xf737c
+ mov al, byte [bp+012h] ; 8a 46 12 ; 0xf737e parallel.c:71
+ mov dx, bx ; 89 da ; 0xf7381
+ out DX, AL ; ee ; 0xf7383
+ lea dx, [bx+002h] ; 8d 57 02 ; 0xf7384 parallel.c:72
+ in AL, DX ; ec ; 0xf7387
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7388
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf738a
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf738d parallel.c:73
+ or AL, strict byte 001h ; 0c 01 ; 0xf7390
+ out DX, AL ; ee ; 0xf7392
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7393 parallel.c:74
+ and AL, strict byte 0feh ; 24 fe ; 0xf7396
+ out DX, AL ; ee ; 0xf7398
+ lea dx, [si+001h] ; 8d 54 01 ; 0xf7399 parallel.c:75
+ in AL, DX ; ec ; 0xf739c
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf739d
+ test AL, strict byte 040h ; a8 40 ; 0xf739f
+ je short 073aah ; 74 07 ; 0xf73a1
+ test cx, cx ; 85 c9 ; 0xf73a3
+ je short 073aah ; 74 03 ; 0xf73a5
+ dec cx ; 49 ; 0xf73a7 parallel.c:76
+ jmp short 07399h ; eb ef ; 0xf73a8 parallel.c:77
+ cmp byte [bp+013h], 001h ; 80 7e 13 01 ; 0xf73aa parallel.c:79
+ jne short 073c5h ; 75 15 ; 0xf73ae
+ lea dx, [si+002h] ; 8d 54 02 ; 0xf73b0 parallel.c:80
+ in AL, DX ; ec ; 0xf73b3
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf73b4
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf73b6
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf73b9 parallel.c:81
+ and AL, strict byte 0fbh ; 24 fb ; 0xf73bc
+ out DX, AL ; ee ; 0xf73be
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf73bf parallel.c:82
+ or AL, strict byte 004h ; 0c 04 ; 0xf73c2
+ out DX, AL ; ee ; 0xf73c4
+ lea dx, [si+001h] ; 8d 54 01 ; 0xf73c5 parallel.c:84
+ in AL, DX ; ec ; 0xf73c8
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf73c9
+ xor AL, strict byte 048h ; 34 48 ; 0xf73cb parallel.c:85
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf73cd
+ test cx, cx ; 85 c9 ; 0xf73d0 parallel.c:86
+ jne short 073d8h ; 75 04 ; 0xf73d2
+ or byte [bp+013h], 001h ; 80 4e 13 01 ; 0xf73d4
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf73d8 parallel.c:87
+ jmp short 073e2h ; eb 04 ; 0xf73dc parallel.c:88
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf73de parallel.c:89
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf73e2 parallel.c:91
+ pop di ; 5f ; 0xf73e5
+ pop si ; 5e ; 0xf73e6
+ pop bp ; 5d ; 0xf73e7
+ retn ; c3 ; 0xf73e8
+ ; disGetNextSymbol 0xf73e9 LB 0x2adf -> off=0x0 cb=00000000000000b7 uValue=00000000000f5de9 '_wait_'
+_wait_: ; 0xf73e9 LB 0xb7
+ push bp ; 55 ; 0xf73e9 logo.c:171
+ mov bp, sp ; 89 e5 ; 0xf73ea
+ push bx ; 53 ; 0xf73ec
+ push cx ; 51 ; 0xf73ed
+ push si ; 56 ; 0xf73ee
+ push di ; 57 ; 0xf73ef
+ sub sp, strict byte 0000ah ; 83 ec 0a ; 0xf73f0
+ mov si, ax ; 89 c6 ; 0xf73f3
+ mov byte [bp-00ah], dl ; 88 56 f6 ; 0xf73f5
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf73f8 logo.c:176
+ pushfw ; 9c ; 0xf73fc logo.c:182
+ pop ax ; 58 ; 0xf73fd
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf73fe
+ sti ; fb ; 0xf7401 logo.c:183
+ xor dx, dx ; 31 d2 ; 0xf7402 logo.c:189
+ mov bx, 0046ch ; bb 6c 04 ; 0xf7404 logo.c:58
+ mov es, dx ; 8e c2 ; 0xf7407
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf7409
+ mov cx, word [es:bx+002h] ; 26 8b 4f 02 ; 0xf740c
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf7410 logo.c:59
+ hlt ; f4 ; 0xf7413 logo.c:193
+ mov bx, 0046ch ; bb 6c 04 ; 0xf7414 logo.c:58
+ xor ax, ax ; 31 c0 ; 0xf7417
+ mov es, ax ; 8e c0 ; 0xf7419
+ mov di, word [es:bx] ; 26 8b 3f ; 0xf741b
+ mov ax, word [es:bx+002h] ; 26 8b 47 02 ; 0xf741e
+ mov word [bp-012h], di ; 89 7e ee ; 0xf7422 logo.c:59
+ mov bx, ax ; 89 c3 ; 0xf7425
+ cmp ax, cx ; 39 c8 ; 0xf7427 logo.c:195
+ jnbe short 07432h ; 77 07 ; 0xf7429
+ jne short 07439h ; 75 0c ; 0xf742b
+ cmp di, word [bp-00eh] ; 3b 7e f2 ; 0xf742d
+ jbe short 07439h ; 76 07 ; 0xf7430
+ sub di, word [bp-00eh] ; 2b 7e f2 ; 0xf7432 logo.c:197
+ sbb ax, cx ; 19 c8 ; 0xf7435
+ jmp short 07444h ; eb 0b ; 0xf7437 logo.c:200
+ cmp ax, cx ; 39 c8 ; 0xf7439
+ jc short 07444h ; 72 07 ; 0xf743b
+ jne short 07448h ; 75 09 ; 0xf743d
+ cmp di, word [bp-00eh] ; 3b 7e f2 ; 0xf743f
+ jnc short 07448h ; 73 04 ; 0xf7442
+ sub si, di ; 29 fe ; 0xf7444 logo.c:201
+ sbb dx, ax ; 19 c2 ; 0xf7446
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf7448 logo.c:202
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf744b
+ mov cx, bx ; 89 d9 ; 0xf744e
+ mov ax, 00100h ; b8 00 01 ; 0xf7450 logo.c:204
+ int 016h ; cd 16 ; 0xf7453
+ je short 0745ch ; 74 05 ; 0xf7455
+ mov AL, strict byte 001h ; b0 01 ; 0xf7457
+ jmp near 0745eh ; e9 02 00 ; 0xf7459
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xf745c
+ test al, al ; 84 c0 ; 0xf745e
+ je short 07485h ; 74 23 ; 0xf7460
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf7462 logo.c:206
+ int 016h ; cd 16 ; 0xf7464
+ xchg ah, al ; 86 c4 ; 0xf7466
+ mov bl, al ; 88 c3 ; 0xf7468
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf746a
+ xor ah, ah ; 30 e4 ; 0xf746d logo.c:207
+ push ax ; 50 ; 0xf746f
+ push 00996h ; 68 96 09 ; 0xf7470
+ push strict byte 00004h ; 6a 04 ; 0xf7473
+ call 018ffh ; e8 87 a4 ; 0xf7475
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7478
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf747b logo.c:208
+ je short 07485h ; 74 04 ; 0xf747f
+ mov al, bl ; 88 d8 ; 0xf7481 logo.c:209
+ jmp short 07497h ; eb 12 ; 0xf7483
+ test dx, dx ; 85 d2 ; 0xf7485 logo.c:211
+ jnle short 07413h ; 7f 8a ; 0xf7487
+ jne short 0748fh ; 75 04 ; 0xf7489
+ test si, si ; 85 f6 ; 0xf748b
+ jnbe short 07413h ; 77 84 ; 0xf748d
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf748f logo.c:212
+ push ax ; 50 ; 0xf7492
+ popfw ; 9d ; 0xf7493
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf7494 logo.c:213
+ lea sp, [bp-008h] ; 8d 66 f8 ; 0xf7497 logo.c:214
+ pop di ; 5f ; 0xf749a
+ pop si ; 5e ; 0xf749b
+ pop cx ; 59 ; 0xf749c
+ pop bx ; 5b ; 0xf749d
+ pop bp ; 5d ; 0xf749e
+ retn ; c3 ; 0xf749f
+ ; disGetNextSymbol 0xf74a0 LB 0x2a28 -> off=0x0 cb=0000000000000016 uValue=00000000000f5ea0 'read_logo_byte'
+read_logo_byte: ; 0xf74a0 LB 0x16
+ push bp ; 55 ; 0xf74a0 logo.c:216
+ mov bp, sp ; 89 e5 ; 0xf74a1
+ push dx ; 52 ; 0xf74a3
+ xor ah, ah ; 30 e4 ; 0xf74a4 logo.c:218
+ or ah, 001h ; 80 cc 01 ; 0xf74a6
+ mov dx, 003b8h ; ba b8 03 ; 0xf74a9
+ out DX, ax ; ef ; 0xf74ac
+ in AL, DX ; ec ; 0xf74ad logo.c:219
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf74ae
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf74b0 logo.c:220
+ pop dx ; 5a ; 0xf74b3
+ pop bp ; 5d ; 0xf74b4
+ retn ; c3 ; 0xf74b5
+ ; disGetNextSymbol 0xf74b6 LB 0x2a12 -> off=0x0 cb=0000000000000014 uValue=00000000000f5eb6 'read_logo_word'
+read_logo_word: ; 0xf74b6 LB 0x14
+ push bp ; 55 ; 0xf74b6 logo.c:222
+ mov bp, sp ; 89 e5 ; 0xf74b7
+ push dx ; 52 ; 0xf74b9
+ xor ah, ah ; 30 e4 ; 0xf74ba logo.c:224
+ or ah, 001h ; 80 cc 01 ; 0xf74bc
+ mov dx, 003b8h ; ba b8 03 ; 0xf74bf
+ out DX, ax ; ef ; 0xf74c2
+ in ax, DX ; ed ; 0xf74c3 logo.c:225
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf74c4 logo.c:226
+ pop dx ; 5a ; 0xf74c7
+ pop bp ; 5d ; 0xf74c8
+ retn ; c3 ; 0xf74c9
+ ; disGetNextSymbol 0xf74ca LB 0x29fe -> off=0x0 cb=000000000000013e uValue=00000000000f5eca 'print_detected_harddisks'
+print_detected_harddisks: ; 0xf74ca LB 0x13e
+ push bp ; 55 ; 0xf74ca logo.c:245
+ mov bp, sp ; 89 e5 ; 0xf74cb
+ push bx ; 53 ; 0xf74cd
+ push cx ; 51 ; 0xf74ce
+ push dx ; 52 ; 0xf74cf
+ push si ; 56 ; 0xf74d0
+ push di ; 57 ; 0xf74d1
+ push ax ; 50 ; 0xf74d2
+ push ax ; 50 ; 0xf74d3
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf74d4 logo.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf74d7
+ mov es, ax ; 8e c0 ; 0xf74da
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf74dc
+ mov di, ax ; 89 c7 ; 0xf74df logo.c:49
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf74e1 logo.c:250
+ xor cl, cl ; 30 c9 ; 0xf74e5 logo.c:251
+ xor ch, ch ; 30 ed ; 0xf74e7 logo.c:252
+ mov bx, 00304h ; bb 04 03 ; 0xf74e9 logo.c:38
+ mov es, ax ; 8e c0 ; 0xf74ec
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf74ee
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf74f1 logo.c:39
+ xor bl, bl ; 30 db ; 0xf74f4 logo.c:257
+ cmp bl, byte [bp-00eh] ; 3a 5e f2 ; 0xf74f6
+ jnc short 07558h ; 73 5d ; 0xf74f9
+ mov al, bl ; 88 d8 ; 0xf74fb logo.c:259
+ xor ah, ah ; 30 e4 ; 0xf74fd
+ mov si, ax ; 89 c6 ; 0xf74ff
+ add si, 00305h ; 81 c6 05 03 ; 0xf7501
+ mov es, di ; 8e c7 ; 0xf7505 logo.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf7507
+ mov bh, al ; 88 c7 ; 0xf750a logo.c:39
+ cmp AL, strict byte 00ch ; 3c 0c ; 0xf750c logo.c:262
+ jc short 07535h ; 72 25 ; 0xf750e
+ test cl, cl ; 84 c9 ; 0xf7510 logo.c:264
+ jne short 07521h ; 75 0d ; 0xf7512
+ push 009a7h ; 68 a7 09 ; 0xf7514 logo.c:266
+ push strict byte 00002h ; 6a 02 ; 0xf7517
+ call 018ffh ; e8 e3 a3 ; 0xf7519
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf751c
+ mov CL, strict byte 001h ; b1 01 ; 0xf751f logo.c:267
+ mov al, bl ; 88 d8 ; 0xf7521 logo.c:270
+ xor ah, ah ; 30 e4 ; 0xf7523
+ inc ax ; 40 ; 0xf7525
+ push ax ; 50 ; 0xf7526
+ push 009bch ; 68 bc 09 ; 0xf7527
+ push strict byte 00002h ; 6a 02 ; 0xf752a
+ call 018ffh ; e8 d0 a3 ; 0xf752c
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf752f
+ jmp near 075d5h ; e9 a0 00 ; 0xf7532 logo.c:273
+ cmp AL, strict byte 008h ; 3c 08 ; 0xf7535 logo.c:276
+ jc short 0754ch ; 72 13 ; 0xf7537
+ test ch, ch ; 84 ed ; 0xf7539 logo.c:278
+ jne short 0754ah ; 75 0d ; 0xf753b
+ push 009cfh ; 68 cf 09 ; 0xf753d logo.c:280
+ push strict byte 00002h ; 6a 02 ; 0xf7540
+ call 018ffh ; e8 ba a3 ; 0xf7542
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7545
+ mov CH, strict byte 001h ; b5 01 ; 0xf7548 logo.c:281
+ jmp short 07521h ; eb d5 ; 0xf754a logo.c:282
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf754c logo.c:291
+ jnc short 0756ch ; 73 1c ; 0xf754e
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf7550
+ je short 0755bh ; 74 05 ; 0xf7554
+ jmp short 0756ch ; eb 14 ; 0xf7556
+ jmp near 075dah ; e9 7f 00 ; 0xf7558
+ push 009e4h ; 68 e4 09 ; 0xf755b logo.c:293
+ push strict byte 00002h ; 6a 02 ; 0xf755e
+ call 018ffh ; e8 9c a3 ; 0xf7560
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7563
+ mov byte [bp-00ch], 001h ; c6 46 f4 01 ; 0xf7566 logo.c:294
+ jmp short 07582h ; eb 16 ; 0xf756a logo.c:296
+ cmp bh, 004h ; 80 ff 04 ; 0xf756c
+ jc short 07582h ; 72 11 ; 0xf756f
+ test cl, cl ; 84 c9 ; 0xf7571
+ jne short 07582h ; 75 0d ; 0xf7573
+ push 009f6h ; 68 f6 09 ; 0xf7575 logo.c:298
+ push strict byte 00002h ; 6a 02 ; 0xf7578
+ call 018ffh ; e8 82 a3 ; 0xf757a
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf757d
+ mov CL, strict byte 001h ; b1 01 ; 0xf7580 logo.c:299
+ mov al, bl ; 88 d8 ; 0xf7582 logo.c:302
+ xor ah, ah ; 30 e4 ; 0xf7584
+ inc ax ; 40 ; 0xf7586
+ push ax ; 50 ; 0xf7587
+ push 00a0ah ; 68 0a 0a ; 0xf7588
+ push strict byte 00002h ; 6a 02 ; 0xf758b
+ call 018ffh ; e8 6f a3 ; 0xf758d
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7590
+ cmp bh, 004h ; 80 ff 04 ; 0xf7593 logo.c:309
+ jc short 0759bh ; 72 03 ; 0xf7596
+ sub bh, 004h ; 80 ef 04 ; 0xf7598 logo.c:310
+ mov al, bh ; 88 f8 ; 0xf759b logo.c:312
+ xor ah, ah ; 30 e4 ; 0xf759d
+ cwd ; 99 ; 0xf759f
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf75a0
+ sar ax, 1 ; d1 f8 ; 0xf75a2
+ test ax, ax ; 85 c0 ; 0xf75a4
+ je short 075adh ; 74 05 ; 0xf75a6
+ push 00a14h ; 68 14 0a ; 0xf75a8 logo.c:313
+ jmp short 075b0h ; eb 03 ; 0xf75ab logo.c:314
+ push 00a1fh ; 68 1f 0a ; 0xf75ad logo.c:315
+ push strict byte 00002h ; 6a 02 ; 0xf75b0
+ call 018ffh ; e8 4a a3 ; 0xf75b2
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf75b5
+ mov al, bh ; 88 f8 ; 0xf75b8 logo.c:317
+ xor ah, ah ; 30 e4 ; 0xf75ba
+ cwd ; 99 ; 0xf75bc
+ mov si, strict word 00002h ; be 02 00 ; 0xf75bd
+ idiv si ; f7 fe ; 0xf75c0
+ test dx, dx ; 85 d2 ; 0xf75c2
+ je short 075cbh ; 74 05 ; 0xf75c4
+ push 00a28h ; 68 28 0a ; 0xf75c6 logo.c:318
+ jmp short 075ceh ; eb 03 ; 0xf75c9 logo.c:319
+ push 00a2eh ; 68 2e 0a ; 0xf75cb logo.c:320
+ push si ; 56 ; 0xf75ce
+ call 018ffh ; e8 2d a3 ; 0xf75cf
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf75d2
+ db 0feh, 0c3h
+ ; inc bl ; fe c3 ; 0xf75d5 logo.c:322
+ jmp near 074f6h ; e9 1c ff ; 0xf75d7
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf75da logo.c:324
+ jne short 075f3h ; 75 13 ; 0xf75de
+ test cl, cl ; 84 c9 ; 0xf75e0
+ jne short 075f3h ; 75 0f ; 0xf75e2
+ test ch, ch ; 84 ed ; 0xf75e4
+ jne short 075f3h ; 75 0b ; 0xf75e6
+ push 00a35h ; 68 35 0a ; 0xf75e8 logo.c:327
+ push strict byte 00002h ; 6a 02 ; 0xf75eb
+ call 018ffh ; e8 0f a3 ; 0xf75ed
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf75f0
+ push 00a49h ; 68 49 0a ; 0xf75f3 logo.c:329
+ push strict byte 00002h ; 6a 02 ; 0xf75f6
+ call 018ffh ; e8 04 a3 ; 0xf75f8
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf75fb
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf75fe logo.c:330
+ pop di ; 5f ; 0xf7601
+ pop si ; 5e ; 0xf7602
+ pop dx ; 5a ; 0xf7603
+ pop cx ; 59 ; 0xf7604
+ pop bx ; 5b ; 0xf7605
+ pop bp ; 5d ; 0xf7606
+ retn ; c3 ; 0xf7607
+ ; disGetNextSymbol 0xf7608 LB 0x28c0 -> off=0x0 cb=0000000000000024 uValue=00000000000f6008 'get_boot_drive'
+get_boot_drive: ; 0xf7608 LB 0x24
+ push bx ; 53 ; 0xf7608 logo.c:332
+ push dx ; 52 ; 0xf7609
+ push bp ; 55 ; 0xf760a
+ mov bp, sp ; 89 e5 ; 0xf760b
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf760d logo.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf7610
+ mov es, dx ; 8e c2 ; 0xf7613
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf7615
+ mov bx, 00304h ; bb 04 03 ; 0xf7618 logo.c:38
+ mov es, dx ; 8e c2 ; 0xf761b
+ mov dl, byte [es:bx] ; 26 8a 17 ; 0xf761d
+ sub AL, strict byte 002h ; 2c 02 ; 0xf7620 logo.c:340
+ cmp al, dl ; 38 d0 ; 0xf7622 logo.c:342
+ jc short 07628h ; 72 02 ; 0xf7624
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf7626 logo.c:343
+ pop bp ; 5d ; 0xf7628 logo.c:347
+ pop dx ; 5a ; 0xf7629
+ pop bx ; 5b ; 0xf762a
+ retn ; c3 ; 0xf762b
+ ; disGetNextSymbol 0xf762c LB 0x289c -> off=0x0 cb=0000000000000252 uValue=00000000000f602c 'show_logo'
+show_logo: ; 0xf762c LB 0x252
+ push bp ; 55 ; 0xf762c logo.c:349
+ mov bp, sp ; 89 e5 ; 0xf762d
+ push bx ; 53 ; 0xf762f
+ push cx ; 51 ; 0xf7630
+ push dx ; 52 ; 0xf7631
+ push si ; 56 ; 0xf7632
+ push di ; 57 ; 0xf7633
+ sub sp, strict byte 0000eh ; 83 ec 0e ; 0xf7634
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf7637 logo.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf763a
+ mov es, ax ; 8e c0 ; 0xf763d
+ mov si, word [es:bx] ; 26 8b 37 ; 0xf763f
+ mov byte [bp-00eh], 000h ; c6 46 f2 00 ; 0xf7642 logo.c:352
+ xor dx, dx ; 31 d2 ; 0xf7646 logo.c:356
+ mov AL, strict byte 034h ; b0 34 ; 0xf7648 logo.c:363
+ out strict byte 043h, AL ; e6 43 ; 0xf764a
+ mov AL, strict byte 0d3h ; b0 d3 ; 0xf764c
+ out strict byte 040h, AL ; e6 40 ; 0xf764e
+ mov AL, strict byte 048h ; b0 48 ; 0xf7650
+ out strict byte 040h, AL ; e6 40 ; 0xf7652
+ mov al, dl ; 88 d0 ; 0xf7654 logo.c:366
+ xor ah, ah ; 30 e4 ; 0xf7656
+ call 074b6h ; e8 5b fe ; 0xf7658
+ cmp ax, 066bbh ; 3d bb 66 ; 0xf765b logo.c:367
+ jne short 07672h ; 75 12 ; 0xf765e
+ push SS ; 16 ; 0xf7660 logo.c:371
+ pop ES ; 07 ; 0xf7661
+ lea di, [bp-018h] ; 8d 7e e8 ; 0xf7662
+ mov ax, 04f03h ; b8 03 4f ; 0xf7665
+ int 010h ; cd 10 ; 0xf7668
+ mov word [es:di], bx ; 26 89 1d ; 0xf766a
+ cmp ax, strict word 0004fh ; 3d 4f 00 ; 0xf766d
+ je short 07675h ; 74 03 ; 0xf7670
+ jmp near 0775dh ; e9 e8 00 ; 0xf7672 logo.c:372
+ mov al, dl ; 88 d0 ; 0xf7675 logo.c:375
+ add AL, strict byte 004h ; 04 04 ; 0xf7677
+ xor ah, ah ; 30 e4 ; 0xf7679
+ call 074a0h ; e8 22 fe ; 0xf767b
+ mov cl, al ; 88 c1 ; 0xf767e
+ mov byte [bp-014h], al ; 88 46 ec ; 0xf7680
+ mov al, dl ; 88 d0 ; 0xf7683 logo.c:376
+ add AL, strict byte 005h ; 04 05 ; 0xf7685
+ xor ah, ah ; 30 e4 ; 0xf7687
+ call 074a0h ; e8 14 fe ; 0xf7689
+ mov dh, al ; 88 c6 ; 0xf768c
+ mov byte [bp-012h], al ; 88 46 ee ; 0xf768e
+ mov al, dl ; 88 d0 ; 0xf7691 logo.c:377
+ add AL, strict byte 002h ; 04 02 ; 0xf7693
+ xor ah, ah ; 30 e4 ; 0xf7695
+ call 074b6h ; e8 1c fe ; 0xf7697
+ mov bx, ax ; 89 c3 ; 0xf769a
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf769c
+ mov al, dl ; 88 d0 ; 0xf769f logo.c:378
+ add AL, strict byte 006h ; 04 06 ; 0xf76a1
+ xor ah, ah ; 30 e4 ; 0xf76a3
+ call 074a0h ; e8 f8 fd ; 0xf76a5
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf76a8
+ test cl, cl ; 84 c9 ; 0xf76ab logo.c:381
+ jne short 076b7h ; 75 08 ; 0xf76ad
+ test dh, dh ; 84 f6 ; 0xf76af
+ jne short 076b7h ; 75 04 ; 0xf76b1
+ test bx, bx ; 85 db ; 0xf76b3
+ je short 07672h ; 74 bb ; 0xf76b5
+ mov BH, strict byte 020h ; b7 20 ; 0xf76b7 logo.c:385
+ mov dx, 001e0h ; ba e0 01 ; 0xf76b9
+ mov cx, 00280h ; b9 80 02 ; 0xf76bc
+ mov ax, 05642h ; b8 42 56 ; 0xf76bf
+ mov BL, strict byte 000h ; b3 00 ; 0xf76c2
+ int 010h ; cd 10 ; 0xf76c4
+ cmp ax, strict word 0004fh ; 3d 4f 00 ; 0xf76c6 logo.c:387
+ je short 076d3h ; 74 08 ; 0xf76c9
+ mov bx, 00142h ; bb 42 01 ; 0xf76cb logo.c:388
+ mov ax, 04f02h ; b8 02 4f ; 0xf76ce
+ int 010h ; cd 10 ; 0xf76d1
+ cmp byte [bp-014h], 000h ; 80 7e ec 00 ; 0xf76d3 logo.c:390
+ je short 076feh ; 74 25 ; 0xf76d7
+ xor bx, bx ; 31 db ; 0xf76d9 logo.c:392
+ jmp short 076e3h ; eb 06 ; 0xf76db
+ inc bx ; 43 ; 0xf76dd logo.c:394
+ cmp bx, strict byte 00010h ; 83 fb 10 ; 0xf76de
+ jnbe short 07705h ; 77 22 ; 0xf76e1
+ mov ax, bx ; 89 d8 ; 0xf76e3
+ or ah, 002h ; 80 cc 02 ; 0xf76e5
+ mov dx, 003b8h ; ba b8 03 ; 0xf76e8
+ out DX, ax ; ef ; 0xf76eb
+ xor dx, dx ; 31 d2 ; 0xf76ec
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf76ee
+ call 073e9h ; e8 f5 fc ; 0xf76f1
+ cmp AL, strict byte 086h ; 3c 86 ; 0xf76f4
+ jne short 076ddh ; 75 e5 ; 0xf76f6
+ mov byte [bp-00eh], 001h ; c6 46 f2 01 ; 0xf76f8
+ jmp short 07705h ; eb 07 ; 0xf76fc
+ mov ax, 00210h ; b8 10 02 ; 0xf76fe logo.c:404
+ mov dx, 003b8h ; ba b8 03 ; 0xf7701
+ out DX, ax ; ef ; 0xf7704
+ cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xf7705 logo.c:407
+ jne short 0771fh ; 75 14 ; 0xf7709
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf770b logo.c:409
+ shr ax, 004h ; c1 e8 04 ; 0xf770e
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf7711
+ call 073e9h ; e8 d2 fc ; 0xf7714
+ cmp AL, strict byte 086h ; 3c 86 ; 0xf7717 logo.c:410
+ jne short 0771fh ; 75 04 ; 0xf7719
+ mov byte [bp-00eh], 001h ; c6 46 f2 01 ; 0xf771b logo.c:411
+ cmp byte [bp-012h], 000h ; 80 7e ee 00 ; 0xf771f logo.c:415
+ je short 07750h ; 74 2b ; 0xf7723
+ cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xf7725
+ jne short 07750h ; 75 25 ; 0xf7729
+ mov bx, strict word 00010h ; bb 10 00 ; 0xf772b logo.c:417
+ jmp short 07735h ; eb 05 ; 0xf772e
+ dec bx ; 4b ; 0xf7730 logo.c:419
+ test bx, bx ; 85 db ; 0xf7731
+ jbe short 0775dh ; 76 28 ; 0xf7733
+ mov ax, bx ; 89 d8 ; 0xf7735
+ or ah, 002h ; 80 cc 02 ; 0xf7737
+ mov dx, 003b8h ; ba b8 03 ; 0xf773a
+ out DX, ax ; ef ; 0xf773d
+ xor dx, dx ; 31 d2 ; 0xf773e
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf7740
+ call 073e9h ; e8 a3 fc ; 0xf7743
+ cmp AL, strict byte 086h ; 3c 86 ; 0xf7746
+ jne short 07730h ; 75 e6 ; 0xf7748
+ mov byte [bp-00eh], 001h ; c6 46 f2 01 ; 0xf774a
+ jmp short 0775dh ; eb 0d ; 0xf774e
+ cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xf7750 logo.c:428
+ jne short 0775dh ; 75 07 ; 0xf7754
+ mov ax, 00200h ; b8 00 02 ; 0xf7756 logo.c:429
+ mov dx, 003b8h ; ba b8 03 ; 0xf7759
+ out DX, ax ; ef ; 0xf775c
+ mov bx, 0037dh ; bb 7d 03 ; 0xf775d logo.c:43
+ mov es, si ; 8e c6 ; 0xf7760
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf7762
+ mov AL, strict byte 003h ; b0 03 ; 0xf7766 logo.c:437
+ mov AH, strict byte 000h ; b4 00 ; 0xf7768
+ int 010h ; cd 10 ; 0xf776a
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf776c logo.c:440
+ je short 07786h ; 74 14 ; 0xf7770
+ cmp byte [bp-014h], 000h ; 80 7e ec 00 ; 0xf7772 logo.c:443
+ jne short 077b1h ; 75 39 ; 0xf7776
+ cmp byte [bp-012h], 000h ; 80 7e ee 00 ; 0xf7778
+ jne short 077b1h ; 75 33 ; 0xf777c
+ cmp word [bp-016h], strict byte 00000h ; 83 7e ea 00 ; 0xf777e
+ je short 07789h ; 74 05 ; 0xf7782
+ jmp short 077b1h ; eb 2b ; 0xf7784
+ jmp near 07861h ; e9 d8 00 ; 0xf7786
+ cmp byte [bp-00ch], 002h ; 80 7e f4 02 ; 0xf7789 logo.c:445
+ jne short 0779ah ; 75 0b ; 0xf778d
+ push 00a4bh ; 68 4b 0a ; 0xf778f logo.c:446
+ push strict byte 00002h ; 6a 02 ; 0xf7792
+ call 018ffh ; e8 68 a1 ; 0xf7794
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7797
+ cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xf779a logo.c:449
+ jne short 077b1h ; 75 11 ; 0xf779e
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf77a0 logo.c:452
+ mov ax, 000c0h ; b8 c0 00 ; 0xf77a3
+ call 073e9h ; e8 40 fc ; 0xf77a6
+ cmp AL, strict byte 086h ; 3c 86 ; 0xf77a9 logo.c:453
+ jne short 077b1h ; 75 04 ; 0xf77ab
+ mov byte [bp-00eh], 001h ; c6 46 f2 01 ; 0xf77ad logo.c:454
+ cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xf77b1 logo.c:459
+ je short 07786h ; 74 cf ; 0xf77b5
+ mov byte [bp-010h], 000h ; c6 46 f0 00 ; 0xf77b7 logo.c:461
+ mov ax, 00100h ; b8 00 01 ; 0xf77bb logo.c:464
+ mov cx, 01000h ; b9 00 10 ; 0xf77be
+ int 010h ; cd 10 ; 0xf77c1
+ mov ax, 00700h ; b8 00 07 ; 0xf77c3
+ mov BH, strict byte 007h ; b7 07 ; 0xf77c6
+ db 033h, 0c9h
+ ; xor cx, cx ; 33 c9 ; 0xf77c8
+ mov dx, 0184fh ; ba 4f 18 ; 0xf77ca
+ int 010h ; cd 10 ; 0xf77cd
+ mov ax, 00200h ; b8 00 02 ; 0xf77cf
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xf77d2
+ db 033h, 0d2h
+ ; xor dx, dx ; 33 d2 ; 0xf77d4
+ int 010h ; cd 10 ; 0xf77d6
+ push 00a6dh ; 68 6d 0a ; 0xf77d8 logo.c:467
+ push strict byte 00002h ; 6a 02 ; 0xf77db
+ call 018ffh ; e8 1f a1 ; 0xf77dd
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf77e0
+ call 074cah ; e8 e4 fc ; 0xf77e3 logo.c:468
+ push 00ab1h ; 68 b1 0a ; 0xf77e6 logo.c:469
+ push strict byte 00002h ; 6a 02 ; 0xf77e9
+ call 018ffh ; e8 11 a1 ; 0xf77eb
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf77ee
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf77f1 logo.c:478
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf77f4
+ call 073e9h ; e8 ef fb ; 0xf77f7
+ mov bl, al ; 88 c3 ; 0xf77fa
+ test al, al ; 84 c0 ; 0xf77fc logo.c:479
+ je short 077f1h ; 74 f1 ; 0xf77fe
+ cmp AL, strict byte 030h ; 3c 30 ; 0xf7800 logo.c:481
+ je short 07850h ; 74 4c ; 0xf7802
+ cmp bl, 002h ; 80 fb 02 ; 0xf7804 logo.c:488
+ jc short 07829h ; 72 20 ; 0xf7807
+ cmp bl, 009h ; 80 fb 09 ; 0xf7809
+ jnbe short 07829h ; 77 1b ; 0xf780c
+ mov al, bl ; 88 d8 ; 0xf780e logo.c:490
+ xor ah, ah ; 30 e4 ; 0xf7810
+ call 07608h ; e8 f3 fd ; 0xf7812
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xf7815 logo.c:497
+ jne short 0781bh ; 75 02 ; 0xf7817
+ jmp short 077f1h ; eb d6 ; 0xf7819 logo.c:498
+ mov bx, 0037ch ; bb 7c 03 ; 0xf781b logo.c:43
+ mov es, si ; 8e c6 ; 0xf781e
+ mov byte [es:bx], al ; 26 88 07 ; 0xf7820
+ mov byte [bp-010h], 002h ; c6 46 f0 02 ; 0xf7823 logo.c:501
+ jmp short 07850h ; eb 27 ; 0xf7827 logo.c:502
+ cmp bl, 02eh ; 80 fb 2e ; 0xf7829 logo.c:505
+ je short 0783eh ; 74 10 ; 0xf782c
+ cmp bl, 026h ; 80 fb 26 ; 0xf782e
+ je short 07844h ; 74 11 ; 0xf7831
+ cmp bl, 021h ; 80 fb 21 ; 0xf7833
+ jne short 0784ah ; 75 12 ; 0xf7836
+ mov byte [bp-010h], 001h ; c6 46 f0 01 ; 0xf7838 logo.c:509
+ jmp short 07850h ; eb 12 ; 0xf783c logo.c:510
+ mov byte [bp-010h], 003h ; c6 46 f0 03 ; 0xf783e logo.c:513
+ jmp short 07850h ; eb 0c ; 0xf7842 logo.c:514
+ mov byte [bp-010h], 004h ; c6 46 f0 04 ; 0xf7844 logo.c:517
+ jmp short 07850h ; eb 06 ; 0xf7848 logo.c:518
+ cmp byte [bp-010h], 000h ; 80 7e f0 00 ; 0xf784a logo.c:521
+ je short 077f1h ; 74 a1 ; 0xf784e
+ mov bx, 0037dh ; bb 7d 03 ; 0xf7850 logo.c:43
+ mov es, si ; 8e c6 ; 0xf7853
+ mov al, byte [bp-010h] ; 8a 46 f0 ; 0xf7855
+ mov byte [es:bx], al ; 26 88 07 ; 0xf7858
+ mov AL, strict byte 003h ; b0 03 ; 0xf785b logo.c:528
+ mov AH, strict byte 000h ; b4 00 ; 0xf785d
+ int 010h ; cd 10 ; 0xf785f
+ mov AL, strict byte 034h ; b0 34 ; 0xf7861 logo.c:533
+ out strict byte 043h, AL ; e6 43 ; 0xf7863
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf7865
+ out strict byte 040h, AL ; e6 40 ; 0xf7867
+ out strict byte 040h, AL ; e6 40 ; 0xf7869
+ push bp ; 55 ; 0xf786b
+ push DS ; 1e ; 0xf786c
+ mov ds, ax ; 8e d8 ; 0xf786d
+ call 0edbfh ; e8 4d 75 ; 0xf786f
+ pop DS ; 1f ; 0xf7872
+ pop bp ; 5d ; 0xf7873
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf7874 logo.c:536
+ pop di ; 5f ; 0xf7877
+ pop si ; 5e ; 0xf7878
+ pop dx ; 5a ; 0xf7879
+ pop cx ; 59 ; 0xf787a
+ pop bx ; 5b ; 0xf787b
+ pop bp ; 5d ; 0xf787c
+ retn ; c3 ; 0xf787d
+ ; disGetNextSymbol 0xf787e LB 0x264a -> off=0x0 cb=000000000000006b uValue=00000000000f627e 'delay_boot'
+delay_boot: ; 0xf787e LB 0x6b
+ push bp ; 55 ; 0xf787e logo.c:539
+ mov bp, sp ; 89 e5 ; 0xf787f
+ push bx ; 53 ; 0xf7881
+ push cx ; 51 ; 0xf7882
+ push dx ; 52 ; 0xf7883
+ push si ; 56 ; 0xf7884
+ push di ; 57 ; 0xf7885
+ mov dx, ax ; 89 c2 ; 0xf7886
+ test ax, ax ; 85 c0 ; 0xf7888 logo.c:543
+ je short 078dfh ; 74 53 ; 0xf788a
+ mov AL, strict byte 034h ; b0 34 ; 0xf788c logo.c:547
+ out strict byte 043h, AL ; e6 43 ; 0xf788e
+ mov AL, strict byte 0d3h ; b0 d3 ; 0xf7890
+ out strict byte 040h, AL ; e6 40 ; 0xf7892
+ mov AL, strict byte 048h ; b0 48 ; 0xf7894
+ out strict byte 040h, AL ; e6 40 ; 0xf7896
+ push dx ; 52 ; 0xf7898 logo.c:549
+ push 00afbh ; 68 fb 0a ; 0xf7899
+ push strict byte 00002h ; 6a 02 ; 0xf789c
+ call 018ffh ; e8 5e a0 ; 0xf789e
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf78a1
+ mov bx, dx ; 89 d3 ; 0xf78a4 logo.c:550
+ test bx, bx ; 85 db ; 0xf78a6
+ jbe short 078c1h ; 76 17 ; 0xf78a8
+ push bx ; 53 ; 0xf78aa logo.c:552
+ push 00b19h ; 68 19 0b ; 0xf78ab
+ push strict byte 00002h ; 6a 02 ; 0xf78ae
+ call 018ffh ; e8 4c a0 ; 0xf78b0
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf78b3
+ xor dx, dx ; 31 d2 ; 0xf78b6 logo.c:553
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf78b8
+ call 073e9h ; e8 2b fb ; 0xf78bb
+ dec bx ; 4b ; 0xf78be logo.c:554
+ jmp short 078a6h ; eb e5 ; 0xf78bf
+ push 00a49h ; 68 49 0a ; 0xf78c1 logo.c:555
+ push strict byte 00002h ; 6a 02 ; 0xf78c4
+ call 018ffh ; e8 36 a0 ; 0xf78c6
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf78c9
+ mov AL, strict byte 034h ; b0 34 ; 0xf78cc logo.c:557
+ out strict byte 043h, AL ; e6 43 ; 0xf78ce
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf78d0
+ out strict byte 040h, AL ; e6 40 ; 0xf78d2
+ out strict byte 040h, AL ; e6 40 ; 0xf78d4
+ push bp ; 55 ; 0xf78d6
+ push DS ; 1e ; 0xf78d7
+ mov ds, ax ; 8e d8 ; 0xf78d8
+ call 0edbfh ; e8 e2 74 ; 0xf78da
+ pop DS ; 1f ; 0xf78dd
+ pop bp ; 5d ; 0xf78de
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf78df logo.c:558
+ pop di ; 5f ; 0xf78e2
+ pop si ; 5e ; 0xf78e3
+ pop dx ; 5a ; 0xf78e4
+ pop cx ; 59 ; 0xf78e5
+ pop bx ; 5b ; 0xf78e6
+ pop bp ; 5d ; 0xf78e7
+ retn ; c3 ; 0xf78e8
+ ; disGetNextSymbol 0xf78e9 LB 0x25df -> off=0x0 cb=00000000000000d5 uValue=00000000000f62e9 'scsi_cmd_data_in'
+scsi_cmd_data_in: ; 0xf78e9 LB 0xd5
+ push bp ; 55 ; 0xf78e9 scsi.c:99
+ mov bp, sp ; 89 e5 ; 0xf78ea
+ push si ; 56 ; 0xf78ec
+ push di ; 57 ; 0xf78ed
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf78ee
+ mov si, ax ; 89 c6 ; 0xf78f1
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf78f3
+ mov word [bp-00ah], bx ; 89 5e f6 ; 0xf78f6
+ mov word [bp-008h], cx ; 89 4e f8 ; 0xf78f9
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf78fc
+ mov dx, si ; 89 f2 ; 0xf78ff scsi.c:107
+ in AL, DX ; ec ; 0xf7901
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7902
+ test AL, strict byte 001h ; a8 01 ; 0xf7904 scsi.c:108
+ jne short 078ffh ; 75 f7 ; 0xf7906
+ mov al, byte [bp+004h] ; 8a 46 04 ; 0xf7908 scsi.c:110
+ cmp AL, strict byte 010h ; 3c 10 ; 0xf790b
+ jne short 07913h ; 75 04 ; 0xf790d
+ xor ax, ax ; 31 c0 ; 0xf790f
+ jmp short 07915h ; eb 02 ; 0xf7911
+ xor ah, ah ; 30 e4 ; 0xf7913
+ mov di, ax ; 89 c7 ; 0xf7915
+ mov ax, bx ; 89 d8 ; 0xf7917
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf7919
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf791c
+ shr dx, 1 ; d1 ea ; 0xf791f
+ rcr ax, 1 ; d1 d8 ; 0xf7921
+ loop 0791fh ; e2 fa ; 0xf7923
+ mov cx, ax ; 89 c1 ; 0xf7925
+ and cx, 000f0h ; 81 e1 f0 00 ; 0xf7927
+ or cx, di ; 09 f9 ; 0xf792b
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf792d scsi.c:111
+ mov dx, si ; 89 f2 ; 0xf7930
+ out DX, AL ; ee ; 0xf7932
+ xor al, al ; 30 c0 ; 0xf7933 scsi.c:112
+ out DX, AL ; ee ; 0xf7935
+ mov al, cl ; 88 c8 ; 0xf7936 scsi.c:113
+ out DX, AL ; ee ; 0xf7938
+ mov al, bl ; 88 d8 ; 0xf7939 scsi.c:114
+ out DX, AL ; ee ; 0xf793b
+ mov ax, bx ; 89 d8 ; 0xf793c scsi.c:115
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf793e
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf7941
+ shr dx, 1 ; d1 ea ; 0xf7944
+ rcr ax, 1 ; d1 d8 ; 0xf7946
+ loop 07944h ; e2 fa ; 0xf7948
+ mov dx, si ; 89 f2 ; 0xf794a
+ out DX, AL ; ee ; 0xf794c
+ xor cx, cx ; 31 c9 ; 0xf794d scsi.c:116
+ mov al, byte [bp+004h] ; 8a 46 04 ; 0xf794f
+ xor ah, ah ; 30 e4 ; 0xf7952
+ cmp cx, ax ; 39 c1 ; 0xf7954
+ jnc short 07966h ; 73 0e ; 0xf7956
+ les di, [bp-00ah] ; c4 7e f6 ; 0xf7958 scsi.c:117
+ add di, cx ; 01 cf ; 0xf795b
+ mov al, byte [es:di] ; 26 8a 05 ; 0xf795d
+ mov dx, si ; 89 f2 ; 0xf7960
+ out DX, AL ; ee ; 0xf7962
+ inc cx ; 41 ; 0xf7963
+ jmp short 0794fh ; eb e9 ; 0xf7964
+ mov dx, si ; 89 f2 ; 0xf7966 scsi.c:121
+ in AL, DX ; ec ; 0xf7968
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7969
+ test AL, strict byte 001h ; a8 01 ; 0xf796b scsi.c:122
+ jne short 07966h ; 75 f7 ; 0xf796d
+ test AL, strict byte 002h ; a8 02 ; 0xf796f scsi.c:125
+ je short 07981h ; 74 0e ; 0xf7971
+ lea dx, [si+003h] ; 8d 54 03 ; 0xf7973 scsi.c:126
+ xor al, al ; 30 c0 ; 0xf7976
+ out DX, AL ; ee ; 0xf7978
+ in AL, DX ; ec ; 0xf7979 scsi.c:128
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf797a
+ mov di, strict word 00004h ; bf 04 00 ; 0xf797c scsi.c:130
+ jmp short 079b3h ; eb 32 ; 0xf797f
+ lea dx, [si+001h] ; 8d 54 01 ; 0xf7981 scsi.c:136
+ cmp word [bp+00ch], strict byte 00000h ; 83 7e 0c 00 ; 0xf7984
+ jne short 07990h ; 75 06 ; 0xf7988
+ cmp bx, 08000h ; 81 fb 00 80 ; 0xf798a
+ jbe short 079aah ; 76 1a ; 0xf798e
+ mov cx, 08000h ; b9 00 80 ; 0xf7990 scsi.c:138
+ les di, [bp+006h] ; c4 7e 06 ; 0xf7993
+ rep insb ; f3 6c ; 0xf7996
+ add bx, 08000h ; 81 c3 00 80 ; 0xf7998 scsi.c:139
+ adc word [bp+00ch], strict byte 0ffffh ; 83 56 0c ff ; 0xf799c
+ mov ax, es ; 8c c0 ; 0xf79a0
+ add ax, 00800h ; 05 00 08 ; 0xf79a2
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf79a5
+ jmp short 07981h ; eb d7 ; 0xf79a8 scsi.c:141
+ mov cx, bx ; 89 d9 ; 0xf79aa scsi.c:144
+ les di, [bp+006h] ; c4 7e 06 ; 0xf79ac
+ rep insb ; f3 6c ; 0xf79af
+ xor di, di ; 31 ff ; 0xf79b1 scsi.c:146
+ mov ax, di ; 89 f8 ; 0xf79b3 scsi.c:147
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf79b5
+ pop di ; 5f ; 0xf79b8
+ pop si ; 5e ; 0xf79b9
+ pop bp ; 5d ; 0xf79ba
+ retn 0000ah ; c2 0a 00 ; 0xf79bb
+ ; disGetNextSymbol 0xf79be LB 0x250a -> off=0x0 cb=00000000000000d5 uValue=00000000000f63be 'scsi_cmd_data_out'
+scsi_cmd_data_out: ; 0xf79be LB 0xd5
+ push bp ; 55 ; 0xf79be scsi.c:149
+ mov bp, sp ; 89 e5 ; 0xf79bf
+ push si ; 56 ; 0xf79c1
+ push di ; 57 ; 0xf79c2
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf79c3
+ mov di, ax ; 89 c7 ; 0xf79c6
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf79c8
+ mov word [bp-00ah], bx ; 89 5e f6 ; 0xf79cb
+ mov word [bp-008h], cx ; 89 4e f8 ; 0xf79ce
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf79d1
+ mov dx, di ; 89 fa ; 0xf79d4 scsi.c:157
+ in AL, DX ; ec ; 0xf79d6
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf79d7
+ test AL, strict byte 001h ; a8 01 ; 0xf79d9 scsi.c:158
+ jne short 079d4h ; 75 f7 ; 0xf79db
+ mov al, byte [bp+004h] ; 8a 46 04 ; 0xf79dd scsi.c:161
+ cmp AL, strict byte 010h ; 3c 10 ; 0xf79e0
+ jne short 079e8h ; 75 04 ; 0xf79e2
+ xor ax, ax ; 31 c0 ; 0xf79e4
+ jmp short 079eah ; eb 02 ; 0xf79e6
+ xor ah, ah ; 30 e4 ; 0xf79e8
+ mov si, ax ; 89 c6 ; 0xf79ea
+ mov ax, bx ; 89 d8 ; 0xf79ec
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf79ee
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf79f1
+ shr dx, 1 ; d1 ea ; 0xf79f4
+ rcr ax, 1 ; d1 d8 ; 0xf79f6
+ loop 079f4h ; e2 fa ; 0xf79f8
+ mov cx, ax ; 89 c1 ; 0xf79fa
+ and cx, 000f0h ; 81 e1 f0 00 ; 0xf79fc
+ or cx, si ; 09 f1 ; 0xf7a00
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7a02 scsi.c:162
+ mov dx, di ; 89 fa ; 0xf7a05
+ out DX, AL ; ee ; 0xf7a07
+ mov AL, strict byte 001h ; b0 01 ; 0xf7a08 scsi.c:163
+ out DX, AL ; ee ; 0xf7a0a
+ mov al, cl ; 88 c8 ; 0xf7a0b scsi.c:164
+ out DX, AL ; ee ; 0xf7a0d
+ mov al, bl ; 88 d8 ; 0xf7a0e scsi.c:165
+ out DX, AL ; ee ; 0xf7a10
+ mov ax, bx ; 89 d8 ; 0xf7a11 scsi.c:166
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf7a13
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf7a16
+ shr dx, 1 ; d1 ea ; 0xf7a19
+ rcr ax, 1 ; d1 d8 ; 0xf7a1b
+ loop 07a19h ; e2 fa ; 0xf7a1d
+ mov dx, di ; 89 fa ; 0xf7a1f
+ out DX, AL ; ee ; 0xf7a21
+ xor cx, cx ; 31 c9 ; 0xf7a22 scsi.c:167
+ mov al, byte [bp+004h] ; 8a 46 04 ; 0xf7a24
+ xor ah, ah ; 30 e4 ; 0xf7a27
+ cmp cx, ax ; 39 c1 ; 0xf7a29
+ jnc short 07a3bh ; 73 0e ; 0xf7a2b
+ les si, [bp-00ah] ; c4 76 f6 ; 0xf7a2d scsi.c:168
+ add si, cx ; 01 ce ; 0xf7a30
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf7a32
+ mov dx, di ; 89 fa ; 0xf7a35
+ out DX, AL ; ee ; 0xf7a37
+ inc cx ; 41 ; 0xf7a38
+ jmp short 07a24h ; eb e9 ; 0xf7a39
+ lea dx, [di+001h] ; 8d 55 01 ; 0xf7a3b scsi.c:173
+ cmp word [bp+00ch], strict byte 00000h ; 83 7e 0c 00 ; 0xf7a3e
+ jne short 07a4ah ; 75 06 ; 0xf7a42
+ cmp bx, 08000h ; 81 fb 00 80 ; 0xf7a44
+ jbe short 07a65h ; 76 1b ; 0xf7a48
+ mov cx, 08000h ; b9 00 80 ; 0xf7a4a scsi.c:175
+ les si, [bp+006h] ; c4 76 06 ; 0xf7a4d
+ db 0f3h, 026h, 06eh
+ ; rep es outsb ; f3 26 6e ; 0xf7a50
+ add bx, 08000h ; 81 c3 00 80 ; 0xf7a53 scsi.c:176
+ adc word [bp+00ch], strict byte 0ffffh ; 83 56 0c ff ; 0xf7a57
+ mov ax, es ; 8c c0 ; 0xf7a5b
+ add ax, 00800h ; 05 00 08 ; 0xf7a5d
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf7a60
+ jmp short 07a3bh ; eb d6 ; 0xf7a63 scsi.c:178
+ mov cx, bx ; 89 d9 ; 0xf7a65 scsi.c:181
+ les si, [bp+006h] ; c4 76 06 ; 0xf7a67
+ db 0f3h, 026h, 06eh
+ ; rep es outsb ; f3 26 6e ; 0xf7a6a
+ mov dx, di ; 89 fa ; 0xf7a6d scsi.c:185
+ in AL, DX ; ec ; 0xf7a6f
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7a70
+ test AL, strict byte 001h ; a8 01 ; 0xf7a72 scsi.c:186
+ jne short 07a6dh ; 75 f7 ; 0xf7a74
+ test AL, strict byte 002h ; a8 02 ; 0xf7a76 scsi.c:189
+ je short 07a88h ; 74 0e ; 0xf7a78
+ lea dx, [di+003h] ; 8d 55 03 ; 0xf7a7a scsi.c:190
+ xor al, al ; 30 c0 ; 0xf7a7d
+ out DX, AL ; ee ; 0xf7a7f
+ in AL, DX ; ec ; 0xf7a80 scsi.c:192
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7a81
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf7a83 scsi.c:194
+ jmp short 07a8ah ; eb 02 ; 0xf7a86
+ xor ax, ax ; 31 c0 ; 0xf7a88 scsi.c:197
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7a8a scsi.c:198
+ pop di ; 5f ; 0xf7a8d
+ pop si ; 5e ; 0xf7a8e
+ pop bp ; 5d ; 0xf7a8f
+ retn 0000ah ; c2 0a 00 ; 0xf7a90
+ ; disGetNextSymbol 0xf7a93 LB 0x2435 -> off=0x0 cb=00000000000000e0 uValue=00000000000f6493 'scsi_read_sectors'
+scsi_read_sectors: ; 0xf7a93 LB 0xe0
+ push bp ; 55 ; 0xf7a93 scsi.c:207
+ mov bp, sp ; 89 e5 ; 0xf7a94
+ push si ; 56 ; 0xf7a96
+ push di ; 57 ; 0xf7a97
+ sub sp, strict byte 00016h ; 83 ec 16 ; 0xf7a98
+ mov si, word [bp+004h] ; 8b 76 04 ; 0xf7a9b
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7a9e scsi.c:216
+ mov al, byte [es:si+00ch] ; 26 8a 44 0c ; 0xf7aa1
+ sub AL, strict byte 008h ; 2c 08 ; 0xf7aa5
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf7aa7
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf7aaa scsi.c:217
+ jbe short 07abfh ; 76 11 ; 0xf7aac
+ xor ah, ah ; 30 e4 ; 0xf7aae scsi.c:218
+ push ax ; 50 ; 0xf7ab0
+ push 00b1eh ; 68 1e 0b ; 0xf7ab1
+ push 00b30h ; 68 30 0b ; 0xf7ab4
+ push strict byte 00007h ; 6a 07 ; 0xf7ab7
+ call 018ffh ; e8 43 9e ; 0xf7ab9
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf7abc
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7abf scsi.c:220
+ mov di, word [es:si+00eh] ; 26 8b 7c 0e ; 0xf7ac2
+ mov word [bp-01ah], 00088h ; c7 46 e6 88 00 ; 0xf7ac6 scsi.c:223
+ mov ax, word [es:si+006h] ; 26 8b 44 06 ; 0xf7acb scsi.c:224
+ mov bx, word [es:si+004h] ; 26 8b 5c 04 ; 0xf7acf
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf7ad3
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf7ad7
+ xchg ah, al ; 86 c4 ; 0xf7ada
+ xchg bh, bl ; 86 df ; 0xf7adc
+ xchg ch, cl ; 86 cd ; 0xf7ade
+ xchg dh, dl ; 86 d6 ; 0xf7ae0
+ xchg dx, ax ; 92 ; 0xf7ae2
+ xchg bx, cx ; 87 cb ; 0xf7ae3
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf7ae5
+ mov word [bp-014h], bx ; 89 5e ec ; 0xf7ae8
+ mov word [bp-016h], cx ; 89 4e ea ; 0xf7aeb
+ mov word [bp-018h], dx ; 89 56 e8 ; 0xf7aee
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf7af1 scsi.c:225
+ mov ax, di ; 89 f8 ; 0xf7af5 scsi.c:226
+ xor dx, dx ; 31 d2 ; 0xf7af7
+ xchg ah, al ; 86 c4 ; 0xf7af9
+ xchg dh, dl ; 86 d6 ; 0xf7afb
+ xchg dx, ax ; 92 ; 0xf7afd
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf7afe
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf7b01
+ mov byte [bp-00bh], 000h ; c6 46 f5 00 ; 0xf7b04 scsi.c:227
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7b08 scsi.c:230
+ xor ah, ah ; 30 e4 ; 0xf7b0b
+ sal ax, 002h ; c1 e0 02 ; 0xf7b0d
+ mov bx, si ; 89 f3 ; 0xf7b10
+ add bx, ax ; 01 c3 ; 0xf7b12
+ mov ax, word [es:bx+0021ch] ; 26 8b 87 1c 02 ; 0xf7b14
+ mov dl, byte [es:bx+0021eh] ; 26 8a 97 1e 02 ; 0xf7b19 scsi.c:231
+ mov word [bp-00ah], di ; 89 7e f6 ; 0xf7b1e scsi.c:236
+ mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xf7b21
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf7b26
+ sal word [bp-00ah], 1 ; d1 66 f6 ; 0xf7b29
+ rcl word [bp-008h], 1 ; d1 56 f8 ; 0xf7b2c
+ loop 07b29h ; e2 f8 ; 0xf7b2f
+ push word [bp-008h] ; ff 76 f8 ; 0xf7b31
+ push word [bp-00ah] ; ff 76 f6 ; 0xf7b34
+ push word [es:si+00ah] ; 26 ff 74 0a ; 0xf7b37
+ push word [es:si+008h] ; 26 ff 74 08 ; 0xf7b3b
+ push strict byte 00010h ; 6a 10 ; 0xf7b3f
+ xor dh, dh ; 30 f6 ; 0xf7b41
+ mov cx, ss ; 8c d1 ; 0xf7b43
+ lea bx, [bp-01ah] ; 8d 5e e6 ; 0xf7b45
+ call 078e9h ; e8 9e fd ; 0xf7b48
+ mov ah, al ; 88 c4 ; 0xf7b4b
+ test al, al ; 84 c0 ; 0xf7b4d scsi.c:239
+ jne short 07b66h ; 75 15 ; 0xf7b4f
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7b51 scsi.c:241
+ mov word [es:si+018h], di ; 26 89 7c 18 ; 0xf7b54
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf7b58 scsi.c:242
+ mov word [es:si+01ah], dx ; 26 89 54 1a ; 0xf7b5b
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf7b5f
+ mov word [es:si+01ch], dx ; 26 89 54 1c ; 0xf7b62
+ mov al, ah ; 88 e0 ; 0xf7b66 scsi.c:246
+ xor ah, ah ; 30 e4 ; 0xf7b68
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7b6a scsi.c:247
+ pop di ; 5f ; 0xf7b6d
+ pop si ; 5e ; 0xf7b6e
+ pop bp ; 5d ; 0xf7b6f
+ retn 00004h ; c2 04 00 ; 0xf7b70
+ ; disGetNextSymbol 0xf7b73 LB 0x2355 -> off=0x0 cb=00000000000000e0 uValue=00000000000f6573 'scsi_write_sectors'
+scsi_write_sectors: ; 0xf7b73 LB 0xe0
+ push bp ; 55 ; 0xf7b73 scsi.c:256
+ mov bp, sp ; 89 e5 ; 0xf7b74
+ push si ; 56 ; 0xf7b76
+ push di ; 57 ; 0xf7b77
+ sub sp, strict byte 00016h ; 83 ec 16 ; 0xf7b78
+ mov si, word [bp+004h] ; 8b 76 04 ; 0xf7b7b
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7b7e scsi.c:265
+ mov al, byte [es:si+00ch] ; 26 8a 44 0c ; 0xf7b81
+ sub AL, strict byte 008h ; 2c 08 ; 0xf7b85
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf7b87
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf7b8a scsi.c:266
+ jbe short 07b9fh ; 76 11 ; 0xf7b8c
+ xor ah, ah ; 30 e4 ; 0xf7b8e scsi.c:267
+ push ax ; 50 ; 0xf7b90
+ push 00b4fh ; 68 4f 0b ; 0xf7b91
+ push 00b30h ; 68 30 0b ; 0xf7b94
+ push strict byte 00007h ; 6a 07 ; 0xf7b97
+ call 018ffh ; e8 63 9d ; 0xf7b99
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf7b9c
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7b9f scsi.c:269
+ mov di, word [es:si+00eh] ; 26 8b 7c 0e ; 0xf7ba2
+ mov word [bp-01ah], 0008ah ; c7 46 e6 8a 00 ; 0xf7ba6 scsi.c:272
+ mov ax, word [es:si+006h] ; 26 8b 44 06 ; 0xf7bab scsi.c:273
+ mov bx, word [es:si+004h] ; 26 8b 5c 04 ; 0xf7baf
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf7bb3
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf7bb7
+ xchg ah, al ; 86 c4 ; 0xf7bba
+ xchg bh, bl ; 86 df ; 0xf7bbc
+ xchg ch, cl ; 86 cd ; 0xf7bbe
+ xchg dh, dl ; 86 d6 ; 0xf7bc0
+ xchg dx, ax ; 92 ; 0xf7bc2
+ xchg bx, cx ; 87 cb ; 0xf7bc3
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf7bc5
+ mov word [bp-014h], bx ; 89 5e ec ; 0xf7bc8
+ mov word [bp-016h], cx ; 89 4e ea ; 0xf7bcb
+ mov word [bp-018h], dx ; 89 56 e8 ; 0xf7bce
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf7bd1 scsi.c:274
+ mov ax, di ; 89 f8 ; 0xf7bd5 scsi.c:275
+ xor dx, dx ; 31 d2 ; 0xf7bd7
+ xchg ah, al ; 86 c4 ; 0xf7bd9
+ xchg dh, dl ; 86 d6 ; 0xf7bdb
+ xchg dx, ax ; 92 ; 0xf7bdd
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf7bde
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf7be1
+ mov byte [bp-00bh], 000h ; c6 46 f5 00 ; 0xf7be4 scsi.c:276
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7be8 scsi.c:278
+ xor ah, ah ; 30 e4 ; 0xf7beb
+ sal ax, 002h ; c1 e0 02 ; 0xf7bed
+ mov bx, si ; 89 f3 ; 0xf7bf0
+ add bx, ax ; 01 c3 ; 0xf7bf2
+ mov ax, word [es:bx+0021ch] ; 26 8b 87 1c 02 ; 0xf7bf4
+ mov dl, byte [es:bx+0021eh] ; 26 8a 97 1e 02 ; 0xf7bf9 scsi.c:279
+ mov word [bp-00ah], di ; 89 7e f6 ; 0xf7bfe scsi.c:284
+ mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xf7c01
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf7c06
+ sal word [bp-00ah], 1 ; d1 66 f6 ; 0xf7c09
+ rcl word [bp-008h], 1 ; d1 56 f8 ; 0xf7c0c
+ loop 07c09h ; e2 f8 ; 0xf7c0f
+ push word [bp-008h] ; ff 76 f8 ; 0xf7c11
+ push word [bp-00ah] ; ff 76 f6 ; 0xf7c14
+ push word [es:si+00ah] ; 26 ff 74 0a ; 0xf7c17
+ push word [es:si+008h] ; 26 ff 74 08 ; 0xf7c1b
+ push strict byte 00010h ; 6a 10 ; 0xf7c1f
+ xor dh, dh ; 30 f6 ; 0xf7c21
+ mov cx, ss ; 8c d1 ; 0xf7c23
+ lea bx, [bp-01ah] ; 8d 5e e6 ; 0xf7c25
+ call 079beh ; e8 93 fd ; 0xf7c28
+ mov ah, al ; 88 c4 ; 0xf7c2b
+ test al, al ; 84 c0 ; 0xf7c2d scsi.c:287
+ jne short 07c46h ; 75 15 ; 0xf7c2f
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7c31 scsi.c:289
+ mov word [es:si+018h], di ; 26 89 7c 18 ; 0xf7c34
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf7c38 scsi.c:290
+ mov word [es:si+01ah], dx ; 26 89 54 1a ; 0xf7c3b
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf7c3f
+ mov word [es:si+01ch], dx ; 26 89 54 1c ; 0xf7c42
+ mov al, ah ; 88 e0 ; 0xf7c46 scsi.c:294
+ xor ah, ah ; 30 e4 ; 0xf7c48
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7c4a scsi.c:295
+ pop di ; 5f ; 0xf7c4d
+ pop si ; 5e ; 0xf7c4e
+ pop bp ; 5d ; 0xf7c4f
+ retn 00004h ; c2 04 00 ; 0xf7c50
+ ; disGetNextSymbol 0xf7c53 LB 0x2275 -> off=0x0 cb=0000000000000176 uValue=00000000000f6653 'scsi_cmd_packet'
+scsi_cmd_packet: ; 0xf7c53 LB 0x176
+ push bp ; 55 ; 0xf7c53 scsi.c:315
+ mov bp, sp ; 89 e5 ; 0xf7c54
+ push si ; 56 ; 0xf7c56
+ push di ; 57 ; 0xf7c57
+ sub sp, strict byte 0000eh ; 83 ec 0e ; 0xf7c58
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf7c5b
+ mov word [bp-010h], bx ; 89 5e f0 ; 0xf7c5e
+ mov word [bp-00ah], cx ; 89 4e f6 ; 0xf7c61
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf7c64 scsi.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf7c67
+ mov es, dx ; 8e c2 ; 0xf7c6a
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf7c6c
+ mov si, 00122h ; be 22 01 ; 0xf7c6f scsi.c:49
+ mov word [bp-012h], dx ; 89 56 ee ; 0xf7c72
+ cmp byte [bp+00ah], 002h ; 80 7e 0a 02 ; 0xf7c75 scsi.c:326
+ jne short 07c9ah ; 75 1f ; 0xf7c79
+ mov bx, 00da0h ; bb a0 0d ; 0xf7c7b scsi.c:327
+ mov cx, ds ; 8c d9 ; 0xf7c7e
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf7c80
+ call 018bch ; e8 36 9c ; 0xf7c83
+ push 00b62h ; 68 62 0b ; 0xf7c86
+ push 00b72h ; 68 72 0b ; 0xf7c89
+ push strict byte 00004h ; 6a 04 ; 0xf7c8c
+ call 018ffh ; e8 6e 9c ; 0xf7c8e
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7c91
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf7c94 scsi.c:328
+ jmp near 07dbeh ; e9 24 01 ; 0xf7c97
+ sub ax, strict word 00008h ; 2d 08 00 ; 0xf7c9a scsi.c:332
+ sal ax, 002h ; c1 e0 02 ; 0xf7c9d scsi.c:342
+ sub byte [bp-006h], 002h ; 80 6e fa 02 ; 0xf7ca0 scsi.c:340
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf7ca4
+ mov di, si ; 89 f7 ; 0xf7ca7
+ add di, ax ; 01 c7 ; 0xf7ca9
+ mov bx, word [es:di+0021ch] ; 26 8b 9d 1c 02 ; 0xf7cab
+ mov al, byte [es:di+0021eh] ; 26 8a 85 1e 02 ; 0xf7cb0 scsi.c:343
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf7cb5
+ mov dx, bx ; 89 da ; 0xf7cb8 scsi.c:347
+ in AL, DX ; ec ; 0xf7cba
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7cbb
+ test AL, strict byte 001h ; a8 01 ; 0xf7cbd scsi.c:348
+ jne short 07cb8h ; 75 f7 ; 0xf7cbf
+ xor di, di ; 31 ff ; 0xf7cc1 scsi.c:354
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf7cc3
+ add ax, word [bp+004h] ; 03 46 04 ; 0xf7cc6
+ adc di, word [bp+008h] ; 13 7e 08 ; 0xf7cc9
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf7ccc
+ mov dx, word [es:si+020h] ; 26 8b 54 20 ; 0xf7ccf
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf7cd3
+ xor dx, dx ; 31 d2 ; 0xf7cd6
+ mov cx, word [bp-00eh] ; 8b 4e f2 ; 0xf7cd8
+ add cx, ax ; 01 c1 ; 0xf7cdb
+ mov word [bp-00ch], cx ; 89 4e f4 ; 0xf7cdd
+ adc di, dx ; 11 d7 ; 0xf7ce0
+ mov ax, cx ; 89 c8 ; 0xf7ce2 scsi.c:356
+ mov dx, di ; 89 fa ; 0xf7ce4
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf7ce6
+ shr dx, 1 ; d1 ea ; 0xf7ce9
+ rcr ax, 1 ; d1 d8 ; 0xf7ceb
+ loop 07ce9h ; e2 fa ; 0xf7ced
+ mov cx, ax ; 89 c1 ; 0xf7cef
+ and cx, 000f0h ; 81 e1 f0 00 ; 0xf7cf1
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7cf5
+ xor ah, ah ; 30 e4 ; 0xf7cf8
+ or cx, ax ; 09 c1 ; 0xf7cfa
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf7cfc scsi.c:357
+ mov dx, bx ; 89 da ; 0xf7cff
+ out DX, AL ; ee ; 0xf7d01
+ xor al, al ; 30 c0 ; 0xf7d02 scsi.c:358
+ out DX, AL ; ee ; 0xf7d04
+ mov al, cl ; 88 c8 ; 0xf7d05 scsi.c:359
+ out DX, AL ; ee ; 0xf7d07
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf7d08 scsi.c:360
+ out DX, AL ; ee ; 0xf7d0b
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf7d0c scsi.c:361
+ mov dx, di ; 89 fa ; 0xf7d0f
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf7d11
+ shr dx, 1 ; d1 ea ; 0xf7d14
+ rcr ax, 1 ; d1 d8 ; 0xf7d16
+ loop 07d14h ; e2 fa ; 0xf7d18
+ mov dx, bx ; 89 da ; 0xf7d1a
+ out DX, AL ; ee ; 0xf7d1c
+ xor cx, cx ; 31 c9 ; 0xf7d1d scsi.c:362
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7d1f
+ xor ah, ah ; 30 e4 ; 0xf7d22
+ cmp cx, ax ; 39 c1 ; 0xf7d24
+ jnc short 07d39h ; 73 11 ; 0xf7d26
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf7d28 scsi.c:363
+ mov di, word [bp-010h] ; 8b 7e f0 ; 0xf7d2b
+ add di, cx ; 01 cf ; 0xf7d2e
+ mov al, byte [es:di] ; 26 8a 05 ; 0xf7d30
+ mov dx, bx ; 89 da ; 0xf7d33
+ out DX, AL ; ee ; 0xf7d35
+ inc cx ; 41 ; 0xf7d36
+ jmp short 07d1fh ; eb e6 ; 0xf7d37
+ mov dx, bx ; 89 da ; 0xf7d39 scsi.c:367
+ in AL, DX ; ec ; 0xf7d3b
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7d3c
+ test AL, strict byte 001h ; a8 01 ; 0xf7d3e scsi.c:368
+ jne short 07d39h ; 75 f7 ; 0xf7d40
+ test AL, strict byte 002h ; a8 02 ; 0xf7d42 scsi.c:371
+ je short 07d54h ; 74 0e ; 0xf7d44
+ lea dx, [bx+003h] ; 8d 57 03 ; 0xf7d46 scsi.c:372
+ xor al, al ; 30 c0 ; 0xf7d49
+ out DX, AL ; ee ; 0xf7d4b
+ in AL, DX ; ec ; 0xf7d4c scsi.c:374
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7d4d
+ mov dx, strict word 00003h ; ba 03 00 ; 0xf7d4f scsi.c:376
+ jmp short 07dbeh ; eb 6a ; 0xf7d52
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf7d54 scsi.c:381
+ test ax, ax ; 85 c0 ; 0xf7d57
+ je short 07d63h ; 74 08 ; 0xf7d59
+ lea dx, [bx+001h] ; 8d 57 01 ; 0xf7d5b scsi.c:382
+ mov cx, ax ; 89 c1 ; 0xf7d5e
+ in AL, DX ; ec ; 0xf7d60
+ loop 07d60h ; e2 fd ; 0xf7d61
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf7d63 scsi.c:384
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf7d66
+ mov word [es:si+01ah], ax ; 26 89 44 1a ; 0xf7d69
+ mov ax, word [bp+008h] ; 8b 46 08 ; 0xf7d6d
+ mov word [es:si+01ch], ax ; 26 89 44 1c ; 0xf7d70
+ lea ax, [bx+001h] ; 8d 47 01 ; 0xf7d74 scsi.c:389
+ cmp word [bp+008h], strict byte 00000h ; 83 7e 08 00 ; 0xf7d77
+ jne short 07d84h ; 75 07 ; 0xf7d7b
+ cmp word [bp+006h], 08000h ; 81 7e 06 00 80 ; 0xf7d7d
+ jbe short 07da1h ; 76 1d ; 0xf7d82
+ mov dx, ax ; 89 c2 ; 0xf7d84 scsi.c:391
+ mov cx, 08000h ; b9 00 80 ; 0xf7d86
+ les di, [bp+00ch] ; c4 7e 0c ; 0xf7d89
+ rep insb ; f3 6c ; 0xf7d8c
+ add word [bp+006h], 08000h ; 81 46 06 00 80 ; 0xf7d8e scsi.c:392
+ adc word [bp+008h], strict byte 0ffffh ; 83 56 08 ff ; 0xf7d93
+ mov ax, es ; 8c c0 ; 0xf7d97
+ add ax, 00800h ; 05 00 08 ; 0xf7d99
+ mov word [bp+00eh], ax ; 89 46 0e ; 0xf7d9c
+ jmp short 07d74h ; eb d3 ; 0xf7d9f scsi.c:394
+ mov dx, ax ; 89 c2 ; 0xf7da1 scsi.c:397
+ mov cx, word [bp+006h] ; 8b 4e 06 ; 0xf7da3
+ les di, [bp+00ch] ; c4 7e 0c ; 0xf7da6
+ rep insb ; f3 6c ; 0xf7da9
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf7dab scsi.c:399
+ cmp word [es:si+020h], strict byte 00000h ; 26 83 7c 20 00 ; 0xf7dae
+ je short 07dbch ; 74 07 ; 0xf7db3
+ mov cx, word [es:si+020h] ; 26 8b 4c 20 ; 0xf7db5 scsi.c:400
+ in AL, DX ; ec ; 0xf7db9
+ loop 07db9h ; e2 fd ; 0xf7dba
+ xor dx, dx ; 31 d2 ; 0xf7dbc scsi.c:402
+ mov ax, dx ; 89 d0 ; 0xf7dbe scsi.c:403
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7dc0
+ pop di ; 5f ; 0xf7dc3
+ pop si ; 5e ; 0xf7dc4
+ pop bp ; 5d ; 0xf7dc5
+ retn 0000ch ; c2 0c 00 ; 0xf7dc6
+ ; disGetNextSymbol 0xf7dc9 LB 0x20ff -> off=0x0 cb=00000000000004a7 uValue=00000000000f67c9 'scsi_enumerate_attached_devices'
+scsi_enumerate_attached_devices: ; 0xf7dc9 LB 0x4a7
+ push bp ; 55 ; 0xf7dc9 scsi.c:411
+ mov bp, sp ; 89 e5 ; 0xf7dca
+ push bx ; 53 ; 0xf7dcc
+ push cx ; 51 ; 0xf7dcd
+ push dx ; 52 ; 0xf7dce
+ push si ; 56 ; 0xf7dcf
+ push di ; 57 ; 0xf7dd0
+ sub sp, 0023ch ; 81 ec 3c 02 ; 0xf7dd1
+ push ax ; 50 ; 0xf7dd5
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf7dd6 scsi.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf7dd9
+ mov es, ax ; 8e c0 ; 0xf7ddc
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf7dde
+ mov di, 00122h ; bf 22 01 ; 0xf7de1 scsi.c:49
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf7de4
+ mov word [bp-012h], strict word 00000h ; c7 46 ee 00 00 ; 0xf7de7 scsi.c:420
+ jmp near 081eeh ; e9 ff 03 ; 0xf7dec
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf7def scsi.c:440
+ jc short 07df6h ; 72 03 ; 0xf7df1
+ jmp near 08266h ; e9 70 04 ; 0xf7df3
+ mov cx, strict word 00010h ; b9 10 00 ; 0xf7df6 scsi.c:455
+ xor bx, bx ; 31 db ; 0xf7df9
+ mov dx, ss ; 8c d2 ; 0xf7dfb
+ lea ax, [bp-046h] ; 8d 46 ba ; 0xf7dfd
+ call 09bb0h ; e8 ad 1d ; 0xf7e00
+ mov byte [bp-046h], 09eh ; c6 46 ba 9e ; 0xf7e03 scsi.c:456
+ mov byte [bp-045h], 010h ; c6 46 bb 10 ; 0xf7e07 scsi.c:457
+ mov byte [bp-039h], 020h ; c6 46 c7 20 ; 0xf7e0b scsi.c:458
+ push strict byte 00000h ; 6a 00 ; 0xf7e0f scsi.c:460
+ push strict byte 00020h ; 6a 20 ; 0xf7e11
+ lea dx, [bp-00246h] ; 8d 96 ba fd ; 0xf7e13
+ push SS ; 16 ; 0xf7e17
+ push dx ; 52 ; 0xf7e18
+ push strict byte 00010h ; 6a 10 ; 0xf7e19
+ mov dl, byte [bp-012h] ; 8a 56 ee ; 0xf7e1b
+ xor dh, dh ; 30 f6 ; 0xf7e1e
+ mov cx, ss ; 8c d1 ; 0xf7e20
+ lea bx, [bp-046h] ; 8d 5e ba ; 0xf7e22
+ mov ax, word [bp-00248h] ; 8b 86 b8 fd ; 0xf7e25
+ call 078e9h ; e8 bd fa ; 0xf7e29
+ test al, al ; 84 c0 ; 0xf7e2c scsi.c:461
+ je short 07e3eh ; 74 0e ; 0xf7e2e
+ push 00b92h ; 68 92 0b ; 0xf7e30 scsi.c:462
+ push 00bcbh ; 68 cb 0b ; 0xf7e33
+ push strict byte 00007h ; 6a 07 ; 0xf7e36
+ call 018ffh ; e8 c4 9a ; 0xf7e38
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7e3b
+ mov ax, word [bp-00240h] ; 8b 86 c0 fd ; 0xf7e3e scsi.c:467
+ mov bx, word [bp-00242h] ; 8b 9e be fd ; 0xf7e42
+ mov cx, word [bp-00244h] ; 8b 8e bc fd ; 0xf7e46
+ mov dx, word [bp-00246h] ; 8b 96 ba fd ; 0xf7e4a
+ xchg ah, al ; 86 c4 ; 0xf7e4e
+ xchg bh, bl ; 86 df ; 0xf7e50
+ xchg ch, cl ; 86 cd ; 0xf7e52
+ xchg dh, dl ; 86 d6 ; 0xf7e54
+ xchg dx, ax ; 92 ; 0xf7e56
+ xchg bx, cx ; 87 cb ; 0xf7e57
+ add dx, strict byte 00001h ; 83 c2 01 ; 0xf7e59
+ mov word [bp-02ah], dx ; 89 56 d6 ; 0xf7e5c
+ adc cx, strict byte 00000h ; 83 d1 00 ; 0xf7e5f
+ mov word [bp-018h], cx ; 89 4e e8 ; 0xf7e62
+ adc bx, strict byte 00000h ; 83 d3 00 ; 0xf7e65
+ mov word [bp-020h], bx ; 89 5e e0 ; 0xf7e68
+ adc ax, strict word 00000h ; 15 00 00 ; 0xf7e6b
+ mov word [bp-01eh], ax ; 89 46 e2 ; 0xf7e6e
+ mov al, byte [bp-0023eh] ; 8a 86 c2 fd ; 0xf7e71 scsi.c:469
+ xor ah, ah ; 30 e4 ; 0xf7e75
+ mov bx, ax ; 89 c3 ; 0xf7e77
+ sal bx, 008h ; c1 e3 08 ; 0xf7e79
+ mov al, byte [bp-0023dh] ; 8a 86 c3 fd ; 0xf7e7c
+ xor si, si ; 31 f6 ; 0xf7e80
+ or bx, ax ; 09 c3 ; 0xf7e82
+ mov al, byte [bp-0023ch] ; 8a 86 c4 fd ; 0xf7e84
+ xor dx, dx ; 31 d2 ; 0xf7e88
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf7e8a
+ sal ax, 1 ; d1 e0 ; 0xf7e8d
+ rcl dx, 1 ; d1 d2 ; 0xf7e8f
+ loop 07e8dh ; e2 fa ; 0xf7e91
+ mov cx, si ; 89 f1 ; 0xf7e93
+ or cx, ax ; 09 c1 ; 0xf7e95
+ or dx, bx ; 09 da ; 0xf7e97
+ mov al, byte [bp-0023bh] ; 8a 86 c5 fd ; 0xf7e99
+ xor ah, ah ; 30 e4 ; 0xf7e9d
+ or cx, ax ; 09 c1 ; 0xf7e9f
+ mov word [bp-016h], cx ; 89 4e ea ; 0xf7ea1
+ test dx, dx ; 85 d2 ; 0xf7ea4 scsi.c:475
+ jne short 07eaeh ; 75 06 ; 0xf7ea6
+ cmp cx, 00200h ; 81 f9 00 02 ; 0xf7ea8
+ je short 07eceh ; 74 20 ; 0xf7eac
+ mov bx, 00da0h ; bb a0 0d ; 0xf7eae scsi.c:478
+ mov cx, ds ; 8c d9 ; 0xf7eb1
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf7eb3
+ call 018bch ; e8 03 9a ; 0xf7eb6
+ push dx ; 52 ; 0xf7eb9
+ push word [bp-016h] ; ff 76 ea ; 0xf7eba
+ push word [bp-012h] ; ff 76 ee ; 0xf7ebd
+ push 00beah ; 68 ea 0b ; 0xf7ec0
+ push strict byte 00004h ; 6a 04 ; 0xf7ec3
+ call 018ffh ; e8 37 9a ; 0xf7ec5
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf7ec8
+ jmp near 081e2h ; e9 14 03 ; 0xf7ecb scsi.c:479
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf7ece scsi.c:483
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf7ed1
+ jc short 07ee1h ; 72 0c ; 0xf7ed3
+ jbe short 07ee9h ; 76 12 ; 0xf7ed5
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf7ed7
+ je short 07ef1h ; 74 16 ; 0xf7ed9
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf7edb
+ je short 07eedh ; 74 0e ; 0xf7edd
+ jmp short 07f3ah ; eb 59 ; 0xf7edf
+ test al, al ; 84 c0 ; 0xf7ee1
+ jne short 07f3ah ; 75 55 ; 0xf7ee3
+ mov BL, strict byte 090h ; b3 90 ; 0xf7ee5 scsi.c:486
+ jmp short 07ef3h ; eb 0a ; 0xf7ee7 scsi.c:487
+ mov BL, strict byte 098h ; b3 98 ; 0xf7ee9 scsi.c:489
+ jmp short 07ef3h ; eb 06 ; 0xf7eeb scsi.c:490
+ mov BL, strict byte 0a0h ; b3 a0 ; 0xf7eed scsi.c:492
+ jmp short 07ef3h ; eb 02 ; 0xf7eef scsi.c:493
+ mov BL, strict byte 0a8h ; b3 a8 ; 0xf7ef1 scsi.c:495
+ mov cl, bl ; 88 d9 ; 0xf7ef3 scsi.c:499
+ add cl, 007h ; 80 c1 07 ; 0xf7ef5
+ xor ch, ch ; 30 ed ; 0xf7ef8
+ mov ax, cx ; 89 c8 ; 0xf7efa
+ call 01650h ; e8 51 97 ; 0xf7efc
+ test al, al ; 84 c0 ; 0xf7eff
+ je short 07f3ah ; 74 37 ; 0xf7f01
+ mov al, bl ; 88 d8 ; 0xf7f03 scsi.c:504
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf7f05
+ xor ah, ah ; 30 e4 ; 0xf7f07
+ call 01650h ; e8 44 97 ; 0xf7f09
+ xor ah, ah ; 30 e4 ; 0xf7f0c
+ mov dx, ax ; 89 c2 ; 0xf7f0e
+ sal dx, 008h ; c1 e2 08 ; 0xf7f10
+ mov al, bl ; 88 d8 ; 0xf7f13
+ call 01650h ; e8 38 97 ; 0xf7f15
+ xor ah, ah ; 30 e4 ; 0xf7f18
+ add ax, dx ; 01 d0 ; 0xf7f1a
+ cwd ; 99 ; 0xf7f1c
+ mov si, ax ; 89 c6 ; 0xf7f1d
+ mov al, bl ; 88 d8 ; 0xf7f1f scsi.c:505
+ add AL, strict byte 002h ; 04 02 ; 0xf7f21
+ xor ah, ah ; 30 e4 ; 0xf7f23
+ call 01650h ; e8 28 97 ; 0xf7f25
+ xor ah, ah ; 30 e4 ; 0xf7f28
+ mov word [bp-022h], ax ; 89 46 de ; 0xf7f2a
+ mov ax, cx ; 89 c8 ; 0xf7f2d scsi.c:506
+ call 01650h ; e8 1e 97 ; 0xf7f2f
+ xor ah, ah ; 30 e4 ; 0xf7f32
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf7f34
+ jmp near 08028h ; e9 ee 00 ; 0xf7f37 scsi.c:508
+ mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xf7f3a scsi.c:509
+ mov bx, word [bp-020h] ; 8b 5e e0 ; 0xf7f3d
+ mov cx, word [bp-018h] ; 8b 4e e8 ; 0xf7f40
+ mov dx, word [bp-02ah] ; 8b 56 d6 ; 0xf7f43
+ mov si, strict word 0000ch ; be 0c 00 ; 0xf7f46
+ call 09b90h ; e8 44 1c ; 0xf7f49
+ mov word [bp-026h], ax ; 89 46 da ; 0xf7f4c
+ mov word [bp-010h], bx ; 89 5e f0 ; 0xf7f4f
+ mov word [bp-014h], cx ; 89 4e ec ; 0xf7f52
+ mov word [bp-028h], dx ; 89 56 d8 ; 0xf7f55
+ mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xf7f58 scsi.c:513
+ test ax, ax ; 85 c0 ; 0xf7f5b
+ jnbe short 07f74h ; 77 15 ; 0xf7f5d
+ je short 07f64h ; 74 03 ; 0xf7f5f
+ jmp near 07fe9h ; e9 85 00 ; 0xf7f61
+ cmp word [bp-020h], strict byte 00000h ; 83 7e e0 00 ; 0xf7f64
+ jnbe short 07f74h ; 77 0a ; 0xf7f68
+ jne short 07f61h ; 75 f5 ; 0xf7f6a
+ cmp word [bp-018h], strict byte 00040h ; 83 7e e8 40 ; 0xf7f6c
+ jnbe short 07f74h ; 77 02 ; 0xf7f70
+ jne short 07fe9h ; 75 75 ; 0xf7f72
+ mov word [bp-022h], 000ffh ; c7 46 de ff 00 ; 0xf7f74 scsi.c:515
+ mov word [bp-024h], strict word 0003fh ; c7 46 dc 3f 00 ; 0xf7f79 scsi.c:516
+ mov bx, word [bp-020h] ; 8b 5e e0 ; 0xf7f7e scsi.c:518
+ mov cx, word [bp-018h] ; 8b 4e e8 ; 0xf7f81
+ mov dx, word [bp-02ah] ; 8b 56 d6 ; 0xf7f84
+ mov si, strict word 00006h ; be 06 00 ; 0xf7f87
+ call 09b90h ; e8 03 1c ; 0xf7f8a
+ mov si, word [bp-028h] ; 8b 76 d8 ; 0xf7f8d
+ add si, dx ; 01 d6 ; 0xf7f90
+ mov word [bp-036h], si ; 89 76 ca ; 0xf7f92
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf7f95
+ adc dx, cx ; 11 ca ; 0xf7f98
+ mov word [bp-034h], dx ; 89 56 cc ; 0xf7f9a
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf7f9d
+ adc dx, bx ; 11 da ; 0xf7fa0
+ mov word [bp-01ch], dx ; 89 56 e4 ; 0xf7fa2
+ mov dx, word [bp-026h] ; 8b 56 da ; 0xf7fa5
+ adc dx, ax ; 11 c2 ; 0xf7fa8
+ mov word [bp-02eh], dx ; 89 56 d2 ; 0xf7faa
+ mov ax, dx ; 89 d0 ; 0xf7fad scsi.c:519
+ mov bx, word [bp-01ch] ; 8b 5e e4 ; 0xf7faf
+ mov cx, word [bp-034h] ; 8b 4e cc ; 0xf7fb2
+ mov dx, si ; 89 f2 ; 0xf7fb5
+ mov si, strict word 00008h ; be 08 00 ; 0xf7fb7
+ call 09b90h ; e8 d3 1b ; 0xf7fba
+ mov word [bp-030h], bx ; 89 5e d0 ; 0xf7fbd
+ mov word [bp-02ch], cx ; 89 4e d4 ; 0xf7fc0
+ mov word [bp-032h], dx ; 89 56 ce ; 0xf7fc3
+ mov ax, word [bp-02eh] ; 8b 46 d2 ; 0xf7fc6
+ mov bx, word [bp-01ch] ; 8b 5e e4 ; 0xf7fc9
+ mov cx, word [bp-034h] ; 8b 4e cc ; 0xf7fcc
+ mov dx, word [bp-036h] ; 8b 56 ca ; 0xf7fcf
+ mov si, strict word 00010h ; be 10 00 ; 0xf7fd2
+ call 09b90h ; e8 b8 1b ; 0xf7fd5
+ mov si, word [bp-032h] ; 8b 76 ce ; 0xf7fd8
+ add si, dx ; 01 d6 ; 0xf7fdb
+ mov dx, word [bp-02ch] ; 8b 56 d4 ; 0xf7fdd
+ adc dx, cx ; 11 ca ; 0xf7fe0
+ mov ax, word [bp-030h] ; 8b 46 d0 ; 0xf7fe2
+ adc ax, bx ; 11 d8 ; 0xf7fe5
+ jmp short 08028h ; eb 3f ; 0xf7fe7 scsi.c:521
+ test ax, ax ; 85 c0 ; 0xf7fe9
+ jnbe short 07fffh ; 77 12 ; 0xf7feb
+ jne short 0800bh ; 75 1c ; 0xf7fed
+ cmp word [bp-020h], strict byte 00000h ; 83 7e e0 00 ; 0xf7fef
+ jnbe short 07fffh ; 77 0a ; 0xf7ff3
+ jne short 0800bh ; 75 14 ; 0xf7ff5
+ cmp word [bp-018h], strict byte 00020h ; 83 7e e8 20 ; 0xf7ff7
+ jnbe short 07fffh ; 77 02 ; 0xf7ffb
+ jne short 0800bh ; 75 0c ; 0xf7ffd
+ mov word [bp-022h], 00080h ; c7 46 de 80 00 ; 0xf7fff scsi.c:523
+ mov word [bp-024h], strict word 00020h ; c7 46 dc 20 00 ; 0xf8004 scsi.c:524
+ jmp short 08024h ; eb 19 ; 0xf8009 scsi.c:527
+ mov word [bp-022h], strict word 00040h ; c7 46 de 40 00 ; 0xf800b scsi.c:529
+ mov word [bp-024h], strict word 00020h ; c7 46 dc 20 00 ; 0xf8010 scsi.c:530
+ mov bx, word [bp-020h] ; 8b 5e e0 ; 0xf8015 scsi.c:531
+ mov cx, word [bp-018h] ; 8b 4e e8 ; 0xf8018
+ mov dx, word [bp-02ah] ; 8b 56 d6 ; 0xf801b
+ mov si, strict word 0000bh ; be 0b 00 ; 0xf801e
+ call 09b90h ; e8 6c 1b ; 0xf8021
+ mov si, dx ; 89 d6 ; 0xf8024
+ mov dx, cx ; 89 ca ; 0xf8026
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf8028 scsi.c:536
+ add AL, strict byte 008h ; 04 08 ; 0xf802b
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf802d
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf8030 scsi.c:538
+ xor ah, ah ; 30 e4 ; 0xf8033
+ sal ax, 002h ; c1 e0 02 ; 0xf8035
+ mov es, [bp-01ah] ; 8e 46 e6 ; 0xf8038
+ mov bx, di ; 89 fb ; 0xf803b
+ add bx, ax ; 01 c3 ; 0xf803d
+ mov ax, word [bp-00248h] ; 8b 86 b8 fd ; 0xf803f
+ mov word [es:bx+0021ch], ax ; 26 89 87 1c 02 ; 0xf8043
+ mov al, byte [bp-012h] ; 8a 46 ee ; 0xf8048 scsi.c:539
+ mov byte [es:bx+0021eh], al ; 26 88 87 1e 02 ; 0xf804b
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf8050 scsi.c:540
+ xor ah, ah ; 30 e4 ; 0xf8053
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf8055
+ mov bx, di ; 89 fb ; 0xf8058
+ add bx, ax ; 01 c3 ; 0xf805a
+ mov word [es:bx+022h], 0ff04h ; 26 c7 47 22 04 ff ; 0xf805c
+ mov word [es:bx+024h], strict word 00000h ; 26 c7 47 24 00 00 ; 0xf8062 scsi.c:542
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf8068 scsi.c:544
+ mov word [es:bx+028h], ax ; 26 89 47 28 ; 0xf806b
+ mov byte [es:bx+027h], 001h ; 26 c6 47 27 01 ; 0xf806f scsi.c:545
+ mov ax, word [bp-022h] ; 8b 46 de ; 0xf8074 scsi.c:548
+ mov word [es:bx+02ah], ax ; 26 89 47 2a ; 0xf8077
+ mov ax, word [bp-024h] ; 8b 46 dc ; 0xf807b scsi.c:549
+ mov word [es:bx+02eh], ax ; 26 89 47 2e ; 0xf807e
+ mov ax, word [bp-022h] ; 8b 46 de ; 0xf8082 scsi.c:550
+ mov word [es:bx+030h], ax ; 26 89 47 30 ; 0xf8085
+ mov ax, word [bp-024h] ; 8b 46 dc ; 0xf8089 scsi.c:551
+ mov word [es:bx+034h], ax ; 26 89 47 34 ; 0xf808c
+ test dx, dx ; 85 d2 ; 0xf8090 scsi.c:553
+ jne short 0809ah ; 75 06 ; 0xf8092
+ cmp si, 00400h ; 81 fe 00 04 ; 0xf8094
+ jbe short 080a8h ; 76 0e ; 0xf8098
+ mov word [es:bx+02ch], 00400h ; 26 c7 47 2c 00 04 ; 0xf809a scsi.c:554
+ mov word [es:bx+032h], 00400h ; 26 c7 47 32 00 04 ; 0xf80a0 scsi.c:555
+ jmp short 080b0h ; eb 08 ; 0xf80a6 scsi.c:556
+ mov word [es:bx+02ch], si ; 26 89 77 2c ; 0xf80a8 scsi.c:557
+ mov word [es:bx+032h], si ; 26 89 77 32 ; 0xf80ac scsi.c:558
+ mov bx, 00da0h ; bb a0 0d ; 0xf80b0 scsi.c:562
+ mov cx, ds ; 8c d9 ; 0xf80b3
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf80b5
+ call 018bch ; e8 01 98 ; 0xf80b8
+ push word [bp-01eh] ; ff 76 e2 ; 0xf80bb
+ push word [bp-020h] ; ff 76 e0 ; 0xf80be
+ push word [bp-018h] ; ff 76 e8 ; 0xf80c1
+ push word [bp-02ah] ; ff 76 d6 ; 0xf80c4
+ push word [bp-024h] ; ff 76 dc ; 0xf80c7
+ push word [bp-022h] ; ff 76 de ; 0xf80ca
+ push dx ; 52 ; 0xf80cd
+ push si ; 56 ; 0xf80ce
+ push word [bp-012h] ; ff 76 ee ; 0xf80cf
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf80d2
+ xor ah, ah ; 30 e4 ; 0xf80d5
+ push ax ; 50 ; 0xf80d7
+ push 00c18h ; 68 18 0c ; 0xf80d8
+ push strict byte 00004h ; 6a 04 ; 0xf80db
+ call 018ffh ; e8 1f 98 ; 0xf80dd
+ add sp, strict byte 00018h ; 83 c4 18 ; 0xf80e0
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf80e3 scsi.c:564
+ xor ah, ah ; 30 e4 ; 0xf80e6
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf80e8
+ mov es, [bp-01ah] ; 8e 46 e6 ; 0xf80eb
+ mov bx, di ; 89 fb ; 0xf80ee
+ add bx, ax ; 01 c3 ; 0xf80f0
+ mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xf80f2
+ mov word [es:bx+03ch], ax ; 26 89 47 3c ; 0xf80f5
+ mov ax, word [bp-020h] ; 8b 46 e0 ; 0xf80f9
+ mov word [es:bx+03ah], ax ; 26 89 47 3a ; 0xf80fc
+ mov ax, word [bp-018h] ; 8b 46 e8 ; 0xf8100
+ mov word [es:bx+038h], ax ; 26 89 47 38 ; 0xf8103
+ mov ax, word [bp-02ah] ; 8b 46 d6 ; 0xf8107
+ mov word [es:bx+036h], ax ; 26 89 47 36 ; 0xf810a
+ mov al, byte [es:di+001e2h] ; 26 8a 85 e2 01 ; 0xf810e scsi.c:567
+ mov ah, byte [bp-00ch] ; 8a 66 f4 ; 0xf8113 scsi.c:568
+ add ah, 008h ; 80 c4 08 ; 0xf8116
+ mov bl, al ; 88 c3 ; 0xf8119
+ xor bh, bh ; 30 ff ; 0xf811b
+ add bx, di ; 01 fb ; 0xf811d
+ mov byte [es:bx+001e3h], ah ; 26 88 a7 e3 01 ; 0xf811f
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf8124 scsi.c:569
+ mov byte [es:di+001e2h], al ; 26 88 85 e2 01 ; 0xf8126 scsi.c:570
+ mov bx, strict word 00075h ; bb 75 00 ; 0xf812b scsi.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf812e
+ mov es, ax ; 8e c0 ; 0xf8131
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf8133
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf8136 scsi.c:574
+ mov byte [es:bx], al ; 26 88 07 ; 0xf8138 scsi.c:43
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf813b scsi.c:577
+ jmp near 081d7h ; e9 96 00 ; 0xf813e scsi.c:579
+ mov bx, 00da0h ; bb a0 0d ; 0xf8141 scsi.c:591
+ mov cx, ds ; 8c d9 ; 0xf8144
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf8146
+ call 018bch ; e8 70 97 ; 0xf8149
+ push word [bp-012h] ; ff 76 ee ; 0xf814c
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf814f
+ xor ah, ah ; 30 e4 ; 0xf8152
+ push ax ; 50 ; 0xf8154
+ push 00c46h ; 68 46 0c ; 0xf8155
+ push strict byte 00004h ; 6a 04 ; 0xf8158
+ call 018ffh ; e8 a2 97 ; 0xf815a
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf815d
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf8160 scsi.c:594
+ add AL, strict byte 008h ; 04 08 ; 0xf8163
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf8165
+ test byte [bp-00245h], 080h ; f6 86 bb fd 80 ; 0xf8168 scsi.c:596
+ je short 08174h ; 74 05 ; 0xf816d
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf816f
+ jmp short 08176h ; eb 02 ; 0xf8172
+ xor dx, dx ; 31 d2 ; 0xf8174
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf8176 scsi.c:598
+ xor ah, ah ; 30 e4 ; 0xf8179
+ sal ax, 002h ; c1 e0 02 ; 0xf817b
+ mov es, [bp-01ah] ; 8e 46 e6 ; 0xf817e
+ mov bx, di ; 89 fb ; 0xf8181
+ add bx, ax ; 01 c3 ; 0xf8183
+ mov ax, word [bp-00248h] ; 8b 86 b8 fd ; 0xf8185
+ mov word [es:bx+0021ch], ax ; 26 89 87 1c 02 ; 0xf8189
+ mov al, byte [bp-012h] ; 8a 46 ee ; 0xf818e scsi.c:599
+ mov byte [es:bx+0021eh], al ; 26 88 87 1e 02 ; 0xf8191
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf8196 scsi.c:600
+ xor ah, ah ; 30 e4 ; 0xf8199
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf819b
+ mov bx, di ; 89 fb ; 0xf819e
+ add bx, ax ; 01 c3 ; 0xf81a0
+ mov word [es:bx+022h], 00504h ; 26 c7 47 22 04 05 ; 0xf81a2
+ mov byte [es:bx+024h], dl ; 26 88 57 24 ; 0xf81a8 scsi.c:602
+ mov word [es:bx+028h], 00800h ; 26 c7 47 28 00 08 ; 0xf81ac scsi.c:603
+ mov byte [es:bx+027h], 000h ; 26 c6 47 27 00 ; 0xf81b2 scsi.c:604
+ mov al, byte [es:di+001f3h] ; 26 8a 85 f3 01 ; 0xf81b7 scsi.c:607
+ mov ah, byte [bp-00ch] ; 8a 66 f4 ; 0xf81bc scsi.c:608
+ add ah, 008h ; 80 c4 08 ; 0xf81bf
+ mov bl, al ; 88 c3 ; 0xf81c2
+ xor bh, bh ; 30 ff ; 0xf81c4
+ add bx, di ; 01 fb ; 0xf81c6
+ mov byte [es:bx+001f4h], ah ; 26 88 a7 f4 01 ; 0xf81c8
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf81cd scsi.c:609
+ mov byte [es:di+001f3h], al ; 26 88 85 f3 01 ; 0xf81cf scsi.c:610
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf81d4 scsi.c:612
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf81d7 scsi.c:617
+ mov es, [bp-01ah] ; 8e 46 e6 ; 0xf81da
+ mov byte [es:di+0022ch], al ; 26 88 85 2c 02 ; 0xf81dd
+ inc word [bp-012h] ; ff 46 ee ; 0xf81e2 scsi.c:618
+ cmp word [bp-012h], strict byte 00010h ; 83 7e ee 10 ; 0xf81e5
+ jl short 081eeh ; 7c 03 ; 0xf81e9
+ jmp near 08266h ; e9 78 00 ; 0xf81eb
+ mov byte [bp-046h], 012h ; c6 46 ba 12 ; 0xf81ee
+ xor al, al ; 30 c0 ; 0xf81f2
+ mov byte [bp-045h], al ; 88 46 bb ; 0xf81f4
+ mov byte [bp-044h], al ; 88 46 bc ; 0xf81f7
+ mov byte [bp-043h], al ; 88 46 bd ; 0xf81fa
+ mov byte [bp-042h], 005h ; c6 46 be 05 ; 0xf81fd
+ mov byte [bp-041h], al ; 88 46 bf ; 0xf8201
+ push strict byte 00000h ; 6a 00 ; 0xf8204
+ push strict byte 00005h ; 6a 05 ; 0xf8206
+ lea dx, [bp-00246h] ; 8d 96 ba fd ; 0xf8208
+ push SS ; 16 ; 0xf820c
+ push dx ; 52 ; 0xf820d
+ push strict byte 00006h ; 6a 06 ; 0xf820e
+ mov dl, byte [bp-012h] ; 8a 56 ee ; 0xf8210
+ xor dh, dh ; 30 f6 ; 0xf8213
+ mov cx, ss ; 8c d1 ; 0xf8215
+ lea bx, [bp-046h] ; 8d 5e ba ; 0xf8217
+ mov ax, word [bp-00248h] ; 8b 86 b8 fd ; 0xf821a
+ call 078e9h ; e8 c8 f6 ; 0xf821e
+ test al, al ; 84 c0 ; 0xf8221
+ je short 08233h ; 74 0e ; 0xf8223
+ push 00b92h ; 68 92 0b ; 0xf8225
+ push 00bb2h ; 68 b2 0b ; 0xf8228
+ push strict byte 00007h ; 6a 07 ; 0xf822b
+ call 018ffh ; e8 cf 96 ; 0xf822d
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf8230
+ mov es, [bp-01ah] ; 8e 46 e6 ; 0xf8233
+ mov al, byte [es:di+0022ch] ; 26 8a 85 2c 02 ; 0xf8236
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf823b
+ test byte [bp-00246h], 0e0h ; f6 86 ba fd e0 ; 0xf823e
+ jne short 0824fh ; 75 0a ; 0xf8243
+ test byte [bp-00246h], 01fh ; f6 86 ba fd 1f ; 0xf8245
+ jne short 0824fh ; 75 03 ; 0xf824a
+ jmp near 07defh ; e9 a0 fb ; 0xf824c
+ test byte [bp-00246h], 0e0h ; f6 86 ba fd e0 ; 0xf824f
+ jne short 081d7h ; 75 81 ; 0xf8254
+ mov al, byte [bp-00246h] ; 8a 86 ba fd ; 0xf8256
+ and AL, strict byte 01fh ; 24 1f ; 0xf825a
+ cmp AL, strict byte 005h ; 3c 05 ; 0xf825c
+ jne short 08263h ; 75 03 ; 0xf825e
+ jmp near 08141h ; e9 de fe ; 0xf8260
+ jmp near 081d7h ; e9 71 ff ; 0xf8263
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf8266 scsi.c:619
+ pop di ; 5f ; 0xf8269
+ pop si ; 5e ; 0xf826a
+ pop dx ; 5a ; 0xf826b
+ pop cx ; 59 ; 0xf826c
+ pop bx ; 5b ; 0xf826d
+ pop bp ; 5d ; 0xf826e
+ retn ; c3 ; 0xf826f
+ ; disGetNextSymbol 0xf8270 LB 0x1c58 -> off=0x0 cb=000000000000002a uValue=00000000000f6c70 'scsi_pci_init'
+scsi_pci_init: ; 0xf8270 LB 0x2a
+ push bp ; 55 ; 0xf8270 scsi.c:621
+ mov bp, sp ; 89 e5 ; 0xf8271
+ push bx ; 53 ; 0xf8273
+ push cx ; 51 ; 0xf8274
+ call 09966h ; e8 ee 16 ; 0xf8275 scsi.c:625
+ mov bx, ax ; 89 c3 ; 0xf8278
+ cmp ax, strict word 0ffffh ; 3d ff ff ; 0xf827a scsi.c:626
+ je short 08293h ; 74 14 ; 0xf827d
+ mov dl, bl ; 88 da ; 0xf827f scsi.c:633
+ xor dh, dh ; 30 f6 ; 0xf8281
+ shr bx, 008h ; c1 eb 08 ; 0xf8283
+ mov al, bl ; 88 d8 ; 0xf8286
+ xor ah, ah ; 30 e4 ; 0xf8288
+ mov cx, strict word 00007h ; b9 07 00 ; 0xf828a
+ mov bx, strict word 00004h ; bb 04 00 ; 0xf828d
+ call 09a2fh ; e8 9c 17 ; 0xf8290
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf8293 scsi.c:634
+ pop cx ; 59 ; 0xf8296
+ pop bx ; 5b ; 0xf8297
+ pop bp ; 5d ; 0xf8298
+ retn ; c3 ; 0xf8299
+ ; disGetNextSymbol 0xf829a LB 0x1c2e -> off=0x0 cb=0000000000000081 uValue=00000000000f6c9a 'scsi_init'
+scsi_init: ; 0xf829a LB 0x81
+ push bp ; 55 ; 0xf829a scsi.c:639
+ mov bp, sp ; 89 e5 ; 0xf829b
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf829d scsi.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf82a0
+ mov es, ax ; 8e c0 ; 0xf82a3
+ mov es, [es:bx] ; 26 8e 07 ; 0xf82a5
+ mov bx, 00122h ; bb 22 01 ; 0xf82a8 scsi.c:49
+ mov byte [es:bx+0022ch], 000h ; 26 c6 87 2c 02 00 ; 0xf82ab scsi.c:646
+ mov AL, strict byte 055h ; b0 55 ; 0xf82b1 scsi.c:651
+ mov dx, 00432h ; ba 32 04 ; 0xf82b3
+ out DX, AL ; ee ; 0xf82b6
+ in AL, DX ; ec ; 0xf82b7 scsi.c:652
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf82b8
+ cmp AL, strict byte 055h ; 3c 55 ; 0xf82ba scsi.c:654
+ jne short 082d3h ; 75 15 ; 0xf82bc
+ xor al, al ; 30 c0 ; 0xf82be scsi.c:658
+ mov dx, 00433h ; ba 33 04 ; 0xf82c0
+ out DX, AL ; ee ; 0xf82c3
+ mov ax, 00430h ; b8 30 04 ; 0xf82c4 scsi.c:659
+ call 07dc9h ; e8 ff fa ; 0xf82c7
+ mov dx, 01040h ; ba 40 10 ; 0xf82ca scsi.c:660
+ mov ax, 0104bh ; b8 4b 10 ; 0xf82cd
+ call 08270h ; e8 9d ff ; 0xf82d0
+ mov AL, strict byte 055h ; b0 55 ; 0xf82d3 scsi.c:668
+ mov dx, 00436h ; ba 36 04 ; 0xf82d5
+ out DX, AL ; ee ; 0xf82d8
+ in AL, DX ; ec ; 0xf82d9 scsi.c:669
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf82da
+ cmp AL, strict byte 055h ; 3c 55 ; 0xf82dc scsi.c:671
+ jne short 082f5h ; 75 15 ; 0xf82de
+ xor al, al ; 30 c0 ; 0xf82e0 scsi.c:675
+ mov dx, 00437h ; ba 37 04 ; 0xf82e2
+ out DX, AL ; ee ; 0xf82e5
+ mov ax, 00434h ; b8 34 04 ; 0xf82e6 scsi.c:676
+ call 07dc9h ; e8 dd fa ; 0xf82e9
+ mov dx, strict word 00030h ; ba 30 00 ; 0xf82ec scsi.c:677
+ mov ax, 01000h ; b8 00 10 ; 0xf82ef
+ call 08270h ; e8 7b ff ; 0xf82f2
+ mov AL, strict byte 055h ; b0 55 ; 0xf82f5 scsi.c:685
+ mov dx, 0043ah ; ba 3a 04 ; 0xf82f7
+ out DX, AL ; ee ; 0xf82fa
+ in AL, DX ; ec ; 0xf82fb scsi.c:686
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf82fc
+ cmp AL, strict byte 055h ; 3c 55 ; 0xf82fe scsi.c:688
+ jne short 08317h ; 75 15 ; 0xf8300
+ xor al, al ; 30 c0 ; 0xf8302 scsi.c:692
+ mov dx, 0043bh ; ba 3b 04 ; 0xf8304
+ out DX, AL ; ee ; 0xf8307
+ mov ax, 00438h ; b8 38 04 ; 0xf8308 scsi.c:693
+ call 07dc9h ; e8 bb fa ; 0xf830b
+ mov dx, strict word 00054h ; ba 54 00 ; 0xf830e scsi.c:694
+ mov ax, 01000h ; b8 00 10 ; 0xf8311
+ call 08270h ; e8 59 ff ; 0xf8314
+ mov sp, bp ; 89 ec ; 0xf8317 scsi.c:700
+ pop bp ; 5d ; 0xf8319
+ retn ; c3 ; 0xf831a
+ ; disGetNextSymbol 0xf831b LB 0x1bad -> off=0x0 cb=000000000000001c uValue=00000000000f6d1b 'ahci_ctrl_extract_bits'
+ahci_ctrl_extract_bits: ; 0xf831b LB 0x1c
+ push si ; 56 ; 0xf831b ahci.c:279
+ push bp ; 55 ; 0xf831c
+ mov bp, sp ; 89 e5 ; 0xf831d
+ mov si, ax ; 89 c6 ; 0xf831f
+ and ax, bx ; 21 d8 ; 0xf8321 ahci.c:281
+ and dx, cx ; 21 ca ; 0xf8323
+ mov cl, byte [bp+006h] ; 8a 4e 06 ; 0xf8325
+ xor ch, ch ; 30 ed ; 0xf8328
+ jcxz 08332h ; e3 06 ; 0xf832a
+ shr dx, 1 ; d1 ea ; 0xf832c
+ rcr ax, 1 ; d1 d8 ; 0xf832e
+ loop 0832ch ; e2 fa ; 0xf8330
+ pop bp ; 5d ; 0xf8332 ahci.c:282
+ pop si ; 5e ; 0xf8333
+ retn 00002h ; c2 02 00 ; 0xf8334
+ ; disGetNextSymbol 0xf8337 LB 0x1b91 -> off=0x0 cb=000000000000001e uValue=00000000000f6d37 'ahci_addr_to_phys'
+ahci_addr_to_phys: ; 0xf8337 LB 0x1e
+ push bx ; 53 ; 0xf8337 ahci.c:287
+ push cx ; 51 ; 0xf8338
+ push bp ; 55 ; 0xf8339
+ mov bp, sp ; 89 e5 ; 0xf833a
+ mov bx, ax ; 89 c3 ; 0xf833c
+ mov ax, dx ; 89 d0 ; 0xf833e
+ xor dx, dx ; 31 d2 ; 0xf8340 ahci.c:289
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf8342
+ sal ax, 1 ; d1 e0 ; 0xf8345
+ rcl dx, 1 ; d1 d2 ; 0xf8347
+ loop 08345h ; e2 fa ; 0xf8349
+ xor cx, cx ; 31 c9 ; 0xf834b
+ add ax, bx ; 01 d8 ; 0xf834d
+ adc dx, cx ; 11 ca ; 0xf834f
+ pop bp ; 5d ; 0xf8351 ahci.c:290
+ pop cx ; 59 ; 0xf8352
+ pop bx ; 5b ; 0xf8353
+ retn ; c3 ; 0xf8354
+ ; disGetNextSymbol 0xf8355 LB 0x1b73 -> off=0x0 cb=0000000000000156 uValue=00000000000f6d55 'ahci_port_cmd_sync'
+ahci_port_cmd_sync: ; 0xf8355 LB 0x156
+ push bp ; 55 ; 0xf8355 ahci.c:295
+ mov bp, sp ; 89 e5 ; 0xf8356
+ push cx ; 51 ; 0xf8358
+ push si ; 56 ; 0xf8359
+ push di ; 57 ; 0xf835a
+ push ax ; 50 ; 0xf835b
+ mov si, ax ; 89 c6 ; 0xf835c
+ mov cx, dx ; 89 d1 ; 0xf835e
+ mov dl, bl ; 88 da ; 0xf8360
+ mov es, cx ; 8e c1 ; 0xf8362 ahci.c:300
+ mov al, byte [es:si+00262h] ; 26 8a 84 62 02 ; 0xf8364
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf8369
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf836c ahci.c:301
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xf8371 ahci.c:303
+ jne short 08378h ; 75 03 ; 0xf8373
+ jmp near 084a3h ; e9 2b 01 ; 0xf8375
+ mov al, byte [es:si+00263h] ; 26 8a 84 63 02 ; 0xf8378 ahci.c:306
+ xor ah, ah ; 30 e4 ; 0xf837d
+ xor di, di ; 31 ff ; 0xf837f
+ or di, 00080h ; 81 cf 80 00 ; 0xf8381
+ xor dh, dh ; 30 f6 ; 0xf8385
+ or di, dx ; 09 d7 ; 0xf8387
+ mov word [es:si], di ; 26 89 3c ; 0xf8389
+ mov word [es:si+002h], ax ; 26 89 44 02 ; 0xf838c
+ mov word [es:si+004h], strict word 00000h ; 26 c7 44 04 00 00 ; 0xf8390 ahci.c:307
+ mov word [es:si+006h], strict word 00000h ; 26 c7 44 06 00 00 ; 0xf8396
+ lea ax, [si+00080h] ; 8d 84 80 00 ; 0xf839c ahci.c:308
+ mov dx, cx ; 89 ca ; 0xf83a0
+ call 08337h ; e8 92 ff ; 0xf83a2
+ mov es, cx ; 8e c1 ; 0xf83a5
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf83a7
+ mov word [es:si+00ah], dx ; 26 89 54 0a ; 0xf83ab
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf83af ahci.c:311
+ xor ah, ah ; 30 e4 ; 0xf83b2
+ mov di, ax ; 89 c7 ; 0xf83b4
+ sal di, 007h ; c1 e7 07 ; 0xf83b6
+ lea ax, [di+00118h] ; 8d 85 18 01 ; 0xf83b9
+ xor cx, cx ; 31 c9 ; 0xf83bd ahci.c:252
+ mov dx, bx ; 89 da ; 0xf83bf
+ xchg cx, ax ; 91 ; 0xf83c1
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf83c2
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf83c6
+ out DX, eax ; 66 ef ; 0xf83c8
+ lea si, [bx+004h] ; 8d 77 04 ; 0xf83ca ahci.c:253
+ mov dx, si ; 89 f2 ; 0xf83cd
+ in eax, DX ; 66 ed ; 0xf83cf
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf83d1
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf83d3
+ xchg dx, ax ; 92 ; 0xf83d7
+ or AL, strict byte 011h ; 0c 11 ; 0xf83d8
+ mov cx, dx ; 89 d1 ; 0xf83da
+ mov dx, si ; 89 f2 ; 0xf83dc
+ xchg cx, ax ; 91 ; 0xf83de
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf83df
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf83e3
+ out DX, eax ; 66 ef ; 0xf83e5
+ lea ax, [di+00138h] ; 8d 85 38 01 ; 0xf83e7 ahci.c:315
+ cwd ; 99 ; 0xf83eb
+ mov cx, dx ; 89 d1 ; 0xf83ec
+ mov dx, bx ; 89 da ; 0xf83ee
+ xchg cx, ax ; 91 ; 0xf83f0
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf83f1
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf83f5
+ out DX, eax ; 66 ef ; 0xf83f7
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf83f9
+ xor cx, cx ; 31 c9 ; 0xf83fc
+ mov dx, si ; 89 f2 ; 0xf83fe
+ xchg cx, ax ; 91 ; 0xf8400
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8401
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8405
+ out DX, eax ; 66 ef ; 0xf8407
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8409 ahci.c:319
+ xor ah, ah ; 30 e4 ; 0xf840c
+ sal ax, 007h ; c1 e0 07 ; 0xf840e
+ add ax, 00110h ; 05 10 01 ; 0xf8411
+ xor cx, cx ; 31 c9 ; 0xf8414 ahci.c:271
+ mov dx, bx ; 89 da ; 0xf8416
+ xchg cx, ax ; 91 ; 0xf8418
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8419
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf841d
+ out DX, eax ; 66 ef ; 0xf841f
+ lea dx, [bx+004h] ; 8d 57 04 ; 0xf8421 ahci.c:272
+ in eax, DX ; 66 ed ; 0xf8424
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8426
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8428
+ xchg dx, ax ; 92 ; 0xf842c
+ test dh, 040h ; f6 c6 40 ; 0xf842d
+ jne short 08436h ; 75 04 ; 0xf8430
+ test AL, strict byte 001h ; a8 01 ; 0xf8432
+ je short 0843ah ; 74 04 ; 0xf8434
+ mov AL, strict byte 001h ; b0 01 ; 0xf8436
+ jmp short 0843ch ; eb 02 ; 0xf8438
+ xor al, al ; 30 c0 ; 0xf843a
+ test al, al ; 84 c0 ; 0xf843c ahci.c:273
+ je short 08409h ; 74 c9 ; 0xf843e
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8440 ahci.c:325
+ xor ah, ah ; 30 e4 ; 0xf8443
+ mov di, ax ; 89 c7 ; 0xf8445
+ sal di, 007h ; c1 e7 07 ; 0xf8447
+ lea ax, [di+00110h] ; 8d 85 10 01 ; 0xf844a
+ xor cx, cx ; 31 c9 ; 0xf844e ahci.c:252
+ mov dx, bx ; 89 da ; 0xf8450
+ xchg cx, ax ; 91 ; 0xf8452
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8453
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8457
+ out DX, eax ; 66 ef ; 0xf8459
+ lea si, [bx+004h] ; 8d 77 04 ; 0xf845b ahci.c:253
+ mov dx, si ; 89 f2 ; 0xf845e
+ in eax, DX ; 66 ed ; 0xf8460
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8462
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8464
+ xchg dx, ax ; 92 ; 0xf8468
+ or AL, strict byte 001h ; 0c 01 ; 0xf8469
+ mov cx, dx ; 89 d1 ; 0xf846b
+ mov dx, si ; 89 f2 ; 0xf846d
+ xchg cx, ax ; 91 ; 0xf846f
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8470
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8474
+ out DX, eax ; 66 ef ; 0xf8476
+ lea ax, [di+00118h] ; 8d 85 18 01 ; 0xf8478 ahci.c:329
+ xor cx, cx ; 31 c9 ; 0xf847c ahci.c:261
+ mov dx, bx ; 89 da ; 0xf847e
+ xchg cx, ax ; 91 ; 0xf8480
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8481
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8485
+ out DX, eax ; 66 ef ; 0xf8487
+ mov dx, si ; 89 f2 ; 0xf8489 ahci.c:262
+ in eax, DX ; 66 ed ; 0xf848b
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf848d
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf848f
+ xchg dx, ax ; 92 ; 0xf8493
+ and AL, strict byte 0feh ; 24 fe ; 0xf8494
+ mov cx, dx ; 89 d1 ; 0xf8496
+ mov dx, si ; 89 f2 ; 0xf8498
+ xchg cx, ax ; 91 ; 0xf849a
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf849b
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf849f
+ out DX, eax ; 66 ef ; 0xf84a1
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf84a3 ahci.c:335
+ pop di ; 5f ; 0xf84a6
+ pop si ; 5e ; 0xf84a7
+ pop cx ; 59 ; 0xf84a8
+ pop bp ; 5d ; 0xf84a9
+ retn ; c3 ; 0xf84aa
+ ; disGetNextSymbol 0xf84ab LB 0x1a1d -> off=0x0 cb=0000000000000267 uValue=00000000000f6eab 'ahci_cmd_data'
+ahci_cmd_data: ; 0xf84ab LB 0x267
+ push bp ; 55 ; 0xf84ab ahci.c:340
+ mov bp, sp ; 89 e5 ; 0xf84ac
+ push cx ; 51 ; 0xf84ae
+ push si ; 56 ; 0xf84af
+ push di ; 57 ; 0xf84b0
+ sub sp, strict byte 0000ch ; 83 ec 0c ; 0xf84b1
+ push ax ; 50 ; 0xf84b4
+ push dx ; 52 ; 0xf84b5
+ mov byte [bp-008h], bl ; 88 5e f8 ; 0xf84b6
+ xor di, di ; 31 ff ; 0xf84b9 ahci.c:342
+ mov es, dx ; 8e c2 ; 0xf84bb
+ mov bx, ax ; 89 c3 ; 0xf84bd
+ mov ax, word [es:bx+00232h] ; 26 8b 87 32 02 ; 0xf84bf
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf84c4
+ mov word [bp-00eh], di ; 89 7e f2 ; 0xf84c7
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf84ca
+ mov ax, word [es:bx+00eh] ; 26 8b 47 0e ; 0xf84cd ahci.c:343
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf84d1
+ mov ax, word [es:bx+010h] ; 26 8b 47 10 ; 0xf84d4 ahci.c:344
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf84d8
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf84db ahci.c:347
+ xor bx, bx ; 31 db ; 0xf84de
+ mov ax, 00080h ; b8 80 00 ; 0xf84e0
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf84e3
+ call 09bb0h ; e8 c7 16 ; 0xf84e6
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf84e9 ahci.c:350
+ mov word [es:di+00080h], 08027h ; 26 c7 85 80 00 27 80 ; 0xf84ec
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf84f3 ahci.c:352
+ mov byte [es:di+00082h], al ; 26 88 85 82 00 ; 0xf84f6
+ mov byte [es:di+00083h], 000h ; 26 c6 85 83 00 00 ; 0xf84fb ahci.c:353
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8501 ahci.c:355
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf8504
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf8507
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf850a
+ mov byte [es:di+00084h], al ; 26 88 85 84 00 ; 0xf850d
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8512 ahci.c:356
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf8515
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf8519
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf851d
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf8520
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf8524
+ mov si, strict word 00008h ; be 08 00 ; 0xf8527
+ call 09b90h ; e8 63 16 ; 0xf852a
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf852d
+ mov byte [es:di+00085h], dl ; 26 88 95 85 00 ; 0xf8530
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8535 ahci.c:357
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf8538
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf853b
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf853f
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf8543
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf8546
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf854a
+ mov si, strict word 00010h ; be 10 00 ; 0xf854d
+ call 09b90h ; e8 3d 16 ; 0xf8550
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8553
+ mov byte [es:di+00086h], dl ; 26 88 95 86 00 ; 0xf8556
+ mov byte [es:di+00087h], 040h ; 26 c6 85 87 00 40 ; 0xf855b ahci.c:358
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8561 ahci.c:360
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf8564
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf8567
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf856b
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf856f
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf8572
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf8576
+ mov si, strict word 00018h ; be 18 00 ; 0xf8579
+ call 09b90h ; e8 11 16 ; 0xf857c
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf857f
+ mov byte [es:di+00088h], dl ; 26 88 95 88 00 ; 0xf8582
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8587 ahci.c:361
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf858a
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf858d
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf8591
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf8595
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf8598
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf859c
+ mov si, strict word 00020h ; be 20 00 ; 0xf859f
+ call 09b90h ; e8 eb 15 ; 0xf85a2
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf85a5
+ mov byte [es:di+00089h], dl ; 26 88 95 89 00 ; 0xf85a8
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf85ad ahci.c:362
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf85b0
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf85b3
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf85b7
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf85bb
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf85be
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf85c2
+ mov si, strict word 00028h ; be 28 00 ; 0xf85c5
+ call 09b90h ; e8 c5 15 ; 0xf85c8
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf85cb
+ mov byte [es:di+0008ah], dl ; 26 88 95 8a 00 ; 0xf85ce
+ mov byte [es:di+0008bh], 000h ; 26 c6 85 8b 00 00 ; 0xf85d3 ahci.c:363
+ mov al, byte [bp-012h] ; 8a 46 ee ; 0xf85d9 ahci.c:365
+ mov byte [es:di+0008ch], al ; 26 88 85 8c 00 ; 0xf85dc
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf85e1 ahci.c:366
+ shr ax, 008h ; c1 e8 08 ; 0xf85e4
+ mov byte [es:di+0008dh], al ; 26 88 85 8d 00 ; 0xf85e7
+ mov word [es:di+00276h], strict word 00010h ; 26 c7 85 76 02 10 00 ; 0xf85ec ahci.c:369
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf85f3 ahci.c:372
+ xor dx, dx ; 31 d2 ; 0xf85f6
+ mov bx, word [bp-010h] ; 8b 5e f0 ; 0xf85f8
+ xor cx, cx ; 31 c9 ; 0xf85fb
+ call 09b40h ; e8 40 15 ; 0xf85fd
+ push dx ; 52 ; 0xf8600
+ push ax ; 50 ; 0xf8601
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8602
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf8605
+ mov bx, word [es:bx+008h] ; 26 8b 5f 08 ; 0xf8608
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf860c
+ mov cx, word [es:si+00ah] ; 26 8b 4c 0a ; 0xf860f
+ mov ax, 0026ah ; b8 6a 02 ; 0xf8613
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8616
+ call 09a8fh ; e8 73 14 ; 0xf8619
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf861c ahci.c:375
+ mov dx, word [es:di+0027eh] ; 26 8b 95 7e 02 ; 0xf861f
+ add dx, strict byte 0ffffh ; 83 c2 ff ; 0xf8624
+ mov ax, word [es:di+00280h] ; 26 8b 85 80 02 ; 0xf8627
+ adc ax, strict word 0ffffh ; 15 ff ff ; 0xf862c
+ mov bl, byte [es:di+00263h] ; 26 8a 9d 63 02 ; 0xf862f
+ xor bh, bh ; 30 ff ; 0xf8634
+ sal bx, 004h ; c1 e3 04 ; 0xf8636
+ mov word [es:bx+0010ch], dx ; 26 89 97 0c 01 ; 0xf8639
+ mov word [es:bx+0010eh], ax ; 26 89 87 0e 01 ; 0xf863e
+ mov bl, byte [es:di+00263h] ; 26 8a 9d 63 02 ; 0xf8643 ahci.c:376
+ xor bh, bh ; 30 ff ; 0xf8648
+ sal bx, 004h ; c1 e3 04 ; 0xf864a
+ mov ax, word [es:di+0027ah] ; 26 8b 85 7a 02 ; 0xf864d
+ mov dx, word [es:di+0027ch] ; 26 8b 95 7c 02 ; 0xf8652
+ mov word [es:bx+00100h], ax ; 26 89 87 00 01 ; 0xf8657
+ mov word [es:bx+00102h], dx ; 26 89 97 02 01 ; 0xf865c
+ inc byte [es:di+00263h] ; 26 fe 85 63 02 ; 0xf8661 ahci.c:377
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8666 ahci.c:379
+ mov bx, si ; 89 f3 ; 0xf8669
+ mov ax, word [es:bx+020h] ; 26 8b 47 20 ; 0xf866b
+ test ax, ax ; 85 c0 ; 0xf866f
+ je short 086aeh ; 74 3b ; 0xf8671
+ dec ax ; 48 ; 0xf8673 ahci.c:380
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8674
+ mov bl, byte [es:di+00263h] ; 26 8a 9d 63 02 ; 0xf8677
+ xor bh, bh ; 30 ff ; 0xf867c
+ sal bx, 004h ; c1 e3 04 ; 0xf867e
+ mov word [es:bx+0010ch], ax ; 26 89 87 0c 01 ; 0xf8681
+ mov word [es:bx+0010eh], di ; 26 89 bf 0e 01 ; 0xf8686
+ mov bl, byte [es:di+00263h] ; 26 8a 9d 63 02 ; 0xf868b ahci.c:381
+ xor bh, bh ; 30 ff ; 0xf8690
+ sal bx, 004h ; c1 e3 04 ; 0xf8692
+ mov dx, word [es:di+00264h] ; 26 8b 95 64 02 ; 0xf8695
+ mov ax, word [es:di+00266h] ; 26 8b 85 66 02 ; 0xf869a
+ mov word [es:bx+00100h], dx ; 26 89 97 00 01 ; 0xf869f
+ mov word [es:bx+00102h], ax ; 26 89 87 02 01 ; 0xf86a4
+ inc byte [es:di+00263h] ; 26 fe 85 63 02 ; 0xf86a9 ahci.c:382
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf86ae ahci.c:397
+ cmp AL, strict byte 035h ; 3c 35 ; 0xf86b1
+ jne short 086bbh ; 75 06 ; 0xf86b3
+ mov byte [bp-008h], 040h ; c6 46 f8 40 ; 0xf86b5 ahci.c:398
+ jmp short 086d2h ; eb 17 ; 0xf86b9 ahci.c:399
+ cmp AL, strict byte 0a0h ; 3c a0 ; 0xf86bb
+ jne short 086ceh ; 75 0f ; 0xf86bd
+ or byte [bp-008h], 020h ; 80 4e f8 20 ; 0xf86bf ahci.c:400
+ les bx, [bp-00eh] ; c4 5e f2 ; 0xf86c3 ahci.c:401
+ or byte [es:bx+00083h], 001h ; 26 80 8f 83 00 01 ; 0xf86c6
+ jmp short 086d2h ; eb 04 ; 0xf86cc ahci.c:402
+ mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xf86ce ahci.c:403
+ or byte [bp-008h], 005h ; 80 4e f8 05 ; 0xf86d2 ahci.c:405
+ mov bl, byte [bp-008h] ; 8a 5e f8 ; 0xf86d6 ahci.c:407
+ xor bh, bh ; 30 ff ; 0xf86d9
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf86db
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf86de
+ call 08355h ; e8 71 fc ; 0xf86e1
+ mov cx, word [bp-00ch] ; 8b 4e f4 ; 0xf86e4 ahci.c:410
+ mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xf86e7
+ add bx, 00240h ; 81 c3 40 02 ; 0xf86ea
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf86ee ahci.c:414
+ add ax, 0026ah ; 05 6a 02 ; 0xf86f1
+ mov dx, cx ; 89 ca ; 0xf86f4
+ call 09b06h ; e8 0d 14 ; 0xf86f6
+ mov es, cx ; 8e c1 ; 0xf86f9 ahci.c:415
+ mov al, byte [es:bx+003h] ; 26 8a 47 03 ; 0xf86fb
+ test al, al ; 84 c0 ; 0xf86ff
+ je short 08708h ; 74 05 ; 0xf8701
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf8703
+ jmp short 0870ah ; eb 02 ; 0xf8706
+ xor ah, ah ; 30 e4 ; 0xf8708
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf870a ahci.c:416
+ pop di ; 5f ; 0xf870d
+ pop si ; 5e ; 0xf870e
+ pop cx ; 59 ; 0xf870f
+ pop bp ; 5d ; 0xf8710
+ retn ; c3 ; 0xf8711
+ ; disGetNextSymbol 0xf8712 LB 0x17b6 -> off=0x0 cb=0000000000000180 uValue=00000000000f7112 'ahci_port_deinit_current'
+ahci_port_deinit_current: ; 0xf8712 LB 0x180
+ push bp ; 55 ; 0xf8712 ahci.c:421
+ mov bp, sp ; 89 e5 ; 0xf8713
+ push bx ; 53 ; 0xf8715
+ push cx ; 51 ; 0xf8716
+ push si ; 56 ; 0xf8717
+ push di ; 57 ; 0xf8718
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf8719
+ mov di, ax ; 89 c7 ; 0xf871c
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf871e
+ mov es, dx ; 8e c2 ; 0xf8721 ahci.c:426
+ mov si, word [es:di+00260h] ; 26 8b b5 60 02 ; 0xf8723
+ mov al, byte [es:di+00262h] ; 26 8a 85 62 02 ; 0xf8728 ahci.c:427
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf872d
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xf8730 ahci.c:429
+ je short 08793h ; 74 5f ; 0xf8732
+ xor ah, ah ; 30 e4 ; 0xf8734 ahci.c:432
+ sal ax, 007h ; c1 e0 07 ; 0xf8736
+ add ax, 00118h ; 05 18 01 ; 0xf8739
+ xor cx, cx ; 31 c9 ; 0xf873c ahci.c:261
+ mov dx, si ; 89 f2 ; 0xf873e
+ xchg cx, ax ; 91 ; 0xf8740
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8741
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8745
+ out DX, eax ; 66 ef ; 0xf8747
+ lea bx, [si+004h] ; 8d 5c 04 ; 0xf8749 ahci.c:262
+ mov dx, bx ; 89 da ; 0xf874c
+ in eax, DX ; 66 ed ; 0xf874e
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8750
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8752
+ xchg dx, ax ; 92 ; 0xf8756
+ and AL, strict byte 0eeh ; 24 ee ; 0xf8757
+ mov cx, dx ; 89 d1 ; 0xf8759
+ mov dx, bx ; 89 da ; 0xf875b
+ xchg cx, ax ; 91 ; 0xf875d
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf875e
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8762
+ out DX, eax ; 66 ef ; 0xf8764
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf8766 ahci.c:435
+ xor ah, ah ; 30 e4 ; 0xf8769
+ sal ax, 007h ; c1 e0 07 ; 0xf876b
+ add ax, 00118h ; 05 18 01 ; 0xf876e
+ xor cx, cx ; 31 c9 ; 0xf8771 ahci.c:271
+ mov dx, si ; 89 f2 ; 0xf8773
+ xchg cx, ax ; 91 ; 0xf8775
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8776
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf877a
+ out DX, eax ; 66 ef ; 0xf877c
+ lea dx, [si+004h] ; 8d 54 04 ; 0xf877e ahci.c:272
+ in eax, DX ; 66 ed ; 0xf8781
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8783
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8785
+ xchg dx, ax ; 92 ; 0xf8789
+ test ax, 0c011h ; a9 11 c0 ; 0xf878a
+ je short 08796h ; 74 07 ; 0xf878d
+ mov AL, strict byte 001h ; b0 01 ; 0xf878f
+ jmp short 08798h ; eb 05 ; 0xf8791
+ jmp near 08889h ; e9 f3 00 ; 0xf8793
+ xor al, al ; 30 c0 ; 0xf8796
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf8798 ahci.c:273
+ je short 08766h ; 74 ca ; 0xf879a
+ mov cx, strict word 00020h ; b9 20 00 ; 0xf879c ahci.c:446
+ xor bx, bx ; 31 db ; 0xf879f
+ mov ax, di ; 89 f8 ; 0xf87a1
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf87a3
+ call 09bb0h ; e8 07 14 ; 0xf87a6
+ lea ax, [di+00080h] ; 8d 85 80 00 ; 0xf87a9 ahci.c:447
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf87ad
+ xor bx, bx ; 31 db ; 0xf87b0
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf87b2
+ call 09bb0h ; e8 f8 13 ; 0xf87b5
+ lea ax, [di+00200h] ; 8d 85 00 02 ; 0xf87b8 ahci.c:448
+ mov cx, strict word 00060h ; b9 60 00 ; 0xf87bc
+ xor bx, bx ; 31 db ; 0xf87bf
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf87c1
+ call 09bb0h ; e8 e9 13 ; 0xf87c4
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf87c7 ahci.c:450
+ xor ah, ah ; 30 e4 ; 0xf87ca
+ sal ax, 007h ; c1 e0 07 ; 0xf87cc
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf87cf
+ add ax, 00108h ; 05 08 01 ; 0xf87d2
+ cwd ; 99 ; 0xf87d5
+ mov cx, dx ; 89 d1 ; 0xf87d6
+ mov dx, si ; 89 f2 ; 0xf87d8
+ xchg cx, ax ; 91 ; 0xf87da
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf87db
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf87df
+ out DX, eax ; 66 ef ; 0xf87e1
+ lea bx, [si+004h] ; 8d 5c 04 ; 0xf87e3
+ xor ax, ax ; 31 c0 ; 0xf87e6
+ xor cx, cx ; 31 c9 ; 0xf87e8
+ mov dx, bx ; 89 da ; 0xf87ea
+ xchg cx, ax ; 91 ; 0xf87ec
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf87ed
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf87f1
+ out DX, eax ; 66 ef ; 0xf87f3
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf87f5 ahci.c:451
+ add ax, 0010ch ; 05 0c 01 ; 0xf87f8
+ cwd ; 99 ; 0xf87fb
+ mov cx, dx ; 89 d1 ; 0xf87fc
+ mov dx, si ; 89 f2 ; 0xf87fe
+ xchg cx, ax ; 91 ; 0xf8800
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8801
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8805
+ out DX, eax ; 66 ef ; 0xf8807
+ xor ax, ax ; 31 c0 ; 0xf8809
+ xor cx, cx ; 31 c9 ; 0xf880b
+ mov dx, bx ; 89 da ; 0xf880d
+ xchg cx, ax ; 91 ; 0xf880f
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8810
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8814
+ out DX, eax ; 66 ef ; 0xf8816
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf8818 ahci.c:453
+ db 0feh, 0c4h
+ ; inc ah ; fe c4 ; 0xf881b
+ cwd ; 99 ; 0xf881d
+ mov cx, dx ; 89 d1 ; 0xf881e
+ mov dx, si ; 89 f2 ; 0xf8820
+ xchg cx, ax ; 91 ; 0xf8822
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8823
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8827
+ out DX, eax ; 66 ef ; 0xf8829
+ xor ax, ax ; 31 c0 ; 0xf882b
+ xor cx, cx ; 31 c9 ; 0xf882d
+ mov dx, bx ; 89 da ; 0xf882f
+ xchg cx, ax ; 91 ; 0xf8831
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8832
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8836
+ out DX, eax ; 66 ef ; 0xf8838
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf883a ahci.c:454
+ add ax, 00104h ; 05 04 01 ; 0xf883d
+ cwd ; 99 ; 0xf8840
+ mov cx, dx ; 89 d1 ; 0xf8841
+ mov dx, si ; 89 f2 ; 0xf8843
+ xchg cx, ax ; 91 ; 0xf8845
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8846
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf884a
+ out DX, eax ; 66 ef ; 0xf884c
+ xor ax, ax ; 31 c0 ; 0xf884e
+ xor cx, cx ; 31 c9 ; 0xf8850
+ mov dx, bx ; 89 da ; 0xf8852
+ xchg cx, ax ; 91 ; 0xf8854
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8855
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8859
+ out DX, eax ; 66 ef ; 0xf885b
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf885d ahci.c:457
+ add ax, 00114h ; 05 14 01 ; 0xf8860
+ cwd ; 99 ; 0xf8863
+ mov cx, dx ; 89 d1 ; 0xf8864
+ mov dx, si ; 89 f2 ; 0xf8866
+ xchg cx, ax ; 91 ; 0xf8868
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8869
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf886d
+ out DX, eax ; 66 ef ; 0xf886f
+ xor ax, ax ; 31 c0 ; 0xf8871
+ xor cx, cx ; 31 c9 ; 0xf8873
+ mov dx, bx ; 89 da ; 0xf8875
+ xchg cx, ax ; 91 ; 0xf8877
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8878
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf887c
+ out DX, eax ; 66 ef ; 0xf887e
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf8880 ahci.c:459
+ mov byte [es:di+00262h], 0ffh ; 26 c6 85 62 02 ff ; 0xf8883
+ lea sp, [bp-008h] ; 8d 66 f8 ; 0xf8889 ahci.c:461
+ pop di ; 5f ; 0xf888c
+ pop si ; 5e ; 0xf888d
+ pop cx ; 59 ; 0xf888e
+ pop bx ; 5b ; 0xf888f
+ pop bp ; 5d ; 0xf8890
+ retn ; c3 ; 0xf8891
+ ; disGetNextSymbol 0xf8892 LB 0x1636 -> off=0x0 cb=000000000000024d uValue=00000000000f7292 'ahci_port_init'
+ahci_port_init: ; 0xf8892 LB 0x24d
+ push bp ; 55 ; 0xf8892 ahci.c:467
+ mov bp, sp ; 89 e5 ; 0xf8893
+ push cx ; 51 ; 0xf8895
+ push si ; 56 ; 0xf8896
+ push di ; 57 ; 0xf8897
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf8898
+ mov si, ax ; 89 c6 ; 0xf889b
+ mov word [bp-00ah], dx ; 89 56 f6 ; 0xf889d
+ mov byte [bp-008h], bl ; 88 5e f8 ; 0xf88a0
+ call 08712h ; e8 6c fe ; 0xf88a3 ahci.c:470
+ mov al, bl ; 88 d8 ; 0xf88a6 ahci.c:473
+ xor ah, ah ; 30 e4 ; 0xf88a8
+ sal ax, 007h ; c1 e0 07 ; 0xf88aa
+ add ax, 00118h ; 05 18 01 ; 0xf88ad
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf88b0 ahci.c:259
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf88b3
+ xor cx, cx ; 31 c9 ; 0xf88b8 ahci.c:261
+ mov dx, bx ; 89 da ; 0xf88ba
+ xchg cx, ax ; 91 ; 0xf88bc
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf88bd
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf88c1
+ out DX, eax ; 66 ef ; 0xf88c3
+ add bx, strict byte 00004h ; 83 c3 04 ; 0xf88c5 ahci.c:262
+ mov dx, bx ; 89 da ; 0xf88c8
+ in eax, DX ; 66 ed ; 0xf88ca
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf88cc
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf88ce
+ xchg dx, ax ; 92 ; 0xf88d2
+ and AL, strict byte 0eeh ; 24 ee ; 0xf88d3
+ mov cx, dx ; 89 d1 ; 0xf88d5
+ mov dx, bx ; 89 da ; 0xf88d7
+ xchg cx, ax ; 91 ; 0xf88d9
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf88da
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf88de
+ out DX, eax ; 66 ef ; 0xf88e0
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf88e2 ahci.c:476
+ xor ah, ah ; 30 e4 ; 0xf88e5
+ sal ax, 007h ; c1 e0 07 ; 0xf88e7
+ add ax, 00118h ; 05 18 01 ; 0xf88ea
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf88ed ahci.c:269
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf88f0
+ xor cx, cx ; 31 c9 ; 0xf88f5 ahci.c:271
+ mov dx, bx ; 89 da ; 0xf88f7
+ xchg cx, ax ; 91 ; 0xf88f9
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf88fa
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf88fe
+ out DX, eax ; 66 ef ; 0xf8900
+ lea dx, [bx+004h] ; 8d 57 04 ; 0xf8902 ahci.c:272
+ in eax, DX ; 66 ed ; 0xf8905
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8907
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8909
+ xchg dx, ax ; 92 ; 0xf890d
+ test ax, 0c011h ; a9 11 c0 ; 0xf890e
+ je short 08917h ; 74 04 ; 0xf8911
+ mov AL, strict byte 001h ; b0 01 ; 0xf8913
+ jmp short 08919h ; eb 02 ; 0xf8915
+ xor al, al ; 30 c0 ; 0xf8917
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf8919 ahci.c:273
+ je short 088e2h ; 74 c5 ; 0xf891b
+ mov cx, strict word 00020h ; b9 20 00 ; 0xf891d ahci.c:487
+ xor bx, bx ; 31 db ; 0xf8920
+ mov ax, si ; 89 f0 ; 0xf8922
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8924
+ call 09bb0h ; e8 86 12 ; 0xf8927
+ lea ax, [si+00080h] ; 8d 84 80 00 ; 0xf892a ahci.c:488
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf892e
+ xor bx, bx ; 31 db ; 0xf8931
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8933
+ call 09bb0h ; e8 77 12 ; 0xf8936
+ lea di, [si+00200h] ; 8d bc 00 02 ; 0xf8939 ahci.c:489
+ mov cx, strict word 00060h ; b9 60 00 ; 0xf893d
+ xor bx, bx ; 31 db ; 0xf8940
+ mov ax, di ; 89 f8 ; 0xf8942
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8944
+ call 09bb0h ; e8 66 12 ; 0xf8947
+ mov bl, byte [bp-008h] ; 8a 5e f8 ; 0xf894a ahci.c:493
+ xor bh, bh ; 30 ff ; 0xf894d
+ sal bx, 007h ; c1 e3 07 ; 0xf894f
+ lea ax, [bx+00108h] ; 8d 87 08 01 ; 0xf8952
+ cwd ; 99 ; 0xf8956
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8957
+ mov cx, word [es:si+00260h] ; 26 8b 8c 60 02 ; 0xf895a
+ mov word [bp-00ch], cx ; 89 4e f4 ; 0xf895f
+ mov cx, dx ; 89 d1 ; 0xf8962
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf8964
+ xchg cx, ax ; 91 ; 0xf8967
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8968
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf896c
+ out DX, eax ; 66 ef ; 0xf896e
+ mov ax, di ; 89 f8 ; 0xf8970
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8972
+ call 08337h ; e8 bf f9 ; 0xf8975
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8978
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf897b
+ add di, strict byte 00004h ; 83 c7 04 ; 0xf8980
+ mov cx, dx ; 89 d1 ; 0xf8983
+ mov dx, di ; 89 fa ; 0xf8985
+ xchg cx, ax ; 91 ; 0xf8987
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8988
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf898c
+ out DX, eax ; 66 ef ; 0xf898e
+ lea ax, [bx+0010ch] ; 8d 87 0c 01 ; 0xf8990 ahci.c:494
+ cwd ; 99 ; 0xf8994
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8995
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8998
+ mov cx, dx ; 89 d1 ; 0xf899d
+ mov dx, di ; 89 fa ; 0xf899f
+ xchg cx, ax ; 91 ; 0xf89a1
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf89a2
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf89a6
+ out DX, eax ; 66 ef ; 0xf89a8
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf89aa
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf89ad
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf89b2
+ xor ax, ax ; 31 c0 ; 0xf89b5
+ xor cx, cx ; 31 c9 ; 0xf89b7
+ xchg cx, ax ; 91 ; 0xf89b9
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf89ba
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf89be
+ out DX, eax ; 66 ef ; 0xf89c0
+ lea ax, [bx+00100h] ; 8d 87 00 01 ; 0xf89c2 ahci.c:497
+ cwd ; 99 ; 0xf89c6
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf89c7
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf89ca
+ mov cx, dx ; 89 d1 ; 0xf89cf
+ mov dx, di ; 89 fa ; 0xf89d1
+ xchg cx, ax ; 91 ; 0xf89d3
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf89d4
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf89d8
+ out DX, eax ; 66 ef ; 0xf89da
+ mov ax, si ; 89 f0 ; 0xf89dc
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf89de
+ call 08337h ; e8 53 f9 ; 0xf89e1
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf89e4
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf89e7
+ add di, strict byte 00004h ; 83 c7 04 ; 0xf89ec
+ mov cx, dx ; 89 d1 ; 0xf89ef
+ mov dx, di ; 89 fa ; 0xf89f1
+ xchg cx, ax ; 91 ; 0xf89f3
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf89f4
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf89f8
+ out DX, eax ; 66 ef ; 0xf89fa
+ lea ax, [bx+00104h] ; 8d 87 04 01 ; 0xf89fc ahci.c:498
+ cwd ; 99 ; 0xf8a00
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a01
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8a04
+ mov cx, dx ; 89 d1 ; 0xf8a09
+ mov dx, di ; 89 fa ; 0xf8a0b
+ xchg cx, ax ; 91 ; 0xf8a0d
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8a0e
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8a12
+ out DX, eax ; 66 ef ; 0xf8a14
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a16
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8a19
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8a1e
+ xor ax, ax ; 31 c0 ; 0xf8a21
+ xor cx, cx ; 31 c9 ; 0xf8a23
+ xchg cx, ax ; 91 ; 0xf8a25
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8a26
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8a2a
+ out DX, eax ; 66 ef ; 0xf8a2c
+ lea ax, [bx+00114h] ; 8d 87 14 01 ; 0xf8a2e ahci.c:501
+ cwd ; 99 ; 0xf8a32
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a33
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8a36
+ mov cx, dx ; 89 d1 ; 0xf8a3b
+ mov dx, di ; 89 fa ; 0xf8a3d
+ xchg cx, ax ; 91 ; 0xf8a3f
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8a40
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8a44
+ out DX, eax ; 66 ef ; 0xf8a46
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a48
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8a4b
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8a50
+ xor ax, ax ; 31 c0 ; 0xf8a53
+ xor cx, cx ; 31 c9 ; 0xf8a55
+ xchg cx, ax ; 91 ; 0xf8a57
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8a58
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8a5c
+ out DX, eax ; 66 ef ; 0xf8a5e
+ lea ax, [bx+00110h] ; 8d 87 10 01 ; 0xf8a60 ahci.c:502
+ cwd ; 99 ; 0xf8a64
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a65
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8a68
+ mov cx, dx ; 89 d1 ; 0xf8a6d
+ mov dx, di ; 89 fa ; 0xf8a6f
+ xchg cx, ax ; 91 ; 0xf8a71
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8a72
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8a76
+ out DX, eax ; 66 ef ; 0xf8a78
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a7a
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8a7d
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8a82
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf8a85
+ mov cx, ax ; 89 c1 ; 0xf8a88
+ xchg cx, ax ; 91 ; 0xf8a8a
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8a8b
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8a8f
+ out DX, eax ; 66 ef ; 0xf8a91
+ lea ax, [bx+00130h] ; 8d 87 30 01 ; 0xf8a93 ahci.c:504
+ cwd ; 99 ; 0xf8a97
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a98
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8a9b
+ mov cx, dx ; 89 d1 ; 0xf8aa0
+ mov dx, bx ; 89 da ; 0xf8aa2
+ xchg cx, ax ; 91 ; 0xf8aa4
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8aa5
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8aa9
+ out DX, eax ; 66 ef ; 0xf8aab
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8aad
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8ab0
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8ab5
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf8ab8
+ mov cx, ax ; 89 c1 ; 0xf8abb
+ xchg cx, ax ; 91 ; 0xf8abd
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8abe
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8ac2
+ out DX, eax ; 66 ef ; 0xf8ac4
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8ac6 ahci.c:506
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8ac9
+ mov byte [es:si+00262h], al ; 26 88 84 62 02 ; 0xf8acc
+ mov byte [es:si+00263h], 000h ; 26 c6 84 63 02 00 ; 0xf8ad1 ahci.c:507
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf8ad7 ahci.c:508
+ pop di ; 5f ; 0xf8ada
+ pop si ; 5e ; 0xf8adb
+ pop cx ; 59 ; 0xf8adc
+ pop bp ; 5d ; 0xf8add
+ retn ; c3 ; 0xf8ade
+ ; disGetNextSymbol 0xf8adf LB 0x13e9 -> off=0x0 cb=00000000000000a8 uValue=00000000000f74df 'ahci_read_sectors'
+ahci_read_sectors: ; 0xf8adf LB 0xa8
+ push bp ; 55 ; 0xf8adf ahci.c:517
+ mov bp, sp ; 89 e5 ; 0xf8ae0
+ push si ; 56 ; 0xf8ae2
+ push di ; 57 ; 0xf8ae3
+ push ax ; 50 ; 0xf8ae4
+ les bx, [bp+004h] ; c4 5e 04 ; 0xf8ae5 ahci.c:522
+ mov bl, byte [es:bx+00ch] ; 26 8a 5f 0c ; 0xf8ae8
+ xor bh, bh ; 30 ff ; 0xf8aec
+ sub bx, strict byte 0000ch ; 83 eb 0c ; 0xf8aee
+ cmp bx, strict byte 00004h ; 83 fb 04 ; 0xf8af1 ahci.c:523
+ jbe short 08b05h ; 76 0f ; 0xf8af4
+ push bx ; 53 ; 0xf8af6 ahci.c:524
+ push 00c62h ; 68 62 0c ; 0xf8af7
+ push 00c74h ; 68 74 0c ; 0xf8afa
+ push strict byte 00007h ; 6a 07 ; 0xf8afd
+ call 018ffh ; e8 fd 8d ; 0xf8aff
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf8b02
+ xor di, di ; 31 ff ; 0xf8b05 ahci.c:530
+ les si, [bp+004h] ; c4 76 04 ; 0xf8b07
+ mov dx, word [es:si+00232h] ; 26 8b 94 32 02 ; 0xf8b0a
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8b0f ahci.c:239
+ mov es, dx ; 8e c2 ; 0xf8b13
+ mov word [es:di+00268h], ax ; 26 89 85 68 02 ; 0xf8b15
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf8b1a ahci.c:531
+ add bx, si ; 01 f3 ; 0xf8b1d
+ mov bl, byte [es:bx+0022dh] ; 26 8a 9f 2d 02 ; 0xf8b1f
+ xor bh, bh ; 30 ff ; 0xf8b24
+ mov di, si ; 89 f7 ; 0xf8b26
+ mov dx, word [es:di+00232h] ; 26 8b 95 32 02 ; 0xf8b28
+ xor ax, ax ; 31 c0 ; 0xf8b2d
+ call 08892h ; e8 60 fd ; 0xf8b2f
+ mov bx, strict word 00025h ; bb 25 00 ; 0xf8b32 ahci.c:532
+ mov ax, si ; 89 f0 ; 0xf8b35
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf8b37
+ call 084abh ; e8 6e f9 ; 0xf8b3a
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf8b3d
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf8b40 ahci.c:534
+ mov bx, si ; 89 f3 ; 0xf8b43
+ mov ax, word [es:bx+00eh] ; 26 8b 47 0e ; 0xf8b45
+ mov word [es:bx+018h], ax ; 26 89 47 18 ; 0xf8b49
+ mov cx, ax ; 89 c1 ; 0xf8b4d ahci.c:536
+ sal cx, 009h ; c1 e1 09 ; 0xf8b4f
+ shr cx, 1 ; d1 e9 ; 0xf8b52
+ mov di, word [es:di+008h] ; 26 8b 7d 08 ; 0xf8b54
+ mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xf8b58
+ mov si, di ; 89 fe ; 0xf8b5c
+ mov dx, ax ; 89 c2 ; 0xf8b5e
+ mov es, ax ; 8e c0 ; 0xf8b60
+ push DS ; 1e ; 0xf8b62
+ mov ds, dx ; 8e da ; 0xf8b63
+ rep movsw ; f3 a5 ; 0xf8b65
+ pop DS ; 1f ; 0xf8b67
+ xor bx, bx ; 31 db ; 0xf8b68 ahci.c:538
+ les di, [bp+004h] ; c4 7e 04 ; 0xf8b6a
+ mov es, [es:di+00232h] ; 26 8e 85 32 02 ; 0xf8b6d
+ mov ax, word [es:bx+00268h] ; 26 8b 87 68 02 ; 0xf8b72 ahci.c:244
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8b77
+ mov ax, word [bp-006h] ; 8b 46 fa ; 0xf8b7b ahci.c:540
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf8b7e
+ pop di ; 5f ; 0xf8b81
+ pop si ; 5e ; 0xf8b82
+ pop bp ; 5d ; 0xf8b83
+ retn 00004h ; c2 04 00 ; 0xf8b84
+ ; disGetNextSymbol 0xf8b87 LB 0x1341 -> off=0x0 cb=0000000000000086 uValue=00000000000f7587 'ahci_write_sectors'
+ahci_write_sectors: ; 0xf8b87 LB 0x86
+ push bp ; 55 ; 0xf8b87 ahci.c:549
+ mov bp, sp ; 89 e5 ; 0xf8b88
+ push si ; 56 ; 0xf8b8a
+ push di ; 57 ; 0xf8b8b
+ mov si, word [bp+004h] ; 8b 76 04 ; 0xf8b8c
+ mov cx, word [bp+006h] ; 8b 4e 06 ; 0xf8b8f
+ mov es, cx ; 8e c1 ; 0xf8b92 ahci.c:554
+ mov dl, byte [es:si+00ch] ; 26 8a 54 0c ; 0xf8b94
+ xor dh, dh ; 30 f6 ; 0xf8b98
+ sub dx, strict byte 0000ch ; 83 ea 0c ; 0xf8b9a
+ cmp dx, strict byte 00004h ; 83 fa 04 ; 0xf8b9d ahci.c:555
+ jbe short 08bb1h ; 76 0f ; 0xf8ba0
+ push dx ; 52 ; 0xf8ba2 ahci.c:556
+ push 00c93h ; 68 93 0c ; 0xf8ba3
+ push 00c74h ; 68 74 0c ; 0xf8ba6
+ push strict byte 00007h ; 6a 07 ; 0xf8ba9
+ call 018ffh ; e8 51 8d ; 0xf8bab
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf8bae
+ xor bx, bx ; 31 db ; 0xf8bb1 ahci.c:562
+ mov es, cx ; 8e c1 ; 0xf8bb3
+ mov di, word [es:si+00232h] ; 26 8b bc 32 02 ; 0xf8bb5
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8bba ahci.c:239
+ mov es, di ; 8e c7 ; 0xf8bbe
+ mov word [es:bx+00268h], ax ; 26 89 87 68 02 ; 0xf8bc0
+ mov es, cx ; 8e c1 ; 0xf8bc5 ahci.c:563
+ mov bx, si ; 89 f3 ; 0xf8bc7
+ add bx, dx ; 01 d3 ; 0xf8bc9
+ mov bl, byte [es:bx+0022dh] ; 26 8a 9f 2d 02 ; 0xf8bcb
+ xor bh, bh ; 30 ff ; 0xf8bd0
+ mov dx, word [es:si+00232h] ; 26 8b 94 32 02 ; 0xf8bd2
+ xor ax, ax ; 31 c0 ; 0xf8bd7
+ call 08892h ; e8 b6 fc ; 0xf8bd9
+ mov bx, strict word 00035h ; bb 35 00 ; 0xf8bdc ahci.c:564
+ mov ax, si ; 89 f0 ; 0xf8bdf
+ mov dx, cx ; 89 ca ; 0xf8be1
+ call 084abh ; e8 c5 f8 ; 0xf8be3
+ mov dx, ax ; 89 c2 ; 0xf8be6
+ mov es, cx ; 8e c1 ; 0xf8be8 ahci.c:566
+ mov ax, word [es:si+00eh] ; 26 8b 44 0e ; 0xf8bea
+ mov word [es:si+018h], ax ; 26 89 44 18 ; 0xf8bee
+ xor bx, bx ; 31 db ; 0xf8bf2 ahci.c:567
+ mov es, [es:si+00232h] ; 26 8e 84 32 02 ; 0xf8bf4
+ mov ax, word [es:bx+00268h] ; 26 8b 87 68 02 ; 0xf8bf9 ahci.c:244
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8bfe
+ mov ax, dx ; 89 d0 ; 0xf8c02 ahci.c:569
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf8c04
+ pop di ; 5f ; 0xf8c07
+ pop si ; 5e ; 0xf8c08
+ pop bp ; 5d ; 0xf8c09
+ retn 00004h ; c2 04 00 ; 0xf8c0a
+ ; disGetNextSymbol 0xf8c0d LB 0x12bb -> off=0x0 cb=000000000000018a uValue=00000000000f760d 'ahci_cmd_packet'
+ahci_cmd_packet: ; 0xf8c0d LB 0x18a
+ push bp ; 55 ; 0xf8c0d ahci.c:576
+ mov bp, sp ; 89 e5 ; 0xf8c0e
+ push si ; 56 ; 0xf8c10
+ push di ; 57 ; 0xf8c11
+ sub sp, strict byte 0000eh ; 83 ec 0e ; 0xf8c12
+ push ax ; 50 ; 0xf8c15
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf8c16
+ mov word [bp-010h], bx ; 89 5e f0 ; 0xf8c19
+ mov word [bp-012h], cx ; 89 4e ee ; 0xf8c1c
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf8c1f ahci.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf8c22
+ mov es, ax ; 8e c0 ; 0xf8c25
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf8c27
+ mov si, 00122h ; be 22 01 ; 0xf8c2a ahci.c:49
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf8c2d
+ cmp byte [bp+00ah], 002h ; 80 7e 0a 02 ; 0xf8c30 ahci.c:583
+ jne short 08c55h ; 75 1f ; 0xf8c34
+ mov bx, 00da0h ; bb a0 0d ; 0xf8c36 ahci.c:584
+ mov cx, ds ; 8c d9 ; 0xf8c39
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf8c3b
+ call 018bch ; e8 7b 8c ; 0xf8c3e
+ push 00ca6h ; 68 a6 0c ; 0xf8c41
+ push 00cb6h ; 68 b6 0c ; 0xf8c44
+ push strict byte 00004h ; 6a 04 ; 0xf8c47
+ call 018ffh ; e8 b3 8c ; 0xf8c49
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf8c4c
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf8c4f ahci.c:585
+ jmp near 08d8eh ; e9 39 01 ; 0xf8c52
+ test byte [bp+004h], 001h ; f6 46 04 01 ; 0xf8c55 ahci.c:589
+ jne short 08c4fh ; 75 f4 ; 0xf8c59
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf8c5b ahci.c:603
+ mov di, word [bp+008h] ; 8b 7e 08 ; 0xf8c5e
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf8c61
+ sal bx, 1 ; d1 e3 ; 0xf8c64
+ rcl di, 1 ; d1 d7 ; 0xf8c66
+ loop 08c64h ; e2 fa ; 0xf8c68
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf8c6a
+ mov word [es:si], bx ; 26 89 1c ; 0xf8c6d
+ mov word [es:si+002h], di ; 26 89 7c 02 ; 0xf8c70
+ mov word [es:si+004h], strict word 00000h ; 26 c7 44 04 00 00 ; 0xf8c74
+ mov word [es:si+006h], strict word 00000h ; 26 c7 44 06 00 00 ; 0xf8c7a
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf8c80 ahci.c:604
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf8c83
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf8c87
+ mov word [es:si+00ah], ax ; 26 89 44 0a ; 0xf8c8a
+ mov bx, word [es:si+010h] ; 26 8b 5c 10 ; 0xf8c8e ahci.c:605
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf8c92
+ mov dx, word [bp+008h] ; 8b 56 08 ; 0xf8c95
+ xor cx, cx ; 31 c9 ; 0xf8c98
+ call 09b60h ; e8 c3 0e ; 0xf8c9a
+ mov word [es:si+00eh], ax ; 26 89 44 0e ; 0xf8c9d
+ xor di, di ; 31 ff ; 0xf8ca1 ahci.c:608
+ mov ax, word [es:si+00232h] ; 26 8b 84 32 02 ; 0xf8ca3
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf8ca8
+ mov word [bp-00eh], di ; 89 7e f2 ; 0xf8cab
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf8cae
+ sub word [bp-014h], strict byte 0000ch ; 83 6e ec 0c ; 0xf8cb1 ahci.c:595
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8cb5 ahci.c:239
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8cb9
+ mov word [es:di+00268h], ax ; 26 89 85 68 02 ; 0xf8cbc
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf8cc1 ahci.c:611
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf8cc4
+ add bx, si ; 01 f3 ; 0xf8cc7
+ mov bl, byte [es:bx+0022dh] ; 26 8a 9f 2d 02 ; 0xf8cc9
+ xor bh, bh ; 30 ff ; 0xf8cce
+ mov dx, word [es:si+00232h] ; 26 8b 94 32 02 ; 0xf8cd0
+ xor ax, ax ; 31 c0 ; 0xf8cd5
+ call 08892h ; e8 b8 fb ; 0xf8cd7
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf8cda ahci.c:614
+ xor ah, ah ; 30 e4 ; 0xf8cdd
+ push ax ; 50 ; 0xf8cdf
+ mov bx, word [bp-010h] ; 8b 5e f0 ; 0xf8ce0
+ mov cx, word [bp-012h] ; 8b 4e ee ; 0xf8ce3
+ mov ax, 000c0h ; b8 c0 00 ; 0xf8ce6
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8ce9
+ call 09bc0h ; e8 d1 0e ; 0xf8cec
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf8cef ahci.c:618
+ mov word [es:si+018h], di ; 26 89 7c 18 ; 0xf8cf2
+ mov word [es:si+01ah], di ; 26 89 7c 1a ; 0xf8cf6 ahci.c:619
+ mov word [es:si+01ch], di ; 26 89 7c 1c ; 0xf8cfa
+ mov ax, word [es:si+01eh] ; 26 8b 44 1e ; 0xf8cfe ahci.c:622
+ test ax, ax ; 85 c0 ; 0xf8d02
+ je short 08d2dh ; 74 27 ; 0xf8d04
+ dec ax ; 48 ; 0xf8d06 ahci.c:623
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8d07
+ mov word [es:di+0010ch], ax ; 26 89 85 0c 01 ; 0xf8d0a
+ mov word [es:di+0010eh], di ; 26 89 bd 0e 01 ; 0xf8d0f
+ mov dx, word [es:di+00264h] ; 26 8b 95 64 02 ; 0xf8d14 ahci.c:624
+ mov ax, word [es:di+00266h] ; 26 8b 85 66 02 ; 0xf8d19
+ mov word [es:di+00100h], dx ; 26 89 95 00 01 ; 0xf8d1e
+ mov word [es:di+00102h], ax ; 26 89 85 02 01 ; 0xf8d23
+ inc byte [es:di+00263h] ; 26 fe 85 63 02 ; 0xf8d28 ahci.c:625
+ mov bx, 000a0h ; bb a0 00 ; 0xf8d2d ahci.c:628
+ mov ax, si ; 89 f0 ; 0xf8d30
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf8d32
+ call 084abh ; e8 73 f7 ; 0xf8d35
+ les bx, [bp-00eh] ; c4 5e f2 ; 0xf8d38 ahci.c:630
+ mov dx, word [es:bx+004h] ; 26 8b 57 04 ; 0xf8d3b
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf8d3f
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf8d43
+ mov word [es:si+01ah], dx ; 26 89 54 1a ; 0xf8d46
+ mov word [es:si+01ch], ax ; 26 89 44 1c ; 0xf8d4a
+ mov bx, word [es:si+01ah] ; 26 8b 5c 1a ; 0xf8d4e ahci.c:632
+ mov cx, ax ; 89 c1 ; 0xf8d52
+ shr cx, 1 ; d1 e9 ; 0xf8d54
+ rcr bx, 1 ; d1 db ; 0xf8d56
+ mov di, word [es:si+008h] ; 26 8b 7c 08 ; 0xf8d58
+ mov ax, word [es:si+00ah] ; 26 8b 44 0a ; 0xf8d5c
+ mov cx, bx ; 89 d9 ; 0xf8d60
+ mov si, di ; 89 fe ; 0xf8d62
+ mov dx, ax ; 89 c2 ; 0xf8d64
+ mov es, ax ; 8e c0 ; 0xf8d66
+ push DS ; 1e ; 0xf8d68
+ mov ds, dx ; 8e da ; 0xf8d69
+ rep movsw ; f3 a5 ; 0xf8d6b
+ pop DS ; 1f ; 0xf8d6d
+ les bx, [bp-00eh] ; c4 5e f2 ; 0xf8d6e ahci.c:244
+ mov ax, word [es:bx+00268h] ; 26 8b 87 68 02 ; 0xf8d71
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8d76
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf8d7a ahci.c:636
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf8d7d
+ or ax, word [es:bx+004h] ; 26 0b 47 04 ; 0xf8d81
+ jne short 08d8ch ; 75 05 ; 0xf8d85
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf8d87
+ jmp short 08d8eh ; eb 02 ; 0xf8d8a
+ xor ax, ax ; 31 c0 ; 0xf8d8c
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf8d8e ahci.c:637
+ pop di ; 5f ; 0xf8d91
+ pop si ; 5e ; 0xf8d92
+ pop bp ; 5d ; 0xf8d93
+ retn 0000ch ; c2 0c 00 ; 0xf8d94
+ ; disGetNextSymbol 0xf8d97 LB 0x1131 -> off=0x0 cb=0000000000000005 uValue=00000000000f7797 'wait_ticks_device_init'
+wait_ticks_device_init: ; 0xf8d97 LB 0x5
+ push bp ; 55 ; 0xf8d97 ahci.c:640
+ mov bp, sp ; 89 e5 ; 0xf8d98
+ pop bp ; 5d ; 0xf8d9a ahci.c:642
+ retn ; c3 ; 0xf8d9b
+ ; disGetNextSymbol 0xf8d9c LB 0x112c -> off=0x0 cb=00000000000004e3 uValue=00000000000f779c 'ahci_port_detect_device'
+ahci_port_detect_device: ; 0xf8d9c LB 0x4e3
+ push bp ; 55 ; 0xf8d9c ahci.c:644
+ mov bp, sp ; 89 e5 ; 0xf8d9d
+ push cx ; 51 ; 0xf8d9f
+ push si ; 56 ; 0xf8da0
+ push di ; 57 ; 0xf8da1
+ sub sp, 0022ch ; 81 ec 2c 02 ; 0xf8da2
+ mov si, ax ; 89 c6 ; 0xf8da6
+ mov word [bp-010h], dx ; 89 56 f0 ; 0xf8da8
+ mov byte [bp-00ah], bl ; 88 5e f6 ; 0xf8dab
+ mov word [bp-020h], strict word 00000h ; c7 46 e0 00 00 ; 0xf8dae ahci.c:650
+ mov cl, bl ; 88 d9 ; 0xf8db3 ahci.c:652
+ xor ch, ch ; 30 ed ; 0xf8db5
+ mov bx, cx ; 89 cb ; 0xf8db7
+ call 08892h ; e8 d6 fa ; 0xf8db9
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf8dbc ahci.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf8dbf
+ mov es, ax ; 8e c0 ; 0xf8dc2
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf8dc4
+ mov word [bp-028h], 00122h ; c7 46 d8 22 01 ; 0xf8dc7 ahci.c:49
+ mov word [bp-026h], ax ; 89 46 da ; 0xf8dcc
+ mov ax, cx ; 89 c8 ; 0xf8dcf ahci.c:657
+ sal ax, 007h ; c1 e0 07 ; 0xf8dd1
+ add ax, 0012ch ; 05 2c 01 ; 0xf8dd4
+ cwd ; 99 ; 0xf8dd7
+ mov bx, ax ; 89 c3 ; 0xf8dd8
+ mov di, dx ; 89 d7 ; 0xf8dda
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf8ddc
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8ddf
+ mov cx, di ; 89 f9 ; 0xf8de4
+ xchg cx, ax ; 91 ; 0xf8de6
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8de7
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8deb
+ out DX, eax ; 66 ef ; 0xf8ded
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf8def
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8df2
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8df7
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf8dfa
+ xor cx, cx ; 31 c9 ; 0xf8dfd
+ xchg cx, ax ; 91 ; 0xf8dff
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8e00
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8e04
+ out DX, eax ; 66 ef ; 0xf8e06
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf8e08 ahci.c:662
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8e0b
+ mov ax, bx ; 89 d8 ; 0xf8e10
+ mov cx, di ; 89 f9 ; 0xf8e12
+ xchg cx, ax ; 91 ; 0xf8e14
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8e15
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8e19
+ out DX, eax ; 66 ef ; 0xf8e1b
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf8e1d
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8e20
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8e25
+ xor ax, ax ; 31 c0 ; 0xf8e28
+ xor cx, cx ; 31 c9 ; 0xf8e2a
+ xchg cx, ax ; 91 ; 0xf8e2c
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8e2d
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8e31
+ out DX, eax ; 66 ef ; 0xf8e33
+ mov di, strict word 0006ch ; bf 6c 00 ; 0xf8e35 ahci.c:671
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf8e38
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf8e3b
+ mov es, ax ; 8e c0 ; 0xf8e3e ahci.c:672
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf8e40
+ add ax, strict word 00003h ; 05 03 00 ; 0xf8e43
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf8e46
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf8e49
+ adc ax, strict word 00000h ; 15 00 00 ; 0xf8e4d
+ mov word [bp-02ah], ax ; 89 46 d6 ; 0xf8e50
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf8e53 ahci.c:674
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf8e56
+ cmp ax, word [bp-02ah] ; 3b 46 d6 ; 0xf8e5a
+ jc short 08e70h ; 72 11 ; 0xf8e5d
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf8e5f
+ cmp ax, word [bp-02ah] ; 3b 46 d6 ; 0xf8e63
+ jne short 08ebch ; 75 54 ; 0xf8e66
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf8e68
+ cmp ax, word [bp-024h] ; 3b 46 dc ; 0xf8e6b
+ jnc short 08ebch ; 73 4c ; 0xf8e6e
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf8e70 ahci.c:677
+ xor ah, ah ; 30 e4 ; 0xf8e73
+ sal ax, 007h ; c1 e0 07 ; 0xf8e75
+ add ax, 00128h ; 05 28 01 ; 0xf8e78
+ cwd ; 99 ; 0xf8e7b
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf8e7c
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8e7f
+ mov cx, dx ; 89 d1 ; 0xf8e84
+ mov dx, bx ; 89 da ; 0xf8e86
+ xchg cx, ax ; 91 ; 0xf8e88
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8e89
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8e8d
+ out DX, eax ; 66 ef ; 0xf8e8f
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf8e91
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8e94
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8e99
+ in eax, DX ; 66 ed ; 0xf8e9c
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8e9e
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8ea0
+ xchg dx, ax ; 92 ; 0xf8ea4
+ mov word [bp-022h], ax ; 89 46 de ; 0xf8ea5
+ mov word [bp-01eh], dx ; 89 56 e2 ; 0xf8ea8
+ push strict byte 00000h ; 6a 00 ; 0xf8eab ahci.c:678
+ mov bx, strict word 0000fh ; bb 0f 00 ; 0xf8ead
+ xor cx, cx ; 31 c9 ; 0xf8eb0
+ call 0831bh ; e8 66 f4 ; 0xf8eb2
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf8eb5
+ jne short 08e53h ; 75 99 ; 0xf8eb8
+ jmp short 08ec5h ; eb 09 ; 0xf8eba ahci.c:680
+ cmp word [bp-020h], strict byte 00000h ; 83 7e e0 00 ; 0xf8ebc ahci.c:685
+ jne short 08ec5h ; 75 03 ; 0xf8ec0
+ jmp near 09277h ; e9 b2 03 ; 0xf8ec2
+ push strict byte 00000h ; 6a 00 ; 0xf8ec5 ahci.c:690
+ mov bx, strict word 0000fh ; bb 0f 00 ; 0xf8ec7
+ xor cx, cx ; 31 c9 ; 0xf8eca
+ mov ax, word [bp-022h] ; 8b 46 de ; 0xf8ecc
+ mov dx, word [bp-01eh] ; 8b 56 e2 ; 0xf8ecf
+ call 0831bh ; e8 46 f4 ; 0xf8ed2
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf8ed5
+ jne short 08ec2h ; 75 e8 ; 0xf8ed8
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf8eda ahci.c:698
+ xor ah, ah ; 30 e4 ; 0xf8edd
+ mov di, ax ; 89 c7 ; 0xf8edf
+ sal di, 007h ; c1 e7 07 ; 0xf8ee1
+ lea ax, [di+00130h] ; 8d 85 30 01 ; 0xf8ee4
+ cwd ; 99 ; 0xf8ee8
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf8ee9
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8eec
+ mov cx, dx ; 89 d1 ; 0xf8ef1
+ mov dx, bx ; 89 da ; 0xf8ef3
+ xchg cx, ax ; 91 ; 0xf8ef5
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8ef6
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8efa
+ out DX, eax ; 66 ef ; 0xf8efc
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf8efe
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8f01
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8f06
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf8f09
+ mov cx, ax ; 89 c1 ; 0xf8f0c
+ xchg cx, ax ; 91 ; 0xf8f0e
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8f0f
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8f13
+ out DX, eax ; 66 ef ; 0xf8f15
+ les bx, [bp-028h] ; c4 5e d8 ; 0xf8f17 ahci.c:700
+ mov al, byte [es:bx+00231h] ; 26 8a 87 31 02 ; 0xf8f1a
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf8f1f
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf8f22 ahci.c:705
+ jnc short 08ec2h ; 73 9c ; 0xf8f24
+ lea ax, [di+00118h] ; 8d 85 18 01 ; 0xf8f26 ahci.c:708
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf8f2a ahci.c:250
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8f2d
+ xor cx, cx ; 31 c9 ; 0xf8f32 ahci.c:252
+ mov dx, bx ; 89 da ; 0xf8f34
+ xchg cx, ax ; 91 ; 0xf8f36
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8f37
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8f3b
+ out DX, eax ; 66 ef ; 0xf8f3d
+ add bx, strict byte 00004h ; 83 c3 04 ; 0xf8f3f ahci.c:253
+ mov dx, bx ; 89 da ; 0xf8f42
+ in eax, DX ; 66 ed ; 0xf8f44
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8f46
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8f48
+ xchg dx, ax ; 92 ; 0xf8f4c
+ or AL, strict byte 010h ; 0c 10 ; 0xf8f4d
+ mov cx, dx ; 89 d1 ; 0xf8f4f
+ mov dx, bx ; 89 da ; 0xf8f51
+ xchg cx, ax ; 91 ; 0xf8f53
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8f54
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8f58
+ out DX, eax ; 66 ef ; 0xf8f5a
+ lea ax, [di+00124h] ; 8d 85 24 01 ; 0xf8f5c ahci.c:712
+ cwd ; 99 ; 0xf8f60
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf8f61
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8f64
+ mov cx, dx ; 89 d1 ; 0xf8f69
+ mov dx, bx ; 89 da ; 0xf8f6b
+ xchg cx, ax ; 91 ; 0xf8f6d
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8f6e
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8f72
+ out DX, eax ; 66 ef ; 0xf8f74
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf8f76
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8f79
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8f7e
+ in eax, DX ; 66 ed ; 0xf8f81
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8f83
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8f85
+ xchg dx, ax ; 92 ; 0xf8f89
+ mov bl, byte [bp-00eh] ; 8a 5e f2 ; 0xf8f8a
+ add bl, 00ch ; 80 c3 0c ; 0xf8f8d
+ mov byte [bp-008h], bl ; 88 5e f8 ; 0xf8f90
+ test dx, dx ; 85 d2 ; 0xf8f93 ahci.c:713
+ jne short 08febh ; 75 54 ; 0xf8f95
+ cmp ax, 00101h ; 3d 01 01 ; 0xf8f97
+ jne short 08febh ; 75 4f ; 0xf8f9a
+ les bx, [bp-028h] ; c4 5e d8 ; 0xf8f9c ahci.c:723
+ mov word [es:bx+006h], strict word 00000h ; 26 c7 47 06 00 00 ; 0xf8f9f
+ mov word [es:bx+004h], strict word 00000h ; 26 c7 47 04 00 00 ; 0xf8fa5
+ mov word [es:bx+002h], strict word 00000h ; 26 c7 47 02 00 00 ; 0xf8fab
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf8fb1
+ lea dx, [bp-00232h] ; 8d 96 ce fd ; 0xf8fb6 ahci.c:724
+ mov word [es:bx+008h], dx ; 26 89 57 08 ; 0xf8fba
+ mov [es:bx+00ah], ss ; 26 8c 57 0a ; 0xf8fbe
+ mov word [es:bx+00eh], strict word 00001h ; 26 c7 47 0e 01 00 ; 0xf8fc2 ahci.c:725
+ mov word [es:bx+010h], 00200h ; 26 c7 47 10 00 02 ; 0xf8fc8 ahci.c:726
+ mov bx, 000ech ; bb ec 00 ; 0xf8fce ahci.c:727
+ mov ax, word [bp-028h] ; 8b 46 d8 ; 0xf8fd1
+ mov dx, es ; 8c c2 ; 0xf8fd4
+ call 084abh ; e8 d2 f4 ; 0xf8fd6
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8fd9 ahci.c:730
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf8fdc
+ test byte [bp-00232h], 080h ; f6 86 ce fd 80 ; 0xf8fdf ahci.c:732
+ je short 08feeh ; 74 08 ; 0xf8fe4
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf8fe6
+ jmp short 08ff0h ; eb 05 ; 0xf8fe9
+ jmp near 091b2h ; e9 c4 01 ; 0xf8feb
+ xor ax, ax ; 31 c0 ; 0xf8fee
+ mov dl, al ; 88 c2 ; 0xf8ff0
+ mov ax, word [bp-00230h] ; 8b 86 d0 fd ; 0xf8ff2 ahci.c:733
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf8ff6
+ mov ax, word [bp-0022ch] ; 8b 86 d4 fd ; 0xf8ff9 ahci.c:734
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf8ffd
+ mov ax, word [bp-00226h] ; 8b 86 da fd ; 0xf9000 ahci.c:735
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf9004
+ mov di, word [bp-001bah] ; 8b be 46 fe ; 0xf9007 ahci.c:736
+ mov si, word [bp-001b8h] ; 8b b6 48 fe ; 0xf900b
+ xor ax, ax ; 31 c0 ; 0xf900f
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf9011
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf9014
+ cmp si, 00fffh ; 81 fe ff 0f ; 0xf9017 ahci.c:738
+ jne short 09038h ; 75 1b ; 0xf901b
+ cmp di, strict byte 0ffffh ; 83 ff ff ; 0xf901d
+ jne short 09038h ; 75 16 ; 0xf9020
+ mov ax, word [bp-00164h] ; 8b 86 9c fe ; 0xf9022 ahci.c:739
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf9026
+ mov ax, word [bp-00166h] ; 8b 86 9a fe ; 0xf9029
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf902d
+ mov si, word [bp-00168h] ; 8b b6 98 fe ; 0xf9030
+ mov di, word [bp-0016ah] ; 8b be 96 fe ; 0xf9034
+ mov bl, byte [bp-00eh] ; 8a 5e f2 ; 0xf9038 ahci.c:743
+ xor bh, bh ; 30 ff ; 0xf903b
+ mov es, [bp-026h] ; 8e 46 da ; 0xf903d
+ add bx, word [bp-028h] ; 03 5e d8 ; 0xf9040
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf9043
+ mov byte [es:bx+0022dh], al ; 26 88 87 2d 02 ; 0xf9046
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf904b ahci.c:744
+ xor ah, ah ; 30 e4 ; 0xf904e
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf9050
+ mov bx, word [bp-028h] ; 8b 5e d8 ; 0xf9053
+ add bx, ax ; 01 c3 ; 0xf9056
+ mov word [es:bx+022h], 0ff05h ; 26 c7 47 22 05 ff ; 0xf9058
+ mov byte [es:bx+024h], dl ; 26 88 57 24 ; 0xf905e ahci.c:746
+ mov byte [es:bx+025h], 000h ; 26 c6 47 25 00 ; 0xf9062 ahci.c:747
+ mov word [es:bx+028h], 00200h ; 26 c7 47 28 00 02 ; 0xf9067 ahci.c:748
+ mov byte [es:bx+027h], 001h ; 26 c6 47 27 01 ; 0xf906d ahci.c:749
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf9072 ahci.c:750
+ mov word [es:bx+03ch], ax ; 26 89 47 3c ; 0xf9075
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf9079
+ mov word [es:bx+03ah], ax ; 26 89 47 3a ; 0xf907c
+ mov word [es:bx+038h], si ; 26 89 77 38 ; 0xf9080
+ mov word [es:bx+036h], di ; 26 89 7f 36 ; 0xf9084
+ mov ax, word [bp-018h] ; 8b 46 e8 ; 0xf9088 ahci.c:752
+ mov word [es:bx+030h], ax ; 26 89 47 30 ; 0xf908b
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf908f ahci.c:753
+ mov word [es:bx+032h], ax ; 26 89 47 32 ; 0xf9092
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf9096 ahci.c:754
+ mov word [es:bx+034h], ax ; 26 89 47 34 ; 0xf9099
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf909d ahci.c:757
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf90a0
+ jc short 090b0h ; 72 0c ; 0xf90a2
+ jbe short 090b8h ; 76 12 ; 0xf90a4
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf90a6
+ je short 090c0h ; 74 16 ; 0xf90a8
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf90aa
+ je short 090bch ; 74 0e ; 0xf90ac
+ jmp short 0910ch ; eb 5c ; 0xf90ae
+ test al, al ; 84 c0 ; 0xf90b0
+ jne short 0910ch ; 75 58 ; 0xf90b2
+ mov BL, strict byte 040h ; b3 40 ; 0xf90b4 ahci.c:760
+ jmp short 090c2h ; eb 0a ; 0xf90b6 ahci.c:761
+ mov BL, strict byte 048h ; b3 48 ; 0xf90b8 ahci.c:763
+ jmp short 090c2h ; eb 06 ; 0xf90ba ahci.c:764
+ mov BL, strict byte 050h ; b3 50 ; 0xf90bc ahci.c:766
+ jmp short 090c2h ; eb 02 ; 0xf90be ahci.c:767
+ mov BL, strict byte 058h ; b3 58 ; 0xf90c0 ahci.c:769
+ mov dl, bl ; 88 da ; 0xf90c2 ahci.c:773
+ add dl, 007h ; 80 c2 07 ; 0xf90c4
+ xor dh, dh ; 30 f6 ; 0xf90c7
+ mov ax, dx ; 89 d0 ; 0xf90c9
+ call 01650h ; e8 82 85 ; 0xf90cb
+ test al, al ; 84 c0 ; 0xf90ce
+ je short 0910ch ; 74 3a ; 0xf90d0
+ mov al, bl ; 88 d8 ; 0xf90d2 ahci.c:776
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf90d4
+ xor ah, ah ; 30 e4 ; 0xf90d6
+ call 01650h ; e8 75 85 ; 0xf90d8
+ xor ah, ah ; 30 e4 ; 0xf90db
+ sal ax, 008h ; c1 e0 08 ; 0xf90dd
+ mov word [bp-02ch], ax ; 89 46 d4 ; 0xf90e0
+ mov al, bl ; 88 d8 ; 0xf90e3
+ xor ah, ah ; 30 e4 ; 0xf90e5
+ call 01650h ; e8 66 85 ; 0xf90e7
+ xor ah, ah ; 30 e4 ; 0xf90ea
+ mov cx, word [bp-02ch] ; 8b 4e d4 ; 0xf90ec
+ add cx, ax ; 01 c1 ; 0xf90ef
+ mov word [bp-030h], cx ; 89 4e d0 ; 0xf90f1
+ mov al, bl ; 88 d8 ; 0xf90f4 ahci.c:777
+ add AL, strict byte 002h ; 04 02 ; 0xf90f6
+ call 01650h ; e8 55 85 ; 0xf90f8
+ xor ah, ah ; 30 e4 ; 0xf90fb
+ mov word [bp-032h], ax ; 89 46 ce ; 0xf90fd
+ mov ax, dx ; 89 d0 ; 0xf9100 ahci.c:778
+ call 01650h ; e8 4b 85 ; 0xf9102
+ xor ah, ah ; 30 e4 ; 0xf9105
+ mov word [bp-02eh], ax ; 89 46 d2 ; 0xf9107
+ jmp short 0911ch ; eb 10 ; 0xf910a ahci.c:780
+ push word [bp-014h] ; ff 76 ec ; 0xf910c ahci.c:781
+ push word [bp-016h] ; ff 76 ea ; 0xf910f
+ push si ; 56 ; 0xf9112
+ push di ; 57 ; 0xf9113
+ mov dx, ss ; 8c d2 ; 0xf9114
+ lea ax, [bp-032h] ; 8d 46 ce ; 0xf9116
+ call 058b0h ; e8 94 c7 ; 0xf9119
+ mov bx, 00da0h ; bb a0 0d ; 0xf911c ahci.c:785
+ mov cx, ds ; 8c d9 ; 0xf911f
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf9121
+ call 018bch ; e8 95 87 ; 0xf9124
+ push word [bp-014h] ; ff 76 ec ; 0xf9127
+ push word [bp-016h] ; ff 76 ea ; 0xf912a
+ push si ; 56 ; 0xf912d
+ push di ; 57 ; 0xf912e
+ mov ax, word [bp-02eh] ; 8b 46 d2 ; 0xf912f
+ push ax ; 50 ; 0xf9132
+ mov ax, word [bp-032h] ; 8b 46 ce ; 0xf9133
+ push ax ; 50 ; 0xf9136
+ mov ax, word [bp-030h] ; 8b 46 d0 ; 0xf9137
+ push ax ; 50 ; 0xf913a
+ push word [bp-01ch] ; ff 76 e4 ; 0xf913b
+ push word [bp-018h] ; ff 76 e8 ; 0xf913e
+ push word [bp-01ah] ; ff 76 e6 ; 0xf9141
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf9144
+ xor ah, ah ; 30 e4 ; 0xf9147
+ push ax ; 50 ; 0xf9149
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf914a
+ push ax ; 50 ; 0xf914d
+ push 00cd6h ; 68 d6 0c ; 0xf914e
+ push strict byte 00004h ; 6a 04 ; 0xf9151
+ call 018ffh ; e8 a9 87 ; 0xf9153
+ add sp, strict byte 0001ch ; 83 c4 1c ; 0xf9156
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf9159 ahci.c:787
+ xor ah, ah ; 30 e4 ; 0xf915c
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf915e
+ mov di, word [bp-028h] ; 8b 7e d8 ; 0xf9161
+ add di, ax ; 01 c7 ; 0xf9164
+ mov es, [bp-026h] ; 8e 46 da ; 0xf9166
+ lea di, [di+02ah] ; 8d 7d 2a ; 0xf9169
+ push DS ; 1e ; 0xf916c
+ push SS ; 16 ; 0xf916d
+ pop DS ; 1f ; 0xf916e
+ lea si, [bp-032h] ; 8d 76 ce ; 0xf916f
+ movsw ; a5 ; 0xf9172
+ movsw ; a5 ; 0xf9173
+ movsw ; a5 ; 0xf9174
+ pop DS ; 1f ; 0xf9175
+ mov bx, word [bp-028h] ; 8b 5e d8 ; 0xf9176 ahci.c:790
+ mov bl, byte [es:bx+001e2h] ; 26 8a 9f e2 01 ; 0xf9179
+ mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xf917e ahci.c:791
+ add dl, 00ch ; 80 c2 0c ; 0xf9181
+ mov al, bl ; 88 d8 ; 0xf9184
+ xor ah, ah ; 30 e4 ; 0xf9186
+ mov si, word [bp-028h] ; 8b 76 d8 ; 0xf9188
+ add si, ax ; 01 c6 ; 0xf918b
+ mov byte [es:si+001e3h], dl ; 26 88 94 e3 01 ; 0xf918d
+ db 0feh, 0c3h
+ ; inc bl ; fe c3 ; 0xf9192 ahci.c:792
+ mov si, word [bp-028h] ; 8b 76 d8 ; 0xf9194 ahci.c:793
+ mov byte [es:si+001e2h], bl ; 26 88 9c e2 01 ; 0xf9197
+ mov bx, strict word 00075h ; bb 75 00 ; 0xf919c ahci.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf919f
+ mov es, ax ; 8e c0 ; 0xf91a2
+ mov bl, byte [es:bx] ; 26 8a 1f ; 0xf91a4
+ db 0feh, 0c3h
+ ; inc bl ; fe c3 ; 0xf91a7 ahci.c:797
+ mov si, strict word 00075h ; be 75 00 ; 0xf91a9 ahci.c:43
+ mov byte [es:si], bl ; 26 88 1c ; 0xf91ac
+ jmp near 09269h ; e9 b7 00 ; 0xf91af ahci.c:800
+ cmp dx, 0eb14h ; 81 fa 14 eb ; 0xf91b2
+ jne short 0920ch ; 75 54 ; 0xf91b6
+ cmp ax, 00101h ; 3d 01 01 ; 0xf91b8
+ jne short 0920ch ; 75 4f ; 0xf91bb
+ les bx, [bp-028h] ; c4 5e d8 ; 0xf91bd ahci.c:805
+ mov word [es:bx+006h], strict word 00000h ; 26 c7 47 06 00 00 ; 0xf91c0
+ mov word [es:bx+004h], strict word 00000h ; 26 c7 47 04 00 00 ; 0xf91c6
+ mov word [es:bx+002h], strict word 00000h ; 26 c7 47 02 00 00 ; 0xf91cc
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf91d2
+ lea dx, [bp-00232h] ; 8d 96 ce fd ; 0xf91d7 ahci.c:806
+ mov word [es:bx+008h], dx ; 26 89 57 08 ; 0xf91db
+ mov [es:bx+00ah], ss ; 26 8c 57 0a ; 0xf91df
+ mov word [es:bx+00eh], strict word 00001h ; 26 c7 47 0e 01 00 ; 0xf91e3 ahci.c:807
+ mov word [es:bx+010h], 00200h ; 26 c7 47 10 00 02 ; 0xf91e9 ahci.c:808
+ mov bx, 000a1h ; bb a1 00 ; 0xf91ef ahci.c:809
+ mov ax, word [bp-028h] ; 8b 46 d8 ; 0xf91f2
+ mov dx, es ; 8c c2 ; 0xf91f5
+ call 084abh ; e8 b1 f2 ; 0xf91f7
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf91fa ahci.c:812
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf91fd
+ test byte [bp-00232h], 080h ; f6 86 ce fd 80 ; 0xf9200 ahci.c:814
+ je short 0920eh ; 74 07 ; 0xf9205
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf9207
+ jmp short 09210h ; eb 04 ; 0xf920a
+ jmp short 09269h ; eb 5b ; 0xf920c
+ xor dx, dx ; 31 d2 ; 0xf920e
+ mov bl, byte [bp-00eh] ; 8a 5e f2 ; 0xf9210 ahci.c:816
+ xor bh, bh ; 30 ff ; 0xf9213
+ mov es, [bp-026h] ; 8e 46 da ; 0xf9215
+ add bx, word [bp-028h] ; 03 5e d8 ; 0xf9218
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf921b
+ mov byte [es:bx+0022dh], al ; 26 88 87 2d 02 ; 0xf921e
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf9223 ahci.c:817
+ xor ah, ah ; 30 e4 ; 0xf9226
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf9228
+ mov bx, word [bp-028h] ; 8b 5e d8 ; 0xf922b
+ add bx, ax ; 01 c3 ; 0xf922e
+ mov word [es:bx+022h], 00505h ; 26 c7 47 22 05 05 ; 0xf9230
+ mov byte [es:bx+024h], dl ; 26 88 57 24 ; 0xf9236 ahci.c:819
+ mov word [es:bx+028h], 00800h ; 26 c7 47 28 00 08 ; 0xf923a ahci.c:820
+ mov byte [es:bx+027h], 000h ; 26 c6 47 27 00 ; 0xf9240 ahci.c:821
+ mov bx, word [bp-028h] ; 8b 5e d8 ; 0xf9245 ahci.c:824
+ mov al, byte [es:bx+001f3h] ; 26 8a 87 f3 01 ; 0xf9248
+ mov ah, byte [bp-00eh] ; 8a 66 f2 ; 0xf924d ahci.c:825
+ add ah, 00ch ; 80 c4 0c ; 0xf9250
+ mov bl, al ; 88 c3 ; 0xf9253
+ xor bh, bh ; 30 ff ; 0xf9255
+ add bx, word [bp-028h] ; 03 5e d8 ; 0xf9257
+ mov byte [es:bx+001f4h], ah ; 26 88 a7 f4 01 ; 0xf925a
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf925f ahci.c:826
+ mov bx, word [bp-028h] ; 8b 5e d8 ; 0xf9261 ahci.c:827
+ mov byte [es:bx+001f3h], al ; 26 88 87 f3 01 ; 0xf9264
+ inc byte [bp-00eh] ; fe 46 f2 ; 0xf9269 ahci.c:832
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf926c ahci.c:833
+ les bx, [bp-028h] ; c4 5e d8 ; 0xf926f
+ mov byte [es:bx+00231h], al ; 26 88 87 31 02 ; 0xf9272
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf9277 ahci.c:838
+ pop di ; 5f ; 0xf927a
+ pop si ; 5e ; 0xf927b
+ pop cx ; 59 ; 0xf927c
+ pop bp ; 5d ; 0xf927d
+ retn ; c3 ; 0xf927e
+ ; disGetNextSymbol 0xf927f LB 0xc49 -> off=0x0 cb=000000000000003a uValue=00000000000f7c7f 'ahci_mem_alloc'
+ahci_mem_alloc: ; 0xf927f LB 0x3a
+ push bx ; 53 ; 0xf927f ahci.c:843
+ push cx ; 51 ; 0xf9280
+ push dx ; 52 ; 0xf9281
+ push di ; 57 ; 0xf9282
+ push bp ; 55 ; 0xf9283
+ mov bp, sp ; 89 e5 ; 0xf9284
+ mov di, 00413h ; bf 13 04 ; 0xf9286 ahci.c:48
+ xor ax, ax ; 31 c0 ; 0xf9289
+ mov es, ax ; 8e c0 ; 0xf928b
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf928d
+ test ax, ax ; 85 c0 ; 0xf9290 ahci.c:852
+ je short 092b3h ; 74 1f ; 0xf9292
+ dec ax ; 48 ; 0xf9294 ahci.c:853
+ mov bx, ax ; 89 c3 ; 0xf9295
+ xor dx, dx ; 31 d2 ; 0xf9297 ahci.c:856
+ mov cx, strict word 0000ah ; b9 0a 00 ; 0xf9299
+ sal ax, 1 ; d1 e0 ; 0xf929c
+ rcl dx, 1 ; d1 d2 ; 0xf929e
+ loop 0929ch ; e2 fa ; 0xf92a0
+ mov di, dx ; 89 d7 ; 0xf92a2
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf92a4
+ shr di, 1 ; d1 ef ; 0xf92a7
+ rcr ax, 1 ; d1 d8 ; 0xf92a9
+ loop 092a7h ; e2 fa ; 0xf92ab
+ mov di, 00413h ; bf 13 04 ; 0xf92ad ahci.c:53
+ mov word [es:di], bx ; 26 89 1d ; 0xf92b0
+ pop bp ; 5d ; 0xf92b3 ahci.c:861
+ pop di ; 5f ; 0xf92b4
+ pop dx ; 5a ; 0xf92b5
+ pop cx ; 59 ; 0xf92b6
+ pop bx ; 5b ; 0xf92b7
+ retn ; c3 ; 0xf92b8
+ ; disGetNextSymbol 0xf92b9 LB 0xc0f -> off=0x0 cb=0000000000000156 uValue=00000000000f7cb9 'ahci_hba_init'
+ahci_hba_init: ; 0xf92b9 LB 0x156
+ push bp ; 55 ; 0xf92b9 ahci.c:866
+ mov bp, sp ; 89 e5 ; 0xf92ba
+ push bx ; 53 ; 0xf92bc
+ push cx ; 51 ; 0xf92bd
+ push dx ; 52 ; 0xf92be
+ push si ; 56 ; 0xf92bf
+ push di ; 57 ; 0xf92c0
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf92c1
+ mov si, ax ; 89 c6 ; 0xf92c4
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf92c6 ahci.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf92c9
+ mov es, ax ; 8e c0 ; 0xf92cc
+ mov di, word [es:bx] ; 26 8b 3f ; 0xf92ce
+ mov bx, 00122h ; bb 22 01 ; 0xf92d1 ahci.c:877
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf92d4 ahci.c:879
+ xor cx, cx ; 31 c9 ; 0xf92d7
+ mov dx, si ; 89 f2 ; 0xf92d9
+ xchg cx, ax ; 91 ; 0xf92db
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf92dc
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf92e0
+ out DX, eax ; 66 ef ; 0xf92e2
+ lea dx, [si+004h] ; 8d 54 04 ; 0xf92e4
+ in eax, DX ; 66 ed ; 0xf92e7
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf92e9
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf92eb
+ xchg dx, ax ; 92 ; 0xf92ef
+ call 0927fh ; e8 8c ff ; 0xf92f0 ahci.c:885
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf92f3
+ test ax, ax ; 85 c0 ; 0xf92f6 ahci.c:886
+ jne short 092fdh ; 75 03 ; 0xf92f8
+ jmp near 09405h ; e9 08 01 ; 0xf92fa
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf92fd ahci.c:889
+ mov es, di ; 8e c7 ; 0xf9300
+ mov word [es:bx+00232h], ax ; 26 89 87 32 02 ; 0xf9302
+ mov byte [es:bx+00231h], 000h ; 26 c6 87 31 02 00 ; 0xf9307 ahci.c:895
+ xor bx, bx ; 31 db ; 0xf930d ahci.c:897
+ mov es, ax ; 8e c0 ; 0xf930f
+ mov byte [es:bx+00262h], 0ffh ; 26 c6 87 62 02 ff ; 0xf9311 ahci.c:898
+ mov word [es:bx+00260h], si ; 26 89 b7 60 02 ; 0xf9317 ahci.c:899
+ mov word [es:bx+00264h], 0c000h ; 26 c7 87 64 02 00 c0 ; 0xf931c ahci.c:904
+ mov word [es:bx+00266h], strict word 0000ch ; 26 c7 87 66 02 0c 00 ; 0xf9323
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf932a ahci.c:252
+ xor cx, cx ; 31 c9 ; 0xf932d
+ mov dx, si ; 89 f2 ; 0xf932f
+ xchg cx, ax ; 91 ; 0xf9331
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9332
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9336
+ out DX, eax ; 66 ef ; 0xf9338
+ lea bx, [si+004h] ; 8d 5c 04 ; 0xf933a ahci.c:253
+ mov dx, bx ; 89 da ; 0xf933d
+ in eax, DX ; 66 ed ; 0xf933f
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9341
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf9343
+ xchg dx, ax ; 92 ; 0xf9347
+ mov cx, dx ; 89 d1 ; 0xf9348
+ or AL, strict byte 001h ; 0c 01 ; 0xf934a
+ mov dx, bx ; 89 da ; 0xf934c
+ xchg cx, ax ; 91 ; 0xf934e
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf934f
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9353
+ out DX, eax ; 66 ef ; 0xf9355
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf9357 ahci.c:910
+ xor cx, cx ; 31 c9 ; 0xf935a
+ mov dx, si ; 89 f2 ; 0xf935c
+ xchg cx, ax ; 91 ; 0xf935e
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf935f
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9363
+ out DX, eax ; 66 ef ; 0xf9365
+ lea bx, [si+004h] ; 8d 5c 04 ; 0xf9367
+ mov dx, bx ; 89 da ; 0xf936a
+ in eax, DX ; 66 ed ; 0xf936c
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf936e
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf9370
+ xchg dx, ax ; 92 ; 0xf9374
+ test AL, strict byte 001h ; a8 01 ; 0xf9375 ahci.c:911
+ jne short 09357h ; 75 de ; 0xf9377
+ xor ax, ax ; 31 c0 ; 0xf9379 ahci.c:913
+ xor cx, cx ; 31 c9 ; 0xf937b
+ mov dx, si ; 89 f2 ; 0xf937d
+ xchg cx, ax ; 91 ; 0xf937f
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9380
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9384
+ out DX, eax ; 66 ef ; 0xf9386
+ mov dx, bx ; 89 da ; 0xf9388
+ in eax, DX ; 66 ed ; 0xf938a
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf938c
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf938e
+ xchg dx, ax ; 92 ; 0xf9392
+ push strict byte 00000h ; 6a 00 ; 0xf9393 ahci.c:914
+ mov bx, strict word 0001fh ; bb 1f 00 ; 0xf9395
+ xor cx, cx ; 31 c9 ; 0xf9398
+ call 0831bh ; e8 7e ef ; 0xf939a
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf939d
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf939f
+ mov byte [bp-00eh], 000h ; c6 46 f2 00 ; 0xf93a2 ahci.c:919
+ jmp short 093c9h ; eb 21 ; 0xf93a6 ahci.c:920
+ xor al, al ; 30 c0 ; 0xf93a8 ahci.c:272
+ test al, al ; 84 c0 ; 0xf93aa ahci.c:273
+ je short 093c0h ; 74 12 ; 0xf93ac
+ mov bl, byte [bp-00eh] ; 8a 5e f2 ; 0xf93ae ahci.c:925
+ xor bh, bh ; 30 ff ; 0xf93b1
+ xor ax, ax ; 31 c0 ; 0xf93b3
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf93b5
+ call 08d9ch ; e8 e1 f9 ; 0xf93b8
+ dec byte [bp-00ch] ; fe 4e f4 ; 0xf93bb ahci.c:926
+ je short 09403h ; 74 43 ; 0xf93be ahci.c:927
+ inc byte [bp-00eh] ; fe 46 f2 ; 0xf93c0 ahci.c:930
+ cmp byte [bp-00eh], 020h ; 80 7e f2 20 ; 0xf93c3 ahci.c:931
+ jnc short 09403h ; 73 3a ; 0xf93c7
+ mov cl, byte [bp-00eh] ; 8a 4e f2 ; 0xf93c9
+ xor ch, ch ; 30 ed ; 0xf93cc
+ mov bx, strict word 00001h ; bb 01 00 ; 0xf93ce
+ xor di, di ; 31 ff ; 0xf93d1
+ jcxz 093dbh ; e3 06 ; 0xf93d3
+ sal bx, 1 ; d1 e3 ; 0xf93d5
+ rcl di, 1 ; d1 d7 ; 0xf93d7
+ loop 093d5h ; e2 fa ; 0xf93d9
+ mov ax, strict word 0000ch ; b8 0c 00 ; 0xf93db
+ xor cx, cx ; 31 c9 ; 0xf93de
+ mov dx, si ; 89 f2 ; 0xf93e0
+ xchg cx, ax ; 91 ; 0xf93e2
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf93e3
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf93e7
+ out DX, eax ; 66 ef ; 0xf93e9
+ lea dx, [si+004h] ; 8d 54 04 ; 0xf93eb
+ in eax, DX ; 66 ed ; 0xf93ee
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf93f0
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf93f2
+ xchg dx, ax ; 92 ; 0xf93f6
+ test dx, di ; 85 fa ; 0xf93f7
+ jne short 093ffh ; 75 04 ; 0xf93f9
+ test ax, bx ; 85 d8 ; 0xf93fb
+ je short 093a8h ; 74 a9 ; 0xf93fd
+ mov AL, strict byte 001h ; b0 01 ; 0xf93ff
+ jmp short 093aah ; eb a7 ; 0xf9401
+ xor ax, ax ; 31 c0 ; 0xf9403 ahci.c:933
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf9405 ahci.c:934
+ pop di ; 5f ; 0xf9408
+ pop si ; 5e ; 0xf9409
+ pop dx ; 5a ; 0xf940a
+ pop cx ; 59 ; 0xf940b
+ pop bx ; 5b ; 0xf940c
+ pop bp ; 5d ; 0xf940d
+ retn ; c3 ; 0xf940e
+ ; disGetNextSymbol 0xf940f LB 0xab9 -> off=0x17 cb=000000000000013a uValue=00000000000f7e26 'ahci_init'
+ db 00bh, 005h, 004h, 003h, 002h, 001h, 000h, 00fh, 095h, 0edh, 094h, 0f3h, 094h, 0f9h, 094h, 0ffh
+ db 094h, 005h, 095h, 00bh, 095h, 00fh, 095h
+ahci_init: ; 0xf9426 LB 0x13a
+ push bp ; 55 ; 0xf9426 ahci.c:939
+ mov bp, sp ; 89 e5 ; 0xf9427
+ push si ; 56 ; 0xf9429
+ push di ; 57 ; 0xf942a
+ sub sp, strict byte 00012h ; 83 ec 12 ; 0xf942b
+ mov ax, 00601h ; b8 01 06 ; 0xf942e ahci.c:943
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf9431
+ call 0995eh ; e8 27 05 ; 0xf9434
+ mov dx, ax ; 89 c2 ; 0xf9437
+ cmp ax, strict word 0ffffh ; 3d ff ff ; 0xf9439 ahci.c:944
+ je short 0948ah ; 74 4c ; 0xf943c
+ xor al, al ; 30 c0 ; 0xf943e ahci.c:949
+ shr ax, 008h ; c1 e8 08 ; 0xf9440
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf9443
+ mov byte [bp-00ah], dl ; 88 56 f6 ; 0xf9446 ahci.c:950
+ xor dh, dh ; 30 f6 ; 0xf9449 ahci.c:955
+ xor ah, ah ; 30 e4 ; 0xf944b
+ mov bx, strict word 00034h ; bb 34 00 ; 0xf944d
+ call 09989h ; e8 36 05 ; 0xf9450
+ mov cl, al ; 88 c1 ; 0xf9453
+ test cl, cl ; 84 c9 ; 0xf9455 ahci.c:957
+ je short 0948dh ; 74 34 ; 0xf9457
+ mov bl, cl ; 88 cb ; 0xf9459 ahci.c:959
+ xor bh, bh ; 30 ff ; 0xf945b
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf945d
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf9460
+ mov byte [bp-00dh], bh ; 88 7e f3 ; 0xf9463
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf9466
+ mov byte [bp-014h], al ; 88 46 ec ; 0xf9469
+ mov byte [bp-013h], bh ; 88 7e ed ; 0xf946c
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf946f
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf9472
+ call 09989h ; e8 11 05 ; 0xf9475
+ cmp AL, strict byte 012h ; 3c 12 ; 0xf9478 ahci.c:963
+ je short 0948dh ; 74 11 ; 0xf947a
+ mov bl, cl ; 88 cb ; 0xf947c ahci.c:967
+ db 0feh, 0c3h
+ ; inc bl ; fe c3 ; 0xf947e
+ xor bh, bh ; 30 ff ; 0xf9480
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf9482
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf9485
+ jmp short 09450h ; eb c6 ; 0xf9488 ahci.c:968
+ jmp near 09559h ; e9 cc 00 ; 0xf948a
+ test cl, cl ; 84 c9 ; 0xf948d ahci.c:970
+ je short 0948ah ; 74 f9 ; 0xf948f
+ add cl, 002h ; 80 c1 02 ; 0xf9491 ahci.c:977
+ mov bl, cl ; 88 cb ; 0xf9494 ahci.c:979
+ xor bh, bh ; 30 ff ; 0xf9496
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf9498
+ mov byte [bp-012h], al ; 88 46 ee ; 0xf949b
+ mov byte [bp-011h], bh ; 88 7e ef ; 0xf949e
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf94a1
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf94a4
+ mov byte [bp-00bh], bh ; 88 7e f5 ; 0xf94a7
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf94aa
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf94ad
+ call 09989h ; e8 d6 04 ; 0xf94b0
+ cmp AL, strict byte 010h ; 3c 10 ; 0xf94b3 ahci.c:980
+ jne short 0948ah ; 75 d3 ; 0xf94b5
+ mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xf94b7 ahci.c:983
+ mov bl, cl ; 88 cb ; 0xf94bb ahci.c:985
+ add bl, 002h ; 80 c3 02 ; 0xf94bd
+ xor bh, bh ; 30 ff ; 0xf94c0
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf94c2
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf94c5
+ call 099b7h ; e8 ec 04 ; 0xf94c8
+ mov dx, ax ; 89 c2 ; 0xf94cb
+ and ax, strict word 0000fh ; 25 0f 00 ; 0xf94cd ahci.c:989
+ sub ax, strict word 00004h ; 2d 04 00 ; 0xf94d0
+ cmp ax, strict word 0000bh ; 3d 0b 00 ; 0xf94d3
+ jnbe short 0950fh ; 77 37 ; 0xf94d6
+ push CS ; 0e ; 0xf94d8
+ pop ES ; 07 ; 0xf94d9
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf94da
+ mov di, 0940fh ; bf 0f 94 ; 0xf94dd
+ repne scasb ; f2 ae ; 0xf94e0
+ sal cx, 1 ; d1 e1 ; 0xf94e2
+ mov di, cx ; 89 cf ; 0xf94e4
+ mov ax, word [cs:di-06beah] ; 2e 8b 85 16 94 ; 0xf94e6
+ jmp ax ; ff e0 ; 0xf94eb
+ mov byte [bp-008h], 010h ; c6 46 f8 10 ; 0xf94ed ahci.c:992
+ jmp short 0950fh ; eb 1c ; 0xf94f1 ahci.c:993
+ mov byte [bp-008h], 014h ; c6 46 f8 14 ; 0xf94f3 ahci.c:995
+ jmp short 0950fh ; eb 16 ; 0xf94f7 ahci.c:996
+ mov byte [bp-008h], 018h ; c6 46 f8 18 ; 0xf94f9 ahci.c:998
+ jmp short 0950fh ; eb 10 ; 0xf94fd ahci.c:999
+ mov byte [bp-008h], 01ch ; c6 46 f8 1c ; 0xf94ff ahci.c:1001
+ jmp short 0950fh ; eb 0a ; 0xf9503 ahci.c:1002
+ mov byte [bp-008h], 020h ; c6 46 f8 20 ; 0xf9505 ahci.c:1004
+ jmp short 0950fh ; eb 04 ; 0xf9509 ahci.c:1005
+ mov byte [bp-008h], 024h ; c6 46 f8 24 ; 0xf950b ahci.c:1007
+ mov si, dx ; 89 d6 ; 0xf950f ahci.c:1016
+ shr si, 004h ; c1 ee 04 ; 0xf9511
+ sal si, 002h ; c1 e6 02 ; 0xf9514
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf9517 ahci.c:1018
+ test al, al ; 84 c0 ; 0xf951a
+ je short 09559h ; 74 3b ; 0xf951c
+ mov bl, al ; 88 c3 ; 0xf951e ahci.c:1020
+ xor bh, bh ; 30 ff ; 0xf9520
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf9522
+ mov byte [bp-010h], al ; 88 46 f0 ; 0xf9525
+ mov byte [bp-00fh], bh ; 88 7e f1 ; 0xf9528
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf952b
+ mov byte [bp-016h], al ; 88 46 ea ; 0xf952e
+ mov byte [bp-015h], bh ; 88 7e eb ; 0xf9531
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf9534
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf9537
+ call 099e1h ; e8 a4 04 ; 0xf953a
+ test AL, strict byte 001h ; a8 01 ; 0xf953d ahci.c:1024
+ je short 09559h ; 74 18 ; 0xf953f
+ and AL, strict byte 0f0h ; 24 f0 ; 0xf9541 ahci.c:1027
+ add si, ax ; 01 c6 ; 0xf9543
+ mov cx, strict word 00007h ; b9 07 00 ; 0xf9545 ahci.c:1030
+ mov bx, strict word 00004h ; bb 04 00 ; 0xf9548
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf954b
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf954e
+ call 09a2fh ; e8 db 04 ; 0xf9551
+ mov ax, si ; 89 f0 ; 0xf9554 ahci.c:1033
+ call 092b9h ; e8 60 fd ; 0xf9556
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9559 ahci.c:1047
+ pop di ; 5f ; 0xf955c
+ pop si ; 5e ; 0xf955d
+ pop bp ; 5d ; 0xf955e
+ retn ; c3 ; 0xf955f
+ ; disGetNextSymbol 0xf9560 LB 0x968 -> off=0x0 cb=000000000000001b uValue=00000000000f7f60 'apm_out_str'
+apm_out_str: ; 0xf9560 LB 0x1b
+ push bp ; 55 ; 0xf9560 apm.c:146
+ mov bp, sp ; 89 e5 ; 0xf9561
+ push bx ; 53 ; 0xf9563
+ mov bx, ax ; 89 c3 ; 0xf9564
+ cmp byte [bx], 000h ; 80 3f 00 ; 0xf9566 apm.c:148
+ je short 09575h ; 74 0a ; 0xf9569
+ mov al, byte [bx] ; 8a 07 ; 0xf956b apm.c:149
+ out DX, AL ; ee ; 0xf956d
+ inc bx ; 43 ; 0xf956e
+ mov al, byte [bx] ; 8a 07 ; 0xf956f
+ db 00ah, 0c0h
+ ; or al, al ; 0a c0 ; 0xf9571
+ jne short 0956dh ; 75 f8 ; 0xf9573
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf9575 apm.c:150
+ pop bx ; 5b ; 0xf9578
+ pop bp ; 5d ; 0xf9579
+ retn ; c3 ; 0xf957a
+ ; disGetNextSymbol 0xf957b LB 0x94d -> off=0x1d cb=00000000000000d7 uValue=00000000000f7f98 'apm_function'
+ db 00eh, 00bh, 007h, 006h, 005h, 004h, 002h, 001h, 000h, 03eh, 096h, 0c6h, 095h, 069h, 096h, 0d8h
+ db 095h, 069h, 096h, 0f3h, 095h, 069h, 096h, 0f8h, 095h, 039h, 096h, 032h, 096h
+apm_function: ; 0xf9598 LB 0xd7
+ push bp ; 55 ; 0xf9598 apm.c:152
+ mov bp, sp ; 89 e5 ; 0xf9599
+ push di ; 57 ; 0xf959b
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf959c apm.c:156
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf95a0 apm.c:157
+ xor dh, dh ; 30 f6 ; 0xf95a3
+ cmp dx, strict byte 0000eh ; 83 fa 0e ; 0xf95a5
+ jnbe short 09615h ; 77 6b ; 0xf95a8
+ mov al, dl ; 88 d0 ; 0xf95aa
+ push CS ; 0e ; 0xf95ac
+ pop ES ; 07 ; 0xf95ad
+ mov cx, strict word 0000ah ; b9 0a 00 ; 0xf95ae
+ mov di, 0957bh ; bf 7b 95 ; 0xf95b1
+ repne scasb ; f2 ae ; 0xf95b4
+ sal cx, 1 ; d1 e1 ; 0xf95b6
+ mov di, cx ; 89 cf ; 0xf95b8
+ mov bx, word [cs:di-06a7ch] ; 2e 8b 9d 84 95 ; 0xf95ba
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf95bf
+ or AL, strict byte 001h ; 0c 01 ; 0xf95c2
+ jmp bx ; ff e3 ; 0xf95c4
+ mov word [bp+012h], 00102h ; c7 46 12 02 01 ; 0xf95c6 apm.c:159
+ mov word [bp+00ch], 0504dh ; c7 46 0c 4d 50 ; 0xf95cb apm.c:160
+ mov word [bp+010h], strict word 00003h ; c7 46 10 03 00 ; 0xf95d0 apm.c:161
+ jmp near 09669h ; e9 91 00 ; 0xf95d5 apm.c:162
+ mov word [bp+012h], 0f000h ; c7 46 12 00 f0 ; 0xf95d8 apm.c:172
+ mov word [bp+00ch], 09c34h ; c7 46 0c 34 9c ; 0xf95dd apm.c:173
+ mov word [bp+010h], 0f000h ; c7 46 10 00 f0 ; 0xf95e2 apm.c:174
+ mov ax, strict word 0fff0h ; b8 f0 ff ; 0xf95e7 apm.c:175
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf95ea
+ mov word [bp+004h], ax ; 89 46 04 ; 0xf95ed apm.c:176
+ jmp near 09669h ; e9 76 00 ; 0xf95f0 apm.c:177
+ sti ; fb ; 0xf95f3 apm.c:194
+ hlt ; f4 ; 0xf95f4 apm.c:195
+ jmp near 09669h ; e9 71 00 ; 0xf95f5 apm.c:196
+ cmp word [bp+010h], strict byte 00003h ; 83 7e 10 03 ; 0xf95f8 apm.c:200
+ je short 0961fh ; 74 21 ; 0xf95fc
+ cmp word [bp+010h], strict byte 00002h ; 83 7e 10 02 ; 0xf95fe
+ je short 09617h ; 74 13 ; 0xf9602
+ cmp word [bp+010h], strict byte 00001h ; 83 7e 10 01 ; 0xf9604
+ jne short 09627h ; 75 1d ; 0xf9608
+ mov dx, 0040fh ; ba 0f 04 ; 0xf960a apm.c:202
+ mov ax, 00d10h ; b8 10 0d ; 0xf960d
+ call 09560h ; e8 4d ff ; 0xf9610
+ jmp short 09669h ; eb 54 ; 0xf9613 apm.c:203
+ jmp short 0963eh ; eb 27 ; 0xf9615
+ mov dx, 0040fh ; ba 0f 04 ; 0xf9617 apm.c:205
+ mov ax, 00d18h ; b8 18 0d ; 0xf961a
+ jmp short 09610h ; eb f1 ; 0xf961d
+ mov dx, 0040fh ; ba 0f 04 ; 0xf961f apm.c:208
+ mov ax, 00d20h ; b8 20 0d ; 0xf9622
+ jmp short 09610h ; eb e9 ; 0xf9625
+ or dh, 00ah ; 80 ce 0a ; 0xf9627 apm.c:211
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf962a
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf962d apm.c:212
+ jmp short 09669h ; eb 37 ; 0xf9630 apm.c:214
+ mov word [bp+012h], 00102h ; c7 46 12 02 01 ; 0xf9632 apm.c:216
+ jmp short 09669h ; eb 30 ; 0xf9637 apm.c:217
+ or dh, 080h ; 80 ce 80 ; 0xf9639 apm.c:224
+ jmp short 0962ah ; eb ec ; 0xf963c
+ mov bx, 00da0h ; bb a0 0d ; 0xf963e apm.c:228
+ mov cx, ds ; 8c d9 ; 0xf9641
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf9643
+ call 018bch ; e8 73 82 ; 0xf9646
+ push word [bp+00ch] ; ff 76 0c ; 0xf9649
+ push word [bp+012h] ; ff 76 12 ; 0xf964c
+ push 00d29h ; 68 29 0d ; 0xf964f
+ push strict byte 00004h ; 6a 04 ; 0xf9652
+ call 018ffh ; e8 a8 82 ; 0xf9654
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf9657
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf965a apm.c:229
+ xor ah, ah ; 30 e4 ; 0xf965d
+ or ah, 00ch ; 80 cc 0c ; 0xf965f
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf9662
+ or byte [bp+018h], 001h ; 80 4e 18 01 ; 0xf9665 apm.c:230
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf9669 apm.c:232
+ pop di ; 5f ; 0xf966c
+ pop bp ; 5d ; 0xf966d
+ retn ; c3 ; 0xf966e
+ ; disGetNextSymbol 0xf966f LB 0x859 -> off=0x0 cb=0000000000000024 uValue=00000000000f806f 'pci16_select_reg'
+pci16_select_reg: ; 0xf966f LB 0x24
+ push bp ; 55 ; 0xf966f pcibios.c:188
+ mov bp, sp ; 89 e5 ; 0xf9670
+ push bx ; 53 ; 0xf9672
+ and dl, 0fch ; 80 e2 fc ; 0xf9673 pcibios.c:190
+ mov bx, dx ; 89 d3 ; 0xf9676
+ mov dx, 00cf8h ; ba f8 0c ; 0xf9678
+ movzx eax, ax ; 66 0f b7 c0 ; 0xf967b
+ sal eax, 008h ; 66 c1 e0 08 ; 0xf967f
+ or eax, strict dword 080000000h ; 66 0d 00 00 00 80 ; 0xf9683
+ db 08ah, 0c3h
+ ; mov al, bl ; 8a c3 ; 0xf9689
+ out DX, eax ; 66 ef ; 0xf968b
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf968d pcibios.c:191
+ pop bx ; 5b ; 0xf9690
+ pop bp ; 5d ; 0xf9691
+ retn ; c3 ; 0xf9692
+ ; disGetNextSymbol 0xf9693 LB 0x835 -> off=0x0 cb=00000000000000ed uValue=00000000000f8093 'pci16_find_device'
+pci16_find_device: ; 0xf9693 LB 0xed
+ push bp ; 55 ; 0xf9693 pcibios.c:221
+ mov bp, sp ; 89 e5 ; 0xf9694
+ push si ; 56 ; 0xf9696
+ push di ; 57 ; 0xf9697
+ sub sp, strict byte 0000ch ; 83 ec 0c ; 0xf9698
+ push ax ; 50 ; 0xf969b
+ push dx ; 52 ; 0xf969c
+ mov si, bx ; 89 de ; 0xf969d
+ mov di, cx ; 89 cf ; 0xf969f
+ test cx, cx ; 85 c9 ; 0xf96a1 pcibios.c:231
+ xor bx, bx ; 31 db ; 0xf96a3 pcibios.c:238
+ mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xf96a5 pcibios.c:239
+ test bl, 007h ; f6 c3 07 ; 0xf96a9 pcibios.c:249
+ jne short 096dbh ; 75 2d ; 0xf96ac
+ mov dx, strict word 0000eh ; ba 0e 00 ; 0xf96ae pcibios.c:250
+ mov ax, bx ; 89 d8 ; 0xf96b1
+ call 0966fh ; e8 b9 ff ; 0xf96b3
+ mov dx, 00cfeh ; ba fe 0c ; 0xf96b6 pcibios.c:251
+ in AL, DX ; ec ; 0xf96b9
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf96ba
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf96bc
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xf96bf pcibios.c:252
+ jne short 096c9h ; 75 06 ; 0xf96c1
+ add bx, strict byte 00008h ; 83 c3 08 ; 0xf96c3 pcibios.c:253
+ jmp near 0975ch ; e9 93 00 ; 0xf96c6 pcibios.c:254
+ test byte [bp-006h], 080h ; f6 46 fa 80 ; 0xf96c9 pcibios.c:256
+ je short 096d6h ; 74 07 ; 0xf96cd
+ mov word [bp-010h], strict word 00001h ; c7 46 f0 01 00 ; 0xf96cf pcibios.c:257
+ jmp short 096dbh ; eb 05 ; 0xf96d4 pcibios.c:258
+ mov word [bp-010h], strict word 00008h ; c7 46 f0 08 00 ; 0xf96d6 pcibios.c:259
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf96db pcibios.c:270
+ and AL, strict byte 007h ; 24 07 ; 0xf96de
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf96e0
+ jne short 09703h ; 75 1f ; 0xf96e2
+ mov ax, bx ; 89 d8 ; 0xf96e4
+ shr ax, 008h ; c1 e8 08 ; 0xf96e6
+ test ax, ax ; 85 c0 ; 0xf96e9
+ jne short 09703h ; 75 16 ; 0xf96eb
+ mov dx, strict word 0001ah ; ba 1a 00 ; 0xf96ed pcibios.c:272
+ mov ax, bx ; 89 d8 ; 0xf96f0
+ call 0966fh ; e8 7a ff ; 0xf96f2
+ mov dx, 00cfeh ; ba fe 0c ; 0xf96f5 pcibios.c:273
+ in AL, DX ; ec ; 0xf96f8
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf96f9
+ cmp al, byte [bp-008h] ; 3a 46 f8 ; 0xf96fb pcibios.c:274
+ jbe short 09703h ; 76 03 ; 0xf96fe
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf9700 pcibios.c:275
+ test di, di ; 85 ff ; 0xf9703 pcibios.c:279
+ je short 0970ch ; 74 05 ; 0xf9705
+ mov dx, strict word 00008h ; ba 08 00 ; 0xf9707
+ jmp short 0970eh ; eb 02 ; 0xf970a
+ xor dx, dx ; 31 d2 ; 0xf970c
+ mov ax, bx ; 89 d8 ; 0xf970e
+ call 0966fh ; e8 5c ff ; 0xf9710
+ mov dx, 00cfch ; ba fc 0c ; 0xf9713 pcibios.c:280
+ in eax, DX ; 66 ed ; 0xf9716
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9718
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf971a
+ xchg dx, ax ; 92 ; 0xf971e
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf971f
+ mov word [bp-00ch], dx ; 89 56 f4 ; 0xf9722
+ mov word [bp-00eh], strict word 00000h ; c7 46 f2 00 00 ; 0xf9725 pcibios.c:281
+ test di, di ; 85 ff ; 0xf972a pcibios.c:284
+ je short 0973dh ; 74 0f ; 0xf972c
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf972e pcibios.c:285
+ shr dx, 1 ; d1 ea ; 0xf9731
+ rcr ax, 1 ; d1 d8 ; 0xf9733
+ loop 09731h ; e2 fa ; 0xf9735
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf9737
+ mov word [bp-00ch], dx ; 89 56 f4 ; 0xf973a
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf973d pcibios.c:292
+ cmp ax, word [bp-014h] ; 3b 46 ec ; 0xf9740
+ jne short 0974dh ; 75 08 ; 0xf9743
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf9745
+ cmp ax, word [bp-012h] ; 3b 46 ee ; 0xf9748
+ je short 09753h ; 74 06 ; 0xf974b
+ cmp word [bp-00eh], strict byte 00000h ; 83 7e f2 00 ; 0xf974d pcibios.c:293
+ je short 09759h ; 74 06 ; 0xf9751
+ dec si ; 4e ; 0xf9753
+ cmp si, strict byte 0ffffh ; 83 fe ff ; 0xf9754
+ je short 0976dh ; 74 14 ; 0xf9757
+ add bx, word [bp-010h] ; 03 5e f0 ; 0xf9759 pcibios.c:301
+ mov dx, bx ; 89 da ; 0xf975c pcibios.c:302
+ shr dx, 008h ; c1 ea 08 ; 0xf975e
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf9761
+ xor ah, ah ; 30 e4 ; 0xf9764
+ cmp dx, ax ; 39 c2 ; 0xf9766
+ jnbe short 0976dh ; 77 03 ; 0xf9768
+ jmp near 096a9h ; e9 3c ff ; 0xf976a
+ cmp si, strict byte 0ffffh ; 83 fe ff ; 0xf976d pcibios.c:304
+ jne short 09776h ; 75 04 ; 0xf9770 pcibios.c:308
+ mov ax, bx ; 89 d8 ; 0xf9772
+ jmp short 09779h ; eb 03 ; 0xf9774
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf9776
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9779 pcibios.c:309
+ pop di ; 5f ; 0xf977c
+ pop si ; 5e ; 0xf977d
+ pop bp ; 5d ; 0xf977e
+ retn ; c3 ; 0xf977f
+ ; disGetNextSymbol 0xf9780 LB 0x748 -> off=0xc cb=00000000000001d2 uValue=00000000000f818c 'pci16_function'
+ db 06dh, 098h, 086h, 098h, 098h, 098h, 0ach, 098h, 0beh, 098h, 0d1h, 098h
+pci16_function: ; 0xf978c LB 0x1d2
+ push bp ; 55 ; 0xf978c pcibios.c:311
+ mov bp, sp ; 89 e5 ; 0xf978d
+ push si ; 56 ; 0xf978f
+ push di ; 57 ; 0xf9790
+ push ax ; 50 ; 0xf9791
+ push ax ; 50 ; 0xf9792
+ and word [bp+020h], 000ffh ; 81 66 20 ff 00 ; 0xf9793 pcibios.c:318
+ and word [bp+02ch], strict byte 0fffeh ; 83 66 2c fe ; 0xf9798 pcibios.c:319
+ mov bx, word [bp+020h] ; 8b 5e 20 ; 0xf979c pcibios.c:321
+ xor bh, bh ; 30 ff ; 0xf979f
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf97a1
+ xor ah, ah ; 30 e4 ; 0xf97a4
+ cmp bx, strict byte 00003h ; 83 fb 03 ; 0xf97a6
+ jc short 097beh ; 72 13 ; 0xf97a9
+ jbe short 09811h ; 76 64 ; 0xf97ab
+ cmp bx, strict byte 0000eh ; 83 fb 0e ; 0xf97ad
+ je short 09819h ; 74 67 ; 0xf97b0
+ cmp bx, strict byte 00008h ; 83 fb 08 ; 0xf97b2
+ jc short 097c8h ; 72 11 ; 0xf97b5
+ cmp bx, strict byte 0000dh ; 83 fb 0d ; 0xf97b7
+ jbe short 0981ch ; 76 60 ; 0xf97ba
+ jmp short 097c8h ; eb 0a ; 0xf97bc
+ cmp bx, strict byte 00002h ; 83 fb 02 ; 0xf97be
+ je short 097e7h ; 74 24 ; 0xf97c1
+ cmp bx, strict byte 00001h ; 83 fb 01 ; 0xf97c3
+ je short 097cbh ; 74 03 ; 0xf97c6
+ jmp near 0992ah ; e9 5f 01 ; 0xf97c8
+ mov word [bp+020h], strict word 00001h ; c7 46 20 01 00 ; 0xf97cb pcibios.c:323
+ mov word [bp+014h], 00210h ; c7 46 14 10 02 ; 0xf97d0 pcibios.c:324
+ mov word [bp+01ch], strict word 00000h ; c7 46 1c 00 00 ; 0xf97d5 pcibios.c:326
+ mov word [bp+018h], 04350h ; c7 46 18 50 43 ; 0xf97da pcibios.c:327
+ mov word [bp+01ah], 02049h ; c7 46 1a 49 20 ; 0xf97df
+ jmp near 09957h ; e9 70 01 ; 0xf97e4 pcibios.c:328
+ cmp word [bp+018h], strict byte 0ffffh ; 83 7e 18 ff ; 0xf97e7 pcibios.c:333
+ jne short 097f3h ; 75 06 ; 0xf97eb
+ or ah, 083h ; 80 cc 83 ; 0xf97ed pcibios.c:334
+ jmp near 09950h ; e9 5d 01 ; 0xf97f0 pcibios.c:335
+ mov bx, word [bp+008h] ; 8b 5e 08 ; 0xf97f3 pcibios.c:337
+ mov dx, word [bp+01ch] ; 8b 56 1c ; 0xf97f6
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf97f9
+ xor cx, cx ; 31 c9 ; 0xf97fc
+ call 09693h ; e8 92 fe ; 0xf97fe
+ cmp ax, strict word 0ffffh ; 3d ff ff ; 0xf9801 pcibios.c:338
+ jne short 09813h ; 75 0d ; 0xf9804
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf9806 pcibios.c:339
+ xor ah, ah ; 30 e4 ; 0xf9809
+ or ah, 086h ; 80 cc 86 ; 0xf980b
+ jmp near 09950h ; e9 3f 01 ; 0xf980e
+ jmp short 0981eh ; eb 0b ; 0xf9811
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf9813 pcibios.c:340
+ jmp near 09957h ; e9 3e 01 ; 0xf9816 pcibios.c:345
+ jmp near 098e5h ; e9 c9 00 ; 0xf9819
+ jmp short 09843h ; eb 25 ; 0xf981c
+ mov bx, word [bp+008h] ; 8b 5e 08 ; 0xf981e pcibios.c:347
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf9821
+ mov dx, word [bp+01eh] ; 8b 56 1e ; 0xf9824
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf9827
+ call 09693h ; e8 66 fe ; 0xf982a
+ cmp ax, strict word 0ffffh ; 3d ff ff ; 0xf982d pcibios.c:348
+ jne short 0983dh ; 75 0b ; 0xf9830
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf9832 pcibios.c:349
+ xor ah, ah ; 30 e4 ; 0xf9835
+ or ah, 086h ; 80 cc 86 ; 0xf9837
+ jmp near 09950h ; e9 13 01 ; 0xf983a pcibios.c:350
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf983d pcibios.c:352
+ jmp near 09957h ; e9 14 01 ; 0xf9840 pcibios.c:354
+ cmp word [bp+004h], 00100h ; 81 7e 04 00 01 ; 0xf9843 pcibios.c:361
+ jc short 09850h ; 72 06 ; 0xf9848
+ or ah, 087h ; 80 cc 87 ; 0xf984a pcibios.c:362
+ jmp near 09950h ; e9 00 01 ; 0xf984d pcibios.c:363
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf9850 pcibios.c:365
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf9853
+ call 0966fh ; e8 16 fe ; 0xf9856
+ mov bx, word [bp+020h] ; 8b 5e 20 ; 0xf9859 pcibios.c:366
+ xor bh, bh ; 30 ff ; 0xf985c
+ sub bx, strict byte 00008h ; 83 eb 08 ; 0xf985e
+ cmp bx, strict byte 00005h ; 83 fb 05 ; 0xf9861
+ jnbe short 098ceh ; 77 68 ; 0xf9864
+ add bx, bx ; 01 db ; 0xf9866
+ jmp word [cs:bx-06880h] ; 2e ff a7 80 97 ; 0xf9868
+ mov bx, word [bp+01ch] ; 8b 5e 1c ; 0xf986d pcibios.c:368
+ xor bl, bl ; 30 db ; 0xf9870
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf9872
+ and dx, strict byte 00003h ; 83 e2 03 ; 0xf9875
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xf9878
+ in AL, DX ; ec ; 0xf987c
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf987d
+ or bx, ax ; 09 c3 ; 0xf987f
+ mov word [bp+01ch], bx ; 89 5e 1c ; 0xf9881
+ jmp short 098ceh ; eb 48 ; 0xf9884 pcibios.c:369
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf9886 pcibios.c:371
+ xor dh, dh ; 30 f6 ; 0xf9889
+ and dl, 002h ; 80 e2 02 ; 0xf988b
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xf988e
+ in ax, DX ; ed ; 0xf9892
+ mov word [bp+01ch], ax ; 89 46 1c ; 0xf9893
+ jmp short 098ceh ; eb 36 ; 0xf9896 pcibios.c:372
+ mov dx, 00cfch ; ba fc 0c ; 0xf9898 pcibios.c:374
+ in eax, DX ; 66 ed ; 0xf989b
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf989d
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf989f
+ xchg dx, ax ; 92 ; 0xf98a3
+ mov word [bp+01ch], ax ; 89 46 1c ; 0xf98a4
+ mov word [bp+01eh], dx ; 89 56 1e ; 0xf98a7
+ jmp short 098ceh ; eb 22 ; 0xf98aa pcibios.c:375
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf98ac pcibios.c:377
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf98af
+ xor dh, dh ; 30 f6 ; 0xf98b2
+ and dl, 003h ; 80 e2 03 ; 0xf98b4
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xf98b7
+ out DX, AL ; ee ; 0xf98bb
+ jmp short 098ceh ; eb 10 ; 0xf98bc pcibios.c:378
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf98be pcibios.c:380
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf98c1
+ xor dh, dh ; 30 f6 ; 0xf98c4
+ and dl, 002h ; 80 e2 02 ; 0xf98c6
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xf98c9
+ out DX, ax ; ef ; 0xf98cd
+ jmp near 09957h ; e9 86 00 ; 0xf98ce pcibios.c:381
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf98d1 pcibios.c:383
+ mov cx, word [bp+01eh] ; 8b 4e 1e ; 0xf98d4
+ mov dx, 00cfch ; ba fc 0c ; 0xf98d7
+ xchg cx, ax ; 91 ; 0xf98da
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf98db
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf98df
+ out DX, eax ; 66 ef ; 0xf98e1
+ jmp short 09957h ; eb 72 ; 0xf98e3 pcibios.c:387
+ mov bx, word [bp+004h] ; 8b 5e 04 ; 0xf98e5 pcibios.c:389
+ mov es, [bp+026h] ; 8e 46 26 ; 0xf98e8
+ mov word [bp-008h], bx ; 89 5e f8 ; 0xf98eb
+ mov [bp-006h], es ; 8c 46 fa ; 0xf98ee
+ mov cx, word [0f380h] ; 8b 0e 80 f3 ; 0xf98f1 pcibios.c:393
+ cmp cx, word [es:bx] ; 26 3b 0f ; 0xf98f5
+ jbe short 0990bh ; 76 11 ; 0xf98f8
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf98fa pcibios.c:394
+ xor ah, ah ; 30 e4 ; 0xf98fd
+ or ah, 089h ; 80 cc 89 ; 0xf98ff
+ mov word [bp+020h], ax ; 89 46 20 ; 0xf9902
+ or word [bp+02ch], strict byte 00001h ; 83 4e 2c 01 ; 0xf9905 pcibios.c:395
+ jmp short 0991fh ; eb 14 ; 0xf9909 pcibios.c:396
+ les di, [es:bx+002h] ; 26 c4 7f 02 ; 0xf990b pcibios.c:397
+ mov si, 0f1a0h ; be a0 f1 ; 0xf990f
+ mov dx, ds ; 8c da ; 0xf9912
+ push DS ; 1e ; 0xf9914
+ mov ds, dx ; 8e da ; 0xf9915
+ rep movsb ; f3 a4 ; 0xf9917
+ pop DS ; 1f ; 0xf9919
+ mov word [bp+014h], 00a00h ; c7 46 14 00 0a ; 0xf991a pcibios.c:399
+ mov ax, word [0f380h] ; a1 80 f3 ; 0xf991f pcibios.c:401
+ les bx, [bp-008h] ; c4 5e f8 ; 0xf9922
+ mov word [es:bx], ax ; 26 89 07 ; 0xf9925
+ jmp short 09957h ; eb 2d ; 0xf9928 pcibios.c:402
+ mov bx, 00da0h ; bb a0 0d ; 0xf992a pcibios.c:404
+ mov cx, ds ; 8c d9 ; 0xf992d
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf992f
+ call 018bch ; e8 87 7f ; 0xf9932
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf9935
+ push ax ; 50 ; 0xf9938
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf9939
+ push ax ; 50 ; 0xf993c
+ push 00d5ch ; 68 5c 0d ; 0xf993d
+ push strict byte 00004h ; 6a 04 ; 0xf9940
+ call 018ffh ; e8 ba 7f ; 0xf9942
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf9945
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf9948 pcibios.c:405
+ xor ah, ah ; 30 e4 ; 0xf994b
+ or ah, 081h ; 80 cc 81 ; 0xf994d
+ mov word [bp+020h], ax ; 89 46 20 ; 0xf9950
+ or word [bp+02ch], strict byte 00001h ; 83 4e 2c 01 ; 0xf9953 pcibios.c:406
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9957 pcibios.c:408
+ pop di ; 5f ; 0xf995a
+ pop si ; 5e ; 0xf995b
+ pop bp ; 5d ; 0xf995c
+ retn ; c3 ; 0xf995d
+ ; disGetNextSymbol 0xf995e LB 0x56a -> off=0x0 cb=0000000000000008 uValue=00000000000f835e 'pci_find_classcode'
+pci_find_classcode: ; 0xf995e LB 0x8
+ push bp ; 55 ; 0xf995e pciutil.c:126
+ mov bp, sp ; 89 e5 ; 0xf995f
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf9961 pciutil.c:133
+ pop bp ; 5d ; 0xf9964
+ retn ; c3 ; 0xf9965
+ ; disGetNextSymbol 0xf9966 LB 0x562 -> off=0x0 cb=0000000000000023 uValue=00000000000f8366 'pci_find_device'
+pci_find_device: ; 0xf9966 LB 0x23
+ push bp ; 55 ; 0xf9966 pciutil.c:146
+ mov bp, sp ; 89 e5 ; 0xf9967
+ push bx ; 53 ; 0xf9969
+ push cx ; 51 ; 0xf996a
+ push si ; 56 ; 0xf996b
+ mov cx, dx ; 89 d1 ; 0xf996c
+ xor si, si ; 31 f6 ; 0xf996e pciutil.c:148
+ mov dx, ax ; 89 c2 ; 0xf9970
+ mov ax, 0b102h ; b8 02 b1 ; 0xf9972
+ int 01ah ; cd 1a ; 0xf9975
+ cmp ah, 000h ; 80 fc 00 ; 0xf9977
+ je short 0997fh ; 74 03 ; 0xf997a
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf997c
+ mov ax, bx ; 89 d8 ; 0xf997f
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf9981 pciutil.c:149
+ pop si ; 5e ; 0xf9984
+ pop cx ; 59 ; 0xf9985
+ pop bx ; 5b ; 0xf9986
+ pop bp ; 5d ; 0xf9987
+ retn ; c3 ; 0xf9988
+ ; disGetNextSymbol 0xf9989 LB 0x53f -> off=0x0 cb=000000000000002e uValue=00000000000f8389 'pci_read_config_byte'
+pci_read_config_byte: ; 0xf9989 LB 0x2e
+ push bp ; 55 ; 0xf9989 pciutil.c:151
+ mov bp, sp ; 89 e5 ; 0xf998a
+ push cx ; 51 ; 0xf998c
+ push di ; 57 ; 0xf998d
+ mov dh, al ; 88 c6 ; 0xf998e
+ mov bh, dl ; 88 d7 ; 0xf9990
+ mov al, bl ; 88 d8 ; 0xf9992
+ xor ah, ah ; 30 e4 ; 0xf9994 pciutil.c:153
+ mov dl, dh ; 88 f2 ; 0xf9996
+ xor dh, dh ; 30 f6 ; 0xf9998
+ sal dx, 008h ; c1 e2 08 ; 0xf999a
+ mov bl, bh ; 88 fb ; 0xf999d
+ xor bh, bh ; 30 ff ; 0xf999f
+ or bx, dx ; 09 d3 ; 0xf99a1
+ mov di, ax ; 89 c7 ; 0xf99a3
+ mov ax, 0b108h ; b8 08 b1 ; 0xf99a5
+ int 01ah ; cd 1a ; 0xf99a8
+ mov al, cl ; 88 c8 ; 0xf99aa
+ xor ah, ah ; 30 e4 ; 0xf99ac
+ xor dx, dx ; 31 d2 ; 0xf99ae pciutil.c:154
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf99b0
+ pop di ; 5f ; 0xf99b3
+ pop cx ; 59 ; 0xf99b4
+ pop bp ; 5d ; 0xf99b5
+ retn ; c3 ; 0xf99b6
+ ; disGetNextSymbol 0xf99b7 LB 0x511 -> off=0x0 cb=000000000000002a uValue=00000000000f83b7 'pci_read_config_word'
+pci_read_config_word: ; 0xf99b7 LB 0x2a
+ push bp ; 55 ; 0xf99b7 pciutil.c:156
+ mov bp, sp ; 89 e5 ; 0xf99b8
+ push cx ; 51 ; 0xf99ba
+ push di ; 57 ; 0xf99bb
+ mov bh, al ; 88 c7 ; 0xf99bc
+ mov al, bl ; 88 d8 ; 0xf99be
+ xor ah, ah ; 30 e4 ; 0xf99c0 pciutil.c:158
+ mov bl, bh ; 88 fb ; 0xf99c2
+ xor bh, bh ; 30 ff ; 0xf99c4
+ mov cx, bx ; 89 d9 ; 0xf99c6
+ sal cx, 008h ; c1 e1 08 ; 0xf99c8
+ mov bl, dl ; 88 d3 ; 0xf99cb
+ or bx, cx ; 09 cb ; 0xf99cd
+ mov di, ax ; 89 c7 ; 0xf99cf
+ mov ax, 0b109h ; b8 09 b1 ; 0xf99d1
+ int 01ah ; cd 1a ; 0xf99d4
+ mov ax, cx ; 89 c8 ; 0xf99d6
+ xor dx, dx ; 31 d2 ; 0xf99d8 pciutil.c:159
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf99da
+ pop di ; 5f ; 0xf99dd
+ pop cx ; 59 ; 0xf99de
+ pop bp ; 5d ; 0xf99df
+ retn ; c3 ; 0xf99e0
+ ; disGetNextSymbol 0xf99e1 LB 0x4e7 -> off=0x0 cb=000000000000004e uValue=00000000000f83e1 'pci_read_config_dword'
+pci_read_config_dword: ; 0xf99e1 LB 0x4e
+ push bp ; 55 ; 0xf99e1 pciutil.c:161
+ mov bp, sp ; 89 e5 ; 0xf99e2
+ push cx ; 51 ; 0xf99e4
+ push di ; 57 ; 0xf99e5
+ push ax ; 50 ; 0xf99e6
+ mov dh, al ; 88 c6 ; 0xf99e7
+ mov cl, dl ; 88 d1 ; 0xf99e9
+ mov byte [bp-006h], bl ; 88 5e fa ; 0xf99eb
+ mov al, bl ; 88 d8 ; 0xf99ee pciutil.c:166
+ xor ah, ah ; 30 e4 ; 0xf99f0
+ mov dl, dh ; 88 f2 ; 0xf99f2
+ xor dh, dh ; 30 f6 ; 0xf99f4
+ mov di, dx ; 89 d7 ; 0xf99f6
+ sal di, 008h ; c1 e7 08 ; 0xf99f8
+ mov dl, cl ; 88 ca ; 0xf99fb
+ or dx, di ; 09 fa ; 0xf99fd
+ mov di, ax ; 89 c7 ; 0xf99ff
+ mov bx, dx ; 89 d3 ; 0xf9a01
+ mov ax, 0b109h ; b8 09 b1 ; 0xf9a03
+ int 01ah ; cd 1a ; 0xf9a06
+ test cx, cx ; 85 c9 ; 0xf9a08
+ jne short 09a20h ; 75 14 ; 0xf9a0a
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf9a0c
+ xor ah, ah ; 30 e4 ; 0xf9a0f
+ mov di, ax ; 89 c7 ; 0xf9a11
+ inc di ; 47 ; 0xf9a13
+ inc di ; 47 ; 0xf9a14
+ mov bx, dx ; 89 d3 ; 0xf9a15
+ mov ax, 0b109h ; b8 09 b1 ; 0xf9a17
+ int 01ah ; cd 1a ; 0xf9a1a
+ test cx, cx ; 85 c9 ; 0xf9a1c
+ je short 09a25h ; 74 05 ; 0xf9a1e
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf9a20
+ jmp short 09a27h ; eb 02 ; 0xf9a23
+ xor ax, ax ; 31 c0 ; 0xf9a25
+ cwd ; 99 ; 0xf9a27
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9a28 pciutil.c:169
+ pop di ; 5f ; 0xf9a2b
+ pop cx ; 59 ; 0xf9a2c
+ pop bp ; 5d ; 0xf9a2d
+ retn ; c3 ; 0xf9a2e
+ ; disGetNextSymbol 0xf9a2f LB 0x499 -> off=0x0 cb=0000000000000025 uValue=00000000000f842f 'pci_write_config_word'
+pci_write_config_word: ; 0xf9a2f LB 0x25
+ push bp ; 55 ; 0xf9a2f pciutil.c:171
+ mov bp, sp ; 89 e5 ; 0xf9a30
+ push di ; 57 ; 0xf9a32
+ push ax ; 50 ; 0xf9a33
+ mov byte [bp-004h], al ; 88 46 fc ; 0xf9a34
+ mov al, bl ; 88 d8 ; 0xf9a37
+ xor ah, ah ; 30 e4 ; 0xf9a39 pciutil.c:173
+ mov di, ax ; 89 c7 ; 0xf9a3b
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf9a3d
+ mov bx, ax ; 89 c3 ; 0xf9a40
+ sal bx, 008h ; c1 e3 08 ; 0xf9a42
+ mov al, dl ; 88 d0 ; 0xf9a45
+ or bx, ax ; 09 c3 ; 0xf9a47
+ mov ax, 0b10ch ; b8 0c b1 ; 0xf9a49
+ int 01ah ; cd 1a ; 0xf9a4c
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf9a4e pciutil.c:174
+ pop di ; 5f ; 0xf9a51
+ pop bp ; 5d ; 0xf9a52
+ retn ; c3 ; 0xf9a53
+ ; disGetNextSymbol 0xf9a54 LB 0x474 -> off=0x0 cb=000000000000001d uValue=00000000000f8454 'vds_is_present'
+vds_is_present: ; 0xf9a54 LB 0x1d
+ push bx ; 53 ; 0xf9a54 vds.c:32
+ push bp ; 55 ; 0xf9a55
+ mov bp, sp ; 89 e5 ; 0xf9a56
+ mov bx, strict word 0007bh ; bb 7b 00 ; 0xf9a58 vds.c:36
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf9a5b
+ mov es, ax ; 8e c0 ; 0xf9a5e
+ test byte [es:bx], 020h ; 26 f6 07 20 ; 0xf9a60 vds.c:37
+ je short 09a6ch ; 74 06 ; 0xf9a64
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf9a66
+ pop bp ; 5d ; 0xf9a69
+ pop bx ; 5b ; 0xf9a6a
+ retn ; c3 ; 0xf9a6b
+ xor ax, ax ; 31 c0 ; 0xf9a6c
+ pop bp ; 5d ; 0xf9a6e vds.c:38
+ pop bx ; 5b ; 0xf9a6f
+ retn ; c3 ; 0xf9a70
+ ; disGetNextSymbol 0xf9a71 LB 0x457 -> off=0x0 cb=000000000000001e uValue=00000000000f8471 'vds_real_to_lin'
+vds_real_to_lin: ; 0xf9a71 LB 0x1e
+ push bx ; 53 ; 0xf9a71 vds.c:67
+ push cx ; 51 ; 0xf9a72
+ push bp ; 55 ; 0xf9a73
+ mov bp, sp ; 89 e5 ; 0xf9a74
+ mov bx, ax ; 89 c3 ; 0xf9a76
+ mov ax, dx ; 89 d0 ; 0xf9a78
+ xor dx, dx ; 31 d2 ; 0xf9a7a vds.c:69
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf9a7c
+ sal ax, 1 ; d1 e0 ; 0xf9a7f
+ rcl dx, 1 ; d1 d2 ; 0xf9a81
+ loop 09a7fh ; e2 fa ; 0xf9a83
+ xor cx, cx ; 31 c9 ; 0xf9a85
+ add ax, bx ; 01 d8 ; 0xf9a87
+ adc dx, cx ; 11 ca ; 0xf9a89
+ pop bp ; 5d ; 0xf9a8b vds.c:70
+ pop cx ; 59 ; 0xf9a8c
+ pop bx ; 5b ; 0xf9a8d
+ retn ; c3 ; 0xf9a8e
+ ; disGetNextSymbol 0xf9a8f LB 0x439 -> off=0x0 cb=0000000000000077 uValue=00000000000f848f 'vds_build_sg_list'
+vds_build_sg_list: ; 0xf9a8f LB 0x77
+ push bp ; 55 ; 0xf9a8f vds.c:77
+ mov bp, sp ; 89 e5 ; 0xf9a90
+ push si ; 56 ; 0xf9a92
+ push di ; 57 ; 0xf9a93
+ mov di, ax ; 89 c7 ; 0xf9a94
+ mov si, dx ; 89 d6 ; 0xf9a96
+ mov ax, bx ; 89 d8 ; 0xf9a98
+ mov dx, cx ; 89 ca ; 0xf9a9a
+ mov bx, word [bp+004h] ; 8b 5e 04 ; 0xf9a9c vds.c:82
+ mov es, si ; 8e c6 ; 0xf9a9f
+ mov word [es:di], bx ; 26 89 1d ; 0xf9aa1
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf9aa4
+ mov word [es:di+002h], bx ; 26 89 5d 02 ; 0xf9aa7
+ call 09a71h ; e8 c3 ff ; 0xf9aab vds.c:83
+ mov es, si ; 8e c6 ; 0xf9aae
+ mov word [es:di+004h], ax ; 26 89 45 04 ; 0xf9ab0
+ mov word [es:di+006h], dx ; 26 89 55 06 ; 0xf9ab4
+ mov word [es:di+008h], strict word 00000h ; 26 c7 45 08 00 00 ; 0xf9ab8 vds.c:84
+ call 09a54h ; e8 93 ff ; 0xf9abe vds.c:85
+ test ax, ax ; 85 c0 ; 0xf9ac1
+ je short 09ad6h ; 74 11 ; 0xf9ac3
+ mov es, si ; 8e c6 ; 0xf9ac5 vds.c:87
+ mov ax, 08105h ; b8 05 81 ; 0xf9ac7
+ mov dx, strict word 00000h ; ba 00 00 ; 0xf9aca
+ int 04bh ; cd 4b ; 0xf9acd
+ jc short 09ad3h ; 72 02 ; 0xf9acf
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xf9ad1
+ cbw ; 98 ; 0xf9ad3
+ jmp short 09afdh ; eb 27 ; 0xf9ad4 vds.c:88
+ mov es, si ; 8e c6 ; 0xf9ad6 vds.c:90
+ mov word [es:di+00eh], strict word 00001h ; 26 c7 45 0e 01 00 ; 0xf9ad8
+ mov dx, word [es:di+004h] ; 26 8b 55 04 ; 0xf9ade vds.c:91
+ mov ax, word [es:di+006h] ; 26 8b 45 06 ; 0xf9ae2
+ mov word [es:di+010h], dx ; 26 89 55 10 ; 0xf9ae6
+ mov word [es:di+012h], ax ; 26 89 45 12 ; 0xf9aea
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf9aee vds.c:92
+ mov word [es:di+014h], ax ; 26 89 45 14 ; 0xf9af1
+ mov ax, bx ; 89 d8 ; 0xf9af5
+ mov word [es:di+016h], bx ; 26 89 5d 16 ; 0xf9af7
+ xor ax, bx ; 31 d8 ; 0xf9afb vds.c:93
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9afd vds.c:96
+ pop di ; 5f ; 0xf9b00
+ pop si ; 5e ; 0xf9b01
+ pop bp ; 5d ; 0xf9b02
+ retn 00004h ; c2 04 00 ; 0xf9b03
+ ; disGetNextSymbol 0xf9b06 LB 0x3c2 -> off=0x0 cb=000000000000002e uValue=00000000000f8506 'vds_free_sg_list'
+vds_free_sg_list: ; 0xf9b06 LB 0x2e
+ push bp ; 55 ; 0xf9b06 vds.c:102
+ mov bp, sp ; 89 e5 ; 0xf9b07
+ push bx ; 53 ; 0xf9b09
+ push di ; 57 ; 0xf9b0a
+ mov bx, ax ; 89 c3 ; 0xf9b0b
+ call 09a54h ; e8 44 ff ; 0xf9b0d vds.c:106
+ test ax, ax ; 85 c0 ; 0xf9b10
+ je short 09b25h ; 74 11 ; 0xf9b12
+ mov di, bx ; 89 df ; 0xf9b14 vds.c:108
+ mov es, dx ; 8e c2 ; 0xf9b16
+ mov ax, 08106h ; b8 06 81 ; 0xf9b18
+ mov dx, strict word 00000h ; ba 00 00 ; 0xf9b1b
+ int 04bh ; cd 4b ; 0xf9b1e
+ jc short 09b24h ; 72 02 ; 0xf9b20
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xf9b22
+ cbw ; 98 ; 0xf9b24
+ mov es, dx ; 8e c2 ; 0xf9b25 vds.c:116
+ mov word [es:bx+00eh], strict word 00000h ; 26 c7 47 0e 00 00 ; 0xf9b27
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9b2d vds.c:118
+ pop di ; 5f ; 0xf9b30
+ pop bx ; 5b ; 0xf9b31
+ pop bp ; 5d ; 0xf9b32
+ retn ; c3 ; 0xf9b33
+ ; disGetNextSymbol 0xf9b34 LB 0x394 -> off=0xc cb=0000000000000020 uValue=00000000000f8540 '__U4M'
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+__U4M: ; 0xf9b40 LB 0x20
+ pushfw ; 9c ; 0xf9b40 __U4M.asm:37
+ push si ; 56 ; 0xf9b41 __U4M.asm:65
+ push di ; 57 ; 0xf9b42 __U4M.asm:66
+ push ax ; 50 ; 0xf9b43 __U4M.asm:79
+ db 08bh, 0fah
+ ; mov di, dx ; 8b fa ; 0xf9b44 __U4M.asm:80
+ mul bx ; f7 e3 ; 0xf9b46 __U4M.asm:83
+ db 08bh, 0f2h
+ ; mov si, dx ; 8b f2 ; 0xf9b48 __U4M.asm:84
+ xchg di, ax ; 97 ; 0xf9b4a __U4M.asm:85
+ mul bx ; f7 e3 ; 0xf9b4b __U4M.asm:88
+ db 003h, 0f0h
+ ; add si, ax ; 03 f0 ; 0xf9b4d __U4M.asm:89
+ pop ax ; 58 ; 0xf9b4f __U4M.asm:92
+ mul cx ; f7 e1 ; 0xf9b50 __U4M.asm:93
+ db 003h, 0f0h
+ ; add si, ax ; 03 f0 ; 0xf9b52 __U4M.asm:94
+ db 08bh, 0d6h
+ ; mov dx, si ; 8b d6 ; 0xf9b54 __U4M.asm:97
+ db 08bh, 0c7h
+ ; mov ax, di ; 8b c7 ; 0xf9b56 __U4M.asm:98
+ pop di ; 5f ; 0xf9b58 __U4M.asm:100
+ pop si ; 5e ; 0xf9b59 __U4M.asm:101
+ popfw ; 9d ; 0xf9b5a __U4M.asm:103
+ retn ; c3 ; 0xf9b5b __U4M.asm:104
+ times 0x4 db 0
+ ; disGetNextSymbol 0xf9b60 LB 0x368 -> off=0x0 cb=0000000000000030 uValue=00000000000f8560 '__U4D'
+__U4D: ; 0xf9b60 LB 0x30
+ pushfw ; 9c ; 0xf9b60 __U4D.asm:44
+ test cx, cx ; 85 c9 ; 0xf9b61 __U4D.asm:77
+ jne short 09b6dh ; 75 08 ; 0xf9b63 __U4D.asm:78
+ div bx ; f7 f3 ; 0xf9b65 __U4D.asm:80
+ db 08bh, 0dah
+ ; mov bx, dx ; 8b da ; 0xf9b67 __U4D.asm:82
+ db 033h, 0d2h
+ ; xor dx, dx ; 33 d2 ; 0xf9b69 __U4D.asm:84
+ popfw ; 9d ; 0xf9b6b __U4D.asm:86
+ retn ; c3 ; 0xf9b6c __U4D.asm:87
+ push DS ; 1e ; 0xf9b6d __U4D.asm:91
+ push ES ; 06 ; 0xf9b6e __U4D.asm:92
+ push bp ; 55 ; 0xf9b6f __U4D.asm:99
+ sub sp, strict byte 00004h ; 83 ec 04 ; 0xf9b70 __U4D.asm:100
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xf9b73 __U4D.asm:101
+ push SS ; 16 ; 0xf9b75 __U4D.asm:104
+ push bp ; 55 ; 0xf9b76 __U4D.asm:105
+ add bp, strict byte 00004h ; 83 c5 04 ; 0xf9b77 __U4D.asm:106
+ push cx ; 51 ; 0xf9b7a __U4D.asm:109
+ push bx ; 53 ; 0xf9b7b __U4D.asm:110
+ push dx ; 52 ; 0xf9b7c __U4D.asm:113
+ push ax ; 50 ; 0xf9b7d __U4D.asm:114
+ call 09c45h ; e8 c4 00 ; 0xf9b7e __U4D.asm:116
+ mov cx, word [bp-002h] ; 8b 4e fe ; 0xf9b81 __U4D.asm:119
+ mov bx, word [bp-004h] ; 8b 5e fc ; 0xf9b84 __U4D.asm:120
+ db 08bh, 0e5h
+ ; mov sp, bp ; 8b e5 ; 0xf9b87 __U4D.asm:124
+ pop bp ; 5d ; 0xf9b89 __U4D.asm:125
+ pop ES ; 07 ; 0xf9b8a __U4D.asm:126
+ pop DS ; 1f ; 0xf9b8b __U4D.asm:127
+ popfw ; 9d ; 0xf9b8c __U4D.asm:129
+ retn ; c3 ; 0xf9b8d __U4D.asm:130
+ times 0x2 db 0
+ ; disGetNextSymbol 0xf9b90 LB 0x338 -> off=0x0 cb=0000000000000010 uValue=00000000000f8590 '__U8RS'
+__U8RS: ; 0xf9b90 LB 0x10
+ test si, si ; 85 f6 ; 0xf9b90 __U8RS.asm:40
+ je short 09b9fh ; 74 0b ; 0xf9b92 __U8RS.asm:41
+ shr ax, 1 ; d1 e8 ; 0xf9b94 __U8RS.asm:43
+ rcr bx, 1 ; d1 db ; 0xf9b96 __U8RS.asm:44
+ rcr cx, 1 ; d1 d9 ; 0xf9b98 __U8RS.asm:45
+ rcr dx, 1 ; d1 da ; 0xf9b9a __U8RS.asm:46
+ dec si ; 4e ; 0xf9b9c __U8RS.asm:47
+ jne short 09b94h ; 75 f5 ; 0xf9b9d __U8RS.asm:48
+ retn ; c3 ; 0xf9b9f __U8RS.asm:50
+ ; disGetNextSymbol 0xf9ba0 LB 0x328 -> off=0x0 cb=0000000000000010 uValue=00000000000f85a0 '__U8LS'
+__U8LS: ; 0xf9ba0 LB 0x10
+ test si, si ; 85 f6 ; 0xf9ba0 __U8LS.asm:40
+ je short 09bafh ; 74 0b ; 0xf9ba2 __U8LS.asm:41
+ sal dx, 1 ; d1 e2 ; 0xf9ba4 __U8LS.asm:43
+ rcl cx, 1 ; d1 d1 ; 0xf9ba6 __U8LS.asm:44
+ rcl bx, 1 ; d1 d3 ; 0xf9ba8 __U8LS.asm:45
+ rcl ax, 1 ; d1 d0 ; 0xf9baa __U8LS.asm:46
+ dec si ; 4e ; 0xf9bac __U8LS.asm:47
+ jne short 09ba4h ; 75 f5 ; 0xf9bad __U8LS.asm:48
+ retn ; c3 ; 0xf9baf __U8LS.asm:50
+ ; disGetNextSymbol 0xf9bb0 LB 0x318 -> off=0x0 cb=0000000000000010 uValue=00000000000f85b0 '_fmemset_'
+_fmemset_: ; 0xf9bb0 LB 0x10
+ push di ; 57 ; 0xf9bb0 fmemset.asm:42
+ mov es, dx ; 8e c2 ; 0xf9bb1 fmemset.asm:44
+ db 08bh, 0f8h
+ ; mov di, ax ; 8b f8 ; 0xf9bb3 fmemset.asm:45
+ xchg al, bl ; 86 d8 ; 0xf9bb5 fmemset.asm:46
+ rep stosb ; f3 aa ; 0xf9bb7 fmemset.asm:47
+ xchg al, bl ; 86 d8 ; 0xf9bb9 fmemset.asm:48
+ pop di ; 5f ; 0xf9bbb fmemset.asm:50
+ retn ; c3 ; 0xf9bbc fmemset.asm:51
+ times 0x3 db 0
+ ; disGetNextSymbol 0xf9bc0 LB 0x308 -> off=0x0 cb=000000000000003a uValue=00000000000f85c0 '_fmemcpy_'
+_fmemcpy_: ; 0xf9bc0 LB 0x3a
+ push bp ; 55 ; 0xf9bc0 fmemcpy.asm:42
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xf9bc1 fmemcpy.asm:43
+ push di ; 57 ; 0xf9bc3 fmemcpy.asm:44
+ push DS ; 1e ; 0xf9bc4 fmemcpy.asm:45
+ push si ; 56 ; 0xf9bc5 fmemcpy.asm:46
+ mov es, dx ; 8e c2 ; 0xf9bc6 fmemcpy.asm:48
+ db 08bh, 0f8h
+ ; mov di, ax ; 8b f8 ; 0xf9bc8 fmemcpy.asm:49
+ mov ds, cx ; 8e d9 ; 0xf9bca fmemcpy.asm:50
+ db 08bh, 0f3h
+ ; mov si, bx ; 8b f3 ; 0xf9bcc fmemcpy.asm:51
+ mov cx, word [bp+004h] ; 8b 4e 04 ; 0xf9bce fmemcpy.asm:52
+ rep movsb ; f3 a4 ; 0xf9bd1 fmemcpy.asm:53
+ pop si ; 5e ; 0xf9bd3 fmemcpy.asm:55
+ pop DS ; 1f ; 0xf9bd4 fmemcpy.asm:56
+ pop di ; 5f ; 0xf9bd5 fmemcpy.asm:57
+ db 08bh, 0e5h
+ ; mov sp, bp ; 8b e5 ; 0xf9bd6 fmemcpy.asm:58
+ pop bp ; 5d ; 0xf9bd8 fmemcpy.asm:59
+ retn ; c3 ; 0xf9bd9 fmemcpy.asm:60
+ add byte [bx+si], al ; 00 00 ; 0xf9bda
+ add byte [bx+si], al ; 00 00 ; 0xf9bdc
+ add byte [bx+si], al ; 00 00 ; 0xf9bde
+ adc byte [si-063eeh], bl ; 10 9c 12 9c ; 0xf9be0
+ push SS ; 16 ; 0xf9be4
+ pushfw ; 9c ; 0xf9be5
+ push SS ; 16 ; 0xf9be6
+ pushfw ; 9c ; 0xf9be7
+ push SS ; 16 ; 0xf9be8
+ pushfw ; 9c ; 0xf9be9
+ sbb byte [si-063e8h], bl ; 18 9c 18 9c ; 0xf9bea
+ sbb bl, byte [si-063e2h] ; 1a 9c 1e 9c ; 0xf9bee
+ push DS ; 1e ; 0xf9bf2
+ pushfw ; 9c ; 0xf9bf3
+ and byte [si-063dbh], bl ; 20 9c 25 9c ; 0xf9bf4
+ daa ; 27 ; 0xf9bf8
+ pushfw ; 9c ; 0xf9bf9
+ ; disGetNextSymbol 0xf9bfa LB 0x2ce -> off=0x0 cb=000000000000003a uValue=00000000000085fa 'apm_worker'
+apm_worker: ; 0xf9bfa LB 0x3a
+ sti ; fb ; 0xf9bfa apm_pm.asm:56
+ push ax ; 50 ; 0xf9bfb apm_pm.asm:58
+ db 032h, 0e4h
+ ; xor ah, ah ; 32 e4 ; 0xf9bfc apm_pm.asm:59
+ sub AL, strict byte 004h ; 2c 04 ; 0xf9bfe apm_pm.asm:60
+ db 08bh, 0e8h
+ ; mov bp, ax ; 8b e8 ; 0xf9c00 apm_pm.asm:61
+ sal bp, 1 ; d1 e5 ; 0xf9c02 apm_pm.asm:62
+ cmp AL, strict byte 00dh ; 3c 0d ; 0xf9c04 apm_pm.asm:63
+ pop ax ; 58 ; 0xf9c06 apm_pm.asm:64
+ mov AH, strict byte 053h ; b4 53 ; 0xf9c07 apm_pm.asm:65
+ jnc short 09c30h ; 73 25 ; 0xf9c09 apm_pm.asm:66
+ jmp word [cs:bp-06420h] ; 2e ff a6 e0 9b ; 0xf9c0b apm_pm.asm:68
+ jmp short 09c2eh ; eb 1c ; 0xf9c10 apm_pm.asm:71
+ sti ; fb ; 0xf9c12 apm_pm.asm:74
+ hlt ; f4 ; 0xf9c13 apm_pm.asm:75
+ jmp short 09c2eh ; eb 18 ; 0xf9c14 apm_pm.asm:76
+ jmp short 09c2eh ; eb 16 ; 0xf9c16 apm_pm.asm:85
+ jmp short 09c30h ; eb 16 ; 0xf9c18 apm_pm.asm:91
+ mov AH, strict byte 080h ; b4 80 ; 0xf9c1a apm_pm.asm:94
+ jmp short 09c32h ; eb 14 ; 0xf9c1c apm_pm.asm:95
+ jmp short 09c30h ; eb 10 ; 0xf9c1e apm_pm.asm:100
+ mov ax, 00102h ; b8 02 01 ; 0xf9c20 apm_pm.asm:103
+ jmp short 09c2eh ; eb 09 ; 0xf9c23 apm_pm.asm:104
+ jmp short 09c2eh ; eb 07 ; 0xf9c25 apm_pm.asm:108
+ mov BL, strict byte 000h ; b3 00 ; 0xf9c27 apm_pm.asm:111
+ mov cx, strict word 00000h ; b9 00 00 ; 0xf9c29 apm_pm.asm:112
+ jmp short 09c2eh ; eb 00 ; 0xf9c2c apm_pm.asm:113
+ clc ; f8 ; 0xf9c2e apm_pm.asm:116
+ retn ; c3 ; 0xf9c2f apm_pm.asm:117
+ mov AH, strict byte 009h ; b4 09 ; 0xf9c30 apm_pm.asm:120
+ stc ; f9 ; 0xf9c32 apm_pm.asm:123
+ retn ; c3 ; 0xf9c33 apm_pm.asm:124
+ ; disGetNextSymbol 0xf9c34 LB 0x294 -> off=0x0 cb=0000000000000011 uValue=00000000000f8634 'apm_pm16_entry'
+apm_pm16_entry: ; 0xf9c34 LB 0x11
+ mov AH, strict byte 002h ; b4 02 ; 0xf9c34 apm_pm.asm:136
+ push DS ; 1e ; 0xf9c36 apm_pm.asm:142
+ push bp ; 55 ; 0xf9c37 apm_pm.asm:143
+ push CS ; 0e ; 0xf9c38 apm_pm.asm:145
+ pop bp ; 5d ; 0xf9c39 apm_pm.asm:146
+ add bp, strict byte 00008h ; 83 c5 08 ; 0xf9c3a apm_pm.asm:147
+ mov ds, bp ; 8e dd ; 0xf9c3d apm_pm.asm:148
+ call 09bfah ; e8 b8 ff ; 0xf9c3f apm_pm.asm:150
+ pop bp ; 5d ; 0xf9c42 apm_pm.asm:152
+ pop DS ; 1f ; 0xf9c43 apm_pm.asm:153
+ retf ; cb ; 0xf9c44 apm_pm.asm:155
+ ; disGetNextSymbol 0xf9c45 LB 0x283 -> off=0x0 cb=0000000000000265 uValue=00000000000f8645 'DoUInt32Div'
+DoUInt32Div: ; 0xf9c45 LB 0x265
+ push bp ; 55 ; 0xf9c45 DoUInt32Div.c:28
+ mov bp, sp ; 89 e5 ; 0xf9c46
+ push si ; 56 ; 0xf9c48
+ push di ; 57 ; 0xf9c49
+ sub sp, strict byte 00018h ; 83 ec 18 ; 0xf9c4a
+ lds bx, [bp+00ch] ; c5 5e 0c ; 0xf9c4d
+ lea si, [bp+004h] ; 8d 76 04 ; 0xf9c50 DoUInt32Div.c:972
+ mov word [bp-010h], si ; 89 76 f0 ; 0xf9c53
+ mov [bp-00eh], ss ; 8c 56 f2 ; 0xf9c56
+ lea di, [bp+008h] ; 8d 7e 08 ; 0xf9c59
+ mov [bp-008h], ss ; 8c 56 f8 ; 0xf9c5c
+ lea si, [bp-01ch] ; 8d 76 e4 ; 0xf9c5f
+ mov word [bp-00ch], si ; 89 76 f4 ; 0xf9c62
+ mov [bp-00ah], ss ; 8c 56 f6 ; 0xf9c65
+ mov si, bx ; 89 de ; 0xf9c68
+ mov [bp-006h], ds ; 8c 5e fa ; 0xf9c6a
+ cmp word [bx+002h], strict byte 00000h ; 83 7f 02 00 ; 0xf9c6d DoUInt32Div.c:980
+ jne short 09c95h ; 75 22 ; 0xf9c71
+ mov ax, word [bx] ; 8b 07 ; 0xf9c73 DoUInt32Div.c:982
+ test ax, ax ; 85 c0 ; 0xf9c75
+ je short 09c92h ; 74 19 ; 0xf9c77
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf9c79 DoUInt32Div.c:985
+ jne short 09c95h ; 75 17 ; 0xf9c7c
+ xor ax, ax ; 31 c0 ; 0xf9c7e DoUInt32Div.c:67
+ mov word [bp+00ah], ax ; 89 46 0a ; 0xf9c80
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf9c83 DoUInt32Div.c:68
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf9c86 DoUInt32Div.c:988
+ mov word [bp+004h], ax ; 89 46 04 ; 0xf9c89
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf9c8c
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf9c8f
+ jmp near 09e9dh ; e9 08 02 ; 0xf9c92
+ lds bx, [bp-00ch] ; c5 5e f4 ; 0xf9c95 DoUInt32Div.c:726
+ mov ax, word [bx+002h] ; 8b 47 02 ; 0xf9c98
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9c9b
+ cmp ax, word [si+002h] ; 3b 44 02 ; 0xf9c9e
+ je short 09cbbh ; 74 18 ; 0xf9ca1
+ mov ds, [bp-00ah] ; 8e 5e f6 ; 0xf9ca3 DoUInt32Div.c:727
+ mov ax, word [bx+002h] ; 8b 47 02 ; 0xf9ca6
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9ca9
+ cmp ax, word [si+002h] ; 3b 44 02 ; 0xf9cac
+ jbe short 09cb6h ; 76 05 ; 0xf9caf
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf9cb1
+ jmp short 09cdch ; eb 26 ; 0xf9cb4
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf9cb6
+ jmp short 09cdch ; eb 21 ; 0xf9cb9
+ mov ds, [bp-00ah] ; 8e 5e f6 ; 0xf9cbb DoUInt32Div.c:728
+ mov ax, word [bx] ; 8b 07 ; 0xf9cbe
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9cc0
+ cmp ax, word [si] ; 3b 04 ; 0xf9cc3
+ je short 09cdah ; 74 13 ; 0xf9cc5
+ mov ds, [bp-00ah] ; 8e 5e f6 ; 0xf9cc7 DoUInt32Div.c:729
+ mov ax, word [bx] ; 8b 07 ; 0xf9cca
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9ccc
+ cmp ax, word [si] ; 3b 04 ; 0xf9ccf
+ jbe short 09cd5h ; 76 02 ; 0xf9cd1
+ jmp short 09cb1h ; eb dc ; 0xf9cd3
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf9cd5
+ jmp short 09cdch ; eb 02 ; 0xf9cd8
+ xor ax, ax ; 31 c0 ; 0xf9cda DoUInt32Div.c:730
+ test ax, ax ; 85 c0 ; 0xf9cdc DoUInt32Div.c:996
+ jnl short 09cfeh ; 7d 1e ; 0xf9cde
+ lds bx, [bp-00ch] ; c5 5e f4 ; 0xf9ce0 DoUInt32Div.c:998
+ mov ax, word [bx] ; 8b 07 ; 0xf9ce3
+ mov dx, word [bx+002h] ; 8b 57 02 ; 0xf9ce5
+ mov ds, [bp-008h] ; 8e 5e f8 ; 0xf9ce8
+ mov word [di], ax ; 89 05 ; 0xf9ceb
+ mov word [di+002h], dx ; 89 55 02 ; 0xf9ced
+ lds bx, [bp-010h] ; c5 5e f0 ; 0xf9cf0 DoUInt32Div.c:67
+ mov word [bx+002h], strict word 00000h ; c7 47 02 00 00 ; 0xf9cf3
+ mov word [bx], strict word 00000h ; c7 07 00 00 ; 0xf9cf8 DoUInt32Div.c:68
+ jmp short 09c92h ; eb 94 ; 0xf9cfc DoUInt32Div.c:1003
+ jne short 09d15h ; 75 15 ; 0xf9cfe
+ mov ds, [bp-008h] ; 8e 5e f8 ; 0xf9d00 DoUInt32Div.c:67
+ mov word [di+002h], ax ; 89 45 02 ; 0xf9d03
+ mov word [di], ax ; 89 05 ; 0xf9d06 DoUInt32Div.c:68
+ lds bx, [bp-010h] ; c5 5e f0 ; 0xf9d08 DoUInt32Div.c:397
+ mov word [bx], strict word 00001h ; c7 07 01 00 ; 0xf9d0b
+ mov word [bx+002h], ax ; 89 47 02 ; 0xf9d0f DoUInt32Div.c:398
+ jmp near 09e9dh ; e9 88 01 ; 0xf9d12 DoUInt32Div.c:1008
+ lds bx, [bp-00ch] ; c5 5e f4 ; 0xf9d15 DoUInt32Div.c:954
+ mov ax, word [bx+002h] ; 8b 47 02 ; 0xf9d18
+ test ax, ax ; 85 c0 ; 0xf9d1b
+ je short 09d30h ; 74 11 ; 0xf9d1d
+ push ax ; 50 ; 0xf9d1f DoUInt32Div.c:955
+ mov ax, 0f000h ; b8 00 f0 ; 0xf9d20
+ mov ds, ax ; 8e d8 ; 0xf9d23
+ call 09eb0h ; e8 88 01 ; 0xf9d25
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xf9d28
+ add ax, strict word 00010h ; 05 10 00 ; 0xf9d2b
+ jmp short 09d3dh ; eb 0d ; 0xf9d2e DoUInt32Div.c:956
+ push word [bx] ; ff 37 ; 0xf9d30 DoUInt32Div.c:957
+ mov ax, 0f000h ; b8 00 f0 ; 0xf9d32
+ mov ds, ax ; 8e d8 ; 0xf9d35
+ call 09eb0h ; e8 76 01 ; 0xf9d37
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xf9d3a
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf9d3d DoUInt32Div.c:959
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9d40 DoUInt32Div.c:954
+ mov ax, word [si+002h] ; 8b 44 02 ; 0xf9d43
+ test ax, ax ; 85 c0 ; 0xf9d46
+ je short 09d5bh ; 74 11 ; 0xf9d48
+ push ax ; 50 ; 0xf9d4a DoUInt32Div.c:955
+ mov ax, 0f000h ; b8 00 f0 ; 0xf9d4b
+ mov ds, ax ; 8e d8 ; 0xf9d4e
+ call 09eb0h ; e8 5d 01 ; 0xf9d50
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xf9d53
+ add ax, strict word 00010h ; 05 10 00 ; 0xf9d56
+ jmp short 09d68h ; eb 0d ; 0xf9d59 DoUInt32Div.c:956
+ push word [si] ; ff 34 ; 0xf9d5b DoUInt32Div.c:957
+ mov ax, 0f000h ; b8 00 f0 ; 0xf9d5d
+ mov ds, ax ; 8e d8 ; 0xf9d60
+ call 09eb0h ; e8 4b 01 ; 0xf9d62
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xf9d65
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf9d68 DoUInt32Div.c:959
+ sub dx, ax ; 29 c2 ; 0xf9d6b
+ mov word [bp-012h], dx ; 89 56 ee ; 0xf9d6d
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9d70 DoUInt32Div.c:1014
+ mov ax, word [si] ; 8b 04 ; 0xf9d73
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf9d75
+ mov ax, word [si+002h] ; 8b 44 02 ; 0xf9d78
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf9d7b
+ test dx, dx ; 85 d2 ; 0xf9d7e DoUInt32Div.c:1015
+ je short 09dd8h ; 74 56 ; 0xf9d80
+ mov cx, dx ; 89 d1 ; 0xf9d82 DoUInt32Div.c:280
+ xor ch, dh ; 30 f5 ; 0xf9d84
+ and cl, 01fh ; 80 e1 1f ; 0xf9d86
+ mov ax, word [si] ; 8b 04 ; 0xf9d89 DoUInt32Div.c:282
+ mov dx, word [si+002h] ; 8b 54 02 ; 0xf9d8b
+ jcxz 09d96h ; e3 06 ; 0xf9d8e
+ sal ax, 1 ; d1 e0 ; 0xf9d90
+ rcl dx, 1 ; d1 d2 ; 0xf9d92
+ loop 09d90h ; e2 fa ; 0xf9d94
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf9d96
+ mov word [bp-016h], dx ; 89 56 ea ; 0xf9d99
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf9d9c DoUInt32Div.c:763
+ lds bx, [bp-00ch] ; c5 5e f4 ; 0xf9d9f
+ cmp ax, word [bx+002h] ; 3b 47 02 ; 0xf9da2
+ jnbe short 09db6h ; 77 0f ; 0xf9da5
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf9da7
+ cmp ax, word [bx+002h] ; 3b 47 02 ; 0xf9daa
+ jne short 09dbah ; 75 0b ; 0xf9dad
+ mov ax, word [bp-018h] ; 8b 46 e8 ; 0xf9daf
+ cmp ax, word [bx] ; 3b 07 ; 0xf9db2
+ jbe short 09dbah ; 76 04 ; 0xf9db4
+ mov AL, strict byte 001h ; b0 01 ; 0xf9db6
+ jmp short 09dbch ; eb 02 ; 0xf9db8
+ xor al, al ; 30 c0 ; 0xf9dba
+ test al, al ; 84 c0 ; 0xf9dbc DoUInt32Div.c:769
+ je short 09de3h ; 74 23 ; 0xf9dbe
+ shr word [bp-016h], 1 ; d1 6e ea ; 0xf9dc0 DoUInt32Div.c:680
+ rcr word [bp-018h], 1 ; d1 5e e8 ; 0xf9dc3
+ dec word [bp-012h] ; ff 4e ee ; 0xf9dc6
+ jmp short 09de3h ; eb 18 ; 0xf9dc9
+ mov cx, strict word 0001fh ; b9 1f 00 ; 0xf9dcb DoUInt32Div.c:632
+ sal word [bp-018h], 1 ; d1 66 e8 ; 0xf9dce
+ rcl word [bp-016h], 1 ; d1 56 ea ; 0xf9dd1
+ loop 09dceh ; e2 f8 ; 0xf9dd4
+ jmp short 09dc6h ; eb ee ; 0xf9dd6 DoUInt32Div.c:647
+ mov ax, word [si] ; 8b 04 ; 0xf9dd8 DoUInt32Div.c:1025
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf9dda
+ mov ax, word [si+002h] ; 8b 44 02 ; 0xf9ddd
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf9de0
+ lds bx, [bp-010h] ; c5 5e f0 ; 0xf9de3 DoUInt32Div.c:67
+ mov word [bx+002h], strict word 00000h ; c7 47 02 00 00 ; 0xf9de6
+ mov word [bx], strict word 00000h ; c7 07 00 00 ; 0xf9deb DoUInt32Div.c:68
+ lds bx, [bp-00ch] ; c5 5e f4 ; 0xf9def DoUInt32Div.c:1028
+ mov dx, word [bx] ; 8b 17 ; 0xf9df2
+ mov ax, word [bx+002h] ; 8b 47 02 ; 0xf9df4
+ mov ds, [bp-008h] ; 8e 5e f8 ; 0xf9df7
+ mov word [di], dx ; 89 15 ; 0xf9dfa
+ mov word [di+002h], ax ; 89 45 02 ; 0xf9dfc
+ mov dx, word [di] ; 8b 15 ; 0xf9dff DoUInt32Div.c:782
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9e01
+ cmp ax, word [si+002h] ; 3b 44 02 ; 0xf9e04
+ jnbe short 09e0fh ; 77 06 ; 0xf9e07
+ jne short 09e13h ; 75 08 ; 0xf9e09
+ cmp dx, word [si] ; 3b 14 ; 0xf9e0b
+ jc short 09e13h ; 72 04 ; 0xf9e0d
+ mov AL, strict byte 001h ; b0 01 ; 0xf9e0f
+ jmp short 09e15h ; eb 02 ; 0xf9e11
+ xor al, al ; 30 c0 ; 0xf9e13
+ test al, al ; 84 c0 ; 0xf9e15 DoUInt32Div.c:788
+ je short 09e7ah ; 74 61 ; 0xf9e17
+ mov ds, [bp-008h] ; 8e 5e f8 ; 0xf9e19 DoUInt32Div.c:782
+ mov ax, word [di+002h] ; 8b 45 02 ; 0xf9e1c
+ cmp ax, word [bp-016h] ; 3b 46 ea ; 0xf9e1f
+ jnbe short 09e30h ; 77 0c ; 0xf9e22
+ cmp ax, word [bp-016h] ; 3b 46 ea ; 0xf9e24
+ jne short 09e34h ; 75 0b ; 0xf9e27
+ mov ax, word [di] ; 8b 05 ; 0xf9e29
+ cmp ax, word [bp-018h] ; 3b 46 e8 ; 0xf9e2b
+ jc short 09e34h ; 72 04 ; 0xf9e2e
+ mov AL, strict byte 001h ; b0 01 ; 0xf9e30
+ jmp short 09e36h ; eb 02 ; 0xf9e32
+ xor al, al ; 30 c0 ; 0xf9e34
+ test al, al ; 84 c0 ; 0xf9e36 DoUInt32Div.c:788
+ je short 09e60h ; 74 26 ; 0xf9e38
+ mov ax, word [bp-018h] ; 8b 46 e8 ; 0xf9e3a DoUInt32Div.c:451
+ mov ds, [bp-008h] ; 8e 5e f8 ; 0xf9e3d
+ sub word [di], ax ; 29 05 ; 0xf9e40
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf9e42
+ sbb word [di+002h], ax ; 19 45 02 ; 0xf9e45
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf9e48 DoUInt32Div.c:586
+ xor dx, dx ; 31 d2 ; 0xf9e4b
+ mov cx, word [bp-012h] ; 8b 4e ee ; 0xf9e4d
+ jcxz 09e58h ; e3 06 ; 0xf9e50
+ sal ax, 1 ; d1 e0 ; 0xf9e52
+ rcl dx, 1 ; d1 d2 ; 0xf9e54
+ loop 09e52h ; e2 fa ; 0xf9e56
+ lds bx, [bp-010h] ; c5 5e f0 ; 0xf9e58
+ or word [bx], ax ; 09 07 ; 0xf9e5b
+ or word [bx+002h], dx ; 09 57 02 ; 0xf9e5d
+ mov ds, [bp-008h] ; 8e 5e f8 ; 0xf9e60 DoUInt32Div.c:744
+ mov dx, word [di] ; 8b 15 ; 0xf9e63
+ mov ax, word [di+002h] ; 8b 45 02 ; 0xf9e65
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9e68
+ cmp ax, word [si+002h] ; 3b 44 02 ; 0xf9e6b
+ jc short 09e76h ; 72 06 ; 0xf9e6e
+ jne short 09e7ch ; 75 0a ; 0xf9e70
+ cmp dx, word [si] ; 3b 14 ; 0xf9e72
+ jnc short 09e7ch ; 73 06 ; 0xf9e74
+ mov AL, strict byte 001h ; b0 01 ; 0xf9e76
+ jmp short 09e7eh ; eb 04 ; 0xf9e78
+ jmp short 09e9dh ; eb 21 ; 0xf9e7a
+ xor al, al ; 30 c0 ; 0xf9e7c
+ test al, al ; 84 c0 ; 0xf9e7e DoUInt32Div.c:750
+ je short 09e91h ; 74 0f ; 0xf9e80
+ jmp short 09e9dh ; eb 19 ; 0xf9e82 DoUInt32Div.c:1043
+ mov cx, strict word 0001fh ; b9 1f 00 ; 0xf9e84 DoUInt32Div.c:680
+ sal word [bp-018h], 1 ; d1 66 e8 ; 0xf9e87
+ rcl word [bp-016h], 1 ; d1 56 ea ; 0xf9e8a
+ loop 09e87h ; e2 f8 ; 0xf9e8d
+ jmp short 09e97h ; eb 06 ; 0xf9e8f DoUInt32Div.c:647
+ shr word [bp-016h], 1 ; d1 6e ea ; 0xf9e91 DoUInt32Div.c:653
+ rcr word [bp-018h], 1 ; d1 5e e8 ; 0xf9e94
+ dec word [bp-012h] ; ff 4e ee ; 0xf9e97 DoUInt32Div.c:1045
+ jmp near 09e19h ; e9 7c ff ; 0xf9e9a DoUInt32Div.c:1046
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf9e9d DoUInt32Div.c:32
+ mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xf9ea0
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9ea3 DoUInt32Div.c:33
+ pop di ; 5f ; 0xf9ea6
+ pop si ; 5e ; 0xf9ea7
+ pop bp ; 5d ; 0xf9ea8
+ retn ; c3 ; 0xf9ea9
+ ; disGetNextSymbol 0xf9eaa LB 0x1e -> off=0x6 cb=0000000000000018 uValue=00000000000f88b0 '_ASMBitLastSetU16'
+ db 000h, 000h, 000h, 000h, 000h, 000h
+_ASMBitLastSetU16: ; 0xf9eb0 LB 0x18
+ push bp ; 55 ; 0xf9eb0 ASMBitLastSetU16.asm:43
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xf9eb1 ASMBitLastSetU16.asm:44
+ mov cx, word [bp+004h] ; 8b 4e 04 ; 0xf9eb3 ASMBitLastSetU16.asm:46
+ test cx, cx ; 85 c9 ; 0xf9eb6 ASMBitLastSetU16.asm:47
+ je short 09ec4h ; 74 0a ; 0xf9eb8 ASMBitLastSetU16.asm:48
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf9eba ASMBitLastSetU16.asm:50
+ sal cx, 1 ; d1 e1 ; 0xf9ebd ASMBitLastSetU16.asm:52
+ jc short 09ec6h ; 72 05 ; 0xf9ebf ASMBitLastSetU16.asm:53
+ dec ax ; 48 ; 0xf9ec1 ASMBitLastSetU16.asm:54
+ jmp short 09ebdh ; eb f9 ; 0xf9ec2 ASMBitLastSetU16.asm:55
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf9ec4 ASMBitLastSetU16.asm:58
+ pop bp ; 5d ; 0xf9ec6 ASMBitLastSetU16.asm:60
+ retn ; c3 ; 0xf9ec7 ASMBitLastSetU16.asm:61
+
+ ; Padding 0x3b38 bytes at 0xf9ec8
+ times 15160 db 0
+
+section BIOS32 progbits vstart=0xda00 align=1 ; size=0x39d class=CODE group=AUTO
+ ; disGetNextSymbol 0xfda00 LB 0x39d -> off=0x0 cb=0000000000000026 uValue=00000000000f0000 'bios32_service'
+bios32_service: ; 0xfda00 LB 0x26
+ pushfw ; 9c ; 0xfda00 pcibio32.asm:52
+ cmp bl, 000h ; 80 fb 00 ; 0xfda01 pcibio32.asm:54
+ jne short 0da22h ; 75 1c ; 0xfda04 pcibio32.asm:55
+ cmp ax, 05024h ; 3d 24 50 ; 0xfda06 pcibio32.asm:57
+ inc bx ; 43 ; 0xfda09
+ dec cx ; 49 ; 0xfda0a
+ mov AL, strict byte 080h ; b0 80 ; 0xfda0b pcibio32.asm:58
+ jne short 0da20h ; 75 11 ; 0xfda0d pcibio32.asm:59
+ mov bx, strict word 00000h ; bb 00 00 ; 0xfda0f pcibio32.asm:61
+ db 00fh
+ add byte [bx+di-01000h], bh ; 00 b9 00 f0 ; 0xfda13
+ add byte [bx+si], al ; 00 00 ; 0xfda17
+ mov dx, 0da26h ; ba 26 da ; 0xfda19 pcibio32.asm:63
+ add byte [bx+si], al ; 00 00 ; 0xfda1c
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xfda1e pcibio32.asm:64
+ popfw ; 9d ; 0xfda20 pcibio32.asm:66
+ retf ; cb ; 0xfda21 pcibio32.asm:67
+ mov AL, strict byte 081h ; b0 81 ; 0xfda22 pcibio32.asm:70
+ jmp short 0da20h ; eb fa ; 0xfda24 pcibio32.asm:71
+ ; disGetNextSymbol 0xfda26 LB 0x377 -> off=0x0 cb=000000000000000d uValue=00000000000f0026 'pcibios32_entry'
+pcibios32_entry: ; 0xfda26 LB 0xd
+ pushfw ; 9c ; 0xfda26 pcibio32.asm:80
+ cld ; fc ; 0xfda27 pcibio32.asm:81
+ push ES ; 06 ; 0xfda28 pcibio32.asm:83
+ pushaw ; 60 ; 0xfda29 pcibio32.asm:84
+ call 0db4ah ; e8 1d 01 ; 0xfda2a pcibio32.asm:85
+ add byte [bx+si], al ; 00 00 ; 0xfda2d
+ popaw ; 61 ; 0xfda2f pcibio32.asm:86
+ pop ES ; 07 ; 0xfda30 pcibio32.asm:87
+ popfw ; 9d ; 0xfda31 pcibio32.asm:89
+ retf ; cb ; 0xfda32 pcibio32.asm:90
+ ; disGetNextSymbol 0xfda33 LB 0x36a -> off=0x0 cb=0000000000000022 uValue=00000000000f0033 'pci32_select_reg_'
+pci32_select_reg_: ; 0xfda33 LB 0x22
+ push bp ; 55 ; 0xfda33 pci32.c:188
+ mov bp, sp ; 89 e5 ; 0xfda34
+ push bx ; 53 ; 0xfda36
+ and dl, 0fch ; 80 e2 fc ; 0xfda37 pci32.c:190
+ mov bx, dx ; 89 d3 ; 0xfda3a
+ mov dx, 00cf8h ; ba f8 0c ; 0xfda3c
+ add byte [bx+si], al ; 00 00 ; 0xfda3f
+ db 00fh, 0b7h, 0c0h
+ ; movzx ax, ax ; 0f b7 c0 ; 0xfda41
+ sal ax, 008h ; c1 e0 08 ; 0xfda44
+ or ax, strict word 00000h ; 0d 00 00 ; 0xfda47
+ add byte [bx+si-03c76h], al ; 00 80 8a c3 ; 0xfda4a
+ out DX, ax ; ef ; 0xfda4e
+ lea sp, [di-004h] ; 8d 65 fc ; 0xfda4f pci32.c:191
+ pop bx ; 5b ; 0xfda52
+ pop bp ; 5d ; 0xfda53
+ retn ; c3 ; 0xfda54
+ ; disGetNextSymbol 0xfda55 LB 0x348 -> off=0x0 cb=00000000000000f7 uValue=00000000000f0055 'pci32_find_device_'
+pci32_find_device_: ; 0xfda55 LB 0xf7
+ push bp ; 55 ; 0xfda55 pci32.c:221
+ mov bp, sp ; 89 e5 ; 0xfda56
+ push cx ; 51 ; 0xfda58
+ push si ; 56 ; 0xfda59
+ push di ; 57 ; 0xfda5a
+ sub sp, strict byte 00014h ; 83 ec 14 ; 0xfda5b
+ push ax ; 50 ; 0xfda5e
+ mov cx, dx ; 89 d1 ; 0xfda5f
+ mov si, bx ; 89 de ; 0xfda61
+ test bx, bx ; 85 db ; 0xfda63 pci32.c:231
+ xor bx, bx ; 31 db ; 0xfda65 pci32.c:238
+ mov byte [di-010h], 000h ; c6 45 f0 00 ; 0xfda67 pci32.c:239
+ test bl, 007h ; f6 c3 07 ; 0xfda6b pci32.c:249
+ jne short 0daa6h ; 75 36 ; 0xfda6e
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfda70 pci32.c:250
+ mov dx, strict word 0000eh ; ba 0e 00 ; 0xfda73
+ add byte [bx+si], al ; 00 00 ; 0xfda76
+ call 0da31h ; e8 b6 ff ; 0xfda78
+ db 0ffh
+ db 0ffh
+ mov dx, 00cfeh ; ba fe 0c ; 0xfda7d pci32.c:251
+ add byte [bx+si], al ; 00 00 ; 0xfda80
+ db 02bh, 0c0h
+ ; sub ax, ax ; 2b c0 ; 0xfda82
+ in AL, DX ; ec ; 0xfda84
+ mov byte [di-014h], al ; 88 45 ec ; 0xfda85
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xfda88 pci32.c:252
+ jne short 0da94h ; 75 08 ; 0xfda8a
+ add bx, strict byte 00008h ; 83 c3 08 ; 0xfda8c pci32.c:253
+ jmp near 0db1ch ; e9 8a 00 ; 0xfda8f pci32.c:254
+ add byte [bx+si], al ; 00 00 ; 0xfda92
+ test byte [di-014h], 080h ; f6 45 ec 80 ; 0xfda94 pci32.c:256
+ je short 0daa1h ; 74 07 ; 0xfda98
+ mov di, strict word 00001h ; bf 01 00 ; 0xfda9a pci32.c:257
+ add byte [bx+si], al ; 00 00 ; 0xfda9d
+ jmp short 0daa6h ; eb 05 ; 0xfda9f pci32.c:258
+ mov di, strict word 00008h ; bf 08 00 ; 0xfdaa1 pci32.c:259
+ add byte [bx+si], al ; 00 00 ; 0xfdaa4
+ mov al, byte [di-014h] ; 8a 45 ec ; 0xfdaa6 pci32.c:270
+ and AL, strict byte 007h ; 24 07 ; 0xfdaa9
+ cmp AL, strict byte 001h ; 3c 01 ; 0xfdaab
+ jne short 0dad5h ; 75 26 ; 0xfdaad
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfdaaf
+ mov dx, ax ; 89 c2 ; 0xfdab2
+ sar dx, 008h ; c1 fa 08 ; 0xfdab4
+ test dx, dx ; 85 d2 ; 0xfdab7
+ jne short 0dad5h ; 75 1a ; 0xfdab9
+ mov dx, strict word 0001ah ; ba 1a 00 ; 0xfdabb pci32.c:272
+ add byte [bx+si], al ; 00 00 ; 0xfdabe
+ call 0da31h ; e8 6e ff ; 0xfdac0
+ db 0ffh
+ db 0ffh
+ mov dx, 00cfeh ; ba fe 0c ; 0xfdac5 pci32.c:273
+ add byte [bx+si], al ; 00 00 ; 0xfdac8
+ db 02bh, 0c0h
+ ; sub ax, ax ; 2b c0 ; 0xfdaca
+ in AL, DX ; ec ; 0xfdacc
+ cmp al, byte [di-010h] ; 3a 45 f0 ; 0xfdacd pci32.c:274
+ jbe short 0dad5h ; 76 03 ; 0xfdad0
+ mov byte [di-010h], al ; 88 45 f0 ; 0xfdad2 pci32.c:275
+ test si, si ; 85 f6 ; 0xfdad5 pci32.c:279
+ je short 0dae0h ; 74 07 ; 0xfdad7
+ mov ax, strict word 00008h ; b8 08 00 ; 0xfdad9
+ add byte [bx+si], al ; 00 00 ; 0xfdadc
+ jmp short 0dae2h ; eb 02 ; 0xfdade
+ xor ax, ax ; 31 c0 ; 0xfdae0
+ db 00fh, 0b7h, 0d0h
+ ; movzx dx, ax ; 0f b7 d0 ; 0xfdae2
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfdae5
+ call 0da31h ; e8 46 ff ; 0xfdae8
+ db 0ffh
+ db 0ffh
+ mov dx, 00cfch ; ba fc 0c ; 0xfdaed pci32.c:280
+ add byte [bx+si], al ; 00 00 ; 0xfdaf0
+ in ax, DX ; ed ; 0xfdaf2
+ mov word [di-018h], ax ; 89 45 e8 ; 0xfdaf3
+ mov word [di-020h], strict word 00000h ; c7 45 e0 00 00 ; 0xfdaf6 pci32.c:281
+ add byte [bx+si], al ; 00 00 ; 0xfdafb
+ test si, si ; 85 f6 ; 0xfdafd pci32.c:284
+ je short 0db07h ; 74 06 ; 0xfdaff
+ shr ax, 008h ; c1 e8 08 ; 0xfdb01 pci32.c:285
+ mov word [di-018h], ax ; 89 45 e8 ; 0xfdb04
+ mov ax, word [di-018h] ; 8b 45 e8 ; 0xfdb07 pci32.c:292
+ cmp ax, word [di-024h] ; 3b 45 dc ; 0xfdb0a
+ je short 0db15h ; 74 06 ; 0xfdb0d
+ cmp word [di-020h], strict byte 00000h ; 83 7d e0 00 ; 0xfdb0f pci32.c:293
+ je short 0db1ch ; 74 07 ; 0xfdb13
+ dec cx ; 49 ; 0xfdb15
+ cmp ecx, strict byte 0ffffffffh ; 66 83 f9 ff ; 0xfdb16
+ je short 0db34h ; 74 18 ; 0xfdb1a
+ add bx, di ; 01 fb ; 0xfdb1c pci32.c:301
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfdb1e pci32.c:302
+ sar ax, 008h ; c1 f8 08 ; 0xfdb21
+ mov word [di-01ch], ax ; 89 45 e4 ; 0xfdb24
+ movzx ax, byte [di-010h] ; 0f b6 45 f0 ; 0xfdb27
+ cmp ax, word [di-01ch] ; 3b 45 e4 ; 0xfdb2b
+ jnl near 0da69h ; 0f 8d 37 ff ; 0xfdb2e
+ db 0ffh
+ jmp word [bp-07dh] ; ff 66 83 ; 0xfdb33
+ stc ; f9 ; 0xfdb36
+ push word [di+005h] ; ff 75 05 ; 0xfdb37
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfdb3a
+ jmp short 0db44h ; eb 05 ; 0xfdb3d
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xfdb3f
+ add byte [bx+si], al ; 00 00 ; 0xfdb42
+ lea sp, [di-00ch] ; 8d 65 f4 ; 0xfdb44 pci32.c:309
+ pop di ; 5f ; 0xfdb47
+ pop si ; 5e ; 0xfdb48
+ pop cx ; 59 ; 0xfdb49
+ pop bp ; 5d ; 0xfdb4a
+ retn ; c3 ; 0xfdb4b
+ ; disGetNextSymbol 0xfdb4c LB 0x251 -> off=0x0 cb=0000000000000251 uValue=00000000000f014c '_pci32_function'
+_pci32_function: ; 0xfdb4c LB 0x251
+ push bp ; 55 ; 0xfdb4c pci32.c:311
+ mov bp, sp ; 89 e5 ; 0xfdb4d
+ push bx ; 53 ; 0xfdb4f
+ push si ; 56 ; 0xfdb50
+ push di ; 57 ; 0xfdb51
+ push ax ; 50 ; 0xfdb52
+ push ax ; 50 ; 0xfdb53
+ and dword [di+024h], strict dword 0658100ffh ; 66 81 65 24 ff 00 81 65 ; 0xfdb54 pci32.c:318
+ sub AL, strict byte 0feh ; 2c fe ; 0xfdb5c
+ inc word [bx+si] ; ff 00 ; 0xfdb5e
+ add byte [bp+di+02445h], cl ; 00 8b 45 24 ; 0xfdb60
+ xor ah, ah ; 30 e4 ; 0xfdb64
+ cmp eax, strict dword 029720003h ; 66 3d 03 00 72 29 ; 0xfdb66
+ jbe near 0dc09h ; 0f 86 99 00 ; 0xfdb6c
+ add byte [bx+si], al ; 00 00 ; 0xfdb70
+ cmp eax, strict dword 0840f000eh ; 66 3d 0e 00 0f 84 ; 0xfdb72
+ test ax, strict word 00001h ; a9 01 00 ; 0xfdb78
+ add byte [bp+03dh], ah ; 00 66 3d ; 0xfdb7b
+ or byte [bx+si], al ; 08 00 ; 0xfdb7e
+ jc near 0dd83h ; 0f 82 ff 01 ; 0xfdb80
+ add byte [bx+si], al ; 00 00 ; 0xfdb84
+ cmp eax, strict dword 0860f000dh ; 66 3d 0d 00 0f 86 ; 0xfdb86
+ test AL, strict byte 000h ; a8 00 ; 0xfdb8c
+ add byte [bx+si], al ; 00 00 ; 0xfdb8e
+ jmp near 0dd83h ; e9 f0 01 ; 0xfdb90
+ add byte [bx+si], al ; 00 00 ; 0xfdb93
+ cmp eax, strict dword 028740002h ; 66 3d 02 00 74 28 ; 0xfdb95
+ cmp eax, strict dword 0850f0001h ; 66 3d 01 00 0f 85 ; 0xfdb9b
+ loopne 0dba4h ; e0 01 ; 0xfdba1
+ add byte [bx+si], al ; 00 00 ; 0xfdba3
+ mov dword [di+024h], strict dword 0c7660001h ; 66 c7 45 24 01 00 66 c7 ; 0xfdba5 pci32.c:323
+ inc bp ; 45 ; 0xfdbad
+ sbb byte [bx+si], dl ; 18 10 ; 0xfdbae
+ add dh, byte [bx+di] ; 02 31 ; 0xfdbb0
+ sal byte [bp-077h], 045h ; c0 66 89 45 ; 0xfdbb2
+ and bh, al ; 20 c7 ; 0xfdbb6
+ inc bp ; 45 ; 0xfdbb8
+ sbb AL, strict byte 050h ; 1c 50 ; 0xfdbb9
+ inc bx ; 43 ; 0xfdbbb
+ dec cx ; 49 ; 0xfdbbc
+ and cl, ch ; 20 e9 ; 0xfdbbd
+ rol byte [bx+di], CL ; d2 01 ; 0xfdbbf
+ add byte [bx+si], al ; 00 00 ; 0xfdbc1
+ cmp dword [di+01ch], strict byte 0ffffffffh ; 66 83 7d 1c ff ; 0xfdbc3 pci32.c:333
+ jne short 0dbd7h ; 75 0d ; 0xfdbc8
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdbca pci32.c:334
+ xor ah, ah ; 30 e4 ; 0xfdbcd
+ or ah, 083h ; 80 cc 83 ; 0xfdbcf
+ jmp near 0dd8bh ; e9 b6 01 ; 0xfdbd2 pci32.c:335
+ add byte [bx+si], al ; 00 00 ; 0xfdbd5
+ xor bx, bx ; 31 db ; 0xfdbd7 pci32.c:337
+ db 00fh, 0b7h, 055h, 00ch
+ ; movzx dx, [di+00ch] ; 0f b7 55 0c ; 0xfdbd9
+ db 00fh, 0b7h, 045h, 020h
+ ; movzx ax, [di+020h] ; 0f b7 45 20 ; 0xfdbdd
+ sal ax, 010h ; c1 e0 10 ; 0xfdbe1
+ db 00fh, 0b7h, 04dh, 01ch
+ ; movzx cx, [di+01ch] ; 0f b7 4d 1c ; 0xfdbe4
+ or ax, cx ; 09 c8 ; 0xfdbe8
+ call 0da53h ; e8 66 fe ; 0xfdbea
+ db 0ffh
+ jmp word [bp+03dh] ; ff 66 3d ; 0xfdbee
+ db 0ffh
+ push word [di+00dh] ; ff 75 0d ; 0xfdbf2
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdbf5 pci32.c:339
+ xor ah, ah ; 30 e4 ; 0xfdbf8
+ or ah, 086h ; 80 cc 86 ; 0xfdbfa
+ jmp near 0dd8bh ; e9 8b 01 ; 0xfdbfd
+ add byte [bx+si], al ; 00 00 ; 0xfdc00
+ mov dword [di+018h], eax ; 66 89 45 18 ; 0xfdc02 pci32.c:340
+ jmp near 0dd93h ; e9 8a 01 ; 0xfdc06 pci32.c:345
+ add byte [bx+si], al ; 00 00 ; 0xfdc09
+ db 00fh, 0b7h, 055h, 00ch
+ ; movzx dx, [di+00ch] ; 0f b7 55 0c ; 0xfdc0b pci32.c:347
+ mov ax, word [di+020h] ; 8b 45 20 ; 0xfdc0f
+ mov bx, strict word 00001h ; bb 01 00 ; 0xfdc12
+ add byte [bx+si], al ; 00 00 ; 0xfdc15
+ call 0da53h ; e8 39 fe ; 0xfdc17
+ db 0ffh
+ jmp word [bp+03dh] ; ff 66 3d ; 0xfdc1b
+ db 0ffh
+ push word [di+00dh] ; ff 75 0d ; 0xfdc1f
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdc22 pci32.c:349
+ xor ah, ah ; 30 e4 ; 0xfdc25
+ or ah, 086h ; 80 cc 86 ; 0xfdc27
+ jmp near 0dd8bh ; e9 5e 01 ; 0xfdc2a pci32.c:350
+ add byte [bx+si], al ; 00 00 ; 0xfdc2d
+ mov dword [di+018h], eax ; 66 89 45 18 ; 0xfdc2f pci32.c:352
+ jmp near 0dd93h ; e9 5d 01 ; 0xfdc33 pci32.c:354
+ add byte [bx+si], al ; 00 00 ; 0xfdc36
+ cmp dword [di+008h], strict dword 00d720100h ; 66 81 7d 08 00 01 72 0d ; 0xfdc38 pci32.c:361
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdc40 pci32.c:362
+ xor ah, ah ; 30 e4 ; 0xfdc43
+ or ah, 087h ; 80 cc 87 ; 0xfdc45
+ jmp near 0dd8bh ; e9 40 01 ; 0xfdc48 pci32.c:363
+ add byte [bx+si], al ; 00 00 ; 0xfdc4b
+ db 00fh, 0b7h, 055h, 008h
+ ; movzx dx, [di+008h] ; 0f b7 55 08 ; 0xfdc4d pci32.c:365
+ db 00fh, 0b7h, 045h, 018h
+ ; movzx ax, [di+018h] ; 0f b7 45 18 ; 0xfdc51
+ call 0da31h ; e8 d9 fd ; 0xfdc55
+ db 0ffh
+ dec word [bp+di+02445h] ; ff 8b 45 24 ; 0xfdc59
+ xor ah, ah ; 30 e4 ; 0xfdc5d
+ cmp eax, strict dword 02172000ah ; 66 3d 0a 00 72 21 ; 0xfdc5f
+ jbe short 0dcd6h ; 76 6f ; 0xfdc65
+ cmp eax, strict dword 0840f000dh ; 66 3d 0d 00 0f 84 ; 0xfdc67
+ test ax, strict word 00000h ; a9 00 00 ; 0xfdc6d
+ add byte [bp+03dh], ah ; 00 66 3d ; 0xfdc70
+ or AL, strict byte 000h ; 0c 00 ; 0xfdc73
+ je near 0dcfch ; 0f 84 83 00 ; 0xfdc75
+ add byte [bx+si], al ; 00 00 ; 0xfdc79
+ cmp eax, strict dword 06374000bh ; 66 3d 0b 00 74 63 ; 0xfdc7b
+ jmp near 0dd93h ; e9 0f 01 ; 0xfdc81
+ add byte [bx+si], al ; 00 00 ; 0xfdc84
+ cmp eax, strict dword 02d740009h ; 66 3d 09 00 74 2d ; 0xfdc86
+ cmp eax, strict dword 0850f0008h ; 66 3d 08 00 0f 85 ; 0xfdc8c
+ inc word [bx+si] ; ff 00 ; 0xfdc92
+ add byte [bx+si], al ; 00 00 ; 0xfdc94
+ mov bx, word [di+020h] ; 8b 5d 20 ; 0xfdc96 pci32.c:368
+ xor bl, bl ; 30 db ; 0xfdc99
+ mov ax, word [di+008h] ; 8b 45 08 ; 0xfdc9b
+ xor ah, ah ; 30 e4 ; 0xfdc9e
+ and AL, strict byte 003h ; 24 03 ; 0xfdca0
+ db 00fh, 0b7h, 0d0h
+ ; movzx dx, ax ; 0f b7 d0 ; 0xfdca2
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xfdca5
+ add byte [bx+si], al ; 00 00 ; 0xfdca9
+ db 02bh, 0c0h
+ ; sub ax, ax ; 2b c0 ; 0xfdcab
+ in AL, DX ; ec ; 0xfdcad
+ or bx, ax ; 09 c3 ; 0xfdcae
+ mov dword [di+020h], ebx ; 66 89 5d 20 ; 0xfdcb0
+ jmp near 0dd93h ; e9 dc 00 ; 0xfdcb4 pci32.c:369
+ add byte [bx+si], al ; 00 00 ; 0xfdcb7
+ mov ax, word [di+008h] ; 8b 45 08 ; 0xfdcb9 pci32.c:371
+ xor ah, ah ; 30 e4 ; 0xfdcbc
+ and AL, strict byte 002h ; 24 02 ; 0xfdcbe
+ db 00fh, 0b7h, 0d0h
+ ; movzx dx, ax ; 0f b7 d0 ; 0xfdcc0
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xfdcc3
+ add byte [bx+si], al ; 00 00 ; 0xfdcc7
+ db 02bh, 0c0h
+ ; sub ax, ax ; 2b c0 ; 0xfdcc9
+ in eax, DX ; 66 ed ; 0xfdccb
+ mov dword [di+020h], eax ; 66 89 45 20 ; 0xfdccd
+ jmp near 0dd93h ; e9 bf 00 ; 0xfdcd1 pci32.c:372
+ add byte [bx+si], al ; 00 00 ; 0xfdcd4
+ mov dx, 00cfch ; ba fc 0c ; 0xfdcd6 pci32.c:374
+ add byte [bx+si], al ; 00 00 ; 0xfdcd9
+ in ax, DX ; ed ; 0xfdcdb
+ mov word [di+020h], ax ; 89 45 20 ; 0xfdcdc
+ jmp near 0dd93h ; e9 b1 00 ; 0xfdcdf pci32.c:375
+ add byte [bx+si], al ; 00 00 ; 0xfdce2
+ mov ax, word [di+020h] ; 8b 45 20 ; 0xfdce4 pci32.c:377
+ mov dx, word [di+008h] ; 8b 55 08 ; 0xfdce7
+ xor dh, dh ; 30 f6 ; 0xfdcea
+ and dl, 003h ; 80 e2 03 ; 0xfdcec
+ db 00fh, 0b7h, 0d2h
+ ; movzx dx, dx ; 0f b7 d2 ; 0xfdcef
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xfdcf2
+ add byte [bx+si], al ; 00 00 ; 0xfdcf6
+ out DX, AL ; ee ; 0xfdcf8
+ jmp near 0dd93h ; e9 97 00 ; 0xfdcf9 pci32.c:378
+ add byte [bx+si], al ; 00 00 ; 0xfdcfc
+ db 00fh, 0b7h, 045h, 020h
+ ; movzx ax, [di+020h] ; 0f b7 45 20 ; 0xfdcfe pci32.c:380
+ mov dx, word [di+008h] ; 8b 55 08 ; 0xfdd02
+ xor dh, dh ; 30 f6 ; 0xfdd05
+ and dl, 002h ; 80 e2 02 ; 0xfdd07
+ db 00fh, 0b7h, 0d2h
+ ; movzx dx, dx ; 0f b7 d2 ; 0xfdd0a
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xfdd0d
+ add byte [bx+si], al ; 00 00 ; 0xfdd11
+ out DX, eax ; 66 ef ; 0xfdd13
+ jmp near 0dd93h ; e9 7b 00 ; 0xfdd15 pci32.c:381
+ add byte [bx+si], al ; 00 00 ; 0xfdd18
+ mov ax, word [di+020h] ; 8b 45 20 ; 0xfdd1a pci32.c:383
+ mov dx, 00cfch ; ba fc 0c ; 0xfdd1d
+ add byte [bx+si], al ; 00 00 ; 0xfdd20
+ out DX, ax ; ef ; 0xfdd22
+ jmp short 0dd95h ; eb 70 ; 0xfdd23 pci32.c:387
+ db 00fh, 0b7h, 045h, 008h
+ ; movzx ax, [di+008h] ; 0f b7 45 08 ; 0xfdd25 pci32.c:389
+ mov es, [di+028h] ; 8e 45 28 ; 0xfdd29
+ mov [di-010h], es ; 8c 45 f0 ; 0xfdd2c
+ mov bx, ax ; 89 c3 ; 0xfdd2f
+ mov edx, dword [di] ; 66 8b 15 ; 0xfdd31 pci32.c:393
+ xor bl, 000h ; 80 f3 00 ; 0xfdd34
+ add byte [bp+026h], ah ; 00 66 26 ; 0xfdd37
+ cmp dx, word [bx+si] ; 3b 10 ; 0xfdd3a
+ jbe short 0dd50h ; 76 12 ; 0xfdd3c
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdd3e pci32.c:394
+ xor ah, ah ; 30 e4 ; 0xfdd41
+ or ah, 089h ; 80 cc 89 ; 0xfdd43
+ mov dword [di+024h], eax ; 66 89 45 24 ; 0xfdd46
+ or word [di+02ch], strict byte 00001h ; 83 4d 2c 01 ; 0xfdd4a pci32.c:395
+ jmp short 0dd76h ; eb 26 ; 0xfdd4e pci32.c:396
+ db 00fh, 0b7h, 0cah
+ ; movzx cx, dx ; 0f b7 ca ; 0xfdd50 pci32.c:397
+ db 066h, 026h, 08bh, 050h, 006h
+ ; mov edx, dword [es:bx+si+006h] ; 66 26 8b 50 06 ; 0xfdd53
+ mov word [di-014h], dx ; 89 55 ec ; 0xfdd58
+ mov di, word [es:bx+si+002h] ; 26 8b 78 02 ; 0xfdd5b
+ mov dx, ds ; 8c da ; 0xfdd5f
+ mov si, 0f1a0h ; be a0 f1 ; 0xfdd61
+ add byte [bx+si], al ; 00 00 ; 0xfdd64
+ mov es, [di-014h] ; 8e 45 ec ; 0xfdd66
+ push DS ; 1e ; 0xfdd69
+ db 066h, 08eh, 0dah
+ ; mov ds, edx ; 66 8e da ; 0xfdd6a
+ rep movsb ; f3 a4 ; 0xfdd6d
+ pop DS ; 1f ; 0xfdd6f
+ mov dword [di+018h], strict dword 0a1660a00h ; 66 c7 45 18 00 0a 66 a1 ; 0xfdd70 pci32.c:399
+ xor bl, 000h ; 80 f3 00 ; 0xfdd78
+ add byte [bp-00fbbh], cl ; 00 8e 45 f0 ; 0xfdd7b
+ db 066h, 026h, 089h, 003h
+ ; mov dword [es:bp+di], eax ; 66 26 89 03 ; 0xfdd7f
+ jmp short 0dd95h ; eb 10 ; 0xfdd83 pci32.c:402
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdd85 pci32.c:405
+ xor ah, ah ; 30 e4 ; 0xfdd88
+ or ah, 081h ; 80 cc 81 ; 0xfdd8a
+ mov dword [di+024h], eax ; 66 89 45 24 ; 0xfdd8d
+ or word [di+02ch], strict byte 00001h ; 83 4d 2c 01 ; 0xfdd91 pci32.c:406
+ lea sp, [di-00ch] ; 8d 65 f4 ; 0xfdd95 pci32.c:408
+ pop di ; 5f ; 0xfdd98
+ pop si ; 5e ; 0xfdd99
+ pop bx ; 5b ; 0xfdd9a
+ pop bp ; 5d ; 0xfdd9b
+ retn ; c3 ; 0xfdd9c
+
+ ; Padding 0x3 bytes at 0xfdd9d
+ times 3 db 0
+
+section BIOS32CONST progbits vstart=0xdda0 align=1 ; size=0x0 class=FAR_DATA group=BIOS32_GROUP
+
+section BIOS32CONST2 progbits vstart=0xdda0 align=1 ; size=0x0 class=FAR_DATA group=BIOS32_GROUP
+
+section BIOS32_DATA progbits vstart=0xdda0 align=1 ; size=0x0 class=FAR_DATA group=BIOS32_GROUP
+
+ ; Padding 0x260 bytes at 0xfdda0
+ times 608 db 0
+
+section BIOSSEG progbits vstart=0xe000 align=1 ; size=0x2000 class=CODE group=AUTO
+ ; disGetNextSymbol 0xfe000 LB 0x2000 -> off=0x0 cb=0000000000000030 uValue=00000000000f0000 'biosorg_check_before_or_at_0E02Eh'
+biosorg_check_before_or_at_0E02Eh: ; 0xfe000 LB 0x30
+ times 0x2e db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe030 LB 0x1fd0 -> off=0x0 cb=0000000000000004 uValue=00000000000f0030 'eoi_both_pics'
+eoi_both_pics: ; 0xfe030 LB 0x4
+ mov AL, strict byte 020h ; b0 20 ; 0xfe030 orgs.asm:238
+ out strict byte 0a0h, AL ; e6 a0 ; 0xfe032 orgs.asm:239
+ ; disGetNextSymbol 0xfe034 LB 0x1fcc -> off=0x0 cb=0000000000000005 uValue=00000000000f0034 'eoi_master_pic'
+eoi_master_pic: ; 0xfe034 LB 0x5
+ mov AL, strict byte 020h ; b0 20 ; 0xfe034 orgs.asm:241
+ out strict byte 020h, AL ; e6 20 ; 0xfe036 orgs.asm:242
+ retn ; c3 ; 0xfe038 orgs.asm:243
+ ; disGetNextSymbol 0xfe039 LB 0x1fc7 -> off=0x0 cb=000000000000000b uValue=0000000000000039 'set_int_vects'
+set_int_vects: ; 0xfe039 LB 0xb
+ mov word [bx], ax ; 89 07 ; 0xfe039 orgs.asm:250
+ mov word [bx+002h], dx ; 89 57 02 ; 0xfe03b orgs.asm:251
+ add bx, strict byte 00004h ; 83 c3 04 ; 0xfe03e orgs.asm:252
+ loop 0e039h ; e2 f6 ; 0xfe041 orgs.asm:253
+ retn ; c3 ; 0xfe043 orgs.asm:254
+ ; disGetNextSymbol 0xfe044 LB 0x1fbc -> off=0x0 cb=0000000000000006 uValue=00000000000f0044 'eoi_jmp_post'
+eoi_jmp_post: ; 0xfe044 LB 0x6
+ in AL, strict byte 060h ; e4 60 ; 0xfe044 orgs.asm:262
+ mov AL, strict byte 020h ; b0 20 ; 0xfe046 orgs.asm:263
+ out strict byte 020h, AL ; e6 20 ; 0xfe048 orgs.asm:264
+ ; disGetNextSymbol 0xfe04a LB 0x1fb6 -> off=0x0 cb=0000000000000009 uValue=00000000000f004a 'no_eoi_jmp_post'
+no_eoi_jmp_post: ; 0xfe04a LB 0x9
+ mov ax, strict word 00040h ; b8 40 00 ; 0xfe04a orgs.asm:267
+ mov ds, ax ; 8e d8 ; 0xfe04d orgs.asm:268
+ jmp far [word 00067h] ; ff 2e 67 00 ; 0xfe04f orgs.asm:269
+ ; disGetNextSymbol 0xfe053 LB 0x1fad -> off=0x0 cb=0000000000000002 uValue=00000000000f0053 'seg_40_value'
+seg_40_value: ; 0xfe053 LB 0x2
+ inc ax ; 40 ; 0xfe053
+ times 0x1 db 0
+ ; disGetNextSymbol 0xfe055 LB 0x1fab -> off=0x0 cb=0000000000000006 uValue=00000000000f0055 'biosorg_check_before_or_at_0E059h'
+biosorg_check_before_or_at_0E059h: ; 0xfe055 LB 0x6
+ add byte [bx+si], al ; 00 00 ; 0xfe055
+ add byte [bx+si], al ; 00 00 ; 0xfe057
+ pop ax ; 58 ; 0xfe059
+ dec bp ; 4d ; 0xfe05a
+ ; disGetNextSymbol 0xfe05b LB 0x1fa5 -> off=0x0 cb=000000000000006e uValue=00000000000f005b 'post'
+post: ; 0xfe05b LB 0x6e
+ cli ; fa ; 0xfe05b orgs.asm:278
+ smsw ax ; 0f 01 e0 ; 0xfe05c orgs.asm:284
+ test ax, strict word 00001h ; a9 01 00 ; 0xfe05f orgs.asm:285
+ je short 0e06ah ; 74 06 ; 0xfe062 orgs.asm:286
+ mov AL, strict byte 001h ; b0 01 ; 0xfe064 orgs.asm:295
+ out strict byte 092h, AL ; e6 92 ; 0xfe066 orgs.asm:296
+ jmp short 0e068h ; eb fe ; 0xfe068 orgs.asm:297
+ mov AL, strict byte 00fh ; b0 0f ; 0xfe06a orgs.asm:302
+ out strict byte 070h, AL ; e6 70 ; 0xfe06c orgs.asm:303
+ in AL, strict byte 071h ; e4 71 ; 0xfe06e orgs.asm:304
+ xchg ah, al ; 86 c4 ; 0xfe070 orgs.asm:307
+ in AL, strict byte 064h ; e4 64 ; 0xfe072 orgs.asm:311
+ test AL, strict byte 004h ; a8 04 ; 0xfe074 orgs.asm:312
+ je short 0e08bh ; 74 13 ; 0xfe076 orgs.asm:313
+ db 08ah, 0c4h
+ ; mov al, ah ; 8a c4 ; 0xfe078 orgs.asm:316
+ db 00ah, 0c0h
+ ; or al, al ; 0a c0 ; 0xfe07a orgs.asm:317
+ jne short 0e08bh ; 75 0d ; 0xfe07c orgs.asm:318
+ mov ds, [cs:0e053h] ; 2e 8e 1e 53 e0 ; 0xfe07e orgs.asm:324
+ cmp word [word 00072h], 01234h ; 81 3e 72 00 34 12 ; 0xfe083 orgs.asm:325
+ jne short 0e064h ; 75 d9 ; 0xfe089 orgs.asm:326
+ mov AL, strict byte 00fh ; b0 0f ; 0xfe08b orgs.asm:330
+ out strict byte 070h, AL ; e6 70 ; 0xfe08d orgs.asm:331
+ mov AL, strict byte 000h ; b0 00 ; 0xfe08f orgs.asm:332
+ out strict byte 071h, AL ; e6 71 ; 0xfe091 orgs.asm:333
+ db 08ah, 0c4h
+ ; mov al, ah ; 8a c4 ; 0xfe093 orgs.asm:337
+ cmp AL, strict byte 009h ; 3c 09 ; 0xfe095 orgs.asm:338
+ je short 0e0abh ; 74 12 ; 0xfe097 orgs.asm:339
+ cmp AL, strict byte 00ah ; 3c 0a ; 0xfe099 orgs.asm:340
+ je short 0e0abh ; 74 0e ; 0xfe09b orgs.asm:341
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xfe09d orgs.asm:343
+ out strict byte 00dh, AL ; e6 0d ; 0xfe09f orgs.asm:346
+ out strict byte 0dah, AL ; e6 da ; 0xfe0a1 orgs.asm:347
+ mov AL, strict byte 0c0h ; b0 c0 ; 0xfe0a3 orgs.asm:350
+ out strict byte 0d6h, AL ; e6 d6 ; 0xfe0a5 orgs.asm:351
+ mov AL, strict byte 000h ; b0 00 ; 0xfe0a7 orgs.asm:352
+ out strict byte 0d4h, AL ; e6 d4 ; 0xfe0a9 orgs.asm:353
+ db 08ah, 0c4h
+ ; mov al, ah ; 8a c4 ; 0xfe0ab orgs.asm:357
+ cmp AL, strict byte 000h ; 3c 00 ; 0xfe0ad orgs.asm:358
+ je short 0e0c9h ; 74 18 ; 0xfe0af orgs.asm:359
+ cmp AL, strict byte 00dh ; 3c 0d ; 0xfe0b1 orgs.asm:361
+ jnc short 0e0c9h ; 73 14 ; 0xfe0b3 orgs.asm:362
+ cmp AL, strict byte 009h ; 3c 09 ; 0xfe0b5 orgs.asm:363
+ jne short 0e0bch ; 75 03 ; 0xfe0b7 orgs.asm:364
+ jmp near 0e350h ; e9 94 02 ; 0xfe0b9 orgs.asm:365
+ mov sp, 00400h ; bc 00 04 ; 0xfe0bc orgs.asm:368
+ cmp AL, strict byte 005h ; 3c 05 ; 0xfe0bf orgs.asm:370
+ je short 0e044h ; 74 81 ; 0xfe0c1 orgs.asm:371
+ cmp AL, strict byte 00ah ; 3c 0a ; 0xfe0c3 orgs.asm:373
+ je short 0e04ah ; 74 83 ; 0xfe0c5 orgs.asm:374
+ jmp short 0e0c9h ; eb 00 ; 0xfe0c7 orgs.asm:378
+ ; disGetNextSymbol 0xfe0c9 LB 0x1f37 -> off=0x0 cb=00000000000001ed uValue=00000000000f00c9 'normal_post'
+normal_post: ; 0xfe0c9 LB 0x1ed
+ mov ax, 07800h ; b8 00 78 ; 0xfe0c9 orgs.asm:387
+ db 08bh, 0e0h
+ ; mov sp, ax ; 8b e0 ; 0xfe0cc orgs.asm:388
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe0ce orgs.asm:389
+ mov ds, ax ; 8e d8 ; 0xfe0d0 orgs.asm:390
+ mov ss, ax ; 8e d0 ; 0xfe0d2 orgs.asm:391
+ mov es, ax ; 8e c0 ; 0xfe0d4 orgs.asm:395
+ db 033h, 0ffh
+ ; xor di, di ; 33 ff ; 0xfe0d6 orgs.asm:396
+ cld ; fc ; 0xfe0d8 orgs.asm:397
+ mov cx, 00239h ; b9 39 02 ; 0xfe0d9 orgs.asm:398
+ rep stosw ; f3 ab ; 0xfe0dc orgs.asm:399
+ inc di ; 47 ; 0xfe0de orgs.asm:400
+ inc di ; 47 ; 0xfe0df orgs.asm:401
+ mov cx, 005c6h ; b9 c6 05 ; 0xfe0e0 orgs.asm:402
+ rep stosw ; f3 ab ; 0xfe0e3 orgs.asm:403
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe0e5 orgs.asm:407
+ add bx, 01000h ; 81 c3 00 10 ; 0xfe0e7 orgs.asm:409
+ cmp bx, 09000h ; 81 fb 00 90 ; 0xfe0eb orgs.asm:410
+ jnc short 0e0fch ; 73 0b ; 0xfe0ef orgs.asm:411
+ mov es, bx ; 8e c3 ; 0xfe0f1 orgs.asm:412
+ db 033h, 0ffh
+ ; xor di, di ; 33 ff ; 0xfe0f3 orgs.asm:413
+ mov cx, 08000h ; b9 00 80 ; 0xfe0f5 orgs.asm:414
+ rep stosw ; f3 ab ; 0xfe0f8 orgs.asm:415
+ jmp short 0e0e7h ; eb eb ; 0xfe0fa orgs.asm:416
+ mov es, bx ; 8e c3 ; 0xfe0fc orgs.asm:418
+ db 033h, 0ffh
+ ; xor di, di ; 33 ff ; 0xfe0fe orgs.asm:419
+ mov cx, 07ff8h ; b9 f8 7f ; 0xfe100 orgs.asm:420
+ rep stosw ; f3 ab ; 0xfe103 orgs.asm:421
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe105 orgs.asm:422
+ push CS ; 0e ; 0xfe107 orgs.asm:104
+ pop DS ; 1f ; 0xfe108 orgs.asm:105
+ cld ; fc ; 0xfe109 orgs.asm:106
+ call 0170dh ; e8 00 36 ; 0xfe10a orgs.asm:426
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe10d orgs.asm:433
+ mov ds, bx ; 8e db ; 0xfe10f orgs.asm:434
+ mov cx, strict word 00060h ; b9 60 00 ; 0xfe111 orgs.asm:435
+ mov ax, 0ff53h ; b8 53 ff ; 0xfe114 orgs.asm:436
+ mov dx, 0f000h ; ba 00 f0 ; 0xfe117 orgs.asm:437
+ call 0e039h ; e8 1c ff ; 0xfe11a orgs.asm:438
+ mov bx, 001a0h ; bb a0 01 ; 0xfe11d orgs.asm:443
+ mov cx, strict word 00010h ; b9 10 00 ; 0xfe120 orgs.asm:444
+ call 0e039h ; e8 13 ff ; 0xfe123 orgs.asm:445
+ mov ax, 0027fh ; b8 7f 02 ; 0xfe126 orgs.asm:448
+ mov word [00413h], ax ; a3 13 04 ; 0xfe129 orgs.asm:449
+ mov ax, 0e9cch ; b8 cc e9 ; 0xfe12c orgs.asm:95
+ mov word [00018h], ax ; a3 18 00 ; 0xfe12f orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe132 orgs.asm:97
+ mov word [0001ah], ax ; a3 1a 00 ; 0xfe135 orgs.asm:98
+ mov ax, 0f84dh ; b8 4d f8 ; 0xfe138 orgs.asm:95
+ mov word [00044h], ax ; a3 44 00 ; 0xfe13b orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe13e orgs.asm:97
+ mov word [00046h], ax ; a3 46 00 ; 0xfe141 orgs.asm:98
+ mov ax, 0f841h ; b8 41 f8 ; 0xfe144 orgs.asm:95
+ mov word [00048h], ax ; a3 48 00 ; 0xfe147 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe14a orgs.asm:97
+ mov word [0004ah], ax ; a3 4a 00 ; 0xfe14d orgs.asm:98
+ mov ax, 0f859h ; b8 59 f8 ; 0xfe150 orgs.asm:95
+ mov word [00054h], ax ; a3 54 00 ; 0xfe153 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe156 orgs.asm:97
+ mov word [00056h], ax ; a3 56 00 ; 0xfe159 orgs.asm:98
+ mov ax, 0efd4h ; b8 d4 ef ; 0xfe15c orgs.asm:95
+ mov word [0005ch], ax ; a3 5c 00 ; 0xfe15f orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe162 orgs.asm:97
+ mov word [0005eh], ax ; a3 5e 00 ; 0xfe165 orgs.asm:98
+ mov ax, 0f0a4h ; b8 a4 f0 ; 0xfe168 orgs.asm:95
+ mov word [00060h], ax ; a3 60 00 ; 0xfe16b orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe16e orgs.asm:97
+ mov word [00062h], ax ; a3 62 00 ; 0xfe171 orgs.asm:98
+ mov ax, 0e6f2h ; b8 f2 e6 ; 0xfe174 orgs.asm:95
+ mov word [00064h], ax ; a3 64 00 ; 0xfe177 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe17a orgs.asm:97
+ mov word [00066h], ax ; a3 66 00 ; 0xfe17d orgs.asm:98
+ mov ax, 0efedh ; b8 ed ef ; 0xfe180 orgs.asm:95
+ mov word [00070h], ax ; a3 70 00 ; 0xfe183 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe186 orgs.asm:97
+ mov word [00072h], ax ; a3 72 00 ; 0xfe189 orgs.asm:98
+ call 0e778h ; e8 e9 05 ; 0xfe18c orgs.asm:465
+ mov ax, 0fe6eh ; b8 6e fe ; 0xfe18f orgs.asm:95
+ mov word [00068h], ax ; a3 68 00 ; 0xfe192 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe195 orgs.asm:97
+ mov word [0006ah], ax ; a3 6a 00 ; 0xfe198 orgs.asm:98
+ mov ax, 0fea5h ; b8 a5 fe ; 0xfe19b orgs.asm:95
+ mov word [00020h], ax ; a3 20 00 ; 0xfe19e orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe1a1 orgs.asm:97
+ mov word [00022h], ax ; a3 22 00 ; 0xfe1a4 orgs.asm:98
+ mov AL, strict byte 034h ; b0 34 ; 0xfe1a7 orgs.asm:476
+ out strict byte 043h, AL ; e6 43 ; 0xfe1a9 orgs.asm:477
+ mov AL, strict byte 000h ; b0 00 ; 0xfe1ab orgs.asm:478
+ out strict byte 040h, AL ; e6 40 ; 0xfe1ad orgs.asm:479
+ out strict byte 040h, AL ; e6 40 ; 0xfe1af orgs.asm:480
+ mov ax, 0f065h ; b8 65 f0 ; 0xfe1b1 orgs.asm:95
+ mov word [00040h], ax ; a3 40 00 ; 0xfe1b4 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe1b7 orgs.asm:97
+ mov word [00042h], ax ; a3 42 00 ; 0xfe1ba orgs.asm:98
+ mov ax, 0e987h ; b8 87 e9 ; 0xfe1bd orgs.asm:95
+ mov word [00024h], ax ; a3 24 00 ; 0xfe1c0 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe1c3 orgs.asm:97
+ mov word [00026h], ax ; a3 26 00 ; 0xfe1c6 orgs.asm:98
+ mov ax, 0e82eh ; b8 2e e8 ; 0xfe1c9 orgs.asm:95
+ mov word [00058h], ax ; a3 58 00 ; 0xfe1cc orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe1cf orgs.asm:97
+ mov word [0005ah], ax ; a3 5a 00 ; 0xfe1d2 orgs.asm:98
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe1d5 orgs.asm:489
+ mov ds, ax ; 8e d8 ; 0xfe1d7 orgs.asm:490
+ mov byte [00417h], AL ; a2 17 04 ; 0xfe1d9 orgs.asm:492
+ mov byte [00418h], AL ; a2 18 04 ; 0xfe1dc orgs.asm:493
+ mov byte [00419h], AL ; a2 19 04 ; 0xfe1df orgs.asm:494
+ mov byte [00471h], AL ; a2 71 04 ; 0xfe1e2 orgs.asm:495
+ mov byte [00497h], AL ; a2 97 04 ; 0xfe1e5 orgs.asm:496
+ mov AL, strict byte 010h ; b0 10 ; 0xfe1e8 orgs.asm:497
+ mov byte [00496h], AL ; a2 96 04 ; 0xfe1ea orgs.asm:498
+ mov bx, strict word 0001eh ; bb 1e 00 ; 0xfe1ed orgs.asm:500
+ mov word [0041ah], bx ; 89 1e 1a 04 ; 0xfe1f0 orgs.asm:501
+ mov word [0041ch], bx ; 89 1e 1c 04 ; 0xfe1f4 orgs.asm:502
+ mov word [00480h], bx ; 89 1e 80 04 ; 0xfe1f8 orgs.asm:503
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xfe1fc orgs.asm:504
+ mov word [00482h], bx ; 89 1e 82 04 ; 0xfe1ff orgs.asm:505
+ mov AL, strict byte 014h ; b0 14 ; 0xfe203 orgs.asm:508
+ out strict byte 070h, AL ; e6 70 ; 0xfe205 orgs.asm:509
+ in AL, strict byte 071h ; e4 71 ; 0xfe207 orgs.asm:510
+ mov byte [00410h], AL ; a2 10 04 ; 0xfe209 orgs.asm:511
+ push DS ; 1e ; 0xfe20c orgs.asm:513
+ push CS ; 0e ; 0xfe20d orgs.asm:104
+ pop DS ; 1f ; 0xfe20e orgs.asm:105
+ cld ; fc ; 0xfe20f orgs.asm:106
+ mov ax, 0c000h ; b8 00 c0 ; 0xfe210 orgs.asm:518
+ mov dx, 0c800h ; ba 00 c8 ; 0xfe213 orgs.asm:519
+ call 01600h ; e8 e7 33 ; 0xfe216 orgs.asm:520
+ call 04e7dh ; e8 61 6c ; 0xfe219 orgs.asm:523
+ pop DS ; 1f ; 0xfe21c orgs.asm:524
+ mov ax, 0ff53h ; b8 53 ff ; 0xfe21d orgs.asm:95
+ mov word [0003ch], ax ; a3 3c 00 ; 0xfe220 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe223 orgs.asm:97
+ mov word [0003eh], ax ; a3 3e 00 ; 0xfe226 orgs.asm:98
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe229 orgs.asm:528
+ mov ds, ax ; 8e d8 ; 0xfe22b orgs.asm:529
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe22d orgs.asm:530
+ mov CL, strict byte 014h ; b1 14 ; 0xfe22f orgs.asm:531
+ mov dx, 00378h ; ba 78 03 ; 0xfe231 orgs.asm:532
+ call 0ecedh ; e8 b6 0a ; 0xfe234 orgs.asm:533
+ mov dx, 00278h ; ba 78 02 ; 0xfe237 orgs.asm:534
+ call 0ecedh ; e8 b0 0a ; 0xfe23a orgs.asm:535
+ sal bx, 00eh ; c1 e3 0e ; 0xfe23d orgs.asm:200
+ mov ax, word [00410h] ; a1 10 04 ; 0xfe240 orgs.asm:537
+ and ax, 03fffh ; 25 ff 3f ; 0xfe243 orgs.asm:538
+ db 00bh, 0c3h
+ ; or ax, bx ; 0b c3 ; 0xfe246 orgs.asm:539
+ mov word [00410h], ax ; a3 10 04 ; 0xfe248 orgs.asm:540
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe24b orgs.asm:95
+ mov word [0002ch], ax ; a3 2c 00 ; 0xfe24e orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe251 orgs.asm:97
+ mov word [0002eh], ax ; a3 2e 00 ; 0xfe254 orgs.asm:98
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe257 orgs.asm:95
+ mov word [00030h], ax ; a3 30 00 ; 0xfe25a orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe25d orgs.asm:97
+ mov word [00032h], ax ; a3 32 00 ; 0xfe260 orgs.asm:98
+ mov ax, 0e739h ; b8 39 e7 ; 0xfe263 orgs.asm:95
+ mov word [00050h], ax ; a3 50 00 ; 0xfe266 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe269 orgs.asm:97
+ mov word [00052h], ax ; a3 52 00 ; 0xfe26c orgs.asm:98
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe26f orgs.asm:546
+ mov CL, strict byte 00ah ; b1 0a ; 0xfe271 orgs.asm:547
+ mov dx, 003f8h ; ba f8 03 ; 0xfe273 orgs.asm:548
+ call 0ed0bh ; e8 92 0a ; 0xfe276 orgs.asm:549
+ mov dx, 002f8h ; ba f8 02 ; 0xfe279 orgs.asm:550
+ call 0ed0bh ; e8 8c 0a ; 0xfe27c orgs.asm:551
+ mov dx, 003e8h ; ba e8 03 ; 0xfe27f orgs.asm:552
+ call 0ed0bh ; e8 86 0a ; 0xfe282 orgs.asm:553
+ mov dx, 002e8h ; ba e8 02 ; 0xfe285 orgs.asm:554
+ call 0ed0bh ; e8 80 0a ; 0xfe288 orgs.asm:555
+ sal bx, 009h ; c1 e3 09 ; 0xfe28b orgs.asm:200
+ mov ax, word [00410h] ; a1 10 04 ; 0xfe28e orgs.asm:557
+ and ax, 0f1ffh ; 25 ff f1 ; 0xfe291 orgs.asm:558
+ db 00bh, 0c3h
+ ; or ax, bx ; 0b c3 ; 0xfe294 orgs.asm:559
+ mov word [00410h], ax ; a3 10 04 ; 0xfe296 orgs.asm:560
+ mov ax, 0ff53h ; b8 53 ff ; 0xfe299 orgs.asm:95
+ mov word [00128h], ax ; a3 28 01 ; 0xfe29c orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe29f orgs.asm:97
+ mov word [0012ah], ax ; a3 2a 01 ; 0xfe2a2 orgs.asm:98
+ mov ax, 0f8e6h ; b8 e6 f8 ; 0xfe2a5 orgs.asm:95
+ mov word [001c0h], ax ; a3 c0 01 ; 0xfe2a8 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe2ab orgs.asm:97
+ mov word [001c2h], ax ; a3 c2 01 ; 0xfe2ae orgs.asm:98
+ call 0edbfh ; e8 0b 0b ; 0xfe2b1 orgs.asm:566
+ jmp short 0e303h ; eb 4d ; 0xfe2b4 orgs.asm:568
+ ; disGetNextSymbol 0xfe2b6 LB 0x1d4a -> off=0x0 cb=000000000000000d uValue=00000000000f02b6 'biosorg_check_before_or_at_0E2C1h'
+biosorg_check_before_or_at_0E2C1h: ; 0xfe2b6 LB 0xd
+ times 0xb db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe2c3 LB 0x1d3d -> off=0x0 cb=0000000000000007 uValue=00000000000f02c3 'nmi'
+nmi: ; 0xfe2c3 LB 0x7
+ push CS ; 0e ; 0xfe2c3 orgs.asm:104
+ pop DS ; 1f ; 0xfe2c4 orgs.asm:105
+ cld ; fc ; 0xfe2c5 orgs.asm:106
+ call 016e9h ; e8 20 34 ; 0xfe2c6 orgs.asm:577
+ iret ; cf ; 0xfe2c9 orgs.asm:578
+ ; disGetNextSymbol 0xfe2ca LB 0x1d36 -> off=0x0 cb=0000000000000008 uValue=00000000000f02ca 'int75_handler'
+int75_handler: ; 0xfe2ca LB 0x8
+ out strict byte 0f0h, AL ; e6 f0 ; 0xfe2ca orgs.asm:581
+ call 0e030h ; e8 61 fd ; 0xfe2cc orgs.asm:582
+ int 002h ; cd 02 ; 0xfe2cf orgs.asm:583
+ iret ; cf ; 0xfe2d1 orgs.asm:584
+ ; disGetNextSymbol 0xfe2d2 LB 0x1d2e -> off=0x0 cb=00000000000000a7 uValue=00000000000f02d2 'hard_drive_post'
+hard_drive_post: ; 0xfe2d2 LB 0xa7
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe2d2 orgs.asm:589
+ mov ds, ax ; 8e d8 ; 0xfe2d4 orgs.asm:590
+ mov byte [00474h], AL ; a2 74 04 ; 0xfe2d6 orgs.asm:592
+ mov byte [00477h], AL ; a2 77 04 ; 0xfe2d9 orgs.asm:593
+ mov byte [0048ch], AL ; a2 8c 04 ; 0xfe2dc orgs.asm:594
+ mov byte [0048dh], AL ; a2 8d 04 ; 0xfe2df orgs.asm:595
+ mov byte [0048eh], AL ; a2 8e 04 ; 0xfe2e2 orgs.asm:596
+ mov AL, strict byte 0c0h ; b0 c0 ; 0xfe2e5 orgs.asm:597
+ mov byte [00476h], AL ; a2 76 04 ; 0xfe2e7 orgs.asm:598
+ mov ax, 0e3feh ; b8 fe e3 ; 0xfe2ea orgs.asm:95
+ mov word [0004ch], ax ; a3 4c 00 ; 0xfe2ed orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe2f0 orgs.asm:97
+ mov word [0004eh], ax ; a3 4e 00 ; 0xfe2f3 orgs.asm:98
+ mov ax, 0f8d4h ; b8 d4 f8 ; 0xfe2f6 orgs.asm:95
+ mov word [001d8h], ax ; a3 d8 01 ; 0xfe2f9 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe2fc orgs.asm:97
+ mov word [001dah], ax ; a3 da 01 ; 0xfe2ff orgs.asm:98
+ retn ; c3 ; 0xfe302 orgs.asm:603
+ mov ax, 0f8a9h ; b8 a9 f8 ; 0xfe303 orgs.asm:95
+ mov word [001d0h], ax ; a3 d0 01 ; 0xfe306 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe309 orgs.asm:97
+ mov word [001d2h], ax ; a3 d2 01 ; 0xfe30c orgs.asm:98
+ mov ax, 0e2cah ; b8 ca e2 ; 0xfe30f orgs.asm:95
+ mov word [001d4h], ax ; a3 d4 01 ; 0xfe312 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe315 orgs.asm:97
+ mov word [001d6h], ax ; a3 d6 01 ; 0xfe318 orgs.asm:98
+ call 0e753h ; e8 35 04 ; 0xfe31b orgs.asm:615
+ push CS ; 0e ; 0xfe31e orgs.asm:104
+ pop DS ; 1f ; 0xfe31f orgs.asm:105
+ cld ; fc ; 0xfe320 orgs.asm:106
+ call 01c38h ; e8 14 39 ; 0xfe321 orgs.asm:629
+ call 020afh ; e8 88 3d ; 0xfe324 orgs.asm:630
+ sti ; fb ; 0xfe327 orgs.asm:637
+ call 09426h ; e8 fb b0 ; 0xfe328 orgs.asm:638
+ cli ; fa ; 0xfe32b orgs.asm:639
+ call 0829ah ; e8 6b 9f ; 0xfe32c orgs.asm:644
+ call 0ed2fh ; e8 fd 09 ; 0xfe32f orgs.asm:648
+ call 0e2d2h ; e8 9d ff ; 0xfe332 orgs.asm:651
+ push CS ; 0e ; 0xfe335 orgs.asm:104
+ pop DS ; 1f ; 0xfe336 orgs.asm:105
+ cld ; fc ; 0xfe337 orgs.asm:106
+ mov ax, 0c800h ; b8 00 c8 ; 0xfe338 orgs.asm:655
+ mov dx, 0f000h ; ba 00 f0 ; 0xfe33b orgs.asm:656
+ call 01600h ; e8 bf 32 ; 0xfe33e orgs.asm:657
+ call 0172dh ; e8 e9 33 ; 0xfe341 orgs.asm:671
+ call 03b42h ; e8 fb 57 ; 0xfe344 orgs.asm:674
+ sti ; fb ; 0xfe347 orgs.asm:677
+ int 019h ; cd 19 ; 0xfe348 orgs.asm:678
+ sti ; fb ; 0xfe34a orgs.asm:680
+ hlt ; f4 ; 0xfe34b orgs.asm:682
+ jmp short 0e34bh ; eb fd ; 0xfe34c orgs.asm:683
+ cli ; fa ; 0xfe34e orgs.asm:684
+ hlt ; f4 ; 0xfe34f orgs.asm:685
+ mov ax, strict word 00040h ; b8 40 00 ; 0xfe350 orgs.asm:694
+ mov ds, ax ; 8e d8 ; 0xfe353 orgs.asm:695
+ mov ss, [word 00069h] ; 8e 16 69 00 ; 0xfe355 orgs.asm:697
+ mov sp, word [word 00067h] ; 8b 26 67 00 ; 0xfe359 orgs.asm:698
+ in AL, strict byte 092h ; e4 92 ; 0xfe35d orgs.asm:700
+ and AL, strict byte 0fdh ; 24 fd ; 0xfe35f orgs.asm:701
+ out strict byte 092h, AL ; e6 92 ; 0xfe361 orgs.asm:702
+ lidt [cs:0efe7h] ; 2e 0f 01 1e e7 ef ; 0xfe363 orgs.asm:704
+ pop DS ; 1f ; 0xfe369 orgs.asm:706
+ pop ES ; 07 ; 0xfe36a orgs.asm:707
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xfe36b orgs.asm:709
+ in AL, strict byte 080h ; e4 80 ; 0xfe36d orgs.asm:711
+ mov byte [bp+00fh], al ; 88 46 0f ; 0xfe36f orgs.asm:712
+ db 03ah, 0e0h
+ ; cmp ah, al ; 3a e0 ; 0xfe372 orgs.asm:714
+ popaw ; 61 ; 0xfe374 orgs.asm:716
+ sti ; fb ; 0xfe375 orgs.asm:717
+ retf 00002h ; ca 02 00 ; 0xfe376 orgs.asm:718
+ ; disGetNextSymbol 0xfe379 LB 0x1c87 -> off=0x0 cb=0000000000000085 uValue=00000000000f0379 'biosorg_check_before_or_at_0E3FCh'
+biosorg_check_before_or_at_0E3FCh: ; 0xfe379 LB 0x85
+ times 0x83 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe3fe LB 0x1c02 -> off=0x0 cb=0000000000000003 uValue=00000000000f03fe 'int13_handler'
+int13_handler: ; 0xfe3fe LB 0x3
+ jmp near 0ec5bh ; e9 5a 08 ; 0xfe3fe orgs.asm:728
+ ; disGetNextSymbol 0xfe401 LB 0x1bff -> off=0x0 cb=00000000000002f1 uValue=00000000000f0401 'rom_fdpt'
+rom_fdpt: ; 0xfe401 LB 0x2f1
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 058h
+ db 04dh
+ ; disGetNextSymbol 0xfe6f2 LB 0x190e -> off=0x0 cb=0000000000000003 uValue=00000000000f06f2 'int19_handler'
+int19_handler: ; 0xfe6f2 LB 0x3
+ jmp near 0f0ach ; e9 b7 09 ; 0xfe6f2 orgs.asm:744
+ ; disGetNextSymbol 0xfe6f5 LB 0x190b -> off=0x0 cb=000000000000000a uValue=00000000000f06f5 'biosorg_check_at_0E6F5h'
+biosorg_check_at_0E6F5h: ; 0xfe6f5 LB 0xa
+ or word [bx+si], ax ; 09 00 ; 0xfe6f5
+ cld ; fc ; 0xfe6f7
+ add byte [bx+di], al ; 00 01 ; 0xfe6f8
+ je short 0e73ch ; 74 40 ; 0xfe6fa
+ times 0x3 db 0
+ ; disGetNextSymbol 0xfe6ff LB 0x1901 -> off=0x0 cb=000000000000002a uValue=00000000000f06ff 'biosorg_check_before_or_at_0E727h'
+biosorg_check_before_or_at_0E727h: ; 0xfe6ff LB 0x2a
+ times 0x28 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe729 LB 0x18d7 -> off=0x0 cb=0000000000000010 uValue=00000000000f0729 'biosorg_check_at_0E729h'
+biosorg_check_at_0E729h: ; 0xfe729 LB 0x10
+ times 0xe db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe739 LB 0x18c7 -> off=0x0 cb=000000000000001a uValue=00000000000f0739 'biosorg_check_at_0E739h'
+biosorg_check_at_0E739h: ; 0xfe739 LB 0x1a
+ push DS ; 1e ; 0xfe739 orgs.asm:817
+ push ES ; 06 ; 0xfe73a orgs.asm:818
+ pushaw ; 60 ; 0xfe73b orgs.asm:97
+ push CS ; 0e ; 0xfe73c orgs.asm:104
+ pop DS ; 1f ; 0xfe73d orgs.asm:105
+ cld ; fc ; 0xfe73e orgs.asm:106
+ call 0637bh ; e8 39 7c ; 0xfe73f orgs.asm:821
+ popaw ; 61 ; 0xfe742 orgs.asm:114
+ pop ES ; 07 ; 0xfe743 orgs.asm:823
+ pop DS ; 1f ; 0xfe744 orgs.asm:824
+ iret ; cf ; 0xfe745 orgs.asm:825
+ push DS ; 1e ; 0xfe746 orgs.asm:833
+ push ES ; 06 ; 0xfe747 orgs.asm:834
+ pushaw ; 60 ; 0xfe748 orgs.asm:97
+ push CS ; 0e ; 0xfe749 orgs.asm:104
+ pop DS ; 1f ; 0xfe74a orgs.asm:105
+ cld ; fc ; 0xfe74b orgs.asm:106
+ call 01688h ; e8 39 2f ; 0xfe74c orgs.asm:837
+ popaw ; 61 ; 0xfe74f orgs.asm:114
+ pop ES ; 07 ; 0xfe750 orgs.asm:839
+ pop DS ; 1f ; 0xfe751 orgs.asm:840
+ iret ; cf ; 0xfe752 orgs.asm:841
+ ; disGetNextSymbol 0xfe753 LB 0x18ad -> off=0x0 cb=0000000000000025 uValue=00000000000f0753 'init_pic'
+init_pic: ; 0xfe753 LB 0x25
+ mov AL, strict byte 011h ; b0 11 ; 0xfe753 orgs.asm:846
+ out strict byte 020h, AL ; e6 20 ; 0xfe755 orgs.asm:847
+ out strict byte 0a0h, AL ; e6 a0 ; 0xfe757 orgs.asm:848
+ mov AL, strict byte 008h ; b0 08 ; 0xfe759 orgs.asm:849
+ out strict byte 021h, AL ; e6 21 ; 0xfe75b orgs.asm:850
+ mov AL, strict byte 070h ; b0 70 ; 0xfe75d orgs.asm:851
+ out strict byte 0a1h, AL ; e6 a1 ; 0xfe75f orgs.asm:852
+ mov AL, strict byte 004h ; b0 04 ; 0xfe761 orgs.asm:853
+ out strict byte 021h, AL ; e6 21 ; 0xfe763 orgs.asm:854
+ mov AL, strict byte 002h ; b0 02 ; 0xfe765 orgs.asm:855
+ out strict byte 0a1h, AL ; e6 a1 ; 0xfe767 orgs.asm:856
+ mov AL, strict byte 001h ; b0 01 ; 0xfe769 orgs.asm:857
+ out strict byte 021h, AL ; e6 21 ; 0xfe76b orgs.asm:858
+ out strict byte 0a1h, AL ; e6 a1 ; 0xfe76d orgs.asm:859
+ mov AL, strict byte 0b8h ; b0 b8 ; 0xfe76f orgs.asm:860
+ out strict byte 021h, AL ; e6 21 ; 0xfe771 orgs.asm:861
+ mov AL, strict byte 08fh ; b0 8f ; 0xfe773 orgs.asm:862
+ out strict byte 0a1h, AL ; e6 a1 ; 0xfe775 orgs.asm:863
+ retn ; c3 ; 0xfe777 orgs.asm:864
+ ; disGetNextSymbol 0xfe778 LB 0x1888 -> off=0x0 cb=0000000000000051 uValue=00000000000f0778 'ebda_post'
+ebda_post: ; 0xfe778 LB 0x51
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe778 orgs.asm:95
+ mov word [00034h], ax ; a3 34 00 ; 0xfe77b orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe77e orgs.asm:97
+ mov word [00036h], ax ; a3 36 00 ; 0xfe781 orgs.asm:98
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe784 orgs.asm:95
+ mov word [0003ch], ax ; a3 3c 00 ; 0xfe787 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe78a orgs.asm:97
+ mov word [0003eh], ax ; a3 3e 00 ; 0xfe78d orgs.asm:98
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe790 orgs.asm:95
+ mov word [001c8h], ax ; a3 c8 01 ; 0xfe793 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe796 orgs.asm:97
+ mov word [001cah], ax ; a3 ca 01 ; 0xfe799 orgs.asm:98
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe79c orgs.asm:95
+ mov word [001cch], ax ; a3 cc 01 ; 0xfe79f orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe7a2 orgs.asm:97
+ mov word [001ceh], ax ; a3 ce 01 ; 0xfe7a5 orgs.asm:98
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe7a8 orgs.asm:95
+ mov word [001dch], ax ; a3 dc 01 ; 0xfe7ab orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe7ae orgs.asm:97
+ mov word [001deh], ax ; a3 de 01 ; 0xfe7b1 orgs.asm:98
+ mov ax, 09fc0h ; b8 c0 9f ; 0xfe7b4 orgs.asm:876
+ mov ds, ax ; 8e d8 ; 0xfe7b7 orgs.asm:877
+ mov byte [word 00000h], 001h ; c6 06 00 00 01 ; 0xfe7b9 orgs.asm:878
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe7be orgs.asm:880
+ mov ds, ax ; 8e d8 ; 0xfe7c0 orgs.asm:881
+ mov word [0040eh], 09fc0h ; c7 06 0e 04 c0 9f ; 0xfe7c2 orgs.asm:882
+ retn ; c3 ; 0xfe7c8 orgs.asm:883
+ ; disGetNextSymbol 0xfe7c9 LB 0x1837 -> off=0x0 cb=0000000000000065 uValue=00000000000f07c9 'biosorg_check_before_or_at_0E82Ch'
+biosorg_check_before_or_at_0E82Ch: ; 0xfe7c9 LB 0x65
+ times 0x63 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe82e LB 0x17d2 -> off=0x0 cb=000000000000003d uValue=00000000000f082e 'biosorg_check_at_0E82Eh'
+biosorg_check_at_0E82Eh: ; 0xfe82e LB 0x3d
+ sti ; fb ; 0xfe82e orgs.asm:894
+ pushfw ; 9c ; 0xfe82f orgs.asm:897
+ push ES ; 06 ; 0xfe830 orgs.asm:898
+ push DS ; 1e ; 0xfe831 orgs.asm:899
+ pushaw ; 60 ; 0xfe832 orgs.asm:97
+ cmp ah, 000h ; 80 fc 00 ; 0xfe833 orgs.asm:902
+ je short 0e84ah ; 74 12 ; 0xfe836 orgs.asm:903
+ cmp ah, 010h ; 80 fc 10 ; 0xfe838 orgs.asm:905
+ je short 0e84ah ; 74 0d ; 0xfe83b orgs.asm:906
+ push CS ; 0e ; 0xfe83d orgs.asm:104
+ pop DS ; 1f ; 0xfe83e orgs.asm:105
+ cld ; fc ; 0xfe83f orgs.asm:106
+ call 055c2h ; e8 7f 6d ; 0xfe840 orgs.asm:909
+ popaw ; 61 ; 0xfe843 orgs.asm:114
+ pop DS ; 1f ; 0xfe844 orgs.asm:911
+ pop ES ; 07 ; 0xfe845 orgs.asm:912
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xfe846 orgs.asm:913
+ iret ; cf ; 0xfe849 orgs.asm:914
+ mov bx, strict word 00040h ; bb 40 00 ; 0xfe84a orgs.asm:917
+ mov ds, bx ; 8e db ; 0xfe84d orgs.asm:918
+ cli ; fa ; 0xfe84f orgs.asm:920
+ mov bx, word [word 0001ah] ; 8b 1e 1a 00 ; 0xfe850 orgs.asm:921
+ cmp bx, word [word 0001ch] ; 3b 1e 1c 00 ; 0xfe854 orgs.asm:922
+ jne short 0e85eh ; 75 04 ; 0xfe858 orgs.asm:923
+ sti ; fb ; 0xfe85a orgs.asm:924
+ nop ; 90 ; 0xfe85b orgs.asm:925
+ jmp short 0e84fh ; eb f1 ; 0xfe85c orgs.asm:933
+ push CS ; 0e ; 0xfe85e orgs.asm:104
+ pop DS ; 1f ; 0xfe85f orgs.asm:105
+ cld ; fc ; 0xfe860 orgs.asm:106
+ call 055c2h ; e8 5e 6d ; 0xfe861 orgs.asm:937
+ popaw ; 61 ; 0xfe864 orgs.asm:114
+ pop DS ; 1f ; 0xfe865 orgs.asm:939
+ pop ES ; 07 ; 0xfe866 orgs.asm:940
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xfe867 orgs.asm:941
+ iret ; cf ; 0xfe86a orgs.asm:949
+ ; disGetNextSymbol 0xfe86b LB 0x1795 -> off=0x0 cb=000000000000011c uValue=00000000000f086b 'biosorg_check_before_or_at_0E985h'
+biosorg_check_before_or_at_0E985h: ; 0xfe86b LB 0x11c
+ times 0x11a db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe987 LB 0x1679 -> off=0x0 cb=0000000000000052 uValue=00000000000f0987 'biosorg_check_at_0E987h'
+biosorg_check_at_0E987h: ; 0xfe987 LB 0x52
+ cli ; fa ; 0xfe987 orgs.asm:966
+ push ax ; 50 ; 0xfe988 orgs.asm:967
+ mov AL, strict byte 0adh ; b0 ad ; 0xfe989 orgs.asm:968
+ out strict byte 064h, AL ; e6 64 ; 0xfe98b orgs.asm:969
+ in AL, strict byte 060h ; e4 60 ; 0xfe98d orgs.asm:971
+ push DS ; 1e ; 0xfe98f orgs.asm:972
+ pushaw ; 60 ; 0xfe990 orgs.asm:97
+ cld ; fc ; 0xfe991 orgs.asm:974
+ mov AH, strict byte 04fh ; b4 4f ; 0xfe992 orgs.asm:976
+ stc ; f9 ; 0xfe994 orgs.asm:977
+ int 015h ; cd 15 ; 0xfe995 orgs.asm:978
+ jnc short 0e9c0h ; 73 27 ; 0xfe997 orgs.asm:979
+ sti ; fb ; 0xfe999 orgs.asm:981
+ cmp AL, strict byte 0e0h ; 3c e0 ; 0xfe99a orgs.asm:984
+ jne short 0e9a9h ; 75 0b ; 0xfe99c orgs.asm:985
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe99e orgs.asm:986
+ mov ds, ax ; 8e d8 ; 0xfe9a0 orgs.asm:987
+ or byte [00496h], 002h ; 80 0e 96 04 02 ; 0xfe9a2 orgs.asm:988
+ jmp short 0e9c0h ; eb 17 ; 0xfe9a7 orgs.asm:989
+ cmp AL, strict byte 0e1h ; 3c e1 ; 0xfe9a9 orgs.asm:992
+ jne short 0e9b8h ; 75 0b ; 0xfe9ab orgs.asm:993
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe9ad orgs.asm:994
+ mov ds, ax ; 8e d8 ; 0xfe9af orgs.asm:995
+ or byte [00496h], 001h ; 80 0e 96 04 01 ; 0xfe9b1 orgs.asm:996
+ jmp short 0e9c0h ; eb 08 ; 0xfe9b6 orgs.asm:997
+ push ES ; 06 ; 0xfe9b8 orgs.asm:1000
+ push CS ; 0e ; 0xfe9b9 orgs.asm:104
+ pop DS ; 1f ; 0xfe9ba orgs.asm:105
+ cld ; fc ; 0xfe9bb orgs.asm:106
+ call 0516fh ; e8 b0 67 ; 0xfe9bc orgs.asm:1002
+ pop ES ; 07 ; 0xfe9bf orgs.asm:1003
+ popaw ; 61 ; 0xfe9c0 orgs.asm:114
+ pop DS ; 1f ; 0xfe9c1 orgs.asm:1007
+ cli ; fa ; 0xfe9c2 orgs.asm:1008
+ call 0e034h ; e8 6e f6 ; 0xfe9c3 orgs.asm:1009
+ mov AL, strict byte 0aeh ; b0 ae ; 0xfe9c6 orgs.asm:1011
+ out strict byte 064h, AL ; e6 64 ; 0xfe9c8 orgs.asm:1012
+ pop ax ; 58 ; 0xfe9ca orgs.asm:1013
+ iret ; cf ; 0xfe9cb orgs.asm:1014
+ pushaw ; 60 ; 0xfe9cc orgs.asm:97
+ push ES ; 06 ; 0xfe9cd orgs.asm:1023
+ push DS ; 1e ; 0xfe9ce orgs.asm:1024
+ push CS ; 0e ; 0xfe9cf orgs.asm:104
+ pop DS ; 1f ; 0xfe9d0 orgs.asm:105
+ cld ; fc ; 0xfe9d1 orgs.asm:106
+ call 069fbh ; e8 26 80 ; 0xfe9d2 orgs.asm:1026
+ pop DS ; 1f ; 0xfe9d5 orgs.asm:1027
+ pop ES ; 07 ; 0xfe9d6 orgs.asm:1028
+ popaw ; 61 ; 0xfe9d7 orgs.asm:114
+ iret ; cf ; 0xfe9d8 orgs.asm:1030
+ ; disGetNextSymbol 0xfe9d9 LB 0x1627 -> off=0x0 cb=0000000000000280 uValue=00000000000f09d9 'biosorg_check_before_or_at_0EC57h'
+biosorg_check_before_or_at_0EC57h: ; 0xfe9d9 LB 0x280
+ times 0x27e db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfec59 LB 0x13a7 -> off=0x0 cb=0000000000000002 uValue=00000000000f0c59 'biosorg_check_at_0EC59h'
+biosorg_check_at_0EC59h: ; 0xfec59 LB 0x2
+ jmp short 0ecb0h ; eb 55 ; 0xfec59 orgs.asm:1037
+ ; disGetNextSymbol 0xfec5b LB 0x13a5 -> off=0x0 cb=0000000000000055 uValue=00000000000f0c5b 'int13_relocated'
+int13_relocated: ; 0xfec5b LB 0x55
+ cmp ah, 04ah ; 80 fc 4a ; 0xfec5b orgs.asm:1046
+ jc short 0ec71h ; 72 11 ; 0xfec5e orgs.asm:1047
+ cmp ah, 04dh ; 80 fc 4d ; 0xfec60 orgs.asm:1049
+ jnbe short 0ec71h ; 77 0c ; 0xfec63 orgs.asm:1050
+ pushaw ; 60 ; 0xfec65 orgs.asm:97
+ push ES ; 06 ; 0xfec66 orgs.asm:1053
+ push DS ; 1e ; 0xfec67 orgs.asm:1054
+ push CS ; 0e ; 0xfec68 orgs.asm:104
+ pop DS ; 1f ; 0xfec69 orgs.asm:105
+ cld ; fc ; 0xfec6a orgs.asm:106
+ push 0ece9h ; 68 e9 ec ; 0xfec6b orgs.asm:83
+ jmp near 03b85h ; e9 14 4f ; 0xfec6e orgs.asm:84
+ push ES ; 06 ; 0xfec71 orgs.asm:1062
+ push ax ; 50 ; 0xfec72 orgs.asm:1063
+ push bx ; 53 ; 0xfec73 orgs.asm:1064
+ push cx ; 51 ; 0xfec74 orgs.asm:1065
+ push dx ; 52 ; 0xfec75 orgs.asm:1066
+ call 03b59h ; e8 e0 4e ; 0xfec76 orgs.asm:1069
+ cmp AL, strict byte 000h ; 3c 00 ; 0xfec79 orgs.asm:1070
+ je short 0ecabh ; 74 2e ; 0xfec7b orgs.asm:1071
+ call 03b6fh ; e8 ef 4e ; 0xfec7d orgs.asm:1074
+ pop dx ; 5a ; 0xfec80 orgs.asm:1075
+ push dx ; 52 ; 0xfec81 orgs.asm:1076
+ db 03ah, 0c2h
+ ; cmp al, dl ; 3a c2 ; 0xfec82 orgs.asm:1077
+ jne short 0ec97h ; 75 11 ; 0xfec84 orgs.asm:1078
+ pop dx ; 5a ; 0xfec86 orgs.asm:1080
+ pop cx ; 59 ; 0xfec87 orgs.asm:1081
+ pop bx ; 5b ; 0xfec88 orgs.asm:1082
+ pop ax ; 58 ; 0xfec89 orgs.asm:1083
+ pop ES ; 07 ; 0xfec8a orgs.asm:1084
+ pushaw ; 60 ; 0xfec8b orgs.asm:97
+ push ES ; 06 ; 0xfec8c orgs.asm:1087
+ push DS ; 1e ; 0xfec8d orgs.asm:1088
+ push CS ; 0e ; 0xfec8e orgs.asm:104
+ pop DS ; 1f ; 0xfec8f orgs.asm:105
+ cld ; fc ; 0xfec90 orgs.asm:106
+ push 0ece9h ; 68 e9 ec ; 0xfec91 orgs.asm:83
+ jmp near 0414dh ; e9 b6 54 ; 0xfec94 orgs.asm:84
+ and dl, 0e0h ; 80 e2 e0 ; 0xfec97 orgs.asm:1094
+ db 03ah, 0c2h
+ ; cmp al, dl ; 3a c2 ; 0xfec9a orgs.asm:1095
+ jne short 0ecabh ; 75 0d ; 0xfec9c orgs.asm:1096
+ pop dx ; 5a ; 0xfec9e orgs.asm:1098
+ pop cx ; 59 ; 0xfec9f orgs.asm:1099
+ pop bx ; 5b ; 0xfeca0 orgs.asm:1100
+ pop ax ; 58 ; 0xfeca1 orgs.asm:1101
+ pop ES ; 07 ; 0xfeca2 orgs.asm:1102
+ push ax ; 50 ; 0xfeca3 orgs.asm:1104
+ push cx ; 51 ; 0xfeca4 orgs.asm:1105
+ push dx ; 52 ; 0xfeca5 orgs.asm:1106
+ push bx ; 53 ; 0xfeca6 orgs.asm:1107
+ db 0feh, 0cah
+ ; dec dl ; fe ca ; 0xfeca7 orgs.asm:1109
+ jmp short 0ecb4h ; eb 09 ; 0xfeca9 orgs.asm:1110
+ pop dx ; 5a ; 0xfecab orgs.asm:1113
+ pop cx ; 59 ; 0xfecac orgs.asm:1114
+ pop bx ; 5b ; 0xfecad orgs.asm:1115
+ pop ax ; 58 ; 0xfecae orgs.asm:1116
+ pop ES ; 07 ; 0xfecaf orgs.asm:1117
+ ; disGetNextSymbol 0xfecb0 LB 0x1350 -> off=0x0 cb=0000000000000004 uValue=00000000000f0cb0 'int13_noeltorito'
+int13_noeltorito: ; 0xfecb0 LB 0x4
+ push ax ; 50 ; 0xfecb0 orgs.asm:1120
+ push cx ; 51 ; 0xfecb1 orgs.asm:1121
+ push dx ; 52 ; 0xfecb2 orgs.asm:1122
+ push bx ; 53 ; 0xfecb3 orgs.asm:1123
+ ; disGetNextSymbol 0xfecb4 LB 0x134c -> off=0x0 cb=0000000000000014 uValue=00000000000f0cb4 'int13_legacy'
+int13_legacy: ; 0xfecb4 LB 0x14
+ push dx ; 52 ; 0xfecb4 orgs.asm:1125
+ push bp ; 55 ; 0xfecb5 orgs.asm:1126
+ push si ; 56 ; 0xfecb6 orgs.asm:1127
+ push di ; 57 ; 0xfecb7 orgs.asm:1128
+ push ES ; 06 ; 0xfecb8 orgs.asm:1129
+ push DS ; 1e ; 0xfecb9 orgs.asm:1130
+ push CS ; 0e ; 0xfecba orgs.asm:104
+ pop DS ; 1f ; 0xfecbb orgs.asm:105
+ cld ; fc ; 0xfecbc orgs.asm:106
+ test dl, 080h ; f6 c2 80 ; 0xfecbd orgs.asm:1135
+ jne short 0ecc8h ; 75 06 ; 0xfecc0 orgs.asm:1136
+ push 0ece9h ; 68 e9 ec ; 0xfecc2 orgs.asm:83
+ jmp near 0313dh ; e9 75 44 ; 0xfecc5 orgs.asm:84
+ ; disGetNextSymbol 0xfecc8 LB 0x1338 -> off=0x0 cb=0000000000000014 uValue=00000000000f0cc8 'int13_notfloppy'
+int13_notfloppy: ; 0xfecc8 LB 0x14
+ cmp dl, 0e0h ; 80 fa e0 ; 0xfecc8 orgs.asm:1141
+ jc short 0ecdch ; 72 0f ; 0xfeccb orgs.asm:1142
+ shr ebx, 010h ; 66 c1 eb 10 ; 0xfeccd orgs.asm:1148
+ push bx ; 53 ; 0xfecd1 orgs.asm:1149
+ call 0478eh ; e8 b9 5a ; 0xfecd2 orgs.asm:1150
+ pop bx ; 5b ; 0xfecd5 orgs.asm:1151
+ sal ebx, 010h ; 66 c1 e3 10 ; 0xfecd6 orgs.asm:1152
+ jmp short 0ece9h ; eb 0d ; 0xfecda orgs.asm:1154
+ ; disGetNextSymbol 0xfecdc LB 0x1324 -> off=0x0 cb=000000000000000d uValue=00000000000f0cdc 'int13_disk'
+int13_disk: ; 0xfecdc LB 0xd
+ cmp ah, 040h ; 80 fc 40 ; 0xfecdc orgs.asm:1158
+ jnbe short 0ece6h ; 77 05 ; 0xfecdf orgs.asm:1159
+ call 05c93h ; e8 af 6f ; 0xfece1 orgs.asm:1160
+ jmp short 0ece9h ; eb 03 ; 0xfece4 orgs.asm:1161
+ call 060e4h ; e8 fb 73 ; 0xfece6 orgs.asm:1164
+ ; disGetNextSymbol 0xfece9 LB 0x1317 -> off=0x0 cb=0000000000000004 uValue=00000000000f0ce9 'int13_out'
+int13_out: ; 0xfece9 LB 0x4
+ pop DS ; 1f ; 0xfece9 orgs.asm:1167
+ pop ES ; 07 ; 0xfecea orgs.asm:1168
+ popaw ; 61 ; 0xfeceb orgs.asm:114
+ iret ; cf ; 0xfecec orgs.asm:1170
+ ; disGetNextSymbol 0xfeced LB 0x1313 -> off=0x0 cb=000000000000001e uValue=00000000000f0ced 'detect_parport'
+detect_parport: ; 0xfeced LB 0x1e
+ push dx ; 52 ; 0xfeced orgs.asm:1177
+ inc dx ; 42 ; 0xfecee orgs.asm:1178
+ inc dx ; 42 ; 0xfecef orgs.asm:1179
+ in AL, DX ; ec ; 0xfecf0 orgs.asm:1180
+ and AL, strict byte 0dfh ; 24 df ; 0xfecf1 orgs.asm:1181
+ out DX, AL ; ee ; 0xfecf3 orgs.asm:1182
+ pop dx ; 5a ; 0xfecf4 orgs.asm:1183
+ mov AL, strict byte 0aah ; b0 aa ; 0xfecf5 orgs.asm:1184
+ out DX, AL ; ee ; 0xfecf7 orgs.asm:1185
+ in AL, DX ; ec ; 0xfecf8 orgs.asm:1186
+ cmp AL, strict byte 0aah ; 3c aa ; 0xfecf9 orgs.asm:1187
+ jne short 0ed0ah ; 75 0d ; 0xfecfb orgs.asm:1188
+ push bx ; 53 ; 0xfecfd orgs.asm:1190
+ sal bx, 1 ; d1 e3 ; 0xfecfe orgs.asm:1191
+ mov word [bx+00408h], dx ; 89 97 08 04 ; 0xfed00 orgs.asm:1192
+ pop bx ; 5b ; 0xfed04 orgs.asm:1193
+ mov byte [bx+00478h], cl ; 88 8f 78 04 ; 0xfed05 orgs.asm:1194
+ inc bx ; 43 ; 0xfed09 orgs.asm:1195
+ retn ; c3 ; 0xfed0a orgs.asm:1197
+ ; disGetNextSymbol 0xfed0b LB 0x12f5 -> off=0x0 cb=0000000000000024 uValue=00000000000f0d0b 'detect_serial'
+detect_serial: ; 0xfed0b LB 0x24
+ push dx ; 52 ; 0xfed0b orgs.asm:1204
+ inc dx ; 42 ; 0xfed0c orgs.asm:1205
+ mov AL, strict byte 002h ; b0 02 ; 0xfed0d orgs.asm:1206
+ out DX, AL ; ee ; 0xfed0f orgs.asm:1207
+ in AL, DX ; ec ; 0xfed10 orgs.asm:1208
+ cmp AL, strict byte 002h ; 3c 02 ; 0xfed11 orgs.asm:1209
+ jne short 0ed2dh ; 75 18 ; 0xfed13 orgs.asm:1210
+ inc dx ; 42 ; 0xfed15 orgs.asm:1212
+ in AL, DX ; ec ; 0xfed16 orgs.asm:1213
+ cmp AL, strict byte 002h ; 3c 02 ; 0xfed17 orgs.asm:1214
+ jne short 0ed2dh ; 75 12 ; 0xfed19 orgs.asm:1215
+ dec dx ; 4a ; 0xfed1b orgs.asm:1217
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xfed1c orgs.asm:1218
+ pop dx ; 5a ; 0xfed1e orgs.asm:1219
+ push bx ; 53 ; 0xfed1f orgs.asm:1220
+ sal bx, 1 ; d1 e3 ; 0xfed20 orgs.asm:1221
+ mov word [bx+00400h], dx ; 89 97 00 04 ; 0xfed22 orgs.asm:1222
+ pop bx ; 5b ; 0xfed26 orgs.asm:1223
+ mov byte [bx+0047ch], cl ; 88 8f 7c 04 ; 0xfed27 orgs.asm:1224
+ inc bx ; 43 ; 0xfed2b orgs.asm:1225
+ retn ; c3 ; 0xfed2c orgs.asm:1226
+ pop dx ; 5a ; 0xfed2d orgs.asm:1229
+ retn ; c3 ; 0xfed2e orgs.asm:1230
+ ; disGetNextSymbol 0xfed2f LB 0x12d1 -> off=0x0 cb=0000000000000087 uValue=00000000000f0d2f 'floppy_post'
+floppy_post: ; 0xfed2f LB 0x87
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfed2f orgs.asm:1240
+ mov ds, ax ; 8e d8 ; 0xfed31 orgs.asm:1241
+ mov AL, strict byte 000h ; b0 00 ; 0xfed33 orgs.asm:1245
+ mov byte [0043eh], AL ; a2 3e 04 ; 0xfed35 orgs.asm:1246
+ mov byte [0043fh], AL ; a2 3f 04 ; 0xfed38 orgs.asm:1247
+ mov byte [00440h], AL ; a2 40 04 ; 0xfed3b orgs.asm:1248
+ mov byte [00441h], AL ; a2 41 04 ; 0xfed3e orgs.asm:1249
+ mov byte [00442h], AL ; a2 42 04 ; 0xfed41 orgs.asm:1250
+ mov byte [00443h], AL ; a2 43 04 ; 0xfed44 orgs.asm:1251
+ mov byte [00444h], AL ; a2 44 04 ; 0xfed47 orgs.asm:1252
+ mov byte [00445h], AL ; a2 45 04 ; 0xfed4a orgs.asm:1253
+ mov byte [00446h], AL ; a2 46 04 ; 0xfed4d orgs.asm:1254
+ mov byte [00447h], AL ; a2 47 04 ; 0xfed50 orgs.asm:1255
+ mov byte [00448h], AL ; a2 48 04 ; 0xfed53 orgs.asm:1256
+ mov byte [0048bh], AL ; a2 8b 04 ; 0xfed56 orgs.asm:1258
+ mov AL, strict byte 010h ; b0 10 ; 0xfed59 orgs.asm:1260
+ out strict byte 070h, AL ; e6 70 ; 0xfed5b orgs.asm:1261
+ in AL, strict byte 071h ; e4 71 ; 0xfed5d orgs.asm:1262
+ db 08ah, 0e0h
+ ; mov ah, al ; 8a e0 ; 0xfed5f orgs.asm:1263
+ shr al, 004h ; c0 e8 04 ; 0xfed61 orgs.asm:169
+ je short 0ed6ah ; 74 04 ; 0xfed64 orgs.asm:1268
+ mov BL, strict byte 007h ; b3 07 ; 0xfed66 orgs.asm:1269
+ jmp short 0ed6ch ; eb 02 ; 0xfed68 orgs.asm:1270
+ mov BL, strict byte 000h ; b3 00 ; 0xfed6a orgs.asm:1273
+ db 08ah, 0c4h
+ ; mov al, ah ; 8a c4 ; 0xfed6c orgs.asm:1276
+ and AL, strict byte 00fh ; 24 0f ; 0xfed6e orgs.asm:1277
+ je short 0ed75h ; 74 03 ; 0xfed70 orgs.asm:1278
+ or bl, 070h ; 80 cb 70 ; 0xfed72 orgs.asm:1279
+ mov byte [0048fh], bl ; 88 1e 8f 04 ; 0xfed75 orgs.asm:1281
+ mov AL, strict byte 000h ; b0 00 ; 0xfed79 orgs.asm:1284
+ mov byte [00490h], AL ; a2 90 04 ; 0xfed7b orgs.asm:1285
+ mov byte [00491h], AL ; a2 91 04 ; 0xfed7e orgs.asm:1286
+ mov byte [00492h], AL ; a2 92 04 ; 0xfed81 orgs.asm:1287
+ mov byte [00493h], AL ; a2 93 04 ; 0xfed84 orgs.asm:1288
+ mov byte [00494h], AL ; a2 94 04 ; 0xfed87 orgs.asm:1289
+ mov byte [00495h], AL ; a2 95 04 ; 0xfed8a orgs.asm:1290
+ mov AL, strict byte 002h ; b0 02 ; 0xfed8d orgs.asm:1292
+ out strict byte 00ah, AL ; e6 0a ; 0xfed8f orgs.asm:1293
+ mov ax, 0efc7h ; b8 c7 ef ; 0xfed91 orgs.asm:95
+ mov word [00078h], ax ; a3 78 00 ; 0xfed94 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfed97 orgs.asm:97
+ mov word [0007ah], ax ; a3 7a 00 ; 0xfed9a orgs.asm:98
+ mov ax, 0ec59h ; b8 59 ec ; 0xfed9d orgs.asm:95
+ mov word [00100h], ax ; a3 00 01 ; 0xfeda0 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfeda3 orgs.asm:97
+ mov word [00102h], ax ; a3 02 01 ; 0xfeda6 orgs.asm:98
+ mov ax, 0ef57h ; b8 57 ef ; 0xfeda9 orgs.asm:95
+ mov word [00038h], ax ; a3 38 00 ; 0xfedac orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfedaf orgs.asm:97
+ mov word [0003ah], ax ; a3 3a 00 ; 0xfedb2 orgs.asm:98
+ retn ; c3 ; 0xfedb5 orgs.asm:1299
+ ; disGetNextSymbol 0xfedb6 LB 0x124a -> off=0x0 cb=0000000000000009 uValue=0000000000000db6 'bcd_to_bin'
+bcd_to_bin: ; 0xfedb6 LB 0x9
+ sal ax, 004h ; c1 e0 04 ; 0xfedb6 orgs.asm:1309
+ shr al, 004h ; c0 e8 04 ; 0xfedb9 orgs.asm:1310
+ aad 00ah ; d5 0a ; 0xfedbc orgs.asm:1318
+ retn ; c3 ; 0xfedbe orgs.asm:1319
+ ; disGetNextSymbol 0xfedbf LB 0x1241 -> off=0x0 cb=000000000000005a uValue=00000000000f0dbf 'rtc_post'
+rtc_post: ; 0xfedbf LB 0x5a
+ mov AL, strict byte 000h ; b0 00 ; 0xfedbf orgs.asm:1327
+ out strict byte 070h, AL ; e6 70 ; 0xfedc1 orgs.asm:1328
+ in AL, strict byte 071h ; e4 71 ; 0xfedc3 orgs.asm:1329
+ call 0edb6h ; e8 ee ff ; 0xfedc5 orgs.asm:1330
+ test al, al ; 84 c0 ; 0xfedc8 orgs.asm:1331
+ db 032h, 0e4h
+ ; xor ah, ah ; 32 e4 ; 0xfedca orgs.asm:1332
+ mov dx, 01234h ; ba 34 12 ; 0xfedcc orgs.asm:1333
+ mul dx ; f7 e2 ; 0xfedcf orgs.asm:1334
+ db 08bh, 0c8h
+ ; mov cx, ax ; 8b c8 ; 0xfedd1 orgs.asm:1335
+ mov AL, strict byte 002h ; b0 02 ; 0xfedd3 orgs.asm:1338
+ out strict byte 070h, AL ; e6 70 ; 0xfedd5 orgs.asm:1339
+ in AL, strict byte 071h ; e4 71 ; 0xfedd7 orgs.asm:1340
+ call 0edb6h ; e8 da ff ; 0xfedd9 orgs.asm:1341
+ test al, al ; 84 c0 ; 0xfeddc orgs.asm:1342
+ je short 0edebh ; 74 0b ; 0xfedde orgs.asm:1343
+ add cx, 04463h ; 81 c1 63 44 ; 0xfede0 orgs.asm:1345
+ adc dx, strict byte 00004h ; 83 d2 04 ; 0xfede4 orgs.asm:1346
+ db 0feh, 0c8h
+ ; dec al ; fe c8 ; 0xfede7 orgs.asm:1347
+ jne short 0ede0h ; 75 f5 ; 0xfede9 orgs.asm:1348
+ mov AL, strict byte 004h ; b0 04 ; 0xfedeb orgs.asm:1352
+ out strict byte 070h, AL ; e6 70 ; 0xfeded orgs.asm:1353
+ in AL, strict byte 071h ; e4 71 ; 0xfedef orgs.asm:1354
+ call 0edb6h ; e8 c2 ff ; 0xfedf1 orgs.asm:1355
+ test al, al ; 84 c0 ; 0xfedf4 orgs.asm:1356
+ je short 0ee04h ; 74 0c ; 0xfedf6 orgs.asm:1357
+ add cx, 0076ch ; 81 c1 6c 07 ; 0xfedf8 orgs.asm:1359
+ adc dx, 00100h ; 81 d2 00 01 ; 0xfedfc orgs.asm:1360
+ db 0feh, 0c8h
+ ; dec al ; fe c8 ; 0xfee00 orgs.asm:1361
+ jne short 0edf8h ; 75 f4 ; 0xfee02 orgs.asm:1362
+ db 08ah, 0cdh
+ ; mov cl, ch ; 8a cd ; 0xfee04 orgs.asm:1365
+ db 08ah, 0eah
+ ; mov ch, dl ; 8a ea ; 0xfee06 orgs.asm:1366
+ db 08ah, 0d6h
+ ; mov dl, dh ; 8a d6 ; 0xfee08 orgs.asm:1367
+ db 032h, 0f6h
+ ; xor dh, dh ; 32 f6 ; 0xfee0a orgs.asm:1368
+ mov word [0046ch], cx ; 89 0e 6c 04 ; 0xfee0c orgs.asm:1369
+ mov word [0046eh], dx ; 89 16 6e 04 ; 0xfee10 orgs.asm:1370
+ mov byte [00470h], dh ; 88 36 70 04 ; 0xfee14 orgs.asm:1371
+ retn ; c3 ; 0xfee18 orgs.asm:1419
+ ; disGetNextSymbol 0xfee19 LB 0x11e7 -> off=0x0 cb=000000000000013e uValue=00000000000f0e19 'biosorg_check_before_or_at_0EF55h'
+biosorg_check_before_or_at_0EF55h: ; 0xfee19 LB 0x13e
+ times 0x13c db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfef57 LB 0x10a9 -> off=0x0 cb=000000000000003b uValue=00000000000f0f57 'int0e_handler'
+int0e_handler: ; 0xfef57 LB 0x3b
+ push ax ; 50 ; 0xfef57 orgs.asm:1430
+ push dx ; 52 ; 0xfef58 orgs.asm:1431
+ mov dx, 003f4h ; ba f4 03 ; 0xfef59 orgs.asm:1432
+ in AL, DX ; ec ; 0xfef5c orgs.asm:1433
+ and AL, strict byte 0c0h ; 24 c0 ; 0xfef5d orgs.asm:1434
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xfef5f orgs.asm:1435
+ je short 0ef81h ; 74 1e ; 0xfef61 orgs.asm:1436
+ mov dx, 003f5h ; ba f5 03 ; 0xfef63 orgs.asm:1437
+ mov AL, strict byte 008h ; b0 08 ; 0xfef66 orgs.asm:1438
+ out DX, AL ; ee ; 0xfef68 orgs.asm:1439
+ mov dx, 003f4h ; ba f4 03 ; 0xfef69 orgs.asm:1441
+ in AL, DX ; ec ; 0xfef6c orgs.asm:1442
+ and AL, strict byte 0c0h ; 24 c0 ; 0xfef6d orgs.asm:1443
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xfef6f orgs.asm:1444
+ jne short 0ef69h ; 75 f6 ; 0xfef71 orgs.asm:1445
+ mov dx, 003f5h ; ba f5 03 ; 0xfef73 orgs.asm:1448
+ in AL, DX ; ec ; 0xfef76 orgs.asm:1449
+ mov dx, 003f4h ; ba f4 03 ; 0xfef77 orgs.asm:1450
+ in AL, DX ; ec ; 0xfef7a orgs.asm:1451
+ and AL, strict byte 0c0h ; 24 c0 ; 0xfef7b orgs.asm:1452
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xfef7d orgs.asm:1453
+ je short 0ef73h ; 74 f2 ; 0xfef7f orgs.asm:1454
+ push DS ; 1e ; 0xfef81 orgs.asm:1457
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfef82 orgs.asm:1458
+ mov ds, ax ; 8e d8 ; 0xfef84 orgs.asm:1459
+ call 0e034h ; e8 ab f0 ; 0xfef86 orgs.asm:1460
+ or byte [0043eh], 080h ; 80 0e 3e 04 80 ; 0xfef89 orgs.asm:1462
+ pop DS ; 1f ; 0xfef8e orgs.asm:1463
+ pop dx ; 5a ; 0xfef8f orgs.asm:1464
+ pop ax ; 58 ; 0xfef90 orgs.asm:1465
+ iret ; cf ; 0xfef91 orgs.asm:1466
+ ; disGetNextSymbol 0xfef92 LB 0x106e -> off=0x0 cb=0000000000000035 uValue=00000000000f0f92 'biosorg_check_before_or_at_0EFC5h'
+biosorg_check_before_or_at_0EFC5h: ; 0xfef92 LB 0x35
+ times 0x33 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfefc7 LB 0x1039 -> off=0x0 cb=000000000000000b uValue=00000000000f0fc7 '_diskette_param_table'
+_diskette_param_table: ; 0xfefc7 LB 0xb
+ scasw ; af ; 0xfefc7
+ add ah, byte [di] ; 02 25 ; 0xfefc8
+ add dl, byte [bp+si] ; 02 12 ; 0xfefca
+ db 01bh, 0ffh
+ ; sbb di, di ; 1b ff ; 0xfefcc
+ insb ; 6c ; 0xfefce
+ db 0f6h
+ invd ; 0f 08 ; 0xfefd0
+ ; disGetNextSymbol 0xfefd2 LB 0x102e -> off=0x0 cb=0000000000000002 uValue=00000000000f0fd2 'biosorg_check_at_0EFD2h'
+biosorg_check_at_0EFD2h: ; 0xfefd2 LB 0x2
+ jmp short 0efd4h ; eb 00 ; 0xfefd2 orgs.asm:1493
+ ; disGetNextSymbol 0xfefd4 LB 0x102c -> off=0x0 cb=000000000000000d uValue=00000000000f0fd4 'int17_handler'
+int17_handler: ; 0xfefd4 LB 0xd
+ push DS ; 1e ; 0xfefd4 orgs.asm:1496
+ push ES ; 06 ; 0xfefd5 orgs.asm:1497
+ pushaw ; 60 ; 0xfefd6 orgs.asm:97
+ push CS ; 0e ; 0xfefd7 orgs.asm:104
+ pop DS ; 1f ; 0xfefd8 orgs.asm:105
+ cld ; fc ; 0xfefd9 orgs.asm:106
+ call 0733dh ; e8 60 83 ; 0xfefda orgs.asm:1500
+ popaw ; 61 ; 0xfefdd orgs.asm:114
+ pop ES ; 07 ; 0xfefde orgs.asm:1502
+ pop DS ; 1f ; 0xfefdf orgs.asm:1503
+ iret ; cf ; 0xfefe0 orgs.asm:1504
+ ; disGetNextSymbol 0xfefe1 LB 0x101f -> off=0x0 cb=0000000000000006 uValue=00000000000f0fe1 '_pmode_IDT'
+_pmode_IDT: ; 0xfefe1 LB 0x6
+ db 000h, 000h, 000h, 000h, 00fh, 000h
+ ; disGetNextSymbol 0xfefe7 LB 0x1019 -> off=0x0 cb=0000000000000006 uValue=00000000000f0fe7 '_rmode_IDT'
+_rmode_IDT: ; 0xfefe7 LB 0x6
+ db 0ffh, 003h, 000h, 000h, 000h, 000h
+ ; disGetNextSymbol 0xfefed LB 0x1013 -> off=0x0 cb=0000000000000001 uValue=00000000000f0fed 'int1c_handler'
+int1c_handler: ; 0xfefed LB 0x1
+ iret ; cf ; 0xfefed orgs.asm:1539
+ ; disGetNextSymbol 0xfefee LB 0x1012 -> off=0x0 cb=0000000000000057 uValue=00000000000f0fee 'biosorg_check_before_or_at_0F043h'
+biosorg_check_before_or_at_0F043h: ; 0xfefee LB 0x57
+ times 0x55 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xff045 LB 0xfbb -> off=0x0 cb=0000000000000001 uValue=00000000000f1045 'biosorg_check_at_0F045h'
+biosorg_check_at_0F045h: ; 0xff045 LB 0x1
+ iret ; cf ; 0xff045 orgs.asm:1548
+ ; disGetNextSymbol 0xff046 LB 0xfba -> off=0x0 cb=000000000000001f uValue=00000000000f1046 'biosorg_check_before_or_at_0F063h'
+biosorg_check_before_or_at_0F063h: ; 0xff046 LB 0x1f
+ times 0x1d db 0
+ db 'XM'
+ ; disGetNextSymbol 0xff065 LB 0xf9b -> off=0x0 cb=0000000000000001 uValue=00000000000f1065 'int10_handler'
+int10_handler: ; 0xff065 LB 0x1
+ iret ; cf ; 0xff065 orgs.asm:1557
+ ; disGetNextSymbol 0xff066 LB 0xf9a -> off=0x0 cb=000000000000003e uValue=00000000000f1066 'biosorg_check_before_or_at_0F0A2h'
+biosorg_check_before_or_at_0F0A2h: ; 0xff066 LB 0x3e
+ times 0x3c db 0
+ db 'XM'
+ ; disGetNextSymbol 0xff0a4 LB 0xf5c -> off=0x0 cb=0000000000000008 uValue=00000000000f10a4 'biosorg_check_at_0F0A4h'
+biosorg_check_at_0F0A4h: ; 0xff0a4 LB 0x8
+ push CS ; 0e ; 0xff0a4 orgs.asm:104
+ pop DS ; 1f ; 0xff0a5 orgs.asm:105
+ cld ; fc ; 0xff0a6 orgs.asm:106
+ call 016fbh ; e8 51 26 ; 0xff0a7 orgs.asm:1572
+ hlt ; f4 ; 0xff0aa orgs.asm:1574
+ iret ; cf ; 0xff0ab orgs.asm:1575
+ ; disGetNextSymbol 0xff0ac LB 0xf54 -> off=0x0 cb=0000000000000090 uValue=00000000000f10ac 'int19_relocated'
+int19_relocated: ; 0xff0ac LB 0x90
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff0ac orgs.asm:1586
+ mov ax, word [bp+002h] ; 8b 46 02 ; 0xff0ae orgs.asm:1587
+ cmp ax, 0f000h ; 3d 00 f0 ; 0xff0b1 orgs.asm:1588
+ je short 0f0c3h ; 74 0d ; 0xff0b4 orgs.asm:1589
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xff0b6 orgs.asm:1591
+ mov ds, ax ; 8e d8 ; 0xff0b8 orgs.asm:1592
+ mov ax, 01234h ; b8 34 12 ; 0xff0ba orgs.asm:1593
+ mov word [001d8h], ax ; a3 d8 01 ; 0xff0bd orgs.asm:1594
+ jmp near 0e05bh ; e9 98 ef ; 0xff0c0 orgs.asm:1595
+ push CS ; 0e ; 0xff0c3 orgs.asm:104
+ pop DS ; 1f ; 0xff0c4 orgs.asm:105
+ cld ; fc ; 0xff0c5 orgs.asm:106
+ push bp ; 55 ; 0xff0c6 orgs.asm:1602
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff0c7 orgs.asm:1603
+ mov ax, strict word 00001h ; b8 01 00 ; 0xff0c9 orgs.asm:1606
+ push ax ; 50 ; 0xff0cc orgs.asm:1607
+ call 04c0fh ; e8 3f 5b ; 0xff0cd orgs.asm:1608
+ inc sp ; 44 ; 0xff0d0 orgs.asm:1609
+ inc sp ; 44 ; 0xff0d1 orgs.asm:1610
+ test ax, ax ; 85 c0 ; 0xff0d2 orgs.asm:1611
+ jne short 0f0fdh ; 75 27 ; 0xff0d4 orgs.asm:1612
+ mov ax, strict word 00002h ; b8 02 00 ; 0xff0d6 orgs.asm:1615
+ push ax ; 50 ; 0xff0d9 orgs.asm:1616
+ call 04c0fh ; e8 32 5b ; 0xff0da orgs.asm:1617
+ inc sp ; 44 ; 0xff0dd orgs.asm:1618
+ inc sp ; 44 ; 0xff0de orgs.asm:1619
+ test ax, ax ; 85 c0 ; 0xff0df orgs.asm:1620
+ jne short 0f0fdh ; 75 1a ; 0xff0e1 orgs.asm:1621
+ mov ax, strict word 00003h ; b8 03 00 ; 0xff0e3 orgs.asm:1624
+ push ax ; 50 ; 0xff0e6 orgs.asm:1625
+ call 04c0fh ; e8 25 5b ; 0xff0e7 orgs.asm:1626
+ inc sp ; 44 ; 0xff0ea orgs.asm:1627
+ inc sp ; 44 ; 0xff0eb orgs.asm:1628
+ test ax, ax ; 85 c0 ; 0xff0ec orgs.asm:1629
+ jne short 0f0fdh ; 75 0d ; 0xff0ee orgs.asm:1630
+ mov ax, strict word 00004h ; b8 04 00 ; 0xff0f0 orgs.asm:1633
+ push ax ; 50 ; 0xff0f3 orgs.asm:1634
+ call 04c0fh ; e8 18 5b ; 0xff0f4 orgs.asm:1635
+ inc sp ; 44 ; 0xff0f7 orgs.asm:1636
+ inc sp ; 44 ; 0xff0f8 orgs.asm:1637
+ test ax, ax ; 85 c0 ; 0xff0f9 orgs.asm:1638
+ je short 0f0a4h ; 74 a7 ; 0xff0fb orgs.asm:1639
+ mov word [byte bp+000h], ax ; 89 46 00 ; 0xff0fd orgs.asm:1645
+ sal ax, 004h ; c1 e0 04 ; 0xff100 orgs.asm:200
+ mov word [bp+002h], ax ; 89 46 02 ; 0xff103 orgs.asm:1647
+ mov ax, word [byte bp+000h] ; 8b 46 00 ; 0xff106 orgs.asm:1648
+ and ax, 0f000h ; 25 00 f0 ; 0xff109 orgs.asm:1657
+ mov word [bp+004h], ax ; 89 46 04 ; 0xff10c orgs.asm:1658
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xff10f orgs.asm:1659
+ mov ds, ax ; 8e d8 ; 0xff111 orgs.asm:1660
+ mov es, ax ; 8e c0 ; 0xff113 orgs.asm:1661
+ mov word [byte bp+000h], ax ; 89 46 00 ; 0xff115 orgs.asm:1662
+ mov ax, 0aa55h ; b8 55 aa ; 0xff118 orgs.asm:1663
+ pop bp ; 5d ; 0xff11b orgs.asm:1665
+ iret ; cf ; 0xff11c orgs.asm:1666
+ or cx, word [bp+si] ; 0b 0a ; 0xff11d
+ or word [bp+di], cx ; 09 0b ; 0xff11f
+ push eax ; 66 50 ; 0xff121 orgs.asm:88
+ mov eax, strict dword 000800000h ; 66 b8 00 00 80 00 ; 0xff123 orgs.asm:89
+ db 08bh, 0c3h
+ ; mov ax, bx ; 8b c3 ; 0xff129 orgs.asm:90
+ sal eax, 008h ; 66 c1 e0 08 ; 0xff12b orgs.asm:91
+ and dl, 0fch ; 80 e2 fc ; 0xff12f orgs.asm:92
+ db 00ah, 0c2h
+ ; or al, dl ; 0a c2 ; 0xff132 orgs.asm:93
+ mov dx, 00cf8h ; ba f8 0c ; 0xff134 orgs.asm:94
+ out DX, eax ; 66 ef ; 0xff137 orgs.asm:95
+ pop eax ; 66 58 ; 0xff139 orgs.asm:96
+ retn ; c3 ; 0xff13b orgs.asm:97
+ ; disGetNextSymbol 0xff13c LB 0xec4 -> off=0x0 cb=0000000000000012 uValue=00000000000f113c 'pcibios_init_iomem_bases'
+pcibios_init_iomem_bases: ; 0xff13c LB 0x12
+ push bp ; 55 ; 0xff13c orgs.asm:100
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff13d orgs.asm:101
+ mov eax, strict dword 00124f9fdh ; 66 b8 fd f9 24 01 ; 0xff13f orgs.asm:103
+ mov dx, 00410h ; ba 10 04 ; 0xff145 orgs.asm:104
+ out DX, eax ; 66 ef ; 0xff148 orgs.asm:105
+ db 08bh, 0e5h
+ ; mov sp, bp ; 8b e5 ; 0xff14a orgs.asm:218
+ pop bp ; 5d ; 0xff14c orgs.asm:219
+ retn ; c3 ; 0xff14d orgs.asm:220
+ ; disGetNextSymbol 0xff14e LB 0xeb2 -> off=0x0 cb=000000000000000c uValue=00000000000f114e 'pcibios_init_set_elcr'
+pcibios_init_set_elcr: ; 0xff14e LB 0xc
+ push ax ; 50 ; 0xff14e orgs.asm:223
+ push cx ; 51 ; 0xff14f orgs.asm:224
+ mov dx, 004d0h ; ba d0 04 ; 0xff150 orgs.asm:225
+ test AL, strict byte 008h ; a8 08 ; 0xff153 orgs.asm:226
+ je short 0f15ah ; 74 03 ; 0xff155 orgs.asm:227
+ inc dx ; 42 ; 0xff157 orgs.asm:229
+ and AL, strict byte 007h ; 24 07 ; 0xff158 orgs.asm:230
+ ; disGetNextSymbol 0xff15a LB 0xea6 -> off=0x0 cb=000000000000000d uValue=00000000000f115a 'is_master_pic'
+is_master_pic: ; 0xff15a LB 0xd
+ db 08ah, 0c8h
+ ; mov cl, al ; 8a c8 ; 0xff15a orgs.asm:232
+ mov BL, strict byte 001h ; b3 01 ; 0xff15c orgs.asm:233
+ sal bl, CL ; d2 e3 ; 0xff15e orgs.asm:234
+ in AL, DX ; ec ; 0xff160 orgs.asm:235
+ db 00ah, 0c3h
+ ; or al, bl ; 0a c3 ; 0xff161 orgs.asm:236
+ out DX, AL ; ee ; 0xff163 orgs.asm:237
+ pop cx ; 59 ; 0xff164 orgs.asm:238
+ pop ax ; 58 ; 0xff165 orgs.asm:239
+ retn ; c3 ; 0xff166 orgs.asm:240
+ ; disGetNextSymbol 0xff167 LB 0xe99 -> off=0x0 cb=0000000000000039 uValue=00000000000f1167 'pcibios_init_irqs'
+pcibios_init_irqs: ; 0xff167 LB 0x39
+ push DS ; 1e ; 0xff167 orgs.asm:243
+ push bp ; 55 ; 0xff168 orgs.asm:244
+ mov ax, 0f000h ; b8 00 f0 ; 0xff169 orgs.asm:245
+ mov ds, ax ; 8e d8 ; 0xff16c orgs.asm:246
+ pop bp ; 5d ; 0xff16e orgs.asm:353
+ pop DS ; 1f ; 0xff16f orgs.asm:354
+ retn ; c3 ; 0xff170 orgs.asm:355
+ mov ax, ax ; 89 c0 ; 0xff171
+ mov ax, ax ; 89 c0 ; 0xff173
+ mov ax, ax ; 89 c0 ; 0xff175
+ mov ax, ax ; 89 c0 ; 0xff177
+ mov ax, ax ; 89 c0 ; 0xff179
+ mov ax, ax ; 89 c0 ; 0xff17b
+ mov ax, ax ; 89 c0 ; 0xff17d
+ cld ; fc ; 0xff17f
+ and AL, strict byte 050h ; 24 50 ; 0xff180
+ dec cx ; 49 ; 0xff182
+ push dx ; 52 ; 0xff183
+ add byte [bx+di], al ; 00 01 ; 0xff184
+ add byte [bp+si], al ; 00 02 ; 0xff186
+ add byte [bx+si], cl ; 00 08 ; 0xff188
+ add byte [bx+si], al ; 00 00 ; 0xff18a
+ xchg byte [bx+si+07000h], al ; 86 80 00 70 ; 0xff18c
+ times 0xf db 0
+ db 031h
+ ; disGetNextSymbol 0xff1a0 LB 0xe60 -> off=0x0 cb=00000000000001e0 uValue=00000000000f11a0 '_pci_routing_table'
+_pci_routing_table: ; 0xff1a0 LB 0x1e0
+ db 000h, 008h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 000h, 000h
+ db 000h, 010h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 001h, 000h
+ db 000h, 018h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 002h, 000h
+ db 000h, 020h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 003h, 000h
+ db 000h, 028h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 004h, 000h
+ db 000h, 030h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 005h, 000h
+ db 000h, 038h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 006h, 000h
+ db 000h, 040h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 007h, 000h
+ db 000h, 048h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 008h, 000h
+ db 000h, 050h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 009h, 000h
+ db 000h, 058h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 00ah, 000h
+ db 000h, 060h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 00bh, 000h
+ db 000h, 068h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 00ch, 000h
+ db 000h, 070h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 00dh, 000h
+ db 000h, 078h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 00eh, 000h
+ db 000h, 080h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 00fh, 000h
+ db 000h, 088h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 010h, 000h
+ db 000h, 090h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 011h, 000h
+ db 000h, 098h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 012h, 000h
+ db 000h, 0a0h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 013h, 000h
+ db 000h, 0a8h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 014h, 000h
+ db 000h, 0b0h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 015h, 000h
+ db 000h, 0b8h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 016h, 000h
+ db 000h, 0c0h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 017h, 000h
+ db 000h, 0c8h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 018h, 000h
+ db 000h, 0d0h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 019h, 000h
+ db 000h, 0d8h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 01ah, 000h
+ db 000h, 0e0h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 01bh, 000h
+ db 000h, 0e8h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 01ch, 000h
+ db 000h, 0f0h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 01dh, 000h
+ ; disGetNextSymbol 0xff380 LB 0xc80 -> off=0x0 cb=0000000000000002 uValue=00000000000f1380 '_pci_routing_table_size'
+_pci_routing_table_size: ; 0xff380 LB 0x2
+ loopne 0f383h ; e0 01 ; 0xff380
+ ; disGetNextSymbol 0xff382 LB 0xc7e -> off=0x0 cb=00000000000004bf uValue=00000000000f1382 'biosorg_check_before_or_at_0F83Fh'
+biosorg_check_before_or_at_0F83Fh: ; 0xff382 LB 0x4bf
+ times 0x4bd db 0
+ db 'XM'
+ ; disGetNextSymbol 0xff841 LB 0x7bf -> off=0x0 cb=000000000000000c uValue=00000000000f1841 'int12_handler'
+int12_handler: ; 0xff841 LB 0xc
+ sti ; fb ; 0xff841 orgs.asm:1680
+ push DS ; 1e ; 0xff842 orgs.asm:1681
+ mov ax, strict word 00040h ; b8 40 00 ; 0xff843 orgs.asm:1682
+ mov ds, ax ; 8e d8 ; 0xff846 orgs.asm:1683
+ mov ax, word [00013h] ; a1 13 00 ; 0xff848 orgs.asm:1684
+ pop DS ; 1f ; 0xff84b orgs.asm:1685
+ iret ; cf ; 0xff84c orgs.asm:1686
+ ; disGetNextSymbol 0xff84d LB 0x7b3 -> off=0x0 cb=000000000000000c uValue=00000000000f184d 'int11_handler'
+int11_handler: ; 0xff84d LB 0xc
+ sti ; fb ; 0xff84d orgs.asm:1695
+ push DS ; 1e ; 0xff84e orgs.asm:1696
+ mov ax, strict word 00040h ; b8 40 00 ; 0xff84f orgs.asm:1697
+ mov ds, ax ; 8e d8 ; 0xff852 orgs.asm:1698
+ mov ax, word [00010h] ; a1 10 00 ; 0xff854 orgs.asm:1699
+ pop DS ; 1f ; 0xff857 orgs.asm:1700
+ iret ; cf ; 0xff858 orgs.asm:1701
+ ; disGetNextSymbol 0xff859 LB 0x7a7 -> off=0x0 cb=0000000000000031 uValue=00000000000f1859 'int15_handler'
+int15_handler: ; 0xff859 LB 0x31
+ cmp ah, 087h ; 80 fc 87 ; 0xff859 orgs.asm:1711
+ jne short 0f86bh ; 75 0d ; 0xff85c orgs.asm:1712
+ pushaw ; 60 ; 0xff85e orgs.asm:1717
+ push ES ; 06 ; 0xff85f orgs.asm:1718
+ push DS ; 1e ; 0xff860 orgs.asm:1719
+ push CS ; 0e ; 0xff861 orgs.asm:104
+ pop DS ; 1f ; 0xff862 orgs.asm:105
+ cld ; fc ; 0xff863 orgs.asm:106
+ call 06894h ; e8 2d 70 ; 0xff864 orgs.asm:1721
+ pop DS ; 1f ; 0xff867 orgs.asm:1722
+ pop ES ; 07 ; 0xff868 orgs.asm:1723
+ popaw ; 61 ; 0xff869 orgs.asm:1724
+ iret ; cf ; 0xff86a orgs.asm:1725
+ pushfw ; 9c ; 0xff86b orgs.asm:1730
+ push DS ; 1e ; 0xff86c orgs.asm:1731
+ push ES ; 06 ; 0xff86d orgs.asm:1732
+ push CS ; 0e ; 0xff86e orgs.asm:104
+ pop DS ; 1f ; 0xff86f orgs.asm:105
+ cld ; fc ; 0xff870 orgs.asm:106
+ pushaw ; 60 ; 0xff871 orgs.asm:97
+ cmp ah, 053h ; 80 fc 53 ; 0xff872 orgs.asm:1743
+ je short 0f885h ; 74 0e ; 0xff875 orgs.asm:1744
+ cmp ah, 0c2h ; 80 fc c2 ; 0xff877 orgs.asm:1745
+ je short 0f88ah ; 74 0e ; 0xff87a orgs.asm:1746
+ call 0657ch ; e8 fd 6c ; 0xff87c orgs.asm:1748
+ popaw ; 61 ; 0xff87f orgs.asm:114
+ pop ES ; 07 ; 0xff880 orgs.asm:1754
+ pop DS ; 1f ; 0xff881 orgs.asm:1755
+ popfw ; 9d ; 0xff882 orgs.asm:1756
+ jmp short 0f88fh ; eb 0a ; 0xff883 orgs.asm:1757
+ call 09598h ; e8 10 9d ; 0xff885 orgs.asm:1760
+ jmp short 0f87fh ; eb f5 ; 0xff888 orgs.asm:1761
+ ; disGetNextSymbol 0xff88a LB 0x776 -> off=0x0 cb=0000000000000005 uValue=00000000000f188a 'int15_handler_mouse'
+int15_handler_mouse: ; 0xff88a LB 0x5
+ call 06fd1h ; e8 44 77 ; 0xff88a orgs.asm:1764
+ jmp short 0f87fh ; eb f0 ; 0xff88d orgs.asm:1765
+ ; disGetNextSymbol 0xff88f LB 0x771 -> off=0x0 cb=000000000000001a uValue=00000000000f188f 'iret_modify_cf'
+iret_modify_cf: ; 0xff88f LB 0x1a
+ jc short 0f89fh ; 72 0e ; 0xff88f orgs.asm:1782
+ push bp ; 55 ; 0xff891 orgs.asm:1783
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff892 orgs.asm:1784
+ and byte [bp+006h], 0feh ; 80 66 06 fe ; 0xff894 orgs.asm:1785
+ or word [bp+006h], 00200h ; 81 4e 06 00 02 ; 0xff898 orgs.asm:1786
+ pop bp ; 5d ; 0xff89d orgs.asm:1787
+ iret ; cf ; 0xff89e orgs.asm:1788
+ push bp ; 55 ; 0xff89f orgs.asm:1790
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff8a0 orgs.asm:1791
+ or word [bp+006h], 00201h ; 81 4e 06 01 02 ; 0xff8a2 orgs.asm:1792
+ pop bp ; 5d ; 0xff8a7 orgs.asm:1793
+ iret ; cf ; 0xff8a8 orgs.asm:1794
+ ; disGetNextSymbol 0xff8a9 LB 0x757 -> off=0x0 cb=000000000000002b uValue=00000000000f18a9 'int74_handler'
+int74_handler: ; 0xff8a9 LB 0x2b
+ sti ; fb ; 0xff8a9 orgs.asm:1801
+ pushaw ; 60 ; 0xff8aa orgs.asm:97
+ push ES ; 06 ; 0xff8ab orgs.asm:1803
+ push DS ; 1e ; 0xff8ac orgs.asm:1804
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xff8ad orgs.asm:1805
+ push ax ; 50 ; 0xff8af orgs.asm:1806
+ push ax ; 50 ; 0xff8b0 orgs.asm:1807
+ push ax ; 50 ; 0xff8b1 orgs.asm:1808
+ push ax ; 50 ; 0xff8b2 orgs.asm:1809
+ push ax ; 50 ; 0xff8b3 orgs.asm:1810
+ push CS ; 0e ; 0xff8b4 orgs.asm:104
+ pop DS ; 1f ; 0xff8b5 orgs.asm:105
+ cld ; fc ; 0xff8b6 orgs.asm:106
+ call 06f23h ; e8 69 76 ; 0xff8b7 orgs.asm:1812
+ pop cx ; 59 ; 0xff8ba orgs.asm:1813
+ jcxz 0f8c9h ; e3 0c ; 0xff8bb orgs.asm:1814
+ push strict byte 00000h ; 6a 00 ; 0xff8bd orgs.asm:1818
+ pop DS ; 1f ; 0xff8bf orgs.asm:1823
+ push word [0040eh] ; ff 36 0e 04 ; 0xff8c0 orgs.asm:1824
+ pop DS ; 1f ; 0xff8c4 orgs.asm:1825
+ call far [word 00022h] ; ff 1e 22 00 ; 0xff8c5 orgs.asm:1826
+ cli ; fa ; 0xff8c9 orgs.asm:1828
+ call 0e030h ; e8 63 e7 ; 0xff8ca orgs.asm:1829
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xff8cd orgs.asm:1830
+ pop DS ; 1f ; 0xff8d0 orgs.asm:1831
+ pop ES ; 07 ; 0xff8d1 orgs.asm:1832
+ popaw ; 61 ; 0xff8d2 orgs.asm:114
+ iret ; cf ; 0xff8d3 orgs.asm:1834
+ ; disGetNextSymbol 0xff8d4 LB 0x72c -> off=0x0 cb=0000000000000012 uValue=00000000000f18d4 'int76_handler'
+int76_handler: ; 0xff8d4 LB 0x12
+ push ax ; 50 ; 0xff8d4 orgs.asm:1841
+ push DS ; 1e ; 0xff8d5 orgs.asm:1842
+ mov ax, strict word 00040h ; b8 40 00 ; 0xff8d6 orgs.asm:1843
+ mov ds, ax ; 8e d8 ; 0xff8d9 orgs.asm:1844
+ mov byte [0008eh], 0ffh ; c6 06 8e 00 ff ; 0xff8db orgs.asm:1845
+ call 0e030h ; e8 4d e7 ; 0xff8e0 orgs.asm:1846
+ pop DS ; 1f ; 0xff8e3 orgs.asm:1847
+ pop ax ; 58 ; 0xff8e4 orgs.asm:1848
+ iret ; cf ; 0xff8e5 orgs.asm:1849
+ ; disGetNextSymbol 0xff8e6 LB 0x71a -> off=0x0 cb=000000000000001f uValue=00000000000f18e6 'int70_handler'
+int70_handler: ; 0xff8e6 LB 0x1f
+ push ES ; 06 ; 0xff8e6 orgs.asm:1858
+ push DS ; 1e ; 0xff8e7 orgs.asm:1859
+ pushaw ; 60 ; 0xff8e8 orgs.asm:97
+ push CS ; 0e ; 0xff8e9 orgs.asm:104
+ pop DS ; 1f ; 0xff8ea orgs.asm:105
+ cld ; fc ; 0xff8eb orgs.asm:106
+ call 06bdfh ; e8 f0 72 ; 0xff8ec orgs.asm:1862
+ popaw ; 61 ; 0xff8ef orgs.asm:114
+ pop DS ; 1f ; 0xff8f0 orgs.asm:1864
+ pop ES ; 07 ; 0xff8f1 orgs.asm:1865
+ iret ; cf ; 0xff8f2 orgs.asm:1866
+ jnbe short 0f8fah ; 77 05 ; 0xff8f3 orgs.asm:1876
+ cmp ax, 000b0h ; 3d b0 00 ; 0xff8f5 orgs.asm:1877
+ jc short 0f902h ; 72 08 ; 0xff8f8 orgs.asm:1878
+ db 033h, 0d2h
+ ; xor dx, dx ; 33 d2 ; 0xff8fa orgs.asm:1881
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xff8fc orgs.asm:1882
+ inc byte [word 00070h] ; fe 06 70 00 ; 0xff8fe orgs.asm:1884
+ jmp near 0fec1h ; e9 bc 05 ; 0xff902 orgs.asm:1886
+ ; disGetNextSymbol 0xff905 LB 0x6fb -> off=0x0 cb=0000000000000169 uValue=00000000000f1905 'biosorg_check_before_or_at_0FA6Ch'
+biosorg_check_before_or_at_0FA6Ch: ; 0xff905 LB 0x169
+ times 0x167 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xffa6e LB 0x592 -> off=0x0 cb=0000000000000400 uValue=00000000000f1a6e 'font8x8'
+font8x8: ; 0xffa6e LB 0x400
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 081h, 0a5h, 081h, 0bdh, 099h, 081h, 07eh
+ db 07eh, 0ffh, 0dbh, 0ffh, 0c3h, 0e7h, 0ffh, 07eh, 06ch, 0feh, 0feh, 0feh, 07ch, 038h, 010h, 000h
+ db 010h, 038h, 07ch, 0feh, 07ch, 038h, 010h, 000h, 038h, 07ch, 038h, 0feh, 0feh, 07ch, 038h, 07ch
+ db 010h, 010h, 038h, 07ch, 0feh, 07ch, 038h, 07ch, 000h, 000h, 018h, 03ch, 03ch, 018h, 000h, 000h
+ db 0ffh, 0ffh, 0e7h, 0c3h, 0c3h, 0e7h, 0ffh, 0ffh, 000h, 03ch, 066h, 042h, 042h, 066h, 03ch, 000h
+ db 0ffh, 0c3h, 099h, 0bdh, 0bdh, 099h, 0c3h, 0ffh, 00fh, 007h, 00fh, 07dh, 0cch, 0cch, 0cch, 078h
+ db 03ch, 066h, 066h, 066h, 03ch, 018h, 07eh, 018h, 03fh, 033h, 03fh, 030h, 030h, 070h, 0f0h, 0e0h
+ db 07fh, 063h, 07fh, 063h, 063h, 067h, 0e6h, 0c0h, 099h, 05ah, 03ch, 0e7h, 0e7h, 03ch, 05ah, 099h
+ db 080h, 0e0h, 0f8h, 0feh, 0f8h, 0e0h, 080h, 000h, 002h, 00eh, 03eh, 0feh, 03eh, 00eh, 002h, 000h
+ db 018h, 03ch, 07eh, 018h, 018h, 07eh, 03ch, 018h, 066h, 066h, 066h, 066h, 066h, 000h, 066h, 000h
+ db 07fh, 0dbh, 0dbh, 07bh, 01bh, 01bh, 01bh, 000h, 03eh, 063h, 038h, 06ch, 06ch, 038h, 0cch, 078h
+ db 000h, 000h, 000h, 000h, 07eh, 07eh, 07eh, 000h, 018h, 03ch, 07eh, 018h, 07eh, 03ch, 018h, 0ffh
+ db 018h, 03ch, 07eh, 018h, 018h, 018h, 018h, 000h, 018h, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h
+ db 000h, 018h, 00ch, 0feh, 00ch, 018h, 000h, 000h, 000h, 030h, 060h, 0feh, 060h, 030h, 000h, 000h
+ db 000h, 000h, 0c0h, 0c0h, 0c0h, 0feh, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h
+ db 000h, 018h, 03ch, 07eh, 0ffh, 0ffh, 000h, 000h, 000h, 0ffh, 0ffh, 07eh, 03ch, 018h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 078h, 078h, 030h, 030h, 000h, 030h, 000h
+ db 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h, 000h, 06ch, 06ch, 0feh, 06ch, 0feh, 06ch, 06ch, 000h
+ db 030h, 07ch, 0c0h, 078h, 00ch, 0f8h, 030h, 000h, 000h, 0c6h, 0cch, 018h, 030h, 066h, 0c6h, 000h
+ db 038h, 06ch, 038h, 076h, 0dch, 0cch, 076h, 000h, 060h, 060h, 0c0h, 000h, 000h, 000h, 000h, 000h
+ db 018h, 030h, 060h, 060h, 060h, 030h, 018h, 000h, 060h, 030h, 018h, 018h, 018h, 030h, 060h, 000h
+ db 000h, 066h, 03ch, 0ffh, 03ch, 066h, 000h, 000h, 000h, 030h, 030h, 0fch, 030h, 030h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 060h, 000h, 000h, 000h, 0fch, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 000h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 080h, 000h
+ db 07ch, 0c6h, 0ceh, 0deh, 0f6h, 0e6h, 07ch, 000h, 030h, 070h, 030h, 030h, 030h, 030h, 0fch, 000h
+ db 078h, 0cch, 00ch, 038h, 060h, 0cch, 0fch, 000h, 078h, 0cch, 00ch, 038h, 00ch, 0cch, 078h, 000h
+ db 01ch, 03ch, 06ch, 0cch, 0feh, 00ch, 01eh, 000h, 0fch, 0c0h, 0f8h, 00ch, 00ch, 0cch, 078h, 000h
+ db 038h, 060h, 0c0h, 0f8h, 0cch, 0cch, 078h, 000h, 0fch, 0cch, 00ch, 018h, 030h, 030h, 030h, 000h
+ db 078h, 0cch, 0cch, 078h, 0cch, 0cch, 078h, 000h, 078h, 0cch, 0cch, 07ch, 00ch, 018h, 070h, 000h
+ db 000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h, 000h, 030h, 030h, 060h
+ db 018h, 030h, 060h, 0c0h, 060h, 030h, 018h, 000h, 000h, 000h, 0fch, 000h, 000h, 0fch, 000h, 000h
+ db 060h, 030h, 018h, 00ch, 018h, 030h, 060h, 000h, 078h, 0cch, 00ch, 018h, 030h, 000h, 030h, 000h
+ db 07ch, 0c6h, 0deh, 0deh, 0deh, 0c0h, 078h, 000h, 030h, 078h, 0cch, 0cch, 0fch, 0cch, 0cch, 000h
+ db 0fch, 066h, 066h, 07ch, 066h, 066h, 0fch, 000h, 03ch, 066h, 0c0h, 0c0h, 0c0h, 066h, 03ch, 000h
+ db 0f8h, 06ch, 066h, 066h, 066h, 06ch, 0f8h, 000h, 0feh, 062h, 068h, 078h, 068h, 062h, 0feh, 000h
+ db 0feh, 062h, 068h, 078h, 068h, 060h, 0f0h, 000h, 03ch, 066h, 0c0h, 0c0h, 0ceh, 066h, 03eh, 000h
+ db 0cch, 0cch, 0cch, 0fch, 0cch, 0cch, 0cch, 000h, 078h, 030h, 030h, 030h, 030h, 030h, 078h, 000h
+ db 01eh, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 000h, 0e6h, 066h, 06ch, 078h, 06ch, 066h, 0e6h, 000h
+ db 0f0h, 060h, 060h, 060h, 062h, 066h, 0feh, 000h, 0c6h, 0eeh, 0feh, 0feh, 0d6h, 0c6h, 0c6h, 000h
+ db 0c6h, 0e6h, 0f6h, 0deh, 0ceh, 0c6h, 0c6h, 000h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 06ch, 038h, 000h
+ db 0fch, 066h, 066h, 07ch, 060h, 060h, 0f0h, 000h, 078h, 0cch, 0cch, 0cch, 0dch, 078h, 01ch, 000h
+ db 0fch, 066h, 066h, 07ch, 06ch, 066h, 0e6h, 000h, 078h, 0cch, 0e0h, 070h, 01ch, 0cch, 078h, 000h
+ db 0fch, 0b4h, 030h, 030h, 030h, 030h, 078h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 0fch, 000h
+ db 0cch, 0cch, 0cch, 0cch, 0cch, 078h, 030h, 000h, 0c6h, 0c6h, 0c6h, 0d6h, 0feh, 0eeh, 0c6h, 000h
+ db 0c6h, 0c6h, 06ch, 038h, 038h, 06ch, 0c6h, 000h, 0cch, 0cch, 0cch, 078h, 030h, 030h, 078h, 000h
+ db 0feh, 0c6h, 08ch, 018h, 032h, 066h, 0feh, 000h, 078h, 060h, 060h, 060h, 060h, 060h, 078h, 000h
+ db 0c0h, 060h, 030h, 018h, 00ch, 006h, 002h, 000h, 078h, 018h, 018h, 018h, 018h, 018h, 078h, 000h
+ db 010h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh
+ db 030h, 030h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 078h, 00ch, 07ch, 0cch, 076h, 000h
+ db 0e0h, 060h, 060h, 07ch, 066h, 066h, 0dch, 000h, 000h, 000h, 078h, 0cch, 0c0h, 0cch, 078h, 000h
+ db 01ch, 00ch, 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h
+ db 038h, 06ch, 060h, 0f0h, 060h, 060h, 0f0h, 000h, 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 0f8h
+ db 0e0h, 060h, 06ch, 076h, 066h, 066h, 0e6h, 000h, 030h, 000h, 070h, 030h, 030h, 030h, 078h, 000h
+ db 00ch, 000h, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 0e0h, 060h, 066h, 06ch, 078h, 06ch, 0e6h, 000h
+ db 070h, 030h, 030h, 030h, 030h, 030h, 078h, 000h, 000h, 000h, 0cch, 0feh, 0feh, 0d6h, 0c6h, 000h
+ db 000h, 000h, 0f8h, 0cch, 0cch, 0cch, 0cch, 000h, 000h, 000h, 078h, 0cch, 0cch, 0cch, 078h, 000h
+ db 000h, 000h, 0dch, 066h, 066h, 07ch, 060h, 0f0h, 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 01eh
+ db 000h, 000h, 0dch, 076h, 066h, 060h, 0f0h, 000h, 000h, 000h, 07ch, 0c0h, 078h, 00ch, 0f8h, 000h
+ db 010h, 030h, 07ch, 030h, 030h, 034h, 018h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 076h, 000h
+ db 000h, 000h, 0cch, 0cch, 0cch, 078h, 030h, 000h, 000h, 000h, 0c6h, 0d6h, 0feh, 0feh, 06ch, 000h
+ db 000h, 000h, 0c6h, 06ch, 038h, 06ch, 0c6h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 07ch, 00ch, 0f8h
+ db 000h, 000h, 0fch, 098h, 030h, 064h, 0fch, 000h, 01ch, 030h, 030h, 0e0h, 030h, 030h, 01ch, 000h
+ db 018h, 018h, 018h, 000h, 018h, 018h, 018h, 000h, 0e0h, 030h, 030h, 01ch, 030h, 030h, 0e0h, 000h
+ db 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 000h
+ ; disGetNextSymbol 0xffe6e LB 0x192 -> off=0x0 cb=000000000000000d uValue=00000000000f1e6e 'biosorg_check_at_0FE6Eh'
+biosorg_check_at_0FE6Eh: ; 0xffe6e LB 0xd
+ push ES ; 06 ; 0xffe6e orgs.asm:1920
+ push DS ; 1e ; 0xffe6f orgs.asm:1921
+ pushaw ; 60 ; 0xffe70 orgs.asm:97
+ push CS ; 0e ; 0xffe71 orgs.asm:104
+ pop DS ; 1f ; 0xffe72 orgs.asm:105
+ cld ; fc ; 0xffe73 orgs.asm:106
+ call 06c87h ; e8 10 6e ; 0xffe74 orgs.asm:1925
+ popaw ; 61 ; 0xffe77 orgs.asm:114
+ pop DS ; 1f ; 0xffe78 orgs.asm:1927
+ pop ES ; 07 ; 0xffe79 orgs.asm:1928
+ iret ; cf ; 0xffe7a orgs.asm:1929
+ ; disGetNextSymbol 0xffe7b LB 0x185 -> off=0x0 cb=000000000000002a uValue=00000000000f1e7b 'biosorg_check_before_or_at_0FEA3h'
+biosorg_check_before_or_at_0FEA3h: ; 0xffe7b LB 0x2a
+ times 0x28 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xffea5 LB 0x15b -> off=0x0 cb=0000000000000042 uValue=00000000000f1ea5 'int08_handler'
+int08_handler: ; 0xffea5 LB 0x42
+ sti ; fb ; 0xffea5 orgs.asm:1942
+ push ax ; 50 ; 0xffea6 orgs.asm:1943
+ push DS ; 1e ; 0xffea7 orgs.asm:1945
+ push dx ; 52 ; 0xffea8 orgs.asm:1946
+ mov ax, strict word 00040h ; b8 40 00 ; 0xffea9 orgs.asm:1947
+ mov ds, ax ; 8e d8 ; 0xffeac orgs.asm:1948
+ mov ax, word [0006ch] ; a1 6c 00 ; 0xffeae orgs.asm:1954
+ mov dx, word [word 0006eh] ; 8b 16 6e 00 ; 0xffeb1 orgs.asm:1955
+ inc ax ; 40 ; 0xffeb5 orgs.asm:1956
+ jne short 0feb9h ; 75 01 ; 0xffeb6 orgs.asm:1957
+ inc dx ; 42 ; 0xffeb8 orgs.asm:1958
+ cmp dx, strict byte 00018h ; 83 fa 18 ; 0xffeb9 orgs.asm:1967
+ jc short 0fec1h ; 72 03 ; 0xffebc orgs.asm:1968
+ jmp near 0f8f3h ; e9 32 fa ; 0xffebe orgs.asm:1969
+ mov word [0006ch], ax ; a3 6c 00 ; 0xffec1 orgs.asm:1981
+ mov word [word 0006eh], dx ; 89 16 6e 00 ; 0xffec4 orgs.asm:1982
+ mov AL, byte [00040h] ; a0 40 00 ; 0xffec8 orgs.asm:1986
+ db 00ah, 0c0h
+ ; or al, al ; 0a c0 ; 0xffecb orgs.asm:1987
+ je short 0feddh ; 74 0e ; 0xffecd orgs.asm:1988
+ db 0feh, 0c8h
+ ; dec al ; fe c8 ; 0xffecf orgs.asm:1989
+ mov byte [00040h], AL ; a2 40 00 ; 0xffed1 orgs.asm:1990
+ jne short 0feddh ; 75 07 ; 0xffed4 orgs.asm:1991
+ mov dx, 003f2h ; ba f2 03 ; 0xffed6 orgs.asm:1993
+ in AL, DX ; ec ; 0xffed9 orgs.asm:1994
+ and AL, strict byte 0cfh ; 24 cf ; 0xffeda orgs.asm:1995
+ out DX, AL ; ee ; 0xffedc orgs.asm:1996
+ int 01ch ; cd 1c ; 0xffedd orgs.asm:1999
+ cli ; fa ; 0xffedf orgs.asm:2001
+ call 0e034h ; e8 51 e1 ; 0xffee0 orgs.asm:2002
+ pop dx ; 5a ; 0xffee3 orgs.asm:2003
+ pop DS ; 1f ; 0xffee4 orgs.asm:2004
+ pop ax ; 58 ; 0xffee5 orgs.asm:2009
+ iret ; cf ; 0xffee6 orgs.asm:2011
+ ; disGetNextSymbol 0xffee7 LB 0x119 -> off=0x0 cb=000000000000000c uValue=00000000000f1ee7 'biosorg_check_before_or_at_0FEF1h'
+biosorg_check_before_or_at_0FEF1h: ; 0xffee7 LB 0xc
+ times 0xa db 0
+ db 'XM'
+ ; disGetNextSymbol 0xffef3 LB 0x10d -> off=0x0 cb=000000000000000d uValue=00000000000f1ef3 'biosorg_check_at_0FEF3h'
+biosorg_check_at_0FEF3h: ; 0xffef3 LB 0xd
+ times 0xb db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfff00 LB 0x100 -> off=0x0 cb=0000000000000019 uValue=00000000000f1f00 'biosorg_check_at_0FF00h'
+biosorg_check_at_0FF00h: ; 0xfff00 LB 0x19
+ dec di ; 4f ; 0xfff00
+ jc short 0ff64h ; 72 61 ; 0xfff01
+ arpl [si+065h], bp ; 63 6c 65 ; 0xfff03
+ and byte [bp+04dh], dl ; 20 56 4d ; 0xfff06
+ and byte [bp+069h], dl ; 20 56 69 ; 0xfff09
+ jc short 0ff82h ; 72 74 ; 0xfff0c
+ jne short 0ff71h ; 75 61 ; 0xfff0e
+ insb ; 6c ; 0xfff10
+ inc dx ; 42 ; 0xfff11
+ outsw ; 6f ; 0xfff12
+ js short 0ff35h ; 78 20 ; 0xfff13
+ inc dx ; 42 ; 0xfff15
+ dec cx ; 49 ; 0xfff16
+ dec di ; 4f ; 0xfff17
+ push bx ; 53 ; 0xfff18
+ ; disGetNextSymbol 0xfff19 LB 0xe7 -> off=0x0 cb=000000000000003a uValue=00000000000f1f19 'biosorg_check_before_or_at_0FF51h'
+biosorg_check_before_or_at_0FF51h: ; 0xfff19 LB 0x3a
+ times 0x38 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfff53 LB 0xad -> off=0x0 cb=0000000000000001 uValue=00000000000f1f53 'dummy_iret'
+dummy_iret: ; 0xfff53 LB 0x1
+ iret ; cf ; 0xfff53 orgs.asm:2036
+ ; disGetNextSymbol 0xfff54 LB 0xac -> off=0x0 cb=000000000000002c uValue=00000000000f1f54 'biosorg_check_at_0FF54h'
+biosorg_check_at_0FF54h: ; 0xfff54 LB 0x2c
+ iret ; cf ; 0xfff54 orgs.asm:2045
+ mov ax, ax ; 89 c0 ; 0xfff55
+ mov ax, ax ; 89 c0 ; 0xfff57
+ mov ax, ax ; 89 c0 ; 0xfff59
+ mov ax, ax ; 89 c0 ; 0xfff5b
+ mov ax, ax ; 89 c0 ; 0xfff5d
+ cld ; fc ; 0xfff5f
+ pop di ; 5f ; 0xfff60
+ push bx ; 53 ; 0xfff61
+ dec bp ; 4d ; 0xfff62
+ pop di ; 5f ; 0xfff63
+ jnl short 0ff85h ; 7d 1f ; 0xfff64
+ add al, byte [di] ; 02 05 ; 0xfff66
+ inc word [bx+si] ; ff 00 ; 0xfff68
+ add byte [bx+si], al ; 00 00 ; 0xfff6a
+ add byte [bx+si], al ; 00 00 ; 0xfff6c
+ add byte [bx+si], al ; 00 00 ; 0xfff6e
+ pop di ; 5f ; 0xfff70
+ inc sp ; 44 ; 0xfff71
+ dec bp ; 4d ; 0xfff72
+ dec cx ; 49 ; 0xfff73
+ pop di ; 5f ; 0xfff74
+ and ax, strict word 00000h ; 25 00 00 ; 0xfff75
+ add byte [bx+si], dl ; 00 10 ; 0xfff78
+ push CS ; 0e ; 0xfff7a
+ add byte [bx+si], al ; 00 00 ; 0xfff7b
+ add byte [di], ah ; 00 25 ; 0xfff7d
+ times 0x1 db 0
+ ; disGetNextSymbol 0xfff80 LB 0x80 -> off=0x0 cb=0000000000000070 uValue=00000000000f1f80 'biosorg_check_before_or_at_0FFEEh'
+biosorg_check_before_or_at_0FFEEh: ; 0xfff80 LB 0x70
+ times 0x6e db 0
+ db 'XM'
+ ; disGetNextSymbol 0xffff0 LB 0x10 -> off=0x0 cb=0000000000000010 uValue=00000000000f1ff0 'cpu_reset'
+cpu_reset: ; 0xffff0 LB 0x10
+ jmp far 0f000h:0e05bh ; ea 5b e0 00 f0 ; 0xffff0 orgs.asm:2055
+ ; disGetNextSymbol 0xffff5 LB 0xb -> off=0xb cb=0000000000000000 uValue=0000000000100000 '_dummy_addr_0x100000'
+ db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 005h
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.md5sum b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.md5sum
new file mode 100644
index 00000000..77ac3ff4
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.md5sum
@@ -0,0 +1 @@
+3dad0312a44e67bb66402a756cd2eef8 *VBoxPcBios286.rom
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.asm b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.asm
new file mode 100644
index 00000000..567b50f4
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.asm
@@ -0,0 +1,17325 @@
+; $Id: VBoxBiosAlternative386.asm $
+;; @file
+; Auto Generated source file. Do not edit.
+;
+
+;
+; Source file: post.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; BIOS POST routines. Used only during initialization.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: bios.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: print.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: ata.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: floppy.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: floppyt.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; Floppy drive tables.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: eltorito.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: boot.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: keyboard.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: disk.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: serial.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: system.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: invop.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; Real mode invalid opcode handler.
+;
+;
+;
+; Copyright (C) 2013-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: timepci.c
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: ps2mouse.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: parallel.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: logo.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; Stuff for drawing the BIOS logo.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: scsi.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; SCSI host adapter driver to boot from SCSI disks
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: ahci.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; AHCI host adapter driver to boot from SATA disks.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: apm.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; APM BIOS support. Implements APM version 1.2.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: pcibios.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; PCI BIOS support.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: pciutil.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; Utility routines for calling the PCI BIOS.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: vds.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; Utility routines for calling the Virtual DMA Services.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: __U4M.asm
+;
+; $Id: VBoxBiosAlternative386.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: __U4D.asm
+;
+; $Id: VBoxBiosAlternative386.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: __U8RS.asm
+;
+; $Id: VBoxBiosAlternative386.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: __U8LS.asm
+;
+; $Id: VBoxBiosAlternative386.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: fmemset.asm
+;
+; $Id: VBoxBiosAlternative386.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: fmemcpy.asm
+;
+; $Id: VBoxBiosAlternative386.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: pcibio32.asm
+;
+; $Id: VBoxBiosAlternative386.asm $
+; BIOS32 service directory and 32-bit PCI BIOS entry point
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+
+;
+; Source file: apm_pm.asm
+;
+; $Id:
+; Protected-mode APM implementation.
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: orgs.asm
+;
+; $Id: VBoxBiosAlternative386.asm $
+; ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: pci32.c
+;
+; $Id: VBoxBiosAlternative386.asm $
+; 32-bit PCI BIOS wrapper.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+
+
+
+section _DATA progbits vstart=0x0 align=1 ; size=0xb0 class=DATA group=DGROUP
+ ; disGetNextSymbol 0xf0000 LB 0xb0 -> off=0x0 cb=000000000000005b uValue=00000000000f0000 '_fd_parm'
+_fd_parm: ; 0xf0000 LB 0x5b
+ db 0dfh, 002h, 025h, 002h, 009h, 02ah, 0ffh, 050h, 0f6h, 00fh, 008h, 027h, 080h, 0dfh, 002h, 025h
+ db 002h, 009h, 02ah, 0ffh, 050h, 0f6h, 00fh, 008h, 027h, 040h, 0dfh, 002h, 025h, 002h, 00fh, 01bh
+ db 0ffh, 054h, 0f6h, 00fh, 008h, 04fh, 000h, 0dfh, 002h, 025h, 002h, 009h, 02ah, 0ffh, 050h, 0f6h
+ db 00fh, 008h, 04fh, 080h, 0afh, 002h, 025h, 002h, 012h, 01bh, 0ffh, 06ch, 0f6h, 00fh, 008h, 04fh
+ db 000h, 0afh, 002h, 025h, 002h, 024h, 01bh, 0ffh, 054h, 0f6h, 00fh, 008h, 04fh, 0c0h, 0afh, 002h
+ db 025h, 002h, 0ffh, 01bh, 0ffh, 054h, 0f6h, 00fh, 008h, 0ffh, 000h
+ ; disGetNextSymbol 0xf005b LB 0x55 -> off=0x0 cb=000000000000000f uValue=00000000000f005b '_fd_map'
+_fd_map: ; 0xf005b LB 0xf
+ db 001h, 000h, 002h, 002h, 003h, 003h, 004h, 004h, 005h, 005h, 00eh, 006h, 00fh, 006h, 000h
+ ; disGetNextSymbol 0xf006a LB 0x46 -> off=0x0 cb=000000000000000c uValue=00000000000f006a '_pktacc'
+_pktacc: ; 0xf006a LB 0xc
+ db 000h, 000h, 000h, 000h, 000h, 000h, 032h, 02ch, 0b3h, 080h, 026h, 090h
+ ; disGetNextSymbol 0xf0076 LB 0x3a -> off=0x0 cb=000000000000000c uValue=00000000000f0076 '_softrst'
+_softrst: ; 0xf0076 LB 0xc
+ db 000h, 000h, 000h, 000h, 000h, 000h, 011h, 02fh, 07dh, 03ch, 07dh, 03ch
+ ; disGetNextSymbol 0xf0082 LB 0x2e -> off=0x0 cb=000000000000002e uValue=00000000000f0082 '_dskacc'
+_dskacc: ; 0xf0082 LB 0x2e
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 022h, 02bh, 0d7h, 02bh, 000h, 000h, 000h, 000h
+ db 0fdh, 07eh, 0d8h, 07fh, 0fch, 08eh, 0a2h, 08fh, 000h, 000h, 000h, 000h, 000h, 000h, 05fh, 033h
+ db 032h, 05fh, 000h, 0dah, 00fh, 000h, 000h, 001h, 0f3h, 000h, 000h, 000h, 000h, 000h
+
+section CONST progbits vstart=0xb0 align=1 ; size=0xcf0 class=DATA group=DGROUP
+ ; disGetNextSymbol 0xf00b0 LB 0xcf0 -> off=0xcf0 cb=0000000000000000 uValue=00000000000f0da0 'bios_cvs_version_string'
+ db 'CPUID EDX: 0x%lx', 00ah, 000h
+ db 'NMI Handler called', 00ah, 000h
+ db 'INT18: BOOT FAILURE', 00ah, 000h
+ db '%s', 00ah, 000h, 000h
+ db 'FATAL: ', 000h
+ db 'bios_printf: unknown %ll format', 00ah, 000h
+ db 'bios_printf: unknown format', 00ah, 000h
+ db 'ata-detect: Failed to detect ATA device', 00ah, 000h
+ db 'ata%d-%d: PCHS=%u/%u/%u LCHS=%u/%u/%u', 00ah, 000h
+ db 'ata-detect: Failed to detect ATAPI device', 00ah, 000h
+ db ' slave', 000h
+ db 'master', 000h
+ db 'ata%d %s: ', 000h
+ db '%c', 000h
+ db ' ATA-%d Hard-Disk (%lu MBytes)', 00ah, 000h
+ db ' ATAPI-%d CD-ROM/DVD-ROM', 00ah, 000h
+ db ' ATAPI-%d Device', 00ah, 000h
+ db 'ata%d %s: Unknown device', 00ah, 000h
+ db 'ata_cmd_packet', 000h
+ db '%s: DATA_OUT not supported yet', 00ah, 000h
+ db 'set_diskette_current_cyl: drive > 1', 00ah, 000h
+ db 'int13_diskette_function', 000h
+ db '%s: drive>1 || head>1 ...', 00ah, 000h
+ db '%s: ctrl not ready', 00ah, 000h
+ db '%s: write error', 00ah, 000h
+ db '%s: bad floppy type', 00ah, 000h
+ db '%s: unsupported AH=%02x', 00ah, 000h, 000h
+ db 'int13_eltorito', 000h
+ db '%s: call with AX=%04x not implemented.', 00ah, 000h
+ db '%s: unsupported AH=%02x', 00ah, 000h
+ db 'int13_cdemu', 000h
+ db '%s: function %02x, emulation not active for DL= %02x', 00ah, 000h
+ db '%s: function %02x, error %02x !', 00ah, 000h
+ db '%s: function %02x. Can', 027h, 't use 64bits lba', 00ah, 000h
+ db '%s: function %02x, status %02x !', 00ah, 000h
+ db '%s: function AH=%02x unsupported, returns fail', 00ah, 000h
+ db 'int13_cdrom', 000h
+ db '%s: function %02x, ELDL out of range %02x', 00ah, 000h
+ db '%s: function %02x, unmapped device for ELDL=%02x', 00ah, 000h, 000h
+ db 'Booting from %s...', 00ah, 000h
+ db 'Boot from %s failed', 00ah, 000h
+ db 'Boot from %s %d failed', 00ah, 000h
+ db 'No bootable medium found! System halted.', 00ah, 000h
+ db 'Could not read from the boot medium! System halted.', 00ah, 000h
+ db 'CDROM boot failure code : %04x', 00ah, 000h
+ db 'Boot : bseqnr=%d, bootseq=%x', 00dh, 00ah, 000h, 000h
+ db 'Keyboard error:%u', 00ah, 000h
+ db 'KBD: int09 handler: AL=0', 00ah, 000h
+ db 'KBD: int09h_handler(): unknown scancode read: 0x%02x!', 00ah, 000h
+ db 'KBD: int09h_handler(): scancode & asciicode are zero?', 00ah, 000h
+ db 'KBD: int16h: out of keyboard input', 00ah, 000h
+ db 'KBD: unsupported int 16h function %02x', 00ah, 000h
+ db 'AX=%04x BX=%04x CX=%04x DX=%04x ', 00ah, 000h, 000h
+ db 'int13_harddisk', 000h
+ db '%s: function %02x, ELDL out of range %02x', 00ah, 000h
+ db '%s: function %02x, unmapped device for ELDL=%02x', 00ah, 000h
+ db '%s: function %02x, count out of range!', 00ah, 000h
+ db '%s: function %02x, disk %02x, parameters out of range %04x/%04x/%04x!', 00ah
+ db 000h
+ db '%s: function %02x, error %02x !', 00ah, 000h
+ db 'format disk track called', 00ah, 000h
+ db '%s: function %02xh unimplemented, returns success', 00ah, 000h
+ db '%s: function %02xh unsupported, returns fail', 00ah, 000h
+ db 'int13_harddisk_ext', 000h
+ db '%s: function %02x. LBA out of range', 00ah, 000h, 000h
+ db 'int15: Func 24h, subfunc %02xh, A20 gate control not supported', 00ah, 000h
+ db '*** int 15h function AH=bf not yet supported!', 00ah, 000h
+ db 'EISA BIOS not present', 00ah, 000h
+ db '*** int 15h function AX=%04x, BX=%04x not yet supported!', 00ah, 000h
+ db 'sendmouse', 000h
+ db 'setkbdcomm', 000h
+ db 'Mouse reset returned %02x (should be ack)', 00ah, 000h
+ db 'Mouse status returned %02x (should be ack)', 00ah, 000h
+ db 'INT 15h C2 AL=6, BH=%02x', 00ah, 000h
+ db 'INT 15h C2 default case entered', 00ah, 000h, 000h
+ db 'Key pressed: %x', 00ah, 000h
+ db 00ah, 00ah, ' AHCI controller:', 000h
+ db 00ah, ' %d) Hard disk', 000h
+ db 00ah, 00ah, ' SCSI controller:', 000h
+ db ' IDE controller:', 000h
+ db 00ah, 00ah, 'AHCI controller:', 00ah, 000h
+ db 00ah, ' %d) ', 000h
+ db 'Secondary ', 000h
+ db 'Primary ', 000h
+ db 'Slave', 000h
+ db 'Master', 000h
+ db 'No hard disks found', 000h
+ db 00ah, 000h
+ db 'Press F12 to select boot device.', 00ah, 000h
+ db 00ah, 'VirtualBox temporary boot device selection', 00ah, 00ah, 'Detected H'
+ db 'ard disks:', 00ah, 00ah, 000h
+ db 00ah, 'Other boot devices:', 00ah, ' f) Floppy', 00ah, ' c) CD-ROM', 00ah
+ db ' l) LAN', 00ah, 00ah, ' b) Continue booting', 00ah, 000h
+ db 'Delaying boot for %d seconds:', 000h
+ db ' %d', 000h, 000h
+ db 'scsi_read_sectors', 000h
+ db '%s: device_id out of range %d', 00ah, 000h
+ db 'scsi_write_sectors', 000h
+ db 'scsi_cmd_packet', 000h
+ db '%s: DATA_OUT not supported yet', 00ah, 000h
+ db 'scsi_enumerate_attached_devices', 000h
+ db '%s: SCSI_INQUIRY failed', 00ah, 000h
+ db '%s: SCSI_READ_CAPACITY failed', 00ah, 000h
+ db 'Disk %d has an unsupported sector size of %u', 00ah, 000h
+ db 'SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors', 00ah, 000h
+ db 'SCSI %d-ID#%d: CD/DVD-ROM', 00ah, 000h, 000h
+ db 'ahci_read_sectors', 000h
+ db '%s: device_id out of range %d', 00ah, 000h
+ db 'ahci_write_sectors', 000h
+ db 'ahci_cmd_packet', 000h
+ db '%s: DATA_OUT not supported yet', 00ah, 000h
+ db 'AHCI %d-P#%d: PCHS=%u/%u/%u LCHS=%u/%u/%u 0x%llx sectors', 00ah, 000h
+ db 'Standby', 000h
+ db 'Suspend', 000h
+ db 'Shutdown', 000h
+ db 'APM: Unsupported function AX=%04X BX=%04X called', 00ah, 000h, 000h
+ db 'PCI: Unsupported function AX=%04X BX=%04X called', 00ah, 000h
+
+section CONST2 progbits vstart=0xda0 align=1 ; size=0x3fa class=DATA group=DGROUP
+ ; disGetNextSymbol 0xf0da0 LB 0x3fa -> off=0x0 cb=0000000000000012 uValue=00000000000f0da0 'bios_cvs_version_string'
+bios_cvs_version_string: ; 0xf0da0 LB 0x12
+ db 'VirtualBox 6.0.4', 000h, 000h
+ ; disGetNextSymbol 0xf0db2 LB 0x3e8 -> off=0x0 cb=0000000000000008 uValue=00000000000f0db2 '_bios_prefix_string'
+_bios_prefix_string: ; 0xf0db2 LB 0x8
+ db 'BIOS: ', 000h, 000h
+ ; disGetNextSymbol 0xf0dba LB 0x3e0 -> off=0x0 cb=0000000000000006 uValue=00000000000f0dba 'isotag'
+isotag: ; 0xf0dba LB 0x6
+ db 'CD001', 000h
+ ; disGetNextSymbol 0xf0dc0 LB 0x3da -> off=0x0 cb=0000000000000018 uValue=00000000000f0dc0 'eltorito'
+eltorito: ; 0xf0dc0 LB 0x18
+ db 'EL TORITO SPECIFICATION', 000h
+ ; disGetNextSymbol 0xf0dd8 LB 0x3c2 -> off=0x0 cb=0000000000000028 uValue=00000000000f0dd8 'drivetypes'
+drivetypes: ; 0xf0dd8 LB 0x28
+ db 046h, 06ch, 06fh, 070h, 070h, 079h, 000h, 000h, 000h, 000h, 048h, 061h, 072h, 064h, 020h, 044h
+ db 069h, 073h, 06bh, 000h, 043h, 044h, 02dh, 052h, 04fh, 04dh, 000h, 000h, 000h, 000h, 04ch, 041h
+ db 04eh, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ ; disGetNextSymbol 0xf0e00 LB 0x39a -> off=0x0 cb=000000000000037a uValue=00000000000f0e00 'scan_to_scanascii'
+scan_to_scanascii: ; 0xf0e00 LB 0x37a
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 01bh, 001h, 01bh, 001h, 01bh, 001h
+ db 000h, 001h, 000h, 000h, 031h, 002h, 021h, 002h, 000h, 000h, 000h, 078h, 000h, 000h, 032h, 003h
+ db 040h, 003h, 000h, 003h, 000h, 079h, 000h, 000h, 033h, 004h, 023h, 004h, 000h, 000h, 000h, 07ah
+ db 000h, 000h, 034h, 005h, 024h, 005h, 000h, 000h, 000h, 07bh, 000h, 000h, 035h, 006h, 025h, 006h
+ db 000h, 000h, 000h, 07ch, 000h, 000h, 036h, 007h, 05eh, 007h, 01eh, 007h, 000h, 07dh, 000h, 000h
+ db 037h, 008h, 026h, 008h, 000h, 000h, 000h, 07eh, 000h, 000h, 038h, 009h, 02ah, 009h, 000h, 000h
+ db 000h, 07fh, 000h, 000h, 039h, 00ah, 028h, 00ah, 000h, 000h, 000h, 080h, 000h, 000h, 030h, 00bh
+ db 029h, 00bh, 000h, 000h, 000h, 081h, 000h, 000h, 02dh, 00ch, 05fh, 00ch, 01fh, 00ch, 000h, 082h
+ db 000h, 000h, 03dh, 00dh, 02bh, 00dh, 000h, 000h, 000h, 083h, 000h, 000h, 008h, 00eh, 008h, 00eh
+ db 07fh, 00eh, 000h, 000h, 000h, 000h, 009h, 00fh, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h
+ db 071h, 010h, 051h, 010h, 011h, 010h, 000h, 010h, 040h, 000h, 077h, 011h, 057h, 011h, 017h, 011h
+ db 000h, 011h, 040h, 000h, 065h, 012h, 045h, 012h, 005h, 012h, 000h, 012h, 040h, 000h, 072h, 013h
+ db 052h, 013h, 012h, 013h, 000h, 013h, 040h, 000h, 074h, 014h, 054h, 014h, 014h, 014h, 000h, 014h
+ db 040h, 000h, 079h, 015h, 059h, 015h, 019h, 015h, 000h, 015h, 040h, 000h, 075h, 016h, 055h, 016h
+ db 015h, 016h, 000h, 016h, 040h, 000h, 069h, 017h, 049h, 017h, 009h, 017h, 000h, 017h, 040h, 000h
+ db 06fh, 018h, 04fh, 018h, 00fh, 018h, 000h, 018h, 040h, 000h, 070h, 019h, 050h, 019h, 010h, 019h
+ db 000h, 019h, 040h, 000h, 05bh, 01ah, 07bh, 01ah, 01bh, 01ah, 000h, 000h, 000h, 000h, 05dh, 01bh
+ db 07dh, 01bh, 01dh, 01bh, 000h, 000h, 000h, 000h, 00dh, 01ch, 00dh, 01ch, 00ah, 01ch, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 061h, 01eh, 041h, 01eh
+ db 001h, 01eh, 000h, 01eh, 040h, 000h, 073h, 01fh, 053h, 01fh, 013h, 01fh, 000h, 01fh, 040h, 000h
+ db 064h, 020h, 044h, 020h, 004h, 020h, 000h, 020h, 040h, 000h, 066h, 021h, 046h, 021h, 006h, 021h
+ db 000h, 021h, 040h, 000h, 067h, 022h, 047h, 022h, 007h, 022h, 000h, 022h, 040h, 000h, 068h, 023h
+ db 048h, 023h, 008h, 023h, 000h, 023h, 040h, 000h, 06ah, 024h, 04ah, 024h, 00ah, 024h, 000h, 024h
+ db 040h, 000h, 06bh, 025h, 04bh, 025h, 00bh, 025h, 000h, 025h, 040h, 000h, 06ch, 026h, 04ch, 026h
+ db 00ch, 026h, 000h, 026h, 040h, 000h, 03bh, 027h, 03ah, 027h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 027h, 028h, 022h, 028h, 000h, 000h, 000h, 000h, 000h, 000h, 060h, 029h, 07eh, 029h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 05ch, 02bh
+ db 07ch, 02bh, 01ch, 02bh, 000h, 000h, 000h, 000h, 07ah, 02ch, 05ah, 02ch, 01ah, 02ch, 000h, 02ch
+ db 040h, 000h, 078h, 02dh, 058h, 02dh, 018h, 02dh, 000h, 02dh, 040h, 000h, 063h, 02eh, 043h, 02eh
+ db 003h, 02eh, 000h, 02eh, 040h, 000h, 076h, 02fh, 056h, 02fh, 016h, 02fh, 000h, 02fh, 040h, 000h
+ db 062h, 030h, 042h, 030h, 002h, 030h, 000h, 030h, 040h, 000h, 06eh, 031h, 04eh, 031h, 00eh, 031h
+ db 000h, 031h, 040h, 000h, 06dh, 032h, 04dh, 032h, 00dh, 032h, 000h, 032h, 040h, 000h, 02ch, 033h
+ db 03ch, 033h, 000h, 000h, 000h, 000h, 000h, 000h, 02eh, 034h, 03eh, 034h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 02fh, 035h, 03fh, 035h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 02ah, 037h, 02ah, 037h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 020h, 039h, 020h, 039h, 020h, 039h
+ db 020h, 039h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 03bh
+ db 000h, 054h, 000h, 05eh, 000h, 068h, 000h, 000h, 000h, 03ch, 000h, 055h, 000h, 05fh, 000h, 069h
+ db 000h, 000h, 000h, 03dh, 000h, 056h, 000h, 060h, 000h, 06ah, 000h, 000h, 000h, 03eh, 000h, 057h
+ db 000h, 061h, 000h, 06bh, 000h, 000h, 000h, 03fh, 000h, 058h, 000h, 062h, 000h, 06ch, 000h, 000h
+ db 000h, 040h, 000h, 059h, 000h, 063h, 000h, 06dh, 000h, 000h, 000h, 041h, 000h, 05ah, 000h, 064h
+ db 000h, 06eh, 000h, 000h, 000h, 042h, 000h, 05bh, 000h, 065h, 000h, 06fh, 000h, 000h, 000h, 043h
+ db 000h, 05ch, 000h, 066h, 000h, 070h, 000h, 000h, 000h, 044h, 000h, 05dh, 000h, 067h, 000h, 071h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 047h, 037h, 047h, 000h, 077h, 000h, 000h, 020h, 000h
+ db 000h, 048h, 038h, 048h, 000h, 000h, 000h, 000h, 020h, 000h, 000h, 049h, 039h, 049h, 000h, 084h
+ db 000h, 000h, 020h, 000h, 02dh, 04ah, 02dh, 04ah, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 04bh
+ db 034h, 04bh, 000h, 073h, 000h, 000h, 020h, 000h, 000h, 04ch, 035h, 04ch, 000h, 000h, 000h, 000h
+ db 020h, 000h, 000h, 04dh, 036h, 04dh, 000h, 074h, 000h, 000h, 020h, 000h, 02bh, 04eh, 02bh, 04eh
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 04fh, 031h, 04fh, 000h, 075h, 000h, 000h, 020h, 000h
+ db 000h, 050h, 032h, 050h, 000h, 000h, 000h, 000h, 020h, 000h, 000h, 051h, 033h, 051h, 000h, 076h
+ db 000h, 000h, 020h, 000h, 000h, 052h, 030h, 052h, 000h, 000h, 000h, 000h, 020h, 000h, 000h, 053h
+ db 02eh, 053h, 000h, 000h, 000h, 000h, 020h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 05ch, 056h, 07ch, 056h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 085h, 000h, 087h, 000h, 089h, 000h, 08bh, 000h, 000h
+ db 000h, 086h, 000h, 088h, 000h, 08ah, 000h, 08ch, 000h, 000h
+ ; disGetNextSymbol 0xf117a LB 0x20 -> off=0x0 cb=0000000000000020 uValue=00000000000f117a 'panic_msg_keyb_buffer_full'
+panic_msg_keyb_buffer_full: ; 0xf117a LB 0x20
+ db '%s: keyboard input buffer full', 00ah, 000h
+
+ ; Padding 0x466 bytes at 0xf119a
+ times 1126 db 0
+
+section _TEXT progbits vstart=0x1600 align=1 ; size=0x8a45 class=CODE group=AUTO
+ ; disGetNextSymbol 0xf1600 LB 0x8a45 -> off=0x0 cb=0000000000000050 uValue=00000000000f0000 'rom_scan'
+rom_scan: ; 0xf1600 LB 0x50
+ push bp ; 55 ; 0xf1600 post.c:73
+ mov bp, sp ; 89 e5 ; 0xf1601
+ push bx ; 53 ; 0xf1603
+ push cx ; 51 ; 0xf1604
+ push si ; 56 ; 0xf1605
+ push ax ; 50 ; 0xf1606
+ push ax ; 50 ; 0xf1607
+ mov bx, ax ; 89 c3 ; 0xf1608
+ mov cx, dx ; 89 d1 ; 0xf160a
+ cmp bx, cx ; 39 cb ; 0xf160c post.c:80
+ jnc short 01648h ; 73 38 ; 0xf160e
+ xor si, si ; 31 f6 ; 0xf1610 post.c:81
+ mov dx, bx ; 89 da ; 0xf1612
+ mov es, bx ; 8e c3 ; 0xf1614 post.c:83
+ cmp word [es:si], 0aa55h ; 26 81 3c 55 aa ; 0xf1616
+ jne short 01642h ; 75 25 ; 0xf161b
+ mov word [bp-008h], bx ; 89 5e f8 ; 0xf161d post.c:89
+ mov word [bp-00ah], strict word 00003h ; c7 46 f6 03 00 ; 0xf1620
+ call far [bp-00ah] ; ff 5e f6 ; 0xf1625 post.c:90
+ cli ; fa ; 0xf1628 post.c:91
+ mov es, bx ; 8e c3 ; 0xf1629 post.c:95
+ mov al, byte [es:si+002h] ; 26 8a 44 02 ; 0xf162b
+ add AL, strict byte 003h ; 04 03 ; 0xf162f
+ and AL, strict byte 0fch ; 24 fc ; 0xf1631
+ xor ah, ah ; 30 e4 ; 0xf1633 post.c:96
+ cwd ; 99 ; 0xf1635
+ sal dx, 002h ; c1 e2 02 ; 0xf1636
+ db 01bh, 0c2h
+ ; sbb ax, dx ; 1b c2 ; 0xf1639
+ sar ax, 002h ; c1 f8 02 ; 0xf163b
+ add bx, ax ; 01 c3 ; 0xf163e
+ jmp short 0160ch ; eb ca ; 0xf1640 post.c:98
+ add bx, 00080h ; 81 c3 80 00 ; 0xf1642 post.c:100
+ jmp short 0160ch ; eb c4 ; 0xf1646 post.c:102
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf1648 post.c:103
+ pop si ; 5e ; 0xf164b
+ pop cx ; 59 ; 0xf164c
+ pop bx ; 5b ; 0xf164d
+ pop bp ; 5d ; 0xf164e
+ retn ; c3 ; 0xf164f
+ ; disGetNextSymbol 0xf1650 LB 0x89f5 -> off=0x0 cb=0000000000000042 uValue=00000000000f0050 'is_cpuid_supported'
+is_cpuid_supported: ; 0xf1650 LB 0x42
+ push bp ; 55 ; 0xf1650 post.c:110
+ mov bp, sp ; 89 e5 ; 0xf1651
+ push bx ; 53 ; 0xf1653
+ push cx ; 51 ; 0xf1654
+ push dx ; 52 ; 0xf1655
+ pushfd ; 66 9c ; 0xf1656 post.c:114
+ pop edx ; 66 5a ; 0xf1658
+ db 08bh, 0c2h
+ ; mov ax, dx ; 8b c2 ; 0xf165a
+ shr edx, 010h ; 66 c1 ea 10 ; 0xf165c
+ mov bx, ax ; 89 c3 ; 0xf1660
+ mov cx, dx ; 89 d1 ; 0xf1662
+ xor dl, 020h ; 80 f2 20 ; 0xf1664 post.c:115
+ sal edx, 010h ; 66 c1 e2 10 ; 0xf1667 post.c:116
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf166b
+ push edx ; 66 52 ; 0xf166d
+ popfd ; 66 9d ; 0xf166f
+ pushfd ; 66 9c ; 0xf1671 post.c:117
+ pop edx ; 66 5a ; 0xf1673
+ db 08bh, 0c2h
+ ; mov ax, dx ; 8b c2 ; 0xf1675
+ shr edx, 010h ; 66 c1 ea 10 ; 0xf1677
+ cmp cx, dx ; 39 d1 ; 0xf167b post.c:118
+ jne short 01683h ; 75 04 ; 0xf167d
+ cmp bx, ax ; 39 c3 ; 0xf167f
+ je short 01688h ; 74 05 ; 0xf1681
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf1683
+ jmp short 0168ah ; eb 02 ; 0xf1686
+ xor ax, ax ; 31 c0 ; 0xf1688
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf168a post.c:119
+ pop dx ; 5a ; 0xf168d
+ pop cx ; 59 ; 0xf168e
+ pop bx ; 5b ; 0xf168f
+ pop bp ; 5d ; 0xf1690
+ retn ; c3 ; 0xf1691
+ ; disGetNextSymbol 0xf1692 LB 0x89b3 -> off=0x0 cb=00000000000000c4 uValue=00000000000f0092 'apic_setup'
+apic_setup: ; 0xf1692 LB 0xc4
+ push bp ; 55 ; 0xf1692 post.c:144
+ mov bp, sp ; 89 e5 ; 0xf1693
+ push si ; 56 ; 0xf1695
+ push di ; 57 ; 0xf1696
+ sub sp, strict byte 00012h ; 83 ec 12 ; 0xf1697
+ call 01650h ; e8 b3 ff ; 0xf169a post.c:153
+ test ax, ax ; 85 c0 ; 0xf169d
+ je near 0174fh ; 0f 84 ac 00 ; 0xf169f
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf16a3 post.c:158
+ xor dx, dx ; 31 d2 ; 0xf16a6
+ push SS ; 16 ; 0xf16a8
+ pop ES ; 07 ; 0xf16a9
+ lea di, [bp-016h] ; 8d 7e ea ; 0xf16aa
+ sal edx, 010h ; 66 c1 e2 10 ; 0xf16ad
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf16b1
+ db 066h, 08bh, 0c2h
+ ; mov eax, edx ; 66 8b c2 ; 0xf16b3
+ cpuid ; 0f a2 ; 0xf16b6
+ db 066h, 026h, 089h, 005h
+ ; mov dword [es:di], eax ; 66 26 89 05 ; 0xf16b8
+ db 066h, 026h, 089h, 05dh, 004h
+ ; mov dword [es:di+004h], ebx ; 66 26 89 5d 04 ; 0xf16bc
+ db 066h, 026h, 089h, 04dh, 008h
+ ; mov dword [es:di+008h], ecx ; 66 26 89 4d 08 ; 0xf16c1
+ db 066h, 026h, 089h, 055h, 00ch
+ ; mov dword [es:di+00ch], edx ; 66 26 89 55 0c ; 0xf16c6
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf16cb post.c:159
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf16ce
+ push dx ; 52 ; 0xf16d1
+ push ax ; 50 ; 0xf16d2
+ push 000b0h ; 68 b0 00 ; 0xf16d3
+ push strict byte 00004h ; 6a 04 ; 0xf16d6
+ call 01a14h ; e8 39 03 ; 0xf16d8
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf16db
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf16de post.c:160
+ test ah, 002h ; f6 c4 02 ; 0xf16e1
+ je short 0174fh ; 74 69 ; 0xf16e4
+ mov ax, strict word 00078h ; b8 78 00 ; 0xf16e6 post.c:165
+ call 01756h ; e8 6a 00 ; 0xf16e9
+ xor si, si ; 31 f6 ; 0xf16ec post.c:167
+ xor di, di ; 31 ff ; 0xf16ee
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf16f0 post.c:168
+ jne short 016f9h ; 75 05 ; 0xf16f2
+ mov di, 00400h ; bf 00 04 ; 0xf16f4 post.c:169
+ jmp short 01708h ; eb 0f ; 0xf16f7 post.c:170
+ test al, al ; 84 c0 ; 0xf16f9
+ jne short 01700h ; 75 03 ; 0xf16fb
+ mov si, 00800h ; be 00 08 ; 0xf16fd post.c:171
+ test di, di ; 85 ff ; 0xf1700 post.c:175
+ jne short 01708h ; 75 04 ; 0xf1702
+ test si, si ; 85 f6 ; 0xf1704
+ je short 0174fh ; 74 47 ; 0xf1706
+ mov ax, strict word 0001bh ; b8 1b 00 ; 0xf1708 post.c:176
+ xor cx, cx ; 31 c9 ; 0xf170b
+ sal ecx, 010h ; 66 c1 e1 10 ; 0xf170d
+ db 08bh, 0c8h
+ ; mov cx, ax ; 8b c8 ; 0xf1711
+ rdmsr ; 0f 32 ; 0xf1713
+ xchg edx, eax ; 66 92 ; 0xf1715
+ db 08bh, 0d8h
+ ; mov bx, ax ; 8b d8 ; 0xf1717
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf1719
+ db 08bh, 0cah
+ ; mov cx, dx ; 8b ca ; 0xf171d
+ shr edx, 010h ; 66 c1 ea 10 ; 0xf171f
+ xchg dx, cx ; 87 ca ; 0xf1723
+ mov word [bp-006h], si ; 89 76 fa ; 0xf1725 post.c:177
+ not word [bp-006h] ; f7 56 fa ; 0xf1728
+ and dx, word [bp-006h] ; 23 56 fa ; 0xf172b
+ or dx, di ; 09 fa ; 0xf172e post.c:178
+ mov si, strict word 0001bh ; be 1b 00 ; 0xf1730 post.c:179
+ xor di, di ; 31 ff ; 0xf1733
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf1735
+ db 08bh, 0c3h
+ ; mov ax, bx ; 8b c3 ; 0xf1739
+ xchg dx, cx ; 87 ca ; 0xf173b
+ sal edx, 010h ; 66 c1 e2 10 ; 0xf173d
+ db 08bh, 0d1h
+ ; mov dx, cx ; 8b d1 ; 0xf1741
+ xchg edx, eax ; 66 92 ; 0xf1743
+ db 08bh, 0cfh
+ ; mov cx, di ; 8b cf ; 0xf1745
+ sal ecx, 010h ; 66 c1 e1 10 ; 0xf1747
+ db 08bh, 0ceh
+ ; mov cx, si ; 8b ce ; 0xf174b
+ wrmsr ; 0f 30 ; 0xf174d
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf174f post.c:181
+ pop di ; 5f ; 0xf1752
+ pop si ; 5e ; 0xf1753
+ pop bp ; 5d ; 0xf1754
+ retn ; c3 ; 0xf1755
+ ; disGetNextSymbol 0xf1756 LB 0x88ef -> off=0x0 cb=000000000000001d uValue=00000000000f0156 'inb_cmos'
+inb_cmos: ; 0xf1756 LB 0x1d
+ push bp ; 55 ; 0xf1756 bios.c:65
+ mov bp, sp ; 89 e5 ; 0xf1757
+ push dx ; 52 ; 0xf1759
+ mov AH, strict byte 070h ; b4 70 ; 0xf175a bios.c:67
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf175c bios.c:69
+ jc short 01762h ; 72 02 ; 0xf175e
+ mov AH, strict byte 072h ; b4 72 ; 0xf1760 bios.c:70
+ movzx dx, ah ; 0f b6 d4 ; 0xf1762 bios.c:71
+ out DX, AL ; ee ; 0xf1765
+ movzx dx, ah ; 0f b6 d4 ; 0xf1766 bios.c:72
+ inc dx ; 42 ; 0xf1769
+ in AL, DX ; ec ; 0xf176a
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf176b
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf176d bios.c:73
+ pop dx ; 5a ; 0xf1770
+ pop bp ; 5d ; 0xf1771
+ retn ; c3 ; 0xf1772
+ ; disGetNextSymbol 0xf1773 LB 0x88d2 -> off=0x0 cb=000000000000001f uValue=00000000000f0173 'outb_cmos'
+outb_cmos: ; 0xf1773 LB 0x1f
+ push bp ; 55 ; 0xf1773 bios.c:75
+ mov bp, sp ; 89 e5 ; 0xf1774
+ push bx ; 53 ; 0xf1776
+ mov ah, dl ; 88 d4 ; 0xf1777
+ mov BL, strict byte 070h ; b3 70 ; 0xf1779 bios.c:77
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf177b bios.c:79
+ jc short 01781h ; 72 02 ; 0xf177d
+ mov BL, strict byte 072h ; b3 72 ; 0xf177f bios.c:80
+ movzx dx, bl ; 0f b6 d3 ; 0xf1781 bios.c:81
+ out DX, AL ; ee ; 0xf1784
+ movzx dx, bl ; 0f b6 d3 ; 0xf1785 bios.c:82
+ inc dx ; 42 ; 0xf1788
+ mov al, ah ; 88 e0 ; 0xf1789
+ out DX, AL ; ee ; 0xf178b
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf178c bios.c:83
+ pop bx ; 5b ; 0xf178f
+ pop bp ; 5d ; 0xf1790
+ retn ; c3 ; 0xf1791
+ ; disGetNextSymbol 0xf1792 LB 0x88b3 -> off=0x0 cb=000000000000006a uValue=00000000000f0192 'dummy_isr_function'
+dummy_isr_function: ; 0xf1792 LB 0x6a
+ push bp ; 55 ; 0xf1792 bios.c:85
+ mov bp, sp ; 89 e5 ; 0xf1793
+ push ax ; 50 ; 0xf1795
+ mov CH, strict byte 0ffh ; b5 ff ; 0xf1796 bios.c:93
+ mov AL, strict byte 00bh ; b0 0b ; 0xf1798 bios.c:95
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf179a
+ out DX, AL ; ee ; 0xf179d
+ in AL, DX ; ec ; 0xf179e bios.c:96
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf179f
+ mov bx, ax ; 89 c3 ; 0xf17a1
+ mov cl, al ; 88 c1 ; 0xf17a3
+ test al, al ; 84 c0 ; 0xf17a5 bios.c:97
+ je short 017edh ; 74 44 ; 0xf17a7
+ mov AL, strict byte 00bh ; b0 0b ; 0xf17a9 bios.c:98
+ mov dx, 000a0h ; ba a0 00 ; 0xf17ab
+ out DX, AL ; ee ; 0xf17ae
+ in AL, DX ; ec ; 0xf17af bios.c:99
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf17b0
+ mov word [bp-002h], ax ; 89 46 fe ; 0xf17b2
+ cmp byte [bp-002h], 000h ; 80 7e fe 00 ; 0xf17b5 bios.c:100
+ je short 017d3h ; 74 18 ; 0xf17b9
+ mov dx, 000a1h ; ba a1 00 ; 0xf17bb bios.c:101
+ in AL, DX ; ec ; 0xf17be
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf17bf
+ movzx bx, al ; 0f b6 d8 ; 0xf17c1 bios.c:102
+ movzx ax, byte [bp-002h] ; 0f b6 46 fe ; 0xf17c4
+ or ax, bx ; 09 d8 ; 0xf17c8
+ out DX, AL ; ee ; 0xf17ca
+ mov AL, strict byte 020h ; b0 20 ; 0xf17cb bios.c:103
+ mov dx, 000a0h ; ba a0 00 ; 0xf17cd
+ out DX, AL ; ee ; 0xf17d0
+ jmp short 017e5h ; eb 12 ; 0xf17d1 bios.c:104
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf17d3 bios.c:105
+ in AL, DX ; ec ; 0xf17d6
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf17d7
+ and cl, 0fbh ; 80 e1 fb ; 0xf17d9 bios.c:106
+ movzx bx, al ; 0f b6 d8 ; 0xf17dc bios.c:107
+ movzx ax, cl ; 0f b6 c1 ; 0xf17df
+ or ax, bx ; 09 d8 ; 0xf17e2
+ out DX, AL ; ee ; 0xf17e4
+ mov AL, strict byte 020h ; b0 20 ; 0xf17e5 bios.c:109
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf17e7
+ out DX, AL ; ee ; 0xf17ea
+ mov ch, cl ; 88 cd ; 0xf17eb bios.c:110
+ mov bx, strict word 0006bh ; bb 6b 00 ; 0xf17ed bios.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf17f0
+ mov es, ax ; 8e c0 ; 0xf17f3
+ mov byte [es:bx], ch ; 26 88 2f ; 0xf17f5
+ mov sp, bp ; 89 ec ; 0xf17f8 bios.c:113
+ pop bp ; 5d ; 0xf17fa
+ retn ; c3 ; 0xf17fb
+ ; disGetNextSymbol 0xf17fc LB 0x8849 -> off=0x0 cb=0000000000000012 uValue=00000000000f01fc 'nmi_handler_msg'
+nmi_handler_msg: ; 0xf17fc LB 0x12
+ push bp ; 55 ; 0xf17fc bios.c:116
+ mov bp, sp ; 89 e5 ; 0xf17fd
+ push 000c2h ; 68 c2 00 ; 0xf17ff bios.c:118
+ push strict byte 00007h ; 6a 07 ; 0xf1802
+ call 01a14h ; e8 0d 02 ; 0xf1804
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf1807
+ mov sp, bp ; 89 ec ; 0xf180a bios.c:119
+ pop bp ; 5d ; 0xf180c
+ retn ; c3 ; 0xf180d
+ ; disGetNextSymbol 0xf180e LB 0x8837 -> off=0x0 cb=0000000000000012 uValue=00000000000f020e 'int18_panic_msg'
+int18_panic_msg: ; 0xf180e LB 0x12
+ push bp ; 55 ; 0xf180e bios.c:121
+ mov bp, sp ; 89 e5 ; 0xf180f
+ push 000d6h ; 68 d6 00 ; 0xf1811 bios.c:123
+ push strict byte 00007h ; 6a 07 ; 0xf1814
+ call 01a14h ; e8 fb 01 ; 0xf1816
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf1819
+ mov sp, bp ; 89 ec ; 0xf181c bios.c:124
+ pop bp ; 5d ; 0xf181e
+ retn ; c3 ; 0xf181f
+ ; disGetNextSymbol 0xf1820 LB 0x8825 -> off=0x0 cb=0000000000000020 uValue=00000000000f0220 'log_bios_start'
+log_bios_start: ; 0xf1820 LB 0x20
+ push bp ; 55 ; 0xf1820 bios.c:126
+ mov bp, sp ; 89 e5 ; 0xf1821
+ mov bx, 00db2h ; bb b2 0d ; 0xf1823 bios.c:131
+ mov cx, ds ; 8c d9 ; 0xf1826
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf1828
+ call 019d3h ; e8 a5 01 ; 0xf182b
+ push 00da0h ; 68 a0 0d ; 0xf182e
+ push 000ebh ; 68 eb 00 ; 0xf1831
+ push strict byte 00004h ; 6a 04 ; 0xf1834
+ call 01a14h ; e8 db 01 ; 0xf1836
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf1839
+ mov sp, bp ; 89 ec ; 0xf183c bios.c:132
+ pop bp ; 5d ; 0xf183e
+ retn ; c3 ; 0xf183f
+ ; disGetNextSymbol 0xf1840 LB 0x8805 -> off=0x0 cb=0000000000000027 uValue=00000000000f0240 'print_bios_banner'
+print_bios_banner: ; 0xf1840 LB 0x27
+ push bp ; 55 ; 0xf1840 bios.c:151
+ mov bp, sp ; 89 e5 ; 0xf1841
+ mov bx, strict word 00072h ; bb 72 00 ; 0xf1843 bios.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf1846
+ mov es, ax ; 8e c0 ; 0xf1849
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf184b
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf184e bios.c:53
+ cmp ax, 01234h ; 3d 34 12 ; 0xf1853 bios.c:157
+ jne short 01860h ; 75 08 ; 0xf1856
+ mov AL, strict byte 003h ; b0 03 ; 0xf1858 bios.c:160
+ mov AH, strict byte 000h ; b4 00 ; 0xf185a
+ int 010h ; cd 10 ; 0xf185c
+ jmp short 01863h ; eb 03 ; 0xf185e bios.c:161
+ call 07a98h ; e8 35 62 ; 0xf1860 bios.c:164
+ mov sp, bp ; 89 ec ; 0xf1863 bios.c:191
+ pop bp ; 5d ; 0xf1865
+ retn ; c3 ; 0xf1866
+ ; disGetNextSymbol 0xf1867 LB 0x87de -> off=0x0 cb=000000000000003b uValue=00000000000f0267 'send'
+send: ; 0xf1867 LB 0x3b
+ push bp ; 55 ; 0xf1867 print.c:72
+ mov bp, sp ; 89 e5 ; 0xf1868
+ push bx ; 53 ; 0xf186a
+ push cx ; 51 ; 0xf186b
+ mov bx, ax ; 89 c3 ; 0xf186c
+ mov cl, dl ; 88 d1 ; 0xf186e
+ test AL, strict byte 008h ; a8 08 ; 0xf1870 print.c:80
+ je short 0187ah ; 74 06 ; 0xf1872
+ mov al, dl ; 88 d0 ; 0xf1874 print.c:81
+ mov dx, 00403h ; ba 03 04 ; 0xf1876
+ out DX, AL ; ee ; 0xf1879
+ test bl, 004h ; f6 c3 04 ; 0xf187a print.c:82
+ je short 01885h ; 74 06 ; 0xf187d
+ mov al, cl ; 88 c8 ; 0xf187f print.c:83
+ mov dx, 00504h ; ba 04 05 ; 0xf1881
+ out DX, AL ; ee ; 0xf1884
+ test bl, 002h ; f6 c3 02 ; 0xf1885 print.c:85
+ je short 0189bh ; 74 11 ; 0xf1888
+ cmp cl, 00ah ; 80 f9 0a ; 0xf188a print.c:86
+ jne short 01895h ; 75 06 ; 0xf188d
+ mov AL, strict byte 00dh ; b0 0d ; 0xf188f print.c:87
+ mov AH, strict byte 00eh ; b4 0e ; 0xf1891
+ int 010h ; cd 10 ; 0xf1893
+ mov al, cl ; 88 c8 ; 0xf1895 print.c:88
+ mov AH, strict byte 00eh ; b4 0e ; 0xf1897
+ int 010h ; cd 10 ; 0xf1899
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf189b print.c:90
+ pop cx ; 59 ; 0xf189e
+ pop bx ; 5b ; 0xf189f
+ pop bp ; 5d ; 0xf18a0
+ retn ; c3 ; 0xf18a1
+ ; disGetNextSymbol 0xf18a2 LB 0x87a3 -> off=0x0 cb=000000000000005f uValue=00000000000f02a2 'put_int'
+put_int: ; 0xf18a2 LB 0x5f
+ push bp ; 55 ; 0xf18a2 print.c:92
+ mov bp, sp ; 89 e5 ; 0xf18a3
+ push si ; 56 ; 0xf18a5
+ push di ; 57 ; 0xf18a6
+ push ax ; 50 ; 0xf18a7
+ push ax ; 50 ; 0xf18a8
+ mov si, ax ; 89 c6 ; 0xf18a9
+ mov word [bp-008h], dx ; 89 56 f8 ; 0xf18ab
+ mov di, strict word 0000ah ; bf 0a 00 ; 0xf18ae print.c:94
+ mov ax, dx ; 89 d0 ; 0xf18b1
+ cwd ; 99 ; 0xf18b3
+ idiv di ; f7 ff ; 0xf18b4
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf18b6
+ test ax, ax ; 85 c0 ; 0xf18b9 print.c:95
+ je short 018c7h ; 74 0a ; 0xf18bb
+ dec bx ; 4b ; 0xf18bd print.c:96
+ mov dx, ax ; 89 c2 ; 0xf18be
+ mov ax, si ; 89 f0 ; 0xf18c0
+ call 018a2h ; e8 dd ff ; 0xf18c2
+ jmp short 018e2h ; eb 1b ; 0xf18c5 print.c:97
+ dec bx ; 4b ; 0xf18c7 print.c:98
+ test bx, bx ; 85 db ; 0xf18c8
+ jle short 018d6h ; 7e 0a ; 0xf18ca
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf18cc print.c:99
+ mov ax, si ; 89 f0 ; 0xf18cf
+ call 01867h ; e8 93 ff ; 0xf18d1
+ jmp short 018c7h ; eb f1 ; 0xf18d4
+ test cx, cx ; 85 c9 ; 0xf18d6 print.c:100
+ je short 018e2h ; 74 08 ; 0xf18d8
+ mov dx, strict word 0002dh ; ba 2d 00 ; 0xf18da print.c:101
+ mov ax, si ; 89 f0 ; 0xf18dd
+ call 01867h ; e8 85 ff ; 0xf18df
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf18e2 print.c:103
+ mov DL, strict byte 00ah ; b2 0a ; 0xf18e5
+ mul dl ; f6 e2 ; 0xf18e7
+ mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xf18e9
+ sub dl, al ; 28 c2 ; 0xf18ec
+ mov al, dl ; 88 d0 ; 0xf18ee
+ add AL, strict byte 030h ; 04 30 ; 0xf18f0
+ movzx dx, al ; 0f b6 d0 ; 0xf18f2
+ mov ax, si ; 89 f0 ; 0xf18f5
+ call 01867h ; e8 6d ff ; 0xf18f7
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf18fa print.c:104
+ pop di ; 5f ; 0xf18fd
+ pop si ; 5e ; 0xf18fe
+ pop bp ; 5d ; 0xf18ff
+ retn ; c3 ; 0xf1900
+ ; disGetNextSymbol 0xf1901 LB 0x8744 -> off=0x0 cb=0000000000000060 uValue=00000000000f0301 'put_uint'
+put_uint: ; 0xf1901 LB 0x60
+ push bp ; 55 ; 0xf1901 print.c:106
+ mov bp, sp ; 89 e5 ; 0xf1902
+ push si ; 56 ; 0xf1904
+ push di ; 57 ; 0xf1905
+ push ax ; 50 ; 0xf1906
+ push ax ; 50 ; 0xf1907
+ mov si, ax ; 89 c6 ; 0xf1908
+ mov word [bp-008h], dx ; 89 56 f8 ; 0xf190a
+ mov ax, dx ; 89 d0 ; 0xf190d print.c:108
+ xor dx, dx ; 31 d2 ; 0xf190f
+ mov di, strict word 0000ah ; bf 0a 00 ; 0xf1911
+ div di ; f7 f7 ; 0xf1914
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf1916
+ test ax, ax ; 85 c0 ; 0xf1919 print.c:109
+ je short 01927h ; 74 0a ; 0xf191b
+ dec bx ; 4b ; 0xf191d print.c:110
+ mov dx, ax ; 89 c2 ; 0xf191e
+ mov ax, si ; 89 f0 ; 0xf1920
+ call 01901h ; e8 dc ff ; 0xf1922
+ jmp short 01942h ; eb 1b ; 0xf1925 print.c:111
+ dec bx ; 4b ; 0xf1927 print.c:112
+ test bx, bx ; 85 db ; 0xf1928
+ jle short 01936h ; 7e 0a ; 0xf192a
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf192c print.c:113
+ mov ax, si ; 89 f0 ; 0xf192f
+ call 01867h ; e8 33 ff ; 0xf1931
+ jmp short 01927h ; eb f1 ; 0xf1934
+ test cx, cx ; 85 c9 ; 0xf1936 print.c:114
+ je short 01942h ; 74 08 ; 0xf1938
+ mov dx, strict word 0002dh ; ba 2d 00 ; 0xf193a print.c:115
+ mov ax, si ; 89 f0 ; 0xf193d
+ call 01867h ; e8 25 ff ; 0xf193f
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf1942 print.c:117
+ mov DL, strict byte 00ah ; b2 0a ; 0xf1945
+ mul dl ; f6 e2 ; 0xf1947
+ mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xf1949
+ sub dl, al ; 28 c2 ; 0xf194c
+ mov al, dl ; 88 d0 ; 0xf194e
+ add AL, strict byte 030h ; 04 30 ; 0xf1950
+ movzx dx, al ; 0f b6 d0 ; 0xf1952
+ mov ax, si ; 89 f0 ; 0xf1955
+ call 01867h ; e8 0d ff ; 0xf1957
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf195a print.c:118
+ pop di ; 5f ; 0xf195d
+ pop si ; 5e ; 0xf195e
+ pop bp ; 5d ; 0xf195f
+ retn ; c3 ; 0xf1960
+ ; disGetNextSymbol 0xf1961 LB 0x86e4 -> off=0x0 cb=0000000000000072 uValue=00000000000f0361 'put_luint'
+put_luint: ; 0xf1961 LB 0x72
+ push bp ; 55 ; 0xf1961 print.c:120
+ mov bp, sp ; 89 e5 ; 0xf1962
+ push si ; 56 ; 0xf1964
+ push di ; 57 ; 0xf1965
+ push ax ; 50 ; 0xf1966
+ push ax ; 50 ; 0xf1967
+ mov si, ax ; 89 c6 ; 0xf1968
+ mov word [bp-006h], bx ; 89 5e fa ; 0xf196a
+ mov di, dx ; 89 d7 ; 0xf196d
+ mov ax, bx ; 89 d8 ; 0xf196f print.c:122
+ mov dx, cx ; 89 ca ; 0xf1971
+ mov bx, strict word 0000ah ; bb 0a 00 ; 0xf1973
+ xor cx, cx ; 31 c9 ; 0xf1976
+ call 09f50h ; e8 d5 85 ; 0xf1978
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf197b
+ mov cx, dx ; 89 d1 ; 0xf197e
+ mov dx, ax ; 89 c2 ; 0xf1980 print.c:123
+ or dx, cx ; 09 ca ; 0xf1982
+ je short 01995h ; 74 0f ; 0xf1984
+ push word [bp+004h] ; ff 76 04 ; 0xf1986 print.c:124
+ lea dx, [di-001h] ; 8d 55 ff ; 0xf1989
+ mov bx, ax ; 89 c3 ; 0xf198c
+ mov ax, si ; 89 f0 ; 0xf198e
+ call 01961h ; e8 ce ff ; 0xf1990
+ jmp short 019b2h ; eb 1d ; 0xf1993 print.c:125
+ dec di ; 4f ; 0xf1995 print.c:126
+ test di, di ; 85 ff ; 0xf1996
+ jle short 019a4h ; 7e 0a ; 0xf1998
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf199a print.c:127
+ mov ax, si ; 89 f0 ; 0xf199d
+ call 01867h ; e8 c5 fe ; 0xf199f
+ jmp short 01995h ; eb f1 ; 0xf19a2
+ cmp word [bp+004h], strict byte 00000h ; 83 7e 04 00 ; 0xf19a4 print.c:128
+ je short 019b2h ; 74 08 ; 0xf19a8
+ mov dx, strict word 0002dh ; ba 2d 00 ; 0xf19aa print.c:129
+ mov ax, si ; 89 f0 ; 0xf19ad
+ call 01867h ; e8 b5 fe ; 0xf19af
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf19b2 print.c:131
+ mov DL, strict byte 00ah ; b2 0a ; 0xf19b5
+ mul dl ; f6 e2 ; 0xf19b7
+ mov dl, byte [bp-006h] ; 8a 56 fa ; 0xf19b9
+ sub dl, al ; 28 c2 ; 0xf19bc
+ mov al, dl ; 88 d0 ; 0xf19be
+ add AL, strict byte 030h ; 04 30 ; 0xf19c0
+ movzx dx, al ; 0f b6 d0 ; 0xf19c2
+ mov ax, si ; 89 f0 ; 0xf19c5
+ call 01867h ; e8 9d fe ; 0xf19c7
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf19ca print.c:132
+ pop di ; 5f ; 0xf19cd
+ pop si ; 5e ; 0xf19ce
+ pop bp ; 5d ; 0xf19cf
+ retn 00002h ; c2 02 00 ; 0xf19d0
+ ; disGetNextSymbol 0xf19d3 LB 0x8672 -> off=0x0 cb=0000000000000021 uValue=00000000000f03d3 'put_str'
+put_str: ; 0xf19d3 LB 0x21
+ push bp ; 55 ; 0xf19d3 print.c:134
+ mov bp, sp ; 89 e5 ; 0xf19d4
+ push dx ; 52 ; 0xf19d6
+ push si ; 56 ; 0xf19d7
+ mov si, ax ; 89 c6 ; 0xf19d8
+ mov es, cx ; 8e c1 ; 0xf19da print.c:138
+ mov dl, byte [es:bx] ; 26 8a 17 ; 0xf19dc
+ test dl, dl ; 84 d2 ; 0xf19df
+ je short 019edh ; 74 0a ; 0xf19e1
+ xor dh, dh ; 30 f6 ; 0xf19e3 print.c:139
+ mov ax, si ; 89 f0 ; 0xf19e5
+ call 01867h ; e8 7d fe ; 0xf19e7
+ inc bx ; 43 ; 0xf19ea print.c:140
+ jmp short 019dah ; eb ed ; 0xf19eb print.c:141
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf19ed print.c:142
+ pop si ; 5e ; 0xf19f0
+ pop dx ; 5a ; 0xf19f1
+ pop bp ; 5d ; 0xf19f2
+ retn ; c3 ; 0xf19f3
+ ; disGetNextSymbol 0xf19f4 LB 0x8651 -> off=0x0 cb=0000000000000020 uValue=00000000000f03f4 'put_str_near'
+put_str_near: ; 0xf19f4 LB 0x20
+ push bp ; 55 ; 0xf19f4 print.c:144
+ mov bp, sp ; 89 e5 ; 0xf19f5
+ push bx ; 53 ; 0xf19f7
+ push cx ; 51 ; 0xf19f8
+ mov cx, ax ; 89 c1 ; 0xf19f9
+ mov bx, dx ; 89 d3 ; 0xf19fb
+ mov dl, byte [bx] ; 8a 17 ; 0xf19fd print.c:148
+ test dl, dl ; 84 d2 ; 0xf19ff
+ je short 01a0dh ; 74 0a ; 0xf1a01
+ xor dh, dh ; 30 f6 ; 0xf1a03 print.c:149
+ mov ax, cx ; 89 c8 ; 0xf1a05
+ call 01867h ; e8 5d fe ; 0xf1a07
+ inc bx ; 43 ; 0xf1a0a print.c:150
+ jmp short 019fdh ; eb f0 ; 0xf1a0b print.c:151
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf1a0d print.c:152
+ pop cx ; 59 ; 0xf1a10
+ pop bx ; 5b ; 0xf1a11
+ pop bp ; 5d ; 0xf1a12
+ retn ; c3 ; 0xf1a13
+ ; disGetNextSymbol 0xf1a14 LB 0x8631 -> off=0x0 cb=000000000000033d uValue=00000000000f0414 'bios_printf'
+bios_printf: ; 0xf1a14 LB 0x33d
+ push bp ; 55 ; 0xf1a14 print.c:165
+ mov bp, sp ; 89 e5 ; 0xf1a15
+ push bx ; 53 ; 0xf1a17
+ push cx ; 51 ; 0xf1a18
+ push dx ; 52 ; 0xf1a19
+ push si ; 56 ; 0xf1a1a
+ push di ; 57 ; 0xf1a1b
+ sub sp, strict byte 0001ch ; 83 ec 1c ; 0xf1a1c
+ lea bx, [bp+008h] ; 8d 5e 08 ; 0xf1a1f print.c:173
+ mov word [bp-016h], bx ; 89 5e ea ; 0xf1a22
+ mov [bp-014h], ss ; 8c 56 ec ; 0xf1a25
+ xor bx, bx ; 31 db ; 0xf1a28 print.c:175
+ xor di, di ; 31 ff ; 0xf1a2a print.c:176
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1a2c print.c:178
+ and ax, strict word 00007h ; 25 07 00 ; 0xf1a2f
+ cmp ax, strict word 00007h ; 3d 07 00 ; 0xf1a32
+ jne short 01a42h ; 75 0b ; 0xf1a35
+ push 000f0h ; 68 f0 00 ; 0xf1a37 print.c:179
+ push strict byte 00002h ; 6a 02 ; 0xf1a3a
+ call 01a14h ; e8 d5 ff ; 0xf1a3c
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf1a3f
+ mov si, word [bp+006h] ; 8b 76 06 ; 0xf1a42 print.c:182
+ mov dl, byte [si] ; 8a 14 ; 0xf1a45
+ test dl, dl ; 84 d2 ; 0xf1a47
+ je near 01d35h ; 0f 84 e8 02 ; 0xf1a49
+ cmp dl, 025h ; 80 fa 25 ; 0xf1a4d print.c:183
+ jne short 01a5ah ; 75 08 ; 0xf1a50
+ mov bx, strict word 00001h ; bb 01 00 ; 0xf1a52 print.c:184
+ xor di, di ; 31 ff ; 0xf1a55 print.c:185
+ jmp near 01d2fh ; e9 d5 02 ; 0xf1a57 print.c:187
+ test bx, bx ; 85 db ; 0xf1a5a
+ je near 01d27h ; 0f 84 c7 02 ; 0xf1a5c
+ cmp dl, 030h ; 80 fa 30 ; 0xf1a60 print.c:188
+ jc short 01a78h ; 72 13 ; 0xf1a63
+ cmp dl, 039h ; 80 fa 39 ; 0xf1a65
+ jnbe short 01a78h ; 77 0e ; 0xf1a68
+ movzx ax, dl ; 0f b6 c2 ; 0xf1a6a print.c:189
+ imul di, di, strict byte 0000ah ; 6b ff 0a ; 0xf1a6d
+ sub ax, strict word 00030h ; 2d 30 00 ; 0xf1a70
+ add di, ax ; 01 c7 ; 0xf1a73
+ jmp near 01d2fh ; e9 b7 02 ; 0xf1a75 print.c:191
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1a78 print.c:192
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1a7b
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1a7e
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1a82
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1a85
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf1a89
+ cmp dl, 078h ; 80 fa 78 ; 0xf1a8c print.c:193
+ je short 01a96h ; 74 05 ; 0xf1a8f
+ cmp dl, 058h ; 80 fa 58 ; 0xf1a91
+ jne short 01aech ; 75 56 ; 0xf1a94
+ test di, di ; 85 ff ; 0xf1a96 print.c:194
+ jne short 01a9dh ; 75 03 ; 0xf1a98
+ mov di, strict word 00004h ; bf 04 00 ; 0xf1a9a print.c:195
+ cmp dl, 078h ; 80 fa 78 ; 0xf1a9d print.c:196
+ jne short 01aa9h ; 75 07 ; 0xf1aa0
+ mov word [bp-00eh], strict word 00061h ; c7 46 f2 61 00 ; 0xf1aa2 print.c:197
+ jmp short 01aaeh ; eb 05 ; 0xf1aa7 print.c:198
+ mov word [bp-00eh], strict word 00041h ; c7 46 f2 41 00 ; 0xf1aa9 print.c:199
+ lea ax, [di-001h] ; 8d 45 ff ; 0xf1aae print.c:200
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf1ab1
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf1ab4
+ test ax, ax ; 85 c0 ; 0xf1ab7
+ jl near 01d23h ; 0f 8c 66 02 ; 0xf1ab9
+ mov cx, ax ; 89 c1 ; 0xf1abd print.c:201
+ sal cx, 002h ; c1 e1 02 ; 0xf1abf
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf1ac2
+ shr ax, CL ; d3 e8 ; 0xf1ac5
+ xor ah, ah ; 30 e4 ; 0xf1ac7
+ and AL, strict byte 00fh ; 24 0f ; 0xf1ac9
+ cmp ax, strict word 00009h ; 3d 09 00 ; 0xf1acb print.c:202
+ jnbe short 01ad7h ; 77 07 ; 0xf1ace
+ mov dx, ax ; 89 c2 ; 0xf1ad0
+ add dx, strict byte 00030h ; 83 c2 30 ; 0xf1ad2
+ jmp short 01adfh ; eb 08 ; 0xf1ad5
+ sub ax, strict word 0000ah ; 2d 0a 00 ; 0xf1ad7
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf1ada
+ add dx, ax ; 01 c2 ; 0xf1add
+ xor dh, dh ; 30 f6 ; 0xf1adf
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1ae1
+ call 01867h ; e8 80 fd ; 0xf1ae4
+ dec word [bp-00ch] ; ff 4e f4 ; 0xf1ae7 print.c:203
+ jmp short 01ab4h ; eb c8 ; 0xf1aea
+ cmp dl, 075h ; 80 fa 75 ; 0xf1aec print.c:205
+ jne short 01b00h ; 75 0f ; 0xf1aef
+ xor cx, cx ; 31 c9 ; 0xf1af1 print.c:206
+ mov bx, di ; 89 fb ; 0xf1af3
+ mov dx, ax ; 89 c2 ; 0xf1af5
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1af7
+ call 01901h ; e8 04 fe ; 0xf1afa
+ jmp near 01d23h ; e9 23 02 ; 0xf1afd print.c:208
+ cmp dl, 06ch ; 80 fa 6c ; 0xf1b00
+ jne near 01be2h ; 0f 85 db 00 ; 0xf1b03
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf1b07
+ cmp dl, byte [bx+001h] ; 3a 57 01 ; 0xf1b0a
+ jne near 01be2h ; 0f 85 d1 00 ; 0xf1b0d
+ add word [bp+006h], strict byte 00002h ; 83 46 06 02 ; 0xf1b11 print.c:212
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf1b15 print.c:213
+ mov dl, byte [bx] ; 8a 17 ; 0xf1b18
+ mov word [bp-026h], ax ; 89 46 da ; 0xf1b1a print.c:215
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1b1d print.c:216
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1b20
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1b23
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1b27
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1b2a
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf1b2e
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1b31 print.c:217
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1b34
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1b37
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1b3b
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1b3e
+ mov word [bp-022h], ax ; 89 46 de ; 0xf1b42
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1b45 print.c:218
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1b48
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1b4b
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1b4f
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1b52
+ mov word [bp-020h], ax ; 89 46 e0 ; 0xf1b56
+ cmp dl, 078h ; 80 fa 78 ; 0xf1b59 print.c:219
+ je short 01b63h ; 74 05 ; 0xf1b5c
+ cmp dl, 058h ; 80 fa 58 ; 0xf1b5e
+ jne short 01bd4h ; 75 71 ; 0xf1b61
+ test di, di ; 85 ff ; 0xf1b63 print.c:220
+ jne short 01b6ah ; 75 03 ; 0xf1b65
+ mov di, strict word 00010h ; bf 10 00 ; 0xf1b67 print.c:221
+ cmp dl, 078h ; 80 fa 78 ; 0xf1b6a print.c:222
+ jne short 01b76h ; 75 07 ; 0xf1b6d
+ mov word [bp-00eh], strict word 00061h ; c7 46 f2 61 00 ; 0xf1b6f print.c:223
+ jmp short 01b7bh ; eb 05 ; 0xf1b74 print.c:224
+ mov word [bp-00eh], strict word 00041h ; c7 46 f2 41 00 ; 0xf1b76 print.c:225
+ lea ax, [di-001h] ; 8d 45 ff ; 0xf1b7b print.c:226
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf1b7e
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf1b81
+ test ax, ax ; 85 c0 ; 0xf1b84
+ jl near 01d23h ; 0f 8c 99 01 ; 0xf1b86
+ sal ax, 002h ; c1 e0 02 ; 0xf1b8a print.c:227
+ mov word [bp-01eh], ax ; 89 46 e2 ; 0xf1b8d
+ xor ax, ax ; 31 c0 ; 0xf1b90
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf1b92
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf1b95
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf1b98
+ mov ax, word [bp-020h] ; 8b 46 e0 ; 0xf1b9b
+ mov bx, word [bp-022h] ; 8b 5e de ; 0xf1b9e
+ mov cx, word [bp-024h] ; 8b 4e dc ; 0xf1ba1
+ mov dx, word [bp-026h] ; 8b 56 da ; 0xf1ba4
+ mov si, word [bp-01eh] ; 8b 76 e2 ; 0xf1ba7
+ call 09f90h ; e8 e3 83 ; 0xf1baa
+ mov ax, dx ; 89 d0 ; 0xf1bad
+ xor ah, dh ; 30 f4 ; 0xf1baf
+ and AL, strict byte 00fh ; 24 0f ; 0xf1bb1
+ cmp ax, strict word 00009h ; 3d 09 00 ; 0xf1bb3 print.c:228
+ jnbe short 01bbfh ; 77 07 ; 0xf1bb6
+ mov dx, ax ; 89 c2 ; 0xf1bb8
+ add dx, strict byte 00030h ; 83 c2 30 ; 0xf1bba
+ jmp short 01bc7h ; eb 08 ; 0xf1bbd
+ sub ax, strict word 0000ah ; 2d 0a 00 ; 0xf1bbf
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf1bc2
+ add dx, ax ; 01 c2 ; 0xf1bc5
+ xor dh, dh ; 30 f6 ; 0xf1bc7
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1bc9
+ call 01867h ; e8 98 fc ; 0xf1bcc
+ dec word [bp-00ch] ; ff 4e f4 ; 0xf1bcf print.c:229
+ jmp short 01b81h ; eb ad ; 0xf1bd2
+ push 000f8h ; 68 f8 00 ; 0xf1bd4 print.c:231
+ push strict byte 00007h ; 6a 07 ; 0xf1bd7
+ call 01a14h ; e8 38 fe ; 0xf1bd9
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf1bdc
+ jmp near 01d23h ; e9 41 01 ; 0xf1bdf print.c:234
+ lea bx, [di-001h] ; 8d 5d ff ; 0xf1be2
+ cmp dl, 06ch ; 80 fa 6c ; 0xf1be5
+ jne near 01cabh ; 0f 85 bf 00 ; 0xf1be8
+ inc word [bp+006h] ; ff 46 06 ; 0xf1bec print.c:235
+ mov si, word [bp+006h] ; 8b 76 06 ; 0xf1bef print.c:236
+ mov dl, byte [si] ; 8a 14 ; 0xf1bf2
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1bf4 print.c:237
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1bf7
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1bfa
+ les si, [bp-016h] ; c4 76 ea ; 0xf1bfe
+ mov ax, word [es:si-002h] ; 26 8b 44 fe ; 0xf1c01
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf1c05
+ cmp dl, 064h ; 80 fa 64 ; 0xf1c08 print.c:238
+ jne short 01c3ah ; 75 2d ; 0xf1c0b
+ test byte [bp-00fh], 080h ; f6 46 f1 80 ; 0xf1c0d print.c:239
+ je short 01c28h ; 74 15 ; 0xf1c11
+ push strict byte 00001h ; 6a 01 ; 0xf1c13 print.c:240
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf1c15
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf1c18
+ neg cx ; f7 d9 ; 0xf1c1b
+ neg ax ; f7 d8 ; 0xf1c1d
+ sbb cx, strict byte 00000h ; 83 d9 00 ; 0xf1c1f
+ mov dx, bx ; 89 da ; 0xf1c22
+ mov bx, ax ; 89 c3 ; 0xf1c24
+ jmp short 01c31h ; eb 09 ; 0xf1c26 print.c:241
+ push strict byte 00000h ; 6a 00 ; 0xf1c28 print.c:242
+ mov bx, word [bp-012h] ; 8b 5e ee ; 0xf1c2a
+ mov dx, di ; 89 fa ; 0xf1c2d
+ mov cx, ax ; 89 c1 ; 0xf1c2f
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1c31
+ call 01961h ; e8 2a fd ; 0xf1c34
+ jmp near 01d23h ; e9 e9 00 ; 0xf1c37 print.c:244
+ cmp dl, 075h ; 80 fa 75 ; 0xf1c3a
+ jne short 01c41h ; 75 02 ; 0xf1c3d
+ jmp short 01c28h ; eb e7 ; 0xf1c3f
+ cmp dl, 078h ; 80 fa 78 ; 0xf1c41 print.c:247
+ je short 01c4dh ; 74 07 ; 0xf1c44
+ cmp dl, 058h ; 80 fa 58 ; 0xf1c46
+ jne near 01d23h ; 0f 85 d6 00 ; 0xf1c49
+ test di, di ; 85 ff ; 0xf1c4d print.c:249
+ jne short 01c54h ; 75 03 ; 0xf1c4f
+ mov di, strict word 00008h ; bf 08 00 ; 0xf1c51 print.c:250
+ cmp dl, 078h ; 80 fa 78 ; 0xf1c54 print.c:251
+ jne short 01c60h ; 75 07 ; 0xf1c57
+ mov word [bp-00eh], strict word 00061h ; c7 46 f2 61 00 ; 0xf1c59 print.c:252
+ jmp short 01c65h ; eb 05 ; 0xf1c5e print.c:253
+ mov word [bp-00eh], strict word 00041h ; c7 46 f2 41 00 ; 0xf1c60 print.c:254
+ lea ax, [di-001h] ; 8d 45 ff ; 0xf1c65 print.c:255
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf1c68
+ cmp word [bp-00ch], strict byte 00000h ; 83 7e f4 00 ; 0xf1c6b
+ jl near 01d23h ; 0f 8c b0 00 ; 0xf1c6f
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf1c73 print.c:256
+ mov cx, word [bp-00ch] ; 8b 4e f4 ; 0xf1c76
+ sal cx, 002h ; c1 e1 02 ; 0xf1c79
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf1c7c
+ jcxz 01c87h ; e3 06 ; 0xf1c7f
+ shr dx, 1 ; d1 ea ; 0xf1c81
+ rcr ax, 1 ; d1 d8 ; 0xf1c83
+ loop 01c81h ; e2 fa ; 0xf1c85
+ and ax, strict word 0000fh ; 25 0f 00 ; 0xf1c87
+ cmp ax, strict word 00009h ; 3d 09 00 ; 0xf1c8a print.c:257
+ jnbe short 01c96h ; 77 07 ; 0xf1c8d
+ mov dx, ax ; 89 c2 ; 0xf1c8f
+ add dx, strict byte 00030h ; 83 c2 30 ; 0xf1c91
+ jmp short 01c9eh ; eb 08 ; 0xf1c94
+ sub ax, strict word 0000ah ; 2d 0a 00 ; 0xf1c96
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf1c99
+ add dx, ax ; 01 c2 ; 0xf1c9c
+ xor dh, dh ; 30 f6 ; 0xf1c9e
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1ca0
+ call 01867h ; e8 c1 fb ; 0xf1ca3
+ dec word [bp-00ch] ; ff 4e f4 ; 0xf1ca6 print.c:258
+ jmp short 01c6bh ; eb c0 ; 0xf1ca9
+ cmp dl, 064h ; 80 fa 64 ; 0xf1cab print.c:261
+ jne short 01ccfh ; 75 1f ; 0xf1cae
+ test byte [bp-011h], 080h ; f6 46 ef 80 ; 0xf1cb0 print.c:262
+ je short 01cc0h ; 74 0a ; 0xf1cb4
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf1cb6 print.c:263
+ neg dx ; f7 da ; 0xf1cb9
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf1cbb
+ jmp short 01cc7h ; eb 07 ; 0xf1cbe print.c:264
+ xor cx, cx ; 31 c9 ; 0xf1cc0 print.c:265
+ mov bx, di ; 89 fb ; 0xf1cc2
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf1cc4
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1cc7
+ call 018a2h ; e8 d5 fb ; 0xf1cca
+ jmp short 01d23h ; eb 54 ; 0xf1ccd print.c:267
+ cmp dl, 073h ; 80 fa 73 ; 0xf1ccf
+ jne short 01ce1h ; 75 0d ; 0xf1cd2
+ mov cx, ds ; 8c d9 ; 0xf1cd4 print.c:268
+ mov bx, word [bp-012h] ; 8b 5e ee ; 0xf1cd6
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1cd9
+ call 019d3h ; e8 f4 fc ; 0xf1cdc
+ jmp short 01d23h ; eb 42 ; 0xf1cdf print.c:270
+ cmp dl, 053h ; 80 fa 53 ; 0xf1ce1
+ jne short 01d07h ; 75 21 ; 0xf1ce4
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf1ce6 print.c:271
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf1ce9
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1cec print.c:272
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1cef
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1cf2
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1cf6
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1cf9
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf1cfd
+ mov bx, ax ; 89 c3 ; 0xf1d00 print.c:273
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf1d02
+ jmp short 01cd9h ; eb d2 ; 0xf1d05
+ cmp dl, 063h ; 80 fa 63 ; 0xf1d07 print.c:275
+ jne short 01d18h ; 75 0c ; 0xf1d0a
+ movzx dx, byte [bp-012h] ; 0f b6 56 ee ; 0xf1d0c print.c:276
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1d10
+ call 01867h ; e8 51 fb ; 0xf1d13
+ jmp short 01d23h ; eb 0b ; 0xf1d16 print.c:278
+ push 00119h ; 68 19 01 ; 0xf1d18 print.c:279
+ push strict byte 00007h ; 6a 07 ; 0xf1d1b
+ call 01a14h ; e8 f4 fc ; 0xf1d1d
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf1d20
+ xor bx, bx ; 31 db ; 0xf1d23 print.c:280
+ jmp short 01d2fh ; eb 08 ; 0xf1d25 print.c:283
+ xor dh, dh ; 30 f6 ; 0xf1d27 print.c:284
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1d29
+ call 01867h ; e8 38 fb ; 0xf1d2c
+ inc word [bp+006h] ; ff 46 06 ; 0xf1d2f print.c:286
+ jmp near 01a42h ; e9 0d fd ; 0xf1d32 print.c:287
+ xor ax, ax ; 31 c0 ; 0xf1d35 print.c:288
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf1d37
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1d3a
+ test byte [bp+004h], 001h ; f6 46 04 01 ; 0xf1d3d print.c:289
+ je short 01d47h ; 74 04 ; 0xf1d41
+ cli ; fa ; 0xf1d43 print.c:291
+ hlt ; f4 ; 0xf1d44 print.c:292
+ jmp short 01d44h ; eb fd ; 0xf1d45
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf1d47 print.c:294
+ pop di ; 5f ; 0xf1d4a
+ pop si ; 5e ; 0xf1d4b
+ pop dx ; 5a ; 0xf1d4c
+ pop cx ; 59 ; 0xf1d4d
+ pop bx ; 5b ; 0xf1d4e
+ pop bp ; 5d ; 0xf1d4f
+ retn ; c3 ; 0xf1d50
+ ; disGetNextSymbol 0xf1d51 LB 0x82f4 -> off=0x0 cb=00000000000000cc uValue=00000000000f0751 'ata_init'
+ata_init: ; 0xf1d51 LB 0xcc
+ push si ; 56 ; 0xf1d51 ata.c:97
+ push bp ; 55 ; 0xf1d52
+ mov bp, sp ; 89 e5 ; 0xf1d53
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf1d55 ata.c:48
+ mov si, strict word 00040h ; be 40 00 ; 0xf1d58
+ mov es, si ; 8e c6 ; 0xf1d5b
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf1d5d
+ mov si, 00122h ; be 22 01 ; 0xf1d60 ata.c:49
+ mov dx, bx ; 89 da ; 0xf1d63
+ xor al, al ; 30 c0 ; 0xf1d65 ata.c:105
+ jmp short 01d6dh ; eb 04 ; 0xf1d67
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf1d69
+ jnc short 01d91h ; 73 24 ; 0xf1d6b
+ movzx bx, al ; 0f b6 d8 ; 0xf1d6d ata.c:106
+ imul bx, bx, strict byte 00006h ; 6b db 06 ; 0xf1d70
+ mov es, dx ; 8e c2 ; 0xf1d73
+ add bx, si ; 01 f3 ; 0xf1d75
+ mov byte [es:bx+00204h], 000h ; 26 c6 87 04 02 00 ; 0xf1d77
+ db 066h, 026h, 0c7h, 087h, 006h, 002h, 000h, 000h, 000h, 000h
+ ; mov dword [es:bx+00206h], strict dword 000000000h ; 66 26 c7 87 06 02 00 00 00 00; 0xf1d7d ata.c:107
+ mov byte [es:bx+00205h], 000h ; 26 c6 87 05 02 00 ; 0xf1d87 ata.c:109
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf1d8d ata.c:110
+ jmp short 01d69h ; eb d8 ; 0xf1d8f
+ xor al, al ; 30 c0 ; 0xf1d91 ata.c:113
+ jmp short 01d99h ; eb 04 ; 0xf1d93
+ cmp AL, strict byte 008h ; 3c 08 ; 0xf1d95
+ jnc short 01dedh ; 73 54 ; 0xf1d97
+ movzx bx, al ; 0f b6 d8 ; 0xf1d99 ata.c:114
+ imul bx, bx, strict byte 0001ch ; 6b db 1c ; 0xf1d9c
+ mov es, dx ; 8e c2 ; 0xf1d9f
+ add bx, si ; 01 f3 ; 0xf1da1
+ db 066h, 026h, 0c7h, 047h, 022h, 000h, 000h, 000h, 000h
+ ; mov dword [es:bx+022h], strict dword 000000000h ; 66 26 c7 47 22 00 00 00 00; 0xf1da3
+ mov byte [es:bx+026h], 000h ; 26 c6 47 26 00 ; 0xf1dac ata.c:118
+ mov word [es:bx+028h], 00200h ; 26 c7 47 28 00 02 ; 0xf1db1 ata.c:119
+ mov byte [es:bx+027h], 000h ; 26 c6 47 27 00 ; 0xf1db7 ata.c:120
+ db 066h, 026h, 0c7h, 047h, 02ah, 000h, 000h, 000h, 000h
+ ; mov dword [es:bx+02ah], strict dword 000000000h ; 66 26 c7 47 2a 00 00 00 00; 0xf1dbc ata.c:121
+ db 066h, 026h, 0c7h, 047h, 02eh, 000h, 000h, 000h, 000h
+ ; mov dword [es:bx+02eh], strict dword 000000000h ; 66 26 c7 47 2e 00 00 00 00; 0xf1dc5 ata.c:123
+ db 066h, 026h, 0c7h, 047h, 032h, 000h, 000h, 000h, 000h
+ ; mov dword [es:bx+032h], strict dword 000000000h ; 66 26 c7 47 32 00 00 00 00; 0xf1dce ata.c:125
+ db 066h, 026h, 0c7h, 047h, 03ah, 000h, 000h, 000h, 000h
+ ; mov dword [es:bx+03ah], strict dword 000000000h ; 66 26 c7 47 3a 00 00 00 00; 0xf1dd7 ata.c:127
+ db 066h, 026h, 0c7h, 047h, 036h, 000h, 000h, 000h, 000h
+ ; mov dword [es:bx+036h], strict dword 000000000h ; 66 26 c7 47 36 00 00 00 00; 0xf1de0
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf1de9 ata.c:128
+ jmp short 01d95h ; eb a8 ; 0xf1deb
+ xor al, al ; 30 c0 ; 0xf1ded ata.c:131
+ jmp short 01df5h ; eb 04 ; 0xf1def
+ cmp AL, strict byte 010h ; 3c 10 ; 0xf1df1
+ jnc short 01e0ch ; 73 17 ; 0xf1df3
+ movzx bx, al ; 0f b6 d8 ; 0xf1df5 ata.c:132
+ mov es, dx ; 8e c2 ; 0xf1df8
+ add bx, si ; 01 f3 ; 0xf1dfa
+ mov byte [es:bx+001e3h], 010h ; 26 c6 87 e3 01 10 ; 0xf1dfc
+ mov byte [es:bx+001f4h], 010h ; 26 c6 87 f4 01 10 ; 0xf1e02 ata.c:133
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf1e08 ata.c:134
+ jmp short 01df1h ; eb e5 ; 0xf1e0a
+ mov es, dx ; 8e c2 ; 0xf1e0c ata.c:136
+ mov byte [es:si+001e2h], 000h ; 26 c6 84 e2 01 00 ; 0xf1e0e
+ mov byte [es:si+001f3h], 000h ; 26 c6 84 f3 01 00 ; 0xf1e14 ata.c:137
+ pop bp ; 5d ; 0xf1e1a ata.c:138
+ pop si ; 5e ; 0xf1e1b
+ retn ; c3 ; 0xf1e1c
+ ; disGetNextSymbol 0xf1e1d LB 0x8228 -> off=0x0 cb=00000000000000dd uValue=00000000000f081d 'ata_reset'
+ata_reset: ; 0xf1e1d LB 0xdd
+ push bp ; 55 ; 0xf1e1d ata.c:146
+ mov bp, sp ; 89 e5 ; 0xf1e1e
+ push bx ; 53 ; 0xf1e20
+ push cx ; 51 ; 0xf1e21
+ push dx ; 52 ; 0xf1e22
+ push si ; 56 ; 0xf1e23
+ push di ; 57 ; 0xf1e24
+ push ax ; 50 ; 0xf1e25
+ push ax ; 50 ; 0xf1e26
+ push ax ; 50 ; 0xf1e27
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf1e28 ata.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf1e2b
+ mov es, ax ; 8e c0 ; 0xf1e2e
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf1e30
+ mov di, 00122h ; bf 22 01 ; 0xf1e33 ata.c:49
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf1e36
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf1e39 ata.c:155
+ shr dx, 1 ; d1 ea ; 0xf1e3c
+ mov dh, byte [bp-010h] ; 8a 76 f0 ; 0xf1e3e ata.c:156
+ and dh, 001h ; 80 e6 01 ; 0xf1e41
+ mov byte [bp-00ch], dh ; 88 76 f4 ; 0xf1e44
+ xor dh, dh ; 30 f6 ; 0xf1e47 ata.c:158
+ imul bx, dx, strict byte 00006h ; 6b da 06 ; 0xf1e49
+ mov es, ax ; 8e c0 ; 0xf1e4c
+ add bx, di ; 01 fb ; 0xf1e4e
+ mov cx, word [es:bx+00206h] ; 26 8b 8f 06 02 ; 0xf1e50
+ mov si, word [es:bx+00208h] ; 26 8b b7 08 02 ; 0xf1e55 ata.c:159
+ lea dx, [si+006h] ; 8d 54 06 ; 0xf1e5a ata.c:164
+ mov AL, strict byte 00eh ; b0 0e ; 0xf1e5d
+ out DX, AL ; ee ; 0xf1e5f
+ mov bx, 000ffh ; bb ff 00 ; 0xf1e60 ata.c:167
+ dec bx ; 4b ; 0xf1e63 ata.c:168
+ test bx, bx ; 85 db ; 0xf1e64
+ jbe short 01e74h ; 76 0c ; 0xf1e66
+ mov dx, cx ; 89 ca ; 0xf1e68 ata.c:169
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1e6a
+ in AL, DX ; ec ; 0xf1e6d
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1e6e
+ test AL, strict byte 080h ; a8 80 ; 0xf1e70 ata.c:170
+ je short 01e63h ; 74 ef ; 0xf1e72
+ lea dx, [si+006h] ; 8d 54 06 ; 0xf1e74 ata.c:175
+ mov AL, strict byte 00ah ; b0 0a ; 0xf1e77
+ out DX, AL ; ee ; 0xf1e79
+ imul bx, word [bp-010h], strict byte 0001ch ; 6b 5e f0 1c ; 0xf1e7a ata.c:177
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf1e7e
+ add bx, di ; 01 fb ; 0xf1e81
+ cmp byte [es:bx+022h], 000h ; 26 80 7f 22 00 ; 0xf1e83
+ je short 01ed6h ; 74 4c ; 0xf1e88
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf1e8a ata.c:180
+ je short 01e95h ; 74 05 ; 0xf1e8e
+ mov ax, 000b0h ; b8 b0 00 ; 0xf1e90
+ jmp short 01e98h ; eb 03 ; 0xf1e93
+ mov ax, 000a0h ; b8 a0 00 ; 0xf1e95
+ mov dx, cx ; 89 ca ; 0xf1e98
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf1e9a
+ out DX, AL ; ee ; 0xf1e9d
+ mov dx, cx ; 89 ca ; 0xf1e9e ata.c:181
+ inc dx ; 42 ; 0xf1ea0
+ inc dx ; 42 ; 0xf1ea1
+ in AL, DX ; ec ; 0xf1ea2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1ea3
+ mov bx, ax ; 89 c3 ; 0xf1ea5
+ mov dx, cx ; 89 ca ; 0xf1ea7 ata.c:182
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf1ea9
+ in AL, DX ; ec ; 0xf1eac
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1ead
+ cmp bl, 001h ; 80 fb 01 ; 0xf1eaf ata.c:184
+ jne short 01ed6h ; 75 22 ; 0xf1eb2
+ cmp al, bl ; 38 d8 ; 0xf1eb4
+ jne short 01ed6h ; 75 1e ; 0xf1eb6
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf1eb8 ata.c:186
+ dec bx ; 4b ; 0xf1ebb ata.c:187
+ test bx, bx ; 85 db ; 0xf1ebc
+ jbe short 01ed6h ; 76 16 ; 0xf1ebe
+ mov dx, cx ; 89 ca ; 0xf1ec0 ata.c:188
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1ec2
+ in AL, DX ; ec ; 0xf1ec5
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1ec6
+ test AL, strict byte 080h ; a8 80 ; 0xf1ec8 ata.c:189
+ je short 01ed6h ; 74 0a ; 0xf1eca
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf1ecc ata.c:191
+ dec ax ; 48 ; 0xf1ecf ata.c:192
+ test ax, ax ; 85 c0 ; 0xf1ed0
+ jnbe short 01ecfh ; 77 fb ; 0xf1ed2
+ jmp short 01ebbh ; eb e5 ; 0xf1ed4 ata.c:195
+ mov bx, strict word 00010h ; bb 10 00 ; 0xf1ed6 ata.c:200
+ dec bx ; 4b ; 0xf1ed9 ata.c:201
+ test bx, bx ; 85 db ; 0xf1eda
+ jbe short 01eeah ; 76 0c ; 0xf1edc
+ mov dx, cx ; 89 ca ; 0xf1ede ata.c:202
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1ee0
+ in AL, DX ; ec ; 0xf1ee3
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1ee4
+ test AL, strict byte 040h ; a8 40 ; 0xf1ee6 ata.c:203
+ je short 01ed9h ; 74 ef ; 0xf1ee8
+ lea dx, [si+006h] ; 8d 54 06 ; 0xf1eea ata.c:208
+ mov AL, strict byte 008h ; b0 08 ; 0xf1eed
+ out DX, AL ; ee ; 0xf1eef
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf1ef0 ata.c:209
+ pop di ; 5f ; 0xf1ef3
+ pop si ; 5e ; 0xf1ef4
+ pop dx ; 5a ; 0xf1ef5
+ pop cx ; 59 ; 0xf1ef6
+ pop bx ; 5b ; 0xf1ef7
+ pop bp ; 5d ; 0xf1ef8
+ retn ; c3 ; 0xf1ef9
+ ; disGetNextSymbol 0xf1efa LB 0x814b -> off=0x0 cb=00000000000002e2 uValue=00000000000f08fa 'ata_cmd_data_in'
+ata_cmd_data_in: ; 0xf1efa LB 0x2e2
+ push bp ; 55 ; 0xf1efa ata.c:223
+ mov bp, sp ; 89 e5 ; 0xf1efb
+ push si ; 56 ; 0xf1efd
+ push di ; 57 ; 0xf1efe
+ sub sp, strict byte 00012h ; 83 ec 12 ; 0xf1eff
+ push ax ; 50 ; 0xf1f02
+ push dx ; 52 ; 0xf1f03
+ push bx ; 53 ; 0xf1f04
+ push cx ; 51 ; 0xf1f05
+ mov es, dx ; 8e c2 ; 0xf1f06 ata.c:233
+ mov bx, ax ; 89 c3 ; 0xf1f08
+ mov al, byte [es:bx+00ch] ; 26 8a 47 0c ; 0xf1f0a
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf1f0e
+ movzx bx, al ; 0f b6 d8 ; 0xf1f11 ata.c:235
+ mov ax, bx ; 89 d8 ; 0xf1f14
+ cwd ; 99 ; 0xf1f16
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf1f17
+ sar ax, 1 ; d1 f8 ; 0xf1f19
+ imul ax, ax, strict byte 00006h ; 6b c0 06 ; 0xf1f1b
+ mov di, word [bp-018h] ; 8b 7e e8 ; 0xf1f1e
+ add di, ax ; 01 c7 ; 0xf1f21
+ mov ax, word [es:di+00206h] ; 26 8b 85 06 02 ; 0xf1f23
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf1f28
+ mov ax, word [es:di+00208h] ; 26 8b 85 08 02 ; 0xf1f2b ata.c:236
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf1f30
+ imul bx, bx, strict byte 0001ch ; 6b db 1c ; 0xf1f33 ata.c:237
+ mov di, word [bp-018h] ; 8b 7e e8 ; 0xf1f36
+ add di, bx ; 01 df ; 0xf1f39
+ mov al, byte [es:di+026h] ; 26 8a 45 26 ; 0xf1f3b
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf1f3f
+ mov ax, word [es:di+028h] ; 26 8b 45 28 ; 0xf1f42 ata.c:238
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf1f46
+ test ax, ax ; 85 c0 ; 0xf1f49 ata.c:239
+ jne short 01f61h ; 75 14 ; 0xf1f4b
+ cmp byte [bp-008h], 001h ; 80 7e f8 01 ; 0xf1f4d ata.c:241
+ jne short 01f5ah ; 75 07 ; 0xf1f51
+ mov word [bp-00eh], 04000h ; c7 46 f2 00 40 ; 0xf1f53 ata.c:242
+ jmp short 01f70h ; eb 16 ; 0xf1f58 ata.c:243
+ mov word [bp-00eh], 08000h ; c7 46 f2 00 80 ; 0xf1f5a ata.c:245
+ jmp short 01f70h ; eb 0f ; 0xf1f5f ata.c:246
+ cmp byte [bp-008h], 001h ; 80 7e f8 01 ; 0xf1f61 ata.c:248
+ jne short 01f6dh ; 75 06 ; 0xf1f65
+ shr word [bp-00eh], 002h ; c1 6e f2 02 ; 0xf1f67 ata.c:249
+ jmp short 01f70h ; eb 03 ; 0xf1f6b ata.c:250
+ shr word [bp-00eh], 1 ; d1 6e f2 ; 0xf1f6d ata.c:252
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf1f70 ata.c:255
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1f73
+ in AL, DX ; ec ; 0xf1f76
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1f77
+ test AL, strict byte 080h ; a8 80 ; 0xf1f79 ata.c:256
+ je short 01f8ch ; 74 0f ; 0xf1f7b
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf1f7d ata.c:260
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf1f80
+ mov AL, strict byte 008h ; b0 08 ; 0xf1f83
+ out DX, AL ; ee ; 0xf1f85
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf1f86 ata.c:261
+ jmp near 021d3h ; e9 47 02 ; 0xf1f89
+ mov es, [bp-01ah] ; 8e 46 e6 ; 0xf1f8c ata.c:264
+ mov di, word [bp-018h] ; 8b 7e e8 ; 0xf1f8f
+ mov di, word [es:di+008h] ; 26 8b 7d 08 ; 0xf1f92
+ mov bx, word [bp-018h] ; 8b 5e e8 ; 0xf1f96
+ mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xf1f99
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf1f9d
+ mov al, byte [es:bx+016h] ; 26 8a 47 16 ; 0xf1fa0 ata.c:265
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf1fa4
+ mov ax, word [es:bx+012h] ; 26 8b 47 12 ; 0xf1fa7 ata.c:266
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1fab
+ mov bl, byte [es:bx+014h] ; 26 8a 5f 14 ; 0xf1fae ata.c:267
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf1fb2 ata.c:270
+ test al, al ; 84 c0 ; 0xf1fb5
+ jne near 0209eh ; 0f 85 e3 00 ; 0xf1fb7
+ xor bx, bx ; 31 db ; 0xf1fbb ata.c:271
+ xor dx, dx ; 31 d2 ; 0xf1fbd
+ xor ah, ah ; 30 e4 ; 0xf1fbf
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf1fc1
+ mov si, word [bp-018h] ; 8b 76 e8 ; 0xf1fc4
+ mov cx, word [es:si] ; 26 8b 0c ; 0xf1fc7
+ add cx, word [bp-01eh] ; 03 4e e2 ; 0xf1fca
+ adc bx, word [es:si+002h] ; 26 13 5c 02 ; 0xf1fcd
+ adc dx, word [es:si+004h] ; 26 13 54 04 ; 0xf1fd1
+ mov ax, word [es:si+006h] ; 26 8b 44 06 ; 0xf1fd5
+ adc ax, word [bp-016h] ; 13 46 ea ; 0xf1fd9
+ test ax, ax ; 85 c0 ; 0xf1fdc
+ jnbe short 01ff0h ; 77 10 ; 0xf1fde
+ jne short 02054h ; 75 72 ; 0xf1fe0
+ test dx, dx ; 85 d2 ; 0xf1fe2
+ jnbe short 01ff0h ; 77 0a ; 0xf1fe4
+ jne short 02054h ; 75 6c ; 0xf1fe6
+ cmp bx, 01000h ; 81 fb 00 10 ; 0xf1fe8
+ jnbe short 01ff0h ; 77 02 ; 0xf1fec
+ jne short 02054h ; 75 64 ; 0xf1fee
+ mov bx, si ; 89 f3 ; 0xf1ff0 ata.c:273
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf1ff2
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf1ff6
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf1ffa
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf1ffe
+ mov si, strict word 00018h ; be 18 00 ; 0xf2001
+ call 09f90h ; e8 89 7f ; 0xf2004
+ xor dh, dh ; 30 f6 ; 0xf2007
+ mov word [bp-016h], dx ; 89 56 ea ; 0xf2009
+ mov bx, word [bp-018h] ; 8b 5e e8 ; 0xf200c ata.c:274
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf200f
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf2013
+ mov si, word [bp-018h] ; 8b 76 e8 ; 0xf2017
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf201a
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf201e
+ mov si, strict word 00020h ; be 20 00 ; 0xf2021
+ call 09f90h ; e8 69 7f ; 0xf2024
+ mov bx, dx ; 89 d3 ; 0xf2027
+ mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xf2029 ata.c:275
+ xor al, al ; 30 c0 ; 0xf202c
+ shr ax, 008h ; c1 e8 08 ; 0xf202e
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2031
+ inc dx ; 42 ; 0xf2034
+ inc dx ; 42 ; 0xf2035
+ out DX, AL ; ee ; 0xf2036
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2037 ata.c:276
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf203a
+ mov al, byte [bp-016h] ; 8a 46 ea ; 0xf203d
+ out DX, AL ; ee ; 0xf2040
+ mov ax, bx ; 89 d8 ; 0xf2041 ata.c:277
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2043
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf2046
+ out DX, AL ; ee ; 0xf2049
+ shr ax, 008h ; c1 e8 08 ; 0xf204a ata.c:278
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf204d
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf2050
+ out DX, AL ; ee ; 0xf2053
+ mov es, [bp-01ah] ; 8e 46 e6 ; 0xf2054 ata.c:282
+ mov bx, word [bp-018h] ; 8b 5e e8 ; 0xf2057
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf205a
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf205d
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf2060 ata.c:283
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf2064
+ mov si, word [bp-018h] ; 8b 76 e8 ; 0xf2068
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf206b
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf206f
+ mov si, strict word 00008h ; be 08 00 ; 0xf2072
+ call 09f90h ; e8 18 7f ; 0xf2075
+ mov word [bp-014h], dx ; 89 56 ec ; 0xf2078
+ mov bx, word [bp-018h] ; 8b 5e e8 ; 0xf207b ata.c:284
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf207e
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf2082
+ mov si, word [bp-018h] ; 8b 76 e8 ; 0xf2086
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf2089
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf208d
+ mov si, strict word 00018h ; be 18 00 ; 0xf2090
+ call 09f90h ; e8 fa 7e ; 0xf2093
+ and dx, strict byte 0000fh ; 83 e2 0f ; 0xf2096
+ or dl, 040h ; 80 ca 40 ; 0xf2099
+ mov bx, dx ; 89 d3 ; 0xf209c
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf209e ata.c:287
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf20a1
+ mov AL, strict byte 00ah ; b0 0a ; 0xf20a4
+ out DX, AL ; ee ; 0xf20a6
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf20a7 ata.c:288
+ inc dx ; 42 ; 0xf20aa
+ xor al, al ; 30 c0 ; 0xf20ab
+ out DX, AL ; ee ; 0xf20ad
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf20ae ata.c:289
+ inc dx ; 42 ; 0xf20b1
+ inc dx ; 42 ; 0xf20b2
+ mov al, byte [bp-01eh] ; 8a 46 e2 ; 0xf20b3
+ out DX, AL ; ee ; 0xf20b6
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf20b7 ata.c:290
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf20ba
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf20bd
+ out DX, AL ; ee ; 0xf20c0
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf20c1 ata.c:291
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf20c4
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf20c7
+ out DX, AL ; ee ; 0xf20ca
+ shr ax, 008h ; c1 e8 08 ; 0xf20cb ata.c:292
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf20ce
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf20d1
+ out DX, AL ; ee ; 0xf20d4
+ test byte [bp-00ah], 001h ; f6 46 f6 01 ; 0xf20d5 ata.c:293
+ je short 020e0h ; 74 05 ; 0xf20d9
+ mov ax, 000b0h ; b8 b0 00 ; 0xf20db
+ jmp short 020e3h ; eb 03 ; 0xf20de
+ mov ax, 000a0h ; b8 a0 00 ; 0xf20e0
+ movzx dx, bl ; 0f b6 d3 ; 0xf20e3
+ or ax, dx ; 09 d0 ; 0xf20e6
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf20e8
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf20eb
+ out DX, AL ; ee ; 0xf20ee
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf20ef ata.c:294
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf20f2
+ mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xf20f5
+ out DX, AL ; ee ; 0xf20f8
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf20f9 ata.c:296
+ cmp ax, 000c4h ; 3d c4 00 ; 0xf20fc
+ je short 02106h ; 74 05 ; 0xf20ff
+ cmp ax, strict word 00029h ; 3d 29 00 ; 0xf2101
+ jne short 02110h ; 75 0a ; 0xf2104
+ mov bx, word [bp-01eh] ; 8b 5e e2 ; 0xf2106 ata.c:297
+ mov word [bp-01eh], strict word 00001h ; c7 46 e2 01 00 ; 0xf2109 ata.c:298
+ jmp short 02113h ; eb 03 ; 0xf210e ata.c:299
+ mov bx, strict word 00001h ; bb 01 00 ; 0xf2110 ata.c:300
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2113 ata.c:304
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2116
+ in AL, DX ; ec ; 0xf2119
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf211a
+ mov dl, al ; 88 c2 ; 0xf211c
+ test AL, strict byte 080h ; a8 80 ; 0xf211e ata.c:305
+ jne short 02113h ; 75 f1 ; 0xf2120
+ test AL, strict byte 001h ; a8 01 ; 0xf2122 ata.c:309
+ je short 02135h ; 74 0f ; 0xf2124
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf2126 ata.c:312
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2129
+ mov AL, strict byte 008h ; b0 08 ; 0xf212c
+ out DX, AL ; ee ; 0xf212e
+ mov dx, strict word 00002h ; ba 02 00 ; 0xf212f ata.c:313
+ jmp near 021d3h ; e9 9e 00 ; 0xf2132
+ test dl, 008h ; f6 c2 08 ; 0xf2135 ata.c:314
+ jne short 02149h ; 75 0f ; 0xf2138
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf213a ata.c:317
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf213d
+ mov AL, strict byte 008h ; b0 08 ; 0xf2140
+ out DX, AL ; ee ; 0xf2142
+ mov dx, strict word 00003h ; ba 03 00 ; 0xf2143 ata.c:318
+ jmp near 021d3h ; e9 8a 00 ; 0xf2146
+ sti ; fb ; 0xf2149 ata.c:323
+ cmp di, 0f800h ; 81 ff 00 f8 ; 0xf214a ata.c:328
+ jc short 0215dh ; 72 0d ; 0xf214e
+ sub di, 00800h ; 81 ef 00 08 ; 0xf2150 ata.c:329
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf2154
+ add ax, 00080h ; 05 80 00 ; 0xf2157
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf215a
+ cmp byte [bp-008h], 001h ; 80 7e f8 01 ; 0xf215d ata.c:332
+ jne short 02171h ; 75 0e ; 0xf2161
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2163 ata.c:333
+ mov cx, word [bp-00eh] ; 8b 4e f2 ; 0xf2166
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf2169
+ db 0f3h, 066h, 06dh
+ ; rep insd ; f3 66 6d ; 0xf216c
+ jmp short 0217ch ; eb 0b ; 0xf216f ata.c:334
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2171 ata.c:336
+ mov cx, word [bp-00eh] ; 8b 4e f2 ; 0xf2174
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf2177
+ rep insw ; f3 6d ; 0xf217a
+ mov es, [bp-01ah] ; 8e 46 e6 ; 0xf217c ata.c:337
+ mov si, word [bp-018h] ; 8b 76 e8 ; 0xf217f
+ add word [es:si+018h], bx ; 26 01 5c 18 ; 0xf2182
+ dec word [bp-01eh] ; ff 4e e2 ; 0xf2186 ata.c:338
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2189 ata.c:340
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf218c
+ in AL, DX ; ec ; 0xf218f
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2190
+ mov dl, al ; 88 c2 ; 0xf2192
+ test AL, strict byte 080h ; a8 80 ; 0xf2194 ata.c:341
+ jne short 02189h ; 75 f1 ; 0xf2196
+ cmp word [bp-01eh], strict byte 00000h ; 83 7e e2 00 ; 0xf2198 ata.c:344
+ jne short 021b2h ; 75 14 ; 0xf219c
+ and AL, strict byte 0c9h ; 24 c9 ; 0xf219e ata.c:345
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf21a0
+ je short 021c8h ; 74 24 ; 0xf21a2
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf21a4 ata.c:349
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf21a7
+ mov AL, strict byte 008h ; b0 08 ; 0xf21aa
+ out DX, AL ; ee ; 0xf21ac
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf21ad ata.c:350
+ jmp short 021d3h ; eb 21 ; 0xf21b0
+ mov al, dl ; 88 d0 ; 0xf21b2 ata.c:355
+ and AL, strict byte 0c9h ; 24 c9 ; 0xf21b4
+ cmp AL, strict byte 048h ; 3c 48 ; 0xf21b6
+ je short 0214ah ; 74 90 ; 0xf21b8
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf21ba ata.c:359
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf21bd
+ mov AL, strict byte 008h ; b0 08 ; 0xf21c0
+ out DX, AL ; ee ; 0xf21c2
+ mov dx, strict word 00005h ; ba 05 00 ; 0xf21c3 ata.c:360
+ jmp short 021d3h ; eb 0b ; 0xf21c6
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf21c8 ata.c:366
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf21cb
+ mov AL, strict byte 008h ; b0 08 ; 0xf21ce
+ out DX, AL ; ee ; 0xf21d0
+ xor dx, dx ; 31 d2 ; 0xf21d1 ata.c:367
+ mov ax, dx ; 89 d0 ; 0xf21d3 ata.c:368
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf21d5
+ pop di ; 5f ; 0xf21d8
+ pop si ; 5e ; 0xf21d9
+ pop bp ; 5d ; 0xf21da
+ retn ; c3 ; 0xf21db
+ ; disGetNextSymbol 0xf21dc LB 0x7e69 -> off=0x0 cb=000000000000068a uValue=00000000000f0bdc 'ata_detect'
+ata_detect: ; 0xf21dc LB 0x68a
+ push bp ; 55 ; 0xf21dc ata.c:374
+ mov bp, sp ; 89 e5 ; 0xf21dd
+ push si ; 56 ; 0xf21df
+ push di ; 57 ; 0xf21e0
+ sub sp, 00262h ; 81 ec 62 02 ; 0xf21e1
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf21e5 ata.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf21e8
+ mov es, ax ; 8e c0 ; 0xf21eb
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf21ed
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf21f0 ata.c:49
+ mov bx, 00122h ; bb 22 01 ; 0xf21f3 ata.c:381
+ mov es, ax ; 8e c0 ; 0xf21f6
+ mov word [bp-01eh], bx ; 89 5e e2 ; 0xf21f8
+ mov word [bp-030h], ax ; 89 46 d0 ; 0xf21fb
+ mov byte [es:bx+00204h], 000h ; 26 c6 87 04 02 00 ; 0xf21fe ata.c:384
+ db 066h, 026h, 0c7h, 087h, 006h, 002h, 0f0h, 001h, 0f0h, 003h
+ ; mov dword [es:bx+00206h], strict dword 003f001f0h ; 66 26 c7 87 06 02 f0 01 f0 03; 0xf2204 ata.c:385
+ mov byte [es:bx+00205h], 00eh ; 26 c6 87 05 02 0e ; 0xf220e ata.c:387
+ mov byte [es:bx+0020ah], 000h ; 26 c6 87 0a 02 00 ; 0xf2214 ata.c:390
+ db 066h, 026h, 0c7h, 087h, 00ch, 002h, 070h, 001h, 070h, 003h
+ ; mov dword [es:bx+0020ch], strict dword 003700170h ; 66 26 c7 87 0c 02 70 01 70 03; 0xf221a ata.c:391
+ mov byte [es:bx+0020bh], 00fh ; 26 c6 87 0b 02 0f ; 0xf2224 ata.c:393
+ xor al, al ; 30 c0 ; 0xf222a ata.c:414
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf222c
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf222f
+ mov byte [bp-016h], al ; 88 46 ea ; 0xf2232 ata.c:416
+ jmp near 027eah ; e9 b2 05 ; 0xf2235
+ mov ax, 000a0h ; b8 a0 00 ; 0xf2238 ata.c:431
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf223b
+ out DX, AL ; ee ; 0xf223e
+ lea si, [bx+002h] ; 8d 77 02 ; 0xf223f ata.c:432
+ mov AL, strict byte 055h ; b0 55 ; 0xf2242
+ mov dx, si ; 89 f2 ; 0xf2244
+ out DX, AL ; ee ; 0xf2246
+ lea di, [bx+003h] ; 8d 7f 03 ; 0xf2247 ata.c:433
+ mov AL, strict byte 0aah ; b0 aa ; 0xf224a
+ mov dx, di ; 89 fa ; 0xf224c
+ out DX, AL ; ee ; 0xf224e
+ mov dx, si ; 89 f2 ; 0xf224f ata.c:434
+ out DX, AL ; ee ; 0xf2251
+ mov AL, strict byte 055h ; b0 55 ; 0xf2252 ata.c:435
+ mov dx, di ; 89 fa ; 0xf2254
+ out DX, AL ; ee ; 0xf2256
+ mov dx, si ; 89 f2 ; 0xf2257 ata.c:436
+ out DX, AL ; ee ; 0xf2259
+ mov AL, strict byte 0aah ; b0 aa ; 0xf225a ata.c:437
+ mov dx, di ; 89 fa ; 0xf225c
+ out DX, AL ; ee ; 0xf225e
+ mov dx, si ; 89 f2 ; 0xf225f ata.c:440
+ in AL, DX ; ec ; 0xf2261
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2262
+ mov cx, ax ; 89 c1 ; 0xf2264
+ mov dx, di ; 89 fa ; 0xf2266 ata.c:441
+ in AL, DX ; ec ; 0xf2268
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2269
+ cmp cl, 055h ; 80 f9 55 ; 0xf226b ata.c:443
+ jne near 02342h ; 0f 85 d0 00 ; 0xf226e
+ cmp AL, strict byte 0aah ; 3c aa ; 0xf2272
+ jne near 02342h ; 0f 85 ca 00 ; 0xf2274
+ movzx ax, byte [bp-016h] ; 0f b6 46 ea ; 0xf2278 ata.c:444
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf227c
+ mov es, [bp-030h] ; 8e 46 d0 ; 0xf227f
+ mov si, word [bp-01eh] ; 8b 76 e2 ; 0xf2282
+ add si, ax ; 01 c6 ; 0xf2285
+ mov byte [es:si+022h], 001h ; 26 c6 44 22 01 ; 0xf2287
+ movzx ax, byte [bp-016h] ; 0f b6 46 ea ; 0xf228c ata.c:447
+ call 01e1dh ; e8 8a fb ; 0xf2290
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf2293 ata.c:450
+ je short 0229eh ; 74 05 ; 0xf2297
+ mov ax, 000b0h ; b8 b0 00 ; 0xf2299
+ jmp short 022a1h ; eb 03 ; 0xf229c
+ mov ax, 000a0h ; b8 a0 00 ; 0xf229e
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf22a1
+ out DX, AL ; ee ; 0xf22a4
+ lea dx, [bx+002h] ; 8d 57 02 ; 0xf22a5 ata.c:451
+ in AL, DX ; ec ; 0xf22a8
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf22a9
+ mov cx, ax ; 89 c1 ; 0xf22ab
+ lea dx, [bx+003h] ; 8d 57 03 ; 0xf22ad ata.c:452
+ in AL, DX ; ec ; 0xf22b0
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf22b1
+ cmp cl, 001h ; 80 f9 01 ; 0xf22b3 ata.c:453
+ jne near 02342h ; 0f 85 88 00 ; 0xf22b6
+ cmp al, cl ; 38 c8 ; 0xf22ba
+ jne near 02342h ; 0f 85 82 00 ; 0xf22bc
+ lea dx, [bx+004h] ; 8d 57 04 ; 0xf22c0 ata.c:454
+ in AL, DX ; ec ; 0xf22c3
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf22c4
+ mov cx, ax ; 89 c1 ; 0xf22c6
+ mov ch, al ; 88 c5 ; 0xf22c8
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf22ca ata.c:455
+ in AL, DX ; ec ; 0xf22cd
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf22ce
+ mov word [bp-020h], ax ; 89 46 e0 ; 0xf22d0
+ mov al, byte [bp-020h] ; 8a 46 e0 ; 0xf22d3
+ mov byte [bp-010h], al ; 88 46 f0 ; 0xf22d6
+ lea dx, [bx+007h] ; 8d 57 07 ; 0xf22d9 ata.c:456
+ in AL, DX ; ec ; 0xf22dc
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf22dd
+ cmp cl, 014h ; 80 f9 14 ; 0xf22df ata.c:458
+ jne short 02300h ; 75 1c ; 0xf22e2
+ cmp byte [bp-020h], 0ebh ; 80 7e e0 eb ; 0xf22e4
+ jne short 02300h ; 75 16 ; 0xf22e8
+ movzx ax, byte [bp-016h] ; 0f b6 46 ea ; 0xf22ea ata.c:459
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf22ee
+ mov es, [bp-030h] ; 8e 46 d0 ; 0xf22f1
+ mov bx, word [bp-01eh] ; 8b 5e e2 ; 0xf22f4
+ add bx, ax ; 01 c3 ; 0xf22f7
+ mov byte [es:bx+022h], 003h ; 26 c6 47 22 03 ; 0xf22f9
+ jmp short 02342h ; eb 42 ; 0xf22fe ata.c:460
+ test ch, ch ; 84 ed ; 0xf2300
+ jne short 02324h ; 75 20 ; 0xf2302
+ cmp byte [bp-010h], 000h ; 80 7e f0 00 ; 0xf2304
+ jne short 02324h ; 75 1a ; 0xf2308
+ test al, al ; 84 c0 ; 0xf230a
+ je short 02324h ; 74 16 ; 0xf230c
+ movzx ax, byte [bp-016h] ; 0f b6 46 ea ; 0xf230e ata.c:461
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf2312
+ mov es, [bp-030h] ; 8e 46 d0 ; 0xf2315
+ mov bx, word [bp-01eh] ; 8b 5e e2 ; 0xf2318
+ add bx, ax ; 01 c3 ; 0xf231b
+ mov byte [es:bx+022h], 002h ; 26 c6 47 22 02 ; 0xf231d
+ jmp short 02342h ; eb 1e ; 0xf2322 ata.c:462
+ cmp ch, 0ffh ; 80 fd ff ; 0xf2324
+ jne short 02342h ; 75 19 ; 0xf2327
+ cmp ch, byte [bp-010h] ; 3a 6e f0 ; 0xf2329
+ jne short 02342h ; 75 14 ; 0xf232c
+ movzx ax, byte [bp-016h] ; 0f b6 46 ea ; 0xf232e ata.c:463
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf2332
+ mov es, [bp-030h] ; 8e 46 d0 ; 0xf2335
+ mov bx, word [bp-01eh] ; 8b 5e e2 ; 0xf2338
+ add bx, ax ; 01 c3 ; 0xf233b
+ mov byte [es:bx+022h], 000h ; 26 c6 47 22 00 ; 0xf233d
+ mov dx, word [bp-026h] ; 8b 56 da ; 0xf2342 ata.c:469
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2345
+ mov AL, strict byte 008h ; b0 08 ; 0xf2348
+ out DX, AL ; ee ; 0xf234a
+ movzx bx, byte [bp-016h] ; 0f b6 5e ea ; 0xf234b ata.c:471
+ imul bx, bx, strict byte 0001ch ; 6b db 1c ; 0xf234f
+ mov es, [bp-030h] ; 8e 46 d0 ; 0xf2352
+ add bx, word [bp-01eh] ; 03 5e e2 ; 0xf2355
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf2358
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf235c
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf235f ata.c:474
+ jne near 025bch ; 0f 85 57 02 ; 0xf2361
+ mov byte [es:bx+023h], 0ffh ; 26 c6 47 23 ff ; 0xf2365 ata.c:482
+ mov byte [es:bx+026h], 000h ; 26 c6 47 26 00 ; 0xf236a ata.c:483
+ lea dx, [bp-00266h] ; 8d 96 9a fd ; 0xf236f ata.c:484
+ mov bx, word [bp-01eh] ; 8b 5e e2 ; 0xf2373
+ mov word [es:bx+008h], dx ; 26 89 57 08 ; 0xf2376
+ mov [es:bx+00ah], ss ; 26 8c 57 0a ; 0xf237a
+ mov al, byte [bp-016h] ; 8a 46 ea ; 0xf237e ata.c:485
+ mov byte [es:bx+00ch], al ; 26 88 47 0c ; 0xf2381
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf2385 ata.c:487
+ mov bx, 000ech ; bb ec 00 ; 0xf2388
+ mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xf238b
+ mov dx, es ; 8c c2 ; 0xf238e
+ call 01efah ; e8 67 fb ; 0xf2390
+ test ax, ax ; 85 c0 ; 0xf2393
+ je short 023a2h ; 74 0b ; 0xf2395
+ push 00136h ; 68 36 01 ; 0xf2397 ata.c:488
+ push strict byte 00007h ; 6a 07 ; 0xf239a
+ call 01a14h ; e8 75 f6 ; 0xf239c
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf239f
+ test byte [bp-00266h], 080h ; f6 86 9a fd 80 ; 0xf23a2 ata.c:490
+ db 00fh, 095h, 0c0h
+ ; setne al ; 0f 95 c0 ; 0xf23a7
+ xor ah, ah ; 30 e4 ; 0xf23aa
+ mov byte [bp-012h], al ; 88 46 ee ; 0xf23ac
+ cmp byte [bp-00206h], 000h ; 80 be fa fd 00 ; 0xf23af ata.c:492
+ db 00fh, 095h, 0c0h
+ ; setne al ; 0f 95 c0 ; 0xf23b4
+ xor ah, ah ; 30 e4 ; 0xf23b7
+ mov byte [bp-018h], al ; 88 46 e8 ; 0xf23b9
+ mov word [bp-036h], 00200h ; c7 46 ca 00 02 ; 0xf23bc ata.c:496
+ mov ax, word [bp-00264h] ; 8b 86 9c fd ; 0xf23c1 ata.c:498
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf23c5
+ mov ax, word [bp-00260h] ; 8b 86 a0 fd ; 0xf23c8 ata.c:499
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf23cc
+ mov ax, word [bp-0025ah] ; 8b 86 a6 fd ; 0xf23cf ata.c:500
+ mov word [bp-022h], ax ; 89 46 de ; 0xf23d3
+ mov ax, word [bp-001eeh] ; 8b 86 12 fe ; 0xf23d6 ata.c:502
+ mov word [bp-02ch], ax ; 89 46 d4 ; 0xf23da
+ mov si, word [bp-001ech] ; 8b b6 14 fe ; 0xf23dd
+ xor ax, ax ; 31 c0 ; 0xf23e1
+ mov word [bp-032h], ax ; 89 46 ce ; 0xf23e3
+ mov word [bp-02eh], ax ; 89 46 d2 ; 0xf23e6
+ cmp si, 00fffh ; 81 fe ff 0f ; 0xf23e9 ata.c:503
+ jne short 0240eh ; 75 1f ; 0xf23ed
+ cmp word [bp-02ch], strict byte 0ffffh ; 83 7e d4 ff ; 0xf23ef
+ jne short 0240eh ; 75 19 ; 0xf23f3
+ mov ax, word [bp-00198h] ; 8b 86 68 fe ; 0xf23f5 ata.c:504
+ mov word [bp-02eh], ax ; 89 46 d2 ; 0xf23f9
+ mov ax, word [bp-0019ah] ; 8b 86 66 fe ; 0xf23fc
+ mov word [bp-032h], ax ; 89 46 ce ; 0xf2400
+ mov si, word [bp-0019ch] ; 8b b6 64 fe ; 0xf2403
+ mov ax, word [bp-0019eh] ; 8b 86 62 fe ; 0xf2407
+ mov word [bp-02ch], ax ; 89 46 d4 ; 0xf240b
+ mov al, byte [bp-016h] ; 8a 46 ea ; 0xf240e ata.c:505
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf2411
+ jc short 02421h ; 72 0c ; 0xf2413
+ jbe short 02429h ; 76 12 ; 0xf2415
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf2417
+ je short 02431h ; 74 16 ; 0xf2419
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf241b
+ je short 0242dh ; 74 0e ; 0xf241d
+ jmp short 0246eh ; eb 4d ; 0xf241f
+ test al, al ; 84 c0 ; 0xf2421
+ jne short 0246eh ; 75 49 ; 0xf2423
+ mov BL, strict byte 01eh ; b3 1e ; 0xf2425 ata.c:508
+ jmp short 02433h ; eb 0a ; 0xf2427 ata.c:509
+ mov BL, strict byte 026h ; b3 26 ; 0xf2429 ata.c:511
+ jmp short 02433h ; eb 06 ; 0xf242b ata.c:512
+ mov BL, strict byte 067h ; b3 67 ; 0xf242d ata.c:514
+ jmp short 02433h ; eb 02 ; 0xf242f ata.c:515
+ mov BL, strict byte 070h ; b3 70 ; 0xf2431 ata.c:517
+ mov al, bl ; 88 d8 ; 0xf2433 ata.c:524
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf2435
+ xor ah, ah ; 30 e4 ; 0xf2437
+ call 01756h ; e8 1a f3 ; 0xf2439
+ xor ah, ah ; 30 e4 ; 0xf243c
+ mov dx, ax ; 89 c2 ; 0xf243e
+ sal dx, 008h ; c1 e2 08 ; 0xf2440
+ movzx ax, bl ; 0f b6 c3 ; 0xf2443
+ call 01756h ; e8 0d f3 ; 0xf2446
+ xor ah, ah ; 30 e4 ; 0xf2449
+ add ax, dx ; 01 d0 ; 0xf244b
+ mov word [bp-03ah], ax ; 89 46 c6 ; 0xf244d
+ mov al, bl ; 88 d8 ; 0xf2450 ata.c:525
+ add AL, strict byte 002h ; 04 02 ; 0xf2452
+ xor ah, ah ; 30 e4 ; 0xf2454
+ call 01756h ; e8 fd f2 ; 0xf2456
+ xor ah, ah ; 30 e4 ; 0xf2459
+ mov word [bp-03ch], ax ; 89 46 c4 ; 0xf245b
+ mov al, bl ; 88 d8 ; 0xf245e ata.c:526
+ add AL, strict byte 007h ; 04 07 ; 0xf2460
+ xor ah, ah ; 30 e4 ; 0xf2462
+ call 01756h ; e8 ef f2 ; 0xf2464
+ xor ah, ah ; 30 e4 ; 0xf2467
+ mov word [bp-038h], ax ; 89 46 c8 ; 0xf2469
+ jmp short 02480h ; eb 12 ; 0xf246c ata.c:528
+ push word [bp-02eh] ; ff 76 d2 ; 0xf246e ata.c:529
+ push word [bp-032h] ; ff 76 ce ; 0xf2471
+ push si ; 56 ; 0xf2474
+ push word [bp-02ch] ; ff 76 d4 ; 0xf2475
+ mov dx, ss ; 8c d2 ; 0xf2478
+ lea ax, [bp-03ch] ; 8d 46 c4 ; 0xf247a
+ call 0599dh ; e8 1d 35 ; 0xf247d
+ mov bx, 00db2h ; bb b2 0d ; 0xf2480 ata.c:532
+ mov cx, ds ; 8c d9 ; 0xf2483
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf2485
+ call 019d3h ; e8 48 f5 ; 0xf2488
+ mov ax, word [bp-038h] ; 8b 46 c8 ; 0xf248b
+ push ax ; 50 ; 0xf248e
+ mov ax, word [bp-03ch] ; 8b 46 c4 ; 0xf248f
+ push ax ; 50 ; 0xf2492
+ mov ax, word [bp-03ah] ; 8b 46 c6 ; 0xf2493
+ push ax ; 50 ; 0xf2496
+ push word [bp-022h] ; ff 76 de ; 0xf2497
+ push word [bp-01ch] ; ff 76 e4 ; 0xf249a
+ push word [bp-01ah] ; ff 76 e6 ; 0xf249d
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf24a0
+ push ax ; 50 ; 0xf24a4
+ movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xf24a5
+ push ax ; 50 ; 0xf24a9
+ push 0015fh ; 68 5f 01 ; 0xf24aa
+ push strict byte 00004h ; 6a 04 ; 0xf24ad
+ call 01a14h ; e8 62 f5 ; 0xf24af
+ add sp, strict byte 00014h ; 83 c4 14 ; 0xf24b2
+ movzx ax, byte [bp-016h] ; 0f b6 46 ea ; 0xf24b5 ata.c:534
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf24b9
+ mov es, [bp-030h] ; 8e 46 d0 ; 0xf24bc
+ mov di, word [bp-01eh] ; 8b 7e e2 ; 0xf24bf
+ add di, ax ; 01 c7 ; 0xf24c2
+ mov byte [es:di+023h], 0ffh ; 26 c6 45 23 ff ; 0xf24c4
+ mov al, byte [bp-012h] ; 8a 46 ee ; 0xf24c9 ata.c:535
+ mov byte [es:di+024h], al ; 26 88 45 24 ; 0xf24cc
+ mov al, byte [bp-018h] ; 8a 46 e8 ; 0xf24d0 ata.c:536
+ mov byte [es:di+026h], al ; 26 88 45 26 ; 0xf24d3
+ mov ax, word [bp-036h] ; 8b 46 ca ; 0xf24d7 ata.c:537
+ mov word [es:di+028h], ax ; 26 89 45 28 ; 0xf24da
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf24de ata.c:538
+ mov word [es:di+030h], ax ; 26 89 45 30 ; 0xf24e1
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf24e5 ata.c:539
+ mov word [es:di+032h], ax ; 26 89 45 32 ; 0xf24e8
+ mov ax, word [bp-022h] ; 8b 46 de ; 0xf24ec ata.c:540
+ mov word [es:di+034h], ax ; 26 89 45 34 ; 0xf24ef
+ mov ax, word [bp-02eh] ; 8b 46 d2 ; 0xf24f3 ata.c:541
+ mov word [es:di+03ch], ax ; 26 89 45 3c ; 0xf24f6
+ mov ax, word [bp-032h] ; 8b 46 ce ; 0xf24fa
+ mov word [es:di+03ah], ax ; 26 89 45 3a ; 0xf24fd
+ mov word [es:di+038h], si ; 26 89 75 38 ; 0xf2501
+ mov ax, word [bp-02ch] ; 8b 46 d4 ; 0xf2505
+ mov word [es:di+036h], ax ; 26 89 45 36 ; 0xf2508
+ lea di, [di+02ah] ; 8d 7d 2a ; 0xf250c ata.c:542
+ push DS ; 1e ; 0xf250f
+ push SS ; 16 ; 0xf2510
+ pop DS ; 1f ; 0xf2511
+ lea si, [bp-03ch] ; 8d 76 c4 ; 0xf2512
+ movsw ; a5 ; 0xf2515
+ movsw ; a5 ; 0xf2516
+ movsw ; a5 ; 0xf2517
+ pop DS ; 1f ; 0xf2518
+ mov al, byte [bp-016h] ; 8a 46 ea ; 0xf2519 ata.c:543
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf251c
+ jnc near 025a7h ; 0f 83 85 00 ; 0xf251e
+ test al, al ; 84 c0 ; 0xf2522 ata.c:549
+ jne short 0252bh ; 75 05 ; 0xf2524
+ mov bx, strict word 0003dh ; bb 3d 00 ; 0xf2526 ata.c:550
+ jmp short 0252eh ; eb 03 ; 0xf2529 ata.c:551
+ mov bx, strict word 0004dh ; bb 4d 00 ; 0xf252b ata.c:552
+ mov dx, word [bp-024h] ; 8b 56 dc ; 0xf252e
+ movzx si, byte [bp-016h] ; 0f b6 76 ea ; 0xf2531 ata.c:564
+ imul si, si, strict byte 00005h ; 6b f6 05 ; 0xf2535
+ sal si, 002h ; c1 e6 02 ; 0xf2538
+ add si, 00104h ; 81 c6 04 01 ; 0xf253b
+ xor ax, ax ; 31 c0 ; 0xf253f
+ mov es, ax ; 8e c0 ; 0xf2541
+ mov word [es:si], bx ; 26 89 1c ; 0xf2543 ata.c:565
+ mov word [es:si+002h], dx ; 26 89 54 02 ; 0xf2546
+ mov es, dx ; 8e c2 ; 0xf254a ata.c:571
+ mov word [es:bx+00ch], ax ; 26 89 47 0c ; 0xf254c
+ mov word [es:bx+005h], ax ; 26 89 47 05 ; 0xf2550
+ mov word [es:bx+007h], ax ; 26 89 47 07 ; 0xf2554
+ mov ax, word [bp-03ah] ; 8b 46 c6 ; 0xf2558 ata.c:573
+ mov word [es:bx], ax ; 26 89 07 ; 0xf255b
+ mov al, byte [bp-03ch] ; 8a 46 c4 ; 0xf255e ata.c:574
+ mov byte [es:bx+002h], al ; 26 88 47 02 ; 0xf2561
+ mov byte [es:bx+003h], 0a0h ; 26 c6 47 03 a0 ; 0xf2565 ata.c:575
+ mov al, byte [bp-022h] ; 8a 46 de ; 0xf256a ata.c:576
+ mov byte [es:bx+004h], al ; 26 88 47 04 ; 0xf256d
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf2571 ata.c:577
+ mov word [es:bx+009h], ax ; 26 89 47 09 ; 0xf2574
+ mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xf2578 ata.c:578
+ mov byte [es:bx+00bh], al ; 26 88 47 0b ; 0xf257b
+ mov al, byte [bp-038h] ; 8a 46 c8 ; 0xf257f ata.c:579
+ mov byte [es:bx+00eh], al ; 26 88 47 0e ; 0xf2582
+ xor al, al ; 30 c0 ; 0xf2586 ata.c:580
+ xor ah, ah ; 30 e4 ; 0xf2588 ata.c:581
+ jmp short 02591h ; eb 05 ; 0xf258a
+ cmp ah, 00fh ; 80 fc 0f ; 0xf258c
+ jnc short 0259fh ; 73 0e ; 0xf258f
+ movzx si, ah ; 0f b6 f4 ; 0xf2591 ata.c:582
+ mov es, dx ; 8e c2 ; 0xf2594
+ add si, bx ; 01 de ; 0xf2596
+ add al, byte [es:si] ; 26 02 04 ; 0xf2598
+ db 0feh, 0c4h
+ ; inc ah ; fe c4 ; 0xf259b
+ jmp short 0258ch ; eb ed ; 0xf259d
+ neg al ; f6 d8 ; 0xf259f ata.c:583
+ mov es, dx ; 8e c2 ; 0xf25a1 ata.c:584
+ mov byte [es:bx+00fh], al ; 26 88 47 0f ; 0xf25a3
+ movzx bx, byte [bp-008h] ; 0f b6 5e f8 ; 0xf25a7 ata.c:588
+ mov es, [bp-030h] ; 8e 46 d0 ; 0xf25ab
+ add bx, word [bp-01eh] ; 03 5e e2 ; 0xf25ae
+ mov al, byte [bp-016h] ; 8a 46 ea ; 0xf25b1
+ mov byte [es:bx+001e3h], al ; 26 88 87 e3 01 ; 0xf25b4
+ inc byte [bp-008h] ; fe 46 f8 ; 0xf25b9 ata.c:589
+ cmp byte [bp-00eh], 003h ; 80 7e f2 03 ; 0xf25bc ata.c:593
+ jne near 0265eh ; 0f 85 9a 00 ; 0xf25c0
+ movzx ax, byte [bp-016h] ; 0f b6 46 ea ; 0xf25c4 ata.c:598
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf25c8
+ mov es, [bp-030h] ; 8e 46 d0 ; 0xf25cb
+ mov bx, word [bp-01eh] ; 8b 5e e2 ; 0xf25ce
+ add bx, ax ; 01 c3 ; 0xf25d1
+ mov byte [es:bx+023h], 005h ; 26 c6 47 23 05 ; 0xf25d3
+ mov byte [es:bx+026h], 000h ; 26 c6 47 26 00 ; 0xf25d8 ata.c:599
+ lea dx, [bp-00266h] ; 8d 96 9a fd ; 0xf25dd ata.c:600
+ mov bx, word [bp-01eh] ; 8b 5e e2 ; 0xf25e1
+ mov word [es:bx+008h], dx ; 26 89 57 08 ; 0xf25e4
+ mov [es:bx+00ah], ss ; 26 8c 57 0a ; 0xf25e8
+ mov al, byte [bp-016h] ; 8a 46 ea ; 0xf25ec ata.c:601
+ mov byte [es:bx+00ch], al ; 26 88 47 0c ; 0xf25ef
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf25f3 ata.c:603
+ mov bx, 000a1h ; bb a1 00 ; 0xf25f6
+ mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xf25f9
+ mov dx, es ; 8c c2 ; 0xf25fc
+ call 01efah ; e8 f9 f8 ; 0xf25fe
+ test ax, ax ; 85 c0 ; 0xf2601
+ je short 02610h ; 74 0b ; 0xf2603
+ push 00186h ; 68 86 01 ; 0xf2605 ata.c:604
+ push strict byte 00007h ; 6a 07 ; 0xf2608
+ call 01a14h ; e8 07 f4 ; 0xf260a
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf260d
+ mov cl, byte [bp-00265h] ; 8a 8e 9b fd ; 0xf2610 ata.c:606
+ and cl, 01fh ; 80 e1 1f ; 0xf2614
+ test byte [bp-00266h], 080h ; f6 86 9a fd 80 ; 0xf2617 ata.c:607
+ db 00fh, 095h, 0c0h
+ ; setne al ; 0f 95 c0 ; 0xf261c
+ xor ah, ah ; 30 e4 ; 0xf261f
+ mov dx, ax ; 89 c2 ; 0xf2621
+ cmp byte [bp-00206h], 000h ; 80 be fa fd 00 ; 0xf2623 ata.c:609
+ db 00fh, 095h, 0c0h
+ ; setne al ; 0f 95 c0 ; 0xf2628
+ xor ah, ah ; 30 e4 ; 0xf262b
+ movzx bx, byte [bp-016h] ; 0f b6 5e ea ; 0xf262d ata.c:615
+ imul bx, bx, strict byte 0001ch ; 6b db 1c ; 0xf2631
+ mov es, [bp-030h] ; 8e 46 d0 ; 0xf2634
+ add bx, word [bp-01eh] ; 03 5e e2 ; 0xf2637
+ mov byte [es:bx+023h], cl ; 26 88 4f 23 ; 0xf263a
+ mov byte [es:bx+024h], dl ; 26 88 57 24 ; 0xf263e ata.c:616
+ mov byte [es:bx+026h], al ; 26 88 47 26 ; 0xf2642 ata.c:617
+ mov word [es:bx+028h], 00800h ; 26 c7 47 28 00 08 ; 0xf2646 ata.c:618
+ movzx bx, byte [bp-00ah] ; 0f b6 5e f6 ; 0xf264c ata.c:621
+ add bx, word [bp-01eh] ; 03 5e e2 ; 0xf2650
+ mov al, byte [bp-016h] ; 8a 46 ea ; 0xf2653
+ mov byte [es:bx+001f4h], al ; 26 88 87 f4 01 ; 0xf2656
+ inc byte [bp-00ah] ; fe 46 f6 ; 0xf265b ata.c:622
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf265e ata.c:631
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf2661
+ je short 02694h ; 74 2f ; 0xf2663
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf2665
+ jne near 026f7h ; 0f 85 8c 00 ; 0xf2667
+ movzx si, byte [bp-016h] ; 0f b6 76 ea ; 0xf266b ata.c:633
+ imul si, si, strict byte 0001ch ; 6b f6 1c ; 0xf266f
+ mov es, [bp-030h] ; 8e 46 d0 ; 0xf2672
+ add si, word [bp-01eh] ; 03 76 e2 ; 0xf2675
+ mov ax, word [es:si+03ch] ; 26 8b 44 3c ; 0xf2678
+ mov bx, word [es:si+03ah] ; 26 8b 5c 3a ; 0xf267c
+ mov cx, word [es:si+038h] ; 26 8b 4c 38 ; 0xf2680
+ mov dx, word [es:si+036h] ; 26 8b 54 36 ; 0xf2684
+ mov si, strict word 0000bh ; be 0b 00 ; 0xf2688
+ call 09f90h ; e8 02 79 ; 0xf268b
+ mov word [bp-02ah], dx ; 89 56 d6 ; 0xf268e
+ mov word [bp-028h], cx ; 89 4e d8 ; 0xf2691
+ movzx dx, byte [bp-001c5h] ; 0f b6 96 3b fe ; 0xf2694 ata.c:636
+ sal dx, 008h ; c1 e2 08 ; 0xf2699
+ movzx ax, byte [bp-001c6h] ; 0f b6 86 3a fe ; 0xf269c
+ or ax, dx ; 09 d0 ; 0xf26a1
+ mov byte [bp-014h], 00fh ; c6 46 ec 0f ; 0xf26a3 ata.c:637
+ jmp short 026b2h ; eb 09 ; 0xf26a7
+ dec byte [bp-014h] ; fe 4e ec ; 0xf26a9 ata.c:640
+ cmp byte [bp-014h], 000h ; 80 7e ec 00 ; 0xf26ac
+ jbe short 026bfh ; 76 0d ; 0xf26b0
+ movzx cx, byte [bp-014h] ; 0f b6 4e ec ; 0xf26b2
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf26b6
+ sal dx, CL ; d3 e2 ; 0xf26b9
+ test ax, dx ; 85 d0 ; 0xf26bb
+ je short 026a9h ; 74 ea ; 0xf26bd
+ xor di, di ; 31 ff ; 0xf26bf ata.c:643
+ jmp short 026c8h ; eb 05 ; 0xf26c1
+ cmp di, strict byte 00014h ; 83 ff 14 ; 0xf26c3
+ jnl short 026ddh ; 7d 15 ; 0xf26c6
+ mov si, di ; 89 fe ; 0xf26c8 ata.c:644
+ add si, di ; 01 fe ; 0xf26ca
+ mov al, byte [bp+si-0022fh] ; 8a 82 d1 fd ; 0xf26cc
+ mov byte [bp+si-066h], al ; 88 42 9a ; 0xf26d0
+ mov al, byte [bp+si-00230h] ; 8a 82 d0 fd ; 0xf26d3 ata.c:645
+ mov byte [bp+si-065h], al ; 88 42 9b ; 0xf26d7
+ inc di ; 47 ; 0xf26da ata.c:646
+ jmp short 026c3h ; eb e6 ; 0xf26db
+ mov byte [bp-03eh], 000h ; c6 46 c2 00 ; 0xf26dd ata.c:649
+ mov di, strict word 00027h ; bf 27 00 ; 0xf26e1 ata.c:650
+ jmp short 026ebh ; eb 05 ; 0xf26e4
+ dec di ; 4f ; 0xf26e6 ata.c:655
+ test di, di ; 85 ff ; 0xf26e7
+ jle short 026f7h ; 7e 0c ; 0xf26e9
+ cmp byte [bp+di-066h], 020h ; 80 7b 9a 20 ; 0xf26eb
+ jne short 026f7h ; 75 06 ; 0xf26ef
+ mov byte [bp+di-066h], 000h ; c6 43 9a 00 ; 0xf26f1
+ jmp short 026e6h ; eb ef ; 0xf26f5
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf26f7 ata.c:662
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf26fa
+ je short 0275ah ; 74 5c ; 0xf26fc
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf26fe
+ je short 0270bh ; 74 09 ; 0xf2700
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf2702
+ je near 027c2h ; 0f 84 ba 00 ; 0xf2704
+ jmp near 027e1h ; e9 d6 00 ; 0xf2708
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf270b ata.c:665
+ je short 02716h ; 74 05 ; 0xf270f
+ mov ax, 001b1h ; b8 b1 01 ; 0xf2711
+ jmp short 02719h ; eb 03 ; 0xf2714
+ mov ax, 001b8h ; b8 b8 01 ; 0xf2716
+ push ax ; 50 ; 0xf2719
+ movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xf271a
+ push ax ; 50 ; 0xf271e
+ push 001bfh ; 68 bf 01 ; 0xf271f
+ push strict byte 00002h ; 6a 02 ; 0xf2722
+ call 01a14h ; e8 ed f2 ; 0xf2724
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf2727
+ xor di, di ; 31 ff ; 0xf272a ata.c:666
+ movzx ax, byte [bp+di-066h] ; 0f b6 43 9a ; 0xf272c ata.c:667
+ inc di ; 47 ; 0xf2730
+ test ax, ax ; 85 c0 ; 0xf2731
+ je short 02743h ; 74 0e ; 0xf2733
+ push ax ; 50 ; 0xf2735 ata.c:668
+ push 001cah ; 68 ca 01 ; 0xf2736
+ push strict byte 00002h ; 6a 02 ; 0xf2739
+ call 01a14h ; e8 d6 f2 ; 0xf273b
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf273e
+ jmp short 0272ch ; eb e9 ; 0xf2741
+ push dword [bp-02ah] ; 66 ff 76 d6 ; 0xf2743 ata.c:669
+ movzx ax, byte [bp-014h] ; 0f b6 46 ec ; 0xf2747
+ push ax ; 50 ; 0xf274b
+ push 001cdh ; 68 cd 01 ; 0xf274c
+ push strict byte 00002h ; 6a 02 ; 0xf274f
+ call 01a14h ; e8 c0 f2 ; 0xf2751
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf2754
+ jmp near 027e1h ; e9 87 00 ; 0xf2757 ata.c:670
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf275a ata.c:672
+ je short 02765h ; 74 05 ; 0xf275e
+ mov ax, 001b1h ; b8 b1 01 ; 0xf2760
+ jmp short 02768h ; eb 03 ; 0xf2763
+ mov ax, 001b8h ; b8 b8 01 ; 0xf2765
+ push ax ; 50 ; 0xf2768
+ movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xf2769
+ push ax ; 50 ; 0xf276d
+ push 001bfh ; 68 bf 01 ; 0xf276e
+ push strict byte 00002h ; 6a 02 ; 0xf2771
+ call 01a14h ; e8 9e f2 ; 0xf2773
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf2776
+ xor di, di ; 31 ff ; 0xf2779 ata.c:673
+ movzx ax, byte [bp+di-066h] ; 0f b6 43 9a ; 0xf277b ata.c:674
+ inc di ; 47 ; 0xf277f
+ test ax, ax ; 85 c0 ; 0xf2780
+ je short 02792h ; 74 0e ; 0xf2782
+ push ax ; 50 ; 0xf2784 ata.c:675
+ push 001cah ; 68 ca 01 ; 0xf2785
+ push strict byte 00002h ; 6a 02 ; 0xf2788
+ call 01a14h ; e8 87 f2 ; 0xf278a
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf278d
+ jmp short 0277bh ; eb e9 ; 0xf2790
+ movzx bx, byte [bp-016h] ; 0f b6 5e ea ; 0xf2792 ata.c:676
+ imul bx, bx, strict byte 0001ch ; 6b db 1c ; 0xf2796
+ mov es, [bp-030h] ; 8e 46 d0 ; 0xf2799
+ add bx, word [bp-01eh] ; 03 5e e2 ; 0xf279c
+ cmp byte [es:bx+023h], 005h ; 26 80 7f 23 05 ; 0xf279f
+ jne short 027b0h ; 75 0a ; 0xf27a4
+ movzx ax, byte [bp-014h] ; 0f b6 46 ec ; 0xf27a6 ata.c:677
+ push ax ; 50 ; 0xf27aa
+ push 001edh ; 68 ed 01 ; 0xf27ab
+ jmp short 027b8h ; eb 08 ; 0xf27ae ata.c:678
+ movzx ax, byte [bp-014h] ; 0f b6 46 ec ; 0xf27b0 ata.c:679
+ push ax ; 50 ; 0xf27b4
+ push 00207h ; 68 07 02 ; 0xf27b5
+ push strict byte 00002h ; 6a 02 ; 0xf27b8
+ call 01a14h ; e8 57 f2 ; 0xf27ba
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf27bd
+ jmp short 027e1h ; eb 1f ; 0xf27c0 ata.c:680
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf27c2 ata.c:682
+ je short 027cdh ; 74 05 ; 0xf27c6
+ mov ax, 001b1h ; b8 b1 01 ; 0xf27c8
+ jmp short 027d0h ; eb 03 ; 0xf27cb
+ mov ax, 001b8h ; b8 b8 01 ; 0xf27cd
+ push ax ; 50 ; 0xf27d0
+ movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xf27d1
+ push ax ; 50 ; 0xf27d5
+ push 00219h ; 68 19 02 ; 0xf27d6
+ push strict byte 00002h ; 6a 02 ; 0xf27d9
+ call 01a14h ; e8 36 f2 ; 0xf27db
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf27de
+ inc byte [bp-016h] ; fe 46 ea ; 0xf27e1 ata.c:687
+ cmp byte [bp-016h], 008h ; 80 7e ea 08 ; 0xf27e4
+ jnc short 0283bh ; 73 51 ; 0xf27e8
+ movzx bx, byte [bp-016h] ; 0f b6 5e ea ; 0xf27ea
+ mov ax, bx ; 89 d8 ; 0xf27ee
+ cwd ; 99 ; 0xf27f0
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf27f1
+ sar ax, 1 ; d1 f8 ; 0xf27f3
+ mov word [bp-034h], ax ; 89 46 cc ; 0xf27f5
+ mov al, byte [bp-034h] ; 8a 46 cc ; 0xf27f8
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf27fb
+ mov ax, bx ; 89 d8 ; 0xf27fe
+ cwd ; 99 ; 0xf2800
+ mov bx, strict word 00002h ; bb 02 00 ; 0xf2801
+ idiv bx ; f7 fb ; 0xf2804
+ mov cx, dx ; 89 d1 ; 0xf2806
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf2808
+ movzx ax, byte [bp-034h] ; 0f b6 46 cc ; 0xf280b
+ imul ax, ax, strict byte 00006h ; 6b c0 06 ; 0xf280f
+ mov es, [bp-030h] ; 8e 46 d0 ; 0xf2812
+ mov si, word [bp-01eh] ; 8b 76 e2 ; 0xf2815
+ add si, ax ; 01 c6 ; 0xf2818
+ mov bx, word [es:si+00206h] ; 26 8b 9c 06 02 ; 0xf281a
+ mov ax, word [es:si+00208h] ; 26 8b 84 08 02 ; 0xf281f
+ mov word [bp-026h], ax ; 89 46 da ; 0xf2824
+ mov dx, ax ; 89 c2 ; 0xf2827
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2829
+ mov AL, strict byte 00ah ; b0 0a ; 0xf282c
+ out DX, AL ; ee ; 0xf282e
+ test cl, cl ; 84 c9 ; 0xf282f
+ je near 02238h ; 0f 84 03 fa ; 0xf2831
+ mov ax, 000b0h ; b8 b0 00 ; 0xf2835
+ jmp near 0223bh ; e9 00 fa ; 0xf2838
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf283b ata.c:690
+ mov es, [bp-030h] ; 8e 46 d0 ; 0xf283e
+ mov bx, word [bp-01eh] ; 8b 5e e2 ; 0xf2841
+ mov byte [es:bx+001e2h], al ; 26 88 87 e2 01 ; 0xf2844
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf2849 ata.c:691
+ mov byte [es:bx+001f3h], al ; 26 88 87 f3 01 ; 0xf284c
+ mov bx, strict word 00075h ; bb 75 00 ; 0xf2851 ata.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2854
+ mov es, ax ; 8e c0 ; 0xf2857
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf2859
+ mov byte [es:bx], al ; 26 88 07 ; 0xf285c
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf285f ata.c:704
+ pop di ; 5f ; 0xf2862
+ pop si ; 5e ; 0xf2863
+ pop bp ; 5d ; 0xf2864
+ retn ; c3 ; 0xf2865
+ ; disGetNextSymbol 0xf2866 LB 0x77df -> off=0x0 cb=00000000000002bc uValue=00000000000f1266 'ata_cmd_data_out'
+ata_cmd_data_out: ; 0xf2866 LB 0x2bc
+ push bp ; 55 ; 0xf2866 ata.c:718
+ mov bp, sp ; 89 e5 ; 0xf2867
+ push si ; 56 ; 0xf2869
+ push di ; 57 ; 0xf286a
+ sub sp, strict byte 00022h ; 83 ec 22 ; 0xf286b
+ mov di, ax ; 89 c7 ; 0xf286e
+ mov word [bp-00ch], dx ; 89 56 f4 ; 0xf2870
+ mov word [bp-024h], bx ; 89 5e dc ; 0xf2873
+ mov word [bp-01ah], cx ; 89 4e e6 ; 0xf2876
+ mov es, dx ; 8e c2 ; 0xf2879 ata.c:730
+ movzx ax, byte [es:di+00ch] ; 26 0f b6 45 0c ; 0xf287b
+ mov dx, ax ; 89 c2 ; 0xf2880 ata.c:731
+ shr dx, 1 ; d1 ea ; 0xf2882
+ mov dh, al ; 88 c6 ; 0xf2884 ata.c:732
+ and dh, 001h ; 80 e6 01 ; 0xf2886
+ mov byte [bp-006h], dh ; 88 76 fa ; 0xf2889
+ xor dh, dh ; 30 f6 ; 0xf288c ata.c:734
+ imul dx, dx, strict byte 00006h ; 6b d2 06 ; 0xf288e
+ mov bx, di ; 89 fb ; 0xf2891
+ add bx, dx ; 01 d3 ; 0xf2893
+ mov dx, word [es:bx+00206h] ; 26 8b 97 06 02 ; 0xf2895
+ mov word [bp-00ah], dx ; 89 56 f6 ; 0xf289a
+ mov dx, word [es:bx+00208h] ; 26 8b 97 08 02 ; 0xf289d ata.c:735
+ mov word [bp-012h], dx ; 89 56 ee ; 0xf28a2
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf28a5 ata.c:736
+ mov bx, di ; 89 fb ; 0xf28a8
+ add bx, ax ; 01 c3 ; 0xf28aa
+ mov al, byte [es:bx+026h] ; 26 8a 47 26 ; 0xf28ac
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf28b0
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf28b3 ata.c:739
+ jne short 028beh ; 75 07 ; 0xf28b5
+ mov word [bp-020h], 00080h ; c7 46 e0 80 00 ; 0xf28b7 ata.c:740
+ jmp short 028c3h ; eb 05 ; 0xf28bc ata.c:741
+ mov word [bp-020h], 00100h ; c7 46 e0 00 01 ; 0xf28be ata.c:743
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf28c3 ata.c:745
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf28c6
+ in AL, DX ; ec ; 0xf28c9
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf28ca
+ test AL, strict byte 080h ; a8 80 ; 0xf28cc ata.c:746
+ je short 028dfh ; 74 0f ; 0xf28ce
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf28d0 ata.c:749
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf28d3
+ mov AL, strict byte 008h ; b0 08 ; 0xf28d6
+ out DX, AL ; ee ; 0xf28d8
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf28d9 ata.c:750
+ jmp near 02b19h ; e9 3a 02 ; 0xf28dc
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf28df ata.c:753
+ mov ax, word [es:di+006h] ; 26 8b 45 06 ; 0xf28e2
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf28e6
+ mov ax, word [es:di+004h] ; 26 8b 45 04 ; 0xf28e9
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf28ed
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf28f0
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf28f4
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf28f7
+ mov word [bp-01eh], ax ; 89 46 e2 ; 0xf28fa
+ mov ax, word [es:di+008h] ; 26 8b 45 08 ; 0xf28fd ata.c:754
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf2901
+ mov ax, word [es:di+00ah] ; 26 8b 45 0a ; 0xf2904
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf2908
+ mov ax, word [es:di+016h] ; 26 8b 45 16 ; 0xf290b ata.c:755
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf290f
+ mov ax, word [es:di+012h] ; 26 8b 45 12 ; 0xf2912 ata.c:756
+ mov word [bp-026h], ax ; 89 46 da ; 0xf2916
+ mov ax, word [es:di+014h] ; 26 8b 45 14 ; 0xf2919 ata.c:757
+ mov word [bp-022h], ax ; 89 46 de ; 0xf291d
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf2920 ata.c:760
+ test ax, ax ; 85 c0 ; 0xf2923
+ jne near 029f0h ; 0f 85 c7 00 ; 0xf2925
+ xor dx, dx ; 31 d2 ; 0xf2929 ata.c:761
+ xor bx, bx ; 31 db ; 0xf292b
+ mov si, word [bp-01eh] ; 8b 76 e2 ; 0xf292d
+ add si, word [bp-01ah] ; 03 76 e6 ; 0xf2930
+ adc dx, word [bp-016h] ; 13 56 ea ; 0xf2933
+ adc bx, word [bp-014h] ; 13 5e ec ; 0xf2936
+ adc ax, word [bp-010h] ; 13 46 f0 ; 0xf2939
+ test ax, ax ; 85 c0 ; 0xf293c
+ jnbe short 02950h ; 77 10 ; 0xf293e
+ jne short 029b3h ; 75 71 ; 0xf2940
+ test bx, bx ; 85 db ; 0xf2942
+ jnbe short 02950h ; 77 0a ; 0xf2944
+ jne short 029b3h ; 75 6b ; 0xf2946
+ cmp dx, 01000h ; 81 fa 00 10 ; 0xf2948
+ jnbe short 02950h ; 77 02 ; 0xf294c
+ jne short 029b3h ; 75 63 ; 0xf294e
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf2950 ata.c:763
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf2953
+ mov cx, word [bp-016h] ; 8b 4e ea ; 0xf2956
+ mov dx, word [bp-01eh] ; 8b 56 e2 ; 0xf2959
+ mov si, strict word 00018h ; be 18 00 ; 0xf295c
+ call 09f90h ; e8 2e 76 ; 0xf295f
+ xor dh, dh ; 30 f6 ; 0xf2962
+ mov word [bp-01ch], dx ; 89 56 e4 ; 0xf2964
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf2967 ata.c:764
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf296a
+ mov cx, word [bp-016h] ; 8b 4e ea ; 0xf296d
+ mov dx, word [bp-01eh] ; 8b 56 e2 ; 0xf2970
+ mov si, strict word 00020h ; be 20 00 ; 0xf2973
+ call 09f90h ; e8 17 76 ; 0xf2976
+ mov bx, dx ; 89 d3 ; 0xf2979
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf297b ata.c:765
+ xor al, al ; 30 c0 ; 0xf297e
+ shr ax, 008h ; c1 e8 08 ; 0xf2980
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2983
+ inc dx ; 42 ; 0xf2986
+ inc dx ; 42 ; 0xf2987
+ out DX, AL ; ee ; 0xf2988
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2989 ata.c:766
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf298c
+ mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xf298f
+ out DX, AL ; ee ; 0xf2992
+ mov ax, bx ; 89 d8 ; 0xf2993 ata.c:767
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2995
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf2998
+ out DX, AL ; ee ; 0xf299b
+ shr ax, 008h ; c1 e8 08 ; 0xf299c ata.c:768
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf299f
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf29a2
+ out DX, AL ; ee ; 0xf29a5
+ xor al, al ; 30 c0 ; 0xf29a6 ata.c:771
+ mov byte [bp-015h], al ; 88 46 eb ; 0xf29a8
+ xor ah, ah ; 30 e4 ; 0xf29ab
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf29ad
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf29b0
+ mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xf29b3 ata.c:773
+ xor ah, ah ; 30 e4 ; 0xf29b6
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf29b8
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf29bb ata.c:774
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf29be
+ mov cx, word [bp-016h] ; 8b 4e ea ; 0xf29c1
+ mov dx, word [bp-01eh] ; 8b 56 e2 ; 0xf29c4
+ mov si, strict word 00008h ; be 08 00 ; 0xf29c7
+ call 09f90h ; e8 c3 75 ; 0xf29ca
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf29cd
+ mov word [bp-014h], bx ; 89 5e ec ; 0xf29d0
+ mov word [bp-016h], cx ; 89 4e ea ; 0xf29d3
+ mov word [bp-01eh], dx ; 89 56 e2 ; 0xf29d6
+ mov word [bp-026h], dx ; 89 56 da ; 0xf29d9 ata.c:775
+ mov si, strict word 00010h ; be 10 00 ; 0xf29dc ata.c:776
+ call 09f90h ; e8 ae 75 ; 0xf29df
+ mov word [bp-01eh], dx ; 89 56 e2 ; 0xf29e2
+ mov ax, dx ; 89 d0 ; 0xf29e5 ata.c:777
+ xor ah, dh ; 30 f4 ; 0xf29e7
+ and AL, strict byte 00fh ; 24 0f ; 0xf29e9
+ or AL, strict byte 040h ; 0c 40 ; 0xf29eb
+ mov word [bp-022h], ax ; 89 46 de ; 0xf29ed
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf29f0 ata.c:780
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf29f3
+ mov AL, strict byte 00ah ; b0 0a ; 0xf29f6
+ out DX, AL ; ee ; 0xf29f8
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf29f9 ata.c:781
+ inc dx ; 42 ; 0xf29fc
+ xor al, al ; 30 c0 ; 0xf29fd
+ out DX, AL ; ee ; 0xf29ff
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2a00 ata.c:782
+ inc dx ; 42 ; 0xf2a03
+ inc dx ; 42 ; 0xf2a04
+ mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xf2a05
+ out DX, AL ; ee ; 0xf2a08
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2a09 ata.c:783
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf2a0c
+ mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xf2a0f
+ out DX, AL ; ee ; 0xf2a12
+ mov ax, word [bp-026h] ; 8b 46 da ; 0xf2a13 ata.c:784
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2a16
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf2a19
+ out DX, AL ; ee ; 0xf2a1c
+ shr ax, 008h ; c1 e8 08 ; 0xf2a1d ata.c:785
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2a20
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf2a23
+ out DX, AL ; ee ; 0xf2a26
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf2a27 ata.c:786
+ je short 02a32h ; 74 05 ; 0xf2a2b
+ mov ax, 000b0h ; b8 b0 00 ; 0xf2a2d
+ jmp short 02a35h ; eb 03 ; 0xf2a30
+ mov ax, 000a0h ; b8 a0 00 ; 0xf2a32
+ movzx dx, byte [bp-022h] ; 0f b6 56 de ; 0xf2a35
+ or ax, dx ; 09 d0 ; 0xf2a39
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2a3b
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2a3e
+ out DX, AL ; ee ; 0xf2a41
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2a42 ata.c:787
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2a45
+ mov al, byte [bp-024h] ; 8a 46 dc ; 0xf2a48
+ out DX, AL ; ee ; 0xf2a4b
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2a4c ata.c:790
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2a4f
+ in AL, DX ; ec ; 0xf2a52
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2a53
+ mov dl, al ; 88 c2 ; 0xf2a55
+ test AL, strict byte 080h ; a8 80 ; 0xf2a57 ata.c:791
+ jne short 02a4ch ; 75 f1 ; 0xf2a59
+ test AL, strict byte 001h ; a8 01 ; 0xf2a5b ata.c:795
+ je short 02a6eh ; 74 0f ; 0xf2a5d
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf2a5f ata.c:798
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2a62
+ mov AL, strict byte 008h ; b0 08 ; 0xf2a65
+ out DX, AL ; ee ; 0xf2a67
+ mov dx, strict word 00002h ; ba 02 00 ; 0xf2a68 ata.c:799
+ jmp near 02b19h ; e9 ab 00 ; 0xf2a6b
+ test dl, 008h ; f6 c2 08 ; 0xf2a6e ata.c:800
+ jne short 02a82h ; 75 0f ; 0xf2a71
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf2a73 ata.c:803
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2a76
+ mov AL, strict byte 008h ; b0 08 ; 0xf2a79
+ out DX, AL ; ee ; 0xf2a7b
+ mov dx, strict word 00003h ; ba 03 00 ; 0xf2a7c ata.c:804
+ jmp near 02b19h ; e9 97 00 ; 0xf2a7f
+ sti ; fb ; 0xf2a82 ata.c:809
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf2a83 ata.c:814
+ cmp ax, 0f800h ; 3d 00 f8 ; 0xf2a86
+ jc short 02a9bh ; 72 10 ; 0xf2a89
+ sub ax, 00800h ; 2d 00 08 ; 0xf2a8b ata.c:815
+ mov dx, word [bp-018h] ; 8b 56 e8 ; 0xf2a8e
+ add dx, 00080h ; 81 c2 80 00 ; 0xf2a91
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf2a95
+ mov word [bp-018h], dx ; 89 56 e8 ; 0xf2a98
+ cmp byte [bp-008h], 001h ; 80 7e f8 01 ; 0xf2a9b ata.c:818
+ jne short 02ab3h ; 75 12 ; 0xf2a9f
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2aa1 ata.c:819
+ mov cx, word [bp-020h] ; 8b 4e e0 ; 0xf2aa4
+ mov si, word [bp-00eh] ; 8b 76 f2 ; 0xf2aa7
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf2aaa
+ db 0f3h, 066h, 026h, 06fh
+ ; rep es outsd ; f3 66 26 6f ; 0xf2aad
+ jmp short 02ac2h ; eb 0f ; 0xf2ab1 ata.c:820
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2ab3 ata.c:822
+ mov cx, word [bp-020h] ; 8b 4e e0 ; 0xf2ab6
+ mov si, word [bp-00eh] ; 8b 76 f2 ; 0xf2ab9
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf2abc
+ db 0f3h, 026h, 06fh
+ ; rep es outsw ; f3 26 6f ; 0xf2abf
+ mov word [bp-00eh], si ; 89 76 f2 ; 0xf2ac2
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf2ac5 ata.c:824
+ inc word [es:di+018h] ; 26 ff 45 18 ; 0xf2ac8
+ dec word [bp-01ah] ; ff 4e e6 ; 0xf2acc ata.c:825
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2acf ata.c:827
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2ad2
+ in AL, DX ; ec ; 0xf2ad5
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2ad6
+ mov dl, al ; 88 c2 ; 0xf2ad8
+ test AL, strict byte 080h ; a8 80 ; 0xf2ada ata.c:828
+ jne short 02acfh ; 75 f1 ; 0xf2adc
+ cmp word [bp-01ah], strict byte 00000h ; 83 7e e6 00 ; 0xf2ade ata.c:831
+ jne short 02af8h ; 75 14 ; 0xf2ae2
+ and AL, strict byte 0e9h ; 24 e9 ; 0xf2ae4 ata.c:832
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf2ae6
+ je short 02b0eh ; 74 24 ; 0xf2ae8
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf2aea ata.c:836
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2aed
+ mov AL, strict byte 008h ; b0 08 ; 0xf2af0
+ out DX, AL ; ee ; 0xf2af2
+ mov dx, strict word 00006h ; ba 06 00 ; 0xf2af3 ata.c:837
+ jmp short 02b19h ; eb 21 ; 0xf2af6
+ mov al, dl ; 88 d0 ; 0xf2af8 ata.c:842
+ and AL, strict byte 0c9h ; 24 c9 ; 0xf2afa
+ cmp AL, strict byte 048h ; 3c 48 ; 0xf2afc
+ je short 02a83h ; 74 83 ; 0xf2afe
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf2b00 ata.c:846
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2b03
+ mov AL, strict byte 008h ; b0 08 ; 0xf2b06
+ out DX, AL ; ee ; 0xf2b08
+ mov dx, strict word 00007h ; ba 07 00 ; 0xf2b09 ata.c:847
+ jmp short 02b19h ; eb 0b ; 0xf2b0c
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf2b0e ata.c:853
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2b11
+ mov AL, strict byte 008h ; b0 08 ; 0xf2b14
+ out DX, AL ; ee ; 0xf2b16
+ xor dx, dx ; 31 d2 ; 0xf2b17 ata.c:854
+ mov ax, dx ; 89 d0 ; 0xf2b19 ata.c:855
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf2b1b
+ pop di ; 5f ; 0xf2b1e
+ pop si ; 5e ; 0xf2b1f
+ pop bp ; 5d ; 0xf2b20
+ retn ; c3 ; 0xf2b21
+ ; disGetNextSymbol 0xf2b22 LB 0x7523 -> off=0x0 cb=00000000000000b5 uValue=00000000000f1522 'ata_read_sectors'
+ata_read_sectors: ; 0xf2b22 LB 0xb5
+ push bp ; 55 ; 0xf2b22 ata.c:865
+ mov bp, sp ; 89 e5 ; 0xf2b23
+ push si ; 56 ; 0xf2b25
+ push di ; 57 ; 0xf2b26
+ sub sp, strict byte 00008h ; 83 ec 08 ; 0xf2b27
+ mov si, word [bp+004h] ; 8b 76 04 ; 0xf2b2a
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf2b2d ata.c:871
+ mov al, byte [es:si+00ch] ; 26 8a 44 0c ; 0xf2b30
+ mov cx, word [es:si+00eh] ; 26 8b 4c 0e ; 0xf2b34 ata.c:872
+ mov dx, cx ; 89 ca ; 0xf2b38
+ sal dx, 009h ; c1 e2 09 ; 0xf2b3a
+ cmp word [es:si+016h], strict byte 00000h ; 26 83 7c 16 00 ; 0xf2b3d ata.c:874
+ je short 02b63h ; 74 1f ; 0xf2b42
+ xor ah, ah ; 30 e4 ; 0xf2b44 ata.c:876
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf2b46
+ mov [bp-00ah], es ; 8c 46 f6 ; 0xf2b49
+ mov di, si ; 89 f7 ; 0xf2b4c
+ add di, ax ; 01 c7 ; 0xf2b4e
+ mov word [es:di+028h], dx ; 26 89 55 28 ; 0xf2b50
+ mov bx, 000c4h ; bb c4 00 ; 0xf2b54 ata.c:878
+ mov ax, si ; 89 f0 ; 0xf2b57
+ mov dx, es ; 8c c2 ; 0xf2b59
+ call 01efah ; e8 9c f3 ; 0xf2b5b
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf2b5e ata.c:879
+ jmp short 02bc8h ; eb 65 ; 0xf2b61 ata.c:880
+ xor bx, bx ; 31 db ; 0xf2b63 ata.c:882
+ mov word [bp-00ah], bx ; 89 5e f6 ; 0xf2b65
+ mov word [bp-00ch], bx ; 89 5e f4 ; 0xf2b68
+ mov di, word [es:si] ; 26 8b 3c ; 0xf2b6b
+ add di, cx ; 01 cf ; 0xf2b6e
+ mov word [bp-008h], di ; 89 7e f8 ; 0xf2b70
+ mov di, word [es:si+002h] ; 26 8b 7c 02 ; 0xf2b73
+ adc di, bx ; 11 df ; 0xf2b77
+ mov word [bp-006h], di ; 89 7e fa ; 0xf2b79
+ mov bx, word [es:si+004h] ; 26 8b 5c 04 ; 0xf2b7c
+ adc bx, word [bp-00ah] ; 13 5e f6 ; 0xf2b80
+ mov di, word [es:si+006h] ; 26 8b 7c 06 ; 0xf2b83
+ adc di, word [bp-00ch] ; 13 7e f4 ; 0xf2b87
+ test di, di ; 85 ff ; 0xf2b8a
+ jnbe short 02b9fh ; 77 11 ; 0xf2b8c
+ jne short 02babh ; 75 1b ; 0xf2b8e
+ test bx, bx ; 85 db ; 0xf2b90
+ jnbe short 02b9fh ; 77 0b ; 0xf2b92
+ jne short 02babh ; 75 15 ; 0xf2b94
+ cmp word [bp-006h], 01000h ; 81 7e fa 00 10 ; 0xf2b96
+ jnbe short 02b9fh ; 77 02 ; 0xf2b9b
+ jne short 02babh ; 75 0c ; 0xf2b9d
+ mov bx, strict word 00024h ; bb 24 00 ; 0xf2b9f ata.c:884
+ mov ax, si ; 89 f0 ; 0xf2ba2
+ mov dx, es ; 8c c2 ; 0xf2ba4
+ call 01efah ; e8 51 f3 ; 0xf2ba6
+ jmp short 02bceh ; eb 23 ; 0xf2ba9 ata.c:885
+ xor ah, ah ; 30 e4 ; 0xf2bab ata.c:886
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf2bad
+ mov [bp-006h], es ; 8c 46 fa ; 0xf2bb0
+ mov di, si ; 89 f7 ; 0xf2bb3
+ add di, ax ; 01 c7 ; 0xf2bb5
+ mov word [es:di+028h], dx ; 26 89 55 28 ; 0xf2bb7
+ mov bx, 000c4h ; bb c4 00 ; 0xf2bbb ata.c:888
+ mov ax, si ; 89 f0 ; 0xf2bbe
+ mov dx, es ; 8c c2 ; 0xf2bc0
+ call 01efah ; e8 35 f3 ; 0xf2bc2
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf2bc5 ata.c:889
+ mov word [es:di+028h], 00200h ; 26 c7 45 28 00 02 ; 0xf2bc8
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf2bce ata.c:893
+ pop di ; 5f ; 0xf2bd1
+ pop si ; 5e ; 0xf2bd2
+ pop bp ; 5d ; 0xf2bd3
+ retn 00004h ; c2 04 00 ; 0xf2bd4
+ ; disGetNextSymbol 0xf2bd7 LB 0x746e -> off=0x0 cb=000000000000005b uValue=00000000000f15d7 'ata_write_sectors'
+ata_write_sectors: ; 0xf2bd7 LB 0x5b
+ push bp ; 55 ; 0xf2bd7 ata.c:902
+ mov bp, sp ; 89 e5 ; 0xf2bd8
+ push si ; 56 ; 0xf2bda
+ push di ; 57 ; 0xf2bdb
+ push ax ; 50 ; 0xf2bdc
+ les si, [bp+004h] ; c4 76 04 ; 0xf2bdd
+ mov cx, word [es:si+00eh] ; 26 8b 4c 0e ; 0xf2be0 ata.c:906
+ cmp word [es:si+016h], strict byte 00000h ; 26 83 7c 16 00 ; 0xf2be4 ata.c:908
+ je short 02bf7h ; 74 0c ; 0xf2be9
+ mov bx, strict word 00030h ; bb 30 00 ; 0xf2beb ata.c:910
+ mov ax, si ; 89 f0 ; 0xf2bee
+ mov dx, es ; 8c c2 ; 0xf2bf0
+ call 02866h ; e8 71 fc ; 0xf2bf2
+ jmp short 02c29h ; eb 32 ; 0xf2bf5
+ xor ax, ax ; 31 c0 ; 0xf2bf7 ata.c:913
+ xor bx, bx ; 31 db ; 0xf2bf9
+ xor dx, dx ; 31 d2 ; 0xf2bfb
+ mov di, word [es:si] ; 26 8b 3c ; 0xf2bfd
+ add di, cx ; 01 cf ; 0xf2c00
+ mov word [bp-006h], di ; 89 7e fa ; 0xf2c02
+ adc ax, word [es:si+002h] ; 26 13 44 02 ; 0xf2c05
+ adc bx, word [es:si+004h] ; 26 13 5c 04 ; 0xf2c09
+ adc dx, word [es:si+006h] ; 26 13 54 06 ; 0xf2c0d
+ test dx, dx ; 85 d2 ; 0xf2c11
+ jnbe short 02c24h ; 77 0f ; 0xf2c13
+ jne short 02bebh ; 75 d4 ; 0xf2c15
+ test bx, bx ; 85 db ; 0xf2c17
+ jnbe short 02c24h ; 77 09 ; 0xf2c19
+ jne short 02bebh ; 75 ce ; 0xf2c1b
+ cmp ax, 01000h ; 3d 00 10 ; 0xf2c1d
+ jnbe short 02c24h ; 77 02 ; 0xf2c20
+ jne short 02bebh ; 75 c7 ; 0xf2c22
+ mov bx, strict word 00034h ; bb 34 00 ; 0xf2c24 ata.c:914
+ jmp short 02beeh ; eb c5 ; 0xf2c27
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf2c29 ata.c:918
+ pop di ; 5f ; 0xf2c2c
+ pop si ; 5e ; 0xf2c2d
+ pop bp ; 5d ; 0xf2c2e
+ retn 00004h ; c2 04 00 ; 0xf2c2f
+ ; disGetNextSymbol 0xf2c32 LB 0x7413 -> off=0x0 cb=00000000000002df uValue=00000000000f1632 'ata_cmd_packet'
+ata_cmd_packet: ; 0xf2c32 LB 0x2df
+ push bp ; 55 ; 0xf2c32 ata.c:930
+ mov bp, sp ; 89 e5 ; 0xf2c33
+ push si ; 56 ; 0xf2c35
+ push di ; 57 ; 0xf2c36
+ sub sp, strict byte 00014h ; 83 ec 14 ; 0xf2c37
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf2c3a
+ mov di, bx ; 89 df ; 0xf2c3d
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf2c3f ata.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf2c42
+ mov es, dx ; 8e c2 ; 0xf2c45
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf2c47
+ mov word [bp-012h], 00122h ; c7 46 ee 22 01 ; 0xf2c4a ata.c:49
+ mov word [bp-010h], dx ; 89 56 f0 ; 0xf2c4f
+ mov dx, ax ; 89 c2 ; 0xf2c52 ata.c:942
+ shr dx, 1 ; d1 ea ; 0xf2c54
+ mov dh, al ; 88 c6 ; 0xf2c56 ata.c:943
+ and dh, 001h ; 80 e6 01 ; 0xf2c58
+ mov byte [bp-00ah], dh ; 88 76 f6 ; 0xf2c5b
+ cmp byte [bp+00ah], 002h ; 80 7e 0a 02 ; 0xf2c5e ata.c:946
+ jne short 02c83h ; 75 1f ; 0xf2c62
+ mov bx, 00db2h ; bb b2 0d ; 0xf2c64 ata.c:947
+ mov cx, ds ; 8c d9 ; 0xf2c67
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf2c69
+ call 019d3h ; e8 64 ed ; 0xf2c6c
+ push 00233h ; 68 33 02 ; 0xf2c6f
+ push 00242h ; 68 42 02 ; 0xf2c72
+ push strict byte 00004h ; 6a 04 ; 0xf2c75
+ call 01a14h ; e8 9a ed ; 0xf2c77
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf2c7a
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf2c7d ata.c:948
+ jmp near 02f06h ; e9 83 02 ; 0xf2c80
+ test byte [bp+004h], 001h ; f6 46 04 01 ; 0xf2c83 ata.c:952
+ jne short 02c7dh ; 75 f4 ; 0xf2c87
+ xor dh, dh ; 30 f6 ; 0xf2c89 ata.c:957
+ imul dx, dx, strict byte 00006h ; 6b d2 06 ; 0xf2c8b
+ les si, [bp-012h] ; c4 76 ee ; 0xf2c8e
+ add si, dx ; 01 d6 ; 0xf2c91
+ mov bx, word [es:si+00206h] ; 26 8b 9c 06 02 ; 0xf2c93
+ mov dx, word [es:si+00208h] ; 26 8b 94 08 02 ; 0xf2c98 ata.c:958
+ mov word [bp-018h], dx ; 89 56 e8 ; 0xf2c9d
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf2ca0 ata.c:959
+ mov si, word [bp-012h] ; 8b 76 ee ; 0xf2ca3
+ add si, ax ; 01 c6 ; 0xf2ca6
+ mov al, byte [es:si+026h] ; 26 8a 44 26 ; 0xf2ca8
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf2cac
+ xor ax, ax ; 31 c0 ; 0xf2caf ata.c:960
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf2cb1
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf2cb4
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf2cb7 ata.c:962
+ cmp AL, strict byte 00ch ; 3c 0c ; 0xf2cba
+ jnc short 02cc4h ; 73 06 ; 0xf2cbc
+ mov byte [bp-006h], 00ch ; c6 46 fa 0c ; 0xf2cbe ata.c:963
+ jmp short 02ccah ; eb 06 ; 0xf2cc2
+ jbe short 02ccah ; 76 04 ; 0xf2cc4 ata.c:964
+ mov byte [bp-006h], 010h ; c6 46 fa 10 ; 0xf2cc6 ata.c:965
+ shr byte [bp-006h], 1 ; d0 6e fa ; 0xf2cca ata.c:966
+ les si, [bp-012h] ; c4 76 ee ; 0xf2ccd ata.c:970
+ db 066h, 026h, 0c7h, 044h, 018h, 000h, 000h, 000h, 000h
+ ; mov dword [es:si+018h], strict dword 000000000h ; 66 26 c7 44 18 00 00 00 00; 0xf2cd0
+ mov word [es:si+01ch], strict word 00000h ; 26 c7 44 1c 00 00 ; 0xf2cd9 ata.c:971
+ lea dx, [bx+007h] ; 8d 57 07 ; 0xf2cdf ata.c:973
+ in AL, DX ; ec ; 0xf2ce2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2ce3
+ test AL, strict byte 080h ; a8 80 ; 0xf2ce5 ata.c:974
+ je short 02cefh ; 74 06 ; 0xf2ce7
+ mov dx, strict word 00002h ; ba 02 00 ; 0xf2ce9 ata.c:975
+ jmp near 02f06h ; e9 17 02 ; 0xf2cec
+ mov dx, word [bp-018h] ; 8b 56 e8 ; 0xf2cef ata.c:977
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2cf2
+ mov AL, strict byte 00ah ; b0 0a ; 0xf2cf5
+ out DX, AL ; ee ; 0xf2cf7
+ lea dx, [bx+004h] ; 8d 57 04 ; 0xf2cf8 ata.c:981
+ mov AL, strict byte 0f0h ; b0 f0 ; 0xf2cfb
+ out DX, AL ; ee ; 0xf2cfd
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf2cfe ata.c:982
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf2d01
+ out DX, AL ; ee ; 0xf2d03
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf2d04 ata.c:983
+ je short 02d0fh ; 74 05 ; 0xf2d08
+ mov ax, 000b0h ; b8 b0 00 ; 0xf2d0a
+ jmp short 02d12h ; eb 03 ; 0xf2d0d
+ mov ax, 000a0h ; b8 a0 00 ; 0xf2d0f
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf2d12
+ out DX, AL ; ee ; 0xf2d15
+ lea dx, [bx+007h] ; 8d 57 07 ; 0xf2d16 ata.c:984
+ mov AL, strict byte 0a0h ; b0 a0 ; 0xf2d19
+ out DX, AL ; ee ; 0xf2d1b
+ lea dx, [bx+007h] ; 8d 57 07 ; 0xf2d1c ata.c:988
+ in AL, DX ; ec ; 0xf2d1f
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2d20
+ mov dl, al ; 88 c2 ; 0xf2d22
+ test AL, strict byte 080h ; a8 80 ; 0xf2d24 ata.c:989
+ jne short 02d1ch ; 75 f4 ; 0xf2d26
+ test AL, strict byte 001h ; a8 01 ; 0xf2d28 ata.c:992
+ je short 02d3bh ; 74 0f ; 0xf2d2a
+ mov dx, word [bp-018h] ; 8b 56 e8 ; 0xf2d2c ata.c:995
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2d2f
+ mov AL, strict byte 008h ; b0 08 ; 0xf2d32
+ out DX, AL ; ee ; 0xf2d34
+ mov dx, strict word 00003h ; ba 03 00 ; 0xf2d35 ata.c:996
+ jmp near 02f06h ; e9 cb 01 ; 0xf2d38
+ test dl, 008h ; f6 c2 08 ; 0xf2d3b ata.c:997
+ jne short 02d4fh ; 75 0f ; 0xf2d3e
+ mov dx, word [bp-018h] ; 8b 56 e8 ; 0xf2d40 ata.c:1000
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2d43
+ mov AL, strict byte 008h ; b0 08 ; 0xf2d46
+ out DX, AL ; ee ; 0xf2d48
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf2d49 ata.c:1001
+ jmp near 02f06h ; e9 b7 01 ; 0xf2d4c
+ sti ; fb ; 0xf2d4f ata.c:1004
+ mov ax, di ; 89 f8 ; 0xf2d50 ata.c:1008
+ shr ax, 004h ; c1 e8 04 ; 0xf2d52
+ add ax, cx ; 01 c8 ; 0xf2d55
+ mov si, di ; 89 fe ; 0xf2d57
+ and si, strict byte 0000fh ; 83 e6 0f ; 0xf2d59
+ movzx cx, byte [bp-006h] ; 0f b6 4e fa ; 0xf2d5c ata.c:1013
+ mov dx, bx ; 89 da ; 0xf2d60
+ mov es, ax ; 8e c0 ; 0xf2d62
+ db 0f3h, 026h, 06fh
+ ; rep es outsw ; f3 26 6f ; 0xf2d64
+ cmp byte [bp+00ah], 000h ; 80 7e 0a 00 ; 0xf2d67 ata.c:1015
+ jne short 02d78h ; 75 0b ; 0xf2d6b
+ lea dx, [bx+007h] ; 8d 57 07 ; 0xf2d6d ata.c:1016
+ in AL, DX ; ec ; 0xf2d70
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2d71
+ mov dl, al ; 88 c2 ; 0xf2d73
+ jmp near 02ee7h ; e9 6f 01 ; 0xf2d75 ata.c:1018
+ lea dx, [bx+007h] ; 8d 57 07 ; 0xf2d78 ata.c:1022
+ in AL, DX ; ec ; 0xf2d7b
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2d7c
+ mov dl, al ; 88 c2 ; 0xf2d7e
+ test AL, strict byte 080h ; a8 80 ; 0xf2d80 ata.c:1023
+ jne short 02d78h ; 75 f4 ; 0xf2d82
+ test AL, strict byte 088h ; a8 88 ; 0xf2d84 ata.c:1028
+ je near 02ee7h ; 0f 84 5d 01 ; 0xf2d86
+ test AL, strict byte 001h ; a8 01 ; 0xf2d8a ata.c:1031
+ je short 02d99h ; 74 0b ; 0xf2d8c
+ mov dx, word [bp-018h] ; 8b 56 e8 ; 0xf2d8e ata.c:1034
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2d91
+ mov AL, strict byte 008h ; b0 08 ; 0xf2d94
+ out DX, AL ; ee ; 0xf2d96
+ jmp short 02d35h ; eb 9c ; 0xf2d97
+ mov al, dl ; 88 d0 ; 0xf2d99 ata.c:1039
+ and AL, strict byte 0c9h ; 24 c9 ; 0xf2d9b
+ cmp AL, strict byte 048h ; 3c 48 ; 0xf2d9d
+ je short 02dach ; 74 0b ; 0xf2d9f
+ mov dx, word [bp-018h] ; 8b 56 e8 ; 0xf2da1 ata.c:1043
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2da4
+ mov AL, strict byte 008h ; b0 08 ; 0xf2da7
+ out DX, AL ; ee ; 0xf2da9
+ jmp short 02d49h ; eb 9d ; 0xf2daa
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf2dac ata.c:1049
+ shr ax, 004h ; c1 e8 04 ; 0xf2daf
+ mov dx, word [bp+00eh] ; 8b 56 0e ; 0xf2db2
+ add dx, ax ; 01 c2 ; 0xf2db5
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf2db7
+ and ax, strict word 0000fh ; 25 0f 00 ; 0xf2dba
+ mov word [bp+00ch], ax ; 89 46 0c ; 0xf2dbd
+ mov word [bp+00eh], dx ; 89 56 0e ; 0xf2dc0
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf2dc3 ata.c:1054
+ in AL, DX ; ec ; 0xf2dc6
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2dc7
+ mov cx, ax ; 89 c1 ; 0xf2dc9
+ sal cx, 008h ; c1 e1 08 ; 0xf2dcb
+ lea dx, [bx+004h] ; 8d 57 04 ; 0xf2dce
+ in AL, DX ; ec ; 0xf2dd1
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2dd2
+ add cx, ax ; 01 c1 ; 0xf2dd4
+ mov word [bp-00ch], cx ; 89 4e f4 ; 0xf2dd6
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf2dd9 ata.c:1057
+ cmp ax, cx ; 39 c8 ; 0xf2ddc
+ jbe short 02dech ; 76 0c ; 0xf2dde
+ mov ax, cx ; 89 c8 ; 0xf2de0 ata.c:1059
+ sub word [bp+004h], cx ; 29 4e 04 ; 0xf2de2
+ xor ax, cx ; 31 c8 ; 0xf2de5 ata.c:1060
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf2de7
+ jmp short 02df6h ; eb 0a ; 0xf2dea ata.c:1062
+ mov cx, ax ; 89 c1 ; 0xf2dec ata.c:1063
+ mov word [bp+004h], strict word 00000h ; c7 46 04 00 00 ; 0xf2dee ata.c:1064
+ sub word [bp-00ch], ax ; 29 46 f4 ; 0xf2df3 ata.c:1065
+ xor ax, ax ; 31 c0 ; 0xf2df6 ata.c:1068
+ cmp word [bp+008h], strict byte 00000h ; 83 7e 08 00 ; 0xf2df8
+ jne short 02e1fh ; 75 21 ; 0xf2dfc
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2dfe
+ cmp dx, word [bp+006h] ; 3b 56 06 ; 0xf2e01
+ jbe short 02e1fh ; 76 19 ; 0xf2e04
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf2e06 ata.c:1069
+ sub ax, word [bp+006h] ; 2b 46 06 ; 0xf2e09
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf2e0c
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf2e0f ata.c:1070
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf2e12
+ xor ax, ax ; 31 c0 ; 0xf2e15 ata.c:1071
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf2e17
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf2e1a
+ jmp short 02e2bh ; eb 0c ; 0xf2e1d ata.c:1073
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf2e1f ata.c:1074
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2e22 ata.c:1075
+ sub word [bp+006h], dx ; 29 56 06 ; 0xf2e25
+ sbb word [bp+008h], ax ; 19 46 08 ; 0xf2e28
+ mov si, word [bp-00ch] ; 8b 76 f4 ; 0xf2e2b ata.c:1079
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf2e2e ata.c:1085
+ test cl, 003h ; f6 c1 03 ; 0xf2e31 ata.c:1086
+ je short 02e38h ; 74 02 ; 0xf2e34
+ xor al, al ; 30 c0 ; 0xf2e36 ata.c:1087
+ test byte [bp-00ch], 003h ; f6 46 f4 03 ; 0xf2e38 ata.c:1088
+ je short 02e40h ; 74 02 ; 0xf2e3c
+ xor al, al ; 30 c0 ; 0xf2e3e ata.c:1089
+ test byte [bp-00eh], 003h ; f6 46 f2 03 ; 0xf2e40 ata.c:1090
+ je short 02e48h ; 74 02 ; 0xf2e44
+ xor al, al ; 30 c0 ; 0xf2e46 ata.c:1091
+ test byte [bp-00ch], 001h ; f6 46 f4 01 ; 0xf2e48 ata.c:1094
+ je short 02e60h ; 74 12 ; 0xf2e4c
+ inc word [bp-00ch] ; ff 46 f4 ; 0xf2e4e ata.c:1095
+ cmp word [bp-00eh], strict byte 00000h ; 83 7e f2 00 ; 0xf2e51 ata.c:1096
+ jbe short 02e60h ; 76 09 ; 0xf2e55
+ test byte [bp-00eh], 001h ; f6 46 f2 01 ; 0xf2e57
+ je short 02e60h ; 74 03 ; 0xf2e5b
+ dec word [bp-00eh] ; ff 4e f2 ; 0xf2e5d ata.c:1097
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf2e60 ata.c:1102
+ jne short 02e71h ; 75 0d ; 0xf2e62
+ shr word [bp-00ch], 002h ; c1 6e f4 02 ; 0xf2e64 ata.c:1103
+ shr cx, 002h ; c1 e9 02 ; 0xf2e68 ata.c:1104
+ shr word [bp-00eh], 002h ; c1 6e f2 02 ; 0xf2e6b ata.c:1105
+ jmp short 02e79h ; eb 08 ; 0xf2e6f ata.c:1106
+ shr word [bp-00ch], 1 ; d1 6e f4 ; 0xf2e71 ata.c:1109
+ shr cx, 1 ; d1 e9 ; 0xf2e74 ata.c:1110
+ shr word [bp-00eh], 1 ; d1 6e f2 ; 0xf2e76 ata.c:1111
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf2e79 ata.c:1115
+ jne short 02ea9h ; 75 2c ; 0xf2e7b
+ test cx, cx ; 85 c9 ; 0xf2e7d ata.c:1116
+ je short 02e8bh ; 74 0a ; 0xf2e7f
+ mov dx, bx ; 89 da ; 0xf2e81 ata.c:1117
+ push eax ; 66 50 ; 0xf2e83
+ in eax, DX ; 66 ed ; 0xf2e85
+ loop 02e85h ; e2 fc ; 0xf2e87
+ pop eax ; 66 58 ; 0xf2e89
+ mov dx, bx ; 89 da ; 0xf2e8b ata.c:1118
+ mov cx, word [bp-00ch] ; 8b 4e f4 ; 0xf2e8d
+ les di, [bp+00ch] ; c4 7e 0c ; 0xf2e90
+ db 0f3h, 066h, 06dh
+ ; rep insd ; f3 66 6d ; 0xf2e93
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf2e96 ata.c:1119
+ test ax, ax ; 85 c0 ; 0xf2e99
+ je short 02ec8h ; 74 2b ; 0xf2e9b
+ mov cx, ax ; 89 c1 ; 0xf2e9d ata.c:1120
+ push eax ; 66 50 ; 0xf2e9f
+ in eax, DX ; 66 ed ; 0xf2ea1
+ loop 02ea1h ; e2 fc ; 0xf2ea3
+ pop eax ; 66 58 ; 0xf2ea5
+ jmp short 02ec8h ; eb 1f ; 0xf2ea7 ata.c:1121
+ test cx, cx ; 85 c9 ; 0xf2ea9 ata.c:1124
+ je short 02eb2h ; 74 05 ; 0xf2eab
+ mov dx, bx ; 89 da ; 0xf2ead ata.c:1125
+ in ax, DX ; ed ; 0xf2eaf
+ loop 02eafh ; e2 fd ; 0xf2eb0
+ mov dx, bx ; 89 da ; 0xf2eb2 ata.c:1126
+ mov cx, word [bp-00ch] ; 8b 4e f4 ; 0xf2eb4
+ les di, [bp+00ch] ; c4 7e 0c ; 0xf2eb7
+ rep insw ; f3 6d ; 0xf2eba
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf2ebc ata.c:1127
+ test ax, ax ; 85 c0 ; 0xf2ebf
+ je short 02ec8h ; 74 05 ; 0xf2ec1
+ mov cx, ax ; 89 c1 ; 0xf2ec3 ata.c:1128
+ in ax, DX ; ed ; 0xf2ec5
+ loop 02ec5h ; e2 fd ; 0xf2ec6
+ add word [bp+00ch], si ; 01 76 0c ; 0xf2ec8 ata.c:1133
+ xor ax, ax ; 31 c0 ; 0xf2ecb ata.c:1136
+ add word [bp-016h], si ; 01 76 ea ; 0xf2ecd
+ adc word [bp-014h], ax ; 11 46 ec ; 0xf2ed0
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf2ed3 ata.c:1137
+ les si, [bp-012h] ; c4 76 ee ; 0xf2ed6
+ mov word [es:si+01ah], ax ; 26 89 44 1a ; 0xf2ed9
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf2edd
+ mov word [es:si+01ch], ax ; 26 89 44 1c ; 0xf2ee0
+ jmp near 02d78h ; e9 91 fe ; 0xf2ee4 ata.c:1138
+ mov al, dl ; 88 d0 ; 0xf2ee7 ata.c:1142
+ and AL, strict byte 0e9h ; 24 e9 ; 0xf2ee9
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf2eeb
+ je short 02efbh ; 74 0c ; 0xf2eed
+ mov dx, word [bp-018h] ; 8b 56 e8 ; 0xf2eef ata.c:1146
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2ef2
+ mov AL, strict byte 008h ; b0 08 ; 0xf2ef5
+ out DX, AL ; ee ; 0xf2ef7
+ jmp near 02d49h ; e9 4e fe ; 0xf2ef8
+ mov dx, word [bp-018h] ; 8b 56 e8 ; 0xf2efb ata.c:1151
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2efe
+ mov AL, strict byte 008h ; b0 08 ; 0xf2f01
+ out DX, AL ; ee ; 0xf2f03
+ xor dx, dx ; 31 d2 ; 0xf2f04 ata.c:1152
+ mov ax, dx ; 89 d0 ; 0xf2f06 ata.c:1153
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf2f08
+ pop di ; 5f ; 0xf2f0b
+ pop si ; 5e ; 0xf2f0c
+ pop bp ; 5d ; 0xf2f0d
+ retn 0000ch ; c2 0c 00 ; 0xf2f0e
+ ; disGetNextSymbol 0xf2f11 LB 0x7134 -> off=0x0 cb=000000000000007b uValue=00000000000f1911 'ata_soft_reset'
+ata_soft_reset: ; 0xf2f11 LB 0x7b
+ push bp ; 55 ; 0xf2f11 ata.c:1161
+ mov bp, sp ; 89 e5 ; 0xf2f12
+ push bx ; 53 ; 0xf2f14
+ push cx ; 51 ; 0xf2f15
+ push dx ; 52 ; 0xf2f16
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf2f17 ata.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf2f1a
+ mov es, dx ; 8e c2 ; 0xf2f1d
+ mov es, [es:bx] ; 26 8e 07 ; 0xf2f1f
+ mov dx, ax ; 89 c2 ; 0xf2f22 ata.c:1170
+ shr dx, 1 ; d1 ea ; 0xf2f24
+ mov ah, al ; 88 c4 ; 0xf2f26 ata.c:1171
+ and ah, 001h ; 80 e4 01 ; 0xf2f28
+ movzx bx, dl ; 0f b6 da ; 0xf2f2b ata.c:1173
+ imul bx, bx, strict byte 00006h ; 6b db 06 ; 0xf2f2e
+ add bx, 00122h ; 81 c3 22 01 ; 0xf2f31
+ mov cx, word [es:bx+00206h] ; 26 8b 8f 06 02 ; 0xf2f35
+ mov bx, word [es:bx+00208h] ; 26 8b 9f 08 02 ; 0xf2f3a ata.c:1174
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf2f3f ata.c:1177
+ mov AL, strict byte 00ah ; b0 0a ; 0xf2f42
+ out DX, AL ; ee ; 0xf2f44
+ test ah, ah ; 84 e4 ; 0xf2f45 ata.c:1178
+ je short 02f4eh ; 74 05 ; 0xf2f47
+ mov ax, 000b0h ; b8 b0 00 ; 0xf2f49
+ jmp short 02f51h ; eb 03 ; 0xf2f4c
+ mov ax, 000a0h ; b8 a0 00 ; 0xf2f4e
+ mov dx, cx ; 89 ca ; 0xf2f51
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2f53
+ out DX, AL ; ee ; 0xf2f56
+ mov dx, cx ; 89 ca ; 0xf2f57 ata.c:1179
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2f59
+ mov AL, strict byte 008h ; b0 08 ; 0xf2f5c
+ out DX, AL ; ee ; 0xf2f5e
+ mov dx, cx ; 89 ca ; 0xf2f5f ata.c:1183
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2f61
+ in AL, DX ; ec ; 0xf2f64
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2f65
+ test AL, strict byte 080h ; a8 80 ; 0xf2f67 ata.c:1184
+ jne short 02f5fh ; 75 f4 ; 0xf2f69
+ and AL, strict byte 0e9h ; 24 e9 ; 0xf2f6b ata.c:1188
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf2f6d
+ je short 02f7ch ; 74 0b ; 0xf2f6f
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf2f71 ata.c:1192
+ mov AL, strict byte 008h ; b0 08 ; 0xf2f74
+ out DX, AL ; ee ; 0xf2f76
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf2f77 ata.c:1193
+ jmp short 02f84h ; eb 08 ; 0xf2f7a
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf2f7c ata.c:1197
+ mov AL, strict byte 008h ; b0 08 ; 0xf2f7f
+ out DX, AL ; ee ; 0xf2f81
+ xor ax, ax ; 31 c0 ; 0xf2f82 ata.c:1198
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf2f84 ata.c:1199
+ pop dx ; 5a ; 0xf2f87
+ pop cx ; 59 ; 0xf2f88
+ pop bx ; 5b ; 0xf2f89
+ pop bp ; 5d ; 0xf2f8a
+ retn ; c3 ; 0xf2f8b
+ ; disGetNextSymbol 0xf2f8c LB 0x70b9 -> off=0x0 cb=000000000000002a uValue=00000000000f198c 'set_diskette_current_cyl'
+set_diskette_current_cyl: ; 0xf2f8c LB 0x2a
+ push bp ; 55 ; 0xf2f8c floppy.c:71
+ mov bp, sp ; 89 e5 ; 0xf2f8d
+ push bx ; 53 ; 0xf2f8f
+ mov dh, al ; 88 c6 ; 0xf2f90
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf2f92 floppy.c:73
+ jbe short 02fa1h ; 76 0b ; 0xf2f94
+ push 00262h ; 68 62 02 ; 0xf2f96 floppy.c:74
+ push strict byte 00007h ; 6a 07 ; 0xf2f99
+ call 01a14h ; e8 76 ea ; 0xf2f9b
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf2f9e
+ movzx bx, dh ; 0f b6 de ; 0xf2fa1 floppy.c:75
+ add bx, 00094h ; 81 c3 94 00 ; 0xf2fa4
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2fa8 floppy.c:43
+ mov es, ax ; 8e c0 ; 0xf2fab
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf2fad
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf2fb0 floppy.c:76
+ pop bx ; 5b ; 0xf2fb3
+ pop bp ; 5d ; 0xf2fb4
+ retn ; c3 ; 0xf2fb5
+ ; disGetNextSymbol 0xf2fb6 LB 0x708f -> off=0x0 cb=0000000000000023 uValue=00000000000f19b6 'floppy_wait_for_interrupt'
+floppy_wait_for_interrupt: ; 0xf2fb6 LB 0x23
+ push bp ; 55 ; 0xf2fb6 floppy.c:96
+ mov bp, sp ; 89 e5 ; 0xf2fb7
+ push bx ; 53 ; 0xf2fb9
+ cli ; fa ; 0xf2fba floppy.c:98
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf2fbb floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2fbe
+ mov es, ax ; 8e c0 ; 0xf2fc1
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2fc3
+ test AL, strict byte 080h ; a8 80 ; 0xf2fc6 floppy.c:102
+ je short 02fceh ; 74 04 ; 0xf2fc8
+ and AL, strict byte 080h ; 24 80 ; 0xf2fca floppy.c:103
+ jmp short 02fd3h ; eb 05 ; 0xf2fcc
+ sti ; fb ; 0xf2fce floppy.c:104
+ hlt ; f4 ; 0xf2fcf
+ cli ; fa ; 0xf2fd0
+ jmp short 02fbbh ; eb e8 ; 0xf2fd1 floppy.c:105
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf2fd3 floppy.c:106
+ pop bx ; 5b ; 0xf2fd6
+ pop bp ; 5d ; 0xf2fd7
+ retn ; c3 ; 0xf2fd8
+ ; disGetNextSymbol 0xf2fd9 LB 0x706c -> off=0x0 cb=0000000000000038 uValue=00000000000f19d9 'floppy_wait_for_interrupt_or_timeout'
+floppy_wait_for_interrupt_or_timeout: ; 0xf2fd9 LB 0x38
+ push bp ; 55 ; 0xf2fd9 floppy.c:116
+ mov bp, sp ; 89 e5 ; 0xf2fda
+ push bx ; 53 ; 0xf2fdc
+ cli ; fa ; 0xf2fdd floppy.c:118
+ mov bx, strict word 00040h ; bb 40 00 ; 0xf2fde floppy.c:38
+ mov es, bx ; 8e c3 ; 0xf2fe1
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2fe3
+ test al, al ; 84 c0 ; 0xf2fe6 floppy.c:122
+ jne short 02fedh ; 75 03 ; 0xf2fe8
+ sti ; fb ; 0xf2fea floppy.c:123
+ jmp short 0300bh ; eb 1e ; 0xf2feb floppy.c:124
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf2fed floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2ff0
+ mov es, ax ; 8e c0 ; 0xf2ff3
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2ff5
+ test AL, strict byte 080h ; a8 80 ; 0xf2ff8 floppy.c:128
+ je short 03006h ; 74 0a ; 0xf2ffa
+ mov ah, al ; 88 c4 ; 0xf2ffc floppy.c:129
+ and ah, 07fh ; 80 e4 7f ; 0xf2ffe
+ mov byte [es:bx], ah ; 26 88 27 ; 0xf3001 floppy.c:43
+ jmp short 0300bh ; eb 05 ; 0xf3004 floppy.c:130
+ sti ; fb ; 0xf3006 floppy.c:132
+ hlt ; f4 ; 0xf3007
+ cli ; fa ; 0xf3008
+ jmp short 02fdeh ; eb d3 ; 0xf3009 floppy.c:133
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf300b floppy.c:134
+ pop bx ; 5b ; 0xf300e
+ pop bp ; 5d ; 0xf300f
+ retn ; c3 ; 0xf3010
+ ; disGetNextSymbol 0xf3011 LB 0x7034 -> off=0x0 cb=0000000000000042 uValue=00000000000f1a11 'floppy_reset_controller'
+floppy_reset_controller: ; 0xf3011 LB 0x42
+ push bp ; 55 ; 0xf3011 floppy.c:138
+ mov bp, sp ; 89 e5 ; 0xf3012
+ push bx ; 53 ; 0xf3014
+ push cx ; 51 ; 0xf3015
+ push dx ; 52 ; 0xf3016
+ mov cx, ax ; 89 c1 ; 0xf3017
+ mov dx, 003f2h ; ba f2 03 ; 0xf3019 floppy.c:143
+ in AL, DX ; ec ; 0xf301c
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf301d
+ mov bx, ax ; 89 c3 ; 0xf301f
+ movzx ax, bl ; 0f b6 c3 ; 0xf3021 floppy.c:144
+ and AL, strict byte 0fbh ; 24 fb ; 0xf3024
+ out DX, AL ; ee ; 0xf3026
+ mov al, bl ; 88 d8 ; 0xf3027 floppy.c:145
+ or AL, strict byte 004h ; 0c 04 ; 0xf3029
+ out DX, AL ; ee ; 0xf302b
+ mov dx, 003f4h ; ba f4 03 ; 0xf302c floppy.c:149
+ in AL, DX ; ec ; 0xf302f
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf3030
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf3032 floppy.c:150
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf3034
+ jne short 0302ch ; 75 f4 ; 0xf3036
+ mov bx, cx ; 89 cb ; 0xf3038 floppy.c:153
+ add bx, 00090h ; 81 c3 90 00 ; 0xf303a
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf303e floppy.c:38
+ mov es, ax ; 8e c0 ; 0xf3041
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf3043
+ and AL, strict byte 0efh ; 24 ef ; 0xf3046 floppy.c:154
+ mov byte [es:bx], al ; 26 88 07 ; 0xf3048 floppy.c:43
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf304b floppy.c:157
+ pop dx ; 5a ; 0xf304e
+ pop cx ; 59 ; 0xf304f
+ pop bx ; 5b ; 0xf3050
+ pop bp ; 5d ; 0xf3051
+ retn ; c3 ; 0xf3052
+ ; disGetNextSymbol 0xf3053 LB 0x6ff2 -> off=0x0 cb=0000000000000074 uValue=00000000000f1a53 'floppy_prepare_controller'
+floppy_prepare_controller: ; 0xf3053 LB 0x74
+ push bp ; 55 ; 0xf3053 floppy.c:159
+ mov bp, sp ; 89 e5 ; 0xf3054
+ push bx ; 53 ; 0xf3056
+ push cx ; 51 ; 0xf3057
+ push dx ; 52 ; 0xf3058
+ push ax ; 50 ; 0xf3059
+ mov cx, ax ; 89 c1 ; 0xf305a
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf305c floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf305f
+ mov es, ax ; 8e c0 ; 0xf3062
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf3064
+ and AL, strict byte 07fh ; 24 7f ; 0xf3067 floppy.c:165
+ mov byte [es:bx], al ; 26 88 07 ; 0xf3069 floppy.c:43
+ mov dx, 003f2h ; ba f2 03 ; 0xf306c floppy.c:169
+ in AL, DX ; ec ; 0xf306f
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf3070
+ and AL, strict byte 004h ; 24 04 ; 0xf3072
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf3074
+ test cx, cx ; 85 c9 ; 0xf3077 floppy.c:170
+ je short 0307fh ; 74 04 ; 0xf3079
+ mov AL, strict byte 020h ; b0 20 ; 0xf307b floppy.c:171
+ jmp short 03081h ; eb 02 ; 0xf307d floppy.c:172
+ mov AL, strict byte 010h ; b0 10 ; 0xf307f floppy.c:173
+ or AL, strict byte 00ch ; 0c 0c ; 0xf3081 floppy.c:174
+ or al, cl ; 08 c8 ; 0xf3083 floppy.c:175
+ mov dx, 003f2h ; ba f2 03 ; 0xf3085 floppy.c:176
+ out DX, AL ; ee ; 0xf3088
+ mov bx, strict word 00040h ; bb 40 00 ; 0xf3089 floppy.c:43
+ mov es, bx ; 8e c3 ; 0xf308c
+ mov byte [es:bx], 025h ; 26 c6 07 25 ; 0xf308e
+ mov bx, 0008bh ; bb 8b 00 ; 0xf3092 floppy.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf3095
+ shr al, 006h ; c0 e8 06 ; 0xf3098 floppy.c:183
+ mov dx, 003f7h ; ba f7 03 ; 0xf309b floppy.c:184
+ out DX, AL ; ee ; 0xf309e
+ mov dx, 003f4h ; ba f4 03 ; 0xf309f floppy.c:188
+ in AL, DX ; ec ; 0xf30a2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf30a3
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf30a5 floppy.c:189
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf30a7
+ jne short 0309fh ; 75 f4 ; 0xf30a9
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf30ab floppy.c:191
+ jne short 030bfh ; 75 0e ; 0xf30af
+ call 02fb6h ; e8 02 ff ; 0xf30b1 floppy.c:202
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf30b4 floppy.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf30b7
+ mov es, dx ; 8e c2 ; 0xf30ba
+ mov byte [es:bx], al ; 26 88 07 ; 0xf30bc
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf30bf floppy.c:206
+ pop dx ; 5a ; 0xf30c2
+ pop cx ; 59 ; 0xf30c3
+ pop bx ; 5b ; 0xf30c4
+ pop bp ; 5d ; 0xf30c5
+ retn ; c3 ; 0xf30c6
+ ; disGetNextSymbol 0xf30c7 LB 0x6f7e -> off=0x0 cb=0000000000000049 uValue=00000000000f1ac7 'floppy_media_known'
+floppy_media_known: ; 0xf30c7 LB 0x49
+ push bx ; 53 ; 0xf30c7 floppy.c:208
+ push dx ; 52 ; 0xf30c8
+ push bp ; 55 ; 0xf30c9
+ mov bp, sp ; 89 e5 ; 0xf30ca
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf30cc floppy.c:38
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf30cf
+ mov es, dx ; 8e c2 ; 0xf30d2
+ mov bh, byte [es:bx] ; 26 8a 3f ; 0xf30d4
+ mov bl, bh ; 88 fb ; 0xf30d7 floppy.c:39
+ test ax, ax ; 85 c0 ; 0xf30d9 floppy.c:214
+ je short 030dfh ; 74 02 ; 0xf30db
+ shr bl, 1 ; d0 eb ; 0xf30dd floppy.c:215
+ and bl, 001h ; 80 e3 01 ; 0xf30df floppy.c:216
+ jne short 030e8h ; 75 04 ; 0xf30e2 floppy.c:217
+ xor bh, bh ; 30 ff ; 0xf30e4 floppy.c:218
+ jmp short 0310ah ; eb 22 ; 0xf30e6
+ mov bx, 00090h ; bb 90 00 ; 0xf30e8 floppy.c:220
+ test ax, ax ; 85 c0 ; 0xf30eb floppy.c:221
+ je short 030f2h ; 74 03 ; 0xf30ed
+ mov bx, 00091h ; bb 91 00 ; 0xf30ef floppy.c:222
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf30f2 floppy.c:38
+ mov es, ax ; 8e c0 ; 0xf30f5
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf30f7
+ xor ah, ah ; 30 e4 ; 0xf30fa floppy.c:225
+ sar ax, 004h ; c1 f8 04 ; 0xf30fc
+ and AL, strict byte 001h ; 24 01 ; 0xf30ff
+ jne short 03107h ; 75 04 ; 0xf3101 floppy.c:226
+ xor bx, bx ; 31 db ; 0xf3103 floppy.c:227
+ jmp short 0310ah ; eb 03 ; 0xf3105
+ mov bx, strict word 00001h ; bb 01 00 ; 0xf3107 floppy.c:230
+ mov ax, bx ; 89 d8 ; 0xf310a floppy.c:231
+ pop bp ; 5d ; 0xf310c
+ pop dx ; 5a ; 0xf310d
+ pop bx ; 5b ; 0xf310e
+ retn ; c3 ; 0xf310f
+ ; disGetNextSymbol 0xf3110 LB 0x6f35 -> off=0x0 cb=000000000000004e uValue=00000000000f1b10 'floppy_read_id'
+floppy_read_id: ; 0xf3110 LB 0x4e
+ push bp ; 55 ; 0xf3110 floppy.c:233
+ mov bp, sp ; 89 e5 ; 0xf3111
+ push bx ; 53 ; 0xf3113
+ push dx ; 52 ; 0xf3114
+ push si ; 56 ; 0xf3115
+ mov bx, ax ; 89 c3 ; 0xf3116
+ call 03053h ; e8 38 ff ; 0xf3118 floppy.c:240
+ mov AL, strict byte 04ah ; b0 4a ; 0xf311b floppy.c:243
+ mov dx, 003f5h ; ba f5 03 ; 0xf311d
+ out DX, AL ; ee ; 0xf3120
+ mov al, bl ; 88 d8 ; 0xf3121 floppy.c:244
+ out DX, AL ; ee ; 0xf3123
+ call 02fb6h ; e8 8f fe ; 0xf3124 floppy.c:259
+ xor bx, bx ; 31 db ; 0xf3127 floppy.c:263
+ jmp short 03130h ; eb 05 ; 0xf3129
+ cmp bx, strict byte 00007h ; 83 fb 07 ; 0xf312b
+ jnl short 03144h ; 7d 14 ; 0xf312e
+ mov dx, 003f5h ; ba f5 03 ; 0xf3130 floppy.c:264
+ in AL, DX ; ec ; 0xf3133
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf3134
+ lea si, [bx+042h] ; 8d 77 42 ; 0xf3136
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3139 floppy.c:43
+ mov es, dx ; 8e c2 ; 0xf313c
+ mov byte [es:si], al ; 26 88 04 ; 0xf313e
+ inc bx ; 43 ; 0xf3141 floppy.c:264
+ jmp short 0312bh ; eb e7 ; 0xf3142
+ mov bx, strict word 00042h ; bb 42 00 ; 0xf3144 floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3147
+ mov es, ax ; 8e c0 ; 0xf314a
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf314c
+ test AL, strict byte 0c0h ; a8 c0 ; 0xf314f floppy.c:39
+ db 00fh, 094h, 0c0h
+ ; sete al ; 0f 94 c0 ; 0xf3151
+ xor ah, ah ; 30 e4 ; 0xf3154
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf3156 floppy.c:270
+ pop si ; 5e ; 0xf3159
+ pop dx ; 5a ; 0xf315a
+ pop bx ; 5b ; 0xf315b
+ pop bp ; 5d ; 0xf315c
+ retn ; c3 ; 0xf315d
+ ; disGetNextSymbol 0xf315e LB 0x6ee7 -> off=0x0 cb=0000000000000041 uValue=00000000000f1b5e 'floppy_drive_recal'
+floppy_drive_recal: ; 0xf315e LB 0x41
+ push bp ; 55 ; 0xf315e floppy.c:272
+ mov bp, sp ; 89 e5 ; 0xf315f
+ push bx ; 53 ; 0xf3161
+ push dx ; 52 ; 0xf3162
+ push si ; 56 ; 0xf3163
+ mov bx, ax ; 89 c3 ; 0xf3164
+ call 03053h ; e8 ea fe ; 0xf3166 floppy.c:277
+ mov AL, strict byte 007h ; b0 07 ; 0xf3169 floppy.c:280
+ mov dx, 003f5h ; ba f5 03 ; 0xf316b
+ out DX, AL ; ee ; 0xf316e
+ mov al, bl ; 88 d8 ; 0xf316f floppy.c:281
+ out DX, AL ; ee ; 0xf3171
+ call 02fb6h ; e8 41 fe ; 0xf3172 floppy.c:300
+ test bx, bx ; 85 db ; 0xf3175 floppy.c:304
+ je short 03180h ; 74 07 ; 0xf3177
+ or AL, strict byte 002h ; 0c 02 ; 0xf3179 floppy.c:305
+ mov bx, 00095h ; bb 95 00 ; 0xf317b floppy.c:306
+ jmp short 03185h ; eb 05 ; 0xf317e floppy.c:307
+ or AL, strict byte 001h ; 0c 01 ; 0xf3180 floppy.c:308
+ mov bx, 00094h ; bb 94 00 ; 0xf3182 floppy.c:309
+ mov si, strict word 0003eh ; be 3e 00 ; 0xf3185 floppy.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3188
+ mov es, dx ; 8e c2 ; 0xf318b
+ mov byte [es:si], al ; 26 88 04 ; 0xf318d
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3190 floppy.c:43
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf3194 floppy.c:315
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf3197
+ pop si ; 5e ; 0xf319a
+ pop dx ; 5a ; 0xf319b
+ pop bx ; 5b ; 0xf319c
+ pop bp ; 5d ; 0xf319d
+ retn ; c3 ; 0xf319e
+ ; disGetNextSymbol 0xf319f LB 0x6ea6 -> off=0x0 cb=00000000000000e4 uValue=00000000000f1b9f 'floppy_media_sense'
+floppy_media_sense: ; 0xf319f LB 0xe4
+ push bp ; 55 ; 0xf319f floppy.c:318
+ mov bp, sp ; 89 e5 ; 0xf31a0
+ push bx ; 53 ; 0xf31a2
+ push cx ; 51 ; 0xf31a3
+ push dx ; 52 ; 0xf31a4
+ push si ; 56 ; 0xf31a5
+ mov bx, ax ; 89 c3 ; 0xf31a6
+ call 0315eh ; e8 b3 ff ; 0xf31a8 floppy.c:324
+ test ax, ax ; 85 c0 ; 0xf31ab
+ jne short 031b4h ; 75 05 ; 0xf31ad
+ xor dx, dx ; 31 d2 ; 0xf31af floppy.c:325
+ jmp near 03278h ; e9 c4 00 ; 0xf31b1
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf31b4 floppy.c:360
+ call 01756h ; e8 9c e5 ; 0xf31b7
+ test bx, bx ; 85 db ; 0xf31ba floppy.c:361
+ jne short 031c5h ; 75 07 ; 0xf31bc
+ mov dl, al ; 88 c2 ; 0xf31be floppy.c:362
+ shr dl, 004h ; c0 ea 04 ; 0xf31c0
+ jmp short 031cah ; eb 05 ; 0xf31c3 floppy.c:363
+ mov dl, al ; 88 c2 ; 0xf31c5 floppy.c:364
+ and dl, 00fh ; 80 e2 0f ; 0xf31c7
+ cmp dl, 001h ; 80 fa 01 ; 0xf31ca floppy.c:365
+ jne short 031d8h ; 75 09 ; 0xf31cd
+ xor dl, dl ; 30 d2 ; 0xf31cf floppy.c:367
+ mov DH, strict byte 015h ; b6 15 ; 0xf31d1 floppy.c:368
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf31d3 floppy.c:369
+ jmp short 03216h ; eb 3e ; 0xf31d6 floppy.c:371
+ cmp dl, 002h ; 80 fa 02 ; 0xf31d8
+ jne short 031e3h ; 75 06 ; 0xf31db
+ xor dl, dl ; 30 d2 ; 0xf31dd floppy.c:373
+ mov DH, strict byte 035h ; b6 35 ; 0xf31df floppy.c:374
+ jmp short 031d3h ; eb f0 ; 0xf31e1
+ cmp dl, 003h ; 80 fa 03 ; 0xf31e3 floppy.c:377
+ jne short 031eeh ; 75 06 ; 0xf31e6
+ xor dl, dl ; 30 d2 ; 0xf31e8 floppy.c:379
+ mov DH, strict byte 017h ; b6 17 ; 0xf31ea floppy.c:380
+ jmp short 031d3h ; eb e5 ; 0xf31ec
+ cmp dl, 004h ; 80 fa 04 ; 0xf31ee floppy.c:383
+ jne short 031f9h ; 75 06 ; 0xf31f1
+ xor dl, dl ; 30 d2 ; 0xf31f3 floppy.c:385
+ mov DH, strict byte 017h ; b6 17 ; 0xf31f5 floppy.c:386
+ jmp short 031d3h ; eb da ; 0xf31f7
+ cmp dl, 005h ; 80 fa 05 ; 0xf31f9 floppy.c:389
+ jne short 03204h ; 75 06 ; 0xf31fc
+ mov DL, strict byte 0cch ; b2 cc ; 0xf31fe floppy.c:391
+ mov DH, strict byte 0d7h ; b6 d7 ; 0xf3200 floppy.c:392
+ jmp short 031d3h ; eb cf ; 0xf3202
+ cmp dl, 00eh ; 80 fa 0e ; 0xf3204 floppy.c:396
+ je short 0320eh ; 74 05 ; 0xf3207
+ cmp dl, 00fh ; 80 fa 0f ; 0xf3209
+ jne short 03210h ; 75 02 ; 0xf320c
+ jmp short 031feh ; eb ee ; 0xf320e
+ xor dl, dl ; 30 d2 ; 0xf3210 floppy.c:404
+ xor dh, dh ; 30 f6 ; 0xf3212 floppy.c:405
+ xor cx, cx ; 31 c9 ; 0xf3214 floppy.c:406
+ mov si, 0008bh ; be 8b 00 ; 0xf3216 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3219
+ mov es, ax ; 8e c0 ; 0xf321c
+ mov byte [es:si], dl ; 26 88 14 ; 0xf321e
+ mov ax, bx ; 89 d8 ; 0xf3221 floppy.c:410
+ call 03110h ; e8 ea fe ; 0xf3223
+ test ax, ax ; 85 c0 ; 0xf3226
+ jne short 0325ch ; 75 32 ; 0xf3228
+ mov al, dl ; 88 d0 ; 0xf322a floppy.c:411
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf322c
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf322e
+ je short 0325ch ; 74 2a ; 0xf3230
+ mov al, dl ; 88 d0 ; 0xf3232 floppy.c:415
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf3234
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xf3236
+ je short 03249h ; 74 0f ; 0xf3238
+ mov ah, dl ; 88 d4 ; 0xf323a
+ and ah, 03fh ; 80 e4 3f ; 0xf323c
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf323f
+ je short 03255h ; 74 12 ; 0xf3241
+ test al, al ; 84 c0 ; 0xf3243
+ je short 0324eh ; 74 07 ; 0xf3245
+ jmp short 03216h ; eb cd ; 0xf3247
+ and dl, 03fh ; 80 e2 3f ; 0xf3249 floppy.c:417
+ jmp short 03216h ; eb c8 ; 0xf324c floppy.c:418
+ mov dl, ah ; 88 e2 ; 0xf324e floppy.c:420
+ or dl, 040h ; 80 ca 40 ; 0xf3250
+ jmp short 03216h ; eb c1 ; 0xf3253 floppy.c:421
+ mov dl, ah ; 88 e2 ; 0xf3255 floppy.c:423
+ or dl, 080h ; 80 ca 80 ; 0xf3257
+ jmp short 03216h ; eb ba ; 0xf325a floppy.c:427
+ test bx, bx ; 85 db ; 0xf325c floppy.c:429
+ db 00fh, 095h, 0c0h
+ ; setne al ; 0f 95 c0 ; 0xf325e
+ movzx bx, al ; 0f b6 d8 ; 0xf3261
+ add bx, 00090h ; 81 c3 90 00 ; 0xf3264
+ mov si, 0008bh ; be 8b 00 ; 0xf3268 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf326b
+ mov es, ax ; 8e c0 ; 0xf326e
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3270
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf3273 floppy.c:43
+ mov dx, cx ; 89 ca ; 0xf3276 floppy.c:436
+ mov ax, dx ; 89 d0 ; 0xf3278 floppy.c:437
+ lea sp, [bp-008h] ; 8d 66 f8 ; 0xf327a
+ pop si ; 5e ; 0xf327d
+ pop dx ; 5a ; 0xf327e
+ pop cx ; 59 ; 0xf327f
+ pop bx ; 5b ; 0xf3280
+ pop bp ; 5d ; 0xf3281
+ retn ; c3 ; 0xf3282
+ ; disGetNextSymbol 0xf3283 LB 0x6dc2 -> off=0x0 cb=0000000000000024 uValue=00000000000f1c83 'floppy_drive_exists'
+floppy_drive_exists: ; 0xf3283 LB 0x24
+ push bp ; 55 ; 0xf3283 floppy.c:440
+ mov bp, sp ; 89 e5 ; 0xf3284
+ push dx ; 52 ; 0xf3286
+ mov dx, ax ; 89 c2 ; 0xf3287
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf3289 floppy.c:446
+ call 01756h ; e8 c7 e4 ; 0xf328c
+ test dx, dx ; 85 d2 ; 0xf328f floppy.c:447
+ jne short 03298h ; 75 05 ; 0xf3291
+ shr al, 004h ; c0 e8 04 ; 0xf3293 floppy.c:448
+ jmp short 0329ah ; eb 02 ; 0xf3296 floppy.c:449
+ and AL, strict byte 00fh ; 24 0f ; 0xf3298 floppy.c:450
+ test al, al ; 84 c0 ; 0xf329a floppy.c:451
+ db 00fh, 095h, 0c0h
+ ; setne al ; 0f 95 c0 ; 0xf329c
+ xor ah, ah ; 30 e4 ; 0xf329f
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf32a1 floppy.c:452
+ pop dx ; 5a ; 0xf32a4
+ pop bp ; 5d ; 0xf32a5
+ retn ; c3 ; 0xf32a6
+ ; disGetNextSymbol 0xf32a7 LB 0x6d9e -> off=0x23 cb=0000000000000984 uValue=00000000000f1cca 'int13_diskette_function'
+ db 018h, 017h, 016h, 015h, 008h, 005h, 004h, 003h, 002h, 001h, 000h, 02bh, 03ch, 00ah, 033h, 087h
+ db 033h, 0a7h, 033h, 0a7h, 033h, 0a7h, 033h, 022h, 037h, 0e0h, 038h, 0d0h, 039h, 012h, 03ah, 046h
+ db 03ah, 0b8h, 03ah
+int13_diskette_function: ; 0xf32ca LB 0x984
+ push bp ; 55 ; 0xf32ca floppy.c:467
+ mov bp, sp ; 89 e5 ; 0xf32cb
+ sub sp, strict byte 0000ch ; 83 ec 0c ; 0xf32cd
+ or byte [bp+01dh], 002h ; 80 4e 1d 02 ; 0xf32d0 floppy.c:478
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf32d4 floppy.c:480
+ shr ax, 008h ; c1 e8 08 ; 0xf32d7
+ cmp ax, strict word 00018h ; 3d 18 00 ; 0xf32da
+ jnbe near 03c2bh ; 0f 87 4a 09 ; 0xf32dd
+ push CS ; 0e ; 0xf32e1
+ pop ES ; 07 ; 0xf32e2
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf32e3
+ mov di, 032a7h ; bf a7 32 ; 0xf32e6
+ repne scasb ; f2 ae ; 0xf32e9
+ sal cx, 1 ; d1 e1 ; 0xf32eb
+ mov di, cx ; 89 cf ; 0xf32ed
+ mov di, word [cs:di+032b2h] ; 2e 8b bd b2 32 ; 0xf32ef
+ mov dx, word [bp+016h] ; 8b 56 16 ; 0xf32f4
+ xor dh, dh ; 30 f6 ; 0xf32f7
+ mov ah, byte [bp+00eh] ; 8a 66 0e ; 0xf32f9
+ mov cx, word [bp+01ch] ; 8b 4e 1c ; 0xf32fc
+ or cl, 001h ; 80 c9 01 ; 0xf32ff
+ mov si, dx ; 89 d6 ; 0xf3302
+ or si, 00100h ; 81 ce 00 01 ; 0xf3304
+ jmp di ; ff e7 ; 0xf3308
+ mov bl, byte [bp+00eh] ; 8a 5e 0e ; 0xf330a floppy.c:483
+ cmp bl, 001h ; 80 fb 01 ; 0xf330d floppy.c:484
+ jbe short 0332ch ; 76 1a ; 0xf3310
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3312 floppy.c:485
+ xor ah, ah ; 30 e4 ; 0xf3315
+ or ah, 001h ; 80 cc 01 ; 0xf3317
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf331a
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf331d floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3320
+ mov es, ax ; 8e c0 ; 0xf3323
+ mov byte [es:bx], 001h ; 26 c6 07 01 ; 0xf3325
+ jmp near 03b18h ; e9 ec 07 ; 0xf3329
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf332c floppy.c:491
+ call 01756h ; e8 24 e4 ; 0xf332f
+ test bl, bl ; 84 db ; 0xf3332 floppy.c:492
+ jne short 0333dh ; 75 07 ; 0xf3334
+ mov dl, al ; 88 c2 ; 0xf3336 floppy.c:493
+ shr dl, 004h ; c0 ea 04 ; 0xf3338
+ jmp short 03342h ; eb 05 ; 0xf333b floppy.c:494
+ mov dl, al ; 88 c2 ; 0xf333d floppy.c:495
+ and dl, 00fh ; 80 e2 0f ; 0xf333f
+ test dl, dl ; 84 d2 ; 0xf3342 floppy.c:496
+ jne short 03360h ; 75 1a ; 0xf3344
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3346 floppy.c:497
+ xor ah, ah ; 30 e4 ; 0xf3349
+ or ah, 080h ; 80 cc 80 ; 0xf334b
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf334e
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3351 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3354
+ mov es, ax ; 8e c0 ; 0xf3357
+ mov byte [es:bx], 080h ; 26 c6 07 80 ; 0xf3359
+ jmp near 03b18h ; e9 b8 07 ; 0xf335d
+ mov si, strict word 0003eh ; be 3e 00 ; 0xf3360 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3363
+ mov es, ax ; 8e c0 ; 0xf3366
+ mov byte [es:si], 000h ; 26 c6 04 00 ; 0xf3368
+ xor al, al ; 30 c0 ; 0xf336c floppy.c:506
+ mov byte [bp+017h], al ; 88 46 17 ; 0xf336e
+ mov si, strict word 00041h ; be 41 00 ; 0xf3371 floppy.c:43
+ mov byte [es:si], al ; 26 88 04 ; 0xf3374
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf3377 floppy.c:508
+ movzx ax, bl ; 0f b6 c3 ; 0xf337b floppy.c:509
+ xor dx, dx ; 31 d2 ; 0xf337e
+ call 02f8ch ; e8 09 fc ; 0xf3380
+ mov sp, bp ; 89 ec ; 0xf3383 floppy.c:510
+ pop bp ; 5d ; 0xf3385
+ retn ; c3 ; 0xf3386
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf3387 floppy.c:513
+ mov bx, 00441h ; bb 41 04 ; 0xf338b floppy.c:38
+ xor ax, ax ; 31 c0 ; 0xf338e
+ mov es, ax ; 8e c0 ; 0xf3390
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf3392
+ movzx bx, al ; 0f b6 d8 ; 0xf3395 floppy.c:515
+ sal bx, 008h ; c1 e3 08 ; 0xf3398
+ or dx, bx ; 09 da ; 0xf339b
+ mov word [bp+016h], dx ; 89 56 16 ; 0xf339d
+ test al, al ; 84 c0 ; 0xf33a0 floppy.c:516
+ je short 03383h ; 74 df ; 0xf33a2
+ jmp near 03b18h ; e9 71 07 ; 0xf33a4
+ mov bh, byte [bp+016h] ; 8a 7e 16 ; 0xf33a7 floppy.c:524
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf33aa floppy.c:525
+ shr ax, 008h ; c1 e8 08 ; 0xf33ad
+ mov byte [bp-002h], al ; 88 46 fe ; 0xf33b0
+ mov al, byte [bp+014h] ; 8a 46 14 ; 0xf33b3 floppy.c:526
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf33b6
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf33b9 floppy.c:527
+ shr ax, 008h ; c1 e8 08 ; 0xf33bc
+ mov byte [bp-004h], al ; 88 46 fc ; 0xf33bf
+ mov bl, byte [bp+00eh] ; 8a 5e 0e ; 0xf33c2 floppy.c:528
+ cmp bl, 001h ; 80 fb 01 ; 0xf33c5 floppy.c:530
+ jnbe short 033d7h ; 77 0d ; 0xf33c8
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf33ca
+ jnbe short 033d7h ; 77 09 ; 0xf33cc
+ test bh, bh ; 84 ff ; 0xf33ce
+ je short 033d7h ; 74 05 ; 0xf33d0
+ cmp bh, 048h ; 80 ff 48 ; 0xf33d2
+ jbe short 0340ah ; 76 33 ; 0xf33d5
+ mov bx, 00db2h ; bb b2 0d ; 0xf33d7 floppy.c:532
+ mov cx, ds ; 8c d9 ; 0xf33da
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf33dc
+ call 019d3h ; e8 f1 e5 ; 0xf33df
+ push 00287h ; 68 87 02 ; 0xf33e2
+ push 0029fh ; 68 9f 02 ; 0xf33e5
+ push strict byte 00004h ; 6a 04 ; 0xf33e8
+ call 01a14h ; e8 27 e6 ; 0xf33ea
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf33ed
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf33f0 floppy.c:533
+ xor ah, ah ; 30 e4 ; 0xf33f3
+ or ah, 001h ; 80 cc 01 ; 0xf33f5
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf33f8
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf33fb floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf33fe
+ mov es, ax ; 8e c0 ; 0xf3401
+ mov byte [es:bx], 001h ; 26 c6 07 01 ; 0xf3403
+ jmp near 03495h ; e9 8b 00 ; 0xf3407
+ movzx ax, bl ; 0f b6 c3 ; 0xf340a floppy.c:535
+ call 03283h ; e8 73 fe ; 0xf340d
+ test ax, ax ; 85 c0 ; 0xf3410
+ je near 0352ch ; 0f 84 16 01 ; 0xf3412
+ movzx cx, bl ; 0f b6 cb ; 0xf3416 floppy.c:551
+ mov ax, cx ; 89 c8 ; 0xf3419
+ call 030c7h ; e8 a9 fc ; 0xf341b
+ test ax, ax ; 85 c0 ; 0xf341e
+ jne short 03444h ; 75 22 ; 0xf3420
+ mov ax, cx ; 89 c8 ; 0xf3422 floppy.c:552
+ call 0319fh ; e8 78 fd ; 0xf3424
+ test ax, ax ; 85 c0 ; 0xf3427
+ jne short 03444h ; 75 19 ; 0xf3429
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf342b floppy.c:554
+ xor ah, ah ; 30 e4 ; 0xf342e
+ or ah, 00ch ; 80 cc 0c ; 0xf3430
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3433
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3436 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3439
+ mov es, ax ; 8e c0 ; 0xf343c
+ mov byte [es:bx], 00ch ; 26 c6 07 0c ; 0xf343e
+ jmp short 03495h ; eb 51 ; 0xf3442
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3444 floppy.c:562
+ shr ax, 008h ; c1 e8 08 ; 0xf3447
+ cmp ax, strict word 00002h ; 3d 02 00 ; 0xf344a
+ jne near 035e0h ; 0f 85 8f 01 ; 0xf344d
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf3451 floppy.c:573
+ shr dx, 00ch ; c1 ea 0c ; 0xf3454
+ mov ah, dl ; 88 d4 ; 0xf3457
+ mov cx, word [bp+006h] ; 8b 4e 06 ; 0xf3459 floppy.c:574
+ sal cx, 004h ; c1 e1 04 ; 0xf345c
+ mov si, word [bp+010h] ; 8b 76 10 ; 0xf345f floppy.c:575
+ add si, cx ; 01 ce ; 0xf3462
+ mov word [bp-008h], si ; 89 76 f8 ; 0xf3464
+ cmp cx, si ; 39 f1 ; 0xf3467 floppy.c:577
+ jbe short 0346dh ; 76 02 ; 0xf3469
+ db 0feh, 0c4h
+ ; inc ah ; fe c4 ; 0xf346b floppy.c:579
+ movzx cx, bh ; 0f b6 cf ; 0xf346d floppy.c:581
+ sal cx, 009h ; c1 e1 09 ; 0xf3470
+ dec cx ; 49 ; 0xf3473
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf3474 floppy.c:584
+ add dx, cx ; 01 ca ; 0xf3477
+ cmp dx, word [bp-008h] ; 3b 56 f8 ; 0xf3479 floppy.c:585
+ jnc short 0349ch ; 73 1e ; 0xf347c
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf347e floppy.c:586
+ xor ah, ah ; 30 e4 ; 0xf3481
+ or ah, 009h ; 80 cc 09 ; 0xf3483
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3486
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3489 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf348c
+ mov es, ax ; 8e c0 ; 0xf348f
+ mov byte [es:bx], 009h ; 26 c6 07 09 ; 0xf3491
+ mov byte [bp+016h], 000h ; c6 46 16 00 ; 0xf3495
+ jmp near 03b18h ; e9 7c 06 ; 0xf3499
+ mov AL, strict byte 006h ; b0 06 ; 0xf349c floppy.c:594
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf349e
+ out DX, AL ; ee ; 0xf34a1
+ xor al, al ; 30 c0 ; 0xf34a2 floppy.c:597
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf34a4
+ out DX, AL ; ee ; 0xf34a7
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf34a8 floppy.c:598
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf34ab
+ out DX, AL ; ee ; 0xf34ae
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf34af floppy.c:599
+ shr dx, 008h ; c1 ea 08 ; 0xf34b2
+ mov al, dl ; 88 d0 ; 0xf34b5
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf34b7
+ out DX, AL ; ee ; 0xf34ba
+ xor al, al ; 30 c0 ; 0xf34bb floppy.c:601
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf34bd
+ out DX, AL ; ee ; 0xf34c0
+ mov al, cl ; 88 c8 ; 0xf34c1 floppy.c:602
+ mov dx, strict word 00005h ; ba 05 00 ; 0xf34c3
+ out DX, AL ; ee ; 0xf34c6
+ shr cx, 008h ; c1 e9 08 ; 0xf34c7 floppy.c:603
+ mov al, cl ; 88 c8 ; 0xf34ca
+ out DX, AL ; ee ; 0xf34cc
+ mov AL, strict byte 046h ; b0 46 ; 0xf34cd floppy.c:611
+ mov dx, strict word 0000bh ; ba 0b 00 ; 0xf34cf
+ out DX, AL ; ee ; 0xf34d2
+ mov al, ah ; 88 e0 ; 0xf34d3 floppy.c:615
+ mov dx, 00081h ; ba 81 00 ; 0xf34d5
+ out DX, AL ; ee ; 0xf34d8
+ mov AL, strict byte 002h ; b0 02 ; 0xf34d9 floppy.c:618
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf34db
+ out DX, AL ; ee ; 0xf34de
+ movzx cx, bl ; 0f b6 cb ; 0xf34df floppy.c:623
+ mov ax, cx ; 89 c8 ; 0xf34e2
+ call 03053h ; e8 6c fb ; 0xf34e4
+ mov AL, strict byte 0e6h ; b0 e6 ; 0xf34e7 floppy.c:626
+ mov dx, 003f5h ; ba f5 03 ; 0xf34e9
+ out DX, AL ; ee ; 0xf34ec
+ movzx dx, byte [bp-004h] ; 0f b6 56 fc ; 0xf34ed floppy.c:627
+ sal dx, 002h ; c1 e2 02 ; 0xf34f1
+ movzx ax, bl ; 0f b6 c3 ; 0xf34f4
+ or ax, dx ; 09 d0 ; 0xf34f7
+ mov dx, 003f5h ; ba f5 03 ; 0xf34f9
+ out DX, AL ; ee ; 0xf34fc
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf34fd floppy.c:628
+ out DX, AL ; ee ; 0xf3500
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf3501 floppy.c:629
+ out DX, AL ; ee ; 0xf3504
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf3505 floppy.c:630
+ out DX, AL ; ee ; 0xf3508
+ mov AL, strict byte 002h ; b0 02 ; 0xf3509 floppy.c:631
+ out DX, AL ; ee ; 0xf350b
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf350c floppy.c:632
+ movzx dx, bh ; 0f b6 d7 ; 0xf3510
+ add ax, dx ; 01 d0 ; 0xf3513
+ dec ax ; 48 ; 0xf3515
+ mov dx, 003f5h ; ba f5 03 ; 0xf3516
+ out DX, AL ; ee ; 0xf3519
+ xor al, al ; 30 c0 ; 0xf351a floppy.c:633
+ out DX, AL ; ee ; 0xf351c
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf351d floppy.c:634
+ out DX, AL ; ee ; 0xf351f
+ call 02fd9h ; e8 b6 fa ; 0xf3520 floppy.c:666
+ test al, al ; 84 c0 ; 0xf3523 floppy.c:667
+ jne short 03546h ; 75 1f ; 0xf3525
+ mov ax, cx ; 89 c8 ; 0xf3527 floppy.c:669
+ call 03011h ; e8 e5 fa ; 0xf3529
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf352c floppy.c:68
+ xor ah, ah ; 30 e4 ; 0xf352f
+ or ah, 080h ; 80 cc 80 ; 0xf3531
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3534
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3537
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf353a
+ mov es, ax ; 8e c0 ; 0xf353d
+ mov byte [es:bx], 080h ; 26 c6 07 80 ; 0xf353f
+ jmp near 03495h ; e9 4f ff ; 0xf3543
+ mov dx, 003f4h ; ba f4 03 ; 0xf3546 floppy.c:679
+ in AL, DX ; ec ; 0xf3549
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf354a
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf354c floppy.c:680
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xf354e
+ je short 03560h ; 74 0e ; 0xf3550
+ push 00287h ; 68 87 02 ; 0xf3552 floppy.c:681
+ push 002bah ; 68 ba 02 ; 0xf3555
+ push strict byte 00007h ; 6a 07 ; 0xf3558
+ call 01a14h ; e8 b7 e4 ; 0xf355a
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf355d
+ xor cx, cx ; 31 c9 ; 0xf3560 floppy.c:684
+ jmp short 03569h ; eb 05 ; 0xf3562
+ cmp cx, strict byte 00007h ; 83 f9 07 ; 0xf3564
+ jnl short 0357fh ; 7d 16 ; 0xf3567
+ mov dx, 003f5h ; ba f5 03 ; 0xf3569 floppy.c:685
+ in AL, DX ; ec ; 0xf356c
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf356d
+ mov si, cx ; 89 ce ; 0xf356f
+ add si, strict byte 00042h ; 83 c6 42 ; 0xf3571
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3574 floppy.c:43
+ mov es, dx ; 8e c2 ; 0xf3577
+ mov byte [es:si], al ; 26 88 04 ; 0xf3579
+ inc cx ; 41 ; 0xf357c floppy.c:685
+ jmp short 03564h ; eb e5 ; 0xf357d
+ mov si, strict word 00042h ; be 42 00 ; 0xf357f floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3582
+ mov es, ax ; 8e c0 ; 0xf3585
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf3587
+ test AL, strict byte 0c0h ; a8 c0 ; 0xf358a floppy.c:39
+ je short 035aeh ; 74 20 ; 0xf358c
+ movzx ax, bl ; 0f b6 c3 ; 0xf358e floppy.c:689
+ call 03011h ; e8 7d fa ; 0xf3591
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3594 floppy.c:690
+ xor ah, ah ; 30 e4 ; 0xf3597
+ or ah, 020h ; 80 cc 20 ; 0xf3599
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf359c
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf359f floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf35a2
+ mov es, ax ; 8e c0 ; 0xf35a5
+ mov byte [es:bx], 020h ; 26 c6 07 20 ; 0xf35a7
+ jmp near 03495h ; e9 e7 fe ; 0xf35ab
+ movzx ax, bh ; 0f b6 c7 ; 0xf35ae floppy.c:698
+ sal ax, 009h ; c1 e0 09 ; 0xf35b1
+ cwd ; 99 ; 0xf35b4
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf35b5
+ sar ax, 1 ; d1 f8 ; 0xf35b7
+ mov si, word [bp+010h] ; 8b 76 10 ; 0xf35b9
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf35bc
+ mov di, si ; 89 f7 ; 0xf35bf
+ mov cx, ax ; 89 c1 ; 0xf35c1
+ mov es, dx ; 8e c2 ; 0xf35c3
+ push DS ; 1e ; 0xf35c5
+ mov ds, dx ; 8e da ; 0xf35c6
+ rep movsw ; f3 a5 ; 0xf35c8
+ pop DS ; 1f ; 0xf35ca
+ movzx dx, byte [bp-002h] ; 0f b6 56 fe ; 0xf35cb floppy.c:702
+ movzx ax, bl ; 0f b6 c3 ; 0xf35cf
+ call 02f8ch ; e8 b7 f9 ; 0xf35d2
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf35d5 floppy.c:704
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf35d9 floppy.c:705
+ jmp near 03383h ; e9 a3 fd ; 0xf35dd floppy.c:706
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf35e0 floppy.c:707
+ shr ax, 008h ; c1 e8 08 ; 0xf35e3
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf35e6
+ jne near 0370dh ; 0f 85 20 01 ; 0xf35e9
+ mov cx, word [bp+006h] ; 8b 4e 06 ; 0xf35ed floppy.c:718
+ shr cx, 00ch ; c1 e9 0c ; 0xf35f0
+ mov ah, cl ; 88 cc ; 0xf35f3
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf35f5 floppy.c:719
+ sal dx, 004h ; c1 e2 04 ; 0xf35f8
+ mov si, word [bp+010h] ; 8b 76 10 ; 0xf35fb floppy.c:720
+ add si, dx ; 01 d6 ; 0xf35fe
+ mov word [bp-008h], si ; 89 76 f8 ; 0xf3600
+ cmp dx, si ; 39 f2 ; 0xf3603 floppy.c:722
+ jbe short 03609h ; 76 02 ; 0xf3605
+ db 0feh, 0c4h
+ ; inc ah ; fe c4 ; 0xf3607 floppy.c:724
+ movzx cx, bh ; 0f b6 cf ; 0xf3609 floppy.c:726
+ sal cx, 009h ; c1 e1 09 ; 0xf360c
+ dec cx ; 49 ; 0xf360f
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf3610 floppy.c:729
+ add dx, cx ; 01 ca ; 0xf3613
+ cmp dx, word [bp-008h] ; 3b 56 f8 ; 0xf3615 floppy.c:730
+ jc near 0347eh ; 0f 82 62 fe ; 0xf3618
+ mov AL, strict byte 006h ; b0 06 ; 0xf361c floppy.c:739
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf361e
+ out DX, AL ; ee ; 0xf3621
+ xor al, al ; 30 c0 ; 0xf3622 floppy.c:741
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3624
+ out DX, AL ; ee ; 0xf3627
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf3628 floppy.c:742
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf362b
+ out DX, AL ; ee ; 0xf362e
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf362f floppy.c:743
+ shr dx, 008h ; c1 ea 08 ; 0xf3632
+ mov al, dl ; 88 d0 ; 0xf3635
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf3637
+ out DX, AL ; ee ; 0xf363a
+ xor al, al ; 30 c0 ; 0xf363b floppy.c:744
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf363d
+ out DX, AL ; ee ; 0xf3640
+ mov al, cl ; 88 c8 ; 0xf3641 floppy.c:745
+ mov dx, strict word 00005h ; ba 05 00 ; 0xf3643
+ out DX, AL ; ee ; 0xf3646
+ shr cx, 008h ; c1 e9 08 ; 0xf3647 floppy.c:746
+ mov al, cl ; 88 c8 ; 0xf364a
+ out DX, AL ; ee ; 0xf364c
+ mov AL, strict byte 04ah ; b0 4a ; 0xf364d floppy.c:753
+ mov dx, strict word 0000bh ; ba 0b 00 ; 0xf364f
+ out DX, AL ; ee ; 0xf3652
+ mov al, ah ; 88 e0 ; 0xf3653 floppy.c:756
+ mov dx, 00081h ; ba 81 00 ; 0xf3655
+ out DX, AL ; ee ; 0xf3658
+ mov AL, strict byte 002h ; b0 02 ; 0xf3659 floppy.c:759
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf365b
+ out DX, AL ; ee ; 0xf365e
+ movzx cx, bl ; 0f b6 cb ; 0xf365f floppy.c:764
+ mov ax, cx ; 89 c8 ; 0xf3662
+ call 03053h ; e8 ec f9 ; 0xf3664
+ mov AL, strict byte 0c5h ; b0 c5 ; 0xf3667 floppy.c:767
+ mov dx, 003f5h ; ba f5 03 ; 0xf3669
+ out DX, AL ; ee ; 0xf366c
+ movzx dx, byte [bp-004h] ; 0f b6 56 fc ; 0xf366d floppy.c:768
+ sal dx, 002h ; c1 e2 02 ; 0xf3671
+ movzx ax, bl ; 0f b6 c3 ; 0xf3674
+ or ax, dx ; 09 d0 ; 0xf3677
+ mov dx, 003f5h ; ba f5 03 ; 0xf3679
+ out DX, AL ; ee ; 0xf367c
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf367d floppy.c:769
+ out DX, AL ; ee ; 0xf3680
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf3681 floppy.c:770
+ out DX, AL ; ee ; 0xf3684
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf3685 floppy.c:771
+ out DX, AL ; ee ; 0xf3688
+ mov AL, strict byte 002h ; b0 02 ; 0xf3689 floppy.c:772
+ out DX, AL ; ee ; 0xf368b
+ movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xf368c floppy.c:773
+ movzx ax, bh ; 0f b6 c7 ; 0xf3690
+ add ax, dx ; 01 d0 ; 0xf3693
+ dec ax ; 48 ; 0xf3695
+ mov dx, 003f5h ; ba f5 03 ; 0xf3696
+ out DX, AL ; ee ; 0xf3699
+ xor al, al ; 30 c0 ; 0xf369a floppy.c:774
+ out DX, AL ; ee ; 0xf369c
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf369d floppy.c:775
+ out DX, AL ; ee ; 0xf369f
+ call 02fd9h ; e8 36 f9 ; 0xf36a0 floppy.c:804
+ test al, al ; 84 c0 ; 0xf36a3 floppy.c:805
+ je near 03527h ; 0f 84 7e fe ; 0xf36a5
+ mov dx, 003f4h ; ba f4 03 ; 0xf36a9 floppy.c:816
+ in AL, DX ; ec ; 0xf36ac
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf36ad
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf36af floppy.c:817
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xf36b1
+ je short 036c3h ; 74 0e ; 0xf36b3
+ push 00287h ; 68 87 02 ; 0xf36b5 floppy.c:818
+ push 002bah ; 68 ba 02 ; 0xf36b8
+ push strict byte 00007h ; 6a 07 ; 0xf36bb
+ call 01a14h ; e8 54 e3 ; 0xf36bd
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf36c0
+ xor cx, cx ; 31 c9 ; 0xf36c3 floppy.c:821
+ jmp short 036cch ; eb 05 ; 0xf36c5
+ cmp cx, strict byte 00007h ; 83 f9 07 ; 0xf36c7
+ jnl short 036e2h ; 7d 16 ; 0xf36ca
+ mov dx, 003f5h ; ba f5 03 ; 0xf36cc floppy.c:822
+ in AL, DX ; ec ; 0xf36cf
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf36d0
+ mov si, cx ; 89 ce ; 0xf36d2
+ add si, strict byte 00042h ; 83 c6 42 ; 0xf36d4
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf36d7 floppy.c:43
+ mov es, dx ; 8e c2 ; 0xf36da
+ mov byte [es:si], al ; 26 88 04 ; 0xf36dc
+ inc cx ; 41 ; 0xf36df floppy.c:822
+ jmp short 036c7h ; eb e5 ; 0xf36e0
+ mov si, strict word 00042h ; be 42 00 ; 0xf36e2 floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf36e5
+ mov es, ax ; 8e c0 ; 0xf36e8
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf36ea
+ test AL, strict byte 0c0h ; a8 c0 ; 0xf36ed floppy.c:39
+ je near 035cbh ; 0f 84 d8 fe ; 0xf36ef
+ mov bx, strict word 00043h ; bb 43 00 ; 0xf36f3 floppy.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf36f6
+ test AL, strict byte 002h ; a8 02 ; 0xf36f9 floppy.c:39
+ je short 03705h ; 74 08 ; 0xf36fb
+ mov word [bp+016h], 00300h ; c7 46 16 00 03 ; 0xf36fd floppy.c:829
+ jmp near 03b18h ; e9 13 04 ; 0xf3702
+ mov word [bp+016h], 00100h ; c7 46 16 00 01 ; 0xf3705 floppy.c:832
+ jmp near 03b18h ; e9 0b 04 ; 0xf370a floppy.c:833
+ movzx dx, byte [bp-002h] ; 0f b6 56 fe ; 0xf370d floppy.c:848
+ movzx ax, bl ; 0f b6 c3 ; 0xf3711
+ call 02f8ch ; e8 75 f8 ; 0xf3714
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf3717 floppy.c:850
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf371b floppy.c:851
+ jmp near 03383h ; e9 61 fc ; 0xf371f floppy.c:852
+ mov bh, byte [bp+016h] ; 8a 7e 16 ; 0xf3722 floppy.c:859
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf3725 floppy.c:860
+ shr ax, 008h ; c1 e8 08 ; 0xf3728
+ mov byte [bp-002h], al ; 88 46 fe ; 0xf372b
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf372e floppy.c:861
+ shr dx, 008h ; c1 ea 08 ; 0xf3731
+ mov byte [bp-004h], dl ; 88 56 fc ; 0xf3734
+ mov bl, byte [bp+00eh] ; 8a 5e 0e ; 0xf3737 floppy.c:862
+ cmp bl, 001h ; 80 fb 01 ; 0xf373a floppy.c:864
+ jnbe short 03751h ; 77 12 ; 0xf373d
+ cmp dl, 001h ; 80 fa 01 ; 0xf373f
+ jnbe short 03751h ; 77 0d ; 0xf3742
+ cmp AL, strict byte 04fh ; 3c 4f ; 0xf3744
+ jnbe short 03751h ; 77 09 ; 0xf3746
+ test bh, bh ; 84 ff ; 0xf3748
+ je short 03751h ; 74 05 ; 0xf374a
+ cmp bh, 012h ; 80 ff 12 ; 0xf374c
+ jbe short 0376ch ; 76 1b ; 0xf374f
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3751 floppy.c:866
+ xor ah, ah ; 30 e4 ; 0xf3754
+ or ah, 001h ; 80 cc 01 ; 0xf3756
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3759
+ mov si, strict word 00041h ; be 41 00 ; 0xf375c floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf375f
+ mov es, ax ; 8e c0 ; 0xf3762
+ mov byte [es:si], 001h ; 26 c6 04 01 ; 0xf3764
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf3768 floppy.c:868
+ movzx ax, bl ; 0f b6 c3 ; 0xf376c floppy.c:872
+ call 03283h ; e8 11 fb ; 0xf376f
+ test ax, ax ; 85 c0 ; 0xf3772
+ jne short 03790h ; 75 1a ; 0xf3774
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3776 floppy.c:873
+ xor ah, ah ; 30 e4 ; 0xf3779
+ or ah, 080h ; 80 cc 80 ; 0xf377b
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf377e
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3781 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3784
+ mov es, ax ; 8e c0 ; 0xf3787
+ mov byte [es:bx], 080h ; 26 c6 07 80 ; 0xf3789
+ jmp near 03b18h ; e9 88 03 ; 0xf378d
+ movzx cx, bl ; 0f b6 cb ; 0xf3790 floppy.c:880
+ mov ax, cx ; 89 c8 ; 0xf3793
+ call 030c7h ; e8 2f f9 ; 0xf3795
+ test ax, ax ; 85 c0 ; 0xf3798
+ jne short 037a7h ; 75 0b ; 0xf379a
+ mov ax, cx ; 89 c8 ; 0xf379c floppy.c:881
+ call 0319fh ; e8 fe f9 ; 0xf379e
+ test ax, ax ; 85 c0 ; 0xf37a1
+ je near 0342bh ; 0f 84 84 fc ; 0xf37a3
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf37a7 floppy.c:892
+ shr dx, 00ch ; c1 ea 0c ; 0xf37aa
+ mov ah, dl ; 88 d4 ; 0xf37ad
+ mov cx, word [bp+006h] ; 8b 4e 06 ; 0xf37af floppy.c:893
+ sal cx, 004h ; c1 e1 04 ; 0xf37b2
+ mov si, word [bp+010h] ; 8b 76 10 ; 0xf37b5 floppy.c:894
+ add si, cx ; 01 ce ; 0xf37b8
+ mov word [bp-008h], si ; 89 76 f8 ; 0xf37ba
+ cmp cx, si ; 39 f1 ; 0xf37bd floppy.c:896
+ jbe short 037c3h ; 76 02 ; 0xf37bf
+ db 0feh, 0c4h
+ ; inc ah ; fe c4 ; 0xf37c1 floppy.c:898
+ movzx cx, bh ; 0f b6 cf ; 0xf37c3 floppy.c:900
+ sal cx, 002h ; c1 e1 02 ; 0xf37c6
+ dec cx ; 49 ; 0xf37c9
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf37ca floppy.c:903
+ add dx, cx ; 01 ca ; 0xf37cd
+ cmp dx, word [bp-008h] ; 3b 56 f8 ; 0xf37cf floppy.c:904
+ jc near 0347eh ; 0f 82 a8 fc ; 0xf37d2
+ mov AL, strict byte 006h ; b0 06 ; 0xf37d6 floppy.c:912
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf37d8
+ out DX, AL ; ee ; 0xf37db
+ xor al, al ; 30 c0 ; 0xf37dc floppy.c:913
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf37de
+ out DX, AL ; ee ; 0xf37e1
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf37e2 floppy.c:914
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf37e5
+ out DX, AL ; ee ; 0xf37e8
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf37e9 floppy.c:915
+ shr dx, 008h ; c1 ea 08 ; 0xf37ec
+ mov al, dl ; 88 d0 ; 0xf37ef
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf37f1
+ out DX, AL ; ee ; 0xf37f4
+ xor al, al ; 30 c0 ; 0xf37f5 floppy.c:916
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf37f7
+ out DX, AL ; ee ; 0xf37fa
+ mov al, cl ; 88 c8 ; 0xf37fb floppy.c:917
+ mov dx, strict word 00005h ; ba 05 00 ; 0xf37fd
+ out DX, AL ; ee ; 0xf3800
+ shr cx, 008h ; c1 e9 08 ; 0xf3801 floppy.c:918
+ mov al, cl ; 88 c8 ; 0xf3804
+ out DX, AL ; ee ; 0xf3806
+ mov AL, strict byte 04ah ; b0 4a ; 0xf3807 floppy.c:921
+ mov dx, strict word 0000bh ; ba 0b 00 ; 0xf3809
+ out DX, AL ; ee ; 0xf380c
+ mov al, ah ; 88 e0 ; 0xf380d floppy.c:923
+ mov dx, 00081h ; ba 81 00 ; 0xf380f
+ out DX, AL ; ee ; 0xf3812
+ mov AL, strict byte 002h ; b0 02 ; 0xf3813 floppy.c:924
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf3815
+ out DX, AL ; ee ; 0xf3818
+ movzx cx, bl ; 0f b6 cb ; 0xf3819 floppy.c:927
+ mov ax, cx ; 89 c8 ; 0xf381c
+ call 03053h ; e8 32 f8 ; 0xf381e
+ mov AL, strict byte 00fh ; b0 0f ; 0xf3821 floppy.c:930
+ mov dx, 003f5h ; ba f5 03 ; 0xf3823
+ out DX, AL ; ee ; 0xf3826
+ movzx dx, byte [bp-004h] ; 0f b6 56 fc ; 0xf3827 floppy.c:931
+ sal dx, 002h ; c1 e2 02 ; 0xf382b
+ movzx ax, bl ; 0f b6 c3 ; 0xf382e
+ or dx, ax ; 09 c2 ; 0xf3831
+ mov word [bp-00ah], dx ; 89 56 f6 ; 0xf3833
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf3836
+ mov dx, 003f5h ; ba f5 03 ; 0xf3839
+ out DX, AL ; ee ; 0xf383c
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf383d floppy.c:932
+ out DX, AL ; ee ; 0xf3840
+ mov AL, strict byte 04dh ; b0 4d ; 0xf3841 floppy.c:935
+ out DX, AL ; ee ; 0xf3843
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf3844 floppy.c:936
+ out DX, AL ; ee ; 0xf3847
+ mov AL, strict byte 002h ; b0 02 ; 0xf3848 floppy.c:937
+ out DX, AL ; ee ; 0xf384a
+ mov al, bh ; 88 f8 ; 0xf384b floppy.c:938
+ out DX, AL ; ee ; 0xf384d
+ xor al, bh ; 30 f8 ; 0xf384e floppy.c:939
+ out DX, AL ; ee ; 0xf3850
+ mov AL, strict byte 0f6h ; b0 f6 ; 0xf3851 floppy.c:940
+ out DX, AL ; ee ; 0xf3853
+ call 02fd9h ; e8 82 f7 ; 0xf3854 floppy.c:968
+ test al, al ; 84 c0 ; 0xf3857 floppy.c:969
+ jne short 03863h ; 75 08 ; 0xf3859
+ mov ax, cx ; 89 c8 ; 0xf385b floppy.c:970
+ call 03011h ; e8 b1 f7 ; 0xf385d
+ jmp near 03776h ; e9 13 ff ; 0xf3860 floppy.c:68
+ mov dx, 003f4h ; ba f4 03 ; 0xf3863 floppy.c:979
+ in AL, DX ; ec ; 0xf3866
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf3867
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf3869 floppy.c:980
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xf386b
+ je short 0387dh ; 74 0e ; 0xf386d
+ push 00287h ; 68 87 02 ; 0xf386f floppy.c:981
+ push 002bah ; 68 ba 02 ; 0xf3872
+ push strict byte 00007h ; 6a 07 ; 0xf3875
+ call 01a14h ; e8 9a e1 ; 0xf3877
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf387a
+ xor cx, cx ; 31 c9 ; 0xf387d floppy.c:984
+ jmp short 03886h ; eb 05 ; 0xf387f
+ cmp cx, strict byte 00007h ; 83 f9 07 ; 0xf3881
+ jnl short 0389ch ; 7d 16 ; 0xf3884
+ mov dx, 003f5h ; ba f5 03 ; 0xf3886 floppy.c:985
+ in AL, DX ; ec ; 0xf3889
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf388a
+ mov si, cx ; 89 ce ; 0xf388c
+ add si, strict byte 00042h ; 83 c6 42 ; 0xf388e
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3891 floppy.c:43
+ mov es, dx ; 8e c2 ; 0xf3894
+ mov byte [es:si], al ; 26 88 04 ; 0xf3896
+ inc cx ; 41 ; 0xf3899 floppy.c:985
+ jmp short 03881h ; eb e5 ; 0xf389a
+ mov si, strict word 00042h ; be 42 00 ; 0xf389c floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf389f
+ mov es, ax ; 8e c0 ; 0xf38a2
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf38a4
+ test AL, strict byte 0c0h ; a8 c0 ; 0xf38a7 floppy.c:39
+ je short 038c5h ; 74 1a ; 0xf38a9
+ mov si, strict word 00043h ; be 43 00 ; 0xf38ab floppy.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf38ae
+ test AL, strict byte 002h ; a8 02 ; 0xf38b1 floppy.c:39
+ jne near 036fdh ; 0f 85 46 fe ; 0xf38b3
+ push 00287h ; 68 87 02 ; 0xf38b7 floppy.c:996
+ push 002ceh ; 68 ce 02 ; 0xf38ba
+ push strict byte 00007h ; 6a 07 ; 0xf38bd
+ call 01a14h ; e8 52 e1 ; 0xf38bf
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf38c2
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf38c5 floppy.c:1000
+ mov si, strict word 00041h ; be 41 00 ; 0xf38c9 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf38cc
+ mov es, ax ; 8e c0 ; 0xf38cf
+ mov byte [es:si], 000h ; 26 c6 04 00 ; 0xf38d1
+ movzx ax, bl ; 0f b6 c3 ; 0xf38d5 floppy.c:1002
+ xor dx, dx ; 31 d2 ; 0xf38d8
+ call 02f8ch ; e8 af f6 ; 0xf38da
+ jmp near 035d9h ; e9 f9 fc ; 0xf38dd
+ mov bl, ah ; 88 e3 ; 0xf38e0 floppy.c:1009
+ cmp ah, 001h ; 80 fc 01 ; 0xf38e2 floppy.c:1011
+ jbe short 03904h ; 76 1d ; 0xf38e5
+ xor ax, ax ; 31 c0 ; 0xf38e7 floppy.c:1012
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf38e9
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf38ec floppy.c:1013
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf38ef floppy.c:1014
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf38f2 floppy.c:1015
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf38f5 floppy.c:1016
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf38f8 floppy.c:1017
+ movzx ax, bh ; 0f b6 c7 ; 0xf38fb floppy.c:1018
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf38fe
+ jmp near 03a26h ; e9 22 01 ; 0xf3901
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf3904 floppy.c:1019
+ call 01756h ; e8 4c de ; 0xf3907
+ mov dl, al ; 88 c2 ; 0xf390a
+ xor bh, bh ; 30 ff ; 0xf390c floppy.c:1025
+ test AL, strict byte 0f0h ; a8 f0 ; 0xf390e floppy.c:1026
+ je short 03914h ; 74 02 ; 0xf3910
+ mov BH, strict byte 001h ; b7 01 ; 0xf3912 floppy.c:1027
+ test dl, 00fh ; f6 c2 0f ; 0xf3914 floppy.c:1028
+ je short 0391bh ; 74 02 ; 0xf3917
+ db 0feh, 0c7h
+ ; inc bh ; fe c7 ; 0xf3919 floppy.c:1029
+ test bl, bl ; 84 db ; 0xf391b floppy.c:1031
+ jne short 03924h ; 75 05 ; 0xf391d
+ shr dl, 004h ; c0 ea 04 ; 0xf391f floppy.c:1032
+ jmp short 03927h ; eb 03 ; 0xf3922 floppy.c:1033
+ and dl, 00fh ; 80 e2 0f ; 0xf3924 floppy.c:1034
+ mov byte [bp+011h], 000h ; c6 46 11 00 ; 0xf3927 floppy.c:1037
+ movzx ax, dl ; 0f b6 c2 ; 0xf392b
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf392e
+ mov word [bp+016h], strict word 00000h ; c7 46 16 00 00 ; 0xf3931 floppy.c:1038
+ mov cx, word [bp+012h] ; 8b 4e 12 ; 0xf3936 floppy.c:1040
+ xor cl, cl ; 30 c9 ; 0xf3939
+ movzx ax, bh ; 0f b6 c7 ; 0xf393b
+ or cx, ax ; 09 c1 ; 0xf393e
+ mov word [bp+012h], cx ; 89 4e 12 ; 0xf3940
+ mov ax, cx ; 89 c8 ; 0xf3943 floppy.c:1041
+ xor ah, ch ; 30 ec ; 0xf3945
+ or ah, 001h ; 80 cc 01 ; 0xf3947
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf394a
+ cmp dl, 003h ; 80 fa 03 ; 0xf394d floppy.c:1043
+ jc short 03967h ; 72 15 ; 0xf3950
+ jbe short 0398eh ; 76 3a ; 0xf3952
+ cmp dl, 005h ; 80 fa 05 ; 0xf3954
+ jc short 03995h ; 72 3c ; 0xf3957
+ jbe short 0399ch ; 76 41 ; 0xf3959
+ cmp dl, 00fh ; 80 fa 0f ; 0xf395b
+ je short 039aah ; 74 4a ; 0xf395e
+ cmp dl, 00eh ; 80 fa 0e ; 0xf3960
+ je short 039a3h ; 74 3e ; 0xf3963
+ jmp short 039b1h ; eb 4a ; 0xf3965
+ cmp dl, 002h ; 80 fa 02 ; 0xf3967
+ je short 03987h ; 74 1b ; 0xf396a
+ cmp dl, 001h ; 80 fa 01 ; 0xf396c
+ je short 03980h ; 74 0f ; 0xf396f
+ test dl, dl ; 84 d2 ; 0xf3971
+ jne short 039b1h ; 75 3c ; 0xf3973
+ mov word [bp+014h], strict word 00000h ; c7 46 14 00 00 ; 0xf3975 floppy.c:1045
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf397a floppy.c:1046
+ jmp short 039bfh ; eb 3f ; 0xf397e floppy.c:1047
+ mov word [bp+014h], 02709h ; c7 46 14 09 27 ; 0xf3980 floppy.c:1050
+ jmp short 039bfh ; eb 38 ; 0xf3985 floppy.c:1051
+ mov word [bp+014h], 04f0fh ; c7 46 14 0f 4f ; 0xf3987 floppy.c:1054
+ jmp short 039bfh ; eb 31 ; 0xf398c floppy.c:1055
+ mov word [bp+014h], 04f09h ; c7 46 14 09 4f ; 0xf398e floppy.c:1058
+ jmp short 039bfh ; eb 2a ; 0xf3993 floppy.c:1059
+ mov word [bp+014h], 04f12h ; c7 46 14 12 4f ; 0xf3995 floppy.c:1062
+ jmp short 039bfh ; eb 23 ; 0xf399a floppy.c:1063
+ mov word [bp+014h], 04f24h ; c7 46 14 24 4f ; 0xf399c floppy.c:1066
+ jmp short 039bfh ; eb 1c ; 0xf39a1 floppy.c:1067
+ mov word [bp+014h], 0fe3fh ; c7 46 14 3f fe ; 0xf39a3 floppy.c:1070
+ jmp short 039bfh ; eb 15 ; 0xf39a8 floppy.c:1071
+ mov word [bp+014h], 0feffh ; c7 46 14 ff fe ; 0xf39aa floppy.c:1074
+ jmp short 039bfh ; eb 0e ; 0xf39af floppy.c:1075
+ push 00287h ; 68 87 02 ; 0xf39b1 floppy.c:1079
+ push 002dfh ; 68 df 02 ; 0xf39b4
+ push strict byte 00007h ; 6a 07 ; 0xf39b7
+ call 01a14h ; e8 58 e0 ; 0xf39b9
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf39bc
+ mov word [bp+006h], 0f000h ; c7 46 06 00 f0 ; 0xf39bf floppy.c:1083
+ movzx ax, dl ; 0f b6 c2 ; 0xf39c4 floppy.c:1084
+ call 03c4eh ; e8 84 02 ; 0xf39c7
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf39ca
+ jmp near 035d9h ; e9 09 fc ; 0xf39cd
+ mov bl, ah ; 88 e3 ; 0xf39d0 floppy.c:1091
+ cmp ah, 001h ; 80 fc 01 ; 0xf39d2 floppy.c:1092
+ jbe short 039dch ; 76 05 ; 0xf39d5
+ mov word [bp+016h], dx ; 89 56 16 ; 0xf39d7 floppy.c:1093
+ jmp short 03a26h ; eb 4a ; 0xf39da
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf39dc floppy.c:1099
+ call 01756h ; e8 74 dd ; 0xf39df
+ test bl, bl ; 84 db ; 0xf39e2 floppy.c:1100
+ jne short 039edh ; 75 07 ; 0xf39e4
+ mov dl, al ; 88 c2 ; 0xf39e6 floppy.c:1101
+ shr dl, 004h ; c0 ea 04 ; 0xf39e8
+ jmp short 039f2h ; eb 05 ; 0xf39eb floppy.c:1102
+ mov dl, al ; 88 c2 ; 0xf39ed floppy.c:1103
+ and dl, 00fh ; 80 e2 0f ; 0xf39ef
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf39f2 floppy.c:1104
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf39f6
+ xor ah, ah ; 30 e4 ; 0xf39f9
+ test dl, dl ; 84 d2 ; 0xf39fb floppy.c:1105
+ je short 03a0ch ; 74 0d ; 0xf39fd
+ cmp dl, 001h ; 80 fa 01 ; 0xf39ff floppy.c:1106
+ jbe short 03a09h ; 76 05 ; 0xf3a02
+ or ah, 002h ; 80 cc 02 ; 0xf3a04 floppy.c:1108
+ jmp short 03a0ch ; eb 03 ; 0xf3a07 floppy.c:1109
+ or ah, 001h ; 80 cc 01 ; 0xf3a09 floppy.c:1110
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3a0c
+ jmp near 03383h ; e9 71 f9 ; 0xf3a0f floppy.c:1113
+ cmp ah, 001h ; 80 fc 01 ; 0xf3a12 floppy.c:1118
+ jbe short 03a2ch ; 76 15 ; 0xf3a15
+ mov word [bp+016h], si ; 89 76 16 ; 0xf3a17 floppy.c:1119
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3a1a floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3a1d
+ mov es, ax ; 8e c0 ; 0xf3a20
+ mov byte [es:bx], 001h ; 26 c6 07 01 ; 0xf3a22
+ mov word [bp+01ch], cx ; 89 4e 1c ; 0xf3a26
+ jmp near 03383h ; e9 57 f9 ; 0xf3a29
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3a2c floppy.c:1125
+ xor ah, ah ; 30 e4 ; 0xf3a2f
+ or ah, 006h ; 80 cc 06 ; 0xf3a31
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3a34
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3a37 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3a3a
+ mov es, ax ; 8e c0 ; 0xf3a3d
+ mov byte [es:bx], 006h ; 26 c6 07 06 ; 0xf3a3f
+ jmp near 03b18h ; e9 d2 00 ; 0xf3a43
+ mov bl, ah ; 88 e3 ; 0xf3a46 floppy.c:1134
+ mov dl, byte [bp+016h] ; 8a 56 16 ; 0xf3a48 floppy.c:1142
+ cmp ah, 001h ; 80 fc 01 ; 0xf3a4b floppy.c:1146
+ jnbe short 03a17h ; 77 c7 ; 0xf3a4e
+ movzx ax, bl ; 0f b6 c3 ; 0xf3a50 floppy.c:1154
+ call 03283h ; e8 2d f8 ; 0xf3a53
+ test ax, ax ; 85 c0 ; 0xf3a56
+ je near 03776h ; 0f 84 1a fd ; 0xf3a58
+ test bl, bl ; 84 db ; 0xf3a5c floppy.c:1162
+ db 00fh, 095h, 0c0h
+ ; setne al ; 0f 95 c0 ; 0xf3a5e
+ movzx bx, al ; 0f b6 d8 ; 0xf3a61
+ add bx, 00090h ; 81 c3 90 00 ; 0xf3a64
+ mov word [bp-008h], bx ; 89 5e f8 ; 0xf3a68
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3a6b floppy.c:38
+ mov es, ax ; 8e c0 ; 0xf3a6e
+ mov bl, byte [es:bx] ; 26 8a 1f ; 0xf3a70
+ and bl, 00fh ; 80 e3 0f ; 0xf3a73 floppy.c:1166
+ cmp dl, 002h ; 80 fa 02 ; 0xf3a76 floppy.c:1168
+ jc short 03a8ah ; 72 0f ; 0xf3a79
+ jbe short 03a97h ; 76 1a ; 0xf3a7b
+ cmp dl, 004h ; 80 fa 04 ; 0xf3a7d
+ je short 03a92h ; 74 10 ; 0xf3a80
+ cmp dl, 003h ; 80 fa 03 ; 0xf3a82
+ je short 03a9ch ; 74 15 ; 0xf3a85
+ jmp near 03312h ; e9 88 f8 ; 0xf3a87
+ cmp dl, 001h ; 80 fa 01 ; 0xf3a8a
+ je short 03a92h ; 74 03 ; 0xf3a8d
+ jmp near 03312h ; e9 80 f8 ; 0xf3a8f
+ or bl, 090h ; 80 cb 90 ; 0xf3a92 floppy.c:1171
+ jmp short 03a9fh ; eb 08 ; 0xf3a95 floppy.c:1172
+ or bl, 070h ; 80 cb 70 ; 0xf3a97 floppy.c:1175
+ jmp short 03a9fh ; eb 03 ; 0xf3a9a floppy.c:1176
+ or bl, 010h ; 80 cb 10 ; 0xf3a9c floppy.c:1179
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3a9f floppy.c:43
+ mov es, ax ; 8e c0 ; 0xf3aa2
+ mov si, word [bp-008h] ; 8b 76 f8 ; 0xf3aa4
+ mov byte [es:si], bl ; 26 88 1c ; 0xf3aa7
+ xor al, al ; 30 c0 ; 0xf3aaa floppy.c:1198
+ mov byte [bp+017h], al ; 88 46 17 ; 0xf3aac
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3aaf floppy.c:43
+ mov byte [es:bx], al ; 26 88 07 ; 0xf3ab2
+ jmp near 035d9h ; e9 21 fb ; 0xf3ab5
+ mov bl, ah ; 88 e3 ; 0xf3ab8 floppy.c:1208
+ mov dl, byte [bp+014h] ; 8a 56 14 ; 0xf3aba floppy.c:1210
+ mov bh, dl ; 88 d7 ; 0xf3abd floppy.c:1211
+ and bh, 03fh ; 80 e7 3f ; 0xf3abf
+ xor dh, dh ; 30 f6 ; 0xf3ac2 floppy.c:1212
+ sar dx, 006h ; c1 fa 06 ; 0xf3ac4
+ sal dx, 008h ; c1 e2 08 ; 0xf3ac7
+ mov word [bp-00ch], dx ; 89 56 f4 ; 0xf3aca
+ mov dx, word [bp+014h] ; 8b 56 14 ; 0xf3acd
+ shr dx, 008h ; c1 ea 08 ; 0xf3ad0
+ add dx, word [bp-00ch] ; 03 56 f4 ; 0xf3ad3
+ mov byte [bp-002h], dl ; 88 56 fe ; 0xf3ad6
+ cmp ah, 001h ; 80 fc 01 ; 0xf3ad9 floppy.c:1217
+ jnbe near 03a17h ; 0f 87 37 ff ; 0xf3adc
+ movzx ax, bl ; 0f b6 c3 ; 0xf3ae0 floppy.c:1225
+ call 03283h ; e8 9d f7 ; 0xf3ae3
+ test ax, ax ; 85 c0 ; 0xf3ae6
+ je near 03776h ; 0f 84 8a fc ; 0xf3ae8
+ movzx cx, bl ; 0f b6 cb ; 0xf3aec floppy.c:1233
+ mov ax, cx ; 89 c8 ; 0xf3aef
+ call 030c7h ; e8 d3 f5 ; 0xf3af1
+ test ax, ax ; 85 c0 ; 0xf3af4
+ jne short 03b1fh ; 75 27 ; 0xf3af6
+ mov ax, cx ; 89 c8 ; 0xf3af8 floppy.c:1234
+ call 0319fh ; e8 a2 f6 ; 0xf3afa
+ test ax, ax ; 85 c0 ; 0xf3afd
+ jne short 03b1fh ; 75 1e ; 0xf3aff
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3b01 floppy.c:1235
+ xor ah, ah ; 30 e4 ; 0xf3b04
+ or ah, 00ch ; 80 cc 0c ; 0xf3b06
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3b09
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3b0c floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3b0f
+ mov es, ax ; 8e c0 ; 0xf3b12
+ mov byte [es:bx], 00ch ; 26 c6 07 0c ; 0xf3b14
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf3b18
+ jmp near 03383h ; e9 64 f8 ; 0xf3b1c
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf3b1f floppy.c:1243
+ call 01756h ; e8 31 dc ; 0xf3b22
+ test bl, bl ; 84 db ; 0xf3b25 floppy.c:1244
+ jne short 03b30h ; 75 07 ; 0xf3b27
+ mov dl, al ; 88 c2 ; 0xf3b29 floppy.c:1245
+ shr dl, 004h ; c0 ea 04 ; 0xf3b2b
+ jmp short 03b35h ; eb 05 ; 0xf3b2e floppy.c:1246
+ mov dl, al ; 88 c2 ; 0xf3b30 floppy.c:1247
+ and dl, 00fh ; 80 e2 0f ; 0xf3b32
+ test bl, bl ; 84 db ; 0xf3b35 floppy.c:1250
+ db 00fh, 095h, 0c0h
+ ; setne al ; 0f 95 c0 ; 0xf3b37
+ movzx si, al ; 0f b6 f0 ; 0xf3b3a
+ add si, 00090h ; 81 c6 90 00 ; 0xf3b3d
+ mov word [bp-008h], si ; 89 76 f8 ; 0xf3b41
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3b44 floppy.c:38
+ mov es, ax ; 8e c0 ; 0xf3b47
+ mov bl, byte [es:si] ; 26 8a 1c ; 0xf3b49
+ and bl, 00fh ; 80 e3 0f ; 0xf3b4c floppy.c:39
+ cmp dl, 003h ; 80 fa 03 ; 0xf3b4f floppy.c:1256
+ jc short 03b71h ; 72 1d ; 0xf3b52
+ mov al, bl ; 88 d8 ; 0xf3b54
+ or AL, strict byte 090h ; 0c 90 ; 0xf3b56
+ cmp dl, 003h ; 80 fa 03 ; 0xf3b58
+ jbe short 03bb2h ; 76 55 ; 0xf3b5b
+ mov ah, bl ; 88 dc ; 0xf3b5d
+ or ah, 010h ; 80 cc 10 ; 0xf3b5f
+ cmp dl, 005h ; 80 fa 05 ; 0xf3b62
+ je near 03bd7h ; 0f 84 6e 00 ; 0xf3b65
+ cmp dl, 004h ; 80 fa 04 ; 0xf3b69
+ je short 03bc1h ; 74 53 ; 0xf3b6c
+ jmp near 03bf3h ; e9 82 00 ; 0xf3b6e
+ cmp dl, 002h ; 80 fa 02 ; 0xf3b71
+ je short 03b92h ; 74 1c ; 0xf3b74
+ cmp dl, 001h ; 80 fa 01 ; 0xf3b76
+ jne near 03bf3h ; 0f 85 76 00 ; 0xf3b79
+ cmp byte [bp-002h], 027h ; 80 7e fe 27 ; 0xf3b7d floppy.c:1258
+ jne near 03bf3h ; 0f 85 6e 00 ; 0xf3b81
+ cmp bh, 009h ; 80 ff 09 ; 0xf3b85
+ jne near 03bf3h ; 0f 85 67 00 ; 0xf3b88
+ or bl, 090h ; 80 cb 90 ; 0xf3b8c floppy.c:1259
+ jmp near 03bf3h ; e9 61 00 ; 0xf3b8f floppy.c:1261
+ cmp byte [bp-002h], 027h ; 80 7e fe 27 ; 0xf3b92 floppy.c:1263
+ jne short 03ba2h ; 75 0a ; 0xf3b96
+ cmp bh, 009h ; 80 ff 09 ; 0xf3b98
+ jne short 03ba2h ; 75 05 ; 0xf3b9b
+ or bl, 070h ; 80 cb 70 ; 0xf3b9d floppy.c:1264
+ jmp short 03bf3h ; eb 51 ; 0xf3ba0 floppy.c:1265
+ cmp byte [bp-002h], 04fh ; 80 7e fe 4f ; 0xf3ba2
+ jne short 03bf3h ; 75 4b ; 0xf3ba6
+ cmp bh, 00fh ; 80 ff 0f ; 0xf3ba8
+ jne short 03bf3h ; 75 46 ; 0xf3bab
+ or bl, 010h ; 80 cb 10 ; 0xf3bad floppy.c:1266
+ jmp short 03bf3h ; eb 41 ; 0xf3bb0 floppy.c:1268
+ cmp byte [bp-002h], 04fh ; 80 7e fe 4f ; 0xf3bb2 floppy.c:1270
+ jne short 03bf3h ; 75 3b ; 0xf3bb6
+ cmp bh, 009h ; 80 ff 09 ; 0xf3bb8
+ jne short 03bf3h ; 75 36 ; 0xf3bbb
+ mov bl, al ; 88 c3 ; 0xf3bbd floppy.c:1271
+ jmp short 03bf3h ; eb 32 ; 0xf3bbf floppy.c:1273
+ cmp byte [bp-002h], 04fh ; 80 7e fe 4f ; 0xf3bc1 floppy.c:1275
+ jne short 03bf3h ; 75 2c ; 0xf3bc5
+ cmp bh, 009h ; 80 ff 09 ; 0xf3bc7 floppy.c:1276
+ jne short 03bceh ; 75 02 ; 0xf3bca
+ jmp short 03bbdh ; eb ef ; 0xf3bcc
+ cmp bh, 012h ; 80 ff 12 ; 0xf3bce floppy.c:1277
+ jne short 03bf3h ; 75 20 ; 0xf3bd1
+ mov bl, ah ; 88 e3 ; 0xf3bd3 floppy.c:1279
+ jmp short 03bf3h ; eb 1c ; 0xf3bd5 floppy.c:1282
+ cmp byte [bp-002h], 04fh ; 80 7e fe 4f ; 0xf3bd7 floppy.c:1284
+ jne short 03bf3h ; 75 16 ; 0xf3bdb
+ cmp bh, 009h ; 80 ff 09 ; 0xf3bdd floppy.c:1285
+ jne short 03be4h ; 75 02 ; 0xf3be0
+ jmp short 03bbdh ; eb d9 ; 0xf3be2
+ cmp bh, 012h ; 80 ff 12 ; 0xf3be4 floppy.c:1286
+ jne short 03bebh ; 75 02 ; 0xf3be7
+ jmp short 03bd3h ; eb e8 ; 0xf3be9
+ cmp bh, 024h ; 80 ff 24 ; 0xf3beb floppy.c:1288
+ jne short 03bf3h ; 75 03 ; 0xf3bee
+ or bl, 0d0h ; 80 cb d0 ; 0xf3bf0 floppy.c:1290
+ movzx ax, bl ; 0f b6 c3 ; 0xf3bf3 floppy.c:1299
+ sar ax, 004h ; c1 f8 04 ; 0xf3bf6
+ test AL, strict byte 001h ; a8 01 ; 0xf3bf9
+ je near 03b01h ; 0f 84 02 ff ; 0xf3bfb
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3bff floppy.c:43
+ mov es, ax ; 8e c0 ; 0xf3c02
+ mov si, word [bp-008h] ; 8b 76 f8 ; 0xf3c04
+ mov byte [es:si], bl ; 26 88 1c ; 0xf3c07
+ mov word [bp+006h], 0f000h ; c7 46 06 00 f0 ; 0xf3c0a floppy.c:1312
+ movzx ax, dl ; 0f b6 c2 ; 0xf3c0f floppy.c:1313
+ call 03c4eh ; e8 39 00 ; 0xf3c12
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf3c15
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf3c18 floppy.c:1316
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3c1c floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3c1f
+ mov es, ax ; 8e c0 ; 0xf3c22
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3c24
+ jmp near 035d9h ; e9 ae f9 ; 0xf3c28
+ mov bx, 00db2h ; bb b2 0d ; 0xf3c2b floppy.c:1322
+ mov cx, ds ; 8c d9 ; 0xf3c2e
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3c30
+ call 019d3h ; e8 9d dd ; 0xf3c33
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3c36
+ shr ax, 008h ; c1 e8 08 ; 0xf3c39
+ push ax ; 50 ; 0xf3c3c
+ push 00287h ; 68 87 02 ; 0xf3c3d
+ push 002f4h ; 68 f4 02 ; 0xf3c40
+ push strict byte 00004h ; 6a 04 ; 0xf3c43
+ call 01a14h ; e8 cc dd ; 0xf3c45
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf3c48
+ jmp near 03312h ; e9 c4 f6 ; 0xf3c4b floppy.c:68
+ ; disGetNextSymbol 0xf3c4e LB 0x63f7 -> off=0x0 cb=000000000000002f uValue=00000000000f264e 'get_floppy_dpt'
+get_floppy_dpt: ; 0xf3c4e LB 0x2f
+ push bx ; 53 ; 0xf3c4e floppyt.c:94
+ push dx ; 52 ; 0xf3c4f
+ push bp ; 55 ; 0xf3c50
+ mov bp, sp ; 89 e5 ; 0xf3c51
+ mov dl, al ; 88 c2 ; 0xf3c53
+ xor ax, ax ; 31 c0 ; 0xf3c55 floppyt.c:98
+ jmp short 03c5fh ; eb 06 ; 0xf3c57
+ inc ax ; 40 ; 0xf3c59 floppyt.c:100
+ cmp ax, strict word 00007h ; 3d 07 00 ; 0xf3c5a
+ jnc short 03c76h ; 73 17 ; 0xf3c5d
+ mov bx, ax ; 89 c3 ; 0xf3c5f
+ add bx, ax ; 01 c3 ; 0xf3c61
+ cmp dl, byte [word bx+0005bh] ; 3a 97 5b 00 ; 0xf3c63
+ jne short 03c59h ; 75 f0 ; 0xf3c67
+ movzx ax, byte [word bx+0005ch] ; 0f b6 87 5c 00 ; 0xf3c69
+ imul ax, ax, strict byte 0000dh ; 6b c0 0d ; 0xf3c6e
+ add ax, strict word 00000h ; 05 00 00 ; 0xf3c71
+ jmp short 03c79h ; eb 03 ; 0xf3c74
+ mov ax, strict word 00041h ; b8 41 00 ; 0xf3c76 floppyt.c:103
+ pop bp ; 5d ; 0xf3c79 floppyt.c:104
+ pop dx ; 5a ; 0xf3c7a
+ pop bx ; 5b ; 0xf3c7b
+ retn ; c3 ; 0xf3c7c
+ ; disGetNextSymbol 0xf3c7d LB 0x63c8 -> off=0x0 cb=0000000000000007 uValue=00000000000f267d 'dummy_soft_reset'
+dummy_soft_reset: ; 0xf3c7d LB 0x7
+ push bp ; 55 ; 0xf3c7d eltorito.c:126
+ mov bp, sp ; 89 e5 ; 0xf3c7e
+ xor ax, ax ; 31 c0 ; 0xf3c80 eltorito.c:129
+ pop bp ; 5d ; 0xf3c82
+ retn ; c3 ; 0xf3c83
+ ; disGetNextSymbol 0xf3c84 LB 0x63c1 -> off=0x0 cb=0000000000000017 uValue=00000000000f2684 'cdemu_init'
+cdemu_init: ; 0xf3c84 LB 0x17
+ push bp ; 55 ; 0xf3c84 eltorito.c:155
+ mov bp, sp ; 89 e5 ; 0xf3c85
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3c87 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3c8a
+ mov es, ax ; 8e c0 ; 0xf3c8d
+ mov es, [es:bx] ; 26 8e 07 ; 0xf3c8f
+ mov bx, 00366h ; bb 66 03 ; 0xf3c92 eltorito.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3c95
+ pop bp ; 5d ; 0xf3c99 eltorito.c:162
+ retn ; c3 ; 0xf3c9a
+ ; disGetNextSymbol 0xf3c9b LB 0x63aa -> off=0x0 cb=0000000000000016 uValue=00000000000f269b 'cdemu_isactive'
+cdemu_isactive: ; 0xf3c9b LB 0x16
+ push bp ; 55 ; 0xf3c9b eltorito.c:164
+ mov bp, sp ; 89 e5 ; 0xf3c9c
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3c9e eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3ca1
+ mov es, ax ; 8e c0 ; 0xf3ca4
+ mov es, [es:bx] ; 26 8e 07 ; 0xf3ca6
+ mov bx, 00366h ; bb 66 03 ; 0xf3ca9 eltorito.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf3cac
+ pop bp ; 5d ; 0xf3caf eltorito.c:170
+ retn ; c3 ; 0xf3cb0
+ ; disGetNextSymbol 0xf3cb1 LB 0x6394 -> off=0x0 cb=0000000000000016 uValue=00000000000f26b1 'cdemu_emulated_drive'
+cdemu_emulated_drive: ; 0xf3cb1 LB 0x16
+ push bp ; 55 ; 0xf3cb1 eltorito.c:172
+ mov bp, sp ; 89 e5 ; 0xf3cb2
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3cb4 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3cb7
+ mov es, ax ; 8e c0 ; 0xf3cba
+ mov es, [es:bx] ; 26 8e 07 ; 0xf3cbc
+ mov bx, 00368h ; bb 68 03 ; 0xf3cbf eltorito.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf3cc2
+ pop bp ; 5d ; 0xf3cc5 eltorito.c:178
+ retn ; c3 ; 0xf3cc6
+ ; disGetNextSymbol 0xf3cc7 LB 0x637e -> off=0x0 cb=000000000000017a uValue=00000000000f26c7 'int13_eltorito'
+int13_eltorito: ; 0xf3cc7 LB 0x17a
+ push bp ; 55 ; 0xf3cc7 eltorito.c:184
+ mov bp, sp ; 89 e5 ; 0xf3cc8
+ push si ; 56 ; 0xf3cca
+ push di ; 57 ; 0xf3ccb
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3ccc eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3ccf
+ mov es, ax ; 8e c0 ; 0xf3cd2
+ mov di, word [es:bx] ; 26 8b 3f ; 0xf3cd4
+ mov bx, 00366h ; bb 66 03 ; 0xf3cd7 eltorito.c:190
+ mov si, word [bp+016h] ; 8b 76 16 ; 0xf3cda eltorito.c:196
+ shr si, 008h ; c1 ee 08 ; 0xf3cdd
+ cmp si, strict byte 0004bh ; 83 fe 4b ; 0xf3ce0
+ jc short 03cefh ; 72 0a ; 0xf3ce3
+ jbe short 03d15h ; 76 2e ; 0xf3ce5
+ cmp si, strict byte 0004dh ; 83 fe 4d ; 0xf3ce7
+ jbe short 03cf6h ; 76 0a ; 0xf3cea
+ jmp near 03e07h ; e9 18 01 ; 0xf3cec
+ cmp si, strict byte 0004ah ; 83 fe 4a ; 0xf3cef
+ jne near 03e07h ; 0f 85 11 01 ; 0xf3cf2
+ mov bx, 00db2h ; bb b2 0d ; 0xf3cf6 eltorito.c:202
+ mov cx, ds ; 8c d9 ; 0xf3cf9
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3cfb
+ call 019d3h ; e8 d2 dc ; 0xf3cfe
+ push word [bp+016h] ; ff 76 16 ; 0xf3d01
+ push 0030eh ; 68 0e 03 ; 0xf3d04
+ push 0031dh ; 68 1d 03 ; 0xf3d07
+ push strict byte 00004h ; 6a 04 ; 0xf3d0a
+ call 01a14h ; e8 05 dd ; 0xf3d0c
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf3d0f
+ jmp near 03e22h ; e9 0d 01 ; 0xf3d12 eltorito.c:203
+ mov es, [bp+004h] ; 8e 46 04 ; 0xf3d15 eltorito.c:41
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3d18
+ mov byte [es:si], 013h ; 26 c6 04 13 ; 0xf3d1b
+ inc si ; 46 ; 0xf3d1f eltorito.c:210
+ mov ax, es ; 8c c0 ; 0xf3d20 eltorito.c:41
+ mov es, di ; 8e c7 ; 0xf3d22
+ mov dl, byte [es:bx+001h] ; 26 8a 57 01 ; 0xf3d24
+ mov es, ax ; 8e c0 ; 0xf3d28 eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3d2a
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3d2d eltorito.c:211
+ inc si ; 46 ; 0xf3d30
+ inc si ; 46 ; 0xf3d31
+ mov es, di ; 8e c7 ; 0xf3d32 eltorito.c:41
+ mov dl, byte [es:bx+002h] ; 26 8a 57 02 ; 0xf3d34
+ mov es, ax ; 8e c0 ; 0xf3d38 eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3d3a
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3d3d eltorito.c:212
+ add si, strict byte 00003h ; 83 c6 03 ; 0xf3d40
+ mov es, di ; 8e c7 ; 0xf3d43 eltorito.c:41
+ mov dl, byte [es:bx+003h] ; 26 8a 57 03 ; 0xf3d45
+ mov es, ax ; 8e c0 ; 0xf3d49 eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3d4b
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3d4e eltorito.c:213
+ add si, strict byte 00004h ; 83 c6 04 ; 0xf3d51
+ mov es, di ; 8e c7 ; 0xf3d54 eltorito.c:61
+ mov dx, word [es:bx+008h] ; 26 8b 57 08 ; 0xf3d56
+ mov cx, word [es:bx+00ah] ; 26 8b 4f 0a ; 0xf3d5a
+ mov es, ax ; 8e c0 ; 0xf3d5e eltorito.c:63
+ mov word [es:si], dx ; 26 89 14 ; 0xf3d60
+ mov word [es:si+002h], cx ; 26 89 4c 02 ; 0xf3d63
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3d67 eltorito.c:214
+ add si, strict byte 00008h ; 83 c6 08 ; 0xf3d6a
+ mov es, di ; 8e c7 ; 0xf3d6d eltorito.c:51
+ mov dx, word [es:bx+004h] ; 26 8b 57 04 ; 0xf3d6f
+ mov es, ax ; 8e c0 ; 0xf3d73 eltorito.c:53
+ mov word [es:si], dx ; 26 89 14 ; 0xf3d75
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3d78 eltorito.c:215
+ add si, strict byte 0000ah ; 83 c6 0a ; 0xf3d7b
+ mov es, di ; 8e c7 ; 0xf3d7e eltorito.c:51
+ mov dx, word [es:bx+006h] ; 26 8b 57 06 ; 0xf3d80
+ mov es, ax ; 8e c0 ; 0xf3d84 eltorito.c:53
+ mov word [es:si], dx ; 26 89 14 ; 0xf3d86
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3d89 eltorito.c:216
+ add si, strict byte 0000ch ; 83 c6 0c ; 0xf3d8c
+ mov es, di ; 8e c7 ; 0xf3d8f eltorito.c:51
+ mov dx, word [es:bx+00ch] ; 26 8b 57 0c ; 0xf3d91
+ mov es, ax ; 8e c0 ; 0xf3d95 eltorito.c:53
+ mov word [es:si], dx ; 26 89 14 ; 0xf3d97
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3d9a eltorito.c:217
+ add si, strict byte 0000eh ; 83 c6 0e ; 0xf3d9d
+ mov es, di ; 8e c7 ; 0xf3da0 eltorito.c:51
+ mov dx, word [es:bx+00eh] ; 26 8b 57 0e ; 0xf3da2
+ mov es, ax ; 8e c0 ; 0xf3da6 eltorito.c:53
+ mov word [es:si], dx ; 26 89 14 ; 0xf3da8
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3dab eltorito.c:218
+ add si, strict byte 00010h ; 83 c6 10 ; 0xf3dae
+ mov es, di ; 8e c7 ; 0xf3db1 eltorito.c:41
+ mov dl, byte [es:bx+012h] ; 26 8a 57 12 ; 0xf3db3
+ mov es, ax ; 8e c0 ; 0xf3db7 eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3db9
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3dbc eltorito.c:219
+ add si, strict byte 00011h ; 83 c6 11 ; 0xf3dbf
+ mov es, di ; 8e c7 ; 0xf3dc2 eltorito.c:41
+ mov dl, byte [es:bx+014h] ; 26 8a 57 14 ; 0xf3dc4
+ mov es, ax ; 8e c0 ; 0xf3dc8 eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3dca
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3dcd eltorito.c:220
+ add si, strict byte 00012h ; 83 c6 12 ; 0xf3dd0
+ mov dx, ax ; 89 c2 ; 0xf3dd3 eltorito.c:41
+ mov es, di ; 8e c7 ; 0xf3dd5
+ mov al, byte [es:bx+010h] ; 26 8a 47 10 ; 0xf3dd7
+ mov es, dx ; 8e c2 ; 0xf3ddb eltorito.c:43
+ mov byte [es:si], al ; 26 88 04 ; 0xf3ddd
+ test byte [bp+016h], 0ffh ; f6 46 16 ff ; 0xf3de0 eltorito.c:223
+ jne short 03dech ; 75 06 ; 0xf3de4
+ mov es, di ; 8e c7 ; 0xf3de6 eltorito.c:225
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3de8
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf3dec eltorito.c:228
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf3df0
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3df3
+ mov es, ax ; 8e c0 ; 0xf3df6
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3df8
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf3dfc
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf3e00
+ pop di ; 5f ; 0xf3e03
+ pop si ; 5e ; 0xf3e04
+ pop bp ; 5d ; 0xf3e05
+ retn ; c3 ; 0xf3e06
+ mov bx, 00db2h ; bb b2 0d ; 0xf3e07 eltorito.c:232
+ mov cx, ds ; 8c d9 ; 0xf3e0a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3e0c
+ call 019d3h ; e8 c1 db ; 0xf3e0f
+ mov bx, word [bp+016h] ; 8b 5e 16 ; 0xf3e12
+ shr bx, 008h ; c1 eb 08 ; 0xf3e15
+ push bx ; 53 ; 0xf3e18
+ push 0030eh ; 68 0e 03 ; 0xf3e19
+ push 00345h ; 68 45 03 ; 0xf3e1c
+ jmp near 03d0ah ; e9 e8 fe ; 0xf3e1f
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3e22 eltorito.c:238
+ xor ah, ah ; 30 e4 ; 0xf3e25
+ or ah, 001h ; 80 cc 01 ; 0xf3e27
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3e2a
+ shr ax, 008h ; c1 e8 08 ; 0xf3e2d eltorito.c:239
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf3e30 eltorito.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3e33
+ mov es, dx ; 8e c2 ; 0xf3e36
+ mov byte [es:bx], al ; 26 88 07 ; 0xf3e38
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf3e3b eltorito.c:240
+ jmp short 03e00h ; eb bf ; 0xf3e3f eltorito.c:241
+ ; disGetNextSymbol 0xf3e41 LB 0x6204 -> off=0x0 cb=0000000000000033 uValue=00000000000f2841 'device_is_cdrom'
+device_is_cdrom: ; 0xf3e41 LB 0x33
+ push bx ; 53 ; 0xf3e41 eltorito.c:256
+ push dx ; 52 ; 0xf3e42
+ push bp ; 55 ; 0xf3e43
+ mov bp, sp ; 89 e5 ; 0xf3e44
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3e46 eltorito.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3e49
+ mov es, dx ; 8e c2 ; 0xf3e4c
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf3e4e
+ cmp AL, strict byte 010h ; 3c 10 ; 0xf3e51 eltorito.c:262
+ jc short 03e59h ; 72 04 ; 0xf3e53
+ xor ax, ax ; 31 c0 ; 0xf3e55 eltorito.c:263
+ jmp short 03e70h ; eb 17 ; 0xf3e57
+ xor ah, ah ; 30 e4 ; 0xf3e59 eltorito.c:268
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf3e5b
+ mov es, bx ; 8e c3 ; 0xf3e5e
+ mov bx, ax ; 89 c3 ; 0xf3e60
+ add bx, 00122h ; 81 c3 22 01 ; 0xf3e62
+ cmp byte [es:bx+023h], 005h ; 26 80 7f 23 05 ; 0xf3e66
+ jne short 03e55h ; 75 e8 ; 0xf3e6b
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf3e6d eltorito.c:269
+ pop bp ; 5d ; 0xf3e70 eltorito.c:272
+ pop dx ; 5a ; 0xf3e71
+ pop bx ; 5b ; 0xf3e72
+ retn ; c3 ; 0xf3e73
+ ; disGetNextSymbol 0xf3e74 LB 0x61d1 -> off=0x0 cb=00000000000003ab uValue=00000000000f2874 'cdrom_boot'
+cdrom_boot: ; 0xf3e74 LB 0x3ab
+ push bp ; 55 ; 0xf3e74 eltorito.c:282
+ mov bp, sp ; 89 e5 ; 0xf3e75
+ push bx ; 53 ; 0xf3e77
+ push cx ; 51 ; 0xf3e78
+ push dx ; 52 ; 0xf3e79
+ push si ; 56 ; 0xf3e7a
+ push di ; 57 ; 0xf3e7b
+ sub sp, 0081ch ; 81 ec 1c 08 ; 0xf3e7c
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3e80 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3e83
+ mov es, ax ; 8e c0 ; 0xf3e86
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf3e88
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf3e8b eltorito.c:49
+ mov si, 00366h ; be 66 03 ; 0xf3e8e eltorito.c:295
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf3e91
+ mov word [bp-012h], 00122h ; c7 46 ee 22 01 ; 0xf3e94 eltorito.c:296
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf3e99
+ mov byte [bp-00eh], 000h ; c6 46 f2 00 ; 0xf3e9c eltorito.c:299
+ jmp short 03eabh ; eb 09 ; 0xf3ea0
+ inc byte [bp-00eh] ; fe 46 f2 ; 0xf3ea2 eltorito.c:302
+ cmp byte [bp-00eh], 010h ; 80 7e f2 10 ; 0xf3ea5
+ jnc short 03eb6h ; 73 0b ; 0xf3ea9
+ movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xf3eab
+ call 03e41h ; e8 8f ff ; 0xf3eaf
+ test ax, ax ; 85 c0 ; 0xf3eb2
+ je short 03ea2h ; 74 ec ; 0xf3eb4
+ cmp byte [bp-00eh], 010h ; 80 7e f2 10 ; 0xf3eb6 eltorito.c:305
+ jc short 03ec2h ; 72 06 ; 0xf3eba
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf3ebc eltorito.c:306
+ jmp near 04215h ; e9 53 03 ; 0xf3ebf
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf3ec2 eltorito.c:309
+ xor bx, bx ; 31 db ; 0xf3ec5
+ mov dx, ss ; 8c d2 ; 0xf3ec7
+ lea ax, [bp-026h] ; 8d 46 da ; 0xf3ec9
+ call 09fb0h ; e8 e1 60 ; 0xf3ecc
+ mov word [bp-026h], strict word 00028h ; c7 46 da 28 00 ; 0xf3ecf eltorito.c:310
+ mov ax, strict word 00011h ; b8 11 00 ; 0xf3ed4 eltorito.c:311
+ xor dx, dx ; 31 d2 ; 0xf3ed7
+ xchg ah, al ; 86 c4 ; 0xf3ed9
+ xchg dh, dl ; 86 d6 ; 0xf3edb
+ xchg dx, ax ; 92 ; 0xf3edd
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf3ede
+ mov word [bp-022h], dx ; 89 56 de ; 0xf3ee1
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf3ee4 eltorito.c:312
+ xchg ah, al ; 86 c4 ; 0xf3ee7
+ mov word [bp-01fh], ax ; 89 46 e1 ; 0xf3ee9
+ les bx, [bp-012h] ; c4 5e ee ; 0xf3eec eltorito.c:314
+ db 066h, 026h, 0c7h, 047h, 00eh, 001h, 000h, 000h, 008h
+ ; mov dword [es:bx+00eh], strict dword 008000001h ; 66 26 c7 47 0e 01 00 00 08; 0xf3eef
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf3ef8 eltorito.c:317
+ jmp short 03f07h ; eb 09 ; 0xf3efc
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf3efe eltorito.c:322
+ cmp byte [bp-00ch], 004h ; 80 7e f4 04 ; 0xf3f01
+ jnbe short 03f3dh ; 77 36 ; 0xf3f05
+ movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xf3f07
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf3f0b
+ les bx, [bp-012h] ; c4 5e ee ; 0xf3f0e
+ add bx, ax ; 01 c3 ; 0xf3f11
+ movzx di, byte [es:bx+022h] ; 26 0f b6 7f 22 ; 0xf3f13
+ add di, di ; 01 ff ; 0xf3f18
+ lea dx, [bp-00826h] ; 8d 96 da f7 ; 0xf3f1a
+ push SS ; 16 ; 0xf3f1e
+ push dx ; 52 ; 0xf3f1f
+ push strict byte 00001h ; 6a 01 ; 0xf3f20
+ push strict byte 00000h ; 6a 00 ; 0xf3f22
+ push 00800h ; 68 00 08 ; 0xf3f24
+ push strict byte 00000h ; 6a 00 ; 0xf3f27
+ movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xf3f29
+ mov cx, ss ; 8c d1 ; 0xf3f2d
+ lea bx, [bp-026h] ; 8d 5e da ; 0xf3f2f
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3f32
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf3f35
+ test ax, ax ; 85 c0 ; 0xf3f39
+ jne short 03efeh ; 75 c1 ; 0xf3f3b
+ test ax, ax ; 85 c0 ; 0xf3f3d eltorito.c:323
+ je short 03f47h ; 74 06 ; 0xf3f3f
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf3f41 eltorito.c:324
+ jmp near 04215h ; e9 ce 02 ; 0xf3f44
+ cmp byte [bp-00826h], 000h ; 80 be da f7 00 ; 0xf3f47 eltorito.c:327
+ je short 03f54h ; 74 06 ; 0xf3f4c
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3f4e eltorito.c:328
+ jmp near 04215h ; e9 c1 02 ; 0xf3f51
+ xor di, di ; 31 ff ; 0xf3f54 eltorito.c:330
+ jmp short 03f5eh ; eb 06 ; 0xf3f56
+ inc di ; 47 ; 0xf3f58 eltorito.c:332
+ cmp di, strict byte 00005h ; 83 ff 05 ; 0xf3f59
+ jnc short 03f6eh ; 73 10 ; 0xf3f5c
+ mov al, byte [bp+di-00825h] ; 8a 83 db f7 ; 0xf3f5e
+ cmp al, byte [di+00dbah] ; 3a 85 ba 0d ; 0xf3f62
+ je short 03f58h ; 74 f0 ; 0xf3f66
+ mov ax, strict word 00005h ; b8 05 00 ; 0xf3f68
+ jmp near 04215h ; e9 a7 02 ; 0xf3f6b
+ xor di, di ; 31 ff ; 0xf3f6e eltorito.c:334
+ jmp short 03f78h ; eb 06 ; 0xf3f70
+ inc di ; 47 ; 0xf3f72 eltorito.c:336
+ cmp di, strict byte 00017h ; 83 ff 17 ; 0xf3f73
+ jnc short 03f88h ; 73 10 ; 0xf3f76
+ mov al, byte [bp+di-0081fh] ; 8a 83 e1 f7 ; 0xf3f78
+ cmp al, byte [di+00dc0h] ; 3a 85 c0 0d ; 0xf3f7c
+ je short 03f72h ; 74 f0 ; 0xf3f80
+ mov ax, strict word 00006h ; b8 06 00 ; 0xf3f82
+ jmp near 04215h ; e9 8d 02 ; 0xf3f85
+ mov ax, word [bp-007dfh] ; 8b 86 21 f8 ; 0xf3f88 eltorito.c:339
+ mov dx, word [bp-007ddh] ; 8b 96 23 f8 ; 0xf3f8c
+ mov word [bp-026h], strict word 00028h ; c7 46 da 28 00 ; 0xf3f90 eltorito.c:343
+ xchg ah, al ; 86 c4 ; 0xf3f95 eltorito.c:344
+ xchg dh, dl ; 86 d6 ; 0xf3f97
+ xchg dx, ax ; 92 ; 0xf3f99
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf3f9a
+ mov word [bp-022h], dx ; 89 56 de ; 0xf3f9d
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf3fa0 eltorito.c:345
+ xchg ah, al ; 86 c4 ; 0xf3fa3
+ mov word [bp-01fh], ax ; 89 46 e1 ; 0xf3fa5
+ movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xf3fa8 eltorito.c:352
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf3fac
+ les di, [bp-012h] ; c4 7e ee ; 0xf3faf
+ add di, ax ; 01 c7 ; 0xf3fb2
+ movzx di, byte [es:di+022h] ; 26 0f b6 7d 22 ; 0xf3fb4
+ add di, di ; 01 ff ; 0xf3fb9
+ lea dx, [bp-00826h] ; 8d 96 da f7 ; 0xf3fbb
+ push SS ; 16 ; 0xf3fbf
+ push dx ; 52 ; 0xf3fc0
+ push strict byte 00001h ; 6a 01 ; 0xf3fc1
+ push strict byte 00000h ; 6a 00 ; 0xf3fc3
+ push 00800h ; 68 00 08 ; 0xf3fc5
+ push strict byte 00000h ; 6a 00 ; 0xf3fc8
+ movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xf3fca
+ mov cx, ss ; 8c d1 ; 0xf3fce
+ lea bx, [bp-026h] ; 8d 5e da ; 0xf3fd0
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3fd3
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf3fd6
+ test ax, ax ; 85 c0 ; 0xf3fda eltorito.c:353
+ je short 03fe4h ; 74 06 ; 0xf3fdc
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf3fde eltorito.c:354
+ jmp near 04215h ; e9 31 02 ; 0xf3fe1
+ cmp byte [bp-00826h], 001h ; 80 be da f7 01 ; 0xf3fe4 eltorito.c:359
+ je short 03ff1h ; 74 06 ; 0xf3fe9
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf3feb eltorito.c:360
+ jmp near 04215h ; e9 24 02 ; 0xf3fee
+ cmp byte [bp-00825h], 000h ; 80 be db f7 00 ; 0xf3ff1 eltorito.c:361
+ je short 03ffeh ; 74 06 ; 0xf3ff6
+ mov ax, strict word 00009h ; b8 09 00 ; 0xf3ff8 eltorito.c:362
+ jmp near 04215h ; e9 17 02 ; 0xf3ffb
+ cmp byte [bp-00808h], 055h ; 80 be f8 f7 55 ; 0xf3ffe eltorito.c:363
+ je short 0400bh ; 74 06 ; 0xf4003
+ mov ax, strict word 0000ah ; b8 0a 00 ; 0xf4005 eltorito.c:364
+ jmp near 04215h ; e9 0a 02 ; 0xf4008
+ cmp byte [bp-00807h], 0aah ; 80 be f9 f7 aa ; 0xf400b eltorito.c:365
+ jne short 04005h ; 75 f3 ; 0xf4010
+ cmp byte [bp-00806h], 088h ; 80 be fa f7 88 ; 0xf4012 eltorito.c:366
+ je short 0401fh ; 74 06 ; 0xf4017
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf4019 eltorito.c:370
+ jmp near 04215h ; e9 f6 01 ; 0xf401c
+ mov al, byte [bp-00805h] ; 8a 86 fb f7 ; 0xf401f eltorito.c:372
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf4023
+ mov byte [es:si+001h], al ; 26 88 44 01 ; 0xf4026
+ cmp byte [bp-00805h], 000h ; 80 be fb f7 00 ; 0xf402a eltorito.c:373
+ jne short 04038h ; 75 07 ; 0xf402f
+ mov byte [es:si+002h], 0e0h ; 26 c6 44 02 e0 ; 0xf4031 eltorito.c:376
+ jmp short 0404bh ; eb 13 ; 0xf4036 eltorito.c:378
+ cmp byte [bp-00805h], 004h ; 80 be fb f7 04 ; 0xf4038
+ jnc short 04046h ; 73 07 ; 0xf403d
+ mov byte [es:si+002h], 000h ; 26 c6 44 02 00 ; 0xf403f eltorito.c:379
+ jmp short 0404bh ; eb 05 ; 0xf4044 eltorito.c:380
+ mov byte [es:si+002h], 080h ; 26 c6 44 02 80 ; 0xf4046 eltorito.c:381
+ movzx di, byte [bp-00eh] ; 0f b6 7e f2 ; 0xf404b eltorito.c:383
+ mov ax, di ; 89 f8 ; 0xf404f
+ cwd ; 99 ; 0xf4051
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf4052
+ sar ax, 1 ; d1 f8 ; 0xf4054
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf4056
+ mov byte [es:si+003h], al ; 26 88 44 03 ; 0xf4059
+ mov ax, di ; 89 f8 ; 0xf405d eltorito.c:384
+ cwd ; 99 ; 0xf405f
+ mov bx, strict word 00002h ; bb 02 00 ; 0xf4060
+ idiv bx ; f7 fb ; 0xf4063
+ mov word [es:si+004h], dx ; 26 89 54 04 ; 0xf4065
+ mov ax, word [bp-00804h] ; 8b 86 fc f7 ; 0xf4069 eltorito.c:386
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf406d
+ test ax, ax ; 85 c0 ; 0xf4070 eltorito.c:387
+ jne short 04079h ; 75 05 ; 0xf4072
+ mov word [bp-014h], 007c0h ; c7 46 ec c0 07 ; 0xf4074 eltorito.c:388
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf4079 eltorito.c:390
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf407c
+ mov word [es:si+00ch], ax ; 26 89 44 0c ; 0xf407f
+ mov word [es:si+006h], strict word 00000h ; 26 c7 44 06 00 00 ; 0xf4083 eltorito.c:391
+ mov di, word [bp-00800h] ; 8b be 00 f8 ; 0xf4089 eltorito.c:393
+ mov word [es:si+00eh], di ; 26 89 7c 0e ; 0xf408d eltorito.c:394
+ test di, di ; 85 ff ; 0xf4091 eltorito.c:399
+ je short 0409bh ; 74 06 ; 0xf4093
+ cmp di, 00400h ; 81 ff 00 04 ; 0xf4095
+ jbe short 040a1h ; 76 06 ; 0xf4099
+ mov ax, strict word 0000ch ; b8 0c 00 ; 0xf409b eltorito.c:400
+ jmp near 04215h ; e9 74 01 ; 0xf409e
+ mov ax, word [bp-007feh] ; 8b 86 02 f8 ; 0xf40a1 eltorito.c:402
+ mov dx, word [bp-007fch] ; 8b 96 04 f8 ; 0xf40a5
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf40a9 eltorito.c:403
+ mov word [es:si+00ah], dx ; 26 89 54 0a ; 0xf40ad
+ mov word [bp-026h], strict word 00028h ; c7 46 da 28 00 ; 0xf40b1 eltorito.c:409
+ xchg ah, al ; 86 c4 ; 0xf40b6 eltorito.c:410
+ xchg dh, dl ; 86 d6 ; 0xf40b8
+ xchg dx, ax ; 92 ; 0xf40ba
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf40bb
+ mov word [bp-022h], dx ; 89 56 de ; 0xf40be
+ lea dx, [di-001h] ; 8d 55 ff ; 0xf40c1 eltorito.c:411
+ shr dx, 002h ; c1 ea 02 ; 0xf40c4
+ inc dx ; 42 ; 0xf40c7
+ mov ax, dx ; 89 d0 ; 0xf40c8
+ xchg ah, al ; 86 c4 ; 0xf40ca
+ mov word [bp-01fh], ax ; 89 46 e1 ; 0xf40cc
+ les bx, [bp-012h] ; c4 5e ee ; 0xf40cf eltorito.c:413
+ mov word [es:bx+00eh], dx ; 26 89 57 0e ; 0xf40d2
+ mov word [es:bx+010h], 00200h ; 26 c7 47 10 00 02 ; 0xf40d6 eltorito.c:414
+ mov ax, di ; 89 f8 ; 0xf40dc eltorito.c:416
+ sal ax, 009h ; c1 e0 09 ; 0xf40de
+ mov dx, 00800h ; ba 00 08 ; 0xf40e1
+ sub dx, ax ; 29 c2 ; 0xf40e4
+ mov ax, dx ; 89 d0 ; 0xf40e6
+ and ah, 007h ; 80 e4 07 ; 0xf40e8
+ mov word [es:bx+020h], ax ; 26 89 47 20 ; 0xf40eb
+ movzx bx, byte [bp-00eh] ; 0f b6 5e f2 ; 0xf40ef eltorito.c:418
+ imul bx, bx, strict byte 0001ch ; 6b db 1c ; 0xf40f3
+ add bx, word [bp-012h] ; 03 5e ee ; 0xf40f6
+ movzx ax, byte [es:bx+022h] ; 26 0f b6 47 22 ; 0xf40f9
+ add ax, ax ; 01 c0 ; 0xf40fe
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf4100
+ push word [bp-014h] ; ff 76 ec ; 0xf4103
+ push dword 000000001h ; 66 6a 01 ; 0xf4106
+ mov ax, di ; 89 f8 ; 0xf4109
+ xor di, di ; 31 ff ; 0xf410b
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf410d
+ sal ax, 1 ; d1 e0 ; 0xf4110
+ rcl di, 1 ; d1 d7 ; 0xf4112
+ loop 04110h ; e2 fa ; 0xf4114
+ push di ; 57 ; 0xf4116
+ push ax ; 50 ; 0xf4117
+ push strict byte 00000h ; 6a 00 ; 0xf4118
+ movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xf411a
+ mov cx, ss ; 8c d1 ; 0xf411e
+ lea bx, [bp-026h] ; 8d 5e da ; 0xf4120
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf4123
+ mov di, word [bp-01ah] ; 8b 7e e6 ; 0xf4126
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf4129
+ les bx, [bp-012h] ; c4 5e ee ; 0xf412d eltorito.c:420
+ mov word [es:bx+020h], strict word 00000h ; 26 c7 47 20 00 00 ; 0xf4130
+ test ax, ax ; 85 c0 ; 0xf4136 eltorito.c:422
+ je short 04140h ; 74 06 ; 0xf4138
+ mov ax, strict word 0000dh ; b8 0d 00 ; 0xf413a eltorito.c:423
+ jmp near 04215h ; e9 d5 00 ; 0xf413d
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf4140 eltorito.c:428
+ mov al, byte [es:si+001h] ; 26 8a 44 01 ; 0xf4143
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf4147
+ jc short 04157h ; 72 0c ; 0xf4149
+ jbe short 0416fh ; 76 22 ; 0xf414b
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf414d
+ je short 04185h ; 74 34 ; 0xf414f
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf4151
+ je short 0417ah ; 74 25 ; 0xf4153
+ jmp short 041cch ; eb 75 ; 0xf4155
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf4157
+ jne short 041cch ; 75 71 ; 0xf4159
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf415b eltorito.c:430
+ db 066h, 026h, 0c7h, 044h, 012h, 050h, 000h, 00fh, 000h
+ ; mov dword [es:si+012h], strict dword 0000f0050h ; 66 26 c7 44 12 50 00 0f 00; 0xf415e
+ mov word [es:si+010h], strict word 00002h ; 26 c7 44 10 02 00 ; 0xf4167 eltorito.c:432
+ jmp short 041cch ; eb 5d ; 0xf416d eltorito.c:433
+ db 066h, 026h, 0c7h, 044h, 012h, 050h, 000h, 012h, 000h
+ ; mov dword [es:si+012h], strict dword 000120050h ; 66 26 c7 44 12 50 00 12 00; 0xf416f eltorito.c:435
+ jmp short 04167h ; eb ed ; 0xf4178
+ db 066h, 026h, 0c7h, 044h, 012h, 050h, 000h, 024h, 000h
+ ; mov dword [es:si+012h], strict dword 000240050h ; 66 26 c7 44 12 50 00 24 00; 0xf417a eltorito.c:440
+ jmp short 04167h ; eb e2 ; 0xf4183
+ mov bx, 001c4h ; bb c4 01 ; 0xf4185 eltorito.c:38
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf4188
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf418b
+ and AL, strict byte 03fh ; 24 3f ; 0xf418e eltorito.c:39
+ xor ah, ah ; 30 e4 ; 0xf4190
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf4192
+ mov word [es:si+014h], ax ; 26 89 44 14 ; 0xf4195
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf4199 eltorito.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf419c
+ and ax, 000c0h ; 25 c0 00 ; 0xf419f eltorito.c:39
+ mov dx, ax ; 89 c2 ; 0xf41a2
+ sal dx, 002h ; c1 e2 02 ; 0xf41a4
+ mov bx, 001c5h ; bb c5 01 ; 0xf41a7 eltorito.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf41aa
+ xor ah, ah ; 30 e4 ; 0xf41ad eltorito.c:39
+ add ax, dx ; 01 d0 ; 0xf41af
+ inc ax ; 40 ; 0xf41b1
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf41b2
+ mov word [es:si+012h], ax ; 26 89 44 12 ; 0xf41b5
+ mov di, 001c3h ; bf c3 01 ; 0xf41b9 eltorito.c:38
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf41bc
+ mov al, byte [es:di] ; 26 8a 05 ; 0xf41bf
+ xor ah, ah ; 30 e4 ; 0xf41c2 eltorito.c:39
+ inc ax ; 40 ; 0xf41c4
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf41c5
+ mov word [es:si+010h], ax ; 26 89 44 10 ; 0xf41c8
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf41cc eltorito.c:453
+ cmp byte [es:si+001h], 000h ; 26 80 7c 01 00 ; 0xf41cf
+ je short 041fch ; 74 26 ; 0xf41d4
+ cmp byte [es:si+002h], 000h ; 26 80 7c 02 00 ; 0xf41d6 eltorito.c:455
+ jne short 041eeh ; 75 11 ; 0xf41db
+ mov bx, strict word 00010h ; bb 10 00 ; 0xf41dd eltorito.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf41e0
+ mov es, ax ; 8e c0 ; 0xf41e3
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf41e5
+ or AL, strict byte 041h ; 0c 41 ; 0xf41e8 eltorito.c:39
+ mov di, bx ; 89 df ; 0xf41ea eltorito.c:43
+ jmp short 041f9h ; eb 0b ; 0xf41ec eltorito.c:457
+ mov di, 00304h ; bf 04 03 ; 0xf41ee eltorito.c:38
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf41f1
+ mov al, byte [es:di] ; 26 8a 05 ; 0xf41f4
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf41f7 eltorito.c:39
+ mov byte [es:di], al ; 26 88 05 ; 0xf41f9 eltorito.c:43
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf41fc eltorito.c:462
+ cmp byte [es:si+001h], 000h ; 26 80 7c 01 00 ; 0xf41ff
+ je short 0420ah ; 74 04 ; 0xf4204
+ mov byte [es:si], 001h ; 26 c6 04 01 ; 0xf4206 eltorito.c:463
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf420a eltorito.c:466
+ movzx ax, byte [es:si+002h] ; 26 0f b6 44 02 ; 0xf420d
+ sal ax, 008h ; c1 e0 08 ; 0xf4212
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf4215 eltorito.c:467
+ pop di ; 5f ; 0xf4218
+ pop si ; 5e ; 0xf4219
+ pop dx ; 5a ; 0xf421a
+ pop cx ; 59 ; 0xf421b
+ pop bx ; 5b ; 0xf421c
+ pop bp ; 5d ; 0xf421d
+ retn ; c3 ; 0xf421e
+ ; disGetNextSymbol 0xf421f LB 0x5e26 -> off=0x59 cb=00000000000005d8 uValue=00000000000f2c78 'int13_cdemu'
+ db 050h, 04eh, 049h, 048h, 047h, 046h, 045h, 044h, 043h, 042h, 041h, 018h, 016h, 015h, 014h, 011h
+ db 010h, 00dh, 00ch, 00bh, 00ah, 009h, 008h, 005h, 004h, 003h, 002h, 001h, 000h, 033h, 048h, 023h
+ db 043h, 06dh, 043h, 091h, 043h, 062h, 043h, 091h, 043h, 062h, 043h, 08ah, 045h, 047h, 043h, 033h
+ db 048h, 033h, 048h, 047h, 043h, 047h, 043h, 047h, 043h, 047h, 043h, 047h, 043h, 032h, 046h, 047h
+ db 043h, 033h, 048h, 03bh, 046h, 04eh, 046h, 033h, 048h, 04eh, 046h, 033h, 048h, 033h, 048h, 04eh
+ db 046h, 0f7h, 047h, 033h, 048h, 033h, 048h, 033h, 048h
+int13_cdemu: ; 0xf4278 LB 0x5d8
+ push bp ; 55 ; 0xf4278 eltorito.c:477
+ mov bp, sp ; 89 e5 ; 0xf4279
+ push si ; 56 ; 0xf427b
+ push di ; 57 ; 0xf427c
+ sub sp, strict byte 00038h ; 83 ec 38 ; 0xf427d
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf4280 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4283
+ mov es, ax ; 8e c0 ; 0xf4286
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf4288
+ mov dx, 00366h ; ba 66 03 ; 0xf428b eltorito.c:493
+ mov cx, ax ; 89 c1 ; 0xf428e
+ mov bx, dx ; 89 d3 ; 0xf4290
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf4292
+ mov si, 00122h ; be 22 01 ; 0xf4295 eltorito.c:494
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf4298
+ mov es, ax ; 8e c0 ; 0xf429b eltorito.c:501
+ mov di, dx ; 89 d7 ; 0xf429d
+ mov al, byte [es:di+003h] ; 26 8a 45 03 ; 0xf429f
+ add al, al ; 00 c0 ; 0xf42a3
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf42a5
+ mov al, byte [es:di+004h] ; 26 8a 45 04 ; 0xf42a8 eltorito.c:502
+ add byte [bp-006h], al ; 00 46 fa ; 0xf42ac
+ mov di, strict word 00074h ; bf 74 00 ; 0xf42af eltorito.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf42b2
+ mov es, ax ; 8e c0 ; 0xf42b5
+ mov byte [es:di], 000h ; 26 c6 05 00 ; 0xf42b7
+ mov es, cx ; 8e c1 ; 0xf42bb eltorito.c:507
+ mov di, dx ; 89 d7 ; 0xf42bd
+ cmp byte [es:di], 000h ; 26 80 3d 00 ; 0xf42bf
+ je short 042d3h ; 74 0e ; 0xf42c3
+ movzx dx, byte [es:di+002h] ; 26 0f b6 55 02 ; 0xf42c5
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf42ca
+ xor ah, ah ; 30 e4 ; 0xf42cd
+ cmp dx, ax ; 39 c2 ; 0xf42cf
+ je short 042fch ; 74 29 ; 0xf42d1
+ mov bx, 00db2h ; bb b2 0d ; 0xf42d3 eltorito.c:508
+ mov cx, ds ; 8c d9 ; 0xf42d6
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf42d8
+ call 019d3h ; e8 f5 d6 ; 0xf42db
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf42de
+ xor ah, ah ; 30 e4 ; 0xf42e1
+ push ax ; 50 ; 0xf42e3
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf42e4
+ shr ax, 008h ; c1 e8 08 ; 0xf42e7
+ push ax ; 50 ; 0xf42ea
+ push 0035eh ; 68 5e 03 ; 0xf42eb
+ push 0036ah ; 68 6a 03 ; 0xf42ee
+ push strict byte 00004h ; 6a 04 ; 0xf42f1
+ call 01a14h ; e8 1e d7 ; 0xf42f3
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf42f6
+ jmp near 04810h ; e9 14 05 ; 0xf42f9 eltorito.c:509
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf42fc eltorito.c:512
+ shr ax, 008h ; c1 e8 08 ; 0xf42ff
+ cmp ax, strict word 00050h ; 3d 50 00 ; 0xf4302
+ jnbe near 04833h ; 0f 87 2a 05 ; 0xf4305
+ push CS ; 0e ; 0xf4309
+ pop ES ; 07 ; 0xf430a
+ mov cx, strict word 0001eh ; b9 1e 00 ; 0xf430b
+ mov di, 0421fh ; bf 1f 42 ; 0xf430e
+ repne scasb ; f2 ae ; 0xf4311
+ sal cx, 1 ; d1 e1 ; 0xf4313
+ mov di, cx ; 89 cf ; 0xf4315
+ mov dx, word [cs:di+0423ch] ; 2e 8b 95 3c 42 ; 0xf4317
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf431c
+ xor ah, ah ; 30 e4 ; 0xf431f
+ jmp dx ; ff e2 ; 0xf4321
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf4323 eltorito.c:515
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf4327
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf432a
+ add si, ax ; 01 c6 ; 0xf432d
+ movzx bx, byte [es:si+022h] ; 26 0f b6 5c 22 ; 0xf432f
+ add bx, bx ; 01 db ; 0xf4334
+ cmp word [word bx+0006ah], strict byte 00000h ; 83 bf 6a 00 00 ; 0xf4336
+ je near 04347h ; 0f 84 08 00 ; 0xf433b
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf433f eltorito.c:517
+ call word [word bx+00076h] ; ff 97 76 00 ; 0xf4343
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf4347 eltorito.c:519
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf434b
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf434e
+ mov es, ax ; 8e c0 ; 0xf4351
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf4353
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf4357
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf435b
+ pop di ; 5f ; 0xf435e
+ pop si ; 5e ; 0xf435f
+ pop bp ; 5d ; 0xf4360
+ retn ; c3 ; 0xf4361
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf4362 eltorito.c:535
+ xor ah, ah ; 30 e4 ; 0xf4365
+ or ah, 003h ; 80 cc 03 ; 0xf4367
+ jmp near 04818h ; e9 ab 04 ; 0xf436a eltorito.c:536
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf436d eltorito.c:38
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf4370
+ mov es, dx ; 8e c2 ; 0xf4373
+ mov dl, byte [es:bx] ; 26 8a 17 ; 0xf4375
+ movzx bx, dl ; 0f b6 da ; 0xf4378 eltorito.c:541
+ sal bx, 008h ; c1 e3 08 ; 0xf437b
+ or ax, bx ; 09 d8 ; 0xf437e
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf4380
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4383 eltorito.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf4386
+ test dl, dl ; 84 d2 ; 0xf438a eltorito.c:545
+ je short 0434bh ; 74 bd ; 0xf438c
+ jmp near 0482ch ; e9 9b 04 ; 0xf438e eltorito.c:546
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf4391 eltorito.c:553
+ mov ax, word [es:bx+014h] ; 26 8b 47 14 ; 0xf4394
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf4398
+ mov dx, word [es:bx+012h] ; 26 8b 57 12 ; 0xf439b eltorito.c:554
+ mov ax, word [es:bx+010h] ; 26 8b 47 10 ; 0xf439f eltorito.c:555
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf43a3
+ mov ax, word [es:bx+008h] ; 26 8b 47 08 ; 0xf43a6 eltorito.c:556
+ mov word [bp-020h], ax ; 89 46 e0 ; 0xf43aa
+ mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xf43ad
+ mov word [bp-01eh], ax ; 89 46 e2 ; 0xf43b1
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf43b4 eltorito.c:558
+ and ax, strict word 0003fh ; 25 3f 00 ; 0xf43b7
+ mov word [bp-022h], ax ; 89 46 de ; 0xf43ba
+ mov bx, word [bp+014h] ; 8b 5e 14 ; 0xf43bd eltorito.c:559
+ and bx, 000c0h ; 81 e3 c0 00 ; 0xf43c0
+ sal bx, 002h ; c1 e3 02 ; 0xf43c4
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf43c7
+ shr ax, 008h ; c1 e8 08 ; 0xf43ca
+ or ax, bx ; 09 d8 ; 0xf43cd
+ mov bx, word [bp+012h] ; 8b 5e 12 ; 0xf43cf eltorito.c:560
+ shr bx, 008h ; c1 eb 08 ; 0xf43d2
+ mov word [bp-012h], bx ; 89 5e ee ; 0xf43d5
+ mov di, word [bp+016h] ; 8b 7e 16 ; 0xf43d8 eltorito.c:561
+ and di, 000ffh ; 81 e7 ff 00 ; 0xf43db
+ jne short 043e4h ; 75 03 ; 0xf43df eltorito.c:569
+ jmp near 04347h ; e9 63 ff ; 0xf43e1 eltorito.c:570
+ mov bx, word [bp-022h] ; 8b 5e de ; 0xf43e4 eltorito.c:573
+ cmp bx, word [bp-00ch] ; 3b 5e f4 ; 0xf43e7
+ jnbe near 04810h ; 0f 87 22 04 ; 0xf43ea
+ cmp ax, dx ; 39 d0 ; 0xf43ee
+ jnc near 04810h ; 0f 83 1c 04 ; 0xf43f0
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf43f4
+ cmp dx, word [bp-00eh] ; 3b 56 f2 ; 0xf43f7
+ jnc near 04810h ; 0f 83 12 04 ; 0xf43fa
+ mov dx, word [bp+016h] ; 8b 56 16 ; 0xf43fe eltorito.c:580
+ shr dx, 008h ; c1 ea 08 ; 0xf4401
+ cmp dx, strict byte 00004h ; 83 fa 04 ; 0xf4404
+ jne short 0440ch ; 75 03 ; 0xf4407
+ jmp near 04347h ; e9 3b ff ; 0xf4409 eltorito.c:581
+ mov dx, word [bp+010h] ; 8b 56 10 ; 0xf440c eltorito.c:583
+ shr dx, 004h ; c1 ea 04 ; 0xf440f
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf4412
+ add bx, dx ; 01 d3 ; 0xf4415
+ mov word [bp-016h], bx ; 89 5e ea ; 0xf4417
+ mov dx, word [bp+010h] ; 8b 56 10 ; 0xf441a eltorito.c:584
+ and dx, strict byte 0000fh ; 83 e2 0f ; 0xf441d
+ mov word [bp-014h], dx ; 89 56 ec ; 0xf4420
+ xor dl, dl ; 30 d2 ; 0xf4423 eltorito.c:587
+ mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xf4425
+ xor cx, cx ; 31 c9 ; 0xf4428
+ call 09f10h ; e8 e3 5a ; 0xf442a
+ xor bx, bx ; 31 db ; 0xf442d
+ add ax, word [bp-012h] ; 03 46 ee ; 0xf442f
+ adc dx, bx ; 11 da ; 0xf4432
+ mov bx, word [bp-00ch] ; 8b 5e f4 ; 0xf4434
+ xor cx, cx ; 31 c9 ; 0xf4437
+ call 09f10h ; e8 d4 5a ; 0xf4439
+ mov bx, dx ; 89 d3 ; 0xf443c
+ mov dx, word [bp-022h] ; 8b 56 de ; 0xf443e
+ dec dx ; 4a ; 0xf4441
+ mov word [bp-026h], strict word 00000h ; c7 46 da 00 00 ; 0xf4442
+ add dx, ax ; 01 c2 ; 0xf4447
+ adc bx, word [bp-026h] ; 13 5e da ; 0xf4449
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf444c eltorito.c:590
+ xor al, al ; 30 c0 ; 0xf444f
+ or ax, di ; 09 f8 ; 0xf4451
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf4453
+ mov word [bp-02ch], dx ; 89 56 d4 ; 0xf4456 eltorito.c:593
+ mov word [bp-02ah], bx ; 89 5e d6 ; 0xf4459
+ shr word [bp-02ah], 1 ; d1 6e d6 ; 0xf445c
+ rcr word [bp-02ch], 1 ; d1 5e d4 ; 0xf445f
+ shr word [bp-02ah], 1 ; d1 6e d6 ; 0xf4462
+ rcr word [bp-02ch], 1 ; d1 5e d4 ; 0xf4465
+ mov ax, word [bp-02ah] ; 8b 46 d6 ; 0xf4468
+ mov word [bp-028h], ax ; 89 46 d8 ; 0xf446b
+ mov ax, dx ; 89 d0 ; 0xf446e eltorito.c:594
+ xor ah, dh ; 30 f4 ; 0xf4470
+ and AL, strict byte 003h ; 24 03 ; 0xf4472
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf4474
+ xor cx, cx ; 31 c9 ; 0xf4477 eltorito.c:597
+ mov ax, dx ; 89 d0 ; 0xf4479
+ add ax, di ; 01 f8 ; 0xf447b
+ mov dx, bx ; 89 da ; 0xf447d
+ adc dx, cx ; 11 ca ; 0xf447f
+ add ax, strict word 0ffffh ; 05 ff ff ; 0xf4481
+ adc dx, strict byte 0ffffh ; 83 d2 ff ; 0xf4484
+ mov word [bp-030h], ax ; 89 46 d0 ; 0xf4487
+ mov word [bp-02eh], dx ; 89 56 d2 ; 0xf448a
+ shr word [bp-02eh], 1 ; d1 6e d2 ; 0xf448d
+ rcr word [bp-030h], 1 ; d1 5e d0 ; 0xf4490
+ shr word [bp-02eh], 1 ; d1 6e d2 ; 0xf4493
+ rcr word [bp-030h], 1 ; d1 5e d0 ; 0xf4496
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf4499 eltorito.c:599
+ xor bx, bx ; 31 db ; 0xf449c
+ mov dx, ss ; 8c d2 ; 0xf449e
+ lea ax, [bp-03ch] ; 8d 46 c4 ; 0xf44a0
+ call 09fb0h ; e8 0a 5b ; 0xf44a3
+ mov word [bp-03ch], strict word 00028h ; c7 46 c4 28 00 ; 0xf44a6 eltorito.c:600
+ mov ax, word [bp-020h] ; 8b 46 e0 ; 0xf44ab eltorito.c:601
+ add ax, word [bp-02ch] ; 03 46 d4 ; 0xf44ae
+ mov dx, word [bp-01eh] ; 8b 56 e2 ; 0xf44b1
+ adc dx, word [bp-028h] ; 13 56 d8 ; 0xf44b4
+ xchg ah, al ; 86 c4 ; 0xf44b7
+ xchg dh, dl ; 86 d6 ; 0xf44b9
+ xchg dx, ax ; 92 ; 0xf44bb
+ mov word [bp-03ah], ax ; 89 46 c6 ; 0xf44bc
+ mov word [bp-038h], dx ; 89 56 c8 ; 0xf44bf
+ mov ax, word [bp-030h] ; 8b 46 d0 ; 0xf44c2 eltorito.c:602
+ sub ax, word [bp-02ch] ; 2b 46 d4 ; 0xf44c5
+ inc ax ; 40 ; 0xf44c8
+ xchg ah, al ; 86 c4 ; 0xf44c9
+ mov word [bp-035h], ax ; 89 46 cb ; 0xf44cb
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf44ce eltorito.c:604
+ mov word [es:si+00eh], di ; 26 89 7c 0e ; 0xf44d1
+ mov word [es:si+010h], 00200h ; 26 c7 44 10 00 02 ; 0xf44d5 eltorito.c:605
+ mov ax, word [bp-024h] ; 8b 46 dc ; 0xf44db eltorito.c:607
+ sal ax, 009h ; c1 e0 09 ; 0xf44de
+ mov word [es:si+01eh], ax ; 26 89 44 1e ; 0xf44e1
+ mov dx, di ; 89 fa ; 0xf44e5 eltorito.c:608
+ xor dh, dh ; 30 f6 ; 0xf44e7
+ and dl, 003h ; 80 e2 03 ; 0xf44e9
+ mov bx, strict word 00004h ; bb 04 00 ; 0xf44ec
+ sub bx, dx ; 29 d3 ; 0xf44ef
+ mov dx, bx ; 89 da ; 0xf44f1
+ sub dx, word [bp-024h] ; 2b 56 dc ; 0xf44f3
+ sal dx, 009h ; c1 e2 09 ; 0xf44f6
+ and dh, 007h ; 80 e6 07 ; 0xf44f9
+ mov word [es:si+020h], dx ; 26 89 54 20 ; 0xf44fc
+ movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xf4500 eltorito.c:610
+ imul dx, dx, strict byte 0001ch ; 6b d2 1c ; 0xf4504
+ mov bx, si ; 89 f3 ; 0xf4507
+ add bx, dx ; 01 d3 ; 0xf4509
+ movzx dx, byte [es:bx+022h] ; 26 0f b6 57 22 ; 0xf450b
+ add dx, dx ; 01 d2 ; 0xf4510
+ mov word [bp-026h], dx ; 89 56 da ; 0xf4512
+ push word [bp-016h] ; ff 76 ea ; 0xf4515
+ push word [bp-014h] ; ff 76 ec ; 0xf4518
+ push strict byte 00001h ; 6a 01 ; 0xf451b
+ mov bx, di ; 89 fb ; 0xf451d
+ xor di, di ; 31 ff ; 0xf451f
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf4521
+ sal bx, 1 ; d1 e3 ; 0xf4524
+ rcl di, 1 ; d1 d7 ; 0xf4526
+ loop 04524h ; e2 fa ; 0xf4528
+ push di ; 57 ; 0xf452a
+ push bx ; 53 ; 0xf452b
+ push ax ; 50 ; 0xf452c
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf452d
+ mov cx, ss ; 8c d1 ; 0xf4531
+ lea bx, [bp-03ch] ; 8d 5e c4 ; 0xf4533
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf4536
+ mov di, word [bp-026h] ; 8b 7e da ; 0xf4539
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf453c
+ mov dx, ax ; 89 c2 ; 0xf4540
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4542 eltorito.c:612
+ db 066h, 026h, 0c7h, 044h, 01eh, 000h, 000h, 000h, 000h
+ ; mov dword [es:si+01eh], strict dword 000000000h ; 66 26 c7 44 1e 00 00 00 00; 0xf4545
+ test al, al ; 84 c0 ; 0xf454e eltorito.c:613
+ je near 04347h ; 0f 84 f3 fd ; 0xf4550
+ mov bx, 00db2h ; bb b2 0d ; 0xf4554 eltorito.c:616
+ mov cx, ds ; 8c d9 ; 0xf4557
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4559
+ call 019d3h ; e8 74 d4 ; 0xf455c
+ movzx ax, dl ; 0f b6 c2 ; 0xf455f
+ push ax ; 50 ; 0xf4562
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf4563
+ shr ax, 008h ; c1 e8 08 ; 0xf4566
+ push ax ; 50 ; 0xf4569
+ push 0035eh ; 68 5e 03 ; 0xf456a
+ push 003a0h ; 68 a0 03 ; 0xf456d
+ push strict byte 00004h ; 6a 04 ; 0xf4570
+ call 01a14h ; e8 9f d4 ; 0xf4572
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf4575
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf4578 eltorito.c:617
+ xor ah, ah ; 30 e4 ; 0xf457b
+ or ah, 002h ; 80 cc 02 ; 0xf457d
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf4580
+ mov byte [bp+016h], 000h ; c6 46 16 00 ; 0xf4583 eltorito.c:618
+ jmp near 0481bh ; e9 91 02 ; 0xf4587 eltorito.c:619
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf458a eltorito.c:626
+ mov ax, word [es:bx+014h] ; 26 8b 47 14 ; 0xf458d
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf4591
+ mov dx, word [es:bx+012h] ; 26 8b 57 12 ; 0xf4594 eltorito.c:627
+ dec dx ; 4a ; 0xf4598
+ mov ax, word [es:bx+010h] ; 26 8b 47 10 ; 0xf4599 eltorito.c:628
+ dec ax ; 48 ; 0xf459d
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf459e
+ mov byte [bp+016h], 000h ; c6 46 16 00 ; 0xf45a1 eltorito.c:630
+ mov si, word [bp+010h] ; 8b 76 10 ; 0xf45a5 eltorito.c:631
+ and si, 0ff00h ; 81 e6 00 ff ; 0xf45a8
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf45ac eltorito.c:632
+ xor ah, ah ; 30 e4 ; 0xf45af
+ mov cx, dx ; 89 d1 ; 0xf45b1
+ xor ch, dh ; 30 f5 ; 0xf45b3
+ sal cx, 008h ; c1 e1 08 ; 0xf45b5
+ or ax, cx ; 09 c8 ; 0xf45b8
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf45ba
+ mov ax, dx ; 89 d0 ; 0xf45bd eltorito.c:633
+ shr ax, 002h ; c1 e8 02 ; 0xf45bf
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf45c2
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf45c4
+ and dl, 03fh ; 80 e2 3f ; 0xf45c7
+ or al, dl ; 08 d0 ; 0xf45ca
+ mov dx, word [bp+014h] ; 8b 56 14 ; 0xf45cc
+ mov dl, al ; 88 c2 ; 0xf45cf
+ mov word [bp+014h], dx ; 89 56 14 ; 0xf45d1
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf45d4 eltorito.c:634
+ xor dh, dh ; 30 f6 ; 0xf45d7
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf45d9
+ sal ax, 008h ; c1 e0 08 ; 0xf45dc
+ or dx, ax ; 09 c2 ; 0xf45df
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf45e1
+ mov ax, dx ; 89 d0 ; 0xf45e4 eltorito.c:635
+ xor al, dl ; 30 d0 ; 0xf45e6
+ or AL, strict byte 002h ; 0c 02 ; 0xf45e8
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf45ea
+ mov al, byte [es:bx+001h] ; 26 8a 47 01 ; 0xf45ed eltorito.c:638
+ mov word [bp+010h], si ; 89 76 10 ; 0xf45f1
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf45f4
+ je short 04614h ; 74 1c ; 0xf45f6
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf45f8
+ je short 0460ch ; 74 10 ; 0xf45fa
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf45fc
+ jne short 04619h ; 75 19 ; 0xf45fe
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf4600 eltorito.c:639
+ xor al, al ; 30 c0 ; 0xf4603
+ or AL, strict byte 002h ; 0c 02 ; 0xf4605
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf4607
+ jmp short 04619h ; eb 0d ; 0xf460a
+ or si, strict byte 00004h ; 83 ce 04 ; 0xf460c eltorito.c:640
+ mov word [bp+010h], si ; 89 76 10 ; 0xf460f
+ jmp short 04619h ; eb 05 ; 0xf4612
+ or si, strict byte 00005h ; 83 ce 05 ; 0xf4614 eltorito.c:641
+ jmp short 0460fh ; eb f6 ; 0xf4617
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf4619 eltorito.c:645
+ cmp byte [es:bx+001h], 004h ; 26 80 7f 01 04 ; 0xf461c
+ jnc near 04347h ; 0f 83 22 fd ; 0xf4621
+ mov word [bp+008h], 0efc7h ; c7 46 08 c7 ef ; 0xf4625 eltorito.c:646
+ mov word [bp+006h], 0f000h ; c7 46 06 00 f0 ; 0xf462a eltorito.c:647
+ jmp near 04347h ; e9 15 fd ; 0xf462f eltorito.c:649
+ or ah, 003h ; 80 cc 03 ; 0xf4632 eltorito.c:654
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf4635
+ jmp near 0434bh ; e9 10 fd ; 0xf4638 eltorito.c:655
+ mov word [bp+010h], 0aa55h ; c7 46 10 55 aa ; 0xf463b eltorito.c:659
+ or ah, 030h ; 80 cc 30 ; 0xf4640 eltorito.c:660
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf4643
+ mov word [bp+014h], strict word 00007h ; c7 46 14 07 00 ; 0xf4646 eltorito.c:661
+ jmp near 0434bh ; e9 fd fc ; 0xf464b eltorito.c:662
+ mov di, word [bp+00ah] ; 8b 7e 0a ; 0xf464e eltorito.c:670
+ mov es, [bp+004h] ; 8e 46 04 ; 0xf4651
+ mov word [bp-01ch], di ; 89 7e e4 ; 0xf4654
+ mov [bp-01ah], es ; 8c 46 e6 ; 0xf4657
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf465a eltorito.c:672
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf465e
+ mov ax, word [es:di+006h] ; 26 8b 45 06 ; 0xf4661 eltorito.c:673
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf4665
+ mov ax, word [es:di+004h] ; 26 8b 45 04 ; 0xf4668 eltorito.c:674
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf466c
+ mov ax, word [es:di+00ch] ; 26 8b 45 0c ; 0xf466f eltorito.c:677
+ mov dx, word [es:di+00eh] ; 26 8b 55 0e ; 0xf4673
+ or ax, dx ; 09 d0 ; 0xf4677 eltorito.c:678
+ je short 04693h ; 74 18 ; 0xf4679
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf467b eltorito.c:679
+ shr ax, 008h ; c1 e8 08 ; 0xf467e
+ push ax ; 50 ; 0xf4681
+ push 0035eh ; 68 5e 03 ; 0xf4682
+ push 003c1h ; 68 c1 03 ; 0xf4685
+ push strict byte 00007h ; 6a 07 ; 0xf4688
+ call 01a14h ; e8 87 d3 ; 0xf468a
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf468d
+ jmp near 04810h ; e9 7d 01 ; 0xf4690 eltorito.c:680
+ les di, [bp-01ch] ; c4 7e e4 ; 0xf4693 eltorito.c:684
+ mov ax, word [es:di+008h] ; 26 8b 45 08 ; 0xf4696
+ mov dx, word [es:di+00ah] ; 26 8b 55 0a ; 0xf469a
+ mov cx, word [bp+016h] ; 8b 4e 16 ; 0xf469e eltorito.c:687
+ shr cx, 008h ; c1 e9 08 ; 0xf46a1
+ mov word [bp-018h], cx ; 89 4e e8 ; 0xf46a4
+ cmp cx, strict byte 00044h ; 83 f9 44 ; 0xf46a7
+ je near 04347h ; 0f 84 99 fc ; 0xf46aa
+ cmp cx, strict byte 00047h ; 83 f9 47 ; 0xf46ae
+ jne short 046b6h ; 75 03 ; 0xf46b1
+ jmp near 04347h ; e9 91 fc ; 0xf46b3 eltorito.c:688
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf46b6 eltorito.c:695
+ mov cx, word [es:bx+008h] ; 26 8b 4f 08 ; 0xf46b9
+ mov word [bp-020h], cx ; 89 4e e0 ; 0xf46bd
+ mov bx, word [es:bx+00ah] ; 26 8b 5f 0a ; 0xf46c0
+ mov word [bp-01eh], bx ; 89 5e e2 ; 0xf46c4
+ mov word [bp-030h], ax ; 89 46 d0 ; 0xf46c7 eltorito.c:698
+ mov word [bp-02eh], dx ; 89 56 d2 ; 0xf46ca
+ shr word [bp-02eh], 1 ; d1 6e d2 ; 0xf46cd
+ rcr word [bp-030h], 1 ; d1 5e d0 ; 0xf46d0
+ shr word [bp-02eh], 1 ; d1 6e d2 ; 0xf46d3
+ rcr word [bp-030h], 1 ; d1 5e d0 ; 0xf46d6
+ mov di, word [bp-02eh] ; 8b 7e d2 ; 0xf46d9
+ mov bx, ax ; 89 c3 ; 0xf46dc eltorito.c:699
+ xor bh, ah ; 30 e7 ; 0xf46de
+ and bl, 003h ; 80 e3 03 ; 0xf46e0
+ mov word [bp-024h], bx ; 89 5e dc ; 0xf46e3
+ xor bx, bx ; 31 db ; 0xf46e6 eltorito.c:702
+ add ax, word [bp-010h] ; 03 46 f0 ; 0xf46e8
+ adc dx, bx ; 11 da ; 0xf46eb
+ add ax, strict word 0ffffh ; 05 ff ff ; 0xf46ed
+ adc dx, strict byte 0ffffh ; 83 d2 ff ; 0xf46f0
+ mov word [bp-02ch], ax ; 89 46 d4 ; 0xf46f3
+ mov word [bp-02ah], dx ; 89 56 d6 ; 0xf46f6
+ shr word [bp-02ah], 1 ; d1 6e d6 ; 0xf46f9
+ rcr word [bp-02ch], 1 ; d1 5e d4 ; 0xf46fc
+ shr word [bp-02ah], 1 ; d1 6e d6 ; 0xf46ff
+ rcr word [bp-02ch], 1 ; d1 5e d4 ; 0xf4702
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf4705 eltorito.c:704
+ mov dx, ss ; 8c d2 ; 0xf4708
+ lea ax, [bp-03ch] ; 8d 46 c4 ; 0xf470a
+ call 09fb0h ; e8 a0 58 ; 0xf470d
+ mov word [bp-03ch], strict word 00028h ; c7 46 c4 28 00 ; 0xf4710 eltorito.c:705
+ mov ax, word [bp-020h] ; 8b 46 e0 ; 0xf4715 eltorito.c:706
+ add ax, word [bp-030h] ; 03 46 d0 ; 0xf4718
+ mov dx, word [bp-01eh] ; 8b 56 e2 ; 0xf471b
+ adc dx, di ; 11 fa ; 0xf471e
+ xchg ah, al ; 86 c4 ; 0xf4720
+ xchg dh, dl ; 86 d6 ; 0xf4722
+ xchg dx, ax ; 92 ; 0xf4724
+ mov word [bp-03ah], ax ; 89 46 c6 ; 0xf4725
+ mov word [bp-038h], dx ; 89 56 c8 ; 0xf4728
+ mov ax, word [bp-02ch] ; 8b 46 d4 ; 0xf472b eltorito.c:707
+ sub ax, word [bp-030h] ; 2b 46 d0 ; 0xf472e
+ inc ax ; 40 ; 0xf4731
+ xchg ah, al ; 86 c4 ; 0xf4732
+ mov word [bp-035h], ax ; 89 46 cb ; 0xf4734
+ mov ax, word [bp-024h] ; 8b 46 dc ; 0xf4737 eltorito.c:709
+ sal ax, 009h ; c1 e0 09 ; 0xf473a
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf473d
+ mov word [es:si+01eh], ax ; 26 89 44 1e ; 0xf4740
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf4744 eltorito.c:710
+ xor dh, dh ; 30 f6 ; 0xf4747
+ and dl, 003h ; 80 e2 03 ; 0xf4749
+ mov bx, strict word 00004h ; bb 04 00 ; 0xf474c
+ sub bx, dx ; 29 d3 ; 0xf474f
+ mov dx, bx ; 89 da ; 0xf4751
+ sub dx, word [bp-024h] ; 2b 56 dc ; 0xf4753
+ sal dx, 009h ; c1 e2 09 ; 0xf4756
+ and dh, 007h ; 80 e6 07 ; 0xf4759
+ mov word [es:si+020h], dx ; 26 89 54 20 ; 0xf475c
+ movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xf4760 eltorito.c:712
+ imul dx, dx, strict byte 0001ch ; 6b d2 1c ; 0xf4764
+ mov bx, si ; 89 f3 ; 0xf4767
+ add bx, dx ; 01 d3 ; 0xf4769
+ movzx dx, byte [es:bx+022h] ; 26 0f b6 57 22 ; 0xf476b
+ add dx, dx ; 01 d2 ; 0xf4770
+ mov word [bp-026h], dx ; 89 56 da ; 0xf4772
+ push word [bp-016h] ; ff 76 ea ; 0xf4775
+ push word [bp-014h] ; ff 76 ec ; 0xf4778
+ push strict byte 00001h ; 6a 01 ; 0xf477b
+ mov bx, word [bp-010h] ; 8b 5e f0 ; 0xf477d
+ xor di, di ; 31 ff ; 0xf4780
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf4782
+ sal bx, 1 ; d1 e3 ; 0xf4785
+ rcl di, 1 ; d1 d7 ; 0xf4787
+ loop 04785h ; e2 fa ; 0xf4789
+ push di ; 57 ; 0xf478b
+ push bx ; 53 ; 0xf478c
+ push ax ; 50 ; 0xf478d
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf478e
+ mov cx, ss ; 8c d1 ; 0xf4792
+ lea bx, [bp-03ch] ; 8d 5e c4 ; 0xf4794
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf4797
+ mov di, word [bp-026h] ; 8b 7e da ; 0xf479a
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf479d
+ mov dx, ax ; 89 c2 ; 0xf47a1
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf47a3 eltorito.c:714
+ db 066h, 026h, 0c7h, 044h, 01eh, 000h, 000h, 000h, 000h
+ ; mov dword [es:si+01eh], strict dword 000000000h ; 66 26 c7 44 1e 00 00 00 00; 0xf47a6
+ mov bx, word [es:si+01ah] ; 26 8b 5c 1a ; 0xf47af eltorito.c:717
+ mov di, word [es:si+01ch] ; 26 8b 7c 1c ; 0xf47b3
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf47b7
+ shr di, 1 ; d1 ef ; 0xf47ba
+ rcr bx, 1 ; d1 db ; 0xf47bc
+ loop 047bah ; e2 fa ; 0xf47be
+ les si, [bp-01ch] ; c4 76 e4 ; 0xf47c0 eltorito.c:718
+ mov word [es:si+002h], bx ; 26 89 5c 02 ; 0xf47c3
+ test al, al ; 84 c0 ; 0xf47c7 eltorito.c:720
+ je near 04347h ; 0f 84 7a fb ; 0xf47c9
+ mov bx, 00db2h ; bb b2 0d ; 0xf47cd eltorito.c:721
+ mov cx, ds ; 8c d9 ; 0xf47d0
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf47d2
+ call 019d3h ; e8 fb d1 ; 0xf47d5
+ movzx ax, dl ; 0f b6 c2 ; 0xf47d8
+ push ax ; 50 ; 0xf47db
+ push word [bp-018h] ; ff 76 e8 ; 0xf47dc
+ push 0035eh ; 68 5e 03 ; 0xf47df
+ push 003eah ; 68 ea 03 ; 0xf47e2
+ push strict byte 00004h ; 6a 04 ; 0xf47e5
+ call 01a14h ; e8 2a d2 ; 0xf47e7
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf47ea
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf47ed eltorito.c:722
+ xor ah, ah ; 30 e4 ; 0xf47f0
+ or ah, 00ch ; 80 cc 0c ; 0xf47f2
+ jmp short 04818h ; eb 21 ; 0xf47f5
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf47f7 eltorito.c:730
+ push ax ; 50 ; 0xf47fb
+ mov ax, word [bp+00ah] ; 8b 46 0a ; 0xf47fc
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf47ff
+ mov bx, si ; 89 f3 ; 0xf4802
+ mov cx, word [bp-008h] ; 8b 4e f8 ; 0xf4804
+ call 05a50h ; e8 46 12 ; 0xf4807
+ test ax, ax ; 85 c0 ; 0xf480a
+ je near 04347h ; 0f 84 37 fb ; 0xf480c
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf4810 eltorito.c:731
+ xor ah, ah ; 30 e4 ; 0xf4813
+ or ah, 001h ; 80 cc 01 ; 0xf4815
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf4818
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf481b
+ shr ax, 008h ; c1 e8 08 ; 0xf481e
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4821
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf4824
+ mov es, dx ; 8e c2 ; 0xf4827
+ mov byte [es:bx], al ; 26 88 07 ; 0xf4829
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf482c
+ jmp near 0435bh ; e9 28 fb ; 0xf4830
+ mov bx, 00db2h ; bb b2 0d ; 0xf4833 eltorito.c:747
+ mov cx, ds ; 8c d9 ; 0xf4836
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4838
+ call 019d3h ; e8 95 d1 ; 0xf483b
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf483e
+ shr ax, 008h ; c1 e8 08 ; 0xf4841
+ push ax ; 50 ; 0xf4844
+ push 0035eh ; 68 5e 03 ; 0xf4845
+ push 0040ch ; 68 0c 04 ; 0xf4848
+ push strict byte 00004h ; 6a 04 ; 0xf484b
+ jmp near 0468ah ; e9 3a fe ; 0xf484d
+ ; disGetNextSymbol 0xf4850 LB 0x57f5 -> off=0x59 cb=0000000000000362 uValue=00000000000f32a9 'int13_cdrom'
+ db 050h, 04eh, 049h, 048h, 047h, 046h, 045h, 044h, 043h, 042h, 041h, 018h, 016h, 015h, 014h, 011h
+ db 010h, 00dh, 00ch, 00bh, 00ah, 009h, 008h, 005h, 004h, 003h, 002h, 001h, 000h, 0eeh, 04bh, 050h
+ db 04bh, 051h, 049h, 0eeh, 04bh, 046h, 049h, 0eeh, 04bh, 046h, 049h, 0eeh, 04bh, 050h, 04bh, 0eeh
+ db 04bh, 0eeh, 04bh, 050h, 04bh, 050h, 04bh, 050h, 04bh, 050h, 04bh, 050h, 04bh, 077h, 049h, 050h
+ db 04bh, 0eeh, 04bh, 07dh, 049h, 090h, 049h, 046h, 049h, 090h, 049h, 0c1h, 04ah, 06bh, 04bh, 090h
+ db 049h, 08fh, 04bh, 0c8h, 04bh, 0d0h, 04bh, 0eeh, 04bh
+int13_cdrom: ; 0xf48a9 LB 0x362
+ push bp ; 55 ; 0xf48a9 eltorito.c:772
+ mov bp, sp ; 89 e5 ; 0xf48aa
+ push si ; 56 ; 0xf48ac
+ push di ; 57 ; 0xf48ad
+ sub sp, strict byte 0001eh ; 83 ec 1e ; 0xf48ae
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf48b1 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf48b4
+ mov es, ax ; 8e c0 ; 0xf48b7
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf48b9
+ mov si, 00122h ; be 22 01 ; 0xf48bc eltorito.c:782
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf48bf
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf48c2 eltorito.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf48c5
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf48c9 eltorito.c:789
+ xor ah, ah ; 30 e4 ; 0xf48cc
+ cmp ax, 000e0h ; 3d e0 00 ; 0xf48ce
+ jc short 048d8h ; 72 05 ; 0xf48d1
+ cmp ax, 000f0h ; 3d f0 00 ; 0xf48d3
+ jc short 048f6h ; 72 1e ; 0xf48d6
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf48d8 eltorito.c:790
+ xor ah, ah ; 30 e4 ; 0xf48db
+ push ax ; 50 ; 0xf48dd
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf48de
+ shr ax, 008h ; c1 e8 08 ; 0xf48e1
+ push ax ; 50 ; 0xf48e4
+ push 0043ch ; 68 3c 04 ; 0xf48e5
+ push 00448h ; 68 48 04 ; 0xf48e8
+ push strict byte 00004h ; 6a 04 ; 0xf48eb
+ call 01a14h ; e8 24 d1 ; 0xf48ed
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf48f0
+ jmp near 04ba6h ; e9 b0 02 ; 0xf48f3 eltorito.c:791
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf48f6 eltorito.c:795
+ xor ah, ah ; 30 e4 ; 0xf48f9
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf48fb
+ mov bx, si ; 89 f3 ; 0xf48fe
+ add bx, ax ; 01 c3 ; 0xf4900
+ mov dl, byte [es:bx+00114h] ; 26 8a 97 14 01 ; 0xf4902
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf4907
+ cmp dl, 010h ; 80 fa 10 ; 0xf490a eltorito.c:798
+ jc short 0491fh ; 72 10 ; 0xf490d
+ push ax ; 50 ; 0xf490f eltorito.c:799
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4910
+ shr ax, 008h ; c1 e8 08 ; 0xf4913
+ push ax ; 50 ; 0xf4916
+ push 0043ch ; 68 3c 04 ; 0xf4917
+ push 00473h ; 68 73 04 ; 0xf491a
+ jmp short 048ebh ; eb cc ; 0xf491d
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf491f eltorito.c:803
+ shr ax, 008h ; c1 e8 08 ; 0xf4922
+ cmp ax, strict word 00050h ; 3d 50 00 ; 0xf4925
+ jnbe near 04beeh ; 0f 87 c2 02 ; 0xf4928
+ push CS ; 0e ; 0xf492c
+ pop ES ; 07 ; 0xf492d
+ mov cx, strict word 0001eh ; b9 1e 00 ; 0xf492e
+ mov di, 04850h ; bf 50 48 ; 0xf4931
+ repne scasb ; f2 ae ; 0xf4934
+ sal cx, 1 ; d1 e1 ; 0xf4936
+ mov di, cx ; 89 cf ; 0xf4938
+ mov dx, word [cs:di+0486dh] ; 2e 8b 95 6d 48 ; 0xf493a
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf493f
+ xor ah, ah ; 30 e4 ; 0xf4942
+ jmp dx ; ff e2 ; 0xf4944
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4946 eltorito.c:821
+ xor ah, ah ; 30 e4 ; 0xf4949
+ or ah, 003h ; 80 cc 03 ; 0xf494b
+ jmp near 04baeh ; e9 5d 02 ; 0xf494e
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4951 eltorito.c:38
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf4954
+ mov es, dx ; 8e c2 ; 0xf4957
+ mov dl, byte [es:bx] ; 26 8a 17 ; 0xf4959
+ movzx bx, dl ; 0f b6 da ; 0xf495c eltorito.c:827
+ sal bx, 008h ; c1 e3 08 ; 0xf495f
+ or ax, bx ; 09 d8 ; 0xf4962
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4964
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4967 eltorito.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf496a
+ test dl, dl ; 84 d2 ; 0xf496e eltorito.c:831
+ je near 04b54h ; 0f 84 e0 01 ; 0xf4970
+ jmp near 04bc2h ; e9 4b 02 ; 0xf4974 eltorito.c:832
+ or ah, 002h ; 80 cc 02 ; 0xf4977 eltorito.c:838
+ jmp near 04baeh ; e9 31 02 ; 0xf497a
+ mov word [bp+012h], 0aa55h ; c7 46 12 55 aa ; 0xf497d eltorito.c:843
+ or ah, 030h ; 80 cc 30 ; 0xf4982 eltorito.c:844
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4985
+ mov word [bp+016h], strict word 00007h ; c7 46 16 07 00 ; 0xf4988 eltorito.c:845
+ jmp near 04b54h ; e9 c4 01 ; 0xf498d eltorito.c:846
+ mov bx, word [bp+00ch] ; 8b 5e 0c ; 0xf4990 eltorito.c:854
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf4993
+ mov word [bp-010h], bx ; 89 5e f0 ; 0xf4996
+ mov [bp-00eh], es ; 8c 46 f2 ; 0xf4999
+ mov ax, word [es:bx+002h] ; 26 8b 47 02 ; 0xf499c eltorito.c:856
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf49a0
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf49a3 eltorito.c:857
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf49a7
+ mov ax, word [es:bx+004h] ; 26 8b 47 04 ; 0xf49aa eltorito.c:858
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf49ae
+ mov di, word [es:bx+00ch] ; 26 8b 7f 0c ; 0xf49b1 eltorito.c:861
+ mov ax, word [es:bx+00eh] ; 26 8b 47 0e ; 0xf49b5
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf49b9
+ or di, ax ; 09 c7 ; 0xf49bc eltorito.c:862
+ je short 049d8h ; 74 18 ; 0xf49be
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf49c0 eltorito.c:863
+ shr ax, 008h ; c1 e8 08 ; 0xf49c3
+ push ax ; 50 ; 0xf49c6
+ push 0043ch ; 68 3c 04 ; 0xf49c7
+ push 003c1h ; 68 c1 03 ; 0xf49ca
+ push strict byte 00007h ; 6a 07 ; 0xf49cd
+ call 01a14h ; e8 42 d0 ; 0xf49cf
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf49d2
+ jmp near 04ba6h ; e9 ce 01 ; 0xf49d5 eltorito.c:864
+ les di, [bp-010h] ; c4 7e f0 ; 0xf49d8 eltorito.c:868
+ mov di, word [es:di+008h] ; 26 8b 7d 08 ; 0xf49db
+ mov bx, word [bp-010h] ; 8b 5e f0 ; 0xf49df
+ mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xf49e2
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf49e6
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf49e9 eltorito.c:871
+ shr ax, 008h ; c1 e8 08 ; 0xf49ec
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf49ef
+ cmp ax, strict word 00044h ; 3d 44 00 ; 0xf49f2
+ je near 04b50h ; 0f 84 57 01 ; 0xf49f5
+ cmp ax, strict word 00047h ; 3d 47 00 ; 0xf49f9
+ je near 04b50h ; 0f 84 50 01 ; 0xf49fc
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf4a00 eltorito.c:877
+ xor bx, bx ; 31 db ; 0xf4a03
+ mov dx, ss ; 8c d2 ; 0xf4a05
+ lea ax, [bp-022h] ; 8d 46 de ; 0xf4a07
+ call 09fb0h ; e8 a3 55 ; 0xf4a0a
+ mov word [bp-022h], strict word 00028h ; c7 46 de 28 00 ; 0xf4a0d eltorito.c:878
+ mov ax, di ; 89 f8 ; 0xf4a12 eltorito.c:879
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf4a14
+ xchg ah, al ; 86 c4 ; 0xf4a17
+ xchg dh, dl ; 86 d6 ; 0xf4a19
+ xchg dx, ax ; 92 ; 0xf4a1b
+ mov word [bp-020h], ax ; 89 46 e0 ; 0xf4a1c
+ mov word [bp-01eh], dx ; 89 56 e2 ; 0xf4a1f
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf4a22 eltorito.c:880
+ xchg ah, al ; 86 c4 ; 0xf4a25
+ mov word [bp-01bh], ax ; 89 46 e5 ; 0xf4a27
+ les ax, [bp-00ah] ; c4 46 f6 ; 0xf4a2a eltorito.c:882
+ mov word [es:si+00eh], ax ; 26 89 44 0e ; 0xf4a2d
+ mov word [es:si+010h], 00800h ; 26 c7 44 10 00 08 ; 0xf4a31 eltorito.c:883
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf4a37 eltorito.c:885
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf4a3b
+ mov bx, si ; 89 f3 ; 0xf4a3e
+ add bx, ax ; 01 c3 ; 0xf4a40
+ movzx di, byte [es:bx+022h] ; 26 0f b6 7f 22 ; 0xf4a42
+ add di, di ; 01 ff ; 0xf4a47
+ push word [bp-016h] ; ff 76 ea ; 0xf4a49
+ push word [bp-014h] ; ff 76 ec ; 0xf4a4c
+ push strict byte 00001h ; 6a 01 ; 0xf4a4f
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf4a51
+ xor bx, bx ; 31 db ; 0xf4a54
+ mov cx, strict word 0000bh ; b9 0b 00 ; 0xf4a56
+ sal ax, 1 ; d1 e0 ; 0xf4a59
+ rcl bx, 1 ; d1 d3 ; 0xf4a5b
+ loop 04a59h ; e2 fa ; 0xf4a5d
+ push bx ; 53 ; 0xf4a5f
+ push ax ; 50 ; 0xf4a60
+ push strict byte 00000h ; 6a 00 ; 0xf4a61
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf4a63
+ mov cx, ss ; 8c d1 ; 0xf4a67
+ lea bx, [bp-022h] ; 8d 5e de ; 0xf4a69
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf4a6c
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf4a6f
+ mov dx, ax ; 89 c2 ; 0xf4a73
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4a75 eltorito.c:887
+ mov ax, word [es:si+01ah] ; 26 8b 44 1a ; 0xf4a78
+ mov bx, word [es:si+01ch] ; 26 8b 5c 1c ; 0xf4a7c
+ mov cx, strict word 0000bh ; b9 0b 00 ; 0xf4a80
+ shr bx, 1 ; d1 eb ; 0xf4a83
+ rcr ax, 1 ; d1 d8 ; 0xf4a85
+ loop 04a83h ; e2 fa ; 0xf4a87
+ les bx, [bp-010h] ; c4 5e f0 ; 0xf4a89 eltorito.c:888
+ mov word [es:bx+002h], ax ; 26 89 47 02 ; 0xf4a8c
+ test dl, dl ; 84 d2 ; 0xf4a90 eltorito.c:890
+ je near 04b50h ; 0f 84 ba 00 ; 0xf4a92
+ mov bx, 00db2h ; bb b2 0d ; 0xf4a96 eltorito.c:891
+ mov cx, ds ; 8c d9 ; 0xf4a99
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4a9b
+ call 019d3h ; e8 32 cf ; 0xf4a9e
+ movzx ax, dl ; 0f b6 c2 ; 0xf4aa1
+ push ax ; 50 ; 0xf4aa4
+ push word [bp-012h] ; ff 76 ee ; 0xf4aa5
+ push 0043ch ; 68 3c 04 ; 0xf4aa8
+ push 003eah ; 68 ea 03 ; 0xf4aab
+ push strict byte 00004h ; 6a 04 ; 0xf4aae
+ call 01a14h ; e8 61 cf ; 0xf4ab0
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf4ab3
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4ab6 eltorito.c:892
+ xor ah, ah ; 30 e4 ; 0xf4ab9
+ or ah, 00ch ; 80 cc 0c ; 0xf4abb
+ jmp near 04baeh ; e9 ed 00 ; 0xf4abe
+ cmp ax, strict word 00002h ; 3d 02 00 ; 0xf4ac1 eltorito.c:900
+ jnbe near 04ba6h ; 0f 87 de 00 ; 0xf4ac4
+ movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xf4ac8 eltorito.c:903
+ imul dx, dx, strict byte 0001ch ; 6b d2 1c ; 0xf4acc
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4acf
+ mov bx, si ; 89 f3 ; 0xf4ad2
+ add bx, dx ; 01 d3 ; 0xf4ad4
+ mov bl, byte [es:bx+025h] ; 26 8a 5f 25 ; 0xf4ad6
+ cmp ax, strict word 00002h ; 3d 02 00 ; 0xf4ada eltorito.c:905
+ je short 04b3eh ; 74 5f ; 0xf4add
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf4adf
+ je short 04b1ch ; 74 38 ; 0xf4ae2
+ test ax, ax ; 85 c0 ; 0xf4ae4
+ jne near 04b50h ; 0f 85 66 00 ; 0xf4ae6
+ cmp bl, 0ffh ; 80 fb ff ; 0xf4aea eltorito.c:907
+ jne short 04b01h ; 75 12 ; 0xf4aed
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4aef eltorito.c:908
+ xor ah, ah ; 30 e4 ; 0xf4af2
+ or ah, 0b4h ; 80 cc b4 ; 0xf4af4
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4af7
+ xor al, al ; 30 c0 ; 0xf4afa eltorito.c:909
+ or AL, strict byte 001h ; 0c 01 ; 0xf4afc
+ jmp near 04baeh ; e9 ad 00 ; 0xf4afe
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf4b01 eltorito.c:911
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf4b05
+ db 0feh, 0c3h
+ ; inc bl ; fe c3 ; 0xf4b08 eltorito.c:912
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4b0a
+ add si, ax ; 01 c6 ; 0xf4b0d
+ mov byte [es:si+025h], bl ; 26 88 5c 25 ; 0xf4b0f
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4b13 eltorito.c:913
+ xor al, al ; 30 c0 ; 0xf4b16
+ or AL, strict byte 001h ; 0c 01 ; 0xf4b18
+ jmp short 04b4dh ; eb 31 ; 0xf4b1a
+ test bl, bl ; 84 db ; 0xf4b1c eltorito.c:916
+ jne short 04b2ch ; 75 0c ; 0xf4b1e
+ or ah, 0b0h ; 80 cc b0 ; 0xf4b20 eltorito.c:917
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4b23
+ mov byte [bp+018h], bl ; 88 5e 18 ; 0xf4b26 eltorito.c:918
+ jmp near 04bb1h ; e9 85 00 ; 0xf4b29 eltorito.c:919
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf4b2c eltorito.c:920
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf4b30
+ db 0feh, 0cbh
+ ; dec bl ; fe cb ; 0xf4b33 eltorito.c:921
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4b35
+ add si, ax ; 01 c6 ; 0xf4b38
+ mov byte [es:si+025h], bl ; 26 88 5c 25 ; 0xf4b3a
+ test bl, bl ; 84 db ; 0xf4b3e eltorito.c:922
+ db 00fh, 095h, 0c0h
+ ; setne al ; 0f 95 c0 ; 0xf4b40
+ movzx dx, al ; 0f b6 d0 ; 0xf4b43
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4b46
+ xor al, al ; 30 c0 ; 0xf4b49
+ or ax, dx ; 09 d0 ; 0xf4b4b
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4b4d
+ mov byte [bp+019h], 000h ; c6 46 19 00 ; 0xf4b50 eltorito.c:928
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4b54
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4b57
+ mov es, ax ; 8e c0 ; 0xf4b5a
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf4b5c
+ and byte [bp+01eh], 0feh ; 80 66 1e fe ; 0xf4b60
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf4b64
+ pop di ; 5f ; 0xf4b67
+ pop si ; 5e ; 0xf4b68
+ pop bp ; 5d ; 0xf4b69
+ retn ; c3 ; 0xf4b6a
+ movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xf4b6b eltorito.c:932
+ imul dx, dx, strict byte 0001ch ; 6b d2 1c ; 0xf4b6f
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4b72
+ mov bx, si ; 89 f3 ; 0xf4b75
+ add bx, dx ; 01 d3 ; 0xf4b77
+ mov bl, byte [es:bx+025h] ; 26 8a 5f 25 ; 0xf4b79
+ test bl, bl ; 84 db ; 0xf4b7d eltorito.c:934
+ je short 04b86h ; 74 05 ; 0xf4b7f
+ or ah, 0b1h ; 80 cc b1 ; 0xf4b81 eltorito.c:935
+ jmp short 04baeh ; eb 28 ; 0xf4b84
+ je short 04b50h ; 74 c8 ; 0xf4b86 eltorito.c:957
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4b88 eltorito.c:958
+ xor ah, ah ; 30 e4 ; 0xf4b8b
+ jmp short 04b81h ; eb f2 ; 0xf4b8d
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf4b8f eltorito.c:966
+ push ax ; 50 ; 0xf4b93
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf4b94
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf4b97
+ mov bx, si ; 89 f3 ; 0xf4b9a
+ mov cx, word [bp-008h] ; 8b 4e f8 ; 0xf4b9c
+ call 05a50h ; e8 ae 0e ; 0xf4b9f
+ test ax, ax ; 85 c0 ; 0xf4ba2
+ je short 04b50h ; 74 aa ; 0xf4ba4
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4ba6 eltorito.c:967
+ xor ah, ah ; 30 e4 ; 0xf4ba9
+ or ah, 001h ; 80 cc 01 ; 0xf4bab
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4bae
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4bb1
+ shr ax, 008h ; c1 e8 08 ; 0xf4bb4
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4bb7
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf4bba
+ mov es, dx ; 8e c2 ; 0xf4bbd
+ mov byte [es:bx], al ; 26 88 07 ; 0xf4bbf
+ or byte [bp+01eh], 001h ; 80 4e 1e 01 ; 0xf4bc2
+ jmp short 04b64h ; eb 9c ; 0xf4bc6
+ or ah, 006h ; 80 cc 06 ; 0xf4bc8 eltorito.c:974
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4bcb
+ jmp short 04bc2h ; eb f2 ; 0xf4bce eltorito.c:975
+ cmp ax, strict word 00006h ; 3d 06 00 ; 0xf4bd0 eltorito.c:980
+ je near 04b50h ; 0f 84 79 ff ; 0xf4bd3
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf4bd7
+ jc short 04ba6h ; 72 ca ; 0xf4bda
+ jbe near 04b50h ; 0f 86 70 ff ; 0xf4bdc
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf4be0
+ jc short 04ba6h ; 72 c1 ; 0xf4be3
+ cmp ax, strict word 00004h ; 3d 04 00 ; 0xf4be5
+ jbe near 04b50h ; 0f 86 64 ff ; 0xf4be8
+ jmp short 04ba6h ; eb b8 ; 0xf4bec eltorito.c:988
+ mov bx, 00db2h ; bb b2 0d ; 0xf4bee eltorito.c:1001
+ mov cx, ds ; 8c d9 ; 0xf4bf1
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4bf3
+ call 019d3h ; e8 da cd ; 0xf4bf6
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4bf9
+ shr ax, 008h ; c1 e8 08 ; 0xf4bfc
+ push ax ; 50 ; 0xf4bff
+ push 0043ch ; 68 3c 04 ; 0xf4c00
+ push 00345h ; 68 45 03 ; 0xf4c03
+ push strict byte 00004h ; 6a 04 ; 0xf4c06
+ jmp near 049cfh ; e9 c4 fd ; 0xf4c08
+ ; disGetNextSymbol 0xf4c0b LB 0x543a -> off=0x0 cb=000000000000004b uValue=00000000000f360b 'print_boot_device'
+print_boot_device: ; 0xf4c0b LB 0x4b
+ push bp ; 55 ; 0xf4c0b boot.c:109
+ mov bp, sp ; 89 e5 ; 0xf4c0c
+ push cx ; 51 ; 0xf4c0e
+ test al, al ; 84 c0 ; 0xf4c0f boot.c:117
+ je short 04c18h ; 74 05 ; 0xf4c11
+ mov dx, strict word 00002h ; ba 02 00 ; 0xf4c13
+ jmp short 04c32h ; eb 1a ; 0xf4c16 boot.c:118
+ test dl, dl ; 84 d2 ; 0xf4c18
+ je short 04c21h ; 74 05 ; 0xf4c1a
+ mov dx, strict word 00003h ; ba 03 00 ; 0xf4c1c
+ jmp short 04c32h ; eb 11 ; 0xf4c1f boot.c:119
+ test bl, 080h ; f6 c3 80 ; 0xf4c21
+ jne short 04c2ah ; 75 04 ; 0xf4c24
+ xor dh, dh ; 30 f6 ; 0xf4c26
+ jmp short 04c32h ; eb 08 ; 0xf4c28 boot.c:120
+ test bl, 080h ; f6 c3 80 ; 0xf4c2a
+ je short 04c50h ; 74 21 ; 0xf4c2d
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf4c2f
+ mov bx, 00db2h ; bb b2 0d ; 0xf4c32 boot.c:123
+ mov cx, ds ; 8c d9 ; 0xf4c35
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4c37
+ call 019d3h ; e8 96 cd ; 0xf4c3a
+ imul dx, dx, strict byte 0000ah ; 6b d2 0a ; 0xf4c3d
+ add dx, 00dd8h ; 81 c2 d8 0d ; 0xf4c40
+ push dx ; 52 ; 0xf4c44
+ push 004a6h ; 68 a6 04 ; 0xf4c45
+ push strict byte 00004h ; 6a 04 ; 0xf4c48
+ call 01a14h ; e8 c7 cd ; 0xf4c4a
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf4c4d
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf4c50 boot.c:124
+ pop cx ; 59 ; 0xf4c53
+ pop bp ; 5d ; 0xf4c54
+ retn ; c3 ; 0xf4c55
+ ; disGetNextSymbol 0xf4c56 LB 0x53ef -> off=0x0 cb=0000000000000093 uValue=00000000000f3656 'print_boot_failure'
+print_boot_failure: ; 0xf4c56 LB 0x93
+ push bp ; 55 ; 0xf4c56 boot.c:131
+ mov bp, sp ; 89 e5 ; 0xf4c57
+ push si ; 56 ; 0xf4c59
+ mov dh, cl ; 88 ce ; 0xf4c5a
+ mov ah, bl ; 88 dc ; 0xf4c5c boot.c:134
+ and ah, 07fh ; 80 e4 7f ; 0xf4c5e
+ movzx si, ah ; 0f b6 f4 ; 0xf4c61
+ test al, al ; 84 c0 ; 0xf4c64 boot.c:142
+ je short 04c83h ; 74 1b ; 0xf4c66
+ mov bx, 00db2h ; bb b2 0d ; 0xf4c68 boot.c:143
+ mov cx, ds ; 8c d9 ; 0xf4c6b
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4c6d
+ call 019d3h ; e8 60 cd ; 0xf4c70
+ push 00dech ; 68 ec 0d ; 0xf4c73
+ push 004bah ; 68 ba 04 ; 0xf4c76
+ push strict byte 00004h ; 6a 04 ; 0xf4c79
+ call 01a14h ; e8 96 cd ; 0xf4c7b
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf4c7e
+ jmp short 04cc7h ; eb 44 ; 0xf4c81 boot.c:144
+ test dl, dl ; 84 d2 ; 0xf4c83
+ je short 04c97h ; 74 10 ; 0xf4c85
+ mov bx, 00db2h ; bb b2 0d ; 0xf4c87 boot.c:145
+ mov cx, ds ; 8c d9 ; 0xf4c8a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4c8c
+ call 019d3h ; e8 41 cd ; 0xf4c8f
+ push 00df6h ; 68 f6 0d ; 0xf4c92
+ jmp short 04c76h ; eb df ; 0xf4c95
+ test bl, 080h ; f6 c3 80 ; 0xf4c97 boot.c:146
+ je short 04cadh ; 74 11 ; 0xf4c9a
+ mov bx, 00db2h ; bb b2 0d ; 0xf4c9c boot.c:147
+ mov cx, ds ; 8c d9 ; 0xf4c9f
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4ca1
+ call 019d3h ; e8 2c cd ; 0xf4ca4
+ push si ; 56 ; 0xf4ca7
+ push 00de2h ; 68 e2 0d ; 0xf4ca8
+ jmp short 04cbch ; eb 0f ; 0xf4cab boot.c:148
+ mov bx, 00db2h ; bb b2 0d ; 0xf4cad boot.c:149
+ mov cx, ds ; 8c d9 ; 0xf4cb0
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4cb2
+ call 019d3h ; e8 1b cd ; 0xf4cb5
+ push si ; 56 ; 0xf4cb8
+ push 00dd8h ; 68 d8 0d ; 0xf4cb9
+ push 004cfh ; 68 cf 04 ; 0xf4cbc
+ push strict byte 00004h ; 6a 04 ; 0xf4cbf
+ call 01a14h ; e8 50 cd ; 0xf4cc1
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf4cc4
+ cmp byte [bp+004h], 001h ; 80 7e 04 01 ; 0xf4cc7 boot.c:151
+ jne short 04ce1h ; 75 14 ; 0xf4ccb
+ test dh, dh ; 84 f6 ; 0xf4ccd boot.c:152
+ jne short 04cd6h ; 75 05 ; 0xf4ccf
+ push 004e7h ; 68 e7 04 ; 0xf4cd1 boot.c:153
+ jmp short 04cd9h ; eb 03 ; 0xf4cd4 boot.c:154
+ push 00511h ; 68 11 05 ; 0xf4cd6 boot.c:155
+ push strict byte 00007h ; 6a 07 ; 0xf4cd9
+ call 01a14h ; e8 36 cd ; 0xf4cdb
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf4cde
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf4ce1 boot.c:157
+ pop si ; 5e ; 0xf4ce4
+ pop bp ; 5d ; 0xf4ce5
+ retn 00002h ; c2 02 00 ; 0xf4ce6
+ ; disGetNextSymbol 0xf4ce9 LB 0x535c -> off=0x0 cb=0000000000000027 uValue=00000000000f36e9 'print_cdromboot_failure'
+print_cdromboot_failure: ; 0xf4ce9 LB 0x27
+ push bp ; 55 ; 0xf4ce9 boot.c:163
+ mov bp, sp ; 89 e5 ; 0xf4cea
+ push bx ; 53 ; 0xf4cec
+ push cx ; 51 ; 0xf4ced
+ push dx ; 52 ; 0xf4cee
+ mov dx, ax ; 89 c2 ; 0xf4cef
+ mov bx, 00db2h ; bb b2 0d ; 0xf4cf1 boot.c:165
+ mov cx, ds ; 8c d9 ; 0xf4cf4
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4cf6
+ call 019d3h ; e8 d7 cc ; 0xf4cf9
+ push dx ; 52 ; 0xf4cfc
+ push 00546h ; 68 46 05 ; 0xf4cfd
+ push strict byte 00004h ; 6a 04 ; 0xf4d00
+ call 01a14h ; e8 0f cd ; 0xf4d02
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf4d05
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf4d08 boot.c:167
+ pop dx ; 5a ; 0xf4d0b
+ pop cx ; 59 ; 0xf4d0c
+ pop bx ; 5b ; 0xf4d0d
+ pop bp ; 5d ; 0xf4d0e
+ retn ; c3 ; 0xf4d0f
+ ; disGetNextSymbol 0xf4d10 LB 0x5335 -> off=0x0 cb=0000000000000245 uValue=00000000000f3710 'int19_function'
+int19_function: ; 0xf4d10 LB 0x245
+ push bp ; 55 ; 0xf4d10 boot.c:170
+ mov bp, sp ; 89 e5 ; 0xf4d11
+ push si ; 56 ; 0xf4d13
+ push di ; 57 ; 0xf4d14
+ sub sp, strict byte 0000eh ; 83 ec 0e ; 0xf4d15
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf4d18 boot.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4d1b
+ mov es, ax ; 8e c0 ; 0xf4d1e
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf4d20
+ mov word [bp-00eh], bx ; 89 5e f2 ; 0xf4d23 boot.c:49
+ mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xf4d26 boot.c:181
+ mov ax, strict word 0003dh ; b8 3d 00 ; 0xf4d2a boot.c:204
+ call 01756h ; e8 26 ca ; 0xf4d2d
+ movzx dx, al ; 0f b6 d0 ; 0xf4d30
+ mov ax, strict word 00038h ; b8 38 00 ; 0xf4d33 boot.c:205
+ call 01756h ; e8 1d ca ; 0xf4d36
+ and AL, strict byte 0f0h ; 24 f0 ; 0xf4d39
+ xor ah, ah ; 30 e4 ; 0xf4d3b
+ sal ax, 004h ; c1 e0 04 ; 0xf4d3d
+ or dx, ax ; 09 c2 ; 0xf4d40
+ mov ax, strict word 0003ch ; b8 3c 00 ; 0xf4d42 boot.c:206
+ call 01756h ; e8 0e ca ; 0xf4d45
+ and AL, strict byte 00fh ; 24 0f ; 0xf4d48
+ xor ah, ah ; 30 e4 ; 0xf4d4a
+ sal ax, 00ch ; c1 e0 0c ; 0xf4d4c
+ or dx, ax ; 09 c2 ; 0xf4d4f
+ mov di, 0037dh ; bf 7d 03 ; 0xf4d51 boot.c:38
+ mov es, bx ; 8e c3 ; 0xf4d54
+ mov al, byte [es:di] ; 26 8a 05 ; 0xf4d56
+ test al, al ; 84 c0 ; 0xf4d59 boot.c:39
+ je short 04d60h ; 74 03 ; 0xf4d5b
+ movzx dx, al ; 0f b6 d0 ; 0xf4d5d boot.c:39
+ cmp byte [bp+004h], 001h ; 80 7e 04 01 ; 0xf4d60 boot.c:210
+ jne short 04d76h ; 75 10 ; 0xf4d64
+ mov ax, strict word 0003ch ; b8 3c 00 ; 0xf4d66 boot.c:211
+ call 01756h ; e8 ea c9 ; 0xf4d69
+ and AL, strict byte 0f0h ; 24 f0 ; 0xf4d6c
+ xor ah, ah ; 30 e4 ; 0xf4d6e
+ sar ax, 004h ; c1 f8 04 ; 0xf4d70
+ call 07cech ; e8 76 2f ; 0xf4d73
+ cmp byte [bp+004h], 002h ; 80 7e 04 02 ; 0xf4d76 boot.c:213
+ jne short 04d7fh ; 75 03 ; 0xf4d7a
+ shr dx, 004h ; c1 ea 04 ; 0xf4d7c
+ cmp byte [bp+004h], 003h ; 80 7e 04 03 ; 0xf4d7f boot.c:214
+ jne short 04d88h ; 75 03 ; 0xf4d83
+ shr dx, 008h ; c1 ea 08 ; 0xf4d85
+ cmp byte [bp+004h], 004h ; 80 7e 04 04 ; 0xf4d88 boot.c:215
+ jne short 04d91h ; 75 03 ; 0xf4d8c
+ shr dx, 00ch ; c1 ea 0c ; 0xf4d8e
+ cmp dx, strict byte 00010h ; 83 fa 10 ; 0xf4d91 boot.c:216
+ jnc short 04d9ah ; 73 04 ; 0xf4d94
+ mov byte [bp-006h], 001h ; c6 46 fa 01 ; 0xf4d96
+ xor al, al ; 30 c0 ; 0xf4d9a boot.c:217
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf4d9c
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf4d9f
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf4da2 boot.c:218
+ mov bx, 00db2h ; bb b2 0d ; 0xf4da5 boot.c:219
+ mov cx, ds ; 8c d9 ; 0xf4da8
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4daa
+ call 019d3h ; e8 23 cc ; 0xf4dad
+ push dx ; 52 ; 0xf4db0
+ movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xf4db1
+ push ax ; 50 ; 0xf4db5
+ push 00566h ; 68 66 05 ; 0xf4db6
+ push strict byte 00004h ; 6a 04 ; 0xf4db9
+ call 01a14h ; e8 56 cc ; 0xf4dbb
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf4dbe
+ and dx, strict byte 0000fh ; 83 e2 0f ; 0xf4dc1 boot.c:221
+ cmp dx, strict byte 00002h ; 83 fa 02 ; 0xf4dc4
+ jc short 04dd7h ; 72 0e ; 0xf4dc7
+ jbe short 04de6h ; 76 1b ; 0xf4dc9
+ cmp dx, strict byte 00004h ; 83 fa 04 ; 0xf4dcb
+ je short 04e03h ; 74 33 ; 0xf4dce
+ cmp dx, strict byte 00003h ; 83 fa 03 ; 0xf4dd0
+ je short 04df9h ; 74 24 ; 0xf4dd3
+ jmp short 04e30h ; eb 59 ; 0xf4dd5
+ cmp dx, strict byte 00001h ; 83 fa 01 ; 0xf4dd7
+ jne short 04e30h ; 75 54 ; 0xf4dda
+ xor al, al ; 30 c0 ; 0xf4ddc boot.c:223
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf4dde
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf4de1 boot.c:224
+ jmp short 04e46h ; eb 60 ; 0xf4de4 boot.c:225
+ mov bx, 0037ch ; bb 7c 03 ; 0xf4de6 boot.c:38
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf4de9
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4dec
+ add AL, strict byte 080h ; 04 80 ; 0xf4def boot.c:231
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf4df1
+ mov byte [bp-00ah], dh ; 88 76 f6 ; 0xf4df4 boot.c:232
+ jmp short 04e46h ; eb 4d ; 0xf4df7 boot.c:233
+ mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xf4df9 boot.c:236
+ mov byte [bp-00ah], 001h ; c6 46 f6 01 ; 0xf4dfd boot.c:237
+ jmp short 04e0dh ; eb 0a ; 0xf4e01 boot.c:238
+ mov byte [bp-00ch], 001h ; c6 46 f4 01 ; 0xf4e03 boot.c:239
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf4e07 boot.c:255
+ je short 04e46h ; 74 39 ; 0xf4e0b
+ call 03e74h ; e8 64 f0 ; 0xf4e0d boot.c:256
+ mov dx, ax ; 89 c2 ; 0xf4e10
+ test AL, strict byte 0ffh ; a8 ff ; 0xf4e12 boot.c:259
+ je short 04e37h ; 74 21 ; 0xf4e14
+ call 04ce9h ; e8 d0 fe ; 0xf4e16 boot.c:260
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf4e19 boot.c:261
+ push ax ; 50 ; 0xf4e1d
+ movzx bx, byte [bp-008h] ; 0f b6 5e f8 ; 0xf4e1e
+ movzx dx, byte [bp-00ch] ; 0f b6 56 f4 ; 0xf4e22
+ movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xf4e26
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf4e2a
+ call 04c56h ; e8 26 fe ; 0xf4e2d
+ xor ax, ax ; 31 c0 ; 0xf4e30
+ xor dx, dx ; 31 d2 ; 0xf4e32
+ jmp near 04f4eh ; e9 17 01 ; 0xf4e34
+ mov bx, 00372h ; bb 72 03 ; 0xf4e37 boot.c:48
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf4e3a
+ mov si, word [es:bx] ; 26 8b 37 ; 0xf4e3d
+ shr dx, 008h ; c1 ea 08 ; 0xf4e40 boot.c:266
+ mov byte [bp-008h], dl ; 88 56 f8 ; 0xf4e43
+ cmp byte [bp-00ch], 001h ; 80 7e f4 01 ; 0xf4e46 boot.c:272
+ jne near 04ec2h ; 0f 85 74 00 ; 0xf4e4a
+ xor si, si ; 31 f6 ; 0xf4e4e boot.c:275
+ mov ax, 0e200h ; b8 00 e2 ; 0xf4e50
+ mov es, ax ; 8e c0 ; 0xf4e53
+ cmp word [es:si], 0aa55h ; 26 81 3c 55 aa ; 0xf4e55 boot.c:276
+ jne short 04e19h ; 75 bd ; 0xf4e5a
+ mov di, ax ; 89 c7 ; 0xf4e5c boot.c:282
+ mov si, word [es:si+01ah] ; 26 8b 74 1a ; 0xf4e5e
+ cmp word [es:si+002h], 0506eh ; 26 81 7c 02 6e 50 ; 0xf4e62 boot.c:283
+ jne short 04e19h ; 75 af ; 0xf4e68
+ cmp word [es:si], 05024h ; 26 81 3c 24 50 ; 0xf4e6a
+ jne short 04e19h ; 75 a8 ; 0xf4e6f
+ mov bx, word [es:si+00eh] ; 26 8b 5c 0e ; 0xf4e71 boot.c:285
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf4e75
+ mov ax, word [es:bx+002h] ; 26 8b 47 02 ; 0xf4e78
+ cmp ax, 06568h ; 3d 68 65 ; 0xf4e7c boot.c:286
+ jne short 04ea0h ; 75 1f ; 0xf4e7f
+ cmp dx, 07445h ; 81 fa 45 74 ; 0xf4e81
+ jne short 04ea0h ; 75 19 ; 0xf4e85
+ movzx bx, byte [bp-008h] ; 0f b6 5e f8 ; 0xf4e87 boot.c:288
+ movzx dx, byte [bp-00ch] ; 0f b6 56 f4 ; 0xf4e8b
+ movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xf4e8f
+ call 04c0bh ; e8 75 fd ; 0xf4e93
+ mov word [bp-012h], strict word 00006h ; c7 46 ee 06 00 ; 0xf4e96 boot.c:289
+ mov word [bp-010h], di ; 89 7e f0 ; 0xf4e9b
+ jmp short 04ebch ; eb 1c ; 0xf4e9e boot.c:292
+ movzx bx, byte [bp-008h] ; 0f b6 5e f8 ; 0xf4ea0 boot.c:295
+ movzx dx, byte [bp-00ch] ; 0f b6 56 f4 ; 0xf4ea4
+ movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xf4ea8
+ call 04c0bh ; e8 5c fd ; 0xf4eac
+ sti ; fb ; 0xf4eaf boot.c:296
+ mov word [bp-010h], di ; 89 7e f0 ; 0xf4eb0 boot.c:297
+ mov es, di ; 8e c7 ; 0xf4eb3
+ mov ax, word [es:si+01ah] ; 26 8b 44 1a ; 0xf4eb5
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf4eb9
+ call far [bp-012h] ; ff 5e ee ; 0xf4ebc boot.c:298
+ jmp near 04e19h ; e9 57 ff ; 0xf4ebf boot.c:301
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf4ec2 boot.c:309
+ jne short 04eeeh ; 75 26 ; 0xf4ec6
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf4ec8
+ jne short 04eeeh ; 75 20 ; 0xf4ecc
+ mov si, 007c0h ; be c0 07 ; 0xf4ece boot.c:310
+ mov es, si ; 8e c6 ; 0xf4ed1 boot.c:312
+ mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xf4ed3
+ mov ax, 00201h ; b8 01 02 ; 0xf4ed6
+ mov DH, strict byte 000h ; b6 00 ; 0xf4ed9
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf4edb
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xf4ede
+ int 013h ; cd 13 ; 0xf4ee0
+ mov ax, strict word 00000h ; b8 00 00 ; 0xf4ee2
+ sbb ax, strict byte 00000h ; 83 d8 00 ; 0xf4ee5
+ test ax, ax ; 85 c0 ; 0xf4ee8 boot.c:313
+ jne near 04e19h ; 0f 85 2b ff ; 0xf4eea
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf4eee boot.c:328
+ db 00fh, 094h, 0c0h
+ ; sete al ; 0f 94 c0 ; 0xf4ef2
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf4ef5 boot.c:333
+ je short 04efdh ; 74 02 ; 0xf4ef9
+ mov AL, strict byte 001h ; b0 01 ; 0xf4efb boot.c:334
+ xor bx, bx ; 31 db ; 0xf4efd boot.c:48
+ mov es, si ; 8e c6 ; 0xf4eff
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf4f01
+ mov bx, strict word 00004h ; bb 04 00 ; 0xf4f04 boot.c:48
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf4f07
+ cmp dx, bx ; 39 da ; 0xf4f0a boot.c:49
+ je short 04f1dh ; 74 0f ; 0xf4f0c
+ test al, al ; 84 c0 ; 0xf4f0e
+ jne short 04f33h ; 75 21 ; 0xf4f10
+ mov bx, 001feh ; bb fe 01 ; 0xf4f12 boot.c:48
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf4f15
+ cmp ax, 0aa55h ; 3d 55 aa ; 0xf4f18 boot.c:49
+ je short 04f33h ; 74 16 ; 0xf4f1b
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf4f1d boot.c:340
+ push ax ; 50 ; 0xf4f21
+ movzx bx, byte [bp-008h] ; 0f b6 5e f8 ; 0xf4f22
+ movzx dx, byte [bp-00ch] ; 0f b6 56 f4 ; 0xf4f26
+ movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xf4f2a
+ xor cx, cx ; 31 c9 ; 0xf4f2e
+ jmp near 04e2dh ; e9 fa fe ; 0xf4f30
+ movzx bx, byte [bp-008h] ; 0f b6 5e f8 ; 0xf4f33 boot.c:346
+ movzx dx, byte [bp-00ch] ; 0f b6 56 f4 ; 0xf4f37
+ movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xf4f3b
+ call 04c0bh ; e8 c9 fc ; 0xf4f3f
+ movzx bx, byte [bp-008h] ; 0f b6 5e f8 ; 0xf4f42 boot.c:352
+ xor dx, dx ; 31 d2 ; 0xf4f46
+ xor ax, ax ; 31 c0 ; 0xf4f48
+ add ax, si ; 01 f0 ; 0xf4f4a
+ adc dx, bx ; 11 da ; 0xf4f4c
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf4f4e boot.c:353
+ pop di ; 5f ; 0xf4f51
+ pop si ; 5e ; 0xf4f52
+ pop bp ; 5d ; 0xf4f53
+ retn ; c3 ; 0xf4f54
+ ; disGetNextSymbol 0xf4f55 LB 0x50f0 -> off=0x0 cb=0000000000000013 uValue=00000000000f3955 'keyboard_panic'
+keyboard_panic: ; 0xf4f55 LB 0x13
+ push bp ; 55 ; 0xf4f55 keyboard.c:194
+ mov bp, sp ; 89 e5 ; 0xf4f56
+ push ax ; 50 ; 0xf4f58 keyboard.c:199
+ push 00586h ; 68 86 05 ; 0xf4f59
+ push strict byte 00007h ; 6a 07 ; 0xf4f5c
+ call 01a14h ; e8 b3 ca ; 0xf4f5e
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf4f61
+ mov sp, bp ; 89 ec ; 0xf4f64 keyboard.c:200
+ pop bp ; 5d ; 0xf4f66
+ retn ; c3 ; 0xf4f67
+ ; disGetNextSymbol 0xf4f68 LB 0x50dd -> off=0x0 cb=000000000000026a uValue=00000000000f3968 'keyboard_init'
+keyboard_init: ; 0xf4f68 LB 0x26a
+ push bp ; 55 ; 0xf4f68 keyboard.c:208
+ mov bp, sp ; 89 e5 ; 0xf4f69
+ mov AL, strict byte 0aah ; b0 aa ; 0xf4f6b keyboard.c:214
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4f6d
+ out DX, AL ; ee ; 0xf4f70
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4f71 keyboard.c:217
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4f74 keyboard.c:218
+ in AL, DX ; ec ; 0xf4f77
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4f78
+ test AL, strict byte 002h ; a8 02 ; 0xf4f7a
+ je short 04f8bh ; 74 0d ; 0xf4f7c
+ dec bx ; 4b ; 0xf4f7e
+ test bx, bx ; 85 db ; 0xf4f7f
+ jbe short 04f8bh ; 76 08 ; 0xf4f81
+ xor al, al ; 30 c0 ; 0xf4f83
+ mov dx, 00080h ; ba 80 00 ; 0xf4f85
+ out DX, AL ; ee ; 0xf4f88
+ jmp short 04f74h ; eb e9 ; 0xf4f89
+ test bx, bx ; 85 db ; 0xf4f8b keyboard.c:219
+ jne short 04f94h ; 75 05 ; 0xf4f8d
+ xor ax, ax ; 31 c0 ; 0xf4f8f
+ call 04f55h ; e8 c1 ff ; 0xf4f91
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4f94 keyboard.c:222
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4f97 keyboard.c:223
+ in AL, DX ; ec ; 0xf4f9a
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4f9b
+ test AL, strict byte 001h ; a8 01 ; 0xf4f9d
+ jne short 04faeh ; 75 0d ; 0xf4f9f
+ dec bx ; 4b ; 0xf4fa1
+ test bx, bx ; 85 db ; 0xf4fa2
+ jbe short 04faeh ; 76 08 ; 0xf4fa4
+ mov AL, strict byte 001h ; b0 01 ; 0xf4fa6
+ mov dx, 00080h ; ba 80 00 ; 0xf4fa8
+ out DX, AL ; ee ; 0xf4fab
+ jmp short 04f97h ; eb e9 ; 0xf4fac
+ test bx, bx ; 85 db ; 0xf4fae keyboard.c:224
+ jne short 04fb8h ; 75 06 ; 0xf4fb0
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf4fb2
+ call 04f55h ; e8 9d ff ; 0xf4fb5
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf4fb8 keyboard.c:227
+ in AL, DX ; ec ; 0xf4fbb
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4fbc
+ cmp ax, strict word 00055h ; 3d 55 00 ; 0xf4fbe
+ je short 04fc9h ; 74 06 ; 0xf4fc1
+ mov ax, 003dfh ; b8 df 03 ; 0xf4fc3 keyboard.c:228
+ call 04f55h ; e8 8c ff ; 0xf4fc6
+ mov AL, strict byte 0abh ; b0 ab ; 0xf4fc9 keyboard.c:232
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4fcb
+ out DX, AL ; ee ; 0xf4fce
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4fcf keyboard.c:235
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4fd2 keyboard.c:236
+ in AL, DX ; ec ; 0xf4fd5
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4fd6
+ test AL, strict byte 002h ; a8 02 ; 0xf4fd8
+ je short 04fe9h ; 74 0d ; 0xf4fda
+ dec bx ; 4b ; 0xf4fdc
+ test bx, bx ; 85 db ; 0xf4fdd
+ jbe short 04fe9h ; 76 08 ; 0xf4fdf
+ mov AL, strict byte 010h ; b0 10 ; 0xf4fe1
+ mov dx, 00080h ; ba 80 00 ; 0xf4fe3
+ out DX, AL ; ee ; 0xf4fe6
+ jmp short 04fd2h ; eb e9 ; 0xf4fe7
+ test bx, bx ; 85 db ; 0xf4fe9 keyboard.c:237
+ jne short 04ff3h ; 75 06 ; 0xf4feb
+ mov ax, strict word 0000ah ; b8 0a 00 ; 0xf4fed
+ call 04f55h ; e8 62 ff ; 0xf4ff0
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4ff3 keyboard.c:240
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4ff6 keyboard.c:241
+ in AL, DX ; ec ; 0xf4ff9
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4ffa
+ test AL, strict byte 001h ; a8 01 ; 0xf4ffc
+ jne short 0500dh ; 75 0d ; 0xf4ffe
+ dec bx ; 4b ; 0xf5000
+ test bx, bx ; 85 db ; 0xf5001
+ jbe short 0500dh ; 76 08 ; 0xf5003
+ mov AL, strict byte 011h ; b0 11 ; 0xf5005
+ mov dx, 00080h ; ba 80 00 ; 0xf5007
+ out DX, AL ; ee ; 0xf500a
+ jmp short 04ff6h ; eb e9 ; 0xf500b
+ test bx, bx ; 85 db ; 0xf500d keyboard.c:242
+ jne short 05017h ; 75 06 ; 0xf500f
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf5011
+ call 04f55h ; e8 3e ff ; 0xf5014
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5017 keyboard.c:246
+ in AL, DX ; ec ; 0xf501a
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf501b
+ test ax, ax ; 85 c0 ; 0xf501d
+ je short 05027h ; 74 06 ; 0xf501f
+ mov ax, 003e0h ; b8 e0 03 ; 0xf5021 keyboard.c:247
+ call 04f55h ; e8 2e ff ; 0xf5024
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf5027 keyboard.c:253
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5029
+ out DX, AL ; ee ; 0xf502c
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf502d keyboard.c:256
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5030 keyboard.c:257
+ in AL, DX ; ec ; 0xf5033
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5034
+ test AL, strict byte 002h ; a8 02 ; 0xf5036
+ je short 05047h ; 74 0d ; 0xf5038
+ dec bx ; 4b ; 0xf503a
+ test bx, bx ; 85 db ; 0xf503b
+ jbe short 05047h ; 76 08 ; 0xf503d
+ mov AL, strict byte 020h ; b0 20 ; 0xf503f
+ mov dx, 00080h ; ba 80 00 ; 0xf5041
+ out DX, AL ; ee ; 0xf5044
+ jmp short 05030h ; eb e9 ; 0xf5045
+ test bx, bx ; 85 db ; 0xf5047 keyboard.c:258
+ jne short 05051h ; 75 06 ; 0xf5049
+ mov ax, strict word 00014h ; b8 14 00 ; 0xf504b
+ call 04f55h ; e8 04 ff ; 0xf504e
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf5051 keyboard.c:261
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5054 keyboard.c:262
+ in AL, DX ; ec ; 0xf5057
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5058
+ test AL, strict byte 001h ; a8 01 ; 0xf505a
+ jne short 0506bh ; 75 0d ; 0xf505c
+ dec bx ; 4b ; 0xf505e
+ test bx, bx ; 85 db ; 0xf505f
+ jbe short 0506bh ; 76 08 ; 0xf5061
+ mov AL, strict byte 021h ; b0 21 ; 0xf5063
+ mov dx, 00080h ; ba 80 00 ; 0xf5065
+ out DX, AL ; ee ; 0xf5068
+ jmp short 05054h ; eb e9 ; 0xf5069
+ test bx, bx ; 85 db ; 0xf506b keyboard.c:263
+ jne short 05075h ; 75 06 ; 0xf506d
+ mov ax, strict word 00015h ; b8 15 00 ; 0xf506f
+ call 04f55h ; e8 e0 fe ; 0xf5072
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5075 keyboard.c:266
+ in AL, DX ; ec ; 0xf5078
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5079
+ cmp ax, 000fah ; 3d fa 00 ; 0xf507b
+ je short 05086h ; 74 06 ; 0xf507e
+ mov ax, 003e1h ; b8 e1 03 ; 0xf5080 keyboard.c:267
+ call 04f55h ; e8 cf fe ; 0xf5083
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5086 keyboard.c:271
+ in AL, DX ; ec ; 0xf5089
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf508a
+ test AL, strict byte 001h ; a8 01 ; 0xf508c
+ jne short 05098h ; 75 08 ; 0xf508e
+ mov AL, strict byte 031h ; b0 31 ; 0xf5090
+ mov dx, 00080h ; ba 80 00 ; 0xf5092
+ out DX, AL ; ee ; 0xf5095
+ jmp short 05086h ; eb ee ; 0xf5096
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5098 keyboard.c:273
+ in AL, DX ; ec ; 0xf509b
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf509c
+ cmp ax, 000aah ; 3d aa 00 ; 0xf509e
+ je short 050b1h ; 74 0e ; 0xf50a1
+ in AL, DX ; ec ; 0xf50a3
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf50a4
+ cmp ax, 000aah ; 3d aa 00 ; 0xf50a6
+ je short 050b1h ; 74 06 ; 0xf50a9
+ mov ax, 003e2h ; b8 e2 03 ; 0xf50ab keyboard.c:274
+ call 04f55h ; e8 a4 fe ; 0xf50ae
+ mov AL, strict byte 0f5h ; b0 f5 ; 0xf50b1 keyboard.c:278
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf50b3
+ out DX, AL ; ee ; 0xf50b6
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf50b7 keyboard.c:281
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf50ba keyboard.c:282
+ in AL, DX ; ec ; 0xf50bd
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf50be
+ test AL, strict byte 002h ; a8 02 ; 0xf50c0
+ je short 050d1h ; 74 0d ; 0xf50c2
+ dec bx ; 4b ; 0xf50c4
+ test bx, bx ; 85 db ; 0xf50c5
+ jbe short 050d1h ; 76 08 ; 0xf50c7
+ mov AL, strict byte 040h ; b0 40 ; 0xf50c9
+ mov dx, 00080h ; ba 80 00 ; 0xf50cb
+ out DX, AL ; ee ; 0xf50ce
+ jmp short 050bah ; eb e9 ; 0xf50cf
+ test bx, bx ; 85 db ; 0xf50d1 keyboard.c:283
+ jne short 050dbh ; 75 06 ; 0xf50d3
+ mov ax, strict word 00028h ; b8 28 00 ; 0xf50d5
+ call 04f55h ; e8 7a fe ; 0xf50d8
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf50db keyboard.c:286
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf50de keyboard.c:287
+ in AL, DX ; ec ; 0xf50e1
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf50e2
+ test AL, strict byte 001h ; a8 01 ; 0xf50e4
+ jne short 050f5h ; 75 0d ; 0xf50e6
+ dec bx ; 4b ; 0xf50e8
+ test bx, bx ; 85 db ; 0xf50e9
+ jbe short 050f5h ; 76 08 ; 0xf50eb
+ mov AL, strict byte 041h ; b0 41 ; 0xf50ed
+ mov dx, 00080h ; ba 80 00 ; 0xf50ef
+ out DX, AL ; ee ; 0xf50f2
+ jmp short 050deh ; eb e9 ; 0xf50f3
+ test bx, bx ; 85 db ; 0xf50f5 keyboard.c:288
+ jne short 050ffh ; 75 06 ; 0xf50f7
+ mov ax, strict word 00029h ; b8 29 00 ; 0xf50f9
+ call 04f55h ; e8 56 fe ; 0xf50fc
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf50ff keyboard.c:291
+ in AL, DX ; ec ; 0xf5102
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5103
+ cmp ax, 000fah ; 3d fa 00 ; 0xf5105
+ je short 05110h ; 74 06 ; 0xf5108
+ mov ax, 003e3h ; b8 e3 03 ; 0xf510a keyboard.c:292
+ call 04f55h ; e8 45 fe ; 0xf510d
+ mov AL, strict byte 060h ; b0 60 ; 0xf5110 keyboard.c:296
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5112
+ out DX, AL ; ee ; 0xf5115
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf5116 keyboard.c:299
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5119 keyboard.c:300
+ in AL, DX ; ec ; 0xf511c
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf511d
+ test AL, strict byte 002h ; a8 02 ; 0xf511f
+ je short 05130h ; 74 0d ; 0xf5121
+ dec bx ; 4b ; 0xf5123
+ test bx, bx ; 85 db ; 0xf5124
+ jbe short 05130h ; 76 08 ; 0xf5126
+ mov AL, strict byte 050h ; b0 50 ; 0xf5128
+ mov dx, 00080h ; ba 80 00 ; 0xf512a
+ out DX, AL ; ee ; 0xf512d
+ jmp short 05119h ; eb e9 ; 0xf512e
+ test bx, bx ; 85 db ; 0xf5130 keyboard.c:301
+ jne short 0513ah ; 75 06 ; 0xf5132
+ mov ax, strict word 00032h ; b8 32 00 ; 0xf5134
+ call 04f55h ; e8 1b fe ; 0xf5137
+ mov AL, strict byte 065h ; b0 65 ; 0xf513a keyboard.c:304
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf513c
+ out DX, AL ; ee ; 0xf513f
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf5140 keyboard.c:307
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5143 keyboard.c:308
+ in AL, DX ; ec ; 0xf5146
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5147
+ test AL, strict byte 002h ; a8 02 ; 0xf5149
+ je short 0515ah ; 74 0d ; 0xf514b
+ dec bx ; 4b ; 0xf514d
+ test bx, bx ; 85 db ; 0xf514e
+ jbe short 0515ah ; 76 08 ; 0xf5150
+ mov AL, strict byte 060h ; b0 60 ; 0xf5152
+ mov dx, 00080h ; ba 80 00 ; 0xf5154
+ out DX, AL ; ee ; 0xf5157
+ jmp short 05143h ; eb e9 ; 0xf5158
+ test bx, bx ; 85 db ; 0xf515a keyboard.c:309
+ jne short 05164h ; 75 06 ; 0xf515c
+ mov ax, strict word 0003ch ; b8 3c 00 ; 0xf515e
+ call 04f55h ; e8 f1 fd ; 0xf5161
+ mov AL, strict byte 0f4h ; b0 f4 ; 0xf5164 keyboard.c:312
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5166
+ out DX, AL ; ee ; 0xf5169
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf516a keyboard.c:315
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf516d keyboard.c:316
+ in AL, DX ; ec ; 0xf5170
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5171
+ test AL, strict byte 002h ; a8 02 ; 0xf5173
+ je short 05184h ; 74 0d ; 0xf5175
+ dec bx ; 4b ; 0xf5177
+ test bx, bx ; 85 db ; 0xf5178
+ jbe short 05184h ; 76 08 ; 0xf517a
+ mov AL, strict byte 070h ; b0 70 ; 0xf517c
+ mov dx, 00080h ; ba 80 00 ; 0xf517e
+ out DX, AL ; ee ; 0xf5181
+ jmp short 0516dh ; eb e9 ; 0xf5182
+ test bx, bx ; 85 db ; 0xf5184 keyboard.c:317
+ jne short 0518eh ; 75 06 ; 0xf5186
+ mov ax, strict word 00046h ; b8 46 00 ; 0xf5188
+ call 04f55h ; e8 c7 fd ; 0xf518b
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf518e keyboard.c:320
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5191 keyboard.c:321
+ in AL, DX ; ec ; 0xf5194
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5195
+ test AL, strict byte 001h ; a8 01 ; 0xf5197
+ jne short 051a8h ; 75 0d ; 0xf5199
+ dec bx ; 4b ; 0xf519b
+ test bx, bx ; 85 db ; 0xf519c
+ jbe short 051a8h ; 76 08 ; 0xf519e
+ mov AL, strict byte 071h ; b0 71 ; 0xf51a0
+ mov dx, 00080h ; ba 80 00 ; 0xf51a2
+ out DX, AL ; ee ; 0xf51a5
+ jmp short 05191h ; eb e9 ; 0xf51a6
+ test bx, bx ; 85 db ; 0xf51a8 keyboard.c:322
+ jne short 051b2h ; 75 06 ; 0xf51aa
+ mov ax, strict word 00046h ; b8 46 00 ; 0xf51ac
+ call 04f55h ; e8 a3 fd ; 0xf51af
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf51b2 keyboard.c:325
+ in AL, DX ; ec ; 0xf51b5
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf51b6
+ cmp ax, 000fah ; 3d fa 00 ; 0xf51b8
+ je short 051c3h ; 74 06 ; 0xf51bb
+ mov ax, 003e4h ; b8 e4 03 ; 0xf51bd keyboard.c:326
+ call 04f55h ; e8 92 fd ; 0xf51c0
+ mov AL, strict byte 0a8h ; b0 a8 ; 0xf51c3 keyboard.c:330
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf51c5
+ out DX, AL ; ee ; 0xf51c8
+ xor ax, ax ; 31 c0 ; 0xf51c9 keyboard.c:335
+ call 065ebh ; e8 1d 14 ; 0xf51cb
+ mov sp, bp ; 89 ec ; 0xf51ce keyboard.c:336
+ pop bp ; 5d ; 0xf51d0
+ retn ; c3 ; 0xf51d1
+ ; disGetNextSymbol 0xf51d2 LB 0x4e73 -> off=0x0 cb=0000000000000053 uValue=00000000000f3bd2 'enqueue_key'
+enqueue_key: ; 0xf51d2 LB 0x53
+ push bx ; 53 ; 0xf51d2 keyboard.c:339
+ push cx ; 51 ; 0xf51d3
+ push si ; 56 ; 0xf51d4
+ push di ; 57 ; 0xf51d5
+ push bp ; 55 ; 0xf51d6
+ mov bp, sp ; 89 e5 ; 0xf51d7
+ mov dh, al ; 88 c6 ; 0xf51d9
+ mov bx, 00080h ; bb 80 00 ; 0xf51db keyboard.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf51de
+ mov es, ax ; 8e c0 ; 0xf51e1
+ mov di, word [es:bx] ; 26 8b 3f ; 0xf51e3
+ mov bx, 00082h ; bb 82 00 ; 0xf51e6 keyboard.c:48
+ mov si, word [es:bx] ; 26 8b 37 ; 0xf51e9
+ mov bx, strict word 0001ah ; bb 1a 00 ; 0xf51ec keyboard.c:48
+ mov cx, word [es:bx] ; 26 8b 0f ; 0xf51ef
+ mov bx, strict word 0001ch ; bb 1c 00 ; 0xf51f2 keyboard.c:48
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf51f5
+ mov bx, ax ; 89 c3 ; 0xf51f8 keyboard.c:354
+ inc ax ; 40 ; 0xf51fa keyboard.c:355
+ inc ax ; 40 ; 0xf51fb
+ cmp ax, si ; 39 f0 ; 0xf51fc keyboard.c:356
+ jc short 05202h ; 72 02 ; 0xf51fe
+ mov ax, di ; 89 f8 ; 0xf5200 keyboard.c:357
+ cmp ax, cx ; 39 c8 ; 0xf5202 keyboard.c:359
+ jne short 0520ah ; 75 04 ; 0xf5204
+ xor ax, cx ; 31 c8 ; 0xf5206 keyboard.c:360
+ jmp short 0521fh ; eb 15 ; 0xf5208
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf520a keyboard.c:43
+ mov es, cx ; 8e c1 ; 0xf520d
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf520f
+ inc bx ; 43 ; 0xf5212 keyboard.c:363
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf5213 keyboard.c:43
+ mov bx, strict word 0001ch ; bb 1c 00 ; 0xf5216 keyboard.c:53
+ mov word [es:bx], ax ; 26 89 07 ; 0xf5219
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf521c keyboard.c:365
+ pop bp ; 5d ; 0xf521f keyboard.c:366
+ pop di ; 5f ; 0xf5220
+ pop si ; 5e ; 0xf5221
+ pop cx ; 59 ; 0xf5222
+ pop bx ; 5b ; 0xf5223
+ retn ; c3 ; 0xf5224
+ ; disGetNextSymbol 0xf5225 LB 0x4e20 -> off=0x35 cb=00000000000003cd uValue=00000000000f3c5a 'int09_function'
+ db 0d4h, 0c6h, 0c5h, 0bah, 0b8h, 0b6h, 0aah, 09dh, 054h, 053h, 046h, 045h, 03ah, 038h, 036h, 02ah
+ db 01dh, 0e6h, 054h, 036h, 053h, 0dfh, 052h, 0dfh, 052h, 09bh, 053h, 0bah, 052h, 0eeh, 053h, 049h
+ db 054h, 0cbh, 054h, 0aeh, 054h, 066h, 053h, 0dfh, 052h, 0dfh, 052h, 0c7h, 053h, 0d1h, 052h, 031h
+ db 054h, 096h, 054h, 0c6h, 054h
+int09_function: ; 0xf525a LB 0x3cd
+ push bp ; 55 ; 0xf525a keyboard.c:371
+ mov bp, sp ; 89 e5 ; 0xf525b
+ push si ; 56 ; 0xf525d
+ push di ; 57 ; 0xf525e
+ push ax ; 50 ; 0xf525f
+ push ax ; 50 ; 0xf5260
+ mov al, byte [bp+014h] ; 8a 46 14 ; 0xf5261 keyboard.c:382
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf5264
+ test al, al ; 84 c0 ; 0xf5267 keyboard.c:384
+ jne short 05284h ; 75 19 ; 0xf5269
+ mov bx, 00db2h ; bb b2 0d ; 0xf526b keyboard.c:385
+ mov cx, ds ; 8c d9 ; 0xf526e
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5270
+ call 019d3h ; e8 5d c7 ; 0xf5273
+ push 00599h ; 68 99 05 ; 0xf5276
+ push strict byte 00004h ; 6a 04 ; 0xf5279
+ call 01a14h ; e8 96 c7 ; 0xf527b
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf527e
+ jmp near 0532fh ; e9 ab 00 ; 0xf5281 keyboard.c:386
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5284 keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5287
+ mov es, ax ; 8e c0 ; 0xf528a
+ mov bl, byte [es:bx] ; 26 8a 1f ; 0xf528c
+ mov dl, bl ; 88 da ; 0xf528f keyboard.c:39
+ mov si, 00096h ; be 96 00 ; 0xf5291 keyboard.c:38
+ mov bh, byte [es:si] ; 26 8a 3c ; 0xf5294
+ mov byte [bp-008h], bh ; 88 7e f8 ; 0xf5297 keyboard.c:39
+ mov si, strict word 00017h ; be 17 00 ; 0xf529a keyboard.c:38
+ mov ah, byte [es:si] ; 26 8a 24 ; 0xf529d
+ mov dh, ah ; 88 e6 ; 0xf52a0 keyboard.c:39
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf52a2 keyboard.c:394
+ push CS ; 0e ; 0xf52a5
+ pop ES ; 07 ; 0xf52a6
+ mov cx, strict word 00012h ; b9 12 00 ; 0xf52a7
+ mov di, 05225h ; bf 25 52 ; 0xf52aa
+ repne scasb ; f2 ae ; 0xf52ad
+ sal cx, 1 ; d1 e1 ; 0xf52af
+ mov di, cx ; 89 cf ; 0xf52b1
+ mov si, word [cs:di+05236h] ; 2e 8b b5 36 52 ; 0xf52b3
+ jmp si ; ff e6 ; 0xf52b8
+ xor dh, 040h ; 80 f6 40 ; 0xf52ba keyboard.c:396
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf52bd keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf52c0
+ mov es, ax ; 8e c0 ; 0xf52c3
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf52c5
+ or dl, 040h ; 80 ca 40 ; 0xf52c8 keyboard.c:398
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf52cb keyboard.c:43
+ jmp near 054c0h ; e9 ef 01 ; 0xf52ce
+ and dl, 0bfh ; 80 e2 bf ; 0xf52d1 keyboard.c:402
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf52d4 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf52d7
+ mov es, ax ; 8e c0 ; 0xf52da
+ jmp near 054c0h ; e9 e1 01 ; 0xf52dc
+ test byte [bp-008h], 002h ; f6 46 f8 02 ; 0xf52df keyboard.c:411
+ jne near 05310h ; 0f 85 29 00 ; 0xf52e3
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf52e7 keyboard.c:412
+ and AL, strict byte 07fh ; 24 7f ; 0xf52ea
+ cmp AL, strict byte 02ah ; 3c 2a ; 0xf52ec
+ db 00fh, 094h, 0c0h
+ ; sete al ; 0f 94 c0 ; 0xf52ee
+ movzx bx, al ; 0f b6 d8 ; 0xf52f1
+ inc bx ; 43 ; 0xf52f4
+ test byte [bp-006h], 080h ; f6 46 fa 80 ; 0xf52f5 keyboard.c:413
+ je short 05303h ; 74 08 ; 0xf52f9
+ mov al, bl ; 88 d8 ; 0xf52fb keyboard.c:414
+ not al ; f6 d0 ; 0xf52fd
+ and dh, al ; 20 c6 ; 0xf52ff
+ jmp short 05305h ; eb 02 ; 0xf5301 keyboard.c:415
+ or dh, bl ; 08 de ; 0xf5303 keyboard.c:416
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf5305 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5308
+ mov es, ax ; 8e c0 ; 0xf530b
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf530d
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf5310 keyboard.c:419
+ and AL, strict byte 07fh ; 24 7f ; 0xf5313
+ cmp AL, strict byte 01dh ; 3c 1d ; 0xf5315
+ je short 0531dh ; 74 04 ; 0xf5317
+ and byte [bp-008h], 0feh ; 80 66 f8 fe ; 0xf5319
+ and byte [bp-008h], 0fdh ; 80 66 f8 fd ; 0xf531d
+ mov bx, 00096h ; bb 96 00 ; 0xf5321
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5324
+ mov es, ax ; 8e c0 ; 0xf5327
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf5329
+ mov byte [es:bx], al ; 26 88 07 ; 0xf532c
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf532f
+ pop di ; 5f ; 0xf5332
+ pop si ; 5e ; 0xf5333
+ pop bp ; 5d ; 0xf5334
+ retn ; c3 ; 0xf5335
+ test bh, 001h ; f6 c7 01 ; 0xf5336 keyboard.c:422
+ jne short 05310h ; 75 d5 ; 0xf5339
+ or dh, 004h ; 80 ce 04 ; 0xf533b keyboard.c:423
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf533e keyboard.c:41
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf5341
+ mov es, ax ; 8e c0 ; 0xf5344 keyboard.c:43
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf5346
+ test byte [bp-008h], 002h ; f6 46 f8 02 ; 0xf5349 keyboard.c:425
+ je short 0535bh ; 74 0c ; 0xf534d
+ or byte [bp-008h], 004h ; 80 4e f8 04 ; 0xf534f keyboard.c:426
+ mov bx, 00096h ; bb 96 00 ; 0xf5353 keyboard.c:41
+ mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xf5356
+ jmp short 05361h ; eb 06 ; 0xf5359 keyboard.c:428
+ or dl, 001h ; 80 ca 01 ; 0xf535b keyboard.c:429
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf535e keyboard.c:41
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5361 keyboard.c:43
+ jmp short 05310h ; eb aa ; 0xf5364 keyboard.c:433
+ test bh, 001h ; f6 c7 01 ; 0xf5366 keyboard.c:435
+ jne short 05310h ; 75 a5 ; 0xf5369
+ and dh, 0fbh ; 80 e6 fb ; 0xf536b keyboard.c:436
+ mov si, strict word 00017h ; be 17 00 ; 0xf536e keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5371
+ mov es, ax ; 8e c0 ; 0xf5374
+ mov byte [es:si], dh ; 26 88 34 ; 0xf5376
+ test bh, 002h ; f6 c7 02 ; 0xf5379 keyboard.c:438
+ je short 0538fh ; 74 11 ; 0xf537c
+ and bh, 0fbh ; 80 e7 fb ; 0xf537e keyboard.c:439
+ mov byte [bp-008h], bh ; 88 7e f8 ; 0xf5381
+ mov bx, 00096h ; bb 96 00 ; 0xf5384 keyboard.c:43
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf5387
+ mov byte [es:bx], al ; 26 88 07 ; 0xf538a
+ jmp short 05310h ; eb 81 ; 0xf538d keyboard.c:441
+ and dl, 0feh ; 80 e2 fe ; 0xf538f keyboard.c:442
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5392 keyboard.c:43
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5395
+ jmp near 05310h ; e9 75 ff ; 0xf5398 keyboard.c:446
+ or dh, 008h ; 80 ce 08 ; 0xf539b keyboard.c:449
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf539e keyboard.c:41
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf53a1
+ mov es, ax ; 8e c0 ; 0xf53a4 keyboard.c:43
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf53a6
+ test byte [bp-008h], 002h ; f6 46 f8 02 ; 0xf53a9 keyboard.c:451
+ je short 053bbh ; 74 0c ; 0xf53ad
+ or byte [bp-008h], 008h ; 80 4e f8 08 ; 0xf53af keyboard.c:452
+ mov bx, 00096h ; bb 96 00 ; 0xf53b3 keyboard.c:41
+ mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xf53b6
+ jmp short 053c1h ; eb 06 ; 0xf53b9 keyboard.c:454
+ or dl, 002h ; 80 ca 02 ; 0xf53bb keyboard.c:455
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf53be keyboard.c:41
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf53c1 keyboard.c:43
+ jmp near 05310h ; e9 49 ff ; 0xf53c4 keyboard.c:458
+ and dh, 0f7h ; 80 e6 f7 ; 0xf53c7 keyboard.c:460
+ mov si, strict word 00017h ; be 17 00 ; 0xf53ca keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf53cd
+ mov es, ax ; 8e c0 ; 0xf53d0
+ mov byte [es:si], dh ; 26 88 34 ; 0xf53d2
+ test bh, 002h ; f6 c7 02 ; 0xf53d5 keyboard.c:462
+ je short 053e2h ; 74 08 ; 0xf53d8
+ and bh, 0f7h ; 80 e7 f7 ; 0xf53da keyboard.c:463
+ mov byte [bp-008h], bh ; 88 7e f8 ; 0xf53dd
+ jmp short 05384h ; eb a2 ; 0xf53e0 keyboard.c:464
+ and dl, 0fdh ; 80 e2 fd ; 0xf53e2 keyboard.c:466
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf53e5 keyboard.c:43
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf53e8
+ jmp near 05310h ; e9 22 ff ; 0xf53eb keyboard.c:469
+ test bh, 003h ; f6 c7 03 ; 0xf53ee keyboard.c:472
+ jne short 05407h ; 75 14 ; 0xf53f1
+ or dl, 020h ; 80 ca 20 ; 0xf53f3 keyboard.c:474
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf53f6 keyboard.c:41
+ mov es, ax ; 8e c0 ; 0xf53f9
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf53fb
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf53fe keyboard.c:43
+ xor dh, 020h ; 80 f6 20 ; 0xf5401 keyboard.c:476
+ jmp near 0548dh ; e9 86 00 ; 0xf5404 keyboard.c:477
+ or dl, 008h ; 80 ca 08 ; 0xf5407 keyboard.c:480
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf540a keyboard.c:41
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf540d
+ mov es, ax ; 8e c0 ; 0xf5410 keyboard.c:43
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5412
+ mov ax, 000aeh ; b8 ae 00 ; 0xf5415 keyboard.c:484
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5418
+ out DX, AL ; ee ; 0xf541b
+ call 0e034h ; e8 15 8c ; 0xf541c keyboard.c:485
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf541f keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5422
+ mov es, ax ; 8e c0 ; 0xf5425
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf5427
+ test AL, strict byte 008h ; a8 08 ; 0xf542a keyboard.c:39
+ jne short 0541fh ; 75 f1 ; 0xf542c
+ jmp near 05310h ; e9 df fe ; 0xf542e keyboard.c:492
+ test bh, 003h ; f6 c7 03 ; 0xf5431 keyboard.c:494
+ jne near 05310h ; 0f 85 d8 fe ; 0xf5434
+ and dl, 0dfh ; 80 e2 df ; 0xf5438 keyboard.c:495
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf543b keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf543e
+ mov es, ax ; 8e c0 ; 0xf5441
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5443
+ jmp near 05310h ; e9 c7 fe ; 0xf5446 keyboard.c:498
+ test bh, 002h ; f6 c7 02 ; 0xf5449 keyboard.c:501
+ je short 0547ch ; 74 2e ; 0xf544c
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf544e keyboard.c:46
+ mov bx, strict word 0001ah ; bb 1a 00 ; 0xf5451
+ mov es, ax ; 8e c0 ; 0xf5454 keyboard.c:48
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf5456
+ mov bx, strict word 0001ch ; bb 1c 00 ; 0xf5459 keyboard.c:51
+ mov word [es:bx], ax ; 26 89 07 ; 0xf545c keyboard.c:53
+ mov bx, strict word 00071h ; bb 71 00 ; 0xf545f keyboard.c:41
+ mov DL, strict byte 080h ; b2 80 ; 0xf5462
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5464 keyboard.c:43
+ mov ax, 000aeh ; b8 ae 00 ; 0xf5467 keyboard.c:506
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf546a
+ out DX, AL ; ee ; 0xf546d
+ push bp ; 55 ; 0xf546e keyboard.c:507
+ int 01bh ; cd 1b ; 0xf546f
+ pop bp ; 5d ; 0xf5471
+ xor dx, dx ; 31 d2 ; 0xf5472 keyboard.c:508
+ xor ax, ax ; 31 c0 ; 0xf5474
+ call 051d2h ; e8 59 fd ; 0xf5476
+ jmp near 05310h ; e9 94 fe ; 0xf5479 keyboard.c:509
+ or dl, 010h ; 80 ca 10 ; 0xf547c keyboard.c:510
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf547f keyboard.c:41
+ mov es, ax ; 8e c0 ; 0xf5482
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5484
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5487 keyboard.c:43
+ xor dh, 010h ; 80 f6 10 ; 0xf548a keyboard.c:512
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf548d keyboard.c:41
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf5490 keyboard.c:43
+ jmp near 05310h ; e9 7a fe ; 0xf5493 keyboard.c:515
+ test bh, 002h ; f6 c7 02 ; 0xf5496 keyboard.c:518
+ jne near 05310h ; 0f 85 73 fe ; 0xf5499
+ and dl, 0efh ; 80 e2 ef ; 0xf549d keyboard.c:519
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf54a0 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf54a3
+ mov es, ax ; 8e c0 ; 0xf54a6
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf54a8
+ jmp near 05310h ; e9 62 fe ; 0xf54ab keyboard.c:522
+ test bl, 004h ; f6 c3 04 ; 0xf54ae keyboard.c:525
+ jne near 05310h ; 0f 85 5b fe ; 0xf54b1
+ or dl, 004h ; 80 ca 04 ; 0xf54b5 keyboard.c:526
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf54b8 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf54bb
+ mov es, ax ; 8e c0 ; 0xf54be
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf54c0
+ jmp near 05310h ; e9 4a fe ; 0xf54c3 keyboard.c:530
+ and dl, 0fbh ; 80 e2 fb ; 0xf54c6 keyboard.c:533
+ jmp short 054b8h ; eb ed ; 0xf54c9 keyboard.c:534
+ mov al, ah ; 88 e0 ; 0xf54cb keyboard.c:539
+ and AL, strict byte 00ch ; 24 0c ; 0xf54cd
+ cmp AL, strict byte 00ch ; 3c 0c ; 0xf54cf
+ jne short 054e6h ; 75 13 ; 0xf54d1
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf54d3 keyboard.c:51
+ mov es, ax ; 8e c0 ; 0xf54d6
+ mov bx, strict word 00072h ; bb 72 00 ; 0xf54d8
+ mov ax, 01234h ; b8 34 12 ; 0xf54db
+ mov word [es:bx], ax ; 26 89 07 ; 0xf54de keyboard.c:53
+ jmp far 0f000h:0e05bh ; ea 5b e0 00 f0 ; 0xf54e1 keyboard.c:542
+ test dl, 008h ; f6 c2 08 ; 0xf54e6 keyboard.c:548
+ je short 054fch ; 74 11 ; 0xf54e9
+ and dl, 0f7h ; 80 e2 f7 ; 0xf54eb keyboard.c:550
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf54ee keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf54f1
+ mov es, ax ; 8e c0 ; 0xf54f4
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf54f6
+ jmp near 0532fh ; e9 33 fe ; 0xf54f9 keyboard.c:552
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf54fc keyboard.c:555
+ test AL, strict byte 080h ; a8 80 ; 0xf54ff
+ je short 05531h ; 74 2e ; 0xf5501
+ cmp AL, strict byte 0fah ; 3c fa ; 0xf5503 keyboard.c:557
+ jne short 05517h ; 75 10 ; 0xf5505
+ mov bx, 00097h ; bb 97 00 ; 0xf5507 keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf550a
+ mov es, ax ; 8e c0 ; 0xf550d
+ mov ah, byte [es:bx] ; 26 8a 27 ; 0xf550f
+ or ah, 010h ; 80 cc 10 ; 0xf5512 keyboard.c:39
+ jmp short 0552bh ; eb 14 ; 0xf5515 keyboard.c:560
+ cmp AL, strict byte 0feh ; 3c fe ; 0xf5517
+ jne near 05310h ; 0f 85 f3 fd ; 0xf5519
+ mov bx, 00097h ; bb 97 00 ; 0xf551d keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5520
+ mov es, ax ; 8e c0 ; 0xf5523
+ mov ah, byte [es:bx] ; 26 8a 27 ; 0xf5525
+ or ah, 020h ; 80 cc 20 ; 0xf5528 keyboard.c:39
+ mov byte [es:bx], ah ; 26 88 27 ; 0xf552b keyboard.c:43
+ jmp near 05310h ; e9 df fd ; 0xf552e keyboard.c:564
+ cmp byte [bp-006h], 058h ; 80 7e fa 58 ; 0xf5531 keyboard.c:566
+ jbe short 05555h ; 76 1e ; 0xf5535
+ mov bx, 00db2h ; bb b2 0d ; 0xf5537 keyboard.c:567
+ mov cx, ds ; 8c d9 ; 0xf553a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf553c
+ call 019d3h ; e8 91 c4 ; 0xf553f
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf5542
+ push ax ; 50 ; 0xf5546
+ push 005b3h ; 68 b3 05 ; 0xf5547
+ push strict byte 00004h ; 6a 04 ; 0xf554a
+ call 01a14h ; e8 c5 c4 ; 0xf554c
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf554f
+ jmp near 0532fh ; e9 da fd ; 0xf5552 keyboard.c:568
+ test dh, 008h ; f6 c6 08 ; 0xf5555 keyboard.c:570
+ je short 0556ch ; 74 12 ; 0xf5558
+ movzx bx, byte [bp-006h] ; 0f b6 5e fa ; 0xf555a keyboard.c:571
+ imul bx, bx, strict byte 0000ah ; 6b db 0a ; 0xf555e
+ mov dl, byte [bx+00e06h] ; 8a 97 06 0e ; 0xf5561
+ mov ax, word [bx+00e06h] ; 8b 87 06 0e ; 0xf5565 keyboard.c:572
+ jmp near 055f8h ; e9 8c 00 ; 0xf5569 keyboard.c:573
+ test dh, 004h ; f6 c6 04 ; 0xf556c
+ je short 05583h ; 74 12 ; 0xf556f
+ movzx bx, byte [bp-006h] ; 0f b6 5e fa ; 0xf5571 keyboard.c:574
+ imul bx, bx, strict byte 0000ah ; 6b db 0a ; 0xf5575
+ mov dl, byte [bx+00e04h] ; 8a 97 04 0e ; 0xf5578
+ mov ax, word [bx+00e04h] ; 8b 87 04 0e ; 0xf557c keyboard.c:575
+ jmp near 055f8h ; e9 75 00 ; 0xf5580 keyboard.c:576
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf5583
+ and AL, strict byte 002h ; 24 02 ; 0xf5586
+ test al, al ; 84 c0 ; 0xf5588
+ jbe short 055a1h ; 76 15 ; 0xf558a
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf558c
+ cmp AL, strict byte 047h ; 3c 47 ; 0xf558f
+ jc short 055a1h ; 72 0e ; 0xf5591
+ cmp AL, strict byte 053h ; 3c 53 ; 0xf5593
+ jnbe short 055a1h ; 77 0a ; 0xf5595
+ mov DL, strict byte 0e0h ; b2 e0 ; 0xf5597 keyboard.c:578
+ movzx bx, al ; 0f b6 d8 ; 0xf5599 keyboard.c:579
+ imul bx, bx, strict byte 0000ah ; 6b db 0a ; 0xf559c
+ jmp short 055f4h ; eb 53 ; 0xf559f keyboard.c:580
+ test dh, 003h ; f6 c6 03 ; 0xf55a1
+ je short 055d3h ; 74 2d ; 0xf55a4
+ movzx bx, byte [bp-006h] ; 0f b6 5e fa ; 0xf55a6 keyboard.c:584
+ imul bx, bx, strict byte 0000ah ; 6b db 0a ; 0xf55aa
+ movzx ax, byte [bx+00e08h] ; 0f b6 87 08 0e ; 0xf55ad
+ movzx dx, dh ; 0f b6 d6 ; 0xf55b2
+ test dx, ax ; 85 c2 ; 0xf55b5
+ je short 055c3h ; 74 0a ; 0xf55b7
+ mov dl, byte [bx+00e00h] ; 8a 97 00 0e ; 0xf55b9 keyboard.c:585
+ mov ax, word [bx+00e00h] ; 8b 87 00 0e ; 0xf55bd keyboard.c:586
+ jmp short 055cbh ; eb 08 ; 0xf55c1 keyboard.c:587
+ mov dl, byte [bx+00e02h] ; 8a 97 02 0e ; 0xf55c3 keyboard.c:588
+ mov ax, word [bx+00e02h] ; 8b 87 02 0e ; 0xf55c7 keyboard.c:589
+ shr ax, 008h ; c1 e8 08 ; 0xf55cb
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf55ce
+ jmp short 055feh ; eb 2b ; 0xf55d1 keyboard.c:591
+ movzx bx, byte [bp-006h] ; 0f b6 5e fa ; 0xf55d3 keyboard.c:593
+ imul bx, bx, strict byte 0000ah ; 6b db 0a ; 0xf55d7
+ movzx si, byte [bx+00e08h] ; 0f b6 b7 08 0e ; 0xf55da
+ movzx ax, dh ; 0f b6 c6 ; 0xf55df
+ test ax, si ; 85 f0 ; 0xf55e2
+ je short 055f0h ; 74 0a ; 0xf55e4
+ mov dl, byte [bx+00e02h] ; 8a 97 02 0e ; 0xf55e6 keyboard.c:594
+ mov ax, word [bx+00e02h] ; 8b 87 02 0e ; 0xf55ea keyboard.c:595
+ jmp short 055f8h ; eb 08 ; 0xf55ee keyboard.c:596
+ mov dl, byte [bx+00e00h] ; 8a 97 00 0e ; 0xf55f0 keyboard.c:597
+ mov ax, word [bx+00e00h] ; 8b 87 00 0e ; 0xf55f4 keyboard.c:598
+ shr ax, 008h ; c1 e8 08 ; 0xf55f8
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf55fb
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf55fe keyboard.c:601
+ jne short 0561eh ; 75 1a ; 0xf5602
+ test dl, dl ; 84 d2 ; 0xf5604
+ jne short 0561eh ; 75 16 ; 0xf5606
+ mov bx, 00db2h ; bb b2 0d ; 0xf5608 keyboard.c:602
+ mov cx, ds ; 8c d9 ; 0xf560b
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf560d
+ call 019d3h ; e8 c0 c3 ; 0xf5610
+ push 005eah ; 68 ea 05 ; 0xf5613
+ push strict byte 00004h ; 6a 04 ; 0xf5616
+ call 01a14h ; e8 f9 c3 ; 0xf5618
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf561b
+ xor dh, dh ; 30 f6 ; 0xf561e keyboard.c:604
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf5620
+ jmp near 05476h ; e9 4f fe ; 0xf5624
+ ; disGetNextSymbol 0xf5627 LB 0x4a1e -> off=0x0 cb=000000000000006c uValue=00000000000f4027 'dequeue_key'
+dequeue_key: ; 0xf5627 LB 0x6c
+ push si ; 56 ; 0xf5627 keyboard.c:614
+ push di ; 57 ; 0xf5628
+ enter 00002h, 000h ; c8 02 00 00 ; 0xf5629
+ push ax ; 50 ; 0xf562d
+ push dx ; 52 ; 0xf562e
+ mov si, bx ; 89 de ; 0xf562f
+ mov bx, 00080h ; bb 80 00 ; 0xf5631 keyboard.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5634
+ mov es, ax ; 8e c0 ; 0xf5637
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf5639
+ mov word [bp-002h], ax ; 89 46 fe ; 0xf563c
+ mov bx, 00082h ; bb 82 00 ; 0xf563f keyboard.c:48
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf5642
+ mov bx, strict word 0001ah ; bb 1a 00 ; 0xf5645 keyboard.c:48
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf5648
+ mov di, strict word 0001ch ; bf 1c 00 ; 0xf564b keyboard.c:48
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf564e
+ cmp bx, ax ; 39 c3 ; 0xf5651 keyboard.c:630
+ je short 0568bh ; 74 36 ; 0xf5653
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf5655 keyboard.c:38
+ lea di, [bx+001h] ; 8d 7f 01 ; 0xf5658 keyboard.c:632
+ mov ah, byte [es:di] ; 26 8a 25 ; 0xf565b keyboard.c:38
+ mov es, cx ; 8e c1 ; 0xf565e keyboard.c:633
+ mov byte [es:si], al ; 26 88 04 ; 0xf5660
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf5663 keyboard.c:634
+ mov si, word [bp-004h] ; 8b 76 fc ; 0xf5666
+ mov byte [es:si], ah ; 26 88 24 ; 0xf5669
+ cmp word [bp+008h], strict byte 00000h ; 83 7e 08 00 ; 0xf566c keyboard.c:637
+ je short 05686h ; 74 14 ; 0xf5670
+ inc bx ; 43 ; 0xf5672 keyboard.c:638
+ inc bx ; 43 ; 0xf5673
+ cmp bx, dx ; 39 d3 ; 0xf5674 keyboard.c:639
+ jc short 0567bh ; 72 03 ; 0xf5676
+ mov bx, word [bp-002h] ; 8b 5e fe ; 0xf5678 keyboard.c:640
+ mov si, strict word 0001ah ; be 1a 00 ; 0xf567b keyboard.c:53
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf567e
+ mov es, ax ; 8e c0 ; 0xf5681
+ mov word [es:si], bx ; 26 89 1c ; 0xf5683
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf5686 keyboard.c:643
+ jmp short 0568dh ; eb 02 ; 0xf5689
+ xor ax, ax ; 31 c0 ; 0xf568b keyboard.c:646
+ leave ; c9 ; 0xf568d keyboard.c:648
+ pop di ; 5f ; 0xf568e
+ pop si ; 5e ; 0xf568f
+ retn 00002h ; c2 02 00 ; 0xf5690
+ ; disGetNextSymbol 0xf5693 LB 0x49b2 -> off=0x23 cb=00000000000002e7 uValue=00000000000f40b6 'int16_function'
+ db 0a2h, 092h, 012h, 011h, 010h, 00ah, 009h, 005h, 002h, 001h, 000h, 053h, 059h, 06bh, 057h, 0b2h
+ db 057h, 0ffh, 057h, 011h, 058h, 03bh, 058h, 044h, 058h, 0b5h, 058h, 0e6h, 058h, 014h, 059h, 048h
+ db 059h, 096h, 059h
+int16_function: ; 0xf56b6 LB 0x2e7
+ push bp ; 55 ; 0xf56b6 keyboard.c:665
+ mov bp, sp ; 89 e5 ; 0xf56b7
+ push si ; 56 ; 0xf56b9
+ push di ; 57 ; 0xf56ba
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf56bb
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf56be keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf56c1
+ mov es, ax ; 8e c0 ; 0xf56c4
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf56c6
+ mov bl, al ; 88 c3 ; 0xf56c9 keyboard.c:39
+ mov si, 00097h ; be 97 00 ; 0xf56cb keyboard.c:38
+ mov ah, byte [es:si] ; 26 8a 24 ; 0xf56ce
+ mov bh, ah ; 88 e7 ; 0xf56d1 keyboard.c:39
+ movzx dx, al ; 0f b6 d0 ; 0xf56d3 keyboard.c:674
+ sar dx, 004h ; c1 fa 04 ; 0xf56d6
+ and dl, 007h ; 80 e2 07 ; 0xf56d9
+ mov al, ah ; 88 e0 ; 0xf56dc
+ and AL, strict byte 007h ; 24 07 ; 0xf56de
+ xor ah, ah ; 30 e4 ; 0xf56e0
+ xor al, dl ; 30 d0 ; 0xf56e2
+ test ax, ax ; 85 c0 ; 0xf56e4
+ je short 05749h ; 74 61 ; 0xf56e6
+ cli ; fa ; 0xf56e8 keyboard.c:675
+ mov AL, strict byte 0edh ; b0 ed ; 0xf56e9 keyboard.c:676
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf56eb
+ out DX, AL ; ee ; 0xf56ee
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf56ef keyboard.c:677
+ in AL, DX ; ec ; 0xf56f2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf56f3
+ test AL, strict byte 001h ; a8 01 ; 0xf56f5
+ jne short 05701h ; 75 08 ; 0xf56f7
+ mov AL, strict byte 021h ; b0 21 ; 0xf56f9
+ mov dx, 00080h ; ba 80 00 ; 0xf56fb
+ out DX, AL ; ee ; 0xf56fe
+ jmp short 056efh ; eb ee ; 0xf56ff
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5701 keyboard.c:678
+ in AL, DX ; ec ; 0xf5704
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5705
+ cmp ax, 000fah ; 3d fa 00 ; 0xf5707
+ jne short 05748h ; 75 3c ; 0xf570a
+ and bh, 0c8h ; 80 e7 c8 ; 0xf570c keyboard.c:679
+ movzx dx, bl ; 0f b6 d3 ; 0xf570f keyboard.c:680
+ sar dx, 004h ; c1 fa 04 ; 0xf5712
+ and dx, strict byte 00007h ; 83 e2 07 ; 0xf5715
+ movzx ax, bh ; 0f b6 c7 ; 0xf5718
+ or ax, dx ; 09 d0 ; 0xf571b
+ mov bh, al ; 88 c7 ; 0xf571d
+ and AL, strict byte 007h ; 24 07 ; 0xf571f keyboard.c:681
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5721
+ out DX, AL ; ee ; 0xf5724
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5725 keyboard.c:682
+ in AL, DX ; ec ; 0xf5728
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5729
+ test AL, strict byte 001h ; a8 01 ; 0xf572b
+ jne short 05737h ; 75 08 ; 0xf572d
+ mov AL, strict byte 021h ; b0 21 ; 0xf572f keyboard.c:683
+ mov dx, 00080h ; ba 80 00 ; 0xf5731
+ out DX, AL ; ee ; 0xf5734
+ jmp short 05725h ; eb ee ; 0xf5735
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5737 keyboard.c:684
+ in AL, DX ; ec ; 0xf573a
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf573b
+ mov si, 00097h ; be 97 00 ; 0xf573d keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5740
+ mov es, ax ; 8e c0 ; 0xf5743
+ mov byte [es:si], bh ; 26 88 3c ; 0xf5745
+ sti ; fb ; 0xf5748 keyboard.c:687
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf5749 keyboard.c:690
+ shr ax, 008h ; c1 e8 08 ; 0xf574c
+ cmp ax, 000a2h ; 3d a2 00 ; 0xf574f
+ jnbe near 05953h ; 0f 87 fd 01 ; 0xf5752
+ push CS ; 0e ; 0xf5756
+ pop ES ; 07 ; 0xf5757
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf5758
+ mov di, 05693h ; bf 93 56 ; 0xf575b
+ repne scasb ; f2 ae ; 0xf575e
+ sal cx, 1 ; d1 e1 ; 0xf5760
+ mov di, cx ; 89 cf ; 0xf5762
+ mov ax, word [cs:di+0569eh] ; 2e 8b 85 9e 56 ; 0xf5764
+ jmp ax ; ff e0 ; 0xf5769
+ push strict byte 00001h ; 6a 01 ; 0xf576b keyboard.c:692
+ mov cx, ss ; 8c d1 ; 0xf576d
+ lea bx, [bp-00ah] ; 8d 5e f6 ; 0xf576f
+ mov dx, ss ; 8c d2 ; 0xf5772
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf5774
+ call 05627h ; e8 ad fe ; 0xf5777
+ test ax, ax ; 85 c0 ; 0xf577a
+ jne short 05789h ; 75 0b ; 0xf577c
+ push 00621h ; 68 21 06 ; 0xf577e keyboard.c:693
+ push strict byte 00007h ; 6a 07 ; 0xf5781
+ call 01a14h ; e8 8e c2 ; 0xf5783
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf5786
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf5789 keyboard.c:695
+ je short 05795h ; 74 06 ; 0xf578d
+ cmp byte [bp-00ah], 0f0h ; 80 7e f6 f0 ; 0xf578f
+ je short 0579bh ; 74 06 ; 0xf5793
+ cmp byte [bp-00ah], 0e0h ; 80 7e f6 e0 ; 0xf5795 keyboard.c:697
+ jne short 0579fh ; 75 04 ; 0xf5799
+ mov byte [bp-00ah], 000h ; c6 46 f6 00 ; 0xf579b keyboard.c:698
+ movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xf579f keyboard.c:699
+ sal dx, 008h ; c1 e2 08 ; 0xf57a3
+ movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xf57a6
+ or dx, ax ; 09 c2 ; 0xf57aa
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf57ac
+ jmp near 05996h ; e9 e4 01 ; 0xf57af keyboard.c:700
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf57b2 keyboard.c:704
+ mov word [bp+01eh], ax ; 89 46 1e ; 0xf57b5
+ push strict byte 00000h ; 6a 00 ; 0xf57b8 keyboard.c:705
+ mov cx, ss ; 8c d1 ; 0xf57ba
+ lea bx, [bp-00ah] ; 8d 5e f6 ; 0xf57bc
+ mov dx, ss ; 8c d2 ; 0xf57bf
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf57c1
+ call 05627h ; e8 60 fe ; 0xf57c4
+ test ax, ax ; 85 c0 ; 0xf57c7
+ jne short 057d2h ; 75 07 ; 0xf57c9
+ or word [bp+01eh], strict byte 00040h ; 83 4e 1e 40 ; 0xf57cb keyboard.c:706
+ jmp near 05996h ; e9 c4 01 ; 0xf57cf keyboard.c:707
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf57d2 keyboard.c:709
+ je short 057deh ; 74 06 ; 0xf57d6
+ cmp byte [bp-00ah], 0f0h ; 80 7e f6 f0 ; 0xf57d8
+ je short 057e4h ; 74 06 ; 0xf57dc
+ cmp byte [bp-00ah], 0e0h ; 80 7e f6 e0 ; 0xf57de keyboard.c:711
+ jne short 057e8h ; 75 04 ; 0xf57e2
+ mov byte [bp-00ah], 000h ; c6 46 f6 00 ; 0xf57e4 keyboard.c:712
+ movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xf57e8 keyboard.c:713
+ sal dx, 008h ; c1 e2 08 ; 0xf57ec
+ movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xf57ef
+ or dx, ax ; 09 c2 ; 0xf57f3
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf57f5
+ and word [bp+01eh], strict byte 0ffbfh ; 83 66 1e bf ; 0xf57f8 keyboard.c:714
+ jmp near 05996h ; e9 97 01 ; 0xf57fc keyboard.c:715
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf57ff keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5802
+ mov es, ax ; 8e c0 ; 0xf5805
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf5807
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf580a keyboard.c:719
+ mov dl, al ; 88 c2 ; 0xf580d
+ jmp short 057ach ; eb 9b ; 0xf580f
+ mov al, byte [bp+010h] ; 8a 46 10 ; 0xf5811 keyboard.c:723
+ movzx dx, al ; 0f b6 d0 ; 0xf5814
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf5817
+ shr ax, 008h ; c1 e8 08 ; 0xf581a
+ xor ah, ah ; 30 e4 ; 0xf581d
+ call 051d2h ; e8 b0 f9 ; 0xf581f
+ test ax, ax ; 85 c0 ; 0xf5822
+ jne short 05833h ; 75 0d ; 0xf5824
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf5826 keyboard.c:724
+ xor al, al ; 30 c0 ; 0xf5829
+ or AL, strict byte 001h ; 0c 01 ; 0xf582b
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf582d
+ jmp near 05996h ; e9 63 01 ; 0xf5830 keyboard.c:726
+ and word [bp+012h], 0ff00h ; 81 66 12 00 ff ; 0xf5833 keyboard.c:727
+ jmp near 05996h ; e9 5b 01 ; 0xf5838 keyboard.c:729
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf583b keyboard.c:742
+ xor al, al ; 30 c0 ; 0xf583e
+ or AL, strict byte 030h ; 0c 30 ; 0xf5840
+ jmp short 0582dh ; eb e9 ; 0xf5842
+ mov byte [bp-008h], 002h ; c6 46 f8 02 ; 0xf5844 keyboard.c:746
+ xor cx, cx ; 31 c9 ; 0xf5848 keyboard.c:747
+ cli ; fa ; 0xf584a keyboard.c:749
+ mov AL, strict byte 0f2h ; b0 f2 ; 0xf584b keyboard.c:750
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf584d
+ out DX, AL ; ee ; 0xf5850
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf5851 keyboard.c:752
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5854 keyboard.c:753
+ in AL, DX ; ec ; 0xf5857
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5858
+ test AL, strict byte 001h ; a8 01 ; 0xf585a
+ jne short 0586bh ; 75 0d ; 0xf585c
+ dec bx ; 4b ; 0xf585e
+ test bx, bx ; 85 db ; 0xf585f
+ jbe short 0586bh ; 76 08 ; 0xf5861
+ mov dx, 00080h ; ba 80 00 ; 0xf5863 keyboard.c:754
+ in AL, DX ; ec ; 0xf5866
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5867
+ jmp short 05854h ; eb e9 ; 0xf5869
+ test bx, bx ; 85 db ; 0xf586b keyboard.c:755
+ jbe short 058afh ; 76 40 ; 0xf586d
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf586f keyboard.c:756
+ in AL, DX ; ec ; 0xf5872
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5873
+ cmp ax, 000fah ; 3d fa 00 ; 0xf5875
+ jne short 058afh ; 75 35 ; 0xf5878
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf587a keyboard.c:758
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf587d keyboard.c:759
+ in AL, DX ; ec ; 0xf5880
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5881
+ test AL, strict byte 001h ; a8 01 ; 0xf5883
+ jne short 05894h ; 75 0d ; 0xf5885
+ dec bx ; 4b ; 0xf5887
+ test bx, bx ; 85 db ; 0xf5888
+ jbe short 05894h ; 76 08 ; 0xf588a
+ mov dx, 00080h ; ba 80 00 ; 0xf588c keyboard.c:760
+ in AL, DX ; ec ; 0xf588f
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5890
+ jmp short 0587dh ; eb e9 ; 0xf5892
+ test bx, bx ; 85 db ; 0xf5894 keyboard.c:761
+ jbe short 058a6h ; 76 0e ; 0xf5896
+ shr cx, 008h ; c1 e9 08 ; 0xf5898 keyboard.c:762
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf589b keyboard.c:763
+ in AL, DX ; ec ; 0xf589e
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf589f
+ sal ax, 008h ; c1 e0 08 ; 0xf58a1
+ or cx, ax ; 09 c1 ; 0xf58a4
+ dec byte [bp-008h] ; fe 4e f8 ; 0xf58a6 keyboard.c:765
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf58a9
+ jnbe short 0587ah ; 77 cb ; 0xf58ad
+ mov word [bp+00ch], cx ; 89 4e 0c ; 0xf58af keyboard.c:768
+ jmp near 05996h ; e9 e1 00 ; 0xf58b2 keyboard.c:769
+ push strict byte 00001h ; 6a 01 ; 0xf58b5 keyboard.c:772
+ mov cx, ss ; 8c d1 ; 0xf58b7
+ lea bx, [bp-00ah] ; 8d 5e f6 ; 0xf58b9
+ mov dx, ss ; 8c d2 ; 0xf58bc
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf58be
+ call 05627h ; e8 63 fd ; 0xf58c1
+ test ax, ax ; 85 c0 ; 0xf58c4
+ jne short 058d3h ; 75 0b ; 0xf58c6
+ push 00621h ; 68 21 06 ; 0xf58c8 keyboard.c:773
+ push strict byte 00007h ; 6a 07 ; 0xf58cb
+ call 01a14h ; e8 44 c1 ; 0xf58cd
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf58d0
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf58d3 keyboard.c:775
+ je near 0579fh ; 0f 84 c4 fe ; 0xf58d7
+ cmp byte [bp-00ah], 0f0h ; 80 7e f6 f0 ; 0xf58db
+ je near 0579bh ; 0f 84 b8 fe ; 0xf58df
+ jmp near 0579fh ; e9 b9 fe ; 0xf58e3
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf58e6 keyboard.c:782
+ mov word [bp+01eh], ax ; 89 46 1e ; 0xf58e9
+ push strict byte 00000h ; 6a 00 ; 0xf58ec keyboard.c:783
+ mov cx, ss ; 8c d1 ; 0xf58ee
+ lea bx, [bp-00ah] ; 8d 5e f6 ; 0xf58f0
+ mov dx, ss ; 8c d2 ; 0xf58f3
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf58f5
+ call 05627h ; e8 2c fd ; 0xf58f8
+ test ax, ax ; 85 c0 ; 0xf58fb
+ je near 057cbh ; 0f 84 ca fe ; 0xf58fd
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf5901 keyboard.c:787
+ je near 057e8h ; 0f 84 df fe ; 0xf5905
+ cmp byte [bp-00ah], 0f0h ; 80 7e f6 f0 ; 0xf5909
+ je near 057e4h ; 0f 84 d3 fe ; 0xf590d
+ jmp near 057e8h ; e9 d4 fe ; 0xf5911
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf5914 keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5917
+ mov es, ax ; 8e c0 ; 0xf591a
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf591c
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf591f keyboard.c:795
+ mov dl, al ; 88 c2 ; 0xf5922
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf5924
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5927 keyboard.c:38
+ mov bl, byte [es:bx] ; 26 8a 1f ; 0xf592a
+ and bl, 073h ; 80 e3 73 ; 0xf592d keyboard.c:39
+ mov si, 00096h ; be 96 00 ; 0xf5930 keyboard.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf5933
+ and AL, strict byte 00ch ; 24 0c ; 0xf5936 keyboard.c:39
+ or bl, al ; 08 c3 ; 0xf5938
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf593a keyboard.c:798
+ xor dh, dh ; 30 f6 ; 0xf593d
+ movzx ax, bl ; 0f b6 c3 ; 0xf593f
+ sal ax, 008h ; c1 e0 08 ; 0xf5942
+ jmp near 057aah ; e9 62 fe ; 0xf5945
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf5948 keyboard.c:803
+ xor ah, ah ; 30 e4 ; 0xf594b
+ or ah, 080h ; 80 cc 80 ; 0xf594d
+ jmp near 0582dh ; e9 da fe ; 0xf5950
+ mov bx, 00db2h ; bb b2 0d ; 0xf5953 keyboard.c:818
+ mov cx, ds ; 8c d9 ; 0xf5956
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5958
+ call 019d3h ; e8 75 c0 ; 0xf595b
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf595e
+ shr ax, 008h ; c1 e8 08 ; 0xf5961
+ push ax ; 50 ; 0xf5964
+ push 00645h ; 68 45 06 ; 0xf5965
+ push strict byte 00004h ; 6a 04 ; 0xf5968
+ call 01a14h ; e8 a7 c0 ; 0xf596a
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf596d
+ mov bx, 00db2h ; bb b2 0d ; 0xf5970 keyboard.c:819
+ mov cx, ds ; 8c d9 ; 0xf5973
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5975
+ call 019d3h ; e8 58 c0 ; 0xf5978
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf597b
+ push ax ; 50 ; 0xf597e
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf597f
+ push ax ; 50 ; 0xf5982
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf5983
+ push ax ; 50 ; 0xf5986
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf5987
+ push ax ; 50 ; 0xf598a
+ push 0066dh ; 68 6d 06 ; 0xf598b
+ push strict byte 00004h ; 6a 04 ; 0xf598e
+ call 01a14h ; e8 81 c0 ; 0xf5990
+ add sp, strict byte 0000ch ; 83 c4 0c ; 0xf5993
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf5996 keyboard.c:822
+ pop di ; 5f ; 0xf5999
+ pop si ; 5e ; 0xf599a
+ pop bp ; 5d ; 0xf599b
+ retn ; c3 ; 0xf599c
+ ; disGetNextSymbol 0xf599d LB 0x46a8 -> off=0x0 cb=00000000000000b3 uValue=00000000000f439d 'set_geom_lba'
+set_geom_lba: ; 0xf599d LB 0xb3
+ push bx ; 53 ; 0xf599d disk.c:115
+ push cx ; 51 ; 0xf599e
+ push si ; 56 ; 0xf599f
+ push di ; 57 ; 0xf59a0
+ enter 00008h, 000h ; c8 08 00 00 ; 0xf59a1
+ mov di, ax ; 89 c7 ; 0xf59a5
+ mov es, dx ; 8e c2 ; 0xf59a7
+ mov dword [bp-008h], strict dword 0007e0000h ; 66 c7 46 f8 00 00 7e 00 ; 0xf59a9 disk.c:117
+ mov word [bp-002h], 000ffh ; c7 46 fe ff 00 ; 0xf59b1 disk.c:119
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf59b6 disk.c:122
+ mov bx, word [bp+010h] ; 8b 5e 10 ; 0xf59b9
+ mov cx, word [bp+00eh] ; 8b 4e 0e ; 0xf59bc
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf59bf
+ mov si, strict word 00020h ; be 20 00 ; 0xf59c2
+ call 09f90h ; e8 c8 45 ; 0xf59c5
+ test ax, ax ; 85 c0 ; 0xf59c8
+ jne short 059d8h ; 75 0c ; 0xf59ca
+ test bx, bx ; 85 db ; 0xf59cc
+ jne short 059d8h ; 75 08 ; 0xf59ce
+ test cx, cx ; 85 c9 ; 0xf59d0
+ jne short 059d8h ; 75 04 ; 0xf59d2
+ test dx, dx ; 85 d2 ; 0xf59d4
+ je short 059dfh ; 74 07 ; 0xf59d6
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf59d8
+ mov si, bx ; 89 de ; 0xf59db
+ jmp short 059e5h ; eb 06 ; 0xf59dd
+ mov bx, word [bp+00ch] ; 8b 5e 0c ; 0xf59df
+ mov si, word [bp+00eh] ; 8b 76 0e ; 0xf59e2
+ mov word [bp-004h], bx ; 89 5e fc ; 0xf59e5
+ xor bx, bx ; 31 db ; 0xf59e8 disk.c:124
+ jmp short 059f1h ; eb 05 ; 0xf59ea
+ cmp bx, strict byte 00004h ; 83 fb 04 ; 0xf59ec
+ jnl short 05a14h ; 7d 23 ; 0xf59ef
+ mov ax, word [bp-006h] ; 8b 46 fa ; 0xf59f1 disk.c:125
+ cmp si, ax ; 39 c6 ; 0xf59f4
+ jc short 05a02h ; 72 0a ; 0xf59f6
+ jne short 05a0bh ; 75 11 ; 0xf59f8
+ mov ax, word [bp-004h] ; 8b 46 fc ; 0xf59fa
+ cmp ax, word [bp-008h] ; 3b 46 f8 ; 0xf59fd
+ jnbe short 05a0bh ; 77 09 ; 0xf5a00
+ mov ax, word [bp-002h] ; 8b 46 fe ; 0xf5a02 disk.c:126
+ inc ax ; 40 ; 0xf5a05
+ shr ax, 1 ; d1 e8 ; 0xf5a06
+ mov word [bp-002h], ax ; 89 46 fe ; 0xf5a08
+ shr word [bp-006h], 1 ; d1 6e fa ; 0xf5a0b disk.c:127
+ rcr word [bp-008h], 1 ; d1 5e f8 ; 0xf5a0e
+ inc bx ; 43 ; 0xf5a11 disk.c:128
+ jmp short 059ech ; eb d8 ; 0xf5a12
+ mov ax, word [bp-002h] ; 8b 46 fe ; 0xf5a14 disk.c:130
+ xor dx, dx ; 31 d2 ; 0xf5a17
+ mov bx, strict word 0003fh ; bb 3f 00 ; 0xf5a19
+ xor cx, cx ; 31 c9 ; 0xf5a1c
+ call 09f10h ; e8 ef 44 ; 0xf5a1e
+ mov bx, ax ; 89 c3 ; 0xf5a21
+ mov cx, dx ; 89 d1 ; 0xf5a23
+ mov ax, word [bp-004h] ; 8b 46 fc ; 0xf5a25
+ mov dx, si ; 89 f2 ; 0xf5a28
+ call 09f50h ; e8 23 45 ; 0xf5a2a
+ mov word [es:di+002h], ax ; 26 89 45 02 ; 0xf5a2d
+ cmp ax, 00400h ; 3d 00 04 ; 0xf5a31 disk.c:131
+ jbe short 05a3ch ; 76 06 ; 0xf5a34
+ mov word [es:di+002h], 00400h ; 26 c7 45 02 00 04 ; 0xf5a36 disk.c:132
+ mov ax, word [bp-002h] ; 8b 46 fe ; 0xf5a3c disk.c:133
+ mov word [es:di], ax ; 26 89 05 ; 0xf5a3f
+ mov word [es:di+004h], strict word 0003fh ; 26 c7 45 04 3f 00 ; 0xf5a42 disk.c:134
+ leave ; c9 ; 0xf5a48 disk.c:135
+ pop di ; 5f ; 0xf5a49
+ pop si ; 5e ; 0xf5a4a
+ pop cx ; 59 ; 0xf5a4b
+ pop bx ; 5b ; 0xf5a4c
+ retn 00008h ; c2 08 00 ; 0xf5a4d
+ ; disGetNextSymbol 0xf5a50 LB 0x45f5 -> off=0x0 cb=00000000000002ed uValue=00000000000f4450 'edd_fill_dpt'
+edd_fill_dpt: ; 0xf5a50 LB 0x2ed
+ push si ; 56 ; 0xf5a50 disk.c:137
+ push di ; 57 ; 0xf5a51
+ enter 0000eh, 000h ; c8 0e 00 00 ; 0xf5a52
+ mov di, ax ; 89 c7 ; 0xf5a56
+ mov word [bp-004h], dx ; 89 56 fc ; 0xf5a58
+ mov word [bp-00eh], bx ; 89 5e f2 ; 0xf5a5b
+ mov word [bp-006h], cx ; 89 4e fa ; 0xf5a5e
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf5a61 disk.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5a64
+ mov es, ax ; 8e c0 ; 0xf5a67
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf5a69
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf5a6c disk.c:49
+ mov es, dx ; 8e c2 ; 0xf5a6f disk.c:142
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf5a71
+ cmp ax, strict word 0001ah ; 3d 1a 00 ; 0xf5a74
+ jnc short 05a7fh ; 73 06 ; 0xf5a77
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf5a79 disk.c:143
+ jmp near 05d37h ; e9 b8 02 ; 0xf5a7c
+ jc near 05b51h ; 0f 82 ce 00 ; 0xf5a7f disk.c:146
+ mov word [es:di], strict word 0001ah ; 26 c7 05 1a 00 ; 0xf5a83 disk.c:149
+ movzx bx, byte [bp+008h] ; 0f b6 5e 08 ; 0xf5a88 disk.c:150
+ imul bx, bx, strict byte 0001ch ; 6b db 1c ; 0xf5a8c
+ mov dx, cx ; 89 ca ; 0xf5a8f
+ add bx, word [bp-00eh] ; 03 5e f2 ; 0xf5a91
+ mov es, cx ; 8e c1 ; 0xf5a94
+ mov ax, word [es:bx+028h] ; 26 8b 47 28 ; 0xf5a96
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5a9a
+ mov word [es:di+018h], ax ; 26 89 45 18 ; 0xf5a9d
+ mov es, cx ; 8e c1 ; 0xf5aa1 disk.c:152
+ cmp byte [es:bx+023h], 005h ; 26 80 7f 23 05 ; 0xf5aa3
+ jne short 05ae2h ; 75 38 ; 0xf5aa8
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5aaa disk.c:153
+ db 066h, 026h, 0c7h, 045h, 002h, 074h, 000h, 0ffh, 0ffh
+ ; mov dword [es:di+002h], strict dword 0ffff0074h ; 66 26 c7 45 02 74 00 ff ff; 0xf5aad
+ db 066h, 026h, 0c7h, 045h, 006h, 0ffh, 0ffh, 0ffh, 0ffh
+ ; mov dword [es:di+006h], strict dword 0ffffffffh ; 66 26 c7 45 06 ff ff ff ff; 0xf5ab6 disk.c:154
+ db 066h, 026h, 0c7h, 045h, 00ah, 0ffh, 0ffh, 0ffh, 0ffh
+ ; mov dword [es:di+00ah], strict dword 0ffffffffh ; 66 26 c7 45 0a ff ff ff ff; 0xf5abf disk.c:155
+ db 066h, 026h, 0c7h, 045h, 00eh, 0ffh, 0ffh, 0ffh, 0ffh
+ ; mov dword [es:di+00eh], strict dword 0ffffffffh ; 66 26 c7 45 0e ff ff ff ff; 0xf5ac8 disk.c:156
+ db 066h, 026h, 0c7h, 045h, 012h, 0ffh, 0ffh, 0ffh, 0ffh
+ ; mov dword [es:di+012h], strict dword 0ffffffffh ; 66 26 c7 45 12 ff ff ff ff; 0xf5ad1 disk.c:157
+ mov word [es:di+016h], strict word 0ffffh ; 26 c7 45 16 ff ff ; 0xf5ada disk.c:158
+ jmp short 05b51h ; eb 6f ; 0xf5ae0 disk.c:159
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5ae2 disk.c:160
+ mov word [es:di+002h], strict word 00002h ; 26 c7 45 02 02 00 ; 0xf5ae5
+ mov es, cx ; 8e c1 ; 0xf5aeb disk.c:161
+ mov ax, word [es:bx+032h] ; 26 8b 47 32 ; 0xf5aed
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5af1
+ mov word [es:di+004h], ax ; 26 89 45 04 ; 0xf5af4
+ mov word [es:di+006h], strict word 00000h ; 26 c7 45 06 00 00 ; 0xf5af8
+ mov es, cx ; 8e c1 ; 0xf5afe disk.c:162
+ mov ax, word [es:bx+030h] ; 26 8b 47 30 ; 0xf5b00
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5b04
+ mov word [es:di+008h], ax ; 26 89 45 08 ; 0xf5b07
+ mov word [es:di+00ah], strict word 00000h ; 26 c7 45 0a 00 00 ; 0xf5b0b
+ mov es, cx ; 8e c1 ; 0xf5b11 disk.c:163
+ mov ax, word [es:bx+034h] ; 26 8b 47 34 ; 0xf5b13
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5b17
+ mov word [es:di+00ch], ax ; 26 89 45 0c ; 0xf5b1a
+ mov word [es:di+00eh], strict word 00000h ; 26 c7 45 0e 00 00 ; 0xf5b1e
+ mov es, cx ; 8e c1 ; 0xf5b24 disk.c:164
+ mov ax, word [es:bx+03ch] ; 26 8b 47 3c ; 0xf5b26
+ mov si, word [es:bx+03ah] ; 26 8b 77 3a ; 0xf5b2a
+ mov cx, word [es:bx+038h] ; 26 8b 4f 38 ; 0xf5b2e
+ mov dx, word [es:bx+036h] ; 26 8b 57 36 ; 0xf5b32
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5b36 disk.c:165
+ mov word [es:di+010h], dx ; 26 89 55 10 ; 0xf5b39
+ mov word [es:di+012h], cx ; 26 89 4d 12 ; 0xf5b3d
+ mov bx, si ; 89 f3 ; 0xf5b41 disk.c:166
+ mov si, strict word 00020h ; be 20 00 ; 0xf5b43
+ call 09f90h ; e8 47 44 ; 0xf5b46
+ mov word [es:di+014h], dx ; 26 89 55 14 ; 0xf5b49
+ mov word [es:di+016h], cx ; 26 89 4d 16 ; 0xf5b4d
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5b51 disk.c:171
+ cmp word [es:di], strict byte 0001eh ; 26 83 3d 1e ; 0xf5b54
+ jc near 05c7ah ; 0f 82 1e 01 ; 0xf5b58
+ mov word [es:di], strict word 0001eh ; 26 c7 05 1e 00 ; 0xf5b5c disk.c:175
+ mov ax, word [bp-008h] ; 8b 46 f8 ; 0xf5b61 disk.c:176
+ mov word [es:di+01ch], ax ; 26 89 45 1c ; 0xf5b64
+ mov word [es:di+01ah], 00356h ; 26 c7 45 1a 56 03 ; 0xf5b68 disk.c:177
+ movzx cx, byte [bp+008h] ; 0f b6 4e 08 ; 0xf5b6e disk.c:180
+ mov ax, cx ; 89 c8 ; 0xf5b72
+ cwd ; 99 ; 0xf5b74
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf5b75
+ sar ax, 1 ; d1 f8 ; 0xf5b77
+ xor ah, ah ; 30 e4 ; 0xf5b79 disk.c:181
+ imul ax, ax, strict byte 00006h ; 6b c0 06 ; 0xf5b7b
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf5b7e
+ mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xf5b81
+ add bx, ax ; 01 c3 ; 0xf5b84
+ mov ax, word [es:bx+00206h] ; 26 8b 87 06 02 ; 0xf5b86
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf5b8b
+ mov ax, word [es:bx+00208h] ; 26 8b 87 08 02 ; 0xf5b8e disk.c:182
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf5b93
+ mov al, byte [es:bx+00205h] ; 26 8a 87 05 02 ; 0xf5b96 disk.c:183
+ mov byte [bp-002h], al ; 88 46 fe ; 0xf5b9b
+ imul bx, cx, strict byte 0001ch ; 6b d9 1c ; 0xf5b9e disk.c:184
+ add bx, word [bp-00eh] ; 03 5e f2 ; 0xf5ba1
+ mov ah, byte [es:bx+026h] ; 26 8a 67 26 ; 0xf5ba4
+ mov al, byte [es:bx+027h] ; 26 8a 47 27 ; 0xf5ba8 disk.c:185
+ test al, al ; 84 c0 ; 0xf5bac disk.c:187
+ jne short 05bb4h ; 75 04 ; 0xf5bae
+ xor bx, bx ; 31 db ; 0xf5bb0
+ jmp short 05bb7h ; eb 03 ; 0xf5bb2
+ mov bx, strict word 00008h ; bb 08 00 ; 0xf5bb4
+ or bl, 010h ; 80 cb 10 ; 0xf5bb7 disk.c:188
+ movzx dx, byte [bp+008h] ; 0f b6 56 08 ; 0xf5bba disk.c:189
+ imul dx, dx, strict byte 0001ch ; 6b d2 1c ; 0xf5bbe
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf5bc1
+ mov si, word [bp-00eh] ; 8b 76 f2 ; 0xf5bc4
+ add si, dx ; 01 d6 ; 0xf5bc7
+ cmp byte [es:si+023h], 005h ; 26 80 7c 23 05 ; 0xf5bc9
+ jne short 05bd3h ; 75 03 ; 0xf5bce
+ or bl, 060h ; 80 cb 60 ; 0xf5bd0 disk.c:190
+ cmp ah, 001h ; 80 fc 01 ; 0xf5bd3 disk.c:194
+ db 00fh, 094h, 0c4h
+ ; sete ah ; 0f 94 c4 ; 0xf5bd6
+ movzx dx, ah ; 0f b6 d4 ; 0xf5bd9
+ or bx, dx ; 09 d3 ; 0xf5bdc
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf5bde disk.c:196
+ db 00fh, 094h, 0c4h
+ ; sete ah ; 0f 94 c4 ; 0xf5be0
+ movzx dx, ah ; 0f b6 d4 ; 0xf5be3
+ or bx, dx ; 09 d3 ; 0xf5be6
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf5be8 disk.c:197
+ jne short 05bf1h ; 75 05 ; 0xf5bea
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf5bec
+ jmp short 05bf3h ; eb 02 ; 0xf5bef
+ xor ax, ax ; 31 c0 ; 0xf5bf1
+ or bx, ax ; 09 c3 ; 0xf5bf3
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf5bf5 disk.c:199
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf5bf8
+ mov si, word [bp-00eh] ; 8b 76 f2 ; 0xf5bfb
+ mov word [es:si+00234h], ax ; 26 89 84 34 02 ; 0xf5bfe
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf5c03 disk.c:200
+ mov word [es:si+00236h], ax ; 26 89 84 36 02 ; 0xf5c06
+ movzx ax, byte [bp+008h] ; 0f b6 46 08 ; 0xf5c0b disk.c:201
+ cwd ; 99 ; 0xf5c0f
+ mov cx, strict word 00002h ; b9 02 00 ; 0xf5c10
+ idiv cx ; f7 f9 ; 0xf5c13
+ or dl, 00eh ; 80 ca 0e ; 0xf5c15
+ sal dx, 004h ; c1 e2 04 ; 0xf5c18
+ mov byte [es:si+00238h], dl ; 26 88 94 38 02 ; 0xf5c1b
+ mov byte [es:si+00239h], 0cbh ; 26 c6 84 39 02 cb ; 0xf5c20 disk.c:202
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf5c26 disk.c:203
+ mov byte [es:si+0023ah], al ; 26 88 84 3a 02 ; 0xf5c29
+ mov word [es:si+0023bh], strict word 00001h ; 26 c7 84 3b 02 01 00 ; 0xf5c2e disk.c:204
+ mov byte [es:si+0023dh], 000h ; 26 c6 84 3d 02 00 ; 0xf5c35 disk.c:206
+ mov word [es:si+0023eh], bx ; 26 89 9c 3e 02 ; 0xf5c3b disk.c:207
+ mov bx, si ; 89 f3 ; 0xf5c40 disk.c:208
+ mov word [es:bx+00240h], strict word 00000h ; 26 c7 87 40 02 00 00 ; 0xf5c42
+ mov byte [es:bx+00242h], 011h ; 26 c6 87 42 02 11 ; 0xf5c49 disk.c:209
+ xor al, al ; 30 c0 ; 0xf5c4f disk.c:211
+ xor ah, ah ; 30 e4 ; 0xf5c51 disk.c:212
+ jmp short 05c5ah ; eb 05 ; 0xf5c53
+ cmp ah, 00fh ; 80 fc 0f ; 0xf5c55
+ jnc short 05c6dh ; 73 13 ; 0xf5c58
+ movzx bx, ah ; 0f b6 dc ; 0xf5c5a disk.c:213
+ add bx, 00356h ; 81 c3 56 03 ; 0xf5c5d
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf5c61 disk.c:38
+ mov dl, byte [es:bx] ; 26 8a 17 ; 0xf5c64
+ add al, dl ; 00 d0 ; 0xf5c67 disk.c:39
+ db 0feh, 0c4h
+ ; inc ah ; fe c4 ; 0xf5c69 disk.c:213
+ jmp short 05c55h ; eb e8 ; 0xf5c6b
+ neg al ; f6 d8 ; 0xf5c6d disk.c:214
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf5c6f disk.c:215
+ mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xf5c72
+ mov byte [es:bx+00243h], al ; 26 88 87 43 02 ; 0xf5c75
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5c7a disk.c:219
+ cmp word [es:di], strict byte 00042h ; 26 83 3d 42 ; 0xf5c7d
+ jc near 05d35h ; 0f 82 b0 00 ; 0xf5c81
+ movzx ax, byte [bp+008h] ; 0f b6 46 08 ; 0xf5c85 disk.c:223
+ cwd ; 99 ; 0xf5c89
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf5c8a
+ sar ax, 1 ; d1 f8 ; 0xf5c8c
+ xor ah, ah ; 30 e4 ; 0xf5c8e disk.c:224
+ imul ax, ax, strict byte 00006h ; 6b c0 06 ; 0xf5c90
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf5c93
+ mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xf5c96
+ add bx, ax ; 01 c3 ; 0xf5c99
+ mov al, byte [es:bx+00204h] ; 26 8a 87 04 02 ; 0xf5c9b
+ mov dx, word [es:bx+00206h] ; 26 8b 97 06 02 ; 0xf5ca0 disk.c:225
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5ca5 disk.c:227
+ mov word [es:di], strict word 00042h ; 26 c7 05 42 00 ; 0xf5ca8
+ db 066h, 026h, 0c7h, 045h, 01eh, 0ddh, 0beh, 024h, 000h
+ ; mov dword [es:di+01eh], strict dword 00024beddh ; 66 26 c7 45 1e dd be 24 00; 0xf5cad disk.c:228
+ mov word [es:di+022h], strict word 00000h ; 26 c7 45 22 00 00 ; 0xf5cb6 disk.c:231
+ test al, al ; 84 c0 ; 0xf5cbc disk.c:233
+ jne short 05cc9h ; 75 09 ; 0xf5cbe
+ db 066h, 026h, 0c7h, 045h, 024h, 049h, 053h, 041h, 020h
+ ; mov dword [es:di+024h], strict dword 020415349h ; 66 26 c7 45 24 49 53 41 20; 0xf5cc0 disk.c:234
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5cc9 disk.c:242
+ db 066h, 026h, 0c7h, 045h, 028h, 041h, 054h, 041h, 020h
+ ; mov dword [es:di+028h], strict dword 020415441h ; 66 26 c7 45 28 41 54 41 20; 0xf5ccc
+ db 066h, 026h, 0c7h, 045h, 02ch, 020h, 020h, 020h, 020h
+ ; mov dword [es:di+02ch], strict dword 020202020h ; 66 26 c7 45 2c 20 20 20 20; 0xf5cd5 disk.c:246
+ test al, al ; 84 c0 ; 0xf5cde disk.c:251
+ jne short 05cf5h ; 75 13 ; 0xf5ce0
+ mov word [es:di+030h], dx ; 26 89 55 30 ; 0xf5ce2 disk.c:252
+ db 066h, 026h, 0c7h, 045h, 032h, 000h, 000h, 000h, 000h
+ ; mov dword [es:di+032h], strict dword 000000000h ; 66 26 c7 45 32 00 00 00 00; 0xf5ce6 disk.c:253
+ mov word [es:di+036h], strict word 00000h ; 26 c7 45 36 00 00 ; 0xf5cef disk.c:254
+ mov al, byte [bp+008h] ; 8a 46 08 ; 0xf5cf5 disk.c:259
+ and AL, strict byte 001h ; 24 01 ; 0xf5cf8
+ xor ah, ah ; 30 e4 ; 0xf5cfa
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5cfc
+ mov word [es:di+038h], ax ; 26 89 45 38 ; 0xf5cff
+ db 066h, 026h, 0c7h, 045h, 03ah, 000h, 000h, 000h, 000h
+ ; mov dword [es:di+03ah], strict dword 000000000h ; 66 26 c7 45 3a 00 00 00 00; 0xf5d03 disk.c:260
+ mov word [es:di+03eh], strict word 00000h ; 26 c7 45 3e 00 00 ; 0xf5d0c disk.c:261
+ xor al, al ; 30 c0 ; 0xf5d12 disk.c:263
+ mov AH, strict byte 01eh ; b4 1e ; 0xf5d14 disk.c:264
+ jmp short 05d1dh ; eb 05 ; 0xf5d16
+ cmp ah, 040h ; 80 fc 40 ; 0xf5d18
+ jnc short 05d2ch ; 73 0f ; 0xf5d1b
+ movzx bx, ah ; 0f b6 dc ; 0xf5d1d disk.c:265
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5d20
+ add bx, di ; 01 fb ; 0xf5d23
+ add al, byte [es:bx] ; 26 02 07 ; 0xf5d25
+ db 0feh, 0c4h
+ ; inc ah ; fe c4 ; 0xf5d28
+ jmp short 05d18h ; eb ec ; 0xf5d2a
+ neg al ; f6 d8 ; 0xf5d2c disk.c:266
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5d2e disk.c:267
+ mov byte [es:di+041h], al ; 26 88 45 41 ; 0xf5d31
+ xor ax, ax ; 31 c0 ; 0xf5d35 disk.c:269
+ leave ; c9 ; 0xf5d37 disk.c:270
+ pop di ; 5f ; 0xf5d38
+ pop si ; 5e ; 0xf5d39
+ retn 00002h ; c2 02 00 ; 0xf5d3a
+ ; disGetNextSymbol 0xf5d3d LB 0x4308 -> off=0x32 cb=000000000000042a uValue=00000000000f476f 'int13_harddisk'
+ db 0fdh, 05dh, 024h, 05eh, 04dh, 05eh, 04dh, 05eh, 04dh, 05eh, 032h, 060h, 05bh, 061h, 05bh, 061h
+ db 04bh, 060h, 038h, 061h, 05bh, 061h, 05bh, 061h, 038h, 061h, 038h, 061h, 05bh, 061h, 05bh, 061h
+ db 0bfh, 060h, 038h, 061h, 05bh, 061h, 05bh, 061h, 038h, 061h, 0efh, 060h, 05bh, 061h, 05bh, 061h
+ db 05bh, 061h
+int13_harddisk: ; 0xf5d6f LB 0x42a
+ push bp ; 55 ; 0xf5d6f disk.c:272
+ mov bp, sp ; 89 e5 ; 0xf5d70
+ sub sp, strict byte 00010h ; 83 ec 10 ; 0xf5d72
+ or byte [bp+01dh], 002h ; 80 4e 1d 02 ; 0xf5d75 disk.c:283
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf5d79 disk.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf5d7c
+ mov es, dx ; 8e c2 ; 0xf5d7f
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf5d81
+ mov si, 00122h ; be 22 01 ; 0xf5d84 disk.c:49
+ mov word [bp-004h], dx ; 89 56 fc ; 0xf5d87
+ mov bx, 0008eh ; bb 8e 00 ; 0xf5d8a disk.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf5d8d
+ mov dx, word [bp+00eh] ; 8b 56 0e ; 0xf5d91 disk.c:289
+ xor dh, dh ; 30 f6 ; 0xf5d94
+ cmp dx, 00080h ; 81 fa 80 00 ; 0xf5d96
+ jc short 05da2h ; 72 06 ; 0xf5d9a
+ cmp dx, 00090h ; 81 fa 90 00 ; 0xf5d9c
+ jc short 05dc0h ; 72 1e ; 0xf5da0
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf5da2 disk.c:290
+ xor ah, ah ; 30 e4 ; 0xf5da5
+ push ax ; 50 ; 0xf5da7
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5da8
+ shr ax, 008h ; c1 e8 08 ; 0xf5dab
+ push ax ; 50 ; 0xf5dae
+ push 00690h ; 68 90 06 ; 0xf5daf
+ push 0069fh ; 68 9f 06 ; 0xf5db2
+ push strict byte 00004h ; 6a 04 ; 0xf5db5
+ call 01a14h ; e8 5a bc ; 0xf5db7
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf5dba
+ jmp near 06176h ; e9 b6 03 ; 0xf5dbd disk.c:291
+ mov dx, word [bp+00eh] ; 8b 56 0e ; 0xf5dc0 disk.c:295
+ xor dh, dh ; 30 f6 ; 0xf5dc3
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5dc5
+ mov bx, si ; 89 f3 ; 0xf5dc8
+ add bx, dx ; 01 d3 ; 0xf5dca
+ mov bl, byte [es:bx+00163h] ; 26 8a 9f 63 01 ; 0xf5dcc
+ mov byte [bp-002h], bl ; 88 5e fe ; 0xf5dd1
+ cmp bl, 010h ; 80 fb 10 ; 0xf5dd4 disk.c:298
+ jc short 05de9h ; 72 10 ; 0xf5dd7
+ push dx ; 52 ; 0xf5dd9 disk.c:299
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5dda
+ shr ax, 008h ; c1 e8 08 ; 0xf5ddd
+ push ax ; 50 ; 0xf5de0
+ push 00690h ; 68 90 06 ; 0xf5de1
+ push 006cah ; 68 ca 06 ; 0xf5de4
+ jmp short 05db5h ; eb cc ; 0xf5de7
+ mov bx, word [bp+016h] ; 8b 5e 16 ; 0xf5de9 disk.c:303
+ shr bx, 008h ; c1 eb 08 ; 0xf5dec
+ cmp bx, strict byte 00018h ; 83 fb 18 ; 0xf5def
+ jnbe near 0615bh ; 0f 87 65 03 ; 0xf5df2
+ add bx, bx ; 01 db ; 0xf5df6
+ jmp word [cs:bx+05d3dh] ; 2e ff a7 3d 5d ; 0xf5df8
+ cmp byte [bp-002h], 008h ; 80 7e fe 08 ; 0xf5dfd disk.c:308
+ jnc near 05e0ch ; 0f 83 07 00 ; 0xf5e01
+ movzx ax, byte [bp-002h] ; 0f b6 46 fe ; 0xf5e05 disk.c:310
+ call 01e1dh ; e8 11 c0 ; 0xf5e09
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf5e0c disk.c:311
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf5e10
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5e13
+ mov es, ax ; 8e c0 ; 0xf5e16
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf5e18
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf5e1c
+ mov sp, bp ; 89 ec ; 0xf5e20
+ pop bp ; 5d ; 0xf5e22
+ retn ; c3 ; 0xf5e23
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf5e24 disk.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5e27
+ mov es, ax ; 8e c0 ; 0xf5e2a
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf5e2c
+ mov bx, word [bp+016h] ; 8b 5e 16 ; 0xf5e2f disk.c:316
+ xor bh, bh ; 30 ff ; 0xf5e32
+ movzx dx, al ; 0f b6 d0 ; 0xf5e34
+ sal dx, 008h ; c1 e2 08 ; 0xf5e37
+ or bx, dx ; 09 d3 ; 0xf5e3a
+ mov word [bp+016h], bx ; 89 5e 16 ; 0xf5e3c
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf5e3f disk.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf5e42
+ test al, al ; 84 c0 ; 0xf5e46 disk.c:319
+ je short 05e10h ; 74 c6 ; 0xf5e48
+ jmp near 06192h ; e9 45 03 ; 0xf5e4a
+ mov dx, word [bp+016h] ; 8b 56 16 ; 0xf5e4d disk.c:327
+ xor dh, dh ; 30 f6 ; 0xf5e50
+ mov word [bp-00ch], dx ; 89 56 f4 ; 0xf5e52
+ mov di, word [bp+014h] ; 8b 7e 14 ; 0xf5e55 disk.c:328
+ shr di, 008h ; c1 ef 08 ; 0xf5e58
+ mov dx, word [bp+014h] ; 8b 56 14 ; 0xf5e5b disk.c:329
+ xor dh, dh ; 30 f6 ; 0xf5e5e
+ sal dx, 002h ; c1 e2 02 ; 0xf5e60
+ xor dl, dl ; 30 d2 ; 0xf5e63
+ and dh, 003h ; 80 e6 03 ; 0xf5e65
+ or di, dx ; 09 d7 ; 0xf5e68
+ mov dx, word [bp+014h] ; 8b 56 14 ; 0xf5e6a disk.c:330
+ and dx, strict byte 0003fh ; 83 e2 3f ; 0xf5e6d
+ mov word [bp-006h], dx ; 89 56 fa ; 0xf5e70
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf5e73 disk.c:331
+ shr dx, 008h ; c1 ea 08 ; 0xf5e76
+ mov word [bp-008h], dx ; 89 56 f8 ; 0xf5e79
+ cmp word [bp-00ch], 00080h ; 81 7e f4 80 00 ; 0xf5e7c disk.c:334
+ jnbe short 05e89h ; 77 06 ; 0xf5e81
+ cmp word [bp-00ch], strict byte 00000h ; 83 7e f4 00 ; 0xf5e83
+ jne short 05each ; 75 23 ; 0xf5e87
+ mov bx, 00db2h ; bb b2 0d ; 0xf5e89 disk.c:335
+ mov cx, ds ; 8c d9 ; 0xf5e8c
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5e8e
+ call 019d3h ; e8 3f bb ; 0xf5e91
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5e94
+ shr ax, 008h ; c1 e8 08 ; 0xf5e97
+ push ax ; 50 ; 0xf5e9a
+ push 00690h ; 68 90 06 ; 0xf5e9b
+ push 006fch ; 68 fc 06 ; 0xf5e9e
+ push strict byte 00004h ; 6a 04 ; 0xf5ea1
+ call 01a14h ; e8 6e bb ; 0xf5ea3
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf5ea6
+ jmp near 06176h ; e9 ca 02 ; 0xf5ea9 disk.c:336
+ movzx dx, byte [bp-002h] ; 0f b6 56 fe ; 0xf5eac disk.c:340
+ imul dx, dx, strict byte 0001ch ; 6b d2 1c ; 0xf5eb0
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5eb3
+ mov bx, si ; 89 f3 ; 0xf5eb6
+ add bx, dx ; 01 d3 ; 0xf5eb8
+ mov dx, word [es:bx+02ch] ; 26 8b 57 2c ; 0xf5eba
+ mov word [bp-010h], dx ; 89 56 f0 ; 0xf5ebe
+ mov cx, word [es:bx+02ah] ; 26 8b 4f 2a ; 0xf5ec1 disk.c:341
+ mov dx, word [es:bx+02eh] ; 26 8b 57 2e ; 0xf5ec5 disk.c:342
+ mov word [bp-00ah], dx ; 89 56 f6 ; 0xf5ec9
+ cmp di, word [bp-010h] ; 3b 7e f0 ; 0xf5ecc disk.c:345
+ jnc short 05edeh ; 73 0d ; 0xf5ecf
+ cmp cx, word [bp-008h] ; 3b 4e f8 ; 0xf5ed1
+ jbe short 05edeh ; 76 08 ; 0xf5ed4
+ mov dx, word [bp-006h] ; 8b 56 fa ; 0xf5ed6
+ cmp dx, word [bp-00ah] ; 3b 56 f6 ; 0xf5ed9
+ jbe short 05f0ch ; 76 2e ; 0xf5edc
+ mov bx, 00db2h ; bb b2 0d ; 0xf5ede disk.c:346
+ mov cx, ds ; 8c d9 ; 0xf5ee1
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5ee3
+ call 019d3h ; e8 ea ba ; 0xf5ee6
+ push dword [bp-008h] ; 66 ff 76 f8 ; 0xf5ee9
+ push di ; 57 ; 0xf5eed
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf5eee
+ xor ah, ah ; 30 e4 ; 0xf5ef1
+ push ax ; 50 ; 0xf5ef3
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5ef4
+ shr ax, 008h ; c1 e8 08 ; 0xf5ef7
+ push ax ; 50 ; 0xf5efa
+ push 00690h ; 68 90 06 ; 0xf5efb
+ push 00724h ; 68 24 07 ; 0xf5efe
+ push strict byte 00004h ; 6a 04 ; 0xf5f01
+ call 01a14h ; e8 0e bb ; 0xf5f03
+ add sp, strict byte 00010h ; 83 c4 10 ; 0xf5f06
+ jmp near 06176h ; e9 6a 02 ; 0xf5f09 disk.c:347
+ mov dx, word [bp+016h] ; 8b 56 16 ; 0xf5f0c disk.c:351
+ shr dx, 008h ; c1 ea 08 ; 0xf5f0f
+ cmp dx, strict byte 00004h ; 83 fa 04 ; 0xf5f12
+ jne short 05f1ah ; 75 03 ; 0xf5f15
+ jmp near 05e0ch ; e9 f2 fe ; 0xf5f17 disk.c:352
+ movzx dx, byte [bp-002h] ; 0f b6 56 fe ; 0xf5f1a disk.c:356
+ imul dx, dx, strict byte 0001ch ; 6b d2 1c ; 0xf5f1e
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5f21
+ mov bx, si ; 89 f3 ; 0xf5f24
+ add bx, dx ; 01 d3 ; 0xf5f26
+ cmp cx, word [es:bx+030h] ; 26 3b 4f 30 ; 0xf5f28
+ jne short 05f3dh ; 75 0f ; 0xf5f2c
+ mov dx, word [es:bx+034h] ; 26 8b 57 34 ; 0xf5f2e
+ cmp dx, word [bp-00ah] ; 3b 56 f6 ; 0xf5f32
+ jne short 05f3dh ; 75 06 ; 0xf5f35
+ cmp byte [bp-002h], 008h ; 80 7e fe 08 ; 0xf5f37
+ jc short 05f6ch ; 72 2f ; 0xf5f3b
+ mov ax, di ; 89 f8 ; 0xf5f3d disk.c:357
+ xor dx, dx ; 31 d2 ; 0xf5f3f
+ mov bx, cx ; 89 cb ; 0xf5f41
+ xor cx, cx ; 31 c9 ; 0xf5f43
+ call 09f10h ; e8 c8 3f ; 0xf5f45
+ xor bx, bx ; 31 db ; 0xf5f48
+ add ax, word [bp-008h] ; 03 46 f8 ; 0xf5f4a
+ adc dx, bx ; 11 da ; 0xf5f4d
+ mov bx, word [bp-00ah] ; 8b 5e f6 ; 0xf5f4f
+ xor cx, cx ; 31 c9 ; 0xf5f52
+ call 09f10h ; e8 b9 3f ; 0xf5f54
+ xor bx, bx ; 31 db ; 0xf5f57
+ add ax, word [bp-006h] ; 03 46 fa ; 0xf5f59
+ adc dx, bx ; 11 da ; 0xf5f5c
+ add ax, strict word 0ffffh ; 05 ff ff ; 0xf5f5e
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf5f61
+ mov ax, dx ; 89 d0 ; 0xf5f64
+ adc ax, strict word 0ffffh ; 15 ff ff ; 0xf5f66
+ mov word [bp-006h], bx ; 89 5e fa ; 0xf5f69 disk.c:358
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5f6c disk.c:365
+ db 066h, 026h, 0c7h, 044h, 018h, 000h, 000h, 000h, 000h
+ ; mov dword [es:si+018h], strict dword 000000000h ; 66 26 c7 44 18 00 00 00 00; 0xf5f6f
+ mov word [es:si+01ch], strict word 00000h ; 26 c7 44 1c 00 00 ; 0xf5f78 disk.c:366
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf5f7e disk.c:369
+ mov word [es:si], dx ; 26 89 14 ; 0xf5f81
+ mov word [es:si+002h], ax ; 26 89 44 02 ; 0xf5f84
+ db 066h, 026h, 0c7h, 044h, 004h, 000h, 000h, 000h, 000h
+ ; mov dword [es:si+004h], strict dword 000000000h ; 66 26 c7 44 04 00 00 00 00; 0xf5f88
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf5f91 disk.c:370
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf5f94
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf5f97
+ mov word [es:si+00ah], dx ; 26 89 54 0a ; 0xf5f9b
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf5f9f disk.c:371
+ mov word [es:si+00eh], ax ; 26 89 44 0e ; 0xf5fa2
+ mov word [es:si+010h], 00200h ; 26 c7 44 10 00 02 ; 0xf5fa6 disk.c:372
+ mov word [es:si+012h], di ; 26 89 7c 12 ; 0xf5fac disk.c:373
+ mov ax, word [bp-008h] ; 8b 46 f8 ; 0xf5fb0 disk.c:374
+ mov word [es:si+014h], ax ; 26 89 44 14 ; 0xf5fb3
+ mov ax, word [bp-006h] ; 8b 46 fa ; 0xf5fb7 disk.c:375
+ mov word [es:si+016h], ax ; 26 89 44 16 ; 0xf5fba
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf5fbe disk.c:376
+ mov byte [es:si+00ch], al ; 26 88 44 0c ; 0xf5fc1
+ movzx ax, byte [bp-002h] ; 0f b6 46 fe ; 0xf5fc5 disk.c:378
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf5fc9
+ mov bx, si ; 89 f3 ; 0xf5fcc
+ add bx, ax ; 01 c3 ; 0xf5fce
+ movzx ax, byte [es:bx+022h] ; 26 0f b6 47 22 ; 0xf5fd0
+ mov bx, ax ; 89 c3 ; 0xf5fd5
+ sal bx, 002h ; c1 e3 02 ; 0xf5fd7
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5fda
+ shr ax, 008h ; c1 e8 08 ; 0xf5fdd
+ add ax, ax ; 01 c0 ; 0xf5fe0
+ add bx, ax ; 01 c3 ; 0xf5fe2
+ push ES ; 06 ; 0xf5fe4
+ push si ; 56 ; 0xf5fe5
+ call word [word bx+0007eh] ; ff 97 7e 00 ; 0xf5fe6
+ mov dx, ax ; 89 c2 ; 0xf5fea
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5fec disk.c:381
+ xor al, al ; 30 c0 ; 0xf5fef
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5ff1
+ mov bx, word [es:si+018h] ; 26 8b 5c 18 ; 0xf5ff4
+ or bx, ax ; 09 c3 ; 0xf5ff8
+ mov word [bp+016h], bx ; 89 5e 16 ; 0xf5ffa
+ test dl, dl ; 84 d2 ; 0xf5ffd disk.c:383
+ je near 05e0ch ; 0f 84 09 fe ; 0xf5fff
+ mov bx, 00db2h ; bb b2 0d ; 0xf6003 disk.c:384
+ mov cx, ds ; 8c d9 ; 0xf6006
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6008
+ call 019d3h ; e8 c5 b9 ; 0xf600b
+ movzx ax, dl ; 0f b6 c2 ; 0xf600e
+ push ax ; 50 ; 0xf6011
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6012
+ shr ax, 008h ; c1 e8 08 ; 0xf6015
+ push ax ; 50 ; 0xf6018
+ push 00690h ; 68 90 06 ; 0xf6019
+ push 0076bh ; 68 6b 07 ; 0xf601c
+ push strict byte 00004h ; 6a 04 ; 0xf601f
+ call 01a14h ; e8 f0 b9 ; 0xf6021
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf6024
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6027 disk.c:385
+ xor ah, ah ; 30 e4 ; 0xf602a
+ or ah, 00ch ; 80 cc 0c ; 0xf602c
+ jmp near 0617eh ; e9 4c 01 ; 0xf602f disk.c:386
+ mov bx, 00db2h ; bb b2 0d ; 0xf6032 disk.c:393
+ mov cx, ds ; 8c d9 ; 0xf6035
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6037
+ call 019d3h ; e8 96 b9 ; 0xf603a
+ push 0078ch ; 68 8c 07 ; 0xf603d
+ push strict byte 00004h ; 6a 04 ; 0xf6040
+ call 01a14h ; e8 cf b9 ; 0xf6042
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf6045
+ jmp near 05e0ch ; e9 c1 fd ; 0xf6048 disk.c:394
+ movzx ax, byte [bp-002h] ; 0f b6 46 fe ; 0xf604b disk.c:400
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf604f
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf6052
+ mov bx, si ; 89 f3 ; 0xf6055
+ add bx, ax ; 01 c3 ; 0xf6057
+ mov ax, word [es:bx+02ch] ; 26 8b 47 2c ; 0xf6059
+ mov cx, word [es:bx+02ah] ; 26 8b 4f 2a ; 0xf605d disk.c:401
+ mov dx, word [es:bx+02eh] ; 26 8b 57 2e ; 0xf6061 disk.c:402
+ mov word [bp-00ah], dx ; 89 56 f6 ; 0xf6065
+ movzx dx, byte [es:si+001e2h] ; 26 0f b6 94 e2 01 ; 0xf6068 disk.c:404
+ mov word [bp-00ch], dx ; 89 56 f4 ; 0xf606e
+ mov byte [bp+016h], 000h ; c6 46 16 00 ; 0xf6071 disk.c:407
+ mov dx, word [bp+014h] ; 8b 56 14 ; 0xf6075 disk.c:408
+ xor dh, dh ; 30 f6 ; 0xf6078
+ dec ax ; 48 ; 0xf607a disk.c:406
+ mov bx, ax ; 89 c3 ; 0xf607b
+ xor bh, ah ; 30 e7 ; 0xf607d
+ sal bx, 008h ; c1 e3 08 ; 0xf607f
+ or dx, bx ; 09 da ; 0xf6082
+ mov word [bp+014h], dx ; 89 56 14 ; 0xf6084
+ mov dx, ax ; 89 c2 ; 0xf6087 disk.c:409
+ shr dx, 002h ; c1 ea 02 ; 0xf6089
+ and dl, 0c0h ; 80 e2 c0 ; 0xf608c
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf608f
+ and AL, strict byte 03fh ; 24 3f ; 0xf6092
+ or dl, al ; 08 c2 ; 0xf6094
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf6096
+ mov al, dl ; 88 d0 ; 0xf6099
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf609b
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf609e disk.c:410
+ xor dh, dh ; 30 f6 ; 0xf60a1
+ mov ax, cx ; 89 c8 ; 0xf60a3
+ sal ax, 008h ; c1 e0 08 ; 0xf60a5
+ sub ax, 00100h ; 2d 00 01 ; 0xf60a8
+ or dx, ax ; 09 c2 ; 0xf60ab
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf60ad
+ mov ax, dx ; 89 d0 ; 0xf60b0 disk.c:411
+ xor al, dl ; 30 d0 ; 0xf60b2
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf60b4
+ or dx, ax ; 09 c2 ; 0xf60b7
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf60b9
+ jmp near 05e0ch ; e9 4d fd ; 0xf60bc disk.c:416
+ movzx ax, byte [bp-002h] ; 0f b6 46 fe ; 0xf60bf disk.c:423
+ cwd ; 99 ; 0xf60c3
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf60c4
+ sar ax, 1 ; d1 f8 ; 0xf60c6
+ imul ax, ax, strict byte 00006h ; 6b c0 06 ; 0xf60c8
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf60cb
+ add si, ax ; 01 c6 ; 0xf60ce
+ mov dx, word [es:si+00206h] ; 26 8b 94 06 02 ; 0xf60d0
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf60d5
+ in AL, DX ; ec ; 0xf60d8
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf60d9
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf60db disk.c:424
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf60dd
+ jne short 060e4h ; 75 03 ; 0xf60df
+ jmp near 05e0ch ; e9 28 fd ; 0xf60e1 disk.c:425
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf60e4 disk.c:427
+ xor ah, ah ; 30 e4 ; 0xf60e7
+ or ah, 0aah ; 80 cc aa ; 0xf60e9
+ jmp near 0617eh ; e9 8f 00 ; 0xf60ec
+ movzx ax, byte [bp-002h] ; 0f b6 46 fe ; 0xf60ef disk.c:435
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf60f3
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf60f6
+ add si, ax ; 01 c6 ; 0xf60f9
+ mov di, word [es:si+032h] ; 26 8b 7c 32 ; 0xf60fb
+ mov ax, word [es:si+030h] ; 26 8b 44 30 ; 0xf60ff disk.c:436
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf6103
+ mov ax, word [es:si+034h] ; 26 8b 44 34 ; 0xf6106 disk.c:437
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf610a
+ mov ax, di ; 89 f8 ; 0xf610d disk.c:440
+ xor dx, dx ; 31 d2 ; 0xf610f
+ mov bx, word [bp-008h] ; 8b 5e f8 ; 0xf6111
+ xor cx, cx ; 31 c9 ; 0xf6114
+ call 09f10h ; e8 f7 3d ; 0xf6116
+ mov bx, word [bp-006h] ; 8b 5e fa ; 0xf6119
+ xor cx, cx ; 31 c9 ; 0xf611c
+ call 09f10h ; e8 ef 3d ; 0xf611e
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf6121
+ mov word [bp+014h], dx ; 89 56 14 ; 0xf6124 disk.c:441
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf6127 disk.c:442
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf612a disk.c:444
+ xor ah, ah ; 30 e4 ; 0xf612d
+ or ah, 003h ; 80 cc 03 ; 0xf612f
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf6132
+ jmp near 05e10h ; e9 d8 fc ; 0xf6135 disk.c:445
+ mov bx, 00db2h ; bb b2 0d ; 0xf6138 disk.c:453
+ mov cx, ds ; 8c d9 ; 0xf613b
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf613d
+ call 019d3h ; e8 90 b8 ; 0xf6140
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6143
+ shr ax, 008h ; c1 e8 08 ; 0xf6146
+ push ax ; 50 ; 0xf6149
+ push 00690h ; 68 90 06 ; 0xf614a
+ push 007a6h ; 68 a6 07 ; 0xf614d
+ push strict byte 00004h ; 6a 04 ; 0xf6150
+ call 01a14h ; e8 bf b8 ; 0xf6152
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf6155
+ jmp near 05e0ch ; e9 b1 fc ; 0xf6158 disk.c:454
+ mov bx, 00db2h ; bb b2 0d ; 0xf615b disk.c:461
+ mov cx, ds ; 8c d9 ; 0xf615e
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6160
+ call 019d3h ; e8 6d b8 ; 0xf6163
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6166
+ shr ax, 008h ; c1 e8 08 ; 0xf6169
+ push ax ; 50 ; 0xf616c
+ push 00690h ; 68 90 06 ; 0xf616d
+ push 007d9h ; 68 d9 07 ; 0xf6170
+ jmp near 05ea1h ; e9 2b fd ; 0xf6173
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6176 disk.c:467
+ xor ah, ah ; 30 e4 ; 0xf6179
+ or ah, 001h ; 80 cc 01 ; 0xf617b
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf617e
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6181 disk.c:469
+ shr ax, 008h ; c1 e8 08 ; 0xf6184
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf6187 disk.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf618a
+ mov es, dx ; 8e c2 ; 0xf618d
+ mov byte [es:bx], al ; 26 88 07 ; 0xf618f
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf6192 disk.c:471
+ jmp near 05e20h ; e9 87 fc ; 0xf6196 disk.c:472
+ ; disGetNextSymbol 0xf6199 LB 0x3eac -> off=0x20 cb=000000000000029e uValue=00000000000f4bb9 'int13_harddisk_ext'
+ db 049h, 062h, 061h, 062h, 061h, 062h, 061h, 062h, 03fh, 064h, 0cbh, 063h, 061h, 062h, 0d3h, 063h
+ db 03fh, 064h, 024h, 064h, 024h, 064h, 024h, 064h, 024h, 064h, 00ch, 064h, 024h, 064h, 024h, 064h
+int13_harddisk_ext: ; 0xf61b9 LB 0x29e
+ push bp ; 55 ; 0xf61b9 disk.c:482
+ mov bp, sp ; 89 e5 ; 0xf61ba
+ sub sp, strict byte 00016h ; 83 ec 16 ; 0xf61bc
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf61bf disk.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf61c2
+ mov es, ax ; 8e c0 ; 0xf61c5
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf61c7
+ mov di, 00122h ; bf 22 01 ; 0xf61ca disk.c:49
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf61cd
+ mov bx, 0008eh ; bb 8e 00 ; 0xf61d0 disk.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf61d3
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf61d7 disk.c:506
+ xor ah, ah ; 30 e4 ; 0xf61da
+ cmp ax, 00080h ; 3d 80 00 ; 0xf61dc
+ jc short 061e6h ; 72 05 ; 0xf61df
+ cmp ax, 00090h ; 3d 90 00 ; 0xf61e1
+ jc short 06204h ; 72 1e ; 0xf61e4
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf61e6 disk.c:507
+ xor ah, ah ; 30 e4 ; 0xf61e9
+ push ax ; 50 ; 0xf61eb
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf61ec
+ shr ax, 008h ; c1 e8 08 ; 0xf61ef
+ push ax ; 50 ; 0xf61f2
+ push 00807h ; 68 07 08 ; 0xf61f3
+ push 0069fh ; 68 9f 06 ; 0xf61f6
+ push strict byte 00004h ; 6a 04 ; 0xf61f9
+ call 01a14h ; e8 16 b8 ; 0xf61fb
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf61fe
+ jmp near 063eah ; e9 e6 01 ; 0xf6201 disk.c:508
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf6204 disk.c:512
+ xor ah, ah ; 30 e4 ; 0xf6207
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6209
+ mov bx, di ; 89 fb ; 0xf620c
+ add bx, ax ; 01 c3 ; 0xf620e
+ mov dl, byte [es:bx+00163h] ; 26 8a 97 63 01 ; 0xf6210
+ mov byte [bp-002h], dl ; 88 56 fe ; 0xf6215
+ cmp dl, 010h ; 80 fa 10 ; 0xf6218 disk.c:515
+ jc short 0622dh ; 72 10 ; 0xf621b
+ push ax ; 50 ; 0xf621d disk.c:516
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf621e
+ shr ax, 008h ; c1 e8 08 ; 0xf6221
+ push ax ; 50 ; 0xf6224
+ push 00807h ; 68 07 08 ; 0xf6225
+ push 006cah ; 68 ca 06 ; 0xf6228
+ jmp short 061f9h ; eb cc ; 0xf622b
+ mov bx, word [bp+016h] ; 8b 5e 16 ; 0xf622d disk.c:520
+ shr bx, 008h ; c1 eb 08 ; 0xf6230
+ sub bx, strict byte 00041h ; 83 eb 41 ; 0xf6233
+ cmp bx, strict byte 0000fh ; 83 fb 0f ; 0xf6236
+ jnbe near 06424h ; 0f 87 e7 01 ; 0xf6239
+ add bx, bx ; 01 db ; 0xf623d
+ mov cx, word [bp+016h] ; 8b 4e 16 ; 0xf623f
+ xor ch, ch ; 30 ed ; 0xf6242
+ jmp word [cs:bx+06199h] ; 2e ff a7 99 61 ; 0xf6244
+ mov word [bp+010h], 0aa55h ; c7 46 10 55 aa ; 0xf6249 disk.c:522
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf624e disk.c:523
+ xor ah, ah ; 30 e4 ; 0xf6251
+ or ah, 030h ; 80 cc 30 ; 0xf6253
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf6256
+ mov word [bp+014h], strict word 00007h ; c7 46 14 07 00 ; 0xf6259 disk.c:524
+ jmp near 06443h ; e9 e2 01 ; 0xf625e disk.c:525
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6261 disk.c:534
+ mov word [bp-016h], bx ; 89 5e ea ; 0xf6264
+ mov es, [bp+004h] ; 8e 46 04 ; 0xf6267
+ mov word [bp-012h], bx ; 89 5e ee ; 0xf626a
+ mov [bp-010h], es ; 8c 46 f0 ; 0xf626d
+ mov ax, word [es:bx+002h] ; 26 8b 47 02 ; 0xf6270 disk.c:536
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf6274
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf6277 disk.c:537
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf627b
+ mov ax, word [es:bx+004h] ; 26 8b 47 04 ; 0xf627e disk.c:538
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf6282
+ mov dx, word [es:bx+00ch] ; 26 8b 57 0c ; 0xf6285 disk.c:541
+ mov cx, word [es:bx+00eh] ; 26 8b 4f 0e ; 0xf6289
+ xor ax, ax ; 31 c0 ; 0xf628d disk.c:542
+ xor bx, bx ; 31 db ; 0xf628f
+ mov si, strict word 00020h ; be 20 00 ; 0xf6291
+ call 09fa0h ; e8 09 3d ; 0xf6294
+ mov si, ax ; 89 c6 ; 0xf6297
+ mov word [bp-014h], bx ; 89 5e ec ; 0xf6299
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf629c disk.c:543
+ mov ax, word [es:bx+008h] ; 26 8b 47 08 ; 0xf629f
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf62a3
+ mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xf62a6
+ or dx, word [bp-016h] ; 0b 56 ea ; 0xf62aa
+ or cx, ax ; 09 c1 ; 0xf62ad
+ movzx ax, byte [bp-002h] ; 0f b6 46 fe ; 0xf62af disk.c:548
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf62b3
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf62b6
+ mov bx, di ; 89 fb ; 0xf62b9
+ add bx, ax ; 01 c3 ; 0xf62bb
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf62bd
+ mov byte [bp-004h], al ; 88 46 fc ; 0xf62c1
+ mov ax, word [es:bx+03ch] ; 26 8b 47 3c ; 0xf62c4 disk.c:549
+ cmp si, ax ; 39 c6 ; 0xf62c8
+ jnbe short 062eeh ; 77 22 ; 0xf62ca
+ jne short 06311h ; 75 43 ; 0xf62cc
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf62ce
+ cmp ax, word [es:bx+03ah] ; 26 3b 47 3a ; 0xf62d1
+ jnbe short 062eeh ; 77 17 ; 0xf62d5
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf62d7
+ cmp ax, word [es:bx+03ah] ; 26 3b 47 3a ; 0xf62da
+ jne short 06311h ; 75 31 ; 0xf62de
+ cmp cx, word [es:bx+038h] ; 26 3b 4f 38 ; 0xf62e0
+ jnbe short 062eeh ; 77 08 ; 0xf62e4
+ jne short 06311h ; 75 29 ; 0xf62e6
+ cmp dx, word [es:bx+036h] ; 26 3b 57 36 ; 0xf62e8
+ jc short 06311h ; 72 23 ; 0xf62ec
+ mov bx, 00db2h ; bb b2 0d ; 0xf62ee disk.c:550
+ mov cx, ds ; 8c d9 ; 0xf62f1
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf62f3
+ call 019d3h ; e8 da b6 ; 0xf62f6
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf62f9
+ shr ax, 008h ; c1 e8 08 ; 0xf62fc
+ push ax ; 50 ; 0xf62ff
+ push 00807h ; 68 07 08 ; 0xf6300
+ push 0081ah ; 68 1a 08 ; 0xf6303
+ push strict byte 00004h ; 6a 04 ; 0xf6306
+ call 01a14h ; e8 09 b7 ; 0xf6308
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf630b
+ jmp near 063eah ; e9 d9 00 ; 0xf630e disk.c:551
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6311 disk.c:555
+ shr ax, 008h ; c1 e8 08 ; 0xf6314
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf6317
+ cmp ax, strict word 00044h ; 3d 44 00 ; 0xf631a
+ je near 0643fh ; 0f 84 1e 01 ; 0xf631d
+ cmp ax, strict word 00047h ; 3d 47 00 ; 0xf6321
+ je near 0643fh ; 0f 84 17 01 ; 0xf6324
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6328 disk.c:559
+ db 066h, 026h, 0c7h, 045h, 018h, 000h, 000h, 000h, 000h
+ ; mov dword [es:di+018h], strict dword 000000000h ; 66 26 c7 45 18 00 00 00 00; 0xf632b
+ mov word [es:di+01ch], strict word 00000h ; 26 c7 45 1c 00 00 ; 0xf6334 disk.c:560
+ mov word [es:di+006h], si ; 26 89 75 06 ; 0xf633a disk.c:563
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf633e
+ mov word [es:di+004h], ax ; 26 89 45 04 ; 0xf6341
+ mov word [es:di+002h], cx ; 26 89 4d 02 ; 0xf6345
+ mov word [es:di], dx ; 26 89 15 ; 0xf6349
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf634c disk.c:564
+ mov word [es:di+008h], ax ; 26 89 45 08 ; 0xf634f
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf6353
+ mov word [es:di+00ah], ax ; 26 89 45 0a ; 0xf6356
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf635a disk.c:565
+ mov word [es:di+00eh], ax ; 26 89 45 0e ; 0xf635d
+ mov word [es:di+010h], 00200h ; 26 c7 45 10 00 02 ; 0xf6361 disk.c:566
+ mov word [es:di+016h], strict word 00000h ; 26 c7 45 16 00 00 ; 0xf6367 disk.c:567
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf636d disk.c:568
+ mov byte [es:di+00ch], al ; 26 88 45 0c ; 0xf6370
+ mov bx, word [bp-008h] ; 8b 5e f8 ; 0xf6374 disk.c:571
+ add bx, bx ; 01 db ; 0xf6377
+ movzx ax, byte [bp-004h] ; 0f b6 46 fc ; 0xf6379
+ sal ax, 002h ; c1 e0 02 ; 0xf637d
+ add bx, ax ; 01 c3 ; 0xf6380
+ push ES ; 06 ; 0xf6382
+ push di ; 57 ; 0xf6383
+ call word [word bx-00002h] ; ff 97 fe ff ; 0xf6384
+ mov dx, ax ; 89 c2 ; 0xf6388
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf638a disk.c:572
+ mov ax, word [es:di+018h] ; 26 8b 45 18 ; 0xf638d
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf6391
+ les bx, [bp-012h] ; c4 5e ee ; 0xf6394 disk.c:573
+ mov word [es:bx+002h], ax ; 26 89 47 02 ; 0xf6397
+ test dl, dl ; 84 d2 ; 0xf639b disk.c:575
+ je near 0643fh ; 0f 84 9e 00 ; 0xf639d
+ mov bx, 00db2h ; bb b2 0d ; 0xf63a1 disk.c:576
+ mov cx, ds ; 8c d9 ; 0xf63a4
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf63a6
+ call 019d3h ; e8 27 b6 ; 0xf63a9
+ movzx ax, dl ; 0f b6 c2 ; 0xf63ac
+ push ax ; 50 ; 0xf63af
+ push word [bp-008h] ; ff 76 f8 ; 0xf63b0
+ push 00807h ; 68 07 08 ; 0xf63b3
+ push 0076bh ; 68 6b 07 ; 0xf63b6
+ push strict byte 00004h ; 6a 04 ; 0xf63b9
+ call 01a14h ; e8 56 b6 ; 0xf63bb
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf63be
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf63c1 disk.c:577
+ xor ah, ah ; 30 e4 ; 0xf63c4
+ or ah, 00ch ; 80 cc 0c ; 0xf63c6
+ jmp short 063f2h ; eb 27 ; 0xf63c9 disk.c:578
+ or ch, 0b2h ; 80 cd b2 ; 0xf63cb disk.c:590
+ mov word [bp+016h], cx ; 89 4e 16 ; 0xf63ce
+ jmp short 063f5h ; eb 22 ; 0xf63d1 disk.c:591
+ movzx ax, byte [bp-002h] ; 0f b6 46 fe ; 0xf63d3 disk.c:595
+ push ax ; 50 ; 0xf63d7
+ mov ax, word [bp+00ah] ; 8b 46 0a ; 0xf63d8
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf63db
+ mov bx, di ; 89 fb ; 0xf63de
+ mov cx, word [bp-006h] ; 8b 4e fa ; 0xf63e0
+ call 05a50h ; e8 6a f6 ; 0xf63e3
+ test ax, ax ; 85 c0 ; 0xf63e6
+ je short 0643fh ; 74 55 ; 0xf63e8
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf63ea disk.c:596
+ xor ah, ah ; 30 e4 ; 0xf63ed
+ or ah, 001h ; 80 cc 01 ; 0xf63ef
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf63f2
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf63f5
+ shr ax, 008h ; c1 e8 08 ; 0xf63f8
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf63fb
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf63fe
+ mov es, dx ; 8e c2 ; 0xf6401
+ mov byte [es:bx], al ; 26 88 07 ; 0xf6403
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf6406
+ jmp short 06453h ; eb 47 ; 0xf640a
+ cmp cx, strict byte 00006h ; 83 f9 06 ; 0xf640c disk.c:603
+ je short 0643fh ; 74 2e ; 0xf640f
+ cmp cx, strict byte 00001h ; 83 f9 01 ; 0xf6411
+ jc short 063eah ; 72 d4 ; 0xf6414
+ jbe short 0643fh ; 76 27 ; 0xf6416
+ cmp cx, strict byte 00003h ; 83 f9 03 ; 0xf6418
+ jc short 063eah ; 72 cd ; 0xf641b
+ cmp cx, strict byte 00004h ; 83 f9 04 ; 0xf641d
+ jbe short 0643fh ; 76 1d ; 0xf6420
+ jmp short 063eah ; eb c6 ; 0xf6422 disk.c:611
+ mov bx, 00db2h ; bb b2 0d ; 0xf6424 disk.c:617
+ mov cx, ds ; 8c d9 ; 0xf6427
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6429
+ call 019d3h ; e8 a4 b5 ; 0xf642c
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf642f
+ shr ax, 008h ; c1 e8 08 ; 0xf6432
+ push ax ; 50 ; 0xf6435
+ push 00807h ; 68 07 08 ; 0xf6436
+ push 007d9h ; 68 d9 07 ; 0xf6439
+ jmp near 06306h ; e9 c7 fe ; 0xf643c
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf643f disk.c:630
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf6443 disk.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf6446
+ mov es, ax ; 8e c0 ; 0xf6449
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf644b
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf644f disk.c:633
+ mov sp, bp ; 89 ec ; 0xf6453 disk.c:635
+ pop bp ; 5d ; 0xf6455
+ retn ; c3 ; 0xf6456
+ ; disGetNextSymbol 0xf6457 LB 0x3bee -> off=0x0 cb=0000000000000151 uValue=00000000000f4e57 'int14_function'
+int14_function: ; 0xf6457 LB 0x151
+ push bp ; 55 ; 0xf6457 serial.c:60
+ mov bp, sp ; 89 e5 ; 0xf6458
+ push si ; 56 ; 0xf645a
+ push di ; 57 ; 0xf645b
+ sti ; fb ; 0xf645c serial.c:65
+ mov si, word [bp+00eh] ; 8b 76 0e ; 0xf645d serial.c:67
+ add si, si ; 01 f6 ; 0xf6460
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf6462 serial.c:48
+ mov es, ax ; 8e c0 ; 0xf6465
+ mov si, word [es:si] ; 26 8b 34 ; 0xf6467
+ mov bx, si ; 89 f3 ; 0xf646a serial.c:49
+ mov di, word [bp+00eh] ; 8b 7e 0e ; 0xf646c serial.c:68
+ add di, strict byte 0007ch ; 83 c7 7c ; 0xf646f
+ mov cl, byte [es:di] ; 26 8a 0d ; 0xf6472 serial.c:38
+ cmp word [bp+00eh], strict byte 00004h ; 83 7e 0e 04 ; 0xf6475 serial.c:69
+ jnc near 0659dh ; 0f 83 20 01 ; 0xf6479
+ test si, si ; 85 f6 ; 0xf647d
+ jbe near 0659dh ; 0f 86 1a 01 ; 0xf647f
+ mov al, byte [bp+013h] ; 8a 46 13 ; 0xf6483 serial.c:70
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf6486
+ jc short 0649bh ; 72 11 ; 0xf6488
+ jbe short 064f4h ; 76 68 ; 0xf648a
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf648c
+ je near 06586h ; 0f 84 f4 00 ; 0xf648e
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf6492
+ je near 0653fh ; 0f 84 a7 00 ; 0xf6494
+ jmp near 06597h ; e9 fc 00 ; 0xf6498
+ test al, al ; 84 c0 ; 0xf649b
+ jne near 06597h ; 0f 85 f6 00 ; 0xf649d
+ lea dx, [bx+003h] ; 8d 57 03 ; 0xf64a1 serial.c:72
+ in AL, DX ; ec ; 0xf64a4
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf64a5
+ or AL, strict byte 080h ; 0c 80 ; 0xf64a7
+ out DX, AL ; ee ; 0xf64a9
+ lea si, [bx+001h] ; 8d 77 01 ; 0xf64aa
+ mov al, byte [bp+012h] ; 8a 46 12 ; 0xf64ad serial.c:73
+ test AL, strict byte 0e0h ; a8 e0 ; 0xf64b0
+ jne short 064c0h ; 75 0c ; 0xf64b2
+ mov AL, strict byte 017h ; b0 17 ; 0xf64b4 serial.c:74
+ mov dx, bx ; 89 da ; 0xf64b6
+ out DX, AL ; ee ; 0xf64b8
+ mov AL, strict byte 004h ; b0 04 ; 0xf64b9 serial.c:75
+ mov dx, si ; 89 f2 ; 0xf64bb
+ out DX, AL ; ee ; 0xf64bd
+ jmp short 064d6h ; eb 16 ; 0xf64be serial.c:76
+ and AL, strict byte 0e0h ; 24 e0 ; 0xf64c0 serial.c:77
+ movzx cx, al ; 0f b6 c8 ; 0xf64c2
+ sar cx, 005h ; c1 f9 05 ; 0xf64c5
+ mov ax, 00600h ; b8 00 06 ; 0xf64c8
+ sar ax, CL ; d3 f8 ; 0xf64cb
+ mov dx, bx ; 89 da ; 0xf64cd serial.c:78
+ out DX, AL ; ee ; 0xf64cf
+ shr ax, 008h ; c1 e8 08 ; 0xf64d0 serial.c:79
+ mov dx, si ; 89 f2 ; 0xf64d3
+ out DX, AL ; ee ; 0xf64d5
+ mov al, byte [bp+012h] ; 8a 46 12 ; 0xf64d6 serial.c:81
+ and AL, strict byte 01fh ; 24 1f ; 0xf64d9
+ lea dx, [bx+003h] ; 8d 57 03 ; 0xf64db
+ out DX, AL ; ee ; 0xf64de
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf64df serial.c:82
+ in AL, DX ; ec ; 0xf64e2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf64e3
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf64e5
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf64e8 serial.c:83
+ in AL, DX ; ec ; 0xf64eb
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf64ec
+ mov byte [bp+012h], al ; 88 46 12 ; 0xf64ee
+ jmp near 06578h ; e9 84 00 ; 0xf64f1
+ mov si, strict word 0006ch ; be 6c 00 ; 0xf64f4 serial.c:48
+ mov si, word [es:si] ; 26 8b 34 ; 0xf64f7
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf64fa serial.c:88
+ in AL, DX ; ec ; 0xf64fd
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf64fe
+ and ax, strict word 00060h ; 25 60 00 ; 0xf6500
+ cmp ax, strict word 00060h ; 3d 60 00 ; 0xf6503
+ je short 06521h ; 74 19 ; 0xf6506
+ test cl, cl ; 84 c9 ; 0xf6508
+ je short 06521h ; 74 15 ; 0xf650a
+ mov di, strict word 0006ch ; bf 6c 00 ; 0xf650c serial.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf650f
+ mov es, ax ; 8e c0 ; 0xf6512
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf6514
+ cmp ax, si ; 39 f0 ; 0xf6517 serial.c:90
+ je short 064fah ; 74 df ; 0xf6519
+ mov si, ax ; 89 c6 ; 0xf651b serial.c:91
+ db 0feh, 0c9h
+ ; dec cl ; fe c9 ; 0xf651d serial.c:92
+ jmp short 064fah ; eb d9 ; 0xf651f serial.c:94
+ test cl, cl ; 84 c9 ; 0xf6521 serial.c:95
+ je short 0652bh ; 74 06 ; 0xf6523
+ mov al, byte [bp+012h] ; 8a 46 12 ; 0xf6525
+ mov dx, bx ; 89 da ; 0xf6528
+ out DX, AL ; ee ; 0xf652a
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf652b serial.c:96
+ in AL, DX ; ec ; 0xf652e
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf652f
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf6531
+ test cl, cl ; 84 c9 ; 0xf6534 serial.c:97
+ jne short 06578h ; 75 40 ; 0xf6536
+ or AL, strict byte 080h ; 0c 80 ; 0xf6538
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf653a
+ jmp short 06578h ; eb 39 ; 0xf653d
+ mov si, strict word 0006ch ; be 6c 00 ; 0xf653f serial.c:48
+ mov si, word [es:si] ; 26 8b 34 ; 0xf6542
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf6545 serial.c:102
+ in AL, DX ; ec ; 0xf6548
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6549
+ test AL, strict byte 001h ; a8 01 ; 0xf654b
+ jne short 06568h ; 75 19 ; 0xf654d
+ test cl, cl ; 84 c9 ; 0xf654f
+ je short 06568h ; 74 15 ; 0xf6551
+ mov di, strict word 0006ch ; bf 6c 00 ; 0xf6553 serial.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf6556
+ mov es, ax ; 8e c0 ; 0xf6559
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf655b
+ cmp ax, si ; 39 f0 ; 0xf655e serial.c:104
+ je short 06545h ; 74 e3 ; 0xf6560
+ mov si, ax ; 89 c6 ; 0xf6562 serial.c:105
+ db 0feh, 0c9h
+ ; dec cl ; fe c9 ; 0xf6564 serial.c:106
+ jmp short 06545h ; eb dd ; 0xf6566 serial.c:108
+ test cl, cl ; 84 c9 ; 0xf6568 serial.c:109
+ je short 0657eh ; 74 12 ; 0xf656a
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf656c serial.c:110
+ mov dx, bx ; 89 da ; 0xf6570 serial.c:111
+ in AL, DX ; ec ; 0xf6572
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6573
+ mov byte [bp+012h], al ; 88 46 12 ; 0xf6575
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf6578 serial.c:112
+ jmp short 065a1h ; eb 23 ; 0xf657c
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf657e serial.c:113
+ in AL, DX ; ec ; 0xf6581
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6582
+ jmp short 0653ah ; eb b4 ; 0xf6584
+ lea dx, [si+005h] ; 8d 54 05 ; 0xf6586 serial.c:118
+ in AL, DX ; ec ; 0xf6589
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf658a
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf658c
+ lea dx, [si+006h] ; 8d 54 06 ; 0xf658f serial.c:119
+ in AL, DX ; ec ; 0xf6592
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6593
+ jmp short 06575h ; eb de ; 0xf6595
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf6597 serial.c:123
+ jmp short 065a1h ; eb 04 ; 0xf659b serial.c:125
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf659d serial.c:126
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf65a1 serial.c:128
+ pop di ; 5f ; 0xf65a4
+ pop si ; 5e ; 0xf65a5
+ pop bp ; 5d ; 0xf65a6
+ retn ; c3 ; 0xf65a7
+ ; disGetNextSymbol 0xf65a8 LB 0x3a9d -> off=0x0 cb=0000000000000043 uValue=00000000000f4fa8 'timer_wait'
+timer_wait: ; 0xf65a8 LB 0x43
+ push bp ; 55 ; 0xf65a8 system.c:289
+ mov bp, sp ; 89 e5 ; 0xf65a9
+ push bx ; 53 ; 0xf65ab
+ push cx ; 51 ; 0xf65ac
+ push ax ; 50 ; 0xf65ad
+ mov bx, strict word 0000fh ; bb 0f 00 ; 0xf65ae system.c:296
+ xor cx, cx ; 31 c9 ; 0xf65b1
+ call 09f50h ; e8 9a 39 ; 0xf65b3
+ mov cx, ax ; 89 c1 ; 0xf65b6
+ mov bx, dx ; 89 d3 ; 0xf65b8
+ mov dx, strict word 00061h ; ba 61 00 ; 0xf65ba system.c:298
+ in AL, DX ; ec ; 0xf65bd
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf65be
+ and AL, strict byte 010h ; 24 10 ; 0xf65c0
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf65c2
+ add cx, strict byte 0ffffh ; 83 c1 ff ; 0xf65c5 system.c:299
+ adc bx, strict byte 0ffffh ; 83 d3 ff ; 0xf65c8
+ cmp bx, strict byte 0ffffh ; 83 fb ff ; 0xf65cb
+ jne short 065d5h ; 75 05 ; 0xf65ce
+ cmp cx, strict byte 0ffffh ; 83 f9 ff ; 0xf65d0
+ je short 065e4h ; 74 0f ; 0xf65d3
+ mov dx, strict word 00061h ; ba 61 00 ; 0xf65d5 system.c:302
+ in AL, DX ; ec ; 0xf65d8
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf65d9
+ and AL, strict byte 010h ; 24 10 ; 0xf65db
+ cmp al, byte [bp-006h] ; 3a 46 fa ; 0xf65dd system.c:303
+ jne short 065d5h ; 75 f3 ; 0xf65e0
+ jmp short 065c5h ; eb e1 ; 0xf65e2 system.c:305
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf65e4 system.c:306
+ pop cx ; 59 ; 0xf65e7
+ pop bx ; 5b ; 0xf65e8
+ pop bp ; 5d ; 0xf65e9
+ retn ; c3 ; 0xf65ea
+ ; disGetNextSymbol 0xf65eb LB 0x3a5a -> off=0x0 cb=000000000000002c uValue=00000000000f4feb 'set_enable_a20'
+set_enable_a20: ; 0xf65eb LB 0x2c
+ push bp ; 55 ; 0xf65eb system.c:308
+ mov bp, sp ; 89 e5 ; 0xf65ec
+ push bx ; 53 ; 0xf65ee
+ push cx ; 51 ; 0xf65ef
+ push dx ; 52 ; 0xf65f0
+ mov bx, ax ; 89 c3 ; 0xf65f1
+ mov dx, 00092h ; ba 92 00 ; 0xf65f3 system.c:315
+ in AL, DX ; ec ; 0xf65f6
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf65f7
+ mov cl, al ; 88 c1 ; 0xf65f9
+ test bx, bx ; 85 db ; 0xf65fb system.c:318
+ je short 06604h ; 74 05 ; 0xf65fd
+ or AL, strict byte 002h ; 0c 02 ; 0xf65ff system.c:319
+ out DX, AL ; ee ; 0xf6601
+ jmp short 06607h ; eb 03 ; 0xf6602 system.c:320
+ and AL, strict byte 0fdh ; 24 fd ; 0xf6604 system.c:321
+ out DX, AL ; ee ; 0xf6606
+ test cl, 002h ; f6 c1 02 ; 0xf6607 system.c:323
+ db 00fh, 095h, 0c0h
+ ; setne al ; 0f 95 c0 ; 0xf660a
+ xor ah, ah ; 30 e4 ; 0xf660d
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf660f system.c:324
+ pop dx ; 5a ; 0xf6612
+ pop cx ; 59 ; 0xf6613
+ pop bx ; 5b ; 0xf6614
+ pop bp ; 5d ; 0xf6615
+ retn ; c3 ; 0xf6616
+ ; disGetNextSymbol 0xf6617 LB 0x3a2e -> off=0x3b cb=00000000000002f7 uValue=00000000000f5052 'int15_function'
+ db 0ech, 0e9h, 0d8h, 0c7h, 0c1h, 0c0h, 0bfh, 091h, 090h, 089h, 088h, 086h, 083h, 052h, 04fh, 041h
+ db 024h, 022h, 000h, 02bh, 069h, 08fh, 066h, 0cch, 068h, 0a2h, 066h, 0cch, 068h, 024h, 069h, 0e6h
+ db 066h, 01ch, 067h, 0b9h, 067h, 0c5h, 067h, 0eeh, 067h, 0b2h, 067h, 0b2h, 067h, 0b6h, 068h, 0deh
+ db 068h, 0f1h, 068h, 0cch, 068h, 005h, 069h, 07bh, 067h, 00ch, 069h
+int15_function: ; 0xf6652 LB 0x2f7
+ push bp ; 55 ; 0xf6652 system.c:345
+ mov bp, sp ; 89 e5 ; 0xf6653
+ push si ; 56 ; 0xf6655
+ push di ; 57 ; 0xf6656
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf6657 system.c:352
+ shr ax, 008h ; c1 e8 08 ; 0xf665a
+ cmp ax, 000ech ; 3d ec 00 ; 0xf665d
+ jnbe near 0692bh ; 0f 87 c7 02 ; 0xf6660
+ push CS ; 0e ; 0xf6664
+ pop ES ; 07 ; 0xf6665
+ mov cx, strict word 00014h ; b9 14 00 ; 0xf6666
+ mov di, 06617h ; bf 17 66 ; 0xf6669
+ repne scasb ; f2 ae ; 0xf666c
+ sal cx, 1 ; d1 e1 ; 0xf666e
+ mov di, cx ; 89 cf ; 0xf6670
+ mov cx, word [cs:di+0662ah] ; 2e 8b 8d 2a 66 ; 0xf6672
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf6677
+ xor ah, ah ; 30 e4 ; 0xf667a
+ mov bx, word [bp+018h] ; 8b 5e 18 ; 0xf667c
+ and bl, 0feh ; 80 e3 fe ; 0xf667f
+ mov si, word [bp+018h] ; 8b 76 18 ; 0xf6682
+ or si, strict byte 00001h ; 83 ce 01 ; 0xf6685
+ mov dx, ax ; 89 c2 ; 0xf6688
+ or dh, 086h ; 80 ce 86 ; 0xf668a
+ jmp cx ; ff e1 ; 0xf668d
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf668f system.c:354
+ xor ah, ah ; 30 e4 ; 0xf6692
+ cmp ax, 000c0h ; 3d c0 00 ; 0xf6694
+ jne near 0692bh ; 0f 85 90 02 ; 0xf6697
+ or byte [bp+018h], 001h ; 80 4e 18 01 ; 0xf669b system.c:361
+ jmp near 068d5h ; e9 33 02 ; 0xf669f
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf66a2 system.c:365
+ xor ah, ah ; 30 e4 ; 0xf66a5
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf66a7
+ jc short 066bah ; 72 0e ; 0xf66aa
+ jbe short 066ceh ; 76 20 ; 0xf66ac
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf66ae
+ je short 066f0h ; 74 3d ; 0xf66b1
+ cmp ax, strict word 00002h ; 3d 02 00 ; 0xf66b3
+ je short 066d3h ; 74 1b ; 0xf66b6
+ jmp short 066fdh ; eb 43 ; 0xf66b8
+ test ax, ax ; 85 c0 ; 0xf66ba
+ jne short 066fdh ; 75 3f ; 0xf66bc
+ xor ax, ax ; 31 c0 ; 0xf66be system.c:367
+ call 065ebh ; e8 28 ff ; 0xf66c0
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf66c3 system.c:368
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf66c7 system.c:369
+ jmp near 067b2h ; e9 e4 00 ; 0xf66cb system.c:370
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf66ce system.c:372
+ jmp short 066c0h ; eb ed ; 0xf66d1
+ mov dx, 00092h ; ba 92 00 ; 0xf66d3 system.c:377
+ in AL, DX ; ec ; 0xf66d6
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf66d7
+ shr ax, 1 ; d1 e8 ; 0xf66d9
+ and ax, strict word 00001h ; 25 01 00 ; 0xf66db
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf66de
+ mov dl, al ; 88 c2 ; 0xf66e1
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf66e3
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf66e6 system.c:378
+ mov byte [bp+013h], ah ; 88 66 13 ; 0xf66ea system.c:379
+ jmp near 067b2h ; e9 c2 00 ; 0xf66ed system.c:380
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf66f0 system.c:382
+ mov byte [bp+013h], ah ; 88 66 13 ; 0xf66f4 system.c:383
+ mov word [bp+00ch], ax ; 89 46 0c ; 0xf66f7 system.c:384
+ jmp near 067b2h ; e9 b5 00 ; 0xf66fa system.c:385
+ mov bx, 00db2h ; bb b2 0d ; 0xf66fd system.c:387
+ mov cx, ds ; 8c d9 ; 0xf6700
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6702
+ call 019d3h ; e8 cb b2 ; 0xf6705
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf6708
+ xor ah, ah ; 30 e4 ; 0xf670b
+ push ax ; 50 ; 0xf670d
+ push 00840h ; 68 40 08 ; 0xf670e
+ push strict byte 00004h ; 6a 04 ; 0xf6711
+ call 01a14h ; e8 fe b2 ; 0xf6713
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf6716
+ jmp near 068cch ; e9 b0 01 ; 0xf6719
+ test byte [bp+012h], 0ffh ; f6 46 12 ff ; 0xf671c system.c:419
+ jne short 06784h ; 75 62 ; 0xf6720
+ mov bx, 000a0h ; bb a0 00 ; 0xf6722 system.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf6725
+ mov es, ax ; 8e c0 ; 0xf6728
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf672a
+ test AL, strict byte 001h ; a8 01 ; 0xf672d system.c:39
+ jne short 0677bh ; 75 4a ; 0xf672f
+ mov DL, strict byte 001h ; b2 01 ; 0xf6731 system.c:41
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf6733 system.c:43
+ mov bx, 00098h ; bb 98 00 ; 0xf6736 system.c:51
+ mov dx, word [bp+014h] ; 8b 56 14 ; 0xf6739
+ mov word [es:bx], dx ; 26 89 17 ; 0xf673c system.c:53
+ mov bx, 0009ah ; bb 9a 00 ; 0xf673f system.c:51
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf6742
+ mov word [es:bx], dx ; 26 89 17 ; 0xf6745 system.c:53
+ mov bx, 0009ch ; bb 9c 00 ; 0xf6748 system.c:51
+ mov dx, word [bp+00eh] ; 8b 56 0e ; 0xf674b
+ mov word [es:bx], dx ; 26 89 17 ; 0xf674e system.c:53
+ mov bx, 0009eh ; bb 9e 00 ; 0xf6751 system.c:51
+ mov dx, word [bp+010h] ; 8b 56 10 ; 0xf6754
+ mov word [es:bx], dx ; 26 89 17 ; 0xf6757 system.c:53
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf675a system.c:428
+ mov dx, 000a1h ; ba a1 00 ; 0xf675e system.c:429
+ in AL, DX ; ec ; 0xf6761
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6762
+ and AL, strict byte 0feh ; 24 fe ; 0xf6764 system.c:430
+ out DX, AL ; ee ; 0xf6766
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6767 system.c:431
+ call 01756h ; e8 e9 af ; 0xf676a
+ or AL, strict byte 040h ; 0c 40 ; 0xf676d system.c:432
+ movzx dx, al ; 0f b6 d0 ; 0xf676f
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6772
+ call 01773h ; e8 fb af ; 0xf6775
+ jmp near 067b2h ; e9 37 00 ; 0xf6778 system.c:433
+ mov word [bp+018h], si ; 89 76 18 ; 0xf677b system.c:436
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf677e system.c:437
+ jmp near 067b2h ; e9 2e 00 ; 0xf6781 system.c:439
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf6784
+ jne short 067a3h ; 75 1a ; 0xf6787
+ mov bx, 000a0h ; bb a0 00 ; 0xf6789 system.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf678c
+ mov es, ax ; 8e c0 ; 0xf678f
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf6791
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf6795 system.c:442
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6799 system.c:443
+ call 01756h ; e8 b7 af ; 0xf679c
+ and AL, strict byte 0bfh ; 24 bf ; 0xf679f system.c:444
+ jmp short 0676fh ; eb cc ; 0xf67a1
+ mov word [bp+018h], si ; 89 76 18 ; 0xf67a3 system.c:447
+ mov ax, dx ; 89 d0 ; 0xf67a6 system.c:449
+ xor ah, dh ; 30 f4 ; 0xf67a8
+ xor dl, dl ; 30 d2 ; 0xf67aa
+ dec ax ; 48 ; 0xf67ac
+ or dx, ax ; 09 c2 ; 0xf67ad
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf67af
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf67b2 system.c:452
+ pop di ; 5f ; 0xf67b5
+ pop si ; 5e ; 0xf67b6
+ pop bp ; 5d ; 0xf67b7
+ retn ; c3 ; 0xf67b8
+ sti ; fb ; 0xf67b9 system.c:458
+ mov dx, word [bp+010h] ; 8b 56 10 ; 0xf67ba system.c:459
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf67bd
+ call 065a8h ; e8 e5 fd ; 0xf67c0
+ jmp short 067b2h ; eb ed ; 0xf67c3 system.c:460
+ mov ax, strict word 00031h ; b8 31 00 ; 0xf67c5 system.c:465
+ call 01756h ; e8 8b af ; 0xf67c8
+ movzx dx, al ; 0f b6 d0 ; 0xf67cb
+ sal dx, 008h ; c1 e2 08 ; 0xf67ce
+ mov ax, strict word 00030h ; b8 30 00 ; 0xf67d1
+ call 01756h ; e8 7f af ; 0xf67d4
+ xor ah, ah ; 30 e4 ; 0xf67d7
+ or dx, ax ; 09 c2 ; 0xf67d9
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf67db
+ cmp dx, strict byte 0ffc0h ; 83 fa c0 ; 0xf67de system.c:470
+ jbe short 067e8h ; 76 05 ; 0xf67e1
+ mov word [bp+012h], strict word 0ffc0h ; c7 46 12 c0 ff ; 0xf67e3 system.c:471
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf67e8 system.c:480
+ jmp short 067b2h ; eb c4 ; 0xf67ec system.c:485
+ cli ; fa ; 0xf67ee system.c:494
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf67ef system.c:496
+ call 065ebh ; e8 f6 fd ; 0xf67f2
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf67f5 system.c:499
+ add bx, strict byte 00038h ; 83 c3 38 ; 0xf67f8
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf67fb system.c:51
+ mov word [es:bx], strict word 0ffffh ; 26 c7 07 ff ff ; 0xf67fe
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf6803 system.c:500
+ add bx, strict byte 0003ah ; 83 c3 3a ; 0xf6806
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf6809 system.c:51
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf680c system.c:53
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf6811 system.c:501
+ add bx, strict byte 0003ch ; 83 c3 3c ; 0xf6814
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf6817 system.c:41
+ mov byte [es:bx], 00fh ; 26 c6 07 0f ; 0xf681a
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf681e system.c:502
+ add bx, strict byte 0003dh ; 83 c3 3d ; 0xf6821
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf6824 system.c:41
+ mov byte [es:bx], 09bh ; 26 c6 07 9b ; 0xf6827
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf682b system.c:503
+ add bx, strict byte 0003eh ; 83 c3 3e ; 0xf682e
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf6831 system.c:51
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf6834
+ mov AL, strict byte 011h ; b0 11 ; 0xf6839 system.c:506
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf683b
+ out DX, AL ; ee ; 0xf683e
+ mov dx, 000a0h ; ba a0 00 ; 0xf683f system.c:507
+ out DX, AL ; ee ; 0xf6842
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf6843 system.c:508
+ shr ax, 008h ; c1 e8 08 ; 0xf6846
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf6849
+ out DX, AL ; ee ; 0xf684c
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf684d system.c:509
+ mov dx, 000a1h ; ba a1 00 ; 0xf6850
+ out DX, AL ; ee ; 0xf6853
+ mov AL, strict byte 004h ; b0 04 ; 0xf6854 system.c:510
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf6856
+ out DX, AL ; ee ; 0xf6859
+ mov AL, strict byte 002h ; b0 02 ; 0xf685a system.c:511
+ mov dx, 000a1h ; ba a1 00 ; 0xf685c
+ out DX, AL ; ee ; 0xf685f
+ mov AL, strict byte 001h ; b0 01 ; 0xf6860 system.c:512
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf6862
+ out DX, AL ; ee ; 0xf6865
+ mov dx, 000a1h ; ba a1 00 ; 0xf6866 system.c:513
+ out DX, AL ; ee ; 0xf6869
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf686a system.c:515
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf686c
+ out DX, AL ; ee ; 0xf686f
+ mov dx, 000a1h ; ba a1 00 ; 0xf6870 system.c:516
+ out DX, AL ; ee ; 0xf6873
+ mov si, word [bp+006h] ; 8b 76 06 ; 0xf6874 system.c:518
+ lgdt [es:si+008h] ; 26 0f 01 54 08 ; 0xf6877
+ lidt [es:si+010h] ; 26 0f 01 5c 10 ; 0xf687c
+ push strict byte 00038h ; 6a 38 ; 0xf6881
+ call 06886h ; e8 00 00 ; 0xf6883
+ pop ax ; 58 ; 0xf6886
+ add ax, strict byte 0000eh ; 83 c0 0e ; 0xf6887
+ push ax ; 50 ; 0xf688a
+ smsw ax ; 0f 01 e0 ; 0xf688b
+ or AL, strict byte 001h ; 0c 01 ; 0xf688e
+ lmsw ax ; 0f 01 f0 ; 0xf6890
+ retf ; cb ; 0xf6893
+ mov ax, strict word 00018h ; b8 18 00 ; 0xf6894
+ mov ds, ax ; 8e d8 ; 0xf6897
+ add AL, strict byte 008h ; 04 08 ; 0xf6899
+ mov es, ax ; 8e c0 ; 0xf689b
+ add AL, strict byte 008h ; 04 08 ; 0xf689d
+ mov ss, ax ; 8e d0 ; 0xf689f
+ lea ax, [bp+004h] ; 8d 46 04 ; 0xf68a1 system.c:519
+ db 08bh, 0e0h
+ ; mov sp, ax ; 8b e0 ; 0xf68a4
+ popaw ; 61 ; 0xf68a6
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf68a7
+ pop cx ; 59 ; 0xf68aa
+ pop ax ; 58 ; 0xf68ab
+ pop ax ; 58 ; 0xf68ac
+ mov ax, strict word 00030h ; b8 30 00 ; 0xf68ad
+ push ax ; 50 ; 0xf68b0
+ push cx ; 51 ; 0xf68b1
+ retf ; cb ; 0xf68b2
+ jmp near 067b2h ; e9 fc fe ; 0xf68b3 system.c:525
+ mov bx, 00db2h ; bb b2 0d ; 0xf68b6 system.c:532
+ mov cx, ds ; 8c d9 ; 0xf68b9
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf68bb
+ call 019d3h ; e8 12 b1 ; 0xf68be
+ push 00880h ; 68 80 08 ; 0xf68c1
+ push strict byte 00004h ; 6a 04 ; 0xf68c4
+ call 01a14h ; e8 4b b1 ; 0xf68c6
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf68c9
+ or byte [bp+018h], 001h ; 80 4e 18 01 ; 0xf68cc
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf68d0
+ xor ah, ah ; 30 e4 ; 0xf68d3
+ or ah, 086h ; 80 cc 86 ; 0xf68d5
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf68d8
+ jmp near 067b2h ; e9 d4 fe ; 0xf68db
+ mov word [bp+018h], bx ; 89 5e 18 ; 0xf68de system.c:538
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf68e1 system.c:539
+ mov word [bp+00ch], 0e6f5h ; c7 46 0c f5 e6 ; 0xf68e4 system.c:540
+ mov word [bp+014h], 0f000h ; c7 46 14 00 f0 ; 0xf68e9 system.c:541
+ jmp near 067b2h ; e9 c1 fe ; 0xf68ee system.c:542
+ mov si, strict word 0000eh ; be 0e 00 ; 0xf68f1 system.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf68f4
+ mov es, ax ; 8e c0 ; 0xf68f7
+ mov ax, word [es:si] ; 26 8b 04 ; 0xf68f9
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf68fc system.c:49
+ mov word [bp+018h], bx ; 89 5e 18 ; 0xf68ff system.c:546
+ jmp near 067b2h ; e9 ad fe ; 0xf6902 system.c:547
+ push 008afh ; 68 af 08 ; 0xf6905 system.c:550
+ push strict byte 00008h ; 6a 08 ; 0xf6908
+ jmp short 068c6h ; eb ba ; 0xf690a
+ test byte [bp+012h], 0ffh ; f6 46 12 ff ; 0xf690c system.c:562
+ jne short 0692bh ; 75 19 ; 0xf6910
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf6912 system.c:564
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf6915 system.c:565
+ xor ah, ah ; 30 e4 ; 0xf6918
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf691a
+ jc short 06924h ; 72 05 ; 0xf691d
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf691f
+ jbe short 068ffh ; 76 db ; 0xf6922
+ or byte [bp+018h], 001h ; 80 4e 18 01 ; 0xf6924 system.c:568
+ jmp near 067b2h ; e9 87 fe ; 0xf6928 system.c:569
+ mov bx, 00db2h ; bb b2 0d ; 0xf692b system.c:573
+ mov cx, ds ; 8c d9 ; 0xf692e
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6930
+ call 019d3h ; e8 9d b0 ; 0xf6933
+ push word [bp+00ch] ; ff 76 0c ; 0xf6936
+ push word [bp+012h] ; ff 76 12 ; 0xf6939
+ push 008c6h ; 68 c6 08 ; 0xf693c
+ push strict byte 00004h ; 6a 04 ; 0xf693f
+ call 01a14h ; e8 d0 b0 ; 0xf6941
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf6944
+ jmp short 068cch ; eb 83 ; 0xf6947
+ ; disGetNextSymbol 0xf6949 LB 0x36fc -> off=0x0 cb=0000000000000057 uValue=00000000000f5349 'set_e820_range'
+set_e820_range: ; 0xf6949 LB 0x57
+ push si ; 56 ; 0xf6949 system.c:590
+ push bp ; 55 ; 0xf694a
+ mov bp, sp ; 89 e5 ; 0xf694b
+ mov es, ax ; 8e c0 ; 0xf694d
+ mov si, dx ; 89 d6 ; 0xf694f
+ mov word [es:si], bx ; 26 89 1c ; 0xf6951 system.c:596
+ mov word [es:si+002h], cx ; 26 89 4c 02 ; 0xf6954
+ movzx ax, byte [bp+00ah] ; 0f b6 46 0a ; 0xf6958 system.c:597
+ mov word [es:si+004h], ax ; 26 89 44 04 ; 0xf695c
+ mov word [es:si+006h], strict word 00000h ; 26 c7 44 06 00 00 ; 0xf6960
+ sub word [bp+006h], bx ; 29 5e 06 ; 0xf6966 system.c:598
+ sbb word [bp+008h], cx ; 19 4e 08 ; 0xf6969
+ mov al, byte [bp+00ah] ; 8a 46 0a ; 0xf696c system.c:599
+ sub byte [bp+00ch], al ; 28 46 0c ; 0xf696f
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf6972 system.c:600
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf6975
+ mov ax, word [bp+008h] ; 8b 46 08 ; 0xf6979
+ mov word [es:si+00ah], ax ; 26 89 44 0a ; 0xf697c
+ movzx ax, byte [bp+00ch] ; 0f b6 46 0c ; 0xf6980 system.c:601
+ mov word [es:si+00ch], ax ; 26 89 44 0c ; 0xf6984
+ mov word [es:si+00eh], strict word 00000h ; 26 c7 44 0e 00 00 ; 0xf6988
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf698e system.c:602
+ mov word [es:si+010h], ax ; 26 89 44 10 ; 0xf6991
+ mov word [es:si+012h], strict word 00000h ; 26 c7 44 12 00 00 ; 0xf6995
+ pop bp ; 5d ; 0xf699b system.c:603
+ pop si ; 5e ; 0xf699c
+ retn 0000ah ; c2 0a 00 ; 0xf699d
+ ; disGetNextSymbol 0xf69a0 LB 0x36a5 -> off=0x14 cb=0000000000000386 uValue=00000000000f53b4 'int15_function32'
+ db 01bh, 06bh, 03dh, 06bh, 060h, 06bh, 082h, 06bh, 0a2h, 06bh, 0c3h, 06bh, 0e7h, 06bh, 00bh, 06ch
+ db 04ah, 06ch, 076h, 06ch
+int15_function32: ; 0xf69b4 LB 0x386
+ push bp ; 55 ; 0xf69b4 system.c:605
+ mov bp, sp ; 89 e5 ; 0xf69b5
+ push si ; 56 ; 0xf69b7
+ sub sp, strict byte 00008h ; 83 ec 08 ; 0xf69b8
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf69bb system.c:614
+ shr ax, 008h ; c1 e8 08 ; 0xf69be
+ cmp ax, 000e8h ; 3d e8 00 ; 0xf69c1
+ je near 06a3ah ; 0f 84 72 00 ; 0xf69c4
+ cmp ax, 000d0h ; 3d d0 00 ; 0xf69c8
+ jne near 06d0ah ; 0f 85 3b 03 ; 0xf69cb
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf69cf system.c:616
+ xor ah, ah ; 30 e4 ; 0xf69d2
+ cmp ax, strict word 0004fh ; 3d 4f 00 ; 0xf69d4
+ jne near 06d0ah ; 0f 85 2f 03 ; 0xf69d7
+ cmp word [bp+016h], 05052h ; 81 7e 16 52 50 ; 0xf69db system.c:618
+ jne near 06d0ah ; 0f 85 26 03 ; 0xf69e0
+ cmp word [bp+014h], 04f43h ; 81 7e 14 43 4f ; 0xf69e4
+ jne near 06d0ah ; 0f 85 1d 03 ; 0xf69e9
+ cmp word [bp+01eh], 04d4fh ; 81 7e 1e 4f 4d ; 0xf69ed
+ jne near 06d0ah ; 0f 85 14 03 ; 0xf69f2
+ cmp word [bp+01ch], 04445h ; 81 7e 1c 45 44 ; 0xf69f6
+ jne near 06d0ah ; 0f 85 0b 03 ; 0xf69fb
+ mov ax, word [bp+00ah] ; 8b 46 0a ; 0xf69ff
+ or ax, word [bp+008h] ; 0b 46 08 ; 0xf6a02
+ jne near 06d0ah ; 0f 85 01 03 ; 0xf6a05
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf6a09
+ or ax, word [bp+004h] ; 0b 46 04 ; 0xf6a0c
+ jne near 06d0ah ; 0f 85 f7 02 ; 0xf6a0f
+ and byte [bp+028h], 0feh ; 80 66 28 fe ; 0xf6a13 system.c:620
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf6a17 system.c:621
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf6a1a
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6a1d
+ mov word [bp+00ah], ax ; 89 46 0a ; 0xf6a20
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf6a23 system.c:622
+ mov word [bp+004h], ax ; 89 46 04 ; 0xf6a26
+ mov ax, word [bp+01eh] ; 8b 46 1e ; 0xf6a29
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf6a2c
+ mov dword [bp+020h], strict dword 049413332h ; 66 c7 46 20 32 33 41 49 ; 0xf6a2f system.c:623
+ jmp near 06d34h ; e9 fa 02 ; 0xf6a37 system.c:627
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf6a3a system.c:630
+ xor ah, ah ; 30 e4 ; 0xf6a3d
+ cmp ax, strict word 00020h ; 3d 20 00 ; 0xf6a3f
+ je short 06a4eh ; 74 0a ; 0xf6a42
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf6a44
+ je near 06cbdh ; 0f 84 72 02 ; 0xf6a47
+ jmp near 06d0ah ; e9 bc 02 ; 0xf6a4b
+ cmp word [bp+01ah], 0534dh ; 81 7e 1a 4d 53 ; 0xf6a4e system.c:632
+ jne near 06d0ah ; 0f 85 b3 02 ; 0xf6a53
+ cmp word [bp+018h], 04150h ; 81 7e 18 50 41 ; 0xf6a57
+ jne near 06d0ah ; 0f 85 aa 02 ; 0xf6a5c
+ mov ax, strict word 00035h ; b8 35 00 ; 0xf6a60 system.c:633
+ call 01756h ; e8 f0 ac ; 0xf6a63
+ movzx bx, al ; 0f b6 d8 ; 0xf6a66
+ xor dx, dx ; 31 d2 ; 0xf6a69
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf6a6b system.c:634
+ sal bx, 1 ; d1 e3 ; 0xf6a6e
+ rcl dx, 1 ; d1 d2 ; 0xf6a70
+ loop 06a6eh ; e2 fa ; 0xf6a72
+ mov ax, strict word 00034h ; b8 34 00 ; 0xf6a74 system.c:635
+ call 01756h ; e8 dc ac ; 0xf6a77
+ xor ah, ah ; 30 e4 ; 0xf6a7a
+ mov dx, bx ; 89 da ; 0xf6a7c
+ or dx, ax ; 09 c2 ; 0xf6a7e
+ xor bx, bx ; 31 db ; 0xf6a80 system.c:644
+ add bx, bx ; 01 db ; 0xf6a82
+ adc dx, 00100h ; 81 d2 00 01 ; 0xf6a84
+ cmp dx, 00100h ; 81 fa 00 01 ; 0xf6a88 system.c:646
+ jc short 06a94h ; 72 06 ; 0xf6a8c
+ jne short 06ac1h ; 75 31 ; 0xf6a8e
+ test bx, bx ; 85 db ; 0xf6a90
+ jnbe short 06ac1h ; 77 2d ; 0xf6a92
+ mov ax, strict word 00031h ; b8 31 00 ; 0xf6a94 system.c:647
+ call 01756h ; e8 bc ac ; 0xf6a97
+ movzx bx, al ; 0f b6 d8 ; 0xf6a9a
+ xor dx, dx ; 31 d2 ; 0xf6a9d
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf6a9f system.c:648
+ sal bx, 1 ; d1 e3 ; 0xf6aa2
+ rcl dx, 1 ; d1 d2 ; 0xf6aa4
+ loop 06aa2h ; e2 fa ; 0xf6aa6
+ mov ax, strict word 00030h ; b8 30 00 ; 0xf6aa8 system.c:649
+ call 01756h ; e8 a8 ac ; 0xf6aab
+ xor ah, ah ; 30 e4 ; 0xf6aae
+ or bx, ax ; 09 c3 ; 0xf6ab0
+ mov cx, strict word 0000ah ; b9 0a 00 ; 0xf6ab2 system.c:650
+ sal bx, 1 ; d1 e3 ; 0xf6ab5
+ rcl dx, 1 ; d1 d2 ; 0xf6ab7
+ loop 06ab5h ; e2 fa ; 0xf6ab9
+ add bx, strict byte 00000h ; 83 c3 00 ; 0xf6abb system.c:651
+ adc dx, strict byte 00010h ; 83 d2 10 ; 0xf6abe
+ mov ax, strict word 00062h ; b8 62 00 ; 0xf6ac1 system.c:656
+ call 01756h ; e8 8f ac ; 0xf6ac4
+ xor ah, ah ; 30 e4 ; 0xf6ac7
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf6ac9
+ xor al, al ; 30 c0 ; 0xf6acc
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf6ace
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf6ad1 system.c:657
+ sal word [bp-00ah], 1 ; d1 66 f6 ; 0xf6ad4
+ rcl word [bp-008h], 1 ; d1 56 f8 ; 0xf6ad7
+ loop 06ad4h ; e2 f8 ; 0xf6ada
+ mov ax, strict word 00061h ; b8 61 00 ; 0xf6adc system.c:658
+ call 01756h ; e8 74 ac ; 0xf6adf
+ xor ah, ah ; 30 e4 ; 0xf6ae2
+ or word [bp-00ah], ax ; 09 46 f6 ; 0xf6ae4
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf6ae7 system.c:659
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf6aea
+ mov word [bp-00ah], strict word 00000h ; c7 46 f6 00 00 ; 0xf6aed
+ mov ax, strict word 00063h ; b8 63 00 ; 0xf6af2 system.c:660
+ call 01756h ; e8 5e ac ; 0xf6af5
+ mov byte [bp-004h], al ; 88 46 fc ; 0xf6af8
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf6afb
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf6afe system.c:674
+ cmp ax, strict word 00009h ; 3d 09 00 ; 0xf6b01
+ jnbe near 06d0ah ; 0f 87 02 02 ; 0xf6b04
+ mov si, ax ; 89 c6 ; 0xf6b08
+ add si, ax ; 01 c6 ; 0xf6b0a
+ mov cx, bx ; 89 d9 ; 0xf6b0c
+ add cx, strict byte 00000h ; 83 c1 00 ; 0xf6b0e
+ mov ax, dx ; 89 d0 ; 0xf6b11
+ adc ax, strict word 0ffffh ; 15 ff ff ; 0xf6b13
+ jmp word [cs:si+069a0h] ; 2e ff a4 a0 69 ; 0xf6b16
+ push strict byte 00001h ; 6a 01 ; 0xf6b1b system.c:677
+ push dword 000000000h ; 66 6a 00 ; 0xf6b1d
+ push strict byte 00009h ; 6a 09 ; 0xf6b20
+ push 0fc00h ; 68 00 fc ; 0xf6b22
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf6b25
+ mov ax, word [bp+024h] ; 8b 46 24 ; 0xf6b28
+ xor bx, bx ; 31 db ; 0xf6b2b
+ xor cx, cx ; 31 c9 ; 0xf6b2d
+ call 06949h ; e8 17 fe ; 0xf6b2f
+ mov dword [bp+014h], strict dword 000000001h ; 66 c7 46 14 01 00 00 00 ; 0xf6b32 system.c:683
+ jmp near 06ca7h ; e9 6a 01 ; 0xf6b3a system.c:684
+ push strict byte 00002h ; 6a 02 ; 0xf6b3d system.c:686
+ push dword 000000000h ; 66 6a 00 ; 0xf6b3f
+ push strict byte 0000ah ; 6a 0a ; 0xf6b42
+ push strict byte 00000h ; 6a 00 ; 0xf6b44
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf6b46
+ mov ax, word [bp+024h] ; 8b 46 24 ; 0xf6b49
+ mov bx, 0fc00h ; bb 00 fc ; 0xf6b4c
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf6b4f
+ call 06949h ; e8 f4 fd ; 0xf6b52
+ mov dword [bp+014h], strict dword 000000002h ; 66 c7 46 14 02 00 00 00 ; 0xf6b55 system.c:692
+ jmp near 06ca7h ; e9 47 01 ; 0xf6b5d system.c:693
+ push strict byte 00002h ; 6a 02 ; 0xf6b60 system.c:707
+ push dword 000000000h ; 66 6a 00 ; 0xf6b62
+ push strict byte 00010h ; 6a 10 ; 0xf6b65
+ push strict byte 00000h ; 6a 00 ; 0xf6b67
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf6b69
+ mov ax, word [bp+024h] ; 8b 46 24 ; 0xf6b6c
+ xor bx, bx ; 31 db ; 0xf6b6f
+ mov cx, strict word 0000fh ; b9 0f 00 ; 0xf6b71
+ call 06949h ; e8 d2 fd ; 0xf6b74
+ mov dword [bp+014h], strict dword 000000003h ; 66 c7 46 14 03 00 00 00 ; 0xf6b77 system.c:713
+ jmp near 06ca7h ; e9 25 01 ; 0xf6b7f system.c:714
+ push strict byte 00001h ; 6a 01 ; 0xf6b82 system.c:717
+ push dword 000000000h ; 66 6a 00 ; 0xf6b84
+ push ax ; 50 ; 0xf6b87
+ push cx ; 51 ; 0xf6b88
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf6b89
+ mov ax, word [bp+024h] ; 8b 46 24 ; 0xf6b8c
+ xor bx, bx ; 31 db ; 0xf6b8f
+ mov cx, strict word 00010h ; b9 10 00 ; 0xf6b91
+ call 06949h ; e8 b2 fd ; 0xf6b94
+ mov dword [bp+014h], strict dword 000000004h ; 66 c7 46 14 04 00 00 00 ; 0xf6b97 system.c:720
+ jmp near 06ca7h ; e9 05 01 ; 0xf6b9f system.c:727
+ push strict byte 00003h ; 6a 03 ; 0xf6ba2 system.c:729
+ push dword 000000000h ; 66 6a 00 ; 0xf6ba4
+ push dx ; 52 ; 0xf6ba7
+ push bx ; 53 ; 0xf6ba8
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf6ba9
+ mov si, word [bp+024h] ; 8b 76 24 ; 0xf6bac
+ mov bx, cx ; 89 cb ; 0xf6baf
+ mov cx, ax ; 89 c1 ; 0xf6bb1
+ mov ax, si ; 89 f0 ; 0xf6bb3
+ call 06949h ; e8 91 fd ; 0xf6bb5
+ mov dword [bp+014h], strict dword 000000005h ; 66 c7 46 14 05 00 00 00 ; 0xf6bb8 system.c:732
+ jmp near 06ca7h ; e9 e4 00 ; 0xf6bc0 system.c:733
+ push strict byte 00002h ; 6a 02 ; 0xf6bc3 system.c:735
+ push dword 000000000h ; 66 6a 00 ; 0xf6bc5
+ push 0fec0h ; 68 c0 fe ; 0xf6bc8
+ push 01000h ; 68 00 10 ; 0xf6bcb
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf6bce
+ mov ax, word [bp+024h] ; 8b 46 24 ; 0xf6bd1
+ xor bx, bx ; 31 db ; 0xf6bd4
+ mov cx, 0fec0h ; b9 c0 fe ; 0xf6bd6
+ call 06949h ; e8 6d fd ; 0xf6bd9
+ mov dword [bp+014h], strict dword 000000006h ; 66 c7 46 14 06 00 00 00 ; 0xf6bdc system.c:738
+ jmp near 06ca7h ; e9 c0 00 ; 0xf6be4 system.c:739
+ push strict byte 00002h ; 6a 02 ; 0xf6be7 system.c:741
+ push dword 000000000h ; 66 6a 00 ; 0xf6be9
+ push 0fee0h ; 68 e0 fe ; 0xf6bec
+ push 01000h ; 68 00 10 ; 0xf6bef
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf6bf2
+ mov ax, word [bp+024h] ; 8b 46 24 ; 0xf6bf5
+ xor bx, bx ; 31 db ; 0xf6bf8
+ mov cx, 0fee0h ; b9 e0 fe ; 0xf6bfa
+ call 06949h ; e8 49 fd ; 0xf6bfd
+ mov dword [bp+014h], strict dword 000000007h ; 66 c7 46 14 07 00 00 00 ; 0xf6c00 system.c:744
+ jmp near 06ca7h ; e9 9c 00 ; 0xf6c08 system.c:745
+ push strict byte 00002h ; 6a 02 ; 0xf6c0b system.c:752
+ push dword 000000000h ; 66 6a 00 ; 0xf6c0d
+ push dword 000000000h ; 66 6a 00 ; 0xf6c10
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf6c13
+ mov ax, word [bp+024h] ; 8b 46 24 ; 0xf6c16
+ xor bx, bx ; 31 db ; 0xf6c19
+ mov cx, strict word 0fffch ; b9 fc ff ; 0xf6c1b
+ call 06949h ; e8 28 fd ; 0xf6c1e
+ cmp byte [bp-004h], 000h ; 80 7e fc 00 ; 0xf6c21
+ jne short 06c2eh ; 75 07 ; 0xf6c25
+ mov ax, word [bp-008h] ; 8b 46 f8 ; 0xf6c27
+ test ax, ax ; 85 c0 ; 0xf6c2a
+ je short 06c42h ; 74 14 ; 0xf6c2c
+ mov dword [bp+014h], strict dword 000000009h ; 66 c7 46 14 09 00 00 00 ; 0xf6c2e
+ jmp short 06ca7h ; eb 6f ; 0xf6c36
+ mov dword [bp+014h], strict dword 000000008h ; 66 c7 46 14 08 00 00 00 ; 0xf6c38 system.c:755
+ jmp short 06ca7h ; eb 65 ; 0xf6c40 system.c:756
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf6c42 system.c:761
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf6c45
+ jmp short 06ca7h ; eb 5d ; 0xf6c48 system.c:763
+ push strict byte 00002h ; 6a 02 ; 0xf6c4a system.c:766
+ push dword 000000000h ; 66 6a 00 ; 0xf6c4c
+ push dword 000000000h ; 66 6a 00 ; 0xf6c4f
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf6c52
+ mov ax, word [bp+024h] ; 8b 46 24 ; 0xf6c55
+ xor bx, bx ; 31 db ; 0xf6c58
+ xor cx, cx ; 31 c9 ; 0xf6c5a
+ call 06949h ; e8 ea fc ; 0xf6c5c
+ cmp byte [bp-004h], 000h ; 80 7e fc 00 ; 0xf6c5f system.c:769
+ jne short 06c6ch ; 75 07 ; 0xf6c63
+ mov ax, word [bp-008h] ; 8b 46 f8 ; 0xf6c65
+ test ax, ax ; 85 c0 ; 0xf6c68
+ je short 06c6eh ; 74 02 ; 0xf6c6a
+ jmp short 06c2eh ; eb c0 ; 0xf6c6c
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf6c6e system.c:772
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf6c71
+ jmp short 06ca7h ; eb 31 ; 0xf6c74 system.c:773
+ cmp byte [bp-004h], 000h ; 80 7e fc 00 ; 0xf6c76 system.c:781
+ jne short 06c82h ; 75 06 ; 0xf6c7a
+ cmp word [bp-008h], strict byte 00000h ; 83 7e f8 00 ; 0xf6c7c
+ je short 06ca7h ; 74 25 ; 0xf6c80
+ push strict byte 00001h ; 6a 01 ; 0xf6c82 system.c:783
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf6c84
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf6c87
+ xor ah, ah ; 30 e4 ; 0xf6c89
+ push ax ; 50 ; 0xf6c8b
+ push strict byte 00001h ; 6a 01 ; 0xf6c8c
+ push dword [bp-00ah] ; 66 ff 76 f6 ; 0xf6c8e
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf6c92
+ mov ax, word [bp+024h] ; 8b 46 24 ; 0xf6c95
+ xor bx, bx ; 31 db ; 0xf6c98
+ xor cx, cx ; 31 c9 ; 0xf6c9a
+ call 06949h ; e8 aa fc ; 0xf6c9c
+ xor ax, ax ; 31 c0 ; 0xf6c9f system.c:786
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf6ca1
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf6ca4
+ mov dword [bp+020h], strict dword 0534d4150h ; 66 c7 46 20 50 41 4d 53 ; 0xf6ca7 system.c:802
+ mov dword [bp+01ch], strict dword 000000014h ; 66 c7 46 1c 14 00 00 00 ; 0xf6caf system.c:803
+ and byte [bp+028h], 0feh ; 80 66 28 fe ; 0xf6cb7 system.c:804
+ jmp short 06d34h ; eb 77 ; 0xf6cbb system.c:809
+ and byte [bp+028h], 0feh ; 80 66 28 fe ; 0xf6cbd system.c:813
+ mov ax, strict word 00031h ; b8 31 00 ; 0xf6cc1 system.c:823
+ call 01756h ; e8 8f aa ; 0xf6cc4
+ xor ah, ah ; 30 e4 ; 0xf6cc7
+ mov dx, ax ; 89 c2 ; 0xf6cc9
+ sal dx, 008h ; c1 e2 08 ; 0xf6ccb
+ mov ax, strict word 00030h ; b8 30 00 ; 0xf6cce
+ call 01756h ; e8 82 aa ; 0xf6cd1
+ xor ah, ah ; 30 e4 ; 0xf6cd4
+ or dx, ax ; 09 c2 ; 0xf6cd6
+ mov word [bp+01ch], dx ; 89 56 1c ; 0xf6cd8
+ cmp dx, 03c00h ; 81 fa 00 3c ; 0xf6cdb system.c:826
+ jbe short 06ce6h ; 76 05 ; 0xf6cdf
+ mov word [bp+01ch], 03c00h ; c7 46 1c 00 3c ; 0xf6ce1 system.c:827
+ mov ax, strict word 00035h ; b8 35 00 ; 0xf6ce6 system.c:830
+ call 01756h ; e8 6a aa ; 0xf6ce9
+ movzx dx, al ; 0f b6 d0 ; 0xf6cec
+ sal dx, 008h ; c1 e2 08 ; 0xf6cef
+ mov ax, strict word 00034h ; b8 34 00 ; 0xf6cf2
+ call 01756h ; e8 5e aa ; 0xf6cf5
+ xor ah, ah ; 30 e4 ; 0xf6cf8
+ or dx, ax ; 09 c2 ; 0xf6cfa
+ mov word [bp+018h], dx ; 89 56 18 ; 0xf6cfc
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf6cff system.c:833
+ mov word [bp+020h], ax ; 89 46 20 ; 0xf6d02
+ mov word [bp+014h], dx ; 89 56 14 ; 0xf6d05 system.c:834
+ jmp short 06d34h ; eb 2a ; 0xf6d08 system.c:839
+ mov bx, 00db2h ; bb b2 0d ; 0xf6d0a system.c:844
+ mov cx, ds ; 8c d9 ; 0xf6d0d
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6d0f
+ call 019d3h ; e8 be ac ; 0xf6d12
+ push word [bp+014h] ; ff 76 14 ; 0xf6d15
+ push word [bp+020h] ; ff 76 20 ; 0xf6d18
+ push 008c6h ; 68 c6 08 ; 0xf6d1b
+ push strict byte 00004h ; 6a 04 ; 0xf6d1e
+ call 01a14h ; e8 f1 ac ; 0xf6d20
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf6d23
+ or byte [bp+028h], 001h ; 80 4e 28 01 ; 0xf6d26 system.c:845
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf6d2a system.c:846
+ xor al, al ; 30 c0 ; 0xf6d2d
+ or AL, strict byte 086h ; 0c 86 ; 0xf6d2f
+ mov word [bp+020h], ax ; 89 46 20 ; 0xf6d31
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf6d34 system.c:849
+ pop si ; 5e ; 0xf6d37
+ pop bp ; 5d ; 0xf6d38
+ retn ; c3 ; 0xf6d39
+ ; disGetNextSymbol 0xf6d3a LB 0x330b -> off=0x0 cb=0000000000000156 uValue=00000000000f573a 'int15_blkmove'
+int15_blkmove: ; 0xf6d3a LB 0x156
+ push bp ; 55 ; 0xf6d3a system.c:858
+ mov bp, sp ; 89 e5 ; 0xf6d3b
+ push si ; 56 ; 0xf6d3d
+ push di ; 57 ; 0xf6d3e
+ cli ; fa ; 0xf6d3f system.c:868
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf6d40 system.c:870
+ call 065ebh ; e8 a5 f8 ; 0xf6d43
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf6d46 system.c:893
+ sal bx, 004h ; c1 e3 04 ; 0xf6d49
+ mov ax, word [bp+00ah] ; 8b 46 0a ; 0xf6d4c
+ add ax, bx ; 01 d8 ; 0xf6d4f
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf6d51 system.c:894
+ shr dx, 00ch ; c1 ea 0c ; 0xf6d54
+ mov cl, dl ; 88 d1 ; 0xf6d57
+ cmp ax, bx ; 39 d8 ; 0xf6d59 system.c:895
+ jnc short 06d5fh ; 73 02 ; 0xf6d5b
+ db 0feh, 0c1h
+ ; inc cl ; fe c1 ; 0xf6d5d system.c:896
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6d5f system.c:897
+ add bx, strict byte 00008h ; 83 c3 08 ; 0xf6d62
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf6d65 system.c:51
+ mov word [es:bx], strict word 0002fh ; 26 c7 07 2f 00 ; 0xf6d68
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6d6d system.c:898
+ add bx, strict byte 0000ah ; 83 c3 0a ; 0xf6d70
+ mov word [es:bx], ax ; 26 89 07 ; 0xf6d73 system.c:51
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6d76 system.c:899
+ add bx, strict byte 0000ch ; 83 c3 0c ; 0xf6d79
+ mov byte [es:bx], cl ; 26 88 0f ; 0xf6d7c system.c:43
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6d7f system.c:900
+ add bx, strict byte 0000dh ; 83 c3 0d ; 0xf6d82
+ mov byte [es:bx], 093h ; 26 c6 07 93 ; 0xf6d85 system.c:43
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6d89 system.c:901
+ add bx, strict byte 0000eh ; 83 c3 0e ; 0xf6d8c
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf6d8f system.c:51
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6d94 system.c:904
+ add bx, strict byte 00020h ; 83 c3 20 ; 0xf6d97
+ mov word [es:bx], strict word 0ffffh ; 26 c7 07 ff ff ; 0xf6d9a system.c:51
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6d9f system.c:905
+ add bx, strict byte 00022h ; 83 c3 22 ; 0xf6da2
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf6da5 system.c:53
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6daa system.c:906
+ add bx, strict byte 00024h ; 83 c3 24 ; 0xf6dad
+ mov byte [es:bx], 00fh ; 26 c6 07 0f ; 0xf6db0 system.c:41
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6db4 system.c:907
+ add bx, strict byte 00025h ; 83 c3 25 ; 0xf6db7
+ mov byte [es:bx], 09bh ; 26 c6 07 9b ; 0xf6dba system.c:41
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6dbe system.c:908
+ add bx, strict byte 00026h ; 83 c3 26 ; 0xf6dc1
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf6dc4 system.c:51
+ mov ax, ss ; 8c d0 ; 0xf6dc9 system.c:911
+ mov cx, ax ; 89 c1 ; 0xf6dcb
+ sal ax, 004h ; c1 e0 04 ; 0xf6dcd system.c:912
+ shr cx, 00ch ; c1 e9 0c ; 0xf6dd0
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6dd3 system.c:914
+ add bx, strict byte 00028h ; 83 c3 28 ; 0xf6dd6
+ mov word [es:bx], strict word 0ffffh ; 26 c7 07 ff ff ; 0xf6dd9 system.c:51
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6dde system.c:915
+ add bx, strict byte 0002ah ; 83 c3 2a ; 0xf6de1
+ mov word [es:bx], ax ; 26 89 07 ; 0xf6de4 system.c:51
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6de7 system.c:916
+ add bx, strict byte 0002ch ; 83 c3 2c ; 0xf6dea
+ mov byte [es:bx], cl ; 26 88 0f ; 0xf6ded system.c:41
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6df0 system.c:917
+ add bx, strict byte 0002dh ; 83 c3 2d ; 0xf6df3
+ mov byte [es:bx], 093h ; 26 c6 07 93 ; 0xf6df6 system.c:43
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf6dfa system.c:918
+ add bx, strict byte 0002eh ; 83 c3 2e ; 0xf6dfd
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf6e00 system.c:53
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf6e05 system.c:924
+ mov cx, word [bp+014h] ; 8b 4e 14 ; 0xf6e08
+ push DS ; 1e ; 0xf6e0b
+ push eax ; 66 50 ; 0xf6e0c
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf6e0e
+ mov ds, ax ; 8e d8 ; 0xf6e10
+ mov word [00467h], sp ; 89 26 67 04 ; 0xf6e12
+ mov [00469h], ss ; 8c 16 69 04 ; 0xf6e16
+ lgdt [es:si+008h] ; 26 0f 01 54 08 ; 0xf6e1a system.c:928
+ lidt [cs:0efe1h] ; 2e 0f 01 1e e1 ef ; 0xf6e1f
+ push strict byte 00020h ; 6a 20 ; 0xf6e25
+ call 06e2ah ; e8 00 00 ; 0xf6e27
+ pop ax ; 58 ; 0xf6e2a
+ add ax, strict byte 0000eh ; 83 c0 0e ; 0xf6e2b
+ push ax ; 50 ; 0xf6e2e
+ mov eax, cr0 ; 0f 20 c0 ; 0xf6e2f
+ or AL, strict byte 001h ; 0c 01 ; 0xf6e32
+ mov cr0, eax ; 0f 22 c0 ; 0xf6e34
+ retf ; cb ; 0xf6e37
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf6e38
+ mov ds, ax ; 8e d8 ; 0xf6e3b
+ add AL, strict byte 008h ; 04 08 ; 0xf6e3d
+ mov es, ax ; 8e c0 ; 0xf6e3f
+ add AL, strict byte 010h ; 04 10 ; 0xf6e41
+ mov ss, ax ; 8e d0 ; 0xf6e43
+ db 033h, 0f6h
+ ; xor si, si ; 33 f6 ; 0xf6e45 system.c:929
+ db 033h, 0ffh
+ ; xor di, di ; 33 ff ; 0xf6e47
+ cld ; fc ; 0xf6e49
+ rep movsw ; f3 a5 ; 0xf6e4a
+ mov ax, strict word 00028h ; b8 28 00 ; 0xf6e4c system.c:930
+ mov ds, ax ; 8e d8 ; 0xf6e4f
+ mov es, ax ; 8e c0 ; 0xf6e51
+ push 0f000h ; 68 00 f0 ; 0xf6e53
+ call 06e59h ; e8 00 00 ; 0xf6e56
+ pop ax ; 58 ; 0xf6e59
+ add ax, strict byte 0000eh ; 83 c0 0e ; 0xf6e5a
+ push ax ; 50 ; 0xf6e5d
+ mov eax, cr0 ; 0f 20 c0 ; 0xf6e5e
+ and AL, strict byte 0feh ; 24 fe ; 0xf6e61
+ mov cr0, eax ; 0f 22 c0 ; 0xf6e63
+ retf ; cb ; 0xf6e66
+ lidt [cs:0efe7h] ; 2e 0f 01 1e e7 ef ; 0xf6e67
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf6e6d system.c:931
+ mov ds, ax ; 8e d8 ; 0xf6e6f
+ mov es, ax ; 8e c0 ; 0xf6e71
+ lss sp, [00467h] ; 0f b2 26 67 04 ; 0xf6e73
+ pop eax ; 66 58 ; 0xf6e78
+ pop DS ; 1f ; 0xf6e7a
+ xor ax, ax ; 31 c0 ; 0xf6e7b system.c:933
+ call 065ebh ; e8 6b f7 ; 0xf6e7d
+ sti ; fb ; 0xf6e80 system.c:936
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf6e81 system.c:938
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf6e85 system.c:939
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf6e89 system.c:940
+ pop di ; 5f ; 0xf6e8c
+ pop si ; 5e ; 0xf6e8d
+ pop bp ; 5d ; 0xf6e8e
+ retn ; c3 ; 0xf6e8f
+ ; disGetNextSymbol 0xf6e90 LB 0x31b5 -> off=0x0 cb=0000000000000195 uValue=00000000000f5890 'inv_op_handler'
+inv_op_handler: ; 0xf6e90 LB 0x195
+ push bp ; 55 ; 0xf6e90 invop.c:237
+ mov bp, sp ; 89 e5 ; 0xf6e91
+ push si ; 56 ; 0xf6e93
+ push di ; 57 ; 0xf6e94
+ push ax ; 50 ; 0xf6e95
+ push ax ; 50 ; 0xf6e96
+ les bx, [bp+018h] ; c4 5e 18 ; 0xf6e97 invop.c:239
+ cmp byte [es:bx], 0f0h ; 26 80 3f f0 ; 0xf6e9a invop.c:241
+ jne short 06ea6h ; 75 06 ; 0xf6e9e
+ inc word [bp+018h] ; ff 46 18 ; 0xf6ea0 invop.c:243
+ jmp near 0701eh ; e9 78 01 ; 0xf6ea3 invop.c:244
+ cmp word [es:bx], 0050fh ; 26 81 3f 0f 05 ; 0xf6ea6
+ jne near 0701ah ; 0f 85 6b 01 ; 0xf6eab
+ mov si, 00800h ; be 00 08 ; 0xf6eaf invop.c:246
+ xor ax, ax ; 31 c0 ; 0xf6eb2
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf6eb4
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf6eb7 invop.c:249
+ mov es, ax ; 8e c0 ; 0xf6eba invop.c:257
+ mov bx, word [es:si+02ch] ; 26 8b 5c 2c ; 0xf6ebc
+ sub bx, strict byte 00006h ; 83 eb 06 ; 0xf6ec0
+ mov dx, word [es:si+020h] ; 26 8b 54 20 ; 0xf6ec3
+ mov ax, word [es:si+01ah] ; 26 8b 44 1a ; 0xf6ec7 invop.c:258
+ mov es, dx ; 8e c2 ; 0xf6ecb
+ mov word [es:bx], ax ; 26 89 07 ; 0xf6ecd
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6ed0 invop.c:259
+ mov ax, word [es:si+022h] ; 26 8b 44 22 ; 0xf6ed3
+ mov es, dx ; 8e c2 ; 0xf6ed7
+ mov word [es:bx+002h], ax ; 26 89 47 02 ; 0xf6ed9
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6edd invop.c:260
+ mov ax, word [es:si+018h] ; 26 8b 44 18 ; 0xf6ee0
+ mov es, dx ; 8e c2 ; 0xf6ee4
+ mov word [es:bx+004h], ax ; 26 89 47 04 ; 0xf6ee6
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6eea invop.c:263
+ movzx bx, byte [es:si+038h] ; 26 0f b6 5c 38 ; 0xf6eed
+ mov di, word [es:si+036h] ; 26 8b 7c 36 ; 0xf6ef2
+ mov ax, word [es:si+024h] ; 26 8b 44 24 ; 0xf6ef6 invop.c:264
+ xor dx, dx ; 31 d2 ; 0xf6efa
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf6efc
+ sal ax, 1 ; d1 e0 ; 0xf6eff
+ rcl dx, 1 ; d1 d2 ; 0xf6f01
+ loop 06effh ; e2 fa ; 0xf6f03
+ cmp bx, dx ; 39 d3 ; 0xf6f05
+ jne short 06f0dh ; 75 04 ; 0xf6f07
+ cmp di, ax ; 39 c7 ; 0xf6f09
+ je short 06f12h ; 74 05 ; 0xf6f0b
+ mov word [bp-008h], strict word 00001h ; c7 46 f8 01 00 ; 0xf6f0d invop.c:265
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6f12 invop.c:266
+ movzx di, byte [es:si+04ah] ; 26 0f b6 7c 4a ; 0xf6f15
+ mov bx, word [es:si+048h] ; 26 8b 5c 48 ; 0xf6f1a
+ mov ax, word [es:si+01eh] ; 26 8b 44 1e ; 0xf6f1e invop.c:267
+ xor dx, dx ; 31 d2 ; 0xf6f22
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf6f24
+ sal ax, 1 ; d1 e0 ; 0xf6f27
+ rcl dx, 1 ; d1 d2 ; 0xf6f29
+ loop 06f27h ; e2 fa ; 0xf6f2b
+ cmp di, dx ; 39 d7 ; 0xf6f2d
+ jne short 06f35h ; 75 04 ; 0xf6f2f
+ cmp bx, ax ; 39 c3 ; 0xf6f31
+ je short 06f39h ; 74 04 ; 0xf6f33
+ or byte [bp-008h], 002h ; 80 4e f8 02 ; 0xf6f35 invop.c:268
+ push strict byte 00000h ; 6a 00 ; 0xf6f39 invop.c:271
+ push 00800h ; 68 00 08 ; 0xf6f3b
+ push strict byte 0001fh ; 6a 1f ; 0xf6f3e
+ db 08bh, 0dch
+ ; mov bx, sp ; 8b dc ; 0xf6f40
+ lgdt [ss:bx] ; 36 0f 01 17 ; 0xf6f42
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf6f46
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf6f49 invop.c:274
+ mov ax, word [es:si+03ah] ; 26 8b 44 3a ; 0xf6f4c
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf6f50
+ mov ax, word [es:si+036h] ; 26 8b 44 36 ; 0xf6f54 invop.c:275
+ mov word [es:si+00ah], ax ; 26 89 44 0a ; 0xf6f58
+ movzx dx, byte [es:si+039h] ; 26 0f b6 54 39 ; 0xf6f5c invop.c:276
+ sal dx, 008h ; c1 e2 08 ; 0xf6f61
+ movzx ax, byte [es:si+038h] ; 26 0f b6 44 38 ; 0xf6f64
+ or dx, ax ; 09 c2 ; 0xf6f69
+ mov word [es:si+00ch], dx ; 26 89 54 0c ; 0xf6f6b
+ mov word [es:si+00eh], strict word 00000h ; 26 c7 44 0e 00 00 ; 0xf6f6f invop.c:277
+ mov ax, word [es:si+04ch] ; 26 8b 44 4c ; 0xf6f75 invop.c:280
+ mov word [es:si], ax ; 26 89 04 ; 0xf6f79
+ mov ax, word [es:si+048h] ; 26 8b 44 48 ; 0xf6f7c invop.c:281
+ mov word [es:si+002h], ax ; 26 89 44 02 ; 0xf6f80
+ movzx dx, byte [es:si+04bh] ; 26 0f b6 54 4b ; 0xf6f84 invop.c:282
+ sal dx, 008h ; c1 e2 08 ; 0xf6f89
+ movzx ax, byte [es:si+04ah] ; 26 0f b6 44 4a ; 0xf6f8c
+ or dx, ax ; 09 c2 ; 0xf6f91
+ mov word [es:si+004h], dx ; 26 89 54 04 ; 0xf6f93
+ movzx ax, byte [es:si+05ch] ; 26 0f b6 44 5c ; 0xf6f97 invop.c:285
+ mov dx, word [es:si+05ah] ; 26 8b 54 5a ; 0xf6f9c
+ push ax ; 50 ; 0xf6fa0 invop.c:286
+ push dx ; 52 ; 0xf6fa1
+ push word [es:si+05eh] ; 26 ff 74 5e ; 0xf6fa2
+ db 08bh, 0dch
+ ; mov bx, sp ; 8b dc ; 0xf6fa6
+ lidt [ss:bx] ; 36 0f 01 1f ; 0xf6fa8
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf6fac
+ mov cx, word [bp-008h] ; 8b 4e f8 ; 0xf6faf invop.c:289
+ mov ax, 00080h ; b8 80 00 ; 0xf6fb2
+ mov ss, ax ; 8e d0 ; 0xf6fb5
+ mov ax, word [ss:0001eh] ; 36 a1 1e 00 ; 0xf6fb7
+ mov ds, ax ; 8e d8 ; 0xf6fbb
+ mov ax, word [ss:00024h] ; 36 a1 24 00 ; 0xf6fbd
+ mov es, ax ; 8e c0 ; 0xf6fc1
+ smsw ax ; 0f 01 e0 ; 0xf6fc3 invop.c:290
+ inc ax ; 40 ; 0xf6fc6
+ lmsw ax ; 0f 01 f0 ; 0xf6fc7
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf6fca
+ test cx, strict word 00001h ; f7 c1 01 00 ; 0xf6fcd
+ je near 06fd7h ; 0f 84 02 00 ; 0xf6fd1
+ mov es, ax ; 8e c0 ; 0xf6fd5
+ test cx, strict word 00002h ; f7 c1 02 00 ; 0xf6fd7
+ je near 06fffh ; 0f 84 20 00 ; 0xf6fdb
+ mov bx, word [word ss:00000h] ; 36 8b 1e 00 00 ; 0xf6fdf
+ mov word [word ss:00008h], bx ; 36 89 1e 08 00 ; 0xf6fe4
+ mov bx, word [word ss:00002h] ; 36 8b 1e 02 00 ; 0xf6fe9
+ mov word [word ss:0000ah], bx ; 36 89 1e 0a 00 ; 0xf6fee
+ mov bx, word [word ss:00004h] ; 36 8b 1e 04 00 ; 0xf6ff3
+ mov word [word ss:0000ch], bx ; 36 89 1e 0c 00 ; 0xf6ff8
+ mov ds, ax ; 8e d8 ; 0xf6ffd
+ mov eax, cr0 ; 0f 20 c0 ; 0xf6fff
+ dec ax ; 48 ; 0xf7002
+ mov cr0, eax ; 0f 22 c0 ; 0xf7003
+ mov sp, strict word 00026h ; bc 26 00 ; 0xf7006 invop.c:291
+ popaw ; 61 ; 0xf7009
+ mov sp, word [word ss:0002ch] ; 36 8b 26 2c 00 ; 0xf700a
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf700f
+ mov ss, [word ss:00020h] ; 36 8e 16 20 00 ; 0xf7012
+ iret ; cf ; 0xf7017
+ jmp short 0701eh ; eb 04 ; 0xf7018 invop.c:343
+ sti ; fb ; 0xf701a invop.c:347
+ hlt ; f4 ; 0xf701b invop.c:348
+ jmp short 0701bh ; eb fd ; 0xf701c
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf701e invop.c:350
+ pop di ; 5f ; 0xf7021
+ pop si ; 5e ; 0xf7022
+ pop bp ; 5d ; 0xf7023
+ retn ; c3 ; 0xf7024
+ ; disGetNextSymbol 0xf7025 LB 0x3020 -> off=0x0 cb=0000000000000028 uValue=00000000000f5a25 'init_rtc'
+init_rtc: ; 0xf7025 LB 0x28
+ push bp ; 55 ; 0xf7025 timepci.c:74
+ mov bp, sp ; 89 e5 ; 0xf7026
+ push dx ; 52 ; 0xf7028
+ mov dx, strict word 00026h ; ba 26 00 ; 0xf7029 timepci.c:76
+ mov ax, strict word 0000ah ; b8 0a 00 ; 0xf702c
+ call 01773h ; e8 41 a7 ; 0xf702f
+ mov dx, strict word 00002h ; ba 02 00 ; 0xf7032 timepci.c:77
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf7035
+ call 01773h ; e8 38 a7 ; 0xf7038
+ mov ax, strict word 0000ch ; b8 0c 00 ; 0xf703b timepci.c:78
+ call 01756h ; e8 15 a7 ; 0xf703e
+ mov ax, strict word 0000dh ; b8 0d 00 ; 0xf7041 timepci.c:79
+ call 01756h ; e8 0f a7 ; 0xf7044
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf7047 timepci.c:80
+ pop dx ; 5a ; 0xf704a
+ pop bp ; 5d ; 0xf704b
+ retn ; c3 ; 0xf704c
+ ; disGetNextSymbol 0xf704d LB 0x2ff8 -> off=0x0 cb=0000000000000021 uValue=00000000000f5a4d 'rtc_updating'
+rtc_updating: ; 0xf704d LB 0x21
+ push bp ; 55 ; 0xf704d timepci.c:82
+ mov bp, sp ; 89 e5 ; 0xf704e
+ push dx ; 52 ; 0xf7050
+ mov dx, 061a8h ; ba a8 61 ; 0xf7051 timepci.c:95
+ dec dx ; 4a ; 0xf7054 timepci.c:96
+ je short 07065h ; 74 0e ; 0xf7055
+ mov ax, strict word 0000ah ; b8 0a 00 ; 0xf7057 timepci.c:97
+ call 01756h ; e8 f9 a6 ; 0xf705a
+ test AL, strict byte 080h ; a8 80 ; 0xf705d
+ jne short 07054h ; 75 f3 ; 0xf705f
+ xor ax, ax ; 31 c0 ; 0xf7061 timepci.c:98
+ jmp short 07068h ; eb 03 ; 0xf7063
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf7065 timepci.c:100
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf7068 timepci.c:101
+ pop dx ; 5a ; 0xf706b
+ pop bp ; 5d ; 0xf706c
+ retn ; c3 ; 0xf706d
+ ; disGetNextSymbol 0xf706e LB 0x2fd7 -> off=0x0 cb=0000000000000091 uValue=00000000000f5a6e 'int70_function'
+int70_function: ; 0xf706e LB 0x91
+ push bp ; 55 ; 0xf706e timepci.c:110
+ mov bp, sp ; 89 e5 ; 0xf706f
+ push si ; 56 ; 0xf7071
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf7072 timepci.c:116
+ call 01756h ; e8 de a6 ; 0xf7075
+ mov bl, al ; 88 c3 ; 0xf7078
+ mov dh, al ; 88 c6 ; 0xf707a
+ mov ax, strict word 0000ch ; b8 0c 00 ; 0xf707c timepci.c:117
+ call 01756h ; e8 d4 a6 ; 0xf707f
+ mov dl, al ; 88 c2 ; 0xf7082
+ test bl, 060h ; f6 c3 60 ; 0xf7084 timepci.c:119
+ je short 070f6h ; 74 6d ; 0xf7087
+ test AL, strict byte 020h ; a8 20 ; 0xf7089 timepci.c:120
+ je short 07091h ; 74 04 ; 0xf708b
+ sti ; fb ; 0xf708d timepci.c:122
+ int 04ah ; cd 4a ; 0xf708e timepci.c:123
+ cli ; fa ; 0xf7090 timepci.c:124
+ test dl, 040h ; f6 c2 40 ; 0xf7091 timepci.c:126
+ je short 070f6h ; 74 60 ; 0xf7094
+ mov bx, 000a0h ; bb a0 00 ; 0xf7096 timepci.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf7099
+ mov es, ax ; 8e c0 ; 0xf709c
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf709e
+ test al, al ; 84 c0 ; 0xf70a1 timepci.c:39
+ je short 070f6h ; 74 51 ; 0xf70a3
+ mov bx, 0009ch ; bb 9c 00 ; 0xf70a5 timepci.c:58
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf70a8
+ mov bx, word [es:bx+002h] ; 26 8b 5f 02 ; 0xf70ab
+ test bx, bx ; 85 db ; 0xf70af timepci.c:134
+ jne short 070e4h ; 75 31 ; 0xf70b1
+ cmp ax, 003d1h ; 3d d1 03 ; 0xf70b3
+ jnc short 070e4h ; 73 2c ; 0xf70b6
+ mov bx, 00098h ; bb 98 00 ; 0xf70b8 timepci.c:48
+ mov cx, word [es:bx] ; 26 8b 0f ; 0xf70bb
+ mov bx, 0009ah ; bb 9a 00 ; 0xf70be timepci.c:48
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf70c1
+ mov si, 000a0h ; be a0 00 ; 0xf70c4 timepci.c:43
+ mov byte [es:si], 000h ; 26 c6 04 00 ; 0xf70c7
+ mov al, dh ; 88 f0 ; 0xf70cb timepci.c:141
+ and AL, strict byte 037h ; 24 37 ; 0xf70cd
+ movzx dx, al ; 0f b6 d0 ; 0xf70cf
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf70d2
+ call 01773h ; e8 9b a6 ; 0xf70d5
+ mov es, cx ; 8e c1 ; 0xf70d8 timepci.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf70da
+ or AL, strict byte 080h ; 0c 80 ; 0xf70dd timepci.c:39
+ mov byte [es:bx], al ; 26 88 07 ; 0xf70df timepci.c:43
+ jmp short 070f6h ; eb 12 ; 0xf70e2 timepci.c:143
+ add ax, 0fc2fh ; 05 2f fc ; 0xf70e4 timepci.c:145
+ mov dx, bx ; 89 da ; 0xf70e7
+ adc dx, strict byte 0ffffh ; 83 d2 ff ; 0xf70e9
+ mov bx, 0009ch ; bb 9c 00 ; 0xf70ec timepci.c:63
+ mov word [es:bx], ax ; 26 89 07 ; 0xf70ef
+ mov word [es:bx+002h], dx ; 26 89 57 02 ; 0xf70f2
+ call 0e030h ; e8 37 6f ; 0xf70f6 timepci.c:151
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf70f9 timepci.c:152
+ pop si ; 5e ; 0xf70fc
+ pop bp ; 5d ; 0xf70fd
+ retn ; c3 ; 0xf70fe
+ ; disGetNextSymbol 0xf70ff LB 0x2f46 -> off=0x10 cb=00000000000001c8 uValue=00000000000f5b0f 'int1a_function'
+ db 026h, 071h, 04fh, 071h, 074h, 071h, 0a6h, 071h, 0f5h, 071h, 02dh, 072h, 070h, 072h, 0c7h, 072h
+int1a_function: ; 0xf710f LB 0x1c8
+ push bp ; 55 ; 0xf710f timepci.c:157
+ mov bp, sp ; 89 e5 ; 0xf7110
+ sti ; fb ; 0xf7112 timepci.c:163
+ mov al, byte [bp+013h] ; 8a 46 13 ; 0xf7113 timepci.c:165
+ cmp AL, strict byte 007h ; 3c 07 ; 0xf7116
+ jnbe near 0714bh ; 0f 87 2f 00 ; 0xf7118
+ movzx bx, al ; 0f b6 d8 ; 0xf711c
+ add bx, bx ; 01 db ; 0xf711f
+ jmp word [cs:bx+070ffh] ; 2e ff a7 ff 70 ; 0xf7121
+ cli ; fa ; 0xf7126 timepci.c:167
+ mov bx, 0046eh ; bb 6e 04 ; 0xf7127 timepci.c:168
+ xor ax, ax ; 31 c0 ; 0xf712a
+ mov es, ax ; 8e c0 ; 0xf712c
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf712e
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf7131
+ mov bx, 0046ch ; bb 6c 04 ; 0xf7134 timepci.c:169
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf7137
+ mov word [bp+00eh], ax ; 89 46 0e ; 0xf713a
+ mov bx, 00470h ; bb 70 04 ; 0xf713d timepci.c:170
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf7140
+ mov byte [bp+012h], al ; 88 46 12 ; 0xf7143
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf7146 timepci.c:171
+ sti ; fb ; 0xf714a timepci.c:172
+ mov sp, bp ; 89 ec ; 0xf714b timepci.c:175
+ pop bp ; 5d ; 0xf714d
+ retn ; c3 ; 0xf714e
+ cli ; fa ; 0xf714f timepci.c:178
+ mov bx, 0046eh ; bb 6e 04 ; 0xf7150 timepci.c:179
+ xor ax, ax ; 31 c0 ; 0xf7153
+ mov es, ax ; 8e c0 ; 0xf7155
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf7157
+ mov word [es:bx], ax ; 26 89 07 ; 0xf715a
+ mov bx, 0046ch ; bb 6c 04 ; 0xf715d timepci.c:180
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf7160
+ mov word [es:bx], ax ; 26 89 07 ; 0xf7163
+ mov bx, 00470h ; bb 70 04 ; 0xf7166 timepci.c:181
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf7169
+ sti ; fb ; 0xf716d timepci.c:182
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf716e timepci.c:183
+ jmp short 0714bh ; eb d7 ; 0xf7172 timepci.c:185
+ call 0704dh ; e8 d6 fe ; 0xf7174 timepci.c:188
+ test ax, ax ; 85 c0 ; 0xf7177
+ je short 0717dh ; 74 02 ; 0xf7179
+ jmp short 0714bh ; eb ce ; 0xf717b timepci.c:190
+ xor ax, ax ; 31 c0 ; 0xf717d timepci.c:193
+ call 01756h ; e8 d4 a5 ; 0xf717f
+ mov byte [bp+00fh], al ; 88 46 0f ; 0xf7182
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf7185 timepci.c:194
+ call 01756h ; e8 cb a5 ; 0xf7188
+ mov byte [bp+010h], al ; 88 46 10 ; 0xf718b
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf718e timepci.c:195
+ call 01756h ; e8 c2 a5 ; 0xf7191
+ mov bl, al ; 88 c3 ; 0xf7194
+ mov byte [bp+011h], al ; 88 46 11 ; 0xf7196
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf7199 timepci.c:196
+ call 01756h ; e8 b7 a5 ; 0xf719c
+ and AL, strict byte 001h ; 24 01 ; 0xf719f
+ mov byte [bp+00eh], al ; 88 46 0e ; 0xf71a1
+ jmp short 071ebh ; eb 45 ; 0xf71a4
+ call 0704dh ; e8 a4 fe ; 0xf71a6 timepci.c:213
+ test ax, ax ; 85 c0 ; 0xf71a9
+ je short 071b0h ; 74 03 ; 0xf71ab
+ call 07025h ; e8 75 fe ; 0xf71ad timepci.c:214
+ movzx dx, byte [bp+00fh] ; 0f b6 56 0f ; 0xf71b0 timepci.c:217
+ xor ax, ax ; 31 c0 ; 0xf71b4
+ call 01773h ; e8 ba a5 ; 0xf71b6
+ movzx dx, byte [bp+010h] ; 0f b6 56 10 ; 0xf71b9 timepci.c:218
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf71bd
+ call 01773h ; e8 b0 a5 ; 0xf71c0
+ movzx dx, byte [bp+011h] ; 0f b6 56 11 ; 0xf71c3 timepci.c:219
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf71c7
+ call 01773h ; e8 a6 a5 ; 0xf71ca
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf71cd timepci.c:221
+ call 01756h ; e8 83 a5 ; 0xf71d0
+ mov bl, al ; 88 c3 ; 0xf71d3
+ and bl, 060h ; 80 e3 60 ; 0xf71d5
+ or bl, 002h ; 80 cb 02 ; 0xf71d8
+ mov al, byte [bp+00eh] ; 8a 46 0e ; 0xf71db
+ and AL, strict byte 001h ; 24 01 ; 0xf71de
+ or bl, al ; 08 c3 ; 0xf71e0
+ movzx dx, bl ; 0f b6 d3 ; 0xf71e2 timepci.c:223
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf71e5
+ call 01773h ; e8 88 a5 ; 0xf71e8
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf71eb
+ mov byte [bp+012h], bl ; 88 5e 12 ; 0xf71ef
+ jmp near 0714bh ; e9 56 ff ; 0xf71f2
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf71f5 timepci.c:230
+ call 0704dh ; e8 51 fe ; 0xf71f9 timepci.c:231
+ test ax, ax ; 85 c0 ; 0xf71fc
+ je short 07203h ; 74 03 ; 0xf71fe
+ jmp near 0714bh ; e9 48 ff ; 0xf7200 timepci.c:233
+ mov ax, strict word 00009h ; b8 09 00 ; 0xf7203 timepci.c:235
+ call 01756h ; e8 4d a5 ; 0xf7206
+ mov byte [bp+010h], al ; 88 46 10 ; 0xf7209
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf720c timepci.c:236
+ call 01756h ; e8 44 a5 ; 0xf720f
+ mov byte [bp+00fh], al ; 88 46 0f ; 0xf7212
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf7215 timepci.c:237
+ call 01756h ; e8 3b a5 ; 0xf7218
+ mov byte [bp+00eh], al ; 88 46 0e ; 0xf721b
+ mov ax, strict word 00032h ; b8 32 00 ; 0xf721e timepci.c:238
+ call 01756h ; e8 32 a5 ; 0xf7221
+ mov byte [bp+011h], al ; 88 46 11 ; 0xf7224
+ mov byte [bp+012h], al ; 88 46 12 ; 0xf7227 timepci.c:239
+ jmp near 0714bh ; e9 1e ff ; 0xf722a timepci.c:241
+ call 0704dh ; e8 1d fe ; 0xf722d timepci.c:254
+ test ax, ax ; 85 c0 ; 0xf7230
+ je short 0723ah ; 74 06 ; 0xf7232
+ call 07025h ; e8 ee fd ; 0xf7234 timepci.c:255
+ jmp near 0714bh ; e9 11 ff ; 0xf7237 timepci.c:257
+ movzx dx, byte [bp+010h] ; 0f b6 56 10 ; 0xf723a timepci.c:259
+ mov ax, strict word 00009h ; b8 09 00 ; 0xf723e
+ call 01773h ; e8 2f a5 ; 0xf7241
+ movzx dx, byte [bp+00fh] ; 0f b6 56 0f ; 0xf7244 timepci.c:260
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf7248
+ call 01773h ; e8 25 a5 ; 0xf724b
+ movzx dx, byte [bp+00eh] ; 0f b6 56 0e ; 0xf724e timepci.c:261
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf7252
+ call 01773h ; e8 1b a5 ; 0xf7255
+ movzx dx, byte [bp+011h] ; 0f b6 56 11 ; 0xf7258 timepci.c:262
+ mov ax, strict word 00032h ; b8 32 00 ; 0xf725c
+ call 01773h ; e8 11 a5 ; 0xf725f
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf7262 timepci.c:263
+ call 01756h ; e8 ee a4 ; 0xf7265
+ mov bl, al ; 88 c3 ; 0xf7268
+ and bl, 07fh ; 80 e3 7f ; 0xf726a
+ jmp near 071e2h ; e9 72 ff ; 0xf726d
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf7270 timepci.c:281
+ call 01756h ; e8 e0 a4 ; 0xf7273
+ mov bl, al ; 88 c3 ; 0xf7276
+ mov word [bp+012h], strict word 00000h ; c7 46 12 00 00 ; 0xf7278 timepci.c:282
+ test AL, strict byte 020h ; a8 20 ; 0xf727d timepci.c:283
+ je short 07284h ; 74 03 ; 0xf727f
+ jmp near 0714bh ; e9 c7 fe ; 0xf7281 timepci.c:286
+ call 0704dh ; e8 c6 fd ; 0xf7284 timepci.c:288
+ test ax, ax ; 85 c0 ; 0xf7287
+ je short 0728eh ; 74 03 ; 0xf7289
+ call 07025h ; e8 97 fd ; 0xf728b timepci.c:289
+ movzx dx, byte [bp+00fh] ; 0f b6 56 0f ; 0xf728e timepci.c:292
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf7292
+ call 01773h ; e8 db a4 ; 0xf7295
+ movzx dx, byte [bp+010h] ; 0f b6 56 10 ; 0xf7298 timepci.c:293
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf729c
+ call 01773h ; e8 d1 a4 ; 0xf729f
+ movzx dx, byte [bp+011h] ; 0f b6 56 11 ; 0xf72a2 timepci.c:294
+ mov ax, strict word 00005h ; b8 05 00 ; 0xf72a6
+ call 01773h ; e8 c7 a4 ; 0xf72a9
+ mov dx, 000a1h ; ba a1 00 ; 0xf72ac timepci.c:295
+ in AL, DX ; ec ; 0xf72af
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf72b0
+ and AL, strict byte 0feh ; 24 fe ; 0xf72b2
+ out DX, AL ; ee ; 0xf72b4
+ mov al, bl ; 88 d8 ; 0xf72b5 timepci.c:297
+ and AL, strict byte 05fh ; 24 5f ; 0xf72b7
+ or AL, strict byte 020h ; 0c 20 ; 0xf72b9
+ movzx dx, al ; 0f b6 d0 ; 0xf72bb
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf72be
+ call 01773h ; e8 af a4 ; 0xf72c1
+ jmp near 0714bh ; e9 84 fe ; 0xf72c4 timepci.c:299
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf72c7 timepci.c:312
+ call 01756h ; e8 89 a4 ; 0xf72ca
+ mov bl, al ; 88 c3 ; 0xf72cd
+ and AL, strict byte 057h ; 24 57 ; 0xf72cf timepci.c:314
+ movzx dx, al ; 0f b6 d0 ; 0xf72d1
+ jmp near 071e5h ; e9 0e ff ; 0xf72d4
+ ; disGetNextSymbol 0xf72d7 LB 0x2d6e -> off=0x0 cb=0000000000000034 uValue=00000000000f5cd7 'send_to_mouse_ctrl'
+send_to_mouse_ctrl: ; 0xf72d7 LB 0x34
+ push bp ; 55 ; 0xf72d7 ps2mouse.c:77
+ mov bp, sp ; 89 e5 ; 0xf72d8
+ push bx ; 53 ; 0xf72da
+ push dx ; 52 ; 0xf72db
+ mov bl, al ; 88 c3 ; 0xf72dc
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf72de ps2mouse.c:81
+ in AL, DX ; ec ; 0xf72e1
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf72e2
+ test AL, strict byte 002h ; a8 02 ; 0xf72e4
+ je short 072f6h ; 74 0e ; 0xf72e6
+ push 00900h ; 68 00 09 ; 0xf72e8 ps2mouse.c:82
+ push 0117ah ; 68 7a 11 ; 0xf72eb
+ push strict byte 00007h ; 6a 07 ; 0xf72ee
+ call 01a14h ; e8 21 a7 ; 0xf72f0
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf72f3
+ mov AL, strict byte 0d4h ; b0 d4 ; 0xf72f6 ps2mouse.c:83
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf72f8
+ out DX, AL ; ee ; 0xf72fb
+ mov al, bl ; 88 d8 ; 0xf72fc ps2mouse.c:84
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf72fe
+ out DX, AL ; ee ; 0xf7301
+ xor al, bl ; 30 d8 ; 0xf7302 ps2mouse.c:86
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7304
+ pop dx ; 5a ; 0xf7307
+ pop bx ; 5b ; 0xf7308
+ pop bp ; 5d ; 0xf7309
+ retn ; c3 ; 0xf730a
+ ; disGetNextSymbol 0xf730b LB 0x2d3a -> off=0x0 cb=000000000000005c uValue=00000000000f5d0b 'get_mouse_data'
+get_mouse_data: ; 0xf730b LB 0x5c
+ push bp ; 55 ; 0xf730b ps2mouse.c:89
+ mov bp, sp ; 89 e5 ; 0xf730c
+ push bx ; 53 ; 0xf730e
+ push cx ; 51 ; 0xf730f
+ push ax ; 50 ; 0xf7310
+ mov bx, ax ; 89 c3 ; 0xf7311
+ mov es, dx ; 8e c2 ; 0xf7313
+ mov cx, 02710h ; b9 10 27 ; 0xf7315 ps2mouse.c:91
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf7318 ps2mouse.c:94
+ in AL, DX ; ec ; 0xf731b
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf731c
+ and ax, strict word 00021h ; 25 21 00 ; 0xf731e
+ cmp ax, strict word 00021h ; 3d 21 00 ; 0xf7321
+ je short 0734dh ; 74 27 ; 0xf7324
+ test cx, cx ; 85 c9 ; 0xf7326
+ je short 0734dh ; 74 23 ; 0xf7328
+ mov dx, strict word 00061h ; ba 61 00 ; 0xf732a ps2mouse.c:97
+ in AL, DX ; ec ; 0xf732d
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf732e
+ and AL, strict byte 010h ; 24 10 ; 0xf7330
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf7332
+ mov dx, strict word 00061h ; ba 61 00 ; 0xf7335 ps2mouse.c:98
+ in AL, DX ; ec ; 0xf7338
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7339
+ mov dx, ax ; 89 c2 ; 0xf733b
+ xor dh, ah ; 30 e6 ; 0xf733d
+ and dl, 010h ; 80 e2 10 ; 0xf733f
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf7342
+ cmp dx, ax ; 39 c2 ; 0xf7346
+ je short 07335h ; 74 eb ; 0xf7348
+ dec cx ; 49 ; 0xf734a ps2mouse.c:100
+ jmp short 07318h ; eb cb ; 0xf734b ps2mouse.c:101
+ test cx, cx ; 85 c9 ; 0xf734d ps2mouse.c:103
+ jne short 07355h ; 75 04 ; 0xf734f
+ mov AL, strict byte 001h ; b0 01 ; 0xf7351 ps2mouse.c:104
+ jmp short 07360h ; eb 0b ; 0xf7353
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf7355 ps2mouse.c:106
+ in AL, DX ; ec ; 0xf7358
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7359
+ mov byte [es:bx], al ; 26 88 07 ; 0xf735b ps2mouse.c:107
+ xor al, al ; 30 c0 ; 0xf735e ps2mouse.c:108
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7360 ps2mouse.c:109
+ pop cx ; 59 ; 0xf7363
+ pop bx ; 5b ; 0xf7364
+ pop bp ; 5d ; 0xf7365
+ retn ; c3 ; 0xf7366
+ ; disGetNextSymbol 0xf7367 LB 0x2cde -> off=0x0 cb=0000000000000032 uValue=00000000000f5d67 'set_kbd_command_byte'
+set_kbd_command_byte: ; 0xf7367 LB 0x32
+ push bp ; 55 ; 0xf7367 ps2mouse.c:111
+ mov bp, sp ; 89 e5 ; 0xf7368
+ push bx ; 53 ; 0xf736a
+ push dx ; 52 ; 0xf736b
+ mov bl, al ; 88 c3 ; 0xf736c
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf736e ps2mouse.c:113
+ in AL, DX ; ec ; 0xf7371
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7372
+ test AL, strict byte 002h ; a8 02 ; 0xf7374
+ je short 07386h ; 74 0e ; 0xf7376
+ push 0090ah ; 68 0a 09 ; 0xf7378 ps2mouse.c:114
+ push 0117ah ; 68 7a 11 ; 0xf737b
+ push strict byte 00007h ; 6a 07 ; 0xf737e
+ call 01a14h ; e8 91 a6 ; 0xf7380
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7383
+ mov AL, strict byte 060h ; b0 60 ; 0xf7386 ps2mouse.c:116
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf7388
+ out DX, AL ; ee ; 0xf738b
+ mov al, bl ; 88 d8 ; 0xf738c ps2mouse.c:117
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf738e
+ out DX, AL ; ee ; 0xf7391
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7392 ps2mouse.c:118
+ pop dx ; 5a ; 0xf7395
+ pop bx ; 5b ; 0xf7396
+ pop bp ; 5d ; 0xf7397
+ retn ; c3 ; 0xf7398
+ ; disGetNextSymbol 0xf7399 LB 0x2cac -> off=0x0 cb=0000000000000094 uValue=00000000000f5d99 'int74_function'
+int74_function: ; 0xf7399 LB 0x94
+ push bp ; 55 ; 0xf7399 ps2mouse.c:121
+ mov bp, sp ; 89 e5 ; 0xf739a
+ push si ; 56 ; 0xf739c
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf739d ps2mouse.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf73a0
+ mov es, ax ; 8e c0 ; 0xf73a3
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf73a5
+ mov word [bp+004h], strict word 00000h ; c7 46 04 00 00 ; 0xf73a8 ps2mouse.c:129
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf73ad ps2mouse.c:131
+ in AL, DX ; ec ; 0xf73b0
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf73b1
+ and AL, strict byte 021h ; 24 21 ; 0xf73b3 ps2mouse.c:132
+ cmp AL, strict byte 021h ; 3c 21 ; 0xf73b5
+ jne short 07427h ; 75 6e ; 0xf73b7
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf73b9 ps2mouse.c:135
+ in AL, DX ; ec ; 0xf73bc
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf73bd
+ mov cl, al ; 88 c1 ; 0xf73bf
+ mov si, strict word 00026h ; be 26 00 ; 0xf73c1 ps2mouse.c:38
+ mov es, bx ; 8e c3 ; 0xf73c4
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf73c6
+ mov si, strict word 00027h ; be 27 00 ; 0xf73c9 ps2mouse.c:38
+ mov ah, byte [es:si] ; 26 8a 24 ; 0xf73cc
+ mov dl, ah ; 88 e2 ; 0xf73cf ps2mouse.c:39
+ test ah, 080h ; f6 c4 80 ; 0xf73d1 ps2mouse.c:141
+ je short 07427h ; 74 51 ; 0xf73d4
+ mov dh, dl ; 88 d6 ; 0xf73d6 ps2mouse.c:145
+ and dh, 007h ; 80 e6 07 ; 0xf73d8
+ mov ah, al ; 88 c4 ; 0xf73db ps2mouse.c:146
+ and ah, 007h ; 80 e4 07 ; 0xf73dd
+ movzx si, ah ; 0f b6 f4 ; 0xf73e0 ps2mouse.c:147
+ add si, strict byte 00028h ; 83 c6 28 ; 0xf73e3
+ mov es, bx ; 8e c3 ; 0xf73e6 ps2mouse.c:43
+ mov byte [es:si], cl ; 26 88 0c ; 0xf73e8
+ cmp ah, dh ; 38 f4 ; 0xf73eb ps2mouse.c:149
+ jc short 0741dh ; 72 2e ; 0xf73ed
+ mov si, strict word 00028h ; be 28 00 ; 0xf73ef ps2mouse.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf73f2
+ xor ah, ah ; 30 e4 ; 0xf73f5 ps2mouse.c:39
+ mov word [bp+00ch], ax ; 89 46 0c ; 0xf73f7
+ mov si, strict word 00029h ; be 29 00 ; 0xf73fa ps2mouse.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf73fd
+ mov word [bp+00ah], ax ; 89 46 0a ; 0xf7400 ps2mouse.c:39
+ mov si, strict word 0002ah ; be 2a 00 ; 0xf7403 ps2mouse.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf7406
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf7409 ps2mouse.c:39
+ xor al, al ; 30 c0 ; 0xf740c ps2mouse.c:154
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf740e
+ test dl, 080h ; f6 c2 80 ; 0xf7411 ps2mouse.c:157
+ je short 0741fh ; 74 09 ; 0xf7414
+ mov word [bp+004h], strict word 00001h ; c7 46 04 01 00 ; 0xf7416 ps2mouse.c:158
+ jmp short 0741fh ; eb 02 ; 0xf741b ps2mouse.c:160
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf741d ps2mouse.c:161
+ mov si, strict word 00026h ; be 26 00 ; 0xf741f ps2mouse.c:43
+ mov es, bx ; 8e c3 ; 0xf7422
+ mov byte [es:si], al ; 26 88 04 ; 0xf7424
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf7427 ps2mouse.c:164
+ pop si ; 5e ; 0xf742a
+ pop bp ; 5d ; 0xf742b
+ retn ; c3 ; 0xf742c
+ ; disGetNextSymbol 0xf742d LB 0x2c18 -> off=0x10 cb=0000000000000370 uValue=00000000000f5e3d 'int15_function_mouse'
+ db 080h, 074h, 0eeh, 074h, 069h, 075h, 0fah, 075h, 068h, 076h, 0cch, 074h, 090h, 076h, 055h, 077h
+int15_function_mouse: ; 0xf743d LB 0x370
+ push bp ; 55 ; 0xf743d ps2mouse.c:166
+ mov bp, sp ; 89 e5 ; 0xf743e
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf7440
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf7443 ps2mouse.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf7446
+ mov es, ax ; 8e c0 ; 0xf7449
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf744b
+ cmp byte [bp+012h], 007h ; 80 7e 12 07 ; 0xf744e ps2mouse.c:188
+ jbe short 0745fh ; 76 0b ; 0xf7452
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf7454 ps2mouse.c:191
+ mov byte [bp+013h], 001h ; c6 46 13 01 ; 0xf7458 ps2mouse.c:192
+ jmp near 077a9h ; e9 4a 03 ; 0xf745c ps2mouse.c:193
+ mov ax, strict word 00065h ; b8 65 00 ; 0xf745f ps2mouse.c:197
+ call 07367h ; e8 02 ff ; 0xf7462
+ and word [bp+018h], strict byte 0fffeh ; 83 66 18 fe ; 0xf7465 ps2mouse.c:198
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf7469 ps2mouse.c:199
+ mov al, byte [bp+012h] ; 8a 46 12 ; 0xf746d ps2mouse.c:201
+ cmp AL, strict byte 007h ; 3c 07 ; 0xf7470
+ jnbe near 07790h ; 0f 87 1a 03 ; 0xf7472
+ movzx bx, al ; 0f b6 d8 ; 0xf7476
+ add bx, bx ; 01 db ; 0xf7479
+ jmp word [cs:bx+0742dh] ; 2e ff a7 2d 74 ; 0xf747b
+ cmp byte [bp+00dh], 001h ; 80 7e 0d 01 ; 0xf7480 ps2mouse.c:204
+ jnbe near 0779bh ; 0f 87 13 03 ; 0xf7484
+ mov bx, strict word 00027h ; bb 27 00 ; 0xf7488 ps2mouse.c:38
+ mov es, dx ; 8e c2 ; 0xf748b
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf748d
+ test AL, strict byte 080h ; a8 80 ; 0xf7490 ps2mouse.c:212
+ jne short 0749fh ; 75 0b ; 0xf7492
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf7494 ps2mouse.c:214
+ mov byte [bp+013h], 005h ; c6 46 13 05 ; 0xf7498 ps2mouse.c:215
+ jmp near 077a3h ; e9 04 03 ; 0xf749c ps2mouse.c:216
+ cmp byte [bp+00dh], 000h ; 80 7e 0d 00 ; 0xf749f ps2mouse.c:218
+ db 00fh, 094h, 0c0h
+ ; sete al ; 0f 94 c0 ; 0xf74a3
+ add AL, strict byte 0f4h ; 04 f4 ; 0xf74a6
+ xor ah, ah ; 30 e4 ; 0xf74a8 ps2mouse.c:226
+ call 072d7h ; e8 2a fe ; 0xf74aa
+ test al, al ; 84 c0 ; 0xf74ad ps2mouse.c:227
+ jne near 07731h ; 0f 85 7e 02 ; 0xf74af
+ mov dx, ss ; 8c d2 ; 0xf74b3 ps2mouse.c:228
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf74b5
+ call 0730bh ; e8 50 fe ; 0xf74b8
+ test al, al ; 84 c0 ; 0xf74bb ps2mouse.c:229
+ je near 077a3h ; 0f 84 e2 02 ; 0xf74bd
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf74c1
+ jne near 07731h ; 0f 85 68 02 ; 0xf74c5
+ jmp near 077a3h ; e9 d7 02 ; 0xf74c9 ps2mouse.c:231
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf74cc ps2mouse.c:242
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf74cf
+ jc short 074d7h ; 72 04 ; 0xf74d1
+ cmp AL, strict byte 008h ; 3c 08 ; 0xf74d3
+ jbe short 074dah ; 76 03 ; 0xf74d5
+ jmp near 0765dh ; e9 83 01 ; 0xf74d7
+ mov bx, strict word 00027h ; bb 27 00 ; 0xf74da ps2mouse.c:38
+ mov es, dx ; 8e c2 ; 0xf74dd
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf74df
+ mov ah, byte [bp+00dh] ; 8a 66 0d ; 0xf74e2 ps2mouse.c:248
+ db 0feh, 0cch
+ ; dec ah ; fe cc ; 0xf74e5
+ and AL, strict byte 0f8h ; 24 f8 ; 0xf74e7
+ or al, ah ; 08 e0 ; 0xf74e9
+ mov byte [es:bx], al ; 26 88 07 ; 0xf74eb ps2mouse.c:43
+ mov bx, strict word 00026h ; bb 26 00 ; 0xf74ee ps2mouse.c:38
+ mov es, dx ; 8e c2 ; 0xf74f1
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf74f3
+ and AL, strict byte 0f8h ; 24 f8 ; 0xf74f6 ps2mouse.c:256
+ mov byte [es:bx], al ; 26 88 07 ; 0xf74f8 ps2mouse.c:43
+ mov ax, 000ffh ; b8 ff 00 ; 0xf74fb ps2mouse.c:258
+ call 072d7h ; e8 d6 fd ; 0xf74fe
+ test al, al ; 84 c0 ; 0xf7501 ps2mouse.c:259
+ jne near 07731h ; 0f 85 2a 02 ; 0xf7503
+ mov dx, ss ; 8c d2 ; 0xf7507 ps2mouse.c:260
+ lea ax, [bp-004h] ; 8d 46 fc ; 0xf7509
+ call 0730bh ; e8 fc fd ; 0xf750c
+ mov dl, al ; 88 c2 ; 0xf750f
+ cmp byte [bp-004h], 0feh ; 80 7e fc fe ; 0xf7511 ps2mouse.c:262
+ jne short 07522h ; 75 0b ; 0xf7515
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf7517 ps2mouse.c:263
+ mov byte [bp+013h], 004h ; c6 46 13 04 ; 0xf751b ps2mouse.c:264
+ jmp near 077a3h ; e9 81 02 ; 0xf751f ps2mouse.c:265
+ cmp byte [bp-004h], 0fah ; 80 7e fc fa ; 0xf7522 ps2mouse.c:267
+ je short 07538h ; 74 10 ; 0xf7526
+ movzx ax, byte [bp-004h] ; 0f b6 46 fc ; 0xf7528 ps2mouse.c:268
+ push ax ; 50 ; 0xf752c
+ push 00915h ; 68 15 09 ; 0xf752d
+ push strict byte 00007h ; 6a 07 ; 0xf7530
+ call 01a14h ; e8 df a4 ; 0xf7532
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7535
+ test dl, dl ; 84 d2 ; 0xf7538 ps2mouse.c:269
+ jne near 07731h ; 0f 85 f3 01 ; 0xf753a
+ mov dx, ss ; 8c d2 ; 0xf753e ps2mouse.c:270
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf7540
+ call 0730bh ; e8 c5 fd ; 0xf7543
+ test al, al ; 84 c0 ; 0xf7546 ps2mouse.c:271
+ jne near 07731h ; 0f 85 e5 01 ; 0xf7548
+ mov dx, ss ; 8c d2 ; 0xf754c ps2mouse.c:272
+ lea ax, [bp-002h] ; 8d 46 fe ; 0xf754e
+ call 0730bh ; e8 b7 fd ; 0xf7551
+ test al, al ; 84 c0 ; 0xf7554 ps2mouse.c:273
+ jne near 07731h ; 0f 85 d7 01 ; 0xf7556
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf755a ps2mouse.c:275
+ mov byte [bp+00ch], al ; 88 46 0c ; 0xf755d
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf7560 ps2mouse.c:276
+ mov byte [bp+00dh], al ; 88 46 0d ; 0xf7563
+ jmp near 077a3h ; e9 3a 02 ; 0xf7566 ps2mouse.c:277
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf7569 ps2mouse.c:290
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf756c
+ jc short 07580h ; 72 10 ; 0xf756e
+ jbe short 0759eh ; 76 2c ; 0xf7570
+ cmp AL, strict byte 006h ; 3c 06 ; 0xf7572
+ je short 075b0h ; 74 3a ; 0xf7574
+ cmp AL, strict byte 005h ; 3c 05 ; 0xf7576
+ je short 075aah ; 74 30 ; 0xf7578
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf757a
+ je short 075a4h ; 74 26 ; 0xf757c
+ jmp short 075b6h ; eb 36 ; 0xf757e
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf7580
+ je short 07598h ; 74 14 ; 0xf7582
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf7584
+ je short 07592h ; 74 0a ; 0xf7586
+ test al, al ; 84 c0 ; 0xf7588
+ jne short 075b6h ; 75 2a ; 0xf758a
+ mov byte [bp-006h], 00ah ; c6 46 fa 0a ; 0xf758c ps2mouse.c:291
+ jmp short 075bah ; eb 28 ; 0xf7590
+ mov byte [bp-006h], 014h ; c6 46 fa 14 ; 0xf7592 ps2mouse.c:292
+ jmp short 075bah ; eb 22 ; 0xf7596
+ mov byte [bp-006h], 028h ; c6 46 fa 28 ; 0xf7598 ps2mouse.c:293
+ jmp short 075bah ; eb 1c ; 0xf759c
+ mov byte [bp-006h], 03ch ; c6 46 fa 3c ; 0xf759e ps2mouse.c:294
+ jmp short 075bah ; eb 16 ; 0xf75a2
+ mov byte [bp-006h], 050h ; c6 46 fa 50 ; 0xf75a4 ps2mouse.c:295
+ jmp short 075bah ; eb 10 ; 0xf75a8
+ mov byte [bp-006h], 064h ; c6 46 fa 64 ; 0xf75aa ps2mouse.c:296
+ jmp short 075bah ; eb 0a ; 0xf75ae
+ mov byte [bp-006h], 0c8h ; c6 46 fa c8 ; 0xf75b0 ps2mouse.c:297
+ jmp short 075bah ; eb 04 ; 0xf75b4
+ mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xf75b6 ps2mouse.c:298
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf75ba ps2mouse.c:300
+ jbe short 075efh ; 76 2f ; 0xf75be
+ mov ax, 000f3h ; b8 f3 00 ; 0xf75c0 ps2mouse.c:301
+ call 072d7h ; e8 11 fd ; 0xf75c3
+ test al, al ; 84 c0 ; 0xf75c6 ps2mouse.c:302
+ jne short 075e4h ; 75 1a ; 0xf75c8
+ mov dx, ss ; 8c d2 ; 0xf75ca ps2mouse.c:303
+ lea ax, [bp-002h] ; 8d 46 fe ; 0xf75cc
+ call 0730bh ; e8 39 fd ; 0xf75cf
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf75d2 ps2mouse.c:304
+ call 072d7h ; e8 fe fc ; 0xf75d6
+ mov dx, ss ; 8c d2 ; 0xf75d9 ps2mouse.c:305
+ lea ax, [bp-002h] ; 8d 46 fe ; 0xf75db
+ call 0730bh ; e8 2a fd ; 0xf75de
+ jmp near 077a3h ; e9 bf 01 ; 0xf75e1 ps2mouse.c:307
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf75e4 ps2mouse.c:309
+ mov byte [bp+013h], 003h ; c6 46 13 03 ; 0xf75e8 ps2mouse.c:310
+ jmp near 077a3h ; e9 b4 01 ; 0xf75ec ps2mouse.c:312
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf75ef ps2mouse.c:314
+ mov byte [bp+013h], 002h ; c6 46 13 02 ; 0xf75f3 ps2mouse.c:315
+ jmp near 077a3h ; e9 a9 01 ; 0xf75f7 ps2mouse.c:317
+ cmp byte [bp+00dh], 004h ; 80 7e 0d 04 ; 0xf75fa ps2mouse.c:326
+ jnc short 0765dh ; 73 5d ; 0xf75fe
+ mov ax, 000e8h ; b8 e8 00 ; 0xf7600 ps2mouse.c:327
+ call 072d7h ; e8 d1 fc ; 0xf7603
+ test al, al ; 84 c0 ; 0xf7606 ps2mouse.c:328
+ jne short 07652h ; 75 48 ; 0xf7608
+ mov dx, ss ; 8c d2 ; 0xf760a ps2mouse.c:329
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf760c
+ call 0730bh ; e8 f9 fc ; 0xf760f
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf7612 ps2mouse.c:330
+ je short 07628h ; 74 10 ; 0xf7616
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf7618 ps2mouse.c:331
+ push ax ; 50 ; 0xf761c
+ push 00940h ; 68 40 09 ; 0xf761d
+ push strict byte 00007h ; 6a 07 ; 0xf7620
+ call 01a14h ; e8 ef a3 ; 0xf7622
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7625
+ movzx ax, byte [bp+00dh] ; 0f b6 46 0d ; 0xf7628 ps2mouse.c:332
+ call 072d7h ; e8 a8 fc ; 0xf762c
+ mov dx, ss ; 8c d2 ; 0xf762f ps2mouse.c:333
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf7631
+ call 0730bh ; e8 d4 fc ; 0xf7634
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf7637 ps2mouse.c:334
+ je near 077a3h ; 0f 84 64 01 ; 0xf763b
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf763f ps2mouse.c:335
+ push ax ; 50 ; 0xf7643
+ push 00940h ; 68 40 09 ; 0xf7644
+ push strict byte 00007h ; 6a 07 ; 0xf7647
+ call 01a14h ; e8 c8 a3 ; 0xf7649
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf764c
+ jmp near 077a3h ; e9 51 01 ; 0xf764f ps2mouse.c:337
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf7652 ps2mouse.c:339
+ mov byte [bp+013h], 003h ; c6 46 13 03 ; 0xf7656 ps2mouse.c:340
+ jmp near 077a3h ; e9 46 01 ; 0xf765a ps2mouse.c:342
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf765d ps2mouse.c:344
+ mov byte [bp+013h], 002h ; c6 46 13 02 ; 0xf7661 ps2mouse.c:345
+ jmp near 077a3h ; e9 3b 01 ; 0xf7665 ps2mouse.c:347
+ mov ax, 000f2h ; b8 f2 00 ; 0xf7668 ps2mouse.c:351
+ call 072d7h ; e8 69 fc ; 0xf766b
+ test al, al ; 84 c0 ; 0xf766e ps2mouse.c:352
+ jne short 07685h ; 75 13 ; 0xf7670
+ mov dx, ss ; 8c d2 ; 0xf7672 ps2mouse.c:353
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf7674
+ call 0730bh ; e8 91 fc ; 0xf7677
+ mov dx, ss ; 8c d2 ; 0xf767a ps2mouse.c:354
+ lea ax, [bp-002h] ; 8d 46 fe ; 0xf767c
+ call 0730bh ; e8 89 fc ; 0xf767f
+ jmp near 07560h ; e9 db fe ; 0xf7682
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf7685 ps2mouse.c:355
+ mov byte [bp+013h], 003h ; c6 46 13 03 ; 0xf7689 ps2mouse.c:360
+ jmp near 077a3h ; e9 13 01 ; 0xf768d ps2mouse.c:362
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf7690 ps2mouse.c:366
+ test al, al ; 84 c0 ; 0xf7693
+ jbe short 0769eh ; 76 07 ; 0xf7695
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf7697
+ jbe short 07707h ; 76 6c ; 0xf7699
+ jmp near 0773bh ; e9 9d 00 ; 0xf769b
+ mov ax, 000e9h ; b8 e9 00 ; 0xf769e ps2mouse.c:368
+ call 072d7h ; e8 33 fc ; 0xf76a1
+ test al, al ; 84 c0 ; 0xf76a4 ps2mouse.c:369
+ jne near 07731h ; 0f 85 87 00 ; 0xf76a6
+ mov dx, ss ; 8c d2 ; 0xf76aa ps2mouse.c:370
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf76ac
+ call 0730bh ; e8 59 fc ; 0xf76af
+ mov dl, al ; 88 c2 ; 0xf76b2
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf76b4 ps2mouse.c:371
+ je short 076cah ; 74 10 ; 0xf76b8
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf76ba ps2mouse.c:372
+ push ax ; 50 ; 0xf76be
+ push 00940h ; 68 40 09 ; 0xf76bf
+ push strict byte 00007h ; 6a 07 ; 0xf76c2
+ call 01a14h ; e8 4d a3 ; 0xf76c4
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf76c7
+ test dl, dl ; 84 d2 ; 0xf76ca ps2mouse.c:373
+ jne short 07731h ; 75 63 ; 0xf76cc
+ mov dx, ss ; 8c d2 ; 0xf76ce ps2mouse.c:374
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf76d0
+ call 0730bh ; e8 35 fc ; 0xf76d3
+ test al, al ; 84 c0 ; 0xf76d6 ps2mouse.c:375
+ jne short 07731h ; 75 57 ; 0xf76d8
+ mov dx, ss ; 8c d2 ; 0xf76da ps2mouse.c:376
+ lea ax, [bp-002h] ; 8d 46 fe ; 0xf76dc
+ call 0730bh ; e8 29 fc ; 0xf76df
+ test al, al ; 84 c0 ; 0xf76e2 ps2mouse.c:377
+ jne short 07731h ; 75 4b ; 0xf76e4
+ mov dx, ss ; 8c d2 ; 0xf76e6 ps2mouse.c:378
+ lea ax, [bp-004h] ; 8d 46 fc ; 0xf76e8
+ call 0730bh ; e8 1d fc ; 0xf76eb
+ test al, al ; 84 c0 ; 0xf76ee ps2mouse.c:379
+ jne short 07731h ; 75 3f ; 0xf76f0
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf76f2 ps2mouse.c:380
+ mov byte [bp+00ch], al ; 88 46 0c ; 0xf76f5
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf76f8 ps2mouse.c:381
+ mov byte [bp+010h], al ; 88 46 10 ; 0xf76fb
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf76fe ps2mouse.c:382
+ mov byte [bp+00eh], al ; 88 46 0e ; 0xf7701
+ jmp near 077a3h ; e9 9c 00 ; 0xf7704 ps2mouse.c:384
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf7707 ps2mouse.c:398
+ jne short 07710h ; 75 05 ; 0xf7709
+ mov ax, 000e6h ; b8 e6 00 ; 0xf770b ps2mouse.c:399
+ jmp short 07713h ; eb 03 ; 0xf770e ps2mouse.c:400
+ mov ax, 000e7h ; b8 e7 00 ; 0xf7710 ps2mouse.c:401
+ call 072d7h ; e8 c1 fb ; 0xf7713
+ mov dl, al ; 88 c2 ; 0xf7716
+ test dl, dl ; 84 d2 ; 0xf7718 ps2mouse.c:403
+ jne short 0772bh ; 75 0f ; 0xf771a
+ mov dx, ss ; 8c d2 ; 0xf771c ps2mouse.c:404
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf771e
+ call 0730bh ; e8 e7 fb ; 0xf7721
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf7724 ps2mouse.c:405
+ db 00fh, 095h, 0c2h
+ ; setne dl ; 0f 95 c2 ; 0xf7728
+ test dl, dl ; 84 d2 ; 0xf772b ps2mouse.c:407
+ je near 077a3h ; 0f 84 72 00 ; 0xf772d
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf7731 ps2mouse.c:409
+ mov byte [bp+013h], 003h ; c6 46 13 03 ; 0xf7735 ps2mouse.c:410
+ jmp short 077a3h ; eb 68 ; 0xf7739 ps2mouse.c:412
+ movzx ax, byte [bp+00dh] ; 0f b6 46 0d ; 0xf773b ps2mouse.c:415
+ push ax ; 50 ; 0xf773f
+ push 0096ch ; 68 6c 09 ; 0xf7740
+ push strict byte 00007h ; 6a 07 ; 0xf7743
+ call 01a14h ; e8 cc a2 ; 0xf7745
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7748
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf774b ps2mouse.c:417
+ mov byte [bp+013h], 001h ; c6 46 13 01 ; 0xf774f ps2mouse.c:418
+ jmp short 077a3h ; eb 4e ; 0xf7753 ps2mouse.c:420
+ mov cx, word [bp+00ch] ; 8b 4e 0c ; 0xf7755 ps2mouse.c:425
+ mov bx, strict word 00022h ; bb 22 00 ; 0xf7758 ps2mouse.c:53
+ mov es, dx ; 8e c2 ; 0xf775b
+ mov word [es:bx], cx ; 26 89 0f ; 0xf775d
+ mov bx, strict word 00024h ; bb 24 00 ; 0xf7760 ps2mouse.c:53
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf7763
+ mov word [es:bx], ax ; 26 89 07 ; 0xf7766
+ mov bx, strict word 00027h ; bb 27 00 ; 0xf7769 ps2mouse.c:38
+ mov bl, byte [es:bx] ; 26 8a 1f ; 0xf776c
+ mov al, bl ; 88 d8 ; 0xf776f ps2mouse.c:39
+ test cx, cx ; 85 c9 ; 0xf7771 ps2mouse.c:429
+ jne short 07784h ; 75 0f ; 0xf7773
+ cmp word [bp+014h], strict byte 00000h ; 83 7e 14 00 ; 0xf7775
+ jne short 07784h ; 75 09 ; 0xf7779
+ test bl, 080h ; f6 c3 80 ; 0xf777b ps2mouse.c:431
+ je short 07786h ; 74 06 ; 0xf777e
+ and AL, strict byte 07fh ; 24 7f ; 0xf7780 ps2mouse.c:432
+ jmp short 07786h ; eb 02 ; 0xf7782 ps2mouse.c:435
+ or AL, strict byte 080h ; 0c 80 ; 0xf7784 ps2mouse.c:437
+ mov bx, strict word 00027h ; bb 27 00 ; 0xf7786 ps2mouse.c:43
+ mov es, dx ; 8e c2 ; 0xf7789
+ mov byte [es:bx], al ; 26 88 07 ; 0xf778b
+ jmp short 077a3h ; eb 13 ; 0xf778e ps2mouse.c:440
+ push 00986h ; 68 86 09 ; 0xf7790 ps2mouse.c:443
+ push strict byte 00007h ; 6a 07 ; 0xf7793
+ call 01a14h ; e8 7c a2 ; 0xf7795
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7798
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf779b ps2mouse.c:445
+ mov byte [bp+013h], 001h ; c6 46 13 01 ; 0xf779f ps2mouse.c:446
+ mov ax, strict word 00047h ; b8 47 00 ; 0xf77a3 ps2mouse.c:450
+ call 07367h ; e8 be fb ; 0xf77a6
+ mov sp, bp ; 89 ec ; 0xf77a9 ps2mouse.c:451
+ pop bp ; 5d ; 0xf77ab
+ retn ; c3 ; 0xf77ac
+ ; disGetNextSymbol 0xf77ad LB 0x2898 -> off=0x0 cb=00000000000000b2 uValue=00000000000f61ad 'int17_function'
+int17_function: ; 0xf77ad LB 0xb2
+ push bp ; 55 ; 0xf77ad parallel.c:60
+ mov bp, sp ; 89 e5 ; 0xf77ae
+ push si ; 56 ; 0xf77b0
+ push di ; 57 ; 0xf77b1
+ push ax ; 50 ; 0xf77b2
+ sti ; fb ; 0xf77b3 parallel.c:65
+ mov bx, word [bp+00eh] ; 8b 5e 0e ; 0xf77b4 parallel.c:67
+ add bx, bx ; 01 db ; 0xf77b7
+ add bx, strict byte 00008h ; 83 c3 08 ; 0xf77b9
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf77bc parallel.c:48
+ mov es, ax ; 8e c0 ; 0xf77bf
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf77c1
+ mov si, bx ; 89 de ; 0xf77c4 parallel.c:49
+ cmp byte [bp+013h], 003h ; 80 7e 13 03 ; 0xf77c6 parallel.c:68
+ jnc near 07854h ; 0f 83 86 00 ; 0xf77ca
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf77ce
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf77d1
+ jnc near 07854h ; 0f 83 7c 00 ; 0xf77d4
+ test bx, bx ; 85 db ; 0xf77d8
+ jbe near 07854h ; 0f 86 76 00 ; 0xf77da
+ mov di, ax ; 89 c7 ; 0xf77de parallel.c:69
+ add di, strict byte 00078h ; 83 c7 78 ; 0xf77e0
+ mov al, byte [es:di] ; 26 8a 05 ; 0xf77e3 parallel.c:38
+ movzx cx, al ; 0f b6 c8 ; 0xf77e6 parallel.c:39
+ sal cx, 008h ; c1 e1 08 ; 0xf77e9
+ cmp byte [bp+013h], 000h ; 80 7e 13 00 ; 0xf77ec parallel.c:70
+ jne short 0781fh ; 75 2d ; 0xf77f0
+ mov al, byte [bp+012h] ; 8a 46 12 ; 0xf77f2 parallel.c:71
+ mov dx, bx ; 89 da ; 0xf77f5
+ out DX, AL ; ee ; 0xf77f7
+ lea dx, [bx+002h] ; 8d 57 02 ; 0xf77f8 parallel.c:72
+ in AL, DX ; ec ; 0xf77fb
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf77fc
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf77fe
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7801 parallel.c:73
+ or AL, strict byte 001h ; 0c 01 ; 0xf7804
+ out DX, AL ; ee ; 0xf7806
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf7807 parallel.c:74
+ and AL, strict byte 0feh ; 24 fe ; 0xf780b
+ out DX, AL ; ee ; 0xf780d
+ lea dx, [si+001h] ; 8d 54 01 ; 0xf780e parallel.c:75
+ in AL, DX ; ec ; 0xf7811
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7812
+ test AL, strict byte 040h ; a8 40 ; 0xf7814
+ je short 0781fh ; 74 07 ; 0xf7816
+ test cx, cx ; 85 c9 ; 0xf7818
+ je short 0781fh ; 74 03 ; 0xf781a
+ dec cx ; 49 ; 0xf781c parallel.c:76
+ jmp short 0780eh ; eb ef ; 0xf781d parallel.c:77
+ cmp byte [bp+013h], 001h ; 80 7e 13 01 ; 0xf781f parallel.c:79
+ jne short 0783bh ; 75 16 ; 0xf7823
+ lea dx, [si+002h] ; 8d 54 02 ; 0xf7825 parallel.c:80
+ in AL, DX ; ec ; 0xf7828
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7829
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf782b
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf782e parallel.c:81
+ and AL, strict byte 0fbh ; 24 fb ; 0xf7832
+ out DX, AL ; ee ; 0xf7834
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7835 parallel.c:82
+ or AL, strict byte 004h ; 0c 04 ; 0xf7838
+ out DX, AL ; ee ; 0xf783a
+ lea dx, [si+001h] ; 8d 54 01 ; 0xf783b parallel.c:84
+ in AL, DX ; ec ; 0xf783e
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf783f
+ xor AL, strict byte 048h ; 34 48 ; 0xf7841 parallel.c:85
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf7843
+ test cx, cx ; 85 c9 ; 0xf7846 parallel.c:86
+ jne short 0784eh ; 75 04 ; 0xf7848
+ or byte [bp+013h], 001h ; 80 4e 13 01 ; 0xf784a
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf784e parallel.c:87
+ jmp short 07858h ; eb 04 ; 0xf7852 parallel.c:88
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf7854 parallel.c:89
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7858 parallel.c:91
+ pop di ; 5f ; 0xf785b
+ pop si ; 5e ; 0xf785c
+ pop bp ; 5d ; 0xf785d
+ retn ; c3 ; 0xf785e
+ ; disGetNextSymbol 0xf785f LB 0x27e6 -> off=0x0 cb=00000000000000b8 uValue=00000000000f625f '_wait_'
+_wait_: ; 0xf785f LB 0xb8
+ push bp ; 55 ; 0xf785f logo.c:171
+ mov bp, sp ; 89 e5 ; 0xf7860
+ push bx ; 53 ; 0xf7862
+ push cx ; 51 ; 0xf7863
+ push si ; 56 ; 0xf7864
+ push di ; 57 ; 0xf7865
+ sub sp, strict byte 0000ah ; 83 ec 0a ; 0xf7866
+ mov di, ax ; 89 c7 ; 0xf7869
+ mov byte [bp-00ah], dl ; 88 56 f6 ; 0xf786b
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf786e logo.c:176
+ pushfw ; 9c ; 0xf7872 logo.c:182
+ pop ax ; 58 ; 0xf7873
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf7874
+ sti ; fb ; 0xf7877 logo.c:183
+ xor dx, dx ; 31 d2 ; 0xf7878 logo.c:189
+ mov bx, 0046ch ; bb 6c 04 ; 0xf787a logo.c:58
+ mov es, dx ; 8e c2 ; 0xf787d
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf787f
+ mov cx, word [es:bx+002h] ; 26 8b 4f 02 ; 0xf7882
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf7886 logo.c:59
+ hlt ; f4 ; 0xf7889 logo.c:193
+ mov bx, 0046ch ; bb 6c 04 ; 0xf788a logo.c:58
+ xor ax, ax ; 31 c0 ; 0xf788d
+ mov es, ax ; 8e c0 ; 0xf788f
+ mov si, word [es:bx] ; 26 8b 37 ; 0xf7891
+ mov ax, word [es:bx+002h] ; 26 8b 47 02 ; 0xf7894
+ mov bx, si ; 89 f3 ; 0xf7898 logo.c:59
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf789a
+ cmp ax, cx ; 39 c8 ; 0xf789d logo.c:195
+ jnbe short 078a8h ; 77 07 ; 0xf789f
+ jne short 078afh ; 75 0c ; 0xf78a1
+ cmp si, word [bp-00eh] ; 3b 76 f2 ; 0xf78a3
+ jbe short 078afh ; 76 07 ; 0xf78a6
+ sub si, word [bp-00eh] ; 2b 76 f2 ; 0xf78a8 logo.c:197
+ sbb ax, cx ; 19 c8 ; 0xf78ab
+ jmp short 078bah ; eb 0b ; 0xf78ad logo.c:200
+ cmp ax, cx ; 39 c8 ; 0xf78af
+ jc short 078bah ; 72 07 ; 0xf78b1
+ jne short 078beh ; 75 09 ; 0xf78b3
+ cmp si, word [bp-00eh] ; 3b 76 f2 ; 0xf78b5
+ jnc short 078beh ; 73 04 ; 0xf78b8
+ sub di, si ; 29 f7 ; 0xf78ba logo.c:201
+ sbb dx, ax ; 19 c2 ; 0xf78bc
+ mov word [bp-00eh], bx ; 89 5e f2 ; 0xf78be logo.c:202
+ mov cx, word [bp-012h] ; 8b 4e ee ; 0xf78c1
+ mov ax, 00100h ; b8 00 01 ; 0xf78c4 logo.c:204
+ int 016h ; cd 16 ; 0xf78c7
+ je near 078d2h ; 0f 84 05 00 ; 0xf78c9
+ mov AL, strict byte 001h ; b0 01 ; 0xf78cd
+ jmp near 078d4h ; e9 02 00 ; 0xf78cf
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xf78d2
+ test al, al ; 84 c0 ; 0xf78d4
+ je short 078fch ; 74 24 ; 0xf78d6
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf78d8 logo.c:206
+ int 016h ; cd 16 ; 0xf78da
+ xchg ah, al ; 86 c4 ; 0xf78dc
+ mov bl, al ; 88 c3 ; 0xf78de
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf78e0
+ movzx ax, bl ; 0f b6 c3 ; 0xf78e3 logo.c:207
+ push ax ; 50 ; 0xf78e6
+ push 009a8h ; 68 a8 09 ; 0xf78e7
+ push strict byte 00004h ; 6a 04 ; 0xf78ea
+ call 01a14h ; e8 25 a1 ; 0xf78ec
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf78ef
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf78f2 logo.c:208
+ je short 078fch ; 74 04 ; 0xf78f6
+ mov al, bl ; 88 d8 ; 0xf78f8 logo.c:209
+ jmp short 0790eh ; eb 12 ; 0xf78fa
+ test dx, dx ; 85 d2 ; 0xf78fc logo.c:211
+ jnle short 07889h ; 7f 89 ; 0xf78fe
+ jne short 07906h ; 75 04 ; 0xf7900
+ test di, di ; 85 ff ; 0xf7902
+ jnbe short 07889h ; 77 83 ; 0xf7904
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf7906 logo.c:212
+ push ax ; 50 ; 0xf7909
+ popfw ; 9d ; 0xf790a
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf790b logo.c:213
+ lea sp, [bp-008h] ; 8d 66 f8 ; 0xf790e logo.c:214
+ pop di ; 5f ; 0xf7911
+ pop si ; 5e ; 0xf7912
+ pop cx ; 59 ; 0xf7913
+ pop bx ; 5b ; 0xf7914
+ pop bp ; 5d ; 0xf7915
+ retn ; c3 ; 0xf7916
+ ; disGetNextSymbol 0xf7917 LB 0x272e -> off=0x0 cb=0000000000000016 uValue=00000000000f6317 'read_logo_byte'
+read_logo_byte: ; 0xf7917 LB 0x16
+ push bp ; 55 ; 0xf7917 logo.c:216
+ mov bp, sp ; 89 e5 ; 0xf7918
+ push dx ; 52 ; 0xf791a
+ xor ah, ah ; 30 e4 ; 0xf791b logo.c:218
+ or ah, 001h ; 80 cc 01 ; 0xf791d
+ mov dx, 003b8h ; ba b8 03 ; 0xf7920
+ out DX, ax ; ef ; 0xf7923
+ in AL, DX ; ec ; 0xf7924 logo.c:219
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7925
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf7927 logo.c:220
+ pop dx ; 5a ; 0xf792a
+ pop bp ; 5d ; 0xf792b
+ retn ; c3 ; 0xf792c
+ ; disGetNextSymbol 0xf792d LB 0x2718 -> off=0x0 cb=0000000000000014 uValue=00000000000f632d 'read_logo_word'
+read_logo_word: ; 0xf792d LB 0x14
+ push bp ; 55 ; 0xf792d logo.c:222
+ mov bp, sp ; 89 e5 ; 0xf792e
+ push dx ; 52 ; 0xf7930
+ xor ah, ah ; 30 e4 ; 0xf7931 logo.c:224
+ or ah, 001h ; 80 cc 01 ; 0xf7933
+ mov dx, 003b8h ; ba b8 03 ; 0xf7936
+ out DX, ax ; ef ; 0xf7939
+ in ax, DX ; ed ; 0xf793a logo.c:225
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf793b logo.c:226
+ pop dx ; 5a ; 0xf793e
+ pop bp ; 5d ; 0xf793f
+ retn ; c3 ; 0xf7940
+ ; disGetNextSymbol 0xf7941 LB 0x2704 -> off=0x0 cb=0000000000000133 uValue=00000000000f6341 'print_detected_harddisks'
+print_detected_harddisks: ; 0xf7941 LB 0x133
+ push bp ; 55 ; 0xf7941 logo.c:245
+ mov bp, sp ; 89 e5 ; 0xf7942
+ push bx ; 53 ; 0xf7944
+ push cx ; 51 ; 0xf7945
+ push dx ; 52 ; 0xf7946
+ push si ; 56 ; 0xf7947
+ push di ; 57 ; 0xf7948
+ push ax ; 50 ; 0xf7949
+ push ax ; 50 ; 0xf794a
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf794b logo.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf794e
+ mov es, ax ; 8e c0 ; 0xf7951
+ mov si, word [es:bx] ; 26 8b 37 ; 0xf7953
+ mov di, si ; 89 f7 ; 0xf7956 logo.c:49
+ xor ch, ch ; 30 ed ; 0xf7958 logo.c:250
+ xor cl, cl ; 30 c9 ; 0xf795a logo.c:251
+ mov byte [bp-00eh], ch ; 88 6e f2 ; 0xf795c logo.c:252
+ mov bx, 00304h ; bb 04 03 ; 0xf795f logo.c:38
+ mov es, si ; 8e c6 ; 0xf7962
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf7964
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf7967 logo.c:39
+ xor bl, bl ; 30 db ; 0xf796a logo.c:257
+ cmp bl, byte [bp-00ch] ; 3a 5e f4 ; 0xf796c
+ jnc near 07a46h ; 0f 83 d3 00 ; 0xf796f
+ movzx si, bl ; 0f b6 f3 ; 0xf7973 logo.c:259
+ add si, 00305h ; 81 c6 05 03 ; 0xf7976
+ mov es, di ; 8e c7 ; 0xf797a logo.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf797c
+ mov bh, al ; 88 c7 ; 0xf797f logo.c:39
+ cmp AL, strict byte 00ch ; 3c 0c ; 0xf7981 logo.c:262
+ jc short 079a9h ; 72 24 ; 0xf7983
+ test cl, cl ; 84 c9 ; 0xf7985 logo.c:264
+ jne short 07996h ; 75 0d ; 0xf7987
+ push 009b9h ; 68 b9 09 ; 0xf7989 logo.c:266
+ push strict byte 00002h ; 6a 02 ; 0xf798c
+ call 01a14h ; e8 83 a0 ; 0xf798e
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7991
+ mov CL, strict byte 001h ; b1 01 ; 0xf7994 logo.c:267
+ movzx ax, bl ; 0f b6 c3 ; 0xf7996 logo.c:270
+ inc ax ; 40 ; 0xf7999
+ push ax ; 50 ; 0xf799a
+ push 009ceh ; 68 ce 09 ; 0xf799b
+ push strict byte 00002h ; 6a 02 ; 0xf799e
+ call 01a14h ; e8 71 a0 ; 0xf79a0
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf79a3
+ jmp near 07a41h ; e9 98 00 ; 0xf79a6 logo.c:273
+ cmp AL, strict byte 008h ; 3c 08 ; 0xf79a9 logo.c:276
+ jc short 079c4h ; 72 17 ; 0xf79ab
+ cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xf79ad logo.c:278
+ jne short 079c2h ; 75 0f ; 0xf79b1
+ push 009e1h ; 68 e1 09 ; 0xf79b3 logo.c:280
+ push strict byte 00002h ; 6a 02 ; 0xf79b6
+ call 01a14h ; e8 59 a0 ; 0xf79b8
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf79bb
+ mov byte [bp-00eh], 001h ; c6 46 f2 01 ; 0xf79be logo.c:281
+ jmp short 07996h ; eb d2 ; 0xf79c2 logo.c:282
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf79c4 logo.c:291
+ jnc short 079dbh ; 73 13 ; 0xf79c6
+ test ch, ch ; 84 ed ; 0xf79c8
+ jne short 079dbh ; 75 0f ; 0xf79ca
+ push 009f6h ; 68 f6 09 ; 0xf79cc logo.c:293
+ push strict byte 00002h ; 6a 02 ; 0xf79cf
+ call 01a14h ; e8 40 a0 ; 0xf79d1
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf79d4
+ mov CH, strict byte 001h ; b5 01 ; 0xf79d7 logo.c:294
+ jmp short 079f1h ; eb 16 ; 0xf79d9 logo.c:296
+ cmp bh, 004h ; 80 ff 04 ; 0xf79db
+ jc short 079f1h ; 72 11 ; 0xf79de
+ test cl, cl ; 84 c9 ; 0xf79e0
+ jne short 079f1h ; 75 0d ; 0xf79e2
+ push 00a08h ; 68 08 0a ; 0xf79e4 logo.c:298
+ push strict byte 00002h ; 6a 02 ; 0xf79e7
+ call 01a14h ; e8 28 a0 ; 0xf79e9
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf79ec
+ mov CL, strict byte 001h ; b1 01 ; 0xf79ef logo.c:299
+ movzx ax, bl ; 0f b6 c3 ; 0xf79f1 logo.c:302
+ inc ax ; 40 ; 0xf79f4
+ push ax ; 50 ; 0xf79f5
+ push 00a1ch ; 68 1c 0a ; 0xf79f6
+ push strict byte 00002h ; 6a 02 ; 0xf79f9
+ call 01a14h ; e8 16 a0 ; 0xf79fb
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf79fe
+ cmp bh, 004h ; 80 ff 04 ; 0xf7a01 logo.c:309
+ jc short 07a09h ; 72 03 ; 0xf7a04
+ sub bh, 004h ; 80 ef 04 ; 0xf7a06 logo.c:310
+ movzx ax, bh ; 0f b6 c7 ; 0xf7a09 logo.c:312
+ cwd ; 99 ; 0xf7a0c
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf7a0d
+ sar ax, 1 ; d1 f8 ; 0xf7a0f
+ test ax, ax ; 85 c0 ; 0xf7a11
+ je short 07a1ah ; 74 05 ; 0xf7a13
+ push 00a26h ; 68 26 0a ; 0xf7a15 logo.c:313
+ jmp short 07a1dh ; eb 03 ; 0xf7a18 logo.c:314
+ push 00a31h ; 68 31 0a ; 0xf7a1a logo.c:315
+ push strict byte 00002h ; 6a 02 ; 0xf7a1d
+ call 01a14h ; e8 f2 9f ; 0xf7a1f
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7a22
+ movzx ax, bh ; 0f b6 c7 ; 0xf7a25 logo.c:317
+ cwd ; 99 ; 0xf7a28
+ mov si, strict word 00002h ; be 02 00 ; 0xf7a29
+ idiv si ; f7 fe ; 0xf7a2c
+ test dx, dx ; 85 d2 ; 0xf7a2e
+ je short 07a37h ; 74 05 ; 0xf7a30
+ push 00a3ah ; 68 3a 0a ; 0xf7a32 logo.c:318
+ jmp short 07a3ah ; eb 03 ; 0xf7a35 logo.c:319
+ push 00a40h ; 68 40 0a ; 0xf7a37 logo.c:320
+ push si ; 56 ; 0xf7a3a
+ call 01a14h ; e8 d6 9f ; 0xf7a3b
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7a3e
+ db 0feh, 0c3h
+ ; inc bl ; fe c3 ; 0xf7a41 logo.c:322
+ jmp near 0796ch ; e9 26 ff ; 0xf7a43
+ test ch, ch ; 84 ed ; 0xf7a46 logo.c:324
+ jne short 07a5fh ; 75 15 ; 0xf7a48
+ test cl, cl ; 84 c9 ; 0xf7a4a
+ jne short 07a5fh ; 75 11 ; 0xf7a4c
+ cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xf7a4e
+ jne short 07a5fh ; 75 0b ; 0xf7a52
+ push 00a47h ; 68 47 0a ; 0xf7a54 logo.c:327
+ push strict byte 00002h ; 6a 02 ; 0xf7a57
+ call 01a14h ; e8 b8 9f ; 0xf7a59
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7a5c
+ push 00a5bh ; 68 5b 0a ; 0xf7a5f logo.c:329
+ push strict byte 00002h ; 6a 02 ; 0xf7a62
+ call 01a14h ; e8 ad 9f ; 0xf7a64
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7a67
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf7a6a logo.c:330
+ pop di ; 5f ; 0xf7a6d
+ pop si ; 5e ; 0xf7a6e
+ pop dx ; 5a ; 0xf7a6f
+ pop cx ; 59 ; 0xf7a70
+ pop bx ; 5b ; 0xf7a71
+ pop bp ; 5d ; 0xf7a72
+ retn ; c3 ; 0xf7a73
+ ; disGetNextSymbol 0xf7a74 LB 0x25d1 -> off=0x0 cb=0000000000000024 uValue=00000000000f6474 'get_boot_drive'
+get_boot_drive: ; 0xf7a74 LB 0x24
+ push bx ; 53 ; 0xf7a74 logo.c:332
+ push dx ; 52 ; 0xf7a75
+ push bp ; 55 ; 0xf7a76
+ mov bp, sp ; 89 e5 ; 0xf7a77
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf7a79 logo.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf7a7c
+ mov es, dx ; 8e c2 ; 0xf7a7f
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf7a81
+ mov bx, 00304h ; bb 04 03 ; 0xf7a84 logo.c:38
+ mov es, dx ; 8e c2 ; 0xf7a87
+ mov dl, byte [es:bx] ; 26 8a 17 ; 0xf7a89
+ sub AL, strict byte 002h ; 2c 02 ; 0xf7a8c logo.c:340
+ cmp al, dl ; 38 d0 ; 0xf7a8e logo.c:342
+ jc short 07a94h ; 72 02 ; 0xf7a90
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf7a92 logo.c:343
+ pop bp ; 5d ; 0xf7a94 logo.c:347
+ pop dx ; 5a ; 0xf7a95
+ pop bx ; 5b ; 0xf7a96
+ retn ; c3 ; 0xf7a97
+ ; disGetNextSymbol 0xf7a98 LB 0x25ad -> off=0x0 cb=0000000000000254 uValue=00000000000f6498 'show_logo'
+show_logo: ; 0xf7a98 LB 0x254
+ push bp ; 55 ; 0xf7a98 logo.c:349
+ mov bp, sp ; 89 e5 ; 0xf7a99
+ push bx ; 53 ; 0xf7a9b
+ push cx ; 51 ; 0xf7a9c
+ push dx ; 52 ; 0xf7a9d
+ push si ; 56 ; 0xf7a9e
+ push di ; 57 ; 0xf7a9f
+ sub sp, strict byte 0000eh ; 83 ec 0e ; 0xf7aa0
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf7aa3 logo.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf7aa6
+ mov es, ax ; 8e c0 ; 0xf7aa9
+ mov si, word [es:bx] ; 26 8b 37 ; 0xf7aab
+ mov byte [bp-00eh], 000h ; c6 46 f2 00 ; 0xf7aae logo.c:352
+ xor dx, dx ; 31 d2 ; 0xf7ab2 logo.c:356
+ mov AL, strict byte 034h ; b0 34 ; 0xf7ab4 logo.c:363
+ out strict byte 043h, AL ; e6 43 ; 0xf7ab6
+ mov AL, strict byte 0d3h ; b0 d3 ; 0xf7ab8
+ out strict byte 040h, AL ; e6 40 ; 0xf7aba
+ mov AL, strict byte 048h ; b0 48 ; 0xf7abc
+ out strict byte 040h, AL ; e6 40 ; 0xf7abe
+ movzx ax, dl ; 0f b6 c2 ; 0xf7ac0 logo.c:366
+ call 0792dh ; e8 67 fe ; 0xf7ac3
+ cmp ax, 066bbh ; 3d bb 66 ; 0xf7ac6 logo.c:367
+ jne near 07bcbh ; 0f 85 fe 00 ; 0xf7ac9
+ push SS ; 16 ; 0xf7acd logo.c:371
+ pop ES ; 07 ; 0xf7ace
+ lea di, [bp-018h] ; 8d 7e e8 ; 0xf7acf
+ mov ax, 04f03h ; b8 03 4f ; 0xf7ad2
+ int 010h ; cd 10 ; 0xf7ad5
+ mov word [es:di], bx ; 26 89 1d ; 0xf7ad7
+ cmp ax, strict word 0004fh ; 3d 4f 00 ; 0xf7ada
+ jne near 07bcbh ; 0f 85 ea 00 ; 0xf7add
+ mov al, dl ; 88 d0 ; 0xf7ae1 logo.c:375
+ add AL, strict byte 004h ; 04 04 ; 0xf7ae3
+ xor ah, ah ; 30 e4 ; 0xf7ae5
+ call 07917h ; e8 2d fe ; 0xf7ae7
+ mov bl, al ; 88 c3 ; 0xf7aea
+ mov byte [bp-012h], al ; 88 46 ee ; 0xf7aec
+ mov al, dl ; 88 d0 ; 0xf7aef logo.c:376
+ add AL, strict byte 005h ; 04 05 ; 0xf7af1
+ xor ah, ah ; 30 e4 ; 0xf7af3
+ call 07917h ; e8 1f fe ; 0xf7af5
+ mov dh, al ; 88 c6 ; 0xf7af8
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf7afa
+ mov al, dl ; 88 d0 ; 0xf7afd logo.c:377
+ add AL, strict byte 002h ; 04 02 ; 0xf7aff
+ xor ah, ah ; 30 e4 ; 0xf7b01
+ call 0792dh ; e8 27 fe ; 0xf7b03
+ mov cx, ax ; 89 c1 ; 0xf7b06
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf7b08
+ mov al, dl ; 88 d0 ; 0xf7b0b logo.c:378
+ add AL, strict byte 006h ; 04 06 ; 0xf7b0d
+ xor ah, ah ; 30 e4 ; 0xf7b0f
+ call 07917h ; e8 03 fe ; 0xf7b11
+ mov byte [bp-014h], al ; 88 46 ec ; 0xf7b14
+ test bl, bl ; 84 db ; 0xf7b17 logo.c:381
+ jne short 07b25h ; 75 0a ; 0xf7b19
+ test dh, dh ; 84 f6 ; 0xf7b1b
+ jne short 07b25h ; 75 06 ; 0xf7b1d
+ test cx, cx ; 85 c9 ; 0xf7b1f
+ je near 07bcbh ; 0f 84 a6 00 ; 0xf7b21
+ mov BH, strict byte 020h ; b7 20 ; 0xf7b25 logo.c:385
+ mov dx, 001e0h ; ba e0 01 ; 0xf7b27
+ mov cx, 00280h ; b9 80 02 ; 0xf7b2a
+ mov ax, 05642h ; b8 42 56 ; 0xf7b2d
+ mov BL, strict byte 000h ; b3 00 ; 0xf7b30
+ int 010h ; cd 10 ; 0xf7b32
+ cmp ax, strict word 0004fh ; 3d 4f 00 ; 0xf7b34 logo.c:387
+ je short 07b41h ; 74 08 ; 0xf7b37
+ mov bx, 00142h ; bb 42 01 ; 0xf7b39 logo.c:388
+ mov ax, 04f02h ; b8 02 4f ; 0xf7b3c
+ int 010h ; cd 10 ; 0xf7b3f
+ cmp byte [bp-012h], 000h ; 80 7e ee 00 ; 0xf7b41 logo.c:390
+ je short 07b6ch ; 74 25 ; 0xf7b45
+ xor bx, bx ; 31 db ; 0xf7b47 logo.c:392
+ jmp short 07b51h ; eb 06 ; 0xf7b49
+ inc bx ; 43 ; 0xf7b4b logo.c:394
+ cmp bx, strict byte 00010h ; 83 fb 10 ; 0xf7b4c
+ jnbe short 07b73h ; 77 22 ; 0xf7b4f
+ mov ax, bx ; 89 d8 ; 0xf7b51
+ or ah, 002h ; 80 cc 02 ; 0xf7b53
+ mov dx, 003b8h ; ba b8 03 ; 0xf7b56
+ out DX, ax ; ef ; 0xf7b59
+ xor dx, dx ; 31 d2 ; 0xf7b5a
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf7b5c
+ call 0785fh ; e8 fd fc ; 0xf7b5f
+ cmp AL, strict byte 086h ; 3c 86 ; 0xf7b62
+ jne short 07b4bh ; 75 e5 ; 0xf7b64
+ mov byte [bp-00eh], 001h ; c6 46 f2 01 ; 0xf7b66
+ jmp short 07b73h ; eb 07 ; 0xf7b6a
+ mov ax, 00210h ; b8 10 02 ; 0xf7b6c logo.c:404
+ mov dx, 003b8h ; ba b8 03 ; 0xf7b6f
+ out DX, ax ; ef ; 0xf7b72
+ cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xf7b73 logo.c:407
+ jne short 07b8dh ; 75 14 ; 0xf7b77
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf7b79 logo.c:409
+ shr ax, 004h ; c1 e8 04 ; 0xf7b7c
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf7b7f
+ call 0785fh ; e8 da fc ; 0xf7b82
+ cmp AL, strict byte 086h ; 3c 86 ; 0xf7b85 logo.c:410
+ jne short 07b8dh ; 75 04 ; 0xf7b87
+ mov byte [bp-00eh], 001h ; c6 46 f2 01 ; 0xf7b89 logo.c:411
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf7b8d logo.c:415
+ je short 07bbeh ; 74 2b ; 0xf7b91
+ cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xf7b93
+ jne short 07bbeh ; 75 25 ; 0xf7b97
+ mov bx, strict word 00010h ; bb 10 00 ; 0xf7b99 logo.c:417
+ jmp short 07ba3h ; eb 05 ; 0xf7b9c
+ dec bx ; 4b ; 0xf7b9e logo.c:419
+ test bx, bx ; 85 db ; 0xf7b9f
+ jbe short 07bcbh ; 76 28 ; 0xf7ba1
+ mov ax, bx ; 89 d8 ; 0xf7ba3
+ or ah, 002h ; 80 cc 02 ; 0xf7ba5
+ mov dx, 003b8h ; ba b8 03 ; 0xf7ba8
+ out DX, ax ; ef ; 0xf7bab
+ xor dx, dx ; 31 d2 ; 0xf7bac
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf7bae
+ call 0785fh ; e8 ab fc ; 0xf7bb1
+ cmp AL, strict byte 086h ; 3c 86 ; 0xf7bb4
+ jne short 07b9eh ; 75 e6 ; 0xf7bb6
+ mov byte [bp-00eh], 001h ; c6 46 f2 01 ; 0xf7bb8
+ jmp short 07bcbh ; eb 0d ; 0xf7bbc
+ cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xf7bbe logo.c:428
+ jne short 07bcbh ; 75 07 ; 0xf7bc2
+ mov ax, 00200h ; b8 00 02 ; 0xf7bc4 logo.c:429
+ mov dx, 003b8h ; ba b8 03 ; 0xf7bc7
+ out DX, ax ; ef ; 0xf7bca
+ mov bx, 0037dh ; bb 7d 03 ; 0xf7bcb logo.c:43
+ mov es, si ; 8e c6 ; 0xf7bce
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf7bd0
+ mov AL, strict byte 003h ; b0 03 ; 0xf7bd4 logo.c:437
+ mov AH, strict byte 000h ; b4 00 ; 0xf7bd6
+ int 010h ; cd 10 ; 0xf7bd8
+ cmp byte [bp-014h], 000h ; 80 7e ec 00 ; 0xf7bda logo.c:440
+ je near 07ccdh ; 0f 84 eb 00 ; 0xf7bde
+ cmp byte [bp-012h], 000h ; 80 7e ee 00 ; 0xf7be2 logo.c:443
+ jne short 07c1ch ; 75 34 ; 0xf7be6
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf7be8
+ jne short 07c1ch ; 75 2e ; 0xf7bec
+ cmp word [bp-016h], strict byte 00000h ; 83 7e ea 00 ; 0xf7bee
+ jne short 07c1ch ; 75 28 ; 0xf7bf2
+ cmp byte [bp-014h], 002h ; 80 7e ec 02 ; 0xf7bf4 logo.c:445
+ jne short 07c05h ; 75 0b ; 0xf7bf8
+ push 00a5dh ; 68 5d 0a ; 0xf7bfa logo.c:446
+ push strict byte 00002h ; 6a 02 ; 0xf7bfd
+ call 01a14h ; e8 12 9e ; 0xf7bff
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7c02
+ cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xf7c05 logo.c:449
+ jne short 07c1ch ; 75 11 ; 0xf7c09
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf7c0b logo.c:452
+ mov ax, 000c0h ; b8 c0 00 ; 0xf7c0e
+ call 0785fh ; e8 4b fc ; 0xf7c11
+ cmp AL, strict byte 086h ; 3c 86 ; 0xf7c14 logo.c:453
+ jne short 07c1ch ; 75 04 ; 0xf7c16
+ mov byte [bp-00eh], 001h ; c6 46 f2 01 ; 0xf7c18 logo.c:454
+ cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xf7c1c logo.c:459
+ je near 07ccdh ; 0f 84 a9 00 ; 0xf7c20
+ mov byte [bp-010h], 000h ; c6 46 f0 00 ; 0xf7c24 logo.c:461
+ mov ax, 00100h ; b8 00 01 ; 0xf7c28 logo.c:464
+ mov cx, 01000h ; b9 00 10 ; 0xf7c2b
+ int 010h ; cd 10 ; 0xf7c2e
+ mov ax, 00700h ; b8 00 07 ; 0xf7c30
+ mov BH, strict byte 007h ; b7 07 ; 0xf7c33
+ db 033h, 0c9h
+ ; xor cx, cx ; 33 c9 ; 0xf7c35
+ mov dx, 0184fh ; ba 4f 18 ; 0xf7c37
+ int 010h ; cd 10 ; 0xf7c3a
+ mov ax, 00200h ; b8 00 02 ; 0xf7c3c
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xf7c3f
+ db 033h, 0d2h
+ ; xor dx, dx ; 33 d2 ; 0xf7c41
+ int 010h ; cd 10 ; 0xf7c43
+ push 00a7fh ; 68 7f 0a ; 0xf7c45 logo.c:467
+ push strict byte 00002h ; 6a 02 ; 0xf7c48
+ call 01a14h ; e8 c7 9d ; 0xf7c4a
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7c4d
+ call 07941h ; e8 ee fc ; 0xf7c50 logo.c:468
+ push 00ac3h ; 68 c3 0a ; 0xf7c53 logo.c:469
+ push strict byte 00002h ; 6a 02 ; 0xf7c56
+ call 01a14h ; e8 b9 9d ; 0xf7c58
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7c5b
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf7c5e logo.c:478
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf7c61
+ call 0785fh ; e8 f8 fb ; 0xf7c64
+ mov bl, al ; 88 c3 ; 0xf7c67
+ test al, al ; 84 c0 ; 0xf7c69 logo.c:479
+ je short 07c5eh ; 74 f1 ; 0xf7c6b
+ cmp AL, strict byte 030h ; 3c 30 ; 0xf7c6d logo.c:481
+ je short 07cbch ; 74 4b ; 0xf7c6f
+ cmp bl, 002h ; 80 fb 02 ; 0xf7c71 logo.c:488
+ jc short 07c95h ; 72 1f ; 0xf7c74
+ cmp bl, 009h ; 80 fb 09 ; 0xf7c76
+ jnbe short 07c95h ; 77 1a ; 0xf7c79
+ movzx ax, bl ; 0f b6 c3 ; 0xf7c7b logo.c:490
+ call 07a74h ; e8 f3 fd ; 0xf7c7e
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xf7c81 logo.c:497
+ jne short 07c87h ; 75 02 ; 0xf7c83
+ jmp short 07c5eh ; eb d7 ; 0xf7c85 logo.c:498
+ mov bx, 0037ch ; bb 7c 03 ; 0xf7c87 logo.c:43
+ mov es, si ; 8e c6 ; 0xf7c8a
+ mov byte [es:bx], al ; 26 88 07 ; 0xf7c8c
+ mov byte [bp-010h], 002h ; c6 46 f0 02 ; 0xf7c8f logo.c:501
+ jmp short 07cbch ; eb 27 ; 0xf7c93 logo.c:502
+ cmp bl, 02eh ; 80 fb 2e ; 0xf7c95 logo.c:505
+ je short 07caah ; 74 10 ; 0xf7c98
+ cmp bl, 026h ; 80 fb 26 ; 0xf7c9a
+ je short 07cb0h ; 74 11 ; 0xf7c9d
+ cmp bl, 021h ; 80 fb 21 ; 0xf7c9f
+ jne short 07cb6h ; 75 12 ; 0xf7ca2
+ mov byte [bp-010h], 001h ; c6 46 f0 01 ; 0xf7ca4 logo.c:509
+ jmp short 07cbch ; eb 12 ; 0xf7ca8 logo.c:510
+ mov byte [bp-010h], 003h ; c6 46 f0 03 ; 0xf7caa logo.c:513
+ jmp short 07cbch ; eb 0c ; 0xf7cae logo.c:514
+ mov byte [bp-010h], 004h ; c6 46 f0 04 ; 0xf7cb0 logo.c:517
+ jmp short 07cbch ; eb 06 ; 0xf7cb4 logo.c:518
+ cmp byte [bp-010h], 000h ; 80 7e f0 00 ; 0xf7cb6 logo.c:521
+ je short 07c5eh ; 74 a2 ; 0xf7cba
+ mov bx, 0037dh ; bb 7d 03 ; 0xf7cbc logo.c:43
+ mov es, si ; 8e c6 ; 0xf7cbf
+ mov al, byte [bp-010h] ; 8a 46 f0 ; 0xf7cc1
+ mov byte [es:bx], al ; 26 88 07 ; 0xf7cc4
+ mov AL, strict byte 003h ; b0 03 ; 0xf7cc7 logo.c:528
+ mov AH, strict byte 000h ; b4 00 ; 0xf7cc9
+ int 010h ; cd 10 ; 0xf7ccb
+ mov AL, strict byte 034h ; b0 34 ; 0xf7ccd logo.c:533
+ out strict byte 043h, AL ; e6 43 ; 0xf7ccf
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf7cd1
+ out strict byte 040h, AL ; e6 40 ; 0xf7cd3
+ out strict byte 040h, AL ; e6 40 ; 0xf7cd5
+ pushad ; 66 60 ; 0xf7cd7
+ push DS ; 1e ; 0xf7cd9
+ mov ds, ax ; 8e d8 ; 0xf7cda
+ call 0edbfh ; e8 e0 70 ; 0xf7cdc
+ pop DS ; 1f ; 0xf7cdf
+ popad ; 66 61 ; 0xf7ce0
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf7ce2 logo.c:536
+ pop di ; 5f ; 0xf7ce5
+ pop si ; 5e ; 0xf7ce6
+ pop dx ; 5a ; 0xf7ce7
+ pop cx ; 59 ; 0xf7ce8
+ pop bx ; 5b ; 0xf7ce9
+ pop bp ; 5d ; 0xf7cea
+ retn ; c3 ; 0xf7ceb
+ ; disGetNextSymbol 0xf7cec LB 0x2359 -> off=0x0 cb=0000000000000067 uValue=00000000000f66ec 'delay_boot'
+delay_boot: ; 0xf7cec LB 0x67
+ push bp ; 55 ; 0xf7cec logo.c:539
+ mov bp, sp ; 89 e5 ; 0xf7ced
+ push bx ; 53 ; 0xf7cef
+ push dx ; 52 ; 0xf7cf0
+ mov dx, ax ; 89 c2 ; 0xf7cf1
+ test ax, ax ; 85 c0 ; 0xf7cf3 logo.c:543
+ je short 07d4ch ; 74 55 ; 0xf7cf5
+ mov AL, strict byte 034h ; b0 34 ; 0xf7cf7 logo.c:547
+ out strict byte 043h, AL ; e6 43 ; 0xf7cf9
+ mov AL, strict byte 0d3h ; b0 d3 ; 0xf7cfb
+ out strict byte 040h, AL ; e6 40 ; 0xf7cfd
+ mov AL, strict byte 048h ; b0 48 ; 0xf7cff
+ out strict byte 040h, AL ; e6 40 ; 0xf7d01
+ push dx ; 52 ; 0xf7d03 logo.c:549
+ push 00b0dh ; 68 0d 0b ; 0xf7d04
+ push strict byte 00002h ; 6a 02 ; 0xf7d07
+ call 01a14h ; e8 08 9d ; 0xf7d09
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7d0c
+ mov bx, dx ; 89 d3 ; 0xf7d0f logo.c:550
+ test bx, bx ; 85 db ; 0xf7d11
+ jbe short 07d2ch ; 76 17 ; 0xf7d13
+ push bx ; 53 ; 0xf7d15 logo.c:552
+ push 00b2bh ; 68 2b 0b ; 0xf7d16
+ push strict byte 00002h ; 6a 02 ; 0xf7d19
+ call 01a14h ; e8 f6 9c ; 0xf7d1b
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7d1e
+ xor dx, dx ; 31 d2 ; 0xf7d21 logo.c:553
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf7d23
+ call 0785fh ; e8 36 fb ; 0xf7d26
+ dec bx ; 4b ; 0xf7d29 logo.c:554
+ jmp short 07d11h ; eb e5 ; 0xf7d2a
+ push 00a5bh ; 68 5b 0a ; 0xf7d2c logo.c:555
+ push strict byte 00002h ; 6a 02 ; 0xf7d2f
+ call 01a14h ; e8 e0 9c ; 0xf7d31
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7d34
+ mov AL, strict byte 034h ; b0 34 ; 0xf7d37 logo.c:557
+ out strict byte 043h, AL ; e6 43 ; 0xf7d39
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf7d3b
+ out strict byte 040h, AL ; e6 40 ; 0xf7d3d
+ out strict byte 040h, AL ; e6 40 ; 0xf7d3f
+ pushad ; 66 60 ; 0xf7d41
+ push DS ; 1e ; 0xf7d43
+ mov ds, ax ; 8e d8 ; 0xf7d44
+ call 0edbfh ; e8 76 70 ; 0xf7d46
+ pop DS ; 1f ; 0xf7d49
+ popad ; 66 61 ; 0xf7d4a
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7d4c logo.c:558
+ pop dx ; 5a ; 0xf7d4f
+ pop bx ; 5b ; 0xf7d50
+ pop bp ; 5d ; 0xf7d51
+ retn ; c3 ; 0xf7d52
+ ; disGetNextSymbol 0xf7d53 LB 0x22f2 -> off=0x0 cb=00000000000000d5 uValue=00000000000f6753 'scsi_cmd_data_in'
+scsi_cmd_data_in: ; 0xf7d53 LB 0xd5
+ push bp ; 55 ; 0xf7d53 scsi.c:99
+ mov bp, sp ; 89 e5 ; 0xf7d54
+ push si ; 56 ; 0xf7d56
+ push di ; 57 ; 0xf7d57
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf7d58
+ mov si, ax ; 89 c6 ; 0xf7d5b
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf7d5d
+ mov word [bp-00ah], bx ; 89 5e f6 ; 0xf7d60
+ mov word [bp-008h], cx ; 89 4e f8 ; 0xf7d63
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf7d66
+ mov dx, si ; 89 f2 ; 0xf7d69 scsi.c:107
+ in AL, DX ; ec ; 0xf7d6b
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7d6c
+ test AL, strict byte 001h ; a8 01 ; 0xf7d6e scsi.c:108
+ jne short 07d69h ; 75 f7 ; 0xf7d70
+ cmp byte [bp+004h], 010h ; 80 7e 04 10 ; 0xf7d72 scsi.c:110
+ jne short 07d7ch ; 75 04 ; 0xf7d76
+ xor ax, ax ; 31 c0 ; 0xf7d78
+ jmp short 07d80h ; eb 04 ; 0xf7d7a
+ movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xf7d7c
+ mov di, ax ; 89 c7 ; 0xf7d80
+ mov ax, bx ; 89 d8 ; 0xf7d82
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf7d84
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf7d87
+ shr dx, 1 ; d1 ea ; 0xf7d8a
+ rcr ax, 1 ; d1 d8 ; 0xf7d8c
+ loop 07d8ah ; e2 fa ; 0xf7d8e
+ mov cx, ax ; 89 c1 ; 0xf7d90
+ and cx, 000f0h ; 81 e1 f0 00 ; 0xf7d92
+ or cx, di ; 09 f9 ; 0xf7d96
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7d98 scsi.c:111
+ mov dx, si ; 89 f2 ; 0xf7d9b
+ out DX, AL ; ee ; 0xf7d9d
+ xor al, al ; 30 c0 ; 0xf7d9e scsi.c:112
+ out DX, AL ; ee ; 0xf7da0
+ mov al, cl ; 88 c8 ; 0xf7da1 scsi.c:113
+ out DX, AL ; ee ; 0xf7da3
+ mov al, bl ; 88 d8 ; 0xf7da4 scsi.c:114
+ out DX, AL ; ee ; 0xf7da6
+ mov ax, bx ; 89 d8 ; 0xf7da7 scsi.c:115
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf7da9
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf7dac
+ shr dx, 1 ; d1 ea ; 0xf7daf
+ rcr ax, 1 ; d1 d8 ; 0xf7db1
+ loop 07dafh ; e2 fa ; 0xf7db3
+ mov dx, si ; 89 f2 ; 0xf7db5
+ out DX, AL ; ee ; 0xf7db7
+ xor cx, cx ; 31 c9 ; 0xf7db8 scsi.c:116
+ movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xf7dba
+ cmp cx, ax ; 39 c1 ; 0xf7dbe
+ jnc short 07dd0h ; 73 0e ; 0xf7dc0
+ les di, [bp-00ah] ; c4 7e f6 ; 0xf7dc2 scsi.c:117
+ add di, cx ; 01 cf ; 0xf7dc5
+ mov al, byte [es:di] ; 26 8a 05 ; 0xf7dc7
+ mov dx, si ; 89 f2 ; 0xf7dca
+ out DX, AL ; ee ; 0xf7dcc
+ inc cx ; 41 ; 0xf7dcd
+ jmp short 07dbah ; eb ea ; 0xf7dce
+ mov dx, si ; 89 f2 ; 0xf7dd0 scsi.c:121
+ in AL, DX ; ec ; 0xf7dd2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7dd3
+ test AL, strict byte 001h ; a8 01 ; 0xf7dd5 scsi.c:122
+ jne short 07dd0h ; 75 f7 ; 0xf7dd7
+ test AL, strict byte 002h ; a8 02 ; 0xf7dd9 scsi.c:125
+ je short 07debh ; 74 0e ; 0xf7ddb
+ lea dx, [si+003h] ; 8d 54 03 ; 0xf7ddd scsi.c:126
+ xor al, al ; 30 c0 ; 0xf7de0
+ out DX, AL ; ee ; 0xf7de2
+ in AL, DX ; ec ; 0xf7de3 scsi.c:128
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7de4
+ mov di, strict word 00004h ; bf 04 00 ; 0xf7de6 scsi.c:130
+ jmp short 07e1dh ; eb 32 ; 0xf7de9
+ lea dx, [si+001h] ; 8d 54 01 ; 0xf7deb scsi.c:136
+ cmp word [bp+00ch], strict byte 00000h ; 83 7e 0c 00 ; 0xf7dee
+ jne short 07dfah ; 75 06 ; 0xf7df2
+ cmp bx, 08000h ; 81 fb 00 80 ; 0xf7df4
+ jbe short 07e14h ; 76 1a ; 0xf7df8
+ mov cx, 08000h ; b9 00 80 ; 0xf7dfa scsi.c:138
+ les di, [bp+006h] ; c4 7e 06 ; 0xf7dfd
+ rep insb ; f3 6c ; 0xf7e00
+ add bx, 08000h ; 81 c3 00 80 ; 0xf7e02 scsi.c:139
+ adc word [bp+00ch], strict byte 0ffffh ; 83 56 0c ff ; 0xf7e06
+ mov ax, es ; 8c c0 ; 0xf7e0a
+ add ax, 00800h ; 05 00 08 ; 0xf7e0c
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf7e0f
+ jmp short 07debh ; eb d7 ; 0xf7e12 scsi.c:141
+ mov cx, bx ; 89 d9 ; 0xf7e14 scsi.c:144
+ les di, [bp+006h] ; c4 7e 06 ; 0xf7e16
+ rep insb ; f3 6c ; 0xf7e19
+ xor di, di ; 31 ff ; 0xf7e1b scsi.c:146
+ mov ax, di ; 89 f8 ; 0xf7e1d scsi.c:147
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7e1f
+ pop di ; 5f ; 0xf7e22
+ pop si ; 5e ; 0xf7e23
+ pop bp ; 5d ; 0xf7e24
+ retn 0000ah ; c2 0a 00 ; 0xf7e25
+ ; disGetNextSymbol 0xf7e28 LB 0x221d -> off=0x0 cb=00000000000000d5 uValue=00000000000f6828 'scsi_cmd_data_out'
+scsi_cmd_data_out: ; 0xf7e28 LB 0xd5
+ push bp ; 55 ; 0xf7e28 scsi.c:149
+ mov bp, sp ; 89 e5 ; 0xf7e29
+ push si ; 56 ; 0xf7e2b
+ push di ; 57 ; 0xf7e2c
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf7e2d
+ mov di, ax ; 89 c7 ; 0xf7e30
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf7e32
+ mov word [bp-00ah], bx ; 89 5e f6 ; 0xf7e35
+ mov word [bp-008h], cx ; 89 4e f8 ; 0xf7e38
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf7e3b
+ mov dx, di ; 89 fa ; 0xf7e3e scsi.c:157
+ in AL, DX ; ec ; 0xf7e40
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7e41
+ test AL, strict byte 001h ; a8 01 ; 0xf7e43 scsi.c:158
+ jne short 07e3eh ; 75 f7 ; 0xf7e45
+ cmp byte [bp+004h], 010h ; 80 7e 04 10 ; 0xf7e47 scsi.c:161
+ jne short 07e51h ; 75 04 ; 0xf7e4b
+ xor ax, ax ; 31 c0 ; 0xf7e4d
+ jmp short 07e55h ; eb 04 ; 0xf7e4f
+ movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xf7e51
+ mov si, ax ; 89 c6 ; 0xf7e55
+ mov ax, bx ; 89 d8 ; 0xf7e57
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf7e59
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf7e5c
+ shr dx, 1 ; d1 ea ; 0xf7e5f
+ rcr ax, 1 ; d1 d8 ; 0xf7e61
+ loop 07e5fh ; e2 fa ; 0xf7e63
+ mov cx, ax ; 89 c1 ; 0xf7e65
+ and cx, 000f0h ; 81 e1 f0 00 ; 0xf7e67
+ or cx, si ; 09 f1 ; 0xf7e6b
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7e6d scsi.c:162
+ mov dx, di ; 89 fa ; 0xf7e70
+ out DX, AL ; ee ; 0xf7e72
+ mov AL, strict byte 001h ; b0 01 ; 0xf7e73 scsi.c:163
+ out DX, AL ; ee ; 0xf7e75
+ mov al, cl ; 88 c8 ; 0xf7e76 scsi.c:164
+ out DX, AL ; ee ; 0xf7e78
+ mov al, bl ; 88 d8 ; 0xf7e79 scsi.c:165
+ out DX, AL ; ee ; 0xf7e7b
+ mov ax, bx ; 89 d8 ; 0xf7e7c scsi.c:166
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf7e7e
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf7e81
+ shr dx, 1 ; d1 ea ; 0xf7e84
+ rcr ax, 1 ; d1 d8 ; 0xf7e86
+ loop 07e84h ; e2 fa ; 0xf7e88
+ mov dx, di ; 89 fa ; 0xf7e8a
+ out DX, AL ; ee ; 0xf7e8c
+ xor cx, cx ; 31 c9 ; 0xf7e8d scsi.c:167
+ movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xf7e8f
+ cmp cx, ax ; 39 c1 ; 0xf7e93
+ jnc short 07ea5h ; 73 0e ; 0xf7e95
+ les si, [bp-00ah] ; c4 76 f6 ; 0xf7e97 scsi.c:168
+ add si, cx ; 01 ce ; 0xf7e9a
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf7e9c
+ mov dx, di ; 89 fa ; 0xf7e9f
+ out DX, AL ; ee ; 0xf7ea1
+ inc cx ; 41 ; 0xf7ea2
+ jmp short 07e8fh ; eb ea ; 0xf7ea3
+ lea dx, [di+001h] ; 8d 55 01 ; 0xf7ea5 scsi.c:173
+ cmp word [bp+00ch], strict byte 00000h ; 83 7e 0c 00 ; 0xf7ea8
+ jne short 07eb4h ; 75 06 ; 0xf7eac
+ cmp bx, 08000h ; 81 fb 00 80 ; 0xf7eae
+ jbe short 07ecfh ; 76 1b ; 0xf7eb2
+ mov cx, 08000h ; b9 00 80 ; 0xf7eb4 scsi.c:175
+ les si, [bp+006h] ; c4 76 06 ; 0xf7eb7
+ db 0f3h, 026h, 06eh
+ ; rep es outsb ; f3 26 6e ; 0xf7eba
+ add bx, 08000h ; 81 c3 00 80 ; 0xf7ebd scsi.c:176
+ adc word [bp+00ch], strict byte 0ffffh ; 83 56 0c ff ; 0xf7ec1
+ mov ax, es ; 8c c0 ; 0xf7ec5
+ add ax, 00800h ; 05 00 08 ; 0xf7ec7
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf7eca
+ jmp short 07ea5h ; eb d6 ; 0xf7ecd scsi.c:178
+ mov cx, bx ; 89 d9 ; 0xf7ecf scsi.c:181
+ les si, [bp+006h] ; c4 76 06 ; 0xf7ed1
+ db 0f3h, 026h, 06eh
+ ; rep es outsb ; f3 26 6e ; 0xf7ed4
+ mov dx, di ; 89 fa ; 0xf7ed7 scsi.c:185
+ in AL, DX ; ec ; 0xf7ed9
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7eda
+ test AL, strict byte 001h ; a8 01 ; 0xf7edc scsi.c:186
+ jne short 07ed7h ; 75 f7 ; 0xf7ede
+ test AL, strict byte 002h ; a8 02 ; 0xf7ee0 scsi.c:189
+ je short 07ef2h ; 74 0e ; 0xf7ee2
+ lea dx, [di+003h] ; 8d 55 03 ; 0xf7ee4 scsi.c:190
+ xor al, al ; 30 c0 ; 0xf7ee7
+ out DX, AL ; ee ; 0xf7ee9
+ in AL, DX ; ec ; 0xf7eea scsi.c:192
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7eeb
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf7eed scsi.c:194
+ jmp short 07ef4h ; eb 02 ; 0xf7ef0
+ xor ax, ax ; 31 c0 ; 0xf7ef2 scsi.c:197
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7ef4 scsi.c:198
+ pop di ; 5f ; 0xf7ef7
+ pop si ; 5e ; 0xf7ef8
+ pop bp ; 5d ; 0xf7ef9
+ retn 0000ah ; c2 0a 00 ; 0xf7efa
+ ; disGetNextSymbol 0xf7efd LB 0x2148 -> off=0x0 cb=00000000000000db uValue=00000000000f68fd 'scsi_read_sectors'
+scsi_read_sectors: ; 0xf7efd LB 0xdb
+ push bp ; 55 ; 0xf7efd scsi.c:207
+ mov bp, sp ; 89 e5 ; 0xf7efe
+ push si ; 56 ; 0xf7f00
+ push di ; 57 ; 0xf7f01
+ sub sp, strict byte 00016h ; 83 ec 16 ; 0xf7f02
+ mov si, word [bp+004h] ; 8b 76 04 ; 0xf7f05
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7f08 scsi.c:216
+ mov al, byte [es:si+00ch] ; 26 8a 44 0c ; 0xf7f0b
+ sub AL, strict byte 008h ; 2c 08 ; 0xf7f0f
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf7f11
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf7f14 scsi.c:217
+ jbe short 07f2bh ; 76 13 ; 0xf7f16
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf7f18 scsi.c:218
+ push ax ; 50 ; 0xf7f1c
+ push 00b30h ; 68 30 0b ; 0xf7f1d
+ push 00b42h ; 68 42 0b ; 0xf7f20
+ push strict byte 00007h ; 6a 07 ; 0xf7f23
+ call 01a14h ; e8 ec 9a ; 0xf7f25
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf7f28
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7f2b scsi.c:220
+ mov di, word [es:si+00eh] ; 26 8b 7c 0e ; 0xf7f2e
+ mov word [bp-01ah], 00088h ; c7 46 e6 88 00 ; 0xf7f32 scsi.c:223
+ mov ax, word [es:si+006h] ; 26 8b 44 06 ; 0xf7f37 scsi.c:224
+ mov bx, word [es:si+004h] ; 26 8b 5c 04 ; 0xf7f3b
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf7f3f
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf7f43
+ xchg ah, al ; 86 c4 ; 0xf7f46
+ xchg bh, bl ; 86 df ; 0xf7f48
+ xchg ch, cl ; 86 cd ; 0xf7f4a
+ xchg dh, dl ; 86 d6 ; 0xf7f4c
+ xchg dx, ax ; 92 ; 0xf7f4e
+ xchg bx, cx ; 87 cb ; 0xf7f4f
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf7f51
+ mov word [bp-014h], bx ; 89 5e ec ; 0xf7f54
+ mov word [bp-016h], cx ; 89 4e ea ; 0xf7f57
+ mov word [bp-018h], dx ; 89 56 e8 ; 0xf7f5a
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf7f5d scsi.c:225
+ mov ax, di ; 89 f8 ; 0xf7f61 scsi.c:226
+ xor dx, dx ; 31 d2 ; 0xf7f63
+ xchg ah, al ; 86 c4 ; 0xf7f65
+ xchg dh, dl ; 86 d6 ; 0xf7f67
+ xchg dx, ax ; 92 ; 0xf7f69
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf7f6a
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf7f6d
+ mov byte [bp-00bh], 000h ; c6 46 f5 00 ; 0xf7f70 scsi.c:227
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf7f74 scsi.c:230
+ sal ax, 002h ; c1 e0 02 ; 0xf7f78
+ mov bx, si ; 89 f3 ; 0xf7f7b
+ add bx, ax ; 01 c3 ; 0xf7f7d
+ mov ax, word [es:bx+0021ch] ; 26 8b 87 1c 02 ; 0xf7f7f
+ mov dl, byte [es:bx+0021eh] ; 26 8a 97 1e 02 ; 0xf7f84 scsi.c:231
+ mov word [bp-00ah], di ; 89 7e f6 ; 0xf7f89 scsi.c:236
+ mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xf7f8c
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf7f91
+ sal word [bp-00ah], 1 ; d1 66 f6 ; 0xf7f94
+ rcl word [bp-008h], 1 ; d1 56 f8 ; 0xf7f97
+ loop 07f94h ; e2 f8 ; 0xf7f9a
+ push dword [bp-00ah] ; 66 ff 76 f6 ; 0xf7f9c
+ db 066h, 026h, 0ffh, 074h, 008h
+ ; push dword [es:si+008h] ; 66 26 ff 74 08 ; 0xf7fa0
+ push strict byte 00010h ; 6a 10 ; 0xf7fa5
+ xor dh, dh ; 30 f6 ; 0xf7fa7
+ mov cx, ss ; 8c d1 ; 0xf7fa9
+ lea bx, [bp-01ah] ; 8d 5e e6 ; 0xf7fab
+ call 07d53h ; e8 a2 fd ; 0xf7fae
+ mov ah, al ; 88 c4 ; 0xf7fb1
+ test al, al ; 84 c0 ; 0xf7fb3 scsi.c:239
+ jne short 07fcch ; 75 15 ; 0xf7fb5
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7fb7 scsi.c:241
+ mov word [es:si+018h], di ; 26 89 7c 18 ; 0xf7fba
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf7fbe scsi.c:242
+ mov word [es:si+01ah], dx ; 26 89 54 1a ; 0xf7fc1
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf7fc5
+ mov word [es:si+01ch], dx ; 26 89 54 1c ; 0xf7fc8
+ movzx ax, ah ; 0f b6 c4 ; 0xf7fcc scsi.c:246
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7fcf scsi.c:247
+ pop di ; 5f ; 0xf7fd2
+ pop si ; 5e ; 0xf7fd3
+ pop bp ; 5d ; 0xf7fd4
+ retn 00004h ; c2 04 00 ; 0xf7fd5
+ ; disGetNextSymbol 0xf7fd8 LB 0x206d -> off=0x0 cb=00000000000000db uValue=00000000000f69d8 'scsi_write_sectors'
+scsi_write_sectors: ; 0xf7fd8 LB 0xdb
+ push bp ; 55 ; 0xf7fd8 scsi.c:256
+ mov bp, sp ; 89 e5 ; 0xf7fd9
+ push si ; 56 ; 0xf7fdb
+ push di ; 57 ; 0xf7fdc
+ sub sp, strict byte 00016h ; 83 ec 16 ; 0xf7fdd
+ mov si, word [bp+004h] ; 8b 76 04 ; 0xf7fe0
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7fe3 scsi.c:265
+ mov al, byte [es:si+00ch] ; 26 8a 44 0c ; 0xf7fe6
+ sub AL, strict byte 008h ; 2c 08 ; 0xf7fea
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf7fec
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf7fef scsi.c:266
+ jbe short 08006h ; 76 13 ; 0xf7ff1
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf7ff3 scsi.c:267
+ push ax ; 50 ; 0xf7ff7
+ push 00b61h ; 68 61 0b ; 0xf7ff8
+ push 00b42h ; 68 42 0b ; 0xf7ffb
+ push strict byte 00007h ; 6a 07 ; 0xf7ffe
+ call 01a14h ; e8 11 9a ; 0xf8000
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf8003
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf8006 scsi.c:269
+ mov di, word [es:si+00eh] ; 26 8b 7c 0e ; 0xf8009
+ mov word [bp-01ah], 0008ah ; c7 46 e6 8a 00 ; 0xf800d scsi.c:272
+ mov ax, word [es:si+006h] ; 26 8b 44 06 ; 0xf8012 scsi.c:273
+ mov bx, word [es:si+004h] ; 26 8b 5c 04 ; 0xf8016
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf801a
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf801e
+ xchg ah, al ; 86 c4 ; 0xf8021
+ xchg bh, bl ; 86 df ; 0xf8023
+ xchg ch, cl ; 86 cd ; 0xf8025
+ xchg dh, dl ; 86 d6 ; 0xf8027
+ xchg dx, ax ; 92 ; 0xf8029
+ xchg bx, cx ; 87 cb ; 0xf802a
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf802c
+ mov word [bp-014h], bx ; 89 5e ec ; 0xf802f
+ mov word [bp-016h], cx ; 89 4e ea ; 0xf8032
+ mov word [bp-018h], dx ; 89 56 e8 ; 0xf8035
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf8038 scsi.c:274
+ mov ax, di ; 89 f8 ; 0xf803c scsi.c:275
+ xor dx, dx ; 31 d2 ; 0xf803e
+ xchg ah, al ; 86 c4 ; 0xf8040
+ xchg dh, dl ; 86 d6 ; 0xf8042
+ xchg dx, ax ; 92 ; 0xf8044
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf8045
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf8048
+ mov byte [bp-00bh], 000h ; c6 46 f5 00 ; 0xf804b scsi.c:276
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf804f scsi.c:278
+ sal ax, 002h ; c1 e0 02 ; 0xf8053
+ mov bx, si ; 89 f3 ; 0xf8056
+ add bx, ax ; 01 c3 ; 0xf8058
+ mov ax, word [es:bx+0021ch] ; 26 8b 87 1c 02 ; 0xf805a
+ mov dl, byte [es:bx+0021eh] ; 26 8a 97 1e 02 ; 0xf805f scsi.c:279
+ mov word [bp-00ah], di ; 89 7e f6 ; 0xf8064 scsi.c:284
+ mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xf8067
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf806c
+ sal word [bp-00ah], 1 ; d1 66 f6 ; 0xf806f
+ rcl word [bp-008h], 1 ; d1 56 f8 ; 0xf8072
+ loop 0806fh ; e2 f8 ; 0xf8075
+ push dword [bp-00ah] ; 66 ff 76 f6 ; 0xf8077
+ db 066h, 026h, 0ffh, 074h, 008h
+ ; push dword [es:si+008h] ; 66 26 ff 74 08 ; 0xf807b
+ push strict byte 00010h ; 6a 10 ; 0xf8080
+ xor dh, dh ; 30 f6 ; 0xf8082
+ mov cx, ss ; 8c d1 ; 0xf8084
+ lea bx, [bp-01ah] ; 8d 5e e6 ; 0xf8086
+ call 07e28h ; e8 9c fd ; 0xf8089
+ mov ah, al ; 88 c4 ; 0xf808c
+ test al, al ; 84 c0 ; 0xf808e scsi.c:287
+ jne short 080a7h ; 75 15 ; 0xf8090
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf8092 scsi.c:289
+ mov word [es:si+018h], di ; 26 89 7c 18 ; 0xf8095
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8099 scsi.c:290
+ mov word [es:si+01ah], dx ; 26 89 54 1a ; 0xf809c
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf80a0
+ mov word [es:si+01ch], dx ; 26 89 54 1c ; 0xf80a3
+ movzx ax, ah ; 0f b6 c4 ; 0xf80a7 scsi.c:294
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf80aa scsi.c:295
+ pop di ; 5f ; 0xf80ad
+ pop si ; 5e ; 0xf80ae
+ pop bp ; 5d ; 0xf80af
+ retn 00004h ; c2 04 00 ; 0xf80b0
+ ; disGetNextSymbol 0xf80b3 LB 0x1f92 -> off=0x0 cb=0000000000000168 uValue=00000000000f6ab3 'scsi_cmd_packet'
+scsi_cmd_packet: ; 0xf80b3 LB 0x168
+ push bp ; 55 ; 0xf80b3 scsi.c:315
+ mov bp, sp ; 89 e5 ; 0xf80b4
+ push si ; 56 ; 0xf80b6
+ push di ; 57 ; 0xf80b7
+ sub sp, strict byte 0000ch ; 83 ec 0c ; 0xf80b8
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf80bb
+ mov word [bp-00eh], bx ; 89 5e f2 ; 0xf80be
+ mov word [bp-00ch], cx ; 89 4e f4 ; 0xf80c1
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf80c4 scsi.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf80c7
+ mov es, dx ; 8e c2 ; 0xf80ca
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf80cc
+ mov si, 00122h ; be 22 01 ; 0xf80cf scsi.c:49
+ mov word [bp-00ah], dx ; 89 56 f6 ; 0xf80d2
+ cmp byte [bp+00ah], 002h ; 80 7e 0a 02 ; 0xf80d5 scsi.c:326
+ jne short 080fah ; 75 1f ; 0xf80d9
+ mov bx, 00db2h ; bb b2 0d ; 0xf80db scsi.c:327
+ mov cx, ds ; 8c d9 ; 0xf80de
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf80e0
+ call 019d3h ; e8 ed 98 ; 0xf80e3
+ push 00b74h ; 68 74 0b ; 0xf80e6
+ push 00b84h ; 68 84 0b ; 0xf80e9
+ push strict byte 00004h ; 6a 04 ; 0xf80ec
+ call 01a14h ; e8 23 99 ; 0xf80ee
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf80f1
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf80f4 scsi.c:328
+ jmp near 08210h ; e9 16 01 ; 0xf80f7
+ sub ax, strict word 00008h ; 2d 08 00 ; 0xf80fa scsi.c:332
+ sal ax, 002h ; c1 e0 02 ; 0xf80fd scsi.c:342
+ sub byte [bp-006h], 002h ; 80 6e fa 02 ; 0xf8100 scsi.c:340
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8104
+ mov di, si ; 89 f7 ; 0xf8107
+ add di, ax ; 01 c7 ; 0xf8109
+ mov bx, word [es:di+0021ch] ; 26 8b 9d 1c 02 ; 0xf810b
+ mov al, byte [es:di+0021eh] ; 26 8a 85 1e 02 ; 0xf8110 scsi.c:343
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf8115
+ mov dx, bx ; 89 da ; 0xf8118 scsi.c:347
+ in AL, DX ; ec ; 0xf811a
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf811b
+ test AL, strict byte 001h ; a8 01 ; 0xf811d scsi.c:348
+ jne short 08118h ; 75 f7 ; 0xf811f
+ xor dx, bx ; 31 da ; 0xf8121 scsi.c:354
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf8123
+ add ax, word [bp+004h] ; 03 46 04 ; 0xf8126
+ mov cx, word [bp+008h] ; 8b 4e 08 ; 0xf8129
+ adc cx, dx ; 11 d1 ; 0xf812c
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf812e
+ mov dx, word [es:si+020h] ; 26 8b 54 20 ; 0xf8131
+ xor di, di ; 31 ff ; 0xf8135
+ add ax, dx ; 01 d0 ; 0xf8137
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf8139
+ adc di, cx ; 11 cf ; 0xf813c
+ mov dx, di ; 89 fa ; 0xf813e scsi.c:356
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf8140
+ shr dx, 1 ; d1 ea ; 0xf8143
+ rcr ax, 1 ; d1 d8 ; 0xf8145
+ loop 08143h ; e2 fa ; 0xf8147
+ and ax, 000f0h ; 25 f0 00 ; 0xf8149
+ movzx cx, byte [bp-006h] ; 0f b6 4e fa ; 0xf814c
+ or cx, ax ; 09 c1 ; 0xf8150
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8152 scsi.c:357
+ mov dx, bx ; 89 da ; 0xf8155
+ out DX, AL ; ee ; 0xf8157
+ xor al, al ; 30 c0 ; 0xf8158 scsi.c:358
+ out DX, AL ; ee ; 0xf815a
+ mov al, cl ; 88 c8 ; 0xf815b scsi.c:359
+ out DX, AL ; ee ; 0xf815d
+ mov al, byte [bp-010h] ; 8a 46 f0 ; 0xf815e scsi.c:360
+ out DX, AL ; ee ; 0xf8161
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf8162 scsi.c:361
+ mov dx, di ; 89 fa ; 0xf8165
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf8167
+ shr dx, 1 ; d1 ea ; 0xf816a
+ rcr ax, 1 ; d1 d8 ; 0xf816c
+ loop 0816ah ; e2 fa ; 0xf816e
+ mov dx, bx ; 89 da ; 0xf8170
+ out DX, AL ; ee ; 0xf8172
+ xor cx, cx ; 31 c9 ; 0xf8173 scsi.c:362
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf8175
+ cmp cx, ax ; 39 c1 ; 0xf8179
+ jnc short 0818bh ; 73 0e ; 0xf817b
+ les di, [bp-00eh] ; c4 7e f2 ; 0xf817d scsi.c:363
+ add di, cx ; 01 cf ; 0xf8180
+ mov al, byte [es:di] ; 26 8a 05 ; 0xf8182
+ mov dx, bx ; 89 da ; 0xf8185
+ out DX, AL ; ee ; 0xf8187
+ inc cx ; 41 ; 0xf8188
+ jmp short 08175h ; eb ea ; 0xf8189
+ mov dx, bx ; 89 da ; 0xf818b scsi.c:367
+ in AL, DX ; ec ; 0xf818d
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf818e
+ test AL, strict byte 001h ; a8 01 ; 0xf8190 scsi.c:368
+ jne short 0818bh ; 75 f7 ; 0xf8192
+ test AL, strict byte 002h ; a8 02 ; 0xf8194 scsi.c:371
+ je short 081a6h ; 74 0e ; 0xf8196
+ lea dx, [bx+003h] ; 8d 57 03 ; 0xf8198 scsi.c:372
+ xor al, al ; 30 c0 ; 0xf819b
+ out DX, AL ; ee ; 0xf819d
+ in AL, DX ; ec ; 0xf819e scsi.c:374
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf819f
+ mov dx, strict word 00003h ; ba 03 00 ; 0xf81a1 scsi.c:376
+ jmp short 08210h ; eb 6a ; 0xf81a4
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf81a6 scsi.c:381
+ test ax, ax ; 85 c0 ; 0xf81a9
+ je short 081b5h ; 74 08 ; 0xf81ab
+ lea dx, [bx+001h] ; 8d 57 01 ; 0xf81ad scsi.c:382
+ mov cx, ax ; 89 c1 ; 0xf81b0
+ in AL, DX ; ec ; 0xf81b2
+ loop 081b2h ; e2 fd ; 0xf81b3
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf81b5 scsi.c:384
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf81b8
+ mov word [es:si+01ah], ax ; 26 89 44 1a ; 0xf81bb
+ mov ax, word [bp+008h] ; 8b 46 08 ; 0xf81bf
+ mov word [es:si+01ch], ax ; 26 89 44 1c ; 0xf81c2
+ lea ax, [bx+001h] ; 8d 47 01 ; 0xf81c6 scsi.c:389
+ cmp word [bp+008h], strict byte 00000h ; 83 7e 08 00 ; 0xf81c9
+ jne short 081d6h ; 75 07 ; 0xf81cd
+ cmp word [bp+006h], 08000h ; 81 7e 06 00 80 ; 0xf81cf
+ jbe short 081f3h ; 76 1d ; 0xf81d4
+ mov dx, ax ; 89 c2 ; 0xf81d6 scsi.c:391
+ mov cx, 08000h ; b9 00 80 ; 0xf81d8
+ les di, [bp+00ch] ; c4 7e 0c ; 0xf81db
+ rep insb ; f3 6c ; 0xf81de
+ add word [bp+006h], 08000h ; 81 46 06 00 80 ; 0xf81e0 scsi.c:392
+ adc word [bp+008h], strict byte 0ffffh ; 83 56 08 ff ; 0xf81e5
+ mov ax, es ; 8c c0 ; 0xf81e9
+ add ax, 00800h ; 05 00 08 ; 0xf81eb
+ mov word [bp+00eh], ax ; 89 46 0e ; 0xf81ee
+ jmp short 081c6h ; eb d3 ; 0xf81f1 scsi.c:394
+ mov dx, ax ; 89 c2 ; 0xf81f3 scsi.c:397
+ mov cx, word [bp+006h] ; 8b 4e 06 ; 0xf81f5
+ les di, [bp+00ch] ; c4 7e 0c ; 0xf81f8
+ rep insb ; f3 6c ; 0xf81fb
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf81fd scsi.c:399
+ cmp word [es:si+020h], strict byte 00000h ; 26 83 7c 20 00 ; 0xf8200
+ je short 0820eh ; 74 07 ; 0xf8205
+ mov cx, word [es:si+020h] ; 26 8b 4c 20 ; 0xf8207 scsi.c:400
+ in AL, DX ; ec ; 0xf820b
+ loop 0820bh ; e2 fd ; 0xf820c
+ xor dx, dx ; 31 d2 ; 0xf820e scsi.c:402
+ mov ax, dx ; 89 d0 ; 0xf8210 scsi.c:403
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf8212
+ pop di ; 5f ; 0xf8215
+ pop si ; 5e ; 0xf8216
+ pop bp ; 5d ; 0xf8217
+ retn 0000ch ; c2 0c 00 ; 0xf8218
+ ; disGetNextSymbol 0xf821b LB 0x1e2a -> off=0x0 cb=0000000000000484 uValue=00000000000f6c1b 'scsi_enumerate_attached_devices'
+scsi_enumerate_attached_devices: ; 0xf821b LB 0x484
+ push bp ; 55 ; 0xf821b scsi.c:411
+ mov bp, sp ; 89 e5 ; 0xf821c
+ push bx ; 53 ; 0xf821e
+ push cx ; 51 ; 0xf821f
+ push dx ; 52 ; 0xf8220
+ push si ; 56 ; 0xf8221
+ push di ; 57 ; 0xf8222
+ sub sp, 0023ch ; 81 ec 3c 02 ; 0xf8223
+ push ax ; 50 ; 0xf8227
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf8228 scsi.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf822b
+ mov es, ax ; 8e c0 ; 0xf822e
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf8230
+ mov di, 00122h ; bf 22 01 ; 0xf8233 scsi.c:49
+ mov word [bp-022h], ax ; 89 46 de ; 0xf8236
+ mov word [bp-01ch], strict word 00000h ; c7 46 e4 00 00 ; 0xf8239 scsi.c:420
+ jmp near 08621h ; e9 e0 03 ; 0xf823e
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf8241 scsi.c:440
+ jnc near 08695h ; 0f 83 4e 04 ; 0xf8243
+ mov cx, strict word 00010h ; b9 10 00 ; 0xf8247 scsi.c:455
+ xor bx, bx ; 31 db ; 0xf824a
+ mov dx, ss ; 8c d2 ; 0xf824c
+ lea ax, [bp-046h] ; 8d 46 ba ; 0xf824e
+ call 09fb0h ; e8 5c 1d ; 0xf8251
+ mov byte [bp-046h], 09eh ; c6 46 ba 9e ; 0xf8254 scsi.c:456
+ mov byte [bp-045h], 010h ; c6 46 bb 10 ; 0xf8258 scsi.c:457
+ mov byte [bp-039h], 020h ; c6 46 c7 20 ; 0xf825c scsi.c:458
+ push dword 000000020h ; 66 6a 20 ; 0xf8260 scsi.c:460
+ lea dx, [bp-00246h] ; 8d 96 ba fd ; 0xf8263
+ push SS ; 16 ; 0xf8267
+ push dx ; 52 ; 0xf8268
+ push strict byte 00010h ; 6a 10 ; 0xf8269
+ movzx dx, byte [bp-01ch] ; 0f b6 56 e4 ; 0xf826b
+ mov cx, ss ; 8c d1 ; 0xf826f
+ lea bx, [bp-046h] ; 8d 5e ba ; 0xf8271
+ mov ax, word [bp-00248h] ; 8b 86 b8 fd ; 0xf8274
+ call 07d53h ; e8 d8 fa ; 0xf8278
+ test al, al ; 84 c0 ; 0xf827b scsi.c:461
+ je short 0828dh ; 74 0e ; 0xf827d
+ push 00ba4h ; 68 a4 0b ; 0xf827f scsi.c:462
+ push 00bddh ; 68 dd 0b ; 0xf8282
+ push strict byte 00007h ; 6a 07 ; 0xf8285
+ call 01a14h ; e8 8a 97 ; 0xf8287
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf828a
+ mov ax, word [bp-00240h] ; 8b 86 c0 fd ; 0xf828d scsi.c:467
+ mov bx, word [bp-00242h] ; 8b 9e be fd ; 0xf8291
+ mov cx, word [bp-00244h] ; 8b 8e bc fd ; 0xf8295
+ mov dx, word [bp-00246h] ; 8b 96 ba fd ; 0xf8299
+ xchg ah, al ; 86 c4 ; 0xf829d
+ xchg bh, bl ; 86 df ; 0xf829f
+ xchg ch, cl ; 86 cd ; 0xf82a1
+ xchg dh, dl ; 86 d6 ; 0xf82a3
+ xchg dx, ax ; 92 ; 0xf82a5
+ xchg bx, cx ; 87 cb ; 0xf82a6
+ add dx, strict byte 00001h ; 83 c2 01 ; 0xf82a8
+ mov word [bp-012h], dx ; 89 56 ee ; 0xf82ab
+ adc cx, strict byte 00000h ; 83 d1 00 ; 0xf82ae
+ mov word [bp-010h], cx ; 89 4e f0 ; 0xf82b1
+ adc bx, strict byte 00000h ; 83 d3 00 ; 0xf82b4
+ mov word [bp-016h], bx ; 89 5e ea ; 0xf82b7
+ adc ax, strict word 00000h ; 15 00 00 ; 0xf82ba
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf82bd
+ movzx si, byte [bp-0023eh] ; 0f b6 b6 c2 fd ; 0xf82c0 scsi.c:469
+ sal si, 008h ; c1 e6 08 ; 0xf82c5
+ movzx ax, byte [bp-0023dh] ; 0f b6 86 c3 fd ; 0xf82c8
+ xor bx, bx ; 31 db ; 0xf82cd
+ or si, ax ; 09 c6 ; 0xf82cf
+ movzx ax, byte [bp-0023ch] ; 0f b6 86 c4 fd ; 0xf82d1
+ xor dx, dx ; 31 d2 ; 0xf82d6
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf82d8
+ sal ax, 1 ; d1 e0 ; 0xf82db
+ rcl dx, 1 ; d1 d2 ; 0xf82dd
+ loop 082dbh ; e2 fa ; 0xf82df
+ or ax, bx ; 09 d8 ; 0xf82e1
+ or dx, si ; 09 f2 ; 0xf82e3
+ movzx bx, byte [bp-0023bh] ; 0f b6 9e c5 fd ; 0xf82e5
+ or ax, bx ; 09 d8 ; 0xf82ea
+ mov word [bp-028h], ax ; 89 46 d8 ; 0xf82ec
+ test dx, dx ; 85 d2 ; 0xf82ef scsi.c:475
+ jne short 082f8h ; 75 05 ; 0xf82f1
+ cmp ax, 00200h ; 3d 00 02 ; 0xf82f3
+ je short 08318h ; 74 20 ; 0xf82f6
+ mov bx, 00db2h ; bb b2 0d ; 0xf82f8 scsi.c:478
+ mov cx, ds ; 8c d9 ; 0xf82fb
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf82fd
+ call 019d3h ; e8 d0 96 ; 0xf8300
+ push dx ; 52 ; 0xf8303
+ push word [bp-028h] ; ff 76 d8 ; 0xf8304
+ push word [bp-01ch] ; ff 76 e4 ; 0xf8307
+ push 00bfch ; 68 fc 0b ; 0xf830a
+ push strict byte 00004h ; 6a 04 ; 0xf830d
+ call 01a14h ; e8 02 97 ; 0xf830f
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf8312
+ jmp near 08618h ; e9 00 03 ; 0xf8315 scsi.c:479
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf8318 scsi.c:483
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf831b
+ jc short 0832bh ; 72 0c ; 0xf831d
+ jbe short 08333h ; 76 12 ; 0xf831f
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf8321
+ je short 0833bh ; 74 16 ; 0xf8323
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf8325
+ je short 08337h ; 74 0e ; 0xf8327
+ jmp short 08384h ; eb 59 ; 0xf8329
+ test al, al ; 84 c0 ; 0xf832b
+ jne short 08384h ; 75 55 ; 0xf832d
+ mov BL, strict byte 090h ; b3 90 ; 0xf832f scsi.c:486
+ jmp short 0833dh ; eb 0a ; 0xf8331 scsi.c:487
+ mov BL, strict byte 098h ; b3 98 ; 0xf8333 scsi.c:489
+ jmp short 0833dh ; eb 06 ; 0xf8335 scsi.c:490
+ mov BL, strict byte 0a0h ; b3 a0 ; 0xf8337 scsi.c:492
+ jmp short 0833dh ; eb 02 ; 0xf8339 scsi.c:493
+ mov BL, strict byte 0a8h ; b3 a8 ; 0xf833b scsi.c:495
+ mov al, bl ; 88 d8 ; 0xf833d scsi.c:499
+ add AL, strict byte 007h ; 04 07 ; 0xf833f
+ movzx cx, al ; 0f b6 c8 ; 0xf8341
+ mov ax, cx ; 89 c8 ; 0xf8344
+ call 01756h ; e8 0d 94 ; 0xf8346
+ test al, al ; 84 c0 ; 0xf8349
+ je short 08384h ; 74 37 ; 0xf834b
+ mov al, bl ; 88 d8 ; 0xf834d scsi.c:504
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf834f
+ xor ah, ah ; 30 e4 ; 0xf8351
+ call 01756h ; e8 00 94 ; 0xf8353
+ movzx dx, al ; 0f b6 d0 ; 0xf8356
+ sal dx, 008h ; c1 e2 08 ; 0xf8359
+ movzx ax, bl ; 0f b6 c3 ; 0xf835c
+ call 01756h ; e8 f4 93 ; 0xf835f
+ xor ah, ah ; 30 e4 ; 0xf8362
+ add ax, dx ; 01 d0 ; 0xf8364
+ cwd ; 99 ; 0xf8366
+ mov si, ax ; 89 c6 ; 0xf8367
+ mov al, bl ; 88 d8 ; 0xf8369 scsi.c:505
+ add AL, strict byte 002h ; 04 02 ; 0xf836b
+ xor ah, ah ; 30 e4 ; 0xf836d
+ call 01756h ; e8 e4 93 ; 0xf836f
+ xor ah, ah ; 30 e4 ; 0xf8372
+ mov word [bp-032h], ax ; 89 46 ce ; 0xf8374
+ mov ax, cx ; 89 c8 ; 0xf8377 scsi.c:506
+ call 01756h ; e8 da 93 ; 0xf8379
+ xor ah, ah ; 30 e4 ; 0xf837c
+ mov word [bp-026h], ax ; 89 46 da ; 0xf837e
+ jmp near 08473h ; e9 ef 00 ; 0xf8381 scsi.c:508
+ mov ax, word [bp-024h] ; 8b 46 dc ; 0xf8384 scsi.c:509
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf8387
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf838a
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf838d
+ mov si, strict word 0000ch ; be 0c 00 ; 0xf8390
+ call 09f90h ; e8 fa 1b ; 0xf8393
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf8396
+ mov word [bp-014h], bx ; 89 5e ec ; 0xf8399
+ mov word [bp-018h], cx ; 89 4e e8 ; 0xf839c
+ mov word [bp-02ah], dx ; 89 56 d6 ; 0xf839f
+ mov ax, word [bp-024h] ; 8b 46 dc ; 0xf83a2 scsi.c:513
+ test ax, ax ; 85 c0 ; 0xf83a5
+ jnbe short 083bfh ; 77 16 ; 0xf83a7
+ jne near 08434h ; 0f 85 87 00 ; 0xf83a9
+ cmp word [bp-016h], strict byte 00000h ; 83 7e ea 00 ; 0xf83ad
+ jnbe short 083bfh ; 77 0c ; 0xf83b1
+ jne near 08434h ; 0f 85 7d 00 ; 0xf83b3
+ cmp word [bp-010h], strict byte 00040h ; 83 7e f0 40 ; 0xf83b7
+ jnbe short 083bfh ; 77 02 ; 0xf83bb
+ jne short 08434h ; 75 75 ; 0xf83bd
+ mov word [bp-032h], 000ffh ; c7 46 ce ff 00 ; 0xf83bf scsi.c:515
+ mov word [bp-026h], strict word 0003fh ; c7 46 da 3f 00 ; 0xf83c4 scsi.c:516
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf83c9 scsi.c:518
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf83cc
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf83cf
+ mov si, strict word 00006h ; be 06 00 ; 0xf83d2
+ call 09f90h ; e8 b8 1b ; 0xf83d5
+ mov si, word [bp-02ah] ; 8b 76 d6 ; 0xf83d8
+ add si, dx ; 01 d6 ; 0xf83db
+ mov word [bp-02ch], si ; 89 76 d4 ; 0xf83dd
+ mov dx, word [bp-018h] ; 8b 56 e8 ; 0xf83e0
+ adc dx, cx ; 11 ca ; 0xf83e3
+ mov word [bp-01eh], dx ; 89 56 e2 ; 0xf83e5
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf83e8
+ adc dx, bx ; 11 da ; 0xf83eb
+ mov word [bp-034h], dx ; 89 56 cc ; 0xf83ed
+ mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xf83f0
+ adc dx, ax ; 11 c2 ; 0xf83f3
+ mov word [bp-036h], dx ; 89 56 ca ; 0xf83f5
+ mov ax, dx ; 89 d0 ; 0xf83f8 scsi.c:519
+ mov bx, word [bp-034h] ; 8b 5e cc ; 0xf83fa
+ mov cx, word [bp-01eh] ; 8b 4e e2 ; 0xf83fd
+ mov dx, si ; 89 f2 ; 0xf8400
+ mov si, strict word 00008h ; be 08 00 ; 0xf8402
+ call 09f90h ; e8 88 1b ; 0xf8405
+ mov word [bp-02eh], bx ; 89 5e d2 ; 0xf8408
+ mov word [bp-020h], cx ; 89 4e e0 ; 0xf840b
+ mov word [bp-030h], dx ; 89 56 d0 ; 0xf840e
+ mov ax, word [bp-036h] ; 8b 46 ca ; 0xf8411
+ mov bx, word [bp-034h] ; 8b 5e cc ; 0xf8414
+ mov cx, word [bp-01eh] ; 8b 4e e2 ; 0xf8417
+ mov dx, word [bp-02ch] ; 8b 56 d4 ; 0xf841a
+ mov si, strict word 00010h ; be 10 00 ; 0xf841d
+ call 09f90h ; e8 6d 1b ; 0xf8420
+ mov si, word [bp-030h] ; 8b 76 d0 ; 0xf8423
+ add si, dx ; 01 d6 ; 0xf8426
+ mov dx, word [bp-020h] ; 8b 56 e0 ; 0xf8428
+ adc dx, cx ; 11 ca ; 0xf842b
+ mov ax, word [bp-02eh] ; 8b 46 d2 ; 0xf842d
+ adc ax, bx ; 11 d8 ; 0xf8430
+ jmp short 08473h ; eb 3f ; 0xf8432 scsi.c:521
+ test ax, ax ; 85 c0 ; 0xf8434
+ jnbe short 0844ah ; 77 12 ; 0xf8436
+ jne short 08456h ; 75 1c ; 0xf8438
+ cmp word [bp-016h], strict byte 00000h ; 83 7e ea 00 ; 0xf843a
+ jnbe short 0844ah ; 77 0a ; 0xf843e
+ jne short 08456h ; 75 14 ; 0xf8440
+ cmp word [bp-010h], strict byte 00020h ; 83 7e f0 20 ; 0xf8442
+ jnbe short 0844ah ; 77 02 ; 0xf8446
+ jne short 08456h ; 75 0c ; 0xf8448
+ mov word [bp-032h], 00080h ; c7 46 ce 80 00 ; 0xf844a scsi.c:523
+ mov word [bp-026h], strict word 00020h ; c7 46 da 20 00 ; 0xf844f scsi.c:524
+ jmp short 0846fh ; eb 19 ; 0xf8454 scsi.c:527
+ mov word [bp-032h], strict word 00040h ; c7 46 ce 40 00 ; 0xf8456 scsi.c:529
+ mov word [bp-026h], strict word 00020h ; c7 46 da 20 00 ; 0xf845b scsi.c:530
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf8460 scsi.c:531
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf8463
+ mov dx, word [bp-012h] ; 8b 56 ee ; 0xf8466
+ mov si, strict word 0000bh ; be 0b 00 ; 0xf8469
+ call 09f90h ; e8 21 1b ; 0xf846c
+ mov si, dx ; 89 d6 ; 0xf846f
+ mov dx, cx ; 89 ca ; 0xf8471
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf8473 scsi.c:536
+ add AL, strict byte 008h ; 04 08 ; 0xf8476
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf8478
+ movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xf847b scsi.c:538
+ sal ax, 002h ; c1 e0 02 ; 0xf847f
+ mov es, [bp-022h] ; 8e 46 de ; 0xf8482
+ mov bx, di ; 89 fb ; 0xf8485
+ add bx, ax ; 01 c3 ; 0xf8487
+ mov ax, word [bp-00248h] ; 8b 86 b8 fd ; 0xf8489
+ mov word [es:bx+0021ch], ax ; 26 89 87 1c 02 ; 0xf848d
+ mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xf8492 scsi.c:539
+ mov byte [es:bx+0021eh], al ; 26 88 87 1e 02 ; 0xf8495
+ movzx bx, byte [bp-00eh] ; 0f b6 5e f2 ; 0xf849a scsi.c:540
+ imul bx, bx, strict byte 0001ch ; 6b db 1c ; 0xf849e
+ add bx, di ; 01 fb ; 0xf84a1
+ db 066h, 026h, 0c7h, 047h, 022h, 004h, 0ffh, 000h, 000h
+ ; mov dword [es:bx+022h], strict dword 00000ff04h ; 66 26 c7 47 22 04 ff 00 00; 0xf84a3
+ mov ax, word [bp-028h] ; 8b 46 d8 ; 0xf84ac scsi.c:544
+ mov word [es:bx+028h], ax ; 26 89 47 28 ; 0xf84af
+ mov byte [es:bx+027h], 001h ; 26 c6 47 27 01 ; 0xf84b3 scsi.c:545
+ mov ax, word [bp-032h] ; 8b 46 ce ; 0xf84b8 scsi.c:548
+ mov word [es:bx+02ah], ax ; 26 89 47 2a ; 0xf84bb
+ mov ax, word [bp-026h] ; 8b 46 da ; 0xf84bf scsi.c:549
+ mov word [es:bx+02eh], ax ; 26 89 47 2e ; 0xf84c2
+ mov ax, word [bp-032h] ; 8b 46 ce ; 0xf84c6 scsi.c:550
+ mov word [es:bx+030h], ax ; 26 89 47 30 ; 0xf84c9
+ mov ax, word [bp-026h] ; 8b 46 da ; 0xf84cd scsi.c:551
+ mov word [es:bx+034h], ax ; 26 89 47 34 ; 0xf84d0
+ test dx, dx ; 85 d2 ; 0xf84d4 scsi.c:553
+ jne short 084deh ; 75 06 ; 0xf84d6
+ cmp si, 00400h ; 81 fe 00 04 ; 0xf84d8
+ jbe short 084ech ; 76 0e ; 0xf84dc
+ mov word [es:bx+02ch], 00400h ; 26 c7 47 2c 00 04 ; 0xf84de scsi.c:554
+ mov word [es:bx+032h], 00400h ; 26 c7 47 32 00 04 ; 0xf84e4 scsi.c:555
+ jmp short 084f4h ; eb 08 ; 0xf84ea scsi.c:556
+ mov word [es:bx+02ch], si ; 26 89 77 2c ; 0xf84ec scsi.c:557
+ mov word [es:bx+032h], si ; 26 89 77 32 ; 0xf84f0 scsi.c:558
+ mov bx, 00db2h ; bb b2 0d ; 0xf84f4 scsi.c:562
+ mov cx, ds ; 8c d9 ; 0xf84f7
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf84f9
+ call 019d3h ; e8 d4 94 ; 0xf84fc
+ push word [bp-024h] ; ff 76 dc ; 0xf84ff
+ push word [bp-016h] ; ff 76 ea ; 0xf8502
+ push dword [bp-012h] ; 66 ff 76 ee ; 0xf8505
+ push word [bp-026h] ; ff 76 da ; 0xf8509
+ push word [bp-032h] ; ff 76 ce ; 0xf850c
+ push dx ; 52 ; 0xf850f
+ push si ; 56 ; 0xf8510
+ push word [bp-01ch] ; ff 76 e4 ; 0xf8511
+ movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xf8514
+ push ax ; 50 ; 0xf8518
+ push 00c2ah ; 68 2a 0c ; 0xf8519
+ push strict byte 00004h ; 6a 04 ; 0xf851c
+ call 01a14h ; e8 f3 94 ; 0xf851e
+ add sp, strict byte 00018h ; 83 c4 18 ; 0xf8521
+ movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xf8524 scsi.c:564
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf8528
+ mov es, [bp-022h] ; 8e 46 de ; 0xf852b
+ mov bx, di ; 89 fb ; 0xf852e
+ add bx, ax ; 01 c3 ; 0xf8530
+ mov ax, word [bp-024h] ; 8b 46 dc ; 0xf8532
+ mov word [es:bx+03ch], ax ; 26 89 47 3c ; 0xf8535
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf8539
+ mov word [es:bx+03ah], ax ; 26 89 47 3a ; 0xf853c
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf8540
+ mov word [es:bx+038h], ax ; 26 89 47 38 ; 0xf8543
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf8547
+ mov word [es:bx+036h], ax ; 26 89 47 36 ; 0xf854a
+ mov al, byte [es:di+001e2h] ; 26 8a 85 e2 01 ; 0xf854e scsi.c:567
+ mov ah, byte [bp-00ch] ; 8a 66 f4 ; 0xf8553 scsi.c:568
+ add ah, 008h ; 80 c4 08 ; 0xf8556
+ movzx bx, al ; 0f b6 d8 ; 0xf8559
+ add bx, di ; 01 fb ; 0xf855c
+ mov byte [es:bx+001e3h], ah ; 26 88 a7 e3 01 ; 0xf855e
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf8563 scsi.c:569
+ mov byte [es:di+001e2h], al ; 26 88 85 e2 01 ; 0xf8565 scsi.c:570
+ mov bx, strict word 00075h ; bb 75 00 ; 0xf856a scsi.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf856d
+ mov es, ax ; 8e c0 ; 0xf8570
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf8572
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf8575 scsi.c:574
+ mov byte [es:bx], al ; 26 88 07 ; 0xf8577 scsi.c:43
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf857a scsi.c:577
+ jmp near 0860dh ; e9 8d 00 ; 0xf857d scsi.c:579
+ mov bx, 00db2h ; bb b2 0d ; 0xf8580 scsi.c:591
+ mov cx, ds ; 8c d9 ; 0xf8583
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf8585
+ call 019d3h ; e8 48 94 ; 0xf8588
+ push word [bp-01ch] ; ff 76 e4 ; 0xf858b
+ movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xf858e
+ push ax ; 50 ; 0xf8592
+ push 00c58h ; 68 58 0c ; 0xf8593
+ push strict byte 00004h ; 6a 04 ; 0xf8596
+ call 01a14h ; e8 79 94 ; 0xf8598
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf859b
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf859e scsi.c:594
+ add AL, strict byte 008h ; 04 08 ; 0xf85a1
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf85a3
+ test byte [bp-00245h], 080h ; f6 86 bb fd 80 ; 0xf85a6 scsi.c:596
+ db 00fh, 095h, 0c0h
+ ; setne al ; 0f 95 c0 ; 0xf85ab
+ xor ah, ah ; 30 e4 ; 0xf85ae
+ mov dx, ax ; 89 c2 ; 0xf85b0
+ movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xf85b2 scsi.c:598
+ sal ax, 002h ; c1 e0 02 ; 0xf85b6
+ mov es, [bp-022h] ; 8e 46 de ; 0xf85b9
+ mov bx, di ; 89 fb ; 0xf85bc
+ add bx, ax ; 01 c3 ; 0xf85be
+ mov ax, word [bp-00248h] ; 8b 86 b8 fd ; 0xf85c0
+ mov word [es:bx+0021ch], ax ; 26 89 87 1c 02 ; 0xf85c4
+ mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xf85c9 scsi.c:599
+ mov byte [es:bx+0021eh], al ; 26 88 87 1e 02 ; 0xf85cc
+ movzx bx, byte [bp-00eh] ; 0f b6 5e f2 ; 0xf85d1 scsi.c:600
+ imul bx, bx, strict byte 0001ch ; 6b db 1c ; 0xf85d5
+ add bx, di ; 01 fb ; 0xf85d8
+ mov word [es:bx+022h], 00504h ; 26 c7 47 22 04 05 ; 0xf85da
+ mov byte [es:bx+024h], dl ; 26 88 57 24 ; 0xf85e0 scsi.c:602
+ mov word [es:bx+028h], 00800h ; 26 c7 47 28 00 08 ; 0xf85e4 scsi.c:603
+ mov byte [es:bx+027h], dh ; 26 88 77 27 ; 0xf85ea scsi.c:604
+ mov al, byte [es:di+001f3h] ; 26 8a 85 f3 01 ; 0xf85ee scsi.c:607
+ mov ah, byte [bp-00ch] ; 8a 66 f4 ; 0xf85f3 scsi.c:608
+ add ah, 008h ; 80 c4 08 ; 0xf85f6
+ movzx bx, al ; 0f b6 d8 ; 0xf85f9
+ add bx, di ; 01 fb ; 0xf85fc
+ mov byte [es:bx+001f4h], ah ; 26 88 a7 f4 01 ; 0xf85fe
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf8603 scsi.c:609
+ mov byte [es:di+001f3h], al ; 26 88 85 f3 01 ; 0xf8605 scsi.c:610
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf860a scsi.c:612
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf860d scsi.c:617
+ mov es, [bp-022h] ; 8e 46 de ; 0xf8610
+ mov byte [es:di+0022ch], al ; 26 88 85 2c 02 ; 0xf8613
+ inc word [bp-01ch] ; ff 46 e4 ; 0xf8618 scsi.c:618
+ cmp word [bp-01ch], strict byte 00010h ; 83 7e e4 10 ; 0xf861b
+ jnl short 08695h ; 7d 74 ; 0xf861f
+ mov byte [bp-046h], 012h ; c6 46 ba 12 ; 0xf8621
+ xor al, al ; 30 c0 ; 0xf8625
+ mov byte [bp-045h], al ; 88 46 bb ; 0xf8627
+ mov byte [bp-044h], al ; 88 46 bc ; 0xf862a
+ mov byte [bp-043h], al ; 88 46 bd ; 0xf862d
+ mov byte [bp-042h], 005h ; c6 46 be 05 ; 0xf8630
+ mov byte [bp-041h], al ; 88 46 bf ; 0xf8634
+ push dword 000000005h ; 66 6a 05 ; 0xf8637
+ lea dx, [bp-00246h] ; 8d 96 ba fd ; 0xf863a
+ push SS ; 16 ; 0xf863e
+ push dx ; 52 ; 0xf863f
+ push strict byte 00006h ; 6a 06 ; 0xf8640
+ movzx dx, byte [bp-01ch] ; 0f b6 56 e4 ; 0xf8642
+ mov cx, ss ; 8c d1 ; 0xf8646
+ lea bx, [bp-046h] ; 8d 5e ba ; 0xf8648
+ mov ax, word [bp-00248h] ; 8b 86 b8 fd ; 0xf864b
+ call 07d53h ; e8 01 f7 ; 0xf864f
+ test al, al ; 84 c0 ; 0xf8652
+ je short 08664h ; 74 0e ; 0xf8654
+ push 00ba4h ; 68 a4 0b ; 0xf8656
+ push 00bc4h ; 68 c4 0b ; 0xf8659
+ push strict byte 00007h ; 6a 07 ; 0xf865c
+ call 01a14h ; e8 b3 93 ; 0xf865e
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf8661
+ mov es, [bp-022h] ; 8e 46 de ; 0xf8664
+ mov al, byte [es:di+0022ch] ; 26 8a 85 2c 02 ; 0xf8667
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf866c
+ test byte [bp-00246h], 0e0h ; f6 86 ba fd e0 ; 0xf866f
+ jne short 0867fh ; 75 09 ; 0xf8674
+ test byte [bp-00246h], 01fh ; f6 86 ba fd 1f ; 0xf8676
+ je near 08241h ; 0f 84 c2 fb ; 0xf867b
+ test byte [bp-00246h], 0e0h ; f6 86 ba fd e0 ; 0xf867f
+ jne short 0860dh ; 75 87 ; 0xf8684
+ mov al, byte [bp-00246h] ; 8a 86 ba fd ; 0xf8686
+ and AL, strict byte 01fh ; 24 1f ; 0xf868a
+ cmp AL, strict byte 005h ; 3c 05 ; 0xf868c
+ je near 08580h ; 0f 84 ee fe ; 0xf868e
+ jmp near 0860dh ; e9 78 ff ; 0xf8692
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf8695 scsi.c:619
+ pop di ; 5f ; 0xf8698
+ pop si ; 5e ; 0xf8699
+ pop dx ; 5a ; 0xf869a
+ pop cx ; 59 ; 0xf869b
+ pop bx ; 5b ; 0xf869c
+ pop bp ; 5d ; 0xf869d
+ retn ; c3 ; 0xf869e
+ ; disGetNextSymbol 0xf869f LB 0x19a6 -> off=0x0 cb=000000000000002d uValue=00000000000f709f 'scsi_pci_init'
+scsi_pci_init: ; 0xf869f LB 0x2d
+ push bp ; 55 ; 0xf869f scsi.c:621
+ mov bp, sp ; 89 e5 ; 0xf86a0
+ push bx ; 53 ; 0xf86a2
+ push cx ; 51 ; 0xf86a3
+ push si ; 56 ; 0xf86a4
+ call 09d7ah ; e8 d2 16 ; 0xf86a5 scsi.c:625
+ mov dx, ax ; 89 c2 ; 0xf86a8
+ cmp ax, strict word 0ffffh ; 3d ff ff ; 0xf86aa scsi.c:626
+ je short 086c4h ; 74 15 ; 0xf86ad
+ movzx si, dl ; 0f b6 f2 ; 0xf86af scsi.c:633
+ mov ax, dx ; 89 d0 ; 0xf86b2
+ shr ax, 008h ; c1 e8 08 ; 0xf86b4
+ xor ah, ah ; 30 e4 ; 0xf86b7
+ mov cx, strict word 00007h ; b9 07 00 ; 0xf86b9
+ mov bx, strict word 00004h ; bb 04 00 ; 0xf86bc
+ mov dx, si ; 89 f2 ; 0xf86bf
+ call 09e0ch ; e8 48 17 ; 0xf86c1
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf86c4 scsi.c:634
+ pop si ; 5e ; 0xf86c7
+ pop cx ; 59 ; 0xf86c8
+ pop bx ; 5b ; 0xf86c9
+ pop bp ; 5d ; 0xf86ca
+ retn ; c3 ; 0xf86cb
+ ; disGetNextSymbol 0xf86cc LB 0x1979 -> off=0x0 cb=0000000000000081 uValue=00000000000f70cc 'scsi_init'
+scsi_init: ; 0xf86cc LB 0x81
+ push bp ; 55 ; 0xf86cc scsi.c:639
+ mov bp, sp ; 89 e5 ; 0xf86cd
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf86cf scsi.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf86d2
+ mov es, ax ; 8e c0 ; 0xf86d5
+ mov es, [es:bx] ; 26 8e 07 ; 0xf86d7
+ mov bx, 00122h ; bb 22 01 ; 0xf86da scsi.c:49
+ mov byte [es:bx+0022ch], 000h ; 26 c6 87 2c 02 00 ; 0xf86dd scsi.c:646
+ mov AL, strict byte 055h ; b0 55 ; 0xf86e3 scsi.c:651
+ mov dx, 00432h ; ba 32 04 ; 0xf86e5
+ out DX, AL ; ee ; 0xf86e8
+ in AL, DX ; ec ; 0xf86e9 scsi.c:652
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf86ea
+ cmp AL, strict byte 055h ; 3c 55 ; 0xf86ec scsi.c:654
+ jne short 08705h ; 75 15 ; 0xf86ee
+ xor al, al ; 30 c0 ; 0xf86f0 scsi.c:658
+ mov dx, 00433h ; ba 33 04 ; 0xf86f2
+ out DX, AL ; ee ; 0xf86f5
+ mov ax, 00430h ; b8 30 04 ; 0xf86f6 scsi.c:659
+ call 0821bh ; e8 1f fb ; 0xf86f9
+ mov dx, 01040h ; ba 40 10 ; 0xf86fc scsi.c:660
+ mov ax, 0104bh ; b8 4b 10 ; 0xf86ff
+ call 0869fh ; e8 9a ff ; 0xf8702
+ mov AL, strict byte 055h ; b0 55 ; 0xf8705 scsi.c:668
+ mov dx, 00436h ; ba 36 04 ; 0xf8707
+ out DX, AL ; ee ; 0xf870a
+ in AL, DX ; ec ; 0xf870b scsi.c:669
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf870c
+ cmp AL, strict byte 055h ; 3c 55 ; 0xf870e scsi.c:671
+ jne short 08727h ; 75 15 ; 0xf8710
+ xor al, al ; 30 c0 ; 0xf8712 scsi.c:675
+ mov dx, 00437h ; ba 37 04 ; 0xf8714
+ out DX, AL ; ee ; 0xf8717
+ mov ax, 00434h ; b8 34 04 ; 0xf8718 scsi.c:676
+ call 0821bh ; e8 fd fa ; 0xf871b
+ mov dx, strict word 00030h ; ba 30 00 ; 0xf871e scsi.c:677
+ mov ax, 01000h ; b8 00 10 ; 0xf8721
+ call 0869fh ; e8 78 ff ; 0xf8724
+ mov AL, strict byte 055h ; b0 55 ; 0xf8727 scsi.c:685
+ mov dx, 0043ah ; ba 3a 04 ; 0xf8729
+ out DX, AL ; ee ; 0xf872c
+ in AL, DX ; ec ; 0xf872d scsi.c:686
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf872e
+ cmp AL, strict byte 055h ; 3c 55 ; 0xf8730 scsi.c:688
+ jne short 08749h ; 75 15 ; 0xf8732
+ xor al, al ; 30 c0 ; 0xf8734 scsi.c:692
+ mov dx, 0043bh ; ba 3b 04 ; 0xf8736
+ out DX, AL ; ee ; 0xf8739
+ mov ax, 00438h ; b8 38 04 ; 0xf873a scsi.c:693
+ call 0821bh ; e8 db fa ; 0xf873d
+ mov dx, strict word 00054h ; ba 54 00 ; 0xf8740 scsi.c:694
+ mov ax, 01000h ; b8 00 10 ; 0xf8743
+ call 0869fh ; e8 56 ff ; 0xf8746
+ mov sp, bp ; 89 ec ; 0xf8749 scsi.c:700
+ pop bp ; 5d ; 0xf874b
+ retn ; c3 ; 0xf874c
+ ; disGetNextSymbol 0xf874d LB 0x18f8 -> off=0x0 cb=000000000000001b uValue=00000000000f714d 'ahci_ctrl_extract_bits'
+ahci_ctrl_extract_bits: ; 0xf874d LB 0x1b
+ push si ; 56 ; 0xf874d ahci.c:279
+ push bp ; 55 ; 0xf874e
+ mov bp, sp ; 89 e5 ; 0xf874f
+ mov si, bx ; 89 de ; 0xf8751
+ and ax, bx ; 21 d8 ; 0xf8753 ahci.c:281
+ and dx, cx ; 21 ca ; 0xf8755
+ movzx cx, byte [bp+006h] ; 0f b6 4e 06 ; 0xf8757
+ jcxz 08763h ; e3 06 ; 0xf875b
+ shr dx, 1 ; d1 ea ; 0xf875d
+ rcr ax, 1 ; d1 d8 ; 0xf875f
+ loop 0875dh ; e2 fa ; 0xf8761
+ pop bp ; 5d ; 0xf8763 ahci.c:282
+ pop si ; 5e ; 0xf8764
+ retn 00002h ; c2 02 00 ; 0xf8765
+ ; disGetNextSymbol 0xf8768 LB 0x18dd -> off=0x0 cb=000000000000001e uValue=00000000000f7168 'ahci_addr_to_phys'
+ahci_addr_to_phys: ; 0xf8768 LB 0x1e
+ push bx ; 53 ; 0xf8768 ahci.c:287
+ push cx ; 51 ; 0xf8769
+ push bp ; 55 ; 0xf876a
+ mov bp, sp ; 89 e5 ; 0xf876b
+ mov bx, ax ; 89 c3 ; 0xf876d
+ mov ax, dx ; 89 d0 ; 0xf876f
+ xor dx, dx ; 31 d2 ; 0xf8771 ahci.c:289
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf8773
+ sal ax, 1 ; d1 e0 ; 0xf8776
+ rcl dx, 1 ; d1 d2 ; 0xf8778
+ loop 08776h ; e2 fa ; 0xf877a
+ xor cx, cx ; 31 c9 ; 0xf877c
+ add ax, bx ; 01 d8 ; 0xf877e
+ adc dx, cx ; 11 ca ; 0xf8780
+ pop bp ; 5d ; 0xf8782 ahci.c:290
+ pop cx ; 59 ; 0xf8783
+ pop bx ; 5b ; 0xf8784
+ retn ; c3 ; 0xf8785
+ ; disGetNextSymbol 0xf8786 LB 0x18bf -> off=0x0 cb=000000000000014b uValue=00000000000f7186 'ahci_port_cmd_sync'
+ahci_port_cmd_sync: ; 0xf8786 LB 0x14b
+ push bp ; 55 ; 0xf8786 ahci.c:295
+ mov bp, sp ; 89 e5 ; 0xf8787
+ push cx ; 51 ; 0xf8789
+ push si ; 56 ; 0xf878a
+ push di ; 57 ; 0xf878b
+ push ax ; 50 ; 0xf878c
+ mov si, ax ; 89 c6 ; 0xf878d
+ mov cx, dx ; 89 d1 ; 0xf878f
+ mov al, bl ; 88 d8 ; 0xf8791
+ mov es, dx ; 8e c2 ; 0xf8793 ahci.c:300
+ mov ah, byte [es:si+00262h] ; 26 8a a4 62 02 ; 0xf8795
+ mov byte [bp-008h], ah ; 88 66 f8 ; 0xf879a
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf879d ahci.c:301
+ cmp ah, 0ffh ; 80 fc ff ; 0xf87a2 ahci.c:303
+ je near 088c9h ; 0f 84 20 01 ; 0xf87a5
+ movzx dx, byte [es:si+00263h] ; 26 0f b6 94 63 02 ; 0xf87a9 ahci.c:306
+ xor di, di ; 31 ff ; 0xf87af
+ or di, 00080h ; 81 cf 80 00 ; 0xf87b1
+ xor ah, ah ; 30 e4 ; 0xf87b5
+ or di, ax ; 09 c7 ; 0xf87b7
+ mov word [es:si], di ; 26 89 3c ; 0xf87b9
+ mov word [es:si+002h], dx ; 26 89 54 02 ; 0xf87bc
+ db 066h, 026h, 0c7h, 044h, 004h, 000h, 000h, 000h, 000h
+ ; mov dword [es:si+004h], strict dword 000000000h ; 66 26 c7 44 04 00 00 00 00; 0xf87c0 ahci.c:307
+ lea ax, [si+00080h] ; 8d 84 80 00 ; 0xf87c9 ahci.c:308
+ mov dx, cx ; 89 ca ; 0xf87cd
+ call 08768h ; e8 96 ff ; 0xf87cf
+ mov es, cx ; 8e c1 ; 0xf87d2
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf87d4
+ mov word [es:si+00ah], dx ; 26 89 54 0a ; 0xf87d8
+ movzx di, byte [bp-008h] ; 0f b6 7e f8 ; 0xf87dc ahci.c:311
+ sal di, 007h ; c1 e7 07 ; 0xf87e0
+ lea ax, [di+00118h] ; 8d 85 18 01 ; 0xf87e3
+ xor cx, cx ; 31 c9 ; 0xf87e7 ahci.c:252
+ mov dx, bx ; 89 da ; 0xf87e9
+ xchg cx, ax ; 91 ; 0xf87eb
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf87ec
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf87f0
+ out DX, eax ; 66 ef ; 0xf87f2
+ lea si, [bx+004h] ; 8d 77 04 ; 0xf87f4 ahci.c:253
+ mov dx, si ; 89 f2 ; 0xf87f7
+ in eax, DX ; 66 ed ; 0xf87f9
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf87fb
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf87fd
+ xchg dx, ax ; 92 ; 0xf8801
+ or AL, strict byte 011h ; 0c 11 ; 0xf8802
+ mov cx, dx ; 89 d1 ; 0xf8804
+ mov dx, si ; 89 f2 ; 0xf8806
+ xchg cx, ax ; 91 ; 0xf8808
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8809
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf880d
+ out DX, eax ; 66 ef ; 0xf880f
+ lea ax, [di+00138h] ; 8d 85 38 01 ; 0xf8811 ahci.c:315
+ cwd ; 99 ; 0xf8815
+ mov cx, dx ; 89 d1 ; 0xf8816
+ mov dx, bx ; 89 da ; 0xf8818
+ xchg cx, ax ; 91 ; 0xf881a
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf881b
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf881f
+ out DX, eax ; 66 ef ; 0xf8821
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf8823
+ xor cx, cx ; 31 c9 ; 0xf8826
+ mov dx, si ; 89 f2 ; 0xf8828
+ xchg cx, ax ; 91 ; 0xf882a
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf882b
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf882f
+ out DX, eax ; 66 ef ; 0xf8831
+ movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xf8833 ahci.c:319
+ sal ax, 007h ; c1 e0 07 ; 0xf8837
+ add ax, 00110h ; 05 10 01 ; 0xf883a
+ xor cx, cx ; 31 c9 ; 0xf883d ahci.c:271
+ mov dx, bx ; 89 da ; 0xf883f
+ xchg cx, ax ; 91 ; 0xf8841
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8842
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8846
+ out DX, eax ; 66 ef ; 0xf8848
+ lea dx, [bx+004h] ; 8d 57 04 ; 0xf884a ahci.c:272
+ in eax, DX ; 66 ed ; 0xf884d
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf884f
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8851
+ xchg dx, ax ; 92 ; 0xf8855
+ test dh, 040h ; f6 c6 40 ; 0xf8856
+ jne short 0885fh ; 75 04 ; 0xf8859
+ test AL, strict byte 001h ; a8 01 ; 0xf885b
+ je short 08863h ; 74 04 ; 0xf885d
+ mov AL, strict byte 001h ; b0 01 ; 0xf885f
+ jmp short 08865h ; eb 02 ; 0xf8861
+ xor al, al ; 30 c0 ; 0xf8863
+ test al, al ; 84 c0 ; 0xf8865 ahci.c:273
+ je short 08833h ; 74 ca ; 0xf8867
+ movzx di, byte [bp-008h] ; 0f b6 7e f8 ; 0xf8869 ahci.c:325
+ sal di, 007h ; c1 e7 07 ; 0xf886d
+ lea ax, [di+00110h] ; 8d 85 10 01 ; 0xf8870
+ xor cx, cx ; 31 c9 ; 0xf8874 ahci.c:252
+ mov dx, bx ; 89 da ; 0xf8876
+ xchg cx, ax ; 91 ; 0xf8878
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8879
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf887d
+ out DX, eax ; 66 ef ; 0xf887f
+ lea si, [bx+004h] ; 8d 77 04 ; 0xf8881 ahci.c:253
+ mov dx, si ; 89 f2 ; 0xf8884
+ in eax, DX ; 66 ed ; 0xf8886
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8888
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf888a
+ xchg dx, ax ; 92 ; 0xf888e
+ or AL, strict byte 001h ; 0c 01 ; 0xf888f
+ mov cx, dx ; 89 d1 ; 0xf8891
+ mov dx, si ; 89 f2 ; 0xf8893
+ xchg cx, ax ; 91 ; 0xf8895
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8896
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf889a
+ out DX, eax ; 66 ef ; 0xf889c
+ lea ax, [di+00118h] ; 8d 85 18 01 ; 0xf889e ahci.c:329
+ xor cx, cx ; 31 c9 ; 0xf88a2 ahci.c:261
+ mov dx, bx ; 89 da ; 0xf88a4
+ xchg cx, ax ; 91 ; 0xf88a6
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf88a7
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf88ab
+ out DX, eax ; 66 ef ; 0xf88ad
+ mov dx, si ; 89 f2 ; 0xf88af ahci.c:262
+ in eax, DX ; 66 ed ; 0xf88b1
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf88b3
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf88b5
+ xchg dx, ax ; 92 ; 0xf88b9
+ and AL, strict byte 0feh ; 24 fe ; 0xf88ba
+ mov cx, dx ; 89 d1 ; 0xf88bc
+ mov dx, si ; 89 f2 ; 0xf88be
+ xchg cx, ax ; 91 ; 0xf88c0
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf88c1
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf88c5
+ out DX, eax ; 66 ef ; 0xf88c7
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf88c9 ahci.c:335
+ pop di ; 5f ; 0xf88cc
+ pop si ; 5e ; 0xf88cd
+ pop cx ; 59 ; 0xf88ce
+ pop bp ; 5d ; 0xf88cf
+ retn ; c3 ; 0xf88d0
+ ; disGetNextSymbol 0xf88d1 LB 0x1774 -> off=0x0 cb=0000000000000262 uValue=00000000000f72d1 'ahci_cmd_data'
+ahci_cmd_data: ; 0xf88d1 LB 0x262
+ push bp ; 55 ; 0xf88d1 ahci.c:340
+ mov bp, sp ; 89 e5 ; 0xf88d2
+ push cx ; 51 ; 0xf88d4
+ push si ; 56 ; 0xf88d5
+ push di ; 57 ; 0xf88d6
+ sub sp, strict byte 0000ch ; 83 ec 0c ; 0xf88d7
+ push ax ; 50 ; 0xf88da
+ push dx ; 52 ; 0xf88db
+ mov byte [bp-008h], bl ; 88 5e f8 ; 0xf88dc
+ xor di, di ; 31 ff ; 0xf88df ahci.c:342
+ mov es, dx ; 8e c2 ; 0xf88e1
+ mov bx, ax ; 89 c3 ; 0xf88e3
+ mov ax, word [es:bx+00232h] ; 26 8b 87 32 02 ; 0xf88e5
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf88ea
+ mov word [bp-00eh], di ; 89 7e f2 ; 0xf88ed
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf88f0
+ mov ax, word [es:bx+00eh] ; 26 8b 47 0e ; 0xf88f3 ahci.c:343
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf88f7
+ mov ax, word [es:bx+010h] ; 26 8b 47 10 ; 0xf88fa ahci.c:344
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf88fe
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf8901 ahci.c:347
+ xor bx, bx ; 31 db ; 0xf8904
+ mov ax, 00080h ; b8 80 00 ; 0xf8906
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8909
+ call 09fb0h ; e8 a1 16 ; 0xf890c
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf890f ahci.c:350
+ mov word [es:di+00080h], 08027h ; 26 c7 85 80 00 27 80 ; 0xf8912
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8919 ahci.c:352
+ mov byte [es:di+00082h], al ; 26 88 85 82 00 ; 0xf891c
+ mov byte [es:di+00083h], 000h ; 26 c6 85 83 00 00 ; 0xf8921 ahci.c:353
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8927 ahci.c:355
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf892a
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf892d
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8930
+ mov byte [es:di+00084h], al ; 26 88 85 84 00 ; 0xf8933
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8938 ahci.c:356
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf893b
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf893f
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf8943
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf8946
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf894a
+ mov si, strict word 00008h ; be 08 00 ; 0xf894d
+ call 09f90h ; e8 3d 16 ; 0xf8950
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8953
+ mov byte [es:di+00085h], dl ; 26 88 95 85 00 ; 0xf8956
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf895b ahci.c:357
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf895e
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf8961
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf8965
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf8969
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf896c
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf8970
+ mov si, strict word 00010h ; be 10 00 ; 0xf8973
+ call 09f90h ; e8 17 16 ; 0xf8976
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8979
+ mov byte [es:di+00086h], dl ; 26 88 95 86 00 ; 0xf897c
+ mov byte [es:di+00087h], 040h ; 26 c6 85 87 00 40 ; 0xf8981 ahci.c:358
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8987 ahci.c:360
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf898a
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf898d
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf8991
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf8995
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf8998
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf899c
+ mov si, strict word 00018h ; be 18 00 ; 0xf899f
+ call 09f90h ; e8 eb 15 ; 0xf89a2
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf89a5
+ mov byte [es:di+00088h], dl ; 26 88 95 88 00 ; 0xf89a8
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf89ad ahci.c:361
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf89b0
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf89b3
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf89b7
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf89bb
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf89be
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf89c2
+ mov si, strict word 00020h ; be 20 00 ; 0xf89c5
+ call 09f90h ; e8 c5 15 ; 0xf89c8
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf89cb
+ mov byte [es:di+00089h], dl ; 26 88 95 89 00 ; 0xf89ce
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf89d3 ahci.c:362
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf89d6
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf89d9
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf89dd
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf89e1
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf89e4
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf89e8
+ mov si, strict word 00028h ; be 28 00 ; 0xf89eb
+ call 09f90h ; e8 9f 15 ; 0xf89ee
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf89f1
+ mov byte [es:di+0008ah], dl ; 26 88 95 8a 00 ; 0xf89f4
+ mov byte [es:di+0008bh], 000h ; 26 c6 85 8b 00 00 ; 0xf89f9 ahci.c:363
+ mov al, byte [bp-012h] ; 8a 46 ee ; 0xf89ff ahci.c:365
+ mov byte [es:di+0008ch], al ; 26 88 85 8c 00 ; 0xf8a02
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf8a07 ahci.c:366
+ shr ax, 008h ; c1 e8 08 ; 0xf8a0a
+ mov byte [es:di+0008dh], al ; 26 88 85 8d 00 ; 0xf8a0d
+ mov word [es:di+00276h], strict word 00010h ; 26 c7 85 76 02 10 00 ; 0xf8a12 ahci.c:369
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf8a19 ahci.c:372
+ xor dx, dx ; 31 d2 ; 0xf8a1c
+ mov bx, word [bp-010h] ; 8b 5e f0 ; 0xf8a1e
+ xor cx, cx ; 31 c9 ; 0xf8a21
+ call 09f10h ; e8 ea 14 ; 0xf8a23
+ push dx ; 52 ; 0xf8a26
+ push ax ; 50 ; 0xf8a27
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8a28
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf8a2b
+ mov bx, word [es:bx+008h] ; 26 8b 5f 08 ; 0xf8a2e
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf8a32
+ mov cx, word [es:si+00ah] ; 26 8b 4c 0a ; 0xf8a35
+ mov ax, 0026ah ; b8 6a 02 ; 0xf8a39
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8a3c
+ call 09e63h ; e8 21 14 ; 0xf8a3f
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a42 ahci.c:375
+ mov ax, word [es:di+0027eh] ; 26 8b 85 7e 02 ; 0xf8a45
+ add ax, strict word 0ffffh ; 05 ff ff ; 0xf8a4a
+ mov dx, word [es:di+00280h] ; 26 8b 95 80 02 ; 0xf8a4d
+ adc dx, strict byte 0ffffh ; 83 d2 ff ; 0xf8a52
+ movzx bx, byte [es:di+00263h] ; 26 0f b6 9d 63 02 ; 0xf8a55
+ sal bx, 004h ; c1 e3 04 ; 0xf8a5b
+ mov word [es:bx+0010ch], ax ; 26 89 87 0c 01 ; 0xf8a5e
+ mov word [es:bx+0010eh], dx ; 26 89 97 0e 01 ; 0xf8a63
+ movzx bx, byte [es:di+00263h] ; 26 0f b6 9d 63 02 ; 0xf8a68 ahci.c:376
+ sal bx, 004h ; c1 e3 04 ; 0xf8a6e
+ mov ax, word [es:di+0027ah] ; 26 8b 85 7a 02 ; 0xf8a71
+ mov dx, word [es:di+0027ch] ; 26 8b 95 7c 02 ; 0xf8a76
+ mov word [es:bx+00100h], ax ; 26 89 87 00 01 ; 0xf8a7b
+ mov word [es:bx+00102h], dx ; 26 89 97 02 01 ; 0xf8a80
+ inc byte [es:di+00263h] ; 26 fe 85 63 02 ; 0xf8a85 ahci.c:377
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8a8a ahci.c:379
+ mov bx, si ; 89 f3 ; 0xf8a8d
+ mov ax, word [es:bx+020h] ; 26 8b 47 20 ; 0xf8a8f
+ test ax, ax ; 85 c0 ; 0xf8a93
+ je short 08ad0h ; 74 39 ; 0xf8a95
+ dec ax ; 48 ; 0xf8a97 ahci.c:380
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a98
+ movzx bx, byte [es:di+00263h] ; 26 0f b6 9d 63 02 ; 0xf8a9b
+ sal bx, 004h ; c1 e3 04 ; 0xf8aa1
+ mov word [es:bx+0010ch], ax ; 26 89 87 0c 01 ; 0xf8aa4
+ mov word [es:bx+0010eh], di ; 26 89 bf 0e 01 ; 0xf8aa9
+ movzx bx, byte [es:di+00263h] ; 26 0f b6 9d 63 02 ; 0xf8aae ahci.c:381
+ sal bx, 004h ; c1 e3 04 ; 0xf8ab4
+ mov dx, word [es:di+00264h] ; 26 8b 95 64 02 ; 0xf8ab7
+ mov ax, word [es:di+00266h] ; 26 8b 85 66 02 ; 0xf8abc
+ mov word [es:bx+00100h], dx ; 26 89 97 00 01 ; 0xf8ac1
+ mov word [es:bx+00102h], ax ; 26 89 87 02 01 ; 0xf8ac6
+ inc byte [es:di+00263h] ; 26 fe 85 63 02 ; 0xf8acb ahci.c:382
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8ad0 ahci.c:397
+ cmp AL, strict byte 035h ; 3c 35 ; 0xf8ad3
+ jne short 08addh ; 75 06 ; 0xf8ad5
+ mov byte [bp-008h], 040h ; c6 46 f8 40 ; 0xf8ad7 ahci.c:398
+ jmp short 08af4h ; eb 17 ; 0xf8adb ahci.c:399
+ cmp AL, strict byte 0a0h ; 3c a0 ; 0xf8add
+ jne short 08af0h ; 75 0f ; 0xf8adf
+ or byte [bp-008h], 020h ; 80 4e f8 20 ; 0xf8ae1 ahci.c:400
+ les bx, [bp-00eh] ; c4 5e f2 ; 0xf8ae5 ahci.c:401
+ or byte [es:bx+00083h], 001h ; 26 80 8f 83 00 01 ; 0xf8ae8
+ jmp short 08af4h ; eb 04 ; 0xf8aee ahci.c:402
+ mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xf8af0 ahci.c:403
+ or byte [bp-008h], 005h ; 80 4e f8 05 ; 0xf8af4 ahci.c:405
+ movzx bx, byte [bp-008h] ; 0f b6 5e f8 ; 0xf8af8 ahci.c:407
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf8afc
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf8aff
+ call 08786h ; e8 81 fc ; 0xf8b02
+ mov cx, word [bp-00ch] ; 8b 4e f4 ; 0xf8b05 ahci.c:410
+ mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xf8b08
+ add bx, 00240h ; 81 c3 40 02 ; 0xf8b0b
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf8b0f ahci.c:414
+ add ax, 0026ah ; 05 6a 02 ; 0xf8b12
+ mov dx, cx ; 89 ca ; 0xf8b15
+ call 09edch ; e8 c2 13 ; 0xf8b17
+ mov es, cx ; 8e c1 ; 0xf8b1a ahci.c:415
+ mov al, byte [es:bx+003h] ; 26 8a 47 03 ; 0xf8b1c
+ test al, al ; 84 c0 ; 0xf8b20
+ je short 08b29h ; 74 05 ; 0xf8b22
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf8b24
+ jmp short 08b2bh ; eb 02 ; 0xf8b27
+ xor ah, ah ; 30 e4 ; 0xf8b29
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf8b2b ahci.c:416
+ pop di ; 5f ; 0xf8b2e
+ pop si ; 5e ; 0xf8b2f
+ pop cx ; 59 ; 0xf8b30
+ pop bp ; 5d ; 0xf8b31
+ retn ; c3 ; 0xf8b32
+ ; disGetNextSymbol 0xf8b33 LB 0x1512 -> off=0x0 cb=000000000000017f uValue=00000000000f7533 'ahci_port_deinit_current'
+ahci_port_deinit_current: ; 0xf8b33 LB 0x17f
+ push bp ; 55 ; 0xf8b33 ahci.c:421
+ mov bp, sp ; 89 e5 ; 0xf8b34
+ push bx ; 53 ; 0xf8b36
+ push cx ; 51 ; 0xf8b37
+ push si ; 56 ; 0xf8b38
+ push di ; 57 ; 0xf8b39
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf8b3a
+ mov di, ax ; 89 c7 ; 0xf8b3d
+ mov word [bp-00ch], dx ; 89 56 f4 ; 0xf8b3f
+ mov es, dx ; 8e c2 ; 0xf8b42 ahci.c:426
+ mov si, word [es:di+00260h] ; 26 8b b5 60 02 ; 0xf8b44
+ mov al, byte [es:di+00262h] ; 26 8a 85 62 02 ; 0xf8b49 ahci.c:427
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf8b4e
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xf8b51 ahci.c:429
+ je near 08ca9h ; 0f 84 52 01 ; 0xf8b53
+ movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xf8b57 ahci.c:432
+ sal ax, 007h ; c1 e0 07 ; 0xf8b5b
+ add ax, 00118h ; 05 18 01 ; 0xf8b5e
+ xor cx, cx ; 31 c9 ; 0xf8b61 ahci.c:261
+ mov dx, si ; 89 f2 ; 0xf8b63
+ xchg cx, ax ; 91 ; 0xf8b65
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8b66
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8b6a
+ out DX, eax ; 66 ef ; 0xf8b6c
+ lea bx, [si+004h] ; 8d 5c 04 ; 0xf8b6e ahci.c:262
+ mov dx, bx ; 89 da ; 0xf8b71
+ in eax, DX ; 66 ed ; 0xf8b73
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8b75
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8b77
+ xchg dx, ax ; 92 ; 0xf8b7b
+ and AL, strict byte 0eeh ; 24 ee ; 0xf8b7c
+ mov cx, dx ; 89 d1 ; 0xf8b7e
+ mov dx, bx ; 89 da ; 0xf8b80
+ xchg cx, ax ; 91 ; 0xf8b82
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8b83
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8b87
+ out DX, eax ; 66 ef ; 0xf8b89
+ movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xf8b8b ahci.c:435
+ sal ax, 007h ; c1 e0 07 ; 0xf8b8f
+ add ax, 00118h ; 05 18 01 ; 0xf8b92
+ xor cx, cx ; 31 c9 ; 0xf8b95 ahci.c:271
+ mov dx, si ; 89 f2 ; 0xf8b97
+ xchg cx, ax ; 91 ; 0xf8b99
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8b9a
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8b9e
+ out DX, eax ; 66 ef ; 0xf8ba0
+ lea dx, [si+004h] ; 8d 54 04 ; 0xf8ba2 ahci.c:272
+ in eax, DX ; 66 ed ; 0xf8ba5
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8ba7
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8ba9
+ xchg dx, ax ; 92 ; 0xf8bad
+ test ax, 0c011h ; a9 11 c0 ; 0xf8bae
+ je short 08bb7h ; 74 04 ; 0xf8bb1
+ mov AL, strict byte 001h ; b0 01 ; 0xf8bb3
+ jmp short 08bb9h ; eb 02 ; 0xf8bb5
+ xor al, al ; 30 c0 ; 0xf8bb7
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf8bb9 ahci.c:273
+ je short 08b8bh ; 74 ce ; 0xf8bbb
+ mov cx, strict word 00020h ; b9 20 00 ; 0xf8bbd ahci.c:446
+ xor bx, bx ; 31 db ; 0xf8bc0
+ mov ax, di ; 89 f8 ; 0xf8bc2
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf8bc4
+ call 09fb0h ; e8 e6 13 ; 0xf8bc7
+ lea ax, [di+00080h] ; 8d 85 80 00 ; 0xf8bca ahci.c:447
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf8bce
+ xor bx, bx ; 31 db ; 0xf8bd1
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf8bd3
+ call 09fb0h ; e8 d7 13 ; 0xf8bd6
+ lea ax, [di+00200h] ; 8d 85 00 02 ; 0xf8bd9 ahci.c:448
+ mov cx, strict word 00060h ; b9 60 00 ; 0xf8bdd
+ xor bx, bx ; 31 db ; 0xf8be0
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf8be2
+ call 09fb0h ; e8 c8 13 ; 0xf8be5
+ movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xf8be8 ahci.c:450
+ sal ax, 007h ; c1 e0 07 ; 0xf8bec
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf8bef
+ add ax, 00108h ; 05 08 01 ; 0xf8bf2
+ cwd ; 99 ; 0xf8bf5
+ mov cx, dx ; 89 d1 ; 0xf8bf6
+ mov dx, si ; 89 f2 ; 0xf8bf8
+ xchg cx, ax ; 91 ; 0xf8bfa
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8bfb
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8bff
+ out DX, eax ; 66 ef ; 0xf8c01
+ lea bx, [si+004h] ; 8d 5c 04 ; 0xf8c03
+ xor ax, ax ; 31 c0 ; 0xf8c06
+ xor cx, cx ; 31 c9 ; 0xf8c08
+ mov dx, bx ; 89 da ; 0xf8c0a
+ xchg cx, ax ; 91 ; 0xf8c0c
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8c0d
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8c11
+ out DX, eax ; 66 ef ; 0xf8c13
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf8c15 ahci.c:451
+ add ax, 0010ch ; 05 0c 01 ; 0xf8c18
+ cwd ; 99 ; 0xf8c1b
+ mov cx, dx ; 89 d1 ; 0xf8c1c
+ mov dx, si ; 89 f2 ; 0xf8c1e
+ xchg cx, ax ; 91 ; 0xf8c20
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8c21
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8c25
+ out DX, eax ; 66 ef ; 0xf8c27
+ xor ax, ax ; 31 c0 ; 0xf8c29
+ xor cx, cx ; 31 c9 ; 0xf8c2b
+ mov dx, bx ; 89 da ; 0xf8c2d
+ xchg cx, ax ; 91 ; 0xf8c2f
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8c30
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8c34
+ out DX, eax ; 66 ef ; 0xf8c36
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf8c38 ahci.c:453
+ db 0feh, 0c4h
+ ; inc ah ; fe c4 ; 0xf8c3b
+ cwd ; 99 ; 0xf8c3d
+ mov cx, dx ; 89 d1 ; 0xf8c3e
+ mov dx, si ; 89 f2 ; 0xf8c40
+ xchg cx, ax ; 91 ; 0xf8c42
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8c43
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8c47
+ out DX, eax ; 66 ef ; 0xf8c49
+ xor ax, ax ; 31 c0 ; 0xf8c4b
+ xor cx, cx ; 31 c9 ; 0xf8c4d
+ mov dx, bx ; 89 da ; 0xf8c4f
+ xchg cx, ax ; 91 ; 0xf8c51
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8c52
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8c56
+ out DX, eax ; 66 ef ; 0xf8c58
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf8c5a ahci.c:454
+ add ax, 00104h ; 05 04 01 ; 0xf8c5d
+ cwd ; 99 ; 0xf8c60
+ mov cx, dx ; 89 d1 ; 0xf8c61
+ mov dx, si ; 89 f2 ; 0xf8c63
+ xchg cx, ax ; 91 ; 0xf8c65
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8c66
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8c6a
+ out DX, eax ; 66 ef ; 0xf8c6c
+ xor ax, ax ; 31 c0 ; 0xf8c6e
+ xor cx, cx ; 31 c9 ; 0xf8c70
+ mov dx, bx ; 89 da ; 0xf8c72
+ xchg cx, ax ; 91 ; 0xf8c74
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8c75
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8c79
+ out DX, eax ; 66 ef ; 0xf8c7b
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf8c7d ahci.c:457
+ add ax, 00114h ; 05 14 01 ; 0xf8c80
+ cwd ; 99 ; 0xf8c83
+ mov cx, dx ; 89 d1 ; 0xf8c84
+ mov dx, si ; 89 f2 ; 0xf8c86
+ xchg cx, ax ; 91 ; 0xf8c88
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8c89
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8c8d
+ out DX, eax ; 66 ef ; 0xf8c8f
+ xor ax, ax ; 31 c0 ; 0xf8c91
+ xor cx, cx ; 31 c9 ; 0xf8c93
+ mov dx, bx ; 89 da ; 0xf8c95
+ xchg cx, ax ; 91 ; 0xf8c97
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8c98
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8c9c
+ out DX, eax ; 66 ef ; 0xf8c9e
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf8ca0 ahci.c:459
+ mov byte [es:di+00262h], 0ffh ; 26 c6 85 62 02 ff ; 0xf8ca3
+ lea sp, [bp-008h] ; 8d 66 f8 ; 0xf8ca9 ahci.c:461
+ pop di ; 5f ; 0xf8cac
+ pop si ; 5e ; 0xf8cad
+ pop cx ; 59 ; 0xf8cae
+ pop bx ; 5b ; 0xf8caf
+ pop bp ; 5d ; 0xf8cb0
+ retn ; c3 ; 0xf8cb1
+ ; disGetNextSymbol 0xf8cb2 LB 0x1393 -> off=0x0 cb=000000000000024a uValue=00000000000f76b2 'ahci_port_init'
+ahci_port_init: ; 0xf8cb2 LB 0x24a
+ push bp ; 55 ; 0xf8cb2 ahci.c:467
+ mov bp, sp ; 89 e5 ; 0xf8cb3
+ push cx ; 51 ; 0xf8cb5
+ push si ; 56 ; 0xf8cb6
+ push di ; 57 ; 0xf8cb7
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf8cb8
+ mov si, ax ; 89 c6 ; 0xf8cbb
+ mov word [bp-00ah], dx ; 89 56 f6 ; 0xf8cbd
+ mov byte [bp-008h], bl ; 88 5e f8 ; 0xf8cc0
+ call 08b33h ; e8 6d fe ; 0xf8cc3 ahci.c:470
+ movzx ax, bl ; 0f b6 c3 ; 0xf8cc6 ahci.c:473
+ sal ax, 007h ; c1 e0 07 ; 0xf8cc9
+ add ax, 00118h ; 05 18 01 ; 0xf8ccc
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8ccf ahci.c:259
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8cd2
+ xor cx, cx ; 31 c9 ; 0xf8cd7 ahci.c:261
+ mov dx, bx ; 89 da ; 0xf8cd9
+ xchg cx, ax ; 91 ; 0xf8cdb
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8cdc
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8ce0
+ out DX, eax ; 66 ef ; 0xf8ce2
+ add bx, strict byte 00004h ; 83 c3 04 ; 0xf8ce4 ahci.c:262
+ mov dx, bx ; 89 da ; 0xf8ce7
+ in eax, DX ; 66 ed ; 0xf8ce9
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8ceb
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8ced
+ xchg dx, ax ; 92 ; 0xf8cf1
+ and AL, strict byte 0eeh ; 24 ee ; 0xf8cf2
+ mov cx, dx ; 89 d1 ; 0xf8cf4
+ mov dx, bx ; 89 da ; 0xf8cf6
+ xchg cx, ax ; 91 ; 0xf8cf8
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8cf9
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8cfd
+ out DX, eax ; 66 ef ; 0xf8cff
+ movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xf8d01 ahci.c:476
+ sal ax, 007h ; c1 e0 07 ; 0xf8d05
+ add ax, 00118h ; 05 18 01 ; 0xf8d08
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8d0b ahci.c:269
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8d0e
+ xor cx, cx ; 31 c9 ; 0xf8d13 ahci.c:271
+ mov dx, bx ; 89 da ; 0xf8d15
+ xchg cx, ax ; 91 ; 0xf8d17
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8d18
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8d1c
+ out DX, eax ; 66 ef ; 0xf8d1e
+ lea dx, [bx+004h] ; 8d 57 04 ; 0xf8d20 ahci.c:272
+ in eax, DX ; 66 ed ; 0xf8d23
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8d25
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8d27
+ xchg dx, ax ; 92 ; 0xf8d2b
+ test ax, 0c011h ; a9 11 c0 ; 0xf8d2c
+ je short 08d35h ; 74 04 ; 0xf8d2f
+ mov AL, strict byte 001h ; b0 01 ; 0xf8d31
+ jmp short 08d37h ; eb 02 ; 0xf8d33
+ xor al, al ; 30 c0 ; 0xf8d35
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf8d37 ahci.c:273
+ je short 08d01h ; 74 c6 ; 0xf8d39
+ mov cx, strict word 00020h ; b9 20 00 ; 0xf8d3b ahci.c:487
+ xor bx, bx ; 31 db ; 0xf8d3e
+ mov ax, si ; 89 f0 ; 0xf8d40
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8d42
+ call 09fb0h ; e8 68 12 ; 0xf8d45
+ lea ax, [si+00080h] ; 8d 84 80 00 ; 0xf8d48 ahci.c:488
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf8d4c
+ xor bx, bx ; 31 db ; 0xf8d4f
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8d51
+ call 09fb0h ; e8 59 12 ; 0xf8d54
+ lea di, [si+00200h] ; 8d bc 00 02 ; 0xf8d57 ahci.c:489
+ mov cx, strict word 00060h ; b9 60 00 ; 0xf8d5b
+ xor bx, bx ; 31 db ; 0xf8d5e
+ mov ax, di ; 89 f8 ; 0xf8d60
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8d62
+ call 09fb0h ; e8 48 12 ; 0xf8d65
+ movzx bx, byte [bp-008h] ; 0f b6 5e f8 ; 0xf8d68 ahci.c:493
+ sal bx, 007h ; c1 e3 07 ; 0xf8d6c
+ lea ax, [bx+00108h] ; 8d 87 08 01 ; 0xf8d6f
+ cwd ; 99 ; 0xf8d73
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8d74
+ mov cx, word [es:si+00260h] ; 26 8b 8c 60 02 ; 0xf8d77
+ mov word [bp-00ch], cx ; 89 4e f4 ; 0xf8d7c
+ mov cx, dx ; 89 d1 ; 0xf8d7f
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf8d81
+ xchg cx, ax ; 91 ; 0xf8d84
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8d85
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8d89
+ out DX, eax ; 66 ef ; 0xf8d8b
+ mov ax, di ; 89 f8 ; 0xf8d8d
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8d8f
+ call 08768h ; e8 d3 f9 ; 0xf8d92
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8d95
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8d98
+ add di, strict byte 00004h ; 83 c7 04 ; 0xf8d9d
+ mov cx, dx ; 89 d1 ; 0xf8da0
+ mov dx, di ; 89 fa ; 0xf8da2
+ xchg cx, ax ; 91 ; 0xf8da4
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8da5
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8da9
+ out DX, eax ; 66 ef ; 0xf8dab
+ lea ax, [bx+0010ch] ; 8d 87 0c 01 ; 0xf8dad ahci.c:494
+ cwd ; 99 ; 0xf8db1
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8db2
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8db5
+ mov cx, dx ; 89 d1 ; 0xf8dba
+ mov dx, di ; 89 fa ; 0xf8dbc
+ xchg cx, ax ; 91 ; 0xf8dbe
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8dbf
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8dc3
+ out DX, eax ; 66 ef ; 0xf8dc5
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8dc7
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8dca
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8dcf
+ xor ax, ax ; 31 c0 ; 0xf8dd2
+ xor cx, cx ; 31 c9 ; 0xf8dd4
+ xchg cx, ax ; 91 ; 0xf8dd6
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8dd7
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8ddb
+ out DX, eax ; 66 ef ; 0xf8ddd
+ lea ax, [bx+00100h] ; 8d 87 00 01 ; 0xf8ddf ahci.c:497
+ cwd ; 99 ; 0xf8de3
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8de4
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8de7
+ mov cx, dx ; 89 d1 ; 0xf8dec
+ mov dx, di ; 89 fa ; 0xf8dee
+ xchg cx, ax ; 91 ; 0xf8df0
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8df1
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8df5
+ out DX, eax ; 66 ef ; 0xf8df7
+ mov ax, si ; 89 f0 ; 0xf8df9
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8dfb
+ call 08768h ; e8 67 f9 ; 0xf8dfe
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8e01
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8e04
+ add di, strict byte 00004h ; 83 c7 04 ; 0xf8e09
+ mov cx, dx ; 89 d1 ; 0xf8e0c
+ mov dx, di ; 89 fa ; 0xf8e0e
+ xchg cx, ax ; 91 ; 0xf8e10
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8e11
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8e15
+ out DX, eax ; 66 ef ; 0xf8e17
+ lea ax, [bx+00104h] ; 8d 87 04 01 ; 0xf8e19 ahci.c:498
+ cwd ; 99 ; 0xf8e1d
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8e1e
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8e21
+ mov cx, dx ; 89 d1 ; 0xf8e26
+ mov dx, di ; 89 fa ; 0xf8e28
+ xchg cx, ax ; 91 ; 0xf8e2a
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8e2b
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8e2f
+ out DX, eax ; 66 ef ; 0xf8e31
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8e33
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8e36
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8e3b
+ xor ax, ax ; 31 c0 ; 0xf8e3e
+ xor cx, cx ; 31 c9 ; 0xf8e40
+ xchg cx, ax ; 91 ; 0xf8e42
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8e43
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8e47
+ out DX, eax ; 66 ef ; 0xf8e49
+ lea ax, [bx+00114h] ; 8d 87 14 01 ; 0xf8e4b ahci.c:501
+ cwd ; 99 ; 0xf8e4f
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8e50
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8e53
+ mov cx, dx ; 89 d1 ; 0xf8e58
+ mov dx, di ; 89 fa ; 0xf8e5a
+ xchg cx, ax ; 91 ; 0xf8e5c
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8e5d
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8e61
+ out DX, eax ; 66 ef ; 0xf8e63
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8e65
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8e68
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8e6d
+ xor ax, ax ; 31 c0 ; 0xf8e70
+ xor cx, cx ; 31 c9 ; 0xf8e72
+ xchg cx, ax ; 91 ; 0xf8e74
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8e75
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8e79
+ out DX, eax ; 66 ef ; 0xf8e7b
+ lea ax, [bx+00110h] ; 8d 87 10 01 ; 0xf8e7d ahci.c:502
+ cwd ; 99 ; 0xf8e81
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8e82
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8e85
+ mov cx, dx ; 89 d1 ; 0xf8e8a
+ mov dx, di ; 89 fa ; 0xf8e8c
+ xchg cx, ax ; 91 ; 0xf8e8e
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8e8f
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8e93
+ out DX, eax ; 66 ef ; 0xf8e95
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8e97
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8e9a
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8e9f
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf8ea2
+ mov cx, ax ; 89 c1 ; 0xf8ea5
+ xchg cx, ax ; 91 ; 0xf8ea7
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8ea8
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8eac
+ out DX, eax ; 66 ef ; 0xf8eae
+ lea ax, [bx+00130h] ; 8d 87 30 01 ; 0xf8eb0 ahci.c:504
+ cwd ; 99 ; 0xf8eb4
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8eb5
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8eb8
+ mov cx, dx ; 89 d1 ; 0xf8ebd
+ mov dx, bx ; 89 da ; 0xf8ebf
+ xchg cx, ax ; 91 ; 0xf8ec1
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8ec2
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8ec6
+ out DX, eax ; 66 ef ; 0xf8ec8
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8eca
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8ecd
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8ed2
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf8ed5
+ mov cx, ax ; 89 c1 ; 0xf8ed8
+ xchg cx, ax ; 91 ; 0xf8eda
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8edb
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8edf
+ out DX, eax ; 66 ef ; 0xf8ee1
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8ee3 ahci.c:506
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8ee6
+ mov byte [es:si+00262h], al ; 26 88 84 62 02 ; 0xf8ee9
+ mov byte [es:si+00263h], 000h ; 26 c6 84 63 02 00 ; 0xf8eee ahci.c:507
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf8ef4 ahci.c:508
+ pop di ; 5f ; 0xf8ef7
+ pop si ; 5e ; 0xf8ef8
+ pop cx ; 59 ; 0xf8ef9
+ pop bp ; 5d ; 0xf8efa
+ retn ; c3 ; 0xf8efb
+ ; disGetNextSymbol 0xf8efc LB 0x1149 -> off=0x0 cb=00000000000000a6 uValue=00000000000f78fc 'ahci_read_sectors'
+ahci_read_sectors: ; 0xf8efc LB 0xa6
+ push bp ; 55 ; 0xf8efc ahci.c:517
+ mov bp, sp ; 89 e5 ; 0xf8efd
+ push si ; 56 ; 0xf8eff
+ push di ; 57 ; 0xf8f00
+ push ax ; 50 ; 0xf8f01
+ les di, [bp+004h] ; c4 7e 04 ; 0xf8f02 ahci.c:522
+ movzx di, byte [es:di+00ch] ; 26 0f b6 7d 0c ; 0xf8f05
+ sub di, strict byte 0000ch ; 83 ef 0c ; 0xf8f0a
+ cmp di, strict byte 00004h ; 83 ff 04 ; 0xf8f0d ahci.c:523
+ jbe short 08f21h ; 76 0f ; 0xf8f10
+ push di ; 57 ; 0xf8f12 ahci.c:524
+ push 00c74h ; 68 74 0c ; 0xf8f13
+ push 00c86h ; 68 86 0c ; 0xf8f16
+ push strict byte 00007h ; 6a 07 ; 0xf8f19
+ call 01a14h ; e8 f6 8a ; 0xf8f1b
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf8f1e
+ xor bx, bx ; 31 db ; 0xf8f21 ahci.c:530
+ les si, [bp+004h] ; c4 76 04 ; 0xf8f23
+ mov dx, word [es:si+00232h] ; 26 8b 94 32 02 ; 0xf8f26
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8f2b ahci.c:239
+ mov es, dx ; 8e c2 ; 0xf8f2f
+ mov word [es:bx+00268h], ax ; 26 89 87 68 02 ; 0xf8f31
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf8f36 ahci.c:531
+ add di, si ; 01 f7 ; 0xf8f39
+ movzx bx, byte [es:di+0022dh] ; 26 0f b6 9d 2d 02 ; 0xf8f3b
+ mov di, si ; 89 f7 ; 0xf8f41
+ mov dx, word [es:di+00232h] ; 26 8b 95 32 02 ; 0xf8f43
+ xor ax, ax ; 31 c0 ; 0xf8f48
+ call 08cb2h ; e8 65 fd ; 0xf8f4a
+ mov bx, strict word 00025h ; bb 25 00 ; 0xf8f4d ahci.c:532
+ mov ax, si ; 89 f0 ; 0xf8f50
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf8f52
+ call 088d1h ; e8 79 f9 ; 0xf8f55
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf8f58
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf8f5b ahci.c:534
+ mov bx, si ; 89 f3 ; 0xf8f5e
+ mov ax, word [es:bx+00eh] ; 26 8b 47 0e ; 0xf8f60
+ mov word [es:bx+018h], ax ; 26 89 47 18 ; 0xf8f64
+ mov cx, ax ; 89 c1 ; 0xf8f68 ahci.c:536
+ sal cx, 009h ; c1 e1 09 ; 0xf8f6a
+ shr cx, 1 ; d1 e9 ; 0xf8f6d
+ mov di, word [es:di+008h] ; 26 8b 7d 08 ; 0xf8f6f
+ mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xf8f73
+ mov si, di ; 89 fe ; 0xf8f77
+ mov dx, ax ; 89 c2 ; 0xf8f79
+ mov es, ax ; 8e c0 ; 0xf8f7b
+ push DS ; 1e ; 0xf8f7d
+ mov ds, dx ; 8e da ; 0xf8f7e
+ rep movsw ; f3 a5 ; 0xf8f80
+ pop DS ; 1f ; 0xf8f82
+ xor bx, bx ; 31 db ; 0xf8f83 ahci.c:538
+ les di, [bp+004h] ; c4 7e 04 ; 0xf8f85
+ mov es, [es:di+00232h] ; 26 8e 85 32 02 ; 0xf8f88
+ mov ax, word [es:bx+00268h] ; 26 8b 87 68 02 ; 0xf8f8d ahci.c:244
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8f92
+ mov ax, word [bp-006h] ; 8b 46 fa ; 0xf8f96 ahci.c:540
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf8f99
+ pop di ; 5f ; 0xf8f9c
+ pop si ; 5e ; 0xf8f9d
+ pop bp ; 5d ; 0xf8f9e
+ retn 00004h ; c2 04 00 ; 0xf8f9f
+ ; disGetNextSymbol 0xf8fa2 LB 0x10a3 -> off=0x0 cb=0000000000000084 uValue=00000000000f79a2 'ahci_write_sectors'
+ahci_write_sectors: ; 0xf8fa2 LB 0x84
+ push bp ; 55 ; 0xf8fa2 ahci.c:549
+ mov bp, sp ; 89 e5 ; 0xf8fa3
+ push si ; 56 ; 0xf8fa5
+ push di ; 57 ; 0xf8fa6
+ mov si, word [bp+004h] ; 8b 76 04 ; 0xf8fa7
+ mov cx, word [bp+006h] ; 8b 4e 06 ; 0xf8faa
+ mov es, cx ; 8e c1 ; 0xf8fad ahci.c:554
+ movzx dx, byte [es:si+00ch] ; 26 0f b6 54 0c ; 0xf8faf
+ sub dx, strict byte 0000ch ; 83 ea 0c ; 0xf8fb4
+ cmp dx, strict byte 00004h ; 83 fa 04 ; 0xf8fb7 ahci.c:555
+ jbe short 08fcbh ; 76 0f ; 0xf8fba
+ push dx ; 52 ; 0xf8fbc ahci.c:556
+ push 00ca5h ; 68 a5 0c ; 0xf8fbd
+ push 00c86h ; 68 86 0c ; 0xf8fc0
+ push strict byte 00007h ; 6a 07 ; 0xf8fc3
+ call 01a14h ; e8 4c 8a ; 0xf8fc5
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf8fc8
+ xor bx, bx ; 31 db ; 0xf8fcb ahci.c:562
+ mov es, cx ; 8e c1 ; 0xf8fcd
+ mov di, word [es:si+00232h] ; 26 8b bc 32 02 ; 0xf8fcf
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8fd4 ahci.c:239
+ mov es, di ; 8e c7 ; 0xf8fd8
+ mov word [es:bx+00268h], ax ; 26 89 87 68 02 ; 0xf8fda
+ mov es, cx ; 8e c1 ; 0xf8fdf ahci.c:563
+ mov bx, si ; 89 f3 ; 0xf8fe1
+ add bx, dx ; 01 d3 ; 0xf8fe3
+ movzx bx, byte [es:bx+0022dh] ; 26 0f b6 9f 2d 02 ; 0xf8fe5
+ mov dx, word [es:si+00232h] ; 26 8b 94 32 02 ; 0xf8feb
+ xor ax, ax ; 31 c0 ; 0xf8ff0
+ call 08cb2h ; e8 bd fc ; 0xf8ff2
+ mov bx, strict word 00035h ; bb 35 00 ; 0xf8ff5 ahci.c:564
+ mov ax, si ; 89 f0 ; 0xf8ff8
+ mov dx, cx ; 89 ca ; 0xf8ffa
+ call 088d1h ; e8 d2 f8 ; 0xf8ffc
+ mov dx, ax ; 89 c2 ; 0xf8fff
+ mov es, cx ; 8e c1 ; 0xf9001 ahci.c:566
+ mov ax, word [es:si+00eh] ; 26 8b 44 0e ; 0xf9003
+ mov word [es:si+018h], ax ; 26 89 44 18 ; 0xf9007
+ xor bx, bx ; 31 db ; 0xf900b ahci.c:567
+ mov es, [es:si+00232h] ; 26 8e 84 32 02 ; 0xf900d
+ mov ax, word [es:bx+00268h] ; 26 8b 87 68 02 ; 0xf9012 ahci.c:244
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9017
+ mov ax, dx ; 89 d0 ; 0xf901b ahci.c:569
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf901d
+ pop di ; 5f ; 0xf9020
+ pop si ; 5e ; 0xf9021
+ pop bp ; 5d ; 0xf9022
+ retn 00004h ; c2 04 00 ; 0xf9023
+ ; disGetNextSymbol 0xf9026 LB 0x101f -> off=0x0 cb=0000000000000185 uValue=00000000000f7a26 'ahci_cmd_packet'
+ahci_cmd_packet: ; 0xf9026 LB 0x185
+ push bp ; 55 ; 0xf9026 ahci.c:576
+ mov bp, sp ; 89 e5 ; 0xf9027
+ push si ; 56 ; 0xf9029
+ push di ; 57 ; 0xf902a
+ sub sp, strict byte 0000eh ; 83 ec 0e ; 0xf902b
+ push ax ; 50 ; 0xf902e
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf902f
+ mov word [bp-012h], bx ; 89 5e ee ; 0xf9032
+ mov word [bp-010h], cx ; 89 4e f0 ; 0xf9035
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf9038 ahci.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf903b
+ mov es, ax ; 8e c0 ; 0xf903e
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf9040
+ mov si, 00122h ; be 22 01 ; 0xf9043 ahci.c:49
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf9046
+ cmp byte [bp+00ah], 002h ; 80 7e 0a 02 ; 0xf9049 ahci.c:583
+ jne short 0906eh ; 75 1f ; 0xf904d
+ mov bx, 00db2h ; bb b2 0d ; 0xf904f ahci.c:584
+ mov cx, ds ; 8c d9 ; 0xf9052
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf9054
+ call 019d3h ; e8 79 89 ; 0xf9057
+ push 00cb8h ; 68 b8 0c ; 0xf905a
+ push 00cc8h ; 68 c8 0c ; 0xf905d
+ push strict byte 00004h ; 6a 04 ; 0xf9060
+ call 01a14h ; e8 af 89 ; 0xf9062
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf9065
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf9068 ahci.c:585
+ jmp near 091a2h ; e9 34 01 ; 0xf906b
+ test byte [bp+004h], 001h ; f6 46 04 01 ; 0xf906e ahci.c:589
+ jne short 09068h ; 75 f4 ; 0xf9072
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf9074 ahci.c:603
+ mov di, word [bp+008h] ; 8b 7e 08 ; 0xf9077
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf907a
+ sal bx, 1 ; d1 e3 ; 0xf907d
+ rcl di, 1 ; d1 d7 ; 0xf907f
+ loop 0907dh ; e2 fa ; 0xf9081
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf9083
+ mov word [es:si], bx ; 26 89 1c ; 0xf9086
+ mov word [es:si+002h], di ; 26 89 7c 02 ; 0xf9089
+ db 066h, 026h, 0c7h, 044h, 004h, 000h, 000h, 000h, 000h
+ ; mov dword [es:si+004h], strict dword 000000000h ; 66 26 c7 44 04 00 00 00 00; 0xf908d
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf9096 ahci.c:604
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf9099
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf909d
+ mov word [es:si+00ah], ax ; 26 89 44 0a ; 0xf90a0
+ mov bx, word [es:si+010h] ; 26 8b 5c 10 ; 0xf90a4 ahci.c:605
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf90a8
+ mov dx, word [bp+008h] ; 8b 56 08 ; 0xf90ab
+ xor cx, cx ; 31 c9 ; 0xf90ae
+ call 09f50h ; e8 9d 0e ; 0xf90b0
+ mov word [es:si+00eh], ax ; 26 89 44 0e ; 0xf90b3
+ xor di, di ; 31 ff ; 0xf90b7 ahci.c:608
+ mov ax, word [es:si+00232h] ; 26 8b 84 32 02 ; 0xf90b9
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf90be
+ mov word [bp-00eh], di ; 89 7e f2 ; 0xf90c1
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf90c4
+ sub word [bp-014h], strict byte 0000ch ; 83 6e ec 0c ; 0xf90c7 ahci.c:595
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf90cb ahci.c:239
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf90cf
+ mov word [es:di+00268h], ax ; 26 89 85 68 02 ; 0xf90d2
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf90d7 ahci.c:611
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf90da
+ add bx, si ; 01 f3 ; 0xf90dd
+ movzx bx, byte [es:bx+0022dh] ; 26 0f b6 9f 2d 02 ; 0xf90df
+ mov dx, word [es:si+00232h] ; 26 8b 94 32 02 ; 0xf90e5
+ xor ax, ax ; 31 c0 ; 0xf90ea
+ call 08cb2h ; e8 c3 fb ; 0xf90ec
+ movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xf90ef ahci.c:614
+ push ax ; 50 ; 0xf90f3
+ mov bx, word [bp-012h] ; 8b 5e ee ; 0xf90f4
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf90f7
+ mov ax, 000c0h ; b8 c0 00 ; 0xf90fa
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf90fd
+ call 09fc0h ; e8 bd 0e ; 0xf9100
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf9103 ahci.c:618
+ mov word [es:si+018h], di ; 26 89 7c 18 ; 0xf9106
+ mov word [es:si+01ah], di ; 26 89 7c 1a ; 0xf910a ahci.c:619
+ mov word [es:si+01ch], di ; 26 89 7c 1c ; 0xf910e
+ mov ax, word [es:si+01eh] ; 26 8b 44 1e ; 0xf9112 ahci.c:622
+ test ax, ax ; 85 c0 ; 0xf9116
+ je short 09141h ; 74 27 ; 0xf9118
+ dec ax ; 48 ; 0xf911a ahci.c:623
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf911b
+ mov word [es:di+0010ch], ax ; 26 89 85 0c 01 ; 0xf911e
+ mov word [es:di+0010eh], di ; 26 89 bd 0e 01 ; 0xf9123
+ mov dx, word [es:di+00264h] ; 26 8b 95 64 02 ; 0xf9128 ahci.c:624
+ mov ax, word [es:di+00266h] ; 26 8b 85 66 02 ; 0xf912d
+ mov word [es:di+00100h], dx ; 26 89 95 00 01 ; 0xf9132
+ mov word [es:di+00102h], ax ; 26 89 85 02 01 ; 0xf9137
+ inc byte [es:di+00263h] ; 26 fe 85 63 02 ; 0xf913c ahci.c:625
+ mov bx, 000a0h ; bb a0 00 ; 0xf9141 ahci.c:628
+ mov ax, si ; 89 f0 ; 0xf9144
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf9146
+ call 088d1h ; e8 85 f7 ; 0xf9149
+ les bx, [bp-00eh] ; c4 5e f2 ; 0xf914c ahci.c:630
+ mov ax, word [es:bx+004h] ; 26 8b 47 04 ; 0xf914f
+ mov dx, word [es:bx+006h] ; 26 8b 57 06 ; 0xf9153
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf9157
+ mov word [es:si+01ah], ax ; 26 89 44 1a ; 0xf915a
+ mov word [es:si+01ch], dx ; 26 89 54 1c ; 0xf915e
+ mov bx, word [es:si+01ah] ; 26 8b 5c 1a ; 0xf9162 ahci.c:632
+ mov cx, dx ; 89 d1 ; 0xf9166
+ shr cx, 1 ; d1 e9 ; 0xf9168
+ rcr bx, 1 ; d1 db ; 0xf916a
+ mov di, word [es:si+008h] ; 26 8b 7c 08 ; 0xf916c
+ mov ax, word [es:si+00ah] ; 26 8b 44 0a ; 0xf9170
+ mov cx, bx ; 89 d9 ; 0xf9174
+ mov si, di ; 89 fe ; 0xf9176
+ mov dx, ax ; 89 c2 ; 0xf9178
+ mov es, ax ; 8e c0 ; 0xf917a
+ push DS ; 1e ; 0xf917c
+ mov ds, dx ; 8e da ; 0xf917d
+ rep movsw ; f3 a5 ; 0xf917f
+ pop DS ; 1f ; 0xf9181
+ les bx, [bp-00eh] ; c4 5e f2 ; 0xf9182 ahci.c:244
+ mov ax, word [es:bx+00268h] ; 26 8b 87 68 02 ; 0xf9185
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf918a
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf918e ahci.c:636
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf9191
+ or ax, word [es:bx+004h] ; 26 0b 47 04 ; 0xf9195
+ jne short 091a0h ; 75 05 ; 0xf9199
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf919b
+ jmp short 091a2h ; eb 02 ; 0xf919e
+ xor ax, ax ; 31 c0 ; 0xf91a0
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf91a2 ahci.c:637
+ pop di ; 5f ; 0xf91a5
+ pop si ; 5e ; 0xf91a6
+ pop bp ; 5d ; 0xf91a7
+ retn 0000ch ; c2 0c 00 ; 0xf91a8
+ ; disGetNextSymbol 0xf91ab LB 0xe9a -> off=0x0 cb=0000000000000005 uValue=00000000000f7bab 'wait_ticks_device_init'
+wait_ticks_device_init: ; 0xf91ab LB 0x5
+ push bp ; 55 ; 0xf91ab ahci.c:640
+ mov bp, sp ; 89 e5 ; 0xf91ac
+ pop bp ; 5d ; 0xf91ae ahci.c:642
+ retn ; c3 ; 0xf91af
+ ; disGetNextSymbol 0xf91b0 LB 0xe95 -> off=0x0 cb=00000000000004c9 uValue=00000000000f7bb0 'ahci_port_detect_device'
+ahci_port_detect_device: ; 0xf91b0 LB 0x4c9
+ push bp ; 55 ; 0xf91b0 ahci.c:644
+ mov bp, sp ; 89 e5 ; 0xf91b1
+ push cx ; 51 ; 0xf91b3
+ push si ; 56 ; 0xf91b4
+ push di ; 57 ; 0xf91b5
+ sub sp, 0022ch ; 81 ec 2c 02 ; 0xf91b6
+ mov si, ax ; 89 c6 ; 0xf91ba
+ mov word [bp-012h], dx ; 89 56 ee ; 0xf91bc
+ mov byte [bp-00eh], bl ; 88 5e f2 ; 0xf91bf
+ mov word [bp-024h], strict word 00000h ; c7 46 dc 00 00 ; 0xf91c2 ahci.c:650
+ movzx di, bl ; 0f b6 fb ; 0xf91c7 ahci.c:652
+ mov bx, di ; 89 fb ; 0xf91ca
+ call 08cb2h ; e8 e3 fa ; 0xf91cc
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf91cf ahci.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf91d2
+ mov es, ax ; 8e c0 ; 0xf91d5
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf91d7
+ mov word [bp-02ch], 00122h ; c7 46 d4 22 01 ; 0xf91da ahci.c:49
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf91df
+ mov ax, di ; 89 f8 ; 0xf91e2 ahci.c:657
+ sal ax, 007h ; c1 e0 07 ; 0xf91e4
+ add ax, 0012ch ; 05 2c 01 ; 0xf91e7
+ cwd ; 99 ; 0xf91ea
+ mov bx, ax ; 89 c3 ; 0xf91eb
+ mov di, dx ; 89 d7 ; 0xf91ed
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf91ef
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf91f2
+ mov cx, di ; 89 f9 ; 0xf91f7
+ xchg cx, ax ; 91 ; 0xf91f9
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf91fa
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf91fe
+ out DX, eax ; 66 ef ; 0xf9200
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf9202
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf9205
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf920a
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf920d
+ xor cx, cx ; 31 c9 ; 0xf9210
+ xchg cx, ax ; 91 ; 0xf9212
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9213
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9217
+ out DX, eax ; 66 ef ; 0xf9219
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf921b ahci.c:662
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf921e
+ mov ax, bx ; 89 d8 ; 0xf9223
+ mov cx, di ; 89 f9 ; 0xf9225
+ xchg cx, ax ; 91 ; 0xf9227
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9228
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf922c
+ out DX, eax ; 66 ef ; 0xf922e
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf9230
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf9233
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf9238
+ xor ax, ax ; 31 c0 ; 0xf923b
+ xor cx, cx ; 31 c9 ; 0xf923d
+ xchg cx, ax ; 91 ; 0xf923f
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9240
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9244
+ out DX, eax ; 66 ef ; 0xf9246
+ mov di, strict word 0006ch ; bf 6c 00 ; 0xf9248 ahci.c:671
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf924b
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf924e
+ mov es, ax ; 8e c0 ; 0xf9251 ahci.c:672
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf9253
+ add ax, strict word 00003h ; 05 03 00 ; 0xf9256
+ mov word [bp-026h], ax ; 89 46 da ; 0xf9259
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf925c
+ adc ax, strict word 00000h ; 15 00 00 ; 0xf9260
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf9263
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf9266 ahci.c:674
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf9269
+ cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xf926d
+ jc short 09283h ; 72 11 ; 0xf9270
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf9272
+ cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xf9276
+ jne short 092ceh ; 75 53 ; 0xf9279
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf927b
+ cmp ax, word [bp-026h] ; 3b 46 da ; 0xf927e
+ jnc short 092ceh ; 73 4b ; 0xf9281
+ movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xf9283 ahci.c:677
+ sal ax, 007h ; c1 e0 07 ; 0xf9287
+ add ax, 00128h ; 05 28 01 ; 0xf928a
+ cwd ; 99 ; 0xf928d
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf928e
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf9291
+ mov cx, dx ; 89 d1 ; 0xf9296
+ mov dx, bx ; 89 da ; 0xf9298
+ xchg cx, ax ; 91 ; 0xf929a
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf929b
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf929f
+ out DX, eax ; 66 ef ; 0xf92a1
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf92a3
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf92a6
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf92ab
+ in eax, DX ; 66 ed ; 0xf92ae
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf92b0
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf92b2
+ xchg dx, ax ; 92 ; 0xf92b6
+ mov word [bp-022h], ax ; 89 46 de ; 0xf92b7
+ mov word [bp-028h], dx ; 89 56 d8 ; 0xf92ba
+ push strict byte 00000h ; 6a 00 ; 0xf92bd ahci.c:678
+ mov bx, strict word 0000fh ; bb 0f 00 ; 0xf92bf
+ xor cx, cx ; 31 c9 ; 0xf92c2
+ call 0874dh ; e8 86 f4 ; 0xf92c4
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf92c7
+ jne short 09266h ; 75 9a ; 0xf92ca
+ jmp short 092d6h ; eb 08 ; 0xf92cc ahci.c:680
+ cmp word [bp-024h], strict byte 00000h ; 83 7e dc 00 ; 0xf92ce ahci.c:685
+ je near 09671h ; 0f 84 9b 03 ; 0xf92d2
+ push strict byte 00000h ; 6a 00 ; 0xf92d6 ahci.c:690
+ mov bx, strict word 0000fh ; bb 0f 00 ; 0xf92d8
+ xor cx, cx ; 31 c9 ; 0xf92db
+ mov ax, word [bp-022h] ; 8b 46 de ; 0xf92dd
+ mov dx, word [bp-028h] ; 8b 56 d8 ; 0xf92e0
+ call 0874dh ; e8 67 f4 ; 0xf92e3
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf92e6
+ jne near 09671h ; 0f 85 84 03 ; 0xf92e9
+ movzx di, byte [bp-00eh] ; 0f b6 7e f2 ; 0xf92ed ahci.c:698
+ sal di, 007h ; c1 e7 07 ; 0xf92f1
+ lea ax, [di+00130h] ; 8d 85 30 01 ; 0xf92f4
+ cwd ; 99 ; 0xf92f8
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf92f9
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf92fc
+ mov cx, dx ; 89 d1 ; 0xf9301
+ mov dx, bx ; 89 da ; 0xf9303
+ xchg cx, ax ; 91 ; 0xf9305
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9306
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf930a
+ out DX, eax ; 66 ef ; 0xf930c
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf930e
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf9311
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf9316
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf9319
+ mov cx, ax ; 89 c1 ; 0xf931c
+ xchg cx, ax ; 91 ; 0xf931e
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf931f
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9323
+ out DX, eax ; 66 ef ; 0xf9325
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf9327 ahci.c:700
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf932a
+ mov al, byte [es:bx+00231h] ; 26 8a 87 31 02 ; 0xf932d
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf9332
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf9335 ahci.c:705
+ jnc near 09671h ; 0f 83 36 03 ; 0xf9337
+ lea ax, [di+00118h] ; 8d 85 18 01 ; 0xf933b ahci.c:708
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf933f ahci.c:250
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf9342
+ xor cx, cx ; 31 c9 ; 0xf9347 ahci.c:252
+ mov dx, bx ; 89 da ; 0xf9349
+ xchg cx, ax ; 91 ; 0xf934b
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf934c
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9350
+ out DX, eax ; 66 ef ; 0xf9352
+ add bx, strict byte 00004h ; 83 c3 04 ; 0xf9354 ahci.c:253
+ mov dx, bx ; 89 da ; 0xf9357
+ in eax, DX ; 66 ed ; 0xf9359
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf935b
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf935d
+ xchg dx, ax ; 92 ; 0xf9361
+ or AL, strict byte 010h ; 0c 10 ; 0xf9362
+ mov cx, dx ; 89 d1 ; 0xf9364
+ mov dx, bx ; 89 da ; 0xf9366
+ xchg cx, ax ; 91 ; 0xf9368
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9369
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf936d
+ out DX, eax ; 66 ef ; 0xf936f
+ lea ax, [di+00124h] ; 8d 85 24 01 ; 0xf9371 ahci.c:712
+ cwd ; 99 ; 0xf9375
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf9376
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf9379
+ mov cx, dx ; 89 d1 ; 0xf937e
+ mov dx, bx ; 89 da ; 0xf9380
+ xchg cx, ax ; 91 ; 0xf9382
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9383
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9387
+ out DX, eax ; 66 ef ; 0xf9389
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf938b
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf938e
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf9393
+ in eax, DX ; 66 ed ; 0xf9396
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9398
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf939a
+ xchg dx, ax ; 92 ; 0xf939e
+ mov si, ax ; 89 c6 ; 0xf939f
+ mov ax, dx ; 89 d0 ; 0xf93a1
+ mov dl, byte [bp-00ch] ; 8a 56 f4 ; 0xf93a3
+ add dl, 00ch ; 80 c2 0c ; 0xf93a6
+ mov byte [bp-008h], dl ; 88 56 f8 ; 0xf93a9
+ test ax, ax ; 85 c0 ; 0xf93ac ahci.c:713
+ jne near 095b9h ; 0f 85 07 02 ; 0xf93ae
+ cmp si, 00101h ; 81 fe 01 01 ; 0xf93b2
+ jne near 095b9h ; 0f 85 ff 01 ; 0xf93b6
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf93ba ahci.c:723
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf93bd
+ db 066h, 026h, 0c7h, 047h, 004h, 000h, 000h, 000h, 000h
+ ; mov dword [es:bx+004h], strict dword 000000000h ; 66 26 c7 47 04 00 00 00 00; 0xf93c0
+ db 066h, 026h, 0c7h, 007h, 000h, 000h, 000h, 000h
+ ; mov dword [es:bx], strict dword 000000000h ; 66 26 c7 07 00 00 00 00 ; 0xf93c9
+ lea dx, [bp-00232h] ; 8d 96 ce fd ; 0xf93d1 ahci.c:724
+ mov word [es:bx+008h], dx ; 26 89 57 08 ; 0xf93d5
+ mov [es:bx+00ah], ss ; 26 8c 57 0a ; 0xf93d9
+ db 066h, 026h, 0c7h, 047h, 00eh, 001h, 000h, 000h, 002h
+ ; mov dword [es:bx+00eh], strict dword 002000001h ; 66 26 c7 47 0e 01 00 00 02; 0xf93dd ahci.c:725
+ mov bx, 000ech ; bb ec 00 ; 0xf93e6 ahci.c:727
+ mov ax, word [bp-02ch] ; 8b 46 d4 ; 0xf93e9
+ mov dx, es ; 8c c2 ; 0xf93ec
+ call 088d1h ; e8 e0 f4 ; 0xf93ee
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf93f1 ahci.c:730
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf93f4
+ test byte [bp-00232h], 080h ; f6 86 ce fd 80 ; 0xf93f7 ahci.c:732
+ db 00fh, 095h, 0c0h
+ ; setne al ; 0f 95 c0 ; 0xf93fc
+ xor ah, ah ; 30 e4 ; 0xf93ff
+ mov dx, word [bp-00230h] ; 8b 96 d0 fd ; 0xf9401 ahci.c:733
+ mov word [bp-01eh], dx ; 89 56 e2 ; 0xf9405
+ mov dx, word [bp-0022ch] ; 8b 96 d4 fd ; 0xf9408 ahci.c:734
+ mov word [bp-01ah], dx ; 89 56 e6 ; 0xf940c
+ mov dx, word [bp-00226h] ; 8b 96 da fd ; 0xf940f ahci.c:735
+ mov word [bp-020h], dx ; 89 56 e0 ; 0xf9413
+ mov di, word [bp-001bah] ; 8b be 46 fe ; 0xf9416 ahci.c:736
+ mov si, word [bp-001b8h] ; 8b b6 48 fe ; 0xf941a
+ mov dword [bp-018h], strict dword 000000000h ; 66 c7 46 e8 00 00 00 00 ; 0xf941e
+ cmp si, 00fffh ; 81 fe ff 0f ; 0xf9426 ahci.c:738
+ jne short 09447h ; 75 1b ; 0xf942a
+ cmp di, strict byte 0ffffh ; 83 ff ff ; 0xf942c
+ jne short 09447h ; 75 16 ; 0xf942f
+ mov dx, word [bp-00164h] ; 8b 96 9c fe ; 0xf9431 ahci.c:739
+ mov word [bp-018h], dx ; 89 56 e8 ; 0xf9435
+ mov dx, word [bp-00166h] ; 8b 96 9a fe ; 0xf9438
+ mov word [bp-016h], dx ; 89 56 ea ; 0xf943c
+ mov si, word [bp-00168h] ; 8b b6 98 fe ; 0xf943f
+ mov di, word [bp-0016ah] ; 8b be 96 fe ; 0xf9443
+ movzx bx, byte [bp-00ch] ; 0f b6 5e f4 ; 0xf9447 ahci.c:743
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf944b
+ add bx, word [bp-02ch] ; 03 5e d4 ; 0xf944e
+ mov ah, byte [bp-00eh] ; 8a 66 f2 ; 0xf9451
+ mov byte [es:bx+0022dh], ah ; 26 88 a7 2d 02 ; 0xf9454
+ movzx dx, byte [bp-00ah] ; 0f b6 56 f6 ; 0xf9459 ahci.c:744
+ imul dx, dx, strict byte 0001ch ; 6b d2 1c ; 0xf945d
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf9460
+ add bx, dx ; 01 d3 ; 0xf9463
+ mov word [es:bx+022h], 0ff05h ; 26 c7 47 22 05 ff ; 0xf9465
+ mov byte [es:bx+024h], al ; 26 88 47 24 ; 0xf946b ahci.c:746
+ mov byte [es:bx+025h], 000h ; 26 c6 47 25 00 ; 0xf946f ahci.c:747
+ mov word [es:bx+028h], 00200h ; 26 c7 47 28 00 02 ; 0xf9474 ahci.c:748
+ mov byte [es:bx+027h], 001h ; 26 c6 47 27 01 ; 0xf947a ahci.c:749
+ mov ax, word [bp-018h] ; 8b 46 e8 ; 0xf947f ahci.c:750
+ mov word [es:bx+03ch], ax ; 26 89 47 3c ; 0xf9482
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf9486
+ mov word [es:bx+03ah], ax ; 26 89 47 3a ; 0xf9489
+ mov word [es:bx+038h], si ; 26 89 77 38 ; 0xf948d
+ mov word [es:bx+036h], di ; 26 89 7f 36 ; 0xf9491
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf9495 ahci.c:752
+ mov word [es:bx+030h], ax ; 26 89 47 30 ; 0xf9498
+ mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xf949c ahci.c:753
+ mov word [es:bx+032h], ax ; 26 89 47 32 ; 0xf949f
+ mov ax, word [bp-020h] ; 8b 46 e0 ; 0xf94a3 ahci.c:754
+ mov word [es:bx+034h], ax ; 26 89 47 34 ; 0xf94a6
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf94aa ahci.c:757
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf94ad
+ jc short 094bdh ; 72 0c ; 0xf94af
+ jbe short 094c5h ; 76 12 ; 0xf94b1
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf94b3
+ je short 094cdh ; 74 16 ; 0xf94b5
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf94b7
+ je short 094c9h ; 74 0e ; 0xf94b9
+ jmp short 0951ah ; eb 5d ; 0xf94bb
+ test al, al ; 84 c0 ; 0xf94bd
+ jne short 0951ah ; 75 59 ; 0xf94bf
+ mov BL, strict byte 040h ; b3 40 ; 0xf94c1 ahci.c:760
+ jmp short 094cfh ; eb 0a ; 0xf94c3 ahci.c:761
+ mov BL, strict byte 048h ; b3 48 ; 0xf94c5 ahci.c:763
+ jmp short 094cfh ; eb 06 ; 0xf94c7 ahci.c:764
+ mov BL, strict byte 050h ; b3 50 ; 0xf94c9 ahci.c:766
+ jmp short 094cfh ; eb 02 ; 0xf94cb ahci.c:767
+ mov BL, strict byte 058h ; b3 58 ; 0xf94cd ahci.c:769
+ mov al, bl ; 88 d8 ; 0xf94cf ahci.c:773
+ add AL, strict byte 007h ; 04 07 ; 0xf94d1
+ movzx dx, al ; 0f b6 d0 ; 0xf94d3
+ mov ax, dx ; 89 d0 ; 0xf94d6
+ call 01756h ; e8 7b 82 ; 0xf94d8
+ test al, al ; 84 c0 ; 0xf94db
+ je short 0951ah ; 74 3b ; 0xf94dd
+ mov al, bl ; 88 d8 ; 0xf94df ahci.c:776
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf94e1
+ xor ah, ah ; 30 e4 ; 0xf94e3
+ call 01756h ; e8 6e 82 ; 0xf94e5
+ xor ah, ah ; 30 e4 ; 0xf94e8
+ sal ax, 008h ; c1 e0 08 ; 0xf94ea
+ mov word [bp-02ah], ax ; 89 46 d6 ; 0xf94ed
+ movzx ax, bl ; 0f b6 c3 ; 0xf94f0
+ call 01756h ; e8 60 82 ; 0xf94f3
+ xor ah, ah ; 30 e4 ; 0xf94f6
+ mov cx, word [bp-02ah] ; 8b 4e d6 ; 0xf94f8
+ add cx, ax ; 01 c1 ; 0xf94fb
+ mov word [bp-030h], cx ; 89 4e d0 ; 0xf94fd
+ mov al, bl ; 88 d8 ; 0xf9500 ahci.c:777
+ add AL, strict byte 002h ; 04 02 ; 0xf9502
+ xor ah, ah ; 30 e4 ; 0xf9504
+ call 01756h ; e8 4d 82 ; 0xf9506
+ xor ah, ah ; 30 e4 ; 0xf9509
+ mov word [bp-032h], ax ; 89 46 ce ; 0xf950b
+ mov ax, dx ; 89 d0 ; 0xf950e ahci.c:778
+ call 01756h ; e8 43 82 ; 0xf9510
+ xor ah, ah ; 30 e4 ; 0xf9513
+ mov word [bp-02eh], ax ; 89 46 d2 ; 0xf9515
+ jmp short 0952ah ; eb 10 ; 0xf9518 ahci.c:780
+ push word [bp-018h] ; ff 76 e8 ; 0xf951a ahci.c:781
+ push word [bp-016h] ; ff 76 ea ; 0xf951d
+ push si ; 56 ; 0xf9520
+ push di ; 57 ; 0xf9521
+ mov dx, ss ; 8c d2 ; 0xf9522
+ lea ax, [bp-032h] ; 8d 46 ce ; 0xf9524
+ call 0599dh ; e8 73 c4 ; 0xf9527
+ mov bx, 00db2h ; bb b2 0d ; 0xf952a ahci.c:785
+ mov cx, ds ; 8c d9 ; 0xf952d
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf952f
+ call 019d3h ; e8 9e 84 ; 0xf9532
+ push word [bp-018h] ; ff 76 e8 ; 0xf9535
+ push word [bp-016h] ; ff 76 ea ; 0xf9538
+ push si ; 56 ; 0xf953b
+ push di ; 57 ; 0xf953c
+ mov ax, word [bp-02eh] ; 8b 46 d2 ; 0xf953d
+ push ax ; 50 ; 0xf9540
+ mov ax, word [bp-032h] ; 8b 46 ce ; 0xf9541
+ push ax ; 50 ; 0xf9544
+ mov ax, word [bp-030h] ; 8b 46 d0 ; 0xf9545
+ push ax ; 50 ; 0xf9548
+ push word [bp-020h] ; ff 76 e0 ; 0xf9549
+ push word [bp-01ah] ; ff 76 e6 ; 0xf954c
+ push word [bp-01eh] ; ff 76 e2 ; 0xf954f
+ movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xf9552
+ push ax ; 50 ; 0xf9556
+ movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xf9557
+ push ax ; 50 ; 0xf955b
+ push 00ce8h ; 68 e8 0c ; 0xf955c
+ push strict byte 00004h ; 6a 04 ; 0xf955f
+ call 01a14h ; e8 b0 84 ; 0xf9561
+ add sp, strict byte 0001ch ; 83 c4 1c ; 0xf9564
+ movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xf9567 ahci.c:787
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf956b
+ mov di, word [bp-02ch] ; 8b 7e d4 ; 0xf956e
+ add di, ax ; 01 c7 ; 0xf9571
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf9573
+ lea di, [di+02ah] ; 8d 7d 2a ; 0xf9576
+ push DS ; 1e ; 0xf9579
+ push SS ; 16 ; 0xf957a
+ pop DS ; 1f ; 0xf957b
+ lea si, [bp-032h] ; 8d 76 ce ; 0xf957c
+ movsw ; a5 ; 0xf957f
+ movsw ; a5 ; 0xf9580
+ movsw ; a5 ; 0xf9581
+ pop DS ; 1f ; 0xf9582
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf9583 ahci.c:790
+ mov al, byte [es:bx+001e2h] ; 26 8a 87 e2 01 ; 0xf9586
+ mov ah, byte [bp-00ch] ; 8a 66 f4 ; 0xf958b ahci.c:791
+ add ah, 00ch ; 80 c4 0c ; 0xf958e
+ movzx bx, al ; 0f b6 d8 ; 0xf9591
+ add bx, word [bp-02ch] ; 03 5e d4 ; 0xf9594
+ mov byte [es:bx+001e3h], ah ; 26 88 a7 e3 01 ; 0xf9597
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf959c ahci.c:792
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf959e ahci.c:793
+ mov byte [es:bx+001e2h], al ; 26 88 87 e2 01 ; 0xf95a1
+ mov bx, strict word 00075h ; bb 75 00 ; 0xf95a6 ahci.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf95a9
+ mov es, ax ; 8e c0 ; 0xf95ac
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf95ae
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf95b1 ahci.c:797
+ mov byte [es:bx], al ; 26 88 07 ; 0xf95b3 ahci.c:43
+ jmp near 09660h ; e9 a7 00 ; 0xf95b6 ahci.c:800
+ cmp ax, 0eb14h ; 3d 14 eb ; 0xf95b9
+ jne near 09660h ; 0f 85 a0 00 ; 0xf95bc
+ cmp si, 00101h ; 81 fe 01 01 ; 0xf95c0
+ jne near 09660h ; 0f 85 98 00 ; 0xf95c4
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf95c8 ahci.c:805
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf95cb
+ db 066h, 026h, 0c7h, 047h, 004h, 000h, 000h, 000h, 000h
+ ; mov dword [es:bx+004h], strict dword 000000000h ; 66 26 c7 47 04 00 00 00 00; 0xf95ce
+ db 066h, 026h, 0c7h, 007h, 000h, 000h, 000h, 000h
+ ; mov dword [es:bx], strict dword 000000000h ; 66 26 c7 07 00 00 00 00 ; 0xf95d7
+ lea dx, [bp-00232h] ; 8d 96 ce fd ; 0xf95df ahci.c:806
+ mov word [es:bx+008h], dx ; 26 89 57 08 ; 0xf95e3
+ mov [es:bx+00ah], ss ; 26 8c 57 0a ; 0xf95e7
+ db 066h, 026h, 0c7h, 047h, 00eh, 001h, 000h, 000h, 002h
+ ; mov dword [es:bx+00eh], strict dword 002000001h ; 66 26 c7 47 0e 01 00 00 02; 0xf95eb ahci.c:807
+ mov bx, 000a1h ; bb a1 00 ; 0xf95f4 ahci.c:809
+ mov ax, word [bp-02ch] ; 8b 46 d4 ; 0xf95f7
+ mov dx, es ; 8c c2 ; 0xf95fa
+ call 088d1h ; e8 d2 f2 ; 0xf95fc
+ test byte [bp-00232h], 080h ; f6 86 ce fd 80 ; 0xf95ff ahci.c:814
+ db 00fh, 095h, 0c0h
+ ; setne al ; 0f 95 c0 ; 0xf9604
+ xor ah, ah ; 30 e4 ; 0xf9607
+ mov dx, ax ; 89 c2 ; 0xf9609
+ movzx bx, byte [bp-00ch] ; 0f b6 5e f4 ; 0xf960b ahci.c:816
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf960f
+ add bx, word [bp-02ch] ; 03 5e d4 ; 0xf9612
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf9615
+ mov byte [es:bx+0022dh], al ; 26 88 87 2d 02 ; 0xf9618
+ movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xf961d ahci.c:817
+ imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xf9621
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf9624
+ add bx, ax ; 01 c3 ; 0xf9627
+ mov word [es:bx+022h], 00505h ; 26 c7 47 22 05 05 ; 0xf9629
+ mov byte [es:bx+024h], dl ; 26 88 57 24 ; 0xf962f ahci.c:819
+ mov word [es:bx+028h], 00800h ; 26 c7 47 28 00 08 ; 0xf9633 ahci.c:820
+ mov byte [es:bx+027h], dh ; 26 88 77 27 ; 0xf9639 ahci.c:821
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf963d ahci.c:824
+ mov al, byte [es:bx+001f3h] ; 26 8a 87 f3 01 ; 0xf9640
+ mov ah, byte [bp-00ch] ; 8a 66 f4 ; 0xf9645 ahci.c:825
+ add ah, 00ch ; 80 c4 0c ; 0xf9648
+ movzx bx, al ; 0f b6 d8 ; 0xf964b
+ add bx, word [bp-02ch] ; 03 5e d4 ; 0xf964e
+ mov byte [es:bx+001f4h], ah ; 26 88 a7 f4 01 ; 0xf9651
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf9656 ahci.c:826
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf9658 ahci.c:827
+ mov byte [es:bx+001f3h], al ; 26 88 87 f3 01 ; 0xf965b
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf9660 ahci.c:832
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf9663 ahci.c:833
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf9666
+ mov bx, word [bp-02ch] ; 8b 5e d4 ; 0xf9669
+ mov byte [es:bx+00231h], al ; 26 88 87 31 02 ; 0xf966c
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf9671 ahci.c:838
+ pop di ; 5f ; 0xf9674
+ pop si ; 5e ; 0xf9675
+ pop cx ; 59 ; 0xf9676
+ pop bp ; 5d ; 0xf9677
+ retn ; c3 ; 0xf9678
+ ; disGetNextSymbol 0xf9679 LB 0x9cc -> off=0x0 cb=000000000000003a uValue=00000000000f8079 'ahci_mem_alloc'
+ahci_mem_alloc: ; 0xf9679 LB 0x3a
+ push bx ; 53 ; 0xf9679 ahci.c:843
+ push cx ; 51 ; 0xf967a
+ push dx ; 52 ; 0xf967b
+ push di ; 57 ; 0xf967c
+ push bp ; 55 ; 0xf967d
+ mov bp, sp ; 89 e5 ; 0xf967e
+ mov di, 00413h ; bf 13 04 ; 0xf9680 ahci.c:48
+ xor ax, ax ; 31 c0 ; 0xf9683
+ mov es, ax ; 8e c0 ; 0xf9685
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf9687
+ test ax, ax ; 85 c0 ; 0xf968a ahci.c:852
+ je short 096adh ; 74 1f ; 0xf968c
+ dec ax ; 48 ; 0xf968e ahci.c:853
+ mov bx, ax ; 89 c3 ; 0xf968f
+ xor dx, dx ; 31 d2 ; 0xf9691 ahci.c:856
+ mov cx, strict word 0000ah ; b9 0a 00 ; 0xf9693
+ sal ax, 1 ; d1 e0 ; 0xf9696
+ rcl dx, 1 ; d1 d2 ; 0xf9698
+ loop 09696h ; e2 fa ; 0xf969a
+ mov di, dx ; 89 d7 ; 0xf969c
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf969e
+ shr di, 1 ; d1 ef ; 0xf96a1
+ rcr ax, 1 ; d1 d8 ; 0xf96a3
+ loop 096a1h ; e2 fa ; 0xf96a5
+ mov di, 00413h ; bf 13 04 ; 0xf96a7 ahci.c:53
+ mov word [es:di], bx ; 26 89 1d ; 0xf96aa
+ pop bp ; 5d ; 0xf96ad ahci.c:861
+ pop di ; 5f ; 0xf96ae
+ pop dx ; 5a ; 0xf96af
+ pop cx ; 59 ; 0xf96b0
+ pop bx ; 5b ; 0xf96b1
+ retn ; c3 ; 0xf96b2
+ ; disGetNextSymbol 0xf96b3 LB 0x992 -> off=0x0 cb=000000000000014f uValue=00000000000f80b3 'ahci_hba_init'
+ahci_hba_init: ; 0xf96b3 LB 0x14f
+ push bp ; 55 ; 0xf96b3 ahci.c:866
+ mov bp, sp ; 89 e5 ; 0xf96b4
+ push bx ; 53 ; 0xf96b6
+ push cx ; 51 ; 0xf96b7
+ push dx ; 52 ; 0xf96b8
+ push si ; 56 ; 0xf96b9
+ push di ; 57 ; 0xf96ba
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf96bb
+ mov si, ax ; 89 c6 ; 0xf96be
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf96c0 ahci.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf96c3
+ mov es, ax ; 8e c0 ; 0xf96c6
+ mov di, word [es:bx] ; 26 8b 3f ; 0xf96c8
+ mov bx, 00122h ; bb 22 01 ; 0xf96cb ahci.c:877
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf96ce ahci.c:879
+ xor cx, cx ; 31 c9 ; 0xf96d1
+ mov dx, si ; 89 f2 ; 0xf96d3
+ xchg cx, ax ; 91 ; 0xf96d5
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf96d6
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf96da
+ out DX, eax ; 66 ef ; 0xf96dc
+ lea dx, [si+004h] ; 8d 54 04 ; 0xf96de
+ in eax, DX ; 66 ed ; 0xf96e1
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf96e3
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf96e5
+ xchg dx, ax ; 92 ; 0xf96e9
+ call 09679h ; e8 8c ff ; 0xf96ea ahci.c:885
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf96ed
+ test ax, ax ; 85 c0 ; 0xf96f0 ahci.c:886
+ je near 097f8h ; 0f 84 02 01 ; 0xf96f2
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf96f6 ahci.c:889
+ mov es, di ; 8e c7 ; 0xf96f9
+ mov word [es:bx+00232h], ax ; 26 89 87 32 02 ; 0xf96fb
+ mov byte [es:bx+00231h], 000h ; 26 c6 87 31 02 00 ; 0xf9700 ahci.c:895
+ xor bx, bx ; 31 db ; 0xf9706 ahci.c:897
+ mov es, ax ; 8e c0 ; 0xf9708
+ mov byte [es:bx+00262h], 0ffh ; 26 c6 87 62 02 ff ; 0xf970a ahci.c:898
+ mov word [es:bx+00260h], si ; 26 89 b7 60 02 ; 0xf9710 ahci.c:899
+ db 066h, 026h, 0c7h, 087h, 064h, 002h, 000h, 0c0h, 00ch, 000h
+ ; mov dword [es:bx+00264h], strict dword 0000cc000h ; 66 26 c7 87 64 02 00 c0 0c 00; 0xf9715 ahci.c:904
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf971f ahci.c:252
+ xor cx, cx ; 31 c9 ; 0xf9722
+ mov dx, si ; 89 f2 ; 0xf9724
+ xchg cx, ax ; 91 ; 0xf9726
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9727
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf972b
+ out DX, eax ; 66 ef ; 0xf972d
+ lea bx, [si+004h] ; 8d 5c 04 ; 0xf972f ahci.c:253
+ mov dx, bx ; 89 da ; 0xf9732
+ in eax, DX ; 66 ed ; 0xf9734
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9736
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf9738
+ xchg dx, ax ; 92 ; 0xf973c
+ or AL, strict byte 001h ; 0c 01 ; 0xf973d
+ mov cx, dx ; 89 d1 ; 0xf973f
+ mov dx, bx ; 89 da ; 0xf9741
+ xchg cx, ax ; 91 ; 0xf9743
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9744
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9748
+ out DX, eax ; 66 ef ; 0xf974a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf974c ahci.c:910
+ xor cx, cx ; 31 c9 ; 0xf974f
+ mov dx, si ; 89 f2 ; 0xf9751
+ xchg cx, ax ; 91 ; 0xf9753
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9754
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9758
+ out DX, eax ; 66 ef ; 0xf975a
+ lea bx, [si+004h] ; 8d 5c 04 ; 0xf975c
+ mov dx, bx ; 89 da ; 0xf975f
+ in eax, DX ; 66 ed ; 0xf9761
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9763
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf9765
+ xchg dx, ax ; 92 ; 0xf9769
+ test AL, strict byte 001h ; a8 01 ; 0xf976a ahci.c:911
+ jne short 0974ch ; 75 de ; 0xf976c
+ xor ax, ax ; 31 c0 ; 0xf976e ahci.c:913
+ xor cx, cx ; 31 c9 ; 0xf9770
+ mov dx, si ; 89 f2 ; 0xf9772
+ xchg cx, ax ; 91 ; 0xf9774
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9775
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9779
+ out DX, eax ; 66 ef ; 0xf977b
+ mov dx, bx ; 89 da ; 0xf977d
+ in eax, DX ; 66 ed ; 0xf977f
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9781
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf9783
+ xchg dx, ax ; 92 ; 0xf9787
+ push strict byte 00000h ; 6a 00 ; 0xf9788 ahci.c:914
+ mov bx, strict word 0001fh ; bb 1f 00 ; 0xf978a
+ xor cx, cx ; 31 c9 ; 0xf978d
+ call 0874dh ; e8 bb ef ; 0xf978f
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf9792
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf9794
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf9797 ahci.c:919
+ jmp short 097bdh ; eb 20 ; 0xf979b ahci.c:920
+ xor al, al ; 30 c0 ; 0xf979d ahci.c:272
+ test al, al ; 84 c0 ; 0xf979f ahci.c:273
+ je short 097b4h ; 74 11 ; 0xf97a1
+ movzx bx, byte [bp-00ch] ; 0f b6 5e f4 ; 0xf97a3 ahci.c:925
+ xor ax, ax ; 31 c0 ; 0xf97a7
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf97a9
+ call 091b0h ; e8 01 fa ; 0xf97ac
+ dec byte [bp-00eh] ; fe 4e f2 ; 0xf97af ahci.c:926
+ je short 097f6h ; 74 42 ; 0xf97b2 ahci.c:927
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf97b4 ahci.c:930
+ cmp byte [bp-00ch], 020h ; 80 7e f4 20 ; 0xf97b7 ahci.c:931
+ jnc short 097f6h ; 73 39 ; 0xf97bb
+ movzx cx, byte [bp-00ch] ; 0f b6 4e f4 ; 0xf97bd
+ mov bx, strict word 00001h ; bb 01 00 ; 0xf97c1
+ xor di, di ; 31 ff ; 0xf97c4
+ jcxz 097ceh ; e3 06 ; 0xf97c6
+ sal bx, 1 ; d1 e3 ; 0xf97c8
+ rcl di, 1 ; d1 d7 ; 0xf97ca
+ loop 097c8h ; e2 fa ; 0xf97cc
+ mov ax, strict word 0000ch ; b8 0c 00 ; 0xf97ce
+ xor cx, cx ; 31 c9 ; 0xf97d1
+ mov dx, si ; 89 f2 ; 0xf97d3
+ xchg cx, ax ; 91 ; 0xf97d5
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf97d6
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf97da
+ out DX, eax ; 66 ef ; 0xf97dc
+ lea dx, [si+004h] ; 8d 54 04 ; 0xf97de
+ in eax, DX ; 66 ed ; 0xf97e1
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf97e3
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf97e5
+ xchg dx, ax ; 92 ; 0xf97e9
+ test dx, di ; 85 fa ; 0xf97ea
+ jne short 097f2h ; 75 04 ; 0xf97ec
+ test ax, bx ; 85 d8 ; 0xf97ee
+ je short 0979dh ; 74 ab ; 0xf97f0
+ mov AL, strict byte 001h ; b0 01 ; 0xf97f2
+ jmp short 0979fh ; eb a9 ; 0xf97f4
+ xor ax, ax ; 31 c0 ; 0xf97f6 ahci.c:933
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf97f8 ahci.c:934
+ pop di ; 5f ; 0xf97fb
+ pop si ; 5e ; 0xf97fc
+ pop dx ; 5a ; 0xf97fd
+ pop cx ; 59 ; 0xf97fe
+ pop bx ; 5b ; 0xf97ff
+ pop bp ; 5d ; 0xf9800
+ retn ; c3 ; 0xf9801
+ ; disGetNextSymbol 0xf9802 LB 0x843 -> off=0x17 cb=0000000000000116 uValue=00000000000f8219 'ahci_init'
+ db 00bh, 005h, 004h, 003h, 002h, 001h, 000h, 0e9h, 098h, 0c7h, 098h, 0cdh, 098h, 0d3h, 098h, 0d9h
+ db 098h, 0dfh, 098h, 0e5h, 098h, 0e9h, 098h
+ahci_init: ; 0xf9819 LB 0x116
+ push bp ; 55 ; 0xf9819 ahci.c:939
+ mov bp, sp ; 89 e5 ; 0xf981a
+ push si ; 56 ; 0xf981c
+ push di ; 57 ; 0xf981d
+ sub sp, strict byte 00008h ; 83 ec 08 ; 0xf981e
+ mov ax, 00601h ; b8 01 06 ; 0xf9821 ahci.c:943
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf9824
+ call 09d4fh ; e8 25 05 ; 0xf9827
+ mov bx, ax ; 89 c3 ; 0xf982a
+ cmp ax, strict word 0ffffh ; 3d ff ff ; 0xf982c ahci.c:944
+ je near 09928h ; 0f 84 f5 00 ; 0xf982f
+ xor al, al ; 30 c0 ; 0xf9833 ahci.c:949
+ shr ax, 008h ; c1 e8 08 ; 0xf9835
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf9838
+ mov byte [bp-008h], bl ; 88 5e f8 ; 0xf983b ahci.c:950
+ movzx dx, bl ; 0f b6 d3 ; 0xf983e ahci.c:955
+ xor ah, ah ; 30 e4 ; 0xf9841
+ mov bx, strict word 00034h ; bb 34 00 ; 0xf9843
+ call 09d9fh ; e8 56 05 ; 0xf9846
+ mov cl, al ; 88 c1 ; 0xf9849
+ test cl, cl ; 84 c9 ; 0xf984b ahci.c:957
+ je short 09872h ; 74 23 ; 0xf984d
+ movzx bx, cl ; 0f b6 d9 ; 0xf984f ahci.c:959
+ movzx di, byte [bp-008h] ; 0f b6 7e f8 ; 0xf9852
+ movzx si, byte [bp-00ah] ; 0f b6 76 f6 ; 0xf9856
+ mov dx, di ; 89 fa ; 0xf985a
+ mov ax, si ; 89 f0 ; 0xf985c
+ call 09d9fh ; e8 3e 05 ; 0xf985e
+ cmp AL, strict byte 012h ; 3c 12 ; 0xf9861 ahci.c:963
+ je short 09872h ; 74 0d ; 0xf9863
+ mov al, cl ; 88 c8 ; 0xf9865 ahci.c:967
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf9867
+ movzx bx, al ; 0f b6 d8 ; 0xf9869
+ mov dx, di ; 89 fa ; 0xf986c
+ mov ax, si ; 89 f0 ; 0xf986e
+ jmp short 09846h ; eb d4 ; 0xf9870 ahci.c:968
+ test cl, cl ; 84 c9 ; 0xf9872 ahci.c:970
+ je near 09928h ; 0f 84 b0 00 ; 0xf9874
+ add cl, 002h ; 80 c1 02 ; 0xf9878 ahci.c:977
+ movzx bx, cl ; 0f b6 d9 ; 0xf987b ahci.c:979
+ movzx si, byte [bp-008h] ; 0f b6 76 f8 ; 0xf987e
+ movzx di, byte [bp-00ah] ; 0f b6 7e f6 ; 0xf9882
+ mov dx, si ; 89 f2 ; 0xf9886
+ mov ax, di ; 89 f8 ; 0xf9888
+ call 09d9fh ; e8 12 05 ; 0xf988a
+ cmp AL, strict byte 010h ; 3c 10 ; 0xf988d ahci.c:980
+ jne near 09928h ; 0f 85 95 00 ; 0xf988f
+ mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xf9893 ahci.c:983
+ mov al, cl ; 88 c8 ; 0xf9897 ahci.c:985
+ add AL, strict byte 002h ; 04 02 ; 0xf9899
+ movzx bx, al ; 0f b6 d8 ; 0xf989b
+ mov dx, si ; 89 f2 ; 0xf989e
+ mov ax, di ; 89 f8 ; 0xf98a0
+ call 09dc3h ; e8 1e 05 ; 0xf98a2
+ mov dx, ax ; 89 c2 ; 0xf98a5
+ and ax, strict word 0000fh ; 25 0f 00 ; 0xf98a7 ahci.c:989
+ sub ax, strict word 00004h ; 2d 04 00 ; 0xf98aa
+ cmp ax, strict word 0000bh ; 3d 0b 00 ; 0xf98ad
+ jnbe short 098e9h ; 77 37 ; 0xf98b0
+ push CS ; 0e ; 0xf98b2
+ pop ES ; 07 ; 0xf98b3
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf98b4
+ mov di, 09802h ; bf 02 98 ; 0xf98b7
+ repne scasb ; f2 ae ; 0xf98ba
+ sal cx, 1 ; d1 e1 ; 0xf98bc
+ mov di, cx ; 89 cf ; 0xf98be
+ mov ax, word [cs:di-067f7h] ; 2e 8b 85 09 98 ; 0xf98c0
+ jmp ax ; ff e0 ; 0xf98c5
+ mov byte [bp-006h], 010h ; c6 46 fa 10 ; 0xf98c7 ahci.c:992
+ jmp short 098e9h ; eb 1c ; 0xf98cb ahci.c:993
+ mov byte [bp-006h], 014h ; c6 46 fa 14 ; 0xf98cd ahci.c:995
+ jmp short 098e9h ; eb 16 ; 0xf98d1 ahci.c:996
+ mov byte [bp-006h], 018h ; c6 46 fa 18 ; 0xf98d3 ahci.c:998
+ jmp short 098e9h ; eb 10 ; 0xf98d7 ahci.c:999
+ mov byte [bp-006h], 01ch ; c6 46 fa 1c ; 0xf98d9 ahci.c:1001
+ jmp short 098e9h ; eb 0a ; 0xf98dd ahci.c:1002
+ mov byte [bp-006h], 020h ; c6 46 fa 20 ; 0xf98df ahci.c:1004
+ jmp short 098e9h ; eb 04 ; 0xf98e3 ahci.c:1005
+ mov byte [bp-006h], 024h ; c6 46 fa 24 ; 0xf98e5 ahci.c:1007
+ mov cx, dx ; 89 d1 ; 0xf98e9 ahci.c:1016
+ shr cx, 004h ; c1 e9 04 ; 0xf98eb
+ sal cx, 002h ; c1 e1 02 ; 0xf98ee
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf98f1 ahci.c:1018
+ test al, al ; 84 c0 ; 0xf98f4
+ je short 09928h ; 74 30 ; 0xf98f6
+ movzx bx, al ; 0f b6 d8 ; 0xf98f8 ahci.c:1020
+ movzx di, byte [bp-008h] ; 0f b6 7e f8 ; 0xf98fb
+ movzx si, byte [bp-00ah] ; 0f b6 76 f6 ; 0xf98ff
+ mov dx, di ; 89 fa ; 0xf9903
+ mov ax, si ; 89 f0 ; 0xf9905
+ call 09de5h ; e8 db 04 ; 0xf9907
+ test AL, strict byte 001h ; a8 01 ; 0xf990a ahci.c:1024
+ je short 09928h ; 74 1a ; 0xf990c
+ and AL, strict byte 0f0h ; 24 f0 ; 0xf990e ahci.c:1027
+ add ax, cx ; 01 c8 ; 0xf9910
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf9912
+ mov cx, strict word 00007h ; b9 07 00 ; 0xf9915 ahci.c:1030
+ mov bx, strict word 00004h ; bb 04 00 ; 0xf9918
+ mov dx, di ; 89 fa ; 0xf991b
+ mov ax, si ; 89 f0 ; 0xf991d
+ call 09e0ch ; e8 ea 04 ; 0xf991f
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf9922 ahci.c:1033
+ call 096b3h ; e8 8b fd ; 0xf9925
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9928 ahci.c:1047
+ pop di ; 5f ; 0xf992b
+ pop si ; 5e ; 0xf992c
+ pop bp ; 5d ; 0xf992d
+ retn ; c3 ; 0xf992e
+ ; disGetNextSymbol 0xf992f LB 0x716 -> off=0x0 cb=000000000000001b uValue=00000000000f832f 'apm_out_str'
+apm_out_str: ; 0xf992f LB 0x1b
+ push bp ; 55 ; 0xf992f apm.c:146
+ mov bp, sp ; 89 e5 ; 0xf9930
+ push bx ; 53 ; 0xf9932
+ mov bx, ax ; 89 c3 ; 0xf9933
+ cmp byte [bx], 000h ; 80 3f 00 ; 0xf9935 apm.c:148
+ je short 09944h ; 74 0a ; 0xf9938
+ mov al, byte [bx] ; 8a 07 ; 0xf993a apm.c:149
+ out DX, AL ; ee ; 0xf993c
+ inc bx ; 43 ; 0xf993d
+ mov al, byte [bx] ; 8a 07 ; 0xf993e
+ db 00ah, 0c0h
+ ; or al, al ; 0a c0 ; 0xf9940
+ jne short 0993ch ; 75 f8 ; 0xf9942
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf9944 apm.c:150
+ pop bx ; 5b ; 0xf9947
+ pop bp ; 5d ; 0xf9948
+ retn ; c3 ; 0xf9949
+ ; disGetNextSymbol 0xf994a LB 0x6fb -> off=0x1e cb=00000000000000f5 uValue=00000000000f8368 'apm_function'
+ db 08bh, 099h, 057h, 09ah, 09dh, 099h, 0b8h, 099h, 057h, 09ah, 0e3h, 099h, 057h, 09ah, 0e8h, 099h
+ db 02ch, 09ah, 02ch, 09ah, 02ch, 09ah, 027h, 09ah, 02ch, 09ah, 02ch, 09ah, 020h, 09ah
+apm_function: ; 0xf9968 LB 0xf5
+ push bp ; 55 ; 0xf9968 apm.c:152
+ mov bp, sp ; 89 e5 ; 0xf9969
+ push si ; 56 ; 0xf996b
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf996c apm.c:156
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf9970 apm.c:157
+ xor ah, ah ; 30 e4 ; 0xf9973
+ cmp ax, strict word 0000eh ; 3d 0e 00 ; 0xf9975
+ jnbe near 09a2ch ; 0f 87 b0 00 ; 0xf9978
+ mov bx, ax ; 89 c3 ; 0xf997c
+ add bx, ax ; 01 c3 ; 0xf997e
+ mov dx, word [bp+018h] ; 8b 56 18 ; 0xf9980
+ or dl, 001h ; 80 ca 01 ; 0xf9983
+ jmp word [cs:bx-066b6h] ; 2e ff a7 4a 99 ; 0xf9986
+ mov word [bp+012h], 00102h ; c7 46 12 02 01 ; 0xf998b apm.c:159
+ mov word [bp+00ch], 0504dh ; c7 46 0c 4d 50 ; 0xf9990 apm.c:160
+ mov word [bp+010h], strict word 00003h ; c7 46 10 03 00 ; 0xf9995 apm.c:161
+ jmp near 09a57h ; e9 ba 00 ; 0xf999a apm.c:162
+ mov word [bp+012h], 0f000h ; c7 46 12 00 f0 ; 0xf999d apm.c:172
+ mov word [bp+00ch], 0a034h ; c7 46 0c 34 a0 ; 0xf99a2 apm.c:173
+ mov word [bp+010h], 0f000h ; c7 46 10 00 f0 ; 0xf99a7 apm.c:174
+ mov ax, strict word 0fff0h ; b8 f0 ff ; 0xf99ac apm.c:175
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf99af
+ mov word [bp+004h], ax ; 89 46 04 ; 0xf99b2 apm.c:176
+ jmp near 09a57h ; e9 9f 00 ; 0xf99b5 apm.c:177
+ mov word [bp+012h], 0f000h ; c7 46 12 00 f0 ; 0xf99b8 apm.c:183
+ mov word [bp+00ch], 0da40h ; c7 46 0c 40 da ; 0xf99bd apm.c:184
+ mov ax, 0f000h ; b8 00 f0 ; 0xf99c2 apm.c:185
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf99c5
+ mov word [bp+00eh], ax ; 89 46 0e ; 0xf99c8 apm.c:186
+ mov ax, strict word 0fff0h ; b8 f0 ff ; 0xf99cb apm.c:187
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf99ce
+ mov word [bp+004h], ax ; 89 46 04 ; 0xf99d1 apm.c:188
+ xor bx, bx ; 31 db ; 0xf99d4 apm.c:189
+ sal ebx, 010h ; 66 c1 e3 10 ; 0xf99d6
+ mov si, ax ; 89 c6 ; 0xf99da apm.c:190
+ sal esi, 010h ; 66 c1 e6 10 ; 0xf99dc
+ jmp near 09a57h ; e9 74 00 ; 0xf99e0 apm.c:191
+ sti ; fb ; 0xf99e3 apm.c:194
+ hlt ; f4 ; 0xf99e4 apm.c:195
+ jmp near 09a57h ; e9 6f 00 ; 0xf99e5 apm.c:196
+ cmp word [bp+010h], strict byte 00003h ; 83 7e 10 03 ; 0xf99e8 apm.c:200
+ je short 09a0dh ; 74 1f ; 0xf99ec
+ cmp word [bp+010h], strict byte 00002h ; 83 7e 10 02 ; 0xf99ee
+ je short 09a05h ; 74 11 ; 0xf99f2
+ cmp word [bp+010h], strict byte 00001h ; 83 7e 10 01 ; 0xf99f4
+ jne short 09a15h ; 75 1b ; 0xf99f8
+ mov dx, 0040fh ; ba 0f 04 ; 0xf99fa apm.c:202
+ mov ax, 00d22h ; b8 22 0d ; 0xf99fd
+ call 0992fh ; e8 2c ff ; 0xf9a00
+ jmp short 09a57h ; eb 52 ; 0xf9a03 apm.c:203
+ mov dx, 0040fh ; ba 0f 04 ; 0xf9a05 apm.c:205
+ mov ax, 00d2ah ; b8 2a 0d ; 0xf9a08
+ jmp short 09a00h ; eb f3 ; 0xf9a0b
+ mov dx, 0040fh ; ba 0f 04 ; 0xf9a0d apm.c:208
+ mov ax, 00d32h ; b8 32 0d ; 0xf9a10
+ jmp short 09a00h ; eb eb ; 0xf9a13
+ or ah, 00ah ; 80 cc 0a ; 0xf9a15 apm.c:211
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf9a18
+ mov word [bp+018h], dx ; 89 56 18 ; 0xf9a1b apm.c:212
+ jmp short 09a57h ; eb 37 ; 0xf9a1e apm.c:214
+ mov word [bp+012h], 00102h ; c7 46 12 02 01 ; 0xf9a20 apm.c:216
+ jmp short 09a57h ; eb 30 ; 0xf9a25 apm.c:217
+ or ah, 080h ; 80 cc 80 ; 0xf9a27 apm.c:224
+ jmp short 09a18h ; eb ec ; 0xf9a2a
+ mov bx, 00db2h ; bb b2 0d ; 0xf9a2c apm.c:228
+ mov cx, ds ; 8c d9 ; 0xf9a2f
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf9a31
+ call 019d3h ; e8 9c 7f ; 0xf9a34
+ push word [bp+00ch] ; ff 76 0c ; 0xf9a37
+ push word [bp+012h] ; ff 76 12 ; 0xf9a3a
+ push 00d3bh ; 68 3b 0d ; 0xf9a3d
+ push strict byte 00004h ; 6a 04 ; 0xf9a40
+ call 01a14h ; e8 cf 7f ; 0xf9a42
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf9a45
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf9a48 apm.c:229
+ xor ah, ah ; 30 e4 ; 0xf9a4b
+ or ah, 00ch ; 80 cc 0c ; 0xf9a4d
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf9a50
+ or byte [bp+018h], 001h ; 80 4e 18 01 ; 0xf9a53 apm.c:230
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf9a57 apm.c:232
+ pop si ; 5e ; 0xf9a5a
+ pop bp ; 5d ; 0xf9a5b
+ retn ; c3 ; 0xf9a5c
+ ; disGetNextSymbol 0xf9a5d LB 0x5e8 -> off=0x0 cb=0000000000000024 uValue=00000000000f845d 'pci16_select_reg'
+pci16_select_reg: ; 0xf9a5d LB 0x24
+ push bp ; 55 ; 0xf9a5d pcibios.c:188
+ mov bp, sp ; 89 e5 ; 0xf9a5e
+ push bx ; 53 ; 0xf9a60
+ and dl, 0fch ; 80 e2 fc ; 0xf9a61 pcibios.c:190
+ mov bx, dx ; 89 d3 ; 0xf9a64
+ mov dx, 00cf8h ; ba f8 0c ; 0xf9a66
+ movzx eax, ax ; 66 0f b7 c0 ; 0xf9a69
+ sal eax, 008h ; 66 c1 e0 08 ; 0xf9a6d
+ or eax, strict dword 080000000h ; 66 0d 00 00 00 80 ; 0xf9a71
+ db 08ah, 0c3h
+ ; mov al, bl ; 8a c3 ; 0xf9a77
+ out DX, eax ; 66 ef ; 0xf9a79
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf9a7b pcibios.c:191
+ pop bx ; 5b ; 0xf9a7e
+ pop bp ; 5d ; 0xf9a7f
+ retn ; c3 ; 0xf9a80
+ ; disGetNextSymbol 0xf9a81 LB 0x5c4 -> off=0x0 cb=00000000000000eb uValue=00000000000f8481 'pci16_find_device'
+pci16_find_device: ; 0xf9a81 LB 0xeb
+ push bp ; 55 ; 0xf9a81 pcibios.c:221
+ mov bp, sp ; 89 e5 ; 0xf9a82
+ push si ; 56 ; 0xf9a84
+ push di ; 57 ; 0xf9a85
+ sub sp, strict byte 0000ch ; 83 ec 0c ; 0xf9a86
+ push ax ; 50 ; 0xf9a89
+ push dx ; 52 ; 0xf9a8a
+ mov si, bx ; 89 de ; 0xf9a8b
+ mov di, cx ; 89 cf ; 0xf9a8d
+ test cx, cx ; 85 c9 ; 0xf9a8f pcibios.c:231
+ xor bx, bx ; 31 db ; 0xf9a91 pcibios.c:238
+ mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xf9a93 pcibios.c:239
+ test bl, 007h ; f6 c3 07 ; 0xf9a97 pcibios.c:249
+ jne short 09ac9h ; 75 2d ; 0xf9a9a
+ mov dx, strict word 0000eh ; ba 0e 00 ; 0xf9a9c pcibios.c:250
+ mov ax, bx ; 89 d8 ; 0xf9a9f
+ call 09a5dh ; e8 b9 ff ; 0xf9aa1
+ mov dx, 00cfeh ; ba fe 0c ; 0xf9aa4 pcibios.c:251
+ in AL, DX ; ec ; 0xf9aa7
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf9aa8
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf9aaa
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xf9aad pcibios.c:252
+ jne short 09ab7h ; 75 06 ; 0xf9aaf
+ add bx, strict byte 00008h ; 83 c3 08 ; 0xf9ab1 pcibios.c:253
+ jmp near 09b4ah ; e9 93 00 ; 0xf9ab4 pcibios.c:254
+ test byte [bp-006h], 080h ; f6 46 fa 80 ; 0xf9ab7 pcibios.c:256
+ je short 09ac4h ; 74 07 ; 0xf9abb
+ mov word [bp-00ah], strict word 00001h ; c7 46 f6 01 00 ; 0xf9abd pcibios.c:257
+ jmp short 09ac9h ; eb 05 ; 0xf9ac2 pcibios.c:258
+ mov word [bp-00ah], strict word 00008h ; c7 46 f6 08 00 ; 0xf9ac4 pcibios.c:259
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf9ac9 pcibios.c:270
+ and AL, strict byte 007h ; 24 07 ; 0xf9acc
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf9ace
+ jne short 09af1h ; 75 1f ; 0xf9ad0
+ mov ax, bx ; 89 d8 ; 0xf9ad2
+ shr ax, 008h ; c1 e8 08 ; 0xf9ad4
+ test ax, ax ; 85 c0 ; 0xf9ad7
+ jne short 09af1h ; 75 16 ; 0xf9ad9
+ mov dx, strict word 0001ah ; ba 1a 00 ; 0xf9adb pcibios.c:272
+ mov ax, bx ; 89 d8 ; 0xf9ade
+ call 09a5dh ; e8 7a ff ; 0xf9ae0
+ mov dx, 00cfeh ; ba fe 0c ; 0xf9ae3 pcibios.c:273
+ in AL, DX ; ec ; 0xf9ae6
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf9ae7
+ cmp al, byte [bp-008h] ; 3a 46 f8 ; 0xf9ae9 pcibios.c:274
+ jbe short 09af1h ; 76 03 ; 0xf9aec
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf9aee pcibios.c:275
+ test di, di ; 85 ff ; 0xf9af1 pcibios.c:279
+ je short 09afah ; 74 05 ; 0xf9af3
+ mov dx, strict word 00008h ; ba 08 00 ; 0xf9af5
+ jmp short 09afch ; eb 02 ; 0xf9af8
+ xor dx, dx ; 31 d2 ; 0xf9afa
+ mov ax, bx ; 89 d8 ; 0xf9afc
+ call 09a5dh ; e8 5c ff ; 0xf9afe
+ mov dx, 00cfch ; ba fc 0c ; 0xf9b01 pcibios.c:280
+ in eax, DX ; 66 ed ; 0xf9b04
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9b06
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf9b08
+ xchg dx, ax ; 92 ; 0xf9b0c
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf9b0d
+ mov word [bp-00ch], dx ; 89 56 f4 ; 0xf9b10
+ mov word [bp-010h], strict word 00000h ; c7 46 f0 00 00 ; 0xf9b13 pcibios.c:281
+ test di, di ; 85 ff ; 0xf9b18 pcibios.c:284
+ je short 09b2bh ; 74 0f ; 0xf9b1a
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf9b1c pcibios.c:285
+ shr dx, 1 ; d1 ea ; 0xf9b1f
+ rcr ax, 1 ; d1 d8 ; 0xf9b21
+ loop 09b1fh ; e2 fa ; 0xf9b23
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf9b25
+ mov word [bp-00ch], dx ; 89 56 f4 ; 0xf9b28
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf9b2b pcibios.c:292
+ cmp ax, word [bp-014h] ; 3b 46 ec ; 0xf9b2e
+ jne short 09b3bh ; 75 08 ; 0xf9b31
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf9b33
+ cmp ax, word [bp-012h] ; 3b 46 ee ; 0xf9b36
+ je short 09b41h ; 74 06 ; 0xf9b39
+ cmp word [bp-010h], strict byte 00000h ; 83 7e f0 00 ; 0xf9b3b pcibios.c:293
+ je short 09b47h ; 74 06 ; 0xf9b3f
+ dec si ; 4e ; 0xf9b41
+ cmp si, strict byte 0ffffh ; 83 fe ff ; 0xf9b42
+ je short 09b59h ; 74 12 ; 0xf9b45
+ add bx, word [bp-00ah] ; 03 5e f6 ; 0xf9b47 pcibios.c:301
+ mov dx, bx ; 89 da ; 0xf9b4a pcibios.c:302
+ shr dx, 008h ; c1 ea 08 ; 0xf9b4c
+ movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xf9b4f
+ cmp dx, ax ; 39 c2 ; 0xf9b53
+ jbe near 09a97h ; 0f 86 3e ff ; 0xf9b55
+ cmp si, strict byte 0ffffh ; 83 fe ff ; 0xf9b59 pcibios.c:304
+ jne short 09b62h ; 75 04 ; 0xf9b5c pcibios.c:308
+ mov ax, bx ; 89 d8 ; 0xf9b5e
+ jmp short 09b65h ; eb 03 ; 0xf9b60
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf9b62
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9b65 pcibios.c:309
+ pop di ; 5f ; 0xf9b68
+ pop si ; 5e ; 0xf9b69
+ pop bp ; 5d ; 0xf9b6a
+ retn ; c3 ; 0xf9b6b
+ ; disGetNextSymbol 0xf9b6c LB 0x4d9 -> off=0xc cb=00000000000001d7 uValue=00000000000f8578 'pci16_function'
+ db 05ah, 09ch, 074h, 09ch, 087h, 09ch, 09ch, 09ch, 0afh, 09ch, 0c2h, 09ch
+pci16_function: ; 0xf9b78 LB 0x1d7
+ push bp ; 55 ; 0xf9b78 pcibios.c:311
+ mov bp, sp ; 89 e5 ; 0xf9b79
+ push si ; 56 ; 0xf9b7b
+ push di ; 57 ; 0xf9b7c
+ push ax ; 50 ; 0xf9b7d
+ push ax ; 50 ; 0xf9b7e
+ and word [bp+020h], 000ffh ; 81 66 20 ff 00 ; 0xf9b7f pcibios.c:318
+ and word [bp+02ch], strict byte 0fffeh ; 83 66 2c fe ; 0xf9b84 pcibios.c:319
+ mov bx, word [bp+020h] ; 8b 5e 20 ; 0xf9b88 pcibios.c:321
+ xor bh, bh ; 30 ff ; 0xf9b8b
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf9b8d
+ xor ah, ah ; 30 e4 ; 0xf9b90
+ cmp bx, strict byte 00003h ; 83 fb 03 ; 0xf9b92
+ jc short 09bb1h ; 72 1a ; 0xf9b95
+ jbe short 09c09h ; 76 70 ; 0xf9b97
+ cmp bx, strict byte 0000eh ; 83 fb 0e ; 0xf9b99
+ je near 09cd6h ; 0f 84 36 01 ; 0xf9b9c
+ cmp bx, strict byte 00008h ; 83 fb 08 ; 0xf9ba0
+ jc near 09d1bh ; 0f 82 74 01 ; 0xf9ba3
+ cmp bx, strict byte 0000dh ; 83 fb 0d ; 0xf9ba7
+ jbe near 09c2eh ; 0f 86 80 00 ; 0xf9baa
+ jmp near 09d1bh ; e9 6a 01 ; 0xf9bae
+ cmp bx, strict byte 00002h ; 83 fb 02 ; 0xf9bb1
+ je short 09bd9h ; 74 23 ; 0xf9bb4
+ cmp bx, strict byte 00001h ; 83 fb 01 ; 0xf9bb6
+ jne near 09d1bh ; 0f 85 5e 01 ; 0xf9bb9
+ mov word [bp+020h], strict word 00001h ; c7 46 20 01 00 ; 0xf9bbd pcibios.c:323
+ mov word [bp+014h], 00210h ; c7 46 14 10 02 ; 0xf9bc2 pcibios.c:324
+ mov word [bp+01ch], strict word 00000h ; c7 46 1c 00 00 ; 0xf9bc7 pcibios.c:326
+ mov word [bp+018h], 04350h ; c7 46 18 50 43 ; 0xf9bcc pcibios.c:327
+ mov word [bp+01ah], 02049h ; c7 46 1a 49 20 ; 0xf9bd1
+ jmp near 09d48h ; e9 6f 01 ; 0xf9bd6 pcibios.c:328
+ cmp word [bp+018h], strict byte 0ffffh ; 83 7e 18 ff ; 0xf9bd9 pcibios.c:333
+ jne short 09be5h ; 75 06 ; 0xf9bdd
+ or ah, 083h ; 80 cc 83 ; 0xf9bdf pcibios.c:334
+ jmp near 09d41h ; e9 5c 01 ; 0xf9be2 pcibios.c:335
+ mov bx, word [bp+008h] ; 8b 5e 08 ; 0xf9be5 pcibios.c:337
+ mov dx, word [bp+01ch] ; 8b 56 1c ; 0xf9be8
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf9beb
+ xor cx, cx ; 31 c9 ; 0xf9bee
+ call 09a81h ; e8 8e fe ; 0xf9bf0
+ cmp ax, strict word 0ffffh ; 3d ff ff ; 0xf9bf3 pcibios.c:338
+ jne short 09c03h ; 75 0b ; 0xf9bf6
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf9bf8 pcibios.c:339
+ xor ah, ah ; 30 e4 ; 0xf9bfb
+ or ah, 086h ; 80 cc 86 ; 0xf9bfd
+ jmp near 09d41h ; e9 3e 01 ; 0xf9c00
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf9c03 pcibios.c:340
+ jmp near 09d48h ; e9 3f 01 ; 0xf9c06 pcibios.c:345
+ mov bx, word [bp+008h] ; 8b 5e 08 ; 0xf9c09 pcibios.c:347
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf9c0c
+ mov dx, word [bp+01eh] ; 8b 56 1e ; 0xf9c0f
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf9c12
+ call 09a81h ; e8 69 fe ; 0xf9c15
+ cmp ax, strict word 0ffffh ; 3d ff ff ; 0xf9c18 pcibios.c:348
+ jne short 09c28h ; 75 0b ; 0xf9c1b
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf9c1d pcibios.c:349
+ xor ah, ah ; 30 e4 ; 0xf9c20
+ or ah, 086h ; 80 cc 86 ; 0xf9c22
+ jmp near 09d41h ; e9 19 01 ; 0xf9c25 pcibios.c:350
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf9c28 pcibios.c:352
+ jmp near 09d48h ; e9 1a 01 ; 0xf9c2b pcibios.c:354
+ cmp word [bp+004h], 00100h ; 81 7e 04 00 01 ; 0xf9c2e pcibios.c:361
+ jc short 09c3bh ; 72 06 ; 0xf9c33
+ or ah, 087h ; 80 cc 87 ; 0xf9c35 pcibios.c:362
+ jmp near 09d41h ; e9 06 01 ; 0xf9c38 pcibios.c:363
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf9c3b pcibios.c:365
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf9c3e
+ call 09a5dh ; e8 19 fe ; 0xf9c41
+ mov bx, word [bp+020h] ; 8b 5e 20 ; 0xf9c44 pcibios.c:366
+ xor bh, bh ; 30 ff ; 0xf9c47
+ sub bx, strict byte 00008h ; 83 eb 08 ; 0xf9c49
+ cmp bx, strict byte 00005h ; 83 fb 05 ; 0xf9c4c
+ jnbe near 09d48h ; 0f 87 f5 00 ; 0xf9c4f
+ add bx, bx ; 01 db ; 0xf9c53
+ jmp word [cs:bx-06494h] ; 2e ff a7 6c 9b ; 0xf9c55
+ mov bx, word [bp+01ch] ; 8b 5e 1c ; 0xf9c5a pcibios.c:368
+ xor bl, bl ; 30 db ; 0xf9c5d
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf9c5f
+ and dx, strict byte 00003h ; 83 e2 03 ; 0xf9c62
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xf9c65
+ in AL, DX ; ec ; 0xf9c69
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf9c6a
+ or bx, ax ; 09 c3 ; 0xf9c6c
+ mov word [bp+01ch], bx ; 89 5e 1c ; 0xf9c6e
+ jmp near 09d48h ; e9 d4 00 ; 0xf9c71 pcibios.c:369
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf9c74 pcibios.c:371
+ xor dh, dh ; 30 f6 ; 0xf9c77
+ and dl, 002h ; 80 e2 02 ; 0xf9c79
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xf9c7c
+ in ax, DX ; ed ; 0xf9c80
+ mov word [bp+01ch], ax ; 89 46 1c ; 0xf9c81
+ jmp near 09d48h ; e9 c1 00 ; 0xf9c84 pcibios.c:372
+ mov dx, 00cfch ; ba fc 0c ; 0xf9c87 pcibios.c:374
+ in eax, DX ; 66 ed ; 0xf9c8a
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9c8c
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf9c8e
+ xchg dx, ax ; 92 ; 0xf9c92
+ mov word [bp+01ch], ax ; 89 46 1c ; 0xf9c93
+ mov word [bp+01eh], dx ; 89 56 1e ; 0xf9c96
+ jmp near 09d48h ; e9 ac 00 ; 0xf9c99 pcibios.c:375
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf9c9c pcibios.c:377
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf9c9f
+ xor dh, dh ; 30 f6 ; 0xf9ca2
+ and dl, 003h ; 80 e2 03 ; 0xf9ca4
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xf9ca7
+ out DX, AL ; ee ; 0xf9cab
+ jmp near 09d48h ; e9 99 00 ; 0xf9cac pcibios.c:378
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf9caf pcibios.c:380
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf9cb2
+ xor dh, dh ; 30 f6 ; 0xf9cb5
+ and dl, 002h ; 80 e2 02 ; 0xf9cb7
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xf9cba
+ out DX, ax ; ef ; 0xf9cbe
+ jmp near 09d48h ; e9 86 00 ; 0xf9cbf pcibios.c:381
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf9cc2 pcibios.c:383
+ mov cx, word [bp+01eh] ; 8b 4e 1e ; 0xf9cc5
+ mov dx, 00cfch ; ba fc 0c ; 0xf9cc8
+ xchg cx, ax ; 91 ; 0xf9ccb
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9ccc
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9cd0
+ out DX, eax ; 66 ef ; 0xf9cd2
+ jmp short 09d48h ; eb 72 ; 0xf9cd4 pcibios.c:387
+ mov bx, word [bp+004h] ; 8b 5e 04 ; 0xf9cd6 pcibios.c:389
+ mov es, [bp+026h] ; 8e 46 26 ; 0xf9cd9
+ mov word [bp-008h], bx ; 89 5e f8 ; 0xf9cdc
+ mov [bp-006h], es ; 8c 46 fa ; 0xf9cdf
+ mov cx, word [0f370h] ; 8b 0e 70 f3 ; 0xf9ce2 pcibios.c:393
+ cmp cx, word [es:bx] ; 26 3b 0f ; 0xf9ce6
+ jbe short 09cfch ; 76 11 ; 0xf9ce9
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf9ceb pcibios.c:394
+ xor ah, ah ; 30 e4 ; 0xf9cee
+ or ah, 089h ; 80 cc 89 ; 0xf9cf0
+ mov word [bp+020h], ax ; 89 46 20 ; 0xf9cf3
+ or word [bp+02ch], strict byte 00001h ; 83 4e 2c 01 ; 0xf9cf6 pcibios.c:395
+ jmp short 09d10h ; eb 14 ; 0xf9cfa pcibios.c:396
+ les di, [es:bx+002h] ; 26 c4 7f 02 ; 0xf9cfc pcibios.c:397
+ mov si, 0f190h ; be 90 f1 ; 0xf9d00
+ mov dx, ds ; 8c da ; 0xf9d03
+ push DS ; 1e ; 0xf9d05
+ mov ds, dx ; 8e da ; 0xf9d06
+ rep movsb ; f3 a4 ; 0xf9d08
+ pop DS ; 1f ; 0xf9d0a
+ mov word [bp+014h], 00a00h ; c7 46 14 00 0a ; 0xf9d0b pcibios.c:399
+ mov ax, word [0f370h] ; a1 70 f3 ; 0xf9d10 pcibios.c:401
+ les bx, [bp-008h] ; c4 5e f8 ; 0xf9d13
+ mov word [es:bx], ax ; 26 89 07 ; 0xf9d16
+ jmp short 09d48h ; eb 2d ; 0xf9d19 pcibios.c:402
+ mov bx, 00db2h ; bb b2 0d ; 0xf9d1b pcibios.c:404
+ mov cx, ds ; 8c d9 ; 0xf9d1e
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf9d20
+ call 019d3h ; e8 ad 7c ; 0xf9d23
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf9d26
+ push ax ; 50 ; 0xf9d29
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf9d2a
+ push ax ; 50 ; 0xf9d2d
+ push 00d6eh ; 68 6e 0d ; 0xf9d2e
+ push strict byte 00004h ; 6a 04 ; 0xf9d31
+ call 01a14h ; e8 de 7c ; 0xf9d33
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf9d36
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf9d39 pcibios.c:405
+ xor ah, ah ; 30 e4 ; 0xf9d3c
+ or ah, 081h ; 80 cc 81 ; 0xf9d3e
+ mov word [bp+020h], ax ; 89 46 20 ; 0xf9d41
+ or word [bp+02ch], strict byte 00001h ; 83 4e 2c 01 ; 0xf9d44 pcibios.c:406
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9d48 pcibios.c:408
+ pop di ; 5f ; 0xf9d4b
+ pop si ; 5e ; 0xf9d4c
+ pop bp ; 5d ; 0xf9d4d
+ retn ; c3 ; 0xf9d4e
+ ; disGetNextSymbol 0xf9d4f LB 0x2f6 -> off=0x0 cb=000000000000002b uValue=00000000000f874f 'pci_find_classcode'
+pci_find_classcode: ; 0xf9d4f LB 0x2b
+ push bp ; 55 ; 0xf9d4f pciutil.c:126
+ mov bp, sp ; 89 e5 ; 0xf9d50
+ push bx ; 53 ; 0xf9d52
+ push cx ; 51 ; 0xf9d53
+ push si ; 56 ; 0xf9d54
+ mov cx, dx ; 89 d1 ; 0xf9d55
+ xor si, si ; 31 f6 ; 0xf9d57 pciutil.c:129
+ mov dx, ax ; 89 c2 ; 0xf9d59
+ mov ax, 0b103h ; b8 03 b1 ; 0xf9d5b
+ sal ecx, 010h ; 66 c1 e1 10 ; 0xf9d5e
+ db 08bh, 0cah
+ ; mov cx, dx ; 8b ca ; 0xf9d62
+ int 01ah ; cd 1a ; 0xf9d64
+ cmp ah, 000h ; 80 fc 00 ; 0xf9d66
+ je near 09d70h ; 0f 84 03 00 ; 0xf9d69
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf9d6d
+ mov ax, bx ; 89 d8 ; 0xf9d70
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf9d72 pciutil.c:133
+ pop si ; 5e ; 0xf9d75
+ pop cx ; 59 ; 0xf9d76
+ pop bx ; 5b ; 0xf9d77
+ pop bp ; 5d ; 0xf9d78
+ retn ; c3 ; 0xf9d79
+ ; disGetNextSymbol 0xf9d7a LB 0x2cb -> off=0x0 cb=0000000000000025 uValue=00000000000f877a 'pci_find_device'
+pci_find_device: ; 0xf9d7a LB 0x25
+ push bp ; 55 ; 0xf9d7a pciutil.c:146
+ mov bp, sp ; 89 e5 ; 0xf9d7b
+ push bx ; 53 ; 0xf9d7d
+ push cx ; 51 ; 0xf9d7e
+ push si ; 56 ; 0xf9d7f
+ mov cx, dx ; 89 d1 ; 0xf9d80
+ xor si, si ; 31 f6 ; 0xf9d82 pciutil.c:148
+ mov dx, ax ; 89 c2 ; 0xf9d84
+ mov ax, 0b102h ; b8 02 b1 ; 0xf9d86
+ int 01ah ; cd 1a ; 0xf9d89
+ cmp ah, 000h ; 80 fc 00 ; 0xf9d8b
+ je near 09d95h ; 0f 84 03 00 ; 0xf9d8e
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf9d92
+ mov ax, bx ; 89 d8 ; 0xf9d95
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf9d97 pciutil.c:149
+ pop si ; 5e ; 0xf9d9a
+ pop cx ; 59 ; 0xf9d9b
+ pop bx ; 5b ; 0xf9d9c
+ pop bp ; 5d ; 0xf9d9d
+ retn ; c3 ; 0xf9d9e
+ ; disGetNextSymbol 0xf9d9f LB 0x2a6 -> off=0x0 cb=0000000000000024 uValue=00000000000f879f 'pci_read_config_byte'
+pci_read_config_byte: ; 0xf9d9f LB 0x24
+ push bp ; 55 ; 0xf9d9f pciutil.c:151
+ mov bp, sp ; 89 e5 ; 0xf9da0
+ push cx ; 51 ; 0xf9da2
+ push di ; 57 ; 0xf9da3
+ movzx di, bl ; 0f b6 fb ; 0xf9da4 pciutil.c:153
+ movzx bx, al ; 0f b6 d8 ; 0xf9da7
+ sal bx, 008h ; c1 e3 08 ; 0xf9daa
+ movzx ax, dl ; 0f b6 c2 ; 0xf9dad
+ or bx, ax ; 09 c3 ; 0xf9db0
+ mov ax, 0b108h ; b8 08 b1 ; 0xf9db2
+ int 01ah ; cd 1a ; 0xf9db5
+ movzx ax, cl ; 0f b6 c1 ; 0xf9db7
+ xor dx, dx ; 31 d2 ; 0xf9dba pciutil.c:154
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9dbc
+ pop di ; 5f ; 0xf9dbf
+ pop cx ; 59 ; 0xf9dc0
+ pop bp ; 5d ; 0xf9dc1
+ retn ; c3 ; 0xf9dc2
+ ; disGetNextSymbol 0xf9dc3 LB 0x282 -> off=0x0 cb=0000000000000022 uValue=00000000000f87c3 'pci_read_config_word'
+pci_read_config_word: ; 0xf9dc3 LB 0x22
+ push bp ; 55 ; 0xf9dc3 pciutil.c:156
+ mov bp, sp ; 89 e5 ; 0xf9dc4
+ push cx ; 51 ; 0xf9dc6
+ push di ; 57 ; 0xf9dc7
+ movzx di, bl ; 0f b6 fb ; 0xf9dc8 pciutil.c:158
+ xor ah, ah ; 30 e4 ; 0xf9dcb
+ sal ax, 008h ; c1 e0 08 ; 0xf9dcd
+ movzx bx, dl ; 0f b6 da ; 0xf9dd0
+ or bx, ax ; 09 c3 ; 0xf9dd3
+ mov ax, 0b109h ; b8 09 b1 ; 0xf9dd5
+ int 01ah ; cd 1a ; 0xf9dd8
+ mov ax, cx ; 89 c8 ; 0xf9dda
+ xor dx, dx ; 31 d2 ; 0xf9ddc pciutil.c:159
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9dde
+ pop di ; 5f ; 0xf9de1
+ pop cx ; 59 ; 0xf9de2
+ pop bp ; 5d ; 0xf9de3
+ retn ; c3 ; 0xf9de4
+ ; disGetNextSymbol 0xf9de5 LB 0x260 -> off=0x0 cb=0000000000000027 uValue=00000000000f87e5 'pci_read_config_dword'
+pci_read_config_dword: ; 0xf9de5 LB 0x27
+ push bp ; 55 ; 0xf9de5 pciutil.c:161
+ mov bp, sp ; 89 e5 ; 0xf9de6
+ push cx ; 51 ; 0xf9de8
+ push di ; 57 ; 0xf9de9
+ movzx di, bl ; 0f b6 fb ; 0xf9dea pciutil.c:164
+ movzx bx, al ; 0f b6 d8 ; 0xf9ded
+ sal bx, 008h ; c1 e3 08 ; 0xf9df0
+ movzx ax, dl ; 0f b6 c2 ; 0xf9df3
+ or bx, ax ; 09 c3 ; 0xf9df6
+ mov ax, 0b10ah ; b8 0a b1 ; 0xf9df8
+ int 01ah ; cd 1a ; 0xf9dfb
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9dfd
+ shr ecx, 010h ; 66 c1 e9 10 ; 0xf9dff
+ mov dx, cx ; 89 ca ; 0xf9e03
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9e05 pciutil.c:169
+ pop di ; 5f ; 0xf9e08
+ pop cx ; 59 ; 0xf9e09
+ pop bp ; 5d ; 0xf9e0a
+ retn ; c3 ; 0xf9e0b
+ ; disGetNextSymbol 0xf9e0c LB 0x239 -> off=0x0 cb=000000000000001c uValue=00000000000f880c 'pci_write_config_word'
+pci_write_config_word: ; 0xf9e0c LB 0x1c
+ push bp ; 55 ; 0xf9e0c pciutil.c:171
+ mov bp, sp ; 89 e5 ; 0xf9e0d
+ push di ; 57 ; 0xf9e0f
+ movzx di, bl ; 0f b6 fb ; 0xf9e10 pciutil.c:173
+ xor ah, ah ; 30 e4 ; 0xf9e13
+ sal ax, 008h ; c1 e0 08 ; 0xf9e15
+ movzx bx, dl ; 0f b6 da ; 0xf9e18
+ or bx, ax ; 09 c3 ; 0xf9e1b
+ mov ax, 0b10ch ; b8 0c b1 ; 0xf9e1d
+ int 01ah ; cd 1a ; 0xf9e20
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf9e22 pciutil.c:174
+ pop di ; 5f ; 0xf9e25
+ pop bp ; 5d ; 0xf9e26
+ retn ; c3 ; 0xf9e27
+ ; disGetNextSymbol 0xf9e28 LB 0x21d -> off=0x0 cb=000000000000001d uValue=00000000000f8828 'vds_is_present'
+vds_is_present: ; 0xf9e28 LB 0x1d
+ push bx ; 53 ; 0xf9e28 vds.c:32
+ push bp ; 55 ; 0xf9e29
+ mov bp, sp ; 89 e5 ; 0xf9e2a
+ mov bx, strict word 0007bh ; bb 7b 00 ; 0xf9e2c vds.c:36
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf9e2f
+ mov es, ax ; 8e c0 ; 0xf9e32
+ test byte [es:bx], 020h ; 26 f6 07 20 ; 0xf9e34 vds.c:37
+ je short 09e40h ; 74 06 ; 0xf9e38
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf9e3a
+ pop bp ; 5d ; 0xf9e3d
+ pop bx ; 5b ; 0xf9e3e
+ retn ; c3 ; 0xf9e3f
+ xor ax, ax ; 31 c0 ; 0xf9e40
+ pop bp ; 5d ; 0xf9e42 vds.c:38
+ pop bx ; 5b ; 0xf9e43
+ retn ; c3 ; 0xf9e44
+ ; disGetNextSymbol 0xf9e45 LB 0x200 -> off=0x0 cb=000000000000001e uValue=00000000000f8845 'vds_real_to_lin'
+vds_real_to_lin: ; 0xf9e45 LB 0x1e
+ push bx ; 53 ; 0xf9e45 vds.c:67
+ push cx ; 51 ; 0xf9e46
+ push bp ; 55 ; 0xf9e47
+ mov bp, sp ; 89 e5 ; 0xf9e48
+ mov bx, ax ; 89 c3 ; 0xf9e4a
+ mov ax, dx ; 89 d0 ; 0xf9e4c
+ xor dx, dx ; 31 d2 ; 0xf9e4e vds.c:69
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf9e50
+ sal ax, 1 ; d1 e0 ; 0xf9e53
+ rcl dx, 1 ; d1 d2 ; 0xf9e55
+ loop 09e53h ; e2 fa ; 0xf9e57
+ xor cx, cx ; 31 c9 ; 0xf9e59
+ add ax, bx ; 01 d8 ; 0xf9e5b
+ adc dx, cx ; 11 ca ; 0xf9e5d
+ pop bp ; 5d ; 0xf9e5f vds.c:70
+ pop cx ; 59 ; 0xf9e60
+ pop bx ; 5b ; 0xf9e61
+ retn ; c3 ; 0xf9e62
+ ; disGetNextSymbol 0xf9e63 LB 0x1e2 -> off=0x0 cb=0000000000000079 uValue=00000000000f8863 'vds_build_sg_list'
+vds_build_sg_list: ; 0xf9e63 LB 0x79
+ push bp ; 55 ; 0xf9e63 vds.c:77
+ mov bp, sp ; 89 e5 ; 0xf9e64
+ push si ; 56 ; 0xf9e66
+ push di ; 57 ; 0xf9e67
+ mov di, ax ; 89 c7 ; 0xf9e68
+ mov si, dx ; 89 d6 ; 0xf9e6a
+ mov ax, bx ; 89 d8 ; 0xf9e6c
+ mov dx, cx ; 89 ca ; 0xf9e6e
+ mov bx, word [bp+004h] ; 8b 5e 04 ; 0xf9e70 vds.c:82
+ mov es, si ; 8e c6 ; 0xf9e73
+ mov word [es:di], bx ; 26 89 1d ; 0xf9e75
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf9e78
+ mov word [es:di+002h], bx ; 26 89 5d 02 ; 0xf9e7b
+ call 09e45h ; e8 c3 ff ; 0xf9e7f vds.c:83
+ mov es, si ; 8e c6 ; 0xf9e82
+ mov word [es:di+004h], ax ; 26 89 45 04 ; 0xf9e84
+ mov word [es:di+006h], dx ; 26 89 55 06 ; 0xf9e88
+ mov word [es:di+008h], strict word 00000h ; 26 c7 45 08 00 00 ; 0xf9e8c vds.c:84
+ call 09e28h ; e8 93 ff ; 0xf9e92 vds.c:85
+ test ax, ax ; 85 c0 ; 0xf9e95
+ je short 09each ; 74 13 ; 0xf9e97
+ mov es, si ; 8e c6 ; 0xf9e99 vds.c:87
+ mov ax, 08105h ; b8 05 81 ; 0xf9e9b
+ mov dx, strict word 00000h ; ba 00 00 ; 0xf9e9e
+ int 04bh ; cd 4b ; 0xf9ea1
+ jc near 09ea9h ; 0f 82 02 00 ; 0xf9ea3
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xf9ea7
+ cbw ; 98 ; 0xf9ea9
+ jmp short 09ed3h ; eb 27 ; 0xf9eaa vds.c:88
+ mov es, si ; 8e c6 ; 0xf9eac vds.c:90
+ mov word [es:di+00eh], strict word 00001h ; 26 c7 45 0e 01 00 ; 0xf9eae
+ mov dx, word [es:di+004h] ; 26 8b 55 04 ; 0xf9eb4 vds.c:91
+ mov ax, word [es:di+006h] ; 26 8b 45 06 ; 0xf9eb8
+ mov word [es:di+010h], dx ; 26 89 55 10 ; 0xf9ebc
+ mov word [es:di+012h], ax ; 26 89 45 12 ; 0xf9ec0
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf9ec4 vds.c:92
+ mov word [es:di+014h], ax ; 26 89 45 14 ; 0xf9ec7
+ mov ax, bx ; 89 d8 ; 0xf9ecb
+ mov word [es:di+016h], bx ; 26 89 5d 16 ; 0xf9ecd
+ xor ax, bx ; 31 d8 ; 0xf9ed1 vds.c:93
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9ed3 vds.c:96
+ pop di ; 5f ; 0xf9ed6
+ pop si ; 5e ; 0xf9ed7
+ pop bp ; 5d ; 0xf9ed8
+ retn 00004h ; c2 04 00 ; 0xf9ed9
+ ; disGetNextSymbol 0xf9edc LB 0x169 -> off=0x0 cb=0000000000000030 uValue=00000000000f88dc 'vds_free_sg_list'
+vds_free_sg_list: ; 0xf9edc LB 0x30
+ push bp ; 55 ; 0xf9edc vds.c:102
+ mov bp, sp ; 89 e5 ; 0xf9edd
+ push bx ; 53 ; 0xf9edf
+ push di ; 57 ; 0xf9ee0
+ mov bx, ax ; 89 c3 ; 0xf9ee1
+ call 09e28h ; e8 42 ff ; 0xf9ee3 vds.c:106
+ test ax, ax ; 85 c0 ; 0xf9ee6
+ je short 09efdh ; 74 13 ; 0xf9ee8
+ mov di, bx ; 89 df ; 0xf9eea vds.c:108
+ mov es, dx ; 8e c2 ; 0xf9eec
+ mov ax, 08106h ; b8 06 81 ; 0xf9eee
+ mov dx, strict word 00000h ; ba 00 00 ; 0xf9ef1
+ int 04bh ; cd 4b ; 0xf9ef4
+ jc near 09efch ; 0f 82 02 00 ; 0xf9ef6
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xf9efa
+ cbw ; 98 ; 0xf9efc
+ mov es, dx ; 8e c2 ; 0xf9efd vds.c:116
+ mov word [es:bx+00eh], strict word 00000h ; 26 c7 47 0e 00 00 ; 0xf9eff
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9f05 vds.c:118
+ pop di ; 5f ; 0xf9f08
+ pop bx ; 5b ; 0xf9f09
+ pop bp ; 5d ; 0xf9f0a
+ retn ; c3 ; 0xf9f0b
+ ; disGetNextSymbol 0xf9f0c LB 0x139 -> off=0x4 cb=0000000000000040 uValue=00000000000f8910 '__U4M'
+ db 000h, 000h, 000h, 000h
+__U4M: ; 0xf9f10 LB 0x40
+ pushfw ; 9c ; 0xf9f10 __U4M.asm:37
+ push eax ; 66 50 ; 0xf9f11 __U4M.asm:40
+ push edx ; 66 52 ; 0xf9f13 __U4M.asm:41
+ push ecx ; 66 51 ; 0xf9f15 __U4M.asm:42
+ rol eax, 010h ; 66 c1 c0 10 ; 0xf9f17 __U4M.asm:44
+ db 08bh, 0c2h
+ ; mov ax, dx ; 8b c2 ; 0xf9f1b __U4M.asm:45
+ ror eax, 010h ; 66 c1 c8 10 ; 0xf9f1d __U4M.asm:46
+ db 066h, 033h, 0d2h
+ ; xor edx, edx ; 66 33 d2 ; 0xf9f21 __U4M.asm:47
+ shr ecx, 010h ; 66 c1 e9 10 ; 0xf9f24 __U4M.asm:49
+ db 08bh, 0cbh
+ ; mov cx, bx ; 8b cb ; 0xf9f28 __U4M.asm:50
+ mul ecx ; 66 f7 e1 ; 0xf9f2a __U4M.asm:52
+ pop ecx ; 66 59 ; 0xf9f2d __U4M.asm:54
+ pop edx ; 66 5a ; 0xf9f2f __U4M.asm:56
+ ror eax, 010h ; 66 c1 c8 10 ; 0xf9f31 __U4M.asm:57
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9f35 __U4M.asm:58
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xf9f37 __U4M.asm:59
+ pop ax ; 58 ; 0xf9f3a __U4M.asm:60
+ rol eax, 010h ; 66 c1 c0 10 ; 0xf9f3b __U4M.asm:61
+ popfw ; 9d ; 0xf9f3f __U4M.asm:103
+ retn ; c3 ; 0xf9f40 __U4M.asm:104
+ times 0xf db 0
+ ; disGetNextSymbol 0xf9f50 LB 0xf5 -> off=0x0 cb=0000000000000040 uValue=00000000000f8950 '__U4D'
+__U4D: ; 0xf9f50 LB 0x40
+ pushfw ; 9c ; 0xf9f50 __U4D.asm:44
+ push eax ; 66 50 ; 0xf9f51 __U4D.asm:47
+ push edx ; 66 52 ; 0xf9f53 __U4D.asm:48
+ push ecx ; 66 51 ; 0xf9f55 __U4D.asm:49
+ rol eax, 010h ; 66 c1 c0 10 ; 0xf9f57 __U4D.asm:51
+ db 08bh, 0c2h
+ ; mov ax, dx ; 8b c2 ; 0xf9f5b __U4D.asm:52
+ ror eax, 010h ; 66 c1 c8 10 ; 0xf9f5d __U4D.asm:53
+ db 066h, 033h, 0d2h
+ ; xor edx, edx ; 66 33 d2 ; 0xf9f61 __U4D.asm:54
+ shr ecx, 010h ; 66 c1 e9 10 ; 0xf9f64 __U4D.asm:56
+ db 08bh, 0cbh
+ ; mov cx, bx ; 8b cb ; 0xf9f68 __U4D.asm:57
+ div ecx ; 66 f7 f1 ; 0xf9f6a __U4D.asm:59
+ db 08bh, 0dah
+ ; mov bx, dx ; 8b da ; 0xf9f6d __U4D.asm:61
+ pop ecx ; 66 59 ; 0xf9f6f __U4D.asm:62
+ shr edx, 010h ; 66 c1 ea 10 ; 0xf9f71 __U4D.asm:63
+ db 08bh, 0cah
+ ; mov cx, dx ; 8b ca ; 0xf9f75 __U4D.asm:64
+ pop edx ; 66 5a ; 0xf9f77 __U4D.asm:66
+ ror eax, 010h ; 66 c1 c8 10 ; 0xf9f79 __U4D.asm:67
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9f7d __U4D.asm:68
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xf9f7f __U4D.asm:69
+ pop ax ; 58 ; 0xf9f82 __U4D.asm:70
+ rol eax, 010h ; 66 c1 c0 10 ; 0xf9f83 __U4D.asm:71
+ popfw ; 9d ; 0xf9f87 __U4D.asm:129
+ retn ; c3 ; 0xf9f88 __U4D.asm:130
+ times 0x7 db 0
+ ; disGetNextSymbol 0xf9f90 LB 0xb5 -> off=0x0 cb=0000000000000010 uValue=00000000000f8990 '__U8RS'
+__U8RS: ; 0xf9f90 LB 0x10
+ test si, si ; 85 f6 ; 0xf9f90 __U8RS.asm:40
+ je short 09f9fh ; 74 0b ; 0xf9f92 __U8RS.asm:41
+ shr ax, 1 ; d1 e8 ; 0xf9f94 __U8RS.asm:43
+ rcr bx, 1 ; d1 db ; 0xf9f96 __U8RS.asm:44
+ rcr cx, 1 ; d1 d9 ; 0xf9f98 __U8RS.asm:45
+ rcr dx, 1 ; d1 da ; 0xf9f9a __U8RS.asm:46
+ dec si ; 4e ; 0xf9f9c __U8RS.asm:47
+ jne short 09f94h ; 75 f5 ; 0xf9f9d __U8RS.asm:48
+ retn ; c3 ; 0xf9f9f __U8RS.asm:50
+ ; disGetNextSymbol 0xf9fa0 LB 0xa5 -> off=0x0 cb=0000000000000010 uValue=00000000000f89a0 '__U8LS'
+__U8LS: ; 0xf9fa0 LB 0x10
+ test si, si ; 85 f6 ; 0xf9fa0 __U8LS.asm:40
+ je short 09fafh ; 74 0b ; 0xf9fa2 __U8LS.asm:41
+ sal dx, 1 ; d1 e2 ; 0xf9fa4 __U8LS.asm:43
+ rcl cx, 1 ; d1 d1 ; 0xf9fa6 __U8LS.asm:44
+ rcl bx, 1 ; d1 d3 ; 0xf9fa8 __U8LS.asm:45
+ rcl ax, 1 ; d1 d0 ; 0xf9faa __U8LS.asm:46
+ dec si ; 4e ; 0xf9fac __U8LS.asm:47
+ jne short 09fa4h ; 75 f5 ; 0xf9fad __U8LS.asm:48
+ retn ; c3 ; 0xf9faf __U8LS.asm:50
+ ; disGetNextSymbol 0xf9fb0 LB 0x95 -> off=0x0 cb=0000000000000010 uValue=00000000000f89b0 '_fmemset_'
+_fmemset_: ; 0xf9fb0 LB 0x10
+ push di ; 57 ; 0xf9fb0 fmemset.asm:42
+ mov es, dx ; 8e c2 ; 0xf9fb1 fmemset.asm:44
+ db 08bh, 0f8h
+ ; mov di, ax ; 8b f8 ; 0xf9fb3 fmemset.asm:45
+ xchg al, bl ; 86 d8 ; 0xf9fb5 fmemset.asm:46
+ rep stosb ; f3 aa ; 0xf9fb7 fmemset.asm:47
+ xchg al, bl ; 86 d8 ; 0xf9fb9 fmemset.asm:48
+ pop di ; 5f ; 0xf9fbb fmemset.asm:50
+ retn ; c3 ; 0xf9fbc fmemset.asm:51
+ times 0x3 db 0
+ ; disGetNextSymbol 0xf9fc0 LB 0x85 -> off=0x0 cb=000000000000003a uValue=00000000000f89c0 '_fmemcpy_'
+_fmemcpy_: ; 0xf9fc0 LB 0x3a
+ push bp ; 55 ; 0xf9fc0 fmemcpy.asm:42
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xf9fc1 fmemcpy.asm:43
+ push di ; 57 ; 0xf9fc3 fmemcpy.asm:44
+ push DS ; 1e ; 0xf9fc4 fmemcpy.asm:45
+ push si ; 56 ; 0xf9fc5 fmemcpy.asm:46
+ mov es, dx ; 8e c2 ; 0xf9fc6 fmemcpy.asm:48
+ db 08bh, 0f8h
+ ; mov di, ax ; 8b f8 ; 0xf9fc8 fmemcpy.asm:49
+ mov ds, cx ; 8e d9 ; 0xf9fca fmemcpy.asm:50
+ db 08bh, 0f3h
+ ; mov si, bx ; 8b f3 ; 0xf9fcc fmemcpy.asm:51
+ mov cx, word [bp+004h] ; 8b 4e 04 ; 0xf9fce fmemcpy.asm:52
+ rep movsb ; f3 a4 ; 0xf9fd1 fmemcpy.asm:53
+ pop si ; 5e ; 0xf9fd3 fmemcpy.asm:55
+ pop DS ; 1f ; 0xf9fd4 fmemcpy.asm:56
+ pop di ; 5f ; 0xf9fd5 fmemcpy.asm:57
+ db 08bh, 0e5h
+ ; mov sp, bp ; 8b e5 ; 0xf9fd6 fmemcpy.asm:58
+ pop bp ; 5d ; 0xf9fd8 fmemcpy.asm:59
+ retn ; c3 ; 0xf9fd9 fmemcpy.asm:60
+ add byte [bx+si], al ; 00 00 ; 0xf9fda
+ add byte [bx+si], al ; 00 00 ; 0xf9fdc
+ add byte [bx+si], al ; 00 00 ; 0xf9fde
+ adc byte [bx+si-05feeh], ah ; 10 a0 12 a0 ; 0xf9fe0
+ push SS ; 16 ; 0xf9fe4
+ mov AL, byte [0a016h] ; a0 16 a0 ; 0xf9fe5
+ push SS ; 16 ; 0xf9fe8
+ mov AL, byte [0a018h] ; a0 18 a0 ; 0xf9fe9
+ sbb byte [bx+si-05fe6h], ah ; 18 a0 1a a0 ; 0xf9fec
+ push DS ; 1e ; 0xf9ff0
+ mov AL, byte [0a01eh] ; a0 1e a0 ; 0xf9ff1
+ and byte [bx+si-05fdbh], ah ; 20 a0 25 a0 ; 0xf9ff4
+ daa ; 27 ; 0xf9ff8
+ db 0a0h
+ ; disGetNextSymbol 0xf9ffa LB 0x4b -> off=0x0 cb=000000000000003a uValue=00000000000089fa 'apm_worker'
+apm_worker: ; 0xf9ffa LB 0x3a
+ sti ; fb ; 0xf9ffa apm_pm.asm:56
+ push ax ; 50 ; 0xf9ffb apm_pm.asm:58
+ db 032h, 0e4h
+ ; xor ah, ah ; 32 e4 ; 0xf9ffc apm_pm.asm:59
+ sub AL, strict byte 004h ; 2c 04 ; 0xf9ffe apm_pm.asm:60
+ db 08bh, 0e8h
+ ; mov bp, ax ; 8b e8 ; 0xfa000 apm_pm.asm:61
+ sal bp, 1 ; d1 e5 ; 0xfa002 apm_pm.asm:62
+ cmp AL, strict byte 00dh ; 3c 0d ; 0xfa004 apm_pm.asm:63
+ pop ax ; 58 ; 0xfa006 apm_pm.asm:64
+ mov AH, strict byte 053h ; b4 53 ; 0xfa007 apm_pm.asm:65
+ jnc short 0a030h ; 73 25 ; 0xfa009 apm_pm.asm:66
+ jmp word [cs:bp-06020h] ; 2e ff a6 e0 9f ; 0xfa00b apm_pm.asm:68
+ jmp short 0a02eh ; eb 1c ; 0xfa010 apm_pm.asm:71
+ sti ; fb ; 0xfa012 apm_pm.asm:74
+ hlt ; f4 ; 0xfa013 apm_pm.asm:75
+ jmp short 0a02eh ; eb 18 ; 0xfa014 apm_pm.asm:76
+ jmp short 0a02eh ; eb 16 ; 0xfa016 apm_pm.asm:85
+ jmp short 0a030h ; eb 16 ; 0xfa018 apm_pm.asm:91
+ mov AH, strict byte 080h ; b4 80 ; 0xfa01a apm_pm.asm:94
+ jmp short 0a032h ; eb 14 ; 0xfa01c apm_pm.asm:95
+ jmp short 0a030h ; eb 10 ; 0xfa01e apm_pm.asm:100
+ mov ax, 00102h ; b8 02 01 ; 0xfa020 apm_pm.asm:103
+ jmp short 0a02eh ; eb 09 ; 0xfa023 apm_pm.asm:104
+ jmp short 0a02eh ; eb 07 ; 0xfa025 apm_pm.asm:108
+ mov BL, strict byte 000h ; b3 00 ; 0xfa027 apm_pm.asm:111
+ mov cx, strict word 00000h ; b9 00 00 ; 0xfa029 apm_pm.asm:112
+ jmp short 0a02eh ; eb 00 ; 0xfa02c apm_pm.asm:113
+ clc ; f8 ; 0xfa02e apm_pm.asm:116
+ retn ; c3 ; 0xfa02f apm_pm.asm:117
+ mov AH, strict byte 009h ; b4 09 ; 0xfa030 apm_pm.asm:120
+ stc ; f9 ; 0xfa032 apm_pm.asm:123
+ retn ; c3 ; 0xfa033 apm_pm.asm:124
+ ; disGetNextSymbol 0xfa034 LB 0x11 -> off=0x0 cb=0000000000000011 uValue=00000000000f8a34 'apm_pm16_entry'
+apm_pm16_entry: ; 0xfa034 LB 0x11
+ mov AH, strict byte 002h ; b4 02 ; 0xfa034 apm_pm.asm:136
+ push DS ; 1e ; 0xfa036 apm_pm.asm:142
+ push bp ; 55 ; 0xfa037 apm_pm.asm:143
+ push CS ; 0e ; 0xfa038 apm_pm.asm:145
+ pop bp ; 5d ; 0xfa039 apm_pm.asm:146
+ add bp, strict byte 00008h ; 83 c5 08 ; 0xfa03a apm_pm.asm:147
+ mov ds, bp ; 8e dd ; 0xfa03d apm_pm.asm:148
+ call 09ffah ; e8 b8 ff ; 0xfa03f apm_pm.asm:150
+ pop bp ; 5d ; 0xfa042 apm_pm.asm:152
+ pop DS ; 1f ; 0xfa043 apm_pm.asm:153
+ retf ; cb ; 0xfa044 apm_pm.asm:155
+
+ ; Padding 0x39bb bytes at 0xfa045
+ times 14779 db 0
+
+section BIOS32 progbits vstart=0xda00 align=1 ; size=0x3cb class=CODE group=AUTO
+ ; disGetNextSymbol 0xfda00 LB 0x3cb -> off=0x0 cb=0000000000000026 uValue=00000000000f0000 'bios32_service'
+bios32_service: ; 0xfda00 LB 0x26
+ pushfw ; 9c ; 0xfda00 pcibio32.asm:52
+ cmp bl, 000h ; 80 fb 00 ; 0xfda01 pcibio32.asm:54
+ jne short 0da22h ; 75 1c ; 0xfda04 pcibio32.asm:55
+ cmp ax, 05024h ; 3d 24 50 ; 0xfda06 pcibio32.asm:57
+ inc bx ; 43 ; 0xfda09
+ dec cx ; 49 ; 0xfda0a
+ mov AL, strict byte 080h ; b0 80 ; 0xfda0b pcibio32.asm:58
+ jne short 0da20h ; 75 11 ; 0xfda0d pcibio32.asm:59
+ mov bx, strict word 00000h ; bb 00 00 ; 0xfda0f pcibio32.asm:61
+ db 00fh
+ add byte [bx+di-01000h], bh ; 00 b9 00 f0 ; 0xfda13
+ add byte [bx+si], al ; 00 00 ; 0xfda17
+ mov dx, 0da26h ; ba 26 da ; 0xfda19 pcibio32.asm:63
+ add byte [bx+si], al ; 00 00 ; 0xfda1c
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xfda1e pcibio32.asm:64
+ popfw ; 9d ; 0xfda20 pcibio32.asm:66
+ retf ; cb ; 0xfda21 pcibio32.asm:67
+ mov AL, strict byte 081h ; b0 81 ; 0xfda22 pcibio32.asm:70
+ jmp short 0da20h ; eb fa ; 0xfda24 pcibio32.asm:71
+ ; disGetNextSymbol 0xfda26 LB 0x3a5 -> off=0x0 cb=000000000000001a uValue=00000000000f0026 'pcibios32_entry'
+pcibios32_entry: ; 0xfda26 LB 0x1a
+ pushfw ; 9c ; 0xfda26 pcibio32.asm:80
+ cld ; fc ; 0xfda27 pcibio32.asm:81
+ push ES ; 06 ; 0xfda28 pcibio32.asm:83
+ pushaw ; 60 ; 0xfda29 pcibio32.asm:84
+ call 0db78h ; e8 4b 01 ; 0xfda2a pcibio32.asm:85
+ add byte [bx+si], al ; 00 00 ; 0xfda2d
+ popaw ; 61 ; 0xfda2f pcibio32.asm:86
+ pop ES ; 07 ; 0xfda30 pcibio32.asm:87
+ popfw ; 9d ; 0xfda31 pcibio32.asm:89
+ retf ; cb ; 0xfda32 pcibio32.asm:90
+ times 0xd db 0
+ ; disGetNextSymbol 0xfda40 LB 0x38b -> off=0x0 cb=0000000000000021 uValue=00000000000f0040 'apm_pm32_entry'
+apm_pm32_entry: ; 0xfda40 LB 0x21
+ push bp ; 55 ; 0xfda40 apm_pm.asm:180
+ mov ebp, cs ; 66 8c cd ; 0xfda41 apm_pm.asm:182
+ push ebp ; 66 55 ; 0xfda44 apm_pm.asm:183
+ mov bp, 0da5fh ; bd 5f da ; 0xfda46 apm_pm.asm:184
+ add byte [bx+si], al ; 00 00 ; 0xfda49
+ push ebp ; 66 55 ; 0xfda4b apm_pm.asm:185
+ push CS ; 0e ; 0xfda4d apm_pm.asm:187
+ pop bp ; 5d ; 0xfda4e apm_pm.asm:188
+ add bp, strict byte 00008h ; 83 c5 08 ; 0xfda4f apm_pm.asm:189
+ push ebp ; 66 55 ; 0xfda52 apm_pm.asm:190
+ mov bp, 0a036h ; bd 36 a0 ; 0xfda54 apm_pm.asm:192
+ add byte [bx+si], al ; 00 00 ; 0xfda57
+ push ebp ; 66 55 ; 0xfda59 apm_pm.asm:193
+ mov AH, strict byte 003h ; b4 03 ; 0xfda5b apm_pm.asm:195
+ db 066h, 0cbh
+ ; retf ; 66 cb ; 0xfda5d
+ pop bp ; 5d ; 0xfda5f apm_pm.asm:202
+ retf ; cb ; 0xfda60 apm_pm.asm:203
+ ; disGetNextSymbol 0xfda61 LB 0x36a -> off=0x0 cb=0000000000000022 uValue=00000000000f0061 'pci32_select_reg_'
+pci32_select_reg_: ; 0xfda61 LB 0x22
+ push bp ; 55 ; 0xfda61 pci32.c:188
+ mov bp, sp ; 89 e5 ; 0xfda62
+ push bx ; 53 ; 0xfda64
+ and dl, 0fch ; 80 e2 fc ; 0xfda65 pci32.c:190
+ mov bx, dx ; 89 d3 ; 0xfda68
+ mov dx, 00cf8h ; ba f8 0c ; 0xfda6a
+ add byte [bx+si], al ; 00 00 ; 0xfda6d
+ db 00fh, 0b7h, 0c0h
+ ; movzx ax, ax ; 0f b7 c0 ; 0xfda6f
+ sal ax, 008h ; c1 e0 08 ; 0xfda72
+ or ax, strict word 00000h ; 0d 00 00 ; 0xfda75
+ add byte [bx+si-03c76h], al ; 00 80 8a c3 ; 0xfda78
+ out DX, ax ; ef ; 0xfda7c
+ lea sp, [di-004h] ; 8d 65 fc ; 0xfda7d pci32.c:191
+ pop bx ; 5b ; 0xfda80
+ pop bp ; 5d ; 0xfda81
+ retn ; c3 ; 0xfda82
+ ; disGetNextSymbol 0xfda83 LB 0x348 -> off=0x0 cb=00000000000000f7 uValue=00000000000f0083 'pci32_find_device_'
+pci32_find_device_: ; 0xfda83 LB 0xf7
+ push bp ; 55 ; 0xfda83 pci32.c:221
+ mov bp, sp ; 89 e5 ; 0xfda84
+ push cx ; 51 ; 0xfda86
+ push si ; 56 ; 0xfda87
+ push di ; 57 ; 0xfda88
+ sub sp, strict byte 00014h ; 83 ec 14 ; 0xfda89
+ push ax ; 50 ; 0xfda8c
+ mov cx, dx ; 89 d1 ; 0xfda8d
+ mov si, bx ; 89 de ; 0xfda8f
+ test bx, bx ; 85 db ; 0xfda91 pci32.c:231
+ xor bx, bx ; 31 db ; 0xfda93 pci32.c:238
+ mov byte [di-010h], 000h ; c6 45 f0 00 ; 0xfda95 pci32.c:239
+ test bl, 007h ; f6 c3 07 ; 0xfda99 pci32.c:249
+ jne short 0dad4h ; 75 36 ; 0xfda9c
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfda9e pci32.c:250
+ mov dx, strict word 0000eh ; ba 0e 00 ; 0xfdaa1
+ add byte [bx+si], al ; 00 00 ; 0xfdaa4
+ call 0da5fh ; e8 b6 ff ; 0xfdaa6
+ db 0ffh
+ db 0ffh
+ mov dx, 00cfeh ; ba fe 0c ; 0xfdaab pci32.c:251
+ add byte [bx+si], al ; 00 00 ; 0xfdaae
+ db 02bh, 0c0h
+ ; sub ax, ax ; 2b c0 ; 0xfdab0
+ in AL, DX ; ec ; 0xfdab2
+ mov byte [di-014h], al ; 88 45 ec ; 0xfdab3
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xfdab6 pci32.c:252
+ jne short 0dac2h ; 75 08 ; 0xfdab8
+ add bx, strict byte 00008h ; 83 c3 08 ; 0xfdaba pci32.c:253
+ jmp near 0db4ah ; e9 8a 00 ; 0xfdabd pci32.c:254
+ add byte [bx+si], al ; 00 00 ; 0xfdac0
+ test byte [di-014h], 080h ; f6 45 ec 80 ; 0xfdac2 pci32.c:256
+ je short 0dacfh ; 74 07 ; 0xfdac6
+ mov di, strict word 00001h ; bf 01 00 ; 0xfdac8 pci32.c:257
+ add byte [bx+si], al ; 00 00 ; 0xfdacb
+ jmp short 0dad4h ; eb 05 ; 0xfdacd pci32.c:258
+ mov di, strict word 00008h ; bf 08 00 ; 0xfdacf pci32.c:259
+ add byte [bx+si], al ; 00 00 ; 0xfdad2
+ mov al, byte [di-014h] ; 8a 45 ec ; 0xfdad4 pci32.c:270
+ and AL, strict byte 007h ; 24 07 ; 0xfdad7
+ cmp AL, strict byte 001h ; 3c 01 ; 0xfdad9
+ jne short 0db03h ; 75 26 ; 0xfdadb
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfdadd
+ mov dx, ax ; 89 c2 ; 0xfdae0
+ sar dx, 008h ; c1 fa 08 ; 0xfdae2
+ test dx, dx ; 85 d2 ; 0xfdae5
+ jne short 0db03h ; 75 1a ; 0xfdae7
+ mov dx, strict word 0001ah ; ba 1a 00 ; 0xfdae9 pci32.c:272
+ add byte [bx+si], al ; 00 00 ; 0xfdaec
+ call 0da5fh ; e8 6e ff ; 0xfdaee
+ db 0ffh
+ db 0ffh
+ mov dx, 00cfeh ; ba fe 0c ; 0xfdaf3 pci32.c:273
+ add byte [bx+si], al ; 00 00 ; 0xfdaf6
+ db 02bh, 0c0h
+ ; sub ax, ax ; 2b c0 ; 0xfdaf8
+ in AL, DX ; ec ; 0xfdafa
+ cmp al, byte [di-010h] ; 3a 45 f0 ; 0xfdafb pci32.c:274
+ jbe short 0db03h ; 76 03 ; 0xfdafe
+ mov byte [di-010h], al ; 88 45 f0 ; 0xfdb00 pci32.c:275
+ test si, si ; 85 f6 ; 0xfdb03 pci32.c:279
+ je short 0db0eh ; 74 07 ; 0xfdb05
+ mov ax, strict word 00008h ; b8 08 00 ; 0xfdb07
+ add byte [bx+si], al ; 00 00 ; 0xfdb0a
+ jmp short 0db10h ; eb 02 ; 0xfdb0c
+ xor ax, ax ; 31 c0 ; 0xfdb0e
+ db 00fh, 0b7h, 0d0h
+ ; movzx dx, ax ; 0f b7 d0 ; 0xfdb10
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfdb13
+ call 0da5fh ; e8 46 ff ; 0xfdb16
+ db 0ffh
+ db 0ffh
+ mov dx, 00cfch ; ba fc 0c ; 0xfdb1b pci32.c:280
+ add byte [bx+si], al ; 00 00 ; 0xfdb1e
+ in ax, DX ; ed ; 0xfdb20
+ mov word [di-018h], ax ; 89 45 e8 ; 0xfdb21
+ mov word [di-020h], strict word 00000h ; c7 45 e0 00 00 ; 0xfdb24 pci32.c:281
+ add byte [bx+si], al ; 00 00 ; 0xfdb29
+ test si, si ; 85 f6 ; 0xfdb2b pci32.c:284
+ je short 0db35h ; 74 06 ; 0xfdb2d
+ shr ax, 008h ; c1 e8 08 ; 0xfdb2f pci32.c:285
+ mov word [di-018h], ax ; 89 45 e8 ; 0xfdb32
+ mov ax, word [di-018h] ; 8b 45 e8 ; 0xfdb35 pci32.c:292
+ cmp ax, word [di-024h] ; 3b 45 dc ; 0xfdb38
+ je short 0db43h ; 74 06 ; 0xfdb3b
+ cmp word [di-020h], strict byte 00000h ; 83 7d e0 00 ; 0xfdb3d pci32.c:293
+ je short 0db4ah ; 74 07 ; 0xfdb41
+ dec cx ; 49 ; 0xfdb43
+ cmp ecx, strict byte 0ffffffffh ; 66 83 f9 ff ; 0xfdb44
+ je short 0db62h ; 74 18 ; 0xfdb48
+ add bx, di ; 01 fb ; 0xfdb4a pci32.c:301
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfdb4c pci32.c:302
+ sar ax, 008h ; c1 f8 08 ; 0xfdb4f
+ mov word [di-01ch], ax ; 89 45 e4 ; 0xfdb52
+ movzx ax, byte [di-010h] ; 0f b6 45 f0 ; 0xfdb55
+ cmp ax, word [di-01ch] ; 3b 45 e4 ; 0xfdb59
+ jnl near 0da97h ; 0f 8d 37 ff ; 0xfdb5c
+ db 0ffh
+ jmp word [bp-07dh] ; ff 66 83 ; 0xfdb61
+ stc ; f9 ; 0xfdb64
+ push word [di+005h] ; ff 75 05 ; 0xfdb65
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfdb68
+ jmp short 0db72h ; eb 05 ; 0xfdb6b
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xfdb6d
+ add byte [bx+si], al ; 00 00 ; 0xfdb70
+ lea sp, [di-00ch] ; 8d 65 f4 ; 0xfdb72 pci32.c:309
+ pop di ; 5f ; 0xfdb75
+ pop si ; 5e ; 0xfdb76
+ pop cx ; 59 ; 0xfdb77
+ pop bp ; 5d ; 0xfdb78
+ retn ; c3 ; 0xfdb79
+ ; disGetNextSymbol 0xfdb7a LB 0x251 -> off=0x0 cb=0000000000000251 uValue=00000000000f017a '_pci32_function'
+_pci32_function: ; 0xfdb7a LB 0x251
+ push bp ; 55 ; 0xfdb7a pci32.c:311
+ mov bp, sp ; 89 e5 ; 0xfdb7b
+ push bx ; 53 ; 0xfdb7d
+ push si ; 56 ; 0xfdb7e
+ push di ; 57 ; 0xfdb7f
+ push ax ; 50 ; 0xfdb80
+ push ax ; 50 ; 0xfdb81
+ and dword [di+024h], strict dword 0658100ffh ; 66 81 65 24 ff 00 81 65 ; 0xfdb82 pci32.c:318
+ sub AL, strict byte 0feh ; 2c fe ; 0xfdb8a
+ inc word [bx+si] ; ff 00 ; 0xfdb8c
+ add byte [bp+di+02445h], cl ; 00 8b 45 24 ; 0xfdb8e
+ xor ah, ah ; 30 e4 ; 0xfdb92
+ cmp eax, strict dword 029720003h ; 66 3d 03 00 72 29 ; 0xfdb94
+ jbe near 0dc37h ; 0f 86 99 00 ; 0xfdb9a
+ add byte [bx+si], al ; 00 00 ; 0xfdb9e
+ cmp eax, strict dword 0840f000eh ; 66 3d 0e 00 0f 84 ; 0xfdba0
+ test ax, strict word 00001h ; a9 01 00 ; 0xfdba6
+ add byte [bp+03dh], ah ; 00 66 3d ; 0xfdba9
+ or byte [bx+si], al ; 08 00 ; 0xfdbac
+ jc near 0ddb1h ; 0f 82 ff 01 ; 0xfdbae
+ add byte [bx+si], al ; 00 00 ; 0xfdbb2
+ cmp eax, strict dword 0860f000dh ; 66 3d 0d 00 0f 86 ; 0xfdbb4
+ test AL, strict byte 000h ; a8 00 ; 0xfdbba
+ add byte [bx+si], al ; 00 00 ; 0xfdbbc
+ jmp near 0ddb1h ; e9 f0 01 ; 0xfdbbe
+ add byte [bx+si], al ; 00 00 ; 0xfdbc1
+ cmp eax, strict dword 028740002h ; 66 3d 02 00 74 28 ; 0xfdbc3
+ cmp eax, strict dword 0850f0001h ; 66 3d 01 00 0f 85 ; 0xfdbc9
+ loopne 0dbd2h ; e0 01 ; 0xfdbcf
+ add byte [bx+si], al ; 00 00 ; 0xfdbd1
+ mov dword [di+024h], strict dword 0c7660001h ; 66 c7 45 24 01 00 66 c7 ; 0xfdbd3 pci32.c:323
+ inc bp ; 45 ; 0xfdbdb
+ sbb byte [bx+si], dl ; 18 10 ; 0xfdbdc
+ add dh, byte [bx+di] ; 02 31 ; 0xfdbde
+ sal byte [bp-077h], 045h ; c0 66 89 45 ; 0xfdbe0
+ and bh, al ; 20 c7 ; 0xfdbe4
+ inc bp ; 45 ; 0xfdbe6
+ sbb AL, strict byte 050h ; 1c 50 ; 0xfdbe7
+ inc bx ; 43 ; 0xfdbe9
+ dec cx ; 49 ; 0xfdbea
+ and cl, ch ; 20 e9 ; 0xfdbeb
+ rol byte [bx+di], CL ; d2 01 ; 0xfdbed
+ add byte [bx+si], al ; 00 00 ; 0xfdbef
+ cmp dword [di+01ch], strict byte 0ffffffffh ; 66 83 7d 1c ff ; 0xfdbf1 pci32.c:333
+ jne short 0dc05h ; 75 0d ; 0xfdbf6
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdbf8 pci32.c:334
+ xor ah, ah ; 30 e4 ; 0xfdbfb
+ or ah, 083h ; 80 cc 83 ; 0xfdbfd
+ jmp near 0ddb9h ; e9 b6 01 ; 0xfdc00 pci32.c:335
+ add byte [bx+si], al ; 00 00 ; 0xfdc03
+ xor bx, bx ; 31 db ; 0xfdc05 pci32.c:337
+ db 00fh, 0b7h, 055h, 00ch
+ ; movzx dx, [di+00ch] ; 0f b7 55 0c ; 0xfdc07
+ db 00fh, 0b7h, 045h, 020h
+ ; movzx ax, [di+020h] ; 0f b7 45 20 ; 0xfdc0b
+ sal ax, 010h ; c1 e0 10 ; 0xfdc0f
+ db 00fh, 0b7h, 04dh, 01ch
+ ; movzx cx, [di+01ch] ; 0f b7 4d 1c ; 0xfdc12
+ or ax, cx ; 09 c8 ; 0xfdc16
+ call 0da81h ; e8 66 fe ; 0xfdc18
+ db 0ffh
+ jmp word [bp+03dh] ; ff 66 3d ; 0xfdc1c
+ db 0ffh
+ push word [di+00dh] ; ff 75 0d ; 0xfdc20
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdc23 pci32.c:339
+ xor ah, ah ; 30 e4 ; 0xfdc26
+ or ah, 086h ; 80 cc 86 ; 0xfdc28
+ jmp near 0ddb9h ; e9 8b 01 ; 0xfdc2b
+ add byte [bx+si], al ; 00 00 ; 0xfdc2e
+ mov dword [di+018h], eax ; 66 89 45 18 ; 0xfdc30 pci32.c:340
+ jmp near 0ddc1h ; e9 8a 01 ; 0xfdc34 pci32.c:345
+ add byte [bx+si], al ; 00 00 ; 0xfdc37
+ db 00fh, 0b7h, 055h, 00ch
+ ; movzx dx, [di+00ch] ; 0f b7 55 0c ; 0xfdc39 pci32.c:347
+ mov ax, word [di+020h] ; 8b 45 20 ; 0xfdc3d
+ mov bx, strict word 00001h ; bb 01 00 ; 0xfdc40
+ add byte [bx+si], al ; 00 00 ; 0xfdc43
+ call 0da81h ; e8 39 fe ; 0xfdc45
+ db 0ffh
+ jmp word [bp+03dh] ; ff 66 3d ; 0xfdc49
+ db 0ffh
+ push word [di+00dh] ; ff 75 0d ; 0xfdc4d
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdc50 pci32.c:349
+ xor ah, ah ; 30 e4 ; 0xfdc53
+ or ah, 086h ; 80 cc 86 ; 0xfdc55
+ jmp near 0ddb9h ; e9 5e 01 ; 0xfdc58 pci32.c:350
+ add byte [bx+si], al ; 00 00 ; 0xfdc5b
+ mov dword [di+018h], eax ; 66 89 45 18 ; 0xfdc5d pci32.c:352
+ jmp near 0ddc1h ; e9 5d 01 ; 0xfdc61 pci32.c:354
+ add byte [bx+si], al ; 00 00 ; 0xfdc64
+ cmp dword [di+008h], strict dword 00d720100h ; 66 81 7d 08 00 01 72 0d ; 0xfdc66 pci32.c:361
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdc6e pci32.c:362
+ xor ah, ah ; 30 e4 ; 0xfdc71
+ or ah, 087h ; 80 cc 87 ; 0xfdc73
+ jmp near 0ddb9h ; e9 40 01 ; 0xfdc76 pci32.c:363
+ add byte [bx+si], al ; 00 00 ; 0xfdc79
+ db 00fh, 0b7h, 055h, 008h
+ ; movzx dx, [di+008h] ; 0f b7 55 08 ; 0xfdc7b pci32.c:365
+ db 00fh, 0b7h, 045h, 018h
+ ; movzx ax, [di+018h] ; 0f b7 45 18 ; 0xfdc7f
+ call 0da5fh ; e8 d9 fd ; 0xfdc83
+ db 0ffh
+ dec word [bp+di+02445h] ; ff 8b 45 24 ; 0xfdc87
+ xor ah, ah ; 30 e4 ; 0xfdc8b
+ cmp eax, strict dword 02172000ah ; 66 3d 0a 00 72 21 ; 0xfdc8d
+ jbe short 0dd04h ; 76 6f ; 0xfdc93
+ cmp eax, strict dword 0840f000dh ; 66 3d 0d 00 0f 84 ; 0xfdc95
+ test ax, strict word 00000h ; a9 00 00 ; 0xfdc9b
+ add byte [bp+03dh], ah ; 00 66 3d ; 0xfdc9e
+ or AL, strict byte 000h ; 0c 00 ; 0xfdca1
+ je near 0dd2ah ; 0f 84 83 00 ; 0xfdca3
+ add byte [bx+si], al ; 00 00 ; 0xfdca7
+ cmp eax, strict dword 06374000bh ; 66 3d 0b 00 74 63 ; 0xfdca9
+ jmp near 0ddc1h ; e9 0f 01 ; 0xfdcaf
+ add byte [bx+si], al ; 00 00 ; 0xfdcb2
+ cmp eax, strict dword 02d740009h ; 66 3d 09 00 74 2d ; 0xfdcb4
+ cmp eax, strict dword 0850f0008h ; 66 3d 08 00 0f 85 ; 0xfdcba
+ inc word [bx+si] ; ff 00 ; 0xfdcc0
+ add byte [bx+si], al ; 00 00 ; 0xfdcc2
+ mov bx, word [di+020h] ; 8b 5d 20 ; 0xfdcc4 pci32.c:368
+ xor bl, bl ; 30 db ; 0xfdcc7
+ mov ax, word [di+008h] ; 8b 45 08 ; 0xfdcc9
+ xor ah, ah ; 30 e4 ; 0xfdccc
+ and AL, strict byte 003h ; 24 03 ; 0xfdcce
+ db 00fh, 0b7h, 0d0h
+ ; movzx dx, ax ; 0f b7 d0 ; 0xfdcd0
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xfdcd3
+ add byte [bx+si], al ; 00 00 ; 0xfdcd7
+ db 02bh, 0c0h
+ ; sub ax, ax ; 2b c0 ; 0xfdcd9
+ in AL, DX ; ec ; 0xfdcdb
+ or bx, ax ; 09 c3 ; 0xfdcdc
+ mov dword [di+020h], ebx ; 66 89 5d 20 ; 0xfdcde
+ jmp near 0ddc1h ; e9 dc 00 ; 0xfdce2 pci32.c:369
+ add byte [bx+si], al ; 00 00 ; 0xfdce5
+ mov ax, word [di+008h] ; 8b 45 08 ; 0xfdce7 pci32.c:371
+ xor ah, ah ; 30 e4 ; 0xfdcea
+ and AL, strict byte 002h ; 24 02 ; 0xfdcec
+ db 00fh, 0b7h, 0d0h
+ ; movzx dx, ax ; 0f b7 d0 ; 0xfdcee
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xfdcf1
+ add byte [bx+si], al ; 00 00 ; 0xfdcf5
+ db 02bh, 0c0h
+ ; sub ax, ax ; 2b c0 ; 0xfdcf7
+ in eax, DX ; 66 ed ; 0xfdcf9
+ mov dword [di+020h], eax ; 66 89 45 20 ; 0xfdcfb
+ jmp near 0ddc1h ; e9 bf 00 ; 0xfdcff pci32.c:372
+ add byte [bx+si], al ; 00 00 ; 0xfdd02
+ mov dx, 00cfch ; ba fc 0c ; 0xfdd04 pci32.c:374
+ add byte [bx+si], al ; 00 00 ; 0xfdd07
+ in ax, DX ; ed ; 0xfdd09
+ mov word [di+020h], ax ; 89 45 20 ; 0xfdd0a
+ jmp near 0ddc1h ; e9 b1 00 ; 0xfdd0d pci32.c:375
+ add byte [bx+si], al ; 00 00 ; 0xfdd10
+ mov ax, word [di+020h] ; 8b 45 20 ; 0xfdd12 pci32.c:377
+ mov dx, word [di+008h] ; 8b 55 08 ; 0xfdd15
+ xor dh, dh ; 30 f6 ; 0xfdd18
+ and dl, 003h ; 80 e2 03 ; 0xfdd1a
+ db 00fh, 0b7h, 0d2h
+ ; movzx dx, dx ; 0f b7 d2 ; 0xfdd1d
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xfdd20
+ add byte [bx+si], al ; 00 00 ; 0xfdd24
+ out DX, AL ; ee ; 0xfdd26
+ jmp near 0ddc1h ; e9 97 00 ; 0xfdd27 pci32.c:378
+ add byte [bx+si], al ; 00 00 ; 0xfdd2a
+ db 00fh, 0b7h, 045h, 020h
+ ; movzx ax, [di+020h] ; 0f b7 45 20 ; 0xfdd2c pci32.c:380
+ mov dx, word [di+008h] ; 8b 55 08 ; 0xfdd30
+ xor dh, dh ; 30 f6 ; 0xfdd33
+ and dl, 002h ; 80 e2 02 ; 0xfdd35
+ db 00fh, 0b7h, 0d2h
+ ; movzx dx, dx ; 0f b7 d2 ; 0xfdd38
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xfdd3b
+ add byte [bx+si], al ; 00 00 ; 0xfdd3f
+ out DX, eax ; 66 ef ; 0xfdd41
+ jmp near 0ddc1h ; e9 7b 00 ; 0xfdd43 pci32.c:381
+ add byte [bx+si], al ; 00 00 ; 0xfdd46
+ mov ax, word [di+020h] ; 8b 45 20 ; 0xfdd48 pci32.c:383
+ mov dx, 00cfch ; ba fc 0c ; 0xfdd4b
+ add byte [bx+si], al ; 00 00 ; 0xfdd4e
+ out DX, ax ; ef ; 0xfdd50
+ jmp short 0ddc3h ; eb 70 ; 0xfdd51 pci32.c:387
+ db 00fh, 0b7h, 045h, 008h
+ ; movzx ax, [di+008h] ; 0f b7 45 08 ; 0xfdd53 pci32.c:389
+ mov es, [di+028h] ; 8e 45 28 ; 0xfdd57
+ mov [di-010h], es ; 8c 45 f0 ; 0xfdd5a
+ mov bx, ax ; 89 c3 ; 0xfdd5d
+ mov edx, dword [di] ; 66 8b 15 ; 0xfdd5f pci32.c:393
+ jo short 0dd57h ; 70 f3 ; 0xfdd62
+ add byte [bx+si], al ; 00 00 ; 0xfdd64
+ db 066h, 026h, 03bh, 010h
+ ; cmp edx, dword [es:bx+si] ; 66 26 3b 10 ; 0xfdd66
+ jbe short 0dd7eh ; 76 12 ; 0xfdd6a
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdd6c pci32.c:394
+ xor ah, ah ; 30 e4 ; 0xfdd6f
+ or ah, 089h ; 80 cc 89 ; 0xfdd71
+ mov dword [di+024h], eax ; 66 89 45 24 ; 0xfdd74
+ or word [di+02ch], strict byte 00001h ; 83 4d 2c 01 ; 0xfdd78 pci32.c:395
+ jmp short 0dda4h ; eb 26 ; 0xfdd7c pci32.c:396
+ db 00fh, 0b7h, 0cah
+ ; movzx cx, dx ; 0f b7 ca ; 0xfdd7e pci32.c:397
+ db 066h, 026h, 08bh, 050h, 006h
+ ; mov edx, dword [es:bx+si+006h] ; 66 26 8b 50 06 ; 0xfdd81
+ mov word [di-014h], dx ; 89 55 ec ; 0xfdd86
+ mov di, word [es:bx+si+002h] ; 26 8b 78 02 ; 0xfdd89
+ mov dx, ds ; 8c da ; 0xfdd8d
+ mov si, 0f190h ; be 90 f1 ; 0xfdd8f
+ add byte [bx+si], al ; 00 00 ; 0xfdd92
+ mov es, [di-014h] ; 8e 45 ec ; 0xfdd94
+ push DS ; 1e ; 0xfdd97
+ db 066h, 08eh, 0dah
+ ; mov ds, edx ; 66 8e da ; 0xfdd98
+ rep movsb ; f3 a4 ; 0xfdd9b
+ pop DS ; 1f ; 0xfdd9d
+ mov dword [di+018h], strict dword 0a1660a00h ; 66 c7 45 18 00 0a 66 a1 ; 0xfdd9e pci32.c:399
+ jo short 0dd9bh ; 70 f3 ; 0xfdda6
+ add byte [bx+si], al ; 00 00 ; 0xfdda8
+ mov es, [di-010h] ; 8e 45 f0 ; 0xfddaa
+ db 066h, 026h, 089h, 003h
+ ; mov dword [es:bp+di], eax ; 66 26 89 03 ; 0xfddad
+ jmp short 0ddc3h ; eb 10 ; 0xfddb1 pci32.c:402
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfddb3 pci32.c:405
+ xor ah, ah ; 30 e4 ; 0xfddb6
+ or ah, 081h ; 80 cc 81 ; 0xfddb8
+ mov dword [di+024h], eax ; 66 89 45 24 ; 0xfddbb
+ or word [di+02ch], strict byte 00001h ; 83 4d 2c 01 ; 0xfddbf pci32.c:406
+ lea sp, [di-00ch] ; 8d 65 f4 ; 0xfddc3 pci32.c:408
+ pop di ; 5f ; 0xfddc6
+ pop si ; 5e ; 0xfddc7
+ pop bx ; 5b ; 0xfddc8
+ pop bp ; 5d ; 0xfddc9
+ retn ; c3 ; 0xfddca
+
+ ; Padding 0x1 bytes at 0xfddcb
+ times 1 db 0
+
+section BIOS32CONST progbits vstart=0xddcc align=1 ; size=0x0 class=FAR_DATA group=BIOS32_GROUP
+
+section BIOS32CONST2 progbits vstart=0xddcc align=1 ; size=0x0 class=FAR_DATA group=BIOS32_GROUP
+
+section BIOS32_DATA progbits vstart=0xddcc align=1 ; size=0x0 class=FAR_DATA group=BIOS32_GROUP
+
+ ; Padding 0x234 bytes at 0xfddcc
+ times 564 db 0
+
+section BIOSSEG progbits vstart=0xe000 align=1 ; size=0x2000 class=CODE group=AUTO
+ ; disGetNextSymbol 0xfe000 LB 0x2000 -> off=0x0 cb=0000000000000030 uValue=00000000000f0000 'biosorg_check_before_or_at_0E02Eh'
+biosorg_check_before_or_at_0E02Eh: ; 0xfe000 LB 0x30
+ times 0x2e db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe030 LB 0x1fd0 -> off=0x0 cb=0000000000000004 uValue=00000000000f0030 'eoi_both_pics'
+eoi_both_pics: ; 0xfe030 LB 0x4
+ mov AL, strict byte 020h ; b0 20 ; 0xfe030 orgs.asm:238
+ out strict byte 0a0h, AL ; e6 a0 ; 0xfe032 orgs.asm:239
+ ; disGetNextSymbol 0xfe034 LB 0x1fcc -> off=0x0 cb=0000000000000005 uValue=00000000000f0034 'eoi_master_pic'
+eoi_master_pic: ; 0xfe034 LB 0x5
+ mov AL, strict byte 020h ; b0 20 ; 0xfe034 orgs.asm:241
+ out strict byte 020h, AL ; e6 20 ; 0xfe036 orgs.asm:242
+ retn ; c3 ; 0xfe038 orgs.asm:243
+ ; disGetNextSymbol 0xfe039 LB 0x1fc7 -> off=0x0 cb=000000000000000b uValue=0000000000000039 'set_int_vects'
+set_int_vects: ; 0xfe039 LB 0xb
+ mov word [bx], ax ; 89 07 ; 0xfe039 orgs.asm:250
+ mov word [bx+002h], dx ; 89 57 02 ; 0xfe03b orgs.asm:251
+ add bx, strict byte 00004h ; 83 c3 04 ; 0xfe03e orgs.asm:252
+ loop 0e039h ; e2 f6 ; 0xfe041 orgs.asm:253
+ retn ; c3 ; 0xfe043 orgs.asm:254
+ ; disGetNextSymbol 0xfe044 LB 0x1fbc -> off=0x0 cb=0000000000000006 uValue=00000000000f0044 'eoi_jmp_post'
+eoi_jmp_post: ; 0xfe044 LB 0x6
+ in AL, strict byte 060h ; e4 60 ; 0xfe044 orgs.asm:262
+ mov AL, strict byte 020h ; b0 20 ; 0xfe046 orgs.asm:263
+ out strict byte 020h, AL ; e6 20 ; 0xfe048 orgs.asm:264
+ ; disGetNextSymbol 0xfe04a LB 0x1fb6 -> off=0x0 cb=0000000000000009 uValue=00000000000f004a 'no_eoi_jmp_post'
+no_eoi_jmp_post: ; 0xfe04a LB 0x9
+ mov ax, strict word 00040h ; b8 40 00 ; 0xfe04a orgs.asm:267
+ mov ds, ax ; 8e d8 ; 0xfe04d orgs.asm:268
+ jmp far [word 00067h] ; ff 2e 67 00 ; 0xfe04f orgs.asm:269
+ ; disGetNextSymbol 0xfe053 LB 0x1fad -> off=0x0 cb=0000000000000002 uValue=00000000000f0053 'seg_40_value'
+seg_40_value: ; 0xfe053 LB 0x2
+ inc ax ; 40 ; 0xfe053
+ times 0x1 db 0
+ ; disGetNextSymbol 0xfe055 LB 0x1fab -> off=0x0 cb=0000000000000006 uValue=00000000000f0055 'biosorg_check_before_or_at_0E059h'
+biosorg_check_before_or_at_0E059h: ; 0xfe055 LB 0x6
+ add byte [bx+si], al ; 00 00 ; 0xfe055
+ add byte [bx+si], al ; 00 00 ; 0xfe057
+ pop ax ; 58 ; 0xfe059
+ dec bp ; 4d ; 0xfe05a
+ ; disGetNextSymbol 0xfe05b LB 0x1fa5 -> off=0x0 cb=000000000000006e uValue=00000000000f005b 'post'
+post: ; 0xfe05b LB 0x6e
+ cli ; fa ; 0xfe05b orgs.asm:278
+ smsw ax ; 0f 01 e0 ; 0xfe05c orgs.asm:284
+ test ax, strict word 00001h ; a9 01 00 ; 0xfe05f orgs.asm:285
+ je short 0e06ah ; 74 06 ; 0xfe062 orgs.asm:286
+ mov AL, strict byte 001h ; b0 01 ; 0xfe064 orgs.asm:295
+ out strict byte 092h, AL ; e6 92 ; 0xfe066 orgs.asm:296
+ jmp short 0e068h ; eb fe ; 0xfe068 orgs.asm:297
+ mov AL, strict byte 00fh ; b0 0f ; 0xfe06a orgs.asm:302
+ out strict byte 070h, AL ; e6 70 ; 0xfe06c orgs.asm:303
+ in AL, strict byte 071h ; e4 71 ; 0xfe06e orgs.asm:304
+ xchg ah, al ; 86 c4 ; 0xfe070 orgs.asm:307
+ in AL, strict byte 064h ; e4 64 ; 0xfe072 orgs.asm:311
+ test AL, strict byte 004h ; a8 04 ; 0xfe074 orgs.asm:312
+ je short 0e08bh ; 74 13 ; 0xfe076 orgs.asm:313
+ db 08ah, 0c4h
+ ; mov al, ah ; 8a c4 ; 0xfe078 orgs.asm:316
+ db 00ah, 0c0h
+ ; or al, al ; 0a c0 ; 0xfe07a orgs.asm:317
+ jne short 0e08bh ; 75 0d ; 0xfe07c orgs.asm:318
+ mov ds, [cs:0e053h] ; 2e 8e 1e 53 e0 ; 0xfe07e orgs.asm:324
+ cmp word [word 00072h], 01234h ; 81 3e 72 00 34 12 ; 0xfe083 orgs.asm:325
+ jne short 0e064h ; 75 d9 ; 0xfe089 orgs.asm:326
+ mov AL, strict byte 00fh ; b0 0f ; 0xfe08b orgs.asm:330
+ out strict byte 070h, AL ; e6 70 ; 0xfe08d orgs.asm:331
+ mov AL, strict byte 000h ; b0 00 ; 0xfe08f orgs.asm:332
+ out strict byte 071h, AL ; e6 71 ; 0xfe091 orgs.asm:333
+ db 08ah, 0c4h
+ ; mov al, ah ; 8a c4 ; 0xfe093 orgs.asm:337
+ cmp AL, strict byte 009h ; 3c 09 ; 0xfe095 orgs.asm:338
+ je short 0e0abh ; 74 12 ; 0xfe097 orgs.asm:339
+ cmp AL, strict byte 00ah ; 3c 0a ; 0xfe099 orgs.asm:340
+ je short 0e0abh ; 74 0e ; 0xfe09b orgs.asm:341
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xfe09d orgs.asm:343
+ out strict byte 00dh, AL ; e6 0d ; 0xfe09f orgs.asm:346
+ out strict byte 0dah, AL ; e6 da ; 0xfe0a1 orgs.asm:347
+ mov AL, strict byte 0c0h ; b0 c0 ; 0xfe0a3 orgs.asm:350
+ out strict byte 0d6h, AL ; e6 d6 ; 0xfe0a5 orgs.asm:351
+ mov AL, strict byte 000h ; b0 00 ; 0xfe0a7 orgs.asm:352
+ out strict byte 0d4h, AL ; e6 d4 ; 0xfe0a9 orgs.asm:353
+ db 08ah, 0c4h
+ ; mov al, ah ; 8a c4 ; 0xfe0ab orgs.asm:357
+ cmp AL, strict byte 000h ; 3c 00 ; 0xfe0ad orgs.asm:358
+ je short 0e0c9h ; 74 18 ; 0xfe0af orgs.asm:359
+ cmp AL, strict byte 00dh ; 3c 0d ; 0xfe0b1 orgs.asm:361
+ jnc short 0e0c9h ; 73 14 ; 0xfe0b3 orgs.asm:362
+ cmp AL, strict byte 009h ; 3c 09 ; 0xfe0b5 orgs.asm:363
+ jne short 0e0bch ; 75 03 ; 0xfe0b7 orgs.asm:364
+ jmp near 0e363h ; e9 a7 02 ; 0xfe0b9 orgs.asm:365
+ mov sp, 00400h ; bc 00 04 ; 0xfe0bc orgs.asm:368
+ cmp AL, strict byte 005h ; 3c 05 ; 0xfe0bf orgs.asm:370
+ je short 0e044h ; 74 81 ; 0xfe0c1 orgs.asm:371
+ cmp AL, strict byte 00ah ; 3c 0a ; 0xfe0c3 orgs.asm:373
+ je short 0e04ah ; 74 83 ; 0xfe0c5 orgs.asm:374
+ jmp short 0e0c9h ; eb 00 ; 0xfe0c7 orgs.asm:378
+ ; disGetNextSymbol 0xfe0c9 LB 0x1f37 -> off=0x0 cb=00000000000001f6 uValue=00000000000f00c9 'normal_post'
+normal_post: ; 0xfe0c9 LB 0x1f6
+ mov ax, 07800h ; b8 00 78 ; 0xfe0c9 orgs.asm:387
+ db 08bh, 0e0h
+ ; mov sp, ax ; 8b e0 ; 0xfe0cc orgs.asm:388
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe0ce orgs.asm:389
+ mov ds, ax ; 8e d8 ; 0xfe0d0 orgs.asm:390
+ mov ss, ax ; 8e d0 ; 0xfe0d2 orgs.asm:391
+ mov es, ax ; 8e c0 ; 0xfe0d4 orgs.asm:395
+ db 033h, 0ffh
+ ; xor di, di ; 33 ff ; 0xfe0d6 orgs.asm:396
+ cld ; fc ; 0xfe0d8 orgs.asm:397
+ mov cx, 00239h ; b9 39 02 ; 0xfe0d9 orgs.asm:398
+ rep stosw ; f3 ab ; 0xfe0dc orgs.asm:399
+ inc di ; 47 ; 0xfe0de orgs.asm:400
+ inc di ; 47 ; 0xfe0df orgs.asm:401
+ mov cx, 005c6h ; b9 c6 05 ; 0xfe0e0 orgs.asm:402
+ rep stosw ; f3 ab ; 0xfe0e3 orgs.asm:403
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe0e5 orgs.asm:407
+ add bx, 01000h ; 81 c3 00 10 ; 0xfe0e7 orgs.asm:409
+ cmp bx, 09000h ; 81 fb 00 90 ; 0xfe0eb orgs.asm:410
+ jnc short 0e0fch ; 73 0b ; 0xfe0ef orgs.asm:411
+ mov es, bx ; 8e c3 ; 0xfe0f1 orgs.asm:412
+ db 033h, 0ffh
+ ; xor di, di ; 33 ff ; 0xfe0f3 orgs.asm:413
+ mov cx, 08000h ; b9 00 80 ; 0xfe0f5 orgs.asm:414
+ rep stosw ; f3 ab ; 0xfe0f8 orgs.asm:415
+ jmp short 0e0e7h ; eb eb ; 0xfe0fa orgs.asm:416
+ mov es, bx ; 8e c3 ; 0xfe0fc orgs.asm:418
+ db 033h, 0ffh
+ ; xor di, di ; 33 ff ; 0xfe0fe orgs.asm:419
+ mov cx, 07ff8h ; b9 f8 7f ; 0xfe100 orgs.asm:420
+ rep stosw ; f3 ab ; 0xfe103 orgs.asm:421
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe105 orgs.asm:422
+ push CS ; 0e ; 0xfe107 orgs.asm:104
+ pop DS ; 1f ; 0xfe108 orgs.asm:105
+ cld ; fc ; 0xfe109 orgs.asm:106
+ call 01820h ; e8 13 37 ; 0xfe10a orgs.asm:426
+ call 0e8e7h ; e8 d7 07 ; 0xfe10d orgs.asm:429
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe110 orgs.asm:433
+ mov ds, bx ; 8e db ; 0xfe112 orgs.asm:434
+ mov cx, strict word 00060h ; b9 60 00 ; 0xfe114 orgs.asm:435
+ mov ax, 0ff53h ; b8 53 ff ; 0xfe117 orgs.asm:436
+ mov dx, 0f000h ; ba 00 f0 ; 0xfe11a orgs.asm:437
+ call 0e039h ; e8 19 ff ; 0xfe11d orgs.asm:438
+ mov bx, 001a0h ; bb a0 01 ; 0xfe120 orgs.asm:443
+ mov cx, strict word 00010h ; b9 10 00 ; 0xfe123 orgs.asm:444
+ call 0e039h ; e8 10 ff ; 0xfe126 orgs.asm:445
+ mov ax, 0027fh ; b8 7f 02 ; 0xfe129 orgs.asm:448
+ mov word [00413h], ax ; a3 13 04 ; 0xfe12c orgs.asm:449
+ mov ax, 0e9cch ; b8 cc e9 ; 0xfe12f orgs.asm:95
+ mov word [00018h], ax ; a3 18 00 ; 0xfe132 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe135 orgs.asm:97
+ mov word [0001ah], ax ; a3 1a 00 ; 0xfe138 orgs.asm:98
+ mov ax, 0f84dh ; b8 4d f8 ; 0xfe13b orgs.asm:95
+ mov word [00044h], ax ; a3 44 00 ; 0xfe13e orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe141 orgs.asm:97
+ mov word [00046h], ax ; a3 46 00 ; 0xfe144 orgs.asm:98
+ mov ax, 0f841h ; b8 41 f8 ; 0xfe147 orgs.asm:95
+ mov word [00048h], ax ; a3 48 00 ; 0xfe14a orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe14d orgs.asm:97
+ mov word [0004ah], ax ; a3 4a 00 ; 0xfe150 orgs.asm:98
+ mov ax, 0f859h ; b8 59 f8 ; 0xfe153 orgs.asm:95
+ mov word [00054h], ax ; a3 54 00 ; 0xfe156 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe159 orgs.asm:97
+ mov word [00056h], ax ; a3 56 00 ; 0xfe15c orgs.asm:98
+ mov ax, 0efd4h ; b8 d4 ef ; 0xfe15f orgs.asm:95
+ mov word [0005ch], ax ; a3 5c 00 ; 0xfe162 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe165 orgs.asm:97
+ mov word [0005eh], ax ; a3 5e 00 ; 0xfe168 orgs.asm:98
+ mov ax, 0f0a4h ; b8 a4 f0 ; 0xfe16b orgs.asm:95
+ mov word [00060h], ax ; a3 60 00 ; 0xfe16e orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe171 orgs.asm:97
+ mov word [00062h], ax ; a3 62 00 ; 0xfe174 orgs.asm:98
+ mov ax, 0e6f2h ; b8 f2 e6 ; 0xfe177 orgs.asm:95
+ mov word [00064h], ax ; a3 64 00 ; 0xfe17a orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe17d orgs.asm:97
+ mov word [00066h], ax ; a3 66 00 ; 0xfe180 orgs.asm:98
+ mov ax, 0efedh ; b8 ed ef ; 0xfe183 orgs.asm:95
+ mov word [00070h], ax ; a3 70 00 ; 0xfe186 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe189 orgs.asm:97
+ mov word [00072h], ax ; a3 72 00 ; 0xfe18c orgs.asm:98
+ call 0e778h ; e8 e6 05 ; 0xfe18f orgs.asm:465
+ call 0f13bh ; e8 a6 0f ; 0xfe192 orgs.asm:469
+ call 0f166h ; e8 ce 0f ; 0xfe195 orgs.asm:470
+ mov ax, 0fe6eh ; b8 6e fe ; 0xfe198 orgs.asm:95
+ mov word [00068h], ax ; a3 68 00 ; 0xfe19b orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe19e orgs.asm:97
+ mov word [0006ah], ax ; a3 6a 00 ; 0xfe1a1 orgs.asm:98
+ mov ax, 0fea5h ; b8 a5 fe ; 0xfe1a4 orgs.asm:95
+ mov word [00020h], ax ; a3 20 00 ; 0xfe1a7 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe1aa orgs.asm:97
+ mov word [00022h], ax ; a3 22 00 ; 0xfe1ad orgs.asm:98
+ mov AL, strict byte 034h ; b0 34 ; 0xfe1b0 orgs.asm:476
+ out strict byte 043h, AL ; e6 43 ; 0xfe1b2 orgs.asm:477
+ mov AL, strict byte 000h ; b0 00 ; 0xfe1b4 orgs.asm:478
+ out strict byte 040h, AL ; e6 40 ; 0xfe1b6 orgs.asm:479
+ out strict byte 040h, AL ; e6 40 ; 0xfe1b8 orgs.asm:480
+ mov ax, 0f065h ; b8 65 f0 ; 0xfe1ba orgs.asm:95
+ mov word [00040h], ax ; a3 40 00 ; 0xfe1bd orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe1c0 orgs.asm:97
+ mov word [00042h], ax ; a3 42 00 ; 0xfe1c3 orgs.asm:98
+ mov ax, 0e987h ; b8 87 e9 ; 0xfe1c6 orgs.asm:95
+ mov word [00024h], ax ; a3 24 00 ; 0xfe1c9 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe1cc orgs.asm:97
+ mov word [00026h], ax ; a3 26 00 ; 0xfe1cf orgs.asm:98
+ mov ax, 0e82eh ; b8 2e e8 ; 0xfe1d2 orgs.asm:95
+ mov word [00058h], ax ; a3 58 00 ; 0xfe1d5 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe1d8 orgs.asm:97
+ mov word [0005ah], ax ; a3 5a 00 ; 0xfe1db orgs.asm:98
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe1de orgs.asm:489
+ mov ds, ax ; 8e d8 ; 0xfe1e0 orgs.asm:490
+ mov byte [00417h], AL ; a2 17 04 ; 0xfe1e2 orgs.asm:492
+ mov byte [00418h], AL ; a2 18 04 ; 0xfe1e5 orgs.asm:493
+ mov byte [00419h], AL ; a2 19 04 ; 0xfe1e8 orgs.asm:494
+ mov byte [00471h], AL ; a2 71 04 ; 0xfe1eb orgs.asm:495
+ mov byte [00497h], AL ; a2 97 04 ; 0xfe1ee orgs.asm:496
+ mov AL, strict byte 010h ; b0 10 ; 0xfe1f1 orgs.asm:497
+ mov byte [00496h], AL ; a2 96 04 ; 0xfe1f3 orgs.asm:498
+ mov bx, strict word 0001eh ; bb 1e 00 ; 0xfe1f6 orgs.asm:500
+ mov word [0041ah], bx ; 89 1e 1a 04 ; 0xfe1f9 orgs.asm:501
+ mov word [0041ch], bx ; 89 1e 1c 04 ; 0xfe1fd orgs.asm:502
+ mov word [00480h], bx ; 89 1e 80 04 ; 0xfe201 orgs.asm:503
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xfe205 orgs.asm:504
+ mov word [00482h], bx ; 89 1e 82 04 ; 0xfe208 orgs.asm:505
+ mov AL, strict byte 014h ; b0 14 ; 0xfe20c orgs.asm:508
+ out strict byte 070h, AL ; e6 70 ; 0xfe20e orgs.asm:509
+ in AL, strict byte 071h ; e4 71 ; 0xfe210 orgs.asm:510
+ mov byte [00410h], AL ; a2 10 04 ; 0xfe212 orgs.asm:511
+ push DS ; 1e ; 0xfe215 orgs.asm:513
+ push CS ; 0e ; 0xfe216 orgs.asm:104
+ pop DS ; 1f ; 0xfe217 orgs.asm:105
+ cld ; fc ; 0xfe218 orgs.asm:106
+ mov ax, 0c000h ; b8 00 c0 ; 0xfe219 orgs.asm:518
+ mov dx, 0c800h ; ba 00 c8 ; 0xfe21c orgs.asm:519
+ call 01600h ; e8 de 33 ; 0xfe21f orgs.asm:520
+ call 04f68h ; e8 43 6d ; 0xfe222 orgs.asm:523
+ pop DS ; 1f ; 0xfe225 orgs.asm:524
+ mov ax, 0ff53h ; b8 53 ff ; 0xfe226 orgs.asm:95
+ mov word [0003ch], ax ; a3 3c 00 ; 0xfe229 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe22c orgs.asm:97
+ mov word [0003eh], ax ; a3 3e 00 ; 0xfe22f orgs.asm:98
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe232 orgs.asm:528
+ mov ds, ax ; 8e d8 ; 0xfe234 orgs.asm:529
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe236 orgs.asm:530
+ mov CL, strict byte 014h ; b1 14 ; 0xfe238 orgs.asm:531
+ mov dx, 00378h ; ba 78 03 ; 0xfe23a orgs.asm:532
+ call 0ecedh ; e8 ad 0a ; 0xfe23d orgs.asm:533
+ mov dx, 00278h ; ba 78 02 ; 0xfe240 orgs.asm:534
+ call 0ecedh ; e8 a7 0a ; 0xfe243 orgs.asm:535
+ sal bx, 00eh ; c1 e3 0e ; 0xfe246 orgs.asm:200
+ mov ax, word [00410h] ; a1 10 04 ; 0xfe249 orgs.asm:537
+ and ax, 03fffh ; 25 ff 3f ; 0xfe24c orgs.asm:538
+ db 00bh, 0c3h
+ ; or ax, bx ; 0b c3 ; 0xfe24f orgs.asm:539
+ mov word [00410h], ax ; a3 10 04 ; 0xfe251 orgs.asm:540
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe254 orgs.asm:95
+ mov word [0002ch], ax ; a3 2c 00 ; 0xfe257 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe25a orgs.asm:97
+ mov word [0002eh], ax ; a3 2e 00 ; 0xfe25d orgs.asm:98
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe260 orgs.asm:95
+ mov word [00030h], ax ; a3 30 00 ; 0xfe263 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe266 orgs.asm:97
+ mov word [00032h], ax ; a3 32 00 ; 0xfe269 orgs.asm:98
+ mov ax, 0e739h ; b8 39 e7 ; 0xfe26c orgs.asm:95
+ mov word [00050h], ax ; a3 50 00 ; 0xfe26f orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe272 orgs.asm:97
+ mov word [00052h], ax ; a3 52 00 ; 0xfe275 orgs.asm:98
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe278 orgs.asm:546
+ mov CL, strict byte 00ah ; b1 0a ; 0xfe27a orgs.asm:547
+ mov dx, 003f8h ; ba f8 03 ; 0xfe27c orgs.asm:548
+ call 0ed0bh ; e8 89 0a ; 0xfe27f orgs.asm:549
+ mov dx, 002f8h ; ba f8 02 ; 0xfe282 orgs.asm:550
+ call 0ed0bh ; e8 83 0a ; 0xfe285 orgs.asm:551
+ mov dx, 003e8h ; ba e8 03 ; 0xfe288 orgs.asm:552
+ call 0ed0bh ; e8 7d 0a ; 0xfe28b orgs.asm:553
+ mov dx, 002e8h ; ba e8 02 ; 0xfe28e orgs.asm:554
+ call 0ed0bh ; e8 77 0a ; 0xfe291 orgs.asm:555
+ sal bx, 009h ; c1 e3 09 ; 0xfe294 orgs.asm:200
+ mov ax, word [00410h] ; a1 10 04 ; 0xfe297 orgs.asm:557
+ and ax, 0f1ffh ; 25 ff f1 ; 0xfe29a orgs.asm:558
+ db 00bh, 0c3h
+ ; or ax, bx ; 0b c3 ; 0xfe29d orgs.asm:559
+ mov word [00410h], ax ; a3 10 04 ; 0xfe29f orgs.asm:560
+ mov ax, 0ff53h ; b8 53 ff ; 0xfe2a2 orgs.asm:95
+ mov word [00128h], ax ; a3 28 01 ; 0xfe2a5 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe2a8 orgs.asm:97
+ mov word [0012ah], ax ; a3 2a 01 ; 0xfe2ab orgs.asm:98
+ mov ax, 0f8f9h ; b8 f9 f8 ; 0xfe2ae orgs.asm:95
+ mov word [001c0h], ax ; a3 c0 01 ; 0xfe2b1 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe2b4 orgs.asm:97
+ mov word [001c2h], ax ; a3 c2 01 ; 0xfe2b7 orgs.asm:98
+ call 0edbfh ; e8 02 0b ; 0xfe2ba orgs.asm:566
+ jmp short 0e303h ; eb 44 ; 0xfe2bd orgs.asm:568
+ ; disGetNextSymbol 0xfe2bf LB 0x1d41 -> off=0x0 cb=0000000000000004 uValue=00000000000f02bf 'biosorg_check_before_or_at_0E2C1h'
+biosorg_check_before_or_at_0E2C1h: ; 0xfe2bf LB 0x4
+ add byte [bx+si], al ; 00 00 ; 0xfe2bf
+ pop ax ; 58 ; 0xfe2c1
+ dec bp ; 4d ; 0xfe2c2
+ ; disGetNextSymbol 0xfe2c3 LB 0x1d3d -> off=0x0 cb=0000000000000007 uValue=00000000000f02c3 'nmi'
+nmi: ; 0xfe2c3 LB 0x7
+ push CS ; 0e ; 0xfe2c3 orgs.asm:104
+ pop DS ; 1f ; 0xfe2c4 orgs.asm:105
+ cld ; fc ; 0xfe2c5 orgs.asm:106
+ call 017fch ; e8 33 35 ; 0xfe2c6 orgs.asm:577
+ iret ; cf ; 0xfe2c9 orgs.asm:578
+ ; disGetNextSymbol 0xfe2ca LB 0x1d36 -> off=0x0 cb=0000000000000008 uValue=00000000000f02ca 'int75_handler'
+int75_handler: ; 0xfe2ca LB 0x8
+ out strict byte 0f0h, AL ; e6 f0 ; 0xfe2ca orgs.asm:581
+ call 0e030h ; e8 61 fd ; 0xfe2cc orgs.asm:582
+ int 002h ; cd 02 ; 0xfe2cf orgs.asm:583
+ iret ; cf ; 0xfe2d1 orgs.asm:584
+ ; disGetNextSymbol 0xfe2d2 LB 0x1d2e -> off=0x0 cb=00000000000000ba uValue=00000000000f02d2 'hard_drive_post'
+hard_drive_post: ; 0xfe2d2 LB 0xba
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe2d2 orgs.asm:589
+ mov ds, ax ; 8e d8 ; 0xfe2d4 orgs.asm:590
+ mov byte [00474h], AL ; a2 74 04 ; 0xfe2d6 orgs.asm:592
+ mov byte [00477h], AL ; a2 77 04 ; 0xfe2d9 orgs.asm:593
+ mov byte [0048ch], AL ; a2 8c 04 ; 0xfe2dc orgs.asm:594
+ mov byte [0048dh], AL ; a2 8d 04 ; 0xfe2df orgs.asm:595
+ mov byte [0048eh], AL ; a2 8e 04 ; 0xfe2e2 orgs.asm:596
+ mov AL, strict byte 0c0h ; b0 c0 ; 0xfe2e5 orgs.asm:597
+ mov byte [00476h], AL ; a2 76 04 ; 0xfe2e7 orgs.asm:598
+ mov ax, 0e3feh ; b8 fe e3 ; 0xfe2ea orgs.asm:95
+ mov word [0004ch], ax ; a3 4c 00 ; 0xfe2ed orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe2f0 orgs.asm:97
+ mov word [0004eh], ax ; a3 4e 00 ; 0xfe2f3 orgs.asm:98
+ mov ax, 0f8e7h ; b8 e7 f8 ; 0xfe2f6 orgs.asm:95
+ mov word [001d8h], ax ; a3 d8 01 ; 0xfe2f9 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe2fc orgs.asm:97
+ mov word [001dah], ax ; a3 da 01 ; 0xfe2ff orgs.asm:98
+ retn ; c3 ; 0xfe302 orgs.asm:603
+ mov ax, 0f8bch ; b8 bc f8 ; 0xfe303 orgs.asm:95
+ mov word [001d0h], ax ; a3 d0 01 ; 0xfe306 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe309 orgs.asm:97
+ mov word [001d2h], ax ; a3 d2 01 ; 0xfe30c orgs.asm:98
+ mov ax, 0e2cah ; b8 ca e2 ; 0xfe30f orgs.asm:95
+ mov word [001d4h], ax ; a3 d4 01 ; 0xfe312 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe315 orgs.asm:97
+ mov word [001d6h], ax ; a3 d6 01 ; 0xfe318 orgs.asm:98
+ call 0e753h ; e8 35 04 ; 0xfe31b orgs.asm:615
+ push CS ; 0e ; 0xfe31e orgs.asm:104
+ pop DS ; 1f ; 0xfe31f orgs.asm:105
+ cld ; fc ; 0xfe320 orgs.asm:106
+ pushad ; 66 60 ; 0xfe321 orgs.asm:622
+ call 01692h ; e8 6c 33 ; 0xfe323 orgs.asm:623
+ popad ; 66 61 ; 0xfe326 orgs.asm:624
+ call 01d51h ; e8 26 3a ; 0xfe328 orgs.asm:629
+ call 021dch ; e8 ae 3e ; 0xfe32b orgs.asm:630
+ sti ; fb ; 0xfe32e orgs.asm:637
+ call 09819h ; e8 e7 b4 ; 0xfe32f orgs.asm:638
+ cli ; fa ; 0xfe332 orgs.asm:639
+ call 086cch ; e8 96 a3 ; 0xfe333 orgs.asm:644
+ call 0ed2fh ; e8 f6 09 ; 0xfe336 orgs.asm:648
+ call 0e2d2h ; e8 96 ff ; 0xfe339 orgs.asm:651
+ push CS ; 0e ; 0xfe33c orgs.asm:104
+ pop DS ; 1f ; 0xfe33d orgs.asm:105
+ cld ; fc ; 0xfe33e orgs.asm:106
+ mov ax, 0c800h ; b8 00 c8 ; 0xfe33f orgs.asm:655
+ mov dx, 0f000h ; ba 00 f0 ; 0xfe342 orgs.asm:656
+ call 01600h ; e8 b8 32 ; 0xfe345 orgs.asm:657
+ db 066h, 033h, 0c0h
+ ; xor eax, eax ; 66 33 c0 ; 0xfe348 orgs.asm:664
+ db 066h, 033h, 0dbh
+ ; xor ebx, ebx ; 66 33 db ; 0xfe34b orgs.asm:665
+ db 066h, 033h, 0c9h
+ ; xor ecx, ecx ; 66 33 c9 ; 0xfe34e orgs.asm:666
+ db 066h, 033h, 0d2h
+ ; xor edx, edx ; 66 33 d2 ; 0xfe351 orgs.asm:667
+ call 01840h ; e8 e9 34 ; 0xfe354 orgs.asm:671
+ call 03c84h ; e8 2a 59 ; 0xfe357 orgs.asm:674
+ sti ; fb ; 0xfe35a orgs.asm:677
+ int 019h ; cd 19 ; 0xfe35b orgs.asm:678
+ sti ; fb ; 0xfe35d orgs.asm:680
+ hlt ; f4 ; 0xfe35e orgs.asm:682
+ jmp short 0e35eh ; eb fd ; 0xfe35f orgs.asm:683
+ cli ; fa ; 0xfe361 orgs.asm:684
+ hlt ; f4 ; 0xfe362 orgs.asm:685
+ mov ax, strict word 00040h ; b8 40 00 ; 0xfe363 orgs.asm:694
+ mov ds, ax ; 8e d8 ; 0xfe366 orgs.asm:695
+ mov ss, [word 00069h] ; 8e 16 69 00 ; 0xfe368 orgs.asm:697
+ mov sp, word [word 00067h] ; 8b 26 67 00 ; 0xfe36c orgs.asm:698
+ in AL, strict byte 092h ; e4 92 ; 0xfe370 orgs.asm:700
+ and AL, strict byte 0fdh ; 24 fd ; 0xfe372 orgs.asm:701
+ out strict byte 092h, AL ; e6 92 ; 0xfe374 orgs.asm:702
+ lidt [cs:0efe7h] ; 2e 0f 01 1e e7 ef ; 0xfe376 orgs.asm:704
+ pop DS ; 1f ; 0xfe37c orgs.asm:706
+ pop ES ; 07 ; 0xfe37d orgs.asm:707
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xfe37e orgs.asm:709
+ in AL, strict byte 080h ; e4 80 ; 0xfe380 orgs.asm:711
+ mov byte [bp+00fh], al ; 88 46 0f ; 0xfe382 orgs.asm:712
+ db 03ah, 0e0h
+ ; cmp ah, al ; 3a e0 ; 0xfe385 orgs.asm:714
+ popaw ; 61 ; 0xfe387 orgs.asm:716
+ sti ; fb ; 0xfe388 orgs.asm:717
+ retf 00002h ; ca 02 00 ; 0xfe389 orgs.asm:718
+ ; disGetNextSymbol 0xfe38c LB 0x1c74 -> off=0x0 cb=0000000000000072 uValue=00000000000f038c 'biosorg_check_before_or_at_0E3FCh'
+biosorg_check_before_or_at_0E3FCh: ; 0xfe38c LB 0x72
+ times 0x70 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe3fe LB 0x1c02 -> off=0x0 cb=0000000000000003 uValue=00000000000f03fe 'int13_handler'
+int13_handler: ; 0xfe3fe LB 0x3
+ jmp near 0ec5bh ; e9 5a 08 ; 0xfe3fe orgs.asm:728
+ ; disGetNextSymbol 0xfe401 LB 0x1bff -> off=0x0 cb=00000000000002f1 uValue=00000000000f0401 'rom_fdpt'
+rom_fdpt: ; 0xfe401 LB 0x2f1
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 058h
+ db 04dh
+ ; disGetNextSymbol 0xfe6f2 LB 0x190e -> off=0x0 cb=0000000000000003 uValue=00000000000f06f2 'int19_handler'
+int19_handler: ; 0xfe6f2 LB 0x3
+ jmp near 0f0ach ; e9 b7 09 ; 0xfe6f2 orgs.asm:744
+ ; disGetNextSymbol 0xfe6f5 LB 0x190b -> off=0x0 cb=000000000000000a uValue=00000000000f06f5 'biosorg_check_at_0E6F5h'
+biosorg_check_at_0E6F5h: ; 0xfe6f5 LB 0xa
+ or word [bx+si], ax ; 09 00 ; 0xfe6f5
+ cld ; fc ; 0xfe6f7
+ add byte [bx+di], al ; 00 01 ; 0xfe6f8
+ je short 0e73ch ; 74 40 ; 0xfe6fa
+ times 0x3 db 0
+ ; disGetNextSymbol 0xfe6ff LB 0x1901 -> off=0x0 cb=000000000000002a uValue=00000000000f06ff 'biosorg_check_before_or_at_0E727h'
+biosorg_check_before_or_at_0E727h: ; 0xfe6ff LB 0x2a
+ times 0x28 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe729 LB 0x18d7 -> off=0x0 cb=0000000000000010 uValue=00000000000f0729 'biosorg_check_at_0E729h'
+biosorg_check_at_0E729h: ; 0xfe729 LB 0x10
+ times 0xe db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe739 LB 0x18c7 -> off=0x0 cb=000000000000001a uValue=00000000000f0739 'biosorg_check_at_0E739h'
+biosorg_check_at_0E739h: ; 0xfe739 LB 0x1a
+ push DS ; 1e ; 0xfe739 orgs.asm:817
+ push ES ; 06 ; 0xfe73a orgs.asm:818
+ pushaw ; 60 ; 0xfe73b orgs.asm:97
+ push CS ; 0e ; 0xfe73c orgs.asm:104
+ pop DS ; 1f ; 0xfe73d orgs.asm:105
+ cld ; fc ; 0xfe73e orgs.asm:106
+ call 06457h ; e8 15 7d ; 0xfe73f orgs.asm:821
+ popaw ; 61 ; 0xfe742 orgs.asm:114
+ pop ES ; 07 ; 0xfe743 orgs.asm:823
+ pop DS ; 1f ; 0xfe744 orgs.asm:824
+ iret ; cf ; 0xfe745 orgs.asm:825
+ push DS ; 1e ; 0xfe746 orgs.asm:833
+ push ES ; 06 ; 0xfe747 orgs.asm:834
+ pushaw ; 60 ; 0xfe748 orgs.asm:97
+ push CS ; 0e ; 0xfe749 orgs.asm:104
+ pop DS ; 1f ; 0xfe74a orgs.asm:105
+ cld ; fc ; 0xfe74b orgs.asm:106
+ call 01792h ; e8 43 30 ; 0xfe74c orgs.asm:837
+ popaw ; 61 ; 0xfe74f orgs.asm:114
+ pop ES ; 07 ; 0xfe750 orgs.asm:839
+ pop DS ; 1f ; 0xfe751 orgs.asm:840
+ iret ; cf ; 0xfe752 orgs.asm:841
+ ; disGetNextSymbol 0xfe753 LB 0x18ad -> off=0x0 cb=0000000000000025 uValue=00000000000f0753 'init_pic'
+init_pic: ; 0xfe753 LB 0x25
+ mov AL, strict byte 011h ; b0 11 ; 0xfe753 orgs.asm:846
+ out strict byte 020h, AL ; e6 20 ; 0xfe755 orgs.asm:847
+ out strict byte 0a0h, AL ; e6 a0 ; 0xfe757 orgs.asm:848
+ mov AL, strict byte 008h ; b0 08 ; 0xfe759 orgs.asm:849
+ out strict byte 021h, AL ; e6 21 ; 0xfe75b orgs.asm:850
+ mov AL, strict byte 070h ; b0 70 ; 0xfe75d orgs.asm:851
+ out strict byte 0a1h, AL ; e6 a1 ; 0xfe75f orgs.asm:852
+ mov AL, strict byte 004h ; b0 04 ; 0xfe761 orgs.asm:853
+ out strict byte 021h, AL ; e6 21 ; 0xfe763 orgs.asm:854
+ mov AL, strict byte 002h ; b0 02 ; 0xfe765 orgs.asm:855
+ out strict byte 0a1h, AL ; e6 a1 ; 0xfe767 orgs.asm:856
+ mov AL, strict byte 001h ; b0 01 ; 0xfe769 orgs.asm:857
+ out strict byte 021h, AL ; e6 21 ; 0xfe76b orgs.asm:858
+ out strict byte 0a1h, AL ; e6 a1 ; 0xfe76d orgs.asm:859
+ mov AL, strict byte 0b8h ; b0 b8 ; 0xfe76f orgs.asm:860
+ out strict byte 021h, AL ; e6 21 ; 0xfe771 orgs.asm:861
+ mov AL, strict byte 08fh ; b0 8f ; 0xfe773 orgs.asm:862
+ out strict byte 0a1h, AL ; e6 a1 ; 0xfe775 orgs.asm:863
+ retn ; c3 ; 0xfe777 orgs.asm:864
+ ; disGetNextSymbol 0xfe778 LB 0x1888 -> off=0x0 cb=0000000000000051 uValue=00000000000f0778 'ebda_post'
+ebda_post: ; 0xfe778 LB 0x51
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe778 orgs.asm:95
+ mov word [00034h], ax ; a3 34 00 ; 0xfe77b orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe77e orgs.asm:97
+ mov word [00036h], ax ; a3 36 00 ; 0xfe781 orgs.asm:98
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe784 orgs.asm:95
+ mov word [0003ch], ax ; a3 3c 00 ; 0xfe787 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe78a orgs.asm:97
+ mov word [0003eh], ax ; a3 3e 00 ; 0xfe78d orgs.asm:98
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe790 orgs.asm:95
+ mov word [001c8h], ax ; a3 c8 01 ; 0xfe793 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe796 orgs.asm:97
+ mov word [001cah], ax ; a3 ca 01 ; 0xfe799 orgs.asm:98
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe79c orgs.asm:95
+ mov word [001cch], ax ; a3 cc 01 ; 0xfe79f orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe7a2 orgs.asm:97
+ mov word [001ceh], ax ; a3 ce 01 ; 0xfe7a5 orgs.asm:98
+ mov ax, 0e746h ; b8 46 e7 ; 0xfe7a8 orgs.asm:95
+ mov word [001dch], ax ; a3 dc 01 ; 0xfe7ab orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe7ae orgs.asm:97
+ mov word [001deh], ax ; a3 de 01 ; 0xfe7b1 orgs.asm:98
+ mov ax, 09fc0h ; b8 c0 9f ; 0xfe7b4 orgs.asm:876
+ mov ds, ax ; 8e d8 ; 0xfe7b7 orgs.asm:877
+ mov byte [word 00000h], 001h ; c6 06 00 00 01 ; 0xfe7b9 orgs.asm:878
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe7be orgs.asm:880
+ mov ds, ax ; 8e d8 ; 0xfe7c0 orgs.asm:881
+ mov word [0040eh], 09fc0h ; c7 06 0e 04 c0 9f ; 0xfe7c2 orgs.asm:882
+ retn ; c3 ; 0xfe7c8 orgs.asm:883
+ ; disGetNextSymbol 0xfe7c9 LB 0x1837 -> off=0x0 cb=0000000000000065 uValue=00000000000f07c9 'biosorg_check_before_or_at_0E82Ch'
+biosorg_check_before_or_at_0E82Ch: ; 0xfe7c9 LB 0x65
+ times 0x63 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe82e LB 0x17d2 -> off=0x0 cb=000000000000003d uValue=00000000000f082e 'biosorg_check_at_0E82Eh'
+biosorg_check_at_0E82Eh: ; 0xfe82e LB 0x3d
+ sti ; fb ; 0xfe82e orgs.asm:894
+ pushfw ; 9c ; 0xfe82f orgs.asm:897
+ push ES ; 06 ; 0xfe830 orgs.asm:898
+ push DS ; 1e ; 0xfe831 orgs.asm:899
+ pushaw ; 60 ; 0xfe832 orgs.asm:97
+ cmp ah, 000h ; 80 fc 00 ; 0xfe833 orgs.asm:902
+ je short 0e84ah ; 74 12 ; 0xfe836 orgs.asm:903
+ cmp ah, 010h ; 80 fc 10 ; 0xfe838 orgs.asm:905
+ je short 0e84ah ; 74 0d ; 0xfe83b orgs.asm:906
+ push CS ; 0e ; 0xfe83d orgs.asm:104
+ pop DS ; 1f ; 0xfe83e orgs.asm:105
+ cld ; fc ; 0xfe83f orgs.asm:106
+ call 056b6h ; e8 73 6e ; 0xfe840 orgs.asm:909
+ popaw ; 61 ; 0xfe843 orgs.asm:114
+ pop DS ; 1f ; 0xfe844 orgs.asm:911
+ pop ES ; 07 ; 0xfe845 orgs.asm:912
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xfe846 orgs.asm:913
+ iret ; cf ; 0xfe849 orgs.asm:914
+ mov bx, strict word 00040h ; bb 40 00 ; 0xfe84a orgs.asm:917
+ mov ds, bx ; 8e db ; 0xfe84d orgs.asm:918
+ cli ; fa ; 0xfe84f orgs.asm:920
+ mov bx, word [word 0001ah] ; 8b 1e 1a 00 ; 0xfe850 orgs.asm:921
+ cmp bx, word [word 0001ch] ; 3b 1e 1c 00 ; 0xfe854 orgs.asm:922
+ jne short 0e85eh ; 75 04 ; 0xfe858 orgs.asm:923
+ sti ; fb ; 0xfe85a orgs.asm:924
+ nop ; 90 ; 0xfe85b orgs.asm:925
+ jmp short 0e84fh ; eb f1 ; 0xfe85c orgs.asm:933
+ push CS ; 0e ; 0xfe85e orgs.asm:104
+ pop DS ; 1f ; 0xfe85f orgs.asm:105
+ cld ; fc ; 0xfe860 orgs.asm:106
+ call 056b6h ; e8 52 6e ; 0xfe861 orgs.asm:937
+ popaw ; 61 ; 0xfe864 orgs.asm:114
+ pop DS ; 1f ; 0xfe865 orgs.asm:939
+ pop ES ; 07 ; 0xfe866 orgs.asm:940
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xfe867 orgs.asm:941
+ iret ; cf ; 0xfe86a orgs.asm:949
+ ; disGetNextSymbol 0xfe86b LB 0x1795 -> off=0x0 cb=000000000000001b uValue=00000000000f086b 'pmode_enter'
+pmode_enter: ; 0xfe86b LB 0x1b
+ push CS ; 0e ; 0xfe86b orgs.asm:30
+ pop DS ; 1f ; 0xfe86c orgs.asm:31
+ lgdt [cs:0e899h] ; 2e 0f 01 16 99 e8 ; 0xfe86d orgs.asm:33
+ mov eax, cr0 ; 0f 20 c0 ; 0xfe873 orgs.asm:34
+ or AL, strict byte 001h ; 0c 01 ; 0xfe876 orgs.asm:35
+ mov cr0, eax ; 0f 22 c0 ; 0xfe878 orgs.asm:36
+ jmp far 00020h:0e880h ; ea 80 e8 20 00 ; 0xfe87b
+ mov ax, strict word 00018h ; b8 18 00 ; 0xfe880 orgs.asm:42
+ mov ds, ax ; 8e d8 ; 0xfe883 orgs.asm:43
+ retn ; c3 ; 0xfe885 orgs.asm:44
+ ; disGetNextSymbol 0xfe886 LB 0x177a -> off=0x0 cb=0000000000000013 uValue=00000000000f0886 'pmode_exit'
+pmode_exit: ; 0xfe886 LB 0x13
+ mov ax, strict word 00040h ; b8 40 00 ; 0xfe886 orgs.asm:51
+ mov ds, ax ; 8e d8 ; 0xfe889 orgs.asm:52
+ mov eax, cr0 ; 0f 20 c0 ; 0xfe88b orgs.asm:54
+ and AL, strict byte 0feh ; 24 fe ; 0xfe88e orgs.asm:55
+ mov cr0, eax ; 0f 22 c0 ; 0xfe890 orgs.asm:56
+ jmp far 0f000h:0e898h ; ea 98 e8 00 f0 ; 0xfe893 orgs.asm:58
+ retn ; c3 ; 0xfe898 orgs.asm:60
+ ; disGetNextSymbol 0xfe899 LB 0x1767 -> off=0x0 cb=0000000000000006 uValue=00000000000f0899 'pmbios_gdt_desc'
+pmbios_gdt_desc: ; 0xfe899 LB 0x6
+ db 047h, 000h, 09fh, 0e8h, 00fh, 000h
+ ; disGetNextSymbol 0xfe89f LB 0x1761 -> off=0x0 cb=0000000000000048 uValue=00000000000f089f 'pmbios_gdt'
+pmbios_gdt: ; 0xfe89f LB 0x48
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 0ffh, 0ffh, 000h, 000h, 000h, 09bh, 0cfh, 000h, 0ffh, 0ffh, 000h, 000h, 000h, 093h, 0cfh, 000h
+ db 0ffh, 0ffh, 000h, 000h, 00fh, 09bh, 000h, 000h, 0ffh, 0ffh, 000h, 000h, 000h, 093h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 0ffh, 0ffh, 000h, 004h, 000h, 093h, 000h, 000h
+ ; disGetNextSymbol 0xfe8e7 LB 0x1719 -> off=0x0 cb=000000000000005c uValue=00000000000f08e7 'pmode_setup'
+pmode_setup: ; 0xfe8e7 LB 0x5c
+ push eax ; 66 50 ; 0xfe8e7 orgs.asm:31
+ push esi ; 66 56 ; 0xfe8e9 orgs.asm:32
+ pushfw ; 9c ; 0xfe8eb orgs.asm:33
+ cli ; fa ; 0xfe8ec orgs.asm:34
+ call 0e86bh ; e8 7b ff ; 0xfe8ed orgs.asm:35
+ mov eax, cr0 ; 0f 20 c0 ; 0xfe8f0 orgs.asm:37
+ and eax, strict dword 09fffffffh ; 66 25 ff ff ff 9f ; 0xfe8f3 orgs.asm:38
+ mov cr0, eax ; 0f 22 c0 ; 0xfe8f9 orgs.asm:39
+ mov esi, strict dword 0fee000f0h ; 66 be f0 00 e0 fe ; 0xfe8fc orgs.asm:41
+ mov eax, strict dword 00000010fh ; 66 b8 0f 01 00 00 ; 0xfe902 orgs.asm:42
+ mov dword [esi], eax ; 67 66 89 06 ; 0xfe908 orgs.asm:43
+ mov esi, strict dword 0fee00350h ; 66 be 50 03 e0 fe ; 0xfe90c orgs.asm:45
+ mov eax, dword [esi] ; 67 66 8b 06 ; 0xfe912 orgs.asm:46
+ and eax, strict dword 0fffe00ffh ; 66 25 ff 00 fe ff ; 0xfe916 orgs.asm:47
+ or ah, 007h ; 80 cc 07 ; 0xfe91c orgs.asm:48
+ mov dword [esi], eax ; 67 66 89 06 ; 0xfe91f orgs.asm:49
+ mov esi, strict dword 0fee00360h ; 66 be 60 03 e0 fe ; 0xfe923 orgs.asm:51
+ mov eax, dword [esi] ; 67 66 8b 06 ; 0xfe929 orgs.asm:52
+ and eax, strict dword 0fffe00ffh ; 66 25 ff 00 fe ff ; 0xfe92d orgs.asm:53
+ or ah, 004h ; 80 cc 04 ; 0xfe933 orgs.asm:54
+ mov dword [esi], eax ; 67 66 89 06 ; 0xfe936 orgs.asm:55
+ call 0e886h ; e8 49 ff ; 0xfe93a orgs.asm:57
+ popfw ; 9d ; 0xfe93d orgs.asm:58
+ pop esi ; 66 5e ; 0xfe93e orgs.asm:59
+ pop eax ; 66 58 ; 0xfe940 orgs.asm:60
+ retn ; c3 ; 0xfe942 orgs.asm:62
+ ; disGetNextSymbol 0xfe943 LB 0x16bd -> off=0x0 cb=0000000000000044 uValue=00000000000f0943 'biosorg_check_before_or_at_0E985h'
+biosorg_check_before_or_at_0E985h: ; 0xfe943 LB 0x44
+ times 0x42 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe987 LB 0x1679 -> off=0x0 cb=0000000000000052 uValue=00000000000f0987 'biosorg_check_at_0E987h'
+biosorg_check_at_0E987h: ; 0xfe987 LB 0x52
+ cli ; fa ; 0xfe987 orgs.asm:966
+ push ax ; 50 ; 0xfe988 orgs.asm:967
+ mov AL, strict byte 0adh ; b0 ad ; 0xfe989 orgs.asm:968
+ out strict byte 064h, AL ; e6 64 ; 0xfe98b orgs.asm:969
+ in AL, strict byte 060h ; e4 60 ; 0xfe98d orgs.asm:971
+ push DS ; 1e ; 0xfe98f orgs.asm:972
+ pushaw ; 60 ; 0xfe990 orgs.asm:97
+ cld ; fc ; 0xfe991 orgs.asm:974
+ mov AH, strict byte 04fh ; b4 4f ; 0xfe992 orgs.asm:976
+ stc ; f9 ; 0xfe994 orgs.asm:977
+ int 015h ; cd 15 ; 0xfe995 orgs.asm:978
+ jnc short 0e9c0h ; 73 27 ; 0xfe997 orgs.asm:979
+ sti ; fb ; 0xfe999 orgs.asm:981
+ cmp AL, strict byte 0e0h ; 3c e0 ; 0xfe99a orgs.asm:984
+ jne short 0e9a9h ; 75 0b ; 0xfe99c orgs.asm:985
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe99e orgs.asm:986
+ mov ds, ax ; 8e d8 ; 0xfe9a0 orgs.asm:987
+ or byte [00496h], 002h ; 80 0e 96 04 02 ; 0xfe9a2 orgs.asm:988
+ jmp short 0e9c0h ; eb 17 ; 0xfe9a7 orgs.asm:989
+ cmp AL, strict byte 0e1h ; 3c e1 ; 0xfe9a9 orgs.asm:992
+ jne short 0e9b8h ; 75 0b ; 0xfe9ab orgs.asm:993
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe9ad orgs.asm:994
+ mov ds, ax ; 8e d8 ; 0xfe9af orgs.asm:995
+ or byte [00496h], 001h ; 80 0e 96 04 01 ; 0xfe9b1 orgs.asm:996
+ jmp short 0e9c0h ; eb 08 ; 0xfe9b6 orgs.asm:997
+ push ES ; 06 ; 0xfe9b8 orgs.asm:1000
+ push CS ; 0e ; 0xfe9b9 orgs.asm:104
+ pop DS ; 1f ; 0xfe9ba orgs.asm:105
+ cld ; fc ; 0xfe9bb orgs.asm:106
+ call 0525ah ; e8 9b 68 ; 0xfe9bc orgs.asm:1002
+ pop ES ; 07 ; 0xfe9bf orgs.asm:1003
+ popaw ; 61 ; 0xfe9c0 orgs.asm:114
+ pop DS ; 1f ; 0xfe9c1 orgs.asm:1007
+ cli ; fa ; 0xfe9c2 orgs.asm:1008
+ call 0e034h ; e8 6e f6 ; 0xfe9c3 orgs.asm:1009
+ mov AL, strict byte 0aeh ; b0 ae ; 0xfe9c6 orgs.asm:1011
+ out strict byte 064h, AL ; e6 64 ; 0xfe9c8 orgs.asm:1012
+ pop ax ; 58 ; 0xfe9ca orgs.asm:1013
+ iret ; cf ; 0xfe9cb orgs.asm:1014
+ pushaw ; 60 ; 0xfe9cc orgs.asm:97
+ push ES ; 06 ; 0xfe9cd orgs.asm:1023
+ push DS ; 1e ; 0xfe9ce orgs.asm:1024
+ push CS ; 0e ; 0xfe9cf orgs.asm:104
+ pop DS ; 1f ; 0xfe9d0 orgs.asm:105
+ cld ; fc ; 0xfe9d1 orgs.asm:106
+ call 06e90h ; e8 bb 84 ; 0xfe9d2 orgs.asm:1026
+ pop DS ; 1f ; 0xfe9d5 orgs.asm:1027
+ pop ES ; 07 ; 0xfe9d6 orgs.asm:1028
+ popaw ; 61 ; 0xfe9d7 orgs.asm:114
+ iret ; cf ; 0xfe9d8 orgs.asm:1030
+ ; disGetNextSymbol 0xfe9d9 LB 0x1627 -> off=0x0 cb=0000000000000280 uValue=00000000000f09d9 'biosorg_check_before_or_at_0EC57h'
+biosorg_check_before_or_at_0EC57h: ; 0xfe9d9 LB 0x280
+ times 0x27e db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfec59 LB 0x13a7 -> off=0x0 cb=0000000000000002 uValue=00000000000f0c59 'biosorg_check_at_0EC59h'
+biosorg_check_at_0EC59h: ; 0xfec59 LB 0x2
+ jmp short 0ecb0h ; eb 55 ; 0xfec59 orgs.asm:1037
+ ; disGetNextSymbol 0xfec5b LB 0x13a5 -> off=0x0 cb=0000000000000055 uValue=00000000000f0c5b 'int13_relocated'
+int13_relocated: ; 0xfec5b LB 0x55
+ cmp ah, 04ah ; 80 fc 4a ; 0xfec5b orgs.asm:1046
+ jc short 0ec71h ; 72 11 ; 0xfec5e orgs.asm:1047
+ cmp ah, 04dh ; 80 fc 4d ; 0xfec60 orgs.asm:1049
+ jnbe short 0ec71h ; 77 0c ; 0xfec63 orgs.asm:1050
+ pushaw ; 60 ; 0xfec65 orgs.asm:97
+ push ES ; 06 ; 0xfec66 orgs.asm:1053
+ push DS ; 1e ; 0xfec67 orgs.asm:1054
+ push CS ; 0e ; 0xfec68 orgs.asm:104
+ pop DS ; 1f ; 0xfec69 orgs.asm:105
+ cld ; fc ; 0xfec6a orgs.asm:106
+ push 0ece9h ; 68 e9 ec ; 0xfec6b orgs.asm:83
+ jmp near 03cc7h ; e9 56 50 ; 0xfec6e orgs.asm:84
+ push ES ; 06 ; 0xfec71 orgs.asm:1062
+ push ax ; 50 ; 0xfec72 orgs.asm:1063
+ push bx ; 53 ; 0xfec73 orgs.asm:1064
+ push cx ; 51 ; 0xfec74 orgs.asm:1065
+ push dx ; 52 ; 0xfec75 orgs.asm:1066
+ call 03c9bh ; e8 22 50 ; 0xfec76 orgs.asm:1069
+ cmp AL, strict byte 000h ; 3c 00 ; 0xfec79 orgs.asm:1070
+ je short 0ecabh ; 74 2e ; 0xfec7b orgs.asm:1071
+ call 03cb1h ; e8 31 50 ; 0xfec7d orgs.asm:1074
+ pop dx ; 5a ; 0xfec80 orgs.asm:1075
+ push dx ; 52 ; 0xfec81 orgs.asm:1076
+ db 03ah, 0c2h
+ ; cmp al, dl ; 3a c2 ; 0xfec82 orgs.asm:1077
+ jne short 0ec97h ; 75 11 ; 0xfec84 orgs.asm:1078
+ pop dx ; 5a ; 0xfec86 orgs.asm:1080
+ pop cx ; 59 ; 0xfec87 orgs.asm:1081
+ pop bx ; 5b ; 0xfec88 orgs.asm:1082
+ pop ax ; 58 ; 0xfec89 orgs.asm:1083
+ pop ES ; 07 ; 0xfec8a orgs.asm:1084
+ pushaw ; 60 ; 0xfec8b orgs.asm:97
+ push ES ; 06 ; 0xfec8c orgs.asm:1087
+ push DS ; 1e ; 0xfec8d orgs.asm:1088
+ push CS ; 0e ; 0xfec8e orgs.asm:104
+ pop DS ; 1f ; 0xfec8f orgs.asm:105
+ cld ; fc ; 0xfec90 orgs.asm:106
+ push 0ece9h ; 68 e9 ec ; 0xfec91 orgs.asm:83
+ jmp near 04278h ; e9 e1 55 ; 0xfec94 orgs.asm:84
+ and dl, 0e0h ; 80 e2 e0 ; 0xfec97 orgs.asm:1094
+ db 03ah, 0c2h
+ ; cmp al, dl ; 3a c2 ; 0xfec9a orgs.asm:1095
+ jne short 0ecabh ; 75 0d ; 0xfec9c orgs.asm:1096
+ pop dx ; 5a ; 0xfec9e orgs.asm:1098
+ pop cx ; 59 ; 0xfec9f orgs.asm:1099
+ pop bx ; 5b ; 0xfeca0 orgs.asm:1100
+ pop ax ; 58 ; 0xfeca1 orgs.asm:1101
+ pop ES ; 07 ; 0xfeca2 orgs.asm:1102
+ push ax ; 50 ; 0xfeca3 orgs.asm:1104
+ push cx ; 51 ; 0xfeca4 orgs.asm:1105
+ push dx ; 52 ; 0xfeca5 orgs.asm:1106
+ push bx ; 53 ; 0xfeca6 orgs.asm:1107
+ db 0feh, 0cah
+ ; dec dl ; fe ca ; 0xfeca7 orgs.asm:1109
+ jmp short 0ecb4h ; eb 09 ; 0xfeca9 orgs.asm:1110
+ pop dx ; 5a ; 0xfecab orgs.asm:1113
+ pop cx ; 59 ; 0xfecac orgs.asm:1114
+ pop bx ; 5b ; 0xfecad orgs.asm:1115
+ pop ax ; 58 ; 0xfecae orgs.asm:1116
+ pop ES ; 07 ; 0xfecaf orgs.asm:1117
+ ; disGetNextSymbol 0xfecb0 LB 0x1350 -> off=0x0 cb=0000000000000004 uValue=00000000000f0cb0 'int13_noeltorito'
+int13_noeltorito: ; 0xfecb0 LB 0x4
+ push ax ; 50 ; 0xfecb0 orgs.asm:1120
+ push cx ; 51 ; 0xfecb1 orgs.asm:1121
+ push dx ; 52 ; 0xfecb2 orgs.asm:1122
+ push bx ; 53 ; 0xfecb3 orgs.asm:1123
+ ; disGetNextSymbol 0xfecb4 LB 0x134c -> off=0x0 cb=0000000000000014 uValue=00000000000f0cb4 'int13_legacy'
+int13_legacy: ; 0xfecb4 LB 0x14
+ push dx ; 52 ; 0xfecb4 orgs.asm:1125
+ push bp ; 55 ; 0xfecb5 orgs.asm:1126
+ push si ; 56 ; 0xfecb6 orgs.asm:1127
+ push di ; 57 ; 0xfecb7 orgs.asm:1128
+ push ES ; 06 ; 0xfecb8 orgs.asm:1129
+ push DS ; 1e ; 0xfecb9 orgs.asm:1130
+ push CS ; 0e ; 0xfecba orgs.asm:104
+ pop DS ; 1f ; 0xfecbb orgs.asm:105
+ cld ; fc ; 0xfecbc orgs.asm:106
+ test dl, 080h ; f6 c2 80 ; 0xfecbd orgs.asm:1135
+ jne short 0ecc8h ; 75 06 ; 0xfecc0 orgs.asm:1136
+ push 0ece9h ; 68 e9 ec ; 0xfecc2 orgs.asm:83
+ jmp near 032cah ; e9 02 46 ; 0xfecc5 orgs.asm:84
+ ; disGetNextSymbol 0xfecc8 LB 0x1338 -> off=0x0 cb=0000000000000014 uValue=00000000000f0cc8 'int13_notfloppy'
+int13_notfloppy: ; 0xfecc8 LB 0x14
+ cmp dl, 0e0h ; 80 fa e0 ; 0xfecc8 orgs.asm:1141
+ jc short 0ecdch ; 72 0f ; 0xfeccb orgs.asm:1142
+ shr ebx, 010h ; 66 c1 eb 10 ; 0xfeccd orgs.asm:1148
+ push bx ; 53 ; 0xfecd1 orgs.asm:1149
+ call 048a9h ; e8 d4 5b ; 0xfecd2 orgs.asm:1150
+ pop bx ; 5b ; 0xfecd5 orgs.asm:1151
+ sal ebx, 010h ; 66 c1 e3 10 ; 0xfecd6 orgs.asm:1152
+ jmp short 0ece9h ; eb 0d ; 0xfecda orgs.asm:1154
+ ; disGetNextSymbol 0xfecdc LB 0x1324 -> off=0x0 cb=000000000000000d uValue=00000000000f0cdc 'int13_disk'
+int13_disk: ; 0xfecdc LB 0xd
+ cmp ah, 040h ; 80 fc 40 ; 0xfecdc orgs.asm:1158
+ jnbe short 0ece6h ; 77 05 ; 0xfecdf orgs.asm:1159
+ call 05d6fh ; e8 8b 70 ; 0xfece1 orgs.asm:1160
+ jmp short 0ece9h ; eb 03 ; 0xfece4 orgs.asm:1161
+ call 061b9h ; e8 d0 74 ; 0xfece6 orgs.asm:1164
+ ; disGetNextSymbol 0xfece9 LB 0x1317 -> off=0x0 cb=0000000000000004 uValue=00000000000f0ce9 'int13_out'
+int13_out: ; 0xfece9 LB 0x4
+ pop DS ; 1f ; 0xfece9 orgs.asm:1167
+ pop ES ; 07 ; 0xfecea orgs.asm:1168
+ popaw ; 61 ; 0xfeceb orgs.asm:114
+ iret ; cf ; 0xfecec orgs.asm:1170
+ ; disGetNextSymbol 0xfeced LB 0x1313 -> off=0x0 cb=000000000000001e uValue=00000000000f0ced 'detect_parport'
+detect_parport: ; 0xfeced LB 0x1e
+ push dx ; 52 ; 0xfeced orgs.asm:1177
+ inc dx ; 42 ; 0xfecee orgs.asm:1178
+ inc dx ; 42 ; 0xfecef orgs.asm:1179
+ in AL, DX ; ec ; 0xfecf0 orgs.asm:1180
+ and AL, strict byte 0dfh ; 24 df ; 0xfecf1 orgs.asm:1181
+ out DX, AL ; ee ; 0xfecf3 orgs.asm:1182
+ pop dx ; 5a ; 0xfecf4 orgs.asm:1183
+ mov AL, strict byte 0aah ; b0 aa ; 0xfecf5 orgs.asm:1184
+ out DX, AL ; ee ; 0xfecf7 orgs.asm:1185
+ in AL, DX ; ec ; 0xfecf8 orgs.asm:1186
+ cmp AL, strict byte 0aah ; 3c aa ; 0xfecf9 orgs.asm:1187
+ jne short 0ed0ah ; 75 0d ; 0xfecfb orgs.asm:1188
+ push bx ; 53 ; 0xfecfd orgs.asm:1190
+ sal bx, 1 ; d1 e3 ; 0xfecfe orgs.asm:1191
+ mov word [bx+00408h], dx ; 89 97 08 04 ; 0xfed00 orgs.asm:1192
+ pop bx ; 5b ; 0xfed04 orgs.asm:1193
+ mov byte [bx+00478h], cl ; 88 8f 78 04 ; 0xfed05 orgs.asm:1194
+ inc bx ; 43 ; 0xfed09 orgs.asm:1195
+ retn ; c3 ; 0xfed0a orgs.asm:1197
+ ; disGetNextSymbol 0xfed0b LB 0x12f5 -> off=0x0 cb=0000000000000024 uValue=00000000000f0d0b 'detect_serial'
+detect_serial: ; 0xfed0b LB 0x24
+ push dx ; 52 ; 0xfed0b orgs.asm:1204
+ inc dx ; 42 ; 0xfed0c orgs.asm:1205
+ mov AL, strict byte 002h ; b0 02 ; 0xfed0d orgs.asm:1206
+ out DX, AL ; ee ; 0xfed0f orgs.asm:1207
+ in AL, DX ; ec ; 0xfed10 orgs.asm:1208
+ cmp AL, strict byte 002h ; 3c 02 ; 0xfed11 orgs.asm:1209
+ jne short 0ed2dh ; 75 18 ; 0xfed13 orgs.asm:1210
+ inc dx ; 42 ; 0xfed15 orgs.asm:1212
+ in AL, DX ; ec ; 0xfed16 orgs.asm:1213
+ cmp AL, strict byte 002h ; 3c 02 ; 0xfed17 orgs.asm:1214
+ jne short 0ed2dh ; 75 12 ; 0xfed19 orgs.asm:1215
+ dec dx ; 4a ; 0xfed1b orgs.asm:1217
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xfed1c orgs.asm:1218
+ pop dx ; 5a ; 0xfed1e orgs.asm:1219
+ push bx ; 53 ; 0xfed1f orgs.asm:1220
+ sal bx, 1 ; d1 e3 ; 0xfed20 orgs.asm:1221
+ mov word [bx+00400h], dx ; 89 97 00 04 ; 0xfed22 orgs.asm:1222
+ pop bx ; 5b ; 0xfed26 orgs.asm:1223
+ mov byte [bx+0047ch], cl ; 88 8f 7c 04 ; 0xfed27 orgs.asm:1224
+ inc bx ; 43 ; 0xfed2b orgs.asm:1225
+ retn ; c3 ; 0xfed2c orgs.asm:1226
+ pop dx ; 5a ; 0xfed2d orgs.asm:1229
+ retn ; c3 ; 0xfed2e orgs.asm:1230
+ ; disGetNextSymbol 0xfed2f LB 0x12d1 -> off=0x0 cb=0000000000000087 uValue=00000000000f0d2f 'floppy_post'
+floppy_post: ; 0xfed2f LB 0x87
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfed2f orgs.asm:1240
+ mov ds, ax ; 8e d8 ; 0xfed31 orgs.asm:1241
+ mov AL, strict byte 000h ; b0 00 ; 0xfed33 orgs.asm:1245
+ mov byte [0043eh], AL ; a2 3e 04 ; 0xfed35 orgs.asm:1246
+ mov byte [0043fh], AL ; a2 3f 04 ; 0xfed38 orgs.asm:1247
+ mov byte [00440h], AL ; a2 40 04 ; 0xfed3b orgs.asm:1248
+ mov byte [00441h], AL ; a2 41 04 ; 0xfed3e orgs.asm:1249
+ mov byte [00442h], AL ; a2 42 04 ; 0xfed41 orgs.asm:1250
+ mov byte [00443h], AL ; a2 43 04 ; 0xfed44 orgs.asm:1251
+ mov byte [00444h], AL ; a2 44 04 ; 0xfed47 orgs.asm:1252
+ mov byte [00445h], AL ; a2 45 04 ; 0xfed4a orgs.asm:1253
+ mov byte [00446h], AL ; a2 46 04 ; 0xfed4d orgs.asm:1254
+ mov byte [00447h], AL ; a2 47 04 ; 0xfed50 orgs.asm:1255
+ mov byte [00448h], AL ; a2 48 04 ; 0xfed53 orgs.asm:1256
+ mov byte [0048bh], AL ; a2 8b 04 ; 0xfed56 orgs.asm:1258
+ mov AL, strict byte 010h ; b0 10 ; 0xfed59 orgs.asm:1260
+ out strict byte 070h, AL ; e6 70 ; 0xfed5b orgs.asm:1261
+ in AL, strict byte 071h ; e4 71 ; 0xfed5d orgs.asm:1262
+ db 08ah, 0e0h
+ ; mov ah, al ; 8a e0 ; 0xfed5f orgs.asm:1263
+ shr al, 004h ; c0 e8 04 ; 0xfed61 orgs.asm:169
+ je short 0ed6ah ; 74 04 ; 0xfed64 orgs.asm:1268
+ mov BL, strict byte 007h ; b3 07 ; 0xfed66 orgs.asm:1269
+ jmp short 0ed6ch ; eb 02 ; 0xfed68 orgs.asm:1270
+ mov BL, strict byte 000h ; b3 00 ; 0xfed6a orgs.asm:1273
+ db 08ah, 0c4h
+ ; mov al, ah ; 8a c4 ; 0xfed6c orgs.asm:1276
+ and AL, strict byte 00fh ; 24 0f ; 0xfed6e orgs.asm:1277
+ je short 0ed75h ; 74 03 ; 0xfed70 orgs.asm:1278
+ or bl, 070h ; 80 cb 70 ; 0xfed72 orgs.asm:1279
+ mov byte [0048fh], bl ; 88 1e 8f 04 ; 0xfed75 orgs.asm:1281
+ mov AL, strict byte 000h ; b0 00 ; 0xfed79 orgs.asm:1284
+ mov byte [00490h], AL ; a2 90 04 ; 0xfed7b orgs.asm:1285
+ mov byte [00491h], AL ; a2 91 04 ; 0xfed7e orgs.asm:1286
+ mov byte [00492h], AL ; a2 92 04 ; 0xfed81 orgs.asm:1287
+ mov byte [00493h], AL ; a2 93 04 ; 0xfed84 orgs.asm:1288
+ mov byte [00494h], AL ; a2 94 04 ; 0xfed87 orgs.asm:1289
+ mov byte [00495h], AL ; a2 95 04 ; 0xfed8a orgs.asm:1290
+ mov AL, strict byte 002h ; b0 02 ; 0xfed8d orgs.asm:1292
+ out strict byte 00ah, AL ; e6 0a ; 0xfed8f orgs.asm:1293
+ mov ax, 0efc7h ; b8 c7 ef ; 0xfed91 orgs.asm:95
+ mov word [00078h], ax ; a3 78 00 ; 0xfed94 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfed97 orgs.asm:97
+ mov word [0007ah], ax ; a3 7a 00 ; 0xfed9a orgs.asm:98
+ mov ax, 0ec59h ; b8 59 ec ; 0xfed9d orgs.asm:95
+ mov word [00100h], ax ; a3 00 01 ; 0xfeda0 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfeda3 orgs.asm:97
+ mov word [00102h], ax ; a3 02 01 ; 0xfeda6 orgs.asm:98
+ mov ax, 0ef57h ; b8 57 ef ; 0xfeda9 orgs.asm:95
+ mov word [00038h], ax ; a3 38 00 ; 0xfedac orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfedaf orgs.asm:97
+ mov word [0003ah], ax ; a3 3a 00 ; 0xfedb2 orgs.asm:98
+ retn ; c3 ; 0xfedb5 orgs.asm:1299
+ ; disGetNextSymbol 0xfedb6 LB 0x124a -> off=0x0 cb=0000000000000009 uValue=0000000000000db6 'bcd_to_bin'
+bcd_to_bin: ; 0xfedb6 LB 0x9
+ sal ax, 004h ; c1 e0 04 ; 0xfedb6 orgs.asm:1309
+ shr al, 004h ; c0 e8 04 ; 0xfedb9 orgs.asm:1310
+ aad 00ah ; d5 0a ; 0xfedbc orgs.asm:1318
+ retn ; c3 ; 0xfedbe orgs.asm:1319
+ ; disGetNextSymbol 0xfedbf LB 0x1241 -> off=0x0 cb=0000000000000077 uValue=00000000000f0dbf 'rtc_post'
+rtc_post: ; 0xfedbf LB 0x77
+ db 066h, 033h, 0c0h
+ ; xor eax, eax ; 66 33 c0 ; 0xfedbf orgs.asm:1376
+ mov AL, strict byte 000h ; b0 00 ; 0xfedc2 orgs.asm:1377
+ out strict byte 070h, AL ; e6 70 ; 0xfedc4 orgs.asm:1378
+ in AL, strict byte 071h ; e4 71 ; 0xfedc6 orgs.asm:1379
+ call 0edb6h ; e8 eb ff ; 0xfedc8 orgs.asm:1380
+ mov edx, strict dword 00115cf2bh ; 66 ba 2b cf 15 01 ; 0xfedcb orgs.asm:1381
+ mul edx ; 66 f7 e2 ; 0xfedd1 orgs.asm:1382
+ mov ebx, strict dword 0000f4240h ; 66 bb 40 42 0f 00 ; 0xfedd4 orgs.asm:1383
+ db 066h, 033h, 0d2h
+ ; xor edx, edx ; 66 33 d2 ; 0xfedda orgs.asm:1384
+ div ebx ; 66 f7 f3 ; 0xfeddd orgs.asm:1385
+ db 066h, 08bh, 0c8h
+ ; mov ecx, eax ; 66 8b c8 ; 0xfede0 orgs.asm:1386
+ db 066h, 033h, 0c0h
+ ; xor eax, eax ; 66 33 c0 ; 0xfede3 orgs.asm:1389
+ mov AL, strict byte 002h ; b0 02 ; 0xfede6 orgs.asm:1390
+ out strict byte 070h, AL ; e6 70 ; 0xfede8 orgs.asm:1391
+ in AL, strict byte 071h ; e4 71 ; 0xfedea orgs.asm:1392
+ call 0edb6h ; e8 c7 ff ; 0xfedec orgs.asm:1393
+ mov edx, strict dword 000a6af80h ; 66 ba 80 af a6 00 ; 0xfedef orgs.asm:1394
+ mul edx ; 66 f7 e2 ; 0xfedf5 orgs.asm:1395
+ mov ebx, strict dword 000002710h ; 66 bb 10 27 00 00 ; 0xfedf8 orgs.asm:1396
+ db 066h, 033h, 0d2h
+ ; xor edx, edx ; 66 33 d2 ; 0xfedfe orgs.asm:1397
+ div ebx ; 66 f7 f3 ; 0xfee01 orgs.asm:1398
+ db 066h, 003h, 0c8h
+ ; add ecx, eax ; 66 03 c8 ; 0xfee04 orgs.asm:1399
+ db 066h, 033h, 0c0h
+ ; xor eax, eax ; 66 33 c0 ; 0xfee07 orgs.asm:1402
+ mov AL, strict byte 004h ; b0 04 ; 0xfee0a orgs.asm:1403
+ out strict byte 070h, AL ; e6 70 ; 0xfee0c orgs.asm:1404
+ in AL, strict byte 071h ; e4 71 ; 0xfee0e orgs.asm:1405
+ call 0edb6h ; e8 a3 ff ; 0xfee10 orgs.asm:1406
+ mov edx, strict dword 003e81d03h ; 66 ba 03 1d e8 03 ; 0xfee13 orgs.asm:1407
+ mul edx ; 66 f7 e2 ; 0xfee19 orgs.asm:1408
+ mov ebx, strict dword 0000003e8h ; 66 bb e8 03 00 00 ; 0xfee1c orgs.asm:1409
+ db 066h, 033h, 0d2h
+ ; xor edx, edx ; 66 33 d2 ; 0xfee22 orgs.asm:1410
+ div ebx ; 66 f7 f3 ; 0xfee25 orgs.asm:1411
+ db 066h, 003h, 0c8h
+ ; add ecx, eax ; 66 03 c8 ; 0xfee28 orgs.asm:1412
+ mov dword [0046ch], ecx ; 66 89 0e 6c 04 ; 0xfee2b orgs.asm:1414
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xfee30 orgs.asm:1415
+ mov byte [00470h], AL ; a2 70 04 ; 0xfee32 orgs.asm:1416
+ retn ; c3 ; 0xfee35 orgs.asm:1419
+ ; disGetNextSymbol 0xfee36 LB 0x11ca -> off=0x0 cb=0000000000000121 uValue=00000000000f0e36 'biosorg_check_before_or_at_0EF55h'
+biosorg_check_before_or_at_0EF55h: ; 0xfee36 LB 0x121
+ times 0x11f db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfef57 LB 0x10a9 -> off=0x0 cb=000000000000003b uValue=00000000000f0f57 'int0e_handler'
+int0e_handler: ; 0xfef57 LB 0x3b
+ push ax ; 50 ; 0xfef57 orgs.asm:1430
+ push dx ; 52 ; 0xfef58 orgs.asm:1431
+ mov dx, 003f4h ; ba f4 03 ; 0xfef59 orgs.asm:1432
+ in AL, DX ; ec ; 0xfef5c orgs.asm:1433
+ and AL, strict byte 0c0h ; 24 c0 ; 0xfef5d orgs.asm:1434
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xfef5f orgs.asm:1435
+ je short 0ef81h ; 74 1e ; 0xfef61 orgs.asm:1436
+ mov dx, 003f5h ; ba f5 03 ; 0xfef63 orgs.asm:1437
+ mov AL, strict byte 008h ; b0 08 ; 0xfef66 orgs.asm:1438
+ out DX, AL ; ee ; 0xfef68 orgs.asm:1439
+ mov dx, 003f4h ; ba f4 03 ; 0xfef69 orgs.asm:1441
+ in AL, DX ; ec ; 0xfef6c orgs.asm:1442
+ and AL, strict byte 0c0h ; 24 c0 ; 0xfef6d orgs.asm:1443
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xfef6f orgs.asm:1444
+ jne short 0ef69h ; 75 f6 ; 0xfef71 orgs.asm:1445
+ mov dx, 003f5h ; ba f5 03 ; 0xfef73 orgs.asm:1448
+ in AL, DX ; ec ; 0xfef76 orgs.asm:1449
+ mov dx, 003f4h ; ba f4 03 ; 0xfef77 orgs.asm:1450
+ in AL, DX ; ec ; 0xfef7a orgs.asm:1451
+ and AL, strict byte 0c0h ; 24 c0 ; 0xfef7b orgs.asm:1452
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xfef7d orgs.asm:1453
+ je short 0ef73h ; 74 f2 ; 0xfef7f orgs.asm:1454
+ push DS ; 1e ; 0xfef81 orgs.asm:1457
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfef82 orgs.asm:1458
+ mov ds, ax ; 8e d8 ; 0xfef84 orgs.asm:1459
+ call 0e034h ; e8 ab f0 ; 0xfef86 orgs.asm:1460
+ or byte [0043eh], 080h ; 80 0e 3e 04 80 ; 0xfef89 orgs.asm:1462
+ pop DS ; 1f ; 0xfef8e orgs.asm:1463
+ pop dx ; 5a ; 0xfef8f orgs.asm:1464
+ pop ax ; 58 ; 0xfef90 orgs.asm:1465
+ iret ; cf ; 0xfef91 orgs.asm:1466
+ ; disGetNextSymbol 0xfef92 LB 0x106e -> off=0x0 cb=0000000000000035 uValue=00000000000f0f92 'biosorg_check_before_or_at_0EFC5h'
+biosorg_check_before_or_at_0EFC5h: ; 0xfef92 LB 0x35
+ times 0x33 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfefc7 LB 0x1039 -> off=0x0 cb=000000000000000b uValue=00000000000f0fc7 '_diskette_param_table'
+_diskette_param_table: ; 0xfefc7 LB 0xb
+ scasw ; af ; 0xfefc7
+ add ah, byte [di] ; 02 25 ; 0xfefc8
+ add dl, byte [bp+si] ; 02 12 ; 0xfefca
+ db 01bh, 0ffh
+ ; sbb di, di ; 1b ff ; 0xfefcc
+ insb ; 6c ; 0xfefce
+ db 0f6h
+ invd ; 0f 08 ; 0xfefd0
+ ; disGetNextSymbol 0xfefd2 LB 0x102e -> off=0x0 cb=0000000000000002 uValue=00000000000f0fd2 'biosorg_check_at_0EFD2h'
+biosorg_check_at_0EFD2h: ; 0xfefd2 LB 0x2
+ jmp short 0efd4h ; eb 00 ; 0xfefd2 orgs.asm:1493
+ ; disGetNextSymbol 0xfefd4 LB 0x102c -> off=0x0 cb=000000000000000d uValue=00000000000f0fd4 'int17_handler'
+int17_handler: ; 0xfefd4 LB 0xd
+ push DS ; 1e ; 0xfefd4 orgs.asm:1496
+ push ES ; 06 ; 0xfefd5 orgs.asm:1497
+ pushaw ; 60 ; 0xfefd6 orgs.asm:97
+ push CS ; 0e ; 0xfefd7 orgs.asm:104
+ pop DS ; 1f ; 0xfefd8 orgs.asm:105
+ cld ; fc ; 0xfefd9 orgs.asm:106
+ call 077adh ; e8 d0 87 ; 0xfefda orgs.asm:1500
+ popaw ; 61 ; 0xfefdd orgs.asm:114
+ pop ES ; 07 ; 0xfefde orgs.asm:1502
+ pop DS ; 1f ; 0xfefdf orgs.asm:1503
+ iret ; cf ; 0xfefe0 orgs.asm:1504
+ ; disGetNextSymbol 0xfefe1 LB 0x101f -> off=0x0 cb=0000000000000006 uValue=00000000000f0fe1 '_pmode_IDT'
+_pmode_IDT: ; 0xfefe1 LB 0x6
+ db 000h, 000h, 000h, 000h, 00fh, 000h
+ ; disGetNextSymbol 0xfefe7 LB 0x1019 -> off=0x0 cb=0000000000000006 uValue=00000000000f0fe7 '_rmode_IDT'
+_rmode_IDT: ; 0xfefe7 LB 0x6
+ db 0ffh, 003h, 000h, 000h, 000h, 000h
+ ; disGetNextSymbol 0xfefed LB 0x1013 -> off=0x0 cb=0000000000000001 uValue=00000000000f0fed 'int1c_handler'
+int1c_handler: ; 0xfefed LB 0x1
+ iret ; cf ; 0xfefed orgs.asm:1539
+ ; disGetNextSymbol 0xfefee LB 0x1012 -> off=0x0 cb=0000000000000057 uValue=00000000000f0fee 'biosorg_check_before_or_at_0F043h'
+biosorg_check_before_or_at_0F043h: ; 0xfefee LB 0x57
+ times 0x55 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xff045 LB 0xfbb -> off=0x0 cb=0000000000000001 uValue=00000000000f1045 'biosorg_check_at_0F045h'
+biosorg_check_at_0F045h: ; 0xff045 LB 0x1
+ iret ; cf ; 0xff045 orgs.asm:1548
+ ; disGetNextSymbol 0xff046 LB 0xfba -> off=0x0 cb=000000000000001f uValue=00000000000f1046 'biosorg_check_before_or_at_0F063h'
+biosorg_check_before_or_at_0F063h: ; 0xff046 LB 0x1f
+ times 0x1d db 0
+ db 'XM'
+ ; disGetNextSymbol 0xff065 LB 0xf9b -> off=0x0 cb=0000000000000001 uValue=00000000000f1065 'int10_handler'
+int10_handler: ; 0xff065 LB 0x1
+ iret ; cf ; 0xff065 orgs.asm:1557
+ ; disGetNextSymbol 0xff066 LB 0xf9a -> off=0x0 cb=000000000000003e uValue=00000000000f1066 'biosorg_check_before_or_at_0F0A2h'
+biosorg_check_before_or_at_0F0A2h: ; 0xff066 LB 0x3e
+ times 0x3c db 0
+ db 'XM'
+ ; disGetNextSymbol 0xff0a4 LB 0xf5c -> off=0x0 cb=0000000000000008 uValue=00000000000f10a4 'biosorg_check_at_0F0A4h'
+biosorg_check_at_0F0A4h: ; 0xff0a4 LB 0x8
+ push CS ; 0e ; 0xff0a4 orgs.asm:104
+ pop DS ; 1f ; 0xff0a5 orgs.asm:105
+ cld ; fc ; 0xff0a6 orgs.asm:106
+ call 0180eh ; e8 64 27 ; 0xff0a7 orgs.asm:1572
+ hlt ; f4 ; 0xff0aa orgs.asm:1574
+ iret ; cf ; 0xff0ab orgs.asm:1575
+ ; disGetNextSymbol 0xff0ac LB 0xf54 -> off=0x0 cb=000000000000008f uValue=00000000000f10ac 'int19_relocated'
+int19_relocated: ; 0xff0ac LB 0x8f
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff0ac orgs.asm:1586
+ mov ax, word [bp+002h] ; 8b 46 02 ; 0xff0ae orgs.asm:1587
+ cmp ax, 0f000h ; 3d 00 f0 ; 0xff0b1 orgs.asm:1588
+ je short 0f0c3h ; 74 0d ; 0xff0b4 orgs.asm:1589
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xff0b6 orgs.asm:1591
+ mov ds, ax ; 8e d8 ; 0xff0b8 orgs.asm:1592
+ mov ax, 01234h ; b8 34 12 ; 0xff0ba orgs.asm:1593
+ mov word [001d8h], ax ; a3 d8 01 ; 0xff0bd orgs.asm:1594
+ jmp near 0e05bh ; e9 98 ef ; 0xff0c0 orgs.asm:1595
+ push CS ; 0e ; 0xff0c3 orgs.asm:104
+ pop DS ; 1f ; 0xff0c4 orgs.asm:105
+ cld ; fc ; 0xff0c5 orgs.asm:106
+ push bp ; 55 ; 0xff0c6 orgs.asm:1602
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff0c7 orgs.asm:1603
+ mov ax, strict word 00001h ; b8 01 00 ; 0xff0c9 orgs.asm:1606
+ push ax ; 50 ; 0xff0cc orgs.asm:1607
+ call 04d10h ; e8 40 5c ; 0xff0cd orgs.asm:1608
+ inc sp ; 44 ; 0xff0d0 orgs.asm:1609
+ inc sp ; 44 ; 0xff0d1 orgs.asm:1610
+ test ax, ax ; 85 c0 ; 0xff0d2 orgs.asm:1611
+ jne short 0f0fdh ; 75 27 ; 0xff0d4 orgs.asm:1612
+ mov ax, strict word 00002h ; b8 02 00 ; 0xff0d6 orgs.asm:1615
+ push ax ; 50 ; 0xff0d9 orgs.asm:1616
+ call 04d10h ; e8 33 5c ; 0xff0da orgs.asm:1617
+ inc sp ; 44 ; 0xff0dd orgs.asm:1618
+ inc sp ; 44 ; 0xff0de orgs.asm:1619
+ test ax, ax ; 85 c0 ; 0xff0df orgs.asm:1620
+ jne short 0f0fdh ; 75 1a ; 0xff0e1 orgs.asm:1621
+ mov ax, strict word 00003h ; b8 03 00 ; 0xff0e3 orgs.asm:1624
+ push ax ; 50 ; 0xff0e6 orgs.asm:1625
+ call 04d10h ; e8 26 5c ; 0xff0e7 orgs.asm:1626
+ inc sp ; 44 ; 0xff0ea orgs.asm:1627
+ inc sp ; 44 ; 0xff0eb orgs.asm:1628
+ test ax, ax ; 85 c0 ; 0xff0ec orgs.asm:1629
+ jne short 0f0fdh ; 75 0d ; 0xff0ee orgs.asm:1630
+ mov ax, strict word 00004h ; b8 04 00 ; 0xff0f0 orgs.asm:1633
+ push ax ; 50 ; 0xff0f3 orgs.asm:1634
+ call 04d10h ; e8 19 5c ; 0xff0f4 orgs.asm:1635
+ inc sp ; 44 ; 0xff0f7 orgs.asm:1636
+ inc sp ; 44 ; 0xff0f8 orgs.asm:1637
+ test ax, ax ; 85 c0 ; 0xff0f9 orgs.asm:1638
+ je short 0f0a4h ; 74 a7 ; 0xff0fb orgs.asm:1639
+ sal eax, 004h ; 66 c1 e0 04 ; 0xff0fd orgs.asm:1651
+ mov word [bp+002h], ax ; 89 46 02 ; 0xff101 orgs.asm:1652
+ shr eax, 004h ; 66 c1 e8 04 ; 0xff104 orgs.asm:1654
+ and ax, 0f000h ; 25 00 f0 ; 0xff108 orgs.asm:1657
+ mov word [bp+004h], ax ; 89 46 04 ; 0xff10b orgs.asm:1658
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xff10e orgs.asm:1659
+ mov ds, ax ; 8e d8 ; 0xff110 orgs.asm:1660
+ mov es, ax ; 8e c0 ; 0xff112 orgs.asm:1661
+ mov word [byte bp+000h], ax ; 89 46 00 ; 0xff114 orgs.asm:1662
+ mov ax, 0aa55h ; b8 55 aa ; 0xff117 orgs.asm:1663
+ pop bp ; 5d ; 0xff11a orgs.asm:1665
+ iret ; cf ; 0xff11b orgs.asm:1666
+ or cx, word [bp+si] ; 0b 0a ; 0xff11c
+ or word [bp+di], cx ; 09 0b ; 0xff11e
+ push eax ; 66 50 ; 0xff120 orgs.asm:88
+ mov eax, strict dword 000800000h ; 66 b8 00 00 80 00 ; 0xff122 orgs.asm:89
+ db 08bh, 0c3h
+ ; mov ax, bx ; 8b c3 ; 0xff128 orgs.asm:90
+ sal eax, 008h ; 66 c1 e0 08 ; 0xff12a orgs.asm:91
+ and dl, 0fch ; 80 e2 fc ; 0xff12e orgs.asm:92
+ db 00ah, 0c2h
+ ; or al, dl ; 0a c2 ; 0xff131 orgs.asm:93
+ mov dx, 00cf8h ; ba f8 0c ; 0xff133 orgs.asm:94
+ out DX, eax ; 66 ef ; 0xff136 orgs.asm:95
+ pop eax ; 66 58 ; 0xff138 orgs.asm:96
+ retn ; c3 ; 0xff13a orgs.asm:97
+ ; disGetNextSymbol 0xff13b LB 0xec5 -> off=0x0 cb=0000000000000012 uValue=00000000000f113b 'pcibios_init_iomem_bases'
+pcibios_init_iomem_bases: ; 0xff13b LB 0x12
+ push bp ; 55 ; 0xff13b orgs.asm:100
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff13c orgs.asm:101
+ mov eax, strict dword 00124f9fdh ; 66 b8 fd f9 24 01 ; 0xff13e orgs.asm:103
+ mov dx, 00410h ; ba 10 04 ; 0xff144 orgs.asm:104
+ out DX, eax ; 66 ef ; 0xff147 orgs.asm:105
+ db 08bh, 0e5h
+ ; mov sp, bp ; 8b e5 ; 0xff149 orgs.asm:218
+ pop bp ; 5d ; 0xff14b orgs.asm:219
+ retn ; c3 ; 0xff14c orgs.asm:220
+ ; disGetNextSymbol 0xff14d LB 0xeb3 -> off=0x0 cb=000000000000000c uValue=00000000000f114d 'pcibios_init_set_elcr'
+pcibios_init_set_elcr: ; 0xff14d LB 0xc
+ push ax ; 50 ; 0xff14d orgs.asm:223
+ push cx ; 51 ; 0xff14e orgs.asm:224
+ mov dx, 004d0h ; ba d0 04 ; 0xff14f orgs.asm:225
+ test AL, strict byte 008h ; a8 08 ; 0xff152 orgs.asm:226
+ je short 0f159h ; 74 03 ; 0xff154 orgs.asm:227
+ inc dx ; 42 ; 0xff156 orgs.asm:229
+ and AL, strict byte 007h ; 24 07 ; 0xff157 orgs.asm:230
+ ; disGetNextSymbol 0xff159 LB 0xea7 -> off=0x0 cb=000000000000000d uValue=00000000000f1159 'is_master_pic'
+is_master_pic: ; 0xff159 LB 0xd
+ db 08ah, 0c8h
+ ; mov cl, al ; 8a c8 ; 0xff159 orgs.asm:232
+ mov BL, strict byte 001h ; b3 01 ; 0xff15b orgs.asm:233
+ sal bl, CL ; d2 e3 ; 0xff15d orgs.asm:234
+ in AL, DX ; ec ; 0xff15f orgs.asm:235
+ db 00ah, 0c3h
+ ; or al, bl ; 0a c3 ; 0xff160 orgs.asm:236
+ out DX, AL ; ee ; 0xff162 orgs.asm:237
+ pop cx ; 59 ; 0xff163 orgs.asm:238
+ pop ax ; 58 ; 0xff164 orgs.asm:239
+ retn ; c3 ; 0xff165 orgs.asm:240
+ ; disGetNextSymbol 0xff166 LB 0xe9a -> off=0x0 cb=000000000000002a uValue=00000000000f1166 'pcibios_init_irqs'
+pcibios_init_irqs: ; 0xff166 LB 0x2a
+ push DS ; 1e ; 0xff166 orgs.asm:243
+ push bp ; 55 ; 0xff167 orgs.asm:244
+ mov ax, 0f000h ; b8 00 f0 ; 0xff168 orgs.asm:245
+ mov ds, ax ; 8e d8 ; 0xff16b orgs.asm:246
+ pop bp ; 5d ; 0xff16d orgs.asm:353
+ pop DS ; 1f ; 0xff16e orgs.asm:354
+ retn ; c3 ; 0xff16f orgs.asm:355
+ and AL, strict byte 050h ; 24 50 ; 0xff170
+ dec cx ; 49 ; 0xff172
+ push dx ; 52 ; 0xff173
+ add byte [bx+di], al ; 00 01 ; 0xff174
+ add byte [bp+si], al ; 00 02 ; 0xff176
+ add byte [bx+si], cl ; 00 08 ; 0xff178
+ add byte [bx+si], al ; 00 00 ; 0xff17a
+ xchg byte [bx+si+07000h], al ; 86 80 00 70 ; 0xff17c
+ times 0xf db 0
+ db 031h
+ ; disGetNextSymbol 0xff190 LB 0xe70 -> off=0x0 cb=00000000000001e0 uValue=00000000000f1190 '_pci_routing_table'
+_pci_routing_table: ; 0xff190 LB 0x1e0
+ db 000h, 008h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 000h, 000h
+ db 000h, 010h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 001h, 000h
+ db 000h, 018h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 002h, 000h
+ db 000h, 020h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 003h, 000h
+ db 000h, 028h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 004h, 000h
+ db 000h, 030h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 005h, 000h
+ db 000h, 038h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 006h, 000h
+ db 000h, 040h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 007h, 000h
+ db 000h, 048h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 008h, 000h
+ db 000h, 050h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 009h, 000h
+ db 000h, 058h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 00ah, 000h
+ db 000h, 060h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 00bh, 000h
+ db 000h, 068h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 00ch, 000h
+ db 000h, 070h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 00dh, 000h
+ db 000h, 078h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 00eh, 000h
+ db 000h, 080h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 00fh, 000h
+ db 000h, 088h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 010h, 000h
+ db 000h, 090h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 011h, 000h
+ db 000h, 098h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 012h, 000h
+ db 000h, 0a0h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 013h, 000h
+ db 000h, 0a8h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 014h, 000h
+ db 000h, 0b0h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 015h, 000h
+ db 000h, 0b8h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 016h, 000h
+ db 000h, 0c0h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 017h, 000h
+ db 000h, 0c8h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 018h, 000h
+ db 000h, 0d0h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 019h, 000h
+ db 000h, 0d8h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 01ah, 000h
+ db 000h, 0e0h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 01bh, 000h
+ db 000h, 0e8h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 01ch, 000h
+ db 000h, 0f0h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 01dh, 000h
+ ; disGetNextSymbol 0xff370 LB 0xc90 -> off=0x0 cb=0000000000000002 uValue=00000000000f1370 '_pci_routing_table_size'
+_pci_routing_table_size: ; 0xff370 LB 0x2
+ loopne 0f373h ; e0 01 ; 0xff370
+ ; disGetNextSymbol 0xff372 LB 0xc8e -> off=0x0 cb=00000000000004cf uValue=00000000000f1372 'biosorg_check_before_or_at_0F83Fh'
+biosorg_check_before_or_at_0F83Fh: ; 0xff372 LB 0x4cf
+ times 0x4cd db 0
+ db 'XM'
+ ; disGetNextSymbol 0xff841 LB 0x7bf -> off=0x0 cb=000000000000000c uValue=00000000000f1841 'int12_handler'
+int12_handler: ; 0xff841 LB 0xc
+ sti ; fb ; 0xff841 orgs.asm:1680
+ push DS ; 1e ; 0xff842 orgs.asm:1681
+ mov ax, strict word 00040h ; b8 40 00 ; 0xff843 orgs.asm:1682
+ mov ds, ax ; 8e d8 ; 0xff846 orgs.asm:1683
+ mov ax, word [00013h] ; a1 13 00 ; 0xff848 orgs.asm:1684
+ pop DS ; 1f ; 0xff84b orgs.asm:1685
+ iret ; cf ; 0xff84c orgs.asm:1686
+ ; disGetNextSymbol 0xff84d LB 0x7b3 -> off=0x0 cb=000000000000000c uValue=00000000000f184d 'int11_handler'
+int11_handler: ; 0xff84d LB 0xc
+ sti ; fb ; 0xff84d orgs.asm:1695
+ push DS ; 1e ; 0xff84e orgs.asm:1696
+ mov ax, strict word 00040h ; b8 40 00 ; 0xff84f orgs.asm:1697
+ mov ds, ax ; 8e d8 ; 0xff852 orgs.asm:1698
+ mov ax, word [00010h] ; a1 10 00 ; 0xff854 orgs.asm:1699
+ pop DS ; 1f ; 0xff857 orgs.asm:1700
+ iret ; cf ; 0xff858 orgs.asm:1701
+ ; disGetNextSymbol 0xff859 LB 0x7a7 -> off=0x0 cb=000000000000003b uValue=00000000000f1859 'int15_handler'
+int15_handler: ; 0xff859 LB 0x3b
+ cmp ah, 087h ; 80 fc 87 ; 0xff859 orgs.asm:1711
+ jne short 0f86bh ; 75 0d ; 0xff85c orgs.asm:1712
+ pushaw ; 60 ; 0xff85e orgs.asm:1717
+ push ES ; 06 ; 0xff85f orgs.asm:1718
+ push DS ; 1e ; 0xff860 orgs.asm:1719
+ push CS ; 0e ; 0xff861 orgs.asm:104
+ pop DS ; 1f ; 0xff862 orgs.asm:105
+ cld ; fc ; 0xff863 orgs.asm:106
+ call 06d3ah ; e8 d3 74 ; 0xff864 orgs.asm:1721
+ pop DS ; 1f ; 0xff867 orgs.asm:1722
+ pop ES ; 07 ; 0xff868 orgs.asm:1723
+ popaw ; 61 ; 0xff869 orgs.asm:1724
+ iret ; cf ; 0xff86a orgs.asm:1725
+ pushfw ; 9c ; 0xff86b orgs.asm:1730
+ push DS ; 1e ; 0xff86c orgs.asm:1731
+ push ES ; 06 ; 0xff86d orgs.asm:1732
+ push CS ; 0e ; 0xff86e orgs.asm:104
+ pop DS ; 1f ; 0xff86f orgs.asm:105
+ cld ; fc ; 0xff870 orgs.asm:106
+ cmp ah, 0e8h ; 80 fc e8 ; 0xff871 orgs.asm:1737
+ je short 0f899h ; 74 23 ; 0xff874 orgs.asm:1738
+ cmp ah, 0d0h ; 80 fc d0 ; 0xff876 orgs.asm:1739
+ je short 0f899h ; 74 1e ; 0xff879 orgs.asm:1740
+ pushaw ; 60 ; 0xff87b orgs.asm:97
+ cmp ah, 053h ; 80 fc 53 ; 0xff87c orgs.asm:1743
+ je short 0f88fh ; 74 0e ; 0xff87f orgs.asm:1744
+ cmp ah, 0c2h ; 80 fc c2 ; 0xff881 orgs.asm:1745
+ je short 0f894h ; 74 0e ; 0xff884 orgs.asm:1746
+ call 06652h ; e8 c9 6d ; 0xff886 orgs.asm:1748
+ popaw ; 61 ; 0xff889 orgs.asm:114
+ pop ES ; 07 ; 0xff88a orgs.asm:1754
+ pop DS ; 1f ; 0xff88b orgs.asm:1755
+ popfw ; 9d ; 0xff88c orgs.asm:1756
+ jmp short 0f8a2h ; eb 13 ; 0xff88d orgs.asm:1757
+ call 09968h ; e8 d6 a0 ; 0xff88f orgs.asm:1760
+ jmp short 0f889h ; eb f5 ; 0xff892 orgs.asm:1761
+ ; disGetNextSymbol 0xff894 LB 0x76c -> off=0x0 cb=0000000000000005 uValue=00000000000f1894 'int15_handler_mouse'
+int15_handler_mouse: ; 0xff894 LB 0x5
+ call 0743dh ; e8 a6 7b ; 0xff894 orgs.asm:1764
+ jmp short 0f889h ; eb f0 ; 0xff897 orgs.asm:1765
+ ; disGetNextSymbol 0xff899 LB 0x767 -> off=0x0 cb=0000000000000009 uValue=00000000000f1899 'int15_handler32'
+int15_handler32: ; 0xff899 LB 0x9
+ pushad ; 66 60 ; 0xff899 orgs.asm:1771
+ call 069b4h ; e8 16 71 ; 0xff89b orgs.asm:1772
+ popad ; 66 61 ; 0xff89e orgs.asm:1773
+ jmp short 0f88ah ; eb e8 ; 0xff8a0 orgs.asm:1775
+ ; disGetNextSymbol 0xff8a2 LB 0x75e -> off=0x0 cb=000000000000001a uValue=00000000000f18a2 'iret_modify_cf'
+iret_modify_cf: ; 0xff8a2 LB 0x1a
+ jc short 0f8b2h ; 72 0e ; 0xff8a2 orgs.asm:1782
+ push bp ; 55 ; 0xff8a4 orgs.asm:1783
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff8a5 orgs.asm:1784
+ and byte [bp+006h], 0feh ; 80 66 06 fe ; 0xff8a7 orgs.asm:1785
+ or word [bp+006h], 00200h ; 81 4e 06 00 02 ; 0xff8ab orgs.asm:1786
+ pop bp ; 5d ; 0xff8b0 orgs.asm:1787
+ iret ; cf ; 0xff8b1 orgs.asm:1788
+ push bp ; 55 ; 0xff8b2 orgs.asm:1790
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff8b3 orgs.asm:1791
+ or word [bp+006h], 00201h ; 81 4e 06 01 02 ; 0xff8b5 orgs.asm:1792
+ pop bp ; 5d ; 0xff8ba orgs.asm:1793
+ iret ; cf ; 0xff8bb orgs.asm:1794
+ ; disGetNextSymbol 0xff8bc LB 0x744 -> off=0x0 cb=000000000000002b uValue=00000000000f18bc 'int74_handler'
+int74_handler: ; 0xff8bc LB 0x2b
+ sti ; fb ; 0xff8bc orgs.asm:1801
+ pushaw ; 60 ; 0xff8bd orgs.asm:97
+ push ES ; 06 ; 0xff8be orgs.asm:1803
+ push DS ; 1e ; 0xff8bf orgs.asm:1804
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xff8c0 orgs.asm:1805
+ push ax ; 50 ; 0xff8c2 orgs.asm:1806
+ push ax ; 50 ; 0xff8c3 orgs.asm:1807
+ push ax ; 50 ; 0xff8c4 orgs.asm:1808
+ push ax ; 50 ; 0xff8c5 orgs.asm:1809
+ push ax ; 50 ; 0xff8c6 orgs.asm:1810
+ push CS ; 0e ; 0xff8c7 orgs.asm:104
+ pop DS ; 1f ; 0xff8c8 orgs.asm:105
+ cld ; fc ; 0xff8c9 orgs.asm:106
+ call 07399h ; e8 cc 7a ; 0xff8ca orgs.asm:1812
+ pop cx ; 59 ; 0xff8cd orgs.asm:1813
+ jcxz 0f8dch ; e3 0c ; 0xff8ce orgs.asm:1814
+ push strict byte 00000h ; 6a 00 ; 0xff8d0 orgs.asm:1818
+ pop DS ; 1f ; 0xff8d2 orgs.asm:1823
+ push word [0040eh] ; ff 36 0e 04 ; 0xff8d3 orgs.asm:1824
+ pop DS ; 1f ; 0xff8d7 orgs.asm:1825
+ call far [word 00022h] ; ff 1e 22 00 ; 0xff8d8 orgs.asm:1826
+ cli ; fa ; 0xff8dc orgs.asm:1828
+ call 0e030h ; e8 50 e7 ; 0xff8dd orgs.asm:1829
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xff8e0 orgs.asm:1830
+ pop DS ; 1f ; 0xff8e3 orgs.asm:1831
+ pop ES ; 07 ; 0xff8e4 orgs.asm:1832
+ popaw ; 61 ; 0xff8e5 orgs.asm:114
+ iret ; cf ; 0xff8e6 orgs.asm:1834
+ ; disGetNextSymbol 0xff8e7 LB 0x719 -> off=0x0 cb=0000000000000012 uValue=00000000000f18e7 'int76_handler'
+int76_handler: ; 0xff8e7 LB 0x12
+ push ax ; 50 ; 0xff8e7 orgs.asm:1841
+ push DS ; 1e ; 0xff8e8 orgs.asm:1842
+ mov ax, strict word 00040h ; b8 40 00 ; 0xff8e9 orgs.asm:1843
+ mov ds, ax ; 8e d8 ; 0xff8ec orgs.asm:1844
+ mov byte [0008eh], 0ffh ; c6 06 8e 00 ff ; 0xff8ee orgs.asm:1845
+ call 0e030h ; e8 3a e7 ; 0xff8f3 orgs.asm:1846
+ pop DS ; 1f ; 0xff8f6 orgs.asm:1847
+ pop ax ; 58 ; 0xff8f7 orgs.asm:1848
+ iret ; cf ; 0xff8f8 orgs.asm:1849
+ ; disGetNextSymbol 0xff8f9 LB 0x707 -> off=0x0 cb=000000000000000d uValue=00000000000f18f9 'int70_handler'
+int70_handler: ; 0xff8f9 LB 0xd
+ push ES ; 06 ; 0xff8f9 orgs.asm:1858
+ push DS ; 1e ; 0xff8fa orgs.asm:1859
+ pushaw ; 60 ; 0xff8fb orgs.asm:97
+ push CS ; 0e ; 0xff8fc orgs.asm:104
+ pop DS ; 1f ; 0xff8fd orgs.asm:105
+ cld ; fc ; 0xff8fe orgs.asm:106
+ call 0706eh ; e8 6c 77 ; 0xff8ff orgs.asm:1862
+ popaw ; 61 ; 0xff902 orgs.asm:114
+ pop DS ; 1f ; 0xff903 orgs.asm:1864
+ pop ES ; 07 ; 0xff904 orgs.asm:1865
+ iret ; cf ; 0xff905 orgs.asm:1866
+ ; disGetNextSymbol 0xff906 LB 0x6fa -> off=0x0 cb=0000000000000168 uValue=00000000000f1906 'biosorg_check_before_or_at_0FA6Ch'
+biosorg_check_before_or_at_0FA6Ch: ; 0xff906 LB 0x168
+ times 0x166 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xffa6e LB 0x592 -> off=0x0 cb=0000000000000400 uValue=00000000000f1a6e 'font8x8'
+font8x8: ; 0xffa6e LB 0x400
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 081h, 0a5h, 081h, 0bdh, 099h, 081h, 07eh
+ db 07eh, 0ffh, 0dbh, 0ffh, 0c3h, 0e7h, 0ffh, 07eh, 06ch, 0feh, 0feh, 0feh, 07ch, 038h, 010h, 000h
+ db 010h, 038h, 07ch, 0feh, 07ch, 038h, 010h, 000h, 038h, 07ch, 038h, 0feh, 0feh, 07ch, 038h, 07ch
+ db 010h, 010h, 038h, 07ch, 0feh, 07ch, 038h, 07ch, 000h, 000h, 018h, 03ch, 03ch, 018h, 000h, 000h
+ db 0ffh, 0ffh, 0e7h, 0c3h, 0c3h, 0e7h, 0ffh, 0ffh, 000h, 03ch, 066h, 042h, 042h, 066h, 03ch, 000h
+ db 0ffh, 0c3h, 099h, 0bdh, 0bdh, 099h, 0c3h, 0ffh, 00fh, 007h, 00fh, 07dh, 0cch, 0cch, 0cch, 078h
+ db 03ch, 066h, 066h, 066h, 03ch, 018h, 07eh, 018h, 03fh, 033h, 03fh, 030h, 030h, 070h, 0f0h, 0e0h
+ db 07fh, 063h, 07fh, 063h, 063h, 067h, 0e6h, 0c0h, 099h, 05ah, 03ch, 0e7h, 0e7h, 03ch, 05ah, 099h
+ db 080h, 0e0h, 0f8h, 0feh, 0f8h, 0e0h, 080h, 000h, 002h, 00eh, 03eh, 0feh, 03eh, 00eh, 002h, 000h
+ db 018h, 03ch, 07eh, 018h, 018h, 07eh, 03ch, 018h, 066h, 066h, 066h, 066h, 066h, 000h, 066h, 000h
+ db 07fh, 0dbh, 0dbh, 07bh, 01bh, 01bh, 01bh, 000h, 03eh, 063h, 038h, 06ch, 06ch, 038h, 0cch, 078h
+ db 000h, 000h, 000h, 000h, 07eh, 07eh, 07eh, 000h, 018h, 03ch, 07eh, 018h, 07eh, 03ch, 018h, 0ffh
+ db 018h, 03ch, 07eh, 018h, 018h, 018h, 018h, 000h, 018h, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h
+ db 000h, 018h, 00ch, 0feh, 00ch, 018h, 000h, 000h, 000h, 030h, 060h, 0feh, 060h, 030h, 000h, 000h
+ db 000h, 000h, 0c0h, 0c0h, 0c0h, 0feh, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h
+ db 000h, 018h, 03ch, 07eh, 0ffh, 0ffh, 000h, 000h, 000h, 0ffh, 0ffh, 07eh, 03ch, 018h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 078h, 078h, 030h, 030h, 000h, 030h, 000h
+ db 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h, 000h, 06ch, 06ch, 0feh, 06ch, 0feh, 06ch, 06ch, 000h
+ db 030h, 07ch, 0c0h, 078h, 00ch, 0f8h, 030h, 000h, 000h, 0c6h, 0cch, 018h, 030h, 066h, 0c6h, 000h
+ db 038h, 06ch, 038h, 076h, 0dch, 0cch, 076h, 000h, 060h, 060h, 0c0h, 000h, 000h, 000h, 000h, 000h
+ db 018h, 030h, 060h, 060h, 060h, 030h, 018h, 000h, 060h, 030h, 018h, 018h, 018h, 030h, 060h, 000h
+ db 000h, 066h, 03ch, 0ffh, 03ch, 066h, 000h, 000h, 000h, 030h, 030h, 0fch, 030h, 030h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 060h, 000h, 000h, 000h, 0fch, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 000h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 080h, 000h
+ db 07ch, 0c6h, 0ceh, 0deh, 0f6h, 0e6h, 07ch, 000h, 030h, 070h, 030h, 030h, 030h, 030h, 0fch, 000h
+ db 078h, 0cch, 00ch, 038h, 060h, 0cch, 0fch, 000h, 078h, 0cch, 00ch, 038h, 00ch, 0cch, 078h, 000h
+ db 01ch, 03ch, 06ch, 0cch, 0feh, 00ch, 01eh, 000h, 0fch, 0c0h, 0f8h, 00ch, 00ch, 0cch, 078h, 000h
+ db 038h, 060h, 0c0h, 0f8h, 0cch, 0cch, 078h, 000h, 0fch, 0cch, 00ch, 018h, 030h, 030h, 030h, 000h
+ db 078h, 0cch, 0cch, 078h, 0cch, 0cch, 078h, 000h, 078h, 0cch, 0cch, 07ch, 00ch, 018h, 070h, 000h
+ db 000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h, 000h, 030h, 030h, 060h
+ db 018h, 030h, 060h, 0c0h, 060h, 030h, 018h, 000h, 000h, 000h, 0fch, 000h, 000h, 0fch, 000h, 000h
+ db 060h, 030h, 018h, 00ch, 018h, 030h, 060h, 000h, 078h, 0cch, 00ch, 018h, 030h, 000h, 030h, 000h
+ db 07ch, 0c6h, 0deh, 0deh, 0deh, 0c0h, 078h, 000h, 030h, 078h, 0cch, 0cch, 0fch, 0cch, 0cch, 000h
+ db 0fch, 066h, 066h, 07ch, 066h, 066h, 0fch, 000h, 03ch, 066h, 0c0h, 0c0h, 0c0h, 066h, 03ch, 000h
+ db 0f8h, 06ch, 066h, 066h, 066h, 06ch, 0f8h, 000h, 0feh, 062h, 068h, 078h, 068h, 062h, 0feh, 000h
+ db 0feh, 062h, 068h, 078h, 068h, 060h, 0f0h, 000h, 03ch, 066h, 0c0h, 0c0h, 0ceh, 066h, 03eh, 000h
+ db 0cch, 0cch, 0cch, 0fch, 0cch, 0cch, 0cch, 000h, 078h, 030h, 030h, 030h, 030h, 030h, 078h, 000h
+ db 01eh, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 000h, 0e6h, 066h, 06ch, 078h, 06ch, 066h, 0e6h, 000h
+ db 0f0h, 060h, 060h, 060h, 062h, 066h, 0feh, 000h, 0c6h, 0eeh, 0feh, 0feh, 0d6h, 0c6h, 0c6h, 000h
+ db 0c6h, 0e6h, 0f6h, 0deh, 0ceh, 0c6h, 0c6h, 000h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 06ch, 038h, 000h
+ db 0fch, 066h, 066h, 07ch, 060h, 060h, 0f0h, 000h, 078h, 0cch, 0cch, 0cch, 0dch, 078h, 01ch, 000h
+ db 0fch, 066h, 066h, 07ch, 06ch, 066h, 0e6h, 000h, 078h, 0cch, 0e0h, 070h, 01ch, 0cch, 078h, 000h
+ db 0fch, 0b4h, 030h, 030h, 030h, 030h, 078h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 0fch, 000h
+ db 0cch, 0cch, 0cch, 0cch, 0cch, 078h, 030h, 000h, 0c6h, 0c6h, 0c6h, 0d6h, 0feh, 0eeh, 0c6h, 000h
+ db 0c6h, 0c6h, 06ch, 038h, 038h, 06ch, 0c6h, 000h, 0cch, 0cch, 0cch, 078h, 030h, 030h, 078h, 000h
+ db 0feh, 0c6h, 08ch, 018h, 032h, 066h, 0feh, 000h, 078h, 060h, 060h, 060h, 060h, 060h, 078h, 000h
+ db 0c0h, 060h, 030h, 018h, 00ch, 006h, 002h, 000h, 078h, 018h, 018h, 018h, 018h, 018h, 078h, 000h
+ db 010h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh
+ db 030h, 030h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 078h, 00ch, 07ch, 0cch, 076h, 000h
+ db 0e0h, 060h, 060h, 07ch, 066h, 066h, 0dch, 000h, 000h, 000h, 078h, 0cch, 0c0h, 0cch, 078h, 000h
+ db 01ch, 00ch, 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h
+ db 038h, 06ch, 060h, 0f0h, 060h, 060h, 0f0h, 000h, 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 0f8h
+ db 0e0h, 060h, 06ch, 076h, 066h, 066h, 0e6h, 000h, 030h, 000h, 070h, 030h, 030h, 030h, 078h, 000h
+ db 00ch, 000h, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 0e0h, 060h, 066h, 06ch, 078h, 06ch, 0e6h, 000h
+ db 070h, 030h, 030h, 030h, 030h, 030h, 078h, 000h, 000h, 000h, 0cch, 0feh, 0feh, 0d6h, 0c6h, 000h
+ db 000h, 000h, 0f8h, 0cch, 0cch, 0cch, 0cch, 000h, 000h, 000h, 078h, 0cch, 0cch, 0cch, 078h, 000h
+ db 000h, 000h, 0dch, 066h, 066h, 07ch, 060h, 0f0h, 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 01eh
+ db 000h, 000h, 0dch, 076h, 066h, 060h, 0f0h, 000h, 000h, 000h, 07ch, 0c0h, 078h, 00ch, 0f8h, 000h
+ db 010h, 030h, 07ch, 030h, 030h, 034h, 018h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 076h, 000h
+ db 000h, 000h, 0cch, 0cch, 0cch, 078h, 030h, 000h, 000h, 000h, 0c6h, 0d6h, 0feh, 0feh, 06ch, 000h
+ db 000h, 000h, 0c6h, 06ch, 038h, 06ch, 0c6h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 07ch, 00ch, 0f8h
+ db 000h, 000h, 0fch, 098h, 030h, 064h, 0fch, 000h, 01ch, 030h, 030h, 0e0h, 030h, 030h, 01ch, 000h
+ db 018h, 018h, 018h, 000h, 018h, 018h, 018h, 000h, 0e0h, 030h, 030h, 01ch, 030h, 030h, 0e0h, 000h
+ db 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 000h
+ ; disGetNextSymbol 0xffe6e LB 0x192 -> off=0x0 cb=0000000000000021 uValue=00000000000f1e6e 'biosorg_check_at_0FE6Eh'
+biosorg_check_at_0FE6Eh: ; 0xffe6e LB 0x21
+ cmp ah, 0b1h ; 80 fc b1 ; 0xffe6e orgs.asm:1903
+ jne short 0fe82h ; 75 0f ; 0xffe71 orgs.asm:1904
+ push ES ; 06 ; 0xffe73 orgs.asm:1906
+ push DS ; 1e ; 0xffe74 orgs.asm:1907
+ push CS ; 0e ; 0xffe75 orgs.asm:104
+ pop DS ; 1f ; 0xffe76 orgs.asm:105
+ cld ; fc ; 0xffe77 orgs.asm:106
+ pushad ; 66 60 ; 0xffe78 orgs.asm:1910
+ call 09b78h ; e8 fb 9c ; 0xffe7a orgs.asm:1911
+ popad ; 66 61 ; 0xffe7d orgs.asm:1912
+ pop DS ; 1f ; 0xffe7f orgs.asm:1914
+ pop ES ; 07 ; 0xffe80 orgs.asm:1915
+ iret ; cf ; 0xffe81 orgs.asm:1916
+ push ES ; 06 ; 0xffe82 orgs.asm:1920
+ push DS ; 1e ; 0xffe83 orgs.asm:1921
+ pushaw ; 60 ; 0xffe84 orgs.asm:97
+ push CS ; 0e ; 0xffe85 orgs.asm:104
+ pop DS ; 1f ; 0xffe86 orgs.asm:105
+ cld ; fc ; 0xffe87 orgs.asm:106
+ call 0710fh ; e8 84 72 ; 0xffe88 orgs.asm:1925
+ popaw ; 61 ; 0xffe8b orgs.asm:114
+ pop DS ; 1f ; 0xffe8c orgs.asm:1927
+ pop ES ; 07 ; 0xffe8d orgs.asm:1928
+ iret ; cf ; 0xffe8e orgs.asm:1929
+ ; disGetNextSymbol 0xffe8f LB 0x171 -> off=0x0 cb=0000000000000016 uValue=00000000000f1e8f 'biosorg_check_before_or_at_0FEA3h'
+biosorg_check_before_or_at_0FEA3h: ; 0xffe8f LB 0x16
+ times 0x14 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xffea5 LB 0x15b -> off=0x0 cb=0000000000000043 uValue=00000000000f1ea5 'int08_handler'
+int08_handler: ; 0xffea5 LB 0x43
+ sti ; fb ; 0xffea5 orgs.asm:1939
+ push eax ; 66 50 ; 0xffea6 orgs.asm:1940
+ push DS ; 1e ; 0xffea8 orgs.asm:1945
+ push dx ; 52 ; 0xffea9 orgs.asm:1946
+ mov ax, strict word 00040h ; b8 40 00 ; 0xffeaa orgs.asm:1947
+ mov ds, ax ; 8e d8 ; 0xffead orgs.asm:1948
+ mov eax, dword [0006ch] ; 66 a1 6c 00 ; 0xffeaf orgs.asm:1951
+ inc eax ; 66 40 ; 0xffeb3 orgs.asm:1952
+ cmp eax, strict dword 0001800b0h ; 66 3d b0 00 18 00 ; 0xffeb5 orgs.asm:1964
+ jc short 0fec4h ; 72 07 ; 0xffebb orgs.asm:1965
+ db 066h, 033h, 0c0h
+ ; xor eax, eax ; 66 33 c0 ; 0xffebd orgs.asm:1974
+ inc byte [word 00070h] ; fe 06 70 00 ; 0xffec0 orgs.asm:1975
+ mov dword [0006ch], eax ; 66 a3 6c 00 ; 0xffec4 orgs.asm:1978
+ mov AL, byte [00040h] ; a0 40 00 ; 0xffec8 orgs.asm:1986
+ db 00ah, 0c0h
+ ; or al, al ; 0a c0 ; 0xffecb orgs.asm:1987
+ je short 0feddh ; 74 0e ; 0xffecd orgs.asm:1988
+ db 0feh, 0c8h
+ ; dec al ; fe c8 ; 0xffecf orgs.asm:1989
+ mov byte [00040h], AL ; a2 40 00 ; 0xffed1 orgs.asm:1990
+ jne short 0feddh ; 75 07 ; 0xffed4 orgs.asm:1991
+ mov dx, 003f2h ; ba f2 03 ; 0xffed6 orgs.asm:1993
+ in AL, DX ; ec ; 0xffed9 orgs.asm:1994
+ and AL, strict byte 0cfh ; 24 cf ; 0xffeda orgs.asm:1995
+ out DX, AL ; ee ; 0xffedc orgs.asm:1996
+ int 01ch ; cd 1c ; 0xffedd orgs.asm:1999
+ cli ; fa ; 0xffedf orgs.asm:2001
+ call 0e034h ; e8 51 e1 ; 0xffee0 orgs.asm:2002
+ pop dx ; 5a ; 0xffee3 orgs.asm:2003
+ pop DS ; 1f ; 0xffee4 orgs.asm:2004
+ pop eax ; 66 58 ; 0xffee5 orgs.asm:2006
+ iret ; cf ; 0xffee7 orgs.asm:2011
+ ; disGetNextSymbol 0xffee8 LB 0x118 -> off=0x0 cb=000000000000000b uValue=00000000000f1ee8 'biosorg_check_before_or_at_0FEF1h'
+biosorg_check_before_or_at_0FEF1h: ; 0xffee8 LB 0xb
+ times 0x9 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xffef3 LB 0x10d -> off=0x0 cb=000000000000000d uValue=00000000000f1ef3 'biosorg_check_at_0FEF3h'
+biosorg_check_at_0FEF3h: ; 0xffef3 LB 0xd
+ times 0xb db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfff00 LB 0x100 -> off=0x0 cb=0000000000000019 uValue=00000000000f1f00 'biosorg_check_at_0FF00h'
+biosorg_check_at_0FF00h: ; 0xfff00 LB 0x19
+ dec di ; 4f ; 0xfff00
+ jc short 0ff64h ; 72 61 ; 0xfff01
+ arpl [si+065h], bp ; 63 6c 65 ; 0xfff03
+ and byte [bp+04dh], dl ; 20 56 4d ; 0xfff06
+ and byte [bp+069h], dl ; 20 56 69 ; 0xfff09
+ jc short 0ff82h ; 72 74 ; 0xfff0c
+ jne short 0ff71h ; 75 61 ; 0xfff0e
+ insb ; 6c ; 0xfff10
+ inc dx ; 42 ; 0xfff11
+ outsw ; 6f ; 0xfff12
+ js short 0ff35h ; 78 20 ; 0xfff13
+ inc dx ; 42 ; 0xfff15
+ dec cx ; 49 ; 0xfff16
+ dec di ; 4f ; 0xfff17
+ push bx ; 53 ; 0xfff18
+ ; disGetNextSymbol 0xfff19 LB 0xe7 -> off=0x0 cb=000000000000003a uValue=00000000000f1f19 'biosorg_check_before_or_at_0FF51h'
+biosorg_check_before_or_at_0FF51h: ; 0xfff19 LB 0x3a
+ times 0x38 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfff53 LB 0xad -> off=0x0 cb=0000000000000001 uValue=00000000000f1f53 'dummy_iret'
+dummy_iret: ; 0xfff53 LB 0x1
+ iret ; cf ; 0xfff53 orgs.asm:2036
+ ; disGetNextSymbol 0xfff54 LB 0xac -> off=0x0 cb=000000000000002c uValue=00000000000f1f54 'biosorg_check_at_0FF54h'
+biosorg_check_at_0FF54h: ; 0xfff54 LB 0x2c
+ iret ; cf ; 0xfff54 orgs.asm:2045
+ mov ax, ax ; 89 c0 ; 0xfff55
+ mov ax, ax ; 89 c0 ; 0xfff57
+ mov ax, ax ; 89 c0 ; 0xfff59
+ mov ax, ax ; 89 c0 ; 0xfff5b
+ mov ax, ax ; 89 c0 ; 0xfff5d
+ cld ; fc ; 0xfff5f
+ pop di ; 5f ; 0xfff60
+ push bx ; 53 ; 0xfff61
+ dec bp ; 4d ; 0xfff62
+ pop di ; 5f ; 0xfff63
+ jnl short 0ff85h ; 7d 1f ; 0xfff64
+ add al, byte [di] ; 02 05 ; 0xfff66
+ inc word [bx+si] ; ff 00 ; 0xfff68
+ add byte [bx+si], al ; 00 00 ; 0xfff6a
+ add byte [bx+si], al ; 00 00 ; 0xfff6c
+ add byte [bx+si], al ; 00 00 ; 0xfff6e
+ pop di ; 5f ; 0xfff70
+ inc sp ; 44 ; 0xfff71
+ dec bp ; 4d ; 0xfff72
+ dec cx ; 49 ; 0xfff73
+ pop di ; 5f ; 0xfff74
+ and ax, strict word 00000h ; 25 00 00 ; 0xfff75
+ add byte [bx+si], dl ; 00 10 ; 0xfff78
+ push CS ; 0e ; 0xfff7a
+ add byte [bx+si], al ; 00 00 ; 0xfff7b
+ add byte [di], ah ; 00 25 ; 0xfff7d
+ times 0x1 db 0
+ ; disGetNextSymbol 0xfff80 LB 0x80 -> off=0x0 cb=0000000000000070 uValue=00000000000f1f80 'biosorg_check_before_or_at_0FFEEh'
+biosorg_check_before_or_at_0FFEEh: ; 0xfff80 LB 0x70
+ times 0x6e db 0
+ db 'XM'
+ ; disGetNextSymbol 0xffff0 LB 0x10 -> off=0x0 cb=0000000000000010 uValue=00000000000f1ff0 'cpu_reset'
+cpu_reset: ; 0xffff0 LB 0x10
+ jmp far 0f000h:0e05bh ; ea 5b e0 00 f0 ; 0xffff0 orgs.asm:2055
+ ; disGetNextSymbol 0xffff5 LB 0xb -> off=0xb cb=0000000000000000 uValue=0000000000100000 '_dummy_addr_0x100000'
+ db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 041h
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.md5sum b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.md5sum
new file mode 100644
index 00000000..0e14786b
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.md5sum
@@ -0,0 +1 @@
+bf4957d3b704b8fe66ba88679a891536 *VBoxPcBios386.rom
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.asm b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.asm
new file mode 100644
index 00000000..a18b3206
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.asm
@@ -0,0 +1,17844 @@
+; $Id: VBoxBiosAlternative8086.asm $
+;; @file
+; Auto Generated source file. Do not edit.
+;
+
+;
+; Source file: post.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; BIOS POST routines. Used only during initialization.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: bios.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: print.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: ata.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: floppy.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: floppyt.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; Floppy drive tables.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: eltorito.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: boot.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: keyboard.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: disk.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: serial.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: system.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: invop.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; Real mode invalid opcode handler.
+;
+;
+;
+; Copyright (C) 2013-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: timepci.c
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: ps2mouse.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: parallel.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; PC BIOS - ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: logo.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; Stuff for drawing the BIOS logo.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: scsi.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; SCSI host adapter driver to boot from SCSI disks
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: ahci.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; AHCI host adapter driver to boot from SATA disks.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: apm.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; APM BIOS support. Implements APM version 1.2.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: pcibios.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; PCI BIOS support.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: pciutil.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; Utility routines for calling the PCI BIOS.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: vds.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; Utility routines for calling the Virtual DMA Services.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: __U4M.asm
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: __U4D.asm
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: __U8RS.asm
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: __U8LS.asm
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: fmemset.asm
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: fmemcpy.asm
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; Compiler support routines.
+;
+;
+;
+; Copyright (C) 2012-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: pcibio32.asm
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; BIOS32 service directory and 32-bit PCI BIOS entry point
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+
+;
+; Source file: apm_pm.asm
+;
+; $Id:
+; Protected-mode APM implementation.
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: orgs.asm
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; ???
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+;
+; Source file: DoUInt32Div.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; AHCI host adapter driver to boot from SATA disks.
+;
+;
+;
+; Copyright (C) 2011-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+;
+; Source file: ASMBitLastSetU16.asm
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; BiosCommonCode - ASMBitLastSetU16() - borrowed from IPRT.
+;
+;
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;
+; Source file: pci32.c
+;
+; $Id: VBoxBiosAlternative8086.asm $
+; 32-bit PCI BIOS wrapper.
+;
+;
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+
+
+
+section _DATA progbits vstart=0x0 align=1 ; size=0xb0 class=DATA group=DGROUP
+ ; disGetNextSymbol 0xf0000 LB 0xb0 -> off=0x0 cb=000000000000005b uValue=00000000000f0000 '_fd_parm'
+_fd_parm: ; 0xf0000 LB 0x5b
+ db 0dfh, 002h, 025h, 002h, 009h, 02ah, 0ffh, 050h, 0f6h, 00fh, 008h, 027h, 080h, 0dfh, 002h, 025h
+ db 002h, 009h, 02ah, 0ffh, 050h, 0f6h, 00fh, 008h, 027h, 040h, 0dfh, 002h, 025h, 002h, 00fh, 01bh
+ db 0ffh, 054h, 0f6h, 00fh, 008h, 04fh, 000h, 0dfh, 002h, 025h, 002h, 009h, 02ah, 0ffh, 050h, 0f6h
+ db 00fh, 008h, 04fh, 080h, 0afh, 002h, 025h, 002h, 012h, 01bh, 0ffh, 06ch, 0f6h, 00fh, 008h, 04fh
+ db 000h, 0afh, 002h, 025h, 002h, 024h, 01bh, 0ffh, 054h, 0f6h, 00fh, 008h, 04fh, 0c0h, 0afh, 002h
+ db 025h, 002h, 0ffh, 01bh, 0ffh, 054h, 0f6h, 00fh, 008h, 0ffh, 000h
+ ; disGetNextSymbol 0xf005b LB 0x55 -> off=0x0 cb=000000000000000f uValue=00000000000f005b '_fd_map'
+_fd_map: ; 0xf005b LB 0xf
+ db 001h, 000h, 002h, 002h, 003h, 003h, 004h, 004h, 005h, 005h, 00eh, 006h, 00fh, 006h, 000h
+ ; disGetNextSymbol 0xf006a LB 0x46 -> off=0x0 cb=000000000000000c uValue=00000000000f006a '_pktacc'
+_pktacc: ; 0xf006a LB 0xc
+ db 000h, 000h, 000h, 000h, 000h, 000h, 044h, 02bh, 0a1h, 07ch, 087h, 08ch
+ ; disGetNextSymbol 0xf0076 LB 0x3a -> off=0x0 cb=000000000000000c uValue=00000000000f0076 '_softrst'
+_softrst: ; 0xf0076 LB 0xc
+ db 000h, 000h, 000h, 000h, 000h, 000h, 0d9h, 02dh, 0dah, 03bh, 0dah, 03bh
+ ; disGetNextSymbol 0xf0082 LB 0x2e -> off=0x0 cb=000000000000002e uValue=00000000000f0082 '_dskacc'
+_dskacc: ; 0xf0082 LB 0x2e
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 028h, 02ah, 0e9h, 02ah, 000h, 000h, 000h, 000h
+ db 0cfh, 07ah, 0b8h, 07bh, 055h, 08bh, 0ffh, 08bh, 000h, 000h, 000h, 000h, 000h, 000h, 05fh, 033h
+ db 032h, 05fh, 000h, 0dah, 00fh, 000h, 000h, 001h, 0f3h, 000h, 000h, 000h, 000h, 000h
+
+section CONST progbits vstart=0xb0 align=1 ; size=0xcde class=DATA group=DGROUP
+ ; disGetNextSymbol 0xf00b0 LB 0xcde -> off=0xcde cb=0000000000000000 uValue=00000000000f0d8e 'bios_cvs_version_string'
+ db 'NMI Handler called', 00ah, 000h
+ db 'INT18: BOOT FAILURE', 00ah, 000h
+ db '%s', 00ah, 000h, 000h
+ db 'FATAL: ', 000h
+ db 'bios_printf: unknown %ll format', 00ah, 000h
+ db 'bios_printf: unknown format', 00ah, 000h
+ db 'ata-detect: Failed to detect ATA device', 00ah, 000h
+ db 'ata%d-%d: PCHS=%u/%u/%u LCHS=%u/%u/%u', 00ah, 000h
+ db 'ata-detect: Failed to detect ATAPI device', 00ah, 000h
+ db ' slave', 000h
+ db 'master', 000h
+ db 'ata%d %s: ', 000h
+ db '%c', 000h
+ db ' ATA-%d Hard-Disk (%lu MBytes)', 00ah, 000h
+ db ' ATAPI-%d CD-ROM/DVD-ROM', 00ah, 000h
+ db ' ATAPI-%d Device', 00ah, 000h
+ db 'ata%d %s: Unknown device', 00ah, 000h
+ db 'ata_cmd_packet', 000h
+ db '%s: DATA_OUT not supported yet', 00ah, 000h
+ db 'set_diskette_current_cyl: drive > 1', 00ah, 000h
+ db 'int13_diskette_function', 000h
+ db '%s: drive>1 || head>1 ...', 00ah, 000h
+ db '%s: ctrl not ready', 00ah, 000h
+ db '%s: write error', 00ah, 000h
+ db '%s: bad floppy type', 00ah, 000h
+ db '%s: unsupported AH=%02x', 00ah, 000h, 000h
+ db 'int13_eltorito', 000h
+ db '%s: call with AX=%04x not implemented.', 00ah, 000h
+ db '%s: unsupported AH=%02x', 00ah, 000h
+ db 'int13_cdemu', 000h
+ db '%s: function %02x, emulation not active for DL= %02x', 00ah, 000h
+ db '%s: function %02x, error %02x !', 00ah, 000h
+ db '%s: function %02x. Can', 027h, 't use 64bits lba', 00ah, 000h
+ db '%s: function %02x, status %02x !', 00ah, 000h
+ db '%s: function AH=%02x unsupported, returns fail', 00ah, 000h
+ db 'int13_cdrom', 000h
+ db '%s: function %02x, ELDL out of range %02x', 00ah, 000h
+ db '%s: function %02x, unmapped device for ELDL=%02x', 00ah, 000h, 000h
+ db 'Booting from %s...', 00ah, 000h
+ db 'Boot from %s failed', 00ah, 000h
+ db 'Boot from %s %d failed', 00ah, 000h
+ db 'No bootable medium found! System halted.', 00ah, 000h
+ db 'Could not read from the boot medium! System halted.', 00ah, 000h
+ db 'CDROM boot failure code : %04x', 00ah, 000h
+ db 'Boot : bseqnr=%d, bootseq=%x', 00dh, 00ah, 000h, 000h
+ db 'Keyboard error:%u', 00ah, 000h
+ db 'KBD: int09 handler: AL=0', 00ah, 000h
+ db 'KBD: int09h_handler(): unknown scancode read: 0x%02x!', 00ah, 000h
+ db 'KBD: int09h_handler(): scancode & asciicode are zero?', 00ah, 000h
+ db 'KBD: int16h: out of keyboard input', 00ah, 000h
+ db 'KBD: unsupported int 16h function %02x', 00ah, 000h
+ db 'AX=%04x BX=%04x CX=%04x DX=%04x ', 00ah, 000h, 000h
+ db 'int13_harddisk', 000h
+ db '%s: function %02x, ELDL out of range %02x', 00ah, 000h
+ db '%s: function %02x, unmapped device for ELDL=%02x', 00ah, 000h
+ db '%s: function %02x, count out of range!', 00ah, 000h
+ db '%s: function %02x, disk %02x, parameters out of range %04x/%04x/%04x!', 00ah
+ db 000h
+ db '%s: function %02x, error %02x !', 00ah, 000h
+ db 'format disk track called', 00ah, 000h
+ db '%s: function %02xh unimplemented, returns success', 00ah, 000h
+ db '%s: function %02xh unsupported, returns fail', 00ah, 000h
+ db 'int13_harddisk_ext', 000h
+ db '%s: function %02x. LBA out of range', 00ah, 000h, 000h
+ db 'int15: Func 24h, subfunc %02xh, A20 gate control not supported', 00ah, 000h
+ db '*** int 15h function AH=bf not yet supported!', 00ah, 000h
+ db 'EISA BIOS not present', 00ah, 000h
+ db '*** int 15h function AX=%04x, BX=%04x not yet supported!', 00ah, 000h
+ db 'sendmouse', 000h
+ db 'setkbdcomm', 000h
+ db 'Mouse reset returned %02x (should be ack)', 00ah, 000h
+ db 'Mouse status returned %02x (should be ack)', 00ah, 000h
+ db 'INT 15h C2 AL=6, BH=%02x', 00ah, 000h
+ db 'INT 15h C2 default case entered', 00ah, 000h, 000h
+ db 'Key pressed: %x', 00ah, 000h
+ db 00ah, 00ah, ' AHCI controller:', 000h
+ db 00ah, ' %d) Hard disk', 000h
+ db 00ah, 00ah, ' SCSI controller:', 000h
+ db ' IDE controller:', 000h
+ db 00ah, 00ah, 'AHCI controller:', 00ah, 000h
+ db 00ah, ' %d) ', 000h
+ db 'Secondary ', 000h
+ db 'Primary ', 000h
+ db 'Slave', 000h
+ db 'Master', 000h
+ db 'No hard disks found', 000h
+ db 00ah, 000h
+ db 'Press F12 to select boot device.', 00ah, 000h
+ db 00ah, 'VirtualBox temporary boot device selection', 00ah, 00ah, 'Detected H'
+ db 'ard disks:', 00ah, 00ah, 000h
+ db 00ah, 'Other boot devices:', 00ah, ' f) Floppy', 00ah, ' c) CD-ROM', 00ah
+ db ' l) LAN', 00ah, 00ah, ' b) Continue booting', 00ah, 000h
+ db 'Delaying boot for %d seconds:', 000h
+ db ' %d', 000h, 000h
+ db 'scsi_read_sectors', 000h
+ db '%s: device_id out of range %d', 00ah, 000h
+ db 'scsi_write_sectors', 000h
+ db 'scsi_cmd_packet', 000h
+ db '%s: DATA_OUT not supported yet', 00ah, 000h
+ db 'scsi_enumerate_attached_devices', 000h
+ db '%s: SCSI_INQUIRY failed', 00ah, 000h
+ db '%s: SCSI_READ_CAPACITY failed', 00ah, 000h
+ db 'Disk %d has an unsupported sector size of %u', 00ah, 000h
+ db 'SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors', 00ah, 000h
+ db 'SCSI %d-ID#%d: CD/DVD-ROM', 00ah, 000h, 000h
+ db 'ahci_read_sectors', 000h
+ db '%s: device_id out of range %d', 00ah, 000h
+ db 'ahci_write_sectors', 000h
+ db 'ahci_cmd_packet', 000h
+ db '%s: DATA_OUT not supported yet', 00ah, 000h
+ db 'AHCI %d-P#%d: PCHS=%u/%u/%u LCHS=%u/%u/%u 0x%llx sectors', 00ah, 000h
+ db 'Standby', 000h
+ db 'Suspend', 000h
+ db 'Shutdown', 000h
+ db 'APM: Unsupported function AX=%04X BX=%04X called', 00ah, 000h, 000h
+ db 'PCI: Unsupported function AX=%04X BX=%04X called', 00ah, 000h
+
+section CONST2 progbits vstart=0xd8e align=1 ; size=0x3fa class=DATA group=DGROUP
+ ; disGetNextSymbol 0xf0d8e LB 0x3fa -> off=0x0 cb=0000000000000012 uValue=00000000000f0d8e 'bios_cvs_version_string'
+bios_cvs_version_string: ; 0xf0d8e LB 0x12
+ db 'VirtualBox 6.0.4', 000h, 000h
+ ; disGetNextSymbol 0xf0da0 LB 0x3e8 -> off=0x0 cb=0000000000000008 uValue=00000000000f0da0 '_bios_prefix_string'
+_bios_prefix_string: ; 0xf0da0 LB 0x8
+ db 'BIOS: ', 000h, 000h
+ ; disGetNextSymbol 0xf0da8 LB 0x3e0 -> off=0x0 cb=0000000000000006 uValue=00000000000f0da8 'isotag'
+isotag: ; 0xf0da8 LB 0x6
+ db 'CD001', 000h
+ ; disGetNextSymbol 0xf0dae LB 0x3da -> off=0x0 cb=0000000000000018 uValue=00000000000f0dae 'eltorito'
+eltorito: ; 0xf0dae LB 0x18
+ db 'EL TORITO SPECIFICATION', 000h
+ ; disGetNextSymbol 0xf0dc6 LB 0x3c2 -> off=0x0 cb=0000000000000028 uValue=00000000000f0dc6 'drivetypes'
+drivetypes: ; 0xf0dc6 LB 0x28
+ db 046h, 06ch, 06fh, 070h, 070h, 079h, 000h, 000h, 000h, 000h, 048h, 061h, 072h, 064h, 020h, 044h
+ db 069h, 073h, 06bh, 000h, 043h, 044h, 02dh, 052h, 04fh, 04dh, 000h, 000h, 000h, 000h, 04ch, 041h
+ db 04eh, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ ; disGetNextSymbol 0xf0dee LB 0x39a -> off=0x0 cb=000000000000037a uValue=00000000000f0dee 'scan_to_scanascii'
+scan_to_scanascii: ; 0xf0dee LB 0x37a
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 01bh, 001h, 01bh, 001h, 01bh, 001h
+ db 000h, 001h, 000h, 000h, 031h, 002h, 021h, 002h, 000h, 000h, 000h, 078h, 000h, 000h, 032h, 003h
+ db 040h, 003h, 000h, 003h, 000h, 079h, 000h, 000h, 033h, 004h, 023h, 004h, 000h, 000h, 000h, 07ah
+ db 000h, 000h, 034h, 005h, 024h, 005h, 000h, 000h, 000h, 07bh, 000h, 000h, 035h, 006h, 025h, 006h
+ db 000h, 000h, 000h, 07ch, 000h, 000h, 036h, 007h, 05eh, 007h, 01eh, 007h, 000h, 07dh, 000h, 000h
+ db 037h, 008h, 026h, 008h, 000h, 000h, 000h, 07eh, 000h, 000h, 038h, 009h, 02ah, 009h, 000h, 000h
+ db 000h, 07fh, 000h, 000h, 039h, 00ah, 028h, 00ah, 000h, 000h, 000h, 080h, 000h, 000h, 030h, 00bh
+ db 029h, 00bh, 000h, 000h, 000h, 081h, 000h, 000h, 02dh, 00ch, 05fh, 00ch, 01fh, 00ch, 000h, 082h
+ db 000h, 000h, 03dh, 00dh, 02bh, 00dh, 000h, 000h, 000h, 083h, 000h, 000h, 008h, 00eh, 008h, 00eh
+ db 07fh, 00eh, 000h, 000h, 000h, 000h, 009h, 00fh, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h
+ db 071h, 010h, 051h, 010h, 011h, 010h, 000h, 010h, 040h, 000h, 077h, 011h, 057h, 011h, 017h, 011h
+ db 000h, 011h, 040h, 000h, 065h, 012h, 045h, 012h, 005h, 012h, 000h, 012h, 040h, 000h, 072h, 013h
+ db 052h, 013h, 012h, 013h, 000h, 013h, 040h, 000h, 074h, 014h, 054h, 014h, 014h, 014h, 000h, 014h
+ db 040h, 000h, 079h, 015h, 059h, 015h, 019h, 015h, 000h, 015h, 040h, 000h, 075h, 016h, 055h, 016h
+ db 015h, 016h, 000h, 016h, 040h, 000h, 069h, 017h, 049h, 017h, 009h, 017h, 000h, 017h, 040h, 000h
+ db 06fh, 018h, 04fh, 018h, 00fh, 018h, 000h, 018h, 040h, 000h, 070h, 019h, 050h, 019h, 010h, 019h
+ db 000h, 019h, 040h, 000h, 05bh, 01ah, 07bh, 01ah, 01bh, 01ah, 000h, 000h, 000h, 000h, 05dh, 01bh
+ db 07dh, 01bh, 01dh, 01bh, 000h, 000h, 000h, 000h, 00dh, 01ch, 00dh, 01ch, 00ah, 01ch, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 061h, 01eh, 041h, 01eh
+ db 001h, 01eh, 000h, 01eh, 040h, 000h, 073h, 01fh, 053h, 01fh, 013h, 01fh, 000h, 01fh, 040h, 000h
+ db 064h, 020h, 044h, 020h, 004h, 020h, 000h, 020h, 040h, 000h, 066h, 021h, 046h, 021h, 006h, 021h
+ db 000h, 021h, 040h, 000h, 067h, 022h, 047h, 022h, 007h, 022h, 000h, 022h, 040h, 000h, 068h, 023h
+ db 048h, 023h, 008h, 023h, 000h, 023h, 040h, 000h, 06ah, 024h, 04ah, 024h, 00ah, 024h, 000h, 024h
+ db 040h, 000h, 06bh, 025h, 04bh, 025h, 00bh, 025h, 000h, 025h, 040h, 000h, 06ch, 026h, 04ch, 026h
+ db 00ch, 026h, 000h, 026h, 040h, 000h, 03bh, 027h, 03ah, 027h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 027h, 028h, 022h, 028h, 000h, 000h, 000h, 000h, 000h, 000h, 060h, 029h, 07eh, 029h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 05ch, 02bh
+ db 07ch, 02bh, 01ch, 02bh, 000h, 000h, 000h, 000h, 07ah, 02ch, 05ah, 02ch, 01ah, 02ch, 000h, 02ch
+ db 040h, 000h, 078h, 02dh, 058h, 02dh, 018h, 02dh, 000h, 02dh, 040h, 000h, 063h, 02eh, 043h, 02eh
+ db 003h, 02eh, 000h, 02eh, 040h, 000h, 076h, 02fh, 056h, 02fh, 016h, 02fh, 000h, 02fh, 040h, 000h
+ db 062h, 030h, 042h, 030h, 002h, 030h, 000h, 030h, 040h, 000h, 06eh, 031h, 04eh, 031h, 00eh, 031h
+ db 000h, 031h, 040h, 000h, 06dh, 032h, 04dh, 032h, 00dh, 032h, 000h, 032h, 040h, 000h, 02ch, 033h
+ db 03ch, 033h, 000h, 000h, 000h, 000h, 000h, 000h, 02eh, 034h, 03eh, 034h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 02fh, 035h, 03fh, 035h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 02ah, 037h, 02ah, 037h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 020h, 039h, 020h, 039h, 020h, 039h
+ db 020h, 039h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 03bh
+ db 000h, 054h, 000h, 05eh, 000h, 068h, 000h, 000h, 000h, 03ch, 000h, 055h, 000h, 05fh, 000h, 069h
+ db 000h, 000h, 000h, 03dh, 000h, 056h, 000h, 060h, 000h, 06ah, 000h, 000h, 000h, 03eh, 000h, 057h
+ db 000h, 061h, 000h, 06bh, 000h, 000h, 000h, 03fh, 000h, 058h, 000h, 062h, 000h, 06ch, 000h, 000h
+ db 000h, 040h, 000h, 059h, 000h, 063h, 000h, 06dh, 000h, 000h, 000h, 041h, 000h, 05ah, 000h, 064h
+ db 000h, 06eh, 000h, 000h, 000h, 042h, 000h, 05bh, 000h, 065h, 000h, 06fh, 000h, 000h, 000h, 043h
+ db 000h, 05ch, 000h, 066h, 000h, 070h, 000h, 000h, 000h, 044h, 000h, 05dh, 000h, 067h, 000h, 071h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 047h, 037h, 047h, 000h, 077h, 000h, 000h, 020h, 000h
+ db 000h, 048h, 038h, 048h, 000h, 000h, 000h, 000h, 020h, 000h, 000h, 049h, 039h, 049h, 000h, 084h
+ db 000h, 000h, 020h, 000h, 02dh, 04ah, 02dh, 04ah, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 04bh
+ db 034h, 04bh, 000h, 073h, 000h, 000h, 020h, 000h, 000h, 04ch, 035h, 04ch, 000h, 000h, 000h, 000h
+ db 020h, 000h, 000h, 04dh, 036h, 04dh, 000h, 074h, 000h, 000h, 020h, 000h, 02bh, 04eh, 02bh, 04eh
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 04fh, 031h, 04fh, 000h, 075h, 000h, 000h, 020h, 000h
+ db 000h, 050h, 032h, 050h, 000h, 000h, 000h, 000h, 020h, 000h, 000h, 051h, 033h, 051h, 000h, 076h
+ db 000h, 000h, 020h, 000h, 000h, 052h, 030h, 052h, 000h, 000h, 000h, 000h, 020h, 000h, 000h, 053h
+ db 02eh, 053h, 000h, 000h, 000h, 000h, 020h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 05ch, 056h, 07ch, 056h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 085h, 000h, 087h, 000h, 089h, 000h, 08bh, 000h, 000h
+ db 000h, 086h, 000h, 088h, 000h, 08ah, 000h, 08ch, 000h, 000h
+ ; disGetNextSymbol 0xf1168 LB 0x20 -> off=0x0 cb=0000000000000020 uValue=00000000000f1168 'panic_msg_keyb_buffer_full'
+panic_msg_keyb_buffer_full: ; 0xf1168 LB 0x20
+ db '%s: keyboard input buffer full', 00ah, 000h
+
+ ; Padding 0x478 bytes at 0xf1188
+ times 1144 db 0
+
+section _TEXT progbits vstart=0x1600 align=1 ; size=0x8948 class=CODE group=AUTO
+ ; disGetNextSymbol 0xf1600 LB 0x8948 -> off=0x0 cb=0000000000000052 uValue=00000000000f0000 'rom_scan'
+rom_scan: ; 0xf1600 LB 0x52
+ push bp ; 55 ; 0xf1600 post.c:73
+ mov bp, sp ; 89 e5 ; 0xf1601
+ push bx ; 53 ; 0xf1603
+ push cx ; 51 ; 0xf1604
+ push si ; 56 ; 0xf1605
+ push di ; 57 ; 0xf1606
+ push ax ; 50 ; 0xf1607
+ push ax ; 50 ; 0xf1608
+ mov bx, ax ; 89 c3 ; 0xf1609
+ mov di, dx ; 89 d7 ; 0xf160b
+ cmp bx, di ; 39 fb ; 0xf160d post.c:80
+ jnc short 01649h ; 73 38 ; 0xf160f
+ xor si, si ; 31 f6 ; 0xf1611 post.c:81
+ mov dx, bx ; 89 da ; 0xf1613
+ mov es, bx ; 8e c3 ; 0xf1615 post.c:83
+ cmp word [es:si], 0aa55h ; 26 81 3c 55 aa ; 0xf1617
+ jne short 01643h ; 75 25 ; 0xf161c
+ mov word [bp-00ah], bx ; 89 5e f6 ; 0xf161e post.c:89
+ mov word [bp-00ch], strict word 00003h ; c7 46 f4 03 00 ; 0xf1621
+ call far [bp-00ch] ; ff 5e f4 ; 0xf1626 post.c:90
+ cli ; fa ; 0xf1629 post.c:91
+ mov es, bx ; 8e c3 ; 0xf162a post.c:95
+ mov al, byte [es:si+002h] ; 26 8a 44 02 ; 0xf162c
+ add AL, strict byte 003h ; 04 03 ; 0xf1630
+ and AL, strict byte 0fch ; 24 fc ; 0xf1632
+ xor ah, ah ; 30 e4 ; 0xf1634 post.c:96
+ cwd ; 99 ; 0xf1636
+ mov CL, strict byte 002h ; b1 02 ; 0xf1637
+ sal dx, CL ; d3 e2 ; 0xf1639
+ db 01bh, 0c2h
+ ; sbb ax, dx ; 1b c2 ; 0xf163b
+ sar ax, CL ; d3 f8 ; 0xf163d
+ add bx, ax ; 01 c3 ; 0xf163f
+ jmp short 0160dh ; eb ca ; 0xf1641 post.c:98
+ add bx, 00080h ; 81 c3 80 00 ; 0xf1643 post.c:100
+ jmp short 0160dh ; eb c4 ; 0xf1647 post.c:102
+ lea sp, [bp-008h] ; 8d 66 f8 ; 0xf1649 post.c:103
+ pop di ; 5f ; 0xf164c
+ pop si ; 5e ; 0xf164d
+ pop cx ; 59 ; 0xf164e
+ pop bx ; 5b ; 0xf164f
+ pop bp ; 5d ; 0xf1650
+ retn ; c3 ; 0xf1651
+ ; disGetNextSymbol 0xf1652 LB 0x88f6 -> off=0x0 cb=000000000000001b uValue=00000000000f0052 'inb_cmos'
+inb_cmos: ; 0xf1652 LB 0x1b
+ push bp ; 55 ; 0xf1652 bios.c:65
+ mov bp, sp ; 89 e5 ; 0xf1653
+ push dx ; 52 ; 0xf1655
+ mov AH, strict byte 070h ; b4 70 ; 0xf1656 bios.c:67
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf1658 bios.c:69
+ jc short 0165eh ; 72 02 ; 0xf165a
+ mov AH, strict byte 072h ; b4 72 ; 0xf165c bios.c:70
+ mov dl, ah ; 88 e2 ; 0xf165e bios.c:71
+ xor dh, dh ; 30 f6 ; 0xf1660
+ out DX, AL ; ee ; 0xf1662
+ inc dx ; 42 ; 0xf1663 bios.c:72
+ in AL, DX ; ec ; 0xf1664
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1665
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf1667 bios.c:73
+ pop dx ; 5a ; 0xf166a
+ pop bp ; 5d ; 0xf166b
+ retn ; c3 ; 0xf166c
+ ; disGetNextSymbol 0xf166d LB 0x88db -> off=0x0 cb=000000000000001d uValue=00000000000f006d 'outb_cmos'
+outb_cmos: ; 0xf166d LB 0x1d
+ push bp ; 55 ; 0xf166d bios.c:75
+ mov bp, sp ; 89 e5 ; 0xf166e
+ push bx ; 53 ; 0xf1670
+ mov bl, dl ; 88 d3 ; 0xf1671
+ mov AH, strict byte 070h ; b4 70 ; 0xf1673 bios.c:77
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf1675 bios.c:79
+ jc short 0167bh ; 72 02 ; 0xf1677
+ mov AH, strict byte 072h ; b4 72 ; 0xf1679 bios.c:80
+ mov dl, ah ; 88 e2 ; 0xf167b bios.c:81
+ xor dh, dh ; 30 f6 ; 0xf167d
+ out DX, AL ; ee ; 0xf167f
+ inc dx ; 42 ; 0xf1680 bios.c:82
+ mov al, bl ; 88 d8 ; 0xf1681
+ out DX, AL ; ee ; 0xf1683
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf1684 bios.c:83
+ pop bx ; 5b ; 0xf1687
+ pop bp ; 5d ; 0xf1688
+ retn ; c3 ; 0xf1689
+ ; disGetNextSymbol 0xf168a LB 0x88be -> off=0x0 cb=0000000000000061 uValue=00000000000f008a 'dummy_isr_function'
+dummy_isr_function: ; 0xf168a LB 0x61
+ push bp ; 55 ; 0xf168a bios.c:85
+ mov bp, sp ; 89 e5 ; 0xf168b
+ push ax ; 50 ; 0xf168d
+ mov CL, strict byte 0ffh ; b1 ff ; 0xf168e bios.c:93
+ mov AL, strict byte 00bh ; b0 0b ; 0xf1690 bios.c:95
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf1692
+ out DX, AL ; ee ; 0xf1695
+ in AL, DX ; ec ; 0xf1696 bios.c:96
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1697
+ mov bx, ax ; 89 c3 ; 0xf1699
+ mov byte [bp-002h], al ; 88 46 fe ; 0xf169b
+ test al, al ; 84 c0 ; 0xf169e bios.c:97
+ je short 016dch ; 74 3a ; 0xf16a0
+ mov AL, strict byte 00bh ; b0 0b ; 0xf16a2 bios.c:98
+ mov dx, 000a0h ; ba a0 00 ; 0xf16a4
+ out DX, AL ; ee ; 0xf16a7
+ in AL, DX ; ec ; 0xf16a8 bios.c:99
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf16a9
+ mov cx, ax ; 89 c1 ; 0xf16ab
+ test al, al ; 84 c0 ; 0xf16ad bios.c:100
+ je short 016c4h ; 74 13 ; 0xf16af
+ mov dx, 000a1h ; ba a1 00 ; 0xf16b1 bios.c:101
+ in AL, DX ; ec ; 0xf16b4
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf16b5
+ mov bl, cl ; 88 cb ; 0xf16b7 bios.c:102
+ or al, bl ; 08 d8 ; 0xf16b9
+ out DX, AL ; ee ; 0xf16bb
+ mov AL, strict byte 020h ; b0 20 ; 0xf16bc bios.c:103
+ mov dx, 000a0h ; ba a0 00 ; 0xf16be
+ out DX, AL ; ee ; 0xf16c1
+ jmp short 016d3h ; eb 0f ; 0xf16c2 bios.c:104
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf16c4 bios.c:105
+ in AL, DX ; ec ; 0xf16c7
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf16c8
+ and bl, 0fbh ; 80 e3 fb ; 0xf16ca bios.c:106
+ mov byte [bp-002h], bl ; 88 5e fe ; 0xf16cd
+ or al, bl ; 08 d8 ; 0xf16d0 bios.c:107
+ out DX, AL ; ee ; 0xf16d2
+ mov AL, strict byte 020h ; b0 20 ; 0xf16d3 bios.c:109
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf16d5
+ out DX, AL ; ee ; 0xf16d8
+ mov cl, byte [bp-002h] ; 8a 4e fe ; 0xf16d9 bios.c:110
+ mov bx, strict word 0006bh ; bb 6b 00 ; 0xf16dc bios.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf16df
+ mov es, ax ; 8e c0 ; 0xf16e2
+ mov byte [es:bx], cl ; 26 88 0f ; 0xf16e4
+ mov sp, bp ; 89 ec ; 0xf16e7 bios.c:113
+ pop bp ; 5d ; 0xf16e9
+ retn ; c3 ; 0xf16ea
+ ; disGetNextSymbol 0xf16eb LB 0x885d -> off=0x0 cb=0000000000000015 uValue=00000000000f00eb 'nmi_handler_msg'
+nmi_handler_msg: ; 0xf16eb LB 0x15
+ push bp ; 55 ; 0xf16eb bios.c:116
+ mov bp, sp ; 89 e5 ; 0xf16ec
+ mov ax, 000b0h ; b8 b0 00 ; 0xf16ee bios.c:118
+ push ax ; 50 ; 0xf16f1
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf16f2
+ push ax ; 50 ; 0xf16f5
+ call 0190fh ; e8 16 02 ; 0xf16f6
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf16f9
+ mov sp, bp ; 89 ec ; 0xf16fc bios.c:119
+ pop bp ; 5d ; 0xf16fe
+ retn ; c3 ; 0xf16ff
+ ; disGetNextSymbol 0xf1700 LB 0x8848 -> off=0x0 cb=0000000000000015 uValue=00000000000f0100 'int18_panic_msg'
+int18_panic_msg: ; 0xf1700 LB 0x15
+ push bp ; 55 ; 0xf1700 bios.c:121
+ mov bp, sp ; 89 e5 ; 0xf1701
+ mov ax, 000c4h ; b8 c4 00 ; 0xf1703 bios.c:123
+ push ax ; 50 ; 0xf1706
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf1707
+ push ax ; 50 ; 0xf170a
+ call 0190fh ; e8 01 02 ; 0xf170b
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf170e
+ mov sp, bp ; 89 ec ; 0xf1711 bios.c:124
+ pop bp ; 5d ; 0xf1713
+ retn ; c3 ; 0xf1714
+ ; disGetNextSymbol 0xf1715 LB 0x8833 -> off=0x0 cb=0000000000000024 uValue=00000000000f0115 'log_bios_start'
+log_bios_start: ; 0xf1715 LB 0x24
+ push bp ; 55 ; 0xf1715 bios.c:126
+ mov bp, sp ; 89 e5 ; 0xf1716
+ mov bx, 00da0h ; bb a0 0d ; 0xf1718 bios.c:131
+ mov cx, ds ; 8c d9 ; 0xf171b
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf171d
+ call 018cch ; e8 a9 01 ; 0xf1720
+ mov ax, 00d8eh ; b8 8e 0d ; 0xf1723
+ push ax ; 50 ; 0xf1726
+ mov ax, 000d9h ; b8 d9 00 ; 0xf1727
+ push ax ; 50 ; 0xf172a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf172b
+ push ax ; 50 ; 0xf172e
+ call 0190fh ; e8 dd 01 ; 0xf172f
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf1732
+ mov sp, bp ; 89 ec ; 0xf1735 bios.c:132
+ pop bp ; 5d ; 0xf1737
+ retn ; c3 ; 0xf1738
+ ; disGetNextSymbol 0xf1739 LB 0x880f -> off=0x0 cb=0000000000000027 uValue=00000000000f0139 'print_bios_banner'
+print_bios_banner: ; 0xf1739 LB 0x27
+ push bp ; 55 ; 0xf1739 bios.c:151
+ mov bp, sp ; 89 e5 ; 0xf173a
+ mov bx, strict word 00072h ; bb 72 00 ; 0xf173c bios.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf173f
+ mov es, ax ; 8e c0 ; 0xf1742
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf1744
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf1747 bios.c:53
+ cmp ax, 01234h ; 3d 34 12 ; 0xf174c bios.c:157
+ jne short 01759h ; 75 08 ; 0xf174f
+ mov AL, strict byte 003h ; b0 03 ; 0xf1751 bios.c:160
+ mov AH, strict byte 000h ; b4 00 ; 0xf1753
+ int 010h ; cd 10 ; 0xf1755
+ jmp short 0175ch ; eb 03 ; 0xf1757 bios.c:161
+ call 07657h ; e8 fb 5e ; 0xf1759 bios.c:164
+ mov sp, bp ; 89 ec ; 0xf175c bios.c:191
+ pop bp ; 5d ; 0xf175e
+ retn ; c3 ; 0xf175f
+ ; disGetNextSymbol 0xf1760 LB 0x87e8 -> off=0x0 cb=000000000000003b uValue=00000000000f0160 'send'
+send: ; 0xf1760 LB 0x3b
+ push bp ; 55 ; 0xf1760 print.c:72
+ mov bp, sp ; 89 e5 ; 0xf1761
+ push bx ; 53 ; 0xf1763
+ push cx ; 51 ; 0xf1764
+ mov bx, ax ; 89 c3 ; 0xf1765
+ mov cl, dl ; 88 d1 ; 0xf1767
+ test AL, strict byte 008h ; a8 08 ; 0xf1769 print.c:80
+ je short 01773h ; 74 06 ; 0xf176b
+ mov al, dl ; 88 d0 ; 0xf176d print.c:81
+ mov dx, 00403h ; ba 03 04 ; 0xf176f
+ out DX, AL ; ee ; 0xf1772
+ test bl, 004h ; f6 c3 04 ; 0xf1773 print.c:82
+ je short 0177eh ; 74 06 ; 0xf1776
+ mov al, cl ; 88 c8 ; 0xf1778 print.c:83
+ mov dx, 00504h ; ba 04 05 ; 0xf177a
+ out DX, AL ; ee ; 0xf177d
+ test bl, 002h ; f6 c3 02 ; 0xf177e print.c:85
+ je short 01794h ; 74 11 ; 0xf1781
+ cmp cl, 00ah ; 80 f9 0a ; 0xf1783 print.c:86
+ jne short 0178eh ; 75 06 ; 0xf1786
+ mov AL, strict byte 00dh ; b0 0d ; 0xf1788 print.c:87
+ mov AH, strict byte 00eh ; b4 0e ; 0xf178a
+ int 010h ; cd 10 ; 0xf178c
+ mov al, cl ; 88 c8 ; 0xf178e print.c:88
+ mov AH, strict byte 00eh ; b4 0e ; 0xf1790
+ int 010h ; cd 10 ; 0xf1792
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf1794 print.c:90
+ pop cx ; 59 ; 0xf1797
+ pop bx ; 5b ; 0xf1798
+ pop bp ; 5d ; 0xf1799
+ retn ; c3 ; 0xf179a
+ ; disGetNextSymbol 0xf179b LB 0x87ad -> off=0x0 cb=0000000000000063 uValue=00000000000f019b 'put_int'
+put_int: ; 0xf179b LB 0x63
+ push bp ; 55 ; 0xf179b print.c:92
+ mov bp, sp ; 89 e5 ; 0xf179c
+ push si ; 56 ; 0xf179e
+ push di ; 57 ; 0xf179f
+ push ax ; 50 ; 0xf17a0
+ push ax ; 50 ; 0xf17a1
+ mov si, ax ; 89 c6 ; 0xf17a2
+ mov word [bp-008h], dx ; 89 56 f8 ; 0xf17a4
+ mov di, bx ; 89 df ; 0xf17a7
+ mov bx, strict word 0000ah ; bb 0a 00 ; 0xf17a9 print.c:94
+ mov ax, dx ; 89 d0 ; 0xf17ac
+ cwd ; 99 ; 0xf17ae
+ idiv bx ; f7 fb ; 0xf17af
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf17b1
+ test ax, ax ; 85 c0 ; 0xf17b4 print.c:95
+ je short 017c4h ; 74 0c ; 0xf17b6
+ lea bx, [di-001h] ; 8d 5d ff ; 0xf17b8 print.c:96
+ mov dx, ax ; 89 c2 ; 0xf17bb
+ mov ax, si ; 89 f0 ; 0xf17bd
+ call 0179bh ; e8 d9 ff ; 0xf17bf
+ jmp short 017dfh ; eb 1b ; 0xf17c2 print.c:97
+ dec di ; 4f ; 0xf17c4 print.c:98
+ test di, di ; 85 ff ; 0xf17c5
+ jle short 017d3h ; 7e 0a ; 0xf17c7
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf17c9 print.c:99
+ mov ax, si ; 89 f0 ; 0xf17cc
+ call 01760h ; e8 8f ff ; 0xf17ce
+ jmp short 017c4h ; eb f1 ; 0xf17d1
+ test cx, cx ; 85 c9 ; 0xf17d3 print.c:100
+ je short 017dfh ; 74 08 ; 0xf17d5
+ mov dx, strict word 0002dh ; ba 2d 00 ; 0xf17d7 print.c:101
+ mov ax, si ; 89 f0 ; 0xf17da
+ call 01760h ; e8 81 ff ; 0xf17dc
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf17df print.c:103
+ mov BL, strict byte 00ah ; b3 0a ; 0xf17e2
+ mul bl ; f6 e3 ; 0xf17e4
+ mov bl, byte [bp-008h] ; 8a 5e f8 ; 0xf17e6
+ sub bl, al ; 28 c3 ; 0xf17e9
+ add bl, 030h ; 80 c3 30 ; 0xf17eb
+ xor bh, bh ; 30 ff ; 0xf17ee
+ mov dx, bx ; 89 da ; 0xf17f0
+ mov ax, si ; 89 f0 ; 0xf17f2
+ call 01760h ; e8 69 ff ; 0xf17f4
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf17f7 print.c:104
+ pop di ; 5f ; 0xf17fa
+ pop si ; 5e ; 0xf17fb
+ pop bp ; 5d ; 0xf17fc
+ retn ; c3 ; 0xf17fd
+ ; disGetNextSymbol 0xf17fe LB 0x874a -> off=0x0 cb=000000000000005e uValue=00000000000f01fe 'put_uint'
+put_uint: ; 0xf17fe LB 0x5e
+ push bp ; 55 ; 0xf17fe print.c:106
+ mov bp, sp ; 89 e5 ; 0xf17ff
+ push si ; 56 ; 0xf1801
+ push di ; 57 ; 0xf1802
+ push ax ; 50 ; 0xf1803
+ push ax ; 50 ; 0xf1804
+ mov si, ax ; 89 c6 ; 0xf1805
+ mov word [bp-008h], dx ; 89 56 f8 ; 0xf1807
+ mov ax, dx ; 89 d0 ; 0xf180a print.c:108
+ xor dx, dx ; 31 d2 ; 0xf180c
+ mov di, strict word 0000ah ; bf 0a 00 ; 0xf180e
+ div di ; f7 f7 ; 0xf1811
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf1813
+ test ax, ax ; 85 c0 ; 0xf1816 print.c:109
+ je short 01824h ; 74 0a ; 0xf1818
+ dec bx ; 4b ; 0xf181a print.c:110
+ mov dx, ax ; 89 c2 ; 0xf181b
+ mov ax, si ; 89 f0 ; 0xf181d
+ call 017feh ; e8 dc ff ; 0xf181f
+ jmp short 0183fh ; eb 1b ; 0xf1822 print.c:111
+ dec bx ; 4b ; 0xf1824 print.c:112
+ test bx, bx ; 85 db ; 0xf1825
+ jle short 01833h ; 7e 0a ; 0xf1827
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf1829 print.c:113
+ mov ax, si ; 89 f0 ; 0xf182c
+ call 01760h ; e8 2f ff ; 0xf182e
+ jmp short 01824h ; eb f1 ; 0xf1831
+ test cx, cx ; 85 c9 ; 0xf1833 print.c:114
+ je short 0183fh ; 74 08 ; 0xf1835
+ mov dx, strict word 0002dh ; ba 2d 00 ; 0xf1837 print.c:115
+ mov ax, si ; 89 f0 ; 0xf183a
+ call 01760h ; e8 21 ff ; 0xf183c
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf183f print.c:117
+ mov DL, strict byte 00ah ; b2 0a ; 0xf1842
+ mul dl ; f6 e2 ; 0xf1844
+ mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xf1846
+ sub dl, al ; 28 c2 ; 0xf1849
+ add dl, 030h ; 80 c2 30 ; 0xf184b
+ xor dh, dh ; 30 f6 ; 0xf184e
+ mov ax, si ; 89 f0 ; 0xf1850
+ call 01760h ; e8 0b ff ; 0xf1852
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf1855 print.c:118
+ pop di ; 5f ; 0xf1858
+ pop si ; 5e ; 0xf1859
+ pop bp ; 5d ; 0xf185a
+ retn ; c3 ; 0xf185b
+ ; disGetNextSymbol 0xf185c LB 0x86ec -> off=0x0 cb=0000000000000070 uValue=00000000000f025c 'put_luint'
+put_luint: ; 0xf185c LB 0x70
+ push bp ; 55 ; 0xf185c print.c:120
+ mov bp, sp ; 89 e5 ; 0xf185d
+ push si ; 56 ; 0xf185f
+ push di ; 57 ; 0xf1860
+ push ax ; 50 ; 0xf1861
+ push ax ; 50 ; 0xf1862
+ mov si, ax ; 89 c6 ; 0xf1863
+ mov word [bp-006h], bx ; 89 5e fa ; 0xf1865
+ mov di, dx ; 89 d7 ; 0xf1868
+ mov ax, bx ; 89 d8 ; 0xf186a print.c:122
+ mov dx, cx ; 89 ca ; 0xf186c
+ mov bx, strict word 0000ah ; bb 0a 00 ; 0xf186e
+ xor cx, cx ; 31 c9 ; 0xf1871
+ call 09be0h ; e8 6a 83 ; 0xf1873
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf1876
+ mov cx, dx ; 89 d1 ; 0xf1879
+ mov dx, ax ; 89 c2 ; 0xf187b print.c:123
+ or dx, cx ; 09 ca ; 0xf187d
+ je short 01890h ; 74 0f ; 0xf187f
+ push word [bp+004h] ; ff 76 04 ; 0xf1881 print.c:124
+ lea dx, [di-001h] ; 8d 55 ff ; 0xf1884
+ mov bx, ax ; 89 c3 ; 0xf1887
+ mov ax, si ; 89 f0 ; 0xf1889
+ call 0185ch ; e8 ce ff ; 0xf188b
+ jmp short 018adh ; eb 1d ; 0xf188e print.c:125
+ dec di ; 4f ; 0xf1890 print.c:126
+ test di, di ; 85 ff ; 0xf1891
+ jle short 0189fh ; 7e 0a ; 0xf1893
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf1895 print.c:127
+ mov ax, si ; 89 f0 ; 0xf1898
+ call 01760h ; e8 c3 fe ; 0xf189a
+ jmp short 01890h ; eb f1 ; 0xf189d
+ cmp word [bp+004h], strict byte 00000h ; 83 7e 04 00 ; 0xf189f print.c:128
+ je short 018adh ; 74 08 ; 0xf18a3
+ mov dx, strict word 0002dh ; ba 2d 00 ; 0xf18a5 print.c:129
+ mov ax, si ; 89 f0 ; 0xf18a8
+ call 01760h ; e8 b3 fe ; 0xf18aa
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf18ad print.c:131
+ mov DL, strict byte 00ah ; b2 0a ; 0xf18b0
+ mul dl ; f6 e2 ; 0xf18b2
+ mov dl, byte [bp-006h] ; 8a 56 fa ; 0xf18b4
+ sub dl, al ; 28 c2 ; 0xf18b7
+ add dl, 030h ; 80 c2 30 ; 0xf18b9
+ xor dh, dh ; 30 f6 ; 0xf18bc
+ mov ax, si ; 89 f0 ; 0xf18be
+ call 01760h ; e8 9d fe ; 0xf18c0
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf18c3 print.c:132
+ pop di ; 5f ; 0xf18c6
+ pop si ; 5e ; 0xf18c7
+ pop bp ; 5d ; 0xf18c8
+ retn 00002h ; c2 02 00 ; 0xf18c9
+ ; disGetNextSymbol 0xf18cc LB 0x867c -> off=0x0 cb=0000000000000021 uValue=00000000000f02cc 'put_str'
+put_str: ; 0xf18cc LB 0x21
+ push bp ; 55 ; 0xf18cc print.c:134
+ mov bp, sp ; 89 e5 ; 0xf18cd
+ push dx ; 52 ; 0xf18cf
+ push si ; 56 ; 0xf18d0
+ mov si, ax ; 89 c6 ; 0xf18d1
+ mov es, cx ; 8e c1 ; 0xf18d3 print.c:138
+ mov dl, byte [es:bx] ; 26 8a 17 ; 0xf18d5
+ test dl, dl ; 84 d2 ; 0xf18d8
+ je short 018e6h ; 74 0a ; 0xf18da
+ xor dh, dh ; 30 f6 ; 0xf18dc print.c:139
+ mov ax, si ; 89 f0 ; 0xf18de
+ call 01760h ; e8 7d fe ; 0xf18e0
+ inc bx ; 43 ; 0xf18e3 print.c:140
+ jmp short 018d3h ; eb ed ; 0xf18e4 print.c:141
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf18e6 print.c:142
+ pop si ; 5e ; 0xf18e9
+ pop dx ; 5a ; 0xf18ea
+ pop bp ; 5d ; 0xf18eb
+ retn ; c3 ; 0xf18ec
+ ; disGetNextSymbol 0xf18ed LB 0x865b -> off=0x0 cb=0000000000000022 uValue=00000000000f02ed 'put_str_near'
+put_str_near: ; 0xf18ed LB 0x22
+ push bp ; 55 ; 0xf18ed print.c:144
+ mov bp, sp ; 89 e5 ; 0xf18ee
+ push bx ; 53 ; 0xf18f0
+ push cx ; 51 ; 0xf18f1
+ mov cx, ax ; 89 c1 ; 0xf18f2
+ mov bx, dx ; 89 d3 ; 0xf18f4
+ mov al, byte [bx] ; 8a 07 ; 0xf18f6 print.c:148
+ test al, al ; 84 c0 ; 0xf18f8
+ je short 01908h ; 74 0c ; 0xf18fa
+ xor ah, ah ; 30 e4 ; 0xf18fc print.c:149
+ mov dx, ax ; 89 c2 ; 0xf18fe
+ mov ax, cx ; 89 c8 ; 0xf1900
+ call 01760h ; e8 5b fe ; 0xf1902
+ inc bx ; 43 ; 0xf1905 print.c:150
+ jmp short 018f6h ; eb ee ; 0xf1906 print.c:151
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf1908 print.c:152
+ pop cx ; 59 ; 0xf190b
+ pop bx ; 5b ; 0xf190c
+ pop bp ; 5d ; 0xf190d
+ retn ; c3 ; 0xf190e
+ ; disGetNextSymbol 0xf190f LB 0x8639 -> off=0x0 cb=000000000000034f uValue=00000000000f030f 'bios_printf'
+bios_printf: ; 0xf190f LB 0x34f
+ push bp ; 55 ; 0xf190f print.c:165
+ mov bp, sp ; 89 e5 ; 0xf1910
+ push bx ; 53 ; 0xf1912
+ push cx ; 51 ; 0xf1913
+ push dx ; 52 ; 0xf1914
+ push si ; 56 ; 0xf1915
+ push di ; 57 ; 0xf1916
+ sub sp, strict byte 0001ch ; 83 ec 1c ; 0xf1917
+ lea bx, [bp+008h] ; 8d 5e 08 ; 0xf191a print.c:173
+ mov word [bp-016h], bx ; 89 5e ea ; 0xf191d
+ mov [bp-014h], ss ; 8c 56 ec ; 0xf1920
+ xor cx, cx ; 31 c9 ; 0xf1923 print.c:175
+ xor di, di ; 31 ff ; 0xf1925 print.c:176
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1927 print.c:178
+ and ax, strict word 00007h ; 25 07 00 ; 0xf192a
+ cmp ax, strict word 00007h ; 3d 07 00 ; 0xf192d
+ jne short 01940h ; 75 0e ; 0xf1930
+ mov ax, 000deh ; b8 de 00 ; 0xf1932 print.c:179
+ push ax ; 50 ; 0xf1935
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf1936
+ push ax ; 50 ; 0xf1939
+ call 0190fh ; e8 d2 ff ; 0xf193a
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf193d
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf1940 print.c:182
+ mov dl, byte [bx] ; 8a 17 ; 0xf1943
+ test dl, dl ; 84 d2 ; 0xf1945
+ je short 019aah ; 74 61 ; 0xf1947
+ cmp dl, 025h ; 80 fa 25 ; 0xf1949 print.c:183
+ jne short 01956h ; 75 08 ; 0xf194c
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf194e print.c:184
+ xor di, di ; 31 ff ; 0xf1951 print.c:185
+ jmp near 01c3ch ; e9 e6 02 ; 0xf1953 print.c:187
+ test cx, cx ; 85 c9 ; 0xf1956
+ je short 019adh ; 74 53 ; 0xf1958
+ cmp dl, 030h ; 80 fa 30 ; 0xf195a print.c:188
+ jc short 01979h ; 72 1a ; 0xf195d
+ cmp dl, 039h ; 80 fa 39 ; 0xf195f
+ jnbe short 01979h ; 77 15 ; 0xf1962
+ mov bl, dl ; 88 d3 ; 0xf1964 print.c:189
+ xor bh, bh ; 30 ff ; 0xf1966
+ mov ax, di ; 89 f8 ; 0xf1968
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf196a
+ mul dx ; f7 e2 ; 0xf196d
+ sub bx, strict byte 00030h ; 83 eb 30 ; 0xf196f
+ mov di, ax ; 89 c7 ; 0xf1972
+ add di, bx ; 01 df ; 0xf1974
+ jmp near 01c3ch ; e9 c3 02 ; 0xf1976 print.c:191
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1979 print.c:192
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf197c
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf197f
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1983
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1986
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf198a
+ cmp dl, 078h ; 80 fa 78 ; 0xf198d print.c:193
+ je short 01997h ; 74 05 ; 0xf1990
+ cmp dl, 058h ; 80 fa 58 ; 0xf1992
+ jne short 019f2h ; 75 5b ; 0xf1995
+ test di, di ; 85 ff ; 0xf1997 print.c:194
+ jne short 0199eh ; 75 03 ; 0xf1999
+ mov di, strict word 00004h ; bf 04 00 ; 0xf199b print.c:195
+ cmp dl, 078h ; 80 fa 78 ; 0xf199e print.c:196
+ jne short 019b0h ; 75 0d ; 0xf19a1
+ mov word [bp-00eh], strict word 00061h ; c7 46 f2 61 00 ; 0xf19a3 print.c:197
+ jmp short 019b5h ; eb 0b ; 0xf19a8 print.c:198
+ jmp near 01c42h ; e9 95 02 ; 0xf19aa
+ jmp near 01c34h ; e9 84 02 ; 0xf19ad
+ mov word [bp-00eh], strict word 00041h ; c7 46 f2 41 00 ; 0xf19b0 print.c:199
+ lea ax, [di-001h] ; 8d 45 ff ; 0xf19b5 print.c:200
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf19b8
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf19bb
+ test ax, ax ; 85 c0 ; 0xf19be
+ jl short 01a03h ; 7c 41 ; 0xf19c0
+ mov cx, ax ; 89 c1 ; 0xf19c2 print.c:201
+ sal cx, 1 ; d1 e1 ; 0xf19c4
+ sal cx, 1 ; d1 e1 ; 0xf19c6
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf19c8
+ shr ax, CL ; d3 e8 ; 0xf19cb
+ xor ah, ah ; 30 e4 ; 0xf19cd
+ and AL, strict byte 00fh ; 24 0f ; 0xf19cf
+ cmp ax, strict word 00009h ; 3d 09 00 ; 0xf19d1 print.c:202
+ jnbe short 019ddh ; 77 07 ; 0xf19d4
+ mov dx, ax ; 89 c2 ; 0xf19d6
+ add dx, strict byte 00030h ; 83 c2 30 ; 0xf19d8
+ jmp short 019e5h ; eb 08 ; 0xf19db
+ sub ax, strict word 0000ah ; 2d 0a 00 ; 0xf19dd
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf19e0
+ add dx, ax ; 01 c2 ; 0xf19e3
+ xor dh, dh ; 30 f6 ; 0xf19e5
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf19e7
+ call 01760h ; e8 73 fd ; 0xf19ea
+ dec word [bp-012h] ; ff 4e ee ; 0xf19ed print.c:203
+ jmp short 019bbh ; eb c9 ; 0xf19f0
+ cmp dl, 075h ; 80 fa 75 ; 0xf19f2 print.c:205
+ jne short 01a06h ; 75 0f ; 0xf19f5
+ xor cx, cx ; 31 c9 ; 0xf19f7 print.c:206
+ mov bx, di ; 89 fb ; 0xf19f9
+ mov dx, ax ; 89 c2 ; 0xf19fb
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf19fd
+ call 017feh ; e8 fb fd ; 0xf1a00
+ jmp near 01c30h ; e9 2a 02 ; 0xf1a03 print.c:208
+ cmp dl, 06ch ; 80 fa 6c ; 0xf1a06
+ jne short 01a13h ; 75 08 ; 0xf1a09
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf1a0b
+ cmp dl, byte [bx+001h] ; 3a 57 01 ; 0xf1a0e
+ je short 01a16h ; 74 03 ; 0xf1a11
+ jmp near 01aebh ; e9 d5 00 ; 0xf1a13
+ add word [bp+006h], strict byte 00002h ; 83 46 06 02 ; 0xf1a16 print.c:212
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf1a1a print.c:213
+ mov dl, byte [bx] ; 8a 17 ; 0xf1a1d
+ mov word [bp-026h], ax ; 89 46 da ; 0xf1a1f print.c:215
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1a22 print.c:216
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1a25
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1a28
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1a2c
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1a2f
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf1a33
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1a36 print.c:217
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1a39
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1a3c
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1a40
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1a43
+ mov word [bp-022h], ax ; 89 46 de ; 0xf1a47
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1a4a print.c:218
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1a4d
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1a50
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1a54
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1a57
+ mov word [bp-020h], ax ; 89 46 e0 ; 0xf1a5b
+ cmp dl, 078h ; 80 fa 78 ; 0xf1a5e print.c:219
+ je short 01a68h ; 74 05 ; 0xf1a61
+ cmp dl, 058h ; 80 fa 58 ; 0xf1a63
+ jne short 01ac3h ; 75 5b ; 0xf1a66
+ test di, di ; 85 ff ; 0xf1a68 print.c:220
+ jne short 01a6fh ; 75 03 ; 0xf1a6a
+ mov di, strict word 00010h ; bf 10 00 ; 0xf1a6c print.c:221
+ cmp dl, 078h ; 80 fa 78 ; 0xf1a6f print.c:222
+ jne short 01a7bh ; 75 07 ; 0xf1a72
+ mov word [bp-00eh], strict word 00061h ; c7 46 f2 61 00 ; 0xf1a74 print.c:223
+ jmp short 01a80h ; eb 05 ; 0xf1a79 print.c:224
+ mov word [bp-00eh], strict word 00041h ; c7 46 f2 41 00 ; 0xf1a7b print.c:225
+ lea ax, [di-001h] ; 8d 45 ff ; 0xf1a80 print.c:226
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf1a83
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf1a86
+ test ax, ax ; 85 c0 ; 0xf1a89
+ jl short 01ae8h ; 7c 5b ; 0xf1a8b
+ sal ax, 1 ; d1 e0 ; 0xf1a8d print.c:227
+ sal ax, 1 ; d1 e0 ; 0xf1a8f
+ mov word [bp-01eh], ax ; 89 46 e2 ; 0xf1a91
+ xor ax, ax ; 31 c0 ; 0xf1a94
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf1a96
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf1a99
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf1a9c
+ mov ax, word [bp-020h] ; 8b 46 e0 ; 0xf1a9f
+ mov bx, word [bp-022h] ; 8b 5e de ; 0xf1aa2
+ mov cx, word [bp-024h] ; 8b 4e dc ; 0xf1aa5
+ mov dx, word [bp-026h] ; 8b 56 da ; 0xf1aa8
+ mov si, word [bp-01eh] ; 8b 76 e2 ; 0xf1aab
+ call 09c10h ; e8 5f 81 ; 0xf1aae
+ mov ax, dx ; 89 d0 ; 0xf1ab1
+ xor ah, dh ; 30 f4 ; 0xf1ab3
+ and AL, strict byte 00fh ; 24 0f ; 0xf1ab5
+ cmp ax, strict word 00009h ; 3d 09 00 ; 0xf1ab7 print.c:228
+ jnbe short 01ac5h ; 77 09 ; 0xf1aba
+ mov dx, ax ; 89 c2 ; 0xf1abc
+ add dx, strict byte 00030h ; 83 c2 30 ; 0xf1abe
+ jmp short 01acdh ; eb 0a ; 0xf1ac1
+ jmp short 01adah ; eb 15 ; 0xf1ac3
+ sub ax, strict word 0000ah ; 2d 0a 00 ; 0xf1ac5
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf1ac8
+ add dx, ax ; 01 c2 ; 0xf1acb
+ xor dh, dh ; 30 f6 ; 0xf1acd
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1acf
+ call 01760h ; e8 8b fc ; 0xf1ad2
+ dec word [bp-012h] ; ff 4e ee ; 0xf1ad5 print.c:229
+ jmp short 01a86h ; eb ac ; 0xf1ad8
+ mov ax, 000e6h ; b8 e6 00 ; 0xf1ada print.c:231
+ push ax ; 50 ; 0xf1add
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf1ade
+ push ax ; 50 ; 0xf1ae1
+ call 0190fh ; e8 2a fe ; 0xf1ae2
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf1ae5
+ jmp near 01c30h ; e9 45 01 ; 0xf1ae8 print.c:234
+ lea bx, [di-001h] ; 8d 5d ff ; 0xf1aeb
+ cmp dl, 06ch ; 80 fa 6c ; 0xf1aee
+ jne short 01b4bh ; 75 58 ; 0xf1af1
+ inc word [bp+006h] ; ff 46 06 ; 0xf1af3 print.c:235
+ mov si, word [bp+006h] ; 8b 76 06 ; 0xf1af6 print.c:236
+ mov dl, byte [si] ; 8a 14 ; 0xf1af9
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1afb print.c:237
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1afe
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1b01
+ les si, [bp-016h] ; c4 76 ea ; 0xf1b05
+ mov ax, word [es:si-002h] ; 26 8b 44 fe ; 0xf1b08
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf1b0c
+ cmp dl, 064h ; 80 fa 64 ; 0xf1b0f print.c:238
+ jne short 01b44h ; 75 30 ; 0xf1b12
+ test byte [bp-00fh], 080h ; f6 46 f1 80 ; 0xf1b14 print.c:239
+ je short 01b31h ; 74 17 ; 0xf1b18
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf1b1a print.c:240
+ push ax ; 50 ; 0xf1b1d
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf1b1e
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf1b21
+ neg cx ; f7 d9 ; 0xf1b24
+ neg ax ; f7 d8 ; 0xf1b26
+ sbb cx, strict byte 00000h ; 83 d9 00 ; 0xf1b28
+ mov dx, bx ; 89 da ; 0xf1b2b
+ mov bx, ax ; 89 c3 ; 0xf1b2d
+ jmp short 01b3ch ; eb 0b ; 0xf1b2f print.c:241
+ xor ax, ax ; 31 c0 ; 0xf1b31 print.c:242
+ push ax ; 50 ; 0xf1b33
+ mov bx, word [bp-00ch] ; 8b 5e f4 ; 0xf1b34
+ mov dx, di ; 89 fa ; 0xf1b37
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf1b39
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1b3c
+ call 0185ch ; e8 1a fd ; 0xf1b3f
+ jmp short 01ae8h ; eb a4 ; 0xf1b42 print.c:244
+ cmp dl, 075h ; 80 fa 75 ; 0xf1b44
+ jne short 01b4dh ; 75 04 ; 0xf1b47
+ jmp short 01b31h ; eb e6 ; 0xf1b49
+ jmp short 01bb4h ; eb 67 ; 0xf1b4b
+ cmp dl, 078h ; 80 fa 78 ; 0xf1b4d print.c:247
+ je short 01b57h ; 74 05 ; 0xf1b50
+ cmp dl, 058h ; 80 fa 58 ; 0xf1b52
+ jne short 01ae8h ; 75 91 ; 0xf1b55
+ test di, di ; 85 ff ; 0xf1b57 print.c:249
+ jne short 01b5eh ; 75 03 ; 0xf1b59
+ mov di, strict word 00008h ; bf 08 00 ; 0xf1b5b print.c:250
+ cmp dl, 078h ; 80 fa 78 ; 0xf1b5e print.c:251
+ jne short 01b6ah ; 75 07 ; 0xf1b61
+ mov word [bp-00eh], strict word 00061h ; c7 46 f2 61 00 ; 0xf1b63 print.c:252
+ jmp short 01b6fh ; eb 05 ; 0xf1b68 print.c:253
+ mov word [bp-00eh], strict word 00041h ; c7 46 f2 41 00 ; 0xf1b6a print.c:254
+ lea ax, [di-001h] ; 8d 45 ff ; 0xf1b6f print.c:255
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf1b72
+ cmp word [bp-012h], strict byte 00000h ; 83 7e ee 00 ; 0xf1b75
+ jl short 01bd6h ; 7c 5b ; 0xf1b79
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf1b7b print.c:256
+ mov cx, word [bp-012h] ; 8b 4e ee ; 0xf1b7e
+ sal cx, 1 ; d1 e1 ; 0xf1b81
+ sal cx, 1 ; d1 e1 ; 0xf1b83
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf1b85
+ jcxz 01b90h ; e3 06 ; 0xf1b88
+ shr dx, 1 ; d1 ea ; 0xf1b8a
+ rcr ax, 1 ; d1 d8 ; 0xf1b8c
+ loop 01b8ah ; e2 fa ; 0xf1b8e
+ and ax, strict word 0000fh ; 25 0f 00 ; 0xf1b90
+ cmp ax, strict word 00009h ; 3d 09 00 ; 0xf1b93 print.c:257
+ jnbe short 01b9fh ; 77 07 ; 0xf1b96
+ mov dx, ax ; 89 c2 ; 0xf1b98
+ add dx, strict byte 00030h ; 83 c2 30 ; 0xf1b9a
+ jmp short 01ba7h ; eb 08 ; 0xf1b9d
+ sub ax, strict word 0000ah ; 2d 0a 00 ; 0xf1b9f
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf1ba2
+ add dx, ax ; 01 c2 ; 0xf1ba5
+ xor dh, dh ; 30 f6 ; 0xf1ba7
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1ba9
+ call 01760h ; e8 b1 fb ; 0xf1bac
+ dec word [bp-012h] ; ff 4e ee ; 0xf1baf print.c:258
+ jmp short 01b75h ; eb c1 ; 0xf1bb2
+ cmp dl, 064h ; 80 fa 64 ; 0xf1bb4 print.c:261
+ jne short 01bd8h ; 75 1f ; 0xf1bb7
+ test byte [bp-00bh], 080h ; f6 46 f5 80 ; 0xf1bb9 print.c:262
+ je short 01bc9h ; 74 0a ; 0xf1bbd
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf1bbf print.c:263
+ neg dx ; f7 da ; 0xf1bc2
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf1bc4
+ jmp short 01bd0h ; eb 07 ; 0xf1bc7 print.c:264
+ xor cx, cx ; 31 c9 ; 0xf1bc9 print.c:265
+ mov bx, di ; 89 fb ; 0xf1bcb
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf1bcd
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1bd0
+ call 0179bh ; e8 c5 fb ; 0xf1bd3
+ jmp short 01c30h ; eb 58 ; 0xf1bd6 print.c:267
+ cmp dl, 073h ; 80 fa 73 ; 0xf1bd8
+ jne short 01beah ; 75 0d ; 0xf1bdb
+ mov cx, ds ; 8c d9 ; 0xf1bdd print.c:268
+ mov bx, word [bp-00ch] ; 8b 5e f4 ; 0xf1bdf
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1be2
+ call 018cch ; e8 e4 fc ; 0xf1be5
+ jmp short 01c30h ; eb 46 ; 0xf1be8 print.c:270
+ cmp dl, 053h ; 80 fa 53 ; 0xf1bea
+ jne short 01c10h ; 75 21 ; 0xf1bed
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf1bef print.c:271
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf1bf2
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf1bf5 print.c:272
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1bf8
+ add word [bp-016h], strict byte 00002h ; 83 46 ea 02 ; 0xf1bfb
+ les bx, [bp-016h] ; c4 5e ea ; 0xf1bff
+ mov ax, word [es:bx-002h] ; 26 8b 47 fe ; 0xf1c02
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf1c06
+ mov bx, ax ; 89 c3 ; 0xf1c09 print.c:273
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf1c0b
+ jmp short 01be2h ; eb d2 ; 0xf1c0e
+ cmp dl, 063h ; 80 fa 63 ; 0xf1c10 print.c:275
+ jne short 01c22h ; 75 0d ; 0xf1c13
+ mov dl, byte [bp-00ch] ; 8a 56 f4 ; 0xf1c15 print.c:276
+ xor dh, dh ; 30 f6 ; 0xf1c18
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1c1a
+ call 01760h ; e8 40 fb ; 0xf1c1d
+ jmp short 01c30h ; eb 0e ; 0xf1c20 print.c:278
+ mov ax, 00107h ; b8 07 01 ; 0xf1c22 print.c:279
+ push ax ; 50 ; 0xf1c25
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf1c26
+ push ax ; 50 ; 0xf1c29
+ call 0190fh ; e8 e2 fc ; 0xf1c2a
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf1c2d
+ xor cx, cx ; 31 c9 ; 0xf1c30 print.c:280
+ jmp short 01c3ch ; eb 08 ; 0xf1c32 print.c:283
+ xor dh, dh ; 30 f6 ; 0xf1c34 print.c:284
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf1c36
+ call 01760h ; e8 24 fb ; 0xf1c39
+ inc word [bp+006h] ; ff 46 06 ; 0xf1c3c print.c:286
+ jmp near 01940h ; e9 fe fc ; 0xf1c3f print.c:287
+ xor ax, ax ; 31 c0 ; 0xf1c42 print.c:288
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf1c44
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf1c47
+ test byte [bp+004h], 001h ; f6 46 04 01 ; 0xf1c4a print.c:289
+ je short 01c54h ; 74 04 ; 0xf1c4e
+ cli ; fa ; 0xf1c50 print.c:291
+ hlt ; f4 ; 0xf1c51 print.c:292
+ jmp short 01c51h ; eb fd ; 0xf1c52
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf1c54 print.c:294
+ pop di ; 5f ; 0xf1c57
+ pop si ; 5e ; 0xf1c58
+ pop dx ; 5a ; 0xf1c59
+ pop cx ; 59 ; 0xf1c5a
+ pop bx ; 5b ; 0xf1c5b
+ pop bp ; 5d ; 0xf1c5c
+ retn ; c3 ; 0xf1c5d
+ ; disGetNextSymbol 0xf1c5e LB 0x82ea -> off=0x0 cb=00000000000000f0 uValue=00000000000f065e 'ata_init'
+ata_init: ; 0xf1c5e LB 0xf0
+ push si ; 56 ; 0xf1c5e ata.c:97
+ push di ; 57 ; 0xf1c5f
+ push bp ; 55 ; 0xf1c60
+ mov bp, sp ; 89 e5 ; 0xf1c61
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf1c63 ata.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf1c66
+ mov es, ax ; 8e c0 ; 0xf1c69
+ mov di, word [es:bx] ; 26 8b 3f ; 0xf1c6b
+ mov si, 00122h ; be 22 01 ; 0xf1c6e ata.c:49
+ xor cl, cl ; 30 c9 ; 0xf1c71 ata.c:105
+ jmp short 01c7ah ; eb 05 ; 0xf1c73
+ cmp cl, 004h ; 80 f9 04 ; 0xf1c75
+ jnc short 01ca7h ; 73 2d ; 0xf1c78
+ mov al, cl ; 88 c8 ; 0xf1c7a ata.c:106
+ xor ah, ah ; 30 e4 ; 0xf1c7c
+ mov bx, strict word 00006h ; bb 06 00 ; 0xf1c7e
+ imul bx ; f7 eb ; 0xf1c81
+ mov es, di ; 8e c7 ; 0xf1c83
+ mov bx, si ; 89 f3 ; 0xf1c85
+ add bx, ax ; 01 c3 ; 0xf1c87
+ mov byte [es:bx+00204h], 000h ; 26 c6 87 04 02 00 ; 0xf1c89
+ mov word [es:bx+00206h], strict word 00000h ; 26 c7 87 06 02 00 00 ; 0xf1c8f ata.c:107
+ mov word [es:bx+00208h], strict word 00000h ; 26 c7 87 08 02 00 00 ; 0xf1c96 ata.c:108
+ mov byte [es:bx+00205h], 000h ; 26 c6 87 05 02 00 ; 0xf1c9d ata.c:109
+ db 0feh, 0c1h
+ ; inc cl ; fe c1 ; 0xf1ca3 ata.c:110
+ jmp short 01c75h ; eb ce ; 0xf1ca5
+ xor cl, cl ; 30 c9 ; 0xf1ca7 ata.c:113
+ jmp short 01cb0h ; eb 05 ; 0xf1ca9
+ cmp cl, 008h ; 80 f9 08 ; 0xf1cab
+ jnc short 01d1bh ; 73 6b ; 0xf1cae
+ mov al, cl ; 88 c8 ; 0xf1cb0 ata.c:114
+ xor ah, ah ; 30 e4 ; 0xf1cb2
+ mov bx, strict word 0001ch ; bb 1c 00 ; 0xf1cb4
+ imul bx ; f7 eb ; 0xf1cb7
+ mov es, di ; 8e c7 ; 0xf1cb9
+ mov bx, si ; 89 f3 ; 0xf1cbb
+ add bx, ax ; 01 c3 ; 0xf1cbd
+ mov word [es:bx+022h], strict word 00000h ; 26 c7 47 22 00 00 ; 0xf1cbf
+ mov word [es:bx+024h], strict word 00000h ; 26 c7 47 24 00 00 ; 0xf1cc5 ata.c:116
+ mov byte [es:bx+026h], 000h ; 26 c6 47 26 00 ; 0xf1ccb ata.c:118
+ mov word [es:bx+028h], 00200h ; 26 c7 47 28 00 02 ; 0xf1cd0 ata.c:119
+ mov byte [es:bx+027h], 000h ; 26 c6 47 27 00 ; 0xf1cd6 ata.c:120
+ mov word [es:bx+02ah], strict word 00000h ; 26 c7 47 2a 00 00 ; 0xf1cdb ata.c:121
+ mov word [es:bx+02ch], strict word 00000h ; 26 c7 47 2c 00 00 ; 0xf1ce1 ata.c:122
+ mov word [es:bx+02eh], strict word 00000h ; 26 c7 47 2e 00 00 ; 0xf1ce7 ata.c:123
+ mov word [es:bx+030h], strict word 00000h ; 26 c7 47 30 00 00 ; 0xf1ced ata.c:124
+ mov word [es:bx+032h], strict word 00000h ; 26 c7 47 32 00 00 ; 0xf1cf3 ata.c:125
+ mov word [es:bx+034h], strict word 00000h ; 26 c7 47 34 00 00 ; 0xf1cf9 ata.c:126
+ mov word [es:bx+03ch], strict word 00000h ; 26 c7 47 3c 00 00 ; 0xf1cff ata.c:127
+ mov word [es:bx+03ah], strict word 00000h ; 26 c7 47 3a 00 00 ; 0xf1d05
+ mov word [es:bx+038h], strict word 00000h ; 26 c7 47 38 00 00 ; 0xf1d0b
+ mov word [es:bx+036h], strict word 00000h ; 26 c7 47 36 00 00 ; 0xf1d11
+ db 0feh, 0c1h
+ ; inc cl ; fe c1 ; 0xf1d17 ata.c:128
+ jmp short 01cabh ; eb 90 ; 0xf1d19
+ xor cl, cl ; 30 c9 ; 0xf1d1b ata.c:131
+ jmp short 01d24h ; eb 05 ; 0xf1d1d
+ cmp cl, 010h ; 80 f9 10 ; 0xf1d1f
+ jnc short 01d3ch ; 73 18 ; 0xf1d22
+ mov bl, cl ; 88 cb ; 0xf1d24 ata.c:132
+ xor bh, bh ; 30 ff ; 0xf1d26
+ mov es, di ; 8e c7 ; 0xf1d28
+ add bx, si ; 01 f3 ; 0xf1d2a
+ mov byte [es:bx+001e3h], 010h ; 26 c6 87 e3 01 10 ; 0xf1d2c
+ mov byte [es:bx+001f4h], 010h ; 26 c6 87 f4 01 10 ; 0xf1d32 ata.c:133
+ db 0feh, 0c1h
+ ; inc cl ; fe c1 ; 0xf1d38 ata.c:134
+ jmp short 01d1fh ; eb e3 ; 0xf1d3a
+ mov es, di ; 8e c7 ; 0xf1d3c ata.c:136
+ mov byte [es:si+001e2h], 000h ; 26 c6 84 e2 01 00 ; 0xf1d3e
+ mov byte [es:si+001f3h], 000h ; 26 c6 84 f3 01 00 ; 0xf1d44 ata.c:137
+ pop bp ; 5d ; 0xf1d4a ata.c:138
+ pop di ; 5f ; 0xf1d4b
+ pop si ; 5e ; 0xf1d4c
+ retn ; c3 ; 0xf1d4d
+ ; disGetNextSymbol 0xf1d4e LB 0x81fa -> off=0x0 cb=00000000000000ea uValue=00000000000f074e 'ata_reset'
+ata_reset: ; 0xf1d4e LB 0xea
+ push bp ; 55 ; 0xf1d4e ata.c:146
+ mov bp, sp ; 89 e5 ; 0xf1d4f
+ push bx ; 53 ; 0xf1d51
+ push cx ; 51 ; 0xf1d52
+ push dx ; 52 ; 0xf1d53
+ push si ; 56 ; 0xf1d54
+ push di ; 57 ; 0xf1d55
+ push ax ; 50 ; 0xf1d56
+ push ax ; 50 ; 0xf1d57
+ push ax ; 50 ; 0xf1d58
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf1d59 ata.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf1d5c
+ mov es, ax ; 8e c0 ; 0xf1d5f
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf1d61
+ mov word [bp-00eh], 00122h ; c7 46 f2 22 01 ; 0xf1d64 ata.c:49
+ mov di, bx ; 89 df ; 0xf1d69
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf1d6b ata.c:155
+ shr ax, 1 ; d1 e8 ; 0xf1d6e
+ mov ah, byte [bp-010h] ; 8a 66 f0 ; 0xf1d70 ata.c:156
+ and ah, 001h ; 80 e4 01 ; 0xf1d73
+ mov byte [bp-00ch], ah ; 88 66 f4 ; 0xf1d76
+ xor ah, ah ; 30 e4 ; 0xf1d79 ata.c:158
+ mov dx, strict word 00006h ; ba 06 00 ; 0xf1d7b
+ imul dx ; f7 ea ; 0xf1d7e
+ mov es, bx ; 8e c3 ; 0xf1d80
+ mov bx, ax ; 89 c3 ; 0xf1d82
+ add bx, 00122h ; 81 c3 22 01 ; 0xf1d84
+ mov cx, word [es:bx+00206h] ; 26 8b 8f 06 02 ; 0xf1d88
+ mov si, word [es:bx+00208h] ; 26 8b b7 08 02 ; 0xf1d8d ata.c:159
+ lea dx, [si+006h] ; 8d 54 06 ; 0xf1d92 ata.c:164
+ mov AL, strict byte 00eh ; b0 0e ; 0xf1d95
+ out DX, AL ; ee ; 0xf1d97
+ mov bx, 000ffh ; bb ff 00 ; 0xf1d98 ata.c:167
+ dec bx ; 4b ; 0xf1d9b ata.c:168
+ test bx, bx ; 85 db ; 0xf1d9c
+ jbe short 01dach ; 76 0c ; 0xf1d9e
+ mov dx, cx ; 89 ca ; 0xf1da0 ata.c:169
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1da2
+ in AL, DX ; ec ; 0xf1da5
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1da6
+ test AL, strict byte 080h ; a8 80 ; 0xf1da8 ata.c:170
+ je short 01d9bh ; 74 ef ; 0xf1daa
+ lea dx, [si+006h] ; 8d 54 06 ; 0xf1dac ata.c:175
+ mov AL, strict byte 00ah ; b0 0a ; 0xf1daf
+ out DX, AL ; ee ; 0xf1db1
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf1db2 ata.c:177
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf1db5
+ imul dx ; f7 ea ; 0xf1db8
+ mov es, di ; 8e c7 ; 0xf1dba
+ mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xf1dbc
+ add bx, ax ; 01 c3 ; 0xf1dbf
+ cmp byte [es:bx+022h], 000h ; 26 80 7f 22 00 ; 0xf1dc1
+ je short 01e14h ; 74 4c ; 0xf1dc6
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf1dc8 ata.c:180
+ je short 01dd3h ; 74 05 ; 0xf1dcc
+ mov ax, 000b0h ; b8 b0 00 ; 0xf1dce
+ jmp short 01dd6h ; eb 03 ; 0xf1dd1
+ mov ax, 000a0h ; b8 a0 00 ; 0xf1dd3
+ mov dx, cx ; 89 ca ; 0xf1dd6
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf1dd8
+ out DX, AL ; ee ; 0xf1ddb
+ mov dx, cx ; 89 ca ; 0xf1ddc ata.c:181
+ inc dx ; 42 ; 0xf1dde
+ inc dx ; 42 ; 0xf1ddf
+ in AL, DX ; ec ; 0xf1de0
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1de1
+ mov bx, ax ; 89 c3 ; 0xf1de3
+ mov dx, cx ; 89 ca ; 0xf1de5 ata.c:182
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf1de7
+ in AL, DX ; ec ; 0xf1dea
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1deb
+ cmp bl, 001h ; 80 fb 01 ; 0xf1ded ata.c:184
+ jne short 01e14h ; 75 22 ; 0xf1df0
+ cmp al, bl ; 38 d8 ; 0xf1df2
+ jne short 01e14h ; 75 1e ; 0xf1df4
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf1df6 ata.c:186
+ dec bx ; 4b ; 0xf1df9 ata.c:187
+ test bx, bx ; 85 db ; 0xf1dfa
+ jbe short 01e14h ; 76 16 ; 0xf1dfc
+ mov dx, cx ; 89 ca ; 0xf1dfe ata.c:188
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1e00
+ in AL, DX ; ec ; 0xf1e03
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1e04
+ test AL, strict byte 080h ; a8 80 ; 0xf1e06 ata.c:189
+ je short 01e14h ; 74 0a ; 0xf1e08
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf1e0a ata.c:191
+ dec ax ; 48 ; 0xf1e0d ata.c:192
+ test ax, ax ; 85 c0 ; 0xf1e0e
+ jnbe short 01e0dh ; 77 fb ; 0xf1e10
+ jmp short 01df9h ; eb e5 ; 0xf1e12 ata.c:195
+ mov bx, strict word 00010h ; bb 10 00 ; 0xf1e14 ata.c:200
+ dec bx ; 4b ; 0xf1e17 ata.c:201
+ test bx, bx ; 85 db ; 0xf1e18
+ jbe short 01e28h ; 76 0c ; 0xf1e1a
+ mov dx, cx ; 89 ca ; 0xf1e1c ata.c:202
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1e1e
+ in AL, DX ; ec ; 0xf1e21
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1e22
+ test AL, strict byte 040h ; a8 40 ; 0xf1e24 ata.c:203
+ je short 01e17h ; 74 ef ; 0xf1e26
+ lea dx, [si+006h] ; 8d 54 06 ; 0xf1e28 ata.c:208
+ mov AL, strict byte 008h ; b0 08 ; 0xf1e2b
+ out DX, AL ; ee ; 0xf1e2d
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf1e2e ata.c:209
+ pop di ; 5f ; 0xf1e31
+ pop si ; 5e ; 0xf1e32
+ pop dx ; 5a ; 0xf1e33
+ pop cx ; 59 ; 0xf1e34
+ pop bx ; 5b ; 0xf1e35
+ pop bp ; 5d ; 0xf1e36
+ retn ; c3 ; 0xf1e37
+ ; disGetNextSymbol 0xf1e38 LB 0x8110 -> off=0x0 cb=00000000000002b7 uValue=00000000000f0838 'ata_cmd_data_in'
+ata_cmd_data_in: ; 0xf1e38 LB 0x2b7
+ push bp ; 55 ; 0xf1e38 ata.c:223
+ mov bp, sp ; 89 e5 ; 0xf1e39
+ push si ; 56 ; 0xf1e3b
+ push di ; 57 ; 0xf1e3c
+ sub sp, strict byte 00010h ; 83 ec 10 ; 0xf1e3d
+ push ax ; 50 ; 0xf1e40
+ push dx ; 52 ; 0xf1e41
+ push bx ; 53 ; 0xf1e42
+ push cx ; 51 ; 0xf1e43
+ mov es, dx ; 8e c2 ; 0xf1e44 ata.c:233
+ mov bx, ax ; 89 c3 ; 0xf1e46
+ mov al, byte [es:bx+00ch] ; 26 8a 47 0c ; 0xf1e48
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf1e4c
+ mov bl, al ; 88 c3 ; 0xf1e4f ata.c:235
+ xor bh, ah ; 30 e7 ; 0xf1e51
+ mov ax, bx ; 89 d8 ; 0xf1e53
+ cwd ; 99 ; 0xf1e55
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf1e56
+ sar ax, 1 ; d1 f8 ; 0xf1e58
+ mov dx, strict word 00006h ; ba 06 00 ; 0xf1e5a
+ imul dx ; f7 ea ; 0xf1e5d
+ mov di, word [bp-016h] ; 8b 7e ea ; 0xf1e5f
+ add di, ax ; 01 c7 ; 0xf1e62
+ mov ax, word [es:di+00206h] ; 26 8b 85 06 02 ; 0xf1e64
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf1e69
+ mov ax, word [es:di+00208h] ; 26 8b 85 08 02 ; 0xf1e6c ata.c:236
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf1e71
+ mov ax, bx ; 89 d8 ; 0xf1e74 ata.c:238
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf1e76
+ imul dx ; f7 ea ; 0xf1e79
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf1e7b
+ add bx, ax ; 01 c3 ; 0xf1e7e
+ mov ax, word [es:bx+028h] ; 26 8b 47 28 ; 0xf1e80
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf1e84
+ test ax, ax ; 85 c0 ; 0xf1e87 ata.c:239
+ jne short 01e92h ; 75 07 ; 0xf1e89
+ mov word [bp-00eh], 08000h ; c7 46 f2 00 80 ; 0xf1e8b ata.c:245
+ jmp short 01e95h ; eb 03 ; 0xf1e90 ata.c:246
+ shr word [bp-00eh], 1 ; d1 6e f2 ; 0xf1e92 ata.c:252
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1e95 ata.c:255
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf1e98
+ in AL, DX ; ec ; 0xf1e9b
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf1e9c
+ test AL, strict byte 080h ; a8 80 ; 0xf1e9e ata.c:256
+ je short 01eb1h ; 74 0f ; 0xf1ea0
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf1ea2 ata.c:260
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf1ea5
+ mov AL, strict byte 008h ; b0 08 ; 0xf1ea8
+ out DX, AL ; ee ; 0xf1eaa
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf1eab ata.c:261
+ jmp near 020e8h ; e9 37 02 ; 0xf1eae
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf1eb1 ata.c:264
+ mov di, word [bp-016h] ; 8b 7e ea ; 0xf1eb4
+ mov di, word [es:di+008h] ; 26 8b 7d 08 ; 0xf1eb7
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf1ebb
+ mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xf1ebe
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf1ec2
+ mov al, byte [es:bx+016h] ; 26 8a 47 16 ; 0xf1ec5 ata.c:265
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf1ec9
+ mov ax, word [es:bx+012h] ; 26 8b 47 12 ; 0xf1ecc ata.c:266
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf1ed0
+ mov bl, byte [es:bx+014h] ; 26 8a 5f 14 ; 0xf1ed3 ata.c:267
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf1ed7 ata.c:270
+ test al, al ; 84 c0 ; 0xf1eda
+ je short 01ee1h ; 74 03 ; 0xf1edc
+ jmp near 01fc6h ; e9 e5 00 ; 0xf1ede
+ xor ah, ah ; 30 e4 ; 0xf1ee1 ata.c:271
+ xor bx, bx ; 31 db ; 0xf1ee3
+ mov word [bp-014h], bx ; 89 5e ec ; 0xf1ee5
+ mov si, word [bp-016h] ; 8b 76 ea ; 0xf1ee8
+ mov cx, word [es:si] ; 26 8b 0c ; 0xf1eeb
+ add cx, word [bp-01ch] ; 03 4e e4 ; 0xf1eee
+ adc ax, word [es:si+002h] ; 26 13 44 02 ; 0xf1ef1
+ adc bx, word [es:si+004h] ; 26 13 5c 04 ; 0xf1ef5
+ mov dx, word [es:si+006h] ; 26 8b 54 06 ; 0xf1ef9
+ adc dx, word [bp-014h] ; 13 56 ec ; 0xf1efd
+ test dx, dx ; 85 d2 ; 0xf1f00
+ jnbe short 01f16h ; 77 12 ; 0xf1f02
+ je short 01f09h ; 74 03 ; 0xf1f04
+ jmp near 01f7ch ; e9 73 00 ; 0xf1f06
+ test bx, bx ; 85 db ; 0xf1f09
+ jnbe short 01f16h ; 77 09 ; 0xf1f0b
+ jne short 01f7ch ; 75 6d ; 0xf1f0d
+ cmp ax, 01000h ; 3d 00 10 ; 0xf1f0f
+ jnbe short 01f16h ; 77 02 ; 0xf1f12
+ jne short 01f7ch ; 75 66 ; 0xf1f14
+ mov bx, si ; 89 f3 ; 0xf1f16 ata.c:273
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf1f18
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf1f1c
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf1f20
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf1f24
+ mov si, strict word 00018h ; be 18 00 ; 0xf1f27
+ call 09c10h ; e8 e3 7c ; 0xf1f2a
+ xor dh, dh ; 30 f6 ; 0xf1f2d
+ mov word [bp-014h], dx ; 89 56 ec ; 0xf1f2f
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf1f32 ata.c:274
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf1f35
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf1f39
+ mov si, word [bp-016h] ; 8b 76 ea ; 0xf1f3d
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf1f40
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf1f44
+ mov si, strict word 00020h ; be 20 00 ; 0xf1f47
+ call 09c10h ; e8 c3 7c ; 0xf1f4a
+ mov bx, dx ; 89 d3 ; 0xf1f4d
+ mov word [bp-010h], dx ; 89 56 f0 ; 0xf1f4f
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf1f52 ata.c:275
+ mov al, ah ; 88 e0 ; 0xf1f55
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1f57
+ inc dx ; 42 ; 0xf1f5a
+ inc dx ; 42 ; 0xf1f5b
+ out DX, AL ; ee ; 0xf1f5c
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1f5d ata.c:276
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf1f60
+ mov al, byte [bp-014h] ; 8a 46 ec ; 0xf1f63
+ out DX, AL ; ee ; 0xf1f66
+ xor bh, bh ; 30 ff ; 0xf1f67 ata.c:277
+ mov ax, bx ; 89 d8 ; 0xf1f69
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1f6b
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf1f6e
+ out DX, AL ; ee ; 0xf1f71
+ mov al, byte [bp-00fh] ; 8a 46 f1 ; 0xf1f72 ata.c:278
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1f75
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf1f78
+ out DX, AL ; ee ; 0xf1f7b
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf1f7c ata.c:282
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf1f7f
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf1f82
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf1f85
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf1f88 ata.c:283
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf1f8c
+ mov si, word [bp-016h] ; 8b 76 ea ; 0xf1f90
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf1f93
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf1f97
+ mov si, strict word 00008h ; be 08 00 ; 0xf1f9a
+ call 09c10h ; e8 70 7c ; 0xf1f9d
+ mov word [bp-010h], dx ; 89 56 f0 ; 0xf1fa0
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf1fa3 ata.c:284
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf1fa6
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf1faa
+ mov si, word [bp-016h] ; 8b 76 ea ; 0xf1fae
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf1fb1
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf1fb5
+ mov si, strict word 00018h ; be 18 00 ; 0xf1fb8
+ call 09c10h ; e8 52 7c ; 0xf1fbb
+ mov bl, dl ; 88 d3 ; 0xf1fbe
+ and bl, 00fh ; 80 e3 0f ; 0xf1fc0
+ or bl, 040h ; 80 cb 40 ; 0xf1fc3
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf1fc6 ata.c:287
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf1fc9
+ mov AL, strict byte 00ah ; b0 0a ; 0xf1fcc
+ out DX, AL ; ee ; 0xf1fce
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1fcf ata.c:288
+ inc dx ; 42 ; 0xf1fd2
+ xor al, al ; 30 c0 ; 0xf1fd3
+ out DX, AL ; ee ; 0xf1fd5
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1fd6 ata.c:289
+ inc dx ; 42 ; 0xf1fd9
+ inc dx ; 42 ; 0xf1fda
+ mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xf1fdb
+ out DX, AL ; ee ; 0xf1fde
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1fdf ata.c:290
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf1fe2
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf1fe5
+ out DX, AL ; ee ; 0xf1fe8
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf1fe9 ata.c:291
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1fec
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf1fef
+ out DX, AL ; ee ; 0xf1ff2
+ mov al, byte [bp-00fh] ; 8a 46 f1 ; 0xf1ff3 ata.c:292
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf1ff6
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf1ff9
+ out DX, AL ; ee ; 0xf1ffc
+ test byte [bp-008h], 001h ; f6 46 f8 01 ; 0xf1ffd ata.c:293
+ je short 02008h ; 74 05 ; 0xf2001
+ mov ax, 000b0h ; b8 b0 00 ; 0xf2003
+ jmp short 0200bh ; eb 03 ; 0xf2006
+ mov ax, 000a0h ; b8 a0 00 ; 0xf2008
+ mov dl, bl ; 88 da ; 0xf200b
+ xor dh, dh ; 30 f6 ; 0xf200d
+ or ax, dx ; 09 d0 ; 0xf200f
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2011
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2014
+ out DX, AL ; ee ; 0xf2017
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2018 ata.c:294
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf201b
+ mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xf201e
+ out DX, AL ; ee ; 0xf2021
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf2022 ata.c:296
+ cmp ax, 000c4h ; 3d c4 00 ; 0xf2025
+ je short 0202fh ; 74 05 ; 0xf2028
+ cmp ax, strict word 00029h ; 3d 29 00 ; 0xf202a
+ jne short 02039h ; 75 0a ; 0xf202d
+ mov si, word [bp-01ch] ; 8b 76 e4 ; 0xf202f ata.c:297
+ mov word [bp-01ch], strict word 00001h ; c7 46 e4 01 00 ; 0xf2032 ata.c:298
+ jmp short 0203ch ; eb 03 ; 0xf2037 ata.c:299
+ mov si, strict word 00001h ; be 01 00 ; 0xf2039 ata.c:300
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf203c ata.c:304
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf203f
+ in AL, DX ; ec ; 0xf2042
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2043
+ mov bl, al ; 88 c3 ; 0xf2045
+ test AL, strict byte 080h ; a8 80 ; 0xf2047 ata.c:305
+ jne short 0203ch ; 75 f1 ; 0xf2049
+ test AL, strict byte 001h ; a8 01 ; 0xf204b ata.c:309
+ je short 0205eh ; 74 0f ; 0xf204d
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf204f ata.c:312
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2052
+ mov AL, strict byte 008h ; b0 08 ; 0xf2055
+ out DX, AL ; ee ; 0xf2057
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf2058 ata.c:313
+ jmp near 020e8h ; e9 8a 00 ; 0xf205b
+ test bl, 008h ; f6 c3 08 ; 0xf205e ata.c:314
+ jne short 02072h ; 75 0f ; 0xf2061
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf2063 ata.c:317
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2066
+ mov AL, strict byte 008h ; b0 08 ; 0xf2069
+ out DX, AL ; ee ; 0xf206b
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf206c ata.c:318
+ jmp near 020e8h ; e9 76 00 ; 0xf206f
+ sti ; fb ; 0xf2072 ata.c:323
+ cmp di, 0f800h ; 81 ff 00 f8 ; 0xf2073 ata.c:328
+ jc short 02086h ; 72 0d ; 0xf2077
+ sub di, 00800h ; 81 ef 00 08 ; 0xf2079 ata.c:329
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf207d
+ add ax, 00080h ; 05 80 00 ; 0xf2080
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf2083
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf2086 ata.c:336
+ mov cx, word [bp-00eh] ; 8b 4e f2 ; 0xf2089
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf208c
+ rep insw ; f3 6d ; 0xf208f
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf2091 ata.c:337
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf2094
+ add word [es:bx+018h], si ; 26 01 77 18 ; 0xf2097
+ dec word [bp-01ch] ; ff 4e e4 ; 0xf209b ata.c:338
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf209e ata.c:340
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf20a1
+ in AL, DX ; ec ; 0xf20a4
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf20a5
+ mov bl, al ; 88 c3 ; 0xf20a7
+ test AL, strict byte 080h ; a8 80 ; 0xf20a9 ata.c:341
+ jne short 0209eh ; 75 f1 ; 0xf20ab
+ cmp word [bp-01ch], strict byte 00000h ; 83 7e e4 00 ; 0xf20ad ata.c:344
+ jne short 020c7h ; 75 14 ; 0xf20b1
+ and AL, strict byte 0c9h ; 24 c9 ; 0xf20b3 ata.c:345
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf20b5
+ je short 020ddh ; 74 24 ; 0xf20b7
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf20b9 ata.c:349
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf20bc
+ mov AL, strict byte 008h ; b0 08 ; 0xf20bf
+ out DX, AL ; ee ; 0xf20c1
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf20c2 ata.c:350
+ jmp short 020e8h ; eb 21 ; 0xf20c5
+ mov al, bl ; 88 d8 ; 0xf20c7 ata.c:355
+ and AL, strict byte 0c9h ; 24 c9 ; 0xf20c9
+ cmp AL, strict byte 048h ; 3c 48 ; 0xf20cb
+ je short 02073h ; 74 a4 ; 0xf20cd
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf20cf ata.c:359
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf20d2
+ mov AL, strict byte 008h ; b0 08 ; 0xf20d5
+ out DX, AL ; ee ; 0xf20d7
+ mov ax, strict word 00005h ; b8 05 00 ; 0xf20d8 ata.c:360
+ jmp short 020e8h ; eb 0b ; 0xf20db
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf20dd ata.c:366
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf20e0
+ mov AL, strict byte 008h ; b0 08 ; 0xf20e3
+ out DX, AL ; ee ; 0xf20e5
+ xor ax, ax ; 31 c0 ; 0xf20e6 ata.c:367
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf20e8 ata.c:368
+ pop di ; 5f ; 0xf20eb
+ pop si ; 5e ; 0xf20ec
+ pop bp ; 5d ; 0xf20ed
+ retn ; c3 ; 0xf20ee
+ ; disGetNextSymbol 0xf20ef LB 0x7e59 -> off=0x0 cb=00000000000006ab uValue=00000000000f0aef 'ata_detect'
+ata_detect: ; 0xf20ef LB 0x6ab
+ push bp ; 55 ; 0xf20ef ata.c:374
+ mov bp, sp ; 89 e5 ; 0xf20f0
+ push si ; 56 ; 0xf20f2
+ push di ; 57 ; 0xf20f3
+ sub sp, 00264h ; 81 ec 64 02 ; 0xf20f4
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf20f8 ata.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf20fb
+ mov es, ax ; 8e c0 ; 0xf20fe
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf2100
+ mov word [bp-028h], ax ; 89 46 d8 ; 0xf2103 ata.c:49
+ mov bx, 00122h ; bb 22 01 ; 0xf2106 ata.c:381
+ mov es, ax ; 8e c0 ; 0xf2109
+ mov word [bp-030h], bx ; 89 5e d0 ; 0xf210b
+ mov word [bp-02eh], ax ; 89 46 d2 ; 0xf210e
+ mov byte [es:bx+00204h], 000h ; 26 c6 87 04 02 00 ; 0xf2111 ata.c:384
+ mov word [es:bx+00206h], 001f0h ; 26 c7 87 06 02 f0 01 ; 0xf2117 ata.c:385
+ mov word [es:bx+00208h], 003f0h ; 26 c7 87 08 02 f0 03 ; 0xf211e ata.c:386
+ mov byte [es:bx+00205h], 00eh ; 26 c6 87 05 02 0e ; 0xf2125 ata.c:387
+ mov byte [es:bx+0020ah], 000h ; 26 c6 87 0a 02 00 ; 0xf212b ata.c:390
+ mov word [es:bx+0020ch], 00170h ; 26 c7 87 0c 02 70 01 ; 0xf2131 ata.c:391
+ mov word [es:bx+0020eh], 00370h ; 26 c7 87 0e 02 70 03 ; 0xf2138 ata.c:392
+ mov byte [es:bx+0020bh], 00fh ; 26 c6 87 0b 02 0f ; 0xf213f ata.c:393
+ xor al, al ; 30 c0 ; 0xf2145 ata.c:414
+ mov byte [bp-014h], al ; 88 46 ec ; 0xf2147
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf214a
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf214d ata.c:416
+ jmp near 0271fh ; e9 cc 05 ; 0xf2150
+ mov ax, 000a0h ; b8 a0 00 ; 0xf2153 ata.c:431
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf2156
+ out DX, AL ; ee ; 0xf2159
+ lea di, [bx+002h] ; 8d 7f 02 ; 0xf215a ata.c:432
+ mov AL, strict byte 055h ; b0 55 ; 0xf215d
+ mov dx, di ; 89 fa ; 0xf215f
+ out DX, AL ; ee ; 0xf2161
+ lea si, [bx+003h] ; 8d 77 03 ; 0xf2162 ata.c:433
+ mov AL, strict byte 0aah ; b0 aa ; 0xf2165
+ mov dx, si ; 89 f2 ; 0xf2167
+ out DX, AL ; ee ; 0xf2169
+ mov dx, di ; 89 fa ; 0xf216a ata.c:434
+ out DX, AL ; ee ; 0xf216c
+ mov AL, strict byte 055h ; b0 55 ; 0xf216d ata.c:435
+ mov dx, si ; 89 f2 ; 0xf216f
+ out DX, AL ; ee ; 0xf2171
+ mov dx, di ; 89 fa ; 0xf2172 ata.c:436
+ out DX, AL ; ee ; 0xf2174
+ mov AL, strict byte 0aah ; b0 aa ; 0xf2175 ata.c:437
+ mov dx, si ; 89 f2 ; 0xf2177
+ out DX, AL ; ee ; 0xf2179
+ mov dx, di ; 89 fa ; 0xf217a ata.c:440
+ in AL, DX ; ec ; 0xf217c
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf217d
+ mov cx, ax ; 89 c1 ; 0xf217f
+ mov dx, si ; 89 f2 ; 0xf2181 ata.c:441
+ in AL, DX ; ec ; 0xf2183
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2184
+ cmp cl, 055h ; 80 f9 55 ; 0xf2186 ata.c:443
+ jne short 021d4h ; 75 49 ; 0xf2189
+ cmp AL, strict byte 0aah ; 3c aa ; 0xf218b
+ jne short 021d4h ; 75 45 ; 0xf218d
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf218f ata.c:444
+ xor ah, ah ; 30 e4 ; 0xf2192
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf2194
+ imul dx ; f7 ea ; 0xf2197
+ les si, [bp-030h] ; c4 76 d0 ; 0xf2199
+ add si, ax ; 01 c6 ; 0xf219c
+ mov byte [es:si+022h], 001h ; 26 c6 44 22 01 ; 0xf219e
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf21a3 ata.c:447
+ xor ah, ah ; 30 e4 ; 0xf21a6
+ call 01d4eh ; e8 a3 fb ; 0xf21a8
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf21ab ata.c:450
+ je short 021b6h ; 74 05 ; 0xf21af
+ mov ax, 000b0h ; b8 b0 00 ; 0xf21b1
+ jmp short 021b9h ; eb 03 ; 0xf21b4
+ mov ax, 000a0h ; b8 a0 00 ; 0xf21b6
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf21b9
+ out DX, AL ; ee ; 0xf21bc
+ lea dx, [bx+002h] ; 8d 57 02 ; 0xf21bd ata.c:451
+ in AL, DX ; ec ; 0xf21c0
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf21c1
+ mov cx, ax ; 89 c1 ; 0xf21c3
+ lea dx, [bx+003h] ; 8d 57 03 ; 0xf21c5 ata.c:452
+ in AL, DX ; ec ; 0xf21c8
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf21c9
+ cmp cl, 001h ; 80 f9 01 ; 0xf21cb ata.c:453
+ jne short 02211h ; 75 41 ; 0xf21ce
+ cmp al, cl ; 38 c8 ; 0xf21d0
+ je short 021d6h ; 74 02 ; 0xf21d2
+ jmp short 02211h ; eb 3b ; 0xf21d4
+ lea dx, [bx+004h] ; 8d 57 04 ; 0xf21d6 ata.c:454
+ in AL, DX ; ec ; 0xf21d9
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf21da
+ mov cx, ax ; 89 c1 ; 0xf21dc
+ mov byte [bp-010h], al ; 88 46 f0 ; 0xf21de
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf21e1 ata.c:455
+ in AL, DX ; ec ; 0xf21e4
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf21e5
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf21e7
+ mov ch, byte [bp-01ch] ; 8a 6e e4 ; 0xf21ea
+ lea dx, [bx+007h] ; 8d 57 07 ; 0xf21ed ata.c:456
+ in AL, DX ; ec ; 0xf21f0
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf21f1
+ cmp cl, 014h ; 80 f9 14 ; 0xf21f3 ata.c:458
+ jne short 02213h ; 75 1b ; 0xf21f6
+ cmp ch, 0ebh ; 80 fd eb ; 0xf21f8
+ jne short 02213h ; 75 16 ; 0xf21fb
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf21fd ata.c:459
+ xor ah, ah ; 30 e4 ; 0xf2200
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf2202
+ imul dx ; f7 ea ; 0xf2205
+ les bx, [bp-030h] ; c4 5e d0 ; 0xf2207
+ add bx, ax ; 01 c3 ; 0xf220a
+ mov byte [es:bx+022h], 003h ; 26 c6 47 22 03 ; 0xf220c
+ jmp short 02256h ; eb 43 ; 0xf2211 ata.c:460
+ cmp byte [bp-010h], 000h ; 80 7e f0 00 ; 0xf2213
+ jne short 02237h ; 75 1e ; 0xf2217
+ test ch, ch ; 84 ed ; 0xf2219
+ jne short 02237h ; 75 1a ; 0xf221b
+ test al, al ; 84 c0 ; 0xf221d
+ je short 02237h ; 74 16 ; 0xf221f
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf2221 ata.c:461
+ xor ah, ah ; 30 e4 ; 0xf2224
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf2226
+ imul dx ; f7 ea ; 0xf2229
+ les bx, [bp-030h] ; c4 5e d0 ; 0xf222b
+ add bx, ax ; 01 c3 ; 0xf222e
+ mov byte [es:bx+022h], 002h ; 26 c6 47 22 02 ; 0xf2230
+ jmp short 02256h ; eb 1f ; 0xf2235 ata.c:462
+ mov al, byte [bp-010h] ; 8a 46 f0 ; 0xf2237
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xf223a
+ jne short 02256h ; 75 18 ; 0xf223c
+ cmp ch, al ; 38 c5 ; 0xf223e
+ jne short 02256h ; 75 14 ; 0xf2240
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf2242 ata.c:463
+ xor ah, ah ; 30 e4 ; 0xf2245
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf2247
+ imul dx ; f7 ea ; 0xf224a
+ les bx, [bp-030h] ; c4 5e d0 ; 0xf224c
+ add bx, ax ; 01 c3 ; 0xf224f
+ mov byte [es:bx+022h], 000h ; 26 c6 47 22 00 ; 0xf2251
+ mov dx, word [bp-02ah] ; 8b 56 d6 ; 0xf2256 ata.c:469
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2259
+ mov AL, strict byte 008h ; b0 08 ; 0xf225c
+ out DX, AL ; ee ; 0xf225e
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf225f ata.c:471
+ xor ah, ah ; 30 e4 ; 0xf2262
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf2264
+ imul dx ; f7 ea ; 0xf2267
+ les bx, [bp-030h] ; c4 5e d0 ; 0xf2269
+ add bx, ax ; 01 c3 ; 0xf226c
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf226e
+ mov byte [bp-018h], al ; 88 46 e8 ; 0xf2272
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf2275 ata.c:474
+ jne short 022c5h ; 75 4c ; 0xf2277
+ mov byte [es:bx+023h], 0ffh ; 26 c6 47 23 ff ; 0xf2279 ata.c:482
+ mov byte [es:bx+026h], 000h ; 26 c6 47 26 00 ; 0xf227e ata.c:483
+ lea dx, [bp-00268h] ; 8d 96 98 fd ; 0xf2283 ata.c:484
+ mov bx, word [bp-030h] ; 8b 5e d0 ; 0xf2287
+ mov word [es:bx+008h], dx ; 26 89 57 08 ; 0xf228a
+ mov [es:bx+00ah], ss ; 26 8c 57 0a ; 0xf228e
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf2292 ata.c:485
+ mov byte [es:bx+00ch], al ; 26 88 47 0c ; 0xf2295
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf2299 ata.c:487
+ mov bx, 000ech ; bb ec 00 ; 0xf229c
+ mov ax, word [bp-030h] ; 8b 46 d0 ; 0xf229f
+ mov dx, es ; 8c c2 ; 0xf22a2
+ call 01e38h ; e8 91 fb ; 0xf22a4
+ test ax, ax ; 85 c0 ; 0xf22a7
+ je short 022b9h ; 74 0e ; 0xf22a9
+ mov ax, 00124h ; b8 24 01 ; 0xf22ab ata.c:488
+ push ax ; 50 ; 0xf22ae
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf22af
+ push ax ; 50 ; 0xf22b2
+ call 0190fh ; e8 59 f6 ; 0xf22b3
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf22b6
+ test byte [bp-00268h], 080h ; f6 86 98 fd 80 ; 0xf22b9 ata.c:490
+ je short 022c8h ; 74 08 ; 0xf22be
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf22c0
+ jmp short 022cah ; eb 05 ; 0xf22c3
+ jmp near 024d6h ; e9 0e 02 ; 0xf22c5
+ xor ax, ax ; 31 c0 ; 0xf22c8
+ mov byte [bp-016h], al ; 88 46 ea ; 0xf22ca
+ mov byte [bp-012h], 000h ; c6 46 ee 00 ; 0xf22cd ata.c:494
+ mov word [bp-034h], 00200h ; c7 46 cc 00 02 ; 0xf22d1 ata.c:496
+ mov ax, word [bp-00266h] ; 8b 86 9a fd ; 0xf22d6 ata.c:498
+ mov word [bp-02ch], ax ; 89 46 d4 ; 0xf22da
+ mov ax, word [bp-00262h] ; 8b 86 9e fd ; 0xf22dd ata.c:499
+ mov word [bp-01eh], ax ; 89 46 e2 ; 0xf22e1
+ mov ax, word [bp-0025ch] ; 8b 86 a4 fd ; 0xf22e4 ata.c:500
+ mov word [bp-032h], ax ; 89 46 ce ; 0xf22e8
+ mov ax, word [bp-001f0h] ; 8b 86 10 fe ; 0xf22eb ata.c:502
+ mov word [bp-036h], ax ; 89 46 ca ; 0xf22ef
+ mov si, word [bp-001eeh] ; 8b b6 12 fe ; 0xf22f2
+ xor ax, ax ; 31 c0 ; 0xf22f6
+ mov word [bp-022h], ax ; 89 46 de ; 0xf22f8
+ mov word [bp-020h], ax ; 89 46 e0 ; 0xf22fb
+ cmp si, 00fffh ; 81 fe ff 0f ; 0xf22fe ata.c:503
+ jne short 02323h ; 75 1f ; 0xf2302
+ cmp word [bp-036h], strict byte 0ffffh ; 83 7e ca ff ; 0xf2304
+ jne short 02323h ; 75 19 ; 0xf2308
+ mov ax, word [bp-0019ah] ; 8b 86 66 fe ; 0xf230a ata.c:504
+ mov word [bp-020h], ax ; 89 46 e0 ; 0xf230e
+ mov ax, word [bp-0019ch] ; 8b 86 64 fe ; 0xf2311
+ mov word [bp-022h], ax ; 89 46 de ; 0xf2315
+ mov si, word [bp-0019eh] ; 8b b6 62 fe ; 0xf2318
+ mov ax, word [bp-001a0h] ; 8b 86 60 fe ; 0xf231c
+ mov word [bp-036h], ax ; 89 46 ca ; 0xf2320
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf2323 ata.c:505
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf2326
+ jc short 02336h ; 72 0c ; 0xf2328
+ jbe short 0233eh ; 76 12 ; 0xf232a
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf232c
+ je short 02346h ; 74 16 ; 0xf232e
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf2330
+ je short 02342h ; 74 0e ; 0xf2332
+ jmp short 0237bh ; eb 45 ; 0xf2334
+ test al, al ; 84 c0 ; 0xf2336
+ jne short 0237bh ; 75 41 ; 0xf2338
+ mov BL, strict byte 01eh ; b3 1e ; 0xf233a ata.c:508
+ jmp short 02348h ; eb 0a ; 0xf233c ata.c:509
+ mov BL, strict byte 026h ; b3 26 ; 0xf233e ata.c:511
+ jmp short 02348h ; eb 06 ; 0xf2340 ata.c:512
+ mov BL, strict byte 067h ; b3 67 ; 0xf2342 ata.c:514
+ jmp short 02348h ; eb 02 ; 0xf2344 ata.c:515
+ mov BL, strict byte 070h ; b3 70 ; 0xf2346 ata.c:517
+ mov al, bl ; 88 d8 ; 0xf2348 ata.c:524
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf234a
+ xor ah, ah ; 30 e4 ; 0xf234c
+ call 01652h ; e8 01 f3 ; 0xf234e
+ mov dh, al ; 88 c6 ; 0xf2351
+ mov al, bl ; 88 d8 ; 0xf2353
+ xor ah, ah ; 30 e4 ; 0xf2355
+ call 01652h ; e8 f8 f2 ; 0xf2357
+ mov ah, dh ; 88 f4 ; 0xf235a
+ mov word [bp-03ch], ax ; 89 46 c4 ; 0xf235c
+ mov al, bl ; 88 d8 ; 0xf235f ata.c:525
+ add AL, strict byte 002h ; 04 02 ; 0xf2361
+ xor ah, ah ; 30 e4 ; 0xf2363
+ call 01652h ; e8 ea f2 ; 0xf2365
+ xor ah, ah ; 30 e4 ; 0xf2368
+ mov word [bp-03eh], ax ; 89 46 c2 ; 0xf236a
+ mov al, bl ; 88 d8 ; 0xf236d ata.c:526
+ add AL, strict byte 007h ; 04 07 ; 0xf236f
+ call 01652h ; e8 de f2 ; 0xf2371
+ xor ah, ah ; 30 e4 ; 0xf2374
+ mov word [bp-03ah], ax ; 89 46 c6 ; 0xf2376
+ jmp short 0238dh ; eb 12 ; 0xf2379 ata.c:528
+ push word [bp-020h] ; ff 76 e0 ; 0xf237b ata.c:529
+ push word [bp-022h] ; ff 76 de ; 0xf237e
+ push si ; 56 ; 0xf2381
+ push word [bp-036h] ; ff 76 ca ; 0xf2382
+ mov dx, ss ; 8c d2 ; 0xf2385
+ lea ax, [bp-03eh] ; 8d 46 c2 ; 0xf2387
+ call 059dch ; e8 4f 36 ; 0xf238a
+ mov bx, 00da0h ; bb a0 0d ; 0xf238d ata.c:532
+ mov cx, ds ; 8c d9 ; 0xf2390
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf2392
+ call 018cch ; e8 34 f5 ; 0xf2395
+ mov ax, word [bp-03ah] ; 8b 46 c6 ; 0xf2398
+ push ax ; 50 ; 0xf239b
+ mov ax, word [bp-03eh] ; 8b 46 c2 ; 0xf239c
+ push ax ; 50 ; 0xf239f
+ mov ax, word [bp-03ch] ; 8b 46 c4 ; 0xf23a0
+ push ax ; 50 ; 0xf23a3
+ push word [bp-032h] ; ff 76 ce ; 0xf23a4
+ push word [bp-01eh] ; ff 76 e2 ; 0xf23a7
+ push word [bp-02ch] ; ff 76 d4 ; 0xf23aa
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf23ad
+ xor ah, ah ; 30 e4 ; 0xf23b0
+ push ax ; 50 ; 0xf23b2
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf23b3
+ push ax ; 50 ; 0xf23b6
+ mov ax, 0014dh ; b8 4d 01 ; 0xf23b7
+ push ax ; 50 ; 0xf23ba
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf23bb
+ push ax ; 50 ; 0xf23be
+ call 0190fh ; e8 4d f5 ; 0xf23bf
+ add sp, strict byte 00014h ; 83 c4 14 ; 0xf23c2
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf23c5 ata.c:534
+ xor ah, ah ; 30 e4 ; 0xf23c8
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf23ca
+ imul dx ; f7 ea ; 0xf23cd
+ les di, [bp-030h] ; c4 7e d0 ; 0xf23cf
+ add di, ax ; 01 c7 ; 0xf23d2
+ mov byte [es:di+023h], 0ffh ; 26 c6 45 23 ff ; 0xf23d4
+ mov al, byte [bp-016h] ; 8a 46 ea ; 0xf23d9 ata.c:535
+ mov byte [es:di+024h], al ; 26 88 45 24 ; 0xf23dc
+ mov al, byte [bp-012h] ; 8a 46 ee ; 0xf23e0 ata.c:536
+ mov byte [es:di+026h], al ; 26 88 45 26 ; 0xf23e3
+ mov ax, word [bp-034h] ; 8b 46 cc ; 0xf23e7 ata.c:537
+ mov word [es:di+028h], ax ; 26 89 45 28 ; 0xf23ea
+ mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xf23ee ata.c:538
+ mov word [es:di+030h], ax ; 26 89 45 30 ; 0xf23f1
+ mov ax, word [bp-02ch] ; 8b 46 d4 ; 0xf23f5 ata.c:539
+ mov word [es:di+032h], ax ; 26 89 45 32 ; 0xf23f8
+ mov ax, word [bp-032h] ; 8b 46 ce ; 0xf23fc ata.c:540
+ mov word [es:di+034h], ax ; 26 89 45 34 ; 0xf23ff
+ mov ax, word [bp-020h] ; 8b 46 e0 ; 0xf2403 ata.c:541
+ mov word [es:di+03ch], ax ; 26 89 45 3c ; 0xf2406
+ mov ax, word [bp-022h] ; 8b 46 de ; 0xf240a
+ mov word [es:di+03ah], ax ; 26 89 45 3a ; 0xf240d
+ mov word [es:di+038h], si ; 26 89 75 38 ; 0xf2411
+ mov ax, word [bp-036h] ; 8b 46 ca ; 0xf2415
+ mov word [es:di+036h], ax ; 26 89 45 36 ; 0xf2418
+ lea di, [di+02ah] ; 8d 7d 2a ; 0xf241c ata.c:542
+ push DS ; 1e ; 0xf241f
+ push SS ; 16 ; 0xf2420
+ pop DS ; 1f ; 0xf2421
+ lea si, [bp-03eh] ; 8d 76 c2 ; 0xf2422
+ movsw ; a5 ; 0xf2425
+ movsw ; a5 ; 0xf2426
+ movsw ; a5 ; 0xf2427
+ pop DS ; 1f ; 0xf2428
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf2429 ata.c:543
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf242c
+ jnc short 024a0h ; 73 70 ; 0xf242e
+ test al, al ; 84 c0 ; 0xf2430 ata.c:549
+ jne short 02439h ; 75 05 ; 0xf2432
+ mov si, strict word 0003dh ; be 3d 00 ; 0xf2434 ata.c:550
+ jmp short 0243ch ; eb 03 ; 0xf2437 ata.c:551
+ mov si, strict word 0004dh ; be 4d 00 ; 0xf2439 ata.c:552
+ mov cx, word [bp-028h] ; 8b 4e d8 ; 0xf243c
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf243f ata.c:564
+ xor ah, ah ; 30 e4 ; 0xf2442
+ mov dx, strict word 00005h ; ba 05 00 ; 0xf2444
+ imul dx ; f7 ea ; 0xf2447
+ mov bx, ax ; 89 c3 ; 0xf2449
+ sal bx, 1 ; d1 e3 ; 0xf244b
+ sal bx, 1 ; d1 e3 ; 0xf244d
+ add bx, 00104h ; 81 c3 04 01 ; 0xf244f
+ xor ax, ax ; 31 c0 ; 0xf2453
+ mov es, ax ; 8e c0 ; 0xf2455
+ mov word [es:bx], si ; 26 89 37 ; 0xf2457 ata.c:565
+ mov word [es:bx+002h], cx ; 26 89 4f 02 ; 0xf245a
+ mov es, cx ; 8e c1 ; 0xf245e ata.c:571
+ mov word [es:si+00ch], ax ; 26 89 44 0c ; 0xf2460
+ mov word [es:si+005h], ax ; 26 89 44 05 ; 0xf2464
+ mov word [es:si+007h], ax ; 26 89 44 07 ; 0xf2468
+ mov bx, word [bp-03ch] ; 8b 5e c4 ; 0xf246c ata.c:573
+ mov word [es:si], bx ; 26 89 1c ; 0xf246f
+ mov bl, byte [bp-03eh] ; 8a 5e c2 ; 0xf2472 ata.c:574
+ mov byte [es:si+002h], bl ; 26 88 5c 02 ; 0xf2475
+ mov byte [es:si+003h], 0a0h ; 26 c6 44 03 a0 ; 0xf2479 ata.c:575
+ mov al, byte [bp-032h] ; 8a 46 ce ; 0xf247e ata.c:576
+ mov byte [es:si+004h], al ; 26 88 44 04 ; 0xf2481
+ mov ax, word [bp-02ch] ; 8b 46 d4 ; 0xf2485 ata.c:577
+ mov word [es:si+009h], ax ; 26 89 44 09 ; 0xf2488
+ mov al, byte [bp-01eh] ; 8a 46 e2 ; 0xf248c ata.c:578
+ mov byte [es:si+00bh], al ; 26 88 44 0b ; 0xf248f
+ mov bl, byte [bp-03ah] ; 8a 5e c6 ; 0xf2493 ata.c:579
+ mov byte [es:si+00eh], bl ; 26 88 5c 0e ; 0xf2496
+ xor bl, bl ; 30 db ; 0xf249a ata.c:580
+ xor bh, bh ; 30 ff ; 0xf249c ata.c:581
+ jmp short 024a7h ; eb 07 ; 0xf249e
+ jmp short 024c0h ; eb 1e ; 0xf24a0
+ cmp bh, 00fh ; 80 ff 0f ; 0xf24a2
+ jnc short 024b8h ; 73 11 ; 0xf24a5
+ mov al, bh ; 88 f8 ; 0xf24a7 ata.c:582
+ xor ah, ah ; 30 e4 ; 0xf24a9
+ mov es, cx ; 8e c1 ; 0xf24ab
+ mov di, si ; 89 f7 ; 0xf24ad
+ add di, ax ; 01 c7 ; 0xf24af
+ add bl, byte [es:di] ; 26 02 1d ; 0xf24b1
+ db 0feh, 0c7h
+ ; inc bh ; fe c7 ; 0xf24b4
+ jmp short 024a2h ; eb ea ; 0xf24b6
+ neg bl ; f6 db ; 0xf24b8 ata.c:583
+ mov es, cx ; 8e c1 ; 0xf24ba ata.c:584
+ mov byte [es:si+00fh], bl ; 26 88 5c 0f ; 0xf24bc
+ mov bl, byte [bp-00ch] ; 8a 5e f4 ; 0xf24c0 ata.c:588
+ xor bh, bh ; 30 ff ; 0xf24c3
+ mov es, [bp-02eh] ; 8e 46 d2 ; 0xf24c5
+ add bx, word [bp-030h] ; 03 5e d0 ; 0xf24c8
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf24cb
+ mov byte [es:bx+001e3h], al ; 26 88 87 e3 01 ; 0xf24ce
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf24d3 ata.c:589
+ cmp byte [bp-018h], 003h ; 80 7e e8 03 ; 0xf24d6 ata.c:593
+ jne short 02540h ; 75 64 ; 0xf24da
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf24dc ata.c:598
+ xor ah, ah ; 30 e4 ; 0xf24df
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf24e1
+ imul dx ; f7 ea ; 0xf24e4
+ les bx, [bp-030h] ; c4 5e d0 ; 0xf24e6
+ add bx, ax ; 01 c3 ; 0xf24e9
+ mov byte [es:bx+023h], 005h ; 26 c6 47 23 05 ; 0xf24eb
+ mov byte [es:bx+026h], 000h ; 26 c6 47 26 00 ; 0xf24f0 ata.c:599
+ lea dx, [bp-00268h] ; 8d 96 98 fd ; 0xf24f5 ata.c:600
+ mov bx, word [bp-030h] ; 8b 5e d0 ; 0xf24f9
+ mov word [es:bx+008h], dx ; 26 89 57 08 ; 0xf24fc
+ mov [es:bx+00ah], ss ; 26 8c 57 0a ; 0xf2500
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf2504 ata.c:601
+ mov byte [es:bx+00ch], al ; 26 88 47 0c ; 0xf2507
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf250b ata.c:603
+ mov bx, 000a1h ; bb a1 00 ; 0xf250e
+ mov ax, word [bp-030h] ; 8b 46 d0 ; 0xf2511
+ mov dx, es ; 8c c2 ; 0xf2514
+ call 01e38h ; e8 1f f9 ; 0xf2516
+ test ax, ax ; 85 c0 ; 0xf2519
+ je short 0252bh ; 74 0e ; 0xf251b
+ mov ax, 00174h ; b8 74 01 ; 0xf251d ata.c:604
+ push ax ; 50 ; 0xf2520
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf2521
+ push ax ; 50 ; 0xf2524
+ call 0190fh ; e8 e7 f3 ; 0xf2525
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf2528
+ mov al, byte [bp-00267h] ; 8a 86 99 fd ; 0xf252b ata.c:606
+ and AL, strict byte 01fh ; 24 1f ; 0xf252f
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf2531
+ test byte [bp-00268h], 080h ; f6 86 98 fd 80 ; 0xf2534 ata.c:607
+ je short 02542h ; 74 07 ; 0xf2539
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf253b
+ jmp short 02544h ; eb 04 ; 0xf253e
+ jmp short 0257ch ; eb 3a ; 0xf2540
+ xor cx, cx ; 31 c9 ; 0xf2542
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf2544 ata.c:615
+ xor ah, ah ; 30 e4 ; 0xf2547
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf2549
+ imul dx ; f7 ea ; 0xf254c
+ les bx, [bp-030h] ; c4 5e d0 ; 0xf254e
+ add bx, ax ; 01 c3 ; 0xf2551
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf2553
+ mov byte [es:bx+023h], al ; 26 88 47 23 ; 0xf2556
+ mov byte [es:bx+024h], cl ; 26 88 4f 24 ; 0xf255a ata.c:616
+ mov byte [es:bx+026h], 000h ; 26 c6 47 26 00 ; 0xf255e ata.c:617
+ mov word [es:bx+028h], 00800h ; 26 c7 47 28 00 08 ; 0xf2563 ata.c:618
+ mov bl, byte [bp-014h] ; 8a 5e ec ; 0xf2569 ata.c:621
+ xor bh, bh ; 30 ff ; 0xf256c
+ add bx, word [bp-030h] ; 03 5e d0 ; 0xf256e
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf2571
+ mov byte [es:bx+001f4h], al ; 26 88 87 f4 01 ; 0xf2574
+ inc byte [bp-014h] ; fe 46 ec ; 0xf2579 ata.c:622
+ mov al, byte [bp-018h] ; 8a 46 e8 ; 0xf257c ata.c:631
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf257f
+ je short 025b2h ; 74 2f ; 0xf2581
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf2583
+ jne short 025d9h ; 75 52 ; 0xf2585
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf2587 ata.c:633
+ xor ah, ah ; 30 e4 ; 0xf258a
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf258c
+ imul dx ; f7 ea ; 0xf258f
+ les si, [bp-030h] ; c4 76 d0 ; 0xf2591
+ add si, ax ; 01 c6 ; 0xf2594
+ mov ax, word [es:si+03ch] ; 26 8b 44 3c ; 0xf2596
+ mov bx, word [es:si+03ah] ; 26 8b 5c 3a ; 0xf259a
+ mov cx, word [es:si+038h] ; 26 8b 4c 38 ; 0xf259e
+ mov dx, word [es:si+036h] ; 26 8b 54 36 ; 0xf25a2
+ mov si, strict word 0000bh ; be 0b 00 ; 0xf25a6
+ call 09c10h ; e8 64 76 ; 0xf25a9
+ mov word [bp-024h], dx ; 89 56 dc ; 0xf25ac
+ mov word [bp-026h], cx ; 89 4e da ; 0xf25af
+ mov ah, byte [bp-001c7h] ; 8a a6 39 fe ; 0xf25b2 ata.c:636
+ mov al, byte [bp-001c8h] ; 8a 86 38 fe ; 0xf25b6
+ mov byte [bp-01ah], 00fh ; c6 46 e6 0f ; 0xf25ba ata.c:637
+ jmp short 025c9h ; eb 09 ; 0xf25be
+ dec byte [bp-01ah] ; fe 4e e6 ; 0xf25c0 ata.c:640
+ cmp byte [bp-01ah], 000h ; 80 7e e6 00 ; 0xf25c3
+ jbe short 025d5h ; 76 0c ; 0xf25c7
+ mov cl, byte [bp-01ah] ; 8a 4e e6 ; 0xf25c9
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf25cc
+ sal dx, CL ; d3 e2 ; 0xf25cf
+ test ax, dx ; 85 d0 ; 0xf25d1
+ je short 025c0h ; 74 eb ; 0xf25d3
+ xor si, si ; 31 f6 ; 0xf25d5 ata.c:643
+ jmp short 025e0h ; eb 07 ; 0xf25d7
+ jmp short 0260fh ; eb 34 ; 0xf25d9
+ cmp si, strict byte 00014h ; 83 fe 14 ; 0xf25db
+ jnl short 025f5h ; 7d 15 ; 0xf25de
+ mov di, si ; 89 f7 ; 0xf25e0 ata.c:644
+ sal di, 1 ; d1 e7 ; 0xf25e2
+ mov al, byte [bp+di-00231h] ; 8a 83 cf fd ; 0xf25e4
+ mov byte [bp+di-068h], al ; 88 43 98 ; 0xf25e8
+ mov al, byte [bp+di-00232h] ; 8a 83 ce fd ; 0xf25eb ata.c:645
+ mov byte [bp+di-067h], al ; 88 43 99 ; 0xf25ef
+ inc si ; 46 ; 0xf25f2 ata.c:646
+ jmp short 025dbh ; eb e6 ; 0xf25f3
+ mov byte [bp-040h], 000h ; c6 46 c0 00 ; 0xf25f5 ata.c:649
+ mov si, strict word 00027h ; be 27 00 ; 0xf25f9 ata.c:650
+ jmp short 02603h ; eb 05 ; 0xf25fc
+ dec si ; 4e ; 0xf25fe ata.c:655
+ test si, si ; 85 f6 ; 0xf25ff
+ jle short 0260fh ; 7e 0c ; 0xf2601
+ cmp byte [bp+si-068h], 020h ; 80 7a 98 20 ; 0xf2603
+ jne short 0260fh ; 75 06 ; 0xf2607
+ mov byte [bp+si-068h], 000h ; c6 42 98 00 ; 0xf2609
+ jmp short 025feh ; eb ef ; 0xf260d
+ mov al, byte [bp-018h] ; 8a 46 e8 ; 0xf260f ata.c:662
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf2612
+ je short 0267ch ; 74 66 ; 0xf2614
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf2616
+ je short 02621h ; 74 07 ; 0xf2618
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf261a
+ je short 02687h ; 74 69 ; 0xf261c
+ jmp near 02716h ; e9 f5 00 ; 0xf261e
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf2621 ata.c:665
+ je short 0262ch ; 74 05 ; 0xf2625
+ mov ax, 0019fh ; b8 9f 01 ; 0xf2627
+ jmp short 0262fh ; eb 03 ; 0xf262a
+ mov ax, 001a6h ; b8 a6 01 ; 0xf262c
+ push ax ; 50 ; 0xf262f
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf2630
+ xor ah, ah ; 30 e4 ; 0xf2633
+ push ax ; 50 ; 0xf2635
+ mov ax, 001adh ; b8 ad 01 ; 0xf2636
+ push ax ; 50 ; 0xf2639
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf263a
+ push ax ; 50 ; 0xf263d
+ call 0190fh ; e8 ce f2 ; 0xf263e
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf2641
+ xor si, si ; 31 f6 ; 0xf2644 ata.c:666
+ mov al, byte [bp+si-068h] ; 8a 42 98 ; 0xf2646 ata.c:667
+ xor ah, ah ; 30 e4 ; 0xf2649
+ inc si ; 46 ; 0xf264b
+ test ax, ax ; 85 c0 ; 0xf264c
+ je short 02661h ; 74 11 ; 0xf264e
+ push ax ; 50 ; 0xf2650 ata.c:668
+ mov ax, 001b8h ; b8 b8 01 ; 0xf2651
+ push ax ; 50 ; 0xf2654
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf2655
+ push ax ; 50 ; 0xf2658
+ call 0190fh ; e8 b3 f2 ; 0xf2659
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf265c
+ jmp short 02646h ; eb e5 ; 0xf265f
+ push word [bp-026h] ; ff 76 da ; 0xf2661 ata.c:669
+ push word [bp-024h] ; ff 76 dc ; 0xf2664
+ mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xf2667
+ push ax ; 50 ; 0xf266a
+ mov ax, 001bbh ; b8 bb 01 ; 0xf266b
+ push ax ; 50 ; 0xf266e
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf266f
+ push ax ; 50 ; 0xf2672
+ call 0190fh ; e8 99 f2 ; 0xf2673
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf2676
+ jmp near 02716h ; e9 9a 00 ; 0xf2679 ata.c:670
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf267c ata.c:672
+ je short 02689h ; 74 07 ; 0xf2680
+ mov ax, 0019fh ; b8 9f 01 ; 0xf2682
+ jmp short 0268ch ; eb 05 ; 0xf2685
+ jmp short 026f3h ; eb 6a ; 0xf2687
+ mov ax, 001a6h ; b8 a6 01 ; 0xf2689
+ push ax ; 50 ; 0xf268c
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf268d
+ xor ah, ah ; 30 e4 ; 0xf2690
+ push ax ; 50 ; 0xf2692
+ mov ax, 001adh ; b8 ad 01 ; 0xf2693
+ push ax ; 50 ; 0xf2696
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf2697
+ push ax ; 50 ; 0xf269a
+ call 0190fh ; e8 71 f2 ; 0xf269b
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf269e
+ xor si, si ; 31 f6 ; 0xf26a1 ata.c:673
+ mov al, byte [bp+si-068h] ; 8a 42 98 ; 0xf26a3 ata.c:674
+ xor ah, ah ; 30 e4 ; 0xf26a6
+ inc si ; 46 ; 0xf26a8
+ test ax, ax ; 85 c0 ; 0xf26a9
+ je short 026beh ; 74 11 ; 0xf26ab
+ push ax ; 50 ; 0xf26ad ata.c:675
+ mov ax, 001b8h ; b8 b8 01 ; 0xf26ae
+ push ax ; 50 ; 0xf26b1
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf26b2
+ push ax ; 50 ; 0xf26b5
+ call 0190fh ; e8 56 f2 ; 0xf26b6
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf26b9
+ jmp short 026a3h ; eb e5 ; 0xf26bc
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf26be ata.c:676
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf26c1
+ imul dx ; f7 ea ; 0xf26c4
+ les bx, [bp-030h] ; c4 5e d0 ; 0xf26c6
+ add bx, ax ; 01 c3 ; 0xf26c9
+ cmp byte [es:bx+023h], 005h ; 26 80 7f 23 05 ; 0xf26cb
+ jne short 026ddh ; 75 0b ; 0xf26d0
+ mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xf26d2 ata.c:677
+ xor ah, ah ; 30 e4 ; 0xf26d5
+ push ax ; 50 ; 0xf26d7
+ mov ax, 001dbh ; b8 db 01 ; 0xf26d8
+ jmp short 026e6h ; eb 09 ; 0xf26db ata.c:678
+ mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xf26dd ata.c:679
+ xor ah, ah ; 30 e4 ; 0xf26e0
+ push ax ; 50 ; 0xf26e2
+ mov ax, 001f5h ; b8 f5 01 ; 0xf26e3
+ push ax ; 50 ; 0xf26e6
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf26e7
+ push ax ; 50 ; 0xf26ea
+ call 0190fh ; e8 21 f2 ; 0xf26eb
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf26ee
+ jmp short 02716h ; eb 23 ; 0xf26f1 ata.c:680
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf26f3 ata.c:682
+ je short 026feh ; 74 05 ; 0xf26f7
+ mov ax, 0019fh ; b8 9f 01 ; 0xf26f9
+ jmp short 02701h ; eb 03 ; 0xf26fc
+ mov ax, 001a6h ; b8 a6 01 ; 0xf26fe
+ push ax ; 50 ; 0xf2701
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf2702
+ xor ah, ah ; 30 e4 ; 0xf2705
+ push ax ; 50 ; 0xf2707
+ mov ax, 00207h ; b8 07 02 ; 0xf2708
+ push ax ; 50 ; 0xf270b
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf270c
+ push ax ; 50 ; 0xf270f
+ call 0190fh ; e8 fc f1 ; 0xf2710
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf2713
+ inc byte [bp-00eh] ; fe 46 f2 ; 0xf2716 ata.c:687
+ cmp byte [bp-00eh], 008h ; 80 7e f2 08 ; 0xf2719
+ jnc short 02772h ; 73 53 ; 0xf271d
+ mov bl, byte [bp-00eh] ; 8a 5e f2 ; 0xf271f
+ xor bh, bh ; 30 ff ; 0xf2722
+ mov ax, bx ; 89 d8 ; 0xf2724
+ cwd ; 99 ; 0xf2726
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf2727
+ sar ax, 1 ; d1 f8 ; 0xf2729
+ mov word [bp-038h], ax ; 89 46 c8 ; 0xf272b
+ mov al, byte [bp-038h] ; 8a 46 c8 ; 0xf272e
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf2731
+ mov ax, bx ; 89 d8 ; 0xf2734
+ cwd ; 99 ; 0xf2736
+ mov bx, strict word 00002h ; bb 02 00 ; 0xf2737
+ idiv bx ; f7 fb ; 0xf273a
+ mov cx, dx ; 89 d1 ; 0xf273c
+ mov byte [bp-008h], dl ; 88 56 f8 ; 0xf273e
+ mov al, byte [bp-038h] ; 8a 46 c8 ; 0xf2741
+ xor ah, ah ; 30 e4 ; 0xf2744
+ mov dx, strict word 00006h ; ba 06 00 ; 0xf2746
+ imul dx ; f7 ea ; 0xf2749
+ les si, [bp-030h] ; c4 76 d0 ; 0xf274b
+ add si, ax ; 01 c6 ; 0xf274e
+ mov bx, word [es:si+00206h] ; 26 8b 9c 06 02 ; 0xf2750
+ mov ax, word [es:si+00208h] ; 26 8b 84 08 02 ; 0xf2755
+ mov word [bp-02ah], ax ; 89 46 d6 ; 0xf275a
+ mov dx, ax ; 89 c2 ; 0xf275d
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf275f
+ mov AL, strict byte 00ah ; b0 0a ; 0xf2762
+ out DX, AL ; ee ; 0xf2764
+ test cl, cl ; 84 c9 ; 0xf2765
+ jne short 0276ch ; 75 03 ; 0xf2767
+ jmp near 02153h ; e9 e7 f9 ; 0xf2769
+ mov ax, 000b0h ; b8 b0 00 ; 0xf276c
+ jmp near 02156h ; e9 e4 f9 ; 0xf276f
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf2772 ata.c:690
+ les bx, [bp-030h] ; c4 5e d0 ; 0xf2775
+ mov byte [es:bx+001e2h], al ; 26 88 87 e2 01 ; 0xf2778
+ mov al, byte [bp-014h] ; 8a 46 ec ; 0xf277d ata.c:691
+ mov byte [es:bx+001f3h], al ; 26 88 87 f3 01 ; 0xf2780
+ mov bx, strict word 00075h ; bb 75 00 ; 0xf2785 ata.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2788
+ mov es, ax ; 8e c0 ; 0xf278b
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf278d
+ mov byte [es:bx], al ; 26 88 07 ; 0xf2790
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf2793 ata.c:704
+ pop di ; 5f ; 0xf2796
+ pop si ; 5e ; 0xf2797
+ pop bp ; 5d ; 0xf2798
+ retn ; c3 ; 0xf2799
+ ; disGetNextSymbol 0xf279a LB 0x77ae -> off=0x0 cb=000000000000028e uValue=00000000000f119a 'ata_cmd_data_out'
+ata_cmd_data_out: ; 0xf279a LB 0x28e
+ push bp ; 55 ; 0xf279a ata.c:718
+ mov bp, sp ; 89 e5 ; 0xf279b
+ push si ; 56 ; 0xf279d
+ push di ; 57 ; 0xf279e
+ sub sp, strict byte 00020h ; 83 ec 20 ; 0xf279f
+ mov di, ax ; 89 c7 ; 0xf27a2
+ mov word [bp-00ah], dx ; 89 56 f6 ; 0xf27a4
+ mov word [bp-01eh], bx ; 89 5e e2 ; 0xf27a7
+ mov word [bp-01ah], cx ; 89 4e e6 ; 0xf27aa
+ mov es, dx ; 8e c2 ; 0xf27ad ata.c:730
+ mov al, byte [es:di+00ch] ; 26 8a 45 0c ; 0xf27af
+ xor ah, ah ; 30 e4 ; 0xf27b3
+ mov dx, ax ; 89 c2 ; 0xf27b5
+ shr ax, 1 ; d1 e8 ; 0xf27b7 ata.c:731
+ and dl, 001h ; 80 e2 01 ; 0xf27b9 ata.c:732
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf27bc
+ xor ah, ah ; 30 e4 ; 0xf27bf ata.c:734
+ mov dx, strict word 00006h ; ba 06 00 ; 0xf27c1
+ imul dx ; f7 ea ; 0xf27c4
+ mov bx, di ; 89 fb ; 0xf27c6
+ add bx, ax ; 01 c3 ; 0xf27c8
+ mov ax, word [es:bx+00206h] ; 26 8b 87 06 02 ; 0xf27ca
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf27cf
+ mov ax, word [es:bx+00208h] ; 26 8b 87 08 02 ; 0xf27d2 ata.c:735
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf27d7
+ mov word [bp-01ch], 00100h ; c7 46 e4 00 01 ; 0xf27da ata.c:743
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf27df ata.c:745
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf27e2
+ in AL, DX ; ec ; 0xf27e5
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf27e6
+ test AL, strict byte 080h ; a8 80 ; 0xf27e8 ata.c:746
+ je short 027fbh ; 74 0f ; 0xf27ea
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf27ec ata.c:749
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf27ef
+ mov AL, strict byte 008h ; b0 08 ; 0xf27f2
+ out DX, AL ; ee ; 0xf27f4
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf27f5 ata.c:750
+ jmp near 02a21h ; e9 26 02 ; 0xf27f8
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf27fb ata.c:753
+ mov ax, word [es:di+006h] ; 26 8b 45 06 ; 0xf27fe
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf2802
+ mov ax, word [es:di+004h] ; 26 8b 45 04 ; 0xf2805
+ mov word [bp-020h], ax ; 89 46 e0 ; 0xf2809
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf280c
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf2810
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf2813
+ mov word [bp-022h], ax ; 89 46 de ; 0xf2816
+ mov ax, word [es:di+008h] ; 26 8b 45 08 ; 0xf2819 ata.c:754
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf281d
+ mov ax, word [es:di+00ah] ; 26 8b 45 0a ; 0xf2820
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf2824
+ mov ax, word [es:di+016h] ; 26 8b 45 16 ; 0xf2827 ata.c:755
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf282b
+ mov ax, word [es:di+012h] ; 26 8b 45 12 ; 0xf282e ata.c:756
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf2832
+ mov ax, word [es:di+014h] ; 26 8b 45 14 ; 0xf2835 ata.c:757
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf2839
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf283c ata.c:760
+ test ax, ax ; 85 c0 ; 0xf283f
+ je short 02846h ; 74 03 ; 0xf2841
+ jmp near 0290dh ; e9 c7 00 ; 0xf2843
+ xor bx, bx ; 31 db ; 0xf2846 ata.c:761
+ xor dx, dx ; 31 d2 ; 0xf2848
+ mov si, word [bp-022h] ; 8b 76 de ; 0xf284a
+ add si, word [bp-01ah] ; 03 76 e6 ; 0xf284d
+ adc bx, word [bp-010h] ; 13 5e f0 ; 0xf2850
+ adc dx, word [bp-020h] ; 13 56 e0 ; 0xf2853
+ adc ax, word [bp-00ch] ; 13 46 f4 ; 0xf2856
+ test ax, ax ; 85 c0 ; 0xf2859
+ jnbe short 0286dh ; 77 10 ; 0xf285b
+ jne short 028d0h ; 75 71 ; 0xf285d
+ test dx, dx ; 85 d2 ; 0xf285f
+ jnbe short 0286dh ; 77 0a ; 0xf2861
+ jne short 028d0h ; 75 6b ; 0xf2863
+ cmp bx, 01000h ; 81 fb 00 10 ; 0xf2865
+ jnbe short 0286dh ; 77 02 ; 0xf2869
+ jne short 028d0h ; 75 63 ; 0xf286b
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf286d ata.c:763
+ mov bx, word [bp-020h] ; 8b 5e e0 ; 0xf2870
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf2873
+ mov dx, word [bp-022h] ; 8b 56 de ; 0xf2876
+ mov si, strict word 00018h ; be 18 00 ; 0xf2879
+ call 09c10h ; e8 91 73 ; 0xf287c
+ xor dh, dh ; 30 f6 ; 0xf287f
+ mov word [bp-014h], dx ; 89 56 ec ; 0xf2881
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf2884 ata.c:764
+ mov bx, word [bp-020h] ; 8b 5e e0 ; 0xf2887
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf288a
+ mov dx, word [bp-022h] ; 8b 56 de ; 0xf288d
+ mov si, strict word 00020h ; be 20 00 ; 0xf2890
+ call 09c10h ; e8 7a 73 ; 0xf2893
+ mov bx, dx ; 89 d3 ; 0xf2896
+ mov word [bp-024h], dx ; 89 56 dc ; 0xf2898
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf289b ata.c:765
+ mov al, ah ; 88 e0 ; 0xf289e
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf28a0
+ inc dx ; 42 ; 0xf28a3
+ inc dx ; 42 ; 0xf28a4
+ out DX, AL ; ee ; 0xf28a5
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf28a6 ata.c:766
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf28a9
+ mov al, byte [bp-014h] ; 8a 46 ec ; 0xf28ac
+ out DX, AL ; ee ; 0xf28af
+ xor bh, bh ; 30 ff ; 0xf28b0 ata.c:767
+ mov ax, bx ; 89 d8 ; 0xf28b2
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf28b4
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf28b7
+ out DX, AL ; ee ; 0xf28ba
+ mov al, byte [bp-023h] ; 8a 46 dd ; 0xf28bb ata.c:768
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf28be
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf28c1
+ out DX, AL ; ee ; 0xf28c4
+ xor al, al ; 30 c0 ; 0xf28c5 ata.c:771
+ mov byte [bp-00fh], bh ; 88 7e f1 ; 0xf28c7
+ mov word [bp-020h], ax ; 89 46 e0 ; 0xf28ca
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf28cd
+ mov ax, word [bp-022h] ; 8b 46 de ; 0xf28d0 ata.c:773
+ xor ah, ah ; 30 e4 ; 0xf28d3
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf28d5
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf28d8 ata.c:774
+ mov bx, word [bp-020h] ; 8b 5e e0 ; 0xf28db
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf28de
+ mov dx, word [bp-022h] ; 8b 56 de ; 0xf28e1
+ mov si, strict word 00008h ; be 08 00 ; 0xf28e4
+ call 09c10h ; e8 26 73 ; 0xf28e7
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf28ea
+ mov word [bp-020h], bx ; 89 5e e0 ; 0xf28ed
+ mov word [bp-010h], cx ; 89 4e f0 ; 0xf28f0
+ mov word [bp-022h], dx ; 89 56 de ; 0xf28f3
+ mov word [bp-024h], dx ; 89 56 dc ; 0xf28f6 ata.c:775
+ mov si, strict word 00010h ; be 10 00 ; 0xf28f9 ata.c:776
+ call 09c10h ; e8 11 73 ; 0xf28fc
+ mov word [bp-022h], dx ; 89 56 de ; 0xf28ff
+ mov ax, dx ; 89 d0 ; 0xf2902 ata.c:777
+ xor ah, dh ; 30 f4 ; 0xf2904
+ and AL, strict byte 00fh ; 24 0f ; 0xf2906
+ or AL, strict byte 040h ; 0c 40 ; 0xf2908
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf290a
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf290d ata.c:780
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2910
+ mov AL, strict byte 00ah ; b0 0a ; 0xf2913
+ out DX, AL ; ee ; 0xf2915
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2916 ata.c:781
+ inc dx ; 42 ; 0xf2919
+ xor al, al ; 30 c0 ; 0xf291a
+ out DX, AL ; ee ; 0xf291c
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf291d ata.c:782
+ inc dx ; 42 ; 0xf2920
+ inc dx ; 42 ; 0xf2921
+ mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xf2922
+ out DX, AL ; ee ; 0xf2925
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2926 ata.c:783
+ add dx, strict byte 00003h ; 83 c2 03 ; 0xf2929
+ mov al, byte [bp-014h] ; 8a 46 ec ; 0xf292c
+ out DX, AL ; ee ; 0xf292f
+ mov ax, word [bp-024h] ; 8b 46 dc ; 0xf2930 ata.c:784
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2933
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf2936
+ out DX, AL ; ee ; 0xf2939
+ mov al, byte [bp-023h] ; 8a 46 dd ; 0xf293a ata.c:785
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf293d
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf2940
+ out DX, AL ; ee ; 0xf2943
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf2944 ata.c:786
+ je short 0294fh ; 74 05 ; 0xf2948
+ mov ax, 000b0h ; b8 b0 00 ; 0xf294a
+ jmp short 02952h ; eb 03 ; 0xf294d
+ mov ax, 000a0h ; b8 a0 00 ; 0xf294f
+ mov dl, byte [bp-018h] ; 8a 56 e8 ; 0xf2952
+ xor dh, dh ; 30 f6 ; 0xf2955
+ or ax, dx ; 09 d0 ; 0xf2957
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2959
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf295c
+ out DX, AL ; ee ; 0xf295f
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2960 ata.c:787
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2963
+ mov al, byte [bp-01eh] ; 8a 46 e2 ; 0xf2966
+ out DX, AL ; ee ; 0xf2969
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf296a ata.c:790
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf296d
+ in AL, DX ; ec ; 0xf2970
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2971
+ mov bl, al ; 88 c3 ; 0xf2973
+ test AL, strict byte 080h ; a8 80 ; 0xf2975 ata.c:791
+ jne short 0296ah ; 75 f1 ; 0xf2977
+ test AL, strict byte 001h ; a8 01 ; 0xf2979 ata.c:795
+ je short 0298ch ; 74 0f ; 0xf297b
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf297d ata.c:798
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2980
+ mov AL, strict byte 008h ; b0 08 ; 0xf2983
+ out DX, AL ; ee ; 0xf2985
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf2986 ata.c:799
+ jmp near 02a21h ; e9 95 00 ; 0xf2989
+ test bl, 008h ; f6 c3 08 ; 0xf298c ata.c:800
+ jne short 029a0h ; 75 0f ; 0xf298f
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf2991 ata.c:803
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2994
+ mov AL, strict byte 008h ; b0 08 ; 0xf2997
+ out DX, AL ; ee ; 0xf2999
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf299a ata.c:804
+ jmp near 02a21h ; e9 81 00 ; 0xf299d
+ sti ; fb ; 0xf29a0 ata.c:809
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf29a1 ata.c:814
+ cmp ax, 0f800h ; 3d 00 f8 ; 0xf29a4
+ jc short 029bbh ; 72 12 ; 0xf29a7
+ mov dx, ax ; 89 c2 ; 0xf29a9 ata.c:815
+ sub dx, 00800h ; 81 ea 00 08 ; 0xf29ab
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf29af
+ add ax, 00080h ; 05 80 00 ; 0xf29b2
+ mov word [bp-016h], dx ; 89 56 ea ; 0xf29b5
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf29b8
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf29bb ata.c:822
+ mov cx, word [bp-01ch] ; 8b 4e e4 ; 0xf29be
+ mov si, word [bp-016h] ; 8b 76 ea ; 0xf29c1
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf29c4
+ db 0f3h, 026h, 06fh
+ ; rep es outsw ; f3 26 6f ; 0xf29c7
+ mov word [bp-016h], si ; 89 76 ea ; 0xf29ca
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf29cd ata.c:824
+ inc word [es:di+018h] ; 26 ff 45 18 ; 0xf29d0
+ dec word [bp-01ah] ; ff 4e e6 ; 0xf29d4 ata.c:825
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf29d7 ata.c:827
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf29da
+ in AL, DX ; ec ; 0xf29dd
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf29de
+ mov bl, al ; 88 c3 ; 0xf29e0
+ test AL, strict byte 080h ; a8 80 ; 0xf29e2 ata.c:828
+ jne short 029d7h ; 75 f1 ; 0xf29e4
+ cmp word [bp-01ah], strict byte 00000h ; 83 7e e6 00 ; 0xf29e6 ata.c:831
+ jne short 02a00h ; 75 14 ; 0xf29ea
+ and AL, strict byte 0e9h ; 24 e9 ; 0xf29ec ata.c:832
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf29ee
+ je short 02a16h ; 74 24 ; 0xf29f0
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf29f2 ata.c:836
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf29f5
+ mov AL, strict byte 008h ; b0 08 ; 0xf29f8
+ out DX, AL ; ee ; 0xf29fa
+ mov ax, strict word 00006h ; b8 06 00 ; 0xf29fb ata.c:837
+ jmp short 02a21h ; eb 21 ; 0xf29fe
+ mov al, bl ; 88 d8 ; 0xf2a00 ata.c:842
+ and AL, strict byte 0c9h ; 24 c9 ; 0xf2a02
+ cmp AL, strict byte 048h ; 3c 48 ; 0xf2a04
+ je short 029a1h ; 74 99 ; 0xf2a06
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf2a08 ata.c:846
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2a0b
+ mov AL, strict byte 008h ; b0 08 ; 0xf2a0e
+ out DX, AL ; ee ; 0xf2a10
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf2a11 ata.c:847
+ jmp short 02a21h ; eb 0b ; 0xf2a14
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf2a16 ata.c:853
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2a19
+ mov AL, strict byte 008h ; b0 08 ; 0xf2a1c
+ out DX, AL ; ee ; 0xf2a1e
+ xor ax, ax ; 31 c0 ; 0xf2a1f ata.c:854
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf2a21 ata.c:855
+ pop di ; 5f ; 0xf2a24
+ pop si ; 5e ; 0xf2a25
+ pop bp ; 5d ; 0xf2a26
+ retn ; c3 ; 0xf2a27
+ ; disGetNextSymbol 0xf2a28 LB 0x7520 -> off=0x0 cb=00000000000000c1 uValue=00000000000f1428 'ata_read_sectors'
+ata_read_sectors: ; 0xf2a28 LB 0xc1
+ push bp ; 55 ; 0xf2a28 ata.c:865
+ mov bp, sp ; 89 e5 ; 0xf2a29
+ push si ; 56 ; 0xf2a2b
+ push di ; 57 ; 0xf2a2c
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf2a2d
+ mov si, word [bp+004h] ; 8b 76 04 ; 0xf2a30
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf2a33 ata.c:871
+ mov al, byte [es:si+00ch] ; 26 8a 44 0c ; 0xf2a36
+ mov bx, word [es:si+00eh] ; 26 8b 5c 0e ; 0xf2a3a ata.c:872
+ mov CL, strict byte 009h ; b1 09 ; 0xf2a3e
+ mov dx, bx ; 89 da ; 0xf2a40
+ sal dx, CL ; d3 e2 ; 0xf2a42
+ mov cx, dx ; 89 d1 ; 0xf2a44
+ cmp word [es:si+016h], strict byte 00000h ; 26 83 7c 16 00 ; 0xf2a46 ata.c:874
+ je short 02a70h ; 74 23 ; 0xf2a4b
+ xor ah, ah ; 30 e4 ; 0xf2a4d ata.c:876
+ mov di, strict word 0001ch ; bf 1c 00 ; 0xf2a4f
+ imul di ; f7 ef ; 0xf2a52
+ mov dx, es ; 8c c2 ; 0xf2a54
+ mov [bp-00ah], es ; 8c 46 f6 ; 0xf2a56
+ mov di, si ; 89 f7 ; 0xf2a59
+ add di, ax ; 01 c7 ; 0xf2a5b
+ mov word [es:di+028h], cx ; 26 89 4d 28 ; 0xf2a5d
+ mov cx, bx ; 89 d9 ; 0xf2a61 ata.c:878
+ mov bx, 000c4h ; bb c4 00 ; 0xf2a63
+ mov ax, si ; 89 f0 ; 0xf2a66
+ call 01e38h ; e8 cd f3 ; 0xf2a68
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf2a6b ata.c:879
+ jmp short 02adah ; eb 6a ; 0xf2a6e ata.c:880
+ xor di, di ; 31 ff ; 0xf2a70 ata.c:882
+ mov word [bp-008h], di ; 89 7e f8 ; 0xf2a72
+ mov word [bp-00ah], di ; 89 7e f6 ; 0xf2a75
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf2a78
+ add dx, bx ; 01 da ; 0xf2a7b
+ mov word [bp-006h], dx ; 89 56 fa ; 0xf2a7d
+ adc di, word [es:si+002h] ; 26 13 7c 02 ; 0xf2a80
+ mov dx, word [es:si+004h] ; 26 8b 54 04 ; 0xf2a84
+ adc dx, word [bp-008h] ; 13 56 f8 ; 0xf2a88
+ mov word [bp-008h], dx ; 89 56 f8 ; 0xf2a8b
+ mov dx, word [es:si+006h] ; 26 8b 54 06 ; 0xf2a8e
+ adc dx, word [bp-00ah] ; 13 56 f6 ; 0xf2a92
+ test dx, dx ; 85 d2 ; 0xf2a95
+ jnbe short 02aabh ; 77 12 ; 0xf2a97
+ jne short 02ab9h ; 75 1e ; 0xf2a99
+ cmp word [bp-008h], strict byte 00000h ; 83 7e f8 00 ; 0xf2a9b
+ jnbe short 02aabh ; 77 0a ; 0xf2a9f
+ jne short 02ab9h ; 75 16 ; 0xf2aa1
+ cmp di, 01000h ; 81 ff 00 10 ; 0xf2aa3
+ jnbe short 02aabh ; 77 02 ; 0xf2aa7
+ jne short 02ab9h ; 75 0e ; 0xf2aa9
+ mov cx, bx ; 89 d9 ; 0xf2aab ata.c:884
+ mov bx, strict word 00024h ; bb 24 00 ; 0xf2aad
+ mov ax, si ; 89 f0 ; 0xf2ab0
+ mov dx, es ; 8c c2 ; 0xf2ab2
+ call 01e38h ; e8 81 f3 ; 0xf2ab4
+ jmp short 02ae0h ; eb 27 ; 0xf2ab7 ata.c:885
+ xor ah, ah ; 30 e4 ; 0xf2ab9 ata.c:886
+ mov di, strict word 0001ch ; bf 1c 00 ; 0xf2abb
+ imul di ; f7 ef ; 0xf2abe
+ mov dx, es ; 8c c2 ; 0xf2ac0
+ mov [bp-006h], es ; 8c 46 fa ; 0xf2ac2
+ mov di, si ; 89 f7 ; 0xf2ac5
+ add di, ax ; 01 c7 ; 0xf2ac7
+ mov word [es:di+028h], cx ; 26 89 4d 28 ; 0xf2ac9
+ mov cx, bx ; 89 d9 ; 0xf2acd ata.c:888
+ mov bx, 000c4h ; bb c4 00 ; 0xf2acf
+ mov ax, si ; 89 f0 ; 0xf2ad2
+ call 01e38h ; e8 61 f3 ; 0xf2ad4
+ mov es, [bp-006h] ; 8e 46 fa ; 0xf2ad7 ata.c:889
+ mov word [es:di+028h], 00200h ; 26 c7 45 28 00 02 ; 0xf2ada
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf2ae0 ata.c:893
+ pop di ; 5f ; 0xf2ae3
+ pop si ; 5e ; 0xf2ae4
+ pop bp ; 5d ; 0xf2ae5
+ retn 00004h ; c2 04 00 ; 0xf2ae6
+ ; disGetNextSymbol 0xf2ae9 LB 0x745f -> off=0x0 cb=000000000000005b uValue=00000000000f14e9 'ata_write_sectors'
+ata_write_sectors: ; 0xf2ae9 LB 0x5b
+ push bp ; 55 ; 0xf2ae9 ata.c:902
+ mov bp, sp ; 89 e5 ; 0xf2aea
+ push si ; 56 ; 0xf2aec
+ push di ; 57 ; 0xf2aed
+ push ax ; 50 ; 0xf2aee
+ les si, [bp+004h] ; c4 76 04 ; 0xf2aef
+ mov cx, word [es:si+00eh] ; 26 8b 4c 0e ; 0xf2af2 ata.c:906
+ cmp word [es:si+016h], strict byte 00000h ; 26 83 7c 16 00 ; 0xf2af6 ata.c:908
+ je short 02b09h ; 74 0c ; 0xf2afb
+ mov bx, strict word 00030h ; bb 30 00 ; 0xf2afd ata.c:910
+ mov ax, si ; 89 f0 ; 0xf2b00
+ mov dx, es ; 8c c2 ; 0xf2b02
+ call 0279ah ; e8 93 fc ; 0xf2b04
+ jmp short 02b3bh ; eb 32 ; 0xf2b07
+ xor ax, ax ; 31 c0 ; 0xf2b09 ata.c:913
+ xor bx, bx ; 31 db ; 0xf2b0b
+ xor dx, dx ; 31 d2 ; 0xf2b0d
+ mov di, word [es:si] ; 26 8b 3c ; 0xf2b0f
+ add di, cx ; 01 cf ; 0xf2b12
+ mov word [bp-006h], di ; 89 7e fa ; 0xf2b14
+ adc ax, word [es:si+002h] ; 26 13 44 02 ; 0xf2b17
+ adc bx, word [es:si+004h] ; 26 13 5c 04 ; 0xf2b1b
+ adc dx, word [es:si+006h] ; 26 13 54 06 ; 0xf2b1f
+ test dx, dx ; 85 d2 ; 0xf2b23
+ jnbe short 02b36h ; 77 0f ; 0xf2b25
+ jne short 02afdh ; 75 d4 ; 0xf2b27
+ test bx, bx ; 85 db ; 0xf2b29
+ jnbe short 02b36h ; 77 09 ; 0xf2b2b
+ jne short 02afdh ; 75 ce ; 0xf2b2d
+ cmp ax, 01000h ; 3d 00 10 ; 0xf2b2f
+ jnbe short 02b36h ; 77 02 ; 0xf2b32
+ jne short 02afdh ; 75 c7 ; 0xf2b34
+ mov bx, strict word 00034h ; bb 34 00 ; 0xf2b36 ata.c:914
+ jmp short 02b00h ; eb c5 ; 0xf2b39
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf2b3b ata.c:918
+ pop di ; 5f ; 0xf2b3e
+ pop si ; 5e ; 0xf2b3f
+ pop bp ; 5d ; 0xf2b40
+ retn 00004h ; c2 04 00 ; 0xf2b41
+ ; disGetNextSymbol 0xf2b44 LB 0x7404 -> off=0x0 cb=0000000000000295 uValue=00000000000f1544 'ata_cmd_packet'
+ata_cmd_packet: ; 0xf2b44 LB 0x295
+ push bp ; 55 ; 0xf2b44 ata.c:930
+ mov bp, sp ; 89 e5 ; 0xf2b45
+ push si ; 56 ; 0xf2b47
+ push di ; 57 ; 0xf2b48
+ sub sp, strict byte 00010h ; 83 ec 10 ; 0xf2b49
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf2b4c
+ mov si, bx ; 89 de ; 0xf2b4f
+ mov di, cx ; 89 cf ; 0xf2b51
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf2b53 ata.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf2b56
+ mov es, dx ; 8e c2 ; 0xf2b59
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf2b5b
+ mov word [bp-00ah], 00122h ; c7 46 f6 22 01 ; 0xf2b5e ata.c:49
+ mov word [bp-010h], dx ; 89 56 f0 ; 0xf2b63
+ mov dx, ax ; 89 c2 ; 0xf2b66 ata.c:942
+ shr dx, 1 ; d1 ea ; 0xf2b68
+ mov ah, dl ; 88 d4 ; 0xf2b6a
+ mov cl, al ; 88 c1 ; 0xf2b6c ata.c:943
+ and cl, 001h ; 80 e1 01 ; 0xf2b6e
+ cmp byte [bp+00ah], 002h ; 80 7e 0a 02 ; 0xf2b71 ata.c:946
+ jne short 02b9ah ; 75 23 ; 0xf2b75
+ mov bx, 00da0h ; bb a0 0d ; 0xf2b77 ata.c:947
+ mov cx, ds ; 8c d9 ; 0xf2b7a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf2b7c
+ call 018cch ; e8 4a ed ; 0xf2b7f
+ mov ax, 00221h ; b8 21 02 ; 0xf2b82
+ push ax ; 50 ; 0xf2b85
+ mov ax, 00230h ; b8 30 02 ; 0xf2b86
+ push ax ; 50 ; 0xf2b89
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf2b8a
+ push ax ; 50 ; 0xf2b8d
+ call 0190fh ; e8 7e ed ; 0xf2b8e
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf2b91
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf2b94 ata.c:948
+ jmp near 02dd0h ; e9 36 02 ; 0xf2b97
+ test byte [bp+004h], 001h ; f6 46 04 01 ; 0xf2b9a ata.c:952
+ jne short 02b94h ; 75 f4 ; 0xf2b9e
+ mov al, ah ; 88 e0 ; 0xf2ba0 ata.c:957
+ xor ah, ah ; 30 e4 ; 0xf2ba2
+ mov dx, strict word 00006h ; ba 06 00 ; 0xf2ba4
+ imul dx ; f7 ea ; 0xf2ba7
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf2ba9
+ mov bx, word [bp-00ah] ; 8b 5e f6 ; 0xf2bac
+ add bx, ax ; 01 c3 ; 0xf2baf
+ mov ax, word [es:bx+00206h] ; 26 8b 87 06 02 ; 0xf2bb1
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf2bb6
+ mov ax, word [es:bx+00208h] ; 26 8b 87 08 02 ; 0xf2bb9 ata.c:958
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf2bbe
+ xor ax, ax ; 31 c0 ; 0xf2bc1 ata.c:960
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf2bc3
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf2bc6
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf2bc9 ata.c:962
+ cmp AL, strict byte 00ch ; 3c 0c ; 0xf2bcc
+ jnc short 02bd6h ; 73 06 ; 0xf2bce
+ mov byte [bp-006h], 00ch ; c6 46 fa 0c ; 0xf2bd0 ata.c:963
+ jmp short 02bdch ; eb 06 ; 0xf2bd4
+ jbe short 02bdch ; 76 04 ; 0xf2bd6 ata.c:964
+ mov byte [bp-006h], 010h ; c6 46 fa 10 ; 0xf2bd8 ata.c:965
+ shr byte [bp-006h], 1 ; d0 6e fa ; 0xf2bdc ata.c:966
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf2bdf ata.c:970
+ mov bx, word [bp-00ah] ; 8b 5e f6 ; 0xf2be2
+ mov word [es:bx+018h], strict word 00000h ; 26 c7 47 18 00 00 ; 0xf2be5
+ mov word [es:bx+01ah], strict word 00000h ; 26 c7 47 1a 00 00 ; 0xf2beb ata.c:971
+ mov word [es:bx+01ch], strict word 00000h ; 26 c7 47 1c 00 00 ; 0xf2bf1
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf2bf7 ata.c:973
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2bfa
+ in AL, DX ; ec ; 0xf2bfd
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2bfe
+ test AL, strict byte 080h ; a8 80 ; 0xf2c00 ata.c:974
+ je short 02c0ah ; 74 06 ; 0xf2c02
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf2c04 ata.c:975
+ jmp near 02dd0h ; e9 c6 01 ; 0xf2c07
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2c0a ata.c:977
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2c0d
+ mov AL, strict byte 00ah ; b0 0a ; 0xf2c10
+ out DX, AL ; ee ; 0xf2c12
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf2c13 ata.c:981
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf2c16
+ mov AL, strict byte 0f0h ; b0 f0 ; 0xf2c19
+ out DX, AL ; ee ; 0xf2c1b
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf2c1c ata.c:982
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf2c1f
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf2c22
+ out DX, AL ; ee ; 0xf2c24
+ test cl, cl ; 84 c9 ; 0xf2c25 ata.c:983
+ je short 02c2eh ; 74 05 ; 0xf2c27
+ mov ax, 000b0h ; b8 b0 00 ; 0xf2c29
+ jmp short 02c31h ; eb 03 ; 0xf2c2c
+ mov ax, 000a0h ; b8 a0 00 ; 0xf2c2e
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf2c31
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2c34
+ out DX, AL ; ee ; 0xf2c37
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf2c38 ata.c:984
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2c3b
+ mov AL, strict byte 0a0h ; b0 a0 ; 0xf2c3e
+ out DX, AL ; ee ; 0xf2c40
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf2c41 ata.c:988
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2c44
+ in AL, DX ; ec ; 0xf2c47
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2c48
+ mov bl, al ; 88 c3 ; 0xf2c4a
+ test AL, strict byte 080h ; a8 80 ; 0xf2c4c ata.c:989
+ jne short 02c41h ; 75 f1 ; 0xf2c4e
+ test AL, strict byte 001h ; a8 01 ; 0xf2c50 ata.c:992
+ je short 02c63h ; 74 0f ; 0xf2c52
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2c54 ata.c:995
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2c57
+ mov AL, strict byte 008h ; b0 08 ; 0xf2c5a
+ out DX, AL ; ee ; 0xf2c5c
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf2c5d ata.c:996
+ jmp near 02dd0h ; e9 6d 01 ; 0xf2c60
+ test bl, 008h ; f6 c3 08 ; 0xf2c63 ata.c:997
+ jne short 02c77h ; 75 0f ; 0xf2c66
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2c68 ata.c:1000
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2c6b
+ mov AL, strict byte 008h ; b0 08 ; 0xf2c6e
+ out DX, AL ; ee ; 0xf2c70
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf2c71 ata.c:1001
+ jmp near 02dd0h ; e9 59 01 ; 0xf2c74
+ sti ; fb ; 0xf2c77 ata.c:1004
+ mov CL, strict byte 004h ; b1 04 ; 0xf2c78 ata.c:1008
+ mov ax, si ; 89 f0 ; 0xf2c7a
+ shr ax, CL ; d3 e8 ; 0xf2c7c
+ add di, ax ; 01 c7 ; 0xf2c7e
+ and si, strict byte 0000fh ; 83 e6 0f ; 0xf2c80
+ mov cl, byte [bp-006h] ; 8a 4e fa ; 0xf2c83 ata.c:1013
+ xor ch, ch ; 30 ed ; 0xf2c86
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf2c88
+ mov es, di ; 8e c7 ; 0xf2c8b
+ db 0f3h, 026h, 06fh
+ ; rep es outsw ; f3 26 6f ; 0xf2c8d
+ cmp byte [bp+00ah], 000h ; 80 7e 0a 00 ; 0xf2c90 ata.c:1015
+ jne short 02ca1h ; 75 0b ; 0xf2c94
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2c96 ata.c:1016
+ in AL, DX ; ec ; 0xf2c99
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2c9a
+ mov bl, al ; 88 c3 ; 0xf2c9c
+ jmp near 02db1h ; e9 10 01 ; 0xf2c9e ata.c:1018
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf2ca1 ata.c:1022
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2ca4
+ in AL, DX ; ec ; 0xf2ca7
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2ca8
+ mov bl, al ; 88 c3 ; 0xf2caa
+ test AL, strict byte 080h ; a8 80 ; 0xf2cac ata.c:1023
+ jne short 02ca1h ; 75 f1 ; 0xf2cae
+ test AL, strict byte 088h ; a8 88 ; 0xf2cb0 ata.c:1028
+ je short 02d14h ; 74 60 ; 0xf2cb2
+ test AL, strict byte 001h ; a8 01 ; 0xf2cb4 ata.c:1031
+ je short 02cc3h ; 74 0b ; 0xf2cb6
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2cb8 ata.c:1034
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2cbb
+ mov AL, strict byte 008h ; b0 08 ; 0xf2cbe
+ out DX, AL ; ee ; 0xf2cc0
+ jmp short 02c5dh ; eb 9a ; 0xf2cc1
+ mov al, bl ; 88 d8 ; 0xf2cc3 ata.c:1039
+ and AL, strict byte 0c9h ; 24 c9 ; 0xf2cc5
+ cmp AL, strict byte 048h ; 3c 48 ; 0xf2cc7
+ je short 02cd6h ; 74 0b ; 0xf2cc9
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2ccb ata.c:1043
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2cce
+ mov AL, strict byte 008h ; b0 08 ; 0xf2cd1
+ out DX, AL ; ee ; 0xf2cd3
+ jmp short 02c71h ; eb 9b ; 0xf2cd4
+ mov CL, strict byte 004h ; b1 04 ; 0xf2cd6 ata.c:1049
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf2cd8
+ shr ax, CL ; d3 e8 ; 0xf2cdb
+ add ax, word [bp+00eh] ; 03 46 0e ; 0xf2cdd
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf2ce0
+ and dx, strict byte 0000fh ; 83 e2 0f ; 0xf2ce3
+ mov word [bp+00ch], dx ; 89 56 0c ; 0xf2ce6
+ mov word [bp+00eh], ax ; 89 46 0e ; 0xf2ce9
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf2cec ata.c:1054
+ add dx, strict byte 00005h ; 83 c2 05 ; 0xf2cef
+ in AL, DX ; ec ; 0xf2cf2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2cf3
+ mov bh, al ; 88 c7 ; 0xf2cf5
+ xor bl, bl ; 30 db ; 0xf2cf7
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf2cf9
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf2cfc
+ in AL, DX ; ec ; 0xf2cff
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2d00
+ add bx, ax ; 01 c3 ; 0xf2d02
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf2d04 ata.c:1057
+ cmp bx, ax ; 39 c3 ; 0xf2d07
+ jnc short 02d17h ; 73 0c ; 0xf2d09
+ mov cx, bx ; 89 d9 ; 0xf2d0b ata.c:1058
+ sub word [bp+004h], bx ; 29 5e 04 ; 0xf2d0d ata.c:1059
+ xor bx, bx ; 31 db ; 0xf2d10 ata.c:1060
+ jmp short 02d20h ; eb 0c ; 0xf2d12 ata.c:1062
+ jmp near 02db1h ; e9 9a 00 ; 0xf2d14
+ mov cx, ax ; 89 c1 ; 0xf2d17 ata.c:1063
+ mov word [bp+004h], strict word 00000h ; c7 46 04 00 00 ; 0xf2d19 ata.c:1064
+ sub bx, ax ; 29 c3 ; 0xf2d1e ata.c:1065
+ xor ax, ax ; 31 c0 ; 0xf2d20 ata.c:1068
+ cmp word [bp+008h], strict byte 00000h ; 83 7e 08 00 ; 0xf2d22
+ jne short 02d3eh ; 75 16 ; 0xf2d26
+ cmp bx, word [bp+006h] ; 3b 5e 06 ; 0xf2d28
+ jbe short 02d3eh ; 76 11 ; 0xf2d2b
+ sub bx, word [bp+006h] ; 2b 5e 06 ; 0xf2d2d ata.c:1069
+ mov word [bp-012h], bx ; 89 5e ee ; 0xf2d30
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf2d33 ata.c:1070
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf2d36 ata.c:1071
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf2d39
+ jmp short 02d47h ; eb 09 ; 0xf2d3c ata.c:1073
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf2d3e ata.c:1074
+ sub word [bp+006h], bx ; 29 5e 06 ; 0xf2d41 ata.c:1075
+ sbb word [bp+008h], ax ; 19 46 08 ; 0xf2d44
+ mov si, bx ; 89 de ; 0xf2d47 ata.c:1079
+ test cl, 003h ; f6 c1 03 ; 0xf2d49 ata.c:1086
+ test bl, 003h ; f6 c3 03 ; 0xf2d4c ata.c:1088
+ test byte [bp-012h], 003h ; f6 46 ee 03 ; 0xf2d4f ata.c:1090
+ test bl, 001h ; f6 c3 01 ; 0xf2d53 ata.c:1094
+ je short 02d68h ; 74 10 ; 0xf2d56
+ inc bx ; 43 ; 0xf2d58 ata.c:1095
+ cmp word [bp-012h], strict byte 00000h ; 83 7e ee 00 ; 0xf2d59 ata.c:1096
+ jbe short 02d68h ; 76 09 ; 0xf2d5d
+ test byte [bp-012h], 001h ; f6 46 ee 01 ; 0xf2d5f
+ je short 02d68h ; 74 03 ; 0xf2d63
+ dec word [bp-012h] ; ff 4e ee ; 0xf2d65 ata.c:1097
+ shr bx, 1 ; d1 eb ; 0xf2d68 ata.c:1109
+ shr cx, 1 ; d1 e9 ; 0xf2d6a ata.c:1110
+ shr word [bp-012h], 1 ; d1 6e ee ; 0xf2d6c ata.c:1111
+ test cx, cx ; 85 c9 ; 0xf2d6f ata.c:1124
+ je short 02d79h ; 74 06 ; 0xf2d71
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf2d73 ata.c:1125
+ in ax, DX ; ed ; 0xf2d76
+ loop 02d76h ; e2 fd ; 0xf2d77
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf2d79 ata.c:1126
+ mov cx, bx ; 89 d9 ; 0xf2d7c
+ les di, [bp+00ch] ; c4 7e 0c ; 0xf2d7e
+ rep insw ; f3 6d ; 0xf2d81
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf2d83 ata.c:1127
+ test ax, ax ; 85 c0 ; 0xf2d86
+ je short 02d8fh ; 74 05 ; 0xf2d88
+ mov cx, ax ; 89 c1 ; 0xf2d8a ata.c:1128
+ in ax, DX ; ed ; 0xf2d8c
+ loop 02d8ch ; e2 fd ; 0xf2d8d
+ add word [bp+00ch], si ; 01 76 0c ; 0xf2d8f ata.c:1133
+ xor ax, ax ; 31 c0 ; 0xf2d92 ata.c:1136
+ add word [bp-00eh], si ; 01 76 f2 ; 0xf2d94
+ adc word [bp-00ch], ax ; 11 46 f4 ; 0xf2d97
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf2d9a ata.c:1137
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf2d9d
+ mov bx, word [bp-00ah] ; 8b 5e f6 ; 0xf2da0
+ mov word [es:bx+01ah], ax ; 26 89 47 1a ; 0xf2da3
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf2da7
+ mov word [es:bx+01ch], ax ; 26 89 47 1c ; 0xf2daa
+ jmp near 02ca1h ; e9 f0 fe ; 0xf2dae ata.c:1138
+ mov al, bl ; 88 d8 ; 0xf2db1 ata.c:1142
+ and AL, strict byte 0e9h ; 24 e9 ; 0xf2db3
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf2db5
+ je short 02dc5h ; 74 0c ; 0xf2db7
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2db9 ata.c:1146
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2dbc
+ mov AL, strict byte 008h ; b0 08 ; 0xf2dbf
+ out DX, AL ; ee ; 0xf2dc1
+ jmp near 02c71h ; e9 ac fe ; 0xf2dc2
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf2dc5 ata.c:1151
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2dc8
+ mov AL, strict byte 008h ; b0 08 ; 0xf2dcb
+ out DX, AL ; ee ; 0xf2dcd
+ xor ax, ax ; 31 c0 ; 0xf2dce ata.c:1152
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf2dd0 ata.c:1153
+ pop di ; 5f ; 0xf2dd3
+ pop si ; 5e ; 0xf2dd4
+ pop bp ; 5d ; 0xf2dd5
+ retn 0000ch ; c2 0c 00 ; 0xf2dd6
+ ; disGetNextSymbol 0xf2dd9 LB 0x716f -> off=0x0 cb=0000000000000083 uValue=00000000000f17d9 'ata_soft_reset'
+ata_soft_reset: ; 0xf2dd9 LB 0x83
+ push bp ; 55 ; 0xf2dd9 ata.c:1161
+ mov bp, sp ; 89 e5 ; 0xf2dda
+ push bx ; 53 ; 0xf2ddc
+ push cx ; 51 ; 0xf2ddd
+ push dx ; 52 ; 0xf2dde
+ push ax ; 50 ; 0xf2ddf
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf2de0 ata.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf2de3
+ mov es, dx ; 8e c2 ; 0xf2de6
+ mov es, [es:bx] ; 26 8e 07 ; 0xf2de8
+ mov dx, ax ; 89 c2 ; 0xf2deb ata.c:1170
+ shr dx, 1 ; d1 ea ; 0xf2ded
+ and AL, strict byte 001h ; 24 01 ; 0xf2def ata.c:1171
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf2df1
+ mov al, dl ; 88 d0 ; 0xf2df4 ata.c:1173
+ xor ah, ah ; 30 e4 ; 0xf2df6
+ mov dx, strict word 00006h ; ba 06 00 ; 0xf2df8
+ imul dx ; f7 ea ; 0xf2dfb
+ mov bx, ax ; 89 c3 ; 0xf2dfd
+ add bx, 00122h ; 81 c3 22 01 ; 0xf2dff
+ mov cx, word [es:bx+00206h] ; 26 8b 8f 06 02 ; 0xf2e03
+ mov bx, word [es:bx+00208h] ; 26 8b 9f 08 02 ; 0xf2e08 ata.c:1174
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf2e0d ata.c:1177
+ mov AL, strict byte 00ah ; b0 0a ; 0xf2e10
+ out DX, AL ; ee ; 0xf2e12
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf2e13 ata.c:1178
+ je short 02e1eh ; 74 05 ; 0xf2e17
+ mov ax, 000b0h ; b8 b0 00 ; 0xf2e19
+ jmp short 02e21h ; eb 03 ; 0xf2e1c
+ mov ax, 000a0h ; b8 a0 00 ; 0xf2e1e
+ mov dx, cx ; 89 ca ; 0xf2e21
+ add dx, strict byte 00006h ; 83 c2 06 ; 0xf2e23
+ out DX, AL ; ee ; 0xf2e26
+ mov dx, cx ; 89 ca ; 0xf2e27 ata.c:1179
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2e29
+ mov AL, strict byte 008h ; b0 08 ; 0xf2e2c
+ out DX, AL ; ee ; 0xf2e2e
+ mov dx, cx ; 89 ca ; 0xf2e2f ata.c:1183
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf2e31
+ in AL, DX ; ec ; 0xf2e34
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2e35
+ test AL, strict byte 080h ; a8 80 ; 0xf2e37 ata.c:1184
+ jne short 02e2fh ; 75 f4 ; 0xf2e39
+ and AL, strict byte 0e9h ; 24 e9 ; 0xf2e3b ata.c:1188
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf2e3d
+ je short 02e4ch ; 74 0b ; 0xf2e3f
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf2e41 ata.c:1192
+ mov AL, strict byte 008h ; b0 08 ; 0xf2e44
+ out DX, AL ; ee ; 0xf2e46
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf2e47 ata.c:1193
+ jmp short 02e54h ; eb 08 ; 0xf2e4a
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf2e4c ata.c:1197
+ mov AL, strict byte 008h ; b0 08 ; 0xf2e4f
+ out DX, AL ; ee ; 0xf2e51
+ xor ax, ax ; 31 c0 ; 0xf2e52 ata.c:1198
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf2e54 ata.c:1199
+ pop dx ; 5a ; 0xf2e57
+ pop cx ; 59 ; 0xf2e58
+ pop bx ; 5b ; 0xf2e59
+ pop bp ; 5d ; 0xf2e5a
+ retn ; c3 ; 0xf2e5b
+ ; disGetNextSymbol 0xf2e5c LB 0x70ec -> off=0x0 cb=000000000000002c uValue=00000000000f185c 'set_diskette_current_cyl'
+set_diskette_current_cyl: ; 0xf2e5c LB 0x2c
+ push bp ; 55 ; 0xf2e5c floppy.c:71
+ mov bp, sp ; 89 e5 ; 0xf2e5d
+ push bx ; 53 ; 0xf2e5f
+ mov bl, al ; 88 c3 ; 0xf2e60
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf2e62 floppy.c:73
+ jbe short 02e74h ; 76 0e ; 0xf2e64
+ mov ax, 00250h ; b8 50 02 ; 0xf2e66 floppy.c:74
+ push ax ; 50 ; 0xf2e69
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf2e6a
+ push ax ; 50 ; 0xf2e6d
+ call 0190fh ; e8 9e ea ; 0xf2e6e
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf2e71
+ xor bh, bh ; 30 ff ; 0xf2e74 floppy.c:75
+ add bx, 00094h ; 81 c3 94 00 ; 0xf2e76
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2e7a floppy.c:43
+ mov es, ax ; 8e c0 ; 0xf2e7d
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf2e7f
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf2e82 floppy.c:76
+ pop bx ; 5b ; 0xf2e85
+ pop bp ; 5d ; 0xf2e86
+ retn ; c3 ; 0xf2e87
+ ; disGetNextSymbol 0xf2e88 LB 0x70c0 -> off=0x0 cb=0000000000000023 uValue=00000000000f1888 'floppy_wait_for_interrupt'
+floppy_wait_for_interrupt: ; 0xf2e88 LB 0x23
+ push bp ; 55 ; 0xf2e88 floppy.c:96
+ mov bp, sp ; 89 e5 ; 0xf2e89
+ push bx ; 53 ; 0xf2e8b
+ cli ; fa ; 0xf2e8c floppy.c:98
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf2e8d floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2e90
+ mov es, ax ; 8e c0 ; 0xf2e93
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2e95
+ test AL, strict byte 080h ; a8 80 ; 0xf2e98 floppy.c:102
+ je short 02ea0h ; 74 04 ; 0xf2e9a
+ and AL, strict byte 080h ; 24 80 ; 0xf2e9c floppy.c:103
+ jmp short 02ea5h ; eb 05 ; 0xf2e9e
+ sti ; fb ; 0xf2ea0 floppy.c:104
+ hlt ; f4 ; 0xf2ea1
+ cli ; fa ; 0xf2ea2
+ jmp short 02e8dh ; eb e8 ; 0xf2ea3 floppy.c:105
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf2ea5 floppy.c:106
+ pop bx ; 5b ; 0xf2ea8
+ pop bp ; 5d ; 0xf2ea9
+ retn ; c3 ; 0xf2eaa
+ ; disGetNextSymbol 0xf2eab LB 0x709d -> off=0x0 cb=0000000000000038 uValue=00000000000f18ab 'floppy_wait_for_interrupt_or_timeout'
+floppy_wait_for_interrupt_or_timeout: ; 0xf2eab LB 0x38
+ push bp ; 55 ; 0xf2eab floppy.c:116
+ mov bp, sp ; 89 e5 ; 0xf2eac
+ push bx ; 53 ; 0xf2eae
+ cli ; fa ; 0xf2eaf floppy.c:118
+ mov bx, strict word 00040h ; bb 40 00 ; 0xf2eb0 floppy.c:38
+ mov es, bx ; 8e c3 ; 0xf2eb3
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2eb5
+ test al, al ; 84 c0 ; 0xf2eb8 floppy.c:122
+ jne short 02ebfh ; 75 03 ; 0xf2eba
+ sti ; fb ; 0xf2ebc floppy.c:123
+ jmp short 02eddh ; eb 1e ; 0xf2ebd floppy.c:124
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf2ebf floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2ec2
+ mov es, ax ; 8e c0 ; 0xf2ec5
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2ec7
+ test AL, strict byte 080h ; a8 80 ; 0xf2eca floppy.c:128
+ je short 02ed8h ; 74 0a ; 0xf2ecc
+ mov ah, al ; 88 c4 ; 0xf2ece floppy.c:129
+ and ah, 07fh ; 80 e4 7f ; 0xf2ed0
+ mov byte [es:bx], ah ; 26 88 27 ; 0xf2ed3 floppy.c:43
+ jmp short 02eddh ; eb 05 ; 0xf2ed6 floppy.c:130
+ sti ; fb ; 0xf2ed8 floppy.c:132
+ hlt ; f4 ; 0xf2ed9
+ cli ; fa ; 0xf2eda
+ jmp short 02eb0h ; eb d3 ; 0xf2edb floppy.c:133
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf2edd floppy.c:134
+ pop bx ; 5b ; 0xf2ee0
+ pop bp ; 5d ; 0xf2ee1
+ retn ; c3 ; 0xf2ee2
+ ; disGetNextSymbol 0xf2ee3 LB 0x7065 -> off=0x0 cb=000000000000003f uValue=00000000000f18e3 'floppy_reset_controller'
+floppy_reset_controller: ; 0xf2ee3 LB 0x3f
+ push bp ; 55 ; 0xf2ee3 floppy.c:138
+ mov bp, sp ; 89 e5 ; 0xf2ee4
+ push bx ; 53 ; 0xf2ee6
+ push cx ; 51 ; 0xf2ee7
+ push dx ; 52 ; 0xf2ee8
+ mov cx, ax ; 89 c1 ; 0xf2ee9
+ mov dx, 003f2h ; ba f2 03 ; 0xf2eeb floppy.c:143
+ in AL, DX ; ec ; 0xf2eee
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2eef
+ mov bx, ax ; 89 c3 ; 0xf2ef1
+ and AL, strict byte 0fbh ; 24 fb ; 0xf2ef3 floppy.c:144
+ out DX, AL ; ee ; 0xf2ef5
+ mov al, bl ; 88 d8 ; 0xf2ef6 floppy.c:145
+ or AL, strict byte 004h ; 0c 04 ; 0xf2ef8
+ out DX, AL ; ee ; 0xf2efa
+ mov dx, 003f4h ; ba f4 03 ; 0xf2efb floppy.c:149
+ in AL, DX ; ec ; 0xf2efe
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2eff
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf2f01 floppy.c:150
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf2f03
+ jne short 02efbh ; 75 f4 ; 0xf2f05
+ mov bx, cx ; 89 cb ; 0xf2f07 floppy.c:153
+ add bx, 00090h ; 81 c3 90 00 ; 0xf2f09
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2f0d floppy.c:38
+ mov es, ax ; 8e c0 ; 0xf2f10
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2f12
+ and AL, strict byte 0efh ; 24 ef ; 0xf2f15 floppy.c:154
+ mov byte [es:bx], al ; 26 88 07 ; 0xf2f17 floppy.c:43
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf2f1a floppy.c:157
+ pop dx ; 5a ; 0xf2f1d
+ pop cx ; 59 ; 0xf2f1e
+ pop bx ; 5b ; 0xf2f1f
+ pop bp ; 5d ; 0xf2f20
+ retn ; c3 ; 0xf2f21
+ ; disGetNextSymbol 0xf2f22 LB 0x7026 -> off=0x0 cb=0000000000000075 uValue=00000000000f1922 'floppy_prepare_controller'
+floppy_prepare_controller: ; 0xf2f22 LB 0x75
+ push bp ; 55 ; 0xf2f22 floppy.c:159
+ mov bp, sp ; 89 e5 ; 0xf2f23
+ push bx ; 53 ; 0xf2f25
+ push cx ; 51 ; 0xf2f26
+ push dx ; 52 ; 0xf2f27
+ push ax ; 50 ; 0xf2f28
+ mov cx, ax ; 89 c1 ; 0xf2f29
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf2f2b floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2f2e
+ mov es, ax ; 8e c0 ; 0xf2f31
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2f33
+ and AL, strict byte 07fh ; 24 7f ; 0xf2f36 floppy.c:165
+ mov byte [es:bx], al ; 26 88 07 ; 0xf2f38 floppy.c:43
+ mov dx, 003f2h ; ba f2 03 ; 0xf2f3b floppy.c:169
+ in AL, DX ; ec ; 0xf2f3e
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2f3f
+ and AL, strict byte 004h ; 24 04 ; 0xf2f41
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf2f43
+ test cx, cx ; 85 c9 ; 0xf2f46 floppy.c:170
+ je short 02f4eh ; 74 04 ; 0xf2f48
+ mov AL, strict byte 020h ; b0 20 ; 0xf2f4a floppy.c:171
+ jmp short 02f50h ; eb 02 ; 0xf2f4c floppy.c:172
+ mov AL, strict byte 010h ; b0 10 ; 0xf2f4e floppy.c:173
+ or AL, strict byte 00ch ; 0c 0c ; 0xf2f50 floppy.c:174
+ or al, cl ; 08 c8 ; 0xf2f52 floppy.c:175
+ mov dx, 003f2h ; ba f2 03 ; 0xf2f54 floppy.c:176
+ out DX, AL ; ee ; 0xf2f57
+ mov bx, strict word 00040h ; bb 40 00 ; 0xf2f58 floppy.c:43
+ mov es, bx ; 8e c3 ; 0xf2f5b
+ mov byte [es:bx], 025h ; 26 c6 07 25 ; 0xf2f5d
+ mov bx, 0008bh ; bb 8b 00 ; 0xf2f61 floppy.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2f64
+ mov CL, strict byte 006h ; b1 06 ; 0xf2f67 floppy.c:183
+ shr al, CL ; d2 e8 ; 0xf2f69
+ mov dx, 003f7h ; ba f7 03 ; 0xf2f6b floppy.c:184
+ out DX, AL ; ee ; 0xf2f6e
+ mov dx, 003f4h ; ba f4 03 ; 0xf2f6f floppy.c:188
+ in AL, DX ; ec ; 0xf2f72
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf2f73
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf2f75 floppy.c:189
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf2f77
+ jne short 02f6fh ; 75 f4 ; 0xf2f79
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf2f7b floppy.c:191
+ jne short 02f8fh ; 75 0e ; 0xf2f7f
+ call 02e88h ; e8 04 ff ; 0xf2f81 floppy.c:202
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf2f84 floppy.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf2f87
+ mov es, dx ; 8e c2 ; 0xf2f8a
+ mov byte [es:bx], al ; 26 88 07 ; 0xf2f8c
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf2f8f floppy.c:206
+ pop dx ; 5a ; 0xf2f92
+ pop cx ; 59 ; 0xf2f93
+ pop bx ; 5b ; 0xf2f94
+ pop bp ; 5d ; 0xf2f95
+ retn ; c3 ; 0xf2f96
+ ; disGetNextSymbol 0xf2f97 LB 0x6fb1 -> off=0x0 cb=000000000000004c uValue=00000000000f1997 'floppy_media_known'
+floppy_media_known: ; 0xf2f97 LB 0x4c
+ push bx ; 53 ; 0xf2f97 floppy.c:208
+ push cx ; 51 ; 0xf2f98
+ push dx ; 52 ; 0xf2f99
+ push bp ; 55 ; 0xf2f9a
+ mov bp, sp ; 89 e5 ; 0xf2f9b
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xf2f9d floppy.c:38
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf2fa0
+ mov es, dx ; 8e c2 ; 0xf2fa3
+ mov bh, byte [es:bx] ; 26 8a 3f ; 0xf2fa5
+ mov bl, bh ; 88 fb ; 0xf2fa8 floppy.c:39
+ test ax, ax ; 85 c0 ; 0xf2faa floppy.c:214
+ je short 02fb0h ; 74 02 ; 0xf2fac
+ shr bl, 1 ; d0 eb ; 0xf2fae floppy.c:215
+ and bl, 001h ; 80 e3 01 ; 0xf2fb0 floppy.c:216
+ jne short 02fb9h ; 75 04 ; 0xf2fb3 floppy.c:217
+ xor bh, bh ; 30 ff ; 0xf2fb5 floppy.c:218
+ jmp short 02fdch ; eb 23 ; 0xf2fb7
+ mov bx, 00090h ; bb 90 00 ; 0xf2fb9 floppy.c:220
+ test ax, ax ; 85 c0 ; 0xf2fbc floppy.c:221
+ je short 02fc3h ; 74 03 ; 0xf2fbe
+ mov bx, 00091h ; bb 91 00 ; 0xf2fc0 floppy.c:222
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf2fc3 floppy.c:38
+ mov es, ax ; 8e c0 ; 0xf2fc6
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf2fc8
+ xor ah, ah ; 30 e4 ; 0xf2fcb floppy.c:225
+ mov CL, strict byte 004h ; b1 04 ; 0xf2fcd
+ sar ax, CL ; d3 f8 ; 0xf2fcf
+ and AL, strict byte 001h ; 24 01 ; 0xf2fd1
+ jne short 02fd9h ; 75 04 ; 0xf2fd3 floppy.c:226
+ xor bx, bx ; 31 db ; 0xf2fd5 floppy.c:227
+ jmp short 02fdch ; eb 03 ; 0xf2fd7
+ mov bx, strict word 00001h ; bb 01 00 ; 0xf2fd9 floppy.c:230
+ mov ax, bx ; 89 d8 ; 0xf2fdc floppy.c:231
+ pop bp ; 5d ; 0xf2fde
+ pop dx ; 5a ; 0xf2fdf
+ pop cx ; 59 ; 0xf2fe0
+ pop bx ; 5b ; 0xf2fe1
+ retn ; c3 ; 0xf2fe2
+ ; disGetNextSymbol 0xf2fe3 LB 0x6f65 -> off=0x0 cb=0000000000000052 uValue=00000000000f19e3 'floppy_read_id'
+floppy_read_id: ; 0xf2fe3 LB 0x52
+ push bp ; 55 ; 0xf2fe3 floppy.c:233
+ mov bp, sp ; 89 e5 ; 0xf2fe4
+ push bx ; 53 ; 0xf2fe6
+ push dx ; 52 ; 0xf2fe7
+ push si ; 56 ; 0xf2fe8
+ mov bx, ax ; 89 c3 ; 0xf2fe9
+ call 02f22h ; e8 34 ff ; 0xf2feb floppy.c:240
+ mov AL, strict byte 04ah ; b0 4a ; 0xf2fee floppy.c:243
+ mov dx, 003f5h ; ba f5 03 ; 0xf2ff0
+ out DX, AL ; ee ; 0xf2ff3
+ mov al, bl ; 88 d8 ; 0xf2ff4 floppy.c:244
+ out DX, AL ; ee ; 0xf2ff6
+ call 02e88h ; e8 8e fe ; 0xf2ff7 floppy.c:259
+ xor bx, bx ; 31 db ; 0xf2ffa floppy.c:263
+ jmp short 03003h ; eb 05 ; 0xf2ffc
+ cmp bx, strict byte 00007h ; 83 fb 07 ; 0xf2ffe
+ jnl short 03017h ; 7d 14 ; 0xf3001
+ mov dx, 003f5h ; ba f5 03 ; 0xf3003 floppy.c:264
+ in AL, DX ; ec ; 0xf3006
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf3007
+ lea si, [bx+042h] ; 8d 77 42 ; 0xf3009
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf300c floppy.c:43
+ mov es, dx ; 8e c2 ; 0xf300f
+ mov byte [es:si], al ; 26 88 04 ; 0xf3011
+ inc bx ; 43 ; 0xf3014 floppy.c:264
+ jmp short 02ffeh ; eb e7 ; 0xf3015
+ mov bx, strict word 00042h ; bb 42 00 ; 0xf3017 floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf301a
+ mov es, ax ; 8e c0 ; 0xf301d
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf301f
+ test AL, strict byte 0c0h ; a8 c0 ; 0xf3022 floppy.c:39
+ je short 0302ah ; 74 04 ; 0xf3024
+ xor ax, ax ; 31 c0 ; 0xf3026 floppy.c:267
+ jmp short 0302dh ; eb 03 ; 0xf3028
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf302a floppy.c:269
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf302d floppy.c:270
+ pop si ; 5e ; 0xf3030
+ pop dx ; 5a ; 0xf3031
+ pop bx ; 5b ; 0xf3032
+ pop bp ; 5d ; 0xf3033
+ retn ; c3 ; 0xf3034
+ ; disGetNextSymbol 0xf3035 LB 0x6f13 -> off=0x0 cb=0000000000000041 uValue=00000000000f1a35 'floppy_drive_recal'
+floppy_drive_recal: ; 0xf3035 LB 0x41
+ push bp ; 55 ; 0xf3035 floppy.c:272
+ mov bp, sp ; 89 e5 ; 0xf3036
+ push bx ; 53 ; 0xf3038
+ push dx ; 52 ; 0xf3039
+ push si ; 56 ; 0xf303a
+ mov bx, ax ; 89 c3 ; 0xf303b
+ call 02f22h ; e8 e2 fe ; 0xf303d floppy.c:277
+ mov AL, strict byte 007h ; b0 07 ; 0xf3040 floppy.c:280
+ mov dx, 003f5h ; ba f5 03 ; 0xf3042
+ out DX, AL ; ee ; 0xf3045
+ mov al, bl ; 88 d8 ; 0xf3046 floppy.c:281
+ out DX, AL ; ee ; 0xf3048
+ call 02e88h ; e8 3c fe ; 0xf3049 floppy.c:300
+ test bx, bx ; 85 db ; 0xf304c floppy.c:304
+ je short 03057h ; 74 07 ; 0xf304e
+ or AL, strict byte 002h ; 0c 02 ; 0xf3050 floppy.c:305
+ mov bx, 00095h ; bb 95 00 ; 0xf3052 floppy.c:306
+ jmp short 0305ch ; eb 05 ; 0xf3055 floppy.c:307
+ or AL, strict byte 001h ; 0c 01 ; 0xf3057 floppy.c:308
+ mov bx, 00094h ; bb 94 00 ; 0xf3059 floppy.c:309
+ mov si, strict word 0003eh ; be 3e 00 ; 0xf305c floppy.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf305f
+ mov es, dx ; 8e c2 ; 0xf3062
+ mov byte [es:si], al ; 26 88 04 ; 0xf3064
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3067 floppy.c:43
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf306b floppy.c:315
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf306e
+ pop si ; 5e ; 0xf3071
+ pop dx ; 5a ; 0xf3072
+ pop bx ; 5b ; 0xf3073
+ pop bp ; 5d ; 0xf3074
+ retn ; c3 ; 0xf3075
+ ; disGetNextSymbol 0xf3076 LB 0x6ed2 -> off=0x0 cb=00000000000000e7 uValue=00000000000f1a76 'floppy_media_sense'
+floppy_media_sense: ; 0xf3076 LB 0xe7
+ push bp ; 55 ; 0xf3076 floppy.c:318
+ mov bp, sp ; 89 e5 ; 0xf3077
+ push bx ; 53 ; 0xf3079
+ push cx ; 51 ; 0xf307a
+ push dx ; 52 ; 0xf307b
+ push si ; 56 ; 0xf307c
+ push di ; 57 ; 0xf307d
+ mov si, ax ; 89 c6 ; 0xf307e
+ call 03035h ; e8 b2 ff ; 0xf3080 floppy.c:324
+ test ax, ax ; 85 c0 ; 0xf3083
+ jne short 0308ch ; 75 05 ; 0xf3085
+ xor dx, dx ; 31 d2 ; 0xf3087 floppy.c:325
+ jmp near 03151h ; e9 c5 00 ; 0xf3089
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf308c floppy.c:360
+ call 01652h ; e8 c0 e5 ; 0xf308f
+ test si, si ; 85 f6 ; 0xf3092 floppy.c:361
+ jne short 0309eh ; 75 08 ; 0xf3094
+ mov CL, strict byte 004h ; b1 04 ; 0xf3096 floppy.c:362
+ mov dl, al ; 88 c2 ; 0xf3098
+ shr dl, CL ; d2 ea ; 0xf309a
+ jmp short 030a3h ; eb 05 ; 0xf309c floppy.c:363
+ mov dl, al ; 88 c2 ; 0xf309e floppy.c:364
+ and dl, 00fh ; 80 e2 0f ; 0xf30a0
+ cmp dl, 001h ; 80 fa 01 ; 0xf30a3 floppy.c:365
+ jne short 030b1h ; 75 09 ; 0xf30a6
+ xor dl, dl ; 30 d2 ; 0xf30a8 floppy.c:367
+ mov DH, strict byte 015h ; b6 15 ; 0xf30aa floppy.c:368
+ mov bx, strict word 00001h ; bb 01 00 ; 0xf30ac floppy.c:369
+ jmp short 030efh ; eb 3e ; 0xf30af floppy.c:371
+ cmp dl, 002h ; 80 fa 02 ; 0xf30b1
+ jne short 030bch ; 75 06 ; 0xf30b4
+ xor dl, dl ; 30 d2 ; 0xf30b6 floppy.c:373
+ mov DH, strict byte 035h ; b6 35 ; 0xf30b8 floppy.c:374
+ jmp short 030ach ; eb f0 ; 0xf30ba
+ cmp dl, 003h ; 80 fa 03 ; 0xf30bc floppy.c:377
+ jne short 030c7h ; 75 06 ; 0xf30bf
+ xor dl, dl ; 30 d2 ; 0xf30c1 floppy.c:379
+ mov DH, strict byte 017h ; b6 17 ; 0xf30c3 floppy.c:380
+ jmp short 030ach ; eb e5 ; 0xf30c5
+ cmp dl, 004h ; 80 fa 04 ; 0xf30c7 floppy.c:383
+ jne short 030d2h ; 75 06 ; 0xf30ca
+ xor dl, dl ; 30 d2 ; 0xf30cc floppy.c:385
+ mov DH, strict byte 017h ; b6 17 ; 0xf30ce floppy.c:386
+ jmp short 030ach ; eb da ; 0xf30d0
+ cmp dl, 005h ; 80 fa 05 ; 0xf30d2 floppy.c:389
+ jne short 030ddh ; 75 06 ; 0xf30d5
+ mov DL, strict byte 0cch ; b2 cc ; 0xf30d7 floppy.c:391
+ mov DH, strict byte 0d7h ; b6 d7 ; 0xf30d9 floppy.c:392
+ jmp short 030ach ; eb cf ; 0xf30db
+ cmp dl, 00eh ; 80 fa 0e ; 0xf30dd floppy.c:396
+ je short 030e7h ; 74 05 ; 0xf30e0
+ cmp dl, 00fh ; 80 fa 0f ; 0xf30e2
+ jne short 030e9h ; 75 02 ; 0xf30e5
+ jmp short 030d7h ; eb ee ; 0xf30e7
+ xor dl, dl ; 30 d2 ; 0xf30e9 floppy.c:404
+ xor dh, dh ; 30 f6 ; 0xf30eb floppy.c:405
+ xor bx, bx ; 31 db ; 0xf30ed floppy.c:406
+ mov di, 0008bh ; bf 8b 00 ; 0xf30ef floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf30f2
+ mov es, ax ; 8e c0 ; 0xf30f5
+ mov byte [es:di], dl ; 26 88 15 ; 0xf30f7
+ mov ax, si ; 89 f0 ; 0xf30fa floppy.c:410
+ call 02fe3h ; e8 e4 fe ; 0xf30fc
+ test ax, ax ; 85 c0 ; 0xf30ff
+ jne short 03135h ; 75 32 ; 0xf3101
+ mov al, dl ; 88 d0 ; 0xf3103 floppy.c:411
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf3105
+ cmp AL, strict byte 080h ; 3c 80 ; 0xf3107
+ je short 03135h ; 74 2a ; 0xf3109
+ mov al, dl ; 88 d0 ; 0xf310b floppy.c:415
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf310d
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xf310f
+ je short 03122h ; 74 0f ; 0xf3111
+ mov ah, dl ; 88 d4 ; 0xf3113
+ and ah, 03fh ; 80 e4 3f ; 0xf3115
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf3118
+ je short 0312eh ; 74 12 ; 0xf311a
+ test al, al ; 84 c0 ; 0xf311c
+ je short 03127h ; 74 07 ; 0xf311e
+ jmp short 030efh ; eb cd ; 0xf3120
+ and dl, 03fh ; 80 e2 3f ; 0xf3122 floppy.c:417
+ jmp short 030efh ; eb c8 ; 0xf3125 floppy.c:418
+ mov dl, ah ; 88 e2 ; 0xf3127 floppy.c:420
+ or dl, 040h ; 80 ca 40 ; 0xf3129
+ jmp short 030efh ; eb c1 ; 0xf312c floppy.c:421
+ mov dl, ah ; 88 e2 ; 0xf312e floppy.c:423
+ or dl, 080h ; 80 ca 80 ; 0xf3130
+ jmp short 030efh ; eb ba ; 0xf3133 floppy.c:427
+ test si, si ; 85 f6 ; 0xf3135 floppy.c:429
+ jne short 0313eh ; 75 05 ; 0xf3137
+ mov si, 00090h ; be 90 00 ; 0xf3139 floppy.c:430
+ jmp short 03141h ; eb 03 ; 0xf313c floppy.c:431
+ mov si, 00091h ; be 91 00 ; 0xf313e floppy.c:432
+ mov di, 0008bh ; bf 8b 00 ; 0xf3141 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3144
+ mov es, ax ; 8e c0 ; 0xf3147
+ mov byte [es:di], dl ; 26 88 15 ; 0xf3149
+ mov byte [es:si], dh ; 26 88 34 ; 0xf314c floppy.c:43
+ mov dx, bx ; 89 da ; 0xf314f floppy.c:436
+ mov ax, dx ; 89 d0 ; 0xf3151 floppy.c:437
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf3153
+ pop di ; 5f ; 0xf3156
+ pop si ; 5e ; 0xf3157
+ pop dx ; 5a ; 0xf3158
+ pop cx ; 59 ; 0xf3159
+ pop bx ; 5b ; 0xf315a
+ pop bp ; 5d ; 0xf315b
+ retn ; c3 ; 0xf315c
+ ; disGetNextSymbol 0xf315d LB 0x6deb -> off=0x0 cb=000000000000002b uValue=00000000000f1b5d 'floppy_drive_exists'
+floppy_drive_exists: ; 0xf315d LB 0x2b
+ push bp ; 55 ; 0xf315d floppy.c:440
+ mov bp, sp ; 89 e5 ; 0xf315e
+ push cx ; 51 ; 0xf3160
+ push dx ; 52 ; 0xf3161
+ mov dx, ax ; 89 c2 ; 0xf3162
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf3164 floppy.c:446
+ call 01652h ; e8 e8 e4 ; 0xf3167
+ test dx, dx ; 85 d2 ; 0xf316a floppy.c:447
+ jne short 03174h ; 75 06 ; 0xf316c
+ mov CL, strict byte 004h ; b1 04 ; 0xf316e floppy.c:448
+ shr al, CL ; d2 e8 ; 0xf3170
+ jmp short 03176h ; eb 02 ; 0xf3172 floppy.c:449
+ and AL, strict byte 00fh ; 24 0f ; 0xf3174 floppy.c:450
+ test al, al ; 84 c0 ; 0xf3176 floppy.c:451
+ je short 0317fh ; 74 05 ; 0xf3178
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf317a
+ jmp short 03181h ; eb 02 ; 0xf317d
+ xor ah, ah ; 30 e4 ; 0xf317f
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf3181 floppy.c:452
+ pop dx ; 5a ; 0xf3184
+ pop cx ; 59 ; 0xf3185
+ pop bp ; 5d ; 0xf3186
+ retn ; c3 ; 0xf3187
+ ; disGetNextSymbol 0xf3188 LB 0x6dc0 -> off=0x23 cb=00000000000009fd uValue=00000000000f1bab 'int13_diskette_function'
+ db 018h, 017h, 016h, 015h, 008h, 005h, 004h, 003h, 002h, 001h, 000h, 082h, 03bh, 0e9h, 031h, 06bh
+ db 032h, 085h, 032h, 085h, 032h, 085h, 032h, 036h, 036h, 01ah, 038h, 015h, 039h, 058h, 039h, 08ch
+ db 039h, 000h, 03ah
+int13_diskette_function: ; 0xf31ab LB 0x9fd
+ push bp ; 55 ; 0xf31ab floppy.c:467
+ mov bp, sp ; 89 e5 ; 0xf31ac
+ sub sp, strict byte 0000eh ; 83 ec 0e ; 0xf31ae
+ or byte [bp+01dh], 002h ; 80 4e 1d 02 ; 0xf31b1 floppy.c:478
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf31b5 floppy.c:480
+ xor ah, ah ; 30 e4 ; 0xf31b8
+ mov dx, ax ; 89 c2 ; 0xf31ba
+ cmp ax, strict word 00018h ; 3d 18 00 ; 0xf31bc
+ jnbe short 0321dh ; 77 5c ; 0xf31bf
+ push CS ; 0e ; 0xf31c1
+ pop ES ; 07 ; 0xf31c2
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf31c3
+ mov di, 03188h ; bf 88 31 ; 0xf31c6
+ repne scasb ; f2 ae ; 0xf31c9
+ sal cx, 1 ; d1 e1 ; 0xf31cb
+ mov di, cx ; 89 cf ; 0xf31cd
+ mov di, word [cs:di+03193h] ; 2e 8b bd 93 31 ; 0xf31cf
+ mov cx, word [bp+016h] ; 8b 4e 16 ; 0xf31d4
+ xor ch, ch ; 30 ed ; 0xf31d7
+ mov dl, byte [bp+00eh] ; 8a 56 0e ; 0xf31d9
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf31dc
+ or AL, strict byte 001h ; 0c 01 ; 0xf31df
+ mov si, cx ; 89 ce ; 0xf31e1
+ or si, 00100h ; 81 ce 00 01 ; 0xf31e3
+ jmp di ; ff e7 ; 0xf31e7
+ mov bl, byte [bp+00eh] ; 8a 5e 0e ; 0xf31e9 floppy.c:483
+ cmp bl, 001h ; 80 fb 01 ; 0xf31ec floppy.c:484
+ jbe short 0320bh ; 76 1a ; 0xf31ef
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf31f1 floppy.c:485
+ xor ah, ah ; 30 e4 ; 0xf31f4
+ or ah, 001h ; 80 cc 01 ; 0xf31f6
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf31f9
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf31fc floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf31ff
+ mov es, ax ; 8e c0 ; 0xf3202
+ mov byte [es:bx], 001h ; 26 c6 07 01 ; 0xf3204
+ jmp near 03a6dh ; e9 62 08 ; 0xf3208
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf320b floppy.c:491
+ call 01652h ; e8 41 e4 ; 0xf320e
+ test bl, bl ; 84 db ; 0xf3211 floppy.c:492
+ jne short 03220h ; 75 0b ; 0xf3213
+ mov CL, strict byte 004h ; b1 04 ; 0xf3215 floppy.c:493
+ mov dl, al ; 88 c2 ; 0xf3217
+ shr dl, CL ; d2 ea ; 0xf3219
+ jmp short 03225h ; eb 08 ; 0xf321b floppy.c:494
+ jmp near 03b82h ; e9 62 09 ; 0xf321d
+ mov dl, al ; 88 c2 ; 0xf3220 floppy.c:495
+ and dl, 00fh ; 80 e2 0f ; 0xf3222
+ test dl, dl ; 84 d2 ; 0xf3225 floppy.c:496
+ jne short 03243h ; 75 1a ; 0xf3227
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3229 floppy.c:497
+ xor ah, ah ; 30 e4 ; 0xf322c
+ or ah, 080h ; 80 cc 80 ; 0xf322e
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3231
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3234 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3237
+ mov es, ax ; 8e c0 ; 0xf323a
+ mov byte [es:bx], 080h ; 26 c6 07 80 ; 0xf323c
+ jmp near 03a6dh ; e9 2a 08 ; 0xf3240
+ mov si, strict word 0003eh ; be 3e 00 ; 0xf3243 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3246
+ mov es, ax ; 8e c0 ; 0xf3249
+ mov byte [es:si], 000h ; 26 c6 04 00 ; 0xf324b
+ xor al, al ; 30 c0 ; 0xf324f floppy.c:506
+ mov byte [bp+017h], al ; 88 46 17 ; 0xf3251
+ mov si, strict word 00041h ; be 41 00 ; 0xf3254 floppy.c:43
+ mov byte [es:si], al ; 26 88 04 ; 0xf3257
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf325a floppy.c:508
+ mov al, bl ; 88 d8 ; 0xf325e floppy.c:509
+ xor ah, ah ; 30 e4 ; 0xf3260
+ xor dx, dx ; 31 d2 ; 0xf3262
+ call 02e5ch ; e8 f5 fb ; 0xf3264
+ mov sp, bp ; 89 ec ; 0xf3267 floppy.c:510
+ pop bp ; 5d ; 0xf3269
+ retn ; c3 ; 0xf326a
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf326b floppy.c:513
+ mov bx, 00441h ; bb 41 04 ; 0xf326f floppy.c:38
+ xor ax, ax ; 31 c0 ; 0xf3272
+ mov es, ax ; 8e c0 ; 0xf3274
+ mov dl, byte [es:bx] ; 26 8a 17 ; 0xf3276
+ mov ch, dl ; 88 d5 ; 0xf3279 floppy.c:515
+ mov word [bp+016h], cx ; 89 4e 16 ; 0xf327b
+ test dl, dl ; 84 d2 ; 0xf327e floppy.c:516
+ je short 03267h ; 74 e5 ; 0xf3280
+ jmp near 03a6dh ; e9 e8 07 ; 0xf3282
+ mov bh, byte [bp+016h] ; 8a 7e 16 ; 0xf3285 floppy.c:524
+ mov al, byte [bp+015h] ; 8a 46 15 ; 0xf3288 floppy.c:525
+ mov byte [bp-004h], al ; 88 46 fc ; 0xf328b
+ mov al, byte [bp+014h] ; 8a 46 14 ; 0xf328e floppy.c:526
+ mov byte [bp-002h], al ; 88 46 fe ; 0xf3291
+ mov al, byte [bp+013h] ; 8a 46 13 ; 0xf3294 floppy.c:527
+ xor ah, ah ; 30 e4 ; 0xf3297
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf3299
+ mov bl, byte [bp+00eh] ; 8a 5e 0e ; 0xf329c floppy.c:528
+ cmp bl, 001h ; 80 fb 01 ; 0xf329f floppy.c:530
+ jnbe short 032b1h ; 77 0d ; 0xf32a2
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf32a4
+ jnbe short 032b1h ; 77 09 ; 0xf32a6
+ test bh, bh ; 84 ff ; 0xf32a8
+ je short 032b1h ; 74 05 ; 0xf32aa
+ cmp bh, 048h ; 80 ff 48 ; 0xf32ac
+ jbe short 032e8h ; 76 37 ; 0xf32af
+ mov bx, 00da0h ; bb a0 0d ; 0xf32b1 floppy.c:532
+ mov cx, ds ; 8c d9 ; 0xf32b4
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf32b6
+ call 018cch ; e8 10 e6 ; 0xf32b9
+ mov ax, 00275h ; b8 75 02 ; 0xf32bc
+ push ax ; 50 ; 0xf32bf
+ mov ax, 0028dh ; b8 8d 02 ; 0xf32c0
+ push ax ; 50 ; 0xf32c3
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf32c4
+ push ax ; 50 ; 0xf32c7
+ call 0190fh ; e8 44 e6 ; 0xf32c8
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf32cb
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf32ce floppy.c:533
+ xor ah, ah ; 30 e4 ; 0xf32d1
+ or ah, 001h ; 80 cc 01 ; 0xf32d3
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf32d6
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf32d9 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf32dc
+ mov es, ax ; 8e c0 ; 0xf32df
+ mov byte [es:bx], 001h ; 26 c6 07 01 ; 0xf32e1
+ jmp near 03392h ; e9 aa 00 ; 0xf32e5
+ mov al, bl ; 88 d8 ; 0xf32e8 floppy.c:535
+ xor ah, ah ; 30 e4 ; 0xf32ea
+ call 0315dh ; e8 6e fe ; 0xf32ec
+ test ax, ax ; 85 c0 ; 0xf32ef
+ jne short 0330dh ; 75 1a ; 0xf32f1
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf32f3 floppy.c:543
+ xor ah, ah ; 30 e4 ; 0xf32f6
+ or ah, 080h ; 80 cc 80 ; 0xf32f8
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf32fb
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf32fe floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3301
+ mov es, ax ; 8e c0 ; 0xf3304
+ mov byte [es:bx], 080h ; 26 c6 07 80 ; 0xf3306
+ jmp near 03392h ; e9 85 00 ; 0xf330a
+ mov cl, bl ; 88 d9 ; 0xf330d floppy.c:551
+ xor ch, ch ; 30 ed ; 0xf330f
+ mov ax, cx ; 89 c8 ; 0xf3311
+ call 02f97h ; e8 81 fc ; 0xf3313
+ test ax, ax ; 85 c0 ; 0xf3316
+ jne short 03340h ; 75 26 ; 0xf3318
+ mov ax, cx ; 89 c8 ; 0xf331a floppy.c:552
+ call 03076h ; e8 57 fd ; 0xf331c
+ test ax, ax ; 85 c0 ; 0xf331f
+ jne short 03340h ; 75 1d ; 0xf3321
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3323 floppy.c:554
+ xor ah, ah ; 30 e4 ; 0xf3326
+ or ah, 00ch ; 80 cc 0c ; 0xf3328
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf332b
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf332e floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3331
+ mov es, ax ; 8e c0 ; 0xf3334
+ mov byte [es:bx], 00ch ; 26 c6 07 0c ; 0xf3336
+ mov byte [bp+016h], ch ; 88 6e 16 ; 0xf333a
+ jmp near 03a6dh ; e9 2d 07 ; 0xf333d
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf3340 floppy.c:556
+ xor ah, ah ; 30 e4 ; 0xf3343
+ cmp ax, strict word 00002h ; 3d 02 00 ; 0xf3345
+ jne short 03399h ; 75 4f ; 0xf3348
+ mov CL, strict byte 00ch ; b1 0c ; 0xf334a floppy.c:573
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf334c
+ shr ax, CL ; d3 e8 ; 0xf334f
+ mov ch, al ; 88 c5 ; 0xf3351
+ mov CL, strict byte 004h ; b1 04 ; 0xf3353 floppy.c:574
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf3355
+ sal dx, CL ; d3 e2 ; 0xf3358
+ mov si, word [bp+010h] ; 8b 76 10 ; 0xf335a floppy.c:575
+ add si, dx ; 01 d6 ; 0xf335d
+ mov word [bp-00ch], si ; 89 76 f4 ; 0xf335f
+ cmp dx, si ; 39 f2 ; 0xf3362 floppy.c:577
+ jbe short 03368h ; 76 02 ; 0xf3364
+ db 0feh, 0c5h
+ ; inc ch ; fe c5 ; 0xf3366 floppy.c:579
+ mov al, bh ; 88 f8 ; 0xf3368 floppy.c:581
+ xor ah, ah ; 30 e4 ; 0xf336a
+ mov CL, strict byte 009h ; b1 09 ; 0xf336c
+ sal ax, CL ; d3 e0 ; 0xf336e
+ dec ax ; 48 ; 0xf3370
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf3371
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf3374 floppy.c:584
+ add ax, word [bp-00eh] ; 03 46 f2 ; 0xf3377
+ cmp ax, word [bp-00ch] ; 3b 46 f4 ; 0xf337a floppy.c:585
+ jnc short 0339ch ; 73 1d ; 0xf337d
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf337f floppy.c:586
+ mov ah, cl ; 88 cc ; 0xf3382
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3384
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3387 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf338a
+ mov es, ax ; 8e c0 ; 0xf338d
+ mov byte [es:bx], cl ; 26 88 0f ; 0xf338f
+ mov byte [bp+016h], 000h ; c6 46 16 00 ; 0xf3392
+ jmp near 03a6dh ; e9 d4 06 ; 0xf3396
+ jmp near 034e6h ; e9 4a 01 ; 0xf3399
+ mov AL, strict byte 006h ; b0 06 ; 0xf339c floppy.c:594
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf339e
+ out DX, AL ; ee ; 0xf33a1
+ xor al, al ; 30 c0 ; 0xf33a2 floppy.c:597
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf33a4
+ out DX, AL ; ee ; 0xf33a7
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf33a8 floppy.c:598
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf33ab
+ out DX, AL ; ee ; 0xf33ae
+ mov al, byte [bp-00bh] ; 8a 46 f5 ; 0xf33af floppy.c:599
+ out DX, AL ; ee ; 0xf33b2
+ xor al, al ; 30 c0 ; 0xf33b3 floppy.c:601
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf33b5
+ out DX, AL ; ee ; 0xf33b8
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf33b9 floppy.c:602
+ mov dx, strict word 00005h ; ba 05 00 ; 0xf33bc
+ out DX, AL ; ee ; 0xf33bf
+ mov al, byte [bp-00dh] ; 8a 46 f3 ; 0xf33c0 floppy.c:603
+ out DX, AL ; ee ; 0xf33c3
+ mov AL, strict byte 046h ; b0 46 ; 0xf33c4 floppy.c:611
+ mov dx, strict word 0000bh ; ba 0b 00 ; 0xf33c6
+ out DX, AL ; ee ; 0xf33c9
+ mov al, ch ; 88 e8 ; 0xf33ca floppy.c:615
+ mov dx, 00081h ; ba 81 00 ; 0xf33cc
+ out DX, AL ; ee ; 0xf33cf
+ mov AL, strict byte 002h ; b0 02 ; 0xf33d0 floppy.c:618
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf33d2
+ out DX, AL ; ee ; 0xf33d5
+ mov cl, bl ; 88 d9 ; 0xf33d6 floppy.c:623
+ xor ch, ch ; 30 ed ; 0xf33d8
+ mov ax, cx ; 89 c8 ; 0xf33da
+ call 02f22h ; e8 43 fb ; 0xf33dc
+ mov AL, strict byte 0e6h ; b0 e6 ; 0xf33df floppy.c:626
+ mov dx, 003f5h ; ba f5 03 ; 0xf33e1
+ out DX, AL ; ee ; 0xf33e4
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf33e5 floppy.c:627
+ xor ah, ah ; 30 e4 ; 0xf33e8
+ mov dx, ax ; 89 c2 ; 0xf33ea
+ sal dx, 1 ; d1 e2 ; 0xf33ec
+ sal dx, 1 ; d1 e2 ; 0xf33ee
+ mov al, bl ; 88 d8 ; 0xf33f0
+ or ax, dx ; 09 d0 ; 0xf33f2
+ mov dx, 003f5h ; ba f5 03 ; 0xf33f4
+ out DX, AL ; ee ; 0xf33f7
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf33f8 floppy.c:628
+ out DX, AL ; ee ; 0xf33fb
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf33fc floppy.c:629
+ out DX, AL ; ee ; 0xf33ff
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf3400 floppy.c:630
+ out DX, AL ; ee ; 0xf3403
+ mov AL, strict byte 002h ; b0 02 ; 0xf3404 floppy.c:631
+ out DX, AL ; ee ; 0xf3406
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf3407 floppy.c:632
+ xor ah, ah ; 30 e4 ; 0xf340a
+ mov dl, bh ; 88 fa ; 0xf340c
+ xor dh, dh ; 30 f6 ; 0xf340e
+ add ax, dx ; 01 d0 ; 0xf3410
+ dec ax ; 48 ; 0xf3412
+ mov dx, 003f5h ; ba f5 03 ; 0xf3413
+ out DX, AL ; ee ; 0xf3416
+ xor al, al ; 30 c0 ; 0xf3417 floppy.c:633
+ out DX, AL ; ee ; 0xf3419
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf341a floppy.c:634
+ out DX, AL ; ee ; 0xf341c
+ call 02eabh ; e8 8b fa ; 0xf341d floppy.c:666
+ test al, al ; 84 c0 ; 0xf3420 floppy.c:667
+ jne short 03443h ; 75 1f ; 0xf3422
+ mov ax, cx ; 89 c8 ; 0xf3424 floppy.c:669
+ call 02ee3h ; e8 ba fa ; 0xf3426
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3429 floppy.c:670
+ xor ah, ah ; 30 e4 ; 0xf342c
+ or ah, 080h ; 80 cc 80 ; 0xf342e
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3431
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3434 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3437
+ mov es, ax ; 8e c0 ; 0xf343a
+ mov byte [es:bx], 080h ; 26 c6 07 80 ; 0xf343c
+ jmp near 0333ah ; e9 f7 fe ; 0xf3440
+ mov dx, 003f4h ; ba f4 03 ; 0xf3443 floppy.c:679
+ in AL, DX ; ec ; 0xf3446
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf3447
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf3449 floppy.c:680
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xf344b
+ je short 03461h ; 74 12 ; 0xf344d
+ mov ax, 00275h ; b8 75 02 ; 0xf344f floppy.c:681
+ push ax ; 50 ; 0xf3452
+ mov ax, 002a8h ; b8 a8 02 ; 0xf3453
+ push ax ; 50 ; 0xf3456
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf3457
+ push ax ; 50 ; 0xf345a
+ call 0190fh ; e8 b1 e4 ; 0xf345b
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf345e
+ xor cx, cx ; 31 c9 ; 0xf3461 floppy.c:684
+ jmp short 0346ah ; eb 05 ; 0xf3463
+ cmp cx, strict byte 00007h ; 83 f9 07 ; 0xf3465
+ jnl short 03480h ; 7d 16 ; 0xf3468
+ mov dx, 003f5h ; ba f5 03 ; 0xf346a floppy.c:685
+ in AL, DX ; ec ; 0xf346d
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf346e
+ mov si, cx ; 89 ce ; 0xf3470
+ add si, strict byte 00042h ; 83 c6 42 ; 0xf3472
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3475 floppy.c:43
+ mov es, dx ; 8e c2 ; 0xf3478
+ mov byte [es:si], al ; 26 88 04 ; 0xf347a
+ inc cx ; 41 ; 0xf347d floppy.c:685
+ jmp short 03465h ; eb e5 ; 0xf347e
+ mov si, strict word 00042h ; be 42 00 ; 0xf3480 floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3483
+ mov es, ax ; 8e c0 ; 0xf3486
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf3488
+ test AL, strict byte 0c0h ; a8 c0 ; 0xf348b floppy.c:39
+ je short 034b0h ; 74 21 ; 0xf348d
+ mov al, bl ; 88 d8 ; 0xf348f floppy.c:689
+ xor ah, ah ; 30 e4 ; 0xf3491
+ call 02ee3h ; e8 4d fa ; 0xf3493
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3496 floppy.c:690
+ xor ah, ah ; 30 e4 ; 0xf3499
+ or ah, 020h ; 80 cc 20 ; 0xf349b
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf349e
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf34a1 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf34a4
+ mov es, ax ; 8e c0 ; 0xf34a7
+ mov byte [es:bx], 020h ; 26 c6 07 20 ; 0xf34a9
+ jmp near 03392h ; e9 e2 fe ; 0xf34ad
+ mov al, bh ; 88 f8 ; 0xf34b0 floppy.c:698
+ xor ah, ah ; 30 e4 ; 0xf34b2
+ mov CL, strict byte 009h ; b1 09 ; 0xf34b4
+ sal ax, CL ; d3 e0 ; 0xf34b6
+ cwd ; 99 ; 0xf34b8
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf34b9
+ sar ax, 1 ; d1 f8 ; 0xf34bb
+ mov si, word [bp+010h] ; 8b 76 10 ; 0xf34bd
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf34c0
+ mov di, si ; 89 f7 ; 0xf34c3
+ mov cx, ax ; 89 c1 ; 0xf34c5
+ mov es, dx ; 8e c2 ; 0xf34c7
+ push DS ; 1e ; 0xf34c9
+ mov ds, dx ; 8e da ; 0xf34ca
+ rep movsw ; f3 a5 ; 0xf34cc
+ pop DS ; 1f ; 0xf34ce
+ mov dl, byte [bp-004h] ; 8a 56 fc ; 0xf34cf floppy.c:702
+ xor dh, dh ; 30 f6 ; 0xf34d2
+ mov al, bl ; 88 d8 ; 0xf34d4
+ xor ah, ah ; 30 e4 ; 0xf34d6
+ call 02e5ch ; e8 81 f9 ; 0xf34d8
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf34db floppy.c:704
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf34df floppy.c:705
+ jmp near 03267h ; e9 81 fd ; 0xf34e3 floppy.c:706
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf34e6 floppy.c:707
+ xor ah, ah ; 30 e4 ; 0xf34e9
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf34eb
+ je short 034f3h ; 74 03 ; 0xf34ee
+ jmp near 0361fh ; e9 2c 01 ; 0xf34f0
+ mov CL, strict byte 00ch ; b1 0c ; 0xf34f3 floppy.c:718
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf34f5
+ shr dx, CL ; d3 ea ; 0xf34f8
+ mov ch, dl ; 88 d5 ; 0xf34fa
+ mov CL, strict byte 004h ; b1 04 ; 0xf34fc floppy.c:719
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf34fe
+ sal ax, CL ; d3 e0 ; 0xf3501
+ mov si, word [bp+010h] ; 8b 76 10 ; 0xf3503 floppy.c:720
+ add si, ax ; 01 c6 ; 0xf3506
+ mov word [bp-00ch], si ; 89 76 f4 ; 0xf3508
+ cmp ax, si ; 39 f0 ; 0xf350b floppy.c:722
+ jbe short 03511h ; 76 02 ; 0xf350d
+ db 0feh, 0c5h
+ ; inc ch ; fe c5 ; 0xf350f floppy.c:724
+ mov al, bh ; 88 f8 ; 0xf3511 floppy.c:726
+ xor ah, ah ; 30 e4 ; 0xf3513
+ mov CL, strict byte 009h ; b1 09 ; 0xf3515
+ sal ax, CL ; d3 e0 ; 0xf3517
+ dec ax ; 48 ; 0xf3519
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf351a
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf351d floppy.c:729
+ add ax, word [bp-00eh] ; 03 46 f2 ; 0xf3520
+ cmp ax, word [bp-00ch] ; 3b 46 f4 ; 0xf3523 floppy.c:730
+ jnc short 0352bh ; 73 03 ; 0xf3526
+ jmp near 0337fh ; e9 54 fe ; 0xf3528
+ mov AL, strict byte 006h ; b0 06 ; 0xf352b floppy.c:739
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf352d
+ out DX, AL ; ee ; 0xf3530
+ xor al, al ; 30 c0 ; 0xf3531 floppy.c:741
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3533
+ out DX, AL ; ee ; 0xf3536
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3537 floppy.c:742
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf353a
+ out DX, AL ; ee ; 0xf353d
+ mov al, byte [bp-00bh] ; 8a 46 f5 ; 0xf353e floppy.c:743
+ out DX, AL ; ee ; 0xf3541
+ xor al, al ; 30 c0 ; 0xf3542 floppy.c:744
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3544
+ out DX, AL ; ee ; 0xf3547
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf3548 floppy.c:745
+ mov dx, strict word 00005h ; ba 05 00 ; 0xf354b
+ out DX, AL ; ee ; 0xf354e
+ mov al, byte [bp-00dh] ; 8a 46 f3 ; 0xf354f floppy.c:746
+ out DX, AL ; ee ; 0xf3552
+ mov AL, strict byte 04ah ; b0 4a ; 0xf3553 floppy.c:753
+ mov dx, strict word 0000bh ; ba 0b 00 ; 0xf3555
+ out DX, AL ; ee ; 0xf3558
+ mov al, ch ; 88 e8 ; 0xf3559 floppy.c:756
+ mov dx, 00081h ; ba 81 00 ; 0xf355b
+ out DX, AL ; ee ; 0xf355e
+ mov AL, strict byte 002h ; b0 02 ; 0xf355f floppy.c:759
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf3561
+ out DX, AL ; ee ; 0xf3564
+ mov cl, bl ; 88 d9 ; 0xf3565 floppy.c:764
+ xor ch, ch ; 30 ed ; 0xf3567
+ mov ax, cx ; 89 c8 ; 0xf3569
+ call 02f22h ; e8 b4 f9 ; 0xf356b
+ mov AL, strict byte 0c5h ; b0 c5 ; 0xf356e floppy.c:767
+ mov dx, 003f5h ; ba f5 03 ; 0xf3570
+ out DX, AL ; ee ; 0xf3573
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf3574 floppy.c:768
+ xor ah, ah ; 30 e4 ; 0xf3577
+ mov dx, ax ; 89 c2 ; 0xf3579
+ sal dx, 1 ; d1 e2 ; 0xf357b
+ sal dx, 1 ; d1 e2 ; 0xf357d
+ mov al, bl ; 88 d8 ; 0xf357f
+ or ax, dx ; 09 d0 ; 0xf3581
+ mov dx, 003f5h ; ba f5 03 ; 0xf3583
+ out DX, AL ; ee ; 0xf3586
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf3587 floppy.c:769
+ out DX, AL ; ee ; 0xf358a
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf358b floppy.c:770
+ out DX, AL ; ee ; 0xf358e
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf358f floppy.c:771
+ out DX, AL ; ee ; 0xf3592
+ mov AL, strict byte 002h ; b0 02 ; 0xf3593 floppy.c:772
+ out DX, AL ; ee ; 0xf3595
+ mov dl, byte [bp-002h] ; 8a 56 fe ; 0xf3596 floppy.c:773
+ xor dh, dh ; 30 f6 ; 0xf3599
+ mov al, bh ; 88 f8 ; 0xf359b
+ xor ah, ah ; 30 e4 ; 0xf359d
+ add ax, dx ; 01 d0 ; 0xf359f
+ dec ax ; 48 ; 0xf35a1
+ mov dx, 003f5h ; ba f5 03 ; 0xf35a2
+ out DX, AL ; ee ; 0xf35a5
+ xor al, al ; 30 c0 ; 0xf35a6 floppy.c:774
+ out DX, AL ; ee ; 0xf35a8
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf35a9 floppy.c:775
+ out DX, AL ; ee ; 0xf35ab
+ call 02eabh ; e8 fc f8 ; 0xf35ac floppy.c:804
+ test al, al ; 84 c0 ; 0xf35af floppy.c:805
+ jne short 035b6h ; 75 03 ; 0xf35b1
+ jmp near 03424h ; e9 6e fe ; 0xf35b3
+ mov dx, 003f4h ; ba f4 03 ; 0xf35b6 floppy.c:816
+ in AL, DX ; ec ; 0xf35b9
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf35ba
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf35bc floppy.c:817
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xf35be
+ je short 035d4h ; 74 12 ; 0xf35c0
+ mov ax, 00275h ; b8 75 02 ; 0xf35c2 floppy.c:818
+ push ax ; 50 ; 0xf35c5
+ mov ax, 002a8h ; b8 a8 02 ; 0xf35c6
+ push ax ; 50 ; 0xf35c9
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf35ca
+ push ax ; 50 ; 0xf35cd
+ call 0190fh ; e8 3e e3 ; 0xf35ce
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf35d1
+ xor cx, cx ; 31 c9 ; 0xf35d4 floppy.c:821
+ jmp short 035ddh ; eb 05 ; 0xf35d6
+ cmp cx, strict byte 00007h ; 83 f9 07 ; 0xf35d8
+ jnl short 035f3h ; 7d 16 ; 0xf35db
+ mov dx, 003f5h ; ba f5 03 ; 0xf35dd floppy.c:822
+ in AL, DX ; ec ; 0xf35e0
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf35e1
+ mov si, cx ; 89 ce ; 0xf35e3
+ add si, strict byte 00042h ; 83 c6 42 ; 0xf35e5
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf35e8 floppy.c:43
+ mov es, dx ; 8e c2 ; 0xf35eb
+ mov byte [es:si], al ; 26 88 04 ; 0xf35ed
+ inc cx ; 41 ; 0xf35f0 floppy.c:822
+ jmp short 035d8h ; eb e5 ; 0xf35f1
+ mov si, strict word 00042h ; be 42 00 ; 0xf35f3 floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf35f6
+ mov es, ax ; 8e c0 ; 0xf35f9
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf35fb
+ test AL, strict byte 0c0h ; a8 c0 ; 0xf35fe floppy.c:39
+ jne short 03605h ; 75 03 ; 0xf3600
+ jmp near 034cfh ; e9 ca fe ; 0xf3602
+ mov bx, strict word 00043h ; bb 43 00 ; 0xf3605 floppy.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf3608
+ test AL, strict byte 002h ; a8 02 ; 0xf360b floppy.c:39
+ je short 03617h ; 74 08 ; 0xf360d
+ mov word [bp+016h], 00300h ; c7 46 16 00 03 ; 0xf360f floppy.c:829
+ jmp near 03a6dh ; e9 56 04 ; 0xf3614
+ mov word [bp+016h], 00100h ; c7 46 16 00 01 ; 0xf3617 floppy.c:832
+ jmp near 03a6dh ; e9 4e 04 ; 0xf361c floppy.c:833
+ mov dl, byte [bp-004h] ; 8a 56 fc ; 0xf361f floppy.c:848
+ xor dh, dh ; 30 f6 ; 0xf3622
+ mov al, bl ; 88 d8 ; 0xf3624
+ xor ah, ah ; 30 e4 ; 0xf3626
+ call 02e5ch ; e8 31 f8 ; 0xf3628
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf362b floppy.c:850
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf362f floppy.c:851
+ jmp near 03267h ; e9 31 fc ; 0xf3633 floppy.c:852
+ mov bh, byte [bp+016h] ; 8a 7e 16 ; 0xf3636 floppy.c:859
+ mov dl, byte [bp+015h] ; 8a 56 15 ; 0xf3639 floppy.c:860
+ xor dh, dh ; 30 f6 ; 0xf363c
+ mov byte [bp-004h], dl ; 88 56 fc ; 0xf363e
+ mov al, byte [bp+013h] ; 8a 46 13 ; 0xf3641 floppy.c:861
+ xor ah, ah ; 30 e4 ; 0xf3644
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf3646
+ mov bl, byte [bp+00eh] ; 8a 5e 0e ; 0xf3649 floppy.c:862
+ cmp bl, 001h ; 80 fb 01 ; 0xf364c floppy.c:864
+ jnbe short 03663h ; 77 12 ; 0xf364f
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf3651
+ jnbe short 03663h ; 77 0e ; 0xf3653
+ cmp dl, 04fh ; 80 fa 4f ; 0xf3655
+ jnbe short 03663h ; 77 09 ; 0xf3658
+ test bh, bh ; 84 ff ; 0xf365a
+ je short 03663h ; 74 05 ; 0xf365c
+ cmp bh, 012h ; 80 ff 12 ; 0xf365e
+ jbe short 0367eh ; 76 1b ; 0xf3661
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3663 floppy.c:866
+ xor ah, ah ; 30 e4 ; 0xf3666
+ or ah, 001h ; 80 cc 01 ; 0xf3668
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf366b
+ mov si, strict word 00041h ; be 41 00 ; 0xf366e floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3671
+ mov es, ax ; 8e c0 ; 0xf3674
+ mov byte [es:si], 001h ; 26 c6 04 01 ; 0xf3676
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf367a floppy.c:868
+ mov al, bl ; 88 d8 ; 0xf367e floppy.c:872
+ xor ah, ah ; 30 e4 ; 0xf3680
+ call 0315dh ; e8 d8 fa ; 0xf3682
+ test ax, ax ; 85 c0 ; 0xf3685
+ jne short 036a3h ; 75 1a ; 0xf3687
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3689 floppy.c:873
+ xor ah, ah ; 30 e4 ; 0xf368c
+ or ah, 080h ; 80 cc 80 ; 0xf368e
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3691
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3694 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3697
+ mov es, ax ; 8e c0 ; 0xf369a
+ mov byte [es:bx], 080h ; 26 c6 07 80 ; 0xf369c
+ jmp near 03a6dh ; e9 ca 03 ; 0xf36a0
+ mov cl, bl ; 88 d9 ; 0xf36a3 floppy.c:880
+ xor ch, ch ; 30 ed ; 0xf36a5
+ mov ax, cx ; 89 c8 ; 0xf36a7
+ call 02f97h ; e8 eb f8 ; 0xf36a9
+ test ax, ax ; 85 c0 ; 0xf36ac
+ jne short 036bch ; 75 0c ; 0xf36ae
+ mov ax, cx ; 89 c8 ; 0xf36b0 floppy.c:881
+ call 03076h ; e8 c1 f9 ; 0xf36b2
+ test ax, ax ; 85 c0 ; 0xf36b5
+ jne short 036bch ; 75 03 ; 0xf36b7
+ jmp near 03323h ; e9 67 fc ; 0xf36b9
+ mov CL, strict byte 00ch ; b1 0c ; 0xf36bc floppy.c:892
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf36be
+ shr ax, CL ; d3 e8 ; 0xf36c1
+ mov ch, al ; 88 c5 ; 0xf36c3
+ mov CL, strict byte 004h ; b1 04 ; 0xf36c5 floppy.c:893
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf36c7
+ sal dx, CL ; d3 e2 ; 0xf36ca
+ mov si, word [bp+010h] ; 8b 76 10 ; 0xf36cc floppy.c:894
+ add si, dx ; 01 d6 ; 0xf36cf
+ mov word [bp-00ch], si ; 89 76 f4 ; 0xf36d1
+ cmp dx, si ; 39 f2 ; 0xf36d4 floppy.c:896
+ jbe short 036dah ; 76 02 ; 0xf36d6
+ db 0feh, 0c5h
+ ; inc ch ; fe c5 ; 0xf36d8 floppy.c:898
+ mov al, bh ; 88 f8 ; 0xf36da floppy.c:900
+ xor ah, ah ; 30 e4 ; 0xf36dc
+ sal ax, 1 ; d1 e0 ; 0xf36de
+ sal ax, 1 ; d1 e0 ; 0xf36e0
+ dec ax ; 48 ; 0xf36e2
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf36e3
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf36e6 floppy.c:903
+ add ax, word [bp-00eh] ; 03 46 f2 ; 0xf36e9
+ cmp ax, word [bp-00ch] ; 3b 46 f4 ; 0xf36ec floppy.c:904
+ jnc short 0370bh ; 73 1a ; 0xf36ef
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf36f1 floppy.c:905
+ xor ah, ah ; 30 e4 ; 0xf36f4
+ or ah, 009h ; 80 cc 09 ; 0xf36f6
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf36f9
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf36fc floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf36ff
+ mov es, ax ; 8e c0 ; 0xf3702
+ mov byte [es:bx], 009h ; 26 c6 07 09 ; 0xf3704
+ jmp near 03392h ; e9 87 fc ; 0xf3708
+ mov AL, strict byte 006h ; b0 06 ; 0xf370b floppy.c:912
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf370d
+ out DX, AL ; ee ; 0xf3710
+ xor al, al ; 30 c0 ; 0xf3711 floppy.c:913
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3713
+ out DX, AL ; ee ; 0xf3716
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3717 floppy.c:914
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf371a
+ out DX, AL ; ee ; 0xf371d
+ mov al, byte [bp-00bh] ; 8a 46 f5 ; 0xf371e floppy.c:915
+ out DX, AL ; ee ; 0xf3721
+ xor al, al ; 30 c0 ; 0xf3722 floppy.c:916
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3724
+ out DX, AL ; ee ; 0xf3727
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf3728 floppy.c:917
+ mov dx, strict word 00005h ; ba 05 00 ; 0xf372b
+ out DX, AL ; ee ; 0xf372e
+ mov al, byte [bp-00dh] ; 8a 46 f3 ; 0xf372f floppy.c:918
+ out DX, AL ; ee ; 0xf3732
+ mov AL, strict byte 04ah ; b0 4a ; 0xf3733 floppy.c:921
+ mov dx, strict word 0000bh ; ba 0b 00 ; 0xf3735
+ out DX, AL ; ee ; 0xf3738
+ mov al, ch ; 88 e8 ; 0xf3739 floppy.c:923
+ mov dx, 00081h ; ba 81 00 ; 0xf373b
+ out DX, AL ; ee ; 0xf373e
+ mov AL, strict byte 002h ; b0 02 ; 0xf373f floppy.c:924
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf3741
+ out DX, AL ; ee ; 0xf3744
+ mov cl, bl ; 88 d9 ; 0xf3745 floppy.c:927
+ xor ch, ch ; 30 ed ; 0xf3747
+ mov ax, cx ; 89 c8 ; 0xf3749
+ call 02f22h ; e8 d4 f7 ; 0xf374b
+ mov AL, strict byte 00fh ; b0 0f ; 0xf374e floppy.c:930
+ mov dx, 003f5h ; ba f5 03 ; 0xf3750
+ out DX, AL ; ee ; 0xf3753
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf3754 floppy.c:931
+ xor ah, ah ; 30 e4 ; 0xf3757
+ mov dx, ax ; 89 c2 ; 0xf3759
+ sal dx, 1 ; d1 e2 ; 0xf375b
+ sal dx, 1 ; d1 e2 ; 0xf375d
+ mov al, bl ; 88 d8 ; 0xf375f
+ or dx, ax ; 09 c2 ; 0xf3761
+ mov word [bp-008h], dx ; 89 56 f8 ; 0xf3763
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf3766
+ mov dx, 003f5h ; ba f5 03 ; 0xf3769
+ out DX, AL ; ee ; 0xf376c
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf376d floppy.c:932
+ out DX, AL ; ee ; 0xf3770
+ mov AL, strict byte 04dh ; b0 4d ; 0xf3771 floppy.c:935
+ out DX, AL ; ee ; 0xf3773
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf3774 floppy.c:936
+ out DX, AL ; ee ; 0xf3777
+ mov AL, strict byte 002h ; b0 02 ; 0xf3778 floppy.c:937
+ out DX, AL ; ee ; 0xf377a
+ mov al, bh ; 88 f8 ; 0xf377b floppy.c:938
+ out DX, AL ; ee ; 0xf377d
+ xor al, bh ; 30 f8 ; 0xf377e floppy.c:939
+ out DX, AL ; ee ; 0xf3780
+ mov AL, strict byte 0f6h ; b0 f6 ; 0xf3781 floppy.c:940
+ out DX, AL ; ee ; 0xf3783
+ call 02eabh ; e8 24 f7 ; 0xf3784 floppy.c:968
+ test al, al ; 84 c0 ; 0xf3787 floppy.c:969
+ jne short 03793h ; 75 08 ; 0xf3789
+ mov ax, cx ; 89 c8 ; 0xf378b floppy.c:970
+ call 02ee3h ; e8 53 f7 ; 0xf378d
+ jmp near 03689h ; e9 f6 fe ; 0xf3790 floppy.c:68
+ mov dx, 003f4h ; ba f4 03 ; 0xf3793 floppy.c:979
+ in AL, DX ; ec ; 0xf3796
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf3797
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf3799 floppy.c:980
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xf379b
+ je short 037b1h ; 74 12 ; 0xf379d
+ mov ax, 00275h ; b8 75 02 ; 0xf379f floppy.c:981
+ push ax ; 50 ; 0xf37a2
+ mov ax, 002a8h ; b8 a8 02 ; 0xf37a3
+ push ax ; 50 ; 0xf37a6
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf37a7
+ push ax ; 50 ; 0xf37aa
+ call 0190fh ; e8 61 e1 ; 0xf37ab
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf37ae
+ xor cx, cx ; 31 c9 ; 0xf37b1 floppy.c:984
+ jmp short 037bah ; eb 05 ; 0xf37b3
+ cmp cx, strict byte 00007h ; 83 f9 07 ; 0xf37b5
+ jnl short 037d0h ; 7d 16 ; 0xf37b8
+ mov dx, 003f5h ; ba f5 03 ; 0xf37ba floppy.c:985
+ in AL, DX ; ec ; 0xf37bd
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf37be
+ mov si, cx ; 89 ce ; 0xf37c0
+ add si, strict byte 00042h ; 83 c6 42 ; 0xf37c2
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf37c5 floppy.c:43
+ mov es, dx ; 8e c2 ; 0xf37c8
+ mov byte [es:si], al ; 26 88 04 ; 0xf37ca
+ inc cx ; 41 ; 0xf37cd floppy.c:985
+ jmp short 037b5h ; eb e5 ; 0xf37ce
+ mov si, strict word 00042h ; be 42 00 ; 0xf37d0 floppy.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf37d3
+ mov es, ax ; 8e c0 ; 0xf37d6
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf37d8
+ test AL, strict byte 0c0h ; a8 c0 ; 0xf37db floppy.c:39
+ je short 037feh ; 74 1f ; 0xf37dd
+ mov si, strict word 00043h ; be 43 00 ; 0xf37df floppy.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf37e2
+ test AL, strict byte 002h ; a8 02 ; 0xf37e5 floppy.c:39
+ je short 037ech ; 74 03 ; 0xf37e7
+ jmp near 0360fh ; e9 23 fe ; 0xf37e9
+ mov ax, 00275h ; b8 75 02 ; 0xf37ec floppy.c:996
+ push ax ; 50 ; 0xf37ef
+ mov ax, 002bch ; b8 bc 02 ; 0xf37f0
+ push ax ; 50 ; 0xf37f3
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf37f4
+ push ax ; 50 ; 0xf37f7
+ call 0190fh ; e8 14 e1 ; 0xf37f8
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf37fb
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf37fe floppy.c:1000
+ mov si, strict word 00041h ; be 41 00 ; 0xf3802 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3805
+ mov es, ax ; 8e c0 ; 0xf3808
+ mov byte [es:si], 000h ; 26 c6 04 00 ; 0xf380a
+ mov al, bl ; 88 d8 ; 0xf380e floppy.c:1002
+ xor ah, ah ; 30 e4 ; 0xf3810
+ xor dx, dx ; 31 d2 ; 0xf3812
+ call 02e5ch ; e8 45 f6 ; 0xf3814
+ jmp near 034dfh ; e9 c5 fc ; 0xf3817
+ mov bl, dl ; 88 d3 ; 0xf381a floppy.c:1009
+ cmp dl, 001h ; 80 fa 01 ; 0xf381c floppy.c:1011
+ jbe short 03847h ; 76 26 ; 0xf381f
+ mov word [bp+016h], strict word 00000h ; c7 46 16 00 00 ; 0xf3821 floppy.c:1012
+ mov word [bp+010h], strict word 00000h ; c7 46 10 00 00 ; 0xf3826 floppy.c:1013
+ mov word [bp+014h], strict word 00000h ; c7 46 14 00 00 ; 0xf382b floppy.c:1014
+ mov word [bp+012h], strict word 00000h ; c7 46 12 00 00 ; 0xf3830 floppy.c:1015
+ mov word [bp+006h], strict word 00000h ; c7 46 06 00 00 ; 0xf3835 floppy.c:1016
+ mov word [bp+008h], strict word 00000h ; c7 46 08 00 00 ; 0xf383a floppy.c:1017
+ mov dl, bh ; 88 fa ; 0xf383f floppy.c:1018
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf3841
+ jmp near 0396ch ; e9 25 01 ; 0xf3844
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf3847 floppy.c:1019
+ call 01652h ; e8 05 de ; 0xf384a
+ mov dl, al ; 88 c2 ; 0xf384d
+ xor bh, bh ; 30 ff ; 0xf384f floppy.c:1025
+ test AL, strict byte 0f0h ; a8 f0 ; 0xf3851 floppy.c:1026
+ je short 03857h ; 74 02 ; 0xf3853
+ mov BH, strict byte 001h ; b7 01 ; 0xf3855 floppy.c:1027
+ test dl, 00fh ; f6 c2 0f ; 0xf3857 floppy.c:1028
+ je short 0385eh ; 74 02 ; 0xf385a
+ db 0feh, 0c7h
+ ; inc bh ; fe c7 ; 0xf385c floppy.c:1029
+ test bl, bl ; 84 db ; 0xf385e floppy.c:1031
+ jne short 03868h ; 75 06 ; 0xf3860
+ mov CL, strict byte 004h ; b1 04 ; 0xf3862 floppy.c:1032
+ shr dl, CL ; d2 ea ; 0xf3864
+ jmp short 0386bh ; eb 03 ; 0xf3866 floppy.c:1033
+ and dl, 00fh ; 80 e2 0f ; 0xf3868 floppy.c:1034
+ mov byte [bp+011h], 000h ; c6 46 11 00 ; 0xf386b floppy.c:1037
+ mov al, dl ; 88 d0 ; 0xf386f
+ xor ah, ah ; 30 e4 ; 0xf3871
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf3873
+ xor al, dl ; 30 d0 ; 0xf3876 floppy.c:1038
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3878
+ mov cx, word [bp+012h] ; 8b 4e 12 ; 0xf387b floppy.c:1040
+ mov cl, bh ; 88 f9 ; 0xf387e
+ mov word [bp+012h], cx ; 89 4e 12 ; 0xf3880
+ mov ax, cx ; 89 c8 ; 0xf3883 floppy.c:1041
+ xor ah, ch ; 30 ec ; 0xf3885
+ or ah, 001h ; 80 cc 01 ; 0xf3887
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf388a
+ cmp dl, 003h ; 80 fa 03 ; 0xf388d floppy.c:1043
+ jc short 038a7h ; 72 15 ; 0xf3890
+ jbe short 038ceh ; 76 3a ; 0xf3892
+ cmp dl, 005h ; 80 fa 05 ; 0xf3894
+ jc short 038d5h ; 72 3c ; 0xf3897
+ jbe short 038dch ; 76 41 ; 0xf3899
+ cmp dl, 00fh ; 80 fa 0f ; 0xf389b
+ je short 038eah ; 74 4a ; 0xf389e
+ cmp dl, 00eh ; 80 fa 0e ; 0xf38a0
+ je short 038e3h ; 74 3e ; 0xf38a3
+ jmp short 038f1h ; eb 4a ; 0xf38a5
+ cmp dl, 002h ; 80 fa 02 ; 0xf38a7
+ je short 038c7h ; 74 1b ; 0xf38aa
+ cmp dl, 001h ; 80 fa 01 ; 0xf38ac
+ je short 038c0h ; 74 0f ; 0xf38af
+ test dl, dl ; 84 d2 ; 0xf38b1
+ jne short 038f1h ; 75 3c ; 0xf38b3
+ mov word [bp+014h], strict word 00000h ; c7 46 14 00 00 ; 0xf38b5 floppy.c:1045
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf38ba floppy.c:1046
+ jmp short 03903h ; eb 43 ; 0xf38be floppy.c:1047
+ mov word [bp+014h], 02709h ; c7 46 14 09 27 ; 0xf38c0 floppy.c:1050
+ jmp short 03903h ; eb 3c ; 0xf38c5 floppy.c:1051
+ mov word [bp+014h], 04f0fh ; c7 46 14 0f 4f ; 0xf38c7 floppy.c:1054
+ jmp short 03903h ; eb 35 ; 0xf38cc floppy.c:1055
+ mov word [bp+014h], 04f09h ; c7 46 14 09 4f ; 0xf38ce floppy.c:1058
+ jmp short 03903h ; eb 2e ; 0xf38d3 floppy.c:1059
+ mov word [bp+014h], 04f12h ; c7 46 14 12 4f ; 0xf38d5 floppy.c:1062
+ jmp short 03903h ; eb 27 ; 0xf38da floppy.c:1063
+ mov word [bp+014h], 04f24h ; c7 46 14 24 4f ; 0xf38dc floppy.c:1066
+ jmp short 03903h ; eb 20 ; 0xf38e1 floppy.c:1067
+ mov word [bp+014h], 0fe3fh ; c7 46 14 3f fe ; 0xf38e3 floppy.c:1070
+ jmp short 03903h ; eb 19 ; 0xf38e8 floppy.c:1071
+ mov word [bp+014h], 0feffh ; c7 46 14 ff fe ; 0xf38ea floppy.c:1074
+ jmp short 03903h ; eb 12 ; 0xf38ef floppy.c:1075
+ mov ax, 00275h ; b8 75 02 ; 0xf38f1 floppy.c:1079
+ push ax ; 50 ; 0xf38f4
+ mov ax, 002cdh ; b8 cd 02 ; 0xf38f5
+ push ax ; 50 ; 0xf38f8
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf38f9
+ push ax ; 50 ; 0xf38fc
+ call 0190fh ; e8 0f e0 ; 0xf38fd
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf3900
+ mov word [bp+006h], 0f000h ; c7 46 06 00 f0 ; 0xf3903 floppy.c:1083
+ mov al, dl ; 88 d0 ; 0xf3908 floppy.c:1084
+ xor ah, ah ; 30 e4 ; 0xf390a
+ call 03ba8h ; e8 99 02 ; 0xf390c
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf390f
+ jmp near 034dfh ; e9 ca fb ; 0xf3912
+ mov bl, dl ; 88 d3 ; 0xf3915 floppy.c:1091
+ cmp dl, 001h ; 80 fa 01 ; 0xf3917 floppy.c:1092
+ jbe short 03921h ; 76 05 ; 0xf391a
+ mov word [bp+016h], cx ; 89 4e 16 ; 0xf391c floppy.c:1093
+ jmp short 0396ch ; eb 4b ; 0xf391f
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf3921 floppy.c:1099
+ call 01652h ; e8 2b dd ; 0xf3924
+ test bl, bl ; 84 db ; 0xf3927 floppy.c:1100
+ jne short 03933h ; 75 08 ; 0xf3929
+ mov CL, strict byte 004h ; b1 04 ; 0xf392b floppy.c:1101
+ mov dl, al ; 88 c2 ; 0xf392d
+ shr dl, CL ; d2 ea ; 0xf392f
+ jmp short 03938h ; eb 05 ; 0xf3931 floppy.c:1102
+ mov dl, al ; 88 c2 ; 0xf3933 floppy.c:1103
+ and dl, 00fh ; 80 e2 0f ; 0xf3935
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf3938 floppy.c:1104
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf393c
+ xor ah, ah ; 30 e4 ; 0xf393f
+ test dl, dl ; 84 d2 ; 0xf3941 floppy.c:1105
+ je short 03952h ; 74 0d ; 0xf3943
+ cmp dl, 001h ; 80 fa 01 ; 0xf3945 floppy.c:1106
+ jbe short 0394fh ; 76 05 ; 0xf3948
+ or ah, 002h ; 80 cc 02 ; 0xf394a floppy.c:1108
+ jmp short 03952h ; eb 03 ; 0xf394d floppy.c:1109
+ or ah, 001h ; 80 cc 01 ; 0xf394f floppy.c:1110
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3952
+ jmp near 03267h ; e9 0f f9 ; 0xf3955 floppy.c:1113
+ cmp dl, 001h ; 80 fa 01 ; 0xf3958 floppy.c:1118
+ jbe short 03972h ; 76 15 ; 0xf395b
+ mov word [bp+016h], si ; 89 76 16 ; 0xf395d floppy.c:1119
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3960 floppy.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3963
+ mov es, dx ; 8e c2 ; 0xf3966
+ mov byte [es:bx], 001h ; 26 c6 07 01 ; 0xf3968
+ mov word [bp+01ch], ax ; 89 46 1c ; 0xf396c
+ jmp near 03267h ; e9 f5 f8 ; 0xf396f
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3972 floppy.c:1125
+ xor ah, ah ; 30 e4 ; 0xf3975
+ or ah, 006h ; 80 cc 06 ; 0xf3977
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf397a
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf397d floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3980
+ mov es, ax ; 8e c0 ; 0xf3983
+ mov byte [es:bx], 006h ; 26 c6 07 06 ; 0xf3985
+ jmp near 03a6dh ; e9 e1 00 ; 0xf3989
+ mov bl, dl ; 88 d3 ; 0xf398c floppy.c:1134
+ mov cl, byte [bp+016h] ; 8a 4e 16 ; 0xf398e floppy.c:1142
+ cmp dl, 001h ; 80 fa 01 ; 0xf3991 floppy.c:1146
+ jnbe short 0395dh ; 77 c7 ; 0xf3994
+ mov al, bl ; 88 d8 ; 0xf3996 floppy.c:1154
+ xor ah, ah ; 30 e4 ; 0xf3998
+ call 0315dh ; e8 c0 f7 ; 0xf399a
+ test ax, ax ; 85 c0 ; 0xf399d
+ jne short 039a4h ; 75 03 ; 0xf399f
+ jmp near 03689h ; e9 e5 fc ; 0xf39a1
+ test bl, bl ; 84 db ; 0xf39a4 floppy.c:1162
+ je short 039adh ; 74 05 ; 0xf39a6
+ mov bx, 00091h ; bb 91 00 ; 0xf39a8
+ jmp short 039b0h ; eb 03 ; 0xf39ab
+ mov bx, 00090h ; bb 90 00 ; 0xf39ad
+ mov word [bp-00ch], bx ; 89 5e f4 ; 0xf39b0
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf39b3 floppy.c:38
+ mov es, ax ; 8e c0 ; 0xf39b6
+ mov bl, byte [es:bx] ; 26 8a 1f ; 0xf39b8
+ and bl, 00fh ; 80 e3 0f ; 0xf39bb floppy.c:1166
+ cmp cl, 002h ; 80 f9 02 ; 0xf39be floppy.c:1168
+ jc short 039d2h ; 72 0f ; 0xf39c1
+ jbe short 039dfh ; 76 1a ; 0xf39c3
+ cmp cl, 004h ; 80 f9 04 ; 0xf39c5
+ je short 039dah ; 74 10 ; 0xf39c8
+ cmp cl, 003h ; 80 f9 03 ; 0xf39ca
+ je short 039e4h ; 74 15 ; 0xf39cd
+ jmp near 031f1h ; e9 1f f8 ; 0xf39cf
+ cmp cl, 001h ; 80 f9 01 ; 0xf39d2
+ je short 039dah ; 74 03 ; 0xf39d5
+ jmp near 031f1h ; e9 17 f8 ; 0xf39d7
+ or bl, 090h ; 80 cb 90 ; 0xf39da floppy.c:1171
+ jmp short 039e7h ; eb 08 ; 0xf39dd floppy.c:1172
+ or bl, 070h ; 80 cb 70 ; 0xf39df floppy.c:1175
+ jmp short 039e7h ; eb 03 ; 0xf39e2 floppy.c:1176
+ or bl, 010h ; 80 cb 10 ; 0xf39e4 floppy.c:1179
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf39e7 floppy.c:43
+ mov es, ax ; 8e c0 ; 0xf39ea
+ mov si, word [bp-00ch] ; 8b 76 f4 ; 0xf39ec
+ mov byte [es:si], bl ; 26 88 1c ; 0xf39ef
+ xor al, al ; 30 c0 ; 0xf39f2 floppy.c:1198
+ mov byte [bp+017h], al ; 88 46 17 ; 0xf39f4
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf39f7 floppy.c:43
+ mov byte [es:bx], al ; 26 88 07 ; 0xf39fa
+ jmp near 034dfh ; e9 df fa ; 0xf39fd
+ mov bl, dl ; 88 d3 ; 0xf3a00 floppy.c:1208
+ mov cl, byte [bp+014h] ; 8a 4e 14 ; 0xf3a02 floppy.c:1210
+ mov bh, cl ; 88 cf ; 0xf3a05 floppy.c:1211
+ and bh, 03fh ; 80 e7 3f ; 0xf3a07
+ mov byte [bp-00ah], cl ; 88 4e f6 ; 0xf3a0a floppy.c:1212
+ mov byte [bp-009h], dh ; 88 76 f7 ; 0xf3a0d
+ mov CL, strict byte 006h ; b1 06 ; 0xf3a10
+ mov di, word [bp-00ah] ; 8b 7e f6 ; 0xf3a12
+ sar di, CL ; d3 ff ; 0xf3a15
+ mov cx, di ; 89 f9 ; 0xf3a17
+ mov byte [bp-009h], cl ; 88 4e f7 ; 0xf3a19
+ mov byte [bp-00ah], dh ; 88 76 f6 ; 0xf3a1c
+ mov cl, byte [bp+015h] ; 8a 4e 15 ; 0xf3a1f
+ xor ch, ch ; 30 ed ; 0xf3a22
+ add cx, word [bp-00ah] ; 03 4e f6 ; 0xf3a24
+ mov byte [bp-004h], cl ; 88 4e fc ; 0xf3a27
+ cmp dl, 001h ; 80 fa 01 ; 0xf3a2a floppy.c:1217
+ jbe short 03a32h ; 76 03 ; 0xf3a2d
+ jmp near 0395dh ; e9 2b ff ; 0xf3a2f
+ mov al, bl ; 88 d8 ; 0xf3a32 floppy.c:1225
+ xor ah, ah ; 30 e4 ; 0xf3a34
+ call 0315dh ; e8 24 f7 ; 0xf3a36
+ test ax, ax ; 85 c0 ; 0xf3a39
+ jne short 03a40h ; 75 03 ; 0xf3a3b
+ jmp near 03689h ; e9 49 fc ; 0xf3a3d
+ mov cl, bl ; 88 d9 ; 0xf3a40 floppy.c:1233
+ xor ch, ch ; 30 ed ; 0xf3a42
+ mov ax, cx ; 89 c8 ; 0xf3a44
+ call 02f97h ; e8 4e f5 ; 0xf3a46
+ test ax, ax ; 85 c0 ; 0xf3a49
+ jne short 03a74h ; 75 27 ; 0xf3a4b
+ mov ax, cx ; 89 c8 ; 0xf3a4d floppy.c:1234
+ call 03076h ; e8 24 f6 ; 0xf3a4f
+ test ax, ax ; 85 c0 ; 0xf3a52
+ jne short 03a74h ; 75 1e ; 0xf3a54
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3a56 floppy.c:1235
+ xor ah, ah ; 30 e4 ; 0xf3a59
+ or ah, 00ch ; 80 cc 0c ; 0xf3a5b
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3a5e
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3a61 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3a64
+ mov es, ax ; 8e c0 ; 0xf3a67
+ mov byte [es:bx], 00ch ; 26 c6 07 0c ; 0xf3a69
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf3a6d
+ jmp near 03267h ; e9 f3 f7 ; 0xf3a71
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf3a74 floppy.c:1243
+ call 01652h ; e8 d8 db ; 0xf3a77
+ test bl, bl ; 84 db ; 0xf3a7a floppy.c:1244
+ jne short 03a86h ; 75 08 ; 0xf3a7c
+ mov CL, strict byte 004h ; b1 04 ; 0xf3a7e floppy.c:1245
+ mov dl, al ; 88 c2 ; 0xf3a80
+ shr dl, CL ; d2 ea ; 0xf3a82
+ jmp short 03a8bh ; eb 05 ; 0xf3a84 floppy.c:1246
+ mov dl, al ; 88 c2 ; 0xf3a86 floppy.c:1247
+ and dl, 00fh ; 80 e2 0f ; 0xf3a88
+ test bl, bl ; 84 db ; 0xf3a8b floppy.c:1250
+ je short 03a94h ; 74 05 ; 0xf3a8d
+ mov si, 00091h ; be 91 00 ; 0xf3a8f
+ jmp short 03a97h ; eb 03 ; 0xf3a92
+ mov si, 00090h ; be 90 00 ; 0xf3a94
+ mov word [bp-00ch], si ; 89 76 f4 ; 0xf3a97
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3a9a floppy.c:38
+ mov es, ax ; 8e c0 ; 0xf3a9d
+ mov bl, byte [es:si] ; 26 8a 1c ; 0xf3a9f
+ and bl, 00fh ; 80 e3 0f ; 0xf3aa2 floppy.c:39
+ cmp dl, 003h ; 80 fa 03 ; 0xf3aa5 floppy.c:1256
+ jc short 03ac5h ; 72 1b ; 0xf3aa8
+ mov al, bl ; 88 d8 ; 0xf3aaa
+ or AL, strict byte 090h ; 0c 90 ; 0xf3aac
+ cmp dl, 003h ; 80 fa 03 ; 0xf3aae
+ jbe short 03b01h ; 76 4e ; 0xf3ab1
+ mov ah, bl ; 88 dc ; 0xf3ab3
+ or ah, 010h ; 80 cc 10 ; 0xf3ab5
+ cmp dl, 005h ; 80 fa 05 ; 0xf3ab8
+ je short 03affh ; 74 42 ; 0xf3abb
+ cmp dl, 004h ; 80 fa 04 ; 0xf3abd
+ je short 03b0eh ; 74 4c ; 0xf3ac0
+ jmp near 03b46h ; e9 81 00 ; 0xf3ac2
+ cmp dl, 002h ; 80 fa 02 ; 0xf3ac5
+ je short 03adfh ; 74 15 ; 0xf3ac8
+ cmp dl, 001h ; 80 fa 01 ; 0xf3aca
+ jne short 03b12h ; 75 43 ; 0xf3acd
+ cmp byte [bp-004h], 027h ; 80 7e fc 27 ; 0xf3acf floppy.c:1258
+ jne short 03b12h ; 75 3d ; 0xf3ad3
+ cmp bh, 009h ; 80 ff 09 ; 0xf3ad5
+ jne short 03b28h ; 75 4e ; 0xf3ad8
+ or bl, 090h ; 80 cb 90 ; 0xf3ada floppy.c:1259
+ jmp short 03b28h ; eb 49 ; 0xf3add floppy.c:1261
+ cmp byte [bp-004h], 027h ; 80 7e fc 27 ; 0xf3adf floppy.c:1263
+ jne short 03aefh ; 75 0a ; 0xf3ae3
+ cmp bh, 009h ; 80 ff 09 ; 0xf3ae5
+ jne short 03aefh ; 75 05 ; 0xf3ae8
+ or bl, 070h ; 80 cb 70 ; 0xf3aea floppy.c:1264
+ jmp short 03b28h ; eb 39 ; 0xf3aed floppy.c:1265
+ cmp byte [bp-004h], 04fh ; 80 7e fc 4f ; 0xf3aef
+ jne short 03b46h ; 75 51 ; 0xf3af3
+ cmp bh, 00fh ; 80 ff 0f ; 0xf3af5
+ jne short 03b46h ; 75 4c ; 0xf3af8
+ or bl, 010h ; 80 cb 10 ; 0xf3afa floppy.c:1266
+ jmp short 03b46h ; eb 47 ; 0xf3afd floppy.c:1268
+ jmp short 03b2ah ; eb 29 ; 0xf3aff
+ cmp byte [bp-004h], 04fh ; 80 7e fc 4f ; 0xf3b01 floppy.c:1270
+ jne short 03b46h ; 75 3f ; 0xf3b05
+ cmp bh, 009h ; 80 ff 09 ; 0xf3b07
+ je short 03b10h ; 74 04 ; 0xf3b0a
+ jmp short 03b46h ; eb 38 ; 0xf3b0c
+ jmp short 03b14h ; eb 04 ; 0xf3b0e
+ mov bl, al ; 88 c3 ; 0xf3b10 floppy.c:1271
+ jmp short 03b46h ; eb 32 ; 0xf3b12 floppy.c:1273
+ cmp byte [bp-004h], 04fh ; 80 7e fc 4f ; 0xf3b14 floppy.c:1275
+ jne short 03b46h ; 75 2c ; 0xf3b18
+ cmp bh, 009h ; 80 ff 09 ; 0xf3b1a floppy.c:1276
+ jne short 03b21h ; 75 02 ; 0xf3b1d
+ jmp short 03b10h ; eb ef ; 0xf3b1f
+ cmp bh, 012h ; 80 ff 12 ; 0xf3b21 floppy.c:1277
+ jne short 03b46h ; 75 20 ; 0xf3b24
+ mov bl, ah ; 88 e3 ; 0xf3b26 floppy.c:1279
+ jmp short 03b46h ; eb 1c ; 0xf3b28 floppy.c:1282
+ cmp byte [bp-004h], 04fh ; 80 7e fc 4f ; 0xf3b2a floppy.c:1284
+ jne short 03b46h ; 75 16 ; 0xf3b2e
+ cmp bh, 009h ; 80 ff 09 ; 0xf3b30 floppy.c:1285
+ jne short 03b37h ; 75 02 ; 0xf3b33
+ jmp short 03b10h ; eb d9 ; 0xf3b35
+ cmp bh, 012h ; 80 ff 12 ; 0xf3b37 floppy.c:1286
+ jne short 03b3eh ; 75 02 ; 0xf3b3a
+ jmp short 03b26h ; eb e8 ; 0xf3b3c
+ cmp bh, 024h ; 80 ff 24 ; 0xf3b3e floppy.c:1288
+ jne short 03b46h ; 75 03 ; 0xf3b41
+ or bl, 0d0h ; 80 cb d0 ; 0xf3b43 floppy.c:1290
+ mov al, bl ; 88 d8 ; 0xf3b46 floppy.c:1299
+ xor ah, ah ; 30 e4 ; 0xf3b48
+ mov CL, strict byte 004h ; b1 04 ; 0xf3b4a
+ sar ax, CL ; d3 f8 ; 0xf3b4c
+ test AL, strict byte 001h ; a8 01 ; 0xf3b4e
+ jne short 03b55h ; 75 03 ; 0xf3b50
+ jmp near 03a56h ; e9 01 ff ; 0xf3b52
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3b55 floppy.c:43
+ mov es, ax ; 8e c0 ; 0xf3b58
+ mov si, word [bp-00ch] ; 8b 76 f4 ; 0xf3b5a
+ mov byte [es:si], bl ; 26 88 1c ; 0xf3b5d
+ mov word [bp+006h], 0f000h ; c7 46 06 00 f0 ; 0xf3b60 floppy.c:1312
+ mov al, dl ; 88 d0 ; 0xf3b65 floppy.c:1313
+ xor ah, ah ; 30 e4 ; 0xf3b67
+ call 03ba8h ; e8 3c 00 ; 0xf3b69
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf3b6c
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf3b6f floppy.c:1316
+ mov bx, strict word 00041h ; bb 41 00 ; 0xf3b73 floppy.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3b76
+ mov es, ax ; 8e c0 ; 0xf3b79
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3b7b
+ jmp near 034dfh ; e9 5d f9 ; 0xf3b7f
+ mov bx, 00da0h ; bb a0 0d ; 0xf3b82 floppy.c:1322
+ mov cx, ds ; 8c d9 ; 0xf3b85
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3b87
+ call 018cch ; e8 3f dd ; 0xf3b8a
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf3b8d
+ xor ah, ah ; 30 e4 ; 0xf3b90
+ push ax ; 50 ; 0xf3b92
+ mov ax, 00275h ; b8 75 02 ; 0xf3b93
+ push ax ; 50 ; 0xf3b96
+ mov ax, 002e2h ; b8 e2 02 ; 0xf3b97
+ push ax ; 50 ; 0xf3b9a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3b9b
+ push ax ; 50 ; 0xf3b9e
+ call 0190fh ; e8 6d dd ; 0xf3b9f
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf3ba2
+ jmp near 031f1h ; e9 49 f6 ; 0xf3ba5 floppy.c:68
+ ; disGetNextSymbol 0xf3ba8 LB 0x63a0 -> off=0x0 cb=0000000000000032 uValue=00000000000f25a8 'get_floppy_dpt'
+get_floppy_dpt: ; 0xf3ba8 LB 0x32
+ push bx ; 53 ; 0xf3ba8 floppyt.c:94
+ push dx ; 52 ; 0xf3ba9
+ push bp ; 55 ; 0xf3baa
+ mov bp, sp ; 89 e5 ; 0xf3bab
+ mov dl, al ; 88 c2 ; 0xf3bad
+ xor ax, ax ; 31 c0 ; 0xf3baf floppyt.c:98
+ jmp short 03bb9h ; eb 06 ; 0xf3bb1
+ inc ax ; 40 ; 0xf3bb3 floppyt.c:100
+ cmp ax, strict word 00007h ; 3d 07 00 ; 0xf3bb4
+ jnc short 03bd3h ; 73 1a ; 0xf3bb7
+ mov bx, ax ; 89 c3 ; 0xf3bb9
+ sal bx, 1 ; d1 e3 ; 0xf3bbb
+ cmp dl, byte [word bx+0005bh] ; 3a 97 5b 00 ; 0xf3bbd
+ jne short 03bb3h ; 75 f0 ; 0xf3bc1
+ mov al, byte [word bx+0005ch] ; 8a 87 5c 00 ; 0xf3bc3
+ xor ah, ah ; 30 e4 ; 0xf3bc7
+ mov bx, strict word 0000dh ; bb 0d 00 ; 0xf3bc9
+ imul bx ; f7 eb ; 0xf3bcc
+ add ax, strict word 00000h ; 05 00 00 ; 0xf3bce
+ jmp short 03bd6h ; eb 03 ; 0xf3bd1
+ mov ax, strict word 00041h ; b8 41 00 ; 0xf3bd3 floppyt.c:103
+ pop bp ; 5d ; 0xf3bd6 floppyt.c:104
+ pop dx ; 5a ; 0xf3bd7
+ pop bx ; 5b ; 0xf3bd8
+ retn ; c3 ; 0xf3bd9
+ ; disGetNextSymbol 0xf3bda LB 0x636e -> off=0x0 cb=0000000000000007 uValue=00000000000f25da 'dummy_soft_reset'
+dummy_soft_reset: ; 0xf3bda LB 0x7
+ push bp ; 55 ; 0xf3bda eltorito.c:126
+ mov bp, sp ; 89 e5 ; 0xf3bdb
+ xor ax, ax ; 31 c0 ; 0xf3bdd eltorito.c:129
+ pop bp ; 5d ; 0xf3bdf
+ retn ; c3 ; 0xf3be0
+ ; disGetNextSymbol 0xf3be1 LB 0x6367 -> off=0x0 cb=0000000000000017 uValue=00000000000f25e1 'cdemu_init'
+cdemu_init: ; 0xf3be1 LB 0x17
+ push bp ; 55 ; 0xf3be1 eltorito.c:155
+ mov bp, sp ; 89 e5 ; 0xf3be2
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3be4 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3be7
+ mov es, ax ; 8e c0 ; 0xf3bea
+ mov es, [es:bx] ; 26 8e 07 ; 0xf3bec
+ mov bx, 00366h ; bb 66 03 ; 0xf3bef eltorito.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3bf2
+ pop bp ; 5d ; 0xf3bf6 eltorito.c:162
+ retn ; c3 ; 0xf3bf7
+ ; disGetNextSymbol 0xf3bf8 LB 0x6350 -> off=0x0 cb=0000000000000016 uValue=00000000000f25f8 'cdemu_isactive'
+cdemu_isactive: ; 0xf3bf8 LB 0x16
+ push bp ; 55 ; 0xf3bf8 eltorito.c:164
+ mov bp, sp ; 89 e5 ; 0xf3bf9
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3bfb eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3bfe
+ mov es, ax ; 8e c0 ; 0xf3c01
+ mov es, [es:bx] ; 26 8e 07 ; 0xf3c03
+ mov bx, 00366h ; bb 66 03 ; 0xf3c06 eltorito.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf3c09
+ pop bp ; 5d ; 0xf3c0c eltorito.c:170
+ retn ; c3 ; 0xf3c0d
+ ; disGetNextSymbol 0xf3c0e LB 0x633a -> off=0x0 cb=0000000000000016 uValue=00000000000f260e 'cdemu_emulated_drive'
+cdemu_emulated_drive: ; 0xf3c0e LB 0x16
+ push bp ; 55 ; 0xf3c0e eltorito.c:172
+ mov bp, sp ; 89 e5 ; 0xf3c0f
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3c11 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3c14
+ mov es, ax ; 8e c0 ; 0xf3c17
+ mov es, [es:bx] ; 26 8e 07 ; 0xf3c19
+ mov bx, 00368h ; bb 68 03 ; 0xf3c1c eltorito.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf3c1f
+ pop bp ; 5d ; 0xf3c22 eltorito.c:178
+ retn ; c3 ; 0xf3c23
+ ; disGetNextSymbol 0xf3c24 LB 0x6324 -> off=0x0 cb=0000000000000180 uValue=00000000000f2624 'int13_eltorito'
+int13_eltorito: ; 0xf3c24 LB 0x180
+ push bp ; 55 ; 0xf3c24 eltorito.c:184
+ mov bp, sp ; 89 e5 ; 0xf3c25
+ push si ; 56 ; 0xf3c27
+ push di ; 57 ; 0xf3c28
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3c29 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3c2c
+ mov es, ax ; 8e c0 ; 0xf3c2f
+ mov di, word [es:bx] ; 26 8b 3f ; 0xf3c31
+ mov bx, 00366h ; bb 66 03 ; 0xf3c34 eltorito.c:190
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf3c37 eltorito.c:196
+ xor ah, ah ; 30 e4 ; 0xf3c3a
+ cmp ax, strict word 0004bh ; 3d 4b 00 ; 0xf3c3c
+ jc short 03c4bh ; 72 0a ; 0xf3c3f
+ jbe short 03c76h ; 76 33 ; 0xf3c41
+ cmp ax, strict word 0004dh ; 3d 4d 00 ; 0xf3c43
+ jbe short 03c50h ; 76 08 ; 0xf3c46
+ jmp near 03d68h ; e9 1d 01 ; 0xf3c48
+ cmp ax, strict word 0004ah ; 3d 4a 00 ; 0xf3c4b
+ jne short 03c73h ; 75 23 ; 0xf3c4e
+ mov bx, 00da0h ; bb a0 0d ; 0xf3c50 eltorito.c:202
+ mov cx, ds ; 8c d9 ; 0xf3c53
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3c55
+ call 018cch ; e8 71 dc ; 0xf3c58
+ push word [bp+016h] ; ff 76 16 ; 0xf3c5b
+ mov ax, 002fch ; b8 fc 02 ; 0xf3c5e
+ push ax ; 50 ; 0xf3c61
+ mov ax, 0030bh ; b8 0b 03 ; 0xf3c62
+ push ax ; 50 ; 0xf3c65
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3c66
+ push ax ; 50 ; 0xf3c69
+ call 0190fh ; e8 a2 dc ; 0xf3c6a
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf3c6d
+ jmp near 03d83h ; e9 10 01 ; 0xf3c70 eltorito.c:203
+ jmp near 03d68h ; e9 f2 00 ; 0xf3c73
+ mov es, [bp+004h] ; 8e 46 04 ; 0xf3c76 eltorito.c:41
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3c79
+ mov byte [es:si], 013h ; 26 c6 04 13 ; 0xf3c7c
+ inc si ; 46 ; 0xf3c80 eltorito.c:210
+ mov ax, es ; 8c c0 ; 0xf3c81 eltorito.c:41
+ mov es, di ; 8e c7 ; 0xf3c83
+ mov dl, byte [es:bx+001h] ; 26 8a 57 01 ; 0xf3c85
+ mov es, ax ; 8e c0 ; 0xf3c89 eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3c8b
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3c8e eltorito.c:211
+ inc si ; 46 ; 0xf3c91
+ inc si ; 46 ; 0xf3c92
+ mov es, di ; 8e c7 ; 0xf3c93 eltorito.c:41
+ mov dl, byte [es:bx+002h] ; 26 8a 57 02 ; 0xf3c95
+ mov es, ax ; 8e c0 ; 0xf3c99 eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3c9b
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3c9e eltorito.c:212
+ add si, strict byte 00003h ; 83 c6 03 ; 0xf3ca1
+ mov es, di ; 8e c7 ; 0xf3ca4 eltorito.c:41
+ mov dl, byte [es:bx+003h] ; 26 8a 57 03 ; 0xf3ca6
+ mov es, ax ; 8e c0 ; 0xf3caa eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3cac
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3caf eltorito.c:213
+ add si, strict byte 00004h ; 83 c6 04 ; 0xf3cb2
+ mov es, di ; 8e c7 ; 0xf3cb5 eltorito.c:61
+ mov dx, word [es:bx+008h] ; 26 8b 57 08 ; 0xf3cb7
+ mov cx, word [es:bx+00ah] ; 26 8b 4f 0a ; 0xf3cbb
+ mov es, ax ; 8e c0 ; 0xf3cbf eltorito.c:63
+ mov word [es:si], dx ; 26 89 14 ; 0xf3cc1
+ mov word [es:si+002h], cx ; 26 89 4c 02 ; 0xf3cc4
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3cc8 eltorito.c:214
+ add si, strict byte 00008h ; 83 c6 08 ; 0xf3ccb
+ mov es, di ; 8e c7 ; 0xf3cce eltorito.c:51
+ mov dx, word [es:bx+004h] ; 26 8b 57 04 ; 0xf3cd0
+ mov es, ax ; 8e c0 ; 0xf3cd4 eltorito.c:53
+ mov word [es:si], dx ; 26 89 14 ; 0xf3cd6
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3cd9 eltorito.c:215
+ add si, strict byte 0000ah ; 83 c6 0a ; 0xf3cdc
+ mov es, di ; 8e c7 ; 0xf3cdf eltorito.c:51
+ mov dx, word [es:bx+006h] ; 26 8b 57 06 ; 0xf3ce1
+ mov es, ax ; 8e c0 ; 0xf3ce5 eltorito.c:53
+ mov word [es:si], dx ; 26 89 14 ; 0xf3ce7
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3cea eltorito.c:216
+ add si, strict byte 0000ch ; 83 c6 0c ; 0xf3ced
+ mov es, di ; 8e c7 ; 0xf3cf0 eltorito.c:51
+ mov dx, word [es:bx+00ch] ; 26 8b 57 0c ; 0xf3cf2
+ mov es, ax ; 8e c0 ; 0xf3cf6 eltorito.c:53
+ mov word [es:si], dx ; 26 89 14 ; 0xf3cf8
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3cfb eltorito.c:217
+ add si, strict byte 0000eh ; 83 c6 0e ; 0xf3cfe
+ mov es, di ; 8e c7 ; 0xf3d01 eltorito.c:51
+ mov dx, word [es:bx+00eh] ; 26 8b 57 0e ; 0xf3d03
+ mov es, ax ; 8e c0 ; 0xf3d07 eltorito.c:53
+ mov word [es:si], dx ; 26 89 14 ; 0xf3d09
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3d0c eltorito.c:218
+ add si, strict byte 00010h ; 83 c6 10 ; 0xf3d0f
+ mov es, di ; 8e c7 ; 0xf3d12 eltorito.c:41
+ mov dl, byte [es:bx+012h] ; 26 8a 57 12 ; 0xf3d14
+ mov es, ax ; 8e c0 ; 0xf3d18 eltorito.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf3d1a
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3d1d eltorito.c:219
+ add si, strict byte 00011h ; 83 c6 11 ; 0xf3d20
+ mov dx, ax ; 89 c2 ; 0xf3d23 eltorito.c:41
+ mov es, di ; 8e c7 ; 0xf3d25
+ mov al, byte [es:bx+014h] ; 26 8a 47 14 ; 0xf3d27
+ mov es, dx ; 8e c2 ; 0xf3d2b eltorito.c:43
+ mov byte [es:si], al ; 26 88 04 ; 0xf3d2d
+ mov si, word [bp+00ah] ; 8b 76 0a ; 0xf3d30 eltorito.c:220
+ add si, strict byte 00012h ; 83 c6 12 ; 0xf3d33
+ mov es, di ; 8e c7 ; 0xf3d36 eltorito.c:41
+ mov al, byte [es:bx+010h] ; 26 8a 47 10 ; 0xf3d38
+ mov es, dx ; 8e c2 ; 0xf3d3c eltorito.c:43
+ mov byte [es:si], al ; 26 88 04 ; 0xf3d3e
+ test byte [bp+016h], 0ffh ; f6 46 16 ff ; 0xf3d41 eltorito.c:223
+ jne short 03d4dh ; 75 06 ; 0xf3d45
+ mov es, di ; 8e c7 ; 0xf3d47 eltorito.c:225
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3d49
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf3d4d eltorito.c:228
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf3d51
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3d54
+ mov es, ax ; 8e c0 ; 0xf3d57
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf3d59
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf3d5d
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf3d61
+ pop di ; 5f ; 0xf3d64
+ pop si ; 5e ; 0xf3d65
+ pop bp ; 5d ; 0xf3d66
+ retn ; c3 ; 0xf3d67
+ mov bx, 00da0h ; bb a0 0d ; 0xf3d68 eltorito.c:232
+ mov cx, ds ; 8c d9 ; 0xf3d6b
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3d6d
+ call 018cch ; e8 59 db ; 0xf3d70
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf3d73
+ xor ah, ah ; 30 e4 ; 0xf3d76
+ push ax ; 50 ; 0xf3d78
+ mov ax, 002fch ; b8 fc 02 ; 0xf3d79
+ push ax ; 50 ; 0xf3d7c
+ mov ax, 00333h ; b8 33 03 ; 0xf3d7d
+ jmp near 03c65h ; e9 e2 fe ; 0xf3d80
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf3d83 eltorito.c:238
+ xor ah, ah ; 30 e4 ; 0xf3d86
+ or ah, 001h ; 80 cc 01 ; 0xf3d88
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf3d8b
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf3d8e eltorito.c:239
+ xor ah, ah ; 30 e4 ; 0xf3d91
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf3d93 eltorito.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3d96
+ mov es, dx ; 8e c2 ; 0xf3d99
+ mov byte [es:bx], al ; 26 88 07 ; 0xf3d9b
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf3d9e eltorito.c:240
+ jmp short 03d61h ; eb bd ; 0xf3da2 eltorito.c:241
+ ; disGetNextSymbol 0xf3da4 LB 0x61a4 -> off=0x0 cb=0000000000000035 uValue=00000000000f27a4 'device_is_cdrom'
+device_is_cdrom: ; 0xf3da4 LB 0x35
+ push bx ; 53 ; 0xf3da4 eltorito.c:256
+ push dx ; 52 ; 0xf3da5
+ push bp ; 55 ; 0xf3da6
+ mov bp, sp ; 89 e5 ; 0xf3da7
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3da9 eltorito.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf3dac
+ mov es, dx ; 8e c2 ; 0xf3daf
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf3db1
+ cmp AL, strict byte 010h ; 3c 10 ; 0xf3db4 eltorito.c:262
+ jc short 03dbch ; 72 04 ; 0xf3db6
+ xor ax, ax ; 31 c0 ; 0xf3db8 eltorito.c:263
+ jmp short 03dd5h ; eb 19 ; 0xf3dba
+ xor ah, ah ; 30 e4 ; 0xf3dbc eltorito.c:268
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf3dbe
+ imul dx ; f7 ea ; 0xf3dc1
+ mov es, bx ; 8e c3 ; 0xf3dc3
+ mov bx, ax ; 89 c3 ; 0xf3dc5
+ add bx, 00122h ; 81 c3 22 01 ; 0xf3dc7
+ cmp byte [es:bx+023h], 005h ; 26 80 7f 23 05 ; 0xf3dcb
+ jne short 03db8h ; 75 e6 ; 0xf3dd0
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf3dd2 eltorito.c:269
+ pop bp ; 5d ; 0xf3dd5 eltorito.c:272
+ pop dx ; 5a ; 0xf3dd6
+ pop bx ; 5b ; 0xf3dd7
+ retn ; c3 ; 0xf3dd8
+ ; disGetNextSymbol 0xf3dd9 LB 0x616f -> off=0x0 cb=00000000000003ca uValue=00000000000f27d9 'cdrom_boot'
+cdrom_boot: ; 0xf3dd9 LB 0x3ca
+ push bp ; 55 ; 0xf3dd9 eltorito.c:282
+ mov bp, sp ; 89 e5 ; 0xf3dda
+ push bx ; 53 ; 0xf3ddc
+ push cx ; 51 ; 0xf3ddd
+ push dx ; 52 ; 0xf3dde
+ push si ; 56 ; 0xf3ddf
+ push di ; 57 ; 0xf3de0
+ sub sp, 0081ch ; 81 ec 1c 08 ; 0xf3de1
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf3de5 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf3de8
+ mov es, ax ; 8e c0 ; 0xf3deb
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf3ded
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf3df0 eltorito.c:49
+ mov si, 00366h ; be 66 03 ; 0xf3df3 eltorito.c:295
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf3df6
+ mov word [bp-018h], 00122h ; c7 46 e8 22 01 ; 0xf3df9 eltorito.c:296
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf3dfe
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf3e01 eltorito.c:299
+ jmp short 03e10h ; eb 09 ; 0xf3e05
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf3e07 eltorito.c:302
+ cmp byte [bp-00ch], 010h ; 80 7e f4 10 ; 0xf3e0a
+ jnc short 03e1ch ; 73 0c ; 0xf3e0e
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3e10
+ xor ah, ah ; 30 e4 ; 0xf3e13
+ call 03da4h ; e8 8c ff ; 0xf3e15
+ test ax, ax ; 85 c0 ; 0xf3e18
+ je short 03e07h ; 74 eb ; 0xf3e1a
+ cmp byte [bp-00ch], 010h ; 80 7e f4 10 ; 0xf3e1c eltorito.c:305
+ jc short 03e28h ; 72 06 ; 0xf3e20
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf3e22 eltorito.c:306
+ jmp near 04199h ; e9 71 03 ; 0xf3e25
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf3e28 eltorito.c:309
+ xor bx, bx ; 31 db ; 0xf3e2b
+ mov dx, ss ; 8c d2 ; 0xf3e2d
+ lea ax, [bp-026h] ; 8d 46 da ; 0xf3e2f
+ call 09c30h ; e8 fb 5d ; 0xf3e32
+ mov word [bp-026h], strict word 00028h ; c7 46 da 28 00 ; 0xf3e35 eltorito.c:310
+ mov ax, strict word 00011h ; b8 11 00 ; 0xf3e3a eltorito.c:311
+ xor dx, dx ; 31 d2 ; 0xf3e3d
+ xchg ah, al ; 86 c4 ; 0xf3e3f
+ xchg dh, dl ; 86 d6 ; 0xf3e41
+ xchg dx, ax ; 92 ; 0xf3e43
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf3e44
+ mov word [bp-022h], dx ; 89 56 de ; 0xf3e47
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf3e4a eltorito.c:312
+ xchg ah, al ; 86 c4 ; 0xf3e4d
+ mov word [bp-01fh], ax ; 89 46 e1 ; 0xf3e4f
+ les bx, [bp-018h] ; c4 5e e8 ; 0xf3e52 eltorito.c:314
+ mov word [es:bx+00eh], strict word 00001h ; 26 c7 47 0e 01 00 ; 0xf3e55
+ mov word [es:bx+010h], 00800h ; 26 c7 47 10 00 08 ; 0xf3e5b eltorito.c:315
+ mov byte [bp-00eh], 000h ; c6 46 f2 00 ; 0xf3e61 eltorito.c:317
+ jmp short 03e70h ; eb 09 ; 0xf3e65
+ inc byte [bp-00eh] ; fe 46 f2 ; 0xf3e67 eltorito.c:322
+ cmp byte [bp-00eh], 004h ; 80 7e f2 04 ; 0xf3e6a
+ jnbe short 03eb2h ; 77 42 ; 0xf3e6e
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3e70
+ xor ah, ah ; 30 e4 ; 0xf3e73
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf3e75
+ imul dx ; f7 ea ; 0xf3e78
+ les bx, [bp-018h] ; c4 5e e8 ; 0xf3e7a
+ add bx, ax ; 01 c3 ; 0xf3e7d
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf3e7f
+ xor ah, ah ; 30 e4 ; 0xf3e83
+ mov di, ax ; 89 c7 ; 0xf3e85
+ sal di, 1 ; d1 e7 ; 0xf3e87
+ lea dx, [bp-00826h] ; 8d 96 da f7 ; 0xf3e89
+ push SS ; 16 ; 0xf3e8d
+ push dx ; 52 ; 0xf3e8e
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf3e8f
+ push ax ; 50 ; 0xf3e92
+ xor ax, ax ; 31 c0 ; 0xf3e93
+ push ax ; 50 ; 0xf3e95
+ mov ax, 00800h ; b8 00 08 ; 0xf3e96
+ push ax ; 50 ; 0xf3e99
+ xor ax, ax ; 31 c0 ; 0xf3e9a
+ push ax ; 50 ; 0xf3e9c
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3e9d
+ xor ah, ah ; 30 e4 ; 0xf3ea0
+ mov cx, ss ; 8c d1 ; 0xf3ea2
+ lea bx, [bp-026h] ; 8d 5e da ; 0xf3ea4
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3ea7
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf3eaa
+ test ax, ax ; 85 c0 ; 0xf3eae
+ jne short 03e67h ; 75 b5 ; 0xf3eb0
+ test ax, ax ; 85 c0 ; 0xf3eb2 eltorito.c:323
+ je short 03ebch ; 74 06 ; 0xf3eb4
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf3eb6 eltorito.c:324
+ jmp near 04199h ; e9 dd 02 ; 0xf3eb9
+ cmp byte [bp-00826h], 000h ; 80 be da f7 00 ; 0xf3ebc eltorito.c:327
+ je short 03ec9h ; 74 06 ; 0xf3ec1
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf3ec3 eltorito.c:328
+ jmp near 04199h ; e9 d0 02 ; 0xf3ec6
+ xor di, di ; 31 ff ; 0xf3ec9 eltorito.c:330
+ jmp short 03ed3h ; eb 06 ; 0xf3ecb
+ inc di ; 47 ; 0xf3ecd eltorito.c:332
+ cmp di, strict byte 00005h ; 83 ff 05 ; 0xf3ece
+ jnc short 03ee3h ; 73 10 ; 0xf3ed1
+ mov al, byte [bp+di-00825h] ; 8a 83 db f7 ; 0xf3ed3
+ cmp al, byte [di+00da8h] ; 3a 85 a8 0d ; 0xf3ed7
+ je short 03ecdh ; 74 f0 ; 0xf3edb
+ mov ax, strict word 00005h ; b8 05 00 ; 0xf3edd
+ jmp near 04199h ; e9 b6 02 ; 0xf3ee0
+ xor di, di ; 31 ff ; 0xf3ee3 eltorito.c:334
+ jmp short 03eedh ; eb 06 ; 0xf3ee5
+ inc di ; 47 ; 0xf3ee7 eltorito.c:336
+ cmp di, strict byte 00017h ; 83 ff 17 ; 0xf3ee8
+ jnc short 03efdh ; 73 10 ; 0xf3eeb
+ mov al, byte [bp+di-0081fh] ; 8a 83 e1 f7 ; 0xf3eed
+ cmp al, byte [di+00daeh] ; 3a 85 ae 0d ; 0xf3ef1
+ je short 03ee7h ; 74 f0 ; 0xf3ef5
+ mov ax, strict word 00006h ; b8 06 00 ; 0xf3ef7
+ jmp near 04199h ; e9 9c 02 ; 0xf3efa
+ mov ax, word [bp-007dfh] ; 8b 86 21 f8 ; 0xf3efd eltorito.c:339
+ mov dx, word [bp-007ddh] ; 8b 96 23 f8 ; 0xf3f01
+ mov word [bp-026h], strict word 00028h ; c7 46 da 28 00 ; 0xf3f05 eltorito.c:343
+ xchg ah, al ; 86 c4 ; 0xf3f0a eltorito.c:344
+ xchg dh, dl ; 86 d6 ; 0xf3f0c
+ xchg dx, ax ; 92 ; 0xf3f0e
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf3f0f
+ mov word [bp-022h], dx ; 89 56 de ; 0xf3f12
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf3f15 eltorito.c:345
+ xchg ah, al ; 86 c4 ; 0xf3f18
+ mov word [bp-01fh], ax ; 89 46 e1 ; 0xf3f1a
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3f1d eltorito.c:352
+ xor ah, ah ; 30 e4 ; 0xf3f20
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf3f22
+ imul dx ; f7 ea ; 0xf3f25
+ les bx, [bp-018h] ; c4 5e e8 ; 0xf3f27
+ add bx, ax ; 01 c3 ; 0xf3f2a
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf3f2c
+ xor ah, ah ; 30 e4 ; 0xf3f30
+ mov di, ax ; 89 c7 ; 0xf3f32
+ sal di, 1 ; d1 e7 ; 0xf3f34
+ lea dx, [bp-00826h] ; 8d 96 da f7 ; 0xf3f36
+ push SS ; 16 ; 0xf3f3a
+ push dx ; 52 ; 0xf3f3b
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf3f3c
+ push ax ; 50 ; 0xf3f3f
+ xor ax, ax ; 31 c0 ; 0xf3f40
+ push ax ; 50 ; 0xf3f42
+ mov ax, 00800h ; b8 00 08 ; 0xf3f43
+ push ax ; 50 ; 0xf3f46
+ xor ax, ax ; 31 c0 ; 0xf3f47
+ push ax ; 50 ; 0xf3f49
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf3f4a
+ xor ah, ah ; 30 e4 ; 0xf3f4d
+ mov cx, ss ; 8c d1 ; 0xf3f4f
+ lea bx, [bp-026h] ; 8d 5e da ; 0xf3f51
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf3f54
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf3f57
+ test ax, ax ; 85 c0 ; 0xf3f5b eltorito.c:353
+ je short 03f65h ; 74 06 ; 0xf3f5d
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf3f5f eltorito.c:354
+ jmp near 04199h ; e9 34 02 ; 0xf3f62
+ cmp byte [bp-00826h], 001h ; 80 be da f7 01 ; 0xf3f65 eltorito.c:359
+ je short 03f72h ; 74 06 ; 0xf3f6a
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf3f6c eltorito.c:360
+ jmp near 04199h ; e9 27 02 ; 0xf3f6f
+ cmp byte [bp-00825h], 000h ; 80 be db f7 00 ; 0xf3f72 eltorito.c:361
+ je short 03f7fh ; 74 06 ; 0xf3f77
+ mov ax, strict word 00009h ; b8 09 00 ; 0xf3f79 eltorito.c:362
+ jmp near 04199h ; e9 1a 02 ; 0xf3f7c
+ cmp byte [bp-00808h], 055h ; 80 be f8 f7 55 ; 0xf3f7f eltorito.c:363
+ je short 03f8ch ; 74 06 ; 0xf3f84
+ mov ax, strict word 0000ah ; b8 0a 00 ; 0xf3f86 eltorito.c:364
+ jmp near 04199h ; e9 0d 02 ; 0xf3f89
+ cmp byte [bp-00807h], 0aah ; 80 be f9 f7 aa ; 0xf3f8c eltorito.c:365
+ jne short 03f86h ; 75 f3 ; 0xf3f91
+ cmp byte [bp-00806h], 088h ; 80 be fa f7 88 ; 0xf3f93 eltorito.c:366
+ je short 03fa0h ; 74 06 ; 0xf3f98
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf3f9a eltorito.c:370
+ jmp near 04199h ; e9 f9 01 ; 0xf3f9d
+ mov al, byte [bp-00805h] ; 8a 86 fb f7 ; 0xf3fa0 eltorito.c:372
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf3fa4
+ mov byte [es:si+001h], al ; 26 88 44 01 ; 0xf3fa7
+ cmp byte [bp-00805h], 000h ; 80 be fb f7 00 ; 0xf3fab eltorito.c:373
+ jne short 03fb9h ; 75 07 ; 0xf3fb0
+ mov byte [es:si+002h], 0e0h ; 26 c6 44 02 e0 ; 0xf3fb2 eltorito.c:376
+ jmp short 03fcch ; eb 13 ; 0xf3fb7 eltorito.c:378
+ cmp byte [bp-00805h], 004h ; 80 be fb f7 04 ; 0xf3fb9
+ jnc short 03fc7h ; 73 07 ; 0xf3fbe
+ mov byte [es:si+002h], 000h ; 26 c6 44 02 00 ; 0xf3fc0 eltorito.c:379
+ jmp short 03fcch ; eb 05 ; 0xf3fc5 eltorito.c:380
+ mov byte [es:si+002h], 080h ; 26 c6 44 02 80 ; 0xf3fc7 eltorito.c:381
+ mov bl, byte [bp-00ch] ; 8a 5e f4 ; 0xf3fcc eltorito.c:383
+ xor bh, bh ; 30 ff ; 0xf3fcf
+ mov ax, bx ; 89 d8 ; 0xf3fd1
+ cwd ; 99 ; 0xf3fd3
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf3fd4
+ sar ax, 1 ; d1 f8 ; 0xf3fd6
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf3fd8
+ mov byte [es:si+003h], al ; 26 88 44 03 ; 0xf3fdb
+ mov ax, bx ; 89 d8 ; 0xf3fdf eltorito.c:384
+ cwd ; 99 ; 0xf3fe1
+ mov bx, strict word 00002h ; bb 02 00 ; 0xf3fe2
+ idiv bx ; f7 fb ; 0xf3fe5
+ mov word [es:si+004h], dx ; 26 89 54 04 ; 0xf3fe7
+ mov ax, word [bp-00804h] ; 8b 86 fc f7 ; 0xf3feb eltorito.c:386
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf3fef
+ test ax, ax ; 85 c0 ; 0xf3ff2 eltorito.c:387
+ jne short 03ffbh ; 75 05 ; 0xf3ff4
+ mov word [bp-010h], 007c0h ; c7 46 f0 c0 07 ; 0xf3ff6 eltorito.c:388
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf3ffb eltorito.c:390
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf3ffe
+ mov word [es:si+00ch], ax ; 26 89 44 0c ; 0xf4001
+ mov word [es:si+006h], strict word 00000h ; 26 c7 44 06 00 00 ; 0xf4005 eltorito.c:391
+ mov bx, word [bp-00800h] ; 8b 9e 00 f8 ; 0xf400b eltorito.c:393
+ mov word [es:si+00eh], bx ; 26 89 5c 0e ; 0xf400f eltorito.c:394
+ test bx, bx ; 85 db ; 0xf4013 eltorito.c:399
+ je short 0401dh ; 74 06 ; 0xf4015
+ cmp bx, 00400h ; 81 fb 00 04 ; 0xf4017
+ jbe short 04023h ; 76 06 ; 0xf401b
+ mov ax, strict word 0000ch ; b8 0c 00 ; 0xf401d eltorito.c:400
+ jmp near 04199h ; e9 76 01 ; 0xf4020
+ mov ax, word [bp-007feh] ; 8b 86 02 f8 ; 0xf4023 eltorito.c:402
+ mov dx, word [bp-007fch] ; 8b 96 04 f8 ; 0xf4027
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf402b eltorito.c:403
+ mov word [es:si+00ah], dx ; 26 89 54 0a ; 0xf402f
+ mov word [bp-026h], strict word 00028h ; c7 46 da 28 00 ; 0xf4033 eltorito.c:409
+ xchg ah, al ; 86 c4 ; 0xf4038 eltorito.c:410
+ xchg dh, dl ; 86 d6 ; 0xf403a
+ xchg dx, ax ; 92 ; 0xf403c
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf403d
+ mov word [bp-022h], dx ; 89 56 de ; 0xf4040
+ lea dx, [bx-001h] ; 8d 57 ff ; 0xf4043 eltorito.c:411
+ shr dx, 1 ; d1 ea ; 0xf4046
+ shr dx, 1 ; d1 ea ; 0xf4048
+ inc dx ; 42 ; 0xf404a
+ mov ax, dx ; 89 d0 ; 0xf404b
+ xchg ah, al ; 86 c4 ; 0xf404d
+ mov word [bp-01fh], ax ; 89 46 e1 ; 0xf404f
+ les di, [bp-018h] ; c4 7e e8 ; 0xf4052 eltorito.c:413
+ mov word [es:di+00eh], dx ; 26 89 55 0e ; 0xf4055
+ mov word [es:di+010h], 00200h ; 26 c7 45 10 00 02 ; 0xf4059 eltorito.c:414
+ mov CL, strict byte 009h ; b1 09 ; 0xf405f eltorito.c:416
+ mov ax, bx ; 89 d8 ; 0xf4061
+ sal ax, CL ; d3 e0 ; 0xf4063
+ mov dx, 00800h ; ba 00 08 ; 0xf4065
+ sub dx, ax ; 29 c2 ; 0xf4068
+ mov ax, dx ; 89 d0 ; 0xf406a
+ and ah, 007h ; 80 e4 07 ; 0xf406c
+ mov word [es:di+020h], ax ; 26 89 45 20 ; 0xf406f
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf4073 eltorito.c:418
+ xor ah, ah ; 30 e4 ; 0xf4076
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf4078
+ imul dx ; f7 ea ; 0xf407b
+ add di, ax ; 01 c7 ; 0xf407d
+ mov al, byte [es:di+022h] ; 26 8a 45 22 ; 0xf407f
+ xor ah, ah ; 30 e4 ; 0xf4083
+ sal ax, 1 ; d1 e0 ; 0xf4085
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf4087
+ push word [bp-010h] ; ff 76 f0 ; 0xf408a
+ xor ax, ax ; 31 c0 ; 0xf408d
+ push ax ; 50 ; 0xf408f
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf4090
+ push ax ; 50 ; 0xf4093
+ mov ax, bx ; 89 d8 ; 0xf4094
+ xor di, di ; 31 ff ; 0xf4096
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf4098
+ sal ax, 1 ; d1 e0 ; 0xf409b
+ rcl di, 1 ; d1 d7 ; 0xf409d
+ loop 0409bh ; e2 fa ; 0xf409f
+ push di ; 57 ; 0xf40a1
+ push ax ; 50 ; 0xf40a2
+ xor ax, ax ; 31 c0 ; 0xf40a3
+ push ax ; 50 ; 0xf40a5
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf40a6
+ xor ah, ah ; 30 e4 ; 0xf40a9
+ mov cx, ss ; 8c d1 ; 0xf40ab
+ lea bx, [bp-026h] ; 8d 5e da ; 0xf40ad
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf40b0
+ mov di, word [bp-01ah] ; 8b 7e e6 ; 0xf40b3
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf40b6
+ les bx, [bp-018h] ; c4 5e e8 ; 0xf40ba eltorito.c:420
+ mov word [es:bx+020h], strict word 00000h ; 26 c7 47 20 00 00 ; 0xf40bd
+ test ax, ax ; 85 c0 ; 0xf40c3 eltorito.c:422
+ je short 040cdh ; 74 06 ; 0xf40c5
+ mov ax, strict word 0000dh ; b8 0d 00 ; 0xf40c7 eltorito.c:423
+ jmp near 04199h ; e9 cc 00 ; 0xf40ca
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf40cd eltorito.c:428
+ mov al, byte [es:si+001h] ; 26 8a 44 01 ; 0xf40d0
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf40d4
+ jc short 040e4h ; 72 0c ; 0xf40d6
+ jbe short 040ffh ; 76 25 ; 0xf40d8
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf40da
+ je short 0410fh ; 74 31 ; 0xf40dc
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf40de
+ je short 04107h ; 74 25 ; 0xf40e0
+ jmp short 04154h ; eb 70 ; 0xf40e2
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf40e4
+ jne short 04154h ; 75 6c ; 0xf40e6
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf40e8 eltorito.c:430
+ mov word [es:si+014h], strict word 0000fh ; 26 c7 44 14 0f 00 ; 0xf40eb
+ mov word [es:si+012h], strict word 00050h ; 26 c7 44 12 50 00 ; 0xf40f1 eltorito.c:431
+ mov word [es:si+010h], strict word 00002h ; 26 c7 44 10 02 00 ; 0xf40f7 eltorito.c:432
+ jmp short 04154h ; eb 55 ; 0xf40fd eltorito.c:433
+ mov word [es:si+014h], strict word 00012h ; 26 c7 44 14 12 00 ; 0xf40ff eltorito.c:435
+ jmp short 040f1h ; eb ea ; 0xf4105
+ mov word [es:si+014h], strict word 00024h ; 26 c7 44 14 24 00 ; 0xf4107 eltorito.c:440
+ jmp short 040f1h ; eb e2 ; 0xf410d
+ mov bx, 001c4h ; bb c4 01 ; 0xf410f eltorito.c:38
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf4112
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4115
+ and AL, strict byte 03fh ; 24 3f ; 0xf4118 eltorito.c:39
+ xor ah, ah ; 30 e4 ; 0xf411a
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf411c
+ mov word [es:si+014h], ax ; 26 89 44 14 ; 0xf411f
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf4123 eltorito.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4126
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf4129 eltorito.c:39
+ mov dx, ax ; 89 c2 ; 0xf412b
+ sal dx, 1 ; d1 e2 ; 0xf412d
+ sal dx, 1 ; d1 e2 ; 0xf412f
+ mov bx, 001c5h ; bb c5 01 ; 0xf4131 eltorito.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4134
+ add ax, dx ; 01 d0 ; 0xf4137 eltorito.c:39
+ inc ax ; 40 ; 0xf4139
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf413a
+ mov word [es:si+012h], ax ; 26 89 44 12 ; 0xf413d
+ mov bx, 001c3h ; bb c3 01 ; 0xf4141 eltorito.c:38
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf4144
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4147
+ xor ah, ah ; 30 e4 ; 0xf414a eltorito.c:39
+ inc ax ; 40 ; 0xf414c
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf414d
+ mov word [es:si+010h], ax ; 26 89 44 10 ; 0xf4150
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf4154 eltorito.c:453
+ cmp byte [es:si+001h], 000h ; 26 80 7c 01 00 ; 0xf4157
+ je short 04182h ; 74 24 ; 0xf415c
+ cmp byte [es:si+002h], 000h ; 26 80 7c 02 00 ; 0xf415e eltorito.c:455
+ jne short 04174h ; 75 0f ; 0xf4163
+ mov bx, strict word 00010h ; bb 10 00 ; 0xf4165 eltorito.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4168
+ mov es, ax ; 8e c0 ; 0xf416b
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf416d
+ or AL, strict byte 041h ; 0c 41 ; 0xf4170 eltorito.c:39
+ jmp short 0417fh ; eb 0b ; 0xf4172 eltorito.c:457
+ mov bx, 00304h ; bb 04 03 ; 0xf4174 eltorito.c:38
+ mov es, [bp-012h] ; 8e 46 ee ; 0xf4177
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf417a
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf417d eltorito.c:39
+ mov byte [es:bx], al ; 26 88 07 ; 0xf417f eltorito.c:43
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf4182 eltorito.c:462
+ cmp byte [es:si+001h], 000h ; 26 80 7c 01 00 ; 0xf4185
+ je short 04190h ; 74 04 ; 0xf418a
+ mov byte [es:si], 001h ; 26 c6 04 01 ; 0xf418c eltorito.c:463
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf4190 eltorito.c:466
+ mov ah, byte [es:si+002h] ; 26 8a 64 02 ; 0xf4193
+ xor al, al ; 30 c0 ; 0xf4197
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf4199 eltorito.c:467
+ pop di ; 5f ; 0xf419c
+ pop si ; 5e ; 0xf419d
+ pop dx ; 5a ; 0xf419e
+ pop cx ; 59 ; 0xf419f
+ pop bx ; 5b ; 0xf41a0
+ pop bp ; 5d ; 0xf41a1
+ retn ; c3 ; 0xf41a2
+ ; disGetNextSymbol 0xf41a3 LB 0x5da5 -> off=0x59 cb=00000000000005ff uValue=00000000000f2bfc 'int13_cdemu'
+ db 050h, 04eh, 049h, 048h, 047h, 046h, 045h, 044h, 043h, 042h, 041h, 018h, 016h, 015h, 014h, 011h
+ db 010h, 00dh, 00ch, 00bh, 00ah, 009h, 008h, 005h, 004h, 003h, 002h, 001h, 000h, 0dch, 047h, 0a8h
+ db 042h, 0ddh, 042h, 0fbh, 042h, 0d2h, 042h, 0fbh, 042h, 0d2h, 042h, 014h, 045h, 0f9h, 044h, 0dch
+ db 047h, 0dch, 047h, 0f9h, 044h, 0f9h, 044h, 0f9h, 044h, 0f9h, 044h, 0f9h, 044h, 0c2h, 045h, 0f9h
+ db 044h, 0dch, 047h, 0cbh, 045h, 0deh, 045h, 0dch, 047h, 0deh, 045h, 0dch, 047h, 0dch, 047h, 0deh
+ db 045h, 0a4h, 047h, 0dch, 047h, 0dch, 047h, 0dch, 047h
+int13_cdemu: ; 0xf41fc LB 0x5ff
+ push bp ; 55 ; 0xf41fc eltorito.c:477
+ mov bp, sp ; 89 e5 ; 0xf41fd
+ push si ; 56 ; 0xf41ff
+ push di ; 57 ; 0xf4200
+ sub sp, strict byte 0003ah ; 83 ec 3a ; 0xf4201
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf4204 eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4207
+ mov es, ax ; 8e c0 ; 0xf420a
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf420c
+ mov dx, 00366h ; ba 66 03 ; 0xf420f eltorito.c:493
+ mov cx, ax ; 89 c1 ; 0xf4212
+ mov bx, dx ; 89 d3 ; 0xf4214
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf4216
+ mov si, 00122h ; be 22 01 ; 0xf4219 eltorito.c:494
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf421c
+ mov es, ax ; 8e c0 ; 0xf421f eltorito.c:501
+ mov di, dx ; 89 d7 ; 0xf4221
+ mov al, byte [es:di+003h] ; 26 8a 45 03 ; 0xf4223
+ sal al, 1 ; d0 e0 ; 0xf4227
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf4229
+ mov al, byte [es:di+004h] ; 26 8a 45 04 ; 0xf422c eltorito.c:502
+ add byte [bp-006h], al ; 00 46 fa ; 0xf4230
+ mov di, strict word 00074h ; bf 74 00 ; 0xf4233 eltorito.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4236
+ mov es, ax ; 8e c0 ; 0xf4239
+ mov byte [es:di], 000h ; 26 c6 05 00 ; 0xf423b
+ mov es, cx ; 8e c1 ; 0xf423f eltorito.c:507
+ mov di, dx ; 89 d7 ; 0xf4241
+ cmp byte [es:di], 000h ; 26 80 3d 00 ; 0xf4243
+ je short 04258h ; 74 0f ; 0xf4247
+ mov al, byte [es:di+002h] ; 26 8a 45 02 ; 0xf4249
+ xor ah, ah ; 30 e4 ; 0xf424d
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf424f
+ xor dh, dh ; 30 f6 ; 0xf4252
+ cmp ax, dx ; 39 d0 ; 0xf4254
+ je short 04282h ; 74 2a ; 0xf4256
+ mov bx, 00da0h ; bb a0 0d ; 0xf4258 eltorito.c:508
+ mov cx, ds ; 8c d9 ; 0xf425b
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf425d
+ call 018cch ; e8 69 d6 ; 0xf4260
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf4263
+ xor ah, ah ; 30 e4 ; 0xf4266
+ push ax ; 50 ; 0xf4268
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf4269
+ push ax ; 50 ; 0xf426c
+ mov ax, 0034ch ; b8 4c 03 ; 0xf426d
+ push ax ; 50 ; 0xf4270
+ mov ax, 00358h ; b8 58 03 ; 0xf4271
+ push ax ; 50 ; 0xf4274
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4275
+ push ax ; 50 ; 0xf4278
+ call 0190fh ; e8 93 d6 ; 0xf4279
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf427c
+ jmp near 047bah ; e9 38 05 ; 0xf427f eltorito.c:509
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf4282 eltorito.c:512
+ xor ah, ah ; 30 e4 ; 0xf4285
+ mov dx, ax ; 89 c2 ; 0xf4287
+ cmp ax, strict word 00050h ; 3d 50 00 ; 0xf4289
+ jnbe short 042f8h ; 77 6a ; 0xf428c
+ push CS ; 0e ; 0xf428e
+ pop ES ; 07 ; 0xf428f
+ mov cx, strict word 0001eh ; b9 1e 00 ; 0xf4290
+ mov di, 041a3h ; bf a3 41 ; 0xf4293
+ repne scasb ; f2 ae ; 0xf4296
+ sal cx, 1 ; d1 e1 ; 0xf4298
+ mov di, cx ; 89 cf ; 0xf429a
+ mov dx, word [cs:di+041c0h] ; 2e 8b 95 c0 41 ; 0xf429c
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf42a1
+ xor ah, ah ; 30 e4 ; 0xf42a4
+ jmp dx ; ff e2 ; 0xf42a6
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf42a8 eltorito.c:515
+ xor ah, ah ; 30 e4 ; 0xf42ab
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf42ad
+ imul dx ; f7 ea ; 0xf42b0
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf42b2
+ add si, ax ; 01 c6 ; 0xf42b5
+ mov bl, byte [es:si+022h] ; 26 8a 5c 22 ; 0xf42b7
+ xor bh, bh ; 30 ff ; 0xf42bb
+ sal bx, 1 ; d1 e3 ; 0xf42bd
+ cmp word [word bx+0006ah], strict byte 00000h ; 83 bf 6a 00 00 ; 0xf42bf
+ je short 042cfh ; 74 09 ; 0xf42c4
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf42c6 eltorito.c:517
+ xor ah, ah ; 30 e4 ; 0xf42c9
+ call word [word bx+00076h] ; ff 97 76 00 ; 0xf42cb
+ jmp near 044f9h ; e9 27 02 ; 0xf42cf eltorito.c:519
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf42d2 eltorito.c:535
+ xor ah, ah ; 30 e4 ; 0xf42d5
+ or ah, 003h ; 80 cc 03 ; 0xf42d7
+ jmp near 047c2h ; e9 e5 04 ; 0xf42da eltorito.c:536
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf42dd eltorito.c:38
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf42e0
+ mov es, dx ; 8e c2 ; 0xf42e3
+ mov cl, byte [es:bx] ; 26 8a 0f ; 0xf42e5
+ mov ah, cl ; 88 cc ; 0xf42e8 eltorito.c:541
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf42ea
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf42ed eltorito.c:43
+ test cl, cl ; 84 c9 ; 0xf42f1 eltorito.c:545
+ je short 0435ch ; 74 67 ; 0xf42f3
+ jmp near 047d5h ; e9 dd 04 ; 0xf42f5 eltorito.c:546
+ jmp near 047dch ; e9 e1 04 ; 0xf42f8
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf42fb eltorito.c:553
+ mov ax, word [es:bx+014h] ; 26 8b 47 14 ; 0xf42fe
+ mov word [bp-028h], ax ; 89 46 d8 ; 0xf4302
+ mov dx, word [es:bx+012h] ; 26 8b 57 12 ; 0xf4305 eltorito.c:554
+ mov ax, word [es:bx+010h] ; 26 8b 47 10 ; 0xf4309 eltorito.c:555
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf430d
+ mov ax, word [es:bx+008h] ; 26 8b 47 08 ; 0xf4310 eltorito.c:556
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf4314
+ mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xf4317
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf431b
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf431e eltorito.c:558
+ and ax, strict word 0003fh ; 25 3f 00 ; 0xf4321
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf4324
+ mov bx, word [bp+014h] ; 8b 5e 14 ; 0xf4327 eltorito.c:559
+ and bx, 000c0h ; 81 e3 c0 00 ; 0xf432a
+ sal bx, 1 ; d1 e3 ; 0xf432e
+ sal bx, 1 ; d1 e3 ; 0xf4330
+ mov al, byte [bp+015h] ; 8a 46 15 ; 0xf4332
+ or ax, bx ; 09 d8 ; 0xf4335
+ mov bl, byte [bp+013h] ; 8a 5e 13 ; 0xf4337 eltorito.c:560
+ xor bh, bh ; 30 ff ; 0xf433a
+ mov word [bp-014h], bx ; 89 5e ec ; 0xf433c
+ mov di, word [bp+016h] ; 8b 7e 16 ; 0xf433f eltorito.c:561
+ and di, 000ffh ; 81 e7 ff 00 ; 0xf4342
+ je short 04369h ; 74 21 ; 0xf4346 eltorito.c:569
+ mov cx, word [bp-01ch] ; 8b 4e e4 ; 0xf4348 eltorito.c:573
+ cmp cx, word [bp-028h] ; 3b 4e d8 ; 0xf434b
+ jnbe short 04359h ; 77 09 ; 0xf434e
+ cmp ax, dx ; 39 d0 ; 0xf4350
+ jnc short 04359h ; 73 05 ; 0xf4352
+ cmp bx, word [bp-00ch] ; 3b 5e f4 ; 0xf4354
+ jc short 0435fh ; 72 06 ; 0xf4357
+ jmp near 047bah ; e9 5e 04 ; 0xf4359 eltorito.c:576
+ jmp near 044fdh ; e9 9e 01 ; 0xf435c
+ mov dl, byte [bp+017h] ; 8a 56 17 ; 0xf435f eltorito.c:580
+ xor dh, dh ; 30 f6 ; 0xf4362
+ cmp dx, strict byte 00004h ; 83 fa 04 ; 0xf4364
+ jne short 0436ch ; 75 03 ; 0xf4367
+ jmp near 044f9h ; e9 8d 01 ; 0xf4369 eltorito.c:581
+ mov CL, strict byte 004h ; b1 04 ; 0xf436c eltorito.c:583
+ mov dx, word [bp+010h] ; 8b 56 10 ; 0xf436e
+ shr dx, CL ; d3 ea ; 0xf4371
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf4373
+ add bx, dx ; 01 d3 ; 0xf4376
+ mov word [bp-012h], bx ; 89 5e ee ; 0xf4378
+ mov dx, word [bp+010h] ; 8b 56 10 ; 0xf437b eltorito.c:584
+ and dx, strict byte 0000fh ; 83 e2 0f ; 0xf437e
+ mov word [bp-010h], dx ; 89 56 f0 ; 0xf4381
+ xor dl, dl ; 30 d2 ; 0xf4384 eltorito.c:587
+ mov bx, word [bp-00ch] ; 8b 5e f4 ; 0xf4386
+ xor cx, cx ; 31 c9 ; 0xf4389
+ call 09bc0h ; e8 32 58 ; 0xf438b
+ xor bx, bx ; 31 db ; 0xf438e
+ add ax, word [bp-014h] ; 03 46 ec ; 0xf4390
+ adc dx, bx ; 11 da ; 0xf4393
+ mov bx, word [bp-028h] ; 8b 5e d8 ; 0xf4395
+ xor cx, cx ; 31 c9 ; 0xf4398
+ call 09bc0h ; e8 23 58 ; 0xf439a
+ mov bx, dx ; 89 d3 ; 0xf439d
+ mov dx, word [bp-01ch] ; 8b 56 e4 ; 0xf439f
+ dec dx ; 4a ; 0xf43a2
+ mov word [bp-026h], strict word 00000h ; c7 46 da 00 00 ; 0xf43a3
+ add dx, ax ; 01 c2 ; 0xf43a8
+ adc bx, word [bp-026h] ; 13 5e da ; 0xf43aa
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf43ad eltorito.c:590
+ xor al, al ; 30 c0 ; 0xf43b0
+ or ax, di ; 09 f8 ; 0xf43b2
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf43b4
+ mov word [bp-02eh], dx ; 89 56 d2 ; 0xf43b7 eltorito.c:593
+ mov word [bp-02ch], bx ; 89 5e d4 ; 0xf43ba
+ shr word [bp-02ch], 1 ; d1 6e d4 ; 0xf43bd
+ rcr word [bp-02eh], 1 ; d1 5e d2 ; 0xf43c0
+ shr word [bp-02ch], 1 ; d1 6e d4 ; 0xf43c3
+ rcr word [bp-02eh], 1 ; d1 5e d2 ; 0xf43c6
+ mov ax, word [bp-02ch] ; 8b 46 d4 ; 0xf43c9
+ mov word [bp-02ah], ax ; 89 46 d6 ; 0xf43cc
+ mov ax, dx ; 89 d0 ; 0xf43cf eltorito.c:594
+ xor ah, dh ; 30 f4 ; 0xf43d1
+ and AL, strict byte 003h ; 24 03 ; 0xf43d3
+ mov word [bp-022h], ax ; 89 46 de ; 0xf43d5
+ xor cx, cx ; 31 c9 ; 0xf43d8 eltorito.c:597
+ mov ax, dx ; 89 d0 ; 0xf43da
+ add ax, di ; 01 f8 ; 0xf43dc
+ mov dx, bx ; 89 da ; 0xf43de
+ adc dx, cx ; 11 ca ; 0xf43e0
+ add ax, strict word 0ffffh ; 05 ff ff ; 0xf43e2
+ adc dx, strict byte 0ffffh ; 83 d2 ff ; 0xf43e5
+ mov word [bp-032h], ax ; 89 46 ce ; 0xf43e8
+ mov word [bp-030h], dx ; 89 56 d0 ; 0xf43eb
+ shr word [bp-030h], 1 ; d1 6e d0 ; 0xf43ee
+ rcr word [bp-032h], 1 ; d1 5e ce ; 0xf43f1
+ shr word [bp-030h], 1 ; d1 6e d0 ; 0xf43f4
+ rcr word [bp-032h], 1 ; d1 5e ce ; 0xf43f7
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf43fa eltorito.c:599
+ xor bx, bx ; 31 db ; 0xf43fd
+ mov dx, ss ; 8c d2 ; 0xf43ff
+ lea ax, [bp-03eh] ; 8d 46 c2 ; 0xf4401
+ call 09c30h ; e8 29 58 ; 0xf4404
+ mov word [bp-03eh], strict word 00028h ; c7 46 c2 28 00 ; 0xf4407 eltorito.c:600
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf440c eltorito.c:601
+ add ax, word [bp-02eh] ; 03 46 d2 ; 0xf440f
+ mov dx, word [bp-018h] ; 8b 56 e8 ; 0xf4412
+ adc dx, word [bp-02ah] ; 13 56 d6 ; 0xf4415
+ xchg ah, al ; 86 c4 ; 0xf4418
+ xchg dh, dl ; 86 d6 ; 0xf441a
+ xchg dx, ax ; 92 ; 0xf441c
+ mov word [bp-03ch], ax ; 89 46 c4 ; 0xf441d
+ mov word [bp-03ah], dx ; 89 56 c6 ; 0xf4420
+ mov ax, word [bp-032h] ; 8b 46 ce ; 0xf4423 eltorito.c:602
+ sub ax, word [bp-02eh] ; 2b 46 d2 ; 0xf4426
+ inc ax ; 40 ; 0xf4429
+ xchg ah, al ; 86 c4 ; 0xf442a
+ mov word [bp-037h], ax ; 89 46 c9 ; 0xf442c
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf442f eltorito.c:604
+ mov word [es:si+00eh], di ; 26 89 7c 0e ; 0xf4432
+ mov word [es:si+010h], 00200h ; 26 c7 44 10 00 02 ; 0xf4436 eltorito.c:605
+ mov CL, strict byte 009h ; b1 09 ; 0xf443c eltorito.c:607
+ mov ax, word [bp-022h] ; 8b 46 de ; 0xf443e
+ sal ax, CL ; d3 e0 ; 0xf4441
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf4443
+ mov word [es:si+01eh], ax ; 26 89 44 1e ; 0xf4446
+ mov ax, di ; 89 f8 ; 0xf444a eltorito.c:608
+ xor ah, ah ; 30 e4 ; 0xf444c
+ and AL, strict byte 003h ; 24 03 ; 0xf444e
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf4450
+ sub dx, ax ; 29 c2 ; 0xf4453
+ mov ax, dx ; 89 d0 ; 0xf4455
+ sub ax, word [bp-022h] ; 2b 46 de ; 0xf4457
+ sal ax, CL ; d3 e0 ; 0xf445a
+ and ah, 007h ; 80 e4 07 ; 0xf445c
+ mov word [es:si+020h], ax ; 26 89 44 20 ; 0xf445f
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4463 eltorito.c:610
+ xor ah, ah ; 30 e4 ; 0xf4466
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf4468
+ imul dx ; f7 ea ; 0xf446b
+ mov bx, si ; 89 f3 ; 0xf446d
+ add bx, ax ; 01 c3 ; 0xf446f
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf4471
+ xor ah, ah ; 30 e4 ; 0xf4475
+ sal ax, 1 ; d1 e0 ; 0xf4477
+ mov word [bp-026h], ax ; 89 46 da ; 0xf4479
+ push word [bp-012h] ; ff 76 ee ; 0xf447c
+ push word [bp-010h] ; ff 76 f0 ; 0xf447f
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf4482
+ push ax ; 50 ; 0xf4485
+ mov bx, di ; 89 fb ; 0xf4486
+ xor di, di ; 31 ff ; 0xf4488
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf448a
+ sal bx, 1 ; d1 e3 ; 0xf448d
+ rcl di, 1 ; d1 d7 ; 0xf448f
+ loop 0448dh ; e2 fa ; 0xf4491
+ push di ; 57 ; 0xf4493
+ push bx ; 53 ; 0xf4494
+ push word [bp-024h] ; ff 76 dc ; 0xf4495
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4498
+ xor ah, ah ; 30 e4 ; 0xf449b
+ mov cx, ss ; 8c d1 ; 0xf449d
+ lea bx, [bp-03eh] ; 8d 5e c2 ; 0xf449f
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf44a2
+ mov di, word [bp-026h] ; 8b 7e da ; 0xf44a5
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf44a8
+ mov dx, ax ; 89 c2 ; 0xf44ac
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf44ae eltorito.c:612
+ mov word [es:si+01eh], strict word 00000h ; 26 c7 44 1e 00 00 ; 0xf44b1
+ mov word [es:si+020h], strict word 00000h ; 26 c7 44 20 00 00 ; 0xf44b7 eltorito.c:613
+ test al, al ; 84 c0 ; 0xf44bd eltorito.c:615
+ je short 044f9h ; 74 38 ; 0xf44bf
+ mov bx, 00da0h ; bb a0 0d ; 0xf44c1 eltorito.c:616
+ mov cx, ds ; 8c d9 ; 0xf44c4
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf44c6
+ call 018cch ; e8 00 d4 ; 0xf44c9
+ mov al, dl ; 88 d0 ; 0xf44cc
+ xor ah, ah ; 30 e4 ; 0xf44ce
+ push ax ; 50 ; 0xf44d0
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf44d1
+ push ax ; 50 ; 0xf44d4
+ mov ax, 0034ch ; b8 4c 03 ; 0xf44d5
+ push ax ; 50 ; 0xf44d8
+ mov ax, 0038eh ; b8 8e 03 ; 0xf44d9
+ push ax ; 50 ; 0xf44dc
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf44dd
+ push ax ; 50 ; 0xf44e0
+ call 0190fh ; e8 2b d4 ; 0xf44e1
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf44e4
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf44e7 eltorito.c:617
+ xor ah, ah ; 30 e4 ; 0xf44ea
+ or ah, 002h ; 80 cc 02 ; 0xf44ec
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf44ef
+ mov byte [bp+016h], 000h ; c6 46 16 00 ; 0xf44f2 eltorito.c:618
+ jmp near 047c5h ; e9 cc 02 ; 0xf44f6 eltorito.c:619
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf44f9
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf44fd
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4500
+ mov es, ax ; 8e c0 ; 0xf4503
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf4505
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf4509
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf450d
+ pop di ; 5f ; 0xf4510
+ pop si ; 5e ; 0xf4511
+ pop bp ; 5d ; 0xf4512
+ retn ; c3 ; 0xf4513
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf4514 eltorito.c:626
+ mov ax, word [es:bx+014h] ; 26 8b 47 14 ; 0xf4517
+ mov word [bp-028h], ax ; 89 46 d8 ; 0xf451b
+ mov dx, word [es:bx+012h] ; 26 8b 57 12 ; 0xf451e eltorito.c:627
+ dec dx ; 4a ; 0xf4522
+ mov ax, word [es:bx+010h] ; 26 8b 47 10 ; 0xf4523 eltorito.c:628
+ dec ax ; 48 ; 0xf4527
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf4528
+ mov byte [bp+016h], 000h ; c6 46 16 00 ; 0xf452b eltorito.c:630
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf452f eltorito.c:631
+ xor al, al ; 30 c0 ; 0xf4532
+ mov si, word [bp+014h] ; 8b 76 14 ; 0xf4534 eltorito.c:632
+ and si, 000ffh ; 81 e6 ff 00 ; 0xf4537
+ mov cx, dx ; 89 d1 ; 0xf453b
+ xor ch, dh ; 30 f5 ; 0xf453d
+ mov word [bp-026h], cx ; 89 4e da ; 0xf453f
+ mov cl, byte [bp-026h] ; 8a 4e da ; 0xf4542
+ mov byte [bp-025h], cl ; 88 4e db ; 0xf4545
+ mov byte [bp-026h], al ; 88 46 da ; 0xf4548
+ mov cx, word [bp-026h] ; 8b 4e da ; 0xf454b
+ or cx, si ; 09 f1 ; 0xf454e
+ mov word [bp+014h], cx ; 89 4e 14 ; 0xf4550
+ mov cx, dx ; 89 d1 ; 0xf4553 eltorito.c:633
+ shr cx, 1 ; d1 e9 ; 0xf4555
+ shr cx, 1 ; d1 e9 ; 0xf4557
+ and cl, 0c0h ; 80 e1 c0 ; 0xf4559
+ mov dx, word [bp-028h] ; 8b 56 d8 ; 0xf455c
+ and dl, 03fh ; 80 e2 3f ; 0xf455f
+ or dl, cl ; 08 ca ; 0xf4562
+ mov cx, word [bp+014h] ; 8b 4e 14 ; 0xf4564
+ mov cl, dl ; 88 d1 ; 0xf4567
+ mov word [bp+014h], cx ; 89 4e 14 ; 0xf4569
+ mov cx, word [bp+012h] ; 8b 4e 12 ; 0xf456c eltorito.c:634
+ mov ch, byte [bp-00ch] ; 8a 6e f4 ; 0xf456f
+ mov word [bp+012h], cx ; 89 4e 12 ; 0xf4572
+ mov dx, cx ; 89 ca ; 0xf4575 eltorito.c:635
+ xor dl, cl ; 30 ca ; 0xf4577
+ or dl, 002h ; 80 ca 02 ; 0xf4579
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf457c
+ mov dl, byte [es:bx+001h] ; 26 8a 57 01 ; 0xf457f eltorito.c:638
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf4583
+ cmp dl, 003h ; 80 fa 03 ; 0xf4586
+ je short 045a5h ; 74 1a ; 0xf4589
+ cmp dl, 002h ; 80 fa 02 ; 0xf458b
+ je short 045a1h ; 74 11 ; 0xf458e
+ cmp dl, 001h ; 80 fa 01 ; 0xf4590
+ jne short 045a9h ; 75 14 ; 0xf4593
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf4595 eltorito.c:639
+ xor al, al ; 30 c0 ; 0xf4598
+ or AL, strict byte 002h ; 0c 02 ; 0xf459a
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf459c
+ jmp short 045a9h ; eb 08 ; 0xf459f
+ or AL, strict byte 004h ; 0c 04 ; 0xf45a1 eltorito.c:640
+ jmp short 0459ch ; eb f7 ; 0xf45a3
+ or AL, strict byte 005h ; 0c 05 ; 0xf45a5 eltorito.c:641
+ jmp short 0459ch ; eb f3 ; 0xf45a7
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf45a9 eltorito.c:645
+ cmp byte [es:bx+001h], 004h ; 26 80 7f 01 04 ; 0xf45ac
+ jc short 045b6h ; 72 03 ; 0xf45b1
+ jmp near 044f9h ; e9 43 ff ; 0xf45b3
+ mov word [bp+008h], 0efc7h ; c7 46 08 c7 ef ; 0xf45b6 eltorito.c:646
+ mov word [bp+006h], 0f000h ; c7 46 06 00 f0 ; 0xf45bb eltorito.c:647
+ jmp short 045b3h ; eb f1 ; 0xf45c0 eltorito.c:649
+ or ah, 003h ; 80 cc 03 ; 0xf45c2 eltorito.c:654
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf45c5
+ jmp near 044fdh ; e9 32 ff ; 0xf45c8 eltorito.c:655
+ mov word [bp+010h], 0aa55h ; c7 46 10 55 aa ; 0xf45cb eltorito.c:659
+ or ah, 030h ; 80 cc 30 ; 0xf45d0 eltorito.c:660
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf45d3
+ mov word [bp+014h], strict word 00007h ; c7 46 14 07 00 ; 0xf45d6 eltorito.c:661
+ jmp near 044fdh ; e9 1f ff ; 0xf45db eltorito.c:662
+ mov di, word [bp+00ah] ; 8b 7e 0a ; 0xf45de eltorito.c:670
+ mov es, [bp+004h] ; 8e 46 04 ; 0xf45e1
+ mov word [bp-020h], di ; 89 7e e0 ; 0xf45e4
+ mov [bp-016h], es ; 8c 46 ea ; 0xf45e7
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf45ea eltorito.c:672
+ mov word [bp-01eh], ax ; 89 46 e2 ; 0xf45ee
+ mov ax, word [es:di+006h] ; 26 8b 45 06 ; 0xf45f1 eltorito.c:673
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf45f5
+ mov ax, word [es:di+004h] ; 26 8b 45 04 ; 0xf45f8 eltorito.c:674
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf45fc
+ mov ax, word [es:di+00ch] ; 26 8b 45 0c ; 0xf45ff eltorito.c:677
+ mov dx, word [es:di+00eh] ; 26 8b 55 0e ; 0xf4603
+ or ax, dx ; 09 d0 ; 0xf4607 eltorito.c:678
+ je short 04626h ; 74 1b ; 0xf4609
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf460b eltorito.c:679
+ xor ah, ah ; 30 e4 ; 0xf460e
+ push ax ; 50 ; 0xf4610
+ mov ax, 0034ch ; b8 4c 03 ; 0xf4611
+ push ax ; 50 ; 0xf4614
+ mov ax, 003afh ; b8 af 03 ; 0xf4615
+ push ax ; 50 ; 0xf4618
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf4619
+ push ax ; 50 ; 0xf461c
+ call 0190fh ; e8 ef d2 ; 0xf461d
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf4620
+ jmp near 047bah ; e9 94 01 ; 0xf4623 eltorito.c:680
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf4626 eltorito.c:684
+ mov di, word [bp-020h] ; 8b 7e e0 ; 0xf4629
+ mov ax, word [es:di+008h] ; 26 8b 45 08 ; 0xf462c
+ mov dx, word [es:di+00ah] ; 26 8b 55 0a ; 0xf4630
+ mov cl, byte [bp+017h] ; 8a 4e 17 ; 0xf4634 eltorito.c:687
+ mov byte [bp-00eh], cl ; 88 4e f2 ; 0xf4637
+ mov byte [bp-00dh], 000h ; c6 46 f3 00 ; 0xf463a
+ cmp word [bp-00eh], strict byte 00044h ; 83 7e f2 44 ; 0xf463e
+ jne short 04647h ; 75 03 ; 0xf4642
+ jmp near 044f9h ; e9 b2 fe ; 0xf4644
+ cmp word [bp-00eh], strict byte 00047h ; 83 7e f2 47 ; 0xf4647
+ jne short 0464fh ; 75 02 ; 0xf464b
+ jmp short 04644h ; eb f5 ; 0xf464d eltorito.c:688
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf464f eltorito.c:695
+ mov cx, word [es:bx+008h] ; 26 8b 4f 08 ; 0xf4652
+ mov word [bp-01ah], cx ; 89 4e e6 ; 0xf4656
+ mov bx, word [es:bx+00ah] ; 26 8b 5f 0a ; 0xf4659
+ mov word [bp-018h], bx ; 89 5e e8 ; 0xf465d
+ mov word [bp-032h], ax ; 89 46 ce ; 0xf4660 eltorito.c:698
+ mov word [bp-030h], dx ; 89 56 d0 ; 0xf4663
+ shr word [bp-030h], 1 ; d1 6e d0 ; 0xf4666
+ rcr word [bp-032h], 1 ; d1 5e ce ; 0xf4669
+ shr word [bp-030h], 1 ; d1 6e d0 ; 0xf466c
+ rcr word [bp-032h], 1 ; d1 5e ce ; 0xf466f
+ mov bx, word [bp-030h] ; 8b 5e d0 ; 0xf4672
+ mov word [bp-02ah], bx ; 89 5e d6 ; 0xf4675
+ mov di, ax ; 89 c7 ; 0xf4678 eltorito.c:699
+ and di, strict byte 00003h ; 83 e7 03 ; 0xf467a
+ xor bx, bx ; 31 db ; 0xf467d eltorito.c:702
+ add ax, word [bp-01eh] ; 03 46 e2 ; 0xf467f
+ adc dx, bx ; 11 da ; 0xf4682
+ add ax, strict word 0ffffh ; 05 ff ff ; 0xf4684
+ adc dx, strict byte 0ffffh ; 83 d2 ff ; 0xf4687
+ mov word [bp-02eh], ax ; 89 46 d2 ; 0xf468a
+ mov word [bp-02ch], dx ; 89 56 d4 ; 0xf468d
+ shr word [bp-02ch], 1 ; d1 6e d4 ; 0xf4690
+ rcr word [bp-02eh], 1 ; d1 5e d2 ; 0xf4693
+ shr word [bp-02ch], 1 ; d1 6e d4 ; 0xf4696
+ rcr word [bp-02eh], 1 ; d1 5e d2 ; 0xf4699
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf469c eltorito.c:704
+ mov dx, ss ; 8c d2 ; 0xf469f
+ lea ax, [bp-03eh] ; 8d 46 c2 ; 0xf46a1
+ call 09c30h ; e8 89 55 ; 0xf46a4
+ mov word [bp-03eh], strict word 00028h ; c7 46 c2 28 00 ; 0xf46a7 eltorito.c:705
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf46ac eltorito.c:706
+ add ax, word [bp-032h] ; 03 46 ce ; 0xf46af
+ mov dx, word [bp-018h] ; 8b 56 e8 ; 0xf46b2
+ adc dx, word [bp-02ah] ; 13 56 d6 ; 0xf46b5
+ xchg ah, al ; 86 c4 ; 0xf46b8
+ xchg dh, dl ; 86 d6 ; 0xf46ba
+ xchg dx, ax ; 92 ; 0xf46bc
+ mov word [bp-03ch], ax ; 89 46 c4 ; 0xf46bd
+ mov word [bp-03ah], dx ; 89 56 c6 ; 0xf46c0
+ mov ax, word [bp-02eh] ; 8b 46 d2 ; 0xf46c3 eltorito.c:707
+ sub ax, word [bp-032h] ; 2b 46 ce ; 0xf46c6
+ inc ax ; 40 ; 0xf46c9
+ xchg ah, al ; 86 c4 ; 0xf46ca
+ mov word [bp-037h], ax ; 89 46 c9 ; 0xf46cc
+ mov CL, strict byte 009h ; b1 09 ; 0xf46cf eltorito.c:709
+ mov ax, di ; 89 f8 ; 0xf46d1
+ sal ax, CL ; d3 e0 ; 0xf46d3
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf46d5
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf46d8
+ mov word [es:si+01eh], ax ; 26 89 44 1e ; 0xf46db
+ mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xf46df eltorito.c:710
+ xor ah, ah ; 30 e4 ; 0xf46e2
+ and AL, strict byte 003h ; 24 03 ; 0xf46e4
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf46e6
+ sub dx, ax ; 29 c2 ; 0xf46e9
+ mov ax, dx ; 89 d0 ; 0xf46eb
+ sub ax, di ; 29 f8 ; 0xf46ed
+ sal ax, CL ; d3 e0 ; 0xf46ef
+ and ah, 007h ; 80 e4 07 ; 0xf46f1
+ mov word [es:si+020h], ax ; 26 89 44 20 ; 0xf46f4
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf46f8 eltorito.c:712
+ xor ah, ah ; 30 e4 ; 0xf46fb
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf46fd
+ imul dx ; f7 ea ; 0xf4700
+ mov bx, si ; 89 f3 ; 0xf4702
+ add bx, ax ; 01 c3 ; 0xf4704
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf4706
+ xor ah, ah ; 30 e4 ; 0xf470a
+ sal ax, 1 ; d1 e0 ; 0xf470c
+ mov word [bp-026h], ax ; 89 46 da ; 0xf470e
+ push word [bp-012h] ; ff 76 ee ; 0xf4711
+ push word [bp-010h] ; ff 76 f0 ; 0xf4714
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf4717
+ push ax ; 50 ; 0xf471a
+ mov bx, word [bp-01eh] ; 8b 5e e2 ; 0xf471b
+ xor di, di ; 31 ff ; 0xf471e
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf4720
+ sal bx, 1 ; d1 e3 ; 0xf4723
+ rcl di, 1 ; d1 d7 ; 0xf4725
+ loop 04723h ; e2 fa ; 0xf4727
+ push di ; 57 ; 0xf4729
+ push bx ; 53 ; 0xf472a
+ push word [bp-024h] ; ff 76 dc ; 0xf472b
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf472e
+ xor ah, ah ; 30 e4 ; 0xf4731
+ mov cx, ss ; 8c d1 ; 0xf4733
+ lea bx, [bp-03eh] ; 8d 5e c2 ; 0xf4735
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf4738
+ mov di, word [bp-026h] ; 8b 7e da ; 0xf473b
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf473e
+ mov dx, ax ; 89 c2 ; 0xf4742
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf4744 eltorito.c:714
+ mov word [es:si+01eh], strict word 00000h ; 26 c7 44 1e 00 00 ; 0xf4747
+ mov word [es:si+020h], strict word 00000h ; 26 c7 44 20 00 00 ; 0xf474d eltorito.c:715
+ mov bx, word [es:si+01ah] ; 26 8b 5c 1a ; 0xf4753 eltorito.c:717
+ mov di, word [es:si+01ch] ; 26 8b 7c 1c ; 0xf4757
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf475b
+ shr di, 1 ; d1 ef ; 0xf475e
+ rcr bx, 1 ; d1 db ; 0xf4760
+ loop 0475eh ; e2 fa ; 0xf4762
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf4764 eltorito.c:718
+ mov si, word [bp-020h] ; 8b 76 e0 ; 0xf4767
+ mov word [es:si+002h], bx ; 26 89 5c 02 ; 0xf476a
+ test al, al ; 84 c0 ; 0xf476e eltorito.c:720
+ jne short 04775h ; 75 03 ; 0xf4770
+ jmp near 044f9h ; e9 84 fd ; 0xf4772
+ mov bx, 00da0h ; bb a0 0d ; 0xf4775 eltorito.c:721
+ mov cx, ds ; 8c d9 ; 0xf4778
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf477a
+ call 018cch ; e8 4c d1 ; 0xf477d
+ mov al, dl ; 88 d0 ; 0xf4780
+ xor ah, ah ; 30 e4 ; 0xf4782
+ push ax ; 50 ; 0xf4784
+ push word [bp-00eh] ; ff 76 f2 ; 0xf4785
+ mov ax, 0034ch ; b8 4c 03 ; 0xf4788
+ push ax ; 50 ; 0xf478b
+ mov ax, 003d8h ; b8 d8 03 ; 0xf478c
+ push ax ; 50 ; 0xf478f
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4790
+ push ax ; 50 ; 0xf4793
+ call 0190fh ; e8 78 d1 ; 0xf4794
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf4797
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf479a eltorito.c:722
+ xor ah, ah ; 30 e4 ; 0xf479d
+ or ah, 00ch ; 80 cc 0c ; 0xf479f
+ jmp short 047c2h ; eb 1e ; 0xf47a2
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf47a4 eltorito.c:730
+ push ax ; 50 ; 0xf47a7
+ mov ax, word [bp+00ah] ; 8b 46 0a ; 0xf47a8
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf47ab
+ mov bx, si ; 89 f3 ; 0xf47ae
+ mov cx, word [bp-008h] ; 8b 4e f8 ; 0xf47b0
+ call 05a95h ; e8 df 12 ; 0xf47b3
+ test ax, ax ; 85 c0 ; 0xf47b6
+ je short 04772h ; 74 b8 ; 0xf47b8
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf47ba eltorito.c:731
+ xor ah, ah ; 30 e4 ; 0xf47bd
+ or ah, 001h ; 80 cc 01 ; 0xf47bf
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf47c2
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf47c5
+ xor ah, ah ; 30 e4 ; 0xf47c8
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf47ca
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf47cd
+ mov es, dx ; 8e c2 ; 0xf47d0
+ mov byte [es:bx], al ; 26 88 07 ; 0xf47d2
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf47d5
+ jmp near 0450dh ; e9 31 fd ; 0xf47d9
+ mov bx, 00da0h ; bb a0 0d ; 0xf47dc eltorito.c:747
+ mov cx, ds ; 8c d9 ; 0xf47df
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf47e1
+ call 018cch ; e8 e5 d0 ; 0xf47e4
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf47e7
+ xor ah, ah ; 30 e4 ; 0xf47ea
+ push ax ; 50 ; 0xf47ec
+ mov ax, 0034ch ; b8 4c 03 ; 0xf47ed
+ push ax ; 50 ; 0xf47f0
+ mov ax, 003fah ; b8 fa 03 ; 0xf47f1
+ push ax ; 50 ; 0xf47f4
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf47f5
+ jmp near 0461ch ; e9 21 fe ; 0xf47f8
+ ; disGetNextSymbol 0xf47fb LB 0x574d -> off=0x59 cb=000000000000038c uValue=00000000000f3254 'int13_cdrom'
+ db 050h, 04eh, 049h, 048h, 047h, 046h, 045h, 044h, 043h, 042h, 041h, 018h, 016h, 015h, 014h, 011h
+ db 010h, 00dh, 00ch, 00bh, 00ah, 009h, 008h, 005h, 004h, 003h, 002h, 001h, 000h, 032h, 049h, 0c5h
+ db 04bh, 0fah, 048h, 032h, 049h, 0efh, 048h, 032h, 049h, 0efh, 048h, 032h, 049h, 0c5h, 04bh, 032h
+ db 049h, 032h, 049h, 0c5h, 04bh, 0c5h, 04bh, 0c5h, 04bh, 0c5h, 04bh, 0c5h, 04bh, 016h, 049h, 0c5h
+ db 04bh, 032h, 049h, 01fh, 049h, 050h, 049h, 0efh, 048h, 050h, 049h, 0a0h, 04ah, 043h, 04bh, 050h
+ db 049h, 06ch, 04bh, 086h, 04bh, 08eh, 04bh, 032h, 049h
+int13_cdrom: ; 0xf4854 LB 0x38c
+ push bp ; 55 ; 0xf4854 eltorito.c:772
+ mov bp, sp ; 89 e5 ; 0xf4855
+ push si ; 56 ; 0xf4857
+ push di ; 57 ; 0xf4858
+ sub sp, strict byte 00020h ; 83 ec 20 ; 0xf4859
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf485c eltorito.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf485f
+ mov es, ax ; 8e c0 ; 0xf4862
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf4864
+ mov si, 00122h ; be 22 01 ; 0xf4867 eltorito.c:782
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf486a
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf486d eltorito.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf4870
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf4874 eltorito.c:789
+ xor ah, ah ; 30 e4 ; 0xf4877
+ cmp ax, 000e0h ; 3d e0 00 ; 0xf4879
+ jc short 04883h ; 72 05 ; 0xf487c
+ cmp ax, 000f0h ; 3d f0 00 ; 0xf487e
+ jc short 048a2h ; 72 1f ; 0xf4881
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf4883 eltorito.c:790
+ xor ah, ah ; 30 e4 ; 0xf4886
+ push ax ; 50 ; 0xf4888
+ mov al, byte [bp+019h] ; 8a 46 19 ; 0xf4889
+ push ax ; 50 ; 0xf488c
+ mov ax, 0042ah ; b8 2a 04 ; 0xf488d
+ push ax ; 50 ; 0xf4890
+ mov ax, 00436h ; b8 36 04 ; 0xf4891
+ push ax ; 50 ; 0xf4894
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4895
+ push ax ; 50 ; 0xf4898
+ call 0190fh ; e8 73 d0 ; 0xf4899
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf489c
+ jmp near 04ba4h ; e9 02 03 ; 0xf489f eltorito.c:791
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf48a2 eltorito.c:795
+ xor ah, ah ; 30 e4 ; 0xf48a5
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf48a7
+ mov bx, si ; 89 f3 ; 0xf48aa
+ add bx, ax ; 01 c3 ; 0xf48ac
+ mov dl, byte [es:bx+00114h] ; 26 8a 97 14 01 ; 0xf48ae
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf48b3
+ cmp dl, 010h ; 80 fa 10 ; 0xf48b6 eltorito.c:798
+ jc short 048c9h ; 72 0e ; 0xf48b9
+ push ax ; 50 ; 0xf48bb eltorito.c:799
+ mov al, byte [bp+019h] ; 8a 46 19 ; 0xf48bc
+ push ax ; 50 ; 0xf48bf
+ mov ax, 0042ah ; b8 2a 04 ; 0xf48c0
+ push ax ; 50 ; 0xf48c3
+ mov ax, 00461h ; b8 61 04 ; 0xf48c4
+ jmp short 04894h ; eb cb ; 0xf48c7
+ mov al, byte [bp+019h] ; 8a 46 19 ; 0xf48c9 eltorito.c:803
+ xor ah, ah ; 30 e4 ; 0xf48cc
+ mov dx, ax ; 89 c2 ; 0xf48ce
+ cmp ax, strict word 00050h ; 3d 50 00 ; 0xf48d0
+ jnbe short 04932h ; 77 5d ; 0xf48d3
+ push CS ; 0e ; 0xf48d5
+ pop ES ; 07 ; 0xf48d6
+ mov cx, strict word 0001eh ; b9 1e 00 ; 0xf48d7
+ mov di, 047fbh ; bf fb 47 ; 0xf48da
+ repne scasb ; f2 ae ; 0xf48dd
+ sal cx, 1 ; d1 e1 ; 0xf48df
+ mov di, cx ; 89 cf ; 0xf48e1
+ mov ax, word [cs:di+04818h] ; 2e 8b 85 18 48 ; 0xf48e3
+ mov bx, word [bp+018h] ; 8b 5e 18 ; 0xf48e8
+ xor bh, bh ; 30 ff ; 0xf48eb
+ jmp ax ; ff e0 ; 0xf48ed
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf48ef eltorito.c:821
+ xor ah, ah ; 30 e4 ; 0xf48f2
+ or ah, 003h ; 80 cc 03 ; 0xf48f4
+ jmp near 04bach ; e9 b2 02 ; 0xf48f7 eltorito.c:822
+ mov si, strict word 00074h ; be 74 00 ; 0xf48fa eltorito.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf48fd
+ mov es, ax ; 8e c0 ; 0xf4900
+ mov dl, byte [es:si] ; 26 8a 14 ; 0xf4902
+ mov bh, dl ; 88 d7 ; 0xf4905 eltorito.c:827
+ mov word [bp+018h], bx ; 89 5e 18 ; 0xf4907
+ mov bx, si ; 89 f3 ; 0xf490a eltorito.c:43
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf490c
+ test dl, dl ; 84 d2 ; 0xf490f eltorito.c:831
+ je short 0492fh ; 74 1c ; 0xf4911
+ jmp near 04bbfh ; e9 a9 02 ; 0xf4913 eltorito.c:832
+ or bh, 002h ; 80 cf 02 ; 0xf4916 eltorito.c:838
+ mov word [bp+018h], bx ; 89 5e 18 ; 0xf4919
+ jmp near 04bafh ; e9 90 02 ; 0xf491c eltorito.c:839
+ mov word [bp+012h], 0aa55h ; c7 46 12 55 aa ; 0xf491f eltorito.c:843
+ or bh, 030h ; 80 cf 30 ; 0xf4924 eltorito.c:844
+ mov word [bp+018h], bx ; 89 5e 18 ; 0xf4927
+ mov word [bp+016h], strict word 00007h ; c7 46 16 07 00 ; 0xf492a eltorito.c:845
+ jmp near 04bc9h ; e9 97 02 ; 0xf492f eltorito.c:846
+ mov bx, 00da0h ; bb a0 0d ; 0xf4932
+ mov cx, ds ; 8c d9 ; 0xf4935
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4937
+ call 018cch ; e8 8f cf ; 0xf493a
+ mov al, byte [bp+019h] ; 8a 46 19 ; 0xf493d
+ xor ah, ah ; 30 e4 ; 0xf4940
+ push ax ; 50 ; 0xf4942
+ mov ax, 0042ah ; b8 2a 04 ; 0xf4943
+ push ax ; 50 ; 0xf4946
+ mov ax, 00333h ; b8 33 03 ; 0xf4947
+ push ax ; 50 ; 0xf494a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf494b
+ jmp short 04991h ; eb 41 ; 0xf494e
+ mov bx, word [bp+00ch] ; 8b 5e 0c ; 0xf4950 eltorito.c:854
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf4953
+ mov word [bp-010h], bx ; 89 5e f0 ; 0xf4956
+ mov [bp-018h], es ; 8c 46 e8 ; 0xf4959
+ mov ax, word [es:bx+002h] ; 26 8b 47 02 ; 0xf495c eltorito.c:856
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf4960
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf4963 eltorito.c:857
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf4967
+ mov ax, word [es:bx+004h] ; 26 8b 47 04 ; 0xf496a eltorito.c:858
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf496e
+ mov ax, word [es:bx+00ch] ; 26 8b 47 0c ; 0xf4971 eltorito.c:861
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf4975
+ mov di, word [es:bx+00eh] ; 26 8b 7f 0e ; 0xf4978
+ or di, ax ; 09 c7 ; 0xf497c eltorito.c:862
+ je short 0499bh ; 74 1b ; 0xf497e
+ mov al, byte [bp+019h] ; 8a 46 19 ; 0xf4980 eltorito.c:863
+ xor ah, ah ; 30 e4 ; 0xf4983
+ push ax ; 50 ; 0xf4985
+ mov ax, 0042ah ; b8 2a 04 ; 0xf4986
+ push ax ; 50 ; 0xf4989
+ mov ax, 003afh ; b8 af 03 ; 0xf498a
+ push ax ; 50 ; 0xf498d
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf498e
+ push ax ; 50 ; 0xf4991
+ call 0190fh ; e8 7a cf ; 0xf4992
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf4995
+ jmp near 04ba4h ; e9 09 02 ; 0xf4998 eltorito.c:864
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf499b eltorito.c:868
+ mov bx, word [bp-010h] ; 8b 5e f0 ; 0xf499e
+ mov ax, word [es:bx+008h] ; 26 8b 47 08 ; 0xf49a1
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf49a5
+ mov di, bx ; 89 df ; 0xf49a8
+ mov di, word [es:di+00ah] ; 26 8b 7d 0a ; 0xf49aa
+ mov al, byte [bp+019h] ; 8a 46 19 ; 0xf49ae eltorito.c:871
+ mov byte [bp-016h], al ; 88 46 ea ; 0xf49b1
+ mov byte [bp-015h], 000h ; c6 46 eb 00 ; 0xf49b4
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf49b8
+ cmp ax, strict word 00044h ; 3d 44 00 ; 0xf49bb
+ je short 049c5h ; 74 05 ; 0xf49be
+ cmp ax, strict word 00047h ; 3d 47 00 ; 0xf49c0
+ jne short 049c8h ; 75 03 ; 0xf49c3
+ jmp near 04bc5h ; e9 fd 01 ; 0xf49c5 eltorito.c:872
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf49c8 eltorito.c:877
+ xor bx, bx ; 31 db ; 0xf49cb
+ mov dx, ss ; 8c d2 ; 0xf49cd
+ lea ax, [bp-024h] ; 8d 46 dc ; 0xf49cf
+ call 09c30h ; e8 5b 52 ; 0xf49d2
+ mov word [bp-024h], strict word 00028h ; c7 46 dc 28 00 ; 0xf49d5 eltorito.c:878
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf49da eltorito.c:879
+ mov dx, di ; 89 fa ; 0xf49dd
+ xchg ah, al ; 86 c4 ; 0xf49df
+ xchg dh, dl ; 86 d6 ; 0xf49e1
+ xchg dx, ax ; 92 ; 0xf49e3
+ mov word [bp-022h], ax ; 89 46 de ; 0xf49e4
+ mov word [bp-020h], dx ; 89 56 e0 ; 0xf49e7
+ mov ax, word [bp-008h] ; 8b 46 f8 ; 0xf49ea eltorito.c:880
+ xchg ah, al ; 86 c4 ; 0xf49ed
+ mov word [bp-01dh], ax ; 89 46 e3 ; 0xf49ef
+ mov ax, word [bp-008h] ; 8b 46 f8 ; 0xf49f2 eltorito.c:882
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf49f5
+ mov word [es:si+00eh], ax ; 26 89 44 0e ; 0xf49f8
+ mov word [es:si+010h], 00800h ; 26 c7 44 10 00 08 ; 0xf49fc eltorito.c:883
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4a02 eltorito.c:885
+ xor ah, ah ; 30 e4 ; 0xf4a05
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf4a07
+ imul dx ; f7 ea ; 0xf4a0a
+ mov bx, si ; 89 f3 ; 0xf4a0c
+ add bx, ax ; 01 c3 ; 0xf4a0e
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf4a10
+ xor ah, ah ; 30 e4 ; 0xf4a14
+ mov di, ax ; 89 c7 ; 0xf4a16
+ sal di, 1 ; d1 e7 ; 0xf4a18
+ push word [bp-00eh] ; ff 76 f2 ; 0xf4a1a
+ push word [bp-012h] ; ff 76 ee ; 0xf4a1d
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf4a20
+ push ax ; 50 ; 0xf4a23
+ mov ax, word [bp-008h] ; 8b 46 f8 ; 0xf4a24
+ xor dx, dx ; 31 d2 ; 0xf4a27
+ mov cx, strict word 0000bh ; b9 0b 00 ; 0xf4a29
+ sal ax, 1 ; d1 e0 ; 0xf4a2c
+ rcl dx, 1 ; d1 d2 ; 0xf4a2e
+ loop 04a2ch ; e2 fa ; 0xf4a30
+ push dx ; 52 ; 0xf4a32
+ push ax ; 50 ; 0xf4a33
+ xor ax, ax ; 31 c0 ; 0xf4a34
+ push ax ; 50 ; 0xf4a36
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4a37
+ xor ah, ah ; 30 e4 ; 0xf4a3a
+ mov cx, ss ; 8c d1 ; 0xf4a3c
+ lea bx, [bp-024h] ; 8d 5e dc ; 0xf4a3e
+ mov dx, strict word 0000ch ; ba 0c 00 ; 0xf4a41
+ call word [word di+0006ah] ; ff 95 6a 00 ; 0xf4a44
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf4a48
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf4a4b eltorito.c:887
+ mov ax, word [es:si+01ah] ; 26 8b 44 1a ; 0xf4a4e
+ mov dx, word [es:si+01ch] ; 26 8b 54 1c ; 0xf4a52
+ mov cx, strict word 0000bh ; b9 0b 00 ; 0xf4a56
+ shr dx, 1 ; d1 ea ; 0xf4a59
+ rcr ax, 1 ; d1 d8 ; 0xf4a5b
+ loop 04a59h ; e2 fa ; 0xf4a5d
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf4a5f eltorito.c:888
+ mov bx, word [bp-010h] ; 8b 5e f0 ; 0xf4a62
+ mov word [es:bx+002h], ax ; 26 89 47 02 ; 0xf4a65
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf4a69 eltorito.c:890
+ je short 04aa8h ; 74 39 ; 0xf4a6d
+ mov bx, 00da0h ; bb a0 0d ; 0xf4a6f eltorito.c:891
+ mov cx, ds ; 8c d9 ; 0xf4a72
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4a74
+ call 018cch ; e8 52 ce ; 0xf4a77
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf4a7a
+ xor ah, ah ; 30 e4 ; 0xf4a7d
+ push ax ; 50 ; 0xf4a7f
+ push word [bp-016h] ; ff 76 ea ; 0xf4a80
+ mov ax, 0042ah ; b8 2a 04 ; 0xf4a83
+ push ax ; 50 ; 0xf4a86
+ mov ax, 003d8h ; b8 d8 03 ; 0xf4a87
+ push ax ; 50 ; 0xf4a8a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4a8b
+ push ax ; 50 ; 0xf4a8e
+ call 0190fh ; e8 7d ce ; 0xf4a8f
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf4a92
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4a95 eltorito.c:892
+ xor ah, ah ; 30 e4 ; 0xf4a98
+ or ah, 00ch ; 80 cc 0c ; 0xf4a9a
+ jmp near 04bach ; e9 0c 01 ; 0xf4a9d
+ cmp bx, strict byte 00002h ; 83 fb 02 ; 0xf4aa0 eltorito.c:900
+ jbe short 04aabh ; 76 06 ; 0xf4aa3
+ jmp near 04ba4h ; e9 fc 00 ; 0xf4aa5 eltorito.c:901
+ jmp near 04bc5h ; e9 1a 01 ; 0xf4aa8
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4aab eltorito.c:903
+ xor ah, ah ; 30 e4 ; 0xf4aae
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf4ab0
+ imul dx ; f7 ea ; 0xf4ab3
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf4ab5
+ mov di, si ; 89 f7 ; 0xf4ab8
+ add di, ax ; 01 c7 ; 0xf4aba
+ mov cl, byte [es:di+025h] ; 26 8a 4d 25 ; 0xf4abc
+ cmp bx, strict byte 00002h ; 83 fb 02 ; 0xf4ac0 eltorito.c:905
+ je short 04b2bh ; 74 66 ; 0xf4ac3
+ cmp bx, strict byte 00001h ; 83 fb 01 ; 0xf4ac5
+ je short 04b06h ; 74 3c ; 0xf4ac8
+ test bx, bx ; 85 db ; 0xf4aca
+ jne short 04b3bh ; 75 6d ; 0xf4acc
+ cmp cl, 0ffh ; 80 f9 ff ; 0xf4ace eltorito.c:907
+ jne short 04ae5h ; 75 12 ; 0xf4ad1
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4ad3 eltorito.c:908
+ xor ah, ah ; 30 e4 ; 0xf4ad6
+ or ah, 0b4h ; 80 cc b4 ; 0xf4ad8
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4adb
+ xor al, al ; 30 c0 ; 0xf4ade eltorito.c:909
+ or AL, strict byte 001h ; 0c 01 ; 0xf4ae0
+ jmp near 04bach ; e9 c7 00 ; 0xf4ae2
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4ae5 eltorito.c:911
+ xor ah, ah ; 30 e4 ; 0xf4ae8
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf4aea
+ imul dx ; f7 ea ; 0xf4aed
+ db 0feh, 0c1h
+ ; inc cl ; fe c1 ; 0xf4aef eltorito.c:912
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf4af1
+ add si, ax ; 01 c6 ; 0xf4af4
+ mov byte [es:si+025h], cl ; 26 88 4c 25 ; 0xf4af6
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4afa eltorito.c:913
+ xor al, al ; 30 c0 ; 0xf4afd
+ or AL, strict byte 001h ; 0c 01 ; 0xf4aff
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4b01
+ jmp short 04b3bh ; eb 35 ; 0xf4b04 eltorito.c:914
+ test cl, cl ; 84 c9 ; 0xf4b06 eltorito.c:916
+ jne short 04b16h ; 75 0c ; 0xf4b08
+ or bh, 0b0h ; 80 cf b0 ; 0xf4b0a eltorito.c:917
+ mov word [bp+018h], bx ; 89 5e 18 ; 0xf4b0d
+ mov byte [bp+018h], cl ; 88 4e 18 ; 0xf4b10 eltorito.c:918
+ jmp near 04bafh ; e9 99 00 ; 0xf4b13 eltorito.c:919
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4b16 eltorito.c:920
+ xor ah, ah ; 30 e4 ; 0xf4b19
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf4b1b
+ imul dx ; f7 ea ; 0xf4b1e
+ db 0feh, 0c9h
+ ; dec cl ; fe c9 ; 0xf4b20 eltorito.c:921
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf4b22
+ add si, ax ; 01 c6 ; 0xf4b25
+ mov byte [es:si+025h], cl ; 26 88 4c 25 ; 0xf4b27
+ test cl, cl ; 84 c9 ; 0xf4b2b eltorito.c:922
+ jne short 04b3eh ; 75 0f ; 0xf4b2d
+ xor ax, ax ; 31 c0 ; 0xf4b2f
+ mov dx, word [bp+018h] ; 8b 56 18 ; 0xf4b31
+ xor dl, dl ; 30 d2 ; 0xf4b34
+ or dx, ax ; 09 c2 ; 0xf4b36
+ mov word [bp+018h], dx ; 89 56 18 ; 0xf4b38
+ jmp near 04bc5h ; e9 87 00 ; 0xf4b3b
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf4b3e
+ jmp short 04b31h ; eb ee ; 0xf4b41
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4b43 eltorito.c:932
+ xor ah, ah ; 30 e4 ; 0xf4b46
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf4b48
+ imul dx ; f7 ea ; 0xf4b4b
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf4b4d
+ add si, ax ; 01 c6 ; 0xf4b50
+ mov cl, byte [es:si+025h] ; 26 8a 4c 25 ; 0xf4b52
+ test cl, cl ; 84 c9 ; 0xf4b56 eltorito.c:934
+ je short 04b60h ; 74 06 ; 0xf4b58
+ or bh, 0b1h ; 80 cf b1 ; 0xf4b5a eltorito.c:935
+ jmp near 04919h ; e9 b9 fd ; 0xf4b5d
+ je short 04bc5h ; 74 63 ; 0xf4b60 eltorito.c:957
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4b62 eltorito.c:958
+ xor ah, ah ; 30 e4 ; 0xf4b65
+ or ah, 0b1h ; 80 cc b1 ; 0xf4b67
+ jmp short 04bach ; eb 40 ; 0xf4b6a
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4b6c eltorito.c:966
+ xor ah, ah ; 30 e4 ; 0xf4b6f
+ push ax ; 50 ; 0xf4b71
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf4b72
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf4b75
+ mov bx, si ; 89 f3 ; 0xf4b78
+ mov cx, word [bp-014h] ; 8b 4e ec ; 0xf4b7a
+ call 05a95h ; e8 15 0f ; 0xf4b7d
+ test ax, ax ; 85 c0 ; 0xf4b80
+ je short 04bc5h ; 74 41 ; 0xf4b82
+ jmp short 04ba4h ; eb 1e ; 0xf4b84 eltorito.c:967
+ or bh, 006h ; 80 cf 06 ; 0xf4b86 eltorito.c:974
+ mov word [bp+018h], bx ; 89 5e 18 ; 0xf4b89
+ jmp short 04bbfh ; eb 31 ; 0xf4b8c eltorito.c:975
+ cmp bx, strict byte 00006h ; 83 fb 06 ; 0xf4b8e eltorito.c:980
+ je short 04bc5h ; 74 32 ; 0xf4b91
+ cmp bx, strict byte 00001h ; 83 fb 01 ; 0xf4b93
+ jc short 04ba4h ; 72 0c ; 0xf4b96
+ jbe short 04bc5h ; 76 2b ; 0xf4b98
+ cmp bx, strict byte 00003h ; 83 fb 03 ; 0xf4b9a
+ jc short 04ba4h ; 72 05 ; 0xf4b9d
+ cmp bx, strict byte 00004h ; 83 fb 04 ; 0xf4b9f
+ jbe short 04bc5h ; 76 21 ; 0xf4ba2
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf4ba4 eltorito.c:1007
+ xor ah, ah ; 30 e4 ; 0xf4ba7
+ or ah, 001h ; 80 cc 01 ; 0xf4ba9
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf4bac
+ mov al, byte [bp+019h] ; 8a 46 19 ; 0xf4baf eltorito.c:1009
+ xor ah, ah ; 30 e4 ; 0xf4bb2
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4bb4 eltorito.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf4bb7
+ mov es, dx ; 8e c2 ; 0xf4bba
+ mov byte [es:bx], al ; 26 88 07 ; 0xf4bbc
+ or byte [bp+01eh], 001h ; 80 4e 1e 01 ; 0xf4bbf eltorito.c:1011
+ jmp short 04bd9h ; eb 14 ; 0xf4bc3 eltorito.c:1012
+ mov byte [bp+019h], 000h ; c6 46 19 00 ; 0xf4bc5 eltorito.c:1015
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf4bc9 eltorito.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4bcc
+ mov es, ax ; 8e c0 ; 0xf4bcf
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf4bd1
+ and byte [bp+01eh], 0feh ; 80 66 1e fe ; 0xf4bd5 eltorito.c:1018
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf4bd9 eltorito.c:1020
+ pop di ; 5f ; 0xf4bdc
+ pop si ; 5e ; 0xf4bdd
+ pop bp ; 5d ; 0xf4bde
+ retn ; c3 ; 0xf4bdf
+ ; disGetNextSymbol 0xf4be0 LB 0x5368 -> off=0x0 cb=0000000000000051 uValue=00000000000f35e0 'print_boot_device'
+print_boot_device: ; 0xf4be0 LB 0x51
+ push bp ; 55 ; 0xf4be0 boot.c:109
+ mov bp, sp ; 89 e5 ; 0xf4be1
+ push cx ; 51 ; 0xf4be3
+ test al, al ; 84 c0 ; 0xf4be4 boot.c:117
+ je short 04bedh ; 74 05 ; 0xf4be6
+ mov dx, strict word 00002h ; ba 02 00 ; 0xf4be8
+ jmp short 04c07h ; eb 1a ; 0xf4beb boot.c:118
+ test dl, dl ; 84 d2 ; 0xf4bed
+ je short 04bf6h ; 74 05 ; 0xf4bef
+ mov dx, strict word 00003h ; ba 03 00 ; 0xf4bf1
+ jmp short 04c07h ; eb 11 ; 0xf4bf4 boot.c:119
+ test bl, 080h ; f6 c3 80 ; 0xf4bf6
+ jne short 04bffh ; 75 04 ; 0xf4bf9
+ xor dh, dh ; 30 f6 ; 0xf4bfb
+ jmp short 04c07h ; eb 08 ; 0xf4bfd boot.c:120
+ test bl, 080h ; f6 c3 80 ; 0xf4bff
+ je short 04c2bh ; 74 27 ; 0xf4c02
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf4c04
+ mov bx, 00da0h ; bb a0 0d ; 0xf4c07 boot.c:123
+ mov cx, ds ; 8c d9 ; 0xf4c0a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4c0c
+ call 018cch ; e8 ba cc ; 0xf4c0f
+ mov ax, dx ; 89 d0 ; 0xf4c12
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf4c14
+ imul dx ; f7 ea ; 0xf4c17
+ add ax, 00dc6h ; 05 c6 0d ; 0xf4c19
+ push ax ; 50 ; 0xf4c1c
+ mov ax, 00494h ; b8 94 04 ; 0xf4c1d
+ push ax ; 50 ; 0xf4c20
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4c21
+ push ax ; 50 ; 0xf4c24
+ call 0190fh ; e8 e7 cc ; 0xf4c25
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf4c28
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf4c2b boot.c:124
+ pop cx ; 59 ; 0xf4c2e
+ pop bp ; 5d ; 0xf4c2f
+ retn ; c3 ; 0xf4c30
+ ; disGetNextSymbol 0xf4c31 LB 0x5317 -> off=0x0 cb=000000000000009f uValue=00000000000f3631 'print_boot_failure'
+print_boot_failure: ; 0xf4c31 LB 0x9f
+ push bp ; 55 ; 0xf4c31 boot.c:131
+ mov bp, sp ; 89 e5 ; 0xf4c32
+ push si ; 56 ; 0xf4c34
+ mov dh, cl ; 88 ce ; 0xf4c35
+ mov cl, bl ; 88 d9 ; 0xf4c37 boot.c:134
+ and cl, 07fh ; 80 e1 7f ; 0xf4c39
+ xor ch, ch ; 30 ed ; 0xf4c3c
+ mov si, cx ; 89 ce ; 0xf4c3e
+ test al, al ; 84 c0 ; 0xf4c40 boot.c:142
+ je short 04c63h ; 74 1f ; 0xf4c42
+ mov bx, 00da0h ; bb a0 0d ; 0xf4c44 boot.c:143
+ mov cx, ds ; 8c d9 ; 0xf4c47
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4c49
+ call 018cch ; e8 7d cc ; 0xf4c4c
+ mov cx, 00ddah ; b9 da 0d ; 0xf4c4f
+ push cx ; 51 ; 0xf4c52
+ mov cx, 004a8h ; b9 a8 04 ; 0xf4c53
+ push cx ; 51 ; 0xf4c56
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf4c57
+ push cx ; 51 ; 0xf4c5a
+ call 0190fh ; e8 b1 cc ; 0xf4c5b
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf4c5e
+ jmp short 04cabh ; eb 48 ; 0xf4c61 boot.c:144
+ test dl, dl ; 84 d2 ; 0xf4c63
+ je short 04c77h ; 74 10 ; 0xf4c65
+ mov bx, 00da0h ; bb a0 0d ; 0xf4c67 boot.c:145
+ mov cx, ds ; 8c d9 ; 0xf4c6a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4c6c
+ call 018cch ; e8 5a cc ; 0xf4c6f
+ mov cx, 00de4h ; b9 e4 0d ; 0xf4c72
+ jmp short 04c52h ; eb db ; 0xf4c75
+ test bl, 080h ; f6 c3 80 ; 0xf4c77 boot.c:146
+ je short 04c8dh ; 74 11 ; 0xf4c7a
+ mov bx, 00da0h ; bb a0 0d ; 0xf4c7c boot.c:147
+ mov cx, ds ; 8c d9 ; 0xf4c7f
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4c81
+ call 018cch ; e8 45 cc ; 0xf4c84
+ push si ; 56 ; 0xf4c87
+ mov cx, 00dd0h ; b9 d0 0d ; 0xf4c88
+ jmp short 04c9ch ; eb 0f ; 0xf4c8b boot.c:148
+ mov bx, 00da0h ; bb a0 0d ; 0xf4c8d boot.c:149
+ mov cx, ds ; 8c d9 ; 0xf4c90
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4c92
+ call 018cch ; e8 34 cc ; 0xf4c95
+ push si ; 56 ; 0xf4c98
+ mov cx, 00dc6h ; b9 c6 0d ; 0xf4c99
+ push cx ; 51 ; 0xf4c9c
+ mov cx, 004bdh ; b9 bd 04 ; 0xf4c9d
+ push cx ; 51 ; 0xf4ca0
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf4ca1
+ push cx ; 51 ; 0xf4ca4
+ call 0190fh ; e8 67 cc ; 0xf4ca5
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf4ca8
+ cmp byte [bp+004h], 001h ; 80 7e 04 01 ; 0xf4cab boot.c:151
+ jne short 04cc8h ; 75 17 ; 0xf4caf
+ test dh, dh ; 84 f6 ; 0xf4cb1 boot.c:152
+ jne short 04cbah ; 75 05 ; 0xf4cb3
+ mov dx, 004d5h ; ba d5 04 ; 0xf4cb5 boot.c:153
+ jmp short 04cbdh ; eb 03 ; 0xf4cb8 boot.c:154
+ mov dx, 004ffh ; ba ff 04 ; 0xf4cba boot.c:155
+ push dx ; 52 ; 0xf4cbd
+ mov dx, strict word 00007h ; ba 07 00 ; 0xf4cbe
+ push dx ; 52 ; 0xf4cc1
+ call 0190fh ; e8 4a cc ; 0xf4cc2
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf4cc5
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf4cc8 boot.c:157
+ pop si ; 5e ; 0xf4ccb
+ pop bp ; 5d ; 0xf4ccc
+ retn 00002h ; c2 02 00 ; 0xf4ccd
+ ; disGetNextSymbol 0xf4cd0 LB 0x5278 -> off=0x0 cb=000000000000002a uValue=00000000000f36d0 'print_cdromboot_failure'
+print_cdromboot_failure: ; 0xf4cd0 LB 0x2a
+ push bp ; 55 ; 0xf4cd0 boot.c:163
+ mov bp, sp ; 89 e5 ; 0xf4cd1
+ push bx ; 53 ; 0xf4cd3
+ push cx ; 51 ; 0xf4cd4
+ push dx ; 52 ; 0xf4cd5
+ mov dx, ax ; 89 c2 ; 0xf4cd6
+ mov bx, 00da0h ; bb a0 0d ; 0xf4cd8 boot.c:165
+ mov cx, ds ; 8c d9 ; 0xf4cdb
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4cdd
+ call 018cch ; e8 e9 cb ; 0xf4ce0
+ push dx ; 52 ; 0xf4ce3
+ mov dx, 00534h ; ba 34 05 ; 0xf4ce4
+ push dx ; 52 ; 0xf4ce7
+ mov dx, strict word 00004h ; ba 04 00 ; 0xf4ce8
+ push dx ; 52 ; 0xf4ceb
+ call 0190fh ; e8 20 cc ; 0xf4cec
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf4cef
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf4cf2 boot.c:167
+ pop dx ; 5a ; 0xf4cf5
+ pop cx ; 59 ; 0xf4cf6
+ pop bx ; 5b ; 0xf4cf7
+ pop bp ; 5d ; 0xf4cf8
+ retn ; c3 ; 0xf4cf9
+ ; disGetNextSymbol 0xf4cfa LB 0x524e -> off=0x0 cb=0000000000000266 uValue=00000000000f36fa 'int19_function'
+int19_function: ; 0xf4cfa LB 0x266
+ push bp ; 55 ; 0xf4cfa boot.c:170
+ mov bp, sp ; 89 e5 ; 0xf4cfb
+ push si ; 56 ; 0xf4cfd
+ push di ; 57 ; 0xf4cfe
+ sub sp, strict byte 0000eh ; 83 ec 0e ; 0xf4cff
+ mov di, strict word 0000eh ; bf 0e 00 ; 0xf4d02 boot.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf4d05
+ mov es, ax ; 8e c0 ; 0xf4d08
+ mov di, word [es:di] ; 26 8b 3d ; 0xf4d0a
+ mov word [bp-00eh], di ; 89 7e f2 ; 0xf4d0d boot.c:49
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf4d10 boot.c:181
+ mov ax, strict word 0003dh ; b8 3d 00 ; 0xf4d14 boot.c:204
+ call 01652h ; e8 38 c9 ; 0xf4d17
+ mov bl, al ; 88 c3 ; 0xf4d1a
+ xor bh, bh ; 30 ff ; 0xf4d1c
+ mov ax, strict word 00038h ; b8 38 00 ; 0xf4d1e boot.c:205
+ call 01652h ; e8 2e c9 ; 0xf4d21
+ and AL, strict byte 0f0h ; 24 f0 ; 0xf4d24
+ xor ah, ah ; 30 e4 ; 0xf4d26
+ mov CL, strict byte 004h ; b1 04 ; 0xf4d28
+ sal ax, CL ; d3 e0 ; 0xf4d2a
+ mov dx, bx ; 89 da ; 0xf4d2c
+ or dx, ax ; 09 c2 ; 0xf4d2e
+ mov ax, strict word 0003ch ; b8 3c 00 ; 0xf4d30 boot.c:206
+ call 01652h ; e8 1c c9 ; 0xf4d33
+ and AL, strict byte 00fh ; 24 0f ; 0xf4d36
+ xor ah, ah ; 30 e4 ; 0xf4d38
+ mov CL, strict byte 00ch ; b1 0c ; 0xf4d3a
+ sal ax, CL ; d3 e0 ; 0xf4d3c
+ or dx, ax ; 09 c2 ; 0xf4d3e
+ mov bx, 0037dh ; bb 7d 03 ; 0xf4d40 boot.c:38
+ mov es, di ; 8e c7 ; 0xf4d43
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4d45
+ test al, al ; 84 c0 ; 0xf4d48 boot.c:39
+ je short 04d50h ; 74 04 ; 0xf4d4a
+ mov dl, al ; 88 c2 ; 0xf4d4c boot.c:38
+ xor dh, dh ; 30 f6 ; 0xf4d4e boot.c:39
+ cmp byte [bp+004h], 001h ; 80 7e 04 01 ; 0xf4d50 boot.c:210
+ jne short 04d67h ; 75 11 ; 0xf4d54
+ mov ax, strict word 0003ch ; b8 3c 00 ; 0xf4d56 boot.c:211
+ call 01652h ; e8 f6 c8 ; 0xf4d59
+ and AL, strict byte 0f0h ; 24 f0 ; 0xf4d5c
+ xor ah, ah ; 30 e4 ; 0xf4d5e
+ mov CL, strict byte 004h ; b1 04 ; 0xf4d60
+ sar ax, CL ; d3 f8 ; 0xf4d62
+ call 078b3h ; e8 4c 2b ; 0xf4d64
+ cmp byte [bp+004h], 002h ; 80 7e 04 02 ; 0xf4d67 boot.c:213
+ jne short 04d71h ; 75 04 ; 0xf4d6b
+ mov CL, strict byte 004h ; b1 04 ; 0xf4d6d
+ shr dx, CL ; d3 ea ; 0xf4d6f
+ cmp byte [bp+004h], 003h ; 80 7e 04 03 ; 0xf4d71 boot.c:214
+ jne short 04d7bh ; 75 04 ; 0xf4d75
+ mov dl, dh ; 88 f2 ; 0xf4d77
+ xor dh, dh ; 30 f6 ; 0xf4d79
+ cmp byte [bp+004h], 004h ; 80 7e 04 04 ; 0xf4d7b boot.c:215
+ jne short 04d85h ; 75 04 ; 0xf4d7f
+ mov CL, strict byte 00ch ; b1 0c ; 0xf4d81
+ shr dx, CL ; d3 ea ; 0xf4d83
+ cmp dx, strict byte 00010h ; 83 fa 10 ; 0xf4d85 boot.c:216
+ jnc short 04d8eh ; 73 04 ; 0xf4d88
+ mov byte [bp-00ch], 001h ; c6 46 f4 01 ; 0xf4d8a
+ xor al, al ; 30 c0 ; 0xf4d8e boot.c:217
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf4d90
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf4d93
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf4d96 boot.c:218
+ mov bx, 00da0h ; bb a0 0d ; 0xf4d99 boot.c:219
+ mov cx, ds ; 8c d9 ; 0xf4d9c
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4d9e
+ call 018cch ; e8 28 cb ; 0xf4da1
+ push dx ; 52 ; 0xf4da4
+ mov al, byte [bp+004h] ; 8a 46 04 ; 0xf4da5
+ xor ah, ah ; 30 e4 ; 0xf4da8
+ push ax ; 50 ; 0xf4daa
+ mov ax, 00554h ; b8 54 05 ; 0xf4dab
+ push ax ; 50 ; 0xf4dae
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf4daf
+ push ax ; 50 ; 0xf4db2
+ call 0190fh ; e8 59 cb ; 0xf4db3
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf4db6
+ and dx, strict byte 0000fh ; 83 e2 0f ; 0xf4db9 boot.c:221
+ cmp dx, strict byte 00002h ; 83 fa 02 ; 0xf4dbc
+ jc short 04dcfh ; 72 0e ; 0xf4dbf
+ jbe short 04ddeh ; 76 1b ; 0xf4dc1
+ cmp dx, strict byte 00004h ; 83 fa 04 ; 0xf4dc3
+ je short 04dfbh ; 74 33 ; 0xf4dc6
+ cmp dx, strict byte 00003h ; 83 fa 03 ; 0xf4dc8
+ je short 04df1h ; 74 24 ; 0xf4dcb
+ jmp short 04e2ah ; eb 5b ; 0xf4dcd
+ cmp dx, strict byte 00001h ; 83 fa 01 ; 0xf4dcf
+ jne short 04e2ah ; 75 56 ; 0xf4dd2
+ xor al, al ; 30 c0 ; 0xf4dd4 boot.c:223
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf4dd6
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf4dd9 boot.c:224
+ jmp short 04e3dh ; eb 5f ; 0xf4ddc boot.c:225
+ mov bx, 0037ch ; bb 7c 03 ; 0xf4dde boot.c:38
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf4de1
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf4de4
+ add AL, strict byte 080h ; 04 80 ; 0xf4de7 boot.c:231
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf4de9
+ mov byte [bp-008h], dh ; 88 76 f8 ; 0xf4dec boot.c:232
+ jmp short 04e3dh ; eb 4c ; 0xf4def boot.c:233
+ mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xf4df1 boot.c:236
+ mov byte [bp-008h], 001h ; c6 46 f8 01 ; 0xf4df5 boot.c:237
+ jmp short 04e05h ; eb 0a ; 0xf4df9 boot.c:238
+ mov byte [bp-00ah], 001h ; c6 46 f6 01 ; 0xf4dfb boot.c:239
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf4dff boot.c:255
+ je short 04e3dh ; 74 38 ; 0xf4e03
+ call 03dd9h ; e8 d1 ef ; 0xf4e05 boot.c:256
+ mov dx, ax ; 89 c2 ; 0xf4e08
+ test AL, strict byte 0ffh ; a8 ff ; 0xf4e0a boot.c:259
+ je short 04e31h ; 74 23 ; 0xf4e0c
+ call 04cd0h ; e8 bf fe ; 0xf4e0e boot.c:260
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf4e11 boot.c:261
+ xor ah, ah ; 30 e4 ; 0xf4e14
+ push ax ; 50 ; 0xf4e16
+ mov bl, byte [bp-006h] ; 8a 5e fa ; 0xf4e17
+ xor bh, bh ; 30 ff ; 0xf4e1a
+ mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xf4e1c
+ xor dh, dh ; 30 f6 ; 0xf4e1f
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf4e21
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf4e24
+ call 04c31h ; e8 07 fe ; 0xf4e27
+ xor ax, ax ; 31 c0 ; 0xf4e2a
+ xor dx, dx ; 31 d2 ; 0xf4e2c
+ jmp near 04f59h ; e9 28 01 ; 0xf4e2e
+ mov bx, 00372h ; bb 72 03 ; 0xf4e31 boot.c:48
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf4e34
+ mov si, word [es:bx] ; 26 8b 37 ; 0xf4e37
+ mov byte [bp-006h], dh ; 88 76 fa ; 0xf4e3a boot.c:266
+ cmp byte [bp-00ah], 001h ; 80 7e f6 01 ; 0xf4e3d boot.c:272
+ jne short 04e98h ; 75 55 ; 0xf4e41
+ xor si, si ; 31 f6 ; 0xf4e43 boot.c:275
+ mov ax, 0e200h ; b8 00 e2 ; 0xf4e45
+ mov es, ax ; 8e c0 ; 0xf4e48
+ cmp word [es:si], 0aa55h ; 26 81 3c 55 aa ; 0xf4e4a boot.c:276
+ jne short 04e11h ; 75 c0 ; 0xf4e4f
+ mov di, ax ; 89 c7 ; 0xf4e51 boot.c:282
+ mov si, word [es:si+01ah] ; 26 8b 74 1a ; 0xf4e53
+ cmp word [es:si+002h], 0506eh ; 26 81 7c 02 6e 50 ; 0xf4e57 boot.c:283
+ jne short 04e11h ; 75 b2 ; 0xf4e5d
+ cmp word [es:si], 05024h ; 26 81 3c 24 50 ; 0xf4e5f
+ jne short 04e11h ; 75 ab ; 0xf4e64
+ mov bx, word [es:si+00eh] ; 26 8b 5c 0e ; 0xf4e66 boot.c:285
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf4e6a
+ mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xf4e6d
+ cmp dx, 06568h ; 81 fa 68 65 ; 0xf4e71 boot.c:286
+ jne short 04e9ah ; 75 23 ; 0xf4e75
+ cmp ax, 07445h ; 3d 45 74 ; 0xf4e77
+ jne short 04e9ah ; 75 1e ; 0xf4e7a
+ mov bl, byte [bp-006h] ; 8a 5e fa ; 0xf4e7c boot.c:288
+ xor bh, bh ; 30 ff ; 0xf4e7f
+ mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xf4e81
+ xor dh, dh ; 30 f6 ; 0xf4e84
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf4e86
+ xor ah, ah ; 30 e4 ; 0xf4e89
+ call 04be0h ; e8 52 fd ; 0xf4e8b
+ mov word [bp-012h], strict word 00006h ; c7 46 ee 06 00 ; 0xf4e8e boot.c:289
+ mov word [bp-010h], di ; 89 7e f0 ; 0xf4e93
+ jmp short 04eb9h ; eb 21 ; 0xf4e96 boot.c:292
+ jmp short 04ebfh ; eb 25 ; 0xf4e98
+ mov bl, byte [bp-006h] ; 8a 5e fa ; 0xf4e9a boot.c:295
+ xor bh, bh ; 30 ff ; 0xf4e9d
+ mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xf4e9f
+ xor dh, dh ; 30 f6 ; 0xf4ea2
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf4ea4
+ xor ah, ah ; 30 e4 ; 0xf4ea7
+ call 04be0h ; e8 34 fd ; 0xf4ea9
+ sti ; fb ; 0xf4eac boot.c:296
+ mov word [bp-010h], di ; 89 7e f0 ; 0xf4ead boot.c:297
+ mov es, di ; 8e c7 ; 0xf4eb0
+ mov ax, word [es:si+01ah] ; 26 8b 44 1a ; 0xf4eb2
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf4eb6
+ call far [bp-012h] ; ff 5e ee ; 0xf4eb9 boot.c:298
+ jmp near 04e11h ; e9 52 ff ; 0xf4ebc boot.c:301
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf4ebf boot.c:309
+ jne short 04eech ; 75 27 ; 0xf4ec3
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf4ec5
+ jne short 04eech ; 75 21 ; 0xf4ec9
+ mov si, 007c0h ; be c0 07 ; 0xf4ecb boot.c:310
+ mov es, si ; 8e c6 ; 0xf4ece boot.c:312
+ mov dl, byte [bp-006h] ; 8a 56 fa ; 0xf4ed0
+ mov ax, 00201h ; b8 01 02 ; 0xf4ed3
+ mov DH, strict byte 000h ; b6 00 ; 0xf4ed6
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf4ed8
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xf4edb
+ int 013h ; cd 13 ; 0xf4edd
+ mov ax, strict word 00000h ; b8 00 00 ; 0xf4edf
+ sbb ax, strict byte 00000h ; 83 d8 00 ; 0xf4ee2
+ test ax, ax ; 85 c0 ; 0xf4ee5 boot.c:313
+ je short 04eech ; 74 03 ; 0xf4ee7
+ jmp near 04e11h ; e9 25 ff ; 0xf4ee9
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf4eec boot.c:328
+ je short 04ef6h ; 74 04 ; 0xf4ef0
+ xor al, al ; 30 c0 ; 0xf4ef2
+ jmp short 04ef8h ; eb 02 ; 0xf4ef4 boot.c:329
+ mov AL, strict byte 001h ; b0 01 ; 0xf4ef6
+ cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xf4ef8 boot.c:333
+ je short 04f00h ; 74 02 ; 0xf4efc
+ mov AL, strict byte 001h ; b0 01 ; 0xf4efe boot.c:334
+ xor bx, bx ; 31 db ; 0xf4f00 boot.c:48
+ mov es, si ; 8e c6 ; 0xf4f02
+ mov di, word [es:bx] ; 26 8b 3f ; 0xf4f04
+ mov bx, strict word 00004h ; bb 04 00 ; 0xf4f07 boot.c:48
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf4f0a
+ cmp di, dx ; 39 d7 ; 0xf4f0d boot.c:49
+ je short 04f20h ; 74 0f ; 0xf4f0f
+ test al, al ; 84 c0 ; 0xf4f11
+ jne short 04f38h ; 75 23 ; 0xf4f13
+ mov bx, 001feh ; bb fe 01 ; 0xf4f15 boot.c:48
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf4f18
+ cmp ax, 0aa55h ; 3d 55 aa ; 0xf4f1b boot.c:49
+ je short 04f38h ; 74 18 ; 0xf4f1e
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf4f20 boot.c:340
+ xor ah, ah ; 30 e4 ; 0xf4f23
+ push ax ; 50 ; 0xf4f25
+ mov bl, byte [bp-006h] ; 8a 5e fa ; 0xf4f26
+ xor bh, bh ; 30 ff ; 0xf4f29
+ mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xf4f2b
+ xor dh, dh ; 30 f6 ; 0xf4f2e
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf4f30
+ xor cx, cx ; 31 c9 ; 0xf4f33
+ jmp near 04e27h ; e9 ef fe ; 0xf4f35
+ mov bl, byte [bp-006h] ; 8a 5e fa ; 0xf4f38 boot.c:346
+ xor bh, bh ; 30 ff ; 0xf4f3b
+ mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xf4f3d
+ xor dh, dh ; 30 f6 ; 0xf4f40
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf4f42
+ xor ah, ah ; 30 e4 ; 0xf4f45
+ call 04be0h ; e8 96 fc ; 0xf4f47
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf4f4a boot.c:352
+ xor ah, ah ; 30 e4 ; 0xf4f4d
+ mov bx, ax ; 89 c3 ; 0xf4f4f
+ xor dx, dx ; 31 d2 ; 0xf4f51
+ xor al, al ; 30 c0 ; 0xf4f53
+ add ax, si ; 01 f0 ; 0xf4f55
+ adc dx, bx ; 11 da ; 0xf4f57
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf4f59 boot.c:353
+ pop di ; 5f ; 0xf4f5c
+ pop si ; 5e ; 0xf4f5d
+ pop bp ; 5d ; 0xf4f5e
+ retn ; c3 ; 0xf4f5f
+ ; disGetNextSymbol 0xf4f60 LB 0x4fe8 -> off=0x0 cb=0000000000000016 uValue=00000000000f3960 'keyboard_panic'
+keyboard_panic: ; 0xf4f60 LB 0x16
+ push bp ; 55 ; 0xf4f60 keyboard.c:194
+ mov bp, sp ; 89 e5 ; 0xf4f61
+ push ax ; 50 ; 0xf4f63 keyboard.c:199
+ mov ax, 00574h ; b8 74 05 ; 0xf4f64
+ push ax ; 50 ; 0xf4f67
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf4f68
+ push ax ; 50 ; 0xf4f6b
+ call 0190fh ; e8 a0 c9 ; 0xf4f6c
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf4f6f
+ mov sp, bp ; 89 ec ; 0xf4f72 keyboard.c:200
+ pop bp ; 5d ; 0xf4f74
+ retn ; c3 ; 0xf4f75
+ ; disGetNextSymbol 0xf4f76 LB 0x4fd2 -> off=0x0 cb=000000000000026a uValue=00000000000f3976 'keyboard_init'
+keyboard_init: ; 0xf4f76 LB 0x26a
+ push bp ; 55 ; 0xf4f76 keyboard.c:208
+ mov bp, sp ; 89 e5 ; 0xf4f77
+ mov AL, strict byte 0aah ; b0 aa ; 0xf4f79 keyboard.c:214
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4f7b
+ out DX, AL ; ee ; 0xf4f7e
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4f7f keyboard.c:217
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4f82 keyboard.c:218
+ in AL, DX ; ec ; 0xf4f85
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4f86
+ test AL, strict byte 002h ; a8 02 ; 0xf4f88
+ je short 04f99h ; 74 0d ; 0xf4f8a
+ dec bx ; 4b ; 0xf4f8c
+ test bx, bx ; 85 db ; 0xf4f8d
+ jbe short 04f99h ; 76 08 ; 0xf4f8f
+ xor al, al ; 30 c0 ; 0xf4f91
+ mov dx, 00080h ; ba 80 00 ; 0xf4f93
+ out DX, AL ; ee ; 0xf4f96
+ jmp short 04f82h ; eb e9 ; 0xf4f97
+ test bx, bx ; 85 db ; 0xf4f99 keyboard.c:219
+ jne short 04fa2h ; 75 05 ; 0xf4f9b
+ xor ax, ax ; 31 c0 ; 0xf4f9d
+ call 04f60h ; e8 be ff ; 0xf4f9f
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4fa2 keyboard.c:222
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4fa5 keyboard.c:223
+ in AL, DX ; ec ; 0xf4fa8
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4fa9
+ test AL, strict byte 001h ; a8 01 ; 0xf4fab
+ jne short 04fbch ; 75 0d ; 0xf4fad
+ dec bx ; 4b ; 0xf4faf
+ test bx, bx ; 85 db ; 0xf4fb0
+ jbe short 04fbch ; 76 08 ; 0xf4fb2
+ mov AL, strict byte 001h ; b0 01 ; 0xf4fb4
+ mov dx, 00080h ; ba 80 00 ; 0xf4fb6
+ out DX, AL ; ee ; 0xf4fb9
+ jmp short 04fa5h ; eb e9 ; 0xf4fba
+ test bx, bx ; 85 db ; 0xf4fbc keyboard.c:224
+ jne short 04fc6h ; 75 06 ; 0xf4fbe
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf4fc0
+ call 04f60h ; e8 9a ff ; 0xf4fc3
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf4fc6 keyboard.c:227
+ in AL, DX ; ec ; 0xf4fc9
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4fca
+ cmp ax, strict word 00055h ; 3d 55 00 ; 0xf4fcc
+ je short 04fd7h ; 74 06 ; 0xf4fcf
+ mov ax, 003dfh ; b8 df 03 ; 0xf4fd1 keyboard.c:228
+ call 04f60h ; e8 89 ff ; 0xf4fd4
+ mov AL, strict byte 0abh ; b0 ab ; 0xf4fd7 keyboard.c:232
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4fd9
+ out DX, AL ; ee ; 0xf4fdc
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf4fdd keyboard.c:235
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf4fe0 keyboard.c:236
+ in AL, DX ; ec ; 0xf4fe3
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf4fe4
+ test AL, strict byte 002h ; a8 02 ; 0xf4fe6
+ je short 04ff7h ; 74 0d ; 0xf4fe8
+ dec bx ; 4b ; 0xf4fea
+ test bx, bx ; 85 db ; 0xf4feb
+ jbe short 04ff7h ; 76 08 ; 0xf4fed
+ mov AL, strict byte 010h ; b0 10 ; 0xf4fef
+ mov dx, 00080h ; ba 80 00 ; 0xf4ff1
+ out DX, AL ; ee ; 0xf4ff4
+ jmp short 04fe0h ; eb e9 ; 0xf4ff5
+ test bx, bx ; 85 db ; 0xf4ff7 keyboard.c:237
+ jne short 05001h ; 75 06 ; 0xf4ff9
+ mov ax, strict word 0000ah ; b8 0a 00 ; 0xf4ffb
+ call 04f60h ; e8 5f ff ; 0xf4ffe
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf5001 keyboard.c:240
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5004 keyboard.c:241
+ in AL, DX ; ec ; 0xf5007
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5008
+ test AL, strict byte 001h ; a8 01 ; 0xf500a
+ jne short 0501bh ; 75 0d ; 0xf500c
+ dec bx ; 4b ; 0xf500e
+ test bx, bx ; 85 db ; 0xf500f
+ jbe short 0501bh ; 76 08 ; 0xf5011
+ mov AL, strict byte 011h ; b0 11 ; 0xf5013
+ mov dx, 00080h ; ba 80 00 ; 0xf5015
+ out DX, AL ; ee ; 0xf5018
+ jmp short 05004h ; eb e9 ; 0xf5019
+ test bx, bx ; 85 db ; 0xf501b keyboard.c:242
+ jne short 05025h ; 75 06 ; 0xf501d
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf501f
+ call 04f60h ; e8 3b ff ; 0xf5022
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5025 keyboard.c:246
+ in AL, DX ; ec ; 0xf5028
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5029
+ test ax, ax ; 85 c0 ; 0xf502b
+ je short 05035h ; 74 06 ; 0xf502d
+ mov ax, 003e0h ; b8 e0 03 ; 0xf502f keyboard.c:247
+ call 04f60h ; e8 2b ff ; 0xf5032
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf5035 keyboard.c:253
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5037
+ out DX, AL ; ee ; 0xf503a
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf503b keyboard.c:256
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf503e keyboard.c:257
+ in AL, DX ; ec ; 0xf5041
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5042
+ test AL, strict byte 002h ; a8 02 ; 0xf5044
+ je short 05055h ; 74 0d ; 0xf5046
+ dec bx ; 4b ; 0xf5048
+ test bx, bx ; 85 db ; 0xf5049
+ jbe short 05055h ; 76 08 ; 0xf504b
+ mov AL, strict byte 020h ; b0 20 ; 0xf504d
+ mov dx, 00080h ; ba 80 00 ; 0xf504f
+ out DX, AL ; ee ; 0xf5052
+ jmp short 0503eh ; eb e9 ; 0xf5053
+ test bx, bx ; 85 db ; 0xf5055 keyboard.c:258
+ jne short 0505fh ; 75 06 ; 0xf5057
+ mov ax, strict word 00014h ; b8 14 00 ; 0xf5059
+ call 04f60h ; e8 01 ff ; 0xf505c
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf505f keyboard.c:261
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5062 keyboard.c:262
+ in AL, DX ; ec ; 0xf5065
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5066
+ test AL, strict byte 001h ; a8 01 ; 0xf5068
+ jne short 05079h ; 75 0d ; 0xf506a
+ dec bx ; 4b ; 0xf506c
+ test bx, bx ; 85 db ; 0xf506d
+ jbe short 05079h ; 76 08 ; 0xf506f
+ mov AL, strict byte 021h ; b0 21 ; 0xf5071
+ mov dx, 00080h ; ba 80 00 ; 0xf5073
+ out DX, AL ; ee ; 0xf5076
+ jmp short 05062h ; eb e9 ; 0xf5077
+ test bx, bx ; 85 db ; 0xf5079 keyboard.c:263
+ jne short 05083h ; 75 06 ; 0xf507b
+ mov ax, strict word 00015h ; b8 15 00 ; 0xf507d
+ call 04f60h ; e8 dd fe ; 0xf5080
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5083 keyboard.c:266
+ in AL, DX ; ec ; 0xf5086
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5087
+ cmp ax, 000fah ; 3d fa 00 ; 0xf5089
+ je short 05094h ; 74 06 ; 0xf508c
+ mov ax, 003e1h ; b8 e1 03 ; 0xf508e keyboard.c:267
+ call 04f60h ; e8 cc fe ; 0xf5091
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5094 keyboard.c:271
+ in AL, DX ; ec ; 0xf5097
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5098
+ test AL, strict byte 001h ; a8 01 ; 0xf509a
+ jne short 050a6h ; 75 08 ; 0xf509c
+ mov AL, strict byte 031h ; b0 31 ; 0xf509e
+ mov dx, 00080h ; ba 80 00 ; 0xf50a0
+ out DX, AL ; ee ; 0xf50a3
+ jmp short 05094h ; eb ee ; 0xf50a4
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf50a6 keyboard.c:273
+ in AL, DX ; ec ; 0xf50a9
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf50aa
+ cmp ax, 000aah ; 3d aa 00 ; 0xf50ac
+ je short 050bfh ; 74 0e ; 0xf50af
+ in AL, DX ; ec ; 0xf50b1
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf50b2
+ cmp ax, 000aah ; 3d aa 00 ; 0xf50b4
+ je short 050bfh ; 74 06 ; 0xf50b7
+ mov ax, 003e2h ; b8 e2 03 ; 0xf50b9 keyboard.c:274
+ call 04f60h ; e8 a1 fe ; 0xf50bc
+ mov AL, strict byte 0f5h ; b0 f5 ; 0xf50bf keyboard.c:278
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf50c1
+ out DX, AL ; ee ; 0xf50c4
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf50c5 keyboard.c:281
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf50c8 keyboard.c:282
+ in AL, DX ; ec ; 0xf50cb
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf50cc
+ test AL, strict byte 002h ; a8 02 ; 0xf50ce
+ je short 050dfh ; 74 0d ; 0xf50d0
+ dec bx ; 4b ; 0xf50d2
+ test bx, bx ; 85 db ; 0xf50d3
+ jbe short 050dfh ; 76 08 ; 0xf50d5
+ mov AL, strict byte 040h ; b0 40 ; 0xf50d7
+ mov dx, 00080h ; ba 80 00 ; 0xf50d9
+ out DX, AL ; ee ; 0xf50dc
+ jmp short 050c8h ; eb e9 ; 0xf50dd
+ test bx, bx ; 85 db ; 0xf50df keyboard.c:283
+ jne short 050e9h ; 75 06 ; 0xf50e1
+ mov ax, strict word 00028h ; b8 28 00 ; 0xf50e3
+ call 04f60h ; e8 77 fe ; 0xf50e6
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf50e9 keyboard.c:286
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf50ec keyboard.c:287
+ in AL, DX ; ec ; 0xf50ef
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf50f0
+ test AL, strict byte 001h ; a8 01 ; 0xf50f2
+ jne short 05103h ; 75 0d ; 0xf50f4
+ dec bx ; 4b ; 0xf50f6
+ test bx, bx ; 85 db ; 0xf50f7
+ jbe short 05103h ; 76 08 ; 0xf50f9
+ mov AL, strict byte 041h ; b0 41 ; 0xf50fb
+ mov dx, 00080h ; ba 80 00 ; 0xf50fd
+ out DX, AL ; ee ; 0xf5100
+ jmp short 050ech ; eb e9 ; 0xf5101
+ test bx, bx ; 85 db ; 0xf5103 keyboard.c:288
+ jne short 0510dh ; 75 06 ; 0xf5105
+ mov ax, strict word 00029h ; b8 29 00 ; 0xf5107
+ call 04f60h ; e8 53 fe ; 0xf510a
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf510d keyboard.c:291
+ in AL, DX ; ec ; 0xf5110
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5111
+ cmp ax, 000fah ; 3d fa 00 ; 0xf5113
+ je short 0511eh ; 74 06 ; 0xf5116
+ mov ax, 003e3h ; b8 e3 03 ; 0xf5118 keyboard.c:292
+ call 04f60h ; e8 42 fe ; 0xf511b
+ mov AL, strict byte 060h ; b0 60 ; 0xf511e keyboard.c:296
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5120
+ out DX, AL ; ee ; 0xf5123
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf5124 keyboard.c:299
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5127 keyboard.c:300
+ in AL, DX ; ec ; 0xf512a
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf512b
+ test AL, strict byte 002h ; a8 02 ; 0xf512d
+ je short 0513eh ; 74 0d ; 0xf512f
+ dec bx ; 4b ; 0xf5131
+ test bx, bx ; 85 db ; 0xf5132
+ jbe short 0513eh ; 76 08 ; 0xf5134
+ mov AL, strict byte 050h ; b0 50 ; 0xf5136
+ mov dx, 00080h ; ba 80 00 ; 0xf5138
+ out DX, AL ; ee ; 0xf513b
+ jmp short 05127h ; eb e9 ; 0xf513c
+ test bx, bx ; 85 db ; 0xf513e keyboard.c:301
+ jne short 05148h ; 75 06 ; 0xf5140
+ mov ax, strict word 00032h ; b8 32 00 ; 0xf5142
+ call 04f60h ; e8 18 fe ; 0xf5145
+ mov AL, strict byte 065h ; b0 65 ; 0xf5148 keyboard.c:304
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf514a
+ out DX, AL ; ee ; 0xf514d
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf514e keyboard.c:307
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5151 keyboard.c:308
+ in AL, DX ; ec ; 0xf5154
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5155
+ test AL, strict byte 002h ; a8 02 ; 0xf5157
+ je short 05168h ; 74 0d ; 0xf5159
+ dec bx ; 4b ; 0xf515b
+ test bx, bx ; 85 db ; 0xf515c
+ jbe short 05168h ; 76 08 ; 0xf515e
+ mov AL, strict byte 060h ; b0 60 ; 0xf5160
+ mov dx, 00080h ; ba 80 00 ; 0xf5162
+ out DX, AL ; ee ; 0xf5165
+ jmp short 05151h ; eb e9 ; 0xf5166
+ test bx, bx ; 85 db ; 0xf5168 keyboard.c:309
+ jne short 05172h ; 75 06 ; 0xf516a
+ mov ax, strict word 0003ch ; b8 3c 00 ; 0xf516c
+ call 04f60h ; e8 ee fd ; 0xf516f
+ mov AL, strict byte 0f4h ; b0 f4 ; 0xf5172 keyboard.c:312
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5174
+ out DX, AL ; ee ; 0xf5177
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf5178 keyboard.c:315
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf517b keyboard.c:316
+ in AL, DX ; ec ; 0xf517e
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf517f
+ test AL, strict byte 002h ; a8 02 ; 0xf5181
+ je short 05192h ; 74 0d ; 0xf5183
+ dec bx ; 4b ; 0xf5185
+ test bx, bx ; 85 db ; 0xf5186
+ jbe short 05192h ; 76 08 ; 0xf5188
+ mov AL, strict byte 070h ; b0 70 ; 0xf518a
+ mov dx, 00080h ; ba 80 00 ; 0xf518c
+ out DX, AL ; ee ; 0xf518f
+ jmp short 0517bh ; eb e9 ; 0xf5190
+ test bx, bx ; 85 db ; 0xf5192 keyboard.c:317
+ jne short 0519ch ; 75 06 ; 0xf5194
+ mov ax, strict word 00046h ; b8 46 00 ; 0xf5196
+ call 04f60h ; e8 c4 fd ; 0xf5199
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf519c keyboard.c:320
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf519f keyboard.c:321
+ in AL, DX ; ec ; 0xf51a2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf51a3
+ test AL, strict byte 001h ; a8 01 ; 0xf51a5
+ jne short 051b6h ; 75 0d ; 0xf51a7
+ dec bx ; 4b ; 0xf51a9
+ test bx, bx ; 85 db ; 0xf51aa
+ jbe short 051b6h ; 76 08 ; 0xf51ac
+ mov AL, strict byte 071h ; b0 71 ; 0xf51ae
+ mov dx, 00080h ; ba 80 00 ; 0xf51b0
+ out DX, AL ; ee ; 0xf51b3
+ jmp short 0519fh ; eb e9 ; 0xf51b4
+ test bx, bx ; 85 db ; 0xf51b6 keyboard.c:322
+ jne short 051c0h ; 75 06 ; 0xf51b8
+ mov ax, strict word 00046h ; b8 46 00 ; 0xf51ba
+ call 04f60h ; e8 a0 fd ; 0xf51bd
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf51c0 keyboard.c:325
+ in AL, DX ; ec ; 0xf51c3
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf51c4
+ cmp ax, 000fah ; 3d fa 00 ; 0xf51c6
+ je short 051d1h ; 74 06 ; 0xf51c9
+ mov ax, 003e4h ; b8 e4 03 ; 0xf51cb keyboard.c:326
+ call 04f60h ; e8 8f fd ; 0xf51ce
+ mov AL, strict byte 0a8h ; b0 a8 ; 0xf51d1 keyboard.c:330
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf51d3
+ out DX, AL ; ee ; 0xf51d6
+ xor ax, ax ; 31 c0 ; 0xf51d7 keyboard.c:335
+ call 0666fh ; e8 93 14 ; 0xf51d9
+ mov sp, bp ; 89 ec ; 0xf51dc keyboard.c:336
+ pop bp ; 5d ; 0xf51de
+ retn ; c3 ; 0xf51df
+ ; disGetNextSymbol 0xf51e0 LB 0x4d68 -> off=0x0 cb=0000000000000045 uValue=00000000000f3be0 'enqueue_key'
+enqueue_key: ; 0xf51e0 LB 0x45
+ push bx ; 53 ; 0xf51e0 keyboard.c:339
+ push cx ; 51 ; 0xf51e1
+ push bp ; 55 ; 0xf51e2
+ mov bp, sp ; 89 e5 ; 0xf51e3
+ mov dh, al ; 88 c6 ; 0xf51e5
+ mov bx, strict word 0001ah ; bb 1a 00 ; 0xf51e7 keyboard.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf51ea
+ mov es, ax ; 8e c0 ; 0xf51ed
+ mov cx, word [es:bx] ; 26 8b 0f ; 0xf51ef
+ mov bx, strict word 0001ch ; bb 1c 00 ; 0xf51f2 keyboard.c:48
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf51f5
+ mov bx, ax ; 89 c3 ; 0xf51f8 keyboard.c:354
+ inc ax ; 40 ; 0xf51fa keyboard.c:355
+ inc ax ; 40 ; 0xf51fb
+ cmp ax, strict word 0003eh ; 3d 3e 00 ; 0xf51fc keyboard.c:356
+ jc short 05204h ; 72 03 ; 0xf51ff
+ mov ax, strict word 0001eh ; b8 1e 00 ; 0xf5201 keyboard.c:357
+ cmp ax, cx ; 39 c8 ; 0xf5204 keyboard.c:359
+ jne short 0520ch ; 75 04 ; 0xf5206
+ xor ax, cx ; 31 c8 ; 0xf5208 keyboard.c:360
+ jmp short 05221h ; eb 15 ; 0xf520a
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf520c keyboard.c:43
+ mov es, cx ; 8e c1 ; 0xf520f
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5211
+ inc bx ; 43 ; 0xf5214 keyboard.c:363
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf5215 keyboard.c:43
+ mov bx, strict word 0001ch ; bb 1c 00 ; 0xf5218 keyboard.c:53
+ mov word [es:bx], ax ; 26 89 07 ; 0xf521b
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf521e keyboard.c:365
+ pop bp ; 5d ; 0xf5221 keyboard.c:366
+ pop cx ; 59 ; 0xf5222
+ pop bx ; 5b ; 0xf5223
+ retn ; c3 ; 0xf5224
+ ; disGetNextSymbol 0xf5225 LB 0x4d23 -> off=0x35 cb=000000000000040a uValue=00000000000f3c5a 'int09_function'
+ db 0d4h, 0c6h, 0c5h, 0bah, 0b8h, 0b6h, 0aah, 09dh, 054h, 053h, 046h, 045h, 03ah, 038h, 036h, 02ah
+ db 01dh, 0e9h, 054h, 015h, 053h, 0e3h, 052h, 0e3h, 052h, 07ah, 053h, 0beh, 052h, 0f4h, 053h, 04fh
+ db 054h, 0ceh, 054h, 0b3h, 054h, 049h, 053h, 0e3h, 052h, 0e3h, 052h, 0cdh, 053h, 0d5h, 052h, 037h
+ db 054h, 09eh, 054h, 0c9h, 054h
+int09_function: ; 0xf525a LB 0x40a
+ push bp ; 55 ; 0xf525a keyboard.c:371
+ mov bp, sp ; 89 e5 ; 0xf525b
+ push si ; 56 ; 0xf525d
+ push di ; 57 ; 0xf525e
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf525f
+ mov al, byte [bp+014h] ; 8a 46 14 ; 0xf5262 keyboard.c:382
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf5265
+ test al, al ; 84 c0 ; 0xf5268 keyboard.c:384
+ jne short 05288h ; 75 1c ; 0xf526a
+ mov bx, 00da0h ; bb a0 0d ; 0xf526c keyboard.c:385
+ mov cx, ds ; 8c d9 ; 0xf526f
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5271
+ call 018cch ; e8 55 c6 ; 0xf5274
+ mov ax, 00587h ; b8 87 05 ; 0xf5277
+ push ax ; 50 ; 0xf527a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf527b
+ push ax ; 50 ; 0xf527e
+ call 0190fh ; e8 8d c6 ; 0xf527f
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf5282
+ jmp near 053c6h ; e9 3e 01 ; 0xf5285 keyboard.c:386
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5288 keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf528b
+ mov es, ax ; 8e c0 ; 0xf528e
+ mov ah, byte [es:bx] ; 26 8a 27 ; 0xf5290
+ mov dl, ah ; 88 e2 ; 0xf5293 keyboard.c:39
+ mov bx, 00096h ; bb 96 00 ; 0xf5295 keyboard.c:38
+ mov dh, byte [es:bx] ; 26 8a 37 ; 0xf5298
+ mov byte [bp-008h], dh ; 88 76 f8 ; 0xf529b keyboard.c:39
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf529e keyboard.c:38
+ mov bh, byte [es:bx] ; 26 8a 3f ; 0xf52a1
+ mov bl, bh ; 88 fb ; 0xf52a4 keyboard.c:39
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf52a6 keyboard.c:394
+ push CS ; 0e ; 0xf52a9
+ pop ES ; 07 ; 0xf52aa
+ mov cx, strict word 00012h ; b9 12 00 ; 0xf52ab
+ mov di, 05225h ; bf 25 52 ; 0xf52ae
+ repne scasb ; f2 ae ; 0xf52b1
+ sal cx, 1 ; d1 e1 ; 0xf52b3
+ mov di, cx ; 89 cf ; 0xf52b5
+ mov cx, word [cs:di+05236h] ; 2e 8b 8d 36 52 ; 0xf52b7
+ jmp cx ; ff e1 ; 0xf52bc
+ xor bl, 040h ; 80 f3 40 ; 0xf52be keyboard.c:396
+ mov si, strict word 00017h ; be 17 00 ; 0xf52c1 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf52c4
+ mov es, ax ; 8e c0 ; 0xf52c7
+ mov byte [es:si], bl ; 26 88 1c ; 0xf52c9
+ or dl, 040h ; 80 ca 40 ; 0xf52cc keyboard.c:398
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf52cf keyboard.c:43
+ jmp near 054c3h ; e9 ee 01 ; 0xf52d2
+ and dl, 0bfh ; 80 e2 bf ; 0xf52d5 keyboard.c:402
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf52d8 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf52db
+ mov es, ax ; 8e c0 ; 0xf52de
+ jmp near 054c3h ; e9 e0 01 ; 0xf52e0
+ test byte [bp-008h], 002h ; f6 46 f8 02 ; 0xf52e3 keyboard.c:411
+ jne short 05347h ; 75 5e ; 0xf52e7
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf52e9 keyboard.c:412
+ and AL, strict byte 07fh ; 24 7f ; 0xf52ec
+ cmp AL, strict byte 02ah ; 3c 2a ; 0xf52ee
+ jne short 052f7h ; 75 05 ; 0xf52f0
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf52f2
+ jmp short 052fah ; eb 03 ; 0xf52f5
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf52f7
+ test byte [bp-006h], 080h ; f6 46 fa 80 ; 0xf52fa keyboard.c:413
+ je short 05306h ; 74 06 ; 0xf52fe
+ not al ; f6 d0 ; 0xf5300 keyboard.c:414
+ and bl, al ; 20 c3 ; 0xf5302
+ jmp short 05308h ; eb 02 ; 0xf5304 keyboard.c:415
+ or bl, al ; 08 c3 ; 0xf5306 keyboard.c:416
+ mov si, strict word 00017h ; be 17 00 ; 0xf5308 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf530b
+ mov es, ax ; 8e c0 ; 0xf530e
+ mov byte [es:si], bl ; 26 88 1c ; 0xf5310
+ jmp short 05347h ; eb 32 ; 0xf5313 keyboard.c:419
+ test dh, 001h ; f6 c6 01 ; 0xf5315 keyboard.c:422
+ jne short 05378h ; 75 5e ; 0xf5318
+ or bl, 004h ; 80 cb 04 ; 0xf531a keyboard.c:423
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf531d keyboard.c:41
+ mov ax, strict word 00017h ; b8 17 00 ; 0xf5320
+ mov dh, bl ; 88 de ; 0xf5323
+ mov bx, ax ; 89 c3 ; 0xf5325 keyboard.c:43
+ mov es, cx ; 8e c1 ; 0xf5327
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf5329
+ test byte [bp-008h], 002h ; f6 46 f8 02 ; 0xf532c keyboard.c:425
+ je short 0533eh ; 74 0c ; 0xf5330
+ or byte [bp-008h], 004h ; 80 4e f8 04 ; 0xf5332 keyboard.c:426
+ mov bx, 00096h ; bb 96 00 ; 0xf5336 keyboard.c:41
+ mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xf5339
+ jmp short 05344h ; eb 06 ; 0xf533c keyboard.c:428
+ or dl, 001h ; 80 ca 01 ; 0xf533e keyboard.c:429
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5341 keyboard.c:41
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5344 keyboard.c:43
+ jmp short 05378h ; eb 2f ; 0xf5347 keyboard.c:433
+ test dh, 001h ; f6 c6 01 ; 0xf5349 keyboard.c:435
+ jne short 053a7h ; 75 59 ; 0xf534c
+ and bl, 0fbh ; 80 e3 fb ; 0xf534e keyboard.c:436
+ mov si, strict word 00017h ; be 17 00 ; 0xf5351 keyboard.c:43
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf5354
+ mov es, cx ; 8e c1 ; 0xf5357
+ mov byte [es:si], bl ; 26 88 1c ; 0xf5359
+ test dh, 002h ; f6 c6 02 ; 0xf535c keyboard.c:438
+ je short 0536fh ; 74 0e ; 0xf535f
+ and dh, 0fbh ; 80 e6 fb ; 0xf5361 keyboard.c:439
+ mov byte [bp-008h], dh ; 88 76 f8 ; 0xf5364
+ mov bx, 00096h ; bb 96 00 ; 0xf5367 keyboard.c:43
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf536a
+ jmp short 053a7h ; eb 38 ; 0xf536d keyboard.c:441
+ and dl, 0feh ; 80 e2 fe ; 0xf536f keyboard.c:442
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5372 keyboard.c:43
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5375
+ jmp short 053a7h ; eb 2d ; 0xf5378 keyboard.c:446
+ or bl, 008h ; 80 cb 08 ; 0xf537a keyboard.c:449
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf537d keyboard.c:41
+ mov cx, strict word 00017h ; b9 17 00 ; 0xf5380
+ mov dh, bl ; 88 de ; 0xf5383
+ mov bx, cx ; 89 cb ; 0xf5385 keyboard.c:43
+ mov es, ax ; 8e c0 ; 0xf5387
+ mov byte [es:bx], dh ; 26 88 37 ; 0xf5389
+ test byte [bp-008h], 002h ; f6 46 f8 02 ; 0xf538c keyboard.c:451
+ je short 0539eh ; 74 0c ; 0xf5390
+ or byte [bp-008h], 008h ; 80 4e f8 08 ; 0xf5392 keyboard.c:452
+ mov bx, 00096h ; bb 96 00 ; 0xf5396 keyboard.c:41
+ mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xf5399
+ jmp short 053a4h ; eb 06 ; 0xf539c keyboard.c:454
+ or dl, 002h ; 80 ca 02 ; 0xf539e keyboard.c:455
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf53a1 keyboard.c:41
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf53a4 keyboard.c:43
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf53a7 keyboard.c:458
+ and AL, strict byte 07fh ; 24 7f ; 0xf53aa
+ cmp AL, strict byte 01dh ; 3c 1d ; 0xf53ac
+ je short 053b4h ; 74 04 ; 0xf53ae
+ and byte [bp-008h], 0feh ; 80 66 f8 fe ; 0xf53b0
+ and byte [bp-008h], 0fdh ; 80 66 f8 fd ; 0xf53b4
+ mov bx, 00096h ; bb 96 00 ; 0xf53b8
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf53bb
+ mov es, ax ; 8e c0 ; 0xf53be
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf53c0
+ mov byte [es:bx], al ; 26 88 07 ; 0xf53c3
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf53c6
+ pop di ; 5f ; 0xf53c9
+ pop si ; 5e ; 0xf53ca
+ pop bp ; 5d ; 0xf53cb
+ retn ; c3 ; 0xf53cc
+ and bl, 0f7h ; 80 e3 f7 ; 0xf53cd keyboard.c:460
+ mov si, strict word 00017h ; be 17 00 ; 0xf53d0 keyboard.c:43
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf53d3
+ mov es, cx ; 8e c1 ; 0xf53d6
+ mov byte [es:si], bl ; 26 88 1c ; 0xf53d8
+ test dh, 002h ; f6 c6 02 ; 0xf53db keyboard.c:462
+ je short 053e9h ; 74 09 ; 0xf53de
+ and dh, 0f7h ; 80 e6 f7 ; 0xf53e0 keyboard.c:463
+ mov byte [bp-008h], dh ; 88 76 f8 ; 0xf53e3
+ jmp near 05367h ; e9 7e ff ; 0xf53e6 keyboard.c:464
+ and dl, 0fdh ; 80 e2 fd ; 0xf53e9 keyboard.c:466
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf53ec keyboard.c:43
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf53ef
+ jmp short 053a7h ; eb b3 ; 0xf53f2 keyboard.c:469
+ test dh, 003h ; f6 c6 03 ; 0xf53f4 keyboard.c:472
+ jne short 0540dh ; 75 14 ; 0xf53f7
+ or dl, 020h ; 80 ca 20 ; 0xf53f9 keyboard.c:474
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf53fc keyboard.c:41
+ mov si, strict word 00018h ; be 18 00 ; 0xf53ff
+ mov es, ax ; 8e c0 ; 0xf5402 keyboard.c:43
+ mov byte [es:si], dl ; 26 88 14 ; 0xf5404
+ xor bl, 020h ; 80 f3 20 ; 0xf5407 keyboard.c:476
+ jmp near 05492h ; e9 85 00 ; 0xf540a keyboard.c:477
+ or dl, 008h ; 80 ca 08 ; 0xf540d keyboard.c:480
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5410 keyboard.c:41
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5413
+ mov es, ax ; 8e c0 ; 0xf5416 keyboard.c:43
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5418
+ mov ax, 000aeh ; b8 ae 00 ; 0xf541b keyboard.c:484
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf541e
+ out DX, AL ; ee ; 0xf5421
+ call 0e034h ; e8 0f 8c ; 0xf5422 keyboard.c:485
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5425 keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5428
+ mov es, ax ; 8e c0 ; 0xf542b
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf542d
+ test AL, strict byte 008h ; a8 08 ; 0xf5430 keyboard.c:39
+ jne short 05425h ; 75 f1 ; 0xf5432
+ jmp near 053a7h ; e9 70 ff ; 0xf5434 keyboard.c:492
+ test dh, 003h ; f6 c6 03 ; 0xf5437 keyboard.c:494
+ je short 0543fh ; 74 03 ; 0xf543a
+ jmp near 053a7h ; e9 68 ff ; 0xf543c
+ and dl, 0dfh ; 80 e2 df ; 0xf543f keyboard.c:495
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf5442 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5445
+ mov es, ax ; 8e c0 ; 0xf5448
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf544a
+ jmp short 0543ch ; eb ed ; 0xf544d keyboard.c:498
+ test dh, 002h ; f6 c6 02 ; 0xf544f keyboard.c:501
+ je short 05481h ; 74 2d ; 0xf5452
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5454 keyboard.c:46
+ mov bx, strict word 0001ah ; bb 1a 00 ; 0xf5457
+ mov es, ax ; 8e c0 ; 0xf545a keyboard.c:48
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf545c
+ mov bx, strict word 0001ch ; bb 1c 00 ; 0xf545f keyboard.c:51
+ mov word [es:bx], ax ; 26 89 07 ; 0xf5462 keyboard.c:53
+ mov bx, strict word 00071h ; bb 71 00 ; 0xf5465 keyboard.c:41
+ mov AL, strict byte 080h ; b0 80 ; 0xf5468
+ mov byte [es:bx], al ; 26 88 07 ; 0xf546a keyboard.c:43
+ mov ax, 000aeh ; b8 ae 00 ; 0xf546d keyboard.c:506
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5470
+ out DX, AL ; ee ; 0xf5473
+ push bp ; 55 ; 0xf5474 keyboard.c:507
+ int 01bh ; cd 1b ; 0xf5475
+ pop bp ; 5d ; 0xf5477
+ xor dx, dx ; 31 d2 ; 0xf5478 keyboard.c:508
+ xor ax, ax ; 31 c0 ; 0xf547a
+ call 051e0h ; e8 61 fd ; 0xf547c
+ jmp short 0543ch ; eb bb ; 0xf547f keyboard.c:509
+ or dl, 010h ; 80 ca 10 ; 0xf5481 keyboard.c:510
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5484 keyboard.c:41
+ mov es, ax ; 8e c0 ; 0xf5487
+ mov si, strict word 00018h ; be 18 00 ; 0xf5489
+ mov byte [es:si], dl ; 26 88 14 ; 0xf548c keyboard.c:43
+ xor bl, 010h ; 80 f3 10 ; 0xf548f keyboard.c:512
+ mov ax, strict word 00017h ; b8 17 00 ; 0xf5492 keyboard.c:41
+ mov dl, bl ; 88 da ; 0xf5495
+ mov bx, ax ; 89 c3 ; 0xf5497 keyboard.c:43
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf5499
+ jmp short 0543ch ; eb 9e ; 0xf549c keyboard.c:515
+ test dh, 002h ; f6 c6 02 ; 0xf549e keyboard.c:518
+ jne short 0543ch ; 75 99 ; 0xf54a1
+ and dl, 0efh ; 80 e2 ef ; 0xf54a3 keyboard.c:519
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf54a6 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf54a9
+ mov es, ax ; 8e c0 ; 0xf54ac
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf54ae
+ jmp short 0543ch ; eb 89 ; 0xf54b1 keyboard.c:522
+ test ah, 004h ; f6 c4 04 ; 0xf54b3 keyboard.c:525
+ jne short 0543ch ; 75 84 ; 0xf54b6
+ or dl, 004h ; 80 ca 04 ; 0xf54b8 keyboard.c:526
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf54bb keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf54be
+ mov es, ax ; 8e c0 ; 0xf54c1
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf54c3
+ jmp near 053a7h ; e9 de fe ; 0xf54c6 keyboard.c:530
+ and dl, 0fbh ; 80 e2 fb ; 0xf54c9 keyboard.c:533
+ jmp short 054bbh ; eb ed ; 0xf54cc keyboard.c:534
+ mov al, bh ; 88 f8 ; 0xf54ce keyboard.c:539
+ and AL, strict byte 00ch ; 24 0c ; 0xf54d0
+ cmp AL, strict byte 00ch ; 3c 0c ; 0xf54d2
+ jne short 054e9h ; 75 13 ; 0xf54d4
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf54d6 keyboard.c:51
+ mov si, strict word 00072h ; be 72 00 ; 0xf54d9
+ mov cx, 01234h ; b9 34 12 ; 0xf54dc
+ mov es, ax ; 8e c0 ; 0xf54df keyboard.c:53
+ mov word [es:si], cx ; 26 89 0c ; 0xf54e1
+ jmp far 0f000h:0e05bh ; ea 5b e0 00 f0 ; 0xf54e4 keyboard.c:542
+ test dl, 008h ; f6 c2 08 ; 0xf54e9 keyboard.c:548
+ je short 054ffh ; 74 11 ; 0xf54ec
+ and dl, 0f7h ; 80 e2 f7 ; 0xf54ee keyboard.c:550
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf54f1 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf54f4
+ mov es, ax ; 8e c0 ; 0xf54f7
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf54f9
+ jmp near 053c6h ; e9 c7 fe ; 0xf54fc keyboard.c:552
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf54ff keyboard.c:555
+ test AL, strict byte 080h ; a8 80 ; 0xf5502
+ je short 05534h ; 74 2e ; 0xf5504
+ cmp AL, strict byte 0fah ; 3c fa ; 0xf5506 keyboard.c:557
+ jne short 0551ah ; 75 10 ; 0xf5508
+ mov bx, 00097h ; bb 97 00 ; 0xf550a keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf550d
+ mov es, ax ; 8e c0 ; 0xf5510
+ mov ah, byte [es:bx] ; 26 8a 27 ; 0xf5512
+ or ah, 010h ; 80 cc 10 ; 0xf5515 keyboard.c:39
+ jmp short 0552fh ; eb 15 ; 0xf5518 keyboard.c:560
+ cmp AL, strict byte 0feh ; 3c fe ; 0xf551a
+ je short 05521h ; 74 03 ; 0xf551c
+ jmp near 053a7h ; e9 86 fe ; 0xf551e
+ mov bx, 00097h ; bb 97 00 ; 0xf5521 keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5524
+ mov es, ax ; 8e c0 ; 0xf5527
+ mov ah, byte [es:bx] ; 26 8a 27 ; 0xf5529
+ or ah, 020h ; 80 cc 20 ; 0xf552c keyboard.c:39
+ mov byte [es:bx], ah ; 26 88 27 ; 0xf552f keyboard.c:43
+ jmp short 0551eh ; eb ea ; 0xf5532 keyboard.c:564
+ cmp byte [bp-006h], 058h ; 80 7e fa 58 ; 0xf5534 keyboard.c:566
+ jbe short 0555ch ; 76 22 ; 0xf5538
+ mov bx, 00da0h ; bb a0 0d ; 0xf553a keyboard.c:567
+ mov cx, ds ; 8c d9 ; 0xf553d
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf553f
+ call 018cch ; e8 87 c3 ; 0xf5542
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf5545
+ xor ah, ah ; 30 e4 ; 0xf5548
+ push ax ; 50 ; 0xf554a
+ mov ax, 005a1h ; b8 a1 05 ; 0xf554b
+ push ax ; 50 ; 0xf554e
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf554f
+ push ax ; 50 ; 0xf5552
+ call 0190fh ; e8 b9 c3 ; 0xf5553
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf5556
+ jmp near 053c6h ; e9 6a fe ; 0xf5559 keyboard.c:568
+ test bl, 008h ; f6 c3 08 ; 0xf555c keyboard.c:570
+ je short 0557bh ; 74 1a ; 0xf555f
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf5561 keyboard.c:571
+ xor ah, ah ; 30 e4 ; 0xf5564
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf5566
+ imul dx ; f7 ea ; 0xf5569
+ mov si, ax ; 89 c6 ; 0xf556b
+ mov al, byte [si+00df4h] ; 8a 84 f4 0d ; 0xf556d
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf5571
+ mov al, byte [si+00df5h] ; 8a 84 f5 0d ; 0xf5574 keyboard.c:572
+ jmp near 0562fh ; e9 b4 00 ; 0xf5578 keyboard.c:573
+ test bl, 004h ; f6 c3 04 ; 0xf557b
+ je short 0559ah ; 74 1a ; 0xf557e
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf5580 keyboard.c:574
+ xor ah, ah ; 30 e4 ; 0xf5583
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf5585
+ imul dx ; f7 ea ; 0xf5588
+ mov si, ax ; 89 c6 ; 0xf558a
+ mov al, byte [si+00df2h] ; 8a 84 f2 0d ; 0xf558c
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf5590
+ mov al, byte [si+00df3h] ; 8a 84 f3 0d ; 0xf5593 keyboard.c:575
+ jmp near 0562fh ; e9 95 00 ; 0xf5597 keyboard.c:576
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf559a
+ and AL, strict byte 002h ; 24 02 ; 0xf559d
+ test al, al ; 84 c0 ; 0xf559f
+ jbe short 055c1h ; 76 1e ; 0xf55a1
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf55a3
+ cmp AL, strict byte 047h ; 3c 47 ; 0xf55a6
+ jc short 055c1h ; 72 17 ; 0xf55a8
+ cmp AL, strict byte 053h ; 3c 53 ; 0xf55aa
+ jnbe short 055c1h ; 77 13 ; 0xf55ac
+ mov byte [bp-00ah], 0e0h ; c6 46 f6 e0 ; 0xf55ae keyboard.c:578
+ xor ah, ah ; 30 e4 ; 0xf55b2 keyboard.c:579
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf55b4
+ imul dx ; f7 ea ; 0xf55b7
+ mov bx, ax ; 89 c3 ; 0xf55b9
+ mov al, byte [bx+00defh] ; 8a 87 ef 0d ; 0xf55bb
+ jmp short 0562fh ; eb 6e ; 0xf55bf keyboard.c:580
+ test bl, 003h ; f6 c3 03 ; 0xf55c1
+ je short 055fdh ; 74 37 ; 0xf55c4
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf55c6 keyboard.c:584
+ xor ah, ah ; 30 e4 ; 0xf55c9
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf55cb
+ imul dx ; f7 ea ; 0xf55ce
+ mov si, ax ; 89 c6 ; 0xf55d0
+ mov al, byte [si+00df6h] ; 8a 84 f6 0d ; 0xf55d2
+ xor ah, ah ; 30 e4 ; 0xf55d6
+ mov dl, bl ; 88 da ; 0xf55d8
+ xor dh, dh ; 30 f6 ; 0xf55da
+ test dx, ax ; 85 c2 ; 0xf55dc
+ je short 055edh ; 74 0d ; 0xf55de
+ mov al, byte [si+00deeh] ; 8a 84 ee 0d ; 0xf55e0 keyboard.c:585
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf55e4
+ mov al, byte [si+00defh] ; 8a 84 ef 0d ; 0xf55e7 keyboard.c:586
+ jmp short 055f8h ; eb 0b ; 0xf55eb keyboard.c:587
+ mov al, byte [si+00df0h] ; 8a 84 f0 0d ; 0xf55ed keyboard.c:588
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf55f1
+ mov al, byte [si+00df1h] ; 8a 84 f1 0d ; 0xf55f4 keyboard.c:589
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf55f8
+ jmp short 05632h ; eb 35 ; 0xf55fb keyboard.c:591
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf55fd keyboard.c:593
+ xor ah, ah ; 30 e4 ; 0xf5600
+ mov dx, strict word 0000ah ; ba 0a 00 ; 0xf5602
+ imul dx ; f7 ea ; 0xf5605
+ mov si, ax ; 89 c6 ; 0xf5607
+ mov dl, byte [si+00df6h] ; 8a 94 f6 0d ; 0xf5609
+ xor dh, dh ; 30 f6 ; 0xf560d
+ mov al, bl ; 88 d8 ; 0xf560f
+ xor ah, ah ; 30 e4 ; 0xf5611
+ test ax, dx ; 85 d0 ; 0xf5613
+ je short 05624h ; 74 0d ; 0xf5615
+ mov al, byte [si+00df0h] ; 8a 84 f0 0d ; 0xf5617 keyboard.c:594
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf561b
+ mov al, byte [si+00df1h] ; 8a 84 f1 0d ; 0xf561e keyboard.c:595
+ jmp short 0562fh ; eb 0b ; 0xf5622 keyboard.c:596
+ mov al, byte [si+00deeh] ; 8a 84 ee 0d ; 0xf5624 keyboard.c:597
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf5628
+ mov al, byte [si+00defh] ; 8a 84 ef 0d ; 0xf562b keyboard.c:598
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf562f
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf5632 keyboard.c:601
+ jne short 05657h ; 75 1f ; 0xf5636
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf5638
+ jne short 05657h ; 75 19 ; 0xf563c
+ mov bx, 00da0h ; bb a0 0d ; 0xf563e keyboard.c:602
+ mov cx, ds ; 8c d9 ; 0xf5641
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5643
+ call 018cch ; e8 83 c2 ; 0xf5646
+ mov ax, 005d8h ; b8 d8 05 ; 0xf5649
+ push ax ; 50 ; 0xf564c
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf564d
+ push ax ; 50 ; 0xf5650
+ call 0190fh ; e8 bb c2 ; 0xf5651
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf5654
+ mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xf5657 keyboard.c:604
+ xor dh, dh ; 30 f6 ; 0xf565a
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf565c
+ xor ah, ah ; 30 e4 ; 0xf565f
+ jmp near 0547ch ; e9 18 fe ; 0xf5661
+ ; disGetNextSymbol 0xf5664 LB 0x48e4 -> off=0x0 cb=0000000000000061 uValue=00000000000f4064 'dequeue_key'
+dequeue_key: ; 0xf5664 LB 0x61
+ push si ; 56 ; 0xf5664 keyboard.c:614
+ push di ; 57 ; 0xf5665
+ push bp ; 55 ; 0xf5666
+ mov bp, sp ; 89 e5 ; 0xf5667
+ push ax ; 50 ; 0xf5669
+ mov si, ax ; 89 c6 ; 0xf566a
+ mov word [bp-002h], bx ; 89 5e fe ; 0xf566c
+ mov bx, strict word 0001ah ; bb 1a 00 ; 0xf566f keyboard.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5672
+ mov es, ax ; 8e c0 ; 0xf5675
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf5677
+ mov di, strict word 0001ch ; bf 1c 00 ; 0xf567a keyboard.c:48
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf567d
+ cmp bx, ax ; 39 c3 ; 0xf5680 keyboard.c:630
+ je short 056bbh ; 74 37 ; 0xf5682
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf5684 keyboard.c:38
+ lea di, [bx+001h] ; 8d 7f 01 ; 0xf5687 keyboard.c:632
+ mov ah, byte [es:di] ; 26 8a 25 ; 0xf568a keyboard.c:38
+ mov es, cx ; 8e c1 ; 0xf568d keyboard.c:633
+ mov di, word [bp-002h] ; 8b 7e fe ; 0xf568f
+ mov byte [es:di], al ; 26 88 05 ; 0xf5692
+ mov es, dx ; 8e c2 ; 0xf5695 keyboard.c:634
+ mov byte [es:si], ah ; 26 88 24 ; 0xf5697
+ cmp word [bp+008h], strict byte 00000h ; 83 7e 08 00 ; 0xf569a keyboard.c:637
+ je short 056b6h ; 74 16 ; 0xf569e
+ lea si, [bx+002h] ; 8d 77 02 ; 0xf56a0 keyboard.c:638
+ cmp si, strict byte 0003eh ; 83 fe 3e ; 0xf56a3 keyboard.c:639
+ jc short 056abh ; 72 03 ; 0xf56a6
+ mov si, strict word 0001eh ; be 1e 00 ; 0xf56a8 keyboard.c:640
+ mov bx, strict word 0001ah ; bb 1a 00 ; 0xf56ab keyboard.c:53
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf56ae
+ mov es, ax ; 8e c0 ; 0xf56b1
+ mov word [es:bx], si ; 26 89 37 ; 0xf56b3
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf56b6 keyboard.c:643
+ jmp short 056bdh ; eb 02 ; 0xf56b9
+ xor ax, ax ; 31 c0 ; 0xf56bb keyboard.c:646
+ mov sp, bp ; 89 ec ; 0xf56bd keyboard.c:648
+ pop bp ; 5d ; 0xf56bf
+ pop di ; 5f ; 0xf56c0
+ pop si ; 5e ; 0xf56c1
+ retn 00002h ; c2 02 00 ; 0xf56c2
+ ; disGetNextSymbol 0xf56c5 LB 0x4883 -> off=0x23 cb=00000000000002f4 uValue=00000000000f40e8 'int16_function'
+ db 0a2h, 092h, 012h, 011h, 010h, 00ah, 009h, 005h, 002h, 001h, 000h, 0eah, 057h, 0a5h, 057h, 03bh
+ db 058h, 080h, 058h, 095h, 058h, 0bch, 058h, 0c6h, 058h, 035h, 059h, 071h, 059h, 0a2h, 059h, 0d1h
+ db 059h, 034h, 058h
+int16_function: ; 0xf56e8 LB 0x2f4
+ push bp ; 55 ; 0xf56e8 keyboard.c:665
+ mov bp, sp ; 89 e5 ; 0xf56e9
+ push si ; 56 ; 0xf56eb
+ push di ; 57 ; 0xf56ec
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf56ed
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf56f0 keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf56f3
+ mov es, ax ; 8e c0 ; 0xf56f6
+ mov dl, byte [es:bx] ; 26 8a 17 ; 0xf56f8
+ mov bh, dl ; 88 d7 ; 0xf56fb keyboard.c:39
+ mov si, 00097h ; be 97 00 ; 0xf56fd keyboard.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf5700
+ mov bl, al ; 88 c3 ; 0xf5703 keyboard.c:39
+ xor dh, dh ; 30 f6 ; 0xf5705 keyboard.c:674
+ mov CL, strict byte 004h ; b1 04 ; 0xf5707
+ sar dx, CL ; d3 fa ; 0xf5709
+ and dl, 007h ; 80 e2 07 ; 0xf570b
+ and AL, strict byte 007h ; 24 07 ; 0xf570e
+ xor ah, ah ; 30 e4 ; 0xf5710
+ xor al, dl ; 30 d0 ; 0xf5712
+ test ax, ax ; 85 c0 ; 0xf5714
+ je short 05784h ; 74 6c ; 0xf5716
+ cli ; fa ; 0xf5718 keyboard.c:675
+ mov AL, strict byte 0edh ; b0 ed ; 0xf5719 keyboard.c:676
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf571b
+ out DX, AL ; ee ; 0xf571e
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf571f keyboard.c:677
+ in AL, DX ; ec ; 0xf5722
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5723
+ test AL, strict byte 001h ; a8 01 ; 0xf5725
+ jne short 05731h ; 75 08 ; 0xf5727
+ mov AL, strict byte 021h ; b0 21 ; 0xf5729
+ mov dx, 00080h ; ba 80 00 ; 0xf572b
+ out DX, AL ; ee ; 0xf572e
+ jmp short 0571fh ; eb ee ; 0xf572f
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5731 keyboard.c:678
+ in AL, DX ; ec ; 0xf5734
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5735
+ cmp ax, 000fah ; 3d fa 00 ; 0xf5737
+ jne short 05783h ; 75 47 ; 0xf573a
+ and bl, 0c8h ; 80 e3 c8 ; 0xf573c keyboard.c:679
+ mov al, bh ; 88 f8 ; 0xf573f keyboard.c:680
+ xor ah, ah ; 30 e4 ; 0xf5741
+ mov CL, strict byte 004h ; b1 04 ; 0xf5743
+ sar ax, CL ; d3 f8 ; 0xf5745
+ mov cx, ax ; 89 c1 ; 0xf5747
+ xor ch, ah ; 30 e5 ; 0xf5749
+ and cl, 007h ; 80 e1 07 ; 0xf574b
+ mov al, bl ; 88 d8 ; 0xf574e
+ xor ah, ah ; 30 e4 ; 0xf5750
+ mov dx, ax ; 89 c2 ; 0xf5752
+ or dx, cx ; 09 ca ; 0xf5754
+ mov bl, dl ; 88 d3 ; 0xf5756
+ mov al, dl ; 88 d0 ; 0xf5758 keyboard.c:681
+ and AL, strict byte 007h ; 24 07 ; 0xf575a
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf575c
+ out DX, AL ; ee ; 0xf575f
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf5760 keyboard.c:682
+ in AL, DX ; ec ; 0xf5763
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5764
+ test AL, strict byte 001h ; a8 01 ; 0xf5766
+ jne short 05772h ; 75 08 ; 0xf5768
+ mov AL, strict byte 021h ; b0 21 ; 0xf576a keyboard.c:683
+ mov dx, 00080h ; ba 80 00 ; 0xf576c
+ out DX, AL ; ee ; 0xf576f
+ jmp short 05760h ; eb ee ; 0xf5770
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf5772 keyboard.c:684
+ in AL, DX ; ec ; 0xf5775
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5776
+ mov si, 00097h ; be 97 00 ; 0xf5778 keyboard.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf577b
+ mov es, ax ; 8e c0 ; 0xf577e
+ mov byte [es:si], bl ; 26 88 1c ; 0xf5780
+ sti ; fb ; 0xf5783 keyboard.c:687
+ mov CL, strict byte 008h ; b1 08 ; 0xf5784 keyboard.c:690
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf5786
+ shr ax, CL ; d3 e8 ; 0xf5789
+ cmp ax, 000a2h ; 3d a2 00 ; 0xf578b
+ jnbe short 057eah ; 77 5a ; 0xf578e
+ push CS ; 0e ; 0xf5790
+ pop ES ; 07 ; 0xf5791
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf5792
+ mov di, 056c5h ; bf c5 56 ; 0xf5795
+ repne scasb ; f2 ae ; 0xf5798
+ sal cx, 1 ; d1 e1 ; 0xf579a
+ mov di, cx ; 89 cf ; 0xf579c
+ mov ax, word [cs:di+056d0h] ; 2e 8b 85 d0 56 ; 0xf579e
+ jmp ax ; ff e0 ; 0xf57a3
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf57a5 keyboard.c:692
+ push ax ; 50 ; 0xf57a8
+ mov cx, ss ; 8c d1 ; 0xf57a9
+ lea bx, [bp-008h] ; 8d 5e f8 ; 0xf57ab
+ mov dx, ss ; 8c d2 ; 0xf57ae
+ lea ax, [bp-00ah] ; 8d 46 f6 ; 0xf57b0
+ call 05664h ; e8 ae fe ; 0xf57b3
+ test ax, ax ; 85 c0 ; 0xf57b6
+ jne short 057c8h ; 75 0e ; 0xf57b8
+ mov ax, 0060fh ; b8 0f 06 ; 0xf57ba keyboard.c:693
+ push ax ; 50 ; 0xf57bd
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf57be
+ push ax ; 50 ; 0xf57c1
+ call 0190fh ; e8 4a c1 ; 0xf57c2
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf57c5
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf57c8 keyboard.c:695
+ je short 057d4h ; 74 06 ; 0xf57cc
+ cmp byte [bp-008h], 0f0h ; 80 7e f8 f0 ; 0xf57ce
+ je short 057dah ; 74 06 ; 0xf57d2
+ cmp byte [bp-008h], 0e0h ; 80 7e f8 e0 ; 0xf57d4 keyboard.c:697
+ jne short 057deh ; 75 04 ; 0xf57d8
+ mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xf57da keyboard.c:698
+ mov ah, byte [bp-00ah] ; 8a 66 f6 ; 0xf57de keyboard.c:699
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf57e1
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf57e4
+ jmp near 05834h ; e9 4a 00 ; 0xf57e7 keyboard.c:700
+ mov bx, 00da0h ; bb a0 0d ; 0xf57ea
+ mov cx, ds ; 8c d9 ; 0xf57ed
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf57ef
+ call 018cch ; e8 d7 c0 ; 0xf57f2
+ mov CL, strict byte 008h ; b1 08 ; 0xf57f5
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf57f7
+ shr ax, CL ; d3 e8 ; 0xf57fa
+ push ax ; 50 ; 0xf57fc
+ mov ax, 00633h ; b8 33 06 ; 0xf57fd
+ push ax ; 50 ; 0xf5800
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5801
+ push ax ; 50 ; 0xf5804
+ call 0190fh ; e8 07 c1 ; 0xf5805
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf5808
+ mov bx, 00da0h ; bb a0 0d ; 0xf580b
+ mov cx, ds ; 8c d9 ; 0xf580e
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5810
+ call 018cch ; e8 b6 c0 ; 0xf5813
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf5816
+ push ax ; 50 ; 0xf5819
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf581a
+ push ax ; 50 ; 0xf581d
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf581e
+ push ax ; 50 ; 0xf5821
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf5822
+ push ax ; 50 ; 0xf5825
+ mov ax, 0065bh ; b8 5b 06 ; 0xf5826
+ push ax ; 50 ; 0xf5829
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf582a
+ push ax ; 50 ; 0xf582d
+ call 0190fh ; e8 de c0 ; 0xf582e
+ add sp, strict byte 0000ch ; 83 c4 0c ; 0xf5831
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf5834
+ pop di ; 5f ; 0xf5837
+ pop si ; 5e ; 0xf5838
+ pop bp ; 5d ; 0xf5839
+ retn ; c3 ; 0xf583a
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf583b keyboard.c:704
+ mov word [bp+01eh], ax ; 89 46 1e ; 0xf583e
+ xor ax, ax ; 31 c0 ; 0xf5841 keyboard.c:705
+ push ax ; 50 ; 0xf5843
+ mov cx, ss ; 8c d1 ; 0xf5844
+ lea bx, [bp-008h] ; 8d 5e f8 ; 0xf5846
+ mov dx, ss ; 8c d2 ; 0xf5849
+ lea ax, [bp-00ah] ; 8d 46 f6 ; 0xf584b
+ call 05664h ; e8 13 fe ; 0xf584e
+ test ax, ax ; 85 c0 ; 0xf5851
+ jne short 0585bh ; 75 06 ; 0xf5853
+ or word [bp+01eh], strict byte 00040h ; 83 4e 1e 40 ; 0xf5855 keyboard.c:706
+ jmp short 05834h ; eb d9 ; 0xf5859 keyboard.c:707
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf585b keyboard.c:709
+ je short 05867h ; 74 06 ; 0xf585f
+ cmp byte [bp-008h], 0f0h ; 80 7e f8 f0 ; 0xf5861
+ je short 0586dh ; 74 06 ; 0xf5865
+ cmp byte [bp-008h], 0e0h ; 80 7e f8 e0 ; 0xf5867 keyboard.c:711
+ jne short 05871h ; 75 04 ; 0xf586b
+ mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xf586d keyboard.c:712
+ mov dh, byte [bp-00ah] ; 8a 76 f6 ; 0xf5871 keyboard.c:713
+ mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xf5874
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf5877
+ and word [bp+01eh], strict byte 0ffbfh ; 83 66 1e bf ; 0xf587a keyboard.c:714
+ jmp short 05834h ; eb b4 ; 0xf587e keyboard.c:715
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf5880 keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5883
+ mov es, ax ; 8e c0 ; 0xf5886
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf5888
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf588b keyboard.c:719
+ mov dl, al ; 88 c2 ; 0xf588e
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf5890
+ jmp short 05834h ; eb 9f ; 0xf5893 keyboard.c:720
+ mov dl, byte [bp+010h] ; 8a 56 10 ; 0xf5895 keyboard.c:723
+ xor dh, dh ; 30 f6 ; 0xf5898
+ mov CL, strict byte 008h ; b1 08 ; 0xf589a
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf589c
+ shr ax, CL ; d3 e8 ; 0xf589f
+ xor ah, ah ; 30 e4 ; 0xf58a1
+ call 051e0h ; e8 3a f9 ; 0xf58a3
+ test ax, ax ; 85 c0 ; 0xf58a6
+ jne short 058b4h ; 75 0a ; 0xf58a8
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf58aa keyboard.c:724
+ xor al, al ; 30 c0 ; 0xf58ad
+ or AL, strict byte 001h ; 0c 01 ; 0xf58af
+ jmp near 057e4h ; e9 30 ff ; 0xf58b1
+ and word [bp+012h], 0ff00h ; 81 66 12 00 ff ; 0xf58b4 keyboard.c:727
+ jmp near 05834h ; e9 78 ff ; 0xf58b9 keyboard.c:729
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf58bc keyboard.c:742
+ xor al, al ; 30 c0 ; 0xf58bf
+ or AL, strict byte 030h ; 0c 30 ; 0xf58c1
+ jmp near 057e4h ; e9 1e ff ; 0xf58c3
+ mov byte [bp-006h], 002h ; c6 46 fa 02 ; 0xf58c6 keyboard.c:746
+ xor cx, cx ; 31 c9 ; 0xf58ca keyboard.c:747
+ cli ; fa ; 0xf58cc keyboard.c:749
+ mov AL, strict byte 0f2h ; b0 f2 ; 0xf58cd keyboard.c:750
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf58cf
+ out DX, AL ; ee ; 0xf58d2
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf58d3 keyboard.c:752
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf58d6 keyboard.c:753
+ in AL, DX ; ec ; 0xf58d9
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf58da
+ test AL, strict byte 001h ; a8 01 ; 0xf58dc
+ jne short 058edh ; 75 0d ; 0xf58de
+ dec bx ; 4b ; 0xf58e0
+ test bx, bx ; 85 db ; 0xf58e1
+ jbe short 058edh ; 76 08 ; 0xf58e3
+ mov dx, 00080h ; ba 80 00 ; 0xf58e5 keyboard.c:754
+ in AL, DX ; ec ; 0xf58e8
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf58e9
+ jmp short 058d6h ; eb e9 ; 0xf58eb
+ test bx, bx ; 85 db ; 0xf58ed keyboard.c:755
+ jbe short 0592fh ; 76 3e ; 0xf58ef
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf58f1 keyboard.c:756
+ in AL, DX ; ec ; 0xf58f4
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf58f5
+ cmp ax, 000fah ; 3d fa 00 ; 0xf58f7
+ jne short 0592fh ; 75 33 ; 0xf58fa
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf58fc keyboard.c:758
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf58ff keyboard.c:759
+ in AL, DX ; ec ; 0xf5902
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5903
+ test AL, strict byte 001h ; a8 01 ; 0xf5905
+ jne short 05916h ; 75 0d ; 0xf5907
+ dec bx ; 4b ; 0xf5909
+ test bx, bx ; 85 db ; 0xf590a
+ jbe short 05916h ; 76 08 ; 0xf590c
+ mov dx, 00080h ; ba 80 00 ; 0xf590e keyboard.c:760
+ in AL, DX ; ec ; 0xf5911
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5912
+ jmp short 058ffh ; eb e9 ; 0xf5914
+ test bx, bx ; 85 db ; 0xf5916 keyboard.c:761
+ jbe short 05926h ; 76 0c ; 0xf5918
+ mov bl, ch ; 88 eb ; 0xf591a keyboard.c:762
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf591c keyboard.c:763
+ in AL, DX ; ec ; 0xf591f
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf5920
+ mov ch, al ; 88 c5 ; 0xf5922
+ mov cl, bl ; 88 d9 ; 0xf5924
+ dec byte [bp-006h] ; fe 4e fa ; 0xf5926 keyboard.c:765
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf5929
+ jnbe short 058fch ; 77 cd ; 0xf592d
+ mov word [bp+00ch], cx ; 89 4e 0c ; 0xf592f keyboard.c:768
+ jmp near 05834h ; e9 ff fe ; 0xf5932 keyboard.c:769
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf5935 keyboard.c:772
+ push ax ; 50 ; 0xf5938
+ mov cx, ss ; 8c d1 ; 0xf5939
+ lea bx, [bp-008h] ; 8d 5e f8 ; 0xf593b
+ mov dx, ss ; 8c d2 ; 0xf593e
+ lea ax, [bp-00ah] ; 8d 46 f6 ; 0xf5940
+ call 05664h ; e8 1e fd ; 0xf5943
+ test ax, ax ; 85 c0 ; 0xf5946
+ jne short 05958h ; 75 0e ; 0xf5948
+ mov ax, 0060fh ; b8 0f 06 ; 0xf594a keyboard.c:773
+ push ax ; 50 ; 0xf594d
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf594e
+ push ax ; 50 ; 0xf5951
+ call 0190fh ; e8 ba bf ; 0xf5952
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf5955
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf5958 keyboard.c:775
+ je short 05968h ; 74 0a ; 0xf595c
+ cmp byte [bp-008h], 0f0h ; 80 7e f8 f0 ; 0xf595e
+ jne short 05968h ; 75 04 ; 0xf5962
+ mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xf5964 keyboard.c:776
+ mov dh, byte [bp-00ah] ; 8a 76 f6 ; 0xf5968 keyboard.c:777
+ mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xf596b
+ jmp near 05890h ; e9 1f ff ; 0xf596e
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf5971 keyboard.c:782
+ mov word [bp+01eh], ax ; 89 46 1e ; 0xf5974
+ xor ax, ax ; 31 c0 ; 0xf5977 keyboard.c:783
+ push ax ; 50 ; 0xf5979
+ mov cx, ss ; 8c d1 ; 0xf597a
+ lea bx, [bp-008h] ; 8d 5e f8 ; 0xf597c
+ mov dx, ss ; 8c d2 ; 0xf597f
+ lea ax, [bp-00ah] ; 8d 46 f6 ; 0xf5981
+ call 05664h ; e8 dd fc ; 0xf5984
+ test ax, ax ; 85 c0 ; 0xf5987
+ jne short 0598eh ; 75 03 ; 0xf5989
+ jmp near 05855h ; e9 c7 fe ; 0xf598b
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf598e keyboard.c:787
+ jne short 05997h ; 75 03 ; 0xf5992
+ jmp near 05871h ; e9 da fe ; 0xf5994
+ cmp byte [bp-008h], 0f0h ; 80 7e f8 f0 ; 0xf5997
+ jne short 059a0h ; 75 03 ; 0xf599b
+ jmp near 0586dh ; e9 cd fe ; 0xf599d
+ jmp short 05994h ; eb f2 ; 0xf59a0
+ mov bx, strict word 00017h ; bb 17 00 ; 0xf59a2 keyboard.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf59a5
+ mov es, ax ; 8e c0 ; 0xf59a8
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf59aa
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf59ad keyboard.c:795
+ mov dl, al ; 88 c2 ; 0xf59b0
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf59b2
+ mov bx, strict word 00018h ; bb 18 00 ; 0xf59b5 keyboard.c:38
+ mov bh, byte [es:bx] ; 26 8a 3f ; 0xf59b8
+ and bh, 073h ; 80 e7 73 ; 0xf59bb keyboard.c:39
+ mov si, 00096h ; be 96 00 ; 0xf59be keyboard.c:38
+ mov ah, byte [es:si] ; 26 8a 24 ; 0xf59c1
+ and ah, 00ch ; 80 e4 0c ; 0xf59c4 keyboard.c:39
+ or ah, bh ; 08 fc ; 0xf59c7
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf59c9 keyboard.c:798
+ mov dh, ah ; 88 e6 ; 0xf59cc
+ jmp near 05890h ; e9 bf fe ; 0xf59ce
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf59d1 keyboard.c:803
+ xor ah, ah ; 30 e4 ; 0xf59d4
+ or ah, 080h ; 80 cc 80 ; 0xf59d6
+ jmp near 057e4h ; e9 08 fe ; 0xf59d9
+ ; disGetNextSymbol 0xf59dc LB 0x456c -> off=0x0 cb=00000000000000b9 uValue=00000000000f43dc 'set_geom_lba'
+set_geom_lba: ; 0xf59dc LB 0xb9
+ push bx ; 53 ; 0xf59dc disk.c:115
+ push cx ; 51 ; 0xf59dd
+ push si ; 56 ; 0xf59de
+ push di ; 57 ; 0xf59df
+ push bp ; 55 ; 0xf59e0
+ mov bp, sp ; 89 e5 ; 0xf59e1
+ sub sp, strict byte 00008h ; 83 ec 08 ; 0xf59e3
+ mov di, ax ; 89 c7 ; 0xf59e6
+ mov es, dx ; 8e c2 ; 0xf59e8
+ mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xf59ea disk.c:117
+ mov word [bp-006h], strict word 0007eh ; c7 46 fa 7e 00 ; 0xf59ef
+ mov word [bp-002h], 000ffh ; c7 46 fe ff 00 ; 0xf59f4 disk.c:119
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf59f9 disk.c:122
+ mov bx, word [bp+010h] ; 8b 5e 10 ; 0xf59fc
+ mov cx, word [bp+00eh] ; 8b 4e 0e ; 0xf59ff
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf5a02
+ mov si, strict word 00020h ; be 20 00 ; 0xf5a05
+ call 09c10h ; e8 05 42 ; 0xf5a08
+ test ax, ax ; 85 c0 ; 0xf5a0b
+ jne short 05a1bh ; 75 0c ; 0xf5a0d
+ test bx, bx ; 85 db ; 0xf5a0f
+ jne short 05a1bh ; 75 08 ; 0xf5a11
+ test cx, cx ; 85 c9 ; 0xf5a13
+ jne short 05a1bh ; 75 04 ; 0xf5a15
+ test dx, dx ; 85 d2 ; 0xf5a17
+ je short 05a22h ; 74 07 ; 0xf5a19
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf5a1b
+ mov si, bx ; 89 de ; 0xf5a1e
+ jmp short 05a28h ; eb 06 ; 0xf5a20
+ mov bx, word [bp+00ch] ; 8b 5e 0c ; 0xf5a22
+ mov si, word [bp+00eh] ; 8b 76 0e ; 0xf5a25
+ mov word [bp-004h], bx ; 89 5e fc ; 0xf5a28
+ xor bx, bx ; 31 db ; 0xf5a2b disk.c:124
+ jmp short 05a34h ; eb 05 ; 0xf5a2d
+ cmp bx, strict byte 00004h ; 83 fb 04 ; 0xf5a2f
+ jnl short 05a57h ; 7d 23 ; 0xf5a32
+ mov ax, word [bp-006h] ; 8b 46 fa ; 0xf5a34 disk.c:125
+ cmp si, ax ; 39 c6 ; 0xf5a37
+ jc short 05a45h ; 72 0a ; 0xf5a39
+ jne short 05a4eh ; 75 11 ; 0xf5a3b
+ mov ax, word [bp-004h] ; 8b 46 fc ; 0xf5a3d
+ cmp ax, word [bp-008h] ; 3b 46 f8 ; 0xf5a40
+ jnbe short 05a4eh ; 77 09 ; 0xf5a43
+ mov ax, word [bp-002h] ; 8b 46 fe ; 0xf5a45 disk.c:126
+ inc ax ; 40 ; 0xf5a48
+ shr ax, 1 ; d1 e8 ; 0xf5a49
+ mov word [bp-002h], ax ; 89 46 fe ; 0xf5a4b
+ shr word [bp-006h], 1 ; d1 6e fa ; 0xf5a4e disk.c:127
+ rcr word [bp-008h], 1 ; d1 5e f8 ; 0xf5a51
+ inc bx ; 43 ; 0xf5a54 disk.c:128
+ jmp short 05a2fh ; eb d8 ; 0xf5a55
+ mov ax, word [bp-002h] ; 8b 46 fe ; 0xf5a57 disk.c:130
+ xor dx, dx ; 31 d2 ; 0xf5a5a
+ mov bx, strict word 0003fh ; bb 3f 00 ; 0xf5a5c
+ xor cx, cx ; 31 c9 ; 0xf5a5f
+ call 09bc0h ; e8 5c 41 ; 0xf5a61
+ mov bx, ax ; 89 c3 ; 0xf5a64
+ mov cx, dx ; 89 d1 ; 0xf5a66
+ mov ax, word [bp-004h] ; 8b 46 fc ; 0xf5a68
+ mov dx, si ; 89 f2 ; 0xf5a6b
+ call 09be0h ; e8 70 41 ; 0xf5a6d
+ mov word [es:di+002h], ax ; 26 89 45 02 ; 0xf5a70
+ cmp ax, 00400h ; 3d 00 04 ; 0xf5a74 disk.c:131
+ jbe short 05a7fh ; 76 06 ; 0xf5a77
+ mov word [es:di+002h], 00400h ; 26 c7 45 02 00 04 ; 0xf5a79 disk.c:132
+ mov ax, word [bp-002h] ; 8b 46 fe ; 0xf5a7f disk.c:133
+ mov word [es:di], ax ; 26 89 05 ; 0xf5a82
+ mov word [es:di+004h], strict word 0003fh ; 26 c7 45 04 3f 00 ; 0xf5a85 disk.c:134
+ mov sp, bp ; 89 ec ; 0xf5a8b disk.c:135
+ pop bp ; 5d ; 0xf5a8d
+ pop di ; 5f ; 0xf5a8e
+ pop si ; 5e ; 0xf5a8f
+ pop cx ; 59 ; 0xf5a90
+ pop bx ; 5b ; 0xf5a91
+ retn 00008h ; c2 08 00 ; 0xf5a92
+ ; disGetNextSymbol 0xf5a95 LB 0x44b3 -> off=0x0 cb=000000000000031e uValue=00000000000f4495 'edd_fill_dpt'
+edd_fill_dpt: ; 0xf5a95 LB 0x31e
+ push si ; 56 ; 0xf5a95 disk.c:137
+ push di ; 57 ; 0xf5a96
+ push bp ; 55 ; 0xf5a97
+ mov bp, sp ; 89 e5 ; 0xf5a98
+ sub sp, strict byte 00010h ; 83 ec 10 ; 0xf5a9a
+ mov di, ax ; 89 c7 ; 0xf5a9d
+ mov word [bp-004h], dx ; 89 56 fc ; 0xf5a9f
+ mov word [bp-008h], bx ; 89 5e f8 ; 0xf5aa2
+ mov word [bp-006h], cx ; 89 4e fa ; 0xf5aa5
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf5aa8 disk.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5aab
+ mov es, ax ; 8e c0 ; 0xf5aae
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf5ab0
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf5ab3 disk.c:49
+ mov es, dx ; 8e c2 ; 0xf5ab6 disk.c:142
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf5ab8
+ cmp ax, strict word 0001ah ; 3d 1a 00 ; 0xf5abb
+ jnc short 05ac6h ; 73 06 ; 0xf5abe
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf5ac0 disk.c:143
+ jmp near 05dabh ; e9 e5 02 ; 0xf5ac3
+ jc short 05b39h ; 72 71 ; 0xf5ac6 disk.c:146
+ mov word [es:di], strict word 0001ah ; 26 c7 05 1a 00 ; 0xf5ac8 disk.c:149
+ mov al, byte [bp+008h] ; 8a 46 08 ; 0xf5acd disk.c:150
+ xor ah, ah ; 30 e4 ; 0xf5ad0
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf5ad2
+ imul dx ; f7 ea ; 0xf5ad5
+ mov dx, cx ; 89 ca ; 0xf5ad7
+ mov bx, word [bp-008h] ; 8b 5e f8 ; 0xf5ad9
+ add bx, ax ; 01 c3 ; 0xf5adc
+ mov es, cx ; 8e c1 ; 0xf5ade
+ mov ax, word [es:bx+028h] ; 26 8b 47 28 ; 0xf5ae0
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5ae4
+ mov word [es:di+018h], ax ; 26 89 45 18 ; 0xf5ae7
+ mov es, cx ; 8e c1 ; 0xf5aeb disk.c:152
+ cmp byte [es:bx+023h], 005h ; 26 80 7f 23 05 ; 0xf5aed
+ jne short 05b3bh ; 75 47 ; 0xf5af2
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5af4 disk.c:153
+ mov word [es:di+002h], strict word 00074h ; 26 c7 45 02 74 00 ; 0xf5af7
+ mov word [es:di+004h], strict word 0ffffh ; 26 c7 45 04 ff ff ; 0xf5afd disk.c:154
+ mov word [es:di+006h], strict word 0ffffh ; 26 c7 45 06 ff ff ; 0xf5b03
+ mov word [es:di+008h], strict word 0ffffh ; 26 c7 45 08 ff ff ; 0xf5b09 disk.c:155
+ mov word [es:di+00ah], strict word 0ffffh ; 26 c7 45 0a ff ff ; 0xf5b0f
+ mov word [es:di+00ch], strict word 0ffffh ; 26 c7 45 0c ff ff ; 0xf5b15 disk.c:156
+ mov word [es:di+00eh], strict word 0ffffh ; 26 c7 45 0e ff ff ; 0xf5b1b
+ mov word [es:di+010h], strict word 0ffffh ; 26 c7 45 10 ff ff ; 0xf5b21 disk.c:157
+ mov word [es:di+012h], strict word 0ffffh ; 26 c7 45 12 ff ff ; 0xf5b27
+ mov word [es:di+014h], strict word 0ffffh ; 26 c7 45 14 ff ff ; 0xf5b2d disk.c:158
+ mov word [es:di+016h], strict word 0ffffh ; 26 c7 45 16 ff ff ; 0xf5b33
+ jmp short 05baah ; eb 6f ; 0xf5b39 disk.c:159
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5b3b disk.c:160
+ mov word [es:di+002h], strict word 00002h ; 26 c7 45 02 02 00 ; 0xf5b3e
+ mov es, cx ; 8e c1 ; 0xf5b44 disk.c:161
+ mov ax, word [es:bx+032h] ; 26 8b 47 32 ; 0xf5b46
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5b4a
+ mov word [es:di+004h], ax ; 26 89 45 04 ; 0xf5b4d
+ mov word [es:di+006h], strict word 00000h ; 26 c7 45 06 00 00 ; 0xf5b51
+ mov es, cx ; 8e c1 ; 0xf5b57 disk.c:162
+ mov ax, word [es:bx+030h] ; 26 8b 47 30 ; 0xf5b59
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5b5d
+ mov word [es:di+008h], ax ; 26 89 45 08 ; 0xf5b60
+ mov word [es:di+00ah], strict word 00000h ; 26 c7 45 0a 00 00 ; 0xf5b64
+ mov es, cx ; 8e c1 ; 0xf5b6a disk.c:163
+ mov ax, word [es:bx+034h] ; 26 8b 47 34 ; 0xf5b6c
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5b70
+ mov word [es:di+00ch], ax ; 26 89 45 0c ; 0xf5b73
+ mov word [es:di+00eh], strict word 00000h ; 26 c7 45 0e 00 00 ; 0xf5b77
+ mov es, cx ; 8e c1 ; 0xf5b7d disk.c:164
+ mov ax, word [es:bx+03ch] ; 26 8b 47 3c ; 0xf5b7f
+ mov si, word [es:bx+03ah] ; 26 8b 77 3a ; 0xf5b83
+ mov cx, word [es:bx+038h] ; 26 8b 4f 38 ; 0xf5b87
+ mov dx, word [es:bx+036h] ; 26 8b 57 36 ; 0xf5b8b
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5b8f disk.c:165
+ mov word [es:di+010h], dx ; 26 89 55 10 ; 0xf5b92
+ mov word [es:di+012h], cx ; 26 89 4d 12 ; 0xf5b96
+ mov bx, si ; 89 f3 ; 0xf5b9a disk.c:166
+ mov si, strict word 00020h ; be 20 00 ; 0xf5b9c
+ call 09c10h ; e8 6e 40 ; 0xf5b9f
+ mov word [es:di+014h], dx ; 26 89 55 14 ; 0xf5ba2
+ mov word [es:di+016h], cx ; 26 89 4d 16 ; 0xf5ba6
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5baa disk.c:171
+ cmp word [es:di], strict byte 0001eh ; 26 83 3d 1e ; 0xf5bad
+ jc short 05c0dh ; 72 5a ; 0xf5bb1
+ mov word [es:di], strict word 0001eh ; 26 c7 05 1e 00 ; 0xf5bb3 disk.c:175
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf5bb8 disk.c:176
+ mov word [es:di+01ch], ax ; 26 89 45 1c ; 0xf5bbb
+ mov word [es:di+01ah], 00356h ; 26 c7 45 1a 56 03 ; 0xf5bbf disk.c:177
+ mov cl, byte [bp+008h] ; 8a 4e 08 ; 0xf5bc5 disk.c:180
+ xor ch, ch ; 30 ed ; 0xf5bc8
+ mov ax, cx ; 89 c8 ; 0xf5bca
+ cwd ; 99 ; 0xf5bcc
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf5bcd
+ sar ax, 1 ; d1 f8 ; 0xf5bcf
+ xor ah, ah ; 30 e4 ; 0xf5bd1 disk.c:181
+ mov dx, strict word 00006h ; ba 06 00 ; 0xf5bd3
+ imul dx ; f7 ea ; 0xf5bd6
+ les bx, [bp-008h] ; c4 5e f8 ; 0xf5bd8
+ add bx, ax ; 01 c3 ; 0xf5bdb
+ mov ax, word [es:bx+00206h] ; 26 8b 87 06 02 ; 0xf5bdd
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf5be2
+ mov ax, word [es:bx+00208h] ; 26 8b 87 08 02 ; 0xf5be5 disk.c:182
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf5bea
+ mov al, byte [es:bx+00205h] ; 26 8a 87 05 02 ; 0xf5bed disk.c:183
+ mov byte [bp-002h], al ; 88 46 fe ; 0xf5bf2
+ mov ax, cx ; 89 c8 ; 0xf5bf5 disk.c:185
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf5bf7
+ imul dx ; f7 ea ; 0xf5bfa
+ mov bx, word [bp-008h] ; 8b 5e f8 ; 0xf5bfc
+ add bx, ax ; 01 c3 ; 0xf5bff
+ mov bl, byte [es:bx+027h] ; 26 8a 5f 27 ; 0xf5c01
+ test bl, bl ; 84 db ; 0xf5c05 disk.c:187
+ jne short 05c10h ; 75 07 ; 0xf5c07
+ xor ax, ax ; 31 c0 ; 0xf5c09
+ jmp short 05c13h ; eb 06 ; 0xf5c0b
+ jmp near 05cd8h ; e9 c8 00 ; 0xf5c0d
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf5c10
+ or AL, strict byte 010h ; 0c 10 ; 0xf5c13 disk.c:188
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf5c15
+ mov al, byte [bp+008h] ; 8a 46 08 ; 0xf5c18 disk.c:189
+ xor ah, ah ; 30 e4 ; 0xf5c1b
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf5c1d
+ imul dx ; f7 ea ; 0xf5c20
+ les si, [bp-008h] ; c4 76 f8 ; 0xf5c22
+ add si, ax ; 01 c6 ; 0xf5c25
+ cmp byte [es:si+023h], 005h ; 26 80 7c 23 05 ; 0xf5c27
+ jne short 05c32h ; 75 04 ; 0xf5c2c
+ or byte [bp-00ah], 060h ; 80 4e f6 60 ; 0xf5c2e disk.c:190
+ cmp bl, 001h ; 80 fb 01 ; 0xf5c32 disk.c:196
+ jne short 05c3ch ; 75 05 ; 0xf5c35
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf5c37
+ jmp short 05c3eh ; eb 02 ; 0xf5c3a
+ xor ax, ax ; 31 c0 ; 0xf5c3c
+ or word [bp-00ah], ax ; 09 46 f6 ; 0xf5c3e
+ cmp bl, 003h ; 80 fb 03 ; 0xf5c41 disk.c:197
+ jne short 05c4bh ; 75 05 ; 0xf5c44
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf5c46
+ jmp short 05c4dh ; eb 02 ; 0xf5c49
+ xor ax, ax ; 31 c0 ; 0xf5c4b
+ or word [bp-00ah], ax ; 09 46 f6 ; 0xf5c4d
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf5c50 disk.c:199
+ les bx, [bp-008h] ; c4 5e f8 ; 0xf5c53
+ mov word [es:bx+00234h], ax ; 26 89 87 34 02 ; 0xf5c56
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf5c5b disk.c:200
+ mov word [es:bx+00236h], ax ; 26 89 87 36 02 ; 0xf5c5e
+ mov al, byte [bp+008h] ; 8a 46 08 ; 0xf5c63 disk.c:201
+ xor ah, ah ; 30 e4 ; 0xf5c66
+ cwd ; 99 ; 0xf5c68
+ mov bx, strict word 00002h ; bb 02 00 ; 0xf5c69
+ idiv bx ; f7 fb ; 0xf5c6c
+ or dl, 00eh ; 80 ca 0e ; 0xf5c6e
+ mov CL, strict byte 004h ; b1 04 ; 0xf5c71
+ sal dx, CL ; d3 e2 ; 0xf5c73
+ mov bx, word [bp-008h] ; 8b 5e f8 ; 0xf5c75
+ mov byte [es:bx+00238h], dl ; 26 88 97 38 02 ; 0xf5c78
+ mov byte [es:bx+00239h], 0cbh ; 26 c6 87 39 02 cb ; 0xf5c7d disk.c:202
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf5c83 disk.c:203
+ mov byte [es:bx+0023ah], al ; 26 88 87 3a 02 ; 0xf5c86
+ mov word [es:bx+0023bh], strict word 00001h ; 26 c7 87 3b 02 01 00 ; 0xf5c8b disk.c:204
+ mov byte [es:bx+0023dh], 000h ; 26 c6 87 3d 02 00 ; 0xf5c92 disk.c:206
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf5c98 disk.c:207
+ mov word [es:bx+0023eh], ax ; 26 89 87 3e 02 ; 0xf5c9b
+ mov word [es:bx+00240h], strict word 00000h ; 26 c7 87 40 02 00 00 ; 0xf5ca0 disk.c:208
+ mov byte [es:bx+00242h], 011h ; 26 c6 87 42 02 11 ; 0xf5ca7 disk.c:209
+ xor bl, bl ; 30 db ; 0xf5cad disk.c:211
+ xor bh, bh ; 30 ff ; 0xf5caf disk.c:212
+ jmp short 05cb8h ; eb 05 ; 0xf5cb1
+ cmp bh, 00fh ; 80 ff 0f ; 0xf5cb3
+ jnc short 05cceh ; 73 16 ; 0xf5cb6
+ mov al, bh ; 88 f8 ; 0xf5cb8 disk.c:213
+ xor ah, ah ; 30 e4 ; 0xf5cba
+ mov si, ax ; 89 c6 ; 0xf5cbc
+ add si, 00356h ; 81 c6 56 03 ; 0xf5cbe
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf5cc2 disk.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf5cc5
+ add bl, al ; 00 c3 ; 0xf5cc8 disk.c:39
+ db 0feh, 0c7h
+ ; inc bh ; fe c7 ; 0xf5cca disk.c:213
+ jmp short 05cb3h ; eb e5 ; 0xf5ccc
+ neg bl ; f6 db ; 0xf5cce disk.c:214
+ les si, [bp-008h] ; c4 76 f8 ; 0xf5cd0 disk.c:215
+ mov byte [es:si+00243h], bl ; 26 88 9c 43 02 ; 0xf5cd3
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5cd8 disk.c:219
+ cmp word [es:di], strict byte 00042h ; 26 83 3d 42 ; 0xf5cdb
+ jnc short 05ce4h ; 73 03 ; 0xf5cdf
+ jmp near 05da9h ; e9 c5 00 ; 0xf5ce1
+ mov al, byte [bp+008h] ; 8a 46 08 ; 0xf5ce4 disk.c:223
+ xor ah, ah ; 30 e4 ; 0xf5ce7
+ cwd ; 99 ; 0xf5ce9
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf5cea
+ sar ax, 1 ; d1 f8 ; 0xf5cec
+ xor ah, ah ; 30 e4 ; 0xf5cee disk.c:224
+ mov dx, strict word 00006h ; ba 06 00 ; 0xf5cf0
+ imul dx ; f7 ea ; 0xf5cf3
+ les bx, [bp-008h] ; c4 5e f8 ; 0xf5cf5
+ add bx, ax ; 01 c3 ; 0xf5cf8
+ mov al, byte [es:bx+00204h] ; 26 8a 87 04 02 ; 0xf5cfa
+ mov dx, word [es:bx+00206h] ; 26 8b 97 06 02 ; 0xf5cff disk.c:225
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5d04 disk.c:227
+ mov word [es:di], strict word 00042h ; 26 c7 05 42 00 ; 0xf5d07
+ mov word [es:di+01eh], 0beddh ; 26 c7 45 1e dd be ; 0xf5d0c disk.c:228
+ mov word [es:di+020h], strict word 00024h ; 26 c7 45 20 24 00 ; 0xf5d12 disk.c:229
+ mov word [es:di+022h], strict word 00000h ; 26 c7 45 22 00 00 ; 0xf5d18 disk.c:231
+ test al, al ; 84 c0 ; 0xf5d1e disk.c:233
+ jne short 05d2eh ; 75 0c ; 0xf5d20
+ mov word [es:di+024h], 05349h ; 26 c7 45 24 49 53 ; 0xf5d22 disk.c:234
+ mov word [es:di+026h], 02041h ; 26 c7 45 26 41 20 ; 0xf5d28 disk.c:236
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5d2e disk.c:242
+ mov word [es:di+028h], 05441h ; 26 c7 45 28 41 54 ; 0xf5d31
+ mov word [es:di+02ah], 02041h ; 26 c7 45 2a 41 20 ; 0xf5d37 disk.c:244
+ mov word [es:di+02ch], 02020h ; 26 c7 45 2c 20 20 ; 0xf5d3d disk.c:246
+ mov word [es:di+02eh], 02020h ; 26 c7 45 2e 20 20 ; 0xf5d43 disk.c:248
+ test al, al ; 84 c0 ; 0xf5d49 disk.c:251
+ jne short 05d63h ; 75 16 ; 0xf5d4b
+ mov word [es:di+030h], dx ; 26 89 55 30 ; 0xf5d4d disk.c:252
+ mov word [es:di+032h], strict word 00000h ; 26 c7 45 32 00 00 ; 0xf5d51 disk.c:253
+ mov word [es:di+034h], strict word 00000h ; 26 c7 45 34 00 00 ; 0xf5d57 disk.c:254
+ mov word [es:di+036h], strict word 00000h ; 26 c7 45 36 00 00 ; 0xf5d5d
+ mov al, byte [bp+008h] ; 8a 46 08 ; 0xf5d63 disk.c:259
+ and AL, strict byte 001h ; 24 01 ; 0xf5d66
+ xor ah, ah ; 30 e4 ; 0xf5d68
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5d6a
+ mov word [es:di+038h], ax ; 26 89 45 38 ; 0xf5d6d
+ mov word [es:di+03ah], strict word 00000h ; 26 c7 45 3a 00 00 ; 0xf5d71 disk.c:260
+ mov word [es:di+03ch], strict word 00000h ; 26 c7 45 3c 00 00 ; 0xf5d77 disk.c:261
+ mov word [es:di+03eh], strict word 00000h ; 26 c7 45 3e 00 00 ; 0xf5d7d
+ xor bl, bl ; 30 db ; 0xf5d83 disk.c:263
+ mov BH, strict byte 01eh ; b7 1e ; 0xf5d85 disk.c:264
+ jmp short 05d8eh ; eb 05 ; 0xf5d87
+ cmp bh, 040h ; 80 ff 40 ; 0xf5d89
+ jnc short 05da0h ; 73 12 ; 0xf5d8c
+ mov al, bh ; 88 f8 ; 0xf5d8e disk.c:265
+ xor ah, ah ; 30 e4 ; 0xf5d90
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5d92
+ mov si, di ; 89 fe ; 0xf5d95
+ add si, ax ; 01 c6 ; 0xf5d97
+ add bl, byte [es:si] ; 26 02 1c ; 0xf5d99
+ db 0feh, 0c7h
+ ; inc bh ; fe c7 ; 0xf5d9c
+ jmp short 05d89h ; eb e9 ; 0xf5d9e
+ neg bl ; f6 db ; 0xf5da0 disk.c:266
+ mov es, [bp-004h] ; 8e 46 fc ; 0xf5da2 disk.c:267
+ mov byte [es:di+041h], bl ; 26 88 5d 41 ; 0xf5da5
+ xor ax, ax ; 31 c0 ; 0xf5da9 disk.c:269
+ mov sp, bp ; 89 ec ; 0xf5dab disk.c:270
+ pop bp ; 5d ; 0xf5dad
+ pop di ; 5f ; 0xf5dae
+ pop si ; 5e ; 0xf5daf
+ retn 00002h ; c2 02 00 ; 0xf5db0
+ ; disGetNextSymbol 0xf5db3 LB 0x4195 -> off=0x32 cb=000000000000042c uValue=00000000000f47e5 'int13_harddisk'
+ db 06dh, 05eh, 07eh, 05eh, 0a2h, 05eh, 0a2h, 05eh, 0a2h, 05eh, 090h, 060h, 0d4h, 061h, 0d4h, 061h
+ db 0c1h, 060h, 0aeh, 061h, 0d4h, 061h, 0d4h, 061h, 0aeh, 061h, 0aeh, 061h, 0d4h, 061h, 0d4h, 061h
+ db 02ch, 061h, 0aeh, 061h, 0d4h, 061h, 0d4h, 061h, 0aeh, 061h, 05fh, 061h, 0d4h, 061h, 0d4h, 061h
+ db 0d4h, 061h
+int13_harddisk: ; 0xf5de5 LB 0x42c
+ push bp ; 55 ; 0xf5de5 disk.c:272
+ mov bp, sp ; 89 e5 ; 0xf5de6
+ sub sp, strict byte 00010h ; 83 ec 10 ; 0xf5de8
+ or byte [bp+01dh], 002h ; 80 4e 1d 02 ; 0xf5deb disk.c:283
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf5def disk.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5df2
+ mov es, ax ; 8e c0 ; 0xf5df5
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf5df7
+ mov si, 00122h ; be 22 01 ; 0xf5dfa disk.c:49
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf5dfd
+ mov bx, 0008eh ; bb 8e 00 ; 0xf5e00 disk.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf5e03
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf5e07 disk.c:289
+ xor ah, ah ; 30 e4 ; 0xf5e0a
+ cmp ax, 00080h ; 3d 80 00 ; 0xf5e0c
+ jc short 05e16h ; 72 05 ; 0xf5e0f
+ cmp ax, 00090h ; 3d 90 00 ; 0xf5e11
+ jc short 05e35h ; 72 1f ; 0xf5e14
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf5e16 disk.c:290
+ xor ah, ah ; 30 e4 ; 0xf5e19
+ push ax ; 50 ; 0xf5e1b
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf5e1c
+ push ax ; 50 ; 0xf5e1f
+ mov ax, 0067eh ; b8 7e 06 ; 0xf5e20
+ push ax ; 50 ; 0xf5e23
+ mov ax, 0068dh ; b8 8d 06 ; 0xf5e24
+ push ax ; 50 ; 0xf5e27
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5e28
+ push ax ; 50 ; 0xf5e2b
+ call 0190fh ; e8 e0 ba ; 0xf5e2c
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf5e2f
+ jmp near 061efh ; e9 ba 03 ; 0xf5e32 disk.c:291
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf5e35 disk.c:295
+ xor ah, ah ; 30 e4 ; 0xf5e38
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf5e3a
+ mov bx, si ; 89 f3 ; 0xf5e3d
+ add bx, ax ; 01 c3 ; 0xf5e3f
+ mov dl, byte [es:bx+00163h] ; 26 8a 97 63 01 ; 0xf5e41
+ mov byte [bp-002h], dl ; 88 56 fe ; 0xf5e46
+ cmp dl, 010h ; 80 fa 10 ; 0xf5e49 disk.c:298
+ jc short 05e5ch ; 72 0e ; 0xf5e4c
+ push ax ; 50 ; 0xf5e4e disk.c:299
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf5e4f
+ push ax ; 50 ; 0xf5e52
+ mov ax, 0067eh ; b8 7e 06 ; 0xf5e53
+ push ax ; 50 ; 0xf5e56
+ mov ax, 006b8h ; b8 b8 06 ; 0xf5e57
+ jmp short 05e27h ; eb cb ; 0xf5e5a
+ mov bl, byte [bp+017h] ; 8a 5e 17 ; 0xf5e5c disk.c:303
+ xor bh, bh ; 30 ff ; 0xf5e5f
+ cmp bx, strict byte 00018h ; 83 fb 18 ; 0xf5e61
+ jnbe short 05e9fh ; 77 39 ; 0xf5e64
+ sal bx, 1 ; d1 e3 ; 0xf5e66
+ jmp word [cs:bx+05db3h] ; 2e ff a7 b3 5d ; 0xf5e68
+ cmp byte [bp-002h], 008h ; 80 7e fe 08 ; 0xf5e6d disk.c:308
+ jnc short 05e7bh ; 73 08 ; 0xf5e71
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf5e73 disk.c:310
+ xor ah, ah ; 30 e4 ; 0xf5e76
+ call 01d4eh ; e8 d3 be ; 0xf5e78
+ jmp near 060a9h ; e9 2b 02 ; 0xf5e7b disk.c:311
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf5e7e disk.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf5e81
+ mov es, ax ; 8e c0 ; 0xf5e84
+ mov dl, byte [es:bx] ; 26 8a 17 ; 0xf5e86
+ mov bx, word [bp+016h] ; 8b 5e 16 ; 0xf5e89 disk.c:316
+ mov bh, dl ; 88 d7 ; 0xf5e8c
+ mov word [bp+016h], bx ; 89 5e 16 ; 0xf5e8e
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf5e91 disk.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf5e94
+ test dl, dl ; 84 d2 ; 0xf5e98 disk.c:319
+ je short 05efeh ; 74 62 ; 0xf5e9a
+ jmp near 0620ah ; e9 6b 03 ; 0xf5e9c
+ jmp near 061d4h ; e9 32 03 ; 0xf5e9f
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf5ea2 disk.c:327
+ xor ah, ah ; 30 e4 ; 0xf5ea5
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf5ea7
+ mov al, byte [bp+015h] ; 8a 46 15 ; 0xf5eaa disk.c:328
+ mov dx, word [bp+014h] ; 8b 56 14 ; 0xf5ead disk.c:329
+ xor dh, dh ; 30 f6 ; 0xf5eb0
+ sal dx, 1 ; d1 e2 ; 0xf5eb2
+ sal dx, 1 ; d1 e2 ; 0xf5eb4
+ and dh, 003h ; 80 e6 03 ; 0xf5eb6
+ mov ah, dh ; 88 f4 ; 0xf5eb9
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf5ebb
+ mov di, word [bp+014h] ; 8b 7e 14 ; 0xf5ebe disk.c:330
+ and di, strict byte 0003fh ; 83 e7 3f ; 0xf5ec1
+ mov al, byte [bp+013h] ; 8a 46 13 ; 0xf5ec4 disk.c:331
+ xor ah, dh ; 30 f4 ; 0xf5ec7
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf5ec9
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf5ecc disk.c:334
+ cmp ax, 00080h ; 3d 80 00 ; 0xf5ecf
+ jnbe short 05ed8h ; 77 04 ; 0xf5ed2
+ test ax, ax ; 85 c0 ; 0xf5ed4
+ jne short 05f01h ; 75 29 ; 0xf5ed6
+ mov bx, 00da0h ; bb a0 0d ; 0xf5ed8 disk.c:335
+ mov cx, ds ; 8c d9 ; 0xf5edb
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5edd
+ call 018cch ; e8 e9 b9 ; 0xf5ee0
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf5ee3
+ xor ah, ah ; 30 e4 ; 0xf5ee6
+ push ax ; 50 ; 0xf5ee8
+ mov ax, 0067eh ; b8 7e 06 ; 0xf5ee9
+ push ax ; 50 ; 0xf5eec
+ mov ax, 006eah ; b8 ea 06 ; 0xf5eed
+ push ax ; 50 ; 0xf5ef0
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5ef1
+ push ax ; 50 ; 0xf5ef4
+ call 0190fh ; e8 17 ba ; 0xf5ef5
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf5ef8
+ jmp near 061efh ; e9 f1 02 ; 0xf5efb disk.c:336
+ jmp near 060adh ; e9 ac 01 ; 0xf5efe
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf5f01 disk.c:340
+ xor ah, ah ; 30 e4 ; 0xf5f04
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf5f06
+ imul dx ; f7 ea ; 0xf5f09
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf5f0b
+ mov bx, si ; 89 f3 ; 0xf5f0e
+ add bx, ax ; 01 c3 ; 0xf5f10
+ mov ax, word [es:bx+02ch] ; 26 8b 47 2c ; 0xf5f12
+ mov cx, word [es:bx+02ah] ; 26 8b 4f 2a ; 0xf5f16 disk.c:341
+ mov dx, word [es:bx+02eh] ; 26 8b 57 2e ; 0xf5f1a disk.c:342
+ mov word [bp-00ah], dx ; 89 56 f6 ; 0xf5f1e
+ cmp ax, word [bp-006h] ; 3b 46 fa ; 0xf5f21 disk.c:345
+ jbe short 05f2fh ; 76 09 ; 0xf5f24
+ cmp cx, word [bp-008h] ; 3b 4e f8 ; 0xf5f26
+ jbe short 05f2fh ; 76 04 ; 0xf5f29
+ cmp di, dx ; 39 d7 ; 0xf5f2b
+ jbe short 05f60h ; 76 31 ; 0xf5f2d
+ mov bx, 00da0h ; bb a0 0d ; 0xf5f2f disk.c:346
+ mov cx, ds ; 8c d9 ; 0xf5f32
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5f34
+ call 018cch ; e8 92 b9 ; 0xf5f37
+ push di ; 57 ; 0xf5f3a
+ push word [bp-008h] ; ff 76 f8 ; 0xf5f3b
+ push word [bp-006h] ; ff 76 fa ; 0xf5f3e
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf5f41
+ xor ah, ah ; 30 e4 ; 0xf5f44
+ push ax ; 50 ; 0xf5f46
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf5f47
+ push ax ; 50 ; 0xf5f4a
+ mov ax, 0067eh ; b8 7e 06 ; 0xf5f4b
+ push ax ; 50 ; 0xf5f4e
+ mov ax, 00712h ; b8 12 07 ; 0xf5f4f
+ push ax ; 50 ; 0xf5f52
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf5f53
+ push ax ; 50 ; 0xf5f56
+ call 0190fh ; e8 b5 b9 ; 0xf5f57
+ add sp, strict byte 00010h ; 83 c4 10 ; 0xf5f5a
+ jmp near 061efh ; e9 8f 02 ; 0xf5f5d disk.c:347
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf5f60 disk.c:351
+ xor ah, ah ; 30 e4 ; 0xf5f63
+ cmp ax, strict word 00004h ; 3d 04 00 ; 0xf5f65
+ je short 05f8ah ; 74 20 ; 0xf5f68
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf5f6a disk.c:356
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf5f6d
+ imul dx ; f7 ea ; 0xf5f70
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf5f72
+ mov bx, si ; 89 f3 ; 0xf5f75
+ add bx, ax ; 01 c3 ; 0xf5f77
+ cmp cx, word [es:bx+030h] ; 26 3b 4f 30 ; 0xf5f79
+ jne short 05f93h ; 75 14 ; 0xf5f7d
+ mov ax, word [es:bx+034h] ; 26 8b 47 34 ; 0xf5f7f
+ cmp ax, word [bp-00ah] ; 3b 46 f6 ; 0xf5f83
+ je short 05f8dh ; 74 05 ; 0xf5f86
+ jmp short 05f93h ; eb 09 ; 0xf5f88
+ jmp near 060a9h ; e9 1c 01 ; 0xf5f8a
+ cmp byte [bp-002h], 008h ; 80 7e fe 08 ; 0xf5f8d
+ jc short 05fc2h ; 72 2f ; 0xf5f91
+ mov ax, word [bp-006h] ; 8b 46 fa ; 0xf5f93 disk.c:357
+ xor dx, dx ; 31 d2 ; 0xf5f96
+ mov bx, cx ; 89 cb ; 0xf5f98
+ xor cx, cx ; 31 c9 ; 0xf5f9a
+ call 09bc0h ; e8 21 3c ; 0xf5f9c
+ xor bx, bx ; 31 db ; 0xf5f9f
+ add ax, word [bp-008h] ; 03 46 f8 ; 0xf5fa1
+ adc dx, bx ; 11 da ; 0xf5fa4
+ mov bx, word [bp-00ah] ; 8b 5e f6 ; 0xf5fa6
+ xor cx, cx ; 31 c9 ; 0xf5fa9
+ call 09bc0h ; e8 12 3c ; 0xf5fab
+ xor bx, bx ; 31 db ; 0xf5fae
+ add ax, di ; 01 f8 ; 0xf5fb0
+ adc dx, bx ; 11 da ; 0xf5fb2
+ add ax, strict word 0ffffh ; 05 ff ff ; 0xf5fb4
+ mov word [bp-004h], ax ; 89 46 fc ; 0xf5fb7
+ adc dx, strict byte 0ffffh ; 83 d2 ff ; 0xf5fba
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf5fbd
+ xor di, di ; 31 ff ; 0xf5fc0 disk.c:358
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf5fc2 disk.c:365
+ mov word [es:si+018h], strict word 00000h ; 26 c7 44 18 00 00 ; 0xf5fc5
+ mov word [es:si+01ah], strict word 00000h ; 26 c7 44 1a 00 00 ; 0xf5fcb disk.c:366
+ mov word [es:si+01ch], strict word 00000h ; 26 c7 44 1c 00 00 ; 0xf5fd1
+ mov ax, word [bp-004h] ; 8b 46 fc ; 0xf5fd7 disk.c:369
+ mov word [es:si], ax ; 26 89 04 ; 0xf5fda
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf5fdd
+ mov word [es:si+002h], ax ; 26 89 44 02 ; 0xf5fe0
+ mov word [es:si+004h], strict word 00000h ; 26 c7 44 04 00 00 ; 0xf5fe4
+ mov word [es:si+006h], strict word 00000h ; 26 c7 44 06 00 00 ; 0xf5fea
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf5ff0 disk.c:370
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf5ff3
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf5ff6
+ mov word [es:si+00ah], dx ; 26 89 54 0a ; 0xf5ffa
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf5ffe disk.c:371
+ mov word [es:si+00eh], ax ; 26 89 44 0e ; 0xf6001
+ mov word [es:si+010h], 00200h ; 26 c7 44 10 00 02 ; 0xf6005 disk.c:372
+ mov ax, word [bp-006h] ; 8b 46 fa ; 0xf600b disk.c:373
+ mov word [es:si+012h], ax ; 26 89 44 12 ; 0xf600e
+ mov ax, word [bp-008h] ; 8b 46 f8 ; 0xf6012 disk.c:374
+ mov word [es:si+014h], ax ; 26 89 44 14 ; 0xf6015
+ mov word [es:si+016h], di ; 26 89 7c 16 ; 0xf6019 disk.c:375
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf601d disk.c:376
+ mov byte [es:si+00ch], al ; 26 88 44 0c ; 0xf6020
+ xor ah, ah ; 30 e4 ; 0xf6024 disk.c:378
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf6026
+ imul dx ; f7 ea ; 0xf6029
+ mov bx, si ; 89 f3 ; 0xf602b
+ add bx, ax ; 01 c3 ; 0xf602d
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf602f
+ xor ah, ah ; 30 e4 ; 0xf6033
+ mov bx, ax ; 89 c3 ; 0xf6035
+ sal bx, 1 ; d1 e3 ; 0xf6037
+ sal bx, 1 ; d1 e3 ; 0xf6039
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf603b
+ sal ax, 1 ; d1 e0 ; 0xf603e
+ add bx, ax ; 01 c3 ; 0xf6040
+ push ES ; 06 ; 0xf6042
+ push si ; 56 ; 0xf6043
+ call word [word bx+0007eh] ; ff 97 7e 00 ; 0xf6044
+ mov dx, ax ; 89 c2 ; 0xf6048
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf604a disk.c:381
+ xor al, al ; 30 c0 ; 0xf604d
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf604f
+ mov bx, word [es:si+018h] ; 26 8b 5c 18 ; 0xf6052
+ or bx, ax ; 09 c3 ; 0xf6056
+ mov word [bp+016h], bx ; 89 5e 16 ; 0xf6058
+ test dl, dl ; 84 d2 ; 0xf605b disk.c:383
+ je short 060a9h ; 74 4a ; 0xf605d
+ mov bx, 00da0h ; bb a0 0d ; 0xf605f disk.c:384
+ mov cx, ds ; 8c d9 ; 0xf6062
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6064
+ call 018cch ; e8 62 b8 ; 0xf6067
+ mov al, dl ; 88 d0 ; 0xf606a
+ xor ah, ah ; 30 e4 ; 0xf606c
+ push ax ; 50 ; 0xf606e
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf606f
+ push ax ; 50 ; 0xf6072
+ mov ax, 0067eh ; b8 7e 06 ; 0xf6073
+ push ax ; 50 ; 0xf6076
+ mov ax, 00759h ; b8 59 07 ; 0xf6077
+ push ax ; 50 ; 0xf607a
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf607b
+ push ax ; 50 ; 0xf607e
+ call 0190fh ; e8 8d b8 ; 0xf607f
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf6082
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6085 disk.c:385
+ xor ah, ah ; 30 e4 ; 0xf6088
+ or ah, 00ch ; 80 cc 0c ; 0xf608a
+ jmp near 061f7h ; e9 67 01 ; 0xf608d disk.c:386
+ mov bx, 00da0h ; bb a0 0d ; 0xf6090 disk.c:393
+ mov cx, ds ; 8c d9 ; 0xf6093
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6095
+ call 018cch ; e8 31 b8 ; 0xf6098
+ mov ax, 0077ah ; b8 7a 07 ; 0xf609b
+ push ax ; 50 ; 0xf609e
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf609f
+ push ax ; 50 ; 0xf60a2
+ call 0190fh ; e8 69 b8 ; 0xf60a3
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf60a6
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf60a9 disk.c:394
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf60ad
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf60b0
+ mov es, ax ; 8e c0 ; 0xf60b3
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf60b5
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf60b9
+ mov sp, bp ; 89 ec ; 0xf60bd
+ pop bp ; 5d ; 0xf60bf
+ retn ; c3 ; 0xf60c0
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf60c1 disk.c:400
+ xor ah, ah ; 30 e4 ; 0xf60c4
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf60c6
+ imul dx ; f7 ea ; 0xf60c9
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf60cb
+ mov bx, si ; 89 f3 ; 0xf60ce
+ add bx, ax ; 01 c3 ; 0xf60d0
+ mov di, word [es:bx+02ch] ; 26 8b 7f 2c ; 0xf60d2
+ mov cx, word [es:bx+02ah] ; 26 8b 4f 2a ; 0xf60d6 disk.c:401
+ mov ax, word [es:bx+02eh] ; 26 8b 47 2e ; 0xf60da disk.c:402
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf60de
+ mov dl, byte [es:si+001e2h] ; 26 8a 94 e2 01 ; 0xf60e1 disk.c:404
+ xor dh, dh ; 30 f6 ; 0xf60e6
+ mov byte [bp+016h], dh ; 88 76 16 ; 0xf60e8 disk.c:407
+ mov bx, word [bp+014h] ; 8b 5e 14 ; 0xf60eb disk.c:408
+ dec di ; 4f ; 0xf60ee disk.c:406
+ mov ax, di ; 89 f8 ; 0xf60ef
+ mov bh, al ; 88 c7 ; 0xf60f1
+ mov word [bp+014h], bx ; 89 5e 14 ; 0xf60f3
+ shr di, 1 ; d1 ef ; 0xf60f6 disk.c:409
+ shr di, 1 ; d1 ef ; 0xf60f8
+ and di, 000c0h ; 81 e7 c0 00 ; 0xf60fa
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf60fe
+ and ax, strict word 0003fh ; 25 3f 00 ; 0xf6101
+ or di, ax ; 09 c7 ; 0xf6104
+ mov ax, bx ; 89 d8 ; 0xf6106
+ xor al, bl ; 30 d8 ; 0xf6108
+ or ax, di ; 09 f8 ; 0xf610a
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf610c
+ mov bx, word [bp+012h] ; 8b 5e 12 ; 0xf610f disk.c:410
+ xor bh, bh ; 30 ff ; 0xf6112
+ mov ah, cl ; 88 cc ; 0xf6114
+ xor al, al ; 30 c0 ; 0xf6116
+ sub ax, 00100h ; 2d 00 01 ; 0xf6118
+ or bx, ax ; 09 c3 ; 0xf611b
+ mov word [bp+012h], bx ; 89 5e 12 ; 0xf611d
+ mov ax, bx ; 89 d8 ; 0xf6120 disk.c:411
+ xor al, bl ; 30 d8 ; 0xf6122
+ or ax, dx ; 09 d0 ; 0xf6124
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf6126
+ jmp near 060a9h ; e9 7d ff ; 0xf6129 disk.c:416
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf612c disk.c:423
+ xor ah, ah ; 30 e4 ; 0xf612f
+ cwd ; 99 ; 0xf6131
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf6132
+ sar ax, 1 ; d1 f8 ; 0xf6134
+ mov dx, strict word 00006h ; ba 06 00 ; 0xf6136
+ imul dx ; f7 ea ; 0xf6139
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf613b
+ add si, ax ; 01 c6 ; 0xf613e
+ mov dx, word [es:si+00206h] ; 26 8b 94 06 02 ; 0xf6140
+ add dx, strict byte 00007h ; 83 c2 07 ; 0xf6145
+ in AL, DX ; ec ; 0xf6148
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6149
+ and AL, strict byte 0c0h ; 24 c0 ; 0xf614b disk.c:424
+ cmp AL, strict byte 040h ; 3c 40 ; 0xf614d
+ jne short 06154h ; 75 03 ; 0xf614f
+ jmp near 060a9h ; e9 55 ff ; 0xf6151 disk.c:425
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6154 disk.c:427
+ xor ah, ah ; 30 e4 ; 0xf6157
+ or ah, 0aah ; 80 cc aa ; 0xf6159
+ jmp near 061f7h ; e9 98 00 ; 0xf615c
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf615f disk.c:435
+ xor ah, ah ; 30 e4 ; 0xf6162
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf6164
+ imul dx ; f7 ea ; 0xf6167
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf6169
+ add si, ax ; 01 c6 ; 0xf616c
+ mov ax, word [es:si+032h] ; 26 8b 44 32 ; 0xf616e
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf6172
+ mov ax, word [es:si+030h] ; 26 8b 44 30 ; 0xf6175 disk.c:436
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf6179
+ mov di, word [es:si+034h] ; 26 8b 7c 34 ; 0xf617c disk.c:437
+ mov ax, word [bp-006h] ; 8b 46 fa ; 0xf6180 disk.c:440
+ xor dx, dx ; 31 d2 ; 0xf6183
+ mov bx, word [bp-008h] ; 8b 5e f8 ; 0xf6185
+ xor cx, cx ; 31 c9 ; 0xf6188
+ call 09bc0h ; e8 33 3a ; 0xf618a
+ mov bx, di ; 89 fb ; 0xf618d
+ xor cx, cx ; 31 c9 ; 0xf618f
+ call 09bc0h ; e8 2c 3a ; 0xf6191
+ mov word [bp-004h], ax ; 89 46 fc ; 0xf6194
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf6197
+ mov word [bp+014h], dx ; 89 56 14 ; 0xf619a disk.c:441
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf619d disk.c:442
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf61a0 disk.c:444
+ xor ah, ah ; 30 e4 ; 0xf61a3
+ or ah, 003h ; 80 cc 03 ; 0xf61a5
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf61a8
+ jmp near 060adh ; e9 ff fe ; 0xf61ab disk.c:445
+ mov bx, 00da0h ; bb a0 0d ; 0xf61ae disk.c:453
+ mov cx, ds ; 8c d9 ; 0xf61b1
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf61b3
+ call 018cch ; e8 13 b7 ; 0xf61b6
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf61b9
+ xor ah, ah ; 30 e4 ; 0xf61bc
+ push ax ; 50 ; 0xf61be
+ mov ax, 0067eh ; b8 7e 06 ; 0xf61bf
+ push ax ; 50 ; 0xf61c2
+ mov ax, 00794h ; b8 94 07 ; 0xf61c3
+ push ax ; 50 ; 0xf61c6
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf61c7
+ push ax ; 50 ; 0xf61ca
+ call 0190fh ; e8 41 b7 ; 0xf61cb
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf61ce
+ jmp near 060a9h ; e9 d5 fe ; 0xf61d1 disk.c:454
+ mov bx, 00da0h ; bb a0 0d ; 0xf61d4 disk.c:461
+ mov cx, ds ; 8c d9 ; 0xf61d7
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf61d9
+ call 018cch ; e8 ed b6 ; 0xf61dc
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf61df
+ xor ah, ah ; 30 e4 ; 0xf61e2
+ push ax ; 50 ; 0xf61e4
+ mov ax, 0067eh ; b8 7e 06 ; 0xf61e5
+ push ax ; 50 ; 0xf61e8
+ mov ax, 007c7h ; b8 c7 07 ; 0xf61e9
+ jmp near 05ef0h ; e9 01 fd ; 0xf61ec
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf61ef disk.c:467
+ xor ah, ah ; 30 e4 ; 0xf61f2
+ or ah, 001h ; 80 cc 01 ; 0xf61f4
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf61f7
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf61fa disk.c:469
+ xor ah, ah ; 30 e4 ; 0xf61fd
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf61ff disk.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf6202
+ mov es, dx ; 8e c2 ; 0xf6205
+ mov byte [es:bx], al ; 26 88 07 ; 0xf6207
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf620a disk.c:471
+ jmp near 060bdh ; e9 ac fe ; 0xf620e disk.c:472
+ ; disGetNextSymbol 0xf6211 LB 0x3d37 -> off=0x20 cb=00000000000002a8 uValue=00000000000f4c31 'int13_harddisk_ext'
+ db 0bfh, 062h, 0f2h, 062h, 0f2h, 062h, 0f2h, 062h, 0c1h, 064h, 06dh, 064h, 0f2h, 062h, 072h, 064h
+ db 0c1h, 064h, 0d7h, 062h, 0d7h, 062h, 0d7h, 062h, 0d7h, 062h, 08ah, 064h, 0d7h, 062h, 0d7h, 062h
+int13_harddisk_ext: ; 0xf6231 LB 0x2a8
+ push bp ; 55 ; 0xf6231 disk.c:482
+ mov bp, sp ; 89 e5 ; 0xf6232
+ sub sp, strict byte 00016h ; 83 ec 16 ; 0xf6234
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf6237 disk.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf623a
+ mov es, ax ; 8e c0 ; 0xf623d
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf623f
+ mov di, 00122h ; bf 22 01 ; 0xf6242 disk.c:49
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf6245
+ mov bx, 0008eh ; bb 8e 00 ; 0xf6248 disk.c:43
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf624b
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf624f disk.c:506
+ xor ah, ah ; 30 e4 ; 0xf6252
+ cmp ax, 00080h ; 3d 80 00 ; 0xf6254
+ jc short 0625eh ; 72 05 ; 0xf6257
+ cmp ax, 00090h ; 3d 90 00 ; 0xf6259
+ jc short 0627dh ; 72 1f ; 0xf625c
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf625e disk.c:507
+ xor ah, ah ; 30 e4 ; 0xf6261
+ push ax ; 50 ; 0xf6263
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf6264
+ push ax ; 50 ; 0xf6267
+ mov ax, 007f5h ; b8 f5 07 ; 0xf6268
+ push ax ; 50 ; 0xf626b
+ mov ax, 0068dh ; b8 8d 06 ; 0xf626c
+ push ax ; 50 ; 0xf626f
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6270
+ push ax ; 50 ; 0xf6273
+ call 0190fh ; e8 98 b6 ; 0xf6274
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf6277
+ jmp near 064a0h ; e9 23 02 ; 0xf627a disk.c:508
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf627d disk.c:512
+ xor ah, ah ; 30 e4 ; 0xf6280
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf6282
+ mov bx, di ; 89 fb ; 0xf6285
+ add bx, ax ; 01 c3 ; 0xf6287
+ mov dl, byte [es:bx+00163h] ; 26 8a 97 63 01 ; 0xf6289
+ mov byte [bp-002h], dl ; 88 56 fe ; 0xf628e
+ cmp dl, 010h ; 80 fa 10 ; 0xf6291 disk.c:515
+ jc short 062a4h ; 72 0e ; 0xf6294
+ push ax ; 50 ; 0xf6296 disk.c:516
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf6297
+ push ax ; 50 ; 0xf629a
+ mov ax, 007f5h ; b8 f5 07 ; 0xf629b
+ push ax ; 50 ; 0xf629e
+ mov ax, 006b8h ; b8 b8 06 ; 0xf629f
+ jmp short 0626fh ; eb cb ; 0xf62a2
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf62a4 disk.c:520
+ xor ah, ah ; 30 e4 ; 0xf62a7
+ sub ax, strict word 00041h ; 2d 41 00 ; 0xf62a9
+ cmp ax, strict word 0000fh ; 3d 0f 00 ; 0xf62ac
+ jnbe short 062d7h ; 77 26 ; 0xf62af
+ mov bx, ax ; 89 c3 ; 0xf62b1
+ sal bx, 1 ; d1 e3 ; 0xf62b3
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf62b5
+ xor ah, ah ; 30 e4 ; 0xf62b8
+ jmp word [cs:bx+06211h] ; 2e ff a7 11 62 ; 0xf62ba
+ mov word [bp+010h], 0aa55h ; c7 46 10 55 aa ; 0xf62bf disk.c:522
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf62c4 disk.c:523
+ xor ah, ah ; 30 e4 ; 0xf62c7
+ or ah, 030h ; 80 cc 30 ; 0xf62c9
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf62cc
+ mov word [bp+014h], strict word 00007h ; c7 46 14 07 00 ; 0xf62cf disk.c:524
+ jmp near 064c5h ; e9 ee 01 ; 0xf62d4 disk.c:525
+ mov bx, 00da0h ; bb a0 0d ; 0xf62d7
+ mov cx, ds ; 8c d9 ; 0xf62da
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf62dc
+ call 018cch ; e8 ea b5 ; 0xf62df
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf62e2
+ xor ah, ah ; 30 e4 ; 0xf62e5
+ push ax ; 50 ; 0xf62e7
+ mov ax, 007f5h ; b8 f5 07 ; 0xf62e8
+ push ax ; 50 ; 0xf62eb
+ mov ax, 007c7h ; b8 c7 07 ; 0xf62ec
+ jmp near 0639bh ; e9 a9 00 ; 0xf62ef
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf62f2 disk.c:534
+ mov word [bp-016h], bx ; 89 5e ea ; 0xf62f5
+ mov es, [bp+004h] ; 8e 46 04 ; 0xf62f8
+ mov word [bp-012h], bx ; 89 5e ee ; 0xf62fb
+ mov [bp-010h], es ; 8c 46 f0 ; 0xf62fe
+ mov ax, word [es:bx+002h] ; 26 8b 47 02 ; 0xf6301 disk.c:536
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf6305
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf6308 disk.c:537
+ mov word [bp-00eh], ax ; 89 46 f2 ; 0xf630c
+ mov ax, word [es:bx+004h] ; 26 8b 47 04 ; 0xf630f disk.c:538
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf6313
+ mov si, bx ; 89 de ; 0xf6316 disk.c:541
+ mov si, word [es:si+00ch] ; 26 8b 74 0c ; 0xf6318
+ mov cx, word [es:bx+00eh] ; 26 8b 4f 0e ; 0xf631c
+ xor ax, ax ; 31 c0 ; 0xf6320 disk.c:542
+ xor bx, bx ; 31 db ; 0xf6322
+ mov dx, si ; 89 f2 ; 0xf6324
+ mov si, strict word 00020h ; be 20 00 ; 0xf6326
+ call 09c20h ; e8 f4 38 ; 0xf6329
+ mov word [bp-004h], ax ; 89 46 fc ; 0xf632c
+ mov word [bp-006h], bx ; 89 5e fa ; 0xf632f
+ mov si, dx ; 89 d6 ; 0xf6332
+ mov bx, word [bp-016h] ; 8b 5e ea ; 0xf6334 disk.c:543
+ mov dx, word [es:bx+008h] ; 26 8b 57 08 ; 0xf6337
+ mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xf633b
+ or si, dx ; 09 d6 ; 0xf633f
+ or cx, ax ; 09 c1 ; 0xf6341
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf6343 disk.c:548
+ xor ah, ah ; 30 e4 ; 0xf6346
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf6348
+ imul dx ; f7 ea ; 0xf634b
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf634d
+ mov bx, di ; 89 fb ; 0xf6350
+ add bx, ax ; 01 c3 ; 0xf6352
+ mov al, byte [es:bx+022h] ; 26 8a 47 22 ; 0xf6354
+ mov dx, word [bp-004h] ; 8b 56 fc ; 0xf6358 disk.c:549
+ cmp dx, word [es:bx+03ch] ; 26 3b 57 3c ; 0xf635b
+ jnbe short 06383h ; 77 22 ; 0xf635f
+ jne short 063a9h ; 75 46 ; 0xf6361
+ mov dx, word [bp-006h] ; 8b 56 fa ; 0xf6363
+ cmp dx, word [es:bx+03ah] ; 26 3b 57 3a ; 0xf6366
+ jnbe short 06383h ; 77 17 ; 0xf636a
+ mov dx, word [bp-006h] ; 8b 56 fa ; 0xf636c
+ cmp dx, word [es:bx+03ah] ; 26 3b 57 3a ; 0xf636f
+ jne short 063a9h ; 75 34 ; 0xf6373
+ cmp cx, word [es:bx+038h] ; 26 3b 4f 38 ; 0xf6375
+ jnbe short 06383h ; 77 08 ; 0xf6379
+ jne short 063a9h ; 75 2c ; 0xf637b
+ cmp si, word [es:bx+036h] ; 26 3b 77 36 ; 0xf637d
+ jc short 063a9h ; 72 26 ; 0xf6381
+ mov bx, 00da0h ; bb a0 0d ; 0xf6383 disk.c:550
+ mov cx, ds ; 8c d9 ; 0xf6386
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6388
+ call 018cch ; e8 3e b5 ; 0xf638b
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf638e
+ xor ah, ah ; 30 e4 ; 0xf6391
+ push ax ; 50 ; 0xf6393
+ mov ax, 007f5h ; b8 f5 07 ; 0xf6394
+ push ax ; 50 ; 0xf6397
+ mov ax, 00808h ; b8 08 08 ; 0xf6398
+ push ax ; 50 ; 0xf639b
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf639c
+ push ax ; 50 ; 0xf639f
+ call 0190fh ; e8 6c b5 ; 0xf63a0
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf63a3
+ jmp near 064a0h ; e9 f7 00 ; 0xf63a6 disk.c:551
+ mov ah, byte [bp+017h] ; 8a 66 17 ; 0xf63a9 disk.c:555
+ mov byte [bp-008h], ah ; 88 66 f8 ; 0xf63ac
+ mov byte [bp-007h], 000h ; c6 46 f9 00 ; 0xf63af
+ cmp word [bp-008h], strict byte 00044h ; 83 7e f8 44 ; 0xf63b3
+ je short 063bfh ; 74 06 ; 0xf63b7
+ cmp word [bp-008h], strict byte 00047h ; 83 7e f8 47 ; 0xf63b9
+ jne short 063c2h ; 75 03 ; 0xf63bd
+ jmp near 064c1h ; e9 ff 00 ; 0xf63bf disk.c:556
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf63c2 disk.c:559
+ mov word [es:di+018h], strict word 00000h ; 26 c7 45 18 00 00 ; 0xf63c5
+ mov word [es:di+01ah], strict word 00000h ; 26 c7 45 1a 00 00 ; 0xf63cb disk.c:560
+ mov word [es:di+01ch], strict word 00000h ; 26 c7 45 1c 00 00 ; 0xf63d1
+ mov dx, word [bp-004h] ; 8b 56 fc ; 0xf63d7 disk.c:563
+ mov word [es:di+006h], dx ; 26 89 55 06 ; 0xf63da
+ mov dx, word [bp-006h] ; 8b 56 fa ; 0xf63de
+ mov word [es:di+004h], dx ; 26 89 55 04 ; 0xf63e1
+ mov word [es:di+002h], cx ; 26 89 4d 02 ; 0xf63e5
+ mov word [es:di], si ; 26 89 35 ; 0xf63e9
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf63ec disk.c:564
+ mov word [es:di+008h], dx ; 26 89 55 08 ; 0xf63ef
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf63f3
+ mov word [es:di+00ah], dx ; 26 89 55 0a ; 0xf63f6
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf63fa disk.c:565
+ mov word [es:di+00eh], dx ; 26 89 55 0e ; 0xf63fd
+ mov word [es:di+010h], 00200h ; 26 c7 45 10 00 02 ; 0xf6401 disk.c:566
+ mov word [es:di+016h], strict word 00000h ; 26 c7 45 16 00 00 ; 0xf6407 disk.c:567
+ mov ah, byte [bp-002h] ; 8a 66 fe ; 0xf640d disk.c:568
+ mov byte [es:di+00ch], ah ; 26 88 65 0c ; 0xf6410
+ mov bx, word [bp-008h] ; 8b 5e f8 ; 0xf6414 disk.c:571
+ sal bx, 1 ; d1 e3 ; 0xf6417
+ xor ah, ah ; 30 e4 ; 0xf6419
+ sal ax, 1 ; d1 e0 ; 0xf641b
+ sal ax, 1 ; d1 e0 ; 0xf641d
+ add bx, ax ; 01 c3 ; 0xf641f
+ push ES ; 06 ; 0xf6421
+ push di ; 57 ; 0xf6422
+ call word [word bx-00002h] ; ff 97 fe ff ; 0xf6423
+ mov dx, ax ; 89 c2 ; 0xf6427
+ mov es, [bp-014h] ; 8e 46 ec ; 0xf6429 disk.c:572
+ mov ax, word [es:di+018h] ; 26 8b 45 18 ; 0xf642c
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf6430
+ les bx, [bp-012h] ; c4 5e ee ; 0xf6433 disk.c:573
+ mov word [es:bx+002h], ax ; 26 89 47 02 ; 0xf6436
+ test dl, dl ; 84 d2 ; 0xf643a disk.c:575
+ je short 063bfh ; 74 81 ; 0xf643c
+ mov bx, 00da0h ; bb a0 0d ; 0xf643e disk.c:576
+ mov cx, ds ; 8c d9 ; 0xf6441
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6443
+ call 018cch ; e8 83 b4 ; 0xf6446
+ mov al, dl ; 88 d0 ; 0xf6449
+ xor ah, ah ; 30 e4 ; 0xf644b
+ push ax ; 50 ; 0xf644d
+ push word [bp-008h] ; ff 76 f8 ; 0xf644e
+ mov ax, 007f5h ; b8 f5 07 ; 0xf6451
+ push ax ; 50 ; 0xf6454
+ mov ax, 00759h ; b8 59 07 ; 0xf6455
+ push ax ; 50 ; 0xf6458
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6459
+ push ax ; 50 ; 0xf645c
+ call 0190fh ; e8 af b4 ; 0xf645d
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf6460
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf6463 disk.c:577
+ xor ah, ah ; 30 e4 ; 0xf6466
+ or ah, 00ch ; 80 cc 0c ; 0xf6468
+ jmp short 064a8h ; eb 3b ; 0xf646b disk.c:578
+ or ah, 0b2h ; 80 cc b2 ; 0xf646d disk.c:590
+ jmp short 064a8h ; eb 36 ; 0xf6470
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf6472 disk.c:595
+ push ax ; 50 ; 0xf6475
+ mov ax, word [bp+00ah] ; 8b 46 0a ; 0xf6476
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf6479
+ mov bx, di ; 89 fb ; 0xf647c
+ mov cx, word [bp-014h] ; 8b 4e ec ; 0xf647e
+ call 05a95h ; e8 11 f6 ; 0xf6481
+ test ax, ax ; 85 c0 ; 0xf6484
+ je short 064c1h ; 74 39 ; 0xf6486
+ jmp short 064a0h ; eb 16 ; 0xf6488 disk.c:596
+ cmp ax, strict word 00006h ; 3d 06 00 ; 0xf648a disk.c:603
+ je short 064c1h ; 74 32 ; 0xf648d
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf648f
+ jc short 064a0h ; 72 0c ; 0xf6492
+ jbe short 064c1h ; 76 2b ; 0xf6494
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf6496
+ jc short 064a0h ; 72 05 ; 0xf6499
+ cmp ax, strict word 00004h ; 3d 04 00 ; 0xf649b
+ jbe short 064c1h ; 76 21 ; 0xf649e
+ mov ax, word [bp+016h] ; 8b 46 16 ; 0xf64a0 disk.c:623
+ xor ah, ah ; 30 e4 ; 0xf64a3
+ or ah, 001h ; 80 cc 01 ; 0xf64a5
+ mov word [bp+016h], ax ; 89 46 16 ; 0xf64a8
+ mov al, byte [bp+017h] ; 8a 46 17 ; 0xf64ab disk.c:625
+ xor ah, ah ; 30 e4 ; 0xf64ae
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf64b0 disk.c:43
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf64b3
+ mov es, dx ; 8e c2 ; 0xf64b6
+ mov byte [es:bx], al ; 26 88 07 ; 0xf64b8
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf64bb disk.c:626
+ jmp short 064d5h ; eb 14 ; 0xf64bf disk.c:627
+ mov byte [bp+017h], 000h ; c6 46 17 00 ; 0xf64c1 disk.c:630
+ mov bx, strict word 00074h ; bb 74 00 ; 0xf64c5 disk.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf64c8
+ mov es, ax ; 8e c0 ; 0xf64cb
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf64cd
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf64d1 disk.c:633
+ mov sp, bp ; 89 ec ; 0xf64d5 disk.c:635
+ pop bp ; 5d ; 0xf64d7
+ retn ; c3 ; 0xf64d8
+ ; disGetNextSymbol 0xf64d9 LB 0x3a6f -> off=0x0 cb=0000000000000153 uValue=00000000000f4ed9 'int14_function'
+int14_function: ; 0xf64d9 LB 0x153
+ push bp ; 55 ; 0xf64d9 serial.c:60
+ mov bp, sp ; 89 e5 ; 0xf64da
+ push si ; 56 ; 0xf64dc
+ push di ; 57 ; 0xf64dd
+ sti ; fb ; 0xf64de serial.c:65
+ mov si, word [bp+00eh] ; 8b 76 0e ; 0xf64df serial.c:67
+ sal si, 1 ; d1 e6 ; 0xf64e2
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf64e4 serial.c:48
+ mov es, ax ; 8e c0 ; 0xf64e7
+ mov si, word [es:si] ; 26 8b 34 ; 0xf64e9
+ mov bx, si ; 89 f3 ; 0xf64ec serial.c:49
+ mov di, word [bp+00eh] ; 8b 7e 0e ; 0xf64ee serial.c:68
+ add di, strict byte 0007ch ; 83 c7 7c ; 0xf64f1
+ mov cl, byte [es:di] ; 26 8a 0d ; 0xf64f4 serial.c:38
+ cmp word [bp+00eh], strict byte 00004h ; 83 7e 0e 04 ; 0xf64f7 serial.c:69
+ jnc short 06501h ; 73 04 ; 0xf64fb
+ test si, si ; 85 f6 ; 0xf64fd
+ jnbe short 06504h ; 77 03 ; 0xf64ff
+ jmp near 06621h ; e9 1d 01 ; 0xf6501
+ mov al, byte [bp+013h] ; 8a 46 13 ; 0xf6504 serial.c:70
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf6507
+ jc short 06518h ; 72 0d ; 0xf6509
+ jbe short 06578h ; 76 6b ; 0xf650b
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf650d
+ je short 06570h ; 74 5f ; 0xf650f
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf6511
+ je short 06573h ; 74 5e ; 0xf6513
+ jmp near 0661bh ; e9 03 01 ; 0xf6515
+ test al, al ; 84 c0 ; 0xf6518
+ jne short 06575h ; 75 59 ; 0xf651a
+ lea dx, [bx+003h] ; 8d 57 03 ; 0xf651c serial.c:72
+ in AL, DX ; ec ; 0xf651f
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6520
+ or AL, strict byte 080h ; 0c 80 ; 0xf6522
+ out DX, AL ; ee ; 0xf6524
+ lea si, [bx+001h] ; 8d 77 01 ; 0xf6525
+ mov al, byte [bp+012h] ; 8a 46 12 ; 0xf6528 serial.c:73
+ test AL, strict byte 0e0h ; a8 e0 ; 0xf652b
+ jne short 0653bh ; 75 0c ; 0xf652d
+ mov AL, strict byte 017h ; b0 17 ; 0xf652f serial.c:74
+ mov dx, bx ; 89 da ; 0xf6531
+ out DX, AL ; ee ; 0xf6533
+ mov AL, strict byte 004h ; b0 04 ; 0xf6534 serial.c:75
+ mov dx, si ; 89 f2 ; 0xf6536
+ out DX, AL ; ee ; 0xf6538
+ jmp short 06552h ; eb 17 ; 0xf6539 serial.c:76
+ and AL, strict byte 0e0h ; 24 e0 ; 0xf653b serial.c:77
+ xor ah, ah ; 30 e4 ; 0xf653d
+ mov CL, strict byte 005h ; b1 05 ; 0xf653f
+ sar ax, CL ; d3 f8 ; 0xf6541
+ mov cl, al ; 88 c1 ; 0xf6543
+ mov ax, 00600h ; b8 00 06 ; 0xf6545
+ sar ax, CL ; d3 f8 ; 0xf6548
+ mov dx, bx ; 89 da ; 0xf654a serial.c:78
+ out DX, AL ; ee ; 0xf654c
+ mov al, ah ; 88 e0 ; 0xf654d serial.c:79
+ mov dx, si ; 89 f2 ; 0xf654f
+ out DX, AL ; ee ; 0xf6551
+ mov al, byte [bp+012h] ; 8a 46 12 ; 0xf6552 serial.c:81
+ and AL, strict byte 01fh ; 24 1f ; 0xf6555
+ lea dx, [bx+003h] ; 8d 57 03 ; 0xf6557
+ out DX, AL ; ee ; 0xf655a
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf655b serial.c:82
+ in AL, DX ; ec ; 0xf655e
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf655f
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf6561
+ lea dx, [bx+006h] ; 8d 57 06 ; 0xf6564 serial.c:83
+ in AL, DX ; ec ; 0xf6567
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6568
+ mov byte [bp+012h], al ; 88 46 12 ; 0xf656a
+ jmp near 065fch ; e9 8c 00 ; 0xf656d
+ jmp near 0660ah ; e9 97 00 ; 0xf6570
+ jmp short 065c3h ; eb 4e ; 0xf6573
+ jmp near 0661bh ; e9 a3 00 ; 0xf6575
+ mov si, strict word 0006ch ; be 6c 00 ; 0xf6578 serial.c:48
+ mov si, word [es:si] ; 26 8b 34 ; 0xf657b
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf657e serial.c:88
+ in AL, DX ; ec ; 0xf6581
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6582
+ and ax, strict word 00060h ; 25 60 00 ; 0xf6584
+ cmp ax, strict word 00060h ; 3d 60 00 ; 0xf6587
+ je short 065a5h ; 74 19 ; 0xf658a
+ test cl, cl ; 84 c9 ; 0xf658c
+ je short 065a5h ; 74 15 ; 0xf658e
+ mov di, strict word 0006ch ; bf 6c 00 ; 0xf6590 serial.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf6593
+ mov es, ax ; 8e c0 ; 0xf6596
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf6598
+ cmp ax, si ; 39 f0 ; 0xf659b serial.c:90
+ je short 0657eh ; 74 df ; 0xf659d
+ mov si, ax ; 89 c6 ; 0xf659f serial.c:91
+ db 0feh, 0c9h
+ ; dec cl ; fe c9 ; 0xf65a1 serial.c:92
+ jmp short 0657eh ; eb d9 ; 0xf65a3 serial.c:94
+ test cl, cl ; 84 c9 ; 0xf65a5 serial.c:95
+ je short 065afh ; 74 06 ; 0xf65a7
+ mov al, byte [bp+012h] ; 8a 46 12 ; 0xf65a9
+ mov dx, bx ; 89 da ; 0xf65ac
+ out DX, AL ; ee ; 0xf65ae
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf65af serial.c:96
+ in AL, DX ; ec ; 0xf65b2
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf65b3
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf65b5
+ test cl, cl ; 84 c9 ; 0xf65b8 serial.c:97
+ jne short 065fch ; 75 40 ; 0xf65ba
+ or AL, strict byte 080h ; 0c 80 ; 0xf65bc
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf65be
+ jmp short 065fch ; eb 39 ; 0xf65c1
+ mov si, strict word 0006ch ; be 6c 00 ; 0xf65c3 serial.c:48
+ mov si, word [es:si] ; 26 8b 34 ; 0xf65c6
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf65c9 serial.c:102
+ in AL, DX ; ec ; 0xf65cc
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf65cd
+ test AL, strict byte 001h ; a8 01 ; 0xf65cf
+ jne short 065ech ; 75 19 ; 0xf65d1
+ test cl, cl ; 84 c9 ; 0xf65d3
+ je short 065ech ; 74 15 ; 0xf65d5
+ mov di, strict word 0006ch ; bf 6c 00 ; 0xf65d7 serial.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf65da
+ mov es, ax ; 8e c0 ; 0xf65dd
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf65df
+ cmp ax, si ; 39 f0 ; 0xf65e2 serial.c:104
+ je short 065c9h ; 74 e3 ; 0xf65e4
+ mov si, ax ; 89 c6 ; 0xf65e6 serial.c:105
+ db 0feh, 0c9h
+ ; dec cl ; fe c9 ; 0xf65e8 serial.c:106
+ jmp short 065c9h ; eb dd ; 0xf65ea serial.c:108
+ test cl, cl ; 84 c9 ; 0xf65ec serial.c:109
+ je short 06602h ; 74 12 ; 0xf65ee
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf65f0 serial.c:110
+ mov dx, bx ; 89 da ; 0xf65f4 serial.c:111
+ in AL, DX ; ec ; 0xf65f6
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf65f7
+ mov byte [bp+012h], al ; 88 46 12 ; 0xf65f9
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf65fc serial.c:112
+ jmp short 06625h ; eb 23 ; 0xf6600
+ lea dx, [bx+005h] ; 8d 57 05 ; 0xf6602 serial.c:113
+ in AL, DX ; ec ; 0xf6605
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6606
+ jmp short 065beh ; eb b4 ; 0xf6608
+ lea dx, [si+005h] ; 8d 54 05 ; 0xf660a serial.c:118
+ in AL, DX ; ec ; 0xf660d
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf660e
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf6610
+ lea dx, [si+006h] ; 8d 54 06 ; 0xf6613 serial.c:119
+ in AL, DX ; ec ; 0xf6616
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6617
+ jmp short 065f9h ; eb de ; 0xf6619
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf661b serial.c:123
+ jmp short 06625h ; eb 04 ; 0xf661f serial.c:125
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf6621 serial.c:126
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf6625 serial.c:128
+ pop di ; 5f ; 0xf6628
+ pop si ; 5e ; 0xf6629
+ pop bp ; 5d ; 0xf662a
+ retn ; c3 ; 0xf662b
+ ; disGetNextSymbol 0xf662c LB 0x391c -> off=0x0 cb=0000000000000043 uValue=00000000000f502c 'timer_wait'
+timer_wait: ; 0xf662c LB 0x43
+ push bp ; 55 ; 0xf662c system.c:289
+ mov bp, sp ; 89 e5 ; 0xf662d
+ push bx ; 53 ; 0xf662f
+ push cx ; 51 ; 0xf6630
+ push ax ; 50 ; 0xf6631
+ mov bx, strict word 0000fh ; bb 0f 00 ; 0xf6632 system.c:296
+ xor cx, cx ; 31 c9 ; 0xf6635
+ call 09be0h ; e8 a6 35 ; 0xf6637
+ mov cx, ax ; 89 c1 ; 0xf663a
+ mov bx, dx ; 89 d3 ; 0xf663c
+ mov dx, strict word 00061h ; ba 61 00 ; 0xf663e system.c:298
+ in AL, DX ; ec ; 0xf6641
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6642
+ and AL, strict byte 010h ; 24 10 ; 0xf6644
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf6646
+ add cx, strict byte 0ffffh ; 83 c1 ff ; 0xf6649 system.c:299
+ adc bx, strict byte 0ffffh ; 83 d3 ff ; 0xf664c
+ cmp bx, strict byte 0ffffh ; 83 fb ff ; 0xf664f
+ jne short 06659h ; 75 05 ; 0xf6652
+ cmp cx, strict byte 0ffffh ; 83 f9 ff ; 0xf6654
+ je short 06668h ; 74 0f ; 0xf6657
+ mov dx, strict word 00061h ; ba 61 00 ; 0xf6659 system.c:302
+ in AL, DX ; ec ; 0xf665c
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf665d
+ and AL, strict byte 010h ; 24 10 ; 0xf665f
+ cmp al, byte [bp-006h] ; 3a 46 fa ; 0xf6661 system.c:303
+ jne short 06659h ; 75 f3 ; 0xf6664
+ jmp short 06649h ; eb e1 ; 0xf6666 system.c:305
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf6668 system.c:306
+ pop cx ; 59 ; 0xf666b
+ pop bx ; 5b ; 0xf666c
+ pop bp ; 5d ; 0xf666d
+ retn ; c3 ; 0xf666e
+ ; disGetNextSymbol 0xf666f LB 0x38d9 -> off=0x0 cb=0000000000000030 uValue=00000000000f506f 'set_enable_a20'
+set_enable_a20: ; 0xf666f LB 0x30
+ push bp ; 55 ; 0xf666f system.c:308
+ mov bp, sp ; 89 e5 ; 0xf6670
+ push bx ; 53 ; 0xf6672
+ push cx ; 51 ; 0xf6673
+ push dx ; 52 ; 0xf6674
+ mov bx, ax ; 89 c3 ; 0xf6675
+ mov dx, 00092h ; ba 92 00 ; 0xf6677 system.c:315
+ in AL, DX ; ec ; 0xf667a
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf667b
+ mov cl, al ; 88 c1 ; 0xf667d
+ test bx, bx ; 85 db ; 0xf667f system.c:318
+ je short 06688h ; 74 05 ; 0xf6681
+ or AL, strict byte 002h ; 0c 02 ; 0xf6683 system.c:319
+ out DX, AL ; ee ; 0xf6685
+ jmp short 0668bh ; eb 03 ; 0xf6686 system.c:320
+ and AL, strict byte 0fdh ; 24 fd ; 0xf6688 system.c:321
+ out DX, AL ; ee ; 0xf668a
+ test cl, 002h ; f6 c1 02 ; 0xf668b system.c:323
+ je short 06695h ; 74 05 ; 0xf668e
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf6690
+ jmp short 06697h ; eb 02 ; 0xf6693
+ xor ax, ax ; 31 c0 ; 0xf6695
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf6697 system.c:324
+ pop dx ; 5a ; 0xf669a
+ pop cx ; 59 ; 0xf669b
+ pop bx ; 5b ; 0xf669c
+ pop bp ; 5d ; 0xf669d
+ retn ; c3 ; 0xf669e
+ ; disGetNextSymbol 0xf669f LB 0x38a9 -> off=0x3b cb=000000000000030d uValue=00000000000f50da 'int15_function'
+ db 0ech, 0e9h, 0d8h, 0c7h, 0c1h, 0c0h, 0bfh, 091h, 090h, 089h, 088h, 086h, 083h, 052h, 04fh, 041h
+ db 024h, 022h, 000h, 0c5h, 069h, 016h, 067h, 064h, 069h, 02ah, 067h, 064h, 069h, 0b2h, 067h, 0c0h
+ db 067h, 0d0h, 067h, 070h, 068h, 07dh, 068h, 086h, 068h, 0c9h, 067h, 0c9h, 067h, 04bh, 069h, 076h
+ db 069h, 089h, 069h, 064h, 069h, 09dh, 069h, 034h, 068h, 0a6h, 069h
+int15_function: ; 0xf66da LB 0x30d
+ push bp ; 55 ; 0xf66da system.c:345
+ mov bp, sp ; 89 e5 ; 0xf66db
+ push si ; 56 ; 0xf66dd
+ push di ; 57 ; 0xf66de
+ mov al, byte [bp+013h] ; 8a 46 13 ; 0xf66df system.c:352
+ xor ah, ah ; 30 e4 ; 0xf66e2
+ mov dx, ax ; 89 c2 ; 0xf66e4
+ cmp ax, 000ech ; 3d ec 00 ; 0xf66e6
+ jnbe short 06720h ; 77 35 ; 0xf66e9
+ push CS ; 0e ; 0xf66eb
+ pop ES ; 07 ; 0xf66ec
+ mov cx, strict word 00014h ; b9 14 00 ; 0xf66ed
+ mov di, 0669fh ; bf 9f 66 ; 0xf66f0
+ repne scasb ; f2 ae ; 0xf66f3
+ sal cx, 1 ; d1 e1 ; 0xf66f5
+ mov di, cx ; 89 cf ; 0xf66f7
+ mov cx, word [cs:di+066b2h] ; 2e 8b 8d b2 66 ; 0xf66f9
+ mov bx, word [bp+012h] ; 8b 5e 12 ; 0xf66fe
+ xor bh, bh ; 30 ff ; 0xf6701
+ mov si, word [bp+018h] ; 8b 76 18 ; 0xf6703
+ and si, strict byte 0fffeh ; 83 e6 fe ; 0xf6706
+ mov dx, word [bp+018h] ; 8b 56 18 ; 0xf6709
+ or dl, 001h ; 80 ca 01 ; 0xf670c
+ mov ax, bx ; 89 d8 ; 0xf670f
+ or ah, 086h ; 80 cc 86 ; 0xf6711
+ jmp cx ; ff e1 ; 0xf6714
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf6716 system.c:354
+ xor ah, ah ; 30 e4 ; 0xf6719
+ cmp ax, 000c0h ; 3d c0 00 ; 0xf671b
+ je short 06723h ; 74 03 ; 0xf671e
+ jmp near 069c5h ; e9 a2 02 ; 0xf6720 system.c:355
+ or byte [bp+018h], 001h ; 80 4e 18 01 ; 0xf6723 system.c:361
+ jmp near 0696dh ; e9 43 02 ; 0xf6727
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf672a system.c:365
+ xor ah, ah ; 30 e4 ; 0xf672d
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf672f
+ jc short 06742h ; 72 0e ; 0xf6732
+ jbe short 06756h ; 76 20 ; 0xf6734
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf6736
+ je short 06783h ; 74 48 ; 0xf6739
+ cmp ax, strict word 00002h ; 3d 02 00 ; 0xf673b
+ je short 06766h ; 74 26 ; 0xf673e
+ jmp short 06790h ; eb 4e ; 0xf6740
+ test ax, ax ; 85 c0 ; 0xf6742
+ jne short 06790h ; 75 4a ; 0xf6744
+ xor ax, ax ; 31 c0 ; 0xf6746 system.c:367
+ call 0666fh ; e8 24 ff ; 0xf6748
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf674b system.c:368
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf674f system.c:369
+ jmp near 067c9h ; e9 73 00 ; 0xf6753 system.c:370
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf6756 system.c:372
+ call 0666fh ; e8 13 ff ; 0xf6759
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf675c system.c:373
+ mov byte [bp+013h], bh ; 88 7e 13 ; 0xf6760 system.c:374
+ jmp near 067c9h ; e9 63 00 ; 0xf6763 system.c:375
+ mov dx, 00092h ; ba 92 00 ; 0xf6766 system.c:377
+ in AL, DX ; ec ; 0xf6769
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf676a
+ shr ax, 1 ; d1 e8 ; 0xf676c
+ and ax, strict word 00001h ; 25 01 00 ; 0xf676e
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf6771
+ mov dl, al ; 88 c2 ; 0xf6774
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf6776
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf6779 system.c:378
+ mov byte [bp+013h], ah ; 88 66 13 ; 0xf677d system.c:379
+ jmp near 067c9h ; e9 46 00 ; 0xf6780 system.c:380
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf6783 system.c:382
+ mov byte [bp+013h], ah ; 88 66 13 ; 0xf6787 system.c:383
+ mov word [bp+00ch], ax ; 89 46 0c ; 0xf678a system.c:384
+ jmp near 067c9h ; e9 39 00 ; 0xf678d system.c:385
+ mov bx, 00da0h ; bb a0 0d ; 0xf6790 system.c:387
+ mov cx, ds ; 8c d9 ; 0xf6793
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6795
+ call 018cch ; e8 31 b1 ; 0xf6798
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf679b
+ xor ah, ah ; 30 e4 ; 0xf679e
+ push ax ; 50 ; 0xf67a0
+ mov ax, 0082eh ; b8 2e 08 ; 0xf67a1
+ push ax ; 50 ; 0xf67a4
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf67a5
+ push ax ; 50 ; 0xf67a8
+ call 0190fh ; e8 63 b1 ; 0xf67a9
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf67ac
+ jmp near 06964h ; e9 b2 01 ; 0xf67af
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf67b2 system.c:408
+ xor ah, ah ; 30 e4 ; 0xf67b5
+ or ah, 086h ; 80 cc 86 ; 0xf67b7
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf67ba
+ jmp near 069beh ; e9 fe 01 ; 0xf67bd
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf67c0 system.c:414
+ xor al, bl ; 30 d8 ; 0xf67c4 system.c:415
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf67c6
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf67c9 system.c:416
+ pop di ; 5f ; 0xf67cc
+ pop si ; 5e ; 0xf67cd
+ pop bp ; 5d ; 0xf67ce
+ retn ; c3 ; 0xf67cf
+ test byte [bp+012h], 0ffh ; f6 46 12 ff ; 0xf67d0 system.c:419
+ jne short 0683ch ; 75 66 ; 0xf67d4
+ mov bx, 000a0h ; bb a0 00 ; 0xf67d6 system.c:38
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf67d9
+ mov es, cx ; 8e c1 ; 0xf67dc
+ mov bl, byte [es:bx] ; 26 8a 1f ; 0xf67de
+ test bl, 001h ; f6 c3 01 ; 0xf67e1 system.c:39
+ jne short 06834h ; 75 4e ; 0xf67e4
+ mov bx, 000a0h ; bb a0 00 ; 0xf67e6 system.c:41
+ mov DL, strict byte 001h ; b2 01 ; 0xf67e9
+ mov byte [es:bx], dl ; 26 88 17 ; 0xf67eb system.c:43
+ mov bx, 00098h ; bb 98 00 ; 0xf67ee system.c:51
+ mov dx, word [bp+014h] ; 8b 56 14 ; 0xf67f1
+ mov word [es:bx], dx ; 26 89 17 ; 0xf67f4 system.c:53
+ mov bx, 0009ah ; bb 9a 00 ; 0xf67f7 system.c:51
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf67fa
+ mov word [es:bx], ax ; 26 89 07 ; 0xf67fd system.c:53
+ mov bx, 0009ch ; bb 9c 00 ; 0xf6800 system.c:51
+ mov dx, word [bp+00eh] ; 8b 56 0e ; 0xf6803
+ mov word [es:bx], dx ; 26 89 17 ; 0xf6806 system.c:53
+ mov bx, 0009eh ; bb 9e 00 ; 0xf6809 system.c:51
+ mov dx, word [bp+010h] ; 8b 56 10 ; 0xf680c
+ mov word [es:bx], dx ; 26 89 17 ; 0xf680f system.c:53
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf6812 system.c:428
+ mov dx, 000a1h ; ba a1 00 ; 0xf6816 system.c:429
+ in AL, DX ; ec ; 0xf6819
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf681a
+ and AL, strict byte 0feh ; 24 fe ; 0xf681c system.c:430
+ out DX, AL ; ee ; 0xf681e
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf681f system.c:431
+ call 01652h ; e8 2d ae ; 0xf6822
+ mov dl, al ; 88 c2 ; 0xf6825 system.c:432
+ or dl, 040h ; 80 ca 40 ; 0xf6827
+ xor dh, dh ; 30 f6 ; 0xf682a
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf682c
+ call 0166dh ; e8 3b ae ; 0xf682f
+ jmp short 067c9h ; eb 95 ; 0xf6832 system.c:433
+ mov word [bp+018h], dx ; 89 56 18 ; 0xf6834 system.c:436
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf6837 system.c:437
+ jmp short 067c9h ; eb 8d ; 0xf683a system.c:439
+ cmp bx, strict byte 00001h ; 83 fb 01 ; 0xf683c
+ jne short 0685eh ; 75 1d ; 0xf683f
+ mov bx, 000a0h ; bb a0 00 ; 0xf6841 system.c:43
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf6844
+ mov es, ax ; 8e c0 ; 0xf6847
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf6849
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf684d system.c:442
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6851 system.c:443
+ call 01652h ; e8 fb ad ; 0xf6854
+ mov dl, al ; 88 c2 ; 0xf6857 system.c:444
+ and dl, 0bfh ; 80 e2 bf ; 0xf6859
+ jmp short 0682ah ; eb cc ; 0xf685c
+ mov word [bp+018h], dx ; 89 56 18 ; 0xf685e system.c:447
+ mov dx, ax ; 89 c2 ; 0xf6861 system.c:449
+ xor dh, ah ; 30 e6 ; 0xf6863
+ xor al, bl ; 30 d8 ; 0xf6865
+ dec dx ; 4a ; 0xf6867
+ or ax, dx ; 09 d0 ; 0xf6868
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf686a
+ jmp near 067c9h ; e9 59 ff ; 0xf686d system.c:452
+ sti ; fb ; 0xf6870 system.c:458
+ mov dx, word [bp+010h] ; 8b 56 10 ; 0xf6871 system.c:459
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf6874
+ call 0662ch ; e8 b2 fd ; 0xf6877
+ jmp near 067c9h ; e9 4c ff ; 0xf687a system.c:460
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf687d system.c:482
+ mov word [bp+018h], dx ; 89 56 18 ; 0xf6880 system.c:483
+ jmp near 067c9h ; e9 43 ff ; 0xf6883 system.c:485
+ cli ; fa ; 0xf6886 system.c:494
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf6887 system.c:496
+ call 0666fh ; e8 e2 fd ; 0xf688a
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf688d system.c:499
+ add bx, strict byte 00038h ; 83 c3 38 ; 0xf6890
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf6893 system.c:51
+ mov word [es:bx], strict word 0ffffh ; 26 c7 07 ff ff ; 0xf6896 system.c:53
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf689b system.c:500
+ add bx, strict byte 0003ah ; 83 c3 3a ; 0xf689e
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf68a1 system.c:51
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf68a4 system.c:53
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf68a9 system.c:501
+ add bx, strict byte 0003ch ; 83 c3 3c ; 0xf68ac
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf68af system.c:41
+ mov byte [es:bx], 00fh ; 26 c6 07 0f ; 0xf68b2 system.c:43
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf68b6 system.c:502
+ add bx, strict byte 0003dh ; 83 c3 3d ; 0xf68b9
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf68bc system.c:41
+ mov byte [es:bx], 09bh ; 26 c6 07 9b ; 0xf68bf
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf68c3 system.c:503
+ add bx, strict byte 0003eh ; 83 c3 3e ; 0xf68c6
+ mov es, [bp+014h] ; 8e 46 14 ; 0xf68c9 system.c:51
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf68cc
+ mov AL, strict byte 011h ; b0 11 ; 0xf68d1 system.c:506
+ mov dx, strict word 00020h ; ba 20 00 ; 0xf68d3
+ out DX, AL ; ee ; 0xf68d6
+ mov dx, 000a0h ; ba a0 00 ; 0xf68d7 system.c:507
+ out DX, AL ; ee ; 0xf68da
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf68db system.c:508
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf68de
+ out DX, AL ; ee ; 0xf68e1
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf68e2 system.c:509
+ mov dx, 000a1h ; ba a1 00 ; 0xf68e5
+ out DX, AL ; ee ; 0xf68e8
+ mov AL, strict byte 004h ; b0 04 ; 0xf68e9 system.c:510
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf68eb
+ out DX, AL ; ee ; 0xf68ee
+ mov AL, strict byte 002h ; b0 02 ; 0xf68ef system.c:511
+ mov dx, 000a1h ; ba a1 00 ; 0xf68f1
+ out DX, AL ; ee ; 0xf68f4
+ mov AL, strict byte 001h ; b0 01 ; 0xf68f5 system.c:512
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf68f7
+ out DX, AL ; ee ; 0xf68fa
+ mov dx, 000a1h ; ba a1 00 ; 0xf68fb system.c:513
+ out DX, AL ; ee ; 0xf68fe
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf68ff system.c:515
+ mov dx, strict word 00021h ; ba 21 00 ; 0xf6901
+ out DX, AL ; ee ; 0xf6904
+ mov dx, 000a1h ; ba a1 00 ; 0xf6905 system.c:516
+ out DX, AL ; ee ; 0xf6908
+ mov si, word [bp+006h] ; 8b 76 06 ; 0xf6909 system.c:518
+ lgdt [es:si+008h] ; 26 0f 01 54 08 ; 0xf690c
+ lidt [es:si+010h] ; 26 0f 01 5c 10 ; 0xf6911
+ push strict byte 00038h ; 6a 38 ; 0xf6916
+ call 0691bh ; e8 00 00 ; 0xf6918
+ pop ax ; 58 ; 0xf691b
+ add ax, strict byte 0000eh ; 83 c0 0e ; 0xf691c
+ push ax ; 50 ; 0xf691f
+ smsw ax ; 0f 01 e0 ; 0xf6920
+ or AL, strict byte 001h ; 0c 01 ; 0xf6923
+ lmsw ax ; 0f 01 f0 ; 0xf6925
+ retf ; cb ; 0xf6928
+ mov ax, strict word 00018h ; b8 18 00 ; 0xf6929
+ mov ds, ax ; 8e d8 ; 0xf692c
+ add AL, strict byte 008h ; 04 08 ; 0xf692e
+ mov es, ax ; 8e c0 ; 0xf6930
+ add AL, strict byte 008h ; 04 08 ; 0xf6932
+ mov ss, ax ; 8e d0 ; 0xf6934
+ lea ax, [bp+004h] ; 8d 46 04 ; 0xf6936 system.c:519
+ db 08bh, 0e0h
+ ; mov sp, ax ; 8b e0 ; 0xf6939
+ popaw ; 61 ; 0xf693b
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf693c
+ pop cx ; 59 ; 0xf693f
+ pop ax ; 58 ; 0xf6940
+ pop ax ; 58 ; 0xf6941
+ mov ax, strict word 00030h ; b8 30 00 ; 0xf6942
+ push ax ; 50 ; 0xf6945
+ push cx ; 51 ; 0xf6946
+ retf ; cb ; 0xf6947
+ jmp near 067c9h ; e9 7e fe ; 0xf6948 system.c:525
+ mov bx, 00da0h ; bb a0 0d ; 0xf694b system.c:532
+ mov cx, ds ; 8c d9 ; 0xf694e
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6950
+ call 018cch ; e8 76 af ; 0xf6953
+ mov ax, 0086eh ; b8 6e 08 ; 0xf6956
+ push ax ; 50 ; 0xf6959
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf695a
+ push ax ; 50 ; 0xf695d
+ call 0190fh ; e8 ae af ; 0xf695e
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf6961
+ or byte [bp+018h], 001h ; 80 4e 18 01 ; 0xf6964
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf6968
+ xor ah, ah ; 30 e4 ; 0xf696b
+ or ah, 086h ; 80 cc 86 ; 0xf696d
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf6970
+ jmp near 067c9h ; e9 53 fe ; 0xf6973
+ mov word [bp+018h], si ; 89 76 18 ; 0xf6976 system.c:538
+ mov word [bp+012h], bx ; 89 5e 12 ; 0xf6979 system.c:539
+ mov word [bp+00ch], 0e6f5h ; c7 46 0c f5 e6 ; 0xf697c system.c:540
+ mov word [bp+014h], 0f000h ; c7 46 14 00 f0 ; 0xf6981 system.c:541
+ jmp near 067c9h ; e9 40 fe ; 0xf6986 system.c:542
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf6989 system.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf698c
+ mov es, ax ; 8e c0 ; 0xf698f
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf6991
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf6994 system.c:49
+ mov word [bp+018h], si ; 89 76 18 ; 0xf6997 system.c:546
+ jmp near 067c9h ; e9 2c fe ; 0xf699a system.c:547
+ mov ax, 0089dh ; b8 9d 08 ; 0xf699d system.c:550
+ push ax ; 50 ; 0xf69a0
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf69a1
+ jmp short 0695dh ; eb b7 ; 0xf69a4
+ test byte [bp+012h], 0ffh ; f6 46 12 ff ; 0xf69a6 system.c:562
+ jne short 069c5h ; 75 19 ; 0xf69aa
+ mov word [bp+012h], bx ; 89 5e 12 ; 0xf69ac system.c:564
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf69af system.c:565
+ xor ah, ah ; 30 e4 ; 0xf69b2
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf69b4
+ jc short 069beh ; 72 05 ; 0xf69b7
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf69b9
+ jbe short 06997h ; 76 d9 ; 0xf69bc
+ or byte [bp+018h], 001h ; 80 4e 18 01 ; 0xf69be system.c:568
+ jmp near 067c9h ; e9 04 fe ; 0xf69c2 system.c:569
+ mov bx, 00da0h ; bb a0 0d ; 0xf69c5 system.c:573
+ mov cx, ds ; 8c d9 ; 0xf69c8
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf69ca
+ call 018cch ; e8 fc ae ; 0xf69cd
+ push word [bp+00ch] ; ff 76 0c ; 0xf69d0
+ push word [bp+012h] ; ff 76 12 ; 0xf69d3
+ mov ax, 008b4h ; b8 b4 08 ; 0xf69d6
+ push ax ; 50 ; 0xf69d9
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf69da
+ push ax ; 50 ; 0xf69dd
+ call 0190fh ; e8 2e af ; 0xf69de
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf69e1
+ jmp near 06964h ; e9 7d ff ; 0xf69e4
+ ; disGetNextSymbol 0xf69e7 LB 0x3561 -> off=0x0 cb=000000000000018f uValue=00000000000f53e7 'inv_op_handler'
+inv_op_handler: ; 0xf69e7 LB 0x18f
+ push bp ; 55 ; 0xf69e7 invop.c:237
+ mov bp, sp ; 89 e5 ; 0xf69e8
+ push si ; 56 ; 0xf69ea
+ push di ; 57 ; 0xf69eb
+ push ax ; 50 ; 0xf69ec
+ push ax ; 50 ; 0xf69ed
+ les bx, [bp+018h] ; c4 5e 18 ; 0xf69ee invop.c:239
+ cmp byte [es:bx], 0f0h ; 26 80 3f f0 ; 0xf69f1 invop.c:241
+ jne short 069fdh ; 75 06 ; 0xf69f5
+ inc word [bp+018h] ; ff 46 18 ; 0xf69f7 invop.c:243
+ jmp near 06b6fh ; e9 72 01 ; 0xf69fa invop.c:244
+ cmp word [es:bx], 0050fh ; 26 81 3f 0f 05 ; 0xf69fd
+ je short 06a07h ; 74 03 ; 0xf6a02
+ jmp near 06b6bh ; e9 64 01 ; 0xf6a04
+ mov si, 00800h ; be 00 08 ; 0xf6a07 invop.c:246
+ xor ax, ax ; 31 c0 ; 0xf6a0a
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf6a0c
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf6a0f invop.c:249
+ mov es, ax ; 8e c0 ; 0xf6a12 invop.c:257
+ mov bx, word [es:si+02ch] ; 26 8b 5c 2c ; 0xf6a14
+ sub bx, strict byte 00006h ; 83 eb 06 ; 0xf6a18
+ mov dx, word [es:si+020h] ; 26 8b 54 20 ; 0xf6a1b
+ mov ax, word [es:si+01ah] ; 26 8b 44 1a ; 0xf6a1f invop.c:258
+ mov es, dx ; 8e c2 ; 0xf6a23
+ mov word [es:bx], ax ; 26 89 07 ; 0xf6a25
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf6a28 invop.c:259
+ mov ax, word [es:si+022h] ; 26 8b 44 22 ; 0xf6a2b
+ mov es, dx ; 8e c2 ; 0xf6a2f
+ mov word [es:bx+002h], ax ; 26 89 47 02 ; 0xf6a31
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf6a35 invop.c:260
+ mov ax, word [es:si+018h] ; 26 8b 44 18 ; 0xf6a38
+ mov es, dx ; 8e c2 ; 0xf6a3c
+ mov word [es:bx+004h], ax ; 26 89 47 04 ; 0xf6a3e
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf6a42 invop.c:263
+ mov bl, byte [es:si+038h] ; 26 8a 5c 38 ; 0xf6a45
+ xor bh, bh ; 30 ff ; 0xf6a49
+ mov di, word [es:si+036h] ; 26 8b 7c 36 ; 0xf6a4b
+ mov ax, word [es:si+024h] ; 26 8b 44 24 ; 0xf6a4f invop.c:264
+ xor dx, dx ; 31 d2 ; 0xf6a53
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf6a55
+ sal ax, 1 ; d1 e0 ; 0xf6a58
+ rcl dx, 1 ; d1 d2 ; 0xf6a5a
+ loop 06a58h ; e2 fa ; 0xf6a5c
+ cmp bx, dx ; 39 d3 ; 0xf6a5e
+ jne short 06a66h ; 75 04 ; 0xf6a60
+ cmp di, ax ; 39 c7 ; 0xf6a62
+ je short 06a6bh ; 74 05 ; 0xf6a64
+ mov word [bp-006h], strict word 00001h ; c7 46 fa 01 00 ; 0xf6a66 invop.c:265
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf6a6b invop.c:266
+ mov bl, byte [es:si+04ah] ; 26 8a 5c 4a ; 0xf6a6e
+ xor bh, bh ; 30 ff ; 0xf6a72
+ mov di, word [es:si+048h] ; 26 8b 7c 48 ; 0xf6a74
+ mov ax, word [es:si+01eh] ; 26 8b 44 1e ; 0xf6a78 invop.c:267
+ xor dx, dx ; 31 d2 ; 0xf6a7c
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf6a7e
+ sal ax, 1 ; d1 e0 ; 0xf6a81
+ rcl dx, 1 ; d1 d2 ; 0xf6a83
+ loop 06a81h ; e2 fa ; 0xf6a85
+ cmp bx, dx ; 39 d3 ; 0xf6a87
+ jne short 06a8fh ; 75 04 ; 0xf6a89
+ cmp di, ax ; 39 c7 ; 0xf6a8b
+ je short 06a93h ; 74 04 ; 0xf6a8d
+ or byte [bp-006h], 002h ; 80 4e fa 02 ; 0xf6a8f invop.c:268
+ xor ax, ax ; 31 c0 ; 0xf6a93 invop.c:271
+ push ax ; 50 ; 0xf6a95
+ mov ax, 00800h ; b8 00 08 ; 0xf6a96
+ push ax ; 50 ; 0xf6a99
+ mov ax, strict word 0001fh ; b8 1f 00 ; 0xf6a9a
+ push ax ; 50 ; 0xf6a9d
+ db 08bh, 0dch
+ ; mov bx, sp ; 8b dc ; 0xf6a9e
+ lgdt [ss:bx] ; 36 0f 01 17 ; 0xf6aa0
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf6aa4
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf6aa7 invop.c:274
+ mov ax, word [es:si+03ah] ; 26 8b 44 3a ; 0xf6aaa
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf6aae
+ mov ax, word [es:si+036h] ; 26 8b 44 36 ; 0xf6ab2 invop.c:275
+ mov word [es:si+00ah], ax ; 26 89 44 0a ; 0xf6ab6
+ mov dh, byte [es:si+039h] ; 26 8a 74 39 ; 0xf6aba invop.c:276
+ mov dl, byte [es:si+038h] ; 26 8a 54 38 ; 0xf6abe
+ mov word [es:si+00ch], dx ; 26 89 54 0c ; 0xf6ac2
+ mov word [es:si+00eh], strict word 00000h ; 26 c7 44 0e 00 00 ; 0xf6ac6 invop.c:277
+ mov ax, word [es:si+04ch] ; 26 8b 44 4c ; 0xf6acc invop.c:280
+ mov word [es:si], ax ; 26 89 04 ; 0xf6ad0
+ mov ax, word [es:si+048h] ; 26 8b 44 48 ; 0xf6ad3 invop.c:281
+ mov word [es:si+002h], ax ; 26 89 44 02 ; 0xf6ad7
+ mov dh, byte [es:si+04bh] ; 26 8a 74 4b ; 0xf6adb invop.c:282
+ mov dl, byte [es:si+04ah] ; 26 8a 54 4a ; 0xf6adf
+ xor ah, ah ; 30 e4 ; 0xf6ae3
+ mov word [es:si+004h], dx ; 26 89 54 04 ; 0xf6ae5
+ mov al, byte [es:si+05ch] ; 26 8a 44 5c ; 0xf6ae9 invop.c:285
+ mov dx, word [es:si+05ah] ; 26 8b 54 5a ; 0xf6aed
+ push ax ; 50 ; 0xf6af1 invop.c:286
+ push dx ; 52 ; 0xf6af2
+ push word [es:si+05eh] ; 26 ff 74 5e ; 0xf6af3
+ db 08bh, 0dch
+ ; mov bx, sp ; 8b dc ; 0xf6af7
+ lidt [ss:bx] ; 36 0f 01 1f ; 0xf6af9
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf6afd
+ mov cx, word [bp-006h] ; 8b 4e fa ; 0xf6b00 invop.c:289
+ mov ax, 00080h ; b8 80 00 ; 0xf6b03
+ mov ss, ax ; 8e d0 ; 0xf6b06
+ mov ax, word [ss:0001eh] ; 36 a1 1e 00 ; 0xf6b08
+ mov ds, ax ; 8e d8 ; 0xf6b0c
+ mov ax, word [ss:00024h] ; 36 a1 24 00 ; 0xf6b0e
+ mov es, ax ; 8e c0 ; 0xf6b12
+ smsw ax ; 0f 01 e0 ; 0xf6b14 invop.c:290
+ inc ax ; 40 ; 0xf6b17
+ lmsw ax ; 0f 01 f0 ; 0xf6b18
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf6b1b
+ test cx, strict word 00001h ; f7 c1 01 00 ; 0xf6b1e
+ je near 06b28h ; 0f 84 02 00 ; 0xf6b22
+ mov es, ax ; 8e c0 ; 0xf6b26
+ test cx, strict word 00002h ; f7 c1 02 00 ; 0xf6b28
+ je near 06b50h ; 0f 84 20 00 ; 0xf6b2c
+ mov bx, word [word ss:00000h] ; 36 8b 1e 00 00 ; 0xf6b30
+ mov word [word ss:00008h], bx ; 36 89 1e 08 00 ; 0xf6b35
+ mov bx, word [word ss:00002h] ; 36 8b 1e 02 00 ; 0xf6b3a
+ mov word [word ss:0000ah], bx ; 36 89 1e 0a 00 ; 0xf6b3f
+ mov bx, word [word ss:00004h] ; 36 8b 1e 04 00 ; 0xf6b44
+ mov word [word ss:0000ch], bx ; 36 89 1e 0c 00 ; 0xf6b49
+ mov ds, ax ; 8e d8 ; 0xf6b4e
+ mov eax, cr0 ; 0f 20 c0 ; 0xf6b50
+ dec ax ; 48 ; 0xf6b53
+ mov cr0, eax ; 0f 22 c0 ; 0xf6b54
+ mov sp, strict word 00026h ; bc 26 00 ; 0xf6b57 invop.c:291
+ popaw ; 61 ; 0xf6b5a
+ mov sp, word [word ss:0002ch] ; 36 8b 26 2c 00 ; 0xf6b5b
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf6b60
+ mov ss, [word ss:00020h] ; 36 8e 16 20 00 ; 0xf6b63
+ iret ; cf ; 0xf6b68
+ jmp short 06b6fh ; eb 04 ; 0xf6b69 invop.c:343
+ sti ; fb ; 0xf6b6b invop.c:347
+ hlt ; f4 ; 0xf6b6c invop.c:348
+ jmp short 06b6ch ; eb fd ; 0xf6b6d
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf6b6f invop.c:350
+ pop di ; 5f ; 0xf6b72
+ pop si ; 5e ; 0xf6b73
+ pop bp ; 5d ; 0xf6b74
+ retn ; c3 ; 0xf6b75
+ ; disGetNextSymbol 0xf6b76 LB 0x33d2 -> off=0x0 cb=0000000000000028 uValue=00000000000f5576 'init_rtc'
+init_rtc: ; 0xf6b76 LB 0x28
+ push bp ; 55 ; 0xf6b76 timepci.c:74
+ mov bp, sp ; 89 e5 ; 0xf6b77
+ push dx ; 52 ; 0xf6b79
+ mov dx, strict word 00026h ; ba 26 00 ; 0xf6b7a timepci.c:76
+ mov ax, strict word 0000ah ; b8 0a 00 ; 0xf6b7d
+ call 0166dh ; e8 ea aa ; 0xf6b80
+ mov dx, strict word 00002h ; ba 02 00 ; 0xf6b83 timepci.c:77
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6b86
+ call 0166dh ; e8 e1 aa ; 0xf6b89
+ mov ax, strict word 0000ch ; b8 0c 00 ; 0xf6b8c timepci.c:78
+ call 01652h ; e8 c0 aa ; 0xf6b8f
+ mov ax, strict word 0000dh ; b8 0d 00 ; 0xf6b92 timepci.c:79
+ call 01652h ; e8 ba aa ; 0xf6b95
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf6b98 timepci.c:80
+ pop dx ; 5a ; 0xf6b9b
+ pop bp ; 5d ; 0xf6b9c
+ retn ; c3 ; 0xf6b9d
+ ; disGetNextSymbol 0xf6b9e LB 0x33aa -> off=0x0 cb=0000000000000021 uValue=00000000000f559e 'rtc_updating'
+rtc_updating: ; 0xf6b9e LB 0x21
+ push bp ; 55 ; 0xf6b9e timepci.c:82
+ mov bp, sp ; 89 e5 ; 0xf6b9f
+ push dx ; 52 ; 0xf6ba1
+ mov dx, 061a8h ; ba a8 61 ; 0xf6ba2 timepci.c:95
+ dec dx ; 4a ; 0xf6ba5 timepci.c:96
+ je short 06bb6h ; 74 0e ; 0xf6ba6
+ mov ax, strict word 0000ah ; b8 0a 00 ; 0xf6ba8 timepci.c:97
+ call 01652h ; e8 a4 aa ; 0xf6bab
+ test AL, strict byte 080h ; a8 80 ; 0xf6bae
+ jne short 06ba5h ; 75 f3 ; 0xf6bb0
+ xor ax, ax ; 31 c0 ; 0xf6bb2 timepci.c:98
+ jmp short 06bb9h ; eb 03 ; 0xf6bb4
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf6bb6 timepci.c:100
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf6bb9 timepci.c:101
+ pop dx ; 5a ; 0xf6bbc
+ pop bp ; 5d ; 0xf6bbd
+ retn ; c3 ; 0xf6bbe
+ ; disGetNextSymbol 0xf6bbf LB 0x3389 -> off=0x0 cb=0000000000000098 uValue=00000000000f55bf 'int70_function'
+int70_function: ; 0xf6bbf LB 0x98
+ push bp ; 55 ; 0xf6bbf timepci.c:110
+ mov bp, sp ; 89 e5 ; 0xf6bc0
+ push si ; 56 ; 0xf6bc2
+ push ax ; 50 ; 0xf6bc3
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6bc4 timepci.c:116
+ call 01652h ; e8 88 aa ; 0xf6bc7
+ mov bl, al ; 88 c3 ; 0xf6bca
+ mov byte [bp-004h], al ; 88 46 fc ; 0xf6bcc
+ mov ax, strict word 0000ch ; b8 0c 00 ; 0xf6bcf timepci.c:117
+ call 01652h ; e8 7d aa ; 0xf6bd2
+ mov dl, al ; 88 c2 ; 0xf6bd5
+ test bl, 060h ; f6 c3 60 ; 0xf6bd7 timepci.c:119
+ je short 06c37h ; 74 5b ; 0xf6bda
+ test AL, strict byte 020h ; a8 20 ; 0xf6bdc timepci.c:120
+ je short 06be4h ; 74 04 ; 0xf6bde
+ sti ; fb ; 0xf6be0 timepci.c:122
+ int 04ah ; cd 4a ; 0xf6be1 timepci.c:123
+ cli ; fa ; 0xf6be3 timepci.c:124
+ test dl, 040h ; f6 c2 40 ; 0xf6be4 timepci.c:126
+ je short 06c4eh ; 74 65 ; 0xf6be7
+ mov bx, 000a0h ; bb a0 00 ; 0xf6be9 timepci.c:38
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf6bec
+ mov es, dx ; 8e c2 ; 0xf6bef
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf6bf1
+ test al, al ; 84 c0 ; 0xf6bf4 timepci.c:39
+ je short 06c4eh ; 74 56 ; 0xf6bf6
+ mov bx, 0009ch ; bb 9c 00 ; 0xf6bf8 timepci.c:58
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf6bfb
+ mov bx, word [es:bx+002h] ; 26 8b 5f 02 ; 0xf6bfe
+ test bx, bx ; 85 db ; 0xf6c02 timepci.c:134
+ jne short 06c39h ; 75 33 ; 0xf6c04
+ cmp dx, 003d1h ; 81 fa d1 03 ; 0xf6c06
+ jnc short 06c39h ; 73 2d ; 0xf6c0a
+ mov bx, 00098h ; bb 98 00 ; 0xf6c0c timepci.c:48
+ mov cx, word [es:bx] ; 26 8b 0f ; 0xf6c0f
+ mov bx, 0009ah ; bb 9a 00 ; 0xf6c12 timepci.c:48
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf6c15
+ mov si, 000a0h ; be a0 00 ; 0xf6c18 timepci.c:43
+ mov byte [es:si], 000h ; 26 c6 04 00 ; 0xf6c1b
+ mov dl, byte [bp-004h] ; 8a 56 fc ; 0xf6c1f timepci.c:141
+ and dl, 037h ; 80 e2 37 ; 0xf6c22
+ xor dh, dh ; 30 f6 ; 0xf6c25
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6c27
+ call 0166dh ; e8 40 aa ; 0xf6c2a
+ mov es, cx ; 8e c1 ; 0xf6c2d timepci.c:38
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf6c2f
+ or AL, strict byte 080h ; 0c 80 ; 0xf6c32 timepci.c:39
+ mov byte [es:bx], al ; 26 88 07 ; 0xf6c34 timepci.c:43
+ jmp short 06c4eh ; eb 15 ; 0xf6c37 timepci.c:143
+ mov cx, dx ; 89 d1 ; 0xf6c39 timepci.c:145
+ add cx, 0fc2fh ; 81 c1 2f fc ; 0xf6c3b
+ mov dx, bx ; 89 da ; 0xf6c3f
+ adc dx, strict byte 0ffffh ; 83 d2 ff ; 0xf6c41
+ mov bx, 0009ch ; bb 9c 00 ; 0xf6c44 timepci.c:63
+ mov word [es:bx], cx ; 26 89 0f ; 0xf6c47
+ mov word [es:bx+002h], dx ; 26 89 57 02 ; 0xf6c4a
+ call 0e030h ; e8 df 73 ; 0xf6c4e timepci.c:151
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf6c51 timepci.c:152
+ pop si ; 5e ; 0xf6c54
+ pop bp ; 5d ; 0xf6c55
+ retn ; c3 ; 0xf6c56
+ ; disGetNextSymbol 0xf6c57 LB 0x32f1 -> off=0x10 cb=00000000000001d9 uValue=00000000000f5667 'int1a_function'
+ db 07dh, 06ch, 0a4h, 06ch, 0c9h, 06ch, 005h, 06dh, 057h, 06dh, 08eh, 06dh, 0d5h, 06dh, 030h, 06eh
+int1a_function: ; 0xf6c67 LB 0x1d9
+ push bp ; 55 ; 0xf6c67 timepci.c:157
+ mov bp, sp ; 89 e5 ; 0xf6c68
+ sti ; fb ; 0xf6c6a timepci.c:163
+ mov al, byte [bp+013h] ; 8a 46 13 ; 0xf6c6b timepci.c:165
+ cmp AL, strict byte 007h ; 3c 07 ; 0xf6c6e
+ jnbe short 06cd0h ; 77 5e ; 0xf6c70
+ mov bl, al ; 88 c3 ; 0xf6c72
+ xor bh, bh ; 30 ff ; 0xf6c74
+ sal bx, 1 ; d1 e3 ; 0xf6c76
+ jmp word [cs:bx+06c57h] ; 2e ff a7 57 6c ; 0xf6c78
+ cli ; fa ; 0xf6c7d timepci.c:167
+ mov bx, 0046eh ; bb 6e 04 ; 0xf6c7e timepci.c:168
+ xor ax, ax ; 31 c0 ; 0xf6c81
+ mov es, ax ; 8e c0 ; 0xf6c83
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf6c85
+ mov word [bp+010h], ax ; 89 46 10 ; 0xf6c88
+ mov bx, 0046ch ; bb 6c 04 ; 0xf6c8b timepci.c:169
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf6c8e
+ mov word [bp+00eh], ax ; 89 46 0e ; 0xf6c91
+ mov bx, 00470h ; bb 70 04 ; 0xf6c94 timepci.c:170
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf6c97
+ mov byte [bp+012h], al ; 88 46 12 ; 0xf6c9a
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf6c9d timepci.c:171
+ sti ; fb ; 0xf6ca1 timepci.c:172
+ jmp short 06cd0h ; eb 2c ; 0xf6ca2 timepci.c:175
+ cli ; fa ; 0xf6ca4 timepci.c:178
+ mov bx, 0046eh ; bb 6e 04 ; 0xf6ca5 timepci.c:179
+ xor ax, ax ; 31 c0 ; 0xf6ca8
+ mov es, ax ; 8e c0 ; 0xf6caa
+ mov ax, word [bp+010h] ; 8b 46 10 ; 0xf6cac
+ mov word [es:bx], ax ; 26 89 07 ; 0xf6caf
+ mov bx, 0046ch ; bb 6c 04 ; 0xf6cb2 timepci.c:180
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf6cb5
+ mov word [es:bx], ax ; 26 89 07 ; 0xf6cb8
+ mov bx, 00470h ; bb 70 04 ; 0xf6cbb timepci.c:181
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf6cbe
+ sti ; fb ; 0xf6cc2 timepci.c:182
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf6cc3 timepci.c:183
+ jmp short 06cd0h ; eb 07 ; 0xf6cc7 timepci.c:185
+ call 06b9eh ; e8 d2 fe ; 0xf6cc9 timepci.c:188
+ test ax, ax ; 85 c0 ; 0xf6ccc
+ je short 06cd3h ; 74 03 ; 0xf6cce
+ jmp near 06d01h ; e9 2e 00 ; 0xf6cd0 timepci.c:190
+ xor ax, ax ; 31 c0 ; 0xf6cd3 timepci.c:193
+ call 01652h ; e8 7a a9 ; 0xf6cd5
+ mov byte [bp+00fh], al ; 88 46 0f ; 0xf6cd8
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf6cdb timepci.c:194
+ call 01652h ; e8 71 a9 ; 0xf6cde
+ mov byte [bp+010h], al ; 88 46 10 ; 0xf6ce1
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6ce4 timepci.c:195
+ call 01652h ; e8 68 a9 ; 0xf6ce7
+ mov dl, al ; 88 c2 ; 0xf6cea
+ mov byte [bp+011h], al ; 88 46 11 ; 0xf6cec
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6cef timepci.c:196
+ call 01652h ; e8 5d a9 ; 0xf6cf2
+ and AL, strict byte 001h ; 24 01 ; 0xf6cf5
+ mov byte [bp+00eh], al ; 88 46 0e ; 0xf6cf7
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf6cfa timepci.c:197
+ mov byte [bp+012h], dl ; 88 56 12 ; 0xf6cfe timepci.c:198
+ mov sp, bp ; 89 ec ; 0xf6d01 timepci.c:200
+ pop bp ; 5d ; 0xf6d03
+ retn ; c3 ; 0xf6d04
+ call 06b9eh ; e8 96 fe ; 0xf6d05 timepci.c:213
+ test ax, ax ; 85 c0 ; 0xf6d08
+ je short 06d0fh ; 74 03 ; 0xf6d0a
+ call 06b76h ; e8 67 fe ; 0xf6d0c timepci.c:214
+ mov dl, byte [bp+00fh] ; 8a 56 0f ; 0xf6d0f timepci.c:217
+ xor dh, dh ; 30 f6 ; 0xf6d12
+ xor ax, ax ; 31 c0 ; 0xf6d14
+ call 0166dh ; e8 54 a9 ; 0xf6d16
+ mov dl, byte [bp+010h] ; 8a 56 10 ; 0xf6d19 timepci.c:218
+ xor dh, dh ; 30 f6 ; 0xf6d1c
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf6d1e
+ call 0166dh ; e8 49 a9 ; 0xf6d21
+ mov dl, byte [bp+011h] ; 8a 56 11 ; 0xf6d24 timepci.c:219
+ xor dh, dh ; 30 f6 ; 0xf6d27
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf6d29
+ call 0166dh ; e8 3e a9 ; 0xf6d2c
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6d2f timepci.c:221
+ call 01652h ; e8 1d a9 ; 0xf6d32
+ mov bl, al ; 88 c3 ; 0xf6d35
+ and bl, 060h ; 80 e3 60 ; 0xf6d37
+ or bl, 002h ; 80 cb 02 ; 0xf6d3a
+ mov al, byte [bp+00eh] ; 8a 46 0e ; 0xf6d3d
+ and AL, strict byte 001h ; 24 01 ; 0xf6d40
+ or bl, al ; 08 c3 ; 0xf6d42
+ mov dl, bl ; 88 da ; 0xf6d44 timepci.c:223
+ xor dh, dh ; 30 f6 ; 0xf6d46
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6d48
+ call 0166dh ; e8 1f a9 ; 0xf6d4b
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf6d4e timepci.c:224
+ mov byte [bp+012h], bl ; 88 5e 12 ; 0xf6d52 timepci.c:225
+ jmp short 06d01h ; eb aa ; 0xf6d55 timepci.c:227
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf6d57 timepci.c:230
+ call 06b9eh ; e8 40 fe ; 0xf6d5b timepci.c:231
+ test ax, ax ; 85 c0 ; 0xf6d5e
+ je short 06d64h ; 74 02 ; 0xf6d60
+ jmp short 06d01h ; eb 9d ; 0xf6d62 timepci.c:233
+ mov ax, strict word 00009h ; b8 09 00 ; 0xf6d64 timepci.c:235
+ call 01652h ; e8 e8 a8 ; 0xf6d67
+ mov byte [bp+010h], al ; 88 46 10 ; 0xf6d6a
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf6d6d timepci.c:236
+ call 01652h ; e8 df a8 ; 0xf6d70
+ mov byte [bp+00fh], al ; 88 46 0f ; 0xf6d73
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf6d76 timepci.c:237
+ call 01652h ; e8 d6 a8 ; 0xf6d79
+ mov byte [bp+00eh], al ; 88 46 0e ; 0xf6d7c
+ mov ax, strict word 00032h ; b8 32 00 ; 0xf6d7f timepci.c:238
+ call 01652h ; e8 cd a8 ; 0xf6d82
+ mov byte [bp+011h], al ; 88 46 11 ; 0xf6d85
+ mov byte [bp+012h], al ; 88 46 12 ; 0xf6d88 timepci.c:239
+ jmp near 06d01h ; e9 73 ff ; 0xf6d8b timepci.c:241
+ call 06b9eh ; e8 0d fe ; 0xf6d8e timepci.c:254
+ test ax, ax ; 85 c0 ; 0xf6d91
+ je short 06d9bh ; 74 06 ; 0xf6d93
+ call 06b76h ; e8 de fd ; 0xf6d95 timepci.c:255
+ jmp near 06d01h ; e9 66 ff ; 0xf6d98 timepci.c:257
+ mov dl, byte [bp+010h] ; 8a 56 10 ; 0xf6d9b timepci.c:259
+ xor dh, dh ; 30 f6 ; 0xf6d9e
+ mov ax, strict word 00009h ; b8 09 00 ; 0xf6da0
+ call 0166dh ; e8 c7 a8 ; 0xf6da3
+ mov dl, byte [bp+00fh] ; 8a 56 0f ; 0xf6da6 timepci.c:260
+ xor dh, dh ; 30 f6 ; 0xf6da9
+ mov ax, strict word 00008h ; b8 08 00 ; 0xf6dab
+ call 0166dh ; e8 bc a8 ; 0xf6dae
+ mov dl, byte [bp+00eh] ; 8a 56 0e ; 0xf6db1 timepci.c:261
+ xor dh, dh ; 30 f6 ; 0xf6db4
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf6db6
+ call 0166dh ; e8 b1 a8 ; 0xf6db9
+ mov dl, byte [bp+011h] ; 8a 56 11 ; 0xf6dbc timepci.c:262
+ xor dh, dh ; 30 f6 ; 0xf6dbf
+ mov ax, strict word 00032h ; b8 32 00 ; 0xf6dc1
+ call 0166dh ; e8 a6 a8 ; 0xf6dc4
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6dc7 timepci.c:263
+ call 01652h ; e8 85 a8 ; 0xf6dca
+ mov bl, al ; 88 c3 ; 0xf6dcd
+ and bl, 07fh ; 80 e3 7f ; 0xf6dcf
+ jmp near 06d44h ; e9 6f ff ; 0xf6dd2
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6dd5 timepci.c:281
+ call 01652h ; e8 77 a8 ; 0xf6dd8
+ mov bl, al ; 88 c3 ; 0xf6ddb
+ mov word [bp+012h], strict word 00000h ; c7 46 12 00 00 ; 0xf6ddd timepci.c:282
+ test AL, strict byte 020h ; a8 20 ; 0xf6de2 timepci.c:283
+ je short 06de9h ; 74 03 ; 0xf6de4
+ jmp near 06d01h ; e9 18 ff ; 0xf6de6 timepci.c:286
+ call 06b9eh ; e8 b2 fd ; 0xf6de9 timepci.c:288
+ test ax, ax ; 85 c0 ; 0xf6dec
+ je short 06df3h ; 74 03 ; 0xf6dee
+ call 06b76h ; e8 83 fd ; 0xf6df0 timepci.c:289
+ mov dl, byte [bp+00fh] ; 8a 56 0f ; 0xf6df3 timepci.c:292
+ xor dh, dh ; 30 f6 ; 0xf6df6
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf6df8
+ call 0166dh ; e8 6f a8 ; 0xf6dfb
+ mov dl, byte [bp+010h] ; 8a 56 10 ; 0xf6dfe timepci.c:293
+ xor dh, dh ; 30 f6 ; 0xf6e01
+ mov ax, strict word 00003h ; b8 03 00 ; 0xf6e03
+ call 0166dh ; e8 64 a8 ; 0xf6e06
+ mov dl, byte [bp+011h] ; 8a 56 11 ; 0xf6e09 timepci.c:294
+ xor dh, dh ; 30 f6 ; 0xf6e0c
+ mov ax, strict word 00005h ; b8 05 00 ; 0xf6e0e
+ call 0166dh ; e8 59 a8 ; 0xf6e11
+ mov dx, 000a1h ; ba a1 00 ; 0xf6e14 timepci.c:295
+ in AL, DX ; ec ; 0xf6e17
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6e18
+ and AL, strict byte 0feh ; 24 fe ; 0xf6e1a
+ out DX, AL ; ee ; 0xf6e1c
+ mov dl, bl ; 88 da ; 0xf6e1d timepci.c:297
+ and dl, 05fh ; 80 e2 5f ; 0xf6e1f
+ or dl, 020h ; 80 ca 20 ; 0xf6e22
+ xor dh, dh ; 30 f6 ; 0xf6e25
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6e27
+ call 0166dh ; e8 40 a8 ; 0xf6e2a
+ jmp near 06d01h ; e9 d1 fe ; 0xf6e2d timepci.c:299
+ mov ax, strict word 0000bh ; b8 0b 00 ; 0xf6e30 timepci.c:312
+ call 01652h ; e8 1c a8 ; 0xf6e33
+ mov bl, al ; 88 c3 ; 0xf6e36
+ mov dl, al ; 88 c2 ; 0xf6e38 timepci.c:314
+ and dl, 057h ; 80 e2 57 ; 0xf6e3a
+ jmp near 06d46h ; e9 06 ff ; 0xf6e3d
+ ; disGetNextSymbol 0xf6e40 LB 0x3108 -> off=0x0 cb=0000000000000038 uValue=00000000000f5840 'send_to_mouse_ctrl'
+send_to_mouse_ctrl: ; 0xf6e40 LB 0x38
+ push bp ; 55 ; 0xf6e40 ps2mouse.c:77
+ mov bp, sp ; 89 e5 ; 0xf6e41
+ push bx ; 53 ; 0xf6e43
+ push dx ; 52 ; 0xf6e44
+ mov bl, al ; 88 c3 ; 0xf6e45
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf6e47 ps2mouse.c:81
+ in AL, DX ; ec ; 0xf6e4a
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6e4b
+ test AL, strict byte 002h ; a8 02 ; 0xf6e4d
+ je short 06e63h ; 74 12 ; 0xf6e4f
+ mov ax, 008eeh ; b8 ee 08 ; 0xf6e51 ps2mouse.c:82
+ push ax ; 50 ; 0xf6e54
+ mov ax, 01168h ; b8 68 11 ; 0xf6e55
+ push ax ; 50 ; 0xf6e58
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf6e59
+ push ax ; 50 ; 0xf6e5c
+ call 0190fh ; e8 af aa ; 0xf6e5d
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf6e60
+ mov AL, strict byte 0d4h ; b0 d4 ; 0xf6e63 ps2mouse.c:83
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf6e65
+ out DX, AL ; ee ; 0xf6e68
+ mov al, bl ; 88 d8 ; 0xf6e69 ps2mouse.c:84
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf6e6b
+ out DX, AL ; ee ; 0xf6e6e
+ xor al, bl ; 30 d8 ; 0xf6e6f ps2mouse.c:86
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf6e71
+ pop dx ; 5a ; 0xf6e74
+ pop bx ; 5b ; 0xf6e75
+ pop bp ; 5d ; 0xf6e76
+ retn ; c3 ; 0xf6e77
+ ; disGetNextSymbol 0xf6e78 LB 0x30d0 -> off=0x0 cb=000000000000005d uValue=00000000000f5878 'get_mouse_data'
+get_mouse_data: ; 0xf6e78 LB 0x5d
+ push bp ; 55 ; 0xf6e78 ps2mouse.c:89
+ mov bp, sp ; 89 e5 ; 0xf6e79
+ push bx ; 53 ; 0xf6e7b
+ push cx ; 51 ; 0xf6e7c
+ push ax ; 50 ; 0xf6e7d
+ mov bx, ax ; 89 c3 ; 0xf6e7e
+ mov es, dx ; 8e c2 ; 0xf6e80
+ mov cx, 02710h ; b9 10 27 ; 0xf6e82 ps2mouse.c:91
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf6e85 ps2mouse.c:94
+ in AL, DX ; ec ; 0xf6e88
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6e89
+ and ax, strict word 00021h ; 25 21 00 ; 0xf6e8b
+ cmp ax, strict word 00021h ; 3d 21 00 ; 0xf6e8e
+ je short 06ebbh ; 74 28 ; 0xf6e91
+ test cx, cx ; 85 c9 ; 0xf6e93
+ je short 06ebbh ; 74 24 ; 0xf6e95
+ mov dx, strict word 00061h ; ba 61 00 ; 0xf6e97 ps2mouse.c:97
+ in AL, DX ; ec ; 0xf6e9a
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6e9b
+ and AL, strict byte 010h ; 24 10 ; 0xf6e9d
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf6e9f
+ mov dx, strict word 00061h ; ba 61 00 ; 0xf6ea2 ps2mouse.c:98
+ in AL, DX ; ec ; 0xf6ea5
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6ea6
+ mov dx, ax ; 89 c2 ; 0xf6ea8
+ xor dh, ah ; 30 e6 ; 0xf6eaa
+ and dl, 010h ; 80 e2 10 ; 0xf6eac
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf6eaf
+ xor ah, ah ; 30 e4 ; 0xf6eb2
+ cmp dx, ax ; 39 c2 ; 0xf6eb4
+ je short 06ea2h ; 74 ea ; 0xf6eb6
+ dec cx ; 49 ; 0xf6eb8 ps2mouse.c:100
+ jmp short 06e85h ; eb ca ; 0xf6eb9 ps2mouse.c:101
+ test cx, cx ; 85 c9 ; 0xf6ebb ps2mouse.c:103
+ jne short 06ec3h ; 75 04 ; 0xf6ebd
+ mov AL, strict byte 001h ; b0 01 ; 0xf6ebf ps2mouse.c:104
+ jmp short 06eceh ; eb 0b ; 0xf6ec1
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf6ec3 ps2mouse.c:106
+ in AL, DX ; ec ; 0xf6ec6
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6ec7
+ mov byte [es:bx], al ; 26 88 07 ; 0xf6ec9 ps2mouse.c:107
+ xor al, al ; 30 c0 ; 0xf6ecc ps2mouse.c:108
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf6ece ps2mouse.c:109
+ pop cx ; 59 ; 0xf6ed1
+ pop bx ; 5b ; 0xf6ed2
+ pop bp ; 5d ; 0xf6ed3
+ retn ; c3 ; 0xf6ed4
+ ; disGetNextSymbol 0xf6ed5 LB 0x3073 -> off=0x0 cb=0000000000000036 uValue=00000000000f58d5 'set_kbd_command_byte'
+set_kbd_command_byte: ; 0xf6ed5 LB 0x36
+ push bp ; 55 ; 0xf6ed5 ps2mouse.c:111
+ mov bp, sp ; 89 e5 ; 0xf6ed6
+ push bx ; 53 ; 0xf6ed8
+ push dx ; 52 ; 0xf6ed9
+ mov bl, al ; 88 c3 ; 0xf6eda
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf6edc ps2mouse.c:113
+ in AL, DX ; ec ; 0xf6edf
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6ee0
+ test AL, strict byte 002h ; a8 02 ; 0xf6ee2
+ je short 06ef8h ; 74 12 ; 0xf6ee4
+ mov ax, 008f8h ; b8 f8 08 ; 0xf6ee6 ps2mouse.c:114
+ push ax ; 50 ; 0xf6ee9
+ mov ax, 01168h ; b8 68 11 ; 0xf6eea
+ push ax ; 50 ; 0xf6eed
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf6eee
+ push ax ; 50 ; 0xf6ef1
+ call 0190fh ; e8 1a aa ; 0xf6ef2
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf6ef5
+ mov AL, strict byte 060h ; b0 60 ; 0xf6ef8 ps2mouse.c:116
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf6efa
+ out DX, AL ; ee ; 0xf6efd
+ mov al, bl ; 88 d8 ; 0xf6efe ps2mouse.c:117
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf6f00
+ out DX, AL ; ee ; 0xf6f03
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf6f04 ps2mouse.c:118
+ pop dx ; 5a ; 0xf6f07
+ pop bx ; 5b ; 0xf6f08
+ pop bp ; 5d ; 0xf6f09
+ retn ; c3 ; 0xf6f0a
+ ; disGetNextSymbol 0xf6f0b LB 0x303d -> off=0x0 cb=000000000000009e uValue=00000000000f590b 'int74_function'
+int74_function: ; 0xf6f0b LB 0x9e
+ push bp ; 55 ; 0xf6f0b ps2mouse.c:121
+ mov bp, sp ; 89 e5 ; 0xf6f0c
+ push si ; 56 ; 0xf6f0e
+ push ax ; 50 ; 0xf6f0f
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf6f10 ps2mouse.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf6f13
+ mov es, ax ; 8e c0 ; 0xf6f16
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf6f18
+ mov word [bp+004h], strict word 00000h ; c7 46 04 00 00 ; 0xf6f1b ps2mouse.c:129
+ mov dx, strict word 00064h ; ba 64 00 ; 0xf6f20 ps2mouse.c:131
+ in AL, DX ; ec ; 0xf6f23
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6f24
+ and AL, strict byte 021h ; 24 21 ; 0xf6f26 ps2mouse.c:132
+ cmp AL, strict byte 021h ; 3c 21 ; 0xf6f28
+ jne short 06f4ah ; 75 1e ; 0xf6f2a
+ mov dx, strict word 00060h ; ba 60 00 ; 0xf6f2c ps2mouse.c:135
+ in AL, DX ; ec ; 0xf6f2f
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf6f30
+ mov byte [bp-004h], al ; 88 46 fc ; 0xf6f32
+ mov si, strict word 00026h ; be 26 00 ; 0xf6f35 ps2mouse.c:38
+ mov es, bx ; 8e c3 ; 0xf6f38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf6f3a
+ mov si, strict word 00027h ; be 27 00 ; 0xf6f3d ps2mouse.c:38
+ mov ah, byte [es:si] ; 26 8a 24 ; 0xf6f40
+ mov cl, ah ; 88 e1 ; 0xf6f43 ps2mouse.c:39
+ test ah, 080h ; f6 c4 80 ; 0xf6f45 ps2mouse.c:141
+ jne short 06f4ch ; 75 02 ; 0xf6f48
+ jmp short 06fa3h ; eb 57 ; 0xf6f4a ps2mouse.c:142
+ mov ch, cl ; 88 cd ; 0xf6f4c ps2mouse.c:145
+ and ch, 007h ; 80 e5 07 ; 0xf6f4e
+ mov ah, al ; 88 c4 ; 0xf6f51 ps2mouse.c:146
+ and ah, 007h ; 80 e4 07 ; 0xf6f53
+ mov dl, ah ; 88 e2 ; 0xf6f56 ps2mouse.c:147
+ xor dh, dh ; 30 f6 ; 0xf6f58
+ mov si, dx ; 89 d6 ; 0xf6f5a
+ add si, strict byte 00028h ; 83 c6 28 ; 0xf6f5c
+ mov es, bx ; 8e c3 ; 0xf6f5f ps2mouse.c:43
+ mov dl, byte [bp-004h] ; 8a 56 fc ; 0xf6f61
+ mov byte [es:si], dl ; 26 88 14 ; 0xf6f64
+ cmp ah, ch ; 38 ec ; 0xf6f67 ps2mouse.c:149
+ jc short 06f99h ; 72 2e ; 0xf6f69
+ mov si, strict word 00028h ; be 28 00 ; 0xf6f6b ps2mouse.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf6f6e
+ xor ah, ah ; 30 e4 ; 0xf6f71 ps2mouse.c:39
+ mov word [bp+00ch], ax ; 89 46 0c ; 0xf6f73
+ mov si, strict word 00029h ; be 29 00 ; 0xf6f76 ps2mouse.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf6f79
+ mov word [bp+00ah], ax ; 89 46 0a ; 0xf6f7c ps2mouse.c:39
+ mov si, strict word 0002ah ; be 2a 00 ; 0xf6f7f ps2mouse.c:38
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf6f82
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf6f85 ps2mouse.c:39
+ xor al, al ; 30 c0 ; 0xf6f88 ps2mouse.c:154
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf6f8a
+ test cl, 080h ; f6 c1 80 ; 0xf6f8d ps2mouse.c:157
+ je short 06f9bh ; 74 09 ; 0xf6f90
+ mov word [bp+004h], strict word 00001h ; c7 46 04 01 00 ; 0xf6f92 ps2mouse.c:158
+ jmp short 06f9bh ; eb 02 ; 0xf6f97 ps2mouse.c:160
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf6f99 ps2mouse.c:161
+ mov si, strict word 00026h ; be 26 00 ; 0xf6f9b ps2mouse.c:43
+ mov es, bx ; 8e c3 ; 0xf6f9e
+ mov byte [es:si], al ; 26 88 04 ; 0xf6fa0
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf6fa3 ps2mouse.c:164
+ pop si ; 5e ; 0xf6fa6
+ pop bp ; 5d ; 0xf6fa7
+ retn ; c3 ; 0xf6fa8
+ ; disGetNextSymbol 0xf6fa9 LB 0x2f9f -> off=0x10 cb=0000000000000380 uValue=00000000000f59b9 'int15_function_mouse'
+ db 0fah, 06fh, 06bh, 070h, 0e1h, 070h, 073h, 071h, 0e5h, 071h, 040h, 070h, 00dh, 072h, 0deh, 072h
+int15_function_mouse: ; 0xf6fb9 LB 0x380
+ push bp ; 55 ; 0xf6fb9 ps2mouse.c:166
+ mov bp, sp ; 89 e5 ; 0xf6fba
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf6fbc
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf6fbf ps2mouse.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf6fc2
+ mov es, ax ; 8e c0 ; 0xf6fc5
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf6fc7
+ cmp byte [bp+012h], 007h ; 80 7e 12 07 ; 0xf6fca ps2mouse.c:188
+ jbe short 06fdbh ; 76 0b ; 0xf6fce
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf6fd0 ps2mouse.c:191
+ mov byte [bp+013h], 001h ; c6 46 13 01 ; 0xf6fd4 ps2mouse.c:192
+ jmp near 07335h ; e9 5a 03 ; 0xf6fd8 ps2mouse.c:193
+ mov ax, strict word 00065h ; b8 65 00 ; 0xf6fdb ps2mouse.c:197
+ call 06ed5h ; e8 f4 fe ; 0xf6fde
+ and word [bp+018h], strict byte 0fffeh ; 83 66 18 fe ; 0xf6fe1 ps2mouse.c:198
+ mov byte [bp+013h], 000h ; c6 46 13 00 ; 0xf6fe5 ps2mouse.c:199
+ mov bl, byte [bp+012h] ; 8a 5e 12 ; 0xf6fe9 ps2mouse.c:201
+ cmp bl, 007h ; 80 fb 07 ; 0xf6fec
+ jnbe short 0704eh ; 77 5d ; 0xf6fef
+ xor bh, bh ; 30 ff ; 0xf6ff1
+ sal bx, 1 ; d1 e3 ; 0xf6ff3
+ jmp word [cs:bx+06fa9h] ; 2e ff a7 a9 6f ; 0xf6ff5
+ cmp byte [bp+00dh], 001h ; 80 7e 0d 01 ; 0xf6ffa ps2mouse.c:204
+ jnbe short 07051h ; 77 51 ; 0xf6ffe
+ mov bx, strict word 00027h ; bb 27 00 ; 0xf7000 ps2mouse.c:38
+ mov es, dx ; 8e c2 ; 0xf7003
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf7005
+ test AL, strict byte 080h ; a8 80 ; 0xf7008 ps2mouse.c:212
+ jne short 07017h ; 75 0b ; 0xf700a
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf700c ps2mouse.c:214
+ mov byte [bp+013h], 005h ; c6 46 13 05 ; 0xf7010 ps2mouse.c:215
+ jmp near 0732fh ; e9 18 03 ; 0xf7014 ps2mouse.c:216
+ cmp byte [bp+00dh], 000h ; 80 7e 0d 00 ; 0xf7017 ps2mouse.c:218
+ jne short 07021h ; 75 04 ; 0xf701b
+ mov AL, strict byte 0f5h ; b0 f5 ; 0xf701d ps2mouse.c:220
+ jmp short 07023h ; eb 02 ; 0xf701f ps2mouse.c:221
+ mov AL, strict byte 0f4h ; b0 f4 ; 0xf7021 ps2mouse.c:223
+ xor ah, ah ; 30 e4 ; 0xf7023 ps2mouse.c:226
+ call 06e40h ; e8 18 fe ; 0xf7025
+ test al, al ; 84 c0 ; 0xf7028 ps2mouse.c:227
+ jne short 07054h ; 75 28 ; 0xf702a
+ mov dx, ss ; 8c d2 ; 0xf702c ps2mouse.c:228
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf702e
+ call 06e78h ; e8 44 fe ; 0xf7031
+ test al, al ; 84 c0 ; 0xf7034 ps2mouse.c:229
+ je short 0709ah ; 74 62 ; 0xf7036
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf7038
+ jne short 07054h ; 75 16 ; 0xf703c
+ jmp short 0709ah ; eb 5a ; 0xf703e ps2mouse.c:231
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf7040 ps2mouse.c:242
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf7043
+ jc short 0704bh ; 72 04 ; 0xf7045
+ cmp AL, strict byte 008h ; 3c 08 ; 0xf7047
+ jbe short 07057h ; 76 0c ; 0xf7049
+ jmp near 071dbh ; e9 8d 01 ; 0xf704b
+ jmp near 07319h ; e9 c8 02 ; 0xf704e
+ jmp near 07327h ; e9 d3 02 ; 0xf7051
+ jmp near 072b6h ; e9 5f 02 ; 0xf7054
+ mov bx, strict word 00027h ; bb 27 00 ; 0xf7057 ps2mouse.c:38
+ mov es, dx ; 8e c2 ; 0xf705a
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf705c
+ mov ah, byte [bp+00dh] ; 8a 66 0d ; 0xf705f ps2mouse.c:248
+ db 0feh, 0cch
+ ; dec ah ; fe cc ; 0xf7062
+ and AL, strict byte 0f8h ; 24 f8 ; 0xf7064
+ or al, ah ; 08 e0 ; 0xf7066
+ mov byte [es:bx], al ; 26 88 07 ; 0xf7068 ps2mouse.c:43
+ mov bx, strict word 00026h ; bb 26 00 ; 0xf706b ps2mouse.c:38
+ mov es, dx ; 8e c2 ; 0xf706e
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf7070
+ and AL, strict byte 0f8h ; 24 f8 ; 0xf7073 ps2mouse.c:256
+ mov byte [es:bx], al ; 26 88 07 ; 0xf7075 ps2mouse.c:43
+ mov ax, 000ffh ; b8 ff 00 ; 0xf7078 ps2mouse.c:258
+ call 06e40h ; e8 c2 fd ; 0xf707b
+ test al, al ; 84 c0 ; 0xf707e ps2mouse.c:259
+ jne short 07054h ; 75 d2 ; 0xf7080
+ mov dx, ss ; 8c d2 ; 0xf7082 ps2mouse.c:260
+ lea ax, [bp-002h] ; 8d 46 fe ; 0xf7084
+ call 06e78h ; e8 ee fd ; 0xf7087
+ mov dl, al ; 88 c2 ; 0xf708a
+ cmp byte [bp-002h], 0feh ; 80 7e fe fe ; 0xf708c ps2mouse.c:262
+ jne short 0709dh ; 75 0b ; 0xf7090
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf7092 ps2mouse.c:263
+ mov byte [bp+013h], 004h ; c6 46 13 04 ; 0xf7096 ps2mouse.c:264
+ jmp near 0732fh ; e9 92 02 ; 0xf709a ps2mouse.c:265
+ cmp byte [bp-002h], 0fah ; 80 7e fe fa ; 0xf709d ps2mouse.c:267
+ je short 070b7h ; 74 14 ; 0xf70a1
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf70a3 ps2mouse.c:268
+ xor ah, ah ; 30 e4 ; 0xf70a6
+ push ax ; 50 ; 0xf70a8
+ mov ax, 00903h ; b8 03 09 ; 0xf70a9
+ push ax ; 50 ; 0xf70ac
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf70ad
+ push ax ; 50 ; 0xf70b0
+ call 0190fh ; e8 5b a8 ; 0xf70b1
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf70b4
+ test dl, dl ; 84 d2 ; 0xf70b7 ps2mouse.c:269
+ jne short 07054h ; 75 99 ; 0xf70b9
+ mov dx, ss ; 8c d2 ; 0xf70bb ps2mouse.c:270
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf70bd
+ call 06e78h ; e8 b5 fd ; 0xf70c0
+ test al, al ; 84 c0 ; 0xf70c3 ps2mouse.c:271
+ jne short 07054h ; 75 8d ; 0xf70c5
+ mov dx, ss ; 8c d2 ; 0xf70c7 ps2mouse.c:272
+ lea ax, [bp-004h] ; 8d 46 fc ; 0xf70c9
+ call 06e78h ; e8 a9 fd ; 0xf70cc
+ test al, al ; 84 c0 ; 0xf70cf ps2mouse.c:273
+ jne short 07054h ; 75 81 ; 0xf70d1
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf70d3 ps2mouse.c:275
+ mov byte [bp+00ch], al ; 88 46 0c ; 0xf70d6
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf70d9 ps2mouse.c:276
+ mov byte [bp+00dh], al ; 88 46 0d ; 0xf70dc
+ jmp short 0709ah ; eb b9 ; 0xf70df ps2mouse.c:277
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf70e1 ps2mouse.c:290
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf70e4
+ jc short 070f8h ; 72 10 ; 0xf70e6
+ jbe short 07116h ; 76 2c ; 0xf70e8
+ cmp AL, strict byte 006h ; 3c 06 ; 0xf70ea
+ je short 07128h ; 74 3a ; 0xf70ec
+ cmp AL, strict byte 005h ; 3c 05 ; 0xf70ee
+ je short 07122h ; 74 30 ; 0xf70f0
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf70f2
+ je short 0711ch ; 74 26 ; 0xf70f4
+ jmp short 0712eh ; eb 36 ; 0xf70f6
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf70f8
+ je short 07110h ; 74 14 ; 0xf70fa
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf70fc
+ je short 0710ah ; 74 0a ; 0xf70fe
+ test al, al ; 84 c0 ; 0xf7100
+ jne short 0712eh ; 75 2a ; 0xf7102
+ mov byte [bp-006h], 00ah ; c6 46 fa 0a ; 0xf7104 ps2mouse.c:291
+ jmp short 07132h ; eb 28 ; 0xf7108
+ mov byte [bp-006h], 014h ; c6 46 fa 14 ; 0xf710a ps2mouse.c:292
+ jmp short 07132h ; eb 22 ; 0xf710e
+ mov byte [bp-006h], 028h ; c6 46 fa 28 ; 0xf7110 ps2mouse.c:293
+ jmp short 07132h ; eb 1c ; 0xf7114
+ mov byte [bp-006h], 03ch ; c6 46 fa 3c ; 0xf7116 ps2mouse.c:294
+ jmp short 07132h ; eb 16 ; 0xf711a
+ mov byte [bp-006h], 050h ; c6 46 fa 50 ; 0xf711c ps2mouse.c:295
+ jmp short 07132h ; eb 10 ; 0xf7120
+ mov byte [bp-006h], 064h ; c6 46 fa 64 ; 0xf7122 ps2mouse.c:296
+ jmp short 07132h ; eb 0a ; 0xf7126
+ mov byte [bp-006h], 0c8h ; c6 46 fa c8 ; 0xf7128 ps2mouse.c:297
+ jmp short 07132h ; eb 04 ; 0xf712c
+ mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xf712e ps2mouse.c:298
+ cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xf7132 ps2mouse.c:300
+ jbe short 07168h ; 76 30 ; 0xf7136
+ mov ax, 000f3h ; b8 f3 00 ; 0xf7138 ps2mouse.c:301
+ call 06e40h ; e8 02 fd ; 0xf713b
+ test al, al ; 84 c0 ; 0xf713e ps2mouse.c:302
+ jne short 0715dh ; 75 1b ; 0xf7140
+ mov dx, ss ; 8c d2 ; 0xf7142 ps2mouse.c:303
+ lea ax, [bp-004h] ; 8d 46 fc ; 0xf7144
+ call 06e78h ; e8 2e fd ; 0xf7147
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf714a ps2mouse.c:304
+ xor ah, ah ; 30 e4 ; 0xf714d
+ call 06e40h ; e8 ee fc ; 0xf714f
+ mov dx, ss ; 8c d2 ; 0xf7152 ps2mouse.c:305
+ lea ax, [bp-004h] ; 8d 46 fc ; 0xf7154
+ call 06e78h ; e8 1e fd ; 0xf7157
+ jmp near 0732fh ; e9 d2 01 ; 0xf715a ps2mouse.c:307
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf715d ps2mouse.c:309
+ mov byte [bp+013h], 003h ; c6 46 13 03 ; 0xf7161 ps2mouse.c:310
+ jmp near 0732fh ; e9 c7 01 ; 0xf7165 ps2mouse.c:312
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf7168 ps2mouse.c:314
+ mov byte [bp+013h], 002h ; c6 46 13 02 ; 0xf716c ps2mouse.c:315
+ jmp near 0732fh ; e9 bc 01 ; 0xf7170 ps2mouse.c:317
+ cmp byte [bp+00dh], 004h ; 80 7e 0d 04 ; 0xf7173 ps2mouse.c:326
+ jnc short 071dbh ; 73 62 ; 0xf7177
+ mov ax, 000e8h ; b8 e8 00 ; 0xf7179 ps2mouse.c:327
+ call 06e40h ; e8 c1 fc ; 0xf717c
+ test al, al ; 84 c0 ; 0xf717f ps2mouse.c:328
+ jne short 071d1h ; 75 4e ; 0xf7181
+ mov dx, ss ; 8c d2 ; 0xf7183 ps2mouse.c:329
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf7185
+ call 06e78h ; e8 ed fc ; 0xf7188
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf718b ps2mouse.c:330
+ je short 071a5h ; 74 14 ; 0xf718f
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7191 ps2mouse.c:331
+ xor ah, ah ; 30 e4 ; 0xf7194
+ push ax ; 50 ; 0xf7196
+ mov ax, 0092eh ; b8 2e 09 ; 0xf7197
+ push ax ; 50 ; 0xf719a
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf719b
+ push ax ; 50 ; 0xf719e
+ call 0190fh ; e8 6d a7 ; 0xf719f
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf71a2
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf71a5 ps2mouse.c:332
+ xor ah, ah ; 30 e4 ; 0xf71a8
+ call 06e40h ; e8 93 fc ; 0xf71aa
+ mov dx, ss ; 8c d2 ; 0xf71ad ps2mouse.c:333
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf71af
+ call 06e78h ; e8 c3 fc ; 0xf71b2
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf71b5 ps2mouse.c:334
+ je short 0720ah ; 74 4f ; 0xf71b9
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf71bb ps2mouse.c:335
+ xor ah, ah ; 30 e4 ; 0xf71be
+ push ax ; 50 ; 0xf71c0
+ mov ax, 0092eh ; b8 2e 09 ; 0xf71c1
+ push ax ; 50 ; 0xf71c4
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf71c5
+ push ax ; 50 ; 0xf71c8
+ call 0190fh ; e8 43 a7 ; 0xf71c9
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf71cc
+ jmp short 0720ah ; eb 39 ; 0xf71cf ps2mouse.c:337
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf71d1 ps2mouse.c:339
+ mov byte [bp+013h], 003h ; c6 46 13 03 ; 0xf71d5 ps2mouse.c:340
+ jmp short 0720ah ; eb 2f ; 0xf71d9 ps2mouse.c:342
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf71db ps2mouse.c:344
+ mov byte [bp+013h], 002h ; c6 46 13 02 ; 0xf71df ps2mouse.c:345
+ jmp short 0720ah ; eb 25 ; 0xf71e3 ps2mouse.c:347
+ mov ax, 000f2h ; b8 f2 00 ; 0xf71e5 ps2mouse.c:351
+ call 06e40h ; e8 55 fc ; 0xf71e8
+ test al, al ; 84 c0 ; 0xf71eb ps2mouse.c:352
+ jne short 07202h ; 75 13 ; 0xf71ed
+ mov dx, ss ; 8c d2 ; 0xf71ef ps2mouse.c:353
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf71f1
+ call 06e78h ; e8 81 fc ; 0xf71f4
+ mov dx, ss ; 8c d2 ; 0xf71f7 ps2mouse.c:354
+ lea ax, [bp-004h] ; 8d 46 fc ; 0xf71f9
+ call 06e78h ; e8 79 fc ; 0xf71fc
+ jmp near 070d9h ; e9 d7 fe ; 0xf71ff
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf7202 ps2mouse.c:355
+ mov byte [bp+013h], 003h ; c6 46 13 03 ; 0xf7206 ps2mouse.c:360
+ jmp near 0732fh ; e9 22 01 ; 0xf720a ps2mouse.c:362
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf720d ps2mouse.c:366
+ test al, al ; 84 c0 ; 0xf7210
+ jbe short 0721dh ; 76 09 ; 0xf7212
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf7214
+ jbe short 0721bh ; 76 03 ; 0xf7216
+ jmp near 072c0h ; e9 a5 00 ; 0xf7218
+ jmp short 07287h ; eb 6a ; 0xf721b
+ mov ax, 000e9h ; b8 e9 00 ; 0xf721d ps2mouse.c:368
+ call 06e40h ; e8 1d fc ; 0xf7220
+ test al, al ; 84 c0 ; 0xf7223 ps2mouse.c:369
+ jne short 07290h ; 75 69 ; 0xf7225
+ mov dx, ss ; 8c d2 ; 0xf7227 ps2mouse.c:370
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf7229
+ call 06e78h ; e8 49 fc ; 0xf722c
+ mov dl, al ; 88 c2 ; 0xf722f
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf7231 ps2mouse.c:371
+ je short 0724bh ; 74 14 ; 0xf7235
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7237 ps2mouse.c:372
+ xor ah, ah ; 30 e4 ; 0xf723a
+ push ax ; 50 ; 0xf723c
+ mov ax, 0092eh ; b8 2e 09 ; 0xf723d
+ push ax ; 50 ; 0xf7240
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf7241
+ push ax ; 50 ; 0xf7244
+ call 0190fh ; e8 c7 a6 ; 0xf7245
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7248
+ test dl, dl ; 84 d2 ; 0xf724b ps2mouse.c:373
+ jne short 07290h ; 75 41 ; 0xf724d
+ mov dx, ss ; 8c d2 ; 0xf724f ps2mouse.c:374
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf7251
+ call 06e78h ; e8 21 fc ; 0xf7254
+ test al, al ; 84 c0 ; 0xf7257 ps2mouse.c:375
+ jne short 072b6h ; 75 5b ; 0xf7259
+ mov dx, ss ; 8c d2 ; 0xf725b ps2mouse.c:376
+ lea ax, [bp-004h] ; 8d 46 fc ; 0xf725d
+ call 06e78h ; e8 15 fc ; 0xf7260
+ test al, al ; 84 c0 ; 0xf7263 ps2mouse.c:377
+ jne short 072b6h ; 75 4f ; 0xf7265
+ mov dx, ss ; 8c d2 ; 0xf7267 ps2mouse.c:378
+ lea ax, [bp-002h] ; 8d 46 fe ; 0xf7269
+ call 06e78h ; e8 09 fc ; 0xf726c
+ test al, al ; 84 c0 ; 0xf726f ps2mouse.c:379
+ jne short 072b6h ; 75 43 ; 0xf7271
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7273 ps2mouse.c:380
+ mov byte [bp+00ch], al ; 88 46 0c ; 0xf7276
+ mov al, byte [bp-004h] ; 8a 46 fc ; 0xf7279 ps2mouse.c:381
+ mov byte [bp+010h], al ; 88 46 10 ; 0xf727c
+ mov al, byte [bp-002h] ; 8a 46 fe ; 0xf727f ps2mouse.c:382
+ mov byte [bp+00eh], al ; 88 46 0e ; 0xf7282
+ jmp short 0720ah ; eb 83 ; 0xf7285 ps2mouse.c:384
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf7287 ps2mouse.c:398
+ jne short 07292h ; 75 07 ; 0xf7289
+ mov ax, 000e6h ; b8 e6 00 ; 0xf728b ps2mouse.c:399
+ jmp short 07295h ; eb 05 ; 0xf728e ps2mouse.c:400
+ jmp short 072b6h ; eb 24 ; 0xf7290
+ mov ax, 000e7h ; b8 e7 00 ; 0xf7292 ps2mouse.c:401
+ call 06e40h ; e8 a8 fb ; 0xf7295
+ mov dl, al ; 88 c2 ; 0xf7298
+ test dl, dl ; 84 d2 ; 0xf729a ps2mouse.c:403
+ jne short 072b2h ; 75 14 ; 0xf729c
+ mov dx, ss ; 8c d2 ; 0xf729e ps2mouse.c:404
+ lea ax, [bp-006h] ; 8d 46 fa ; 0xf72a0
+ call 06e78h ; e8 d2 fb ; 0xf72a3
+ cmp byte [bp-006h], 0fah ; 80 7e fa fa ; 0xf72a6 ps2mouse.c:405
+ je short 072b0h ; 74 04 ; 0xf72aa
+ mov DL, strict byte 001h ; b2 01 ; 0xf72ac
+ jmp short 072b2h ; eb 02 ; 0xf72ae
+ xor dl, dl ; 30 d2 ; 0xf72b0
+ test dl, dl ; 84 d2 ; 0xf72b2 ps2mouse.c:407
+ je short 07317h ; 74 61 ; 0xf72b4
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf72b6 ps2mouse.c:409
+ mov byte [bp+013h], 003h ; c6 46 13 03 ; 0xf72ba ps2mouse.c:410
+ jmp short 07317h ; eb 57 ; 0xf72be ps2mouse.c:412
+ mov al, byte [bp+00dh] ; 8a 46 0d ; 0xf72c0 ps2mouse.c:415
+ xor ah, ah ; 30 e4 ; 0xf72c3
+ push ax ; 50 ; 0xf72c5
+ mov ax, 0095ah ; b8 5a 09 ; 0xf72c6
+ push ax ; 50 ; 0xf72c9
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf72ca
+ push ax ; 50 ; 0xf72cd
+ call 0190fh ; e8 3e a6 ; 0xf72ce
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf72d1
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf72d4 ps2mouse.c:417
+ mov byte [bp+013h], 001h ; c6 46 13 01 ; 0xf72d8 ps2mouse.c:418
+ jmp short 0732fh ; eb 51 ; 0xf72dc ps2mouse.c:420
+ mov cx, word [bp+00ch] ; 8b 4e 0c ; 0xf72de ps2mouse.c:425
+ mov bx, strict word 00022h ; bb 22 00 ; 0xf72e1 ps2mouse.c:53
+ mov es, dx ; 8e c2 ; 0xf72e4
+ mov word [es:bx], cx ; 26 89 0f ; 0xf72e6
+ mov bx, strict word 00024h ; bb 24 00 ; 0xf72e9 ps2mouse.c:53
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf72ec
+ mov word [es:bx], ax ; 26 89 07 ; 0xf72ef
+ mov bx, strict word 00027h ; bb 27 00 ; 0xf72f2 ps2mouse.c:38
+ mov ah, byte [es:bx] ; 26 8a 27 ; 0xf72f5
+ mov al, ah ; 88 e0 ; 0xf72f8 ps2mouse.c:39
+ test cx, cx ; 85 c9 ; 0xf72fa ps2mouse.c:429
+ jne short 0730dh ; 75 0f ; 0xf72fc
+ cmp word [bp+014h], strict byte 00000h ; 83 7e 14 00 ; 0xf72fe
+ jne short 0730dh ; 75 09 ; 0xf7302
+ test ah, 080h ; f6 c4 80 ; 0xf7304 ps2mouse.c:431
+ je short 0730fh ; 74 06 ; 0xf7307
+ and AL, strict byte 07fh ; 24 7f ; 0xf7309 ps2mouse.c:432
+ jmp short 0730fh ; eb 02 ; 0xf730b ps2mouse.c:435
+ or AL, strict byte 080h ; 0c 80 ; 0xf730d ps2mouse.c:437
+ mov bx, strict word 00027h ; bb 27 00 ; 0xf730f ps2mouse.c:43
+ mov es, dx ; 8e c2 ; 0xf7312
+ mov byte [es:bx], al ; 26 88 07 ; 0xf7314
+ jmp short 0732fh ; eb 16 ; 0xf7317 ps2mouse.c:440
+ mov ax, 00974h ; b8 74 09 ; 0xf7319 ps2mouse.c:443
+ push ax ; 50 ; 0xf731c
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf731d
+ push ax ; 50 ; 0xf7320
+ call 0190fh ; e8 eb a5 ; 0xf7321
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7324
+ or word [bp+018h], strict byte 00001h ; 83 4e 18 01 ; 0xf7327 ps2mouse.c:445
+ mov byte [bp+013h], 001h ; c6 46 13 01 ; 0xf732b ps2mouse.c:446
+ mov ax, strict word 00047h ; b8 47 00 ; 0xf732f ps2mouse.c:450
+ call 06ed5h ; e8 a0 fb ; 0xf7332
+ mov sp, bp ; 89 ec ; 0xf7335 ps2mouse.c:451
+ pop bp ; 5d ; 0xf7337
+ retn ; c3 ; 0xf7338
+ ; disGetNextSymbol 0xf7339 LB 0x2c0f -> off=0x0 cb=00000000000000a9 uValue=00000000000f5d39 'int17_function'
+int17_function: ; 0xf7339 LB 0xa9
+ push bp ; 55 ; 0xf7339 parallel.c:60
+ mov bp, sp ; 89 e5 ; 0xf733a
+ push si ; 56 ; 0xf733c
+ push di ; 57 ; 0xf733d
+ push ax ; 50 ; 0xf733e
+ sti ; fb ; 0xf733f parallel.c:65
+ mov bx, word [bp+00eh] ; 8b 5e 0e ; 0xf7340 parallel.c:67
+ sal bx, 1 ; d1 e3 ; 0xf7343
+ add bx, strict byte 00008h ; 83 c3 08 ; 0xf7345
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf7348 parallel.c:48
+ mov es, ax ; 8e c0 ; 0xf734b
+ mov bx, word [es:bx] ; 26 8b 1f ; 0xf734d
+ mov di, bx ; 89 df ; 0xf7350 parallel.c:49
+ cmp byte [bp+013h], 003h ; 80 7e 13 03 ; 0xf7352 parallel.c:68
+ jnc short 07364h ; 73 0c ; 0xf7356
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf7358
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf735b
+ jnc short 07364h ; 73 04 ; 0xf735e
+ test bx, bx ; 85 db ; 0xf7360
+ jnbe short 07367h ; 77 03 ; 0xf7362
+ jmp near 073d7h ; e9 70 00 ; 0xf7364
+ mov si, ax ; 89 c6 ; 0xf7367 parallel.c:69
+ add si, strict byte 00078h ; 83 c6 78 ; 0xf7369
+ mov ch, byte [es:si] ; 26 8a 2c ; 0xf736c parallel.c:38
+ xor cl, cl ; 30 c9 ; 0xf736f parallel.c:39
+ cmp byte [bp+013h], 000h ; 80 7e 13 00 ; 0xf7371 parallel.c:70
+ jne short 073a3h ; 75 2c ; 0xf7375
+ mov al, byte [bp+012h] ; 8a 46 12 ; 0xf7377 parallel.c:71
+ mov dx, bx ; 89 da ; 0xf737a
+ out DX, AL ; ee ; 0xf737c
+ lea dx, [bx+002h] ; 8d 57 02 ; 0xf737d parallel.c:72
+ in AL, DX ; ec ; 0xf7380
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7381
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf7383
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7386 parallel.c:73
+ or AL, strict byte 001h ; 0c 01 ; 0xf7389
+ out DX, AL ; ee ; 0xf738b
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf738c parallel.c:74
+ and AL, strict byte 0feh ; 24 fe ; 0xf738f
+ out DX, AL ; ee ; 0xf7391
+ lea dx, [di+001h] ; 8d 55 01 ; 0xf7392 parallel.c:75
+ in AL, DX ; ec ; 0xf7395
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7396
+ test AL, strict byte 040h ; a8 40 ; 0xf7398
+ je short 073a3h ; 74 07 ; 0xf739a
+ test cx, cx ; 85 c9 ; 0xf739c
+ je short 073a3h ; 74 03 ; 0xf739e
+ dec cx ; 49 ; 0xf73a0 parallel.c:76
+ jmp short 07392h ; eb ef ; 0xf73a1 parallel.c:77
+ cmp byte [bp+013h], 001h ; 80 7e 13 01 ; 0xf73a3 parallel.c:79
+ jne short 073beh ; 75 15 ; 0xf73a7
+ lea dx, [di+002h] ; 8d 55 02 ; 0xf73a9 parallel.c:80
+ in AL, DX ; ec ; 0xf73ac
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf73ad
+ mov word [bp-006h], ax ; 89 46 fa ; 0xf73af
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf73b2 parallel.c:81
+ and AL, strict byte 0fbh ; 24 fb ; 0xf73b5
+ out DX, AL ; ee ; 0xf73b7
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf73b8 parallel.c:82
+ or AL, strict byte 004h ; 0c 04 ; 0xf73bb
+ out DX, AL ; ee ; 0xf73bd
+ lea dx, [di+001h] ; 8d 55 01 ; 0xf73be parallel.c:84
+ in AL, DX ; ec ; 0xf73c1
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf73c2
+ xor AL, strict byte 048h ; 34 48 ; 0xf73c4 parallel.c:85
+ mov byte [bp+013h], al ; 88 46 13 ; 0xf73c6
+ test cx, cx ; 85 c9 ; 0xf73c9 parallel.c:86
+ jne short 073d1h ; 75 04 ; 0xf73cb
+ or byte [bp+013h], 001h ; 80 4e 13 01 ; 0xf73cd
+ and byte [bp+01ch], 0feh ; 80 66 1c fe ; 0xf73d1 parallel.c:87
+ jmp short 073dbh ; eb 04 ; 0xf73d5 parallel.c:88
+ or byte [bp+01ch], 001h ; 80 4e 1c 01 ; 0xf73d7 parallel.c:89
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf73db parallel.c:91
+ pop di ; 5f ; 0xf73de
+ pop si ; 5e ; 0xf73df
+ pop bp ; 5d ; 0xf73e0
+ retn ; c3 ; 0xf73e1
+ ; disGetNextSymbol 0xf73e2 LB 0x2b66 -> off=0x0 cb=00000000000000c8 uValue=00000000000f5de2 '_wait_'
+_wait_: ; 0xf73e2 LB 0xc8
+ push bp ; 55 ; 0xf73e2 logo.c:171
+ mov bp, sp ; 89 e5 ; 0xf73e3
+ push bx ; 53 ; 0xf73e5
+ push cx ; 51 ; 0xf73e6
+ push si ; 56 ; 0xf73e7
+ push di ; 57 ; 0xf73e8
+ sub sp, strict byte 00010h ; 83 ec 10 ; 0xf73e9
+ mov cx, ax ; 89 c1 ; 0xf73ec
+ mov byte [bp-00ch], dl ; 88 56 f4 ; 0xf73ee
+ mov byte [bp-00ah], 000h ; c6 46 f6 00 ; 0xf73f1 logo.c:176
+ pushfw ; 9c ; 0xf73f5 logo.c:182
+ pop ax ; 58 ; 0xf73f6
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf73f7
+ sti ; fb ; 0xf73fa logo.c:183
+ xor dx, dx ; 31 d2 ; 0xf73fb logo.c:189
+ mov bx, 0046ch ; bb 6c 04 ; 0xf73fd logo.c:58
+ mov es, dx ; 8e c2 ; 0xf7400
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf7402
+ mov bx, word [es:bx+002h] ; 26 8b 5f 02 ; 0xf7405
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf7409 logo.c:59
+ hlt ; f4 ; 0xf740c logo.c:193
+ mov si, 0046ch ; be 6c 04 ; 0xf740d logo.c:58
+ xor ax, ax ; 31 c0 ; 0xf7410
+ mov es, ax ; 8e c0 ; 0xf7412
+ mov di, word [es:si] ; 26 8b 3c ; 0xf7414
+ mov ax, word [es:si+002h] ; 26 8b 44 02 ; 0xf7417
+ mov word [bp-016h], di ; 89 7e ea ; 0xf741b logo.c:59
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf741e
+ cmp ax, bx ; 39 d8 ; 0xf7421 logo.c:195
+ jnbe short 0742ch ; 77 07 ; 0xf7423
+ jne short 07433h ; 75 0c ; 0xf7425
+ cmp di, word [bp-010h] ; 3b 7e f0 ; 0xf7427
+ jbe short 07433h ; 76 07 ; 0xf742a
+ sub di, word [bp-010h] ; 2b 7e f0 ; 0xf742c logo.c:197
+ sbb ax, bx ; 19 d8 ; 0xf742f
+ jmp short 0743eh ; eb 0b ; 0xf7431 logo.c:200
+ cmp ax, bx ; 39 d8 ; 0xf7433
+ jc short 0743eh ; 72 07 ; 0xf7435
+ jne short 07442h ; 75 09 ; 0xf7437
+ cmp di, word [bp-010h] ; 3b 7e f0 ; 0xf7439
+ jnc short 07442h ; 73 04 ; 0xf743c
+ sub cx, di ; 29 f9 ; 0xf743e logo.c:201
+ sbb dx, ax ; 19 c2 ; 0xf7440
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf7442 logo.c:202
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf7445
+ mov bx, word [bp-012h] ; 8b 5e ee ; 0xf7448
+ mov ax, 00100h ; b8 00 01 ; 0xf744b logo.c:204
+ int 016h ; cd 16 ; 0xf744e
+ je short 07457h ; 74 05 ; 0xf7450
+ mov AL, strict byte 001h ; b0 01 ; 0xf7452
+ jmp near 07459h ; e9 02 00 ; 0xf7454
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xf7457
+ test al, al ; 84 c0 ; 0xf7459
+ je short 0748ch ; 74 2f ; 0xf745b
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf745d logo.c:206
+ int 016h ; cd 16 ; 0xf745f
+ xchg ah, al ; 86 c4 ; 0xf7461
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf7463
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf7466
+ mov byte [bp-018h], al ; 88 46 e8 ; 0xf7469 logo.c:207
+ mov byte [bp-017h], 000h ; c6 46 e9 00 ; 0xf746c
+ push word [bp-018h] ; ff 76 e8 ; 0xf7470
+ mov ax, 00996h ; b8 96 09 ; 0xf7473
+ push ax ; 50 ; 0xf7476
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf7477
+ push ax ; 50 ; 0xf747a
+ call 0190fh ; e8 91 a4 ; 0xf747b
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf747e
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf7481 logo.c:208
+ je short 0748ch ; 74 05 ; 0xf7485
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf7487 logo.c:209
+ jmp short 074a1h ; eb 15 ; 0xf748a
+ test dx, dx ; 85 d2 ; 0xf748c logo.c:211
+ jle short 07493h ; 7e 03 ; 0xf748e
+ jmp near 0740ch ; e9 79 ff ; 0xf7490
+ jne short 07499h ; 75 04 ; 0xf7493
+ test cx, cx ; 85 c9 ; 0xf7495
+ jnbe short 07490h ; 77 f7 ; 0xf7497
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf7499 logo.c:212
+ push ax ; 50 ; 0xf749c
+ popfw ; 9d ; 0xf749d
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf749e logo.c:213
+ lea sp, [bp-008h] ; 8d 66 f8 ; 0xf74a1 logo.c:214
+ pop di ; 5f ; 0xf74a4
+ pop si ; 5e ; 0xf74a5
+ pop cx ; 59 ; 0xf74a6
+ pop bx ; 5b ; 0xf74a7
+ pop bp ; 5d ; 0xf74a8
+ retn ; c3 ; 0xf74a9
+ ; disGetNextSymbol 0xf74aa LB 0x2a9e -> off=0x0 cb=0000000000000016 uValue=00000000000f5eaa 'read_logo_byte'
+read_logo_byte: ; 0xf74aa LB 0x16
+ push bp ; 55 ; 0xf74aa logo.c:216
+ mov bp, sp ; 89 e5 ; 0xf74ab
+ push dx ; 52 ; 0xf74ad
+ xor ah, ah ; 30 e4 ; 0xf74ae logo.c:218
+ or ah, 001h ; 80 cc 01 ; 0xf74b0
+ mov dx, 003b8h ; ba b8 03 ; 0xf74b3
+ out DX, ax ; ef ; 0xf74b6
+ in AL, DX ; ec ; 0xf74b7 logo.c:219
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf74b8
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf74ba logo.c:220
+ pop dx ; 5a ; 0xf74bd
+ pop bp ; 5d ; 0xf74be
+ retn ; c3 ; 0xf74bf
+ ; disGetNextSymbol 0xf74c0 LB 0x2a88 -> off=0x0 cb=0000000000000014 uValue=00000000000f5ec0 'read_logo_word'
+read_logo_word: ; 0xf74c0 LB 0x14
+ push bp ; 55 ; 0xf74c0 logo.c:222
+ mov bp, sp ; 89 e5 ; 0xf74c1
+ push dx ; 52 ; 0xf74c3
+ xor ah, ah ; 30 e4 ; 0xf74c4 logo.c:224
+ or ah, 001h ; 80 cc 01 ; 0xf74c6
+ mov dx, 003b8h ; ba b8 03 ; 0xf74c9
+ out DX, ax ; ef ; 0xf74cc
+ in ax, DX ; ed ; 0xf74cd logo.c:225
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf74ce logo.c:226
+ pop dx ; 5a ; 0xf74d1
+ pop bp ; 5d ; 0xf74d2
+ retn ; c3 ; 0xf74d3
+ ; disGetNextSymbol 0xf74d4 LB 0x2a74 -> off=0x0 cb=000000000000015f uValue=00000000000f5ed4 'print_detected_harddisks'
+print_detected_harddisks: ; 0xf74d4 LB 0x15f
+ push bp ; 55 ; 0xf74d4 logo.c:245
+ mov bp, sp ; 89 e5 ; 0xf74d5
+ push bx ; 53 ; 0xf74d7
+ push cx ; 51 ; 0xf74d8
+ push dx ; 52 ; 0xf74d9
+ push si ; 56 ; 0xf74da
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf74db
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf74de logo.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf74e1
+ mov es, ax ; 8e c0 ; 0xf74e4
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf74e6
+ mov si, ax ; 89 c6 ; 0xf74e9 logo.c:49
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf74eb logo.c:250
+ xor ch, ch ; 30 ed ; 0xf74ef logo.c:251
+ mov byte [bp-00ah], ch ; 88 6e f6 ; 0xf74f1 logo.c:252
+ mov bx, 00304h ; bb 04 03 ; 0xf74f4 logo.c:38
+ mov es, ax ; 8e c0 ; 0xf74f7
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf74f9
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf74fc logo.c:39
+ xor cl, cl ; 30 c9 ; 0xf74ff logo.c:257
+ cmp cl, byte [bp-00eh] ; 3a 4e f2 ; 0xf7501
+ jnc short 07564h ; 73 5e ; 0xf7504
+ mov bl, cl ; 88 cb ; 0xf7506 logo.c:259
+ xor bh, bh ; 30 ff ; 0xf7508
+ add bx, 00305h ; 81 c3 05 03 ; 0xf750a
+ mov es, si ; 8e c6 ; 0xf750e logo.c:38
+ mov bh, byte [es:bx] ; 26 8a 3f ; 0xf7510
+ mov bl, bh ; 88 fb ; 0xf7513 logo.c:39
+ cmp bh, 00ch ; 80 ff 0c ; 0xf7515 logo.c:262
+ jc short 07545h ; 72 2b ; 0xf7518
+ test ch, ch ; 84 ed ; 0xf751a logo.c:264
+ jne short 0752eh ; 75 10 ; 0xf751c
+ mov ax, 009a7h ; b8 a7 09 ; 0xf751e logo.c:266
+ push ax ; 50 ; 0xf7521
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf7522
+ push ax ; 50 ; 0xf7525
+ call 0190fh ; e8 e6 a3 ; 0xf7526
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7529
+ mov CH, strict byte 001h ; b5 01 ; 0xf752c logo.c:267
+ mov al, cl ; 88 c8 ; 0xf752e logo.c:270
+ xor ah, ah ; 30 e4 ; 0xf7530
+ inc ax ; 40 ; 0xf7532
+ push ax ; 50 ; 0xf7533
+ mov ax, 009bch ; b8 bc 09 ; 0xf7534
+ push ax ; 50 ; 0xf7537
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf7538
+ push ax ; 50 ; 0xf753b
+ call 0190fh ; e8 d0 a3 ; 0xf753c
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf753f
+ jmp near 075f9h ; e9 b4 00 ; 0xf7542 logo.c:273
+ cmp bh, 008h ; 80 ff 08 ; 0xf7545 logo.c:276
+ jc short 07567h ; 72 1d ; 0xf7548
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf754a logo.c:278
+ jne short 07562h ; 75 12 ; 0xf754e
+ mov ax, 009cfh ; b8 cf 09 ; 0xf7550 logo.c:280
+ push ax ; 50 ; 0xf7553
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf7554
+ push ax ; 50 ; 0xf7557
+ call 0190fh ; e8 b4 a3 ; 0xf7558
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf755b
+ mov byte [bp-00ah], 001h ; c6 46 f6 01 ; 0xf755e logo.c:281
+ jmp short 0752eh ; eb ca ; 0xf7562 logo.c:282
+ jmp near 075feh ; e9 97 00 ; 0xf7564
+ cmp bh, 004h ; 80 ff 04 ; 0xf7567 logo.c:291
+ jnc short 07586h ; 73 1a ; 0xf756a
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf756c
+ jne short 07586h ; 75 14 ; 0xf7570
+ mov ax, 009e4h ; b8 e4 09 ; 0xf7572 logo.c:293
+ push ax ; 50 ; 0xf7575
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf7576
+ push ax ; 50 ; 0xf7579
+ call 0190fh ; e8 92 a3 ; 0xf757a
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf757d
+ mov byte [bp-00ch], 001h ; c6 46 f4 01 ; 0xf7580 logo.c:294
+ jmp short 0759fh ; eb 19 ; 0xf7584 logo.c:296
+ cmp bl, 004h ; 80 fb 04 ; 0xf7586
+ jc short 0759fh ; 72 14 ; 0xf7589
+ test ch, ch ; 84 ed ; 0xf758b
+ jne short 0759fh ; 75 10 ; 0xf758d
+ mov ax, 009f6h ; b8 f6 09 ; 0xf758f logo.c:298
+ push ax ; 50 ; 0xf7592
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf7593
+ push ax ; 50 ; 0xf7596
+ call 0190fh ; e8 75 a3 ; 0xf7597
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf759a
+ mov CH, strict byte 001h ; b5 01 ; 0xf759d logo.c:299
+ mov al, cl ; 88 c8 ; 0xf759f logo.c:302
+ xor ah, ah ; 30 e4 ; 0xf75a1
+ inc ax ; 40 ; 0xf75a3
+ push ax ; 50 ; 0xf75a4
+ mov ax, 00a0ah ; b8 0a 0a ; 0xf75a5
+ push ax ; 50 ; 0xf75a8
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf75a9
+ push ax ; 50 ; 0xf75ac
+ call 0190fh ; e8 5f a3 ; 0xf75ad
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf75b0
+ cmp bl, 004h ; 80 fb 04 ; 0xf75b3 logo.c:309
+ jc short 075bbh ; 72 03 ; 0xf75b6
+ sub bl, 004h ; 80 eb 04 ; 0xf75b8 logo.c:310
+ mov al, bl ; 88 d8 ; 0xf75bb logo.c:312
+ xor ah, ah ; 30 e4 ; 0xf75bd
+ cwd ; 99 ; 0xf75bf
+ db 02bh, 0c2h
+ ; sub ax, dx ; 2b c2 ; 0xf75c0
+ sar ax, 1 ; d1 f8 ; 0xf75c2
+ test ax, ax ; 85 c0 ; 0xf75c4
+ je short 075cdh ; 74 05 ; 0xf75c6
+ mov ax, 00a14h ; b8 14 0a ; 0xf75c8 logo.c:313
+ jmp short 075d0h ; eb 03 ; 0xf75cb logo.c:314
+ mov ax, 00a1fh ; b8 1f 0a ; 0xf75cd logo.c:315
+ push ax ; 50 ; 0xf75d0
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf75d1
+ push ax ; 50 ; 0xf75d4
+ call 0190fh ; e8 37 a3 ; 0xf75d5
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf75d8
+ mov al, bl ; 88 d8 ; 0xf75db logo.c:317
+ xor ah, ah ; 30 e4 ; 0xf75dd
+ cwd ; 99 ; 0xf75df
+ mov bx, strict word 00002h ; bb 02 00 ; 0xf75e0
+ idiv bx ; f7 fb ; 0xf75e3
+ test dx, dx ; 85 d2 ; 0xf75e5
+ je short 075eeh ; 74 05 ; 0xf75e7
+ mov ax, 00a28h ; b8 28 0a ; 0xf75e9 logo.c:318
+ jmp short 075f1h ; eb 03 ; 0xf75ec logo.c:319
+ mov ax, 00a2eh ; b8 2e 0a ; 0xf75ee logo.c:320
+ push ax ; 50 ; 0xf75f1
+ push bx ; 53 ; 0xf75f2
+ call 0190fh ; e8 19 a3 ; 0xf75f3
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf75f6
+ db 0feh, 0c1h
+ ; inc cl ; fe c1 ; 0xf75f9 logo.c:322
+ jmp near 07501h ; e9 03 ff ; 0xf75fb
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf75fe logo.c:324
+ jne short 0761ch ; 75 18 ; 0xf7602
+ test ch, ch ; 84 ed ; 0xf7604
+ jne short 0761ch ; 75 14 ; 0xf7606
+ cmp byte [bp-00ah], 000h ; 80 7e f6 00 ; 0xf7608
+ jne short 0761ch ; 75 0e ; 0xf760c
+ mov ax, 00a35h ; b8 35 0a ; 0xf760e logo.c:327
+ push ax ; 50 ; 0xf7611
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf7612
+ push ax ; 50 ; 0xf7615
+ call 0190fh ; e8 f6 a2 ; 0xf7616
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7619
+ mov ax, 00a49h ; b8 49 0a ; 0xf761c logo.c:329
+ push ax ; 50 ; 0xf761f
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf7620
+ push ax ; 50 ; 0xf7623
+ call 0190fh ; e8 e8 a2 ; 0xf7624
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7627
+ lea sp, [bp-008h] ; 8d 66 f8 ; 0xf762a logo.c:330
+ pop si ; 5e ; 0xf762d
+ pop dx ; 5a ; 0xf762e
+ pop cx ; 59 ; 0xf762f
+ pop bx ; 5b ; 0xf7630
+ pop bp ; 5d ; 0xf7631
+ retn ; c3 ; 0xf7632
+ ; disGetNextSymbol 0xf7633 LB 0x2915 -> off=0x0 cb=0000000000000024 uValue=00000000000f6033 'get_boot_drive'
+get_boot_drive: ; 0xf7633 LB 0x24
+ push bx ; 53 ; 0xf7633 logo.c:332
+ push dx ; 52 ; 0xf7634
+ push bp ; 55 ; 0xf7635
+ mov bp, sp ; 89 e5 ; 0xf7636
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf7638 logo.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf763b
+ mov es, dx ; 8e c2 ; 0xf763e
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf7640
+ mov bx, 00304h ; bb 04 03 ; 0xf7643 logo.c:38
+ mov es, dx ; 8e c2 ; 0xf7646
+ mov dl, byte [es:bx] ; 26 8a 17 ; 0xf7648
+ sub AL, strict byte 002h ; 2c 02 ; 0xf764b logo.c:340
+ cmp al, dl ; 38 d0 ; 0xf764d logo.c:342
+ jc short 07653h ; 72 02 ; 0xf764f
+ mov AL, strict byte 0ffh ; b0 ff ; 0xf7651 logo.c:343
+ pop bp ; 5d ; 0xf7653 logo.c:347
+ pop dx ; 5a ; 0xf7654
+ pop bx ; 5b ; 0xf7655
+ retn ; c3 ; 0xf7656
+ ; disGetNextSymbol 0xf7657 LB 0x28f1 -> off=0x0 cb=000000000000025c uValue=00000000000f6057 'show_logo'
+show_logo: ; 0xf7657 LB 0x25c
+ push bp ; 55 ; 0xf7657 logo.c:349
+ mov bp, sp ; 89 e5 ; 0xf7658
+ push bx ; 53 ; 0xf765a
+ push cx ; 51 ; 0xf765b
+ push dx ; 52 ; 0xf765c
+ push si ; 56 ; 0xf765d
+ push di ; 57 ; 0xf765e
+ sub sp, strict byte 0000eh ; 83 ec 0e ; 0xf765f
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf7662 logo.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf7665
+ mov es, ax ; 8e c0 ; 0xf7668
+ mov si, word [es:bx] ; 26 8b 37 ; 0xf766a
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf766d logo.c:352
+ xor cx, cx ; 31 c9 ; 0xf7671 logo.c:356
+ mov AL, strict byte 034h ; b0 34 ; 0xf7673 logo.c:363
+ out strict byte 043h, AL ; e6 43 ; 0xf7675
+ mov AL, strict byte 0d3h ; b0 d3 ; 0xf7677
+ out strict byte 040h, AL ; e6 40 ; 0xf7679
+ mov AL, strict byte 048h ; b0 48 ; 0xf767b
+ out strict byte 040h, AL ; e6 40 ; 0xf767d
+ mov al, cl ; 88 c8 ; 0xf767f logo.c:366
+ xor ah, ah ; 30 e4 ; 0xf7681
+ call 074c0h ; e8 3a fe ; 0xf7683
+ cmp ax, 066bbh ; 3d bb 66 ; 0xf7686 logo.c:367
+ jne short 0769dh ; 75 12 ; 0xf7689
+ push SS ; 16 ; 0xf768b logo.c:371
+ pop ES ; 07 ; 0xf768c
+ lea di, [bp-018h] ; 8d 7e e8 ; 0xf768d
+ mov ax, 04f03h ; b8 03 4f ; 0xf7690
+ int 010h ; cd 10 ; 0xf7693
+ mov word [es:di], bx ; 26 89 1d ; 0xf7695
+ cmp ax, strict word 0004fh ; 3d 4f 00 ; 0xf7698
+ je short 076a0h ; 74 03 ; 0xf769b
+ jmp near 07789h ; e9 e9 00 ; 0xf769d logo.c:372
+ mov al, cl ; 88 c8 ; 0xf76a0 logo.c:375
+ add AL, strict byte 004h ; 04 04 ; 0xf76a2
+ xor ah, ah ; 30 e4 ; 0xf76a4
+ call 074aah ; e8 01 fe ; 0xf76a6
+ mov dl, al ; 88 c2 ; 0xf76a9
+ mov byte [bp-014h], al ; 88 46 ec ; 0xf76ab
+ mov al, cl ; 88 c8 ; 0xf76ae logo.c:376
+ add AL, strict byte 005h ; 04 05 ; 0xf76b0
+ xor ah, ah ; 30 e4 ; 0xf76b2
+ call 074aah ; e8 f3 fd ; 0xf76b4
+ mov ch, al ; 88 c5 ; 0xf76b7
+ mov byte [bp-010h], al ; 88 46 f0 ; 0xf76b9
+ mov al, cl ; 88 c8 ; 0xf76bc logo.c:377
+ add AL, strict byte 002h ; 04 02 ; 0xf76be
+ xor ah, ah ; 30 e4 ; 0xf76c0
+ call 074c0h ; e8 fb fd ; 0xf76c2
+ mov bx, ax ; 89 c3 ; 0xf76c5
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf76c7
+ mov al, cl ; 88 c8 ; 0xf76ca logo.c:378
+ add AL, strict byte 006h ; 04 06 ; 0xf76cc
+ xor ah, ah ; 30 e4 ; 0xf76ce
+ call 074aah ; e8 d7 fd ; 0xf76d0
+ mov byte [bp-012h], al ; 88 46 ee ; 0xf76d3
+ test dl, dl ; 84 d2 ; 0xf76d6 logo.c:381
+ jne short 076e2h ; 75 08 ; 0xf76d8
+ test ch, ch ; 84 ed ; 0xf76da
+ jne short 076e2h ; 75 04 ; 0xf76dc
+ test bx, bx ; 85 db ; 0xf76de
+ je short 0769dh ; 74 bb ; 0xf76e0
+ mov BH, strict byte 020h ; b7 20 ; 0xf76e2 logo.c:385
+ mov dx, 001e0h ; ba e0 01 ; 0xf76e4
+ mov cx, 00280h ; b9 80 02 ; 0xf76e7
+ mov ax, 05642h ; b8 42 56 ; 0xf76ea
+ mov BL, strict byte 000h ; b3 00 ; 0xf76ed
+ int 010h ; cd 10 ; 0xf76ef
+ cmp ax, strict word 0004fh ; 3d 4f 00 ; 0xf76f1 logo.c:387
+ je short 076feh ; 74 08 ; 0xf76f4
+ mov bx, 00142h ; bb 42 01 ; 0xf76f6 logo.c:388
+ mov ax, 04f02h ; b8 02 4f ; 0xf76f9
+ int 010h ; cd 10 ; 0xf76fc
+ cmp byte [bp-014h], 000h ; 80 7e ec 00 ; 0xf76fe logo.c:390
+ je short 07729h ; 74 25 ; 0xf7702
+ xor cx, cx ; 31 c9 ; 0xf7704 logo.c:392
+ jmp short 0770eh ; eb 06 ; 0xf7706
+ inc cx ; 41 ; 0xf7708 logo.c:394
+ cmp cx, strict byte 00010h ; 83 f9 10 ; 0xf7709
+ jnbe short 07730h ; 77 22 ; 0xf770c
+ mov ax, cx ; 89 c8 ; 0xf770e
+ or ah, 002h ; 80 cc 02 ; 0xf7710
+ mov dx, 003b8h ; ba b8 03 ; 0xf7713
+ out DX, ax ; ef ; 0xf7716
+ xor dx, dx ; 31 d2 ; 0xf7717
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf7719
+ call 073e2h ; e8 c3 fc ; 0xf771c
+ cmp AL, strict byte 086h ; 3c 86 ; 0xf771f
+ jne short 07708h ; 75 e5 ; 0xf7721
+ mov byte [bp-00ch], 001h ; c6 46 f4 01 ; 0xf7723
+ jmp short 07730h ; eb 07 ; 0xf7727
+ mov ax, 00210h ; b8 10 02 ; 0xf7729 logo.c:404
+ mov dx, 003b8h ; ba b8 03 ; 0xf772c
+ out DX, ax ; ef ; 0xf772f
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf7730 logo.c:407
+ jne short 0774bh ; 75 15 ; 0xf7734
+ mov CL, strict byte 004h ; b1 04 ; 0xf7736 logo.c:409
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf7738
+ shr ax, CL ; d3 e8 ; 0xf773b
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf773d
+ call 073e2h ; e8 9f fc ; 0xf7740
+ cmp AL, strict byte 086h ; 3c 86 ; 0xf7743 logo.c:410
+ jne short 0774bh ; 75 04 ; 0xf7745
+ mov byte [bp-00ch], 001h ; c6 46 f4 01 ; 0xf7747 logo.c:411
+ cmp byte [bp-010h], 000h ; 80 7e f0 00 ; 0xf774b logo.c:415
+ je short 0777ch ; 74 2b ; 0xf774f
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf7751
+ jne short 0777ch ; 75 25 ; 0xf7755
+ mov cx, strict word 00010h ; b9 10 00 ; 0xf7757 logo.c:417
+ jmp short 07761h ; eb 05 ; 0xf775a
+ dec cx ; 49 ; 0xf775c logo.c:419
+ test cx, cx ; 85 c9 ; 0xf775d
+ jbe short 07789h ; 76 28 ; 0xf775f
+ mov ax, cx ; 89 c8 ; 0xf7761
+ or ah, 002h ; 80 cc 02 ; 0xf7763
+ mov dx, 003b8h ; ba b8 03 ; 0xf7766
+ out DX, ax ; ef ; 0xf7769
+ xor dx, dx ; 31 d2 ; 0xf776a
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf776c
+ call 073e2h ; e8 70 fc ; 0xf776f
+ cmp AL, strict byte 086h ; 3c 86 ; 0xf7772
+ jne short 0775ch ; 75 e6 ; 0xf7774
+ mov byte [bp-00ch], 001h ; c6 46 f4 01 ; 0xf7776
+ jmp short 07789h ; eb 0d ; 0xf777a
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf777c logo.c:428
+ jne short 07789h ; 75 07 ; 0xf7780
+ mov ax, 00200h ; b8 00 02 ; 0xf7782 logo.c:429
+ mov dx, 003b8h ; ba b8 03 ; 0xf7785
+ out DX, ax ; ef ; 0xf7788
+ mov bx, 0037dh ; bb 7d 03 ; 0xf7789 logo.c:43
+ mov es, si ; 8e c6 ; 0xf778c
+ mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xf778e
+ mov AL, strict byte 003h ; b0 03 ; 0xf7792 logo.c:437
+ mov AH, strict byte 000h ; b4 00 ; 0xf7794
+ int 010h ; cd 10 ; 0xf7796
+ cmp byte [bp-012h], 000h ; 80 7e ee 00 ; 0xf7798 logo.c:440
+ je short 077b2h ; 74 14 ; 0xf779c
+ cmp byte [bp-014h], 000h ; 80 7e ec 00 ; 0xf779e logo.c:443
+ jne short 077e0h ; 75 3c ; 0xf77a2
+ cmp byte [bp-010h], 000h ; 80 7e f0 00 ; 0xf77a4
+ jne short 077e0h ; 75 36 ; 0xf77a8
+ cmp word [bp-016h], strict byte 00000h ; 83 7e ea 00 ; 0xf77aa
+ je short 077b5h ; 74 05 ; 0xf77ae
+ jmp short 077e0h ; eb 2e ; 0xf77b0
+ jmp near 07896h ; e9 e1 00 ; 0xf77b2
+ cmp byte [bp-012h], 002h ; 80 7e ee 02 ; 0xf77b5 logo.c:445
+ jne short 077c9h ; 75 0e ; 0xf77b9
+ mov ax, 00a4bh ; b8 4b 0a ; 0xf77bb logo.c:446
+ push ax ; 50 ; 0xf77be
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf77bf
+ push ax ; 50 ; 0xf77c2
+ call 0190fh ; e8 49 a1 ; 0xf77c3
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf77c6
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf77c9 logo.c:449
+ jne short 077e0h ; 75 11 ; 0xf77cd
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf77cf logo.c:452
+ mov ax, 000c0h ; b8 c0 00 ; 0xf77d2
+ call 073e2h ; e8 0a fc ; 0xf77d5
+ cmp AL, strict byte 086h ; 3c 86 ; 0xf77d8 logo.c:453
+ jne short 077e0h ; 75 04 ; 0xf77da
+ mov byte [bp-00ch], 001h ; c6 46 f4 01 ; 0xf77dc logo.c:454
+ cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xf77e0 logo.c:459
+ je short 077b2h ; 74 cc ; 0xf77e4
+ mov byte [bp-00eh], 000h ; c6 46 f2 00 ; 0xf77e6 logo.c:461
+ mov ax, 00100h ; b8 00 01 ; 0xf77ea logo.c:464
+ mov cx, 01000h ; b9 00 10 ; 0xf77ed
+ int 010h ; cd 10 ; 0xf77f0
+ mov ax, 00700h ; b8 00 07 ; 0xf77f2
+ mov BH, strict byte 007h ; b7 07 ; 0xf77f5
+ db 033h, 0c9h
+ ; xor cx, cx ; 33 c9 ; 0xf77f7
+ mov dx, 0184fh ; ba 4f 18 ; 0xf77f9
+ int 010h ; cd 10 ; 0xf77fc
+ mov ax, 00200h ; b8 00 02 ; 0xf77fe
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xf7801
+ db 033h, 0d2h
+ ; xor dx, dx ; 33 d2 ; 0xf7803
+ int 010h ; cd 10 ; 0xf7805
+ mov ax, 00a6dh ; b8 6d 0a ; 0xf7807 logo.c:467
+ push ax ; 50 ; 0xf780a
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf780b
+ push ax ; 50 ; 0xf780e
+ call 0190fh ; e8 fd a0 ; 0xf780f
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7812
+ call 074d4h ; e8 bc fc ; 0xf7815 logo.c:468
+ mov ax, 00ab1h ; b8 b1 0a ; 0xf7818 logo.c:469
+ push ax ; 50 ; 0xf781b
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf781c
+ push ax ; 50 ; 0xf781f
+ call 0190fh ; e8 ec a0 ; 0xf7820
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7823
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf7826 logo.c:478
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf7829
+ call 073e2h ; e8 b3 fb ; 0xf782c
+ mov cl, al ; 88 c1 ; 0xf782f
+ test al, al ; 84 c0 ; 0xf7831 logo.c:479
+ je short 07826h ; 74 f1 ; 0xf7833
+ cmp AL, strict byte 030h ; 3c 30 ; 0xf7835 logo.c:481
+ je short 07885h ; 74 4c ; 0xf7837
+ cmp cl, 002h ; 80 f9 02 ; 0xf7839 logo.c:488
+ jc short 0785eh ; 72 20 ; 0xf783c
+ cmp cl, 009h ; 80 f9 09 ; 0xf783e
+ jnbe short 0785eh ; 77 1b ; 0xf7841
+ mov al, cl ; 88 c8 ; 0xf7843 logo.c:490
+ xor ah, ah ; 30 e4 ; 0xf7845
+ call 07633h ; e8 e9 fd ; 0xf7847
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xf784a logo.c:497
+ jne short 07850h ; 75 02 ; 0xf784c
+ jmp short 07826h ; eb d6 ; 0xf784e logo.c:498
+ mov bx, 0037ch ; bb 7c 03 ; 0xf7850 logo.c:43
+ mov es, si ; 8e c6 ; 0xf7853
+ mov byte [es:bx], al ; 26 88 07 ; 0xf7855
+ mov byte [bp-00eh], 002h ; c6 46 f2 02 ; 0xf7858 logo.c:501
+ jmp short 07885h ; eb 27 ; 0xf785c logo.c:502
+ cmp cl, 02eh ; 80 f9 2e ; 0xf785e logo.c:505
+ je short 07873h ; 74 10 ; 0xf7861
+ cmp cl, 026h ; 80 f9 26 ; 0xf7863
+ je short 07879h ; 74 11 ; 0xf7866
+ cmp cl, 021h ; 80 f9 21 ; 0xf7868
+ jne short 0787fh ; 75 12 ; 0xf786b
+ mov byte [bp-00eh], 001h ; c6 46 f2 01 ; 0xf786d logo.c:509
+ jmp short 07885h ; eb 12 ; 0xf7871 logo.c:510
+ mov byte [bp-00eh], 003h ; c6 46 f2 03 ; 0xf7873 logo.c:513
+ jmp short 07885h ; eb 0c ; 0xf7877 logo.c:514
+ mov byte [bp-00eh], 004h ; c6 46 f2 04 ; 0xf7879 logo.c:517
+ jmp short 07885h ; eb 06 ; 0xf787d logo.c:518
+ cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xf787f logo.c:521
+ je short 07826h ; 74 a1 ; 0xf7883
+ mov bx, 0037dh ; bb 7d 03 ; 0xf7885 logo.c:43
+ mov es, si ; 8e c6 ; 0xf7888
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf788a
+ mov byte [es:bx], al ; 26 88 07 ; 0xf788d
+ mov AL, strict byte 003h ; b0 03 ; 0xf7890 logo.c:528
+ mov AH, strict byte 000h ; b4 00 ; 0xf7892
+ int 010h ; cd 10 ; 0xf7894
+ mov AL, strict byte 034h ; b0 34 ; 0xf7896 logo.c:533
+ out strict byte 043h, AL ; e6 43 ; 0xf7898
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf789a
+ out strict byte 040h, AL ; e6 40 ; 0xf789c
+ out strict byte 040h, AL ; e6 40 ; 0xf789e
+ push bp ; 55 ; 0xf78a0
+ push DS ; 1e ; 0xf78a1
+ mov ds, ax ; 8e d8 ; 0xf78a2
+ call 0ede3h ; e8 3c 75 ; 0xf78a4
+ pop DS ; 1f ; 0xf78a7
+ pop bp ; 5d ; 0xf78a8
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf78a9 logo.c:536
+ pop di ; 5f ; 0xf78ac
+ pop si ; 5e ; 0xf78ad
+ pop dx ; 5a ; 0xf78ae
+ pop cx ; 59 ; 0xf78af
+ pop bx ; 5b ; 0xf78b0
+ pop bp ; 5d ; 0xf78b1
+ retn ; c3 ; 0xf78b2
+ ; disGetNextSymbol 0xf78b3 LB 0x2695 -> off=0x0 cb=0000000000000072 uValue=00000000000f62b3 'delay_boot'
+delay_boot: ; 0xf78b3 LB 0x72
+ push bp ; 55 ; 0xf78b3 logo.c:539
+ mov bp, sp ; 89 e5 ; 0xf78b4
+ push bx ; 53 ; 0xf78b6
+ push cx ; 51 ; 0xf78b7
+ push dx ; 52 ; 0xf78b8
+ push si ; 56 ; 0xf78b9
+ push di ; 57 ; 0xf78ba
+ mov bx, ax ; 89 c3 ; 0xf78bb
+ test ax, ax ; 85 c0 ; 0xf78bd logo.c:543
+ je short 0791bh ; 74 5a ; 0xf78bf
+ mov AL, strict byte 034h ; b0 34 ; 0xf78c1 logo.c:547
+ out strict byte 043h, AL ; e6 43 ; 0xf78c3
+ mov AL, strict byte 0d3h ; b0 d3 ; 0xf78c5
+ out strict byte 040h, AL ; e6 40 ; 0xf78c7
+ mov AL, strict byte 048h ; b0 48 ; 0xf78c9
+ out strict byte 040h, AL ; e6 40 ; 0xf78cb
+ push bx ; 53 ; 0xf78cd logo.c:549
+ mov ax, 00afbh ; b8 fb 0a ; 0xf78ce
+ push ax ; 50 ; 0xf78d1
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf78d2
+ push ax ; 50 ; 0xf78d5
+ call 0190fh ; e8 36 a0 ; 0xf78d6
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf78d9
+ test bx, bx ; 85 db ; 0xf78dc logo.c:550
+ jbe short 078fah ; 76 1a ; 0xf78de
+ push bx ; 53 ; 0xf78e0 logo.c:552
+ mov ax, 00b19h ; b8 19 0b ; 0xf78e1
+ push ax ; 50 ; 0xf78e4
+ mov ax, strict word 00002h ; b8 02 00 ; 0xf78e5
+ push ax ; 50 ; 0xf78e8
+ call 0190fh ; e8 23 a0 ; 0xf78e9
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf78ec
+ xor dx, dx ; 31 d2 ; 0xf78ef logo.c:553
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf78f1
+ call 073e2h ; e8 eb fa ; 0xf78f4
+ dec bx ; 4b ; 0xf78f7 logo.c:554
+ jmp short 078dch ; eb e2 ; 0xf78f8
+ mov bx, 00a49h ; bb 49 0a ; 0xf78fa logo.c:555
+ push bx ; 53 ; 0xf78fd
+ mov bx, strict word 00002h ; bb 02 00 ; 0xf78fe
+ push bx ; 53 ; 0xf7901
+ call 0190fh ; e8 0a a0 ; 0xf7902
+ add sp, strict byte 00004h ; 83 c4 04 ; 0xf7905
+ mov AL, strict byte 034h ; b0 34 ; 0xf7908 logo.c:557
+ out strict byte 043h, AL ; e6 43 ; 0xf790a
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf790c
+ out strict byte 040h, AL ; e6 40 ; 0xf790e
+ out strict byte 040h, AL ; e6 40 ; 0xf7910
+ push bp ; 55 ; 0xf7912
+ push DS ; 1e ; 0xf7913
+ mov ds, ax ; 8e d8 ; 0xf7914
+ call 0ede3h ; e8 ca 74 ; 0xf7916
+ pop DS ; 1f ; 0xf7919
+ pop bp ; 5d ; 0xf791a
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf791b logo.c:558
+ pop di ; 5f ; 0xf791e
+ pop si ; 5e ; 0xf791f
+ pop dx ; 5a ; 0xf7920
+ pop cx ; 59 ; 0xf7921
+ pop bx ; 5b ; 0xf7922
+ pop bp ; 5d ; 0xf7923
+ retn ; c3 ; 0xf7924
+ ; disGetNextSymbol 0xf7925 LB 0x2623 -> off=0x0 cb=00000000000000d5 uValue=00000000000f6325 'scsi_cmd_data_in'
+scsi_cmd_data_in: ; 0xf7925 LB 0xd5
+ push bp ; 55 ; 0xf7925 scsi.c:99
+ mov bp, sp ; 89 e5 ; 0xf7926
+ push si ; 56 ; 0xf7928
+ push di ; 57 ; 0xf7929
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf792a
+ mov si, ax ; 89 c6 ; 0xf792d
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf792f
+ mov word [bp-00ah], bx ; 89 5e f6 ; 0xf7932
+ mov word [bp-008h], cx ; 89 4e f8 ; 0xf7935
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf7938
+ mov dx, si ; 89 f2 ; 0xf793b scsi.c:107
+ in AL, DX ; ec ; 0xf793d
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf793e
+ test AL, strict byte 001h ; a8 01 ; 0xf7940 scsi.c:108
+ jne short 0793bh ; 75 f7 ; 0xf7942
+ mov al, byte [bp+004h] ; 8a 46 04 ; 0xf7944 scsi.c:110
+ cmp AL, strict byte 010h ; 3c 10 ; 0xf7947
+ jne short 0794fh ; 75 04 ; 0xf7949
+ xor ax, ax ; 31 c0 ; 0xf794b
+ jmp short 07951h ; eb 02 ; 0xf794d
+ xor ah, ah ; 30 e4 ; 0xf794f
+ mov di, ax ; 89 c7 ; 0xf7951
+ mov ax, bx ; 89 d8 ; 0xf7953
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf7955
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf7958
+ shr dx, 1 ; d1 ea ; 0xf795b
+ rcr ax, 1 ; d1 d8 ; 0xf795d
+ loop 0795bh ; e2 fa ; 0xf795f
+ mov cx, ax ; 89 c1 ; 0xf7961
+ and cx, 000f0h ; 81 e1 f0 00 ; 0xf7963
+ or cx, di ; 09 f9 ; 0xf7967
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7969 scsi.c:111
+ mov dx, si ; 89 f2 ; 0xf796c
+ out DX, AL ; ee ; 0xf796e
+ xor al, al ; 30 c0 ; 0xf796f scsi.c:112
+ out DX, AL ; ee ; 0xf7971
+ mov al, cl ; 88 c8 ; 0xf7972 scsi.c:113
+ out DX, AL ; ee ; 0xf7974
+ mov al, bl ; 88 d8 ; 0xf7975 scsi.c:114
+ out DX, AL ; ee ; 0xf7977
+ mov ax, bx ; 89 d8 ; 0xf7978 scsi.c:115
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf797a
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf797d
+ shr dx, 1 ; d1 ea ; 0xf7980
+ rcr ax, 1 ; d1 d8 ; 0xf7982
+ loop 07980h ; e2 fa ; 0xf7984
+ mov dx, si ; 89 f2 ; 0xf7986
+ out DX, AL ; ee ; 0xf7988
+ xor cx, cx ; 31 c9 ; 0xf7989 scsi.c:116
+ mov al, byte [bp+004h] ; 8a 46 04 ; 0xf798b
+ xor ah, ah ; 30 e4 ; 0xf798e
+ cmp cx, ax ; 39 c1 ; 0xf7990
+ jnc short 079a2h ; 73 0e ; 0xf7992
+ les di, [bp-00ah] ; c4 7e f6 ; 0xf7994 scsi.c:117
+ add di, cx ; 01 cf ; 0xf7997
+ mov al, byte [es:di] ; 26 8a 05 ; 0xf7999
+ mov dx, si ; 89 f2 ; 0xf799c
+ out DX, AL ; ee ; 0xf799e
+ inc cx ; 41 ; 0xf799f
+ jmp short 0798bh ; eb e9 ; 0xf79a0
+ mov dx, si ; 89 f2 ; 0xf79a2 scsi.c:121
+ in AL, DX ; ec ; 0xf79a4
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf79a5
+ test AL, strict byte 001h ; a8 01 ; 0xf79a7 scsi.c:122
+ jne short 079a2h ; 75 f7 ; 0xf79a9
+ test AL, strict byte 002h ; a8 02 ; 0xf79ab scsi.c:125
+ je short 079bdh ; 74 0e ; 0xf79ad
+ lea dx, [si+003h] ; 8d 54 03 ; 0xf79af scsi.c:126
+ xor al, al ; 30 c0 ; 0xf79b2
+ out DX, AL ; ee ; 0xf79b4
+ in AL, DX ; ec ; 0xf79b5 scsi.c:128
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf79b6
+ mov di, strict word 00004h ; bf 04 00 ; 0xf79b8 scsi.c:130
+ jmp short 079efh ; eb 32 ; 0xf79bb
+ lea dx, [si+001h] ; 8d 54 01 ; 0xf79bd scsi.c:136
+ cmp word [bp+00ch], strict byte 00000h ; 83 7e 0c 00 ; 0xf79c0
+ jne short 079cch ; 75 06 ; 0xf79c4
+ cmp bx, 08000h ; 81 fb 00 80 ; 0xf79c6
+ jbe short 079e6h ; 76 1a ; 0xf79ca
+ mov cx, 08000h ; b9 00 80 ; 0xf79cc scsi.c:138
+ les di, [bp+006h] ; c4 7e 06 ; 0xf79cf
+ rep insb ; f3 6c ; 0xf79d2
+ add bx, 08000h ; 81 c3 00 80 ; 0xf79d4 scsi.c:139
+ adc word [bp+00ch], strict byte 0ffffh ; 83 56 0c ff ; 0xf79d8
+ mov ax, es ; 8c c0 ; 0xf79dc
+ add ax, 00800h ; 05 00 08 ; 0xf79de
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf79e1
+ jmp short 079bdh ; eb d7 ; 0xf79e4 scsi.c:141
+ mov cx, bx ; 89 d9 ; 0xf79e6 scsi.c:144
+ les di, [bp+006h] ; c4 7e 06 ; 0xf79e8
+ rep insb ; f3 6c ; 0xf79eb
+ xor di, di ; 31 ff ; 0xf79ed scsi.c:146
+ mov ax, di ; 89 f8 ; 0xf79ef scsi.c:147
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf79f1
+ pop di ; 5f ; 0xf79f4
+ pop si ; 5e ; 0xf79f5
+ pop bp ; 5d ; 0xf79f6
+ retn 0000ah ; c2 0a 00 ; 0xf79f7
+ ; disGetNextSymbol 0xf79fa LB 0x254e -> off=0x0 cb=00000000000000d5 uValue=00000000000f63fa 'scsi_cmd_data_out'
+scsi_cmd_data_out: ; 0xf79fa LB 0xd5
+ push bp ; 55 ; 0xf79fa scsi.c:149
+ mov bp, sp ; 89 e5 ; 0xf79fb
+ push si ; 56 ; 0xf79fd
+ push di ; 57 ; 0xf79fe
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf79ff
+ mov di, ax ; 89 c7 ; 0xf7a02
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf7a04
+ mov word [bp-00ah], bx ; 89 5e f6 ; 0xf7a07
+ mov word [bp-008h], cx ; 89 4e f8 ; 0xf7a0a
+ mov bx, word [bp+00ah] ; 8b 5e 0a ; 0xf7a0d
+ mov dx, di ; 89 fa ; 0xf7a10 scsi.c:157
+ in AL, DX ; ec ; 0xf7a12
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7a13
+ test AL, strict byte 001h ; a8 01 ; 0xf7a15 scsi.c:158
+ jne short 07a10h ; 75 f7 ; 0xf7a17
+ mov al, byte [bp+004h] ; 8a 46 04 ; 0xf7a19 scsi.c:161
+ cmp AL, strict byte 010h ; 3c 10 ; 0xf7a1c
+ jne short 07a24h ; 75 04 ; 0xf7a1e
+ xor ax, ax ; 31 c0 ; 0xf7a20
+ jmp short 07a26h ; eb 02 ; 0xf7a22
+ xor ah, ah ; 30 e4 ; 0xf7a24
+ mov si, ax ; 89 c6 ; 0xf7a26
+ mov ax, bx ; 89 d8 ; 0xf7a28
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf7a2a
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf7a2d
+ shr dx, 1 ; d1 ea ; 0xf7a30
+ rcr ax, 1 ; d1 d8 ; 0xf7a32
+ loop 07a30h ; e2 fa ; 0xf7a34
+ mov cx, ax ; 89 c1 ; 0xf7a36
+ and cx, 000f0h ; 81 e1 f0 00 ; 0xf7a38
+ or cx, si ; 09 f1 ; 0xf7a3c
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7a3e scsi.c:162
+ mov dx, di ; 89 fa ; 0xf7a41
+ out DX, AL ; ee ; 0xf7a43
+ mov AL, strict byte 001h ; b0 01 ; 0xf7a44 scsi.c:163
+ out DX, AL ; ee ; 0xf7a46
+ mov al, cl ; 88 c8 ; 0xf7a47 scsi.c:164
+ out DX, AL ; ee ; 0xf7a49
+ mov al, bl ; 88 d8 ; 0xf7a4a scsi.c:165
+ out DX, AL ; ee ; 0xf7a4c
+ mov ax, bx ; 89 d8 ; 0xf7a4d scsi.c:166
+ mov dx, word [bp+00ch] ; 8b 56 0c ; 0xf7a4f
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf7a52
+ shr dx, 1 ; d1 ea ; 0xf7a55
+ rcr ax, 1 ; d1 d8 ; 0xf7a57
+ loop 07a55h ; e2 fa ; 0xf7a59
+ mov dx, di ; 89 fa ; 0xf7a5b
+ out DX, AL ; ee ; 0xf7a5d
+ xor cx, cx ; 31 c9 ; 0xf7a5e scsi.c:167
+ mov al, byte [bp+004h] ; 8a 46 04 ; 0xf7a60
+ xor ah, ah ; 30 e4 ; 0xf7a63
+ cmp cx, ax ; 39 c1 ; 0xf7a65
+ jnc short 07a77h ; 73 0e ; 0xf7a67
+ les si, [bp-00ah] ; c4 76 f6 ; 0xf7a69 scsi.c:168
+ add si, cx ; 01 ce ; 0xf7a6c
+ mov al, byte [es:si] ; 26 8a 04 ; 0xf7a6e
+ mov dx, di ; 89 fa ; 0xf7a71
+ out DX, AL ; ee ; 0xf7a73
+ inc cx ; 41 ; 0xf7a74
+ jmp short 07a60h ; eb e9 ; 0xf7a75
+ lea dx, [di+001h] ; 8d 55 01 ; 0xf7a77 scsi.c:173
+ cmp word [bp+00ch], strict byte 00000h ; 83 7e 0c 00 ; 0xf7a7a
+ jne short 07a86h ; 75 06 ; 0xf7a7e
+ cmp bx, 08000h ; 81 fb 00 80 ; 0xf7a80
+ jbe short 07aa1h ; 76 1b ; 0xf7a84
+ mov cx, 08000h ; b9 00 80 ; 0xf7a86 scsi.c:175
+ les si, [bp+006h] ; c4 76 06 ; 0xf7a89
+ db 0f3h, 026h, 06eh
+ ; rep es outsb ; f3 26 6e ; 0xf7a8c
+ add bx, 08000h ; 81 c3 00 80 ; 0xf7a8f scsi.c:176
+ adc word [bp+00ch], strict byte 0ffffh ; 83 56 0c ff ; 0xf7a93
+ mov ax, es ; 8c c0 ; 0xf7a97
+ add ax, 00800h ; 05 00 08 ; 0xf7a99
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf7a9c
+ jmp short 07a77h ; eb d6 ; 0xf7a9f scsi.c:178
+ mov cx, bx ; 89 d9 ; 0xf7aa1 scsi.c:181
+ les si, [bp+006h] ; c4 76 06 ; 0xf7aa3
+ db 0f3h, 026h, 06eh
+ ; rep es outsb ; f3 26 6e ; 0xf7aa6
+ mov dx, di ; 89 fa ; 0xf7aa9 scsi.c:185
+ in AL, DX ; ec ; 0xf7aab
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7aac
+ test AL, strict byte 001h ; a8 01 ; 0xf7aae scsi.c:186
+ jne short 07aa9h ; 75 f7 ; 0xf7ab0
+ test AL, strict byte 002h ; a8 02 ; 0xf7ab2 scsi.c:189
+ je short 07ac4h ; 74 0e ; 0xf7ab4
+ lea dx, [di+003h] ; 8d 55 03 ; 0xf7ab6 scsi.c:190
+ xor al, al ; 30 c0 ; 0xf7ab9
+ out DX, AL ; ee ; 0xf7abb
+ in AL, DX ; ec ; 0xf7abc scsi.c:192
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7abd
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf7abf scsi.c:194
+ jmp short 07ac6h ; eb 02 ; 0xf7ac2
+ xor ax, ax ; 31 c0 ; 0xf7ac4 scsi.c:197
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7ac6 scsi.c:198
+ pop di ; 5f ; 0xf7ac9
+ pop si ; 5e ; 0xf7aca
+ pop bp ; 5d ; 0xf7acb
+ retn 0000ah ; c2 0a 00 ; 0xf7acc
+ ; disGetNextSymbol 0xf7acf LB 0x2479 -> off=0x0 cb=00000000000000e9 uValue=00000000000f64cf 'scsi_read_sectors'
+scsi_read_sectors: ; 0xf7acf LB 0xe9
+ push bp ; 55 ; 0xf7acf scsi.c:207
+ mov bp, sp ; 89 e5 ; 0xf7ad0
+ push si ; 56 ; 0xf7ad2
+ push di ; 57 ; 0xf7ad3
+ sub sp, strict byte 00016h ; 83 ec 16 ; 0xf7ad4
+ mov si, word [bp+004h] ; 8b 76 04 ; 0xf7ad7
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7ada scsi.c:216
+ mov al, byte [es:si+00ch] ; 26 8a 44 0c ; 0xf7add
+ sub AL, strict byte 008h ; 2c 08 ; 0xf7ae1
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf7ae3
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf7ae6 scsi.c:217
+ jbe short 07affh ; 76 15 ; 0xf7ae8
+ xor ah, ah ; 30 e4 ; 0xf7aea scsi.c:218
+ push ax ; 50 ; 0xf7aec
+ mov ax, 00b1eh ; b8 1e 0b ; 0xf7aed
+ push ax ; 50 ; 0xf7af0
+ mov ax, 00b30h ; b8 30 0b ; 0xf7af1
+ push ax ; 50 ; 0xf7af4
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf7af5
+ push ax ; 50 ; 0xf7af8
+ call 0190fh ; e8 13 9e ; 0xf7af9
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf7afc
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7aff scsi.c:220
+ mov di, word [es:si+00eh] ; 26 8b 7c 0e ; 0xf7b02
+ mov word [bp-01ah], 00088h ; c7 46 e6 88 00 ; 0xf7b06 scsi.c:223
+ mov ax, word [es:si+006h] ; 26 8b 44 06 ; 0xf7b0b scsi.c:224
+ mov bx, word [es:si+004h] ; 26 8b 5c 04 ; 0xf7b0f
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf7b13
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf7b17
+ xchg ah, al ; 86 c4 ; 0xf7b1a
+ xchg bh, bl ; 86 df ; 0xf7b1c
+ xchg ch, cl ; 86 cd ; 0xf7b1e
+ xchg dh, dl ; 86 d6 ; 0xf7b20
+ xchg dx, ax ; 92 ; 0xf7b22
+ xchg bx, cx ; 87 cb ; 0xf7b23
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf7b25
+ mov word [bp-014h], bx ; 89 5e ec ; 0xf7b28
+ mov word [bp-016h], cx ; 89 4e ea ; 0xf7b2b
+ mov word [bp-018h], dx ; 89 56 e8 ; 0xf7b2e
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf7b31 scsi.c:225
+ mov ax, di ; 89 f8 ; 0xf7b35 scsi.c:226
+ xor dx, dx ; 31 d2 ; 0xf7b37
+ xchg ah, al ; 86 c4 ; 0xf7b39
+ xchg dh, dl ; 86 d6 ; 0xf7b3b
+ xchg dx, ax ; 92 ; 0xf7b3d
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf7b3e
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf7b41
+ mov byte [bp-00bh], 000h ; c6 46 f5 00 ; 0xf7b44 scsi.c:227
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7b48 scsi.c:230
+ xor ah, ah ; 30 e4 ; 0xf7b4b
+ sal ax, 1 ; d1 e0 ; 0xf7b4d
+ sal ax, 1 ; d1 e0 ; 0xf7b4f
+ mov bx, si ; 89 f3 ; 0xf7b51
+ add bx, ax ; 01 c3 ; 0xf7b53
+ mov ax, word [es:bx+0021ch] ; 26 8b 87 1c 02 ; 0xf7b55
+ mov bl, byte [es:bx+0021eh] ; 26 8a 9f 1e 02 ; 0xf7b5a scsi.c:231
+ mov word [bp-00ah], di ; 89 7e f6 ; 0xf7b5f scsi.c:236
+ mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xf7b62
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf7b67
+ sal word [bp-00ah], 1 ; d1 66 f6 ; 0xf7b6a
+ rcl word [bp-008h], 1 ; d1 56 f8 ; 0xf7b6d
+ loop 07b6ah ; e2 f8 ; 0xf7b70
+ push word [bp-008h] ; ff 76 f8 ; 0xf7b72
+ push word [bp-00ah] ; ff 76 f6 ; 0xf7b75
+ push word [es:si+00ah] ; 26 ff 74 0a ; 0xf7b78
+ push word [es:si+008h] ; 26 ff 74 08 ; 0xf7b7c
+ mov dx, strict word 00010h ; ba 10 00 ; 0xf7b80
+ push dx ; 52 ; 0xf7b83
+ mov dl, bl ; 88 da ; 0xf7b84
+ xor dh, dh ; 30 f6 ; 0xf7b86
+ mov cx, ss ; 8c d1 ; 0xf7b88
+ lea bx, [bp-01ah] ; 8d 5e e6 ; 0xf7b8a
+ call 07925h ; e8 95 fd ; 0xf7b8d
+ mov ah, al ; 88 c4 ; 0xf7b90
+ test al, al ; 84 c0 ; 0xf7b92 scsi.c:239
+ jne short 07babh ; 75 15 ; 0xf7b94
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7b96 scsi.c:241
+ mov word [es:si+018h], di ; 26 89 7c 18 ; 0xf7b99
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf7b9d scsi.c:242
+ mov word [es:si+01ah], dx ; 26 89 54 1a ; 0xf7ba0
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf7ba4
+ mov word [es:si+01ch], dx ; 26 89 54 1c ; 0xf7ba7
+ mov al, ah ; 88 e0 ; 0xf7bab scsi.c:246
+ xor ah, ah ; 30 e4 ; 0xf7bad
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7baf scsi.c:247
+ pop di ; 5f ; 0xf7bb2
+ pop si ; 5e ; 0xf7bb3
+ pop bp ; 5d ; 0xf7bb4
+ retn 00004h ; c2 04 00 ; 0xf7bb5
+ ; disGetNextSymbol 0xf7bb8 LB 0x2390 -> off=0x0 cb=00000000000000e9 uValue=00000000000f65b8 'scsi_write_sectors'
+scsi_write_sectors: ; 0xf7bb8 LB 0xe9
+ push bp ; 55 ; 0xf7bb8 scsi.c:256
+ mov bp, sp ; 89 e5 ; 0xf7bb9
+ push si ; 56 ; 0xf7bbb
+ push di ; 57 ; 0xf7bbc
+ sub sp, strict byte 00016h ; 83 ec 16 ; 0xf7bbd
+ mov si, word [bp+004h] ; 8b 76 04 ; 0xf7bc0
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7bc3 scsi.c:265
+ mov al, byte [es:si+00ch] ; 26 8a 44 0c ; 0xf7bc6
+ sub AL, strict byte 008h ; 2c 08 ; 0xf7bca
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf7bcc
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf7bcf scsi.c:266
+ jbe short 07be8h ; 76 15 ; 0xf7bd1
+ xor ah, ah ; 30 e4 ; 0xf7bd3 scsi.c:267
+ push ax ; 50 ; 0xf7bd5
+ mov ax, 00b4fh ; b8 4f 0b ; 0xf7bd6
+ push ax ; 50 ; 0xf7bd9
+ mov ax, 00b30h ; b8 30 0b ; 0xf7bda
+ push ax ; 50 ; 0xf7bdd
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf7bde
+ push ax ; 50 ; 0xf7be1
+ call 0190fh ; e8 2a 9d ; 0xf7be2
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf7be5
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7be8 scsi.c:269
+ mov di, word [es:si+00eh] ; 26 8b 7c 0e ; 0xf7beb
+ mov word [bp-01ah], 0008ah ; c7 46 e6 8a 00 ; 0xf7bef scsi.c:272
+ mov ax, word [es:si+006h] ; 26 8b 44 06 ; 0xf7bf4 scsi.c:273
+ mov bx, word [es:si+004h] ; 26 8b 5c 04 ; 0xf7bf8
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf7bfc
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf7c00
+ xchg ah, al ; 86 c4 ; 0xf7c03
+ xchg bh, bl ; 86 df ; 0xf7c05
+ xchg ch, cl ; 86 cd ; 0xf7c07
+ xchg dh, dl ; 86 d6 ; 0xf7c09
+ xchg dx, ax ; 92 ; 0xf7c0b
+ xchg bx, cx ; 87 cb ; 0xf7c0c
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf7c0e
+ mov word [bp-014h], bx ; 89 5e ec ; 0xf7c11
+ mov word [bp-016h], cx ; 89 4e ea ; 0xf7c14
+ mov word [bp-018h], dx ; 89 56 e8 ; 0xf7c17
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf7c1a scsi.c:274
+ mov ax, di ; 89 f8 ; 0xf7c1e scsi.c:275
+ xor dx, dx ; 31 d2 ; 0xf7c20
+ xchg ah, al ; 86 c4 ; 0xf7c22
+ xchg dh, dl ; 86 d6 ; 0xf7c24
+ xchg dx, ax ; 92 ; 0xf7c26
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf7c27
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf7c2a
+ mov byte [bp-00bh], 000h ; c6 46 f5 00 ; 0xf7c2d scsi.c:276
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7c31 scsi.c:278
+ xor ah, ah ; 30 e4 ; 0xf7c34
+ sal ax, 1 ; d1 e0 ; 0xf7c36
+ sal ax, 1 ; d1 e0 ; 0xf7c38
+ mov bx, si ; 89 f3 ; 0xf7c3a
+ add bx, ax ; 01 c3 ; 0xf7c3c
+ mov ax, word [es:bx+0021ch] ; 26 8b 87 1c 02 ; 0xf7c3e
+ mov bl, byte [es:bx+0021eh] ; 26 8a 9f 1e 02 ; 0xf7c43 scsi.c:279
+ mov word [bp-00ah], di ; 89 7e f6 ; 0xf7c48 scsi.c:284
+ mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xf7c4b
+ mov cx, strict word 00009h ; b9 09 00 ; 0xf7c50
+ sal word [bp-00ah], 1 ; d1 66 f6 ; 0xf7c53
+ rcl word [bp-008h], 1 ; d1 56 f8 ; 0xf7c56
+ loop 07c53h ; e2 f8 ; 0xf7c59
+ push word [bp-008h] ; ff 76 f8 ; 0xf7c5b
+ push word [bp-00ah] ; ff 76 f6 ; 0xf7c5e
+ push word [es:si+00ah] ; 26 ff 74 0a ; 0xf7c61
+ push word [es:si+008h] ; 26 ff 74 08 ; 0xf7c65
+ mov dx, strict word 00010h ; ba 10 00 ; 0xf7c69
+ push dx ; 52 ; 0xf7c6c
+ mov dl, bl ; 88 da ; 0xf7c6d
+ xor dh, dh ; 30 f6 ; 0xf7c6f
+ mov cx, ss ; 8c d1 ; 0xf7c71
+ lea bx, [bp-01ah] ; 8d 5e e6 ; 0xf7c73
+ call 079fah ; e8 81 fd ; 0xf7c76
+ mov ah, al ; 88 c4 ; 0xf7c79
+ test al, al ; 84 c0 ; 0xf7c7b scsi.c:287
+ jne short 07c94h ; 75 15 ; 0xf7c7d
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf7c7f scsi.c:289
+ mov word [es:si+018h], di ; 26 89 7c 18 ; 0xf7c82
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf7c86 scsi.c:290
+ mov word [es:si+01ah], dx ; 26 89 54 1a ; 0xf7c89
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf7c8d
+ mov word [es:si+01ch], dx ; 26 89 54 1c ; 0xf7c90
+ mov al, ah ; 88 e0 ; 0xf7c94 scsi.c:294
+ xor ah, ah ; 30 e4 ; 0xf7c96
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7c98 scsi.c:295
+ pop di ; 5f ; 0xf7c9b
+ pop si ; 5e ; 0xf7c9c
+ pop bp ; 5d ; 0xf7c9d
+ retn 00004h ; c2 04 00 ; 0xf7c9e
+ ; disGetNextSymbol 0xf7ca1 LB 0x22a7 -> off=0x0 cb=0000000000000174 uValue=00000000000f66a1 'scsi_cmd_packet'
+scsi_cmd_packet: ; 0xf7ca1 LB 0x174
+ push bp ; 55 ; 0xf7ca1 scsi.c:315
+ mov bp, sp ; 89 e5 ; 0xf7ca2
+ push si ; 56 ; 0xf7ca4
+ push di ; 57 ; 0xf7ca5
+ sub sp, strict byte 0000ch ; 83 ec 0c ; 0xf7ca6
+ mov byte [bp-008h], dl ; 88 56 f8 ; 0xf7ca9
+ mov word [bp-00ch], bx ; 89 5e f4 ; 0xf7cac
+ mov word [bp-00ah], cx ; 89 4e f6 ; 0xf7caf
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf7cb2 scsi.c:48
+ mov dx, strict word 00040h ; ba 40 00 ; 0xf7cb5
+ mov es, dx ; 8e c2 ; 0xf7cb8
+ mov dx, word [es:bx] ; 26 8b 17 ; 0xf7cba
+ mov si, 00122h ; be 22 01 ; 0xf7cbd scsi.c:49
+ mov word [bp-010h], dx ; 89 56 f0 ; 0xf7cc0
+ cmp byte [bp+00ah], 002h ; 80 7e 0a 02 ; 0xf7cc3 scsi.c:326
+ jne short 07cech ; 75 23 ; 0xf7cc7
+ mov bx, 00da0h ; bb a0 0d ; 0xf7cc9 scsi.c:327
+ mov cx, ds ; 8c d9 ; 0xf7ccc
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf7cce
+ call 018cch ; e8 f8 9b ; 0xf7cd1
+ mov ax, 00b62h ; b8 62 0b ; 0xf7cd4
+ push ax ; 50 ; 0xf7cd7
+ mov ax, 00b72h ; b8 72 0b ; 0xf7cd8
+ push ax ; 50 ; 0xf7cdb
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf7cdc
+ push ax ; 50 ; 0xf7cdf
+ call 0190fh ; e8 2c 9c ; 0xf7ce0
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7ce3
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf7ce6 scsi.c:328
+ jmp near 07e0ah ; e9 1e 01 ; 0xf7ce9
+ sub ax, strict word 00008h ; 2d 08 00 ; 0xf7cec scsi.c:332
+ sal ax, 1 ; d1 e0 ; 0xf7cef scsi.c:342
+ sal ax, 1 ; d1 e0 ; 0xf7cf1
+ sub byte [bp-008h], 002h ; 80 6e f8 02 ; 0xf7cf3 scsi.c:340
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf7cf7
+ mov di, si ; 89 f7 ; 0xf7cfa
+ add di, ax ; 01 c7 ; 0xf7cfc
+ mov bx, word [es:di+0021ch] ; 26 8b 9d 1c 02 ; 0xf7cfe
+ mov al, byte [es:di+0021eh] ; 26 8a 85 1e 02 ; 0xf7d03 scsi.c:343
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf7d08
+ mov dx, bx ; 89 da ; 0xf7d0b scsi.c:347
+ in AL, DX ; ec ; 0xf7d0d
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7d0e
+ test AL, strict byte 001h ; a8 01 ; 0xf7d10 scsi.c:348
+ jne short 07d0bh ; 75 f7 ; 0xf7d12
+ xor ax, ax ; 31 c0 ; 0xf7d14 scsi.c:354
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf7d16
+ add dx, word [bp+004h] ; 03 56 04 ; 0xf7d19
+ mov cx, word [bp+008h] ; 8b 4e 08 ; 0xf7d1c
+ adc cx, ax ; 11 c1 ; 0xf7d1f
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf7d21
+ mov ax, word [es:si+020h] ; 26 8b 44 20 ; 0xf7d24
+ xor di, di ; 31 ff ; 0xf7d28
+ add dx, ax ; 01 c2 ; 0xf7d2a
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf7d2c
+ adc di, cx ; 11 cf ; 0xf7d2f
+ mov ax, dx ; 89 d0 ; 0xf7d31 scsi.c:356
+ mov dx, di ; 89 fa ; 0xf7d33
+ mov cx, strict word 0000ch ; b9 0c 00 ; 0xf7d35
+ shr dx, 1 ; d1 ea ; 0xf7d38
+ rcr ax, 1 ; d1 d8 ; 0xf7d3a
+ loop 07d38h ; e2 fa ; 0xf7d3c
+ mov cx, ax ; 89 c1 ; 0xf7d3e
+ and cx, 000f0h ; 81 e1 f0 00 ; 0xf7d40
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf7d44
+ xor ah, ah ; 30 e4 ; 0xf7d47
+ or cx, ax ; 09 c1 ; 0xf7d49
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf7d4b scsi.c:357
+ mov dx, bx ; 89 da ; 0xf7d4e
+ out DX, AL ; ee ; 0xf7d50
+ xor al, al ; 30 c0 ; 0xf7d51 scsi.c:358
+ out DX, AL ; ee ; 0xf7d53
+ mov al, cl ; 88 c8 ; 0xf7d54 scsi.c:359
+ out DX, AL ; ee ; 0xf7d56
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf7d57 scsi.c:360
+ out DX, AL ; ee ; 0xf7d5a
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf7d5b scsi.c:361
+ mov dx, di ; 89 fa ; 0xf7d5e
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf7d60
+ shr dx, 1 ; d1 ea ; 0xf7d63
+ rcr ax, 1 ; d1 d8 ; 0xf7d65
+ loop 07d63h ; e2 fa ; 0xf7d67
+ mov dx, bx ; 89 da ; 0xf7d69
+ out DX, AL ; ee ; 0xf7d6b
+ xor cx, cx ; 31 c9 ; 0xf7d6c scsi.c:362
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf7d6e
+ xor ah, ah ; 30 e4 ; 0xf7d71
+ cmp cx, ax ; 39 c1 ; 0xf7d73
+ jnc short 07d85h ; 73 0e ; 0xf7d75
+ les di, [bp-00ch] ; c4 7e f4 ; 0xf7d77 scsi.c:363
+ add di, cx ; 01 cf ; 0xf7d7a
+ mov al, byte [es:di] ; 26 8a 05 ; 0xf7d7c
+ mov dx, bx ; 89 da ; 0xf7d7f
+ out DX, AL ; ee ; 0xf7d81
+ inc cx ; 41 ; 0xf7d82
+ jmp short 07d6eh ; eb e9 ; 0xf7d83
+ mov dx, bx ; 89 da ; 0xf7d85 scsi.c:367
+ in AL, DX ; ec ; 0xf7d87
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7d88
+ test AL, strict byte 001h ; a8 01 ; 0xf7d8a scsi.c:368
+ jne short 07d85h ; 75 f7 ; 0xf7d8c
+ test AL, strict byte 002h ; a8 02 ; 0xf7d8e scsi.c:371
+ je short 07da0h ; 74 0e ; 0xf7d90
+ lea dx, [bx+003h] ; 8d 57 03 ; 0xf7d92 scsi.c:372
+ xor al, al ; 30 c0 ; 0xf7d95
+ out DX, AL ; ee ; 0xf7d97
+ in AL, DX ; ec ; 0xf7d98 scsi.c:374
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf7d99
+ mov dx, strict word 00003h ; ba 03 00 ; 0xf7d9b scsi.c:376
+ jmp short 07e0ah ; eb 6a ; 0xf7d9e
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf7da0 scsi.c:381
+ test ax, ax ; 85 c0 ; 0xf7da3
+ je short 07dafh ; 74 08 ; 0xf7da5
+ lea dx, [bx+001h] ; 8d 57 01 ; 0xf7da7 scsi.c:382
+ mov cx, ax ; 89 c1 ; 0xf7daa
+ in AL, DX ; ec ; 0xf7dac
+ loop 07dach ; e2 fd ; 0xf7dad
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf7daf scsi.c:384
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf7db2
+ mov word [es:si+01ah], ax ; 26 89 44 1a ; 0xf7db5
+ mov ax, word [bp+008h] ; 8b 46 08 ; 0xf7db9
+ mov word [es:si+01ch], ax ; 26 89 44 1c ; 0xf7dbc
+ lea ax, [bx+001h] ; 8d 47 01 ; 0xf7dc0 scsi.c:389
+ cmp word [bp+008h], strict byte 00000h ; 83 7e 08 00 ; 0xf7dc3
+ jne short 07dd0h ; 75 07 ; 0xf7dc7
+ cmp word [bp+006h], 08000h ; 81 7e 06 00 80 ; 0xf7dc9
+ jbe short 07dedh ; 76 1d ; 0xf7dce
+ mov dx, ax ; 89 c2 ; 0xf7dd0 scsi.c:391
+ mov cx, 08000h ; b9 00 80 ; 0xf7dd2
+ les di, [bp+00ch] ; c4 7e 0c ; 0xf7dd5
+ rep insb ; f3 6c ; 0xf7dd8
+ add word [bp+006h], 08000h ; 81 46 06 00 80 ; 0xf7dda scsi.c:392
+ adc word [bp+008h], strict byte 0ffffh ; 83 56 08 ff ; 0xf7ddf
+ mov ax, es ; 8c c0 ; 0xf7de3
+ add ax, 00800h ; 05 00 08 ; 0xf7de5
+ mov word [bp+00eh], ax ; 89 46 0e ; 0xf7de8
+ jmp short 07dc0h ; eb d3 ; 0xf7deb scsi.c:394
+ mov dx, ax ; 89 c2 ; 0xf7ded scsi.c:397
+ mov cx, word [bp+006h] ; 8b 4e 06 ; 0xf7def
+ les di, [bp+00ch] ; c4 7e 0c ; 0xf7df2
+ rep insb ; f3 6c ; 0xf7df5
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf7df7 scsi.c:399
+ cmp word [es:si+020h], strict byte 00000h ; 26 83 7c 20 00 ; 0xf7dfa
+ je short 07e08h ; 74 07 ; 0xf7dff
+ mov cx, word [es:si+020h] ; 26 8b 4c 20 ; 0xf7e01 scsi.c:400
+ in AL, DX ; ec ; 0xf7e05
+ loop 07e05h ; e2 fd ; 0xf7e06
+ xor dx, dx ; 31 d2 ; 0xf7e08 scsi.c:402
+ mov ax, dx ; 89 d0 ; 0xf7e0a scsi.c:403
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf7e0c
+ pop di ; 5f ; 0xf7e0f
+ pop si ; 5e ; 0xf7e10
+ pop bp ; 5d ; 0xf7e11
+ retn 0000ch ; c2 0c 00 ; 0xf7e12
+ ; disGetNextSymbol 0xf7e15 LB 0x2133 -> off=0x0 cb=00000000000004cc uValue=00000000000f6815 'scsi_enumerate_attached_devices'
+scsi_enumerate_attached_devices: ; 0xf7e15 LB 0x4cc
+ push bp ; 55 ; 0xf7e15 scsi.c:411
+ mov bp, sp ; 89 e5 ; 0xf7e16
+ push bx ; 53 ; 0xf7e18
+ push cx ; 51 ; 0xf7e19
+ push dx ; 52 ; 0xf7e1a
+ push si ; 56 ; 0xf7e1b
+ push di ; 57 ; 0xf7e1c
+ sub sp, 0023eh ; 81 ec 3e 02 ; 0xf7e1d
+ push ax ; 50 ; 0xf7e21
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf7e22 scsi.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf7e25
+ mov es, ax ; 8e c0 ; 0xf7e28
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf7e2a
+ mov di, 00122h ; bf 22 01 ; 0xf7e2d scsi.c:49
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf7e30
+ mov word [bp-016h], strict word 00000h ; c7 46 ea 00 00 ; 0xf7e33 scsi.c:420
+ jmp near 08254h ; e9 19 04 ; 0xf7e38
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf7e3b scsi.c:440
+ jc short 07e42h ; 72 03 ; 0xf7e3d
+ jmp near 082d7h ; e9 95 04 ; 0xf7e3f
+ mov cx, strict word 00010h ; b9 10 00 ; 0xf7e42 scsi.c:455
+ xor bx, bx ; 31 db ; 0xf7e45
+ mov dx, ss ; 8c d2 ; 0xf7e47
+ lea ax, [bp-048h] ; 8d 46 b8 ; 0xf7e49
+ call 09c30h ; e8 e1 1d ; 0xf7e4c
+ mov byte [bp-048h], 09eh ; c6 46 b8 9e ; 0xf7e4f scsi.c:456
+ mov byte [bp-047h], 010h ; c6 46 b9 10 ; 0xf7e53 scsi.c:457
+ mov byte [bp-03bh], 020h ; c6 46 c5 20 ; 0xf7e57 scsi.c:458
+ xor ax, ax ; 31 c0 ; 0xf7e5b scsi.c:460
+ push ax ; 50 ; 0xf7e5d
+ mov ax, strict word 00020h ; b8 20 00 ; 0xf7e5e
+ push ax ; 50 ; 0xf7e61
+ lea dx, [bp-00248h] ; 8d 96 b8 fd ; 0xf7e62
+ push SS ; 16 ; 0xf7e66
+ push dx ; 52 ; 0xf7e67
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf7e68
+ push ax ; 50 ; 0xf7e6b
+ mov dl, byte [bp-016h] ; 8a 56 ea ; 0xf7e6c
+ xor dh, dh ; 30 f6 ; 0xf7e6f
+ mov cx, ss ; 8c d1 ; 0xf7e71
+ lea bx, [bp-048h] ; 8d 5e b8 ; 0xf7e73
+ mov ax, word [bp-0024ah] ; 8b 86 b6 fd ; 0xf7e76
+ call 07925h ; e8 a8 fa ; 0xf7e7a
+ test al, al ; 84 c0 ; 0xf7e7d scsi.c:461
+ je short 07e93h ; 74 12 ; 0xf7e7f
+ mov ax, 00b92h ; b8 92 0b ; 0xf7e81 scsi.c:462
+ push ax ; 50 ; 0xf7e84
+ mov ax, 00bcbh ; b8 cb 0b ; 0xf7e85
+ push ax ; 50 ; 0xf7e88
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf7e89
+ push ax ; 50 ; 0xf7e8c
+ call 0190fh ; e8 7f 9a ; 0xf7e8d
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf7e90
+ mov ax, word [bp-00242h] ; 8b 86 be fd ; 0xf7e93 scsi.c:467
+ mov bx, word [bp-00244h] ; 8b 9e bc fd ; 0xf7e97
+ mov cx, word [bp-00246h] ; 8b 8e ba fd ; 0xf7e9b
+ mov dx, word [bp-00248h] ; 8b 96 b8 fd ; 0xf7e9f
+ xchg ah, al ; 86 c4 ; 0xf7ea3
+ xchg bh, bl ; 86 df ; 0xf7ea5
+ xchg ch, cl ; 86 cd ; 0xf7ea7
+ xchg dh, dl ; 86 d6 ; 0xf7ea9
+ xchg dx, ax ; 92 ; 0xf7eab
+ xchg bx, cx ; 87 cb ; 0xf7eac
+ add dx, strict byte 00001h ; 83 c2 01 ; 0xf7eae
+ mov word [bp-01ah], dx ; 89 56 e6 ; 0xf7eb1
+ adc cx, strict byte 00000h ; 83 d1 00 ; 0xf7eb4
+ mov word [bp-02eh], cx ; 89 4e d2 ; 0xf7eb7
+ adc bx, strict byte 00000h ; 83 d3 00 ; 0xf7eba
+ mov word [bp-018h], bx ; 89 5e e8 ; 0xf7ebd
+ adc ax, strict word 00000h ; 15 00 00 ; 0xf7ec0
+ mov word [bp-02ah], ax ; 89 46 d6 ; 0xf7ec3
+ mov ah, byte [bp-00240h] ; 8a a6 c0 fd ; 0xf7ec6 scsi.c:469
+ xor al, al ; 30 c0 ; 0xf7eca
+ mov dl, byte [bp-0023fh] ; 8a 96 c1 fd ; 0xf7ecc
+ xor dh, dh ; 30 f6 ; 0xf7ed0
+ xor bx, bx ; 31 db ; 0xf7ed2
+ mov si, ax ; 89 c6 ; 0xf7ed4
+ or si, dx ; 09 d6 ; 0xf7ed6
+ mov al, byte [bp-0023eh] ; 8a 86 c2 fd ; 0xf7ed8
+ xor ah, ah ; 30 e4 ; 0xf7edc
+ xor dl, dl ; 30 d2 ; 0xf7ede
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf7ee0
+ sal ax, 1 ; d1 e0 ; 0xf7ee3
+ rcl dx, 1 ; d1 d2 ; 0xf7ee5
+ loop 07ee3h ; e2 fa ; 0xf7ee7
+ or bx, ax ; 09 c3 ; 0xf7ee9
+ or dx, si ; 09 f2 ; 0xf7eeb
+ mov al, byte [bp-0023dh] ; 8a 86 c3 fd ; 0xf7eed
+ xor ah, ah ; 30 e4 ; 0xf7ef1
+ or bx, ax ; 09 c3 ; 0xf7ef3
+ mov word [bp-012h], bx ; 89 5e ee ; 0xf7ef5
+ test dx, dx ; 85 d2 ; 0xf7ef8 scsi.c:475
+ jne short 07f02h ; 75 06 ; 0xf7efa
+ cmp bx, 00200h ; 81 fb 00 02 ; 0xf7efc
+ je short 07f25h ; 74 23 ; 0xf7f00
+ mov bx, 00da0h ; bb a0 0d ; 0xf7f02 scsi.c:478
+ mov cx, ds ; 8c d9 ; 0xf7f05
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf7f07
+ call 018cch ; e8 bf 99 ; 0xf7f0a
+ push dx ; 52 ; 0xf7f0d
+ push word [bp-012h] ; ff 76 ee ; 0xf7f0e
+ push word [bp-016h] ; ff 76 ea ; 0xf7f11
+ mov ax, 00beah ; b8 ea 0b ; 0xf7f14
+ push ax ; 50 ; 0xf7f17
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf7f18
+ push ax ; 50 ; 0xf7f1b
+ call 0190fh ; e8 f0 99 ; 0xf7f1c
+ add sp, strict byte 0000ah ; 83 c4 0a ; 0xf7f1f
+ jmp near 08248h ; e9 23 03 ; 0xf7f22 scsi.c:479
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf7f25 scsi.c:483
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf7f28
+ jc short 07f38h ; 72 0c ; 0xf7f2a
+ jbe short 07f40h ; 76 12 ; 0xf7f2c
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf7f2e
+ je short 07f48h ; 74 16 ; 0xf7f30
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf7f32
+ je short 07f44h ; 74 0e ; 0xf7f34
+ jmp short 07f8fh ; eb 57 ; 0xf7f36
+ test al, al ; 84 c0 ; 0xf7f38
+ jne short 07f8fh ; 75 53 ; 0xf7f3a
+ mov BL, strict byte 090h ; b3 90 ; 0xf7f3c scsi.c:486
+ jmp short 07f4ah ; eb 0a ; 0xf7f3e scsi.c:487
+ mov BL, strict byte 098h ; b3 98 ; 0xf7f40 scsi.c:489
+ jmp short 07f4ah ; eb 06 ; 0xf7f42 scsi.c:490
+ mov BL, strict byte 0a0h ; b3 a0 ; 0xf7f44 scsi.c:492
+ jmp short 07f4ah ; eb 02 ; 0xf7f46 scsi.c:493
+ mov BL, strict byte 0a8h ; b3 a8 ; 0xf7f48 scsi.c:495
+ mov cl, bl ; 88 d9 ; 0xf7f4a scsi.c:499
+ add cl, 007h ; 80 c1 07 ; 0xf7f4c
+ xor ch, ch ; 30 ed ; 0xf7f4f
+ mov ax, cx ; 89 c8 ; 0xf7f51
+ call 01652h ; e8 fc 96 ; 0xf7f53
+ test al, al ; 84 c0 ; 0xf7f56
+ je short 07f8fh ; 74 35 ; 0xf7f58
+ mov al, bl ; 88 d8 ; 0xf7f5a scsi.c:504
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf7f5c
+ xor ah, ah ; 30 e4 ; 0xf7f5e
+ call 01652h ; e8 ef 96 ; 0xf7f60
+ mov dh, al ; 88 c6 ; 0xf7f63
+ mov al, bl ; 88 d8 ; 0xf7f65
+ xor ah, ah ; 30 e4 ; 0xf7f67
+ call 01652h ; e8 e6 96 ; 0xf7f69
+ mov ah, dh ; 88 f4 ; 0xf7f6c
+ cwd ; 99 ; 0xf7f6e
+ mov si, ax ; 89 c6 ; 0xf7f6f
+ mov word [bp-020h], dx ; 89 56 e0 ; 0xf7f71
+ mov al, bl ; 88 d8 ; 0xf7f74 scsi.c:505
+ add AL, strict byte 002h ; 04 02 ; 0xf7f76
+ xor ah, ah ; 30 e4 ; 0xf7f78
+ call 01652h ; e8 d5 96 ; 0xf7f7a
+ xor ah, ah ; 30 e4 ; 0xf7f7d
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf7f7f
+ mov ax, cx ; 89 c8 ; 0xf7f82 scsi.c:506
+ call 01652h ; e8 cb 96 ; 0xf7f84
+ xor ah, ah ; 30 e4 ; 0xf7f87
+ mov word [bp-01eh], ax ; 89 46 e2 ; 0xf7f89
+ jmp near 0807ch ; e9 ed 00 ; 0xf7f8c scsi.c:508
+ mov ax, word [bp-02ah] ; 8b 46 d6 ; 0xf7f8f scsi.c:509
+ mov bx, word [bp-018h] ; 8b 5e e8 ; 0xf7f92
+ mov cx, word [bp-02eh] ; 8b 4e d2 ; 0xf7f95
+ mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xf7f98
+ mov si, strict word 0000ch ; be 0c 00 ; 0xf7f9b
+ call 09c10h ; e8 6f 1c ; 0xf7f9e
+ mov word [bp-022h], ax ; 89 46 de ; 0xf7fa1
+ mov word [bp-024h], bx ; 89 5e dc ; 0xf7fa4
+ mov word [bp-026h], cx ; 89 4e da ; 0xf7fa7
+ mov word [bp-028h], dx ; 89 56 d8 ; 0xf7faa
+ mov ax, word [bp-02ah] ; 8b 46 d6 ; 0xf7fad scsi.c:513
+ test ax, ax ; 85 c0 ; 0xf7fb0
+ jnbe short 07fc9h ; 77 15 ; 0xf7fb2
+ je short 07fb9h ; 74 03 ; 0xf7fb4
+ jmp near 0803ch ; e9 83 00 ; 0xf7fb6
+ cmp word [bp-018h], strict byte 00000h ; 83 7e e8 00 ; 0xf7fb9
+ jnbe short 07fc9h ; 77 0a ; 0xf7fbd
+ jne short 07fb6h ; 75 f5 ; 0xf7fbf
+ cmp word [bp-02eh], strict byte 00040h ; 83 7e d2 40 ; 0xf7fc1
+ jnbe short 07fc9h ; 77 02 ; 0xf7fc5
+ jne short 0803ch ; 75 73 ; 0xf7fc7
+ mov word [bp-01ch], 000ffh ; c7 46 e4 ff 00 ; 0xf7fc9 scsi.c:515
+ mov word [bp-01eh], strict word 0003fh ; c7 46 e2 3f 00 ; 0xf7fce scsi.c:516
+ mov bx, word [bp-018h] ; 8b 5e e8 ; 0xf7fd3 scsi.c:518
+ mov cx, word [bp-02eh] ; 8b 4e d2 ; 0xf7fd6
+ mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xf7fd9
+ mov si, strict word 00006h ; be 06 00 ; 0xf7fdc
+ call 09c10h ; e8 2e 1c ; 0xf7fdf
+ mov si, word [bp-028h] ; 8b 76 d8 ; 0xf7fe2
+ add si, dx ; 01 d6 ; 0xf7fe5
+ mov word [bp-038h], si ; 89 76 c8 ; 0xf7fe7
+ mov dx, word [bp-026h] ; 8b 56 da ; 0xf7fea
+ adc dx, cx ; 11 ca ; 0xf7fed
+ mov word [bp-036h], dx ; 89 56 ca ; 0xf7fef
+ mov dx, word [bp-024h] ; 8b 56 dc ; 0xf7ff2
+ adc dx, bx ; 11 da ; 0xf7ff5
+ mov word [bp-014h], dx ; 89 56 ec ; 0xf7ff7
+ mov dx, word [bp-022h] ; 8b 56 de ; 0xf7ffa
+ adc dx, ax ; 11 c2 ; 0xf7ffd
+ mov word [bp-02ch], dx ; 89 56 d4 ; 0xf7fff
+ mov ax, dx ; 89 d0 ; 0xf8002 scsi.c:519
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf8004
+ mov cx, word [bp-036h] ; 8b 4e ca ; 0xf8007
+ mov dx, si ; 89 f2 ; 0xf800a
+ mov si, strict word 00008h ; be 08 00 ; 0xf800c
+ call 09c10h ; e8 fe 1b ; 0xf800f
+ mov word [bp-030h], bx ; 89 5e d0 ; 0xf8012
+ mov word [bp-032h], cx ; 89 4e ce ; 0xf8015
+ mov word [bp-034h], dx ; 89 56 cc ; 0xf8018
+ mov ax, word [bp-02ch] ; 8b 46 d4 ; 0xf801b
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf801e
+ mov cx, word [bp-036h] ; 8b 4e ca ; 0xf8021
+ mov dx, word [bp-038h] ; 8b 56 c8 ; 0xf8024
+ mov si, strict word 00010h ; be 10 00 ; 0xf8027
+ call 09c10h ; e8 e3 1b ; 0xf802a
+ mov si, word [bp-034h] ; 8b 76 cc ; 0xf802d
+ add si, dx ; 01 d6 ; 0xf8030
+ adc cx, word [bp-032h] ; 13 4e ce ; 0xf8032
+ mov ax, word [bp-030h] ; 8b 46 d0 ; 0xf8035
+ adc ax, bx ; 11 d8 ; 0xf8038
+ jmp short 08079h ; eb 3d ; 0xf803a scsi.c:521
+ test ax, ax ; 85 c0 ; 0xf803c
+ jnbe short 08052h ; 77 12 ; 0xf803e
+ jne short 0805eh ; 75 1c ; 0xf8040
+ cmp word [bp-018h], strict byte 00000h ; 83 7e e8 00 ; 0xf8042
+ jnbe short 08052h ; 77 0a ; 0xf8046
+ jne short 0805eh ; 75 14 ; 0xf8048
+ cmp word [bp-02eh], strict byte 00020h ; 83 7e d2 20 ; 0xf804a
+ jnbe short 08052h ; 77 02 ; 0xf804e
+ jne short 0805eh ; 75 0c ; 0xf8050
+ mov word [bp-01ch], 00080h ; c7 46 e4 80 00 ; 0xf8052 scsi.c:523
+ mov word [bp-01eh], strict word 00020h ; c7 46 e2 20 00 ; 0xf8057 scsi.c:524
+ jmp short 08077h ; eb 19 ; 0xf805c scsi.c:527
+ mov word [bp-01ch], strict word 00040h ; c7 46 e4 40 00 ; 0xf805e scsi.c:529
+ mov word [bp-01eh], strict word 00020h ; c7 46 e2 20 00 ; 0xf8063 scsi.c:530
+ mov bx, word [bp-018h] ; 8b 5e e8 ; 0xf8068 scsi.c:531
+ mov cx, word [bp-02eh] ; 8b 4e d2 ; 0xf806b
+ mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xf806e
+ mov si, strict word 0000bh ; be 0b 00 ; 0xf8071
+ call 09c10h ; e8 99 1b ; 0xf8074
+ mov si, dx ; 89 d6 ; 0xf8077
+ mov word [bp-020h], cx ; 89 4e e0 ; 0xf8079
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf807c scsi.c:536
+ add AL, strict byte 008h ; 04 08 ; 0xf807f
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf8081
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf8084 scsi.c:538
+ xor ah, ah ; 30 e4 ; 0xf8087
+ sal ax, 1 ; d1 e0 ; 0xf8089
+ sal ax, 1 ; d1 e0 ; 0xf808b
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf808d
+ mov bx, di ; 89 fb ; 0xf8090
+ add bx, ax ; 01 c3 ; 0xf8092
+ mov ax, word [bp-0024ah] ; 8b 86 b6 fd ; 0xf8094
+ mov word [es:bx+0021ch], ax ; 26 89 87 1c 02 ; 0xf8098
+ mov al, byte [bp-016h] ; 8a 46 ea ; 0xf809d scsi.c:539
+ mov byte [es:bx+0021eh], al ; 26 88 87 1e 02 ; 0xf80a0
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf80a5 scsi.c:540
+ xor ah, ah ; 30 e4 ; 0xf80a8
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf80aa
+ imul dx ; f7 ea ; 0xf80ad
+ mov bx, di ; 89 fb ; 0xf80af
+ add bx, ax ; 01 c3 ; 0xf80b1
+ mov word [es:bx+022h], 0ff04h ; 26 c7 47 22 04 ff ; 0xf80b3
+ mov word [es:bx+024h], strict word 00000h ; 26 c7 47 24 00 00 ; 0xf80b9 scsi.c:542
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf80bf scsi.c:544
+ mov word [es:bx+028h], ax ; 26 89 47 28 ; 0xf80c2
+ mov byte [es:bx+027h], 001h ; 26 c6 47 27 01 ; 0xf80c6 scsi.c:545
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf80cb scsi.c:548
+ mov word [es:bx+02ah], ax ; 26 89 47 2a ; 0xf80ce
+ mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xf80d2 scsi.c:549
+ mov word [es:bx+02eh], ax ; 26 89 47 2e ; 0xf80d5
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf80d9 scsi.c:550
+ mov word [es:bx+030h], ax ; 26 89 47 30 ; 0xf80dc
+ mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xf80e0 scsi.c:551
+ mov word [es:bx+034h], ax ; 26 89 47 34 ; 0xf80e3
+ cmp word [bp-020h], strict byte 00000h ; 83 7e e0 00 ; 0xf80e7 scsi.c:553
+ jne short 080f3h ; 75 06 ; 0xf80eb
+ cmp si, 00400h ; 81 fe 00 04 ; 0xf80ed
+ jbe short 08101h ; 76 0e ; 0xf80f1
+ mov word [es:bx+02ch], 00400h ; 26 c7 47 2c 00 04 ; 0xf80f3 scsi.c:554
+ mov word [es:bx+032h], 00400h ; 26 c7 47 32 00 04 ; 0xf80f9 scsi.c:555
+ jmp short 08109h ; eb 08 ; 0xf80ff scsi.c:556
+ mov word [es:bx+02ch], si ; 26 89 77 2c ; 0xf8101 scsi.c:557
+ mov word [es:bx+032h], si ; 26 89 77 32 ; 0xf8105 scsi.c:558
+ mov bx, 00da0h ; bb a0 0d ; 0xf8109 scsi.c:562
+ mov cx, ds ; 8c d9 ; 0xf810c
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf810e
+ call 018cch ; e8 b8 97 ; 0xf8111
+ push word [bp-02ah] ; ff 76 d6 ; 0xf8114
+ push word [bp-018h] ; ff 76 e8 ; 0xf8117
+ push word [bp-02eh] ; ff 76 d2 ; 0xf811a
+ push word [bp-01ah] ; ff 76 e6 ; 0xf811d
+ push word [bp-01eh] ; ff 76 e2 ; 0xf8120
+ push word [bp-01ch] ; ff 76 e4 ; 0xf8123
+ push word [bp-020h] ; ff 76 e0 ; 0xf8126
+ push si ; 56 ; 0xf8129
+ push word [bp-016h] ; ff 76 ea ; 0xf812a
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf812d
+ xor ah, ah ; 30 e4 ; 0xf8130
+ push ax ; 50 ; 0xf8132
+ mov ax, 00c18h ; b8 18 0c ; 0xf8133
+ push ax ; 50 ; 0xf8136
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf8137
+ push ax ; 50 ; 0xf813a
+ call 0190fh ; e8 d1 97 ; 0xf813b
+ add sp, strict byte 00018h ; 83 c4 18 ; 0xf813e
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf8141 scsi.c:564
+ xor ah, ah ; 30 e4 ; 0xf8144
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf8146
+ imul dx ; f7 ea ; 0xf8149
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf814b
+ mov bx, di ; 89 fb ; 0xf814e
+ add bx, ax ; 01 c3 ; 0xf8150
+ mov ax, word [bp-02ah] ; 8b 46 d6 ; 0xf8152
+ mov word [es:bx+03ch], ax ; 26 89 47 3c ; 0xf8155
+ mov ax, word [bp-018h] ; 8b 46 e8 ; 0xf8159
+ mov word [es:bx+03ah], ax ; 26 89 47 3a ; 0xf815c
+ mov ax, word [bp-02eh] ; 8b 46 d2 ; 0xf8160
+ mov word [es:bx+038h], ax ; 26 89 47 38 ; 0xf8163
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf8167
+ mov word [es:bx+036h], ax ; 26 89 47 36 ; 0xf816a
+ mov al, byte [es:di+001e2h] ; 26 8a 85 e2 01 ; 0xf816e scsi.c:567
+ mov ah, byte [bp-00ch] ; 8a 66 f4 ; 0xf8173 scsi.c:568
+ add ah, 008h ; 80 c4 08 ; 0xf8176
+ mov bl, al ; 88 c3 ; 0xf8179
+ xor bh, bh ; 30 ff ; 0xf817b
+ add bx, di ; 01 fb ; 0xf817d
+ mov byte [es:bx+001e3h], ah ; 26 88 a7 e3 01 ; 0xf817f
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf8184 scsi.c:569
+ mov byte [es:di+001e2h], al ; 26 88 85 e2 01 ; 0xf8186 scsi.c:570
+ mov bx, strict word 00075h ; bb 75 00 ; 0xf818b scsi.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf818e
+ mov es, ax ; 8e c0 ; 0xf8191
+ mov al, byte [es:bx] ; 26 8a 07 ; 0xf8193
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf8196 scsi.c:574
+ mov byte [es:bx], al ; 26 88 07 ; 0xf8198 scsi.c:43
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf819b scsi.c:577
+ jmp near 0823dh ; e9 9c 00 ; 0xf819e scsi.c:579
+ mov bx, 00da0h ; bb a0 0d ; 0xf81a1 scsi.c:591
+ mov cx, ds ; 8c d9 ; 0xf81a4
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf81a6
+ call 018cch ; e8 20 97 ; 0xf81a9
+ push word [bp-016h] ; ff 76 ea ; 0xf81ac
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf81af
+ xor ah, ah ; 30 e4 ; 0xf81b2
+ push ax ; 50 ; 0xf81b4
+ mov ax, 00c46h ; b8 46 0c ; 0xf81b5
+ push ax ; 50 ; 0xf81b8
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf81b9
+ push ax ; 50 ; 0xf81bc
+ call 0190fh ; e8 4f 97 ; 0xf81bd
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf81c0
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf81c3 scsi.c:594
+ add AL, strict byte 008h ; 04 08 ; 0xf81c6
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf81c8
+ test byte [bp-00247h], 080h ; f6 86 b9 fd 80 ; 0xf81cb scsi.c:596
+ je short 081d7h ; 74 05 ; 0xf81d0
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf81d2
+ jmp short 081d9h ; eb 02 ; 0xf81d5
+ xor cx, cx ; 31 c9 ; 0xf81d7
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf81d9 scsi.c:598
+ xor ah, ah ; 30 e4 ; 0xf81dc
+ sal ax, 1 ; d1 e0 ; 0xf81de
+ sal ax, 1 ; d1 e0 ; 0xf81e0
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf81e2
+ mov bx, di ; 89 fb ; 0xf81e5
+ add bx, ax ; 01 c3 ; 0xf81e7
+ mov ax, word [bp-0024ah] ; 8b 86 b6 fd ; 0xf81e9
+ mov word [es:bx+0021ch], ax ; 26 89 87 1c 02 ; 0xf81ed
+ mov al, byte [bp-016h] ; 8a 46 ea ; 0xf81f2 scsi.c:599
+ mov byte [es:bx+0021eh], al ; 26 88 87 1e 02 ; 0xf81f5
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf81fa scsi.c:600
+ xor ah, ah ; 30 e4 ; 0xf81fd
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf81ff
+ imul dx ; f7 ea ; 0xf8202
+ mov bx, di ; 89 fb ; 0xf8204
+ add bx, ax ; 01 c3 ; 0xf8206
+ mov word [es:bx+022h], 00504h ; 26 c7 47 22 04 05 ; 0xf8208
+ mov byte [es:bx+024h], cl ; 26 88 4f 24 ; 0xf820e scsi.c:602
+ mov word [es:bx+028h], 00800h ; 26 c7 47 28 00 08 ; 0xf8212 scsi.c:603
+ mov byte [es:bx+027h], 000h ; 26 c6 47 27 00 ; 0xf8218 scsi.c:604
+ mov al, byte [es:di+001f3h] ; 26 8a 85 f3 01 ; 0xf821d scsi.c:607
+ mov ah, byte [bp-00ch] ; 8a 66 f4 ; 0xf8222 scsi.c:608
+ add ah, 008h ; 80 c4 08 ; 0xf8225
+ mov bl, al ; 88 c3 ; 0xf8228
+ xor bh, bh ; 30 ff ; 0xf822a
+ add bx, di ; 01 fb ; 0xf822c
+ mov byte [es:bx+001f4h], ah ; 26 88 a7 f4 01 ; 0xf822e
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf8233 scsi.c:609
+ mov byte [es:di+001f3h], al ; 26 88 85 f3 01 ; 0xf8235 scsi.c:610
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf823a scsi.c:612
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf823d scsi.c:617
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf8240
+ mov byte [es:di+0022ch], al ; 26 88 85 2c 02 ; 0xf8243
+ inc word [bp-016h] ; ff 46 ea ; 0xf8248 scsi.c:618
+ cmp word [bp-016h], strict byte 00010h ; 83 7e ea 10 ; 0xf824b
+ jl short 08254h ; 7c 03 ; 0xf824f
+ jmp near 082d7h ; e9 83 00 ; 0xf8251
+ mov byte [bp-048h], 012h ; c6 46 b8 12 ; 0xf8254
+ xor al, al ; 30 c0 ; 0xf8258
+ mov byte [bp-047h], al ; 88 46 b9 ; 0xf825a
+ mov byte [bp-046h], al ; 88 46 ba ; 0xf825d
+ mov byte [bp-045h], al ; 88 46 bb ; 0xf8260
+ mov byte [bp-044h], 005h ; c6 46 bc 05 ; 0xf8263
+ mov byte [bp-043h], al ; 88 46 bd ; 0xf8267
+ xor ah, ah ; 30 e4 ; 0xf826a
+ push ax ; 50 ; 0xf826c
+ mov ax, strict word 00005h ; b8 05 00 ; 0xf826d
+ push ax ; 50 ; 0xf8270
+ lea dx, [bp-00248h] ; 8d 96 b8 fd ; 0xf8271
+ push SS ; 16 ; 0xf8275
+ push dx ; 52 ; 0xf8276
+ mov ax, strict word 00006h ; b8 06 00 ; 0xf8277
+ push ax ; 50 ; 0xf827a
+ mov dl, byte [bp-016h] ; 8a 56 ea ; 0xf827b
+ xor dh, dh ; 30 f6 ; 0xf827e
+ mov cx, ss ; 8c d1 ; 0xf8280
+ lea bx, [bp-048h] ; 8d 5e b8 ; 0xf8282
+ mov ax, word [bp-0024ah] ; 8b 86 b6 fd ; 0xf8285
+ call 07925h ; e8 99 f6 ; 0xf8289
+ test al, al ; 84 c0 ; 0xf828c
+ je short 082a2h ; 74 12 ; 0xf828e
+ mov ax, 00b92h ; b8 92 0b ; 0xf8290
+ push ax ; 50 ; 0xf8293
+ mov ax, 00bb2h ; b8 b2 0b ; 0xf8294
+ push ax ; 50 ; 0xf8297
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf8298
+ push ax ; 50 ; 0xf829b
+ call 0190fh ; e8 70 96 ; 0xf829c
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf829f
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf82a2
+ mov al, byte [es:di+0022ch] ; 26 8a 85 2c 02 ; 0xf82a5
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf82aa
+ test byte [bp-00248h], 0e0h ; f6 86 b8 fd e0 ; 0xf82ad
+ jne short 082beh ; 75 0a ; 0xf82b2
+ test byte [bp-00248h], 01fh ; f6 86 b8 fd 1f ; 0xf82b4
+ jne short 082beh ; 75 03 ; 0xf82b9
+ jmp near 07e3bh ; e9 7d fb ; 0xf82bb
+ test byte [bp-00248h], 0e0h ; f6 86 b8 fd e0 ; 0xf82be
+ je short 082c8h ; 74 03 ; 0xf82c3
+ jmp near 0823dh ; e9 75 ff ; 0xf82c5
+ mov al, byte [bp-00248h] ; 8a 86 b8 fd ; 0xf82c8
+ and AL, strict byte 01fh ; 24 1f ; 0xf82cc
+ cmp AL, strict byte 005h ; 3c 05 ; 0xf82ce
+ jne short 082d5h ; 75 03 ; 0xf82d0
+ jmp near 081a1h ; e9 cc fe ; 0xf82d2
+ jmp short 082c5h ; eb ee ; 0xf82d5
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf82d7 scsi.c:619
+ pop di ; 5f ; 0xf82da
+ pop si ; 5e ; 0xf82db
+ pop dx ; 5a ; 0xf82dc
+ pop cx ; 59 ; 0xf82dd
+ pop bx ; 5b ; 0xf82de
+ pop bp ; 5d ; 0xf82df
+ retn ; c3 ; 0xf82e0
+ ; disGetNextSymbol 0xf82e1 LB 0x1c67 -> off=0x0 cb=000000000000002b uValue=00000000000f6ce1 'scsi_pci_init'
+scsi_pci_init: ; 0xf82e1 LB 0x2b
+ push bp ; 55 ; 0xf82e1 scsi.c:621
+ mov bp, sp ; 89 e5 ; 0xf82e2
+ push bx ; 53 ; 0xf82e4
+ push cx ; 51 ; 0xf82e5
+ push si ; 56 ; 0xf82e6
+ call 09a10h ; e8 26 17 ; 0xf82e7 scsi.c:625
+ mov dx, ax ; 89 c2 ; 0xf82ea
+ cmp ax, strict word 0ffffh ; 3d ff ff ; 0xf82ec scsi.c:626
+ je short 08304h ; 74 13 ; 0xf82ef
+ mov al, dl ; 88 d0 ; 0xf82f1 scsi.c:633
+ xor ah, ah ; 30 e4 ; 0xf82f3
+ mov si, ax ; 89 c6 ; 0xf82f5
+ mov al, dh ; 88 f0 ; 0xf82f7
+ mov cx, strict word 00007h ; b9 07 00 ; 0xf82f9
+ mov bx, strict word 00004h ; bb 04 00 ; 0xf82fc
+ mov dx, si ; 89 f2 ; 0xf82ff
+ call 09abeh ; e8 ba 17 ; 0xf8301
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf8304 scsi.c:634
+ pop si ; 5e ; 0xf8307
+ pop cx ; 59 ; 0xf8308
+ pop bx ; 5b ; 0xf8309
+ pop bp ; 5d ; 0xf830a
+ retn ; c3 ; 0xf830b
+ ; disGetNextSymbol 0xf830c LB 0x1c3c -> off=0x0 cb=0000000000000081 uValue=00000000000f6d0c 'scsi_init'
+scsi_init: ; 0xf830c LB 0x81
+ push bp ; 55 ; 0xf830c scsi.c:639
+ mov bp, sp ; 89 e5 ; 0xf830d
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf830f scsi.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf8312
+ mov es, ax ; 8e c0 ; 0xf8315
+ mov es, [es:bx] ; 26 8e 07 ; 0xf8317
+ mov bx, 00122h ; bb 22 01 ; 0xf831a scsi.c:49
+ mov byte [es:bx+0022ch], 000h ; 26 c6 87 2c 02 00 ; 0xf831d scsi.c:646
+ mov AL, strict byte 055h ; b0 55 ; 0xf8323 scsi.c:651
+ mov dx, 00432h ; ba 32 04 ; 0xf8325
+ out DX, AL ; ee ; 0xf8328
+ in AL, DX ; ec ; 0xf8329 scsi.c:652
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf832a
+ cmp AL, strict byte 055h ; 3c 55 ; 0xf832c scsi.c:654
+ jne short 08345h ; 75 15 ; 0xf832e
+ xor al, al ; 30 c0 ; 0xf8330 scsi.c:658
+ mov dx, 00433h ; ba 33 04 ; 0xf8332
+ out DX, AL ; ee ; 0xf8335
+ mov ax, 00430h ; b8 30 04 ; 0xf8336 scsi.c:659
+ call 07e15h ; e8 d9 fa ; 0xf8339
+ mov dx, 01040h ; ba 40 10 ; 0xf833c scsi.c:660
+ mov ax, 0104bh ; b8 4b 10 ; 0xf833f
+ call 082e1h ; e8 9c ff ; 0xf8342
+ mov AL, strict byte 055h ; b0 55 ; 0xf8345 scsi.c:668
+ mov dx, 00436h ; ba 36 04 ; 0xf8347
+ out DX, AL ; ee ; 0xf834a
+ in AL, DX ; ec ; 0xf834b scsi.c:669
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf834c
+ cmp AL, strict byte 055h ; 3c 55 ; 0xf834e scsi.c:671
+ jne short 08367h ; 75 15 ; 0xf8350
+ xor al, al ; 30 c0 ; 0xf8352 scsi.c:675
+ mov dx, 00437h ; ba 37 04 ; 0xf8354
+ out DX, AL ; ee ; 0xf8357
+ mov ax, 00434h ; b8 34 04 ; 0xf8358 scsi.c:676
+ call 07e15h ; e8 b7 fa ; 0xf835b
+ mov dx, strict word 00030h ; ba 30 00 ; 0xf835e scsi.c:677
+ mov ax, 01000h ; b8 00 10 ; 0xf8361
+ call 082e1h ; e8 7a ff ; 0xf8364
+ mov AL, strict byte 055h ; b0 55 ; 0xf8367 scsi.c:685
+ mov dx, 0043ah ; ba 3a 04 ; 0xf8369
+ out DX, AL ; ee ; 0xf836c
+ in AL, DX ; ec ; 0xf836d scsi.c:686
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf836e
+ cmp AL, strict byte 055h ; 3c 55 ; 0xf8370 scsi.c:688
+ jne short 08389h ; 75 15 ; 0xf8372
+ xor al, al ; 30 c0 ; 0xf8374 scsi.c:692
+ mov dx, 0043bh ; ba 3b 04 ; 0xf8376
+ out DX, AL ; ee ; 0xf8379
+ mov ax, 00438h ; b8 38 04 ; 0xf837a scsi.c:693
+ call 07e15h ; e8 95 fa ; 0xf837d
+ mov dx, strict word 00054h ; ba 54 00 ; 0xf8380 scsi.c:694
+ mov ax, 01000h ; b8 00 10 ; 0xf8383
+ call 082e1h ; e8 58 ff ; 0xf8386
+ mov sp, bp ; 89 ec ; 0xf8389 scsi.c:700
+ pop bp ; 5d ; 0xf838b
+ retn ; c3 ; 0xf838c
+ ; disGetNextSymbol 0xf838d LB 0x1bbb -> off=0x0 cb=000000000000001c uValue=00000000000f6d8d 'ahci_ctrl_extract_bits'
+ahci_ctrl_extract_bits: ; 0xf838d LB 0x1c
+ push si ; 56 ; 0xf838d ahci.c:279
+ push bp ; 55 ; 0xf838e
+ mov bp, sp ; 89 e5 ; 0xf838f
+ mov si, ax ; 89 c6 ; 0xf8391
+ and ax, bx ; 21 d8 ; 0xf8393 ahci.c:281
+ and dx, cx ; 21 ca ; 0xf8395
+ mov cl, byte [bp+006h] ; 8a 4e 06 ; 0xf8397
+ xor ch, ch ; 30 ed ; 0xf839a
+ jcxz 083a4h ; e3 06 ; 0xf839c
+ shr dx, 1 ; d1 ea ; 0xf839e
+ rcr ax, 1 ; d1 d8 ; 0xf83a0
+ loop 0839eh ; e2 fa ; 0xf83a2
+ pop bp ; 5d ; 0xf83a4 ahci.c:282
+ pop si ; 5e ; 0xf83a5
+ retn 00002h ; c2 02 00 ; 0xf83a6
+ ; disGetNextSymbol 0xf83a9 LB 0x1b9f -> off=0x0 cb=000000000000001e uValue=00000000000f6da9 'ahci_addr_to_phys'
+ahci_addr_to_phys: ; 0xf83a9 LB 0x1e
+ push bx ; 53 ; 0xf83a9 ahci.c:287
+ push cx ; 51 ; 0xf83aa
+ push bp ; 55 ; 0xf83ab
+ mov bp, sp ; 89 e5 ; 0xf83ac
+ mov bx, ax ; 89 c3 ; 0xf83ae
+ mov ax, dx ; 89 d0 ; 0xf83b0
+ xor dx, dx ; 31 d2 ; 0xf83b2 ahci.c:289
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf83b4
+ sal ax, 1 ; d1 e0 ; 0xf83b7
+ rcl dx, 1 ; d1 d2 ; 0xf83b9
+ loop 083b7h ; e2 fa ; 0xf83bb
+ xor cx, cx ; 31 c9 ; 0xf83bd
+ add ax, bx ; 01 d8 ; 0xf83bf
+ adc dx, cx ; 11 ca ; 0xf83c1
+ pop bp ; 5d ; 0xf83c3 ahci.c:290
+ pop cx ; 59 ; 0xf83c4
+ pop bx ; 5b ; 0xf83c5
+ retn ; c3 ; 0xf83c6
+ ; disGetNextSymbol 0xf83c7 LB 0x1b81 -> off=0x0 cb=0000000000000159 uValue=00000000000f6dc7 'ahci_port_cmd_sync'
+ahci_port_cmd_sync: ; 0xf83c7 LB 0x159
+ push bp ; 55 ; 0xf83c7 ahci.c:295
+ mov bp, sp ; 89 e5 ; 0xf83c8
+ push cx ; 51 ; 0xf83ca
+ push si ; 56 ; 0xf83cb
+ push di ; 57 ; 0xf83cc
+ push ax ; 50 ; 0xf83cd
+ mov si, ax ; 89 c6 ; 0xf83ce
+ mov cx, dx ; 89 d1 ; 0xf83d0
+ mov dl, bl ; 88 da ; 0xf83d2
+ mov es, cx ; 8e c1 ; 0xf83d4 ahci.c:300
+ mov al, byte [es:si+00262h] ; 26 8a 84 62 02 ; 0xf83d6
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf83db
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf83de ahci.c:301
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xf83e3 ahci.c:303
+ jne short 083eah ; 75 03 ; 0xf83e5
+ jmp near 08518h ; e9 2e 01 ; 0xf83e7
+ mov al, byte [es:si+00263h] ; 26 8a 84 63 02 ; 0xf83ea ahci.c:306
+ xor ah, ah ; 30 e4 ; 0xf83ef
+ xor di, di ; 31 ff ; 0xf83f1
+ or di, 00080h ; 81 cf 80 00 ; 0xf83f3
+ xor dh, dh ; 30 f6 ; 0xf83f7
+ or di, dx ; 09 d7 ; 0xf83f9
+ mov word [es:si], di ; 26 89 3c ; 0xf83fb
+ mov word [es:si+002h], ax ; 26 89 44 02 ; 0xf83fe
+ mov word [es:si+004h], strict word 00000h ; 26 c7 44 04 00 00 ; 0xf8402 ahci.c:307
+ mov word [es:si+006h], strict word 00000h ; 26 c7 44 06 00 00 ; 0xf8408
+ lea ax, [si+00080h] ; 8d 84 80 00 ; 0xf840e ahci.c:308
+ mov dx, cx ; 89 ca ; 0xf8412
+ call 083a9h ; e8 92 ff ; 0xf8414
+ mov es, cx ; 8e c1 ; 0xf8417
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf8419
+ mov word [es:si+00ah], dx ; 26 89 54 0a ; 0xf841d
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8421 ahci.c:311
+ xor ah, ah ; 30 e4 ; 0xf8424
+ mov CL, strict byte 007h ; b1 07 ; 0xf8426
+ mov di, ax ; 89 c7 ; 0xf8428
+ sal di, CL ; d3 e7 ; 0xf842a
+ lea ax, [di+00118h] ; 8d 85 18 01 ; 0xf842c
+ xor cx, cx ; 31 c9 ; 0xf8430 ahci.c:252
+ mov dx, bx ; 89 da ; 0xf8432
+ xchg cx, ax ; 91 ; 0xf8434
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8435
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8439
+ out DX, eax ; 66 ef ; 0xf843b
+ lea si, [bx+004h] ; 8d 77 04 ; 0xf843d ahci.c:253
+ mov dx, si ; 89 f2 ; 0xf8440
+ in eax, DX ; 66 ed ; 0xf8442
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8444
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8446
+ xchg dx, ax ; 92 ; 0xf844a
+ or AL, strict byte 011h ; 0c 11 ; 0xf844b
+ mov cx, dx ; 89 d1 ; 0xf844d
+ mov dx, si ; 89 f2 ; 0xf844f
+ xchg cx, ax ; 91 ; 0xf8451
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8452
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8456
+ out DX, eax ; 66 ef ; 0xf8458
+ lea ax, [di+00138h] ; 8d 85 38 01 ; 0xf845a ahci.c:315
+ cwd ; 99 ; 0xf845e
+ mov cx, dx ; 89 d1 ; 0xf845f
+ mov dx, bx ; 89 da ; 0xf8461
+ xchg cx, ax ; 91 ; 0xf8463
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8464
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8468
+ out DX, eax ; 66 ef ; 0xf846a
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf846c
+ xor cx, cx ; 31 c9 ; 0xf846f
+ mov dx, si ; 89 f2 ; 0xf8471
+ xchg cx, ax ; 91 ; 0xf8473
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8474
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8478
+ out DX, eax ; 66 ef ; 0xf847a
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf847c ahci.c:319
+ xor ah, ah ; 30 e4 ; 0xf847f
+ mov CL, strict byte 007h ; b1 07 ; 0xf8481
+ sal ax, CL ; d3 e0 ; 0xf8483
+ add ax, 00110h ; 05 10 01 ; 0xf8485
+ xor cx, cx ; 31 c9 ; 0xf8488 ahci.c:271
+ mov dx, bx ; 89 da ; 0xf848a
+ xchg cx, ax ; 91 ; 0xf848c
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf848d
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8491
+ out DX, eax ; 66 ef ; 0xf8493
+ lea dx, [bx+004h] ; 8d 57 04 ; 0xf8495 ahci.c:272
+ in eax, DX ; 66 ed ; 0xf8498
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf849a
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf849c
+ xchg dx, ax ; 92 ; 0xf84a0
+ test dh, 040h ; f6 c6 40 ; 0xf84a1
+ jne short 084aah ; 75 04 ; 0xf84a4
+ test AL, strict byte 001h ; a8 01 ; 0xf84a6
+ je short 084aeh ; 74 04 ; 0xf84a8
+ mov AL, strict byte 001h ; b0 01 ; 0xf84aa
+ jmp short 084b0h ; eb 02 ; 0xf84ac
+ xor al, al ; 30 c0 ; 0xf84ae
+ test al, al ; 84 c0 ; 0xf84b0 ahci.c:273
+ je short 0847ch ; 74 c8 ; 0xf84b2
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf84b4 ahci.c:325
+ xor ah, ah ; 30 e4 ; 0xf84b7
+ mov CL, strict byte 007h ; b1 07 ; 0xf84b9
+ mov di, ax ; 89 c7 ; 0xf84bb
+ sal di, CL ; d3 e7 ; 0xf84bd
+ lea ax, [di+00110h] ; 8d 85 10 01 ; 0xf84bf
+ xor cx, cx ; 31 c9 ; 0xf84c3 ahci.c:252
+ mov dx, bx ; 89 da ; 0xf84c5
+ xchg cx, ax ; 91 ; 0xf84c7
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf84c8
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf84cc
+ out DX, eax ; 66 ef ; 0xf84ce
+ lea si, [bx+004h] ; 8d 77 04 ; 0xf84d0 ahci.c:253
+ mov dx, si ; 89 f2 ; 0xf84d3
+ in eax, DX ; 66 ed ; 0xf84d5
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf84d7
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf84d9
+ xchg dx, ax ; 92 ; 0xf84dd
+ or AL, strict byte 001h ; 0c 01 ; 0xf84de
+ mov cx, dx ; 89 d1 ; 0xf84e0
+ mov dx, si ; 89 f2 ; 0xf84e2
+ xchg cx, ax ; 91 ; 0xf84e4
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf84e5
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf84e9
+ out DX, eax ; 66 ef ; 0xf84eb
+ lea ax, [di+00118h] ; 8d 85 18 01 ; 0xf84ed ahci.c:329
+ xor cx, cx ; 31 c9 ; 0xf84f1 ahci.c:261
+ mov dx, bx ; 89 da ; 0xf84f3
+ xchg cx, ax ; 91 ; 0xf84f5
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf84f6
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf84fa
+ out DX, eax ; 66 ef ; 0xf84fc
+ mov dx, si ; 89 f2 ; 0xf84fe ahci.c:262
+ in eax, DX ; 66 ed ; 0xf8500
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8502
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8504
+ xchg dx, ax ; 92 ; 0xf8508
+ and AL, strict byte 0feh ; 24 fe ; 0xf8509
+ mov cx, dx ; 89 d1 ; 0xf850b
+ mov dx, si ; 89 f2 ; 0xf850d
+ xchg cx, ax ; 91 ; 0xf850f
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8510
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8514
+ out DX, eax ; 66 ef ; 0xf8516
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf8518 ahci.c:335
+ pop di ; 5f ; 0xf851b
+ pop si ; 5e ; 0xf851c
+ pop cx ; 59 ; 0xf851d
+ pop bp ; 5d ; 0xf851e
+ retn ; c3 ; 0xf851f
+ ; disGetNextSymbol 0xf8520 LB 0x1a28 -> off=0x0 cb=0000000000000262 uValue=00000000000f6f20 'ahci_cmd_data'
+ahci_cmd_data: ; 0xf8520 LB 0x262
+ push bp ; 55 ; 0xf8520 ahci.c:340
+ mov bp, sp ; 89 e5 ; 0xf8521
+ push cx ; 51 ; 0xf8523
+ push si ; 56 ; 0xf8524
+ push di ; 57 ; 0xf8525
+ sub sp, strict byte 0000ch ; 83 ec 0c ; 0xf8526
+ push ax ; 50 ; 0xf8529
+ push dx ; 52 ; 0xf852a
+ mov byte [bp-008h], bl ; 88 5e f8 ; 0xf852b
+ xor di, di ; 31 ff ; 0xf852e ahci.c:342
+ mov es, dx ; 8e c2 ; 0xf8530
+ mov bx, ax ; 89 c3 ; 0xf8532
+ mov ax, word [es:bx+00232h] ; 26 8b 87 32 02 ; 0xf8534
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf8539
+ mov word [bp-00eh], di ; 89 7e f2 ; 0xf853c
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf853f
+ mov ax, word [es:bx+00eh] ; 26 8b 47 0e ; 0xf8542 ahci.c:343
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf8546
+ mov ax, word [es:bx+010h] ; 26 8b 47 10 ; 0xf8549 ahci.c:344
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf854d
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf8550 ahci.c:347
+ xor bx, bx ; 31 db ; 0xf8553
+ mov ax, 00080h ; b8 80 00 ; 0xf8555
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8558
+ call 09c30h ; e8 d2 16 ; 0xf855b
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf855e ahci.c:350
+ mov word [es:di+00080h], 08027h ; 26 c7 85 80 00 27 80 ; 0xf8561
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8568 ahci.c:352
+ mov byte [es:di+00082h], al ; 26 88 85 82 00 ; 0xf856b
+ mov byte [es:di+00083h], 000h ; 26 c6 85 83 00 00 ; 0xf8570 ahci.c:353
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8576 ahci.c:355
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf8579
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf857c
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf857f
+ mov byte [es:di+00084h], al ; 26 88 85 84 00 ; 0xf8582
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8587 ahci.c:356
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf858a
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf858e
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf8592
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf8595
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf8599
+ mov si, strict word 00008h ; be 08 00 ; 0xf859c
+ call 09c10h ; e8 6e 16 ; 0xf859f
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf85a2
+ mov byte [es:di+00085h], dl ; 26 88 95 85 00 ; 0xf85a5
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf85aa ahci.c:357
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf85ad
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf85b0
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf85b4
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf85b8
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf85bb
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf85bf
+ mov si, strict word 00010h ; be 10 00 ; 0xf85c2
+ call 09c10h ; e8 48 16 ; 0xf85c5
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf85c8
+ mov byte [es:di+00086h], dl ; 26 88 95 86 00 ; 0xf85cb
+ mov byte [es:di+00087h], 040h ; 26 c6 85 87 00 40 ; 0xf85d0 ahci.c:358
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf85d6 ahci.c:360
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf85d9
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf85dc
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf85e0
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf85e4
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf85e7
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf85eb
+ mov si, strict word 00018h ; be 18 00 ; 0xf85ee
+ call 09c10h ; e8 1c 16 ; 0xf85f1
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf85f4
+ mov byte [es:di+00088h], dl ; 26 88 95 88 00 ; 0xf85f7
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf85fc ahci.c:361
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf85ff
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf8602
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf8606
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf860a
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf860d
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf8611
+ mov si, strict word 00020h ; be 20 00 ; 0xf8614
+ call 09c10h ; e8 f6 15 ; 0xf8617
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf861a
+ mov byte [es:di+00089h], dl ; 26 88 95 89 00 ; 0xf861d
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8622 ahci.c:362
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf8625
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf8628
+ mov bx, word [es:bx+004h] ; 26 8b 5f 04 ; 0xf862c
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf8630
+ mov cx, word [es:si+002h] ; 26 8b 4c 02 ; 0xf8633
+ mov dx, word [es:si] ; 26 8b 14 ; 0xf8637
+ mov si, strict word 00028h ; be 28 00 ; 0xf863a
+ call 09c10h ; e8 d0 15 ; 0xf863d
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8640
+ mov byte [es:di+0008ah], dl ; 26 88 95 8a 00 ; 0xf8643
+ mov byte [es:di+0008bh], 000h ; 26 c6 85 8b 00 00 ; 0xf8648 ahci.c:363
+ mov al, byte [bp-010h] ; 8a 46 f0 ; 0xf864e ahci.c:365
+ mov byte [es:di+0008ch], al ; 26 88 85 8c 00 ; 0xf8651
+ mov al, byte [bp-00fh] ; 8a 46 f1 ; 0xf8656 ahci.c:366
+ mov byte [es:di+0008dh], al ; 26 88 85 8d 00 ; 0xf8659
+ mov word [es:di+00276h], strict word 00010h ; 26 c7 85 76 02 10 00 ; 0xf865e ahci.c:369
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf8665 ahci.c:372
+ xor dx, dx ; 31 d2 ; 0xf8668
+ mov bx, word [bp-012h] ; 8b 5e ee ; 0xf866a
+ xor cx, cx ; 31 c9 ; 0xf866d
+ call 09bc0h ; e8 4e 15 ; 0xf866f
+ push dx ; 52 ; 0xf8672
+ push ax ; 50 ; 0xf8673
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8674
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf8677
+ mov bx, word [es:bx+008h] ; 26 8b 5f 08 ; 0xf867a
+ mov si, word [bp-014h] ; 8b 76 ec ; 0xf867e
+ mov cx, word [es:si+00ah] ; 26 8b 4c 0a ; 0xf8681
+ mov ax, 0026ah ; b8 6a 02 ; 0xf8685
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8688
+ call 09b17h ; e8 89 14 ; 0xf868b
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf868e ahci.c:375
+ mov dx, word [es:di+0027eh] ; 26 8b 95 7e 02 ; 0xf8691
+ add dx, strict byte 0ffffh ; 83 c2 ff ; 0xf8696
+ mov ax, word [es:di+00280h] ; 26 8b 85 80 02 ; 0xf8699
+ adc ax, strict word 0ffffh ; 15 ff ff ; 0xf869e
+ mov bl, byte [es:di+00263h] ; 26 8a 9d 63 02 ; 0xf86a1
+ xor bh, bh ; 30 ff ; 0xf86a6
+ mov CL, strict byte 004h ; b1 04 ; 0xf86a8
+ sal bx, CL ; d3 e3 ; 0xf86aa
+ mov word [es:bx+0010ch], dx ; 26 89 97 0c 01 ; 0xf86ac
+ mov word [es:bx+0010eh], ax ; 26 89 87 0e 01 ; 0xf86b1
+ mov bl, byte [es:di+00263h] ; 26 8a 9d 63 02 ; 0xf86b6 ahci.c:376
+ xor bh, bh ; 30 ff ; 0xf86bb
+ sal bx, CL ; d3 e3 ; 0xf86bd
+ mov ax, word [es:di+0027ah] ; 26 8b 85 7a 02 ; 0xf86bf
+ mov dx, word [es:di+0027ch] ; 26 8b 95 7c 02 ; 0xf86c4
+ mov word [es:bx+00100h], ax ; 26 89 87 00 01 ; 0xf86c9
+ mov word [es:bx+00102h], dx ; 26 89 97 02 01 ; 0xf86ce
+ inc byte [es:di+00263h] ; 26 fe 85 63 02 ; 0xf86d3 ahci.c:377
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf86d8 ahci.c:379
+ mov bx, si ; 89 f3 ; 0xf86db
+ mov ax, word [es:bx+020h] ; 26 8b 47 20 ; 0xf86dd
+ test ax, ax ; 85 c0 ; 0xf86e1
+ je short 0871eh ; 74 39 ; 0xf86e3
+ dec ax ; 48 ; 0xf86e5 ahci.c:380
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf86e6
+ mov bl, byte [es:di+00263h] ; 26 8a 9d 63 02 ; 0xf86e9
+ xor bh, bh ; 30 ff ; 0xf86ee
+ sal bx, CL ; d3 e3 ; 0xf86f0
+ mov word [es:bx+0010ch], ax ; 26 89 87 0c 01 ; 0xf86f2
+ mov word [es:bx+0010eh], di ; 26 89 bf 0e 01 ; 0xf86f7
+ mov bl, byte [es:di+00263h] ; 26 8a 9d 63 02 ; 0xf86fc ahci.c:381
+ xor bh, bh ; 30 ff ; 0xf8701
+ sal bx, CL ; d3 e3 ; 0xf8703
+ mov ax, word [es:di+00264h] ; 26 8b 85 64 02 ; 0xf8705
+ mov dx, word [es:di+00266h] ; 26 8b 95 66 02 ; 0xf870a
+ mov word [es:bx+00100h], ax ; 26 89 87 00 01 ; 0xf870f
+ mov word [es:bx+00102h], dx ; 26 89 97 02 01 ; 0xf8714
+ inc byte [es:di+00263h] ; 26 fe 85 63 02 ; 0xf8719 ahci.c:382
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf871e ahci.c:397
+ cmp AL, strict byte 035h ; 3c 35 ; 0xf8721
+ jne short 0872bh ; 75 06 ; 0xf8723
+ mov byte [bp-008h], 040h ; c6 46 f8 40 ; 0xf8725 ahci.c:398
+ jmp short 08742h ; eb 17 ; 0xf8729 ahci.c:399
+ cmp AL, strict byte 0a0h ; 3c a0 ; 0xf872b
+ jne short 0873eh ; 75 0f ; 0xf872d
+ or byte [bp-008h], 020h ; 80 4e f8 20 ; 0xf872f ahci.c:400
+ les bx, [bp-00eh] ; c4 5e f2 ; 0xf8733 ahci.c:401
+ or byte [es:bx+00083h], 001h ; 26 80 8f 83 00 01 ; 0xf8736
+ jmp short 08742h ; eb 04 ; 0xf873c ahci.c:402
+ mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xf873e ahci.c:403
+ or byte [bp-008h], 005h ; 80 4e f8 05 ; 0xf8742 ahci.c:405
+ mov bl, byte [bp-008h] ; 8a 5e f8 ; 0xf8746 ahci.c:407
+ xor bh, bh ; 30 ff ; 0xf8749
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf874b
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf874e
+ call 083c7h ; e8 73 fc ; 0xf8751
+ mov cx, word [bp-00ch] ; 8b 4e f4 ; 0xf8754 ahci.c:410
+ mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xf8757
+ add bx, 00240h ; 81 c3 40 02 ; 0xf875a
+ mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xf875e ahci.c:414
+ add ax, 0026ah ; 05 6a 02 ; 0xf8761
+ mov dx, cx ; 89 ca ; 0xf8764
+ call 09b8eh ; e8 25 14 ; 0xf8766
+ mov es, cx ; 8e c1 ; 0xf8769 ahci.c:415
+ mov al, byte [es:bx+003h] ; 26 8a 47 03 ; 0xf876b
+ test al, al ; 84 c0 ; 0xf876f
+ je short 08778h ; 74 05 ; 0xf8771
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf8773
+ jmp short 0877ah ; eb 02 ; 0xf8776
+ xor ah, ah ; 30 e4 ; 0xf8778
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf877a ahci.c:416
+ pop di ; 5f ; 0xf877d
+ pop si ; 5e ; 0xf877e
+ pop cx ; 59 ; 0xf877f
+ pop bp ; 5d ; 0xf8780
+ retn ; c3 ; 0xf8781
+ ; disGetNextSymbol 0xf8782 LB 0x17c6 -> off=0x0 cb=0000000000000183 uValue=00000000000f7182 'ahci_port_deinit_current'
+ahci_port_deinit_current: ; 0xf8782 LB 0x183
+ push bp ; 55 ; 0xf8782 ahci.c:421
+ mov bp, sp ; 89 e5 ; 0xf8783
+ push bx ; 53 ; 0xf8785
+ push cx ; 51 ; 0xf8786
+ push si ; 56 ; 0xf8787
+ push di ; 57 ; 0xf8788
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf8789
+ mov di, ax ; 89 c7 ; 0xf878c
+ mov word [bp-00eh], dx ; 89 56 f2 ; 0xf878e
+ mov es, dx ; 8e c2 ; 0xf8791 ahci.c:426
+ mov si, word [es:di+00260h] ; 26 8b b5 60 02 ; 0xf8793
+ mov al, byte [es:di+00262h] ; 26 8a 85 62 02 ; 0xf8798 ahci.c:427
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf879d
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xf87a0 ahci.c:429
+ je short 08805h ; 74 61 ; 0xf87a2
+ xor ah, ah ; 30 e4 ; 0xf87a4 ahci.c:432
+ mov CL, strict byte 007h ; b1 07 ; 0xf87a6
+ sal ax, CL ; d3 e0 ; 0xf87a8
+ add ax, 00118h ; 05 18 01 ; 0xf87aa
+ xor cx, cx ; 31 c9 ; 0xf87ad ahci.c:261
+ mov dx, si ; 89 f2 ; 0xf87af
+ xchg cx, ax ; 91 ; 0xf87b1
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf87b2
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf87b6
+ out DX, eax ; 66 ef ; 0xf87b8
+ lea bx, [si+004h] ; 8d 5c 04 ; 0xf87ba ahci.c:262
+ mov dx, bx ; 89 da ; 0xf87bd
+ in eax, DX ; 66 ed ; 0xf87bf
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf87c1
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf87c3
+ xchg dx, ax ; 92 ; 0xf87c7
+ and AL, strict byte 0eeh ; 24 ee ; 0xf87c8
+ mov cx, dx ; 89 d1 ; 0xf87ca
+ mov dx, bx ; 89 da ; 0xf87cc
+ xchg cx, ax ; 91 ; 0xf87ce
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf87cf
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf87d3
+ out DX, eax ; 66 ef ; 0xf87d5
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf87d7 ahci.c:435
+ xor ah, ah ; 30 e4 ; 0xf87da
+ mov CL, strict byte 007h ; b1 07 ; 0xf87dc
+ sal ax, CL ; d3 e0 ; 0xf87de
+ add ax, 00118h ; 05 18 01 ; 0xf87e0
+ xor cx, cx ; 31 c9 ; 0xf87e3 ahci.c:271
+ mov dx, si ; 89 f2 ; 0xf87e5
+ xchg cx, ax ; 91 ; 0xf87e7
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf87e8
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf87ec
+ out DX, eax ; 66 ef ; 0xf87ee
+ lea dx, [si+004h] ; 8d 54 04 ; 0xf87f0 ahci.c:272
+ in eax, DX ; 66 ed ; 0xf87f3
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf87f5
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf87f7
+ xchg dx, ax ; 92 ; 0xf87fb
+ test ax, 0c011h ; a9 11 c0 ; 0xf87fc
+ je short 08808h ; 74 07 ; 0xf87ff
+ mov AL, strict byte 001h ; b0 01 ; 0xf8801
+ jmp short 0880ah ; eb 05 ; 0xf8803
+ jmp near 088fch ; e9 f4 00 ; 0xf8805
+ xor al, al ; 30 c0 ; 0xf8808
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf880a ahci.c:273
+ je short 087d7h ; 74 c9 ; 0xf880c
+ mov cx, strict word 00020h ; b9 20 00 ; 0xf880e ahci.c:446
+ xor bx, bx ; 31 db ; 0xf8811
+ mov ax, di ; 89 f8 ; 0xf8813
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf8815
+ call 09c30h ; e8 15 14 ; 0xf8818
+ lea ax, [di+00080h] ; 8d 85 80 00 ; 0xf881b ahci.c:447
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf881f
+ xor bx, bx ; 31 db ; 0xf8822
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf8824
+ call 09c30h ; e8 06 14 ; 0xf8827
+ lea ax, [di+00200h] ; 8d 85 00 02 ; 0xf882a ahci.c:448
+ mov cx, strict word 00060h ; b9 60 00 ; 0xf882e
+ xor bx, bx ; 31 db ; 0xf8831
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf8833
+ call 09c30h ; e8 f7 13 ; 0xf8836
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf8839 ahci.c:450
+ xor ah, ah ; 30 e4 ; 0xf883c
+ mov CL, strict byte 007h ; b1 07 ; 0xf883e
+ sal ax, CL ; d3 e0 ; 0xf8840
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf8842
+ add ax, 00108h ; 05 08 01 ; 0xf8845
+ cwd ; 99 ; 0xf8848
+ mov cx, dx ; 89 d1 ; 0xf8849
+ mov dx, si ; 89 f2 ; 0xf884b
+ xchg cx, ax ; 91 ; 0xf884d
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf884e
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8852
+ out DX, eax ; 66 ef ; 0xf8854
+ lea bx, [si+004h] ; 8d 5c 04 ; 0xf8856
+ xor ax, ax ; 31 c0 ; 0xf8859
+ xor cx, cx ; 31 c9 ; 0xf885b
+ mov dx, bx ; 89 da ; 0xf885d
+ xchg cx, ax ; 91 ; 0xf885f
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8860
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8864
+ out DX, eax ; 66 ef ; 0xf8866
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf8868 ahci.c:451
+ add ax, 0010ch ; 05 0c 01 ; 0xf886b
+ cwd ; 99 ; 0xf886e
+ mov cx, dx ; 89 d1 ; 0xf886f
+ mov dx, si ; 89 f2 ; 0xf8871
+ xchg cx, ax ; 91 ; 0xf8873
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8874
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8878
+ out DX, eax ; 66 ef ; 0xf887a
+ xor ax, ax ; 31 c0 ; 0xf887c
+ xor cx, cx ; 31 c9 ; 0xf887e
+ mov dx, bx ; 89 da ; 0xf8880
+ xchg cx, ax ; 91 ; 0xf8882
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8883
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8887
+ out DX, eax ; 66 ef ; 0xf8889
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf888b ahci.c:453
+ db 0feh, 0c4h
+ ; inc ah ; fe c4 ; 0xf888e
+ cwd ; 99 ; 0xf8890
+ mov cx, dx ; 89 d1 ; 0xf8891
+ mov dx, si ; 89 f2 ; 0xf8893
+ xchg cx, ax ; 91 ; 0xf8895
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8896
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf889a
+ out DX, eax ; 66 ef ; 0xf889c
+ xor ax, ax ; 31 c0 ; 0xf889e
+ xor cx, cx ; 31 c9 ; 0xf88a0
+ mov dx, bx ; 89 da ; 0xf88a2
+ xchg cx, ax ; 91 ; 0xf88a4
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf88a5
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf88a9
+ out DX, eax ; 66 ef ; 0xf88ab
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf88ad ahci.c:454
+ add ax, 00104h ; 05 04 01 ; 0xf88b0
+ cwd ; 99 ; 0xf88b3
+ mov cx, dx ; 89 d1 ; 0xf88b4
+ mov dx, si ; 89 f2 ; 0xf88b6
+ xchg cx, ax ; 91 ; 0xf88b8
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf88b9
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf88bd
+ out DX, eax ; 66 ef ; 0xf88bf
+ xor ax, ax ; 31 c0 ; 0xf88c1
+ xor cx, cx ; 31 c9 ; 0xf88c3
+ mov dx, bx ; 89 da ; 0xf88c5
+ xchg cx, ax ; 91 ; 0xf88c7
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf88c8
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf88cc
+ out DX, eax ; 66 ef ; 0xf88ce
+ mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xf88d0 ahci.c:457
+ add ax, 00114h ; 05 14 01 ; 0xf88d3
+ cwd ; 99 ; 0xf88d6
+ mov cx, dx ; 89 d1 ; 0xf88d7
+ mov dx, si ; 89 f2 ; 0xf88d9
+ xchg cx, ax ; 91 ; 0xf88db
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf88dc
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf88e0
+ out DX, eax ; 66 ef ; 0xf88e2
+ xor ax, ax ; 31 c0 ; 0xf88e4
+ xor cx, cx ; 31 c9 ; 0xf88e6
+ mov dx, bx ; 89 da ; 0xf88e8
+ xchg cx, ax ; 91 ; 0xf88ea
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf88eb
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf88ef
+ out DX, eax ; 66 ef ; 0xf88f1
+ mov es, [bp-00eh] ; 8e 46 f2 ; 0xf88f3 ahci.c:459
+ mov byte [es:di+00262h], 0ffh ; 26 c6 85 62 02 ff ; 0xf88f6
+ lea sp, [bp-008h] ; 8d 66 f8 ; 0xf88fc ahci.c:461
+ pop di ; 5f ; 0xf88ff
+ pop si ; 5e ; 0xf8900
+ pop cx ; 59 ; 0xf8901
+ pop bx ; 5b ; 0xf8902
+ pop bp ; 5d ; 0xf8903
+ retn ; c3 ; 0xf8904
+ ; disGetNextSymbol 0xf8905 LB 0x1643 -> off=0x0 cb=0000000000000250 uValue=00000000000f7305 'ahci_port_init'
+ahci_port_init: ; 0xf8905 LB 0x250
+ push bp ; 55 ; 0xf8905 ahci.c:467
+ mov bp, sp ; 89 e5 ; 0xf8906
+ push cx ; 51 ; 0xf8908
+ push si ; 56 ; 0xf8909
+ push di ; 57 ; 0xf890a
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf890b
+ mov si, ax ; 89 c6 ; 0xf890e
+ mov word [bp-00ah], dx ; 89 56 f6 ; 0xf8910
+ mov byte [bp-008h], bl ; 88 5e f8 ; 0xf8913
+ call 08782h ; e8 69 fe ; 0xf8916 ahci.c:470
+ mov al, bl ; 88 d8 ; 0xf8919 ahci.c:473
+ xor ah, ah ; 30 e4 ; 0xf891b
+ mov CL, strict byte 007h ; b1 07 ; 0xf891d
+ sal ax, CL ; d3 e0 ; 0xf891f
+ add ax, 00118h ; 05 18 01 ; 0xf8921
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8924 ahci.c:259
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8927
+ xor cx, cx ; 31 c9 ; 0xf892c ahci.c:261
+ mov dx, bx ; 89 da ; 0xf892e
+ xchg cx, ax ; 91 ; 0xf8930
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8931
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8935
+ out DX, eax ; 66 ef ; 0xf8937
+ add bx, strict byte 00004h ; 83 c3 04 ; 0xf8939 ahci.c:262
+ mov dx, bx ; 89 da ; 0xf893c
+ in eax, DX ; 66 ed ; 0xf893e
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8940
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8942
+ xchg dx, ax ; 92 ; 0xf8946
+ and AL, strict byte 0eeh ; 24 ee ; 0xf8947
+ mov cx, dx ; 89 d1 ; 0xf8949
+ mov dx, bx ; 89 da ; 0xf894b
+ xchg cx, ax ; 91 ; 0xf894d
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf894e
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8952
+ out DX, eax ; 66 ef ; 0xf8954
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8956 ahci.c:476
+ xor ah, ah ; 30 e4 ; 0xf8959
+ mov CL, strict byte 007h ; b1 07 ; 0xf895b
+ sal ax, CL ; d3 e0 ; 0xf895d
+ add ax, 00118h ; 05 18 01 ; 0xf895f
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8962 ahci.c:269
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8965
+ xor cx, cx ; 31 c9 ; 0xf896a ahci.c:271
+ mov dx, bx ; 89 da ; 0xf896c
+ xchg cx, ax ; 91 ; 0xf896e
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf896f
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8973
+ out DX, eax ; 66 ef ; 0xf8975
+ lea dx, [bx+004h] ; 8d 57 04 ; 0xf8977 ahci.c:272
+ in eax, DX ; 66 ed ; 0xf897a
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf897c
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf897e
+ xchg dx, ax ; 92 ; 0xf8982
+ test ax, 0c011h ; a9 11 c0 ; 0xf8983
+ je short 0898ch ; 74 04 ; 0xf8986
+ mov AL, strict byte 001h ; b0 01 ; 0xf8988
+ jmp short 0898eh ; eb 02 ; 0xf898a
+ xor al, al ; 30 c0 ; 0xf898c
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf898e ahci.c:273
+ je short 08956h ; 74 c4 ; 0xf8990
+ mov cx, strict word 00020h ; b9 20 00 ; 0xf8992 ahci.c:487
+ xor bx, bx ; 31 db ; 0xf8995
+ mov ax, si ; 89 f0 ; 0xf8997
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8999
+ call 09c30h ; e8 91 12 ; 0xf899c
+ lea ax, [si+00080h] ; 8d 84 80 00 ; 0xf899f ahci.c:488
+ mov cx, strict word 00040h ; b9 40 00 ; 0xf89a3
+ xor bx, bx ; 31 db ; 0xf89a6
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf89a8
+ call 09c30h ; e8 82 12 ; 0xf89ab
+ lea di, [si+00200h] ; 8d bc 00 02 ; 0xf89ae ahci.c:489
+ mov cx, strict word 00060h ; b9 60 00 ; 0xf89b2
+ xor bx, bx ; 31 db ; 0xf89b5
+ mov ax, di ; 89 f8 ; 0xf89b7
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf89b9
+ call 09c30h ; e8 71 12 ; 0xf89bc
+ mov bl, byte [bp-008h] ; 8a 5e f8 ; 0xf89bf ahci.c:493
+ xor bh, bh ; 30 ff ; 0xf89c2
+ mov CL, strict byte 007h ; b1 07 ; 0xf89c4
+ sal bx, CL ; d3 e3 ; 0xf89c6
+ lea ax, [bx+00108h] ; 8d 87 08 01 ; 0xf89c8
+ cwd ; 99 ; 0xf89cc
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf89cd
+ mov cx, word [es:si+00260h] ; 26 8b 8c 60 02 ; 0xf89d0
+ mov word [bp-00ch], cx ; 89 4e f4 ; 0xf89d5
+ mov cx, dx ; 89 d1 ; 0xf89d8
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf89da
+ xchg cx, ax ; 91 ; 0xf89dd
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf89de
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf89e2
+ out DX, eax ; 66 ef ; 0xf89e4
+ mov ax, di ; 89 f8 ; 0xf89e6
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf89e8
+ call 083a9h ; e8 bb f9 ; 0xf89eb
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf89ee
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf89f1
+ add di, strict byte 00004h ; 83 c7 04 ; 0xf89f6
+ mov cx, dx ; 89 d1 ; 0xf89f9
+ mov dx, di ; 89 fa ; 0xf89fb
+ xchg cx, ax ; 91 ; 0xf89fd
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf89fe
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8a02
+ out DX, eax ; 66 ef ; 0xf8a04
+ lea ax, [bx+0010ch] ; 8d 87 0c 01 ; 0xf8a06 ahci.c:494
+ cwd ; 99 ; 0xf8a0a
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a0b
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8a0e
+ mov cx, dx ; 89 d1 ; 0xf8a13
+ mov dx, di ; 89 fa ; 0xf8a15
+ xchg cx, ax ; 91 ; 0xf8a17
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8a18
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8a1c
+ out DX, eax ; 66 ef ; 0xf8a1e
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a20
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8a23
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8a28
+ xor ax, ax ; 31 c0 ; 0xf8a2b
+ xor cx, cx ; 31 c9 ; 0xf8a2d
+ xchg cx, ax ; 91 ; 0xf8a2f
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8a30
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8a34
+ out DX, eax ; 66 ef ; 0xf8a36
+ lea ax, [bx+00100h] ; 8d 87 00 01 ; 0xf8a38 ahci.c:497
+ cwd ; 99 ; 0xf8a3c
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a3d
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8a40
+ mov cx, dx ; 89 d1 ; 0xf8a45
+ mov dx, di ; 89 fa ; 0xf8a47
+ xchg cx, ax ; 91 ; 0xf8a49
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8a4a
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8a4e
+ out DX, eax ; 66 ef ; 0xf8a50
+ mov ax, si ; 89 f0 ; 0xf8a52
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8a54
+ call 083a9h ; e8 4f f9 ; 0xf8a57
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a5a
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8a5d
+ add di, strict byte 00004h ; 83 c7 04 ; 0xf8a62
+ mov cx, dx ; 89 d1 ; 0xf8a65
+ mov dx, di ; 89 fa ; 0xf8a67
+ xchg cx, ax ; 91 ; 0xf8a69
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8a6a
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8a6e
+ out DX, eax ; 66 ef ; 0xf8a70
+ lea ax, [bx+00104h] ; 8d 87 04 01 ; 0xf8a72 ahci.c:498
+ cwd ; 99 ; 0xf8a76
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a77
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8a7a
+ mov cx, dx ; 89 d1 ; 0xf8a7f
+ mov dx, di ; 89 fa ; 0xf8a81
+ xchg cx, ax ; 91 ; 0xf8a83
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8a84
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8a88
+ out DX, eax ; 66 ef ; 0xf8a8a
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8a8c
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8a8f
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8a94
+ xor ax, ax ; 31 c0 ; 0xf8a97
+ xor cx, cx ; 31 c9 ; 0xf8a99
+ xchg cx, ax ; 91 ; 0xf8a9b
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8a9c
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8aa0
+ out DX, eax ; 66 ef ; 0xf8aa2
+ lea ax, [bx+00114h] ; 8d 87 14 01 ; 0xf8aa4 ahci.c:501
+ cwd ; 99 ; 0xf8aa8
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8aa9
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8aac
+ mov cx, dx ; 89 d1 ; 0xf8ab1
+ mov dx, di ; 89 fa ; 0xf8ab3
+ xchg cx, ax ; 91 ; 0xf8ab5
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8ab6
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8aba
+ out DX, eax ; 66 ef ; 0xf8abc
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8abe
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8ac1
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8ac6
+ xor ax, ax ; 31 c0 ; 0xf8ac9
+ xor cx, cx ; 31 c9 ; 0xf8acb
+ xchg cx, ax ; 91 ; 0xf8acd
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8ace
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8ad2
+ out DX, eax ; 66 ef ; 0xf8ad4
+ lea ax, [bx+00110h] ; 8d 87 10 01 ; 0xf8ad6 ahci.c:502
+ cwd ; 99 ; 0xf8ada
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8adb
+ mov di, word [es:si+00260h] ; 26 8b bc 60 02 ; 0xf8ade
+ mov cx, dx ; 89 d1 ; 0xf8ae3
+ mov dx, di ; 89 fa ; 0xf8ae5
+ xchg cx, ax ; 91 ; 0xf8ae7
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8ae8
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8aec
+ out DX, eax ; 66 ef ; 0xf8aee
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8af0
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8af3
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8af8
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf8afb
+ mov cx, ax ; 89 c1 ; 0xf8afe
+ xchg cx, ax ; 91 ; 0xf8b00
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8b01
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8b05
+ out DX, eax ; 66 ef ; 0xf8b07
+ lea ax, [bx+00130h] ; 8d 87 30 01 ; 0xf8b09 ahci.c:504
+ cwd ; 99 ; 0xf8b0d
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8b0e
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8b11
+ mov cx, dx ; 89 d1 ; 0xf8b16
+ mov dx, bx ; 89 da ; 0xf8b18
+ xchg cx, ax ; 91 ; 0xf8b1a
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8b1b
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8b1f
+ out DX, eax ; 66 ef ; 0xf8b21
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8b23
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8b26
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8b2b
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf8b2e
+ mov cx, ax ; 89 c1 ; 0xf8b31
+ xchg cx, ax ; 91 ; 0xf8b33
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8b34
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8b38
+ out DX, eax ; 66 ef ; 0xf8b3a
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8b3c ahci.c:506
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8b3f
+ mov byte [es:si+00262h], al ; 26 88 84 62 02 ; 0xf8b42
+ mov byte [es:si+00263h], 000h ; 26 c6 84 63 02 00 ; 0xf8b47 ahci.c:507
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf8b4d ahci.c:508
+ pop di ; 5f ; 0xf8b50
+ pop si ; 5e ; 0xf8b51
+ pop cx ; 59 ; 0xf8b52
+ pop bp ; 5d ; 0xf8b53
+ retn ; c3 ; 0xf8b54
+ ; disGetNextSymbol 0xf8b55 LB 0x13f3 -> off=0x0 cb=00000000000000aa uValue=00000000000f7555 'ahci_read_sectors'
+ahci_read_sectors: ; 0xf8b55 LB 0xaa
+ push bp ; 55 ; 0xf8b55 ahci.c:517
+ mov bp, sp ; 89 e5 ; 0xf8b56
+ push si ; 56 ; 0xf8b58
+ push di ; 57 ; 0xf8b59
+ les bx, [bp+004h] ; c4 5e 04 ; 0xf8b5a ahci.c:522
+ mov al, byte [es:bx+00ch] ; 26 8a 47 0c ; 0xf8b5d
+ xor ah, ah ; 30 e4 ; 0xf8b61
+ mov di, ax ; 89 c7 ; 0xf8b63
+ sub di, strict byte 0000ch ; 83 ef 0c ; 0xf8b65
+ cmp di, strict byte 00004h ; 83 ff 04 ; 0xf8b68 ahci.c:523
+ jbe short 08b80h ; 76 13 ; 0xf8b6b
+ push di ; 57 ; 0xf8b6d ahci.c:524
+ mov ax, 00c62h ; b8 62 0c ; 0xf8b6e
+ push ax ; 50 ; 0xf8b71
+ mov ax, 00c74h ; b8 74 0c ; 0xf8b72
+ push ax ; 50 ; 0xf8b75
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf8b76
+ push ax ; 50 ; 0xf8b79
+ call 0190fh ; e8 92 8d ; 0xf8b7a
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf8b7d
+ xor bx, bx ; 31 db ; 0xf8b80 ahci.c:530
+ les si, [bp+004h] ; c4 76 04 ; 0xf8b82
+ mov dx, word [es:si+00232h] ; 26 8b 94 32 02 ; 0xf8b85
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8b8a ahci.c:239
+ mov es, dx ; 8e c2 ; 0xf8b8e
+ mov word [es:bx+00268h], ax ; 26 89 87 68 02 ; 0xf8b90
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf8b95 ahci.c:531
+ add di, si ; 01 f7 ; 0xf8b98
+ mov bl, byte [es:di+0022dh] ; 26 8a 9d 2d 02 ; 0xf8b9a
+ xor bh, bh ; 30 ff ; 0xf8b9f
+ mov dx, word [es:si+00232h] ; 26 8b 94 32 02 ; 0xf8ba1
+ xor ax, ax ; 31 c0 ; 0xf8ba6
+ call 08905h ; e8 5a fd ; 0xf8ba8
+ mov bx, strict word 00025h ; bb 25 00 ; 0xf8bab ahci.c:532
+ mov ax, si ; 89 f0 ; 0xf8bae
+ mov dx, word [bp+006h] ; 8b 56 06 ; 0xf8bb0
+ call 08520h ; e8 6a f9 ; 0xf8bb3
+ mov bx, ax ; 89 c3 ; 0xf8bb6
+ mov es, [bp+006h] ; 8e 46 06 ; 0xf8bb8 ahci.c:534
+ mov ax, word [es:si+00eh] ; 26 8b 44 0e ; 0xf8bbb
+ mov word [es:si+018h], ax ; 26 89 44 18 ; 0xf8bbf
+ mov CL, strict byte 009h ; b1 09 ; 0xf8bc3 ahci.c:536
+ sal ax, CL ; d3 e0 ; 0xf8bc5
+ mov cx, ax ; 89 c1 ; 0xf8bc7
+ shr cx, 1 ; d1 e9 ; 0xf8bc9
+ mov di, si ; 89 f7 ; 0xf8bcb
+ mov di, word [es:di+008h] ; 26 8b 7d 08 ; 0xf8bcd
+ mov ax, word [es:si+00ah] ; 26 8b 44 0a ; 0xf8bd1
+ mov si, di ; 89 fe ; 0xf8bd5
+ mov dx, ax ; 89 c2 ; 0xf8bd7
+ mov es, ax ; 8e c0 ; 0xf8bd9
+ push DS ; 1e ; 0xf8bdb
+ mov ds, dx ; 8e da ; 0xf8bdc
+ rep movsw ; f3 a5 ; 0xf8bde
+ pop DS ; 1f ; 0xf8be0
+ xor di, di ; 31 ff ; 0xf8be1 ahci.c:538
+ les si, [bp+004h] ; c4 76 04 ; 0xf8be3
+ mov es, [es:si+00232h] ; 26 8e 84 32 02 ; 0xf8be6
+ mov ax, word [es:di+00268h] ; 26 8b 85 68 02 ; 0xf8beb ahci.c:244
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8bf0
+ mov ax, bx ; 89 d8 ; 0xf8bf4 ahci.c:540
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf8bf6
+ pop di ; 5f ; 0xf8bf9
+ pop si ; 5e ; 0xf8bfa
+ pop bp ; 5d ; 0xf8bfb
+ retn 00004h ; c2 04 00 ; 0xf8bfc
+ ; disGetNextSymbol 0xf8bff LB 0x1349 -> off=0x0 cb=0000000000000088 uValue=00000000000f75ff 'ahci_write_sectors'
+ahci_write_sectors: ; 0xf8bff LB 0x88
+ push bp ; 55 ; 0xf8bff ahci.c:549
+ mov bp, sp ; 89 e5 ; 0xf8c00
+ push si ; 56 ; 0xf8c02
+ push di ; 57 ; 0xf8c03
+ mov si, word [bp+004h] ; 8b 76 04 ; 0xf8c04
+ mov cx, word [bp+006h] ; 8b 4e 06 ; 0xf8c07
+ mov es, cx ; 8e c1 ; 0xf8c0a ahci.c:554
+ mov bl, byte [es:si+00ch] ; 26 8a 5c 0c ; 0xf8c0c
+ xor bh, bh ; 30 ff ; 0xf8c10
+ sub bx, strict byte 0000ch ; 83 eb 0c ; 0xf8c12
+ cmp bx, strict byte 00004h ; 83 fb 04 ; 0xf8c15 ahci.c:555
+ jbe short 08c2dh ; 76 13 ; 0xf8c18
+ push bx ; 53 ; 0xf8c1a ahci.c:556
+ mov ax, 00c93h ; b8 93 0c ; 0xf8c1b
+ push ax ; 50 ; 0xf8c1e
+ mov ax, 00c74h ; b8 74 0c ; 0xf8c1f
+ push ax ; 50 ; 0xf8c22
+ mov ax, strict word 00007h ; b8 07 00 ; 0xf8c23
+ push ax ; 50 ; 0xf8c26
+ call 0190fh ; e8 e5 8c ; 0xf8c27
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf8c2a
+ xor di, di ; 31 ff ; 0xf8c2d ahci.c:562
+ mov es, cx ; 8e c1 ; 0xf8c2f
+ mov dx, word [es:si+00232h] ; 26 8b 94 32 02 ; 0xf8c31
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8c36 ahci.c:239
+ mov es, dx ; 8e c2 ; 0xf8c3a
+ mov word [es:di+00268h], ax ; 26 89 85 68 02 ; 0xf8c3c
+ mov es, cx ; 8e c1 ; 0xf8c41 ahci.c:563
+ add bx, si ; 01 f3 ; 0xf8c43
+ mov bl, byte [es:bx+0022dh] ; 26 8a 9f 2d 02 ; 0xf8c45
+ xor bh, bh ; 30 ff ; 0xf8c4a
+ mov dx, word [es:si+00232h] ; 26 8b 94 32 02 ; 0xf8c4c
+ xor ax, ax ; 31 c0 ; 0xf8c51
+ call 08905h ; e8 af fc ; 0xf8c53
+ mov bx, strict word 00035h ; bb 35 00 ; 0xf8c56 ahci.c:564
+ mov ax, si ; 89 f0 ; 0xf8c59
+ mov dx, cx ; 89 ca ; 0xf8c5b
+ call 08520h ; e8 c0 f8 ; 0xf8c5d
+ mov dx, ax ; 89 c2 ; 0xf8c60
+ mov es, cx ; 8e c1 ; 0xf8c62 ahci.c:566
+ mov ax, word [es:si+00eh] ; 26 8b 44 0e ; 0xf8c64
+ mov word [es:si+018h], ax ; 26 89 44 18 ; 0xf8c68
+ xor bx, bx ; 31 db ; 0xf8c6c ahci.c:567
+ mov es, [es:si+00232h] ; 26 8e 84 32 02 ; 0xf8c6e
+ mov ax, word [es:bx+00268h] ; 26 8b 87 68 02 ; 0xf8c73 ahci.c:244
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8c78
+ mov ax, dx ; 89 d0 ; 0xf8c7c ahci.c:569
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf8c7e
+ pop di ; 5f ; 0xf8c81
+ pop si ; 5e ; 0xf8c82
+ pop bp ; 5d ; 0xf8c83
+ retn 00004h ; c2 04 00 ; 0xf8c84
+ ; disGetNextSymbol 0xf8c87 LB 0x12c1 -> off=0x0 cb=0000000000000190 uValue=00000000000f7687 'ahci_cmd_packet'
+ahci_cmd_packet: ; 0xf8c87 LB 0x190
+ push bp ; 55 ; 0xf8c87 ahci.c:576
+ mov bp, sp ; 89 e5 ; 0xf8c88
+ push si ; 56 ; 0xf8c8a
+ push di ; 57 ; 0xf8c8b
+ sub sp, strict byte 0000eh ; 83 ec 0e ; 0xf8c8c
+ push ax ; 50 ; 0xf8c8f
+ mov byte [bp-006h], dl ; 88 56 fa ; 0xf8c90
+ mov word [bp-012h], bx ; 89 5e ee ; 0xf8c93
+ mov word [bp-010h], cx ; 89 4e f0 ; 0xf8c96
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf8c99 ahci.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf8c9c
+ mov es, ax ; 8e c0 ; 0xf8c9f
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf8ca1
+ mov si, 00122h ; be 22 01 ; 0xf8ca4 ahci.c:49
+ mov word [bp-008h], ax ; 89 46 f8 ; 0xf8ca7
+ cmp byte [bp+00ah], 002h ; 80 7e 0a 02 ; 0xf8caa ahci.c:583
+ jne short 08cd3h ; 75 23 ; 0xf8cae
+ mov bx, 00da0h ; bb a0 0d ; 0xf8cb0 ahci.c:584
+ mov cx, ds ; 8c d9 ; 0xf8cb3
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf8cb5
+ call 018cch ; e8 11 8c ; 0xf8cb8
+ mov ax, 00ca6h ; b8 a6 0c ; 0xf8cbb
+ push ax ; 50 ; 0xf8cbe
+ mov ax, 00cb6h ; b8 b6 0c ; 0xf8cbf
+ push ax ; 50 ; 0xf8cc2
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf8cc3
+ push ax ; 50 ; 0xf8cc6
+ call 0190fh ; e8 45 8c ; 0xf8cc7
+ add sp, strict byte 00006h ; 83 c4 06 ; 0xf8cca
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf8ccd ahci.c:585
+ jmp near 08e0eh ; e9 3b 01 ; 0xf8cd0
+ test byte [bp+004h], 001h ; f6 46 04 01 ; 0xf8cd3 ahci.c:589
+ jne short 08ccdh ; 75 f4 ; 0xf8cd7
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf8cd9 ahci.c:603
+ mov dx, word [bp+008h] ; 8b 56 08 ; 0xf8cdc
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf8cdf
+ sal ax, 1 ; d1 e0 ; 0xf8ce2
+ rcl dx, 1 ; d1 d2 ; 0xf8ce4
+ loop 08ce2h ; e2 fa ; 0xf8ce6
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf8ce8
+ mov word [es:si], ax ; 26 89 04 ; 0xf8ceb
+ mov word [es:si+002h], dx ; 26 89 54 02 ; 0xf8cee
+ mov word [es:si+004h], strict word 00000h ; 26 c7 44 04 00 00 ; 0xf8cf2
+ mov word [es:si+006h], strict word 00000h ; 26 c7 44 06 00 00 ; 0xf8cf8
+ mov ax, word [bp+00ch] ; 8b 46 0c ; 0xf8cfe ahci.c:604
+ mov word [es:si+008h], ax ; 26 89 44 08 ; 0xf8d01
+ mov ax, word [bp+00eh] ; 8b 46 0e ; 0xf8d05
+ mov word [es:si+00ah], ax ; 26 89 44 0a ; 0xf8d08
+ mov bx, word [es:si+010h] ; 26 8b 5c 10 ; 0xf8d0c ahci.c:605
+ mov ax, word [bp+006h] ; 8b 46 06 ; 0xf8d10
+ mov dx, word [bp+008h] ; 8b 56 08 ; 0xf8d13
+ xor cx, cx ; 31 c9 ; 0xf8d16
+ call 09be0h ; e8 c5 0e ; 0xf8d18
+ mov word [es:si+00eh], ax ; 26 89 44 0e ; 0xf8d1b
+ xor di, di ; 31 ff ; 0xf8d1f ahci.c:608
+ mov ax, word [es:si+00232h] ; 26 8b 84 32 02 ; 0xf8d21
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf8d26
+ mov word [bp-00eh], di ; 89 7e f2 ; 0xf8d29
+ mov word [bp-00ch], ax ; 89 46 f4 ; 0xf8d2c
+ sub word [bp-014h], strict byte 0000ch ; 83 6e ec 0c ; 0xf8d2f ahci.c:595
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8d33 ahci.c:239
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8d37
+ mov word [es:di+00268h], ax ; 26 89 85 68 02 ; 0xf8d3a
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf8d3f ahci.c:611
+ mov bx, word [bp-014h] ; 8b 5e ec ; 0xf8d42
+ add bx, si ; 01 f3 ; 0xf8d45
+ mov al, byte [es:bx+0022dh] ; 26 8a 87 2d 02 ; 0xf8d47
+ xor ah, ah ; 30 e4 ; 0xf8d4c
+ mov dx, word [es:si+00232h] ; 26 8b 94 32 02 ; 0xf8d4e
+ mov bx, ax ; 89 c3 ; 0xf8d53
+ xor al, al ; 30 c0 ; 0xf8d55
+ call 08905h ; e8 ab fb ; 0xf8d57
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf8d5a ahci.c:614
+ xor ah, ah ; 30 e4 ; 0xf8d5d
+ push ax ; 50 ; 0xf8d5f
+ mov bx, word [bp-012h] ; 8b 5e ee ; 0xf8d60
+ mov cx, word [bp-010h] ; 8b 4e f0 ; 0xf8d63
+ mov ax, 000c0h ; b8 c0 00 ; 0xf8d66
+ mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xf8d69
+ call 09c40h ; e8 d1 0e ; 0xf8d6c
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf8d6f ahci.c:618
+ mov word [es:si+018h], di ; 26 89 7c 18 ; 0xf8d72
+ mov word [es:si+01ah], di ; 26 89 7c 1a ; 0xf8d76 ahci.c:619
+ mov word [es:si+01ch], di ; 26 89 7c 1c ; 0xf8d7a
+ mov ax, word [es:si+01eh] ; 26 8b 44 1e ; 0xf8d7e ahci.c:622
+ test ax, ax ; 85 c0 ; 0xf8d82
+ je short 08dadh ; 74 27 ; 0xf8d84
+ dec ax ; 48 ; 0xf8d86 ahci.c:623
+ mov es, [bp-00ah] ; 8e 46 f6 ; 0xf8d87
+ mov word [es:di+0010ch], ax ; 26 89 85 0c 01 ; 0xf8d8a
+ mov word [es:di+0010eh], di ; 26 89 bd 0e 01 ; 0xf8d8f
+ mov ax, word [es:di+00264h] ; 26 8b 85 64 02 ; 0xf8d94 ahci.c:624
+ mov dx, word [es:di+00266h] ; 26 8b 95 66 02 ; 0xf8d99
+ mov word [es:di+00100h], ax ; 26 89 85 00 01 ; 0xf8d9e
+ mov word [es:di+00102h], dx ; 26 89 95 02 01 ; 0xf8da3
+ inc byte [es:di+00263h] ; 26 fe 85 63 02 ; 0xf8da8 ahci.c:625
+ mov bx, 000a0h ; bb a0 00 ; 0xf8dad ahci.c:628
+ mov ax, si ; 89 f0 ; 0xf8db0
+ mov dx, word [bp-008h] ; 8b 56 f8 ; 0xf8db2
+ call 08520h ; e8 68 f7 ; 0xf8db5
+ les bx, [bp-00eh] ; c4 5e f2 ; 0xf8db8 ahci.c:630
+ mov ax, word [es:bx+004h] ; 26 8b 47 04 ; 0xf8dbb
+ mov dx, word [es:bx+006h] ; 26 8b 57 06 ; 0xf8dbf
+ mov es, [bp-008h] ; 8e 46 f8 ; 0xf8dc3
+ mov word [es:si+01ah], ax ; 26 89 44 1a ; 0xf8dc6
+ mov word [es:si+01ch], dx ; 26 89 54 1c ; 0xf8dca
+ mov bx, word [es:si+01ah] ; 26 8b 5c 1a ; 0xf8dce ahci.c:632
+ mov cx, dx ; 89 d1 ; 0xf8dd2
+ shr cx, 1 ; d1 e9 ; 0xf8dd4
+ rcr bx, 1 ; d1 db ; 0xf8dd6
+ mov di, word [es:si+008h] ; 26 8b 7c 08 ; 0xf8dd8
+ mov ax, word [es:si+00ah] ; 26 8b 44 0a ; 0xf8ddc
+ mov cx, bx ; 89 d9 ; 0xf8de0
+ mov si, di ; 89 fe ; 0xf8de2
+ mov dx, ax ; 89 c2 ; 0xf8de4
+ mov es, ax ; 8e c0 ; 0xf8de6
+ push DS ; 1e ; 0xf8de8
+ mov ds, dx ; 8e da ; 0xf8de9
+ rep movsw ; f3 a5 ; 0xf8deb
+ pop DS ; 1f ; 0xf8ded
+ les bx, [bp-00eh] ; c4 5e f2 ; 0xf8dee ahci.c:244
+ mov ax, word [es:bx+00268h] ; 26 8b 87 68 02 ; 0xf8df1
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8df6
+ mov es, [bp-00ch] ; 8e 46 f4 ; 0xf8dfa ahci.c:636
+ mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xf8dfd
+ or ax, word [es:bx+004h] ; 26 0b 47 04 ; 0xf8e01
+ jne short 08e0ch ; 75 05 ; 0xf8e05
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf8e07
+ jmp short 08e0eh ; eb 02 ; 0xf8e0a
+ xor ax, ax ; 31 c0 ; 0xf8e0c
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf8e0e ahci.c:637
+ pop di ; 5f ; 0xf8e11
+ pop si ; 5e ; 0xf8e12
+ pop bp ; 5d ; 0xf8e13
+ retn 0000ch ; c2 0c 00 ; 0xf8e14
+ ; disGetNextSymbol 0xf8e17 LB 0x1131 -> off=0x0 cb=0000000000000005 uValue=00000000000f7817 'wait_ticks_device_init'
+wait_ticks_device_init: ; 0xf8e17 LB 0x5
+ push bp ; 55 ; 0xf8e17 ahci.c:640
+ mov bp, sp ; 89 e5 ; 0xf8e18
+ pop bp ; 5d ; 0xf8e1a ahci.c:642
+ retn ; c3 ; 0xf8e1b
+ ; disGetNextSymbol 0xf8e1c LB 0x112c -> off=0x0 cb=0000000000000509 uValue=00000000000f781c 'ahci_port_detect_device'
+ahci_port_detect_device: ; 0xf8e1c LB 0x509
+ push bp ; 55 ; 0xf8e1c ahci.c:644
+ mov bp, sp ; 89 e5 ; 0xf8e1d
+ push cx ; 51 ; 0xf8e1f
+ push si ; 56 ; 0xf8e20
+ push di ; 57 ; 0xf8e21
+ sub sp, 0022eh ; 81 ec 2e 02 ; 0xf8e22
+ mov si, ax ; 89 c6 ; 0xf8e26
+ mov word [bp-018h], dx ; 89 56 e8 ; 0xf8e28
+ mov byte [bp-008h], bl ; 88 5e f8 ; 0xf8e2b
+ mov word [bp-022h], strict word 00000h ; c7 46 de 00 00 ; 0xf8e2e ahci.c:650
+ mov al, bl ; 88 d8 ; 0xf8e33 ahci.c:652
+ mov byte [bp-02ah], bl ; 88 5e d6 ; 0xf8e35
+ xor al, bl ; 30 d8 ; 0xf8e38
+ mov byte [bp-029h], al ; 88 46 d7 ; 0xf8e3a
+ mov bx, word [bp-02ah] ; 8b 5e d6 ; 0xf8e3d
+ mov ax, si ; 89 f0 ; 0xf8e40
+ call 08905h ; e8 c0 fa ; 0xf8e42
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf8e45 ahci.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf8e48
+ mov es, ax ; 8e c0 ; 0xf8e4b
+ mov ax, word [es:bx] ; 26 8b 07 ; 0xf8e4d
+ mov word [bp-026h], 00122h ; c7 46 da 22 01 ; 0xf8e50 ahci.c:49
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf8e55
+ mov CL, strict byte 007h ; b1 07 ; 0xf8e58 ahci.c:657
+ mov ax, word [bp-02ah] ; 8b 46 d6 ; 0xf8e5a
+ sal ax, CL ; d3 e0 ; 0xf8e5d
+ add ax, 0012ch ; 05 2c 01 ; 0xf8e5f
+ cwd ; 99 ; 0xf8e62
+ mov di, ax ; 89 c7 ; 0xf8e63
+ mov bx, dx ; 89 d3 ; 0xf8e65
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf8e67
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8e6a
+ mov cx, bx ; 89 d9 ; 0xf8e6f
+ xchg cx, ax ; 91 ; 0xf8e71
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8e72
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8e76
+ out DX, eax ; 66 ef ; 0xf8e78
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf8e7a
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8e7d
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8e82
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf8e85
+ xor cx, cx ; 31 c9 ; 0xf8e88
+ xchg cx, ax ; 91 ; 0xf8e8a
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8e8b
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8e8f
+ out DX, eax ; 66 ef ; 0xf8e91
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf8e93 ahci.c:662
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8e96
+ mov ax, di ; 89 f8 ; 0xf8e9b
+ mov cx, bx ; 89 d9 ; 0xf8e9d
+ xchg cx, ax ; 91 ; 0xf8e9f
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8ea0
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8ea4
+ out DX, eax ; 66 ef ; 0xf8ea6
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf8ea8
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8eab
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8eb0
+ xor ax, ax ; 31 c0 ; 0xf8eb3
+ xor cx, cx ; 31 c9 ; 0xf8eb5
+ xchg cx, ax ; 91 ; 0xf8eb7
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8eb8
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8ebc
+ out DX, eax ; 66 ef ; 0xf8ebe
+ mov di, strict word 0006ch ; bf 6c 00 ; 0xf8ec0 ahci.c:671
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf8ec3
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf8ec6
+ mov es, ax ; 8e c0 ; 0xf8ec9 ahci.c:672
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf8ecb
+ add ax, strict word 00003h ; 05 03 00 ; 0xf8ece
+ mov word [bp-01eh], ax ; 89 46 e2 ; 0xf8ed1
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf8ed4
+ adc ax, strict word 00000h ; 15 00 00 ; 0xf8ed8
+ mov word [bp-01ch], ax ; 89 46 e4 ; 0xf8edb
+ mov es, [bp-010h] ; 8e 46 f0 ; 0xf8ede ahci.c:674
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf8ee1
+ cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xf8ee5
+ jc short 08efbh ; 72 11 ; 0xf8ee8
+ mov ax, word [es:di+002h] ; 26 8b 45 02 ; 0xf8eea
+ cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xf8eee
+ jne short 08f49h ; 75 56 ; 0xf8ef1
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf8ef3
+ cmp ax, word [bp-01eh] ; 3b 46 e2 ; 0xf8ef6
+ jnc short 08f49h ; 73 4e ; 0xf8ef9
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8efb ahci.c:677
+ xor ah, ah ; 30 e4 ; 0xf8efe
+ mov CL, strict byte 007h ; b1 07 ; 0xf8f00
+ sal ax, CL ; d3 e0 ; 0xf8f02
+ add ax, 00128h ; 05 28 01 ; 0xf8f04
+ cwd ; 99 ; 0xf8f07
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf8f08
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8f0b
+ mov cx, dx ; 89 d1 ; 0xf8f10
+ mov dx, bx ; 89 da ; 0xf8f12
+ xchg cx, ax ; 91 ; 0xf8f14
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8f15
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8f19
+ out DX, eax ; 66 ef ; 0xf8f1b
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf8f1d
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8f20
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8f25
+ in eax, DX ; 66 ed ; 0xf8f28
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8f2a
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8f2c
+ xchg dx, ax ; 92 ; 0xf8f30
+ mov word [bp-024h], ax ; 89 46 dc ; 0xf8f31
+ mov word [bp-020h], dx ; 89 56 e0 ; 0xf8f34
+ xor bx, bx ; 31 db ; 0xf8f37 ahci.c:678
+ push bx ; 53 ; 0xf8f39
+ mov bx, strict word 0000fh ; bb 0f 00 ; 0xf8f3a
+ xor cx, cx ; 31 c9 ; 0xf8f3d
+ call 0838dh ; e8 4b f4 ; 0xf8f3f
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf8f42
+ jne short 08edeh ; 75 97 ; 0xf8f45
+ jmp short 08f52h ; eb 09 ; 0xf8f47 ahci.c:680
+ cmp word [bp-022h], strict byte 00000h ; 83 7e de 00 ; 0xf8f49 ahci.c:685
+ jne short 08f52h ; 75 03 ; 0xf8f4d
+ jmp near 0931dh ; e9 cb 03 ; 0xf8f4f
+ xor ax, ax ; 31 c0 ; 0xf8f52 ahci.c:690
+ push ax ; 50 ; 0xf8f54
+ mov bx, strict word 0000fh ; bb 0f 00 ; 0xf8f55
+ xor cx, cx ; 31 c9 ; 0xf8f58
+ mov ax, word [bp-024h] ; 8b 46 dc ; 0xf8f5a
+ mov dx, word [bp-020h] ; 8b 56 e0 ; 0xf8f5d
+ call 0838dh ; e8 2a f4 ; 0xf8f60
+ cmp ax, strict word 00003h ; 3d 03 00 ; 0xf8f63
+ jne short 08f4fh ; 75 e7 ; 0xf8f66
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf8f68 ahci.c:698
+ xor ah, ah ; 30 e4 ; 0xf8f6b
+ mov CL, strict byte 007h ; b1 07 ; 0xf8f6d
+ mov di, ax ; 89 c7 ; 0xf8f6f
+ sal di, CL ; d3 e7 ; 0xf8f71
+ lea ax, [di+00130h] ; 8d 85 30 01 ; 0xf8f73
+ cwd ; 99 ; 0xf8f77
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf8f78
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8f7b
+ mov cx, dx ; 89 d1 ; 0xf8f80
+ mov dx, bx ; 89 da ; 0xf8f82
+ xchg cx, ax ; 91 ; 0xf8f84
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8f85
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8f89
+ out DX, eax ; 66 ef ; 0xf8f8b
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf8f8d
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf8f90
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf8f95
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf8f98
+ mov cx, ax ; 89 c1 ; 0xf8f9b
+ xchg cx, ax ; 91 ; 0xf8f9d
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8f9e
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8fa2
+ out DX, eax ; 66 ef ; 0xf8fa4
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf8fa6 ahci.c:700
+ mov bx, word [bp-026h] ; 8b 5e da ; 0xf8fa9
+ mov al, byte [es:bx+00231h] ; 26 8a 87 31 02 ; 0xf8fac
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf8fb1
+ cmp AL, strict byte 004h ; 3c 04 ; 0xf8fb4 ahci.c:705
+ jnc short 08f4fh ; 73 97 ; 0xf8fb6
+ lea ax, [di+00118h] ; 8d 85 18 01 ; 0xf8fb8 ahci.c:708
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf8fbc ahci.c:250
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8fbf
+ xor cx, cx ; 31 c9 ; 0xf8fc4 ahci.c:252
+ mov dx, bx ; 89 da ; 0xf8fc6
+ xchg cx, ax ; 91 ; 0xf8fc8
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8fc9
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8fcd
+ out DX, eax ; 66 ef ; 0xf8fcf
+ add bx, strict byte 00004h ; 83 c3 04 ; 0xf8fd1 ahci.c:253
+ mov dx, bx ; 89 da ; 0xf8fd4
+ in eax, DX ; 66 ed ; 0xf8fd6
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf8fd8
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf8fda
+ xchg dx, ax ; 92 ; 0xf8fde
+ or AL, strict byte 010h ; 0c 10 ; 0xf8fdf
+ mov cx, dx ; 89 d1 ; 0xf8fe1
+ mov dx, bx ; 89 da ; 0xf8fe3
+ xchg cx, ax ; 91 ; 0xf8fe5
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf8fe6
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf8fea
+ out DX, eax ; 66 ef ; 0xf8fec
+ lea ax, [di+00124h] ; 8d 85 24 01 ; 0xf8fee ahci.c:712
+ cwd ; 99 ; 0xf8ff2
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf8ff3
+ mov bx, word [es:si+00260h] ; 26 8b 9c 60 02 ; 0xf8ff6
+ mov cx, dx ; 89 d1 ; 0xf8ffb
+ mov dx, bx ; 89 da ; 0xf8ffd
+ xchg cx, ax ; 91 ; 0xf8fff
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9000
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9004
+ out DX, eax ; 66 ef ; 0xf9006
+ mov es, [bp-018h] ; 8e 46 e8 ; 0xf9008
+ mov dx, word [es:si+00260h] ; 26 8b 94 60 02 ; 0xf900b
+ add dx, strict byte 00004h ; 83 c2 04 ; 0xf9010
+ in eax, DX ; 66 ed ; 0xf9013
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9015
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf9017
+ xchg dx, ax ; 92 ; 0xf901b
+ mov si, ax ; 89 c6 ; 0xf901c
+ mov ax, dx ; 89 d0 ; 0xf901e
+ mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xf9020
+ add dl, 00ch ; 80 c2 0c ; 0xf9023
+ mov byte [bp-00ch], dl ; 88 56 f4 ; 0xf9026
+ test ax, ax ; 85 c0 ; 0xf9029 ahci.c:713
+ jne short 09085h ; 75 58 ; 0xf902b
+ cmp si, 00101h ; 81 fe 01 01 ; 0xf902d
+ jne short 09085h ; 75 52 ; 0xf9031
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf9033 ahci.c:723
+ mov bx, word [bp-026h] ; 8b 5e da ; 0xf9036
+ mov word [es:bx+006h], strict word 00000h ; 26 c7 47 06 00 00 ; 0xf9039
+ mov word [es:bx+004h], strict word 00000h ; 26 c7 47 04 00 00 ; 0xf903f
+ mov word [es:bx+002h], strict word 00000h ; 26 c7 47 02 00 00 ; 0xf9045
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf904b
+ lea dx, [bp-00234h] ; 8d 96 cc fd ; 0xf9050 ahci.c:724
+ mov word [es:bx+008h], dx ; 26 89 57 08 ; 0xf9054
+ mov [es:bx+00ah], ss ; 26 8c 57 0a ; 0xf9058
+ mov word [es:bx+00eh], strict word 00001h ; 26 c7 47 0e 01 00 ; 0xf905c ahci.c:725
+ mov word [es:bx+010h], 00200h ; 26 c7 47 10 00 02 ; 0xf9062 ahci.c:726
+ mov bx, 000ech ; bb ec 00 ; 0xf9068 ahci.c:727
+ mov ax, word [bp-026h] ; 8b 46 da ; 0xf906b
+ mov dx, es ; 8c c2 ; 0xf906e
+ call 08520h ; e8 ad f4 ; 0xf9070
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf9073 ahci.c:730
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf9076
+ test byte [bp-00234h], 080h ; f6 86 cc fd 80 ; 0xf9079 ahci.c:732
+ je short 09088h ; 74 08 ; 0xf907e
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf9080
+ jmp short 0908ah ; eb 05 ; 0xf9083
+ jmp near 09251h ; e9 c9 01 ; 0xf9085
+ xor ax, ax ; 31 c0 ; 0xf9088
+ mov cl, al ; 88 c1 ; 0xf908a
+ mov ax, word [bp-00232h] ; 8b 86 ce fd ; 0xf908c ahci.c:733
+ mov word [bp-01ah], ax ; 89 46 e6 ; 0xf9090
+ mov ax, word [bp-0022eh] ; 8b 86 d2 fd ; 0xf9093 ahci.c:734
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf9097
+ mov ax, word [bp-00228h] ; 8b 86 d8 fd ; 0xf909a ahci.c:735
+ mov word [bp-02eh], ax ; 89 46 d2 ; 0xf909e
+ mov si, word [bp-001bch] ; 8b b6 44 fe ; 0xf90a1 ahci.c:736
+ mov di, word [bp-001bah] ; 8b be 46 fe ; 0xf90a5
+ xor ax, ax ; 31 c0 ; 0xf90a9
+ mov word [bp-028h], ax ; 89 46 d8 ; 0xf90ab
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf90ae
+ cmp di, 00fffh ; 81 ff ff 0f ; 0xf90b1 ahci.c:738
+ jne short 090d2h ; 75 1b ; 0xf90b5
+ cmp si, strict byte 0ffffh ; 83 fe ff ; 0xf90b7
+ jne short 090d2h ; 75 16 ; 0xf90ba
+ mov ax, word [bp-00166h] ; 8b 86 9a fe ; 0xf90bc ahci.c:739
+ mov word [bp-012h], ax ; 89 46 ee ; 0xf90c0
+ mov ax, word [bp-00168h] ; 8b 86 98 fe ; 0xf90c3
+ mov word [bp-028h], ax ; 89 46 d8 ; 0xf90c7
+ mov di, word [bp-0016ah] ; 8b be 96 fe ; 0xf90ca
+ mov si, word [bp-0016ch] ; 8b b6 94 fe ; 0xf90ce
+ mov bl, byte [bp-00eh] ; 8a 5e f2 ; 0xf90d2 ahci.c:743
+ xor bh, bh ; 30 ff ; 0xf90d5
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf90d7
+ add bx, word [bp-026h] ; 03 5e da ; 0xf90da
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf90dd
+ mov byte [es:bx+0022dh], al ; 26 88 87 2d 02 ; 0xf90e0
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf90e5 ahci.c:744
+ xor ah, ah ; 30 e4 ; 0xf90e8
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf90ea
+ imul dx ; f7 ea ; 0xf90ed
+ mov bx, word [bp-026h] ; 8b 5e da ; 0xf90ef
+ add bx, ax ; 01 c3 ; 0xf90f2
+ mov word [es:bx+022h], 0ff05h ; 26 c7 47 22 05 ff ; 0xf90f4
+ mov byte [es:bx+024h], cl ; 26 88 4f 24 ; 0xf90fa ahci.c:746
+ mov byte [es:bx+025h], 000h ; 26 c6 47 25 00 ; 0xf90fe ahci.c:747
+ mov word [es:bx+028h], 00200h ; 26 c7 47 28 00 02 ; 0xf9103 ahci.c:748
+ mov byte [es:bx+027h], 001h ; 26 c6 47 27 01 ; 0xf9109 ahci.c:749
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf910e ahci.c:750
+ mov word [es:bx+03ch], ax ; 26 89 47 3c ; 0xf9111
+ mov ax, word [bp-028h] ; 8b 46 d8 ; 0xf9115
+ mov word [es:bx+03ah], ax ; 26 89 47 3a ; 0xf9118
+ mov word [es:bx+038h], di ; 26 89 7f 38 ; 0xf911c
+ mov word [es:bx+036h], si ; 26 89 77 36 ; 0xf9120
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf9124 ahci.c:752
+ mov word [es:bx+030h], ax ; 26 89 47 30 ; 0xf9127
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf912b ahci.c:753
+ mov word [es:bx+032h], ax ; 26 89 47 32 ; 0xf912e
+ mov ax, word [bp-02eh] ; 8b 46 d2 ; 0xf9132 ahci.c:754
+ mov word [es:bx+034h], ax ; 26 89 47 34 ; 0xf9135
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf9139 ahci.c:757
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf913c
+ jc short 0914ch ; 72 0c ; 0xf913e
+ jbe short 09154h ; 76 12 ; 0xf9140
+ cmp AL, strict byte 003h ; 3c 03 ; 0xf9142
+ je short 0915ch ; 74 16 ; 0xf9144
+ cmp AL, strict byte 002h ; 3c 02 ; 0xf9146
+ je short 09158h ; 74 0e ; 0xf9148
+ jmp short 091a6h ; eb 5a ; 0xf914a
+ test al, al ; 84 c0 ; 0xf914c
+ jne short 091a6h ; 75 56 ; 0xf914e
+ mov BL, strict byte 040h ; b3 40 ; 0xf9150 ahci.c:760
+ jmp short 0915eh ; eb 0a ; 0xf9152 ahci.c:761
+ mov BL, strict byte 048h ; b3 48 ; 0xf9154 ahci.c:763
+ jmp short 0915eh ; eb 06 ; 0xf9156 ahci.c:764
+ mov BL, strict byte 050h ; b3 50 ; 0xf9158 ahci.c:766
+ jmp short 0915eh ; eb 02 ; 0xf915a ahci.c:767
+ mov BL, strict byte 058h ; b3 58 ; 0xf915c ahci.c:769
+ mov dl, bl ; 88 da ; 0xf915e ahci.c:773
+ add dl, 007h ; 80 c2 07 ; 0xf9160
+ xor dh, dh ; 30 f6 ; 0xf9163
+ mov ax, dx ; 89 d0 ; 0xf9165
+ call 01652h ; e8 e8 84 ; 0xf9167
+ test al, al ; 84 c0 ; 0xf916a
+ je short 091a6h ; 74 38 ; 0xf916c
+ mov al, bl ; 88 d8 ; 0xf916e ahci.c:776
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf9170
+ xor ah, ah ; 30 e4 ; 0xf9172
+ call 01652h ; e8 db 84 ; 0xf9174
+ mov byte [bp-02bh], al ; 88 46 d5 ; 0xf9177
+ mov byte [bp-02ch], dh ; 88 76 d4 ; 0xf917a
+ mov al, bl ; 88 d8 ; 0xf917d
+ xor ah, ah ; 30 e4 ; 0xf917f
+ call 01652h ; e8 ce 84 ; 0xf9181
+ xor ah, ah ; 30 e4 ; 0xf9184
+ mov cx, word [bp-02ch] ; 8b 4e d4 ; 0xf9186
+ add cx, ax ; 01 c1 ; 0xf9189
+ mov word [bp-032h], cx ; 89 4e ce ; 0xf918b
+ mov al, bl ; 88 d8 ; 0xf918e ahci.c:777
+ add AL, strict byte 002h ; 04 02 ; 0xf9190
+ call 01652h ; e8 bd 84 ; 0xf9192
+ xor ah, ah ; 30 e4 ; 0xf9195
+ mov word [bp-034h], ax ; 89 46 cc ; 0xf9197
+ mov ax, dx ; 89 d0 ; 0xf919a ahci.c:778
+ call 01652h ; e8 b3 84 ; 0xf919c
+ xor ah, ah ; 30 e4 ; 0xf919f
+ mov word [bp-030h], ax ; 89 46 d0 ; 0xf91a1
+ jmp short 091b6h ; eb 10 ; 0xf91a4 ahci.c:780
+ push word [bp-012h] ; ff 76 ee ; 0xf91a6 ahci.c:781
+ push word [bp-028h] ; ff 76 d8 ; 0xf91a9
+ push di ; 57 ; 0xf91ac
+ push si ; 56 ; 0xf91ad
+ mov dx, ss ; 8c d2 ; 0xf91ae
+ lea ax, [bp-034h] ; 8d 46 cc ; 0xf91b0
+ call 059dch ; e8 26 c8 ; 0xf91b3
+ mov bx, 00da0h ; bb a0 0d ; 0xf91b6 ahci.c:785
+ mov cx, ds ; 8c d9 ; 0xf91b9
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf91bb
+ call 018cch ; e8 0b 87 ; 0xf91be
+ push word [bp-012h] ; ff 76 ee ; 0xf91c1
+ push word [bp-028h] ; ff 76 d8 ; 0xf91c4
+ push di ; 57 ; 0xf91c7
+ push si ; 56 ; 0xf91c8
+ mov ax, word [bp-030h] ; 8b 46 d0 ; 0xf91c9
+ push ax ; 50 ; 0xf91cc
+ mov ax, word [bp-034h] ; 8b 46 cc ; 0xf91cd
+ push ax ; 50 ; 0xf91d0
+ mov ax, word [bp-032h] ; 8b 46 ce ; 0xf91d1
+ push ax ; 50 ; 0xf91d4
+ push word [bp-02eh] ; ff 76 d2 ; 0xf91d5
+ push word [bp-014h] ; ff 76 ec ; 0xf91d8
+ push word [bp-01ah] ; ff 76 e6 ; 0xf91db
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf91de
+ xor ah, ah ; 30 e4 ; 0xf91e1
+ push ax ; 50 ; 0xf91e3
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf91e4
+ push ax ; 50 ; 0xf91e7
+ mov ax, 00cd6h ; b8 d6 0c ; 0xf91e8
+ push ax ; 50 ; 0xf91eb
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf91ec
+ push ax ; 50 ; 0xf91ef
+ call 0190fh ; e8 1c 87 ; 0xf91f0
+ add sp, strict byte 0001ch ; 83 c4 1c ; 0xf91f3
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf91f6 ahci.c:787
+ xor ah, ah ; 30 e4 ; 0xf91f9
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf91fb
+ imul dx ; f7 ea ; 0xf91fe
+ mov di, word [bp-026h] ; 8b 7e da ; 0xf9200
+ add di, ax ; 01 c7 ; 0xf9203
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf9205
+ lea di, [di+02ah] ; 8d 7d 2a ; 0xf9208
+ push DS ; 1e ; 0xf920b
+ push SS ; 16 ; 0xf920c
+ pop DS ; 1f ; 0xf920d
+ lea si, [bp-034h] ; 8d 76 cc ; 0xf920e
+ movsw ; a5 ; 0xf9211
+ movsw ; a5 ; 0xf9212
+ movsw ; a5 ; 0xf9213
+ pop DS ; 1f ; 0xf9214
+ mov bx, word [bp-026h] ; 8b 5e da ; 0xf9215 ahci.c:790
+ mov bl, byte [es:bx+001e2h] ; 26 8a 9f e2 01 ; 0xf9218
+ mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xf921d ahci.c:791
+ add dl, 00ch ; 80 c2 0c ; 0xf9220
+ mov al, bl ; 88 d8 ; 0xf9223
+ xor ah, ah ; 30 e4 ; 0xf9225
+ mov si, word [bp-026h] ; 8b 76 da ; 0xf9227
+ add si, ax ; 01 c6 ; 0xf922a
+ mov byte [es:si+001e3h], dl ; 26 88 94 e3 01 ; 0xf922c
+ db 0feh, 0c3h
+ ; inc bl ; fe c3 ; 0xf9231 ahci.c:792
+ mov si, word [bp-026h] ; 8b 76 da ; 0xf9233 ahci.c:793
+ mov byte [es:si+001e2h], bl ; 26 88 9c e2 01 ; 0xf9236
+ mov bx, strict word 00075h ; bb 75 00 ; 0xf923b ahci.c:38
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf923e
+ mov es, ax ; 8e c0 ; 0xf9241
+ mov bl, byte [es:bx] ; 26 8a 1f ; 0xf9243
+ db 0feh, 0c3h
+ ; inc bl ; fe c3 ; 0xf9246 ahci.c:797
+ mov si, strict word 00075h ; be 75 00 ; 0xf9248 ahci.c:43
+ mov byte [es:si], bl ; 26 88 1c ; 0xf924b
+ jmp near 0930ch ; e9 bb 00 ; 0xf924e ahci.c:800
+ cmp ax, 0eb14h ; 3d 14 eb ; 0xf9251
+ jne short 092aeh ; 75 58 ; 0xf9254
+ cmp si, 00101h ; 81 fe 01 01 ; 0xf9256
+ jne short 092aeh ; 75 52 ; 0xf925a
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf925c ahci.c:805
+ mov bx, word [bp-026h] ; 8b 5e da ; 0xf925f
+ mov word [es:bx+006h], strict word 00000h ; 26 c7 47 06 00 00 ; 0xf9262
+ mov word [es:bx+004h], strict word 00000h ; 26 c7 47 04 00 00 ; 0xf9268
+ mov word [es:bx+002h], strict word 00000h ; 26 c7 47 02 00 00 ; 0xf926e
+ mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xf9274
+ lea dx, [bp-00234h] ; 8d 96 cc fd ; 0xf9279 ahci.c:806
+ mov word [es:bx+008h], dx ; 26 89 57 08 ; 0xf927d
+ mov [es:bx+00ah], ss ; 26 8c 57 0a ; 0xf9281
+ mov word [es:bx+00eh], strict word 00001h ; 26 c7 47 0e 01 00 ; 0xf9285 ahci.c:807
+ mov word [es:bx+010h], 00200h ; 26 c7 47 10 00 02 ; 0xf928b ahci.c:808
+ mov bx, 000a1h ; bb a1 00 ; 0xf9291 ahci.c:809
+ mov ax, word [bp-026h] ; 8b 46 da ; 0xf9294
+ mov dx, es ; 8c c2 ; 0xf9297
+ call 08520h ; e8 84 f2 ; 0xf9299
+ mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xf929c ahci.c:812
+ mov byte [bp-00ah], al ; 88 46 f6 ; 0xf929f
+ test byte [bp-00234h], 080h ; f6 86 cc fd 80 ; 0xf92a2 ahci.c:814
+ je short 092b0h ; 74 07 ; 0xf92a7
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf92a9
+ jmp short 092b2h ; eb 04 ; 0xf92ac
+ jmp short 0930ch ; eb 5c ; 0xf92ae
+ xor cx, cx ; 31 c9 ; 0xf92b0
+ mov bl, byte [bp-00eh] ; 8a 5e f2 ; 0xf92b2 ahci.c:816
+ xor bh, bh ; 30 ff ; 0xf92b5
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf92b7
+ add bx, word [bp-026h] ; 03 5e da ; 0xf92ba
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf92bd
+ mov byte [es:bx+0022dh], al ; 26 88 87 2d 02 ; 0xf92c0
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf92c5 ahci.c:817
+ xor ah, ah ; 30 e4 ; 0xf92c8
+ mov dx, strict word 0001ch ; ba 1c 00 ; 0xf92ca
+ imul dx ; f7 ea ; 0xf92cd
+ mov bx, word [bp-026h] ; 8b 5e da ; 0xf92cf
+ add bx, ax ; 01 c3 ; 0xf92d2
+ mov word [es:bx+022h], 00505h ; 26 c7 47 22 05 05 ; 0xf92d4
+ mov byte [es:bx+024h], cl ; 26 88 4f 24 ; 0xf92da ahci.c:819
+ mov word [es:bx+028h], 00800h ; 26 c7 47 28 00 08 ; 0xf92de ahci.c:820
+ mov byte [es:bx+027h], 000h ; 26 c6 47 27 00 ; 0xf92e4 ahci.c:821
+ mov bx, word [bp-026h] ; 8b 5e da ; 0xf92e9 ahci.c:824
+ mov dl, byte [es:bx+001f3h] ; 26 8a 97 f3 01 ; 0xf92ec
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf92f1 ahci.c:825
+ add AL, strict byte 00ch ; 04 0c ; 0xf92f4
+ mov bl, dl ; 88 d3 ; 0xf92f6
+ xor bh, bh ; 30 ff ; 0xf92f8
+ add bx, word [bp-026h] ; 03 5e da ; 0xf92fa
+ mov byte [es:bx+001f4h], al ; 26 88 87 f4 01 ; 0xf92fd
+ db 0feh, 0c2h
+ ; inc dl ; fe c2 ; 0xf9302 ahci.c:826
+ mov bx, word [bp-026h] ; 8b 5e da ; 0xf9304 ahci.c:827
+ mov byte [es:bx+001f3h], dl ; 26 88 97 f3 01 ; 0xf9307
+ inc byte [bp-00eh] ; fe 46 f2 ; 0xf930c ahci.c:832
+ mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xf930f ahci.c:833
+ mov es, [bp-016h] ; 8e 46 ea ; 0xf9312
+ mov bx, word [bp-026h] ; 8b 5e da ; 0xf9315
+ mov byte [es:bx+00231h], al ; 26 88 87 31 02 ; 0xf9318
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf931d ahci.c:838
+ pop di ; 5f ; 0xf9320
+ pop si ; 5e ; 0xf9321
+ pop cx ; 59 ; 0xf9322
+ pop bp ; 5d ; 0xf9323
+ retn ; c3 ; 0xf9324
+ ; disGetNextSymbol 0xf9325 LB 0xc23 -> off=0x0 cb=000000000000003a uValue=00000000000f7d25 'ahci_mem_alloc'
+ahci_mem_alloc: ; 0xf9325 LB 0x3a
+ push bx ; 53 ; 0xf9325 ahci.c:843
+ push cx ; 51 ; 0xf9326
+ push dx ; 52 ; 0xf9327
+ push di ; 57 ; 0xf9328
+ push bp ; 55 ; 0xf9329
+ mov bp, sp ; 89 e5 ; 0xf932a
+ mov di, 00413h ; bf 13 04 ; 0xf932c ahci.c:48
+ xor ax, ax ; 31 c0 ; 0xf932f
+ mov es, ax ; 8e c0 ; 0xf9331
+ mov ax, word [es:di] ; 26 8b 05 ; 0xf9333
+ test ax, ax ; 85 c0 ; 0xf9336 ahci.c:852
+ je short 09359h ; 74 1f ; 0xf9338
+ dec ax ; 48 ; 0xf933a ahci.c:853
+ mov bx, ax ; 89 c3 ; 0xf933b
+ xor dx, dx ; 31 d2 ; 0xf933d ahci.c:856
+ mov cx, strict word 0000ah ; b9 0a 00 ; 0xf933f
+ sal ax, 1 ; d1 e0 ; 0xf9342
+ rcl dx, 1 ; d1 d2 ; 0xf9344
+ loop 09342h ; e2 fa ; 0xf9346
+ mov di, dx ; 89 d7 ; 0xf9348
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf934a
+ shr di, 1 ; d1 ef ; 0xf934d
+ rcr ax, 1 ; d1 d8 ; 0xf934f
+ loop 0934dh ; e2 fa ; 0xf9351
+ mov di, 00413h ; bf 13 04 ; 0xf9353 ahci.c:53
+ mov word [es:di], bx ; 26 89 1d ; 0xf9356
+ pop bp ; 5d ; 0xf9359 ahci.c:861
+ pop di ; 5f ; 0xf935a
+ pop dx ; 5a ; 0xf935b
+ pop cx ; 59 ; 0xf935c
+ pop bx ; 5b ; 0xf935d
+ retn ; c3 ; 0xf935e
+ ; disGetNextSymbol 0xf935f LB 0xbe9 -> off=0x0 cb=0000000000000157 uValue=00000000000f7d5f 'ahci_hba_init'
+ahci_hba_init: ; 0xf935f LB 0x157
+ push bp ; 55 ; 0xf935f ahci.c:866
+ mov bp, sp ; 89 e5 ; 0xf9360
+ push bx ; 53 ; 0xf9362
+ push cx ; 51 ; 0xf9363
+ push dx ; 52 ; 0xf9364
+ push si ; 56 ; 0xf9365
+ push di ; 57 ; 0xf9366
+ sub sp, strict byte 00006h ; 83 ec 06 ; 0xf9367
+ mov si, ax ; 89 c6 ; 0xf936a
+ mov bx, strict word 0000eh ; bb 0e 00 ; 0xf936c ahci.c:48
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf936f
+ mov es, ax ; 8e c0 ; 0xf9372
+ mov di, word [es:bx] ; 26 8b 3f ; 0xf9374
+ mov bx, 00122h ; bb 22 01 ; 0xf9377 ahci.c:877
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf937a ahci.c:879
+ xor cx, cx ; 31 c9 ; 0xf937d
+ mov dx, si ; 89 f2 ; 0xf937f
+ xchg cx, ax ; 91 ; 0xf9381
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9382
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9386
+ out DX, eax ; 66 ef ; 0xf9388
+ lea dx, [si+004h] ; 8d 54 04 ; 0xf938a
+ in eax, DX ; 66 ed ; 0xf938d
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf938f
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf9391
+ xchg dx, ax ; 92 ; 0xf9395
+ call 09325h ; e8 8c ff ; 0xf9396 ahci.c:885
+ mov word [bp-010h], ax ; 89 46 f0 ; 0xf9399
+ test ax, ax ; 85 c0 ; 0xf939c ahci.c:886
+ jne short 093a3h ; 75 03 ; 0xf939e
+ jmp near 094ach ; e9 09 01 ; 0xf93a0
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf93a3 ahci.c:889
+ mov es, di ; 8e c7 ; 0xf93a6
+ mov word [es:bx+00232h], ax ; 26 89 87 32 02 ; 0xf93a8
+ mov byte [es:bx+00231h], 000h ; 26 c6 87 31 02 00 ; 0xf93ad ahci.c:895
+ xor bx, bx ; 31 db ; 0xf93b3 ahci.c:897
+ mov es, ax ; 8e c0 ; 0xf93b5
+ mov byte [es:bx+00262h], 0ffh ; 26 c6 87 62 02 ff ; 0xf93b7 ahci.c:898
+ mov word [es:bx+00260h], si ; 26 89 b7 60 02 ; 0xf93bd ahci.c:899
+ mov word [es:bx+00264h], 0c000h ; 26 c7 87 64 02 00 c0 ; 0xf93c2 ahci.c:904
+ mov word [es:bx+00266h], strict word 0000ch ; 26 c7 87 66 02 0c 00 ; 0xf93c9
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf93d0 ahci.c:252
+ xor cx, cx ; 31 c9 ; 0xf93d3
+ mov dx, si ; 89 f2 ; 0xf93d5
+ xchg cx, ax ; 91 ; 0xf93d7
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf93d8
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf93dc
+ out DX, eax ; 66 ef ; 0xf93de
+ lea bx, [si+004h] ; 8d 5c 04 ; 0xf93e0 ahci.c:253
+ mov dx, bx ; 89 da ; 0xf93e3
+ in eax, DX ; 66 ed ; 0xf93e5
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf93e7
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf93e9
+ xchg dx, ax ; 92 ; 0xf93ed
+ or AL, strict byte 001h ; 0c 01 ; 0xf93ee
+ mov cx, dx ; 89 d1 ; 0xf93f0
+ mov dx, bx ; 89 da ; 0xf93f2
+ xchg cx, ax ; 91 ; 0xf93f4
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf93f5
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf93f9
+ out DX, eax ; 66 ef ; 0xf93fb
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf93fd ahci.c:910
+ xor cx, cx ; 31 c9 ; 0xf9400
+ mov dx, si ; 89 f2 ; 0xf9402
+ xchg cx, ax ; 91 ; 0xf9404
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9405
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9409
+ out DX, eax ; 66 ef ; 0xf940b
+ lea bx, [si+004h] ; 8d 5c 04 ; 0xf940d
+ mov dx, bx ; 89 da ; 0xf9410
+ in eax, DX ; 66 ed ; 0xf9412
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9414
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf9416
+ xchg dx, ax ; 92 ; 0xf941a
+ test AL, strict byte 001h ; a8 01 ; 0xf941b ahci.c:911
+ jne short 093fdh ; 75 de ; 0xf941d
+ xor ax, ax ; 31 c0 ; 0xf941f ahci.c:913
+ xor cx, cx ; 31 c9 ; 0xf9421
+ mov dx, si ; 89 f2 ; 0xf9423
+ xchg cx, ax ; 91 ; 0xf9425
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9426
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf942a
+ out DX, eax ; 66 ef ; 0xf942c
+ mov dx, bx ; 89 da ; 0xf942e
+ in eax, DX ; 66 ed ; 0xf9430
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9432
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf9434
+ xchg dx, ax ; 92 ; 0xf9438
+ xor bx, bx ; 31 db ; 0xf9439 ahci.c:914
+ push bx ; 53 ; 0xf943b
+ mov bx, strict word 0001fh ; bb 1f 00 ; 0xf943c
+ xor cx, cx ; 31 c9 ; 0xf943f
+ call 0838dh ; e8 49 ef ; 0xf9441
+ db 0feh, 0c0h
+ ; inc al ; fe c0 ; 0xf9444
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf9446
+ mov byte [bp-00ch], 000h ; c6 46 f4 00 ; 0xf9449 ahci.c:919
+ jmp short 09470h ; eb 21 ; 0xf944d ahci.c:920
+ xor al, al ; 30 c0 ; 0xf944f ahci.c:272
+ test al, al ; 84 c0 ; 0xf9451 ahci.c:273
+ je short 09467h ; 74 12 ; 0xf9453
+ mov bl, byte [bp-00ch] ; 8a 5e f4 ; 0xf9455 ahci.c:925
+ xor bh, bh ; 30 ff ; 0xf9458
+ xor ax, ax ; 31 c0 ; 0xf945a
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf945c
+ call 08e1ch ; e8 ba f9 ; 0xf945f
+ dec byte [bp-00eh] ; fe 4e f2 ; 0xf9462 ahci.c:926
+ je short 094aah ; 74 43 ; 0xf9465 ahci.c:927
+ inc byte [bp-00ch] ; fe 46 f4 ; 0xf9467 ahci.c:930
+ cmp byte [bp-00ch], 020h ; 80 7e f4 20 ; 0xf946a ahci.c:931
+ jnc short 094aah ; 73 3a ; 0xf946e
+ mov cl, byte [bp-00ch] ; 8a 4e f4 ; 0xf9470
+ xor ch, ch ; 30 ed ; 0xf9473
+ mov bx, strict word 00001h ; bb 01 00 ; 0xf9475
+ xor di, di ; 31 ff ; 0xf9478
+ jcxz 09482h ; e3 06 ; 0xf947a
+ sal bx, 1 ; d1 e3 ; 0xf947c
+ rcl di, 1 ; d1 d7 ; 0xf947e
+ loop 0947ch ; e2 fa ; 0xf9480
+ mov ax, strict word 0000ch ; b8 0c 00 ; 0xf9482
+ xor cx, cx ; 31 c9 ; 0xf9485
+ mov dx, si ; 89 f2 ; 0xf9487
+ xchg cx, ax ; 91 ; 0xf9489
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf948a
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf948e
+ out DX, eax ; 66 ef ; 0xf9490
+ lea dx, [si+004h] ; 8d 54 04 ; 0xf9492
+ in eax, DX ; 66 ed ; 0xf9495
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9497
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf9499
+ xchg dx, ax ; 92 ; 0xf949d
+ test dx, di ; 85 fa ; 0xf949e
+ jne short 094a6h ; 75 04 ; 0xf94a0
+ test ax, bx ; 85 d8 ; 0xf94a2
+ je short 0944fh ; 74 a9 ; 0xf94a4
+ mov AL, strict byte 001h ; b0 01 ; 0xf94a6
+ jmp short 09451h ; eb a7 ; 0xf94a8
+ xor ax, ax ; 31 c0 ; 0xf94aa ahci.c:933
+ lea sp, [bp-00ah] ; 8d 66 f6 ; 0xf94ac ahci.c:934
+ pop di ; 5f ; 0xf94af
+ pop si ; 5e ; 0xf94b0
+ pop dx ; 5a ; 0xf94b1
+ pop cx ; 59 ; 0xf94b2
+ pop bx ; 5b ; 0xf94b3
+ pop bp ; 5d ; 0xf94b4
+ retn ; c3 ; 0xf94b5
+ ; disGetNextSymbol 0xf94b6 LB 0xa92 -> off=0x17 cb=0000000000000139 uValue=00000000000f7ecd 'ahci_init'
+ db 00bh, 005h, 004h, 003h, 002h, 001h, 000h, 0b3h, 095h, 091h, 095h, 097h, 095h, 09dh, 095h, 0a3h
+ db 095h, 0a9h, 095h, 0afh, 095h, 0b3h, 095h
+ahci_init: ; 0xf94cd LB 0x139
+ push bp ; 55 ; 0xf94cd ahci.c:939
+ mov bp, sp ; 89 e5 ; 0xf94ce
+ push si ; 56 ; 0xf94d0
+ push di ; 57 ; 0xf94d1
+ sub sp, strict byte 00012h ; 83 ec 12 ; 0xf94d2
+ mov ax, 00601h ; b8 01 06 ; 0xf94d5 ahci.c:943
+ mov dx, strict word 00001h ; ba 01 00 ; 0xf94d8
+ call 09a08h ; e8 2a 05 ; 0xf94db
+ mov dx, ax ; 89 c2 ; 0xf94de
+ cmp ax, strict word 0ffffh ; 3d ff ff ; 0xf94e0 ahci.c:944
+ je short 0952eh ; 74 49 ; 0xf94e3
+ mov al, ah ; 88 e0 ; 0xf94e5 ahci.c:949
+ mov byte [bp-008h], ah ; 88 66 f8 ; 0xf94e7
+ mov byte [bp-00ah], dl ; 88 56 f6 ; 0xf94ea ahci.c:950
+ xor dh, ah ; 30 e6 ; 0xf94ed ahci.c:955
+ xor ah, ah ; 30 e4 ; 0xf94ef
+ mov bx, strict word 00034h ; bb 34 00 ; 0xf94f1
+ call 09a33h ; e8 3c 05 ; 0xf94f4
+ mov cl, al ; 88 c1 ; 0xf94f7
+ test cl, cl ; 84 c9 ; 0xf94f9 ahci.c:957
+ je short 09531h ; 74 34 ; 0xf94fb
+ mov bl, cl ; 88 cb ; 0xf94fd ahci.c:959
+ xor bh, bh ; 30 ff ; 0xf94ff
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf9501
+ mov byte [bp-00ch], al ; 88 46 f4 ; 0xf9504
+ mov byte [bp-00bh], bh ; 88 7e f5 ; 0xf9507
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf950a
+ mov byte [bp-012h], al ; 88 46 ee ; 0xf950d
+ mov byte [bp-011h], bh ; 88 7e ef ; 0xf9510
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf9513
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf9516
+ call 09a33h ; e8 17 05 ; 0xf9519
+ cmp AL, strict byte 012h ; 3c 12 ; 0xf951c ahci.c:963
+ je short 09531h ; 74 11 ; 0xf951e
+ mov bl, cl ; 88 cb ; 0xf9520 ahci.c:967
+ db 0feh, 0c3h
+ ; inc bl ; fe c3 ; 0xf9522
+ xor bh, bh ; 30 ff ; 0xf9524
+ mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xf9526
+ mov ax, word [bp-012h] ; 8b 46 ee ; 0xf9529
+ jmp short 094f4h ; eb c6 ; 0xf952c ahci.c:968
+ jmp near 095ffh ; e9 ce 00 ; 0xf952e
+ test cl, cl ; 84 c9 ; 0xf9531 ahci.c:970
+ je short 0952eh ; 74 f9 ; 0xf9533
+ add cl, 002h ; 80 c1 02 ; 0xf9535 ahci.c:977
+ mov bl, cl ; 88 cb ; 0xf9538 ahci.c:979
+ xor bh, bh ; 30 ff ; 0xf953a
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf953c
+ mov byte [bp-00eh], al ; 88 46 f2 ; 0xf953f
+ mov byte [bp-00dh], bh ; 88 7e f3 ; 0xf9542
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf9545
+ mov byte [bp-014h], al ; 88 46 ec ; 0xf9548
+ mov byte [bp-013h], bh ; 88 7e ed ; 0xf954b
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf954e
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf9551
+ call 09a33h ; e8 dc 04 ; 0xf9554
+ cmp AL, strict byte 010h ; 3c 10 ; 0xf9557 ahci.c:980
+ jne short 0952eh ; 75 d3 ; 0xf9559
+ mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xf955b ahci.c:983
+ mov bl, cl ; 88 cb ; 0xf955f ahci.c:985
+ add bl, 002h ; 80 c3 02 ; 0xf9561
+ xor bh, bh ; 30 ff ; 0xf9564
+ mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xf9566
+ mov ax, word [bp-014h] ; 8b 46 ec ; 0xf9569
+ call 09a5ah ; e8 eb 04 ; 0xf956c
+ mov dx, ax ; 89 c2 ; 0xf956f
+ and ax, strict word 0000fh ; 25 0f 00 ; 0xf9571 ahci.c:989
+ sub ax, strict word 00004h ; 2d 04 00 ; 0xf9574
+ cmp ax, strict word 0000bh ; 3d 0b 00 ; 0xf9577
+ jnbe short 095b3h ; 77 37 ; 0xf957a
+ push CS ; 0e ; 0xf957c
+ pop ES ; 07 ; 0xf957d
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf957e
+ mov di, 094b6h ; bf b6 94 ; 0xf9581
+ repne scasb ; f2 ae ; 0xf9584
+ sal cx, 1 ; d1 e1 ; 0xf9586
+ mov di, cx ; 89 cf ; 0xf9588
+ mov ax, word [cs:di-06b43h] ; 2e 8b 85 bd 94 ; 0xf958a
+ jmp ax ; ff e0 ; 0xf958f
+ mov byte [bp-006h], 010h ; c6 46 fa 10 ; 0xf9591 ahci.c:992
+ jmp short 095b3h ; eb 1c ; 0xf9595 ahci.c:993
+ mov byte [bp-006h], 014h ; c6 46 fa 14 ; 0xf9597 ahci.c:995
+ jmp short 095b3h ; eb 16 ; 0xf959b ahci.c:996
+ mov byte [bp-006h], 018h ; c6 46 fa 18 ; 0xf959d ahci.c:998
+ jmp short 095b3h ; eb 10 ; 0xf95a1 ahci.c:999
+ mov byte [bp-006h], 01ch ; c6 46 fa 1c ; 0xf95a3 ahci.c:1001
+ jmp short 095b3h ; eb 0a ; 0xf95a7 ahci.c:1002
+ mov byte [bp-006h], 020h ; c6 46 fa 20 ; 0xf95a9 ahci.c:1004
+ jmp short 095b3h ; eb 04 ; 0xf95ad ahci.c:1005
+ mov byte [bp-006h], 024h ; c6 46 fa 24 ; 0xf95af ahci.c:1007
+ mov CL, strict byte 004h ; b1 04 ; 0xf95b3 ahci.c:1016
+ mov si, dx ; 89 d6 ; 0xf95b5
+ shr si, CL ; d3 ee ; 0xf95b7
+ sal si, 1 ; d1 e6 ; 0xf95b9
+ sal si, 1 ; d1 e6 ; 0xf95bb
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf95bd ahci.c:1018
+ test al, al ; 84 c0 ; 0xf95c0
+ je short 095ffh ; 74 3b ; 0xf95c2
+ mov bl, al ; 88 c3 ; 0xf95c4 ahci.c:1020
+ xor bh, bh ; 30 ff ; 0xf95c6
+ mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xf95c8
+ mov byte [bp-010h], al ; 88 46 f0 ; 0xf95cb
+ mov byte [bp-00fh], bh ; 88 7e f1 ; 0xf95ce
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf95d1
+ mov byte [bp-016h], al ; 88 46 ea ; 0xf95d4
+ mov byte [bp-015h], bh ; 88 7e eb ; 0xf95d7
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf95da
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf95dd
+ call 09a7fh ; e8 9c 04 ; 0xf95e0
+ test AL, strict byte 001h ; a8 01 ; 0xf95e3 ahci.c:1024
+ je short 095ffh ; 74 18 ; 0xf95e5
+ and AL, strict byte 0f0h ; 24 f0 ; 0xf95e7 ahci.c:1027
+ add si, ax ; 01 c6 ; 0xf95e9
+ mov cx, strict word 00007h ; b9 07 00 ; 0xf95eb ahci.c:1030
+ mov bx, strict word 00004h ; bb 04 00 ; 0xf95ee
+ mov dx, word [bp-010h] ; 8b 56 f0 ; 0xf95f1
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf95f4
+ call 09abeh ; e8 c4 04 ; 0xf95f7
+ mov ax, si ; 89 f0 ; 0xf95fa ahci.c:1033
+ call 0935fh ; e8 60 fd ; 0xf95fc
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf95ff ahci.c:1047
+ pop di ; 5f ; 0xf9602
+ pop si ; 5e ; 0xf9603
+ pop bp ; 5d ; 0xf9604
+ retn ; c3 ; 0xf9605
+ ; disGetNextSymbol 0xf9606 LB 0x942 -> off=0x0 cb=000000000000001b uValue=00000000000f8006 'apm_out_str'
+apm_out_str: ; 0xf9606 LB 0x1b
+ push bp ; 55 ; 0xf9606 apm.c:146
+ mov bp, sp ; 89 e5 ; 0xf9607
+ push bx ; 53 ; 0xf9609
+ mov bx, ax ; 89 c3 ; 0xf960a
+ cmp byte [bx], 000h ; 80 3f 00 ; 0xf960c apm.c:148
+ je short 0961bh ; 74 0a ; 0xf960f
+ mov al, byte [bx] ; 8a 07 ; 0xf9611 apm.c:149
+ out DX, AL ; ee ; 0xf9613
+ inc bx ; 43 ; 0xf9614
+ mov al, byte [bx] ; 8a 07 ; 0xf9615
+ db 00ah, 0c0h
+ ; or al, al ; 0a c0 ; 0xf9617
+ jne short 09613h ; 75 f8 ; 0xf9619
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf961b apm.c:150
+ pop bx ; 5b ; 0xf961e
+ pop bp ; 5d ; 0xf961f
+ retn ; c3 ; 0xf9620
+ ; disGetNextSymbol 0xf9621 LB 0x927 -> off=0x1d cb=00000000000000da uValue=00000000000f803e 'apm_function'
+ db 00eh, 00bh, 007h, 006h, 005h, 004h, 002h, 001h, 000h, 0e4h, 096h, 06ch, 096h, 012h, 097h, 07eh
+ db 096h, 012h, 097h, 099h, 096h, 012h, 097h, 09eh, 096h, 0dfh, 096h, 0d8h, 096h
+apm_function: ; 0xf963e LB 0xda
+ push bp ; 55 ; 0xf963e apm.c:152
+ mov bp, sp ; 89 e5 ; 0xf963f
+ push di ; 57 ; 0xf9641
+ and byte [bp+018h], 0feh ; 80 66 18 fe ; 0xf9642 apm.c:156
+ mov dx, word [bp+012h] ; 8b 56 12 ; 0xf9646 apm.c:157
+ xor dh, dh ; 30 f6 ; 0xf9649
+ cmp dx, strict byte 0000eh ; 83 fa 0e ; 0xf964b
+ jnbe short 096bbh ; 77 6b ; 0xf964e
+ mov al, dl ; 88 d0 ; 0xf9650
+ push CS ; 0e ; 0xf9652
+ pop ES ; 07 ; 0xf9653
+ mov cx, strict word 0000ah ; b9 0a 00 ; 0xf9654
+ mov di, 09621h ; bf 21 96 ; 0xf9657
+ repne scasb ; f2 ae ; 0xf965a
+ sal cx, 1 ; d1 e1 ; 0xf965c
+ mov di, cx ; 89 cf ; 0xf965e
+ mov bx, word [cs:di-069d6h] ; 2e 8b 9d 2a 96 ; 0xf9660
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf9665
+ or AL, strict byte 001h ; 0c 01 ; 0xf9668
+ jmp bx ; ff e3 ; 0xf966a
+ mov word [bp+012h], 00102h ; c7 46 12 02 01 ; 0xf966c apm.c:159
+ mov word [bp+00ch], 0504dh ; c7 46 0c 4d 50 ; 0xf9671 apm.c:160
+ mov word [bp+010h], strict word 00003h ; c7 46 10 03 00 ; 0xf9676 apm.c:161
+ jmp near 09712h ; e9 94 00 ; 0xf967b apm.c:162
+ mov word [bp+012h], 0f000h ; c7 46 12 00 f0 ; 0xf967e apm.c:172
+ mov word [bp+00ch], 09cb4h ; c7 46 0c b4 9c ; 0xf9683 apm.c:173
+ mov word [bp+010h], 0f000h ; c7 46 10 00 f0 ; 0xf9688 apm.c:174
+ mov ax, strict word 0fff0h ; b8 f0 ff ; 0xf968d apm.c:175
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf9690
+ mov word [bp+004h], ax ; 89 46 04 ; 0xf9693 apm.c:176
+ jmp near 09712h ; e9 79 00 ; 0xf9696 apm.c:177
+ sti ; fb ; 0xf9699 apm.c:194
+ hlt ; f4 ; 0xf969a apm.c:195
+ jmp near 09712h ; e9 74 00 ; 0xf969b apm.c:196
+ cmp word [bp+010h], strict byte 00003h ; 83 7e 10 03 ; 0xf969e apm.c:200
+ je short 096c5h ; 74 21 ; 0xf96a2
+ cmp word [bp+010h], strict byte 00002h ; 83 7e 10 02 ; 0xf96a4
+ je short 096bdh ; 74 13 ; 0xf96a8
+ cmp word [bp+010h], strict byte 00001h ; 83 7e 10 01 ; 0xf96aa
+ jne short 096cdh ; 75 1d ; 0xf96ae
+ mov dx, 0040fh ; ba 0f 04 ; 0xf96b0 apm.c:202
+ mov ax, 00d10h ; b8 10 0d ; 0xf96b3
+ call 09606h ; e8 4d ff ; 0xf96b6
+ jmp short 09712h ; eb 57 ; 0xf96b9 apm.c:203
+ jmp short 096e4h ; eb 27 ; 0xf96bb
+ mov dx, 0040fh ; ba 0f 04 ; 0xf96bd apm.c:205
+ mov ax, 00d18h ; b8 18 0d ; 0xf96c0
+ jmp short 096b6h ; eb f1 ; 0xf96c3
+ mov dx, 0040fh ; ba 0f 04 ; 0xf96c5 apm.c:208
+ mov ax, 00d20h ; b8 20 0d ; 0xf96c8
+ jmp short 096b6h ; eb e9 ; 0xf96cb
+ or dh, 00ah ; 80 ce 0a ; 0xf96cd apm.c:211
+ mov word [bp+012h], dx ; 89 56 12 ; 0xf96d0
+ mov word [bp+018h], ax ; 89 46 18 ; 0xf96d3 apm.c:212
+ jmp short 09712h ; eb 3a ; 0xf96d6 apm.c:214
+ mov word [bp+012h], 00102h ; c7 46 12 02 01 ; 0xf96d8 apm.c:216
+ jmp short 09712h ; eb 33 ; 0xf96dd apm.c:217
+ or dh, 080h ; 80 ce 80 ; 0xf96df apm.c:224
+ jmp short 096d0h ; eb ec ; 0xf96e2
+ mov bx, 00da0h ; bb a0 0d ; 0xf96e4 apm.c:228
+ mov cx, ds ; 8c d9 ; 0xf96e7
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf96e9
+ call 018cch ; e8 dd 81 ; 0xf96ec
+ push word [bp+00ch] ; ff 76 0c ; 0xf96ef
+ push word [bp+012h] ; ff 76 12 ; 0xf96f2
+ mov ax, 00d29h ; b8 29 0d ; 0xf96f5
+ push ax ; 50 ; 0xf96f8
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf96f9
+ push ax ; 50 ; 0xf96fc
+ call 0190fh ; e8 0f 82 ; 0xf96fd
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf9700
+ mov ax, word [bp+012h] ; 8b 46 12 ; 0xf9703 apm.c:229
+ xor ah, ah ; 30 e4 ; 0xf9706
+ or ah, 00ch ; 80 cc 0c ; 0xf9708
+ mov word [bp+012h], ax ; 89 46 12 ; 0xf970b
+ or byte [bp+018h], 001h ; 80 4e 18 01 ; 0xf970e apm.c:230
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf9712 apm.c:232
+ pop di ; 5f ; 0xf9715
+ pop bp ; 5d ; 0xf9716
+ retn ; c3 ; 0xf9717
+ ; disGetNextSymbol 0xf9718 LB 0x830 -> off=0x0 cb=0000000000000024 uValue=00000000000f8118 'pci16_select_reg'
+pci16_select_reg: ; 0xf9718 LB 0x24
+ push bp ; 55 ; 0xf9718 pcibios.c:188
+ mov bp, sp ; 89 e5 ; 0xf9719
+ push bx ; 53 ; 0xf971b
+ and dl, 0fch ; 80 e2 fc ; 0xf971c pcibios.c:190
+ mov bx, dx ; 89 d3 ; 0xf971f
+ mov dx, 00cf8h ; ba f8 0c ; 0xf9721
+ movzx eax, ax ; 66 0f b7 c0 ; 0xf9724
+ sal eax, 008h ; 66 c1 e0 08 ; 0xf9728
+ or eax, strict dword 080000000h ; 66 0d 00 00 00 80 ; 0xf972c
+ db 08ah, 0c3h
+ ; mov al, bl ; 8a c3 ; 0xf9732
+ out DX, eax ; 66 ef ; 0xf9734
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf9736 pcibios.c:191
+ pop bx ; 5b ; 0xf9739
+ pop bp ; 5d ; 0xf973a
+ retn ; c3 ; 0xf973b
+ ; disGetNextSymbol 0xf973c LB 0x80c -> off=0x0 cb=00000000000000eb uValue=00000000000f813c 'pci16_find_device'
+pci16_find_device: ; 0xf973c LB 0xeb
+ push bp ; 55 ; 0xf973c pcibios.c:221
+ mov bp, sp ; 89 e5 ; 0xf973d
+ push si ; 56 ; 0xf973f
+ push di ; 57 ; 0xf9740
+ sub sp, strict byte 0000ch ; 83 ec 0c ; 0xf9741
+ push ax ; 50 ; 0xf9744
+ push dx ; 52 ; 0xf9745
+ mov si, bx ; 89 de ; 0xf9746
+ mov di, cx ; 89 cf ; 0xf9748
+ test cx, cx ; 85 c9 ; 0xf974a pcibios.c:231
+ xor bx, bx ; 31 db ; 0xf974c pcibios.c:238
+ mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xf974e pcibios.c:239
+ test bl, 007h ; f6 c3 07 ; 0xf9752 pcibios.c:249
+ jne short 09784h ; 75 2d ; 0xf9755
+ mov dx, strict word 0000eh ; ba 0e 00 ; 0xf9757 pcibios.c:250
+ mov ax, bx ; 89 d8 ; 0xf975a
+ call 09718h ; e8 b9 ff ; 0xf975c
+ mov dx, 00cfeh ; ba fe 0c ; 0xf975f pcibios.c:251
+ in AL, DX ; ec ; 0xf9762
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf9763
+ mov byte [bp-008h], al ; 88 46 f8 ; 0xf9765
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xf9768 pcibios.c:252
+ jne short 09772h ; 75 06 ; 0xf976a
+ add bx, strict byte 00008h ; 83 c3 08 ; 0xf976c pcibios.c:253
+ jmp near 09804h ; e9 92 00 ; 0xf976f pcibios.c:254
+ test byte [bp-008h], 080h ; f6 46 f8 80 ; 0xf9772 pcibios.c:256
+ je short 0977fh ; 74 07 ; 0xf9776
+ mov word [bp-00eh], strict word 00001h ; c7 46 f2 01 00 ; 0xf9778 pcibios.c:257
+ jmp short 09784h ; eb 05 ; 0xf977d pcibios.c:258
+ mov word [bp-00eh], strict word 00008h ; c7 46 f2 08 00 ; 0xf977f pcibios.c:259
+ mov al, byte [bp-008h] ; 8a 46 f8 ; 0xf9784 pcibios.c:270
+ and AL, strict byte 007h ; 24 07 ; 0xf9787
+ cmp AL, strict byte 001h ; 3c 01 ; 0xf9789
+ jne short 097abh ; 75 1e ; 0xf978b
+ mov al, bh ; 88 f8 ; 0xf978d
+ xor ah, ah ; 30 e4 ; 0xf978f
+ test ax, ax ; 85 c0 ; 0xf9791
+ jne short 097abh ; 75 16 ; 0xf9793
+ mov dx, strict word 0001ah ; ba 1a 00 ; 0xf9795 pcibios.c:272
+ mov ax, bx ; 89 d8 ; 0xf9798
+ call 09718h ; e8 7b ff ; 0xf979a
+ mov dx, 00cfeh ; ba fe 0c ; 0xf979d pcibios.c:273
+ in AL, DX ; ec ; 0xf97a0
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf97a1
+ cmp al, byte [bp-006h] ; 3a 46 fa ; 0xf97a3 pcibios.c:274
+ jbe short 097abh ; 76 03 ; 0xf97a6
+ mov byte [bp-006h], al ; 88 46 fa ; 0xf97a8 pcibios.c:275
+ test di, di ; 85 ff ; 0xf97ab pcibios.c:279
+ je short 097b4h ; 74 05 ; 0xf97ad
+ mov dx, strict word 00008h ; ba 08 00 ; 0xf97af
+ jmp short 097b6h ; eb 02 ; 0xf97b2
+ xor dx, dx ; 31 d2 ; 0xf97b4
+ mov ax, bx ; 89 d8 ; 0xf97b6
+ call 09718h ; e8 5d ff ; 0xf97b8
+ mov dx, 00cfch ; ba fc 0c ; 0xf97bb pcibios.c:280
+ in eax, DX ; 66 ed ; 0xf97be
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf97c0
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf97c2
+ xchg dx, ax ; 92 ; 0xf97c6
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf97c7
+ mov word [bp-010h], dx ; 89 56 f0 ; 0xf97ca
+ mov word [bp-00ch], strict word 00000h ; c7 46 f4 00 00 ; 0xf97cd pcibios.c:281
+ test di, di ; 85 ff ; 0xf97d2 pcibios.c:284
+ je short 097e5h ; 74 0f ; 0xf97d4
+ mov cx, strict word 00008h ; b9 08 00 ; 0xf97d6 pcibios.c:285
+ shr dx, 1 ; d1 ea ; 0xf97d9
+ rcr ax, 1 ; d1 d8 ; 0xf97db
+ loop 097d9h ; e2 fa ; 0xf97dd
+ mov word [bp-00ah], ax ; 89 46 f6 ; 0xf97df
+ mov word [bp-010h], dx ; 89 56 f0 ; 0xf97e2
+ mov ax, word [bp-010h] ; 8b 46 f0 ; 0xf97e5 pcibios.c:292
+ cmp ax, word [bp-014h] ; 3b 46 ec ; 0xf97e8
+ jne short 097f5h ; 75 08 ; 0xf97eb
+ mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xf97ed
+ cmp ax, word [bp-012h] ; 3b 46 ee ; 0xf97f0
+ je short 097fbh ; 74 06 ; 0xf97f3
+ cmp word [bp-00ch], strict byte 00000h ; 83 7e f4 00 ; 0xf97f5 pcibios.c:293
+ je short 09801h ; 74 06 ; 0xf97f9
+ dec si ; 4e ; 0xf97fb
+ cmp si, strict byte 0ffffh ; 83 fe ff ; 0xf97fc
+ je short 09814h ; 74 13 ; 0xf97ff
+ add bx, word [bp-00eh] ; 03 5e f2 ; 0xf9801 pcibios.c:301
+ mov al, bh ; 88 f8 ; 0xf9804 pcibios.c:302
+ xor ah, ah ; 30 e4 ; 0xf9806
+ mov dl, byte [bp-006h] ; 8a 56 fa ; 0xf9808
+ xor dh, dh ; 30 f6 ; 0xf980b
+ cmp ax, dx ; 39 d0 ; 0xf980d
+ jnbe short 09814h ; 77 03 ; 0xf980f
+ jmp near 09752h ; e9 3e ff ; 0xf9811
+ cmp si, strict byte 0ffffh ; 83 fe ff ; 0xf9814 pcibios.c:304
+ jne short 0981dh ; 75 04 ; 0xf9817 pcibios.c:308
+ mov ax, bx ; 89 d8 ; 0xf9819
+ jmp short 09820h ; eb 03 ; 0xf981b
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf981d
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9820 pcibios.c:309
+ pop di ; 5f ; 0xf9823
+ pop si ; 5e ; 0xf9824
+ pop bp ; 5d ; 0xf9825
+ retn ; c3 ; 0xf9826
+ ; disGetNextSymbol 0xf9827 LB 0x721 -> off=0xc cb=00000000000001d5 uValue=00000000000f8233 'pci16_function'
+ db 014h, 099h, 02dh, 099h, 03fh, 099h, 053h, 099h, 065h, 099h, 078h, 099h
+pci16_function: ; 0xf9833 LB 0x1d5
+ push bp ; 55 ; 0xf9833 pcibios.c:311
+ mov bp, sp ; 89 e5 ; 0xf9834
+ push si ; 56 ; 0xf9836
+ push di ; 57 ; 0xf9837
+ push ax ; 50 ; 0xf9838
+ push ax ; 50 ; 0xf9839
+ and word [bp+020h], 000ffh ; 81 66 20 ff 00 ; 0xf983a pcibios.c:318
+ and word [bp+02ch], strict byte 0fffeh ; 83 66 2c fe ; 0xf983f pcibios.c:319
+ mov bx, word [bp+020h] ; 8b 5e 20 ; 0xf9843 pcibios.c:321
+ xor bh, bh ; 30 ff ; 0xf9846
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf9848
+ xor ah, ah ; 30 e4 ; 0xf984b
+ cmp bx, strict byte 00003h ; 83 fb 03 ; 0xf984d
+ jc short 09865h ; 72 13 ; 0xf9850
+ jbe short 098b8h ; 76 64 ; 0xf9852
+ cmp bx, strict byte 0000eh ; 83 fb 0e ; 0xf9854
+ je short 098c0h ; 74 67 ; 0xf9857
+ cmp bx, strict byte 00008h ; 83 fb 08 ; 0xf9859
+ jc short 0986fh ; 72 11 ; 0xf985c
+ cmp bx, strict byte 0000dh ; 83 fb 0d ; 0xf985e
+ jbe short 098c3h ; 76 60 ; 0xf9861
+ jmp short 0986fh ; eb 0a ; 0xf9863
+ cmp bx, strict byte 00002h ; 83 fb 02 ; 0xf9865
+ je short 0988eh ; 74 24 ; 0xf9868
+ cmp bx, strict byte 00001h ; 83 fb 01 ; 0xf986a
+ je short 09872h ; 74 03 ; 0xf986d
+ jmp near 099d1h ; e9 5f 01 ; 0xf986f
+ mov word [bp+020h], strict word 00001h ; c7 46 20 01 00 ; 0xf9872 pcibios.c:323
+ mov word [bp+014h], 00210h ; c7 46 14 10 02 ; 0xf9877 pcibios.c:324
+ mov word [bp+01ch], strict word 00000h ; c7 46 1c 00 00 ; 0xf987c pcibios.c:326
+ mov word [bp+018h], 04350h ; c7 46 18 50 43 ; 0xf9881 pcibios.c:327
+ mov word [bp+01ah], 02049h ; c7 46 1a 49 20 ; 0xf9886
+ jmp near 09a01h ; e9 73 01 ; 0xf988b pcibios.c:328
+ cmp word [bp+018h], strict byte 0ffffh ; 83 7e 18 ff ; 0xf988e pcibios.c:333
+ jne short 0989ah ; 75 06 ; 0xf9892
+ or ah, 083h ; 80 cc 83 ; 0xf9894 pcibios.c:334
+ jmp near 099fah ; e9 60 01 ; 0xf9897 pcibios.c:335
+ mov bx, word [bp+008h] ; 8b 5e 08 ; 0xf989a pcibios.c:337
+ mov dx, word [bp+01ch] ; 8b 56 1c ; 0xf989d
+ mov ax, word [bp+018h] ; 8b 46 18 ; 0xf98a0
+ xor cx, cx ; 31 c9 ; 0xf98a3
+ call 0973ch ; e8 94 fe ; 0xf98a5
+ cmp ax, strict word 0ffffh ; 3d ff ff ; 0xf98a8 pcibios.c:338
+ jne short 098bah ; 75 0d ; 0xf98ab
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf98ad pcibios.c:339
+ xor ah, ah ; 30 e4 ; 0xf98b0
+ or ah, 086h ; 80 cc 86 ; 0xf98b2
+ jmp near 099fah ; e9 42 01 ; 0xf98b5
+ jmp short 098c5h ; eb 0b ; 0xf98b8
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf98ba pcibios.c:340
+ jmp near 09a01h ; e9 41 01 ; 0xf98bd pcibios.c:345
+ jmp near 0998ch ; e9 c9 00 ; 0xf98c0
+ jmp short 098eah ; eb 25 ; 0xf98c3
+ mov bx, word [bp+008h] ; 8b 5e 08 ; 0xf98c5 pcibios.c:347
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf98c8
+ mov dx, word [bp+01eh] ; 8b 56 1e ; 0xf98cb
+ mov cx, strict word 00001h ; b9 01 00 ; 0xf98ce
+ call 0973ch ; e8 68 fe ; 0xf98d1
+ cmp ax, strict word 0ffffh ; 3d ff ff ; 0xf98d4 pcibios.c:348
+ jne short 098e4h ; 75 0b ; 0xf98d7
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf98d9 pcibios.c:349
+ xor ah, ah ; 30 e4 ; 0xf98dc
+ or ah, 086h ; 80 cc 86 ; 0xf98de
+ jmp near 099fah ; e9 16 01 ; 0xf98e1 pcibios.c:350
+ mov word [bp+014h], ax ; 89 46 14 ; 0xf98e4 pcibios.c:352
+ jmp near 09a01h ; e9 17 01 ; 0xf98e7 pcibios.c:354
+ cmp word [bp+004h], 00100h ; 81 7e 04 00 01 ; 0xf98ea pcibios.c:361
+ jc short 098f7h ; 72 06 ; 0xf98ef
+ or ah, 087h ; 80 cc 87 ; 0xf98f1 pcibios.c:362
+ jmp near 099fah ; e9 03 01 ; 0xf98f4 pcibios.c:363
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf98f7 pcibios.c:365
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf98fa
+ call 09718h ; e8 18 fe ; 0xf98fd
+ mov bx, word [bp+020h] ; 8b 5e 20 ; 0xf9900 pcibios.c:366
+ xor bh, bh ; 30 ff ; 0xf9903
+ sub bx, strict byte 00008h ; 83 eb 08 ; 0xf9905
+ cmp bx, strict byte 00005h ; 83 fb 05 ; 0xf9908
+ jnbe short 09975h ; 77 68 ; 0xf990b
+ sal bx, 1 ; d1 e3 ; 0xf990d
+ jmp word [cs:bx-067d9h] ; 2e ff a7 27 98 ; 0xf990f
+ mov bx, word [bp+01ch] ; 8b 5e 1c ; 0xf9914 pcibios.c:368
+ xor bl, bl ; 30 db ; 0xf9917
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf9919
+ and dx, strict byte 00003h ; 83 e2 03 ; 0xf991c
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xf991f
+ in AL, DX ; ec ; 0xf9923
+ db 02ah, 0e4h
+ ; sub ah, ah ; 2a e4 ; 0xf9924
+ or bx, ax ; 09 c3 ; 0xf9926
+ mov word [bp+01ch], bx ; 89 5e 1c ; 0xf9928
+ jmp short 09975h ; eb 48 ; 0xf992b pcibios.c:369
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf992d pcibios.c:371
+ xor dh, dh ; 30 f6 ; 0xf9930
+ and dl, 002h ; 80 e2 02 ; 0xf9932
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xf9935
+ in ax, DX ; ed ; 0xf9939
+ mov word [bp+01ch], ax ; 89 46 1c ; 0xf993a
+ jmp short 09975h ; eb 36 ; 0xf993d pcibios.c:372
+ mov dx, 00cfch ; ba fc 0c ; 0xf993f pcibios.c:374
+ in eax, DX ; 66 ed ; 0xf9942
+ db 08bh, 0d0h
+ ; mov dx, ax ; 8b d0 ; 0xf9944
+ shr eax, 010h ; 66 c1 e8 10 ; 0xf9946
+ xchg dx, ax ; 92 ; 0xf994a
+ mov word [bp+01ch], ax ; 89 46 1c ; 0xf994b
+ mov word [bp+01eh], dx ; 89 56 1e ; 0xf994e
+ jmp short 09975h ; eb 22 ; 0xf9951 pcibios.c:375
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf9953 pcibios.c:377
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf9956
+ xor dh, dh ; 30 f6 ; 0xf9959
+ and dl, 003h ; 80 e2 03 ; 0xf995b
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xf995e
+ out DX, AL ; ee ; 0xf9962
+ jmp short 09975h ; eb 10 ; 0xf9963 pcibios.c:378
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf9965 pcibios.c:380
+ mov dx, word [bp+004h] ; 8b 56 04 ; 0xf9968
+ xor dh, dh ; 30 f6 ; 0xf996b
+ and dl, 002h ; 80 e2 02 ; 0xf996d
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xf9970
+ out DX, ax ; ef ; 0xf9974
+ jmp near 09a01h ; e9 89 00 ; 0xf9975 pcibios.c:381
+ mov ax, word [bp+01ch] ; 8b 46 1c ; 0xf9978 pcibios.c:383
+ mov cx, word [bp+01eh] ; 8b 4e 1e ; 0xf997b
+ mov dx, 00cfch ; ba fc 0c ; 0xf997e
+ xchg cx, ax ; 91 ; 0xf9981
+ sal eax, 010h ; 66 c1 e0 10 ; 0xf9982
+ db 08bh, 0c1h
+ ; mov ax, cx ; 8b c1 ; 0xf9986
+ out DX, eax ; 66 ef ; 0xf9988
+ jmp short 09a01h ; eb 75 ; 0xf998a pcibios.c:387
+ mov bx, word [bp+004h] ; 8b 5e 04 ; 0xf998c pcibios.c:389
+ mov es, [bp+026h] ; 8e 46 26 ; 0xf998f
+ mov word [bp-008h], bx ; 89 5e f8 ; 0xf9992
+ mov [bp-006h], es ; 8c 46 fa ; 0xf9995
+ mov cx, word [0f380h] ; 8b 0e 80 f3 ; 0xf9998 pcibios.c:393
+ cmp cx, word [es:bx] ; 26 3b 0f ; 0xf999c
+ jbe short 099b2h ; 76 11 ; 0xf999f
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf99a1 pcibios.c:394
+ xor ah, ah ; 30 e4 ; 0xf99a4
+ or ah, 089h ; 80 cc 89 ; 0xf99a6
+ mov word [bp+020h], ax ; 89 46 20 ; 0xf99a9
+ or word [bp+02ch], strict byte 00001h ; 83 4e 2c 01 ; 0xf99ac pcibios.c:395
+ jmp short 099c6h ; eb 14 ; 0xf99b0 pcibios.c:396
+ les di, [es:bx+002h] ; 26 c4 7f 02 ; 0xf99b2 pcibios.c:397
+ mov si, 0f1a0h ; be a0 f1 ; 0xf99b6
+ mov dx, ds ; 8c da ; 0xf99b9
+ push DS ; 1e ; 0xf99bb
+ mov ds, dx ; 8e da ; 0xf99bc
+ rep movsb ; f3 a4 ; 0xf99be
+ pop DS ; 1f ; 0xf99c0
+ mov word [bp+014h], 00a00h ; c7 46 14 00 0a ; 0xf99c1 pcibios.c:399
+ mov ax, word [0f380h] ; a1 80 f3 ; 0xf99c6 pcibios.c:401
+ les bx, [bp-008h] ; c4 5e f8 ; 0xf99c9
+ mov word [es:bx], ax ; 26 89 07 ; 0xf99cc
+ jmp short 09a01h ; eb 30 ; 0xf99cf pcibios.c:402
+ mov bx, 00da0h ; bb a0 0d ; 0xf99d1 pcibios.c:404
+ mov cx, ds ; 8c d9 ; 0xf99d4
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf99d6
+ call 018cch ; e8 f0 7e ; 0xf99d9
+ mov ax, word [bp+014h] ; 8b 46 14 ; 0xf99dc
+ push ax ; 50 ; 0xf99df
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf99e0
+ push ax ; 50 ; 0xf99e3
+ mov ax, 00d5ch ; b8 5c 0d ; 0xf99e4
+ push ax ; 50 ; 0xf99e7
+ mov ax, strict word 00004h ; b8 04 00 ; 0xf99e8
+ push ax ; 50 ; 0xf99eb
+ call 0190fh ; e8 20 7f ; 0xf99ec
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xf99ef
+ mov ax, word [bp+020h] ; 8b 46 20 ; 0xf99f2 pcibios.c:405
+ xor ah, ah ; 30 e4 ; 0xf99f5
+ or ah, 081h ; 80 cc 81 ; 0xf99f7
+ mov word [bp+020h], ax ; 89 46 20 ; 0xf99fa
+ or word [bp+02ch], strict byte 00001h ; 83 4e 2c 01 ; 0xf99fd pcibios.c:406
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9a01 pcibios.c:408
+ pop di ; 5f ; 0xf9a04
+ pop si ; 5e ; 0xf9a05
+ pop bp ; 5d ; 0xf9a06
+ retn ; c3 ; 0xf9a07
+ ; disGetNextSymbol 0xf9a08 LB 0x540 -> off=0x0 cb=0000000000000008 uValue=00000000000f8408 'pci_find_classcode'
+pci_find_classcode: ; 0xf9a08 LB 0x8
+ push bp ; 55 ; 0xf9a08 pciutil.c:126
+ mov bp, sp ; 89 e5 ; 0xf9a09
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf9a0b pciutil.c:133
+ pop bp ; 5d ; 0xf9a0e
+ retn ; c3 ; 0xf9a0f
+ ; disGetNextSymbol 0xf9a10 LB 0x538 -> off=0x0 cb=0000000000000023 uValue=00000000000f8410 'pci_find_device'
+pci_find_device: ; 0xf9a10 LB 0x23
+ push bp ; 55 ; 0xf9a10 pciutil.c:146
+ mov bp, sp ; 89 e5 ; 0xf9a11
+ push bx ; 53 ; 0xf9a13
+ push cx ; 51 ; 0xf9a14
+ push si ; 56 ; 0xf9a15
+ mov cx, dx ; 89 d1 ; 0xf9a16
+ xor si, si ; 31 f6 ; 0xf9a18 pciutil.c:148
+ mov dx, ax ; 89 c2 ; 0xf9a1a
+ mov ax, 0b102h ; b8 02 b1 ; 0xf9a1c
+ int 01ah ; cd 1a ; 0xf9a1f
+ cmp ah, 000h ; 80 fc 00 ; 0xf9a21
+ je short 09a29h ; 74 03 ; 0xf9a24
+ mov bx, strict word 0ffffh ; bb ff ff ; 0xf9a26
+ mov ax, bx ; 89 d8 ; 0xf9a29
+ lea sp, [bp-006h] ; 8d 66 fa ; 0xf9a2b pciutil.c:149
+ pop si ; 5e ; 0xf9a2e
+ pop cx ; 59 ; 0xf9a2f
+ pop bx ; 5b ; 0xf9a30
+ pop bp ; 5d ; 0xf9a31
+ retn ; c3 ; 0xf9a32
+ ; disGetNextSymbol 0xf9a33 LB 0x515 -> off=0x0 cb=0000000000000027 uValue=00000000000f8433 'pci_read_config_byte'
+pci_read_config_byte: ; 0xf9a33 LB 0x27
+ push bp ; 55 ; 0xf9a33 pciutil.c:151
+ mov bp, sp ; 89 e5 ; 0xf9a34
+ push cx ; 51 ; 0xf9a36
+ push di ; 57 ; 0xf9a37
+ mov dh, al ; 88 c6 ; 0xf9a38
+ mov bh, dl ; 88 d7 ; 0xf9a3a
+ mov al, bl ; 88 d8 ; 0xf9a3c
+ xor ah, ah ; 30 e4 ; 0xf9a3e pciutil.c:153
+ xor dl, dl ; 30 d2 ; 0xf9a40
+ mov bl, bh ; 88 fb ; 0xf9a42
+ mov bh, dh ; 88 f7 ; 0xf9a44
+ mov di, ax ; 89 c7 ; 0xf9a46
+ mov ax, 0b108h ; b8 08 b1 ; 0xf9a48
+ int 01ah ; cd 1a ; 0xf9a4b
+ mov al, cl ; 88 c8 ; 0xf9a4d
+ xor ah, ah ; 30 e4 ; 0xf9a4f
+ xor dh, dh ; 30 f6 ; 0xf9a51 pciutil.c:154
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9a53
+ pop di ; 5f ; 0xf9a56
+ pop cx ; 59 ; 0xf9a57
+ pop bp ; 5d ; 0xf9a58
+ retn ; c3 ; 0xf9a59
+ ; disGetNextSymbol 0xf9a5a LB 0x4ee -> off=0x0 cb=0000000000000025 uValue=00000000000f845a 'pci_read_config_word'
+pci_read_config_word: ; 0xf9a5a LB 0x25
+ push bp ; 55 ; 0xf9a5a pciutil.c:156
+ mov bp, sp ; 89 e5 ; 0xf9a5b
+ push cx ; 51 ; 0xf9a5d
+ push di ; 57 ; 0xf9a5e
+ mov dh, al ; 88 c6 ; 0xf9a5f
+ mov cl, dl ; 88 d1 ; 0xf9a61
+ mov al, bl ; 88 d8 ; 0xf9a63
+ xor ah, ah ; 30 e4 ; 0xf9a65 pciutil.c:158
+ mov bh, dh ; 88 f7 ; 0xf9a67
+ xor dh, dh ; 30 f6 ; 0xf9a69
+ mov bl, dl ; 88 d3 ; 0xf9a6b
+ mov di, ax ; 89 c7 ; 0xf9a6d
+ mov ax, 0b109h ; b8 09 b1 ; 0xf9a6f
+ int 01ah ; cd 1a ; 0xf9a72
+ mov ax, cx ; 89 c8 ; 0xf9a74
+ xor dl, dl ; 30 d2 ; 0xf9a76 pciutil.c:159
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9a78
+ pop di ; 5f ; 0xf9a7b
+ pop cx ; 59 ; 0xf9a7c
+ pop bp ; 5d ; 0xf9a7d
+ retn ; c3 ; 0xf9a7e
+ ; disGetNextSymbol 0xf9a7f LB 0x4c9 -> off=0x0 cb=000000000000003f uValue=00000000000f847f 'pci_read_config_dword'
+pci_read_config_dword: ; 0xf9a7f LB 0x3f
+ push bp ; 55 ; 0xf9a7f pciutil.c:161
+ mov bp, sp ; 89 e5 ; 0xf9a80
+ push cx ; 51 ; 0xf9a82
+ push di ; 57 ; 0xf9a83
+ push ax ; 50 ; 0xf9a84
+ mov dh, al ; 88 c6 ; 0xf9a85
+ mov byte [bp-006h], bl ; 88 5e fa ; 0xf9a87
+ mov al, bl ; 88 d8 ; 0xf9a8a pciutil.c:166
+ xor ah, ah ; 30 e4 ; 0xf9a8c
+ mov di, ax ; 89 c7 ; 0xf9a8e
+ mov bx, dx ; 89 d3 ; 0xf9a90
+ mov ax, 0b109h ; b8 09 b1 ; 0xf9a92
+ int 01ah ; cd 1a ; 0xf9a95
+ test cx, cx ; 85 c9 ; 0xf9a97
+ jne short 09aafh ; 75 14 ; 0xf9a99
+ mov al, byte [bp-006h] ; 8a 46 fa ; 0xf9a9b
+ xor ah, ah ; 30 e4 ; 0xf9a9e
+ mov di, ax ; 89 c7 ; 0xf9aa0
+ inc di ; 47 ; 0xf9aa2
+ inc di ; 47 ; 0xf9aa3
+ mov bx, dx ; 89 d3 ; 0xf9aa4
+ mov ax, 0b109h ; b8 09 b1 ; 0xf9aa6
+ int 01ah ; cd 1a ; 0xf9aa9
+ test cx, cx ; 85 c9 ; 0xf9aab
+ je short 09ab4h ; 74 05 ; 0xf9aad
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf9aaf
+ jmp short 09ab6h ; eb 02 ; 0xf9ab2
+ xor ax, ax ; 31 c0 ; 0xf9ab4
+ cwd ; 99 ; 0xf9ab6
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9ab7 pciutil.c:169
+ pop di ; 5f ; 0xf9aba
+ pop cx ; 59 ; 0xf9abb
+ pop bp ; 5d ; 0xf9abc
+ retn ; c3 ; 0xf9abd
+ ; disGetNextSymbol 0xf9abe LB 0x48a -> off=0x0 cb=000000000000001e uValue=00000000000f84be 'pci_write_config_word'
+pci_write_config_word: ; 0xf9abe LB 0x1e
+ push bp ; 55 ; 0xf9abe pciutil.c:171
+ mov bp, sp ; 89 e5 ; 0xf9abf
+ push di ; 57 ; 0xf9ac1
+ push ax ; 50 ; 0xf9ac2
+ mov byte [bp-004h], al ; 88 46 fc ; 0xf9ac3
+ mov al, bl ; 88 d8 ; 0xf9ac6
+ xor ah, ah ; 30 e4 ; 0xf9ac8 pciutil.c:173
+ mov di, ax ; 89 c7 ; 0xf9aca
+ mov bh, byte [bp-004h] ; 8a 7e fc ; 0xf9acc
+ mov bl, dl ; 88 d3 ; 0xf9acf
+ mov ax, 0b10ch ; b8 0c b1 ; 0xf9ad1
+ int 01ah ; cd 1a ; 0xf9ad4
+ lea sp, [bp-002h] ; 8d 66 fe ; 0xf9ad6 pciutil.c:174
+ pop di ; 5f ; 0xf9ad9
+ pop bp ; 5d ; 0xf9ada
+ retn ; c3 ; 0xf9adb
+ ; disGetNextSymbol 0xf9adc LB 0x46c -> off=0x0 cb=000000000000001d uValue=00000000000f84dc 'vds_is_present'
+vds_is_present: ; 0xf9adc LB 0x1d
+ push bx ; 53 ; 0xf9adc vds.c:32
+ push bp ; 55 ; 0xf9add
+ mov bp, sp ; 89 e5 ; 0xf9ade
+ mov bx, strict word 0007bh ; bb 7b 00 ; 0xf9ae0 vds.c:36
+ mov ax, strict word 00040h ; b8 40 00 ; 0xf9ae3
+ mov es, ax ; 8e c0 ; 0xf9ae6
+ test byte [es:bx], 020h ; 26 f6 07 20 ; 0xf9ae8 vds.c:37
+ je short 09af4h ; 74 06 ; 0xf9aec
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf9aee
+ pop bp ; 5d ; 0xf9af1
+ pop bx ; 5b ; 0xf9af2
+ retn ; c3 ; 0xf9af3
+ xor ax, ax ; 31 c0 ; 0xf9af4
+ pop bp ; 5d ; 0xf9af6 vds.c:38
+ pop bx ; 5b ; 0xf9af7
+ retn ; c3 ; 0xf9af8
+ ; disGetNextSymbol 0xf9af9 LB 0x44f -> off=0x0 cb=000000000000001e uValue=00000000000f84f9 'vds_real_to_lin'
+vds_real_to_lin: ; 0xf9af9 LB 0x1e
+ push bx ; 53 ; 0xf9af9 vds.c:67
+ push cx ; 51 ; 0xf9afa
+ push bp ; 55 ; 0xf9afb
+ mov bp, sp ; 89 e5 ; 0xf9afc
+ mov bx, ax ; 89 c3 ; 0xf9afe
+ mov ax, dx ; 89 d0 ; 0xf9b00
+ xor dx, dx ; 31 d2 ; 0xf9b02 vds.c:69
+ mov cx, strict word 00004h ; b9 04 00 ; 0xf9b04
+ sal ax, 1 ; d1 e0 ; 0xf9b07
+ rcl dx, 1 ; d1 d2 ; 0xf9b09
+ loop 09b07h ; e2 fa ; 0xf9b0b
+ xor cx, cx ; 31 c9 ; 0xf9b0d
+ add ax, bx ; 01 d8 ; 0xf9b0f
+ adc dx, cx ; 11 ca ; 0xf9b11
+ pop bp ; 5d ; 0xf9b13 vds.c:70
+ pop cx ; 59 ; 0xf9b14
+ pop bx ; 5b ; 0xf9b15
+ retn ; c3 ; 0xf9b16
+ ; disGetNextSymbol 0xf9b17 LB 0x431 -> off=0x0 cb=0000000000000077 uValue=00000000000f8517 'vds_build_sg_list'
+vds_build_sg_list: ; 0xf9b17 LB 0x77
+ push bp ; 55 ; 0xf9b17 vds.c:77
+ mov bp, sp ; 89 e5 ; 0xf9b18
+ push si ; 56 ; 0xf9b1a
+ push di ; 57 ; 0xf9b1b
+ mov di, ax ; 89 c7 ; 0xf9b1c
+ mov si, dx ; 89 d6 ; 0xf9b1e
+ mov ax, bx ; 89 d8 ; 0xf9b20
+ mov dx, cx ; 89 ca ; 0xf9b22
+ mov bx, word [bp+004h] ; 8b 5e 04 ; 0xf9b24 vds.c:82
+ mov es, si ; 8e c6 ; 0xf9b27
+ mov word [es:di], bx ; 26 89 1d ; 0xf9b29
+ mov bx, word [bp+006h] ; 8b 5e 06 ; 0xf9b2c
+ mov word [es:di+002h], bx ; 26 89 5d 02 ; 0xf9b2f
+ call 09af9h ; e8 c3 ff ; 0xf9b33 vds.c:83
+ mov es, si ; 8e c6 ; 0xf9b36
+ mov word [es:di+004h], ax ; 26 89 45 04 ; 0xf9b38
+ mov word [es:di+006h], dx ; 26 89 55 06 ; 0xf9b3c
+ mov word [es:di+008h], strict word 00000h ; 26 c7 45 08 00 00 ; 0xf9b40 vds.c:84
+ call 09adch ; e8 93 ff ; 0xf9b46 vds.c:85
+ test ax, ax ; 85 c0 ; 0xf9b49
+ je short 09b5eh ; 74 11 ; 0xf9b4b
+ mov es, si ; 8e c6 ; 0xf9b4d vds.c:87
+ mov ax, 08105h ; b8 05 81 ; 0xf9b4f
+ mov dx, strict word 00000h ; ba 00 00 ; 0xf9b52
+ int 04bh ; cd 4b ; 0xf9b55
+ jc short 09b5bh ; 72 02 ; 0xf9b57
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xf9b59
+ cbw ; 98 ; 0xf9b5b
+ jmp short 09b85h ; eb 27 ; 0xf9b5c vds.c:88
+ mov es, si ; 8e c6 ; 0xf9b5e vds.c:90
+ mov word [es:di+00eh], strict word 00001h ; 26 c7 45 0e 01 00 ; 0xf9b60
+ mov dx, word [es:di+004h] ; 26 8b 55 04 ; 0xf9b66 vds.c:91
+ mov ax, word [es:di+006h] ; 26 8b 45 06 ; 0xf9b6a
+ mov word [es:di+010h], dx ; 26 89 55 10 ; 0xf9b6e
+ mov word [es:di+012h], ax ; 26 89 45 12 ; 0xf9b72
+ mov ax, word [bp+004h] ; 8b 46 04 ; 0xf9b76 vds.c:92
+ mov word [es:di+014h], ax ; 26 89 45 14 ; 0xf9b79
+ mov ax, bx ; 89 d8 ; 0xf9b7d
+ mov word [es:di+016h], bx ; 26 89 5d 16 ; 0xf9b7f
+ xor ax, bx ; 31 d8 ; 0xf9b83 vds.c:93
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9b85 vds.c:96
+ pop di ; 5f ; 0xf9b88
+ pop si ; 5e ; 0xf9b89
+ pop bp ; 5d ; 0xf9b8a
+ retn 00004h ; c2 04 00 ; 0xf9b8b
+ ; disGetNextSymbol 0xf9b8e LB 0x3ba -> off=0x0 cb=000000000000002e uValue=00000000000f858e 'vds_free_sg_list'
+vds_free_sg_list: ; 0xf9b8e LB 0x2e
+ push bp ; 55 ; 0xf9b8e vds.c:102
+ mov bp, sp ; 89 e5 ; 0xf9b8f
+ push bx ; 53 ; 0xf9b91
+ push di ; 57 ; 0xf9b92
+ mov bx, ax ; 89 c3 ; 0xf9b93
+ call 09adch ; e8 44 ff ; 0xf9b95 vds.c:106
+ test ax, ax ; 85 c0 ; 0xf9b98
+ je short 09badh ; 74 11 ; 0xf9b9a
+ mov di, bx ; 89 df ; 0xf9b9c vds.c:108
+ mov es, dx ; 8e c2 ; 0xf9b9e
+ mov ax, 08106h ; b8 06 81 ; 0xf9ba0
+ mov dx, strict word 00000h ; ba 00 00 ; 0xf9ba3
+ int 04bh ; cd 4b ; 0xf9ba6
+ jc short 09bach ; 72 02 ; 0xf9ba8
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xf9baa
+ cbw ; 98 ; 0xf9bac
+ mov es, dx ; 8e c2 ; 0xf9bad vds.c:116
+ mov word [es:bx+00eh], strict word 00000h ; 26 c7 47 0e 00 00 ; 0xf9baf
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9bb5 vds.c:118
+ pop di ; 5f ; 0xf9bb8
+ pop bx ; 5b ; 0xf9bb9
+ pop bp ; 5d ; 0xf9bba
+ retn ; c3 ; 0xf9bbb
+ ; disGetNextSymbol 0xf9bbc LB 0x38c -> off=0x4 cb=0000000000000020 uValue=00000000000f85c0 '__U4M'
+ db 000h, 000h, 000h, 000h
+__U4M: ; 0xf9bc0 LB 0x20
+ pushfw ; 9c ; 0xf9bc0 __U4M.asm:37
+ push si ; 56 ; 0xf9bc1 __U4M.asm:65
+ push di ; 57 ; 0xf9bc2 __U4M.asm:66
+ push ax ; 50 ; 0xf9bc3 __U4M.asm:79
+ db 08bh, 0fah
+ ; mov di, dx ; 8b fa ; 0xf9bc4 __U4M.asm:80
+ mul bx ; f7 e3 ; 0xf9bc6 __U4M.asm:83
+ db 08bh, 0f2h
+ ; mov si, dx ; 8b f2 ; 0xf9bc8 __U4M.asm:84
+ xchg di, ax ; 97 ; 0xf9bca __U4M.asm:85
+ mul bx ; f7 e3 ; 0xf9bcb __U4M.asm:88
+ db 003h, 0f0h
+ ; add si, ax ; 03 f0 ; 0xf9bcd __U4M.asm:89
+ pop ax ; 58 ; 0xf9bcf __U4M.asm:92
+ mul cx ; f7 e1 ; 0xf9bd0 __U4M.asm:93
+ db 003h, 0f0h
+ ; add si, ax ; 03 f0 ; 0xf9bd2 __U4M.asm:94
+ db 08bh, 0d6h
+ ; mov dx, si ; 8b d6 ; 0xf9bd4 __U4M.asm:97
+ db 08bh, 0c7h
+ ; mov ax, di ; 8b c7 ; 0xf9bd6 __U4M.asm:98
+ pop di ; 5f ; 0xf9bd8 __U4M.asm:100
+ pop si ; 5e ; 0xf9bd9 __U4M.asm:101
+ popfw ; 9d ; 0xf9bda __U4M.asm:103
+ retn ; c3 ; 0xf9bdb __U4M.asm:104
+ times 0x4 db 0
+ ; disGetNextSymbol 0xf9be0 LB 0x368 -> off=0x0 cb=0000000000000030 uValue=00000000000f85e0 '__U4D'
+__U4D: ; 0xf9be0 LB 0x30
+ pushfw ; 9c ; 0xf9be0 __U4D.asm:44
+ test cx, cx ; 85 c9 ; 0xf9be1 __U4D.asm:77
+ jne short 09bedh ; 75 08 ; 0xf9be3 __U4D.asm:78
+ div bx ; f7 f3 ; 0xf9be5 __U4D.asm:80
+ db 08bh, 0dah
+ ; mov bx, dx ; 8b da ; 0xf9be7 __U4D.asm:82
+ db 033h, 0d2h
+ ; xor dx, dx ; 33 d2 ; 0xf9be9 __U4D.asm:84
+ popfw ; 9d ; 0xf9beb __U4D.asm:86
+ retn ; c3 ; 0xf9bec __U4D.asm:87
+ push DS ; 1e ; 0xf9bed __U4D.asm:91
+ push ES ; 06 ; 0xf9bee __U4D.asm:92
+ push bp ; 55 ; 0xf9bef __U4D.asm:99
+ sub sp, strict byte 00004h ; 83 ec 04 ; 0xf9bf0 __U4D.asm:100
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xf9bf3 __U4D.asm:101
+ push SS ; 16 ; 0xf9bf5 __U4D.asm:104
+ push bp ; 55 ; 0xf9bf6 __U4D.asm:105
+ add bp, strict byte 00004h ; 83 c5 04 ; 0xf9bf7 __U4D.asm:106
+ push cx ; 51 ; 0xf9bfa __U4D.asm:109
+ push bx ; 53 ; 0xf9bfb __U4D.asm:110
+ push dx ; 52 ; 0xf9bfc __U4D.asm:113
+ push ax ; 50 ; 0xf9bfd __U4D.asm:114
+ call 09cc5h ; e8 c4 00 ; 0xf9bfe __U4D.asm:116
+ mov cx, word [bp-002h] ; 8b 4e fe ; 0xf9c01 __U4D.asm:119
+ mov bx, word [bp-004h] ; 8b 5e fc ; 0xf9c04 __U4D.asm:120
+ db 08bh, 0e5h
+ ; mov sp, bp ; 8b e5 ; 0xf9c07 __U4D.asm:124
+ pop bp ; 5d ; 0xf9c09 __U4D.asm:125
+ pop ES ; 07 ; 0xf9c0a __U4D.asm:126
+ pop DS ; 1f ; 0xf9c0b __U4D.asm:127
+ popfw ; 9d ; 0xf9c0c __U4D.asm:129
+ retn ; c3 ; 0xf9c0d __U4D.asm:130
+ times 0x2 db 0
+ ; disGetNextSymbol 0xf9c10 LB 0x338 -> off=0x0 cb=0000000000000010 uValue=00000000000f8610 '__U8RS'
+__U8RS: ; 0xf9c10 LB 0x10
+ test si, si ; 85 f6 ; 0xf9c10 __U8RS.asm:40
+ je short 09c1fh ; 74 0b ; 0xf9c12 __U8RS.asm:41
+ shr ax, 1 ; d1 e8 ; 0xf9c14 __U8RS.asm:43
+ rcr bx, 1 ; d1 db ; 0xf9c16 __U8RS.asm:44
+ rcr cx, 1 ; d1 d9 ; 0xf9c18 __U8RS.asm:45
+ rcr dx, 1 ; d1 da ; 0xf9c1a __U8RS.asm:46
+ dec si ; 4e ; 0xf9c1c __U8RS.asm:47
+ jne short 09c14h ; 75 f5 ; 0xf9c1d __U8RS.asm:48
+ retn ; c3 ; 0xf9c1f __U8RS.asm:50
+ ; disGetNextSymbol 0xf9c20 LB 0x328 -> off=0x0 cb=0000000000000010 uValue=00000000000f8620 '__U8LS'
+__U8LS: ; 0xf9c20 LB 0x10
+ test si, si ; 85 f6 ; 0xf9c20 __U8LS.asm:40
+ je short 09c2fh ; 74 0b ; 0xf9c22 __U8LS.asm:41
+ sal dx, 1 ; d1 e2 ; 0xf9c24 __U8LS.asm:43
+ rcl cx, 1 ; d1 d1 ; 0xf9c26 __U8LS.asm:44
+ rcl bx, 1 ; d1 d3 ; 0xf9c28 __U8LS.asm:45
+ rcl ax, 1 ; d1 d0 ; 0xf9c2a __U8LS.asm:46
+ dec si ; 4e ; 0xf9c2c __U8LS.asm:47
+ jne short 09c24h ; 75 f5 ; 0xf9c2d __U8LS.asm:48
+ retn ; c3 ; 0xf9c2f __U8LS.asm:50
+ ; disGetNextSymbol 0xf9c30 LB 0x318 -> off=0x0 cb=0000000000000010 uValue=00000000000f8630 '_fmemset_'
+_fmemset_: ; 0xf9c30 LB 0x10
+ push di ; 57 ; 0xf9c30 fmemset.asm:42
+ mov es, dx ; 8e c2 ; 0xf9c31 fmemset.asm:44
+ db 08bh, 0f8h
+ ; mov di, ax ; 8b f8 ; 0xf9c33 fmemset.asm:45
+ xchg al, bl ; 86 d8 ; 0xf9c35 fmemset.asm:46
+ rep stosb ; f3 aa ; 0xf9c37 fmemset.asm:47
+ xchg al, bl ; 86 d8 ; 0xf9c39 fmemset.asm:48
+ pop di ; 5f ; 0xf9c3b fmemset.asm:50
+ retn ; c3 ; 0xf9c3c fmemset.asm:51
+ times 0x3 db 0
+ ; disGetNextSymbol 0xf9c40 LB 0x308 -> off=0x0 cb=000000000000003a uValue=00000000000f8640 '_fmemcpy_'
+_fmemcpy_: ; 0xf9c40 LB 0x3a
+ push bp ; 55 ; 0xf9c40 fmemcpy.asm:42
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xf9c41 fmemcpy.asm:43
+ push di ; 57 ; 0xf9c43 fmemcpy.asm:44
+ push DS ; 1e ; 0xf9c44 fmemcpy.asm:45
+ push si ; 56 ; 0xf9c45 fmemcpy.asm:46
+ mov es, dx ; 8e c2 ; 0xf9c46 fmemcpy.asm:48
+ db 08bh, 0f8h
+ ; mov di, ax ; 8b f8 ; 0xf9c48 fmemcpy.asm:49
+ mov ds, cx ; 8e d9 ; 0xf9c4a fmemcpy.asm:50
+ db 08bh, 0f3h
+ ; mov si, bx ; 8b f3 ; 0xf9c4c fmemcpy.asm:51
+ mov cx, word [bp+004h] ; 8b 4e 04 ; 0xf9c4e fmemcpy.asm:52
+ rep movsb ; f3 a4 ; 0xf9c51 fmemcpy.asm:53
+ pop si ; 5e ; 0xf9c53 fmemcpy.asm:55
+ pop DS ; 1f ; 0xf9c54 fmemcpy.asm:56
+ pop di ; 5f ; 0xf9c55 fmemcpy.asm:57
+ db 08bh, 0e5h
+ ; mov sp, bp ; 8b e5 ; 0xf9c56 fmemcpy.asm:58
+ pop bp ; 5d ; 0xf9c58 fmemcpy.asm:59
+ retn ; c3 ; 0xf9c59 fmemcpy.asm:60
+ add byte [bx+si], al ; 00 00 ; 0xf9c5a
+ add byte [bx+si], al ; 00 00 ; 0xf9c5c
+ add byte [bx+si], al ; 00 00 ; 0xf9c5e
+ nop ; 90 ; 0xf9c60
+ pushfw ; 9c ; 0xf9c61
+ xchg dx, ax ; 92 ; 0xf9c62
+ pushfw ; 9c ; 0xf9c63
+ xchg si, ax ; 96 ; 0xf9c64
+ pushfw ; 9c ; 0xf9c65
+ xchg si, ax ; 96 ; 0xf9c66
+ pushfw ; 9c ; 0xf9c67
+ xchg si, ax ; 96 ; 0xf9c68
+ pushfw ; 9c ; 0xf9c69
+ cbw ; 98 ; 0xf9c6a
+ pushfw ; 9c ; 0xf9c6b
+ cbw ; 98 ; 0xf9c6c
+ pushfw ; 9c ; 0xf9c6d
+ call far 09e9ch:09e9ch ; 9a 9c 9e 9c 9e ; 0xf9c6e
+ pushfw ; 9c ; 0xf9c73
+ mov AL, byte [0a59ch] ; a0 9c a5 ; 0xf9c74
+ pushfw ; 9c ; 0xf9c77
+ cmpsw ; a7 ; 0xf9c78
+ pushfw ; 9c ; 0xf9c79
+ ; disGetNextSymbol 0xf9c7a LB 0x2ce -> off=0x0 cb=000000000000003a uValue=000000000000867a 'apm_worker'
+apm_worker: ; 0xf9c7a LB 0x3a
+ sti ; fb ; 0xf9c7a apm_pm.asm:56
+ push ax ; 50 ; 0xf9c7b apm_pm.asm:58
+ db 032h, 0e4h
+ ; xor ah, ah ; 32 e4 ; 0xf9c7c apm_pm.asm:59
+ sub AL, strict byte 004h ; 2c 04 ; 0xf9c7e apm_pm.asm:60
+ db 08bh, 0e8h
+ ; mov bp, ax ; 8b e8 ; 0xf9c80 apm_pm.asm:61
+ sal bp, 1 ; d1 e5 ; 0xf9c82 apm_pm.asm:62
+ cmp AL, strict byte 00dh ; 3c 0d ; 0xf9c84 apm_pm.asm:63
+ pop ax ; 58 ; 0xf9c86 apm_pm.asm:64
+ mov AH, strict byte 053h ; b4 53 ; 0xf9c87 apm_pm.asm:65
+ jnc short 09cb0h ; 73 25 ; 0xf9c89 apm_pm.asm:66
+ jmp word [cs:bp-063a0h] ; 2e ff a6 60 9c ; 0xf9c8b apm_pm.asm:68
+ jmp short 09caeh ; eb 1c ; 0xf9c90 apm_pm.asm:71
+ sti ; fb ; 0xf9c92 apm_pm.asm:74
+ hlt ; f4 ; 0xf9c93 apm_pm.asm:75
+ jmp short 09caeh ; eb 18 ; 0xf9c94 apm_pm.asm:76
+ jmp short 09caeh ; eb 16 ; 0xf9c96 apm_pm.asm:85
+ jmp short 09cb0h ; eb 16 ; 0xf9c98 apm_pm.asm:91
+ mov AH, strict byte 080h ; b4 80 ; 0xf9c9a apm_pm.asm:94
+ jmp short 09cb2h ; eb 14 ; 0xf9c9c apm_pm.asm:95
+ jmp short 09cb0h ; eb 10 ; 0xf9c9e apm_pm.asm:100
+ mov ax, 00102h ; b8 02 01 ; 0xf9ca0 apm_pm.asm:103
+ jmp short 09caeh ; eb 09 ; 0xf9ca3 apm_pm.asm:104
+ jmp short 09caeh ; eb 07 ; 0xf9ca5 apm_pm.asm:108
+ mov BL, strict byte 000h ; b3 00 ; 0xf9ca7 apm_pm.asm:111
+ mov cx, strict word 00000h ; b9 00 00 ; 0xf9ca9 apm_pm.asm:112
+ jmp short 09caeh ; eb 00 ; 0xf9cac apm_pm.asm:113
+ clc ; f8 ; 0xf9cae apm_pm.asm:116
+ retn ; c3 ; 0xf9caf apm_pm.asm:117
+ mov AH, strict byte 009h ; b4 09 ; 0xf9cb0 apm_pm.asm:120
+ stc ; f9 ; 0xf9cb2 apm_pm.asm:123
+ retn ; c3 ; 0xf9cb3 apm_pm.asm:124
+ ; disGetNextSymbol 0xf9cb4 LB 0x294 -> off=0x0 cb=0000000000000011 uValue=00000000000f86b4 'apm_pm16_entry'
+apm_pm16_entry: ; 0xf9cb4 LB 0x11
+ mov AH, strict byte 002h ; b4 02 ; 0xf9cb4 apm_pm.asm:136
+ push DS ; 1e ; 0xf9cb6 apm_pm.asm:142
+ push bp ; 55 ; 0xf9cb7 apm_pm.asm:143
+ push CS ; 0e ; 0xf9cb8 apm_pm.asm:145
+ pop bp ; 5d ; 0xf9cb9 apm_pm.asm:146
+ add bp, strict byte 00008h ; 83 c5 08 ; 0xf9cba apm_pm.asm:147
+ mov ds, bp ; 8e dd ; 0xf9cbd apm_pm.asm:148
+ call 09c7ah ; e8 b8 ff ; 0xf9cbf apm_pm.asm:150
+ pop bp ; 5d ; 0xf9cc2 apm_pm.asm:152
+ pop DS ; 1f ; 0xf9cc3 apm_pm.asm:153
+ retf ; cb ; 0xf9cc4 apm_pm.asm:155
+ ; disGetNextSymbol 0xf9cc5 LB 0x283 -> off=0x0 cb=0000000000000265 uValue=00000000000f86c5 'DoUInt32Div'
+DoUInt32Div: ; 0xf9cc5 LB 0x265
+ push bp ; 55 ; 0xf9cc5 DoUInt32Div.c:28
+ mov bp, sp ; 89 e5 ; 0xf9cc6
+ push si ; 56 ; 0xf9cc8
+ push di ; 57 ; 0xf9cc9
+ sub sp, strict byte 00018h ; 83 ec 18 ; 0xf9cca
+ lds bx, [bp+00ch] ; c5 5e 0c ; 0xf9ccd
+ lea si, [bp+004h] ; 8d 76 04 ; 0xf9cd0 DoUInt32Div.c:972
+ mov word [bp-010h], si ; 89 76 f0 ; 0xf9cd3
+ mov [bp-00eh], ss ; 8c 56 f2 ; 0xf9cd6
+ lea di, [bp+008h] ; 8d 7e 08 ; 0xf9cd9
+ mov [bp-008h], ss ; 8c 56 f8 ; 0xf9cdc
+ lea si, [bp-01ch] ; 8d 76 e4 ; 0xf9cdf
+ mov word [bp-00ch], si ; 89 76 f4 ; 0xf9ce2
+ mov [bp-00ah], ss ; 8c 56 f6 ; 0xf9ce5
+ mov si, bx ; 89 de ; 0xf9ce8
+ mov [bp-006h], ds ; 8c 5e fa ; 0xf9cea
+ cmp word [bx+002h], strict byte 00000h ; 83 7f 02 00 ; 0xf9ced DoUInt32Div.c:980
+ jne short 09d15h ; 75 22 ; 0xf9cf1
+ mov ax, word [bx] ; 8b 07 ; 0xf9cf3 DoUInt32Div.c:982
+ test ax, ax ; 85 c0 ; 0xf9cf5
+ je short 09d12h ; 74 19 ; 0xf9cf7
+ cmp ax, strict word 00001h ; 3d 01 00 ; 0xf9cf9 DoUInt32Div.c:985
+ jne short 09d15h ; 75 17 ; 0xf9cfc
+ xor ax, ax ; 31 c0 ; 0xf9cfe DoUInt32Div.c:67
+ mov word [bp+00ah], ax ; 89 46 0a ; 0xf9d00
+ mov word [bp+008h], ax ; 89 46 08 ; 0xf9d03 DoUInt32Div.c:68
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf9d06 DoUInt32Div.c:988
+ mov word [bp+004h], ax ; 89 46 04 ; 0xf9d09
+ mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xf9d0c
+ mov word [bp+006h], ax ; 89 46 06 ; 0xf9d0f
+ jmp near 09f1dh ; e9 08 02 ; 0xf9d12
+ lds bx, [bp-00ch] ; c5 5e f4 ; 0xf9d15 DoUInt32Div.c:726
+ mov ax, word [bx+002h] ; 8b 47 02 ; 0xf9d18
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9d1b
+ cmp ax, word [si+002h] ; 3b 44 02 ; 0xf9d1e
+ je short 09d3bh ; 74 18 ; 0xf9d21
+ mov ds, [bp-00ah] ; 8e 5e f6 ; 0xf9d23 DoUInt32Div.c:727
+ mov ax, word [bx+002h] ; 8b 47 02 ; 0xf9d26
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9d29
+ cmp ax, word [si+002h] ; 3b 44 02 ; 0xf9d2c
+ jbe short 09d36h ; 76 05 ; 0xf9d2f
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf9d31
+ jmp short 09d5ch ; eb 26 ; 0xf9d34
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf9d36
+ jmp short 09d5ch ; eb 21 ; 0xf9d39
+ mov ds, [bp-00ah] ; 8e 5e f6 ; 0xf9d3b DoUInt32Div.c:728
+ mov ax, word [bx] ; 8b 07 ; 0xf9d3e
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9d40
+ cmp ax, word [si] ; 3b 04 ; 0xf9d43
+ je short 09d5ah ; 74 13 ; 0xf9d45
+ mov ds, [bp-00ah] ; 8e 5e f6 ; 0xf9d47 DoUInt32Div.c:729
+ mov ax, word [bx] ; 8b 07 ; 0xf9d4a
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9d4c
+ cmp ax, word [si] ; 3b 04 ; 0xf9d4f
+ jbe short 09d55h ; 76 02 ; 0xf9d51
+ jmp short 09d31h ; eb dc ; 0xf9d53
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xf9d55
+ jmp short 09d5ch ; eb 02 ; 0xf9d58
+ xor ax, ax ; 31 c0 ; 0xf9d5a DoUInt32Div.c:730
+ test ax, ax ; 85 c0 ; 0xf9d5c DoUInt32Div.c:996
+ jnl short 09d7eh ; 7d 1e ; 0xf9d5e
+ lds bx, [bp-00ch] ; c5 5e f4 ; 0xf9d60 DoUInt32Div.c:998
+ mov ax, word [bx] ; 8b 07 ; 0xf9d63
+ mov dx, word [bx+002h] ; 8b 57 02 ; 0xf9d65
+ mov ds, [bp-008h] ; 8e 5e f8 ; 0xf9d68
+ mov word [di], ax ; 89 05 ; 0xf9d6b
+ mov word [di+002h], dx ; 89 55 02 ; 0xf9d6d
+ lds bx, [bp-010h] ; c5 5e f0 ; 0xf9d70 DoUInt32Div.c:67
+ mov word [bx+002h], strict word 00000h ; c7 47 02 00 00 ; 0xf9d73
+ mov word [bx], strict word 00000h ; c7 07 00 00 ; 0xf9d78 DoUInt32Div.c:68
+ jmp short 09d12h ; eb 94 ; 0xf9d7c DoUInt32Div.c:1003
+ jne short 09d95h ; 75 15 ; 0xf9d7e
+ mov ds, [bp-008h] ; 8e 5e f8 ; 0xf9d80 DoUInt32Div.c:67
+ mov word [di+002h], ax ; 89 45 02 ; 0xf9d83
+ mov word [di], ax ; 89 05 ; 0xf9d86 DoUInt32Div.c:68
+ lds bx, [bp-010h] ; c5 5e f0 ; 0xf9d88 DoUInt32Div.c:397
+ mov word [bx], strict word 00001h ; c7 07 01 00 ; 0xf9d8b
+ mov word [bx+002h], ax ; 89 47 02 ; 0xf9d8f DoUInt32Div.c:398
+ jmp near 09f1dh ; e9 88 01 ; 0xf9d92 DoUInt32Div.c:1008
+ lds bx, [bp-00ch] ; c5 5e f4 ; 0xf9d95 DoUInt32Div.c:954
+ mov ax, word [bx+002h] ; 8b 47 02 ; 0xf9d98
+ test ax, ax ; 85 c0 ; 0xf9d9b
+ je short 09db0h ; 74 11 ; 0xf9d9d
+ push ax ; 50 ; 0xf9d9f DoUInt32Div.c:955
+ mov ax, 0f000h ; b8 00 f0 ; 0xf9da0
+ mov ds, ax ; 8e d8 ; 0xf9da3
+ call 09f30h ; e8 88 01 ; 0xf9da5
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xf9da8
+ add ax, strict word 00010h ; 05 10 00 ; 0xf9dab
+ jmp short 09dbdh ; eb 0d ; 0xf9dae DoUInt32Div.c:956
+ push word [bx] ; ff 37 ; 0xf9db0 DoUInt32Div.c:957
+ mov ax, 0f000h ; b8 00 f0 ; 0xf9db2
+ mov ds, ax ; 8e d8 ; 0xf9db5
+ call 09f30h ; e8 76 01 ; 0xf9db7
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xf9dba
+ mov word [bp-014h], ax ; 89 46 ec ; 0xf9dbd DoUInt32Div.c:959
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9dc0 DoUInt32Div.c:954
+ mov ax, word [si+002h] ; 8b 44 02 ; 0xf9dc3
+ test ax, ax ; 85 c0 ; 0xf9dc6
+ je short 09ddbh ; 74 11 ; 0xf9dc8
+ push ax ; 50 ; 0xf9dca DoUInt32Div.c:955
+ mov ax, 0f000h ; b8 00 f0 ; 0xf9dcb
+ mov ds, ax ; 8e d8 ; 0xf9dce
+ call 09f30h ; e8 5d 01 ; 0xf9dd0
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xf9dd3
+ add ax, strict word 00010h ; 05 10 00 ; 0xf9dd6
+ jmp short 09de8h ; eb 0d ; 0xf9dd9 DoUInt32Div.c:956
+ push word [si] ; ff 34 ; 0xf9ddb DoUInt32Div.c:957
+ mov ax, 0f000h ; b8 00 f0 ; 0xf9ddd
+ mov ds, ax ; 8e d8 ; 0xf9de0
+ call 09f30h ; e8 4b 01 ; 0xf9de2
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xf9de5
+ mov dx, word [bp-014h] ; 8b 56 ec ; 0xf9de8 DoUInt32Div.c:959
+ sub dx, ax ; 29 c2 ; 0xf9deb
+ mov word [bp-012h], dx ; 89 56 ee ; 0xf9ded
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9df0 DoUInt32Div.c:1014
+ mov ax, word [si] ; 8b 04 ; 0xf9df3
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf9df5
+ mov ax, word [si+002h] ; 8b 44 02 ; 0xf9df8
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf9dfb
+ test dx, dx ; 85 d2 ; 0xf9dfe DoUInt32Div.c:1015
+ je short 09e58h ; 74 56 ; 0xf9e00
+ mov cx, dx ; 89 d1 ; 0xf9e02 DoUInt32Div.c:280
+ xor ch, dh ; 30 f5 ; 0xf9e04
+ and cl, 01fh ; 80 e1 1f ; 0xf9e06
+ mov ax, word [si] ; 8b 04 ; 0xf9e09 DoUInt32Div.c:282
+ mov dx, word [si+002h] ; 8b 54 02 ; 0xf9e0b
+ jcxz 09e16h ; e3 06 ; 0xf9e0e
+ sal ax, 1 ; d1 e0 ; 0xf9e10
+ rcl dx, 1 ; d1 d2 ; 0xf9e12
+ loop 09e10h ; e2 fa ; 0xf9e14
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf9e16
+ mov word [bp-016h], dx ; 89 56 ea ; 0xf9e19
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf9e1c DoUInt32Div.c:763
+ lds bx, [bp-00ch] ; c5 5e f4 ; 0xf9e1f
+ cmp ax, word [bx+002h] ; 3b 47 02 ; 0xf9e22
+ jnbe short 09e36h ; 77 0f ; 0xf9e25
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf9e27
+ cmp ax, word [bx+002h] ; 3b 47 02 ; 0xf9e2a
+ jne short 09e3ah ; 75 0b ; 0xf9e2d
+ mov ax, word [bp-018h] ; 8b 46 e8 ; 0xf9e2f
+ cmp ax, word [bx] ; 3b 07 ; 0xf9e32
+ jbe short 09e3ah ; 76 04 ; 0xf9e34
+ mov AL, strict byte 001h ; b0 01 ; 0xf9e36
+ jmp short 09e3ch ; eb 02 ; 0xf9e38
+ xor al, al ; 30 c0 ; 0xf9e3a
+ test al, al ; 84 c0 ; 0xf9e3c DoUInt32Div.c:769
+ je short 09e63h ; 74 23 ; 0xf9e3e
+ shr word [bp-016h], 1 ; d1 6e ea ; 0xf9e40 DoUInt32Div.c:680
+ rcr word [bp-018h], 1 ; d1 5e e8 ; 0xf9e43
+ dec word [bp-012h] ; ff 4e ee ; 0xf9e46
+ jmp short 09e63h ; eb 18 ; 0xf9e49
+ mov cx, strict word 0001fh ; b9 1f 00 ; 0xf9e4b DoUInt32Div.c:632
+ sal word [bp-018h], 1 ; d1 66 e8 ; 0xf9e4e
+ rcl word [bp-016h], 1 ; d1 56 ea ; 0xf9e51
+ loop 09e4eh ; e2 f8 ; 0xf9e54
+ jmp short 09e46h ; eb ee ; 0xf9e56 DoUInt32Div.c:647
+ mov ax, word [si] ; 8b 04 ; 0xf9e58 DoUInt32Div.c:1025
+ mov word [bp-018h], ax ; 89 46 e8 ; 0xf9e5a
+ mov ax, word [si+002h] ; 8b 44 02 ; 0xf9e5d
+ mov word [bp-016h], ax ; 89 46 ea ; 0xf9e60
+ lds bx, [bp-010h] ; c5 5e f0 ; 0xf9e63 DoUInt32Div.c:67
+ mov word [bx+002h], strict word 00000h ; c7 47 02 00 00 ; 0xf9e66
+ mov word [bx], strict word 00000h ; c7 07 00 00 ; 0xf9e6b DoUInt32Div.c:68
+ lds bx, [bp-00ch] ; c5 5e f4 ; 0xf9e6f DoUInt32Div.c:1028
+ mov dx, word [bx] ; 8b 17 ; 0xf9e72
+ mov ax, word [bx+002h] ; 8b 47 02 ; 0xf9e74
+ mov ds, [bp-008h] ; 8e 5e f8 ; 0xf9e77
+ mov word [di], dx ; 89 15 ; 0xf9e7a
+ mov word [di+002h], ax ; 89 45 02 ; 0xf9e7c
+ mov dx, word [di] ; 8b 15 ; 0xf9e7f DoUInt32Div.c:782
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9e81
+ cmp ax, word [si+002h] ; 3b 44 02 ; 0xf9e84
+ jnbe short 09e8fh ; 77 06 ; 0xf9e87
+ jne short 09e93h ; 75 08 ; 0xf9e89
+ cmp dx, word [si] ; 3b 14 ; 0xf9e8b
+ jc short 09e93h ; 72 04 ; 0xf9e8d
+ mov AL, strict byte 001h ; b0 01 ; 0xf9e8f
+ jmp short 09e95h ; eb 02 ; 0xf9e91
+ xor al, al ; 30 c0 ; 0xf9e93
+ test al, al ; 84 c0 ; 0xf9e95 DoUInt32Div.c:788
+ je short 09efah ; 74 61 ; 0xf9e97
+ mov ds, [bp-008h] ; 8e 5e f8 ; 0xf9e99 DoUInt32Div.c:782
+ mov ax, word [di+002h] ; 8b 45 02 ; 0xf9e9c
+ cmp ax, word [bp-016h] ; 3b 46 ea ; 0xf9e9f
+ jnbe short 09eb0h ; 77 0c ; 0xf9ea2
+ cmp ax, word [bp-016h] ; 3b 46 ea ; 0xf9ea4
+ jne short 09eb4h ; 75 0b ; 0xf9ea7
+ mov ax, word [di] ; 8b 05 ; 0xf9ea9
+ cmp ax, word [bp-018h] ; 3b 46 e8 ; 0xf9eab
+ jc short 09eb4h ; 72 04 ; 0xf9eae
+ mov AL, strict byte 001h ; b0 01 ; 0xf9eb0
+ jmp short 09eb6h ; eb 02 ; 0xf9eb2
+ xor al, al ; 30 c0 ; 0xf9eb4
+ test al, al ; 84 c0 ; 0xf9eb6 DoUInt32Div.c:788
+ je short 09ee0h ; 74 26 ; 0xf9eb8
+ mov ax, word [bp-018h] ; 8b 46 e8 ; 0xf9eba DoUInt32Div.c:451
+ mov ds, [bp-008h] ; 8e 5e f8 ; 0xf9ebd
+ sub word [di], ax ; 29 05 ; 0xf9ec0
+ mov ax, word [bp-016h] ; 8b 46 ea ; 0xf9ec2
+ sbb word [di+002h], ax ; 19 45 02 ; 0xf9ec5
+ mov ax, strict word 00001h ; b8 01 00 ; 0xf9ec8 DoUInt32Div.c:586
+ xor dx, dx ; 31 d2 ; 0xf9ecb
+ mov cx, word [bp-012h] ; 8b 4e ee ; 0xf9ecd
+ jcxz 09ed8h ; e3 06 ; 0xf9ed0
+ sal ax, 1 ; d1 e0 ; 0xf9ed2
+ rcl dx, 1 ; d1 d2 ; 0xf9ed4
+ loop 09ed2h ; e2 fa ; 0xf9ed6
+ lds bx, [bp-010h] ; c5 5e f0 ; 0xf9ed8
+ or word [bx], ax ; 09 07 ; 0xf9edb
+ or word [bx+002h], dx ; 09 57 02 ; 0xf9edd
+ mov ds, [bp-008h] ; 8e 5e f8 ; 0xf9ee0 DoUInt32Div.c:744
+ mov dx, word [di] ; 8b 15 ; 0xf9ee3
+ mov ax, word [di+002h] ; 8b 45 02 ; 0xf9ee5
+ mov ds, [bp-006h] ; 8e 5e fa ; 0xf9ee8
+ cmp ax, word [si+002h] ; 3b 44 02 ; 0xf9eeb
+ jc short 09ef6h ; 72 06 ; 0xf9eee
+ jne short 09efch ; 75 0a ; 0xf9ef0
+ cmp dx, word [si] ; 3b 14 ; 0xf9ef2
+ jnc short 09efch ; 73 06 ; 0xf9ef4
+ mov AL, strict byte 001h ; b0 01 ; 0xf9ef6
+ jmp short 09efeh ; eb 04 ; 0xf9ef8
+ jmp short 09f1dh ; eb 21 ; 0xf9efa
+ xor al, al ; 30 c0 ; 0xf9efc
+ test al, al ; 84 c0 ; 0xf9efe DoUInt32Div.c:750
+ je short 09f11h ; 74 0f ; 0xf9f00
+ jmp short 09f1dh ; eb 19 ; 0xf9f02 DoUInt32Div.c:1043
+ mov cx, strict word 0001fh ; b9 1f 00 ; 0xf9f04 DoUInt32Div.c:680
+ sal word [bp-018h], 1 ; d1 66 e8 ; 0xf9f07
+ rcl word [bp-016h], 1 ; d1 56 ea ; 0xf9f0a
+ loop 09f07h ; e2 f8 ; 0xf9f0d
+ jmp short 09f17h ; eb 06 ; 0xf9f0f DoUInt32Div.c:647
+ shr word [bp-016h], 1 ; d1 6e ea ; 0xf9f11 DoUInt32Div.c:653
+ rcr word [bp-018h], 1 ; d1 5e e8 ; 0xf9f14
+ dec word [bp-012h] ; ff 4e ee ; 0xf9f17 DoUInt32Div.c:1045
+ jmp near 09e99h ; e9 7c ff ; 0xf9f1a DoUInt32Div.c:1046
+ mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xf9f1d DoUInt32Div.c:32
+ mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xf9f20
+ lea sp, [bp-004h] ; 8d 66 fc ; 0xf9f23 DoUInt32Div.c:33
+ pop di ; 5f ; 0xf9f26
+ pop si ; 5e ; 0xf9f27
+ pop bp ; 5d ; 0xf9f28
+ retn ; c3 ; 0xf9f29
+ ; disGetNextSymbol 0xf9f2a LB 0x1e -> off=0x6 cb=0000000000000018 uValue=00000000000f8930 '_ASMBitLastSetU16'
+ db 000h, 000h, 000h, 000h, 000h, 000h
+_ASMBitLastSetU16: ; 0xf9f30 LB 0x18
+ push bp ; 55 ; 0xf9f30 ASMBitLastSetU16.asm:43
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xf9f31 ASMBitLastSetU16.asm:44
+ mov cx, word [bp+004h] ; 8b 4e 04 ; 0xf9f33 ASMBitLastSetU16.asm:46
+ test cx, cx ; 85 c9 ; 0xf9f36 ASMBitLastSetU16.asm:47
+ je short 09f44h ; 74 0a ; 0xf9f38 ASMBitLastSetU16.asm:48
+ mov ax, strict word 00010h ; b8 10 00 ; 0xf9f3a ASMBitLastSetU16.asm:50
+ sal cx, 1 ; d1 e1 ; 0xf9f3d ASMBitLastSetU16.asm:52
+ jc short 09f46h ; 72 05 ; 0xf9f3f ASMBitLastSetU16.asm:53
+ dec ax ; 48 ; 0xf9f41 ASMBitLastSetU16.asm:54
+ jmp short 09f3dh ; eb f9 ; 0xf9f42 ASMBitLastSetU16.asm:55
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xf9f44 ASMBitLastSetU16.asm:58
+ pop bp ; 5d ; 0xf9f46 ASMBitLastSetU16.asm:60
+ retn ; c3 ; 0xf9f47 ASMBitLastSetU16.asm:61
+
+ ; Padding 0x3ab8 bytes at 0xf9f48
+ times 15032 db 0
+
+section BIOS32 progbits vstart=0xda00 align=1 ; size=0x39d class=CODE group=AUTO
+ ; disGetNextSymbol 0xfda00 LB 0x39d -> off=0x0 cb=0000000000000026 uValue=00000000000f0000 'bios32_service'
+bios32_service: ; 0xfda00 LB 0x26
+ pushfw ; 9c ; 0xfda00 pcibio32.asm:52
+ cmp bl, 000h ; 80 fb 00 ; 0xfda01 pcibio32.asm:54
+ jne short 0da22h ; 75 1c ; 0xfda04 pcibio32.asm:55
+ cmp ax, 05024h ; 3d 24 50 ; 0xfda06 pcibio32.asm:57
+ inc bx ; 43 ; 0xfda09
+ dec cx ; 49 ; 0xfda0a
+ mov AL, strict byte 080h ; b0 80 ; 0xfda0b pcibio32.asm:58
+ jne short 0da20h ; 75 11 ; 0xfda0d pcibio32.asm:59
+ mov bx, strict word 00000h ; bb 00 00 ; 0xfda0f pcibio32.asm:61
+ db 00fh
+ add byte [bx+di-01000h], bh ; 00 b9 00 f0 ; 0xfda13
+ add byte [bx+si], al ; 00 00 ; 0xfda17
+ mov dx, 0da26h ; ba 26 da ; 0xfda19 pcibio32.asm:63
+ add byte [bx+si], al ; 00 00 ; 0xfda1c
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xfda1e pcibio32.asm:64
+ popfw ; 9d ; 0xfda20 pcibio32.asm:66
+ retf ; cb ; 0xfda21 pcibio32.asm:67
+ mov AL, strict byte 081h ; b0 81 ; 0xfda22 pcibio32.asm:70
+ jmp short 0da20h ; eb fa ; 0xfda24 pcibio32.asm:71
+ ; disGetNextSymbol 0xfda26 LB 0x377 -> off=0x0 cb=000000000000000d uValue=00000000000f0026 'pcibios32_entry'
+pcibios32_entry: ; 0xfda26 LB 0xd
+ pushfw ; 9c ; 0xfda26 pcibio32.asm:80
+ cld ; fc ; 0xfda27 pcibio32.asm:81
+ push ES ; 06 ; 0xfda28 pcibio32.asm:83
+ pushaw ; 60 ; 0xfda29 pcibio32.asm:84
+ call 0db4ah ; e8 1d 01 ; 0xfda2a pcibio32.asm:85
+ add byte [bx+si], al ; 00 00 ; 0xfda2d
+ popaw ; 61 ; 0xfda2f pcibio32.asm:86
+ pop ES ; 07 ; 0xfda30 pcibio32.asm:87
+ popfw ; 9d ; 0xfda31 pcibio32.asm:89
+ retf ; cb ; 0xfda32 pcibio32.asm:90
+ ; disGetNextSymbol 0xfda33 LB 0x36a -> off=0x0 cb=0000000000000022 uValue=00000000000f0033 'pci32_select_reg_'
+pci32_select_reg_: ; 0xfda33 LB 0x22
+ push bp ; 55 ; 0xfda33 pci32.c:188
+ mov bp, sp ; 89 e5 ; 0xfda34
+ push bx ; 53 ; 0xfda36
+ and dl, 0fch ; 80 e2 fc ; 0xfda37 pci32.c:190
+ mov bx, dx ; 89 d3 ; 0xfda3a
+ mov dx, 00cf8h ; ba f8 0c ; 0xfda3c
+ add byte [bx+si], al ; 00 00 ; 0xfda3f
+ db 00fh, 0b7h, 0c0h
+ ; movzx ax, ax ; 0f b7 c0 ; 0xfda41
+ sal ax, 008h ; c1 e0 08 ; 0xfda44
+ or ax, strict word 00000h ; 0d 00 00 ; 0xfda47
+ add byte [bx+si-03c76h], al ; 00 80 8a c3 ; 0xfda4a
+ out DX, ax ; ef ; 0xfda4e
+ lea sp, [di-004h] ; 8d 65 fc ; 0xfda4f pci32.c:191
+ pop bx ; 5b ; 0xfda52
+ pop bp ; 5d ; 0xfda53
+ retn ; c3 ; 0xfda54
+ ; disGetNextSymbol 0xfda55 LB 0x348 -> off=0x0 cb=00000000000000f7 uValue=00000000000f0055 'pci32_find_device_'
+pci32_find_device_: ; 0xfda55 LB 0xf7
+ push bp ; 55 ; 0xfda55 pci32.c:221
+ mov bp, sp ; 89 e5 ; 0xfda56
+ push cx ; 51 ; 0xfda58
+ push si ; 56 ; 0xfda59
+ push di ; 57 ; 0xfda5a
+ sub sp, strict byte 00014h ; 83 ec 14 ; 0xfda5b
+ push ax ; 50 ; 0xfda5e
+ mov cx, dx ; 89 d1 ; 0xfda5f
+ mov si, bx ; 89 de ; 0xfda61
+ test bx, bx ; 85 db ; 0xfda63 pci32.c:231
+ xor bx, bx ; 31 db ; 0xfda65 pci32.c:238
+ mov byte [di-010h], 000h ; c6 45 f0 00 ; 0xfda67 pci32.c:239
+ test bl, 007h ; f6 c3 07 ; 0xfda6b pci32.c:249
+ jne short 0daa6h ; 75 36 ; 0xfda6e
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfda70 pci32.c:250
+ mov dx, strict word 0000eh ; ba 0e 00 ; 0xfda73
+ add byte [bx+si], al ; 00 00 ; 0xfda76
+ call 0da31h ; e8 b6 ff ; 0xfda78
+ db 0ffh
+ db 0ffh
+ mov dx, 00cfeh ; ba fe 0c ; 0xfda7d pci32.c:251
+ add byte [bx+si], al ; 00 00 ; 0xfda80
+ db 02bh, 0c0h
+ ; sub ax, ax ; 2b c0 ; 0xfda82
+ in AL, DX ; ec ; 0xfda84
+ mov byte [di-014h], al ; 88 45 ec ; 0xfda85
+ cmp AL, strict byte 0ffh ; 3c ff ; 0xfda88 pci32.c:252
+ jne short 0da94h ; 75 08 ; 0xfda8a
+ add bx, strict byte 00008h ; 83 c3 08 ; 0xfda8c pci32.c:253
+ jmp near 0db1ch ; e9 8a 00 ; 0xfda8f pci32.c:254
+ add byte [bx+si], al ; 00 00 ; 0xfda92
+ test byte [di-014h], 080h ; f6 45 ec 80 ; 0xfda94 pci32.c:256
+ je short 0daa1h ; 74 07 ; 0xfda98
+ mov di, strict word 00001h ; bf 01 00 ; 0xfda9a pci32.c:257
+ add byte [bx+si], al ; 00 00 ; 0xfda9d
+ jmp short 0daa6h ; eb 05 ; 0xfda9f pci32.c:258
+ mov di, strict word 00008h ; bf 08 00 ; 0xfdaa1 pci32.c:259
+ add byte [bx+si], al ; 00 00 ; 0xfdaa4
+ mov al, byte [di-014h] ; 8a 45 ec ; 0xfdaa6 pci32.c:270
+ and AL, strict byte 007h ; 24 07 ; 0xfdaa9
+ cmp AL, strict byte 001h ; 3c 01 ; 0xfdaab
+ jne short 0dad5h ; 75 26 ; 0xfdaad
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfdaaf
+ mov dx, ax ; 89 c2 ; 0xfdab2
+ sar dx, 008h ; c1 fa 08 ; 0xfdab4
+ test dx, dx ; 85 d2 ; 0xfdab7
+ jne short 0dad5h ; 75 1a ; 0xfdab9
+ mov dx, strict word 0001ah ; ba 1a 00 ; 0xfdabb pci32.c:272
+ add byte [bx+si], al ; 00 00 ; 0xfdabe
+ call 0da31h ; e8 6e ff ; 0xfdac0
+ db 0ffh
+ db 0ffh
+ mov dx, 00cfeh ; ba fe 0c ; 0xfdac5 pci32.c:273
+ add byte [bx+si], al ; 00 00 ; 0xfdac8
+ db 02bh, 0c0h
+ ; sub ax, ax ; 2b c0 ; 0xfdaca
+ in AL, DX ; ec ; 0xfdacc
+ cmp al, byte [di-010h] ; 3a 45 f0 ; 0xfdacd pci32.c:274
+ jbe short 0dad5h ; 76 03 ; 0xfdad0
+ mov byte [di-010h], al ; 88 45 f0 ; 0xfdad2 pci32.c:275
+ test si, si ; 85 f6 ; 0xfdad5 pci32.c:279
+ je short 0dae0h ; 74 07 ; 0xfdad7
+ mov ax, strict word 00008h ; b8 08 00 ; 0xfdad9
+ add byte [bx+si], al ; 00 00 ; 0xfdadc
+ jmp short 0dae2h ; eb 02 ; 0xfdade
+ xor ax, ax ; 31 c0 ; 0xfdae0
+ db 00fh, 0b7h, 0d0h
+ ; movzx dx, ax ; 0f b7 d0 ; 0xfdae2
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfdae5
+ call 0da31h ; e8 46 ff ; 0xfdae8
+ db 0ffh
+ db 0ffh
+ mov dx, 00cfch ; ba fc 0c ; 0xfdaed pci32.c:280
+ add byte [bx+si], al ; 00 00 ; 0xfdaf0
+ in ax, DX ; ed ; 0xfdaf2
+ mov word [di-018h], ax ; 89 45 e8 ; 0xfdaf3
+ mov word [di-020h], strict word 00000h ; c7 45 e0 00 00 ; 0xfdaf6 pci32.c:281
+ add byte [bx+si], al ; 00 00 ; 0xfdafb
+ test si, si ; 85 f6 ; 0xfdafd pci32.c:284
+ je short 0db07h ; 74 06 ; 0xfdaff
+ shr ax, 008h ; c1 e8 08 ; 0xfdb01 pci32.c:285
+ mov word [di-018h], ax ; 89 45 e8 ; 0xfdb04
+ mov ax, word [di-018h] ; 8b 45 e8 ; 0xfdb07 pci32.c:292
+ cmp ax, word [di-024h] ; 3b 45 dc ; 0xfdb0a
+ je short 0db15h ; 74 06 ; 0xfdb0d
+ cmp word [di-020h], strict byte 00000h ; 83 7d e0 00 ; 0xfdb0f pci32.c:293
+ je short 0db1ch ; 74 07 ; 0xfdb13
+ dec cx ; 49 ; 0xfdb15
+ cmp ecx, strict byte 0ffffffffh ; 66 83 f9 ff ; 0xfdb16
+ je short 0db34h ; 74 18 ; 0xfdb1a
+ add bx, di ; 01 fb ; 0xfdb1c pci32.c:301
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfdb1e pci32.c:302
+ sar ax, 008h ; c1 f8 08 ; 0xfdb21
+ mov word [di-01ch], ax ; 89 45 e4 ; 0xfdb24
+ movzx ax, byte [di-010h] ; 0f b6 45 f0 ; 0xfdb27
+ cmp ax, word [di-01ch] ; 3b 45 e4 ; 0xfdb2b
+ jnl near 0da69h ; 0f 8d 37 ff ; 0xfdb2e
+ db 0ffh
+ jmp word [bp-07dh] ; ff 66 83 ; 0xfdb33
+ stc ; f9 ; 0xfdb36
+ push word [di+005h] ; ff 75 05 ; 0xfdb37
+ db 00fh, 0b7h, 0c3h
+ ; movzx ax, bx ; 0f b7 c3 ; 0xfdb3a
+ jmp short 0db44h ; eb 05 ; 0xfdb3d
+ mov ax, strict word 0ffffh ; b8 ff ff ; 0xfdb3f
+ add byte [bx+si], al ; 00 00 ; 0xfdb42
+ lea sp, [di-00ch] ; 8d 65 f4 ; 0xfdb44 pci32.c:309
+ pop di ; 5f ; 0xfdb47
+ pop si ; 5e ; 0xfdb48
+ pop cx ; 59 ; 0xfdb49
+ pop bp ; 5d ; 0xfdb4a
+ retn ; c3 ; 0xfdb4b
+ ; disGetNextSymbol 0xfdb4c LB 0x251 -> off=0x0 cb=0000000000000251 uValue=00000000000f014c '_pci32_function'
+_pci32_function: ; 0xfdb4c LB 0x251
+ push bp ; 55 ; 0xfdb4c pci32.c:311
+ mov bp, sp ; 89 e5 ; 0xfdb4d
+ push bx ; 53 ; 0xfdb4f
+ push si ; 56 ; 0xfdb50
+ push di ; 57 ; 0xfdb51
+ push ax ; 50 ; 0xfdb52
+ push ax ; 50 ; 0xfdb53
+ and dword [di+024h], strict dword 0658100ffh ; 66 81 65 24 ff 00 81 65 ; 0xfdb54 pci32.c:318
+ sub AL, strict byte 0feh ; 2c fe ; 0xfdb5c
+ inc word [bx+si] ; ff 00 ; 0xfdb5e
+ add byte [bp+di+02445h], cl ; 00 8b 45 24 ; 0xfdb60
+ xor ah, ah ; 30 e4 ; 0xfdb64
+ cmp eax, strict dword 029720003h ; 66 3d 03 00 72 29 ; 0xfdb66
+ jbe near 0dc09h ; 0f 86 99 00 ; 0xfdb6c
+ add byte [bx+si], al ; 00 00 ; 0xfdb70
+ cmp eax, strict dword 0840f000eh ; 66 3d 0e 00 0f 84 ; 0xfdb72
+ test ax, strict word 00001h ; a9 01 00 ; 0xfdb78
+ add byte [bp+03dh], ah ; 00 66 3d ; 0xfdb7b
+ or byte [bx+si], al ; 08 00 ; 0xfdb7e
+ jc near 0dd83h ; 0f 82 ff 01 ; 0xfdb80
+ add byte [bx+si], al ; 00 00 ; 0xfdb84
+ cmp eax, strict dword 0860f000dh ; 66 3d 0d 00 0f 86 ; 0xfdb86
+ test AL, strict byte 000h ; a8 00 ; 0xfdb8c
+ add byte [bx+si], al ; 00 00 ; 0xfdb8e
+ jmp near 0dd83h ; e9 f0 01 ; 0xfdb90
+ add byte [bx+si], al ; 00 00 ; 0xfdb93
+ cmp eax, strict dword 028740002h ; 66 3d 02 00 74 28 ; 0xfdb95
+ cmp eax, strict dword 0850f0001h ; 66 3d 01 00 0f 85 ; 0xfdb9b
+ loopne 0dba4h ; e0 01 ; 0xfdba1
+ add byte [bx+si], al ; 00 00 ; 0xfdba3
+ mov dword [di+024h], strict dword 0c7660001h ; 66 c7 45 24 01 00 66 c7 ; 0xfdba5 pci32.c:323
+ inc bp ; 45 ; 0xfdbad
+ sbb byte [bx+si], dl ; 18 10 ; 0xfdbae
+ add dh, byte [bx+di] ; 02 31 ; 0xfdbb0
+ sal byte [bp-077h], 045h ; c0 66 89 45 ; 0xfdbb2
+ and bh, al ; 20 c7 ; 0xfdbb6
+ inc bp ; 45 ; 0xfdbb8
+ sbb AL, strict byte 050h ; 1c 50 ; 0xfdbb9
+ inc bx ; 43 ; 0xfdbbb
+ dec cx ; 49 ; 0xfdbbc
+ and cl, ch ; 20 e9 ; 0xfdbbd
+ rol byte [bx+di], CL ; d2 01 ; 0xfdbbf
+ add byte [bx+si], al ; 00 00 ; 0xfdbc1
+ cmp dword [di+01ch], strict byte 0ffffffffh ; 66 83 7d 1c ff ; 0xfdbc3 pci32.c:333
+ jne short 0dbd7h ; 75 0d ; 0xfdbc8
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdbca pci32.c:334
+ xor ah, ah ; 30 e4 ; 0xfdbcd
+ or ah, 083h ; 80 cc 83 ; 0xfdbcf
+ jmp near 0dd8bh ; e9 b6 01 ; 0xfdbd2 pci32.c:335
+ add byte [bx+si], al ; 00 00 ; 0xfdbd5
+ xor bx, bx ; 31 db ; 0xfdbd7 pci32.c:337
+ db 00fh, 0b7h, 055h, 00ch
+ ; movzx dx, [di+00ch] ; 0f b7 55 0c ; 0xfdbd9
+ db 00fh, 0b7h, 045h, 020h
+ ; movzx ax, [di+020h] ; 0f b7 45 20 ; 0xfdbdd
+ sal ax, 010h ; c1 e0 10 ; 0xfdbe1
+ db 00fh, 0b7h, 04dh, 01ch
+ ; movzx cx, [di+01ch] ; 0f b7 4d 1c ; 0xfdbe4
+ or ax, cx ; 09 c8 ; 0xfdbe8
+ call 0da53h ; e8 66 fe ; 0xfdbea
+ db 0ffh
+ jmp word [bp+03dh] ; ff 66 3d ; 0xfdbee
+ db 0ffh
+ push word [di+00dh] ; ff 75 0d ; 0xfdbf2
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdbf5 pci32.c:339
+ xor ah, ah ; 30 e4 ; 0xfdbf8
+ or ah, 086h ; 80 cc 86 ; 0xfdbfa
+ jmp near 0dd8bh ; e9 8b 01 ; 0xfdbfd
+ add byte [bx+si], al ; 00 00 ; 0xfdc00
+ mov dword [di+018h], eax ; 66 89 45 18 ; 0xfdc02 pci32.c:340
+ jmp near 0dd93h ; e9 8a 01 ; 0xfdc06 pci32.c:345
+ add byte [bx+si], al ; 00 00 ; 0xfdc09
+ db 00fh, 0b7h, 055h, 00ch
+ ; movzx dx, [di+00ch] ; 0f b7 55 0c ; 0xfdc0b pci32.c:347
+ mov ax, word [di+020h] ; 8b 45 20 ; 0xfdc0f
+ mov bx, strict word 00001h ; bb 01 00 ; 0xfdc12
+ add byte [bx+si], al ; 00 00 ; 0xfdc15
+ call 0da53h ; e8 39 fe ; 0xfdc17
+ db 0ffh
+ jmp word [bp+03dh] ; ff 66 3d ; 0xfdc1b
+ db 0ffh
+ push word [di+00dh] ; ff 75 0d ; 0xfdc1f
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdc22 pci32.c:349
+ xor ah, ah ; 30 e4 ; 0xfdc25
+ or ah, 086h ; 80 cc 86 ; 0xfdc27
+ jmp near 0dd8bh ; e9 5e 01 ; 0xfdc2a pci32.c:350
+ add byte [bx+si], al ; 00 00 ; 0xfdc2d
+ mov dword [di+018h], eax ; 66 89 45 18 ; 0xfdc2f pci32.c:352
+ jmp near 0dd93h ; e9 5d 01 ; 0xfdc33 pci32.c:354
+ add byte [bx+si], al ; 00 00 ; 0xfdc36
+ cmp dword [di+008h], strict dword 00d720100h ; 66 81 7d 08 00 01 72 0d ; 0xfdc38 pci32.c:361
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdc40 pci32.c:362
+ xor ah, ah ; 30 e4 ; 0xfdc43
+ or ah, 087h ; 80 cc 87 ; 0xfdc45
+ jmp near 0dd8bh ; e9 40 01 ; 0xfdc48 pci32.c:363
+ add byte [bx+si], al ; 00 00 ; 0xfdc4b
+ db 00fh, 0b7h, 055h, 008h
+ ; movzx dx, [di+008h] ; 0f b7 55 08 ; 0xfdc4d pci32.c:365
+ db 00fh, 0b7h, 045h, 018h
+ ; movzx ax, [di+018h] ; 0f b7 45 18 ; 0xfdc51
+ call 0da31h ; e8 d9 fd ; 0xfdc55
+ db 0ffh
+ dec word [bp+di+02445h] ; ff 8b 45 24 ; 0xfdc59
+ xor ah, ah ; 30 e4 ; 0xfdc5d
+ cmp eax, strict dword 02172000ah ; 66 3d 0a 00 72 21 ; 0xfdc5f
+ jbe short 0dcd6h ; 76 6f ; 0xfdc65
+ cmp eax, strict dword 0840f000dh ; 66 3d 0d 00 0f 84 ; 0xfdc67
+ test ax, strict word 00000h ; a9 00 00 ; 0xfdc6d
+ add byte [bp+03dh], ah ; 00 66 3d ; 0xfdc70
+ or AL, strict byte 000h ; 0c 00 ; 0xfdc73
+ je near 0dcfch ; 0f 84 83 00 ; 0xfdc75
+ add byte [bx+si], al ; 00 00 ; 0xfdc79
+ cmp eax, strict dword 06374000bh ; 66 3d 0b 00 74 63 ; 0xfdc7b
+ jmp near 0dd93h ; e9 0f 01 ; 0xfdc81
+ add byte [bx+si], al ; 00 00 ; 0xfdc84
+ cmp eax, strict dword 02d740009h ; 66 3d 09 00 74 2d ; 0xfdc86
+ cmp eax, strict dword 0850f0008h ; 66 3d 08 00 0f 85 ; 0xfdc8c
+ inc word [bx+si] ; ff 00 ; 0xfdc92
+ add byte [bx+si], al ; 00 00 ; 0xfdc94
+ mov bx, word [di+020h] ; 8b 5d 20 ; 0xfdc96 pci32.c:368
+ xor bl, bl ; 30 db ; 0xfdc99
+ mov ax, word [di+008h] ; 8b 45 08 ; 0xfdc9b
+ xor ah, ah ; 30 e4 ; 0xfdc9e
+ and AL, strict byte 003h ; 24 03 ; 0xfdca0
+ db 00fh, 0b7h, 0d0h
+ ; movzx dx, ax ; 0f b7 d0 ; 0xfdca2
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xfdca5
+ add byte [bx+si], al ; 00 00 ; 0xfdca9
+ db 02bh, 0c0h
+ ; sub ax, ax ; 2b c0 ; 0xfdcab
+ in AL, DX ; ec ; 0xfdcad
+ or bx, ax ; 09 c3 ; 0xfdcae
+ mov dword [di+020h], ebx ; 66 89 5d 20 ; 0xfdcb0
+ jmp near 0dd93h ; e9 dc 00 ; 0xfdcb4 pci32.c:369
+ add byte [bx+si], al ; 00 00 ; 0xfdcb7
+ mov ax, word [di+008h] ; 8b 45 08 ; 0xfdcb9 pci32.c:371
+ xor ah, ah ; 30 e4 ; 0xfdcbc
+ and AL, strict byte 002h ; 24 02 ; 0xfdcbe
+ db 00fh, 0b7h, 0d0h
+ ; movzx dx, ax ; 0f b7 d0 ; 0xfdcc0
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xfdcc3
+ add byte [bx+si], al ; 00 00 ; 0xfdcc7
+ db 02bh, 0c0h
+ ; sub ax, ax ; 2b c0 ; 0xfdcc9
+ in eax, DX ; 66 ed ; 0xfdccb
+ mov dword [di+020h], eax ; 66 89 45 20 ; 0xfdccd
+ jmp near 0dd93h ; e9 bf 00 ; 0xfdcd1 pci32.c:372
+ add byte [bx+si], al ; 00 00 ; 0xfdcd4
+ mov dx, 00cfch ; ba fc 0c ; 0xfdcd6 pci32.c:374
+ add byte [bx+si], al ; 00 00 ; 0xfdcd9
+ in ax, DX ; ed ; 0xfdcdb
+ mov word [di+020h], ax ; 89 45 20 ; 0xfdcdc
+ jmp near 0dd93h ; e9 b1 00 ; 0xfdcdf pci32.c:375
+ add byte [bx+si], al ; 00 00 ; 0xfdce2
+ mov ax, word [di+020h] ; 8b 45 20 ; 0xfdce4 pci32.c:377
+ mov dx, word [di+008h] ; 8b 55 08 ; 0xfdce7
+ xor dh, dh ; 30 f6 ; 0xfdcea
+ and dl, 003h ; 80 e2 03 ; 0xfdcec
+ db 00fh, 0b7h, 0d2h
+ ; movzx dx, dx ; 0f b7 d2 ; 0xfdcef
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xfdcf2
+ add byte [bx+si], al ; 00 00 ; 0xfdcf6
+ out DX, AL ; ee ; 0xfdcf8
+ jmp near 0dd93h ; e9 97 00 ; 0xfdcf9 pci32.c:378
+ add byte [bx+si], al ; 00 00 ; 0xfdcfc
+ db 00fh, 0b7h, 045h, 020h
+ ; movzx ax, [di+020h] ; 0f b7 45 20 ; 0xfdcfe pci32.c:380
+ mov dx, word [di+008h] ; 8b 55 08 ; 0xfdd02
+ xor dh, dh ; 30 f6 ; 0xfdd05
+ and dl, 002h ; 80 e2 02 ; 0xfdd07
+ db 00fh, 0b7h, 0d2h
+ ; movzx dx, dx ; 0f b7 d2 ; 0xfdd0a
+ add dx, 00cfch ; 81 c2 fc 0c ; 0xfdd0d
+ add byte [bx+si], al ; 00 00 ; 0xfdd11
+ out DX, eax ; 66 ef ; 0xfdd13
+ jmp near 0dd93h ; e9 7b 00 ; 0xfdd15 pci32.c:381
+ add byte [bx+si], al ; 00 00 ; 0xfdd18
+ mov ax, word [di+020h] ; 8b 45 20 ; 0xfdd1a pci32.c:383
+ mov dx, 00cfch ; ba fc 0c ; 0xfdd1d
+ add byte [bx+si], al ; 00 00 ; 0xfdd20
+ out DX, ax ; ef ; 0xfdd22
+ jmp short 0dd95h ; eb 70 ; 0xfdd23 pci32.c:387
+ db 00fh, 0b7h, 045h, 008h
+ ; movzx ax, [di+008h] ; 0f b7 45 08 ; 0xfdd25 pci32.c:389
+ mov es, [di+028h] ; 8e 45 28 ; 0xfdd29
+ mov [di-010h], es ; 8c 45 f0 ; 0xfdd2c
+ mov bx, ax ; 89 c3 ; 0xfdd2f
+ mov edx, dword [di] ; 66 8b 15 ; 0xfdd31 pci32.c:393
+ xor bl, 000h ; 80 f3 00 ; 0xfdd34
+ add byte [bp+026h], ah ; 00 66 26 ; 0xfdd37
+ cmp dx, word [bx+si] ; 3b 10 ; 0xfdd3a
+ jbe short 0dd50h ; 76 12 ; 0xfdd3c
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdd3e pci32.c:394
+ xor ah, ah ; 30 e4 ; 0xfdd41
+ or ah, 089h ; 80 cc 89 ; 0xfdd43
+ mov dword [di+024h], eax ; 66 89 45 24 ; 0xfdd46
+ or word [di+02ch], strict byte 00001h ; 83 4d 2c 01 ; 0xfdd4a pci32.c:395
+ jmp short 0dd76h ; eb 26 ; 0xfdd4e pci32.c:396
+ db 00fh, 0b7h, 0cah
+ ; movzx cx, dx ; 0f b7 ca ; 0xfdd50 pci32.c:397
+ db 066h, 026h, 08bh, 050h, 006h
+ ; mov edx, dword [es:bx+si+006h] ; 66 26 8b 50 06 ; 0xfdd53
+ mov word [di-014h], dx ; 89 55 ec ; 0xfdd58
+ mov di, word [es:bx+si+002h] ; 26 8b 78 02 ; 0xfdd5b
+ mov dx, ds ; 8c da ; 0xfdd5f
+ mov si, 0f1a0h ; be a0 f1 ; 0xfdd61
+ add byte [bx+si], al ; 00 00 ; 0xfdd64
+ mov es, [di-014h] ; 8e 45 ec ; 0xfdd66
+ push DS ; 1e ; 0xfdd69
+ db 066h, 08eh, 0dah
+ ; mov ds, edx ; 66 8e da ; 0xfdd6a
+ rep movsb ; f3 a4 ; 0xfdd6d
+ pop DS ; 1f ; 0xfdd6f
+ mov dword [di+018h], strict dword 0a1660a00h ; 66 c7 45 18 00 0a 66 a1 ; 0xfdd70 pci32.c:399
+ xor bl, 000h ; 80 f3 00 ; 0xfdd78
+ add byte [bp-00fbbh], cl ; 00 8e 45 f0 ; 0xfdd7b
+ db 066h, 026h, 089h, 003h
+ ; mov dword [es:bp+di], eax ; 66 26 89 03 ; 0xfdd7f
+ jmp short 0dd95h ; eb 10 ; 0xfdd83 pci32.c:402
+ mov ax, word [di+024h] ; 8b 45 24 ; 0xfdd85 pci32.c:405
+ xor ah, ah ; 30 e4 ; 0xfdd88
+ or ah, 081h ; 80 cc 81 ; 0xfdd8a
+ mov dword [di+024h], eax ; 66 89 45 24 ; 0xfdd8d
+ or word [di+02ch], strict byte 00001h ; 83 4d 2c 01 ; 0xfdd91 pci32.c:406
+ lea sp, [di-00ch] ; 8d 65 f4 ; 0xfdd95 pci32.c:408
+ pop di ; 5f ; 0xfdd98
+ pop si ; 5e ; 0xfdd99
+ pop bx ; 5b ; 0xfdd9a
+ pop bp ; 5d ; 0xfdd9b
+ retn ; c3 ; 0xfdd9c
+
+ ; Padding 0x3 bytes at 0xfdd9d
+ times 3 db 0
+
+section BIOS32CONST progbits vstart=0xdda0 align=1 ; size=0x0 class=FAR_DATA group=BIOS32_GROUP
+
+section BIOS32CONST2 progbits vstart=0xdda0 align=1 ; size=0x0 class=FAR_DATA group=BIOS32_GROUP
+
+section BIOS32_DATA progbits vstart=0xdda0 align=1 ; size=0x0 class=FAR_DATA group=BIOS32_GROUP
+
+ ; Padding 0x260 bytes at 0xfdda0
+ times 608 db 0
+
+section BIOSSEG progbits vstart=0xe000 align=1 ; size=0x2000 class=CODE group=AUTO
+ ; disGetNextSymbol 0xfe000 LB 0x2000 -> off=0x0 cb=0000000000000030 uValue=00000000000f0000 'biosorg_check_before_or_at_0E02Eh'
+biosorg_check_before_or_at_0E02Eh: ; 0xfe000 LB 0x30
+ times 0x2e db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe030 LB 0x1fd0 -> off=0x0 cb=0000000000000004 uValue=00000000000f0030 'eoi_both_pics'
+eoi_both_pics: ; 0xfe030 LB 0x4
+ mov AL, strict byte 020h ; b0 20 ; 0xfe030 orgs.asm:238
+ out strict byte 0a0h, AL ; e6 a0 ; 0xfe032 orgs.asm:239
+ ; disGetNextSymbol 0xfe034 LB 0x1fcc -> off=0x0 cb=0000000000000005 uValue=00000000000f0034 'eoi_master_pic'
+eoi_master_pic: ; 0xfe034 LB 0x5
+ mov AL, strict byte 020h ; b0 20 ; 0xfe034 orgs.asm:241
+ out strict byte 020h, AL ; e6 20 ; 0xfe036 orgs.asm:242
+ retn ; c3 ; 0xfe038 orgs.asm:243
+ ; disGetNextSymbol 0xfe039 LB 0x1fc7 -> off=0x0 cb=000000000000000b uValue=0000000000000039 'set_int_vects'
+set_int_vects: ; 0xfe039 LB 0xb
+ mov word [bx], ax ; 89 07 ; 0xfe039 orgs.asm:250
+ mov word [bx+002h], dx ; 89 57 02 ; 0xfe03b orgs.asm:251
+ add bx, strict byte 00004h ; 83 c3 04 ; 0xfe03e orgs.asm:252
+ loop 0e039h ; e2 f6 ; 0xfe041 orgs.asm:253
+ retn ; c3 ; 0xfe043 orgs.asm:254
+ ; disGetNextSymbol 0xfe044 LB 0x1fbc -> off=0x0 cb=0000000000000006 uValue=00000000000f0044 'eoi_jmp_post'
+eoi_jmp_post: ; 0xfe044 LB 0x6
+ in AL, strict byte 060h ; e4 60 ; 0xfe044 orgs.asm:262
+ mov AL, strict byte 020h ; b0 20 ; 0xfe046 orgs.asm:263
+ out strict byte 020h, AL ; e6 20 ; 0xfe048 orgs.asm:264
+ ; disGetNextSymbol 0xfe04a LB 0x1fb6 -> off=0x0 cb=0000000000000009 uValue=00000000000f004a 'no_eoi_jmp_post'
+no_eoi_jmp_post: ; 0xfe04a LB 0x9
+ mov ax, strict word 00040h ; b8 40 00 ; 0xfe04a orgs.asm:267
+ mov ds, ax ; 8e d8 ; 0xfe04d orgs.asm:268
+ jmp far [word 00067h] ; ff 2e 67 00 ; 0xfe04f orgs.asm:269
+ ; disGetNextSymbol 0xfe053 LB 0x1fad -> off=0x0 cb=0000000000000002 uValue=00000000000f0053 'seg_40_value'
+seg_40_value: ; 0xfe053 LB 0x2
+ inc ax ; 40 ; 0xfe053
+ times 0x1 db 0
+ ; disGetNextSymbol 0xfe055 LB 0x1fab -> off=0x0 cb=0000000000000006 uValue=00000000000f0055 'biosorg_check_before_or_at_0E059h'
+biosorg_check_before_or_at_0E059h: ; 0xfe055 LB 0x6
+ add byte [bx+si], al ; 00 00 ; 0xfe055
+ add byte [bx+si], al ; 00 00 ; 0xfe057
+ pop ax ; 58 ; 0xfe059
+ dec bp ; 4d ; 0xfe05a
+ ; disGetNextSymbol 0xfe05b LB 0x1fa5 -> off=0x0 cb=0000000000000068 uValue=00000000000f005b 'post'
+post: ; 0xfe05b LB 0x68
+ cli ; fa ; 0xfe05b orgs.asm:278
+ jmp short 0e064h ; eb 06 ; 0xfe05c orgs.asm:289
+ mov AL, strict byte 001h ; b0 01 ; 0xfe05e orgs.asm:295
+ out strict byte 092h, AL ; e6 92 ; 0xfe060 orgs.asm:296
+ jmp short 0e062h ; eb fe ; 0xfe062 orgs.asm:297
+ mov AL, strict byte 00fh ; b0 0f ; 0xfe064 orgs.asm:302
+ out strict byte 070h, AL ; e6 70 ; 0xfe066 orgs.asm:303
+ in AL, strict byte 071h ; e4 71 ; 0xfe068 orgs.asm:304
+ xchg ah, al ; 86 c4 ; 0xfe06a orgs.asm:307
+ in AL, strict byte 064h ; e4 64 ; 0xfe06c orgs.asm:311
+ test AL, strict byte 004h ; a8 04 ; 0xfe06e orgs.asm:312
+ je short 0e085h ; 74 13 ; 0xfe070 orgs.asm:313
+ db 08ah, 0c4h
+ ; mov al, ah ; 8a c4 ; 0xfe072 orgs.asm:316
+ db 00ah, 0c0h
+ ; or al, al ; 0a c0 ; 0xfe074 orgs.asm:317
+ jne short 0e085h ; 75 0d ; 0xfe076 orgs.asm:318
+ mov ds, [cs:0e053h] ; 2e 8e 1e 53 e0 ; 0xfe078 orgs.asm:324
+ cmp word [word 00072h], 01234h ; 81 3e 72 00 34 12 ; 0xfe07d orgs.asm:325
+ jne short 0e05eh ; 75 d9 ; 0xfe083 orgs.asm:326
+ mov AL, strict byte 00fh ; b0 0f ; 0xfe085 orgs.asm:330
+ out strict byte 070h, AL ; e6 70 ; 0xfe087 orgs.asm:331
+ mov AL, strict byte 000h ; b0 00 ; 0xfe089 orgs.asm:332
+ out strict byte 071h, AL ; e6 71 ; 0xfe08b orgs.asm:333
+ db 08ah, 0c4h
+ ; mov al, ah ; 8a c4 ; 0xfe08d orgs.asm:337
+ cmp AL, strict byte 009h ; 3c 09 ; 0xfe08f orgs.asm:338
+ je short 0e0a5h ; 74 12 ; 0xfe091 orgs.asm:339
+ cmp AL, strict byte 00ah ; 3c 0a ; 0xfe093 orgs.asm:340
+ je short 0e0a5h ; 74 0e ; 0xfe095 orgs.asm:341
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xfe097 orgs.asm:343
+ out strict byte 00dh, AL ; e6 0d ; 0xfe099 orgs.asm:346
+ out strict byte 0dah, AL ; e6 da ; 0xfe09b orgs.asm:347
+ mov AL, strict byte 0c0h ; b0 c0 ; 0xfe09d orgs.asm:350
+ out strict byte 0d6h, AL ; e6 d6 ; 0xfe09f orgs.asm:351
+ mov AL, strict byte 000h ; b0 00 ; 0xfe0a1 orgs.asm:352
+ out strict byte 0d4h, AL ; e6 d4 ; 0xfe0a3 orgs.asm:353
+ db 08ah, 0c4h
+ ; mov al, ah ; 8a c4 ; 0xfe0a5 orgs.asm:357
+ cmp AL, strict byte 000h ; 3c 00 ; 0xfe0a7 orgs.asm:358
+ je short 0e0c3h ; 74 18 ; 0xfe0a9 orgs.asm:359
+ cmp AL, strict byte 00dh ; 3c 0d ; 0xfe0ab orgs.asm:361
+ jnc short 0e0c3h ; 73 14 ; 0xfe0ad orgs.asm:362
+ cmp AL, strict byte 009h ; 3c 09 ; 0xfe0af orgs.asm:363
+ jne short 0e0b6h ; 75 03 ; 0xfe0b1 orgs.asm:364
+ jmp near 0e350h ; e9 9a 02 ; 0xfe0b3 orgs.asm:365
+ mov sp, 00400h ; bc 00 04 ; 0xfe0b6 orgs.asm:368
+ cmp AL, strict byte 005h ; 3c 05 ; 0xfe0b9 orgs.asm:370
+ je short 0e044h ; 74 87 ; 0xfe0bb orgs.asm:371
+ cmp AL, strict byte 00ah ; 3c 0a ; 0xfe0bd orgs.asm:373
+ je short 0e04ah ; 74 89 ; 0xfe0bf orgs.asm:374
+ jmp short 0e0c3h ; eb 00 ; 0xfe0c1 orgs.asm:378
+ ; disGetNextSymbol 0xfe0c3 LB 0x1f3d -> off=0x0 cb=00000000000001f3 uValue=00000000000f00c3 'normal_post'
+normal_post: ; 0xfe0c3 LB 0x1f3
+ mov ax, 07800h ; b8 00 78 ; 0xfe0c3 orgs.asm:387
+ db 08bh, 0e0h
+ ; mov sp, ax ; 8b e0 ; 0xfe0c6 orgs.asm:388
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe0c8 orgs.asm:389
+ mov ds, ax ; 8e d8 ; 0xfe0ca orgs.asm:390
+ mov ss, ax ; 8e d0 ; 0xfe0cc orgs.asm:391
+ mov es, ax ; 8e c0 ; 0xfe0ce orgs.asm:395
+ db 033h, 0ffh
+ ; xor di, di ; 33 ff ; 0xfe0d0 orgs.asm:396
+ cld ; fc ; 0xfe0d2 orgs.asm:397
+ mov cx, 00239h ; b9 39 02 ; 0xfe0d3 orgs.asm:398
+ rep stosw ; f3 ab ; 0xfe0d6 orgs.asm:399
+ inc di ; 47 ; 0xfe0d8 orgs.asm:400
+ inc di ; 47 ; 0xfe0d9 orgs.asm:401
+ mov cx, 005c6h ; b9 c6 05 ; 0xfe0da orgs.asm:402
+ rep stosw ; f3 ab ; 0xfe0dd orgs.asm:403
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe0df orgs.asm:407
+ add bx, 01000h ; 81 c3 00 10 ; 0xfe0e1 orgs.asm:409
+ cmp bx, 09000h ; 81 fb 00 90 ; 0xfe0e5 orgs.asm:410
+ jnc short 0e0f6h ; 73 0b ; 0xfe0e9 orgs.asm:411
+ mov es, bx ; 8e c3 ; 0xfe0eb orgs.asm:412
+ db 033h, 0ffh
+ ; xor di, di ; 33 ff ; 0xfe0ed orgs.asm:413
+ mov cx, 08000h ; b9 00 80 ; 0xfe0ef orgs.asm:414
+ rep stosw ; f3 ab ; 0xfe0f2 orgs.asm:415
+ jmp short 0e0e1h ; eb eb ; 0xfe0f4 orgs.asm:416
+ mov es, bx ; 8e c3 ; 0xfe0f6 orgs.asm:418
+ db 033h, 0ffh
+ ; xor di, di ; 33 ff ; 0xfe0f8 orgs.asm:419
+ mov cx, 07ff8h ; b9 f8 7f ; 0xfe0fa orgs.asm:420
+ rep stosw ; f3 ab ; 0xfe0fd orgs.asm:421
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe0ff orgs.asm:422
+ push CS ; 0e ; 0xfe101 orgs.asm:104
+ pop DS ; 1f ; 0xfe102 orgs.asm:105
+ cld ; fc ; 0xfe103 orgs.asm:106
+ call 01715h ; e8 0e 36 ; 0xfe104 orgs.asm:426
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe107 orgs.asm:433
+ mov ds, bx ; 8e db ; 0xfe109 orgs.asm:434
+ mov cx, strict word 00060h ; b9 60 00 ; 0xfe10b orgs.asm:435
+ mov ax, 0ff53h ; b8 53 ff ; 0xfe10e orgs.asm:436
+ mov dx, 0f000h ; ba 00 f0 ; 0xfe111 orgs.asm:437
+ call 0e039h ; e8 22 ff ; 0xfe114 orgs.asm:438
+ mov bx, 001a0h ; bb a0 01 ; 0xfe117 orgs.asm:443
+ mov cx, strict word 00010h ; b9 10 00 ; 0xfe11a orgs.asm:444
+ call 0e039h ; e8 19 ff ; 0xfe11d orgs.asm:445
+ mov ax, 0027fh ; b8 7f 02 ; 0xfe120 orgs.asm:448
+ mov word [00413h], ax ; a3 13 04 ; 0xfe123 orgs.asm:449
+ mov ax, 0e9dah ; b8 da e9 ; 0xfe126 orgs.asm:95
+ mov word [00018h], ax ; a3 18 00 ; 0xfe129 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe12c orgs.asm:97
+ mov word [0001ah], ax ; a3 1a 00 ; 0xfe12f orgs.asm:98
+ mov ax, 0f84dh ; b8 4d f8 ; 0xfe132 orgs.asm:95
+ mov word [00044h], ax ; a3 44 00 ; 0xfe135 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe138 orgs.asm:97
+ mov word [00046h], ax ; a3 46 00 ; 0xfe13b orgs.asm:98
+ mov ax, 0f841h ; b8 41 f8 ; 0xfe13e orgs.asm:95
+ mov word [00048h], ax ; a3 48 00 ; 0xfe141 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe144 orgs.asm:97
+ mov word [0004ah], ax ; a3 4a 00 ; 0xfe147 orgs.asm:98
+ mov ax, 0f859h ; b8 59 f8 ; 0xfe14a orgs.asm:95
+ mov word [00054h], ax ; a3 54 00 ; 0xfe14d orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe150 orgs.asm:97
+ mov word [00056h], ax ; a3 56 00 ; 0xfe153 orgs.asm:98
+ mov ax, 0efd4h ; b8 d4 ef ; 0xfe156 orgs.asm:95
+ mov word [0005ch], ax ; a3 5c 00 ; 0xfe159 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe15c orgs.asm:97
+ mov word [0005eh], ax ; a3 5e 00 ; 0xfe15f orgs.asm:98
+ mov ax, 0f0a4h ; b8 a4 f0 ; 0xfe162 orgs.asm:95
+ mov word [00060h], ax ; a3 60 00 ; 0xfe165 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe168 orgs.asm:97
+ mov word [00062h], ax ; a3 62 00 ; 0xfe16b orgs.asm:98
+ mov ax, 0e6f2h ; b8 f2 e6 ; 0xfe16e orgs.asm:95
+ mov word [00064h], ax ; a3 64 00 ; 0xfe171 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe174 orgs.asm:97
+ mov word [00066h], ax ; a3 66 00 ; 0xfe177 orgs.asm:98
+ mov ax, 0effbh ; b8 fb ef ; 0xfe17a orgs.asm:95
+ mov word [00070h], ax ; a3 70 00 ; 0xfe17d orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe180 orgs.asm:97
+ mov word [00072h], ax ; a3 72 00 ; 0xfe183 orgs.asm:98
+ call 0e794h ; e8 0b 06 ; 0xfe186 orgs.asm:465
+ mov ax, 0fe6eh ; b8 6e fe ; 0xfe189 orgs.asm:95
+ mov word [00068h], ax ; a3 68 00 ; 0xfe18c orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe18f orgs.asm:97
+ mov word [0006ah], ax ; a3 6a 00 ; 0xfe192 orgs.asm:98
+ mov ax, 0fea5h ; b8 a5 fe ; 0xfe195 orgs.asm:95
+ mov word [00020h], ax ; a3 20 00 ; 0xfe198 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe19b orgs.asm:97
+ mov word [00022h], ax ; a3 22 00 ; 0xfe19e orgs.asm:98
+ mov AL, strict byte 034h ; b0 34 ; 0xfe1a1 orgs.asm:476
+ out strict byte 043h, AL ; e6 43 ; 0xfe1a3 orgs.asm:477
+ mov AL, strict byte 000h ; b0 00 ; 0xfe1a5 orgs.asm:478
+ out strict byte 040h, AL ; e6 40 ; 0xfe1a7 orgs.asm:479
+ out strict byte 040h, AL ; e6 40 ; 0xfe1a9 orgs.asm:480
+ mov ax, 0f065h ; b8 65 f0 ; 0xfe1ab orgs.asm:95
+ mov word [00040h], ax ; a3 40 00 ; 0xfe1ae orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe1b1 orgs.asm:97
+ mov word [00042h], ax ; a3 42 00 ; 0xfe1b4 orgs.asm:98
+ mov ax, 0e987h ; b8 87 e9 ; 0xfe1b7 orgs.asm:95
+ mov word [00024h], ax ; a3 24 00 ; 0xfe1ba orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe1bd orgs.asm:97
+ mov word [00026h], ax ; a3 26 00 ; 0xfe1c0 orgs.asm:98
+ mov ax, 0e82eh ; b8 2e e8 ; 0xfe1c3 orgs.asm:95
+ mov word [00058h], ax ; a3 58 00 ; 0xfe1c6 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe1c9 orgs.asm:97
+ mov word [0005ah], ax ; a3 5a 00 ; 0xfe1cc orgs.asm:98
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe1cf orgs.asm:489
+ mov ds, ax ; 8e d8 ; 0xfe1d1 orgs.asm:490
+ mov byte [00417h], AL ; a2 17 04 ; 0xfe1d3 orgs.asm:492
+ mov byte [00418h], AL ; a2 18 04 ; 0xfe1d6 orgs.asm:493
+ mov byte [00419h], AL ; a2 19 04 ; 0xfe1d9 orgs.asm:494
+ mov byte [00471h], AL ; a2 71 04 ; 0xfe1dc orgs.asm:495
+ mov byte [00497h], AL ; a2 97 04 ; 0xfe1df orgs.asm:496
+ mov AL, strict byte 010h ; b0 10 ; 0xfe1e2 orgs.asm:497
+ mov byte [00496h], AL ; a2 96 04 ; 0xfe1e4 orgs.asm:498
+ mov bx, strict word 0001eh ; bb 1e 00 ; 0xfe1e7 orgs.asm:500
+ mov word [0041ah], bx ; 89 1e 1a 04 ; 0xfe1ea orgs.asm:501
+ mov word [0041ch], bx ; 89 1e 1c 04 ; 0xfe1ee orgs.asm:502
+ mov word [00480h], bx ; 89 1e 80 04 ; 0xfe1f2 orgs.asm:503
+ mov bx, strict word 0003eh ; bb 3e 00 ; 0xfe1f6 orgs.asm:504
+ mov word [00482h], bx ; 89 1e 82 04 ; 0xfe1f9 orgs.asm:505
+ mov AL, strict byte 014h ; b0 14 ; 0xfe1fd orgs.asm:508
+ out strict byte 070h, AL ; e6 70 ; 0xfe1ff orgs.asm:509
+ in AL, strict byte 071h ; e4 71 ; 0xfe201 orgs.asm:510
+ mov byte [00410h], AL ; a2 10 04 ; 0xfe203 orgs.asm:511
+ push DS ; 1e ; 0xfe206 orgs.asm:513
+ push CS ; 0e ; 0xfe207 orgs.asm:104
+ pop DS ; 1f ; 0xfe208 orgs.asm:105
+ cld ; fc ; 0xfe209 orgs.asm:106
+ mov ax, 0c000h ; b8 00 c0 ; 0xfe20a orgs.asm:518
+ mov dx, 0c800h ; ba 00 c8 ; 0xfe20d orgs.asm:519
+ call 01600h ; e8 ed 33 ; 0xfe210 orgs.asm:520
+ call 04f76h ; e8 60 6d ; 0xfe213 orgs.asm:523
+ pop DS ; 1f ; 0xfe216 orgs.asm:524
+ mov ax, 0ff53h ; b8 53 ff ; 0xfe217 orgs.asm:95
+ mov word [0003ch], ax ; a3 3c 00 ; 0xfe21a orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe21d orgs.asm:97
+ mov word [0003eh], ax ; a3 3e 00 ; 0xfe220 orgs.asm:98
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe223 orgs.asm:528
+ mov ds, ax ; 8e d8 ; 0xfe225 orgs.asm:529
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe227 orgs.asm:530
+ mov CL, strict byte 014h ; b1 14 ; 0xfe229 orgs.asm:531
+ mov dx, 00378h ; ba 78 03 ; 0xfe22b orgs.asm:532
+ call 0ed0ah ; e8 d9 0a ; 0xfe22e orgs.asm:533
+ mov dx, 00278h ; ba 78 02 ; 0xfe231 orgs.asm:534
+ call 0ed0ah ; e8 d3 0a ; 0xfe234 orgs.asm:535
+ push cx ; 51 ; 0xfe237 orgs.asm:203
+ mov CL, strict byte 00eh ; b1 0e ; 0xfe238 orgs.asm:204
+ sal bx, CL ; d3 e3 ; 0xfe23a orgs.asm:205
+ pop cx ; 59 ; 0xfe23c orgs.asm:206
+ mov ax, word [00410h] ; a1 10 04 ; 0xfe23d orgs.asm:537
+ and ax, 03fffh ; 25 ff 3f ; 0xfe240 orgs.asm:538
+ db 00bh, 0c3h
+ ; or ax, bx ; 0b c3 ; 0xfe243 orgs.asm:539
+ mov word [00410h], ax ; a3 10 04 ; 0xfe245 orgs.asm:540
+ mov ax, 0e754h ; b8 54 e7 ; 0xfe248 orgs.asm:95
+ mov word [0002ch], ax ; a3 2c 00 ; 0xfe24b orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe24e orgs.asm:97
+ mov word [0002eh], ax ; a3 2e 00 ; 0xfe251 orgs.asm:98
+ mov ax, 0e754h ; b8 54 e7 ; 0xfe254 orgs.asm:95
+ mov word [00030h], ax ; a3 30 00 ; 0xfe257 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe25a orgs.asm:97
+ mov word [00032h], ax ; a3 32 00 ; 0xfe25d orgs.asm:98
+ mov ax, 0e739h ; b8 39 e7 ; 0xfe260 orgs.asm:95
+ mov word [00050h], ax ; a3 50 00 ; 0xfe263 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe266 orgs.asm:97
+ mov word [00052h], ax ; a3 52 00 ; 0xfe269 orgs.asm:98
+ db 033h, 0dbh
+ ; xor bx, bx ; 33 db ; 0xfe26c orgs.asm:546
+ mov CL, strict byte 00ah ; b1 0a ; 0xfe26e orgs.asm:547
+ mov dx, 003f8h ; ba f8 03 ; 0xfe270 orgs.asm:548
+ call 0ed28h ; e8 b2 0a ; 0xfe273 orgs.asm:549
+ mov dx, 002f8h ; ba f8 02 ; 0xfe276 orgs.asm:550
+ call 0ed28h ; e8 ac 0a ; 0xfe279 orgs.asm:551
+ mov dx, 003e8h ; ba e8 03 ; 0xfe27c orgs.asm:552
+ call 0ed28h ; e8 a6 0a ; 0xfe27f orgs.asm:553
+ mov dx, 002e8h ; ba e8 02 ; 0xfe282 orgs.asm:554
+ call 0ed28h ; e8 a0 0a ; 0xfe285 orgs.asm:555
+ push cx ; 51 ; 0xfe288 orgs.asm:203
+ mov CL, strict byte 009h ; b1 09 ; 0xfe289 orgs.asm:204
+ sal bx, CL ; d3 e3 ; 0xfe28b orgs.asm:205
+ pop cx ; 59 ; 0xfe28d orgs.asm:206
+ mov ax, word [00410h] ; a1 10 04 ; 0xfe28e orgs.asm:557
+ and ax, 0f1ffh ; 25 ff f1 ; 0xfe291 orgs.asm:558
+ db 00bh, 0c3h
+ ; or ax, bx ; 0b c3 ; 0xfe294 orgs.asm:559
+ mov word [00410h], ax ; a3 10 04 ; 0xfe296 orgs.asm:560
+ mov ax, 0ff53h ; b8 53 ff ; 0xfe299 orgs.asm:95
+ mov word [00128h], ax ; a3 28 01 ; 0xfe29c orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe29f orgs.asm:97
+ mov word [0012ah], ax ; a3 2a 01 ; 0xfe2a2 orgs.asm:98
+ mov ax, 0f8f1h ; b8 f1 f8 ; 0xfe2a5 orgs.asm:95
+ mov word [001c0h], ax ; a3 c0 01 ; 0xfe2a8 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe2ab orgs.asm:97
+ mov word [001c2h], ax ; a3 c2 01 ; 0xfe2ae orgs.asm:98
+ call 0ede3h ; e8 2f 0b ; 0xfe2b1 orgs.asm:566
+ jmp short 0e303h ; eb 4d ; 0xfe2b4 orgs.asm:568
+ ; disGetNextSymbol 0xfe2b6 LB 0x1d4a -> off=0x0 cb=000000000000000d uValue=00000000000f02b6 'biosorg_check_before_or_at_0E2C1h'
+biosorg_check_before_or_at_0E2C1h: ; 0xfe2b6 LB 0xd
+ times 0xb db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe2c3 LB 0x1d3d -> off=0x0 cb=0000000000000007 uValue=00000000000f02c3 'nmi'
+nmi: ; 0xfe2c3 LB 0x7
+ push CS ; 0e ; 0xfe2c3 orgs.asm:104
+ pop DS ; 1f ; 0xfe2c4 orgs.asm:105
+ cld ; fc ; 0xfe2c5 orgs.asm:106
+ call 016ebh ; e8 22 34 ; 0xfe2c6 orgs.asm:577
+ iret ; cf ; 0xfe2c9 orgs.asm:578
+ ; disGetNextSymbol 0xfe2ca LB 0x1d36 -> off=0x0 cb=0000000000000008 uValue=00000000000f02ca 'int75_handler'
+int75_handler: ; 0xfe2ca LB 0x8
+ out strict byte 0f0h, AL ; e6 f0 ; 0xfe2ca orgs.asm:581
+ call 0e030h ; e8 61 fd ; 0xfe2cc orgs.asm:582
+ int 002h ; cd 02 ; 0xfe2cf orgs.asm:583
+ iret ; cf ; 0xfe2d1 orgs.asm:584
+ ; disGetNextSymbol 0xfe2d2 LB 0x1d2e -> off=0x0 cb=00000000000000a7 uValue=00000000000f02d2 'hard_drive_post'
+hard_drive_post: ; 0xfe2d2 LB 0xa7
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe2d2 orgs.asm:589
+ mov ds, ax ; 8e d8 ; 0xfe2d4 orgs.asm:590
+ mov byte [00474h], AL ; a2 74 04 ; 0xfe2d6 orgs.asm:592
+ mov byte [00477h], AL ; a2 77 04 ; 0xfe2d9 orgs.asm:593
+ mov byte [0048ch], AL ; a2 8c 04 ; 0xfe2dc orgs.asm:594
+ mov byte [0048dh], AL ; a2 8d 04 ; 0xfe2df orgs.asm:595
+ mov byte [0048eh], AL ; a2 8e 04 ; 0xfe2e2 orgs.asm:596
+ mov AL, strict byte 0c0h ; b0 c0 ; 0xfe2e5 orgs.asm:597
+ mov byte [00476h], AL ; a2 76 04 ; 0xfe2e7 orgs.asm:598
+ mov ax, 0e3feh ; b8 fe e3 ; 0xfe2ea orgs.asm:95
+ mov word [0004ch], ax ; a3 4c 00 ; 0xfe2ed orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe2f0 orgs.asm:97
+ mov word [0004eh], ax ; a3 4e 00 ; 0xfe2f3 orgs.asm:98
+ mov ax, 0f8dfh ; b8 df f8 ; 0xfe2f6 orgs.asm:95
+ mov word [001d8h], ax ; a3 d8 01 ; 0xfe2f9 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe2fc orgs.asm:97
+ mov word [001dah], ax ; a3 da 01 ; 0xfe2ff orgs.asm:98
+ retn ; c3 ; 0xfe302 orgs.asm:603
+ mov ax, 0f8a5h ; b8 a5 f8 ; 0xfe303 orgs.asm:95
+ mov word [001d0h], ax ; a3 d0 01 ; 0xfe306 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe309 orgs.asm:97
+ mov word [001d2h], ax ; a3 d2 01 ; 0xfe30c orgs.asm:98
+ mov ax, 0e2cah ; b8 ca e2 ; 0xfe30f orgs.asm:95
+ mov word [001d4h], ax ; a3 d4 01 ; 0xfe312 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe315 orgs.asm:97
+ mov word [001d6h], ax ; a3 d6 01 ; 0xfe318 orgs.asm:98
+ call 0e76fh ; e8 51 04 ; 0xfe31b orgs.asm:615
+ push CS ; 0e ; 0xfe31e orgs.asm:104
+ pop DS ; 1f ; 0xfe31f orgs.asm:105
+ cld ; fc ; 0xfe320 orgs.asm:106
+ call 01c5eh ; e8 3a 39 ; 0xfe321 orgs.asm:629
+ call 020efh ; e8 c8 3d ; 0xfe324 orgs.asm:630
+ sti ; fb ; 0xfe327 orgs.asm:637
+ call 094cdh ; e8 a2 b1 ; 0xfe328 orgs.asm:638
+ cli ; fa ; 0xfe32b orgs.asm:639
+ call 0830ch ; e8 dd 9f ; 0xfe32c orgs.asm:644
+ call 0ed4ch ; e8 1a 0a ; 0xfe32f orgs.asm:648
+ call 0e2d2h ; e8 9d ff ; 0xfe332 orgs.asm:651
+ push CS ; 0e ; 0xfe335 orgs.asm:104
+ pop DS ; 1f ; 0xfe336 orgs.asm:105
+ cld ; fc ; 0xfe337 orgs.asm:106
+ mov ax, 0c800h ; b8 00 c8 ; 0xfe338 orgs.asm:655
+ mov dx, 0f000h ; ba 00 f0 ; 0xfe33b orgs.asm:656
+ call 01600h ; e8 bf 32 ; 0xfe33e orgs.asm:657
+ call 01739h ; e8 f5 33 ; 0xfe341 orgs.asm:671
+ call 03be1h ; e8 9a 58 ; 0xfe344 orgs.asm:674
+ sti ; fb ; 0xfe347 orgs.asm:677
+ int 019h ; cd 19 ; 0xfe348 orgs.asm:678
+ sti ; fb ; 0xfe34a orgs.asm:680
+ hlt ; f4 ; 0xfe34b orgs.asm:682
+ jmp short 0e34bh ; eb fd ; 0xfe34c orgs.asm:683
+ cli ; fa ; 0xfe34e orgs.asm:684
+ hlt ; f4 ; 0xfe34f orgs.asm:685
+ mov ax, strict word 00040h ; b8 40 00 ; 0xfe350 orgs.asm:694
+ mov ds, ax ; 8e d8 ; 0xfe353 orgs.asm:695
+ mov ss, [word 00069h] ; 8e 16 69 00 ; 0xfe355 orgs.asm:697
+ mov sp, word [word 00067h] ; 8b 26 67 00 ; 0xfe359 orgs.asm:698
+ in AL, strict byte 092h ; e4 92 ; 0xfe35d orgs.asm:700
+ and AL, strict byte 0fdh ; 24 fd ; 0xfe35f orgs.asm:701
+ out strict byte 092h, AL ; e6 92 ; 0xfe361 orgs.asm:702
+ lidt [cs:0eff5h] ; 2e 0f 01 1e f5 ef ; 0xfe363 orgs.asm:704
+ pop DS ; 1f ; 0xfe369 orgs.asm:706
+ pop ES ; 07 ; 0xfe36a orgs.asm:707
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xfe36b orgs.asm:709
+ in AL, strict byte 080h ; e4 80 ; 0xfe36d orgs.asm:711
+ mov byte [bp+00fh], al ; 88 46 0f ; 0xfe36f orgs.asm:712
+ db 03ah, 0e0h
+ ; cmp ah, al ; 3a e0 ; 0xfe372 orgs.asm:714
+ popaw ; 61 ; 0xfe374 orgs.asm:716
+ sti ; fb ; 0xfe375 orgs.asm:717
+ retf 00002h ; ca 02 00 ; 0xfe376 orgs.asm:718
+ ; disGetNextSymbol 0xfe379 LB 0x1c87 -> off=0x0 cb=0000000000000085 uValue=00000000000f0379 'biosorg_check_before_or_at_0E3FCh'
+biosorg_check_before_or_at_0E3FCh: ; 0xfe379 LB 0x85
+ times 0x83 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe3fe LB 0x1c02 -> off=0x0 cb=0000000000000003 uValue=00000000000f03fe 'int13_handler'
+int13_handler: ; 0xfe3fe LB 0x3
+ jmp near 0ec5bh ; e9 5a 08 ; 0xfe3fe orgs.asm:728
+ ; disGetNextSymbol 0xfe401 LB 0x1bff -> off=0x0 cb=00000000000002f1 uValue=00000000000f0401 'rom_fdpt'
+rom_fdpt: ; 0xfe401 LB 0x2f1
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 058h
+ db 04dh
+ ; disGetNextSymbol 0xfe6f2 LB 0x190e -> off=0x0 cb=0000000000000003 uValue=00000000000f06f2 'int19_handler'
+int19_handler: ; 0xfe6f2 LB 0x3
+ jmp near 0f0ach ; e9 b7 09 ; 0xfe6f2 orgs.asm:744
+ ; disGetNextSymbol 0xfe6f5 LB 0x190b -> off=0x0 cb=000000000000000a uValue=00000000000f06f5 'biosorg_check_at_0E6F5h'
+biosorg_check_at_0E6F5h: ; 0xfe6f5 LB 0xa
+ or word [bx+si], ax ; 09 00 ; 0xfe6f5
+ sti ; fb ; 0xfe6f7
+ add byte [bx+di], al ; 00 01 ; 0xfe6f8
+ je short 0e73ch ; 74 40 ; 0xfe6fa
+ times 0x3 db 0
+ ; disGetNextSymbol 0xfe6ff LB 0x1901 -> off=0x0 cb=000000000000002a uValue=00000000000f06ff 'biosorg_check_before_or_at_0E727h'
+biosorg_check_before_or_at_0E727h: ; 0xfe6ff LB 0x2a
+ times 0x28 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe729 LB 0x18d7 -> off=0x0 cb=0000000000000010 uValue=00000000000f0729 'biosorg_check_at_0E729h'
+biosorg_check_at_0E729h: ; 0xfe729 LB 0x10
+ times 0xe db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe739 LB 0x18c7 -> off=0x0 cb=0000000000000036 uValue=00000000000f0739 'biosorg_check_at_0E739h'
+biosorg_check_at_0E739h: ; 0xfe739 LB 0x36
+ push DS ; 1e ; 0xfe739 orgs.asm:817
+ push ES ; 06 ; 0xfe73a orgs.asm:818
+ push ax ; 50 ; 0xfe73b orgs.asm:99
+ push cx ; 51 ; 0xfe73c orgs.asm:100
+ push dx ; 52 ; 0xfe73d orgs.asm:101
+ push bx ; 53 ; 0xfe73e orgs.asm:102
+ push sp ; 54 ; 0xfe73f orgs.asm:103
+ push bp ; 55 ; 0xfe740 orgs.asm:104
+ push si ; 56 ; 0xfe741 orgs.asm:105
+ push di ; 57 ; 0xfe742 orgs.asm:106
+ push CS ; 0e ; 0xfe743 orgs.asm:104
+ pop DS ; 1f ; 0xfe744 orgs.asm:105
+ cld ; fc ; 0xfe745 orgs.asm:106
+ call 064d9h ; e8 90 7d ; 0xfe746 orgs.asm:821
+ pop di ; 5f ; 0xfe749 orgs.asm:116
+ pop si ; 5e ; 0xfe74a orgs.asm:117
+ pop bp ; 5d ; 0xfe74b orgs.asm:118
+ pop bx ; 5b ; 0xfe74c orgs.asm:119
+ pop bx ; 5b ; 0xfe74d orgs.asm:120
+ pop dx ; 5a ; 0xfe74e orgs.asm:121
+ pop cx ; 59 ; 0xfe74f orgs.asm:122
+ pop ax ; 58 ; 0xfe750 orgs.asm:123
+ pop ES ; 07 ; 0xfe751 orgs.asm:823
+ pop DS ; 1f ; 0xfe752 orgs.asm:824
+ iret ; cf ; 0xfe753 orgs.asm:825
+ push DS ; 1e ; 0xfe754 orgs.asm:833
+ push ES ; 06 ; 0xfe755 orgs.asm:834
+ push ax ; 50 ; 0xfe756 orgs.asm:99
+ push cx ; 51 ; 0xfe757 orgs.asm:100
+ push dx ; 52 ; 0xfe758 orgs.asm:101
+ push bx ; 53 ; 0xfe759 orgs.asm:102
+ push sp ; 54 ; 0xfe75a orgs.asm:103
+ push bp ; 55 ; 0xfe75b orgs.asm:104
+ push si ; 56 ; 0xfe75c orgs.asm:105
+ push di ; 57 ; 0xfe75d orgs.asm:106
+ push CS ; 0e ; 0xfe75e orgs.asm:104
+ pop DS ; 1f ; 0xfe75f orgs.asm:105
+ cld ; fc ; 0xfe760 orgs.asm:106
+ call 0168ah ; e8 26 2f ; 0xfe761 orgs.asm:837
+ pop di ; 5f ; 0xfe764 orgs.asm:116
+ pop si ; 5e ; 0xfe765 orgs.asm:117
+ pop bp ; 5d ; 0xfe766 orgs.asm:118
+ pop bx ; 5b ; 0xfe767 orgs.asm:119
+ pop bx ; 5b ; 0xfe768 orgs.asm:120
+ pop dx ; 5a ; 0xfe769 orgs.asm:121
+ pop cx ; 59 ; 0xfe76a orgs.asm:122
+ pop ax ; 58 ; 0xfe76b orgs.asm:123
+ pop ES ; 07 ; 0xfe76c orgs.asm:839
+ pop DS ; 1f ; 0xfe76d orgs.asm:840
+ iret ; cf ; 0xfe76e orgs.asm:841
+ ; disGetNextSymbol 0xfe76f LB 0x1891 -> off=0x0 cb=0000000000000025 uValue=00000000000f076f 'init_pic'
+init_pic: ; 0xfe76f LB 0x25
+ mov AL, strict byte 011h ; b0 11 ; 0xfe76f orgs.asm:846
+ out strict byte 020h, AL ; e6 20 ; 0xfe771 orgs.asm:847
+ out strict byte 0a0h, AL ; e6 a0 ; 0xfe773 orgs.asm:848
+ mov AL, strict byte 008h ; b0 08 ; 0xfe775 orgs.asm:849
+ out strict byte 021h, AL ; e6 21 ; 0xfe777 orgs.asm:850
+ mov AL, strict byte 070h ; b0 70 ; 0xfe779 orgs.asm:851
+ out strict byte 0a1h, AL ; e6 a1 ; 0xfe77b orgs.asm:852
+ mov AL, strict byte 004h ; b0 04 ; 0xfe77d orgs.asm:853
+ out strict byte 021h, AL ; e6 21 ; 0xfe77f orgs.asm:854
+ mov AL, strict byte 002h ; b0 02 ; 0xfe781 orgs.asm:855
+ out strict byte 0a1h, AL ; e6 a1 ; 0xfe783 orgs.asm:856
+ mov AL, strict byte 001h ; b0 01 ; 0xfe785 orgs.asm:857
+ out strict byte 021h, AL ; e6 21 ; 0xfe787 orgs.asm:858
+ out strict byte 0a1h, AL ; e6 a1 ; 0xfe789 orgs.asm:859
+ mov AL, strict byte 0b8h ; b0 b8 ; 0xfe78b orgs.asm:860
+ out strict byte 021h, AL ; e6 21 ; 0xfe78d orgs.asm:861
+ mov AL, strict byte 08fh ; b0 8f ; 0xfe78f orgs.asm:862
+ out strict byte 0a1h, AL ; e6 a1 ; 0xfe791 orgs.asm:863
+ retn ; c3 ; 0xfe793 orgs.asm:864
+ ; disGetNextSymbol 0xfe794 LB 0x186c -> off=0x0 cb=0000000000000051 uValue=00000000000f0794 'ebda_post'
+ebda_post: ; 0xfe794 LB 0x51
+ mov ax, 0e754h ; b8 54 e7 ; 0xfe794 orgs.asm:95
+ mov word [00034h], ax ; a3 34 00 ; 0xfe797 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe79a orgs.asm:97
+ mov word [00036h], ax ; a3 36 00 ; 0xfe79d orgs.asm:98
+ mov ax, 0e754h ; b8 54 e7 ; 0xfe7a0 orgs.asm:95
+ mov word [0003ch], ax ; a3 3c 00 ; 0xfe7a3 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe7a6 orgs.asm:97
+ mov word [0003eh], ax ; a3 3e 00 ; 0xfe7a9 orgs.asm:98
+ mov ax, 0e754h ; b8 54 e7 ; 0xfe7ac orgs.asm:95
+ mov word [001c8h], ax ; a3 c8 01 ; 0xfe7af orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe7b2 orgs.asm:97
+ mov word [001cah], ax ; a3 ca 01 ; 0xfe7b5 orgs.asm:98
+ mov ax, 0e754h ; b8 54 e7 ; 0xfe7b8 orgs.asm:95
+ mov word [001cch], ax ; a3 cc 01 ; 0xfe7bb orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe7be orgs.asm:97
+ mov word [001ceh], ax ; a3 ce 01 ; 0xfe7c1 orgs.asm:98
+ mov ax, 0e754h ; b8 54 e7 ; 0xfe7c4 orgs.asm:95
+ mov word [001dch], ax ; a3 dc 01 ; 0xfe7c7 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfe7ca orgs.asm:97
+ mov word [001deh], ax ; a3 de 01 ; 0xfe7cd orgs.asm:98
+ mov ax, 09fc0h ; b8 c0 9f ; 0xfe7d0 orgs.asm:876
+ mov ds, ax ; 8e d8 ; 0xfe7d3 orgs.asm:877
+ mov byte [word 00000h], 001h ; c6 06 00 00 01 ; 0xfe7d5 orgs.asm:878
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe7da orgs.asm:880
+ mov ds, ax ; 8e d8 ; 0xfe7dc orgs.asm:881
+ mov word [0040eh], 09fc0h ; c7 06 0e 04 c0 9f ; 0xfe7de orgs.asm:882
+ retn ; c3 ; 0xfe7e4 orgs.asm:883
+ ; disGetNextSymbol 0xfe7e5 LB 0x181b -> off=0x0 cb=0000000000000049 uValue=00000000000f07e5 'biosorg_check_before_or_at_0E82Ch'
+biosorg_check_before_or_at_0E82Ch: ; 0xfe7e5 LB 0x49
+ times 0x47 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe82e LB 0x17d2 -> off=0x0 cb=0000000000000052 uValue=00000000000f082e 'biosorg_check_at_0E82Eh'
+biosorg_check_at_0E82Eh: ; 0xfe82e LB 0x52
+ sti ; fb ; 0xfe82e orgs.asm:894
+ pushfw ; 9c ; 0xfe82f orgs.asm:897
+ push ES ; 06 ; 0xfe830 orgs.asm:898
+ push DS ; 1e ; 0xfe831 orgs.asm:899
+ push ax ; 50 ; 0xfe832 orgs.asm:99
+ push cx ; 51 ; 0xfe833 orgs.asm:100
+ push dx ; 52 ; 0xfe834 orgs.asm:101
+ push bx ; 53 ; 0xfe835 orgs.asm:102
+ push sp ; 54 ; 0xfe836 orgs.asm:103
+ push bp ; 55 ; 0xfe837 orgs.asm:104
+ push si ; 56 ; 0xfe838 orgs.asm:105
+ push di ; 57 ; 0xfe839 orgs.asm:106
+ cmp ah, 000h ; 80 fc 00 ; 0xfe83a orgs.asm:902
+ je short 0e858h ; 74 19 ; 0xfe83d orgs.asm:903
+ cmp ah, 010h ; 80 fc 10 ; 0xfe83f orgs.asm:905
+ je short 0e858h ; 74 14 ; 0xfe842 orgs.asm:906
+ push CS ; 0e ; 0xfe844 orgs.asm:104
+ pop DS ; 1f ; 0xfe845 orgs.asm:105
+ cld ; fc ; 0xfe846 orgs.asm:106
+ call 056e8h ; e8 9e 6e ; 0xfe847 orgs.asm:909
+ pop di ; 5f ; 0xfe84a orgs.asm:116
+ pop si ; 5e ; 0xfe84b orgs.asm:117
+ pop bp ; 5d ; 0xfe84c orgs.asm:118
+ pop bx ; 5b ; 0xfe84d orgs.asm:119
+ pop bx ; 5b ; 0xfe84e orgs.asm:120
+ pop dx ; 5a ; 0xfe84f orgs.asm:121
+ pop cx ; 59 ; 0xfe850 orgs.asm:122
+ pop ax ; 58 ; 0xfe851 orgs.asm:123
+ pop DS ; 1f ; 0xfe852 orgs.asm:911
+ pop ES ; 07 ; 0xfe853 orgs.asm:912
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xfe854 orgs.asm:913
+ iret ; cf ; 0xfe857 orgs.asm:914
+ mov bx, strict word 00040h ; bb 40 00 ; 0xfe858 orgs.asm:917
+ mov ds, bx ; 8e db ; 0xfe85b orgs.asm:918
+ cli ; fa ; 0xfe85d orgs.asm:920
+ mov bx, word [word 0001ah] ; 8b 1e 1a 00 ; 0xfe85e orgs.asm:921
+ cmp bx, word [word 0001ch] ; 3b 1e 1c 00 ; 0xfe862 orgs.asm:922
+ jne short 0e86ch ; 75 04 ; 0xfe866 orgs.asm:923
+ sti ; fb ; 0xfe868 orgs.asm:924
+ nop ; 90 ; 0xfe869 orgs.asm:925
+ jmp short 0e85dh ; eb f1 ; 0xfe86a orgs.asm:933
+ push CS ; 0e ; 0xfe86c orgs.asm:104
+ pop DS ; 1f ; 0xfe86d orgs.asm:105
+ cld ; fc ; 0xfe86e orgs.asm:106
+ call 056e8h ; e8 76 6e ; 0xfe86f orgs.asm:937
+ pop di ; 5f ; 0xfe872 orgs.asm:116
+ pop si ; 5e ; 0xfe873 orgs.asm:117
+ pop bp ; 5d ; 0xfe874 orgs.asm:118
+ pop bx ; 5b ; 0xfe875 orgs.asm:119
+ pop bx ; 5b ; 0xfe876 orgs.asm:120
+ pop dx ; 5a ; 0xfe877 orgs.asm:121
+ pop cx ; 59 ; 0xfe878 orgs.asm:122
+ pop ax ; 58 ; 0xfe879 orgs.asm:123
+ pop DS ; 1f ; 0xfe87a orgs.asm:939
+ pop ES ; 07 ; 0xfe87b orgs.asm:940
+ add sp, strict byte 00002h ; 83 c4 02 ; 0xfe87c orgs.asm:941
+ iret ; cf ; 0xfe87f orgs.asm:949
+ ; disGetNextSymbol 0xfe880 LB 0x1780 -> off=0x0 cb=0000000000000107 uValue=00000000000f0880 'biosorg_check_before_or_at_0E985h'
+biosorg_check_before_or_at_0E985h: ; 0xfe880 LB 0x107
+ times 0x105 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfe987 LB 0x1679 -> off=0x0 cb=000000000000006e uValue=00000000000f0987 'biosorg_check_at_0E987h'
+biosorg_check_at_0E987h: ; 0xfe987 LB 0x6e
+ cli ; fa ; 0xfe987 orgs.asm:966
+ push ax ; 50 ; 0xfe988 orgs.asm:967
+ mov AL, strict byte 0adh ; b0 ad ; 0xfe989 orgs.asm:968
+ out strict byte 064h, AL ; e6 64 ; 0xfe98b orgs.asm:969
+ in AL, strict byte 060h ; e4 60 ; 0xfe98d orgs.asm:971
+ push DS ; 1e ; 0xfe98f orgs.asm:972
+ push ax ; 50 ; 0xfe990 orgs.asm:99
+ push cx ; 51 ; 0xfe991 orgs.asm:100
+ push dx ; 52 ; 0xfe992 orgs.asm:101
+ push bx ; 53 ; 0xfe993 orgs.asm:102
+ push sp ; 54 ; 0xfe994 orgs.asm:103
+ push bp ; 55 ; 0xfe995 orgs.asm:104
+ push si ; 56 ; 0xfe996 orgs.asm:105
+ push di ; 57 ; 0xfe997 orgs.asm:106
+ cld ; fc ; 0xfe998 orgs.asm:974
+ mov AH, strict byte 04fh ; b4 4f ; 0xfe999 orgs.asm:976
+ stc ; f9 ; 0xfe99b orgs.asm:977
+ int 015h ; cd 15 ; 0xfe99c orgs.asm:978
+ jnc short 0e9c7h ; 73 27 ; 0xfe99e orgs.asm:979
+ sti ; fb ; 0xfe9a0 orgs.asm:981
+ cmp AL, strict byte 0e0h ; 3c e0 ; 0xfe9a1 orgs.asm:984
+ jne short 0e9b0h ; 75 0b ; 0xfe9a3 orgs.asm:985
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe9a5 orgs.asm:986
+ mov ds, ax ; 8e d8 ; 0xfe9a7 orgs.asm:987
+ or byte [00496h], 002h ; 80 0e 96 04 02 ; 0xfe9a9 orgs.asm:988
+ jmp short 0e9c7h ; eb 17 ; 0xfe9ae orgs.asm:989
+ cmp AL, strict byte 0e1h ; 3c e1 ; 0xfe9b0 orgs.asm:992
+ jne short 0e9bfh ; 75 0b ; 0xfe9b2 orgs.asm:993
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfe9b4 orgs.asm:994
+ mov ds, ax ; 8e d8 ; 0xfe9b6 orgs.asm:995
+ or byte [00496h], 001h ; 80 0e 96 04 01 ; 0xfe9b8 orgs.asm:996
+ jmp short 0e9c7h ; eb 08 ; 0xfe9bd orgs.asm:997
+ push ES ; 06 ; 0xfe9bf orgs.asm:1000
+ push CS ; 0e ; 0xfe9c0 orgs.asm:104
+ pop DS ; 1f ; 0xfe9c1 orgs.asm:105
+ cld ; fc ; 0xfe9c2 orgs.asm:106
+ call 0525ah ; e8 94 68 ; 0xfe9c3 orgs.asm:1002
+ pop ES ; 07 ; 0xfe9c6 orgs.asm:1003
+ pop di ; 5f ; 0xfe9c7 orgs.asm:116
+ pop si ; 5e ; 0xfe9c8 orgs.asm:117
+ pop bp ; 5d ; 0xfe9c9 orgs.asm:118
+ pop bx ; 5b ; 0xfe9ca orgs.asm:119
+ pop bx ; 5b ; 0xfe9cb orgs.asm:120
+ pop dx ; 5a ; 0xfe9cc orgs.asm:121
+ pop cx ; 59 ; 0xfe9cd orgs.asm:122
+ pop ax ; 58 ; 0xfe9ce orgs.asm:123
+ pop DS ; 1f ; 0xfe9cf orgs.asm:1007
+ cli ; fa ; 0xfe9d0 orgs.asm:1008
+ call 0e034h ; e8 60 f6 ; 0xfe9d1 orgs.asm:1009
+ mov AL, strict byte 0aeh ; b0 ae ; 0xfe9d4 orgs.asm:1011
+ out strict byte 064h, AL ; e6 64 ; 0xfe9d6 orgs.asm:1012
+ pop ax ; 58 ; 0xfe9d8 orgs.asm:1013
+ iret ; cf ; 0xfe9d9 orgs.asm:1014
+ push ax ; 50 ; 0xfe9da orgs.asm:99
+ push cx ; 51 ; 0xfe9db orgs.asm:100
+ push dx ; 52 ; 0xfe9dc orgs.asm:101
+ push bx ; 53 ; 0xfe9dd orgs.asm:102
+ push sp ; 54 ; 0xfe9de orgs.asm:103
+ push bp ; 55 ; 0xfe9df orgs.asm:104
+ push si ; 56 ; 0xfe9e0 orgs.asm:105
+ push di ; 57 ; 0xfe9e1 orgs.asm:106
+ push ES ; 06 ; 0xfe9e2 orgs.asm:1023
+ push DS ; 1e ; 0xfe9e3 orgs.asm:1024
+ push CS ; 0e ; 0xfe9e4 orgs.asm:104
+ pop DS ; 1f ; 0xfe9e5 orgs.asm:105
+ cld ; fc ; 0xfe9e6 orgs.asm:106
+ call 069e7h ; e8 fd 7f ; 0xfe9e7 orgs.asm:1026
+ pop DS ; 1f ; 0xfe9ea orgs.asm:1027
+ pop ES ; 07 ; 0xfe9eb orgs.asm:1028
+ pop di ; 5f ; 0xfe9ec orgs.asm:116
+ pop si ; 5e ; 0xfe9ed orgs.asm:117
+ pop bp ; 5d ; 0xfe9ee orgs.asm:118
+ pop bx ; 5b ; 0xfe9ef orgs.asm:119
+ pop bx ; 5b ; 0xfe9f0 orgs.asm:120
+ pop dx ; 5a ; 0xfe9f1 orgs.asm:121
+ pop cx ; 59 ; 0xfe9f2 orgs.asm:122
+ pop ax ; 58 ; 0xfe9f3 orgs.asm:123
+ iret ; cf ; 0xfe9f4 orgs.asm:1030
+ ; disGetNextSymbol 0xfe9f5 LB 0x160b -> off=0x0 cb=0000000000000264 uValue=00000000000f09f5 'biosorg_check_before_or_at_0EC57h'
+biosorg_check_before_or_at_0EC57h: ; 0xfe9f5 LB 0x264
+ times 0x262 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfec59 LB 0x13a7 -> off=0x0 cb=0000000000000002 uValue=00000000000f0c59 'biosorg_check_at_0EC59h'
+biosorg_check_at_0EC59h: ; 0xfec59 LB 0x2
+ jmp short 0ecc4h ; eb 69 ; 0xfec59 orgs.asm:1037
+ ; disGetNextSymbol 0xfec5b LB 0x13a5 -> off=0x0 cb=000000000000001f uValue=00000000000f0c5b 'int13_relocated'
+int13_relocated: ; 0xfec5b LB 0x1f
+ cmp ah, 04ah ; 80 fc 4a ; 0xfec5b orgs.asm:1046
+ jc short 0ec7ch ; 72 1c ; 0xfec5e orgs.asm:1047
+ cmp ah, 04dh ; 80 fc 4d ; 0xfec60 orgs.asm:1049
+ jnbe short 0ec7ch ; 77 17 ; 0xfec63 orgs.asm:1050
+ push ax ; 50 ; 0xfec65 orgs.asm:99
+ push cx ; 51 ; 0xfec66 orgs.asm:100
+ push dx ; 52 ; 0xfec67 orgs.asm:101
+ push bx ; 53 ; 0xfec68 orgs.asm:102
+ push sp ; 54 ; 0xfec69 orgs.asm:103
+ push bp ; 55 ; 0xfec6a orgs.asm:104
+ push si ; 56 ; 0xfec6b orgs.asm:105
+ push di ; 57 ; 0xfec6c orgs.asm:106
+ push ES ; 06 ; 0xfec6d orgs.asm:1053
+ push DS ; 1e ; 0xfec6e orgs.asm:1054
+ push CS ; 0e ; 0xfec6f orgs.asm:104
+ pop DS ; 1f ; 0xfec70 orgs.asm:105
+ cld ; fc ; 0xfec71 orgs.asm:106
+ push word [cs:0ec7ah] ; 2e ff 36 7a ec ; 0xfec72 orgs.asm:86
+ jmp near 03c24h ; e9 aa 4f ; 0xfec77 orgs.asm:87
+ ; disGetNextSymbol 0xfec7a LB 0x1386 -> off=0x0 cb=000000000000004a uValue=00000000000f0c7a 'jmp_call_ret_int13_out'
+jmp_call_ret_int13_out: ; 0xfec7a LB 0x4a
+ db 0ffh
+ in AL, DX ; ec ; 0xfec7b
+ push ES ; 06 ; 0xfec7c orgs.asm:1062
+ push ax ; 50 ; 0xfec7d orgs.asm:1063
+ push bx ; 53 ; 0xfec7e orgs.asm:1064
+ push cx ; 51 ; 0xfec7f orgs.asm:1065
+ push dx ; 52 ; 0xfec80 orgs.asm:1066
+ call 03bf8h ; e8 74 4f ; 0xfec81 orgs.asm:1069
+ cmp AL, strict byte 000h ; 3c 00 ; 0xfec84 orgs.asm:1070
+ je short 0ecbfh ; 74 37 ; 0xfec86 orgs.asm:1071
+ call 03c0eh ; e8 83 4f ; 0xfec88 orgs.asm:1074
+ pop dx ; 5a ; 0xfec8b orgs.asm:1075
+ push dx ; 52 ; 0xfec8c orgs.asm:1076
+ db 03ah, 0c2h
+ ; cmp al, dl ; 3a c2 ; 0xfec8d orgs.asm:1077
+ jne short 0ecabh ; 75 1a ; 0xfec8f orgs.asm:1078
+ pop dx ; 5a ; 0xfec91 orgs.asm:1080
+ pop cx ; 59 ; 0xfec92 orgs.asm:1081
+ pop bx ; 5b ; 0xfec93 orgs.asm:1082
+ pop ax ; 58 ; 0xfec94 orgs.asm:1083
+ pop ES ; 07 ; 0xfec95 orgs.asm:1084
+ push ax ; 50 ; 0xfec96 orgs.asm:99
+ push cx ; 51 ; 0xfec97 orgs.asm:100
+ push dx ; 52 ; 0xfec98 orgs.asm:101
+ push bx ; 53 ; 0xfec99 orgs.asm:102
+ push sp ; 54 ; 0xfec9a orgs.asm:103
+ push bp ; 55 ; 0xfec9b orgs.asm:104
+ push si ; 56 ; 0xfec9c orgs.asm:105
+ push di ; 57 ; 0xfec9d orgs.asm:106
+ push ES ; 06 ; 0xfec9e orgs.asm:1087
+ push DS ; 1e ; 0xfec9f orgs.asm:1088
+ push CS ; 0e ; 0xfeca0 orgs.asm:104
+ pop DS ; 1f ; 0xfeca1 orgs.asm:105
+ cld ; fc ; 0xfeca2 orgs.asm:106
+ push word [cs:0ec7ah] ; 2e ff 36 7a ec ; 0xfeca3 orgs.asm:86
+ jmp near 041fch ; e9 51 55 ; 0xfeca8 orgs.asm:87
+ and dl, 0e0h ; 80 e2 e0 ; 0xfecab orgs.asm:1094
+ db 03ah, 0c2h
+ ; cmp al, dl ; 3a c2 ; 0xfecae orgs.asm:1095
+ jne short 0ecbfh ; 75 0d ; 0xfecb0 orgs.asm:1096
+ pop dx ; 5a ; 0xfecb2 orgs.asm:1098
+ pop cx ; 59 ; 0xfecb3 orgs.asm:1099
+ pop bx ; 5b ; 0xfecb4 orgs.asm:1100
+ pop ax ; 58 ; 0xfecb5 orgs.asm:1101
+ pop ES ; 07 ; 0xfecb6 orgs.asm:1102
+ push ax ; 50 ; 0xfecb7 orgs.asm:1104
+ push cx ; 51 ; 0xfecb8 orgs.asm:1105
+ push dx ; 52 ; 0xfecb9 orgs.asm:1106
+ push bx ; 53 ; 0xfecba orgs.asm:1107
+ db 0feh, 0cah
+ ; dec dl ; fe ca ; 0xfecbb orgs.asm:1109
+ jmp short 0ecc8h ; eb 09 ; 0xfecbd orgs.asm:1110
+ pop dx ; 5a ; 0xfecbf orgs.asm:1113
+ pop cx ; 59 ; 0xfecc0 orgs.asm:1114
+ pop bx ; 5b ; 0xfecc1 orgs.asm:1115
+ pop ax ; 58 ; 0xfecc2 orgs.asm:1116
+ pop ES ; 07 ; 0xfecc3 orgs.asm:1117
+ ; disGetNextSymbol 0xfecc4 LB 0x133c -> off=0x0 cb=0000000000000004 uValue=00000000000f0cc4 'int13_noeltorito'
+int13_noeltorito: ; 0xfecc4 LB 0x4
+ push ax ; 50 ; 0xfecc4 orgs.asm:1120
+ push cx ; 51 ; 0xfecc5 orgs.asm:1121
+ push dx ; 52 ; 0xfecc6 orgs.asm:1122
+ push bx ; 53 ; 0xfecc7 orgs.asm:1123
+ ; disGetNextSymbol 0xfecc8 LB 0x1338 -> off=0x0 cb=0000000000000016 uValue=00000000000f0cc8 'int13_legacy'
+int13_legacy: ; 0xfecc8 LB 0x16
+ push dx ; 52 ; 0xfecc8 orgs.asm:1125
+ push bp ; 55 ; 0xfecc9 orgs.asm:1126
+ push si ; 56 ; 0xfecca orgs.asm:1127
+ push di ; 57 ; 0xfeccb orgs.asm:1128
+ push ES ; 06 ; 0xfeccc orgs.asm:1129
+ push DS ; 1e ; 0xfeccd orgs.asm:1130
+ push CS ; 0e ; 0xfecce orgs.asm:104
+ pop DS ; 1f ; 0xfeccf orgs.asm:105
+ cld ; fc ; 0xfecd0 orgs.asm:106
+ test dl, 080h ; f6 c2 80 ; 0xfecd1 orgs.asm:1135
+ jne short 0ecdeh ; 75 08 ; 0xfecd4 orgs.asm:1136
+ push word [cs:0ec7ah] ; 2e ff 36 7a ec ; 0xfecd6 orgs.asm:86
+ jmp near 031abh ; e9 cd 44 ; 0xfecdb orgs.asm:87
+ ; disGetNextSymbol 0xfecde LB 0x1322 -> off=0x0 cb=0000000000000014 uValue=00000000000f0cde 'int13_notfloppy'
+int13_notfloppy: ; 0xfecde LB 0x14
+ cmp dl, 0e0h ; 80 fa e0 ; 0xfecde orgs.asm:1141
+ jc short 0ecf2h ; 72 0f ; 0xfece1 orgs.asm:1142
+ shr ebx, 010h ; 66 c1 eb 10 ; 0xfece3 orgs.asm:1148
+ push bx ; 53 ; 0xfece7 orgs.asm:1149
+ call 04854h ; e8 69 5b ; 0xfece8 orgs.asm:1150
+ pop bx ; 5b ; 0xfeceb orgs.asm:1151
+ sal ebx, 010h ; 66 c1 e3 10 ; 0xfecec orgs.asm:1152
+ jmp short 0ecffh ; eb 0d ; 0xfecf0 orgs.asm:1154
+ ; disGetNextSymbol 0xfecf2 LB 0x130e -> off=0x0 cb=000000000000000d uValue=00000000000f0cf2 'int13_disk'
+int13_disk: ; 0xfecf2 LB 0xd
+ cmp ah, 040h ; 80 fc 40 ; 0xfecf2 orgs.asm:1158
+ jnbe short 0ecfch ; 77 05 ; 0xfecf5 orgs.asm:1159
+ call 05de5h ; e8 eb 70 ; 0xfecf7 orgs.asm:1160
+ jmp short 0ecffh ; eb 03 ; 0xfecfa orgs.asm:1161
+ call 06231h ; e8 32 75 ; 0xfecfc orgs.asm:1164
+ ; disGetNextSymbol 0xfecff LB 0x1301 -> off=0x0 cb=000000000000000b uValue=00000000000f0cff 'int13_out'
+int13_out: ; 0xfecff LB 0xb
+ pop DS ; 1f ; 0xfecff orgs.asm:1167
+ pop ES ; 07 ; 0xfed00 orgs.asm:1168
+ pop di ; 5f ; 0xfed01 orgs.asm:116
+ pop si ; 5e ; 0xfed02 orgs.asm:117
+ pop bp ; 5d ; 0xfed03 orgs.asm:118
+ pop bx ; 5b ; 0xfed04 orgs.asm:119
+ pop bx ; 5b ; 0xfed05 orgs.asm:120
+ pop dx ; 5a ; 0xfed06 orgs.asm:121
+ pop cx ; 59 ; 0xfed07 orgs.asm:122
+ pop ax ; 58 ; 0xfed08 orgs.asm:123
+ iret ; cf ; 0xfed09 orgs.asm:1170
+ ; disGetNextSymbol 0xfed0a LB 0x12f6 -> off=0x0 cb=000000000000001e uValue=00000000000f0d0a 'detect_parport'
+detect_parport: ; 0xfed0a LB 0x1e
+ push dx ; 52 ; 0xfed0a orgs.asm:1177
+ inc dx ; 42 ; 0xfed0b orgs.asm:1178
+ inc dx ; 42 ; 0xfed0c orgs.asm:1179
+ in AL, DX ; ec ; 0xfed0d orgs.asm:1180
+ and AL, strict byte 0dfh ; 24 df ; 0xfed0e orgs.asm:1181
+ out DX, AL ; ee ; 0xfed10 orgs.asm:1182
+ pop dx ; 5a ; 0xfed11 orgs.asm:1183
+ mov AL, strict byte 0aah ; b0 aa ; 0xfed12 orgs.asm:1184
+ out DX, AL ; ee ; 0xfed14 orgs.asm:1185
+ in AL, DX ; ec ; 0xfed15 orgs.asm:1186
+ cmp AL, strict byte 0aah ; 3c aa ; 0xfed16 orgs.asm:1187
+ jne short 0ed27h ; 75 0d ; 0xfed18 orgs.asm:1188
+ push bx ; 53 ; 0xfed1a orgs.asm:1190
+ sal bx, 1 ; d1 e3 ; 0xfed1b orgs.asm:1191
+ mov word [bx+00408h], dx ; 89 97 08 04 ; 0xfed1d orgs.asm:1192
+ pop bx ; 5b ; 0xfed21 orgs.asm:1193
+ mov byte [bx+00478h], cl ; 88 8f 78 04 ; 0xfed22 orgs.asm:1194
+ inc bx ; 43 ; 0xfed26 orgs.asm:1195
+ retn ; c3 ; 0xfed27 orgs.asm:1197
+ ; disGetNextSymbol 0xfed28 LB 0x12d8 -> off=0x0 cb=0000000000000024 uValue=00000000000f0d28 'detect_serial'
+detect_serial: ; 0xfed28 LB 0x24
+ push dx ; 52 ; 0xfed28 orgs.asm:1204
+ inc dx ; 42 ; 0xfed29 orgs.asm:1205
+ mov AL, strict byte 002h ; b0 02 ; 0xfed2a orgs.asm:1206
+ out DX, AL ; ee ; 0xfed2c orgs.asm:1207
+ in AL, DX ; ec ; 0xfed2d orgs.asm:1208
+ cmp AL, strict byte 002h ; 3c 02 ; 0xfed2e orgs.asm:1209
+ jne short 0ed4ah ; 75 18 ; 0xfed30 orgs.asm:1210
+ inc dx ; 42 ; 0xfed32 orgs.asm:1212
+ in AL, DX ; ec ; 0xfed33 orgs.asm:1213
+ cmp AL, strict byte 002h ; 3c 02 ; 0xfed34 orgs.asm:1214
+ jne short 0ed4ah ; 75 12 ; 0xfed36 orgs.asm:1215
+ dec dx ; 4a ; 0xfed38 orgs.asm:1217
+ db 032h, 0c0h
+ ; xor al, al ; 32 c0 ; 0xfed39 orgs.asm:1218
+ pop dx ; 5a ; 0xfed3b orgs.asm:1219
+ push bx ; 53 ; 0xfed3c orgs.asm:1220
+ sal bx, 1 ; d1 e3 ; 0xfed3d orgs.asm:1221
+ mov word [bx+00400h], dx ; 89 97 00 04 ; 0xfed3f orgs.asm:1222
+ pop bx ; 5b ; 0xfed43 orgs.asm:1223
+ mov byte [bx+0047ch], cl ; 88 8f 7c 04 ; 0xfed44 orgs.asm:1224
+ inc bx ; 43 ; 0xfed48 orgs.asm:1225
+ retn ; c3 ; 0xfed49 orgs.asm:1226
+ pop dx ; 5a ; 0xfed4a orgs.asm:1229
+ retn ; c3 ; 0xfed4b orgs.asm:1230
+ ; disGetNextSymbol 0xfed4c LB 0x12b4 -> off=0x0 cb=000000000000008c uValue=00000000000f0d4c 'floppy_post'
+floppy_post: ; 0xfed4c LB 0x8c
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfed4c orgs.asm:1240
+ mov ds, ax ; 8e d8 ; 0xfed4e orgs.asm:1241
+ mov AL, strict byte 000h ; b0 00 ; 0xfed50 orgs.asm:1245
+ mov byte [0043eh], AL ; a2 3e 04 ; 0xfed52 orgs.asm:1246
+ mov byte [0043fh], AL ; a2 3f 04 ; 0xfed55 orgs.asm:1247
+ mov byte [00440h], AL ; a2 40 04 ; 0xfed58 orgs.asm:1248
+ mov byte [00441h], AL ; a2 41 04 ; 0xfed5b orgs.asm:1249
+ mov byte [00442h], AL ; a2 42 04 ; 0xfed5e orgs.asm:1250
+ mov byte [00443h], AL ; a2 43 04 ; 0xfed61 orgs.asm:1251
+ mov byte [00444h], AL ; a2 44 04 ; 0xfed64 orgs.asm:1252
+ mov byte [00445h], AL ; a2 45 04 ; 0xfed67 orgs.asm:1253
+ mov byte [00446h], AL ; a2 46 04 ; 0xfed6a orgs.asm:1254
+ mov byte [00447h], AL ; a2 47 04 ; 0xfed6d orgs.asm:1255
+ mov byte [00448h], AL ; a2 48 04 ; 0xfed70 orgs.asm:1256
+ mov byte [0048bh], AL ; a2 8b 04 ; 0xfed73 orgs.asm:1258
+ mov AL, strict byte 010h ; b0 10 ; 0xfed76 orgs.asm:1260
+ out strict byte 070h, AL ; e6 70 ; 0xfed78 orgs.asm:1261
+ in AL, strict byte 071h ; e4 71 ; 0xfed7a orgs.asm:1262
+ db 08ah, 0e0h
+ ; mov ah, al ; 8a e0 ; 0xfed7c orgs.asm:1263
+ shr al, 1 ; d0 e8 ; 0xfed7e orgs.asm:181
+ shr al, 1 ; d0 e8 ; 0xfed80 orgs.asm:184
+ shr al, 1 ; d0 e8 ; 0xfed82 orgs.asm:187
+ shr al, 1 ; d0 e8 ; 0xfed84 orgs.asm:190
+ je short 0ed8ch ; 74 04 ; 0xfed86 orgs.asm:1268
+ mov BL, strict byte 007h ; b3 07 ; 0xfed88 orgs.asm:1269
+ jmp short 0ed8eh ; eb 02 ; 0xfed8a orgs.asm:1270
+ mov BL, strict byte 000h ; b3 00 ; 0xfed8c orgs.asm:1273
+ db 08ah, 0c4h
+ ; mov al, ah ; 8a c4 ; 0xfed8e orgs.asm:1276
+ and AL, strict byte 00fh ; 24 0f ; 0xfed90 orgs.asm:1277
+ je short 0ed97h ; 74 03 ; 0xfed92 orgs.asm:1278
+ or bl, 070h ; 80 cb 70 ; 0xfed94 orgs.asm:1279
+ mov byte [0048fh], bl ; 88 1e 8f 04 ; 0xfed97 orgs.asm:1281
+ mov AL, strict byte 000h ; b0 00 ; 0xfed9b orgs.asm:1284
+ mov byte [00490h], AL ; a2 90 04 ; 0xfed9d orgs.asm:1285
+ mov byte [00491h], AL ; a2 91 04 ; 0xfeda0 orgs.asm:1286
+ mov byte [00492h], AL ; a2 92 04 ; 0xfeda3 orgs.asm:1287
+ mov byte [00493h], AL ; a2 93 04 ; 0xfeda6 orgs.asm:1288
+ mov byte [00494h], AL ; a2 94 04 ; 0xfeda9 orgs.asm:1289
+ mov byte [00495h], AL ; a2 95 04 ; 0xfedac orgs.asm:1290
+ mov AL, strict byte 002h ; b0 02 ; 0xfedaf orgs.asm:1292
+ out strict byte 00ah, AL ; e6 0a ; 0xfedb1 orgs.asm:1293
+ mov ax, 0efc7h ; b8 c7 ef ; 0xfedb3 orgs.asm:95
+ mov word [00078h], ax ; a3 78 00 ; 0xfedb6 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfedb9 orgs.asm:97
+ mov word [0007ah], ax ; a3 7a 00 ; 0xfedbc orgs.asm:98
+ mov ax, 0ec59h ; b8 59 ec ; 0xfedbf orgs.asm:95
+ mov word [00100h], ax ; a3 00 01 ; 0xfedc2 orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfedc5 orgs.asm:97
+ mov word [00102h], ax ; a3 02 01 ; 0xfedc8 orgs.asm:98
+ mov ax, 0ef57h ; b8 57 ef ; 0xfedcb orgs.asm:95
+ mov word [00038h], ax ; a3 38 00 ; 0xfedce orgs.asm:96
+ mov ax, 0f000h ; b8 00 f0 ; 0xfedd1 orgs.asm:97
+ mov word [0003ah], ax ; a3 3a 00 ; 0xfedd4 orgs.asm:98
+ retn ; c3 ; 0xfedd7 orgs.asm:1299
+ ; disGetNextSymbol 0xfedd8 LB 0x1228 -> off=0x0 cb=000000000000000b uValue=0000000000000dd8 'bcd_to_bin'
+bcd_to_bin: ; 0xfedd8 LB 0xb
+ push cx ; 51 ; 0xfedd8 orgs.asm:1312
+ mov CL, strict byte 004h ; b1 04 ; 0xfedd9 orgs.asm:1313
+ sal ax, CL ; d3 e0 ; 0xfeddb orgs.asm:1314
+ shr al, CL ; d2 e8 ; 0xfeddd orgs.asm:1315
+ pop cx ; 59 ; 0xfeddf orgs.asm:1316
+ aad 00ah ; d5 0a ; 0xfede0 orgs.asm:1318
+ retn ; c3 ; 0xfede2 orgs.asm:1319
+ ; disGetNextSymbol 0xfede3 LB 0x121d -> off=0x0 cb=000000000000005a uValue=00000000000f0de3 'rtc_post'
+rtc_post: ; 0xfede3 LB 0x5a
+ mov AL, strict byte 000h ; b0 00 ; 0xfede3 orgs.asm:1327
+ out strict byte 070h, AL ; e6 70 ; 0xfede5 orgs.asm:1328
+ in AL, strict byte 071h ; e4 71 ; 0xfede7 orgs.asm:1329
+ call 0edd8h ; e8 ec ff ; 0xfede9 orgs.asm:1330
+ test al, al ; 84 c0 ; 0xfedec orgs.asm:1331
+ db 032h, 0e4h
+ ; xor ah, ah ; 32 e4 ; 0xfedee orgs.asm:1332
+ mov dx, 01234h ; ba 34 12 ; 0xfedf0 orgs.asm:1333
+ mul dx ; f7 e2 ; 0xfedf3 orgs.asm:1334
+ db 08bh, 0c8h
+ ; mov cx, ax ; 8b c8 ; 0xfedf5 orgs.asm:1335
+ mov AL, strict byte 002h ; b0 02 ; 0xfedf7 orgs.asm:1338
+ out strict byte 070h, AL ; e6 70 ; 0xfedf9 orgs.asm:1339
+ in AL, strict byte 071h ; e4 71 ; 0xfedfb orgs.asm:1340
+ call 0edd8h ; e8 d8 ff ; 0xfedfd orgs.asm:1341
+ test al, al ; 84 c0 ; 0xfee00 orgs.asm:1342
+ je short 0ee0fh ; 74 0b ; 0xfee02 orgs.asm:1343
+ add cx, 04463h ; 81 c1 63 44 ; 0xfee04 orgs.asm:1345
+ adc dx, strict byte 00004h ; 83 d2 04 ; 0xfee08 orgs.asm:1346
+ db 0feh, 0c8h
+ ; dec al ; fe c8 ; 0xfee0b orgs.asm:1347
+ jne short 0ee04h ; 75 f5 ; 0xfee0d orgs.asm:1348
+ mov AL, strict byte 004h ; b0 04 ; 0xfee0f orgs.asm:1352
+ out strict byte 070h, AL ; e6 70 ; 0xfee11 orgs.asm:1353
+ in AL, strict byte 071h ; e4 71 ; 0xfee13 orgs.asm:1354
+ call 0edd8h ; e8 c0 ff ; 0xfee15 orgs.asm:1355
+ test al, al ; 84 c0 ; 0xfee18 orgs.asm:1356
+ je short 0ee28h ; 74 0c ; 0xfee1a orgs.asm:1357
+ add cx, 0076ch ; 81 c1 6c 07 ; 0xfee1c orgs.asm:1359
+ adc dx, 00100h ; 81 d2 00 01 ; 0xfee20 orgs.asm:1360
+ db 0feh, 0c8h
+ ; dec al ; fe c8 ; 0xfee24 orgs.asm:1361
+ jne short 0ee1ch ; 75 f4 ; 0xfee26 orgs.asm:1362
+ db 08ah, 0cdh
+ ; mov cl, ch ; 8a cd ; 0xfee28 orgs.asm:1365
+ db 08ah, 0eah
+ ; mov ch, dl ; 8a ea ; 0xfee2a orgs.asm:1366
+ db 08ah, 0d6h
+ ; mov dl, dh ; 8a d6 ; 0xfee2c orgs.asm:1367
+ db 032h, 0f6h
+ ; xor dh, dh ; 32 f6 ; 0xfee2e orgs.asm:1368
+ mov word [0046ch], cx ; 89 0e 6c 04 ; 0xfee30 orgs.asm:1369
+ mov word [0046eh], dx ; 89 16 6e 04 ; 0xfee34 orgs.asm:1370
+ mov byte [00470h], dh ; 88 36 70 04 ; 0xfee38 orgs.asm:1371
+ retn ; c3 ; 0xfee3c orgs.asm:1419
+ ; disGetNextSymbol 0xfee3d LB 0x11c3 -> off=0x0 cb=000000000000011a uValue=00000000000f0e3d 'biosorg_check_before_or_at_0EF55h'
+biosorg_check_before_or_at_0EF55h: ; 0xfee3d LB 0x11a
+ times 0x118 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfef57 LB 0x10a9 -> off=0x0 cb=000000000000003b uValue=00000000000f0f57 'int0e_handler'
+int0e_handler: ; 0xfef57 LB 0x3b
+ push ax ; 50 ; 0xfef57 orgs.asm:1430
+ push dx ; 52 ; 0xfef58 orgs.asm:1431
+ mov dx, 003f4h ; ba f4 03 ; 0xfef59 orgs.asm:1432
+ in AL, DX ; ec ; 0xfef5c orgs.asm:1433
+ and AL, strict byte 0c0h ; 24 c0 ; 0xfef5d orgs.asm:1434
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xfef5f orgs.asm:1435
+ je short 0ef81h ; 74 1e ; 0xfef61 orgs.asm:1436
+ mov dx, 003f5h ; ba f5 03 ; 0xfef63 orgs.asm:1437
+ mov AL, strict byte 008h ; b0 08 ; 0xfef66 orgs.asm:1438
+ out DX, AL ; ee ; 0xfef68 orgs.asm:1439
+ mov dx, 003f4h ; ba f4 03 ; 0xfef69 orgs.asm:1441
+ in AL, DX ; ec ; 0xfef6c orgs.asm:1442
+ and AL, strict byte 0c0h ; 24 c0 ; 0xfef6d orgs.asm:1443
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xfef6f orgs.asm:1444
+ jne short 0ef69h ; 75 f6 ; 0xfef71 orgs.asm:1445
+ mov dx, 003f5h ; ba f5 03 ; 0xfef73 orgs.asm:1448
+ in AL, DX ; ec ; 0xfef76 orgs.asm:1449
+ mov dx, 003f4h ; ba f4 03 ; 0xfef77 orgs.asm:1450
+ in AL, DX ; ec ; 0xfef7a orgs.asm:1451
+ and AL, strict byte 0c0h ; 24 c0 ; 0xfef7b orgs.asm:1452
+ cmp AL, strict byte 0c0h ; 3c c0 ; 0xfef7d orgs.asm:1453
+ je short 0ef73h ; 74 f2 ; 0xfef7f orgs.asm:1454
+ push DS ; 1e ; 0xfef81 orgs.asm:1457
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xfef82 orgs.asm:1458
+ mov ds, ax ; 8e d8 ; 0xfef84 orgs.asm:1459
+ call 0e034h ; e8 ab f0 ; 0xfef86 orgs.asm:1460
+ or byte [0043eh], 080h ; 80 0e 3e 04 80 ; 0xfef89 orgs.asm:1462
+ pop DS ; 1f ; 0xfef8e orgs.asm:1463
+ pop dx ; 5a ; 0xfef8f orgs.asm:1464
+ pop ax ; 58 ; 0xfef90 orgs.asm:1465
+ iret ; cf ; 0xfef91 orgs.asm:1466
+ ; disGetNextSymbol 0xfef92 LB 0x106e -> off=0x0 cb=0000000000000035 uValue=00000000000f0f92 'biosorg_check_before_or_at_0EFC5h'
+biosorg_check_before_or_at_0EFC5h: ; 0xfef92 LB 0x35
+ times 0x33 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfefc7 LB 0x1039 -> off=0x0 cb=000000000000000b uValue=00000000000f0fc7 '_diskette_param_table'
+_diskette_param_table: ; 0xfefc7 LB 0xb
+ scasw ; af ; 0xfefc7
+ add ah, byte [di] ; 02 25 ; 0xfefc8
+ add dl, byte [bp+si] ; 02 12 ; 0xfefca
+ db 01bh, 0ffh
+ ; sbb di, di ; 1b ff ; 0xfefcc
+ insb ; 6c ; 0xfefce
+ db 0f6h
+ invd ; 0f 08 ; 0xfefd0
+ ; disGetNextSymbol 0xfefd2 LB 0x102e -> off=0x0 cb=0000000000000002 uValue=00000000000f0fd2 'biosorg_check_at_0EFD2h'
+biosorg_check_at_0EFD2h: ; 0xfefd2 LB 0x2
+ jmp short 0efd4h ; eb 00 ; 0xfefd2 orgs.asm:1493
+ ; disGetNextSymbol 0xfefd4 LB 0x102c -> off=0x0 cb=000000000000001b uValue=00000000000f0fd4 'int17_handler'
+int17_handler: ; 0xfefd4 LB 0x1b
+ push DS ; 1e ; 0xfefd4 orgs.asm:1496
+ push ES ; 06 ; 0xfefd5 orgs.asm:1497
+ push ax ; 50 ; 0xfefd6 orgs.asm:99
+ push cx ; 51 ; 0xfefd7 orgs.asm:100
+ push dx ; 52 ; 0xfefd8 orgs.asm:101
+ push bx ; 53 ; 0xfefd9 orgs.asm:102
+ push sp ; 54 ; 0xfefda orgs.asm:103
+ push bp ; 55 ; 0xfefdb orgs.asm:104
+ push si ; 56 ; 0xfefdc orgs.asm:105
+ push di ; 57 ; 0xfefdd orgs.asm:106
+ push CS ; 0e ; 0xfefde orgs.asm:104
+ pop DS ; 1f ; 0xfefdf orgs.asm:105
+ cld ; fc ; 0xfefe0 orgs.asm:106
+ call 07339h ; e8 55 83 ; 0xfefe1 orgs.asm:1500
+ pop di ; 5f ; 0xfefe4 orgs.asm:116
+ pop si ; 5e ; 0xfefe5 orgs.asm:117
+ pop bp ; 5d ; 0xfefe6 orgs.asm:118
+ pop bx ; 5b ; 0xfefe7 orgs.asm:119
+ pop bx ; 5b ; 0xfefe8 orgs.asm:120
+ pop dx ; 5a ; 0xfefe9 orgs.asm:121
+ pop cx ; 59 ; 0xfefea orgs.asm:122
+ pop ax ; 58 ; 0xfefeb orgs.asm:123
+ pop ES ; 07 ; 0xfefec orgs.asm:1502
+ pop DS ; 1f ; 0xfefed orgs.asm:1503
+ iret ; cf ; 0xfefee orgs.asm:1504
+ ; disGetNextSymbol 0xfefef LB 0x1011 -> off=0x0 cb=0000000000000006 uValue=00000000000f0fef '_pmode_IDT'
+_pmode_IDT: ; 0xfefef LB 0x6
+ db 000h, 000h, 000h, 000h, 00fh, 000h
+ ; disGetNextSymbol 0xfeff5 LB 0x100b -> off=0x0 cb=0000000000000006 uValue=00000000000f0ff5 '_rmode_IDT'
+_rmode_IDT: ; 0xfeff5 LB 0x6
+ db 0ffh, 003h, 000h, 000h, 000h, 000h
+ ; disGetNextSymbol 0xfeffb LB 0x1005 -> off=0x0 cb=0000000000000001 uValue=00000000000f0ffb 'int1c_handler'
+int1c_handler: ; 0xfeffb LB 0x1
+ iret ; cf ; 0xfeffb orgs.asm:1539
+ ; disGetNextSymbol 0xfeffc LB 0x1004 -> off=0x0 cb=0000000000000049 uValue=00000000000f0ffc 'biosorg_check_before_or_at_0F043h'
+biosorg_check_before_or_at_0F043h: ; 0xfeffc LB 0x49
+ times 0x47 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xff045 LB 0xfbb -> off=0x0 cb=0000000000000001 uValue=00000000000f1045 'biosorg_check_at_0F045h'
+biosorg_check_at_0F045h: ; 0xff045 LB 0x1
+ iret ; cf ; 0xff045 orgs.asm:1548
+ ; disGetNextSymbol 0xff046 LB 0xfba -> off=0x0 cb=000000000000001f uValue=00000000000f1046 'biosorg_check_before_or_at_0F063h'
+biosorg_check_before_or_at_0F063h: ; 0xff046 LB 0x1f
+ times 0x1d db 0
+ db 'XM'
+ ; disGetNextSymbol 0xff065 LB 0xf9b -> off=0x0 cb=0000000000000001 uValue=00000000000f1065 'int10_handler'
+int10_handler: ; 0xff065 LB 0x1
+ iret ; cf ; 0xff065 orgs.asm:1557
+ ; disGetNextSymbol 0xff066 LB 0xf9a -> off=0x0 cb=000000000000003e uValue=00000000000f1066 'biosorg_check_before_or_at_0F0A2h'
+biosorg_check_before_or_at_0F0A2h: ; 0xff066 LB 0x3e
+ times 0x3c db 0
+ db 'XM'
+ ; disGetNextSymbol 0xff0a4 LB 0xf5c -> off=0x0 cb=0000000000000008 uValue=00000000000f10a4 'biosorg_check_at_0F0A4h'
+biosorg_check_at_0F0A4h: ; 0xff0a4 LB 0x8
+ push CS ; 0e ; 0xff0a4 orgs.asm:104
+ pop DS ; 1f ; 0xff0a5 orgs.asm:105
+ cld ; fc ; 0xff0a6 orgs.asm:106
+ call 01700h ; e8 56 26 ; 0xff0a7 orgs.asm:1572
+ hlt ; f4 ; 0xff0aa orgs.asm:1574
+ iret ; cf ; 0xff0ab orgs.asm:1575
+ ; disGetNextSymbol 0xff0ac LB 0xf54 -> off=0x0 cb=0000000000000095 uValue=00000000000f10ac 'int19_relocated'
+int19_relocated: ; 0xff0ac LB 0x95
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff0ac orgs.asm:1586
+ mov ax, word [bp+002h] ; 8b 46 02 ; 0xff0ae orgs.asm:1587
+ cmp ax, 0f000h ; 3d 00 f0 ; 0xff0b1 orgs.asm:1588
+ je short 0f0c3h ; 74 0d ; 0xff0b4 orgs.asm:1589
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xff0b6 orgs.asm:1591
+ mov ds, ax ; 8e d8 ; 0xff0b8 orgs.asm:1592
+ mov ax, 01234h ; b8 34 12 ; 0xff0ba orgs.asm:1593
+ mov word [001d8h], ax ; a3 d8 01 ; 0xff0bd orgs.asm:1594
+ jmp near 0e05bh ; e9 98 ef ; 0xff0c0 orgs.asm:1595
+ push CS ; 0e ; 0xff0c3 orgs.asm:104
+ pop DS ; 1f ; 0xff0c4 orgs.asm:105
+ cld ; fc ; 0xff0c5 orgs.asm:106
+ push bp ; 55 ; 0xff0c6 orgs.asm:1602
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff0c7 orgs.asm:1603
+ mov ax, strict word 00001h ; b8 01 00 ; 0xff0c9 orgs.asm:1606
+ push ax ; 50 ; 0xff0cc orgs.asm:1607
+ call 04cfah ; e8 2a 5c ; 0xff0cd orgs.asm:1608
+ inc sp ; 44 ; 0xff0d0 orgs.asm:1609
+ inc sp ; 44 ; 0xff0d1 orgs.asm:1610
+ test ax, ax ; 85 c0 ; 0xff0d2 orgs.asm:1611
+ jne short 0f0fdh ; 75 27 ; 0xff0d4 orgs.asm:1612
+ mov ax, strict word 00002h ; b8 02 00 ; 0xff0d6 orgs.asm:1615
+ push ax ; 50 ; 0xff0d9 orgs.asm:1616
+ call 04cfah ; e8 1d 5c ; 0xff0da orgs.asm:1617
+ inc sp ; 44 ; 0xff0dd orgs.asm:1618
+ inc sp ; 44 ; 0xff0de orgs.asm:1619
+ test ax, ax ; 85 c0 ; 0xff0df orgs.asm:1620
+ jne short 0f0fdh ; 75 1a ; 0xff0e1 orgs.asm:1621
+ mov ax, strict word 00003h ; b8 03 00 ; 0xff0e3 orgs.asm:1624
+ push ax ; 50 ; 0xff0e6 orgs.asm:1625
+ call 04cfah ; e8 10 5c ; 0xff0e7 orgs.asm:1626
+ inc sp ; 44 ; 0xff0ea orgs.asm:1627
+ inc sp ; 44 ; 0xff0eb orgs.asm:1628
+ test ax, ax ; 85 c0 ; 0xff0ec orgs.asm:1629
+ jne short 0f0fdh ; 75 0d ; 0xff0ee orgs.asm:1630
+ mov ax, strict word 00004h ; b8 04 00 ; 0xff0f0 orgs.asm:1633
+ push ax ; 50 ; 0xff0f3 orgs.asm:1634
+ call 04cfah ; e8 03 5c ; 0xff0f4 orgs.asm:1635
+ inc sp ; 44 ; 0xff0f7 orgs.asm:1636
+ inc sp ; 44 ; 0xff0f8 orgs.asm:1637
+ test ax, ax ; 85 c0 ; 0xff0f9 orgs.asm:1638
+ je short 0f0a4h ; 74 a7 ; 0xff0fb orgs.asm:1639
+ mov word [byte bp+000h], ax ; 89 46 00 ; 0xff0fd orgs.asm:1645
+ sal ax, 1 ; d1 e0 ; 0xff100 orgs.asm:212
+ sal ax, 1 ; d1 e0 ; 0xff102 orgs.asm:215
+ sal ax, 1 ; d1 e0 ; 0xff104 orgs.asm:218
+ sal ax, 1 ; d1 e0 ; 0xff106 orgs.asm:221
+ mov word [bp+002h], ax ; 89 46 02 ; 0xff108 orgs.asm:1647
+ mov ax, word [byte bp+000h] ; 8b 46 00 ; 0xff10b orgs.asm:1648
+ and ax, 0f000h ; 25 00 f0 ; 0xff10e orgs.asm:1657
+ mov word [bp+004h], ax ; 89 46 04 ; 0xff111 orgs.asm:1658
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xff114 orgs.asm:1659
+ mov ds, ax ; 8e d8 ; 0xff116 orgs.asm:1660
+ mov es, ax ; 8e c0 ; 0xff118 orgs.asm:1661
+ mov word [byte bp+000h], ax ; 89 46 00 ; 0xff11a orgs.asm:1662
+ mov ax, 0aa55h ; b8 55 aa ; 0xff11d orgs.asm:1663
+ pop bp ; 5d ; 0xff120 orgs.asm:1665
+ iret ; cf ; 0xff121 orgs.asm:1666
+ or cx, word [bp+si] ; 0b 0a ; 0xff122
+ or word [bp+di], cx ; 09 0b ; 0xff124
+ push eax ; 66 50 ; 0xff126 orgs.asm:88
+ mov eax, strict dword 000800000h ; 66 b8 00 00 80 00 ; 0xff128 orgs.asm:89
+ db 08bh, 0c3h
+ ; mov ax, bx ; 8b c3 ; 0xff12e orgs.asm:90
+ sal eax, 008h ; 66 c1 e0 08 ; 0xff130 orgs.asm:91
+ and dl, 0fch ; 80 e2 fc ; 0xff134 orgs.asm:92
+ db 00ah, 0c2h
+ ; or al, dl ; 0a c2 ; 0xff137 orgs.asm:93
+ mov dx, 00cf8h ; ba f8 0c ; 0xff139 orgs.asm:94
+ out DX, eax ; 66 ef ; 0xff13c orgs.asm:95
+ pop eax ; 66 58 ; 0xff13e orgs.asm:96
+ retn ; c3 ; 0xff140 orgs.asm:97
+ ; disGetNextSymbol 0xff141 LB 0xebf -> off=0x0 cb=0000000000000012 uValue=00000000000f1141 'pcibios_init_iomem_bases'
+pcibios_init_iomem_bases: ; 0xff141 LB 0x12
+ push bp ; 55 ; 0xff141 orgs.asm:100
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff142 orgs.asm:101
+ mov eax, strict dword 00124f9fdh ; 66 b8 fd f9 24 01 ; 0xff144 orgs.asm:103
+ mov dx, 00410h ; ba 10 04 ; 0xff14a orgs.asm:104
+ out DX, eax ; 66 ef ; 0xff14d orgs.asm:105
+ db 08bh, 0e5h
+ ; mov sp, bp ; 8b e5 ; 0xff14f orgs.asm:218
+ pop bp ; 5d ; 0xff151 orgs.asm:219
+ retn ; c3 ; 0xff152 orgs.asm:220
+ ; disGetNextSymbol 0xff153 LB 0xead -> off=0x0 cb=000000000000000c uValue=00000000000f1153 'pcibios_init_set_elcr'
+pcibios_init_set_elcr: ; 0xff153 LB 0xc
+ push ax ; 50 ; 0xff153 orgs.asm:223
+ push cx ; 51 ; 0xff154 orgs.asm:224
+ mov dx, 004d0h ; ba d0 04 ; 0xff155 orgs.asm:225
+ test AL, strict byte 008h ; a8 08 ; 0xff158 orgs.asm:226
+ je short 0f15fh ; 74 03 ; 0xff15a orgs.asm:227
+ inc dx ; 42 ; 0xff15c orgs.asm:229
+ and AL, strict byte 007h ; 24 07 ; 0xff15d orgs.asm:230
+ ; disGetNextSymbol 0xff15f LB 0xea1 -> off=0x0 cb=000000000000000d uValue=00000000000f115f 'is_master_pic'
+is_master_pic: ; 0xff15f LB 0xd
+ db 08ah, 0c8h
+ ; mov cl, al ; 8a c8 ; 0xff15f orgs.asm:232
+ mov BL, strict byte 001h ; b3 01 ; 0xff161 orgs.asm:233
+ sal bl, CL ; d2 e3 ; 0xff163 orgs.asm:234
+ in AL, DX ; ec ; 0xff165 orgs.asm:235
+ db 00ah, 0c3h
+ ; or al, bl ; 0a c3 ; 0xff166 orgs.asm:236
+ out DX, AL ; ee ; 0xff168 orgs.asm:237
+ pop cx ; 59 ; 0xff169 orgs.asm:238
+ pop ax ; 58 ; 0xff16a orgs.asm:239
+ retn ; c3 ; 0xff16b orgs.asm:240
+ ; disGetNextSymbol 0xff16c LB 0xe94 -> off=0x0 cb=0000000000000034 uValue=00000000000f116c 'pcibios_init_irqs'
+pcibios_init_irqs: ; 0xff16c LB 0x34
+ push DS ; 1e ; 0xff16c orgs.asm:243
+ push bp ; 55 ; 0xff16d orgs.asm:244
+ mov ax, 0f000h ; b8 00 f0 ; 0xff16e orgs.asm:245
+ mov ds, ax ; 8e d8 ; 0xff171 orgs.asm:246
+ pop bp ; 5d ; 0xff173 orgs.asm:353
+ pop DS ; 1f ; 0xff174 orgs.asm:354
+ retn ; c3 ; 0xff175 orgs.asm:355
+ mov ax, ax ; 89 c0 ; 0xff176
+ mov ax, ax ; 89 c0 ; 0xff178
+ mov ax, ax ; 89 c0 ; 0xff17a
+ mov ax, ax ; 89 c0 ; 0xff17c
+ mov ax, ax ; 89 c0 ; 0xff17e
+ and AL, strict byte 050h ; 24 50 ; 0xff180
+ dec cx ; 49 ; 0xff182
+ push dx ; 52 ; 0xff183
+ add byte [bx+di], al ; 00 01 ; 0xff184
+ add byte [bp+si], al ; 00 02 ; 0xff186
+ add byte [bx+si], cl ; 00 08 ; 0xff188
+ add byte [bx+si], al ; 00 00 ; 0xff18a
+ xchg byte [bx+si+07000h], al ; 86 80 00 70 ; 0xff18c
+ times 0xf db 0
+ db 031h
+ ; disGetNextSymbol 0xff1a0 LB 0xe60 -> off=0x0 cb=00000000000001e0 uValue=00000000000f11a0 '_pci_routing_table'
+_pci_routing_table: ; 0xff1a0 LB 0x1e0
+ db 000h, 008h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 000h, 000h
+ db 000h, 010h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 001h, 000h
+ db 000h, 018h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 002h, 000h
+ db 000h, 020h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 003h, 000h
+ db 000h, 028h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 004h, 000h
+ db 000h, 030h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 005h, 000h
+ db 000h, 038h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 006h, 000h
+ db 000h, 040h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 007h, 000h
+ db 000h, 048h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 008h, 000h
+ db 000h, 050h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 009h, 000h
+ db 000h, 058h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 00ah, 000h
+ db 000h, 060h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 00bh, 000h
+ db 000h, 068h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 00ch, 000h
+ db 000h, 070h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 00dh, 000h
+ db 000h, 078h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 00eh, 000h
+ db 000h, 080h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 00fh, 000h
+ db 000h, 088h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 010h, 000h
+ db 000h, 090h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 011h, 000h
+ db 000h, 098h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 012h, 000h
+ db 000h, 0a0h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 013h, 000h
+ db 000h, 0a8h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 014h, 000h
+ db 000h, 0b0h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 015h, 000h
+ db 000h, 0b8h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 016h, 000h
+ db 000h, 0c0h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 017h, 000h
+ db 000h, 0c8h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 018h, 000h
+ db 000h, 0d0h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 019h, 000h
+ db 000h, 0d8h, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 01ah, 000h
+ db 000h, 0e0h, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 01bh, 000h
+ db 000h, 0e8h, 060h, 0f8h, 0deh, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 01ch, 000h
+ db 000h, 0f0h, 061h, 0f8h, 0deh, 062h, 0f8h, 0deh, 063h, 0f8h, 0deh, 060h, 0f8h, 0deh, 01dh, 000h
+ ; disGetNextSymbol 0xff380 LB 0xc80 -> off=0x0 cb=0000000000000002 uValue=00000000000f1380 '_pci_routing_table_size'
+_pci_routing_table_size: ; 0xff380 LB 0x2
+ loopne 0f383h ; e0 01 ; 0xff380
+ ; disGetNextSymbol 0xff382 LB 0xc7e -> off=0x0 cb=00000000000004bf uValue=00000000000f1382 'biosorg_check_before_or_at_0F83Fh'
+biosorg_check_before_or_at_0F83Fh: ; 0xff382 LB 0x4bf
+ times 0x4bd db 0
+ db 'XM'
+ ; disGetNextSymbol 0xff841 LB 0x7bf -> off=0x0 cb=000000000000000c uValue=00000000000f1841 'int12_handler'
+int12_handler: ; 0xff841 LB 0xc
+ sti ; fb ; 0xff841 orgs.asm:1680
+ push DS ; 1e ; 0xff842 orgs.asm:1681
+ mov ax, strict word 00040h ; b8 40 00 ; 0xff843 orgs.asm:1682
+ mov ds, ax ; 8e d8 ; 0xff846 orgs.asm:1683
+ mov ax, word [00013h] ; a1 13 00 ; 0xff848 orgs.asm:1684
+ pop DS ; 1f ; 0xff84b orgs.asm:1685
+ iret ; cf ; 0xff84c orgs.asm:1686
+ ; disGetNextSymbol 0xff84d LB 0x7b3 -> off=0x0 cb=000000000000000c uValue=00000000000f184d 'int11_handler'
+int11_handler: ; 0xff84d LB 0xc
+ sti ; fb ; 0xff84d orgs.asm:1695
+ push DS ; 1e ; 0xff84e orgs.asm:1696
+ mov ax, strict word 00040h ; b8 40 00 ; 0xff84f orgs.asm:1697
+ mov ds, ax ; 8e d8 ; 0xff852 orgs.asm:1698
+ mov ax, word [00010h] ; a1 10 00 ; 0xff854 orgs.asm:1699
+ pop DS ; 1f ; 0xff857 orgs.asm:1700
+ iret ; cf ; 0xff858 orgs.asm:1701
+ ; disGetNextSymbol 0xff859 LB 0x7a7 -> off=0x0 cb=000000000000002d uValue=00000000000f1859 'int15_handler'
+int15_handler: ; 0xff859 LB 0x2d
+ pushfw ; 9c ; 0xff859 orgs.asm:1730
+ push DS ; 1e ; 0xff85a orgs.asm:1731
+ push ES ; 06 ; 0xff85b orgs.asm:1732
+ push CS ; 0e ; 0xff85c orgs.asm:104
+ pop DS ; 1f ; 0xff85d orgs.asm:105
+ cld ; fc ; 0xff85e orgs.asm:106
+ push ax ; 50 ; 0xff85f orgs.asm:99
+ push cx ; 51 ; 0xff860 orgs.asm:100
+ push dx ; 52 ; 0xff861 orgs.asm:101
+ push bx ; 53 ; 0xff862 orgs.asm:102
+ push sp ; 54 ; 0xff863 orgs.asm:103
+ push bp ; 55 ; 0xff864 orgs.asm:104
+ push si ; 56 ; 0xff865 orgs.asm:105
+ push di ; 57 ; 0xff866 orgs.asm:106
+ cmp ah, 053h ; 80 fc 53 ; 0xff867 orgs.asm:1743
+ je short 0f881h ; 74 15 ; 0xff86a orgs.asm:1744
+ cmp ah, 0c2h ; 80 fc c2 ; 0xff86c orgs.asm:1745
+ je short 0f886h ; 74 15 ; 0xff86f orgs.asm:1746
+ call 066dah ; e8 66 6e ; 0xff871 orgs.asm:1748
+ pop di ; 5f ; 0xff874 orgs.asm:116
+ pop si ; 5e ; 0xff875 orgs.asm:117
+ pop bp ; 5d ; 0xff876 orgs.asm:118
+ pop bx ; 5b ; 0xff877 orgs.asm:119
+ pop bx ; 5b ; 0xff878 orgs.asm:120
+ pop dx ; 5a ; 0xff879 orgs.asm:121
+ pop cx ; 59 ; 0xff87a orgs.asm:122
+ pop ax ; 58 ; 0xff87b orgs.asm:123
+ pop ES ; 07 ; 0xff87c orgs.asm:1754
+ pop DS ; 1f ; 0xff87d orgs.asm:1755
+ popfw ; 9d ; 0xff87e orgs.asm:1756
+ jmp short 0f88bh ; eb 0a ; 0xff87f orgs.asm:1757
+ call 0963eh ; e8 ba 9d ; 0xff881 orgs.asm:1760
+ jmp short 0f874h ; eb ee ; 0xff884 orgs.asm:1761
+ ; disGetNextSymbol 0xff886 LB 0x77a -> off=0x0 cb=0000000000000005 uValue=00000000000f1886 'int15_handler_mouse'
+int15_handler_mouse: ; 0xff886 LB 0x5
+ call 06fb9h ; e8 30 77 ; 0xff886 orgs.asm:1764
+ jmp short 0f874h ; eb e9 ; 0xff889 orgs.asm:1765
+ ; disGetNextSymbol 0xff88b LB 0x775 -> off=0x0 cb=000000000000001a uValue=00000000000f188b 'iret_modify_cf'
+iret_modify_cf: ; 0xff88b LB 0x1a
+ jc short 0f89bh ; 72 0e ; 0xff88b orgs.asm:1782
+ push bp ; 55 ; 0xff88d orgs.asm:1783
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff88e orgs.asm:1784
+ and byte [bp+006h], 0feh ; 80 66 06 fe ; 0xff890 orgs.asm:1785
+ or word [bp+006h], 00200h ; 81 4e 06 00 02 ; 0xff894 orgs.asm:1786
+ pop bp ; 5d ; 0xff899 orgs.asm:1787
+ iret ; cf ; 0xff89a orgs.asm:1788
+ push bp ; 55 ; 0xff89b orgs.asm:1790
+ db 08bh, 0ech
+ ; mov bp, sp ; 8b ec ; 0xff89c orgs.asm:1791
+ or word [bp+006h], 00201h ; 81 4e 06 01 02 ; 0xff89e orgs.asm:1792
+ pop bp ; 5d ; 0xff8a3 orgs.asm:1793
+ iret ; cf ; 0xff8a4 orgs.asm:1794
+ ; disGetNextSymbol 0xff8a5 LB 0x75b -> off=0x0 cb=000000000000003a uValue=00000000000f18a5 'int74_handler'
+int74_handler: ; 0xff8a5 LB 0x3a
+ sti ; fb ; 0xff8a5 orgs.asm:1801
+ push ax ; 50 ; 0xff8a6 orgs.asm:99
+ push cx ; 51 ; 0xff8a7 orgs.asm:100
+ push dx ; 52 ; 0xff8a8 orgs.asm:101
+ push bx ; 53 ; 0xff8a9 orgs.asm:102
+ push sp ; 54 ; 0xff8aa orgs.asm:103
+ push bp ; 55 ; 0xff8ab orgs.asm:104
+ push si ; 56 ; 0xff8ac orgs.asm:105
+ push di ; 57 ; 0xff8ad orgs.asm:106
+ push ES ; 06 ; 0xff8ae orgs.asm:1803
+ push DS ; 1e ; 0xff8af orgs.asm:1804
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xff8b0 orgs.asm:1805
+ push ax ; 50 ; 0xff8b2 orgs.asm:1806
+ push ax ; 50 ; 0xff8b3 orgs.asm:1807
+ push ax ; 50 ; 0xff8b4 orgs.asm:1808
+ push ax ; 50 ; 0xff8b5 orgs.asm:1809
+ push ax ; 50 ; 0xff8b6 orgs.asm:1810
+ push CS ; 0e ; 0xff8b7 orgs.asm:104
+ pop DS ; 1f ; 0xff8b8 orgs.asm:105
+ cld ; fc ; 0xff8b9 orgs.asm:106
+ call 06f0bh ; e8 4e 76 ; 0xff8ba orgs.asm:1812
+ pop cx ; 59 ; 0xff8bd orgs.asm:1813
+ jcxz 0f8cdh ; e3 0d ; 0xff8be orgs.asm:1814
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xff8c0 orgs.asm:1820
+ push ax ; 50 ; 0xff8c2 orgs.asm:1821
+ pop DS ; 1f ; 0xff8c3 orgs.asm:1823
+ push word [0040eh] ; ff 36 0e 04 ; 0xff8c4 orgs.asm:1824
+ pop DS ; 1f ; 0xff8c8 orgs.asm:1825
+ call far [word 00022h] ; ff 1e 22 00 ; 0xff8c9 orgs.asm:1826
+ cli ; fa ; 0xff8cd orgs.asm:1828
+ call 0e030h ; e8 5f e7 ; 0xff8ce orgs.asm:1829
+ add sp, strict byte 00008h ; 83 c4 08 ; 0xff8d1 orgs.asm:1830
+ pop DS ; 1f ; 0xff8d4 orgs.asm:1831
+ pop ES ; 07 ; 0xff8d5 orgs.asm:1832
+ pop di ; 5f ; 0xff8d6 orgs.asm:116
+ pop si ; 5e ; 0xff8d7 orgs.asm:117
+ pop bp ; 5d ; 0xff8d8 orgs.asm:118
+ pop bx ; 5b ; 0xff8d9 orgs.asm:119
+ pop bx ; 5b ; 0xff8da orgs.asm:120
+ pop dx ; 5a ; 0xff8db orgs.asm:121
+ pop cx ; 59 ; 0xff8dc orgs.asm:122
+ pop ax ; 58 ; 0xff8dd orgs.asm:123
+ iret ; cf ; 0xff8de orgs.asm:1834
+ ; disGetNextSymbol 0xff8df LB 0x721 -> off=0x0 cb=0000000000000012 uValue=00000000000f18df 'int76_handler'
+int76_handler: ; 0xff8df LB 0x12
+ push ax ; 50 ; 0xff8df orgs.asm:1841
+ push DS ; 1e ; 0xff8e0 orgs.asm:1842
+ mov ax, strict word 00040h ; b8 40 00 ; 0xff8e1 orgs.asm:1843
+ mov ds, ax ; 8e d8 ; 0xff8e4 orgs.asm:1844
+ mov byte [0008eh], 0ffh ; c6 06 8e 00 ff ; 0xff8e6 orgs.asm:1845
+ call 0e030h ; e8 42 e7 ; 0xff8eb orgs.asm:1846
+ pop DS ; 1f ; 0xff8ee orgs.asm:1847
+ pop ax ; 58 ; 0xff8ef orgs.asm:1848
+ iret ; cf ; 0xff8f0 orgs.asm:1849
+ ; disGetNextSymbol 0xff8f1 LB 0x70f -> off=0x0 cb=000000000000002d uValue=00000000000f18f1 'int70_handler'
+int70_handler: ; 0xff8f1 LB 0x2d
+ push ES ; 06 ; 0xff8f1 orgs.asm:1858
+ push DS ; 1e ; 0xff8f2 orgs.asm:1859
+ push ax ; 50 ; 0xff8f3 orgs.asm:99
+ push cx ; 51 ; 0xff8f4 orgs.asm:100
+ push dx ; 52 ; 0xff8f5 orgs.asm:101
+ push bx ; 53 ; 0xff8f6 orgs.asm:102
+ push sp ; 54 ; 0xff8f7 orgs.asm:103
+ push bp ; 55 ; 0xff8f8 orgs.asm:104
+ push si ; 56 ; 0xff8f9 orgs.asm:105
+ push di ; 57 ; 0xff8fa orgs.asm:106
+ push CS ; 0e ; 0xff8fb orgs.asm:104
+ pop DS ; 1f ; 0xff8fc orgs.asm:105
+ cld ; fc ; 0xff8fd orgs.asm:106
+ call 06bbfh ; e8 be 72 ; 0xff8fe orgs.asm:1862
+ pop di ; 5f ; 0xff901 orgs.asm:116
+ pop si ; 5e ; 0xff902 orgs.asm:117
+ pop bp ; 5d ; 0xff903 orgs.asm:118
+ pop bx ; 5b ; 0xff904 orgs.asm:119
+ pop bx ; 5b ; 0xff905 orgs.asm:120
+ pop dx ; 5a ; 0xff906 orgs.asm:121
+ pop cx ; 59 ; 0xff907 orgs.asm:122
+ pop ax ; 58 ; 0xff908 orgs.asm:123
+ pop DS ; 1f ; 0xff909 orgs.asm:1864
+ pop ES ; 07 ; 0xff90a orgs.asm:1865
+ iret ; cf ; 0xff90b orgs.asm:1866
+ jnbe short 0f913h ; 77 05 ; 0xff90c orgs.asm:1876
+ cmp ax, 000b0h ; 3d b0 00 ; 0xff90e orgs.asm:1877
+ jc short 0f91bh ; 72 08 ; 0xff911 orgs.asm:1878
+ db 033h, 0d2h
+ ; xor dx, dx ; 33 d2 ; 0xff913 orgs.asm:1881
+ db 033h, 0c0h
+ ; xor ax, ax ; 33 c0 ; 0xff915 orgs.asm:1882
+ inc byte [word 00070h] ; fe 06 70 00 ; 0xff917 orgs.asm:1884
+ jmp near 0fec1h ; e9 a3 05 ; 0xff91b orgs.asm:1886
+ ; disGetNextSymbol 0xff91e LB 0x6e2 -> off=0x0 cb=0000000000000150 uValue=00000000000f191e 'biosorg_check_before_or_at_0FA6Ch'
+biosorg_check_before_or_at_0FA6Ch: ; 0xff91e LB 0x150
+ times 0x14e db 0
+ db 'XM'
+ ; disGetNextSymbol 0xffa6e LB 0x592 -> off=0x0 cb=0000000000000400 uValue=00000000000f1a6e 'font8x8'
+font8x8: ; 0xffa6e LB 0x400
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 081h, 0a5h, 081h, 0bdh, 099h, 081h, 07eh
+ db 07eh, 0ffh, 0dbh, 0ffh, 0c3h, 0e7h, 0ffh, 07eh, 06ch, 0feh, 0feh, 0feh, 07ch, 038h, 010h, 000h
+ db 010h, 038h, 07ch, 0feh, 07ch, 038h, 010h, 000h, 038h, 07ch, 038h, 0feh, 0feh, 07ch, 038h, 07ch
+ db 010h, 010h, 038h, 07ch, 0feh, 07ch, 038h, 07ch, 000h, 000h, 018h, 03ch, 03ch, 018h, 000h, 000h
+ db 0ffh, 0ffh, 0e7h, 0c3h, 0c3h, 0e7h, 0ffh, 0ffh, 000h, 03ch, 066h, 042h, 042h, 066h, 03ch, 000h
+ db 0ffh, 0c3h, 099h, 0bdh, 0bdh, 099h, 0c3h, 0ffh, 00fh, 007h, 00fh, 07dh, 0cch, 0cch, 0cch, 078h
+ db 03ch, 066h, 066h, 066h, 03ch, 018h, 07eh, 018h, 03fh, 033h, 03fh, 030h, 030h, 070h, 0f0h, 0e0h
+ db 07fh, 063h, 07fh, 063h, 063h, 067h, 0e6h, 0c0h, 099h, 05ah, 03ch, 0e7h, 0e7h, 03ch, 05ah, 099h
+ db 080h, 0e0h, 0f8h, 0feh, 0f8h, 0e0h, 080h, 000h, 002h, 00eh, 03eh, 0feh, 03eh, 00eh, 002h, 000h
+ db 018h, 03ch, 07eh, 018h, 018h, 07eh, 03ch, 018h, 066h, 066h, 066h, 066h, 066h, 000h, 066h, 000h
+ db 07fh, 0dbh, 0dbh, 07bh, 01bh, 01bh, 01bh, 000h, 03eh, 063h, 038h, 06ch, 06ch, 038h, 0cch, 078h
+ db 000h, 000h, 000h, 000h, 07eh, 07eh, 07eh, 000h, 018h, 03ch, 07eh, 018h, 07eh, 03ch, 018h, 0ffh
+ db 018h, 03ch, 07eh, 018h, 018h, 018h, 018h, 000h, 018h, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h
+ db 000h, 018h, 00ch, 0feh, 00ch, 018h, 000h, 000h, 000h, 030h, 060h, 0feh, 060h, 030h, 000h, 000h
+ db 000h, 000h, 0c0h, 0c0h, 0c0h, 0feh, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h
+ db 000h, 018h, 03ch, 07eh, 0ffh, 0ffh, 000h, 000h, 000h, 0ffh, 0ffh, 07eh, 03ch, 018h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 078h, 078h, 030h, 030h, 000h, 030h, 000h
+ db 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h, 000h, 06ch, 06ch, 0feh, 06ch, 0feh, 06ch, 06ch, 000h
+ db 030h, 07ch, 0c0h, 078h, 00ch, 0f8h, 030h, 000h, 000h, 0c6h, 0cch, 018h, 030h, 066h, 0c6h, 000h
+ db 038h, 06ch, 038h, 076h, 0dch, 0cch, 076h, 000h, 060h, 060h, 0c0h, 000h, 000h, 000h, 000h, 000h
+ db 018h, 030h, 060h, 060h, 060h, 030h, 018h, 000h, 060h, 030h, 018h, 018h, 018h, 030h, 060h, 000h
+ db 000h, 066h, 03ch, 0ffh, 03ch, 066h, 000h, 000h, 000h, 030h, 030h, 0fch, 030h, 030h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 060h, 000h, 000h, 000h, 0fch, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 000h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 080h, 000h
+ db 07ch, 0c6h, 0ceh, 0deh, 0f6h, 0e6h, 07ch, 000h, 030h, 070h, 030h, 030h, 030h, 030h, 0fch, 000h
+ db 078h, 0cch, 00ch, 038h, 060h, 0cch, 0fch, 000h, 078h, 0cch, 00ch, 038h, 00ch, 0cch, 078h, 000h
+ db 01ch, 03ch, 06ch, 0cch, 0feh, 00ch, 01eh, 000h, 0fch, 0c0h, 0f8h, 00ch, 00ch, 0cch, 078h, 000h
+ db 038h, 060h, 0c0h, 0f8h, 0cch, 0cch, 078h, 000h, 0fch, 0cch, 00ch, 018h, 030h, 030h, 030h, 000h
+ db 078h, 0cch, 0cch, 078h, 0cch, 0cch, 078h, 000h, 078h, 0cch, 0cch, 07ch, 00ch, 018h, 070h, 000h
+ db 000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h, 000h, 030h, 030h, 060h
+ db 018h, 030h, 060h, 0c0h, 060h, 030h, 018h, 000h, 000h, 000h, 0fch, 000h, 000h, 0fch, 000h, 000h
+ db 060h, 030h, 018h, 00ch, 018h, 030h, 060h, 000h, 078h, 0cch, 00ch, 018h, 030h, 000h, 030h, 000h
+ db 07ch, 0c6h, 0deh, 0deh, 0deh, 0c0h, 078h, 000h, 030h, 078h, 0cch, 0cch, 0fch, 0cch, 0cch, 000h
+ db 0fch, 066h, 066h, 07ch, 066h, 066h, 0fch, 000h, 03ch, 066h, 0c0h, 0c0h, 0c0h, 066h, 03ch, 000h
+ db 0f8h, 06ch, 066h, 066h, 066h, 06ch, 0f8h, 000h, 0feh, 062h, 068h, 078h, 068h, 062h, 0feh, 000h
+ db 0feh, 062h, 068h, 078h, 068h, 060h, 0f0h, 000h, 03ch, 066h, 0c0h, 0c0h, 0ceh, 066h, 03eh, 000h
+ db 0cch, 0cch, 0cch, 0fch, 0cch, 0cch, 0cch, 000h, 078h, 030h, 030h, 030h, 030h, 030h, 078h, 000h
+ db 01eh, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 000h, 0e6h, 066h, 06ch, 078h, 06ch, 066h, 0e6h, 000h
+ db 0f0h, 060h, 060h, 060h, 062h, 066h, 0feh, 000h, 0c6h, 0eeh, 0feh, 0feh, 0d6h, 0c6h, 0c6h, 000h
+ db 0c6h, 0e6h, 0f6h, 0deh, 0ceh, 0c6h, 0c6h, 000h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 06ch, 038h, 000h
+ db 0fch, 066h, 066h, 07ch, 060h, 060h, 0f0h, 000h, 078h, 0cch, 0cch, 0cch, 0dch, 078h, 01ch, 000h
+ db 0fch, 066h, 066h, 07ch, 06ch, 066h, 0e6h, 000h, 078h, 0cch, 0e0h, 070h, 01ch, 0cch, 078h, 000h
+ db 0fch, 0b4h, 030h, 030h, 030h, 030h, 078h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 0fch, 000h
+ db 0cch, 0cch, 0cch, 0cch, 0cch, 078h, 030h, 000h, 0c6h, 0c6h, 0c6h, 0d6h, 0feh, 0eeh, 0c6h, 000h
+ db 0c6h, 0c6h, 06ch, 038h, 038h, 06ch, 0c6h, 000h, 0cch, 0cch, 0cch, 078h, 030h, 030h, 078h, 000h
+ db 0feh, 0c6h, 08ch, 018h, 032h, 066h, 0feh, 000h, 078h, 060h, 060h, 060h, 060h, 060h, 078h, 000h
+ db 0c0h, 060h, 030h, 018h, 00ch, 006h, 002h, 000h, 078h, 018h, 018h, 018h, 018h, 018h, 078h, 000h
+ db 010h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh
+ db 030h, 030h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 078h, 00ch, 07ch, 0cch, 076h, 000h
+ db 0e0h, 060h, 060h, 07ch, 066h, 066h, 0dch, 000h, 000h, 000h, 078h, 0cch, 0c0h, 0cch, 078h, 000h
+ db 01ch, 00ch, 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h
+ db 038h, 06ch, 060h, 0f0h, 060h, 060h, 0f0h, 000h, 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 0f8h
+ db 0e0h, 060h, 06ch, 076h, 066h, 066h, 0e6h, 000h, 030h, 000h, 070h, 030h, 030h, 030h, 078h, 000h
+ db 00ch, 000h, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 0e0h, 060h, 066h, 06ch, 078h, 06ch, 0e6h, 000h
+ db 070h, 030h, 030h, 030h, 030h, 030h, 078h, 000h, 000h, 000h, 0cch, 0feh, 0feh, 0d6h, 0c6h, 000h
+ db 000h, 000h, 0f8h, 0cch, 0cch, 0cch, 0cch, 000h, 000h, 000h, 078h, 0cch, 0cch, 0cch, 078h, 000h
+ db 000h, 000h, 0dch, 066h, 066h, 07ch, 060h, 0f0h, 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 01eh
+ db 000h, 000h, 0dch, 076h, 066h, 060h, 0f0h, 000h, 000h, 000h, 07ch, 0c0h, 078h, 00ch, 0f8h, 000h
+ db 010h, 030h, 07ch, 030h, 030h, 034h, 018h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 076h, 000h
+ db 000h, 000h, 0cch, 0cch, 0cch, 078h, 030h, 000h, 000h, 000h, 0c6h, 0d6h, 0feh, 0feh, 06ch, 000h
+ db 000h, 000h, 0c6h, 06ch, 038h, 06ch, 0c6h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 07ch, 00ch, 0f8h
+ db 000h, 000h, 0fch, 098h, 030h, 064h, 0fch, 000h, 01ch, 030h, 030h, 0e0h, 030h, 030h, 01ch, 000h
+ db 018h, 018h, 018h, 000h, 018h, 018h, 018h, 000h, 0e0h, 030h, 030h, 01ch, 030h, 030h, 0e0h, 000h
+ db 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 000h
+ ; disGetNextSymbol 0xffe6e LB 0x192 -> off=0x0 cb=000000000000001b uValue=00000000000f1e6e 'biosorg_check_at_0FE6Eh'
+biosorg_check_at_0FE6Eh: ; 0xffe6e LB 0x1b
+ push ES ; 06 ; 0xffe6e orgs.asm:1920
+ push DS ; 1e ; 0xffe6f orgs.asm:1921
+ push ax ; 50 ; 0xffe70 orgs.asm:99
+ push cx ; 51 ; 0xffe71 orgs.asm:100
+ push dx ; 52 ; 0xffe72 orgs.asm:101
+ push bx ; 53 ; 0xffe73 orgs.asm:102
+ push sp ; 54 ; 0xffe74 orgs.asm:103
+ push bp ; 55 ; 0xffe75 orgs.asm:104
+ push si ; 56 ; 0xffe76 orgs.asm:105
+ push di ; 57 ; 0xffe77 orgs.asm:106
+ push CS ; 0e ; 0xffe78 orgs.asm:104
+ pop DS ; 1f ; 0xffe79 orgs.asm:105
+ cld ; fc ; 0xffe7a orgs.asm:106
+ call 06c67h ; e8 e9 6d ; 0xffe7b orgs.asm:1925
+ pop di ; 5f ; 0xffe7e orgs.asm:116
+ pop si ; 5e ; 0xffe7f orgs.asm:117
+ pop bp ; 5d ; 0xffe80 orgs.asm:118
+ pop bx ; 5b ; 0xffe81 orgs.asm:119
+ pop bx ; 5b ; 0xffe82 orgs.asm:120
+ pop dx ; 5a ; 0xffe83 orgs.asm:121
+ pop cx ; 59 ; 0xffe84 orgs.asm:122
+ pop ax ; 58 ; 0xffe85 orgs.asm:123
+ pop DS ; 1f ; 0xffe86 orgs.asm:1927
+ pop ES ; 07 ; 0xffe87 orgs.asm:1928
+ iret ; cf ; 0xffe88 orgs.asm:1929
+ ; disGetNextSymbol 0xffe89 LB 0x177 -> off=0x0 cb=000000000000001c uValue=00000000000f1e89 'biosorg_check_before_or_at_0FEA3h'
+biosorg_check_before_or_at_0FEA3h: ; 0xffe89 LB 0x1c
+ times 0x1a db 0
+ db 'XM'
+ ; disGetNextSymbol 0xffea5 LB 0x15b -> off=0x0 cb=0000000000000042 uValue=00000000000f1ea5 'int08_handler'
+int08_handler: ; 0xffea5 LB 0x42
+ sti ; fb ; 0xffea5 orgs.asm:1942
+ push ax ; 50 ; 0xffea6 orgs.asm:1943
+ push DS ; 1e ; 0xffea7 orgs.asm:1945
+ push dx ; 52 ; 0xffea8 orgs.asm:1946
+ mov ax, strict word 00040h ; b8 40 00 ; 0xffea9 orgs.asm:1947
+ mov ds, ax ; 8e d8 ; 0xffeac orgs.asm:1948
+ mov ax, word [0006ch] ; a1 6c 00 ; 0xffeae orgs.asm:1954
+ mov dx, word [word 0006eh] ; 8b 16 6e 00 ; 0xffeb1 orgs.asm:1955
+ inc ax ; 40 ; 0xffeb5 orgs.asm:1956
+ jne short 0feb9h ; 75 01 ; 0xffeb6 orgs.asm:1957
+ inc dx ; 42 ; 0xffeb8 orgs.asm:1958
+ cmp dx, strict byte 00018h ; 83 fa 18 ; 0xffeb9 orgs.asm:1967
+ jc short 0fec1h ; 72 03 ; 0xffebc orgs.asm:1968
+ jmp near 0f90ch ; e9 4b fa ; 0xffebe orgs.asm:1969
+ mov word [0006ch], ax ; a3 6c 00 ; 0xffec1 orgs.asm:1981
+ mov word [word 0006eh], dx ; 89 16 6e 00 ; 0xffec4 orgs.asm:1982
+ mov AL, byte [00040h] ; a0 40 00 ; 0xffec8 orgs.asm:1986
+ db 00ah, 0c0h
+ ; or al, al ; 0a c0 ; 0xffecb orgs.asm:1987
+ je short 0feddh ; 74 0e ; 0xffecd orgs.asm:1988
+ db 0feh, 0c8h
+ ; dec al ; fe c8 ; 0xffecf orgs.asm:1989
+ mov byte [00040h], AL ; a2 40 00 ; 0xffed1 orgs.asm:1990
+ jne short 0feddh ; 75 07 ; 0xffed4 orgs.asm:1991
+ mov dx, 003f2h ; ba f2 03 ; 0xffed6 orgs.asm:1993
+ in AL, DX ; ec ; 0xffed9 orgs.asm:1994
+ and AL, strict byte 0cfh ; 24 cf ; 0xffeda orgs.asm:1995
+ out DX, AL ; ee ; 0xffedc orgs.asm:1996
+ int 01ch ; cd 1c ; 0xffedd orgs.asm:1999
+ cli ; fa ; 0xffedf orgs.asm:2001
+ call 0e034h ; e8 51 e1 ; 0xffee0 orgs.asm:2002
+ pop dx ; 5a ; 0xffee3 orgs.asm:2003
+ pop DS ; 1f ; 0xffee4 orgs.asm:2004
+ pop ax ; 58 ; 0xffee5 orgs.asm:2009
+ iret ; cf ; 0xffee6 orgs.asm:2011
+ ; disGetNextSymbol 0xffee7 LB 0x119 -> off=0x0 cb=000000000000000c uValue=00000000000f1ee7 'biosorg_check_before_or_at_0FEF1h'
+biosorg_check_before_or_at_0FEF1h: ; 0xffee7 LB 0xc
+ times 0xa db 0
+ db 'XM'
+ ; disGetNextSymbol 0xffef3 LB 0x10d -> off=0x0 cb=000000000000000d uValue=00000000000f1ef3 'biosorg_check_at_0FEF3h'
+biosorg_check_at_0FEF3h: ; 0xffef3 LB 0xd
+ times 0xb db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfff00 LB 0x100 -> off=0x0 cb=0000000000000019 uValue=00000000000f1f00 'biosorg_check_at_0FF00h'
+biosorg_check_at_0FF00h: ; 0xfff00 LB 0x19
+ dec di ; 4f ; 0xfff00
+ jc short 0ff64h ; 72 61 ; 0xfff01
+ arpl [si+065h], bp ; 63 6c 65 ; 0xfff03
+ and byte [bp+04dh], dl ; 20 56 4d ; 0xfff06
+ and byte [bp+069h], dl ; 20 56 69 ; 0xfff09
+ jc short 0ff82h ; 72 74 ; 0xfff0c
+ jne short 0ff71h ; 75 61 ; 0xfff0e
+ insb ; 6c ; 0xfff10
+ inc dx ; 42 ; 0xfff11
+ outsw ; 6f ; 0xfff12
+ js short 0ff35h ; 78 20 ; 0xfff13
+ inc dx ; 42 ; 0xfff15
+ dec cx ; 49 ; 0xfff16
+ dec di ; 4f ; 0xfff17
+ push bx ; 53 ; 0xfff18
+ ; disGetNextSymbol 0xfff19 LB 0xe7 -> off=0x0 cb=000000000000003a uValue=00000000000f1f19 'biosorg_check_before_or_at_0FF51h'
+biosorg_check_before_or_at_0FF51h: ; 0xfff19 LB 0x3a
+ times 0x38 db 0
+ db 'XM'
+ ; disGetNextSymbol 0xfff53 LB 0xad -> off=0x0 cb=0000000000000001 uValue=00000000000f1f53 'dummy_iret'
+dummy_iret: ; 0xfff53 LB 0x1
+ iret ; cf ; 0xfff53 orgs.asm:2036
+ ; disGetNextSymbol 0xfff54 LB 0xac -> off=0x0 cb=000000000000002c uValue=00000000000f1f54 'biosorg_check_at_0FF54h'
+biosorg_check_at_0FF54h: ; 0xfff54 LB 0x2c
+ iret ; cf ; 0xfff54 orgs.asm:2045
+ mov ax, ax ; 89 c0 ; 0xfff55
+ mov ax, ax ; 89 c0 ; 0xfff57
+ mov ax, ax ; 89 c0 ; 0xfff59
+ mov ax, ax ; 89 c0 ; 0xfff5b
+ mov ax, ax ; 89 c0 ; 0xfff5d
+ cld ; fc ; 0xfff5f
+ pop di ; 5f ; 0xfff60
+ push bx ; 53 ; 0xfff61
+ dec bp ; 4d ; 0xfff62
+ pop di ; 5f ; 0xfff63
+ jnl short 0ff85h ; 7d 1f ; 0xfff64
+ add al, byte [di] ; 02 05 ; 0xfff66
+ inc word [bx+si] ; ff 00 ; 0xfff68
+ add byte [bx+si], al ; 00 00 ; 0xfff6a
+ add byte [bx+si], al ; 00 00 ; 0xfff6c
+ add byte [bx+si], al ; 00 00 ; 0xfff6e
+ pop di ; 5f ; 0xfff70
+ inc sp ; 44 ; 0xfff71
+ dec bp ; 4d ; 0xfff72
+ dec cx ; 49 ; 0xfff73
+ pop di ; 5f ; 0xfff74
+ and ax, strict word 00000h ; 25 00 00 ; 0xfff75
+ add byte [bx+si], dl ; 00 10 ; 0xfff78
+ push CS ; 0e ; 0xfff7a
+ add byte [bx+si], al ; 00 00 ; 0xfff7b
+ add byte [di], ah ; 00 25 ; 0xfff7d
+ times 0x1 db 0
+ ; disGetNextSymbol 0xfff80 LB 0x80 -> off=0x0 cb=0000000000000070 uValue=00000000000f1f80 'biosorg_check_before_or_at_0FFEEh'
+biosorg_check_before_or_at_0FFEEh: ; 0xfff80 LB 0x70
+ times 0x6e db 0
+ db 'XM'
+ ; disGetNextSymbol 0xffff0 LB 0x10 -> off=0x0 cb=0000000000000010 uValue=00000000000f1ff0 'cpu_reset'
+cpu_reset: ; 0xffff0 LB 0x10
+ jmp far 0f000h:0e05bh ; ea 5b e0 00 f0 ; 0xffff0 orgs.asm:2055
+ ; disGetNextSymbol 0xffff5 LB 0xb -> off=0xb cb=0000000000000000 uValue=0000000000100000 '_dummy_addr_0x100000'
+ db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fbh, 0d1h
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.md5sum b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.md5sum
new file mode 100644
index 00000000..9c061b45
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.md5sum
@@ -0,0 +1 @@
+2a6d3641685368af1d50214fda8e7ba0 *VBoxPcBios8086.rom
diff --git a/src/VBox/Devices/PC/BIOS/ahci.c b/src/VBox/Devices/PC/BIOS/ahci.c
new file mode 100644
index 00000000..f198e894
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/ahci.c
@@ -0,0 +1,1047 @@
+/* $Id: ahci.c $ */
+/** @file
+ * AHCI host adapter driver to boot from SATA disks.
+ */
+
+/*
+ * Copyright (C) 2011-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "biosint.h"
+#include "ebda.h"
+#include "inlines.h"
+#include "pciutil.h"
+#include "vds.h"
+
+#if DEBUG_AHCI
+# define DBG_AHCI(...) BX_INFO(__VA_ARGS__)
+#else
+# define DBG_AHCI(...)
+#endif
+
+/* Number of S/G table entries in EDDS. */
+#define NUM_EDDS_SG 16
+
+
+/**
+ * AHCI PRDT structure.
+ */
+typedef struct
+{
+ uint32_t phys_addr;
+ uint32_t something;
+ uint32_t reserved;
+ uint32_t len;
+} ahci_prdt;
+
+/**
+ * SATA D2H FIS (Device to Host Frame Information Structure).
+ */
+typedef struct {
+ uint8_t fis_type; /* 34h */
+ uint8_t intr; /* Bit 6 indicates interrupt status. */
+ uint8_t status; /* Status register. */
+ uint8_t error; /* Error register. */
+ uint8_t sec_no; /* Sector number register. */
+ uint8_t cyl_lo; /* Cylinder low register. */
+ uint8_t cyl_hi; /* Cylinder high register. */
+ uint8_t dev_hd; /* Device/head register. */
+ uint8_t sec_no_exp; /* Expanded sector number register. */
+ uint8_t cyl_lo_exp; /* Expanded cylinder low register. */
+ uint8_t cyl_hi_exp; /* Expanded cylinder high register. */
+ uint8_t resvd0;
+ uint8_t sec_cn; /* Sector count register. */
+ uint8_t sec_cn_exp; /* Expanded sector count register. */
+ uint16_t resvd1;
+ uint32_t resvd2;
+} fis_d2h;
+
+ct_assert(sizeof(fis_d2h) == 20);
+
+/**
+ * AHCI controller data.
+ */
+typedef struct
+{
+ /** The AHCI command list as defined by chapter 4.2.2 of the Intel AHCI spec.
+ * Because the BIOS doesn't support NCQ only the first command header is defined
+ * to save memory. - Must be aligned on a 1K boundary.
+ */
+ uint32_t aCmdHdr[0x8];
+ /** Align the next structure on a 128 byte boundary. */
+ uint8_t abAlignment1[0x60];
+ /** The command table of one request as defined by chapter 4.2.3 of the Intel AHCI spec.
+ * Must be aligned on 128 byte boundary.
+ */
+ uint8_t abCmd[0x40];
+ /** The ATAPI command region.
+ * Located 40h bytes after the beginning of the CFIS (Command FIS).
+ */
+ uint8_t abAcmd[0x20];
+ /** Align the PRDT structure on a 128 byte boundary. */
+ uint8_t abAlignment2[0x20];
+ /** Physical Region Descriptor Table (PRDT) array. In other
+ * words, a scatter/gather descriptor list.
+ */
+ ahci_prdt aPrdt[16];
+ /** Memory for the received command FIS area as specified by chapter 4.2.1
+ * of the Intel AHCI spec. This area is normally 256 bytes big but to save memory
+ * only the first 96 bytes are used because it is assumed that the controller
+ * never writes to the UFIS or reserved area. - Must be aligned on a 256byte boundary.
+ */
+ uint8_t abFisRecv[0x60];
+ /** Base I/O port for the index/data register pair. */
+ uint16_t iobase;
+ /** Current port which uses the memory to communicate with the controller. */
+ uint8_t cur_port;
+ /** Current PRD index (for pre/post skip). */
+ uint8_t cur_prd;
+ /** Physical address of the sink buffer (for pre/post skip). */
+ uint32_t sink_buf_phys;
+ /** Saved high bits of EAX. */
+ uint16_t saved_eax_hi;
+ /** VDS EDDS DMA buffer descriptor structure. */
+ vds_edds edds;
+ vds_sg edds_more_sg[NUM_EDDS_SG - 1];
+} ahci_t;
+
+/* The AHCI specific data must fit into 1KB (statically allocated). */
+ct_assert(sizeof(ahci_t) <= 1024);
+
+/** PCI configuration fields. */
+#define PCI_CONFIG_CAP 0x34
+
+#define PCI_CAP_ID_SATACR 0x12
+#define VBOX_AHCI_NO_DEVICE 0xffff
+
+#define RT_BIT_32(bit) ((uint32_t)(1L << (bit)))
+
+/** Global register set. */
+#define AHCI_HBA_SIZE 0x100
+
+/// @todo what are the casts good for?
+#define AHCI_REG_CAP ((uint32_t)0x00)
+#define AHCI_REG_GHC ((uint32_t)0x04)
+# define AHCI_GHC_AE RT_BIT_32(31)
+# define AHCI_GHC_IR RT_BIT_32(1)
+# define AHCI_GHC_HR RT_BIT_32(0)
+#define AHCI_REG_IS ((uint32_t)0x08)
+#define AHCI_REG_PI ((uint32_t)0x0c)
+#define AHCI_REG_VS ((uint32_t)0x10)
+
+/** Per port register set. */
+#define AHCI_PORT_SIZE 0x80
+
+#define AHCI_REG_PORT_CLB 0x00
+#define AHCI_REG_PORT_CLBU 0x04
+#define AHCI_REG_PORT_FB 0x08
+#define AHCI_REG_PORT_FBU 0x0c
+#define AHCI_REG_PORT_IS 0x10
+# define AHCI_REG_PORT_IS_DHRS RT_BIT_32(0)
+# define AHCI_REG_PORT_IS_TFES RT_BIT_32(30)
+#define AHCI_REG_PORT_IE 0x14
+#define AHCI_REG_PORT_CMD 0x18
+# define AHCI_REG_PORT_CMD_ST RT_BIT_32(0)
+# define AHCI_REG_PORT_CMD_FRE RT_BIT_32(4)
+# define AHCI_REG_PORT_CMD_FR RT_BIT_32(14)
+# define AHCI_REG_PORT_CMD_CR RT_BIT_32(15)
+#define AHCI_REG_PORT_TFD 0x20
+#define AHCI_REG_PORT_SIG 0x24
+#define AHCI_REG_PORT_SSTS 0x28
+#define AHCI_REG_PORT_SCTL 0x2c
+#define AHCI_REG_PORT_SERR 0x30
+#define AHCI_REG_PORT_SACT 0x34
+#define AHCI_REG_PORT_CI 0x38
+
+/** Returns the absolute register offset from a given port and port register. */
+#define AHCI_PORT_REG(port, reg) (AHCI_HBA_SIZE + (port) * AHCI_PORT_SIZE + (reg))
+
+#define AHCI_REG_IDX 0
+#define AHCI_REG_DATA 4
+
+/** Writes the given value to a AHCI register. */
+#define AHCI_WRITE_REG(iobase, reg, val) \
+ outpd((iobase) + AHCI_REG_IDX, reg); \
+ outpd((iobase) + AHCI_REG_DATA, val)
+
+/** Reads from a AHCI register. */
+#define AHCI_READ_REG(iobase, reg, val) \
+ outpd((iobase) + AHCI_REG_IDX, reg); \
+ (val) = inpd((iobase) + AHCI_REG_DATA)
+
+/** Writes to the given port register. */
+#define VBOXAHCI_PORT_WRITE_REG(iobase, port, reg, val) \
+ AHCI_WRITE_REG((iobase), AHCI_PORT_REG((port), (reg)), val)
+
+/** Reads from the given port register. */
+#define VBOXAHCI_PORT_READ_REG(iobase, port, reg, val) \
+ AHCI_READ_REG((iobase), AHCI_PORT_REG((port), (reg)), val)
+
+#define ATA_CMD_IDENTIFY_DEVICE 0xEC
+#define ATA_CMD_IDENTIFY_PACKET 0xA1
+#define ATA_CMD_PACKET 0xA0
+#define AHCI_CMD_READ_DMA_EXT 0x25
+#define AHCI_CMD_WRITE_DMA_EXT 0x35
+
+
+/* Warning: Destroys high bits of EAX. */
+uint32_t inpd(uint16_t port);
+#pragma aux inpd = \
+ ".386" \
+ "in eax, dx" \
+ "mov dx, ax" \
+ "shr eax, 16" \
+ "xchg ax, dx" \
+ parm [dx] value [dx ax] modify nomemory;
+
+/* Warning: Destroys high bits of EAX. */
+void outpd(uint16_t port, uint32_t val);
+#pragma aux outpd = \
+ ".386" \
+ "xchg ax, cx" \
+ "shl eax, 16" \
+ "mov ax, cx" \
+ "out dx, eax" \
+ parm [dx] [cx ax] modify nomemory;
+
+
+/* Machinery to save/restore high bits of EAX. 32-bit port I/O needs to use
+ * EAX, but saving/restoring EAX around each port access would be inefficient.
+ * Instead, each externally callable routine must save the high bits before
+ * modifying them and restore the high bits before exiting.
+ */
+
+/* Note: Reading high EAX bits destroys them - *must* be restored later. */
+uint16_t eax_hi_rd(void);
+#pragma aux eax_hi_rd = \
+ ".386" \
+ "shr eax, 16" \
+ value [ax] modify nomemory;
+
+void eax_hi_wr(uint16_t);
+#pragma aux eax_hi_wr = \
+ ".386" \
+ "shl eax, 16" \
+ parm [ax] modify nomemory;
+
+void inline high_bits_save(ahci_t __far *ahci)
+{
+ ahci->saved_eax_hi = eax_hi_rd();
+}
+
+void inline high_bits_restore(ahci_t __far *ahci)
+{
+ eax_hi_wr(ahci->saved_eax_hi);
+}
+
+/**
+ * Sets a given set of bits in a register.
+ */
+static void inline ahci_ctrl_set_bits(uint16_t iobase, uint16_t reg, uint32_t mask)
+{
+ outpd(iobase + AHCI_REG_IDX, reg);
+ outpd(iobase + AHCI_REG_DATA, inpd(iobase + AHCI_REG_DATA) | mask);
+}
+
+/**
+ * Clears a given set of bits in a register.
+ */
+static void inline ahci_ctrl_clear_bits(uint16_t iobase, uint16_t reg, uint32_t mask)
+{
+ outpd(iobase + AHCI_REG_IDX, reg);
+ outpd(iobase + AHCI_REG_DATA, inpd(iobase + AHCI_REG_DATA) & ~mask);
+}
+
+/**
+ * Returns whether at least one of the bits in the given mask is set
+ * for a register.
+ */
+static uint8_t inline ahci_ctrl_is_bit_set(uint16_t iobase, uint16_t reg, uint32_t mask)
+{
+ outpd(iobase + AHCI_REG_IDX, reg);
+ return (inpd(iobase + AHCI_REG_DATA) & mask) != 0;
+}
+
+/**
+ * Extracts a range of bits from a register and shifts them
+ * to the right.
+ */
+static uint16_t ahci_ctrl_extract_bits(uint32_t val, uint32_t mask, uint8_t shift)
+{
+ return (val & mask) >> shift;
+}
+
+/**
+ * Converts a segment:offset pair into a 32bit physical address.
+ */
+static uint32_t ahci_addr_to_phys(void __far *ptr)
+{
+ return ((uint32_t)FP_SEG(ptr) << 4) + FP_OFF(ptr);
+}
+
+/**
+ * Issues a command to the SATA controller and waits for completion.
+ */
+static void ahci_port_cmd_sync(ahci_t __far *ahci, uint8_t val)
+{
+ uint16_t io_base;
+ uint8_t port;
+
+ port = ahci->cur_port;
+ io_base = ahci->iobase;
+
+ if (port != 0xff)
+ {
+ /* Prepare the command header. */
+ ahci->aCmdHdr[0] = ((uint32_t)ahci->cur_prd << 16) | RT_BIT_32(7) | val;
+ ahci->aCmdHdr[1] = 0;
+ ahci->aCmdHdr[2] = ahci_addr_to_phys(&ahci->abCmd[0]);
+
+ /* Enable Command and FIS receive engine. */
+ ahci_ctrl_set_bits(io_base, AHCI_PORT_REG(port, AHCI_REG_PORT_CMD),
+ AHCI_REG_PORT_CMD_FRE | AHCI_REG_PORT_CMD_ST);
+
+ /* Queue command. */
+ VBOXAHCI_PORT_WRITE_REG(io_base, port, AHCI_REG_PORT_CI, 0x1);
+
+ /* Wait for a D2H FIS. */
+ DBG_AHCI("AHCI: Waiting for D2H FIS\n");
+ while (ahci_ctrl_is_bit_set(io_base, AHCI_PORT_REG(port, AHCI_REG_PORT_IS),
+ AHCI_REG_PORT_IS_DHRS | AHCI_REG_PORT_IS_TFES) == 0)
+ {
+ // This is where we'd need some kind of a yield functionality...
+ }
+
+ ahci_ctrl_set_bits(io_base, AHCI_PORT_REG(port, AHCI_REG_PORT_IS),
+ AHCI_REG_PORT_IS_DHRS); /* Acknowledge received D2H FIS. */
+
+ /* Disable command engine. */
+ ahci_ctrl_clear_bits(io_base, AHCI_PORT_REG(port, AHCI_REG_PORT_CMD),
+ AHCI_REG_PORT_CMD_ST);
+ /* Caller must examine status. */
+ }
+ else
+ DBG_AHCI("AHCI: Invalid port given\n");
+}
+
+/**
+ * Issue command to device.
+ */
+static uint16_t ahci_cmd_data(bio_dsk_t __far *bios_dsk, uint8_t cmd)
+{
+ ahci_t __far *ahci = bios_dsk->ahci_seg :> 0;
+ uint16_t n_sect = bios_dsk->drqp.nsect;
+ uint16_t sectsz = bios_dsk->drqp.sect_sz;
+ fis_d2h __far *d2h;
+
+ _fmemset(&ahci->abCmd[0], 0, sizeof(ahci->abCmd));
+
+ /* Prepare the FIS. */
+ ahci->abCmd[0] = 0x27; /* FIS type H2D. */
+ ahci->abCmd[1] = 1 << 7; /* Command update. */
+ ahci->abCmd[2] = cmd;
+ ahci->abCmd[3] = 0;
+
+ ahci->abCmd[4] = bios_dsk->drqp.lba & 0xff;
+ ahci->abCmd[5] = (bios_dsk->drqp.lba >> 8) & 0xff;
+ ahci->abCmd[6] = (bios_dsk->drqp.lba >> 16) & 0xff;
+ ahci->abCmd[7] = RT_BIT_32(6); /* LBA access. */
+
+ ahci->abCmd[8] = (bios_dsk->drqp.lba >> 24) & 0xff;
+ ahci->abCmd[9] = (bios_dsk->drqp.lba >> 32) & 0xff;
+ ahci->abCmd[10] = (bios_dsk->drqp.lba >> 40) & 0xff;
+ ahci->abCmd[11] = 0;
+
+ ahci->abCmd[12] = (uint8_t)(n_sect & 0xff);
+ ahci->abCmd[13] = (uint8_t)((n_sect >> 8) & 0xff);
+
+ /* Lock memory needed for DMA. */
+ ahci->edds.num_avail = NUM_EDDS_SG;
+ DBG_AHCI("AHCI: S/G list for %lu bytes (skip %u)\n",
+ (uint32_t)n_sect * sectsz, bios_dsk->drqp.skip_a);
+ vds_build_sg_list(&ahci->edds, bios_dsk->drqp.buffer, (uint32_t)n_sect * sectsz);
+
+ /* Set up the PRDT. */
+ ahci->aPrdt[ahci->cur_prd].len = ahci->edds.u.sg[0].size - 1;
+ ahci->aPrdt[ahci->cur_prd].phys_addr = ahci->edds.u.sg[0].phys_addr;
+ ++ahci->cur_prd;
+
+ if (bios_dsk->drqp.skip_a) {
+ ahci->aPrdt[ahci->cur_prd].len = bios_dsk->drqp.skip_a - 1;
+ ahci->aPrdt[ahci->cur_prd].phys_addr = ahci->sink_buf_phys;
+ ++ahci->cur_prd;
+ }
+
+#if DEBUG_AHCI
+ {
+ uint16_t prdt_idx;
+
+ for (prdt_idx = 0; prdt_idx < ahci->cur_prd; ++prdt_idx) {
+ DBG_AHCI("S/G entry %u: %5lu bytes @ %08lX\n", prdt_idx,
+ ahci->aPrdt[prdt_idx].len + 1, ahci->aPrdt[prdt_idx].phys_addr);
+ }
+ }
+#endif
+
+ /* Build variable part of first command DWORD (reuses 'cmd'). */
+ if (cmd == AHCI_CMD_WRITE_DMA_EXT)
+ cmd = RT_BIT_32(6); /* Indicate a write to device. */
+ else if (cmd == ATA_CMD_PACKET) {
+ cmd |= RT_BIT_32(5); /* Indicate ATAPI command. */
+ ahci->abCmd[3] |= 1; /* DMA transfers. */
+ } else
+ cmd = 0;
+
+ cmd |= 5; /* Five DWORDs. */
+
+ ahci_port_cmd_sync(ahci, cmd);
+
+ /* Examine operation status. */
+ d2h = (void __far *)&ahci->abFisRecv[0x40];
+ DBG_AHCI("AHCI: ERR=%02x, STAT=%02x, SCNT=%02x\n", d2h->error, d2h->status, d2h->sec_cn);
+
+ /* Unlock the buffer again. */
+ vds_free_sg_list(&ahci->edds);
+ return d2h->error ? 4 : 0;
+}
+
+/**
+ * Deinits the curent active port.
+ */
+static void ahci_port_deinit_current(ahci_t __far *ahci)
+{
+ uint16_t io_base;
+ uint8_t port;
+
+ io_base = ahci->iobase;
+ port = ahci->cur_port;
+
+ if (port != 0xff)
+ {
+ /* Put the port into an idle state. */
+ ahci_ctrl_clear_bits(io_base, AHCI_PORT_REG(port, AHCI_REG_PORT_CMD),
+ AHCI_REG_PORT_CMD_FRE | AHCI_REG_PORT_CMD_ST);
+
+ while (ahci_ctrl_is_bit_set(io_base, AHCI_PORT_REG(port, AHCI_REG_PORT_CMD),
+ AHCI_REG_PORT_CMD_FRE | AHCI_REG_PORT_CMD_ST | AHCI_REG_PORT_CMD_FR | AHCI_REG_PORT_CMD_CR) == 1)
+ {
+ DBG_AHCI("AHCI: Waiting for the port to idle\n");
+ }
+
+ /*
+ * Port idles, set up memory for commands and received FIS and program the
+ * address registers.
+ */
+ /// @todo merge memsets?
+ _fmemset(&ahci->aCmdHdr[0], 0, sizeof(ahci->aCmdHdr));
+ _fmemset(&ahci->abCmd[0], 0, sizeof(ahci->abCmd));
+ _fmemset(&ahci->abFisRecv[0], 0, sizeof(ahci->abFisRecv));
+
+ VBOXAHCI_PORT_WRITE_REG(io_base, port, AHCI_REG_PORT_FB, 0);
+ VBOXAHCI_PORT_WRITE_REG(io_base, port, AHCI_REG_PORT_FBU, 0);
+
+ VBOXAHCI_PORT_WRITE_REG(io_base, port, AHCI_REG_PORT_CLB, 0);
+ VBOXAHCI_PORT_WRITE_REG(io_base, port, AHCI_REG_PORT_CLBU, 0);
+
+ /* Disable all interrupts. */
+ VBOXAHCI_PORT_WRITE_REG(io_base, port, AHCI_REG_PORT_IE, 0);
+
+ ahci->cur_port = 0xff;
+ }
+}
+
+/**
+ * Brings a port into a minimal state to make device detection possible
+ * or to queue requests.
+ */
+static void ahci_port_init(ahci_t __far *ahci, uint8_t u8Port)
+{
+ /* Deinit any other port first. */
+ ahci_port_deinit_current(ahci);
+
+ /* Put the port into an idle state. */
+ ahci_ctrl_clear_bits(ahci->iobase, AHCI_PORT_REG(u8Port, AHCI_REG_PORT_CMD),
+ AHCI_REG_PORT_CMD_FRE | AHCI_REG_PORT_CMD_ST);
+
+ while (ahci_ctrl_is_bit_set(ahci->iobase, AHCI_PORT_REG(u8Port, AHCI_REG_PORT_CMD),
+ AHCI_REG_PORT_CMD_FRE | AHCI_REG_PORT_CMD_ST | AHCI_REG_PORT_CMD_FR | AHCI_REG_PORT_CMD_CR) == 1)
+ {
+ DBG_AHCI("AHCI: Waiting for the port to idle\n");
+ }
+
+ /*
+ * Port idles, set up memory for commands and received FIS and program the
+ * address registers.
+ */
+ /// @todo just one memset?
+ _fmemset(&ahci->aCmdHdr[0], 0, sizeof(ahci->aCmdHdr));
+ _fmemset(&ahci->abCmd[0], 0, sizeof(ahci->abCmd));
+ _fmemset(&ahci->abFisRecv[0], 0, sizeof(ahci->abFisRecv));
+
+ DBG_AHCI("AHCI: FIS receive area %lx from %x:%x\n",
+ ahci_addr_to_phys(&ahci->abFisRecv), FP_SEG(ahci->abFisRecv), FP_OFF(ahci->abFisRecv));
+ VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_FB, ahci_addr_to_phys(&ahci->abFisRecv));
+ VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_FBU, 0);
+
+ DBG_AHCI("AHCI: CMD list area %lx\n", ahci_addr_to_phys(&ahci->aCmdHdr));
+ VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_CLB, ahci_addr_to_phys(&ahci->aCmdHdr));
+ VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_CLBU, 0);
+
+ /* Disable all interrupts. */
+ VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_IE, 0);
+ VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_IS, 0xffffffff);
+ /* Clear all errors. */
+ VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SERR, 0xffffffff);
+
+ ahci->cur_port = u8Port;
+ ahci->cur_prd = 0;
+}
+
+/**
+ * Read sectors from an attached AHCI device.
+ *
+ * @returns status code.
+ * @param bios_dsk Pointer to disk request packet (in the
+ * EBDA).
+ */
+int ahci_read_sectors(bio_dsk_t __far *bios_dsk)
+{
+ uint16_t device_id;
+ uint16_t rc;
+
+ device_id = VBOX_GET_AHCI_DEVICE(bios_dsk->drqp.dev_id);
+ if (device_id > BX_MAX_AHCI_DEVICES)
+ BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
+
+ DBG_AHCI("%s: %u sectors @ LBA 0x%llx, device %d, port %d\n", __func__,
+ bios_dsk->drqp.nsect, bios_dsk->drqp.lba,
+ device_id, bios_dsk->ahcidev[device_id].port);
+
+ high_bits_save(bios_dsk->ahci_seg :> 0);
+ ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
+ rc = ahci_cmd_data(bios_dsk, AHCI_CMD_READ_DMA_EXT);
+ DBG_AHCI("%s: transferred %lu bytes\n", __func__, ((ahci_t __far *)(bios_dsk->ahci_seg :> 0))->aCmdHdr[1]);
+ bios_dsk->drqp.trsfsectors = bios_dsk->drqp.nsect;
+#ifdef DMA_WORKAROUND
+ rep_movsw(bios_dsk->drqp.buffer, bios_dsk->drqp.buffer, bios_dsk->drqp.nsect * 512 / 2);
+#endif
+ high_bits_restore(bios_dsk->ahci_seg :> 0);
+ return rc;
+}
+
+/**
+ * Write sectors to an attached AHCI device.
+ *
+ * @returns status code.
+ * @param bios_dsk Pointer to disk request packet (in the
+ * EBDA).
+ */
+int ahci_write_sectors(bio_dsk_t __far *bios_dsk)
+{
+ uint16_t device_id;
+ uint16_t rc;
+
+ device_id = VBOX_GET_AHCI_DEVICE(bios_dsk->drqp.dev_id);
+ if (device_id > BX_MAX_AHCI_DEVICES)
+ BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
+
+ DBG_AHCI("%s: %u sectors @ LBA 0x%llx, device %d, port %d\n", __func__,
+ bios_dsk->drqp.nsect, bios_dsk->drqp.lba, device_id,
+ bios_dsk->ahcidev[device_id].port);
+
+ high_bits_save(bios_dsk->ahci_seg :> 0);
+ ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
+ rc = ahci_cmd_data(bios_dsk, AHCI_CMD_WRITE_DMA_EXT);
+ DBG_AHCI("%s: transferred %lu bytes\n", __func__, ((ahci_t __far *)(bios_dsk->ahci_seg :> 0))->aCmdHdr[1]);
+ bios_dsk->drqp.trsfsectors = bios_dsk->drqp.nsect;
+ high_bits_restore(bios_dsk->ahci_seg :> 0);
+ return rc;
+}
+
+/// @todo move
+#define ATA_DATA_NO 0x00
+#define ATA_DATA_IN 0x01
+#define ATA_DATA_OUT 0x02
+
+uint16_t ahci_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,
+ uint16_t skip_b, uint32_t length, uint8_t inout, char __far *buffer)
+{
+ bio_dsk_t __far *bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
+ ahci_t __far *ahci;
+
+ /* Data out is currently not supported. */
+ if (inout == ATA_DATA_OUT) {
+ BX_INFO("%s: DATA_OUT not supported yet\n", __func__);
+ return 1;
+ }
+
+ /* The skip length must be even. */
+ if (skip_b & 1) {
+ DBG_AHCI("%s: skip must be even (%04x)\n", __func__, skip_b);
+ return 1;
+ }
+
+ /* Convert to AHCI specific device number. */
+ device_id = VBOX_GET_AHCI_DEVICE(device_id);
+
+ DBG_AHCI("%s: reading %lu bytes, skip %u/%u, device %d, port %d\n", __func__,
+ length, bios_dsk->drqp.skip_b, bios_dsk->drqp.skip_a,
+ device_id, bios_dsk->ahcidev[device_id].port);
+ DBG_AHCI("%s: reading %u %u-byte sectors\n", __func__,
+ bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz);
+
+ bios_dsk->drqp.lba = length << 8; /// @todo xfer length limit
+ bios_dsk->drqp.buffer = buffer;
+ bios_dsk->drqp.nsect = length / bios_dsk->drqp.sect_sz;
+// bios_dsk->drqp.sect_sz = 2048;
+
+ ahci = bios_dsk->ahci_seg :> 0;
+ high_bits_save(ahci);
+
+ ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
+
+ /* Copy the ATAPI command where the HBA can fetch it. */
+ _fmemcpy(ahci->abAcmd, cmdbuf, cmdlen);
+
+ /* Reset transferred counts. */
+ /// @todo clear in calling code?
+ bios_dsk->drqp.trsfsectors = 0;
+ bios_dsk->drqp.trsfbytes = 0;
+
+ /* Set up a PRD entry to throw away the beginning of the transfer. */
+ if (bios_dsk->drqp.skip_b) {
+ ahci->aPrdt[0].len = bios_dsk->drqp.skip_b - 1;
+ ahci->aPrdt[0].phys_addr = ahci->sink_buf_phys;
+ ahci->cur_prd++;
+ }
+
+ ahci_cmd_data(bios_dsk, ATA_CMD_PACKET);
+ DBG_AHCI("%s: transferred %lu bytes\n", __func__, ahci->aCmdHdr[1]);
+ bios_dsk->drqp.trsfbytes = ahci->aCmdHdr[1];
+#ifdef DMA_WORKAROUND
+ rep_movsw(bios_dsk->drqp.buffer, bios_dsk->drqp.buffer, bios_dsk->drqp.trsfbytes / 2);
+#endif
+ high_bits_restore(ahci);
+
+ return ahci->aCmdHdr[1] == 0 ? 4 : 0;
+}
+
+/* Wait for the specified number of BIOS timer ticks or data bytes. */
+void wait_ticks_device_init( unsigned wait_ticks, unsigned wait_bytes )
+{
+}
+
+void ahci_port_detect_device(ahci_t __far *ahci, uint8_t u8Port)
+{
+ uint32_t val;
+ bio_dsk_t __far *bios_dsk;
+ volatile uint32_t __far *ticks;
+ uint32_t end_tick;
+ int device_found = 0;
+
+ ahci_port_init(ahci, u8Port);
+
+ bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
+
+ /* Reset connection. */
+ VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SCTL, 0x01);
+ /*
+ * According to the spec we should wait at least 1msec until the reset
+ * is cleared but this is a virtual controller so we don't have to.
+ */
+ VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SCTL, 0);
+
+ /*
+ * We do however have to wait for the device to initialize (the port reset
+ * to complete). That can take up to 10ms according to the SATA spec (device
+ * must send COMINIT within 10ms of COMRESET). We should be generous with
+ * the wait because in the typical case there are no ports without a device
+ * attached.
+ */
+ ticks = MK_FP( 0x40, 0x6C );
+ end_tick = *ticks + 3; /* Wait up to five BIOS ticks, something in 150ms range. */
+
+ while( *ticks < end_tick )
+ {
+ /* If PxSSTS.DET is 3, everything went fine. */
+ VBOXAHCI_PORT_READ_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SSTS, val);
+ if (ahci_ctrl_extract_bits(val, 0xfL, 0) == 3) {
+ device_found = 1;
+ break;
+ }
+ }
+
+ /* Timed out, no device detected. */
+ if (!device_found) {
+ DBG_AHCI("AHCI: Timed out, no device detected on port %d\n", u8Port);
+ return;
+ }
+
+ if (ahci_ctrl_extract_bits(val, 0xfL, 0) == 0x3)
+ {
+ uint8_t abBuffer[0x0200];
+ uint8_t hdcount, devcount_ahci, hd_index;
+ uint8_t cdcount;
+ uint8_t removable;
+
+ /* Clear all errors after the reset. */
+ VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SERR, 0xffffffff);
+
+ devcount_ahci = bios_dsk->ahci_devcnt;
+
+ DBG_AHCI("AHCI: Device detected on port %d\n", u8Port);
+
+ /// @todo Merge common HD/CDROM detection code
+ if (devcount_ahci < BX_MAX_AHCI_DEVICES)
+ {
+ /* Device detected, enable FIS receive. */
+ ahci_ctrl_set_bits(ahci->iobase, AHCI_PORT_REG(u8Port, AHCI_REG_PORT_CMD),
+ AHCI_REG_PORT_CMD_FRE);
+
+ /* Check signature to determine device type. */
+ VBOXAHCI_PORT_READ_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SIG, val);
+ if (val == 0x101)
+ {
+ uint64_t sectors;
+ uint16_t cylinders, heads, spt;
+ chs_t lgeo;
+ uint8_t idxCmosChsBase;
+
+ DBG_AHCI("AHCI: Detected hard disk\n");
+
+ /* Identify device. */
+ bios_dsk->drqp.lba = 0;
+ bios_dsk->drqp.buffer = &abBuffer;
+ bios_dsk->drqp.nsect = 1;
+ bios_dsk->drqp.sect_sz = 512;
+ ahci_cmd_data(bios_dsk, ATA_CMD_IDENTIFY_DEVICE);
+
+ /* Calculate index into the generic device table. */
+ hd_index = devcount_ahci + BX_MAX_ATA_DEVICES + BX_MAX_SCSI_DEVICES;
+
+ removable = *(abBuffer+0) & 0x80 ? 1 : 0;
+ cylinders = *(uint16_t *)(abBuffer+(1*2)); // word 1
+ heads = *(uint16_t *)(abBuffer+(3*2)); // word 3
+ spt = *(uint16_t *)(abBuffer+(6*2)); // word 6
+ sectors = *(uint32_t *)(abBuffer+(60*2)); // word 60 and word 61
+
+ if (sectors == 0x0FFFFFFF) /* For disks bigger than ~128GB */
+ sectors = *(uint64_t *)(abBuffer+(100*2)); // words 100 to 103
+
+ DBG_AHCI("AHCI: 0x%llx sectors\n", sectors);
+
+ bios_dsk->ahcidev[devcount_ahci].port = u8Port;
+ bios_dsk->devices[hd_index].type = DSK_TYPE_AHCI;
+ bios_dsk->devices[hd_index].device = DSK_DEVICE_HD;
+ bios_dsk->devices[hd_index].removable = removable;
+ bios_dsk->devices[hd_index].lock = 0;
+ bios_dsk->devices[hd_index].blksize = 512;
+ bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;
+ bios_dsk->devices[hd_index].sectors = sectors;
+
+ bios_dsk->devices[hd_index].pchs.heads = heads;
+ bios_dsk->devices[hd_index].pchs.cylinders = cylinders;
+ bios_dsk->devices[hd_index].pchs.spt = spt;
+
+ /* Get logical CHS geometry. */
+ switch (devcount_ahci)
+ {
+ case 0:
+ idxCmosChsBase = 0x40;
+ break;
+ case 1:
+ idxCmosChsBase = 0x48;
+ break;
+ case 2:
+ idxCmosChsBase = 0x50;
+ break;
+ case 3:
+ idxCmosChsBase = 0x58;
+ break;
+ default:
+ idxCmosChsBase = 0;
+ }
+ if (idxCmosChsBase && inb_cmos(idxCmosChsBase+7))
+ {
+ lgeo.cylinders = inb_cmos(idxCmosChsBase + 0) + (inb_cmos(idxCmosChsBase + 1) << 8);
+ lgeo.heads = inb_cmos(idxCmosChsBase + 2);
+ lgeo.spt = inb_cmos(idxCmosChsBase + 7);
+ }
+ else
+ set_geom_lba(&lgeo, sectors); /* Default EDD-style translated LBA geometry. */
+
+ BX_INFO("AHCI %d-P#%d: PCHS=%u/%u/%u LCHS=%u/%u/%u 0x%llx sectors\n", devcount_ahci,
+ u8Port, cylinders, heads, spt, lgeo.cylinders, lgeo.heads, lgeo.spt,
+ sectors);
+
+ bios_dsk->devices[hd_index].lchs = lgeo;
+
+ /* Store the ID of the disk in the BIOS hdidmap. */
+ hdcount = bios_dsk->hdcount;
+ bios_dsk->hdidmap[hdcount] = devcount_ahci + BX_MAX_ATA_DEVICES + BX_MAX_SCSI_DEVICES;
+ hdcount++;
+ bios_dsk->hdcount = hdcount;
+
+ /* Update hdcount in the BDA. */
+ hdcount = read_byte(0x40, 0x75);
+ hdcount++;
+ write_byte(0x40, 0x75, hdcount);
+ }
+ else if (val == 0xeb140101)
+ {
+ DBG_AHCI("AHCI: Detected ATAPI device\n");
+
+ /* Identify packet device. */
+ bios_dsk->drqp.lba = 0;
+ bios_dsk->drqp.buffer = &abBuffer;
+ bios_dsk->drqp.nsect = 1;
+ bios_dsk->drqp.sect_sz = 512;
+ ahci_cmd_data(bios_dsk, ATA_CMD_IDENTIFY_PACKET);
+
+ /* Calculate index into the generic device table. */
+ hd_index = devcount_ahci + BX_MAX_ATA_DEVICES + BX_MAX_SCSI_DEVICES;
+
+ removable = *(abBuffer+0) & 0x80 ? 1 : 0;
+
+ bios_dsk->ahcidev[devcount_ahci].port = u8Port;
+ bios_dsk->devices[hd_index].type = DSK_TYPE_AHCI;
+ bios_dsk->devices[hd_index].device = DSK_DEVICE_CDROM;
+ bios_dsk->devices[hd_index].removable = removable;
+ bios_dsk->devices[hd_index].blksize = 2048;
+ bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_NONE;
+
+ /* Store the ID of the device in the BIOS cdidmap. */
+ cdcount = bios_dsk->cdcount;
+ bios_dsk->cdidmap[cdcount] = devcount_ahci + BX_MAX_ATA_DEVICES + BX_MAX_SCSI_DEVICES;
+ cdcount++;
+ bios_dsk->cdcount = cdcount;
+ }
+ else
+ DBG_AHCI("AHCI: Ignoring unknown device\n");
+
+ devcount_ahci++;
+ bios_dsk->ahci_devcnt = devcount_ahci;
+ }
+ else
+ DBG_AHCI("AHCI: Reached maximum device count, skipping\n");
+ }
+}
+
+/**
+ * Allocates 1K of conventional memory.
+ */
+static uint16_t ahci_mem_alloc(void)
+{
+ uint16_t base_mem_kb;
+ uint16_t ahci_seg;
+
+ base_mem_kb = read_word(0x00, 0x0413);
+
+ DBG_AHCI("AHCI: %dK of base mem\n", base_mem_kb);
+
+ if (base_mem_kb == 0)
+ return 0;
+
+ base_mem_kb--; /* Allocate one block. */
+ ahci_seg = (((uint32_t)base_mem_kb * 1024) >> 4); /* Calculate start segment. */
+
+ write_word(0x00, 0x0413, base_mem_kb);
+
+ return ahci_seg;
+}
+
+/**
+ * Initializes the AHCI HBA and detects attached devices.
+ */
+static int ahci_hba_init(uint16_t io_base)
+{
+ uint8_t i, cPorts;
+ uint32_t val;
+ uint16_t ebda_seg;
+ uint16_t ahci_seg;
+ bio_dsk_t __far *bios_dsk;
+ ahci_t __far *ahci;
+
+
+ ebda_seg = read_word(0x0040, 0x000E);
+ bios_dsk = ebda_seg :> &EbdaData->bdisk;
+
+ AHCI_READ_REG(io_base, AHCI_REG_VS, val);
+ DBG_AHCI("AHCI: Controller version: 0x%x (major) 0x%x (minor)\n",
+ ahci_ctrl_extract_bits(val, 0xffff0000, 16),
+ ahci_ctrl_extract_bits(val, 0x0000ffff, 0));
+
+ /* Allocate 1K of base memory. */
+ ahci_seg = ahci_mem_alloc();
+ if (ahci_seg == 0)
+ {
+ DBG_AHCI("AHCI: Could not allocate 1K of memory, can't boot from controller\n");
+ return 0;
+ }
+ DBG_AHCI("AHCI: ahci_seg=%04x, size=%04x, pointer at EBDA:%04x (EBDA size=%04x)\n",
+ ahci_seg, sizeof(ahci_t), (uint16_t)&EbdaData->bdisk.ahci_seg, sizeof(ebda_data_t));
+
+ bios_dsk->ahci_seg = ahci_seg;
+ bios_dsk->ahci_devcnt = 0;
+
+ ahci = ahci_seg :> 0;
+ ahci->cur_port = 0xff;
+ ahci->iobase = io_base;
+
+ /* Physical address of memory used for throwing away ATAPI data when reading 512-byte
+ * blocks from 2048-byte CD sectors.
+ */
+ ahci->sink_buf_phys = 0xCC000; /// @todo find some better place!
+
+ /* Reset the controller. */
+ ahci_ctrl_set_bits(io_base, AHCI_REG_GHC, AHCI_GHC_HR);
+ do
+ {
+ AHCI_READ_REG(io_base, AHCI_REG_GHC, val);
+ } while ((val & AHCI_GHC_HR) != 0);
+
+ AHCI_READ_REG(io_base, AHCI_REG_CAP, val);
+ cPorts = ahci_ctrl_extract_bits(val, 0x1f, 0) + 1; /* Extract number of ports.*/
+
+ DBG_AHCI("AHCI: HBA has %u ports\n", cPorts);
+
+ /* Go through the ports. */
+ i = 0;
+ while (i < 32)
+ {
+ if (ahci_ctrl_is_bit_set(io_base, AHCI_REG_PI, RT_BIT_32(i)) != 0)
+ {
+ DBG_AHCI("AHCI: Port %u is present\n", i);
+ ahci_port_detect_device(ahci_seg :> 0, i);
+ cPorts--;
+ if (cPorts == 0)
+ break;
+ }
+ i++;
+ }
+
+ return 0;
+}
+
+/**
+ * Init the AHCI driver and detect attached disks.
+ */
+void BIOSCALL ahci_init(void)
+{
+ uint16_t busdevfn;
+
+ busdevfn = pci_find_classcode(0x00010601);
+ if (busdevfn != VBOX_AHCI_NO_DEVICE)
+ {
+ uint8_t u8Bus, u8DevFn;
+ uint8_t u8PciCapOff;
+
+ u8Bus = (busdevfn & 0xff00) >> 8;
+ u8DevFn = busdevfn & 0x00ff;
+
+ DBG_AHCI("AHCI HBA at Bus %u DevFn 0x%x (raw 0x%x)\n", u8Bus, u8DevFn, busdevfn);
+
+ /* Examine the capability list and search for the Serial ATA Capability Register. */
+ u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, PCI_CONFIG_CAP);
+
+ while (u8PciCapOff != 0)
+ {
+ uint8_t u8PciCapId = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff);
+
+ DBG_AHCI("Capability ID 0x%x at 0x%x\n", u8PciCapId, u8PciCapOff);
+
+ if (u8PciCapId == PCI_CAP_ID_SATACR)
+ break;
+
+ /* Go on to the next capability. */
+ u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1);
+ }
+
+ if (u8PciCapOff != 0)
+ {
+ uint8_t u8Rev;
+
+ DBG_AHCI("AHCI HBA with SATA Capability register at 0x%x\n", u8PciCapOff);
+
+ /* Advance to the stuff behind the id and next capability pointer. */
+ u8PciCapOff += 2;
+
+ u8Rev = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff);
+ if (u8Rev == 0x10)
+ {
+ /* Read the SATACR1 register and get the bar and offset of the index/data pair register. */
+ uint8_t u8Bar = 0x00;
+ uint16_t u16Off = 0x00;
+ uint16_t u16BarOff = pci_read_config_word(u8Bus, u8DevFn, u8PciCapOff + 2);
+
+ DBG_AHCI("SATACR1: 0x%x\n", u16BarOff);
+
+ switch (u16BarOff & 0xf)
+ {
+ case 0x04:
+ u8Bar = 0x10;
+ break;
+ case 0x05:
+ u8Bar = 0x14;
+ break;
+ case 0x06:
+ u8Bar = 0x18;
+ break;
+ case 0x07:
+ u8Bar = 0x1c;
+ break;
+ case 0x08:
+ u8Bar = 0x20;
+ break;
+ case 0x09:
+ u8Bar = 0x24;
+ break;
+ case 0x0f:
+ default:
+ /* Reserved or unsupported. */
+ DBG_AHCI("BAR 0x%x unsupported\n", u16BarOff & 0xf);
+ }
+
+ /* Get the offset inside the BAR from bits 4:15. */
+ u16Off = (u16BarOff >> 4) * 4;
+
+ if (u8Bar != 0x00)
+ {
+ uint32_t u32Bar = pci_read_config_dword(u8Bus, u8DevFn, u8Bar);
+
+ DBG_AHCI("BAR at 0x%x : 0x%x\n", u8Bar, u32Bar);
+
+ if ((u32Bar & 0x01) != 0)
+ {
+ int rc;
+ uint16_t u16AhciIoBase = (u32Bar & 0xfff0) + u16Off;
+
+ /* Enable PCI memory, I/O, bus mastering access in command register. */
+ pci_write_config_word(u8Bus, u8DevFn, 4, 0x7);
+
+ DBG_AHCI("I/O base: 0x%x\n", u16AhciIoBase);
+ rc = ahci_hba_init(u16AhciIoBase);
+ }
+ else
+ DBG_AHCI("BAR is MMIO\n");
+ }
+ }
+ else
+ DBG_AHCI("Invalid revision 0x%x\n", u8Rev);
+ }
+ else
+ DBG_AHCI("AHCI HBA with no usable Index/Data register pair!\n");
+ }
+ else
+ DBG_AHCI("No AHCI HBA!\n");
+}
diff --git a/src/VBox/Devices/PC/BIOS/apm.c b/src/VBox/Devices/PC/BIOS/apm.c
new file mode 100644
index 00000000..c7fbf6ea
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/apm.c
@@ -0,0 +1,232 @@
+/* $Id: apm.c $ */
+/** @file
+ * APM BIOS support. Implements APM version 1.2.
+ */
+
+/*
+ * Copyright (C) 2004-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "biosint.h"
+#include "inlines.h"
+#include "VBox/bios.h"
+
+#if DEBUG_APM
+# define BX_DEBUG_APM(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define BX_DEBUG_APM(...)
+#endif
+
+/* Implemented in assembly. */
+extern void apm_pm16_entry(void);
+#pragma aux apm_pm16_entry "*"
+
+#if VBOX_BIOS_CPU >= 80386
+extern void apm_pm32_entry(void);
+#pragma aux apm_pm32_entry "*"
+#endif
+
+/* APM function codes. */
+enum apm_func {
+ APM_CHECK = 0x00, /* APM Installation Check */
+ APM_RM_CONN = 0x01, /* APM Real Mode Interface Connect */
+ APM_PM_CONN = 0x02, /* APM Protected Mode 16-bit Interface Connect */
+ APM_32_CONN = 0x03, /* APM Protected Mode 32-bit Interface Connect */
+ APM_DISCONN = 0x04, /* APM Interface Disconnect */
+ APM_IDLE = 0x05, /* CPU Idle */
+ APM_BUSY = 0x06, /* CPU Busy */
+ APM_SET_PWR = 0x07, /* Set Power State */
+ APM_ENBL_PM = 0x08, /* Enable/Disable Power Management */
+ APM_SET_DFL = 0x09, /* Restore APM BIOS Power-On Defaults */
+ APM_STATUS = 0x0A, /* Get Power Status */
+ APM_GET_EVT = 0x0B, /* Get PM Event */
+ APM_GET_PWR = 0x0C, /* Get Power State */
+ APM_DEVPM = 0x0D, /* Enable/Disable Device Power Management */
+ APM_DRV_VER = 0x0E, /* APM Driver Version */
+ APM_ENGAGE = 0x0F, /* Engage/Disengage Power Management */
+ APM_GET_CAP = 0x10 /* Get Capabilities */
+};
+
+enum apm_error {
+ APM_ERR_PM_DISABLED = 0x01, /* Power Management functionality disabled */
+ APM_ERR_RM_INUSE = 0x02, /* Real mode interface connection already established */
+ APM_ERR_NOT_CONN = 0x03, /* Interface not connected */
+ APM_ERR_PM_16_INUSE = 0x05, /* 16-bit protected mode interface connection already established */
+ APM_ERR_NO_PM_16 = 0x06, /* 16-bit protected mode interface not supported */
+ APM_ERR_PM_32_INUSE = 0x07, /* 32-bit protected mode interface connection already established */
+ APM_ERR_NO_PM_32 = 0x08, /* 32-bit protected mode interface not supported */
+ APM_ERR_BAD_DEV_ID = 0x09, /* Unrecognized device ID */
+ APM_ERR_INVAL_PARAM = 0x0A, /* Parameter out of range */
+ APM_ERR_NOT_ENGAGED = 0x0B, /* Interface not engaged */
+ APM_ERR_UNSUPPORTED = 0x0C, /* Function not supported */
+ APM_ERR_NO_RSM_TMR = 0x0D, /* Resume timer disabled */
+ APM_ERR_NO_EVENTS = 0x80 /* No power management events pending */
+};
+
+enum apm_power_state {
+ APM_PS_ENABLED = 0x00, /* APM enabled */
+ APM_PS_STANDBY = 0x01, /* Standby */
+ APM_PS_SUSPEND = 0x02, /* Suspend */
+ APM_PS_OFF = 0x03, /* Suspend */
+};
+
+/// @todo merge with system.c
+#define AX r.gr.u.r16.ax
+#define BX r.gr.u.r16.bx
+#define CX r.gr.u.r16.cx
+#define DX r.gr.u.r16.dx
+#define SI r.gr.u.r16.si
+#define DI r.gr.u.r16.di
+#define BP r.gr.u.r16.bp
+#define SP r.gr.u.r16.sp
+#define FLAGS r.fl.u.r16.flags
+#define EAX r.gr.u.r32.eax
+#define EBX r.gr.u.r32.ebx
+#define ECX r.gr.u.r32.ecx
+#define EDX r.gr.u.r32.edx
+#define ES r.es
+
+#define APM_BIOS_SEG 0xF000 /* Real-mode APM segment. */
+#define APM_BIOS_SEG_LEN 0xFFF0 /* Length of APM segment. */
+
+/* The APM BIOS interface uses 32-bit registers *only* in the 32-bit
+ * protected mode connect call. Rather than saving/restoring 32-bit
+ * registers all the time, simply set the high words of those registers
+ * when necessary.
+ */
+void set_ebx_hi(uint16_t val);
+#pragma aux set_ebx_hi = \
+ ".386" \
+ "shl ebx, 16" \
+ parm [bx] modify exact [bx] nomemory;
+
+void set_esi_hi(uint16_t val);
+#pragma aux set_esi_hi = \
+ ".386" \
+ "shl esi, 16" \
+ parm [si] modify exact [si] nomemory;
+
+
+/* The APM handler has unique requirements. It must be callable from real and
+ * protected mode, both 16-bit and 32-bit. In protected mode, the caller must
+ * ensures that appropriate selectors are available; these only cover the BIOS
+ * code and data, hence the BIOS Data Area or EBDA cannot be accessed. CMOS is
+ * a good place to store information which needs to be accessible from several
+ * different contexts.
+ *
+ * Note that the 32-bit protected-mode handler only needs to thunk down to the
+ * 16-bit code. There's no need for separate 16-bit and 32-bit implementation.
+ */
+
+/* Output a null-terminated string to a specified port, without the
+ * terminating null character.
+ */
+static void apm_out_str_asm(uint16_t port, const char *s);
+#pragma aux apm_out_str_asm = \
+ "mov al, [bx]" \
+ "next:" \
+ "out dx, al" \
+ "inc bx" \
+ "mov al, [bx]" \
+ "or al, al" \
+ "jnz next" \
+ parm [dx] [bx] modify exact [ax bx] nomemory;
+
+/* Wrapper to avoid unnecessary inlining. */
+void apm_out_str(const char *s, uint16_t port)
+{
+ if (*s)
+ apm_out_str_asm(port, s);
+}
+
+void BIOSCALL apm_function(sys_regs_t r)
+{
+ BX_DEBUG_APM("APM: AX=%04X BX=%04X CX=%04X\n", AX, BX, CX);
+
+ CLEAR_CF(); /* Boldly expect success. */
+ switch (GET_AL()) {
+ case APM_CHECK:
+ AX = 0x0102; /* Version 1.2 */
+ BX = 0x504D; /* 'PM' */
+ CX = 3; /* Bits 0/1: 16-bit/32-bit PM interface */
+ break;
+ case APM_RM_CONN:
+ /// @todo validate device ID
+ /// @todo validate current connection state
+ /// @todo change connection state
+ break;
+ case APM_PM_CONN:
+ /// @todo validate device ID
+ /// @todo validate current connection state
+ /// @todo change connection state
+ AX = APM_BIOS_SEG; /* 16-bit PM code segment (RM segment base). */
+ BX = (uint16_t)apm_pm16_entry; /* 16-bit PM entry point offset. */
+ CX = APM_BIOS_SEG; /* 16-bit data segment. */
+ SI = APM_BIOS_SEG_LEN; /* 16-bit PM code segment length. */
+ DI = APM_BIOS_SEG_LEN; /* Data segment length. */
+ break;
+#if VBOX_BIOS_CPU >= 80386
+ case APM_32_CONN:
+ /// @todo validate device ID
+ /// @todo validate current connection state
+ /// @todo change connection state
+ AX = APM_BIOS_SEG; /* 32-bit PM code segment (RM segment base). */
+ BX = (uint16_t)apm_pm32_entry; /* 32-bit entry point offset. */
+ CX = APM_BIOS_SEG; /* 16-bit code segment. */
+ DX = APM_BIOS_SEG; /* 16-bit data segment. */
+ SI = APM_BIOS_SEG_LEN; /* 32-bit code segment length. */
+ DI = APM_BIOS_SEG_LEN; /* Data segment length. */
+ set_ebx_hi(0);
+ set_esi_hi(APM_BIOS_SEG_LEN); /* 16-bit code segment length. */
+ break;
+#endif
+ case APM_IDLE:
+ int_enable(); /* Simply halt the CPU with interrupts enabled. */
+ halt();
+ break;
+ case APM_SET_PWR:
+ /// @todo validate device ID
+ /// @todo validate current connection state
+ switch (CX) {
+ case APM_PS_STANDBY:
+ apm_out_str("Standby", VBOX_BIOS_SHUTDOWN_PORT);
+ break;
+ case APM_PS_SUSPEND:
+ apm_out_str("Suspend", VBOX_BIOS_SHUTDOWN_PORT);
+ break;
+ case APM_PS_OFF:
+ apm_out_str("Shutdown", VBOX_BIOS_SHUTDOWN_PORT); /* Should not return. */
+ break;
+ default:
+ SET_AH(APM_ERR_INVAL_PARAM);
+ SET_CF();
+ }
+ break;
+ case APM_DRV_VER:
+ AX = 0x0102; /// @todo Not right - must take driver version into account!
+ break;
+ case APM_DISCONN:
+ /// @todo actually perform a disconnect...
+ case APM_BUSY: /* Nothing to do as APM Idle doesn't slow CPU clock. */
+ break;
+ case APM_GET_EVT:
+ /// @todo error should be different if interface not connected + engaged
+ SET_AH(APM_ERR_NO_EVENTS); /* PM events don't happen. */
+ SET_CF();
+ break;
+ default:
+ BX_INFO("APM: Unsupported function AX=%04X BX=%04X called\n", AX, BX);
+ SET_AH(APM_ERR_UNSUPPORTED);
+ SET_CF();
+ }
+}
diff --git a/src/VBox/Devices/PC/BIOS/apm_pm.asm b/src/VBox/Devices/PC/BIOS/apm_pm.asm
new file mode 100644
index 00000000..7e775528
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/apm_pm.asm
@@ -0,0 +1,209 @@
+; $Id:
+;; @file
+; Protected-mode APM implementation.
+;
+
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+
+include commondefs.inc
+
+;; 16-bit protected mode APM entry point
+
+_TEXT segment public 'CODE'
+
+extern _apm_function:near ; implemented in C code
+
+
+public apm_pm16_entry
+
+SET_DEFAULT_CPU_286
+
+
+; APM function dispatch table
+apm_disp:
+ dw offset apmf_disconnect ; 04h
+ dw offset apmf_idle ; 05h
+ dw offset apmf_busy ; 06h
+ dw offset apmf_set_state ; 07h
+ dw offset apmf_enable ; 08h
+ dw offset apmf_restore ; 09h
+ dw offset apmf_get_status ; 0Ah
+ dw offset apmf_get_event ; 0Bh
+ dw offset apmf_pwr_state ; 0Ch
+ dw offset apmf_dev_pm ; 0Dh
+ dw offset apmf_version ; 0Eh
+ dw offset apmf_engage ; 0Fh
+ dw offset apmf_get_caps ; 10h
+apm_disp_end:
+
+;
+; APM worker routine. Function code in AL; it is assumed that AL >= 4.
+; Caller must preserve BP.
+;
+apm_worker proc near
+
+ sti ; TODO ?? necessary ??
+
+ push ax ; check if function is supported...
+ xor ah, ah
+ sub al, 4
+ mov bp, ax
+ shl bp, 1
+ cmp al, (apm_disp_end - apm_disp) / 2
+ pop ax
+ mov ah, 53h ; put back APM function
+ jae apmw_bad_func ; validate function range
+
+ jmp apm_disp[bp] ; and dispatch
+
+apmf_disconnect: ; function 04h
+ jmp apmw_success
+
+apmf_idle: ; function 05h
+ sti
+ hlt
+ jmp apmw_success
+
+apmf_busy: ; function 06h
+; jmp apmw_success
+
+apmf_set_state: ; function 07h
+; jmp apmw_success
+
+apmf_enable: ; function 08h
+ jmp apmw_success
+
+apmf_restore: ; function 09h
+; jmp apmw_success
+
+apmf_get_status: ; function 0Ah
+ jmp apmw_bad_func
+
+apmf_get_event: ; function 0Bh
+ mov ah, 80h
+ jmp apmw_failure
+
+apmf_pwr_state: ; function 0Ch
+
+apmf_dev_pm: ; function 0Dh
+ jmp apmw_bad_func
+
+apmf_version: ; function 0Eh
+ mov ax, 0102h
+ jmp apmw_success
+
+apmf_engage: ; function 0Fh
+ ; TODO do something?
+ jmp apmw_success
+
+apmf_get_caps: ; function 10h
+ mov bl, 0 ; no batteries
+ mov cx, 0 ; no special caps
+ jmp apmw_success
+
+apmw_success:
+ clc ; successful return
+ ret
+
+apmw_bad_func:
+ mov ah, 09h ; unrecognized device ID - generic
+
+apmw_failure:
+ stc ; error for unsupported functions
+ ret
+
+apm_worker endp
+
+
+;; 16-bit protected mode APM entry point
+
+;; According to the APM spec, only CS (16-bit code selector) is defined.
+;; The data selector can be derived from it.
+
+apm_pm16_entry:
+
+ mov ah, 2 ; mark as originating in 16-bit PM
+
+ ; fall through
+
+apm_pm16_entry_from_32:
+
+ push ds ; save registers
+ push bp
+
+ push cs
+ pop bp
+ add bp, 8 ; calculate data selector
+ mov ds, bp ; load data segment
+
+ call apm_worker ; call APM handler
+
+ pop bp
+ pop ds ; restore registers
+
+ retf ; return to caller - 16-bit return
+ ; even to 32-bit thunk!
+
+_TEXT ends
+
+
+if VBOX_BIOS_CPU ge 80386
+
+.386
+
+BIOS32 segment public 'CODE' use32
+
+public apm_pm32_entry
+
+;; 32-bit protected mode APM entry point and thunk
+
+;; According to the APM spec, only CS (32-bit) is defined. 16-bit code
+;; selector and the data selector can be derived from it.
+
+;; WARNING: To simplify matters, we use 16-bit far return to go from 32-bit
+;; code to 16-bit and back. As a consequence, the 32-bit APM code must lie
+;; below 64K boundary in the 32-bit APM code segment.
+
+apm_pm32_entry:
+
+ push ebp ; ebp is not used by APM
+
+ mov bp, cs ; return address for 16-bit code
+ push bp
+ mov ebp, apm_pm32_back
+ push bp ; Note: 16:16 address!
+
+ push cs
+ pop ebp
+ add ebp, 8 ; calculate 16-bit code selector
+ push bp ; push 16-bit code selector
+
+ mov ebp, apm_pm16_entry_from_32
+ push bp ; push 16-bit offset
+
+ mov ah, 3 ; mark as originating in 32-bit PM
+
+ db 66h ; force a 16-bit return
+ retf ; off to 16-bit code...
+
+apm_pm32_back: ; return here from 16-bit code
+
+ pop ebp ; restore scratch register
+ retf
+
+BIOS32 ends
+
+endif ; 32-bit code
+
+ end
diff --git a/src/VBox/Devices/PC/BIOS/ata.c b/src/VBox/Devices/PC/BIOS/ata.c
new file mode 100644
index 00000000..53529614
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/ata.c
@@ -0,0 +1,1204 @@
+/* $Id: ata.c $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+
+#include <stdint.h>
+#include <stdarg.h>
+#include "inlines.h"
+#include "biosint.h"
+#include "ebda.h"
+#include "ata.h"
+
+#if DEBUG_ATA
+# define BX_DEBUG_ATA(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define BX_DEBUG_ATA(...)
+#endif
+
+
+// ---------------------------------------------------------------------------
+// Start of ATA/ATAPI Driver
+// ---------------------------------------------------------------------------
+
+void insw_discard(unsigned nwords, unsigned port);
+#pragma aux insw_discard = \
+ ".286" \
+ "again:" \
+ "in ax,dx" \
+ "loop again" \
+ parm [cx] [dx] modify exact [cx ax] nomemory;
+
+void insd_discard(unsigned ndwords, unsigned port);
+#if VBOX_BIOS_CPU >= 80386
+# pragma aux insd_discard = \
+ ".386" \
+ "push eax" \
+ "again:" \
+ "in eax,dx" \
+ "loop again" \
+ "pop eax" \
+ parm [cx] [dx] modify exact [cx] nomemory;
+#endif
+
+// ---------------------------------------------------------------------------
+// ATA/ATAPI driver : initialization
+// ---------------------------------------------------------------------------
+void BIOSCALL ata_init(void)
+{
+ uint8_t channel, device;
+ bio_dsk_t __far *bios_dsk;
+
+ bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
+
+ // Channels info init.
+ for (channel=0; channel<BX_MAX_ATA_INTERFACES; channel++) {
+ bios_dsk->channels[channel].iface = ATA_IFACE_NONE;
+ bios_dsk->channels[channel].iobase1 = 0x0;
+ bios_dsk->channels[channel].iobase2 = 0x0;
+ bios_dsk->channels[channel].irq = 0;
+ }
+
+ // Devices info init.
+ for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
+ bios_dsk->devices[device].type = DSK_TYPE_NONE;
+ bios_dsk->devices[device].device = DSK_DEVICE_NONE;
+ bios_dsk->devices[device].removable = 0;
+ bios_dsk->devices[device].lock = 0;
+ bios_dsk->devices[device].mode = ATA_MODE_NONE;
+ bios_dsk->devices[device].blksize = 0x200;
+ bios_dsk->devices[device].translation = GEO_TRANSLATION_NONE;
+ bios_dsk->devices[device].lchs.heads = 0;
+ bios_dsk->devices[device].lchs.cylinders = 0;
+ bios_dsk->devices[device].lchs.spt = 0;
+ bios_dsk->devices[device].pchs.heads = 0;
+ bios_dsk->devices[device].pchs.cylinders = 0;
+ bios_dsk->devices[device].pchs.spt = 0;
+ bios_dsk->devices[device].sectors = 0;
+ }
+
+ // hdidmap and cdidmap init.
+ for (device=0; device<BX_MAX_STORAGE_DEVICES; device++) {
+ bios_dsk->hdidmap[device] = BX_MAX_STORAGE_DEVICES;
+ bios_dsk->cdidmap[device] = BX_MAX_STORAGE_DEVICES;
+ }
+
+ bios_dsk->hdcount = 0;
+ bios_dsk->cdcount = 0;
+}
+
+// ---------------------------------------------------------------------------
+// ATA/ATAPI driver : software reset
+// ---------------------------------------------------------------------------
+// ATA-3
+// 8.2.1 Software reset - Device 0
+
+void ata_reset(uint16_t device)
+{
+ uint16_t iobase1, iobase2;
+ uint8_t channel, slave, sn, sc;
+ uint16_t max;
+ uint16_t pdelay;
+ bio_dsk_t __far *bios_dsk;
+
+ bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
+ channel = device / 2;
+ slave = device % 2;
+
+ iobase1 = bios_dsk->channels[channel].iobase1;
+ iobase2 = bios_dsk->channels[channel].iobase2;
+
+ // Reset
+
+ // 8.2.1 (a) -- set SRST in DC
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST);
+
+ // 8.2.1 (b) -- wait for BSY
+ max=0xff;
+ while(--max>0) {
+ uint8_t status = inb(iobase1+ATA_CB_STAT);
+ if ((status & ATA_CB_STAT_BSY) != 0)
+ break;
+ }
+
+ // 8.2.1 (f) -- clear SRST
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
+
+ if (bios_dsk->devices[device].type != DSK_TYPE_NONE) {
+ // 8.2.1 (g) -- check for sc==sn==0x01
+ // select device
+ outb(iobase1+ATA_CB_DH, slave?ATA_CB_DH_DEV1:ATA_CB_DH_DEV0);
+ sc = inb(iobase1+ATA_CB_SC);
+ sn = inb(iobase1+ATA_CB_SN);
+
+ if ( (sc==0x01) && (sn==0x01) ) {
+ // 8.2.1 (h) -- wait for not BSY
+ max=0xffff; /* The ATA specification says that the drive may be busy for up to 30 seconds. */
+ while(--max>0) {
+ uint8_t status = inb(iobase1+ATA_CB_STAT);
+ if ((status & ATA_CB_STAT_BSY) == 0)
+ break;
+ pdelay=0xffff;
+ while (--pdelay>0) {
+ /* nothing */
+ }
+ }
+ }
+ }
+
+ // 8.2.1 (i) -- wait for DRDY
+ max = 0x10; /* Speed up for virtual drives. Disks are immediately ready, CDs never */
+ while(--max>0) {
+ uint8_t status = inb(iobase1+ATA_CB_STAT);
+ if ((status & ATA_CB_STAT_RDY) != 0)
+ break;
+ }
+
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+}
+
+// ---------------------------------------------------------------------------
+// ATA/ATAPI driver : execute a data-in command
+// ---------------------------------------------------------------------------
+ // returns
+ // 0 : no error
+ // 1 : BUSY bit set
+ // 2 : read error
+ // 3 : expected DRQ=1
+ // 4 : no sectors left to read/verify
+ // 5 : more sectors to read/verify
+ // 6 : no sectors left to write
+ // 7 : more sectors to write
+uint16_t ata_cmd_data_in(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t count)
+{
+ uint16_t iobase1, iobase2, blksize, mult_blk_cnt;
+ uint16_t cylinder;
+ uint8_t head;
+ uint8_t sector;
+ uint8_t device;
+ uint8_t status, mode;
+ char __far *buffer;
+
+ device = bios_dsk->drqp.dev_id;
+
+ iobase1 = bios_dsk->channels[device / 2].iobase1;
+ iobase2 = bios_dsk->channels[device / 2].iobase2;
+ mode = bios_dsk->devices[device].mode;
+ blksize = bios_dsk->devices[device].blksize;
+ if (blksize == 0) { /* If transfer size is exactly 64K */
+#if VBOX_BIOS_CPU >= 80386
+ if (mode == ATA_MODE_PIO32)
+ blksize = 0x4000;
+ else
+#endif
+ blksize = 0x8000;
+ } else {
+#if VBOX_BIOS_CPU >= 80386
+ if (mode == ATA_MODE_PIO32)
+ blksize >>= 2;
+ else
+#endif
+ blksize >>= 1;
+ }
+
+ status = inb(iobase1 + ATA_CB_STAT);
+ if (status & ATA_CB_STAT_BSY)
+ {
+ BX_DEBUG_ATA("%s: disk busy\n", __func__);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 1;
+ }
+
+ buffer = bios_dsk->drqp.buffer;
+ sector = bios_dsk->drqp.sector;
+ cylinder = bios_dsk->drqp.cylinder;
+ head = bios_dsk->drqp.head;
+
+ // sector will be 0 only on lba access. Convert to lba-chs
+ if (sector == 0) {
+ if (bios_dsk->drqp.lba + count >= 268435456)
+ {
+ sector = (bios_dsk->drqp.lba >> 24) & 0x00ff;
+ cylinder = (bios_dsk->drqp.lba >> 32) & 0xffff;
+ outb(iobase1 + ATA_CB_SC, (count & 0xff00) >> 8);
+ outb(iobase1 + ATA_CB_SN, sector);
+ outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
+ outb(iobase1 + ATA_CB_CH, cylinder >> 8);
+ /* Leave the bottom 24 bits as is, they are treated correctly by the
+ * LBA28 code path. */
+ }
+ sector = bios_dsk->drqp.lba & 0x000000ffL;
+ cylinder = (bios_dsk->drqp.lba >> 8) & 0x0000ffffL;
+ head = ((bios_dsk->drqp.lba >> 24) & 0x0000000fL) | 0x40;
+ }
+
+ outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
+ outb(iobase1 + ATA_CB_FR, 0x00);
+ outb(iobase1 + ATA_CB_SC, count);
+ outb(iobase1 + ATA_CB_SN, sector);
+ outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
+ outb(iobase1 + ATA_CB_CH, cylinder >> 8);
+ outb(iobase1 + ATA_CB_DH, ((device & 1) ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | head );
+ outb(iobase1 + ATA_CB_CMD, command);
+
+ if (command == ATA_CMD_READ_MULTIPLE || command == ATA_CMD_READ_MULTIPLE_EXT) {
+ mult_blk_cnt = count;
+ count = 1;
+ } else {
+ mult_blk_cnt = 1;
+ }
+
+ while (1) {
+ status = inb(iobase1 + ATA_CB_STAT);
+ if ( !(status & ATA_CB_STAT_BSY) )
+ break;
+ }
+
+ if (status & ATA_CB_STAT_ERR) {
+ BX_DEBUG_ATA("%s: read error\n", __func__);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 2;
+ } else if ( !(status & ATA_CB_STAT_DRQ) ) {
+ BX_DEBUG_ATA("%s: DRQ not set (status %02x)\n", __func__, (unsigned) status);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 3;
+ }
+
+ // FIXME : move seg/off translation here
+
+ int_enable(); // enable higher priority interrupts
+
+ while (1) {
+
+ // adjust if there will be an overrun. 2K max sector size
+ if (FP_OFF(buffer) >= 0xF800)
+ buffer = MK_FP(FP_SEG(buffer) + 0x80, FP_OFF(buffer) - 0x800);
+
+#if VBOX_BIOS_CPU >= 80386
+ if (mode == ATA_MODE_PIO32)
+ buffer = rep_insd(buffer, blksize, iobase1);
+ else
+#endif
+ buffer = rep_insw(buffer, blksize, iobase1);
+ bios_dsk->drqp.trsfsectors += mult_blk_cnt;
+ count--;
+ while (1) {
+ status = inb(iobase1 + ATA_CB_STAT);
+ if ( !(status & ATA_CB_STAT_BSY) )
+ break;
+ }
+ if (count == 0) {
+ if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
+ != ATA_CB_STAT_RDY ) {
+ BX_DEBUG_ATA("%s: no sectors left (status %02x)\n", __func__, (unsigned) status);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 4;
+ }
+ break;
+ }
+ else {
+ if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
+ != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
+ BX_DEBUG_ATA("%s: more sectors left (status %02x)\n", __func__, (unsigned) status);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 5;
+ }
+ continue;
+ }
+ }
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 0;
+}
+
+// ---------------------------------------------------------------------------
+// ATA/ATAPI driver : device detection
+// ---------------------------------------------------------------------------
+
+void BIOSCALL ata_detect(void)
+{
+ uint16_t ebda_seg = read_word(0x0040,0x000E);
+ uint8_t hdcount, cdcount, device, type;
+ uint8_t buffer[0x0200];
+ bio_dsk_t __far *bios_dsk;
+
+ bios_dsk = ebda_seg :> &EbdaData->bdisk;
+
+#if BX_MAX_ATA_INTERFACES > 0
+ bios_dsk->channels[0].iface = ATA_IFACE_ISA;
+ bios_dsk->channels[0].iobase1 = 0x1f0;
+ bios_dsk->channels[0].iobase2 = 0x3f0;
+ bios_dsk->channels[0].irq = 14;
+#endif
+#if BX_MAX_ATA_INTERFACES > 1
+ bios_dsk->channels[1].iface = ATA_IFACE_ISA;
+ bios_dsk->channels[1].iobase1 = 0x170;
+ bios_dsk->channels[1].iobase2 = 0x370;
+ bios_dsk->channels[1].irq = 15;
+#endif
+#if 0 /// @todo - temporarily removed to avoid conflict with AHCI
+#if BX_MAX_ATA_INTERFACES > 2
+ bios_dsk->channels[2].iface = ATA_IFACE_ISA;
+ bios_dsk->channels[2].iobase1 = 0x1e8;
+ bios_dsk->channels[2].iobase2 = 0x3e0;
+ bios_dsk->channels[2].irq = 12;
+#endif
+#if BX_MAX_ATA_INTERFACES > 3
+ bios_dsk->channels[3].iface = ATA_IFACE_ISA;
+ bios_dsk->channels[3].iobase1 = 0x168;
+ bios_dsk->channels[3].iobase2 = 0x360;
+ bios_dsk->channels[3].irq = 11;
+#endif
+#endif
+#if BX_MAX_ATA_INTERFACES > 4
+#error Please fill the ATA interface informations
+#endif
+
+ // Device detection
+ hdcount = cdcount = 0;
+
+ for (device = 0; device < BX_MAX_ATA_DEVICES; device++) {
+ uint16_t iobase1, iobase2;
+ uint8_t channel, slave;
+ uint8_t sc, sn, cl, ch, st;
+
+ channel = device / 2;
+ slave = device % 2;
+
+ iobase1 = bios_dsk->channels[channel].iobase1;
+ iobase2 = bios_dsk->channels[channel].iobase2;
+
+ // Disable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
+
+ // Look for device
+ outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
+ outb(iobase1+ATA_CB_SC, 0x55);
+ outb(iobase1+ATA_CB_SN, 0xaa);
+ outb(iobase1+ATA_CB_SC, 0xaa);
+ outb(iobase1+ATA_CB_SN, 0x55);
+ outb(iobase1+ATA_CB_SC, 0x55);
+ outb(iobase1+ATA_CB_SN, 0xaa);
+
+ // If we found something
+ sc = inb(iobase1+ATA_CB_SC);
+ sn = inb(iobase1+ATA_CB_SN);
+
+ if ( (sc == 0x55) && (sn == 0xaa) ) {
+ bios_dsk->devices[device].type = DSK_TYPE_UNKNOWN;
+
+ // reset the channel
+ ata_reset(device);
+
+ // check for ATA or ATAPI
+ outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
+ sc = inb(iobase1+ATA_CB_SC);
+ sn = inb(iobase1+ATA_CB_SN);
+ if ((sc==0x01) && (sn==0x01)) {
+ cl = inb(iobase1+ATA_CB_CL);
+ ch = inb(iobase1+ATA_CB_CH);
+ st = inb(iobase1+ATA_CB_STAT);
+
+ if ((cl==0x14) && (ch==0xeb)) {
+ bios_dsk->devices[device].type = DSK_TYPE_ATAPI;
+ } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) {
+ bios_dsk->devices[device].type = DSK_TYPE_ATA;
+ } else if ((cl==0xff) && (ch==0xff)) {
+ bios_dsk->devices[device].type = DSK_TYPE_NONE;
+ }
+ }
+ }
+
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+
+ type = bios_dsk->devices[device].type;
+
+ // Now we send a IDENTIFY command to ATA device
+ if (type == DSK_TYPE_ATA) {
+ uint64_t sectors;
+ uint16_t cylinders, heads, spt, blksize;
+ chs_t lgeo;
+ uint8_t chsgeo_base;
+ uint8_t removable, mode;
+
+ //Temporary values to do the transfer
+ bios_dsk->devices[device].device = DSK_DEVICE_HD;
+ bios_dsk->devices[device].mode = ATA_MODE_PIO16;
+ bios_dsk->drqp.buffer = buffer;
+ bios_dsk->drqp.dev_id = device;
+
+ if (ata_cmd_data_in(bios_dsk, ATA_CMD_IDENTIFY_DEVICE, 1) !=0 )
+ BX_PANIC("ata-detect: Failed to detect ATA device\n");
+
+ removable = (*(buffer+0) & 0x80) ? 1 : 0;
+#if VBOX_BIOS_CPU >= 80386
+ mode = *(buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
+#else
+ mode = ATA_MODE_PIO16;
+#endif
+ blksize = 512; /* There is no sector size field any more. */
+
+ cylinders = *(uint16_t *)(buffer+(1*2)); // word 1
+ heads = *(uint16_t *)(buffer+(3*2)); // word 3
+ spt = *(uint16_t *)(buffer+(6*2)); // word 6
+
+ sectors = *(uint32_t *)(buffer+(60*2)); // word 60 and word 61
+ if (sectors == 0x0FFFFFFF) /* For disks bigger than ~128GB */
+ sectors = *(uint64_t *)(buffer+(100*2)); // words 100 to 103
+ switch (device)
+ {
+ case 0:
+ chsgeo_base = 0x1e;
+ break;
+ case 1:
+ chsgeo_base = 0x26;
+ break;
+ case 2:
+ chsgeo_base = 0x67;
+ break;
+ case 3:
+ chsgeo_base = 0x70;
+ break;
+ default:
+ chsgeo_base = 0;
+ }
+ if (chsgeo_base)
+ {
+ lgeo.cylinders = inb_cmos(chsgeo_base) + (inb_cmos(chsgeo_base + 1) << 8);
+ lgeo.heads = inb_cmos(chsgeo_base + 2);
+ lgeo.spt = inb_cmos(chsgeo_base + 7);
+ }
+ else
+ set_geom_lba(&lgeo, sectors); /* Default EDD-style translated LBA geometry. */
+
+ BX_INFO("ata%d-%d: PCHS=%u/%u/%u LCHS=%u/%u/%u\n", channel, slave,
+ cylinders, heads, spt, lgeo.cylinders, lgeo.heads, lgeo.spt);
+
+ bios_dsk->devices[device].device = DSK_DEVICE_HD;
+ bios_dsk->devices[device].removable = removable;
+ bios_dsk->devices[device].mode = mode;
+ bios_dsk->devices[device].blksize = blksize;
+ bios_dsk->devices[device].pchs.heads = heads;
+ bios_dsk->devices[device].pchs.cylinders = cylinders;
+ bios_dsk->devices[device].pchs.spt = spt;
+ bios_dsk->devices[device].sectors = sectors;
+ bios_dsk->devices[device].lchs = lgeo;
+ if (device < 2)
+ {
+ uint8_t sum, i;
+ fdpt_t __far *fdpt;
+ void __far * __far *int_vec;
+
+ if (device == 0)
+ fdpt = ebda_seg :> &EbdaData->fdpt0;
+ else
+ fdpt = ebda_seg :> &EbdaData->fdpt1;
+
+#if 0
+ /* Place the FDPT outside of conventional memory. Needed for
+ * 286 XENIX 2.1.3/2.2.1 because it completely wipes out
+ * the EBDA and low memory. Hack!
+ */
+ fdpt = MK_FP(0xE200, 0xf00);
+ fdpt += device;
+#endif
+
+ /* Set the INT 41h or 46h pointer. */
+ int_vec = MK_FP(0, (0x41 + device * 5) * sizeof(void __far *));
+ *int_vec = fdpt;
+
+ /* Update the DPT for drive 0/1 pointed to by Int41/46. This used
+ * to be done at POST time with lots of ugly assembler code, which
+ * isn't worth the effort of converting from AMI to Award CMOS
+ * format. Just do it here. */
+ fdpt->resvd1 = fdpt->resvd2 = 0;
+
+ fdpt->lcyl = lgeo.cylinders;
+ fdpt->lhead = lgeo.heads;
+ fdpt->sig = 0xa0;
+ fdpt->spt = spt;
+ fdpt->cyl = cylinders;
+ fdpt->head = heads;
+ fdpt->lspt = lgeo.spt;
+ sum = 0;
+ for (i = 0; i < 0xf; i++)
+ sum += *((uint8_t __far *)fdpt + i);
+ sum = -sum;
+ fdpt->csum = sum;
+ }
+
+ // fill hdidmap
+ bios_dsk->hdidmap[hdcount] = device;
+ hdcount++;
+ }
+
+ // Now we send an IDENTIFY command to ATAPI device
+ if (type == DSK_TYPE_ATAPI) {
+ uint8_t type, removable, mode;
+ uint16_t blksize;
+
+ // Temporary values to do the transfer
+ bios_dsk->devices[device].device = DSK_DEVICE_CDROM;
+ bios_dsk->devices[device].mode = ATA_MODE_PIO16;
+ bios_dsk->drqp.buffer = buffer;
+ bios_dsk->drqp.dev_id = device;
+
+ if (ata_cmd_data_in(bios_dsk, ATA_CMD_IDENTIFY_PACKET, 1) != 0)
+ BX_PANIC("ata-detect: Failed to detect ATAPI device\n");
+
+ type = *(buffer+1) & 0x1f;
+ removable = (*(buffer+0) & 0x80) ? 1 : 0;
+#if VBOX_BIOS_CPU >= 80386
+ mode = *(buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
+#else
+ mode = ATA_MODE_PIO16;
+#endif
+ blksize = 2048;
+
+ bios_dsk->devices[device].device = type;
+ bios_dsk->devices[device].removable = removable;
+ bios_dsk->devices[device].mode = mode;
+ bios_dsk->devices[device].blksize = blksize;
+
+ // fill cdidmap
+ bios_dsk->cdidmap[cdcount] = device;
+ cdcount++;
+ }
+
+ {
+ uint32_t sizeinmb;
+ uint16_t ataversion;
+ uint8_t version, model[41];
+ int i;
+
+ switch (type) {
+ case DSK_TYPE_ATA:
+ sizeinmb = (bios_dsk->devices[device].sectors >> 11);
+ case DSK_TYPE_ATAPI:
+ // Read ATA/ATAPI version
+ ataversion = ((uint16_t)(*(buffer+161))<<8) | *(buffer+160);
+ for (version = 15; version > 0; version--) {
+ if ((ataversion & (1 << version)) !=0 )
+ break;
+ }
+
+ // Read model name
+ for (i = 0; i < 20; i++ ) {
+ *(model+(i*2)) = *(buffer+(i*2)+54+1);
+ *(model+(i*2)+1) = *(buffer+(i*2)+54);
+ }
+
+ // Reformat
+ *(model+40) = 0x00;
+ for ( i = 39; i > 0; i-- ){
+ if (*(model+i) == 0x20)
+ *(model+i) = 0x00;
+ else
+ break;
+ }
+ break;
+ }
+
+#ifdef VBOXz
+ // we don't want any noisy output for now
+#else /* !VBOX */
+ switch (type) {
+ int c;
+ case DSK_TYPE_ATA:
+ printf("ata%d %s: ", channel, slave ? " slave" : "master");
+ i=0;
+ while(c=*(model+i++))
+ printf("%c", c);
+ printf(" ATA-%d Hard-Disk (%lu MBytes)\n", version, sizeinmb);
+ break;
+ case DSK_TYPE_ATAPI:
+ printf("ata%d %s: ", channel, slave ? " slave" : "master");
+ i=0;
+ while(c=*(model+i++))
+ printf("%c", c);
+ if (bios_dsk->devices[device].device == DSK_DEVICE_CDROM)
+ printf(" ATAPI-%d CD-ROM/DVD-ROM\n", version);
+ else
+ printf(" ATAPI-%d Device\n", version);
+ break;
+ case DSK_TYPE_UNKNOWN:
+ printf("ata%d %s: Unknown device\n", channel , slave ? " slave" : "master");
+ break;
+ }
+#endif /* !VBOX */
+ }
+ }
+
+ // Store the devices counts
+ bios_dsk->hdcount = hdcount;
+ bios_dsk->cdcount = cdcount;
+ write_byte(0x40,0x75, hdcount);
+
+#ifdef VBOX
+ // we don't want any noisy output for now
+#else /* !VBOX */
+ printf("\n");
+#endif /* !VBOX */
+
+ // FIXME : should use bios=cmos|auto|disable bits
+ // FIXME : should know about translation bits
+ // FIXME : move hard_drive_post here
+
+}
+
+// ---------------------------------------------------------------------------
+// ATA/ATAPI driver : execute a data-out command
+// ---------------------------------------------------------------------------
+ // returns
+ // 0 : no error
+ // 1 : BUSY bit set
+ // 2 : read error
+ // 3 : expected DRQ=1
+ // 4 : no sectors left to read/verify
+ // 5 : more sectors to read/verify
+ // 6 : no sectors left to write
+ // 7 : more sectors to write
+uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t count)
+{
+ uint64_t lba;
+ char __far *buffer;
+ uint16_t iobase1, iobase2, blksize;
+ uint16_t cylinder;
+ uint16_t head;
+ uint16_t sector;
+ uint16_t device;
+ uint8_t channel, slave;
+ uint8_t status, mode;
+
+ device = bios_dsk->drqp.dev_id;
+ channel = device / 2;
+ slave = device % 2;
+
+ iobase1 = bios_dsk->channels[channel].iobase1;
+ iobase2 = bios_dsk->channels[channel].iobase2;
+ mode = bios_dsk->devices[device].mode;
+ blksize = 0x200; // was = bios_dsk->devices[device].blksize;
+#if VBOX_BIOS_CPU >= 80386
+ if (mode == ATA_MODE_PIO32)
+ blksize >>= 2;
+ else
+#endif
+ blksize >>= 1;
+
+ status = inb(iobase1 + ATA_CB_STAT);
+ if (status & ATA_CB_STAT_BSY)
+ {
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 1;
+ }
+
+ lba = bios_dsk->drqp.lba;
+ buffer = bios_dsk->drqp.buffer;
+ sector = bios_dsk->drqp.sector;
+ cylinder = bios_dsk->drqp.cylinder;
+ head = bios_dsk->drqp.head;
+
+ // sector will be 0 only on lba access. Convert to lba-chs
+ if (sector == 0) {
+ if (lba + count >= 268435456)
+ {
+ sector = (lba >> 24) & 0x00ff;
+ cylinder = (lba >> 32) & 0xffff;
+ outb(iobase1 + ATA_CB_SC, (count & 0xff00) >> 8);
+ outb(iobase1 + ATA_CB_SN, sector);
+ outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
+ outb(iobase1 + ATA_CB_CH, cylinder >> 8);
+ /* Leave the bottom 24 bits as is, they are treated correctly by the
+ * LBA28 code path. */
+ lba &= 0xffffff;
+ }
+ sector = (uint16_t) (lba & 0x000000ffL);
+ lba >>= 8;
+ cylinder = (uint16_t) (lba & 0x0000ffffL);
+ lba >>= 16;
+ head = ((uint16_t) (lba & 0x0000000fL)) | 0x40;
+ }
+
+ outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
+ outb(iobase1 + ATA_CB_FR, 0x00);
+ outb(iobase1 + ATA_CB_SC, count);
+ outb(iobase1 + ATA_CB_SN, sector);
+ outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
+ outb(iobase1 + ATA_CB_CH, cylinder >> 8);
+ outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (uint8_t) head );
+ outb(iobase1 + ATA_CB_CMD, command);
+
+ while (1) {
+ status = inb(iobase1 + ATA_CB_STAT);
+ if ( !(status & ATA_CB_STAT_BSY) )
+ break;
+ }
+
+ if (status & ATA_CB_STAT_ERR) {
+ BX_DEBUG_ATA("%s: write error\n", __func__);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 2;
+ } else if ( !(status & ATA_CB_STAT_DRQ) ) {
+ BX_DEBUG_ATA("%s: DRQ not set (status %02x)\n", __func__, (unsigned) status);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 3;
+ }
+
+ // FIXME : move seg/off translation here
+
+ int_enable(); // enable higher priority interrupts
+
+ while (1) {
+
+ // adjust if there will be an overrun. 2K max sector size
+ if (FP_OFF(buffer) >= 0xF800)
+ buffer = MK_FP(FP_SEG(buffer) + 0x80, FP_OFF(buffer) - 0x800);
+
+#if VBOX_BIOS_CPU >= 80386
+ if (mode == ATA_MODE_PIO32)
+ buffer = rep_outsd(buffer, blksize, iobase1);
+ else
+#endif
+ buffer = rep_outsw(buffer, blksize, iobase1);
+
+ bios_dsk->drqp.trsfsectors++;
+ count--;
+ while (1) {
+ status = inb(iobase1 + ATA_CB_STAT);
+ if ( !(status & ATA_CB_STAT_BSY) )
+ break;
+ }
+ if (count == 0) {
+ if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
+ != ATA_CB_STAT_RDY ) {
+ BX_DEBUG_ATA("%s: no sectors left (status %02x)\n", __func__, (unsigned) status);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 6;
+ }
+ break;
+ }
+ else {
+ if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
+ != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
+ BX_DEBUG_ATA("%s: more sectors left (status %02x)\n", __func__, (unsigned) status);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 7;
+ }
+ continue;
+ }
+ }
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 0;
+}
+
+
+/**
+ * Read sectors from an attached ATA device.
+ *
+ * @returns status code.
+ * @param bios_dsk Pointer to disk request packet (in the
+ * EBDA).
+ */
+int ata_read_sectors(bio_dsk_t __far *bios_dsk)
+{
+ uint16_t n_sect;
+ int status;
+ uint8_t device_id;
+
+ device_id = bios_dsk->drqp.dev_id;
+ n_sect = bios_dsk->drqp.nsect;
+
+ if (bios_dsk->drqp.sector) {
+ /* CHS addressing. */
+ bios_dsk->devices[device_id].blksize = n_sect * 0x200;
+ BX_DEBUG_ATA("%s: reading %u sectors (CHS)\n", __func__, n_sect);
+ status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_MULTIPLE, n_sect);
+ bios_dsk->devices[device_id].blksize = 0x200;
+ } else {
+ /* LBA addressing. */
+ if (bios_dsk->drqp.lba + n_sect >= 268435456) {
+ BX_DEBUG_ATA("%s: reading %u sector (LBA,EXT)\n", __func__, n_sect);
+ status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_SECTORS_EXT, n_sect);
+ } else {
+ bios_dsk->devices[device_id].blksize = n_sect * 0x200;
+ BX_DEBUG_ATA("%s: reading %u sector (LBA,MULT)\n", __func__, n_sect);
+ status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_MULTIPLE, n_sect);
+ bios_dsk->devices[device_id].blksize = 0x200;
+ }
+ }
+ return status;
+}
+
+/**
+ * Write sectors to an attached ATA device.
+ *
+ * @returns status code.
+ * @param bios_dsk Pointer to disk request packet (in the
+ * EBDA).
+ */
+int ata_write_sectors(bio_dsk_t __far *bios_dsk)
+{
+ uint16_t n_sect;
+
+ n_sect = bios_dsk->drqp.nsect;
+
+ if (bios_dsk->drqp.sector) {
+ /* CHS addressing. */
+ return ata_cmd_data_out(bios_dsk, ATA_CMD_WRITE_SECTORS, n_sect);
+ } else {
+ /* LBA addressing. */
+ if (bios_dsk->drqp.lba + n_sect >= 268435456)
+ return ata_cmd_data_out(bios_dsk, ATA_CMD_WRITE_SECTORS_EXT, n_sect);
+ else
+ return ata_cmd_data_out(bios_dsk, ATA_CMD_WRITE_SECTORS, n_sect);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ATA/ATAPI driver : execute a packet command
+// ---------------------------------------------------------------------------
+ // returns
+ // 0 : no error
+ // 1 : error in parameters
+ // 2 : BUSY bit set
+ // 3 : error
+ // 4 : not ready
+uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
+ uint16_t header, uint32_t length, uint8_t inout, char __far *buffer)
+{
+ uint16_t iobase1, iobase2;
+ uint16_t lcount, lbefore, lafter, count;
+ uint8_t channel, slave;
+ uint8_t status, mode, lmode;
+ uint32_t transfer;
+ bio_dsk_t __far *bios_dsk;
+
+ bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
+
+ channel = device / 2;
+ slave = device % 2;
+
+ // Data out is not supported yet
+ if (inout == ATA_DATA_OUT) {
+ BX_INFO("%s: DATA_OUT not supported yet\n", __func__);
+ return 1;
+ }
+
+ // The header length must be even
+ if (header & 1) {
+ BX_DEBUG_ATA("%s: header must be even (%04x)\n", __func__, header);
+ return 1;
+ }
+
+ iobase1 = bios_dsk->channels[channel].iobase1;
+ iobase2 = bios_dsk->channels[channel].iobase2;
+ mode = bios_dsk->devices[device].mode;
+ transfer = 0L;
+
+ if (cmdlen < 12)
+ cmdlen = 12;
+ if (cmdlen > 12)
+ cmdlen = 16;
+ cmdlen >>= 1;
+
+ // Reset count of transferred data
+ /// @todo clear in calling code?
+ bios_dsk->drqp.trsfsectors = 0;
+ bios_dsk->drqp.trsfbytes = 0;
+
+ status = inb(iobase1 + ATA_CB_STAT);
+ if (status & ATA_CB_STAT_BSY)
+ return 2;
+
+ outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
+ // outb(iobase1 + ATA_CB_FR, 0x00);
+ // outb(iobase1 + ATA_CB_SC, 0x00);
+ // outb(iobase1 + ATA_CB_SN, 0x00);
+ outb(iobase1 + ATA_CB_CL, 0xfff0 & 0x00ff);
+ outb(iobase1 + ATA_CB_CH, 0xfff0 >> 8);
+ outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
+ outb(iobase1 + ATA_CB_CMD, ATA_CMD_PACKET);
+
+ // Device should ok to receive command
+ while (1) {
+ status = inb(iobase1 + ATA_CB_STAT);
+ if ( !(status & ATA_CB_STAT_BSY) ) break;
+ }
+
+ if (status & ATA_CB_STAT_CHK) {
+ BX_DEBUG_ATA("%s: error, status is %02x\n", __func__, status);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 3;
+ } else if ( !(status & ATA_CB_STAT_DRQ) ) {
+ BX_DEBUG_ATA("%s: DRQ not set (status %02x)\n", __func__, (unsigned) status);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 4;
+ }
+
+ int_enable(); // enable higher priority interrupts
+
+ // Normalize address
+ BX_DEBUG_ATA("acp1 buffer ptr: %04x:%04x wlen %04x\n", FP_SEG(cmdbuf), FP_OFF(cmdbuf), cmdlen);
+ cmdbuf = MK_FP(FP_SEG(cmdbuf) + FP_OFF(cmdbuf) / 16 , FP_OFF(cmdbuf) % 16);
+ // cmdseg += (cmdoff / 16);
+ // cmdoff %= 16;
+
+ // Send command to device
+ rep_outsw(cmdbuf, cmdlen, iobase1);
+
+ if (inout == ATA_DATA_NO) {
+ status = inb(iobase1 + ATA_CB_STAT);
+ }
+ else {
+ while (1) {
+
+ while (1) {
+ status = inb(iobase1 + ATA_CB_STAT);
+ if ( !(status & ATA_CB_STAT_BSY) )
+ break;
+ }
+
+ // Check if command completed
+ if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ) ) ==0 )
+ break;
+
+ if (status & ATA_CB_STAT_CHK) {
+ BX_DEBUG_ATA("%s: error (status %02x)\n", __func__, status);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 3;
+ }
+
+ // Device must be ready to send data
+ if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_CHK) )
+ != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
+ BX_DEBUG_ATA("%s: not ready (status %02x)\n", __func__, status);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 4;
+ }
+
+ // Normalize address
+ BX_DEBUG_ATA("acp2 buffer ptr: %04x:%04x\n", FP_SEG(buffer), FP_OFF(buffer));
+ buffer = MK_FP(FP_SEG(buffer) + FP_OFF(buffer) / 16 , FP_OFF(buffer) % 16);
+ // bufseg += (bufoff / 16);
+ // bufoff %= 16;
+
+ // Get the byte count
+ lcount = ((uint16_t)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL);
+
+ // adjust to read what we want
+ if (header>lcount) {
+ lbefore = lcount;
+ header -= lcount;
+ lcount = 0;
+ }
+ else {
+ lbefore = header;
+ header = 0;
+ lcount -= lbefore;
+ }
+
+ if (lcount>length) {
+ lafter = lcount - length;
+ lcount = length;
+ length = 0;
+ }
+ else {
+ lafter = 0;
+ length -= lcount;
+ }
+
+ // Save byte count
+ count = lcount;
+
+ BX_DEBUG_ATA("Trying to read %04x bytes (%04x %04x %04x) ",lbefore+lcount+lafter,lbefore,lcount,lafter);
+ BX_DEBUG_ATA("to 0x%04x:0x%04x\n",FP_SEG(buffer),FP_OFF(buffer));
+
+ // If counts not dividable by 4, use 16bits mode
+ lmode = mode;
+ if (lbefore & 0x03)
+ lmode = ATA_MODE_PIO16;
+ if (lcount & 0x03)
+ lmode = ATA_MODE_PIO16;
+ if (lafter & 0x03)
+ lmode = ATA_MODE_PIO16;
+
+ // adds an extra byte if count are odd. before is always even
+ if (lcount & 0x01) {
+ lcount += 1;
+ if ((lafter > 0) && (lafter & 0x01)) {
+ lafter -= 1;
+ }
+ }
+
+#if VBOX_BIOS_CPU >= 80386
+ if (lmode == ATA_MODE_PIO32) {
+ lcount >>= 2;
+ lbefore >>= 2;
+ lafter >>= 2;
+ } else
+#endif
+ {
+ lcount >>= 1;
+ lbefore >>= 1;
+ lafter >>= 1;
+ }
+
+#if VBOX_BIOS_CPU >= 80386
+ if (lmode == ATA_MODE_PIO32) {
+ if (lbefore)
+ insd_discard(lbefore, iobase1);
+ rep_insd(buffer, lcount, iobase1);
+ if (lafter)
+ insd_discard(lafter, iobase1);
+ } else
+#endif
+ {
+ if (lbefore)
+ insw_discard(lbefore, iobase1);
+ rep_insw(buffer, lcount, iobase1);
+ if (lafter)
+ insw_discard(lafter, iobase1);
+ }
+
+
+ // Compute new buffer address
+ buffer += count;
+
+ // Save transferred bytes count
+ transfer += count;
+ bios_dsk->drqp.trsfbytes = transfer;
+ }
+ }
+
+ // Final check, device must be ready
+ if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_CHK) )
+ != ATA_CB_STAT_RDY ) {
+ BX_DEBUG_ATA("%s: not ready (status %02x)\n", __func__, (unsigned) status);
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 4;
+ }
+
+ // Enable interrupts
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 0;
+}
+
+// ---------------------------------------------------------------------------
+// ATA/ATAPI driver : reset device; intended for ATAPI devices
+// ---------------------------------------------------------------------------
+ // returns
+ // 0 : no error
+ // 1 : error
+uint16_t ata_soft_reset(uint16_t device)
+{
+ uint16_t iobase1, iobase2;
+ uint8_t channel, slave;
+ uint8_t status;
+ bio_dsk_t __far *bios_dsk;
+
+ bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
+
+ channel = device / 2;
+ slave = device % 2;
+
+ iobase1 = bios_dsk->channels[channel].iobase1;
+ iobase2 = bios_dsk->channels[channel].iobase2;
+
+ /* Send a reset command to the device. */
+ outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
+ outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
+ outb(iobase1 + ATA_CB_CMD, ATA_CMD_DEVICE_RESET);
+
+ /* Wait for the device to clear BSY. */
+ while (1) {
+ status = inb(iobase1 + ATA_CB_STAT);
+ if ( !(status & ATA_CB_STAT_BSY) ) break;
+ }
+
+ /* Final check, device must be ready */
+ if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_CHK) )
+ != ATA_CB_STAT_RDY ) {
+ BX_DEBUG_ATA("%s: not ready (status %02x)\n", __func__, (unsigned) status);
+ /* Enable interrupts */
+ outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15);
+ return 1;
+ }
+
+ /* Enable interrupts */
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// End of ATA/ATAPI Driver
+// ---------------------------------------------------------------------------
diff --git a/src/VBox/Devices/PC/BIOS/ata.h b/src/VBox/Devices/PC/BIOS/ata.h
new file mode 100644
index 00000000..2af0fe38
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/ata.h
@@ -0,0 +1,190 @@
+/* $Id: ata.h $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+#ifndef VBOX_INCLUDED_SRC_PC_BIOS_ata_h
+#define VBOX_INCLUDED_SRC_PC_BIOS_ata_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#define ATA_DATA_NO 0x00
+#define ATA_DATA_IN 0x01
+#define ATA_DATA_OUT 0x02
+
+#define ATA_IFACE_NONE 0x00
+#define ATA_IFACE_ISA 0x00
+#define ATA_IFACE_PCI 0x01
+
+#define ATA_MODE_NONE 0x00
+#define ATA_MODE_PIO16 0x00
+#if VBOX_BIOS_CPU >= 80386
+# define ATA_MODE_PIO32 0x01
+#endif
+#define ATA_MODE_ISADMA 0x02
+#define ATA_MODE_PCIDMA 0x03
+#define ATA_MODE_USEIRQ 0x10
+
+// Global defines -- ATA register and register bits.
+// command block & control block regs
+#define ATA_CB_DATA 0 // data reg in/out pio_base_addr1+0
+#define ATA_CB_ERR 1 // error in pio_base_addr1+1
+#define ATA_CB_FR 1 // feature reg out pio_base_addr1+1
+#define ATA_CB_SC 2 // sector count in/out pio_base_addr1+2
+#define ATA_CB_SN 3 // sector number in/out pio_base_addr1+3
+#define ATA_CB_CL 4 // cylinder low in/out pio_base_addr1+4
+#define ATA_CB_CH 5 // cylinder high in/out pio_base_addr1+5
+#define ATA_CB_DH 6 // device head in/out pio_base_addr1+6
+#define ATA_CB_STAT 7 // primary status in pio_base_addr1+7
+#define ATA_CB_CMD 7 // command out pio_base_addr1+7
+#define ATA_CB_ASTAT 6 // alternate status in pio_base_addr2+6
+#define ATA_CB_DC 6 // device control out pio_base_addr2+6
+#define ATA_CB_DA 7 // device address in pio_base_addr2+7
+
+#define ATA_CB_ER_ICRC 0x80 // ATA Ultra DMA bad CRC
+#define ATA_CB_ER_BBK 0x80 // ATA bad block
+#define ATA_CB_ER_UNC 0x40 // ATA uncorrected error
+#define ATA_CB_ER_MC 0x20 // ATA media change
+#define ATA_CB_ER_IDNF 0x10 // ATA id not found
+#define ATA_CB_ER_MCR 0x08 // ATA media change request
+#define ATA_CB_ER_ABRT 0x04 // ATA command aborted
+#define ATA_CB_ER_NTK0 0x02 // ATA track 0 not found
+#define ATA_CB_ER_NDAM 0x01 // ATA address mark not found
+
+#define ATA_CB_ER_P_SNSKEY 0xf0 // ATAPI sense key (mask)
+#define ATA_CB_ER_P_MCR 0x08 // ATAPI Media Change Request
+#define ATA_CB_ER_P_ABRT 0x04 // ATAPI command abort
+#define ATA_CB_ER_P_EOM 0x02 // ATAPI End of Media
+#define ATA_CB_ER_P_ILI 0x01 // ATAPI Illegal Length Indication
+
+// ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC)
+#define ATA_CB_SC_P_TAG 0xf8 // ATAPI tag (mask)
+#define ATA_CB_SC_P_REL 0x04 // ATAPI release
+#define ATA_CB_SC_P_IO 0x02 // ATAPI I/O
+#define ATA_CB_SC_P_CD 0x01 // ATAPI C/D
+
+// bits 7-4 of the device/head (CB_DH) reg
+#define ATA_CB_DH_DEV0 0xa0 // select device 0
+#define ATA_CB_DH_DEV1 0xb0 // select device 1
+
+// status reg (CB_STAT and CB_ASTAT) bits
+#define ATA_CB_STAT_BSY 0x80 // busy
+#define ATA_CB_STAT_RDY 0x40 // ready
+#define ATA_CB_STAT_DF 0x20 // device fault
+#define ATA_CB_STAT_WFT 0x20 // write fault (old name)
+#define ATA_CB_STAT_SKC 0x10 // seek complete
+#define ATA_CB_STAT_SERV 0x10 // service
+#define ATA_CB_STAT_DRQ 0x08 // data request
+#define ATA_CB_STAT_CORR 0x04 // corrected
+#define ATA_CB_STAT_IDX 0x02 // index
+#define ATA_CB_STAT_ERR 0x01 // error (ATA)
+#define ATA_CB_STAT_CHK 0x01 // check (ATAPI)
+
+// device control reg (CB_DC) bits
+#define ATA_CB_DC_HD15 0x08 // bit should always be set to one
+#define ATA_CB_DC_SRST 0x04 // soft reset
+#define ATA_CB_DC_NIEN 0x02 // disable interrupts
+
+// Most mandatory and optional ATA commands (from ATA-3),
+#define ATA_CMD_CFA_ERASE_SECTORS 0xC0
+#define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE 0x03
+#define ATA_CMD_CFA_TRANSLATE_SECTOR 0x87
+#define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD
+#define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38
+#define ATA_CMD_CHECK_POWER_MODE1 0xE5
+#define ATA_CMD_CHECK_POWER_MODE2 0x98
+#define ATA_CMD_DEVICE_RESET 0x08
+#define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90
+#define ATA_CMD_FLUSH_CACHE 0xE7
+#define ATA_CMD_FORMAT_TRACK 0x50
+#define ATA_CMD_IDENTIFY_DEVICE 0xEC
+#define ATA_CMD_IDENTIFY_PACKET 0xA1
+#define ATA_CMD_IDLE1 0xE3
+#define ATA_CMD_IDLE2 0x97
+#define ATA_CMD_IDLE_IMMEDIATE1 0xE1
+#define ATA_CMD_IDLE_IMMEDIATE2 0x95
+#define ATA_CMD_INITIALIZE_DRIVE_PARAMETERS 0x91
+#define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
+#define ATA_CMD_NOP 0x00
+#define ATA_CMD_PACKET 0xA0
+#define ATA_CMD_READ_BUFFER 0xE4
+#define ATA_CMD_READ_DMA 0xC8
+#define ATA_CMD_READ_DMA_QUEUED 0xC7
+#define ATA_CMD_READ_MULTIPLE 0xC4
+#define ATA_CMD_READ_SECTORS 0x20
+#define ATA_CMD_READ_SECTORS_EXT 0x24
+#define ATA_CMD_READ_MULTIPLE_EXT 0x29
+#define ATA_CMD_WRITE_MULTIPLE_EXT 0x39
+#define ATA_CMD_READ_VERIFY_SECTORS 0x40
+#define ATA_CMD_RECALIBRATE 0x10
+#define ATA_CMD_SEEK 0x70
+#define ATA_CMD_SET_FEATURES 0xEF
+#define ATA_CMD_SET_MULTIPLE_MODE 0xC6
+#define ATA_CMD_SLEEP1 0xE6
+#define ATA_CMD_SLEEP2 0x99
+#define ATA_CMD_STANDBY1 0xE2
+#define ATA_CMD_STANDBY2 0x96
+#define ATA_CMD_STANDBY_IMMEDIATE1 0xE0
+#define ATA_CMD_STANDBY_IMMEDIATE2 0x94
+#define ATA_CMD_WRITE_BUFFER 0xE8
+#define ATA_CMD_WRITE_DMA 0xCA
+#define ATA_CMD_WRITE_DMA_QUEUED 0xCC
+#define ATA_CMD_WRITE_MULTIPLE 0xC5
+#define ATA_CMD_WRITE_SECTORS 0x30
+#define ATA_CMD_WRITE_SECTORS_EXT 0x34
+#define ATA_CMD_WRITE_VERIFY 0x3C
+
+extern void ata_reset(uint16_t device);
+
+#endif /* !VBOX_INCLUDED_SRC_PC_BIOS_ata_h */
+
diff --git a/src/VBox/Devices/PC/BIOS/bios.c b/src/VBox/Devices/PC/BIOS/bios.c
new file mode 100644
index 00000000..15481b08
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/bios.c
@@ -0,0 +1,191 @@
+/* $Id: bios.c $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+
+#include <stdint.h>
+#include "inlines.h"
+#include "biosint.h"
+#ifndef VBOX_VERSION_STRING
+#include <VBox/version.h>
+#endif
+
+static const char bios_cvs_version_string[] = "VirtualBox " VBOX_VERSION_STRING;
+
+uint8_t inb_cmos(uint8_t cmos_reg)
+{
+ uint8_t cmos_port = 0x70;
+
+ if (cmos_reg >= 0x80)
+ cmos_port += 2;
+ outb(cmos_port, cmos_reg);
+ return inb(cmos_port + 1);
+}
+
+void outb_cmos(uint8_t cmos_reg, uint8_t val)
+{
+ uint8_t cmos_port = 0x70;
+
+ if (cmos_reg >= 0x80)
+ cmos_port += 2;
+ outb(cmos_port, cmos_reg);
+ outb(cmos_port + 1, val);
+}
+
+void BIOSCALL dummy_isr_function(pusha_regs_t regs, uint16_t es,
+ uint16_t ds, iret_addr_t iret_addr)
+{
+ // Interrupt handler for unexpected hardware interrupts. We have to clear
+ // the PIC because if we don't, the next EOI will clear the wrong interrupt
+ // and all hell will break loose! This routine also masks the unexpected
+ // interrupt so it will generally be called only once for each unexpected
+ // interrupt level.
+ uint8_t isrA, isrB, imr, last_int = 0xFF;
+
+ outb(PIC_MASTER, PIC_CMD_RD_ISR); // Read master ISR
+ isrA = inb(PIC_MASTER);
+ if (isrA) {
+ outb(PIC_SLAVE, PIC_CMD_RD_ISR); // Read slave ISR
+ isrB = inb(PIC_SLAVE);
+ if (isrB) {
+ imr = inb(PIC_SLAVE_MASK);
+ outb(PIC_SLAVE_MASK, imr | isrB ); // Mask this interrupt
+ outb(PIC_SLAVE, PIC_CMD_EOI); // Send EOI on slave PIC
+ } else {
+ imr = inb(PIC_MASTER_MASK);
+ isrA &= 0xFB; // Never mask the cascade interrupt
+ outb(PIC_MASTER_MASK, imr | isrA); // Mask this interrupt
+ }
+ outb(PIC_MASTER, PIC_CMD_EOI); // Send EOI on master PIC
+ last_int = isrA;
+ }
+ write_byte(0x40, 0x6B, last_int); // Write INTR_FLAG
+}
+
+
+void BIOSCALL nmi_handler_msg(void)
+{
+ BX_PANIC("NMI Handler called\n");
+}
+
+void BIOSCALL int18_panic_msg(void)
+{
+ BX_PANIC("INT18: BOOT FAILURE\n");
+}
+
+void BIOSCALL log_bios_start(void)
+{
+#if BX_DEBUG_SERIAL
+ outb(BX_DEBUG_PORT+UART_LCR, 0x03); /* setup for serial logging: 8N1 */
+#endif
+ BX_INFO("%s\n", bios_cvs_version_string);
+}
+
+/* Set video mode. */
+void set_mode(uint8_t mode);
+#pragma aux set_mode = \
+ "mov ah, 0" \
+ "int 10h" \
+ parm [al] modify [ax];
+
+/// @todo restore
+//#undef VBOX
+
+#define BX_PCIBIOS 1
+#define BX_APPNAME "VirtualBox"
+#define BIOS_BUILD_DATE __DATE__
+//--------------------------------------------------------------------------
+// print_bios_banner
+// displays a the bios version
+//--------------------------------------------------------------------------
+void BIOSCALL print_bios_banner(void)
+{
+#ifdef VBOX
+ // Skip the logo if a warm boot is requested.
+ uint16_t warm_boot = read_word(0x0040,0x0072);
+ write_word(0x0040,0x0072, 0);
+ if (warm_boot == 0x1234)
+ {
+ /* Only set text mode. */
+ set_mode(3);
+ return;
+ }
+ /* show graphical logo */
+ show_logo();
+#else /* !VBOX */
+ char *bios_conf;
+
+ /* Avoid using preprocessing directives within macro arguments. */
+ bios_conf =
+#ifdef __WATCOMC__
+ "watcom "
+#endif
+#if BX_APM
+ "apmbios "
+#endif
+#if BX_PCIBIOS
+ "pcibios "
+#endif
+#if BX_ELTORITO_BOOT
+ "eltorito "
+#endif
+#if BX_ROMBIOS32
+ "rombios32 "
+#endif
+ "\n\n";
+
+ printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ",
+ BIOS_BUILD_DATE, bios_cvs_version_string);
+ printf(bios_conf, 0);
+#endif /* VBOX */
+}
diff --git a/src/VBox/Devices/PC/BIOS/biosint.h b/src/VBox/Devices/PC/BIOS/biosint.h
new file mode 100644
index 00000000..befd794f
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/biosint.h
@@ -0,0 +1,311 @@
+/* $Id: biosint.h $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+#ifndef VBOX_INCLUDED_SRC_PC_BIOS_biosint_h
+#define VBOX_INCLUDED_SRC_PC_BIOS_biosint_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Compile-time assertion macro. */
+#define ct_assert(a) extern int ct_ass_arr[!!(a) == 1];
+
+/* For functions called from assembly code. */
+#define BIOSCALL __cdecl
+
+#define BX_ELTORITO_BOOT 1
+#define BX_PCIBIOS 1
+#define BX_USE_PS2_MOUSE 1
+#define BX_APM 1
+
+#ifndef DEBUG_ATA
+# define DEBUG_ATA 0
+#endif
+#ifdef DEBUG_AHCI
+# define DEBUG_AHCI 0
+#endif
+#ifndef DEBUG_SCSI
+# define DEBUG_SCSI 0
+#endif
+#ifndef DEBUG_CD_BOOT
+# define DEBUG_CD_BOOT 0
+#endif
+#ifndef DEBUG_ELTORITO
+# define DEBUG_ELTORITO 0
+#endif
+#ifndef DEBUG_INT13_HD
+# define DEBUG_INT13_HD 0
+#endif
+#ifndef DEBUG_INT13_FL
+# define DEBUG_INT13_FL 0
+#endif
+#ifndef DEBUG_INT13_CD
+# define DEBUG_INT13_CD 0
+#endif
+#ifndef DEBUG_INT15
+# define DEBUG_INT15 0
+#endif
+#ifndef DEBUG_INT15_MS
+# define DEBUG_INT15_MS 0
+#endif
+#ifndef DEBUG_INT16
+# define DEBUG_INT16 0
+#endif
+#ifndef DEBUG_INT1A
+# define DEBUG_INT1A 0
+#endif
+#ifndef DEBUG_INT74
+# define DEBUG_INT74 0
+#endif
+#ifndef DEBUG_PCI
+# define DEBUG_PCI 0
+#endif
+#ifndef DEBUG_APM
+# define DEBUG_APM 0
+#endif
+#ifndef DEBUG_POST
+# define DEBUG_POST 0
+#endif
+
+#define FP_OFF(p) ((unsigned)(p))
+#define FP_SEG(p) ((unsigned)((unsigned long)(void __far*)(p) >> 16))
+#define MK_FP(s,o) (((unsigned short)(s)):>((void __near *)(o)))
+
+typedef struct {
+ union {
+ struct {
+ uint16_t di, si, bp, sp;
+ uint16_t bx, dx, cx, ax;
+ } r16;
+ struct {
+ uint16_t filler[4];
+ uint8_t bl, bh, dl, dh, cl, ch, al, ah;
+ } r8;
+ } u;
+} pusha_regs_t;
+
+typedef struct {
+ union {
+ struct {
+ uint32_t edi, esi, ebp, esp;
+ uint32_t ebx, edx, ecx, eax;
+ } r32;
+ struct {
+ uint16_t di, filler1, si, filler2, bp, filler3, sp, filler4;
+ uint16_t bx, filler5, dx, filler6, cx, filler7, ax, filler8;
+ } r16;
+ struct {
+ uint32_t filler[4];
+ uint8_t bl, bh;
+ uint16_t filler1;
+ uint8_t dl, dh;
+ uint16_t filler2;
+ uint8_t cl, ch;
+ uint16_t filler3;
+ uint8_t al, ah;
+ uint16_t filler4;
+ } r8;
+ } u;
+} pushad_regs_t;
+
+typedef struct {
+ union {
+ struct {
+ uint16_t flags;
+ } r16;
+ struct {
+ uint8_t flagsl;
+ uint8_t flagsh;
+ } r8;
+ } u;
+} flags_t;
+
+typedef struct {
+ uint16_t ip;
+ uint16_t cs;
+ flags_t flags;
+} iret_addr_t;
+
+typedef struct {
+ uint16_t ds;
+ uint16_t es;
+ pusha_regs_t gr;
+ iret_addr_t ra;
+} disk_regs_t;
+
+typedef struct {
+ pusha_regs_t gr;
+ uint16_t es;
+ uint16_t ds;
+ uint16_t ifl;
+ iret_addr_t ra;
+} kbd_regs_t;
+
+typedef struct {
+ pusha_regs_t gr;
+ uint16_t es;
+ uint16_t ds;
+ flags_t fl;
+} sys_regs_t;
+
+typedef struct {
+ pushad_regs_t gr;
+ uint16_t es;
+ uint16_t ds;
+ flags_t fl;
+} sys32_regs_t;
+
+typedef struct {
+ pusha_regs_t gr;
+ iret_addr_t ra;
+} i1apci_regs_t;
+
+
+#define SetCF(x) x.u.r8.flagsl |= 0x01
+#define SetZF(x) x.u.r8.flagsl |= 0x40
+#define ClearCF(x) x.u.r8.flagsl &= 0xfe
+#define ClearZF(x) x.u.r8.flagsl &= 0xbf
+#define GetCF(x) (x.u.r8.flagsl & 0x01)
+
+#define SET_AL(val8) AX = ((AX & 0xff00) | (val8))
+#define SET_BL(val8) BX = ((BX & 0xff00) | (val8))
+#define SET_CL(val8) CX = ((CX & 0xff00) | (val8))
+#define SET_DL(val8) DX = ((DX & 0xff00) | (val8))
+#define SET_AH(val8) AX = ((AX & 0x00ff) | ((val8) << 8))
+#define SET_BH(val8) BX = ((BX & 0x00ff) | ((val8) << 8))
+#define SET_CH(val8) CX = ((CX & 0x00ff) | ((val8) << 8))
+#define SET_DH(val8) DX = ((DX & 0x00ff) | ((val8) << 8))
+
+#define GET_AL() ( AX & 0x00ff )
+#define GET_BL() ( BX & 0x00ff )
+#define GET_CL() ( CX & 0x00ff )
+#define GET_DL() ( DX & 0x00ff )
+#define GET_AH() ( AX >> 8 )
+#define GET_BH() ( BX >> 8 )
+#define GET_CH() ( CX >> 8 )
+#define GET_DH() ( DX >> 8 )
+
+#define GET_ELDL() ( ELDX & 0x00ff )
+#define GET_ELDH() ( ELDX >> 8 )
+
+#define SET_CF() FLAGS |= 0x0001
+#define CLEAR_CF() FLAGS &= 0xfffe
+#define GET_CF() (FLAGS & 0x0001)
+
+#define SET_ZF() FLAGS |= 0x0040
+#define CLEAR_ZF() FLAGS &= 0xffbf
+#define GET_ZF() (FLAGS & 0x0040)
+
+#define SET_IF() FLAGS |= 0x0200
+
+typedef unsigned short bx_bool;
+
+#define BX_VIRTUAL_PORTS 1 /* normal output to Bochs ports */
+#define BX_DEBUG_SERIAL 0 /* output to COM1 */
+
+#define BIOS_PRINTF_HALT 1
+#define BIOS_PRINTF_SCREEN 2
+#define BIOS_PRINTF_INFO 4
+#define BIOS_PRINTF_DEBUG 8
+#define BIOS_PRINTF_ALL (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO)
+#define BIOS_PRINTF_DEBHALT (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO | BIOS_PRINTF_HALT)
+
+extern const char bios_prefix_string[];
+extern void bios_printf(uint16_t action, const char *s, ...);
+extern void put_str(uint16_t action, const char __far *s);
+extern void put_str_near(uint16_t action, const char __near *s);
+extern uint8_t inb_cmos(uint8_t cmos_reg);
+extern void outb_cmos(uint8_t cmos_reg, uint8_t val);
+extern uint16_t cdrom_boot(void);
+extern void show_logo(void);
+extern void delay_boot(uint16_t secs);
+extern bx_bool set_enable_a20(bx_bool val);
+
+#define printf(...) bios_printf(BIOS_PRINTF_SCREEN, __VA_ARGS__)
+
+// Defines the output macros.
+// BX_DEBUG goes to INFO port until we can easily choose debug info on a
+// per-device basis. Debug info are sent only in debug mode
+#define DEBUG_ROMBIOS 1
+#if DEBUG_ROMBIOS
+# define BX_DEBUG(...) bios_printf(BIOS_PRINTF_INFO, __VA_ARGS__)
+#else
+# define BX_DEBUG(...)
+#endif
+#ifdef VBOX
+#define BX_INFO(...) do { put_str(BIOS_PRINTF_INFO, bios_prefix_string); bios_printf(BIOS_PRINTF_INFO, __VA_ARGS__); } while (0)
+#else /* !VBOX */
+#define BX_INFO(...) bios_printf(BIOS_PRINTF_INFO, __VA_ARGS__)
+#endif /* !VBOX */
+#define BX_PANIC(...) bios_printf(BIOS_PRINTF_DEBHALT, __VA_ARGS__)
+
+/* Because we don't tell the recompiler when guest physical memory
+ * is written, it can incorrectly cache guest code overwritten by
+ * DMA (bus master or not). We just re-write the memory block to flush
+ * any of its caches. This is not exactly efficient, but works!
+ */
+#define DMA_WORKAROUND 1
+
+/* Random hardware-related definitions. */
+
+#define PIC_MASTER 0x20
+#define PIC_MASTER_MASK 0x21
+#define PIC_SLAVE 0xA0
+#define PIC_SLAVE_MASK 0xA1
+#define PIC_CMD_EOI 0x20
+#define PIC_CMD_RD_ISR 0x0B
+#define PIC_CMD_INIT 0x11
+
+#endif /* !VBOX_INCLUDED_SRC_PC_BIOS_biosint_h */
+
diff --git a/src/VBox/Devices/PC/BIOS/boot.c b/src/VBox/Devices/PC/BIOS/boot.c
new file mode 100644
index 00000000..b35e4789
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/boot.c
@@ -0,0 +1,354 @@
+/* $Id: boot.c $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+
+#include <stdint.h>
+#include <string.h>
+#include "inlines.h"
+#include "biosint.h"
+#include "ebda.h"
+
+/* Sanity check the LAN boot segment definition. */
+#if VBOX_LANBOOT_SEG < 0xA000
+#error VBOX_LANBOOT_SEG incorrect!
+#endif
+
+/* PnP header used with LAN boot ROMs. */
+typedef struct {
+ uint32_t sig;
+ uint8_t revision;
+ uint8_t length;
+ uint16_t next_s;
+ uint8_t pad1;
+ uint8_t checksum;
+ uint32_t dev_id;
+ uint16_t mfg_string;
+ uint16_t prod_string;
+ uint8_t base_class;
+ uint8_t subclass;
+ uint8_t interface;
+ uint8_t dev_ind;
+ uint16_t boot_code;
+ uint16_t dv;
+ uint16_t bev;
+ uint16_t pad2;
+ uint16_t sriv;
+} pnp_exp_t;
+
+
+int read_boot_sec(uint8_t bootdrv, uint16_t segment);
+#pragma aux read_boot_sec = \
+ "mov ax,0201h" \
+ "mov dh,0" \
+ "mov cx,1" \
+ "xor bx,bx" \
+ "int 13h" \
+ "mov ax,0" \
+ "sbb ax,0" \
+ parm [dl] [es] modify [ax bx cx dx];
+
+//--------------------------------------------------------------------------
+// print_boot_device
+// displays the boot device
+//--------------------------------------------------------------------------
+
+static const char drivetypes[][10]={"Floppy","Hard Disk","CD-ROM","LAN"};
+
+/// @todo pass inputs as bit flags rather than bytes?
+void print_boot_device(uint8_t cdboot, uint8_t lanboot, uint8_t drive)
+{
+ int i;
+
+ // cdboot contains 0 if lan/floppy/harddisk, 1 otherwise
+ // lanboot contains 0 if floppy/harddisk, 1 otherwise
+ // drive contains real/emulated boot drive
+
+ if(cdboot)i=2; // CD-Rom
+ else if(lanboot)i=3; // LAN
+ else if((drive&0x0080)==0x00)i=0; // Floppy
+ else if((drive&0x0080)==0x80)i=1; // Hard drive
+ else return;
+
+ BX_INFO("Booting from %s...\n",drivetypes[i]);
+}
+
+//--------------------------------------------------------------------------
+// print_boot_failure
+// displays the reason why boot failed
+//--------------------------------------------------------------------------
+/// @todo pass inputs as bit flags rather than bytes?
+void print_boot_failure(uint8_t cdboot, uint8_t lanboot, uint8_t drive,
+ uint8_t reason, uint8_t lastdrive)
+{
+ uint16_t drivenum = drive&0x7f;
+
+ // cdboot: 1 if boot from cd, 0 otherwise
+ // lanboot: 1 if boot from lan, 0 otherwise
+ // drive : drive number
+ // reason: 0 signature check failed, 1 read error
+ // lastdrive: 1 boot drive is the last one in boot sequence
+
+ if (cdboot)
+ BX_INFO("Boot from %s failed\n",drivetypes[2]);
+ else if (lanboot)
+ BX_INFO("Boot from %s failed\n",drivetypes[3]);
+ else if (drive & 0x80)
+ BX_INFO("Boot from %s %d failed\n", drivetypes[1],drivenum);
+ else
+ BX_INFO("Boot from %s %d failed\n", drivetypes[0],drivenum);
+
+ if (lastdrive==1) {
+ if (reason==0)
+ BX_PANIC("No bootable medium found! System halted.\n");
+ else
+ BX_PANIC("Could not read from the boot medium! System halted.\n");
+ }
+}
+
+//--------------------------------------------------------------------------
+// print_cdromboot_failure
+// displays the reason why boot failed
+//--------------------------------------------------------------------------
+void print_cdromboot_failure(uint16_t code)
+{
+ BX_INFO("CDROM boot failure code : %04x\n",code);
+ return;
+}
+
+// returns bootsegment in ax, drive in bl
+uint32_t BIOSCALL int19_function(uint8_t bseqnr)
+{
+ /// @todo common code for getting the EBDA segment
+ uint16_t ebda_seg=read_word(0x0040,0x000E);
+ uint16_t bootseq;
+ uint8_t bootdrv;
+ uint8_t bootcd;
+ uint8_t bootlan;
+ uint8_t bootchk;
+ uint16_t bootseg;
+ uint16_t status;
+ uint8_t lastdrive=0;
+
+ // if BX_ELTORITO_BOOT is not defined, old behavior
+ // check bit 5 in CMOS reg 0x2d. load either 0x00 or 0x80 into DL
+ // in preparation for the initial INT 13h (0=floppy A:, 0x80=C:)
+ // 0: system boot sequence, first drive C: then A:
+ // 1: system boot sequence, first drive A: then C:
+ // else BX_ELTORITO_BOOT is defined
+ // CMOS regs 0x3D and 0x38 contain the boot sequence:
+ // CMOS reg 0x3D & 0x0f : 1st boot device
+ // CMOS reg 0x3D & 0xf0 : 2nd boot device
+ // CMOS reg 0x38 & 0xf0 : 3rd boot device
+ // CMOS reg 0x3C & 0x0f : 4th boot device
+ // boot device codes:
+ // 0x00 : not defined
+ // 0x01 : first floppy
+ // 0x02 : first harddrive
+ // 0x03 : first cdrom
+ // 0x04 : local area network
+ // else : boot failure
+
+ // Get the boot sequence
+#if BX_ELTORITO_BOOT
+ bootseq=inb_cmos(0x3d);
+ bootseq|=((inb_cmos(0x38) & 0xf0) << 4);
+ bootseq|=((inb_cmos(0x3c) & 0x0f) << 12);
+ if (read_byte(ebda_seg, (uint16_t)&EbdaData->uForceBootDevice))
+ bootseq = read_byte(ebda_seg, (uint16_t)&EbdaData->uForceBootDevice);
+ /* Boot delay hack. */
+ if (bseqnr == 1)
+ delay_boot((inb_cmos(0x3c) & 0xf0) >> 4); /* Implemented in logo.c */
+
+ if (bseqnr==2) bootseq >>= 4;
+ if (bseqnr==3) bootseq >>= 8;
+ if (bseqnr==4) bootseq >>= 12;
+ if (bootseq<0x10) lastdrive = 1;
+ bootdrv=0x00; bootcd=0;
+ bootlan=0;
+ BX_INFO("Boot : bseqnr=%d, bootseq=%x\r\n",bseqnr, bootseq);
+
+ switch(bootseq & 0x0f) {
+ case 0x01:
+ bootdrv=0x00;
+ bootcd=0;
+ break;
+ case 0x02:
+ {
+ // Get the Boot drive.
+ uint8_t boot_drive = read_byte(ebda_seg, (uint16_t)&EbdaData->uForceBootDrive);
+
+ bootdrv = boot_drive + 0x80;
+ bootcd=0;
+ break;
+ }
+ case 0x03:
+ bootdrv=0x00;
+ bootcd=1;
+ break;
+ case 0x04: bootlan=1; break;
+ default: return 0x00000000;
+ }
+#else
+ bootseq=inb_cmos(0x2d);
+
+ if (bseqnr==2) {
+ bootseq ^= 0x20;
+ lastdrive = 1;
+ }
+ bootdrv=0x00; bootcd=0;
+ if((bootseq&0x20)==0) bootdrv=0x80;
+#endif // BX_ELTORITO_BOOT
+
+#if BX_ELTORITO_BOOT
+ // We have to boot from cd
+ if (bootcd != 0) {
+ status = cdrom_boot();
+
+ // If failure
+ if ( (status & 0x00ff) !=0 ) {
+ print_cdromboot_failure(status);
+ print_boot_failure(bootcd, bootlan, bootdrv, 1, lastdrive);
+ return 0x00000000;
+ }
+
+ bootseg = read_word(ebda_seg,(uint16_t)&EbdaData->cdemu.load_segment);
+ bootdrv = (uint8_t)(status>>8);
+ }
+
+#endif // BX_ELTORITO_BOOT
+
+ // Check for boot from LAN first
+ if (bootlan == 1) {
+ uint8_t __far *fplan;
+
+ fplan = MK_FP(VBOX_LANBOOT_SEG, 0);
+ if (*(uint16_t __far *)fplan == 0xaa55) {
+ pnp_exp_t __far *pnps;
+ uint32_t manuf;
+ void (__far *netboot_entry)(void);
+
+ // This is NOT a generic PnP implementation, but an Etherboot-specific hack.
+ pnps = (void __far *)(fplan + *(uint16_t __far *)(fplan + 0x1a));
+ if (pnps->sig == 0x506e5024/* '$PnP' */) {
+ // Found PnP signature
+ manuf = *(uint32_t __far *)(fplan + pnps->mfg_string);
+ if (manuf == 0x65687445/* 'Ethe' */) {
+ // Found Etherboot ROM
+ print_boot_device(bootcd, bootlan, bootdrv);
+ netboot_entry = (void __far *)(fplan + 6);
+ netboot_entry();
+ }
+ else
+ {
+ //Found Normal Pnp ROM
+ print_boot_device(bootcd, bootlan, bootdrv);
+ int_enable(); /* Disabled as we were invoked via INT instruction. */
+ netboot_entry = (void __far *)(fplan + pnps->bev);
+ netboot_entry();
+ }
+ }
+ }
+
+ // boot from LAN will not return if successful.
+ print_boot_failure(bootcd, bootlan, bootdrv, 1, lastdrive);
+ return 0x00000000;
+ }
+
+ // We have to boot from harddisk or floppy
+ if (bootcd == 0 && bootlan == 0) {
+ bootseg=0x07c0;
+
+ status = read_boot_sec(bootdrv,bootseg);
+ if (status != 0) {
+ print_boot_failure(bootcd, bootlan, bootdrv, 1, lastdrive);
+ return 0x00000000;
+ }
+ }
+
+ // There is *no* requirement whatsoever for a valid floppy boot sector
+ // to have a 55AAh signature. UNIX boot floppies typically have no such
+ // signature. In general, it is impossible to tell a valid bootsector
+ // from an invalid one.
+ // NB: It is somewhat common for failed OS installs to have the
+ // 0x55AA signature and a valid partition table but zeros in the
+ // rest of the boot sector. We do a quick check by comparing the first
+ // and third word of boot sector; if identical, the boot sector is
+ // extremely unlikely to be valid.
+ if (bootdrv != 0) bootchk = 0;
+ else bootchk = 1; /* disable 0x55AA signature check on drive A: */
+
+#if BX_ELTORITO_BOOT
+ // if boot from cd, no signature check
+ if (bootcd != 0)
+ bootchk = 1;
+#endif // BX_ELTORITO_BOOT
+
+ if (read_word(bootseg,0) == read_word(bootseg,4)
+ || (bootchk == 0 && read_word(bootseg,0x1fe) != 0xaa55))
+ {
+ print_boot_failure(bootcd, bootlan, bootdrv, 0, lastdrive);
+ return 0x00000000;
+ }
+
+#if BX_ELTORITO_BOOT
+ // Print out the boot string
+ print_boot_device(bootcd, bootlan, bootdrv);
+#else // BX_ELTORITO_BOOT
+ print_boot_device(0, bootlan, bootdrv);
+#endif // BX_ELTORITO_BOOT
+
+ // return the boot segment
+ return (((uint32_t)bootdrv) << 16) + bootseg;
+}
+
diff --git a/src/VBox/Devices/PC/BIOS/disk.c b/src/VBox/Devices/PC/BIOS/disk.c
new file mode 100644
index 00000000..8da813ef
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/disk.c
@@ -0,0 +1,640 @@
+/* $Id: disk.c $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+
+#include <stdint.h>
+#include "biosint.h"
+#include "inlines.h"
+#include "ebda.h"
+#include "ata.h"
+
+
+#if DEBUG_INT13_HD
+# define BX_DEBUG_INT13_HD(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define BX_DEBUG_INT13_HD(...)
+#endif
+
+/* Generic disk read/write routine signature. */
+typedef __fastcall (* dsk_rw_func)(bio_dsk_t __far *bios_dsk);
+
+/* Controller specific disk access routines. Declared as a union to reduce
+ * the need for conditionals when choosing between read/write functions.
+ * Note that we get away with using near pointers, which is nice.
+ */
+typedef union {
+ struct {
+ dsk_rw_func read;
+ dsk_rw_func write;
+ } s;
+ dsk_rw_func a[2];
+} dsk_acc_t;
+
+/* Pointers to HW specific disk access routines. */
+dsk_acc_t dskacc[DSKTYP_CNT] = {
+ [DSK_TYPE_ATA] = { ata_read_sectors, ata_write_sectors },
+#ifdef VBOX_WITH_AHCI
+ [DSK_TYPE_AHCI] = { ahci_read_sectors, ahci_write_sectors },
+#endif
+#ifdef VBOX_WITH_SCSI
+ [DSK_TYPE_SCSI] = { scsi_read_sectors, scsi_write_sectors },
+#endif
+};
+
+
+/// @todo put in a header
+#define AX r.gr.u.r16.ax
+#define BX r.gr.u.r16.bx
+#define CX r.gr.u.r16.cx
+#define DX r.gr.u.r16.dx
+#define SI r.gr.u.r16.si
+#define DI r.gr.u.r16.di
+#define BP r.gr.u.r16.bp
+#define ELDX r.gr.u.r16.sp
+#define DS r.ds
+#define ES r.es
+#define FLAGS r.ra.flags.u.r16.flags
+
+
+/*
+ * Build translated CHS geometry given a disk size in sectors. Based on
+ * Phoenix EDD 3.0. This is used as a fallback to generate sane logical
+ * geometry in case none was provided in CMOS.
+ */
+void set_geom_lba(chs_t __far *lgeo, uint64_t nsectors64)
+{
+ uint32_t limit = 8257536; /* 1024 * 128 * 63 */
+ uint32_t nsectors;
+ unsigned heads = 255;
+ int i;
+
+ nsectors = (nsectors64 >> 32) ? 0xFFFFFFFFL : (uint32_t)nsectors64;
+ /* Start with ~4GB limit, go down to 504MB. */
+ for (i = 0; i < 4; ++i) {
+ if (nsectors <= limit)
+ heads = (heads + 1) / 2;
+ limit /= 2;
+ }
+
+ lgeo->cylinders = nsectors / (heads * 63UL);
+ if (lgeo->cylinders > 1024)
+ lgeo->cylinders = 1024;
+ lgeo->heads = heads;
+ lgeo->spt = 63; /* Always 63 sectors per track, the maximum. */
+}
+
+int edd_fill_dpt(dpt_t __far *dpt, bio_dsk_t __far *bios_dsk, uint8_t device)
+{
+ uint16_t ebda_seg = read_word(0x0040,0x000E);
+
+ /* Check if buffer is large enough. */
+ if (dpt->size < 0x1a)
+ return -1;
+
+ /* Fill in EDD 1.x table. */
+ if (dpt->size >= 0x1a) {
+ uint64_t lba;
+
+ dpt->size = 0x1a;
+ dpt->blksize = bios_dsk->devices[device].blksize;
+
+ if (bios_dsk->devices[device].device == DSK_DEVICE_CDROM) {
+ dpt->infos = 0x74; /* Removable, media change, lockable, max values */
+ dpt->cylinders = 0xffffffff;
+ dpt->heads = 0xffffffff;
+ dpt->spt = 0xffffffff;
+ dpt->sector_count1 = 0xffffffff;
+ dpt->sector_count2 = 0xffffffff;
+ } else {
+ dpt->infos = 0x02; // geometry is valid
+ dpt->cylinders = bios_dsk->devices[device].pchs.cylinders;
+ dpt->heads = bios_dsk->devices[device].pchs.heads;
+ dpt->spt = bios_dsk->devices[device].pchs.spt;
+ lba = bios_dsk->devices[device].sectors;
+ dpt->sector_count1 = lba;
+ dpt->sector_count2 = lba >> 32;
+ }
+ }
+
+ /* Fill in EDD 2.x table. */
+ if (dpt->size >= 0x1e) {
+ uint8_t channel, irq, mode, checksum, i, xlation;
+ uint16_t iobase1, iobase2, options;
+
+ dpt->size = 0x1e;
+ dpt->dpte_segment = ebda_seg;
+ dpt->dpte_offset = (uint16_t)&EbdaData->bdisk.dpte;
+
+ // Fill in dpte
+ channel = device / 2;
+ iobase1 = bios_dsk->channels[channel].iobase1;
+ iobase2 = bios_dsk->channels[channel].iobase2;
+ irq = bios_dsk->channels[channel].irq;
+ mode = bios_dsk->devices[device].mode;
+ xlation = bios_dsk->devices[device].translation;
+
+ options = (xlation == GEO_TRANSLATION_NONE ? 0 : 1 << 3); /* CHS translation */
+ options |= (1 << 4); /* LBA translation */
+ if (bios_dsk->devices[device].device == DSK_DEVICE_CDROM) {
+ options |= (1 << 5); /* Removable device */
+ options |= (1 << 6); /* ATAPI device */
+ }
+#if VBOX_BIOS_CPU >= 80386
+ options |= (mode == ATA_MODE_PIO32 ? 1 : 0 << 7);
+#endif
+ options |= (xlation == GEO_TRANSLATION_LBA ? 1 : 0 << 9);
+ options |= (xlation == GEO_TRANSLATION_RECHS ? 3 : 0 << 9);
+
+ bios_dsk->dpte.iobase1 = iobase1;
+ bios_dsk->dpte.iobase2 = iobase2;
+ bios_dsk->dpte.prefix = (0xe | (device % 2)) << 4;
+ bios_dsk->dpte.unused = 0xcb;
+ bios_dsk->dpte.irq = irq;
+ bios_dsk->dpte.blkcount = 1;
+ bios_dsk->dpte.dma = 0;
+ bios_dsk->dpte.pio = 0;
+ bios_dsk->dpte.options = options;
+ bios_dsk->dpte.reserved = 0;
+ bios_dsk->dpte.revision = 0x11;
+
+ checksum = 0;
+ for (i = 0; i < 15; ++i)
+ checksum += read_byte(ebda_seg, (uint16_t)&EbdaData->bdisk.dpte + i);
+ checksum = -checksum;
+ bios_dsk->dpte.checksum = checksum;
+ }
+
+ /* Fill in EDD 3.x table. */
+ if (dpt->size >= 0x42) {
+ uint8_t channel, iface, checksum, i;
+ uint16_t iobase1;
+
+ channel = device / 2;
+ iface = bios_dsk->channels[channel].iface;
+ iobase1 = bios_dsk->channels[channel].iobase1;
+
+ dpt->size = 0x42;
+ dpt->key = 0xbedd;
+ dpt->dpi_length = 0x24;
+ dpt->reserved1 = 0;
+ dpt->reserved2 = 0;
+
+ if (iface == ATA_IFACE_ISA) {
+ dpt->host_bus[0] = 'I';
+ dpt->host_bus[1] = 'S';
+ dpt->host_bus[2] = 'A';
+ dpt->host_bus[3] = ' ';
+ }
+ else {
+ // FIXME PCI
+ }
+ dpt->iface_type[0] = 'A';
+ dpt->iface_type[1] = 'T';
+ dpt->iface_type[2] = 'A';
+ dpt->iface_type[3] = ' ';
+ dpt->iface_type[4] = ' ';
+ dpt->iface_type[5] = ' ';
+ dpt->iface_type[6] = ' ';
+ dpt->iface_type[7] = ' ';
+
+ if (iface == ATA_IFACE_ISA) {
+ ((uint16_t __far *)dpt->iface_path)[0] = iobase1;
+ ((uint16_t __far *)dpt->iface_path)[1] = 0;
+ ((uint32_t __far *)dpt->iface_path)[1] = 0;
+ }
+ else {
+ // FIXME PCI
+ }
+ ((uint16_t __far *)dpt->device_path)[0] = device & 1; // device % 2; @todo: correct?
+ ((uint16_t __far *)dpt->device_path)[1] = 0;
+ ((uint32_t __far *)dpt->device_path)[1] = 0;
+
+ checksum = 0;
+ for (i = 30; i < 64; i++)
+ checksum += ((uint8_t __far *)dpt)[i];
+ checksum = -checksum;
+ dpt->checksum = checksum;
+ }
+ return 0;
+}
+
+void BIOSCALL int13_harddisk(disk_regs_t r)
+{
+ uint32_t lba;
+ uint16_t cylinder, head, sector;
+ uint16_t nlc, nlh, nlspt;
+ uint16_t count;
+ uint8_t device, status;
+ bio_dsk_t __far *bios_dsk;
+
+ BX_DEBUG_INT13_HD("%s: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", __func__, AX, BX, CX, DX, ES);
+
+ SET_IF(); /* INT 13h always returns with interrupts enabled. */
+
+ bios_dsk = read_word(0x0040,0x000E) :> &EbdaData->bdisk;
+ write_byte(0x0040, 0x008e, 0); // clear completion flag
+
+ // basic check : device has to be defined
+ if ( (GET_ELDL() < 0x80) || (GET_ELDL() >= 0x80 + BX_MAX_STORAGE_DEVICES) ) {
+ BX_DEBUG("%s: function %02x, ELDL out of range %02x\n", __func__, GET_AH(), GET_ELDL());
+ goto int13_fail;
+ }
+
+ // Get the ata channel
+ device = bios_dsk->hdidmap[GET_ELDL()-0x80];
+
+ // basic check : device has to be valid
+ if (device >= BX_MAX_STORAGE_DEVICES) {
+ BX_DEBUG("%s: function %02x, unmapped device for ELDL=%02x\n", __func__, GET_AH(), GET_ELDL());
+ goto int13_fail;
+ }
+
+ switch (GET_AH()) {
+
+ case 0x00: /* disk controller reset */
+#ifdef VBOX_WITH_SCSI
+ /* SCSI controller does not need a reset. */
+ if (!VBOX_IS_SCSI_DEVICE(device))
+#endif
+ ata_reset (device);
+ goto int13_success;
+ break;
+
+ case 0x01: /* read disk status */
+ status = read_byte(0x0040, 0x0074);
+ SET_AH(status);
+ SET_DISK_RET_STATUS(0);
+ /* set CF if error status read */
+ if (status) goto int13_fail_nostatus;
+ else goto int13_success_noah;
+ break;
+
+ case 0x02: // read disk sectors
+ case 0x03: // write disk sectors
+ case 0x04: // verify disk sectors
+
+ count = GET_AL();
+ cylinder = GET_CH();
+ cylinder |= ( ((uint16_t) GET_CL()) << 2) & 0x300;
+ sector = (GET_CL() & 0x3f);
+ head = GET_DH();
+
+ /* Segment and offset are in ES:BX. */
+ if ( (count > 128) || (count == 0) ) {
+ BX_INFO("%s: function %02x, count out of range!\n", __func__, GET_AH());
+ goto int13_fail;
+ }
+
+ /* Get the logical CHS geometry. */
+ nlc = bios_dsk->devices[device].lchs.cylinders;
+ nlh = bios_dsk->devices[device].lchs.heads;
+ nlspt = bios_dsk->devices[device].lchs.spt;
+
+ /* Sanity check the geometry. */
+ if( (cylinder >= nlc) || (head >= nlh) || (sector > nlspt )) {
+ BX_INFO("%s: function %02x, disk %02x, parameters out of range %04x/%04x/%04x!\n", __func__, GET_AH(), GET_DL(), cylinder, head, sector);
+ goto int13_fail;
+ }
+
+ // FIXME verify
+ if ( GET_AH() == 0x04 )
+ goto int13_success;
+
+ /* If required, translate LCHS to LBA and execute command. */
+ /// @todo The IS_SCSI_DEVICE check should be redundant...
+ if (( (bios_dsk->devices[device].pchs.heads != nlh) || (bios_dsk->devices[device].pchs.spt != nlspt)) || VBOX_IS_SCSI_DEVICE(device)) {
+ lba = ((((uint32_t)cylinder * (uint32_t)nlh) + (uint32_t)head) * (uint32_t)nlspt) + (uint32_t)sector - 1;
+ sector = 0; // this forces the command to be lba
+ }
+
+ BX_DEBUG_INT13_HD("%s: %d sectors from lba %lu @ %04x:%04x\n", __func__,
+ count, lba, ES, BX);
+
+ /* Clear the count of transferred sectors/bytes. */
+ bios_dsk->drqp.trsfsectors = 0;
+ bios_dsk->drqp.trsfbytes = 0;
+
+ /* Pass request information to low level disk code. */
+ bios_dsk->drqp.lba = lba;
+ bios_dsk->drqp.buffer = MK_FP(ES, BX);
+ bios_dsk->drqp.nsect = count;
+ bios_dsk->drqp.sect_sz = 512; /// @todo device specific?
+ bios_dsk->drqp.cylinder = cylinder;
+ bios_dsk->drqp.head = head;
+ bios_dsk->drqp.sector = sector;
+ bios_dsk->drqp.dev_id = device;
+
+ status = dskacc[bios_dsk->devices[device].type].a[GET_AH() - 0x02](bios_dsk);
+
+ // Set nb of sector transferred
+ SET_AL(bios_dsk->drqp.trsfsectors);
+
+ if (status != 0) {
+ BX_INFO("%s: function %02x, error %02x !\n", __func__, GET_AH(), status);
+ SET_AH(0x0c);
+ goto int13_fail_noah;
+ }
+
+ goto int13_success;
+ break;
+
+ case 0x05: /* format disk track */
+ BX_INFO("format disk track called\n");
+ goto int13_success;
+ break;
+
+ case 0x08: /* read disk drive parameters */
+
+ /* Get the logical geometry from internal table. */
+ nlc = bios_dsk->devices[device].lchs.cylinders;
+ nlh = bios_dsk->devices[device].lchs.heads;
+ nlspt = bios_dsk->devices[device].lchs.spt;
+
+ count = bios_dsk->hdcount;
+ /* Maximum cylinder number is just one less than the number of cylinders. */
+ nlc = nlc - 1; /* 0 based , last sector not used */
+ SET_AL(0);
+ SET_CH(nlc & 0xff);
+ SET_CL(((nlc >> 2) & 0xc0) | (nlspt & 0x3f));
+ SET_DH(nlh - 1);
+ SET_DL(count); /* FIXME returns 0, 1, or n hard drives */
+
+ // FIXME should set ES & DI
+ /// @todo Actually, the above comment is nonsense.
+
+ goto int13_success;
+ break;
+
+ case 0x10: /* check drive ready */
+ // should look at 40:8E also???
+
+ // Read the status from controller
+ status = inb(bios_dsk->channels[device/2].iobase1 + ATA_CB_STAT);
+ if ( (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY ) {
+ goto int13_success;
+ } else {
+ SET_AH(0xAA);
+ goto int13_fail_noah;
+ }
+ break;
+
+ case 0x15: /* read disk drive size */
+
+ /* Get the physical geometry from internal table. */
+ cylinder = bios_dsk->devices[device].pchs.cylinders;
+ head = bios_dsk->devices[device].pchs.heads;
+ sector = bios_dsk->devices[device].pchs.spt;
+
+ /* Calculate sector count seen by old style INT 13h. */
+ lba = (uint32_t)cylinder * head * sector;
+ CX = lba >> 16;
+ DX = lba & 0xffff;
+
+ SET_AH(3); // hard disk accessible
+ goto int13_success_noah;
+ break;
+
+ case 0x09: /* initialize drive parameters */
+ case 0x0c: /* seek to specified cylinder */
+ case 0x0d: /* alternate disk reset */
+ case 0x11: /* recalibrate */
+ case 0x14: /* controller internal diagnostic */
+ BX_INFO("%s: function %02xh unimplemented, returns success\n", __func__, GET_AH());
+ goto int13_success;
+ break;
+
+ case 0x0a: /* read disk sectors with ECC */
+ case 0x0b: /* write disk sectors with ECC */
+ case 0x18: // set media type for format
+ default:
+ BX_INFO("%s: function %02xh unsupported, returns fail\n", __func__, GET_AH());
+ goto int13_fail;
+ break;
+ }
+
+int13_fail:
+ SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
+int13_fail_noah:
+ SET_DISK_RET_STATUS(GET_AH());
+int13_fail_nostatus:
+ SET_CF(); // error occurred
+ return;
+
+int13_success:
+ SET_AH(0x00); // no error
+int13_success_noah:
+ SET_DISK_RET_STATUS(0x00);
+ CLEAR_CF(); // no error
+ return;
+}
+
+void BIOSCALL int13_harddisk_ext(disk_regs_t r)
+{
+ uint64_t lba;
+ uint16_t segment, offset;
+ uint8_t device, status;
+ uint16_t count;
+ uint8_t type;
+ bio_dsk_t __far *bios_dsk;
+ int13ext_t __far *i13_ext;
+#if 0
+ uint16_t ebda_seg = read_word(0x0040,0x000E);
+ uint16_t npc, nph, npspt;
+ uint16_t size;
+ dpt_t __far *dpt;
+#endif
+
+ bios_dsk = read_word(0x0040,0x000E) :> &EbdaData->bdisk;
+
+ BX_DEBUG_INT13_HD("%s: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x DS=%04x SI=%04x\n",
+ __func__, AX, BX, CX, DX, ES, DS, SI);
+
+ write_byte(0x0040, 0x008e, 0); // clear completion flag
+
+ // basic check : device has to be defined
+ if ( (GET_ELDL() < 0x80) || (GET_ELDL() >= 0x80 + BX_MAX_STORAGE_DEVICES) ) {
+ BX_DEBUG("%s: function %02x, ELDL out of range %02x\n", __func__, GET_AH(), GET_ELDL());
+ goto int13x_fail;
+ }
+
+ // Get the ata channel
+ device = bios_dsk->hdidmap[GET_ELDL()-0x80];
+
+ // basic check : device has to be valid
+ if (device >= BX_MAX_STORAGE_DEVICES) {
+ BX_DEBUG("%s: function %02x, unmapped device for ELDL=%02x\n", __func__, GET_AH(), GET_ELDL());
+ goto int13x_fail;
+ }
+
+ switch (GET_AH()) {
+ case 0x41: // IBM/MS installation check
+ BX=0xaa55; // install check
+ SET_AH(0x30); // EDD 3.0
+ CX=0x0007; // ext disk access and edd, removable supported
+ goto int13x_success_noah;
+ break;
+
+ case 0x42: // IBM/MS extended read
+ case 0x43: // IBM/MS extended write
+ case 0x44: // IBM/MS verify
+ case 0x47: // IBM/MS extended seek
+
+ /* Get a pointer to the extended structure. */
+ i13_ext = DS :> (int13ext_t *)SI;
+
+ count = i13_ext->count;
+ segment = i13_ext->segment;
+ offset = i13_ext->offset;
+
+ // Get 64 bits lba and check
+ lba = i13_ext->lba2;
+ lba <<= 32;
+ lba |= i13_ext->lba1;
+
+ BX_DEBUG_INT13_HD("%s: %d sectors from LBA 0x%llx @ %04x:%04x\n", __func__,
+ count, lba, segment, offset);
+
+ type = bios_dsk->devices[device].type;
+ if (lba >= bios_dsk->devices[device].sectors) {
+ BX_INFO("%s: function %02x. LBA out of range\n", __func__, GET_AH());
+ goto int13x_fail;
+ }
+
+ /* Don't bother with seek or verify. */
+ if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
+ goto int13x_success;
+
+ /* Clear the count of transferred sectors/bytes. */
+ bios_dsk->drqp.trsfsectors = 0;
+ bios_dsk->drqp.trsfbytes = 0;
+
+ /* Pass request information to low level disk code. */
+ bios_dsk->drqp.lba = lba;
+ bios_dsk->drqp.buffer = MK_FP(segment, offset);
+ bios_dsk->drqp.nsect = count;
+ bios_dsk->drqp.sect_sz = 512; /// @todo device specific?
+ bios_dsk->drqp.sector = 0; /* Indicate LBA. */
+ bios_dsk->drqp.dev_id = device;
+
+ /* Execute the read or write command. */
+ status = dskacc[type].a[GET_AH() - 0x42](bios_dsk);
+ count = bios_dsk->drqp.trsfsectors;
+ i13_ext->count = count;
+
+ if (status != 0) {
+ BX_INFO("%s: function %02x, error %02x !\n", __func__, GET_AH(), status);
+ SET_AH(0x0c);
+ goto int13x_fail_noah;
+ }
+
+ goto int13x_success;
+ break;
+
+ case 0x45: // IBM/MS lock/unlock drive
+ case 0x49: // IBM/MS extended media change
+ goto int13x_success; // Always success for HD
+ break;
+
+ case 0x46: // IBM/MS eject media
+ SET_AH(0xb2); // Volume Not Removable
+ goto int13x_fail_noah; // Always fail for HD
+ break;
+
+ case 0x48: // IBM/MS get drive parameters
+ if (edd_fill_dpt(DS :> (dpt_t *)SI, bios_dsk, device))
+ goto int13x_fail;
+ else
+ goto int13x_success;
+ break;
+
+ case 0x4e: // // IBM/MS set hardware configuration
+ // DMA, prefetch, PIO maximum not supported
+ switch (GET_AL()) {
+ case 0x01:
+ case 0x03:
+ case 0x04:
+ case 0x06:
+ goto int13x_success;
+ break;
+ default :
+ goto int13x_fail;
+ }
+ break;
+
+ case 0x50: // IBM/MS send packet command
+ default:
+ BX_INFO("%s: function %02xh unsupported, returns fail\n", __func__, GET_AH());
+ goto int13x_fail;
+ break;
+ }
+
+int13x_fail:
+ SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
+int13x_fail_noah:
+ SET_DISK_RET_STATUS(GET_AH());
+ SET_CF(); // error occurred
+ return;
+
+int13x_success:
+ SET_AH(0x00); // no error
+int13x_success_noah:
+ SET_DISK_RET_STATUS(0x00);
+ CLEAR_CF(); // no error
+ return;
+}
+
+/* Avoid saving general registers already saved by caller (PUSHA). */
+#pragma aux int13_harddisk modify [di si cx dx bx];
+#pragma aux int13_harddisk_ext modify [di si cx dx bx];
+
diff --git a/src/VBox/Devices/PC/BIOS/ebda.h b/src/VBox/Devices/PC/BIOS/ebda.h
new file mode 100644
index 00000000..910e7542
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/ebda.h
@@ -0,0 +1,382 @@
+/* $Id: ebda.h $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+#ifndef VBOX_INCLUDED_SRC_PC_BIOS_ebda_h
+#define VBOX_INCLUDED_SRC_PC_BIOS_ebda_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <stdint.h>
+
+/* Must be defined here (EBDA structures depend on these). */
+#define BX_MAX_ATA_INTERFACES 4
+#define BX_MAX_ATA_DEVICES (BX_MAX_ATA_INTERFACES*2)
+
+#define BX_USE_ATADRV 1
+#define BX_ELTORITO_BOOT 1
+
+#ifdef VBOX_WITH_SCSI
+ /* Enough for now */
+ #define BX_MAX_SCSI_DEVICES 4
+ /* A SCSI device starts always at BX_MAX_ATA_DEVICES. */
+ #define VBOX_IS_SCSI_DEVICE(device_id) (device_id >= BX_MAX_ATA_DEVICES)
+ #define VBOX_GET_SCSI_DEVICE(device_id) (device_id - BX_MAX_ATA_DEVICES)
+#else
+ #define BX_MAX_SCSI_DEVICES 0
+#endif
+
+#ifdef VBOX_WITH_AHCI
+ /* Four should be enough for now */
+ #define BX_MAX_AHCI_DEVICES 4
+
+ /* An AHCI device starts always at BX_MAX_ATA_DEVICES + BX_MAX_SCSI_DEVICES. */
+ #define VBOX_IS_AHCI_DEVICE(device_id) (device_id >= (BX_MAX_ATA_DEVICES + BX_MAX_SCSI_DEVICES))
+ #define VBOX_GET_AHCI_DEVICE(device_id) (device_id - (BX_MAX_ATA_DEVICES + BX_MAX_SCSI_DEVICES))
+#else
+ #define BX_MAX_AHCI_DEVICES 0
+#endif
+
+#define BX_MAX_STORAGE_DEVICES (BX_MAX_ATA_DEVICES + BX_MAX_SCSI_DEVICES + BX_MAX_AHCI_DEVICES)
+
+/* Generic storage device types. These depend on the controller type and
+ * determine which device access routines should be called.
+ */
+enum dsk_type_enm {
+ DSK_TYPE_NONE, /* Unknown device. */
+ DSK_TYPE_UNKNOWN, /* Unknown ATA device. */
+ DSK_TYPE_ATA, /* ATA disk. */
+ DSK_TYPE_ATAPI, /* ATAPI device. */
+ DSK_TYPE_SCSI, /* SCSI disk. */
+ DSK_TYPE_AHCI, /* SATA disk via AHCI. */
+ DSKTYP_CNT /* Number of disk types. */
+};
+
+/* Disk device types. */
+//@todo: Do we really need these?
+#define DSK_DEVICE_NONE 0x00 /* No device attached. */
+#define DSK_DEVICE_HD 0xFF /* Device is a hard disk. */
+#define DSK_DEVICE_CDROM 0x05 /* Device is a CD-ROM. */
+
+/* Geometry translation modes. */
+enum geo_xlat_enm {
+ GEO_TRANSLATION_NONE, /* No geometry translation. */
+ GEO_TRANSLATION_LBA, /* LBA translation. */
+ GEO_TRANSLATION_LARGE, /* Large CHS translation. */
+ GEO_TRANSLATION_RECHS
+};
+
+#if 1 //BX_USE_ATADRV
+
+/* Note: The DPTE and FDPT structures are industry standards and
+ * may not be modified. The other disk-related structures are
+ * internal to the BIOS.
+ */
+
+/* Translated DPT (Device Parameter Table). */
+typedef struct {
+ uint16_t iobase1;
+ uint16_t iobase2;
+ uint8_t prefix;
+ uint8_t unused;
+ uint8_t irq;
+ uint8_t blkcount;
+ uint8_t dma;
+ uint8_t pio;
+ uint16_t options;
+ uint16_t reserved;
+ uint8_t revision;
+ uint8_t checksum;
+} dpte_t;
+
+ct_assert(sizeof(dpte_t) == 16); /* Ensure correct size. */
+
+#pragma pack(0)
+
+/* FDPT - Fixed Disk Parameter Table. PC/AT compatible; note
+ * that this structure is slightly misaligned.
+ */
+typedef struct {
+ uint16_t lcyl;
+ uint8_t lhead;
+ uint8_t sig;
+ uint8_t spt;
+ uint32_t resvd1;
+ uint16_t cyl;
+ uint8_t head;
+ uint16_t resvd2;
+ uint8_t lspt;
+ uint8_t csum;
+} fdpt_t;
+
+#pragma pack()
+
+ct_assert(sizeof(fdpt_t) == 16); /* Ensure correct size. */
+
+
+/* C/H/S geometry information. */
+typedef struct {
+ uint16_t heads; /* Number of heads. */
+ uint16_t cylinders; /* Number of cylinders. */
+ uint16_t spt; /* Number of sectors per track. */
+} chs_t;
+
+/* IDE/ATA specific device information. */
+typedef struct {
+ uint8_t iface; /* ISA or PCI. */
+ uint8_t irq; /* IRQ (on the PIC). */
+ uint16_t iobase1; /* I/O base 1. */
+ uint16_t iobase2; /* I/O base 2. */
+} ata_chan_t;
+
+#ifdef VBOX_WITH_SCSI
+
+/* SCSI specific device information. */
+typedef struct {
+ uint16_t io_base; /* Port base for HBA communication. */
+ uint8_t target_id; /* Target ID. */
+} scsi_dev_t;
+
+#endif
+
+#ifdef VBOX_WITH_AHCI
+
+/* AHCI specific device information. */
+typedef struct {
+ uint8_t port; /* SATA port. */
+} ahci_dev_t;
+
+#endif
+
+/* Generic disk information. */
+typedef struct {
+ uint8_t type; /* Device type (ATA/ATAPI/SCSI/none/unknown). */
+ uint8_t device; /* Detected type of attached device (HD/CD/none). */
+ uint8_t removable; /* Removable device flag. */
+ uint8_t lock; /* Lock count for removable devices. */
+ //@todo: ATA specific - move?
+ uint8_t mode; /* Transfer mode: PIO 16/32 bits - IRQ - ISADMA - PCIDMA. */
+ uint8_t translation; /* Type of geometry translation. */
+ uint16_t blksize; /* Disk block size. */
+ chs_t lchs; /* Logical CHS geometry. */
+ chs_t pchs; /* Physical CHS geometry. */
+ uint64_t sectors; /* Total sector count. */
+} disk_dev_t;
+
+/* A structure for passing disk request information around. This structure
+ * is designed for saving stack space. As BIOS requests cannot be overlapped,
+ * one such structure is sufficient.
+ */
+typedef struct {
+ uint64_t lba; /* Starting LBA. */
+ void __far *buffer; /* Read/write data buffer pointer. */
+ uint8_t dev_id; /* Device ID; index into devices array. */
+ uint16_t nsect; /* Number of sectors to be transferred. */
+ uint16_t sect_sz; /* Size of a sector in bytes. */
+ uint16_t cylinder; /* Starting cylinder (CHS only). */
+ uint16_t head; /* Starting head (CHS only). */
+ uint16_t sector; /* Starting sector (CHS only). */
+ uint16_t trsfsectors; /* Actual sectors transferred. */
+ uint32_t trsfbytes; /* Actual bytes transferred. */
+ uint16_t skip_b; /* Bytes to skip before transfer. */
+ uint16_t skip_a; /* Bytes to skip after transfer. */
+} disk_req_t;
+
+extern uint16_t ahci_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,
+ uint16_t header, uint32_t length, uint8_t inout, char __far *buffer);
+extern uint16_t scsi_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
+ uint16_t header, uint32_t length, uint8_t inout, char __far *buffer);
+extern uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
+ uint16_t header, uint32_t length, uint8_t inout, char __far *buffer);
+
+extern uint16_t ata_soft_reset(uint16_t device);
+
+/* All BIOS disk information. Disk-related code in the BIOS should not need
+ * anything outside of this structure.
+ */
+typedef struct {
+ disk_req_t drqp; /* Disk request packet. */
+
+ /* Bus-independent disk device information. */
+ disk_dev_t devices[BX_MAX_STORAGE_DEVICES];
+
+ uint8_t hdcount; /* Total number of BIOS disks. */
+ /* Map between (BIOS disk ID - 0x80) and ATA/SCSI/AHCI disks. */
+ uint8_t hdidmap[BX_MAX_STORAGE_DEVICES];
+
+ uint8_t cdcount; /* Number of CD-ROMs. */
+ /* Map between (BIOS CD-ROM ID - 0xE0) and ATA/SCSI/AHCI devices. */
+ uint8_t cdidmap[BX_MAX_STORAGE_DEVICES];
+
+ /* ATA bus-specific device information. */
+ ata_chan_t channels[BX_MAX_ATA_INTERFACES];
+
+#ifdef VBOX_WITH_SCSI
+ /* SCSI bus-specific device information. */
+ scsi_dev_t scsidev[BX_MAX_SCSI_DEVICES];
+ uint8_t scsi_devcount; /* Number of SCSI devices. */
+#endif
+
+#ifdef VBOX_WITH_AHCI
+ /* SATA (AHCI) bus-specific device information. */
+ ahci_dev_t ahcidev[BX_MAX_AHCI_DEVICES];
+ uint8_t ahci_devcnt; /* Number of SATA devices. */
+ uint16_t ahci_seg; /* Segment of AHCI data block. */
+#endif
+
+ dpte_t dpte; /* Buffer for building a DPTE. */
+} bio_dsk_t;
+
+#if BX_ELTORITO_BOOT
+/* El Torito device emulation state. */
+typedef struct {
+ uint8_t active;
+ uint8_t media;
+ uint8_t emulated_drive;
+ uint8_t controller_index;
+ uint16_t device_spec;
+ uint16_t buffer_segment;
+ uint32_t ilba;
+ uint16_t load_segment;
+ uint16_t sector_count;
+ chs_t vdevice; /* Virtual device geometry. */
+} cdemu_t;
+#endif
+
+// for access to EBDA area
+// The EBDA structure should conform to
+// http://www.frontiernet.net/~fys/rombios.htm document
+// I made the ata and cdemu structs begin at 0x121 in the EBDA seg
+/* MS-DOS KEYB.COM may overwrite the word at offset 0x117 in the EBDA
+ * which contains the keyboard ID for PS/2 BIOSes.
+ */
+typedef struct {
+ uint8_t filler1[0x3D];
+
+ fdpt_t fdpt0; /* FDPTs for the first two ATA disks. */
+ fdpt_t fdpt1;
+
+ uint8_t filler2[0xC4];
+
+ bio_dsk_t bdisk; /* Disk driver data (ATA/SCSI/AHCI). */
+
+#if BX_ELTORITO_BOOT
+ cdemu_t cdemu; /* El Torito floppy/HD emulation data. */
+#endif
+
+ unsigned char uForceBootDrive;
+ unsigned char uForceBootDevice;
+} ebda_data_t;
+
+ct_assert(sizeof(ebda_data_t) < 0x380); /* Must be under 1K in size. */
+
+// the last 16 bytes of the EBDA segment are used for the MPS floating
+// pointer structure (though only if an I/O APIC is present)
+
+#define EbdaData ((ebda_data_t *) 0)
+
+// for access to the int13ext structure
+typedef struct {
+ uint8_t size;
+ uint8_t reserved;
+ uint16_t count;
+ uint16_t offset;
+ uint16_t segment;
+ uint32_t lba1;
+ uint32_t lba2;
+} int13ext_t;
+
+/* Disk Physical Table structure */
+typedef struct {
+ uint16_t size;
+ uint16_t infos;
+ uint32_t cylinders;
+ uint32_t heads;
+ uint32_t spt;
+ uint32_t sector_count1;
+ uint32_t sector_count2;
+ uint16_t blksize;
+ uint16_t dpte_offset;
+ uint16_t dpte_segment;
+ uint16_t key;
+ uint8_t dpi_length;
+ uint8_t reserved1;
+ uint16_t reserved2;
+ uint8_t host_bus[4];
+ uint8_t iface_type[8];
+ uint8_t iface_path[8];
+ uint8_t device_path[8];
+ uint8_t reserved3;
+ uint8_t checksum;
+} dpt_t;
+
+/* Note: Using fastcall reduces stack usage a little. */
+int __fastcall ata_read_sectors(bio_dsk_t __far *bios_dsk);
+int __fastcall ata_write_sectors(bio_dsk_t __far *bios_dsk);
+
+int __fastcall scsi_read_sectors(bio_dsk_t __far *bios_dsk);
+int __fastcall scsi_write_sectors(bio_dsk_t __far *bios_dsk);
+
+int __fastcall ahci_read_sectors(bio_dsk_t __far *bios_dsk);
+int __fastcall ahci_write_sectors(bio_dsk_t __far *bios_dsk);
+
+extern void set_geom_lba(chs_t __far *lgeo, uint64_t nsectors);
+extern int edd_fill_dpt(dpt_t __far *dpt, bio_dsk_t __far *bios_dsk, uint8_t device);
+
+// @todo: put this elsewhere (and change/eliminate?)
+#define SET_DISK_RET_STATUS(status) write_byte(0x0040, 0x0074, status)
+
+#endif
+#endif /* !VBOX_INCLUDED_SRC_PC_BIOS_ebda_h */
+
diff --git a/src/VBox/Devices/PC/BIOS/eltorito.c b/src/VBox/Devices/PC/BIOS/eltorito.c
new file mode 100644
index 00000000..ff309023
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/eltorito.c
@@ -0,0 +1,1025 @@
+/* $Id: eltorito.c $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+
+#include <stdint.h>
+#include <string.h>
+#include "inlines.h"
+#include "biosint.h"
+#include "ebda.h"
+#include "ata.h"
+
+#if DEBUG_ELTORITO
+# define BX_DEBUG_INT13_ET(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define BX_DEBUG_INT13_ET(...)
+#endif
+
+#if DEBUG_INT13_CD
+# define BX_DEBUG_INT13_CD(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define BX_DEBUG_INT13_CD(...)
+#endif
+
+#if DEBUG_CD_BOOT
+# define BX_DEBUG_ELTORITO(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define BX_DEBUG_ELTORITO(...)
+#endif
+
+
+/// @todo put in a header
+#define AX r.gr.u.r16.ax
+#define BX r.gr.u.r16.bx
+#define CX r.gr.u.r16.cx
+#define DX r.gr.u.r16.dx
+#define SI r.gr.u.r16.si
+#define DI r.gr.u.r16.di
+#define BP r.gr.u.r16.bp
+#define ELDX r.gr.u.r16.sp
+#define DS r.ds
+#define ES r.es
+#define FLAGS r.ra.flags.u.r16.flags
+
+#pragma pack(1)
+
+/* READ_10/WRITE_10 CDB padded to 12 bytes for ATAPI. */
+typedef struct {
+ uint16_t command; /* Command. */
+ uint32_t lba; /* LBA, MSB first! */
+ uint8_t pad1; /* Unused. */
+ uint16_t nsect; /* Sector count, MSB first! */
+ uint8_t pad2[3]; /* Unused. */
+} cdb_atapi;
+
+#pragma pack()
+
+ct_assert(sizeof(cdb_atapi) == 12);
+
+/* Generic ATAPI/SCSI CD-ROM access routine signature. */
+typedef uint16_t (* cd_pkt_func)(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,
+ uint16_t header, uint32_t length, uint8_t inout, char __far *buffer);
+
+/* Pointers to HW specific CD-ROM access routines. */
+cd_pkt_func pktacc[DSKTYP_CNT] = {
+ [DSK_TYPE_ATAPI] = { ata_cmd_packet },
+#ifdef VBOX_WITH_AHCI
+ [DSK_TYPE_AHCI] = { ahci_cmd_packet },
+#endif
+#ifdef VBOX_WITH_SCSI
+ [DSK_TYPE_SCSI] = { scsi_cmd_packet },
+#endif
+};
+
+#if defined(VBOX_WITH_AHCI) || defined(VBOX_WITH_SCSI)
+uint16_t dummy_soft_reset(uint16_t device_id)
+{
+ return 0;
+}
+#endif
+
+/* Generic reset routine signature. */
+typedef uint16_t (* cd_rst_func)(uint16_t device_id);
+
+/* Pointers to HW specific CD-ROM reset routines. */
+cd_rst_func softrst[DSKTYP_CNT] = {
+ [DSK_TYPE_ATAPI] = { ata_soft_reset },
+#ifdef VBOX_WITH_AHCI
+ [DSK_TYPE_AHCI] = { dummy_soft_reset },
+#endif
+#ifdef VBOX_WITH_SCSI
+ [DSK_TYPE_SCSI] = { dummy_soft_reset },
+#endif
+};
+
+
+// ---------------------------------------------------------------------------
+// Start of El-Torito boot functions
+// ---------------------------------------------------------------------------
+
+// !! TODO !! convert EBDA accesses to far pointers
+
+extern int diskette_param_table;
+
+void BIOSCALL cdemu_init(void)
+{
+ /// @todo a macro or a function for getting the EBDA segment
+ uint16_t ebda_seg = read_word(0x0040,0x000E);
+
+ // the only important data is this one for now
+ write_byte(ebda_seg,(uint16_t)&EbdaData->cdemu.active, 0x00);
+}
+
+uint8_t BIOSCALL cdemu_isactive(void)
+{
+ /// @todo a macro or a function for getting the EBDA segment
+ uint16_t ebda_seg = read_word(0x0040,0x000E);
+
+ return read_byte(ebda_seg,(uint16_t)&EbdaData->cdemu.active);
+}
+
+uint8_t BIOSCALL cdemu_emulated_drive(void)
+{
+ /// @todo a macro or a function for getting the EBDA segment
+ uint16_t ebda_seg = read_word(0x0040,0x000E);
+
+ return read_byte(ebda_seg,(uint16_t)&EbdaData->cdemu.emulated_drive);
+}
+
+// ---------------------------------------------------------------------------
+// Start of int13 for eltorito functions
+// ---------------------------------------------------------------------------
+
+void BIOSCALL int13_eltorito(disk_regs_t r)
+{
+ /// @todo a macro or a function for getting the EBDA segment
+ uint16_t ebda_seg=read_word(0x0040,0x000E);
+ cdemu_t __far *cdemu;
+
+ cdemu = ebda_seg :> &EbdaData->cdemu;
+
+
+ BX_DEBUG_INT13_ET("%s: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", __func__, AX, BX, CX, DX, ES);
+ // BX_DEBUG_INT13_ET("%s: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n", __func__, get_SS(), DS, ES, DI, SI);
+
+ switch (GET_AH()) {
+
+ // FIXME ElTorito Various. Not implemented in many real BIOSes.
+ case 0x4a: // ElTorito - Initiate disk emu
+ case 0x4c: // ElTorito - Initiate disk emu and boot
+ case 0x4d: // ElTorito - Return Boot catalog
+ BX_INFO("%s: call with AX=%04x not implemented.\n", __func__, AX);
+ goto int13_fail;
+ break;
+
+ case 0x4b: // ElTorito - Terminate disk emu
+ // FIXME ElTorito Hardcoded
+ /// @todo maybe our cdemu struct should match El Torito to allow memcpy()?
+ write_byte(DS,SI+0x00,0x13);
+ write_byte(DS,SI+0x01,cdemu->media);
+ write_byte(DS,SI+0x02,cdemu->emulated_drive);
+ write_byte(DS,SI+0x03,cdemu->controller_index);
+ write_dword(DS,SI+0x04,cdemu->ilba);
+ write_word(DS,SI+0x08,cdemu->device_spec);
+ write_word(DS,SI+0x0a,cdemu->buffer_segment);
+ write_word(DS,SI+0x0c,cdemu->load_segment);
+ write_word(DS,SI+0x0e,cdemu->sector_count);
+ write_byte(DS,SI+0x10,cdemu->vdevice.cylinders);
+ write_byte(DS,SI+0x11,cdemu->vdevice.spt);
+ write_byte(DS,SI+0x12,cdemu->vdevice.heads);
+
+ // If we have to terminate emulation
+ if(GET_AL() == 0x00) {
+ // FIXME ElTorito Various. Should be handled accordingly to spec
+ cdemu->active = 0; // bye bye
+ }
+
+ goto int13_success;
+ break;
+
+ default:
+ BX_INFO("%s: unsupported AH=%02x\n", __func__, GET_AH());
+ goto int13_fail;
+ break;
+ }
+
+int13_fail:
+ SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
+ SET_DISK_RET_STATUS(GET_AH());
+ SET_CF(); // error occurred
+ return;
+
+int13_success:
+ SET_AH(0x00); // no error
+ SET_DISK_RET_STATUS(0x00);
+ CLEAR_CF(); // no error
+ return;
+}
+
+// ---------------------------------------------------------------------------
+// End of int13 for eltorito functions
+// ---------------------------------------------------------------------------
+
+/* Utility routine to check if a device is a CD-ROM. */
+/// @todo this function is kinda useless as the ATAPI type check is obsolete.
+static uint16_t device_is_cdrom(uint8_t device)
+{
+ bio_dsk_t __far *bios_dsk;
+
+ bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
+
+ if (device >= BX_MAX_STORAGE_DEVICES)
+ return 0;
+
+// if (bios_dsk->devices[device].type != DSK_TYPE_ATAPI)
+// return 0;
+
+ if (bios_dsk->devices[device].device != DSK_DEVICE_CDROM)
+ return 0;
+
+ return 1;
+}
+
+// ---------------------------------------------------------------------------
+// End of ATA/ATAPI generic functions
+// ---------------------------------------------------------------------------
+static const char isotag[]="CD001";
+static const char eltorito[]="EL TORITO SPECIFICATION";
+//
+// Returns ah: emulated drive, al: error code
+//
+uint16_t cdrom_boot(void)
+{
+ /// @todo a macro or a function for getting the EBDA segment
+ uint16_t ebda_seg=read_word(0x0040,0x000E);
+ uint8_t buffer[2048];
+ cdb_atapi atapicmd;
+ uint32_t lba;
+ uint16_t boot_segment, nbsectors, i, error;
+ uint8_t device;
+ uint8_t read_try;
+ cdemu_t __far *cdemu;
+ bio_dsk_t __far *bios_dsk;
+
+ cdemu = ebda_seg :> &EbdaData->cdemu;
+ bios_dsk = ebda_seg :> &EbdaData->bdisk;
+
+ /* Find the first CD-ROM. */
+ for (device = 0; device < BX_MAX_STORAGE_DEVICES; ++device) {
+ if (device_is_cdrom(device))
+ break;
+ }
+
+ /* Fail if not found. */
+ if (device >= BX_MAX_STORAGE_DEVICES)
+ return 2;
+
+ /* Read the Boot Record Volume Descriptor (BRVD). */
+ _fmemset(&atapicmd, 0, sizeof(atapicmd));
+ atapicmd.command = 0x28; // READ 10 command
+ atapicmd.lba = swap_32(0x11);
+ atapicmd.nsect = swap_16(1);
+
+ bios_dsk->drqp.nsect = 1;
+ bios_dsk->drqp.sect_sz = 2048;
+
+ for (read_try = 0; read_try <= 4; ++read_try)
+ {
+ error = pktacc[bios_dsk->devices[device].type](device, 12, (char __far *)&atapicmd, 0, 2048L, ATA_DATA_IN, &buffer);
+ if (!error)
+ break;
+ }
+ if (error)
+ return 3;
+
+ /* Check for a valid BRVD. */
+ if (buffer[0] != 0)
+ return 4;
+ /// @todo what's wrong with memcmp()?
+ for (i = 0; i < 5; ++i) {
+ if (buffer[1+i] != isotag[i])
+ return 5;
+ }
+ for (i = 0; i < 23; ++i)
+ if (buffer[7+i] != eltorito[i])
+ return 6;
+
+ // ok, now we calculate the Boot catalog address
+ lba = *((uint32_t *)&buffer[0x47]);
+ BX_DEBUG_ELTORITO("BRVD at LBA %lx\n", lba);
+
+ /* Now we read the Boot Catalog. */
+ atapicmd.command = 0x28; // READ 10 command
+ atapicmd.lba = swap_32(lba);
+ atapicmd.nsect = swap_16(1);
+
+#if 0 // Not necessary as long as previous values are reused
+ bios_dsk->drqp.nsect = 1;
+ bios_dsk->drqp.sect_sz = 512;
+#endif
+
+ error = pktacc[bios_dsk->devices[device].type](device, 12, (char __far *)&atapicmd, 0, 2048L, ATA_DATA_IN, &buffer);
+ if (error != 0)
+ return 7;
+
+ /// @todo Define a struct for the Boot Catalog, the hardcoded offsets are so dumb...
+
+ /* Check if the Boot Catalog looks valid. */
+ if (buffer[0x00] != 0x01)
+ return 8; // Header
+ if (buffer[0x01] != 0x00)
+ return 9; // Platform
+ if (buffer[0x1E] != 0x55)
+ return 10; // key 1
+ if (buffer[0x1F] != 0xAA)
+ return 10; // key 2
+
+ // Initial/Default Entry
+ if (buffer[0x20] != 0x88)
+ return 11; // Bootable
+
+ cdemu->media = buffer[0x21];
+ if (buffer[0x21] == 0) {
+ // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0.
+ // Win2000 cd boot needs to know it booted from cd
+ cdemu->emulated_drive = 0xE0;
+ }
+ else if (buffer[0x21] < 4)
+ cdemu->emulated_drive = 0x00;
+ else
+ cdemu->emulated_drive = 0x80;
+
+ cdemu->controller_index = device / 2;
+ cdemu->device_spec = device % 2;
+
+ boot_segment = *((uint16_t *)&buffer[0x22]);
+ if (boot_segment == 0)
+ boot_segment = 0x07C0;
+
+ cdemu->load_segment = boot_segment;
+ cdemu->buffer_segment = 0x0000;
+
+ nbsectors = ((uint16_t *)buffer)[0x26 / 2];
+ cdemu->sector_count = nbsectors;
+
+ /* Sanity check the sector count. In incorrectly mastered CDs, it might
+ * be zero. If it's more than 512K, reject it as well.
+ */
+ if (nbsectors == 0 || nbsectors > 1024)
+ return 12;
+
+ lba = *((uint32_t *)&buffer[0x28]);
+ cdemu->ilba = lba;
+
+ BX_DEBUG_ELTORITO("Emulate drive %02x, type %02x, LBA %lu\n",
+ cdemu->emulated_drive, cdemu->media, cdemu->ilba);
+
+ /* Read the disk image's boot sector into memory. */
+ atapicmd.command = 0x28; // READ 10 command
+ atapicmd.lba = swap_32(lba);
+ atapicmd.nsect = swap_16(1 + (nbsectors - 1) / 4);
+
+ bios_dsk->drqp.nsect = 1 + (nbsectors - 1) / 4;
+ bios_dsk->drqp.sect_sz = 512;
+
+ bios_dsk->drqp.skip_a = (2048 - nbsectors * 512) % 2048;
+
+ error = pktacc[bios_dsk->devices[device].type](device, 12, (char __far *)&atapicmd, 0, nbsectors*512L, ATA_DATA_IN, MK_FP(boot_segment,0));
+
+ bios_dsk->drqp.skip_a = 0;
+
+ if (error != 0)
+ return 13;
+
+ BX_DEBUG_ELTORITO("Emulate drive %02x, type %02x, LBA %lu\n",
+ cdemu->emulated_drive, cdemu->media, cdemu->ilba);
+ /* Set up emulated drive geometry based on the media type. */
+ switch (cdemu->media) {
+ case 0x01: /* 1.2M floppy */
+ cdemu->vdevice.spt = 15;
+ cdemu->vdevice.cylinders = 80;
+ cdemu->vdevice.heads = 2;
+ break;
+ case 0x02: /* 1.44M floppy */
+ cdemu->vdevice.spt = 18;
+ cdemu->vdevice.cylinders = 80;
+ cdemu->vdevice.heads = 2;
+ break;
+ case 0x03: /* 2.88M floppy */
+ cdemu->vdevice.spt = 36;
+ cdemu->vdevice.cylinders = 80;
+ cdemu->vdevice.heads = 2;
+ break;
+ case 0x04: /* Hard disk */
+ cdemu->vdevice.spt = read_byte(boot_segment,446+6)&0x3f;
+ cdemu->vdevice.cylinders = ((read_byte(boot_segment,446+6)&~0x3f)<<2) + read_byte(boot_segment,446+7) + 1;
+ cdemu->vdevice.heads = read_byte(boot_segment,446+5) + 1;
+ break;
+ }
+ BX_DEBUG_ELTORITO("VCHS=%u/%u/%u\n", cdemu->vdevice.cylinders,
+ cdemu->vdevice.heads, cdemu->vdevice.spt);
+
+ if (cdemu->media != 0) {
+ /* Increase BIOS installed number of drives (floppy or fixed). */
+ if (cdemu->emulated_drive == 0x00)
+ write_byte(0x40,0x10,read_byte(0x40,0x10)|0x41);
+ else
+ write_byte(ebda_seg,(uint16_t)&EbdaData->bdisk.hdcount, read_byte(ebda_seg, (uint16_t)&EbdaData->bdisk.hdcount) + 1);
+ }
+
+ // everything is ok, so from now on, the emulation is active
+ if (cdemu->media != 0)
+ cdemu->active = 0x01;
+
+ // return the boot drive + no error
+ return (cdemu->emulated_drive*0x100)+0;
+}
+
+// ---------------------------------------------------------------------------
+// End of El-Torito boot functions
+// ---------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+// Start of int13 when emulating a device from the cd
+// ---------------------------------------------------------------------------
+
+void BIOSCALL int13_cdemu(disk_regs_t r)
+{
+ /// @todo a macro or a function for getting the EBDA segment
+ uint16_t ebda_seg=read_word(0x0040,0x000E);
+ uint8_t device, status;
+ uint16_t vheads, vspt, vcylinders;
+ uint16_t head, sector, cylinder, nbsectors;
+ uint32_t vlba, ilba, slba, elba;
+ uint16_t before, segment, offset;
+ cdb_atapi atapicmd;
+ cdemu_t __far *cdemu;
+ bio_dsk_t __far *bios_dsk;
+ int13ext_t __far *i13x;
+ uint32_t lba;
+ uint16_t count;
+
+ cdemu = ebda_seg :> &EbdaData->cdemu;
+ bios_dsk = ebda_seg :> &EbdaData->bdisk;
+
+ BX_DEBUG_INT13_ET("%s: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", __func__, AX, BX, CX, DX, ES);
+
+ /* at this point, we are emulating a floppy/harddisk */
+
+ // Recompute the device number
+ device = cdemu->controller_index * 2;
+ device += cdemu->device_spec;
+
+ SET_DISK_RET_STATUS(0x00);
+
+ /* basic checks : emulation should be active, dl should equal the emulated drive */
+ if (!cdemu->active || (cdemu->emulated_drive != GET_DL())) {
+ BX_INFO("%s: function %02x, emulation not active for DL= %02x\n", __func__, GET_AH(), GET_DL());
+ goto int13_fail;
+ }
+
+ switch (GET_AH()) {
+
+ case 0x00: /* disk controller reset */
+ if (pktacc[bios_dsk->devices[device].type])
+ {
+ status = softrst[bios_dsk->devices[device].type](device);
+ }
+ goto int13_success;
+ break;
+ // all those functions return SUCCESS
+ case 0x09: /* initialize drive parameters */
+ case 0x0c: /* seek to specified cylinder */
+ case 0x0d: /* alternate disk reset */ // FIXME ElTorito Various. should really reset ?
+ case 0x10: /* check drive ready */ // FIXME ElTorito Various. should check if ready ?
+ case 0x11: /* recalibrate */
+ case 0x14: /* controller internal diagnostic */
+ case 0x16: /* detect disk change */
+ goto int13_success;
+ break;
+
+ // all those functions return disk write-protected
+ case 0x03: /* write disk sectors */
+ case 0x05: /* format disk track */
+ SET_AH(0x03);
+ goto int13_fail_noah;
+ break;
+
+ case 0x01: /* read disk status */
+ status=read_byte(0x0040, 0x0074);
+ SET_AH(status);
+ SET_DISK_RET_STATUS(0);
+
+ /* set CF if error status read */
+ if (status)
+ goto int13_fail_nostatus;
+ else
+ goto int13_success_noah;
+ break;
+
+ case 0x02: // read disk sectors
+ case 0x04: // verify disk sectors
+ vspt = cdemu->vdevice.spt;
+ vcylinders = cdemu->vdevice.cylinders;
+ vheads = cdemu->vdevice.heads;
+ ilba = cdemu->ilba;
+
+ sector = GET_CL() & 0x003f;
+ cylinder = (GET_CL() & 0x00c0) << 2 | GET_CH();
+ head = GET_DH();
+ nbsectors = GET_AL();
+ segment = ES;
+ offset = BX;
+
+ BX_DEBUG_INT13_ET("%s: read to %04x:%04x @ VCHS %u/%u/%u (%u sectors)\n", __func__,
+ ES, BX, cylinder, head, sector, nbsectors);
+
+ // no sector to read ?
+ if(nbsectors==0)
+ goto int13_success;
+
+ // sanity checks sco openserver needs this!
+ if ((sector > vspt)
+ || (cylinder >= vcylinders)
+ || (head >= vheads)) {
+ goto int13_fail;
+ }
+
+ // After validating the input, verify does nothing
+ if (GET_AH() == 0x04)
+ goto int13_success;
+
+ segment = ES+(BX / 16);
+ offset = BX % 16;
+
+ // calculate the virtual lba inside the image
+ vlba=((((uint32_t)cylinder*(uint32_t)vheads)+(uint32_t)head)*(uint32_t)vspt)+((uint32_t)(sector-1));
+
+ // In advance so we don't lose the count
+ SET_AL(nbsectors);
+
+ // start lba on cd
+ slba = (uint32_t)vlba / 4;
+ before = (uint32_t)vlba % 4;
+
+ // end lba on cd
+ elba = (uint32_t)(vlba + nbsectors - 1) / 4;
+
+ _fmemset(&atapicmd, 0, sizeof(atapicmd));
+ atapicmd.command = 0x28; // READ 10 command
+ atapicmd.lba = swap_32(ilba + slba);
+ atapicmd.nsect = swap_16(elba - slba + 1);
+
+ bios_dsk->drqp.nsect = nbsectors;
+ bios_dsk->drqp.sect_sz = 512;
+
+ bios_dsk->drqp.skip_b = before * 512;
+ bios_dsk->drqp.skip_a = ((4 - nbsectors % 4 - before) * 512) % 2048;
+
+ status = pktacc[bios_dsk->devices[device].type](device, 12, (char __far *)&atapicmd, before*512, nbsectors*512L, ATA_DATA_IN, MK_FP(segment,offset));
+
+ bios_dsk->drqp.skip_b = 0;
+ bios_dsk->drqp.skip_a = 0;
+
+ if (status != 0) {
+ BX_INFO("%s: function %02x, error %02x !\n", __func__, GET_AH(), status);
+ SET_AH(0x02);
+ SET_AL(0);
+ goto int13_fail_noah;
+ }
+
+ goto int13_success;
+ break;
+
+ case 0x08: /* read disk drive parameters */
+ vspt = cdemu->vdevice.spt;
+ vcylinders = cdemu->vdevice.cylinders - 1;
+ vheads = cdemu->vdevice.heads - 1;
+
+ SET_AL( 0x00 );
+ SET_BL( 0x00 );
+ SET_CH( vcylinders & 0xff );
+ SET_CL((( vcylinders >> 2) & 0xc0) | ( vspt & 0x3f ));
+ SET_DH( vheads );
+ SET_DL( 0x02 ); // FIXME ElTorito Various. should send the real count of drives 1 or 2
+ // FIXME ElTorito Harddisk. should send the HD count
+
+ switch (cdemu->media) {
+ case 0x01: SET_BL( 0x02 ); break; /* 1.2 MB */
+ case 0x02: SET_BL( 0x04 ); break; /* 1.44 MB */
+ case 0x03: SET_BL( 0x05 ); break; /* 2.88 MB */
+ }
+
+ /* Only set the DPT pointer for emulated floppies. */
+ if (cdemu->media < 4) {
+ DI = (uint16_t)&diskette_param_table; /// @todo should this depend on emulated medium?
+ ES = 0xF000; /// @todo how to make this relocatable?
+ }
+ goto int13_success;
+ break;
+
+ case 0x15: /* read disk drive size */
+ // FIXME ElTorito Harddisk. What geometry to send ?
+ SET_AH(0x03);
+ goto int13_success_noah;
+ break;
+
+ case 0x41: // IBM/MS installation check
+ BX = 0xaa55; // install check
+ SET_AH(0x30); // EDD 2.1
+ CX = 0x0007; // ext disk access, removable and edd
+ goto int13_success_noah;
+ break;
+
+ case 0x42: // IBM/MS extended read
+ case 0x44: // IBM/MS verify sectors
+ case 0x47: // IBM/MS extended seek
+
+ /* Load the I13X struct pointer. */
+ i13x = MK_FP(DS, SI);
+
+ count = i13x->count;
+ segment = i13x->segment;
+ offset = i13x->offset;
+
+ // Can't use 64 bits lba
+ lba = i13x->lba2;
+ if (lba != 0L) {
+ BX_PANIC("%s: function %02x. Can't use 64bits lba\n", __func__, GET_AH());
+ goto int13_fail;
+ }
+
+ // Get 32 bits lba
+ lba = i13x->lba1;
+
+ // If verify or seek
+ if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
+ goto int13_success;
+
+ BX_DEBUG_INT13_ET("%s: read %u sectors @ LBA %lu to %04X:%04X\n",
+ __func__, count, lba, segment, offset);
+
+ nbsectors = count;
+ vlba = lba;
+ ilba = cdemu->ilba;
+
+ // start lba on cd
+ slba = (uint32_t)vlba / 4;
+ before = (uint32_t)vlba % 4;
+
+ // end lba on cd
+ elba = (uint32_t)(vlba + nbsectors - 1) / 4;
+
+ _fmemset(&atapicmd, 0, sizeof(atapicmd));
+ atapicmd.command = 0x28; // READ 10 command
+ atapicmd.lba = swap_32(ilba + slba);
+ atapicmd.nsect = swap_16(elba - slba + 1);
+
+ bios_dsk->drqp.skip_b = before * 512;
+ bios_dsk->drqp.skip_a = ((4 - nbsectors % 4 - before) * 512) % 2048;
+
+ status = pktacc[bios_dsk->devices[device].type](device, 12, (char __far *)&atapicmd, before*512, nbsectors*512L, ATA_DATA_IN, MK_FP(segment,offset));
+
+ bios_dsk->drqp.skip_b = 0;
+ bios_dsk->drqp.skip_a = 0;
+
+ count = (uint16_t)(bios_dsk->drqp.trsfbytes >> 9);
+ i13x->count = count;
+
+ if (status != 0) {
+ BX_INFO("%s: function %02x, status %02x !\n", __func__, GET_AH(), status);
+ SET_AH(0x0c);
+ goto int13_fail_noah;
+ }
+
+ goto int13_success;
+ break;
+
+ case 0x48: // IBM/MS get drive parameters
+ if (edd_fill_dpt(DS :> (dpt_t *)SI, bios_dsk, device))
+ goto int13_fail;
+ else
+ goto int13_success;
+ break;
+
+ // all those functions return unimplemented
+ case 0x0a: /* read disk sectors with ECC */
+ case 0x0b: /* write disk sectors with ECC */
+ case 0x18: /* set media type for format */
+ case 0x43: // IBM/MS extended write
+ case 0x45: // IBM/MS lock/unlock drive
+ case 0x46: // IBM/MS eject media
+ case 0x49: // IBM/MS extended media change
+ case 0x4e: // ? - set hardware configuration
+ case 0x50: // ? - send packet command
+ default:
+ BX_INFO("%s: function AH=%02x unsupported, returns fail\n", __func__, GET_AH());
+ goto int13_fail;
+ break;
+ }
+
+int13_fail:
+ SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
+int13_fail_noah:
+ SET_DISK_RET_STATUS(GET_AH());
+int13_fail_nostatus:
+ SET_CF(); // error occurred
+ return;
+
+int13_success:
+ SET_AH(0x00); // no error
+int13_success_noah:
+ SET_DISK_RET_STATUS(0x00);
+ CLEAR_CF(); // no error
+ return;
+}
+
+// ---------------------------------------------------------------------------
+// Start of int13 for cdrom
+// ---------------------------------------------------------------------------
+
+void BIOSCALL int13_cdrom(uint16_t EHBX, disk_regs_t r)
+{
+ uint16_t ebda_seg = read_word(0x0040,0x000E);
+ uint8_t device, status, locks;
+ cdb_atapi atapicmd;
+ uint32_t lba;
+ uint16_t count, segment, offset;
+ bio_dsk_t __far *bios_dsk;
+ int13ext_t __far *i13x;
+
+ bios_dsk = ebda_seg :> &EbdaData->bdisk;
+
+ BX_DEBUG_INT13_CD("%s: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", __func__, AX, BX, CX, DX, ES);
+
+ SET_DISK_RET_STATUS(0x00);
+
+ /* basic check : device should be 0xE0+ */
+ if( (GET_ELDL() < 0xE0) || (GET_ELDL() >= 0xE0 + BX_MAX_STORAGE_DEVICES) ) {
+ BX_DEBUG("%s: function %02x, ELDL out of range %02x\n", __func__, GET_AH(), GET_ELDL());
+ goto int13_fail;
+ }
+
+ // Get the ata channel
+ device = bios_dsk->cdidmap[GET_ELDL()-0xE0];
+
+ /* basic check : device has to be valid */
+ if (device >= BX_MAX_STORAGE_DEVICES) {
+ BX_DEBUG("%s: function %02x, unmapped device for ELDL=%02x\n", __func__, GET_AH(), GET_ELDL());
+ goto int13_fail;
+ }
+
+ switch (GET_AH()) {
+
+ // all those functions return SUCCESS
+ case 0x00: /* disk controller reset */
+ case 0x09: /* initialize drive parameters */
+ case 0x0c: /* seek to specified cylinder */
+ case 0x0d: /* alternate disk reset */
+ case 0x10: /* check drive ready */
+ case 0x11: /* recalibrate */
+ case 0x14: /* controller internal diagnostic */
+ case 0x16: /* detect disk change */
+ goto int13_success;
+ break;
+
+ // all those functions return disk write-protected
+ case 0x03: /* write disk sectors */
+ case 0x05: /* format disk track */
+ case 0x43: // IBM/MS extended write
+ SET_AH(0x03);
+ goto int13_fail_noah;
+ break;
+
+ case 0x01: /* read disk status */
+ status = read_byte(0x0040, 0x0074);
+ SET_AH(status);
+ SET_DISK_RET_STATUS(0);
+
+ /* set CF if error status read */
+ if (status)
+ goto int13_fail_nostatus;
+ else
+ goto int13_success_noah;
+ break;
+
+ case 0x15: /* read disk drive size */
+ SET_AH(0x02);
+ goto int13_fail_noah;
+ break;
+
+ case 0x41: // IBM/MS installation check
+ BX = 0xaa55; // install check
+ SET_AH(0x30); // EDD 2.1
+ CX = 0x0007; // ext disk access, removable and edd
+ goto int13_success_noah;
+ break;
+
+ case 0x42: // IBM/MS extended read
+ case 0x44: // IBM/MS verify sectors
+ case 0x47: // IBM/MS extended seek
+
+ /* Load the I13X struct pointer. */
+ i13x = MK_FP(DS, SI);
+
+ count = i13x->count;
+ segment = i13x->segment;
+ offset = i13x->offset;
+
+ // Can't use 64 bits lba
+ lba = i13x->lba2;
+ if (lba != 0L) {
+ BX_PANIC("%s: function %02x. Can't use 64bits lba\n", __func__, GET_AH());
+ goto int13_fail;
+ }
+
+ // Get 32 bits lba
+ lba = i13x->lba1;
+
+ // If verify or seek
+ if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
+ goto int13_success;
+
+ BX_DEBUG_INT13_CD("%s: read %u sectors @ LBA %lu to %04X:%04X\n",
+ __func__, count, lba, segment, offset);
+
+ _fmemset(&atapicmd, 0, sizeof(atapicmd));
+ atapicmd.command = 0x28; // READ 10 command
+ atapicmd.lba = swap_32(lba);
+ atapicmd.nsect = swap_16(count);
+
+ bios_dsk->drqp.nsect = count;
+ bios_dsk->drqp.sect_sz = 2048;
+
+ status = pktacc[bios_dsk->devices[device].type](device, 12, (char __far *)&atapicmd, 0, count*2048L, ATA_DATA_IN, MK_FP(segment,offset));
+
+ count = (uint16_t)(bios_dsk->drqp.trsfbytes >> 11);
+ i13x->count = count;
+
+ if (status != 0) {
+ BX_INFO("%s: function %02x, status %02x !\n", __func__, GET_AH(), status);
+ SET_AH(0x0c);
+ goto int13_fail_noah;
+ }
+
+ goto int13_success;
+ break;
+
+ case 0x45: // IBM/MS lock/unlock drive
+ if (GET_AL() > 2)
+ goto int13_fail;
+
+ locks = bios_dsk->devices[device].lock;
+
+ switch (GET_AL()) {
+ case 0 : // lock
+ if (locks == 0xff) {
+ SET_AH(0xb4);
+ SET_AL(1);
+ goto int13_fail_noah;
+ }
+ bios_dsk->devices[device].lock = ++locks;
+ SET_AL(1);
+ break;
+ case 1 : // unlock
+ if (locks == 0x00) {
+ SET_AH(0xb0);
+ SET_AL(0);
+ goto int13_fail_noah;
+ }
+ bios_dsk->devices[device].lock = --locks;
+ SET_AL(locks==0?0:1);
+ break;
+ case 2 : // status
+ SET_AL(locks==0?0:1);
+ break;
+ }
+ goto int13_success;
+ break;
+
+ case 0x46: // IBM/MS eject media
+ locks = bios_dsk->devices[device].lock;
+
+ if (locks != 0) {
+ SET_AH(0xb1); // media locked
+ goto int13_fail_noah;
+ }
+ // FIXME should handle 0x31 no media in device
+ // FIXME should handle 0xb5 valid request failed
+
+#if 0 /// @todo implement!
+ // Call removable media eject
+ ASM_START
+ push bp
+ mov bp, sp
+
+ mov ah, #0x52
+ int #0x15
+ mov _int13_cdrom.status + 2[bp], ah
+ jnc int13_cdrom_rme_end
+ mov _int13_cdrom.status, #1
+int13_cdrom_rme_end:
+ pop bp
+ ASM_END
+#endif
+
+ if (status != 0) {
+ SET_AH(0xb1); // media locked
+ goto int13_fail_noah;
+ }
+
+ goto int13_success;
+ break;
+
+ case 0x48: // IBM/MS get drive parameters
+ if (edd_fill_dpt(DS :> (dpt_t *)SI, bios_dsk, device))
+ goto int13_fail;
+ else
+ goto int13_success;
+ break;
+
+ case 0x49: // IBM/MS extended media change
+ // always send changed ??
+ SET_AH(06);
+ goto int13_fail_nostatus;
+ break;
+
+ case 0x4e: // // IBM/MS set hardware configuration
+ // DMA, prefetch, PIO maximum not supported
+ switch (GET_AL()) {
+ case 0x01:
+ case 0x03:
+ case 0x04:
+ case 0x06:
+ goto int13_success;
+ break;
+ default :
+ goto int13_fail;
+ }
+ break;
+
+ // all those functions return unimplemented
+ case 0x02: /* read sectors */
+ case 0x04: /* verify sectors */
+ case 0x08: /* read disk drive parameters */
+ case 0x0a: /* read disk sectors with ECC */
+ case 0x0b: /* write disk sectors with ECC */
+ case 0x18: /* set media type for format */
+ case 0x50: // ? - send packet command
+ default:
+ BX_INFO("%s: unsupported AH=%02x\n", __func__, GET_AH());
+ goto int13_fail;
+ break;
+ }
+
+int13_fail:
+ SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
+int13_fail_noah:
+ SET_DISK_RET_STATUS(GET_AH());
+int13_fail_nostatus:
+ SET_CF(); // error occurred
+ return;
+
+int13_success:
+ SET_AH(0x00); // no error
+int13_success_noah:
+ SET_DISK_RET_STATUS(0x00);
+ CLEAR_CF(); // no error
+ return;
+}
+
+// ---------------------------------------------------------------------------
+// End of int13 for cdrom
+// ---------------------------------------------------------------------------
+
diff --git a/src/VBox/Devices/PC/BIOS/floppy.c b/src/VBox/Devices/PC/BIOS/floppy.c
new file mode 100644
index 00000000..958db2e5
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/floppy.c
@@ -0,0 +1,1360 @@
+/* $Id: floppy.c $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+
+#include <stdint.h>
+#include "inlines.h"
+#include "biosint.h"
+
+extern uint16_t get_floppy_dpt(uint8_t drive_type);
+
+//////////////////////
+// FLOPPY functions //
+//////////////////////
+
+inline void set_diskette_ret_status(uint8_t value)
+{
+ write_byte(0x0040, 0x0041, value);
+}
+
+void set_diskette_current_cyl(uint8_t drive, uint8_t cyl)
+{
+ if (drive > 1)
+ BX_PANIC("set_diskette_current_cyl: drive > 1\n");
+ write_byte(0x0040, 0x0094+drive, cyl);
+}
+
+#if 1 //BX_SUPPORT_FLOPPY
+
+#if DEBUG_INT13_FL
+# define BX_DEBUG_INT13_FL(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define BX_DEBUG_INT13_FL(...)
+#endif
+
+#define BX_FLOPPY_ON_CNT 37 /* 2 seconds */
+
+extern int diskette_param_table; /* At a fixed location. */
+
+#ifndef VBOX_WITH_FLOPPY_IRQ_POLLING
+
+/**
+ * Wait for the 7th bit of 0040:003e to be set by int0e_handler.
+ * @returns first 7 bits of byte 0040:003e, interrupts disabled.
+ */
+uint8_t floppy_wait_for_interrupt(void)
+{
+ int_disable();
+ for (;;)
+ {
+ uint8_t val8 = read_byte(0x0040, 0x003e);
+ if (val8 & 0x80)
+ return val8 & ~0x7f;
+ int_enable_hlt_disable();
+ }
+}
+
+/**
+ * Wait for the 7th bit of 0040:003e to be set by int0e_handler or 0040:0040 to
+ * be cleared by the timer, clearing the interrupt flag on success.
+ *
+ * @returns 0 on timeout with interrupts enabled.
+ * All 8 bits at 0040:003e on interrupt with interrupts disabled (i.e.
+ * non-zero), after first clearing the 7th bit at 0040:003e.
+ */
+uint8_t floppy_wait_for_interrupt_or_timeout(void)
+{
+ int_disable();
+ for (;;)
+ {
+ uint8_t val8 = read_byte(0x0040, 0x0040);
+ if (val8 == 0) {
+ int_enable();
+ return 0;
+ }
+
+ val8 = read_byte(0x0040, 0x003e);
+ if (val8 & 0x80) {
+ write_byte(0x0040, 0x003e, val8 & 0x7f);
+ return val8;
+ }
+ int_enable_hlt_disable();
+ }
+}
+
+#endif /* !VBOX_WITH_FLOPPY_IRQ_POLLING */
+
+void floppy_reset_controller(uint16_t drive)
+{
+ uint8_t val8;
+
+ // Reset controller
+ val8 = inb(0x03f2);
+ outb(0x03f2, val8 & ~0x04);
+ outb(0x03f2, val8 | 0x04);
+
+ // Wait for controller to come out of reset
+ do {
+ val8 = inb(0x3f4);
+ } while ( (val8 & 0xc0) != 0x80 );
+
+ // Mark media in drive as unknown
+ val8 = read_byte(0x0040, 0x0090 + drive);
+ val8 &= ~0x10;
+ write_byte(0x0040, 0x90 + drive, val8);
+
+}
+
+void floppy_prepare_controller(uint16_t drive)
+{
+ uint8_t val8, dor, prev_reset;
+
+ // set 40:3e bit 7 to 0
+ val8 = read_byte(0x0040, 0x003e);
+ val8 &= 0x7f;
+ write_byte(0x0040, 0x003e, val8);
+
+ // turn on motor of selected drive, DMA & int enabled, normal operation
+ prev_reset = inb(0x03f2) & 0x04;
+ if (drive)
+ dor = 0x20;
+ else
+ dor = 0x10;
+ dor |= 0x0c;
+ dor |= drive;
+ outb(0x03f2, dor);
+
+ // reset the disk motor timeout value of INT 08
+ write_byte(0x0040,0x0040, BX_FLOPPY_ON_CNT);
+
+ // program data rate
+ val8 = read_byte(0x0040, 0x008b);
+ val8 >>= 6;
+ outb(0x03f7, val8);
+
+ // wait for drive readiness
+ do {
+ val8 = inb(0x3f4);
+ } while ( (val8 & 0xc0) != 0x80 );
+
+ if (prev_reset == 0) {
+#ifdef VBOX_WITH_FLOPPY_IRQ_POLLING
+ // turn on interrupts
+ int_enable();
+ // wait on 40:3e bit 7 to become 1
+ do {
+ val8 = read_byte(0x0040, 0x003e);
+ } while ( (val8 & 0x80) == 0 );
+ val8 &= 0x7f;
+ int_disable();
+#else
+ val8 = floppy_wait_for_interrupt(); /* (7th bit cleared in ret val) */
+#endif
+ write_byte(0x0040, 0x003e, val8);
+ }
+}
+
+bx_bool floppy_media_known(uint16_t drive)
+{
+ uint8_t val8;
+ uint16_t media_state_offset;
+
+ val8 = read_byte(0x0040, 0x003e); // diskette recal status
+ if (drive)
+ val8 >>= 1;
+ val8 &= 0x01;
+ if (val8 == 0)
+ return 0;
+
+ media_state_offset = 0x0090;
+ if (drive)
+ media_state_offset += 1;
+
+ val8 = read_byte(0x0040, media_state_offset);
+ val8 = (val8 >> 4) & 0x01;
+ if (val8 == 0)
+ return 0;
+
+ // checks passed, return KNOWN
+ return 1;
+}
+
+bx_bool floppy_read_id(uint16_t drive)
+{
+#ifdef VBOX_WITH_FLOPPY_IRQ_POLLING
+ uint8_t val8;
+#endif
+ int i;
+
+ floppy_prepare_controller(drive);
+
+ // send Read ID command (2 bytes) to controller
+ outb(0x03f5, 0x4a); // 4a: Read ID (MFM)
+ outb(0x03f5, drive); // 0=drive0, 1=drive1, head always 0
+
+#ifdef VBOX_WITH_FLOPPY_IRQ_POLLING
+ // turn on interrupts
+ int_enable();
+
+ // wait on 40:3e bit 7 to become 1
+ do {
+ val8 = (read_byte(0x0040, 0x003e) & 0x80);
+ } while ( val8 == 0 );
+
+ val8 = 0; // separate asm from while() loop
+ // turn off interrupts
+ int_disable();
+#else
+ floppy_wait_for_interrupt();
+#endif
+
+ // read 7 return status bytes from controller
+ for (i = 0; i < 7; ++i)
+ write_byte(0x0040, 0x0042 + i, inb(0x3f5));
+
+ if ((read_byte(0x0040, 0x0042 + 0) & 0xc0) != 0)
+ return 0;
+ else
+ return 1;
+}
+
+bx_bool floppy_drive_recal(uint16_t drive)
+{
+ uint8_t val8;
+ uint16_t curr_cyl_offset;
+
+ floppy_prepare_controller(drive);
+
+ // send Recalibrate command (2 bytes) to controller
+ outb(0x03f5, 0x07); // 07: Recalibrate
+ outb(0x03f5, drive); // 0=drive0, 1=drive1
+
+#ifdef VBOX_WITH_FLOPPY_IRQ_POLLING
+ // turn on interrupts
+ int_enable();
+
+ // wait on 40:3e bit 7 to become 1
+ do {
+ val8 = (read_byte(0x0040, 0x003e) & 0x80);
+ } while ( val8 == 0 );
+
+ val8 = 0; // separate asm from while() loop
+ // turn off interrupts
+ int_disable();
+
+ // set 40:3e bit 7 to 0, and calibrated bit
+ val8 = read_byte(0x0040, 0x003e);
+ val8 &= 0x7f;
+#else
+ val8 = floppy_wait_for_interrupt(); /* (7th bit cleared in ret val) */
+
+ // set 40:3e bit 7 to 0, and calibrated bit
+#endif
+ if (drive) {
+ val8 |= 0x02; // Drive 1 calibrated
+ curr_cyl_offset = 0x0095;
+ } else {
+ val8 |= 0x01; // Drive 0 calibrated
+ curr_cyl_offset = 0x0094;
+ }
+ write_byte(0x0040, 0x003e, val8);
+ write_byte(0x0040, curr_cyl_offset, 0); // current cylinder is 0
+
+ return 1;
+}
+
+
+bx_bool floppy_media_sense(uint16_t drive)
+{
+ bx_bool retval;
+ uint16_t media_state_offset;
+ uint8_t drive_type, config_data, media_state;
+
+ if (floppy_drive_recal(drive) == 0)
+ return 0;
+
+ // Try the diskette data rates in the following order:
+ // 1 Mbps -> 500 Kbps -> 300 Kbps -> 250 Kbps
+ // The 1 Mbps rate is only tried for 2.88M drives.
+
+ // ** config_data **
+ // Bitfields for diskette media control:
+ // Bit(s) Description (Table M0028)
+ // 7-6 last data rate set by controller
+ // 00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps
+ // 5-4 last diskette drive step rate selected
+ // 00=0Ch, 01=0Dh, 10=0Eh, 11=0Ah
+ // 3-2 {data rate at start of operation}
+ // 1-0 reserved
+
+ // ** media_state **
+ // Bitfields for diskette drive media state:
+ // Bit(s) Description (Table M0030)
+ // 7-6 data rate
+ // 00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps
+ // 5 double stepping required (e.g. 360kB in 1.2MB)
+ // 4 media type established
+ // 3 drive capable of supporting 4MB media
+ // 2-0 on exit from BIOS, contains
+ // 000 trying 360kB in 360kB
+ // 001 trying 360kB in 1.2MB
+ // 010 trying 1.2MB in 1.2MB
+ // 011 360kB in 360kB established
+ // 100 360kB in 1.2MB established
+ // 101 1.2MB in 1.2MB established
+ // 110 reserved
+ // 111 all other formats/drives
+
+ /// @todo break out drive type determination
+ drive_type = inb_cmos(0x10);
+ if (drive == 0)
+ drive_type >>= 4;
+ else
+ drive_type &= 0x0f;
+ if ( drive_type == 1 ) {
+ // 360K 5.25" drive
+ config_data = 0x00; // 0000 0000
+ media_state = 0x15; // 0001 0101
+ retval = 1;
+ }
+ else if ( drive_type == 2 ) {
+ // 1.2 MB 5.25" drive
+ config_data = 0x00; // 0000 0000
+ media_state = 0x35; // 0011 0101 // need double stepping??? (bit 5)
+ retval = 1;
+ }
+ else if ( drive_type == 3 ) {
+ // 720K 3.5" drive
+ config_data = 0x00; // 0000 0000 ???
+ media_state = 0x17; // 0001 0111
+ retval = 1;
+ }
+ else if ( drive_type == 4 ) {
+ // 1.44 MB 3.5" drive
+ config_data = 0x00; // 0000 0000
+ media_state = 0x17; // 0001 0111
+ retval = 1;
+ }
+ else if ( drive_type == 5 ) {
+ // 2.88 MB 3.5" drive
+ config_data = 0xCC; // 1100 1100
+ media_state = 0xD7; // 1101 0111
+ retval = 1;
+ }
+ // Extended floppy size uses special cmos setting
+ else if ( drive_type == 14 || drive_type == 15 ) {
+ // 15.6 MB 3.5" (fake) || 63.5 MB 3.5" (fake) - report same as 2.88 MB.
+ config_data = 0xCC; // 1100 1100
+ media_state = 0xD7; // 1101 0111
+ retval = 1;
+ }
+ else {
+ // not recognized
+ config_data = 0x00; // 0000 0000
+ media_state = 0x00; // 0000 0000
+ retval = 0;
+ }
+
+ write_byte(0x0040, 0x008B, config_data);
+ while (!floppy_read_id(drive)) {
+ if ((config_data & 0xC0) == 0x80) {
+ // If even 250 Kbps failed, we can't do much
+ break;
+ }
+ switch (config_data & 0xC0) {
+ case 0xC0: // 1 Mbps
+ config_data = config_data & 0x3F | 0x00;
+ break;
+ case 0x00: // 500 Kbps
+ config_data = config_data & 0x3F | 0x40;
+ break;
+ case 0x40: // 300 Kbps
+ config_data = config_data & 0x3F | 0x80;
+ break;
+ }
+ write_byte(0x0040, 0x008B, config_data);
+ }
+
+ if (drive == 0)
+ media_state_offset = 0x0090;
+ else
+ media_state_offset = 0x0091;
+ write_byte(0x0040, 0x008B, config_data);
+ write_byte(0x0040, media_state_offset, media_state);
+
+ return retval;
+}
+
+
+bx_bool floppy_drive_exists(uint16_t drive)
+{
+ uint8_t drive_type;
+
+ // check CMOS to see if drive exists
+ /// @todo break out drive type determination
+ drive_type = inb_cmos(0x10);
+ if (drive == 0)
+ drive_type >>= 4;
+ else
+ drive_type &= 0x0f;
+ return drive_type != 0;
+}
+
+/// @todo put in a header
+#define AX r.gr.u.r16.ax
+#define BX r.gr.u.r16.bx
+#define CX r.gr.u.r16.cx
+#define DX r.gr.u.r16.dx
+#define SI r.gr.u.r16.si // not used
+#define DI r.gr.u.r16.di
+#define BP r.gr.u.r16.bp // not used
+#define ELDX r.gr.u.r16.sp
+#define DS r.ds // not used
+#define ES r.es
+#define FLAGS r.ra.flags.u.r16.flags
+
+void BIOSCALL int13_diskette_function(disk_regs_t r)
+{
+ uint8_t drive, num_sectors, track, sector, head;
+ uint16_t base_address, base_count, base_es;
+ uint8_t page, mode_register, val8, media_state;
+ uint8_t drive_type, num_floppies;
+ uint16_t last_addr;
+ int i;
+
+ BX_DEBUG_INT13_FL("%s: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", __func__, AX, BX, CX, DX, ES);
+
+ SET_IF(); /* INT 13h always returns with interrupts enabled. */
+
+ switch ( GET_AH() ) {
+ case 0x00: // diskette controller reset
+ BX_DEBUG_INT13_FL("floppy f00\n");
+ drive = GET_ELDL();
+ if (drive > 1) {
+ SET_AH(1); // invalid param
+ set_diskette_ret_status(1);
+ SET_CF();
+ return;
+ }
+ /// @todo break out drive type determination
+ drive_type = inb_cmos(0x10);
+ if (drive == 0)
+ drive_type >>= 4;
+ else
+ drive_type &= 0x0f;
+ if (drive_type == 0) {
+ SET_AH(0x80); // drive not responding
+ set_diskette_ret_status(0x80);
+ SET_CF();
+ return;
+ }
+
+ // force re-calibration etc.
+ write_byte(0x0040, 0x003e, 0);
+
+ SET_AH(0);
+ set_diskette_ret_status(0);
+ CLEAR_CF(); // successful
+ set_diskette_current_cyl(drive, 0); // current cylinder
+ return;
+
+ case 0x01: // Read Diskette Status
+ CLEAR_CF();
+ val8 = read_byte(0x0000, 0x0441);
+ SET_AH(val8);
+ if (val8) {
+ SET_CF();
+ }
+ return;
+
+ case 0x02: // Read Diskette Sectors
+ case 0x03: // Write Diskette Sectors
+ case 0x04: // Verify Diskette Sectors
+ num_sectors = GET_AL();
+ track = GET_CH();
+ sector = GET_CL();
+ head = GET_DH();
+ drive = GET_ELDL();
+
+ if ( (drive > 1) || (head > 1) ||
+ (num_sectors == 0) || (num_sectors > 72) ) {
+ BX_INFO("%s: drive>1 || head>1 ...\n", __func__);
+ SET_AH(1);
+ set_diskette_ret_status(1);
+ SET_AL(0); // no sectors read
+ SET_CF(); // error occurred
+ return;
+ }
+
+ // see if drive exists
+ if (floppy_drive_exists(drive) == 0) {
+ BX_DEBUG_INT13_FL("failed (not ready)\n");
+ SET_AH(0x80); // not responding
+ set_diskette_ret_status(0x80);
+ SET_AL(0); // no sectors read
+ SET_CF(); // error occurred
+ return;
+ }
+
+ // see if media in drive, and type is known
+ if (floppy_media_known(drive) == 0) {
+ if (floppy_media_sense(drive) == 0) {
+ BX_DEBUG_INT13_FL("media not found\n");
+ SET_AH(0x0C); // Media type not found
+ set_diskette_ret_status(0x0C);
+ SET_AL(0); // no sectors read
+ SET_CF(); // error occurred
+ return;
+ }
+ }
+
+ if (GET_AH() == 0x02) {
+ // Read Diskette Sectors
+
+ //-----------------------------------
+ // set up DMA controller for transfer
+ //-----------------------------------
+
+ // es:bx = pointer to where to place information from diskette
+ // port 04: DMA-1 base and current address, channel 2
+ // port 05: DMA-1 base and current count, channel 2
+ /// @todo merge/factor out pointer normalization
+ page = (ES >> 12); // upper 4 bits
+ base_es = (ES << 4); // lower 16bits contributed by ES
+ base_address = base_es + BX; // lower 16 bits of address
+ // contributed by ES:BX
+ if ( base_address < base_es ) {
+ // in case of carry, adjust page by 1
+ page++;
+ }
+ base_count = (num_sectors * 512) - 1;
+
+ // check for 64K boundary overrun
+ last_addr = base_address + base_count;
+ if (last_addr < base_address) {
+ SET_AH(0x09);
+ set_diskette_ret_status(0x09);
+ SET_AL(0); // no sectors read
+ SET_CF(); // error occurred
+ return;
+ }
+
+ BX_DEBUG_INT13_FL("masking DMA-1 c2\n");
+ outb(0x000a, 0x06);
+
+ BX_DEBUG_INT13_FL("clear flip-flop\n");
+ outb(0x000c, 0x00); // clear flip-flop
+ outb(0x0004, base_address);
+ outb(0x0004, base_address>>8);
+ BX_DEBUG_INT13_FL("clear flip-flop\n");
+ outb(0x000c, 0x00); // clear flip-flop
+ outb(0x0005, base_count);
+ outb(0x0005, base_count>>8);
+ BX_DEBUG_INT13_FL("xfer buf %x bytes at %x:%x\n",
+ base_count + 1, page, base_address);
+
+ // port 0b: DMA-1 Mode Register
+ mode_register = 0x46; // single mode, increment, autoinit disable,
+ // transfer type=write, channel 2
+ BX_DEBUG_INT13_FL("setting mode register\n");
+ outb(0x000b, mode_register);
+
+ BX_DEBUG_INT13_FL("setting page register\n");
+ // port 81: DMA-1 Page Register, channel 2
+ outb(0x0081, page);
+
+ BX_DEBUG_INT13_FL("unmasking DMA-1 c2\n");
+ outb(0x000a, 0x02); // unmask channel 2
+
+ //--------------------------------------
+ // set up floppy controller for transfer
+ //--------------------------------------
+ floppy_prepare_controller(drive);
+
+ // send read-normal-data command (9 bytes) to controller
+ outb(0x03f5, 0xe6); // e6: read normal data
+ outb(0x03f5, (head << 2) | drive); // HD DR1 DR2
+ outb(0x03f5, track);
+ outb(0x03f5, head);
+ outb(0x03f5, sector);
+ outb(0x03f5, 2); // 512 byte sector size
+ outb(0x03f5, sector + num_sectors - 1); // last sector to read on track
+ outb(0x03f5, 0); // Gap length
+ outb(0x03f5, 0xff); // Gap length
+ BX_DEBUG_INT13_FL("read initiated\n");
+
+#ifdef VBOX_WITH_FLOPPY_IRQ_POLLING
+ // turn on interrupts
+ int_enable();
+
+ // wait on 40:3e bit 7 to become 1 or timeout (latter isn't armed so it won't happen)
+ do {
+ val8 = read_byte(0x0040, 0x0040);
+ if (val8 == 0) {
+ BX_DEBUG_INT13_FL("failed (not ready)\n");
+ floppy_reset_controller(drive);
+ SET_AH(0x80); // drive not ready (timeout)
+ set_diskette_ret_status(0x80);
+ SET_AL(0); // no sectors read
+ SET_CF(); // error occurred
+ return;
+ }
+ val8 = (read_byte(0x0040, 0x003e) & 0x80);
+ } while ( val8 == 0 );
+
+ val8 = 0; // separate asm from while() loop
+ // turn off interrupts
+ int_disable();
+
+ // set 40:3e bit 7 to 0
+ val8 = read_byte(0x0040, 0x003e);
+ val8 &= 0x7f;
+ write_byte(0x0040, 0x003e, val8);
+
+#else
+ val8 = floppy_wait_for_interrupt_or_timeout();
+ if (val8 == 0) { /* Note! Interrupts enabled in this branch. */
+ BX_DEBUG_INT13_FL("failed (not ready)\n");
+ floppy_reset_controller(drive);
+ SET_AH(0x80); // drive not ready (timeout)
+ set_diskette_ret_status(0x80);
+ SET_AL(0); // no sectors read
+ SET_CF(); // error occurred
+ return;
+ }
+#endif
+
+ // check port 3f4 for accessibility to status bytes
+ val8 = inb(0x3f4);
+ if ( (val8 & 0xc0) != 0xc0 )
+ BX_PANIC("%s: ctrl not ready\n", __func__);
+
+ // read 7 return status bytes from controller and store in BDA
+ for (i = 0; i < 7; ++i)
+ write_byte(0x0040, 0x0042 + i, inb(0x3f5));
+
+ if ((read_byte(0x0040, 0x0042 + 0) & 0xc0) != 0) {
+ BX_DEBUG_INT13_FL("failed (FDC failure)\n");
+ floppy_reset_controller(drive);
+ SET_AH(0x20);
+ set_diskette_ret_status(0x20);
+ SET_AL(0); // no sectors read
+ SET_CF(); // error occurred
+ return;
+ }
+
+#ifdef DMA_WORKAROUND
+ rep_movsw(ES :> BX, ES :> BX, num_sectors * 512 / 2);
+#endif
+ BX_DEBUG_INT13_FL("success!\n");
+ // ??? should track be new val from return_status[3] ?
+ set_diskette_current_cyl(drive, track);
+ // AL = number of sectors read (same value as passed)
+ SET_AH(0x00); // success
+ CLEAR_CF(); // success
+ return;
+ } else if (GET_AH() == 0x03) {
+ // Write Diskette Sectors
+
+ //-----------------------------------
+ // set up DMA controller for transfer
+ //-----------------------------------
+
+ // es:bx = pointer to where to place information from diskette
+ // port 04: DMA-1 base and current address, channel 2
+ // port 05: DMA-1 base and current count, channel 2
+ /// @todo merge/factor out pointer normalization
+ page = (ES >> 12); // upper 4 bits
+ base_es = (ES << 4); // lower 16bits contributed by ES
+ base_address = base_es + BX; // lower 16 bits of address
+ // contributed by ES:BX
+ if ( base_address < base_es ) {
+ // in case of carry, adjust page by 1
+ page++;
+ }
+ base_count = (num_sectors * 512) - 1;
+
+ // check for 64K boundary overrun
+ last_addr = base_address + base_count;
+ if (last_addr < base_address) {
+ SET_AH(0x09);
+ set_diskette_ret_status(0x09);
+ SET_AL(0); // no sectors read
+ SET_CF(); // error occurred
+ return;
+ }
+
+ BX_DEBUG_INT13_FL("masking DMA-1 c2\n");
+ outb(0x000a, 0x06);
+
+ outb(0x000c, 0x00); // clear flip-flop
+ outb(0x0004, base_address);
+ outb(0x0004, base_address>>8);
+ outb(0x000c, 0x00); // clear flip-flop
+ outb(0x0005, base_count);
+ outb(0x0005, base_count>>8);
+ BX_DEBUG_INT13_FL("xfer buf %x bytes at %x:%x\n",
+ base_count, page, base_address);
+
+ // port 0b: DMA-1 Mode Register
+ mode_register = 0x4a; // single mode, increment, autoinit disable,
+ // transfer type=read, channel 2
+ outb(0x000b, mode_register);
+
+ // port 81: DMA-1 Page Register, channel 2
+ outb(0x0081, page);
+
+ BX_DEBUG_INT13_FL("unmasking DMA-1 c2\n");
+ outb(0x000a, 0x02);
+
+ //--------------------------------------
+ // set up floppy controller for transfer
+ //--------------------------------------
+ floppy_prepare_controller(drive);
+
+ // send write-normal-data command (9 bytes) to controller
+ outb(0x03f5, 0xc5); // c5: write normal data
+ outb(0x03f5, (head << 2) | drive); // HD DR1 DR2
+ outb(0x03f5, track);
+ outb(0x03f5, head);
+ outb(0x03f5, sector);
+ outb(0x03f5, 2); // 512 byte sector size
+ outb(0x03f5, sector + num_sectors - 1); // last sector to write on track
+ outb(0x03f5, 0); // Gap length
+ outb(0x03f5, 0xff); // Gap length
+
+#ifdef VBOX_WITH_FLOPPY_IRQ_POLLING
+ // turn on interrupts
+ int_enable();
+
+ // wait on 40:3e bit 7 to become 1
+ do {
+ val8 = read_byte(0x0040, 0x0040);
+ if (val8 == 0) {
+ floppy_reset_controller(drive);
+ SET_AH(0x80); // drive not ready (timeout)
+ set_diskette_ret_status(0x80);
+ SET_AL(0); // no sectors written
+ SET_CF(); // error occurred
+ return;
+ }
+ val8 = (read_byte(0x0040, 0x003e) & 0x80);
+ } while ( val8 == 0 );
+
+ val8 = 0; // separate asm from while() loop @todo: why??
+ // turn off interrupts
+ int_disable();
+
+ // set 40:3e bit 7 to 0
+ val8 = read_byte(0x0040, 0x003e);
+ val8 &= 0x7f;
+ write_byte(0x0040, 0x003e, val8);
+#else
+ val8 = floppy_wait_for_interrupt_or_timeout();
+ if (val8 == 0) { /* Note! Interrupts enabled in this branch. */
+ floppy_reset_controller(drive);
+ SET_AH(0x80); // drive not ready (timeout)
+ set_diskette_ret_status(0x80);
+ SET_AL(0); // no sectors written
+ SET_CF(); // error occurred
+ return;
+ }
+#endif
+
+ // check port 3f4 for accessibility to status bytes
+ val8 = inb(0x3f4);
+ if ( (val8 & 0xc0) != 0xc0 )
+ BX_PANIC("%s: ctrl not ready\n", __func__);
+
+ // read 7 return status bytes from controller and store in BDA
+ for (i = 0; i < 7; ++i)
+ write_byte(0x0040, 0x0042 + i, inb(0x3f5));
+
+ if ((read_byte(0x0040, 0x0042 + 0) & 0xc0) != 0) {
+ if ((read_byte(0x0040, 0x0042 + 1) & 0x02) != 0) {
+ // diskette not writable.
+ // AH=status code=0x03 (tried to write on write-protected disk)
+ // AL=number of sectors written=0
+ AX = 0x0300;
+ } else {
+ // Some other problem occurred.
+ AX = 0x0100;
+ }
+ SET_CF();
+ return;
+ }
+
+ // ??? should track be new val from return_status[3] ?
+ set_diskette_current_cyl(drive, track);
+ // AL = number of sectors read (same value as passed)
+ SET_AH(0x00); // success
+ CLEAR_CF(); // success
+ return;
+ } else { // if (ah == 0x04)
+ // Verify Diskette Sectors
+
+ // ??? should track be new val from return_status[3] ?
+ set_diskette_current_cyl(drive, track);
+ // AL = number of sectors verified (same value as passed)
+ CLEAR_CF(); // success
+ SET_AH(0x00); // success
+ return;
+ }
+ break;
+
+ case 0x05: // format diskette track
+ BX_DEBUG_INT13_FL("floppy f05\n");
+
+ num_sectors = GET_AL();
+ track = GET_CH();
+ head = GET_DH();
+ drive = GET_ELDL();
+
+ if ((drive > 1) || (head > 1) || (track > 79) ||
+ (num_sectors == 0) || (num_sectors > 18)) {
+ SET_AH(1);
+ set_diskette_ret_status(1);
+ SET_CF(); // error occurred
+ }
+
+ // see if drive exists
+ if (floppy_drive_exists(drive) == 0) {
+ SET_AH(0x80); // drive not responding
+ set_diskette_ret_status(0x80);
+ SET_CF(); // error occurred
+ return;
+ }
+
+ // see if media in drive, and type is known
+ if (floppy_media_known(drive) == 0) {
+ if (floppy_media_sense(drive) == 0) {
+ SET_AH(0x0C); // Media type not found
+ set_diskette_ret_status(0x0C);
+ SET_AL(0); // no sectors read
+ SET_CF(); // error occurred
+ return;
+ }
+ }
+
+ // set up DMA controller for transfer
+ /// @todo merge/factor out pointer normalization
+ page = (ES >> 12); // upper 4 bits
+ base_es = (ES << 4); // lower 16bits contributed by ES
+ base_address = base_es + BX; // lower 16 bits of address
+ // contributed by ES:BX
+ if ( base_address < base_es ) {
+ // in case of carry, adjust page by 1
+ page++;
+ }
+ base_count = (num_sectors * 4) - 1;
+
+ // check for 64K boundary overrun
+ last_addr = base_address + base_count;
+ if (last_addr < base_address) {
+ SET_AH(0x09);
+ set_diskette_ret_status(0x09);
+ SET_AL(0); // no sectors read
+ SET_CF(); // error occurred
+ return;
+ }
+
+ outb(0x000a, 0x06);
+ outb(0x000c, 0x00); // clear flip-flop
+ outb(0x0004, base_address);
+ outb(0x0004, base_address>>8);
+ outb(0x000c, 0x00); // clear flip-flop
+ outb(0x0005, base_count);
+ outb(0x0005, base_count>>8);
+ mode_register = 0x4a; // single mode, increment, autoinit disable,
+ // transfer type=read, channel 2
+ outb(0x000b, mode_register);
+ // port 81: DMA-1 Page Register, channel 2
+ outb(0x0081, page);
+ outb(0x000a, 0x02);
+
+ // set up floppy controller for transfer
+ floppy_prepare_controller(drive);
+
+ // send seek command to controller
+ outb(0x03f5, 0x0f); // 0f: seek
+ outb(0x03f5, (head << 2) | drive); // HD DR1 DR2
+ outb(0x03f5, track);
+
+ // send format-track command (6 bytes) to controller
+ outb(0x03f5, 0x4d); // 4d: format track
+ outb(0x03f5, (head << 2) | drive); // HD DR1 DR2
+ outb(0x03f5, 2); // 512 byte sector size
+ outb(0x03f5, num_sectors); // number of sectors per track
+ outb(0x03f5, 0); // Gap length
+ outb(0x03f5, 0xf6); // Fill byte
+
+#ifdef VBOX_WITH_FLOPPY_IRQ_POLLING
+ // turn on interrupts
+ int_enable();
+
+ // wait on 40:3e bit 7 to become 1
+ do {
+ val8 = read_byte(0x0040, 0x0040);
+ if (val8 == 0) {
+ floppy_reset_controller(drive);
+ SET_AH(0x80); // drive not ready (timeout)
+ set_diskette_ret_status(0x80);
+ SET_CF(); // error occurred
+ return;
+ }
+ val8 = (read_byte(0x0040, 0x003e) & 0x80);
+ } while ( val8 == 0 );
+
+ val8 = 0; // separate asm from while() loop
+ // turn off interrupts
+ int_disable();
+
+ // set 40:3e bit 7 to 0
+ val8 = read_byte(0x0040, 0x003e);
+ val8 &= 0x7f;
+ write_byte(0x0040, 0x003e, val8);
+#else
+ val8 = floppy_wait_for_interrupt_or_timeout();
+ if (val8 == 0) { /* Note! Interrupts enabled in this branch. */
+ floppy_reset_controller(drive);
+ SET_AH(0x80); // drive not ready (timeout)
+ set_diskette_ret_status(0x80);
+ SET_CF(); // error occurred
+ return;
+ }
+#endif
+
+ // check port 3f4 for accessibility to status bytes
+ val8 = inb(0x3f4);
+ if ( (val8 & 0xc0) != 0xc0 )
+ BX_PANIC("%s: ctrl not ready\n", __func__);
+
+ // read 7 return status bytes from controller and store in BDA
+ for (i = 0; i < 7; ++i)
+ write_byte(0x0040, 0x0042 + i, inb(0x3f5));
+
+ if ((read_byte(0x0040, 0x0042 + 0) & 0xc0) != 0) {
+ if ((read_byte(0x0040, 0x0042 + 1) & 0x02) != 0) {
+ // diskette not writable.
+ // AH=status code=0x03 (tried to write on write-protected disk)
+ // AL=number of sectors written=0
+ AX = 0x0300;
+ SET_CF();
+ return;
+ } else {
+ BX_PANIC("%s: write error\n", __func__);
+ }
+ }
+
+ SET_AH(0);
+ set_diskette_ret_status(0);
+ set_diskette_current_cyl(drive, 0);
+ CLEAR_CF(); // successful
+ return;
+
+
+ case 0x08: // read diskette drive parameters
+ BX_DEBUG_INT13_FL("floppy f08\n");
+ drive = GET_ELDL();
+
+ if (drive > 1) {
+ AX = 0;
+ BX = 0;
+ CX = 0;
+ DX = 0;
+ ES = 0;
+ DI = 0;
+ SET_DL(num_floppies);
+ SET_CF();
+ return;
+ }
+
+ /// @todo break out drive type determination
+ drive_type = inb_cmos(0x10);
+ num_floppies = 0;
+ if (drive_type & 0xf0)
+ num_floppies++;
+ if (drive_type & 0x0f)
+ num_floppies++;
+
+ if (drive == 0)
+ drive_type >>= 4;
+ else
+ drive_type &= 0x0f;
+
+ SET_BH(0);
+ SET_BL(drive_type);
+ SET_AH(0);
+ SET_AL(0);
+ SET_DL(num_floppies);
+ SET_DH(1); // max head #
+
+ switch (drive_type) {
+ case 0: // none
+ CX = 0;
+ SET_DH(0); // max head #
+ break;
+
+ case 1: // 360KB, 5.25"
+ CX = 0x2709; // 40 tracks, 9 sectors
+ break;
+
+ case 2: // 1.2MB, 5.25"
+ CX = 0x4f0f; // 80 tracks, 15 sectors
+ break;
+
+ case 3: // 720KB, 3.5"
+ CX = 0x4f09; // 80 tracks, 9 sectors
+ break;
+
+ case 4: // 1.44MB, 3.5"
+ CX = 0x4f12; // 80 tracks, 18 sectors
+ break;
+
+ case 5: // 2.88MB, 3.5"
+ CX = 0x4f24; // 80 tracks, 36 sectors
+ break;
+
+ case 14: // 15.6 MB 3.5" (fake)
+ CX = 0xfe3f; // 255 tracks, 63 sectors
+ break;
+
+ case 15: // 63.5 MB 3.5" (fake)
+ CX = 0xfeff; // 255 tracks, 255 sectors - This works because the cylinder
+ break; // and sectors limits/encoding aren't checked by the BIOS
+ // due to copy protection schemes and such stuff.
+
+ default: // ?
+ BX_PANIC("%s: bad floppy type\n", __func__);
+ }
+
+ /* set es & di to point to 11 byte diskette param table in ROM */
+ ES = 0xF000; /// @todo any way to make this relocatable?
+ DI = get_floppy_dpt(drive_type);
+ CLEAR_CF(); // success
+ /* disk status not changed upon success */
+ return;
+
+ case 0x15: // read diskette drive type
+ BX_DEBUG_INT13_FL("floppy f15\n");
+ drive = GET_ELDL();
+ if (drive > 1) {
+ SET_AH(0); // only 2 drives supported
+ // set_diskette_ret_status here ???
+ SET_CF();
+ return;
+ }
+ /// @todo break out drive type determination
+ drive_type = inb_cmos(0x10);
+ if (drive == 0)
+ drive_type >>= 4;
+ else
+ drive_type &= 0x0f;
+ CLEAR_CF(); // successful, not present
+ if (drive_type==0) {
+ SET_AH(0); // drive not present
+ } else if (drive_type > 1) {
+ SET_AH(2); // drive present, supports change line
+ } else {
+ SET_AH(1); // drive present, does not support change line
+ }
+
+ return;
+
+ case 0x16: // get diskette change line status
+ BX_DEBUG_INT13_FL("floppy f16\n");
+ drive = GET_ELDL();
+ if (drive > 1) {
+ SET_AH(0x01); // invalid drive
+ set_diskette_ret_status(0x01);
+ SET_CF();
+ return;
+ }
+
+ SET_AH(0x06); // change line not supported
+ set_diskette_ret_status(0x06);
+ SET_CF();
+ return;
+
+ case 0x17: // set diskette type for format(old)
+ BX_DEBUG_INT13_FL("floppy f17\n");
+ // NOTE: 1.44M diskette not supported by this function, use INT14h/18h instead.
+ // Drive number (0 or 1) values allowed
+ drive = GET_ELDL();
+
+ // Format type (AL)
+ // 00 - NOT USED
+ // 01 - DISKETTE 360K IN 360K DRIVE
+ // 02 - DISKETTE 360K IN 1.2M DRIVE
+ // 03 - DISKETTE 1.2M IN 1.2M DRIVE
+ // 04 - DISKETTE 720K IN 720K DRIVE
+ val8 = GET_AL();
+
+ BX_DEBUG_INT13_FL("floppy f17 - drive: %d, format type: %d\n", drive, val8);
+
+ if (drive > 1) {
+ SET_AH(0x01); // invalid drive
+ set_diskette_ret_status(0x01); // bad parameter
+ SET_CF();
+ return;
+ }
+
+ // see if drive exists
+ if (floppy_drive_exists(drive) == 0) {
+ SET_AH(0x80); // not responding/time out
+ set_diskette_ret_status(0x80);
+ SET_CF();
+ return;
+ }
+
+ // Get current drive state. Set 'base_address' to media status offset address
+ base_address = (drive) ? 0x0091 : 0x0090;
+ media_state = read_byte(0x0040, base_address);
+
+ // Mask out (clear) bits 4-7 (4:media type established, 5:double stepping, 6-7:data rate)
+ media_state &= 0x0f;
+
+ switch (val8) {
+ case 1:
+ // 360K media in 360K drive
+ media_state |= 0x90; // 1001 0000 (media type established, 250 kbps)
+ break;
+ case 2:
+ // 360K media in 1.2M drive
+ media_state |= 0x70; // 0111 0000 (media type established, double stepping, 300 kbps)
+ break;
+ case 3:
+ // 1.2M media in 1.2M drive
+ media_state |= 0x10; // 0001 0000 (media type established, 500 kbps)
+ break;
+ case 4:
+ // 720K media in 720K drive
+ media_state |= 0x90; // 1001 0000 (media type established, 250 kbps)
+ break;
+ default:
+ // bad parameter
+ SET_AH(0x01); // invalid format mode parameter
+ set_diskette_ret_status(0x01);
+ SET_CF();
+ return;
+ }
+
+ // Update media status
+ write_byte(0x0040, base_address, media_state);
+ BX_DEBUG_INT13_FL("floppy f17 - media status set to: %02x\n", media_state);
+
+ // return success!
+ SET_AH(0);
+ set_diskette_ret_status(0);
+ CLEAR_CF();
+ return;
+
+ case 0x18: // set diskette type for format(new)
+ BX_DEBUG_INT13_FL("floppy f18\n");
+ // Set Media Type for Format. Verifies that the device supports a specific geometry.
+ // Unlike INT13h/17h, this service supports higher capacity drives (1.44M and 2.88M).
+ // Drive number (0 or 1) values allowed
+ drive = GET_ELDL();
+
+ val8 = GET_CL();
+ num_sectors = val8 & 0x3f; // max sector number per cylinder
+ track = ((val8 >> 6) << 8) + GET_CH(); // max cylinder number (max cylinders - 1)
+
+ BX_DEBUG_INT13_FL("floppy f18 - drive: %d, max cylinder/track number: %d, sectors-per-tracks: %d\n",
+ drive, track, num_sectors);
+
+ if (drive > 1) {
+ SET_AH(0x01); // invalid drive
+ set_diskette_ret_status(0x01);
+ SET_CF();
+ return;
+ }
+
+ // see if drive exists
+ if (floppy_drive_exists(drive) == 0) {
+ SET_AH(0x80); // not responding/time out
+ set_diskette_ret_status(0x80);
+ SET_CF();
+ return;
+ }
+
+ // see if media in drive, and media type is known
+ if (floppy_media_known(drive) == 0) {
+ if (floppy_media_sense(drive) == 0) {
+ SET_AH(0x0C); // drive/media type unknown
+ set_diskette_ret_status(0x0C);
+ SET_CF();
+ return;
+ }
+ }
+
+ /// @todo break out drive type determination
+ drive_type = inb_cmos(0x10);
+ if (drive == 0)
+ drive_type >>= 4;
+ else
+ drive_type &= 0x0f;
+
+ // Get current drive state. Set 'base_address' to media status offset address
+ base_address = (drive) ? 0x0091 : 0x0090;
+ media_state = read_byte(0x0040, base_address);
+
+ // Mask out (clear) bits 4-7 (4:media type established, 5:double stepping, 6-7:data rate)
+ media_state &= 0x0f;
+
+ switch (drive_type) {
+ case 1: // 360KB, 5.25"
+ if (track == 39 && num_sectors == 9)
+ media_state |= 0x90; // 1001 0000 (media type established, 250 kbps)
+
+ break;
+ case 2: // 1.2MB, 5.25"
+ if (track == 39 && num_sectors == 9) { // 360K disk in 1.2M drive
+ media_state |= 0x70; // 0111 0000 (media type established, double stepping, 300 kbps)
+ } else if (track == 79 && num_sectors == 15) { // 1.2M disk in 1.2M drive
+ media_state |= 0x10; // 0001 0000 (media type established, 500 kbps)
+ }
+ break;
+ case 3: // 720KB, 3.5"
+ if (track == 79 && num_sectors == 9)
+ media_state |= 0x90; // 1001 0000 (media type established, 250 kbps)
+
+ break;
+ case 4: // 1.44MB, 3.5"
+ if (track == 79) {
+ if (num_sectors == 9) { // 720K disk in 1.44M drive
+ media_state |= 0x90; // 1001 0000 (media type established, 250 kbps)
+ } else if (num_sectors == 18) { // 1.44M disk in 1.44M drive
+ media_state |= 0x10; // 0001 0000 (media type established, 500 kbps)
+ }
+ }
+ break;
+ case 5: // 2.88MB, 3.5"
+ if (track == 79) {
+ if (num_sectors == 9) { // 720K disk in 2.88M drive
+ media_state |= 0x90; // 1001 0000 (media type established, 250 kbps)
+ } else if (num_sectors == 18) { // 1.44M disk in 2.88M drive
+ media_state |= 0x10; // 0001 0000 (media type established, 500 kbps)
+ } else if (num_sectors == 36) { // 2.88M disk in 2.88M drive
+ media_state |= 0xD0; // 1101 0000 (media type established, 1 Mbps)
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ // Error if bit 4 (media type established) has not just been set above.
+ if (((media_state >> 4) & 0x01) == 0) {
+ // Error - assume requested tracks/sectors-per-track not supported
+ // for current drive type - or drive type is unknown!
+ SET_AH(0x0C);
+ set_diskette_ret_status(0x0C);
+ SET_CF();
+ return;
+ }
+
+ // Update media status
+ write_byte(0x0040, base_address, media_state);
+
+ // set es & di to point to 11 byte diskette param table in ROM
+ ES = 0xF000; /// @todo any way to make this relocatable?
+ DI = get_floppy_dpt(drive_type);
+
+ // return success!
+ SET_AH(0);
+ set_diskette_ret_status(0);
+ CLEAR_CF();
+ return;
+
+ default:
+ BX_INFO("%s: unsupported AH=%02x\n", __func__, GET_AH());
+
+ // if ( (ah==0x20) || ((ah>=0x41) && (ah<=0x49)) || (ah==0x4e) ) {
+ SET_AH(0x01); // ???
+ set_diskette_ret_status(1);
+ SET_CF();
+ return;
+ // }
+ }
+}
+
+#else // #if BX_SUPPORT_FLOPPY
+
+void BIOSCALL int13_diskette_function(disk_regs_t r)
+{
+ uint8_t val8;
+
+ switch ( GET_AH() ) {
+
+ case 0x01: // Read Diskette Status
+ CLEAR_CF();
+ val8 = read_byte(0x0000, 0x0441);
+ SET_AH(val8);
+ if (val8) {
+ SET_CF();
+ }
+ return;
+
+ default:
+ SET_CF();
+ write_byte(0x0000, 0x0441, 0x01);
+ SET_AH(0x01);
+ }
+}
+
+#endif // #if BX_SUPPORT_FLOPPY
+
+/* Avoid saving general registers already saved by caller (PUSHA). */
+#pragma aux int13_diskette_function modify [di si cx dx bx];
diff --git a/src/VBox/Devices/PC/BIOS/floppyt.c b/src/VBox/Devices/PC/BIOS/floppyt.c
new file mode 100644
index 00000000..4b9a2792
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/floppyt.c
@@ -0,0 +1,104 @@
+/* $Id: floppyt.c $ */
+/** @file
+ * Floppy drive tables.
+ */
+
+/*
+ * Copyright (C) 2011-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "biosint.h"
+#include "inlines.h"
+
+/**
+ * Extended DPT (Disk Parameter Table) structure.
+ */
+typedef struct
+{
+ uint8_t spec1; /* First SPECIFY byte. */
+ uint8_t spec2; /* Second SPECIFY byte. */
+ uint8_t mot_wait; /* Motor wait time after operation. */
+ uint8_t ss_code; /* Sector size code. */
+ uint8_t eot; /* End of Track (ID of last sector). */
+ uint8_t gap; /* Gap length. */
+ uint8_t dtl; /* Data length. */
+ uint8_t fmt_gap; /* Gap length for format. */
+ uint8_t fmt_fill; /* Format fill byte. */
+ uint8_t hd_settle; /* Head settle time (msec). */
+ uint8_t mot_start; /* Motor start time (1/8 sec units). */
+ uint8_t max_trk; /* Maximum track number. */
+ uint8_t rate; /* Data transfer rate code. */
+} dpt_ext;
+
+ct_assert(sizeof(dpt_ext) == 13);
+
+/* Motor spin-up wait time in BIOS ticks (~2 seconds). */
+#define MOTOR_WAIT 0x25
+
+/* Data rates as stored in the DPT */
+#define RATE_250K 0x80
+#define RATE_300K 0x40
+#define RATE_500K 0x00
+#define RATE_1M 0xC0
+
+/* In the 13-entry DPT, 7 entries are constant. Use a macro to set those. */
+#define MAKE_DPT_ENTRY(sp1, eot, gap, fgp, mxt, dtr) \
+ { sp1, 2, MOTOR_WAIT, 2, eot, gap, 0xFF, fgp, 0xF6, 15, 8, mxt, dtr }
+
+dpt_ext fd_parm[] = {
+ MAKE_DPT_ENTRY(0xDF, 9, 0x2A, 0x50, 39, RATE_250K), /* 360K disk/360K drive */
+ MAKE_DPT_ENTRY(0xDF, 9, 0x2A, 0x50, 39, RATE_300K), /* 360K disk/1.2M drive */
+ MAKE_DPT_ENTRY(0xDF, 15, 0x1B, 0x54, 79, RATE_500K), /* 1.2M disk */
+ MAKE_DPT_ENTRY(0xDF, 9, 0x2A, 0x50, 79, RATE_250K), /* 720K disk */
+ MAKE_DPT_ENTRY(0xAF, 18, 0x1B, 0x6C, 79, RATE_500K), /* 1.44M disk */
+ MAKE_DPT_ENTRY(0xAF, 36, 0x1B, 0x54, 79, RATE_1M), /* 2.88M disk */
+ MAKE_DPT_ENTRY(0xAF, 255, 0x1B, 0x54, 255, RATE_500K) /* Fake mega-disk */
+};
+
+typedef struct {
+ uint8_t type; /* Drive type. */
+ uint8_t dpt_entry; /* Index of entry in fd_parm. */
+} fd_map_entry;
+
+/* Drive types as stored in the CMOS. Must match DevPCBios! */
+#define FDRV_360K 1
+#define FDRV_1_2M 2
+#define FDRV_720K 3
+#define FDRV_1_44M 4
+#define FDRV_2_88M 5
+#define FDRV_15M 14
+#define FDRV_63M 15
+
+/* A table mapping (CMOS) drive types to DPT entries. */
+fd_map_entry fd_map[] = {
+ { FDRV_360K, 0 },
+ { FDRV_1_2M, 2 },
+ { FDRV_720K, 3 },
+ { FDRV_1_44M, 4 },
+ { FDRV_2_88M, 5 },
+ { FDRV_15M, 6 },
+ { FDRV_63M, 6 }
+};
+
+/* Find a DPT corresponding to the given drive type. */
+dpt_ext *get_floppy_dpt(uint8_t drv_typ)
+{
+ int i;
+
+ for (i = 0; i < sizeof(fd_map) / sizeof(fd_map[0]); ++i)
+ if (fd_map[i].type == drv_typ)
+ return &fd_parm[fd_map[i].dpt_entry];
+
+ /* As a fallback, return the 1.44M DPT. */
+ return &fd_parm[5];
+}
diff --git a/src/VBox/Devices/PC/BIOS/font8x8.inc b/src/VBox/Devices/PC/BIOS/font8x8.inc
new file mode 100644
index 00000000..8fee2937
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/font8x8.inc
@@ -0,0 +1,133 @@
+; This font comes from the fntcol16.zip package (c) by Joseph Gil
+; found at ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
+; This font is in the public domain
+
+font8x8:
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 07eh, 081h, 0a5h, 081h, 0bdh, 099h, 081h, 07eh
+ db 07eh, 0ffh, 0dbh, 0ffh, 0c3h, 0e7h, 0ffh, 07eh
+ db 06ch, 0feh, 0feh, 0feh, 07ch, 038h, 010h, 000h
+ db 010h, 038h, 07ch, 0feh, 07ch, 038h, 010h, 000h
+ db 038h, 07ch, 038h, 0feh, 0feh, 07ch, 038h, 07ch
+ db 010h, 010h, 038h, 07ch, 0feh, 07ch, 038h, 07ch
+ db 000h, 000h, 018h, 03ch, 03ch, 018h, 000h, 000h
+ db 0ffh, 0ffh, 0e7h, 0c3h, 0c3h, 0e7h, 0ffh, 0ffh
+ db 000h, 03ch, 066h, 042h, 042h, 066h, 03ch, 000h
+ db 0ffh, 0c3h, 099h, 0bdh, 0bdh, 099h, 0c3h, 0ffh
+ db 00fh, 007h, 00fh, 07dh, 0cch, 0cch, 0cch, 078h
+ db 03ch, 066h, 066h, 066h, 03ch, 018h, 07eh, 018h
+ db 03fh, 033h, 03fh, 030h, 030h, 070h, 0f0h, 0e0h
+ db 07fh, 063h, 07fh, 063h, 063h, 067h, 0e6h, 0c0h
+ db 099h, 05ah, 03ch, 0e7h, 0e7h, 03ch, 05ah, 099h
+ db 080h, 0e0h, 0f8h, 0feh, 0f8h, 0e0h, 080h, 000h
+ db 002h, 00eh, 03eh, 0feh, 03eh, 00eh, 002h, 000h
+ db 018h, 03ch, 07eh, 018h, 018h, 07eh, 03ch, 018h
+ db 066h, 066h, 066h, 066h, 066h, 000h, 066h, 000h
+ db 07fh, 0dbh, 0dbh, 07bh, 01bh, 01bh, 01bh, 000h
+ db 03eh, 063h, 038h, 06ch, 06ch, 038h, 0cch, 078h
+ db 000h, 000h, 000h, 000h, 07eh, 07eh, 07eh, 000h
+ db 018h, 03ch, 07eh, 018h, 07eh, 03ch, 018h, 0ffh
+ db 018h, 03ch, 07eh, 018h, 018h, 018h, 018h, 000h
+ db 018h, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h
+ db 000h, 018h, 00ch, 0feh, 00ch, 018h, 000h, 000h
+ db 000h, 030h, 060h, 0feh, 060h, 030h, 000h, 000h
+ db 000h, 000h, 0c0h, 0c0h, 0c0h, 0feh, 000h, 000h
+ db 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h
+ db 000h, 018h, 03ch, 07eh, 0ffh, 0ffh, 000h, 000h
+ db 000h, 0ffh, 0ffh, 07eh, 03ch, 018h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
+ db 030h, 078h, 078h, 030h, 030h, 000h, 030h, 000h
+ db 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h, 000h
+ db 06ch, 06ch, 0feh, 06ch, 0feh, 06ch, 06ch, 000h
+ db 030h, 07ch, 0c0h, 078h, 00ch, 0f8h, 030h, 000h
+ db 000h, 0c6h, 0cch, 018h, 030h, 066h, 0c6h, 000h
+ db 038h, 06ch, 038h, 076h, 0dch, 0cch, 076h, 000h
+ db 060h, 060h, 0c0h, 000h, 000h, 000h, 000h, 000h
+ db 018h, 030h, 060h, 060h, 060h, 030h, 018h, 000h
+ db 060h, 030h, 018h, 018h, 018h, 030h, 060h, 000h
+ db 000h, 066h, 03ch, 0ffh, 03ch, 066h, 000h, 000h
+ db 000h, 030h, 030h, 0fch, 030h, 030h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 060h
+ db 000h, 000h, 000h, 0fch, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 000h
+ db 006h, 00ch, 018h, 030h, 060h, 0c0h, 080h, 000h
+ db 07ch, 0c6h, 0ceh, 0deh, 0f6h, 0e6h, 07ch, 000h
+ db 030h, 070h, 030h, 030h, 030h, 030h, 0fch, 000h
+ db 078h, 0cch, 00ch, 038h, 060h, 0cch, 0fch, 000h
+ db 078h, 0cch, 00ch, 038h, 00ch, 0cch, 078h, 000h
+ db 01ch, 03ch, 06ch, 0cch, 0feh, 00ch, 01eh, 000h
+ db 0fch, 0c0h, 0f8h, 00ch, 00ch, 0cch, 078h, 000h
+ db 038h, 060h, 0c0h, 0f8h, 0cch, 0cch, 078h, 000h
+ db 0fch, 0cch, 00ch, 018h, 030h, 030h, 030h, 000h
+ db 078h, 0cch, 0cch, 078h, 0cch, 0cch, 078h, 000h
+ db 078h, 0cch, 0cch, 07ch, 00ch, 018h, 070h, 000h
+ db 000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h
+ db 000h, 030h, 030h, 000h, 000h, 030h, 030h, 060h
+ db 018h, 030h, 060h, 0c0h, 060h, 030h, 018h, 000h
+ db 000h, 000h, 0fch, 000h, 000h, 0fch, 000h, 000h
+ db 060h, 030h, 018h, 00ch, 018h, 030h, 060h, 000h
+ db 078h, 0cch, 00ch, 018h, 030h, 000h, 030h, 000h
+ db 07ch, 0c6h, 0deh, 0deh, 0deh, 0c0h, 078h, 000h
+ db 030h, 078h, 0cch, 0cch, 0fch, 0cch, 0cch, 000h
+ db 0fch, 066h, 066h, 07ch, 066h, 066h, 0fch, 000h
+ db 03ch, 066h, 0c0h, 0c0h, 0c0h, 066h, 03ch, 000h
+ db 0f8h, 06ch, 066h, 066h, 066h, 06ch, 0f8h, 000h
+ db 0feh, 062h, 068h, 078h, 068h, 062h, 0feh, 000h
+ db 0feh, 062h, 068h, 078h, 068h, 060h, 0f0h, 000h
+ db 03ch, 066h, 0c0h, 0c0h, 0ceh, 066h, 03eh, 000h
+ db 0cch, 0cch, 0cch, 0fch, 0cch, 0cch, 0cch, 000h
+ db 078h, 030h, 030h, 030h, 030h, 030h, 078h, 000h
+ db 01eh, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 000h
+ db 0e6h, 066h, 06ch, 078h, 06ch, 066h, 0e6h, 000h
+ db 0f0h, 060h, 060h, 060h, 062h, 066h, 0feh, 000h
+ db 0c6h, 0eeh, 0feh, 0feh, 0d6h, 0c6h, 0c6h, 000h
+ db 0c6h, 0e6h, 0f6h, 0deh, 0ceh, 0c6h, 0c6h, 000h
+ db 038h, 06ch, 0c6h, 0c6h, 0c6h, 06ch, 038h, 000h
+ db 0fch, 066h, 066h, 07ch, 060h, 060h, 0f0h, 000h
+ db 078h, 0cch, 0cch, 0cch, 0dch, 078h, 01ch, 000h
+ db 0fch, 066h, 066h, 07ch, 06ch, 066h, 0e6h, 000h
+ db 078h, 0cch, 0e0h, 070h, 01ch, 0cch, 078h, 000h
+ db 0fch, 0b4h, 030h, 030h, 030h, 030h, 078h, 000h
+ db 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 0fch, 000h
+ db 0cch, 0cch, 0cch, 0cch, 0cch, 078h, 030h, 000h
+ db 0c6h, 0c6h, 0c6h, 0d6h, 0feh, 0eeh, 0c6h, 000h
+ db 0c6h, 0c6h, 06ch, 038h, 038h, 06ch, 0c6h, 000h
+ db 0cch, 0cch, 0cch, 078h, 030h, 030h, 078h, 000h
+ db 0feh, 0c6h, 08ch, 018h, 032h, 066h, 0feh, 000h
+ db 078h, 060h, 060h, 060h, 060h, 060h, 078h, 000h
+ db 0c0h, 060h, 030h, 018h, 00ch, 006h, 002h, 000h
+ db 078h, 018h, 018h, 018h, 018h, 018h, 078h, 000h
+ db 010h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh
+ db 030h, 030h, 018h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 000h, 078h, 00ch, 07ch, 0cch, 076h, 000h
+ db 0e0h, 060h, 060h, 07ch, 066h, 066h, 0dch, 000h
+ db 000h, 000h, 078h, 0cch, 0c0h, 0cch, 078h, 000h
+ db 01ch, 00ch, 00ch, 07ch, 0cch, 0cch, 076h, 000h
+ db 000h, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h
+ db 038h, 06ch, 060h, 0f0h, 060h, 060h, 0f0h, 000h
+ db 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 0f8h
+ db 0e0h, 060h, 06ch, 076h, 066h, 066h, 0e6h, 000h
+ db 030h, 000h, 070h, 030h, 030h, 030h, 078h, 000h
+ db 00ch, 000h, 00ch, 00ch, 00ch, 0cch, 0cch, 078h
+ db 0e0h, 060h, 066h, 06ch, 078h, 06ch, 0e6h, 000h
+ db 070h, 030h, 030h, 030h, 030h, 030h, 078h, 000h
+ db 000h, 000h, 0cch, 0feh, 0feh, 0d6h, 0c6h, 000h
+ db 000h, 000h, 0f8h, 0cch, 0cch, 0cch, 0cch, 000h
+ db 000h, 000h, 078h, 0cch, 0cch, 0cch, 078h, 000h
+ db 000h, 000h, 0dch, 066h, 066h, 07ch, 060h, 0f0h
+ db 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 01eh
+ db 000h, 000h, 0dch, 076h, 066h, 060h, 0f0h, 000h
+ db 000h, 000h, 07ch, 0c0h, 078h, 00ch, 0f8h, 000h
+ db 010h, 030h, 07ch, 030h, 030h, 034h, 018h, 000h
+ db 000h, 000h, 0cch, 0cch, 0cch, 0cch, 076h, 000h
+ db 000h, 000h, 0cch, 0cch, 0cch, 078h, 030h, 000h
+ db 000h, 000h, 0c6h, 0d6h, 0feh, 0feh, 06ch, 000h
+ db 000h, 000h, 0c6h, 06ch, 038h, 06ch, 0c6h, 000h
+ db 000h, 000h, 0cch, 0cch, 0cch, 07ch, 00ch, 0f8h
+ db 000h, 000h, 0fch, 098h, 030h, 064h, 0fch, 000h
+ db 01ch, 030h, 030h, 0e0h, 030h, 030h, 01ch, 000h
+ db 018h, 018h, 018h, 000h, 018h, 018h, 018h, 000h
+ db 0e0h, 030h, 030h, 01ch, 030h, 030h, 0e0h, 000h
+ db 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h
+ db 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 000h
diff --git a/src/VBox/Devices/PC/BIOS/inlines.h b/src/VBox/Devices/PC/BIOS/inlines.h
new file mode 100644
index 00000000..19983373
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/inlines.h
@@ -0,0 +1,247 @@
+/* $Id: inlines.h $ */
+/** @file
+ * Inline routines for Watcom C.
+ */
+
+/*
+ * Copyright (C) 2010-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_INCLUDED_SRC_PC_BIOS_inlines_h
+#define VBOX_INCLUDED_SRC_PC_BIOS_inlines_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+extern unsigned inp(unsigned port);
+extern unsigned outp(unsigned port, unsigned value);
+extern unsigned inpw(unsigned port);
+extern unsigned outpw(unsigned port, unsigned value);
+#pragma intrinsic(inp,outp,inpw,outpw)
+#define inb(p) inp(p)
+#define outb(p, v) outp(p, v)
+#define inw(p) inpw(p)
+#define outw(p, v) outpw(p, v)
+
+/* Far byte/word/dword access routines. */
+
+inline uint8_t read_byte(uint16_t seg, uint16_t offset)
+{
+ return( *(seg:>(uint8_t *)offset) );
+}
+
+inline void write_byte(uint16_t seg, uint16_t offset, uint8_t data)
+{
+ *(seg:>(uint8_t *)offset) = data;
+}
+
+inline uint16_t read_word(uint16_t seg, uint16_t offset)
+{
+ return( *(seg:>(uint16_t *)offset) );
+}
+
+inline void write_word(uint16_t seg, uint16_t offset, uint16_t data)
+{
+ *(seg:>(uint16_t *)offset) = data;
+}
+
+inline uint32_t read_dword(uint16_t seg, uint16_t offset)
+{
+ return( *(seg:>(uint32_t *)offset) );
+}
+
+inline void write_dword(uint16_t seg, uint16_t offset, uint32_t data)
+{
+ *(seg:>(uint32_t *)offset) = data;
+}
+
+
+void int_enable(void);
+#pragma aux int_enable = "sti" modify exact [] nomemory;
+
+void int_disable(void);
+#pragma aux int_disable = "cli" modify exact [] nomemory;
+
+void int_enable_hlt_disable(void);
+#pragma aux int_enable_hlt_disable = \
+ "sti" \
+ "hlt" \
+ "cli" \
+ modify exact [] nomemory;
+
+uint16_t int_query(void);
+#pragma aux int_query = \
+ "pushf" \
+ "pop ax" \
+ value [ax] modify exact [ax] nomemory;
+
+void int_restore(uint16_t old_flags);
+#pragma aux int_restore = \
+ "push ax" \
+ "popf" \
+ parm [ax] modify exact [] nomemory;
+
+void halt(void);
+#pragma aux halt = "hlt" modify exact [] nomemory;
+
+void halt_forever(void);
+#pragma aux halt_forever = \
+ "forever:" \
+ "hlt" \
+ "jmp forever" \
+ modify exact [] nomemory aborts;
+
+#ifdef __386__
+
+void rep_movsb(void __far *d, void __far *s, int nbytes);
+#pragma aux rep_movsb = \
+ "push ds" \
+ "mov ds, dx" \
+ "rep movsb" \
+ "pop ds" \
+ parm [es edi] [dx esi] [ecx];
+
+#else
+
+void rep_movsb(void __far *d, void __far *s, int nbytes);
+#pragma aux rep_movsb = \
+ "push ds" \
+ "mov ds, dx" \
+ "rep movsb" \
+ "pop ds" \
+ parm [es di] [dx si] [cx];
+
+#endif
+
+void rep_movsw(void __far *d, void __far *s, int nwords);
+#pragma aux rep_movsw = \
+ "push ds" \
+ "mov ds, dx" \
+ "rep movsw" \
+ "pop ds" \
+ parm [es di] [dx si] [cx];
+
+#ifndef __386__
+
+char __far *rep_insb(char __far *buffer, unsigned nbytes, unsigned port);
+#pragma aux rep_insb = ".286" "rep insb" parm [es di] [cx] [dx] value [es di] modify exact [cx di];
+
+char __far *rep_insw(char __far *buffer, unsigned nwords, unsigned port);
+#pragma aux rep_insw = ".286" "rep insw" parm [es di] [cx] [dx] value [es di] modify exact [cx di];
+
+# if VBOX_BIOS_CPU >= 80386
+char __far *rep_insd(char __far *buffer, unsigned ndwords, unsigned port);
+# pragma aux rep_insd = ".386" "rep insd" parm [es di] [cx] [dx] value [es di] modify exact [cx di];
+# endif
+
+char __far *rep_outsb(char __far *buffer, unsigned nbytes, unsigned port);
+#pragma aux rep_outsb = ".286" "rep outs dx,byte ptr es:[si]" parm [es si] [cx] [dx] value [es si] modify exact [cx si];
+
+char __far *rep_outsw(char __far *buffer, unsigned nwords, unsigned port);
+#pragma aux rep_outsw = ".286" "rep outs dx,word ptr es:[si]" parm [es si] [cx] [dx] value [es si] modify exact [cx si];
+
+# if VBOX_BIOS_CPU >= 80386
+char __far *rep_outsd(char __far *buffer, unsigned ndwords, unsigned port);
+# pragma aux rep_outsd = ".386" "rep outs dx,dword ptr es:[si]" parm [es si] [cx] [dx] value [es si] modify exact [cx si];
+# endif
+
+uint16_t swap_16(uint16_t val);
+#pragma aux swap_16 = "xchg ah,al" parm [ax] value [ax] modify exact [ax] nomemory;
+
+uint32_t swap_32(uint32_t val);
+#pragma aux swap_32 = \
+ "xchg ah, al" \
+ "xchg dh, dl" \
+ "xchg ax, dx" \
+ parm [dx ax] value [dx ax] modify exact [dx ax] nomemory;
+
+uint64_t swap_64(uint64_t val);
+#pragma aux swap_64 = \
+ "xchg ah, al" \
+ "xchg bh, bl" \
+ "xchg ch, cl" \
+ "xchg dh, dl" \
+ "xchg ax, dx" \
+ "xchg bx, cx" \
+ parm [ax bx cx dx] value [ax bx cx dx] modify exact [ax bx cx dx] nomemory;
+
+#endif
+
+#if VBOX_BIOS_CPU >= 80386
+
+/* Warning: msr_read/msr_write destroy high bits of 32-bit registers (EAX, ECX, EDX). */
+
+uint64_t msr_read(uint32_t msr);
+#pragma aux msr_read = \
+ ".586" \
+ "shl ecx, 16" \
+ "mov cx, ax" \
+ "rdmsr" \
+ "xchg eax, edx" \
+ "mov bx, ax" \
+ "shr eax, 16" \
+ "mov cx, dx" \
+ "shr edx, 16" \
+ "xchg dx, cx" \
+ parm [cx ax] value [ax bx cx dx] modify [] nomemory;
+
+void msr_write(uint64_t val, uint32_t msr);
+#pragma aux msr_write = \
+ ".586" \
+ "shl eax, 16" \
+ "mov ax, bx" \
+ "xchg dx, cx" \
+ "shl edx, 16" \
+ "mov dx, cx" \
+ "xchg eax, edx" \
+ "mov cx, di" \
+ "shl ecx, 16" \
+ "mov cx, si" \
+ "wrmsr" \
+ parm [ax bx cx dx] [di si] modify [] nomemory;
+
+/* Warning: eflags_read/eflags_write destroy high bits of 32-bit registers (EDX). */
+uint32_t eflags_read( void );
+#pragma aux eflags_read = \
+ ".386" \
+ "pushfd" \
+ "pop edx" \
+ "mov ax, dx" \
+ "shr edx, 16" \
+ value [dx ax] modify [dx ax];
+
+uint32_t eflags_write( uint32_t e_flags );
+#pragma aux eflags_write = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "push edx" \
+ "popfd" \
+ parm [dx ax] modify [dx ax];
+
+/* Warning cpuid destroys high bits of 32-bit registers (EAX, EBX, ECX, EDX). */
+void cpuid( uint32_t __far cpu_id[4], uint32_t leaf );
+#pragma aux cpuid = \
+ ".586" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "mov eax, edx" \
+ "cpuid" \
+ "mov es:[di+0], eax" \
+ "mov es:[di+4], ebx" \
+ "mov es:[di+8], ecx" \
+ "mov es:[di+12], edx" \
+ parm [es di] [dx ax] modify [bx cx dx]
+
+#endif
+
+#endif /* !VBOX_INCLUDED_SRC_PC_BIOS_inlines_h */
+
diff --git a/src/VBox/Devices/PC/BIOS/invop.c b/src/VBox/Devices/PC/BIOS/invop.c
new file mode 100644
index 00000000..cee14a27
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/invop.c
@@ -0,0 +1,350 @@
+/* $Id: invop.c $ */
+/** @file
+ * Real mode invalid opcode handler.
+ */
+
+/*
+ * Copyright (C) 2013-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "biosint.h"
+#include "inlines.h"
+
+//#define EMU_386_LOADALL
+
+/* The layout of 286 LOADALL descriptors. */
+typedef struct tag_ldall_desc {
+ uint16_t base_lo; /* Bits 0-15 of segment base. */
+ uint8_t base_hi; /* Bits 16-13 of segment base. */
+ uint8_t attr; /* Segment attributes. */
+ uint16_t limit; /* Segment limit. */
+} ldall_desc;
+
+/* The 286 LOADALL memory buffer at physical address 800h. From
+ * The Undocumented PC.
+ */
+typedef struct tag_ldall_286 {
+ uint16_t unused1[3];
+ uint16_t msw; /* 806h */
+ uint16_t unused2[7];
+ uint16_t tr; /* 816h */
+ uint16_t flags; /* 818h */
+ uint16_t ip; /* 81Ah */
+ uint16_t ldt; /* 81Ch */
+ uint16_t ds; /* 81Eh */
+ uint16_t ss; /* 820h */
+ uint16_t cs; /* 822h */
+ uint16_t es; /* 824h */
+ uint16_t di; /* 826h */
+ uint16_t si; /* 828h */
+ uint16_t bp; /* 82Ah */
+ uint16_t sp; /* 82Ch */
+ uint16_t bx; /* 82Eh */
+ uint16_t dx; /* 830h */
+ uint16_t cx; /* 832h */
+ uint16_t ax; /* 834h */
+ ldall_desc es_desc; /* 836h */
+ ldall_desc cs_desc; /* 83Ch */
+ ldall_desc ss_desc; /* 842h */
+ ldall_desc ds_desc; /* 848h */
+ ldall_desc gdt_desc; /* 84Eh */
+ ldall_desc ldt_desc; /* 854h */
+ ldall_desc idt_desc; /* 85Ah */
+ ldall_desc tss_desc; /* 860h */
+} ldall_286_s;
+ct_assert(sizeof(ldall_286_s) == 0x66);
+
+#ifdef EMU_386_LOADALL
+
+/* The layout of 386 LOADALL descriptors. */
+typedef struct tag_ldal3_desc {
+ uint32_t attr; /* Segment attributes. */
+ uint32_t base; /* Expanded segment base. */
+ uint32_t limit; /* Expanded segment limit. */
+} ldal3_desc;
+
+/* The 386 LOADALL memory buffer pointed to by ES:EDI.
+ */
+typedef struct tag_ldall_386 {
+ uint32_t cr0; /* 00h */
+ uint32_t eflags; /* 04h */
+ uint32_t eip; /* 08h */
+ uint32_t edi; /* 0Ch */
+ uint32_t esi; /* 10h */
+ uint32_t ebp; /* 14h */
+ uint32_t esp; /* 18h */
+ uint32_t ebx; /* 1Ch */
+ uint32_t edx; /* 20h */
+ uint32_t ecx; /* 24h */
+ uint32_t eax; /* 28h */
+ uint32_t dr6; /* 2Ch */
+ uint32_t dr7; /* 30h */
+ uint32_t tr; /* 34h */
+ uint32_t ldt; /* 38h */
+ uint32_t gs; /* 3Ch */
+ uint32_t fs; /* 40h */
+ uint32_t ds; /* 44h */
+ uint32_t ss; /* 4Ch */
+ uint32_t cs; /* 48h */
+ uint32_t es; /* 50h */
+ ldal3_desc tss_desc; /* 54h */
+ ldal3_desc idt_desc; /* 60h */
+ ldal3_desc gdt_desc; /* 6Ch */
+ ldal3_desc ldt_desc; /* 78h */
+ ldal3_desc gs_desc; /* 84h */
+ ldal3_desc fs_desc; /* 90h */
+ ldal3_desc ds_desc; /* 9Ch */
+ ldal3_desc ss_desc; /* A8h */
+ ldal3_desc cs_desc; /* B4h */
+ ldal3_desc es_desc; /* C0h */
+} ldall_386_s;
+ct_assert(sizeof(ldall_386_s) == 0xCC);
+
+#endif
+
+/*
+ * LOADALL emulation assumptions:
+ * - MSW indicates real mode
+ * - Standard real mode CS and SS is to be used
+ * - Segment values of non-RM segments (if any) do not matter
+ * - Standard segment attributes are used
+ */
+
+/* A wrapper for LIDT. */
+void load_idtr(uint32_t base, uint16_t limit);
+#pragma aux load_idtr = \
+ ".286p" \
+ "mov bx, sp" \
+ "lidt fword ptr ss:[bx]"\
+ parm caller reverse [] modify [bx] exact;
+
+/* A wrapper for LGDT. */
+void load_gdtr(uint32_t base, uint16_t limit);
+#pragma aux load_gdtr = \
+ ".286p" \
+ "mov bx, sp" \
+ "lgdt fword ptr ss:[bx]"\
+ parm caller reverse [] modify [bx] exact;
+
+/* Load DS/ES as real-mode segments. May be overwritten later.
+ * NB: Loads SS with 80h to address the LOADALL buffer. Must
+ * not touch CX!
+ */
+void load_rm_segs(int seg_flags);
+#pragma aux load_rm_segs = \
+ "mov ax, 80h" \
+ "mov ss, ax" \
+ "mov ax, ss:[1Eh]" \
+ "mov ds, ax" \
+ "mov ax, ss:[24h]" \
+ "mov es, ax" \
+ parm [cx] nomemory modify nomemory;
+
+/* Briefly switch to protected mode and load ES and/or DS if necessary.
+ * NB: Trashes high bits of EAX, but that should be safe. Expects flags
+ * in CX.
+ */
+void load_pm_segs(void);
+#pragma aux load_pm_segs = \
+ ".386p" \
+ "smsw ax" \
+ "inc ax" \
+ "lmsw ax" \
+ "mov ax, 8" \
+ "test cx, 1" \
+ "jz skip_es" \
+ "mov es, ax" \
+ "skip_es:" \
+ "test cx, 2" \
+ "jz skip_ds" \
+ "mov bx,ss:[00h]" \
+ "mov ss:[08h], bx" \
+ "mov bx,ss:[02h]" \
+ "mov ss:[0Ah], bx" \
+ "mov bx,ss:[04h]" \
+ "mov ss:[0Ch], bx" \
+ "mov ds, ax" \
+ "skip_ds:" \
+ "mov eax, cr0" \
+ "dec ax" \
+ "mov cr0, eax" \
+ parm nomemory modify nomemory;
+
+/* Complete LOADALL emulation: Restore general-purpose registers, stack
+ * pointer, and CS:IP. NB: The LOADALL instruction stores registers in
+ * the same order as PUSHA. Surprise, surprise!
+ */
+void ldall_finish(void);
+#pragma aux ldall_finish = \
+ ".286" \
+ "mov sp, 26h" \
+ "popa" \
+ "mov sp, ss:[2Ch]" \
+ "sub sp, 6" \
+ "mov ss, ss:[20h]" \
+ "iret" \
+ parm nomemory modify nomemory aborts;
+
+#ifdef EMU_386_LOADALL
+
+/* 386 version of the above. */
+void ldal3_finish(void);
+#pragma aux ldal3_finish = \
+ ".386" \
+ "mov sp, 28h" \
+ "popad" \
+ "mov sp, ss:[18h]" \
+ "sub sp, 6" \
+ "mov ss, ss:[48h]" \
+ "iret" \
+ parm nomemory modify nomemory aborts;
+
+/* 386 version of load_rm_segs.
+ * NB: Must not touch CX!
+ */
+void load_rm_seg3(int seg_flags, uint16_t ss_base);
+#pragma aux load_rm_seg3 = \
+ "mov ss, ax" \
+ "mov ax, ss:[44h]" \
+ "mov ds, ax" \
+ "mov ax, ss:[50h]" \
+ "mov es, ax" \
+ parm [ax] [cx] nomemory modify nomemory;
+
+#endif
+
+#define LOAD_ES 0x01 /* ES needs to be loaded in protected mode. */
+#define LOAD_DS 0x02 /* DS needs to be loaded in protected mode. */
+
+/*
+ * The invalid opcode handler exists to work around fishy application
+ * code and paper over CPU generation differences:
+ *
+ * - Skip redundant LOCK prefixes (allowed on 8086, #UD on 286+).
+ * - Emulate just enough of 286 LOADALL.
+ *
+ */
+void BIOSCALL inv_op_handler(uint16_t ds, uint16_t es, pusha_regs_t gr, volatile iret_addr_t ra)
+{
+ void __far *ins = ra.cs :> ra.ip;
+
+ if (*(uint8_t __far *)ins == 0xF0) {
+ /* LOCK prefix - skip over it and try again. */
+ ++ra.ip;
+ } else if (*(uint16_t __far *)ins == 0x050F) {
+ /* 286 LOADALL. NB: Same opcode as SYSCALL. */
+ ldall_286_s __far *ldbuf = 0 :> 0x800;
+ iret_addr_t __far *ret_addr;
+ uint32_t seg_base;
+ int seg_flags = 0;
+
+ /* One of the challenges is that we must restore SS:SP as well
+ * as CS:IP and FLAGS from the LOADALL buffer. We copy CS/IP/FLAGS
+ * from the buffer just below the SS:SP values from the buffer so
+ * that we can eventually IRET to the desired CS/IP/FLAGS/SS/SP
+ * values in one go.
+ */
+ ret_addr = ldbuf->ss :> (ldbuf->sp - sizeof(iret_addr_t));
+ ret_addr->ip = ldbuf->ip;
+ ret_addr->cs = ldbuf->cs;
+ ret_addr->flags.u.r16.flags = ldbuf->flags;
+
+ /* Examine ES/DS. */
+ seg_base = ldbuf->es_desc.base_lo | (uint32_t)ldbuf->es_desc.base_hi << 16;
+ if (seg_base != (uint32_t)ldbuf->es << 4)
+ seg_flags |= LOAD_ES;
+ seg_base = ldbuf->ds_desc.base_lo | (uint32_t)ldbuf->ds_desc.base_hi << 16;
+ if (seg_base != (uint32_t)ldbuf->ds << 4)
+ seg_flags |= LOAD_DS;
+
+ /* The LOADALL buffer doubles as a tiny GDT. */
+ load_gdtr(0x800, 4 * 8 - 1);
+
+ /* Store the ES base/limit/attributes in the unused words (GDT selector 8). */
+ ldbuf->unused2[0] = ldbuf->es_desc.limit;
+ ldbuf->unused2[1] = ldbuf->es_desc.base_lo;
+ ldbuf->unused2[2] = (ldbuf->es_desc.attr << 8) | ldbuf->es_desc.base_hi;
+ ldbuf->unused2[3] = 0;
+
+ /* Store the DS base/limit/attributes in other unused words. */
+ ldbuf->unused1[0] = ldbuf->ds_desc.limit;
+ ldbuf->unused1[1] = ldbuf->ds_desc.base_lo;
+ ldbuf->unused1[2] = (ldbuf->ds_desc.attr << 8) | ldbuf->ds_desc.base_hi;
+
+ /* Load the IDTR as specified. */
+ seg_base = ldbuf->idt_desc.base_lo | (uint32_t)ldbuf->idt_desc.base_hi << 16;
+ load_idtr(seg_base, ldbuf->idt_desc.limit);
+
+ /* Do the tricky bits now. */
+ load_rm_segs(seg_flags);
+ load_pm_segs();
+ ldall_finish();
+#ifdef EMU_386_LOADALL
+ } else if (*(uint16_t __far *)ins == 0x070F) {
+ /* 386 LOADALL. NB: Same opcode as SYSRET. */
+ ldall_386_s __far *ldbuf = (void __far *)es :> gr.u.r16.di; /* Assume 16-bit value in EDI. */
+ ldall_286_s __far *ldbuf2 = 0 :> 0x800;
+ iret_addr_t __far *ret_addr;
+ uint32_t seg_base;
+ int seg_flags = 0;
+
+ /* NB: BIG FAT ASSUMPTION! Users of 386 LOADALL are assumed to also
+ * have a 286 LOADALL buffer at physical address 800h. We use unused fields
+ * in that buffer for temporary storage.
+ */
+
+ /* Set up return stack. */
+ ret_addr = ldbuf->ss :> (ldbuf->esp - sizeof(iret_addr_t));
+ ret_addr->ip = ldbuf->eip;
+ ret_addr->cs = ldbuf->cs;
+ ret_addr->flags.u.r16.flags = ldbuf->eflags;
+
+ /* Examine ES/DS. */
+ seg_base = ldbuf->es_desc.base;
+ if (seg_base != (uint32_t)ldbuf->es << 4)
+ seg_flags |= LOAD_ES;
+ seg_base = ldbuf->ds_desc.base;
+ if (seg_base != (uint32_t)ldbuf->ds << 4)
+ seg_flags |= LOAD_DS;
+
+ /* The LOADALL buffer doubles as a tiny GDT. */
+ load_gdtr(0x800, 4 * 8 - 1);
+
+ /* Store the ES base/limit/attributes in the unused words (GDT selector 8). */
+ ldbuf2->unused2[0] = ldbuf->es_desc.limit;
+ ldbuf2->unused2[1] = (uint16_t)ldbuf->es_desc.base;
+ ldbuf2->unused2[2] = (ldbuf->es_desc.attr & 0xFF00) | (ldbuf->es_desc.base >> 16);
+ ldbuf2->unused2[3] = 0;
+
+ /* Store the DS base/limit/attributes in other unused words. */
+ ldbuf2->unused1[0] = ldbuf->ds_desc.limit;
+ ldbuf2->unused1[1] = (uint16_t)ldbuf->ds_desc.base;
+ ldbuf2->unused1[2] = (ldbuf->ds_desc.attr & 0xFF00) | (ldbuf->ds_desc.base >> 16);
+
+ /* Load the IDTR as specified. */
+ seg_base = ldbuf->idt_desc.base;
+ load_idtr(seg_base, ldbuf->idt_desc.limit);
+
+ /* Do the tricky bits now. */
+ load_rm_seg3(es, seg_flags);
+ load_pm_segs();
+ ldal3_finish();
+#endif
+ } else {
+ /* There isn't much point in executing the invalid opcode handler
+ * in an endless loop, so halt right here.
+ */
+ int_enable();
+ halt_forever();
+ }
+}
diff --git a/src/VBox/Devices/PC/BIOS/keyboard.c b/src/VBox/Devices/PC/BIOS/keyboard.c
new file mode 100644
index 00000000..e141b743
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/keyboard.c
@@ -0,0 +1,822 @@
+/* $Id: keyboard.c $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+
+#include <stdint.h>
+#include "inlines.h"
+#include "biosint.h"
+
+#if DEBUG_INT16
+# define BX_DEBUG_INT16(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define BX_DEBUG_INT16(...)
+#endif
+
+extern void post(void);
+#pragma aux post "*";
+
+void jmp_post(void);
+#pragma aux jmp_post = "jmp far ptr post" aborts;
+
+extern void eoi_master_pic(void); /* in assembly code */
+#pragma aux eoi_master_pic "*";
+
+/* Manually save/restore BP around invoking user Ctrl-Break handler.
+ * The handler could conceivably clobber BP and the compiler does not
+ * believe us when we say 'modify [bp]' (BP is considered unalterable).
+ */
+void int_1b(void);
+#pragma aux int_1b = \
+ "push bp" \
+ "int 1Bh" \
+ "pop bp" \
+ value [bp] modify [bp];
+
+
+#define none 0
+#define MAX_SCAN_CODE 0x58
+
+struct {
+ uint16_t normal;
+ uint16_t shift;
+ uint16_t control;
+ uint16_t alt;
+ uint8_t lock_flags;
+} static const scan_to_scanascii[MAX_SCAN_CODE + 1] = {
+ { none, none, none, none, none },
+ { 0x011b, 0x011b, 0x011b, 0x0100, none }, /* escape */
+ { 0x0231, 0x0221, none, 0x7800, none }, /* 1! */
+ { 0x0332, 0x0340, 0x0300, 0x7900, none }, /* 2@ */
+ { 0x0433, 0x0423, none, 0x7a00, none }, /* 3# */
+ { 0x0534, 0x0524, none, 0x7b00, none }, /* 4$ */
+ { 0x0635, 0x0625, none, 0x7c00, none }, /* 5% */
+ { 0x0736, 0x075e, 0x071e, 0x7d00, none }, /* 6^ */
+ { 0x0837, 0x0826, none, 0x7e00, none }, /* 7& */
+ { 0x0938, 0x092a, none, 0x7f00, none }, /* 8* */
+ { 0x0a39, 0x0a28, none, 0x8000, none }, /* 9( */
+ { 0x0b30, 0x0b29, none, 0x8100, none }, /* 0) */
+ { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200, none }, /* -_ */
+ { 0x0d3d, 0x0d2b, none, 0x8300, none }, /* =+ */
+ { 0x0e08, 0x0e08, 0x0e7f, none, none }, /* backspace */
+ { 0x0f09, 0x0f00, none, none, none }, /* tab */
+ { 0x1071, 0x1051, 0x1011, 0x1000, 0x40 }, /* Q */
+ { 0x1177, 0x1157, 0x1117, 0x1100, 0x40 }, /* W */
+ { 0x1265, 0x1245, 0x1205, 0x1200, 0x40 }, /* E */
+ { 0x1372, 0x1352, 0x1312, 0x1300, 0x40 }, /* R */
+ { 0x1474, 0x1454, 0x1414, 0x1400, 0x40 }, /* T */
+ { 0x1579, 0x1559, 0x1519, 0x1500, 0x40 }, /* Y */
+ { 0x1675, 0x1655, 0x1615, 0x1600, 0x40 }, /* U */
+ { 0x1769, 0x1749, 0x1709, 0x1700, 0x40 }, /* I */
+ { 0x186f, 0x184f, 0x180f, 0x1800, 0x40 }, /* O */
+ { 0x1970, 0x1950, 0x1910, 0x1900, 0x40 }, /* P */
+ { 0x1a5b, 0x1a7b, 0x1a1b, none, none }, /* [{ */
+ { 0x1b5d, 0x1b7d, 0x1b1d, none, none }, /* ]} */
+ { 0x1c0d, 0x1c0d, 0x1c0a, none, none }, /* Enter */
+ { none, none, none, none, none }, /* L Ctrl */
+ { 0x1e61, 0x1e41, 0x1e01, 0x1e00, 0x40 }, /* A */
+ { 0x1f73, 0x1f53, 0x1f13, 0x1f00, 0x40 }, /* S */
+ { 0x2064, 0x2044, 0x2004, 0x2000, 0x40 }, /* D */
+ { 0x2166, 0x2146, 0x2106, 0x2100, 0x40 }, /* F */
+ { 0x2267, 0x2247, 0x2207, 0x2200, 0x40 }, /* G */
+ { 0x2368, 0x2348, 0x2308, 0x2300, 0x40 }, /* H */
+ { 0x246a, 0x244a, 0x240a, 0x2400, 0x40 }, /* J */
+ { 0x256b, 0x254b, 0x250b, 0x2500, 0x40 }, /* K */
+ { 0x266c, 0x264c, 0x260c, 0x2600, 0x40 }, /* L */
+ { 0x273b, 0x273a, none, none, none }, /* ;: */
+ { 0x2827, 0x2822, none, none, none }, /* '" */
+ { 0x2960, 0x297e, none, none, none }, /* `~ */
+ { none, none, none, none, none }, /* L shift */
+ { 0x2b5c, 0x2b7c, 0x2b1c, none, none }, /* |\ */
+ { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00, 0x40 }, /* Z */
+ { 0x2d78, 0x2d58, 0x2d18, 0x2d00, 0x40 }, /* X */
+ { 0x2e63, 0x2e43, 0x2e03, 0x2e00, 0x40 }, /* C */
+ { 0x2f76, 0x2f56, 0x2f16, 0x2f00, 0x40 }, /* V */
+ { 0x3062, 0x3042, 0x3002, 0x3000, 0x40 }, /* B */
+ { 0x316e, 0x314e, 0x310e, 0x3100, 0x40 }, /* N */
+ { 0x326d, 0x324d, 0x320d, 0x3200, 0x40 }, /* M */
+ { 0x332c, 0x333c, none, none, none }, /* ,< */
+ { 0x342e, 0x343e, none, none, none }, /* .> */
+ { 0x352f, 0x353f, none, none, none }, /* /? */
+ { none, none, none, none, none }, /* R Shift */
+ { 0x372a, 0x372a, none, none, none }, /* * */
+ { none, none, none, none, none }, /* L Alt */
+ { 0x3920, 0x3920, 0x3920, 0x3920, none }, /* space */
+ { none, none, none, none, none }, /* caps lock */
+ { 0x3b00, 0x5400, 0x5e00, 0x6800, none }, /* F1 */
+ { 0x3c00, 0x5500, 0x5f00, 0x6900, none }, /* F2 */
+ { 0x3d00, 0x5600, 0x6000, 0x6a00, none }, /* F3 */
+ { 0x3e00, 0x5700, 0x6100, 0x6b00, none }, /* F4 */
+ { 0x3f00, 0x5800, 0x6200, 0x6c00, none }, /* F5 */
+ { 0x4000, 0x5900, 0x6300, 0x6d00, none }, /* F6 */
+ { 0x4100, 0x5a00, 0x6400, 0x6e00, none }, /* F7 */
+ { 0x4200, 0x5b00, 0x6500, 0x6f00, none }, /* F8 */
+ { 0x4300, 0x5c00, 0x6600, 0x7000, none }, /* F9 */
+ { 0x4400, 0x5d00, 0x6700, 0x7100, none }, /* F10 */
+ { none, none, none, none, none }, /* Num Lock */
+ { none, none, none, none, none }, /* Scroll Lock */
+ { 0x4700, 0x4737, 0x7700, none, 0x20 }, /* 7 Home */
+ { 0x4800, 0x4838, none, none, 0x20 }, /* 8 UP */
+ { 0x4900, 0x4939, 0x8400, none, 0x20 }, /* 9 PgUp */
+ { 0x4a2d, 0x4a2d, none, none, none }, /* - */
+ { 0x4b00, 0x4b34, 0x7300, none, 0x20 }, /* 4 Left */
+ { 0x4c00, 0x4c35, none, none, 0x20 }, /* 5 */
+ { 0x4d00, 0x4d36, 0x7400, none, 0x20 }, /* 6 Right */
+ { 0x4e2b, 0x4e2b, none, none, none }, /* + */
+ { 0x4f00, 0x4f31, 0x7500, none, 0x20 }, /* 1 End */
+ { 0x5000, 0x5032, none, none, 0x20 }, /* 2 Down */
+ { 0x5100, 0x5133, 0x7600, none, 0x20 }, /* 3 PgDn */
+ { 0x5200, 0x5230, none, none, 0x20 }, /* 0 Ins */
+ { 0x5300, 0x532e, none, none, 0x20 }, /* Del */
+ { none, none, none, none, none },
+ { none, none, none, none, none },
+ { 0x565c, 0x567c, none, none, none }, /* \| */
+ { 0x8500, 0x8700, 0x8900, 0x8b00, none }, /* F11 */
+ { 0x8600, 0x8800, 0x8a00, 0x8c00, none } /* F12 */
+};
+
+
+/* Keyboard initialization. */
+
+//--------------------------------------------------------------------------
+// keyboard_panic
+//--------------------------------------------------------------------------
+void keyboard_panic(uint16_t status)
+{
+ // If you're getting a 993 keyboard panic here,
+ // please see the comment in keyboard_init
+
+ BX_PANIC("Keyboard error:%u\n",status);
+}
+
+
+//--------------------------------------------------------------------------
+// keyboard_init
+//--------------------------------------------------------------------------
+// this file is based on LinuxBIOS implementation of keyboard.c
+// could convert to #asm to gain space
+void BIOSCALL keyboard_init(void)
+{
+ uint16_t max;
+
+ /* ------------------- controller side ----------------------*/
+ /* send cmd = 0xAA, self test 8042 */
+ outb(0x64, 0xaa);
+
+ /* Wait until buffer is empty */
+ max=0xffff;
+ while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00);
+ if (max==0x0) keyboard_panic(00);
+
+ /* Wait for data */
+ max=0xffff;
+ while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x01);
+ if (max==0x0) keyboard_panic(01);
+
+ /* read self-test result, 0x55 should be returned from 0x60 */
+ if ((inb(0x60) != 0x55)){
+ keyboard_panic(991);
+ }
+
+ /* send cmd = 0xAB, keyboard interface test */
+ outb(0x64,0xab);
+
+ /* Wait until buffer is empty */
+ max=0xffff;
+ while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x10);
+ if (max==0x0) keyboard_panic(10);
+
+ /* Wait for data */
+ max=0xffff;
+ while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x11);
+ if (max==0x0) keyboard_panic(11);
+
+ /* read keyboard interface test result, */
+ /* 0x00 should be returned form 0x60 */
+ if ((inb(0x60) != 0x00)) {
+ keyboard_panic(992);
+ }
+
+ /* ------------------- keyboard side ------------------------*/
+ /* reset keyboard and self test (keyboard side) */
+ /* also enables the keyboard interface */
+ outb(0x60, 0xff);
+
+ /* Wait until buffer is empty */
+ max=0xffff;
+ while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x20);
+ if (max==0x0) keyboard_panic(20);
+
+ /* Wait for data */
+ max=0xffff;
+ while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x21);
+ if (max==0x0) keyboard_panic(21);
+
+ /* keyboard should return ACK */
+ if ((inb(0x60) != 0xfa)) {
+ keyboard_panic(993);
+ }
+
+ /* Wait for reset to complete */
+ while ( (inb(0x64) & 0x01) == 0 ) outb(0x80, 0x31);
+
+ if ((inb(0x60) != 0xaa && inb(0x60) != 0xaa)) {
+ keyboard_panic(994);
+ }
+
+ /* Disable keyboard */
+ outb(0x60, 0xf5);
+
+ /* Wait until buffer is empty */
+ max=0xffff;
+ while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x40);
+ if (max==0x0) keyboard_panic(40);
+
+ /* Wait for data */
+ max=0xffff;
+ while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x41);
+ if (max==0x0) keyboard_panic(41);
+
+ /* keyboard should return ACK */
+ if ((inb(0x60) != 0xfa)) {
+ keyboard_panic(995);
+ }
+
+ /* Write Keyboard Mode */
+ outb(0x64, 0x60);
+
+ /* Wait until buffer is empty */
+ max=0xffff;
+ while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x50);
+ if (max==0x0) keyboard_panic(50);
+
+ /* send cmd: scan code convert, disable mouse, enable IRQ 1 */
+ outb(0x60, 0x65);
+
+ /* Wait until buffer is empty */
+ max=0xffff;
+ while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x60);
+ if (max==0x0) keyboard_panic(60);
+
+ /* Enable keyboard */
+ outb(0x60, 0xf4);
+
+ /* Wait until buffer is empty */
+ max=0xffff;
+ while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x70);
+ if (max==0x0) keyboard_panic(70);
+
+ /* Wait for data */
+ max=0xffff;
+ while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x71);
+ if (max==0x0) keyboard_panic(70);
+
+ /* keyboard should return ACK */
+ if ((inb(0x60) != 0xfa)) {
+ keyboard_panic(996);
+ }
+
+ /* Enable aux interface */
+ outb(0x64,0xa8);
+
+ /* While we're here, disable the A20 gate. Required for
+ * compatibility with the IBM PC and DOS.
+ */
+ set_enable_a20(0);
+}
+
+
+unsigned int enqueue_key(uint8_t scan_code, uint8_t ascii_code)
+{
+ uint16_t buffer_start, buffer_end, buffer_head, buffer_tail, temp_tail;
+
+#if VBOX_BIOS_CPU >= 80286
+ buffer_start = read_word(0x0040, 0x0080);
+ buffer_end = read_word(0x0040, 0x0082);
+#else
+ buffer_start = 0x001E;
+ buffer_end = 0x003E;
+#endif
+
+ buffer_head = read_word(0x0040, 0x001A);
+ buffer_tail = read_word(0x0040, 0x001C);
+
+ temp_tail = buffer_tail;
+ buffer_tail += 2;
+ if (buffer_tail >= buffer_end)
+ buffer_tail = buffer_start;
+
+ if (buffer_tail == buffer_head)
+ return(0);
+
+ write_byte(0x0040, temp_tail, ascii_code);
+ write_byte(0x0040, temp_tail+1, scan_code);
+ write_word(0x0040, 0x001C, buffer_tail);
+ return(1);
+}
+
+
+/* Keyboard hardware interrupt handler. */
+/// @todo should this be declared as taking arguments at all?
+void BIOSCALL int09_function(uint16_t ES, uint16_t DI, uint16_t SI, uint16_t BP, uint16_t SP,
+ uint16_t BX, uint16_t DX, uint16_t CX, uint16_t AX)
+{
+ uint8_t scancode, asciicode, shift_flags;
+ uint8_t mf2_flags, mf2_state, flag;
+
+ //
+ // DS has been set to F000 before call
+ //
+
+
+ scancode = GET_AL();
+
+ if (scancode == 0) {
+ BX_INFO("KBD: int09 handler: AL=0\n");
+ return;
+ }
+
+ mf2_flags = read_byte(0x0040, 0x18);
+ mf2_state = read_byte(0x0040, 0x96);
+ shift_flags = read_byte(0x0040, 0x17);
+ asciicode = 0;
+
+ switch (scancode) {
+ case 0x3a: /* Caps Lock press */
+ shift_flags ^= 0x40;
+ write_byte(0x0040, 0x17, shift_flags);
+ mf2_flags |= 0x40;
+ write_byte(0x0040, 0x18, mf2_flags);
+ break;
+ case 0xba: /* Caps Lock release */
+ mf2_flags &= ~0x40;
+ write_byte(0x0040, 0x18, mf2_flags);
+ break;
+
+ case 0x2a: /* L Shift press */
+ case 0xaa: /* L Shift release */
+ case 0x36: /* R Shift press */
+ case 0xb6: /* R Shift release */
+ /* If this was an extended (i.e. faked) key, leave flags alone. */
+ if (!(mf2_state & 0x02)) {
+ flag = (scancode & 0x7f) == 0x2a ? 0x02 : 0x01;
+ if (scancode & 0x80)
+ shift_flags &= ~flag;
+ else
+ shift_flags |= flag;
+ write_byte(0x0040, 0x17, shift_flags);
+ }
+ break;
+
+ case 0x1d: /* Ctrl press */
+ if ((mf2_state & 0x01) == 0) {
+ shift_flags |= 0x04;
+ write_byte(0x0040, 0x17, shift_flags);
+ if (mf2_state & 0x02) {
+ mf2_state |= 0x04;
+ write_byte(0x0040, 0x96, mf2_state);
+ } else {
+ mf2_flags |= 0x01;
+ write_byte(0x0040, 0x18, mf2_flags);
+ }
+ }
+ break;
+ case 0x9d: /* Ctrl release */
+ if ((mf2_state & 0x01) == 0) {
+ shift_flags &= ~0x04;
+ write_byte(0x0040, 0x17, shift_flags);
+ if (mf2_state & 0x02) {
+ mf2_state &= ~0x04;
+ write_byte(0x0040, 0x96, mf2_state);
+ } else {
+ mf2_flags &= ~0x01;
+ write_byte(0x0040, 0x18, mf2_flags);
+ }
+ }
+ break;
+
+ case 0x38: /* Alt press */
+ shift_flags |= 0x08;
+ write_byte(0x0040, 0x17, shift_flags);
+ if (mf2_state & 0x02) {
+ mf2_state |= 0x08;
+ write_byte(0x0040, 0x96, mf2_state);
+ } else {
+ mf2_flags |= 0x02;
+ write_byte(0x0040, 0x18, mf2_flags);
+ }
+ break;
+ case 0xb8: /* Alt release */
+ shift_flags &= ~0x08;
+ write_byte(0x0040, 0x17, shift_flags);
+ if (mf2_state & 0x02) {
+ mf2_state &= ~0x08;
+ write_byte(0x0040, 0x96, mf2_state);
+ } else {
+ mf2_flags &= ~0x02;
+ write_byte(0x0040, 0x18, mf2_flags);
+ }
+ break;
+
+ case 0x45: /* Num Lock/Pause press */
+ if ((mf2_state & 0x03) == 0) {
+ /* Num Lock */
+ mf2_flags |= 0x20;
+ write_byte(0x0040, 0x18, mf2_flags);
+ shift_flags ^= 0x20;
+ write_byte(0x0040, 0x17, shift_flags);
+ } else {
+ /* Pause */
+ mf2_flags |= 0x08; /* Set the suspend flag */
+ write_byte(0x0040, 0x18, mf2_flags);
+
+ /* Enable keyboard and send EOI. */
+ outp(0x64, 0xae);
+ eoi_master_pic();
+
+ while (read_byte(0x0040, 0x18) & 0x08)
+ ; /* Hold on and wait... */
+
+ /// @todo We will send EOI again (and enable keyboard) on the way out; we shouldn't
+ }
+ break;
+ case 0xc5: /* Num Lock/Pause release */
+ if ((mf2_state & 0x03) == 0) {
+ mf2_flags &= ~0x20;
+ write_byte(0x0040, 0x18, mf2_flags);
+ }
+ break;
+
+ case 0x46: /* Scroll Lock/Break press */
+ if (mf2_state & 0x02) { /* E0 prefix? */
+ /* Zap the keyboard buffer. */
+ write_word(0x0040, 0x001c, read_word(0x0040, 0x001a));
+
+ write_byte(0x0040, 0x71, 0x80); /* Set break flag */
+ outp(0x64, 0xae); /* Enable keyboard */
+ int_1b(); /* Invoke user handler */
+ enqueue_key(0, 0); /* Dummy key press*/
+ } else {
+ mf2_flags |= 0x10;
+ write_byte(0x0040, 0x18, mf2_flags);
+ shift_flags ^= 0x10;
+ write_byte(0x0040, 0x17, shift_flags);
+ }
+ break;
+
+ case 0xc6: /* Scroll Lock/Break release */
+ if (!(mf2_state & 0x02)) { /* Only if no E0 prefix */
+ mf2_flags &= ~0x10;
+ write_byte(0x0040, 0x18, mf2_flags);
+ }
+ break;
+
+ case 0x54: /* SysRq press */
+ if (!(mf2_flags & 0x04)) { /* If not already down */
+ mf2_flags |= 0x04;
+ write_byte(0x0040, 0x18, mf2_flags);
+ /// @todo EOI/enable kbd/enable interrupts/call INT 15h/8500h
+ }
+ break;
+
+ case 0xd4: /* SysRq release */
+ mf2_flags &= ~0x04;
+ write_byte(0x0040, 0x18, mf2_flags);
+ /// @todo EOI/enable kbd/enable interrupts/call INT 15h/8501h
+ break;
+
+ case 0x53: /* Del press */
+ if ((shift_flags & 0x0c) == 0x0c) {
+ /* Indicate a warm boot. */
+ write_word(0x0040,0x0072, 0x1234);
+ jmp_post();
+ }
+ /* fall through */
+
+ default:
+ /* Check if suspend flag set. */
+ if (mf2_flags & 0x08) {
+ /* Pause had been pressed. Clear suspend flag and do nothing. */
+ mf2_flags &= ~0x08;
+ write_byte(0x0040, 0x18, mf2_flags);
+ return;
+ }
+
+ if (scancode & 0x80) {
+ /* Set ack/resend flags if appropriate. */
+ if (scancode == 0xFA) {
+ flag = read_byte(0x0040, 0x97) | 0x10;
+ write_byte(0x0040, 0x97, flag);
+ } else if (scancode == 0xFE) {
+ flag = read_byte(0x0040, 0x97) | 0x20;
+ write_byte(0x0040, 0x97, flag);
+ }
+ break; /* toss key releases ... */
+ }
+ if (scancode > MAX_SCAN_CODE) {
+ BX_INFO("KBD: int09h_handler(): unknown scancode read: 0x%02x!\n", scancode);
+ return;
+ }
+ if (shift_flags & 0x08) { /* ALT */
+ asciicode = scan_to_scanascii[scancode].alt;
+ scancode = scan_to_scanascii[scancode].alt >> 8;
+ } else if (shift_flags & 0x04) { /* CONTROL */
+ asciicode = scan_to_scanascii[scancode].control;
+ scancode = scan_to_scanascii[scancode].control >> 8;
+ } else if (((mf2_state & 0x02) > 0) && ((scancode >= 0x47) && (scancode <= 0x53))) {
+ /* extended keys handling */
+ asciicode = 0xe0;
+ scancode = scan_to_scanascii[scancode].normal >> 8;
+ } else if (shift_flags & 0x03) { /* LSHIFT + RSHIFT */
+ /* check if lock state should be ignored
+ * because a SHIFT key are pressed */
+
+ if (shift_flags & scan_to_scanascii[scancode].lock_flags) {
+ asciicode = scan_to_scanascii[scancode].normal;
+ scancode = scan_to_scanascii[scancode].normal >> 8;
+ } else {
+ asciicode = scan_to_scanascii[scancode].shift;
+ scancode = scan_to_scanascii[scancode].shift >> 8;
+ }
+ } else {
+ /* check if lock is on */
+ if (shift_flags & scan_to_scanascii[scancode].lock_flags) {
+ asciicode = scan_to_scanascii[scancode].shift;
+ scancode = scan_to_scanascii[scancode].shift >> 8;
+ } else {
+ asciicode = scan_to_scanascii[scancode].normal;
+ scancode = scan_to_scanascii[scancode].normal >> 8;
+ }
+ }
+ if (scancode==0 && asciicode==0) {
+ BX_INFO("KBD: int09h_handler(): scancode & asciicode are zero?\n");
+ }
+ enqueue_key(scancode, asciicode);
+ break;
+ }
+ if ((scancode & 0x7f) != 0x1d) {
+ mf2_state &= ~0x01;
+ }
+ mf2_state &= ~0x02;
+ write_byte(0x0040, 0x96, mf2_state);
+}
+
+unsigned int dequeue_key(uint8_t __far *scan_code, uint8_t __far *ascii_code, unsigned incr)
+{
+ uint16_t buffer_start, buffer_end, buffer_head, buffer_tail;
+ uint8_t acode, scode;
+
+#if VBOX_BIOS_CPU >= 80286
+ buffer_start = read_word(0x0040, 0x0080);
+ buffer_end = read_word(0x0040, 0x0082);
+#else
+ buffer_start = 0x001E;
+ buffer_end = 0x003E;
+#endif
+
+ buffer_head = read_word(0x0040, 0x001a);
+ buffer_tail = read_word(0x0040, 0x001c);
+
+ if (buffer_head != buffer_tail) {
+ acode = read_byte(0x0040, buffer_head);
+ scode = read_byte(0x0040, buffer_head+1);
+ *ascii_code = acode;
+ *scan_code = scode;
+ BX_DEBUG_INT16("dequeue_key: ascii=%02x scan=%02x \n", acode, scode);
+
+ if (incr) {
+ buffer_head += 2;
+ if (buffer_head >= buffer_end)
+ buffer_head = buffer_start;
+ write_word(0x0040, 0x001a, buffer_head);
+ }
+ return(1);
+ }
+ else {
+ return(0);
+ }
+}
+
+
+/// @todo move somewhere else?
+#define AX r.gr.u.r16.ax
+#define BX r.gr.u.r16.bx
+#define CX r.gr.u.r16.cx
+#define DX r.gr.u.r16.dx
+#define SI r.gr.u.r16.si
+#define DI r.gr.u.r16.di
+#define BP r.gr.u.r16.bp
+#define SP r.gr.u.r16.sp
+#define FLAGS r.ra.flags.u.r16.flags
+#define IFLGS r.ifl
+
+/* Interrupt 16h service implementation. */
+
+void BIOSCALL int16_function(volatile kbd_regs_t r)
+{
+ uint8_t scan_code, ascii_code, shift_flags, led_flags, count;
+ uint16_t kbd_code, max;
+
+ BX_DEBUG_INT16("int16: AX=%04x BX=%04x CX=%04x DX=%04x \n", AX, BX, CX, DX);
+
+ shift_flags = read_byte(0x0040, 0x17);
+ led_flags = read_byte(0x0040, 0x97);
+ if ((((shift_flags >> 4) & 0x07) ^ (led_flags & 0x07)) != 0) {
+ int_disable(); /// @todo interrupts should be disabled already??
+ outb(0x60, 0xed);
+ while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21);
+ if ((inb(0x60) == 0xfa)) {
+ led_flags &= 0xc8;
+ led_flags |= ((shift_flags >> 4) & 0x07);
+ outb(0x60, led_flags & 0x07);
+ while ((inb(0x64) & 0x01) == 0)
+ outb(0x80, 0x21);
+ inb(0x60);
+ write_byte(0x0040, 0x97, led_flags);
+ }
+ int_enable();
+ }
+
+ switch (GET_AH()) {
+ case 0x00: /* read keyboard input */
+ if ( !dequeue_key(&scan_code, &ascii_code, 1) ) {
+ BX_PANIC("KBD: int16h: out of keyboard input\n");
+ }
+ if (scan_code !=0 && ascii_code == 0xF0)
+ ascii_code = 0;
+ else if (ascii_code == 0xE0)
+ ascii_code = 0;
+ AX = (scan_code << 8) | ascii_code;
+ break;
+
+ case 0x01: /* check keyboard status */
+ /* Enable interrupts, preserve most flags. Some callers depend on that! */
+ FLAGS = IFLGS;
+ if ( !dequeue_key(&scan_code, &ascii_code, 0) ) {
+ SET_ZF();
+ return;
+ }
+ if (scan_code !=0 && ascii_code == 0xF0)
+ ascii_code = 0;
+ else if (ascii_code == 0xE0)
+ ascii_code = 0;
+ AX = (scan_code << 8) | ascii_code;
+ CLEAR_ZF();
+ break;
+
+ case 0x02: /* get shift flag status */
+ shift_flags = read_byte(0x0040, 0x17);
+ SET_AL(shift_flags);
+ break;
+
+ case 0x05: /* store key-stroke into buffer */
+ if ( !enqueue_key(GET_CH(), GET_CL()) ) {
+ SET_AL(1);
+ }
+ else {
+ SET_AL(0);
+ }
+ break;
+
+ case 0x09: /* GET KEYBOARD FUNCTIONALITY */
+ // bit Bochs Description
+ // 7 0 reserved
+ // 6 0 INT 16/AH=20h-22h supported (122-key keyboard support)
+ // 5 1 INT 16/AH=10h-12h supported (enhanced keyboard support)
+ // 4 1 INT 16/AH=0Ah supported
+ // 3 0 INT 16/AX=0306h supported
+ // 2 0 INT 16/AX=0305h supported
+ // 1 0 INT 16/AX=0304h supported
+ // 0 0 INT 16/AX=0300h supported
+ //
+ SET_AL(0x30);
+ break;
+
+ case 0x0A: /* GET KEYBOARD ID */
+ count = 2;
+ kbd_code = 0x0;
+ /// @todo Might be better to just mask the KB interrupt
+ int_disable();
+ outb(0x60, 0xf2);
+ /* Wait for data */
+ max=0xffff;
+ while ( ((inb(0x64) & 0x01) == 0) && (--max>0) )
+ inb(0x80);
+ if (max>0x0) {
+ if ((inb(0x60) == 0xfa)) {
+ do {
+ max=0xffff;
+ while ( ((inb(0x64) & 0x01) == 0) && (--max>0) )
+ inb(0x80);
+ if (max>0x0) {
+ kbd_code >>= 8;
+ kbd_code |= (inb(0x60) << 8);
+ }
+ } while (--count>0);
+ }
+ }
+ BX=kbd_code;
+ break;
+
+ case 0x10: /* read MF-II keyboard input */
+ if ( !dequeue_key(&scan_code, &ascii_code, 1) ) {
+ BX_PANIC("KBD: int16h: out of keyboard input\n");
+ }
+ if (scan_code !=0 && ascii_code == 0xF0)
+ ascii_code = 0;
+ AX = (scan_code << 8) | ascii_code;
+ break;
+
+ case 0x11: /* check MF-II keyboard status */
+ /* Enable interrupts, preserve most flags. Some callers depend on that! */
+ FLAGS = IFLGS;
+ if ( !dequeue_key(&scan_code, &ascii_code, 0) ) {
+ SET_ZF();
+ return;
+ }
+ if (scan_code !=0 && ascii_code == 0xF0)
+ ascii_code = 0;
+ AX = (scan_code << 8) | ascii_code;
+ CLEAR_ZF();
+ break;
+
+ case 0x12: /* get extended keyboard status */
+ shift_flags = read_byte(0x0040, 0x17);
+ SET_AL(shift_flags);
+ shift_flags = read_byte(0x0040, 0x18) & 0x73;
+ shift_flags |= read_byte(0x0040, 0x96) & 0x0c;
+ SET_AH(shift_flags);
+ BX_DEBUG_INT16("int16: func 12 sending %04x\n",AX);
+ break;
+
+ case 0x92: /* keyboard capability check called by DOS 5.0+ keyb */
+ SET_AH(0x80); // function int16 ah=0x10-0x12 supported
+ break;
+
+ case 0xA2: /* 122 keys capability check called by DOS 5.0+ keyb */
+ // don't change AH : function int16 ah=0x20-0x22 NOT supported
+ break;
+
+ /// @todo what's the point of handling this??
+#if 0
+ case 0x6F:
+ if (GET_AL() == 0x08)
+ SET_AH(0x02); // unsupported, aka normal keyboard
+#endif
+
+ default:
+ BX_INFO("KBD: unsupported int 16h function %02x\n", GET_AH());
+ BX_INFO("AX=%04x BX=%04x CX=%04x DX=%04x \n", AX, BX, CX, DX);
+ }
+ BX_DEBUG_INT16("int16ex: AX=%04x BX=%04x CX=%04x DX=%04x \n", AX, BX, CX, DX);
+}
diff --git a/src/VBox/Devices/PC/BIOS/logo.c b/src/VBox/Devices/PC/BIOS/logo.c
new file mode 100644
index 00000000..9a82ef11
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/logo.c
@@ -0,0 +1,558 @@
+/* $Id: logo.c $ */
+/** @file
+ * Stuff for drawing the BIOS logo.
+ */
+
+/*
+ * Copyright (C) 2004-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <stdint.h>
+#include "biosint.h"
+#include "inlines.h"
+#include "ebda.h"
+
+#define WAIT_HZ 64
+#define WAIT_MS 16
+
+#define F12_SCAN_CODE 0x86
+#define F12_WAIT_TIME (3 * WAIT_HZ) /* 3 seconds. Used only if logo disabled. */
+
+#include <VBox/bioslogo.h>
+
+/**
+ * Set video mode (VGA).
+ * @param mode New video mode.
+ */
+void set_mode(uint8_t mode);
+#pragma aux set_mode = \
+ "mov ah, 0" \
+ "int 10h" \
+ parm [al] modify [ax] nomemory;
+
+
+/**
+ * Set VESA video mode.
+ * @param mode New video mode.
+ */
+uint16_t vesa_set_mode(uint16_t mode);
+#pragma aux vesa_set_mode = \
+ "mov ax, 4F02h" \
+ "int 10h" \
+ parm [bx] modify [ax] nomemory;
+
+/**
+ * Get current VESA video mode.
+ * @param mode New video mode.
+ */
+uint16_t vesa_get_mode(uint16_t __far *mode);
+#pragma aux vesa_get_mode = \
+ "mov ax, 4F03h" \
+ "int 10h" \
+ "mov es:[di], bx" \
+ parm [es di] modify [ax bx] nomemory;
+
+
+/**
+ * Set custom video mode.
+ * @param xres Requested width
+ * @param yres Requested height
+ * @param bpp Requested bits per pixel
+ */
+uint16_t custom_set_mode(uint16_t xres, uint16_t yres, uint8_t bpp);
+#pragma aux custom_set_mode = \
+ "mov ax, 5642h" \
+ "mov bl, 0" \
+ "int 10h" \
+ parm [cx] [dx] [bh] modify [ax] nomemory;
+
+/**
+ * Check for keystroke.
+ * @returns True if keystroke available, False if not.
+ */
+/// @todo INT 16h should already be returning the right value in al; could also use setz
+uint8_t check_for_keystroke(void);
+#pragma aux check_for_keystroke = \
+ "mov ax, 100h" \
+ "int 16h" \
+ "jz no_key" \
+ "mov al, 1" \
+ "jmp done" \
+ "no_key:" \
+ "xor al, al" \
+ "done:" \
+ modify [ax] nomemory;
+
+
+/**
+ * Get keystroke.
+ * @returns BIOS scan code.
+ */
+uint8_t get_keystroke(void);
+#pragma aux get_keystroke = \
+ "xor ax, ax" \
+ "int 16h" \
+ "xchg ah, al" \
+ modify [ax] nomemory;
+
+
+/// @todo This whole business with reprogramming the PIT is rather suspect.
+// The BIOS already has waiting facilities in INT 15h (fn 83h, 86h) which
+// should be utilized instead.
+
+// Set the timer to 16ms ticks (64K / (Hz / (PIT_HZ / 64K)) = count).
+void wait_init(void);
+#pragma aux wait_init = \
+ "mov al, 34h" \
+ "out 43h, al" \
+ "mov al, 0D3h" \
+ "out 40h, al" \
+ "mov al, 048h" \
+ "out 40h, al" \
+ modify [ax] nomemory;
+
+/// @todo using this private interface is not great
+extern void rtc_post(void);
+#pragma aux rtc_post "*";
+
+/* Restore the timer to the default 18.2Hz. Reinitialize the tick
+ * and rollover counts since we've screwed them up by running the
+ * timer at WAIT_HZ for a while.
+ */
+void wait_uninit(void);
+#if VBOX_BIOS_CPU >= 80386
+# pragma aux wait_uninit = \
+ ".386" \
+ "mov al, 34h" \
+ "out 43h, al" \
+ "xor ax, ax" \
+ "out 40h, al" \
+ "out 40h, al" \
+ "pushad" \
+ "push ds" \
+ "mov ds, ax" \
+ "call rtc_post" \
+ "pop ds" \
+ "popad" \
+ modify [ax] nomemory;
+#else
+# pragma aux wait_uninit = \
+ "mov al, 34h" \
+ "out 43h, al" \
+ "xor ax, ax" \
+ "out 40h, al" \
+ "out 40h, al" \
+ "push bp" \
+ "push ds" \
+ "mov ds, ax" \
+ "call rtc_post" \
+ "pop ds" \
+ "pop bp" \
+ modify [ax bx cx dx si di];
+#endif
+
+
+/**
+ * Waits (sleeps) for the given number of ticks.
+ * Checks for keystroke.
+ *
+ * @returns BIOS scan code if available, 0 if not.
+ * @param ticks Number of ticks to sleep.
+ * @param stop_on_key Whether to stop immediately upon keypress.
+ */
+uint8_t wait(uint16_t ticks, uint8_t stop_on_key)
+{
+ long ticks_to_wait, delta;
+ uint16_t old_flags;
+ uint32_t prev_ticks, t;
+ uint8_t scan_code = 0;
+
+ /*
+ * We may or may not be called with interrupts disabled. For the duration
+ * of this function, interrupts must be enabled.
+ */
+ old_flags = int_query();
+ int_enable();
+
+ /*
+ * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock.
+ * We also have to be careful about interrupt storms.
+ */
+ ticks_to_wait = ticks;
+ prev_ticks = read_dword(0x0, 0x46c);
+ do
+ {
+ halt();
+ t = read_dword(0x0, 0x46c);
+ if (t > prev_ticks)
+ {
+ delta = t - prev_ticks; /* The temp var is required or bcc screws up. */
+ ticks_to_wait -= delta;
+ }
+ else if (t < prev_ticks)
+ ticks_to_wait -= t; /* wrapped */
+ prev_ticks = t;
+
+ if (check_for_keystroke())
+ {
+ scan_code = get_keystroke();
+ bios_printf(BIOS_PRINTF_INFO, "Key pressed: %x\n", scan_code);
+ if (stop_on_key)
+ return scan_code;
+ }
+ } while (ticks_to_wait > 0);
+ int_restore(old_flags);
+ return scan_code;
+}
+
+uint8_t read_logo_byte(uint8_t offset)
+{
+ outw(LOGO_IO_PORT, LOGO_CMD_SET_OFFSET | offset);
+ return inb(LOGO_IO_PORT);
+}
+
+uint16_t read_logo_word(uint8_t offset)
+{
+ outw(LOGO_IO_PORT, LOGO_CMD_SET_OFFSET | offset);
+ return inw(LOGO_IO_PORT);
+}
+
+// Hide cursor, clear screen and move cursor to starting position
+void clear_screen(void);
+#pragma aux clear_screen = \
+ "mov ax, 100h" \
+ "mov cx, 1000h" \
+ "int 10h" \
+ "mov ax, 700h" \
+ "mov bh, 7" \
+ "xor cx, cx" \
+ "mov dx, 184Fh" \
+ "int 10h" \
+ "mov ax, 200h" \
+ "xor bx, bx" \
+ "xor dx, dx" \
+ "int 10h" \
+ modify [ax bx cx dx] nomemory;
+
+void print_detected_harddisks(void)
+{
+ uint16_t ebda_seg=read_word(0x0040,0x000E);
+ uint8_t hd_count;
+ uint8_t hd_curr = 0;
+ uint8_t ide_ctrl_printed = 0;
+ uint8_t sata_ctrl_printed = 0;
+ uint8_t scsi_ctrl_printed = 0;
+ uint8_t device;
+
+ hd_count = read_byte(ebda_seg, (uint16_t)&EbdaData->bdisk.hdcount);
+
+ for (hd_curr = 0; hd_curr < hd_count; hd_curr++)
+ {
+ device = read_byte(ebda_seg, (uint16_t)&EbdaData->bdisk.hdidmap[hd_curr]);
+
+#ifdef VBOX_WITH_AHCI
+ if (VBOX_IS_AHCI_DEVICE(device))
+ {
+ if (sata_ctrl_printed == 0)
+ {
+ printf("\n\n AHCI controller:");
+ sata_ctrl_printed = 1;
+ }
+
+ printf("\n %d) Hard disk", hd_curr+1);
+
+ }
+ else
+#endif
+#ifdef VBOX_WITH_SCSI
+ if (VBOX_IS_SCSI_DEVICE(device))
+ {
+ if (scsi_ctrl_printed == 0)
+ {
+ printf("\n\n SCSI controller:");
+ scsi_ctrl_printed = 1;
+ }
+
+ printf("\n %d) Hard disk", hd_curr+1);
+
+ }
+ else
+#endif
+ {
+
+ if ((device < 4) && (ide_ctrl_printed == 0))
+ {
+ printf(" IDE controller:");
+ ide_ctrl_printed = 1;
+ }
+ else if ((device >= 4) && (sata_ctrl_printed == 0))
+ {
+ printf("\n\nAHCI controller:\n");
+ sata_ctrl_printed = 1;
+ }
+
+ printf("\n %d) ", hd_curr+1);
+
+ /*
+ * If actual_device is bigger than or equal 4
+ * this is the next controller and
+ * the positions start at the beginning.
+ */
+ if (device >= 4)
+ device -= 4;
+
+ if (device / 2)
+ printf("Secondary ");
+ else
+ printf("Primary ");
+
+ if (device % 2)
+ printf("Slave");
+ else
+ printf("Master");
+ }
+ }
+
+ if ( (ide_ctrl_printed == 0)
+ && (sata_ctrl_printed == 0)
+ && (scsi_ctrl_printed == 0))
+ printf("No hard disks found");
+
+ printf("\n");
+}
+
+uint8_t get_boot_drive(uint8_t scode)
+{
+ uint16_t ebda_seg=read_word(0x0040,0x000E);
+
+ /* Check that the scan code is in the range of detected hard disks. */
+ uint8_t hd_count = read_byte(ebda_seg, (uint16_t)&EbdaData->bdisk.hdcount);
+
+ /* The key '1' has scancode 0x02 which represents the first disk */
+ scode -= 2;
+
+ if (scode < hd_count)
+ return scode;
+
+ /* Scancode is higher than number of available devices */
+ return 0xff;
+}
+
+void show_logo(void)
+{
+ uint16_t ebda_seg = read_word(0x0040,0x000E);
+ uint8_t f12_pressed = 0;
+ uint8_t scode;
+ uint16_t tmp, i;
+
+ LOGOHDR *logo_hdr = 0;
+ uint8_t is_fade_in, is_fade_out, uBootMenu;
+ uint16_t logo_time;
+ uint16_t old_mode;
+
+
+ // Set PIT to 64hz.
+ wait_init();
+
+ // Get main signature
+ tmp = read_logo_word((uint8_t)&logo_hdr->u16Signature);
+ if (tmp != 0x66BB)
+ goto done;
+
+ // If there is no VBE, just skip this
+ if (vesa_get_mode(&old_mode) != 0x004f )
+ goto done;
+
+ // Get options
+ is_fade_in = read_logo_byte((uint8_t)&logo_hdr->fu8FadeIn);
+ is_fade_out = read_logo_byte((uint8_t)&logo_hdr->fu8FadeOut);
+ logo_time = read_logo_word((uint8_t)&logo_hdr->u16LogoMillies);
+ uBootMenu = read_logo_byte((uint8_t)&logo_hdr->fu8ShowBootMenu);
+
+ // Is Logo disabled?
+ if (!is_fade_in && !is_fade_out && !logo_time)
+ goto done;
+
+ /* Set video mode using private video BIOS interface. */
+ tmp = custom_set_mode(640, 480, 32);
+ /* If custom mode set failed, fall back to VBE. */
+ if (tmp != 0x4F)
+ vesa_set_mode(0x142);
+
+ if (is_fade_in)
+ {
+ for (i = 0; i <= LOGO_SHOW_STEPS; i++)
+ {
+ outw(LOGO_IO_PORT, LOGO_CMD_SHOW_BMP | i);
+ scode = wait(16 / WAIT_MS, 0);
+ if (scode == F12_SCAN_CODE)
+ {
+ f12_pressed = 1;
+ break;
+ }
+ }
+ }
+ else
+ outw(LOGO_IO_PORT, LOGO_CMD_SHOW_BMP | LOGO_SHOW_STEPS);
+
+ // Wait (interval in milliseconds)
+ if (!f12_pressed)
+ {
+ scode = wait(logo_time / WAIT_MS, 1);
+ if (scode == F12_SCAN_CODE)
+ f12_pressed = 1;
+ }
+
+ // Fade out (only if F12 was not pressed)
+ if (is_fade_out && !f12_pressed)
+ {
+ for (i = LOGO_SHOW_STEPS; i > 0 ; i--)
+ {
+ outw(LOGO_IO_PORT, LOGO_CMD_SHOW_BMP | i);
+ scode = wait(16 / WAIT_MS, 0);
+ if (scode == F12_SCAN_CODE)
+ {
+ f12_pressed = 1;
+ break;
+ }
+ }
+ }
+ else if (!f12_pressed)
+ outw(LOGO_IO_PORT, LOGO_CMD_SHOW_BMP | 0);
+
+done:
+ // Clear forced boot drive setting.
+ write_byte(ebda_seg, (uint16_t)&EbdaData->uForceBootDevice, 0);
+
+ // Don't restore previous video mode
+ // The default text mode should be set up. (defect @bugref{1235})
+ set_mode(0x0003);
+
+ // If Setup menu enabled
+ if (uBootMenu)
+ {
+ // If the graphics logo disabled
+ if (!is_fade_in && !is_fade_out && !logo_time)
+ {
+ if (uBootMenu == 2)
+ printf("Press F12 to select boot device.\n");
+
+ // if the user has pressed F12 don't wait here
+ if (!f12_pressed)
+ {
+ // Wait for timeout or keystroke
+ scode = wait(F12_WAIT_TIME, 1);
+ if (scode == F12_SCAN_CODE)
+ f12_pressed = 1;
+ }
+ }
+
+ // If F12 pressed, show boot menu
+ if (f12_pressed)
+ {
+ uint8_t boot_device = 0;
+ uint8_t boot_drive = 0;
+
+ clear_screen();
+
+ // Show menu. Note that some versions of bcc freak out if we split these strings.
+ printf("\nVirtualBox temporary boot device selection\n\nDetected Hard disks:\n\n");
+ print_detected_harddisks();
+ printf("\nOther boot devices:\n f) Floppy\n c) CD-ROM\n l) LAN\n\n b) Continue booting\n");
+
+
+
+ // Wait for keystroke
+ for (;;)
+ {
+ do
+ {
+ scode = wait(WAIT_HZ, 1);
+ } while (scode == 0);
+
+ if (scode == 0x30)
+ {
+ // 'b' ... continue
+ break;
+ }
+
+ // Check if hard disk was selected
+ if ((scode >= 0x02) && (scode <= 0x09))
+ {
+ boot_drive = get_boot_drive(scode);
+
+ /*
+ * 0xff indicates that there is no mapping
+ * from the scan code to a hard drive.
+ * Wait for next keystroke.
+ */
+ if (boot_drive == 0xff)
+ continue;
+
+ write_byte(ebda_seg, (uint16_t)&EbdaData->uForceBootDrive, boot_drive);
+ boot_device = 0x02;
+ break;
+ }
+
+ switch (scode)
+ {
+ case 0x21:
+ // Floppy
+ boot_device = 0x01;
+ break;
+ case 0x2e:
+ // CD-ROM
+ boot_device = 0x03;
+ break;
+ case 0x26:
+ // LAN
+ boot_device = 0x04;
+ break;
+ }
+
+ if (boot_device != 0)
+ break;
+ }
+
+ write_byte(ebda_seg, (uint16_t)&EbdaData->uForceBootDevice, boot_device);
+
+ // Switch to text mode. Clears screen and enables cursor again.
+ set_mode(0x0003);
+ }
+ }
+
+ // Restore PIT ticks
+ wait_uninit();
+
+ return;
+}
+
+
+void delay_boot(uint16_t secs)
+{
+ uint16_t i;
+
+ if (!secs)
+ return;
+
+ // Set PIT to 1ms ticks
+ wait_init();
+
+ printf("Delaying boot for %d seconds:", secs);
+ for (i = secs; i > 0; i--)
+ {
+ printf(" %d", i);
+ wait(WAIT_HZ, 0);
+ }
+ printf("\n");
+ // Restore PIT ticks
+ wait_uninit();
+}
diff --git a/src/VBox/Devices/PC/BIOS/makefile b/src/VBox/Devices/PC/BIOS/makefile
new file mode 100644
index 00000000..40d0f4ad
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/makefile
@@ -0,0 +1,72 @@
+# Compiler flags:
+# -q no banner
+# -wx max warnings
+# -0 generate 8086 code
+# -ms force small model (default)
+# -s remove runtime stack checks (required)
+# -os optimize for size
+# -zu assume that SS != DS (required)
+# -ecc default to __cdecl calling convention (bad idea)
+#
+!ifdef __UNIX__
+Q=\"
+!else
+Q="
+!endif
+
+CPU = 386
+
+CFLAGS = -q -0 -wx -zu -s -oas -d1+ -ms
+CFLAGS32 = -q -wx -zu -s -oas -d1+ -ms -nt=BIOS32 -nd=BIOS32
+# -oat seems to prevent ENTER/LEAVE generation
+#CFLAGS32 = -q -wx -zu -s -oat -d1+ -ms -nt=BIOS32 -nd=BIOS32
+
+DEFS = -DVBOX -DVBOX_LANBOOT_SEG=0xE200 -DVBOX_VERSION_STRING=$(Q)0.9$(Q) &
+ -DVBOX_WITH_SCSI -DVBOX_BIOS_CPU=80386
+
+AFLAGS = -q -0 -wx
+
+INCLS = -I$(Q)../../../../../include$(Q) -I$(Q) ../../BiosCommonCode$(Q)
+
+OBJS = bios.obj post.obj ata.obj floppy.obj floppyt.obj eltorito.obj &
+ boot.obj keyboard.obj disk.obj serial.obj system.obj invop.obj &
+ timepci.obj logo.obj ps2mouse.obj parallel.obj scsi.obj &
+ apm.obj apm_pm.obj pcibios.obj pciutil.obj vds.obj &
+ print.obj pcibio32.obj pci32.obj orgs.obj
+
+!if $(CPU) > 286
+OBJS += ahci.obj
+DEFS += -DVBOX_WITH_AHCI
+!endif
+
+.c.obj : .autodepend
+ wcc -fo=.obj $(CFLAGS) $(DEFS) $(INCLS) $<
+
+.asm.obj : .autodepend
+ wasm -fo=.obj $(AFLAGS) $(DEFS) $(INCLS) $<
+
+vbxbios.rom : vbxbios.bin
+ biossums $< $@
+
+vbxbios.bin : $(OBJS) $(__MAKEFILES__)
+ wlink name $@ system dos debug all option quiet &
+ option nofarcalls, map, verbose, statics, symfile &
+ output raw offset=0xF0000 order &
+ clname DATA segaddr=0xF000 segment _DATA &
+ clname CODE &
+ segment _TEXT segaddr=0xF000 offset=0x1C00 &
+ segment BIOS32 segaddr=0xF000 offset=0xDB00 &
+ segment BIOSSEG segaddr=0xF000 offset=0xE000 &
+ file { $(OBJS) } &
+ library clibs.lib &
+ disable 1014, 1023, 2120
+
+logo.obj : logo.c .autodepend
+ wcc -fo=.obj $(INCLS) $(CFLAGS) $(DEFS) -DVBOX_PC_BIOS $<
+
+pci32.obj : pci32.c .autodepend
+ wcc386 -fo=.obj $(INCLS) $(DEFS) $(CFLAGS32) $<
+
+clean : .symbolic
+ @rm -f *.obj *.err
+ @rm -f vbxbios.bin vbxbios.rom vbxbios.map vbxbios.sym
diff --git a/src/VBox/Devices/PC/BIOS/notes.txt b/src/VBox/Devices/PC/BIOS/notes.txt
new file mode 100644
index 00000000..2861cb8b
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/notes.txt
@@ -0,0 +1,195 @@
+
+ Notes on BIOS usage
+ -------------------
+
+- DOS (including 6.22/7.1) does not need INT 15h or INT 1Ah. Most other
+ operating systems require INT 15h to detect installed memory.
+
+- OS/2 (WSeB/MCP/ACP) and Windows 98 SE are some of the very few operating
+ systems which use the El Torito floppy emulation.
+
+- NetWare 5.1 is one of the *extremely* few users of El Torito hard disk
+ emulation.
+
+- Keystroke check (INT 16h, fn 01h/11h) always enables interrupts on return.
+ DOS POWER.EXE depends on that in some situations.
+
+- IBM DOS J5.00/V is even worse and does a far jump into INT 16h/11h after
+ pushing garbage on the stack. Using IRET directly may change IOPL, set
+ TF, change direction flag, etc. We have to use or simulate RETF 2 instead.
+
+- MS-DOS 5.0/V setup assumes that INT 13h always returns with interrupts
+ enabled.
+
+- INT 15h also always returns with interrupts enabled (even for unsupported
+ functions).
+
+- MS-DOS 6.2/V is a rare user of the INT 15h keyboard intercept routines.
+
+- Some software uses the model byte at F000:FFFE to determine the system
+ type (PC-DOS 3.0, Norton Utilities 8). Other software first tries INT 15h,
+ fn C0h instead (PC-DOS 3.1, MSD).
+
+- DOS 4.01 (both IBM and Microsoft) calls INT 13h to read from disk with less
+ than 100 bytes of stack space early in the boot sequence. This tends to be
+ a problem especially for the SATA and SCSI code paths.
+
+- Very few guests use the 32-bit PCI BIOS interface. One is OS/2 (but falls
+ back), another is Etherboot.
+
+- OS/2 is the only known guest which can run the 16-bit PCI BIOS in protected
+ mode (but only if the 32-bit PCI BIOS is unavailable).
+
+- NetWare 6.x is the only known guest which uses the PCI BIOS service to read
+ the IRQ routing table.
+
+- Any disk reads which use bus-master DMA (AHCI, IDE BM) must use VDS
+ (Virtual DMA Services) when present. Otherwise any reads/writes when the
+ real mode addresses don't map directly to physical addresses will fail
+ horribly. DOS 6.x with EMM386 is a good testcase (esp. loading drivers
+ into UMBs).
+
+- Many older OSes (especially UNIX based) require the FDPT to contain
+ physical ATA disk geometry; for that reason, disks smaller than ~500MB are
+ easiest to use. Otherwise a "large" BIOS disk option would be required.
+
+- Some really old OSes (Xenix circa 1986-7) do not understand the EBDA idea
+ and clear the memory. For those, the FDPT must be in the BIOS ROM area, or
+ the OS will destroy it (even when it's at 0:300 in the IVT).
+
+- NetWare 2.15 has a similar restriction, the FDPT must explicitly point above
+ segment address C800 or the NetWare AT disk driver abends.
+
+- Windows NT (including XP) uses INT 13h/08h to obtain the DPT for each floppy
+ drive. NT assumes a 13-byte DPT which includes the number of tracks. NT will
+ refuse to read more tracks than the DPT specifies and formats as many tracks
+ as the DPT specifies.
+
+- Windows 98 SE boot CD uses 32-bit registers in real mode and will fail in
+ mysterious ways if BIOS trashes high bits of EAX (and likely others).
+
+- PC DOS 6.x/7.x QCONFIG is a rare user of INT 16h fn 0Ah (read keyboard ID).
+
+- DOS POWER.EXE uses the real mode APM interface, OS/2 APM.SYS uses the 16-bit
+ protected mode APM interface, and Windows 9x uses the 32-bit protected mode
+ APM interface.
+
+- Windows 98 is one of the few APM 1.2 users; Windows 95 uses APM 1.1, while
+ newer systems prefer ACPI.
+
+- QNX4 calls 16-bit protected-mode PCI BIOS in an environment where ESP is
+ 16-bit but SS is a 32-bit stack segment. In such environments, using the
+ ENTER/LEAVE sequence is fatal if the high word of EBP is non-zero (which
+ it will be with QNX 4.25). LEAVE propagates the high word of EBP into ESP
+ with fatal consequences.
+
+- Plan 9 also runs 16-bit code with a 32-bit stack segment, except Plan 9
+ thinks it counts as real mode. Same ENTER/LEAVE problem as above.
+
+- AIX 1.3 is a rare user of INT 15h/89h (switch to protected mode) service.
+
+- IBM OS/2 1.0/1.1 (but not other versions!) attempt to execute a 286 LOADALL
+ instruction. LOADALL must be emulated for OS/2 to work properly. HIMEM.SYS
+ version 2.03 and later also contains 286 LOADALL code but this will not be
+ executed on 386+ processors.
+
+- IBM and Microsoft OS/2 1.0 use CMOS shutdown status 9 to get back from
+ protected mode without having called INT 15h/87h at all. That makes the
+ status 9 handling a public interface (just like codes 5 and 0Ah) which
+ has to be compatible with other BIOS implementations.
+
+- Windows NT 3.5 and 3.51 with MPS HAL requires that INT 15h/E820h return the
+ I/O APIC range as reserved, or not return any ranges at all just below 4GB.
+ Otherwise the NT kernel will crash early during init due to confusion about
+ the top of memory.
+
+- Darwin x86 6.0.2 ISO (darwinx86-602.iso) has a bizarre boot sector (using
+ El Torito hard disk emulation) with the first five bytes being zero. It
+ appears to be valid despite the oddity.
+
+- Darwin 6.0.2 also uses an El Torito emulated hard disk. In addition, if
+ INT 13h/41h succeeds, Darwin uses INT13X to read from the emulated drive.
+
+- Symantec Ghost 11.5 bootable CD also uses El Torito hard disk emulation,
+ uses INT13X without checking for support, and crashes if INT13X is not
+ supported on the emulated drive.
+
+
+ 286 BIOS
+ --------
+
+ For testing purposes, it's quite useful to have a BIOS that can run in a
+classic PC/AT environment with a 286 CPU. This forces various changes, not
+always obvious:
+
+ - C code can be easily compiled to produce 286-compatible object code
+
+ - 32-bit BIOS services such as APM or PCI BIOS are irrelevant
+
+ - PCI cannot be supported because it requires 32-bit port I/O
+
+ - AHCI cannot be supported because it requires 32-bit port I/O and PCI
+
+ - Switching to protected mode must be done using LMSW instead of CR0
+
+ - Switching back to real mode must reset the CPU (currently triple fault)
+ and regain control by setting up the CMOS shutdown status byte
+
+
+
+ Notes on BIOS implementation
+ ----------------------------
+
+- To return values from functions not declared as __interrupt, the arguments
+ may need to be declared volatile (not ideal, but does the job).
+
+- The way the POST code selectively clears or doesn't clear memory
+ is extremely suspect and will need reworking.
+
+- Need to review string routines wrt direction flag (should be OK now).
+
+- Need to review CMOS access wrt interrupts (possible index reg change by
+ an interrupt handler).
+
+- The POST code zeroes the entire BDA, and then various bits zero specific
+ parts of the BDA again. That's a waste of time.
+
+- After a reset, all interrupts are unmasked. Not sure if that's OK.
+
+- BCC mishandles the following (where buf is an uint8_t array):
+ lba=buf[0x2B]*0x1000000+buf[0x2A]*0x10000+buf[0x29]*0x100+buf[0x28];
+ The buf[x]*100 expression should end up being of type signed int, which
+ causes the sign to be incorrectly propagated. BCC incorrectly keeps
+ the type unsigned.
+
+- The PCI BIOS services are implemented in C, compiled twice as 16-bit and
+ 32-bit code. This reduces the development effort and significantly lowers
+ the risk of discrepancies between 16-bit and 32-bit implementation. Care
+ must be taken because the 16-bit implementation can be executed in both
+ real and protected mode.
+
+- APM can be in theory implemented only once for real, 16-bit protected and
+ 32-bit protected mode. Unfortunately this is very inconvenient in C since
+ the default stack size changes between 16-bit and 32-bit callers. Therefore
+ real mode APM (which supports most functions) is implemented in C and
+ protected-mode APM is written in assembler for both 16-bit and 32-bit calls,
+ with a small 32->16 thunk.
+
+- The -of switch can be used to avoid generating ENTER/LEAVE instructions.
+ This appears to be an undocumented and perhaps unintentional side effect.
+
+
+ Code size notes (code as of 7/6/2011):
+
+ The following values are the size of the _TEXT segment, i.e. only C code;
+data defined in C is not included, neither are assembly modules.
+
+ Options: Size (hex):
+ -------- -----------
+ -0 -zu -s -oas -ecc 631A
+ -3 -zu -s -oas -ecc 5C1E
+ -0 -zu -s -oas 578A
+ -3 -zu -s -oas 5452
+
+ Both generating 386 code and using register-based calling convention for
+internal functions brings significant size savings (15% when combined).
diff --git a/src/VBox/Devices/PC/BIOS/orgs.asm b/src/VBox/Devices/PC/BIOS/orgs.asm
new file mode 100644
index 00000000..1706b71d
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/orgs.asm
@@ -0,0 +1,2069 @@
+; $Id: orgs.asm $
+;; @file
+; ???
+;
+
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+; other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+; a choice of LGPL license versions is made available with the language indicating
+; that LGPLv2 or any later version may be used, or where a choice of which version
+; of the LGPL is applied is otherwise unspecified.
+
+
+include commondefs.inc
+
+EBDA_SEG equ 09FC0h ; starts at 639K
+EBDA_SIZE equ 1 ; 1K
+BASE_MEM_IN_K equ (640 - EBDA_SIZE)
+
+CMOS_ADDR equ 070h
+CMOS_DATA equ 071h
+
+
+PIC_CMD_EOI equ 020h
+PIC_MASTER equ 020h
+PIC_SLAVE equ 0A0h
+
+BIOS_FIX_BASE equ 0E000h
+
+if VBOX_BIOS_CPU ge 80286
+SYS_MODEL_ID equ 0FCh ; PC/AT
+else
+SYS_MODEL_ID equ 0FBh ; PC/XT
+endif
+SYS_SUBMODEL_ID equ 0
+BIOS_REVISION equ 1
+
+BIOS_BUILD_DATE equ '06/23/99'
+BIOS_COPYRIGHT equ 'Oracle VM VirtualBox BIOS'
+
+BX_ROMBIOS32 equ 0
+BX_CALL_INT15_4F equ 1
+
+;; Set a fixed BIOS location, with a marker for verification
+BIOSORG macro addr, addr_minus_two
+.errnz (addr - 2 - addr_minus_two) ;; Couldn't convince wasm to accept $ here. Would've save us a lot of bother and ugly SED.
+ BIOSORG_CHECK_BEFORE addr_minus_two
+ org addr - BIOS_FIX_BASE - 2
+ db 'XM'
+ BIOSORG_CHECK addr
+ endm
+
+;; Set an interrupt vector (not very efficient if multiple vectors are
+;; programmed in one go)
+SET_INT_VECTOR macro vec, segm, offs
+ mov ax, offs
+ mov ds:[vec*4], ax
+ mov ax, segm
+ mov ds:[vec*4+2], ax
+endm
+
+; Set up an environment C code expects. DS must point to the BIOS segment
+; and the direction flag must be cleared(!)
+C_SETUP macro
+ push cs
+ pop ds
+ cld
+endm
+
+
+;; External function in separate modules
+extrn _dummy_isr_function:near
+extrn _log_bios_start:near
+extrn _nmi_handler_msg:near
+extrn _int18_panic_msg:near
+extrn _int09_function:near
+extrn _int13_diskette_function:near
+extrn _int13_eltorito:near
+extrn _int13_cdemu:near
+extrn _int13_cdrom:near
+extrn _cdemu_isactive:near
+extrn _cdemu_emulated_drive:near
+extrn _int13_harddisk:near
+extrn _int13_harddisk_ext:near
+extrn _int14_function:near
+extrn _int15_function:near
+extrn _int15_function_mouse:near
+extrn _int16_function:near
+extrn _int17_function:near
+extrn _int19_function:near
+extrn _int1a_function:near
+extrn _pci16_function:near
+extrn _int70_function:near
+extrn _int74_function:near
+extrn _apm_function:near
+extrn _ata_init:near
+extrn _scsi_init:near
+extrn _ata_detect:near
+extrn _cdemu_init:near
+extrn _keyboard_init:near
+extrn _print_bios_banner:near
+extrn _inv_op_handler:near
+extrn rom_scan_:near
+ifdef VBOX_WITH_AHCI
+extrn _ahci_init:near
+endif
+if VBOX_BIOS_CPU ge 80286
+extrn _int15_blkmove:near
+endif
+if VBOX_BIOS_CPU ge 80386
+extrn _int15_function32:near
+extrn _apic_setup:near
+endif
+
+
+;; Symbols referenced from C code
+public _diskette_param_table
+public _pmode_IDT
+public _rmode_IDT
+public post
+public eoi_both_pics
+public rtc_post
+
+;; Additional publics for easier disassembly and debugging
+ifndef DEBUG
+ DEBUG equ 1
+endif
+ifdef DEBUG
+
+public int08_handler
+public int0e_handler
+public int11_handler
+public int12_handler
+public int13_handler
+public int13_relocated
+if VBOX_BIOS_CPU eq 8086
+public jmp_call_ret_int13_out
+endif
+public int15_handler
+public int17_handler
+public int19_handler
+public int19_relocated
+public dummy_iret
+public nmi
+public rom_fdpt
+public cpu_reset
+public normal_post
+public eoi_jmp_post
+public no_eoi_jmp_post
+public eoi_master_pic
+public ebda_post
+public seg_40_value
+public hard_drive_post
+public int13_legacy
+public int70_handler
+public int75_handler
+public int15_handler32
+public int15_handler_mouse
+public iret_modify_cf
+public init_pic
+public floppy_post
+public int13_out
+public int13_disk
+public int13_notfloppy
+public int13_legacy
+public int13_noeltorito
+public int1c_handler
+public int10_handler
+public int74_handler
+public int76_handler
+public detect_parport
+public detect_serial
+public font8x8
+
+endif
+
+;; Keyboard related constants
+KBDC_DISABLE EQU 0ADh
+KBDC_ENABLE EQU 0AEh
+KBC_CMD EQU 64h
+KBC_DATA EQU 60h
+
+
+;; NOTE: The last 8K of the ROM BIOS are peppered with fixed locations which
+;; must be retained for compatibility. As a consequence, some of the space is
+;; going to be wasted, but the gaps should be filled with miscellaneous code
+;; and data when possible.
+
+SET_DEFAULT_CPU_286
+
+BIOSSEG segment 'CODE'
+ assume cs:BIOSSEG
+
+;;
+;; Start of fixed code - eoi_jmp_post is kept near here to allow short jumps.
+;;
+ BIOSORG 0E030h, 0E02Eh
+eoi_both_pics:
+ mov al, PIC_CMD_EOI
+ out PIC_SLAVE, al
+eoi_master_pic:
+ mov al, PIC_CMD_EOI
+ out PIC_MASTER, al
+ ret
+
+ ;; routine to write the pointer in DX:AX to memory starting
+ ;; at DS:BX (repeat CX times)
+ ;; - modifies BX, CX
+set_int_vects proc near
+
+ mov [bx], ax
+ mov [bx+2], dx
+ add bx, 4
+ loop set_int_vects
+ ret
+
+set_int_vects endp
+
+eoi_jmp_post:
+;; Calling eoi_both_pics can't be done because it writes to stack, potentially
+;; corrupting memory. AT BIOS also only clears the master PIC, not both.
+ ;; clear keyboard buffer (and possible interrupt)
+ in al, KBC_DATA
+ mov al, PIC_CMD_EOI
+ out PIC_MASTER, al
+
+no_eoi_jmp_post:
+ mov ax, 40h
+ mov ds, ax
+ jmp dword ptr ds:[67h]
+
+seg_40_value: dw 40h ;; Replaces a push 40; pop ds.
+
+;; --------------------------------------------------------
+;; POST entry point
+;; --------------------------------------------------------
+ BIOSORG 0E05Bh, 0E059h
+post:
+ cli
+
+if VBOX_BIOS_CPU ge 80286
+ ;; Check if in protected (V86) mode. If so, the CPU needs
+ ;; to be reset.
+ .286p
+ smsw ax
+ test ax, 1
+ jz in_real_mode
+ SET_DEFAULT_CPU_286
+else
+ jmp in_real_mode
+endif
+
+ ;; Reset processor to get out of protected mode. Use system
+ ;; port instead of KBC.
+reset_sys:
+ mov al, 1
+ out 92h, al
+ jmp $ ; not strictly necessary in a VM
+
+
+in_real_mode:
+ ;; read the CMOS shutdown status
+ mov al, 0Fh
+ out CMOS_ADDR, al
+ in al, CMOS_DATA
+
+ ;; save status
+ xchg ah, al
+
+ ;; Check KBC self-test/shutdown flag. If it is set, we need
+ ;; to check for a reboot attempt.
+ in al, 64h
+ test al, 4 ; clear flag indicates cold boot
+ jz cont_post
+
+ ;; Warm boot, check the shutdown byte.
+ mov al, ah
+ or al, al
+ jnz cont_post
+
+ ;; Warm boot but shutdown byte is zero. This is either a warm
+ ;; boot request or an attempt to reset the system via triple
+ ;; faulting the CPU or similar. Check reboot flag.
+ ;; NB: At this point, registers need not be preserved.
+ mov ds, cs:[seg_40_value]
+ cmp word ptr ds:[72h], 1234h
+ jnz reset_sys ; trigger system reset
+
+cont_post:
+ ;; reset the shutdown status in CMOS
+ mov al, 0Fh
+ out CMOS_ADDR, al
+ mov al, 0
+ out CMOS_DATA, al
+
+ ;; pre-check the shutdown status - shutdown codes 9/A leave
+ ;; the hardware alone
+ mov al, ah
+ cmp al, 09h
+ jz check_shutdown
+ cmp al, 0Ah
+ jz check_shutdown
+
+ xor al, al
+
+ ;; reset the DMA controllers
+ out 00Dh, al
+ out 0DAh, al
+
+ ;; then initialize the DMA controllers
+ mov al, 0C0h
+ out 0D6h, al ; enable channel 4 cascade
+ mov al, 0
+ out 0D4h, al ; unmask channel 4
+
+check_shutdown:
+ ;; examine the shutdown status code
+ mov al, ah
+ cmp al, 0
+ jz normal_post
+
+ cmp al, 0Dh
+ jae normal_post
+ cmp al, 9
+ jne check_next_std
+ jmp return_blkmove
+check_next_std:
+
+ mov sp, 400h
+ ;; 05h = EOI + jump through 40:67
+ cmp al, 5
+ je eoi_jmp_post
+ ;; 0ah = jump through 40:67 (no EOI) ;ba x 1 %fe05b ; ba x 1 %18b81
+ cmp al, 0ah
+ je no_eoi_jmp_post
+
+ ;; any other shutdown status values are ignored
+ ;; OpenSolaris sets the status to 0Ah in some cases?
+ jmp normal_post
+
+normal_post:
+ ;; shutdown code 0: normal startup
+
+ ;; Set up the stack top at 0:7800h. The stack should not be
+ ;; located above 0:7C00h; that conflicts with PXE, which
+ ;; considers anything above that address to be fair game.
+ ;; The traditional locations are 30:100 (PC) or 0:400 (PC/AT).
+ mov ax, 7800h
+ mov sp, ax
+ xor ax, ax
+ mov ds, ax
+ mov ss, ax
+
+ ;; clear the bottom of memory except for the word at 40:72
+ ;; TODO: Why not clear all of it? What's the point?
+ mov es, ax
+ xor di, di
+ cld
+ mov cx, 0472h / 2
+ rep stosw
+ inc di
+ inc di
+ mov cx, (1000h - 0472h - 2) / 2
+ rep stosw
+
+ ;; clear the remaining base memory except for the top
+ ;; of the EBDA (the MP table is planted there)
+ xor bx, bx
+memory_zero_loop:
+ add bx, 1000h
+ cmp bx, 9000h
+ jae memory_cleared
+ mov es, bx
+ xor di, di
+ mov cx, 8000h ; 32K words
+ rep stosw
+ jmp memory_zero_loop
+memory_cleared:
+ mov es, bx
+ xor di, di
+ mov cx, 7FF8h ; all but the last 16 bytes
+ rep stosw
+ xor bx, bx
+
+
+ C_SETUP
+ call _log_bios_start
+
+if VBOX_BIOS_CPU ge 80386
+ call pmode_setup
+endif
+
+ ;; set all interrupts in 00h-5Fh range to default handler
+ xor bx, bx
+ mov ds, bx
+ mov cx, 60h ; leave the rest as zeros
+ mov ax, dummy_iret
+ mov dx, BIOSSEG
+ call set_int_vects
+
+ ;; also set 68h-77h to default handler; note that the
+ ;; 60h-67h range must contain zeros for certain programs
+ ;; to function correctly
+ mov bx, 68h * 4
+ mov cx, 10h
+ call set_int_vects
+
+ ;; base memory in K to 40:13
+ mov ax, BASE_MEM_IN_K
+ mov ds:[413h], ax
+
+ ;; manufacturing test at 40:12
+ ;; zeroed out above
+
+ ;; set up various service vectors
+ ;; TODO: This should use the table at FEF3h instead
+ SET_INT_VECTOR 06h, BIOSSEG, int06_handler
+ SET_INT_VECTOR 11h, BIOSSEG, int11_handler
+ SET_INT_VECTOR 12h, BIOSSEG, int12_handler
+ SET_INT_VECTOR 15h, BIOSSEG, int15_handler
+ SET_INT_VECTOR 17h, BIOSSEG, int17_handler
+ SET_INT_VECTOR 18h, BIOSSEG, int18_handler
+ SET_INT_VECTOR 19h, BIOSSEG, int19_handler
+ SET_INT_VECTOR 1Ch, BIOSSEG, int1c_handler
+
+ call ebda_post
+
+ ;; Initialize PCI devices. This can and should be done early.
+if VBOX_BIOS_CPU ge 80386 ; (Impossible to do on 16-bit CPUs.)
+ call pcibios_init_iomem_bases
+ call pcibios_init_irqs
+endif
+ SET_INT_VECTOR 1Ah, BIOSSEG, int1a_handler
+
+ ;; PIT setup
+ SET_INT_VECTOR 08h, BIOSSEG, int08_handler
+ mov al, 34h ; timer 0, binary, 16-bit, mode 2
+ out 43h, al
+ mov al, 0 ; max count -> ~18.2 Hz
+ out 40h, al
+ out 40h, al
+
+ ;; video setup - must be done before POSTing VGA ROM
+ SET_INT_VECTOR 10h, BIOSSEG, int10_handler
+
+ ;; keyboard setup
+ SET_INT_VECTOR 09h, BIOSSEG, int09_handler
+ SET_INT_VECTOR 16h, BIOSSEG, int16_handler
+
+ xor ax, ax
+ mov ds, ax
+ ;; TODO: What's the point? The BDA is zeroed already?!
+ mov ds:[417h], al ; keyboard shift flags, set 1
+ mov ds:[418h], al ; keyboard shift flags, set 2
+ mov ds:[419h], al ; keyboard Alt-numpad work area
+ mov ds:[471h], al ; keyboard Ctrl-Break flag
+ mov ds:[497h], al ; keyboard status flags 4
+ mov al, 10h
+ mov ds:[496h], al ; keyboard status flags 3
+
+ mov bx, 1Eh
+ mov ds:[41Ah], bx ; keyboard buffer head
+ mov ds:[41Ch], bx ; keyboard buffer tail
+ mov ds:[480h], bx ; keyboard buffer start
+ mov bx, 3Eh
+ mov ds:[482h], bx ; keyboard buffer end
+
+ ;; store CMOS equipment byte in BDA
+ mov al, 14h
+ out CMOS_ADDR, al
+ in al, CMOS_DATA
+ mov ds:[410h], al
+
+ push ds
+ C_SETUP
+
+ ;; Scan for video ROMs in the C000-C800 range. This is done
+ ;; early so that errors are displayed on the screen.
+ mov ax, 0C000h
+ mov dx, 0C800h
+ call rom_scan_
+
+ ;; Initialize the keyboard
+ call _keyboard_init
+ pop ds
+
+ ;; parallel setup
+ SET_INT_VECTOR 0Fh, BIOSSEG, dummy_iret
+ xor ax, ax
+ mov ds, ax
+ xor bx, bx
+ mov cl, 14h ; timeout value
+ mov dx, 378h ; parallel port 1
+ call detect_parport
+ mov dx, 278h ; parallel port 2
+ call detect_parport
+ DO_shl bx, 0Eh
+ mov ax, ds:[410h] ; equipment word
+ and ax, 3FFFh
+ or ax, bx ; set number of parallel ports
+ mov ds:[410h], ax ; store in BDA
+
+ ;; Serial setup
+ SET_INT_VECTOR 0Bh, BIOSSEG, dummy_isr ; IRQ 3
+ SET_INT_VECTOR 0Ch, BIOSSEG, dummy_isr ; IRQ 4
+ SET_INT_VECTOR 14h, BIOSSEG, int14_handler
+ xor bx, bx
+ mov cl, 0Ah ; timeout value
+ mov dx, 3F8h ; first serial address
+ call detect_serial
+ mov dx, 2F8h ; second serial address
+ call detect_serial
+ mov dx, 3E8h ; third serial address
+ call detect_serial
+ mov dx, 2E8h ; fourth serial address
+ call detect_serial
+ DO_shl bx, 9
+ mov ax, ds:[410h] ; equipment word
+ and ax, 0F1FFh ; bits 9-11 determine serial ports
+ or ax, bx
+ mov ds:[410h], ax
+
+ ;; CMOS RTC
+ SET_INT_VECTOR 4Ah, BIOSSEG, dummy_iret ; TODO: redundant?
+ SET_INT_VECTOR 70h, BIOSSEG, int70_handler
+ ;; BIOS DATA AREA 4CEh ???
+ call rtc_post
+
+ jmp norm_post_cont
+
+
+;; --------------------------------------------------------
+;; NMI handler
+;; --------------------------------------------------------
+ BIOSORG 0E2C3h, 0E2C1h
+nmi:
+ C_SETUP
+ call _nmi_handler_msg
+ iret
+
+int75_handler:
+ out 0F0h, al ; clear IRQ13
+ call eoi_both_pics
+ int 2 ; emulate legacy NMI
+ iret
+
+
+hard_drive_post proc near
+
+ xor ax, ax
+ mov ds, ax
+ ;; TODO: Didn't we just clear the entire EBDA?
+ mov ds:[474h], al ; last HD operation status
+ mov ds:[477h], al ; HD port offset (XT only???)
+ mov ds:[48Ch], al ; HD status register
+ mov ds:[48Dh], al ; HD error register
+ mov ds:[48Eh], al ; HD task complete flag
+ mov al, 0C0h
+ mov ds:[476h], al ; HD control byte
+ ;; set up hard disk interrupt vectors
+ SET_INT_VECTOR 13h, BIOSSEG, int13_handler
+ SET_INT_VECTOR 76h, BIOSSEG, int76_handler
+ ;; The ATA init code sets up INT 41h/46h FDPT pointers
+ ret
+
+hard_drive_post endp
+
+
+norm_post_cont:
+ ;; PS/2 mouse setup
+ SET_INT_VECTOR 74h, BIOSSEG, int74_handler
+
+ ;; IRQ 13h (FPU exception) setup
+ SET_INT_VECTOR 75h, BIOSSEG, int75_handler
+
+ call init_pic
+
+ C_SETUP
+
+if VBOX_BIOS_CPU ge 80386
+ ;; Set up local APIC
+ .386
+ pushad
+ call _apic_setup
+ popad
+ SET_DEFAULT_CPU_286
+endif
+
+ ;; ATA/ATAPI driver setup
+ call _ata_init
+ call _ata_detect
+
+ifdef VBOX_WITH_AHCI
+ ; AHCI driver setup
+ ;; TODO: AHCI initialization needs timer, but enabling
+ ;; interrupts elsewhere may be risky. Just do it around
+ ;; the AHCI init.
+ sti
+ call _ahci_init
+ cli
+endif
+
+ifdef VBOX_WITH_SCSI
+ ; SCSI driver setup
+ call _scsi_init
+endif
+
+ ;; floppy setup
+ call floppy_post
+
+ ;; hard drive setup
+ call hard_drive_post
+
+ C_SETUP ; in case assembly code changed things
+ ;; Scan for additional ROMs in the C800-EFFF range
+ mov ax, 0C800h
+ mov dx, 0F000h
+ call rom_scan_
+
+if VBOX_BIOS_CPU ge 80386
+ ;; The POST code does not bother preserving high bits of the
+ ;; 32-bit registers. Now is a good time to clear them so that
+ ;; there's no garbage left in high bits.
+ .386
+ xor eax, eax
+ xor ebx, ebx
+ xor ecx, ecx
+ xor edx, edx
+ .286
+endif
+
+ call _print_bios_banner
+
+ ;; El Torito floppy/hard disk emulation
+ call _cdemu_init
+
+ ; TODO: what's the point of enabling interrupts here??
+ sti ; enable interrupts
+ int 19h
+ ;; does not return here
+ sti
+wait_forever:
+ hlt
+ jmp wait_forever
+ cli
+ hlt
+
+
+;;
+;; Return from block move (shutdown code 09h). Care must be taken to disturb
+;; register and memory state as little as possible.
+;;
+return_blkmove:
+ .286p
+ mov ax, 40h
+ mov ds, ax
+ ;; restore user stack
+ mov ss, ds:[69h]
+ mov sp, ds:[67h]
+ ;; reset A20 gate
+ in al, 92h
+ and al, 0FDh
+ out 92h, al
+ ;; ensure proper real mode IDT
+ lidt fword ptr cs:_rmode_IDT
+ ;; restore user segments
+ pop ds
+ pop es
+ ;; set up BP
+ mov bp, sp
+ ;; restore status code
+ in al, 80h
+ mov [bp+15], al
+ ;; set ZF/CF
+ cmp ah,al ; AH is zero here!
+ ;; restore registers and return
+ popa
+ sti
+ retf 2
+ SET_DEFAULT_CPU_286
+
+
+;; --------------------------------------------------------
+;; INT 13h handler - Disk services
+;; --------------------------------------------------------
+ BIOSORG 0E3FEh, 0E3FCh
+
+int13_handler:
+ jmp int13_relocated
+
+
+;; --------------------------------------------------------
+;; Fixed Disk Parameter Table
+;; --------------------------------------------------------
+ BIOSORG_CHECK 0E401h ; fixed wrt preceding
+
+rom_fdpt:
+
+;; --------------------------------------------------------
+;; INT 19h handler - Boot load service
+;; --------------------------------------------------------
+ BIOSORG 0E6F2h, 0E6F0h
+
+int19_handler:
+ jmp int19_relocated
+
+
+
+;; --------------------------------------------------------
+;; System BIOS Configuration Table
+;; --------------------------------------------------------
+ BIOSORG_CHECK 0E6F5h ; fixed wrt preceding
+; must match BIOS_CONFIG_TABLE
+bios_cfg_table:
+ dw 9 ; table size in bytes
+ db SYS_MODEL_ID
+ db SYS_SUBMODEL_ID
+ db BIOS_REVISION
+ ; Feature byte 1
+ ; b7: 1=DMA channel 3 used by hard disk
+ ; b6: 1=2 interrupt controllers present
+ ; b5: 1=RTC present
+ ; b4: 1=BIOS calls int 15h/4Fh for every key
+ ; b3: 1=wait for extern event supported (Int 15h/41h)
+ ; b2: 1=extended BIOS data area used
+ ; b1: 0=AT or ESDI bus, 1=MicroChannel
+ ; b0: 1=Dual bus (MicroChannel + ISA)
+ifdef BX_CALL_INT15_4F
+ db 74h; or USE_EBDA
+else
+ db 64h; or USE_EBDA
+endif
+ ; Feature byte 2
+ ; b7: 1=32-bit DMA supported
+ ; b6: 1=int16h, function 9 supported
+ ; b5: 1=int15h/C6h (get POS data) supported
+ ; b4: 1=int15h/C7h (get mem map info) supported
+ ; b3: 1=int15h/C8h (en/dis CPU) supported
+ ; b2: 1=non-8042 kb controller
+ ; b1: 1=data streaming supported
+ ; b0: reserved
+ db 40h
+ ; Feature byte 3
+ ; b7: not used
+ ; b6: reserved
+ ; b5: reserved
+ ; b4: POST supports ROM-to-RAM enable/disable
+ ; b3: SCSI on system board
+ ; b2: info panel installed
+ ; b1: Initial Machine Load (IML) system - BIOS on disk
+ ; b0: SCSI supported in IML
+ db 0
+ ; Feature byte 4
+ ; b7: IBM private
+ ; b6: EEPROM present
+ ; b5-3: ABIOS presence (011 = not supported)
+ ; b2: private
+ ; b1: memory split above 16Mb supported
+ ; b0: POSTEXT directly supported by POST
+ db 0
+ ; Feature byte 5 (IBM)
+ ; b1: enhanced mouse
+ ; b0: flash EPROM
+ db 0
+
+
+;; --------------------------------------------------------
+;; Baud Rate Generator Table
+;; --------------------------------------------------------
+ BIOSORG 0E729h, 0E727h
+
+
+;; --------------------------------------------------------
+;; INT 14h handler - Serial Communication Service
+;; --------------------------------------------------------
+ BIOSORG 0E739h, 0E737h
+int14_handler:
+ push ds
+ push es
+ DO_pusha
+ C_SETUP
+ call _int14_function
+ DO_popa
+ pop es
+ pop ds
+ iret
+
+
+
+;;
+;; Handler for unexpected hardware interrupts
+;;
+dummy_isr:
+ push ds
+ push es
+ DO_pusha
+ C_SETUP
+ call _dummy_isr_function
+ DO_popa
+ pop es
+ pop ds
+ iret
+
+
+init_pic proc near
+
+ mov al, 11h ; send init commands
+ out PIC_MASTER, al
+ out PIC_SLAVE, al
+ mov al, 08h ; base 08h
+ out PIC_MASTER+1, al
+ mov al, 70h ; base 70h
+ out PIC_SLAVE+1, al
+ mov al, 04h ; master PIC
+ out PIC_MASTER+1, al
+ mov al, 02h ; slave PIC
+ out PIC_SLAVE+1, al
+ mov al, 01h
+ out PIC_MASTER+1, al
+ out PIC_SLAVE+1, al
+ mov al, 0B8h ; unmask IRQs 0/1/2/6
+ out PIC_MASTER+1, al
+ mov al, 08Fh
+ out PIC_SLAVE+1, al ; unmask IRQs 12/13/14
+ ret
+
+init_pic endp
+
+ebda_post proc near
+
+ SET_INT_VECTOR 0Dh, BIOSSEG, dummy_isr ; IRQ 5
+ SET_INT_VECTOR 0Fh, BIOSSEG, dummy_isr ; IRQ 7
+ SET_INT_VECTOR 72h, BIOSSEG, dummy_isr ; IRQ 10
+ SET_INT_VECTOR 73h, BIOSSEG, dummy_isr ; IRQ 11
+ SET_INT_VECTOR 77h, BIOSSEG, dummy_isr ; IRQ 15
+
+ mov ax, EBDA_SEG
+ mov ds, ax
+ mov byte ptr ds:[0], EBDA_SIZE
+ ;; store EBDA seg in 40:0E
+ xor ax, ax
+ mov ds, ax
+ mov word ptr ds:[40Eh], EBDA_SEG
+ ret
+
+ebda_post endp
+
+
+
+;; --------------------------------------------------------
+;; INT 16h handler - Keyboard service
+;; --------------------------------------------------------
+ BIOSORG 0E82Eh, 0E82Ch
+int16_handler:
+ sti
+ ;; Flags are saved *after* enabling interrupts, and with
+ ;; implicitly cleared TF. Software may depend on that.
+ pushf
+ push es
+ push ds
+ DO_pusha
+
+ cmp ah, 0
+ je int16_F00
+
+ cmp ah, 10h
+ je int16_F00
+
+ C_SETUP
+ call _int16_function
+ DO_popa
+ pop ds
+ pop es
+ add sp, 2 ; Skip saved flags
+ iret
+
+int16_F00:
+ mov bx, 40h ; TODO: why 40h here and 0 elsewhere?
+ mov ds, bx
+int16_wait_for_key:
+ cli
+ mov bx, ds:[1Ah]
+ cmp bx, ds:[1Ch]
+ jne int16_key_found
+ sti
+ nop
+; TODO: review/enable?
+if 0
+ push ax
+ mov ax, 9002h
+ int 15h
+ pop ax
+endif
+ jmp int16_wait_for_key
+
+int16_key_found:
+ C_SETUP
+ call _int16_function
+ DO_popa
+ pop ds
+ pop es
+ add sp, 2 ; Skip saved flags
+; TODO: review/enable? If so, flags should be restored here?
+if 0
+ push ax
+ mov ax, 9202h
+ int 15h
+ pop ax
+endif
+ iret
+
+
+if VBOX_BIOS_CPU ge 80386
+;; Quick and dirty protected mode entry/exit routines
+include pmode.inc
+
+;; Initialization code which needs to run in protected mode (LAPIC etc.)
+include pmsetup.inc
+endif
+
+
+;; --------------------------------------------------------
+;; INT 09h handler - Keyboard ISR (IRQ 1)
+;; --------------------------------------------------------
+ BIOSORG 0E987h, 0E985h
+int09_handler:
+ cli ; TODO: why? they're off already!
+ push ax
+ mov al, KBDC_DISABLE
+ out KBC_CMD, al
+
+ in al, KBC_DATA
+ push ds
+ DO_pusha
+ cld ; Before INT 15h (and any C code)
+ifdef BX_CALL_INT15_4F
+ mov ah, 4Fh
+ stc
+ int 15h ; keyboard intercept
+ jnc int09_done
+endif
+ sti ; Only after calling INT 15h
+
+ ;; check for extended key
+ cmp al, 0E0h
+ jne int09_check_pause
+ xor ax, ax
+ mov ds, ax
+ or byte ptr ds:[496h], 2 ; mf2_state |= 0x02
+ jmp int09_done
+
+int09_check_pause:
+ cmp al, 0E1h ; pause key?
+ jne int09_process_key
+ xor ax, ax
+ mov ds, ax
+ or byte ptr ds:[496h], 1 ; mf2_state | 0x01
+ jmp int09_done
+
+int09_process_key:
+ push es
+ C_SETUP
+ call _int09_function
+ pop es
+
+int09_done:
+ DO_popa
+ pop ds
+ cli
+ call eoi_master_pic
+
+ mov al, KBDC_ENABLE
+ out KBC_CMD, al
+ pop ax
+ iret
+
+
+;; --------------------------------------------------------
+;; INT 06h handler - Invalid Opcode Exception
+;; --------------------------------------------------------
+
+int06_handler:
+ DO_pusha
+ push es
+ push ds
+ C_SETUP
+ call _inv_op_handler
+ pop ds
+ pop es
+ DO_popa
+ iret
+
+;; --------------------------------------------------------
+;; INT 13h handler - Diskette service
+;; --------------------------------------------------------
+ BIOSORG 0EC59h, 0EC57h
+int13_diskette:
+ jmp int13_noeltorito
+
+
+
+;; --------------------------------------------------------
+;; INT 13h handler - Disk service
+;; --------------------------------------------------------
+int13_relocated:
+ ;; check for an El-Torito function
+ cmp ah, 4Ah
+ jb int13_not_eltorito
+
+ cmp ah, 4Dh
+ ja int13_not_eltorito
+
+ DO_pusha
+ push es
+ push ds
+ C_SETUP ; TODO: setup C envrionment only once?
+ DO_JMP_CALL_EX _int13_eltorito, int13_out, jmp_call_ret_int13_out ; ELDX not used
+if VBOX_BIOS_CPU eq 8086
+jmp_call_ret_int13_out: dw offset int13_out
+endif
+
+int13_not_eltorito:
+ push es
+ push ax ; TODO: better register save/restore
+ push bx
+ push cx
+ push dx
+
+ ;; check if emulation is active
+ call _cdemu_isactive
+ cmp al, 0
+ je int13_cdemu_inactive
+
+ ;; check if access to the emulated drive
+ call _cdemu_emulated_drive
+ pop dx ; recover dx (destroyed by C code)
+ push dx
+ cmp al, dl ; INT 13h on emulated drive
+ jne int13_nocdemu
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ pop es
+
+ DO_pusha
+ push es
+ push ds
+ C_SETUP ; TODO: setup environment only once?
+
+ DO_JMP_CALL_EX _int13_cdemu, int13_out, jmp_call_ret_int13_out ; ELDX not used
+
+int13_nocdemu:
+ and dl, 0E0h ; mask to get device class
+ cmp al, dl
+ jne int13_cdemu_inactive
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ pop es
+
+ push ax
+ push cx
+ push dx
+ push bx
+
+ dec dl ; real drive is dl - 1
+ jmp int13_legacy
+
+int13_cdemu_inactive:
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ pop es
+
+int13_noeltorito:
+ push ax
+ push cx
+ push dx
+ push bx
+int13_legacy:
+ push dx ; push eltorito dx in place of sp
+ push bp
+ push si
+ push di
+ push es
+ push ds
+ C_SETUP ; TODO: setup environment only once?
+
+ ;; now the registers can be restored with
+ ;; pop ds; pop es; DO_popa; iret
+ test dl, 80h ; non-removable?
+ jnz int13_notfloppy
+
+ DO_JMP_CALL_EX _int13_diskette_function, int13_out, jmp_call_ret_int13_out
+
+int13_notfloppy:
+ cmp dl, 0E0h
+ jb int13_notcdrom
+
+ ;; ebx may be modified, save here
+ ;; TODO: check/review 32-bit register use
+ ;; @todo figure if 80286/8086 variant is applicable.
+ .386
+ shr ebx, 16
+ push bx
+ call _int13_cdrom
+ pop bx
+ shl ebx, 16
+ SET_DEFAULT_CPU_286
+ jmp int13_out
+
+int13_notcdrom:
+int13_disk:
+ cmp ah,40h
+ ja int13x
+ call _int13_harddisk
+ jmp int13_out
+
+int13x:
+ call _int13_harddisk_ext
+
+int13_out:
+ pop ds
+ pop es
+ DO_popa
+ iret
+
+
+
+; parallel port detection: port in dx, index in bx, timeout in cl
+detect_parport proc near
+
+ push dx
+ inc dx
+ inc dx
+ in al, dx
+ and al, 0DFh ; clear input mode
+ out dx, al
+ pop dx
+ mov al, 0AAh
+ out dx, al
+ in al, dx
+ cmp al, 0AAh
+ jne no_parport
+
+ push bx
+ shl bx, 1
+ mov [bx+408h], dx ; parallel I/O address
+ pop bx
+ mov [bx+478h], cl ; parallel printer timeout
+ inc bx
+no_parport:
+ ret
+
+detect_parport endp
+
+; setial port detection: port in dx, index in bx, timeout in cl
+detect_serial proc near
+
+ push dx
+ inc dx
+ mov al, 2
+ out dx, al
+ in al, dx
+ cmp al, 2
+ jne no_serial
+
+ inc dx
+ in al, dx
+ cmp al, 2
+ jne no_serial
+
+ dec dx
+ xor al, al
+ pop dx
+ push bx
+ shl bx, 1
+ mov [bx+400h], dx ; serial I/O address
+ pop bx
+ mov [bx+47Ch], cl ; serial timeout
+ inc bx
+ ret
+
+no_serial:
+ pop dx
+ ret
+
+detect_serial endp
+
+
+;;
+;; POST: Floppy drive
+;;
+floppy_post proc near
+
+ xor ax, ax
+ mov ds, ax
+
+ ;; TODO: This code is really stupid. Zeroing the BDA byte
+ ;; by byte is dumb, and it's been already zeroed elsewhere!
+ mov al, 0
+ mov ds:[43Eh], al ; drive 0/1 uncalibrated, no IRQ
+ mov ds:[43Fh], al ; motor status
+ mov ds:[440h], al ; motor timeout counter
+ mov ds:[441h], al ; controller status return code
+ mov ds:[442h], al ; hd/floppy ctlr status register
+ mov ds:[443h], al ; controller status register 1
+ mov ds:[444h], al ; controller status register 2
+ mov ds:[445h], al ; cylinder number
+ mov ds:[446h], al ; head number
+ mov ds:[447h], al ; sector number
+ mov ds:[448h], al ; bytes written
+
+ mov ds:[48Bh], al ; configuration data
+
+ mov al, 10h ; floppy drive type
+ out CMOS_ADDR, al
+ in al, CMOS_DATA
+ mov ah, al ; save drive type byte
+
+look_drive0:
+ ; TODO: pre-init bl to reduce jumps
+ DO_shr al, 4 ; drive 0 in high nibble
+ jz f0_missing ; jump if no drive
+ mov bl, 7 ; drv0 determined, multi-rate, chgline
+ jmp look_drive1
+
+f0_missing:
+ mov bl, 0 ; no drive 0
+
+look_drive1:
+ mov al, ah ; restore CMOS data
+ and al, 0Fh ; drive 1 in low nibble
+ jz f1_missing
+ or bl, 70h ; drv1 determined, multi-rate, chgline
+f1_missing:
+ mov ds:[48Fh], bl ; store in BDA
+
+ ;; TODO: See above. Dumb *and* redundant!
+ mov al, 0
+ mov ds:[490h], al ; drv0 media state
+ mov ds:[491h], al ; drv1 media state
+ mov ds:[492h], al ; drv0 operational state
+ mov ds:[493h], al ; drv1 operational state
+ mov ds:[494h], al ; drv0 current cylinder
+ mov ds:[495h], al ; drv1 current cylinder
+
+ mov al, 2
+ out 0Ah, al ; unmask DMA channel 2
+
+ SET_INT_VECTOR 1Eh, BIOSSEG, _diskette_param_table
+ SET_INT_VECTOR 40h, BIOSSEG, int13_diskette
+ SET_INT_VECTOR 0Eh, BIOSSEG, int0e_handler ; IRQ 6
+
+ ret
+
+floppy_post endp
+
+
+bcd_to_bin proc near
+
+ ;; in : AL in packed BCD format
+ ;; out: AL in binary, AH always 0
+if VBOX_BIOS_CPU ge 80186
+ shl ax, 4
+ shr al, 4
+else
+ push cx
+ mov cl, 4
+ shl ax, cl
+ shr al, cl
+ pop cx
+endif
+ aad
+ ret
+
+bcd_to_bin endp
+
+rtc_post proc near
+
+if VBOX_BIOS_CPU lt 80386 ;; @todo fix loopy code below
+ ;; get RTC seconds
+ mov al, 0
+ out CMOS_ADDR, al
+ in al, CMOS_DATA ; RTC seconds, in BCD
+ call bcd_to_bin ; ax now has seconds in binary
+ test al, al
+ xor ah, ah
+ mov dx, 0x1234 ; 18206507*0x100/1000000 = 0x1234 (4660.865792)
+ mul dx
+ mov cx, ax ; tick count in dx:cx
+
+ ;; get RTC minutes
+ mov al, 2
+ out CMOS_ADDR, al
+ in al, CMOS_DATA ; RTC minutes, in BCD
+ call bcd_to_bin ; eax now has minutes in binary
+ test al, al
+ jz rtc_post_hours
+rtc_pos_min_loop: ; 18206507*60*0x100/1000000 = 0x44463 (279651.94752)
+ add cx, 0x4463
+ adc dx, 0x0004
+ dec al
+ jnz rtc_pos_min_loop
+
+ ;; get RTC hours
+rtc_post_hours:
+ mov al, 4
+ out CMOS_ADDR, al
+ in al, CMOS_DATA ; RTC hours, in BCD
+ call bcd_to_bin ; eax now has hours in binary
+ test al, al
+ jz rtc_pos_shift
+rtc_pos_hour_loop: ; 18206507*3600*0x100/1000000 = 0x100076C (16779116.8512)
+ add cx, 0x076C
+ adc dx, 0x0100
+ dec al
+ jnz rtc_pos_hour_loop
+
+rtc_pos_shift:
+ mov cl, ch
+ mov ch, dl
+ mov dl, dh
+ xor dh, dh
+ mov ds:[46Ch], cx ; timer tick count
+ mov ds:[46Ch+2], dx ; timer tick count
+ mov ds:[470h], dh ; rollover flag
+
+else
+ .386
+ ;; get RTC seconds
+ xor eax, eax
+ mov al, 0
+ out CMOS_ADDR, al
+ in al, CMOS_DATA ; RTC seconds, in BCD
+ call bcd_to_bin ; eax now has seconds in binary
+ mov edx, 18206507
+ mul edx
+ mov ebx, 1000000
+ xor edx, edx
+ div ebx
+ mov ecx, eax ; total ticks in ecx
+
+ ;; get RTC minutes
+ xor eax, eax
+ mov al, 2
+ out CMOS_ADDR, al
+ in al, CMOS_DATA ; RTC minutes, in BCD
+ call bcd_to_bin ; eax now has minutes in binary
+ mov edx, 10923904
+ mul edx
+ mov ebx, 10000
+ xor edx, edx
+ div ebx
+ add ecx, eax ; add to total ticks
+
+ ;; get RTC hours
+ xor eax, eax
+ mov al, 4
+ out CMOS_ADDR, al
+ in al, CMOS_DATA ; RTC hours, in BCD
+ call bcd_to_bin ; eax now has hours in binary
+ mov edx, 65543427
+ mul edx
+ mov ebx, 1000
+ xor edx, edx
+ div ebx
+ add ecx, eax ; add to total ticks
+
+ mov ds:[46Ch], ecx ; timer tick count
+ xor al, al ; TODO: redundant?
+ mov ds:[470h], al ; rollover flag
+ .286
+endif
+ ret
+
+rtc_post endp
+
+
+
+;; --------------------------------------------------------
+;; INT 0Eh handler - Diskette IRQ 6 ISR
+;; --------------------------------------------------------
+ BIOSORG 0EF57h, 0EF55h
+int0e_handler:
+ push ax
+ push dx
+ mov dx, 3F4h
+ in al, dx
+ and al, 0C0h
+ cmp al, 0C0h
+ je int0e_normal
+ mov dx, 3F5h
+ mov al, 08h ; sense interrupt
+ out dx, al
+int0e_loop1:
+ mov dx, 3F4h ; TODO: move out of the loop?
+ in al, dx
+ and al, 0C0h
+ cmp al, 0C0h
+ jne int0e_loop1
+
+int0e_loop2:
+ mov dx, 3F5h ; TODO: inc/dec dx instead
+ in al, dx
+ mov dx, 3F4h
+ in al, dx
+ and al, 0C0h
+ cmp al, 0C0h
+ je int0e_loop2
+
+int0e_normal:
+ push ds
+ xor ax, ax
+ mov ds, ax
+ call eoi_master_pic
+ ; indicate that an interrupt occurred
+ or byte ptr ds:[43Eh], 80h
+ pop ds
+ pop dx
+ pop ax
+ iret
+
+
+;; --------------------------------------------------------
+;; Diskette Parameter Table
+;; --------------------------------------------------------
+ BIOSORG 0EFC7h, 0EFC5h
+_diskette_param_table:
+ db 0AFh
+ db 2 ; HLT=1, DMA mode
+ db 025h
+ db 2
+ db 18 ; SPT (good for 1.44MB media)
+ db 01Bh
+ db 0FFh
+ db 06Ch
+ db 0F6h ; format filler
+ db 15
+ db 8
+
+
+
+;; --------------------------------------------------------
+;; INT 17h handler - Printer service
+;; --------------------------------------------------------
+ BIOSORG_CHECK 0EFD2h ; fixed WRT preceding code
+
+ jmp int17_handler ; NT floppy boot workaround
+ ; see @bugref{6481}
+int17_handler:
+ push ds
+ push es
+ DO_pusha
+ C_SETUP
+ call _int17_function
+ DO_popa
+ pop es
+ pop ds
+ iret
+
+
+
+;; Protected mode IDT descriptor
+;;
+;; The limit is 0 to cause a shutdown if an exception occurs
+;; in protected mode. TODO: Is that what we really want?
+;;
+;; Set base to F0000 to correspond to beginning of BIOS,
+;; in case an IDT is defined later.
+
+_pmode_IDT:
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ dw 0Fh ; base 23:16
+
+
+;; Real mode IDT descriptor
+;;
+;; Set to typical real-mode values.
+;; base = 000000
+;; limit = 03ff
+
+_rmode_IDT:
+ dw 3FFh ; limit 15:00
+ dw 0 ; base 15:00
+ dw 0 ; base 23:16
+
+
+;;
+;; INT 1Ch
+;;
+;; TODO: Why does this need a special handler?
+int1c_handler: ;; user timer tick
+ iret
+
+
+
+;; --------------------------------------------------------
+;; INT 10h functions 0-Fh entry point
+;; --------------------------------------------------------
+ BIOSORG 0F045h, 0F043h
+i10f0f_entry:
+ iret
+
+
+;; --------------------------------------------------------
+;; INT 10h handler - MDA/CGA video
+;; --------------------------------------------------------
+ BIOSORG 0F065h, 0F063h
+int10_handler:
+ ;; do nothing - assumes VGA
+ iret
+
+
+;; --------------------------------------------------------
+;; MDA/CGA Video Parameter Table (INT 1Dh)
+;; --------------------------------------------------------
+ BIOSORG 0F0A4h, 0F0A2h
+mdacga_vpt:
+
+
+;;
+;; INT 18h - boot failure
+;;
+int18_handler:
+ C_SETUP
+ call _int18_panic_msg
+ ;; TODO: handle failure better?
+ hlt
+ iret
+
+;;
+;; INT 19h - boot service - relocated
+;;
+int19_relocated:
+; If an already booted OS calls int 0x19 to reboot, it is not sufficient
+; just to try booting from the configured drives. All BIOS variables and
+; interrupt vectors need to be reset, otherwise strange things may happen.
+; The approach used is faking a warm reboot (which just skips showing the
+; logo), which is a bit more than what we need, but hey, it's fast.
+ mov bp, sp
+ mov ax, [bp+2] ; TODO: redundant? address via sp?
+ cmp ax, BIOSSEG ; check caller's segment
+ jz bios_initiated_boot
+
+ xor ax, ax
+ mov ds, ax
+ mov ax, 1234h
+ mov ds:[472], ax
+ jmp post
+
+bios_initiated_boot:
+ ;; The C worker function returns the boot drive in bl and
+ ;; the boot segment in ax. In case of failure, the boot
+ ;; segment will be zero.
+ C_SETUP ; TODO: Here? Now?
+ push bp
+ mov bp, sp
+
+ ;; 1st boot device
+ mov ax, 1
+ push ax
+ call _int19_function
+ inc sp
+ inc sp
+ test ax, ax ; if 0, try next device
+ jnz boot_setup
+
+ ;; 2nd boot device
+ mov ax, 2
+ push ax
+ call _int19_function
+ inc sp
+ inc sp
+ test ax, ax ; if 0, try next device
+ jnz boot_setup
+
+ ; 3rd boot device
+ mov ax, 3
+ push ax
+ call _int19_function
+ inc sp
+ inc sp
+ test ax, ax ; if 0, try next device
+ jnz boot_setup
+
+ ; 4th boot device
+ mov ax, 4
+ push ax
+ call _int19_function
+ inc sp
+ inc sp
+ test ax, ax ; if 0, invoke INT 18h
+ jz int18_handler
+
+boot_setup:
+; TODO: the drive should be in dl already??
+;; mov dl, bl ; tell guest OS what boot drive is
+if VBOX_BIOS_CPU lt 80386
+ mov [bp], ax
+ DO_shl ax, 4
+ mov [bp+2], ax ; set ip
+ mov ax, [bp]
+else
+ .386 ; NB: We're getting garbage into high eax bits
+ shl eax, 4 ; convert seg to ip
+ mov [bp+2], ax ; set ip
+
+ shr eax, 4 ; get cs back
+ .286
+endif
+ and ax, BIOSSEG ; remove what went in ip
+ mov [bp+4], ax ; set cs
+ xor ax, ax
+ mov ds, ax
+ mov es, ax
+ mov [bp], ax ; TODO: what's this?!
+ mov ax, 0AA55h ; set ok flag ; TODO: and this?
+
+ pop bp ; TODO: why'd we just zero it??
+ iret ; beam me up scotty
+
+;; PCI BIOS
+
+include pcibios.inc
+include pirq.inc
+
+
+;; --------------------------------------------------------
+;; INT 12h handler - Memory size
+;; --------------------------------------------------------
+ BIOSORG 0F841h, 0F83Fh
+int12_handler:
+ ;; Don't touch - fixed size!
+ sti
+ push ds
+ mov ax, 40h
+ mov ds, ax
+ mov ax, ds:[13h]
+ pop ds
+ iret
+
+
+;; --------------------------------------------------------
+;; INT 11h handler - Equipment list service
+;; --------------------------------------------------------
+ BIOSORG_CHECK 0F84Dh ; fixed wrt preceding code
+int11_handler:
+ ;; Don't touch - fixed size!
+ sti
+ push ds
+ mov ax, 40h
+ mov ds, ax
+ mov ax, ds:[10h]
+ pop ds
+ iret
+
+
+;; --------------------------------------------------------
+;; INT 15h handler - System services
+;; --------------------------------------------------------
+ BIOSORG_CHECK 0F859h ; fixed wrt preceding code
+int15_handler:
+
+if VBOX_BIOS_CPU ge 80286
+ cmp ah, 87h
+ jne not_blkmove
+
+ ;; INT 15h/87h has semi-public interface because software
+ ;; may use CMOS shutdown status code 9 for its own purposes.
+ ;; The stack layout has to match.
+ pusha
+ push es
+ push ds
+ C_SETUP
+ call _int15_blkmove
+ pop ds
+ pop es
+ popa
+ iret
+not_blkmove:
+
+endif
+
+ pushf
+ push ds
+ push es
+ C_SETUP
+if VBOX_BIOS_CPU ge 80386
+ ;; int15_function32 exists in 386+ BIOS only, but INT 15h is
+ ;; not 386-specific
+ cmp ah, 0E8h
+ je int15_handler32
+ cmp ah, 0d0h
+ je int15_handler32
+endif
+ DO_pusha
+ cmp ah, 53h ; APM function?
+ je apm_call
+ cmp ah, 0C2h ; PS/2 mouse function?
+ je int15_handler_mouse
+
+ call _int15_function
+int15_handler_popa_ret:
+ DO_popa
+if VBOX_BIOS_CPU ge 80386
+int15_handler32_ret:
+endif
+ pop es
+ pop ds
+ popf
+ jmp iret_modify_cf
+
+apm_call:
+ call _apm_function
+ jmp int15_handler_popa_ret
+
+int15_handler_mouse:
+ call _int15_function_mouse
+ jmp int15_handler_popa_ret
+
+if VBOX_BIOS_CPU ge 80386
+int15_handler32:
+ ;; need to save/restore 32-bit registers
+ .386
+ pushad
+ call _int15_function32
+ popad
+ .286
+ jmp int15_handler32_ret
+endif
+
+;;
+;; Perform an IRET but retain the current carry flag value
+;;
+iret_modify_cf:
+ jc carry_set
+ push bp
+ mov bp, sp
+ and byte ptr [bp + 6], 0FEh
+ or word ptr [bp + 6], 0200h
+ pop bp
+ iret
+carry_set:
+ push bp
+ mov bp, sp
+ or word ptr [bp + 6], 0201h
+ pop bp
+ iret
+
+;;
+;; INT 74h handler - PS/2 mouse (IRQ 12)
+;;
+int74_handler proc
+
+ sti
+ DO_pusha
+ push es
+ push ds
+ xor ax, ax
+ push ax ; placeholder for status
+ push ax ; placeholder for X
+ push ax ; placeholder for Y
+ push ax ; placeholder for Z
+ push ax ; placeholder for make_far_call bool
+ C_SETUP
+ call _int74_function
+ pop cx ; pop make_far_call flag
+ jcxz int74_done
+
+ ;; make far call to EBDA:0022
+if VBOX_BIOS_CPU ge 80186
+ push 0
+else
+ xor ax, ax
+ push ax
+endif
+ pop ds
+ push ds:[40Eh]
+ pop ds
+ call far ptr ds:[22h]
+int74_done:
+ cli
+ call eoi_both_pics
+ add sp, 8 ; remove status, X, Y, Z
+ pop ds
+ pop es
+ DO_popa
+ iret
+
+int74_handler endp
+
+int76_handler proc
+
+ ;; record completion in BIOS task complete flag
+ push ax
+ push ds
+ mov ax, 40h
+ mov ds, ax
+ mov byte ptr ds:[8Eh], 0FFh
+ call eoi_both_pics
+ pop ds
+ pop ax
+ iret
+
+int76_handler endp
+
+
+;;
+;; IRQ 8 handler (RTC)
+;;
+int70_handler:
+ push es
+ push ds
+ DO_pusha
+ C_SETUP
+ call _int70_function
+ DO_popa
+ pop ds
+ pop es
+ iret
+
+
+
+if VBOX_BIOS_CPU lt 80386
+;
+; We're tight on space down below in the int08_handler, so put
+; the 16-bit rollover code here.
+;
+int08_maybe_rollover:
+ ja int08_rollover
+ cmp ax, 00B0h
+ jb int08_rollover_store
+ ;; there has been a midnight rollover
+int08_rollover:
+ xor dx, dx
+ xor ax, ax
+
+ inc byte ptr ds:[70h] ; increment rollover flag
+int08_rollover_store:
+ jmp int08_store_ticks
+endif
+
+
+;; --------------------------------------------------------
+;; 8x8 font (first 128 characters)
+;; --------------------------------------------------------
+ BIOSORG 0FA6Eh, 0FA6Ch
+include font8x8.inc
+
+
+;; --------------------------------------------------------
+;; INT 1Ah handler - Time of the day + PCI BIOS
+;; --------------------------------------------------------
+ BIOSORG_CHECK 0FE6Eh ; fixed wrt preceding table
+int1a_handler:
+if VBOX_BIOS_CPU ge 80386
+ cmp ah, 0B1h
+ jne int1a_normal
+
+ push es
+ push ds
+ C_SETUP
+ .386
+ pushad
+ call _pci16_function
+ popad
+ .286
+ pop ds
+ pop es
+ iret
+endif
+
+int1a_normal:
+ push es
+ push ds
+ DO_pusha
+ C_SETUP
+int1a_callfunction:
+ call _int1a_function
+ DO_popa
+ pop ds
+ pop es
+ iret
+
+
+;; --------------------------------------------------------
+;; Timer tick - IRQ 0 handler
+;; --------------------------------------------------------
+ BIOSORG 0FEA5h, 0FEA3h
+int08_handler:
+if VBOX_BIOS_CPU ge 80386
+ .386
+ sti
+ push eax
+else
+ sti
+ push ax
+endif
+ push ds
+ push dx
+ mov ax, 40h
+ mov ds, ax
+
+if VBOX_BIOS_CPU ge 80386
+ mov eax, ds:[6Ch] ; get ticks dword
+ inc eax
+else
+ mov ax, ds:[6Ch] ; get ticks dword
+ mov dx, ds:[6Ch+2]
+ inc ax ; inc+jz+inc saves two bytes over add+adc.
+ jnz int08_compare
+ inc dx
+int08_compare:
+endif
+
+ ;; compare eax to one day's worth of ticks (at 18.2 Hz)
+if VBOX_BIOS_CPU ge 80386
+ cmp eax, 1800B0h
+ jb int08_store_ticks
+else
+ cmp dx, 18h
+ jb int08_store_ticks
+ jmp int08_maybe_rollover
+endif
+
+if VBOX_BIOS_CPU ge 80386
+ ;; there has been a midnight rollover
+ xor eax, eax
+ inc byte ptr ds:[70h] ; increment rollover flag
+
+int08_store_ticks:
+ mov ds:[6Ch], eax
+else
+int08_store_ticks:
+ mov ds:[6Ch], ax
+ mov ds:[6Ch+2], dx
+endif
+
+ ;; time to turn off floppy drive motor(s)?
+ mov al, ds:[40h]
+ or al, al
+ jz int08_floppy_off
+ dec al
+ mov ds:[40h], al
+ jnz int08_floppy_off
+ ;; turn motor(s) off
+ mov dx, 03F2h
+ in al, dx
+ and al, 0CFh
+ out dx, al
+int08_floppy_off:
+
+ int 1Ch ; call the user timer handler
+
+ cli
+ call eoi_master_pic
+ pop dx
+ pop ds
+if VBOX_BIOS_CPU ge 80386
+ pop eax
+ .286
+else
+ pop ax
+endif
+ iret
+
+
+;; --------------------------------------------------------
+;; Initial interrupt vector offsets for POST
+;; --------------------------------------------------------
+ BIOSORG 0FEF3h, 0FEF1h
+vector_table:
+
+
+
+;; --------------------------------------------------------
+;; BIOS copyright string
+;; --------------------------------------------------------
+ BIOSORG 0FF00h, 0FEFEh
+bios_string:
+ db BIOS_COPYRIGHT
+
+
+;; --------------------------------------------------------
+;; IRET - default interrupt handler
+;; --------------------------------------------------------
+ BIOSORG 0FF53h, 0FF51h
+
+dummy_iret:
+ iret
+
+
+;; --------------------------------------------------------
+;; INT 05h - Print Screen service
+;; --------------------------------------------------------
+ BIOSORG_CHECK 0FF54h ; fixed wrt preceding
+int05_handler:
+ ;; Not implemented
+ iret
+
+include smidmi.inc
+
+;; --------------------------------------------------------
+;; Processor reset entry point
+;; --------------------------------------------------------
+ BIOSORG 0FFF0h, 0FFEEh
+cpu_reset:
+ ;; This is where the CPU starts executing after a reset
+ jmp far ptr post
+
+ ;; BIOS build date
+ db BIOS_BUILD_DATE
+ db 0 ; padding
+ ;; System model ID
+ db SYS_MODEL_ID
+ ;; Checksum byte
+ db 0FFh
+
+
+BIOSSEG ends
+
+ end
+
diff --git a/src/VBox/Devices/PC/BIOS/parallel.c b/src/VBox/Devices/PC/BIOS/parallel.c
new file mode 100644
index 00000000..9dfd289f
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/parallel.c
@@ -0,0 +1,91 @@
+/* $Id: parallel.c $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+
+#include <stdint.h>
+#include "biosint.h"
+#include "inlines.h"
+
+void BIOSCALL int17_function(pusha_regs_t regs, uint16_t es, uint16_t ds, volatile iret_addr_t iret_addr)
+{
+ uint16_t addr,timeout;
+ uint8_t val8;
+
+ int_enable();
+
+ addr = read_word(0x0040, (regs.u.r16.dx << 1) + 8);
+ if ((regs.u.r8.ah < 3) && (regs.u.r16.dx < 3) && (addr > 0)) {
+ timeout = read_byte(0x0040, 0x0078 + regs.u.r16.dx) << 8;
+ if (regs.u.r8.ah == 0) {
+ outb(addr, regs.u.r8.al);
+ val8 = inb(addr+2);
+ outb(addr+2, val8 | 0x01); // send strobe
+ outb(addr+2, val8 & ~0x01);
+ while (((inb(addr+1) & 0x40) == 0x40) && (timeout)) {
+ timeout--;
+ }
+ }
+ if (regs.u.r8.ah == 1) {
+ val8 = inb(addr+2);
+ outb(addr+2, val8 & ~0x04); // send init
+ outb(addr+2, val8 | 0x04);
+ }
+ val8 = inb(addr+1);
+ regs.u.r8.ah = (val8 ^ 0x48);
+ if (!timeout) regs.u.r8.ah |= 0x01;
+ ClearCF(iret_addr.flags);
+ } else {
+ SetCF(iret_addr.flags); // Unsupported
+ }
+}
diff --git a/src/VBox/Devices/PC/BIOS/pci32.c b/src/VBox/Devices/PC/BIOS/pci32.c
new file mode 100644
index 00000000..eb05df64
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/pci32.c
@@ -0,0 +1,22 @@
+/* $Id: pci32.c $ */
+/** @file
+ * 32-bit PCI BIOS wrapper.
+ */
+
+/*
+ * Copyright (C) 2004-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef __386__
+#error This file must be compiled as 32-bit!
+#endif
+
+#include "pcibios.c"
diff --git a/src/VBox/Devices/PC/BIOS/pcibio32.asm b/src/VBox/Devices/PC/BIOS/pcibio32.asm
new file mode 100644
index 00000000..b423c588
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/pcibio32.asm
@@ -0,0 +1,98 @@
+; $Id: pcibio32.asm $
+;; @file
+; BIOS32 service directory and 32-bit PCI BIOS entry point
+;
+
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+
+
+; Public symbols for debugging only
+public pcibios32_entry
+public bios32_service
+
+; The BIOS32 service directory header must be located in the E0000h-FFFF0h
+; range on a paragraph boundary. Note that the actual 32-bit code need not
+; be located below 1MB at all.
+
+_DATA segment public 'DATA'
+
+align 16
+bios32_directory:
+ db '_32_' ; ASCII signature
+ dw bios32_service ; Entry point address...
+ dw 000Fh ; ...hardcoded to F000 segment
+ db 0 ; Revision
+ db 1 ; Length in paras - must be 1
+ db 0 ; Checksum calculated later
+ db 5 dup(0) ; Unused, must be zero
+
+_DATA ends
+
+.386
+
+extrn _pci32_function:near
+
+BIOS32 segment public 'CODE' use32
+
+;
+; The BIOS32 Service Directory - must be less than 4K in size (easy!).
+;
+bios32_service proc far
+
+ pushfd
+
+ cmp bl, 0 ; Only function 0 supported
+ jnz b32_bad_func
+
+ cmp eax, 'ICP$' ; "$PCI"
+ mov al, 80h ; Unknown service
+ jnz b32_done
+
+ mov ebx, 000f0000h ; Base address (linear)
+ mov ecx, 0f000h ; Length of service
+ mov edx, pcibios32_entry ; Entry point offset from base
+ xor al, al ; Indicate success
+b32_done:
+ popfd
+ retf
+
+b32_bad_func:
+ mov al, 81h ; Unsupported function
+ jmp b32_done
+
+bios32_service endp
+
+;
+; The 32-bit PCI BIOS entry point - simply calls into C code.
+;
+pcibios32_entry proc far
+
+ pushfd ; Preserve flags
+ cld ; Just in case...
+
+ push es ; Call into C implementation
+ pushad
+ call _pci32_function
+ popad
+ pop es
+
+ popfd ; Restore flags and return
+ retf
+
+pcibios32_entry endp
+
+
+BIOS32 ends
+
+ end
+
diff --git a/src/VBox/Devices/PC/BIOS/pcibios.c b/src/VBox/Devices/PC/BIOS/pcibios.c
new file mode 100644
index 00000000..7c33da8e
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/pcibios.c
@@ -0,0 +1,408 @@
+/* $Id: pcibios.c $ */
+/** @file
+ * PCI BIOS support.
+ */
+
+/*
+ * Copyright (C) 2004-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "biosint.h"
+#include "inlines.h"
+
+#if DEBUG_PCI
+# define BX_DEBUG_PCI(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define BX_DEBUG_PCI(...)
+#endif
+
+/* PCI function codes. */
+enum pci_func {
+ PCI_BIOS_PRESENT = 0x01, /* PCI BIOS presence check. */
+ FIND_PCI_DEVICE = 0x02, /* Find PCI device by ID. */
+ FIND_PCI_CLASS_CODE = 0x03, /* Find PCI device by class. */
+ GEN_SPECIAL_CYCLE = 0x06, /* Generate special cycle. */
+ READ_CONFIG_BYTE = 0x08, /* Read a byte from PCI config space. */
+ READ_CONFIG_WORD = 0x09, /* Read a word from PCI config space. */
+ READ_CONFIG_DWORD = 0x0A, /* Read a dword from PCI config space. */
+ WRITE_CONFIG_BYTE = 0x0B, /* Write a byte to PCI config space. */
+ WRITE_CONFIG_WORD = 0x0C, /* Write a word to PCI config space. */
+ WRITE_CONFIG_DWORD = 0x0D, /* Write a dword to PCI config space. */
+ GET_IRQ_ROUTING = 0x0E, /* Get IRQ routing table. */
+ SET_PCI_HW_INT = 0x0F, /* Set PCI hardware interrupt. */
+};
+
+enum pci_error {
+ SUCCESSFUL = 0x00, /* Success. */
+ FUNC_NOT_SUPPORTED = 0x81, /* Unsupported function. */
+ BAD_VENDOR_ID = 0x83, /* Bad vendor ID (all bits set) passed. */
+ DEVICE_NOT_FOUND = 0x86, /* No matching device found. */
+ BAD_REGISTER_NUMBER = 0x87, /* Register number out of range. */
+ SET_FAILED = 0x88, /* Failed to set PCI interrupt. */
+ BUFFER_TOO_SMALL = 0x89 /* Routing table buffer insufficient. */
+};
+
+/// @todo merge with system.c
+#define AX r.gr.u.r16.ax
+#define BX r.gr.u.r16.bx
+#define CX r.gr.u.r16.cx
+#define DX r.gr.u.r16.dx
+#define SI r.gr.u.r16.si
+#define DI r.gr.u.r16.di
+#define BP r.gr.u.r16.bp
+#define SP r.gr.u.r16.sp
+#define EAX r.gr.u.r32.eax
+#define EBX r.gr.u.r32.ebx
+#define ECX r.gr.u.r32.ecx
+#define EDX r.gr.u.r32.edx
+#define ES r.es
+
+/* The 16-bit PCI BIOS service must be callable from both real and protected
+ * mode. In protected mode, the caller must set the CS selector base to F0000h
+ * (but the CS selector value is not specified!). The caller does not always
+ * provide a DS which covers the BIOS segment.
+ *
+ * Unlike APM, there are no provisions for the 32-bit PCI BIOS interface
+ * calling the 16-bit implementation.
+ *
+ * The PCI Firmware Specification requires that the PCI BIOS service is called
+ * with at least 1,024 bytes of stack space available, that interrupts are not
+ * enabled during execution, and that the routines are re-entrant.
+ *
+ * Implementation notes:
+ * - The PCI BIOS interface already uses certain 32-bit registers even in
+ * 16-bit mode. To simplify matters, all 32-bit GPRs are saved/restored and
+ * may be used by helper routines (notably for 32-bit port I/O).
+ */
+
+#define PCI_CFG_ADDR 0xCF8
+#define PCI_CFG_DATA 0xCFC
+
+#ifdef __386__
+
+#define PCIxx(x) pci32_##x
+
+/* The stack layout is different in 32-bit mode. */
+typedef struct {
+ pushad_regs_t gr;
+ uint32_t es;
+ uint32_t flags;
+} pci_regs_t;
+
+#define FLAGS r.flags
+
+/* In 32-bit mode, don't do any output; not technically impossible but needs
+ * a lot of extra code.
+ */
+#undef BX_INFO
+#define BX_INFO(...)
+#undef BX_DEBUG_PCI
+#define BX_DEBUG_PCI(...)
+
+#else
+
+#define PCIxx(x) pci16_##x
+
+typedef struct {
+ pushad_regs_t gr;
+ uint16_t ds;
+ uint16_t es;
+ iret_addr_t ra;
+} pci_regs_t;
+
+#define FLAGS r.ra.flags.u.r16.flags
+
+#endif
+
+#ifdef __386__
+
+/* 32-bit code can just use the compiler intrinsics. */
+extern unsigned inpd(unsigned port);
+extern unsigned outpd(unsigned port, unsigned value);
+#pragma intrinsic(inpd,outpd)
+
+#else
+
+/// @todo merge with AHCI code
+
+/* Warning: Destroys high bits of EAX. */
+uint32_t inpd(uint16_t port);
+#pragma aux inpd = \
+ ".386" \
+ "in eax, dx" \
+ "mov dx, ax" \
+ "shr eax, 16" \
+ "xchg ax, dx" \
+ parm [dx] value [dx ax] modify nomemory;
+
+/* Warning: Destroys high bits of EAX. */
+void outpd(uint16_t port, uint32_t val);
+#pragma aux outpd = \
+ ".386" \
+ "xchg ax, cx" \
+ "shl eax, 16" \
+ "mov ax, cx" \
+ "out dx, eax" \
+ parm [dx] [cx ax] modify nomemory;
+
+#endif
+
+/* PCI IRQ routing expansion buffer descriptor. */
+typedef struct {
+ uint16_t buf_size;
+ uint8_t __far *buf_ptr;
+} pci_route_buf;
+
+/* Defined in assembler module .*/
+extern char pci_routing_table[];
+extern uint16_t pci_routing_table_size;
+
+/* Write the CONFIG_ADDRESS register to prepare for data access. Requires
+ * the register offset to be DWORD aligned (low two bits clear). Warning:
+ * destroys high bits of EAX.
+ */
+void pci16_w_addr(uint16_t bus_dev_fn, uint16_t ofs, uint16_t cfg_addr);
+#pragma aux pci16_w_addr = \
+ ".386" \
+ "movzx eax, ax" \
+ "shl eax, 8" \
+ "or eax, 80000000h" \
+ "mov al, bl" \
+ "out dx, eax" \
+ parm [ax] [bx] [dx] modify exact [ax] nomemory;
+
+
+/* Select a PCI configuration register given its offset and bus/dev/fn.
+ * This is largely a wrapper to avoid excessive inlining.
+ */
+void PCIxx(select_reg)(uint16_t bus_dev_fn, uint16_t ofs)
+{
+ pci16_w_addr(bus_dev_fn, ofs & ~3, PCI_CFG_ADDR);
+}
+
+/* Selected configuration space offsets. */
+#define PCI_VEN_ID 0x00
+#define PCI_DEV_ID 0x02
+#define PCI_REV_ID 0x08
+#define PCI_CLASS_CODE 0x09
+#define PCI_HEADER_TYPE 0x0E
+#define PCI_BRIDGE_SUBORD 0x1A
+
+/* To avoid problems with 16-bit code, we reserve the last possible
+ * bus/dev/fn combination (65,535). Upon reaching this location, the
+ * probing will end.
+ */
+#define BUSDEVFN_NOT_FOUND 0xFFFF
+
+/* In the search algorithm, we decrement the device index every time
+ * a matching device is found. If the requested device is indeed found,
+ * the index will have decremented down to -1/0xFFFF.
+ */
+#define INDEX_DEV_FOUND 0xFFFF
+
+/* Find a specified PCI device, either by vendor+device ID or class.
+ * If index is non-zero, the n-th device will be located.
+ *
+ * Note: This function is somewhat performance critical; since it may
+ * generate a high number of port I/O accesses, it can take a significant
+ * amount of time in cases where the caller is looking for a number of
+ * non-present devices.
+ */
+uint16_t PCIxx(find_device)(uint32_t search_item, uint16_t index, int search_class)
+{
+ uint32_t data;
+ uint16_t bus_dev_fn;
+ uint8_t max_bus;
+ uint8_t hdr_type;
+ uint8_t subordinate;
+ int step;
+ int found;
+
+ if (search_class) {
+ BX_DEBUG_PCI("PCI: Find class %08lX index %u\n",
+ search_item, index);
+ } else
+ BX_DEBUG_PCI("PCI: Find device %04X:%04X index %u\n",
+ (uint16_t)search_item, (uint16_t)(search_item >> 16), index);
+
+ bus_dev_fn = 0; /* Start at the beginning. */
+ max_bus = 0; /* Initially assume primary bus only. */
+
+ do {
+ /* For the first function of a device, read the device's header type.
+ * If the header type has all bits set, there's no device. A PCI
+ * multi-function device must implement function 0 and the header type
+ * will be something other than 0xFF. If the header type has the high
+ * bit clear, there is a device but it's not multi-function, so we can
+ * skip probing the next 7 sub-functions.
+ */
+ if ((bus_dev_fn & 7) == 0) {
+ PCIxx(select_reg)(bus_dev_fn, PCI_HEADER_TYPE);
+ hdr_type = inp(PCI_CFG_DATA + (PCI_HEADER_TYPE & 3));
+ if (hdr_type == 0xFF) {
+ bus_dev_fn += 8; /* Skip to next device. */
+ continue;
+ }
+ if (hdr_type & 0x80)
+ step = 1; /* MFD - try every sub-function. */
+ else
+ step = 8; /* No MFD, go to next device after probing. */
+ }
+
+ /* If the header type indicates a bus, we're interested. The secondary
+ * and subordinate bus numbers will indicate which buses are present;
+ * thus we can determine the highest bus number. In the common case,
+ * there will be only the primary bus (i.e. bus 0) and we can avoid
+ * looking at the remaining 255 theoretically present buses. This check
+ * only needs to be done on the primary bus, since bridges must report
+ * all bridges potentially behind them.
+ */
+ if ((hdr_type & 7) == 1 && (bus_dev_fn >> 8) == 0) {
+ /* Read the subordinate (last) bridge number. */
+ PCIxx(select_reg)(bus_dev_fn, PCI_BRIDGE_SUBORD);
+ subordinate = inp(PCI_CFG_DATA + (PCI_BRIDGE_SUBORD & 3));
+ if (subordinate > max_bus)
+ max_bus = subordinate;
+ }
+
+ /* Select the appropriate register. */
+ PCIxx(select_reg)(bus_dev_fn, search_class ? PCI_REV_ID : PCI_VEN_ID);
+ data = inpd(PCI_CFG_DATA);
+ found = 0;
+
+ /* Only 3 bytes are compared for class searches. */
+ if (search_class)
+ data >>= 8;
+
+#if 0
+ BX_DEBUG_PCI("PCI: Data is %08lX @ %02X:%%02X:%01X\n", data,
+ bus_dev_fn >> 8, bus_dev_fn >> 3 & 31, bus_dev_fn & 7);
+#endif
+
+ if (data == search_item)
+ found = 1;
+
+ /* If device was found but index is non-zero, decrement index and
+ * continue looking. If requested device was found, index will be -1!
+ */
+ if (found && !index--)
+ break;
+
+ bus_dev_fn += step;
+ } while ((bus_dev_fn >> 8) <= max_bus);
+
+ if (index == INDEX_DEV_FOUND)
+ BX_DEBUG_PCI("PCI: Device found (%02X:%%02X:%01X)\n", bus_dev_fn >> 8,
+ bus_dev_fn >> 3 & 31, bus_dev_fn & 7);
+
+ return index == INDEX_DEV_FOUND ? bus_dev_fn : BUSDEVFN_NOT_FOUND;
+}
+
+void BIOSCALL PCIxx(function)(volatile pci_regs_t r)
+{
+ pci_route_buf __far *route_buf;
+ uint16_t device;
+
+ BX_DEBUG_PCI("PCI: AX=%04X BX=%04X CX=%04X DI=%04X\n", AX, BX, CX, DI);
+
+ SET_AH(SUCCESSFUL); /* Assume success. */
+ CLEAR_CF();
+
+ switch (GET_AL()) {
+ case PCI_BIOS_PRESENT:
+ AX = 0x0001; /* Configuration mechanism #1 supported. */
+ BX = 0x0210; /* Version 2.1. */
+ /// @todo return true max bus # in CL
+ CX = 0; /* Maximum bus number. */
+ EDX = 'P' | ('C' << 8) | ((uint32_t)'I' << 16) | ((uint32_t)' ' << 24);
+ break;
+ case FIND_PCI_DEVICE:
+ /* Vendor ID FFFFh is reserved so that non-present devices can
+ * be easily detected.
+ */
+ if (DX == 0xFFFF) {
+ SET_AH(BAD_VENDOR_ID);
+ SET_CF();
+ } else {
+ device = PCIxx(find_device)(DX | (uint32_t)CX << 16, SI, 0);
+ if (device == BUSDEVFN_NOT_FOUND) {
+ SET_AH(DEVICE_NOT_FOUND);
+ SET_CF();
+ } else {
+ BX = device;
+ }
+ }
+ break;
+ case FIND_PCI_CLASS_CODE:
+ device = PCIxx(find_device)(ECX, SI, 1);
+ if (device == BUSDEVFN_NOT_FOUND) {
+ SET_AH(DEVICE_NOT_FOUND);
+ SET_CF();
+ } else {
+ BX = device;
+ }
+ break;
+ case READ_CONFIG_BYTE:
+ case READ_CONFIG_WORD:
+ case READ_CONFIG_DWORD:
+ case WRITE_CONFIG_BYTE:
+ case WRITE_CONFIG_WORD:
+ case WRITE_CONFIG_DWORD:
+ if (DI >= 256) {
+ SET_AH(BAD_REGISTER_NUMBER);
+ SET_CF();
+ } else {
+ PCIxx(select_reg)(BX, DI);
+ switch (GET_AL()) {
+ case READ_CONFIG_BYTE:
+ SET_CL(inp(PCI_CFG_DATA + (DI & 3)));
+ break;
+ case READ_CONFIG_WORD:
+ CX = inpw(PCI_CFG_DATA + (DI & 2));
+ break;
+ case READ_CONFIG_DWORD:
+ ECX = inpd(PCI_CFG_DATA);
+ break;
+ case WRITE_CONFIG_BYTE:
+ outp(PCI_CFG_DATA + (DI & 3), GET_CL());
+ break;
+ case WRITE_CONFIG_WORD:
+ outpw(PCI_CFG_DATA + (DI & 2), CX);
+ break;
+ case WRITE_CONFIG_DWORD:
+ outpd(PCI_CFG_DATA, ECX);
+ break;
+ }
+ }
+ break;
+ case GET_IRQ_ROUTING:
+ route_buf = ES :> (void *)DI;
+ BX_DEBUG_PCI("PCI: Route Buf %04X:%04X size %04X, need %04X (at %04X:%04X)\n",
+ FP_SEG(route_buf->buf_ptr), FP_OFF(route_buf->buf_ptr),
+ route_buf->buf_size, pci_routing_table_size, ES, DI);
+ if (pci_routing_table_size > route_buf->buf_size) {
+ SET_AH(BUFFER_TOO_SMALL);
+ SET_CF();
+ } else {
+ rep_movsb(route_buf->buf_ptr, pci_routing_table, pci_routing_table_size);
+ /* IRQs 9 and 11 are PCI only. */
+ BX = (1 << 9) | (1 << 11);
+ }
+ route_buf->buf_size = pci_routing_table_size;
+ break;
+ default:
+ BX_INFO("PCI: Unsupported function AX=%04X BX=%04X called\n", AX, BX);
+ SET_AH(FUNC_NOT_SUPPORTED);
+ SET_CF();
+ }
+}
diff --git a/src/VBox/Devices/PC/BIOS/pcibios.inc b/src/VBox/Devices/PC/BIOS/pcibios.inc
new file mode 100644
index 00000000..a3a2e6a9
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/pcibios.inc
@@ -0,0 +1,362 @@
+; $Id: pcibios.inc $
+;; @file
+; ???
+;
+
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+
+; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+; other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+; a choice of LGPL license versions is made available with the language indicating
+; that LGPLv2 or any later version may be used, or where a choice of which version
+; of the LGPL is applied is otherwise unspecified.
+
+
+include pcicfg.inc
+
+if BX_PCIBIOS
+
+ifdef DEBUG
+
+; Publics for easier debugging and disassembly
+
+public pcibios_init_iomem_bases
+public pci_init_io_loop1
+public pci_init_io_loop2
+public init_io_base
+public next_pci_base
+public enable_iomem_space
+public next_pci_dev
+public pcibios_init_set_elcr
+public is_master_pic
+public pcibios_init_irqs
+public pci_init_irq_loop1
+public pci_init_irq_loop2
+public pci_test_int_pin
+public pirq_found
+public next_pci_func
+public next_pir_entry
+public pci_init_end
+
+endif
+
+.386
+
+if not BX_ROMBIOS32
+pci_irq_list:
+ db 11, 10, 9, 11
+
+pcibios_init_sel_reg:
+ push eax
+ mov eax, 800000h
+ mov ax, bx
+ shl eax, 8
+ and dl, 0FCh
+ or al, dl
+ mov dx, PCI_CFG1
+ out dx, eax
+ pop eax
+ ret
+
+pcibios_init_iomem_bases:
+ push bp
+ mov bp, sp
+ifdef VBOX
+ mov eax,19200509
+ mov dx,410h
+ out dx, eax
+else
+; This incomplete PCI resource setup code is less functional than the PCI
+; resource assignment created by the fake PCI BIOS and is therefore disabled.
+; Blindly enabling everything on the root bus (including bus mastering!) can
+; only be called buggy. It causes the trouble with AMD PCNet which it then
+; tries to work around, but that still contains a race.
+ mov eax, 0E0000000h ; base for memory init
+ push eax
+ mov ax, 0D000h ; base for i/o init
+ push ax
+ mov ax, 010h ; start at base address #0
+ push ax
+ mov bx, 8
+pci_init_io_loop1:
+ mov dl, 0
+ call pcibios_init_sel_reg
+ mov dx, PCI_CFG2
+ in ax, dx
+ cmp ax, 0FFFFh
+ jz next_pci_dev
+
+ifndef VBOX ; This currently breaks restoring a previously saved state.
+ mov dl, 4 ; disable i/o and memory space access
+ call pcibios_init_sel_reg
+ mov dx, PCI_CFG2
+ in al, dx
+ and al, 0FCh
+ out dx, al
+pci_init_io_loop2:
+ mov dl, [bp-8]
+ call pcibios_init_sel_reg
+ mov dx, PCI_CFG2
+ in eax, dx
+ test al, 1
+ jnz init_io_base
+
+ mov ecx, eax
+ mov eax, 0FFFFFFFFh
+ out dx, eax
+ in eax, dx
+ cmp eax, ecx
+ je next_pci_base
+ xor eax, 0FFFFFFFFh
+ mov ecx, eax
+ mov eax, [bp-4]
+ out dx, eax
+ add eax, ecx ; calculate next free mem base
+ add eax, 01000000h
+ and eax, 0FF000000h
+ mov [bp-4], eax
+ jmp next_pci_base
+
+init_io_base:
+ mov cx, ax
+ mov ax, 0FFFFh
+ out dx, eax
+ in eax, dx
+ cmp ax, cx
+ je next_pci_base
+
+ xor ax, 0FFFEh
+ mov cx, ax
+ mov ax, [bp-6]
+ out dx, eax
+ add ax, cx ; calculate next free i/o base
+ add ax, 00100h
+ and ax, 0FF00h
+ mov [bp-6], ax
+next_pci_base:
+ mov al, [bp-8]
+ add al, 4
+ cmp al, 28h
+ je enable_iomem_space
+
+ mov byte ptr[bp-8], al
+ jmp pci_init_io_loop2
+endif ; !VBOX
+
+enable_iomem_space:
+ mov dl, 4 ;; enable i/o and memory space access if available
+ call pcibios_init_sel_reg
+ mov dx, PCI_CFG2
+ in al, dx
+ or al, 7
+ out dx, al
+ifdef VBOX
+ mov dl, 0 ; check if PCI device is AMD PCNet
+ call pcibios_init_sel_reg
+ mov dx, PCI_CFG2
+ in eax, dx
+ cmp eax, 020001022h
+ jne next_pci_dev
+
+ mov dl, 10h ; get I/O address
+ call pcibios_init_sel_reg
+ mov dx, PCI_CFG2
+ in ax, dx
+ and ax, 0FFFCh
+ mov cx, ax
+ mov dx, cx
+ add dx, 14h ; reset register if PCNet is in word I/O mode
+ in ax, dx ; reset is performed by reading the reset register
+ mov dx, cx
+ add dx, 18h ; reset register if PCNet is in word I/O mode
+ in eax, dx ; reset is performed by reading the reset register
+endif ; VBOX
+next_pci_dev:
+ mov byte ptr[bp-8], 10h
+ inc bx
+ cmp bx, 0100h
+ jne pci_init_io_loop1
+endif ; !VBOX
+ mov sp, bp
+ pop bp
+ ret
+
+pcibios_init_set_elcr:
+ push ax
+ push cx
+ mov dx, 04D0h
+ test al, 8
+ jz is_master_pic
+
+ inc dx
+ and al, 7
+is_master_pic:
+ mov cl, al
+ mov bl, 1
+ shl bl, cl
+ in al, dx
+ or al, bl
+ out dx, al
+ pop cx
+ pop ax
+ ret
+
+pcibios_init_irqs:
+ push ds
+ push bp
+ mov ax, 0F000h
+ mov ds, ax
+ifndef VBOX
+; this code works OK, but it's unnecessary effort since the fake PCI BIOS
+; already configured the IRQ lines and the ELCR correctly
+ mov dx, 04D0h ;; reset ELCR1 + ELCR2
+ mov al, 0
+ out dx, al
+ inc dx
+ out dx, al
+ mov si, pci_routing_table_structure
+ mov bh, [si+8]
+ mov bl, [si+9]
+ mov dl, 0
+ call pcibios_init_sel_reg
+ mov dx, PCI_CFG2
+ in eax, dx
+ cmp eax, [si+12] ;; check irq router
+ jne pci_init_end
+
+ mov dl, [si+34]
+ call pcibios_init_sel_reg
+ push bx ;; save irq router bus + devfunc
+ mov dx, PCI_CFG2
+ mov ax, 8080h
+ out dx, ax ;; reset PIRQ route control
+ add dx, 2
+ out dx, ax
+ mov ax, [si+6]
+ sub ax, 20h
+ shr ax, 4
+ mov cx, ax
+ add si, 20h ;; set pointer to 1st entry
+ mov bp, sp
+ mov ax, pci_irq_list
+ push ax
+ xor ax, ax
+ push ax
+pci_init_irq_loop1:
+ mov bh, [si]
+ mov bl, [si+1]
+pci_init_irq_loop2:
+ mov dl, 0
+ call pcibios_init_sel_reg
+ mov dx, PCI_CFG2
+ in ax, dx
+ cmp ax, 0FFFFh
+ jnz pci_test_int_pin
+
+ test bl, 7
+ jz next_pir_entry
+
+ jmp next_pci_func
+
+pci_test_int_pin:
+ mov dl, 3Ch
+ call pcibios_init_sel_reg
+ mov dx, PCI_CFG2 + 1 ; access config space at 3Dh
+ in al, dx
+ and al, 7
+ jz next_pci_func
+
+ dec al ;; determine pirq reg
+ mov dl, 3
+ mul dl
+ add al, 2
+ xor ah, ah
+ mov bx, ax
+ mov al, [si+bx]
+ mov dl, al
+ mov bx, [bp]
+ call pcibios_init_sel_reg
+ mov dx, PCI_CFG2
+ and al, 3
+ add dl, al
+ in al, dx
+ cmp al, 80h
+ jb pirq_found
+
+ mov bx, [bp-2] ;; pci irq list pointer
+ mov al, [bx]
+ out dx, al
+ inc bx
+ mov [bp-2], bx
+ call pcibios_init_set_elcr
+pirq_found:
+ mov bh, [si]
+ mov bl, [si+1]
+ add bl, [bp-3] ;; pci function number
+ mov dl, 3Ch
+ call pcibios_init_sel_reg
+ mov dx, PCI_CFG2
+ out dx, al
+next_pci_func:
+ inc byte ptr[bp-3]
+ inc bl
+ test bl, 7
+ jnz pci_init_irq_loop2
+
+next_pir_entry:
+ add si, 10h
+ mov byte ptr[bp-3], 0
+ loop pci_init_irq_loop1
+
+ mov sp, bp
+ pop bx
+pci_init_end:
+endif
+ pop bp
+ pop ds
+ ret
+
+endif ; !BX_ROMBIOS32
+
+endif ; BX_PCIBIOS
+
+SET_DEFAULT_CPU_286
+
diff --git a/src/VBox/Devices/PC/BIOS/pcicfg.inc b/src/VBox/Devices/PC/BIOS/pcicfg.inc
new file mode 100644
index 00000000..83e2c2d5
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/pcicfg.inc
@@ -0,0 +1,6 @@
+
+BX_PCIBIOS equ 1 ; Enable PCI BIOS
+
+PCI_CFG1 equ 0CF8h
+PCI_CFG2 equ 0CFCh
+
diff --git a/src/VBox/Devices/PC/BIOS/pciutil.c b/src/VBox/Devices/PC/BIOS/pciutil.c
new file mode 100644
index 00000000..49ff0877
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/pciutil.c
@@ -0,0 +1,186 @@
+/* $Id: pciutil.c $ */
+/** @file
+ * Utility routines for calling the PCI BIOS.
+ */
+
+/*
+ * Copyright (C) 2011-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "biosint.h"
+#include "inlines.h"
+
+/** PCI BIOS functions. */
+#define PCIBIOS_ID 0xb1
+#define PCIBIOS_PCI_BIOS_PRESENT 0x01
+#define PCIBIOS_FIND_PCI_DEVICE 0x02
+#define PCIBIOS_FIND_CLASS_CODE 0x03
+#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0x06
+#define PCIBIOS_READ_CONFIG_BYTE 0x08
+#define PCIBIOS_READ_CONFIG_WORD 0x09
+#define PCIBIOS_READ_CONFIG_DWORD 0x0a
+#define PCIBIOS_WRITE_CONFIG_BYTE 0x0b
+#define PCIBIOS_WRITE_CONFIG_WORD 0x0c
+#define PCIBIOS_WRITE_CONFIG_DWORD 0x0d
+#define PCIBIOS_GET_IRQ_ROUTING_OPTIONS 0x0e
+#define PCIBIOS_SET_PCI_IRQ 0x0f
+
+/** Status codes. */
+#define SUCCESSFUL 0x00
+#define FUNC_NOT_SUPPORTED 0x81
+#define BAD_VENDOR_ID 0x83
+#define DEVICE_NOT_FOUND 0x86
+#define BAD_REGISTER_NUMBER 0x87
+#define SET_FAILED 0x88
+#define BUFFER_TOO_SMALL 0x89
+
+
+#if VBOX_BIOS_CPU >= 80386
+/* Warning: Destroys high bits of ECX. */
+uint16_t pci_find_class(uint16_t op, uint32_t dev_class, uint16_t index);
+# pragma aux pci_find_class = \
+ ".386" \
+ "shl ecx, 16" \
+ "mov cx, dx" \
+ "int 0x1a" \
+ "cmp ah, 0" \
+ "je found" \
+ "mov bx, 0xffff" \
+ "found:" \
+ parm [ax] [cx dx] [si] value [bx];
+#endif
+
+uint16_t pci_find_dev(uint16_t op, uint16_t dev_id, uint16_t ven_id, uint16_t index);
+#pragma aux pci_find_dev = \
+ "int 0x1a" \
+ "cmp ah, 0" \
+ "je found" \
+ "mov bx, 0xffff" \
+ "found:" \
+ parm [ax] [cx] [dx] [si] value [bx];
+
+uint8_t pci_read_cfgb(uint16_t op, uint16_t bus_dev_fn, uint16_t reg);
+#pragma aux pci_read_cfgb = \
+ "int 0x1a" \
+ parm [ax] [bx] [di] value [cl];
+
+uint16_t pci_read_cfgw(uint16_t op, uint16_t bus_dev_fn, uint16_t reg);
+#pragma aux pci_read_cfgw = \
+ "int 0x1a" \
+ parm [ax] [bx] [di] value [cx];
+
+#if VBOX_BIOS_CPU >= 80386
+/* Warning: Destroys high bits of ECX. */
+uint32_t pci_read_cfgd(uint16_t op, uint16_t bus_dev_fn, uint16_t reg);
+# pragma aux pci_read_cfgd = \
+ ".386" \
+ "int 0x1a" \
+ "mov ax, cx" \
+ "shr ecx, 16" \
+ parm [ax] [bx] [di] value [cx ax];
+#endif
+
+uint8_t pci_write_cfgb(uint16_t op, uint16_t bus_dev_fn, uint16_t reg, uint8_t val);
+#pragma aux pci_write_cfgb = \
+ "int 0x1a" \
+ parm [ax] [bx] [di] [cl];
+
+uint8_t pci_write_cfgw(uint16_t op, uint16_t bus_dev_fn, uint16_t reg, uint16_t val);
+#pragma aux pci_write_cfgw = \
+ "int 0x1a" \
+ parm [ax] [bx] [di] [cx];
+
+#if VBOX_BIOS_CPU >= 80386
+/* Warning: Destroys high bits of ECX. */
+uint8_t pci_write_cfgd(uint16_t op, uint16_t bus_dev_fn, uint16_t reg, uint32_t val);
+# pragma aux pci_write_cfgd = \
+ ".386" \
+ "xchg cx, dx" \
+ "shl ecx, 16" \
+ "mov cx, dx" \
+ "int 0x1a" \
+ parm [ax] [bx] [di] [dx cx];
+#endif
+
+
+/**
+ * Returns the bus/device/function of a PCI device with
+ * the given class code.
+ *
+ * @returns bus/device/fn in a 16-bit integer where
+ * where the upper byte contains the bus number
+ * and lower one the device and function number.
+ * 0xffff if no device was found.
+ * @param dev_class The PCI class code to search for.
+ */
+uint16_t pci_find_classcode(uint32_t dev_class)
+{
+#if VBOX_BIOS_CPU >= 80386
+ return pci_find_class((PCIBIOS_ID << 8) | PCIBIOS_FIND_CLASS_CODE, dev_class, 0);
+#else
+ return UINT16_C(0xffff);
+#endif
+}
+
+/**
+ * Returns the bus/device/function of a PCI device with
+ * the given vendor and device id.
+ *
+ * @returns bus/device/fn in one 16bit integer where
+ * where the upper byte contains the bus number
+ * and lower one the device and function number.
+ * 0xffff if no device was found.
+ * @param v_id The vendor ID.
+ * @param d_id The device ID.
+ */
+uint16_t pci_find_device(uint16_t v_id, uint16_t d_id)
+{
+ return pci_find_dev((PCIBIOS_ID << 8) | PCIBIOS_FIND_PCI_DEVICE, d_id, v_id, 0);
+}
+
+uint32_t pci_read_config_byte(uint8_t bus, uint8_t dev_fn, uint8_t reg)
+{
+ return pci_read_cfgb((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_BYTE, (bus << 8) | dev_fn, reg);
+}
+
+uint32_t pci_read_config_word(uint8_t bus, uint8_t dev_fn, uint8_t reg)
+{
+ return pci_read_cfgw((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_WORD, (bus << 8) | dev_fn, reg);
+}
+
+uint32_t pci_read_config_dword(uint8_t bus, uint8_t dev_fn, uint8_t reg)
+{
+#if VBOX_BIOS_CPU >= 80386
+ return pci_read_cfgd((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_DWORD, (bus << 8) | dev_fn, reg);
+#else
+ return pci_read_cfgw((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_WORD, (bus << 8) | dev_fn, reg)
+ || ((uint32_t)pci_read_cfgw((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_WORD, (bus << 8) | dev_fn, reg + 2) << 16);
+#endif
+}
+
+void pci_write_config_word(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint16_t val)
+{
+ pci_write_cfgw((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_WORD, (bus << 8) | dev_fn, reg, val);
+}
+
+#if 0 /* Disabled to save space because they are not needed. Might become useful in the future. */
+void pci_write_config_byte(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint8_t val)
+{
+ pci_write_cfgb((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_BYTE, (bus << 8) | dev_fn, reg, val);
+}
+
+void pci_write_config_dword(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint32_t val)
+{
+ pci_write_cfgd((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_DWORD, (bus << 8) | dev_fn, reg, val);
+}
+#endif /* 0 */
diff --git a/src/VBox/Devices/PC/BIOS/pciutil.h b/src/VBox/Devices/PC/BIOS/pciutil.h
new file mode 100644
index 00000000..ad50ed82
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/pciutil.h
@@ -0,0 +1,37 @@
+/* $Id: pciutil.h $ */
+/** @file
+ * Utility routines for calling the PCI BIOS.
+ */
+
+/*
+ * Copyright (C) 2011-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_INCLUDED_SRC_PC_BIOS_pciutil_h
+#define VBOX_INCLUDED_SRC_PC_BIOS_pciutil_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+extern uint16_t pci_find_device(uint16_t v_id, uint16_t d_id);
+/* Warning: pci_find_classcode destroys the high bits of ECX. */
+extern uint16_t pci_find_classcode(uint32_t dev_class);
+extern uint32_t pci_read_config_byte(uint8_t bus, uint8_t dev_fn, uint8_t reg);
+extern uint32_t pci_read_config_word(uint8_t bus, uint8_t dev_fn, uint8_t reg);
+/* Warning: pci_read_config_dword destroys the high bits of ECX. */
+extern uint32_t pci_read_config_dword(uint8_t bus, uint8_t dev_fn, uint8_t reg);
+extern void pci_write_config_byte(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint8_t val);
+extern void pci_write_config_word(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint16_t val);
+/* Warning: pci_write_config_dword destroys the high bits of ECX. */
+extern void pci_write_config_dword(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint32_t val);
+
+#endif /* !VBOX_INCLUDED_SRC_PC_BIOS_pciutil_h */
+
diff --git a/src/VBox/Devices/PC/BIOS/pirq.inc b/src/VBox/Devices/PC/BIOS/pirq.inc
new file mode 100644
index 00000000..7dd4040f
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/pirq.inc
@@ -0,0 +1,477 @@
+; $Id: pirq.inc $
+;; @file
+; ???
+;
+
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+;
+
+; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+; other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+; a choice of LGPL license versions is made available with the language indicating
+; that LGPLv2 or any later version may be used, or where a choice of which version
+; of the LGPL is applied is otherwise unspecified.
+
+
+if BX_PCIBIOS
+public _pci_routing_table
+public _pci_routing_table_size
+
+align 16
+pci_routing_table_structure:
+ db '$PIR' ;; "$PIR" signature
+ db 0, 1 ;; version
+ifdef VBOX
+ dw 32 + (30 * 16) ;; table size
+else ; !VBOX
+ dw 32 + (6 * 16) ;; table size
+endif ; !VBOX
+ db 0 ;; PCI interrupt router bus
+ db 8 ;; PCI interrupt router DevFunc
+ dw 0000h ;; PCI exclusive IRQs
+ dw 8086h ;; compatible PCI interrupt router vendor ID
+ dw 7000h ;; compatible PCI interrupt router device ID
+ dw 0,0 ;; Miniport data
+ db 0,0,0,0,0,0,0,0,0,0,0 ;; reserved
+ifdef VBOX
+ db 0 ;; checksum (set by biossums)
+else ; !VBOX
+ db 7 ;; checksum
+endif ; !VBOX
+_pci_routing_table:
+pci_routing_table:
+ ;; first slot entry PCI-to-ISA (embedded)
+ db 0 ;; pci bus number
+ db 008h ;; pci device number (bit 7-3)
+ db 60h ;; link value INTA#: pointer into PCI2ISA config space
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 61h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 62h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 63h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 0 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; second slot entry: 1st PCI slot
+ db 0 ;; pci bus number
+ db 010h ;; pci device number (bit 7-3)
+ db 61h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 62h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 63h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 60h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 1 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; third slot entry: 2nd PCI slot
+ db 0 ;; pci bus number
+ db 018h ;; pci device number (bit 7-3)
+ db 62h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 63h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 60h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 61h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 2 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 4th slot entry: 3rd PCI slot
+ db 0 ;; pci bus number
+ db 020h ;; pci device number (bit 7-3)
+ db 63h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 60h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 61h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 62h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 3 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 5th slot entry: 4th PCI slot
+ db 0 ;; pci bus number
+ db 028h ;; pci device number (bit 7-3)
+ db 60h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 61h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 62h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 63h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 4 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 6th slot entry: 5th PCI slot
+ db 0 ;; pci bus number
+ db 030h ;; pci device number (bit 7-3)
+ db 61h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 62h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 63h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 60h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 5 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ifdef VBOX
+ ;; 7th slot entry: 6th PCI slot
+ db 0 ;; pci bus number
+ db 038h ;; pci device number (bit 7-3)
+ db 62h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 63h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 60h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 61h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 6 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 8th slot entry: 7th PCI slot
+ db 0 ;; pci bus number
+ db 040h ;; pci device number (bit 7-3)
+ db 63h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 60h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 61h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 62h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 7 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 9th slot entry: 8th PCI slot
+ db 0 ;; pci bus number
+ db 048h ;; pci device number (bit 7-3)
+ db 60h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 61h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 62h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 63h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 8 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 10th slot entry: 9th PCI slot
+ db 0 ;; pci bus number
+ db 050h ;; pci device number (bit 7-3)
+ db 61h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 62h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 63h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 60h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 9 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 11th slot entry: 10th PCI slot
+ db 0 ;; pci bus number
+ db 058h ;; pci device number (bit 7-3)
+ db 62h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 63h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 60h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 61h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 10 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 12th slot entry: 11th PCI slot
+ db 0 ;; pci bus number
+ db 60h ;; pci device number (bit 7-3)
+ db 63h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 60h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 61h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 62h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 11 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 13th slot entry: 12th PCI slot
+ db 0 ;; pci bus number
+ db 068h ;; pci device number (bit 7-3)
+ db 60h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 61h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 62h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 63h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 12 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 14th slot entry: 13th PCI slot
+ db 0 ;; pci bus number
+ db 070h ;; pci device number (bit 7-3)
+ db 61h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 62h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 63h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 60h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 13 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 15th slot entry: 14th PCI slot
+ db 0 ;; pci bus number
+ db 078h ;; pci device number (bit 7-3)
+ db 62h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 63h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 60h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 61h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 14 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 16th slot entry: 15th PCI slot
+ db 0 ;; pci bus number
+ db 080h ;; pci device number (bit 7-3)
+ db 63h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 60h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 61h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 62h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 15 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 17th slot entry: 16th PCI slot
+ db 0 ;; pci bus number
+ db 088h ;; pci device number (bit 7-3)
+ db 60h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 61h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 62h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 63h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 16 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 18th slot entry: 17th PCI slot
+ db 0 ;; pci bus number
+ db 090h ;; pci device number (bit 7-3)
+ db 61h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 62h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 63h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 60h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 17 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 19th slot entry: 18th PCI slot
+ db 0 ;; pci bus number
+ db 098h ;; pci device number (bit 7-3)
+ db 62h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 63h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 60h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 61h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 18 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 20th slot entry: 19th PCI slot
+ db 0 ;; pci bus number
+ db 0A0h ;; pci device number (bit 7-3)
+ db 63h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 60h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 61h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 62h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 19 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 21st slot entry: 20th PCI slot
+ db 0 ;; pci bus number
+ db 0A8h ;; pci device number (bit 7-3)
+ db 60h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 61h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 62h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 63h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 20 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 22nd slot entry: 21st PCI slot
+ db 0 ;; pci bus number
+ db 0B0h ;; pci device number (bit 7-3)
+ db 61h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 62h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 63h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 60h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 21 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 23rd slot entry: 22nd PCI slot
+ db 0 ;; pci bus number
+ db 0B8h ;; pci device number (bit 7-3)
+ db 62h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 63h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 60h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 61h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 22 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 24th slot entry: 23rd PCI slot
+ db 0 ;; pci bus number
+ db 0C0h ;; pci device number (bit 7-3)
+ db 63h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 60h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 61h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 62h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 23 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 25th slot entry: 24th PCI slot
+ db 0 ;; pci bus number
+ db 0C8h ;; pci device number (bit 7-3)
+ db 60h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 61h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 62h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 63h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 24 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 26th slot entry: 25th PCI slot
+ db 0 ;; pci bus number
+ db 0D0h ;; pci device number (bit 7-3)
+ db 61h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 62h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 63h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 60h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 25 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 27th slot entry: 26th PCI slot
+ db 0 ;; pci bus number
+ db 0D8h ;; pci device number (bit 7-3)
+ db 62h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 63h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 60h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 61h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 26 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 28th slot entry: 27th PCI slot
+ db 0 ;; pci bus number
+ db 0E0h ;; pci device number (bit 7-3)
+ db 63h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 60h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 61h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 62h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 27 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 29th slot entry: 28th PCI slot
+ db 0 ;; pci bus number
+ db 0E8h ;; pci device number (bit 7-3)
+ db 60h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 61h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 62h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 63h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 28 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+ ;; 30th slot entry: 29th PCI slot
+ db 0 ;; pci bus number
+ db 0F0h ;; pci device number (bit 7-3)
+ db 61h ;; link value INTA#
+ dw 0DEF8h ;; IRQ bitmap INTA#
+ db 62h ;; link value INTB#
+ dw 0DEF8h ;; IRQ bitmap INTB#
+ db 63h ;; link value INTC#
+ dw 0DEF8h ;; IRQ bitmap INTC#
+ db 60h ;; link value INTD#
+ dw 0DEF8h ;; IRQ bitmap INTD#
+ db 29 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
+endif ; VBOX
+pci_routing_table_end:
+;; Size of the table
+_pci_routing_table_size dw pci_routing_table_end - pci_routing_table
+
+endif ; BX_PCIBIOS
diff --git a/src/VBox/Devices/PC/BIOS/pmode.inc b/src/VBox/Devices/PC/BIOS/pmode.inc
new file mode 100644
index 00000000..fba20b8d
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/pmode.inc
@@ -0,0 +1,81 @@
+; $Id: pmode.inc $
+;; @file
+; Enter and exit a minimal protected-mode environment.
+;
+
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;; Caveats: May only be called from the F000 segment (16-bit). Does not
+;; switch stacks. Must be run with disabled interrupts(!), any exceptions
+;; will cause a crash. On return from pmode_enter, DS contains a selector
+;; which can address the entire 4GB address space.
+
+public pmode_enter
+public pmode_exit
+public pmbios_gdt_desc
+public pmbios_gdt
+
+pmode_enter proc near
+
+ push cs
+ pop ds
+ .386p
+ lgdt fword ptr [pmbios_gdt_desc]
+ mov eax, cr0
+ or al, 1
+ mov cr0, eax
+; jmp far ptr 20h:really_enter_pm
+ db 0EAh
+ dw really_enter_pm
+ dw 20h
+really_enter_pm:
+ mov ax, 18h
+ mov ds, ax
+ ret
+
+pmode_enter endp
+
+
+pmode_exit proc near
+
+ mov ax, 40h ; Ensure RM limit/attributes
+ mov ds, ax ; (where base = selector << 4)
+
+ mov eax, cr0
+ and al, 0FEh
+ mov cr0, eax
+ SET_DEFAULT_CPU_286
+ jmp far ptr really_exit_pm
+really_exit_pm:
+ ret
+
+pmode_exit endp
+
+
+
+pmbios_gdt_desc:
+ dw 40h + 7 ; last selector plus 8 - 1
+ dw pmbios_gdt
+ dw 000Fh
+
+pmbios_gdt:
+ dw 0, 0, 0, 0
+ dw 0, 0, 0, 0
+ dw 0ffffh, 0, 9b00h, 00cfh ; 32-bit code (0x10)
+ dw 0ffffh, 0, 9300h, 00cfh ; 32-bit data (0x18)
+ dw 0ffffh, 0, 9b0fh, 0000h ; 16-bit code, base=0xf0000
+ dw 0ffffh, 0, 9300h, 0000h ; 16-bit data, base=0x0
+ dw 0, 0, 0, 0
+ dw 0, 0, 0, 0
+ dw 0ffffh, 400h, 9300h, 0000h ; 16-bit data, base=0x40
+
diff --git a/src/VBox/Devices/PC/BIOS/pmsetup.inc b/src/VBox/Devices/PC/BIOS/pmsetup.inc
new file mode 100644
index 00000000..383b0709
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/pmsetup.inc
@@ -0,0 +1,65 @@
+; $Id: pmsetup.inc $
+;; @file
+; Initial system setup which needs to run in protected mode.
+;
+
+;
+; Copyright (C) 2004-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+SVR equ 0FEE000F0h
+LVT_LINT0 equ 0FEE00350h
+LVT_LINT1 equ 0FEE00360h
+
+public pmode_setup
+
+;; Enable the local APIC and program LINT0/LINT1 entries. Without that,
+;; virtual wire interrupts could not be delivered. Note that the APIC must
+;; be enabled first because when disabled, all LVTs are forced masked.
+
+pmode_setup proc near
+
+ .386
+ push eax
+ push esi
+ pushf
+ cli ; Interrupts would kill us!
+ call pmode_enter
+
+ mov eax, cr0 ; Clear CR0.CD and CR0.NW
+ and eax, 09FFFFFFFh
+ mov cr0, eax
+
+ mov esi, SVR ; Program the SVR -- enable the APIC,
+ mov eax, 010Fh ; set spurious interrupt vector to 15
+ mov [esi], eax
+
+ mov esi, LVT_LINT0 ; Program LINT0 to ExtINT and unmask
+ mov eax, [esi]
+ and eax, 0FFFE00FFh
+ or ah, 7
+ mov [esi], eax
+
+ mov esi, LVT_LINT1 ; Program LINT1 to NMI and unmask
+ mov eax, [esi]
+ and eax, 0FFFE00FFh
+ or ah, 4
+ mov [esi], eax
+
+ call pmode_exit
+ popf
+ pop esi
+ pop eax
+ SET_DEFAULT_CPU_286
+ ret
+
+pmode_setup endp
+
diff --git a/src/VBox/Devices/PC/BIOS/post.c b/src/VBox/Devices/PC/BIOS/post.c
new file mode 100644
index 00000000..f7834d2c
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/post.c
@@ -0,0 +1,183 @@
+/* $Id: post.c $ */
+/** @file
+ * BIOS POST routines. Used only during initialization.
+ */
+
+/*
+ * Copyright (C) 2004-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "biosint.h"
+#include "inlines.h"
+
+#if DEBUG_POST
+# define DPRINT(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define DPRINT(...)
+#endif
+
+/* In general, checksumming ROMs in a VM just wastes time. */
+//#define CHECKSUM_ROMS
+
+/* The format of a ROM is as follows:
+ *
+ * ------------------------------
+ * 0 | AA55h signature (word) |
+ * ------------------------------
+ * 2 | Size in 512B blocks (byte) |
+ * ------------------------------
+ * 3 | Start of executable code |
+ * | ....... |
+ * end | |
+ * ------------------------------
+ */
+
+typedef struct rom_hdr_tag {
+ uint16_t signature;
+ uint8_t num_blks;
+ uint8_t code;
+} rom_hdr;
+
+
+/* Calculate the checksum of a ROM. Note that the ROM might be
+ * larger than 64K.
+ */
+static inline uint8_t rom_checksum(uint8_t __far *rom, uint8_t blocks)
+{
+ uint8_t sum = 0;
+
+#ifdef CHECKSUM_ROMS
+ while (blocks--) {
+ int i;
+
+ for (i = 0; i < 512; ++i)
+ sum += rom[i];
+ /* Add 512 bytes (32 paragraphs) to segment. */
+ rom = MK_FP(FP_SEG(rom) + (512 >> 4), 0);
+ }
+#endif
+ return sum;
+}
+
+/* Scan for ROMs in the given range and execute their POST code. */
+void rom_scan(uint16_t start_seg, uint16_t end_seg)
+{
+ rom_hdr __far *rom;
+ uint8_t rom_blks;
+
+ DPRINT("Scanning for ROMs in %04X-%04X range\n", start_seg, end_seg);
+
+ while (start_seg < end_seg) {
+ rom = MK_FP(start_seg, 0);
+ /* Check for the ROM signature. */
+ if (rom->signature == 0xAA55) {
+ DPRINT("Found ROM at segment %04X\n", start_seg);
+ if (!rom_checksum((void __far *)rom, rom->num_blks)) {
+ void (__far * rom_init)(void);
+
+ /* Checksum good, initialize ROM. */
+ rom_init = (void __far *)&rom->code;
+ rom_init();
+ int_disable();
+ DPRINT("ROM initialized\n");
+
+ /* Continue scanning past the end of this ROM. */
+ rom_blks = (rom->num_blks + 3) & ~3; /* 4 blocks = 2K */
+ start_seg += rom_blks / 4;
+ }
+ } else {
+ /* Scanning is done in 2K steps. */
+ start_seg += 2048 >> 4;
+ }
+ }
+}
+
+#if VBOX_BIOS_CPU >= 80386
+
+/* NB: The CPUID detection is generic but currently not used elsewhere. */
+
+/* Check CPUID availability. */
+int is_cpuid_supported( void )
+{
+ uint32_t old_flags, new_flags;
+
+ old_flags = eflags_read();
+ new_flags = old_flags ^ (1L << 21); /* Toggle CPUID bit. */
+ eflags_write( new_flags );
+ new_flags = eflags_read();
+ return( old_flags != new_flags ); /* Supported if bit changed. */
+}
+
+#define APICMODE_DISABLED 0
+#define APICMODE_APIC 1
+#define APICMODE_X2APIC 2
+
+#define APIC_BASE_MSR 0x1B
+#define APICBASE_X2APIC 0x400 /* bit 10 */
+#define APICBASE_ENABLE 0x800 /* bit 11 */
+
+/*
+ * Set up APIC/x2APIC. See also DevPcBios.cpp.
+ *
+ * NB: Virtual wire compatibility is set up earlier in 32-bit protected
+ * mode assembler (because it needs to access MMIO just under 4GB).
+ * Switching to x2APIC mode or disabling the APIC is done through an MSR
+ * and needs no 32-bit addressing. Going to x2APIC mode does not lose the
+ * existing virtual wire setup.
+ *
+ * NB: This code does not assume that there is a local APIC. It is necessary
+ * to check CPUID whether APIC is present; the CPUID instruction might not be
+ * available either.
+ *
+ * NB: Destroys high bits of 32-bit registers.
+ */
+void BIOSCALL apic_setup(void)
+{
+ uint64_t base_msr;
+ uint16_t mask_set;
+ uint16_t mask_clr;
+ uint8_t apic_mode;
+ uint32_t cpu_id[4];
+
+ /* If there's no CPUID, there's certainly no APIC. */
+ if (!is_cpuid_supported()) {
+ return;
+ }
+
+ /* Check EDX bit 9 */
+ cpuid(&cpu_id, 1);
+ BX_DEBUG("CPUID EDX: 0x%lx\n", cpu_id[3]);
+ if ((cpu_id[3] & (1 << 9)) == 0) {
+ return; /* No local APIC, nothing to do. */
+ }
+
+ /* APIC mode at offset 78h in CMOS NVRAM. */
+ apic_mode = inb_cmos(0x78);
+
+ mask_set = mask_clr = 0;
+ if (apic_mode == APICMODE_X2APIC)
+ mask_set = APICBASE_X2APIC;
+ else if (apic_mode == APICMODE_DISABLED)
+ mask_clr = APICBASE_ENABLE;
+ else
+ ; /* Any other setting leaves things alone. */
+
+ if (mask_set || mask_clr) {
+ base_msr = msr_read(APIC_BASE_MSR);
+ base_msr &= ~(uint64_t)mask_clr;
+ base_msr |= mask_set;
+ msr_write(base_msr, APIC_BASE_MSR);
+ }
+}
+
+#endif
diff --git a/src/VBox/Devices/PC/BIOS/print.c b/src/VBox/Devices/PC/BIOS/print.c
new file mode 100644
index 00000000..f8eb32c7
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/print.c
@@ -0,0 +1,296 @@
+/* $Id: print.c $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+
+#include <stdint.h>
+#include <stdarg.h>
+#include "inlines.h"
+#include "biosint.h"
+
+// Debug printf support
+
+/* Redirect INFO output to backdoor logging port. */
+#define INFO_PORT 0x504
+#define DEBUG_PORT 0x403
+
+const char bios_prefix_string[] = "BIOS: ";
+
+void wrch(uint8_t c);
+#pragma aux wrch = "mov ah, 0eh" "int 10h" parm [al] modify exact [ax bx];
+
+void send(uint16_t action, uint8_t c)
+{
+#if BX_DEBUG_SERIAL
+ if (c == '\n')
+ uart_tx_byte(BX_DEBUG_PORT, '\r');
+ uart_tx_byte(BX_DEBUG_PORT, c);
+#endif
+#if BX_VIRTUAL_PORTS
+ if (action & BIOS_PRINTF_DEBUG)
+ outb(DEBUG_PORT, c);
+ if (action & BIOS_PRINTF_INFO)
+ outb(INFO_PORT, c);
+#endif
+ if (action & BIOS_PRINTF_SCREEN) {
+ if (c == '\n')
+ wrch('\r');
+ wrch(c);
+ }
+}
+
+void put_int(uint16_t action, short val, short width, bx_bool neg)
+{
+ short nval = val / 10;
+ if (nval)
+ put_int(action, nval, width - 1, neg);
+ else {
+ while (--width > 0)
+ send(action, ' ');
+ if (neg)
+ send(action, '-');
+ }
+ send(action, val - (nval * 10) + '0');
+}
+
+void put_uint(uint16_t action, unsigned short val, short width, bx_bool neg)
+{
+ unsigned short nval = val / 10;
+ if (nval)
+ put_uint(action, nval, width - 1, neg);
+ else {
+ while (--width > 0)
+ send(action, ' ');
+ if (neg)
+ send(action, '-');
+ }
+ send(action, val - (nval * 10) + '0');
+}
+
+void put_luint(uint16_t action, unsigned long val, short width, bx_bool neg)
+{
+ unsigned long nval = val / 10;
+ if (nval)
+ put_luint(action, nval, width - 1, neg);
+ else {
+ while (--width > 0)
+ send(action, ' ');
+ if (neg)
+ send(action, '-');
+ }
+ send(action, val - (nval * 10) + '0');
+}
+
+void put_str(uint16_t action, const char __far *s)
+{
+ uint8_t c;
+
+ while (c = *s) {
+ send(action, c);
+ s++;
+ }
+}
+
+void put_str_near(uint16_t action, const char __near *s)
+{
+ uint8_t c;
+
+ while (c = *s) {
+ send(action, c);
+ s++;
+ }
+}
+
+
+//--------------------------------------------------------------------------
+// bios_printf()
+// A compact variable argument printf function.
+//
+// Supports %[format_width][length]format
+// where format can be x,X,u,d,s,S,c
+// and the optional length modifier is l (ell, long 32-bit) or ll
+// (long long, 64-bit).
+// Only x,X work with ll
+//--------------------------------------------------------------------------
+void bios_printf(uint16_t action, const char *s, ...)
+{
+ uint8_t c;
+ bx_bool in_format;
+ int i;
+ uint16_t arg, nibble, hibyte, format_width, hexadd;
+ va_list args;
+
+ va_start( args, s );
+
+ in_format = 0;
+ format_width = 0;
+
+ if ((action & BIOS_PRINTF_DEBHALT) == BIOS_PRINTF_DEBHALT) {
+ bios_printf (BIOS_PRINTF_SCREEN, "FATAL: ");
+ }
+
+ while (c = *s) {
+ if ( c == '%' ) {
+ in_format = 1;
+ format_width = 0;
+ }
+ else if (in_format) {
+ if ( (c>='0') && (c<='9') ) {
+ format_width = (format_width * 10) + (c - '0');
+ }
+ else {
+ arg = va_arg( args, uint16_t );
+ if (c == 'x' || c == 'X') {
+ if (format_width == 0)
+ format_width = 4;
+ if (c == 'x')
+ hexadd = 'a';
+ else
+ hexadd = 'A';
+ for (i=format_width-1; i>=0; i--) {
+ nibble = (arg >> (4 * i)) & 0x000f;
+ send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
+ }
+ }
+ else if (c == 'u') {
+ put_uint(action, arg, format_width, 0);
+ }
+ else if (c == 'l' && s[1] == 'l') {
+ uint64_t llval;
+ uint16_t __far *cp16;
+
+ s += 2;
+ c = *s;
+ cp16 = (uint16_t __far *)&llval;
+ cp16[0] = arg;
+ cp16[1] = va_arg( args, uint16_t );
+ cp16[2] = va_arg( args, uint16_t );
+ cp16[3] = va_arg( args, uint16_t );
+ if (c == 'x' || c == 'X') {
+ if (format_width == 0)
+ format_width = 16;
+ if (c == 'x')
+ hexadd = 'a';
+ else
+ hexadd = 'A';
+ for (i=format_width-1; i>=0; i--) {
+ nibble = (llval >> (i * 4)) & 0x000f;
+ send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
+ }
+ } else {
+ BX_PANIC("bios_printf: unknown %ll format\n");
+ }
+ }
+ else if (c == 'l') {
+ s++;
+ c = *s; /* is it ld,lx,lu? */
+ hibyte = va_arg( args, uint16_t );
+ if (c == 'd') {
+ if (hibyte & 0x8000)
+ put_luint(action, 0L-(((uint32_t) hibyte << 16) | arg), format_width-1, 1);
+ else
+ put_luint(action, ((uint32_t) hibyte << 16) | arg, format_width, 0);
+ }
+ else if (c == 'u') {
+ put_luint(action, ((uint32_t) hibyte << 16) | arg, format_width, 0);
+ }
+ else if (c == 'x' || c == 'X')
+ {
+ if (format_width == 0)
+ format_width = 8;
+ if (c == 'x')
+ hexadd = 'a';
+ else
+ hexadd = 'A';
+ for (i=format_width-1; i>=0; i--) {
+ nibble = ((((uint32_t)hibyte << 16) | arg) >> (4 * i)) & 0x000f;
+ send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
+ }
+ }
+ }
+ else if (c == 'd') {
+ if (arg & 0x8000)
+ put_int(action, -arg, format_width - 1, 1);
+ else
+ put_int(action, arg, format_width, 0);
+ }
+ else if (c == 's') {
+ put_str(action, (char *)arg);
+ }
+ else if (c == 'S') {
+ hibyte = arg;
+ arg = va_arg( args, uint16_t );
+ put_str(action, hibyte :> (char *)arg);
+ }
+ else if (c == 'c') {
+ send(action, arg);
+ }
+ else
+ BX_PANIC("bios_printf: unknown format\n");
+ in_format = 0;
+ }
+ }
+ else {
+ send(action, c);
+ }
+ ++s;
+ }
+ va_end( args );
+ if (action & BIOS_PRINTF_HALT) {
+ // freeze in a busy loop.
+ int_disable();
+ halt_forever();
+ }
+}
+
+// End of printf support
diff --git a/src/VBox/Devices/PC/BIOS/ps2mouse.c b/src/VBox/Devices/PC/BIOS/ps2mouse.c
new file mode 100644
index 00000000..6b485f68
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/ps2mouse.c
@@ -0,0 +1,452 @@
+/* $Id: ps2mouse.c $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+
+#include <stdint.h>
+#include "biosint.h"
+#include "inlines.h"
+
+
+#if DEBUG_INT15_MS
+# define BX_DEBUG_INT15_MS(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define BX_DEBUG_INT15_MS(...)
+#endif
+
+#if DEBUG_INT74
+# define BX_DEBUG_INT74(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define BX_DEBUG_INT74(...)
+#endif
+
+#if BX_USE_PS2_MOUSE
+
+static const char panic_msg_keyb_buffer_full[] = "%s: keyboard input buffer full\n";
+
+uint8_t send_to_mouse_ctrl(uint8_t sendbyte)
+{
+ BX_DEBUG_INT15_MS("send %02x to mouse:\n", sendbyte);
+ // wait for chance to write to ctrl
+ if (inb(0x64) & 0x02)
+ BX_PANIC(panic_msg_keyb_buffer_full,"sendmouse");
+ outb(0x64, 0xD4);
+ outb(0x60, sendbyte);
+ return(0);
+}
+
+
+uint8_t get_mouse_data(uint8_t __far *data)
+{
+ int retries = 10000; /* ~150ms timeout */
+ uint8_t response;
+
+ while ((inb(0x64) & 0x21) != 0x21 && retries)
+ {
+ /* Wait until the 15us refresh counter toggles. */
+ response = inb(0x61) & 0x10;
+ while((inb(0x61) & 0x10) == response)
+ ;
+ --retries;
+ }
+
+ if (!retries)
+ return(1);
+
+ response = inb(0x60);
+ *data = response;
+ return(0);
+}
+
+void set_kbd_command_byte(uint8_t command_byte)
+{
+ if (inb(0x64) & 0x02)
+ BX_PANIC(panic_msg_keyb_buffer_full,"setkbdcomm");
+
+ outb(0x64, 0x60); // write command byte
+ outb(0x60, command_byte);
+}
+
+
+void BIOSCALL int74_function(volatile uint16_t make_farcall, volatile uint16_t Z,
+ volatile uint16_t Y, volatile uint16_t X, volatile uint16_t status)
+{
+ uint16_t ebda_seg=read_word(0x0040,0x000E);
+ uint8_t in_byte, index, package_count;
+ uint8_t mouse_flags_1, mouse_flags_2;
+
+ BX_DEBUG_INT74("entering int74_function\n");
+ make_farcall = 0;
+
+ in_byte = inb(0x64);
+ if ( (in_byte & 0x21) != 0x21 ) {
+ return;
+ }
+ in_byte = inb(0x60);
+ BX_DEBUG_INT74("int74: read byte %02x\n", in_byte);
+
+ mouse_flags_1 = read_byte(ebda_seg, 0x0026);
+ mouse_flags_2 = read_byte(ebda_seg, 0x0027);
+
+ if ( (mouse_flags_2 & 0x80) != 0x80 ) {
+ return;
+ }
+
+ package_count = mouse_flags_2 & 0x07;
+ index = mouse_flags_1 & 0x07;
+ write_byte(ebda_seg, 0x28 + index, in_byte);
+
+ if ( index >= package_count ) {
+ BX_DEBUG_INT74("int74_function: make_farcall=1\n");
+ status = read_byte(ebda_seg, 0x0028 + 0);
+ X = read_byte(ebda_seg, 0x0028 + 1);
+ Y = read_byte(ebda_seg, 0x0028 + 2);
+ Z = 0;
+ mouse_flags_1 = 0;
+ // check if far call handler installed
+ if (mouse_flags_2 & 0x80)
+ make_farcall = 1;
+ }
+ else {
+ mouse_flags_1++;
+ }
+ write_byte(ebda_seg, 0x0026, mouse_flags_1);
+}
+
+void BIOSCALL int15_function_mouse(pusha_regs_t regs, uint16_t ES, uint16_t DS, volatile uint16_t FLAGS)
+{
+ uint16_t ebda_seg=read_word(0x0040,0x000E);
+ uint8_t mouse_flags_1, mouse_flags_2;
+ uint16_t mouse_driver_seg;
+ uint16_t mouse_driver_offset;
+ uint8_t mouse_cmd;
+ uint8_t ret, mouse_data1, mouse_data2, mouse_data3;
+
+ BX_DEBUG_INT15_MS("int15 AX=%04x\n",regs.u.r16.ax);
+
+ // Return Codes status in AH
+ // =========================
+ // 00: success
+ // 01: invalid subfunction (AL > 7)
+ // 02: invalid input value (out of allowable range)
+ // 03: interface error
+ // 04: resend command received from mouse controller,
+ // device driver should attempt command again
+ // 05: cannot enable mouse, since no far call has been installed
+ // 80/86: mouse service not implemented
+
+ if (regs.u.r8.al > 7) {
+ BX_DEBUG_INT15_MS("unsupported subfn\n");
+ // invalid function
+ SET_CF();
+ regs.u.r8.ah = 1;
+ return;
+ }
+
+ // Valid subfn; disable AUX input and IRQ12, assume no error
+ set_kbd_command_byte(0x65);
+ CLEAR_CF();
+ regs.u.r8.ah = 0;
+
+ switch (regs.u.r8.al) {
+ case 0: // Disable/Enable Mouse
+ BX_DEBUG_INT15_MS("case 0: ");
+ if (regs.u.r8.bh > 1) {
+ BX_DEBUG_INT15_MS("INT 15h C2 AL=0, BH=%02x\n", (unsigned) regs.u.r8.bh);
+ // invalid subfunction
+ SET_CF();
+ regs.u.r8.ah = 1;
+ break;
+ }
+ mouse_flags_2 = read_byte(ebda_seg, 0x0027);
+ if ( (mouse_flags_2 & 0x80) == 0 ) {
+ BX_DEBUG_INT15_MS("INT 15h C2 Enable/Disable Mouse, no far call handler\n");
+ SET_CF();
+ regs.u.r8.ah = 5; // no far call installed
+ break;
+ }
+ if (regs.u.r8.bh == 0) {
+ BX_DEBUG_INT15_MS("Disable Mouse\n");
+ mouse_cmd = 0xF5; // disable mouse command
+ } else {
+ BX_DEBUG_INT15_MS("Enable Mouse\n");
+ mouse_cmd = 0xF4; // enable mouse command
+ }
+
+ ret = send_to_mouse_ctrl(mouse_cmd); // disable mouse command
+ if (ret == 0) {
+ ret = get_mouse_data(&mouse_data1);
+ if ( (ret == 0) || (mouse_data1 == 0xFA) ) {
+ // success
+ break;
+ }
+ }
+
+ // interface error
+ SET_CF();
+ regs.u.r8.ah = 3;
+ break;
+
+ case 5: // Initialize Mouse
+ // Valid package sizes are 1 to 8
+ if ( (regs.u.r8.bh < 1) || (regs.u.r8.bh > 8) ) {
+ SET_CF();
+ regs.u.r8.ah = 2; // invalid input
+ break;
+ }
+ mouse_flags_2 = read_byte(ebda_seg, 0x0027);
+ mouse_flags_2 = (mouse_flags_2 & 0xf8) | (regs.u.r8.bh - 1);
+ write_byte(ebda_seg, 0x0027, mouse_flags_2);
+ // fall through!
+
+ case 1: // Reset Mouse
+ BX_DEBUG_INT15_MS("case 1 or 5:\n");
+ // clear current package byte index
+ mouse_flags_1 = read_byte(ebda_seg, 0x0026);
+ mouse_flags_1 = mouse_flags_1 & 0xf8;
+ write_byte(ebda_seg, 0x0026, mouse_flags_1);
+ ret = send_to_mouse_ctrl(0xFF); // reset mouse command
+ if (ret == 0) {
+ ret = get_mouse_data(&mouse_data3);
+ // if no mouse attached, it will return RESEND
+ if (mouse_data3 == 0xfe) {
+ SET_CF();
+ regs.u.r8.ah = 4; // resend
+ break;
+ }
+ if (mouse_data3 != 0xfa)
+ BX_PANIC("Mouse reset returned %02x (should be ack)\n", (unsigned)mouse_data3);
+ if ( ret == 0 ) {
+ ret = get_mouse_data(&mouse_data1);
+ if ( ret == 0 ) {
+ ret = get_mouse_data(&mouse_data2);
+ if ( ret == 0 ) {
+ // success
+ regs.u.r8.bl = mouse_data1;
+ regs.u.r8.bh = mouse_data2;
+ break;
+ }
+ }
+ }
+ }
+
+ // interface error
+ SET_CF();
+ regs.u.r8.ah = 3;
+ break;
+
+ case 2: // Set Sample Rate
+ BX_DEBUG_INT15_MS("case 2:\n");
+ switch (regs.u.r8.bh) {
+ case 0: mouse_data1 = 10; break; // 10 reports/sec
+ case 1: mouse_data1 = 20; break; // 20 reports/sec
+ case 2: mouse_data1 = 40; break; // 40 reports/sec
+ case 3: mouse_data1 = 60; break; // 60 reports/sec
+ case 4: mouse_data1 = 80; break; // 80 reports/sec
+ case 5: mouse_data1 = 100; break; // 100 reports/sec (default)
+ case 6: mouse_data1 = 200; break; // 200 reports/sec
+ default: mouse_data1 = 0;
+ }
+ if (mouse_data1 > 0) {
+ ret = send_to_mouse_ctrl(0xF3); // set sample rate command
+ if (ret == 0) {
+ ret = get_mouse_data(&mouse_data2);
+ ret = send_to_mouse_ctrl(mouse_data1);
+ ret = get_mouse_data(&mouse_data2);
+ // success
+ } else {
+ // interface error
+ SET_CF();
+ regs.u.r8.ah = 3;
+ }
+ } else {
+ // invalid input
+ SET_CF();
+ regs.u.r8.ah = 2;
+ }
+ break;
+
+ case 3: // Set Resolution
+ BX_DEBUG_INT15_MS("case 3:\n");
+ // BX:
+ // 0 = 25 dpi, 1 count per millimeter
+ // 1 = 50 dpi, 2 counts per millimeter
+ // 2 = 100 dpi, 4 counts per millimeter
+ // 3 = 200 dpi, 8 counts per millimeter
+ if (regs.u.r8.bh < 4) {
+ ret = send_to_mouse_ctrl(0xE8); // set resolution command
+ if (ret == 0) {
+ ret = get_mouse_data(&mouse_data1);
+ if (mouse_data1 != 0xfa)
+ BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
+ ret = send_to_mouse_ctrl(regs.u.r8.bh);
+ ret = get_mouse_data(&mouse_data1);
+ if (mouse_data1 != 0xfa)
+ BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
+ // success
+ } else {
+ // interface error
+ SET_CF();
+ regs.u.r8.ah = 3;
+ }
+ } else {
+ // invalid input
+ SET_CF();
+ regs.u.r8.ah = 2;
+ }
+ break;
+
+ case 4: // Get Device ID
+ BX_DEBUG_INT15_MS("case 4:\n");
+ ret = send_to_mouse_ctrl(0xF2); // get mouse ID command
+ if (ret == 0) {
+ ret = get_mouse_data(&mouse_data1);
+ ret = get_mouse_data(&mouse_data2);
+ regs.u.r8.bh = mouse_data2;
+ // success
+ } else {
+ // interface error
+ SET_CF();
+ regs.u.r8.ah = 3;
+ }
+ break;
+
+ case 6: // Return Status & Set Scaling Factor...
+ BX_DEBUG_INT15_MS("case 6:\n");
+ switch (regs.u.r8.bh) {
+ case 0: // Return Status
+ ret = send_to_mouse_ctrl(0xE9); // get mouse info command
+ if (ret == 0) {
+ ret = get_mouse_data(&mouse_data1);
+ if (mouse_data1 != 0xfa)
+ BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
+ if (ret == 0) {
+ ret = get_mouse_data(&mouse_data1);
+ if ( ret == 0 ) {
+ ret = get_mouse_data(&mouse_data2);
+ if ( ret == 0 ) {
+ ret = get_mouse_data(&mouse_data3);
+ if ( ret == 0 ) {
+ regs.u.r8.bl = mouse_data1;
+ regs.u.r8.cl = mouse_data2;
+ regs.u.r8.dl = mouse_data3;
+ // success
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // interface error
+ SET_CF();
+ regs.u.r8.ah = 3;
+ break;
+
+ case 1: // Set Scaling Factor to 1:1
+ case 2: // Set Scaling Factor to 2:1
+ if (regs.u.r8.bh == 1) {
+ ret = send_to_mouse_ctrl(0xE6);
+ } else {
+ ret = send_to_mouse_ctrl(0xE7);
+ }
+ if (ret == 0) {
+ get_mouse_data(&mouse_data1);
+ ret = (mouse_data1 != 0xFA);
+ }
+ if (ret != 0) {
+ // interface error
+ SET_CF();
+ regs.u.r8.ah = 3;
+ }
+ break;
+
+ default:
+ BX_PANIC("INT 15h C2 AL=6, BH=%02x\n", (unsigned) regs.u.r8.bh);
+ // invalid subfunction
+ SET_CF();
+ regs.u.r8.ah = 1;
+ }
+ break;
+
+ case 7: // Set Mouse Handler Address
+ BX_DEBUG_INT15_MS("case 7:\n");
+ mouse_driver_seg = ES;
+ mouse_driver_offset = regs.u.r16.bx;
+ write_word(ebda_seg, 0x0022, mouse_driver_offset);
+ write_word(ebda_seg, 0x0024, mouse_driver_seg);
+ mouse_flags_2 = read_byte(ebda_seg, 0x0027);
+ if (mouse_driver_offset == 0 && mouse_driver_seg == 0) {
+ /* remove handler */
+ if ( (mouse_flags_2 & 0x80) != 0 ) {
+ mouse_flags_2 &= ~0x80;
+ }
+ }
+ else {
+ /* install handler */
+ mouse_flags_2 |= 0x80;
+ }
+ write_byte(ebda_seg, 0x0027, mouse_flags_2);
+ break;
+
+ default:
+ BX_PANIC("INT 15h C2 default case entered\n");
+ // invalid subfunction
+ SET_CF();
+ regs.u.r8.ah = 1;
+ }
+ BX_DEBUG_INT15_MS("returning cf = %u, ah = %02x\n", (unsigned)GET_CF(), (unsigned)regs.u.r8.ah);
+ // Re-enable AUX input and IRQ12
+ set_kbd_command_byte(0x47);
+}
+#endif // BX_USE_PS2_MOUSE
diff --git a/src/VBox/Devices/PC/BIOS/scsi.c b/src/VBox/Devices/PC/BIOS/scsi.c
new file mode 100644
index 00000000..74d2b043
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/scsi.c
@@ -0,0 +1,700 @@
+/* $Id: scsi.c $ */
+/** @file
+ * SCSI host adapter driver to boot from SCSI disks
+ */
+
+/*
+ * Copyright (C) 2004-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "biosint.h"
+#include "inlines.h"
+#include "pciutil.h"
+#include "ebda.h"
+
+
+#if DEBUG_SCSI
+# define DBG_SCSI(...) BX_INFO(__VA_ARGS__)
+#else
+# define DBG_SCSI(...)
+#endif
+
+#define VBSCSI_BUSY (1 << 0)
+#define VBSCSI_ERROR (1 << 1)
+
+/* The I/O port of the BusLogic SCSI adapter. */
+#define BUSLOGIC_BIOS_IO_PORT 0x430
+/* The I/O port of the LsiLogic SCSI adapter. */
+#define LSILOGIC_BIOS_IO_PORT 0x434
+/* The I/O port of the LsiLogic SAS adapter. */
+#define LSILOGIC_SAS_BIOS_IO_PORT 0x438
+
+#define VBSCSI_REGISTER_STATUS 0
+#define VBSCSI_REGISTER_COMMAND 0
+#define VBSCSI_REGISTER_DATA_IN 1
+#define VBSCSI_REGISTER_IDENTIFY 2
+#define VBSCSI_REGISTER_RESET 3
+#define VBSCSI_REGISTER_DEVSTAT 3
+
+#define VBSCSI_MAX_DEVICES 16 /* Maximum number of devices a SCSI device can have. */
+
+/* Command opcodes. */
+#define SCSI_SERVICE_ACT 0x9e
+#define SCSI_INQUIRY 0x12
+#define SCSI_READ_CAP_10 0x25
+#define SCSI_READ_10 0x28
+#define SCSI_WRITE_10 0x2a
+#define SCSI_READ_CAP_16 0x10 /* Not an opcode by itself, sub-action for the "Service Action" */
+#define SCSI_READ_16 0x88
+#define SCSI_WRITE_16 0x8a
+
+/* Data transfer direction. */
+#define SCSI_TXDIR_FROM_DEVICE 0
+#define SCSI_TXDIR_TO_DEVICE 1
+
+#pragma pack(1)
+
+/* READ_10/WRITE_10 CDB layout. */
+typedef struct {
+ uint16_t command; /* Command. */
+ uint32_t lba; /* LBA, MSB first! */
+ uint8_t pad1; /* Unused. */
+ uint16_t nsect; /* Sector count, MSB first! */
+ uint8_t pad2; /* Unused. */
+} cdb_rw10;
+
+/* READ_16/WRITE_16 CDB layout. */
+typedef struct {
+ uint16_t command; /* Command. */
+ uint64_t lba; /* LBA, MSB first! */
+ uint32_t nsect32; /* Sector count, MSB first! */
+ uint8_t pad1; /* Unused. */
+ uint8_t pad2; /* Unused. */
+} cdb_rw16;
+
+#pragma pack()
+
+ct_assert(sizeof(cdb_rw10) == 10);
+ct_assert(sizeof(cdb_rw16) == 16);
+
+void insb_discard(unsigned nbytes, unsigned port);
+#pragma aux insb_discard = \
+ ".286" \
+ "again:" \
+ "in al,dx" \
+ "loop again" \
+ parm [cx] [dx] modify exact [cx ax] nomemory;
+
+
+int scsi_cmd_data_in(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
+ uint8_t cbCDB, uint8_t __far *buffer, uint32_t length)
+{
+ /* Check that the adapter is ready. */
+ uint8_t status, sizes;
+ uint16_t i;
+
+ do
+ status = inb(io_base + VBSCSI_REGISTER_STATUS);
+ while (status & VBSCSI_BUSY);
+
+ sizes = ((length >> 12) & 0xF0) | ((cbCDB == 16) ? 0 : cbCDB);
+ outb(io_base + VBSCSI_REGISTER_COMMAND, target_id); /* Write the target ID. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_FROM_DEVICE); /* Write the transfer direction. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, sizes); /* Write CDB size and top bufsize bits. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, length); /* Write the buffer size. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, (length >> 8));
+ for (i = 0; i < cbCDB; i++) /* Write the CDB. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, aCDB[i]);
+
+ /* Now wait for the command to complete. */
+ do
+ status = inb(io_base + VBSCSI_REGISTER_STATUS);
+ while (status & VBSCSI_BUSY);
+
+ /* If any error occurred, inform the caller and don't bother reading the data. */
+ if (status & VBSCSI_ERROR) {
+ outb(io_base + VBSCSI_REGISTER_RESET, 0);
+
+ status = inb(io_base + VBSCSI_REGISTER_DEVSTAT);
+ DBG_SCSI("%s: read failed, device status %02X\n", __func__, status);
+ return 4; /* Sector not found */
+ }
+
+ /* Read in the data. The transfer length may be exactly 64K or more,
+ * which needs a bit of care when we're using 16-bit 'rep ins'.
+ */
+ while (length > 32768) {
+ DBG_SCSI("%s: reading 32K to %X:%X\n", __func__, FP_SEG(buffer), FP_OFF(buffer));
+ rep_insb(buffer, 32768, io_base + VBSCSI_REGISTER_DATA_IN);
+ length -= 32768;
+ buffer = (FP_SEG(buffer) + (32768 >> 4)) :> FP_OFF(buffer);
+ }
+
+ DBG_SCSI("%s: reading %ld bytes to %X:%X\n", __func__, length, FP_SEG(buffer), FP_OFF(buffer));
+ rep_insb(buffer, length, io_base + VBSCSI_REGISTER_DATA_IN);
+
+ return 0;
+}
+
+int scsi_cmd_data_out(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
+ uint8_t cbCDB, uint8_t __far *buffer, uint32_t length)
+{
+ /* Check that the adapter is ready. */
+ uint8_t status, sizes;
+ uint16_t i;
+
+ do
+ status = inb(io_base + VBSCSI_REGISTER_STATUS);
+ while (status & VBSCSI_BUSY);
+
+
+ sizes = ((length >> 12) & 0xF0) | ((cbCDB == 16) ? 0 : cbCDB);
+ outb(io_base + VBSCSI_REGISTER_COMMAND, target_id); /* Write the target ID. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_TO_DEVICE); /* Write the transfer direction. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, sizes); /* Write CDB size and top bufsize bits. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, length); /* Write the buffer size. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, (length >> 8));
+ for (i = 0; i < cbCDB; i++) /* Write the CDB. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, aCDB[i]);
+
+ /* Write out the data. The transfer length may be exactly 64K or more,
+ * which needs a bit of care when we're using 16-bit 'rep outs'.
+ */
+ while (length > 32768) {
+ DBG_SCSI("%s: writing 32K from %X:%X\n", __func__, FP_SEG(buffer), FP_OFF(buffer));
+ rep_outsb(buffer, 32768, io_base + VBSCSI_REGISTER_DATA_IN);
+ length -= 32768;
+ buffer = (FP_SEG(buffer) + (32768 >> 4)) :> FP_OFF(buffer);
+ }
+
+ DBG_SCSI("%s: writing %ld bytes from %X:%X\n", __func__, length, FP_SEG(buffer), FP_OFF(buffer));
+ rep_outsb(buffer, length, io_base + VBSCSI_REGISTER_DATA_IN);
+
+ /* Now wait for the command to complete. */
+ do
+ status = inb(io_base + VBSCSI_REGISTER_STATUS);
+ while (status & VBSCSI_BUSY);
+
+ /* If any error occurred, inform the caller. */
+ if (status & VBSCSI_ERROR) {
+ outb(io_base + VBSCSI_REGISTER_RESET, 0);
+
+ status = inb(io_base + VBSCSI_REGISTER_DEVSTAT);
+ DBG_SCSI("%s: write failed, device status %02X\n", __func__, status);
+ return 4; /* Sector not found */
+ }
+
+ return 0;
+}
+
+/**
+ * Read sectors from an attached SCSI device.
+ *
+ * @returns status code.
+ * @param bios_dsk Pointer to disk request packet (in the
+ * EBDA).
+ */
+int scsi_read_sectors(bio_dsk_t __far *bios_dsk)
+{
+ uint8_t rc;
+ cdb_rw16 cdb;
+ uint32_t count;
+ uint16_t io_base;
+ uint8_t target_id;
+ uint8_t device_id;
+
+ device_id = VBOX_GET_SCSI_DEVICE(bios_dsk->drqp.dev_id);
+ if (device_id > BX_MAX_SCSI_DEVICES)
+ BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
+
+ count = bios_dsk->drqp.nsect;
+
+ /* Prepare a CDB. */
+ cdb.command = SCSI_READ_16;
+ cdb.lba = swap_64(bios_dsk->drqp.lba);
+ cdb.pad1 = 0;
+ cdb.nsect32 = swap_32(count);
+ cdb.pad2 = 0;
+
+
+ io_base = bios_dsk->scsidev[device_id].io_base;
+ target_id = bios_dsk->scsidev[device_id].target_id;
+
+ DBG_SCSI("%s: reading %u sectors, device %d, target %d\n", __func__,
+ count, device_id, bios_dsk->scsidev[device_id].target_id);
+
+ rc = scsi_cmd_data_in(io_base, target_id, (void __far *)&cdb, 16,
+ bios_dsk->drqp.buffer, (count * 512L));
+
+ if (!rc)
+ {
+ bios_dsk->drqp.trsfsectors = count;
+ bios_dsk->drqp.trsfbytes = count * 512L;
+ }
+ DBG_SCSI("%s: transferred %u sectors\n", __func__, bios_dsk->drqp.nsect);
+
+ return rc;
+}
+
+/**
+ * Write sectors to an attached SCSI device.
+ *
+ * @returns status code.
+ * @param bios_dsk Pointer to disk request packet (in the
+ * EBDA).
+ */
+int scsi_write_sectors(bio_dsk_t __far *bios_dsk)
+{
+ uint8_t rc;
+ cdb_rw16 cdb;
+ uint32_t count;
+ uint16_t io_base;
+ uint8_t target_id;
+ uint8_t device_id;
+
+ device_id = VBOX_GET_SCSI_DEVICE(bios_dsk->drqp.dev_id);
+ if (device_id > BX_MAX_SCSI_DEVICES)
+ BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
+
+ count = bios_dsk->drqp.nsect;
+
+ /* Prepare a CDB. */
+ cdb.command = SCSI_WRITE_16;
+ cdb.lba = swap_64(bios_dsk->drqp.lba);
+ cdb.pad1 = 0;
+ cdb.nsect32 = swap_32(count);
+ cdb.pad2 = 0;
+
+ io_base = bios_dsk->scsidev[device_id].io_base;
+ target_id = bios_dsk->scsidev[device_id].target_id;
+
+ DBG_SCSI("%s: writing %u sectors, device %d, target %d\n", __func__,
+ count, device_id, bios_dsk->scsidev[device_id].target_id);
+
+ rc = scsi_cmd_data_out(io_base, target_id, (void __far *)&cdb, 16,
+ bios_dsk->drqp.buffer, (count * 512L));
+
+ if (!rc)
+ {
+ bios_dsk->drqp.trsfsectors = count;
+ bios_dsk->drqp.trsfbytes = (count * 512L);
+ }
+ DBG_SCSI("%s: transferred %u sectors\n", __func__, bios_dsk->drqp.nsect);
+
+ return rc;
+}
+
+
+/// @todo move
+#define ATA_DATA_NO 0x00
+#define ATA_DATA_IN 0x01
+#define ATA_DATA_OUT 0x02
+
+/**
+ * Perform a "packet style" read with supplied CDB.
+ *
+ * @returns status code.
+ * @param device_id ID of the device to access.
+ * @param cmdlen Length of the CDB.
+ * @param cmdbuf The CDB buffer.
+ * @param before How much to skip before reading into the provided data buffer.
+ * @param length How much to transfer.
+ * @param inout Read/Write direction indicator.
+ * @param buffer Data buffer to store the data from the device in.
+ */
+uint16_t scsi_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,
+ uint16_t before, uint32_t length, uint8_t inout, char __far *buffer)
+{
+ bio_dsk_t __far *bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
+ uint32_t read_len;
+ uint8_t status, sizes;
+ uint16_t i;
+ uint16_t io_base;
+ uint8_t target_id;
+
+ /* Data out is currently not supported. */
+ if (inout == ATA_DATA_OUT) {
+ BX_INFO("%s: DATA_OUT not supported yet\n", __func__);
+ return 1;
+ }
+
+ /* Convert to SCSI specific device number. */
+ device_id = VBOX_GET_SCSI_DEVICE(device_id);
+
+ DBG_SCSI("%s: reading %lu bytes, skip %u/%u, device %d, target %d\n", __func__,
+ length, bios_dsk->drqp.skip_b, bios_dsk->drqp.skip_a,
+ device_id, bios_dsk->scsidev[device_id].target_id);
+ DBG_SCSI("%s: reading %u %u-byte sectors\n", __func__,
+ bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz);
+
+ cmdlen -= 2; /* ATAPI uses 12-byte command packets for a READ 10. */
+
+ io_base = bios_dsk->scsidev[device_id].io_base;
+ target_id = bios_dsk->scsidev[device_id].target_id;
+
+ /* Wait until the adapter is ready. */
+ do
+ status = inb(io_base + VBSCSI_REGISTER_STATUS);
+ while (status & VBSCSI_BUSY);
+
+ /* On the SCSI level, we have to transfer whole sectors. */
+ /* NB: With proper residual length support, this should not be necessary; we should
+ * be able to avoid transferring the 'after' part of the sector.
+ */
+ read_len = length + before + bios_dsk->drqp.skip_a;
+
+ sizes = (((read_len) >> 12) & 0xF0) | cmdlen;
+ outb(io_base + VBSCSI_REGISTER_COMMAND, target_id); /* Write the target ID. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_FROM_DEVICE); /* Write the transfer direction. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, sizes); /* Write the CDB size. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, read_len); /* Write the buffer size. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, (read_len) >> 8);
+ for (i = 0; i < cmdlen; i++) /* Write the CDB. */
+ outb(io_base + VBSCSI_REGISTER_COMMAND, cmdbuf[i]);
+
+ /* Now wait for the command to complete. */
+ do
+ status = inb(io_base + VBSCSI_REGISTER_STATUS);
+ while (status & VBSCSI_BUSY);
+
+ /* If any error occurred, inform the caller and don't bother reading the data. */
+ if (status & VBSCSI_ERROR) {
+ outb(io_base + VBSCSI_REGISTER_RESET, 0);
+
+ status = inb(io_base + VBSCSI_REGISTER_DEVSTAT);
+ DBG_SCSI("%s: read failed, device status %02X\n", __func__, status);
+ return 3;
+ }
+
+ /* Transfer the data read from the device. */
+
+ if (before) /* If necessary, throw away data which needs to be skipped. */
+ insb_discard(before, io_base + VBSCSI_REGISTER_DATA_IN);
+
+ bios_dsk->drqp.trsfbytes = length;
+
+ /* The requested length may be exactly 64K or more, which needs
+ * a bit of care when we're using 16-bit 'rep ins'.
+ */
+ while (length > 32768) {
+ DBG_SCSI("%s: reading 32K to %X:%X\n", __func__, FP_SEG(buffer), FP_OFF(buffer));
+ rep_insb(buffer, 32768, io_base + VBSCSI_REGISTER_DATA_IN);
+ length -= 32768;
+ buffer = (FP_SEG(buffer) + (32768 >> 4)) :> FP_OFF(buffer);
+ }
+
+ DBG_SCSI("%s: reading %ld bytes to %X:%X\n", __func__, length, FP_SEG(buffer), FP_OFF(buffer));
+ rep_insb(buffer, length, io_base + VBSCSI_REGISTER_DATA_IN);
+
+ if (bios_dsk->drqp.skip_a) /* If necessary, throw away more data. */
+ insb_discard(bios_dsk->drqp.skip_a, io_base + VBSCSI_REGISTER_DATA_IN);
+
+ return 0;
+}
+
+/**
+ * Enumerate attached devices.
+ *
+ * @returns nothing.
+ * @param io_base The I/O base port of the controller.
+ */
+void scsi_enumerate_attached_devices(uint16_t io_base)
+{
+ int i;
+ uint8_t buffer[0x0200];
+ bio_dsk_t __far *bios_dsk;
+
+ bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
+
+ /* Go through target devices. */
+ for (i = 0; i < VBSCSI_MAX_DEVICES; i++)
+ {
+ uint8_t rc;
+ uint8_t aCDB[16];
+ uint8_t hd_index, devcount_scsi;
+
+ aCDB[0] = SCSI_INQUIRY;
+ aCDB[1] = 0;
+ aCDB[2] = 0;
+ aCDB[3] = 0;
+ aCDB[4] = 5; /* Allocation length. */
+ aCDB[5] = 0;
+
+ rc = scsi_cmd_data_in(io_base, i, aCDB, 6, buffer, 5);
+ if (rc != 0)
+ BX_PANIC("%s: SCSI_INQUIRY failed\n", __func__);
+
+ devcount_scsi = bios_dsk->scsi_devcount;
+
+ /* Check the attached device. */
+ if ( ((buffer[0] & 0xe0) == 0)
+ && ((buffer[0] & 0x1f) == 0x00))
+ {
+ DBG_SCSI("%s: Disk detected at %d\n", __func__, i);
+
+ /* We add the disk only if the maximum is not reached yet. */
+ if (devcount_scsi < BX_MAX_SCSI_DEVICES)
+ {
+ uint64_t sectors, t;
+ uint32_t sector_size, cylinders;
+ uint16_t heads, sectors_per_track;
+ uint8_t hdcount;
+ uint8_t cmos_base;
+
+ /* Issue a read capacity command now. */
+ _fmemset(aCDB, 0, sizeof(aCDB));
+ aCDB[0] = SCSI_SERVICE_ACT;
+ aCDB[1] = SCSI_READ_CAP_16;
+ aCDB[13] = 32; /* Allocation length. */
+
+ rc = scsi_cmd_data_in(io_base, i, aCDB, 16, buffer, 32);
+ if (rc != 0)
+ BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__);
+
+ /* The value returned is the last addressable LBA, not
+ * the size, which what "+ 1" is for.
+ */
+ sectors = swap_64(*(uint64_t *)buffer) + 1;
+
+ sector_size = ((uint32_t)buffer[8] << 24)
+ | ((uint32_t)buffer[9] << 16)
+ | ((uint32_t)buffer[10] << 8)
+ | ((uint32_t)buffer[11]);
+
+ /* We only support the disk if sector size is 512 bytes. */
+ if (sector_size != 512)
+ {
+ /* Leave a log entry. */
+ BX_INFO("Disk %d has an unsupported sector size of %u\n", i, sector_size);
+ continue;
+ }
+
+ /* Get logical CHS geometry. */
+ switch (devcount_scsi)
+ {
+ case 0:
+ cmos_base = 0x90;
+ break;
+ case 1:
+ cmos_base = 0x98;
+ break;
+ case 2:
+ cmos_base = 0xA0;
+ break;
+ case 3:
+ cmos_base = 0xA8;
+ break;
+ default:
+ cmos_base = 0;
+ }
+
+ if (cmos_base && inb_cmos(cmos_base + 7))
+ {
+ /* If provided, grab the logical geometry from CMOS. */
+ cylinders = inb_cmos(cmos_base + 0) + (inb_cmos(cmos_base + 1) << 8);
+ heads = inb_cmos(cmos_base + 2);
+ sectors_per_track = inb_cmos(cmos_base + 7);
+ }
+ else
+ {
+ /* Calculate default logical geometry. NB: Very different
+ * from default ATA/SATA logical geometry!
+ */
+ if (sectors >= (uint32_t)4 * 1024 * 1024)
+ {
+ heads = 255;
+ sectors_per_track = 63;
+ /* Approximate x / (255 * 63) using shifts */
+ t = (sectors >> 6) + (sectors >> 12);
+ cylinders = (t >> 8) + (t >> 16);
+ }
+ else if (sectors >= (uint32_t)2 * 1024 * 1024)
+ {
+ heads = 128;
+ sectors_per_track = 32;
+ cylinders = sectors >> 12;
+ }
+ else
+ {
+ heads = 64;
+ sectors_per_track = 32;
+ cylinders = sectors >> 11;
+ }
+ }
+
+ /* Calculate index into the generic disk table. */
+ hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
+
+ bios_dsk->scsidev[devcount_scsi].io_base = io_base;
+ bios_dsk->scsidev[devcount_scsi].target_id = i;
+ bios_dsk->devices[hd_index].type = DSK_TYPE_SCSI;
+ bios_dsk->devices[hd_index].device = DSK_DEVICE_HD;
+ bios_dsk->devices[hd_index].removable = 0;
+ bios_dsk->devices[hd_index].lock = 0;
+ bios_dsk->devices[hd_index].blksize = sector_size;
+ bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;
+
+ /* Write LCHS/PCHS values. */
+ bios_dsk->devices[hd_index].lchs.heads = heads;
+ bios_dsk->devices[hd_index].lchs.spt = sectors_per_track;
+ bios_dsk->devices[hd_index].pchs.heads = heads;
+ bios_dsk->devices[hd_index].pchs.spt = sectors_per_track;
+
+ if (cylinders > 1024) {
+ bios_dsk->devices[hd_index].lchs.cylinders = 1024;
+ bios_dsk->devices[hd_index].pchs.cylinders = 1024;
+ } else {
+ bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;
+ bios_dsk->devices[hd_index].pchs.cylinders = (uint16_t)cylinders;
+ }
+
+ BX_INFO("SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors\n", devcount_scsi,
+ i, (uint32_t)cylinders, heads, sectors_per_track, sectors);
+
+ bios_dsk->devices[hd_index].sectors = sectors;
+
+ /* Store the id of the disk in the ata hdidmap. */
+ hdcount = bios_dsk->hdcount;
+ bios_dsk->hdidmap[hdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;
+ hdcount++;
+ bios_dsk->hdcount = hdcount;
+
+ /* Update hdcount in the BDA. */
+ hdcount = read_byte(0x40, 0x75);
+ hdcount++;
+ write_byte(0x40, 0x75, hdcount);
+
+ devcount_scsi++;
+ }
+ else
+ {
+ /* We reached the maximum of SCSI disks we can boot from. We can quit detecting. */
+ break;
+ }
+ }
+ else if ( ((buffer[0] & 0xe0) == 0)
+ && ((buffer[0] & 0x1f) == 0x05))
+ {
+ uint8_t cdcount;
+ uint8_t removable;
+
+ BX_INFO("SCSI %d-ID#%d: CD/DVD-ROM\n", devcount_scsi, i);
+
+ /* Calculate index into the generic device table. */
+ hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
+
+ removable = buffer[1] & 0x80 ? 1 : 0;
+
+ bios_dsk->scsidev[devcount_scsi].io_base = io_base;
+ bios_dsk->scsidev[devcount_scsi].target_id = i;
+ bios_dsk->devices[hd_index].type = DSK_TYPE_SCSI;
+ bios_dsk->devices[hd_index].device = DSK_DEVICE_CDROM;
+ bios_dsk->devices[hd_index].removable = removable;
+ bios_dsk->devices[hd_index].blksize = 2048;
+ bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_NONE;
+
+ /* Store the ID of the device in the BIOS cdidmap. */
+ cdcount = bios_dsk->cdcount;
+ bios_dsk->cdidmap[cdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;
+ cdcount++;
+ bios_dsk->cdcount = cdcount;
+
+ devcount_scsi++;
+ }
+ else
+ DBG_SCSI("%s: No supported device detected at %d\n", __func__, i);
+
+ bios_dsk->scsi_devcount = devcount_scsi;
+ }
+}
+
+void scsi_pci_init(uint16_t vendor_id, uint16_t device_id)
+{
+ uint16_t bus_dev_fn;
+
+ bus_dev_fn = pci_find_device(vendor_id, device_id);
+ if (bus_dev_fn == -1) {
+ DBG_SCSI("%s: Adapter %x:%x not found, how come?!\n", __func__, vendor_id, device_id);
+ return;
+ }
+
+ DBG_SCSI("%s: Adapter %x:%x found at %x, enabling BM\n", __func__, vendor_id, device_id, bus_dev_fn);
+ /* Enable PCI memory, I/O, bus mastering access in command register. */
+ pci_write_config_word(bus_dev_fn >> 8, (uint8_t)bus_dev_fn, 4, 0x7);
+}
+
+/**
+ * Init the SCSI driver and detect attached disks.
+ */
+void BIOSCALL scsi_init(void)
+{
+ uint8_t identifier;
+ bio_dsk_t __far *bios_dsk;
+
+ bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
+
+ bios_dsk->scsi_devcount = 0;
+
+ identifier = 0;
+
+ /* Detect the BusLogic adapter. */
+ outb(BUSLOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY, 0x55);
+ identifier = inb(BUSLOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY);
+
+ if (identifier == 0x55)
+ {
+ /* Detected - Enumerate attached devices. */
+ DBG_SCSI("%s: BusLogic SCSI adapter detected\n", __func__);
+ outb(BUSLOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_RESET, 0);
+ scsi_enumerate_attached_devices(BUSLOGIC_BIOS_IO_PORT);
+ scsi_pci_init(0x104B, 0x1040);
+ }
+ else
+ {
+ DBG_SCSI("%s: BusLogic SCSI adapter not detected\n", __func__);
+ }
+
+ /* Detect the LSI Logic parallel SCSI adapter. */
+ outb(LSILOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY, 0x55);
+ identifier = inb(LSILOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY);
+
+ if (identifier == 0x55)
+ {
+ /* Detected - Enumerate attached devices. */
+ DBG_SCSI("%s: LSI Logic SCSI adapter detected\n", __func__);
+ outb(LSILOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_RESET, 0);
+ scsi_enumerate_attached_devices(LSILOGIC_BIOS_IO_PORT);
+ scsi_pci_init(0x1000, 0x0030);
+ }
+ else
+ {
+ DBG_SCSI("%s: LSI Logic SCSI adapter not detected\n", __func__);
+ }
+
+ /* Detect the LSI Logic SAS adapter. */
+ outb(LSILOGIC_SAS_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY, 0x55);
+ identifier = inb(LSILOGIC_SAS_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY);
+
+ if (identifier == 0x55)
+ {
+ /* Detected - Enumerate attached devices. */
+ DBG_SCSI("%s: LSI Logic SAS adapter detected\n", __func__);
+ outb(LSILOGIC_SAS_BIOS_IO_PORT+VBSCSI_REGISTER_RESET, 0);
+ scsi_enumerate_attached_devices(LSILOGIC_SAS_BIOS_IO_PORT);
+ scsi_pci_init(0x1000, 0x0054);
+ }
+ else
+ {
+ DBG_SCSI("%s: LSI Logic SAS adapter not detected\n", __func__);
+ }
+}
diff --git a/src/VBox/Devices/PC/BIOS/serial.c b/src/VBox/Devices/PC/BIOS/serial.c
new file mode 100644
index 00000000..b240a897
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/serial.c
@@ -0,0 +1,128 @@
+/* $Id: serial.c $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+
+#include <stdint.h>
+#include "inlines.h"
+#include "biosint.h"
+
+void BIOSCALL int14_function(pusha_regs_t regs, uint16_t es, uint16_t ds, volatile iret_addr_t iret_addr)
+{
+ uint16_t addr, timer, val16;
+ uint8_t timeout;
+
+ int_enable();
+
+ addr = read_word(0x0040, (regs.u.r16.dx << 1));
+ timeout = read_byte(0x0040, 0x007C + regs.u.r16.dx);
+ if ((regs.u.r16.dx < 4) && (addr > 0)) {
+ switch (regs.u.r8.ah) {
+ case 0:
+ outb(addr+3, inb(addr+3) | 0x80);
+ if ((regs.u.r8.al & 0xE0) == 0) {
+ outb(addr, 0x17);
+ outb(addr+1, 0x04);
+ } else {
+ val16 = 0x600 >> ((regs.u.r8.al & 0xE0) >> 5);
+ outb(addr, val16 & 0xFF);
+ outb(addr+1, val16 >> 8);
+ }
+ outb(addr+3, regs.u.r8.al & 0x1F);
+ regs.u.r8.ah = inb(addr+5);
+ regs.u.r8.al = inb(addr+6);
+ ClearCF(iret_addr.flags);
+ break;
+ case 1:
+ timer = read_word(0x0040, 0x006C);
+ while (((inb(addr+5) & 0x60) != 0x60) && (timeout)) {
+ val16 = read_word(0x0040, 0x006C);
+ if (val16 != timer) {
+ timer = val16;
+ timeout--;
+ }
+ }
+ if (timeout) outb(addr, regs.u.r8.al);
+ regs.u.r8.ah = inb(addr+5);
+ if (!timeout) regs.u.r8.ah |= 0x80;
+ ClearCF(iret_addr.flags);
+ break;
+ case 2:
+ timer = read_word(0x0040, 0x006C);
+ while (((inb(addr+5) & 0x01) == 0) && (timeout)) {
+ val16 = read_word(0x0040, 0x006C);
+ if (val16 != timer) {
+ timer = val16;
+ timeout--;
+ }
+ }
+ if (timeout) {
+ regs.u.r8.ah = 0;
+ regs.u.r8.al = inb(addr);
+ } else {
+ regs.u.r8.ah = inb(addr+5);
+ }
+ ClearCF(iret_addr.flags);
+ break;
+ case 3:
+ regs.u.r8.ah = inb(addr+5);
+ regs.u.r8.al = inb(addr+6);
+ ClearCF(iret_addr.flags);
+ break;
+ default:
+ SetCF(iret_addr.flags); // Unsupported
+ }
+ } else {
+ SetCF(iret_addr.flags); // Unsupported
+ }
+}
diff --git a/src/VBox/Devices/PC/BIOS/smidmi.inc b/src/VBox/Devices/PC/BIOS/smidmi.inc
new file mode 100644
index 00000000..5ad67c67
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/smidmi.inc
@@ -0,0 +1,70 @@
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+;
+; Copyright (C) 2002 MandrakeSoft S.A.
+;
+; MandrakeSoft S.A.
+; 43, rue d'Aboukir
+; 75002 Paris - France
+; http://www.linux-mandrake.com/
+; http://www.mandrakesoft.com/
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+;
+
+; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+; other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+; a choice of LGPL license versions is made available with the language indicating
+; that LGPLv2 or any later version may be used, or where a choice of which version
+; of the LGPL is applied is otherwise unspecified.
+
+include vbdmismi.inc
+
+; org 0xff30
+align 16
+ ;; The SMBIOS header
+ db '_SM_' ; signature
+ db 0 ; checksum (set by biossums)
+ db 01Fh ; EPS length, defined by standard
+ db VBOX_SMBIOS_MAJOR_VER ; SMBIOS major version
+ db VBOX_SMBIOS_MINOR_VER ; SMBIOS minor version
+ dw VBOX_SMBIOS_MAXSS ; Maximum structure size
+ db 0 ; Entry point revision
+ db 0, 0, 0, 0, 0 ; 16 bytes total
+
+ ;; The DMI header
+ db '_DMI_' ; signature
+ db 0 ; checksum (set by biossums)
+ dw 0 ; DMI tables length (set by DevPcBios)
+ dd VBOX_DMI_TABLE_BASE ; DMI tables base
+ dw 0 ; DMI tables entries (set by DevPcBios)
+ db VBOX_DMI_TABLE_VER ; DMI version
+ db 0 ; Just for alignment (16 bytes total)
+
diff --git a/src/VBox/Devices/PC/BIOS/system.c b/src/VBox/Devices/PC/BIOS/system.c
new file mode 100644
index 00000000..d1cb66af
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/system.c
@@ -0,0 +1,941 @@
+/* $Id: system.c $ */
+/** @file
+ * PC BIOS - ???
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+
+#include <stdint.h>
+#include "biosint.h"
+#include "inlines.h"
+
+#if DEBUG_INT15
+# define BX_DEBUG_INT15(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define BX_DEBUG_INT15(...)
+#endif
+
+
+#define UNSUPPORTED_FUNCTION 0x86 /* Specific to INT 15h. */
+
+#define BIOS_CONFIG_TABLE 0xe6f5 /** @todo configurable? put elsewhere? */
+
+#define ACPI_DATA_SIZE 0x00010000L /** @todo configurable? put elsewhere? */
+
+extern int pmode_IDT;
+extern int rmode_IDT;
+
+uint16_t read_ss(void);
+#pragma aux read_ss = "mov ax, ss" modify exact [ax] nomemory;
+
+#if VBOX_BIOS_CPU >= 80386
+
+/* The 386+ code uses CR0 to switch to/from protected mode.
+ * Quite straightforward.
+ */
+
+void pm_stack_save(uint16_t cx, uint16_t es, uint16_t si);
+#pragma aux pm_stack_save = \
+ ".386" \
+ "push ds" \
+ "push eax" \
+ "xor ax, ax" \
+ "mov ds, ax" \
+ "mov ds:[467h], sp" \
+ "mov ds:[469h], ss" \
+ parm [cx] [es] [si] modify nomemory;
+
+/* Uses position independent code to build a far return... because it was
+ * too hard to figure out how to code the far call in inline assembler.
+ *
+ * NB: It would be lovely to do 'add [sp],N' instead of 'pop ax; add ax,M;
+ * push ax'. Unfortunately the former cannot be encoded, though 'add [esp],N'
+ * can be on 386 and later -- but it may be unwise to assume that the high
+ * bits of ESP are all zero.
+ */
+void pm_enter(void);
+#pragma aux pm_enter = \
+ ".386p" \
+ "lgdt fword ptr es:[si+8]" \
+ "lidt fword ptr cs:pmode_IDT" \
+ "push 20h" \
+ "call pentry" \
+ "pentry:" \
+ "pop ax" \
+ "add ax, 0Eh" \
+ "push ax" \
+ "mov eax, cr0" \
+ "or al, 1" \
+ "mov cr0, eax" \
+ "retf" \
+ "pm_pm:" \
+ "mov ax, 10h" \
+ "mov ds, ax" \
+ "add al, 08h" \
+ "mov es, ax" \
+ "add al, 10h" \
+ "mov ss, ax" \
+ modify nomemory;
+
+/* Restore segment limits to real mode compatible values and
+ * return to real mode.
+ */
+void pm_exit(void);
+#pragma aux pm_exit = \
+ ".386p" \
+ "mov ax, 28h" \
+ "mov ds, ax" \
+ "mov es, ax" \
+ "push 0F000h" \
+ "call pexit" \
+ "pexit:" \
+ "pop ax" \
+ "add ax, 0Eh" \
+ "push ax" \
+ "mov eax, cr0" \
+ "and al, 0FEh" \
+ "mov cr0, eax" \
+ "retf" \
+ "real_mode:" \
+ "lidt fword ptr cs:rmode_IDT" \
+ modify nomemory;
+
+/* Restore stack and reload segment registers in real mode to ensure
+ * real mode compatible selector+base.
+ */
+void pm_stack_restore(void);
+#pragma aux pm_stack_restore = \
+ ".386" \
+ "xor ax, ax" \
+ "mov ds, ax" \
+ "mov es, ax" \
+ "lss sp, ds:[467h]" \
+ "pop eax" \
+ "pop ds" \
+ modify nomemory;
+
+#elif VBOX_BIOS_CPU >= 80286
+
+/* The 286 code uses LMSW to switch to protected mode but it has to reset
+ * the CPU to get back to real mode. Ugly! See return_blkmove in orgs.asm
+ * for the other matching half.
+ */
+void pm_stack_save(uint16_t cx, uint16_t es, uint16_t si, uint16_t frame);
+#pragma aux pm_stack_save = \
+ "xor ax, ax" \
+ "mov ds, ax" \
+ "mov ds:[467h], bx" \
+ "mov ds:[469h], ss" \
+ parm [cx] [es] [si] [bx] modify nomemory;
+
+/* Uses position independent code... because it was too hard to figure
+ * out how to code the far call in inline assembler.
+ */
+void pm_enter(void);
+#pragma aux pm_enter = \
+ ".286p" \
+ "lgdt fword ptr es:[si+8]" \
+ "lidt fword ptr cs:pmode_IDT" \
+ "push 20h" \
+ "call pentry" \
+ "pentry:" \
+ "pop ax" \
+ "add ax, 0Eh" \
+ "push ax" \
+ "smsw ax" \
+ "or al, 1" \
+ "lmsw ax" \
+ "retf" \
+ "pm_pm:" \
+ "mov ax, 10h" \
+ "mov ds, ax" \
+ "add al, 08h" \
+ "mov es, ax" \
+ "add al, 10h" \
+ "mov ss, ax" \
+ modify nomemory;
+
+/* Set up shutdown status and reset the CPU. The POST code
+ * will regain control. Port 80h is written with status.
+ * Code 9 is written to CMOS shutdown status byte (0Fh).
+ * CPU is triple faulted. .
+ */
+void pm_exit(void);
+#pragma aux pm_exit = \
+ "xor ax, ax" \
+ "out 80h, al" \
+ "mov al, 0Fh" \
+ "out 70h, al" \
+ "mov al, 09h" \
+ "out 71h, al" \
+ ".286p" \
+ "lidt fword ptr cs:pmode_IDT" \
+ "int 3" \
+ modify nomemory;
+
+/* Dummy. Actually done in return_blkmove. */
+void pm_stack_restore(void);
+#pragma aux pm_stack_restore = \
+ "rm_return:" \
+ modify nomemory;
+
+#endif
+
+/* NB: CX is set earlier in pm_stack_save */
+void pm_copy(void);
+#pragma aux pm_copy = \
+ "xor si, si" \
+ "xor di, di" \
+ "cld" \
+ "rep movsw" \
+ modify [si di cx] nomemory;
+
+/* The pm_switch has a few crucial differences from pm_enter, hence
+ * it is replicated here. Uses LMSW to avoid trashing high word of eax.
+ */
+void pm_switch(uint16_t reg_si);
+#pragma aux pm_switch = \
+ ".286p" \
+ "lgdt fword ptr es:[si+08h]" \
+ "lidt fword ptr es:[si+10h]" \
+ "push 38h" \
+ "call pentry" \
+ "pentry:" \
+ "pop ax" \
+ "add ax, 0Eh" \
+ "push ax" \
+ "smsw ax" \
+ "or al, 1" \
+ "lmsw ax" \
+ "retf" \
+ "pm_pm:" \
+ "mov ax, 18h" \
+ "mov ds, ax" \
+ "add al, 08h" \
+ "mov es, ax" \
+ "add al, 08h" \
+ "mov ss, ax" \
+ parm [si] modify nomemory;
+
+/* Return to caller - we do not use IRET because we should not enable
+ * interrupts. Note that AH must be zero on exit.
+ * WARNING: Needs to be adapted if calling sequence is modified!
+ */
+void pm_unwind(uint16_t args);
+#pragma aux pm_unwind = \
+ ".286" \
+ "mov sp, ax" \
+ "popa" \
+ "add sp, 6" \
+ "pop cx" \
+ "pop ax" \
+ "pop ax" \
+ "mov ax, 30h" \
+ "push ax" \
+ "push cx" \
+ "retf" \
+ parm [ax] modify nomemory aborts;
+
+/// @todo This method is silly. The RTC should be programmed to fire an interrupt
+// instead of hogging the CPU with inaccurate code.
+void timer_wait(uint32_t usec_wait)
+{
+ uint32_t cycles;
+ uint8_t old_val;
+ uint8_t cur_val;
+
+ /* We wait in 15 usec increments. */
+ cycles = usec_wait / 15;
+
+ old_val = inp(0x61) & 0x10;
+ while (cycles--) {
+ /* Wait 15us. */
+ do {
+ cur_val = inp(0x61) & 0x10;
+ } while (cur_val != old_val);
+ old_val = cur_val;
+ }
+}
+
+bx_bool set_enable_a20(bx_bool val)
+{
+ uint8_t oldval;
+
+ // Use PS/2 System Control port A to set A20 enable
+
+ // get current setting first
+ oldval = inb(0x92);
+
+ // change A20 status
+ if (val)
+ outb(0x92, oldval | 0x02);
+ else
+ outb(0x92, oldval & 0xfd);
+
+ return((oldval & 0x02) != 0);
+}
+
+/// @todo move elsewhere?
+#define AX r.gr.u.r16.ax
+#define BX r.gr.u.r16.bx
+#define CX r.gr.u.r16.cx
+#define DX r.gr.u.r16.dx
+#define SI r.gr.u.r16.si
+#define DI r.gr.u.r16.di
+#define BP r.gr.u.r16.bp
+#define SP r.gr.u.r16.sp
+#define FLAGS r.fl.u.r16.flags
+#define EAX r.gr.u.r32.eax
+#define EBX r.gr.u.r32.ebx
+#define ECX r.gr.u.r32.ecx
+#define EDX r.gr.u.r32.edx
+#define ESI r.gr.u.r32.esi
+#define EDI r.gr.u.r32.edi
+#define ES r.es
+
+
+void BIOSCALL int15_function(sys_regs_t r)
+{
+ uint16_t bRegister;
+ uint8_t irqDisable;
+
+ BX_DEBUG_INT15("int15 AX=%04x\n",AX);
+
+ switch (GET_AH()) {
+ case 0x00: /* assorted functions */
+ if (GET_AL() != 0xc0)
+ goto undecoded;
+ /* GRUB calls int15 with ax=0x00c0 to get the ROM configuration table,
+ * which we don't support, but logging that event is annoying. In fact
+ * it is likely that they just misread some specs, because there is a
+ * int15 BIOS function AH=0xc0 which sounds quite similar to what GRUB
+ * wants to achieve. */
+ SET_CF();
+ SET_AH(UNSUPPORTED_FUNCTION);
+ break;
+ case 0x24: /* A20 Control */
+ switch (GET_AL()) {
+ case 0x00:
+ set_enable_a20(0);
+ CLEAR_CF();
+ SET_AH(0);
+ break;
+ case 0x01:
+ set_enable_a20(1);
+ CLEAR_CF();
+ SET_AH(0);
+ break;
+ case 0x02:
+ SET_AL( (inb(0x92) >> 1) & 0x01 );
+ CLEAR_CF();
+ SET_AH(0);
+ break;
+ case 0x03:
+ CLEAR_CF();
+ SET_AH(0);
+ BX = 3;
+ break;
+ default:
+ BX_INFO("int15: Func 24h, subfunc %02xh, A20 gate control not supported\n", (unsigned) GET_AL());
+ SET_CF();
+ SET_AH(UNSUPPORTED_FUNCTION);
+ }
+ break;
+
+ /* These are here just to avoid warnings being logged. */
+ case 0x22: /* Locate ROM BASIC (tough when we don't have any.) */
+ case 0x41: /* PC Convertible, wait for external events. */
+ case 0xC7: /* PS/2, get memory map. */
+ SET_CF();
+ SET_AH(UNSUPPORTED_FUNCTION);
+ break;
+
+ /// @todo Why does this need special handling? All we need is to set CF
+ // but not handle this as an unknown function (regardless of CPU type).
+ case 0x4f:
+ /* keyboard intercept */
+#if VBOX_BIOS_CPU >= 80286
+ // nop
+#else
+ SET_AH(UNSUPPORTED_FUNCTION);
+#endif
+ SET_CF();
+ break;
+
+ case 0x52: // removable media eject
+ CLEAR_CF();
+ SET_AH(0); // "ok ejection may proceed"
+ break;
+
+ case 0x83: {
+ if( GET_AL() == 0 ) {
+ // Set Interval requested.
+ if( ( read_byte( 0x40, 0xA0 ) & 1 ) == 0 ) {
+ // Interval not already set.
+ write_byte( 0x40, 0xA0, 1 ); // Set status byte.
+ write_word( 0x40, 0x98, ES ); // Byte location, segment
+ write_word( 0x40, 0x9A, BX ); // Byte location, offset
+ write_word( 0x40, 0x9C, DX ); // Low word, delay
+ write_word( 0x40, 0x9E, CX ); // High word, delay.
+ CLEAR_CF( );
+ irqDisable = inb( 0xA1 );
+ outb( 0xA1, irqDisable & 0xFE );
+ bRegister = inb_cmos( 0xB ); // Unmask IRQ8 so INT70 will get through.
+ outb_cmos( 0xB, bRegister | 0x40 ); // Turn on the Periodic Interrupt timer
+ } else {
+ // Interval already set.
+ BX_DEBUG_INT15("int15: Func 83h, failed, already waiting.\n" );
+ SET_CF();
+ SET_AH(UNSUPPORTED_FUNCTION);
+ }
+ } else if( GET_AL() == 1 ) {
+ // Clear Interval requested
+ write_byte( 0x40, 0xA0, 0 ); // Clear status byte
+ CLEAR_CF( );
+ bRegister = inb_cmos( 0xB );
+ outb_cmos( 0xB, bRegister & ~0x40 ); // Turn off the Periodic Interrupt timer
+ } else {
+ BX_DEBUG_INT15("int15: Func 83h, failed.\n" );
+ SET_CF();
+ SET_AH(UNSUPPORTED_FUNCTION);
+ SET_AL(GET_AL() - 1);
+ }
+
+ break;
+ }
+
+ case 0x86:
+ // Wait for CX:DX microseconds. currently using the
+ // refresh request port 0x61 bit4, toggling every 15usec
+ int_enable();
+ timer_wait(((uint32_t)CX << 16) | DX);
+ break;
+
+ case 0x88:
+ // Get the amount of extended memory (above 1M)
+#if VBOX_BIOS_CPU >= 80286
+ AX = (inb_cmos(0x31) << 8) | inb_cmos(0x30);
+
+#if VBOX_BIOS_CPU >= 80386
+ // According to Ralf Brown's interrupt the limit should be 15M,
+ // but real machines mostly return max. 63M.
+ if(AX > 0xffc0)
+ AX = 0xffc0;
+#else
+ // An AT compatible cannot have more than 15M extended memory.
+ // If more is reported, some software (e.g. Windows 3.1) gets
+ // quite upset.
+ if(AX > 0x3c00)
+ AX = 0x3c00;
+#endif
+
+ CLEAR_CF();
+#else
+ SET_AH(UNSUPPORTED_FUNCTION);
+ SET_CF();
+#endif
+ break;
+
+ case 0x89:
+ // Switch to Protected Mode.
+ // ES:DI points to user-supplied GDT
+ // BH/BL contains starting interrupt numbers for PIC0/PIC1
+ // This subfunction does not return!
+
+ // turn off interrupts
+ int_disable(); /// @todo aren't they off already?
+
+ set_enable_a20(1); // enable A20 line; we're supposed to fail if that fails
+
+ // Initialize CS descriptor for BIOS
+ write_word(ES, SI+0x38+0, 0xffff);// limit 15:00 = normal 64K limit
+ write_word(ES, SI+0x38+2, 0x0000);// base 15:00
+ write_byte(ES, SI+0x38+4, 0x000f);// base 23:16 (hardcoded to f000:0000)
+ write_byte(ES, SI+0x38+5, 0x9b); // access
+ write_word(ES, SI+0x38+6, 0x0000);// base 31:24/reserved/limit 19:16
+
+ /* Reprogram the PICs. */
+ outb(PIC_MASTER, PIC_CMD_INIT);
+ outb(PIC_SLAVE, PIC_CMD_INIT);
+ outb(PIC_MASTER + 1, GET_BH());
+ outb(PIC_SLAVE + 1, GET_BL());
+ outb(PIC_MASTER + 1, 4);
+ outb(PIC_SLAVE + 1, 2);
+ outb(PIC_MASTER + 1, 1);
+ outb(PIC_SLAVE + 1, 1);
+ /* Mask all IRQs, user must re-enable. */
+ outb(PIC_MASTER_MASK, 0xff);
+ outb(PIC_SLAVE_MASK, 0xff);
+
+ pm_switch(SI);
+ pm_unwind((uint16_t)&r);
+
+ break;
+
+ case 0x90:
+ /* Device busy interrupt. Called by Int 16h when no key available */
+ break;
+
+ case 0x91:
+ /* Interrupt complete. Called by Int 16h when key becomes available */
+ break;
+
+ case 0xbf:
+ BX_INFO("*** int 15h function AH=bf not yet supported!\n");
+ SET_CF();
+ SET_AH(UNSUPPORTED_FUNCTION);
+ break;
+
+ case 0xC0:
+ CLEAR_CF();
+ SET_AH(0);
+ BX = BIOS_CONFIG_TABLE;
+ ES = 0xF000;
+ break;
+
+ case 0xc1:
+ ES = read_word(0x0040, 0x000E);
+ CLEAR_CF();
+ break;
+
+ case 0xd8:
+ bios_printf(BIOS_PRINTF_DEBUG, "EISA BIOS not present\n");
+ SET_CF();
+ SET_AH(UNSUPPORTED_FUNCTION);
+ break;
+
+ /* Make the BIOS warning for pretty much every Linux kernel start
+ * disappear - it calls with ax=0xe980 to figure out SMI info. */
+ case 0xe9: /* SMI functions (SpeedStep and similar things) */
+ SET_CF();
+ SET_AH(UNSUPPORTED_FUNCTION);
+ break;
+ case 0xec: /* AMD64 target operating mode callback */
+ if (GET_AL() != 0)
+ goto undecoded;
+ SET_AH(0);
+ if (GET_BL() >= 1 && GET_BL() <= 3)
+ CLEAR_CF(); /* Accepted value. */
+ else
+ SET_CF(); /* Reserved, error. */
+ break;
+undecoded:
+ default:
+ BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n",
+ (unsigned) AX, (unsigned) BX);
+ SET_CF();
+ SET_AH(UNSUPPORTED_FUNCTION);
+ break;
+ }
+}
+
+#if VBOX_BIOS_CPU >= 80386
+
+typedef struct {
+ uint32_t start;
+ uint32_t xstart;
+ uint32_t len;
+ uint32_t xlen;
+ uint32_t type;
+} mem_range_t;
+
+void set_e820_range(uint16_t reg_ES, uint16_t reg_DI, uint32_t start, uint32_t end,
+ uint8_t extra_start, uint8_t extra_end, uint16_t type)
+{
+ mem_range_t __far *range;
+
+ range = reg_ES :> (mem_range_t *)reg_DI;
+ range->start = start;
+ range->xstart = extra_start;
+ end -= start;
+ extra_end -= extra_start;
+ range->len = end;
+ range->xlen = extra_end;
+ range->type = type;
+}
+
+void BIOSCALL int15_function32(sys32_regs_t r)
+{
+ uint32_t extended_memory_size=0; // 64bits long
+ uint32_t extra_lowbits_memory_size=0;
+ uint8_t extra_highbits_memory_size=0;
+ uint32_t mcfgStart, mcfgSize;
+
+ BX_DEBUG_INT15("int15 AX=%04x\n",AX);
+
+ switch (GET_AH()) {
+ case 0xd0:
+ if (GET_AL() != 0x4f)
+ goto int15_unimplemented;
+ if (EBX == 0x50524f43 && ECX == 0x4d4f4445 && ESI == 0 && EDI == 0)
+ {
+ CLEAR_CF();
+ ESI = EBX;
+ EDI = ECX;
+ EAX = 0x49413332;
+ }
+ else
+ goto int15_unimplemented;
+ break;
+
+ case 0xe8:
+ switch(GET_AL()) {
+ case 0x20: // coded by osmaker aka K.J.
+ if(EDX == 0x534D4150) {
+ extended_memory_size = inb_cmos(0x35);
+ extended_memory_size <<= 8;
+ extended_memory_size |= inb_cmos(0x34);
+ extended_memory_size *= 64;
+#ifndef VBOX /* The following excludes 0xf0000000 thru 0xffffffff. Trust DevPcBios.cpp to get this right. */
+ // greater than EFF00000???
+ if(extended_memory_size > 0x3bc000) {
+ extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000
+ }
+#endif /* !VBOX */
+ extended_memory_size *= 1024;
+ extended_memory_size += (16L * 1024 * 1024);
+
+ if(extended_memory_size <= (16L * 1024 * 1024)) {
+ extended_memory_size = inb_cmos(0x31);
+ extended_memory_size <<= 8;
+ extended_memory_size |= inb_cmos(0x30);
+ extended_memory_size *= 1024;
+ extended_memory_size += (1L * 1024 * 1024);
+ }
+
+#ifdef VBOX /* We've already used the CMOS entries for SATA.
+ BTW. This is the amount of memory above 4GB measured in 64KB units. */
+ extra_lowbits_memory_size = inb_cmos(0x62);
+ extra_lowbits_memory_size <<= 8;
+ extra_lowbits_memory_size |= inb_cmos(0x61);
+ extra_lowbits_memory_size <<= 16;
+ extra_highbits_memory_size = inb_cmos(0x63);
+ /* 0x64 and 0x65 can be used if we need to dig 1 TB or more at a later point. */
+#else
+ extra_lowbits_memory_size = inb_cmos(0x5c);
+ extra_lowbits_memory_size <<= 8;
+ extra_lowbits_memory_size |= inb_cmos(0x5b);
+ extra_lowbits_memory_size *= 64;
+ extra_lowbits_memory_size *= 1024;
+ extra_highbits_memory_size = inb_cmos(0x5d);
+#endif /* !VBOX */
+
+ mcfgStart = 0;
+ mcfgSize = 0;
+
+ switch(BX)
+ {
+ case 0:
+ set_e820_range(ES, DI,
+#ifndef VBOX /** @todo Upstream suggests the following, needs checking. (see next as well) */
+ 0x0000000L, 0x0009f000L, 0, 0, 1);
+#else
+ 0x0000000L, 0x0009fc00L, 0, 0, 1);
+#endif
+ EBX = 1;
+ break;
+ case 1:
+ set_e820_range(ES, DI,
+#ifndef VBOX /** @todo Upstream suggests the following, needs checking. (see next as well) */
+ 0x0009f000L, 0x000a0000L, 0, 0, 2);
+#else
+ 0x0009fc00L, 0x000a0000L, 0, 0, 2);
+#endif
+ EBX = 2;
+ break;
+ case 2:
+#ifdef VBOX
+ /* Mark the BIOS as reserved. VBox doesn't currently
+ * use the 0xe0000-0xeffff area. It does use the
+ * 0xd0000-0xdffff area for the BIOS logo, but it's
+ * not worth marking it as reserved. (this is not
+ * true anymore because the VGA adapter handles the logo stuff)
+ * The whole 0xe0000-0xfffff can be used for the BIOS.
+ * Note that various
+ * Windows versions don't accept (read: in debug builds
+ * they trigger the "Too many similar traps" assertion)
+ * a single reserved range from 0xd0000 to 0xffffff.
+ * A 128K area starting from 0xd0000 works. */
+ set_e820_range(ES, DI,
+ 0x000f0000L, 0x00100000L, 0, 0, 2);
+#else /* !VBOX */
+ set_e820_range(ES, DI,
+ 0x000e8000L, 0x00100000L, 0, 0, 2);
+#endif /* !VBOX */
+ EBX = 3;
+ break;
+ case 3:
+#if BX_ROMBIOS32 || defined(VBOX)
+ set_e820_range(ES, DI,
+ 0x00100000L,
+ extended_memory_size - ACPI_DATA_SIZE, 0, 0, 1);
+ EBX = 4;
+#else
+ set_e820_range(ES, DI,
+ 0x00100000L,
+ extended_memory_size, 1);
+ EBX = 5;
+#endif
+ break;
+ case 4:
+ set_e820_range(ES, DI,
+ extended_memory_size - ACPI_DATA_SIZE,
+ extended_memory_size, 0, 0, 3); // ACPI RAM
+ EBX = 5;
+ break;
+ case 5:
+ set_e820_range(ES, DI,
+ 0xfec00000,
+ 0xfec00000 + 0x1000, 0, 0, 2); // I/O APIC
+ EBX = 6;
+ break;
+ case 6:
+ set_e820_range(ES, DI,
+ 0xfee00000,
+ 0xfee00000 + 0x1000, 0, 0, 2); // Local APIC
+ EBX = 7;
+ break;
+ case 7:
+ /* 256KB BIOS area at the end of 4 GB */
+#ifdef VBOX
+ /* We don't set the end to 1GB here and rely on the 32-bit
+ unsigned wrap around effect (0-0xfffc0000L). */
+#endif
+ set_e820_range(ES, DI,
+ 0xfffc0000L, 0x00000000L, 0, 0, 2);
+ if (mcfgStart != 0)
+ EBX = 8;
+ else
+ {
+ if (extra_highbits_memory_size || extra_lowbits_memory_size)
+ EBX = 9;
+ else
+ EBX = 0;
+ }
+ break;
+ case 8:
+ /* PCI MMIO config space (MCFG) */
+ set_e820_range(ES, DI,
+ mcfgStart, mcfgStart + mcfgSize, 0, 0, 2);
+
+ if (extra_highbits_memory_size || extra_lowbits_memory_size)
+ EBX = 9;
+ else
+ EBX = 0;
+ break;
+ case 9:
+#ifdef VBOX /* Don't succeeded if no memory above 4 GB. */
+ /* Mapping of memory above 4 GB if present.
+ Note1: set_e820_range needs do no borrowing in the
+ subtraction because of the nice numbers.
+ Note2* works only up to 1TB because of uint8_t for
+ the upper bits!*/
+ if (extra_highbits_memory_size || extra_lowbits_memory_size)
+ {
+ set_e820_range(ES, DI,
+ 0x00000000L, extra_lowbits_memory_size,
+ 1 /*x4GB*/, extra_highbits_memory_size + 1 /*x4GB*/, 1);
+ EBX = 0;
+ }
+ break;
+ /* fall thru */
+#else /* !VBOX */
+ /* Mapping of memory above 4 GB */
+ set_e820_range(ES, DI, 0x00000000L,
+ extra_lowbits_memory_size, 1, extra_highbits_memory_size
+ + 1, 1);
+ EBX = 0;
+ break;
+#endif /* !VBOX */
+ default: /* AX=E820, DX=534D4150, BX unrecognized */
+ goto int15_unimplemented;
+ break;
+ }
+ EAX = 0x534D4150;
+ ECX = 0x14;
+ CLEAR_CF();
+ } else {
+ // if DX != 0x534D4150)
+ goto int15_unimplemented;
+ }
+ break;
+
+ case 0x01:
+ // do we have any reason to fail here ?
+ CLEAR_CF();
+
+ // my real system sets ax and bx to 0
+ // this is confirmed by Ralph Brown list
+ // but syslinux v1.48 is known to behave
+ // strangely if ax is set to 0
+ // regs.u.r16.ax = 0;
+ // regs.u.r16.bx = 0;
+
+ // Get the amount of extended memory (above 1M)
+ CX = (inb_cmos(0x31) << 8) | inb_cmos(0x30);
+
+ // limit to 15M
+ if(CX > 0x3c00)
+ CX = 0x3c00;
+
+ // Get the amount of extended memory above 16M in 64k blocks
+ DX = (inb_cmos(0x35) << 8) | inb_cmos(0x34);
+
+ // Set configured memory equal to extended memory
+ AX = CX;
+ BX = DX;
+ break;
+ default: /* AH=0xE8?? but not implemented */
+ goto int15_unimplemented;
+ }
+ break;
+ int15_unimplemented:
+ // fall into the default case
+ default:
+ BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n",
+ (unsigned) AX, (unsigned) BX);
+ SET_CF();
+ SET_AL(UNSUPPORTED_FUNCTION);
+ break;
+ }
+}
+#endif /* VBOX_BIOS_CPU >= 80386 */
+
+#if VBOX_BIOS_CPU >= 80286
+
+#undef FLAGS
+#define FLAGS r.ra.flags.u.r16.flags
+
+/* Function 0x87 handled separately due to specific stack layout requirements. */
+void BIOSCALL int15_blkmove(disk_regs_t r)
+{
+ uint16_t base15_00;
+ uint8_t base23_16;
+ uint16_t ss;
+
+ // +++ should probably have descriptor checks
+ // +++ should have exception handlers
+
+ // turn off interrupts
+ int_disable(); /// @todo aren't they disabled already?
+
+ set_enable_a20(1); // enable A20 line
+
+ // 128K max of transfer on 386+ ???
+ // source == destination ???
+
+ // ES:SI points to descriptor table
+ // offset use initially comments
+ // ==============================================
+ // 00..07 Unused zeros Null descriptor
+ // 08..0f scratch zeros work area used by BIOS
+ // 10..17 source ssssssss source of data
+ // 18..1f dest dddddddd destination of data
+ // 20..27 CS zeros filled in by BIOS
+ // 28..2f SS zeros filled in by BIOS
+
+ //es:si
+ //eeee0
+ //0ssss
+ //-----
+
+ // check for access rights of source & dest here
+
+ // Initialize GDT descriptor
+ base15_00 = (ES << 4) + SI;
+ base23_16 = ES >> 12;
+ if (base15_00 < (ES<<4))
+ base23_16++;
+ write_word(ES, SI+0x08+0, 47); // limit 15:00 = 6 * 8bytes/descriptor
+ write_word(ES, SI+0x08+2, base15_00);// base 15:00
+ write_byte(ES, SI+0x08+4, base23_16);// base 23:16
+ write_byte(ES, SI+0x08+5, 0x93); // access
+ write_word(ES, SI+0x08+6, 0x0000); // base 31:24/reserved/limit 19:16
+
+ // Initialize CS descriptor
+ write_word(ES, SI+0x20+0, 0xffff);// limit 15:00 = normal 64K limit
+ write_word(ES, SI+0x20+2, 0x0000);// base 15:00
+ write_byte(ES, SI+0x20+4, 0x000f);// base 23:16
+ write_byte(ES, SI+0x20+5, 0x9b); // access
+ write_word(ES, SI+0x20+6, 0x0000);// base 31:24/reserved/limit 19:16
+
+ // Initialize SS descriptor
+ ss = read_ss();
+ base15_00 = ss << 4;
+ base23_16 = ss >> 12;
+ write_word(ES, SI+0x28+0, 0xffff); // limit 15:00 = normal 64K limit
+ write_word(ES, SI+0x28+2, base15_00);// base 15:00
+ write_byte(ES, SI+0x28+4, base23_16);// base 23:16
+ write_byte(ES, SI+0x28+5, 0x93); // access
+ write_word(ES, SI+0x28+6, 0x0000); // base 31:24/reserved/limit 19:16
+
+#if VBOX_BIOS_CPU >= 80386
+ /* Not taking the address of the parameter allows the code generator
+ * produce slightly better code for some unknown reason.
+ */
+ pm_stack_save(CX, ES, SI);
+#else
+ pm_stack_save(CX, ES, SI, FP_OFF(&r));
+#endif
+ pm_enter();
+ pm_copy();
+ pm_exit();
+ pm_stack_restore();
+
+ set_enable_a20(0); // unconditionally disable A20 line
+
+ // turn interrupts back on
+ int_enable();
+
+ SET_AH(0);
+ CLEAR_CF();
+}
+#endif /* VBOX_BIOS_CPU >= 80286 */
diff --git a/src/VBox/Devices/PC/BIOS/timepci.c b/src/VBox/Devices/PC/BIOS/timepci.c
new file mode 100644
index 00000000..f6b75645
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/timepci.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
+ *
+ * Copyright (C) 2002 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+
+#include <stdint.h>
+#include "biosint.h"
+#include "inlines.h"
+
+#if DEBUG_INT1A
+# define BX_DEBUG_INT1A(...) BX_DEBUG(__VA_ARGS__)
+#else
+# define BX_DEBUG_INT1A(...)
+#endif
+
+// for access to RAM area which is used by interrupt vectors
+// and BIOS Data Area
+
+typedef struct {
+ uint8_t filler1[0x400];
+ uint8_t filler2[0x6c];
+ uint16_t ticks_low;
+ uint16_t ticks_high;
+ uint8_t midnight_flag;
+} bios_data_t;
+
+#define BiosData ((bios_data_t __far *) 0)
+
+void init_rtc(void)
+{
+ outb_cmos(0x0a, 0x26);
+ outb_cmos(0x0b, 0x02);
+ inb_cmos(0x0c);
+ inb_cmos(0x0d);
+}
+
+bx_bool rtc_updating(void)
+{
+ // This function checks to see if the update-in-progress bit
+ // is set in CMOS Status Register A. If not, it returns 0.
+ // If it is set, it tries to wait until there is a transition
+ // to 0, and will return 0 if such a transition occurs. A 1
+ // is returned only after timing out. The maximum period
+ // that this bit should be set is constrained to 244useconds.
+ // The count I use below guarantees coverage or more than
+ // this time, with any reasonable IPS setting.
+
+ uint16_t iter;
+
+ iter = 25000;
+ while (--iter != 0) {
+ if ( (inb_cmos(0x0a) & 0x80) == 0 )
+ return 0;
+ }
+ return 1; // update-in-progress never transitioned to 0
+}
+
+
+extern void eoi_both_pics(void); /* in assembly code */
+#pragma aux eoi_both_pics "*";
+
+void call_int_4a(void);
+#pragma aux call_int_4a = "int 4Ah";
+
+void BIOSCALL int70_function(pusha_regs_t regs, uint16_t ds, uint16_t es, iret_addr_t iret_addr)
+{
+ // INT 70h: IRQ 8 - CMOS RTC interrupt from periodic or alarm modes
+ uint8_t registerB = 0, registerC = 0;
+
+ // Check which modes are enabled and have occurred.
+ registerB = inb_cmos( 0xB );
+ registerC = inb_cmos( 0xC );
+
+ if( ( registerB & 0x60 ) != 0 ) {
+ if( ( registerC & 0x20 ) != 0 ) {
+ // Handle Alarm Interrupt.
+ int_enable();
+ call_int_4a();
+ int_disable();
+ }
+ if( ( registerC & 0x40 ) != 0 ) {
+ // Handle Periodic Interrupt.
+
+ if( read_byte( 0x40, 0xA0 ) != 0 ) {
+ // Wait Interval (Int 15, AH=83) active.
+ uint32_t time;
+
+ time = read_dword( 0x40, 0x9C ); // Time left in microseconds.
+ if( time < 0x3D1 ) {
+ // Done waiting.
+ uint16_t segment, offset;
+
+ segment = read_word( 0x40, 0x98 );
+ offset = read_word( 0x40, 0x9A );
+ write_byte( 0x40, 0xA0, 0 ); // Turn of status byte.
+ outb_cmos( 0xB, registerB & 0x37 ); // Clear the Periodic Interrupt.
+ write_byte( segment, offset, read_byte(segment, offset) | 0x80 ); // Write to specified flag byte.
+ } else {
+ // Continue waiting.
+ time -= 0x3D1;
+ write_dword( 0x40, 0x9C, time );
+ }
+ }
+ }
+ }
+ eoi_both_pics();
+}
+
+/// @todo the coding style WRT register access is totally inconsistent
+// in the following routines
+
+void BIOSCALL int1a_function(pusha_regs_t regs, uint16_t ds, uint16_t es, iret_addr_t iret_addr)
+{
+ uint8_t val8;
+
+ BX_DEBUG_INT1A("int1a: AX=%04x BX=%04x CX=%04x DX=%04x DS=%04x\n",
+ regs.u.r16.ax, regs.u.r16.bx, regs.u.r16.cx, regs.u.r16.dx, ds);
+ int_enable();
+
+ switch (regs.u.r8.ah) {
+ case 0: // get current clock count
+ int_disable();
+ regs.u.r16.cx = BiosData->ticks_high;
+ regs.u.r16.dx = BiosData->ticks_low;
+ regs.u.r8.al = BiosData->midnight_flag;
+ BiosData->midnight_flag = 0; // reset flag
+ int_enable();
+ // AH already 0
+ ClearCF(iret_addr.flags); // OK
+ break;
+
+ case 1: // Set Current Clock Count
+ int_disable();
+ BiosData->ticks_high = regs.u.r16.cx;
+ BiosData->ticks_low = regs.u.r16.dx;
+ BiosData->midnight_flag = 0; // reset flag
+ int_enable();
+ regs.u.r8.ah = 0;
+ ClearCF(iret_addr.flags); // OK
+ break;
+
+ case 2: // Read CMOS Time
+ if (rtc_updating()) {
+ SetCF(iret_addr.flags);
+ break;
+ }
+
+ regs.u.r8.dh = inb_cmos(0x00); // Seconds
+ regs.u.r8.cl = inb_cmos(0x02); // Minutes
+ regs.u.r8.ch = inb_cmos(0x04); // Hours
+ regs.u.r8.dl = inb_cmos(0x0b) & 0x01; // Stat Reg B
+ regs.u.r8.ah = 0;
+ regs.u.r8.al = regs.u.r8.ch;
+ ClearCF(iret_addr.flags); // OK
+ break;
+
+ case 3: // Set CMOS Time
+ // Using a debugger, I notice the following masking/setting
+ // of bits in Status Register B, by setting Reg B to
+ // a few values and getting its value after INT 1A was called.
+ //
+ // try#1 try#2 try#3
+ // before 1111 1101 0111 1101 0000 0000
+ // after 0110 0010 0110 0010 0000 0010
+ //
+ // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
+ // My assumption: RegB = ((RegB & 01100000b) | 00000010b)
+ if (rtc_updating()) {
+ init_rtc();
+ // fall through as if an update were not in progress
+ }
+ outb_cmos(0x00, regs.u.r8.dh); // Seconds
+ outb_cmos(0x02, regs.u.r8.cl); // Minutes
+ outb_cmos(0x04, regs.u.r8.ch); // Hours
+ // Set Daylight Savings time enabled bit to requested value
+ val8 = (inb_cmos(0x0b) & 0x60) | 0x02 | (regs.u.r8.dl & 0x01);
+ // (reg B already selected)
+ outb_cmos(0x0b, val8);
+ regs.u.r8.ah = 0;
+ regs.u.r8.al = val8; // val last written to Reg B
+ ClearCF(iret_addr.flags); // OK
+ break;
+
+ case 4: // Read CMOS Date
+ regs.u.r8.ah = 0;
+ if (rtc_updating()) {
+ SetCF(iret_addr.flags);
+ break;
+ }
+ regs.u.r8.cl = inb_cmos(0x09); // Year
+ regs.u.r8.dh = inb_cmos(0x08); // Month
+ regs.u.r8.dl = inb_cmos(0x07); // Day of Month
+ regs.u.r8.ch = inb_cmos(0x32); // Century
+ regs.u.r8.al = regs.u.r8.ch;
+ ClearCF(iret_addr.flags); // OK
+ break;
+
+ case 5: // Set CMOS Date
+ // Using a debugger, I notice the following masking/setting
+ // of bits in Status Register B, by setting Reg B to
+ // a few values and getting its value after INT 1A was called.
+ //
+ // try#1 try#2 try#3 try#4
+ // before 1111 1101 0111 1101 0000 0010 0000 0000
+ // after 0110 1101 0111 1101 0000 0010 0000 0000
+ //
+ // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
+ // My assumption: RegB = (RegB & 01111111b)
+ if (rtc_updating()) {
+ init_rtc();
+ SetCF(iret_addr.flags);
+ break;
+ }
+ outb_cmos(0x09, regs.u.r8.cl); // Year
+ outb_cmos(0x08, regs.u.r8.dh); // Month
+ outb_cmos(0x07, regs.u.r8.dl); // Day of Month
+ outb_cmos(0x32, regs.u.r8.ch); // Century
+ val8 = inb_cmos(0x0b) & 0x7f; // clear halt-clock bit
+ outb_cmos(0x0b, val8);
+ regs.u.r8.ah = 0;
+ regs.u.r8.al = val8; // AL = val last written to Reg B
+ ClearCF(iret_addr.flags); // OK
+ break;
+
+ case 6: // Set Alarm Time in CMOS
+ // Using a debugger, I notice the following masking/setting
+ // of bits in Status Register B, by setting Reg B to
+ // a few values and getting its value after INT 1A was called.
+ //
+ // try#1 try#2 try#3
+ // before 1101 1111 0101 1111 0000 0000
+ // after 0110 1111 0111 1111 0010 0000
+ //
+ // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
+ // My assumption: RegB = ((RegB & 01111111b) | 00100000b)
+ val8 = inb_cmos(0x0b); // Get Status Reg B
+ regs.u.r16.ax = 0;
+ if (val8 & 0x20) {
+ // Alarm interrupt enabled already
+ SetCF(iret_addr.flags); // Error: alarm in use
+ break;
+ }
+ if (rtc_updating()) {
+ init_rtc();
+ // fall through as if an update were not in progress
+ }
+ outb_cmos(0x01, regs.u.r8.dh); // Seconds alarm
+ outb_cmos(0x03, regs.u.r8.cl); // Minutes alarm
+ outb_cmos(0x05, regs.u.r8.ch); // Hours alarm
+ outb(0xa1, inb(0xa1) & 0xfe); // enable IRQ 8
+ // enable Status Reg B alarm bit, clear halt clock bit
+ outb_cmos(0x0b, (val8 & 0x7f) | 0x20);
+ ClearCF(iret_addr.flags); // OK
+ break;
+
+ case 7: // Turn off Alarm
+ // Using a debugger, I notice the following masking/setting
+ // of bits in Status Register B, by setting Reg B to
+ // a few values and getting its value after INT 1A was called.
+ //
+ // try#1 try#2 try#3 try#4
+ // before 1111 1101 0111 1101 0010 0000 0010 0010
+ // after 0100 0101 0101 0101 0000 0000 0000 0010
+ //
+ // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
+ // My assumption: RegB = (RegB & 01010111b)
+ val8 = inb_cmos(0x0b); // Get Status Reg B
+ // clear clock-halt bit, disable alarm bit
+ outb_cmos(0x0b, val8 & 0x57); // disable alarm bit
+ regs.u.r8.ah = 0;
+ regs.u.r8.al = val8; // val last written to Reg B
+ ClearCF(iret_addr.flags); // OK
+ break;
+
+ default:
+ BX_DEBUG_INT1A("int1a: AX=%04x unsupported\n", regs.u.r16.ax);
+ SetCF(iret_addr.flags); // Unsupported
+ }
+}
diff --git a/src/VBox/Devices/PC/BIOS/vbdmismi.inc b/src/VBox/Devices/PC/BIOS/vbdmismi.inc
new file mode 100644
index 00000000..67e22f19
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/vbdmismi.inc
@@ -0,0 +1,27 @@
+; $Id: vbdmismi.inc $
+;; @file
+; DMI and SMBIOS definitions for VBox.
+;
+
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;; TODO: make dynamic
+
+VBOX_DMI_TABLE_BASE equ 0E1000h
+VBOX_DMI_TABLE_VER equ 25h
+VBOX_DMI_TABLE_SIZE equ 352
+
+VBOX_SMBIOS_MAJOR_VER equ 2
+VBOX_SMBIOS_MINOR_VER equ 5
+VBOX_SMBIOS_MAXSS equ 0FFh
+
diff --git a/src/VBox/Devices/PC/BIOS/vds.c b/src/VBox/Devices/PC/BIOS/vds.c
new file mode 100644
index 00000000..e4dab0d3
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/vds.c
@@ -0,0 +1,118 @@
+/* $Id: vds.c $ */
+/** @file
+ * Utility routines for calling the Virtual DMA Services.
+ */
+
+/*
+ * Copyright (C) 2011-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+#include <stdint.h>
+#include "biosint.h"
+#include "vds.h"
+
+typedef struct {
+ uint8_t major; /* VDS spec major version number. */
+ uint8_t minor; /* VDS spec minor version number. */
+ uint16_t flags; /* Capabilities/status flags. */
+ uint16_t prod_no; /* Product number. */
+ uint16_t prod_rev; /* Product revision number. */
+ uint32_t max_buf; /* Maximum buffer size supported. */
+} vds_ver;
+
+int vds_is_present( void )
+{
+ uint8_t __far *vds_flags;
+
+ vds_flags = MK_FP( 0x40, VDS_FLAGS_OFS );
+ return( !!(*vds_flags & VDS_PRESENT) );
+}
+
+int vds_lock_sg( vds_edds __far *edds );
+#pragma aux vds_lock_sg = \
+ "mov ax, 8105h" \
+ "mov dx, 0" \
+ "int 4Bh" \
+ "jc error" \
+ "xor al, al" \
+ "error:" \
+ "cbw" \
+ parm [es di] value [ax];
+
+int vds_unlock_sg( vds_edds __far *edds );
+#pragma aux vds_unlock_sg = \
+ "mov ax, 8106h" \
+ "mov dx, 0" \
+ "int 4Bh" \
+ "jc error" \
+ "xor al, al" \
+ "error:" \
+ "cbw" \
+ parm [es di] value [ax];
+
+
+/*
+ * Convert a real mode 16:16 segmented address to a simple 32-bit
+ * linear address.
+ */
+uint32_t vds_real_to_lin( void __far *ptr )
+{
+ return( ((uint32_t)FP_SEG( ptr ) << 4) + FP_OFF( ptr ) );
+}
+
+/*
+ * Build a VDS-style scatter/gather list, regardless of whether VDS is
+ * present or not. This routine either calls VDS to do the work or
+ * trivially creates the list if no remapping is needed.
+ */
+int vds_build_sg_list( vds_edds __far *edds, void __far *buf, uint32_t len )
+{
+ int rc;
+
+ /* NB: The num_avail field in the EDDS must be set correctly! */
+ edds->region_size = len;
+ edds->offset = vds_real_to_lin( buf );
+ edds->seg_sel = 0; /* Indicates a linear address. */
+ if( vds_is_present() ) {
+ /* VDS is present, use it. */
+ rc = vds_lock_sg( edds );
+ } else {
+ /* No VDS, do it ourselves with one S/G entry. */
+ edds->num_used = 1;
+ edds->u.sg[0].phys_addr = edds->offset;
+ edds->u.sg[0].size = len;
+ rc = VDS_SUCCESS;
+ }
+ return( rc );
+}
+
+/*
+ * Free a VDS-style scatter/gather list, regardless of whether VDS
+ * is present or not.
+ */
+int vds_free_sg_list( vds_edds __far *edds )
+{
+ int rc;
+
+ if( vds_is_present() ) {
+ /* VDS is present, use it. */
+ rc = vds_unlock_sg( edds );
+ } else {
+ /* No VDS, not much to do. */
+ /* We could check here if the EDDS had in fact been built by us.
+ * But if VDS really went away, what can we do about it anyway?
+ */
+ rc = VDS_SUCCESS;
+ }
+ edds->num_used = 0;
+ return( rc );
+}
diff --git a/src/VBox/Devices/PC/BIOS/vds.h b/src/VBox/Devices/PC/BIOS/vds.h
new file mode 100644
index 00000000..e003448c
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/vds.h
@@ -0,0 +1,122 @@
+/* $Id: vds.h $ */
+/** @file
+ * Utility routines for calling the Virtual DMA Services.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_INCLUDED_SRC_PC_BIOS_vds_h
+#define VBOX_INCLUDED_SRC_PC_BIOS_vds_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Virtual DMA Services (VDS) */
+
+#define VDS_FLAGS_OFS 0x7B /* Offset of VDS flag byte in BDA. */
+#define VDS_PRESENT 0x20 /* The VDS present bit. */
+
+/** The DMA descriptor data structure. */
+typedef struct
+{
+ uint32_t region_size; /* Region size in bytes. */
+ uint32_t offset; /* Offset. */
+ uint16_t seg_sel; /* Segment selector. */
+ uint16_t buf_id; /* Buffer ID. */
+ uint32_t phys_addr; /* Physical address. */
+} vds_dds;
+
+
+/** Scatter/gather descriptor entry. */
+typedef struct
+{
+ uint32_t phys_addr; /* Physical address. */
+ uint32_t size; /* Entry size. */
+} vds_sg;
+
+/** The extended DDS for scatter/gather.
+ * Note that the EDDS contains either S/G descriptors or x86-style PTEs.
+ */
+typedef struct
+{
+ uint32_t region_size; /* Region size in bytes. */
+ uint32_t offset; /* Offset. */
+ uint16_t seg_sel; /* Segment or selector. */
+ uint16_t resvd; /* Reserved. */
+ uint16_t num_avail; /* Number of entries available. */
+ uint16_t num_used; /* Number of entries used. */
+ union
+ {
+ vds_sg sg[1]; /* S/G entry array. */
+ uint32_t pte[1]; /* Page table entry array. */
+ } u;
+} vds_edds;
+
+
+/* VDS services */
+
+#define VDS_SERVICE 0x81
+
+#define VDS_GET_VERSION 0x02 /* Get version */
+#define VDS_LOCK_BUFFER 0x03 /* Lock DMA buffer region */
+#define VDS_UNLOCK_BUFFER 0x04 /* Unlock DMA buffer region */
+#define VDS_SG_LOCK 0x05 /* Scatter/gather lock region */
+#define VDS_SG_UNLOCK 0x06 /* Scatter/gather unlock region */
+#define VDS_REQUEST_BUFFER 0x07 /* Request DMA buffer */
+#define VDS_RELEASE_BUFFER 0x08 /* Release DMA buffer */
+#define VDS_BUFFER_COPYIN 0x09 /* Copy into DMA buffer */
+#define VDS_BUFFER_COPYOUT 0x0A /* Copy out of DMA buffer */
+#define VDS_DISABLE_DMA_XLAT 0x0B /* Disable DMA translation */
+#define VDS_ENABLE_DMA_XLAT 0x0C /* Enable DMA translation */
+
+/* VDS error codes */
+
+#define VDS_SUCCESS 0x00 /* No error */
+#define VDS_ERR_NOT_CONTIG 0x01 /* Region not contiguous */
+#define VDS_ERR_BOUNDRY_CROSS 0x02 /* Rgn crossed phys align boundary */
+#define VDS_ERR_CANT_LOCK 0x03 /* Unable to lock pages */
+#define VDS_ERR_NO_BUF 0x04 /* No buffer available */
+#define VDS_ERR_RGN_TOO_BIG 0x05 /* Region too large for buffer */
+#define VDS_ERR_BUF_IN_USE 0x06 /* Buffer currently in use */
+#define VDS_ERR_RGN_INVALID 0x07 /* Invalid memory region */
+#define VDS_ERR_RGN_NOT_LOCKED 0x08 /* Region was not locked */
+#define VDS_ERR_TOO_MANY_PAGES 0x09 /* Num pages greater than table len */
+#define VDS_ERR_INVALID_ID 0x0A /* Invalid buffer ID */
+#define VDS_ERR_BNDRY_VIOL 0x0B /* Buffer boundary violated */
+#define VDS_ERR_INVAL_DMACHN 0x0C /* Invalid DMA channel number */
+#define VDS_ERR_COUNT_OVRFLO 0x0D /* Disable count overflow */
+#define VDS_ERR_COUNT_UNDRFLO 0x0E /* Disable count underflow */
+#define VDS_ERR_UNSUPP_FUNC 0x0F /* Function not supported */
+#define VDS_ERR_BAD_FLAG 0x10 /* Reserved flag bits set in DX */
+
+/* VDS option flags */
+
+#define VDSF_AUTOCOPY 0x02 /* Automatic copy to/from buffer */
+#define VDSF_NOALLOC 0x04 /* Disable auto buffer allocation */
+#define VDSF_NOREMAP 0x08 /* Disable auto remap feature */
+#define VDSF_NO64K 0x10 /* Region can't cross 64K boundary */
+#define VDSF_NO128K 0x20 /* Region can't cross 128K boundary */
+#define VDSF_COPYTBL 0x40 /* Copy page table for S/G remap */
+#define VDSF_NPOK 0x80 /* Allow non-present pages for S/G */
+
+/* Higher level routines for utilizing VDS. */
+
+int vds_build_sg_list( vds_edds __far *edds, void __far *buf, uint32_t len );
+int vds_free_sg_list( vds_edds __far *edds );
+
+/* Helper for translating 16:16 real mode addresses to 32-bit linear. */
+
+uint32_t vds_real_to_lin( void __far *ptr );
+
+#endif /* !VBOX_INCLUDED_SRC_PC_BIOS_vds_h */
+
diff --git a/src/VBox/Devices/PC/DevACPI.cpp b/src/VBox/Devices/PC/DevACPI.cpp
new file mode 100644
index 00000000..19235d53
--- /dev/null
+++ b/src/VBox/Devices/PC/DevACPI.cpp
@@ -0,0 +1,4236 @@
+/* $Id: DevACPI.cpp $ */
+/** @file
+ * DevACPI - Advanced Configuration and Power Interface (ACPI) Device.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_ACPI
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/vmm/pgm.h>
+#include <VBox/vmm/dbgftrace.h>
+#include <VBox/vmm/vmcpuset.h>
+#include <VBox/log.h>
+#include <VBox/param.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+#include <iprt/asm-math.h>
+#include <iprt/file.h>
+#ifdef IN_RING3
+# include <iprt/alloc.h>
+# include <iprt/string.h>
+# include <iprt/uuid.h>
+#endif /* IN_RING3 */
+
+#include "VBoxDD.h"
+
+#ifdef LOG_ENABLED
+# define DEBUG_ACPI
+#endif
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+#ifdef IN_RING3
+/** Locks the device state, ring-3 only. */
+# define DEVACPI_LOCK_R3(a_pThis) \
+ do { \
+ int rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, VERR_IGNORED); \
+ AssertRC(rcLock); \
+ } while (0)
+#endif
+/** Unlocks the device state (all contexts). */
+#define DEVACPI_UNLOCK(a_pThis) \
+ do { PDMCritSectLeave(&(a_pThis)->CritSect); } while (0)
+
+
+#define DEBUG_HEX 0x3000
+#define DEBUG_CHR 0x3001
+
+/** PM Base Address PCI config space offset */
+#define PMBA 0x40
+/** PM Miscellaneous Power Management PCI config space offset */
+#define PMREGMISC 0x80
+
+#define PM_TMR_FREQ 3579545
+/** Default base for PM PIIX4 device */
+#define PM_PORT_BASE 0x4000
+/* Port offsets in PM device */
+enum
+{
+ PM1a_EVT_OFFSET = 0x00,
+ PM1b_EVT_OFFSET = -1, /**< not supported */
+ PM1a_CTL_OFFSET = 0x04,
+ PM1b_CTL_OFFSET = -1, /**< not supported */
+ PM2_CTL_OFFSET = -1, /**< not supported */
+ PM_TMR_OFFSET = 0x08,
+ GPE0_OFFSET = 0x20,
+ GPE1_OFFSET = -1 /**< not supported */
+};
+
+/* Maximum supported number of custom ACPI tables */
+#define MAX_CUST_TABLES 4
+
+/* Undef this to enable 24 bit PM timer (mostly for debugging purposes) */
+#define PM_TMR_32BIT
+
+#define BAT_INDEX 0x00004040
+#define BAT_DATA 0x00004044
+#define SYSI_INDEX 0x00004048
+#define SYSI_DATA 0x0000404c
+#define ACPI_RESET_BLK 0x00004050
+
+/* PM1x status register bits */
+#define TMR_STS RT_BIT(0)
+#define RSR1_STS (RT_BIT(1) | RT_BIT(2) | RT_BIT(3))
+#define BM_STS RT_BIT(4)
+#define GBL_STS RT_BIT(5)
+#define RSR2_STS (RT_BIT(6) | RT_BIT(7))
+#define PWRBTN_STS RT_BIT(8)
+#define SLPBTN_STS RT_BIT(9)
+#define RTC_STS RT_BIT(10)
+#define IGN_STS RT_BIT(11)
+#define RSR3_STS (RT_BIT(12) | RT_BIT(13) | RT_BIT(14))
+#define WAK_STS RT_BIT(15)
+#define RSR_STS (RSR1_STS | RSR2_STS | RSR3_STS)
+
+/* PM1x enable register bits */
+#define TMR_EN RT_BIT(0)
+#define RSR1_EN (RT_BIT(1) | RT_BIT(2) | RT_BIT(3) | RT_BIT(4))
+#define GBL_EN RT_BIT(5)
+#define RSR2_EN (RT_BIT(6) | RT_BIT(7))
+#define PWRBTN_EN RT_BIT(8)
+#define SLPBTN_EN RT_BIT(9)
+#define RTC_EN RT_BIT(10)
+#define RSR3_EN (RT_BIT(11) | RT_BIT(12) | RT_BIT(13) | RT_BIT(14) | RT_BIT(15))
+#define RSR_EN (RSR1_EN | RSR2_EN | RSR3_EN)
+#define IGN_EN 0
+
+/* PM1x control register bits */
+#define SCI_EN RT_BIT(0)
+#define BM_RLD RT_BIT(1)
+#define GBL_RLS RT_BIT(2)
+#define RSR1_CNT (RT_BIT(3) | RT_BIT(4) | RT_BIT(5) | RT_BIT(6) | RT_BIT(7) | RT_BIT(8))
+#define IGN_CNT RT_BIT(9)
+#define SLP_TYPx_SHIFT 10
+#define SLP_TYPx_MASK 7
+#define SLP_EN RT_BIT(13)
+#define RSR2_CNT (RT_BIT(14) | RT_BIT(15))
+#define RSR_CNT (RSR1_CNT | RSR2_CNT)
+
+#define GPE0_BATTERY_INFO_CHANGED RT_BIT(0)
+
+enum
+{
+ BAT_STATUS_STATE = 0x00, /**< BST battery state */
+ BAT_STATUS_PRESENT_RATE = 0x01, /**< BST battery present rate */
+ BAT_STATUS_REMAINING_CAPACITY = 0x02, /**< BST battery remaining capacity */
+ BAT_STATUS_PRESENT_VOLTAGE = 0x03, /**< BST battery present voltage */
+ BAT_INFO_UNITS = 0x04, /**< BIF power unit */
+ BAT_INFO_DESIGN_CAPACITY = 0x05, /**< BIF design capacity */
+ BAT_INFO_LAST_FULL_CHARGE_CAPACITY = 0x06, /**< BIF last full charge capacity */
+ BAT_INFO_TECHNOLOGY = 0x07, /**< BIF battery technology */
+ BAT_INFO_DESIGN_VOLTAGE = 0x08, /**< BIF design voltage */
+ BAT_INFO_DESIGN_CAPACITY_OF_WARNING = 0x09, /**< BIF design capacity of warning */
+ BAT_INFO_DESIGN_CAPACITY_OF_LOW = 0x0A, /**< BIF design capacity of low */
+ BAT_INFO_CAPACITY_GRANULARITY_1 = 0x0B, /**< BIF battery capacity granularity 1 */
+ BAT_INFO_CAPACITY_GRANULARITY_2 = 0x0C, /**< BIF battery capacity granularity 2 */
+ BAT_DEVICE_STATUS = 0x0D, /**< STA device status */
+ BAT_POWER_SOURCE = 0x0E, /**< PSR power source */
+ BAT_INDEX_LAST
+};
+
+enum
+{
+ CPU_EVENT_TYPE_ADD = 0x01, /**< Event type add */
+ CPU_EVENT_TYPE_REMOVE = 0x03 /**< Event type remove */
+};
+
+enum
+{
+ SYSTEM_INFO_INDEX_LOW_MEMORY_LENGTH = 0,
+ SYSTEM_INFO_INDEX_USE_IOAPIC = 1,
+ SYSTEM_INFO_INDEX_HPET_STATUS = 2,
+ SYSTEM_INFO_INDEX_SMC_STATUS = 3,
+ SYSTEM_INFO_INDEX_FDC_STATUS = 4,
+ SYSTEM_INFO_INDEX_SERIAL2_IOBASE = 5,
+ SYSTEM_INFO_INDEX_SERIAL2_IRQ = 6,
+ SYSTEM_INFO_INDEX_SERIAL3_IOBASE = 7,
+ SYSTEM_INFO_INDEX_SERIAL3_IRQ = 8,
+ SYSTEM_INFO_INDEX_PREF64_MEMORY_MIN = 9,
+ SYSTEM_INFO_INDEX_RTC_STATUS = 10,
+ SYSTEM_INFO_INDEX_CPU_LOCKED = 11, /**< Contains a flag indicating whether the CPU is locked or not */
+ SYSTEM_INFO_INDEX_CPU_LOCK_CHECK = 12, /**< For which CPU the lock status should be checked */
+ SYSTEM_INFO_INDEX_CPU_EVENT_TYPE = 13, /**< Type of the CPU hot-plug event */
+ SYSTEM_INFO_INDEX_CPU_EVENT = 14, /**< The CPU id the event is for */
+ SYSTEM_INFO_INDEX_NIC_ADDRESS = 15, /**< NIC PCI address, or 0 */
+ SYSTEM_INFO_INDEX_AUDIO_ADDRESS = 16, /**< Audio card PCI address, or 0 */
+ SYSTEM_INFO_INDEX_POWER_STATES = 17,
+ SYSTEM_INFO_INDEX_IOC_ADDRESS = 18, /**< IO controller PCI address */
+ SYSTEM_INFO_INDEX_HBC_ADDRESS = 19, /**< host bus controller PCI address */
+ SYSTEM_INFO_INDEX_PCI_BASE = 20, /**< PCI bus MCFG MMIO range base */
+ SYSTEM_INFO_INDEX_PCI_LENGTH = 21, /**< PCI bus MCFG MMIO range length */
+ SYSTEM_INFO_INDEX_SERIAL0_IOBASE = 22,
+ SYSTEM_INFO_INDEX_SERIAL0_IRQ = 23,
+ SYSTEM_INFO_INDEX_SERIAL1_IOBASE = 24,
+ SYSTEM_INFO_INDEX_SERIAL1_IRQ = 25,
+ SYSTEM_INFO_INDEX_PARALLEL0_IOBASE = 26,
+ SYSTEM_INFO_INDEX_PARALLEL0_IRQ = 27,
+ SYSTEM_INFO_INDEX_PARALLEL1_IOBASE = 28,
+ SYSTEM_INFO_INDEX_PARALLEL1_IRQ = 29,
+ SYSTEM_INFO_INDEX_PREF64_MEMORY_MAX = 30,
+ SYSTEM_INFO_INDEX_END = 31,
+ SYSTEM_INFO_INDEX_INVALID = 0x80,
+ SYSTEM_INFO_INDEX_VALID = 0x200
+};
+
+#define AC_OFFLINE 0
+#define AC_ONLINE 1
+
+#define BAT_TECH_PRIMARY 1
+#define BAT_TECH_SECONDARY 2
+
+#define STA_DEVICE_PRESENT_MASK RT_BIT(0) /**< present */
+#define STA_DEVICE_ENABLED_MASK RT_BIT(1) /**< enabled and decodes its resources */
+#define STA_DEVICE_SHOW_IN_UI_MASK RT_BIT(2) /**< should be shown in UI */
+#define STA_DEVICE_FUNCTIONING_PROPERLY_MASK RT_BIT(3) /**< functioning properly */
+#define STA_BATTERY_PRESENT_MASK RT_BIT(4) /**< the battery is present */
+
+/** SMBus Base Address PCI config space offset */
+#define SMBBA 0x90
+/** SMBus Host Configuration PCI config space offset */
+#define SMBHSTCFG 0xd2
+/** SMBus Slave Command PCI config space offset */
+#define SMBSLVC 0xd3
+/** SMBus Slave Shadow Port 1 PCI config space offset */
+#define SMBSHDW1 0xd4
+/** SMBus Slave Shadow Port 2 PCI config space offset */
+#define SMBSHDW2 0xd5
+/** SMBus Revision Identification PCI config space offset */
+#define SMBREV 0xd6
+
+#define SMBHSTCFG_SMB_HST_EN RT_BIT(0)
+#define SMBHSTCFG_INTRSEL (RT_BIT(1) | RT_BIT(2) | RT_BIT(3))
+#define SMBHSTCFG_INTRSEL_SMI 0
+#define SMBHSTCFG_INTRSEL_IRQ9 4
+#define SMBHSTCFG_INTRSEL_SHIFT 1
+
+/** Default base for SMBus PIIX4 device */
+#define SMB_PORT_BASE 0x4100
+
+/** SMBus Host Status Register I/O offset */
+#define SMBHSTSTS_OFF 0x0000
+/** SMBus Slave Status Register I/O offset */
+#define SMBSLVSTS_OFF 0x0001
+/** SMBus Host Count Register I/O offset */
+#define SMBHSTCNT_OFF 0x0002
+/** SMBus Host Command Register I/O offset */
+#define SMBHSTCMD_OFF 0x0003
+/** SMBus Host Address Register I/O offset */
+#define SMBHSTADD_OFF 0x0004
+/** SMBus Host Data 0 Register I/O offset */
+#define SMBHSTDAT0_OFF 0x0005
+/** SMBus Host Data 1 Register I/O offset */
+#define SMBHSTDAT1_OFF 0x0006
+/** SMBus Block Data Register I/O offset */
+#define SMBBLKDAT_OFF 0x0007
+/** SMBus Slave Control Register I/O offset */
+#define SMBSLVCNT_OFF 0x0008
+/** SMBus Shadow Command Register I/O offset */
+#define SMBSHDWCMD_OFF 0x0009
+/** SMBus Slave Event Register I/O offset */
+#define SMBSLVEVT_OFF 0x000a
+/** SMBus Slave Data Register I/O offset */
+#define SMBSLVDAT_OFF 0x000c
+
+#define SMBHSTSTS_HOST_BUSY RT_BIT(0)
+#define SMBHSTSTS_INTER RT_BIT(1)
+#define SMBHSTSTS_DEV_ERR RT_BIT(2)
+#define SMBHSTSTS_BUS_ERR RT_BIT(3)
+#define SMBHSTSTS_FAILED RT_BIT(4)
+#define SMBHSTSTS_INT_MASK (SMBHSTSTS_INTER | SMBHSTSTS_DEV_ERR | SMBHSTSTS_BUS_ERR | SMBHSTSTS_FAILED)
+
+#define SMBSLVSTS_WRITE_MASK 0x3c
+
+#define SMBHSTCNT_INTEREN RT_BIT(0)
+#define SMBHSTCNT_KILL RT_BIT(1)
+#define SMBHSTCNT_CMD_PROT (RT_BIT(2) | RT_BIT(3) | RT_BIT(4))
+#define SMBHSTCNT_START RT_BIT(6)
+#define SMBHSTCNT_WRITE_MASK (SMBHSTCNT_INTEREN | SMBHSTCNT_KILL | SMBHSTCNT_CMD_PROT)
+
+#define SMBSLVCNT_WRITE_MASK (RT_BIT(0) | RT_BIT(1) | RT_BIT(2) | RT_BIT(3))
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * The ACPI device state.
+ */
+typedef struct ACPIState
+{
+ PDMPCIDEV dev;
+ /** Critical section protecting the ACPI state. */
+ PDMCRITSECT CritSect;
+
+ uint16_t pm1a_en;
+ uint16_t pm1a_sts;
+ uint16_t pm1a_ctl;
+ /** Number of logical CPUs in guest */
+ uint16_t cCpus;
+ uint64_t u64PmTimerInitial;
+ PTMTIMERR3 pPmTimerR3;
+ PTMTIMERR0 pPmTimerR0;
+ PTMTIMERRC pPmTimerRC;
+
+ /* PM Timer last calculated value */
+ uint32_t uPmTimerVal;
+ uint32_t Alignment0;
+
+ uint32_t gpe0_en;
+ uint32_t gpe0_sts;
+
+ uint32_t uBatteryIndex;
+ uint32_t au8BatteryInfo[13];
+
+ uint32_t uSystemInfoIndex;
+ uint64_t u64RamSize;
+ /** Offset of the 64-bit prefetchable memory window. */
+ uint64_t u64PciPref64Min;
+ /** Limit of the 64-bit prefetchable memory window. */
+ uint64_t u64PciPref64Max;
+ /** The number of bytes below 4GB. */
+ uint32_t cbRamLow;
+
+ /** Current ACPI S* state. We support S0 and S5. */
+ uint32_t uSleepState;
+ uint8_t au8RSDPPage[0x1000];
+ /** This is a workaround for incorrect index field handling by Intels ACPICA.
+ * The system info _INI method writes to offset 0x200. We either observe a
+ * write request to index 0x80 (in that case we don't change the index) or a
+ * write request to offset 0x200 (in that case we divide the index value by
+ * 4. Note that the _STA method is sometimes called prior to the _INI method
+ * (ACPI spec 6.3.7, _STA). See the special case for BAT_DEVICE_STATUS in
+ * acpiR3BatIndexWrite() for handling this. */
+ uint8_t u8IndexShift;
+ /** provide an I/O-APIC */
+ uint8_t u8UseIOApic;
+ /** provide a floppy controller */
+ bool fUseFdc;
+ /** If High Precision Event Timer device should be supported */
+ bool fUseHpet;
+ /** If System Management Controller device should be supported */
+ bool fUseSmc;
+ /** the guest handled the last power button event */
+ bool fPowerButtonHandled;
+ /** If ACPI CPU device should be shown */
+ bool fShowCpu;
+ /** If Real Time Clock ACPI object to be shown */
+ bool fShowRtc;
+ /** I/O port address of PM device. */
+ RTIOPORT uPmIoPortBase;
+ /** I/O port address of SMBus device. */
+ RTIOPORT uSMBusIoPortBase;
+ /** Flag whether the GC part of the device is enabled. */
+ bool fGCEnabled;
+ /** Flag whether the R0 part of the device is enabled. */
+ bool fR0Enabled;
+ /** Array of flags of attached CPUs */
+ VMCPUSET CpuSetAttached;
+ /** Which CPU to check for the locked status. */
+ uint32_t idCpuLockCheck;
+ /** Mask of locked CPUs (used by the guest). */
+ VMCPUSET CpuSetLocked;
+ /** The CPU event type. */
+ uint32_t u32CpuEventType;
+ /** The CPU id affected. */
+ uint32_t u32CpuEvent;
+ /** Flag whether CPU hot plugging is enabled. */
+ bool fCpuHotPlug;
+ /** If MCFG ACPI table shown to the guest */
+ bool fUseMcfg;
+ /** if the 64-bit prefetchable memory window is shown to the guest */
+ bool fPciPref64Enabled;
+ /** Primary NIC PCI address. */
+ uint32_t u32NicPciAddress;
+ /** Primary audio card PCI address. */
+ uint32_t u32AudioPciAddress;
+ /** Flag whether S1 power state is enabled. */
+ bool fS1Enabled;
+ /** Flag whether S4 power state is enabled. */
+ bool fS4Enabled;
+ /** Flag whether S1 triggers a state save. */
+ bool fSuspendToSavedState;
+ /** Flag whether to set WAK_STS on resume (restore included). */
+ bool fSetWakeupOnResume;
+ /** PCI address of the IO controller device. */
+ uint32_t u32IocPciAddress;
+ /** PCI address of the host bus controller device. */
+ uint32_t u32HbcPciAddress;
+
+ uint32_t Alignment1;
+
+ /** Physical address of PCI config space MMIO region */
+ uint64_t u64PciConfigMMioAddress;
+ /** Length of PCI config space MMIO region */
+ uint64_t u64PciConfigMMioLength;
+ /** Serial 0 IRQ number */
+ uint8_t uSerial0Irq;
+ /** Serial 1 IRQ number */
+ uint8_t uSerial1Irq;
+ /** Serial 2 IRQ number */
+ uint8_t uSerial2Irq;
+ /** Serial 3 IRQ number */
+ uint8_t uSerial3Irq;
+ /** Serial 0 IO port base */
+ RTIOPORT uSerial0IoPortBase;
+ /** Serial 1 IO port base */
+ RTIOPORT uSerial1IoPortBase;
+ /** Serial 2 IO port base */
+ RTIOPORT uSerial2IoPortBase;
+ /** Serial 3 IO port base */
+ RTIOPORT uSerial3IoPortBase;
+
+ /** @name Parallel port config bits
+ * @{ */
+ /** Parallel 0 IRQ number */
+ uint8_t uParallel0Irq;
+ /** Parallel 1 IRQ number */
+ uint8_t uParallel1Irq;
+ /** Parallel 0 IO port base */
+ RTIOPORT uParallel0IoPortBase;
+ /** Parallel 1 IO port base */
+ RTIOPORT uParallel1IoPortBase;
+ /** @} */
+
+ uint32_t Alignment2;
+
+ /** ACPI port base interface. */
+ PDMIBASE IBase;
+ /** ACPI port interface. */
+ PDMIACPIPORT IACPIPort;
+ /** Pointer to the device instance. */
+ PPDMDEVINSR3 pDevInsR3;
+ PPDMDEVINSR0 pDevInsR0;
+ PPDMDEVINSRC pDevInsRC;
+
+ uint32_t Alignment3;
+ /** Pointer to the driver base interface. */
+ R3PTRTYPE(PPDMIBASE) pDrvBase;
+ /** Pointer to the driver connector interface. */
+ R3PTRTYPE(PPDMIACPICONNECTOR) pDrv;
+
+ /** Pointer to default PCI config read function. */
+ R3PTRTYPE(PFNPCICONFIGREAD) pfnAcpiPciConfigRead;
+ /** Pointer to default PCI config write function. */
+ R3PTRTYPE(PFNPCICONFIGWRITE) pfnAcpiPciConfigWrite;
+
+ /** Number of custom ACPI tables */
+ uint8_t cCustTbls;
+ /** ACPI OEM ID */
+ uint8_t au8OemId[6];
+ /** ACPI Crator ID */
+ uint8_t au8CreatorId[4];
+ /** ACPI Crator Rev */
+ uint32_t u32CreatorRev;
+ /** ACPI custom OEM Tab ID */
+ uint8_t au8OemTabId[8];
+ /** ACPI custom OEM Rev */
+ uint32_t u32OemRevision;
+ uint32_t Alignment4;
+
+ /** Custom ACPI tables binary data. */
+ R3PTRTYPE(uint8_t *) apu8CustBin[MAX_CUST_TABLES];
+ /** The size of the custom table binary. */
+ uint64_t acbCustBin[MAX_CUST_TABLES];
+
+ /** SMBus Host Status Register */
+ uint8_t u8SMBusHstSts;
+ /** SMBus Slave Status Register */
+ uint8_t u8SMBusSlvSts;
+ /** SMBus Host Control Register */
+ uint8_t u8SMBusHstCnt;
+ /** SMBus Host Command Register */
+ uint8_t u8SMBusHstCmd;
+ /** SMBus Host Address Register */
+ uint8_t u8SMBusHstAdd;
+ /** SMBus Host Data 0 Register */
+ uint8_t u8SMBusHstDat0;
+ /** SMBus Host Data 1 Register */
+ uint8_t u8SMBusHstDat1;
+ /** SMBus Slave Control Register */
+ uint8_t u8SMBusSlvCnt;
+ /** SMBus Shadow Command Register */
+ uint8_t u8SMBusShdwCmd;
+ /** SMBus Slave Event Register */
+ uint16_t u16SMBusSlvEvt;
+ /** SMBus Slave Data Register */
+ uint16_t u16SMBusSlvDat;
+ /** SMBus Host Block Data Buffer */
+ uint8_t au8SMBusBlkDat[32];
+ /** SMBus Host Block Index */
+ uint8_t u8SMBusBlkIdx;
+
+ /** @todo DEBUGGING */
+ uint32_t uPmTimeOld;
+ uint32_t uPmTimeA;
+ uint32_t uPmTimeB;
+ uint32_t Alignment5;
+} ACPIState;
+
+#pragma pack(1)
+
+/** Generic Address Structure (see ACPIspec 3.0, 5.2.3.1) */
+struct ACPIGENADDR
+{
+ uint8_t u8AddressSpaceId; /**< 0=sys, 1=IO, 2=PCICfg, 3=emb, 4=SMBus */
+ uint8_t u8RegisterBitWidth; /**< size in bits of the given register */
+ uint8_t u8RegisterBitOffset; /**< bit offset of register */
+ uint8_t u8AccessSize; /**< 1=byte, 2=word, 3=dword, 4=qword */
+ uint64_t u64Address; /**< 64-bit address of register */
+};
+AssertCompileSize(ACPIGENADDR, 12);
+
+/** Root System Description Pointer */
+struct ACPITBLRSDP
+{
+ uint8_t au8Signature[8]; /**< 'RSD PTR ' */
+ uint8_t u8Checksum; /**< checksum for the first 20 bytes */
+ uint8_t au8OemId[6]; /**< OEM-supplied identifier */
+ uint8_t u8Revision; /**< revision number, currently 2 */
+#define ACPI_REVISION 2 /**< ACPI 3.0 */
+ uint32_t u32RSDT; /**< phys addr of RSDT */
+ uint32_t u32Length; /**< bytes of this table */
+ uint64_t u64XSDT; /**< 64-bit phys addr of XSDT */
+ uint8_t u8ExtChecksum; /**< checksum of entire table */
+ uint8_t u8Reserved[3]; /**< reserved */
+};
+AssertCompileSize(ACPITBLRSDP, 36);
+
+/** System Description Table Header */
+struct ACPITBLHEADER
+{
+ uint8_t au8Signature[4]; /**< table identifier */
+ uint32_t u32Length; /**< length of the table including header */
+ uint8_t u8Revision; /**< revision number */
+ uint8_t u8Checksum; /**< all fields inclusive this add to zero */
+ uint8_t au8OemId[6]; /**< OEM-supplied string */
+ uint8_t au8OemTabId[8]; /**< to identify the particular data table */
+ uint32_t u32OemRevision; /**< OEM-supplied revision number */
+ uint8_t au8CreatorId[4]; /**< ID for the ASL compiler */
+ uint32_t u32CreatorRev; /**< revision for the ASL compiler */
+};
+AssertCompileSize(ACPITBLHEADER, 36);
+
+/** Root System Description Table */
+struct ACPITBLRSDT
+{
+ ACPITBLHEADER header;
+ uint32_t u32Entry[1]; /**< array of phys. addresses to other tables */
+};
+AssertCompileSize(ACPITBLRSDT, 40);
+
+/** Extended System Description Table */
+struct ACPITBLXSDT
+{
+ ACPITBLHEADER header;
+ uint64_t u64Entry[1]; /**< array of phys. addresses to other tables */
+};
+AssertCompileSize(ACPITBLXSDT, 44);
+
+/** Fixed ACPI Description Table */
+struct ACPITBLFADT
+{
+ ACPITBLHEADER header;
+ uint32_t u32FACS; /**< phys. address of FACS */
+ uint32_t u32DSDT; /**< phys. address of DSDT */
+ uint8_t u8IntModel; /**< was eleminated in ACPI 2.0 */
+#define INT_MODEL_DUAL_PIC 1 /**< for ACPI 2+ */
+#define INT_MODEL_MULTIPLE_APIC 2
+ uint8_t u8PreferredPMProfile; /**< preferred power management profile */
+ uint16_t u16SCIInt; /**< system vector the SCI is wired in 8259 mode */
+#define SCI_INT 9
+ uint32_t u32SMICmd; /**< system port address of SMI command port */
+#define SMI_CMD 0x0000442e
+ uint8_t u8AcpiEnable; /**< SMICmd val to disable ownership of ACPIregs */
+#define ACPI_ENABLE 0xa1
+ uint8_t u8AcpiDisable; /**< SMICmd val to re-enable ownership of ACPIregs */
+#define ACPI_DISABLE 0xa0
+ uint8_t u8S4BIOSReq; /**< SMICmd val to enter S4BIOS state */
+ uint8_t u8PStateCnt; /**< SMICmd val to assume processor performance
+ state control responsibility */
+ uint32_t u32PM1aEVTBLK; /**< port addr of PM1a event regs block */
+ uint32_t u32PM1bEVTBLK; /**< port addr of PM1b event regs block */
+ uint32_t u32PM1aCTLBLK; /**< port addr of PM1a control regs block */
+ uint32_t u32PM1bCTLBLK; /**< port addr of PM1b control regs block */
+ uint32_t u32PM2CTLBLK; /**< port addr of PM2 control regs block */
+ uint32_t u32PMTMRBLK; /**< port addr of PMTMR regs block */
+ uint32_t u32GPE0BLK; /**< port addr of gen-purp event 0 regs block */
+ uint32_t u32GPE1BLK; /**< port addr of gen-purp event 1 regs block */
+ uint8_t u8PM1EVTLEN; /**< bytes decoded by PM1a_EVT_BLK. >= 4 */
+ uint8_t u8PM1CTLLEN; /**< bytes decoded by PM1b_CNT_BLK. >= 2 */
+ uint8_t u8PM2CTLLEN; /**< bytes decoded by PM2_CNT_BLK. >= 1 or 0 */
+ uint8_t u8PMTMLEN; /**< bytes decoded by PM_TMR_BLK. ==4 */
+ uint8_t u8GPE0BLKLEN; /**< bytes decoded by GPE0_BLK. %2==0 */
+#define GPE0_BLK_LEN 2
+ uint8_t u8GPE1BLKLEN; /**< bytes decoded by GPE1_BLK. %2==0 */
+#define GPE1_BLK_LEN 0
+ uint8_t u8GPE1BASE; /**< offset of GPE1 based events */
+#define GPE1_BASE 0
+ uint8_t u8CSTCNT; /**< SMICmd val to indicate OS supp for C states */
+ uint16_t u16PLVL2LAT; /**< us to enter/exit C2. >100 => unsupported */
+#define P_LVL2_LAT 101 /**< C2 state not supported */
+ uint16_t u16PLVL3LAT; /**< us to enter/exit C3. >1000 => unsupported */
+#define P_LVL3_LAT 1001 /**< C3 state not supported */
+ uint16_t u16FlushSize; /**< # of flush strides to read to flush dirty
+ lines from any processors memory caches */
+#define FLUSH_SIZE 0 /**< Ignored if WBVIND set in FADT_FLAGS */
+ uint16_t u16FlushStride; /**< cache line width */
+#define FLUSH_STRIDE 0 /**< Ignored if WBVIND set in FADT_FLAGS */
+ uint8_t u8DutyOffset;
+ uint8_t u8DutyWidth;
+ uint8_t u8DayAlarm; /**< RTC CMOS RAM index of day-of-month alarm */
+ uint8_t u8MonAlarm; /**< RTC CMOS RAM index of month-of-year alarm */
+ uint8_t u8Century; /**< RTC CMOS RAM index of century */
+ uint16_t u16IAPCBOOTARCH; /**< IA-PC boot architecture flags */
+#define IAPC_BOOT_ARCH_LEGACY_DEV RT_BIT(0) /**< legacy devices present such as LPT
+ (COM too?) */
+#define IAPC_BOOT_ARCH_8042 RT_BIT(1) /**< legacy keyboard device present */
+#define IAPC_BOOT_ARCH_NO_VGA RT_BIT(2) /**< VGA not present */
+#define IAPC_BOOT_ARCH_NO_MSI RT_BIT(3) /**< OSPM must not enable MSIs on this platform */
+#define IAPC_BOOT_ARCH_NO_ASPM RT_BIT(4) /**< OSPM must not enable ASPM on this platform */
+ uint8_t u8Must0_0; /**< must be 0 */
+ uint32_t u32Flags; /**< fixed feature flags */
+#define FADT_FL_WBINVD RT_BIT(0) /**< emulation of WBINVD available */
+#define FADT_FL_WBINVD_FLUSH RT_BIT(1)
+#define FADT_FL_PROC_C1 RT_BIT(2) /**< 1=C1 supported on all processors */
+#define FADT_FL_P_LVL2_UP RT_BIT(3) /**< 1=C2 works on SMP and UNI systems */
+#define FADT_FL_PWR_BUTTON RT_BIT(4) /**< 1=power button handled as ctrl method dev */
+#define FADT_FL_SLP_BUTTON RT_BIT(5) /**< 1=sleep button handled as ctrl method dev */
+#define FADT_FL_FIX_RTC RT_BIT(6) /**< 0=RTC wake status in fixed register */
+#define FADT_FL_RTC_S4 RT_BIT(7) /**< 1=RTC can wake system from S4 */
+#define FADT_FL_TMR_VAL_EXT RT_BIT(8) /**< 1=TMR_VAL implemented as 32 bit */
+#define FADT_FL_DCK_CAP RT_BIT(9) /**< 0=system cannot support docking */
+#define FADT_FL_RESET_REG_SUP RT_BIT(10) /**< 1=system supports system resets */
+#define FADT_FL_SEALED_CASE RT_BIT(11) /**< 1=case is sealed */
+#define FADT_FL_HEADLESS RT_BIT(12) /**< 1=system cannot detect moni/keyb/mouse */
+#define FADT_FL_CPU_SW_SLP RT_BIT(13)
+#define FADT_FL_PCI_EXT_WAK RT_BIT(14) /**< 1=system supports PCIEXP_WAKE_STS */
+#define FADT_FL_USE_PLATFORM_CLOCK RT_BIT(15) /**< 1=system has ACPI PM timer */
+#define FADT_FL_S4_RTC_STS_VALID RT_BIT(16) /**< 1=RTC_STS flag is valid when waking from S4 */
+#define FADT_FL_REMOVE_POWER_ON_CAPABLE RT_BIT(17) /**< 1=platform can remote power on */
+#define FADT_FL_FORCE_APIC_CLUSTER_MODEL RT_BIT(18)
+#define FADT_FL_FORCE_APIC_PHYS_DEST_MODE RT_BIT(19)
+
+/* PM Timer mask and msb */
+#ifndef PM_TMR_32BIT
+#define TMR_VAL_MSB 0x800000
+#define TMR_VAL_MASK 0xffffff
+#undef FADT_FL_TMR_VAL_EXT
+#define FADT_FL_TMR_VAL_EXT 0
+#else
+#define TMR_VAL_MSB 0x80000000
+#define TMR_VAL_MASK 0xffffffff
+#endif
+
+ /** Start of the ACPI 2.0 extension. */
+ ACPIGENADDR ResetReg; /**< ext addr of reset register */
+ uint8_t u8ResetVal; /**< ResetReg value to reset the system */
+#define ACPI_RESET_REG_VAL 0x10
+ uint8_t au8Must0_1[3]; /**< must be 0 */
+ uint64_t u64XFACS; /**< 64-bit phys address of FACS */
+ uint64_t u64XDSDT; /**< 64-bit phys address of DSDT */
+ ACPIGENADDR X_PM1aEVTBLK; /**< ext addr of PM1a event regs block */
+ ACPIGENADDR X_PM1bEVTBLK; /**< ext addr of PM1b event regs block */
+ ACPIGENADDR X_PM1aCTLBLK; /**< ext addr of PM1a control regs block */
+ ACPIGENADDR X_PM1bCTLBLK; /**< ext addr of PM1b control regs block */
+ ACPIGENADDR X_PM2CTLBLK; /**< ext addr of PM2 control regs block */
+ ACPIGENADDR X_PMTMRBLK; /**< ext addr of PMTMR control regs block */
+ ACPIGENADDR X_GPE0BLK; /**< ext addr of GPE1 regs block */
+ ACPIGENADDR X_GPE1BLK; /**< ext addr of GPE1 regs block */
+};
+AssertCompileSize(ACPITBLFADT, 244);
+#define ACPITBLFADT_VERSION1_SIZE RT_OFFSETOF(ACPITBLFADT, ResetReg)
+
+/** Firmware ACPI Control Structure */
+struct ACPITBLFACS
+{
+ uint8_t au8Signature[4]; /**< 'FACS' */
+ uint32_t u32Length; /**< bytes of entire FACS structure >= 64 */
+ uint32_t u32HWSignature; /**< systems HW signature at last boot */
+ uint32_t u32FWVector; /**< address of waking vector */
+ uint32_t u32GlobalLock; /**< global lock to sync HW/SW */
+ uint32_t u32Flags; /**< FACS flags */
+ uint64_t u64X_FWVector; /**< 64-bit waking vector */
+ uint8_t u8Version; /**< version of this table */
+ uint8_t au8Reserved[31]; /**< zero */
+};
+AssertCompileSize(ACPITBLFACS, 64);
+
+/** Processor Local APIC Structure */
+struct ACPITBLLAPIC
+{
+ uint8_t u8Type; /**< 0 = LAPIC */
+ uint8_t u8Length; /**< 8 */
+ uint8_t u8ProcId; /**< processor ID */
+ uint8_t u8ApicId; /**< local APIC ID */
+ uint32_t u32Flags; /**< Flags */
+#define LAPIC_ENABLED 0x1
+};
+AssertCompileSize(ACPITBLLAPIC, 8);
+
+/** I/O APIC Structure */
+struct ACPITBLIOAPIC
+{
+ uint8_t u8Type; /**< 1 == I/O APIC */
+ uint8_t u8Length; /**< 12 */
+ uint8_t u8IOApicId; /**< I/O APIC ID */
+ uint8_t u8Reserved; /**< 0 */
+ uint32_t u32Address; /**< phys address to access I/O APIC */
+ uint32_t u32GSIB; /**< global system interrupt number to start */
+};
+AssertCompileSize(ACPITBLIOAPIC, 12);
+
+/** Interrupt Source Override Structure */
+struct ACPITBLISO
+{
+ uint8_t u8Type; /**< 2 == Interrupt Source Override*/
+ uint8_t u8Length; /**< 10 */
+ uint8_t u8Bus; /**< Bus */
+ uint8_t u8Source; /**< Bus-relative interrupt source (IRQ) */
+ uint32_t u32GSI; /**< Global System Interrupt */
+ uint16_t u16Flags; /**< MPS INTI flags Global */
+};
+AssertCompileSize(ACPITBLISO, 10);
+#define NUMBER_OF_IRQ_SOURCE_OVERRIDES 2
+
+/** HPET Descriptor Structure */
+struct ACPITBLHPET
+{
+ ACPITBLHEADER aHeader;
+ uint32_t u32Id; /**< hardware ID of event timer block
+ [31:16] PCI vendor ID of first timer block
+ [15] legacy replacement IRQ routing capable
+ [14] reserved
+ [13] COUNT_SIZE_CAP counter size
+ [12:8] number of comparators in first timer block
+ [7:0] hardware rev ID */
+ ACPIGENADDR HpetAddr; /**< lower 32-bit base address */
+ uint8_t u32Number; /**< sequence number starting at 0 */
+ uint16_t u32MinTick; /**< minimum clock ticks which can be set without
+ lost interrupts while the counter is programmed
+ to operate in periodic mode. Unit: clock tick. */
+ uint8_t u8Attributes; /**< page protection and OEM attribute. */
+};
+AssertCompileSize(ACPITBLHPET, 56);
+
+/** MCFG Descriptor Structure */
+typedef struct ACPITBLMCFG
+{
+ ACPITBLHEADER aHeader;
+ uint64_t u64Reserved;
+} ACPITBLMCFG;
+AssertCompileSize(ACPITBLMCFG, 44);
+
+/** Number of such entries can be computed from the whole table length in header */
+typedef struct ACPITBLMCFGENTRY
+{
+ uint64_t u64BaseAddress;
+ uint16_t u16PciSegmentGroup;
+ uint8_t u8StartBus;
+ uint8_t u8EndBus;
+ uint32_t u32Reserved;
+} ACPITBLMCFGENTRY;
+AssertCompileSize(ACPITBLMCFGENTRY, 16);
+
+#define PCAT_COMPAT 0x1 /**< system has also a dual-8259 setup */
+
+/** Custom Description Table */
+struct ACPITBLCUST
+{
+ ACPITBLHEADER header;
+ uint8_t au8Data[476];
+};
+AssertCompileSize(ACPITBLCUST, 512);
+
+
+#pragma pack()
+
+
+#ifndef VBOX_DEVICE_STRUCT_TESTCASE /* exclude the rest of the file */
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+RT_C_DECLS_BEGIN
+PDMBOTHCBDECL(int) acpiPMTmrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
+RT_C_DECLS_END
+#ifdef IN_RING3
+static int acpiR3PlantTables(ACPIState *pThis);
+#endif
+
+/* SCI, usually IRQ9 */
+DECLINLINE(void) acpiSetIrq(ACPIState *pThis, int level)
+{
+ PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, level);
+}
+
+DECLINLINE(bool) pm1a_level(ACPIState *pThis)
+{
+ return (pThis->pm1a_ctl & SCI_EN)
+ && (pThis->pm1a_en & pThis->pm1a_sts & ~(RSR_EN | IGN_EN));
+}
+
+DECLINLINE(bool) gpe0_level(ACPIState *pThis)
+{
+ return !!(pThis->gpe0_en & pThis->gpe0_sts);
+}
+
+DECLINLINE(bool) smbus_level(ACPIState *pThis)
+{
+ return (pThis->u8SMBusHstCnt & SMBHSTCNT_INTEREN)
+ && (pThis->dev.abConfig[SMBHSTCFG] & SMBHSTCFG_SMB_HST_EN)
+ && (pThis->dev.abConfig[SMBHSTCFG] & SMBHSTCFG_INTRSEL) == SMBHSTCFG_INTRSEL_IRQ9 << SMBHSTCFG_INTRSEL_SHIFT
+ && (pThis->u8SMBusHstSts & SMBHSTSTS_INT_MASK);
+}
+
+DECLINLINE(bool) acpiSCILevel(ACPIState *pThis)
+{
+ return pm1a_level(pThis) || gpe0_level(pThis) || smbus_level(pThis);
+}
+
+/**
+ * Used by acpiR3PM1aStsWrite, acpiR3PM1aEnWrite, acpiR3PmTimer,
+ * acpiR3Port_PowerBuffonPress, acpiR3Port_SleepButtonPress
+ * and acpiPmTmrRead to update the PM1a.STS and PM1a.EN
+ * registers and trigger IRQs.
+ *
+ * Caller must hold the state lock.
+ *
+ * @param pThis The ACPI instance.
+ * @param sts The new PM1a.STS value.
+ * @param en The new PM1a.EN value.
+ */
+static void apicUpdatePm1a(ACPIState *pThis, uint32_t sts, uint32_t en)
+{
+ Assert(PDMCritSectIsOwner(&pThis->CritSect));
+
+ const bool old_level = acpiSCILevel(pThis);
+ pThis->pm1a_en = en;
+ pThis->pm1a_sts = sts;
+ const bool new_level = acpiSCILevel(pThis);
+
+ LogFunc(("old=%x new=%x\n", old_level, new_level));
+
+ if (new_level != old_level)
+ acpiSetIrq(pThis, new_level);
+}
+
+#ifdef IN_RING3
+
+/**
+ * Used by acpiR3Gpe0StsWrite, acpiR3Gpe0EnWrite, acpiAttach and acpiDetach to
+ * update the GPE0.STS and GPE0.EN registers and trigger IRQs.
+ *
+ * Caller must hold the state lock.
+ *
+ * @param pThis The ACPI instance.
+ * @param sts The new GPE0.STS value.
+ * @param en The new GPE0.EN value.
+ */
+static void apicR3UpdateGpe0(ACPIState *pThis, uint32_t sts, uint32_t en)
+{
+ Assert(PDMCritSectIsOwner(&pThis->CritSect));
+
+ const bool old_level = acpiSCILevel(pThis);
+ pThis->gpe0_en = en;
+ pThis->gpe0_sts = sts;
+ const bool new_level = acpiSCILevel(pThis);
+
+ LogFunc(("old=%x new=%x\n", old_level, new_level));
+
+ if (new_level != old_level)
+ acpiSetIrq(pThis, new_level);
+}
+
+/**
+ * Used by acpiR3PM1aCtlWrite to power off the VM.
+ *
+ * @param pThis The ACPI instance.
+ * @returns Strict VBox status code.
+ */
+static int acpiR3DoPowerOff(ACPIState *pThis)
+{
+ int rc = PDMDevHlpVMPowerOff(pThis->pDevInsR3);
+ if (RT_FAILURE(rc))
+ AssertMsgFailed(("Could not power down the VM. rc = %Rrc\n", rc));
+ return rc;
+}
+
+/**
+ * Used by acpiR3PM1aCtlWrite to put the VM to sleep.
+ *
+ * @param pThis The ACPI instance.
+ * @returns Strict VBox status code.
+ */
+static int acpiR3DoSleep(ACPIState *pThis)
+{
+ /* We must set WAK_STS on resume (includes restore) so the guest knows that
+ we've woken up and can continue executing code. The guest is probably
+ reading the PMSTS register in a loop to check this. */
+ int rc;
+ pThis->fSetWakeupOnResume = true;
+ if (pThis->fSuspendToSavedState)
+ {
+ rc = PDMDevHlpVMSuspendSaveAndPowerOff(pThis->pDevInsR3);
+ if (rc != VERR_NOT_SUPPORTED)
+ AssertRC(rc);
+ else
+ {
+ LogRel(("ACPI: PDMDevHlpVMSuspendSaveAndPowerOff is not supported, falling back to suspend-only\n"));
+ rc = PDMDevHlpVMSuspend(pThis->pDevInsR3);
+ AssertRC(rc);
+ }
+ }
+ else
+ {
+ rc = PDMDevHlpVMSuspend(pThis->pDevInsR3);
+ AssertRC(rc);
+ }
+ return rc;
+}
+
+
+/**
+ * @interface_method_impl{PDMIACPIPORT,pfnPowerButtonPress}
+ */
+static DECLCALLBACK(int) acpiR3Port_PowerButtonPress(PPDMIACPIPORT pInterface)
+{
+ ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IACPIPort);
+ DEVACPI_LOCK_R3(pThis);
+
+ Log(("acpiR3Port_PowerButtonPress: handled=%d status=%x\n", pThis->fPowerButtonHandled, pThis->pm1a_sts));
+ pThis->fPowerButtonHandled = false;
+ apicUpdatePm1a(pThis, pThis->pm1a_sts | PWRBTN_STS, pThis->pm1a_en);
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * @interface_method_impl{PDMIACPIPORT,pfnGetPowerButtonHandled}
+ */
+static DECLCALLBACK(int) acpiR3Port_GetPowerButtonHandled(PPDMIACPIPORT pInterface, bool *pfHandled)
+{
+ ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IACPIPort);
+ DEVACPI_LOCK_R3(pThis);
+
+ *pfHandled = pThis->fPowerButtonHandled;
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * @interface_method_impl{PDMIACPIPORT,pfnGetGuestEnteredACPIMode, Check if the
+ * Guest entered into G0 (working) or G1 (sleeping)}
+ */
+static DECLCALLBACK(int) acpiR3Port_GetGuestEnteredACPIMode(PPDMIACPIPORT pInterface, bool *pfEntered)
+{
+ ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IACPIPort);
+ DEVACPI_LOCK_R3(pThis);
+
+ *pfEntered = (pThis->pm1a_ctl & SCI_EN) != 0;
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * @interface_method_impl{PDMIACPIPORT,pfnGetCpuStatus}
+ */
+static DECLCALLBACK(int) acpiR3Port_GetCpuStatus(PPDMIACPIPORT pInterface, unsigned uCpu, bool *pfLocked)
+{
+ ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IACPIPort);
+ DEVACPI_LOCK_R3(pThis);
+
+ *pfLocked = VMCPUSET_IS_PRESENT(&pThis->CpuSetLocked, uCpu);
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Send an ACPI sleep button event.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+static DECLCALLBACK(int) acpiR3Port_SleepButtonPress(PPDMIACPIPORT pInterface)
+{
+ ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IACPIPort);
+ DEVACPI_LOCK_R3(pThis);
+
+ apicUpdatePm1a(pThis, pThis->pm1a_sts | SLPBTN_STS, pThis->pm1a_en);
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Send an ACPI monitor hot-plug event.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the
+ * called function pointer.
+ */
+static DECLCALLBACK(int) acpiR3Port_MonitorHotPlugEvent(PPDMIACPIPORT pInterface)
+{
+ ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IACPIPort);
+ DEVACPI_LOCK_R3(pThis);
+
+ apicR3UpdateGpe0(pThis, pThis->gpe0_sts | 0x4, pThis->gpe0_en);
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Send an ACPI battery status change event.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the
+ * called function pointer.
+ */
+static DECLCALLBACK(int) acpiR3Port_BatteryStatusChangeEvent(PPDMIACPIPORT pInterface)
+{
+ ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IACPIPort);
+ DEVACPI_LOCK_R3(pThis);
+
+ apicR3UpdateGpe0(pThis, pThis->gpe0_sts | 0x1, pThis->gpe0_en);
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Used by acpiR3PmTimer to re-arm the PM timer.
+ *
+ * The caller is expected to either hold the clock lock or to have made sure
+ * the VM is resetting or loading state.
+ *
+ * @param pThis The ACPI instance.
+ * @param uNow The current time.
+ */
+static void acpiR3PmTimerReset(ACPIState *pThis, uint64_t uNow)
+{
+ uint64_t uTimerFreq = TMTimerGetFreq(pThis->CTX_SUFF(pPmTimer));
+ uint32_t uPmTmrCyclesToRollover = TMR_VAL_MSB - (pThis->uPmTimerVal & (TMR_VAL_MSB - 1));
+ uint64_t uInterval = ASMMultU64ByU32DivByU32(uPmTmrCyclesToRollover, uTimerFreq, PM_TMR_FREQ);
+ TMTimerSet(pThis->pPmTimerR3, uNow + uInterval + 1);
+ Log(("acpi: uInterval = %RU64\n", uInterval));
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * Used by acpiR3PMTimer & acpiPmTmrRead to update TMR_VAL and update TMR_STS
+ *
+ * The caller is expected to either hold the clock lock or to have made sure
+ * the VM is resetting or loading state.
+ *
+ * @param pThis The ACPI instance
+ * @param u64Now The current time
+ */
+
+static void acpiPmTimerUpdate(ACPIState *pThis, uint64_t u64Now)
+{
+ uint32_t msb = pThis->uPmTimerVal & TMR_VAL_MSB;
+ uint64_t u64Elapsed = u64Now - pThis->u64PmTimerInitial;
+ Assert(TMTimerIsLockOwner(pThis->CTX_SUFF(pPmTimer)));
+
+ pThis->uPmTimerVal = ASMMultU64ByU32DivByU32(u64Elapsed, PM_TMR_FREQ, TMTimerGetFreq(pThis->CTX_SUFF(pPmTimer))) & TMR_VAL_MASK;
+
+ if ( (pThis->uPmTimerVal & TMR_VAL_MSB) != msb)
+ {
+ apicUpdatePm1a(pThis, pThis->pm1a_sts | TMR_STS, pThis->pm1a_en);
+ }
+}
+
+#ifdef IN_RING3
+
+/**
+ * @callback_method_impl{FNTMTIMERDEV, PM Timer callback}
+ */
+static DECLCALLBACK(void) acpiR3PmTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+ ACPIState *pThis = (ACPIState *)pvUser;
+ Assert(TMTimerIsLockOwner(pTimer));
+ NOREF(pDevIns);
+
+ DEVACPI_LOCK_R3(pThis);
+ Log(("acpi: pm timer sts %#x (%d), en %#x (%d)\n",
+ pThis->pm1a_sts, (pThis->pm1a_sts & TMR_STS) != 0,
+ pThis->pm1a_en, (pThis->pm1a_en & TMR_EN) != 0));
+ uint64_t u64Now = TMTimerGet(pTimer);
+ acpiPmTimerUpdate(pThis, u64Now);
+ DEVACPI_UNLOCK(pThis);
+
+ acpiR3PmTimerReset(pThis, u64Now);
+}
+
+/**
+ * _BST method - used by acpiR3BatDataRead to implement BAT_STATUS_STATE and
+ * acpiR3LoadState.
+ *
+ * @returns VINF_SUCCESS.
+ * @param pThis The ACPI instance.
+ */
+static int acpiR3FetchBatteryStatus(ACPIState *pThis)
+{
+ uint32_t *p = pThis->au8BatteryInfo;
+ bool fPresent; /* battery present? */
+ PDMACPIBATCAPACITY hostRemainingCapacity; /* 0..100 */
+ PDMACPIBATSTATE hostBatteryState; /* bitfield */
+ uint32_t hostPresentRate; /* 0..1000 */
+ int rc;
+
+ if (!pThis->pDrv)
+ return VINF_SUCCESS;
+ rc = pThis->pDrv->pfnQueryBatteryStatus(pThis->pDrv, &fPresent, &hostRemainingCapacity,
+ &hostBatteryState, &hostPresentRate);
+ AssertRC(rc);
+
+ /* default values */
+ p[BAT_STATUS_STATE] = hostBatteryState;
+ p[BAT_STATUS_PRESENT_RATE] = hostPresentRate == ~0U ? 0xFFFFFFFF
+ : hostPresentRate * 50; /* mW */
+ p[BAT_STATUS_REMAINING_CAPACITY] = 50000; /* mWh */
+ p[BAT_STATUS_PRESENT_VOLTAGE] = 10000; /* mV */
+
+ /* did we get a valid battery state? */
+ if (hostRemainingCapacity != PDM_ACPI_BAT_CAPACITY_UNKNOWN)
+ p[BAT_STATUS_REMAINING_CAPACITY] = hostRemainingCapacity * 500; /* mWh */
+ if (hostBatteryState == PDM_ACPI_BAT_STATE_CHARGED)
+ p[BAT_STATUS_PRESENT_RATE] = 0; /* mV */
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * _BIF method - used by acpiR3BatDataRead to implement BAT_INFO_UNITS and
+ * acpiR3LoadState.
+ *
+ * @returns VINF_SUCCESS.
+ * @param pThis The ACPI instance.
+ */
+static int acpiR3FetchBatteryInfo(ACPIState *pThis)
+{
+ uint32_t *p = pThis->au8BatteryInfo;
+
+ p[BAT_INFO_UNITS] = 0; /* mWh */
+ p[BAT_INFO_DESIGN_CAPACITY] = 50000; /* mWh */
+ p[BAT_INFO_LAST_FULL_CHARGE_CAPACITY] = 50000; /* mWh */
+ p[BAT_INFO_TECHNOLOGY] = BAT_TECH_PRIMARY;
+ p[BAT_INFO_DESIGN_VOLTAGE] = 10000; /* mV */
+ p[BAT_INFO_DESIGN_CAPACITY_OF_WARNING] = 100; /* mWh */
+ p[BAT_INFO_DESIGN_CAPACITY_OF_LOW] = 50; /* mWh */
+ p[BAT_INFO_CAPACITY_GRANULARITY_1] = 1; /* mWh */
+ p[BAT_INFO_CAPACITY_GRANULARITY_2] = 1; /* mWh */
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * The _STA method - used by acpiR3BatDataRead to implement BAT_DEVICE_STATUS.
+ *
+ * @returns status mask or 0.
+ * @param pThis The ACPI instance.
+ */
+static uint32_t acpiR3GetBatteryDeviceStatus(ACPIState *pThis)
+{
+ bool fPresent; /* battery present? */
+ PDMACPIBATCAPACITY hostRemainingCapacity; /* 0..100 */
+ PDMACPIBATSTATE hostBatteryState; /* bitfield */
+ uint32_t hostPresentRate; /* 0..1000 */
+ int rc;
+
+ if (!pThis->pDrv)
+ return 0;
+ rc = pThis->pDrv->pfnQueryBatteryStatus(pThis->pDrv, &fPresent, &hostRemainingCapacity,
+ &hostBatteryState, &hostPresentRate);
+ AssertRC(rc);
+
+ return fPresent
+ ? STA_DEVICE_PRESENT_MASK /* present */
+ | STA_DEVICE_ENABLED_MASK /* enabled and decodes its resources */
+ | STA_DEVICE_SHOW_IN_UI_MASK /* should be shown in UI */
+ | STA_DEVICE_FUNCTIONING_PROPERLY_MASK /* functioning properly */
+ | STA_BATTERY_PRESENT_MASK /* battery is present */
+ : 0; /* device not present */
+}
+
+/**
+ * Used by acpiR3BatDataRead to implement BAT_POWER_SOURCE.
+ *
+ * @returns status.
+ * @param pThis The ACPI instance.
+ */
+static uint32_t acpiR3GetPowerSource(ACPIState *pThis)
+{
+ /* query the current power source from the host driver */
+ if (!pThis->pDrv)
+ return AC_ONLINE;
+
+ PDMACPIPOWERSOURCE ps;
+ int rc = pThis->pDrv->pfnQueryPowerSource(pThis->pDrv, &ps);
+ AssertRC(rc);
+ return ps == PDM_ACPI_POWER_SOURCE_BATTERY ? AC_OFFLINE : AC_ONLINE;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, Battery status index}
+ */
+PDMBOTHCBDECL(int) acpiR3BatIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ Log(("acpiR3BatIndexWrite: %#x (%#x)\n", u32, u32 >> 2));
+ if (cb != 4)
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32);
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ u32 >>= pThis->u8IndexShift;
+ /* see comment at the declaration of u8IndexShift */
+ if (pThis->u8IndexShift == 0 && u32 == (BAT_DEVICE_STATUS << 2))
+ {
+ pThis->u8IndexShift = 2;
+ u32 >>= 2;
+ }
+ Assert(u32 < BAT_INDEX_LAST);
+ pThis->uBatteryIndex = u32;
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, Battery status data}
+ */
+PDMBOTHCBDECL(int) acpiR3BatDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ if (cb != 4)
+ return VERR_IOM_IOPORT_UNUSED;
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ int rc = VINF_SUCCESS;
+ switch (pThis->uBatteryIndex)
+ {
+ case BAT_STATUS_STATE:
+ acpiR3FetchBatteryStatus(pThis);
+ RT_FALL_THRU();
+ case BAT_STATUS_PRESENT_RATE:
+ case BAT_STATUS_REMAINING_CAPACITY:
+ case BAT_STATUS_PRESENT_VOLTAGE:
+ *pu32 = pThis->au8BatteryInfo[pThis->uBatteryIndex];
+ break;
+
+ case BAT_INFO_UNITS:
+ acpiR3FetchBatteryInfo(pThis);
+ RT_FALL_THRU();
+ case BAT_INFO_DESIGN_CAPACITY:
+ case BAT_INFO_LAST_FULL_CHARGE_CAPACITY:
+ case BAT_INFO_TECHNOLOGY:
+ case BAT_INFO_DESIGN_VOLTAGE:
+ case BAT_INFO_DESIGN_CAPACITY_OF_WARNING:
+ case BAT_INFO_DESIGN_CAPACITY_OF_LOW:
+ case BAT_INFO_CAPACITY_GRANULARITY_1:
+ case BAT_INFO_CAPACITY_GRANULARITY_2:
+ *pu32 = pThis->au8BatteryInfo[pThis->uBatteryIndex];
+ break;
+
+ case BAT_DEVICE_STATUS:
+ *pu32 = acpiR3GetBatteryDeviceStatus(pThis);
+ break;
+
+ case BAT_POWER_SOURCE:
+ *pu32 = acpiR3GetPowerSource(pThis);
+ break;
+
+ default:
+ rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u idx=%u\n", cb, Port, pThis->uBatteryIndex);
+ *pu32 = UINT32_MAX;
+ break;
+ }
+
+ DEVACPI_UNLOCK(pThis);
+ return rc;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, System info index}
+ */
+PDMBOTHCBDECL(int) acpiR3SysInfoIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ Log(("acpiR3SysInfoIndexWrite: %#x (%#x)\n", u32, u32 >> 2));
+ if (cb != 4)
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32);
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ if (u32 == SYSTEM_INFO_INDEX_VALID || u32 == SYSTEM_INFO_INDEX_INVALID)
+ pThis->uSystemInfoIndex = u32;
+ else
+ {
+ /* see comment at the declaration of u8IndexShift */
+ if (u32 > SYSTEM_INFO_INDEX_END && pThis->u8IndexShift == 0)
+ {
+ if ((u32 >> 2) < SYSTEM_INFO_INDEX_END && (u32 & 0x3) == 0)
+ pThis->u8IndexShift = 2;
+ }
+
+ u32 >>= pThis->u8IndexShift;
+ Assert(u32 < SYSTEM_INFO_INDEX_END);
+ pThis->uSystemInfoIndex = u32;
+ }
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, System info data}
+ */
+PDMBOTHCBDECL(int) acpiR3SysInfoDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ if (cb != 4)
+ return VERR_IOM_IOPORT_UNUSED;
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ int rc = VINF_SUCCESS;
+ uint32_t const uSystemInfoIndex = pThis->uSystemInfoIndex;
+ switch (uSystemInfoIndex)
+ {
+ case SYSTEM_INFO_INDEX_LOW_MEMORY_LENGTH:
+ *pu32 = pThis->cbRamLow;
+ break;
+
+ case SYSTEM_INFO_INDEX_PREF64_MEMORY_MIN:
+ *pu32 = pThis->u64PciPref64Min >> 16; /* 64KB units */
+ Assert(((uint64_t)*pu32 << 16) == pThis->u64PciPref64Min);
+ break;
+
+ case SYSTEM_INFO_INDEX_PREF64_MEMORY_MAX:
+ *pu32 = pThis->u64PciPref64Max >> 16; /* 64KB units */
+ Assert(((uint64_t)*pu32 << 16) == pThis->u64PciPref64Max);
+ break;
+
+ case SYSTEM_INFO_INDEX_USE_IOAPIC:
+ *pu32 = pThis->u8UseIOApic;
+ break;
+
+ case SYSTEM_INFO_INDEX_HPET_STATUS:
+ *pu32 = pThis->fUseHpet
+ ? ( STA_DEVICE_PRESENT_MASK
+ | STA_DEVICE_ENABLED_MASK
+ | STA_DEVICE_SHOW_IN_UI_MASK
+ | STA_DEVICE_FUNCTIONING_PROPERLY_MASK)
+ : 0;
+ break;
+
+ case SYSTEM_INFO_INDEX_SMC_STATUS:
+ *pu32 = pThis->fUseSmc
+ ? ( STA_DEVICE_PRESENT_MASK
+ | STA_DEVICE_ENABLED_MASK
+ /* no need to show this device in the UI */
+ | STA_DEVICE_FUNCTIONING_PROPERLY_MASK)
+ : 0;
+ break;
+
+ case SYSTEM_INFO_INDEX_FDC_STATUS:
+ *pu32 = pThis->fUseFdc
+ ? ( STA_DEVICE_PRESENT_MASK
+ | STA_DEVICE_ENABLED_MASK
+ | STA_DEVICE_SHOW_IN_UI_MASK
+ | STA_DEVICE_FUNCTIONING_PROPERLY_MASK)
+ : 0;
+ break;
+
+ case SYSTEM_INFO_INDEX_NIC_ADDRESS:
+ *pu32 = pThis->u32NicPciAddress;
+ break;
+
+ case SYSTEM_INFO_INDEX_AUDIO_ADDRESS:
+ *pu32 = pThis->u32AudioPciAddress;
+ break;
+
+ case SYSTEM_INFO_INDEX_POWER_STATES:
+ *pu32 = RT_BIT(0) | RT_BIT(5); /* S1 and S5 always exposed */
+ if (pThis->fS1Enabled) /* Optionally expose S1 and S4 */
+ *pu32 |= RT_BIT(1);
+ if (pThis->fS4Enabled)
+ *pu32 |= RT_BIT(4);
+ break;
+
+ case SYSTEM_INFO_INDEX_IOC_ADDRESS:
+ *pu32 = pThis->u32IocPciAddress;
+ break;
+
+ case SYSTEM_INFO_INDEX_HBC_ADDRESS:
+ *pu32 = pThis->u32HbcPciAddress;
+ break;
+
+ case SYSTEM_INFO_INDEX_PCI_BASE:
+ /** @todo couldn't MCFG be in 64-bit range? */
+ Assert(pThis->u64PciConfigMMioAddress < 0xffffffff);
+ *pu32 = (uint32_t)pThis->u64PciConfigMMioAddress;
+ break;
+
+ case SYSTEM_INFO_INDEX_PCI_LENGTH:
+ /** @todo couldn't MCFG be in 64-bit range? */
+ Assert(pThis->u64PciConfigMMioLength < 0xffffffff);
+ *pu32 = (uint32_t)pThis->u64PciConfigMMioLength;
+ break;
+
+ case SYSTEM_INFO_INDEX_RTC_STATUS:
+ *pu32 = pThis->fShowRtc
+ ? ( STA_DEVICE_PRESENT_MASK
+ | STA_DEVICE_ENABLED_MASK
+ | STA_DEVICE_SHOW_IN_UI_MASK
+ | STA_DEVICE_FUNCTIONING_PROPERLY_MASK)
+ : 0;
+ break;
+
+ case SYSTEM_INFO_INDEX_CPU_LOCKED:
+ if (pThis->idCpuLockCheck < VMM_MAX_CPU_COUNT)
+ {
+ *pu32 = VMCPUSET_IS_PRESENT(&pThis->CpuSetLocked, pThis->idCpuLockCheck);
+ pThis->idCpuLockCheck = UINT32_C(0xffffffff); /* Make the entry invalid */
+ }
+ else
+ {
+ rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "CPU lock check protocol violation (idCpuLockCheck=%#x)\n",
+ pThis->idCpuLockCheck);
+ /* Always return locked status just to be safe */
+ *pu32 = 1;
+ }
+ break;
+
+ case SYSTEM_INFO_INDEX_CPU_EVENT_TYPE:
+ *pu32 = pThis->u32CpuEventType;
+ break;
+
+ case SYSTEM_INFO_INDEX_CPU_EVENT:
+ *pu32 = pThis->u32CpuEvent;
+ break;
+
+ case SYSTEM_INFO_INDEX_SERIAL0_IOBASE:
+ *pu32 = pThis->uSerial0IoPortBase;
+ break;
+
+ case SYSTEM_INFO_INDEX_SERIAL0_IRQ:
+ *pu32 = pThis->uSerial0Irq;
+ break;
+
+ case SYSTEM_INFO_INDEX_SERIAL1_IOBASE:
+ *pu32 = pThis->uSerial1IoPortBase;
+ break;
+
+ case SYSTEM_INFO_INDEX_SERIAL1_IRQ:
+ *pu32 = pThis->uSerial1Irq;
+ break;
+
+ case SYSTEM_INFO_INDEX_SERIAL2_IOBASE:
+ *pu32 = pThis->uSerial2IoPortBase;
+ break;
+
+ case SYSTEM_INFO_INDEX_SERIAL2_IRQ:
+ *pu32 = pThis->uSerial2Irq;
+ break;
+
+ case SYSTEM_INFO_INDEX_SERIAL3_IOBASE:
+ *pu32 = pThis->uSerial3IoPortBase;
+ break;
+
+ case SYSTEM_INFO_INDEX_SERIAL3_IRQ:
+ *pu32 = pThis->uSerial3Irq;
+ break;
+
+ case SYSTEM_INFO_INDEX_PARALLEL0_IOBASE:
+ *pu32 = pThis->uParallel0IoPortBase;
+ break;
+
+ case SYSTEM_INFO_INDEX_PARALLEL0_IRQ:
+ *pu32 = pThis->uParallel0Irq;
+ break;
+
+ case SYSTEM_INFO_INDEX_PARALLEL1_IOBASE:
+ *pu32 = pThis->uParallel1IoPortBase;
+ break;
+
+ case SYSTEM_INFO_INDEX_PARALLEL1_IRQ:
+ *pu32 = pThis->uParallel1Irq;
+ break;
+
+ case SYSTEM_INFO_INDEX_END:
+ /** @todo why isn't this setting any output value? */
+ break;
+
+ /* Solaris 9 tries to read from this index */
+ case SYSTEM_INFO_INDEX_INVALID:
+ *pu32 = 0;
+ break;
+
+ default:
+ *pu32 = UINT32_MAX;
+ rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u idx=%u\n", cb, Port, pThis->uBatteryIndex);
+ break;
+ }
+
+ DEVACPI_UNLOCK(pThis);
+ Log(("acpiR3SysInfoDataRead: idx=%d val=%#x (%u) rc=%Rrc\n", uSystemInfoIndex, *pu32, *pu32, rc));
+ return rc;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, System info data}
+ */
+PDMBOTHCBDECL(int) acpiR3SysInfoDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ ACPIState *pThis = (ACPIState *)pvUser;
+ if (cb != 4)
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x idx=%u\n", cb, Port, u32, pThis->uSystemInfoIndex);
+
+ DEVACPI_LOCK_R3(pThis);
+ Log(("addr=%#x cb=%d u32=%#x si=%#x\n", Port, cb, u32, pThis->uSystemInfoIndex));
+
+ int rc = VINF_SUCCESS;
+ switch (pThis->uSystemInfoIndex)
+ {
+ case SYSTEM_INFO_INDEX_INVALID:
+ AssertMsg(u32 == 0xbadc0de, ("u32=%u\n", u32));
+ pThis->u8IndexShift = 0;
+ break;
+
+ case SYSTEM_INFO_INDEX_VALID:
+ AssertMsg(u32 == 0xbadc0de, ("u32=%u\n", u32));
+ pThis->u8IndexShift = 2;
+ break;
+
+ case SYSTEM_INFO_INDEX_CPU_LOCK_CHECK:
+ pThis->idCpuLockCheck = u32;
+ break;
+
+ case SYSTEM_INFO_INDEX_CPU_LOCKED:
+ if (u32 < pThis->cCpus)
+ VMCPUSET_DEL(&pThis->CpuSetLocked, u32); /* Unlock the CPU */
+ else
+ LogRel(("ACPI: CPU %u does not exist\n", u32));
+ break;
+
+ default:
+ rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x idx=%u\n", cb, Port, u32, pThis->uSystemInfoIndex);
+ break;
+ }
+
+ DEVACPI_UNLOCK(pThis);
+ return rc;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, PM1a Enable}
+ */
+PDMBOTHCBDECL(int) acpiR3Pm1aEnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ NOREF(pDevIns); NOREF(Port);
+ if (cb != 2)
+ return VERR_IOM_IOPORT_UNUSED;
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ *pu32 = pThis->pm1a_en;
+
+ DEVACPI_UNLOCK(pThis);
+ Log(("acpiR3Pm1aEnRead -> %#x\n", *pu32));
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, PM1a Enable}
+ */
+PDMBOTHCBDECL(int) acpiR3PM1aEnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ if (cb != 2 && cb != 4)
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32);
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ Log(("acpiR3PM1aEnWrite: %#x (%#x)\n", u32, u32 & ~(RSR_EN | IGN_EN) & 0xffff));
+ u32 &= ~(RSR_EN | IGN_EN);
+ u32 &= 0xffff;
+ apicUpdatePm1a(pThis, pThis->pm1a_sts, u32);
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, PM1a Status}
+ */
+PDMBOTHCBDECL(int) acpiR3Pm1aStsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ if (cb != 2)
+ {
+ int rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u\n", cb, Port);
+ return rc == VINF_SUCCESS ? VERR_IOM_IOPORT_UNUSED : rc;
+ }
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ *pu32 = pThis->pm1a_sts;
+
+ DEVACPI_UNLOCK(pThis);
+ Log(("acpiR3Pm1aStsRead: %#x\n", *pu32));
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, PM1a Status}
+ */
+PDMBOTHCBDECL(int) acpiR3PM1aStsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ if (cb != 2 && cb != 4)
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32);
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ Log(("acpiR3PM1aStsWrite: %#x (%#x)\n", u32, u32 & ~(RSR_STS | IGN_STS) & 0xffff));
+ u32 &= 0xffff;
+ if (u32 & PWRBTN_STS)
+ pThis->fPowerButtonHandled = true; /* Remember that the guest handled the last power button event */
+ u32 = pThis->pm1a_sts & ~(u32 & ~(RSR_STS | IGN_STS));
+ apicUpdatePm1a(pThis, u32, pThis->pm1a_en);
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, PM1a Control}
+ */
+PDMBOTHCBDECL(int) acpiR3Pm1aCtlRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ if (cb != 2)
+ {
+ int rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u\n", cb, Port);
+ return rc == VINF_SUCCESS ? VERR_IOM_IOPORT_UNUSED : rc;
+ }
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ *pu32 = pThis->pm1a_ctl;
+
+ DEVACPI_UNLOCK(pThis);
+ Log(("acpiR3Pm1aCtlRead: %#x\n", *pu32));
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, PM1a Control}
+ */
+PDMBOTHCBDECL(int) acpiR3PM1aCtlWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ if (cb != 2 && cb != 4)
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32);
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ Log(("acpiR3PM1aCtlWrite: %#x (%#x)\n", u32, u32 & ~(RSR_CNT | IGN_CNT) & 0xffff));
+ u32 &= 0xffff;
+ pThis->pm1a_ctl = u32 & ~(RSR_CNT | IGN_CNT);
+
+ int rc = VINF_SUCCESS;
+ uint32_t const uSleepState = (pThis->pm1a_ctl >> SLP_TYPx_SHIFT) & SLP_TYPx_MASK;
+ if (uSleepState != pThis->uSleepState)
+ {
+ pThis->uSleepState = uSleepState;
+ switch (uSleepState)
+ {
+ case 0x00: /* S0 */
+ break;
+
+ case 0x01: /* S1 */
+ if (pThis->fS1Enabled)
+ {
+ LogRel(("ACPI: Entering S1 power state (powered-on suspend)\n"));
+ rc = acpiR3DoSleep(pThis);
+ break;
+ }
+ LogRel(("ACPI: Ignoring guest attempt to enter S1 power state (powered-on suspend)!\n"));
+ RT_FALL_THRU();
+
+ case 0x04: /* S4 */
+ if (pThis->fS4Enabled)
+ {
+ LogRel(("ACPI: Entering S4 power state (suspend to disk)\n"));
+ rc = acpiR3DoPowerOff(pThis);/* Same behavior as S5 */
+ break;
+ }
+ LogRel(("ACPI: Ignoring guest attempt to enter S4 power state (suspend to disk)!\n"));
+ RT_FALL_THRU();
+
+ case 0x05: /* S5 */
+ LogRel(("ACPI: Entering S5 power state (power down)\n"));
+ rc = acpiR3DoPowerOff(pThis);
+ break;
+
+ default:
+ rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Unknown sleep state %#x (u32=%#x)\n", uSleepState, u32);
+ break;
+ }
+ }
+
+ DEVACPI_UNLOCK(pThis);
+ Log(("acpiR3PM1aCtlWrite: rc=%Rrc\n", rc));
+ return rc;
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, PMTMR}
+ *
+ * @remarks Only I/O port currently implemented in all contexts.
+ */
+PDMBOTHCBDECL(int) acpiPMTmrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ if (cb != 4)
+ return VERR_IOM_IOPORT_UNUSED;
+
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+
+ /*
+ * We use the clock lock to serialize access to u64PmTimerInitial and to
+ * make sure we get a reliable time from the clock
+ * as well as and to prevent uPmTimerVal from being updated during read.
+ */
+
+ int rc = TMTimerLock(pThis->CTX_SUFF(pPmTimer), VINF_IOM_R3_IOPORT_READ);
+ if (rc != VINF_SUCCESS)
+ return rc;
+
+ rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_IOPORT_READ);
+ if (rc != VINF_SUCCESS)
+ {
+ TMTimerUnlock(pThis->CTX_SUFF(pPmTimer));
+ return rc;
+ }
+
+ uint64_t u64Now = TMTimerGet(pThis->CTX_SUFF(pPmTimer));
+ acpiPmTimerUpdate(pThis, u64Now);
+ *pu32 = pThis->uPmTimerVal;
+
+ DEVACPI_UNLOCK(pThis);
+ TMTimerUnlock(pThis->CTX_SUFF(pPmTimer));
+
+ DBGFTRACE_PDM_U64_TAG(pDevIns, u64Now, "acpi");
+ Log(("acpi: acpiPMTmrRead -> %#x\n", *pu32));
+
+#if 0
+ /** @todo temporary: sanity check against running backwards */
+ uint32_t uOld = ASMAtomicXchgU32(&pThis->uPmTimeOld, *pu32);
+ if (*pu32 - uOld >= 0x10000000)
+ {
+#if defined(IN_RING0)
+ pThis->uPmTimeA = uOld;
+ pThis->uPmTimeB = *pu32;
+ return VERR_TM_TIMER_BAD_CLOCK;
+#elif defined(IN_RING3)
+ AssertReleaseMsgFailed(("acpiPMTmrRead: old=%08RX32, current=%08RX32\n", uOld, *pu32));
+#endif
+ }
+#endif
+
+ NOREF(pvUser); NOREF(Port);
+ return rc;
+}
+
+#ifdef IN_RING3
+
+static DECLCALLBACK(void) acpiR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+ RT_NOREF(pszArgs);
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+ pHlp->pfnPrintf(pHlp,
+ "timer: old=%08RX32, current=%08RX32\n", pThis->uPmTimeA, pThis->uPmTimeB);
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, GPE0 Status}
+ */
+PDMBOTHCBDECL(int) acpiR3Gpe0StsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ if (cb != 1)
+ {
+ int rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u\n", cb, Port);
+ return rc == VINF_SUCCESS ? VERR_IOM_IOPORT_UNUSED : rc;
+ }
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ *pu32 = pThis->gpe0_sts & 0xff;
+
+ DEVACPI_UNLOCK(pThis);
+ Log(("acpiR3Gpe0StsRead: %#x\n", *pu32));
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, GPE0 Status}
+ */
+PDMBOTHCBDECL(int) acpiR3Gpe0StsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ if (cb != 1)
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32);
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ Log(("acpiR3Gpe0StsWrite: %#x (%#x)\n", u32, pThis->gpe0_sts & ~u32));
+ u32 = pThis->gpe0_sts & ~u32;
+ apicR3UpdateGpe0(pThis, u32, pThis->gpe0_en);
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, GPE0 Enable}
+ */
+PDMBOTHCBDECL(int) acpiR3Gpe0EnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ if (cb != 1)
+ {
+ int rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u\n", cb, Port);
+ return rc == VINF_SUCCESS ? VERR_IOM_IOPORT_UNUSED : rc;
+ }
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ *pu32 = pThis->gpe0_en & 0xff;
+
+ DEVACPI_UNLOCK(pThis);
+ Log(("acpiR3Gpe0EnRead: %#x\n", *pu32));
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, GPE0 Enable}
+ */
+PDMBOTHCBDECL(int) acpiR3Gpe0EnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ if (cb != 1)
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32);
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ Log(("acpiR3Gpe0EnWrite: %#x\n", u32));
+ apicR3UpdateGpe0(pThis, pThis->gpe0_sts, u32);
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, SMI_CMD}
+ */
+PDMBOTHCBDECL(int) acpiR3SmiWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ Log(("acpiR3SmiWrite %#x\n", u32));
+ if (cb != 1)
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32);
+
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ if (u32 == ACPI_ENABLE)
+ pThis->pm1a_ctl |= SCI_EN;
+ else if (u32 == ACPI_DISABLE)
+ pThis->pm1a_ctl &= ~SCI_EN;
+ else
+ Log(("acpiR3SmiWrite: %#x <- unknown value\n", u32));
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * @{FNIOMIOPORTOUT, ACPI_RESET_BLK}
+ */
+PDMBOTHCBDECL(int) acpiR3ResetWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ Log(("acpiR3ResetWrite: %#x\n", u32));
+ NOREF(pvUser);
+ if (cb != 1)
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32);
+
+ /* No state locking required. */
+ int rc = VINF_SUCCESS;
+ if (u32 == ACPI_RESET_REG_VAL)
+ {
+ LogRel(("ACPI: Reset initiated by ACPI\n"));
+ rc = PDMDevHlpVMReset(pDevIns, PDMVMRESET_F_ACPI);
+ }
+ else
+ Log(("acpiR3ResetWrite: %#x <- unknown value\n", u32));
+
+ return rc;
+}
+
+# ifdef DEBUG_ACPI
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, Debug hex value logger}
+ */
+PDMBOTHCBDECL(int) acpiR3DhexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ NOREF(pvUser);
+ switch (cb)
+ {
+ case 1:
+ Log(("%#x\n", u32 & 0xff));
+ break;
+ case 2:
+ Log(("%#6x\n", u32 & 0xffff));
+ break;
+ case 4:
+ Log(("%#10x\n", u32));
+ break;
+ default:
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32);
+ }
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, Debug char logger}
+ */
+PDMBOTHCBDECL(int) acpiR3DchrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ NOREF(pvUser);
+ switch (cb)
+ {
+ case 1:
+ Log(("%c", u32 & 0xff));
+ break;
+ default:
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32);
+ }
+ return VINF_SUCCESS;
+}
+
+# endif /* DEBUG_ACPI */
+
+/**
+ * Called by acpiR3Reset and acpiR3Construct to set up the PM PCI config space.
+ *
+ * @param pThis The ACPI instance.
+ */
+static void acpiR3PmPCIBIOSFake(ACPIState *pThis)
+{
+ pThis->dev.abConfig[PMBA ] = pThis->uPmIoPortBase | 1; /* PMBA, PM base address, bit 0 marks it as IO range */
+ pThis->dev.abConfig[PMBA+1] = pThis->uPmIoPortBase >> 8;
+ pThis->dev.abConfig[PMBA+2] = 0x00;
+ pThis->dev.abConfig[PMBA+3] = 0x00;
+}
+
+/**
+ * Used to calculate the value of a PM I/O port.
+ *
+ * @returns The actual I/O port value.
+ * @param pThis The ACPI instance.
+ * @param offset The offset into the I/O space, or -1 if invalid.
+ */
+static RTIOPORT acpiR3CalcPmPort(ACPIState *pThis, int32_t offset)
+{
+ Assert(pThis->uPmIoPortBase != 0);
+
+ if (offset == -1)
+ return 0;
+
+ return (RTIOPORT)(pThis->uPmIoPortBase + offset);
+}
+
+/**
+ * Called by acpiR3LoadState and acpiR3UpdatePmHandlers to register the PM1a, PM
+ * timer and GPE0 I/O ports.
+ *
+ * @returns VBox status code.
+ * @param pThis The ACPI instance.
+ */
+static int acpiR3RegisterPmHandlers(ACPIState *pThis)
+{
+ if (pThis->uPmIoPortBase == 0)
+ return VINF_SUCCESS;
+
+#define R(offset, cnt, writer, reader, description) \
+ do { \
+ int rc = PDMDevHlpIOPortRegister(pThis->pDevInsR3, acpiR3CalcPmPort(pThis, offset), cnt, pThis, writer, reader, \
+ NULL, NULL, description); \
+ if (RT_FAILURE(rc)) \
+ return rc; \
+ } while (0)
+#define L (GPE0_BLK_LEN / 2)
+
+ R(PM1a_EVT_OFFSET+2, 1, acpiR3PM1aEnWrite, acpiR3Pm1aEnRead, "ACPI PM1a Enable");
+ R(PM1a_EVT_OFFSET, 1, acpiR3PM1aStsWrite, acpiR3Pm1aStsRead, "ACPI PM1a Status");
+ R(PM1a_CTL_OFFSET, 1, acpiR3PM1aCtlWrite, acpiR3Pm1aCtlRead, "ACPI PM1a Control");
+ R(PM_TMR_OFFSET, 1, NULL, acpiPMTmrRead, "ACPI PM Timer");
+ R(GPE0_OFFSET + L, L, acpiR3Gpe0EnWrite, acpiR3Gpe0EnRead, "ACPI GPE0 Enable");
+ R(GPE0_OFFSET, L, acpiR3Gpe0StsWrite, acpiR3Gpe0StsRead, "ACPI GPE0 Status");
+#undef L
+#undef R
+
+ /* register RC stuff */
+ if (pThis->fGCEnabled)
+ {
+ int rc = PDMDevHlpIOPortRegisterRC(pThis->pDevInsR3, acpiR3CalcPmPort(pThis, PM_TMR_OFFSET),
+ 1, 0, NULL, "acpiPMTmrRead",
+ NULL, NULL, "ACPI PM Timer");
+ AssertRCReturn(rc, rc);
+ }
+
+ /* register R0 stuff */
+ if (pThis->fR0Enabled)
+ {
+ int rc = PDMDevHlpIOPortRegisterR0(pThis->pDevInsR3, acpiR3CalcPmPort(pThis, PM_TMR_OFFSET),
+ 1, 0, NULL, "acpiPMTmrRead",
+ NULL, NULL, "ACPI PM Timer");
+ AssertRCReturn(rc, rc);
+ }
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Called by acpiR3LoadState and acpiR3UpdatePmHandlers to unregister the PM1a, PM
+ * timer and GPE0 I/O ports.
+ *
+ * @returns VBox status code.
+ * @param pThis The ACPI instance.
+ */
+static int acpiR3UnregisterPmHandlers(ACPIState *pThis)
+{
+ if (pThis->uPmIoPortBase == 0)
+ return VINF_SUCCESS;
+
+#define U(offset, cnt) \
+ do { \
+ int rc = PDMDevHlpIOPortDeregister(pThis->pDevInsR3, acpiR3CalcPmPort(pThis, offset), cnt); \
+ AssertRCReturn(rc, rc); \
+ } while (0)
+#define L (GPE0_BLK_LEN / 2)
+
+ U(PM1a_EVT_OFFSET+2, 1);
+ U(PM1a_EVT_OFFSET, 1);
+ U(PM1a_CTL_OFFSET, 1);
+ U(PM_TMR_OFFSET, 1);
+ U(GPE0_OFFSET + L, L);
+ U(GPE0_OFFSET, L);
+#undef L
+#undef U
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Called by acpiR3PciConfigWrite and acpiReset to change the location of the
+ * PM1a, PM timer and GPE0 ports.
+ *
+ * @returns VBox status code.
+ *
+ * @param pThis The ACPI instance.
+ * @param NewIoPortBase The new base address of the I/O ports.
+ */
+static int acpiR3UpdatePmHandlers(ACPIState *pThis, RTIOPORT NewIoPortBase)
+{
+ Log(("acpi: rebasing PM 0x%x -> 0x%x\n", pThis->uPmIoPortBase, NewIoPortBase));
+ if (NewIoPortBase != pThis->uPmIoPortBase)
+ {
+ int rc = acpiR3UnregisterPmHandlers(pThis);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ pThis->uPmIoPortBase = NewIoPortBase;
+
+ rc = acpiR3RegisterPmHandlers(pThis);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /* We have to update FADT table acccording to the new base */
+ rc = acpiR3PlantTables(pThis);
+ AssertRC(rc);
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, SMBus}
+ */
+PDMBOTHCBDECL(int) acpiR3SMBusWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ LogFunc(("Port=%#x u32=%#x cb=%u\n", Port, u32, cb));
+ uint8_t off = Port & 0x000f;
+ if ( (cb != 1 && off <= SMBSHDWCMD_OFF)
+ || (cb != 2 && (off == SMBSLVEVT_OFF || off == SMBSLVDAT_OFF)))
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32);
+
+ switch (off)
+ {
+ case SMBHSTSTS_OFF:
+ /* Bit 0 is readonly, bits 1..4 are write clear, bits 5..7 are reserved */
+ pThis->u8SMBusHstSts &= ~(u32 & SMBHSTSTS_INT_MASK);
+ break;
+ case SMBSLVSTS_OFF:
+ /* Bit 0 is readonly, bit 1 is reserved, bits 2..5 are write clear, bits 6..7 are reserved */
+ pThis->u8SMBusSlvSts &= ~(u32 & SMBSLVSTS_WRITE_MASK);
+ break;
+ case SMBHSTCNT_OFF:
+ {
+ Assert(PDMCritSectIsOwner(&pThis->CritSect));
+
+ const bool old_level = acpiSCILevel(pThis);
+ pThis->u8SMBusHstCnt = u32 & SMBHSTCNT_WRITE_MASK;
+ if (u32 & SMBHSTCNT_START)
+ {
+ /* Start, trigger error as this is a dummy implementation */
+ pThis->u8SMBusHstSts |= SMBHSTSTS_DEV_ERR | SMBHSTSTS_INTER;
+ }
+ if (u32 & SMBHSTCNT_KILL)
+ {
+ /* Kill */
+ pThis->u8SMBusHstSts |= SMBHSTSTS_FAILED | SMBHSTSTS_INTER;
+ }
+ const bool new_level = acpiSCILevel(pThis);
+
+ LogFunc(("old=%x new=%x\n", old_level, new_level));
+
+ /* This handles only SCI/IRQ9. SMI# makes not much sense today and
+ * needs to be implemented later if it ever becomes relevant. */
+ if (new_level != old_level)
+ acpiSetIrq(pThis, new_level);
+ break;
+ }
+ case SMBHSTCMD_OFF:
+ pThis->u8SMBusHstCmd = u32;
+ break;
+ case SMBHSTADD_OFF:
+ pThis->u8SMBusHstAdd = u32;
+ break;
+ case SMBHSTDAT0_OFF:
+ pThis->u8SMBusHstDat0 = u32;
+ break;
+ case SMBHSTDAT1_OFF:
+ pThis->u8SMBusHstDat1 = u32;
+ break;
+ case SMBBLKDAT_OFF:
+ pThis->au8SMBusBlkDat[pThis->u8SMBusBlkIdx] = u32;
+ pThis->u8SMBusBlkIdx++;
+ pThis->u8SMBusBlkIdx &= sizeof(pThis->au8SMBusBlkDat) - 1;
+ break;
+ case SMBSLVCNT_OFF:
+ pThis->u8SMBusSlvCnt = u32 & SMBSLVCNT_WRITE_MASK;
+ break;
+ case SMBSHDWCMD_OFF:
+ /* readonly register */
+ break;
+ case SMBSLVEVT_OFF:
+ pThis->u16SMBusSlvEvt = u32;
+ break;
+ case SMBSLVDAT_OFF:
+ /* readonly register */
+ break;
+ default:
+ /* caught by the sanity check above */
+ ;
+ }
+
+ DEVACPI_UNLOCK(pThis);
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, SMBus}
+ */
+PDMBOTHCBDECL(int) acpiR3SMBusRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ RT_NOREF1(pDevIns);
+ ACPIState *pThis = (ACPIState *)pvUser;
+ DEVACPI_LOCK_R3(pThis);
+
+ int rc = VINF_SUCCESS;
+ LogFunc(("Port=%#x cb=%u\n", Port, cb));
+ uint8_t off = Port & 0x000f;
+ if ( (cb != 1 && off <= SMBSHDWCMD_OFF)
+ || (cb != 2 && (off == SMBSLVEVT_OFF || off == SMBSLVDAT_OFF)))
+ return VERR_IOM_IOPORT_UNUSED;
+
+ switch (off)
+ {
+ case SMBHSTSTS_OFF:
+ *pu32 = pThis->u8SMBusHstSts;
+ break;
+ case SMBSLVSTS_OFF:
+ *pu32 = pThis->u8SMBusSlvSts;
+ break;
+ case SMBHSTCNT_OFF:
+ pThis->u8SMBusBlkIdx = 0;
+ *pu32 = pThis->u8SMBusHstCnt;
+ break;
+ case SMBHSTCMD_OFF:
+ *pu32 = pThis->u8SMBusHstCmd;
+ break;
+ case SMBHSTADD_OFF:
+ *pu32 = pThis->u8SMBusHstAdd;
+ break;
+ case SMBHSTDAT0_OFF:
+ *pu32 = pThis->u8SMBusHstDat0;
+ break;
+ case SMBHSTDAT1_OFF:
+ *pu32 = pThis->u8SMBusHstDat1;
+ break;
+ case SMBBLKDAT_OFF:
+ *pu32 = pThis->au8SMBusBlkDat[pThis->u8SMBusBlkIdx];
+ pThis->u8SMBusBlkIdx++;
+ pThis->u8SMBusBlkIdx &= sizeof(pThis->au8SMBusBlkDat) - 1;
+ break;
+ case SMBSLVCNT_OFF:
+ *pu32 = pThis->u8SMBusSlvCnt;
+ break;
+ case SMBSHDWCMD_OFF:
+ *pu32 = pThis->u8SMBusShdwCmd;
+ break;
+ case SMBSLVEVT_OFF:
+ *pu32 = pThis->u16SMBusSlvEvt;
+ break;
+ case SMBSLVDAT_OFF:
+ *pu32 = pThis->u16SMBusSlvDat;
+ break;
+ default:
+ /* caught by the sanity check above */
+ rc = VERR_IOM_IOPORT_UNUSED;
+ }
+
+ DEVACPI_UNLOCK(pThis);
+ LogFunc(("Port=%#x u32=%#x cb=%u rc=%Rrc\n", Port, *pu32, cb, rc));
+ return rc;
+}
+
+/**
+ * Called by acpiR3Reset and acpiR3Construct to set up the SMBus PCI config space.
+ *
+ * @param pThis The ACPI instance.
+ */
+static void acpiR3SMBusPCIBIOSFake(ACPIState *pThis)
+{
+ pThis->dev.abConfig[SMBBA ] = pThis->uSMBusIoPortBase | 1; /* SMBBA, SMBus base address, bit 0 marks it as IO range */
+ pThis->dev.abConfig[SMBBA+1] = pThis->uSMBusIoPortBase >> 8;
+ pThis->dev.abConfig[SMBBA+2] = 0x00;
+ pThis->dev.abConfig[SMBBA+3] = 0x00;
+ pThis->dev.abConfig[SMBHSTCFG] = SMBHSTCFG_INTRSEL_IRQ9 << SMBHSTCFG_INTRSEL_SHIFT | SMBHSTCFG_SMB_HST_EN; /* SMBHSTCFG */
+ pThis->dev.abConfig[SMBSLVC] = 0x00; /* SMBSLVC */
+ pThis->dev.abConfig[SMBSHDW1] = 0x00; /* SMBSHDW1 */
+ pThis->dev.abConfig[SMBSHDW2] = 0x00; /* SMBSHDW2 */
+ pThis->dev.abConfig[SMBREV] = 0x00; /* SMBREV */
+}
+
+/**
+ * Called by acpiR3LoadState, acpiR3Reset and acpiR3Construct to reset the SMBus device register state.
+ *
+ * @param pThis The ACPI instance.
+ */
+static void acpiR3SMBusResetDevice(ACPIState *pThis)
+{
+ pThis->u8SMBusHstSts = 0x00;
+ pThis->u8SMBusSlvSts = 0x00;
+ pThis->u8SMBusHstCnt = 0x00;
+ pThis->u8SMBusHstCmd = 0x00;
+ pThis->u8SMBusHstAdd = 0x00;
+ pThis->u8SMBusHstDat0 = 0x00;
+ pThis->u8SMBusHstDat1 = 0x00;
+ pThis->u8SMBusSlvCnt = 0x00;
+ pThis->u8SMBusShdwCmd = 0x00;
+ pThis->u16SMBusSlvEvt = 0x0000;
+ pThis->u16SMBusSlvDat = 0x0000;
+ memset(pThis->au8SMBusBlkDat, 0x00, sizeof(pThis->au8SMBusBlkDat));
+ pThis->u8SMBusBlkIdx = 0;
+}
+
+/**
+ * Called by acpiR3LoadState and acpiR3UpdateSMBusHandlers to register the SMBus ports.
+ *
+ * @returns VBox status code.
+ * @param pThis The ACPI instance.
+ */
+static int acpiR3RegisterSMBusHandlers(ACPIState *pThis)
+{
+ int rc = VINF_SUCCESS;
+
+ if (pThis->uSMBusIoPortBase == 0)
+ return VINF_SUCCESS;
+
+ rc = PDMDevHlpIOPortRegister(pThis->pDevInsR3, pThis->uSMBusIoPortBase, 16, pThis, acpiR3SMBusWrite, acpiR3SMBusRead, NULL, NULL, "SMBus");
+ if (RT_FAILURE(rc))
+ return rc;
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Called by acpiR3LoadState and acpiR3UpdateSMBusHandlers to unregister the SMBus ports.
+ *
+ * @returns VBox status code.
+ * @param pThis The ACPI instance.
+ */
+static int acpiR3UnregisterSMBusHandlers(ACPIState *pThis)
+{
+ if (pThis->uSMBusIoPortBase == 0)
+ return VINF_SUCCESS;
+
+ int rc = PDMDevHlpIOPortDeregister(pThis->pDevInsR3, pThis->uSMBusIoPortBase, 16);
+ AssertRCReturn(rc, rc);
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Called by acpiR3PciConfigWrite and acpiReset to change the location of the
+ * SMBus ports.
+ *
+ * @returns VBox status code.
+ *
+ * @param pThis The ACPI instance.
+ * @param NewIoPortBase The new base address of the I/O ports.
+ */
+static int acpiR3UpdateSMBusHandlers(ACPIState *pThis, RTIOPORT NewIoPortBase)
+{
+ Log(("acpi: rebasing SMBus 0x%x -> 0x%x\n", pThis->uSMBusIoPortBase, NewIoPortBase));
+ if (NewIoPortBase != pThis->uSMBusIoPortBase)
+ {
+ int rc = acpiR3UnregisterSMBusHandlers(pThis);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ pThis->uSMBusIoPortBase = NewIoPortBase;
+
+ rc = acpiR3RegisterSMBusHandlers(pThis);
+ if (RT_FAILURE(rc))
+ return rc;
+
+#if 0 /* is there an FADT table entry for the SMBus base? */
+ /* We have to update FADT table acccording to the new base */
+ rc = acpiR3PlantTables(pThis);
+ AssertRC(rc);
+ if (RT_FAILURE(rc))
+ return rc;
+#endif
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * Saved state structure description, version 4.
+ */
+static const SSMFIELD g_AcpiSavedStateFields4[] =
+{
+ SSMFIELD_ENTRY(ACPIState, pm1a_en),
+ SSMFIELD_ENTRY(ACPIState, pm1a_sts),
+ SSMFIELD_ENTRY(ACPIState, pm1a_ctl),
+ SSMFIELD_ENTRY(ACPIState, u64PmTimerInitial),
+ SSMFIELD_ENTRY(ACPIState, gpe0_en),
+ SSMFIELD_ENTRY(ACPIState, gpe0_sts),
+ SSMFIELD_ENTRY(ACPIState, uBatteryIndex),
+ SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex),
+ SSMFIELD_ENTRY(ACPIState, u64RamSize),
+ SSMFIELD_ENTRY(ACPIState, u8IndexShift),
+ SSMFIELD_ENTRY(ACPIState, u8UseIOApic),
+ SSMFIELD_ENTRY(ACPIState, uSleepState),
+ SSMFIELD_ENTRY_TERM()
+};
+
+/**
+ * Saved state structure description, version 5.
+ */
+static const SSMFIELD g_AcpiSavedStateFields5[] =
+{
+ SSMFIELD_ENTRY(ACPIState, pm1a_en),
+ SSMFIELD_ENTRY(ACPIState, pm1a_sts),
+ SSMFIELD_ENTRY(ACPIState, pm1a_ctl),
+ SSMFIELD_ENTRY(ACPIState, u64PmTimerInitial),
+ SSMFIELD_ENTRY(ACPIState, gpe0_en),
+ SSMFIELD_ENTRY(ACPIState, gpe0_sts),
+ SSMFIELD_ENTRY(ACPIState, uBatteryIndex),
+ SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex),
+ SSMFIELD_ENTRY(ACPIState, uSleepState),
+ SSMFIELD_ENTRY(ACPIState, u8IndexShift),
+ SSMFIELD_ENTRY(ACPIState, uPmIoPortBase),
+ SSMFIELD_ENTRY_TERM()
+};
+
+/**
+ * Saved state structure description, version 6.
+ */
+static const SSMFIELD g_AcpiSavedStateFields6[] =
+{
+ SSMFIELD_ENTRY(ACPIState, pm1a_en),
+ SSMFIELD_ENTRY(ACPIState, pm1a_sts),
+ SSMFIELD_ENTRY(ACPIState, pm1a_ctl),
+ SSMFIELD_ENTRY(ACPIState, u64PmTimerInitial),
+ SSMFIELD_ENTRY(ACPIState, gpe0_en),
+ SSMFIELD_ENTRY(ACPIState, gpe0_sts),
+ SSMFIELD_ENTRY(ACPIState, uBatteryIndex),
+ SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex),
+ SSMFIELD_ENTRY(ACPIState, uSleepState),
+ SSMFIELD_ENTRY(ACPIState, u8IndexShift),
+ SSMFIELD_ENTRY(ACPIState, uPmIoPortBase),
+ SSMFIELD_ENTRY(ACPIState, fSuspendToSavedState),
+ SSMFIELD_ENTRY_TERM()
+};
+
+/**
+ * Saved state structure description, version 7.
+ */
+static const SSMFIELD g_AcpiSavedStateFields7[] =
+{
+ SSMFIELD_ENTRY(ACPIState, pm1a_en),
+ SSMFIELD_ENTRY(ACPIState, pm1a_sts),
+ SSMFIELD_ENTRY(ACPIState, pm1a_ctl),
+ SSMFIELD_ENTRY(ACPIState, u64PmTimerInitial),
+ SSMFIELD_ENTRY(ACPIState, uPmTimerVal),
+ SSMFIELD_ENTRY(ACPIState, gpe0_en),
+ SSMFIELD_ENTRY(ACPIState, gpe0_sts),
+ SSMFIELD_ENTRY(ACPIState, uBatteryIndex),
+ SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex),
+ SSMFIELD_ENTRY(ACPIState, uSleepState),
+ SSMFIELD_ENTRY(ACPIState, u8IndexShift),
+ SSMFIELD_ENTRY(ACPIState, uPmIoPortBase),
+ SSMFIELD_ENTRY(ACPIState, fSuspendToSavedState),
+ SSMFIELD_ENTRY_TERM()
+};
+
+/**
+ * Saved state structure description, version 8.
+ */
+static const SSMFIELD g_AcpiSavedStateFields8[] =
+{
+ SSMFIELD_ENTRY(ACPIState, pm1a_en),
+ SSMFIELD_ENTRY(ACPIState, pm1a_sts),
+ SSMFIELD_ENTRY(ACPIState, pm1a_ctl),
+ SSMFIELD_ENTRY(ACPIState, u64PmTimerInitial),
+ SSMFIELD_ENTRY(ACPIState, uPmTimerVal),
+ SSMFIELD_ENTRY(ACPIState, gpe0_en),
+ SSMFIELD_ENTRY(ACPIState, gpe0_sts),
+ SSMFIELD_ENTRY(ACPIState, uBatteryIndex),
+ SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex),
+ SSMFIELD_ENTRY(ACPIState, uSleepState),
+ SSMFIELD_ENTRY(ACPIState, u8IndexShift),
+ SSMFIELD_ENTRY(ACPIState, uPmIoPortBase),
+ SSMFIELD_ENTRY(ACPIState, fSuspendToSavedState),
+ SSMFIELD_ENTRY(ACPIState, uSMBusIoPortBase),
+ SSMFIELD_ENTRY(ACPIState, u8SMBusHstSts),
+ SSMFIELD_ENTRY(ACPIState, u8SMBusSlvSts),
+ SSMFIELD_ENTRY(ACPIState, u8SMBusHstCnt),
+ SSMFIELD_ENTRY(ACPIState, u8SMBusHstCmd),
+ SSMFIELD_ENTRY(ACPIState, u8SMBusHstAdd),
+ SSMFIELD_ENTRY(ACPIState, u8SMBusHstDat0),
+ SSMFIELD_ENTRY(ACPIState, u8SMBusHstDat1),
+ SSMFIELD_ENTRY(ACPIState, u8SMBusSlvCnt),
+ SSMFIELD_ENTRY(ACPIState, u8SMBusShdwCmd),
+ SSMFIELD_ENTRY(ACPIState, u16SMBusSlvEvt),
+ SSMFIELD_ENTRY(ACPIState, u16SMBusSlvDat),
+ SSMFIELD_ENTRY(ACPIState, au8SMBusBlkDat),
+ SSMFIELD_ENTRY(ACPIState, u8SMBusBlkIdx),
+ SSMFIELD_ENTRY_TERM()
+};
+
+/**
+ * @callback_method_impl{FNSSMDEVSAVEEXEC}
+ */
+static DECLCALLBACK(int) acpiR3SaveState(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+ return SSMR3PutStruct(pSSM, pThis, &g_AcpiSavedStateFields8[0]);
+}
+
+/**
+ * @callback_method_impl{FNSSMDEVLOADEXEC}
+ */
+static DECLCALLBACK(int) acpiR3LoadState(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+{
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+ Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
+
+ /*
+ * Unregister PM handlers, will register with actual base after state
+ * successfully loaded.
+ */
+ int rc = acpiR3UnregisterPmHandlers(pThis);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * Unregister SMBus handlers, will register with actual base after state
+ * successfully loaded.
+ */
+ rc = acpiR3UnregisterSMBusHandlers(pThis);
+ if (RT_FAILURE(rc))
+ return rc;
+ acpiR3SMBusResetDevice(pThis);
+
+ switch (uVersion)
+ {
+ case 4:
+ rc = SSMR3GetStruct(pSSM, pThis, &g_AcpiSavedStateFields4[0]);
+ break;
+ case 5:
+ rc = SSMR3GetStruct(pSSM, pThis, &g_AcpiSavedStateFields5[0]);
+ break;
+ case 6:
+ rc = SSMR3GetStruct(pSSM, pThis, &g_AcpiSavedStateFields6[0]);
+ break;
+ case 7:
+ rc = SSMR3GetStruct(pSSM, pThis, &g_AcpiSavedStateFields7[0]);
+ break;
+ case 8:
+ rc = SSMR3GetStruct(pSSM, pThis, &g_AcpiSavedStateFields8[0]);
+ break;
+ default:
+ rc = VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
+ break;
+ }
+ if (RT_SUCCESS(rc))
+ {
+ AssertLogRelMsgReturn(pThis->u8SMBusBlkIdx < RT_ELEMENTS(pThis->au8SMBusBlkDat),
+ ("%#x\n", pThis->u8SMBusBlkIdx), VERR_SSM_LOAD_CONFIG_MISMATCH);
+ rc = acpiR3RegisterPmHandlers(pThis);
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = acpiR3RegisterSMBusHandlers(pThis);
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = acpiR3FetchBatteryStatus(pThis);
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = acpiR3FetchBatteryInfo(pThis);
+ if (RT_FAILURE(rc))
+ return rc;
+ TMTimerLock(pThis->pPmTimerR3, VERR_IGNORED);
+ DEVACPI_LOCK_R3(pThis);
+ uint64_t u64Now = TMTimerGet(pThis->pPmTimerR3);
+ /* The interrupt may be incorrectly re-generated
+ * if the state is restored from versions < 7
+ */
+ acpiPmTimerUpdate(pThis, u64Now);
+ acpiR3PmTimerReset(pThis, u64Now);
+ DEVACPI_UNLOCK(pThis);
+ TMTimerUnlock(pThis->pPmTimerR3);
+ }
+ return rc;
+}
+
+/**
+ * @interface_method_impl{PDMIBASE,pfnQueryInterface}
+ */
+static DECLCALLBACK(void *) acpiR3QueryInterface(PPDMIBASE pInterface, const char *pszIID)
+{
+ ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IBase);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIACPIPORT, &pThis->IACPIPort);
+ return NULL;
+}
+
+/**
+ * Calculate the check sum for some ACPI data before planting it.
+ *
+ * All the bytes must add up to 0.
+ *
+ * @returns check sum.
+ * @param pvSrc What to check sum.
+ * @param cbData The amount of data to checksum.
+ */
+static uint8_t acpiR3Checksum(const void * const pvSrc, size_t cbData)
+{
+ uint8_t const *pbSrc = (uint8_t const *)pvSrc;
+ uint8_t uSum = 0;
+ for (size_t i = 0; i < cbData; ++i)
+ uSum += pbSrc[i];
+ return -uSum;
+}
+
+/**
+ * Prepare a ACPI table header.
+ */
+static void acpiR3PrepareHeader(ACPIState *pThis, ACPITBLHEADER *header,
+ const char au8Signature[4],
+ uint32_t u32Length, uint8_t u8Revision)
+{
+ memcpy(header->au8Signature, au8Signature, 4);
+ header->u32Length = RT_H2LE_U32(u32Length);
+ header->u8Revision = u8Revision;
+ memcpy(header->au8OemId, pThis->au8OemId, 6);
+ memcpy(header->au8OemTabId, "VBOX", 4);
+ memcpy(header->au8OemTabId+4, au8Signature, 4);
+ header->u32OemRevision = RT_H2LE_U32(1);
+ memcpy(header->au8CreatorId, pThis->au8CreatorId, 4);
+ header->u32CreatorRev = pThis->u32CreatorRev;
+}
+
+/**
+ * Initialize a generic address structure (ACPIGENADDR).
+ */
+static void acpiR3WriteGenericAddr(ACPIGENADDR *g, uint8_t u8AddressSpaceId,
+ uint8_t u8RegisterBitWidth, uint8_t u8RegisterBitOffset,
+ uint8_t u8AccessSize, uint64_t u64Address)
+{
+ g->u8AddressSpaceId = u8AddressSpaceId;
+ g->u8RegisterBitWidth = u8RegisterBitWidth;
+ g->u8RegisterBitOffset = u8RegisterBitOffset;
+ g->u8AccessSize = u8AccessSize;
+ g->u64Address = RT_H2LE_U64(u64Address);
+}
+
+/**
+ * Wrapper around PDMDevHlpPhysWrite used when planting ACPI tables.
+ */
+DECLINLINE(void) acpiR3PhysCopy(ACPIState *pThis, RTGCPHYS32 GCPhys32Dst, const void *pvSrc, size_t cbToCopy)
+{
+ PDMDevHlpPhysWrite(pThis->pDevInsR3, GCPhys32Dst, pvSrc, cbToCopy);
+}
+
+/**
+ * Plant the Differentiated System Description Table (DSDT).
+ */
+static void acpiR3SetupDsdt(ACPIState *pThis, RTGCPHYS32 GCPhys32, void *pvPtr, size_t cbDsdt)
+{
+ acpiR3PhysCopy(pThis, GCPhys32, pvPtr, cbDsdt);
+}
+
+/**
+ * Plan the Secondary System Description Table (SSDT).
+ */
+static void acpiR3SetupSsdt(ACPIState *pThis, RTGCPHYS32 addr,
+ void* pPtr, size_t uSsdtLen)
+{
+ acpiR3PhysCopy(pThis, addr, pPtr, uSsdtLen);
+}
+
+/**
+ * Plant the Firmware ACPI Control Structure (FACS).
+ */
+static void acpiR3SetupFacs(ACPIState *pThis, RTGCPHYS32 addr)
+{
+ ACPITBLFACS facs;
+
+ memset(&facs, 0, sizeof(facs));
+ memcpy(facs.au8Signature, "FACS", 4);
+ facs.u32Length = RT_H2LE_U32(sizeof(ACPITBLFACS));
+ facs.u32HWSignature = RT_H2LE_U32(0);
+ facs.u32FWVector = RT_H2LE_U32(0);
+ facs.u32GlobalLock = RT_H2LE_U32(0);
+ facs.u32Flags = RT_H2LE_U32(0);
+ facs.u64X_FWVector = RT_H2LE_U64(0);
+ facs.u8Version = 1;
+
+ acpiR3PhysCopy(pThis, addr, (const uint8_t *)&facs, sizeof(facs));
+}
+
+/**
+ * Plant the Fixed ACPI Description Table (FADT aka FACP).
+ */
+static void acpiR3SetupFadt(ACPIState *pThis, RTGCPHYS32 GCPhysAcpi1, RTGCPHYS32 GCPhysAcpi2,
+ RTGCPHYS32 GCPhysFacs, RTGCPHYS GCPhysDsdt)
+{
+ ACPITBLFADT fadt;
+
+ /* First the ACPI version 2+ version of the structure. */
+ memset(&fadt, 0, sizeof(fadt));
+ acpiR3PrepareHeader(pThis, &fadt.header, "FACP", sizeof(fadt), 4);
+ fadt.u32FACS = RT_H2LE_U32(GCPhysFacs);
+ fadt.u32DSDT = RT_H2LE_U32(GCPhysDsdt);
+ fadt.u8IntModel = 0; /* dropped from the ACPI 2.0 spec. */
+ fadt.u8PreferredPMProfile = 0; /* unspecified */
+ fadt.u16SCIInt = RT_H2LE_U16(SCI_INT);
+ fadt.u32SMICmd = RT_H2LE_U32(SMI_CMD);
+ fadt.u8AcpiEnable = ACPI_ENABLE;
+ fadt.u8AcpiDisable = ACPI_DISABLE;
+ fadt.u8S4BIOSReq = 0;
+ fadt.u8PStateCnt = 0;
+ fadt.u32PM1aEVTBLK = RT_H2LE_U32(acpiR3CalcPmPort(pThis, PM1a_EVT_OFFSET));
+ fadt.u32PM1bEVTBLK = RT_H2LE_U32(acpiR3CalcPmPort(pThis, PM1b_EVT_OFFSET));
+ fadt.u32PM1aCTLBLK = RT_H2LE_U32(acpiR3CalcPmPort(pThis, PM1a_CTL_OFFSET));
+ fadt.u32PM1bCTLBLK = RT_H2LE_U32(acpiR3CalcPmPort(pThis, PM1b_CTL_OFFSET));
+ fadt.u32PM2CTLBLK = RT_H2LE_U32(acpiR3CalcPmPort(pThis, PM2_CTL_OFFSET));
+ fadt.u32PMTMRBLK = RT_H2LE_U32(acpiR3CalcPmPort(pThis, PM_TMR_OFFSET));
+ fadt.u32GPE0BLK = RT_H2LE_U32(acpiR3CalcPmPort(pThis, GPE0_OFFSET));
+ fadt.u32GPE1BLK = RT_H2LE_U32(acpiR3CalcPmPort(pThis, GPE1_OFFSET));
+ fadt.u8PM1EVTLEN = 4;
+ fadt.u8PM1CTLLEN = 2;
+ fadt.u8PM2CTLLEN = 0;
+ fadt.u8PMTMLEN = 4;
+ fadt.u8GPE0BLKLEN = GPE0_BLK_LEN;
+ fadt.u8GPE1BLKLEN = GPE1_BLK_LEN;
+ fadt.u8GPE1BASE = GPE1_BASE;
+ fadt.u8CSTCNT = 0;
+ fadt.u16PLVL2LAT = RT_H2LE_U16(P_LVL2_LAT);
+ fadt.u16PLVL3LAT = RT_H2LE_U16(P_LVL3_LAT);
+ fadt.u16FlushSize = RT_H2LE_U16(FLUSH_SIZE);
+ fadt.u16FlushStride = RT_H2LE_U16(FLUSH_STRIDE);
+ fadt.u8DutyOffset = 0;
+ fadt.u8DutyWidth = 0;
+ fadt.u8DayAlarm = 0;
+ fadt.u8MonAlarm = 0;
+ fadt.u8Century = 0;
+ fadt.u16IAPCBOOTARCH = RT_H2LE_U16(IAPC_BOOT_ARCH_LEGACY_DEV | IAPC_BOOT_ARCH_8042);
+ /** @note WBINVD is required for ACPI versions newer than 1.0 */
+ fadt.u32Flags = RT_H2LE_U32( FADT_FL_WBINVD
+ | FADT_FL_FIX_RTC
+ | FADT_FL_TMR_VAL_EXT
+ | FADT_FL_RESET_REG_SUP);
+
+ /* We have to force physical APIC mode or Linux can't use more than 8 CPUs */
+ if (pThis->fCpuHotPlug)
+ fadt.u32Flags |= RT_H2LE_U32(FADT_FL_FORCE_APIC_PHYS_DEST_MODE);
+
+ acpiR3WriteGenericAddr(&fadt.ResetReg, 1, 8, 0, 1, ACPI_RESET_BLK);
+ fadt.u8ResetVal = ACPI_RESET_REG_VAL;
+ fadt.u64XFACS = RT_H2LE_U64((uint64_t)GCPhysFacs);
+ fadt.u64XDSDT = RT_H2LE_U64((uint64_t)GCPhysDsdt);
+ acpiR3WriteGenericAddr(&fadt.X_PM1aEVTBLK, 1, 32, 0, 2, acpiR3CalcPmPort(pThis, PM1a_EVT_OFFSET));
+ acpiR3WriteGenericAddr(&fadt.X_PM1bEVTBLK, 0, 0, 0, 0, acpiR3CalcPmPort(pThis, PM1b_EVT_OFFSET));
+ acpiR3WriteGenericAddr(&fadt.X_PM1aCTLBLK, 1, 16, 0, 2, acpiR3CalcPmPort(pThis, PM1a_CTL_OFFSET));
+ acpiR3WriteGenericAddr(&fadt.X_PM1bCTLBLK, 0, 0, 0, 0, acpiR3CalcPmPort(pThis, PM1b_CTL_OFFSET));
+ acpiR3WriteGenericAddr(&fadt.X_PM2CTLBLK, 0, 0, 0, 0, acpiR3CalcPmPort(pThis, PM2_CTL_OFFSET));
+ acpiR3WriteGenericAddr(&fadt.X_PMTMRBLK, 1, 32, 0, 3, acpiR3CalcPmPort(pThis, PM_TMR_OFFSET));
+ acpiR3WriteGenericAddr(&fadt.X_GPE0BLK, 1, 16, 0, 1, acpiR3CalcPmPort(pThis, GPE0_OFFSET));
+ acpiR3WriteGenericAddr(&fadt.X_GPE1BLK, 0, 0, 0, 0, acpiR3CalcPmPort(pThis, GPE1_OFFSET));
+ fadt.header.u8Checksum = acpiR3Checksum(&fadt, sizeof(fadt));
+ acpiR3PhysCopy(pThis, GCPhysAcpi2, &fadt, sizeof(fadt));
+
+ /* Now the ACPI 1.0 version. */
+ fadt.header.u32Length = ACPITBLFADT_VERSION1_SIZE;
+ fadt.u8IntModel = INT_MODEL_DUAL_PIC;
+ fadt.header.u8Checksum = 0; /* Must be zeroed before recalculating checksum! */
+ fadt.header.u8Checksum = acpiR3Checksum(&fadt, ACPITBLFADT_VERSION1_SIZE);
+ acpiR3PhysCopy(pThis, GCPhysAcpi1, &fadt, ACPITBLFADT_VERSION1_SIZE);
+}
+
+/**
+ * Plant the root System Description Table.
+ *
+ * The RSDT and XSDT tables are basically identical. The only difference is 32
+ * vs 64 bits addresses for description headers. RSDT is for ACPI 1.0. XSDT for
+ * ACPI 2.0 and up.
+ */
+static int acpiR3SetupRsdt(ACPIState *pThis, RTGCPHYS32 addr, unsigned int nb_entries, uint32_t *addrs)
+{
+ ACPITBLRSDT *rsdt;
+ const size_t size = sizeof(ACPITBLHEADER) + nb_entries * sizeof(rsdt->u32Entry[0]);
+
+ rsdt = (ACPITBLRSDT*)RTMemAllocZ(size);
+ if (!rsdt)
+ return PDMDEV_SET_ERROR(pThis->pDevInsR3, VERR_NO_TMP_MEMORY, N_("Cannot allocate RSDT"));
+
+ acpiR3PrepareHeader(pThis, &rsdt->header, "RSDT", (uint32_t)size, 1);
+ for (unsigned int i = 0; i < nb_entries; ++i)
+ {
+ rsdt->u32Entry[i] = RT_H2LE_U32(addrs[i]);
+ Log(("Setup RSDT: [%d] = %x\n", i, rsdt->u32Entry[i]));
+ }
+ rsdt->header.u8Checksum = acpiR3Checksum(rsdt, size);
+ acpiR3PhysCopy(pThis, addr, rsdt, size);
+ RTMemFree(rsdt);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Plant the Extended System Description Table.
+ */
+static int acpiR3SetupXsdt(ACPIState *pThis, RTGCPHYS32 addr, unsigned int nb_entries, uint32_t *addrs)
+{
+ ACPITBLXSDT *xsdt;
+ const size_t size = sizeof(ACPITBLHEADER) + nb_entries * sizeof(xsdt->u64Entry[0]);
+
+ xsdt = (ACPITBLXSDT*)RTMemAllocZ(size);
+ if (!xsdt)
+ return VERR_NO_TMP_MEMORY;
+
+ acpiR3PrepareHeader(pThis, &xsdt->header, "XSDT", (uint32_t)size, 1 /* according to ACPI 3.0 specs */);
+
+ if (pThis->cCustTbls > 0)
+ memcpy(xsdt->header.au8OemTabId, pThis->au8OemTabId, 8);
+
+ for (unsigned int i = 0; i < nb_entries; ++i)
+ {
+ xsdt->u64Entry[i] = RT_H2LE_U64((uint64_t)addrs[i]);
+ Log(("Setup XSDT: [%d] = %RX64\n", i, xsdt->u64Entry[i]));
+ }
+ xsdt->header.u8Checksum = acpiR3Checksum(xsdt, size);
+ acpiR3PhysCopy(pThis, addr, xsdt, size);
+ RTMemFree(xsdt);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Plant the Root System Description Pointer (RSDP).
+ */
+static void acpiR3SetupRsdp(ACPIState *pThis, ACPITBLRSDP *rsdp, RTGCPHYS32 GCPhysRsdt, RTGCPHYS GCPhysXsdt)
+{
+ memset(rsdp, 0, sizeof(*rsdp));
+
+ /* ACPI 1.0 part (RSDT) */
+ memcpy(rsdp->au8Signature, "RSD PTR ", 8);
+ memcpy(rsdp->au8OemId, pThis->au8OemId, 6);
+ rsdp->u8Revision = ACPI_REVISION;
+ rsdp->u32RSDT = RT_H2LE_U32(GCPhysRsdt);
+ rsdp->u8Checksum = acpiR3Checksum(rsdp, RT_OFFSETOF(ACPITBLRSDP, u32Length));
+
+ /* ACPI 2.0 part (XSDT) */
+ rsdp->u32Length = RT_H2LE_U32(sizeof(ACPITBLRSDP));
+ rsdp->u64XSDT = RT_H2LE_U64(GCPhysXsdt);
+ rsdp->u8ExtChecksum = acpiR3Checksum(rsdp, sizeof(ACPITBLRSDP));
+}
+
+/**
+ * Multiple APIC Description Table.
+ *
+ * This structure looks somewhat convoluted due layout of MADT table in MP case.
+ * There extpected to be multiple LAPIC records for each CPU, thus we cannot
+ * use regular C structure and proxy to raw memory instead.
+ */
+class AcpiTableMadt
+{
+ /**
+ * All actual data stored in dynamically allocated memory pointed by this field.
+ */
+ uint8_t *m_pbData;
+ /**
+ * Number of CPU entries in this MADT.
+ */
+ uint32_t m_cCpus;
+
+ /**
+ * Number of interrupt overrides.
+ */
+ uint32_t m_cIsos;
+
+public:
+ /**
+ * Address of ACPI header
+ */
+ inline ACPITBLHEADER *header_addr(void) const
+ {
+ return (ACPITBLHEADER *)m_pbData;
+ }
+
+ /**
+ * Address of local APIC for each CPU. Note that different CPUs address different LAPICs,
+ * although address is the same for all of them.
+ */
+ inline uint32_t *u32LAPIC_addr(void) const
+ {
+ return (uint32_t *)(header_addr() + 1);
+ }
+
+ /**
+ * Address of APIC flags
+ */
+ inline uint32_t *u32Flags_addr(void) const
+ {
+ return (uint32_t *)(u32LAPIC_addr() + 1);
+ }
+
+ /**
+ * Address of ISO description
+ */
+ inline ACPITBLISO *ISO_addr(void) const
+ {
+ return (ACPITBLISO *)(u32Flags_addr() + 1);
+ }
+
+ /**
+ * Address of per-CPU LAPIC descriptions
+ */
+ inline ACPITBLLAPIC *LApics_addr(void) const
+ {
+ return (ACPITBLLAPIC *)(ISO_addr() + m_cIsos);
+ }
+
+ /**
+ * Address of IO APIC description
+ */
+ inline ACPITBLIOAPIC *IOApic_addr(void) const
+ {
+ return (ACPITBLIOAPIC *)(LApics_addr() + m_cCpus);
+ }
+
+ /**
+ * Size of MADT.
+ * Note that this function assumes IOApic to be the last field in structure.
+ */
+ inline uint32_t size(void) const
+ {
+ return (uint8_t *)(IOApic_addr() + 1) - (uint8_t *)header_addr();
+ }
+
+ /**
+ * Raw data of MADT.
+ */
+ inline const uint8_t *data(void) const
+ {
+ return m_pbData;
+ }
+
+ /**
+ * Size of MADT for given ACPI config, useful to compute layout.
+ */
+ static uint32_t sizeFor(ACPIState *pThis, uint32_t cIsos)
+ {
+ return AcpiTableMadt(pThis->cCpus, cIsos).size();
+ }
+
+ /*
+ * Constructor, only works in Ring 3, doesn't look like a big deal.
+ */
+ AcpiTableMadt(uint32_t cCpus, uint32_t cIsos)
+ {
+ m_cCpus = cCpus;
+ m_cIsos = cIsos;
+ m_pbData = NULL; /* size() uses this and gcc will complain if not initialized. */
+ uint32_t cb = size();
+ m_pbData = (uint8_t *)RTMemAllocZ(cb);
+ }
+
+ ~AcpiTableMadt()
+ {
+ RTMemFree(m_pbData);
+ }
+};
+
+
+/**
+ * Plant the Multiple APIC Description Table (MADT).
+ *
+ * @note APIC without IO-APIC hangs Windows Vista therefore we setup both.
+ *
+ * @todo All hardcoded, should set this up based on the actual VM config!!!!!
+ */
+static void acpiR3SetupMadt(ACPIState *pThis, RTGCPHYS32 addr)
+{
+ uint16_t cpus = pThis->cCpus;
+ AcpiTableMadt madt(cpus, NUMBER_OF_IRQ_SOURCE_OVERRIDES);
+
+ acpiR3PrepareHeader(pThis, madt.header_addr(), "APIC", madt.size(), 2);
+
+ *madt.u32LAPIC_addr() = RT_H2LE_U32(0xfee00000);
+ *madt.u32Flags_addr() = RT_H2LE_U32(PCAT_COMPAT);
+
+ /* LAPICs records */
+ ACPITBLLAPIC* lapic = madt.LApics_addr();
+ for (uint16_t i = 0; i < cpus; i++)
+ {
+ lapic->u8Type = 0;
+ lapic->u8Length = sizeof(ACPITBLLAPIC);
+ lapic->u8ProcId = i;
+ /** Must match numbering convention in MPTABLES */
+ lapic->u8ApicId = i;
+ lapic->u32Flags = VMCPUSET_IS_PRESENT(&pThis->CpuSetAttached, i) ? RT_H2LE_U32(LAPIC_ENABLED) : 0;
+ lapic++;
+ }
+
+ /* IO-APIC record */
+ ACPITBLIOAPIC* ioapic = madt.IOApic_addr();
+ ioapic->u8Type = 1;
+ ioapic->u8Length = sizeof(ACPITBLIOAPIC);
+ /** Must match MP tables ID */
+ ioapic->u8IOApicId = cpus;
+ ioapic->u8Reserved = 0;
+ ioapic->u32Address = RT_H2LE_U32(0xfec00000);
+ ioapic->u32GSIB = RT_H2LE_U32(0);
+
+ /* Interrupt Source Overrides */
+ /* Flags:
+ bits[3:2]:
+ 00 conforms to the bus
+ 01 edge-triggered
+ 10 reserved
+ 11 level-triggered
+ bits[1:0]
+ 00 conforms to the bus
+ 01 active-high
+ 10 reserved
+ 11 active-low */
+ /* If changing, also update PDMIsaSetIrq() and MPS */
+ ACPITBLISO* isos = madt.ISO_addr();
+ /* Timer interrupt rule IRQ0 to GSI2 */
+ isos[0].u8Type = 2;
+ isos[0].u8Length = sizeof(ACPITBLISO);
+ isos[0].u8Bus = 0; /* Must be 0 */
+ isos[0].u8Source = 0; /* IRQ0 */
+ isos[0].u32GSI = 2; /* connected to pin 2 */
+ isos[0].u16Flags = 0; /* conform to the bus */
+
+ /* ACPI interrupt rule - IRQ9 to GSI9 */
+ isos[1].u8Type = 2;
+ isos[1].u8Length = sizeof(ACPITBLISO);
+ isos[1].u8Bus = 0; /* Must be 0 */
+ isos[1].u8Source = 9; /* IRQ9 */
+ isos[1].u32GSI = 9; /* connected to pin 9 */
+ isos[1].u16Flags = 0xf; /* active low, level triggered */
+ Assert(NUMBER_OF_IRQ_SOURCE_OVERRIDES == 2);
+
+ madt.header_addr()->u8Checksum = acpiR3Checksum(madt.data(), madt.size());
+ acpiR3PhysCopy(pThis, addr, madt.data(), madt.size());
+}
+
+/**
+ * Plant the High Performance Event Timer (HPET) descriptor.
+ */
+static void acpiR3SetupHpet(ACPIState *pThis, RTGCPHYS32 addr)
+{
+ ACPITBLHPET hpet;
+
+ memset(&hpet, 0, sizeof(hpet));
+
+ acpiR3PrepareHeader(pThis, &hpet.aHeader, "HPET", sizeof(hpet), 1);
+ /* Keep base address consistent with appropriate DSDT entry (vbox.dsl) */
+ acpiR3WriteGenericAddr(&hpet.HpetAddr,
+ 0 /* Memory address space */,
+ 64 /* Register bit width */,
+ 0 /* Bit offset */,
+ 0, /* Register access size, is it correct? */
+ 0xfed00000 /* Address */);
+
+ hpet.u32Id = 0x8086a201; /* must match what HPET ID returns, is it correct ? */
+ hpet.u32Number = 0;
+ hpet.u32MinTick = 4096;
+ hpet.u8Attributes = 0;
+
+ hpet.aHeader.u8Checksum = acpiR3Checksum(&hpet, sizeof(hpet));
+
+ acpiR3PhysCopy(pThis, addr, (const uint8_t *)&hpet, sizeof(hpet));
+}
+
+
+/**
+ * Used by acpiR3PlantTables to plant a MMCONFIG PCI config space access (MCFG)
+ * descriptor.
+ *
+ * @param pThis The ACPI instance.
+ * @param GCPhysDst Where to plant it.
+ */
+static void acpiR3SetupMcfg(ACPIState *pThis, RTGCPHYS32 GCPhysDst)
+{
+ struct
+ {
+ ACPITBLMCFG hdr;
+ ACPITBLMCFGENTRY entry;
+ } tbl;
+ uint8_t u8StartBus = 0;
+ uint8_t u8EndBus = (pThis->u64PciConfigMMioLength >> 20) - 1;
+
+ RT_ZERO(tbl);
+
+ acpiR3PrepareHeader(pThis, &tbl.hdr.aHeader, "MCFG", sizeof(tbl), 1);
+ tbl.entry.u64BaseAddress = pThis->u64PciConfigMMioAddress;
+ tbl.entry.u8StartBus = u8StartBus;
+ tbl.entry.u8EndBus = u8EndBus;
+ // u16PciSegmentGroup must match _SEG in ACPI table
+
+ tbl.hdr.aHeader.u8Checksum = acpiR3Checksum(&tbl, sizeof(tbl));
+
+ acpiR3PhysCopy(pThis, GCPhysDst, (const uint8_t *)&tbl, sizeof(tbl));
+}
+
+/**
+ * Used by acpiR3PlantTables and acpiConstruct.
+ *
+ * @returns Guest memory address.
+ */
+static uint32_t apicR3FindRsdpSpace(void)
+{
+ return 0xe0000;
+}
+
+/**
+ * Called by acpiR3Construct to read and allocate a custom ACPI table
+ *
+ * @param pDevIns The device instance.
+ * @param ppu8CustBin Address to receive the address of the table
+ * @param pcbCustBin Address to receive the size of the the table.
+ * @param pszCustBinFile
+ * @param cbBufAvail Maximum space in bytes available for the custom
+ * table (including header).
+ */
+static int acpiR3ReadCustomTable(PPDMDEVINS pDevIns, uint8_t **ppu8CustBin, uint64_t *pcbCustBin,
+ char *pszCustBinFile, uint32_t cbBufAvail)
+{
+ RTFILE FileCUSTBin;
+ int rc = RTFileOpen(&FileCUSTBin, pszCustBinFile,
+ RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTFileGetSize(FileCUSTBin, pcbCustBin);
+ if (RT_SUCCESS(rc))
+ {
+ /* The following checks should be in sync the AssertReleaseMsg's below. */
+ if ( *pcbCustBin > cbBufAvail
+ || *pcbCustBin < sizeof(ACPITBLHEADER))
+ rc = VERR_TOO_MUCH_DATA;
+
+ /*
+ * Allocate buffer for the custom table binary data.
+ */
+ *ppu8CustBin = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, *pcbCustBin);
+ if (*ppu8CustBin)
+ {
+ rc = RTFileRead(FileCUSTBin, *ppu8CustBin, *pcbCustBin, NULL);
+ if (RT_FAILURE(rc))
+ {
+ AssertMsgFailed(("RTFileRead(,,%d,NULL) -> %Rrc\n", *pcbCustBin, rc));
+ PDMDevHlpMMHeapFree(pDevIns, *ppu8CustBin);
+ *ppu8CustBin = NULL;
+ }
+ }
+ else
+ {
+ rc = VERR_NO_MEMORY;
+ }
+ RTFileClose(FileCUSTBin);
+ }
+ }
+ return rc;
+}
+
+/**
+ * Create the ACPI tables in guest memory.
+ */
+static int acpiR3PlantTables(ACPIState *pThis)
+{
+ int rc;
+ RTGCPHYS32 GCPhysCur, GCPhysRsdt, GCPhysXsdt, GCPhysFadtAcpi1, GCPhysFadtAcpi2, GCPhysFacs, GCPhysDsdt;
+ RTGCPHYS32 GCPhysHpet = 0;
+ RTGCPHYS32 GCPhysApic = 0;
+ RTGCPHYS32 GCPhysSsdt = 0;
+ RTGCPHYS32 GCPhysMcfg = 0;
+ RTGCPHYS32 aGCPhysCust[MAX_CUST_TABLES] = {0};
+ uint32_t addend = 0;
+ RTGCPHYS32 aGCPhysRsdt[7 + MAX_CUST_TABLES];
+ RTGCPHYS32 aGCPhysXsdt[7 + MAX_CUST_TABLES];
+ uint32_t cAddr;
+ uint32_t iMadt = 0;
+ uint32_t iHpet = 0;
+ uint32_t iSsdt = 0;
+ uint32_t iMcfg = 0;
+ uint32_t iCust = 0;
+ size_t cbRsdt = sizeof(ACPITBLHEADER);
+ size_t cbXsdt = sizeof(ACPITBLHEADER);
+
+ cAddr = 1; /* FADT */
+ if (pThis->u8UseIOApic)
+ iMadt = cAddr++; /* MADT */
+
+ if (pThis->fUseHpet)
+ iHpet = cAddr++; /* HPET */
+
+ if (pThis->fUseMcfg)
+ iMcfg = cAddr++; /* MCFG */
+
+ if (pThis->cCustTbls > 0)
+ {
+ iCust = cAddr; /* CUST */
+ cAddr += pThis->cCustTbls;
+ }
+
+ iSsdt = cAddr++; /* SSDT */
+
+ Assert(cAddr < RT_ELEMENTS(aGCPhysRsdt));
+ Assert(cAddr < RT_ELEMENTS(aGCPhysXsdt));
+
+ cbRsdt += cAddr*sizeof(uint32_t); /* each entry: 32 bits phys. address. */
+ cbXsdt += cAddr*sizeof(uint64_t); /* each entry: 64 bits phys. address. */
+
+ /*
+ * Calculate the sizes for the low region and for the 64-bit prefetchable memory.
+ * The latter starts never below 4G.
+ */
+ PVM pVM = PDMDevHlpGetVM(pThis->pDevInsR3);
+ uint32_t cbBelow4GB = MMR3PhysGetRamSizeBelow4GB(pVM);
+ uint64_t const cbAbove4GB = MMR3PhysGetRamSizeAbove4GB(pVM);
+
+ pThis->u64RamSize = MMR3PhysGetRamSize(pVM);
+ if (pThis->fPciPref64Enabled)
+ {
+ uint64_t const u64PciPref64Min = _4G + cbAbove4GB;
+ if (pThis->u64PciPref64Max > u64PciPref64Min)
+ {
+ /* Activate MEM4. See also DevPciIch9.cpp / ich9pciFakePCIBIOS() / uPciBiosMmio64 */
+ pThis->u64PciPref64Min = u64PciPref64Min;
+ LogRel(("ACPI: enabling 64-bit prefetch root bus resource %#018RX64..%#018RX64\n",
+ u64PciPref64Min, pThis->u64PciPref64Max-1));
+ }
+ else
+ LogRel(("ACPI: NOT enabling 64-bit prefetch root bus resource (min/%#018RX64 >= max/%#018RX64)\n",
+ u64PciPref64Min, pThis->u64PciPref64Max-1));
+ }
+ if (cbBelow4GB > UINT32_C(0xfe000000)) /* See MEM3. */
+ {
+ /* Note: This is also enforced by DevPcBios.cpp. */
+ LogRel(("ACPI: Clipping cbRamLow=%#RX64 down to 0xfe000000.\n", cbBelow4GB));
+ cbBelow4GB = UINT32_C(0xfe000000);
+ }
+ pThis->cbRamLow = cbBelow4GB;
+
+ GCPhysCur = 0;
+ GCPhysRsdt = GCPhysCur;
+
+ GCPhysCur = RT_ALIGN_32(GCPhysCur + cbRsdt, 16);
+ GCPhysXsdt = GCPhysCur;
+
+ GCPhysCur = RT_ALIGN_32(GCPhysCur + cbXsdt, 16);
+ GCPhysFadtAcpi1 = GCPhysCur;
+
+ GCPhysCur = RT_ALIGN_32(GCPhysCur + ACPITBLFADT_VERSION1_SIZE, 16);
+ GCPhysFadtAcpi2 = GCPhysCur;
+
+ GCPhysCur = RT_ALIGN_32(GCPhysCur + sizeof(ACPITBLFADT), 64);
+ GCPhysFacs = GCPhysCur;
+
+ GCPhysCur = RT_ALIGN_32(GCPhysCur + sizeof(ACPITBLFACS), 16);
+ if (pThis->u8UseIOApic)
+ {
+ GCPhysApic = GCPhysCur;
+ GCPhysCur = RT_ALIGN_32(GCPhysCur + AcpiTableMadt::sizeFor(pThis, NUMBER_OF_IRQ_SOURCE_OVERRIDES), 16);
+ }
+ if (pThis->fUseHpet)
+ {
+ GCPhysHpet = GCPhysCur;
+ GCPhysCur = RT_ALIGN_32(GCPhysCur + sizeof(ACPITBLHPET), 16);
+ }
+ if (pThis->fUseMcfg)
+ {
+ GCPhysMcfg = GCPhysCur;
+ /* Assume one entry */
+ GCPhysCur = RT_ALIGN_32(GCPhysCur + sizeof(ACPITBLMCFG) + sizeof(ACPITBLMCFGENTRY), 16);
+ }
+
+ for (uint8_t i = 0; i < pThis->cCustTbls; i++)
+ {
+ aGCPhysCust[i] = GCPhysCur;
+ GCPhysCur = RT_ALIGN_32(GCPhysCur + pThis->acbCustBin[i], 16);
+ }
+
+ void *pvSsdtCode = NULL;
+ size_t cbSsdt = 0;
+ rc = acpiPrepareSsdt(pThis->pDevInsR3, &pvSsdtCode, &cbSsdt);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ GCPhysSsdt = GCPhysCur;
+ GCPhysCur = RT_ALIGN_32(GCPhysCur + cbSsdt, 16);
+
+ GCPhysDsdt = GCPhysCur;
+
+ void *pvDsdtCode = NULL;
+ size_t cbDsdt = 0;
+ rc = acpiPrepareDsdt(pThis->pDevInsR3, &pvDsdtCode, &cbDsdt);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ GCPhysCur = RT_ALIGN_32(GCPhysCur + cbDsdt, 16);
+
+ if (GCPhysCur > 0x10000)
+ return PDMDEV_SET_ERROR(pThis->pDevInsR3, VERR_TOO_MUCH_DATA,
+ N_("Error: ACPI tables bigger than 64KB"));
+
+ Log(("RSDP 0x%08X\n", apicR3FindRsdpSpace()));
+ addend = pThis->cbRamLow - 0x10000;
+ Log(("RSDT 0x%08X XSDT 0x%08X\n", GCPhysRsdt + addend, GCPhysXsdt + addend));
+ Log(("FACS 0x%08X FADT (1.0) 0x%08X, FADT (2+) 0x%08X\n", GCPhysFacs + addend, GCPhysFadtAcpi1 + addend, GCPhysFadtAcpi2 + addend));
+ Log(("DSDT 0x%08X", GCPhysDsdt + addend));
+ if (pThis->u8UseIOApic)
+ Log((" MADT 0x%08X", GCPhysApic + addend));
+ if (pThis->fUseHpet)
+ Log((" HPET 0x%08X", GCPhysHpet + addend));
+ if (pThis->fUseMcfg)
+ Log((" MCFG 0x%08X", GCPhysMcfg + addend));
+ for (uint8_t i = 0; i < pThis->cCustTbls; i++)
+ Log((" CUST(%d) 0x%08X", i, aGCPhysCust[i] + addend));
+ Log((" SSDT 0x%08X", GCPhysSsdt + addend));
+ Log(("\n"));
+
+ acpiR3SetupRsdp(pThis, (ACPITBLRSDP *)pThis->au8RSDPPage, GCPhysRsdt + addend, GCPhysXsdt + addend);
+ acpiR3SetupDsdt(pThis, GCPhysDsdt + addend, pvDsdtCode, cbDsdt);
+ acpiCleanupDsdt(pThis->pDevInsR3, pvDsdtCode);
+ acpiR3SetupFacs(pThis, GCPhysFacs + addend);
+ acpiR3SetupFadt(pThis, GCPhysFadtAcpi1 + addend, GCPhysFadtAcpi2 + addend, GCPhysFacs + addend, GCPhysDsdt + addend);
+
+ aGCPhysRsdt[0] = GCPhysFadtAcpi1 + addend;
+ aGCPhysXsdt[0] = GCPhysFadtAcpi2 + addend;
+ if (pThis->u8UseIOApic)
+ {
+ acpiR3SetupMadt(pThis, GCPhysApic + addend);
+ aGCPhysRsdt[iMadt] = GCPhysApic + addend;
+ aGCPhysXsdt[iMadt] = GCPhysApic + addend;
+ }
+ if (pThis->fUseHpet)
+ {
+ acpiR3SetupHpet(pThis, GCPhysHpet + addend);
+ aGCPhysRsdt[iHpet] = GCPhysHpet + addend;
+ aGCPhysXsdt[iHpet] = GCPhysHpet + addend;
+ }
+ if (pThis->fUseMcfg)
+ {
+ acpiR3SetupMcfg(pThis, GCPhysMcfg + addend);
+ aGCPhysRsdt[iMcfg] = GCPhysMcfg + addend;
+ aGCPhysXsdt[iMcfg] = GCPhysMcfg + addend;
+ }
+ for (uint8_t i = 0; i < pThis->cCustTbls; i++)
+ {
+ Assert(i < MAX_CUST_TABLES);
+ acpiR3PhysCopy(pThis, aGCPhysCust[i] + addend, pThis->apu8CustBin[i], pThis->acbCustBin[i]);
+ aGCPhysRsdt[iCust + i] = aGCPhysCust[i] + addend;
+ aGCPhysXsdt[iCust + i] = aGCPhysCust[i] + addend;
+ uint8_t* pSig = pThis->apu8CustBin[i];
+ LogRel(("ACPI: Planted custom table '%c%c%c%c' at 0x%08X\n",
+ pSig[0], pSig[1], pSig[2], pSig[3], aGCPhysCust[i] + addend));
+ }
+
+ acpiR3SetupSsdt(pThis, GCPhysSsdt + addend, pvSsdtCode, cbSsdt);
+ acpiCleanupSsdt(pThis->pDevInsR3, pvSsdtCode);
+ aGCPhysRsdt[iSsdt] = GCPhysSsdt + addend;
+ aGCPhysXsdt[iSsdt] = GCPhysSsdt + addend;
+
+ rc = acpiR3SetupRsdt(pThis, GCPhysRsdt + addend, cAddr, aGCPhysRsdt);
+ if (RT_FAILURE(rc))
+ return rc;
+ return acpiR3SetupXsdt(pThis, GCPhysXsdt + addend, cAddr, aGCPhysXsdt);
+}
+
+/**
+ * @callback_method_impl{FNPCICONFIGREAD}
+ */
+static DECLCALLBACK(uint32_t) acpiR3PciConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress, unsigned cb)
+{
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+
+ Log2(("acpi: PCI config read: 0x%x (%d)\n", uAddress, cb));
+ return pThis->pfnAcpiPciConfigRead(pDevIns, pPciDev, uAddress, cb);
+}
+
+/**
+ * @callback_method_impl{FNPCICONFIGWRITE}
+ */
+static DECLCALLBACK(VBOXSTRICTRC) acpiR3PciConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress,
+ uint32_t u32Value, unsigned cb)
+{
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+
+ Log2(("acpi: PCI config write: 0x%x -> 0x%x (%d)\n", u32Value, uAddress, cb));
+ DEVACPI_LOCK_R3(pThis);
+
+ if (uAddress == VBOX_PCI_INTERRUPT_LINE)
+ {
+ Log(("acpi: ignore interrupt line settings: %d, we'll use hardcoded value %d\n", u32Value, SCI_INT));
+ u32Value = SCI_INT;
+ }
+
+ VBOXSTRICTRC rcBase = pThis->pfnAcpiPciConfigWrite(pDevIns, pPciDev, uAddress, u32Value, cb);
+
+ /* Assume that the base address is only changed when the corresponding
+ * hardware functionality is disabled. The IO region is mapped when the
+ * functionality is enabled by the guest. */
+
+ if (uAddress == PMREGMISC)
+ {
+ RTIOPORT NewIoPortBase = 0;
+ /* Check Power Management IO Space Enable (PMIOSE) bit */
+ if (pPciDev->abConfig[PMREGMISC] & 0x01)
+ {
+ NewIoPortBase = (RTIOPORT)PCIDevGetDWord(pPciDev, PMBA);
+ NewIoPortBase &= 0xffc0;
+ }
+
+ int rc = acpiR3UpdatePmHandlers(pThis, NewIoPortBase);
+ AssertRC(rc);
+ }
+
+ if (uAddress == SMBHSTCFG)
+ {
+ RTIOPORT NewIoPortBase = 0;
+ /* Check SMBus Controller Host Interface Enable (SMB_HST_EN) bit */
+ if (pPciDev->abConfig[SMBHSTCFG] & SMBHSTCFG_SMB_HST_EN)
+ {
+ NewIoPortBase = (RTIOPORT)PCIDevGetDWord(pPciDev, SMBBA);
+ NewIoPortBase &= 0xfff0;
+ }
+
+ int rc = acpiR3UpdateSMBusHandlers(pThis, NewIoPortBase);
+ AssertRC(rc);
+ }
+
+ DEVACPI_UNLOCK(pThis);
+ return rcBase;
+}
+
+/**
+ * Attach a new CPU.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iLUN The logical unit which is being attached.
+ * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
+ *
+ * @remarks This code path is not used during construction.
+ */
+static DECLCALLBACK(int) acpiR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
+{
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+ LogFlow(("acpiAttach: pDevIns=%p iLUN=%u fFlags=%#x\n", pDevIns, iLUN, fFlags));
+
+ AssertMsgReturn(!(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG),
+ ("Hot-plug flag is not set\n"),
+ VERR_NOT_SUPPORTED);
+ AssertReturn(iLUN < VMM_MAX_CPU_COUNT, VERR_PDM_NO_SUCH_LUN);
+
+ /* Check if it was already attached */
+ int rc = VINF_SUCCESS;
+ DEVACPI_LOCK_R3(pThis);
+ if (!VMCPUSET_IS_PRESENT(&pThis->CpuSetAttached, iLUN))
+ {
+ PPDMIBASE IBaseTmp;
+ rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pThis->IBase, &IBaseTmp, "ACPI CPU");
+ if (RT_SUCCESS(rc))
+ {
+ /* Enable the CPU */
+ VMCPUSET_ADD(&pThis->CpuSetAttached, iLUN);
+
+ /*
+ * Lock the CPU because we don't know if the guest will use it or not.
+ * Prevents ejection while the CPU is still used
+ */
+ VMCPUSET_ADD(&pThis->CpuSetLocked, iLUN);
+ pThis->u32CpuEventType = CPU_EVENT_TYPE_ADD;
+ pThis->u32CpuEvent = iLUN;
+
+ /* Notify the guest */
+ apicR3UpdateGpe0(pThis, pThis->gpe0_sts | 0x2, pThis->gpe0_en);
+ }
+ }
+ DEVACPI_UNLOCK(pThis);
+ return rc;
+}
+
+/**
+ * Detach notification.
+ *
+ * @param pDevIns The device instance.
+ * @param iLUN The logical unit which is being detached.
+ * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
+ */
+static DECLCALLBACK(void) acpiR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
+{
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+
+ LogFlow(("acpiDetach: pDevIns=%p iLUN=%u fFlags=%#x\n", pDevIns, iLUN, fFlags));
+
+ AssertMsgReturnVoid(!(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG),
+ ("Hot-plug flag is not set\n"));
+
+ /* Check if it was already detached */
+ DEVACPI_LOCK_R3(pThis);
+ if (VMCPUSET_IS_PRESENT(&pThis->CpuSetAttached, iLUN))
+ {
+ if (!VMCPUSET_IS_PRESENT(&pThis->CpuSetLocked, iLUN))
+ {
+ /* Disable the CPU */
+ VMCPUSET_DEL(&pThis->CpuSetAttached, iLUN);
+ pThis->u32CpuEventType = CPU_EVENT_TYPE_REMOVE;
+ pThis->u32CpuEvent = iLUN;
+
+ /* Notify the guest */
+ apicR3UpdateGpe0(pThis, pThis->gpe0_sts | 0x2, pThis->gpe0_en);
+ }
+ else
+ AssertMsgFailed(("CPU is still locked by the guest\n"));
+ }
+ DEVACPI_UNLOCK(pThis);
+}
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnResume}
+ */
+static DECLCALLBACK(void) acpiR3Resume(PPDMDEVINS pDevIns)
+{
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+ if (pThis->fSetWakeupOnResume)
+ {
+ Log(("acpiResume: setting WAK_STS\n"));
+ pThis->fSetWakeupOnResume = false;
+ pThis->pm1a_sts |= WAK_STS;
+ }
+}
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnMemSetup}
+ */
+static DECLCALLBACK(void) acpiR3MemSetup(PPDMDEVINS pDevIns, PDMDEVMEMSETUPCTX enmCtx)
+{
+ RT_NOREF1(enmCtx);
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+ acpiR3PlantTables(pThis);
+}
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnReset}
+ */
+static DECLCALLBACK(void) acpiR3Reset(PPDMDEVINS pDevIns)
+{
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+
+ /* Play safe: make sure that the IRQ isn't stuck after a reset. */
+ acpiSetIrq(pThis, 0);
+
+ TMTimerLock(pThis->pPmTimerR3, VERR_IGNORED);
+ pThis->pm1a_en = 0;
+ pThis->pm1a_sts = 0;
+ pThis->pm1a_ctl = 0;
+ pThis->u64PmTimerInitial = TMTimerGet(pThis->pPmTimerR3);
+ pThis->uPmTimerVal = 0;
+ acpiR3PmTimerReset(pThis, pThis->u64PmTimerInitial);
+ pThis->uPmTimeOld = pThis->uPmTimerVal;
+ pThis->uBatteryIndex = 0;
+ pThis->uSystemInfoIndex = 0;
+ pThis->gpe0_en = 0;
+ pThis->gpe0_sts = 0;
+ pThis->uSleepState = 0;
+ TMTimerUnlock(pThis->pPmTimerR3);
+
+ /* Real device behavior is resetting only the PM controller state,
+ * but we're additionally doing the job of the BIOS. */
+ acpiR3UpdatePmHandlers(pThis, PM_PORT_BASE);
+ acpiR3PmPCIBIOSFake(pThis);
+
+ /* Reset SMBus base and PCI config space in addition to the SMBus controller
+ * state. Real device behavior is only the SMBus controller state reset,
+ * but we're additionally doing the job of the BIOS. */
+ acpiR3UpdateSMBusHandlers(pThis, SMB_PORT_BASE);
+ acpiR3SMBusPCIBIOSFake(pThis);
+ acpiR3SMBusResetDevice(pThis);
+}
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnRelocate}
+ */
+static DECLCALLBACK(void) acpiR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
+{
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+ pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+ pThis->pPmTimerRC = TMTimerRCPtr(pThis->pPmTimerR3);
+ NOREF(offDelta);
+}
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnDestruct}
+ */
+static DECLCALLBACK(int) acpiR3Destruct(PPDMDEVINS pDevIns)
+{
+ PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+ for (uint8_t i = 0; i < pThis->cCustTbls; i++)
+ {
+ if (pThis->apu8CustBin[i])
+ {
+ PDMDevHlpMMHeapFree(pDevIns, pThis->apu8CustBin[i]);
+ pThis->apu8CustBin[i] = NULL;
+ }
+ }
+ return VINF_SUCCESS;
+}
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnConstruct}
+ */
+static DECLCALLBACK(int) acpiR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
+{
+ PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+ ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
+
+ /*
+ * Init data and set defaults.
+ */
+ /** @todo move more of the code up! */
+
+ pThis->pDevInsR3 = pDevIns;
+ pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
+ pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+ VMCPUSET_EMPTY(&pThis->CpuSetAttached);
+ VMCPUSET_EMPTY(&pThis->CpuSetLocked);
+ pThis->idCpuLockCheck = UINT32_C(0xffffffff);
+ pThis->u32CpuEventType = 0;
+ pThis->u32CpuEvent = UINT32_C(0xffffffff);
+
+ /* The first CPU can't be attached/detached */
+ VMCPUSET_ADD(&pThis->CpuSetAttached, 0);
+ VMCPUSET_ADD(&pThis->CpuSetLocked, 0);
+
+ /* IBase */
+ pThis->IBase.pfnQueryInterface = acpiR3QueryInterface;
+ /* IACPIPort */
+ pThis->IACPIPort.pfnSleepButtonPress = acpiR3Port_SleepButtonPress;
+ pThis->IACPIPort.pfnPowerButtonPress = acpiR3Port_PowerButtonPress;
+ pThis->IACPIPort.pfnGetPowerButtonHandled = acpiR3Port_GetPowerButtonHandled;
+ pThis->IACPIPort.pfnGetGuestEnteredACPIMode = acpiR3Port_GetGuestEnteredACPIMode;
+ pThis->IACPIPort.pfnGetCpuStatus = acpiR3Port_GetCpuStatus;
+ pThis->IACPIPort.pfnMonitorHotPlugEvent = acpiR3Port_MonitorHotPlugEvent;
+ pThis->IACPIPort.pfnBatteryStatusChangeEvent = acpiR3Port_BatteryStatusChangeEvent;
+
+ /*
+ * Set the default critical section to NOP (related to the PM timer).
+ */
+ int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
+ AssertRCReturn(rc, rc);
+
+ rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "acpi#%u", iInstance);
+ AssertRCReturn(rc, rc);
+
+ /*
+ * Validate and read the configuration.
+ */
+ if (!CFGMR3AreValuesValid(pCfg,
+ "IOAPIC\0"
+ "NumCPUs\0"
+ "GCEnabled\0"
+ "R0Enabled\0"
+ "HpetEnabled\0"
+ "McfgEnabled\0"
+ "McfgBase\0"
+ "McfgLength\0"
+ "PciPref64Enabled\0"
+ "PciPref64LimitGB\0"
+ "SmcEnabled\0"
+ "FdcEnabled\0"
+ "ShowRtc\0"
+ "ShowCpu\0"
+ "NicPciAddress\0"
+ "AudioPciAddress\0"
+ "IocPciAddress\0"
+ "HostBusPciAddress\0"
+ "EnableSuspendToDisk\0"
+ "PowerS1Enabled\0"
+ "PowerS4Enabled\0"
+ "CpuHotPlug\0"
+ "AmlFilePath\0"
+ "Serial0IoPortBase\0"
+ "Serial1IoPortBase\0"
+ "Serial2IoPortBase\0"
+ "Serial3IoPortBase\0"
+ "Serial0Irq\0"
+ "Serial1Irq\0"
+ "Serial2Irq\0"
+ "Serial3Irq\0"
+ "AcpiOemId\0"
+ "AcpiCreatorId\0"
+ "AcpiCreatorRev\0"
+ "CustomTable\0"
+ "CustomTable0\0"
+ "CustomTable1\0"
+ "CustomTable2\0"
+ "CustomTable3\0"
+ "Parallel0IoPortBase\0"
+ "Parallel1IoPortBase\0"
+ "Parallel0Irq\0"
+ "Parallel1Irq\0"
+ ))
+ return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
+ N_("Configuration error: Invalid config key for ACPI device"));
+
+ /* query whether we are supposed to present an IOAPIC */
+ rc = CFGMR3QueryU8Def(pCfg, "IOAPIC", &pThis->u8UseIOApic, 1);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"IOAPIC\""));
+
+ rc = CFGMR3QueryU16Def(pCfg, "NumCPUs", &pThis->cCpus, 1);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"NumCPUs\" as integer failed"));
+
+ /* query whether we are supposed to present an FDC controller */
+ rc = CFGMR3QueryBoolDef(pCfg, "FdcEnabled", &pThis->fUseFdc, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"FdcEnabled\""));
+
+ /* query whether we are supposed to present HPET */
+ rc = CFGMR3QueryBoolDef(pCfg, "HpetEnabled", &pThis->fUseHpet, false);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"HpetEnabled\""));
+ /* query MCFG configuration */
+ rc = CFGMR3QueryU64Def(pCfg, "McfgBase", &pThis->u64PciConfigMMioAddress, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"McfgBase\""));
+ rc = CFGMR3QueryU64Def(pCfg, "McfgLength", &pThis->u64PciConfigMMioLength, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"McfgLength\""));
+ pThis->fUseMcfg = (pThis->u64PciConfigMMioAddress != 0) && (pThis->u64PciConfigMMioLength != 0);
+
+ /* query whether we are supposed to set up the 64-bit prefetchable memory window */
+ rc = CFGMR3QueryBoolDef(pCfg, "PciPref64Enabled", &pThis->fPciPref64Enabled, false);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"PciPref64Enabled\""));
+
+ /* query the limit of the the 64-bit prefetchable memory window */
+ uint64_t u64PciPref64MaxGB;
+ rc = CFGMR3QueryU64Def(pCfg, "PciPref64LimitGB", &u64PciPref64MaxGB, 64);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"PciPref64LimitGB\""));
+ pThis->u64PciPref64Max = _1G64 * u64PciPref64MaxGB;
+
+ /* query whether we are supposed to present SMC */
+ rc = CFGMR3QueryBoolDef(pCfg, "SmcEnabled", &pThis->fUseSmc, false);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"SmcEnabled\""));
+
+ /* query whether we are supposed to present RTC object */
+ rc = CFGMR3QueryBoolDef(pCfg, "ShowRtc", &pThis->fShowRtc, false);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"ShowRtc\""));
+
+ /* query whether we are supposed to present CPU objects */
+ rc = CFGMR3QueryBoolDef(pCfg, "ShowCpu", &pThis->fShowCpu, false);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"ShowCpu\""));
+
+ /* query primary NIC PCI address */
+ rc = CFGMR3QueryU32Def(pCfg, "NicPciAddress", &pThis->u32NicPciAddress, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"NicPciAddress\""));
+
+ /* query primary NIC PCI address */
+ rc = CFGMR3QueryU32Def(pCfg, "AudioPciAddress", &pThis->u32AudioPciAddress, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"AudioPciAddress\""));
+
+ /* query IO controller (southbridge) PCI address */
+ rc = CFGMR3QueryU32Def(pCfg, "IocPciAddress", &pThis->u32IocPciAddress, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"IocPciAddress\""));
+
+ /* query host bus controller PCI address */
+ rc = CFGMR3QueryU32Def(pCfg, "HostBusPciAddress", &pThis->u32HbcPciAddress, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"HostBusPciAddress\""));
+
+ /* query whether S1 power state should be exposed */
+ rc = CFGMR3QueryBoolDef(pCfg, "PowerS1Enabled", &pThis->fS1Enabled, false);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"PowerS1Enabled\""));
+
+ /* query whether S4 power state should be exposed */
+ rc = CFGMR3QueryBoolDef(pCfg, "PowerS4Enabled", &pThis->fS4Enabled, false);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"PowerS4Enabled\""));
+
+ /* query whether S1 power state should save the VM state */
+ rc = CFGMR3QueryBoolDef(pCfg, "EnableSuspendToDisk", &pThis->fSuspendToSavedState, false);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"EnableSuspendToDisk\""));
+
+ /* query whether we are allow CPU hot plugging */
+ rc = CFGMR3QueryBoolDef(pCfg, "CpuHotPlug", &pThis->fCpuHotPlug, false);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"CpuHotPlug\""));
+
+ rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &pThis->fGCEnabled, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"GCEnabled\""));
+
+ rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &pThis->fR0Enabled, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("configuration error: failed to read \"R0Enabled\""));
+
+ /* query serial info */
+ rc = CFGMR3QueryU8Def(pCfg, "Serial0Irq", &pThis->uSerial0Irq, 4);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"Serial0Irq\""));
+
+ rc = CFGMR3QueryU16Def(pCfg, "Serial0IoPortBase", &pThis->uSerial0IoPortBase, 0x3f8);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"Serial0IoPortBase\""));
+
+ /* Serial 1 is enabled, get config data */
+ rc = CFGMR3QueryU8Def(pCfg, "Serial1Irq", &pThis->uSerial1Irq, 3);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"Serial1Irq\""));
+
+ rc = CFGMR3QueryU16Def(pCfg, "Serial1IoPortBase", &pThis->uSerial1IoPortBase, 0x2f8);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"Serial1IoPortBase\""));
+
+ /* Read serial port 2 settings; disabled if CFGM keys do not exist. */
+ rc = CFGMR3QueryU8Def(pCfg, "Serial2Irq", &pThis->uSerial2Irq, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"Serial2Irq\""));
+
+ rc = CFGMR3QueryU16Def(pCfg, "Serial2IoPortBase", &pThis->uSerial2IoPortBase, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"Serial2IoPortBase\""));
+
+ /* Read serial port 3 settings; disabled if CFGM keys do not exist. */
+ rc = CFGMR3QueryU8Def(pCfg, "Serial3Irq", &pThis->uSerial3Irq, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"Serial3Irq\""));
+
+ rc = CFGMR3QueryU16Def(pCfg, "Serial3IoPortBase", &pThis->uSerial3IoPortBase, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"Serial3IoPortBase\""));
+ /*
+ * Query settings for both parallel ports, if the CFGM keys don't exist pretend that
+ * the corresponding parallel port is not enabled.
+ */
+ rc = CFGMR3QueryU8Def(pCfg, "Parallel0Irq", &pThis->uParallel0Irq, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"Parallel0Irq\""));
+
+ rc = CFGMR3QueryU16Def(pCfg, "Parallel0IoPortBase", &pThis->uParallel0IoPortBase, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"Parallel0IoPortBase\""));
+
+ rc = CFGMR3QueryU8Def(pCfg, "Parallel1Irq", &pThis->uParallel1Irq, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"Parallel1Irq\""));
+
+ rc = CFGMR3QueryU16Def(pCfg, "Parallel1IoPortBase", &pThis->uParallel1IoPortBase, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"Parallel1IoPortBase\""));
+
+ /* Try to attach the other CPUs */
+ for (unsigned i = 1; i < pThis->cCpus; i++)
+ {
+ if (pThis->fCpuHotPlug)
+ {
+ PPDMIBASE IBaseTmp;
+ rc = PDMDevHlpDriverAttach(pDevIns, i, &pThis->IBase, &IBaseTmp, "ACPI CPU");
+
+ if (RT_SUCCESS(rc))
+ {
+ VMCPUSET_ADD(&pThis->CpuSetAttached, i);
+ VMCPUSET_ADD(&pThis->CpuSetLocked, i);
+ Log(("acpi: Attached CPU %u\n", i));
+ }
+ else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
+ Log(("acpi: CPU %u not attached yet\n", i));
+ else
+ return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach CPU object\n"));
+ }
+ else
+ {
+ /* CPU is always attached if hot-plug is not enabled. */
+ VMCPUSET_ADD(&pThis->CpuSetAttached, i);
+ VMCPUSET_ADD(&pThis->CpuSetLocked, i);
+ }
+ }
+
+ char *pszOemId = NULL;
+ rc = CFGMR3QueryStringAllocDef(pCfg, "AcpiOemId", &pszOemId, "VBOX ");
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"AcpiOemId\" as string failed"));
+ size_t cbOemId = strlen(pszOemId);
+ if (cbOemId > 6)
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: \"AcpiOemId\" must contain not more than 6 characters"));
+ memset(pThis->au8OemId, ' ', sizeof(pThis->au8OemId));
+ memcpy(pThis->au8OemId, pszOemId, cbOemId);
+ MMR3HeapFree(pszOemId);
+
+ char *pszCreatorId = NULL;
+ rc = CFGMR3QueryStringAllocDef(pCfg, "AcpiCreatorId", &pszCreatorId, "ASL ");
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"AcpiCreatorId\" as string failed"));
+ size_t cbCreatorId = strlen(pszCreatorId);
+ if (cbCreatorId > 4)
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: \"AcpiCreatorId\" must contain not more than 4 characters"));
+ memset(pThis->au8CreatorId, ' ', sizeof(pThis->au8CreatorId));
+ memcpy(pThis->au8CreatorId, pszCreatorId, cbCreatorId);
+ MMR3HeapFree(pszCreatorId);
+
+ rc = CFGMR3QueryU32Def(pCfg, "AcpiCreatorRev", &pThis->u32CreatorRev, RT_H2LE_U32(0x61));
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"AcpiCreatorRev\" as integer failed"));
+ pThis->u32OemRevision = RT_H2LE_U32(0x1);
+
+ /*
+ * Load custom ACPI tables.
+ */
+ char *pszCustBinFile;
+
+ /* Maintain legacy behavior for CustomTable config key.
+ * If present, use it as alias for CustomTable1. */
+ rc = CFGMR3QueryStringAlloc(pCfg, "CustomTable", &pszCustBinFile);
+ if (rc != VERR_CFGM_VALUE_NOT_FOUND)
+ {
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"CustomTable\" as a string failed"));
+ if (!*pszCustBinFile)
+ {
+ MMR3HeapFree(pszCustBinFile);
+ pszCustBinFile = NULL;
+ }
+ else if (pszCustBinFile)
+ {
+ /* Try creating CustomTable0 using legacy value. */
+ rc = CFGMR3InsertString(pCfg, "CustomTable0", pszCustBinFile);
+ if (rc == VERR_CFGM_LEAF_EXISTS)
+ LogRel(("ACPI: Warning: \"CustomTable\" configuration"
+ " setting ignored as \"CustomTable0\" setting exists.\n"));
+ MMR3HeapFree(pszCustBinFile);
+ }
+ }
+
+ /* Total space available for custom ACPI tables
+ * @todo define as appropriate, remove as a magic number, and document
+ * limitation in product manual */
+ uint32_t cbBufAvail = 3072;
+ pThis->cCustTbls = 0;
+
+ const char* custTblConfigKeys[] = {"CustomTable0", "CustomTable1", "CustomTable2", "CustomTable3"};
+ for (unsigned i = 0; i < RT_ELEMENTS(custTblConfigKeys); ++i)
+ {
+ const char* pszConfigKey = custTblConfigKeys[i];
+
+ /*
+ * Get the custom table binary file name.
+ */
+ rc = CFGMR3QueryStringAlloc(pCfg, pszConfigKey, &pszCustBinFile);
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+ {
+ pszCustBinFile = NULL;
+ rc = VINF_SUCCESS;
+ }
+ else if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"CustomTableN\" as a string failed"));
+ else if (!*pszCustBinFile)
+ {
+ MMR3HeapFree(pszCustBinFile);
+ pszCustBinFile = NULL;
+ }
+ /*
+ * Determine the custom table binary size, open specified file in the process.
+ */
+ if (pszCustBinFile)
+ {
+ uint32_t tblIdx = pThis->cCustTbls;
+ rc = acpiR3ReadCustomTable(pDevIns, &(pThis->apu8CustBin[tblIdx]),
+ &(pThis->acbCustBin[tblIdx]), pszCustBinFile, cbBufAvail);
+ LogRel(("ACPI: Reading custom ACPI table(%u) from file '%s' (%d bytes)\n",
+ tblIdx, pszCustBinFile, pThis->acbCustBin[tblIdx]));
+ MMR3HeapFree(pszCustBinFile);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc, N_("Error reading custom ACPI table."));
+ cbBufAvail -= pThis->acbCustBin[tblIdx];
+
+ /* Update custom OEM attributes based on custom table
+ * @todo: is it intended for custom tables to overwrite user provided values above? */
+ ACPITBLHEADER *pTblHdr = (ACPITBLHEADER*)pThis->apu8CustBin[tblIdx];
+ memcpy(&pThis->au8OemId[0], &pTblHdr->au8OemId[0], 6);
+ memcpy(&pThis->au8OemTabId[0], &pTblHdr->au8OemTabId[0], 8);
+ pThis->u32OemRevision = pTblHdr->u32OemRevision;
+ memcpy(&pThis->au8CreatorId[0], &pTblHdr->au8CreatorId[0], 4);
+ pThis->u32CreatorRev = pTblHdr->u32CreatorRev;
+
+ pThis->cCustTbls++;
+ Assert(pThis->cCustTbls <= MAX_CUST_TABLES);
+ }
+ }
+
+ /* Set default PM port base */
+ pThis->uPmIoPortBase = PM_PORT_BASE;
+
+ /* Set default SMBus port base */
+ pThis->uSMBusIoPortBase = SMB_PORT_BASE;
+
+ /*
+ * FDC and SMC try to use the same non-shareable interrupt (6),
+ * enable only one device.
+ */
+ if (pThis->fUseSmc)
+ pThis->fUseFdc = false;
+
+ /*
+ * Plant ACPI tables.
+ */
+ /** @todo Part of this is redone by acpiR3MemSetup, we only need to init the
+ * au8RSDPPage here. However, there should be no harm in doing it
+ * twice, so the lazy bird is taking the quick way out for now. */
+ RTGCPHYS32 GCPhysRsdp = apicR3FindRsdpSpace();
+ if (!GCPhysRsdp)
+ return PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY,
+ N_("Can not find space for RSDP. ACPI is disabled"));
+
+ rc = acpiR3PlantTables(pThis);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ rc = PDMDevHlpROMRegister(pDevIns, GCPhysRsdp, 0x1000, pThis->au8RSDPPage, 0x1000,
+ PGMPHYS_ROM_FLAGS_PERMANENT_BINARY, "ACPI RSDP");
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * Register I/O ports.
+ */
+ rc = acpiR3RegisterPmHandlers(pThis);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ rc = acpiR3RegisterSMBusHandlers(pThis);
+ if (RT_FAILURE(rc))
+ return rc;
+
+#define R(addr, cnt, writer, reader, description) \
+ do { \
+ rc = PDMDevHlpIOPortRegister(pDevIns, addr, cnt, pThis, writer, reader, \
+ NULL, NULL, description); \
+ if (RT_FAILURE(rc)) \
+ return rc; \
+ } while (0)
+ R(SMI_CMD, 1, acpiR3SmiWrite, NULL, "ACPI SMI");
+#ifdef DEBUG_ACPI
+ R(DEBUG_HEX, 1, acpiR3DhexWrite, NULL, "ACPI Debug hex");
+ R(DEBUG_CHR, 1, acpiR3DchrWrite, NULL, "ACPI Debug char");
+#endif
+ R(BAT_INDEX, 1, acpiR3BatIndexWrite, NULL, "ACPI Battery status index");
+ R(BAT_DATA, 1, NULL, acpiR3BatDataRead, "ACPI Battery status data");
+ R(SYSI_INDEX, 1, acpiR3SysInfoIndexWrite, NULL, "ACPI system info index");
+ R(SYSI_DATA, 1, acpiR3SysInfoDataWrite, acpiR3SysInfoDataRead, "ACPI system info data");
+ R(ACPI_RESET_BLK, 1, acpiR3ResetWrite, NULL, "ACPI Reset");
+#undef R
+
+ /*
+ * Create the PM timer.
+ */
+ PTMTIMER pTimer;
+ rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, acpiR3PmTimer, &pThis->dev,
+ TMTIMER_FLAGS_NO_CRIT_SECT, "ACPI PM Timer", &pTimer);
+ AssertRCReturn(rc, rc);
+ pThis->pPmTimerR3 = pTimer;
+ pThis->pPmTimerR0 = TMTimerR0Ptr(pTimer);
+ pThis->pPmTimerRC = TMTimerRCPtr(pTimer);
+
+ rc = TMTimerLock(pTimer, VERR_IGNORED);
+ AssertRCReturn(rc, rc);
+ pThis->u64PmTimerInitial = TMTimerGet(pTimer);
+ acpiR3PmTimerReset(pThis, pThis->u64PmTimerInitial);
+ TMTimerUnlock(pTimer);
+
+ /*
+ * Set up the PCI device.
+ */
+ PCIDevSetVendorId(&pThis->dev, 0x8086); /* Intel */
+ PCIDevSetDeviceId(&pThis->dev, 0x7113); /* 82371AB */
+
+ /* See p. 50 of PIIX4 manual */
+ PCIDevSetCommand(&pThis->dev, PCI_COMMAND_IOACCESS);
+ PCIDevSetStatus(&pThis->dev, 0x0280);
+
+ PCIDevSetRevisionId(&pThis->dev, 0x08);
+
+ PCIDevSetClassProg(&pThis->dev, 0x00);
+ PCIDevSetClassSub(&pThis->dev, 0x80);
+ PCIDevSetClassBase(&pThis->dev, 0x06);
+
+ PCIDevSetHeaderType(&pThis->dev, 0x80);
+
+ PCIDevSetBIST(&pThis->dev, 0x00);
+
+ PCIDevSetInterruptLine(&pThis->dev, SCI_INT);
+ PCIDevSetInterruptPin (&pThis->dev, 0x01);
+
+ Assert((pThis->uPmIoPortBase & 0x003f) == 0);
+ acpiR3PmPCIBIOSFake(pThis);
+
+ Assert((pThis->uSMBusIoPortBase & 0x000f) == 0);
+ acpiR3SMBusPCIBIOSFake(pThis);
+ acpiR3SMBusResetDevice(pThis);
+
+ rc = PDMDevHlpPCIRegister(pDevIns, &pThis->dev);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ PDMDevHlpPCISetConfigCallbacks(pDevIns, &pThis->dev,
+ acpiR3PciConfigRead, &pThis->pfnAcpiPciConfigRead,
+ acpiR3PciConfigWrite, &pThis->pfnAcpiPciConfigWrite);
+
+ /*
+ * Register the saved state.
+ */
+ rc = PDMDevHlpSSMRegister(pDevIns, 8, sizeof(*pThis), acpiR3SaveState, acpiR3LoadState);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * Get the corresponding connector interface
+ */
+ rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "ACPI Driver Port");
+ if (RT_SUCCESS(rc))
+ {
+ pThis->pDrv = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIACPICONNECTOR);
+ if (!pThis->pDrv)
+ return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_MISSING_INTERFACE,
+ N_("LUN #0 doesn't have an ACPI connector interface"));
+ }
+ else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
+ {
+ Log(("acpi: %s/%d: warning: no driver attached to LUN #0!\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ rc = VINF_SUCCESS;
+ }
+ else
+ return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach LUN #0"));
+
+ PDMDevHlpDBGFInfoRegister(pDevIns, "acpi", "ACPI info", acpiR3Info);
+
+ return rc;
+}
+
+/**
+ * The device registration structure.
+ */
+const PDMDEVREG g_DeviceACPI =
+{
+ /* u32Version */
+ PDM_DEVREG_VERSION,
+ /* szName */
+ "acpi",
+ /* szRCMod */
+ "VBoxDDRC.rc",
+ /* szR0Mod */
+ "VBoxDDR0.r0",
+ /* pszDescription */
+ "Advanced Configuration and Power Interface",
+ /* fFlags */
+ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
+ /* fClass */
+ PDM_DEVREG_CLASS_ACPI,
+ /* cMaxInstances */
+ ~0U,
+ /* cbInstance */
+ sizeof(ACPIState),
+ /* pfnConstruct */
+ acpiR3Construct,
+ /* pfnDestruct */
+ acpiR3Destruct,
+ /* pfnRelocate */
+ acpiR3Relocate,
+ /* pfnMemSetup */
+ acpiR3MemSetup,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ acpiR3Reset,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ acpiR3Resume,
+ /* pfnAttach */
+ acpiR3Attach,
+ /* pfnDetach */
+ acpiR3Detach,
+ /* pfnQueryInterface. */
+ NULL,
+ /* pfnInitComplete */
+ NULL,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32VersionEnd */
+ PDM_DEVREG_VERSION
+};
+
+#endif /* IN_RING3 */
+#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
diff --git a/src/VBox/Devices/PC/DevDMA.cpp b/src/VBox/Devices/PC/DevDMA.cpp
new file mode 100644
index 00000000..f239aa23
--- /dev/null
+++ b/src/VBox/Devices/PC/DevDMA.cpp
@@ -0,0 +1,1178 @@
+/* $Id: DevDMA.cpp $ */
+/** @file
+ * DevDMA - DMA Controller Device.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is loosely based on:
+ *
+ * QEMU DMA emulation
+ *
+ * Copyright (c) 2003 Vassili Karpov (malc)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_DMA
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/err.h>
+
+#include <VBox/log.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+
+#include "VBoxDD.h"
+
+
+/** @page pg_dev_dma DMA Overview and notes
+ *
+ * Modern PCs typically emulate AT-compatible DMA. The IBM PC/AT used dual
+ * cascaded 8237A DMA controllers, augmented with a 74LS612 memory mapper.
+ * The 8237As are 8-bit parts, only capable of addressing up to 64KB; the
+ * 74LS612 extends addressing to 24 bits. That leads to well known and
+ * inconvenient DMA limitations:
+ * - DMA can only access physical memory under the 16MB line
+ * - DMA transfers must occur within a 64KB/128KB 'page'
+ *
+ * The 16-bit DMA controller added in the PC/AT shifts all 8237A addresses
+ * left by one, including the control registers addresses. The DMA register
+ * offsets (except for the page registers) are therefore "double spaced".
+ *
+ * Due to the address shifting, the DMA controller decodes more addresses
+ * than are usually documented, with aliasing. See the ICH8 datasheet.
+ *
+ * In the IBM PC and PC/XT, DMA channel 0 was used for memory refresh, thus
+ * preventing the use of memory-to-memory DMA transfers (which use channels
+ * 0 and 1). In the PC/AT, memory-to-memory DMA was theoretically possible.
+ * However, it would transfer a single byte at a time, while the CPU can
+ * transfer two (on a 286) or four (on a 386+) bytes at a time. On many
+ * compatibles, memory-to-memory DMA is not even implemented at all, and
+ * therefore has no practical use.
+ *
+ * Auto-init mode is handled implicitly; a device's transfer handler may
+ * return an end count lower than the start count.
+ *
+ * Naming convention: 'channel' refers to a system-wide DMA channel (0-7)
+ * while 'chidx' refers to a DMA channel index within a controller (0-3).
+ *
+ * References:
+ * - IBM Personal Computer AT Technical Reference, 1984
+ * - Intel 8237A-5 Datasheet, 1993
+ * - Frank van Gilluwe, The Undocumented PC, 1994
+ * - OPTi 82C206 Data Book, 1996 (or Chips & Tech 82C206)
+ * - Intel ICH8 Datasheet, 2007
+ */
+
+
+/* Saved state versions. */
+#define DMA_SAVESTATE_OLD 1 /* The original saved state. */
+#define DMA_SAVESTATE_CURRENT 2 /* The new and improved saved state. */
+
+/* State information for a single DMA channel. */
+typedef struct {
+ RTR3PTR pvUser; /* User specific context. */
+ R3PTRTYPE(PFNDMATRANSFERHANDLER) pfnXferHandler; /* Transfer handler for channel. */
+ uint16_t u16BaseAddr; /* Base address for transfers. */
+ uint16_t u16BaseCount; /* Base count for transfers. */
+ uint16_t u16CurAddr; /* Current address. */
+ uint16_t u16CurCount; /* Current count. */
+ uint8_t u8Mode; /* Channel mode. */
+ uint8_t abPadding[7];
+} DMAChannel;
+
+/* State information for a DMA controller (DMA8 or DMA16). */
+typedef struct {
+ DMAChannel ChState[4]; /* Per-channel state. */
+ uint8_t au8Page[8]; /* Page registers (A16-A23). */
+ uint8_t au8PageHi[8]; /* High page registers (A24-A31). */
+ uint8_t u8Command; /* Command register. */
+ uint8_t u8Status; /* Status register. */
+ uint8_t u8Mask; /* Mask register. */
+ uint8_t u8Temp; /* Temporary (mem/mem) register. */
+ uint8_t u8ModeCtr; /* Mode register counter for reads. */
+ bool fHiByte; /* Byte pointer (T/F -> high/low). */
+ uint8_t abPadding0[2];
+ uint32_t is16bit; /* True for 16-bit DMA. */
+ uint8_t abPadding1[4];
+} DMAControl;
+
+/* Complete DMA state information. */
+typedef struct {
+ PPDMDEVINSR3 pDevIns; /* Device instance. */
+ R3PTRTYPE(PCPDMDMACHLP) pHlp; /* PDM DMA helpers. */
+ DMAControl DMAC[2]; /* Two DMA controllers. */
+ bool fRZEnabled;
+ uint8_t abPadding[7];
+} DMAState;
+
+/* DMA command register bits. */
+enum {
+ CMD_MEMTOMEM = 0x01, /* Enable mem-to-mem trasfers. */
+ CMD_ADRHOLD = 0x02, /* Address hold for mem-to-mem. */
+ CMD_DISABLE = 0x04, /* Disable controller. */
+ CMD_COMPRTIME = 0x08, /* Compressed timing. */
+ CMD_ROTPRIO = 0x10, /* Rotating priority. */
+ CMD_EXTWR = 0x20, /* Extended write. */
+ CMD_DREQHI = 0x40, /* DREQ is active high if set. */
+ CMD_DACKHI = 0x80, /* DACK is active high if set. */
+ CMD_UNSUPPORTED = CMD_MEMTOMEM | CMD_ADRHOLD | CMD_COMPRTIME
+ | CMD_EXTWR | CMD_DREQHI | CMD_DACKHI
+};
+
+/* DMA control register offsets for read accesses. */
+enum {
+ CTL_R_STAT, /* Read status registers. */
+ CTL_R_DMAREQ, /* Read DRQ register. */
+ CTL_R_CMD, /* Read command register. */
+ CTL_R_MODE, /* Read mode register. */
+ CTL_R_SETBPTR, /* Set byte pointer flip-flop. */
+ CTL_R_TEMP, /* Read temporary register. */
+ CTL_R_CLRMODE, /* Clear mode register counter. */
+ CTL_R_MASK /* Read all DRQ mask bits. */
+};
+
+/* DMA control register offsets for read accesses. */
+enum {
+ CTL_W_CMD, /* Write command register. */
+ CTL_W_DMAREQ, /* Write DRQ register. */
+ CTL_W_MASKONE, /* Write single DRQ mask bit. */
+ CTL_W_MODE, /* Write mode register. */
+ CTL_W_CLRBPTR, /* Clear byte pointer flip-flop. */
+ CTL_W_MASTRCLR, /* Master clear. */
+ CTL_W_CLRMASK, /* Clear all DRQ mask bits. */
+ CTL_W_MASK /* Write all DRQ mask bits. */
+};
+
+/* DMA transfer modes. */
+enum {
+ DMODE_DEMAND, /* Demand transfer mode. */
+ DMODE_SINGLE, /* Single transfer mode. */
+ DMODE_BLOCK, /* Block transfer mode. */
+ DMODE_CASCADE /* Cascade mode. */
+};
+
+/* DMA transfer types. */
+enum {
+ DTYPE_VERIFY, /* Verify transfer type. */
+ DTYPE_WRITE, /* Write transfer type. */
+ DTYPE_READ, /* Read transfer type. */
+ DTYPE_ILLEGAL /* Undefined. */
+};
+
+#ifndef VBOX_DEVICE_STRUCT_TESTCASE
+
+
+/* Convert DMA channel number (0-7) to controller number (0-1). */
+#define DMACH2C(c) (c < 4 ? 0 : 1)
+
+#ifdef LOG_ENABLED
+static int const g_aiDmaChannelMap[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
+/* Map a DMA page register offset (0-7) to channel index (0-3). */
+# define DMAPG2CX(c) (g_aiDmaChannelMap[c])
+#endif
+
+#ifdef IN_RING3
+static int const g_aiDmaMapChannel[4] = {7, 3, 1, 2};
+/* Map a channel index (0-3) to DMA page register offset (0-7). */
+# define DMACX2PG(c) (g_aiDmaMapChannel[c])
+/* Map a channel number (0-7) to DMA page register offset (0-7). */
+# define DMACH2PG(c) (g_aiDmaMapChannel[c & 3])
+#endif
+
+/* Test the decrement bit of mode register. */
+#define IS_MODE_DEC(c) ((c) & 0x20)
+/* Test the auto-init bit of mode register. */
+#define IS_MODE_AI(c) ((c) & 0x10)
+/* Extract the transfer type bits of mode register. */
+#define GET_MODE_XTYP(c) (((c) & 0x0c) >> 2)
+
+
+/* Perform a master clear (reset) on a DMA controller. */
+static void dmaClear(DMAControl *dc)
+{
+ dc->u8Command = 0;
+ dc->u8Status = 0;
+ dc->u8Temp = 0;
+ dc->u8ModeCtr = 0;
+ dc->fHiByte = false;
+ dc->u8Mask = UINT8_MAX;
+}
+
+
+/** Read the byte pointer and flip it. */
+DECLINLINE(bool) dmaReadBytePtr(DMAControl *dc)
+{
+ bool fHighByte = !!dc->fHiByte;
+ dc->fHiByte ^= 1;
+ return fHighByte;
+}
+
+
+/* DMA address registers writes and reads. */
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, Ports 0-7 & 0xc0-0xcf}
+ */
+PDMBOTHCBDECL(int) dmaWriteAddr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t u32, unsigned cb)
+{
+ RT_NOREF(pDevIns);
+ if (cb == 1)
+ {
+ DMAControl *dc = (DMAControl *)pvUser;
+ DMAChannel *ch;
+ int chidx, reg, is_count;
+
+ Assert(!(u32 & ~0xff)); /* Check for garbage in high bits. */
+ reg = (port >> dc->is16bit) & 0x0f;
+ chidx = reg >> 1;
+ is_count = reg & 1;
+ ch = &dc->ChState[chidx];
+ if (dmaReadBytePtr(dc))
+ {
+ /* Write the high byte. */
+ if (is_count)
+ ch->u16BaseCount = RT_MAKE_U16(ch->u16BaseCount, u32);
+ else
+ ch->u16BaseAddr = RT_MAKE_U16(ch->u16BaseAddr, u32);
+
+ ch->u16CurCount = 0;
+ ch->u16CurAddr = ch->u16BaseAddr;
+ }
+ else
+ {
+ /* Write the low byte. */
+ if (is_count)
+ ch->u16BaseCount = RT_MAKE_U16(u32, RT_HIBYTE(ch->u16BaseCount));
+ else
+ ch->u16BaseAddr = RT_MAKE_U16(u32, RT_HIBYTE(ch->u16BaseAddr));
+ }
+ Log2(("dmaWriteAddr: port %#06x, chidx %d, data %#02x\n",
+ port, chidx, u32));
+ }
+ else
+ {
+ /* Likely a guest bug. */
+ Log(("Bad size write to count register %#x (size %d, data %#x)\n",
+ port, cb, u32));
+ }
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, Ports 0-7 & 0xc0-0xcf}
+ */
+PDMBOTHCBDECL(int) dmaReadAddr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb)
+{
+ RT_NOREF(pDevIns);
+ if (cb == 1)
+ {
+ DMAControl *dc = (DMAControl *)pvUser;
+ DMAChannel *ch;
+ int chidx, reg, val, dir;
+ int bptr;
+
+ reg = (port >> dc->is16bit) & 0x0f;
+ chidx = reg >> 1;
+ ch = &dc->ChState[chidx];
+
+ dir = IS_MODE_DEC(ch->u8Mode) ? -1 : 1;
+ if (reg & 1)
+ val = ch->u16BaseCount - ch->u16CurCount;
+ else
+ val = ch->u16CurAddr + ch->u16CurCount * dir;
+
+ bptr = dmaReadBytePtr(dc);
+ *pu32 = RT_LOBYTE(val >> (bptr * 8));
+
+ Log(("Count read: port %#06x, reg %#04x, data %#x\n", port, reg, val));
+ return VINF_SUCCESS;
+ }
+ return VERR_IOM_IOPORT_UNUSED;
+}
+
+/* DMA control registers writes and reads. */
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, Ports 0x8-0xf & 0xd0-0xdf}
+ */
+PDMBOTHCBDECL(int) dmaWriteCtl(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t u32, unsigned cb)
+{
+ RT_NOREF(pDevIns);
+ if (cb == 1)
+ {
+ DMAControl *dc = (DMAControl *)pvUser;
+ int chidx = 0;
+ int reg;
+
+ reg = ((port >> dc->is16bit) & 0x0f) - 8;
+ Assert((reg >= CTL_W_CMD && reg <= CTL_W_MASK));
+ Assert(!(u32 & ~0xff)); /* Check for garbage in high bits. */
+
+ switch (reg) {
+ case CTL_W_CMD:
+ /* Unsupported commands are entirely ignored. */
+ if (u32 & CMD_UNSUPPORTED)
+ {
+ Log(("DMA command %#x is not supported, ignoring!\n", u32));
+ break;
+ }
+ dc->u8Command = u32;
+ break;
+ case CTL_W_DMAREQ:
+ chidx = u32 & 3;
+ if (u32 & 4)
+ dc->u8Status |= 1 << (chidx + 4);
+ else
+ dc->u8Status &= ~(1 << (chidx + 4));
+ dc->u8Status &= ~(1 << chidx); /* Clear TC for channel. */
+ break;
+ case CTL_W_MASKONE:
+ chidx = u32 & 3;
+ if (u32 & 4)
+ dc->u8Mask |= 1 << chidx;
+ else
+ dc->u8Mask &= ~(1 << chidx);
+ break;
+ case CTL_W_MODE:
+ {
+ int op, opmode;
+
+ chidx = u32 & 3;
+ op = (u32 >> 2) & 3;
+ opmode = (u32 >> 6) & 3;
+ Log2(("chidx %d, op %d, %sauto-init, %screment, opmode %d\n",
+ chidx, op, IS_MODE_AI(u32) ? "" : "no ",
+ IS_MODE_DEC(u32) ? "de" : "in", opmode));
+
+ dc->ChState[chidx].u8Mode = u32;
+ break;
+ }
+ case CTL_W_CLRBPTR:
+ dc->fHiByte = false;
+ break;
+ case CTL_W_MASTRCLR:
+ dmaClear(dc);
+ break;
+ case CTL_W_CLRMASK:
+ dc->u8Mask = 0;
+ break;
+ case CTL_W_MASK:
+ dc->u8Mask = u32;
+ break;
+ default:
+ Assert(0);
+ break;
+ }
+ Log(("dmaWriteCtl: port %#06x, chidx %d, data %#02x\n",
+ port, chidx, u32));
+ }
+ else
+ {
+ /* Likely a guest bug. */
+ Log(("Bad size write to controller register %#x (size %d, data %#x)\n",
+ port, cb, u32));
+ }
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, Ports 0x8-0xf & 0xd0-0xdf}
+ */
+PDMBOTHCBDECL(int) dmaReadCtl(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb)
+{
+ RT_NOREF(pDevIns);
+ if (cb == 1)
+ {
+ DMAControl *dc = (DMAControl *)pvUser;
+ uint8_t val = 0;
+ int reg;
+
+ reg = ((port >> dc->is16bit) & 0x0f) - 8;
+ Assert((reg >= CTL_R_STAT && reg <= CTL_R_MASK));
+
+ switch (reg)
+ {
+ case CTL_R_STAT:
+ val = dc->u8Status;
+ dc->u8Status &= 0xf0; /* A read clears all TCs. */
+ break;
+ case CTL_R_DMAREQ:
+ val = (dc->u8Status >> 4) | 0xf0;
+ break;
+ case CTL_R_CMD:
+ val = dc->u8Command;
+ break;
+ case CTL_R_MODE:
+ val = dc->ChState[dc->u8ModeCtr].u8Mode | 3;
+ dc->u8ModeCtr = (dc->u8ModeCtr + 1) & 3;
+ break;
+ case CTL_R_SETBPTR:
+ dc->fHiByte = true;
+ break;
+ case CTL_R_TEMP:
+ val = dc->u8Temp;
+ break;
+ case CTL_R_CLRMODE:
+ dc->u8ModeCtr = 0;
+ break;
+ case CTL_R_MASK:
+ val = dc->u8Mask;
+ break;
+ default:
+ Assert(0);
+ break;
+ }
+
+ Log(("Ctrl read: port %#06x, reg %#04x, data %#x\n", port, reg, val));
+ *pu32 = val;
+
+ return VINF_SUCCESS;
+ }
+ return VERR_IOM_IOPORT_UNUSED;
+}
+
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN,
+ * DMA page registers - Ports 0x80-0x87 & 0x88-0x8f}
+ *
+ * There are 16 R/W page registers for compatibility with the IBM PC/AT; only
+ * some of those registers are used for DMA. The page register accessible via
+ * port 80h may be read to insert small delays or used as a scratch register by
+ * a BIOS.
+ */
+PDMBOTHCBDECL(int) dmaReadPage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb)
+{
+ RT_NOREF(pDevIns);
+ DMAControl *dc = (DMAControl *)pvUser;
+ int reg;
+
+ if (cb == 1)
+ {
+ reg = port & 7;
+ *pu32 = dc->au8Page[reg];
+ Log2(("Read %#x (byte) from page register %#x (channel %d)\n",
+ *pu32, port, DMAPG2CX(reg)));
+ return VINF_SUCCESS;
+ }
+
+ if (cb == 2)
+ {
+ reg = port & 7;
+ *pu32 = dc->au8Page[reg] | (dc->au8Page[(reg + 1) & 7] << 8);
+ Log2(("Read %#x (word) from page register %#x (channel %d)\n",
+ *pu32, port, DMAPG2CX(reg)));
+ return VINF_SUCCESS;
+ }
+
+ return VERR_IOM_IOPORT_UNUSED;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT,
+ * DMA page registers - Ports 0x80-0x87 & 0x88-0x8f}
+ */
+PDMBOTHCBDECL(int) dmaWritePage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t u32, unsigned cb)
+{
+ RT_NOREF(pDevIns);
+ DMAControl *dc = (DMAControl *)pvUser;
+ int reg;
+
+ if (cb == 1)
+ {
+ Assert(!(u32 & ~0xff)); /* Check for garbage in high bits. */
+ reg = port & 7;
+ dc->au8Page[reg] = u32;
+ dc->au8PageHi[reg] = 0; /* Corresponding high page cleared. */
+ Log2(("Wrote %#x to page register %#x (channel %d)\n",
+ u32, port, DMAPG2CX(reg)));
+ }
+ else if (cb == 2)
+ {
+ Assert(!(u32 & ~0xffff)); /* Check for garbage in high bits. */
+ reg = port & 7;
+ dc->au8Page[reg] = u32;
+ dc->au8PageHi[reg] = 0; /* Corresponding high page cleared. */
+ reg = (port + 1) & 7;
+ dc->au8Page[reg] = u32 >> 8;
+ dc->au8PageHi[reg] = 0; /* Corresponding high page cleared. */
+ }
+ else
+ {
+ /* Likely a guest bug. */
+ Log(("Bad size write to page register %#x (size %d, data %#x)\n",
+ port, cb, u32));
+ }
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN,
+ * EISA style high page registers for extending the DMA addresses to cover
+ * the entire 32-bit address space. Ports 0x480-0x487 & 0x488-0x48f}
+ */
+PDMBOTHCBDECL(int) dmaReadHiPage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb)
+{
+ RT_NOREF(pDevIns);
+ if (cb == 1)
+ {
+ DMAControl *dc = (DMAControl *)pvUser;
+ int reg;
+
+ reg = port & 7;
+ *pu32 = dc->au8PageHi[reg];
+ Log2(("Read %#x to from high page register %#x (channel %d)\n",
+ *pu32, port, DMAPG2CX(reg)));
+ return VINF_SUCCESS;
+ }
+ return VERR_IOM_IOPORT_UNUSED;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, Ports 0x480-0x487 & 0x488-0x48f}
+ */
+PDMBOTHCBDECL(int) dmaWriteHiPage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t u32, unsigned cb)
+{
+ RT_NOREF(pDevIns);
+ if (cb == 1)
+ {
+ DMAControl *dc = (DMAControl *)pvUser;
+ int reg;
+
+ Assert(!(u32 & ~0xff)); /* Check for garbage in high bits. */
+ reg = port & 7;
+ dc->au8PageHi[reg] = u32;
+ Log2(("Wrote %#x to high page register %#x (channel %d)\n",
+ u32, port, DMAPG2CX(reg)));
+ }
+ else
+ {
+ /* Likely a guest bug. */
+ Log(("Bad size write to high page register %#x (size %d, data %#x)\n",
+ port, cb, u32));
+ }
+ return VINF_SUCCESS;
+}
+
+
+#ifdef IN_RING3
+
+/** Perform any pending transfers on a single DMA channel. */
+static void dmaRunChannel(DMAState *pThis, int ctlidx, int chidx)
+{
+ DMAControl *dc = &pThis->DMAC[ctlidx];
+ DMAChannel *ch = &dc->ChState[chidx];
+ uint32_t start_cnt, end_cnt;
+ int opmode;
+
+ opmode = (ch->u8Mode >> 6) & 3;
+
+ Log3(("DMA address %screment, mode %d\n",
+ IS_MODE_DEC(ch->u8Mode) ? "de" : "in",
+ ch->u8Mode >> 6));
+
+ /* Addresses and counts are shifted for 16-bit channels. */
+ start_cnt = ch->u16CurCount << dc->is16bit;
+ /* NB: The device is responsible for examining the DMA mode and not
+ * transferring more than it should if auto-init is not in use.
+ */
+ end_cnt = ch->pfnXferHandler(pThis->pDevIns, ch->pvUser, (ctlidx * 4) + chidx,
+ start_cnt, (ch->u16BaseCount + 1) << dc->is16bit);
+ ch->u16CurCount = end_cnt >> dc->is16bit;
+ /* Set the TC (Terminal Count) bit if transfer was completed. */
+ if (ch->u16CurCount == ch->u16BaseCount + 1)
+ switch (opmode)
+ {
+ case DMODE_DEMAND:
+ case DMODE_SINGLE:
+ case DMODE_BLOCK:
+ dc->u8Status |= RT_BIT(chidx);
+ Log3(("TC set for DMA channel %d\n", (ctlidx * 4) + chidx));
+ break;
+ default:
+ break;
+ }
+ Log3(("DMA position %d, size %d\n", end_cnt, (ch->u16BaseCount + 1) << dc->is16bit));
+}
+
+/**
+ * @interface_method_impl{PDMDMAREG,pfnRun}
+ */
+static DECLCALLBACK(bool) dmaRun(PPDMDEVINS pDevIns)
+{
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAControl *dc;
+ int ctlidx, chidx, mask;
+ PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
+
+ /* Run all controllers and channels. */
+ for (ctlidx = 0; ctlidx < 2; ++ctlidx)
+ {
+ dc = &pThis->DMAC[ctlidx];
+
+ /* If controller is disabled, don't even bother. */
+ if (dc->u8Command & CMD_DISABLE)
+ continue;
+
+ for (chidx = 0; chidx < 4; ++chidx)
+ {
+ mask = 1 << chidx;
+ if (!(dc->u8Mask & mask) && (dc->u8Status & (mask << 4)))
+ dmaRunChannel(pThis, ctlidx, chidx);
+ }
+ }
+
+ PDMCritSectLeave(pDevIns->pCritSectRoR3);
+ return 0;
+}
+
+/**
+ * @interface_method_impl{PDMDMAREG,pfnRegister}
+ */
+static DECLCALLBACK(void) dmaRegister(PPDMDEVINS pDevIns, unsigned uChannel,
+ PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
+{
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAChannel *ch = &pThis->DMAC[DMACH2C(uChannel)].ChState[uChannel & 3];
+
+ LogFlow(("dmaRegister: pThis=%p uChannel=%u pfnTransferHandler=%p pvUser=%p\n", pThis, uChannel, pfnTransferHandler, pvUser));
+
+ PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
+ ch->pfnXferHandler = pfnTransferHandler;
+ ch->pvUser = pvUser;
+ PDMCritSectLeave(pDevIns->pCritSectRoR3);
+}
+
+/** Reverse the order of bytes in a memory buffer. */
+static void dmaReverseBuf8(void *buf, unsigned len)
+{
+ uint8_t *pBeg, *pEnd;
+ uint8_t temp;
+
+ pBeg = (uint8_t *)buf;
+ pEnd = pBeg + len - 1;
+ for (len = len / 2; len; --len)
+ {
+ temp = *pBeg;
+ *pBeg++ = *pEnd;
+ *pEnd-- = temp;
+ }
+}
+
+/** Reverse the order of words in a memory buffer. */
+static void dmaReverseBuf16(void *buf, unsigned len)
+{
+ uint16_t *pBeg, *pEnd;
+ uint16_t temp;
+
+ Assert(!(len & 1));
+ len /= 2; /* Convert to word count. */
+ pBeg = (uint16_t *)buf;
+ pEnd = pBeg + len - 1;
+ for (len = len / 2; len; --len)
+ {
+ temp = *pBeg;
+ *pBeg++ = *pEnd;
+ *pEnd-- = temp;
+ }
+}
+
+/**
+ * @interface_method_impl{PDMDMAREG,pfnReadMemory}
+ */
+static DECLCALLBACK(uint32_t) dmaReadMemory(PPDMDEVINS pDevIns, unsigned uChannel,
+ void *pvBuffer, uint32_t off, uint32_t cbBlock)
+{
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAControl *dc = &pThis->DMAC[DMACH2C(uChannel)];
+ DMAChannel *ch = &dc->ChState[uChannel & 3];
+ uint32_t page, pagehi;
+ uint32_t addr;
+
+ LogFlow(("dmaReadMemory: pThis=%p uChannel=%u pvBuffer=%p off=%u cbBlock=%u\n", pThis, uChannel, pvBuffer, off, cbBlock));
+
+ PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
+
+ /* Build the address for this transfer. */
+ page = dc->au8Page[DMACH2PG(uChannel)] & ~dc->is16bit;
+ pagehi = dc->au8PageHi[DMACH2PG(uChannel)];
+ addr = (pagehi << 24) | (page << 16) | (ch->u16CurAddr << dc->is16bit);
+
+ if (IS_MODE_DEC(ch->u8Mode))
+ {
+ PDMDevHlpPhysRead(pThis->pDevIns, addr - off - cbBlock, pvBuffer, cbBlock);
+ if (dc->is16bit)
+ dmaReverseBuf16(pvBuffer, cbBlock);
+ else
+ dmaReverseBuf8(pvBuffer, cbBlock);
+ }
+ else
+ PDMDevHlpPhysRead(pThis->pDevIns, addr + off, pvBuffer, cbBlock);
+
+ PDMCritSectLeave(pDevIns->pCritSectRoR3);
+ return cbBlock;
+}
+
+/**
+ * @interface_method_impl{PDMDMAREG,pfnWriteMemory}
+ */
+static DECLCALLBACK(uint32_t) dmaWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel,
+ const void *pvBuffer, uint32_t off, uint32_t cbBlock)
+{
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAControl *dc = &pThis->DMAC[DMACH2C(uChannel)];
+ DMAChannel *ch = &dc->ChState[uChannel & 3];
+ uint32_t page, pagehi;
+ uint32_t addr;
+
+ LogFlow(("dmaWriteMemory: pThis=%p uChannel=%u pvBuffer=%p off=%u cbBlock=%u\n", pThis, uChannel, pvBuffer, off, cbBlock));
+ if (GET_MODE_XTYP(ch->u8Mode) == DTYPE_VERIFY)
+ {
+ Log(("DMA verify transfer, ignoring write.\n"));
+ return cbBlock;
+ }
+
+ PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
+
+ /* Build the address for this transfer. */
+ page = dc->au8Page[DMACH2PG(uChannel)] & ~dc->is16bit;
+ pagehi = dc->au8PageHi[DMACH2PG(uChannel)];
+ addr = (pagehi << 24) | (page << 16) | (ch->u16CurAddr << dc->is16bit);
+
+ if (IS_MODE_DEC(ch->u8Mode))
+ {
+ /// @todo This would need a temporary buffer.
+ Assert(0);
+#if 0
+ if (dc->is16bit)
+ dmaReverseBuf16(pvBuffer, cbBlock);
+ else
+ dmaReverseBuf8(pvBuffer, cbBlock);
+#endif
+ PDMDevHlpPhysWrite(pThis->pDevIns, addr - off - cbBlock, pvBuffer, cbBlock);
+ }
+ else
+ PDMDevHlpPhysWrite(pThis->pDevIns, addr + off, pvBuffer, cbBlock);
+
+ PDMCritSectLeave(pDevIns->pCritSectRoR3);
+ return cbBlock;
+}
+
+/**
+ * @interface_method_impl{PDMDMAREG,pfnSetDREQ}
+ */
+static DECLCALLBACK(void) dmaSetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
+{
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAControl *dc = &pThis->DMAC[DMACH2C(uChannel)];
+ int chidx;
+
+ LogFlow(("dmaSetDREQ: pThis=%p uChannel=%u uLevel=%u\n", pThis, uChannel, uLevel));
+
+ PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
+ chidx = uChannel & 3;
+ if (uLevel)
+ dc->u8Status |= 1 << (chidx + 4);
+ else
+ dc->u8Status &= ~(1 << (chidx + 4));
+ PDMCritSectLeave(pDevIns->pCritSectRoR3);
+}
+
+/**
+ * @interface_method_impl{PDMDMAREG,pfnGetChannelMode}
+ */
+static DECLCALLBACK(uint8_t) dmaGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
+{
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+
+ LogFlow(("dmaGetChannelMode: pThis=%p uChannel=%u\n", pThis, uChannel));
+
+ PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
+ uint8_t u8Mode = pThis->DMAC[DMACH2C(uChannel)].ChState[uChannel & 3].u8Mode;
+ PDMCritSectLeave(pDevIns->pCritSectRoR3);
+ return u8Mode;
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnReset}
+ */
+static DECLCALLBACK(void) dmaReset(PPDMDEVINS pDevIns)
+{
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+
+ LogFlow(("dmaReset: pThis=%p\n", pThis));
+
+ /* NB: The page and address registers are unaffected by a reset
+ * and in an undefined state after power-up.
+ */
+ dmaClear(&pThis->DMAC[0]);
+ dmaClear(&pThis->DMAC[1]);
+}
+
+/** Register DMA I/O port handlers. */
+static int dmaIORegister(PPDMDEVINS pDevIns, bool fHighPage)
+{
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAControl *dc8 = &pThis->DMAC[0];
+ DMAControl *dc16 = &pThis->DMAC[1];
+ int rc;
+
+ dc8->is16bit = false;
+ dc16->is16bit = true;
+
+ /* Base and current address for each channel. */
+ rc = PDMDevHlpIOPortRegister(pThis->pDevIns, 0x00, 8, dc8, dmaWriteAddr, dmaReadAddr, NULL, NULL, "DMA8 Address");
+ AssertLogRelRCReturn(rc, rc);
+ rc = PDMDevHlpIOPortRegister(pThis->pDevIns, 0xC0, 16, dc16, dmaWriteAddr, dmaReadAddr, NULL, NULL, "DMA16 Address");
+ AssertLogRelRCReturn(rc, rc);
+
+ /* Control registers for both DMA controllers. */
+ rc = PDMDevHlpIOPortRegister(pThis->pDevIns, 0x08, 8, dc8, dmaWriteCtl, dmaReadCtl, NULL, NULL, "DMA8 Control");
+ AssertLogRelRCReturn(rc, rc);
+ rc = PDMDevHlpIOPortRegister(pThis->pDevIns, 0xD0, 16, dc16, dmaWriteCtl, dmaReadCtl, NULL, NULL, "DMA16 Control");
+ AssertLogRelRCReturn(rc, rc);
+
+ /* Page registers for each channel (plus a few unused ones). */
+ rc = PDMDevHlpIOPortRegister(pThis->pDevIns, 0x80, 8, dc8, dmaWritePage, dmaReadPage, NULL, NULL, "DMA8 Page");
+ AssertLogRelRCReturn(rc, rc);
+ rc = PDMDevHlpIOPortRegister(pThis->pDevIns, 0x88, 8, dc16, dmaWritePage, dmaReadPage, NULL, NULL, "DMA16 Page");
+ AssertLogRelRCReturn(rc, rc);
+
+ /* Optional EISA style high page registers (address bits 24-31). */
+ if (fHighPage)
+ {
+ rc = PDMDevHlpIOPortRegister(pThis->pDevIns, 0x480, 8, dc8, dmaWriteHiPage, dmaReadHiPage, NULL, NULL, "DMA8 Page High");
+ AssertLogRelRCReturn(rc, rc);
+ rc = PDMDevHlpIOPortRegister(pThis->pDevIns, 0x488, 8, dc16, dmaWriteHiPage, dmaReadHiPage, NULL, NULL, "DMA16 Page High");
+ AssertLogRelRCReturn(rc, rc);
+ }
+
+ if (pThis->fRZEnabled)
+ {
+ /*
+ * Ditto for raw-mode.
+ */
+ RTRCPTR RCPtrDc8 = PDMINS_2_DATA_RCPTR(pDevIns) + RT_OFFSETOF(DMAState, DMAC[0]);
+ RTRCPTR RCPtrDc16 = PDMINS_2_DATA_RCPTR(pDevIns) + RT_OFFSETOF(DMAState, DMAC[1]);
+
+ /* Base and current address for each channel. */
+ rc = PDMDevHlpIOPortRegisterRC(pThis->pDevIns, 0x00, 8, RCPtrDc8, "dmaWriteAddr", "dmaReadAddr", NULL, NULL, "DMA8 Address");
+ AssertLogRelRCReturn(rc, rc);
+ rc = PDMDevHlpIOPortRegisterRC(pThis->pDevIns, 0xC0, 16, RCPtrDc16, "dmaWriteAddr", "dmaReadAddr", NULL, NULL, "DMA16 Address");
+ AssertLogRelRCReturn(rc, rc);
+
+ /* Control registers for both DMA controllers. */
+ rc = PDMDevHlpIOPortRegisterRC(pThis->pDevIns, 0x08, 8, RCPtrDc8, "dmaWriteCtl", "dmaReadCtl", NULL, NULL, "DMA8 Control");
+ AssertLogRelRCReturn(rc, rc);
+ rc = PDMDevHlpIOPortRegisterRC(pThis->pDevIns, 0xD0, 16, RCPtrDc16, "dmaWriteCtl", "dmaReadCtl", NULL, NULL, "DMA16 Control");
+ AssertLogRelRCReturn(rc, rc);
+
+ /* Page registers for each channel (plus a few unused ones). */
+ rc = PDMDevHlpIOPortRegisterRC(pThis->pDevIns, 0x80, 8, RCPtrDc8, "dmaWritePage", "dmaReadPage", NULL, NULL, "DMA8 Page");
+ AssertLogRelRCReturn(rc, rc);
+ rc = PDMDevHlpIOPortRegisterRC(pThis->pDevIns, 0x88, 8, RCPtrDc16, "dmaWritePage", "dmaReadPage", NULL, NULL, "DMA16 Page");
+ AssertLogRelRCReturn(rc, rc);
+
+ /* Optional EISA style high page registers (address bits 24-31). */
+ if (fHighPage)
+ {
+ rc = PDMDevHlpIOPortRegisterRC(pThis->pDevIns, 0x480, 8, RCPtrDc8, "dmaWriteHiPage", "dmaReadHiPage", NULL, NULL, "DMA8 Page High");
+ AssertLogRelRCReturn(rc, rc);
+ rc = PDMDevHlpIOPortRegisterRC(pThis->pDevIns, 0x488, 8, RCPtrDc16, "dmaWriteHiPage", "dmaReadHiPage", NULL, NULL, "DMA16 Page High");
+ AssertLogRelRCReturn(rc, rc);
+ }
+
+ /*
+ * Ditto for ring-0.
+ */
+ RTR0PTR R0PtrDc8 = PDMINS_2_DATA_R0PTR(pDevIns) + RT_OFFSETOF(DMAState, DMAC[0]);
+ RTR0PTR R0PtrDc16 = PDMINS_2_DATA_R0PTR(pDevIns) + RT_OFFSETOF(DMAState, DMAC[1]);
+
+ /* Base and current address for each channel. */
+ rc = PDMDevHlpIOPortRegisterR0(pThis->pDevIns, 0x00, 8, R0PtrDc8, "dmaWriteAddr", "dmaReadAddr", NULL, NULL, "DMA8 Address");
+ AssertLogRelRCReturn(rc, rc);
+ rc = PDMDevHlpIOPortRegisterR0(pThis->pDevIns, 0xC0, 16, R0PtrDc16, "dmaWriteAddr", "dmaReadAddr", NULL, NULL, "DMA16 Address");
+ AssertLogRelRCReturn(rc, rc);
+
+ /* Control registers for both DMA controllers. */
+ rc = PDMDevHlpIOPortRegisterR0(pThis->pDevIns, 0x08, 8, R0PtrDc8, "dmaWriteCtl", "dmaReadCtl", NULL, NULL, "DMA8 Control");
+ AssertLogRelRCReturn(rc, rc);
+ rc = PDMDevHlpIOPortRegisterR0(pThis->pDevIns, 0xD0, 16, R0PtrDc16, "dmaWriteCtl", "dmaReadCtl", NULL, NULL, "DMA16 Control");
+ AssertLogRelRCReturn(rc, rc);
+
+ /* Page registers for each channel (plus a few unused ones). */
+ rc = PDMDevHlpIOPortRegisterR0(pThis->pDevIns, 0x80, 8, R0PtrDc8, "dmaWritePage", "dmaReadPage", NULL, NULL, "DMA8 Page");
+ AssertLogRelRCReturn(rc, rc);
+ rc = PDMDevHlpIOPortRegisterR0(pThis->pDevIns, 0x88, 8, R0PtrDc16, "dmaWritePage", "dmaReadPage", NULL, NULL, "DMA16 Page");
+ AssertLogRelRCReturn(rc, rc);
+
+ /* Optional EISA style high page registers (address bits 24-31). */
+ if (fHighPage)
+ {
+ rc = PDMDevHlpIOPortRegisterR0(pThis->pDevIns, 0x480, 8, R0PtrDc8, "dmaWriteHiPage", "dmaReadHiPage", NULL, NULL, "DMA8 Page High");
+ AssertLogRelRCReturn(rc, rc);
+ rc = PDMDevHlpIOPortRegisterR0(pThis->pDevIns, 0x488, 8, R0PtrDc16, "dmaWriteHiPage", "dmaReadHiPage", NULL, NULL, "DMA16 Page High");
+ AssertLogRelRCReturn(rc, rc);
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+static void dmaSaveController(PSSMHANDLE pSSM, DMAControl *dc)
+{
+ int chidx;
+
+ /* Save controller state... */
+ SSMR3PutU8(pSSM, dc->u8Command);
+ SSMR3PutU8(pSSM, dc->u8Mask);
+ SSMR3PutU8(pSSM, dc->fHiByte);
+ SSMR3PutU32(pSSM, dc->is16bit);
+ SSMR3PutU8(pSSM, dc->u8Status);
+ SSMR3PutU8(pSSM, dc->u8Temp);
+ SSMR3PutU8(pSSM, dc->u8ModeCtr);
+ SSMR3PutMem(pSSM, &dc->au8Page, sizeof(dc->au8Page));
+ SSMR3PutMem(pSSM, &dc->au8PageHi, sizeof(dc->au8PageHi));
+
+ /* ...and all four of its channels. */
+ for (chidx = 0; chidx < 4; ++chidx)
+ {
+ DMAChannel *ch = &dc->ChState[chidx];
+
+ SSMR3PutU16(pSSM, ch->u16CurAddr);
+ SSMR3PutU16(pSSM, ch->u16CurCount);
+ SSMR3PutU16(pSSM, ch->u16BaseAddr);
+ SSMR3PutU16(pSSM, ch->u16BaseCount);
+ SSMR3PutU8(pSSM, ch->u8Mode);
+ }
+}
+
+static int dmaLoadController(PSSMHANDLE pSSM, DMAControl *dc, int version)
+{
+ uint8_t u8val;
+ uint32_t u32val;
+ int chidx;
+
+ SSMR3GetU8(pSSM, &dc->u8Command);
+ SSMR3GetU8(pSSM, &dc->u8Mask);
+ SSMR3GetU8(pSSM, &u8val);
+ dc->fHiByte = !!u8val;
+ SSMR3GetU32(pSSM, &dc->is16bit);
+ if (version > DMA_SAVESTATE_OLD)
+ {
+ SSMR3GetU8(pSSM, &dc->u8Status);
+ SSMR3GetU8(pSSM, &dc->u8Temp);
+ SSMR3GetU8(pSSM, &dc->u8ModeCtr);
+ SSMR3GetMem(pSSM, &dc->au8Page, sizeof(dc->au8Page));
+ SSMR3GetMem(pSSM, &dc->au8PageHi, sizeof(dc->au8PageHi));
+ }
+
+ for (chidx = 0; chidx < 4; ++chidx)
+ {
+ DMAChannel *ch = &dc->ChState[chidx];
+
+ if (version == DMA_SAVESTATE_OLD)
+ {
+ /* Convert from 17-bit to 16-bit format. */
+ SSMR3GetU32(pSSM, &u32val);
+ ch->u16CurAddr = u32val >> dc->is16bit;
+ SSMR3GetU32(pSSM, &u32val);
+ ch->u16CurCount = u32val >> dc->is16bit;
+ }
+ else
+ {
+ SSMR3GetU16(pSSM, &ch->u16CurAddr);
+ SSMR3GetU16(pSSM, &ch->u16CurCount);
+ }
+ SSMR3GetU16(pSSM, &ch->u16BaseAddr);
+ SSMR3GetU16(pSSM, &ch->u16BaseCount);
+ SSMR3GetU8(pSSM, &ch->u8Mode);
+ /* Convert from old save state. */
+ if (version == DMA_SAVESTATE_OLD)
+ {
+ /* Remap page register contents. */
+ SSMR3GetU8(pSSM, &u8val);
+ dc->au8Page[DMACX2PG(chidx)] = u8val;
+ SSMR3GetU8(pSSM, &u8val);
+ dc->au8PageHi[DMACX2PG(chidx)] = u8val;
+ /* Throw away dack, eop. */
+ SSMR3GetU8(pSSM, &u8val);
+ SSMR3GetU8(pSSM, &u8val);
+ }
+ }
+ return 0;
+}
+
+/** @callback_method_impl{FNSSMDEVSAVEEXEC} */
+static DECLCALLBACK(int) dmaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+
+ dmaSaveController(pSSM, &pThis->DMAC[0]);
+ dmaSaveController(pSSM, &pThis->DMAC[1]);
+ return VINF_SUCCESS;
+}
+
+/** @callback_method_impl{FNSSMDEVLOADEXEC} */
+static DECLCALLBACK(int) dmaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+{
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+
+ AssertMsgReturn(uVersion <= DMA_SAVESTATE_CURRENT, ("%d\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
+ Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
+
+ dmaLoadController(pSSM, &pThis->DMAC[0], uVersion);
+ return dmaLoadController(pSSM, &pThis->DMAC[1], uVersion);
+}
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnConstruct}
+ */
+static DECLCALLBACK(int) dmaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
+{
+ PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+ RT_NOREF(iInstance);
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+
+ /*
+ * Initialize data.
+ */
+ pThis->pDevIns = pDevIns;
+
+ /*
+ * Validate configuration.
+ */
+ if (!CFGMR3AreValuesValid(pCfg, "RZEnabled\0"
+ "\0")) /* "HighPageEnable\0")) */
+ return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
+
+ bool bHighPage = false;
+#if 0
+ rc = CFGMR3QueryBool(pCfg, "HighPageEnable", &bHighPage);
+ if (RT_FAILURE (rc))
+ return rc;
+#endif
+
+ int rc = CFGMR3QueryBoolDef(pCfg, "RZEnabled", &pThis->fRZEnabled, true);
+ AssertLogRelRCReturn(rc, rc);
+
+ rc = dmaIORegister(pDevIns, bHighPage);
+ AssertLogRelRCReturn(rc, rc);
+
+ dmaReset(pDevIns);
+
+ PDMDMACREG Reg;
+ Reg.u32Version = PDM_DMACREG_VERSION;
+ Reg.pfnRun = dmaRun;
+ Reg.pfnRegister = dmaRegister;
+ Reg.pfnReadMemory = dmaReadMemory;
+ Reg.pfnWriteMemory = dmaWriteMemory;
+ Reg.pfnSetDREQ = dmaSetDREQ;
+ Reg.pfnGetChannelMode = dmaGetChannelMode;
+
+ rc = PDMDevHlpDMACRegister(pDevIns, &Reg, &pThis->pHlp);
+ if (RT_FAILURE (rc))
+ return rc;
+
+ rc = PDMDevHlpSSMRegister(pDevIns, DMA_SAVESTATE_CURRENT, sizeof(*pThis), dmaSaveExec, dmaLoadExec);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * The device registration structure.
+ */
+const PDMDEVREG g_DeviceDMA =
+{
+ /* u32Version */
+ PDM_DEVREG_VERSION,
+ /* szName */
+ "8237A",
+ /* szRCMod */
+ "VBoxDDRC.rc",
+ /* szR0Mod */
+ "VBoxDDR0.r0",
+ /* pszDescription */
+ "DMA Controller Device",
+ /* fFlags */
+ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_R0 | PDM_DEVREG_FLAGS_RC,
+ /* fClass */
+ PDM_DEVREG_CLASS_DMA,
+ /* cMaxInstances */
+ 1,
+ /* cbInstance */
+ sizeof(DMAState),
+ /* pfnConstruct */
+ dmaConstruct,
+ /* pfnDestruct */
+ NULL,
+ /* pfnRelocate */
+ NULL,
+ /* pfnMemSetup */
+ NULL,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ dmaReset,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnAttach */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnQueryInterface. */
+ NULL,
+ /* pfnInitComplete */
+ NULL,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32VersionEnd */
+ PDM_DEVREG_VERSION
+};
+#endif /* IN_RING3 */
+#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
+
diff --git a/src/VBox/Devices/PC/DevFwCommon.cpp b/src/VBox/Devices/PC/DevFwCommon.cpp
new file mode 100644
index 00000000..6bc66c18
--- /dev/null
+++ b/src/VBox/Devices/PC/DevFwCommon.cpp
@@ -0,0 +1,1193 @@
+/* $Id: DevFwCommon.cpp $ */
+/** @file
+ * FwCommon - Shared firmware code (used by DevPcBios & DevEFI).
+ */
+
+/*
+ * Copyright (C) 2009-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV
+#include <VBox/vmm/pdmdev.h>
+
+#include <VBox/log.h>
+#include <VBox/err.h>
+#include <VBox/param.h>
+
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/buildconfig.h>
+#include <iprt/file.h>
+#include <iprt/mem.h>
+#include <iprt/string.h>
+#include <iprt/uuid.h>
+#include <iprt/system.h>
+#include <iprt/cdefs.h>
+
+#include "VBoxDD.h"
+#include "VBoxDD2.h"
+#include "DevFwCommon.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+
+/*
+ * Default DMI data (legacy).
+ * Don't change this information otherwise Windows guests might demand re-activation!
+ */
+
+/* type 0 -- DMI BIOS information */
+static const int32_t g_iDefDmiBIOSReleaseMajor = 0;
+static const int32_t g_iDefDmiBIOSReleaseMinor = 0;
+static const int32_t g_iDefDmiBIOSFirmwareMajor = 0;
+static const int32_t g_iDefDmiBIOSFirmwareMinor = 0;
+static const char *g_pszDefDmiBIOSVendor = "innotek GmbH";
+static const char *g_pszDefDmiBIOSVersion = "VirtualBox";
+static const char *g_pszDefDmiBIOSReleaseDate = "12/01/2006";
+/* type 1 -- DMI system information */
+static const char *g_pszDefDmiSystemVendor = "innotek GmbH";
+static const char *g_pszDefDmiSystemProduct = "VirtualBox";
+static const char *g_pszDefDmiSystemVersion = "1.2";
+static const char *g_pszDefDmiSystemSerial = "0";
+static const char *g_pszDefDmiSystemSKU = "";
+static const char *g_pszDefDmiSystemFamily = "Virtual Machine";
+/* type 2 -- DMI board information */
+static const char *g_pszDefDmiBoardVendor = "Oracle Corporation";
+static const char *g_pszDefDmiBoardProduct = "VirtualBox";
+static const char *g_pszDefDmiBoardVersion = "1.2";
+static const char *g_pszDefDmiBoardSerial = "0";
+static const char *g_pszDefDmiBoardAssetTag = "";
+static const char *g_pszDefDmiBoardLocInChass = "";
+static const int32_t g_iDefDmiBoardBoardType = 0x0A; /* Motherboard */
+/* type 3 -- DMI chassis information */
+static const char *g_pszDefDmiChassisVendor = "Oracle Corporation";
+static const int32_t g_iDefDmiChassisType = 0x01; /* ''other'', no chassis lock present */
+static const char *g_pszDefDmiChassisVersion = "";
+static const char *g_pszDefDmiChassisSerial = "";
+static const char *g_pszDefDmiChassisAssetTag = "";
+/* type 4 -- DMI processor information */
+static const char *g_pszDefDmiProcManufacturer= "GenuineIntel";
+static const char *g_pszDefDmiProcVersion = "Pentium(R) III";
+
+/** The host DMI system product value, for DmiUseHostInfo=1. */
+static char g_szHostDmiSystemProduct[64];
+/** The host DMI system version value, for DmiUseHostInfo=1. */
+static char g_szHostDmiSystemVersion[64];
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+#pragma pack(1)
+
+typedef struct SMBIOSHDR
+{
+ uint8_t au8Signature[4];
+ uint8_t u8Checksum;
+ uint8_t u8Eps;
+ uint8_t u8VersionMajor;
+ uint8_t u8VersionMinor;
+ uint16_t u16MaxStructureSize;
+ uint8_t u8EntryPointRevision;
+ uint8_t u8Pad[5];
+} *SMBIOSHDRPTR;
+AssertCompileSize(SMBIOSHDR, 16);
+
+typedef struct DMIMAINHDR
+{
+ uint8_t au8Signature[5];
+ uint8_t u8Checksum;
+ uint16_t u16TablesLength;
+ uint32_t u32TableBase;
+ uint16_t u16TableEntries;
+ uint8_t u8TableVersion;
+} *DMIMAINHDRPTR;
+AssertCompileSize(DMIMAINHDR, 15);
+
+AssertCompile(sizeof(SMBIOSHDR) + sizeof(DMIMAINHDR) <= VBOX_DMI_HDR_SIZE);
+
+/** DMI header */
+typedef struct DMIHDR
+{
+ uint8_t u8Type;
+ uint8_t u8Length;
+ uint16_t u16Handle;
+} *PDMIHDR;
+AssertCompileSize(DMIHDR, 4);
+
+/** DMI BIOS information (Type 0) */
+typedef struct DMIBIOSINF
+{
+ DMIHDR header;
+ uint8_t u8Vendor;
+ uint8_t u8Version;
+ uint16_t u16Start;
+ uint8_t u8Release;
+ uint8_t u8ROMSize;
+ uint64_t u64Characteristics;
+ uint8_t u8CharacteristicsByte1;
+ uint8_t u8CharacteristicsByte2;
+ uint8_t u8ReleaseMajor;
+ uint8_t u8ReleaseMinor;
+ uint8_t u8FirmwareMajor;
+ uint8_t u8FirmwareMinor;
+} *PDMIBIOSINF;
+AssertCompileSize(DMIBIOSINF, 0x18);
+
+/** DMI system information (Type 1) */
+typedef struct DMISYSTEMINF
+{
+ DMIHDR header;
+ uint8_t u8Manufacturer;
+ uint8_t u8ProductName;
+ uint8_t u8Version;
+ uint8_t u8SerialNumber;
+ uint8_t au8Uuid[16];
+ uint8_t u8WakeupType;
+ uint8_t u8SKUNumber;
+ uint8_t u8Family;
+} *PDMISYSTEMINF;
+AssertCompileSize(DMISYSTEMINF, 0x1b);
+
+/** DMI board (or module) information (Type 2) */
+typedef struct DMIBOARDINF
+{
+ DMIHDR header;
+ uint8_t u8Manufacturer;
+ uint8_t u8Product;
+ uint8_t u8Version;
+ uint8_t u8SerialNumber;
+ uint8_t u8AssetTag;
+ uint8_t u8FeatureFlags;
+ uint8_t u8LocationInChass;
+ uint16_t u16ChassisHandle;
+ uint8_t u8BoardType;
+ uint8_t u8cObjectHandles;
+} *PDMIBOARDINF;
+AssertCompileSize(DMIBOARDINF, 0x0f);
+
+/** DMI system enclosure or chassis type (Type 3) */
+typedef struct DMICHASSIS
+{
+ DMIHDR header;
+ uint8_t u8Manufacturer;
+ uint8_t u8Type;
+ uint8_t u8Version;
+ uint8_t u8SerialNumber;
+ uint8_t u8AssetTag;
+ uint8_t u8BootupState;
+ uint8_t u8PowerSupplyState;
+ uint8_t u8ThermalState;
+ uint8_t u8SecurityStatus;
+ /* v2.3+, currently not supported */
+ uint32_t u32OEMdefined;
+ uint8_t u8Height;
+ uint8_t u8NumPowerChords;
+ uint8_t u8ContElems;
+ uint8_t u8ContElemRecLen;
+} *PDMICHASSIS;
+AssertCompileSize(DMICHASSIS, 0x15);
+
+/** DMI processor information (Type 4) */
+typedef struct DMIPROCESSORINF
+{
+ DMIHDR header;
+ uint8_t u8SocketDesignation;
+ uint8_t u8ProcessorType;
+ uint8_t u8ProcessorFamily;
+ uint8_t u8ProcessorManufacturer;
+ uint64_t u64ProcessorID;
+ uint8_t u8ProcessorVersion;
+ uint8_t u8Voltage;
+ uint16_t u16ExternalClock;
+ uint16_t u16MaxSpeed;
+ uint16_t u16CurrentSpeed;
+ uint8_t u8Status;
+ uint8_t u8ProcessorUpgrade;
+ /* v2.1+ */
+ uint16_t u16L1CacheHandle;
+ uint16_t u16L2CacheHandle;
+ uint16_t u16L3CacheHandle;
+ /* v2.3+ */
+ uint8_t u8SerialNumber;
+ uint8_t u8AssetTag;
+ uint8_t u8PartNumber;
+ /* v2.5+ */
+ uint8_t u8CoreCount;
+ uint8_t u8CoreEnabled;
+ uint8_t u8ThreadCount;
+ uint16_t u16ProcessorCharacteristics;
+ /* v2.6+ */
+ uint16_t u16ProcessorFamily2;
+} *PDMIPROCESSORINF;
+AssertCompileSize(DMIPROCESSORINF, 0x2a);
+
+/** DMI OEM strings (Type 11) */
+typedef struct DMIOEMSTRINGS
+{
+ DMIHDR header;
+ uint8_t u8Count;
+ uint8_t u8VBoxVersion;
+ uint8_t u8VBoxRevision;
+} *PDMIOEMSTRINGS;
+AssertCompileSize(DMIOEMSTRINGS, 0x7);
+
+/** DMI OEM-specific table (Type 128) */
+typedef struct DMIOEMSPECIFIC
+{
+ DMIHDR header;
+ uint32_t u32CpuFreqKHz;
+} *PDMIOEMSPECIFIC;
+AssertCompileSize(DMIOEMSPECIFIC, 0x8);
+
+/** Physical memory array (Type 16) */
+typedef struct DMIRAMARRAY
+{
+ DMIHDR header;
+ uint8_t u8Location;
+ uint8_t u8Use;
+ uint8_t u8MemErrorCorrection;
+ uint32_t u32MaxCapacity;
+ uint16_t u16MemErrorHandle;
+ uint16_t u16NumberOfMemDevices;
+} *PDMIRAMARRAY;
+AssertCompileSize(DMIRAMARRAY, 15);
+
+/** DMI Memory Device (Type 17) */
+typedef struct DMIMEMORYDEV
+{
+ DMIHDR header;
+ uint16_t u16PhysMemArrayHandle;
+ uint16_t u16MemErrHandle;
+ uint16_t u16TotalWidth;
+ uint16_t u16DataWidth;
+ uint16_t u16Size;
+ uint8_t u8FormFactor;
+ uint8_t u8DeviceSet;
+ uint8_t u8DeviceLocator;
+ uint8_t u8BankLocator;
+ uint8_t u8MemoryType;
+ uint16_t u16TypeDetail;
+ uint16_t u16Speed;
+ uint8_t u8Manufacturer;
+ uint8_t u8SerialNumber;
+ uint8_t u8AssetTag;
+ uint8_t u8PartNumber;
+ /* v2.6+ */
+ uint8_t u8Attributes;
+} *PDMIMEMORYDEV;
+AssertCompileSize(DMIMEMORYDEV, 28);
+
+/** MPS floating pointer structure */
+typedef struct MPSFLOATPTR
+{
+ uint8_t au8Signature[4];
+ uint32_t u32MPSAddr;
+ uint8_t u8Length;
+ uint8_t u8SpecRev;
+ uint8_t u8Checksum;
+ uint8_t au8Feature[5];
+} *PMPSFLOATPTR;
+AssertCompileSize(MPSFLOATPTR, 16);
+
+/** MPS config table header */
+typedef struct MPSCFGTBLHEADER
+{
+ uint8_t au8Signature[4];
+ uint16_t u16Length;
+ uint8_t u8SpecRev;
+ uint8_t u8Checksum;
+ uint8_t au8OemId[8];
+ uint8_t au8ProductId[12];
+ uint32_t u32OemTablePtr;
+ uint16_t u16OemTableSize;
+ uint16_t u16EntryCount;
+ uint32_t u32AddrLocalApic;
+ uint16_t u16ExtTableLength;
+ uint8_t u8ExtTableChecksum;
+ uint8_t u8Reserved;
+} *PMPSCFGTBLHEADER;
+AssertCompileSize(MPSCFGTBLHEADER, 0x2c);
+
+/** MPS processor entry */
+typedef struct MPSPROCENTRY
+{
+ uint8_t u8EntryType;
+ uint8_t u8LocalApicId;
+ uint8_t u8LocalApicVersion;
+ uint8_t u8CPUFlags;
+ uint32_t u32CPUSignature;
+ uint32_t u32CPUFeatureFlags;
+ uint32_t u32Reserved[2];
+} *PMPSPROCENTRY;
+AssertCompileSize(MPSPROCENTRY, 20);
+
+/** MPS bus entry */
+typedef struct MPSBUSENTRY
+{
+ uint8_t u8EntryType;
+ uint8_t u8BusId;
+ uint8_t au8BusTypeStr[6];
+} *PMPSBUSENTRY;
+AssertCompileSize(MPSBUSENTRY, 8);
+
+/** MPS I/O-APIC entry */
+typedef struct MPSIOAPICENTRY
+{
+ uint8_t u8EntryType;
+ uint8_t u8Id;
+ uint8_t u8Version;
+ uint8_t u8Flags;
+ uint32_t u32Addr;
+} *PMPSIOAPICENTRY;
+AssertCompileSize(MPSIOAPICENTRY, 8);
+
+/** MPS I/O-Interrupt entry */
+typedef struct MPSIOINTERRUPTENTRY
+{
+ uint8_t u8EntryType;
+ uint8_t u8Type;
+ uint16_t u16Flags;
+ uint8_t u8SrcBusId;
+ uint8_t u8SrcBusIrq;
+ uint8_t u8DstIOAPICId;
+ uint8_t u8DstIOAPICInt;
+} *PMPSIOIRQENTRY;
+AssertCompileSize(MPSIOINTERRUPTENTRY, 8);
+
+#pragma pack()
+
+
+/**
+ * Calculate a simple checksum for the MPS table.
+ *
+ * @param au8Data data
+ * @param u32Length size of data
+ */
+static uint8_t fwCommonChecksum(const uint8_t * const au8Data, uint32_t u32Length)
+{
+ uint8_t u8Sum = 0;
+ for (size_t i = 0; i < u32Length; ++i)
+ u8Sum += au8Data[i];
+ return -u8Sum;
+}
+
+#if 0 /* unused */
+static bool fwCommonChecksumOk(const uint8_t * const au8Data, uint32_t u32Length)
+{
+ uint8_t u8Sum = 0;
+ for (size_t i = 0; i < u32Length; i++)
+ u8Sum += au8Data[i];
+ return (u8Sum == 0);
+}
+#endif
+
+/**
+ * Try fetch the DMI strings from the system.
+ */
+static void fwCommonUseHostDMIStrings(void)
+{
+ int rc;
+
+ rc = RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_NAME,
+ g_szHostDmiSystemProduct, sizeof(g_szHostDmiSystemProduct));
+ if (RT_SUCCESS(rc))
+ {
+ g_pszDefDmiSystemProduct = g_szHostDmiSystemProduct;
+ LogRel(("DMI: Using DmiSystemProduct from host: %s\n", g_szHostDmiSystemProduct));
+ }
+
+ rc = RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_VERSION,
+ g_szHostDmiSystemVersion, sizeof(g_szHostDmiSystemVersion));
+ if (RT_SUCCESS(rc))
+ {
+ g_pszDefDmiSystemVersion = g_szHostDmiSystemVersion;
+ LogRel(("DMI: Using DmiSystemVersion from host: %s\n", g_szHostDmiSystemVersion));
+ }
+}
+
+/**
+ * Construct the DMI table.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pTable Where to create the DMI table.
+ * @param cbMax The maximum size of the DMI table.
+ * @param pUuid Pointer to the UUID to use if the DmiUuid
+ * configuration string isn't present.
+ * @param pCfg The handle to our config node.
+ * @param cCpus Number of VCPUs.
+ * @param pcbDmiTables Size of DMI data in bytes.
+ * @param pcNumDmiTables Number of DMI tables.
+ */
+int FwCommonPlantDMITable(PPDMDEVINS pDevIns, uint8_t *pTable, unsigned cbMax, PCRTUUID pUuid, PCFGMNODE pCfg, uint16_t cCpus, uint16_t *pcbDmiTables, uint16_t *pcNumDmiTables)
+{
+ /*
+ * CFGM Hint!
+ *
+ * The macros below makes it a bit hard to figure out the config options
+ * available here. To get a quick hint, take a look a the CFGM
+ * validation in the calling code (DevEFI.cpp and DevPcBios.cpp).
+ *
+ * 32-bit signed integer CFGM options are read by DMI_READ_CFG_S32, the 2nd
+ * parameter is the CFGM value name.
+ *
+ * Strings are read by DMI_READ_CFG_STR and DMI_READ_CFG_STR_DEF, the 2nd parameter is
+ * the CFGM value name.
+ */
+#define DMI_CHECK_SIZE(cbWant) \
+ { \
+ size_t cbNeed = (size_t)(pszStr + cbWant - (char *)pTable) + 5; /* +1 for strtab terminator +4 for end-of-table entry */ \
+ if (cbNeed > cbMax) \
+ { \
+ if (fHideErrors) \
+ { \
+ LogRel(("One of the DMI strings is too long -- using default DMI data!\n")); \
+ continue; \
+ } \
+ return PDMDevHlpVMSetError(pDevIns, VERR_TOO_MUCH_DATA, RT_SRC_POS, \
+ N_("One of the DMI strings is too long. Check all bios/Dmi* configuration entries. At least %zu bytes are needed but there is no space for more than %d bytes"), cbNeed, cbMax); \
+ } \
+ }
+
+#define DMI_READ_CFG_STR_DEF(variable, name, default_value) \
+ { \
+ if (fForceDefault) \
+ pszTmp = default_value; \
+ else \
+ { \
+ rc = CFGMR3QueryStringDef(pCfg, name, szBuf, sizeof(szBuf), default_value); \
+ if (RT_FAILURE(rc)) \
+ { \
+ if (fHideErrors) \
+ { \
+ LogRel(("Configuration error: Querying \"" name "\" as a string failed -- using default DMI data!\n")); \
+ continue; \
+ } \
+ return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, \
+ N_("Configuration error: Querying \"" name "\" as a string failed")); \
+ } \
+ else if (!strcmp(szBuf, "<EMPTY>")) \
+ pszTmp = ""; \
+ else \
+ pszTmp = szBuf; \
+ } \
+ if (!pszTmp[0]) \
+ variable = 0; /* empty string */ \
+ else \
+ { \
+ variable = iStrNr++; \
+ size_t cStr = strlen(pszTmp) + 1; \
+ DMI_CHECK_SIZE(cStr); \
+ memcpy(pszStr, pszTmp, cStr); \
+ pszStr += cStr ; \
+ } \
+ }
+
+#define DMI_READ_CFG_STR(variable, name) \
+ DMI_READ_CFG_STR_DEF(variable, # name, g_pszDef ## name)
+
+#define DMI_READ_CFG_S32(variable, name) \
+ { \
+ if (fForceDefault) \
+ variable = g_iDef ## name; \
+ else \
+ { \
+ rc = CFGMR3QueryS32Def(pCfg, # name, & variable, g_iDef ## name); \
+ if (RT_FAILURE(rc)) \
+ { \
+ if (fHideErrors) \
+ { \
+ LogRel(("Configuration error: Querying \"" # name "\" as an int failed -- using default DMI data!\n")); \
+ continue; \
+ } \
+ return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, \
+ N_("Configuration error: Querying \"" # name "\" as an int failed")); \
+ } \
+ } \
+ }
+
+#define DMI_START_STRUCT(tbl) \
+ pszStr = (char *)(tbl + 1); \
+ iStrNr = 1;
+
+#define DMI_TERM_STRUCT \
+ { \
+ *pszStr++ = '\0'; /* terminate set of text strings */ \
+ if (iStrNr == 1) \
+ *pszStr++ = '\0'; /* terminate a structure without strings */ \
+ }
+
+ bool fForceDefault = false;
+#ifdef VBOX_BIOS_DMI_FALLBACK
+ /*
+ * There will be two passes. If an error occurs during the first pass, a
+ * message will be written to the release log and we fall back to default
+ * DMI data and start a second pass.
+ */
+ bool fHideErrors = true;
+#else
+ /*
+ * There will be one pass, every error is fatal and will prevent the VM
+ * from starting.
+ */
+ bool fHideErrors = false;
+#endif
+
+ uint8_t fDmiUseHostInfo;
+ int rc = CFGMR3QueryU8Def(pCfg, "DmiUseHostInfo", &fDmiUseHostInfo, 0);
+ if (RT_FAILURE (rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"DmiUseHostInfo\""));
+
+ /* Sync up with host default DMI values */
+ if (fDmiUseHostInfo)
+ fwCommonUseHostDMIStrings();
+
+ uint8_t fDmiExposeMemoryTable;
+ rc = CFGMR3QueryU8Def(pCfg, "DmiExposeMemoryTable", &fDmiExposeMemoryTable, 0);
+ if (RT_FAILURE (rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"DmiExposeMemoryTable\""));
+ uint8_t fDmiExposeProcessorInf;
+ rc = CFGMR3QueryU8Def(pCfg, "DmiExposeProcInf", &fDmiExposeProcessorInf, 0);
+ if (RT_FAILURE (rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"DmiExposeProcInf\""));
+
+ for (;; fForceDefault = true, fHideErrors = false)
+ {
+ int iStrNr;
+ char szBuf[256];
+ char *pszStr = (char *)pTable;
+ char szDmiSystemUuid[64];
+ char *pszDmiSystemUuid;
+ const char *pszTmp;
+
+ if (fForceDefault)
+ pszDmiSystemUuid = NULL;
+ else
+ {
+ rc = CFGMR3QueryString(pCfg, "DmiSystemUuid", szDmiSystemUuid, sizeof(szDmiSystemUuid));
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+ pszDmiSystemUuid = NULL;
+ else if (RT_FAILURE(rc))
+ {
+ if (fHideErrors)
+ {
+ LogRel(("Configuration error: Querying \"DmiSystemUuid\" as a string failed, using default DMI data\n"));
+ continue;
+ }
+ return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+ N_("Configuration error: Querying \"DmiSystemUuid\" as a string failed"));
+ }
+ else
+ pszDmiSystemUuid = szDmiSystemUuid;
+ }
+
+ /*********************************
+ * DMI BIOS information (Type 0) *
+ *********************************/
+ PDMIBIOSINF pBIOSInf = (PDMIBIOSINF)pszStr;
+ DMI_CHECK_SIZE(sizeof(*pBIOSInf));
+
+ pszStr = (char *)&pBIOSInf->u8ReleaseMajor;
+ pBIOSInf->header.u8Length = RT_OFFSETOF(DMIBIOSINF, u8ReleaseMajor);
+
+ /* don't set these fields by default for legacy compatibility */
+ int iDmiBIOSReleaseMajor, iDmiBIOSReleaseMinor;
+ DMI_READ_CFG_S32(iDmiBIOSReleaseMajor, DmiBIOSReleaseMajor);
+ DMI_READ_CFG_S32(iDmiBIOSReleaseMinor, DmiBIOSReleaseMinor);
+ if (iDmiBIOSReleaseMajor != 0 || iDmiBIOSReleaseMinor != 0)
+ {
+ pszStr = (char *)&pBIOSInf->u8FirmwareMajor;
+ pBIOSInf->header.u8Length = RT_OFFSETOF(DMIBIOSINF, u8FirmwareMajor);
+ pBIOSInf->u8ReleaseMajor = iDmiBIOSReleaseMajor;
+ pBIOSInf->u8ReleaseMinor = iDmiBIOSReleaseMinor;
+
+ int iDmiBIOSFirmwareMajor, iDmiBIOSFirmwareMinor;
+ DMI_READ_CFG_S32(iDmiBIOSFirmwareMajor, DmiBIOSFirmwareMajor);
+ DMI_READ_CFG_S32(iDmiBIOSFirmwareMinor, DmiBIOSFirmwareMinor);
+ if (iDmiBIOSFirmwareMajor != 0 || iDmiBIOSFirmwareMinor != 0)
+ {
+ pszStr = (char *)(pBIOSInf + 1);
+ pBIOSInf->header.u8Length = sizeof(DMIBIOSINF);
+ pBIOSInf->u8FirmwareMajor = iDmiBIOSFirmwareMajor;
+ pBIOSInf->u8FirmwareMinor = iDmiBIOSFirmwareMinor;
+ }
+ }
+
+ iStrNr = 1;
+ pBIOSInf->header.u8Type = 0; /* BIOS Information */
+ pBIOSInf->header.u16Handle = 0x0000;
+ DMI_READ_CFG_STR(pBIOSInf->u8Vendor, DmiBIOSVendor);
+ DMI_READ_CFG_STR(pBIOSInf->u8Version, DmiBIOSVersion);
+ pBIOSInf->u16Start = 0xE000;
+ DMI_READ_CFG_STR(pBIOSInf->u8Release, DmiBIOSReleaseDate);
+ pBIOSInf->u8ROMSize = 1; /* 128K */
+ pBIOSInf->u64Characteristics = RT_BIT(4) /* ISA is supported */
+ | RT_BIT(7) /* PCI is supported */
+ | RT_BIT(15) /* Boot from CD is supported */
+ | RT_BIT(16) /* Selectable Boot is supported */
+ | RT_BIT(27) /* Int 9h, 8042 Keyboard services supported */
+ | RT_BIT(30) /* Int 10h, CGA/Mono Video Services supported */
+ /* any more?? */
+ ;
+ pBIOSInf->u8CharacteristicsByte1 = RT_BIT(0) /* ACPI is supported */
+ /* any more?? */
+ ;
+ pBIOSInf->u8CharacteristicsByte2 = 0
+ /* any more?? */
+ ;
+ DMI_TERM_STRUCT;
+
+ /***********************************
+ * DMI system information (Type 1) *
+ ***********************************/
+ PDMISYSTEMINF pSystemInf = (PDMISYSTEMINF)pszStr;
+ DMI_CHECK_SIZE(sizeof(*pSystemInf));
+ DMI_START_STRUCT(pSystemInf);
+ pSystemInf->header.u8Type = 1; /* System Information */
+ pSystemInf->header.u8Length = sizeof(*pSystemInf);
+ pSystemInf->header.u16Handle = 0x0001;
+ DMI_READ_CFG_STR(pSystemInf->u8Manufacturer, DmiSystemVendor);
+ DMI_READ_CFG_STR(pSystemInf->u8ProductName, DmiSystemProduct);
+ DMI_READ_CFG_STR(pSystemInf->u8Version, DmiSystemVersion);
+ DMI_READ_CFG_STR(pSystemInf->u8SerialNumber, DmiSystemSerial);
+
+ RTUUID uuid;
+ if (pszDmiSystemUuid)
+ {
+ rc = RTUuidFromStr(&uuid, pszDmiSystemUuid);
+ if (RT_FAILURE(rc))
+ {
+ if (fHideErrors)
+ {
+ LogRel(("Configuration error: Invalid UUID for DMI tables specified, using default DMI data\n"));
+ continue;
+ }
+ return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+ N_("Configuration error: Invalid UUID for DMI tables specified"));
+ }
+ uuid.Gen.u32TimeLow = RT_H2BE_U32(uuid.Gen.u32TimeLow);
+ uuid.Gen.u16TimeMid = RT_H2BE_U16(uuid.Gen.u16TimeMid);
+ uuid.Gen.u16TimeHiAndVersion = RT_H2BE_U16(uuid.Gen.u16TimeHiAndVersion);
+ pUuid = &uuid;
+ }
+ memcpy(pSystemInf->au8Uuid, pUuid, sizeof(RTUUID));
+
+ pSystemInf->u8WakeupType = 6; /* Power Switch */
+ DMI_READ_CFG_STR(pSystemInf->u8SKUNumber, DmiSystemSKU);
+ DMI_READ_CFG_STR(pSystemInf->u8Family, DmiSystemFamily);
+ DMI_TERM_STRUCT;
+
+ /**********************************
+ * DMI board information (Type 2) *
+ **********************************/
+ PDMIBOARDINF pBoardInf = (PDMIBOARDINF)pszStr;
+ DMI_CHECK_SIZE(sizeof(*pBoardInf));
+ DMI_START_STRUCT(pBoardInf);
+ int iDmiBoardBoardType;
+ pBoardInf->header.u8Type = 2; /* Board Information */
+ pBoardInf->header.u8Length = sizeof(*pBoardInf);
+ pBoardInf->header.u16Handle = 0x0008;
+ DMI_READ_CFG_STR(pBoardInf->u8Manufacturer, DmiBoardVendor);
+ DMI_READ_CFG_STR(pBoardInf->u8Product, DmiBoardProduct);
+ DMI_READ_CFG_STR(pBoardInf->u8Version, DmiBoardVersion);
+ DMI_READ_CFG_STR(pBoardInf->u8SerialNumber, DmiBoardSerial);
+ DMI_READ_CFG_STR(pBoardInf->u8AssetTag, DmiBoardAssetTag);
+ pBoardInf->u8FeatureFlags = RT_BIT(0) /* hosting board, e.g. motherboard */
+ ;
+ DMI_READ_CFG_STR(pBoardInf->u8LocationInChass, DmiBoardLocInChass);
+ pBoardInf->u16ChassisHandle = 0x0003; /* see type 3 */
+ DMI_READ_CFG_S32(iDmiBoardBoardType, DmiBoardBoardType);
+ pBoardInf->u8BoardType = iDmiBoardBoardType;
+ pBoardInf->u8cObjectHandles = 0;
+
+ DMI_TERM_STRUCT;
+
+ /********************************************
+ * DMI System Enclosure or Chassis (Type 3) *
+ ********************************************/
+ PDMICHASSIS pChassis = (PDMICHASSIS)pszStr;
+ DMI_CHECK_SIZE(sizeof(*pChassis));
+ pszStr = (char*)&pChassis->u32OEMdefined;
+ iStrNr = 1;
+#ifdef VBOX_WITH_DMI_CHASSIS
+ pChassis->header.u8Type = 3; /* System Enclosure or Chassis */
+#else
+ pChassis->header.u8Type = 0x7e; /* inactive */
+#endif
+ pChassis->header.u8Length = RT_OFFSETOF(DMICHASSIS, u32OEMdefined);
+ pChassis->header.u16Handle = 0x0003;
+ DMI_READ_CFG_STR(pChassis->u8Manufacturer, DmiChassisVendor);
+ int iDmiChassisType;
+ DMI_READ_CFG_S32(iDmiChassisType, DmiChassisType);
+ pChassis->u8Type = iDmiChassisType;
+ DMI_READ_CFG_STR(pChassis->u8Version, DmiChassisVersion);
+ DMI_READ_CFG_STR(pChassis->u8SerialNumber, DmiChassisSerial);
+ DMI_READ_CFG_STR(pChassis->u8AssetTag, DmiChassisAssetTag);
+ pChassis->u8BootupState = 0x03; /* safe */
+ pChassis->u8PowerSupplyState = 0x03; /* safe */
+ pChassis->u8ThermalState = 0x03; /* safe */
+ pChassis->u8SecurityStatus = 0x03; /* none XXX */
+# if 0
+ /* v2.3+, currently not supported */
+ pChassis->u32OEMdefined = 0;
+ pChassis->u8Height = 0; /* unspecified */
+ pChassis->u8NumPowerChords = 0; /* unspecified */
+ pChassis->u8ContElems = 0; /* no contained elements */
+ pChassis->u8ContElemRecLen = 0; /* no contained elements */
+# endif
+ DMI_TERM_STRUCT;
+
+ /**************************************
+ * DMI Processor Information (Type 4) *
+ **************************************/
+
+ /*
+ * This is just a dummy processor. Should we expose the real guest CPU features
+ * here? Accessing this information at this point is difficult.
+ */
+ char szSocket[32];
+ PDMIPROCESSORINF pProcessorInf = (PDMIPROCESSORINF)pszStr;
+ DMI_CHECK_SIZE(sizeof(*pProcessorInf));
+ DMI_START_STRUCT(pProcessorInf);
+ if (fDmiExposeProcessorInf)
+ pProcessorInf->header.u8Type = 4; /* Processor Information */
+ else
+ pProcessorInf->header.u8Type = 126; /* inactive structure */
+ pProcessorInf->header.u8Length = sizeof(*pProcessorInf);
+ pProcessorInf->header.u16Handle = 0x0007;
+ RTStrPrintf(szSocket, sizeof(szSocket), "Socket #%u", 0);
+ pProcessorInf->u8SocketDesignation = iStrNr++;
+ {
+ size_t cStr = strlen(szSocket) + 1;
+ DMI_CHECK_SIZE(cStr);
+ memcpy(pszStr, szSocket, cStr);
+ pszStr += cStr;
+ }
+ pProcessorInf->u8ProcessorType = 0x03; /* Central Processor */
+ pProcessorInf->u8ProcessorFamily = 0xB1; /* Pentium III with Intel SpeedStep(TM) */
+ DMI_READ_CFG_STR(pProcessorInf->u8ProcessorManufacturer, DmiProcManufacturer);
+
+ pProcessorInf->u64ProcessorID = UINT64_C(0x0FEBFBFF00010676);
+ /* Ext Family ID = 0
+ * Ext Model ID = 2
+ * Processor Type = 0
+ * Family ID = 6
+ * Model = 7
+ * Stepping = 6
+ * Features: FPU, VME, DE, PSE, TSC, MSR, PAE, MCE, CX8,
+ * APIC, SEP, MTRR, PGE, MCA, CMOV, PAT, PSE-36,
+ * CFLSH, DS, ACPI, MMX, FXSR, SSE, SSE2, SS */
+ DMI_READ_CFG_STR(pProcessorInf->u8ProcessorVersion, DmiProcVersion);
+ pProcessorInf->u8Voltage = 0x02; /* 3.3V */
+ pProcessorInf->u16ExternalClock = 0x00; /* unknown */
+ pProcessorInf->u16MaxSpeed = 3000; /* 3GHz */
+ pProcessorInf->u16CurrentSpeed = 3000; /* 3GHz */
+ pProcessorInf->u8Status = RT_BIT(6) /* CPU socket populated */
+ | RT_BIT(0) /* CPU enabled */
+ ;
+ pProcessorInf->u8ProcessorUpgrade = 0x04; /* ZIF Socket */
+ pProcessorInf->u16L1CacheHandle = 0xFFFF; /* not specified */
+ pProcessorInf->u16L2CacheHandle = 0xFFFF; /* not specified */
+ pProcessorInf->u16L3CacheHandle = 0xFFFF; /* not specified */
+ pProcessorInf->u8SerialNumber = 0; /* not specified */
+ pProcessorInf->u8AssetTag = 0; /* not specified */
+ pProcessorInf->u8PartNumber = 0; /* not specified */
+ pProcessorInf->u8CoreCount = cCpus; /* */
+ pProcessorInf->u8CoreEnabled = cCpus;
+ pProcessorInf->u8ThreadCount = 1;
+ pProcessorInf->u16ProcessorCharacteristics
+ = RT_BIT(2); /* 64-bit capable */
+ pProcessorInf->u16ProcessorFamily2 = 0;
+ DMI_TERM_STRUCT;
+
+ /***************************************
+ * DMI Physical Memory Array (Type 16) *
+ ***************************************/
+ uint64_t const cbRamSize = MMR3PhysGetRamSize(PDMDevHlpGetVM(pDevIns));
+
+ PDMIRAMARRAY pMemArray = (PDMIRAMARRAY)pszStr;
+ DMI_CHECK_SIZE(sizeof(*pMemArray));
+ DMI_START_STRUCT(pMemArray);
+ if (fDmiExposeMemoryTable)
+ pMemArray->header.u8Type = 16; /* Physical Memory Array */
+ else
+ pMemArray->header.u8Type = 126; /* inactive structure */
+ pMemArray->header.u8Length = sizeof(*pMemArray);
+ pMemArray->header.u16Handle = 0x0005;
+ pMemArray->u8Location = 0x03; /* Motherboard */
+ pMemArray->u8Use = 0x03; /* System memory */
+ pMemArray->u8MemErrorCorrection = 0x01; /* Other */
+ if (cbRamSize / _1K > INT32_MAX)
+ {
+ /** @todo 2TB-1K limit. In such cases we probably need to provide multiple type-16 descriptors.
+ * Or use 0x8000'0000 = 'capacity unknown'? */
+ AssertLogRelMsgFailed(("DMI: RAM size %#RX64 does not fit into type-16 descriptor, clipping to %#RX64\n",
+ cbRamSize, (uint64_t)INT32_MAX * _1K));
+ pMemArray->u32MaxCapacity = INT32_MAX;
+ }
+ else
+ pMemArray->u32MaxCapacity = (int32_t)(cbRamSize / _1K); /* RAM size in K */
+ pMemArray->u16MemErrorHandle = 0xfffe; /* No error info structure */
+ pMemArray->u16NumberOfMemDevices = 1;
+ DMI_TERM_STRUCT;
+
+ /***************************************
+ * DMI Memory Device (Type 17) *
+ ***************************************/
+ PDMIMEMORYDEV pMemDev = (PDMIMEMORYDEV)pszStr;
+ DMI_CHECK_SIZE(sizeof(*pMemDev));
+ DMI_START_STRUCT(pMemDev);
+ if (fDmiExposeMemoryTable)
+ pMemDev->header.u8Type = 17; /* Memory Device */
+ else
+ pMemDev->header.u8Type = 126; /* inactive structure */
+ pMemDev->header.u8Length = sizeof(*pMemDev);
+ pMemDev->header.u16Handle = 0x0006;
+ pMemDev->u16PhysMemArrayHandle = 0x0005; /* handle of array we belong to */
+ pMemDev->u16MemErrHandle = 0xfffe; /* system doesn't provide this information */
+ pMemDev->u16TotalWidth = 0xffff; /* Unknown */
+ pMemDev->u16DataWidth = 0xffff; /* Unknown */
+ int16_t u16RamSizeM;
+ if (cbRamSize / _1M > INT16_MAX)
+ {
+ /** @todo 32G-1M limit. Provide multiple type-17 descriptors.
+ * The highest bit of u16Size must be 0 to specify 'GB' units / 1 would be 'KB' */
+ AssertLogRelMsgFailed(("DMI: RAM size %#RX64 too big for one type-17 descriptor, clipping to %#RX64\n",
+ cbRamSize, (uint64_t)INT16_MAX * _1M));
+ u16RamSizeM = INT16_MAX;
+ }
+ else
+ u16RamSizeM = (uint16_t)(cbRamSize / _1M);
+ if (u16RamSizeM == 0)
+ u16RamSizeM = 0x400; /* 1G */
+ pMemDev->u16Size = u16RamSizeM; /* RAM size */
+ pMemDev->u8FormFactor = 0x09; /* DIMM */
+ pMemDev->u8DeviceSet = 0x00; /* Not part of a device set */
+ DMI_READ_CFG_STR_DEF(pMemDev->u8DeviceLocator, " ", "DIMM 0");
+ DMI_READ_CFG_STR_DEF(pMemDev->u8BankLocator, " ", "Bank 0");
+ pMemDev->u8MemoryType = 0x03; /* DRAM */
+ pMemDev->u16TypeDetail = 0; /* Nothing special */
+ pMemDev->u16Speed = 1600; /* Unknown, shall be speed in MHz */
+ DMI_READ_CFG_STR(pMemDev->u8Manufacturer, DmiSystemVendor);
+ DMI_READ_CFG_STR_DEF(pMemDev->u8SerialNumber, " ", "00000000");
+ DMI_READ_CFG_STR_DEF(pMemDev->u8AssetTag, " ", "00000000");
+ DMI_READ_CFG_STR_DEF(pMemDev->u8PartNumber, " ", "00000000");
+ pMemDev->u8Attributes = 0; /* Unknown */
+ DMI_TERM_STRUCT;
+
+ /*****************************
+ * DMI OEM strings (Type 11) *
+ *****************************/
+ PDMIOEMSTRINGS pOEMStrings = (PDMIOEMSTRINGS)pszStr;
+ DMI_CHECK_SIZE(sizeof(*pOEMStrings));
+ DMI_START_STRUCT(pOEMStrings);
+#ifdef VBOX_WITH_DMI_OEMSTRINGS
+ pOEMStrings->header.u8Type = 0xb; /* OEM Strings */
+#else
+ pOEMStrings->header.u8Type = 126; /* inactive structure */
+#endif
+ pOEMStrings->header.u8Length = sizeof(*pOEMStrings);
+ pOEMStrings->header.u16Handle = 0x0002;
+ pOEMStrings->u8Count = 2;
+
+ char szTmp[64];
+ RTStrPrintf(szTmp, sizeof(szTmp), "vboxVer_%u.%u.%u",
+ RTBldCfgVersionMajor(), RTBldCfgVersionMinor(), RTBldCfgVersionBuild());
+ DMI_READ_CFG_STR_DEF(pOEMStrings->u8VBoxVersion, "DmiOEMVBoxVer", szTmp);
+ RTStrPrintf(szTmp, sizeof(szTmp), "vboxRev_%u", RTBldCfgRevision());
+ DMI_READ_CFG_STR_DEF(pOEMStrings->u8VBoxRevision, "DmiOEMVBoxRev", szTmp);
+ DMI_TERM_STRUCT;
+
+ /*************************************
+ * DMI OEM specific table (Type 128) *
+ ************************************/
+ PDMIOEMSPECIFIC pOEMSpecific = (PDMIOEMSPECIFIC)pszStr;
+ DMI_CHECK_SIZE(sizeof(*pOEMSpecific));
+ DMI_START_STRUCT(pOEMSpecific);
+ pOEMSpecific->header.u8Type = 0x80; /* OEM specific */
+ pOEMSpecific->header.u8Length = sizeof(*pOEMSpecific);
+ pOEMSpecific->header.u16Handle = 0x0008; /* Just next free handle */
+ pOEMSpecific->u32CpuFreqKHz = RT_H2LE_U32((uint32_t)((uint64_t)TMCpuTicksPerSecond(PDMDevHlpGetVM(pDevIns)) / 1000));
+ DMI_TERM_STRUCT;
+
+ /* End-of-table marker - includes padding to account for fixed table size. */
+ PDMIHDR pEndOfTable = (PDMIHDR)pszStr;
+ pszStr = (char *)(pEndOfTable + 1);
+ pEndOfTable->u8Type = 0x7f;
+
+ pEndOfTable->u8Length = sizeof(*pEndOfTable);
+ pEndOfTable->u16Handle = 0xFEFF;
+ *pcbDmiTables = ((uintptr_t)pszStr - (uintptr_t)pTable) + 2;
+
+ /* We currently plant 10 DMI tables. Update this if tables number changed. */
+ *pcNumDmiTables = 10;
+
+ /* If more fields are added here, fix the size check in DMI_READ_CFG_STR */
+
+ /* Success! */
+ break;
+ }
+
+#undef DMI_READ_CFG_STR
+#undef DMI_READ_CFG_S32
+#undef DMI_CHECK_SIZE
+ return VINF_SUCCESS;
+}
+
+/**
+ * Construct the SMBIOS and DMI headers table pointer at VM construction and
+ * reset.
+ *
+ * @param pDevIns The device instance data.
+ * @param pHdr Pointer to the header destination.
+ * @param cbDmiTables Size of all DMI tables planted in bytes.
+ * @param cNumDmiTables Number of DMI tables planted.
+ */
+void FwCommonPlantSmbiosAndDmiHdrs(PPDMDEVINS pDevIns, uint8_t *pHdr, uint16_t cbDmiTables, uint16_t cNumDmiTables)
+{
+ RT_NOREF(pDevIns);
+
+ struct
+ {
+ struct SMBIOSHDR smbios;
+ struct DMIMAINHDR dmi;
+ }
+ aBiosHeaders =
+ {
+ // The SMBIOS header
+ {
+ { 0x5f, 0x53, 0x4d, 0x5f}, // "_SM_" signature
+ 0x00, // checksum
+ 0x1f, // EPS length, defined by standard
+ VBOX_SMBIOS_MAJOR_VER, // SMBIOS major version
+ VBOX_SMBIOS_MINOR_VER, // SMBIOS minor version
+ VBOX_SMBIOS_MAXSS, // Maximum structure size
+ 0x00, // Entry point revision
+ { 0x00, 0x00, 0x00, 0x00, 0x00 } // padding
+ },
+ // The DMI header
+ {
+ { 0x5f, 0x44, 0x4d, 0x49, 0x5f }, // "_DMI_" signature
+ 0x00, // checksum
+ 0, // DMI tables length
+ VBOX_DMI_TABLE_BASE, // DMI tables base
+ 0, // DMI tables entries
+ VBOX_DMI_TABLE_VER, // DMI version
+ }
+ };
+
+ aBiosHeaders.dmi.u16TablesLength = cbDmiTables;
+ aBiosHeaders.dmi.u16TableEntries = cNumDmiTables;
+ aBiosHeaders.smbios.u8Checksum = fwCommonChecksum((uint8_t*)&aBiosHeaders.smbios, sizeof(aBiosHeaders.smbios));
+ aBiosHeaders.dmi.u8Checksum = fwCommonChecksum((uint8_t*)&aBiosHeaders.dmi, sizeof(aBiosHeaders.dmi));
+
+ memcpy(pHdr, &aBiosHeaders, sizeof(aBiosHeaders));
+}
+
+/**
+ * Construct the MPS table for implanting as a ROM page.
+ *
+ * Only applicable if IOAPIC is active!
+ *
+ * See ``MultiProcessor Specification Version 1.4 (May 1997)'':
+ * ``1.3 Scope
+ * ...
+ * The hardware required to implement the MP specification is kept to a
+ * minimum, as follows:
+ * * One or more processors that are Intel architecture instruction set
+ * compatible, such as the CPUs in the Intel486 or Pentium processor
+ * family.
+ * * One or more APICs, such as the Intel 82489DX Advanced Programmable
+ * Interrupt Controller or the integrated APIC, such as that on the
+ * Intel Pentium 735\\90 and 815\\100 processors, together with a discrete
+ * I/O APIC unit.''
+ * and later:
+ * ``4.3.3 I/O APIC Entries
+ * The configuration table contains one or more entries for I/O APICs.
+ * ...
+ * I/O APIC FLAGS: EN 3:0 1 If zero, this I/O APIC is unusable, and the
+ * operating system should not attempt to access
+ * this I/O APIC.
+ * At least one I/O APIC must be enabled.''
+ *
+ * @param pDevIns The device instance data.
+ * @param pTable Where to write the table.
+ * @param cbMax The maximum size of the MPS table.
+ * @param cCpus The number of guest CPUs.
+ */
+void FwCommonPlantMpsTable(PPDMDEVINS pDevIns, uint8_t *pTable, unsigned cbMax, uint16_t cCpus)
+{
+ RT_NOREF1(cbMax);
+
+ /* configuration table */
+ PMPSCFGTBLHEADER pCfgTab = (MPSCFGTBLHEADER*)pTable;
+ memcpy(pCfgTab->au8Signature, "PCMP", 4);
+ pCfgTab->u8SpecRev = 4; /* 1.4 */
+ memcpy(pCfgTab->au8OemId, "VBOXCPU ", 8);
+ memcpy(pCfgTab->au8ProductId, "VirtualBox ", 12);
+ pCfgTab->u32OemTablePtr = 0;
+ pCfgTab->u16OemTableSize = 0;
+ pCfgTab->u16EntryCount = 0; /* Incremented as we go. */
+ pCfgTab->u32AddrLocalApic = 0xfee00000;
+ pCfgTab->u16ExtTableLength = 0;
+ pCfgTab->u8ExtTableChecksum = 0;
+ pCfgTab->u8Reserved = 0;
+
+ uint32_t u32Eax, u32Ebx, u32Ecx, u32Edx;
+ uint32_t u32CPUSignature = 0x0520; /* default: Pentium 100 */
+ uint32_t u32FeatureFlags = 0x0001; /* default: FPU */
+ PDMDevHlpGetCpuId(pDevIns, 0, &u32Eax, &u32Ebx, &u32Ecx, &u32Edx);
+ if (u32Eax >= 1)
+ {
+ PDMDevHlpGetCpuId(pDevIns, 1, &u32Eax, &u32Ebx, &u32Ecx, &u32Edx);
+ u32CPUSignature = u32Eax & 0xfff;
+ /* Local APIC will be enabled later so override it here. Since we provide
+ * an MP table we have an IOAPIC and therefore a Local APIC. */
+ u32FeatureFlags = u32Edx | X86_CPUID_FEATURE_EDX_APIC;
+ }
+ /* Construct MPS table for each VCPU. */
+ PMPSPROCENTRY pProcEntry = (PMPSPROCENTRY)(pCfgTab+1);
+ for (int i = 0; i < cCpus; i++)
+ {
+ pProcEntry->u8EntryType = 0; /* processor entry */
+ pProcEntry->u8LocalApicId = i;
+ pProcEntry->u8LocalApicVersion = 0x14;
+ pProcEntry->u8CPUFlags = (i == 0 ? 2 /* bootstrap processor */ : 0 /* application processor */) | 1 /* enabled */;
+ pProcEntry->u32CPUSignature = u32CPUSignature;
+ pProcEntry->u32CPUFeatureFlags = u32FeatureFlags;
+ pProcEntry->u32Reserved[0] =
+ pProcEntry->u32Reserved[1] = 0;
+ pProcEntry++;
+ pCfgTab->u16EntryCount++;
+ }
+
+ uint32_t iBusIdIsa = 0;
+ uint32_t iBusIdPci0 = 1;
+
+ /* ISA bus */
+ PMPSBUSENTRY pBusEntry = (PMPSBUSENTRY)pProcEntry;
+ pBusEntry->u8EntryType = 1; /* bus entry */
+ pBusEntry->u8BusId = iBusIdIsa; /* this ID is referenced by the interrupt entries */
+ memcpy(pBusEntry->au8BusTypeStr, "ISA ", 6);
+ pBusEntry++;
+ pCfgTab->u16EntryCount++;
+
+ /* PCI bus */
+ pBusEntry->u8EntryType = 1; /* bus entry */
+ pBusEntry->u8BusId = iBusIdPci0; /* this ID can be referenced by the interrupt entries */
+ memcpy(pBusEntry->au8BusTypeStr, "PCI ", 6);
+ pBusEntry++;
+ pCfgTab->u16EntryCount++;
+
+
+ /* I/O-APIC.
+ * MP spec: "The configuration table contains one or more entries for I/O APICs.
+ * ... At least one I/O APIC must be enabled." */
+ PMPSIOAPICENTRY pIOAPICEntry = (PMPSIOAPICENTRY)(pBusEntry);
+ uint16_t iApicId = 0;
+ pIOAPICEntry->u8EntryType = 2; /* I/O-APIC entry */
+ pIOAPICEntry->u8Id = iApicId; /* this ID is referenced by the interrupt entries */
+ pIOAPICEntry->u8Version = 0x11;
+ pIOAPICEntry->u8Flags = 1 /* enable */;
+ pIOAPICEntry->u32Addr = 0xfec00000;
+ pCfgTab->u16EntryCount++;
+
+ /* Interrupt tables */
+ /* Bus vectors */
+ /* Note: The PIC is currently not routed to the I/O APIC. Therefore we skip
+ * pin 0 on the I/O APIC.
+ */
+ PMPSIOIRQENTRY pIrqEntry = (PMPSIOIRQENTRY)(pIOAPICEntry+1);
+ for (int iPin = 1; iPin < 16; iPin++, pIrqEntry++)
+ {
+ pIrqEntry->u8EntryType = 3; /* I/O interrupt entry */
+ /*
+ * 0 - INT, vectored interrupt,
+ * 3 - ExtINT, vectored interrupt provided by PIC
+ * As we emulate system with both APIC and PIC, it's needed for their coexistence.
+ */
+ pIrqEntry->u8Type = (iPin == 0) ? 3 : 0;
+ pIrqEntry->u16Flags = 0; /* polarity of APIC I/O input signal = conforms to bus,
+ trigger mode = conforms to bus */
+ pIrqEntry->u8SrcBusId = iBusIdIsa; /* ISA bus */
+ /* IRQ0 mapped to pin 2, other are identity mapped */
+ /* If changing, also update PDMIsaSetIrq() and MADT */
+ pIrqEntry->u8SrcBusIrq = (iPin == 2) ? 0 : iPin; /* IRQ on the bus */
+ pIrqEntry->u8DstIOAPICId = iApicId; /* destination IO-APIC */
+ pIrqEntry->u8DstIOAPICInt = iPin; /* pin on destination IO-APIC */
+ pCfgTab->u16EntryCount++;
+ }
+ /* Local delivery */
+ pIrqEntry->u8EntryType = 4; /* Local interrupt entry */
+ pIrqEntry->u8Type = 3; /* ExtINT */
+ pIrqEntry->u16Flags = (1 << 2) | 1; /* active-high, edge-triggered */
+ pIrqEntry->u8SrcBusId = iBusIdIsa;
+ pIrqEntry->u8SrcBusIrq = 0;
+ pIrqEntry->u8DstIOAPICId = 0xff;
+ pIrqEntry->u8DstIOAPICInt = 0;
+ pIrqEntry++;
+ pCfgTab->u16EntryCount++;
+ pIrqEntry->u8EntryType = 4; /* Local interrupt entry */
+ pIrqEntry->u8Type = 1; /* NMI */
+ pIrqEntry->u16Flags = (1 << 2) | 1; /* active-high, edge-triggered */
+ pIrqEntry->u8SrcBusId = iBusIdIsa;
+ pIrqEntry->u8SrcBusIrq = 0;
+ pIrqEntry->u8DstIOAPICId = 0xff;
+ pIrqEntry->u8DstIOAPICInt = 1;
+ pIrqEntry++;
+ pCfgTab->u16EntryCount++;
+
+ pCfgTab->u16Length = (uint8_t*)pIrqEntry - pTable;
+ pCfgTab->u8Checksum = fwCommonChecksum(pTable, pCfgTab->u16Length);
+
+ AssertMsg(pCfgTab->u16Length < cbMax,
+ ("VBOX_MPS_TABLE_SIZE=%d, maximum allowed size is %d",
+ pCfgTab->u16Length, cbMax));
+}
+
+/**
+ * Construct the MPS table pointer at VM construction and reset.
+ *
+ * Only applicable if IOAPIC is active!
+ *
+ * @param pDevIns The device instance data.
+ * @param u32MpTableAddr The MP table physical address.
+ */
+void FwCommonPlantMpsFloatPtr(PPDMDEVINS pDevIns, uint32_t u32MpTableAddr)
+{
+ MPSFLOATPTR floatPtr;
+ floatPtr.au8Signature[0] = '_';
+ floatPtr.au8Signature[1] = 'M';
+ floatPtr.au8Signature[2] = 'P';
+ floatPtr.au8Signature[3] = '_';
+ floatPtr.u32MPSAddr = u32MpTableAddr;
+ floatPtr.u8Length = 1; /* structure size in paragraphs */
+ floatPtr.u8SpecRev = 4; /* MPS revision 1.4 */
+ floatPtr.u8Checksum = 0;
+ floatPtr.au8Feature[0] = 0;
+ floatPtr.au8Feature[1] = 0;
+ floatPtr.au8Feature[2] = 0;
+ floatPtr.au8Feature[3] = 0;
+ floatPtr.au8Feature[4] = 0;
+ floatPtr.u8Checksum = fwCommonChecksum((uint8_t*)&floatPtr, 16);
+ PDMDevHlpPhysWrite(pDevIns, 0x9fff0, &floatPtr, 16);
+}
+
diff --git a/src/VBox/Devices/PC/DevFwCommon.h b/src/VBox/Devices/PC/DevFwCommon.h
new file mode 100644
index 00000000..61d8c333
--- /dev/null
+++ b/src/VBox/Devices/PC/DevFwCommon.h
@@ -0,0 +1,34 @@
+/* $Id: DevFwCommon.h $ */
+/** @file
+ * FwCommon - Shared firmware code, header.
+ */
+
+/*
+ * Copyright (C) 2009-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_INCLUDED_SRC_PC_DevFwCommon_h
+#define VBOX_INCLUDED_SRC_PC_DevFwCommon_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "DevPcBios.h"
+
+/* Plant DMI table */
+int FwCommonPlantDMITable(PPDMDEVINS pDevIns, uint8_t *pTable, unsigned cbMax, PCRTUUID pUuid, PCFGMNODE pCfg, uint16_t cCpus, uint16_t *pcbDmiTables, uint16_t *pcNumDmiTables);
+void FwCommonPlantSmbiosAndDmiHdrs(PPDMDEVINS pDevIns, uint8_t *pHdr, uint16_t cbDmiTables, uint16_t cNumDmiTables);
+
+/* Plant MPS table */
+void FwCommonPlantMpsTable(PPDMDEVINS pDevIns, uint8_t *pTable, unsigned cbMax, uint16_t cCpus);
+void FwCommonPlantMpsFloatPtr(PPDMDEVINS pDevIns, uint32_t u32MpTableAddr);
+
+#endif /* !VBOX_INCLUDED_SRC_PC_DevFwCommon_h */
diff --git a/src/VBox/Devices/PC/DevHPET.cpp b/src/VBox/Devices/PC/DevHPET.cpp
new file mode 100644
index 00000000..95c00ea1
--- /dev/null
+++ b/src/VBox/Devices/PC/DevHPET.cpp
@@ -0,0 +1,1492 @@
+/* $Id: DevHPET.cpp $ */
+/** @file
+ * HPET virtual device - High Precision Event Timer emulation.
+ */
+
+/*
+ * Copyright (C) 2009-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/* This implementation is based on the (generic) Intel IA-PC HPET specification
+ * and the Intel ICH9 datasheet.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_HPET
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/vmm/stam.h>
+#include <VBox/log.h>
+#include <iprt/assert.h>
+#include <iprt/asm-math.h>
+#include <iprt/string.h>
+
+#include "VBoxDD.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+/*
+ * Current limitations:
+ * - not entirely correct time of interrupt, i.e. never
+ * schedule interrupt earlier than in 1ms
+ * - statistics not implemented
+ * - level-triggered mode not implemented
+ */
+
+/** Base address for MMIO.
+ * On ICH9, it is 0xFED0x000 where 'x' is 0-3, default 0. We do not support
+ * relocation as the platform firmware is responsible for configuring the
+ * HPET base address and the OS isn't expected to move it.
+ * WARNING: This has to match the ACPI tables! */
+#define HPET_BASE 0xfed00000
+
+/** HPET reserves a 1K range. */
+#define HPET_BAR_SIZE 0x1000
+
+/** The number of timers for PIIX4 / PIIX3. */
+#define HPET_NUM_TIMERS_PIIX 3 /* Minimal implementation. */
+/** The number of timers for ICH9. */
+#define HPET_NUM_TIMERS_ICH9 4
+
+/** HPET clock period for PIIX4 / PIIX3.
+ * 10000000 femtoseconds == 10ns.
+ */
+#define HPET_CLK_PERIOD_PIIX UINT32_C(10000000)
+
+/** HPET clock period for ICH9.
+ * 69841279 femtoseconds == 69.84 ns (1 / 14.31818MHz).
+ */
+#define HPET_CLK_PERIOD_ICH9 UINT32_C(69841279)
+
+/**
+ * Femtosecods in a nanosecond
+ */
+#define FS_PER_NS 1000000
+
+/** @name Interrupt type
+ * @{ */
+#define HPET_TIMER_TYPE_LEVEL (1 << 1)
+#define HPET_TIMER_TYPE_EDGE (0 << 1)
+/** @} */
+
+/** @name Delivery mode
+ * @{ */
+#define HPET_TIMER_DELIVERY_APIC 0 /**< Delivery through APIC. */
+#define HPET_TIMER_DELIVERY_FSB 1 /**< Delivery through FSB. */
+/** @} */
+
+#define HPET_TIMER_CAP_FSB_INT_DEL (1 << 15)
+#define HPET_TIMER_CAP_PER_INT (1 << 4)
+
+#define HPET_CFG_ENABLE 0x001 /**< ENABLE_CNF */
+#define HPET_CFG_LEGACY 0x002 /**< LEG_RT_CNF */
+
+/** @name Register offsets in HPET space.
+ * @{ */
+#define HPET_ID 0x000 /**< Device ID. */
+#define HPET_PERIOD 0x004 /**< Clock period in femtoseconds. */
+#define HPET_CFG 0x010 /**< Configuration register. */
+#define HPET_STATUS 0x020 /**< Status register. */
+#define HPET_COUNTER 0x0f0 /**< Main HPET counter. */
+/** @} */
+
+/** @name Timer N offsets (within each timer's space).
+ * @{ */
+#define HPET_TN_CFG 0x000 /**< Timer N configuration. */
+#define HPET_TN_CMP 0x008 /**< Timer N comparator. */
+#define HPET_TN_ROUTE 0x010 /**< Timer N interrupt route. */
+/** @} */
+
+#define HPET_CFG_WRITE_MASK 0x3
+
+#define HPET_TN_INT_TYPE RT_BIT_64(1)
+#define HPET_TN_ENABLE RT_BIT_64(2)
+#define HPET_TN_PERIODIC RT_BIT_64(3)
+#define HPET_TN_PERIODIC_CAP RT_BIT_64(4)
+#define HPET_TN_SIZE_CAP RT_BIT_64(5)
+#define HPET_TN_SETVAL RT_BIT_64(6)
+#define HPET_TN_32BIT RT_BIT_64(8)
+#define HPET_TN_INT_ROUTE_MASK UINT64_C(0x3e00)
+#define HPET_TN_CFG_WRITE_MASK UINT64_C(0x3e46)
+#define HPET_TN_INT_ROUTE_SHIFT 9
+#define HPET_TN_INT_ROUTE_CAP_SHIFT 32
+
+#define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
+
+/** Extract the timer count from the capabilities. */
+#define HPET_CAP_GET_TIMERS(a_u32) ( ((a_u32) >> 8) & 0x1f )
+
+/** The version of the saved state. */
+#define HPET_SAVED_STATE_VERSION 2
+/** Empty saved state */
+#define HPET_SAVED_STATE_VERSION_EMPTY 1
+
+
+/**
+ * Acquires the HPET lock or returns.
+ */
+#define DEVHPET_LOCK_RETURN(a_pThis, a_rcBusy) \
+ do { \
+ int rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, (a_rcBusy)); \
+ if (rcLock != VINF_SUCCESS) \
+ return rcLock; \
+ } while (0)
+
+/**
+ * Releases the HPET lock.
+ */
+#define DEVHPET_UNLOCK(a_pThis) \
+ do { PDMCritSectLeave(&(a_pThis)->CritSect); } while (0)
+
+
+/**
+ * Acquires the TM lock and HPET lock, returns on failure.
+ */
+#define DEVHPET_LOCK_BOTH_RETURN(a_pThis, a_rcBusy) \
+ do { \
+ int rcLock = TMTimerLock((a_pThis)->aTimers[0].CTX_SUFF(pTimer), (a_rcBusy)); \
+ if (rcLock != VINF_SUCCESS) \
+ return rcLock; \
+ rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, (a_rcBusy)); \
+ if (rcLock != VINF_SUCCESS) \
+ { \
+ TMTimerUnlock((a_pThis)->aTimers[0].CTX_SUFF(pTimer)); \
+ return rcLock; \
+ } \
+ } while (0)
+
+
+/**
+ * Releases the HPET lock and TM lock.
+ */
+#define DEVHPET_UNLOCK_BOTH(a_pThis) \
+ do { \
+ PDMCritSectLeave(&(a_pThis)->CritSect); \
+ TMTimerUnlock((a_pThis)->aTimers[0].CTX_SUFF(pTimer)); \
+ } while (0)
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * A HPET timer.
+ */
+typedef struct HPETTIMER
+{
+ /** The HPET timer - R3 Ptr. */
+ PTMTIMERR3 pTimerR3;
+ /** Pointer to the instance data - R3 Ptr. */
+ R3PTRTYPE(struct HPET *) pHpetR3;
+
+ /** The HPET timer - R0 Ptr. */
+ PTMTIMERR0 pTimerR0;
+ /** Pointer to the instance data - R0 Ptr. */
+ R0PTRTYPE(struct HPET *) pHpetR0;
+
+ /** The HPET timer - RC Ptr. */
+ PTMTIMERRC pTimerRC;
+ /** Pointer to the instance data - RC Ptr. */
+ RCPTRTYPE(struct HPET *) pHpetRC;
+
+ /** Timer index. */
+ uint8_t idxTimer;
+ /** Wrap. */
+ uint8_t u8Wrap;
+ /** Alignment. */
+ uint32_t alignment0;
+
+ /** @name Memory-mapped, software visible timer registers.
+ * @{ */
+ /** Configuration/capabilities. */
+ uint64_t u64Config;
+ /** Comparator. */
+ uint64_t u64Cmp;
+ /** FSB route, not supported now. */
+ uint64_t u64Fsb;
+ /** @} */
+
+ /** @name Hidden register state.
+ * @{ */
+ /** Last value written to comparator. */
+ uint64_t u64Period;
+ /** @} */
+} HPETTIMER;
+AssertCompileMemberAlignment(HPETTIMER, u64Config, sizeof(uint64_t));
+
+/**
+ * The HPET state.
+ */
+typedef struct HPET
+{
+ /** Pointer to the device instance. - R3 ptr. */
+ PPDMDEVINSR3 pDevInsR3;
+ /** The HPET helpers - R3 Ptr. */
+ PCPDMHPETHLPR3 pHpetHlpR3;
+
+ /** Pointer to the device instance. - R0 ptr. */
+ PPDMDEVINSR0 pDevInsR0;
+ /** The HPET helpers - R0 Ptr. */
+ PCPDMHPETHLPR0 pHpetHlpR0;
+
+ /** Pointer to the device instance. - RC ptr. */
+ PPDMDEVINSRC pDevInsRC;
+ /** The HPET helpers - RC Ptr. */
+ PCPDMHPETHLPRC pHpetHlpRC;
+
+ /** Timer structures. */
+ HPETTIMER aTimers[RT_MAX(HPET_NUM_TIMERS_PIIX, HPET_NUM_TIMERS_ICH9)];
+
+ /** Offset realtive to the virtual sync clock. */
+ uint64_t u64HpetOffset;
+
+ /** @name Memory-mapped, software visible registers
+ * @{ */
+ /** Capabilities. */
+ uint32_t u32Capabilities;
+ /** HPET_PERIOD - . */
+ uint32_t u32Period;
+ /** Configuration. */
+ uint64_t u64HpetConfig;
+ /** Interrupt status register. */
+ uint64_t u64Isr;
+ /** Main counter. */
+ uint64_t u64HpetCounter;
+ /** @} */
+
+ /** Global device lock. */
+ PDMCRITSECT CritSect;
+
+ /** Whether we emulate ICH9 HPET (different frequency & timer count). */
+ bool fIch9;
+ /** Size alignment padding. */
+ uint8_t abPadding0[7];
+} HPET;
+
+
+#ifndef VBOX_DEVICE_STRUCT_TESTCASE
+
+
+DECLINLINE(bool) hpet32bitTimer(HPETTIMER *pHpetTimer)
+{
+ uint64_t u64Cfg = pHpetTimer->u64Config;
+
+ return ((u64Cfg & HPET_TN_SIZE_CAP) == 0) || ((u64Cfg & HPET_TN_32BIT) != 0);
+}
+
+DECLINLINE(uint64_t) hpetInvalidValue(HPETTIMER *pHpetTimer)
+{
+ return hpet32bitTimer(pHpetTimer) ? UINT32_MAX : UINT64_MAX;
+}
+
+DECLINLINE(uint64_t) hpetTicksToNs(HPET *pThis, uint64_t value)
+{
+ return ASMMultU64ByU32DivByU32(value, pThis->u32Period, FS_PER_NS);
+}
+
+DECLINLINE(uint64_t) nsToHpetTicks(HPET const *pThis, uint64_t u64Value)
+{
+ return ASMMultU64ByU32DivByU32(u64Value, FS_PER_NS, pThis->u32Period);
+}
+
+DECLINLINE(uint64_t) hpetGetTicks(HPET const *pThis)
+{
+ /*
+ * We can use any timer to get current time, they all go
+ * with the same speed.
+ */
+ return nsToHpetTicks(pThis,
+ TMTimerGet(pThis->aTimers[0].CTX_SUFF(pTimer))
+ + pThis->u64HpetOffset);
+}
+
+DECLINLINE(uint64_t) hpetUpdateMasked(uint64_t u64NewValue, uint64_t u64OldValue, uint64_t u64Mask)
+{
+ u64NewValue &= u64Mask;
+ u64NewValue |= (u64OldValue & ~u64Mask);
+ return u64NewValue;
+}
+
+DECLINLINE(bool) hpetBitJustSet(uint64_t u64OldValue, uint64_t u64NewValue, uint64_t u64Mask)
+{
+ return !(u64OldValue & u64Mask)
+ && !!(u64NewValue & u64Mask);
+}
+
+DECLINLINE(bool) hpetBitJustCleared(uint64_t u64OldValue, uint64_t u64NewValue, uint64_t u64Mask)
+{
+ return !!(u64OldValue & u64Mask)
+ && !(u64NewValue & u64Mask);
+}
+
+DECLINLINE(uint64_t) hpetComputeDiff(HPETTIMER *pHpetTimer, uint64_t u64Now)
+{
+
+ if (hpet32bitTimer(pHpetTimer))
+ {
+ uint32_t u32Diff;
+
+ u32Diff = (uint32_t)pHpetTimer->u64Cmp - (uint32_t)u64Now;
+ u32Diff = ((int32_t)u32Diff > 0) ? u32Diff : (uint32_t)0;
+ return (uint64_t)u32Diff;
+ }
+ else
+ {
+ uint64_t u64Diff;
+
+ u64Diff = pHpetTimer->u64Cmp - u64Now;
+ u64Diff = ((int64_t)u64Diff > 0) ? u64Diff : (uint64_t)0;
+ return u64Diff;
+ }
+}
+
+
+static void hpetAdjustComparator(HPETTIMER *pHpetTimer, uint64_t u64Now)
+{
+ uint64_t u64Period = pHpetTimer->u64Period;
+
+ if ((pHpetTimer->u64Config & HPET_TN_PERIODIC) && u64Period)
+ {
+ uint64_t cPeriods = (u64Now - pHpetTimer->u64Cmp) / u64Period;
+
+ pHpetTimer->u64Cmp += (cPeriods + 1) * u64Period;
+ }
+}
+
+
+/**
+ * Sets the frequency hint if it's a periodic timer.
+ *
+ * @param pThis The HPET state.
+ * @param pHpetTimer The timer.
+ */
+DECLINLINE(void) hpetTimerSetFrequencyHint(HPET *pThis, HPETTIMER *pHpetTimer)
+{
+ if (pHpetTimer->u64Config & HPET_TN_PERIODIC)
+ {
+ uint64_t const u64Period = pHpetTimer->u64Period;
+ uint32_t const u32Freq = pThis->u32Period;
+ if (u64Period > 0 && u64Period < u32Freq)
+ TMTimerSetFrequencyHint(pHpetTimer->CTX_SUFF(pTimer), u32Freq / (uint32_t)u64Period);
+ }
+}
+
+
+static void hpetProgramTimer(HPETTIMER *pHpetTimer)
+{
+ /* no wrapping on new timers */
+ pHpetTimer->u8Wrap = 0;
+
+ uint64_t u64Ticks = hpetGetTicks(pHpetTimer->CTX_SUFF(pHpet));
+ hpetAdjustComparator(pHpetTimer, u64Ticks);
+
+ uint64_t u64Diff = hpetComputeDiff(pHpetTimer, u64Ticks);
+
+ /*
+ * HPET spec says in one-shot 32-bit mode, generate an interrupt when
+ * counter wraps in addition to an interrupt with comparator match.
+ */
+ if ( hpet32bitTimer(pHpetTimer)
+ && !(pHpetTimer->u64Config & HPET_TN_PERIODIC))
+ {
+ uint32_t u32TillWrap = 0xffffffff - (uint32_t)u64Ticks + 1;
+ if (u32TillWrap < (uint32_t)u64Diff)
+ {
+ Log(("wrap on timer %d: till=%u ticks=%lld diff64=%lld\n",
+ pHpetTimer->idxTimer, u32TillWrap, u64Ticks, u64Diff));
+ u64Diff = u32TillWrap;
+ pHpetTimer->u8Wrap = 1;
+ }
+ }
+
+ /*
+ * HACK ALERT! Avoid killing VM with interrupts.
+ */
+#if 1 /** @todo HACK, rethink, may have negative impact on the guest */
+ if (u64Diff == 0)
+ u64Diff = 100000; /* 1 millisecond */
+#endif
+
+ Log4(("HPET: next IRQ in %lld ticks (%lld ns)\n", u64Diff, hpetTicksToNs(pHpetTimer->CTX_SUFF(pHpet), u64Diff)));
+ TMTimerSetNano(pHpetTimer->CTX_SUFF(pTimer), hpetTicksToNs(pHpetTimer->CTX_SUFF(pHpet), u64Diff));
+ hpetTimerSetFrequencyHint(pHpetTimer->CTX_SUFF(pHpet), pHpetTimer);
+}
+
+
+/* -=-=-=-=-=- Timer register accesses -=-=-=-=-=- */
+
+
+/**
+ * Reads a HPET timer register.
+ *
+ * @returns VBox strict status code.
+ * @param pThis The HPET instance.
+ * @param iTimerNo The timer index.
+ * @param iTimerReg The index of the timer register to read.
+ * @param pu32Value Where to return the register value.
+ *
+ * @remarks ASSUMES the caller holds the HPET lock.
+ */
+static int hpetTimerRegRead32(HPET const *pThis, uint32_t iTimerNo, uint32_t iTimerReg, uint32_t *pu32Value)
+{
+ Assert(PDMCritSectIsOwner(&pThis->CritSect));
+
+ if ( iTimerNo >= HPET_CAP_GET_TIMERS(pThis->u32Capabilities) /* The second check is only to satisfy Parfait; */
+ || iTimerNo >= RT_ELEMENTS(pThis->aTimers) ) /* in practice, the number of configured timers */
+ { /* will always be <= aTimers elements. */
+ LogRelMax(10, ("HPET: Using timer above configured range: %d\n", iTimerNo));
+ *pu32Value = 0;
+ return VINF_SUCCESS;
+ }
+
+ HPETTIMER const *pHpetTimer = &pThis->aTimers[iTimerNo];
+ uint32_t u32Value;
+ switch (iTimerReg)
+ {
+ case HPET_TN_CFG:
+ u32Value = (uint32_t)pHpetTimer->u64Config;
+ Log(("read HPET_TN_CFG on %d: %#x\n", iTimerNo, u32Value));
+ break;
+
+ case HPET_TN_CFG + 4:
+ u32Value = (uint32_t)(pHpetTimer->u64Config >> 32);
+ Log(("read HPET_TN_CFG+4 on %d: %#x\n", iTimerNo, u32Value));
+ break;
+
+ case HPET_TN_CMP:
+ u32Value = (uint32_t)pHpetTimer->u64Cmp;
+ Log(("read HPET_TN_CMP on %d: %#x (%#llx)\n", pHpetTimer->idxTimer, u32Value, pHpetTimer->u64Cmp));
+ break;
+
+ case HPET_TN_CMP + 4:
+ u32Value = (uint32_t)(pHpetTimer->u64Cmp >> 32);
+ Log(("read HPET_TN_CMP+4 on %d: %#x (%#llx)\n", pHpetTimer->idxTimer, u32Value, pHpetTimer->u64Cmp));
+ break;
+
+ case HPET_TN_ROUTE:
+ u32Value = (uint32_t)(pHpetTimer->u64Fsb >> 32); /** @todo Looks wrong, but since it's not supported, who cares. */
+ Log(("read HPET_TN_ROUTE on %d: %#x\n", iTimerNo, u32Value));
+ break;
+
+ default:
+ {
+ LogRelMax(10, ("HPET: Invalid HPET register read %d on %d\n", iTimerReg, pHpetTimer->idxTimer));
+ u32Value = 0;
+ break;
+ }
+ }
+ *pu32Value = u32Value;
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * 32-bit write to a HPET timer register.
+ *
+ * @returns Strict VBox status code.
+ *
+ * @param pThis The HPET state.
+ * @param iTimerNo The timer being written to.
+ * @param iTimerReg The register being written to.
+ * @param u32NewValue The value being written.
+ *
+ * @remarks The caller should not hold the device lock, unless it also holds
+ * the TM lock.
+ */
+static int hpetTimerRegWrite32(HPET *pThis, uint32_t iTimerNo, uint32_t iTimerReg, uint32_t u32NewValue)
+{
+ Assert(!PDMCritSectIsOwner(&pThis->CritSect) || TMTimerIsLockOwner(pThis->aTimers[0].CTX_SUFF(pTimer)));
+
+ if ( iTimerNo >= HPET_CAP_GET_TIMERS(pThis->u32Capabilities)
+ || iTimerNo >= RT_ELEMENTS(pThis->aTimers) ) /* Parfait - see above. */
+ {
+ LogRelMax(10, ("HPET: Using timer above configured range: %d\n", iTimerNo));
+ return VINF_SUCCESS;
+ }
+ HPETTIMER *pHpetTimer = &pThis->aTimers[iTimerNo];
+
+ switch (iTimerReg)
+ {
+ case HPET_TN_CFG:
+ {
+ DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
+ uint64_t u64Mask = HPET_TN_CFG_WRITE_MASK;
+
+ Log(("write HPET_TN_CFG: %d: %x\n", iTimerNo, u32NewValue));
+ if (pHpetTimer->u64Config & HPET_TN_PERIODIC_CAP)
+ u64Mask |= HPET_TN_PERIODIC;
+
+ if (pHpetTimer->u64Config & HPET_TN_SIZE_CAP)
+ u64Mask |= HPET_TN_32BIT;
+ else
+ u32NewValue &= ~HPET_TN_32BIT;
+
+ if (u32NewValue & HPET_TN_32BIT)
+ {
+ Log(("setting timer %d to 32-bit mode\n", iTimerNo));
+ pHpetTimer->u64Cmp = (uint32_t)pHpetTimer->u64Cmp;
+ pHpetTimer->u64Period = (uint32_t)pHpetTimer->u64Period;
+ }
+ if ((u32NewValue & HPET_TN_INT_TYPE) == HPET_TIMER_TYPE_LEVEL)
+ {
+ LogRelMax(10, ("HPET: Level-triggered config not yet supported\n"));
+ AssertFailed();
+ }
+
+ /* We only care about lower 32-bits so far */
+ pHpetTimer->u64Config = hpetUpdateMasked(u32NewValue, pHpetTimer->u64Config, u64Mask);
+ DEVHPET_UNLOCK(pThis);
+ break;
+ }
+
+ case HPET_TN_CFG + 4: /* Interrupt capabilities - read only. */
+ Log(("write HPET_TN_CFG + 4, useless\n"));
+ break;
+
+ case HPET_TN_CMP: /* lower bits of comparator register */
+ {
+ DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
+ Log(("write HPET_TN_CMP on %d: %#x\n", iTimerNo, u32NewValue));
+
+ if (pHpetTimer->u64Config & HPET_TN_PERIODIC)
+ pHpetTimer->u64Period = RT_MAKE_U64(u32NewValue, RT_HI_U32(pHpetTimer->u64Period));
+ pHpetTimer->u64Cmp = RT_MAKE_U64(u32NewValue, RT_HI_U32(pHpetTimer->u64Cmp));
+ pHpetTimer->u64Config &= ~HPET_TN_SETVAL;
+ Log2(("after HPET_TN_CMP cmp=%#llx per=%#llx\n", pHpetTimer->u64Cmp, pHpetTimer->u64Period));
+
+ if (pThis->u64HpetConfig & HPET_CFG_ENABLE)
+ hpetProgramTimer(pHpetTimer);
+ DEVHPET_UNLOCK_BOTH(pThis);
+ break;
+ }
+
+ case HPET_TN_CMP + 4: /* upper bits of comparator register */
+ {
+ DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
+ Log(("write HPET_TN_CMP + 4 on %d: %#x\n", iTimerNo, u32NewValue));
+ if (!hpet32bitTimer(pHpetTimer))
+ {
+ if (pHpetTimer->u64Config & HPET_TN_PERIODIC)
+ pHpetTimer->u64Period = RT_MAKE_U64(RT_LO_U32(pHpetTimer->u64Period), u32NewValue);
+ pHpetTimer->u64Cmp = RT_MAKE_U64(RT_LO_U32(pHpetTimer->u64Cmp), u32NewValue);
+
+ Log2(("after HPET_TN_CMP+4 cmp=%llx per=%llx tmr=%d\n", pHpetTimer->u64Cmp, pHpetTimer->u64Period, iTimerNo));
+
+ pHpetTimer->u64Config &= ~HPET_TN_SETVAL;
+
+ if (pThis->u64HpetConfig & HPET_CFG_ENABLE)
+ hpetProgramTimer(pHpetTimer);
+ }
+ DEVHPET_UNLOCK_BOTH(pThis);
+ break;
+ }
+
+ case HPET_TN_ROUTE:
+ Log(("write HPET_TN_ROUTE\n"));
+ break;
+
+ case HPET_TN_ROUTE + 4:
+ Log(("write HPET_TN_ROUTE + 4\n"));
+ break;
+
+ default:
+ LogRelMax(10, ("HPET: Invalid timer register write: %d\n", iTimerReg));
+ break;
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+/* -=-=-=-=-=- Non-timer register accesses -=-=-=-=-=- */
+
+
+/**
+ * Read a 32-bit HPET register.
+ *
+ * @returns Strict VBox status code.
+ * @param pThis The HPET state.
+ * @param idxReg The register to read.
+ * @param pu32Value Where to return the register value.
+ *
+ * @remarks The caller must not own the device lock if HPET_COUNTER is read.
+ */
+static int hpetConfigRegRead32(HPET *pThis, uint32_t idxReg, uint32_t *pu32Value)
+{
+ Assert(!PDMCritSectIsOwner(&pThis->CritSect) || (idxReg != HPET_COUNTER && idxReg != HPET_COUNTER + 4));
+
+ uint32_t u32Value;
+ switch (idxReg)
+ {
+ case HPET_ID:
+ DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
+ u32Value = pThis->u32Capabilities;
+ DEVHPET_UNLOCK(pThis);
+ Log(("read HPET_ID: %#x\n", u32Value));
+ break;
+
+ case HPET_PERIOD:
+ DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
+ u32Value = pThis->u32Period;
+ DEVHPET_UNLOCK(pThis);
+ Log(("read HPET_PERIOD: %#x\n", u32Value));
+ break;
+
+ case HPET_CFG:
+ DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
+ u32Value = (uint32_t)pThis->u64HpetConfig;
+ DEVHPET_UNLOCK(pThis);
+ Log(("read HPET_CFG: %#x\n", u32Value));
+ break;
+
+ case HPET_CFG + 4:
+ DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
+ u32Value = (uint32_t)(pThis->u64HpetConfig >> 32);
+ DEVHPET_UNLOCK(pThis);
+ Log(("read of HPET_CFG + 4: %#x\n", u32Value));
+ break;
+
+ case HPET_COUNTER:
+ case HPET_COUNTER + 4:
+ {
+ DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
+
+ uint64_t u64Ticks;
+ if (pThis->u64HpetConfig & HPET_CFG_ENABLE)
+ u64Ticks = hpetGetTicks(pThis);
+ else
+ u64Ticks = pThis->u64HpetCounter;
+
+ DEVHPET_UNLOCK_BOTH(pThis);
+
+ /** @todo is it correct? */
+ u32Value = (idxReg == HPET_COUNTER) ? (uint32_t)u64Ticks : (uint32_t)(u64Ticks >> 32);
+ Log(("read HPET_COUNTER: %s part value %x (%#llx)\n",
+ (idxReg == HPET_COUNTER) ? "low" : "high", u32Value, u64Ticks));
+ break;
+ }
+
+ case HPET_STATUS:
+ DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
+ u32Value = (uint32_t)pThis->u64Isr;
+ DEVHPET_UNLOCK(pThis);
+ Log(("read HPET_STATUS: %#x\n", u32Value));
+ break;
+
+ default:
+ Log(("invalid HPET register read: %x\n", idxReg));
+ u32Value = 0;
+ break;
+ }
+
+ *pu32Value = u32Value;
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * 32-bit write to a config register.
+ *
+ * @returns Strict VBox status code.
+ *
+ * @param pThis The HPET state.
+ * @param idxReg The register being written to.
+ * @param u32NewValue The value being written.
+ *
+ * @remarks The caller should not hold the device lock, unless it also holds
+ * the TM lock.
+ */
+static int hpetConfigRegWrite32(HPET *pThis, uint32_t idxReg, uint32_t u32NewValue)
+{
+ Assert(!PDMCritSectIsOwner(&pThis->CritSect) || TMTimerIsLockOwner(pThis->aTimers[0].CTX_SUFF(pTimer)));
+
+ int rc = VINF_SUCCESS;
+ switch (idxReg)
+ {
+ case HPET_ID:
+ case HPET_ID + 4:
+ {
+ Log(("write HPET_ID, useless\n"));
+ break;
+ }
+
+ case HPET_CFG:
+ {
+ DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
+ uint32_t const iOldValue = (uint32_t)(pThis->u64HpetConfig);
+ Log(("write HPET_CFG: %x (old %x)\n", u32NewValue, iOldValue));
+
+ /*
+ * This check must be here, before actual update, as hpetLegacyMode
+ * may request retry in R3 - so we must keep state intact.
+ */
+ if ( ((iOldValue ^ u32NewValue) & HPET_CFG_LEGACY)
+ && pThis->pHpetHlpR3 != NIL_RTR3PTR)
+ {
+#ifdef IN_RING3
+ rc = pThis->pHpetHlpR3->pfnSetLegacyMode(pThis->pDevInsR3, RT_BOOL(u32NewValue & HPET_CFG_LEGACY));
+ if (rc != VINF_SUCCESS)
+#else
+ rc = VINF_IOM_R3_MMIO_WRITE;
+#endif
+ {
+ DEVHPET_UNLOCK_BOTH(pThis);
+ break;
+ }
+ }
+
+ pThis->u64HpetConfig = hpetUpdateMasked(u32NewValue, iOldValue, HPET_CFG_WRITE_MASK);
+
+ uint32_t const cTimers = HPET_CAP_GET_TIMERS(pThis->u32Capabilities);
+ if (hpetBitJustSet(iOldValue, u32NewValue, HPET_CFG_ENABLE))
+ {
+/** @todo Only get the time stamp once when reprogramming? */
+ /* Enable main counter and interrupt generation. */
+ pThis->u64HpetOffset = hpetTicksToNs(pThis, pThis->u64HpetCounter)
+ - TMTimerGet(pThis->aTimers[0].CTX_SUFF(pTimer));
+ for (uint32_t i = 0; i < cTimers; i++)
+ if (pThis->aTimers[i].u64Cmp != hpetInvalidValue(&pThis->aTimers[i]))
+ hpetProgramTimer(&pThis->aTimers[i]);
+ }
+ else if (hpetBitJustCleared(iOldValue, u32NewValue, HPET_CFG_ENABLE))
+ {
+ /* Halt main counter and disable interrupt generation. */
+ pThis->u64HpetCounter = hpetGetTicks(pThis);
+ for (uint32_t i = 0; i < cTimers; i++)
+ TMTimerStop(pThis->aTimers[i].CTX_SUFF(pTimer));
+ }
+
+ DEVHPET_UNLOCK_BOTH(pThis);
+ break;
+ }
+
+ case HPET_CFG + 4:
+ {
+ DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
+ pThis->u64HpetConfig = hpetUpdateMasked((uint64_t)u32NewValue << 32,
+ pThis->u64HpetConfig,
+ UINT64_C(0xffffffff00000000));
+ Log(("write HPET_CFG + 4: %x -> %#llx\n", u32NewValue, pThis->u64HpetConfig));
+ DEVHPET_UNLOCK(pThis);
+ break;
+ }
+
+ case HPET_STATUS:
+ {
+ DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
+ /* Clear ISR for all set bits in u32NewValue, see p. 14 of the HPET spec. */
+ pThis->u64Isr &= ~((uint64_t)u32NewValue);
+ Log(("write HPET_STATUS: %x -> ISR=%#llx\n", u32NewValue, pThis->u64Isr));
+ DEVHPET_UNLOCK(pThis);
+ break;
+ }
+
+ case HPET_STATUS + 4:
+ {
+ Log(("write HPET_STATUS + 4: %x\n", u32NewValue));
+ if (u32NewValue != 0)
+ LogRelMax(10, ("HPET: Writing HPET_STATUS + 4 with non-zero, ignored\n"));
+ break;
+ }
+
+ case HPET_COUNTER:
+ {
+ DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
+ pThis->u64HpetCounter = RT_MAKE_U64(u32NewValue, RT_HI_U32(pThis->u64HpetCounter));
+ Log(("write HPET_COUNTER: %#x -> %llx\n", u32NewValue, pThis->u64HpetCounter));
+ DEVHPET_UNLOCK(pThis);
+ break;
+ }
+
+ case HPET_COUNTER + 4:
+ {
+ DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
+ pThis->u64HpetCounter = RT_MAKE_U64(RT_LO_U32(pThis->u64HpetCounter), u32NewValue);
+ Log(("write HPET_COUNTER + 4: %#x -> %llx\n", u32NewValue, pThis->u64HpetCounter));
+ DEVHPET_UNLOCK(pThis);
+ break;
+ }
+
+ default:
+ LogRelMax(10, ("HPET: Invalid HPET config write: %x\n", idxReg));
+ break;
+ }
+
+ return rc;
+}
+
+
+/* -=-=-=-=-=- MMIO callbacks -=-=-=-=-=- */
+
+
+/**
+ * @callback_method_impl{FNIOMMMIOREAD}
+ */
+PDMBOTHCBDECL(int) hpetMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
+{
+ HPET *pThis = PDMINS_2_DATA(pDevIns, HPET*);
+ uint32_t const idxReg = (uint32_t)(GCPhysAddr - HPET_BASE);
+ NOREF(pvUser);
+ Assert(cb == 4 || cb == 8);
+
+ LogFlow(("hpetMMIORead (%d): %llx (%x)\n", cb, (uint64_t)GCPhysAddr, idxReg));
+
+ int rc;
+ if (cb == 4)
+ {
+ /*
+ * 4-byte access.
+ */
+ if (idxReg >= 0x100 && idxReg < 0x400)
+ {
+ DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
+ rc = hpetTimerRegRead32(pThis,
+ (idxReg - 0x100) / 0x20,
+ (idxReg - 0x100) % 0x20,
+ (uint32_t *)pv);
+ DEVHPET_UNLOCK(pThis);
+ }
+ else
+ rc = hpetConfigRegRead32(pThis, idxReg, (uint32_t *)pv);
+ }
+ else
+ {
+ /*
+ * 8-byte access - Split the access except for timing sensitive registers.
+ * The others assume the protection of the lock.
+ */
+ PRTUINT64U pValue = (PRTUINT64U)pv;
+ if (idxReg == HPET_COUNTER)
+ {
+ /* When reading HPET counter we must read it in a single read,
+ to avoid unexpected time jumps on 32-bit overflow. */
+ DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
+ if (pThis->u64HpetConfig & HPET_CFG_ENABLE)
+ pValue->u = hpetGetTicks(pThis);
+ else
+ pValue->u = pThis->u64HpetCounter;
+ DEVHPET_UNLOCK_BOTH(pThis);
+ rc = VINF_SUCCESS;
+ }
+ else
+ {
+ DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
+ if (idxReg >= 0x100 && idxReg < 0x400)
+ {
+ uint32_t iTimer = (idxReg - 0x100) / 0x20;
+ uint32_t iTimerReg = (idxReg - 0x100) % 0x20;
+ rc = hpetTimerRegRead32(pThis, iTimer, iTimerReg, &pValue->s.Lo);
+ if (rc == VINF_SUCCESS)
+ rc = hpetTimerRegRead32(pThis, iTimer, iTimerReg + 4, &pValue->s.Hi);
+ }
+ else
+ {
+ /* for most 8-byte accesses we just split them, happens under lock anyway. */
+ rc = hpetConfigRegRead32(pThis, idxReg, &pValue->s.Lo);
+ if (rc == VINF_SUCCESS)
+ rc = hpetConfigRegRead32(pThis, idxReg + 4, &pValue->s.Hi);
+ }
+ DEVHPET_UNLOCK(pThis);
+ }
+ }
+ return rc;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMMMIOWRITE}
+ */
+PDMBOTHCBDECL(int) hpetMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
+{
+ HPET *pThis = PDMINS_2_DATA(pDevIns, HPET*);
+ uint32_t idxReg = (uint32_t)(GCPhysAddr - HPET_BASE);
+ LogFlow(("hpetMMIOWrite: cb=%u reg=%03x (%RGp) val=%llx\n",
+ cb, idxReg, GCPhysAddr, cb == 4 ? *(uint32_t *)pv : cb == 8 ? *(uint64_t *)pv : 0xdeadbeef));
+ NOREF(pvUser);
+ Assert(cb == 4 || cb == 8);
+
+ int rc;
+ if (cb == 4)
+ {
+ if (idxReg >= 0x100 && idxReg < 0x400)
+ rc = hpetTimerRegWrite32(pThis,
+ (idxReg - 0x100) / 0x20,
+ (idxReg - 0x100) % 0x20,
+ *(uint32_t const *)pv);
+ else
+ rc = hpetConfigRegWrite32(pThis, idxReg, *(uint32_t const *)pv);
+ }
+ else
+ {
+ /*
+ * 8-byte access.
+ */
+ /* Split the access and rely on the locking to prevent trouble. */
+ DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
+ RTUINT64U uValue;
+ uValue.u = *(uint64_t const *)pv;
+ if (idxReg >= 0x100 && idxReg < 0x400)
+ {
+ uint32_t iTimer = (idxReg - 0x100) / 0x20;
+ uint32_t iTimerReg = (idxReg - 0x100) % 0x20;
+ /** @todo Consider handling iTimerReg == HPET_TN_CMP specially here */
+ rc = hpetTimerRegWrite32(pThis, iTimer, iTimerReg, uValue.s.Lo);
+ if (RT_LIKELY(rc == VINF_SUCCESS))
+ rc = hpetTimerRegWrite32(pThis, iTimer, iTimerReg + 4, uValue.s.Hi);
+ }
+ else
+ {
+ rc = hpetConfigRegWrite32(pThis, idxReg, uValue.s.Lo);
+ if (RT_LIKELY(rc == VINF_SUCCESS))
+ rc = hpetConfigRegWrite32(pThis, idxReg + 4, uValue.s.Hi);
+ }
+ DEVHPET_UNLOCK_BOTH(pThis);
+ }
+
+ return rc;
+}
+
+#ifdef IN_RING3
+
+/* -=-=-=-=-=- Timer Callback Processing -=-=-=-=-=- */
+
+/**
+ * Gets the IRQ of an HPET timer.
+ *
+ * @returns IRQ number.
+ * @param pHpetTimer The HPET timer.
+ */
+static uint32_t hpetR3TimerGetIrq(struct HPETTIMER const *pHpetTimer)
+{
+ /*
+ * Per spec, in legacy mode the HPET timers are wired as follows:
+ * timer 0: IRQ0 for PIC and IRQ2 for APIC
+ * timer 1: IRQ8 for both PIC and APIC
+ *
+ * ISA IRQ delivery logic will take care of correct delivery
+ * to the different ICs.
+ */
+ if ( (pHpetTimer->idxTimer <= 1)
+ && (pHpetTimer->CTX_SUFF(pHpet)->u64HpetConfig & HPET_CFG_LEGACY))
+ return (pHpetTimer->idxTimer == 0) ? 0 : 8;
+
+ return (pHpetTimer->u64Config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
+}
+
+
+/**
+ * Used by hpetR3Timer to update the IRQ status.
+ *
+ * @param pThis The HPET device state.
+ * @param pHpetTimer The HPET timer.
+ */
+static void hpetR3TimerUpdateIrq(HPET *pThis, struct HPETTIMER *pHpetTimer)
+{
+ /** @todo is it correct? */
+ if ( !!(pHpetTimer->u64Config & HPET_TN_ENABLE)
+ && !!(pThis->u64HpetConfig & HPET_CFG_ENABLE))
+ {
+ uint32_t irq = hpetR3TimerGetIrq(pHpetTimer);
+ Log4(("HPET: raising IRQ %d\n", irq));
+
+ /* ISR bits are only set in level-triggered mode. */
+ if ((pHpetTimer->u64Config & HPET_TN_INT_TYPE) == HPET_TIMER_TYPE_LEVEL)
+ pThis->u64Isr |= UINT64_C(1) << pHpetTimer->idxTimer;
+
+ /* We trigger flip/flop in edge-triggered mode and do nothing in
+ level-triggered mode yet. */
+ if ((pHpetTimer->u64Config & HPET_TN_INT_TYPE) == HPET_TIMER_TYPE_EDGE)
+ pThis->pHpetHlpR3->pfnSetIrq(pThis->CTX_SUFF(pDevIns), irq, PDM_IRQ_LEVEL_FLIP_FLOP);
+ else
+ AssertFailed();
+ /** @todo implement IRQs in level-triggered mode */
+ }
+}
+
+/**
+ * Device timer callback function.
+ *
+ * @param pDevIns Device instance of the device which registered the timer.
+ * @param pTimer The timer handle.
+ * @param pvUser Pointer to the HPET timer state.
+ */
+static DECLCALLBACK(void) hpetR3Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+ HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
+ HPETTIMER *pHpetTimer = (HPETTIMER *)pvUser;
+ uint64_t u64Period = pHpetTimer->u64Period;
+ uint64_t u64CurTick = hpetGetTicks(pThis);
+ uint64_t u64Diff;
+
+ if (pHpetTimer->u64Config & HPET_TN_PERIODIC)
+ {
+ if (u64Period) {
+ hpetAdjustComparator(pHpetTimer, u64CurTick);
+
+ u64Diff = hpetComputeDiff(pHpetTimer, u64CurTick);
+
+ Log4(("HPET: periodic: next in %llu\n", hpetTicksToNs(pThis, u64Diff)));
+ TMTimerSetNano(pTimer, hpetTicksToNs(pThis, u64Diff));
+ }
+ }
+ else if (hpet32bitTimer(pHpetTimer))
+ {
+ /* For 32-bit non-periodic timers, generate wrap-around interrupts. */
+ if (pHpetTimer->u8Wrap)
+ {
+ u64Diff = hpetComputeDiff(pHpetTimer, u64CurTick);
+ TMTimerSetNano(pTimer, hpetTicksToNs(pThis, u64Diff));
+ pHpetTimer->u8Wrap = 0;
+ }
+ }
+
+ /* Should it really be under lock, does it really matter? */
+ hpetR3TimerUpdateIrq(pThis, pHpetTimer);
+}
+
+
+/* -=-=-=-=-=- DBGF Info Handlers -=-=-=-=-=- */
+
+
+/**
+ * @callback_method_impl{FNDBGFHANDLERDEV}
+ */
+static DECLCALLBACK(void) hpetR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+ HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
+ NOREF(pszArgs);
+
+ pHlp->pfnPrintf(pHlp,
+ "HPET status:\n"
+ " config=%016RX64 isr=%016RX64\n"
+ " offset=%016RX64 counter=%016RX64 frequency=%08x\n"
+ " legacy-mode=%s timer-count=%u\n",
+ pThis->u64HpetConfig, pThis->u64Isr,
+ pThis->u64HpetOffset, pThis->u64HpetCounter, pThis->u32Period,
+ !!(pThis->u64HpetConfig & HPET_CFG_LEGACY) ? "on " : "off",
+ HPET_CAP_GET_TIMERS(pThis->u32Capabilities));
+ pHlp->pfnPrintf(pHlp,
+ "Timers:\n");
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->aTimers); i++)
+ {
+ pHlp->pfnPrintf(pHlp, " %d: comparator=%016RX64 period(hidden)=%016RX64 cfg=%016RX64\n",
+ pThis->aTimers[i].idxTimer,
+ pThis->aTimers[i].u64Cmp,
+ pThis->aTimers[i].u64Period,
+ pThis->aTimers[i].u64Config);
+ }
+}
+
+
+/* -=-=-=-=-=- Saved State -=-=-=-=-=- */
+
+
+/**
+ * @callback_method_impl{FNSSMDEVLIVEEXEC}
+ */
+static DECLCALLBACK(int) hpetR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
+{
+ HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
+ NOREF(uPass);
+
+ SSMR3PutU8(pSSM, HPET_CAP_GET_TIMERS(pThis->u32Capabilities));
+
+ return VINF_SSM_DONT_CALL_AGAIN;
+}
+
+
+/**
+ * @callback_method_impl{FNSSMDEVSAVEEXEC}
+ */
+static DECLCALLBACK(int) hpetR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+ HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
+
+ /*
+ * The config.
+ */
+ hpetR3LiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
+
+ /*
+ * The state.
+ */
+ uint32_t const cTimers = HPET_CAP_GET_TIMERS(pThis->u32Capabilities);
+ for (uint32_t iTimer = 0; iTimer < cTimers; iTimer++)
+ {
+ HPETTIMER *pHpetTimer = &pThis->aTimers[iTimer];
+ TMR3TimerSave(pHpetTimer->pTimerR3, pSSM);
+ SSMR3PutU8(pSSM, pHpetTimer->u8Wrap);
+ SSMR3PutU64(pSSM, pHpetTimer->u64Config);
+ SSMR3PutU64(pSSM, pHpetTimer->u64Cmp);
+ SSMR3PutU64(pSSM, pHpetTimer->u64Fsb);
+ SSMR3PutU64(pSSM, pHpetTimer->u64Period);
+ }
+
+ SSMR3PutU64(pSSM, pThis->u64HpetOffset);
+ uint64_t u64CapPer = RT_MAKE_U64(pThis->u32Capabilities, pThis->u32Period);
+ SSMR3PutU64(pSSM, u64CapPer);
+ SSMR3PutU64(pSSM, pThis->u64HpetConfig);
+ SSMR3PutU64(pSSM, pThis->u64Isr);
+ return SSMR3PutU64(pSSM, pThis->u64HpetCounter);
+}
+
+
+/**
+ * @callback_method_impl{FNSSMDEVLOADEXEC}
+ */
+static DECLCALLBACK(int) hpetR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+{
+ HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
+
+ /*
+ * Version checks.
+ */
+ if (uVersion == HPET_SAVED_STATE_VERSION_EMPTY)
+ return VINF_SUCCESS;
+ if (uVersion != HPET_SAVED_STATE_VERSION)
+ return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
+
+ /*
+ * The config.
+ */
+ uint8_t cTimers;
+ int rc = SSMR3GetU8(pSSM, &cTimers);
+ AssertRCReturn(rc, rc);
+ if (cTimers > RT_ELEMENTS(pThis->aTimers))
+ return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - too many timers: saved=%#x config=%#x"),
+ cTimers, RT_ELEMENTS(pThis->aTimers));
+
+ if (uPass != SSM_PASS_FINAL)
+ return VINF_SUCCESS;
+
+ /*
+ * The state.
+ */
+ for (uint32_t iTimer = 0; iTimer < cTimers; iTimer++)
+ {
+ HPETTIMER *pHpetTimer = &pThis->aTimers[iTimer];
+ TMR3TimerLoad(pHpetTimer->pTimerR3, pSSM);
+ SSMR3GetU8(pSSM, &pHpetTimer->u8Wrap);
+ SSMR3GetU64(pSSM, &pHpetTimer->u64Config);
+ SSMR3GetU64(pSSM, &pHpetTimer->u64Cmp);
+ SSMR3GetU64(pSSM, &pHpetTimer->u64Fsb);
+ SSMR3GetU64(pSSM, &pHpetTimer->u64Period);
+ }
+
+ SSMR3GetU64(pSSM, &pThis->u64HpetOffset);
+ uint64_t u64CapPer;
+ SSMR3GetU64(pSSM, &u64CapPer);
+ SSMR3GetU64(pSSM, &pThis->u64HpetConfig);
+ SSMR3GetU64(pSSM, &pThis->u64Isr);
+ rc = SSMR3GetU64(pSSM, &pThis->u64HpetCounter);
+ if (RT_FAILURE(rc))
+ return rc;
+ if (HPET_CAP_GET_TIMERS(RT_LO_U32(u64CapPer)) != cTimers)
+ return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Capabilities does not match timer count: cTimers=%#x caps=%#x"),
+ cTimers, (unsigned)HPET_CAP_GET_TIMERS(u64CapPer));
+ pThis->u32Capabilities = RT_LO_U32(u64CapPer);
+ pThis->u32Period = RT_HI_U32(u64CapPer);
+
+ /*
+ * Set the timer frequency hints.
+ */
+ PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
+ for (uint32_t iTimer = 0; iTimer < cTimers; iTimer++)
+ {
+ HPETTIMER *pHpetTimer = &pThis->aTimers[iTimer];
+ if (TMTimerIsActive(pHpetTimer->CTX_SUFF(pTimer)))
+ hpetTimerSetFrequencyHint(pThis, pHpetTimer);
+ }
+ PDMCritSectLeave(&pThis->CritSect);
+ return VINF_SUCCESS;
+}
+
+
+/* -=-=-=-=-=- PDMDEVREG -=-=-=-=-=- */
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnRelocate}
+ */
+static DECLCALLBACK(void) hpetR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
+{
+ HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
+ LogFlow(("hpetR3Relocate:\n"));
+ NOREF(offDelta);
+
+ pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+ pThis->pHpetHlpRC = pThis->pHpetHlpR3->pfnGetRCHelpers(pDevIns);
+
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->aTimers); i++)
+ {
+ HPETTIMER *pTm = &pThis->aTimers[i];
+ if (pTm->pTimerR3)
+ pTm->pTimerRC = TMTimerRCPtr(pTm->pTimerR3);
+ pTm->pHpetRC = PDMINS_2_DATA_RCPTR(pDevIns);
+ }
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnReset}
+ */
+static DECLCALLBACK(void) hpetR3Reset(PPDMDEVINS pDevIns)
+{
+ HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
+ LogFlow(("hpetR3Reset:\n"));
+
+ /*
+ * The timers first.
+ */
+ TMTimerLock(pThis->aTimers[0].pTimerR3, VERR_IGNORED);
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->aTimers); i++)
+ {
+ HPETTIMER *pHpetTimer = &pThis->aTimers[i];
+ Assert(pHpetTimer->idxTimer == i);
+ TMTimerStop(pHpetTimer->pTimerR3);
+
+ /* capable of periodic operations and 64-bits */
+ if (pThis->fIch9)
+ pHpetTimer->u64Config = (i == 0)
+ ? (HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP)
+ : 0;
+ else
+ pHpetTimer->u64Config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
+
+ /* We can do all IRQs */
+ uint32_t u32RoutingCap = 0xffffffff;
+ pHpetTimer->u64Config |= ((uint64_t)u32RoutingCap) << 32;
+ pHpetTimer->u64Period = 0;
+ pHpetTimer->u8Wrap = 0;
+ pHpetTimer->u64Cmp = hpetInvalidValue(pHpetTimer);
+ }
+ TMTimerUnlock(pThis->aTimers[0].pTimerR3);
+
+ /*
+ * The HPET state.
+ */
+ pThis->u64HpetConfig = 0;
+ pThis->u64HpetCounter = 0;
+ pThis->u64HpetOffset = 0;
+
+ /* 64-bit main counter; 3 timers supported; LegacyReplacementRoute. */
+ pThis->u32Capabilities = (1 << 15) /* LEG_RT_CAP - LegacyReplacementRoute capable. */
+ | (1 << 13) /* COUNTER_SIZE_CAP - Main counter is 64-bit capable. */
+ | 1; /* REV_ID - Revision, must not be 0 */
+ if (pThis->fIch9) /* NUM_TIM_CAP - Number of timers -1. */
+ pThis->u32Capabilities |= (HPET_NUM_TIMERS_ICH9 - 1) << 8;
+ else
+ pThis->u32Capabilities |= (HPET_NUM_TIMERS_PIIX - 1) << 8;
+ pThis->u32Capabilities |= UINT32_C(0x80860000); /* VENDOR */
+ AssertCompile(HPET_NUM_TIMERS_ICH9 <= RT_ELEMENTS(pThis->aTimers));
+ AssertCompile(HPET_NUM_TIMERS_PIIX <= RT_ELEMENTS(pThis->aTimers));
+
+ pThis->u32Period = pThis->fIch9 ? HPET_CLK_PERIOD_ICH9 : HPET_CLK_PERIOD_PIIX;
+
+ /*
+ * Notify the PIT/RTC devices.
+ */
+ if (pThis->pHpetHlpR3)
+ pThis->pHpetHlpR3->pfnSetLegacyMode(pDevIns, false /*fActive*/);
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnConstruct}
+ */
+static DECLCALLBACK(int) hpetR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
+{
+ PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+ HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
+
+ /* Only one HPET device now, as we use fixed MMIO region. */
+ Assert(iInstance == 0); RT_NOREF(iInstance);
+
+ /*
+ * Initialize the device state.
+ */
+ pThis->pDevInsR3 = pDevIns;
+ pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
+ pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+
+ /* Init the HPET timers (init all regardless of how many we expose). */
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->aTimers); i++)
+ {
+ HPETTIMER *pHpetTimer = &pThis->aTimers[i];
+
+ pHpetTimer->idxTimer = i;
+ pHpetTimer->pHpetR3 = pThis;
+ pHpetTimer->pHpetR0 = PDMINS_2_DATA_R0PTR(pDevIns);
+ pHpetTimer->pHpetRC = PDMINS_2_DATA_RCPTR(pDevIns);
+ }
+
+ /*
+ * Validate and read the configuration.
+ */
+ PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "GCEnabled|R0Enabled|ICH9", "");
+
+ bool fRCEnabled;
+ int rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fRCEnabled, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"GCEnabled\" as a bool failed"));
+
+ bool fR0Enabled;
+ rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: failed to read R0Enabled as boolean"));
+
+ rc = CFGMR3QueryBoolDef(pCfg, "ICH9", &pThis->fIch9, false);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: failed to read ICH9 as boolean"));
+
+
+ /*
+ * Create critsect and timers.
+ * Note! We don't use the default critical section of the device, but our own.
+ */
+ rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "HPET");
+ AssertRCReturn(rc, rc);
+
+ rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
+ AssertRCReturn(rc, rc);
+
+ /* Init the HPET timers (init all regardless of how many we expose). */
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->aTimers); i++)
+ {
+ HPETTIMER *pHpetTimer = &pThis->aTimers[i];
+
+ rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hpetR3Timer, pHpetTimer,
+ TMTIMER_FLAGS_NO_CRIT_SECT, "HPET Timer",
+ &pThis->aTimers[i].pTimerR3);
+ AssertRCReturn(rc, rc);
+ pThis->aTimers[i].pTimerRC = TMTimerRCPtr(pThis->aTimers[i].pTimerR3);
+ pThis->aTimers[i].pTimerR0 = TMTimerR0Ptr(pThis->aTimers[i].pTimerR3);
+ rc = TMR3TimerSetCritSect(pThis->aTimers[i].pTimerR3, &pThis->CritSect);
+ AssertRCReturn(rc, rc);
+ }
+
+ /*
+ * This must be done prior to registering the HPET, right?
+ */
+ hpetR3Reset(pDevIns);
+
+ /*
+ * Register the HPET and get helpers.
+ */
+ PDMHPETREG HpetReg;
+ HpetReg.u32Version = PDM_HPETREG_VERSION;
+ rc = PDMDevHlpHPETRegister(pDevIns, &HpetReg, &pThis->pHpetHlpR3);
+ AssertRCReturn(rc, rc);
+
+ /*
+ * Register the MMIO range, PDM API requests page aligned
+ * addresses and sizes.
+ */
+ rc = PDMDevHlpMMIORegister(pDevIns, HPET_BASE, HPET_BAR_SIZE, pThis,
+ IOMMMIO_FLAGS_READ_DWORD_QWORD | IOMMMIO_FLAGS_WRITE_ONLY_DWORD_QWORD,
+ hpetMMIOWrite, hpetMMIORead, "HPET Memory");
+ AssertRCReturn(rc, rc);
+
+ if (fRCEnabled)
+ {
+ rc = PDMDevHlpMMIORegisterRC(pDevIns, HPET_BASE, HPET_BAR_SIZE, NIL_RTRCPTR /*pvUser*/, "hpetMMIOWrite", "hpetMMIORead");
+ AssertRCReturn(rc, rc);
+
+ pThis->pHpetHlpRC = pThis->pHpetHlpR3->pfnGetRCHelpers(pDevIns);
+ }
+
+ if (fR0Enabled)
+ {
+ rc = PDMDevHlpMMIORegisterR0(pDevIns, HPET_BASE, HPET_BAR_SIZE, NIL_RTR0PTR /*pvUser*/,
+ "hpetMMIOWrite", "hpetMMIORead");
+ AssertRCReturn(rc, rc);
+
+ pThis->pHpetHlpR0 = pThis->pHpetHlpR3->pfnGetR0Helpers(pDevIns);
+ AssertReturn(pThis->pHpetHlpR0 != NIL_RTR0PTR, VERR_INTERNAL_ERROR);
+ }
+
+ /* Register SSM callbacks */
+ rc = PDMDevHlpSSMRegister3(pDevIns, HPET_SAVED_STATE_VERSION, sizeof(*pThis), hpetR3LiveExec, hpetR3SaveExec, hpetR3LoadExec);
+ AssertRCReturn(rc, rc);
+
+ /* Register an info callback. */
+ PDMDevHlpDBGFInfoRegister(pDevIns, "hpet", "Display HPET status. (no arguments)", hpetR3Info);
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * The device registration structure.
+ */
+const PDMDEVREG g_DeviceHPET =
+{
+ /* u32Version */
+ PDM_DEVREG_VERSION,
+ /* szName */
+ "hpet",
+ /* szRCMod */
+ "VBoxDDRC.rc",
+ /* szR0Mod */
+ "VBoxDDR0.r0",
+ /* pszDescription */
+ " High Precision Event Timer (HPET) Device",
+ /* fFlags */
+ PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36
+ | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
+ /* fClass */
+ PDM_DEVREG_CLASS_PIT,
+ /* cMaxInstances */
+ 1,
+ /* cbInstance */
+ sizeof(HPET),
+ /* pfnConstruct */
+ hpetR3Construct,
+ /* pfnDestruct */
+ NULL,
+ /* pfnRelocate */
+ hpetR3Relocate,
+ /* pfnMemSetup */
+ NULL,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ hpetR3Reset,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnAttach */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnQueryInterface. */
+ NULL,
+ /* pfnInitComplete */
+ NULL,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32VersionEnd */
+ PDM_DEVREG_VERSION
+};
+
+#endif /* IN_RING3 */
+#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
+
diff --git a/src/VBox/Devices/PC/DevIoApic.cpp b/src/VBox/Devices/PC/DevIoApic.cpp
new file mode 100644
index 00000000..10f6c202
--- /dev/null
+++ b/src/VBox/Devices/PC/DevIoApic.cpp
@@ -0,0 +1,1429 @@
+/* $Id: DevIoApic.cpp $ */
+/** @file
+ * IO APIC - Input/Output Advanced Programmable Interrupt Controller.
+ */
+
+/*
+ * Copyright (C) 2016-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_IOAPIC
+#include <VBox/log.h>
+#include <VBox/vmm/hm.h>
+#include <VBox/msi.h>
+#include <VBox/vmm/pdmdev.h>
+
+#include "VBoxDD.h"
+#include <iprt/x86.h>
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+/** The current IO APIC saved state version. */
+#define IOAPIC_SAVED_STATE_VERSION 2
+/** The saved state version used by VirtualBox 5.0 and
+ * earlier. */
+#define IOAPIC_SAVED_STATE_VERSION_VBOX_50 1
+
+/** Implementation specified by the "Intel I/O Controller Hub 9
+ * (ICH9) Family" */
+#define IOAPIC_VERSION_ICH9 0x20
+/** Implementation specified by the "82093AA I/O Advanced Programmable Interrupt
+Controller" */
+#define IOAPIC_VERSION_82093AA 0x11
+
+/** The default MMIO base physical address. */
+#define IOAPIC_MMIO_BASE_PHYSADDR UINT64_C(0xfec00000)
+/** The size of the MMIO range. */
+#define IOAPIC_MMIO_SIZE X86_PAGE_4K_SIZE
+/** The mask for getting direct registers from physical address. */
+#define IOAPIC_MMIO_REG_MASK 0xff
+
+/** The number of interrupt input pins. */
+#define IOAPIC_NUM_INTR_PINS 24
+/** Maximum redirection entires. */
+#define IOAPIC_MAX_RTE_INDEX (IOAPIC_NUM_INTR_PINS - 1)
+/** Reduced RTEs used by SIO.A (82379AB). */
+#define IOAPIC_REDUCED_MAX_RTE_INDEX (16 - 1)
+
+/** Version register - Gets the version. */
+#define IOAPIC_VER_GET_VER(a_Reg) ((a_Reg) & 0xff)
+/** Version register - Gets the maximum redirection entry. */
+#define IOAPIC_VER_GET_MRE(a_Reg) (((a_Reg) >> 16) & 0xff)
+/** Version register - Gets whether Pin Assertion Register (PRQ) is
+ * supported. */
+#define IOAPIC_VER_HAS_PRQ(a_Reg) RT_BOOL((a_Reg) & RT_BIT_32(15))
+
+/** Index register - Valid write mask. */
+#define IOAPIC_INDEX_VALID_WRITE_MASK UINT32_C(0xff)
+
+/** Arbitration register - Gets the ID. */
+#define IOAPIC_ARB_GET_ID(a_Reg) ((a_Reg) >> 24 & 0xf)
+
+/** ID register - Gets the ID. */
+#define IOAPIC_ID_GET_ID(a_Reg) ((a_Reg) >> 24 & 0xff)
+
+/** Redirection table entry - Vector. */
+#define IOAPIC_RTE_VECTOR UINT64_C(0xff)
+/** Redirection table entry - Delivery mode. */
+#define IOAPIC_RTE_DELIVERY_MODE (RT_BIT_64(8) | RT_BIT_64(9) | RT_BIT_64(10))
+/** Redirection table entry - Destination mode. */
+#define IOAPIC_RTE_DEST_MODE RT_BIT_64(11)
+/** Redirection table entry - Delivery status. */
+#define IOAPIC_RTE_DELIVERY_STATUS RT_BIT_64(12)
+/** Redirection table entry - Interrupt input pin polarity. */
+#define IOAPIC_RTE_POLARITY RT_BIT_64(13)
+/** Redirection table entry - Remote IRR. */
+#define IOAPIC_RTE_REMOTE_IRR RT_BIT_64(14)
+/** Redirection table entry - Trigger Mode. */
+#define IOAPIC_RTE_TRIGGER_MODE RT_BIT_64(15)
+/** Redirection table entry - the mask bit number. */
+#define IOAPIC_RTE_MASK_BIT 16
+/** Redirection table entry - the mask. */
+#define IOAPIC_RTE_MASK RT_BIT_64(IOAPIC_RTE_MASK_BIT)
+/** Redirection table entry - Extended Destination ID. */
+#define IOAPIC_RTE_EXT_DEST_ID UINT64_C(0x00ff000000000000)
+/** Redirection table entry - Destination. */
+#define IOAPIC_RTE_DEST UINT64_C(0xff00000000000000)
+
+/** Redirection table entry - Gets the destination. */
+#define IOAPIC_RTE_GET_DEST(a_Reg) ((a_Reg) >> 56 & 0xff)
+/** Redirection table entry - Gets the mask flag. */
+#define IOAPIC_RTE_GET_MASK(a_Reg) (((a_Reg) >> IOAPIC_RTE_MASK_BIT) & 0x1)
+/** Redirection table entry - Checks whether it's masked. */
+#define IOAPIC_RTE_IS_MASKED(a_Reg) ((a_Reg) & IOAPIC_RTE_MASK)
+/** Redirection table entry - Gets the trigger mode. */
+#define IOAPIC_RTE_GET_TRIGGER_MODE(a_Reg) (((a_Reg) >> 15) & 0x1)
+/** Redirection table entry - Gets the remote IRR flag. */
+#define IOAPIC_RTE_GET_REMOTE_IRR(a_Reg) (((a_Reg) >> 14) & 0x1)
+/** Redirection table entry - Gets the interrupt pin polarity. */
+#define IOAPIC_RTE_GET_POLARITY(a_Reg) (((a_Reg) >> 13) & 0x1)
+/** Redirection table entry - Gets the delivery status. */
+#define IOAPIC_RTE_GET_DELIVERY_STATUS(a_Reg) (((a_Reg) >> 12) & 0x1)
+/** Redirection table entry - Gets the destination mode. */
+#define IOAPIC_RTE_GET_DEST_MODE(a_Reg) (((a_Reg) >> 11) & 0x1)
+/** Redirection table entry - Gets the delivery mode. */
+#define IOAPIC_RTE_GET_DELIVERY_MODE(a_Reg) (((a_Reg) >> 8) & 0x7)
+/** Redirection table entry - Gets the vector. */
+#define IOAPIC_RTE_GET_VECTOR(a_Reg) ((a_Reg) & IOAPIC_RTE_VECTOR)
+
+/** Redirection table entry - Valid write mask for 82093AA. */
+#define IOAPIC_RTE_VALID_WRITE_MASK_82093AA ( IOAPIC_RTE_DEST | IOAPIC_RTE_MASK | IOAPIC_RTE_TRIGGER_MODE \
+ | IOAPIC_RTE_POLARITY | IOAPIC_RTE_DEST_MODE | IOAPIC_RTE_DELIVERY_MODE \
+ | IOAPIC_RTE_VECTOR)
+/** Redirection table entry - Valid read mask for 82093AA. */
+#define IOAPIC_RTE_VALID_READ_MASK_82093AA ( IOAPIC_RTE_DEST | IOAPIC_RTE_MASK | IOAPIC_RTE_TRIGGER_MODE \
+ | IOAPIC_RTE_REMOTE_IRR | IOAPIC_RTE_POLARITY | IOAPIC_RTE_DELIVERY_STATUS \
+ | IOAPIC_RTE_DEST_MODE | IOAPIC_RTE_DELIVERY_MODE | IOAPIC_RTE_VECTOR)
+
+/** Redirection table entry - Valid write mask for ICH9. */
+/** @note The remote IRR bit has been reverted to read-only as it turns out the
+ * ICH9 spec. is wrong, see @bugref{8386#c46}. */
+#define IOAPIC_RTE_VALID_WRITE_MASK_ICH9 ( IOAPIC_RTE_DEST | IOAPIC_RTE_MASK | IOAPIC_RTE_TRIGGER_MODE \
+ /*| IOAPIC_RTE_REMOTE_IRR */| IOAPIC_RTE_POLARITY | IOAPIC_RTE_DEST_MODE \
+ | IOAPIC_RTE_DELIVERY_MODE | IOAPIC_RTE_VECTOR)
+/** Redirection table entry - Valid read mask (incl. ExtDestID) for ICH9. */
+#define IOAPIC_RTE_VALID_READ_MASK_ICH9 ( IOAPIC_RTE_DEST | IOAPIC_RTE_EXT_DEST_ID | IOAPIC_RTE_MASK \
+ | IOAPIC_RTE_TRIGGER_MODE | IOAPIC_RTE_REMOTE_IRR | IOAPIC_RTE_POLARITY \
+ | IOAPIC_RTE_DELIVERY_STATUS | IOAPIC_RTE_DEST_MODE | IOAPIC_RTE_DELIVERY_MODE \
+ | IOAPIC_RTE_VECTOR)
+
+/** Redirection table entry - Trigger mode edge. */
+#define IOAPIC_RTE_TRIGGER_MODE_EDGE 0
+/** Redirection table entry - Trigger mode level. */
+#define IOAPIC_RTE_TRIGGER_MODE_LEVEL 1
+/** Redirection table entry - Destination mode physical. */
+#define IOAPIC_RTE_DEST_MODE_PHYSICAL 0
+/** Redirection table entry - Destination mode logical. */
+#define IOAPIC_RTE_DEST_MODE_LOGICAL 1
+
+
+/** Index of indirect registers in the I/O APIC register table. */
+#define IOAPIC_INDIRECT_INDEX_ID 0x0
+#define IOAPIC_INDIRECT_INDEX_VERSION 0x1
+#define IOAPIC_INDIRECT_INDEX_ARB 0x2 /* Older I/O APIC only. */
+#define IOAPIC_INDIRECT_INDEX_REDIR_TBL_START 0x10 /* First valid RTE register index. */
+#define IOAPIC_INDIRECT_INDEX_RTE_END 0x3F /* Last valid RTE register index (24 RTEs). */
+#define IOAPIC_REDUCED_INDIRECT_INDEX_RTE_END 0x2F /* Last valid RTE register index (16 RTEs). */
+
+/** Offset of direct registers in the I/O APIC MMIO space. */
+#define IOAPIC_DIRECT_OFF_INDEX 0x00
+#define IOAPIC_DIRECT_OFF_DATA 0x10
+#define IOAPIC_DIRECT_OFF_EOI 0x40 /* Newer I/O APIC only. */
+
+/* Use PDM critsect for now for I/O APIC locking, see @bugref{8245#c121}. */
+#define IOAPIC_WITH_PDM_CRITSECT
+#ifdef IOAPIC_WITH_PDM_CRITSECT
+# define IOAPIC_LOCK(pThis, rcBusy) (pThis)->CTX_SUFF(pIoApicHlp)->pfnLock((pThis)->CTX_SUFF(pDevIns), (rcBusy))
+# define IOAPIC_UNLOCK(pThis) (pThis)->CTX_SUFF(pIoApicHlp)->pfnUnlock((pThis)->CTX_SUFF(pDevIns))
+#else
+# define IOAPIC_LOCK(pThis, rcBusy) PDMCritSectEnter(&(pThis)->CritSect, (rcBusy))
+# define IOAPIC_UNLOCK(pThis) PDMCritSectLeave(&(pThis)->CritSect)
+#endif
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * The per-VM I/O APIC device state.
+ */
+typedef struct IOAPIC
+{
+ /** The device instance - R3 Ptr. */
+ PPDMDEVINSR3 pDevInsR3;
+ /** The IOAPIC helpers - R3 Ptr. */
+ PCPDMIOAPICHLPR3 pIoApicHlpR3;
+
+ /** The device instance - R0 Ptr. */
+ PPDMDEVINSR0 pDevInsR0;
+ /** The IOAPIC helpers - R0 Ptr. */
+ PCPDMIOAPICHLPR0 pIoApicHlpR0;
+
+ /** The device instance - RC Ptr. */
+ PPDMDEVINSRC pDevInsRC;
+ /** The IOAPIC helpers - RC Ptr. */
+ PCPDMIOAPICHLPRC pIoApicHlpRC;
+
+ /** The ID register. */
+ uint8_t volatile u8Id;
+ /** The index register. */
+ uint8_t volatile u8Index;
+ /** Number of CPUs. */
+ uint8_t cCpus;
+ /** I/O APIC version. */
+ uint8_t u8ApicVer;
+ /** I/O APIC ID mask. */
+ uint8_t u8IdMask;
+ /** Maximum Redirection Table Entry (RTE) Entry. */
+ uint8_t u8MaxRte;
+ /** Last valid RTE indirect register index. */
+ uint8_t u8LastRteRegIdx;
+ /* Alignment padding. */
+ uint8_t u8Padding0[1];
+ /** Redirection table entry - Valid write mask. */
+ uint64_t u64RteWriteMask;
+ /** Redirection table entry - Valid read mask. */
+ uint64_t u64RteReadMask;
+
+ /** The redirection table registers. */
+ uint64_t au64RedirTable[IOAPIC_NUM_INTR_PINS];
+ /** The IRQ tags and source IDs for each pin (tracing purposes). */
+ uint32_t au32TagSrc[IOAPIC_NUM_INTR_PINS];
+
+ /** Alignment padding. */
+ uint32_t u32Padding2;
+ /** The internal IRR reflecting state of the interrupt lines. */
+ uint32_t uIrr;
+
+#ifndef IOAPIC_WITH_PDM_CRITSECT
+ /** The critsect for updating to the RTEs. */
+ PDMCRITSECT CritSect;
+#endif
+
+#ifdef VBOX_WITH_STATISTICS
+ /** Number of MMIO reads in RZ. */
+ STAMCOUNTER StatMmioReadRZ;
+ /** Number of MMIO reads in R3. */
+ STAMCOUNTER StatMmioReadR3;
+
+ /** Number of MMIO writes in RZ. */
+ STAMCOUNTER StatMmioWriteRZ;
+ /** Number of MMIO writes in R3. */
+ STAMCOUNTER StatMmioWriteR3;
+
+ /** Number of SetIrq calls in RZ. */
+ STAMCOUNTER StatSetIrqRZ;
+ /** Number of SetIrq calls in R3. */
+ STAMCOUNTER StatSetIrqR3;
+
+ /** Number of SetEoi calls in RZ. */
+ STAMCOUNTER StatSetEoiRZ;
+ /** Number of SetEoi calls in R3. */
+ STAMCOUNTER StatSetEoiR3;
+
+ /** Number of redundant edge-triggered interrupts. */
+ STAMCOUNTER StatRedundantEdgeIntr;
+ /** Number of redundant level-triggered interrupts. */
+ STAMCOUNTER StatRedundantLevelIntr;
+ /** Number of suppressed level-triggered interrupts (by remote IRR). */
+ STAMCOUNTER StatSuppressedLevelIntr;
+ /** Number of returns to ring-3 due to EOI broadcast lock contention. */
+ STAMCOUNTER StatEoiContention;
+ /** Number of returns to ring-3 due to Set RTE lock contention. */
+ STAMCOUNTER StatSetRteContention;
+ /** Number of level-triggered interrupts dispatched to the local APIC(s). */
+ STAMCOUNTER StatLevelIrqSent;
+ /** Number of EOIs received for level-triggered interrupts from the local
+ * APIC(s). */
+ STAMCOUNTER StatEoiReceived;
+#endif
+} IOAPIC;
+/** Pointer to IOAPIC data. */
+typedef IOAPIC *PIOAPIC;
+/** Pointer to a const IOAPIC data. */
+typedef IOAPIC const *PCIOAPIC;
+AssertCompileMemberAlignment(IOAPIC, au64RedirTable, 8);
+
+#ifndef VBOX_DEVICE_STRUCT_TESTCASE
+
+/**
+ * Gets the arbitration register.
+ *
+ * @returns The arbitration.
+ */
+DECLINLINE(uint32_t) ioapicGetArb(void)
+{
+ Log2(("IOAPIC: ioapicGetArb: returns 0\n"));
+ return 0;
+}
+
+
+/**
+ * Gets the version register.
+ *
+ * @returns The version.
+ */
+DECLINLINE(uint32_t) ioapicGetVersion(PCIOAPIC pThis)
+{
+ uint32_t uValue = RT_MAKE_U32(pThis->u8ApicVer, pThis->u8MaxRte);
+ Log2(("IOAPIC: ioapicGetVersion: returns %#RX32\n", uValue));
+ return uValue;
+}
+
+
+/**
+ * Sets the ID register.
+ *
+ * @param pThis Pointer to the IOAPIC instance.
+ * @param uValue The value to set.
+ */
+DECLINLINE(void) ioapicSetId(PIOAPIC pThis, uint32_t uValue)
+{
+ Log2(("IOAPIC: ioapicSetId: uValue=%#RX32\n", uValue));
+ ASMAtomicWriteU8(&pThis->u8Id, (uValue >> 24) & pThis->u8IdMask);
+}
+
+
+/**
+ * Gets the ID register.
+ *
+ * @returns The ID.
+ * @param pThis Pointer to the IOAPIC instance.
+ */
+DECLINLINE(uint32_t) ioapicGetId(PCIOAPIC pThis)
+{
+ uint32_t uValue = (uint32_t)pThis->u8Id << 24;
+ Log2(("IOAPIC: ioapicGetId: returns %#RX32\n", uValue));
+ return uValue;
+}
+
+
+/**
+ * Sets the index register.
+ *
+ * @param pThis Pointer to the IOAPIC instance.
+ * @param uValue The value to set.
+ */
+DECLINLINE(void) ioapicSetIndex(PIOAPIC pThis, uint32_t uValue)
+{
+ LogFlow(("IOAPIC: ioapicSetIndex: uValue=%#RX32\n", uValue));
+ ASMAtomicWriteU8(&pThis->u8Index, uValue & IOAPIC_INDEX_VALID_WRITE_MASK);
+}
+
+
+/**
+ * Gets the index register.
+ *
+ * @returns The index value.
+ */
+DECLINLINE(uint32_t) ioapicGetIndex(PCIOAPIC pThis)
+{
+ uint32_t const uValue = pThis->u8Index;
+ LogFlow(("IOAPIC: ioapicGetIndex: returns %#x\n", uValue));
+ return uValue;
+}
+
+
+/**
+ * Signals the next pending interrupt for the specified Redirection Table Entry
+ * (RTE).
+ *
+ * @param pThis The IOAPIC instance.
+ * @param idxRte The index of the RTE.
+ *
+ * @remarks It is the responsibility of the caller to verify that an interrupt is
+ * pending for the pin corresponding to the RTE before calling this
+ * function.
+ */
+static void ioapicSignalIntrForRte(PIOAPIC pThis, uint8_t idxRte)
+{
+#ifndef IOAPIC_WITH_PDM_CRITSECT
+ Assert(PDMCritSectIsOwner(&pThis->CritSect));
+#endif
+
+ /* Ensure the RTE isn't masked. */
+ uint64_t const u64Rte = pThis->au64RedirTable[idxRte];
+ if (!IOAPIC_RTE_IS_MASKED(u64Rte))
+ {
+ /* We cannot accept another level-triggered interrupt until remote IRR has been cleared. */
+ uint8_t const u8TriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u64Rte);
+ if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL)
+ {
+ uint8_t const u8RemoteIrr = IOAPIC_RTE_GET_REMOTE_IRR(u64Rte);
+ if (u8RemoteIrr)
+ {
+ STAM_COUNTER_INC(&pThis->StatSuppressedLevelIntr);
+ return;
+ }
+ }
+
+ uint8_t const u8Vector = IOAPIC_RTE_GET_VECTOR(u64Rte);
+ uint8_t const u8DeliveryMode = IOAPIC_RTE_GET_DELIVERY_MODE(u64Rte);
+ uint8_t const u8DestMode = IOAPIC_RTE_GET_DEST_MODE(u64Rte);
+ uint8_t const u8Polarity = IOAPIC_RTE_GET_POLARITY(u64Rte);
+ uint8_t const u8Dest = IOAPIC_RTE_GET_DEST(u64Rte);
+ uint32_t const u32TagSrc = pThis->au32TagSrc[idxRte];
+
+ Log2(("IOAPIC: Signaling %s-triggered interrupt. Dest=%#x DestMode=%s Vector=%#x (%u)\n",
+ u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_EDGE ? "edge" : "level", u8Dest,
+ u8DestMode == IOAPIC_RTE_DEST_MODE_PHYSICAL ? "physical" : "logical", u8Vector, u8Vector));
+
+ /*
+ * Deliver to the local APIC via the system/3-wire-APIC bus.
+ */
+ int rc = pThis->CTX_SUFF(pIoApicHlp)->pfnApicBusDeliver(pThis->CTX_SUFF(pDevIns),
+ u8Dest,
+ u8DestMode,
+ u8DeliveryMode,
+ u8Vector,
+ u8Polarity,
+ u8TriggerMode,
+ u32TagSrc);
+ /* Can't reschedule to R3. */
+ Assert(rc == VINF_SUCCESS || rc == VERR_APIC_INTR_DISCARDED);
+#ifdef DEBUG_ramshankar
+ if (rc == VERR_APIC_INTR_DISCARDED)
+ AssertMsgFailed(("APIC: Interrupt discarded u8Vector=%#x (%u) u64Rte=%#RX64\n", u8Vector, u8Vector, u64Rte));
+#endif
+
+ /*
+ * For level-triggered interrupts, we set the remote IRR bit to indicate
+ * the local APIC has accepted the interrupt.
+ *
+ * For edge-triggered interrupts, we should not clear the IRR bit as it
+ * should remain intact to reflect the state of the interrupt line.
+ * The device will explicitly transition to inactive state via the
+ * ioapicSetIrq() callback.
+ */
+ if ( u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL
+ && rc == VINF_SUCCESS)
+ {
+ Assert(u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL);
+ pThis->au64RedirTable[idxRte] |= IOAPIC_RTE_REMOTE_IRR;
+ STAM_COUNTER_INC(&pThis->StatLevelIrqSent);
+ }
+ }
+}
+
+
+/**
+ * Gets the redirection table entry.
+ *
+ * @returns The redirection table entry.
+ * @param pThis Pointer to the IOAPIC instance.
+ * @param uIndex The index value.
+ */
+DECLINLINE(uint32_t) ioapicGetRedirTableEntry(PCIOAPIC pThis, uint32_t uIndex)
+{
+ uint8_t const idxRte = (uIndex - IOAPIC_INDIRECT_INDEX_REDIR_TBL_START) >> 1;
+ uint32_t uValue;
+ if (!(uIndex & 1))
+ uValue = RT_LO_U32(pThis->au64RedirTable[idxRte]) & RT_LO_U32(pThis->u64RteReadMask);
+ else
+ uValue = RT_HI_U32(pThis->au64RedirTable[idxRte]) & RT_HI_U32(pThis->u64RteReadMask);
+
+ LogFlow(("IOAPIC: ioapicGetRedirTableEntry: uIndex=%#RX32 idxRte=%u returns %#RX32\n", uIndex, idxRte, uValue));
+ return uValue;
+}
+
+
+/**
+ * Sets the redirection table entry.
+ *
+ * @param pThis Pointer to the IOAPIC instance.
+ * @param uIndex The index value.
+ * @param uValue The value to set.
+ */
+static int ioapicSetRedirTableEntry(PIOAPIC pThis, uint32_t uIndex, uint32_t uValue)
+{
+ uint8_t const idxRte = (uIndex - IOAPIC_INDIRECT_INDEX_REDIR_TBL_START) >> 1;
+ AssertMsg(idxRte < RT_ELEMENTS(pThis->au64RedirTable), ("Invalid index %u, expected <= %u\n", idxRte,
+ RT_ELEMENTS(pThis->au64RedirTable)));
+
+ int rc = IOAPIC_LOCK(pThis, VINF_IOM_R3_MMIO_WRITE);
+ if (rc == VINF_SUCCESS)
+ {
+ /*
+ * Write the low or high 32-bit value into the specified 64-bit RTE register,
+ * update only the valid, writable bits.
+ *
+ * We need to preserve the read-only bits as it can have dire consequences
+ * otherwise, see @bugref{8386#c24}.
+ */
+ uint64_t const u64Rte = pThis->au64RedirTable[idxRte];
+ if (!(uIndex & 1))
+ {
+ uint32_t const u32RtePreserveLo = RT_LO_U32(u64Rte) & ~RT_LO_U32(pThis->u64RteWriteMask);
+ uint32_t const u32RteNewLo = (uValue & RT_LO_U32(pThis->u64RteWriteMask)) | u32RtePreserveLo;
+ uint64_t const u64RteHi = u64Rte & UINT64_C(0xffffffff00000000);
+ pThis->au64RedirTable[idxRte] = u64RteHi | u32RteNewLo;
+ }
+ else
+ {
+ uint32_t const u32RtePreserveHi = RT_HI_U32(u64Rte) & ~RT_HI_U32(pThis->u64RteWriteMask);
+ uint32_t const u32RteLo = RT_LO_U32(u64Rte);
+ uint64_t const u64RteNewHi = ((uint64_t)((uValue & RT_HI_U32(pThis->u64RteWriteMask)) | u32RtePreserveHi) << 32);
+ pThis->au64RedirTable[idxRte] = u64RteNewHi | u32RteLo;
+ }
+
+ /*
+ * Signal the next pending interrupt for this RTE.
+ */
+ uint32_t const uPinMask = UINT32_C(1) << idxRte;
+ if (pThis->uIrr & uPinMask)
+ ioapicSignalIntrForRte(pThis, idxRte);
+
+ IOAPIC_UNLOCK(pThis);
+ LogFlow(("IOAPIC: ioapicSetRedirTableEntry: uIndex=%#RX32 idxRte=%u uValue=%#RX32\n", uIndex, idxRte, uValue));
+ }
+ else
+ STAM_COUNTER_INC(&pThis->StatSetRteContention);
+
+ return rc;
+}
+
+
+/**
+ * Gets the data register.
+ *
+ * @returns The data value.
+ * @param pThis Pointer to the IOAPIC instance.
+ */
+static uint32_t ioapicGetData(PCIOAPIC pThis)
+{
+ uint8_t const uIndex = pThis->u8Index;
+ RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
+ if ( uIndex >= IOAPIC_INDIRECT_INDEX_REDIR_TBL_START
+ && uIndex <= pThis->u8LastRteRegIdx)
+ return ioapicGetRedirTableEntry(pThis, uIndex);
+
+ uint32_t uValue;
+ switch (uIndex)
+ {
+ case IOAPIC_INDIRECT_INDEX_ID:
+ uValue = ioapicGetId(pThis);
+ break;
+
+ case IOAPIC_INDIRECT_INDEX_VERSION:
+ uValue = ioapicGetVersion(pThis);
+ break;
+
+ case IOAPIC_INDIRECT_INDEX_ARB:
+ if (pThis->u8ApicVer == IOAPIC_VERSION_82093AA)
+ {
+ uValue = ioapicGetArb();
+ break;
+ }
+ RT_FALL_THRU();
+
+ default:
+ uValue = UINT32_C(0xffffffff);
+ Log2(("IOAPIC: Attempt to read register at invalid index %#x\n", uIndex));
+ break;
+ }
+ return uValue;
+}
+
+
+/**
+ * Sets the data register.
+ *
+ * @param pThis Pointer to the IOAPIC instance.
+ * @param uValue The value to set.
+ */
+static int ioapicSetData(PIOAPIC pThis, uint32_t uValue)
+{
+ uint8_t const uIndex = pThis->u8Index;
+ RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
+ LogFlow(("IOAPIC: ioapicSetData: uIndex=%#x uValue=%#RX32\n", uIndex, uValue));
+
+ if ( uIndex >= IOAPIC_INDIRECT_INDEX_REDIR_TBL_START
+ && uIndex <= pThis->u8LastRteRegIdx)
+ return ioapicSetRedirTableEntry(pThis, uIndex, uValue);
+
+ if (uIndex == IOAPIC_INDIRECT_INDEX_ID)
+ ioapicSetId(pThis, uValue);
+ else
+ Log2(("IOAPIC: ioapicSetData: Invalid index %#RX32, ignoring write request with uValue=%#RX32\n", uIndex, uValue));
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{PDMIOAPICREG,pfnSetEoiR3}
+ */
+PDMBOTHCBDECL(int) ioapicSetEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)
+{
+ PIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC);
+ STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatSetEoi));
+ LogFlow(("IOAPIC: ioapicSetEoi: u8Vector=%#x (%u)\n", u8Vector, u8Vector));
+
+ bool fRemoteIrrCleared = false;
+ int rc = IOAPIC_LOCK(pThis, VINF_IOM_R3_MMIO_WRITE);
+ if (rc == VINF_SUCCESS)
+ {
+ for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)
+ {
+ uint64_t const u64Rte = pThis->au64RedirTable[idxRte];
+ if (IOAPIC_RTE_GET_VECTOR(u64Rte) == u8Vector)
+ {
+#ifdef DEBUG_ramshankar
+ /* This assertion may trigger when restoring saved-states created using the old, incorrect I/O APIC code. */
+ Assert(IOAPIC_RTE_GET_REMOTE_IRR(u64Rte));
+#endif
+ pThis->au64RedirTable[idxRte] &= ~IOAPIC_RTE_REMOTE_IRR;
+ fRemoteIrrCleared = true;
+ STAM_COUNTER_INC(&pThis->StatEoiReceived);
+ Log2(("IOAPIC: ioapicSetEoi: Cleared remote IRR, idxRte=%u vector=%#x (%u)\n", idxRte, u8Vector, u8Vector));
+
+ /*
+ * Signal the next pending interrupt for this RTE.
+ */
+ uint32_t const uPinMask = UINT32_C(1) << idxRte;
+ if (pThis->uIrr & uPinMask)
+ ioapicSignalIntrForRte(pThis, idxRte);
+ }
+ }
+
+ IOAPIC_UNLOCK(pThis);
+ AssertMsg(fRemoteIrrCleared, ("Failed to clear remote IRR for vector %#x (%u)\n", u8Vector, u8Vector));
+ }
+ else
+ STAM_COUNTER_INC(&pThis->StatEoiContention);
+
+ return rc;
+}
+
+
+/**
+ * @interface_method_impl{PDMIOAPICREG,pfnSetIrqR3}
+ */
+PDMBOTHCBDECL(void) ioapicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
+{
+#define IOAPIC_ASSERT_IRQ(a_idxRte, a_PinMask) do { \
+ pThis->au32TagSrc[(a_idxRte)] = !pThis->au32TagSrc[(a_idxRte)] ? uTagSrc : RT_BIT_32(31); \
+ pThis->uIrr |= a_PinMask; \
+ ioapicSignalIntrForRte(pThis, (a_idxRte)); \
+ } while (0)
+
+ PIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC);
+ LogFlow(("IOAPIC: ioapicSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
+
+ STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatSetIrq));
+
+ if (RT_LIKELY(iIrq >= 0 && iIrq < (int)RT_ELEMENTS(pThis->au64RedirTable)))
+ {
+ int rc = IOAPIC_LOCK(pThis, VINF_SUCCESS);
+ AssertRC(rc);
+
+ uint8_t const idxRte = iIrq;
+ uint32_t const uPinMask = UINT32_C(1) << idxRte;
+ uint32_t const u32RteLo = RT_LO_U32(pThis->au64RedirTable[idxRte]);
+ uint8_t const u8TriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u32RteLo);
+
+ bool fActive = RT_BOOL(iLevel & 1);
+ /** @todo Polarity is busted elsewhere, we need to fix that
+ * first. See @bugref{8386#c7}. */
+#if 0
+ uint8_t const u8Polarity = IOAPIC_RTE_GET_POLARITY(u32RteLo);
+ fActive ^= u8Polarity; */
+#endif
+ if (!fActive)
+ {
+ pThis->uIrr &= ~uPinMask;
+ IOAPIC_UNLOCK(pThis);
+ return;
+ }
+
+ bool const fFlipFlop = ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP);
+ uint32_t const uPrevIrr = pThis->uIrr & uPinMask;
+ if (!fFlipFlop)
+ {
+ if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_EDGE)
+ {
+ /*
+ * For edge-triggered interrupts, we need to act only on a low to high edge transition.
+ * See ICH9 spec. 13.5.7 "REDIR_TBL: Redirection Table (LPC I/F-D31:F0)".
+ */
+ if (!uPrevIrr)
+ IOAPIC_ASSERT_IRQ(idxRte, uPinMask);
+ else
+ {
+ STAM_COUNTER_INC(&pThis->StatRedundantEdgeIntr);
+ Log2(("IOAPIC: Redundant edge-triggered interrupt %#x (%u)\n", idxRte, idxRte));
+ }
+ }
+ else
+ {
+ Assert(u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL);
+
+ /*
+ * For level-triggered interrupts, redundant interrupts are not a problem
+ * and will eventually be delivered anyway after an EOI, but our PDM devices
+ * should not typically call us with no change to the level.
+ */
+ if (!uPrevIrr)
+ { /* likely */ }
+ else
+ {
+ STAM_COUNTER_INC(&pThis->StatRedundantLevelIntr);
+ Log2(("IOAPIC: Redundant level-triggered interrupt %#x (%u)\n", idxRte, idxRte));
+ }
+
+ IOAPIC_ASSERT_IRQ(idxRte, uPinMask);
+ }
+ }
+ else
+ {
+ /*
+ * The device is flip-flopping the interrupt line, which implies we should de-assert
+ * and assert the interrupt line. The interrupt line is left in the asserted state
+ * after a flip-flop request. The de-assert is a NOP wrts to signaling an interrupt
+ * hence just the assert is done.
+ */
+ IOAPIC_ASSERT_IRQ(idxRte, uPinMask);
+ }
+
+ IOAPIC_UNLOCK(pThis);
+ }
+#undef IOAPIC_ASSERT_IRQ
+}
+
+
+/**
+ * @interface_method_impl{PDMIOAPICREG,pfnSendMsiR3}
+ */
+PDMBOTHCBDECL(void) ioapicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc)
+{
+ PCIOAPIC pThis = PDMINS_2_DATA(pDevIns, PCIOAPIC);
+ LogFlow(("IOAPIC: ioapicSendMsi: GCPhys=%#RGp uValue=%#RX32\n", GCPhys, uValue));
+
+ /*
+ * Parse the message from the physical address.
+ * See Intel spec. 10.11.1 "Message Address Register Format".
+ */
+ uint8_t const u8DestAddr = (GCPhys & VBOX_MSI_ADDR_DEST_ID_MASK) >> VBOX_MSI_ADDR_DEST_ID_SHIFT;
+ uint8_t const u8DestMode = (GCPhys >> VBOX_MSI_ADDR_DEST_MODE_SHIFT) & 0x1;
+ /** @todo Check if we need to implement Redirection Hint Indicator. */
+ /* uint8_t const uRedirectHint = (GCPhys >> VBOX_MSI_ADDR_REDIRECTION_SHIFT) & 0x1; */
+
+ /*
+ * Parse the message data.
+ * See Intel spec. 10.11.2 "Message Data Register Format".
+ */
+ uint8_t const u8Vector = (uValue & VBOX_MSI_DATA_VECTOR_MASK) >> VBOX_MSI_DATA_VECTOR_SHIFT;
+ uint8_t const u8TriggerMode = (uValue >> VBOX_MSI_DATA_TRIGGER_SHIFT) & 0x1;
+ uint8_t const u8DeliveryMode = (uValue >> VBOX_MSI_DATA_DELIVERY_MODE_SHIFT) & 0x7;
+
+ /*
+ * Deliver to the local APIC via the system/3-wire-APIC bus.
+ */
+ int rc = pThis->CTX_SUFF(pIoApicHlp)->pfnApicBusDeliver(pDevIns,
+ u8DestAddr,
+ u8DestMode,
+ u8DeliveryMode,
+ u8Vector,
+ 0 /* u8Polarity - N/A */,
+ u8TriggerMode,
+ uTagSrc);
+ /* Can't reschedule to R3. */
+ Assert(rc == VINF_SUCCESS || rc == VERR_APIC_INTR_DISCARDED); NOREF(rc);
+}
+
+
+/**
+ * @callback_method_impl{FNIOMMMIOREAD}
+ */
+PDMBOTHCBDECL(int) ioapicMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
+{
+ PIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC);
+ STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMmioRead));
+ Assert(cb == 4); RT_NOREF_PV(cb); /* registered for dwords only */
+ RT_NOREF_PV(pvUser);
+
+ int rc = VINF_SUCCESS;
+ uint32_t *puValue = (uint32_t *)pv;
+ uint32_t offReg = GCPhysAddr & IOAPIC_MMIO_REG_MASK;
+ switch (offReg)
+ {
+ case IOAPIC_DIRECT_OFF_INDEX:
+ *puValue = ioapicGetIndex(pThis);
+ break;
+
+ case IOAPIC_DIRECT_OFF_DATA:
+ *puValue = ioapicGetData(pThis);
+ break;
+
+ default:
+ Log2(("IOAPIC: ioapicMmioRead: Invalid offset. GCPhysAddr=%#RGp offReg=%#x\n", GCPhysAddr, offReg));
+ rc = VINF_IOM_MMIO_UNUSED_FF;
+ break;
+ }
+
+ LogFlow(("IOAPIC: ioapicMmioRead: offReg=%#x, returns %#RX32\n", offReg, *puValue));
+ return rc;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMMMIOWRITE}
+ */
+PDMBOTHCBDECL(int) ioapicMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
+{
+ PIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC);
+ RT_NOREF_PV(pvUser);
+
+ STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMmioWrite));
+
+ Assert(!(GCPhysAddr & 3));
+ Assert(cb == 4); RT_NOREF_PV(cb); /* registered for dwords only */
+
+ uint32_t const uValue = *(uint32_t const *)pv;
+ uint32_t const offReg = GCPhysAddr & IOAPIC_MMIO_REG_MASK;
+
+ LogFlow(("IOAPIC: ioapicMmioWrite: pThis=%p GCPhysAddr=%#RGp cb=%u uValue=%#RX32\n", pThis, GCPhysAddr, cb, uValue));
+ int rc = VINF_SUCCESS;
+ switch (offReg)
+ {
+ case IOAPIC_DIRECT_OFF_INDEX:
+ ioapicSetIndex(pThis, uValue);
+ break;
+
+ case IOAPIC_DIRECT_OFF_DATA:
+ rc = ioapicSetData(pThis, uValue);
+ break;
+
+ case IOAPIC_DIRECT_OFF_EOI:
+ if (pThis->u8ApicVer == IOAPIC_VERSION_ICH9)
+ rc = ioapicSetEoi(pDevIns, uValue);
+ else
+ Log(("IOAPIC: ioapicMmioWrite: Write to EOI register ignored!\n"));
+ break;
+
+ default:
+ Log2(("IOAPIC: ioapicMmioWrite: Invalid offset. GCPhysAddr=%#RGp offReg=%#x\n", GCPhysAddr, offReg));
+ break;
+ }
+
+ return rc;
+}
+
+
+#ifdef IN_RING3
+
+/** @interface_method_impl{DBGFREGDESC,pfnGet} */
+static DECLCALLBACK(int) ioapicDbgReg_GetIndex(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
+{
+ RT_NOREF(pDesc);
+ pValue->u32 = ioapicGetIndex(PDMINS_2_DATA((PPDMDEVINS)pvUser, PCIOAPIC));
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{DBGFREGDESC,pfnSet} */
+static DECLCALLBACK(int) ioapicDbgReg_SetIndex(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
+{
+ RT_NOREF(pDesc, pfMask);
+ ioapicSetIndex(PDMINS_2_DATA((PPDMDEVINS)pvUser, PIOAPIC), pValue->u8);
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{DBGFREGDESC,pfnGet} */
+static DECLCALLBACK(int) ioapicDbgReg_GetData(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
+{
+ RT_NOREF(pDesc);
+ pValue->u32 = ioapicGetData((PDMINS_2_DATA((PPDMDEVINS)pvUser, PCIOAPIC)));
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{DBGFREGDESC,pfnSet} */
+static DECLCALLBACK(int) ioapicDbgReg_SetData(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
+{
+ RT_NOREF(pDesc, pfMask);
+ return ioapicSetData(PDMINS_2_DATA((PPDMDEVINS)pvUser, PIOAPIC), pValue->u32);
+}
+
+
+/** @interface_method_impl{DBGFREGDESC,pfnGet} */
+static DECLCALLBACK(int) ioapicDbgReg_GetVersion(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
+{
+ PCIOAPIC pThis = PDMINS_2_DATA((PPDMDEVINS)pvUser, PCIOAPIC);
+ RT_NOREF(pDesc);
+ pValue->u32 = ioapicGetVersion(pThis);
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{DBGFREGDESC,pfnGet} */
+static DECLCALLBACK(int) ioapicDbgReg_GetArb(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
+{
+ RT_NOREF(pvUser, pDesc);
+ pValue->u32 = ioapicGetArb();
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{DBGFREGDESC,pfnGet} */
+static DECLCALLBACK(int) ioapicDbgReg_GetRte(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
+{
+ PCIOAPIC pThis = PDMINS_2_DATA((PPDMDEVINS)pvUser, PCIOAPIC);
+ Assert(pDesc->offRegister < RT_ELEMENTS(pThis->au64RedirTable));
+ pValue->u64 = pThis->au64RedirTable[pDesc->offRegister];
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{DBGFREGDESC,pfnSet} */
+static DECLCALLBACK(int) ioapicDbgReg_SetRte(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
+{
+ RT_NOREF(pfMask);
+ PIOAPIC pThis = PDMINS_2_DATA((PPDMDEVINS)pvUser, PIOAPIC);
+ /* No locks, no checks, just do it. */
+ Assert(pDesc->offRegister < RT_ELEMENTS(pThis->au64RedirTable));
+ pThis->au64RedirTable[pDesc->offRegister] = pValue->u64;
+ return VINF_SUCCESS;
+}
+
+
+/** IOREDTBLn sub fields. */
+static DBGFREGSUBFIELD const g_aRteSubs[] =
+{
+ { "vector", 0, 8, 0, 0, NULL, NULL },
+ { "dlvr_mode", 8, 3, 0, 0, NULL, NULL },
+ { "dest_mode", 11, 1, 0, 0, NULL, NULL },
+ { "dlvr_status", 12, 1, 0, DBGFREGSUBFIELD_FLAGS_READ_ONLY, NULL, NULL },
+ { "polarity", 13, 1, 0, 0, NULL, NULL },
+ { "remote_irr", 14, 1, 0, DBGFREGSUBFIELD_FLAGS_READ_ONLY, NULL, NULL },
+ { "trigger_mode", 15, 1, 0, 0, NULL, NULL },
+ { "mask", 16, 1, 0, 0, NULL, NULL },
+ { "ext_dest_id", 48, 8, 0, DBGFREGSUBFIELD_FLAGS_READ_ONLY, NULL, NULL },
+ { "dest", 56, 8, 0, 0, NULL, NULL },
+ DBGFREGSUBFIELD_TERMINATOR()
+};
+
+
+/** Register descriptors for DBGF. */
+static DBGFREGDESC const g_aRegDesc[] =
+{
+ { "index", DBGFREG_END, DBGFREGVALTYPE_U8, 0, 0, ioapicDbgReg_GetIndex, ioapicDbgReg_SetIndex, NULL, NULL },
+ { "data", DBGFREG_END, DBGFREGVALTYPE_U32, 0, 0, ioapicDbgReg_GetData, ioapicDbgReg_SetData, NULL, NULL },
+ { "version", DBGFREG_END, DBGFREGVALTYPE_U32, DBGFREG_FLAGS_READ_ONLY, 0, ioapicDbgReg_GetVersion, NULL, NULL, NULL },
+ { "arb", DBGFREG_END, DBGFREGVALTYPE_U32, DBGFREG_FLAGS_READ_ONLY, 0, ioapicDbgReg_GetArb, NULL, NULL, NULL },
+ { "rte0", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 0, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte1", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 1, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte2", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 2, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte3", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 3, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte4", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 4, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte5", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 5, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte6", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 6, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte7", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 7, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte8", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 8, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte9", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 9, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte10", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 10, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte11", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 11, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte12", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 12, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte13", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 13, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte14", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 14, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte15", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 15, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte16", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 16, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte17", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 17, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte18", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 18, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte19", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 19, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte20", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 20, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte21", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 21, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte22", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 22, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ { "rte23", DBGFREG_END, DBGFREGVALTYPE_U64, 0, 23, ioapicDbgReg_GetRte, ioapicDbgReg_SetRte, NULL, &g_aRteSubs[0] },
+ DBGFREGDESC_TERMINATOR()
+};
+
+
+/**
+ * @callback_method_impl{FNDBGFHANDLERDEV}
+ */
+static DECLCALLBACK(void) ioapicR3DbgInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+ RT_NOREF(pszArgs);
+ PCIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC);
+ LogFlow(("IOAPIC: ioapicR3DbgInfo: pThis=%p pszArgs=%s\n", pThis, pszArgs));
+
+ pHlp->pfnPrintf(pHlp, "I/O APIC at %#010x:\n", IOAPIC_MMIO_BASE_PHYSADDR);
+
+ uint32_t const uId = ioapicGetId(pThis);
+ pHlp->pfnPrintf(pHlp, " ID = %#RX32\n", uId);
+ pHlp->pfnPrintf(pHlp, " ID = %#x\n", IOAPIC_ID_GET_ID(uId));
+
+ uint32_t const uVer = ioapicGetVersion(pThis);
+ pHlp->pfnPrintf(pHlp, " Version = %#RX32\n", uVer);
+ pHlp->pfnPrintf(pHlp, " Version = %#x\n", IOAPIC_VER_GET_VER(uVer));
+ pHlp->pfnPrintf(pHlp, " Pin Assert Reg. Support = %RTbool\n", IOAPIC_VER_HAS_PRQ(uVer));
+ pHlp->pfnPrintf(pHlp, " Max. Redirection Entry = %u\n", IOAPIC_VER_GET_MRE(uVer));
+
+ if (pThis->u8ApicVer == IOAPIC_VERSION_82093AA)
+ {
+ uint32_t const uArb = ioapicGetArb();
+ pHlp->pfnPrintf(pHlp, " Arbitration = %#RX32\n", uArb);
+ pHlp->pfnPrintf(pHlp, " Arbitration ID = %#x\n", IOAPIC_ARB_GET_ID(uArb));
+ }
+
+ pHlp->pfnPrintf(pHlp, " Current index = %#x\n", ioapicGetIndex(pThis));
+
+ pHlp->pfnPrintf(pHlp, " I/O Redirection Table and IRR:\n");
+ pHlp->pfnPrintf(pHlp, " idx dst_mode dst_addr mask irr trigger rirr polar dlvr_st dlvr_mode vector\n");
+
+ for (uint8_t idxRte = 0; idxRte <= pThis->u8MaxRte; idxRte++)
+ {
+ static const char * const s_apszDeliveryModes[] =
+ {
+ "Fixed ",
+ "LowPri",
+ "SMI ",
+ "Rsvd ",
+ "NMI ",
+ "INIT ",
+ "Rsvd ",
+ "ExtINT"
+ };
+
+ const uint64_t u64Rte = pThis->au64RedirTable[idxRte];
+ const char *pszDestMode = IOAPIC_RTE_GET_DEST_MODE(u64Rte) == 0 ? "phys" : "log ";
+ const uint8_t uDest = IOAPIC_RTE_GET_DEST(u64Rte);
+ const uint8_t uMask = IOAPIC_RTE_GET_MASK(u64Rte);
+ const char *pszTriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u64Rte) == 0 ? "edge " : "level";
+ const uint8_t uRemoteIrr = IOAPIC_RTE_GET_REMOTE_IRR(u64Rte);
+ const char *pszPolarity = IOAPIC_RTE_GET_POLARITY(u64Rte) == 0 ? "acthi" : "actlo";
+ const char *pszDeliveryStatus = IOAPIC_RTE_GET_DELIVERY_STATUS(u64Rte) == 0 ? "idle" : "pend";
+ const uint8_t uDeliveryMode = IOAPIC_RTE_GET_DELIVERY_MODE(u64Rte);
+ Assert(uDeliveryMode < RT_ELEMENTS(s_apszDeliveryModes));
+ const char *pszDeliveryMode = s_apszDeliveryModes[uDeliveryMode];
+ const uint8_t uVector = IOAPIC_RTE_GET_VECTOR(u64Rte);
+
+ pHlp->pfnPrintf(pHlp, " %02d %s %02x %u %u %s %u %s %s %s %3u (%016llx)\n",
+ idxRte,
+ pszDestMode,
+ uDest,
+ uMask,
+ (pThis->uIrr >> idxRte) & 1,
+ pszTriggerMode,
+ uRemoteIrr,
+ pszPolarity,
+ pszDeliveryStatus,
+ pszDeliveryMode,
+ uVector,
+ u64Rte);
+ }
+}
+
+
+/**
+ * @copydoc FNSSMDEVSAVEEXEC
+ */
+static DECLCALLBACK(int) ioapicR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+ PCIOAPIC pThis = PDMINS_2_DATA(pDevIns, PCIOAPIC);
+ LogFlow(("IOAPIC: ioapicR3SaveExec\n"));
+
+ SSMR3PutU32(pSSM, pThis->uIrr);
+ SSMR3PutU8(pSSM, pThis->u8Id);
+ SSMR3PutU8(pSSM, pThis->u8Index);
+ for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)
+ SSMR3PutU64(pSSM, pThis->au64RedirTable[idxRte]);
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @copydoc FNSSMDEVLOADEXEC
+ */
+static DECLCALLBACK(int) ioapicR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+{
+ PIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC);
+ LogFlow(("APIC: apicR3LoadExec: uVersion=%u uPass=%#x\n", uVersion, uPass));
+
+ Assert(uPass == SSM_PASS_FINAL);
+ NOREF(uPass);
+
+ /* Weed out invalid versions. */
+ if ( uVersion != IOAPIC_SAVED_STATE_VERSION
+ && uVersion != IOAPIC_SAVED_STATE_VERSION_VBOX_50)
+ {
+ LogRel(("IOAPIC: ioapicR3LoadExec: Invalid/unrecognized saved-state version %u (%#x)\n", uVersion, uVersion));
+ return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
+ }
+
+ if (uVersion == IOAPIC_SAVED_STATE_VERSION)
+ SSMR3GetU32(pSSM, (uint32_t *)&pThis->uIrr);
+
+ SSMR3GetU8(pSSM, (uint8_t *)&pThis->u8Id);
+ SSMR3GetU8(pSSM, (uint8_t *)&pThis->u8Index);
+ for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)
+ SSMR3GetU64(pSSM, &pThis->au64RedirTable[idxRte]);
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnReset}
+ */
+static DECLCALLBACK(void) ioapicR3Reset(PPDMDEVINS pDevIns)
+{
+ PIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC);
+ LogFlow(("IOAPIC: ioapicR3Reset: pThis=%p\n", pThis));
+
+ /* There might be devices threads calling ioapicSetIrq() in parallel, hence the lock. */
+ IOAPIC_LOCK(pThis, VERR_IGNORED);
+
+ pThis->uIrr = 0;
+ pThis->u8Index = 0;
+ pThis->u8Id = 0;
+
+ for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)
+ {
+ pThis->au64RedirTable[idxRte] = IOAPIC_RTE_MASK;
+ pThis->au32TagSrc[idxRte] = 0;
+ }
+
+ IOAPIC_UNLOCK(pThis);
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnRelocate}
+ */
+static DECLCALLBACK(void) ioapicR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
+{
+ RT_NOREF(offDelta);
+ PIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC);
+ LogFlow(("IOAPIC: ioapicR3Relocate: pThis=%p offDelta=%RGi\n", pThis, offDelta));
+
+ pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+ pThis->pIoApicHlpRC = pThis->pIoApicHlpR3->pfnGetRCHelpers(pDevIns);
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnDestruct}
+ */
+static DECLCALLBACK(int) ioapicR3Destruct(PPDMDEVINS pDevIns)
+{
+ PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
+ PIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC);
+ LogFlow(("IOAPIC: ioapicR3Destruct: pThis=%p\n", pThis));
+
+# ifndef IOAPIC_WITH_PDM_CRITSECT
+ /*
+ * Destroy the RTE critical section.
+ */
+ if (PDMCritSectIsInitialized(&pThis->CritSect))
+ PDMR3CritSectDelete(&pThis->CritSect);
+# else
+ RT_NOREF_PV(pThis);
+# endif
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnConstruct}
+ */
+static DECLCALLBACK(int) ioapicR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
+{
+ PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+ PIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC);
+ LogFlow(("IOAPIC: ioapicR3Construct: pThis=%p iInstance=%d\n", pThis, iInstance));
+ Assert(iInstance == 0); RT_NOREF(iInstance);
+
+ /*
+ * Initialize the state data.
+ */
+ pThis->pDevInsR3 = pDevIns;
+ pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
+ pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+
+ /*
+ * Validate and read the configuration.
+ */
+ PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "NumCPUs|RZEnabled|ChipType", "");
+
+ /* The number of CPUs is currently unused, but left in CFGM and saved-state in case an ID of 0 is
+ upsets some guest which we haven't yet tested. */
+ uint32_t cCpus;
+ int rc = CFGMR3QueryU32Def(pCfg, "NumCPUs", &cCpus, 1);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to query integer value \"NumCPUs\""));
+ pThis->cCpus = (uint8_t)cCpus;
+
+ bool fRZEnabled;
+ rc = CFGMR3QueryBoolDef(pCfg, "RZEnabled", &fRZEnabled, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to query boolean value \"RZEnabled\""));
+
+ char szChipType[16];
+ rc = CFGMR3QueryStringDef(pCfg, "ChipType", &szChipType[0], sizeof(szChipType), "ICH9");
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to query string value \"ChipType\""));
+
+ if (!strcmp(szChipType, "ICH9"))
+ {
+ /* Newer 2007-ish I/O APIC integrated into ICH southbridges. */
+ pThis->u8ApicVer = IOAPIC_VERSION_ICH9;
+ pThis->u8IdMask = 0xff;
+ pThis->u8MaxRte = IOAPIC_MAX_RTE_INDEX;
+ pThis->u8LastRteRegIdx = IOAPIC_INDIRECT_INDEX_RTE_END;
+ pThis->u64RteWriteMask = IOAPIC_RTE_VALID_WRITE_MASK_ICH9;
+ pThis->u64RteReadMask = IOAPIC_RTE_VALID_READ_MASK_ICH9;
+ }
+ else if (!strcmp(szChipType, "82093AA"))
+ {
+ /* Older 1995-ish discrete I/O APIC, used in P6 class systems. */
+ pThis->u8ApicVer = IOAPIC_VERSION_82093AA;
+ pThis->u8IdMask = 0x0f;
+ pThis->u8MaxRte = IOAPIC_MAX_RTE_INDEX;
+ pThis->u8LastRteRegIdx = IOAPIC_INDIRECT_INDEX_RTE_END;
+ pThis->u64RteWriteMask = IOAPIC_RTE_VALID_WRITE_MASK_82093AA;
+ pThis->u64RteReadMask = IOAPIC_RTE_VALID_READ_MASK_82093AA;
+ }
+ else if (!strcmp(szChipType, "82379AB"))
+ {
+ /* Even older 1993-ish I/O APIC built into SIO.A, used in EISA and early PCI systems. */
+ /* Exact same version and behavior as 82093AA, only the number of RTEs is different. */
+ pThis->u8ApicVer = IOAPIC_VERSION_82093AA;
+ pThis->u8IdMask = 0x0f;
+ pThis->u8MaxRte = IOAPIC_REDUCED_MAX_RTE_INDEX;
+ pThis->u8LastRteRegIdx = IOAPIC_REDUCED_INDIRECT_INDEX_RTE_END;
+ pThis->u64RteWriteMask = IOAPIC_RTE_VALID_WRITE_MASK_82093AA;
+ pThis->u64RteReadMask = IOAPIC_RTE_VALID_READ_MASK_82093AA;
+ }
+ else
+ {
+ return PDMDevHlpVMSetError(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES, RT_SRC_POS,
+ N_("I/O APIC configuration error: The \"ChipType\" value \"%s\" is unsupported"),
+ szChipType);
+ }
+ Log2(("IOAPIC: cCpus=%u fRZEnabled=%RTbool szChipType=%s\n", cCpus, fRZEnabled, szChipType));
+
+ /*
+ * We will use our own critical section for the IOAPIC device.
+ */
+ rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
+ AssertRCReturn(rc, rc);
+
+# ifndef IOAPIC_WITH_PDM_CRITSECT
+ /*
+ * Setup the critical section to protect concurrent writes to the RTEs.
+ */
+ rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "IOAPIC");
+ if (RT_FAILURE(rc))
+ return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("IOAPIC: Failed to create critical section. rc=%Rrc"), rc);
+# endif
+
+ /*
+ * Register the IOAPIC.
+ */
+ PDMIOAPICREG IoApicReg;
+ RT_ZERO(IoApicReg);
+ IoApicReg.u32Version = PDM_IOAPICREG_VERSION;
+ IoApicReg.pfnSetIrqR3 = ioapicSetIrq;
+ IoApicReg.pfnSendMsiR3 = ioapicSendMsi;
+ IoApicReg.pfnSetEoiR3 = ioapicSetEoi;
+ if (fRZEnabled)
+ {
+ IoApicReg.pszSetIrqRC = "ioapicSetIrq";
+ IoApicReg.pszSetIrqR0 = "ioapicSetIrq";
+
+ IoApicReg.pszSendMsiRC = "ioapicSendMsi";
+ IoApicReg.pszSendMsiR0 = "ioapicSendMsi";
+
+ IoApicReg.pszSetEoiRC = "ioapicSetEoi";
+ IoApicReg.pszSetEoiR0 = "ioapicSetEoi";
+ }
+ rc = PDMDevHlpIOAPICRegister(pDevIns, &IoApicReg, &pThis->pIoApicHlpR3);
+ if (RT_FAILURE(rc))
+ {
+ AssertMsgFailed(("IOAPIC: PDMDevHlpIOAPICRegister failed! rc=%Rrc\n", rc));
+ return rc;
+ }
+
+ /*
+ * Register MMIO callbacks.
+ */
+ rc = PDMDevHlpMMIORegister(pDevIns, IOAPIC_MMIO_BASE_PHYSADDR, IOAPIC_MMIO_SIZE, pThis,
+ IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_DWORD_ZEROED, ioapicMmioWrite, ioapicMmioRead,
+ "I/O APIC");
+ if (RT_SUCCESS(rc))
+ {
+ if (fRZEnabled)
+ {
+ pThis->pIoApicHlpRC = pThis->pIoApicHlpR3->pfnGetRCHelpers(pDevIns);
+ rc = PDMDevHlpMMIORegisterRC(pDevIns, IOAPIC_MMIO_BASE_PHYSADDR, IOAPIC_MMIO_SIZE, NIL_RTRCPTR /* pvUser */,
+ "ioapicMmioWrite", "ioapicMmioRead");
+ AssertRCReturn(rc, rc);
+
+ pThis->pIoApicHlpR0 = pThis->pIoApicHlpR3->pfnGetR0Helpers(pDevIns);
+ rc = PDMDevHlpMMIORegisterR0(pDevIns, IOAPIC_MMIO_BASE_PHYSADDR, IOAPIC_MMIO_SIZE, NIL_RTR0PTR /* pvUser */,
+ "ioapicMmioWrite", "ioapicMmioRead");
+ AssertRCReturn(rc, rc);
+ }
+ }
+ else
+ {
+ LogRel(("IOAPIC: PDMDevHlpMMIORegister failed! rc=%Rrc\n", rc));
+ return rc;
+ }
+
+ /*
+ * Register saved-state callbacks.
+ */
+ rc = PDMDevHlpSSMRegister(pDevIns, IOAPIC_SAVED_STATE_VERSION, sizeof(*pThis), ioapicR3SaveExec, ioapicR3LoadExec);
+ if (RT_FAILURE(rc))
+ {
+ LogRel(("IOAPIC: PDMDevHlpSSMRegister failed! rc=%Rrc\n", rc));
+ return rc;
+ }
+
+ /*
+ * Register debugger info callback.
+ */
+ rc = PDMDevHlpDBGFInfoRegister(pDevIns, "ioapic", "Display IO APIC state.", ioapicR3DbgInfo);
+ AssertRCReturn(rc, rc);
+
+ /*
+ * Register debugger register access.
+ */
+ rc = PDMDevHlpDBGFRegRegister(pDevIns, g_aRegDesc); AssertRC(rc);
+ AssertRCReturn(rc, rc);
+
+# ifdef VBOX_WITH_STATISTICS
+ /*
+ * Statistics.
+ */
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioReadRZ, STAMTYPE_COUNTER, "/Devices/IOAPIC/RZ/MmioReadRZ", STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO reads in RZ.");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioWriteRZ, STAMTYPE_COUNTER, "/Devices/IOAPIC/RZ/MmioWriteRZ", STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO writes in RZ.");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetIrqRZ, STAMTYPE_COUNTER, "/Devices/IOAPIC/RZ/SetIrqRZ", STAMUNIT_OCCURENCES, "Number of IOAPIC SetIrq calls in RZ.");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetEoiRZ, STAMTYPE_COUNTER, "/Devices/IOAPIC/RZ/SetEoiRZ", STAMUNIT_OCCURENCES, "Number of IOAPIC SetEoi calls in RZ.");
+
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioReadR3, STAMTYPE_COUNTER, "/Devices/IOAPIC/R3/MmioReadR3", STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO reads in R3");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioWriteR3, STAMTYPE_COUNTER, "/Devices/IOAPIC/R3/MmioWriteR3", STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO writes in R3.");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetIrqR3, STAMTYPE_COUNTER, "/Devices/IOAPIC/R3/SetIrqR3", STAMUNIT_OCCURENCES, "Number of IOAPIC SetIrq calls in R3.");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetEoiR3, STAMTYPE_COUNTER, "/Devices/IOAPIC/R3/SetEoiR3", STAMUNIT_OCCURENCES, "Number of IOAPIC SetEoi calls in R3.");
+
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRedundantEdgeIntr, STAMTYPE_COUNTER, "/Devices/IOAPIC/RedundantEdgeIntr", STAMUNIT_OCCURENCES, "Number of redundant edge-triggered interrupts (no IRR change).");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRedundantLevelIntr, STAMTYPE_COUNTER, "/Devices/IOAPIC/RedundantLevelIntr", STAMUNIT_OCCURENCES, "Number of redundant level-triggered interrupts (no IRR change).");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSuppressedLevelIntr, STAMTYPE_COUNTER, "/Devices/IOAPIC/SuppressedLevelIntr", STAMUNIT_OCCURENCES, "Number of suppressed level-triggered interrupts by remote IRR.");
+
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatEoiContention, STAMTYPE_COUNTER, "/Devices/IOAPIC/CritSect/ContentionSetEoi", STAMUNIT_OCCURENCES, "Number of times the critsect is busy during EOI writes causing trips to R3.");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetRteContention, STAMTYPE_COUNTER, "/Devices/IOAPIC/CritSect/ContentionSetRte", STAMUNIT_OCCURENCES, "Number of times the critsect is busy during RTE writes causing trips to R3.");
+
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatLevelIrqSent, STAMTYPE_COUNTER, "/Devices/IOAPIC/LevelIntr/Sent", STAMUNIT_OCCURENCES, "Number of level-triggered interrupts sent to the local APIC(s).");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatEoiReceived, STAMTYPE_COUNTER, "/Devices/IOAPIC/LevelIntr/Recv", STAMUNIT_OCCURENCES, "Number of EOIs received for level-triggered interrupts from the local APIC(s).");
+# endif
+
+ /*
+ * Init. the device state.
+ */
+ LogRel(("IOAPIC: Using implementation 2.0! Chipset type %s\n", szChipType));
+ ioapicR3Reset(pDevIns);
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * IO APIC device registration structure.
+ */
+const PDMDEVREG g_DeviceIOAPIC =
+{
+ /* u32Version */
+ PDM_DEVREG_VERSION,
+ /* szName */
+ "ioapic",
+ /* szRCMod */
+ "VBoxDDRC.rc",
+ /* szR0Mod */
+ "VBoxDDR0.r0",
+ /* pszDescription */
+ "I/O Advanced Programmable Interrupt Controller (IO-APIC) Device",
+ /* fFlags */
+ PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36
+ | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
+ /* fClass */
+ PDM_DEVREG_CLASS_PIC,
+ /* cMaxInstances */
+ 1,
+ /* cbInstance */
+ sizeof(IOAPIC),
+ /* pfnConstruct */
+ ioapicR3Construct,
+ /* pfnDestruct */
+ ioapicR3Destruct,
+ /* pfnRelocate */
+ ioapicR3Relocate,
+ /* pfnMemSetup */
+ NULL,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ ioapicR3Reset,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnAttach */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnQueryInterface. */
+ NULL,
+ /* pfnInitComplete */
+ NULL,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32VersionEnd */
+ PDM_DEVREG_VERSION
+};
+
+#endif /* IN_RING3 */
+
+#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
+
diff --git a/src/VBox/Devices/PC/DevLpc-new.cpp b/src/VBox/Devices/PC/DevLpc-new.cpp
new file mode 100644
index 00000000..98c4c718
--- /dev/null
+++ b/src/VBox/Devices/PC/DevLpc-new.cpp
@@ -0,0 +1,442 @@
+/* $Id: DevLpc-new.cpp $ */
+/** @file
+ * DevLPC - Minimal ICH9 LPC device emulation.
+ */
+
+/*
+ * Copyright (C) 2018-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_LPC
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/vmm/stam.h>
+#include <VBox/log.h>
+
+#include <iprt/assert.h>
+#include <iprt/string.h>
+
+#include "VBoxDD.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+#define LPC_REG_HPET_CONFIG_POINTER 0x3404
+#define LPC_REG_GCS 0x3410
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * The ICH9 LPC state.
+ */
+typedef struct LPCSTATE
+{
+ /** The PCI device. */
+ PDMPCIDEV PciDev;
+ /** Pointer to the ring-3 device instance. */
+ PPDMDEVINSR3 pDevInsR3;
+
+ /** The root complex base address. */
+ RTGCPHYS32 GCPhys32Rcba;
+ /** Set if R0/RC context is enabled. */
+ bool fRZEnabled;
+ /** The ICH version (7 or 9). */
+ uint8_t uIchVersion;
+ /** Explicit padding. */
+ uint8_t abPadding[HC_ARCH_BITS == 32 ? 2 : 6];
+
+ /** Pointer to generic PCI config reader. */
+ R3PTRTYPE(PFNPCICONFIGREAD) pfnPciConfigReadFallback;
+ /** Pointer to generic PCI config write. */
+ R3PTRTYPE(PFNPCICONFIGWRITE) pfnPciConfigWriteFallback;
+
+ /** Number of MMIO reads. */
+ STAMCOUNTER StatMmioReads;
+ /** Number of MMIO writes. */
+ STAMCOUNTER StatMmioWrites;
+ /** Number of PCI config space reads. */
+ STAMCOUNTER StatPciCfgReads;
+ /** Number of PCI config space writes. */
+ STAMCOUNTER StatPciCfgWrites;
+} LPCSTATE;
+/** Pointer to the LPC state. */
+typedef LPCSTATE *PLPCSTATE;
+
+
+#ifndef VBOX_DEVICE_STRUCT_TESTCASE
+
+/**
+ * @callback_method_impl{FNIOMMMIOREAD}
+ */
+PDMBOTHCBDECL(int) lpcMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
+{
+ RT_NOREF(pvUser, cb);
+ PLPCSTATE pThis = PDMINS_2_DATA(pDevIns, PLPCSTATE);
+ RTGCPHYS32 const offReg = (RTGCPHYS32)GCPhysAddr - pThis->GCPhys32Rcba;
+ Assert(cb == 4); Assert(!(GCPhysAddr & 3)); /* IOMMMIO_FLAGS_READ_DWORD should make sure of this */
+
+ uint32_t *puValue = (uint32_t *)pv;
+ if (offReg == LPC_REG_HPET_CONFIG_POINTER)
+ {
+ *puValue = 0xf0;
+ Log(("lpcMmioRead: HPET_CONFIG_POINTER: %#x\n", *puValue));
+ }
+ else if (offReg == LPC_REG_GCS)
+ {
+ *puValue = 0;
+ Log(("lpcMmioRead: GCS: %#x\n", *puValue));
+ }
+ else
+ {
+ *puValue = 0;
+ Log(("lpcMmioRead: WARNING! Unknown register %#x!\n", offReg));
+ }
+
+ STAM_REL_COUNTER_INC(&pThis->StatMmioReads);
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMMMIOWRITE}
+ */
+PDMBOTHCBDECL(int) lpcMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
+{
+ RT_NOREF(pvUser, pv);
+ PLPCSTATE pThis = PDMINS_2_DATA(pDevIns, PLPCSTATE);
+ RTGCPHYS32 const offReg = (RTGCPHYS32)GCPhysAddr - pThis->GCPhys32Rcba;
+
+ if (cb == 4)
+ {
+ if (offReg == LPC_REG_GCS)
+ Log(("lpcMmioWrite: Ignorning write to GCS: %.*Rhxs\n", cb, pv));
+ else
+ Log(("lpcMmioWrite: Ignorning write to unknown register %#x: %.*Rhxs\n", offReg, cb, pv));
+ }
+ else
+ Log(("lpcMmioWrite: WARNING! Ignoring non-DWORD write to offReg=%#x: %.*Rhxs\n", offReg, cb, pv));
+
+ STAM_REL_COUNTER_INC(&pThis->StatMmioWrites);
+ return VINF_SUCCESS;
+}
+
+#ifdef IN_RING3
+
+/**
+ * @callback_method_impl{FNPCICONFIGREAD}
+ */
+static DECLCALLBACK(uint32_t) lpcPciConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress, unsigned cb)
+{
+ PLPCSTATE pThis = PDMINS_2_DATA(pDevIns, PLPCSTATE);
+ Assert(pPciDev == &pThis->PciDev);
+
+ STAM_REL_COUNTER_INC(&pThis->StatPciCfgReads);
+ uint32_t uValue = pThis->pfnPciConfigReadFallback(pDevIns, pPciDev, uAddress, cb);
+ switch (cb)
+ {
+ case 1: Log(("lpcPciConfigRead: %#04x -> %#04x\n", uAddress, uValue)); break;
+ case 2: Log(("lpcPciConfigRead: %#04x -> %#06x\n", uAddress, uValue)); break;
+ case 4: Log(("lpcPciConfigRead: %#04x -> %#010x\n", uAddress, uValue)); break;
+ }
+ return uValue;
+}
+
+
+/**
+ * @callback_method_impl{FNPCICONFIGWRITE}
+ */
+static DECLCALLBACK(VBOXSTRICTRC)
+lpcPciConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress, uint32_t u32Value, unsigned cb)
+{
+ PLPCSTATE pThis = PDMINS_2_DATA(pDevIns, PLPCSTATE);
+ Assert(pPciDev == &pThis->PciDev);
+
+ STAM_REL_COUNTER_INC(&pThis->StatPciCfgWrites);
+ switch (cb)
+ {
+ case 1: Log(("lpcPciConfigWrite: %#04x <- %#04x\n", uAddress, u32Value)); break;
+ case 2: Log(("lpcPciConfigWrite: %#04x <- %#06x\n", uAddress, u32Value)); break;
+ case 4: Log(("lpcPciConfigWrite: %#04x <- %#010x\n", uAddress, u32Value)); break;
+ }
+
+ return pThis->pfnPciConfigWriteFallback(pDevIns, pPciDev, uAddress, u32Value, cb);
+}
+
+
+/**
+ * Info handler, device version.
+ *
+ * @param pDevIns Device instance which registered the info.
+ * @param pHlp Callback functions for doing output.
+ * @param pszArgs Argument string. Optional and specific to the handler.
+ */
+static DECLCALLBACK(void) lpcInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+ PLPCSTATE pThis = PDMINS_2_DATA(pDevIns, PLPCSTATE);
+ RT_NOREF(pszArgs);
+
+ if (pThis->uIchVersion == 7)
+ {
+ uint8_t b1 = PDMPciDevGetByte(&pThis->PciDev, 0xde);
+ uint8_t b2 = PDMPciDevGetByte(&pThis->PciDev, 0xad);
+ if ( b1 == 0xbe
+ && b2 == 0xef)
+ pHlp->pfnPrintf(pHlp, "APIC backdoor activated\n");
+ else
+ pHlp->pfnPrintf(pHlp, "APIC backdoor closed: %02x %02x\n", b1, b2);
+ }
+
+ for (unsigned iLine = 0; iLine < 8; iLine++)
+ {
+ unsigned offBase = iLine < 4 ? 0x60 : 0x68 - 4;
+ uint8_t bMap = PDMPciDevGetByte(&pThis->PciDev, offBase + iLine);
+ if (bMap & 0x80)
+ pHlp->pfnPrintf(pHlp, "PIRQ%c_ROUT disabled\n", 'A' + iLine);
+ else
+ pHlp->pfnPrintf(pHlp, "PIRQ%c_ROUT -> IRQ%d\n", 'A' + iLine, bMap & 0xf);
+ }
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnConstruct}
+ */
+static DECLCALLBACK(int) lpcConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
+{
+ PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+ PLPCSTATE pThis = PDMINS_2_DATA(pDevIns, PLPCSTATE);
+ Assert(iInstance == 0); RT_NOREF(iInstance);
+
+ /*
+ * Initialize state.
+ */
+ pThis->pDevInsR3 = pDevIns;
+
+ /*
+ * Read configuration.
+ */
+ PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "RZEnabled|RCBA|ICHVersion", "");
+
+ int rc = CFGMR3QueryBoolDef(pCfg, "RZEnabled", &pThis->fRZEnabled, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to query boolean value \"RZEnabled\""));
+
+ rc = CFGMR3QueryU8Def(pCfg, "ICHVersion", &pThis->uIchVersion, 7 /** @todo 9 */);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to query boolean value \"ICHVersion\""));
+ if ( pThis->uIchVersion != 7
+ && pThis->uIchVersion != 9)
+ return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Invalid \"ICHVersion\" value (must be 7 or 9)"));
+
+ rc = CFGMR3QueryU32Def(pCfg, "RCBA", &pThis->GCPhys32Rcba, UINT32_C(0xfed1c000));
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to query boolean value \"RCBA\""));
+
+
+ /*
+ * Register the PCI device.
+ *
+ * See sections 13.1 (page 371) and section 13.8.1 (page 429) in the ICH9
+ * specification.
+ *
+ * We set these up so they don't need much/any configuration from the
+ * guest. This is quite possibly wrong, but at the moment we just need to
+ * have this device working w/o lots of firmware fun.
+ */
+ PDMPciDevSetVendorId( &pThis->PciDev, 0x8086); /* Intel */
+ if (pThis->uIchVersion == 7)
+ PDMPciDevSetDeviceId( &pThis->PciDev, 0x27b9);
+ else if (pThis->uIchVersion == 9)
+ PDMPciDevSetDeviceId( &pThis->PciDev, 0x2918); /** @todo unsure if 0x2918 is the right PCI ID... */
+ else
+ AssertFailedReturn(VERR_INTERNAL_ERROR_3);
+ PDMPciDevSetCommand( &pThis->PciDev, PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS | PCI_COMMAND_BUSMASTER);
+ PDMPciDevSetStatus( &pThis->PciDev, 0x0210); /* Note! Used to be 0x0200 for ICH7. */
+ PDMPciDevSetRevisionId( &pThis->PciDev, 0x02);
+ PDMPciDevSetClassSub( &pThis->PciDev, 0x01); /* PCI-to-ISA bridge */
+ PDMPciDevSetClassBase( &pThis->PciDev, 0x06); /* bridge */
+ PDMPciDevSetHeaderType( &pThis->PciDev, 0x80); /* Normal, multifunction device (so that other devices can be its functions) */
+ if (pThis->uIchVersion == 7)
+ {
+ PDMPciDevSetSubSystemVendorId(&pThis->PciDev, 0x8086);
+ PDMPciDevSetSubSystemId( &pThis->PciDev, 0x7270);
+ }
+ else if (pThis->uIchVersion == 9)
+ {
+ PDMPciDevSetSubSystemVendorId(&pThis->PciDev, 0x0000); /** @todo docs stays subsystem IDs are zero, check real HW */
+ PDMPciDevSetSubSystemId( &pThis->PciDev, 0x0000);
+ }
+ PDMPciDevSetInterruptPin( &pThis->PciDev, 0x00); /* The LPC device itself generates no interrupts */
+ PDMPciDevSetDWord( &pThis->PciDev, 0x40, 0x00008001); /* PMBASE: ACPI base address; (PM_PORT_BASE (?) * 2 | PCI_ADDRESS_SPACE_IO) */
+ PDMPciDevSetByte( &pThis->PciDev, 0x44, 0x80); /* ACPI_CNTL: SCI is IRQ9, ACPI enabled */ /** @todo documented as defaulting to 0x00. */
+ PDMPciDevSetDWord( &pThis->PciDev, 0x48, 0x00000001); /* GPIOBASE (note: used to be zero) */
+ PDMPciDevSetByte( &pThis->PciDev, 0x4c, 0x4d); /* GC - GPIO control: ??? */ /** @todo documented as defaulting to 0x00. */
+ if (pThis->uIchVersion == 7)
+ PDMPciDevSetByte(&pThis->PciDev, 0x4e, 0x03); /* ??? */
+ PDMPciDevSetByte( &pThis->PciDev, 0x60, 0x0b); /* PIRQA_ROUT: PCI A -> IRQ 11 (documented default is 0x80) */
+ PDMPciDevSetByte( &pThis->PciDev, 0x61, 0x09); /* PIRQB_ROUT: PCI B -> IRQ 9 (documented default is 0x80) */
+ PDMPciDevSetByte( &pThis->PciDev, 0x62, 0x0b); /* PIRQC_ROUT: PCI C -> IRQ 11 (documented default is 0x80) */
+ PDMPciDevSetByte( &pThis->PciDev, 0x63, 0x09); /* PIRQD_ROUT: PCI D -> IRQ 9 (documented default is 0x80) */
+ PDMPciDevSetByte( &pThis->PciDev, 0x64, 0x10); /* SIRQ_CNTL: Serial IRQ Control 10h R/W, RO */
+ PDMPciDevSetByte( &pThis->PciDev, 0x68, 0x80); /* PIRQE_ROUT */
+ PDMPciDevSetByte( &pThis->PciDev, 0x69, 0x80); /* PIRQF_ROUT */
+ PDMPciDevSetByte( &pThis->PciDev, 0x6a, 0x80); /* PIRQG_ROUT */
+ PDMPciDevSetByte( &pThis->PciDev, 0x6b, 0x80); /* PIRQH_ROUT */
+ PDMPciDevSetWord( &pThis->PciDev, 0x6c, 0x00f8); /* IPC_IBDF: IOxAPIC bus:device:function. (Note! Used to be zero.) */
+ if (pThis->uIchVersion == 7)
+ {
+ /* No idea what this is/was yet: */
+ PDMPciDevSetByte( &pThis->PciDev, 0x70, 0x80);
+ PDMPciDevSetByte( &pThis->PciDev, 0x76, 0x0c);
+ PDMPciDevSetByte( &pThis->PciDev, 0x77, 0x0c);
+ PDMPciDevSetByte( &pThis->PciDev, 0x78, 0x02);
+ PDMPciDevSetByte( &pThis->PciDev, 0x79, 0x00);
+ }
+ PDMPciDevSetWord( &pThis->PciDev, 0x80, 0x0000); /* LPC_I/O_DEC: I/O decode ranges. */
+ PDMPciDevSetWord( &pThis->PciDev, 0x82, 0x0000); /* LPC_EN: LPC I/F enables. */
+ PDMPciDevSetDWord( &pThis->PciDev, 0x84, 0x00000000); /* GEN1_DEC: LPC I/F generic decode range 1. */
+ PDMPciDevSetDWord( &pThis->PciDev, 0x88, 0x00000000); /* GEN2_DEC: LPC I/F generic decode range 2. */
+ PDMPciDevSetDWord( &pThis->PciDev, 0x8c, 0x00000000); /* GEN3_DEC: LPC I/F generic decode range 3. */
+ PDMPciDevSetDWord( &pThis->PciDev, 0x90, 0x00000000); /* GEN4_DEC: LPC I/F generic decode range 4. */
+
+ PDMPciDevSetWord( &pThis->PciDev, 0xa0, 0x0008); /* GEN_PMCON_1: Documented default is 0x0000 */
+ PDMPciDevSetByte( &pThis->PciDev, 0xa2, 0x00); /* GEN_PMON_2: */
+ PDMPciDevSetByte( &pThis->PciDev, 0xa4, 0x00); /* GEN_PMON_3: */
+ PDMPciDevSetByte( &pThis->PciDev, 0xa6, 0x00); /* GEN_PMON_LOCK: Configuration lock. */
+ if (pThis->uIchVersion == 7)
+ PDMPciDevSetByte(&pThis->PciDev, 0xa8, 0x0f); /* Is this part of GEN_PMON_LOCK? */
+ PDMPciDevSetByte( &pThis->PciDev, 0xab, 0x00); /* BM_BREAK_EN */
+ PDMPciDevSetDWord( &pThis->PciDev, 0xac, 0x00000000); /* PMIR: Power */
+ PDMPciDevSetDWord( &pThis->PciDev, 0xb8, 0x00000000); /* GPI_ROUT: GPI Route Control */
+ if (pThis->uIchVersion == 9)
+ {
+ /** @todo the next two values looks bogus. */
+ PDMPciDevSetDWord(&pThis->PciDev, 0xd0, 0x00112233); /* FWH_SEL1: Firmware Hub Select 1 */
+ PDMPciDevSetWord( &pThis->PciDev, 0xd4, 0x4567); /* FWH_SEL2: Firmware Hub Select 2 */
+ PDMPciDevSetWord( &pThis->PciDev, 0xd8, 0xffcf); /* FWH_DEC_EN1: Firmware Hub Decode Enable 1 */
+ PDMPciDevSetByte( &pThis->PciDev, 0xdc, 0x00); /* BIOS_CNTL: BIOS control */
+ PDMPciDevSetWord( &pThis->PciDev, 0xe0, 0x0009); /* FDCAP: Feature Detection Capability ID */
+ PDMPciDevSetByte( &pThis->PciDev, 0xe2, 0x0c); /* FDLEN: Feature Detection Capability Length */
+ PDMPciDevSetByte( &pThis->PciDev, 0xe3, 0x10); /* FDVER: Feature Detection Version */
+ PDMPciDevSetByte( &pThis->PciDev, 0xe4, 0x20); /* FDVCT[0]: 5=SATA RAID 0/1/5/10 capability (1=disabled) */
+ PDMPciDevSetByte( &pThis->PciDev, 0xe5, 0x00); /* FDVCT[1]: */
+ PDMPciDevSetByte( &pThis->PciDev, 0xe6, 0x00); /* FDVCT[2]: */
+ PDMPciDevSetByte( &pThis->PciDev, 0xe7, 0x00); /* FDVCT[3]: */
+ PDMPciDevSetByte( &pThis->PciDev, 0xe8, 0xc0); /* FDVCT[4]: 6-7=Intel active magament technology capability (11=disabled). */
+ PDMPciDevSetByte( &pThis->PciDev, 0xe9, 0x00); /* FDVCT[5]: */
+ PDMPciDevSetByte( &pThis->PciDev, 0xea, 0x00); /* FDVCT[6]: */
+ PDMPciDevSetByte( &pThis->PciDev, 0xeb, 0x00); /* FDVCT[7]: */
+ PDMPciDevSetByte( &pThis->PciDev, 0xec, 0x00); /* FDVCT[8]: */
+ PDMPciDevSetByte( &pThis->PciDev, 0xed, 0x00); /* FDVCT[9]: */
+ PDMPciDevSetByte( &pThis->PciDev, 0xee, 0x00); /* FDVCT[a]: */
+ PDMPciDevSetByte( &pThis->PciDev, 0xef, 0x00); /* FDVCT[b]: */
+ }
+
+ /* RCBA: Root complex base address (documented default is 0x00000000). Bit 0 is enable bit. */
+ Assert(!(pThis->GCPhys32Rcba & 0x3fff)); /* 16KB aligned */
+ PDMPciDevSetDWord(&pThis->PciDev, 0xf0, pThis->GCPhys32Rcba | 1);
+
+ rc = PDMDevHlpPCIRegisterEx(pDevIns, &pThis->PciDev, PDMPCIDEVREG_CFG_PRIMARY, PDMPCIDEVREG_F_NOT_MANDATORY_NO,
+ 31 /*uPciDevNo*/, 0 /*uPciFunNo*/, "lpc");
+ AssertRCReturn(rc, rc);
+ PDMDevHlpPCISetConfigCallbacks(pDevIns, &pThis->PciDev,
+ lpcPciConfigRead, &pThis->pfnPciConfigReadFallback,
+ lpcPciConfigWrite, &pThis->pfnPciConfigWriteFallback);
+
+ /*
+ * Register the MMIO regions.
+ */
+ /** @todo This should actually be done when RCBA is enabled, but was
+ * mentioned above we just want this working. */
+ rc = PDMDevHlpMMIORegister(pDevIns, pThis->GCPhys32Rcba, 0x4000, pThis,
+ IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_PASSTHRU,
+ lpcMmioWrite, lpcMmioRead, "LPC Memory");
+ AssertRCReturn(rc, rc);
+
+
+ /*
+ * Debug info and stats.
+ */
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioReads, STAMTYPE_COUNTER, "/Devices/LPC/MMIOReads", STAMUNIT_OCCURENCES, "MMIO reads");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioWrites, STAMTYPE_COUNTER, "/Devices/LPC/MMIOWrites", STAMUNIT_OCCURENCES, "MMIO writes");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatPciCfgReads, STAMTYPE_COUNTER, "/Devices/LPC/ConfigReads", STAMUNIT_OCCURENCES, "PCI config reads");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatPciCfgWrites, STAMTYPE_COUNTER, "/Devices/LPC/ConfigWrites", STAMUNIT_OCCURENCES, "PCI config writes");
+
+ PDMDevHlpDBGFInfoRegister(pDevIns, "lpc", "Display LPC status. (no arguments)", lpcInfo);
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * The device registration structure.
+ */
+const PDMDEVREG g_DeviceLPC =
+{
+ /* u32Version */
+ PDM_DEVREG_VERSION,
+ /* szName */
+ "lpc",
+ /* szRCMod */
+ "",
+ /* szR0Mod */
+ "",
+ /* pszDescription */
+ "Low Pin Count (LPC) Bus",
+ /* fFlags */
+ PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36,
+ /* fClass */
+ PDM_DEVREG_CLASS_MISC,
+ /* cMaxInstances */
+ 1,
+ /* cbInstance */
+ sizeof(LPCSTATE),
+ /* pfnConstruct */
+ lpcConstruct,
+ /* pfnDestruct */
+ NULL,
+ /* pfnRelocate */
+ NULL,
+ /* pfnMemSetup */
+ NULL,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ NULL,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnAttach */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnQueryInterface. */
+ NULL,
+ /* pfnInitComplete */
+ NULL,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32VersionEnd */
+ PDM_DEVREG_VERSION
+};
+
+#endif /* IN_RING3 */
+#endif /* VBOX_DEVICE_STRUCT_TESTCASE */
+
diff --git a/src/VBox/Devices/PC/DevPIC.cpp b/src/VBox/Devices/PC/DevPIC.cpp
new file mode 100644
index 00000000..9fe3d5c2
--- /dev/null
+++ b/src/VBox/Devices/PC/DevPIC.cpp
@@ -0,0 +1,1095 @@
+/* $Id: DevPIC.cpp $ */
+/** @file
+ * DevPIC - Intel 8259 Programmable Interrupt Controller (PIC) Device.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * -------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * QEMU 8259 interrupt controller emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_PIC
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/log.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+
+#include "VBoxDD.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+/** @def PIC_LOCK
+ * Acquires the PDM lock. This is a NOP if locking is disabled. */
+/** @def PIC_UNLOCK
+ * Releases the PDM lock. This is a NOP if locking is disabled. */
+#define PIC_LOCK(pThis, rc) \
+ do { \
+ int rc2 = (pThis)->CTX_SUFF(pPicHlp)->pfnLock((pThis)->CTX_SUFF(pDevIns), rc); \
+ if (rc2 != VINF_SUCCESS) \
+ return rc2; \
+ } while (0)
+#define PIC_UNLOCK(pThis) \
+ (pThis)->CTX_SUFF(pPicHlp)->pfnUnlock((pThis)->CTX_SUFF(pDevIns))
+
+
+/* debug PIC */
+#define DEBUG_PIC
+
+/*#define DEBUG_IRQ_COUNT*/
+
+/**
+ * The instance data of one (1) PIC.
+ */
+typedef struct PICSTATE
+{
+ uint8_t last_irr; /**< edge detection */
+ uint8_t irr; /**< interrupt request register */
+ uint8_t imr; /**< interrupt mask register */
+ uint8_t isr; /**< interrupt service register */
+ uint8_t priority_add; /**< highest irq priority */
+ uint8_t irq_base;
+ uint8_t read_reg_select;
+ uint8_t poll;
+ uint8_t special_mask;
+ uint8_t init_state;
+ uint8_t auto_eoi;
+ uint8_t rotate_on_auto_eoi;
+ uint8_t special_fully_nested_mode;
+ uint8_t init4; /**< true if 4 byte init */
+ uint8_t elcr; /**< PIIX edge/trigger selection*/
+ uint8_t elcr_mask;
+ /** Pointer to the device instance, R3 Ptr. */
+ PPDMDEVINSR3 pDevInsR3;
+ /** Pointer to the device instance, R0 Ptr. */
+ PPDMDEVINSR0 pDevInsR0;
+ /** Pointer to the device instance, RC Ptr. */
+ PPDMDEVINSRC pDevInsRC;
+ /** The PIC index (0 or 1). */
+ uint8_t idxPic;
+ uint8_t abAlignment0[3]; /**< Alignment padding. */
+ /** The IRQ tags and source IDs for each (tracing purposes). */
+ uint32_t auTags[8];
+} PICSTATE;
+/** Pointer to the state of one PIC. */
+typedef PICSTATE *PPICSTATE;
+
+
+/**
+ * The whole PIC device instance data.
+ */
+typedef struct DEVPIC
+{
+ /** The two interrupt controllers. */
+ PICSTATE aPics[2];
+ /** Pointer to the device instance - R3 Ptr. */
+ PPDMDEVINSR3 pDevInsR3;
+ /** Pointer to the PIC R3 helpers. */
+ PCPDMPICHLPR3 pPicHlpR3;
+ /** Pointer to the device instance - R0 Ptr. */
+ PPDMDEVINSR0 pDevInsR0;
+ /** Pointer to the PIC R0 helpers. */
+ PCPDMPICHLPR0 pPicHlpR0;
+ /** Pointer to the device instance - RC Ptr. */
+ PPDMDEVINSRC pDevInsRC;
+ /** Pointer to the PIC RC helpers. */
+ PCPDMPICHLPRC pPicHlpRC;
+ /** Number of release log entries. Used to prevent flooding. */
+ uint32_t cRelLogEntries;
+ uint32_t u32AlignmentPadding;
+#ifdef VBOX_WITH_STATISTICS
+ STAMCOUNTER StatSetIrqGC;
+ STAMCOUNTER StatSetIrqHC;
+ STAMCOUNTER StatClearedActiveIRQ2;
+ STAMCOUNTER StatClearedActiveMasterIRQ;
+ STAMCOUNTER StatClearedActiveSlaveIRQ;
+#endif
+} DEVPIC;
+/** Pointer to the whole PIC instance data. */
+typedef DEVPIC *PDEVPIC;
+
+
+#ifndef VBOX_DEVICE_STRUCT_TESTCASE
+#ifdef LOG_ENABLED
+DECLINLINE(void) DumpPICState(PPICSTATE pPic, const char *pszFn)
+{
+ PDEVPIC pThis = PDMINS_2_DATA(pPic->CTX_SUFF(pDevIns), PDEVPIC);
+
+ Log2(("%s: pic%d: elcr=%x last_irr=%x irr=%x imr=%x isr=%x irq_base=%x\n",
+ pszFn, (&pThis->aPics[0] == pPic) ? 0 : 1,
+ pPic->elcr, pPic->last_irr, pPic->irr, pPic->imr, pPic->isr, pPic->irq_base));
+}
+#else
+# define DumpPICState(pThis, szFn) do { } while (0)
+#endif
+
+/* set irq level. If an edge is detected, then the IRR is set to 1 */
+DECLINLINE(void) pic_set_irq1(PPICSTATE pPic, int irq, int level, uint32_t uTagSrc)
+{
+ Log(("pic_set_irq1: irq=%d level=%d\n", irq, level));
+ int mask = 1 << irq;
+ if (pPic->elcr & mask)
+ {
+ /* level triggered */
+ if (level)
+ {
+ Log2(("pic_set_irq1(ls) irr=%d irrnew=%d\n", pPic->irr, pPic->irr | mask));
+ pPic->irr |= mask;
+ pPic->last_irr |= mask;
+ }
+ else
+ {
+ Log2(("pic_set_irq1(lc) irr=%d irrnew=%d\n", pPic->irr, pPic->irr & ~mask));
+ pPic->irr &= ~mask;
+ pPic->last_irr &= ~mask;
+ }
+ }
+ else
+ {
+ /* edge triggered */
+ if (level)
+ {
+ if ((pPic->last_irr & mask) == 0)
+ {
+ Log2(("pic_set_irq1 irr=%x last_irr=%x\n", pPic->irr | mask, pPic->last_irr));
+ pPic->irr |= mask;
+ }
+ pPic->last_irr |= mask;
+ }
+ else
+ {
+ pPic->irr &= ~mask;
+ pPic->last_irr &= ~mask;
+ }
+ }
+
+ /* Save the tag. */
+ if (level)
+ {
+ if (!pPic->auTags[irq])
+ pPic->auTags[irq] = uTagSrc;
+ else
+ pPic->auTags[irq] |= RT_BIT_32(31);
+ }
+
+ DumpPICState(pPic, "pic_set_irq1");
+}
+
+/* return the highest priority found in mask (highest = smallest
+ number). Return 8 if no irq */
+DECLINLINE(int) get_priority(PPICSTATE pPic, int mask)
+{
+ int priority;
+ if (mask == 0)
+ return 8;
+ priority = 0;
+ while ((mask & (1 << ((priority + pPic->priority_add) & 7))) == 0)
+ priority++;
+ return priority;
+}
+
+/* return the pic wanted interrupt. return -1 if none */
+static int pic_get_irq(PPICSTATE pPic)
+{
+ int mask, cur_priority, priority;
+ Log(("pic_get_irq%d: mask=%x\n", pPic->idxPic, pPic->irr & ~pPic->imr));
+ DumpPICState(pPic, "pic_get_irq");
+
+ mask = pPic->irr & ~pPic->imr;
+ priority = get_priority(pPic, mask);
+ Log(("pic_get_irq: priority=%x\n", priority));
+ if (priority == 8)
+ return -1;
+ /* compute current priority. If special fully nested mode on the
+ master, the IRQ coming from the slave is not taken into account
+ for the priority computation. */
+ mask = pPic->isr;
+ if (pPic->special_mask)
+ mask &= ~pPic->imr;
+ if (pPic->special_fully_nested_mode && pPic->idxPic == 0)
+ mask &= ~(1 << 2);
+ cur_priority = get_priority(pPic, mask);
+ Log(("pic_get_irq%d: cur_priority=%x pending=%d\n", pPic->idxPic,
+ cur_priority, (priority == 8) ? -1 : (priority + pPic->priority_add) & 7));
+ if (priority < cur_priority)
+ {
+ /* higher priority found: an irq should be generated */
+ return (priority + pPic->priority_add) & 7;
+ }
+ return -1;
+}
+
+/* raise irq to CPU if necessary. must be called every time the active
+ irq may change */
+static int pic_update_irq(PDEVPIC pThis)
+{
+ int irq2, irq;
+
+ /* first look at slave pic */
+ irq2 = pic_get_irq(&pThis->aPics[1]);
+ Log(("pic_update_irq irq2=%d\n", irq2));
+ if (irq2 >= 0)
+ {
+ /* if irq request by slave pic, signal master PIC */
+ pic_set_irq1(&pThis->aPics[0], 2, 1, pThis->aPics[1].auTags[irq2]);
+ }
+ else
+ {
+ /* If not, clear the IR on the master PIC. */
+ pic_set_irq1(&pThis->aPics[0], 2, 0, 0 /*uTagSrc*/);
+ }
+ /* look at requested irq */
+ irq = pic_get_irq(&pThis->aPics[0]);
+ if (irq >= 0)
+ {
+ /* If irq 2 is pending on the master pic, then there must be one pending on the slave pic too! Otherwise we'll get
+ * spurious slave interrupts in picGetInterrupt.
+ */
+ if (irq != 2 || irq2 != -1)
+ {
+#if defined(DEBUG_PIC)
+ for (int i = 0; i < 2; i++)
+ Log(("pic%d: imr=%x irr=%x padd=%d\n", i, pThis->aPics[i].imr, pThis->aPics[i].irr, pThis->aPics[i].priority_add));
+ Log(("pic: cpu_interrupt\n"));
+#endif
+ pThis->CTX_SUFF(pPicHlp)->pfnSetInterruptFF(pThis->CTX_SUFF(pDevIns));
+ }
+ else
+ {
+ STAM_COUNTER_INC(&pThis->StatClearedActiveIRQ2);
+ Log(("pic_update_irq: irq 2 is active, but no interrupt is pending on the slave pic!!\n"));
+ /* Clear it here, so lower priority interrupts can still be dispatched. */
+
+ /* if this was the only pending irq, then we must clear the interrupt ff flag */
+ pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns));
+
+ /** @todo Is this correct? */
+ pThis->aPics[0].irr &= ~(1 << 2);
+
+ /* Call ourselves again just in case other interrupts are pending */
+ return pic_update_irq(pThis);
+ }
+ }
+ else
+ {
+ Log(("pic_update_irq: no interrupt is pending!!\n"));
+
+ /* we must clear the interrupt ff flag */
+ pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns));
+ }
+ return VINF_SUCCESS;
+}
+
+/**
+ * Set the an IRQ.
+ *
+ * @param pDevIns Device instance of the PICs.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level.
+ * @param uTagSrc The IRQ tag and source ID (for tracing).
+ */
+PDMBOTHCBDECL(void) picSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
+{
+ PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
+ Assert(pThis->CTX_SUFF(pDevIns) == pDevIns);
+ Assert(pThis->aPics[0].CTX_SUFF(pDevIns) == pDevIns);
+ Assert(pThis->aPics[1].CTX_SUFF(pDevIns) == pDevIns);
+ AssertMsg(iIrq < 16, ("iIrq=%d\n", iIrq));
+
+ Log(("picSetIrq %d %d\n", iIrq, iLevel));
+ DumpPICState(&pThis->aPics[0], "picSetIrq");
+ DumpPICState(&pThis->aPics[1], "picSetIrq");
+ STAM_COUNTER_INC(&pThis->CTXSUFF(StatSetIrq));
+ if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP)
+ {
+ /* A flip-flop lowers the IRQ line and immediately raises it, so
+ * that a rising edge is guaranteed to occur. Note that the IRQ
+ * line must be held high for a while to avoid spurious interrupts.
+ */
+ pic_set_irq1(&pThis->aPics[iIrq >> 3], iIrq & 7, 0, uTagSrc);
+ pic_update_irq(pThis);
+ }
+ pic_set_irq1(&pThis->aPics[iIrq >> 3], iIrq & 7, iLevel & PDM_IRQ_LEVEL_HIGH, uTagSrc);
+ pic_update_irq(pThis);
+}
+
+
+/* acknowledge interrupt 'irq' */
+DECLINLINE(void) pic_intack(PPICSTATE pPic, int irq)
+{
+ if (pPic->auto_eoi)
+ {
+ if (pPic->rotate_on_auto_eoi)
+ pPic->priority_add = (irq + 1) & 7;
+ }
+ else
+ pPic->isr |= (1 << irq);
+
+ /* We don't clear a level sensitive interrupt here */
+ if (!(pPic->elcr & (1 << irq)))
+ {
+ Log2(("pic_intack: irr=%x irrnew=%x\n", pPic->irr, pPic->irr & ~(1 << irq)));
+ pPic->irr &= ~(1 << irq);
+ }
+}
+
+
+/**
+ * Get a pending interrupt.
+ *
+ * @returns Pending interrupt number.
+ * @param pDevIns Device instance of the PICs.
+ * @param puTagSrc Where to return the IRQ tag and source ID.
+ */
+PDMBOTHCBDECL(int) picGetInterrupt(PPDMDEVINS pDevIns, uint32_t *puTagSrc)
+{
+ PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
+ int irq;
+ int irq2;
+ int intno;
+
+ /* read the irq from the PIC */
+ DumpPICState(&pThis->aPics[0], "picGetInterrupt");
+ DumpPICState(&pThis->aPics[1], "picGetInterrupt");
+
+ irq = pic_get_irq(&pThis->aPics[0]);
+ if (irq >= 0)
+ {
+ pic_intack(&pThis->aPics[0], irq);
+ if (irq == 2)
+ {
+ irq2 = pic_get_irq(&pThis->aPics[1]);
+ if (irq2 >= 0)
+ pic_intack(&pThis->aPics[1], irq2);
+ else
+ {
+ /* Interrupt went away or is now masked. */
+ Log(("picGetInterrupt: spurious IRQ on slave controller, converted to IRQ15\n"));
+ irq2 = 7;
+ }
+ intno = pThis->aPics[1].irq_base + irq2;
+ *puTagSrc = pThis->aPics[0].auTags[irq2];
+ pThis->aPics[0].auTags[irq2] = 0;
+ Log2(("picGetInterrupt1: %x base=%x irq=%x uTagSrc=%#x\n", intno, pThis->aPics[1].irq_base, irq2, *puTagSrc));
+ irq = irq2 + 8;
+ }
+ else
+ {
+ intno = pThis->aPics[0].irq_base + irq;
+ *puTagSrc = pThis->aPics[0].auTags[irq];
+ pThis->aPics[0].auTags[irq] = 0;
+ Log2(("picGetInterrupt0: %x base=%x irq=%x uTagSrc=%#x\n", intno, pThis->aPics[0].irq_base, irq, *puTagSrc));
+ }
+ }
+ else
+ {
+ /* Interrupt went away or is now masked. */
+ Log(("picGetInterrupt: spurious IRQ on master controller, converted to IRQ7\n"));
+ irq = 7;
+ intno = pThis->aPics[0].irq_base + irq;
+ *puTagSrc = 0;
+ }
+ pic_update_irq(pThis);
+
+ Log(("picGetInterrupt: 0x%02x pending 0:%d 1:%d\n", intno, pic_get_irq(&pThis->aPics[0]), pic_get_irq(&pThis->aPics[1])));
+
+ return intno;
+}
+
+static void pic_reset(PPICSTATE pPic)
+{
+ PPDMDEVINSR3 pDevInsR3 = pPic->pDevInsR3;
+ PPDMDEVINSR0 pDevInsR0 = pPic->pDevInsR0;
+ PPDMDEVINSRC pDevInsRC = pPic->pDevInsRC;
+ int elcr_mask = pPic->elcr_mask;
+ int elcr = pPic->elcr;
+
+ memset(pPic, 0, sizeof(*pPic));
+
+ pPic->elcr = elcr;
+ pPic->elcr_mask = elcr_mask;
+ pPic->pDevInsRC = pDevInsRC;
+ pPic->pDevInsR0 = pDevInsR0;
+ pPic->pDevInsR3 = pDevInsR3;
+}
+
+
+static int pic_ioport_write(PDEVPIC pThis, PPICSTATE pPic, uint32_t addr, uint32_t val)
+{
+ int rc = VINF_SUCCESS;
+ int irq;
+
+ Log(("pic_write: addr=0x%02x val=0x%02x\n", addr, val));
+ addr &= 1;
+ if (addr == 0)
+ {
+ if (val & 0x10)
+ {
+ /* init */
+ pic_reset(pPic);
+ /* deassert a pending interrupt */
+ pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns));
+
+ pPic->init_state = 1;
+ pPic->init4 = val & 1;
+ if (val & 0x02)
+ AssertReleaseMsgFailed(("single mode not supported"));
+ if (val & 0x08)
+ if (pThis->cRelLogEntries++ < 64)
+ LogRel(("pic_write: Level sensitive IRQ setting ignored.\n"));
+ }
+ else if (val & 0x08)
+ {
+ if (val & 0x04)
+ pPic->poll = 1;
+ if (val & 0x02)
+ pPic->read_reg_select = val & 1;
+ if (val & 0x40)
+ pPic->special_mask = (val >> 5) & 1;
+ }
+ else
+ {
+ int cmd = val >> 5;
+ switch (cmd)
+ {
+ case 0:
+ case 4:
+ pPic->rotate_on_auto_eoi = cmd >> 2;
+ break;
+ case 1: /* end of interrupt */
+ case 5:
+ {
+ int priority = get_priority(pPic, pPic->isr);
+ if (priority != 8) {
+ irq = (priority + pPic->priority_add) & 7;
+ Log(("pic_write: EOI prio=%d irq=%d\n", priority, irq));
+ pPic->isr &= ~(1 << irq);
+ if (cmd == 5)
+ pPic->priority_add = (irq + 1) & 7;
+ rc = pic_update_irq(pThis);
+ Assert(rc == VINF_SUCCESS);
+ DumpPICState(pPic, "eoi");
+ }
+ break;
+ }
+ case 3:
+ {
+ irq = val & 7;
+ Log(("pic_write: EOI2 for irq %d\n", irq));
+ pPic->isr &= ~(1 << irq);
+ rc = pic_update_irq(pThis);
+ Assert(rc == VINF_SUCCESS);
+ DumpPICState(pPic, "eoi2");
+ break;
+ }
+ case 6:
+ {
+ pPic->priority_add = (val + 1) & 7;
+ Log(("pic_write: lowest priority %d (highest %d)\n", val & 7, pPic->priority_add));
+ rc = pic_update_irq(pThis);
+ Assert(rc == VINF_SUCCESS);
+ break;
+ }
+ case 7:
+ {
+ irq = val & 7;
+ Log(("pic_write: EOI3 for irq %d\n", irq));
+ pPic->isr &= ~(1 << irq);
+ pPic->priority_add = (irq + 1) & 7;
+ rc = pic_update_irq(pThis);
+ Assert(rc == VINF_SUCCESS);
+ DumpPICState(pPic, "eoi3");
+ break;
+ }
+ default:
+ /* no operation */
+ break;
+ }
+ }
+ }
+ else
+ {
+ switch (pPic->init_state)
+ {
+ case 0:
+ /* normal mode */
+ pPic->imr = val;
+ rc = pic_update_irq(pThis);
+ Assert(rc == VINF_SUCCESS);
+ break;
+ case 1:
+ pPic->irq_base = val & 0xf8;
+ pPic->init_state = 2;
+ Log(("pic_write: set irq base to %x\n", pPic->irq_base));
+ break;
+ case 2:
+ if (pPic->init4)
+ pPic->init_state = 3;
+ else
+ pPic->init_state = 0;
+ break;
+ case 3:
+ pPic->special_fully_nested_mode = (val >> 4) & 1;
+ pPic->auto_eoi = (val >> 1) & 1;
+ pPic->init_state = 0;
+ Log(("pic_write: special_fully_nested_mode=%d auto_eoi=%d\n", pPic->special_fully_nested_mode, pPic->auto_eoi));
+ break;
+ }
+ }
+ return rc;
+}
+
+
+static uint32_t pic_poll_read(PPICSTATE pPic, uint32_t addr1)
+{
+ PDEVPIC pThis = RT_FROM_MEMBER_DYN(pPic, DEVPIC, aPics[pPic->idxPic]);
+
+ int ret = pic_get_irq(pPic);
+ if (ret >= 0)
+ {
+ if (addr1 >> 7)
+ {
+ Log2(("pic_poll_read: clear slave irq (isr)\n"));
+ pThis->aPics[0].isr &= ~(1 << 2);
+ pThis->aPics[0].irr &= ~(1 << 2);
+ }
+ Log2(("pic_poll_read: clear irq %d (isr)\n", ret));
+ pPic->irr &= ~(1 << ret);
+ pPic->isr &= ~(1 << ret);
+ if (addr1 >> 7 || ret != 2)
+ pic_update_irq(pThis);
+ }
+ else
+ {
+ ret = 0;
+ pic_update_irq(pThis);
+ }
+
+ return ret;
+}
+
+
+static uint32_t pic_ioport_read(PPICSTATE pPic, uint32_t addr1, int *pRC)
+{
+ unsigned int addr;
+ int ret;
+
+ *pRC = VINF_SUCCESS;
+
+ addr = addr1;
+ addr &= 1;
+ if (pPic->poll)
+ {
+ ret = pic_poll_read(pPic, addr1);
+ pPic->poll = 0;
+ }
+ else
+ {
+ if (addr == 0)
+ {
+ if (pPic->read_reg_select)
+ ret = pPic->isr;
+ else
+ ret = pPic->irr;
+ }
+ else
+ ret = pPic->imr;
+ }
+ Log(("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret));
+ return ret;
+}
+
+
+
+/* -=-=-=-=-=- I/O ports -=-=-=-=-=- */
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN}
+ */
+PDMBOTHCBDECL(int) picIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb)
+{
+ PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
+ uint32_t iPic = (uint32_t)(uintptr_t)pvUser;
+
+ Assert(iPic == 0 || iPic == 1);
+ if (cb == 1)
+ {
+ int rc;
+ PIC_LOCK(pThis, VINF_IOM_R3_IOPORT_READ);
+ *pu32 = pic_ioport_read(&pThis->aPics[iPic], uPort, &rc);
+ PIC_UNLOCK(pThis);
+ return rc;
+ }
+ return VERR_IOM_IOPORT_UNUSED;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT}
+ */
+PDMBOTHCBDECL(int) picIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb)
+{
+ PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
+ uint32_t iPic = (uint32_t)(uintptr_t)pvUser;
+
+ Assert(iPic == 0 || iPic == 1);
+
+ if (cb == 1)
+ {
+ int rc;
+ PIC_LOCK(pThis, VINF_IOM_R3_IOPORT_WRITE);
+ rc = pic_ioport_write(pThis, &pThis->aPics[iPic], uPort, u32);
+ PIC_UNLOCK(pThis);
+ return rc;
+ }
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, ELCR}
+ */
+PDMBOTHCBDECL(int) picIOPortElcrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ if (cb == 1)
+ {
+ PPICSTATE pPic = (PPICSTATE)pvUser;
+ PIC_LOCK(PDMINS_2_DATA(pDevIns, PDEVPIC), VINF_IOM_R3_IOPORT_READ);
+ *pu32 = pPic->elcr;
+ PIC_UNLOCK(PDMINS_2_DATA(pDevIns, PDEVPIC));
+ return VINF_SUCCESS;
+ }
+ NOREF(Port);
+ return VERR_IOM_IOPORT_UNUSED;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, ELCR}
+ */
+PDMBOTHCBDECL(int) picIOPortElcrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ if (cb == 1)
+ {
+ PPICSTATE pPic = (PPICSTATE)pvUser;
+ PIC_LOCK(PDMINS_2_DATA(pDevIns, PDEVPIC), VINF_IOM_R3_IOPORT_WRITE);
+ pPic->elcr = u32 & pPic->elcr_mask;
+ PIC_UNLOCK(PDMINS_2_DATA(pDevIns, PDEVPIC));
+ }
+ NOREF(Port);
+ return VINF_SUCCESS;
+}
+
+
+#ifdef IN_RING3
+
+/**
+ * @callback_method_impl{FNDBGFHANDLERDEV}
+ */
+static DECLCALLBACK(void) picInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+ PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
+ NOREF(pszArgs);
+
+ /*
+ * Show info.
+ */
+ for (int i = 0; i < 2; i++)
+ {
+ PPICSTATE pPic = &pThis->aPics[i];
+
+ pHlp->pfnPrintf(pHlp, "PIC%d:\n", i);
+ pHlp->pfnPrintf(pHlp, " IMR :%02x ISR :%02x IRR :%02x LIRR:%02x\n",
+ pPic->imr, pPic->isr, pPic->irr, pPic->last_irr);
+ pHlp->pfnPrintf(pHlp, " Base:%02x PriAdd:%02x RegSel:%02x\n",
+ pPic->irq_base, pPic->priority_add, pPic->read_reg_select);
+ pHlp->pfnPrintf(pHlp, " Poll:%02x SpMask:%02x IState:%02x\n",
+ pPic->poll, pPic->special_mask, pPic->init_state);
+ pHlp->pfnPrintf(pHlp, " AEOI:%02x Rotate:%02x FNest :%02x Ini4:%02x\n",
+ pPic->auto_eoi, pPic->rotate_on_auto_eoi,
+ pPic->special_fully_nested_mode, pPic->init4);
+ pHlp->pfnPrintf(pHlp, " ELCR:%02x ELMask:%02x\n", pPic->elcr, pPic->elcr_mask);
+ }
+}
+
+
+/* -=-=-=-=-=- Saved State -=-=-=-=-=- */
+
+/**
+ * @callback_method_impl{FNSSMDEVSAVEEXEC}
+ */
+static DECLCALLBACK(int) picSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+ PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->aPics); i++)
+ {
+ SSMR3PutU8(pSSM, pThis->aPics[i].last_irr);
+ SSMR3PutU8(pSSM, pThis->aPics[i].irr);
+ SSMR3PutU8(pSSM, pThis->aPics[i].imr);
+ SSMR3PutU8(pSSM, pThis->aPics[i].isr);
+ SSMR3PutU8(pSSM, pThis->aPics[i].priority_add);
+ SSMR3PutU8(pSSM, pThis->aPics[i].irq_base);
+ SSMR3PutU8(pSSM, pThis->aPics[i].read_reg_select);
+ SSMR3PutU8(pSSM, pThis->aPics[i].poll);
+ SSMR3PutU8(pSSM, pThis->aPics[i].special_mask);
+ SSMR3PutU8(pSSM, pThis->aPics[i].init_state);
+ SSMR3PutU8(pSSM, pThis->aPics[i].auto_eoi);
+ SSMR3PutU8(pSSM, pThis->aPics[i].rotate_on_auto_eoi);
+ SSMR3PutU8(pSSM, pThis->aPics[i].special_fully_nested_mode);
+ SSMR3PutU8(pSSM, pThis->aPics[i].init4);
+ SSMR3PutU8(pSSM, pThis->aPics[i].elcr);
+ }
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNSSMDEVLOADEXEC}
+ */
+static DECLCALLBACK(int) picLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+{
+ PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
+
+ if (uVersion != 1)
+ return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
+ Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
+
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->aPics); i++)
+ {
+ SSMR3GetU8(pSSM, &pThis->aPics[i].last_irr);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].irr);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].imr);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].isr);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].priority_add);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].irq_base);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].read_reg_select);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].poll);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].special_mask);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].init_state);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].auto_eoi);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].rotate_on_auto_eoi);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].special_fully_nested_mode);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].init4);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].elcr);
+ }
+ return VINF_SUCCESS;
+}
+
+
+/* -=-=-=-=-=- PDMDEVREG -=-=-=-=-=- */
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnReset}
+ */
+static DECLCALLBACK(void) picReset(PPDMDEVINS pDevIns)
+{
+ PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
+ unsigned i;
+ LogFlow(("picReset:\n"));
+ pThis->pPicHlpR3->pfnLock(pDevIns, VERR_INTERNAL_ERROR);
+
+ for (i = 0; i < RT_ELEMENTS(pThis->aPics); i++)
+ pic_reset(&pThis->aPics[i]);
+
+ PIC_UNLOCK(pThis);
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnRelocate}
+ */
+static DECLCALLBACK(void) picRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
+{
+ RT_NOREF1(offDelta);
+ PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
+ unsigned i;
+
+ pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+ pThis->pPicHlpRC = pThis->pPicHlpR3->pfnGetRCHelpers(pDevIns);
+ for (i = 0; i < RT_ELEMENTS(pThis->aPics); i++)
+ pThis->aPics[i].pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnConstruct}
+ */
+static DECLCALLBACK(int) picConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
+{
+ PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+ RT_NOREF1(iInstance);
+ PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
+ int rc;
+ bool fGCEnabled;
+ bool fR0Enabled;
+ Assert(iInstance == 0);
+
+ /*
+ * Validate and read configuration.
+ */
+ if (!CFGMR3AreValuesValid(pCfg, "GCEnabled\0" "R0Enabled\0"))
+ return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
+
+ rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: failed to read GCEnabled as boolean"));
+
+ rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: failed to read R0Enabled as boolean"));
+
+ Log(("DevPIC: fGCEnabled=%RTbool fR0Enabled=%RTbool\n", fGCEnabled, fR0Enabled));
+
+ /*
+ * Init the data.
+ */
+ Assert(RT_ELEMENTS(pThis->aPics) == 2);
+ pThis->pDevInsR3 = pDevIns;
+ pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
+ pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+ pThis->aPics[0].elcr_mask = 0xf8;
+ pThis->aPics[1].elcr_mask = 0xde;
+ pThis->aPics[0].pDevInsR3 = pDevIns;
+ pThis->aPics[1].pDevInsR3 = pDevIns;
+ pThis->aPics[0].pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
+ pThis->aPics[1].pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
+ pThis->aPics[0].pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+ pThis->aPics[1].pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+ pThis->aPics[0].idxPic = 0;
+ pThis->aPics[1].idxPic = 1;
+ pThis->cRelLogEntries = 0;
+
+ /*
+ * Register us as the PIC with PDM.
+ */
+ PDMPICREG PicReg;
+ PicReg.u32Version = PDM_PICREG_VERSION;
+ PicReg.pfnSetIrqR3 = picSetIrq;
+ PicReg.pfnGetInterruptR3 = picGetInterrupt;
+
+ if (fGCEnabled)
+ {
+ PicReg.pszSetIrqRC = "picSetIrq";
+ PicReg.pszGetInterruptRC = "picGetInterrupt";
+ }
+ else
+ {
+ PicReg.pszSetIrqRC = NULL;
+ PicReg.pszGetInterruptRC = NULL;
+ }
+
+ if (fR0Enabled)
+ {
+ PicReg.pszSetIrqR0 = "picSetIrq";
+ PicReg.pszGetInterruptR0 = "picGetInterrupt";
+ }
+ else
+ {
+ PicReg.pszSetIrqR0 = NULL;
+ PicReg.pszGetInterruptR0 = NULL;
+ }
+
+ rc = PDMDevHlpPICRegister(pDevIns, &PicReg, &pThis->pPicHlpR3);
+ AssertLogRelMsgRCReturn(rc, ("PICRegister -> %Rrc\n", rc), rc);
+ if (fGCEnabled)
+ pThis->pPicHlpRC = pThis->pPicHlpR3->pfnGetRCHelpers(pDevIns);
+ if (fR0Enabled)
+ pThis->pPicHlpR0 = pThis->pPicHlpR3->pfnGetR0Helpers(pDevIns);
+
+ /*
+ * Since the PIC helper interface provides access to the PDM lock,
+ * we need no device level critical section.
+ */
+ rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
+ AssertRCReturn(rc, rc);
+
+ /*
+ * Register I/O ports and save state.
+ */
+ rc = PDMDevHlpIOPortRegister(pDevIns, 0x20, 2, (void *)0, picIOPortWrite, picIOPortRead, NULL, NULL, "i8259 PIC #0");
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = PDMDevHlpIOPortRegister(pDevIns, 0xa0, 2, (void *)1, picIOPortWrite, picIOPortRead, NULL, NULL, "i8259 PIC #1");
+ if (RT_FAILURE(rc))
+ return rc;
+ if (fGCEnabled)
+ {
+ rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x20, 2, 0, "picIOPortWrite", "picIOPortRead", NULL, NULL, "i8259 PIC #0");
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0xa0, 2, 1, "picIOPortWrite", "picIOPortRead", NULL, NULL, "i8259 PIC #1");
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+ if (fR0Enabled)
+ {
+ rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x20, 2, 0, "picIOPortWrite", "picIOPortRead", NULL, NULL, "i8259 PIC #0");
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0xa0, 2, 1, "picIOPortWrite", "picIOPortRead", NULL, NULL, "i8259 PIC #1");
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+
+ rc = PDMDevHlpIOPortRegister(pDevIns, 0x4d0, 1, &pThis->aPics[0],
+ picIOPortElcrWrite, picIOPortElcrRead, NULL, NULL, "i8259 PIC #0 - elcr");
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = PDMDevHlpIOPortRegister(pDevIns, 0x4d1, 1, &pThis->aPics[1],
+ picIOPortElcrWrite, picIOPortElcrRead, NULL, NULL, "i8259 PIC #1 - elcr");
+ if (RT_FAILURE(rc))
+ return rc;
+ if (fGCEnabled)
+ {
+ RTRCPTR pDataRC = PDMINS_2_DATA_RCPTR(pDevIns);
+ rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x4d0, 1, pDataRC + RT_OFFSETOF(DEVPIC, aPics[0]),
+ "picIOPortElcrWrite", "picIOPortElcrRead", NULL, NULL, "i8259 PIC #0 - elcr");
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x4d1, 1, pDataRC + RT_OFFSETOF(DEVPIC, aPics[1]),
+ "picIOPortElcrWrite", "picIOPortElcrRead", NULL, NULL, "i8259 PIC #1 - elcr");
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+ if (fR0Enabled)
+ {
+ RTR0PTR pDataR0 = PDMINS_2_DATA_R0PTR(pDevIns);
+ rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x4d0, 1, pDataR0 + RT_OFFSETOF(DEVPIC, aPics[0]),
+ "picIOPortElcrWrite", "picIOPortElcrRead", NULL, NULL, "i8259 PIC #0 - elcr");
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x4d1, 1, pDataR0 + RT_OFFSETOF(DEVPIC, aPics[1]),
+ "picIOPortElcrWrite", "picIOPortElcrRead", NULL, NULL, "i8259 PIC #1 - elcr");
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+
+ rc = PDMDevHlpSSMRegister(pDevIns, 1 /* uVersion */, sizeof(*pThis), picSaveExec, picLoadExec);
+ if (RT_FAILURE(rc))
+ return rc;
+
+
+ /*
+ * Register the info item.
+ */
+ PDMDevHlpDBGFInfoRegister(pDevIns, "pic", "PIC info.", picInfo);
+
+ /*
+ * Initialize the device state.
+ */
+ picReset(pDevIns);
+
+#ifdef VBOX_WITH_STATISTICS
+ /*
+ * Statistics.
+ */
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetIrqGC, STAMTYPE_COUNTER, "/Devices/PIC/SetIrqGC", STAMUNIT_OCCURENCES, "Number of PIC SetIrq calls in GC.");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetIrqHC, STAMTYPE_COUNTER, "/Devices/PIC/SetIrqHC", STAMUNIT_OCCURENCES, "Number of PIC SetIrq calls in HC.");
+
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatClearedActiveIRQ2, STAMTYPE_COUNTER, "/Devices/PIC/Masked/ActiveIRQ2", STAMUNIT_OCCURENCES, "Number of cleared irq 2.");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatClearedActiveMasterIRQ, STAMTYPE_COUNTER, "/Devices/PIC/Masked/ActiveMaster", STAMUNIT_OCCURENCES, "Number of cleared master irqs.");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatClearedActiveSlaveIRQ, STAMTYPE_COUNTER, "/Devices/PIC/Masked/ActiveSlave", STAMUNIT_OCCURENCES, "Number of cleared slave irqs.");
+#endif
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * The device registration structure.
+ */
+const PDMDEVREG g_DeviceI8259 =
+{
+ /* u32Version */
+ PDM_DEVREG_VERSION,
+ /* szName */
+ "i8259",
+ /* szRCMod */
+ "VBoxDDRC.rc",
+ /* szR0Mod */
+ "VBoxDDR0.r0",
+ /* pszDescription */
+ "Intel 8259 Programmable Interrupt Controller (PIC) Device.",
+ /* fFlags */
+ PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36 | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
+ /* fClass */
+ PDM_DEVREG_CLASS_PIC,
+ /* cMaxInstances */
+ 1,
+ /* cbInstance */
+ sizeof(DEVPIC),
+ /* pfnConstruct */
+ picConstruct,
+ /* pfnDestruct */
+ NULL,
+ /* pfnRelocate */
+ picRelocate,
+ /* pfnMemSetup */
+ NULL,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ picReset,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnAttach */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnQueryInterface. */
+ NULL,
+ /* pfnInitComplete */
+ NULL,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32VersionEnd */
+ PDM_DEVREG_VERSION
+};
+
+#endif /* IN_RING3 */
+#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
+
diff --git a/src/VBox/Devices/PC/DevPcArch.cpp b/src/VBox/Devices/PC/DevPcArch.cpp
new file mode 100644
index 00000000..ec88d2c3
--- /dev/null
+++ b/src/VBox/Devices/PC/DevPcArch.cpp
@@ -0,0 +1,339 @@
+/* $Id: DevPcArch.cpp $ */
+/** @file
+ * DevPcArch - PC Architecture Device.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_PC_ARCH
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/vmm/mm.h>
+#include <VBox/vmm/pgm.h>
+#include <VBox/log.h>
+#include <VBox/err.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+
+#include "VBoxDD.h"
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+
+/**
+ * PC Bios instance data structure.
+ */
+typedef struct DEVPCARCH
+{
+ /** Pointer back to the device instance. */
+ PPDMDEVINS pDevIns;
+} DEVPCARCH, *PDEVPCARCH;
+
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, Math coprocessor.}
+ */
+static DECLCALLBACK(int) pcarchIOPortFPURead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ int rc;
+ NOREF(pvUser); NOREF(pDevIns); NOREF(pu32);
+ rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Port=%#x cb=%d\n", Port, cb);
+ if (rc == VINF_SUCCESS)
+ rc = VERR_IOM_IOPORT_UNUSED;
+ return rc;
+}
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, Math coprocessor.}
+ * @todo Add IGNNE support.
+ */
+static DECLCALLBACK(int) pcarchIOPortFPUWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ int rc = VINF_SUCCESS;
+ NOREF(pvUser);
+ if (cb == 1)
+ {
+ switch (Port)
+ {
+ /*
+ * Clear busy latch.
+ */
+ case 0xf0:
+ Log2(("PCARCH: FPU Clear busy latch u32=%#x\n", u32));
+/* This is triggered when booting Knoppix (3.7) */
+#if 0
+ if (!u32)
+ rc = PDMDeviceDBGFStop(pDevIns, RT_SRC_POS, "Port=%#x cb=%d u32=%#x\n", Port, cb, u32);
+#endif
+ /* pDevIns->pHlp->pfnPICSetIrq(pDevIns, 13, 0); */
+ break;
+
+ /* Reset. */
+ case 0xf1:
+ Log2(("PCARCH: FPU Reset cb=%d u32=%#x\n", cb, u32));
+ /** @todo figure out what the difference between FPU ports 0xf0 and 0xf1 are... */
+ /* pDevIns->pHlp->pfnPICSetIrq(pDevIns, 13, 0); */
+ break;
+
+ /* opcode transfers */
+ case 0xf8:
+ case 0xfa:
+ case 0xfc:
+ default:
+ rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Port=%#x cb=%d u32=%#x\n", Port, cb, u32);
+ break;
+ }
+ /* this works better, but probably not entirely correct. */
+ PDMDevHlpISASetIrq(pDevIns, 13, 0);
+ }
+ else
+ rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Port=%#x cb=%d u32=%#x\n", Port, cb, u32);
+ return rc;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, PS/2 system control port A.}
+ *
+ * @todo Check if the A20 enable/disable method implemented here in any way
+ * should cooperate with the one implemented in the PS/2 keyboard device.
+ * This probably belongs together in the PS/2 keyboard device (since that
+ * is where the "port B" mentioned by Ralph Brown is implemented).
+ *
+ * @remark Ralph Brown and friends have this to say about this port:
+ *
+ * @verbatim
+0092 RW PS/2 system control port A (port B is at PORT 0061h) (see #P0415)
+
+Bitfields for PS/2 system control port A:
+Bit(s) Description (Table P0415)
+ 7-6 any bit set to 1 turns activity light on
+ 5 unused
+ 4 watchdog timout occurred
+ 3 =0 RTC/CMOS security lock (on password area) unlocked
+ =1 CMOS locked (done by POST)
+ 2 unused
+ 1 A20 is active
+ 0 =0 system reset or write
+ =1 pulse alternate reset pin (high-speed alternate CPU reset)
+Notes: once set, bit 3 may only be cleared by a power-on reset
+ on at least the C&T 82C235, bit 0 remains set through a CPU reset to
+ allow the BIOS to determine the reset method
+ on the PS/2 30-286 & "Tortuga" the INT 15h/87h memory copy does
+ not use this port for A20 control, but instead uses the keyboard
+ controller (8042). Reportedly this may cause the system to crash
+ when access to the 8042 is disabled in password server mode
+ (see #P0398).
+SeeAlso: #P0416,#P0417,MSR 00001000h
+ * @endverbatim
+ */
+static DECLCALLBACK(int)
+pcarchIOPortPS2SysControlPortARead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ RT_NOREF1(pvUser);
+ if (cb == 1)
+ {
+ *pu32 = PDMDevHlpA20IsEnabled(pDevIns) << 1;
+ return VINF_SUCCESS;
+ }
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Port=%#x cb=%d\n", Port, cb);
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, PS/2 system control port A.}
+ * @see Remark and todo of pcarchIOPortPS2SysControlPortARead().
+ */
+static DECLCALLBACK(int)
+pcarchIOPortPS2SysControlPortAWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ NOREF(pvUser);
+ if (cb == 1)
+ {
+ /*
+ * Fast reset?
+ */
+ if (u32 & 1)
+ {
+ LogRel(("Reset initiated by system port A\n"));
+ return PDMDevHlpVMReset(pDevIns, PDMVMRESET_F_PORT_A);
+ }
+
+ /*
+ * A20 is the only thing we care about of the other stuff.
+ */
+ PDMDevHlpA20Set(pDevIns, !!(u32 & 2));
+ return VINF_SUCCESS;
+ }
+ return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Port=%#x cb=%d u32=%#x\n", Port, cb, u32);
+}
+
+
+/**
+ * @callback_method_impl{FNIOMMMIOWRITE, Ignores writes to the reserved memory.}
+ */
+static DECLCALLBACK(int) pcarchReservedMemoryWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr,
+ void const *pv, unsigned cb)
+{
+ Log2(("pcarchReservedMemoryRead: %#RGp LB %#x %.*Rhxs\n", GCPhysAddr, cb, RT_MIN(cb, 16), pv));
+ NOREF(pDevIns); NOREF(pvUser); NOREF(GCPhysAddr); NOREF(pv); NOREF(cb);
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMMMIOREAD, The reserved memory reads as 0xff.}
+ */
+static DECLCALLBACK(int) pcarchReservedMemoryRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
+{
+ Log2(("pcarchReservedMemoryRead: %#RGp LB %#x\n", GCPhysAddr, cb));
+ NOREF(pDevIns); NOREF(pvUser); NOREF(GCPhysAddr);
+ memset(pv, 0xff, cb);
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnInitComplete,
+ * Turn RAM pages between 0xa0000 and 0xfffff into reserved memory.}
+ */
+static DECLCALLBACK(int) pcarchInitComplete(PPDMDEVINS pDevIns)
+{
+ PVM pVM = PDMDevHlpGetVM(pDevIns);
+ int iRegion = 0;
+ RTGCPHYS const GCPhysEnd = 0x100000;
+ RTGCPHYS GCPhysCur = 0x0a0000;
+ do
+ {
+ if (!PGMPhysIsGCPhysNormal(pVM, GCPhysCur))
+ GCPhysCur += X86_PAGE_SIZE;
+ else
+ {
+ RTGCPHYS const GCPhysStart = GCPhysCur;
+ do
+ GCPhysCur += X86_PAGE_SIZE;
+ while (GCPhysCur < GCPhysEnd && PGMPhysIsGCPhysNormal(pVM, GCPhysCur));
+
+ int rc = PDMDevHlpMMIORegister(pDevIns, GCPhysStart, GCPhysCur - GCPhysStart, NULL /*pvUser*/,
+ IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
+ pcarchReservedMemoryWrite, pcarchReservedMemoryRead,
+ MMR3HeapAPrintf(pVM, MM_TAG_PGM_PHYS /* bad bird*/, "PC Arch Reserved #%u", iRegion));
+ AssertLogRelRCReturn(rc, rc);
+ iRegion++;
+ }
+ } while (GCPhysCur < GCPhysEnd);
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnConstruct}
+ */
+static DECLCALLBACK(int) pcarchConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
+{
+ PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+ PDEVPCARCH pThis = PDMINS_2_DATA(pDevIns, PDEVPCARCH);
+ int rc;
+ Assert(iInstance == 0); RT_NOREF(iInstance);
+
+ /*
+ * Validate configuration.
+ */
+ if (!CFGMR3AreValuesValid(pCfg, "\0"))
+ return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
+
+ /*
+ * Init the data.
+ */
+ pThis->pDevIns = pDevIns;
+
+ /*
+ * Register I/O Ports
+ */
+ rc = PDMDevHlpIOPortRegister(pDevIns, 0xF0, 0x10, NULL,
+ pcarchIOPortFPUWrite, pcarchIOPortFPURead,
+ NULL, NULL, "Math Co-Processor (DOS/OS2 mode)");
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = PDMDevHlpIOPortRegister(pDevIns, 0x92, 1, NULL,
+ pcarchIOPortPS2SysControlPortAWrite, pcarchIOPortPS2SysControlPortARead,
+ NULL, NULL, "PS/2 system control port A (A20 and more)");
+ if (RT_FAILURE(rc))
+ return rc;
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * The device registration structure.
+ */
+const PDMDEVREG g_DevicePcArch =
+{
+ /* u32Version */
+ PDM_DEVREG_VERSION,
+ /* szName */
+ "pcarch",
+ /* szRCMod */
+ "",
+ /* szR0Mod */
+ "",
+ /* pszDescription */
+ "PC Architecture Device",
+ /* fFlags */
+ PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT,
+ /* fClass */
+ PDM_DEVREG_CLASS_ARCH,
+ /* cMaxInstances */
+ 1,
+ /* cbInstance */
+ sizeof(DEVPCARCH),
+ /* pfnConstruct */
+ pcarchConstruct,
+ /* pfnDestruct */
+ NULL,
+ /* pfnRelocate */
+ NULL,
+ /* pfnMemSetup */
+ NULL,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ NULL,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnAttach */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnQueryInterface. */
+ NULL,
+ /* pfnInitComplete. */
+ pcarchInitComplete,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32VersionEnd */
+ PDM_DEVREG_VERSION
+};
+
diff --git a/src/VBox/Devices/PC/DevPcBios.cpp b/src/VBox/Devices/PC/DevPcBios.cpp
new file mode 100644
index 00000000..05d48449
--- /dev/null
+++ b/src/VBox/Devices/PC/DevPcBios.cpp
@@ -0,0 +1,1850 @@
+/* $Id: DevPcBios.cpp $ */
+/** @file
+ * DevPcBios - PC BIOS Device.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_PC_BIOS
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/vmm/pdmstorageifs.h>
+#include <VBox/vmm/mm.h>
+#include <VBox/vmm/pgm.h>
+#include <VBox/vmm/cpum.h>
+#include <VBox/vmm/vm.h>
+
+#include <VBox/log.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/buildconfig.h>
+#include <iprt/file.h>
+#include <iprt/mem.h>
+#include <iprt/string.h>
+#include <iprt/uuid.h>
+#include <iprt/cdefs.h>
+#include <VBox/bios.h>
+#include <VBox/err.h>
+#include <VBox/param.h>
+
+#include "VBoxDD.h"
+#include "VBoxDD2.h"
+#include "DevPcBios.h"
+#include "DevFwCommon.h"
+
+#define NET_BOOT_DEVS 4
+
+
+/** @page pg_devbios_cmos_assign CMOS Assignments (BIOS)
+ *
+ * The BIOS uses a CMOS to store configuration data.
+ * It is currently used as follows:
+ *
+ * @verbatim
+ First CMOS bank (offsets 0x00 to 0x7f):
+ Floppy drive type:
+ 0x10
+ Hard disk type (old):
+ 0x12
+ Equipment byte:
+ 0x14
+ Base memory:
+ 0x15
+ 0x16
+ Extended memory:
+ 0x17
+ 0x18
+ 0x30
+ 0x31
+ First IDE HDD:
+ 0x19
+ 0x1e - 0x25
+ Second IDE HDD:
+ 0x1a
+ 0x26 - 0x2d
+ Checksum of 0x10-0x2d:
+ 0x2e
+ 0x2f
+ Amount of memory above 16M and below 4GB in 64KB units:
+ 0x34
+ 0x35
+ Boot device (BOCHS BIOS specific):
+ 0x38
+ 0x3c
+ 0x3d
+ PXE debug:
+ 0x3f
+ First SATA HDD:
+ 0x40 - 0x47
+ Second SATA HDD:
+ 0x48 - 0x4f
+ Third SATA HDD:
+ 0x50 - 0x57
+ Fourth SATA HDD:
+ 0x58 - 0x5f
+ Number of CPUs:
+ 0x60
+ RAM above 4G in 64KB units:
+ 0x61 - 0x65
+ Third IDE HDD:
+ 0x67 - 0x6e
+ Fourth IDE HDD:
+ 0x70 - 0x77
+ APIC/x2APIC settings:
+ 0x78
+
+ Second CMOS bank (offsets 0x80 to 0xff):
+ Reserved for internal use by PXE ROM:
+ 0x80 - 0x81
+ First net boot device PCI bus/dev/fn:
+ 0x82 - 0x83
+ Second to third net boot devices:
+ 0x84 - 0x89
+ First SCSI HDD:
+ 0x90 - 0x97
+ Second SCSI HDD:
+ 0x98 - 0x9f
+ Third SCSI HDD:
+ 0xa0 - 0xa7
+ Fourth SCSI HDD:
+ 0xa8 - 0xaf
+
+@endverbatim
+ *
+ * @todo Mark which bits are compatible with which BIOSes and
+ * which are our own definitions.
+ */
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+
+/**
+ * The boot device.
+ */
+typedef enum DEVPCBIOSBOOT
+{
+ DEVPCBIOSBOOT_NONE,
+ DEVPCBIOSBOOT_FLOPPY,
+ DEVPCBIOSBOOT_HD,
+ DEVPCBIOSBOOT_DVD,
+ DEVPCBIOSBOOT_LAN
+} DEVPCBIOSBOOT;
+
+/**
+ * PC Bios instance data structure.
+ */
+typedef struct DEVPCBIOS
+{
+ /** Pointer back to the device instance. */
+ PPDMDEVINS pDevIns;
+
+ /** Boot devices (ordered). */
+ DEVPCBIOSBOOT aenmBootDevice[4];
+ /** Bochs shutdown index. */
+ uint32_t iShutdown;
+ /** Floppy device. */
+ char *pszFDDevice;
+ /** Harddisk device. */
+ char *pszHDDevice;
+ /** Sata harddisk device. */
+ char *pszSataDevice;
+ /** LUNs of the four BIOS-accessible SATA disks. */
+ uint32_t iSataHDLUN[4];
+ /** SCSI harddisk device. */
+ char *pszScsiDevice;
+ /** LUNs of the four BIOS-accessible SCSI disks. */
+ uint32_t iScsiHDLUN[4];
+ /** Bios message buffer. */
+ char szMsg[256];
+ /** Bios message buffer index. */
+ uint32_t iMsg;
+ /** The system BIOS ROM data. */
+ uint8_t *pu8PcBios;
+ /** The size of the system BIOS ROM. */
+ uint32_t cbPcBios;
+ /** The name of the BIOS ROM file. */
+ char *pszPcBiosFile;
+ /** The LAN boot ROM data. */
+ uint8_t *pu8LanBoot;
+ /** The name of the LAN boot ROM file. */
+ char *pszLanBootFile;
+ /** The size of the LAN boot ROM. */
+ uint64_t cbLanBoot;
+ /** The DMI tables. */
+ uint8_t au8DMIPage[0x1000];
+ /** The boot countdown (in seconds). */
+ uint8_t uBootDelay;
+ /** I/O-APIC enabled? */
+ uint8_t u8IOAPIC;
+ /** APIC mode to be set up by BIOS */
+ uint8_t u8APICMode;
+ /** PXE debug logging enabled? */
+ uint8_t u8PXEDebug;
+ /** PXE boot PCI bus/dev/fn list. */
+ uint16_t au16NetBootDev[NET_BOOT_DEVS];
+ /** Number of logical CPUs in guest */
+ uint16_t cCpus;
+ /* Physical address of PCI config space MMIO region. Currently unused. */
+ uint64_t u64McfgBase;
+ /* Length of PCI config space MMIO region. Currently unused. */
+ uint64_t cbMcfgLength;
+
+ /** Firmware registration structure. */
+ PDMFWREG FwReg;
+ /** Dummy. */
+ PCPDMFWHLPR3 pFwHlpR3;
+ /** Whether to consult the shutdown status (CMOS[0xf]) for deciding upon soft
+ * or hard reset. */
+ bool fCheckShutdownStatusForSoftReset;
+ /** Whether to clear the shutdown status on hard reset. */
+ bool fClearShutdownStatusOnHardReset;
+ /** Number of soft resets we've logged. */
+ uint32_t cLoggedSoftResets;
+ /** Current port number for Bochs shutdown (used by APM). */
+ RTIOPORT ShutdownPort;
+ /** True=use new port number for Bochs shutdown (used by APM). */
+ bool fNewShutdownPort;
+} DEVPCBIOS;
+/** Pointer to the BIOS device state. */
+typedef DEVPCBIOS *PDEVPCBIOS;
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+/** The saved state version. */
+#define PCBIOS_SSM_VERSION 0
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+/** Saved state DEVPCBIOS field descriptors. */
+static SSMFIELD const g_aPcBiosFields[] =
+{
+ SSMFIELD_ENTRY( DEVPCBIOS, fNewShutdownPort),
+ SSMFIELD_ENTRY_TERM()
+};
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, Bochs Debug and Shutdown ports.}
+ */
+static DECLCALLBACK(int) pcbiosIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ RT_NOREF5(pDevIns, pvUser, Port, pu32, cb);
+ return VERR_IOM_IOPORT_UNUSED;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, Bochs Debug and Shutdown ports.}
+ */
+static DECLCALLBACK(int) pcbiosIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ RT_NOREF1(pvUser);
+ PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS);
+
+ /*
+ * Bochs BIOS char printing.
+ */
+ if ( cb == 1
+ && ( Port == 0x402
+ || Port == 0x403))
+ {
+ /* The raw version. */
+ switch (u32)
+ {
+ case '\r': Log2(("pcbios: <return>\n")); break;
+ case '\n': Log2(("pcbios: <newline>\n")); break;
+ case '\t': Log2(("pcbios: <tab>\n")); break;
+ default: Log2(("pcbios: %c (%02x)\n", u32, u32)); break;
+ }
+
+ /* The readable, buffered version. */
+ uint32_t iMsg = pThis->iMsg;
+ if (u32 == '\n' || u32 == '\r')
+ {
+ AssertStmt(iMsg < sizeof(pThis->szMsg), iMsg = sizeof(pThis->szMsg) - 1);
+ pThis->szMsg[iMsg] = '\0';
+ if (iMsg)
+ Log(("pcbios: %s\n", pThis->szMsg));
+ iMsg = 0;
+ }
+ else
+ {
+ if (iMsg >= sizeof(pThis->szMsg) - 1)
+ {
+ pThis->szMsg[iMsg] = '\0';
+ Log(("pcbios: %s\n", pThis->szMsg));
+ iMsg = 0;
+ }
+ pThis->szMsg[iMsg] = (char)u32;
+ pThis->szMsg[++iMsg] = '\0';
+ }
+ pThis->iMsg = iMsg;
+ return VINF_SUCCESS;
+ }
+
+ /*
+ * Bochs BIOS shutdown request.
+ */
+ if (cb == 1 && Port == pThis->ShutdownPort)
+ {
+ static const unsigned char s_szShutdown[] = "Shutdown";
+ if ( pThis->iShutdown < sizeof(s_szShutdown) /* paranoia */
+ && u32 == s_szShutdown[pThis->iShutdown])
+ {
+ pThis->iShutdown++;
+ if (pThis->iShutdown >= 8)
+ {
+ pThis->iShutdown = 0;
+ LogRel(("PcBios: APM shutdown request\n"));
+ return PDMDevHlpVMPowerOff(pDevIns);
+ }
+ }
+ else
+ pThis->iShutdown = 0;
+ return VINF_SUCCESS;
+ }
+
+ /* not in use. */
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * Register the Bochs shutdown port.
+ * This is used by pcbiosConstruct, pcbiosReset and pcbiosLoadExec.
+ */
+static int pcbiosRegisterShutdown(PPDMDEVINS pDevIns, PDEVPCBIOS pThis, bool fNewShutdownPort)
+{
+ if (pThis->ShutdownPort != 0)
+ {
+ int rc = PDMDevHlpIOPortDeregister(pDevIns, pThis->ShutdownPort, 1);
+ AssertRC(rc);
+ }
+ pThis->fNewShutdownPort = fNewShutdownPort;
+ if (fNewShutdownPort)
+ pThis->ShutdownPort = VBOX_BIOS_SHUTDOWN_PORT;
+ else
+ pThis->ShutdownPort = VBOX_BIOS_OLD_SHUTDOWN_PORT;
+ return PDMDevHlpIOPortRegister(pDevIns, pThis->ShutdownPort, 1, NULL,
+ pcbiosIOPortWrite, pcbiosIOPortRead,
+ NULL, NULL, "Bochs PC BIOS - Shutdown");
+}
+
+
+/**
+ * @callback_method_impl{FNSSMDEVSAVEEXEC}
+ */
+static DECLCALLBACK(int) pcbiosSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+ PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS);
+ SSMR3PutStruct(pSSM, pThis, g_aPcBiosFields);
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNSSMDEVLOADPREP,
+ * Clears the fNewShutdownPort flag prior to loading the state so that old
+ * saved VM states keeps using the old port address (no pcbios state)}
+ */
+static DECLCALLBACK(int) pcbiosLoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+ RT_NOREF(pSSM);
+ PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS);
+
+ /* Since there are legacy saved state files without any SSM data for PCBIOS
+ * this is the only way to handle them correctly. */
+ pThis->fNewShutdownPort = false;
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNSSMDEVLOADEXEC}
+ */
+static DECLCALLBACK(int) pcbiosLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+{
+ PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS);
+
+ if (uVersion > PCBIOS_SSM_VERSION)
+ return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
+ Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
+
+ return SSMR3GetStruct(pSSM, pThis, g_aPcBiosFields);
+}
+
+
+/**
+ * @callback_method_impl{FNSSMDEVLOADDONE,
+ * Updates the shutdown port registration to match the flag loaded (or not).}
+ */
+static DECLCALLBACK(int) pcbiosLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+ RT_NOREF(pSSM);
+ PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS);
+ return pcbiosRegisterShutdown(pDevIns, pThis, pThis->fNewShutdownPort);
+}
+
+
+/**
+ * Write to CMOS memory.
+ * This is used by the init complete code.
+ */
+static void pcbiosCmosWrite(PPDMDEVINS pDevIns, int off, uint32_t u32Val)
+{
+ Assert(off < 256);
+ Assert(u32Val < 256);
+
+ int rc = PDMDevHlpCMOSWrite(pDevIns, off, u32Val);
+ AssertRC(rc);
+}
+
+
+/**
+ * Read from CMOS memory.
+ * This is used by the init complete code.
+ */
+static uint8_t pcbiosCmosRead(PPDMDEVINS pDevIns, unsigned off)
+{
+ Assert(off < 256);
+
+ uint8_t u8val;
+ int rc = PDMDevHlpCMOSRead(pDevIns, off, &u8val);
+ AssertRC(rc);
+
+ return u8val;
+}
+
+
+/**
+ * @interface_method_impl{PDMFWREG,pfnIsHardReset}
+ */
+static DECLCALLBACK(bool) pcbiosFw_IsHardReset(PPDMDEVINS pDevIns, uint32_t fFlags)
+{
+ RT_NOREF1(fFlags);
+ PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS);
+ if (pThis->fCheckShutdownStatusForSoftReset)
+ {
+ uint8_t bShutdownStatus = pcbiosCmosRead(pDevIns, 0xf);
+ if ( bShutdownStatus == 0x5
+ || bShutdownStatus == 0x9
+ || bShutdownStatus == 0xa)
+ {
+ const uint32_t cMaxLogged = 10;
+ if (pThis->cLoggedSoftResets < cMaxLogged)
+ {
+ RTFAR16 Far16 = { 0xfeed, 0xface };
+ PDMDevHlpPhysRead(pDevIns, 0x467, &Far16, sizeof(Far16));
+ pThis->cLoggedSoftResets++;
+ LogRel(("PcBios: Soft reset #%u - shutdown status %#x, warm reset vector (0040:0067) is %04x:%04x%s\n",
+ pThis->cLoggedSoftResets, bShutdownStatus, Far16.sel, Far16.off,
+ pThis->cLoggedSoftResets < cMaxLogged ? "." : " - won't log any more!"));
+ }
+ return false;
+ }
+ }
+ return true;
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnReset}
+ */
+static DECLCALLBACK(void) pcbiosReset(PPDMDEVINS pDevIns)
+{
+ PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS);
+
+ if (pThis->fClearShutdownStatusOnHardReset)
+ {
+ uint8_t bShutdownStatus = pcbiosCmosRead(pDevIns, 0xf);
+ if (bShutdownStatus != 0)
+ {
+ LogRel(("PcBios: Clearing shutdown status code %02x.\n", bShutdownStatus));
+ pcbiosCmosWrite(pDevIns, 0xf, 0);
+ }
+ }
+
+ /* After reset the new BIOS code is active, use the new shutdown port. */
+ pcbiosRegisterShutdown(pDevIns, pThis, true /* fNewShutdownPort */);
+}
+
+
+/**
+ * Attempt to guess the LCHS disk geometry from the MS-DOS master boot record
+ * (partition table).
+ *
+ * @returns VBox status code.
+ * @param pMedia The media device interface of the disk.
+ * @param pLCHSGeometry Where to return the disk geometry on success
+ */
+static int biosGuessDiskLCHS(PPDMIMEDIA pMedia, PPDMMEDIAGEOMETRY pLCHSGeometry)
+{
+ uint8_t aMBR[512], *p;
+ int rc;
+ uint32_t iEndHead, iEndSector, cLCHSCylinders, cLCHSHeads, cLCHSSectors;
+
+ if (!pMedia)
+ return VERR_INVALID_PARAMETER;
+ rc = pMedia->pfnReadPcBios(pMedia, 0, aMBR, sizeof(aMBR));
+ if (RT_FAILURE(rc))
+ return rc;
+ /* Test MBR magic number. */
+ if (aMBR[510] != 0x55 || aMBR[511] != 0xaa)
+ return VERR_INVALID_PARAMETER;
+ for (uint32_t i = 0; i < 4; i++)
+ {
+ /* Figure out the start of a partition table entry. */
+ p = &aMBR[0x1be + i * 16];
+ iEndHead = p[5];
+ iEndSector = p[6] & 63;
+ if ((p[12] | p[13] | p[14] | p[15]) && iEndSector & iEndHead)
+ {
+ /* Assumption: partition terminates on a cylinder boundary. */
+ cLCHSHeads = iEndHead + 1;
+ cLCHSSectors = iEndSector;
+ cLCHSCylinders = RT_MIN(1024, pMedia->pfnGetSize(pMedia) / (512 * cLCHSHeads * cLCHSSectors));
+ if (cLCHSCylinders >= 1)
+ {
+ pLCHSGeometry->cCylinders = cLCHSCylinders;
+ pLCHSGeometry->cHeads = cLCHSHeads;
+ pLCHSGeometry->cSectors = cLCHSSectors;
+ Log(("%s: LCHS=%d %d %d\n", __FUNCTION__, cLCHSCylinders, cLCHSHeads, cLCHSSectors));
+ return VINF_SUCCESS;
+ }
+ }
+ }
+ return VERR_INVALID_PARAMETER;
+}
+
+
+/**
+ * Initializes the CMOS data for one harddisk.
+ */
+static void pcbiosCmosInitHardDisk(PPDMDEVINS pDevIns, int offType, int offInfo, PCPDMMEDIAGEOMETRY pLCHSGeometry)
+{
+ Log2(("%s: offInfo=%#x: LCHS=%d/%d/%d\n", __FUNCTION__, offInfo, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
+ if (offType)
+ pcbiosCmosWrite(pDevIns, offType, 47);
+ /* Cylinders low */
+ pcbiosCmosWrite(pDevIns, offInfo + 0, RT_MIN(pLCHSGeometry->cCylinders, 1024) & 0xff);
+ /* Cylinders high */
+ pcbiosCmosWrite(pDevIns, offInfo + 1, RT_MIN(pLCHSGeometry->cCylinders, 1024) >> 8);
+ /* Heads */
+ pcbiosCmosWrite(pDevIns, offInfo + 2, pLCHSGeometry->cHeads);
+ /* Landing zone low */
+ pcbiosCmosWrite(pDevIns, offInfo + 3, 0xff);
+ /* Landing zone high */
+ pcbiosCmosWrite(pDevIns, offInfo + 4, 0xff);
+ /* Write precomp low */
+ pcbiosCmosWrite(pDevIns, offInfo + 5, 0xff);
+ /* Write precomp high */
+ pcbiosCmosWrite(pDevIns, offInfo + 6, 0xff);
+ /* Sectors */
+ pcbiosCmosWrite(pDevIns, offInfo + 7, pLCHSGeometry->cSectors);
+}
+
+
+/**
+ * Set logical CHS geometry for a hard disk
+ *
+ * @returns VBox status code.
+ * @param pBase Base interface for the device.
+ * @param pHardDisk The hard disk.
+ * @param pLCHSGeometry Where to store the geometry settings.
+ */
+static int setLogicalDiskGeometry(PPDMIBASE pBase, PPDMIMEDIA pHardDisk, PPDMMEDIAGEOMETRY pLCHSGeometry)
+{
+ RT_NOREF1(pBase);
+
+ PDMMEDIAGEOMETRY LCHSGeometry;
+ int rc = pHardDisk->pfnBiosGetLCHSGeometry(pHardDisk, &LCHSGeometry);
+ if ( rc == VERR_PDM_GEOMETRY_NOT_SET
+ || LCHSGeometry.cCylinders == 0
+ || LCHSGeometry.cHeads == 0
+ || LCHSGeometry.cHeads > 255
+ || LCHSGeometry.cSectors == 0
+ || LCHSGeometry.cSectors > 63)
+ {
+ /* No LCHS geometry, autodetect and set. */
+ rc = biosGuessDiskLCHS(pHardDisk, &LCHSGeometry);
+ if (RT_FAILURE(rc))
+ {
+ /* Try if PCHS geometry works, otherwise fall back. */
+ rc = pHardDisk->pfnBiosGetPCHSGeometry(pHardDisk, &LCHSGeometry);
+ }
+ if ( RT_FAILURE(rc)
+ || LCHSGeometry.cCylinders == 0
+ || LCHSGeometry.cCylinders > 1024
+ || LCHSGeometry.cHeads == 0
+ || LCHSGeometry.cHeads > 16
+ || LCHSGeometry.cSectors == 0
+ || LCHSGeometry.cSectors > 63)
+ {
+ uint64_t cSectors = pHardDisk->pfnGetSize(pHardDisk) / 512;
+ if (cSectors / 16 / 63 <= 1024)
+ {
+ LCHSGeometry.cCylinders = RT_MAX(cSectors / 16 / 63, 1);
+ LCHSGeometry.cHeads = 16;
+ }
+ else if (cSectors / 32 / 63 <= 1024)
+ {
+ LCHSGeometry.cCylinders = RT_MAX(cSectors / 32 / 63, 1);
+ LCHSGeometry.cHeads = 32;
+ }
+ else if (cSectors / 64 / 63 <= 1024)
+ {
+ LCHSGeometry.cCylinders = cSectors / 64 / 63;
+ LCHSGeometry.cHeads = 64;
+ }
+ else if (cSectors / 128 / 63 <= 1024)
+ {
+ LCHSGeometry.cCylinders = cSectors / 128 / 63;
+ LCHSGeometry.cHeads = 128;
+ }
+ else
+ {
+ LCHSGeometry.cCylinders = RT_MIN(cSectors / 255 / 63, 1024);
+ LCHSGeometry.cHeads = 255;
+ }
+ LCHSGeometry.cSectors = 63;
+
+ }
+ rc = pHardDisk->pfnBiosSetLCHSGeometry(pHardDisk, &LCHSGeometry);
+ if (rc == VERR_VD_IMAGE_READ_ONLY)
+ {
+ LogRel(("PcBios: ATA failed to update LCHS geometry, read only\n"));
+ rc = VINF_SUCCESS;
+ }
+ else if (rc == VERR_PDM_GEOMETRY_NOT_SET)
+ {
+ LogRel(("PcBios: ATA failed to update LCHS geometry, backend refused\n"));
+ rc = VINF_SUCCESS;
+ }
+ }
+
+ *pLCHSGeometry = LCHSGeometry;
+
+ return rc;
+}
+
+
+/**
+ * Get logical CHS geometry for a hard disk, intended for SCSI/SAS drives
+ * with no physical geometry.
+ *
+ * @returns VBox status code.
+ * @param pHardDisk The hard disk.
+ * @param pLCHSGeometry Where to store the geometry settings.
+ */
+static int getLogicalDiskGeometry(PPDMIMEDIA pHardDisk, PPDMMEDIAGEOMETRY pLCHSGeometry)
+{
+ PDMMEDIAGEOMETRY LCHSGeometry;
+ int rc = VINF_SUCCESS;
+
+ rc = pHardDisk->pfnBiosGetLCHSGeometry(pHardDisk, &LCHSGeometry);
+ if ( rc == VERR_PDM_GEOMETRY_NOT_SET
+ || LCHSGeometry.cCylinders == 0
+ || LCHSGeometry.cHeads == 0
+ || LCHSGeometry.cHeads > 255
+ || LCHSGeometry.cSectors == 0
+ || LCHSGeometry.cSectors > 63)
+ {
+ /* Unlike the ATA case, if the image does not provide valid logical
+ * geometry, we leave things alone and let the BIOS decide what the
+ * logical geometry should be.
+ */
+ rc = VERR_PDM_GEOMETRY_NOT_SET;
+ }
+ else
+ *pLCHSGeometry = LCHSGeometry;
+
+ return rc;
+}
+
+
+/**
+ * Get BIOS boot code from enmBootDevice in order
+ *
+ * @todo r=bird: This is a rather silly function since the conversion is 1:1.
+ */
+static uint8_t getBiosBootCode(PDEVPCBIOS pThis, unsigned iOrder)
+{
+ switch (pThis->aenmBootDevice[iOrder])
+ {
+ case DEVPCBIOSBOOT_NONE:
+ return 0;
+ case DEVPCBIOSBOOT_FLOPPY:
+ return 1;
+ case DEVPCBIOSBOOT_HD:
+ return 2;
+ case DEVPCBIOSBOOT_DVD:
+ return 3;
+ case DEVPCBIOSBOOT_LAN:
+ return 4;
+ default:
+ AssertMsgFailed(("aenmBootDevice[%d]=%d\n", iOrder, pThis->aenmBootDevice[iOrder]));
+ return 0;
+ }
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnInitComplete}
+ *
+ * This routine will write information needed by the bios to the CMOS.
+ *
+ * @see http://www.brl.ntt.co.jp/people/takehiko/interrupt/CMOS.LST.txt for
+ * a description of standard and non-standard CMOS registers.
+ */
+static DECLCALLBACK(int) pcbiosInitComplete(PPDMDEVINS pDevIns)
+{
+ PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS);
+ uint32_t u32;
+ unsigned i;
+ PUVM pUVM = PDMDevHlpGetUVM(pDevIns); AssertRelease(pUVM);
+ PPDMIMEDIA apHDs[4] = {0};
+ LogFlow(("pcbiosInitComplete:\n"));
+
+ PVM pVM = PDMDevHlpGetVM(pDevIns);
+ uint64_t const cbRamSize = MMR3PhysGetRamSize(pVM);
+ uint32_t const cbBelow4GB = MMR3PhysGetRamSizeBelow4GB(pVM);
+ uint64_t const cbAbove4GB = MMR3PhysGetRamSizeAbove4GB(pVM);
+
+ /*
+ * Memory sizes.
+ */
+ /* base memory. */
+ u32 = cbRamSize > 640 ? 640 : (uint32_t)cbRamSize / _1K; /* <-- this test is wrong, but it doesn't matter since we never assign less than 1MB */
+ pcbiosCmosWrite(pDevIns, 0x15, RT_BYTE1(u32)); /* 15h - Base Memory in K, Low Byte */
+ pcbiosCmosWrite(pDevIns, 0x16, RT_BYTE2(u32)); /* 16h - Base Memory in K, High Byte */
+
+ /* Extended memory, up to 65MB */
+ u32 = cbRamSize >= 65 * _1M ? 0xffff : ((uint32_t)cbRamSize - _1M) / _1K;
+ pcbiosCmosWrite(pDevIns, 0x17, RT_BYTE1(u32)); /* 17h - Extended Memory in K, Low Byte */
+ pcbiosCmosWrite(pDevIns, 0x18, RT_BYTE2(u32)); /* 18h - Extended Memory in K, High Byte */
+ pcbiosCmosWrite(pDevIns, 0x30, RT_BYTE1(u32)); /* 30h - Extended Memory in K, Low Byte */
+ pcbiosCmosWrite(pDevIns, 0x31, RT_BYTE2(u32)); /* 31h - Extended Memory in K, High Byte */
+
+ /* Bochs BIOS specific? Anyway, it's the amount of memory above 16MB
+ and below 4GB (as it can only hold 4GB-16M). We have to chop off the
+ top 32MB or it conflict with what the ACPI tables return. (Should these
+ be adjusted, we still have to chop it at 0xfffc0000 or it'll conflict
+ with the high BIOS mapping.) */
+ if (cbRamSize > 16 * _1M)
+ u32 = (RT_MIN(cbBelow4GB, UINT32_C(0xfe000000)) - 16U * _1M) / _64K;
+ else
+ u32 = 0;
+ pcbiosCmosWrite(pDevIns, 0x34, RT_BYTE1(u32));
+ pcbiosCmosWrite(pDevIns, 0x35, RT_BYTE2(u32));
+
+ /* Bochs/VBox BIOS specific way of specifying memory above 4GB in 64KB units.
+ Bochs got these in a different location which we've already used for SATA,
+ it also lacks the last two. */
+ uint64_t c64KBAbove4GB = cbAbove4GB / _64K;
+ /* Make sure it doesn't hit the limits of the current BIOS code (RAM limit of ~255TB). */
+ AssertLogRelMsgReturn((c64KBAbove4GB >> (3 * 8)) < 255, ("%#RX64\n", c64KBAbove4GB), VERR_OUT_OF_RANGE);
+ pcbiosCmosWrite(pDevIns, 0x61, RT_BYTE1(c64KBAbove4GB));
+ pcbiosCmosWrite(pDevIns, 0x62, RT_BYTE2(c64KBAbove4GB));
+ pcbiosCmosWrite(pDevIns, 0x63, RT_BYTE3(c64KBAbove4GB));
+ pcbiosCmosWrite(pDevIns, 0x64, RT_BYTE4(c64KBAbove4GB));
+ pcbiosCmosWrite(pDevIns, 0x65, RT_BYTE5(c64KBAbove4GB));
+
+ /*
+ * Number of CPUs.
+ */
+ pcbiosCmosWrite(pDevIns, 0x60, pThis->cCpus & 0xff);
+
+ /*
+ * APIC mode.
+ */
+ pcbiosCmosWrite(pDevIns, 0x78, pThis->u8APICMode);
+
+ /*
+ * Bochs BIOS specifics - boot device.
+ * We do both new and old (ami-style) settings.
+ * See rombios.c line ~7215 (int19_function).
+ */
+
+ uint8_t reg3d = getBiosBootCode(pThis, 0) | (getBiosBootCode(pThis, 1) << 4);
+ uint8_t reg38 = /* pcbiosCmosRead(pDevIns, 0x38) | */ getBiosBootCode(pThis, 2) << 4;
+ /* This is an extension. Bochs BIOS normally supports only 3 boot devices. */
+ uint8_t reg3c = getBiosBootCode(pThis, 3) | (pThis->uBootDelay << 4);
+ pcbiosCmosWrite(pDevIns, 0x3d, reg3d);
+ pcbiosCmosWrite(pDevIns, 0x38, reg38);
+ pcbiosCmosWrite(pDevIns, 0x3c, reg3c);
+
+ /*
+ * PXE debug option.
+ */
+ pcbiosCmosWrite(pDevIns, 0x3f, pThis->u8PXEDebug);
+
+ /*
+ * Network boot device list.
+ */
+ for (i = 0; i < NET_BOOT_DEVS; ++i)
+ {
+ pcbiosCmosWrite(pDevIns, 0x82 + i * 2, RT_BYTE1(pThis->au16NetBootDev[i]));
+ pcbiosCmosWrite(pDevIns, 0x83 + i * 2, RT_BYTE2(pThis->au16NetBootDev[i]));
+ }
+
+ /*
+ * Floppy drive type.
+ */
+ uint32_t cFDs = 0;
+ u32 = 0;
+ for (i = 0; i < 2; i++)
+ {
+ PPDMIBASE pBase;
+ int rc = PDMR3QueryLun(pUVM, pThis->pszFDDevice, 0, i, &pBase);
+ if (RT_SUCCESS(rc))
+ {
+ PPDMIMEDIA pFD = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIA);
+ if (pFD)
+ {
+ cFDs++;
+ unsigned cShift = i == 0 ? 4 : 0;
+ switch (pFD->pfnGetType(pFD))
+ {
+ case PDMMEDIATYPE_FLOPPY_360: u32 |= 1 << cShift; break;
+ case PDMMEDIATYPE_FLOPPY_1_20: u32 |= 2 << cShift; break;
+ case PDMMEDIATYPE_FLOPPY_720: u32 |= 3 << cShift; break;
+ case PDMMEDIATYPE_FLOPPY_1_44: u32 |= 4 << cShift; break;
+ case PDMMEDIATYPE_FLOPPY_2_88: u32 |= 5 << cShift; break;
+ case PDMMEDIATYPE_FLOPPY_FAKE_15_6: u32 |= 14 << cShift; break;
+ case PDMMEDIATYPE_FLOPPY_FAKE_63_5: u32 |= 15 << cShift; break;
+ default: AssertFailed(); break;
+ }
+ }
+ }
+ }
+ pcbiosCmosWrite(pDevIns, 0x10, u32); /* 10h - Floppy Drive Type */
+
+ /*
+ * Equipment byte.
+ */
+ if (cFDs > 0)
+ u32 = ((cFDs - 1) << 6) | 0x01; /* floppy installed, additional drives. */
+ else
+ u32 = 0x00; /* floppy not installed. */
+ u32 |= RT_BIT(1); /* math coprocessor installed */
+ u32 |= RT_BIT(2); /* keyboard enabled (or mouse?) */
+ u32 |= RT_BIT(3); /* display enabled (monitory type is 0, i.e. vga) */
+ pcbiosCmosWrite(pDevIns, 0x14, u32); /* 14h - Equipment Byte */
+
+ /*
+ * IDE harddisks.
+ */
+ for (i = 0; i < RT_ELEMENTS(apHDs); i++)
+ {
+ PPDMIBASE pBase;
+ int rc = PDMR3QueryLun(pUVM, pThis->pszHDDevice, 0, i, &pBase);
+ if (RT_SUCCESS(rc))
+ apHDs[i] = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIA);
+ if ( apHDs[i]
+ && ( apHDs[i]->pfnGetType(apHDs[i]) != PDMMEDIATYPE_HARD_DISK
+ || !apHDs[i]->pfnBiosIsVisible(apHDs[i])))
+ apHDs[i] = NULL;
+ if (apHDs[i])
+ {
+ PDMMEDIAGEOMETRY LCHSGeometry;
+ int rc2 = setLogicalDiskGeometry(pBase, apHDs[i], &LCHSGeometry);
+ AssertRC(rc2);
+
+ if (i < 4)
+ {
+ /* Award BIOS extended drive types for first to fourth disk.
+ * Used by the BIOS for setting the logical geometry. */
+ int offType, offInfo;
+ switch (i)
+ {
+ case 0:
+ offType = 0x19;
+ offInfo = 0x1e;
+ break;
+ case 1:
+ offType = 0x1a;
+ offInfo = 0x26;
+ break;
+ case 2:
+ offType = 0x00;
+ offInfo = 0x67;
+ break;
+ case 3:
+ default:
+ offType = 0x00;
+ offInfo = 0x70;
+ break;
+ }
+ pcbiosCmosInitHardDisk(pDevIns, offType, offInfo,
+ &LCHSGeometry);
+ }
+ LogRel(("PcBios: ATA LUN#%d LCHS=%u/%u/%u\n", i, LCHSGeometry.cCylinders, LCHSGeometry.cHeads, LCHSGeometry.cSectors));
+ }
+ }
+
+ /* 0Fh means extended and points to 19h, 1Ah */
+ u32 = (apHDs[0] ? 0xf0 : 0) | (apHDs[1] ? 0x0f : 0);
+ pcbiosCmosWrite(pDevIns, 0x12, u32);
+
+ /*
+ * SATA harddisks.
+ */
+ if (pThis->pszSataDevice)
+ {
+ /* Clear pointers to the block devices. */
+ for (i = 0; i < RT_ELEMENTS(apHDs); i++)
+ apHDs[i] = NULL;
+
+ for (i = 0; i < RT_ELEMENTS(apHDs); i++)
+ {
+ PPDMIBASE pBase;
+ int rc = PDMR3QueryLun(pUVM, pThis->pszSataDevice, 0, pThis->iSataHDLUN[i], &pBase);
+ if (RT_SUCCESS(rc))
+ apHDs[i] = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIA);
+ if ( apHDs[i]
+ && ( apHDs[i]->pfnGetType(apHDs[i]) != PDMMEDIATYPE_HARD_DISK
+ || !apHDs[i]->pfnBiosIsVisible(apHDs[i])))
+ apHDs[i] = NULL;
+ if (apHDs[i])
+ {
+ PDMMEDIAGEOMETRY LCHSGeometry;
+ rc = setLogicalDiskGeometry(pBase, apHDs[i], &LCHSGeometry);
+ AssertRC(rc);
+
+ if (i < 4)
+ {
+ /* Award BIOS extended drive types for first to fourth disk.
+ * Used by the BIOS for setting the logical geometry. */
+ int offInfo;
+ switch (i)
+ {
+ case 0:
+ offInfo = 0x40;
+ break;
+ case 1:
+ offInfo = 0x48;
+ break;
+ case 2:
+ offInfo = 0x50;
+ break;
+ case 3:
+ default:
+ offInfo = 0x58;
+ break;
+ }
+ pcbiosCmosInitHardDisk(pDevIns, 0x00, offInfo,
+ &LCHSGeometry);
+ }
+ LogRel(("PcBios: SATA LUN#%d LCHS=%u/%u/%u\n", i, LCHSGeometry.cCylinders, LCHSGeometry.cHeads, LCHSGeometry.cSectors));
+ }
+ }
+ }
+
+ /*
+ * SCSI harddisks. Not handled quite the same as SATA.
+ */
+ if (pThis->pszScsiDevice)
+ {
+ /* Clear pointers to the block devices. */
+ for (i = 0; i < RT_ELEMENTS(apHDs); i++)
+ apHDs[i] = NULL;
+
+ for (i = 0; i < RT_ELEMENTS(apHDs); i++)
+ {
+ PPDMIBASE pBase;
+ int rc = PDMR3QueryLun(pUVM, pThis->pszScsiDevice, 0, pThis->iScsiHDLUN[i], &pBase);
+ if (RT_SUCCESS(rc))
+ apHDs[i] = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIA);
+ if ( apHDs[i]
+ && ( apHDs[i]->pfnGetType(apHDs[i]) != PDMMEDIATYPE_HARD_DISK
+ || !apHDs[i]->pfnBiosIsVisible(apHDs[i])))
+ apHDs[i] = NULL;
+ if (apHDs[i])
+ {
+ PDMMEDIAGEOMETRY LCHSGeometry;
+ rc = getLogicalDiskGeometry(apHDs[i], &LCHSGeometry);
+
+ if (i < 4 && RT_SUCCESS(rc))
+ {
+ /* Extended drive information (for SCSI disks).
+ * Used by the BIOS for setting the logical geometry, but
+ * only if the image provided valid data.
+ */
+ int offInfo;
+ switch (i)
+ {
+ case 0:
+ offInfo = 0x90;
+ break;
+ case 1:
+ offInfo = 0x98;
+ break;
+ case 2:
+ offInfo = 0xa0;
+ break;
+ case 3:
+ default:
+ offInfo = 0xa8;
+ break;
+ }
+ pcbiosCmosInitHardDisk(pDevIns, 0x00, offInfo, &LCHSGeometry);
+ LogRel(("PcBios: SCSI LUN#%d LCHS=%u/%u/%u\n", i, LCHSGeometry.cCylinders, LCHSGeometry.cHeads, LCHSGeometry.cSectors));
+ }
+ else
+ LogRel(("PcBios: SCSI LUN#%d LCHS not provided\n", i));
+ }
+ }
+ }
+
+ /* Calculate and store AT-style CMOS checksum. */
+ uint16_t cksum = 0;
+ for (i = 0x10; i < 0x2e; ++i)
+ cksum += pcbiosCmosRead(pDevIns, i);
+ pcbiosCmosWrite(pDevIns, 0x2e, RT_BYTE1(cksum));
+ pcbiosCmosWrite(pDevIns, 0x2f, RT_BYTE2(cksum));
+
+ LogFlow(("%s: returns VINF_SUCCESS\n", __FUNCTION__));
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnMemSetup}
+ */
+static DECLCALLBACK(void) pcbiosMemSetup(PPDMDEVINS pDevIns, PDMDEVMEMSETUPCTX enmCtx)
+{
+ RT_NOREF1(enmCtx);
+ PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS);
+ LogFlow(("pcbiosMemSetup:\n"));
+
+ /*
+ * Re-shadow the LAN ROM image and make it RAM/RAM.
+ *
+ * This is normally done by the BIOS code, but since we're currently lacking
+ * the chipset support for this we do it here (and in the constructor).
+ */
+ uint32_t cPages = RT_ALIGN_64(pThis->cbLanBoot, PAGE_SIZE) >> PAGE_SHIFT;
+ RTGCPHYS GCPhys = VBOX_LANBOOT_SEG << 4;
+ while (cPages > 0)
+ {
+ uint8_t abPage[PAGE_SIZE];
+ int rc;
+
+ /* Read the (original) ROM page and write it back to the RAM page. */
+ rc = PDMDevHlpROMProtectShadow(pDevIns, GCPhys, PAGE_SIZE, PGMROMPROT_READ_ROM_WRITE_RAM);
+ AssertLogRelRC(rc);
+
+ rc = PDMDevHlpPhysRead(pDevIns, GCPhys, abPage, PAGE_SIZE);
+ AssertLogRelRC(rc);
+ if (RT_FAILURE(rc))
+ memset(abPage, 0xcc, sizeof(abPage));
+
+ rc = PDMDevHlpPhysWrite(pDevIns, GCPhys, abPage, PAGE_SIZE);
+ AssertLogRelRC(rc);
+
+ /* Switch to the RAM/RAM mode. */
+ rc = PDMDevHlpROMProtectShadow(pDevIns, GCPhys, PAGE_SIZE, PGMROMPROT_READ_RAM_WRITE_RAM);
+ AssertLogRelRC(rc);
+
+ /* Advance */
+ GCPhys += PAGE_SIZE;
+ cPages--;
+ }
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnDestruct}
+ */
+static DECLCALLBACK(int) pcbiosDestruct(PPDMDEVINS pDevIns)
+{
+ PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
+ PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS);
+ LogFlow(("pcbiosDestruct:\n"));
+
+ /*
+ * Free MM heap pointers.
+ */
+ if (pThis->pu8PcBios)
+ {
+ PDMDevHlpMMHeapFree(pDevIns, pThis->pu8PcBios);
+ pThis->pu8PcBios = NULL;
+ }
+
+ if (pThis->pszPcBiosFile)
+ {
+ PDMDevHlpMMHeapFree(pDevIns, pThis->pszPcBiosFile);
+ pThis->pszPcBiosFile = NULL;
+ }
+
+ if (pThis->pu8LanBoot)
+ {
+ PDMDevHlpMMHeapFree(pDevIns, pThis->pu8LanBoot);
+ pThis->pu8LanBoot = NULL;
+ }
+
+ if (pThis->pszLanBootFile)
+ {
+ PDMDevHlpMMHeapFree(pDevIns, pThis->pszLanBootFile);
+ pThis->pszLanBootFile = NULL;
+ }
+
+ if (pThis->pszHDDevice)
+ {
+ PDMDevHlpMMHeapFree(pDevIns, pThis->pszHDDevice);
+ pThis->pszHDDevice = NULL;
+ }
+
+ if (pThis->pszFDDevice)
+ {
+ PDMDevHlpMMHeapFree(pDevIns, pThis->pszFDDevice);
+ pThis->pszFDDevice = NULL;
+ }
+
+ if (pThis->pszSataDevice)
+ {
+ PDMDevHlpMMHeapFree(pDevIns, pThis->pszSataDevice);
+ pThis->pszSataDevice = NULL;
+ }
+
+ if (pThis->pszScsiDevice)
+ {
+ PDMDevHlpMMHeapFree(pDevIns, pThis->pszScsiDevice);
+ pThis->pszScsiDevice = NULL;
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * Convert config value to DEVPCBIOSBOOT.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance data.
+ * @param pCfg Configuration handle.
+ * @param pszParam The name of the value to read.
+ * @param penmBoot Where to store the boot method.
+ */
+static int pcbiosBootFromCfg(PPDMDEVINS pDevIns, PCFGMNODE pCfg, const char *pszParam, DEVPCBIOSBOOT *penmBoot)
+{
+ char *psz;
+ int rc = CFGMR3QueryStringAlloc(pCfg, pszParam, &psz);
+ if (RT_FAILURE(rc))
+ return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+ N_("Configuration error: Querying \"%s\" as a string failed"),
+ pszParam);
+ if (!strcmp(psz, "DVD") || !strcmp(psz, "CDROM"))
+ *penmBoot = DEVPCBIOSBOOT_DVD;
+ else if (!strcmp(psz, "IDE"))
+ *penmBoot = DEVPCBIOSBOOT_HD;
+ else if (!strcmp(psz, "FLOPPY"))
+ *penmBoot = DEVPCBIOSBOOT_FLOPPY;
+ else if (!strcmp(psz, "LAN"))
+ *penmBoot = DEVPCBIOSBOOT_LAN;
+ else if (!strcmp(psz, "NONE"))
+ *penmBoot = DEVPCBIOSBOOT_NONE;
+ else
+ {
+ PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+ N_("Configuration error: The \"%s\" value \"%s\" is unknown"),
+ pszParam, psz);
+ rc = VERR_INTERNAL_ERROR;
+ }
+ MMR3HeapFree(psz);
+ return rc;
+}
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnConstruct}
+ */
+static DECLCALLBACK(int) pcbiosConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
+{
+ PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+ PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS);
+ int rc;
+ int cb;
+ Assert(iInstance == 0); RT_NOREF(iInstance);
+
+ /*
+ * Validate configuration.
+ */
+ if (!CFGMR3AreValuesValid(pCfg,
+ "BootDevice0\0"
+ "BootDevice1\0"
+ "BootDevice2\0"
+ "BootDevice3\0"
+ "HardDiskDevice\0"
+ "SataHardDiskDevice\0"
+ "SataLUN1\0"
+ "SataLUN2\0"
+ "SataLUN3\0"
+ "SataLUN4\0"
+ "ScsiHardDiskDevice\0"
+ "ScsiLUN1\0"
+ "ScsiLUN2\0"
+ "ScsiLUN3\0"
+ "ScsiLUN4\0"
+ "FloppyDevice\0"
+ "DelayBoot\0"
+ "BiosRom\0"
+ "LanBootRom\0"
+ "PXEDebug\0"
+ "UUID\0"
+ "IOAPIC\0"
+ "APIC\0"
+ "NumCPUs\0"
+ "McfgBase\0"
+ "McfgLength\0"
+ "DmiBIOSFirmwareMajor\0"
+ "DmiBIOSFirmwareMinor\0"
+ "DmiBIOSReleaseDate\0"
+ "DmiBIOSReleaseMajor\0"
+ "DmiBIOSReleaseMinor\0"
+ "DmiBIOSVendor\0"
+ "DmiBIOSVersion\0"
+ "DmiSystemFamily\0"
+ "DmiSystemProduct\0"
+ "DmiSystemSerial\0"
+ "DmiSystemSKU\0"
+ "DmiSystemUuid\0"
+ "DmiSystemVendor\0"
+ "DmiSystemVersion\0"
+ "DmiBoardAssetTag\0"
+ "DmiBoardBoardType\0"
+ "DmiBoardLocInChass\0"
+ "DmiBoardProduct\0"
+ "DmiBoardSerial\0"
+ "DmiBoardVendor\0"
+ "DmiBoardVersion\0"
+ "DmiChassisAssetTag\0"
+ "DmiChassisSerial\0"
+ "DmiChassisType\0"
+ "DmiChassisVendor\0"
+ "DmiChassisVersion\0"
+ "DmiProcManufacturer\0"
+ "DmiProcVersion\0"
+ "DmiOEMVBoxVer\0"
+ "DmiOEMVBoxRev\0"
+ "DmiUseHostInfo\0"
+ "DmiExposeMemoryTable\0"
+ "DmiExposeProcInf\0"
+ "CheckShutdownStatusForSoftReset\0"
+ "ClearShutdownStatusOnHardReset\0"
+ ))
+ return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
+ N_("Invalid configuration for device pcbios device"));
+
+ /*
+ * Init the data.
+ */
+ rc = CFGMR3QueryU16Def(pCfg, "NumCPUs", &pThis->cCpus, 1);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"NumCPUs\" as integer failed"));
+
+ rc = CFGMR3QueryU64Def(pCfg, "McfgBase", &pThis->u64McfgBase, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"\" as integer failed"));
+ rc = CFGMR3QueryU64Def(pCfg, "McfgLength", &pThis->cbMcfgLength, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"McfgLength\" as integer failed"));
+
+
+ LogRel(("PcBios: [SMP] BIOS with %u CPUs\n", pThis->cCpus));
+
+ rc = CFGMR3QueryU8Def(pCfg, "IOAPIC", &pThis->u8IOAPIC, 1);
+ if (RT_FAILURE (rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"IOAPIC\""));
+
+ rc = CFGMR3QueryU8Def(pCfg, "APIC", &pThis->u8APICMode, 1);
+ if (RT_FAILURE (rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Failed to read \"APIC\""));
+
+ static const char * const s_apszBootDevices[] = { "BootDevice0", "BootDevice1", "BootDevice2", "BootDevice3" };
+ Assert(RT_ELEMENTS(s_apszBootDevices) == RT_ELEMENTS(pThis->aenmBootDevice));
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->aenmBootDevice); i++)
+ {
+ rc = pcbiosBootFromCfg(pDevIns, pCfg, s_apszBootDevices[i], &pThis->aenmBootDevice[i]);
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+
+ rc = CFGMR3QueryStringAlloc(pCfg, "HardDiskDevice", &pThis->pszHDDevice);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"HardDiskDevice\" as a string failed"));
+
+ rc = CFGMR3QueryStringAlloc(pCfg, "FloppyDevice", &pThis->pszFDDevice);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"FloppyDevice\" as a string failed"));
+
+ rc = CFGMR3QueryStringAlloc(pCfg, "SataHardDiskDevice", &pThis->pszSataDevice);
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+ pThis->pszSataDevice = NULL;
+ else if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"SataHardDiskDevice\" as a string failed"));
+
+ if (pThis->pszSataDevice)
+ {
+ static const char * const s_apszSataDisks[] =
+ { "SataLUN1", "SataLUN2", "SataLUN3", "SataLUN4" };
+ Assert(RT_ELEMENTS(s_apszSataDisks) == RT_ELEMENTS(pThis->iSataHDLUN));
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->iSataHDLUN); i++)
+ {
+ rc = CFGMR3QueryU32(pCfg, s_apszSataDisks[i], &pThis->iSataHDLUN[i]);
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+ pThis->iSataHDLUN[i] = i;
+ else if (RT_FAILURE(rc))
+ return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+ N_("Configuration error: Querying \"%s\" as a string failed"), s_apszSataDisks);
+ }
+ }
+
+ /* Repeat the exercise for SCSI drives. */
+ rc = CFGMR3QueryStringAlloc(pCfg, "ScsiHardDiskDevice", &pThis->pszScsiDevice);
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+ pThis->pszScsiDevice = NULL;
+ else if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"ScsiHardDiskDevice\" as a string failed"));
+
+ if (pThis->pszScsiDevice)
+ {
+ static const char * const s_apszScsiDisks[] =
+ { "ScsiLUN1", "ScsiLUN2", "ScsiLUN3", "ScsiLUN4" };
+ Assert(RT_ELEMENTS(s_apszScsiDisks) == RT_ELEMENTS(pThis->iScsiHDLUN));
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->iScsiHDLUN); i++)
+ {
+ rc = CFGMR3QueryU32(pCfg, s_apszScsiDisks[i], &pThis->iScsiHDLUN[i]);
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+ pThis->iScsiHDLUN[i] = i;
+ else if (RT_FAILURE(rc))
+ return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+ N_("Configuration error: Querying \"%s\" as a string failed"), s_apszScsiDisks);
+ }
+ }
+
+
+ /*
+ * Register I/O Ports and PC BIOS.
+ */
+ rc = PDMDevHlpIOPortRegister(pDevIns, 0x400, 4, NULL, pcbiosIOPortWrite, pcbiosIOPortRead,
+ NULL, NULL, "Bochs PC BIOS - Panic & Debug");
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = pcbiosRegisterShutdown(pDevIns, pThis, true /* fNewShutdownPort */);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * Register SSM handlers, for remembering which shutdown port to use.
+ */
+ rc = PDMDevHlpSSMRegisterEx(pDevIns, PCBIOS_SSM_VERSION, 1 /* cbGuess */, NULL,
+ NULL, NULL, NULL,
+ NULL, pcbiosSaveExec, NULL,
+ pcbiosLoadPrep, pcbiosLoadExec, pcbiosLoadDone);
+
+ /*
+ * Read the PXE debug logging option.
+ */
+ rc = CFGMR3QueryU8Def(pCfg, "PXEDebug", &pThis->u8PXEDebug, false);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"PXEDebug\" as integer failed"));
+
+ /* Clear the net boot device list. All bits set invokes old behavior,
+ * as if no second CMOS bank was present.
+ */
+ memset(&pThis->au16NetBootDev, 0xff, sizeof(pThis->au16NetBootDev));
+
+ /*
+ * Determine the network boot order.
+ */
+ PCFGMNODE pCfgNetBoot = CFGMR3GetChild(pCfg, "NetBoot");
+ if (pCfgNetBoot == NULL)
+ {
+ /* Do nothing. */
+ rc = VINF_SUCCESS;
+ }
+ else
+ {
+ PCFGMNODE pCfgNetBootDevice;
+ uint8_t u8PciBus;
+ uint8_t u8PciDev;
+ uint8_t u8PciFn;
+ uint16_t u16BusDevFn;
+ char szIndex[] = "?";
+
+ Assert(pCfgNetBoot);
+ for (unsigned i = 0; i < NET_BOOT_DEVS; ++i)
+ {
+ szIndex[0] = '0' + i;
+ pCfgNetBootDevice = CFGMR3GetChild(pCfgNetBoot, szIndex);
+
+ rc = CFGMR3QueryU8(pCfgNetBootDevice, "PCIBusNo", &u8PciBus);
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
+ {
+ /* Do nothing and stop iterating. */
+ rc = VINF_SUCCESS;
+ break;
+ }
+ else if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"Netboot/x/PCIBusNo\" as integer failed"));
+ rc = CFGMR3QueryU8(pCfgNetBootDevice, "PCIDeviceNo", &u8PciDev);
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
+ {
+ /* Do nothing and stop iterating. */
+ rc = VINF_SUCCESS;
+ break;
+ }
+ else if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"Netboot/x/PCIDeviceNo\" as integer failed"));
+ rc = CFGMR3QueryU8(pCfgNetBootDevice, "PCIFunctionNo", &u8PciFn);
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
+ {
+ /* Do nothing and stop iterating. */
+ rc = VINF_SUCCESS;
+ break;
+ }
+ else if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"Netboot/x/PCIFunctionNo\" as integer failed"));
+ u16BusDevFn = (((uint16_t)u8PciBus) << 8) | ((u8PciDev & 0x1F) << 3) | (u8PciFn & 0x7);
+ pThis->au16NetBootDev[i] = u16BusDevFn;
+ }
+ }
+
+ /*
+ * Get the system BIOS ROM file name.
+ */
+ rc = CFGMR3QueryStringAlloc(pCfg, "BiosRom", &pThis->pszPcBiosFile);
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+ {
+ pThis->pszPcBiosFile = NULL;
+ rc = VINF_SUCCESS;
+ }
+ else if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"BiosRom\" as a string failed"));
+ else if (!*pThis->pszPcBiosFile)
+ {
+ MMR3HeapFree(pThis->pszPcBiosFile);
+ pThis->pszPcBiosFile = NULL;
+ }
+
+ /*
+ * Get the CPU arch so we can load the appropriate ROMs.
+ */
+ PVM pVM = PDMDevHlpGetVM(pDevIns);
+ CPUMMICROARCH const enmMicroarch = pVM ? pVM->cpum.ro.GuestFeatures.enmMicroarch : kCpumMicroarch_Intel_P6;
+
+ if (pThis->pszPcBiosFile)
+ {
+ /*
+ * Load the BIOS ROM.
+ */
+ RTFILE hFilePcBios;
+ rc = RTFileOpen(&hFilePcBios, pThis->pszPcBiosFile,
+ RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
+ if (RT_SUCCESS(rc))
+ {
+ /* Figure the size and check restrictions. */
+ uint64_t cbPcBios;
+ rc = RTFileGetSize(hFilePcBios, &cbPcBios);
+ if (RT_SUCCESS(rc))
+ {
+ pThis->cbPcBios = (uint32_t)cbPcBios;
+ if ( RT_ALIGN(pThis->cbPcBios, _64K) == pThis->cbPcBios
+ && pThis->cbPcBios == cbPcBios
+ && pThis->cbPcBios <= 32 * _64K
+ && pThis->cbPcBios >= _64K)
+ {
+ pThis->pu8PcBios = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, pThis->cbPcBios);
+ if (pThis->pu8PcBios)
+ {
+ rc = RTFileRead(hFilePcBios, pThis->pu8PcBios, pThis->cbPcBios, NULL);
+ if (RT_FAILURE(rc))
+ rc = PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+ N_("Error reading the BIOS image ('%s)"), pThis->pszPcBiosFile);
+ }
+ else
+ rc = PDMDevHlpVMSetError(pDevIns, VERR_NO_MEMORY, RT_SRC_POS,
+ N_("Failed to allocate %#x bytes for loading the BIOS image"),
+ pThis->cbPcBios);
+ }
+ else
+ rc = PDMDevHlpVMSetError(pDevIns, VERR_OUT_OF_RANGE, RT_SRC_POS,
+ N_("Invalid system BIOS file size ('%s'): %#llx (%llu)"),
+ pThis->pszPcBiosFile, cbPcBios, cbPcBios);
+ }
+ else
+ rc = PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+ N_("Failed to query the system BIOS file size ('%s')"),
+ pThis->pszPcBiosFile);
+ RTFileClose(hFilePcBios);
+ }
+ else
+ rc = PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+ N_("Failed to open system BIOS file '%s'"), pThis->pszPcBiosFile);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ LogRel(("PcBios: Using BIOS ROM '%s' with a size of %#x bytes\n", pThis->pszPcBiosFile, pThis->cbPcBios));
+ }
+ else
+ {
+ /*
+ * Use one of the embedded BIOS ROM images.
+ */
+ uint8_t const *pbBios;
+ uint32_t cbBios;
+ if ( enmMicroarch == kCpumMicroarch_Intel_8086
+ || enmMicroarch == kCpumMicroarch_Intel_80186
+ || enmMicroarch == kCpumMicroarch_NEC_V20
+ || enmMicroarch == kCpumMicroarch_NEC_V30)
+ {
+ pbBios = g_abPcBiosBinary8086;
+ cbBios = g_cbPcBiosBinary8086;
+ LogRel(("PcBios: Using the 8086 BIOS image!\n"));
+ }
+ else if (enmMicroarch == kCpumMicroarch_Intel_80286)
+ {
+ pbBios = g_abPcBiosBinary286;
+ cbBios = g_cbPcBiosBinary286;
+ LogRel(("PcBios: Using the 286 BIOS image!\n"));
+ }
+ else
+ {
+ pbBios = g_abPcBiosBinary386;
+ cbBios = g_cbPcBiosBinary386;
+ LogRel(("PcBios: Using the 386+ BIOS image.\n"));
+ }
+ pThis->pu8PcBios = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, cbBios);
+ if (pThis->pu8PcBios)
+ {
+ pThis->cbPcBios = cbBios;
+ memcpy(pThis->pu8PcBios, pbBios, cbBios);
+ }
+ else
+ return PDMDevHlpVMSetError(pDevIns, VERR_NO_MEMORY, RT_SRC_POS,
+ N_("Failed to allocate %#x bytes for loading the embedded BIOS image"), cbBios);
+ }
+ const uint8_t *pu8PcBiosBinary = pThis->pu8PcBios;
+ uint32_t cbPcBiosBinary = pThis->cbPcBios;
+
+ /*
+ * Query the machine's UUID for SMBIOS/DMI use.
+ */
+ RTUUID uuid;
+ rc = CFGMR3QueryBytes(pCfg, "UUID", &uuid, sizeof(uuid));
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"UUID\" failed"));
+
+ /* Convert the UUID to network byte order. Not entirely straightforward as parts are MSB already... */
+ uuid.Gen.u32TimeLow = RT_H2BE_U32(uuid.Gen.u32TimeLow);
+ uuid.Gen.u16TimeMid = RT_H2BE_U16(uuid.Gen.u16TimeMid);
+ uuid.Gen.u16TimeHiAndVersion = RT_H2BE_U16(uuid.Gen.u16TimeHiAndVersion);
+ uint16_t cbDmiTables = 0;
+ uint16_t cNumDmiTables = 0;
+ rc = FwCommonPlantDMITable(pDevIns, pThis->au8DMIPage, VBOX_DMI_TABLE_SIZE,
+ &uuid, pCfg, pThis->cCpus, &cbDmiTables, &cNumDmiTables);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ for (unsigned i = 0; i < pThis->cbPcBios; i += 16)
+ {
+ /* If the DMI table is located at the expected place, patch the DMI table length and the checksum. */
+ if ( pThis->pu8PcBios[i + 0x00] == '_'
+ && pThis->pu8PcBios[i + 0x01] == 'D'
+ && pThis->pu8PcBios[i + 0x02] == 'M'
+ && pThis->pu8PcBios[i + 0x03] == 'I'
+ && pThis->pu8PcBios[i + 0x04] == '_'
+ && *(uint16_t*)&pThis->pu8PcBios[i + 0x06] == 0)
+ {
+ *(uint16_t*)&pThis->pu8PcBios[i + 0x06] = RT_H2LE_U16(cbDmiTables);
+ *(uint16_t*)&pThis->pu8PcBios[i + 0x0C] = RT_H2LE_U16(cNumDmiTables);
+ uint8_t u8Sum = 0;
+ for (unsigned j = 0; j < pThis->cbPcBios; j++)
+ if (j != i + 0x05)
+ u8Sum += pThis->pu8PcBios[j];
+ pThis->pu8PcBios[i + 0x05] = -u8Sum;
+ break;
+ }
+ }
+
+ if (pThis->u8IOAPIC)
+ {
+ FwCommonPlantMpsTable(pDevIns, pThis->au8DMIPage /* aka VBOX_DMI_TABLE_BASE */ + VBOX_DMI_TABLE_SIZE,
+ _4K - VBOX_DMI_TABLE_SIZE, pThis->cCpus);
+ FwCommonPlantMpsFloatPtr(pDevIns, VBOX_DMI_TABLE_BASE + VBOX_DMI_TABLE_SIZE);
+ LogRel(("PcBios: MPS table at %08x\n", VBOX_DMI_TABLE_BASE + VBOX_DMI_TABLE_SIZE));
+ }
+
+ rc = PDMDevHlpROMRegister(pDevIns, VBOX_DMI_TABLE_BASE, _4K, pThis->au8DMIPage, _4K,
+ PGMPHYS_ROM_FLAGS_PERMANENT_BINARY, "DMI tables");
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * Map the BIOS into memory.
+ * There are two mappings:
+ * 1. 0x000e0000 to 0x000fffff contains the last 128 kb of the bios.
+ * The bios code might be 64 kb in size, and will then start at 0xf0000.
+ * 2. 0xfffxxxxx to 0xffffffff contains the entire bios.
+ */
+ AssertReleaseMsg(cbPcBiosBinary >= _64K, ("cbPcBiosBinary=%#x\n", cbPcBiosBinary));
+ AssertReleaseMsg(RT_ALIGN_Z(cbPcBiosBinary, _64K) == cbPcBiosBinary,
+ ("cbPcBiosBinary=%#x\n", cbPcBiosBinary));
+ cb = RT_MIN(cbPcBiosBinary, 128 * _1K); /* Effectively either 64 or 128K. */
+ rc = PDMDevHlpROMRegister(pDevIns, 0x00100000 - cb, cb, &pu8PcBiosBinary[cbPcBiosBinary - cb], cb,
+ PGMPHYS_ROM_FLAGS_PERMANENT_BINARY, "PC BIOS - 0xfffff");
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = PDMDevHlpROMRegister(pDevIns, (uint32_t)-(int32_t)cbPcBiosBinary, cbPcBiosBinary, pu8PcBiosBinary, cbPcBiosBinary,
+ PGMPHYS_ROM_FLAGS_PERMANENT_BINARY, "PC BIOS - 0xffffffff");
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * Get the LAN boot ROM file name.
+ */
+ rc = CFGMR3QueryStringAlloc(pCfg, "LanBootRom", &pThis->pszLanBootFile);
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+ {
+ pThis->pszLanBootFile = NULL;
+ rc = VINF_SUCCESS;
+ }
+ else if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"LanBootRom\" as a string failed"));
+ else if (!*pThis->pszLanBootFile)
+ {
+ MMR3HeapFree(pThis->pszLanBootFile);
+ pThis->pszLanBootFile = NULL;
+ }
+
+ /*
+ * Not loading LAN ROM for old CPUs.
+ */
+ if ( enmMicroarch != kCpumMicroarch_Intel_8086
+ && enmMicroarch != kCpumMicroarch_Intel_80186
+ && enmMicroarch != kCpumMicroarch_NEC_V20
+ && enmMicroarch != kCpumMicroarch_NEC_V30
+ && enmMicroarch != kCpumMicroarch_Intel_80286)
+ {
+ const uint8_t *pu8LanBootBinary = NULL;
+ uint64_t cbLanBootBinary;
+ uint64_t cbFileLanBoot = 0;
+
+ /*
+ * Open the LAN boot ROM and figure it size.
+ * Determine the LAN boot ROM size, open specified ROM file in the process.
+ */
+ if (pThis->pszLanBootFile)
+ {
+ RTFILE hFileLanBoot = NIL_RTFILE;
+ rc = RTFileOpen(&hFileLanBoot, pThis->pszLanBootFile,
+ RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTFileGetSize(hFileLanBoot, &cbFileLanBoot);
+ if (RT_SUCCESS(rc))
+ {
+ if (cbFileLanBoot <= _64K - (VBOX_LANBOOT_SEG << 4 & 0xffff))
+ {
+ LogRel(("PcBios: Using LAN ROM '%s' with a size of %#x bytes\n", pThis->pszLanBootFile, cbFileLanBoot));
+
+ /*
+ * Allocate buffer for the LAN boot ROM data and load it.
+ */
+ pThis->pu8LanBoot = (uint8_t *)PDMDevHlpMMHeapAllocZ(pDevIns, cbFileLanBoot);
+ if (pThis->pu8LanBoot)
+ {
+ rc = RTFileRead(hFileLanBoot, pThis->pu8LanBoot, cbFileLanBoot, NULL);
+ AssertLogRelRCReturnStmt(rc, RTFileClose(hFileLanBoot), rc);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+ else
+ rc = VERR_TOO_MUCH_DATA;
+ }
+ RTFileClose(hFileLanBoot);
+ }
+ if (RT_FAILURE(rc))
+ {
+ /*
+ * Play stupid and ignore failures, falling back to the built-in LAN boot ROM.
+ */
+ /** @todo r=bird: This should have some kind of rational. We don't usually
+ * ignore the VM configuration. */
+ LogRel(("PcBios: Failed to open LAN boot ROM file '%s', rc=%Rrc!\n", pThis->pszLanBootFile, rc));
+ MMR3HeapFree(pThis->pszLanBootFile);
+ pThis->pszLanBootFile = NULL;
+ }
+ }
+
+ /* If we were unable to get the data from file for whatever reason, fall
+ * back to the built-in LAN boot ROM image.
+ */
+ if (pThis->pu8LanBoot == NULL)
+ {
+#ifdef VBOX_WITH_PXE_ROM
+ pu8LanBootBinary = g_abNetBiosBinary;
+ cbLanBootBinary = g_cbNetBiosBinary;
+#endif
+ }
+ else
+ {
+ pu8LanBootBinary = pThis->pu8LanBoot;
+ cbLanBootBinary = cbFileLanBoot;
+ }
+
+ /*
+ * Map the Network Boot ROM into memory.
+ *
+ * Currently there is a fixed mapping: 0x000e2000 to 0x000effff contains
+ * the (up to) 56 kb ROM image. The mapping size is fixed to trouble with
+ * the saved state (in PGM).
+ */
+ if (pu8LanBootBinary)
+ {
+ pThis->cbLanBoot = cbLanBootBinary;
+
+ rc = PDMDevHlpROMRegister(pDevIns, VBOX_LANBOOT_SEG << 4,
+ RT_MAX(cbLanBootBinary, _64K - (VBOX_LANBOOT_SEG << 4 & 0xffff)),
+ pu8LanBootBinary, cbLanBootBinary,
+ PGMPHYS_ROM_FLAGS_SHADOWED, "Net Boot ROM");
+ AssertRCReturn(rc, rc);
+ }
+ }
+ else if (pThis->pszLanBootFile)
+ LogRel(("PcBios: Skipping LAN ROM '%s' due to ancient target CPU.\n", pThis->pszLanBootFile));
+#ifdef VBOX_WITH_PXE_ROM
+ else
+ LogRel(("PcBios: Skipping built in ROM due to ancient target CPU.\n"));
+#endif
+
+ /*
+ * Configure Boot delay.
+ */
+ rc = CFGMR3QueryU8Def(pCfg, "DelayBoot", &pThis->uBootDelay, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"DelayBoot\" as integer failed"));
+ if (pThis->uBootDelay > 15)
+ pThis->uBootDelay = 15;
+
+
+ /*
+ * Read shutdown status code config and register ourselves as the firmware device.
+ */
+
+ /** @cfgm{CheckShutdownStatusForSoftReset, boolean, true}
+ * Whether to consult the shutdown status code (CMOS register 0Fh) to
+ * determine whether the guest intended a soft or hard reset. Currently only
+ * shutdown status codes 05h, 09h and 0Ah are considered soft reset. */
+ rc = CFGMR3QueryBoolDef(pCfg, "CheckShutdownStatusForSoftReset", &pThis->fCheckShutdownStatusForSoftReset, true);
+ AssertLogRelRCReturn(rc, rc);
+
+ /** @cfgm{ClearShutdownStatusOnHardReset, boolean, true}
+ * Whether to clear the shutdown status code (CMOS register 0Fh) on hard reset. */
+ rc = CFGMR3QueryBoolDef(pCfg, "ClearShutdownStatusOnHardReset", &pThis->fClearShutdownStatusOnHardReset, true);
+ AssertLogRelRCReturn(rc, rc);
+
+ LogRel(("PcBios: fCheckShutdownStatusForSoftReset=%RTbool fClearShutdownStatusOnHardReset=%RTbool\n",
+ pThis->fCheckShutdownStatusForSoftReset, pThis->fClearShutdownStatusOnHardReset));
+
+ static PDMFWREG const s_FwReg = { PDM_FWREG_VERSION, pcbiosFw_IsHardReset, PDM_FWREG_VERSION };
+ rc = PDMDevHlpFirmwareRegister(pDevIns, &s_FwReg, &pThis->pFwHlpR3);
+ AssertLogRelRCReturn(rc, rc);
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * The device registration structure.
+ */
+const PDMDEVREG g_DevicePcBios =
+{
+ /* u32Version */
+ PDM_DEVREG_VERSION,
+ /* szName */
+ "pcbios",
+ /* szRCMod */
+ "",
+ /* szR0Mod */
+ "",
+ /* pszDescription */
+ "PC BIOS Device",
+ /* fFlags */
+ PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64,
+ /* fClass */
+ PDM_DEVREG_CLASS_ARCH_BIOS,
+ /* cMaxInstances */
+ 1,
+ /* cbInstance */
+ sizeof(DEVPCBIOS),
+ /* pfnConstruct */
+ pcbiosConstruct,
+ /* pfnDestruct */
+ pcbiosDestruct,
+ /* pfnRelocate */
+ NULL,
+ /* pfnMemSetup */
+ pcbiosMemSetup,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ pcbiosReset,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnAttach */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnQueryInterface. */
+ NULL,
+ /* pfnInitComplete. */
+ pcbiosInitComplete,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32VersionEnd */
+ PDM_DEVREG_VERSION
+};
+
diff --git a/src/VBox/Devices/PC/DevPcBios.h b/src/VBox/Devices/PC/DevPcBios.h
new file mode 100644
index 00000000..d0404c91
--- /dev/null
+++ b/src/VBox/Devices/PC/DevPcBios.h
@@ -0,0 +1,52 @@
+/* $Id: DevPcBios.h $ */
+/** @file
+ * DevPcBios - PC BIOS Device, header shared with the BIOS code.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_INCLUDED_SRC_PC_DevPcBios_h
+#define VBOX_INCLUDED_SRC_PC_DevPcBios_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/** @def VBOX_DMI_TABLE_BASE */
+#define VBOX_DMI_TABLE_BASE 0xe1000
+#define VBOX_DMI_TABLE_VER 0x25
+
+/** def VBOX_DMI_TABLE_SIZE
+ *
+ * The size should be at least 16-byte aligned for a proper alignment of
+ * the MPS table.
+ */
+#define VBOX_DMI_TABLE_SIZE 768
+
+/** def VBOX_DMI_TABLE_SIZE
+ *
+ * The size should be at least 16-byte aligned for a proper alignment of
+ * the MPS table.
+ */
+#define VBOX_DMI_HDR_SIZE 32
+
+/** @def VBOX_LANBOOT_SEG
+ *
+ * Should usually start right after the DMI BIOS page
+ */
+#define VBOX_LANBOOT_SEG 0xe200
+
+#define VBOX_SMBIOS_MAJOR_VER 2
+#define VBOX_SMBIOS_MINOR_VER 5
+#define VBOX_SMBIOS_MAXSS 0xff /* Not very accurate */
+
+#endif /* !VBOX_INCLUDED_SRC_PC_DevPcBios_h */
diff --git a/src/VBox/Devices/PC/DevPit-i8254.cpp b/src/VBox/Devices/PC/DevPit-i8254.cpp
new file mode 100644
index 00000000..e9635458
--- /dev/null
+++ b/src/VBox/Devices/PC/DevPit-i8254.cpp
@@ -0,0 +1,1581 @@
+/* $Id: DevPit-i8254.cpp $ */
+/** @file
+ * DevPIT-i8254 - Intel 8254 Programmable Interval Timer (PIT) And Dummy Speaker Device.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * QEMU 8253/8254 interval timer emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_PIT
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/log.h>
+#include <VBox/vmm/stam.h>
+#include <iprt/assert.h>
+#include <iprt/asm-math.h>
+
+#ifdef IN_RING3
+# ifdef RT_OS_LINUX
+# include <fcntl.h>
+# include <errno.h>
+# include <unistd.h>
+# include <stdio.h>
+# include <linux/kd.h>
+# include <linux/input.h>
+# include <sys/ioctl.h>
+# endif
+# include <iprt/alloc.h>
+# include <iprt/string.h>
+# include <iprt/uuid.h>
+#endif /* IN_RING3 */
+
+#include "VBoxDD.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+/** The PIT frequency. */
+#define PIT_FREQ 1193182
+
+#define RW_STATE_LSB 1
+#define RW_STATE_MSB 2
+#define RW_STATE_WORD0 3
+#define RW_STATE_WORD1 4
+
+/** The current saved state version. */
+#define PIT_SAVED_STATE_VERSION 4
+/** The saved state version used by VirtualBox 3.1 and earlier.
+ * This did not include disable by HPET flag. */
+#define PIT_SAVED_STATE_VERSION_VBOX_31 3
+/** The saved state version used by VirtualBox 3.0 and earlier.
+ * This did not include the config part. */
+#define PIT_SAVED_STATE_VERSION_VBOX_30 2
+
+/** @def FAKE_REFRESH_CLOCK
+ * Define this to flip the 15usec refresh bit on every read.
+ * If not defined, it will be flipped correctly. */
+/* #define FAKE_REFRESH_CLOCK */
+#ifdef DOXYGEN_RUNNING
+# define FAKE_REFRESH_CLOCK
+#endif
+
+/** The effective counter mode - if bit 1 is set, bit 2 is ignored. */
+#define EFFECTIVE_MODE(x) ((x) & ~(((x) & 2) << 1))
+
+
+/**
+ * Acquires the PIT lock or returns.
+ */
+#define DEVPIT_LOCK_RETURN(a_pThis, a_rcBusy) \
+ do { \
+ int rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, (a_rcBusy)); \
+ if (rcLock != VINF_SUCCESS) \
+ return rcLock; \
+ } while (0)
+
+/**
+ * Releases the PIT lock.
+ */
+#define DEVPIT_UNLOCK(a_pThis) \
+ do { PDMCritSectLeave(&(a_pThis)->CritSect); } while (0)
+
+
+/**
+ * Acquires the TM lock and PIT lock, returns on failure.
+ */
+#define DEVPIT_LOCK_BOTH_RETURN(a_pThis, a_rcBusy) \
+ do { \
+ int rcLock = TMTimerLock((a_pThis)->channels[0].CTX_SUFF(pTimer), (a_rcBusy)); \
+ if (rcLock != VINF_SUCCESS) \
+ return rcLock; \
+ rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, (a_rcBusy)); \
+ if (rcLock != VINF_SUCCESS) \
+ { \
+ TMTimerUnlock((a_pThis)->channels[0].CTX_SUFF(pTimer)); \
+ return rcLock; \
+ } \
+ } while (0)
+
+#ifdef IN_RING3
+/**
+ * Acquires the TM lock and PIT lock, ignores failures.
+ */
+# define DEVPIT_R3_LOCK_BOTH(a_pThis) \
+ do { \
+ TMTimerLock((a_pThis)->channels[0].CTX_SUFF(pTimer), VERR_IGNORED); \
+ PDMCritSectEnter(&(a_pThis)->CritSect, VERR_IGNORED); \
+ } while (0)
+#endif /* IN_RING3 */
+
+/**
+ * Releases the PIT lock and TM lock.
+ */
+#define DEVPIT_UNLOCK_BOTH(a_pThis) \
+ do { \
+ PDMCritSectLeave(&(a_pThis)->CritSect); \
+ TMTimerUnlock((a_pThis)->channels[0].CTX_SUFF(pTimer)); \
+ } while (0)
+
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * The state of one PIT channel.
+ */
+typedef struct PITCHANNEL
+{
+ /** Pointer to the instance data - R3 Ptr. */
+ R3PTRTYPE(struct PITSTATE *) pPitR3;
+ /** The timer - R3 Ptr.
+ * @note Only channel 0 has a timer. */
+ PTMTIMERR3 pTimerR3;
+ /** Pointer to the instance data - R0 Ptr. */
+ R0PTRTYPE(struct PITSTATE *) pPitR0;
+ /** The timer - R0 Ptr.
+ * @note Only channel 0 has a timer. */
+ PTMTIMERR0 pTimerR0;
+ /** Pointer to the instance data - RC Ptr. */
+ RCPTRTYPE(struct PITSTATE *) pPitRC;
+ /** The timer - RC Ptr.
+ * @note Only channel 0 has a timer. */
+ PTMTIMERRC pTimerRC;
+ /** The virtual time stamp at the last reload. (only used in mode 2 for now) */
+ uint64_t u64ReloadTS;
+ /** The actual time of the next tick.
+ * As apposed to the next_transition_time which contains the correct time of the next tick. */
+ uint64_t u64NextTS;
+
+ /** (count_load_time is only set by TMTimerGet() which returns uint64_t) */
+ uint64_t count_load_time;
+ /* irq handling */
+ int64_t next_transition_time;
+ int32_t irq;
+ /** Number of release log entries. Used to prevent flooding. */
+ uint32_t cRelLogEntries;
+
+ uint32_t count; /* can be 65536 */
+ uint16_t latched_count;
+ uint8_t count_latched;
+ uint8_t status_latched;
+
+ uint8_t status;
+ uint8_t read_state;
+ uint8_t write_state;
+ uint8_t write_latch;
+
+ uint8_t rw_mode;
+ uint8_t mode;
+ uint8_t bcd; /* not supported */
+ uint8_t gate; /* timer start */
+
+} PITCHANNEL;
+/** Pointer to the state of one PIT channel. */
+typedef PITCHANNEL *PPITCHANNEL;
+
+/** Speaker emulation state. */
+typedef enum PITSPEAKEREMU
+{
+ PIT_SPEAKER_EMU_NONE = 0,
+ PIT_SPEAKER_EMU_CONSOLE,
+ PIT_SPEAKER_EMU_EVDEV,
+ PIT_SPEAKER_EMU_TTY
+} PITSPEAKEREMU;
+
+/**
+ * The whole PIT state.
+ */
+typedef struct PITSTATE
+{
+ /** Channel state. Must come first? */
+ PITCHANNEL channels[3];
+ /** Speaker data. */
+ int32_t speaker_data_on;
+#ifdef FAKE_REFRESH_CLOCK
+ /** Refresh dummy. */
+ int32_t dummy_refresh_clock;
+#else
+ uint32_t Alignment1;
+#endif
+ /** Config: I/O port base. */
+ RTIOPORT IOPortBaseCfg;
+ /** Config: Speaker enabled. */
+ bool fSpeakerCfg;
+ /** Disconnect PIT from the interrupt controllers if requested by HPET. */
+ bool fDisabledByHpet;
+ /** Config: What to do with speaker activity. */
+ PITSPEAKEREMU enmSpeakerEmu;
+#ifdef RT_OS_LINUX
+ /** File handle for host speaker functionality. */
+ int hHostSpeaker;
+ int afAlignment2;
+#endif
+ /** PIT port interface. */
+ PDMIHPETLEGACYNOTIFY IHpetLegacyNotify;
+ /** Pointer to the device instance. */
+ PPDMDEVINSR3 pDevIns;
+ /** Number of IRQs that's been raised. */
+ STAMCOUNTER StatPITIrq;
+ /** Profiling the timer callback handler. */
+ STAMPROFILEADV StatPITHandler;
+ /** Critical section protecting the state. */
+ PDMCRITSECT CritSect;
+} PITSTATE;
+/** Pointer to the PIT device state. */
+typedef PITSTATE *PPITSTATE;
+
+
+#ifndef VBOX_DEVICE_STRUCT_TESTCASE
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+#ifdef IN_RING3
+static void pit_irq_timer_update(PPITCHANNEL pChan, uint64_t current_time, uint64_t now, bool in_timer);
+#endif
+
+
+#ifdef IN_RING3
+# ifdef RT_OS_LINUX
+static int pitTryDeviceOpen(const char *pszPath, int flags)
+{
+ int fd = open(pszPath, flags);
+ if (fd == -1)
+ LogRel(("PIT: speaker: cannot open \"%s\", errno=%d\n", pszPath, errno));
+ else
+ LogRel(("PIT: speaker: opened \"%s\"\n", pszPath));
+ return fd;
+}
+
+static int pitTryDeviceOpenSanitizeIoctl(const char *pszPath, int flags)
+{
+ int fd = open(pszPath, flags);
+ if (fd == -1)
+ LogRel(("PIT: speaker: cannot open \"%s\", errno=%d\n", pszPath, errno));
+ else
+ {
+ int errno_eviocgsnd0 = 0;
+ int errno_kiocsound = 0;
+ if (ioctl(fd, EVIOCGSND(0)) == -1)
+ {
+ errno_eviocgsnd0 = errno;
+ if (ioctl(fd, KIOCSOUND, 1) == -1)
+ errno_kiocsound = errno;
+ else
+ ioctl(fd, KIOCSOUND, 0);
+ }
+ if (errno_eviocgsnd0 && errno_kiocsound)
+ {
+ LogRel(("PIT: speaker: cannot use \"%s\", ioctl failed errno=%d/errno=%d\n", pszPath, errno_eviocgsnd0, errno_kiocsound));
+ close(fd);
+ fd = -1;
+ }
+ else
+ LogRel(("PIT: speaker: opened \"%s\"\n", pszPath));
+ }
+ return fd;
+}
+# endif /* RT_OS_LINUX */
+#endif /* IN_RING3 */
+
+static int pit_get_count(PPITCHANNEL pChan)
+{
+ uint64_t d;
+ PTMTIMER pTimer = pChan->CTX_SUFF(pPit)->channels[0].CTX_SUFF(pTimer);
+ Assert(TMTimerIsLockOwner(pTimer));
+
+ if (EFFECTIVE_MODE(pChan->mode) == 2)
+ {
+ if (pChan->u64NextTS == UINT64_MAX)
+ {
+ d = ASMMultU64ByU32DivByU32(TMTimerGet(pTimer) - pChan->count_load_time, PIT_FREQ, TMTimerGetFreq(pTimer));
+ return pChan->count - (d % pChan->count); /** @todo check this value. */
+ }
+ uint64_t Interval = pChan->u64NextTS - pChan->u64ReloadTS;
+ if (!Interval)
+ return pChan->count - 1; /** @todo This is WRONG! But I'm too tired to fix it properly and just want to shut up a DIV/0 trap now. */
+ d = TMTimerGet(pTimer);
+ d = ASMMultU64ByU32DivByU32(d - pChan->u64ReloadTS, pChan->count, Interval);
+ if (d >= pChan->count)
+ return 1;
+ return pChan->count - d;
+ }
+
+ d = ASMMultU64ByU32DivByU32(TMTimerGet(pTimer) - pChan->count_load_time, PIT_FREQ, TMTimerGetFreq(pTimer));
+ int counter;
+ switch (EFFECTIVE_MODE(pChan->mode))
+ {
+ case 0:
+ case 1:
+ case 4:
+ case 5:
+ counter = (pChan->count - d) & 0xffff;
+ break;
+ case 3:
+ /* XXX: may be incorrect for odd counts */
+ counter = pChan->count - ((2 * d) % pChan->count);
+ break;
+ default:
+ counter = pChan->count - (d % pChan->count);
+ break;
+ }
+ /** @todo check that we don't return 0, in most modes (all?) the counter shouldn't be zero. */
+ return counter;
+}
+
+/* get pit output bit */
+static int pit_get_out1(PPITCHANNEL pChan, int64_t current_time)
+{
+ PTMTIMER pTimer = pChan->CTX_SUFF(pPit)->channels[0].CTX_SUFF(pTimer);
+ uint64_t d;
+ int out;
+
+ d = ASMMultU64ByU32DivByU32(current_time - pChan->count_load_time, PIT_FREQ, TMTimerGetFreq(pTimer));
+ switch (EFFECTIVE_MODE(pChan->mode))
+ {
+ default:
+ case 0:
+ out = (d >= pChan->count);
+ break;
+ case 1:
+ out = (d < pChan->count);
+ break;
+ case 2:
+ Log2(("pit_get_out1: d=%llx c=%x %x \n", d, pChan->count, (unsigned)(d % pChan->count)));
+ if ((d % pChan->count) == 0 && d != 0)
+ out = 1;
+ else
+ out = 0;
+ break;
+ case 3:
+ out = (d % pChan->count) < ((pChan->count + 1) >> 1);
+ break;
+ case 4:
+ case 5:
+ out = (d != pChan->count);
+ break;
+ }
+ return out;
+}
+
+
+static int pit_get_out(PPITSTATE pThis, int channel, int64_t current_time)
+{
+ PPITCHANNEL pChan = &pThis->channels[channel];
+ return pit_get_out1(pChan, current_time);
+}
+
+
+static int pit_get_gate(PPITSTATE pThis, int channel)
+{
+ PPITCHANNEL pChan = &pThis->channels[channel];
+ return pChan->gate;
+}
+
+
+/* if already latched, do not latch again */
+static void pit_latch_count(PPITCHANNEL pChan)
+{
+ if (!pChan->count_latched)
+ {
+ pChan->latched_count = pit_get_count(pChan);
+ pChan->count_latched = pChan->rw_mode;
+ LogFlow(("pit_latch_count: latched_count=%#06x / %10RU64 ns (c=%#06x m=%d)\n",
+ pChan->latched_count, ASMMultU64ByU32DivByU32(pChan->count - pChan->latched_count, 1000000000, PIT_FREQ),
+ pChan->count, pChan->mode));
+ }
+}
+
+#ifdef IN_RING3
+
+/* val must be 0 or 1 */
+static void pit_set_gate(PPITSTATE pThis, int channel, int val)
+{
+ PPITCHANNEL pChan = &pThis->channels[channel];
+ PTMTIMER pTimer = pChan->CTX_SUFF(pPit)->channels[0].CTX_SUFF(pTimer);
+
+ Assert((val & 1) == val);
+ Assert(TMTimerIsLockOwner(pTimer));
+
+ switch (EFFECTIVE_MODE(pChan->mode))
+ {
+ default:
+ case 0:
+ case 4:
+ /* XXX: just disable/enable counting */
+ break;
+ case 1:
+ case 5:
+ if (pChan->gate < val)
+ {
+ /* restart counting on rising edge */
+ Log(("pit_set_gate: restarting mode %d\n", pChan->mode));
+ pChan->count_load_time = TMTimerGet(pTimer);
+ pit_irq_timer_update(pChan, pChan->count_load_time, pChan->count_load_time, false);
+ }
+ break;
+ case 2:
+ case 3:
+ if (pChan->gate < val)
+ {
+ /* restart counting on rising edge */
+ Log(("pit_set_gate: restarting mode %d\n", pChan->mode));
+ pChan->count_load_time = pChan->u64ReloadTS = TMTimerGet(pTimer);
+ pit_irq_timer_update(pChan, pChan->count_load_time, pChan->count_load_time, false);
+ }
+ /* XXX: disable/enable counting */
+ break;
+ }
+ pChan->gate = val;
+}
+
+static void pit_load_count(PPITCHANNEL pChan, int val)
+{
+ PTMTIMER pTimer = pChan->CTX_SUFF(pPit)->channels[0].CTX_SUFF(pTimer);
+ Assert(TMTimerIsLockOwner(pTimer));
+
+ if (val == 0)
+ val = 0x10000;
+ pChan->count_load_time = pChan->u64ReloadTS = TMTimerGet(pTimer);
+ pChan->count = val;
+ pit_irq_timer_update(pChan, pChan->count_load_time, pChan->count_load_time, false);
+
+ /* log the new rate (ch 0 only). */
+ if (pChan->pTimerR3 /* ch 0 */)
+ {
+ if (pChan->cRelLogEntries++ < 32)
+ LogRel(("PIT: mode=%d count=%#x (%u) - %d.%02d Hz (ch=0)\n",
+ pChan->mode, pChan->count, pChan->count, PIT_FREQ / pChan->count, (PIT_FREQ * 100 / pChan->count) % 100));
+ else
+ Log(("PIT: mode=%d count=%#x (%u) - %d.%02d Hz (ch=0)\n",
+ pChan->mode, pChan->count, pChan->count, PIT_FREQ / pChan->count, (PIT_FREQ * 100 / pChan->count) % 100));
+ TMTimerSetFrequencyHint(pChan->CTX_SUFF(pTimer), PIT_FREQ / pChan->count);
+ }
+ else
+ Log(("PIT: mode=%d count=%#x (%u) - %d.%02d Hz (ch=%d)\n",
+ pChan->mode, pChan->count, pChan->count, PIT_FREQ / pChan->count, (PIT_FREQ * 100 / pChan->count) % 100,
+ pChan - &pChan->CTX_SUFF(pPit)->channels[0]));
+}
+
+/* return -1 if no transition will occur. */
+static int64_t pit_get_next_transition_time(PPITCHANNEL pChan, uint64_t current_time)
+{
+ PTMTIMER pTimer = pChan->CTX_SUFF(pPit)->channels[0].CTX_SUFF(pTimer);
+ uint64_t d, next_time, base;
+ uint32_t period2;
+
+ d = ASMMultU64ByU32DivByU32(current_time - pChan->count_load_time, PIT_FREQ, TMTimerGetFreq(pTimer));
+ switch(EFFECTIVE_MODE(pChan->mode))
+ {
+ default:
+ case 0:
+ case 1:
+ if (d < pChan->count)
+ next_time = pChan->count;
+ else
+ return -1;
+ break;
+
+ /*
+ * Mode 2: The period is 'count' PIT ticks.
+ * When the counter reaches 1 we set the output low (for channel 0 that
+ * means lowering IRQ0). On the next tick, where we should be decrementing
+ * from 1 to 0, the count is loaded and the output goes high (channel 0
+ * means raising IRQ0 again and triggering timer interrupt).
+ *
+ * In VirtualBox we compress the pulse and flip-flop the IRQ line at the
+ * end of the period, which signals an interrupt at the exact same time.
+ */
+ case 2:
+ base = (d / pChan->count) * pChan->count;
+#ifndef VBOX /* see above */
+ if ((d - base) == 0 && d != 0)
+ next_time = base + pChan->count - 1;
+ else
+#endif
+ next_time = base + pChan->count;
+ break;
+ case 3:
+ base = (d / pChan->count) * pChan->count;
+ period2 = ((pChan->count + 1) >> 1);
+ if ((d - base) < period2)
+ next_time = base + period2;
+ else
+ next_time = base + pChan->count;
+ break;
+
+ /* Modes 4 and 5 generate a short pulse at the end of the time delay. This
+ * is similar to mode 2, except modes 4/5 aren't periodic. We use the same
+ * optimization - only use one timer callback and pulse the IRQ.
+ * Note: Tickless Linux kernels use PIT mode 4 with 'nolapic'.
+ */
+ case 4:
+ case 5:
+#ifdef VBOX
+ if (d <= pChan->count)
+ next_time = pChan->count;
+#else
+ if (d < pChan->count)
+ next_time = pChan->count;
+ else if (d == pChan->count)
+ next_time = pChan->count + 1;
+#endif
+ else
+ return -1;
+ break;
+ }
+
+ /* convert to timer units */
+ LogFlow(("PIT: next_time=%'14RU64 %'20RU64 mode=%#x count=%#06x\n", next_time,
+ ASMMultU64ByU32DivByU32(next_time, TMTimerGetFreq(pTimer), PIT_FREQ), pChan->mode, pChan->count));
+ next_time = pChan->count_load_time + ASMMultU64ByU32DivByU32(next_time, TMTimerGetFreq(pTimer), PIT_FREQ);
+
+ /* fix potential rounding problems */
+ if (next_time <= current_time)
+ next_time = current_time;
+
+ /* Add one to next_time; if we don't, integer truncation will cause
+ * the algorithm to think that at the end of each period, it'pChan still
+ * within the first one instead of at the beginning of the next one.
+ */
+ return next_time + 1;
+}
+
+static void pit_irq_timer_update(PPITCHANNEL pChan, uint64_t current_time, uint64_t now, bool in_timer)
+{
+ int64_t expire_time;
+ int irq_level;
+ Assert(TMTimerIsLockOwner(pChan->CTX_SUFF(pPit)->channels[0].CTX_SUFF(pTimer)));
+
+ if (!pChan->CTX_SUFF(pTimer))
+ return;
+ expire_time = pit_get_next_transition_time(pChan, current_time);
+ irq_level = pit_get_out1(pChan, current_time) ? PDM_IRQ_LEVEL_HIGH : PDM_IRQ_LEVEL_LOW;
+
+ /* If PIT is disabled by HPET - simply disconnect ticks from interrupt controllers,
+ * but do not modify other aspects of device operation.
+ */
+ if (!pChan->pPitR3->fDisabledByHpet)
+ {
+ PPDMDEVINS pDevIns = pChan->CTX_SUFF(pPit)->pDevIns;
+
+ switch (EFFECTIVE_MODE(pChan->mode))
+ {
+ case 2:
+ case 4:
+ case 5:
+ /* We just flip-flop the IRQ line to save an extra timer call,
+ * which isn't generally required. However, the pulse is only
+ * generated when running on the timer callback (and thus on
+ * the trailing edge of the output signal pulse).
+ */
+ if (in_timer)
+ {
+ PDMDevHlpISASetIrq(pDevIns, pChan->irq, PDM_IRQ_LEVEL_FLIP_FLOP);
+ break;
+ }
+ RT_FALL_THRU();
+ default:
+ PDMDevHlpISASetIrq(pDevIns, pChan->irq, irq_level);
+ break;
+ }
+ }
+
+ if (irq_level)
+ {
+ pChan->u64ReloadTS = now;
+ STAM_COUNTER_INC(&pChan->CTX_SUFF(pPit)->StatPITIrq);
+ }
+
+ if (expire_time != -1)
+ {
+ Log3(("pit_irq_timer_update: next=%'RU64 now=%'RU64\n", expire_time, now));
+ pChan->u64NextTS = expire_time;
+ TMTimerSet(pChan->CTX_SUFF(pTimer), pChan->u64NextTS);
+ }
+ else
+ {
+ LogFlow(("PIT: m=%d count=%#4x irq_level=%#x stopped\n", pChan->mode, pChan->count, irq_level));
+ TMTimerStop(pChan->CTX_SUFF(pTimer));
+ pChan->u64NextTS = UINT64_MAX;
+ }
+ pChan->next_transition_time = expire_time;
+}
+
+#endif /* IN_RING3 */
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN}
+ */
+PDMBOTHCBDECL(int) pitIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb)
+{
+ Log2(("pitIOPortRead: uPort=%#x cb=%x\n", uPort, cb));
+ NOREF(pvUser);
+ uPort &= 3;
+ if (cb != 1 || uPort == 3)
+ {
+ Log(("pitIOPortRead: uPort=%#x cb=%x *pu32=unused!\n", uPort, cb));
+ return VERR_IOM_IOPORT_UNUSED;
+ }
+ RT_UNTRUSTED_VALIDATED_FENCE(); /* paranoia */
+
+ PPITSTATE pThis = PDMINS_2_DATA(pDevIns, PPITSTATE);
+ PPITCHANNEL pChan = &pThis->channels[uPort];
+ int ret;
+
+ DEVPIT_LOCK_RETURN(pThis, VINF_IOM_R3_IOPORT_READ);
+ if (pChan->status_latched)
+ {
+ pChan->status_latched = 0;
+ ret = pChan->status;
+ DEVPIT_UNLOCK(pThis);
+ }
+ else if (pChan->count_latched)
+ {
+ switch (pChan->count_latched)
+ {
+ default:
+ case RW_STATE_LSB:
+ ret = pChan->latched_count & 0xff;
+ pChan->count_latched = 0;
+ break;
+ case RW_STATE_MSB:
+ ret = pChan->latched_count >> 8;
+ pChan->count_latched = 0;
+ break;
+ case RW_STATE_WORD0:
+ ret = pChan->latched_count & 0xff;
+ pChan->count_latched = RW_STATE_MSB;
+ break;
+ }
+ DEVPIT_UNLOCK(pThis);
+ }
+ else
+ {
+ DEVPIT_UNLOCK(pThis);
+ DEVPIT_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_IOPORT_READ);
+ int count;
+ switch (pChan->read_state)
+ {
+ default:
+ case RW_STATE_LSB:
+ count = pit_get_count(pChan);
+ ret = count & 0xff;
+ break;
+ case RW_STATE_MSB:
+ count = pit_get_count(pChan);
+ ret = (count >> 8) & 0xff;
+ break;
+ case RW_STATE_WORD0:
+ count = pit_get_count(pChan);
+ ret = count & 0xff;
+ pChan->read_state = RW_STATE_WORD1;
+ break;
+ case RW_STATE_WORD1:
+ count = pit_get_count(pChan);
+ ret = (count >> 8) & 0xff;
+ pChan->read_state = RW_STATE_WORD0;
+ break;
+ }
+ DEVPIT_UNLOCK_BOTH(pThis);
+ }
+
+ *pu32 = ret;
+ Log2(("pitIOPortRead: uPort=%#x cb=%x *pu32=%#04x\n", uPort, cb, *pu32));
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT}
+ */
+PDMBOTHCBDECL(int) pitIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb)
+{
+ Log2(("pitIOPortWrite: uPort=%#x cb=%x u32=%#04x\n", uPort, cb, u32));
+ NOREF(pvUser);
+ if (cb != 1)
+ return VINF_SUCCESS;
+
+ PPITSTATE pThis = PDMINS_2_DATA(pDevIns, PPITSTATE);
+ uPort &= 3;
+ if (uPort == 3)
+ {
+ /*
+ * Port 43h - Mode/Command Register.
+ * 7 6 5 4 3 2 1 0
+ * * * . . . . . . Select channel: 0 0 = Channel 0
+ * 0 1 = Channel 1
+ * 1 0 = Channel 2
+ * 1 1 = Read-back command (8254 only)
+ * (Illegal on 8253)
+ * (Illegal on PS/2 {JAM})
+ * . . * * . . . . Command/Access mode: 0 0 = Latch count value command
+ * 0 1 = Access mode: lobyte only
+ * 1 0 = Access mode: hibyte only
+ * 1 1 = Access mode: lobyte/hibyte
+ * . . . . * * * . Operating mode: 0 0 0 = Mode 0, 0 0 1 = Mode 1,
+ * 0 1 0 = Mode 2, 0 1 1 = Mode 3,
+ * 1 0 0 = Mode 4, 1 0 1 = Mode 5,
+ * 1 1 0 = Mode 2, 1 1 1 = Mode 3
+ * . . . . . . . * BCD/Binary mode: 0 = 16-bit binary, 1 = four-digit BCD
+ */
+ unsigned channel = (u32 >> 6) & 0x3;
+ RT_UNTRUSTED_VALIDATED_FENCE(); /* paranoia */
+ if (channel == 3)
+ {
+ /* read-back command */
+ DEVPIT_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_IOPORT_WRITE);
+ for (channel = 0; channel < RT_ELEMENTS(pThis->channels); channel++)
+ {
+ PPITCHANNEL pChan = &pThis->channels[channel];
+ if (u32 & (2 << channel))
+ {
+ if (!(u32 & 0x20))
+ pit_latch_count(pChan);
+ if (!(u32 & 0x10) && !pChan->status_latched)
+ {
+ /* status latch */
+ /* XXX: add BCD and null count */
+ PTMTIMER pTimer = pChan->CTX_SUFF(pPit)->channels[0].CTX_SUFF(pTimer);
+ pChan->status = (pit_get_out1(pChan, TMTimerGet(pTimer)) << 7)
+ | (pChan->rw_mode << 4)
+ | (pChan->mode << 1)
+ | pChan->bcd;
+ pChan->status_latched = 1;
+ }
+ }
+ }
+ DEVPIT_UNLOCK_BOTH(pThis);
+ }
+ else
+ {
+ PPITCHANNEL pChan = &pThis->channels[channel];
+ unsigned access = (u32 >> 4) & 3;
+ if (access == 0)
+ {
+ DEVPIT_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_IOPORT_WRITE);
+ pit_latch_count(pChan);
+ DEVPIT_UNLOCK_BOTH(pThis);
+ }
+ else
+ {
+ DEVPIT_LOCK_RETURN(pThis, VINF_IOM_R3_IOPORT_WRITE);
+ pChan->rw_mode = access;
+ pChan->read_state = access;
+ pChan->write_state = access;
+
+ pChan->mode = (u32 >> 1) & 7;
+ pChan->bcd = u32 & 1;
+ /* XXX: update irq timer ? */
+ DEVPIT_UNLOCK(pThis);
+ }
+ }
+ }
+ else
+ {
+#ifndef IN_RING3
+ /** @todo There is no reason not to do this in all contexts these
+ * days... */
+ return VINF_IOM_R3_IOPORT_WRITE;
+#else /* IN_RING3 */
+ /*
+ * Port 40-42h - Channel Data Ports.
+ */
+ RT_UNTRUSTED_VALIDATED_FENCE(); /* paranoia */
+ PPITCHANNEL pChan = &pThis->channels[uPort];
+ DEVPIT_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_IOPORT_WRITE);
+ switch (pChan->write_state)
+ {
+ default:
+ case RW_STATE_LSB:
+ pit_load_count(pChan, u32);
+ break;
+ case RW_STATE_MSB:
+ pit_load_count(pChan, u32 << 8);
+ break;
+ case RW_STATE_WORD0:
+ pChan->write_latch = u32;
+ pChan->write_state = RW_STATE_WORD1;
+ break;
+ case RW_STATE_WORD1:
+ pit_load_count(pChan, pChan->write_latch | (u32 << 8));
+ pChan->write_state = RW_STATE_WORD0;
+ break;
+ }
+ DEVPIT_UNLOCK_BOTH(pThis);
+#endif /* !IN_RING3 */
+ }
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, Speaker}
+ */
+PDMBOTHCBDECL(int) pitIOPortSpeakerRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb)
+{
+ RT_NOREF2(pvUser, uPort);
+ if (cb == 1)
+ {
+ PPITSTATE pThis = PDMINS_2_DATA(pDevIns, PPITSTATE);
+ DEVPIT_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_IOPORT_READ);
+
+ const uint64_t u64Now = TMTimerGet(pThis->channels[0].CTX_SUFF(pTimer));
+ Assert(TMTimerGetFreq(pThis->channels[0].CTX_SUFF(pTimer)) == 1000000000); /* lazy bird. */
+
+ /* bit 6,7 Parity error stuff. */
+ /* bit 5 - mirrors timer 2 output condition. */
+ const int fOut = pit_get_out(pThis, 2, u64Now);
+ /* bit 4 - toggled with each (DRAM?) refresh request, every 15.085 u-op Chan.
+ ASSUMES ns timer freq, see assertion above. */
+#ifndef FAKE_REFRESH_CLOCK
+ const int fRefresh = (u64Now / 15085) & 1;
+#else
+ pThis->dummy_refresh_clock ^= 1;
+ const int fRefresh = pThis->dummy_refresh_clock;
+#endif
+ /* bit 2,3 NMI / parity status stuff. */
+ /* bit 1 - speaker data status */
+ const int fSpeakerStatus = pThis->speaker_data_on;
+ /* bit 0 - timer 2 clock gate to speaker status. */
+ const int fTimer2GateStatus = pit_get_gate(pThis, 2);
+
+ DEVPIT_UNLOCK_BOTH(pThis);
+
+ *pu32 = fTimer2GateStatus
+ | (fSpeakerStatus << 1)
+ | (fRefresh << 4)
+ | (fOut << 5);
+ Log(("pitIOPortSpeakerRead: uPort=%#x cb=%x *pu32=%#x\n", uPort, cb, *pu32));
+ return VINF_SUCCESS;
+ }
+ Log(("pitIOPortSpeakerRead: uPort=%#x cb=%x *pu32=unused!\n", uPort, cb));
+ return VERR_IOM_IOPORT_UNUSED;
+}
+
+#ifdef IN_RING3
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, Speaker}
+ */
+PDMBOTHCBDECL(int) pitIOPortSpeakerWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb)
+{
+ RT_NOREF2(pvUser, uPort);
+ if (cb == 1)
+ {
+ PPITSTATE pThis = PDMINS_2_DATA(pDevIns, PPITSTATE);
+ DEVPIT_LOCK_BOTH_RETURN(pThis, VERR_IGNORED);
+
+ pThis->speaker_data_on = (u32 >> 1) & 1;
+ pit_set_gate(pThis, 2, u32 & 1);
+
+ /** @todo r=klaus move this to a (system-specific) driver, which can
+ * abstract the details, and if necessary create a thread to minimize
+ * impact on VM execution. */
+#ifdef RT_OS_LINUX
+ if (pThis->enmSpeakerEmu != PIT_SPEAKER_EMU_NONE)
+ {
+ PPITCHANNEL pChan = &pThis->channels[2];
+ if (pThis->speaker_data_on)
+ {
+ Log2Func(("starting beep freq=%d\n", PIT_FREQ / pChan->count));
+ switch (pThis->enmSpeakerEmu)
+ {
+ case PIT_SPEAKER_EMU_CONSOLE:
+ {
+ int res;
+ res = ioctl(pThis->hHostSpeaker, KIOCSOUND, pChan->count);
+ if (res == -1)
+ {
+ LogRel(("PIT: speaker: ioctl failed errno=%d, disabling emulation\n", errno));
+ pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
+ }
+ break;
+ }
+ case PIT_SPEAKER_EMU_EVDEV:
+ {
+ struct input_event e;
+ e.type = EV_SND;
+ e.code = SND_TONE;
+ e.value = PIT_FREQ / pChan->count;
+ int res = write(pThis->hHostSpeaker, &e, sizeof(struct input_event));
+ NOREF(res);
+ break;
+ }
+ case PIT_SPEAKER_EMU_TTY:
+ {
+ int res = write(pThis->hHostSpeaker, "\a", 1);
+ NOREF(res);
+ break;
+ }
+ case PIT_SPEAKER_EMU_NONE:
+ break;
+ default:
+ Log2Func(("unknown speaker emulation %d, disabling emulation\n", pThis->enmSpeakerEmu));
+ pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
+ }
+ }
+ else
+ {
+ Log2Func(("stopping beep\n"));
+ switch (pThis->enmSpeakerEmu)
+ {
+ case PIT_SPEAKER_EMU_CONSOLE:
+ /* No error checking here. The Linux device driver
+ * implementation considers it an error (errno=22,
+ * EINVAL) to stop sound if it hasn't been started.
+ * Of course we could detect this by checking only
+ * for enabled->disabled transitions and ignoring
+ * disabled->disabled ones, but it's not worth the
+ * effort. */
+ ioctl(pThis->hHostSpeaker, KIOCSOUND, 0);
+ break;
+ case PIT_SPEAKER_EMU_EVDEV:
+ {
+ struct input_event e;
+ e.type = EV_SND;
+ e.code = SND_TONE;
+ e.value = 0;
+ int res = write(pThis->hHostSpeaker, &e, sizeof(struct input_event));
+ NOREF(res);
+ break;
+ }
+ case PIT_SPEAKER_EMU_TTY:
+ break;
+ case PIT_SPEAKER_EMU_NONE:
+ break;
+ default:
+ Log2Func(("unknown speaker emulation %d, disabling emulation\n", pThis->enmSpeakerEmu));
+ pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
+ }
+ }
+ }
+#endif
+
+ DEVPIT_UNLOCK_BOTH(pThis);
+ }
+ Log(("pitIOPortSpeakerWrite: uPort=%#x cb=%x u32=%#x\n", uPort, cb, u32));
+ return VINF_SUCCESS;
+}
+
+
+/* -=-=-=-=-=- Saved state -=-=-=-=-=- */
+
+/**
+ * @callback_method_impl{FNSSMDEVLIVEEXEC}
+ */
+static DECLCALLBACK(int) pitLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
+{
+ RT_NOREF1(uPass);
+ PPITSTATE pThis = PDMINS_2_DATA(pDevIns, PPITSTATE);
+ SSMR3PutIOPort(pSSM, pThis->IOPortBaseCfg);
+ SSMR3PutU8( pSSM, pThis->channels[0].irq);
+ SSMR3PutBool( pSSM, pThis->fSpeakerCfg);
+ return VINF_SSM_DONT_CALL_AGAIN;
+}
+
+
+/**
+ * @callback_method_impl{FNSSMDEVSAVEEXEC}
+ */
+static DECLCALLBACK(int) pitSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+ PPITSTATE pThis = PDMINS_2_DATA(pDevIns, PPITSTATE);
+ PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
+
+ /* The config. */
+ pitLiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
+
+ /* The state. */
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->channels); i++)
+ {
+ PPITCHANNEL pChan = &pThis->channels[i];
+ SSMR3PutU32(pSSM, pChan->count);
+ SSMR3PutU16(pSSM, pChan->latched_count);
+ SSMR3PutU8(pSSM, pChan->count_latched);
+ SSMR3PutU8(pSSM, pChan->status_latched);
+ SSMR3PutU8(pSSM, pChan->status);
+ SSMR3PutU8(pSSM, pChan->read_state);
+ SSMR3PutU8(pSSM, pChan->write_state);
+ SSMR3PutU8(pSSM, pChan->write_latch);
+ SSMR3PutU8(pSSM, pChan->rw_mode);
+ SSMR3PutU8(pSSM, pChan->mode);
+ SSMR3PutU8(pSSM, pChan->bcd);
+ SSMR3PutU8(pSSM, pChan->gate);
+ SSMR3PutU64(pSSM, pChan->count_load_time);
+ SSMR3PutU64(pSSM, pChan->u64NextTS);
+ SSMR3PutU64(pSSM, pChan->u64ReloadTS);
+ SSMR3PutS64(pSSM, pChan->next_transition_time);
+ if (pChan->CTX_SUFF(pTimer))
+ TMR3TimerSave(pChan->CTX_SUFF(pTimer), pSSM);
+ }
+
+ SSMR3PutS32(pSSM, pThis->speaker_data_on);
+#ifdef FAKE_REFRESH_CLOCK
+ SSMR3PutS32(pSSM, pThis->dummy_refresh_clock);
+#else
+ SSMR3PutS32(pSSM, 0);
+#endif
+
+ SSMR3PutBool(pSSM, pThis->fDisabledByHpet);
+
+ PDMCritSectLeave(&pThis->CritSect);
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNSSMDEVLOADEXEC}
+ */
+static DECLCALLBACK(int) pitLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+{
+ PPITSTATE pThis = PDMINS_2_DATA(pDevIns, PPITSTATE);
+ int rc;
+
+ if ( uVersion != PIT_SAVED_STATE_VERSION
+ && uVersion != PIT_SAVED_STATE_VERSION_VBOX_30
+ && uVersion != PIT_SAVED_STATE_VERSION_VBOX_31)
+ return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
+
+ /* The config. */
+ if (uVersion > PIT_SAVED_STATE_VERSION_VBOX_30)
+ {
+ RTIOPORT IOPortBaseCfg;
+ rc = SSMR3GetIOPort(pSSM, &IOPortBaseCfg); AssertRCReturn(rc, rc);
+ if (IOPortBaseCfg != pThis->IOPortBaseCfg)
+ return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - IOPortBaseCfg: saved=%RTiop config=%RTiop"),
+ IOPortBaseCfg, pThis->IOPortBaseCfg);
+
+ uint8_t u8Irq;
+ rc = SSMR3GetU8(pSSM, &u8Irq); AssertRCReturn(rc, rc);
+ if (u8Irq != pThis->channels[0].irq)
+ return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - u8Irq: saved=%#x config=%#x"),
+ u8Irq, pThis->channels[0].irq);
+
+ bool fSpeakerCfg;
+ rc = SSMR3GetBool(pSSM, &fSpeakerCfg); AssertRCReturn(rc, rc);
+ if (fSpeakerCfg != pThis->fSpeakerCfg)
+ return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - fSpeakerCfg: saved=%RTbool config=%RTbool"),
+ fSpeakerCfg, pThis->fSpeakerCfg);
+ }
+
+ if (uPass != SSM_PASS_FINAL)
+ return VINF_SUCCESS;
+
+ /* The state. */
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->channels); i++)
+ {
+ PPITCHANNEL pChan = &pThis->channels[i];
+ SSMR3GetU32(pSSM, &pChan->count);
+ SSMR3GetU16(pSSM, &pChan->latched_count);
+ SSMR3GetU8(pSSM, &pChan->count_latched);
+ SSMR3GetU8(pSSM, &pChan->status_latched);
+ SSMR3GetU8(pSSM, &pChan->status);
+ SSMR3GetU8(pSSM, &pChan->read_state);
+ SSMR3GetU8(pSSM, &pChan->write_state);
+ SSMR3GetU8(pSSM, &pChan->write_latch);
+ SSMR3GetU8(pSSM, &pChan->rw_mode);
+ SSMR3GetU8(pSSM, &pChan->mode);
+ SSMR3GetU8(pSSM, &pChan->bcd);
+ SSMR3GetU8(pSSM, &pChan->gate);
+ SSMR3GetU64(pSSM, &pChan->count_load_time);
+ SSMR3GetU64(pSSM, &pChan->u64NextTS);
+ SSMR3GetU64(pSSM, &pChan->u64ReloadTS);
+ SSMR3GetS64(pSSM, &pChan->next_transition_time);
+ if (pChan->CTX_SUFF(pTimer))
+ {
+ TMR3TimerLoad(pChan->CTX_SUFF(pTimer), pSSM);
+ LogRel(("PIT: mode=%d count=%#x (%u) - %d.%02d Hz (ch=%d) (restore)\n",
+ pChan->mode, pChan->count, pChan->count, PIT_FREQ / pChan->count, (PIT_FREQ * 100 / pChan->count) % 100, i));
+ PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
+ TMTimerSetFrequencyHint(pChan->CTX_SUFF(pTimer), PIT_FREQ / pChan->count);
+ PDMCritSectLeave(&pThis->CritSect);
+ }
+ pThis->channels[i].cRelLogEntries = 0;
+ }
+
+ SSMR3GetS32(pSSM, &pThis->speaker_data_on);
+#ifdef FAKE_REFRESH_CLOCK
+ SSMR3GetS32(pSSM, &pThis->dummy_refresh_clock);
+#else
+ int32_t u32Dummy;
+ SSMR3GetS32(pSSM, &u32Dummy);
+#endif
+ if (uVersion > PIT_SAVED_STATE_VERSION_VBOX_31)
+ SSMR3GetBool(pSSM, &pThis->fDisabledByHpet);
+
+ return VINF_SUCCESS;
+}
+
+
+/* -=-=-=-=-=- Timer -=-=-=-=-=- */
+
+/**
+ * @callback_method_impl{FNTMTIMERDEV}
+ * @param pvUser Pointer to the PIT channel state.
+ */
+static DECLCALLBACK(void) pitTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+ RT_NOREF1(pDevIns);
+ PPITCHANNEL pChan = (PPITCHANNEL)pvUser;
+ STAM_PROFILE_ADV_START(&pChan->CTX_SUFF(pPit)->StatPITHandler, a);
+
+ Log(("pitTimer\n"));
+ Assert(PDMCritSectIsOwner(&PDMINS_2_DATA(pDevIns, PPITSTATE)->CritSect));
+ Assert(TMTimerIsLockOwner(pTimer));
+
+ pit_irq_timer_update(pChan, pChan->next_transition_time, TMTimerGet(pTimer), true);
+
+ STAM_PROFILE_ADV_STOP(&pChan->CTX_SUFF(pPit)->StatPITHandler, a);
+}
+
+
+/* -=-=-=-=-=- Debug Info -=-=-=-=-=- */
+
+/**
+ * @callback_method_impl{FNDBGFHANDLERDEV}
+ */
+static DECLCALLBACK(void) pitInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+ RT_NOREF1(pszArgs);
+ PPITSTATE pThis = PDMINS_2_DATA(pDevIns, PPITSTATE);
+ unsigned i;
+ for (i = 0; i < RT_ELEMENTS(pThis->channels); i++)
+ {
+ const PITCHANNEL *pChan = &pThis->channels[i];
+
+ pHlp->pfnPrintf(pHlp,
+ "PIT (i8254) channel %d status: irq=%#x\n"
+ " count=%08x" " latched_count=%04x count_latched=%02x\n"
+ " status=%02x status_latched=%02x read_state=%02x\n"
+ " write_state=%02x write_latch=%02x rw_mode=%02x\n"
+ " mode=%02x bcd=%02x gate=%02x\n"
+ " count_load_time=%016RX64 next_transition_time=%016RX64\n"
+ " u64ReloadTS=%016RX64 u64NextTS=%016RX64\n"
+ ,
+ i, pChan->irq,
+ pChan->count, pChan->latched_count, pChan->count_latched,
+ pChan->status, pChan->status_latched, pChan->read_state,
+ pChan->write_state, pChan->write_latch, pChan->rw_mode,
+ pChan->mode, pChan->bcd, pChan->gate,
+ pChan->count_load_time, pChan->next_transition_time,
+ pChan->u64ReloadTS, pChan->u64NextTS);
+ }
+#ifdef FAKE_REFRESH_CLOCK
+ pHlp->pfnPrintf(pHlp, "speaker_data_on=%#x dummy_refresh_clock=%#x\n",
+ pThis->speaker_data_on, pThis->dummy_refresh_clock);
+#else
+ pHlp->pfnPrintf(pHlp, "speaker_data_on=%#x\n", pThis->speaker_data_on);
+#endif
+ if (pThis->fDisabledByHpet)
+ pHlp->pfnPrintf(pHlp, "Disabled by HPET\n");
+}
+
+
+/* -=-=-=-=-=- IHpetLegacyNotify -=-=-=-=-=- */
+
+/**
+ * @interface_method_impl{PDMIHPETLEGACYNOTIFY,pfnModeChanged}
+ */
+static DECLCALLBACK(void) pitNotifyHpetLegacyNotify_ModeChanged(PPDMIHPETLEGACYNOTIFY pInterface, bool fActivated)
+{
+ PPITSTATE pThis = RT_FROM_MEMBER(pInterface, PITSTATE, IHpetLegacyNotify);
+ PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
+
+ pThis->fDisabledByHpet = fActivated;
+
+ PDMCritSectLeave(&pThis->CritSect);
+}
+
+
+/* -=-=-=-=-=- PDMDEVINS::IBase -=-=-=-=-=- */
+
+/**
+ * @interface_method_impl{PDMIBASE,pfnQueryInterface}
+ */
+static DECLCALLBACK(void *) pitQueryInterface(PPDMIBASE pInterface, const char *pszIID)
+{
+ PPDMDEVINS pDevIns = RT_FROM_MEMBER(pInterface, PDMDEVINS, IBase);
+ PPITSTATE pThis = PDMINS_2_DATA(pDevIns, PPITSTATE);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDevIns->IBase);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHPETLEGACYNOTIFY, &pThis->IHpetLegacyNotify);
+ return NULL;
+}
+
+
+/* -=-=-=-=-=- PDMDEVREG -=-=-=-=-=- */
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnRelocate}
+ */
+static DECLCALLBACK(void) pitRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
+{
+ RT_NOREF1(offDelta);
+ PPITSTATE pThis = PDMINS_2_DATA(pDevIns, PPITSTATE);
+ LogFlow(("pitRelocate: \n"));
+
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->channels); i++)
+ {
+ PPITCHANNEL pChan = &pThis->channels[i];
+ if (pChan->pTimerR3)
+ pChan->pTimerRC = TMTimerRCPtr(pChan->pTimerR3);
+ pThis->channels[i].pPitRC = PDMINS_2_DATA_RCPTR(pDevIns);
+ }
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnReset}
+ */
+static DECLCALLBACK(void) pitReset(PPDMDEVINS pDevIns)
+{
+ PPITSTATE pThis = PDMINS_2_DATA(pDevIns, PPITSTATE);
+ LogFlow(("pitReset: \n"));
+
+ DEVPIT_R3_LOCK_BOTH(pThis);
+
+ pThis->fDisabledByHpet = false;
+
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->channels); i++)
+ {
+ PPITCHANNEL pChan = &pThis->channels[i];
+
+#if 1 /* Set everything back to virgin state. (might not be strictly correct) */
+ pChan->latched_count = 0;
+ pChan->count_latched = 0;
+ pChan->status_latched = 0;
+ pChan->status = 0;
+ pChan->read_state = 0;
+ pChan->write_state = 0;
+ pChan->write_latch = 0;
+ pChan->rw_mode = 0;
+ pChan->bcd = 0;
+#endif
+ pChan->u64NextTS = UINT64_MAX;
+ pChan->cRelLogEntries = 0;
+ pChan->mode = 3;
+ pChan->gate = (i != 2);
+ pit_load_count(pChan, 0);
+ }
+
+ DEVPIT_UNLOCK_BOTH(pThis);
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnConstruct}
+ */
+static DECLCALLBACK(int) pitConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
+{
+ PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+ PPITSTATE pThis = PDMINS_2_DATA(pDevIns, PPITSTATE);
+ int rc;
+ uint8_t u8Irq;
+ uint16_t u16Base;
+ bool fSpeaker;
+ bool fGCEnabled;
+ bool fR0Enabled;
+ unsigned i;
+ Assert(iInstance == 0);
+
+ /*
+ * Validate configuration.
+ */
+ if (!CFGMR3AreValuesValid(pCfg, "Irq\0" "Base\0"
+ "SpeakerEnabled\0" "PassthroughSpeaker\0" "PassthroughSpeakerDevice\0"
+ "R0Enabled\0" "GCEnabled\0"))
+ return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
+
+ /*
+ * Init the data.
+ */
+ rc = CFGMR3QueryU8Def(pCfg, "Irq", &u8Irq, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"Irq\" as a uint8_t failed"));
+
+ rc = CFGMR3QueryU16Def(pCfg, "Base", &u16Base, 0x40);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"Base\" as a uint16_t failed"));
+
+ rc = CFGMR3QueryBoolDef(pCfg, "SpeakerEnabled", &fSpeaker, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"SpeakerEnabled\" as a bool failed"));
+
+ uint8_t uPassthroughSpeaker;
+ char *pszPassthroughSpeakerDevice = NULL;
+ rc = CFGMR3QueryU8Def(pCfg, "PassthroughSpeaker", &uPassthroughSpeaker, 0);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: failed to read PassthroughSpeaker as uint8_t"));
+ if (uPassthroughSpeaker)
+ {
+ rc = CFGMR3QueryStringAllocDef(pCfg, "PassthroughSpeakerDevice", &pszPassthroughSpeakerDevice, NULL);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: failed to read PassthroughSpeakerDevice as string"));
+ }
+
+ rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"GCEnabled\" as a bool failed"));
+
+ rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: failed to read R0Enabled as boolean"));
+
+ pThis->pDevIns = pDevIns;
+ pThis->IOPortBaseCfg = u16Base;
+ pThis->fSpeakerCfg = fSpeaker;
+ pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
+ if (uPassthroughSpeaker)
+ {
+ /** @todo r=klaus move this to a (system-specific) driver */
+#ifdef RT_OS_LINUX
+ int fd = -1;
+ if ((uPassthroughSpeaker == 1 || uPassthroughSpeaker == 100) && fd == -1)
+ fd = pitTryDeviceOpenSanitizeIoctl("/dev/input/by-path/platform-pcspkr-event-spkr", O_WRONLY);
+ if ((uPassthroughSpeaker == 2 || uPassthroughSpeaker == 100) && fd == -1)
+ fd = pitTryDeviceOpenSanitizeIoctl("/dev/tty", O_WRONLY);
+ if ((uPassthroughSpeaker == 3 || uPassthroughSpeaker == 100) && fd == -1)
+ {
+ fd = pitTryDeviceOpenSanitizeIoctl("/dev/tty0", O_WRONLY);
+ if (fd == -1)
+ fd = pitTryDeviceOpenSanitizeIoctl("/dev/vc/0", O_WRONLY);
+ }
+ if ((uPassthroughSpeaker == 9 || uPassthroughSpeaker == 100) && pszPassthroughSpeakerDevice && fd == -1)
+ fd = pitTryDeviceOpenSanitizeIoctl(pszPassthroughSpeakerDevice, O_WRONLY);
+ if (pThis->enmSpeakerEmu == PIT_SPEAKER_EMU_NONE && fd != -1)
+ {
+ pThis->hHostSpeaker = fd;
+ if (ioctl(fd, EVIOCGSND(0)) != -1)
+ {
+ pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_EVDEV;
+ LogRel(("PIT: speaker: emulation mode evdev\n"));
+ }
+ else
+ {
+ pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_CONSOLE;
+ LogRel(("PIT: speaker: emulation mode console\n"));
+ }
+ }
+ if ((uPassthroughSpeaker == 70 || uPassthroughSpeaker == 100) && fd == -1)
+ fd = pitTryDeviceOpen("/dev/tty", O_WRONLY);
+ if ((uPassthroughSpeaker == 79 || uPassthroughSpeaker == 100) && pszPassthroughSpeakerDevice && fd == -1)
+ fd = pitTryDeviceOpen(pszPassthroughSpeakerDevice, O_WRONLY);
+ if (pThis->enmSpeakerEmu == PIT_SPEAKER_EMU_NONE && fd != -1)
+ {
+ pThis->hHostSpeaker = fd;
+ pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_TTY;
+ LogRel(("PIT: speaker: emulation mode tty\n"));
+ }
+ if (pThis->enmSpeakerEmu == PIT_SPEAKER_EMU_NONE)
+ {
+ Assert(fd == -1);
+ LogRel(("PIT: speaker: no emulation possible\n"));
+ }
+#else
+ LogRel(("PIT: speaker: emulation deactivated\n"));
+#endif
+ if (pszPassthroughSpeakerDevice)
+ {
+ MMR3HeapFree(pszPassthroughSpeakerDevice);
+ pszPassthroughSpeakerDevice = NULL;
+ }
+ }
+ pThis->channels[0].irq = u8Irq;
+ for (i = 0; i < RT_ELEMENTS(pThis->channels); i++)
+ {
+ pThis->channels[i].pPitR3 = pThis;
+ pThis->channels[i].pPitR0 = PDMINS_2_DATA_R0PTR(pDevIns);
+ pThis->channels[i].pPitRC = PDMINS_2_DATA_RCPTR(pDevIns);
+ }
+
+ /*
+ * Interfaces
+ */
+ /* IBase */
+ pDevIns->IBase.pfnQueryInterface = pitQueryInterface;
+ /* IHpetLegacyNotify */
+ pThis->IHpetLegacyNotify.pfnModeChanged = pitNotifyHpetLegacyNotify_ModeChanged;
+
+ /*
+ * We do our own locking. This must be done before creating timers.
+ */
+ rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "pit#%u", iInstance);
+ AssertRCReturn(rc, rc);
+
+ rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
+ AssertRCReturn(rc, rc);
+
+ /*
+ * Create the timer, make it take our critsect.
+ */
+ rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, pitTimer, &pThis->channels[0],
+ TMTIMER_FLAGS_NO_CRIT_SECT, "i8254 Programmable Interval Timer",
+ &pThis->channels[0].pTimerR3);
+ if (RT_FAILURE(rc))
+ return rc;
+ pThis->channels[0].pTimerRC = TMTimerRCPtr(pThis->channels[0].pTimerR3);
+ pThis->channels[0].pTimerR0 = TMTimerR0Ptr(pThis->channels[0].pTimerR3);
+ rc = TMR3TimerSetCritSect(pThis->channels[0].pTimerR3, &pThis->CritSect);
+ AssertRCReturn(rc, rc);
+
+ /*
+ * Register I/O ports.
+ */
+ rc = PDMDevHlpIOPortRegister(pDevIns, u16Base, 4, NULL, pitIOPortWrite, pitIOPortRead, NULL, NULL, "i8254 Programmable Interval Timer");
+ if (RT_FAILURE(rc))
+ return rc;
+ if (fGCEnabled)
+ {
+ rc = PDMDevHlpIOPortRegisterRC(pDevIns, u16Base, 4, 0, "pitIOPortWrite", "pitIOPortRead", NULL, NULL, "i8254 Programmable Interval Timer");
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+ if (fR0Enabled)
+ {
+ rc = PDMDevHlpIOPortRegisterR0(pDevIns, u16Base, 4, 0, "pitIOPortWrite", "pitIOPortRead", NULL, NULL, "i8254 Programmable Interval Timer");
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+
+ if (fSpeaker)
+ {
+ rc = PDMDevHlpIOPortRegister(pDevIns, 0x61, 1, NULL, pitIOPortSpeakerWrite, pitIOPortSpeakerRead, NULL, NULL, "PC Speaker");
+ if (RT_FAILURE(rc))
+ return rc;
+ if (fGCEnabled)
+ {
+ rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x61, 1, 0, NULL, "pitIOPortSpeakerRead", NULL, NULL, "PC Speaker");
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+ }
+
+ /*
+ * Saved state.
+ */
+ rc = PDMDevHlpSSMRegister3(pDevIns, PIT_SAVED_STATE_VERSION, sizeof(*pThis), pitLiveExec, pitSaveExec, pitLoadExec);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * Initialize the device state.
+ */
+ pitReset(pDevIns);
+
+ /*
+ * Register statistics and debug info.
+ */
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatPITIrq, STAMTYPE_COUNTER, "/TM/PIT/Irq", STAMUNIT_OCCURENCES, "The number of times a timer interrupt was triggered.");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatPITHandler, STAMTYPE_PROFILE, "/TM/PIT/Handler", STAMUNIT_TICKS_PER_CALL, "Profiling timer callback handler.");
+
+ PDMDevHlpDBGFInfoRegister(pDevIns, "pit", "Display PIT (i8254) status. (no arguments)", pitInfo);
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * The device registration structure.
+ */
+const PDMDEVREG g_DeviceI8254 =
+{
+ /* u32Version */
+ PDM_DEVREG_VERSION,
+ /* szName */
+ "i8254",
+ /* szRCMod */
+ "VBoxDDRC.rc",
+ /* szR0Mod */
+ "VBoxDDR0.r0",
+ /* pszDescription */
+ "Intel 8254 Programmable Interval Timer (PIT) And Dummy Speaker Device",
+ /* fFlags */
+ PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36 | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
+ /* fClass */
+ PDM_DEVREG_CLASS_PIT,
+ /* cMaxInstances */
+ 1,
+ /* cbInstance */
+ sizeof(PITSTATE),
+ /* pfnConstruct */
+ pitConstruct,
+ /* pfnDestruct */
+ NULL,
+ /* pfnRelocate */
+ pitRelocate,
+ /* pfnMemSetup */
+ NULL,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ pitReset,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnAttach */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnQueryInterface */
+ NULL,
+ /* pfnInitComplete */
+ NULL,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32VersionEnd */
+ PDM_DEVREG_VERSION
+};
+
+#endif /* IN_RING3 */
+#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
diff --git a/src/VBox/Devices/PC/DevRTC.cpp b/src/VBox/Devices/PC/DevRTC.cpp
new file mode 100644
index 00000000..4416aa99
--- /dev/null
+++ b/src/VBox/Devices/PC/DevRTC.cpp
@@ -0,0 +1,1299 @@
+/* $Id: DevRTC.cpp $ */
+/** @file
+ * Motorola MC146818 RTC/CMOS Device with PIIX4 extensions.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * QEMU MC146818 RTC emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_RTC
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/log.h>
+#include <iprt/asm-math.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+
+#ifdef IN_RING3
+# include <iprt/alloc.h>
+# include <iprt/uuid.h>
+#endif /* IN_RING3 */
+
+#include "VBoxDD.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+/*#define DEBUG_CMOS*/
+#define RTC_CRC_START 0x10
+#define RTC_CRC_LAST 0x2d
+#define RTC_CRC_HIGH 0x2e
+#define RTC_CRC_LOW 0x2f
+
+#define RTC_SECONDS 0
+#define RTC_SECONDS_ALARM 1
+#define RTC_MINUTES 2
+#define RTC_MINUTES_ALARM 3
+#define RTC_HOURS 4
+#define RTC_HOURS_ALARM 5
+#define RTC_ALARM_DONT_CARE 0xC0
+
+#define RTC_DAY_OF_WEEK 6
+#define RTC_DAY_OF_MONTH 7
+#define RTC_MONTH 8
+#define RTC_YEAR 9
+
+#define RTC_REG_A 10
+#define RTC_REG_B 11
+#define RTC_REG_C 12
+#define RTC_REG_D 13
+
+#define REG_A_UIP 0x80
+
+#define REG_B_SET 0x80
+#define REG_B_PIE 0x40
+#define REG_B_AIE 0x20
+#define REG_B_UIE 0x10
+
+#define CMOS_BANK_LOWER_LIMIT 0x0E
+#define CMOS_BANK_UPPER_LIMIT 0x7F
+#define CMOS_BANK2_LOWER_LIMIT 0x80
+#define CMOS_BANK2_UPPER_LIMIT 0xFF
+#define CMOS_BANK_SIZE 0x80
+
+/** The saved state version. */
+#define RTC_SAVED_STATE_VERSION 4
+/** The saved state version used by VirtualBox pre-3.2.
+ * This does not include the second 128-byte bank. */
+#define RTC_SAVED_STATE_VERSION_VBOX_32PRE 3
+/** The saved state version used by VirtualBox 3.1 and earlier.
+ * This does not include disabled by HPET state. */
+#define RTC_SAVED_STATE_VERSION_VBOX_31 2
+/** The saved state version used by VirtualBox 3.0 and earlier.
+ * This does not include the configuration. */
+#define RTC_SAVED_STATE_VERSION_VBOX_30 1
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/** @todo Replace struct my_tm with RTTIME. */
+struct my_tm
+{
+ int32_t tm_sec;
+ int32_t tm_min;
+ int32_t tm_hour;
+ int32_t tm_mday;
+ int32_t tm_mon;
+ int32_t tm_year;
+ int32_t tm_wday;
+ int32_t tm_yday;
+};
+
+
+typedef struct RTCSTATE
+{
+ uint8_t cmos_data[256];
+ uint8_t cmos_index[2];
+ uint8_t Alignment0[6];
+ struct my_tm current_tm;
+ /** The configured IRQ. */
+ int32_t irq;
+ /** The configured I/O port base. */
+ RTIOPORT IOPortBase;
+ /** Use UTC or local time initially. */
+ bool fUTC;
+ /** Disabled by HPET legacy mode. */
+ bool fDisabledByHpet;
+ /* periodic timer */
+ int64_t next_periodic_time;
+ /* second update */
+ int64_t next_second_time;
+
+ /** Pointer to the device instance - R3 Ptr. */
+ PPDMDEVINSR3 pDevInsR3;
+ /** The periodic timer (rtcTimerPeriodic) - R3 Ptr. */
+ PTMTIMERR3 pPeriodicTimerR3;
+ /** The second timer (rtcTimerSecond) - R3 Ptr. */
+ PTMTIMERR3 pSecondTimerR3;
+ /** The second second timer (rtcTimerSecond2) - R3 Ptr. */
+ PTMTIMERR3 pSecondTimer2R3;
+
+ /** Pointer to the device instance - R0 Ptr. */
+ PPDMDEVINSR0 pDevInsR0;
+ /** The periodic timer (rtcTimerPeriodic) - R0 Ptr. */
+ PTMTIMERR0 pPeriodicTimerR0;
+ /** The second timer (rtcTimerSecond) - R0 Ptr. */
+ PTMTIMERR0 pSecondTimerR0;
+ /** The second second timer (rtcTimerSecond2) - R0 Ptr. */
+ PTMTIMERR0 pSecondTimer2R0;
+
+ /** Pointer to the device instance - RC Ptr. */
+ PPDMDEVINSRC pDevInsRC;
+ /** The periodic timer (rtcTimerPeriodic) - RC Ptr. */
+ PTMTIMERRC pPeriodicTimerRC;
+ /** The second timer (rtcTimerSecond) - RC Ptr. */
+ PTMTIMERRC pSecondTimerRC;
+ /** The second second timer (rtcTimerSecond2) - RC Ptr. */
+ PTMTIMERRC pSecondTimer2RC;
+
+ /** The RTC registration structure. */
+ PDMRTCREG RtcReg;
+ /** The RTC device helpers. */
+ R3PTRTYPE(PCPDMRTCHLP) pRtcHlpR3;
+ /** Number of release log entries. Used to prevent flooding. */
+ uint32_t cRelLogEntries;
+ /** The current/previous logged timer period. */
+ int32_t CurLogPeriod;
+ /** The current/previous hinted timer period. */
+ int32_t CurHintPeriod;
+ /** How many consecutive times the UIP has been seen. */
+ int32_t cUipSeen;
+
+ /** HPET legacy mode notification interface. */
+ PDMIHPETLEGACYNOTIFY IHpetLegacyNotify;
+
+ /** Number of IRQs that's been raised. */
+ STAMCOUNTER StatRTCIrq;
+ /** Number of times the timer callback handler ran. */
+ STAMCOUNTER StatRTCTimerCB;
+} RTCSTATE;
+/** Pointer to the RTC device state. */
+typedef RTCSTATE *PRTCSTATE;
+
+#ifndef VBOX_DEVICE_STRUCT_TESTCASE
+
+static void rtc_timer_update(PRTCSTATE pThis, int64_t current_time)
+{
+ int period_code, period;
+ uint64_t cur_clock, next_irq_clock;
+ uint32_t freq;
+
+ Assert(TMTimerIsLockOwner(pThis->CTX_SUFF(pPeriodicTimer)));
+ Assert(PDMCritSectIsOwner(pThis->CTX_SUFF(pDevIns)->CTX_SUFF(pCritSectRo)));
+
+ period_code = pThis->cmos_data[RTC_REG_A] & 0x0f;
+ if ( period_code != 0
+ && (pThis->cmos_data[RTC_REG_B] & REG_B_PIE))
+ {
+ if (period_code <= 2)
+ period_code += 7;
+ /* period in 32 kHz cycles */
+ period = 1 << (period_code - 1);
+ /* compute 32 kHz clock */
+ freq = TMTimerGetFreq(pThis->CTX_SUFF(pPeriodicTimer));
+
+ cur_clock = ASMMultU64ByU32DivByU32(current_time, 32768, freq);
+ next_irq_clock = (cur_clock & ~(uint64_t)(period - 1)) + period;
+ pThis->next_periodic_time = ASMMultU64ByU32DivByU32(next_irq_clock, freq, 32768) + 1;
+ TMTimerSet(pThis->CTX_SUFF(pPeriodicTimer), pThis->next_periodic_time);
+
+#ifdef IN_RING3
+ if (RT_UNLIKELY(period != pThis->CurLogPeriod))
+#else
+ if (RT_UNLIKELY(period != pThis->CurHintPeriod))
+#endif
+ {
+#ifdef IN_RING3
+ if (pThis->cRelLogEntries++ < 64)
+ LogRel(("RTC: period=%#x (%d) %u Hz\n", period, period, _32K / period));
+ pThis->CurLogPeriod = period;
+#endif
+ pThis->CurHintPeriod = period;
+ TMTimerSetFrequencyHint(pThis->CTX_SUFF(pPeriodicTimer), _32K / period);
+ }
+ }
+ else
+ {
+#ifdef IN_RING3
+ if (TMTimerIsActive(pThis->CTX_SUFF(pPeriodicTimer)) && pThis->cRelLogEntries++ < 64)
+ LogRel(("RTC: Stopped the periodic timer\n"));
+#endif
+ TMTimerStop(pThis->CTX_SUFF(pPeriodicTimer));
+ }
+}
+
+
+static void rtc_raise_irq(PRTCSTATE pThis, uint32_t iLevel)
+{
+ if (!pThis->fDisabledByHpet)
+ {
+ PDMDevHlpISASetIrq(pThis->CTX_SUFF(pDevIns), pThis->irq, iLevel);
+ if (iLevel)
+ STAM_COUNTER_INC(&pThis->StatRTCIrq);
+ }
+}
+
+
+#ifdef IN_RING3
+DECLINLINE(int) to_bcd(PRTCSTATE pThis, int a)
+{
+ if (pThis->cmos_data[RTC_REG_B] & 0x04)
+ return a;
+ return ((a / 10) << 4) | (a % 10);
+}
+#endif
+
+
+DECLINLINE(int) from_bcd(PRTCSTATE pThis, int a)
+{
+ if (pThis->cmos_data[RTC_REG_B] & 0x04)
+ return a;
+ return ((a >> 4) * 10) + (a & 0x0f);
+}
+
+
+static void rtc_set_time(PRTCSTATE pThis)
+{
+ struct my_tm *tm = &pThis->current_tm;
+
+ tm->tm_sec = from_bcd(pThis, pThis->cmos_data[RTC_SECONDS]);
+ tm->tm_min = from_bcd(pThis, pThis->cmos_data[RTC_MINUTES]);
+ tm->tm_hour = from_bcd(pThis, pThis->cmos_data[RTC_HOURS] & 0x7f);
+ if (!(pThis->cmos_data[RTC_REG_B] & 0x02))
+ {
+ tm->tm_hour %= 12;
+ if (pThis->cmos_data[RTC_HOURS] & 0x80)
+ tm->tm_hour += 12;
+ }
+ tm->tm_wday = from_bcd(pThis, pThis->cmos_data[RTC_DAY_OF_WEEK]);
+ tm->tm_mday = from_bcd(pThis, pThis->cmos_data[RTC_DAY_OF_MONTH]);
+ tm->tm_mon = from_bcd(pThis, pThis->cmos_data[RTC_MONTH]) - 1;
+ tm->tm_year = from_bcd(pThis, pThis->cmos_data[RTC_YEAR]) + 100;
+}
+
+
+/* -=-=-=-=-=- I/O Port Handlers -=-=-=-=-=- */
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN}
+ */
+PDMBOTHCBDECL(int) rtcIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb)
+{
+ NOREF(pvUser);
+ if (cb != 1)
+ return VERR_IOM_IOPORT_UNUSED;
+
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+ if ((uPort & 1) == 0)
+ *pu32 = 0xff;
+ else
+ {
+ unsigned bank = (uPort >> 1) & 1;
+ switch (pThis->cmos_index[bank])
+ {
+ case RTC_SECONDS:
+ case RTC_MINUTES:
+ case RTC_HOURS:
+ case RTC_DAY_OF_WEEK:
+ case RTC_DAY_OF_MONTH:
+ case RTC_MONTH:
+ case RTC_YEAR:
+ *pu32 = pThis->cmos_data[pThis->cmos_index[0]];
+ break;
+
+ case RTC_REG_A:
+ if (pThis->cmos_data[RTC_REG_A] & REG_A_UIP)
+ ++pThis->cUipSeen;
+ else
+ pThis->cUipSeen = 0;
+ if (pThis->cUipSeen >= 250)
+ {
+ pThis->cmos_data[pThis->cmos_index[0]] &= ~REG_A_UIP;
+ pThis->cUipSeen = 0;
+ }
+ *pu32 = pThis->cmos_data[pThis->cmos_index[0]];
+ break;
+
+ case RTC_REG_C:
+ *pu32 = pThis->cmos_data[pThis->cmos_index[0]];
+ rtc_raise_irq(pThis, 0);
+ pThis->cmos_data[RTC_REG_C] = 0x00;
+ break;
+
+ default:
+ *pu32 = pThis->cmos_data[pThis->cmos_index[bank]];
+ break;
+ }
+
+ Log(("CMOS: Read bank %d idx %#04x: %#04x\n", bank, pThis->cmos_index[bank], *pu32));
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT}
+ */
+PDMBOTHCBDECL(int) rtcIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb)
+{
+ NOREF(pvUser);
+ if (cb != 1)
+ return VINF_SUCCESS;
+
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+ uint32_t bank = (uPort >> 1) & 1;
+ if ((uPort & 1) == 0)
+ {
+ pThis->cmos_index[bank] = (u32 & 0x7f) + (bank * CMOS_BANK_SIZE);
+
+ /* HACK ALERT! Attempt to trigger VM_FF_TIMER and/or VM_FF_TM_VIRTUAL_SYNC
+ for forcing the pSecondTimer2 timer to run be run and clear UIP in
+ a timely fashion. */
+ if (u32 == RTC_REG_A)
+ TMTimerGet(pThis->CTX_SUFF(pSecondTimer));
+ }
+ else
+ {
+ Log(("CMOS: Write bank %d idx %#04x: %#04x (old %#04x)\n", bank,
+ pThis->cmos_index[bank], u32, pThis->cmos_data[pThis->cmos_index[bank]]));
+
+ int const idx = pThis->cmos_index[bank];
+ switch (idx)
+ {
+ case RTC_SECONDS_ALARM:
+ case RTC_MINUTES_ALARM:
+ case RTC_HOURS_ALARM:
+ pThis->cmos_data[pThis->cmos_index[0]] = u32;
+ break;
+
+ case RTC_SECONDS:
+ case RTC_MINUTES:
+ case RTC_HOURS:
+ case RTC_DAY_OF_WEEK:
+ case RTC_DAY_OF_MONTH:
+ case RTC_MONTH:
+ case RTC_YEAR:
+ pThis->cmos_data[pThis->cmos_index[0]] = u32;
+ /* if in set mode, do not update the time */
+ if (!(pThis->cmos_data[RTC_REG_B] & REG_B_SET))
+ rtc_set_time(pThis);
+ break;
+
+ case RTC_REG_A:
+ case RTC_REG_B:
+ {
+ /* We need to acquire the clock lock, because of lock ordering
+ issues this means having to release the device lock. Since
+ we're letting IOM do the locking, we must not return without
+ holding the device lock.*/
+ PDMCritSectLeave(pThis->CTX_SUFF(pDevIns)->CTX_SUFF(pCritSectRo));
+ int rc1 = TMTimerLock(pThis->CTX_SUFF(pPeriodicTimer), VINF_SUCCESS /* must get it */);
+ int rc2 = PDMCritSectEnter(pThis->CTX_SUFF(pDevIns)->CTX_SUFF(pCritSectRo), VINF_SUCCESS /* must get it */);
+ AssertRCReturn(rc1, rc1);
+ AssertRCReturnStmt(rc2, TMTimerUnlock(pThis->CTX_SUFF(pPeriodicTimer)), rc2);
+
+ if (idx == RTC_REG_A)
+ {
+ /* UIP bit is read only */
+ pThis->cmos_data[RTC_REG_A] = (u32 & ~REG_A_UIP)
+ | (pThis->cmos_data[RTC_REG_A] & REG_A_UIP);
+ }
+ else
+ {
+ if (u32 & REG_B_SET)
+ {
+ /* set mode: reset UIP mode */
+ pThis->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
+#if 0 /* This is probably wrong as it breaks changing the time/date in OS/2. */
+ u32 &= ~REG_B_UIE;
+#endif
+ }
+ else
+ {
+ /* if disabling set mode, update the time */
+ if (pThis->cmos_data[RTC_REG_B] & REG_B_SET)
+ rtc_set_time(pThis);
+ }
+ pThis->cmos_data[RTC_REG_B] = u32;
+ }
+
+ rtc_timer_update(pThis, TMTimerGet(pThis->CTX_SUFF(pPeriodicTimer)));
+
+ TMTimerUnlock(pThis->CTX_SUFF(pPeriodicTimer));
+ /* the caller leaves the other lock. */
+ break;
+ }
+
+ case RTC_REG_C:
+ case RTC_REG_D:
+ /* cannot write to them */
+ break;
+
+ default:
+ pThis->cmos_data[pThis->cmos_index[bank]] = u32;
+ break;
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+#ifdef IN_RING3
+
+/* -=-=-=-=-=- Debug Info Handlers -=-=-=-=-=- */
+
+/**
+ * @callback_method_impl{FNDBGFHANDLERDEV,
+ * Dumps the cmos Bank Info.}
+ */
+static DECLCALLBACK(void) rtcCmosBankInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+ RT_NOREF1(pszArgs);
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+
+ pHlp->pfnPrintf(pHlp,
+ "First CMOS bank, offsets 0x0E - 0x7F\n"
+ "Offset %02x : --- use 'info rtc' to show CMOS clock ---", 0);
+ for (unsigned iCmos = CMOS_BANK_LOWER_LIMIT; iCmos <= CMOS_BANK_UPPER_LIMIT; iCmos++)
+ {
+ if ((iCmos & 15) == 0)
+ pHlp->pfnPrintf(pHlp, "Offset %02x : %02x", iCmos, pThis->cmos_data[iCmos]);
+ else if ((iCmos & 15) == 8)
+ pHlp->pfnPrintf(pHlp, "-%02x", pThis->cmos_data[iCmos]);
+ else if ((iCmos & 15) == 15)
+ pHlp->pfnPrintf(pHlp, " %02x\n", pThis->cmos_data[iCmos]);
+ else
+ pHlp->pfnPrintf(pHlp, " %02x", pThis->cmos_data[iCmos]);
+ }
+}
+
+/**
+ * @callback_method_impl{FNDBGFHANDLERDEV,
+ * Dumps the cmos Bank2 Info.}
+ */
+static DECLCALLBACK(void) rtcCmosBank2Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+ RT_NOREF1(pszArgs);
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+
+ pHlp->pfnPrintf(pHlp, "Second CMOS bank, offsets 0x80 - 0xFF\n");
+ for (uint16_t iCmos = CMOS_BANK2_LOWER_LIMIT; iCmos <= CMOS_BANK2_UPPER_LIMIT; iCmos++)
+ {
+ if ((iCmos & 15) == 0)
+ pHlp->pfnPrintf(pHlp, "Offset %02x : %02x", iCmos, pThis->cmos_data[iCmos]);
+ else if ((iCmos & 15) == 8)
+ pHlp->pfnPrintf(pHlp, "-%02x", pThis->cmos_data[iCmos]);
+ else if ((iCmos & 15) == 15)
+ pHlp->pfnPrintf(pHlp, " %02x\n", pThis->cmos_data[iCmos]);
+ else
+ pHlp->pfnPrintf(pHlp, " %02x", pThis->cmos_data[iCmos]);
+ }
+}
+
+/**
+ * @callback_method_impl{FNDBGFHANDLERDEV,
+ * Dumps the cmos RTC Info.}
+ */
+static DECLCALLBACK(void) rtcCmosClockInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+ RT_NOREF1(pszArgs);
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+ uint8_t u8Sec = from_bcd(pThis, pThis->cmos_data[RTC_SECONDS]);
+ uint8_t u8Min = from_bcd(pThis, pThis->cmos_data[RTC_MINUTES]);
+ uint8_t u8Hr = from_bcd(pThis, pThis->cmos_data[RTC_HOURS] & 0x7f);
+ if ( !(pThis->cmos_data[RTC_REG_B] & 0x02)
+ && (pThis->cmos_data[RTC_HOURS] & 0x80))
+ u8Hr += 12;
+ uint8_t u8Day = from_bcd(pThis, pThis->cmos_data[RTC_DAY_OF_MONTH]);
+ uint8_t u8Month = from_bcd(pThis, pThis->cmos_data[RTC_MONTH]) ;
+ uint8_t u8Year = from_bcd(pThis, pThis->cmos_data[RTC_YEAR]);
+ pHlp->pfnPrintf(pHlp, "Time: %02u:%02u:%02u Date: %02u-%02u-%02u\n",
+ u8Hr, u8Min, u8Sec, u8Year, u8Month, u8Day);
+ pHlp->pfnPrintf(pHlp, "REG A=%02x B=%02x C=%02x D=%02x\n",
+ pThis->cmos_data[RTC_REG_A], pThis->cmos_data[RTC_REG_B],
+ pThis->cmos_data[RTC_REG_C], pThis->cmos_data[RTC_REG_D]);
+}
+
+
+
+/* -=-=-=-=-=- Timers and their support code -=-=-=-=-=- */
+
+
+/**
+ * @callback_method_impl{FNTMTIMERDEV, periodic}
+ */
+static DECLCALLBACK(void) rtcTimerPeriodic(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+ RT_NOREF2(pTimer, pvUser);
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+ Assert(TMTimerIsLockOwner(pThis->CTX_SUFF(pPeriodicTimer)));
+ Assert(PDMCritSectIsOwner(pThis->CTX_SUFF(pDevIns)->CTX_SUFF(pCritSectRo)));
+
+ rtc_timer_update(pThis, pThis->next_periodic_time);
+ STAM_COUNTER_INC(&pThis->StatRTCTimerCB);
+ pThis->cmos_data[RTC_REG_C] |= 0xc0;
+
+ rtc_raise_irq(pThis, 1);
+}
+
+
+/* month is between 0 and 11. */
+static int get_days_in_month(int month, int year)
+{
+ static const int days_tab[12] =
+ {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ int d;
+
+ if ((unsigned )month >= 12)
+ return 31;
+
+ d = days_tab[month];
+ if (month == 1)
+ {
+ if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
+ d++;
+ }
+ return d;
+}
+
+
+/* update 'tm' to the next second */
+static void rtc_next_second(struct my_tm *tm)
+{
+ int days_in_month;
+
+ tm->tm_sec++;
+ if ((unsigned)tm->tm_sec >= 60)
+ {
+ tm->tm_sec = 0;
+ tm->tm_min++;
+ if ((unsigned)tm->tm_min >= 60)
+ {
+ tm->tm_min = 0;
+ tm->tm_hour++;
+ if ((unsigned)tm->tm_hour >= 24)
+ {
+ tm->tm_hour = 0;
+ /* next day */
+ tm->tm_wday++;
+ if ((unsigned)tm->tm_wday >= 7)
+ tm->tm_wday = 0;
+ days_in_month = get_days_in_month(tm->tm_mon,
+ tm->tm_year + 1900);
+ tm->tm_mday++;
+ if (tm->tm_mday < 1)
+ tm->tm_mday = 1;
+ else if (tm->tm_mday > days_in_month)
+ {
+ tm->tm_mday = 1;
+ tm->tm_mon++;
+ if (tm->tm_mon >= 12)
+ {
+ tm->tm_mon = 0;
+ tm->tm_year++;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * @callback_method_impl{FNTMTIMERDEV, Second timer.}
+ */
+static DECLCALLBACK(void) rtcTimerSecond(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+ RT_NOREF2(pTimer, pvUser);
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+ Assert(TMTimerIsLockOwner(pThis->CTX_SUFF(pPeriodicTimer)));
+ Assert(PDMCritSectIsOwner(pThis->CTX_SUFF(pDevIns)->CTX_SUFF(pCritSectRo)));
+
+ /* if the oscillator is not in normal operation, we do not update */
+ if ((pThis->cmos_data[RTC_REG_A] & 0x70) != 0x20)
+ {
+ pThis->next_second_time += TMTimerGetFreq(pThis->CTX_SUFF(pSecondTimer));
+ TMTimerSet(pThis->CTX_SUFF(pSecondTimer), pThis->next_second_time);
+ }
+ else
+ {
+ rtc_next_second(&pThis->current_tm);
+
+ if (!(pThis->cmos_data[RTC_REG_B] & REG_B_SET))
+ {
+ /* update in progress bit */
+ Log2(("RTC: UIP %x -> 1\n", !!(pThis->cmos_data[RTC_REG_A] & REG_A_UIP)));
+ pThis->cmos_data[RTC_REG_A] |= REG_A_UIP;
+ }
+
+ /* 244140 ns = 8 / 32768 seconds */
+ uint64_t delay = TMTimerFromNano(pThis->CTX_SUFF(pSecondTimer2), 244140);
+ TMTimerSet(pThis->CTX_SUFF(pSecondTimer2), pThis->next_second_time + delay);
+ }
+}
+
+
+/* Used by rtc_set_date and rtcTimerSecond2. */
+static void rtc_copy_date(PRTCSTATE pThis)
+{
+ const struct my_tm *tm = &pThis->current_tm;
+
+ pThis->cmos_data[RTC_SECONDS] = to_bcd(pThis, tm->tm_sec);
+ pThis->cmos_data[RTC_MINUTES] = to_bcd(pThis, tm->tm_min);
+ if (pThis->cmos_data[RTC_REG_B] & 0x02)
+ {
+ /* 24 hour format */
+ pThis->cmos_data[RTC_HOURS] = to_bcd(pThis, tm->tm_hour);
+ }
+ else
+ {
+ /* 12 hour format */
+ int h = tm->tm_hour % 12;
+ pThis->cmos_data[RTC_HOURS] = to_bcd(pThis, h ? h : 12);
+ if (tm->tm_hour >= 12)
+ pThis->cmos_data[RTC_HOURS] |= 0x80;
+ }
+ pThis->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(pThis, tm->tm_wday);
+ pThis->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(pThis, tm->tm_mday);
+ pThis->cmos_data[RTC_MONTH] = to_bcd(pThis, tm->tm_mon + 1);
+ pThis->cmos_data[RTC_YEAR] = to_bcd(pThis, tm->tm_year % 100);
+}
+
+
+/**
+ * @callback_method_impl{FNTMTIMERDEV, Second2 timer.}
+ */
+static DECLCALLBACK(void) rtcTimerSecond2(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+ RT_NOREF2(pTimer, pvUser);
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+ Assert(TMTimerIsLockOwner(pThis->CTX_SUFF(pPeriodicTimer)));
+ Assert(PDMCritSectIsOwner(pThis->CTX_SUFF(pDevIns)->CTX_SUFF(pCritSectRo)));
+
+ if (!(pThis->cmos_data[RTC_REG_B] & REG_B_SET))
+ rtc_copy_date(pThis);
+
+ /* check alarm */
+ if (pThis->cmos_data[RTC_REG_B] & REG_B_AIE)
+ {
+ if ( ( (pThis->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0
+ || from_bcd(pThis, pThis->cmos_data[RTC_SECONDS_ALARM]) == pThis->current_tm.tm_sec)
+ && ( (pThis->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0
+ || from_bcd(pThis, pThis->cmos_data[RTC_MINUTES_ALARM]) == pThis->current_tm.tm_min)
+ && ( (pThis->cmos_data[RTC_HOURS_ALARM ] & 0xc0) == 0xc0
+ || from_bcd(pThis, pThis->cmos_data[RTC_HOURS_ALARM ]) == pThis->current_tm.tm_hour)
+ )
+ {
+ pThis->cmos_data[RTC_REG_C] |= 0xa0;
+ rtc_raise_irq(pThis, 1);
+ }
+ }
+
+ /* update ended interrupt */
+ if (pThis->cmos_data[RTC_REG_B] & REG_B_UIE)
+ {
+ pThis->cmos_data[RTC_REG_C] |= 0x90;
+ rtc_raise_irq(pThis, 1);
+ }
+
+ /* clear update in progress bit */
+ Log2(("RTC: UIP %x -> 0\n", !!(pThis->cmos_data[RTC_REG_A] & REG_A_UIP)));
+ pThis->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
+
+ pThis->next_second_time += TMTimerGetFreq(pThis->CTX_SUFF(pSecondTimer));
+ TMTimerSet(pThis->CTX_SUFF(pSecondTimer), pThis->next_second_time);
+}
+
+
+/* -=-=-=-=-=- Saved State -=-=-=-=-=- */
+
+
+/**
+ * @callback_method_impl{FNSSMDEVLIVEEXEC}
+ */
+static DECLCALLBACK(int) rtcLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
+{
+ RT_NOREF1(uPass);
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+
+ SSMR3PutU8( pSSM, pThis->irq);
+ SSMR3PutIOPort(pSSM, pThis->IOPortBase);
+ SSMR3PutBool( pSSM, pThis->fUTC);
+
+ return VINF_SSM_DONT_CALL_AGAIN;
+}
+
+
+/**
+ * @callback_method_impl{FNSSMDEVSAVEEXEC}
+ */
+static DECLCALLBACK(int) rtcSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+
+ /* The config. */
+ rtcLiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
+
+ /* The state. */
+ SSMR3PutMem(pSSM, pThis->cmos_data, CMOS_BANK_SIZE);
+ SSMR3PutU8(pSSM, pThis->cmos_index[0]);
+
+ SSMR3PutS32(pSSM, pThis->current_tm.tm_sec);
+ SSMR3PutS32(pSSM, pThis->current_tm.tm_min);
+ SSMR3PutS32(pSSM, pThis->current_tm.tm_hour);
+ SSMR3PutS32(pSSM, pThis->current_tm.tm_wday);
+ SSMR3PutS32(pSSM, pThis->current_tm.tm_mday);
+ SSMR3PutS32(pSSM, pThis->current_tm.tm_mon);
+ SSMR3PutS32(pSSM, pThis->current_tm.tm_year);
+
+ TMR3TimerSave(pThis->CTX_SUFF(pPeriodicTimer), pSSM);
+
+ SSMR3PutS64(pSSM, pThis->next_periodic_time);
+
+ SSMR3PutS64(pSSM, pThis->next_second_time);
+ TMR3TimerSave(pThis->CTX_SUFF(pSecondTimer), pSSM);
+ TMR3TimerSave(pThis->CTX_SUFF(pSecondTimer2), pSSM);
+
+ SSMR3PutBool(pSSM, pThis->fDisabledByHpet);
+
+ SSMR3PutMem(pSSM, &pThis->cmos_data[CMOS_BANK_SIZE], CMOS_BANK_SIZE);
+ return SSMR3PutU8(pSSM, pThis->cmos_index[1]);
+}
+
+
+/**
+ * @callback_method_impl{FNSSMDEVLOADEXEC}
+ */
+static DECLCALLBACK(int) rtcLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+{
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+ int rc;
+
+ if ( uVersion != RTC_SAVED_STATE_VERSION
+ && uVersion != RTC_SAVED_STATE_VERSION_VBOX_32PRE
+ && uVersion != RTC_SAVED_STATE_VERSION_VBOX_31
+ && uVersion != RTC_SAVED_STATE_VERSION_VBOX_30)
+ return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
+
+ /* The config. */
+ if (uVersion > RTC_SAVED_STATE_VERSION_VBOX_30)
+ {
+ uint8_t u8Irq;
+ rc = SSMR3GetU8(pSSM, &u8Irq); AssertRCReturn(rc, rc);
+ if (u8Irq != pThis->irq)
+ return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - u8Irq: saved=%#x config=%#x"), u8Irq, pThis->irq);
+
+ RTIOPORT IOPortBase;
+ rc = SSMR3GetIOPort(pSSM, &IOPortBase); AssertRCReturn(rc, rc);
+ if (IOPortBase != pThis->IOPortBase)
+ return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - IOPortBase: saved=%RTiop config=%RTiop"), IOPortBase, pThis->IOPortBase);
+
+ bool fUTC;
+ rc = SSMR3GetBool(pSSM, &fUTC); AssertRCReturn(rc, rc);
+ if (fUTC != pThis->fUTC)
+ LogRel(("RTC: Config mismatch - fUTC: saved=%RTbool config=%RTbool\n", fUTC, pThis->fUTC));
+ }
+
+ if (uPass != SSM_PASS_FINAL)
+ return VINF_SUCCESS;
+
+ /* The state. */
+ SSMR3GetMem(pSSM, pThis->cmos_data, CMOS_BANK_SIZE);
+ SSMR3GetU8(pSSM, &pThis->cmos_index[0]);
+
+ SSMR3GetS32(pSSM, &pThis->current_tm.tm_sec);
+ SSMR3GetS32(pSSM, &pThis->current_tm.tm_min);
+ SSMR3GetS32(pSSM, &pThis->current_tm.tm_hour);
+ SSMR3GetS32(pSSM, &pThis->current_tm.tm_wday);
+ SSMR3GetS32(pSSM, &pThis->current_tm.tm_mday);
+ SSMR3GetS32(pSSM, &pThis->current_tm.tm_mon);
+ SSMR3GetS32(pSSM, &pThis->current_tm.tm_year);
+
+ TMR3TimerLoad(pThis->CTX_SUFF(pPeriodicTimer), pSSM);
+
+ SSMR3GetS64(pSSM, &pThis->next_periodic_time);
+
+ SSMR3GetS64(pSSM, &pThis->next_second_time);
+ TMR3TimerLoad(pThis->CTX_SUFF(pSecondTimer), pSSM);
+ TMR3TimerLoad(pThis->CTX_SUFF(pSecondTimer2), pSSM);
+
+ if (uVersion > RTC_SAVED_STATE_VERSION_VBOX_31)
+ SSMR3GetBool(pSSM, &pThis->fDisabledByHpet);
+
+ if (uVersion > RTC_SAVED_STATE_VERSION_VBOX_32PRE)
+ {
+ /* Second CMOS bank. */
+ SSMR3GetMem(pSSM, &pThis->cmos_data[CMOS_BANK_SIZE], CMOS_BANK_SIZE);
+ SSMR3GetU8(pSSM, &pThis->cmos_index[1]);
+ }
+
+ int period_code = pThis->cmos_data[RTC_REG_A] & 0x0f;
+ if ( period_code != 0
+ && (pThis->cmos_data[RTC_REG_B] & REG_B_PIE))
+ {
+ if (period_code <= 2)
+ period_code += 7;
+ int period = 1 << (period_code - 1);
+ LogRel(("RTC: period=%#x (%d) %u Hz (restore)\n", period, period, _32K / period));
+ PDMCritSectEnter(pThis->pDevInsR3->pCritSectRoR3, VINF_SUCCESS);
+ TMTimerSetFrequencyHint(pThis->CTX_SUFF(pPeriodicTimer), _32K / period);
+ PDMCritSectLeave(pThis->pDevInsR3->pCritSectRoR3);
+ pThis->CurLogPeriod = period;
+ pThis->CurHintPeriod = period;
+ }
+ else
+ {
+ LogRel(("RTC: Stopped the periodic timer (restore)\n"));
+ pThis->CurLogPeriod = 0;
+ pThis->CurHintPeriod = 0;
+ }
+ pThis->cRelLogEntries = 0;
+
+ return VINF_SUCCESS;
+}
+
+
+/* -=-=-=-=-=- PDM Interface provided by the RTC device -=-=-=-=-=- */
+
+/**
+ * Calculate and update the standard CMOS checksum.
+ *
+ * @param pThis Pointer to the RTC state data.
+ */
+static void rtcCalcCRC(PRTCSTATE pThis)
+{
+ uint16_t u16 = 0;
+ for (unsigned i = RTC_CRC_START; i <= RTC_CRC_LAST; i++)
+ u16 += pThis->cmos_data[i];
+
+ pThis->cmos_data[RTC_CRC_LOW] = u16 & 0xff;
+ pThis->cmos_data[RTC_CRC_HIGH] = (u16 >> 8) & 0xff;
+}
+
+
+/**
+ * @interface_method_impl{PDMRTCREG,pfnWrite}
+ */
+static DECLCALLBACK(int) rtcCMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
+{
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+ Assert(PDMCritSectIsOwner(pDevIns->pCritSectRoR3));
+ if (iReg < RT_ELEMENTS(pThis->cmos_data))
+ {
+ pThis->cmos_data[iReg] = u8Value;
+
+ /* does it require checksum update? */
+ if ( iReg >= RTC_CRC_START
+ && iReg <= RTC_CRC_LAST)
+ rtcCalcCRC(pThis);
+
+ return VINF_SUCCESS;
+ }
+
+ AssertMsgFailed(("iReg=%d\n", iReg));
+ return VERR_INVALID_PARAMETER;
+}
+
+
+/**
+ * @interface_method_impl{PDMRTCREG,pfnRead}
+ */
+static DECLCALLBACK(int) rtcCMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
+{
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+ Assert(PDMCritSectIsOwner(pDevIns->pCritSectRoR3));
+
+ if (iReg < RT_ELEMENTS(pThis->cmos_data))
+ {
+ *pu8Value = pThis->cmos_data[iReg];
+ return VINF_SUCCESS;
+ }
+ AssertMsgFailed(("iReg=%d\n", iReg));
+ return VERR_INVALID_PARAMETER;
+}
+
+
+/**
+ * @interface_method_impl{PDMIHPETLEGACYNOTIFY,pfnModeChanged}
+ */
+static DECLCALLBACK(void) rtcHpetLegacyNotify_ModeChanged(PPDMIHPETLEGACYNOTIFY pInterface, bool fActivated)
+{
+ PRTCSTATE pThis = RT_FROM_MEMBER(pInterface, RTCSTATE, IHpetLegacyNotify);
+ PDMCritSectEnter(pThis->pDevInsR3->pCritSectRoR3, VERR_IGNORED);
+
+ pThis->fDisabledByHpet = fActivated;
+
+ PDMCritSectLeave(pThis->pDevInsR3->pCritSectRoR3);
+}
+
+
+
+/* -=-=-=-=-=- IBase -=-=-=-=-=- */
+
+/**
+ * @interface_method_impl{PDMIBASE,pfnQueryInterface}
+ */
+static DECLCALLBACK(void *) rtcQueryInterface(PPDMIBASE pInterface, const char *pszIID)
+{
+ PPDMDEVINS pDevIns = RT_FROM_MEMBER(pInterface, PDMDEVINS, IBase);
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDevIns->IBase);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHPETLEGACYNOTIFY, &pThis->IHpetLegacyNotify);
+ return NULL;
+}
+
+
+/* -=-=-=-=-=- PDMDEVREG -=-=-=-=-=- */
+
+static void rtc_set_memory(PRTCSTATE pThis, int addr, int val)
+{
+ if (addr >= 0 && addr <= 127)
+ pThis->cmos_data[addr] = val;
+}
+
+
+static void rtc_set_date(PRTCSTATE pThis, const struct my_tm *tm)
+{
+ pThis->current_tm = *tm;
+ rtc_copy_date(pThis);
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnInitComplete}
+ *
+ * Used to set the clock.
+ */
+static DECLCALLBACK(int) rtcInitComplete(PPDMDEVINS pDevIns)
+{
+ /** @todo this should be (re)done at power on if we didn't load a state... */
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+
+ /*
+ * Set the CMOS date/time.
+ */
+ RTTIMESPEC Now;
+ PDMDevHlpTMUtcNow(pDevIns, &Now);
+ RTTIME Time;
+ if (pThis->fUTC)
+ RTTimeExplode(&Time, &Now);
+ else
+ RTTimeLocalExplode(&Time, &Now);
+
+ struct my_tm Tm;
+ memset(&Tm, 0, sizeof(Tm));
+ Tm.tm_year = Time.i32Year - 1900;
+ Tm.tm_mon = Time.u8Month - 1;
+ Tm.tm_mday = Time.u8MonthDay;
+ Tm.tm_wday = (Time.u8WeekDay + 1 + 7) % 7; /* 0 = Monday -> Sunday */
+ Tm.tm_yday = Time.u16YearDay - 1;
+ Tm.tm_hour = Time.u8Hour;
+ Tm.tm_min = Time.u8Minute;
+ Tm.tm_sec = Time.u8Second;
+
+ rtc_set_date(pThis, &Tm);
+
+ int iYear = to_bcd(pThis, (Tm.tm_year / 100) + 19); /* tm_year is 1900 based */
+ rtc_set_memory(pThis, 0x32, iYear); /* 32h - Century Byte (BCD value for the century */
+ rtc_set_memory(pThis, 0x37, iYear); /* 37h - (IBM PS/2) Date Century Byte */
+
+ /*
+ * Recalculate the checksum just in case.
+ */
+ rtcCalcCRC(pThis);
+
+ Log(("CMOS bank 0: \n%16.128Rhxd\n", &pThis->cmos_data[0]));
+ Log(("CMOS bank 1: \n%16.128Rhxd\n", &pThis->cmos_data[CMOS_BANK_SIZE]));
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnRelocate}
+ */
+static DECLCALLBACK(void) rtcRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
+{
+ RT_NOREF1(offDelta);
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+
+ pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+ pThis->pPeriodicTimerRC = TMTimerRCPtr(pThis->pPeriodicTimerR3);
+ pThis->pSecondTimerRC = TMTimerRCPtr(pThis->pSecondTimerR3);
+ pThis->pSecondTimer2RC = TMTimerRCPtr(pThis->pSecondTimer2R3);
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnReset}
+ */
+static DECLCALLBACK(void) rtcReset(PPDMDEVINS pDevIns)
+{
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+
+ /* Reset index values (important for second bank). */
+ pThis->cmos_index[0] = 0;
+ pThis->cmos_index[1] = CMOS_BANK_SIZE; /* Point to start of second bank. */
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnConstruct}
+ */
+static DECLCALLBACK(int) rtcConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
+{
+ PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+ PRTCSTATE pThis = PDMINS_2_DATA(pDevIns, PRTCSTATE);
+ int rc;
+ Assert(iInstance == 0); RT_NOREF(iInstance);
+
+ /*
+ * Validate configuration.
+ */
+ if (!CFGMR3AreValuesValid(pCfg,
+ "Irq\0"
+ "Base\0"
+ "UseUTC\0"
+ "RCEnabled\0"
+ "R0Enabled\0"))
+ return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
+
+ /*
+ * Init the data.
+ */
+ uint8_t u8Irq;
+ rc = CFGMR3QueryU8Def(pCfg, "Irq", &u8Irq, 8);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"Irq\" as a uint8_t failed"));
+ pThis->irq = u8Irq;
+
+ rc = CFGMR3QueryPortDef(pCfg, "Base", &pThis->IOPortBase, 0x70);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"Base\" as a RTIOPORT failed"));
+
+ rc = CFGMR3QueryBoolDef(pCfg, "UseUTC", &pThis->fUTC, false);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: Querying \"UseUTC\" as a bool failed"));
+
+ bool fRCEnabled;
+ rc = CFGMR3QueryBoolDef(pCfg, "RCEnabled", &fRCEnabled, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: failed to read GCEnabled as boolean"));
+
+ bool fR0Enabled;
+ rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
+ if (RT_FAILURE(rc))
+ return PDMDEV_SET_ERROR(pDevIns, rc,
+ N_("Configuration error: failed to read R0Enabled as boolean"));
+
+ Log(("RTC: Irq=%#x Base=%#x fRCEnabled=%RTbool fR0Enabled=%RTbool\n",
+ u8Irq, pThis->IOPortBase, fRCEnabled, fR0Enabled));
+
+
+ pThis->pDevInsR3 = pDevIns;
+ pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
+ pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+ pThis->cmos_data[RTC_REG_A] = 0x26;
+ pThis->cmos_data[RTC_REG_B] = 0x02;
+ pThis->cmos_data[RTC_REG_C] = 0x00;
+ pThis->cmos_data[RTC_REG_D] = 0x80;
+ pThis->RtcReg.u32Version = PDM_RTCREG_VERSION;
+ pThis->RtcReg.pfnRead = rtcCMOSRead;
+ pThis->RtcReg.pfnWrite = rtcCMOSWrite;
+ pThis->fDisabledByHpet = false;
+ pThis->cmos_index[1] = CMOS_BANK_SIZE; /* Point to start of second bank. */
+
+
+ /* IBase */
+ pDevIns->IBase.pfnQueryInterface = rtcQueryInterface;
+ /* IHpetLegacyNotify */
+ pThis->IHpetLegacyNotify.pfnModeChanged = rtcHpetLegacyNotify_ModeChanged;
+
+ /*
+ * Create timers.
+ */
+ PTMTIMER pTimer;
+ /* Periodic timer. */
+ rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, rtcTimerPeriodic, pThis,
+ TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "MC146818 RTC/CMOS - Periodic",
+ &pTimer);
+ if (RT_FAILURE(rc))
+ return rc;
+ pThis->pPeriodicTimerR3 = pTimer;
+ pThis->pPeriodicTimerR0 = TMTimerR0Ptr(pTimer);
+ pThis->pPeriodicTimerRC = TMTimerRCPtr(pTimer);
+
+ /* Seconds timer. */
+ rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, rtcTimerSecond, pThis,
+ TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "MC146818 RTC/CMOS - Second",
+ &pTimer);
+ if (RT_FAILURE(rc))
+ return rc;
+ pThis->pSecondTimerR3 = pTimer;
+ pThis->pSecondTimerR0 = TMTimerR0Ptr(pTimer);
+ pThis->pSecondTimerRC = TMTimerRCPtr(pTimer);
+
+ /* The second2 timer, this is always active. */
+ rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, rtcTimerSecond2, pThis,
+ TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "MC146818 RTC/CMOS - Second2",
+ &pTimer);
+ if (RT_FAILURE(rc))
+ return rc;
+ pThis->pSecondTimer2R3 = pTimer;
+ pThis->pSecondTimer2R0 = TMTimerR0Ptr(pTimer);
+ pThis->pSecondTimer2RC = TMTimerRCPtr(pTimer);
+ pThis->next_second_time = TMTimerGet(pTimer)
+ + (TMTimerGetFreq(pTimer) * 99) / 100;
+ rc = TMTimerLock(pTimer, VERR_IGNORED);
+ AssertRCReturn(rc, rc);
+ rc = TMTimerSet(pTimer, pThis->next_second_time);
+ TMTimerUnlock(pTimer);
+ AssertRCReturn(rc, rc);
+
+ /*
+ * Register I/O ports.
+ */
+ rc = PDMDevHlpIOPortRegister(pDevIns, pThis->IOPortBase, 4, NULL,
+ rtcIOPortWrite, rtcIOPortRead, NULL, NULL, "MC146818 RTC/CMOS");
+ if (RT_FAILURE(rc))
+ return rc;
+ if (fRCEnabled)
+ {
+ rc = PDMDevHlpIOPortRegisterRC(pDevIns, pThis->IOPortBase, 4, NIL_RTRCPTR,
+ "rtcIOPortWrite", "rtcIOPortRead", NULL, NULL, "MC146818 RTC/CMOS");
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+ if (fR0Enabled)
+ {
+ rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->IOPortBase, 4, NIL_RTR0PTR,
+ "rtcIOPortWrite", "rtcIOPortRead", NULL, NULL, "MC146818 RTC/CMOS");
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+
+ /*
+ * Register the saved state.
+ */
+ rc = PDMDevHlpSSMRegister3(pDevIns, RTC_SAVED_STATE_VERSION, sizeof(*pThis), rtcLiveExec, rtcSaveExec, rtcLoadExec);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * Register ourselves as the RTC/CMOS with PDM.
+ */
+ rc = PDMDevHlpRTCRegister(pDevIns, &pThis->RtcReg, &pThis->pRtcHlpR3);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * Register debugger info callback.
+ */
+ PDMDevHlpDBGFInfoRegister(pDevIns, "cmos1", "Display CMOS Bank 1 Info (0x0e-0x7f). No arguments. See also rtc.", rtcCmosBankInfo);
+ PDMDevHlpDBGFInfoRegister(pDevIns, "cmos2", "Display CMOS Bank 2 Info (0x0e-0x7f). No arguments.", rtcCmosBank2Info);
+ PDMDevHlpDBGFInfoRegister(pDevIns, "rtc", "Display CMOS RTC (0x00-0x0d). No arguments. See also cmos1 & cmos2", rtcCmosClockInfo);
+
+ /*
+ * Register statistics.
+ */
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRTCIrq, STAMTYPE_COUNTER, "/TM/RTC/Irq", STAMUNIT_OCCURENCES, "The number of times a RTC interrupt was triggered.");
+ PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRTCTimerCB, STAMTYPE_COUNTER, "/TM/RTC/TimerCB", STAMUNIT_OCCURENCES, "The number of times the RTC timer callback ran.");
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * The device registration structure.
+ */
+const PDMDEVREG g_DeviceMC146818 =
+{
+ /* u32Version */
+ PDM_DEVREG_VERSION,
+ /* szName */
+ "mc146818",
+ /* szRCMod */
+ "VBoxDDRC.rc",
+ /* szR0Mod */
+ "VBoxDDR0.r0",
+ /* pszDescription */
+ "Motorola MC146818 RTC/CMOS Device.",
+ /* fFlags */
+ PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36 | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
+ /* fClass */
+ PDM_DEVREG_CLASS_RTC,
+ /* cMaxInstances */
+ 1,
+ /* cbInstance */
+ sizeof(RTCSTATE),
+ /* pfnConstruct */
+ rtcConstruct,
+ /* pfnDestruct */
+ NULL,
+ /* pfnRelocate */
+ rtcRelocate,
+ /* pfnMemSetup */
+ NULL,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ rtcReset,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnAttach */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnQueryInterface */
+ NULL,
+ /* pfnInitComplete */
+ rtcInitComplete,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32VersionEnd */
+ PDM_DEVREG_VERSION
+};
+
+#endif /* IN_RING3 */
+#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
+
diff --git a/src/VBox/Devices/PC/DrvACPI.cpp b/src/VBox/Devices/PC/DrvACPI.cpp
new file mode 100644
index 00000000..21317a13
--- /dev/null
+++ b/src/VBox/Devices/PC/DrvACPI.cpp
@@ -0,0 +1,1087 @@
+/* $Id: DrvACPI.cpp $ */
+/** @file
+ * DrvACPI - ACPI Host Driver.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DRV_ACPI
+
+#ifdef RT_OS_WINDOWS
+# include <iprt/win/windows.h>
+#endif
+
+#include <VBox/vmm/pdmdrv.h>
+#include <VBox/log.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/uuid.h>
+
+#ifdef RT_OS_LINUX
+# include <iprt/critsect.h>
+# include <iprt/dir.h>
+# include <iprt/semaphore.h>
+# include <iprt/stream.h>
+#endif
+
+#ifdef RT_OS_DARWIN
+# include <Carbon/Carbon.h>
+# include <IOKit/ps/IOPowerSources.h>
+# include <IOKit/ps/IOPSKeys.h>
+# undef PVM /* This still messed up in the 10.9 SDK. Sigh. */
+#endif
+
+#ifdef RT_OS_FREEBSD
+# include <sys/ioctl.h>
+# include <dev/acpica/acpiio.h>
+# include <sys/types.h>
+# include <sys/sysctl.h>
+# include <stdio.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <unistd.h>
+#endif
+
+#include "VBoxDD.h"
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * ACPI driver instance data.
+ *
+ * @implements PDMIACPICONNECTOR
+ */
+typedef struct DRVACPI
+{
+ /** The ACPI interface. */
+ PDMIACPICONNECTOR IACPIConnector;
+ /** The ACPI port interface. */
+ PPDMIACPIPORT pPort;
+ /** Pointer to the driver instance. */
+ PPDMDRVINS pDrvIns;
+
+#ifdef RT_OS_LINUX
+ /** The current power source. */
+ PDMACPIPOWERSOURCE enmPowerSource;
+ /** true = one or more batteries preset, false = no battery present. */
+ bool fBatteryPresent;
+ /** No need to RTThreadPoke the poller when set. */
+ bool volatile fDontPokePoller;
+ /** Remaining battery capacity. */
+ PDMACPIBATCAPACITY enmBatteryRemainingCapacity;
+ /** Battery state. */
+ PDMACPIBATSTATE enmBatteryState;
+ /** Preset battery charging/discharging rate. */
+ uint32_t u32BatteryPresentRate;
+ /** The poller thread. */
+ PPDMTHREAD pPollerThread;
+ /** Synchronize access to the above fields.
+ * XXX A spinlock is probably cheaper ... */
+ RTCRITSECT CritSect;
+ /** Event semaphore the poller thread is sleeping on. */
+ RTSEMEVENT hPollerSleepEvent;
+#endif
+
+} DRVACPI, *PDRVACPI;
+
+
+/**
+ * @interface_method_impl{PDMIBASE,pfnQueryInterface}
+ */
+static DECLCALLBACK(void *) drvACPIQueryInterface(PPDMIBASE pInterface, const char *pszIID)
+{
+ PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
+ PDRVACPI pThis = PDMINS_2_DATA(pDrvIns, PDRVACPI);
+
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIACPICONNECTOR, &pThis->IACPIConnector);
+ return NULL;
+}
+
+/**
+ * Get the current power source of the host system.
+ *
+ * @returns status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pPowerSource Pointer to the power source result variable.
+ */
+static DECLCALLBACK(int) drvACPIQueryPowerSource(PPDMIACPICONNECTOR pInterface,
+ PDMACPIPOWERSOURCE *pPowerSource)
+{
+#if defined(RT_OS_WINDOWS)
+ RT_NOREF(pInterface);
+ SYSTEM_POWER_STATUS powerStatus;
+ if (GetSystemPowerStatus(&powerStatus))
+ {
+ /* running on battery? */
+ if ( powerStatus.ACLineStatus == 0 /* Offline */
+ || powerStatus.ACLineStatus == 255 /* Unknown */
+ && (powerStatus.BatteryFlag & 15) /* high | low | critical | charging */
+ ) /** @todo why is 'charging' included in the flag test? Add parenthesis around the right bits so the code is clearer. */
+ {
+ *pPowerSource = PDM_ACPI_POWER_SOURCE_BATTERY;
+ }
+ /* running on AC link? */
+ else if (powerStatus.ACLineStatus == 1)
+ {
+ *pPowerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
+ }
+ else
+ /* what the hell we're running on? */
+ {
+ *pPowerSource = PDM_ACPI_POWER_SOURCE_UNKNOWN;
+ }
+ }
+ else
+ {
+ AssertMsgFailed(("Could not determine system power status, error: 0x%x\n",
+ GetLastError()));
+ *pPowerSource = PDM_ACPI_POWER_SOURCE_UNKNOWN;
+ }
+
+#elif defined (RT_OS_LINUX)
+ PDRVACPI pThis = RT_FROM_MEMBER(pInterface, DRVACPI, IACPIConnector);
+ RTCritSectEnter(&pThis->CritSect);
+ *pPowerSource = pThis->enmPowerSource;
+ RTCritSectLeave(&pThis->CritSect);
+
+#elif defined (RT_OS_DARWIN)
+ RT_NOREF(pInterface);
+ *pPowerSource = PDM_ACPI_POWER_SOURCE_UNKNOWN;
+
+ CFTypeRef pBlob = IOPSCopyPowerSourcesInfo();
+ CFArrayRef pSources = IOPSCopyPowerSourcesList(pBlob);
+
+ CFDictionaryRef pSource = NULL;
+ const void *psValue;
+ bool fResult;
+
+ if (CFArrayGetCount(pSources) > 0)
+ {
+ for (int i = 0; i < CFArrayGetCount(pSources); ++i)
+ {
+ pSource = IOPSGetPowerSourceDescription(pBlob, CFArrayGetValueAtIndex(pSources, i));
+ /* If the source is empty skip over to the next one. */
+ if(!pSource)
+ continue;
+ /* Skip all power sources which are currently not present like a
+ * second battery. */
+ if (CFDictionaryGetValue(pSource, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse)
+ continue;
+ /* Only internal power types are of interest. */
+ fResult = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTransportTypeKey), &psValue);
+ if ( fResult
+ && CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSInternalType), 0) == kCFCompareEqualTo)
+ {
+ /* Check which power source we are connect on. */
+ fResult = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSPowerSourceStateKey), &psValue);
+ if ( fResult
+ && CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo)
+ *pPowerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
+ else if ( fResult
+ && CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo)
+ *pPowerSource = PDM_ACPI_POWER_SOURCE_BATTERY;
+ }
+ }
+ }
+ CFRelease(pBlob);
+ CFRelease(pSources);
+
+#elif defined(RT_OS_FREEBSD)
+ RT_NOREF(pInterface);
+ int fAcLine = 0;
+ size_t cbParameter = sizeof(fAcLine);
+
+ int rc = sysctlbyname("hw.acpi.acline", &fAcLine, &cbParameter, NULL, 0);
+
+ if (!rc)
+ {
+ if (fAcLine == 1)
+ *pPowerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
+ else if (fAcLine == 0)
+ *pPowerSource = PDM_ACPI_POWER_SOURCE_BATTERY;
+ else
+ *pPowerSource = PDM_ACPI_POWER_SOURCE_UNKNOWN;
+ }
+ else
+ {
+ AssertMsg(errno == ENOENT, ("rc=%d (%s)\n", rc, strerror(errno)));
+ *pPowerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
+ }
+#else /* !RT_OS_FREEBSD either - what could this be? */
+ RT_NOREF(pInterface);
+ *pPowerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
+
+#endif /* !RT_OS_FREEBSD */
+ return VINF_SUCCESS;
+}
+
+/**
+ * @interface_method_impl{PDMIACPICONNECTOR,pfnQueryBatteryStatus}
+ */
+static DECLCALLBACK(int) drvACPIQueryBatteryStatus(PPDMIACPICONNECTOR pInterface, bool *pfPresent,
+ PPDMACPIBATCAPACITY penmRemainingCapacity,
+ PPDMACPIBATSTATE penmBatteryState,
+ uint32_t *pu32PresentRate)
+{
+ /* default return values for all architectures */
+ *pfPresent = false; /* no battery present */
+ *penmBatteryState = PDM_ACPI_BAT_STATE_CHARGED;
+ *penmRemainingCapacity = PDM_ACPI_BAT_CAPACITY_UNKNOWN;
+ *pu32PresentRate = UINT32_MAX; /* present rate is unknown */
+
+#if defined(RT_OS_WINDOWS)
+ RT_NOREF(pInterface);
+ SYSTEM_POWER_STATUS powerStatus;
+ if (GetSystemPowerStatus(&powerStatus))
+ {
+ /* 128 means no battery present */
+ *pfPresent = !(powerStatus.BatteryFlag & 128);
+ /* just forward the value directly */
+ *penmRemainingCapacity = (PDMACPIBATCAPACITY)powerStatus.BatteryLifePercent;
+ /* we assume that we are discharging the battery if we are not on-line and
+ * not charge the battery */
+ uint32_t uBs = PDM_ACPI_BAT_STATE_CHARGED;
+ if (powerStatus.BatteryFlag & 8)
+ uBs = PDM_ACPI_BAT_STATE_CHARGING;
+ else if (powerStatus.ACLineStatus == 0 || powerStatus.ACLineStatus == 255)
+ uBs = PDM_ACPI_BAT_STATE_DISCHARGING;
+ if (powerStatus.BatteryFlag & 4)
+ uBs |= PDM_ACPI_BAT_STATE_CRITICAL;
+ *penmBatteryState = (PDMACPIBATSTATE)uBs;
+ /* on Windows it is difficult to request the present charging/discharging rate */
+ }
+ else
+ {
+ AssertMsgFailed(("Could not determine system power status, error: 0x%x\n",
+ GetLastError()));
+ }
+
+#elif defined(RT_OS_LINUX)
+ PDRVACPI pThis = RT_FROM_MEMBER(pInterface, DRVACPI, IACPIConnector);
+ RTCritSectEnter(&pThis->CritSect);
+ *pfPresent = pThis->fBatteryPresent;
+ *penmRemainingCapacity = pThis->enmBatteryRemainingCapacity;
+ *penmBatteryState = pThis->enmBatteryState;
+ *pu32PresentRate = pThis->u32BatteryPresentRate;
+ RTCritSectLeave(&pThis->CritSect);
+
+#elif defined(RT_OS_DARWIN)
+ RT_NOREF(pInterface);
+ CFTypeRef pBlob = IOPSCopyPowerSourcesInfo();
+ CFArrayRef pSources = IOPSCopyPowerSourcesList(pBlob);
+
+ CFDictionaryRef pSource = NULL;
+ const void *psValue;
+ bool fResult;
+
+ if (CFArrayGetCount(pSources) > 0)
+ {
+ for (int i = 0; i < CFArrayGetCount(pSources); ++i)
+ {
+ pSource = IOPSGetPowerSourceDescription(pBlob, CFArrayGetValueAtIndex(pSources, i));
+ /* If the source is empty skip over to the next one. */
+ if(!pSource)
+ continue;
+ /* Skip all power sources which are currently not present like a
+ * second battery. */
+ if (CFDictionaryGetValue(pSource, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse)
+ continue;
+ /* Only internal power types are of interest. */
+ fResult = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTransportTypeKey), &psValue);
+ if ( fResult
+ && CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSInternalType), 0) == kCFCompareEqualTo)
+ {
+ PDMACPIPOWERSOURCE powerSource = PDM_ACPI_POWER_SOURCE_UNKNOWN;
+ /* First check which power source we are connect on. */
+ fResult = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSPowerSourceStateKey), &psValue);
+ if ( fResult
+ && CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo)
+ powerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
+ else if ( fResult
+ && CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo)
+ powerSource = PDM_ACPI_POWER_SOURCE_BATTERY;
+
+ /* At this point the power source is present. */
+ *pfPresent = true;
+ *penmBatteryState = PDM_ACPI_BAT_STATE_CHARGED;
+
+ int curCapacity = 0;
+ int maxCapacity = 1;
+ float remCapacity = 0.0f;
+
+ /* Fetch the current capacity value of the power source */
+ fResult = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSCurrentCapacityKey), &psValue);
+ if (fResult)
+ CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &curCapacity);
+ /* Fetch the maximum capacity value of the power source */
+ fResult = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSMaxCapacityKey), &psValue);
+ if (fResult)
+ CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &maxCapacity);
+
+ /* Calculate the remaining capacity in percent */
+ remCapacity = ((float)curCapacity/(float)maxCapacity * PDM_ACPI_BAT_CAPACITY_MAX);
+ *penmRemainingCapacity = (PDMACPIBATCAPACITY)remCapacity;
+
+ if (powerSource == PDM_ACPI_POWER_SOURCE_BATTERY)
+ {
+ /* If we are on battery power we are discharging in every
+ * case */
+ *penmBatteryState = PDM_ACPI_BAT_STATE_DISCHARGING;
+ int timeToEmpty = -1;
+ /* Get the time till the battery source will be empty */
+ fResult = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTimeToEmptyKey), &psValue);
+ if (fResult)
+ CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &timeToEmpty);
+ if (timeToEmpty != -1)
+ /* 0...1000 */
+ *pu32PresentRate = (uint32_t)roundf((remCapacity / ((float)timeToEmpty/60.0)) * 10.0);
+ }
+
+ if ( powerSource == PDM_ACPI_POWER_SOURCE_OUTLET
+ && CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSIsChargingKey), &psValue))
+ {
+ /* We are running on an AC power source, but we also have a
+ * battery power source present. */
+ if (CFBooleanGetValue((CFBooleanRef)psValue) > 0)
+ {
+ /* This means charging. */
+ *penmBatteryState = PDM_ACPI_BAT_STATE_CHARGING;
+ int timeToFull = -1;
+ /* Get the time till the battery source will be charged */
+ fResult = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTimeToFullChargeKey), &psValue);
+ if (fResult)
+ CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &timeToFull);
+ if (timeToFull != -1)
+ /* 0...1000 */
+ *pu32PresentRate = (uint32_t)roundf((100.0-(float)remCapacity) / ((float)timeToFull/60.0)) * 10.0;
+ }
+ }
+
+ /* Check for critical */
+ int criticalValue = 20;
+ fResult = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSDeadWarnLevelKey), &psValue);
+ if (fResult)
+ CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &criticalValue);
+ if (remCapacity < criticalValue)
+ *penmBatteryState = (PDMACPIBATSTATE)(*penmBatteryState | PDM_ACPI_BAT_STATE_CRITICAL);
+ }
+ }
+ }
+ CFRelease(pBlob);
+ CFRelease(pSources);
+
+#elif defined(RT_OS_FREEBSD)
+ RT_NOREF(pInterface);
+ /* We try to use /dev/acpi first and if that fails use the sysctls. */
+ bool fSuccess = true;
+ int FileAcpi = 0;
+ int rc = 0;
+
+ FileAcpi = open("/dev/acpi", O_RDONLY);
+ if (FileAcpi != -1)
+ {
+ bool fMilliWatt;
+ union acpi_battery_ioctl_arg BatteryIo;
+
+ memset(&BatteryIo, 0, sizeof(BatteryIo));
+ BatteryIo.unit = 0; /* Always use the first battery. */
+
+ /* Determine the power units first. */
+ if (ioctl(FileAcpi, ACPIIO_BATT_GET_BIF, &BatteryIo) == -1)
+ fSuccess = false;
+ else
+ {
+ if (BatteryIo.bif.units == ACPI_BIF_UNITS_MW)
+ fMilliWatt = true;
+ else
+ fMilliWatt = false; /* mA */
+
+ BatteryIo.unit = 0;
+ if (ioctl(FileAcpi, ACPIIO_BATT_GET_BATTINFO, &BatteryIo) == -1)
+ fSuccess = false;
+ else
+ {
+ if ((BatteryIo.battinfo.state & ACPI_BATT_STAT_NOT_PRESENT) == ACPI_BATT_STAT_NOT_PRESENT)
+ *pfPresent = false;
+ else
+ {
+ *pfPresent = true;
+
+ if (BatteryIo.battinfo.state & ACPI_BATT_STAT_DISCHARG)
+ *penmBatteryState = PDM_ACPI_BAT_STATE_DISCHARGING;
+ else if (BatteryIo.battinfo.state & ACPI_BATT_STAT_CHARGING)
+ *penmBatteryState = PDM_ACPI_BAT_STATE_CHARGING;
+ else
+ *penmBatteryState = PDM_ACPI_BAT_STATE_CHARGED;
+
+ if (BatteryIo.battinfo.state & ACPI_BATT_STAT_CRITICAL)
+ *penmBatteryState = (PDMACPIBATSTATE)(*penmBatteryState | PDM_ACPI_BAT_STATE_CRITICAL);
+ }
+
+ if (BatteryIo.battinfo.cap != -1)
+ *penmRemainingCapacity = (PDMACPIBATCAPACITY)BatteryIo.battinfo.cap;
+
+ BatteryIo.unit = 0;
+ if (ioctl(FileAcpi, ACPIIO_BATT_GET_BST, &BatteryIo) == 0)
+ {
+ /* The rate can be either mW or mA but the ACPI device wants mW. */
+ if (BatteryIo.bst.rate != 0xffffffff)
+ {
+ if (fMilliWatt)
+ *pu32PresentRate = BatteryIo.bst.rate;
+ else if (BatteryIo.bst.volt != 0xffffffff)
+ {
+ /*
+ * The rate is in mA so we have to convert it.
+ * The current power rate can be calculated with P = U * I
+ */
+ *pu32PresentRate = (uint32_t)( ( ((float)BatteryIo.bst.volt/1000.0)
+ * ((float)BatteryIo.bst.rate/1000.0))
+ * 1000.0);
+ }
+ }
+ }
+ }
+ }
+
+ close(FileAcpi);
+ }
+ else
+ fSuccess = false;
+
+ if (!fSuccess)
+ {
+ int fBatteryState = 0;
+ size_t cbParameter = sizeof(fBatteryState);
+
+ rc = sysctlbyname("hw.acpi.battery.state", &fBatteryState, &cbParameter, NULL, 0);
+ if (!rc)
+ {
+ if ((fBatteryState & ACPI_BATT_STAT_NOT_PRESENT) == ACPI_BATT_STAT_NOT_PRESENT)
+ *pfPresent = false;
+ else
+ {
+ *pfPresent = true;
+
+ if (fBatteryState & ACPI_BATT_STAT_DISCHARG)
+ *penmBatteryState = PDM_ACPI_BAT_STATE_DISCHARGING;
+ else if (fBatteryState & ACPI_BATT_STAT_CHARGING)
+ *penmBatteryState = PDM_ACPI_BAT_STATE_CHARGING;
+ else
+ *penmBatteryState = PDM_ACPI_BAT_STATE_CHARGED;
+
+ if (fBatteryState & ACPI_BATT_STAT_CRITICAL)
+ *penmBatteryState = (PDMACPIBATSTATE)(*penmBatteryState | PDM_ACPI_BAT_STATE_CRITICAL);
+
+ /* Get battery level. */
+ int curCapacity = 0;
+ cbParameter = sizeof(curCapacity);
+ rc = sysctlbyname("hw.acpi.battery.life", &curCapacity, &cbParameter, NULL, 0);
+ if (!rc && curCapacity >= 0)
+ *penmRemainingCapacity = (PDMACPIBATCAPACITY)curCapacity;
+
+ /* The rate can't be determined with sysctls. */
+ }
+ }
+ }
+
+#endif /* RT_OS_FREEBSD */
+
+ return VINF_SUCCESS;
+}
+
+#ifdef RT_OS_LINUX
+/**
+ * Poller thread for /proc/acpi status files.
+ *
+ * Reading these files takes ages (several seconds) on some hosts, therefore
+ * start this thread. The termination of this thread may take some seconds
+ * on such a hosts!
+ *
+ * @param pDrvIns The driver instance data.
+ * @param pThread The thread.
+ */
+static DECLCALLBACK(int) drvACPIPoller(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
+{
+ PDRVACPI pThis = PDMINS_2_DATA(pDrvIns, PDRVACPI);
+
+ if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
+ return VINF_SUCCESS;
+
+ while (pThread->enmState == PDMTHREADSTATE_RUNNING)
+ {
+ ASMAtomicWriteBool(&pThis->fDontPokePoller, false);
+
+ PDMACPIPOWERSOURCE enmPowerSource = PDM_ACPI_POWER_SOURCE_UNKNOWN;
+ PRTSTREAM pStrmStatus;
+ PRTSTREAM pStrmType;
+ RTDIR hDir = NIL_RTDIR;
+ RTDIRENTRY DirEntry;
+ char szLine[1024];
+ bool fBatteryPresent = false; /* one or more batteries present */
+ bool fCharging = false; /* one or more batteries charging */
+ bool fDischarging = false; /* one or more batteries discharging */
+ bool fCritical = false; /* one or more batteries in critical state */
+ bool fDataChanged; /* if battery status data changed during last poll */
+ int32_t maxCapacityTotal = 0; /* total capacity of all batteries */
+ int32_t currentCapacityTotal = 0; /* total current capacity of all batteries */
+ int32_t presentRateTotal = 0; /* total present (dis)charging rate of all batts */
+ PDMACPIBATCAPACITY enmBatteryRemainingCapacity; /* total remaining capacity of vbox batt */
+ uint32_t u32BatteryPresentRate; /* total present (dis)charging rate of vbox batt */
+
+ int rc = RTDirOpen(&hDir, "/sys/class/power_supply/");
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * The new /sys interface introduced with Linux 2.6.25.
+ */
+ while (pThread->enmState == PDMTHREADSTATE_RUNNING)
+ {
+ rc = RTDirRead(hDir, &DirEntry, NULL);
+ if (RT_FAILURE(rc))
+ break;
+ if ( strcmp(DirEntry.szName, ".") == 0
+ || strcmp(DirEntry.szName, "..") == 0)
+ continue;
+#define POWER_OPEN(s, n) RTStrmOpenF("r", s, "/sys/class/power_supply/%s/" n, DirEntry.szName)
+ rc = POWER_OPEN(&pStrmType, "type");
+ if (RT_FAILURE(rc))
+ continue;
+ rc = RTStrmGetLine(pStrmType, szLine, sizeof(szLine));
+ if (RT_SUCCESS(rc))
+ {
+ if (strcmp(szLine, "Mains") == 0)
+ {
+ /* AC adapter */
+ rc = POWER_OPEN(&pStrmStatus, "online");
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTStrmGetLine(pStrmStatus, szLine, sizeof(szLine));
+ if ( RT_SUCCESS(rc)
+ && strcmp(szLine, "1") == 0)
+ enmPowerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
+ else
+ enmPowerSource = PDM_ACPI_POWER_SOURCE_BATTERY;
+ RTStrmClose(pStrmStatus);
+ }
+ }
+ else if (strcmp(szLine, "Battery") == 0)
+ {
+ /* Battery */
+ rc = POWER_OPEN(&pStrmStatus, "present");
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTStrmGetLine(pStrmStatus, szLine, sizeof(szLine));
+ RTStrmClose(pStrmStatus);
+ if ( RT_SUCCESS(rc)
+ && strcmp(szLine, "1") == 0)
+ {
+ fBatteryPresent = true;
+ rc = RTStrmOpenF("r", &pStrmStatus,
+ "/sys/class/power_supply/%s/status", DirEntry.szName);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTStrmGetLine(pStrmStatus, szLine, sizeof(szLine));
+ if (RT_SUCCESS(rc))
+ {
+ if (strcmp(szLine, "Discharging") == 0)
+ fDischarging = true;
+ else if (strcmp(szLine, "Charging") == 0)
+ fCharging = true;
+ }
+ RTStrmClose(pStrmStatus);
+ }
+ rc = POWER_OPEN(&pStrmStatus, "capacity_level");
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTStrmGetLine(pStrmStatus, szLine, sizeof(szLine));
+ if ( RT_SUCCESS(rc)
+ && strcmp(szLine, "Critical") == 0)
+ fCritical = true;
+ RTStrmClose(pStrmStatus);
+ }
+ rc = POWER_OPEN(&pStrmStatus, "energy_full");
+ if (RT_FAILURE(rc))
+ rc = POWER_OPEN(&pStrmStatus, "charge_full");
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTStrmGetLine(pStrmStatus, szLine, sizeof(szLine));
+ if (RT_SUCCESS(rc))
+ {
+ int32_t maxCapacity = 0;
+ rc = RTStrToInt32Full(szLine, 0, &maxCapacity);
+ if ( RT_SUCCESS(rc)
+ && maxCapacity > 0)
+ maxCapacityTotal += maxCapacity;
+ }
+ RTStrmClose(pStrmStatus);
+ }
+ rc = POWER_OPEN(&pStrmStatus, "energy_now");
+ if (RT_FAILURE(rc))
+ rc = POWER_OPEN(&pStrmStatus, "charge_now");
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTStrmGetLine(pStrmStatus, szLine, sizeof(szLine));
+ if (RT_SUCCESS(rc))
+ {
+ int32_t currentCapacity = 0;
+ rc = RTStrToInt32Full(szLine, 0, &currentCapacity);
+ if ( RT_SUCCESS(rc)
+ && currentCapacity > 0)
+ currentCapacityTotal += currentCapacity;
+ }
+ RTStrmClose(pStrmStatus);
+ }
+ rc = POWER_OPEN(&pStrmStatus, "power_now");
+ if (RT_FAILURE(rc))
+ rc = POWER_OPEN(&pStrmStatus, "current_now");
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTStrmGetLine(pStrmStatus, szLine, sizeof(szLine));
+ if (RT_SUCCESS(rc))
+ {
+ int32_t presentRate = 0;
+ rc = RTStrToInt32Full(szLine, 0, &presentRate);
+ if ( RT_SUCCESS(rc)
+ && presentRate > 0)
+ {
+ if (fDischarging)
+ presentRateTotal -= presentRate;
+ else
+ presentRateTotal += presentRate;
+ }
+ }
+ RTStrmClose(pStrmStatus);
+ }
+ }
+ }
+ }
+ }
+ RTStrmClose(pStrmType);
+#undef POWER_OPEN
+ }
+ RTDirClose(hDir);
+ }
+ else /* !/sys */
+ {
+ /*
+ * The old /proc/acpi interface
+ */
+ /*
+ * Read the status of the powerline-adapter.
+ */
+ rc = RTDirOpen(&hDir, "/proc/acpi/ac_adapter/");
+ if (RT_SUCCESS(rc))
+ {
+#define POWER_OPEN(s, n) RTStrmOpenF("r", s, "/proc/acpi/ac_adapter/%s/" n, DirEntry.szName)
+ while (pThread->enmState == PDMTHREADSTATE_RUNNING)
+ {
+ rc = RTDirRead(hDir, &DirEntry, NULL);
+ if (RT_FAILURE(rc))
+ break;
+ if ( strcmp(DirEntry.szName, ".") == 0
+ || strcmp(DirEntry.szName, "..") == 0)
+ continue;
+ rc = POWER_OPEN(&pStrmStatus, "status");
+ if (RT_FAILURE(rc))
+ rc = POWER_OPEN(&pStrmStatus, "state");
+ if (RT_SUCCESS(rc))
+ {
+ while (pThread->enmState == PDMTHREADSTATE_RUNNING)
+ {
+ rc = RTStrmGetLine(pStrmStatus, szLine, sizeof(szLine));
+ if (RT_FAILURE(rc))
+ break;
+ if ( strstr(szLine, "Status:") != NULL
+ || strstr(szLine, "state:") != NULL)
+ {
+ if (strstr(szLine, "on-line") != NULL)
+ enmPowerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
+ else
+ enmPowerSource = PDM_ACPI_POWER_SOURCE_BATTERY;
+ break;
+ }
+ }
+ RTStrmClose(pStrmStatus);
+ break;
+ }
+ }
+ RTDirClose(hDir);
+#undef POWER_OPEN
+ }
+
+ /*
+ * Read the status of all batteries and collect it into one.
+ */
+ rc = RTDirOpen(&hDir, "/proc/acpi/battery/");
+ if (RT_SUCCESS(rc))
+ {
+#define POWER_OPEN(s, n) RTStrmOpenF("r", s, "/proc/acpi/battery/%s/" n, DirEntry.szName)
+ bool fThisBatteryPresent = false;
+ bool fThisDischarging = false;
+
+ while (pThread->enmState == PDMTHREADSTATE_RUNNING)
+ {
+ rc = RTDirRead(hDir, &DirEntry, NULL);
+ if (RT_FAILURE(rc))
+ break;
+ if ( strcmp(DirEntry.szName, ".") == 0
+ || strcmp(DirEntry.szName, "..") == 0)
+ continue;
+
+ rc = POWER_OPEN(&pStrmStatus, "status");
+ /* there is a 2nd variant of that file */
+ if (RT_FAILURE(rc))
+ rc = POWER_OPEN(&pStrmStatus, "state");
+ if (RT_FAILURE(rc))
+ continue;
+
+ PRTSTREAM pStrmInfo;
+ rc = POWER_OPEN(&pStrmInfo, "info");
+ if (RT_FAILURE(rc))
+ {
+ RTStrmClose(pStrmStatus);
+ continue;
+ }
+
+ /* get 'present' status from the info file */
+ while (pThread->enmState == PDMTHREADSTATE_RUNNING)
+ {
+ rc = RTStrmGetLine(pStrmInfo, szLine, sizeof(szLine));
+ if (RT_FAILURE(rc))
+ break;
+ if (strstr(szLine, "present:") != NULL)
+ {
+ if (strstr(szLine, "yes") != NULL)
+ {
+ fThisBatteryPresent = true;
+ break;
+ }
+ }
+ }
+
+ if (fThisBatteryPresent)
+ {
+ fBatteryPresent = true;
+ RTStrmRewind(pStrmInfo);
+
+ /* get the maximum capacity from the info file */
+ while (pThread->enmState == PDMTHREADSTATE_RUNNING)
+ {
+ rc = RTStrmGetLine(pStrmInfo, szLine, sizeof(szLine));
+ if (RT_FAILURE(rc))
+ break;
+ if (strstr(szLine, "last full capacity:") != NULL)
+ {
+ char *psz;
+ int32_t maxCapacity = 0;
+ rc = RTStrToInt32Ex(RTStrStripL(&szLine[19]), &psz, 0, &maxCapacity);
+ if (RT_FAILURE(rc))
+ maxCapacity = 0;
+ maxCapacityTotal += maxCapacity;
+ break;
+ }
+ }
+
+ /* get the current capacity/state from the status file */
+ int32_t presentRate = 0;
+ bool fGotRemainingCapacity = false;
+ bool fGotBatteryState = false;
+ bool fGotCapacityState = false;
+ bool fGotPresentRate = false;
+ while ( ( !fGotRemainingCapacity
+ || !fGotBatteryState
+ || !fGotCapacityState
+ || !fGotPresentRate)
+ && pThread->enmState == PDMTHREADSTATE_RUNNING)
+ {
+ rc = RTStrmGetLine(pStrmStatus, szLine, sizeof(szLine));
+ if (RT_FAILURE(rc))
+ break;
+ if (strstr(szLine, "remaining capacity:") != NULL)
+ {
+ char *psz;
+ int32_t currentCapacity = 0;
+ rc = RTStrToInt32Ex(RTStrStripL(&szLine[19]), &psz, 0, &currentCapacity);
+ if ( RT_SUCCESS(rc)
+ && currentCapacity > 0)
+ currentCapacityTotal += currentCapacity;
+ fGotRemainingCapacity = true;
+ }
+ else if (strstr(szLine, "charging state:") != NULL)
+ {
+ if (strstr(szLine + 15, "discharging") != NULL)
+ {
+ fDischarging = true;
+ fThisDischarging = true;
+ }
+ else if (strstr(szLine + 15, "charging") != NULL)
+ fCharging = true;
+ fGotBatteryState = true;
+ }
+ else if (strstr(szLine, "capacity state:") != NULL)
+ {
+ if (strstr(szLine + 15, "critical") != NULL)
+ fCritical = true;
+ fGotCapacityState = true;
+ }
+ if (strstr(szLine, "present rate:") != NULL)
+ {
+ char *psz;
+ rc = RTStrToInt32Ex(RTStrStripL(&szLine[13]), &psz, 0, &presentRate);
+ if (RT_FAILURE(rc))
+ presentRate = 0;
+ fGotPresentRate = true;
+ }
+ }
+ if (fThisDischarging)
+ presentRateTotal -= presentRate;
+ else
+ presentRateTotal += presentRate;
+ }
+ RTStrmClose(pStrmStatus);
+ RTStrmClose(pStrmInfo);
+ }
+ RTDirClose(hDir);
+#undef POWER_OPEN
+ }
+ } /* /proc/acpi */
+
+ /* atomic update of the state */
+ RTCritSectEnter(&pThis->CritSect);
+
+ /* charging/discharging bits are mutual exclusive */
+ uint32_t uBs = PDM_ACPI_BAT_STATE_CHARGED;
+ if (fDischarging)
+ uBs = PDM_ACPI_BAT_STATE_DISCHARGING;
+ else if (fCharging)
+ uBs = PDM_ACPI_BAT_STATE_CHARGING;
+ if (fCritical)
+ uBs |= PDM_ACPI_BAT_STATE_CRITICAL;
+
+ if (maxCapacityTotal > 0 && currentCapacityTotal > 0)
+ {
+ if (presentRateTotal < 0)
+ presentRateTotal = -presentRateTotal;
+
+ /* calculate the percentage */
+
+ enmBatteryRemainingCapacity =
+ (PDMACPIBATCAPACITY)( ( (float)currentCapacityTotal
+ / (float)maxCapacityTotal)
+ * PDM_ACPI_BAT_CAPACITY_MAX);
+ u32BatteryPresentRate =
+ (uint32_t)(( (float)presentRateTotal
+ / (float)maxCapacityTotal) * 1000);
+ }
+ else
+ {
+ /* unknown capacity / state */
+ enmBatteryRemainingCapacity = PDM_ACPI_BAT_CAPACITY_UNKNOWN;
+ u32BatteryPresentRate = ~0;
+ }
+
+ if ( pThis->enmPowerSource == enmPowerSource
+ && pThis->fBatteryPresent == fBatteryPresent
+ && pThis->enmBatteryState == (PDMACPIBATSTATE) uBs
+ && pThis->enmBatteryRemainingCapacity == enmBatteryRemainingCapacity
+ && pThis->u32BatteryPresentRate == u32BatteryPresentRate)
+ {
+ fDataChanged = false;
+ }
+ else
+ {
+ fDataChanged = true;
+
+ pThis->enmPowerSource = enmPowerSource;
+ pThis->fBatteryPresent = fBatteryPresent;
+ pThis->enmBatteryState = (PDMACPIBATSTATE)uBs;
+ pThis->enmBatteryRemainingCapacity = enmBatteryRemainingCapacity;
+ pThis->u32BatteryPresentRate = u32BatteryPresentRate;
+ }
+
+ RTCritSectLeave(&pThis->CritSect);
+
+ if (fDataChanged)
+ pThis->pPort->pfnBatteryStatusChangeEvent(pThis->pPort);
+
+ /* wait a bit (e.g. Ubuntu/GNOME polls every 30 seconds) */
+ ASMAtomicWriteBool(&pThis->fDontPokePoller, true);
+ rc = RTSemEventWait(pThis->hPollerSleepEvent, 20000);
+ }
+
+ return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) drvACPIPollerWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
+{
+ PDRVACPI pThis = PDMINS_2_DATA(pDrvIns, PDRVACPI);
+
+ RTSemEventSignal(pThis->hPollerSleepEvent);
+ if (!ASMAtomicReadBool(&pThis->fDontPokePoller))
+ RTThreadPoke(pThread->Thread);
+ return VINF_SUCCESS;
+}
+#endif /* RT_OS_LINUX */
+
+
+/**
+ * Destruct a driver instance.
+ *
+ * Most VM resources are freed by the VM. This callback is provided so that any non-VM
+ * resources can be freed correctly.
+ *
+ * @param pDrvIns The driver instance data.
+ */
+static DECLCALLBACK(void) drvACPIDestruct(PPDMDRVINS pDrvIns)
+{
+ LogFlow(("drvACPIDestruct\n"));
+ PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
+
+#ifdef RT_OS_LINUX
+ PDRVACPI pThis = PDMINS_2_DATA(pDrvIns, PDRVACPI);
+ if (pThis->hPollerSleepEvent != NIL_RTSEMEVENT)
+ {
+ RTSemEventDestroy(pThis->hPollerSleepEvent);
+ pThis->hPollerSleepEvent = NIL_RTSEMEVENT;
+ }
+ RTCritSectDelete(&pThis->CritSect);
+#endif
+}
+
+/**
+ * Construct an ACPI driver instance.
+ *
+ * @copydoc FNPDMDRVCONSTRUCT
+ */
+static DECLCALLBACK(int) drvACPIConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
+{
+ RT_NOREF(fFlags);
+ PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
+ PDRVACPI pThis = PDMINS_2_DATA(pDrvIns, PDRVACPI);
+ int rc = VINF_SUCCESS;
+
+ /*
+ * Init the static parts.
+ */
+ pThis->pDrvIns = pDrvIns;
+#ifdef RT_OS_LINUX
+ pThis->hPollerSleepEvent = NIL_RTSEMEVENT;
+#endif
+ /* IBase */
+ pDrvIns->IBase.pfnQueryInterface = drvACPIQueryInterface;
+ /* IACPIConnector */
+ pThis->IACPIConnector.pfnQueryPowerSource = drvACPIQueryPowerSource;
+ pThis->IACPIConnector.pfnQueryBatteryStatus = drvACPIQueryBatteryStatus;
+
+ /*
+ * Validate the config.
+ */
+ if (!CFGMR3AreValuesValid(pCfg, "\0"))
+ return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
+
+ /*
+ * Check that no-one is attached to us.
+ */
+ AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
+ ("Configuration error: Not possible to attach anything to this driver!\n"),
+ VERR_PDM_DRVINS_NO_ATTACH);
+
+ /*
+ * Query the ACPI port interface.
+ */
+ pThis->pPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIACPIPORT);
+ if (!pThis->pPort)
+ {
+ AssertMsgFailed(("Configuration error: the above device/driver didn't export the ACPI port interface!\n"));
+ return VERR_PDM_MISSING_INTERFACE_ABOVE;
+ }
+
+#ifdef RT_OS_LINUX
+ /*
+ * Start the poller thread.
+ */
+ rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pPollerThread, pThis, drvACPIPoller,
+ drvACPIPollerWakeup, 0, RTTHREADTYPE_INFREQUENT_POLLER, "ACPI Poller");
+ if (RT_FAILURE(rc))
+ return rc;
+
+ rc = RTCritSectInit(&pThis->CritSect);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ rc = RTSemEventCreate(&pThis->hPollerSleepEvent);
+#endif
+
+ return rc;
+}
+
+
+/**
+ * ACPI driver registration record.
+ */
+const PDMDRVREG g_DrvACPI =
+{
+ /* u32Version */
+ PDM_DRVREG_VERSION,
+ /* szName */
+ "ACPIHost",
+ /* szRCMod */
+ "",
+ /* szR0Mod */
+ "",
+ /* pszDescription */
+ "ACPI Host Driver",
+ /* fFlags */
+ PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
+ /* fClass. */
+ PDM_DRVREG_CLASS_ACPI,
+ /* cMaxInstances */
+ ~0U,
+ /* cbInstance */
+ sizeof(DRVACPI),
+ /* pfnConstruct */
+ drvACPIConstruct,
+ /* pfnDestruct */
+ drvACPIDestruct,
+ /* pfnRelocate */
+ NULL,
+ /* pfnIOCtl */
+ NULL,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ NULL,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnAttach */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32EndVersion */
+ PDM_DRVREG_VERSION
+};
diff --git a/src/VBox/Devices/PC/DrvAcpiCpu.cpp b/src/VBox/Devices/PC/DrvAcpiCpu.cpp
new file mode 100644
index 00000000..bd5e429f
--- /dev/null
+++ b/src/VBox/Devices/PC/DrvAcpiCpu.cpp
@@ -0,0 +1,124 @@
+/* $Id: DrvAcpiCpu.cpp $ */
+/** @file
+ * DrvAcpiCpu - ACPI CPU dummy driver for hotplugging.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DRV_ACPI
+
+#include <VBox/vmm/pdmdrv.h>
+#include <VBox/log.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/uuid.h>
+
+#include "VBoxDD.h"
+
+
+/**
+ * @interface_method_impl{PDMIBASE,pfnQueryInterface}
+ */
+static DECLCALLBACK(void *) drvACPICpuQueryInterface(PPDMIBASE pInterface, const char *pszIID)
+{
+ PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
+ return NULL;
+}
+
+/**
+ * Construct an ACPI CPU driver instance.
+ *
+ * @copydoc FNPDMDRVCONSTRUCT
+ */
+static DECLCALLBACK(int) drvACPICpuConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
+{
+ RT_NOREF(fFlags);
+ PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
+
+ /*
+ * Init the static parts.
+ */
+ /* IBase */
+ pDrvIns->IBase.pfnQueryInterface = drvACPICpuQueryInterface;
+
+ /*
+ * Validate the config.
+ */
+ if (!CFGMR3AreValuesValid(pCfg, "\0"))
+ return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
+
+ /*
+ * Check that no-one is attached to us.
+ */
+ AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
+ ("Configuration error: Not possible to attach anything to this driver!\n"),
+ VERR_PDM_DRVINS_NO_ATTACH);
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * ACPI CPU driver registration record.
+ */
+const PDMDRVREG g_DrvAcpiCpu =
+{
+ /* u32Version */
+ PDM_DRVREG_VERSION,
+ /* szName */
+ "ACPICpu",
+ /* szRCMod */
+ "",
+ /* szR0Mod */
+ "",
+ /* pszDescription */
+ "ACPI CPU Driver",
+ /* fFlags */
+ PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
+ /* fClass. */
+ PDM_DRVREG_CLASS_ACPI,
+ /* cMaxInstances */
+ ~0U,
+ /* cbInstance */
+ sizeof(PDMDRVINS),
+ /* pfnConstruct */
+ drvACPICpuConstruct,
+ /* pfnDestruct */
+ NULL,
+ /* pfnRelocate */
+ NULL,
+ /* pfnIOCtl */
+ NULL,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ NULL,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnAttach */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32EndVersion */
+ PDM_DRVREG_VERSION
+};
diff --git a/src/VBox/Devices/PC/Makefile.kup b/src/VBox/Devices/PC/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Devices/PC/Makefile.kup
diff --git a/src/VBox/Devices/PC/ipxe/COPYING b/src/VBox/Devices/PC/ipxe/COPYING
new file mode 100644
index 00000000..a43ea212
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/src/VBox/Devices/PC/ipxe/COPYRIGHTS b/src/VBox/Devices/PC/ipxe/COPYRIGHTS
new file mode 100644
index 00000000..342330bb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/COPYRIGHTS
@@ -0,0 +1,12 @@
+In general iPXE files are licensed under the GPL. For historical
+reasons, individual files may contain their own licence declarations.
+Most builds of iPXE do not contain all iPXE code (in particular, most
+builds will include only one driver), and so the overall licence can
+vary depending on what target you are building.
+
+The resultant applicable licence(s) for any particular build can be
+determined by using "make bin/xxxxxxx.yyy.licence"; for example:
+
+ make bin/rtl8139.rom.licence
+
+to determine the resultant licence(s) for the build bin/rtl8139.rom
diff --git a/src/VBox/Devices/PC/ipxe/Makefile.kmk b/src/VBox/Devices/PC/ipxe/Makefile.kmk
new file mode 100644
index 00000000..7f0b8377
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/Makefile.kmk
@@ -0,0 +1,367 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-makefile for iPXE.
+#
+
+#
+# Copyright (C) 2012-2019 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+SUB_DEPTH = ../../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+#
+# Globals.
+#
+VBOX_PATH_IPXE_SRC := $(PATH_SUB_CURRENT)
+
+
+#
+# iPxeBiosBin - Library containing the iPXE ROM as a data blob.
+# Will be linked into VBoxDD2.
+#
+LIBRARIES += iPxeBiosBin
+iPxeBiosBin_TEMPLATE = VBOXR3
+iPxeBiosBin_DEFS = IN_VBOXDD2
+iPxeBiosBin_SOURCES = $(iPxeBiosBin_0_OUTDIR)/iPxeBiosBin.c
+iPxeBiosBin_CLEAN = \
+ $(iPxeBiosBin_0_OUTDIR)/iPxeBiosBin.c \
+
+if1of ($(KBUILD_TARGET), darwin os2 solaris win)
+ $$(iPxeBiosBin_0_OUTDIR)/iPxeBiosBin.c: $(PATH_SUB_CURRENT)/iPxeBiosBin.rom $(VBOX_BIN2C) | $$(dir $$@)
+ $(call MSG_TOOL,bin2c,iPxeBiosBin,$<,$@)
+ $(QUIET)$(VBOX_BIN2C) -min 32 -max 56 -mask 0x1ff -export NetBiosBinary $< $@
+
+else
+ iPxeBiosBin_CLEAN += \
+ $(iPxeBiosBin_0_OUTDIR)/iPxeBiosBin.rom \
+ $(iPxeBiosBin_0_OUTDIR)/iPxeBaseBin.rom.bin \
+ $(iPxeBiosBin_0_OUTDIR)/iPxeBaseBin.rom.zinfo
+
+ $$(iPxeBiosBin_0_OUTDIR)/iPxeBiosBin.c: $$(iPxeBiosBin_0_OUTDIR)/iPxeBiosBin.rom $(VBOX_BIN2C)
+ $(call MSG_TOOL,bin2c,iPxeBiosBin,$<,$@)
+ $(QUIET)$(VBOX_BIN2C) -min 32 -max 56 -mask 0x1ff -export NetBiosBinary $< $@
+
+
+ $$(iPxeBiosBin_0_OUTDIR)/iPxeBiosBin.rom: \
+ $$(iPxeBaseBin_1_TARGET) \
+ $$(ipxezbin_1_TARGET) \
+ $(VBOX_PATH_IPXE_SRC)/src/util/padimg.pl \
+ $(VBOX_PATH_IPXE_SRC)/src/util/fixrom.pl \
+ | $$(dir $$@)
+ $(call MSG_TOOL,zbin,iPxeBiosBin,$<,$@)
+ $(TOOL_$(VBOX_GCC32_TOOL)_OBJCOPY) -O binary -R .zinfo $< $(iPxeBiosBin_0_OUTDIR)/iPxeBaseBin.rom.bin
+ $(TOOL_$(VBOX_GCC32_TOOL)_OBJCOPY) -O binary -j .zinfo $< $(iPxeBiosBin_0_OUTDIR)/iPxeBaseBin.rom.zinfo
+ $(ipxezbin_1_TARGET) \
+ $(iPxeBiosBin_0_OUTDIR)/iPxeBaseBin.rom.bin \
+ $(iPxeBiosBin_0_OUTDIR)/iPxeBaseBin.rom.zinfo \
+ > $@
+ perl $(VBOX_PATH_IPXE_SRC)/src/util/padimg.pl --blksize=512 --byte=0xff $@
+ perl $(VBOX_PATH_IPXE_SRC)/src/util/fixrom.pl $@
+ $(RM) -- \
+ $(iPxeBiosBin_0_OUTDIR)/iPxeBaseBin.rom.bin \
+ $(iPxeBiosBin_0_OUTDIR)/iPxeBaseBin.rom.zinfo
+
+ #
+ # iPxeLinker - Linker tool used to link the ROM binary.
+ #
+ TOOL_iPxeLinker = iPXE LD tool.
+ TOOL_iPxeLinker_LINK_PROGRAM_OUTPUT =
+ TOOL_iPxeLinker_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map
+ TOOL_iPxeLinker_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).debug
+ TOOL_iPxeLinker_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug
+ TOOL_iPxeLinker_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+ $(filter %.def, $(othersrc))
+ TOOL_iPxeLinker_LINK_PROGRAM_DEPORD =
+ define TOOL_iPxeLinker_LINK_PROGRAM_CMDS
+ $(QUIET)ld $(flags) -o $(out) $(objs)\
+ $(foreach p,$(libpath), -L$(p))\
+ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+ endef
+
+ #
+ # iPXE - Template used to build the ROM binary.
+ #
+ TEMPLATE_iPxe = iPXE code
+ TEMPLATE_iPxe_TOOL = $(VBOX_GCC32_TOOL)
+ TEMPLATE_iPxe_LDTOOL = iPxeLinker
+ TEMPLATE_iPxe_LDFLAGS = \
+ -N \
+ --no-check-sections \
+ --gc-sections \
+ -T $(VBOX_PATH_IPXE_SRC)/src/arch/i386/scripts/i386.lds \
+ -u _rom_start --defsym check__rom_start=_rom_start \
+ -u obj_config --defsym check_obj_config=obj_config \
+ --defsym pci_vendor_id=0x8086 \
+ --defsym pci_device_id=0x100E \
+ -e _rom_start
+ifeq ($(KBUILD_TARGET), freebsd)
+ TEMPLATE_iPxe_LDFLAGS += -m elf_i386_fbsd
+else
+ TEMPLATE_iPxe_LDFLAGS += -m elf_i386
+endif
+ TEMPLATE_iPxe_LNK_DEPS = $(VBOX_PATH_IPXE_SRC)/src/arch/i386/scripts/i386.lds
+ TEMPLATE_iPxe_CFLAGS = \
+ -fno-pie \
+ -ffreestanding \
+ -ffunction-sections \
+ -march=i386 \
+ -fomit-frame-pointer \
+ -fstrength-reduce \
+ -falign-jumps=1 \
+ -falign-loops=1 \
+ -Os \
+ -falign-functions=1 \
+ -mpreferred-stack-boundary=2 \
+ -mregparm=3 \
+ -mrtd \
+ -freg-struct-return \
+ -fshort-wchar \
+ -Ui386 \
+ -Ulinux \
+ -include compiler.h \
+ -Wall \
+ -W \
+ -Wformat-nonliteral \
+ $(VBOX_GCC_fno-stack-protector) \
+ $(VBOX_GCC_fno-dwarf2-cfi-asm) \
+ $(VBOX_GCC_Wno-address)
+ TEMPLATE_iPxe_ASFLAGS = \
+ -ffreestanding \
+ -ffunction-sections \
+ -march=i386 \
+ -fomit-frame-pointer \
+ -fstrength-reduce \
+ -falign-jumps=1 \
+ -falign-loops=1 \
+ -falign-functions=1 \
+ -mpreferred-stack-boundary=2 \
+ -mregparm=3 \
+ -mrtd \
+ -freg-struct-return \
+ -fshort-wchar \
+ -Ui386 \
+ -Ulinux \
+ -include compiler.h \
+ -Wall \
+ -W \
+ -Wformat-nonliteral \
+ $(VBOX_GCC_fno-stack-protector) \
+ $(VBOX_GCC_fno-dwarf2-cfi-asm) \
+ $(VBOX_GCC_Wno-address) \
+ -DASSEMBLY
+ TEMPLATE_iPxe_DEFS = \
+ ARCH=i386 \
+ PLATFORM=pcbios \
+ VERSION_MAJOR=1 \
+ VERSION_MINOR=0 \
+ VERSION_PATCH=0 \
+ VERSION=\"1.0.0+\" \
+ _build_id=0xaffeaffe
+
+
+ #
+ # iPxeBaseBin - The iPXE ROM base binary.
+ #
+ PROGRAMS += iPxeBaseBin
+
+ iPxeBaseBin_TEMPLATE = iPxe
+
+ iPxeBaseBin_INCS = \
+ src \
+ src/include \
+ src/arch/x86/include \
+ src/arch/i386/include \
+ src/arch/i386/include/pcbios
+
+ iPxeBaseBin_SOURCES = \
+ src/arch/i386/core/basemem_packet.c \
+ src/arch/i386/core/relocate.c \
+ src/arch/i386/core/timer2.c \
+ src/arch/i386/firmware/pcbios/basemem.c \
+ src/arch/i386/firmware/pcbios/bios_console.c \
+ src/arch/i386/firmware/pcbios/hidemem.c \
+ src/arch/i386/firmware/pcbios/memmap.c \
+ src/arch/i386/hci/commands/reboot_cmd.c \
+ src/arch/i386/image/bootsector.c \
+ src/arch/i386/image/pxe_image.c \
+ src/arch/i386/interface/pcbios/bios_nap.c \
+ src/arch/i386/interface/pcbios/bios_smbios.c \
+ src/arch/i386/interface/pcbios/bios_timer.c \
+ src/arch/i386/interface/pcbios/biosint.c \
+ src/arch/i386/interface/pcbios/int13.c \
+ src/arch/i386/interface/pcbios/memtop_umalloc.c \
+ src/arch/i386/interface/pcbios/pcibios.c \
+ src/arch/i386/interface/pxe/pxe_call.c \
+ src/arch/i386/interface/pxe/pxe_file.c \
+ src/arch/i386/interface/pxe/pxe_loader.c \
+ src/arch/i386/interface/pxe/pxe_preboot.c \
+ src/arch/i386/interface/pxe/pxe_tftp.c \
+ src/arch/i386/interface/pxe/pxe_udp.c \
+ src/arch/i386/interface/pxe/pxe_undi.c \
+ src/arch/x86/core/x86_string.c \
+ src/config/config.c \
+ src/config/config_romprefix.c \
+ src/core/acpi.c \
+ src/core/ansiesc.c \
+ src/core/asprintf.c \
+ src/core/base16.c \
+ src/core/base64.c \
+ src/core/basename.c \
+ src/core/bitmap.c \
+ src/core/blockdev.c \
+ src/core/console.c \
+ src/core/ctype.c \
+ src/core/cwuri.c \
+ src/core/device.c \
+ src/core/downloader.c \
+ src/core/edd.c \
+ src/core/exec.c \
+ src/core/getkey.c \
+ src/core/getopt.c \
+ src/core/image.c \
+ src/core/init.c \
+ src/core/interface.c \
+ src/core/iobuf.c \
+ src/core/job.c \
+ src/core/linebuf.c \
+ src/core/main.c \
+ src/core/malloc.c \
+ src/core/menu.c \
+ src/core/misc.c \
+ src/core/monojob.c \
+ src/core/nvo.c \
+ src/core/open.c \
+ src/core/parseopt.c \
+ src/core/posix_io.c \
+ src/core/process.c \
+ src/core/random.c \
+ src/core/refcnt.c \
+ src/core/resolv.c \
+ src/core/settings.c \
+ src/core/string.c \
+ src/core/time.c \
+ src/core/timer.c \
+ src/core/uri.c \
+ src/core/uuid.c \
+ src/core/vsprintf.c \
+ src/core/xfer.c \
+ src/crypto/chap.c \
+ src/crypto/md5.c \
+ src/drivers/bitbash/bitbash.c \
+ src/drivers/bitbash/spi_bit.c \
+ src/drivers/block/ata.c \
+ src/drivers/block/ibft.c \
+ src/drivers/block/scsi.c \
+ src/drivers/bus/pci.c \
+ src/drivers/bus/virtio-ring.c \
+ src/drivers/bus/virtio-pci.c \
+ src/drivers/net/mii.c \
+ src/drivers/net/ne.c \
+ src/drivers/net/intel.c \
+ src/drivers/net/pcnet32.c \
+ src/drivers/net/virtio-net.c \
+ src/drivers/nvs/nvs.c \
+ src/drivers/nvs/spi.c \
+ src/drivers/nvs/threewire.c \
+ src/hci/commands/autoboot_cmd.c \
+ src/hci/commands/config_cmd.c \
+ src/hci/commands/dhcp_cmd.c \
+ src/hci/commands/ifmgmt_cmd.c \
+ src/hci/commands/image_cmd.c \
+ src/hci/commands/login_cmd.c \
+ src/hci/commands/menu_cmd.c \
+ src/hci/commands/nvo_cmd.c \
+ src/hci/commands/route_cmd.c \
+ src/hci/editstring.c \
+ src/hci/keymap/keymap_us.c \
+ src/hci/mucurses/ansi_screen.c \
+ src/hci/mucurses/clear.c \
+ src/hci/mucurses/colour.c \
+ src/hci/mucurses/mucurses.c \
+ src/hci/mucurses/print.c \
+ src/hci/mucurses/widgets/editbox.c \
+ src/hci/mucurses/winattrs.c \
+ src/hci/mucurses/wininit.c \
+ src/hci/readline.c \
+ src/hci/shell.c \
+ src/hci/strerror.c \
+ src/hci/tui/login_ui.c \
+ src/hci/tui/menu_ui.c \
+ src/hci/tui/settings_ui.c \
+ src/image/script.c \
+ src/image/segment.c \
+ src/interface/smbios/smbios.c \
+ src/interface/smbios/smbios_settings.c \
+ src/libgcc/memcpy.c \
+ src/net/arp.c \
+ src/net/dhcpopts.c \
+ src/net/dhcppkt.c \
+ src/net/eth_slow.c \
+ src/net/ethernet.c \
+ src/net/fakedhcp.c \
+ src/net/icmp.c \
+ src/net/iobpad.c \
+ src/net/ipv4.c \
+ src/net/netdev_settings.c \
+ src/net/netdevice.c \
+ src/net/nullnet.c \
+ src/net/rarp.c \
+ src/net/retry.c \
+ src/net/tcp.c \
+ src/net/tcpip.c \
+ src/net/udp.c \
+ src/net/udp/dhcp.c \
+ src/net/udp/dns.c \
+ src/net/udp/tftp.c \
+ src/net/tcp/http.c \
+ src/net/tcp/httpcore.c \
+ src/usr/autoboot.c \
+ src/usr/dhcpmgmt.c \
+ src/usr/ifmgmt.c \
+ src/usr/imgmgmt.c \
+ src/usr/prompt.c \
+ src/usr/pxemenu.c \
+ src/usr/route.c \
+ src/arch/i386/core/patch_cf.S \
+ src/arch/i386/core/setjmp.S \
+ src/arch/i386/core/stack.S \
+ src/arch/i386/core/stack16.S \
+ src/arch/i386/core/virtaddr.S \
+ src/arch/i386/firmware/pcbios/e820mangler.S \
+ src/arch/i386/interface/pxe/pxe_entry.S \
+ src/arch/i386/prefix/libprefix.S \
+ src/arch/i386/prefix/romprefix.S \
+ src/arch/i386/prefix/undiloader.S \
+ src/arch/i386/prefix/unnrv2b.S \
+ src/arch/i386/prefix/unnrv2b16.S \
+ src/arch/i386/transitions/liba20.S \
+ src/arch/i386/transitions/librm.S
+
+ define def_iPxeBaseBinDefs
+ $(file)_DEFS += OBJECT=$(subst -,_,$(basename $(notdir $(file))))
+ endef
+
+ $(foreach file,$(iPxeBaseBin_SOURCES),$(eval $(call def_iPxeBaseBinDefs)))
+
+ #
+ # ipxezbin - Compressor?
+ #
+ BLDPROGS += ipxezbin
+ ipxezbin_TEMPLATE = VBoxBldProg
+ ipxezbin_CFLAGS = -Wno-format -Wno-unused-function
+ ipxezbin_SOURCES = src/util/zbin.c
+
+endif
+
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Devices/PC/ipxe/README b/src/VBox/Devices/PC/ipxe/README
new file mode 100644
index 00000000..011aa210
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/README
@@ -0,0 +1,8 @@
+iPXE README File
+
+Quick start guide:
+
+ cd src
+ make
+
+For any more detailed instructions, see http://ipxe.org
diff --git a/src/VBox/Devices/PC/ipxe/README.vbox b/src/VBox/Devices/PC/ipxe/README.vbox
new file mode 100644
index 00000000..a2720fcc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/README.vbox
@@ -0,0 +1,8 @@
+These iPXE sources were taken from git.ipxe.org.
+
+Initial commit: a33298dcda4f9b6037e1c21f3d6f056dba77ab18
+
+Manually applied 238050dfd46e3c4a87329da1d48b4d8dde5af8a1 and
+cba22d36b77da53890bd65fdadd0e63925687af0 manually to make it
+compile with recent gcc versions not allowing the ebp register
+to be clobbered.
diff --git a/src/VBox/Devices/PC/ipxe/contrib/README b/src/VBox/Devices/PC/ipxe/contrib/README
new file mode 100644
index 00000000..e77d4690
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/README
@@ -0,0 +1,9 @@
+Most of the content that was previously in this directory has been
+moved to a separate git repository:
+
+ http://git.etherboot.org/?p=contrib.git;a=summary
+
+or the Etherboot Project wiki:
+
+ http://etherboot.org/
+
diff --git a/src/VBox/Devices/PC/ipxe/contrib/errdb/errdb.pl b/src/VBox/Devices/PC/ipxe/contrib/errdb/errdb.pl
new file mode 100755
index 00000000..fc1919f6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/errdb/errdb.pl
@@ -0,0 +1,108 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+errdb.pl
+
+=head1 SYNOPSIS
+
+errdb.pl [options] ../../src/bin/errors
+
+Options:
+
+ -d,--database=db Specify path to errors.db
+ -h,--help Display brief help message
+ -v,--verbose Increase verbosity
+ -q,--quiet Decrease verbosity
+
+=cut
+
+use Getopt::Long;
+use Pod::Usage;
+use DBI;
+use strict;
+use warnings;
+
+# Parse command-line options
+my $verbosity = 0;
+my $errdb = "errors.db";
+Getopt::Long::Configure ( 'bundling', 'auto_abbrev' );
+GetOptions (
+ 'database|d=s' => sub { shift; $errdb = shift; },
+ 'verbose|v+' => sub { $verbosity++; },
+ 'quiet|q+' => sub { $verbosity--; },
+ 'help|h' => sub { pod2usage ( 1 ); },
+) or die "Could not parse command-line options\n";
+pod2usage ( 1 ) unless @ARGV >= 1;
+
+# Open database
+my $dbh = DBI->connect ( "dbi:SQLite:dbname=".$errdb, "", "",
+ { RaiseError => 1, PrintError => 0 } );
+$dbh->begin_work();
+
+# Create errors table if necessary
+eval {
+ $dbh->selectall_arrayref ( "SELECT * FROM errors LIMIT 1" );
+};
+if ( $@ ) {
+ print "Creating errors table\n" if $verbosity >= 1;
+ $dbh->do ( "CREATE TABLE errors (".
+ " errno char(8) NOT NULL,".
+ " description text NOT NULL,".
+ " PRIMARY KEY ( errno ) )" );
+}
+
+# Create xrefs table if necessary
+eval {
+ $dbh->selectall_arrayref ( "SELECT * FROM xrefs LIMIT 1" );
+};
+if ( $@ ) {
+ print "Creating xrefs table\n" if $verbosity >= 1;
+ $dbh->do ( "CREATE TABLE xrefs (".
+ " errno char(8) NOT NULL,".
+ " filename text NOT NULL,".
+ " line integer NOT NULL,".
+ " UNIQUE ( errno, filename, line ),".
+ " FOREIGN KEY ( errno ) REFERENCES errors ( errno ) )" );
+ $dbh->do ( "CREATE INDEX xrefs_errno ON xrefs ( errno )" );
+}
+
+# Parse input file(s)
+my $errors = {};
+my $xrefs = {};
+while ( <> ) {
+ chomp;
+ ( my $errno, my $filename, my $line, my $description ) = split ( /\t/ );
+ $errors->{$errno} = $description;
+ $xrefs->{$errno} ||= {};
+ $xrefs->{$errno}->{$filename} ||= {};
+ $xrefs->{$errno}->{$filename}->{$line} ||= 1;
+}
+
+# Ensure all errors are present in database
+my $error_update =
+ $dbh->prepare ( "UPDATE errors SET description = ? WHERE errno = ?" );
+my $error_insert = $dbh->prepare ( "INSERT INTO errors VALUES ( ?, ? )" );
+while ( ( my $errno, my $description ) = each %$errors ) {
+ print "Error ".$errno." is \"".$description."\"\n" if $verbosity >= 2;
+ if ( $error_update->execute ( $description, $errno ) == 0 ) {
+ $error_insert->execute ( $errno, $description );
+ }
+}
+
+# Replace xrefs in database
+$dbh->do ( "DELETE FROM xrefs" );
+my $xref_insert = $dbh->prepare ( "INSERT INTO xrefs VALUES ( ?, ?, ? )" );
+while ( ( my $errno, my $xref_errno ) = each %$xrefs ) {
+ while ( ( my $filename, my $xref_filename ) = each %$xref_errno ) {
+ foreach my $line ( keys %$xref_filename ) {
+ print "Error ".$errno." is used at ".$filename." line ".$line."\n"
+ if $verbosity >= 2;
+ $xref_insert->execute ( $errno, $filename, $line );
+ }
+ }
+}
+
+# Close database
+$dbh->commit();
+$dbh->disconnect();
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/README b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/README
new file mode 100644
index 00000000..b68cf775
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/README
@@ -0,0 +1,62 @@
+ROM-o-matic web interface for building iPXE ROMs
+------------------------------------------------
+
+This web application generates iPXE images and sends them to a web
+browser.
+
+Available as part of the iPXE source code distribution, which can be
+downlaoded from http://etherboot.org/
+
+Author: Marty Connor <mdc@etherboot.org>
+License: GPLv2
+Support: http://etherboot.org/mailman/listinfo/ipxe
+ Please send support questions to the iPXE mailing list
+
+System Requirements
+-------------------
+- Apache web server
+- PHP 4+
+- Tools required to build iPXE installed on the server
+ - gcc, mtools, syslinux, perl, etc.
+
+Setup
+-----
+As distributed, it is expected that the rom-o-matic source code
+directory is in the contrib directory of a iPXE source distribution.
+
+The easiest way to do this is to simply put a iPXE source distribution
+in a web server accessible directory.
+
+If this is not the case, you will need to either edit the file
+
+ "globals.php"
+
+or create a file called
+
+ "local-config.php"
+
+containing the following lines:
+
+<?php
+$src_dir = "../../src";
+?>
+
+Then change the line beginning "$src_dir = " to the path of your iPXE
+source code tree.
+
+To make build times shorter, before you run rom-o-matic for the first time
+you should cd to the ipxe "src" directory and enter the following
+commands:
+
+ $ make
+ $ make bin/NIC
+
+This will pro-compile most object files and will make your rom-o-matic
+builds much faster.
+
+Running rom-o-matic from a web browser
+--------------------------------------
+Enter a URL like:
+
+ http://example.com/ipxe-1.x.x/contrib/rom-o-matic
+
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/bottom.php b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/bottom.php
new file mode 100644
index 00000000..9ba8e319
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/bottom.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
+ * Copyright (C) 2009 Entity Cyber, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+?>
+<hr>
+<h4>
+Resources:
+</h4>
+<ul>
+ <li>
+ Source code for iPXE images is available at
+ <a href="http://www.ipxe.org/download" target="_blank">
+ http://www.ipxe.org/download</a>
+ <br><br>
+ </li>
+ <li>
+ For general information about using iPXE, please visit the
+ <a href="http://www.ipxe.org/" target="_blank">
+ iPXE Project Home Page</a>
+ <br><br>
+ </li>
+ <li>
+ For Email-based support for iPXE please join
+ <a href="http://www.ipxe.org/contact" target="_blank">
+ iPXE Project mailing lists.</a>
+ <br><br>
+ </li>
+ <li>
+ For real-time online iPXE support via IRC please visit the
+ <a href="irc://irc.freenode.net/%23ipxe"> #ipxe channel
+ of irc.freenode.net</a>.
+ <br><br>
+ </li>
+</ul>
+<hr>
+ <font size="-1">
+ <br>
+ Please email <a href="mailto:<?php echo "${webmaster_email}" ?>"><?php echo "${webmaster_email}"?></a>
+ with questions or comments about this website.
+ </font>
+ <br><br>
+<hr>
+</body>
+</html>
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/build.php b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/build.php
new file mode 100644
index 00000000..b9bc5951
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/build.php
@@ -0,0 +1,306 @@
+<?php // -*- Mode: PHP; -*-
+
+/**
+ * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
+ * Copyright (C) 2009 Entity Cyber, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+// Get utility functions and set globals
+require_once "utils.php";
+
+// Make sure at least $A (action) was supplied
+if ( ! isset ( $_POST['A'] ) ) {
+
+ // Present user with form to customize build options
+ require_once "customize-flags.php";
+
+ exit ();
+
+// If user chose "Customize" option on form
+} else if ( $_POST['A'] == "Customize" ) {
+
+ // Present user with form to customize build options
+ require_once "customize-flags.php";
+
+ exit ();
+
+// The following conditional includes all other cases except "Get Image"
+// particularly the explicit ($A == "Start Over") case
+} else if ( $_POST['A'] != "Get Image" ) {
+
+ // Note that this method of redirections discards all the
+ // configuration flags, which is intentional in this case.
+
+ $dest = curDirURL ();
+ header ( "Location: $dest" );
+
+ // This next "echo" should normally not be seen, because
+ // the "header" statement above should cause immediate
+ // redirection but just in case...
+
+ echo "Try this link: <a href=\"$dest\">$dest</a>";
+
+ exit ();
+}
+
+// OK, we're going to try to use whatever options have been set
+// to build an image.
+
+// Make sure at least $nic was supplied
+if ( ! isset ( $_POST['nic'] ) ) {
+ die ( "No NIC supplied!" );
+}
+if ( isset ( $nics[$_POST['nic']] ) ) {
+ $nic = $nics[$_POST['nic']];
+} else {
+ die ( "Invalid NIC \"${_POST['nic']}\" supplied!" );
+}
+
+// Fetch flags
+$flags = get_flags ();
+
+// Get requested format
+$ofmt = isset ( $_POST['ofmt'] ) ? $_POST['ofmt'] : "";
+$fmt_extension = isset ( $ofmts[$ofmt] ) ? $ofmts[$ofmt] : 'dsk';
+
+// Handle some special cases
+
+$pci_vendor_code = "";
+$pci_device_code = "";
+
+if ( $nic == 'undionly' && $fmt_extension == "pxe" ) {
+
+ // undionly.pxe can't work because it unloads the PXE stack
+ // that it needs to communicate with, so we set the extension
+ // to .kpxe, which has a chance of working. The extension
+ // .kkpxe is another option.
+
+ $fmt_extension = "kpxe";
+
+} else if ( $fmt_extension == "rom" ) {
+
+ if ( ! isset ( $_POST['pci_vendor_code'] )
+ || ! isset ( $_POST['pci_device_code'] ) ) {
+ die ( "rom output format selected but PCI code(s) missing!" );
+ }
+
+ $pci_vendor_code = $_POST['pci_vendor_code'];
+ $pci_device_code = $_POST['pci_device_code'];
+
+ if ( $pci_vendor_code == ""
+ || $pci_device_code == "" ) {
+ die ( "rom output format selected but PCI code(s) missing!" );
+ }
+
+ // Try to be forgiving of 0xAAAA format
+ if ( strtolower ( substr ( $pci_vendor_code, 0, 2 ) ) == "0x"
+ && strlen ( $pci_vendor_code ) == 6 ) {
+ $pci_vendor_code = substr ( $pci_vendor_code, 2, 4 );
+ }
+ if ( strtolower ( substr ( $pci_device_code, 0, 2 ) ) == "0x"
+ && strlen ( $pci_device_code ) == 6 ) {
+ $pci_device_code = substr ( $pci_device_code, 2, 4 );
+ }
+
+ // concatenate the pci codes to get the $nic part of the
+ // Make target
+ $pci_codes = strtolower ( $pci_vendor_code . $pci_device_code );
+
+ $nic = $pci_codes;
+ if ( ! isset ( $roms[$pci_codes] ) ) {
+ die ( "Sorry, no network driver supports PCI codes<br>"
+ . "${_POST['pci_vendor_code']}:"
+ . "${_POST['pci_device_code']}" );
+ }
+} else if ( $fmt_extension != "rom"
+ && ( $pci_vendor_code != "" || $pci_device_code != "" ) ) {
+ die ( "'$fmt_extension' format was selected but PCI IDs were"
+ . " also entered.<br>Did you mean to select 'rom' output format"
+ . " instead?" );
+}
+
+/**
+ * remove temporary build directory
+ *
+ * @return bool true if removal is successful, false otherwise
+ */
+function rm_build_dir ()
+{
+ global $build_dir;
+ global $keep_build_dir;
+
+ if ( $keep_build_dir !== true ) {
+ rm_file_or_dir ( $build_dir );
+ }
+}
+
+// Arrange for the build directory to always be removed on exit.
+$build_dir = "";
+$keep_build_dir = false;
+register_shutdown_function ( 'rm_build_dir' );
+
+// Make temporary copy of src directory
+$build_dir = mktempcopy ( "$src_dir", "/tmp", "MDCROM" );
+$config_dir = $build_dir . "/config";
+
+// Write config files with supplied flags
+write_ipxe_config_files ( $config_dir, $flags );
+
+// Handle a possible embedded script
+$emb_script_cmd = "";
+$embedded_script = isset ( $_POST['embedded_script'] ) ? $_POST['embedded_script'] : "";
+if ( $embedded_script != "" ) {
+ $emb_script_path = "$build_dir" . "/script0.ipxe";
+
+ if ( substr ( $embedded_script, 0, 5 ) != "#!ipxe" ) {
+ $embedded_script = "#!ipxe\n" . $embedded_script;
+ }
+
+ // iPXE 0.9.7 doesn't like '\r\n" in the shebang...
+ $embedded_script = str_replace ( "\r\n", "\n", $embedded_script );
+
+ write_file_from_string ( $emb_script_path, $embedded_script );
+ $emb_script_cmd = "EMBEDDED_IMAGE=${emb_script_path}";
+}
+
+// Make the requested image. $status is set to 0 on success
+$make_target = "bin/${nic}.${fmt_extension}";
+$make_cmd = "make -C '$build_dir' '$make_target' $emb_script_cmd 2>&1";
+
+exec ( $make_cmd, $maketxt, $status );
+
+// Uncomment the following section for debugging
+
+/**
+
+echo "<h2>build.php:</h2>";
+echo "<h3>Begin debugging output</h3>";
+
+//echo "<h3>\$_POST variables</h3>";
+//echo "<pre>"; var_dump ( $_POST ); echo "</pre>";
+
+echo "<h3>Build options:</h3>";
+echo "<strong>Build directory is:</strong> $build_dir" . "<br><br>";
+echo "\$_POST['ofmt'] = " . "\"${_POST['ofmt']}\"" . "<br>";
+echo "\$_POST['nic'] = " . "\"${_POST['nic']}\"" . "<br>";
+echo "\$_POST['pci_vendor_code'] = " . "\"${_POST['pci_vendor_code']}\"" . "<br>";
+echo "\$_POST['pci_device_code'] = " . "\"${_POST['pci_device_code']}\"" . "<br>";
+
+echo "<h3>Flags:</h3>";
+show_flags ( $flags );
+
+if ( $embedded_script != "" ) {
+ echo "<h3>Embedded script:</h3>";
+ echo "<blockquote>"."<pre>";
+ echo $embedded_script;
+ echo "</pre>"."</blockquote>";
+}
+
+echo "<h3>Make output:</h3>";
+echo "Make command: " . $make_cmd . "<br>";
+echo "Build status = <? echo $status ?>" . "<br>";
+echo "<blockquote>"."<pre>";
+echo htmlentities ( implode ("\n", $maketxt ) );
+echo "</pre>"."</blockquote>";
+// Uncomment the next line if you want to keep the
+// build directory around for inspection after building.
+$keep_build_dir = true;
+die ( "<h3>End debugging output</h3>" );
+
+**/ // End debugging section
+
+// Send ROM to browser (with extreme prejudice)
+
+if ( $status == 0 ) {
+
+ $fp = fopen("${build_dir}/${make_target}", "rb" );
+ if ( $fp > 0 ) {
+
+ $len = filesize ( "${build_dir}/${make_target}" );
+ if ( $len > 0 ) {
+
+ $buf = fread ( $fp, $len );
+ fclose ( $fp );
+
+ // Delete build directory as soon as it is not needed
+ rm_build_dir ();
+
+ $output_filename = "ipxe-${version}-${nic}.${fmt_extension}";
+
+ // Try to force IE to handle downloading right.
+ Header ( "Cache-control: private");
+ Header ( "Content-Type: application/x-octet-stream; " .
+ "name=$output_filename");
+ Header ( "Content-Disposition: attachment; " .
+ "Filename=$output_filename");
+ Header ( "Content-Location: $output_filename");
+ Header ( "Content-Length: $len");
+
+ echo $buf;
+
+ exit ();
+ }
+ }
+}
+
+/*
+ * If we reach this point, the build has failed, and we provide
+ * debugging information for a potential bug report
+ *
+ */
+
+// Remove build directory
+rm_build_dir ();
+
+// Announce failure if $status from make was non-zero
+echo "<h2>Build failed. Status = " . $status . "</h2>";
+echo "<h2>build.php:</h2>";
+echo "<h3>Build options:</h3>";
+echo "<strong>Build directory is:</strong> $build_dir" . "<br><br>";
+echo "\$_POST['ofmt'] = " . "\"${_POST['ofmt']}\"" . "<br>";
+echo "\$_POST['nic'] = " . "\"${_POST['nic']}\"" . "<br>";
+echo "\$_POST['pci_vendor_code'] = " . "\"${_POST['pci_vendor_code']}\"" . "<br>";
+echo "\$_POST['pci_device_code'] = " . "\"${_POST['pci_device_code']}\"" . "<br>";
+
+echo "<h3>Flags:</h3>";
+show_flags ( $flags );
+
+if ( $embedded_script != "" ) {
+ echo "<h3>Embedded script:</h3>";
+ echo "<blockquote>"."<pre>";
+ echo $embedded_script;
+ echo "</pre>"."</blockquote>";
+}
+
+echo "<h3>Make output:</h3>";
+echo "Make command: " . $make_cmd . "<br>";
+echo "<blockquote>"."<pre>";
+echo htmlentities ( implode ("\n", $maketxt ) );
+echo "</pre>"."</blockquote>";
+
+echo "Please let us know that this happened, and paste the above output into your email message.<br>";
+
+include_once $bottom_inc;
+
+// For emacs:
+// Local variables:
+// c-basic-offset: 4
+// c-indent-level: 4
+// tab-width: 4
+// End:
+
+?>
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/customize-flags.php b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/customize-flags.php
new file mode 100644
index 00000000..e283921a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/customize-flags.php
@@ -0,0 +1,69 @@
+<?php // -*- Mode: PHP; -*-
+
+/**
+ * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
+ * Copyright (C) 2009 Entity Cyber, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+// Get utility functions and set globals
+require_once "utils.php";
+
+// Prepare settable compile options for presentation to user
+$flags = default_flags ();
+
+$build = "<input type=\"submit\" name=\"A\" value=\"Get Image\">";
+$restart = "<input type=\"submit\" name=\"A\" value=\"Start Over\">";
+
+// Begin html output
+include_once $top_inc;
+
+?>
+
+<form action="build.php" method=POST>
+ <input type="hidden" name="version" value = "<?php echo $version ?>">
+ <input type="hidden" name="use_flags" value="1">
+ <h3>
+ Make changes below and press <?php echo $build ?> to create an image, <br>
+ Or press <?php echo $restart ?> to return to the main page.
+ </h3>
+ <hr>
+ <ul>
+ <?php require ( "directions.php" ); ?>
+ </ul>
+ <hr>
+ <?php echo_flags( $flags ); ?>
+ <hr>
+ <h3>Embedded Script:</h3>
+ <?php echo textarea ( "embedded_script", "", "10", "50" ); ?>
+ <br><br>
+ <hr>
+ <center><table width="35%"><tr>
+ <td align="left"> <?php echo $build; ?> </td>
+ <td align="right"> <?php echo $restart ?></td>
+ </tr></table></center>
+</form>
+
+<?php include_once $bottom_inc; ?>
+<?
+// For emacs:
+//
+// Local variables:
+// c-basic-offset: 4
+// c-indent-level: 4
+// tab-width: 4
+// End:
+?>
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/directions.php b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/directions.php
new file mode 100644
index 00000000..540121ed
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/directions.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
+ * Copyright (C) 2009 Entity Cyber, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+?>
+ <li>
+ Choose an output format: <?php echo keys_menubox ( "ofmt", $ofmts,
+ isset ( $_POST['ofmt'] ) ? $_POST['ofmt'] : "") ?>
+ <br><br>
+ </li>
+ <li>
+ Choose a NIC type: <?php echo keys_menubox ( "nic", $nics,
+ isset ( $_POST['nic'] ) ? $_POST['nic'] : "" ) ?>
+ <br><br>
+ </li>
+ <li>
+ <strong>( optional &mdash; for binary ROM image format only )</strong> <br><br>
+ If you choose <em>Binary ROM image</em> as your output format, you must<br>
+ enter <strong>4 hex digits</strong> below for
+ <em>PCI VENDOR CODE</em> and <em>PCI DEVICE CODE</em> <br>
+ that match the NIC device for which you are making this image.<br><br>
+ Information on how to determine NIC PCI IDs may be found
+ <a href="http://www.ipxe.org/howto/romburning"
+ target="_blank">here</a>.
+ <br><br>
+ PCI VENDOR CODE: <?php echo textbox ( "pci_vendor_code",
+ isset ( $_POST['pci_vendor_code'] ) ? $_POST['pci_vendor_code']
+ : "", 6 ); ?>
+ &nbsp;&nbsp;
+ PCI DEVICE CODE: <?php echo textbox ( "pci_device_code",
+ isset ( $_POST['pci_device_code'] ) ? $_POST['pci_device_code']
+ : "", 6 ); ?>
+ <h4>Please note for ROM images:</h4>
+ <ul>
+ <li>
+ If you enter PCI IDs, we will attempt to determine the correct<br>
+ driver to support them, and will ignore any NIC type entered
+ above.<br><br>
+ </li>
+ <li>
+ iPXE does not support all possible PCI IDs for supported
+ NICs.
+ <br><br>
+ </li>
+ </ul>
+ </li>
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/AUTOBOOT_CMD.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/AUTOBOOT_CMD.html
new file mode 100644
index 00000000..444c5e60
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/AUTOBOOT_CMD.html
@@ -0,0 +1 @@
+Automatic booting
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/BANNER_TIMEOUT.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/BANNER_TIMEOUT.html
new file mode 100644
index 00000000..e135897f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/BANNER_TIMEOUT.html
@@ -0,0 +1 @@
+Tenths of a second for which the shell banner should appear
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMCONSOLE.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMCONSOLE.html
new file mode 100644
index 00000000..e7036c00
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMCONSOLE.html
@@ -0,0 +1,3 @@
+Serial Console I/O port address. Common addresses are:<br>
+COM1 => 0x3f8, COM2 => 0x2f8, COM3 => 0x3e8, COM4 => 0x2e8
+
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMDATA.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMDATA.html
new file mode 100644
index 00000000..a27e2751
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMDATA.html
@@ -0,0 +1 @@
+Serial Console Data bits
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMPARITY.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMPARITY.html
new file mode 100644
index 00000000..14f35951
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMPARITY.html
@@ -0,0 +1 @@
+Serial Console Parity: 0=None, 1=Odd, 2=Even
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMPRESERVE.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMPRESERVE.html
new file mode 100644
index 00000000..6e41a10b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMPRESERVE.html
@@ -0,0 +1 @@
+Keep settings from a previous user of the serial port \ No newline at end of file
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMSPEED.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMSPEED.html
new file mode 100644
index 00000000..32b68595
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMSPEED.html
@@ -0,0 +1 @@
+Serial Console Baud rate
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMSTOP.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMSTOP.html
new file mode 100644
index 00000000..ae3fd24f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/COMSTOP.html
@@ -0,0 +1 @@
+Serial Console Stop bits
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CONFIG_CMD.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CONFIG_CMD.html
new file mode 100644
index 00000000..1256c069
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CONFIG_CMD.html
@@ -0,0 +1 @@
+Option configuration console
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CONSOLE_PC_BIOS.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CONSOLE_PC_BIOS.html
new file mode 100644
index 00000000..144eea3b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CONSOLE_PC_BIOS.html
@@ -0,0 +1 @@
+Enable Default BIOS console
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CONSOLE_SERIAL.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CONSOLE_SERIAL.html
new file mode 100644
index 00000000..f35e2ff5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CONSOLE_SERIAL.html
@@ -0,0 +1 @@
+Enable Serial port console
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CRYPTO_80211_WEP.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CRYPTO_80211_WEP.html
new file mode 100644
index 00000000..26fdf8a8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CRYPTO_80211_WEP.html
@@ -0,0 +1 @@
+Wireless WEP encryption support
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CRYPTO_80211_WPA.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CRYPTO_80211_WPA.html
new file mode 100644
index 00000000..b218a1e9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CRYPTO_80211_WPA.html
@@ -0,0 +1 @@
+Wireless WPA encryption support
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CRYPTO_80211_WPA2.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CRYPTO_80211_WPA2.html
new file mode 100644
index 00000000..947597d1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/CRYPTO_80211_WPA2.html
@@ -0,0 +1 @@
+Wireless WPA2 encryption support
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DHCP_CMD.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DHCP_CMD.html
new file mode 100644
index 00000000..a0c31c7c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DHCP_CMD.html
@@ -0,0 +1 @@
+DHCP management commands
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DNS_RESOLVER.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DNS_RESOLVER.html
new file mode 100644
index 00000000..1029b9c5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DNS_RESOLVER.html
@@ -0,0 +1 @@
+DNS resolver
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_FTP.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_FTP.html
new file mode 100644
index 00000000..7686d5d8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_FTP.html
@@ -0,0 +1 @@
+File Transfer Protocol
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_HTTP.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_HTTP.html
new file mode 100644
index 00000000..c28d8886
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_HTTP.html
@@ -0,0 +1 @@
+Hypertext Transfer Protocol
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_TFTP.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_TFTP.html
new file mode 100644
index 00000000..f2b31b17
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_TFTP.html
@@ -0,0 +1 @@
+Trivial File Transfer Protocol
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IFMGMT_CMD.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IFMGMT_CMD.html
new file mode 100644
index 00000000..0e2b2a5e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IFMGMT_CMD.html
@@ -0,0 +1 @@
+Interface management commands
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_BZIMAGE.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_BZIMAGE.html
new file mode 100644
index 00000000..d85e5d07
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_BZIMAGE.html
@@ -0,0 +1 @@
+Linux bzImage image support
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_CMD.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_CMD.html
new file mode 100644
index 00000000..6f5acb53
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_CMD.html
@@ -0,0 +1 @@
+Image management commands
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_ELF.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_ELF.html
new file mode 100644
index 00000000..5e39e8bd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_ELF.html
@@ -0,0 +1 @@
+ELF image support
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_MULTIBOOT.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_MULTIBOOT.html
new file mode 100644
index 00000000..6a092a20
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_MULTIBOOT.html
@@ -0,0 +1 @@
+MultiBoot image support
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_NBI.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_NBI.html
new file mode 100644
index 00000000..eb78e03c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_NBI.html
@@ -0,0 +1 @@
+NBI image support
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_PXE.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_PXE.html
new file mode 100644
index 00000000..bdca3841
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_PXE.html
@@ -0,0 +1 @@
+PXE image support
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_SCRIPT.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_SCRIPT.html
new file mode 100644
index 00000000..87416727
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IMAGE_SCRIPT.html
@@ -0,0 +1 @@
+iPXE script image support
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IWMGMT_CMD.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IWMGMT_CMD.html
new file mode 100644
index 00000000..0d5bd4a6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/IWMGMT_CMD.html
@@ -0,0 +1 @@
+Wireless interface management commands
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/NMB_RESOLVER.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/NMB_RESOLVER.html
new file mode 100644
index 00000000..a0bdc17d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/NMB_RESOLVER.html
@@ -0,0 +1 @@
+NMB resolver
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/NVO_CMD.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/NVO_CMD.html
new file mode 100644
index 00000000..5346f3f5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/NVO_CMD.html
@@ -0,0 +1 @@
+Non-volatile option storage commands
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/ROUTE_CMD.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/ROUTE_CMD.html
new file mode 100644
index 00000000..8114c265
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/ROUTE_CMD.html
@@ -0,0 +1 @@
+Routing table management commands
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/SANBOOT_CMD.html b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/SANBOOT_CMD.html
new file mode 100644
index 00000000..2e9d8407
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/doc/SANBOOT_CMD.html
@@ -0,0 +1 @@
+SAN boot commands
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/flag-table.php b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/flag-table.php
new file mode 100644
index 00000000..0eee0c3f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/flag-table.php
@@ -0,0 +1,521 @@
+<?php // -*- Mode: PHP; -*-
+
+/**
+ * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
+ * Copyright (C) 2009 Entity Cyber, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+$ofmts = array
+ ( "Floppy bootable image (.dsk)" => "dsk",
+ "SYSLINUX-based bootable floppy image (.sdsk)" => "sdsk",
+ "ISO bootable image (.iso)" => "iso",
+ "ISO bootable image with legacy floppy emulation (.liso)" => "liso",
+ "Linux kernel (SYSLINUX/GRUB/LILO) loadable image (.lkrn)" => "lkrn",
+ "USB Keychain disk image (.usb)" => "usb",
+ "ROM binary (flashable) image (.rom)" => "rom",
+ "ROM binary (flashable) for problem PMM BIOSES (.hrom)" => "hrom",
+ "PXE bootstrap loader image [Unload PXE stack] (.pxe)" => "pxe",
+ "PXE bootstrap loader keep [Keep PXE stack method 1] (.kpxe)" => "kpxe",
+ "PXE bootstrap loader keep [Keep PXE stack method 2] (.kkpxe)" => "kkpxe",
+ );
+
+$flag_table = array (
+
+ // Begin General Options:
+
+ "HDR_MISC_OPTIONS"
+ => array (
+ "flag" => "HDR_MISC_OPTIONS",
+ "hide_from_user" => "yes", // Hide even the header
+ "type" => "header",
+ "label" => "Miscellaneous Options"
+ ),
+
+ "PRODUCT_NAME"
+ => array (
+ "flag" => "PRODUCT_NAME",
+ "hide_from_user" => "yes",
+ "type" => "string",
+ "value" => "",
+ "cfgsec" => "general"
+ ),
+
+ "PRODUCT_SHORT_NAME"
+ => array (
+ "flag" => "PRODUCT_SHORT_NAME",
+ "hide_from_user" => "yes",
+ "type" => "string",
+ "value" => "iPXE",
+ "cfgsec" => "general"
+ ),
+
+ // End General Options:
+
+ // Begin Console Options:
+
+ "HDR_CONSOLE_OPTIONS"
+ => array (
+ "flag" => "HDR_CONSOLE_OPTIONS",
+ "type" => "header",
+ "label" => "Console Options"
+ ),
+
+ "CONSOLE_PCBIOS"
+ => array (
+ "flag" => "CONSOLE_PCBIOS",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "console"
+ ),
+
+ "CONSOLE_SERIAL"
+ => array (
+ "flag" => "CONSOLE_SERIAL",
+ "type" => "on/off",
+ "value" => "off",
+ "cfgsec" => "console"
+ ),
+
+ "BANNER_TIMEOUT"
+ => array (
+ "flag" => "BANNER_TIMEOUT",
+ "type" => "integer",
+ "value" => "20",
+ "cfgsec" => "general"
+ ),
+
+ "KEYBOARD_MAP"
+ => array (
+ "flag" => "KEYBOARD_MAP",
+ "type" => "choice",
+ "options" => array("al","az","bg","by","cf","cz","de","dk","es","et","fi","fr",
+ "gr","hu","il","it","lt","mk","mt","nl","no","pl","pt","ro","ru","sg","sr",
+ "th","ua","uk","us","wo"),
+ "value" => "us",
+ "cfgsec" => "console"
+ ),
+
+ // End Console Options
+
+ // Begin Network Protocol Options:
+
+ "HDR_NETWORK_PROTOCOL_OPTIONS"
+ => array (
+ "flag" => "HDR_NETWORK_PROTOCOL_OPTIONS",
+ "hide_from_user" => "yes", // Hide even the header
+ "type" => "header",
+ "label" => "Network Protocol Options"
+ ),
+
+ "NET_PROTO_IPV4"
+ => array (
+ "flag" => "NET_PROTO_IPV4",
+ "type" => "on/off",
+ "value" => "on",
+ "hide_from_user" => "yes",
+ "cfgsec" => "general"
+ ),
+
+ // End Network Protocol Options
+
+ // Begin Serial Port configuration
+
+ "HDR_SERIAL_PORT_OPTIONS"
+ => array (
+ "flag" => "HDR_SERIAL_PORT_OPTIONS",
+ "type" => "header",
+ "label" => "Serial Port Options"
+ ),
+
+ "COMCONSOLE"
+ => array (
+ "flag" => "COMCONSOLE",
+ "type" => "integer-hex", // e.g. 0x378
+ "value" => "0x3F8",
+ "cfgsec" => "serial"
+ ),
+
+ "COMPRESERVE"
+ => array (
+ "flag" => "COMPRESERVE",
+ "type" => "on/off",
+ "value" => "off",
+ "cfgsec" => "serial"
+ ),
+
+ "COMSPEED"
+ => array (
+ "flag" => "COMSPEED",
+ "type" => "integer",
+ "value" => "115200",
+ "cfgsec" => "serial"
+ ),
+
+ "COMDATA"
+ => array (
+ "flag" => "COMDATA",
+ "type" => "integer",
+ "value" => "8",
+ "cfgsec" => "serial"
+ ),
+
+ "COMPARITY"
+ => array (
+ "flag" => "COMPARITY",
+ "type" => "integer",
+ "value" => "0",
+ "cfgsec" => "serial"
+ ),
+
+ "COMSTOP"
+ => array (
+ "flag" => "COMSTOP",
+ "type" => "integer",
+ "value" => "1",
+ "cfgsec" => "serial"
+ ),
+
+ // End Serial Options
+
+ // Begin Download Protocols
+
+ "HDR_DOWNLOAD_PROTOCOLS"
+ => array (
+ "flag" => "HDR_DOWNLOAD_PROTOCOLS",
+ "type" => "header",
+ "label" => "Download Protocols"
+ ),
+
+ "DOWNLOAD_PROTO_TFTP"
+ => array (
+ "flag" => "DOWNLOAD_PROTO_TFTP",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "DOWNLOAD_PROTO_HTTP"
+ => array (
+ "flag" => "DOWNLOAD_PROTO_HTTP",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "DOWNLOAD_PROTO_HTTPS"
+ => array (
+ "flag" => "DOWNLOAD_PROTO_HTTPS",
+ "type" => "on/off",
+ "value" => "off",
+ "cfgsec" => "general"
+ ),
+
+ "DOWNLOAD_PROTO_FTP"
+ => array (
+ "flag" => "DOWNLOAD_PROTO_FTP",
+ "type" => "on/off",
+ "value" => "off",
+ "cfgsec" => "general"
+ ),
+
+ // End Download Protocols
+
+ // Begin SAN boot protocols
+
+ "HDR_SANBOOT_PROTOCOLS"
+ => array (
+ "flag" => "HDR_SANBOOT_PROTOCOLS",
+ "type" => "header",
+ "label" => "SAN Boot Protocols"
+ ),
+
+ "SANBOOT_PROTO_ISCSI"
+ => array (
+ "flag" => "SANBOOT_PROTO_ISCSI",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "SANBOOT_PROTO_AOE"
+ => array (
+ "flag" => "SANBOOT_PROTO_AOE",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ // End SAN boot protocols
+
+ // Begin Name resolution modules
+
+ "HDR_NAME_RESOLUTION_MODULES"
+ => array (
+ "flag" => "HDR_NAME_RESOLUTION_MODULES",
+ "type" => "header",
+ "label" => "Name Resolution Modules"
+ ),
+
+ "DNS_RESOLVER"
+ => array (
+ "flag" => "DNS_RESOLVER",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "NMB_RESOLVER"
+ => array (
+ "flag" => "NMB_RESOLVER",
+ "type" => "on/off",
+ "value" => "off",
+ "hide_from_user" => "yes",
+ "cfgsec" => "general"
+ ),
+
+ // End Name resolution modules
+
+ // Begin Image types
+
+ "HDR_IMAGE_TYPES"
+ => array (
+ "flag" => "HDR_IMAGE_TYPES",
+ "type" => "header",
+ "label" => "Image Types",
+ ),
+
+ "IMAGE_ELF"
+ => array (
+ "flag" => "IMAGE_ELF",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "IMAGE_NBI"
+ => array (
+ "flag" => "IMAGE_NBI",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "IMAGE_MULTIBOOT"
+ => array (
+ "flag" => "IMAGE_MULTIBOOT",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "IMAGE_PXE"
+ => array (
+ "flag" => "IMAGE_PXE",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "IMAGE_SCRIPT"
+ => array (
+ "flag" => "IMAGE_SCRIPT",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "IMAGE_BZIMAGE"
+ => array (
+ "flag" => "IMAGE_BZIMAGE",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "IMAGE_COMBOOT"
+ => array (
+ "flag" => "IMAGE_COMBOOT",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ // End Image types
+
+ // Begin Command-line commands to include
+
+ "HDR_COMMAND_LINE_OPTIONS"
+ => array (
+ "flag" => "HDR_COMMAND_LINE_OPTIONS",
+ "type" => "header",
+ "label" => "Command Line Options",
+ ),
+
+ "AUTOBOOT_CMD"
+ => array (
+ "flag" => "AUTOBOOT_CMD",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "NVO_CMD"
+ => array (
+ "flag" => "NVO_CMD",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "CONFIG_CMD"
+ => array (
+ "flag" => "CONFIG_CMD",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "IFMGMT_CMD"
+ => array (
+ "flag" => "IFMGMT_CMD",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "IWMGMT_CMD"
+ => array (
+ "flag" => "IWMGMT_CMD",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "ROUTE_CMD"
+ => array (
+ "flag" => "ROUTE_CMD",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "IMAGE_CMD"
+ => array (
+ "flag" => "IMAGE_CMD",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "DHCP_CMD"
+ => array (
+ "flag" => "DHCP_CMD",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "SANBOOT_CMD"
+ => array (
+ "flag" => "SANBOOT_CMD",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "LOGIN_CMD"
+ => array (
+ "flag" => "LOGIN_CMD",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "TIME_CMD"
+ => array (
+ "flag" => "TIME_CMD",
+ "type" => "on/off",
+ "value" => "off",
+ "cfgsec" => "general"
+ ),
+
+ "DIGEST_CMD"
+ => array (
+ "flag" => "DIGEST_CMD",
+ "type" => "on/off",
+ "value" => "off",
+ "cfgsec" => "general"
+ ),
+
+ // End Command-line commands to include
+
+ // Begin Wireless options
+
+ "HDR_WIRELESS_OPTIONS"
+ => array (
+ "flag" => "HDR_WIRELESS_OPTIONS",
+ "type" => "header",
+ "label" => "Wireless Interface Options",
+ ),
+
+ "CRYPTO_80211_WEP"
+ => array (
+ "flag" => "CRYPTO_80211_WEP",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "CRYPTO_80211_WPA"
+ => array (
+ "flag" => "CRYPTO_80211_WPA",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ "CRYPTO_80211_WPA2"
+ => array (
+ "flag" => "CRYPTO_80211_WPA2",
+ "type" => "on/off",
+ "value" => "on",
+ "cfgsec" => "general"
+ ),
+
+ // End Wireless options
+
+ // Obscure options required to compile
+ "NETDEV_DISCARD_RATE"
+ => array (
+ "flag" => "NETDEV_DISCARD_RATE",
+ "type" => "integer",
+ "value" => "0",
+ "cfgsec" => "general",
+ "hide_from_user" => true
+ )
+
+ // End Obscure options
+);
+
+// For emacs:
+// Local variables:
+// c-basic-offset: 4
+// c-indent-level: 4
+// tab-width: 4
+// End:
+
+?>
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/globals.php b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/globals.php
new file mode 100644
index 00000000..822e4bc0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/globals.php
@@ -0,0 +1,51 @@
+<?php // -*- Mode: PHP; -*-
+
+/**
+ * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
+ * Copyright (C) 2009 Entity Cyber, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+// Directory containing iPXE source code tree
+$src_dir = "../../src";
+
+// Compute iPXE version based on source tree
+exec ( "make -C '$src_dir' version 2>&1", $make_output, $status );
+$version = ( $status == 0 && count ( $make_output ) > 1 )
+ ? trim ( $make_output[count ( $make_output ) - 2] )
+ : "";
+
+// Email address of person responsible for this website
+$webmaster_email = "webmaster@example.com";
+
+// Files that header and footer text
+$top_inc = "top.php";
+$bottom_inc = "bottom.php";
+
+// Descriptive strings
+$header_title = "ROM-o-matic for iPXE $version";
+$html_tagline = "ROM-o-matic dynamically generates iPXE images";
+$html_title = "ROM-o-matic for iPXE $version";
+$description = "a dynamic iPXE image generator";
+
+// For emacs:
+// Local variables:
+// c-basic-offset: 4
+// c-indent-level: 4
+// tab-width: 4
+// End:
+
+?>
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/index.php b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/index.php
new file mode 100644
index 00000000..26585c97
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/index.php
@@ -0,0 +1,47 @@
+<?php // -*- Mode: PHP; -*-
+
+/**
+ * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
+ * Copyright (C) 2009 Entity Cyber, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+// Get utility functions and set globals
+require_once "utils.php";
+
+// Begin html output
+include_once $top_inc;
+
+?>
+<form action="build.php" method=POST>
+ <input type="hidden" name="version" value = "<?php echo $version ?>">
+ <h3>To create an image:</h3>
+ <ol>
+ <?php require ( "directions.php" ); ?>
+ <li>
+ Generate and download an image:
+ <input type="submit" name="A" value="Get Image">
+ <br><br>
+ </li>
+ <li>
+ (optional) Customize image configuration options:
+ <input type="submit" name="A" value="Customize">
+ <br><br>
+ </li>
+ </ol>
+</form>
+
+<?php include_once $bottom_inc ?>
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/top.php b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/top.php
new file mode 100644
index 00000000..42a8e2d2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/top.php
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<?php
+
+/**
+ * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
+ * Copyright (C) 2009 Entity Cyber, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+?>
+
+<html>
+<head>
+ <link rev="made" href="mailto:<?php echo "${webmaster_email}" ?>">
+ <meta name="keywords" content="rom, etherboot, ipxe, open source, rom-o-matic.net">
+ <title><?php echo $header_title ?></title>
+ <meta name="description" content="<?php echo $description ?>">
+</head>
+<h1>
+<?php echo "$html_title" ?>&nbsp;
+</h1>
+<hr>
+<h2>
+<?php echo "$html_tagline" ?>
+</h2>
+</form>
+<hr>
diff --git a/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/utils.php b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/utils.php
new file mode 100644
index 00000000..e0e62f44
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/rom-o-matic/utils.php
@@ -0,0 +1,684 @@
+<?php // -*- Mode: PHP; -*-
+
+/**
+ * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
+ * Copyright (C) 2009 Entity Cyber, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+// Include table of user-configurable iPXE options
+require_once "flag-table.php";
+
+// Include user-shadowable globals
+require_once "globals.php";
+
+// Allow user to shadow globals
+if ( is_file ( 'local-config.php' ) ) {
+ include_once "local-config.php";
+}
+
+////
+// General utility functions
+////
+
+/**
+ * Remove undesirable characters from a given string
+ *
+ * Certain characters have the potential to be used for
+ * malicious purposes by web-based attackers. This routine
+ * filters out such characters.
+ *
+ * @param string $s supplied string
+ *
+ * @return string returned string with unwanted characters
+ * removed
+ */
+function cleanstring ( $s )
+{
+ $len = strlen ( $s );
+ if ( $len > 80 ) {
+ $s = substr ( $s, 0, 80 );
+ }
+
+ $s = trim ( $s );
+ $pos = 0;
+ $result = "";
+
+ while ( $pos < $len ) {
+ $ltr = ord ( ucfirst ( $s[$pos] ) );
+ if ( ( $ltr >= ord ( "A" ) ) && ( $ltr <= ord ( "Z" ) ) ||
+ ( $ltr >= ord ( "0" ) ) && ( $ltr <= ord ( "9" ) ) ||
+ ( $ltr == ord ( "." ) ) && ( strlen ( $result ) > 0 ) ||
+ ( $ltr == ord ( "_" ) ) ||
+ ( $ltr == ord ( "+" ) ) ||
+ ( $ltr == ord ( ":" ) ) ||
+ ( $ltr == ord ( "/" ) ) ||
+ ( $ltr == ord ( "-" ) ) ) {
+ $result .= $s[$pos];
+ }
+ $pos++;
+ }
+ return $result;
+}
+
+/**
+ * Return URL of the currently running script, minus the filename
+ *
+ * @return string the URL of the currently running script, minus the filename
+ */
+function curDirURL ()
+{
+ $dir = dirname ( $_SERVER['PHP_SELF'] );
+
+ if ( $dir == "." || $dir == "/" ) {
+ $dir = "";
+ }
+
+ $isHTTPS = ( isset ( $_SERVER["HTTPS"] ) && $_SERVER["HTTPS"] == "on" );
+ $port = ( isset($_SERVER["SERVER_PORT"] ) &&
+ ( ( !$isHTTPS && $_SERVER["SERVER_PORT"] != "80" ) ||
+ ( $isHTTPS && $_SERVER["SERVER_PORT"] != "443" ) ) );
+
+ $port = ( $port ) ? ':' . $_SERVER["SERVER_PORT"] : '';
+
+ $dest = ( $isHTTPS ? 'https://' : 'http://' ) .
+ $_SERVER["SERVER_NAME"] . $dir . "/";
+
+ return $dest;
+}
+
+/**
+ * Extract NIC families and associated ROM PCI IDs from the src/bin/NIC file.
+ *
+ * $src_dir must contain the path of the iPXE src directory for this build
+ *
+ * @return array[0] array $new_nics
+ * @return array[1] array $roms
+ */
+function parse_nic_file ()
+{
+ global $src_dir;
+
+ $fd = fopen ( "$src_dir/bin/NIC", "r" );
+ if ( ! $fd ) {
+ die ( "Missing src/bin/NIC file. 'make bin/NIC'" );
+ }
+
+ $nics = array ();
+ $roms = array ();
+ $nic = "";
+
+ while ( !feof ( $fd ) ) {
+
+ $line = trim ( fgets ( $fd, 200 ) );
+
+ $first_eight_chars = substr ( $line, 0, 8 );
+ settype ( $first_eight_chars, "string" );
+
+ if ( strpos ( $first_eight_chars, "family" ) === 0 ) {
+
+ // get pathname of NIC driver
+ #list ( $dummy, $nic ) = split( "[ \t]+", $line );
+ list ( $dummy, $nic ) = explode("\t", $line);
+ settype ( $nic, "string" );
+
+ // extract filename name of driver from pathname
+ $nic = substr ( $nic, strrpos ( $nic, "/" ) + 1,
+ strlen ( $nic ) - strrpos ( $nic, "/" ) + 1 );
+
+ $nics[$nic] = $nic;
+
+ // For each ISA NIC, there can only be one ROM variant
+ $roms[$nic] = $nic;
+ }
+
+ // If the first 8 digits of the line are hex digits
+ // add this rom to the current nic family.
+
+ if ( ( strlen ( $first_eight_chars ) == 8 )
+ && ( ctype_xdigit ( $first_eight_chars ) )
+ && ( $nic != "" ) ) {
+
+ $roms[$first_eight_chars] = $nic;
+ }
+ }
+ fclose ( $fd );
+
+ // put most NICs in nice alpha order for menu
+ ksort ( $nics );
+
+ // add special cases to the top
+
+ $new_nics = array ( "all-drivers" => "ipxe",
+ "undionly" => "undionly",
+ "undi" => "undi",
+ );
+
+ foreach ( $nics as $key => $value ) {
+ // skip the undi driver
+ if ( $key != "undi" ) {
+ $new_nics[$key] = $value;
+ }
+ }
+
+ return array ( $new_nics, $roms );
+}
+
+////
+// HTML form utility functions
+////
+
+/**
+ * Return html code to create hidden form input fields
+ *
+ * @param string $flag name of form variable to set
+ * @param string $value value to give form variable
+ *
+ * @return string html code for given hidden form input field
+ */
+function hidden ( $flag, $value )
+{
+ $value = htmlentities ( $value );
+ return "<input type=\"hidden\" value=\"$value\" name=\"$flag\"></input>";
+}
+
+/**
+ * Return html code to create checkbox form input fields
+ *
+ * @param string $flag name of form variable to set
+ * @param string $value "on" means box should be checked
+ *
+ * @return string html code for given hidden form input field
+ */
+function checkbox ( $flag, $value )
+{
+ return "<input type=\"checkbox\" value=\"on\" name=\"$flag\"" .
+ ($value == "on" ? " checked>" : ">" );
+}
+
+/**
+ * Return html code to create text form input fields
+ *
+ * @param string $flag name of form variable to set
+ * @param string $value initial contents of field
+ * @param string $size size in characters of text box
+ *
+ * @return string html code for given text input field
+ */
+function textbox ( $flag, $value, $size )
+{
+ $value = htmlentities ( $value );
+ return "<input type=\"text\" size=\"$size\" value=\"$value\" name=\"$flag\">";
+}
+
+/**
+ * Return html code to create textarea form fields
+ *
+ * @param string $flag name of form variable to set
+ * @param string $value initial contents of textarea
+ * @param string $rows height of text area in rows
+ * @param string $cols width of text area in columns
+ *
+ * @return string html code for given textarea input field
+ */
+function textarea ( $flag, $value, $rows, $cols )
+{
+ $value = htmlentities ( $value );
+ return "<textarea name=\"$flag\" rows=\"$rows\" cols=\"$cols\">"
+ . $value . "</textarea>";
+}
+
+/**
+ * Return html code to create select (menu) form fields
+ *
+ * Use array of strings as menu choices
+ *
+ * @param string $flag name of form variable to set
+ * @param array $options array of strings representing choices
+ * @param string $value value of choice to select in menu
+ *
+ * @return string html code for given select (menu) input field
+ */
+function menubox ( $name, $options, $value )
+{
+ $s="<select name=\"$name\">";
+
+ foreach ( $options as $ignore => $option ) {
+ if ( !$value ) $value = $option;
+ $s .= "<option" . ( $option == $value ? " selected>" : ">" ) .
+ htmlentities ( $option ) . "</option>";
+ }
+ return $s . "</select>";
+}
+
+/**
+ * Return html code to create select (menu) form fields
+ *
+ * Use indices of array of strings as menu choices rather than
+ * the values pointed to by the indicies.
+ *
+ * @param string $flag name of form variable to set
+ * @param array $options array of strings representing choices
+ * @param string $value value of choice to select in menu
+ *
+ * @return string html code for given select (menu) input field
+ */
+function keys_menubox ( $name, $options, $value )
+{
+ $s="<select name=\"$name\">";
+
+ foreach ( $options as $option => $ignore ) {
+ if ( !$value ) $value = $option;
+ $s .= "<option" . ( $option == $value ? " selected>" : ">" ) .
+ htmlentities ( $option ) . "</option>";
+ }
+ return $s . "</select>";
+}
+
+////
+// Flag (compile option) handling functions
+////
+
+/**
+ * Return default compile options (flags)
+ *
+ * Initial compile options are in a global called $flag_table.
+ * Create and return an array containing the ones we want.
+ *
+ * @return array default compile options (flags)
+ */
+function default_flags ()
+{
+ global $flag_table;
+
+ $flags = array ();
+
+ foreach ( $flag_table as $key => $props ) {
+
+ $flag = $props["flag"];
+ $type = $props["type"];
+
+ // Fields like headers have no "value" property
+ if ( isset ( $props["value"] ) ) {
+ $flags[$flag] = $props["value"];
+ }
+ }
+ return $flags;
+}
+
+/**
+ * Return combination of default and user compile options (flags)
+ *
+ * Initial compile options are in a global called $flag_table.
+ * Compile options may have been changed via form input. We return
+ * an array with either the default value of each option or a user
+ * supplied value from form input.
+ *
+ * @return array combined default and user supplied compile options (flags)
+ */
+function get_flags ()
+{
+ global $flag_table;
+
+ $flags = default_flags ();
+
+ if ( ! isset ( $_POST["use_flags"] ) )
+ return $flags;
+
+ foreach ( $flag_table as $key => $props ) {
+
+ $flag = $props["flag"];
+ $type = $props["type"];
+
+ if ( isset ( $_POST["$flag"] ) ) {
+ $flags[$flag] = $_POST["$flag"];
+ if ( $type == "integer-hex" ) {
+ if ( strtolower ( substr ( $flags[$flag], 0, 2 ) ) != "0x" ) {
+ $flags[$flag] = "0x" . $flags[$flag];
+ }
+ }
+ } else if ( $type == "on/off" ) {
+ // Unchecked checkboxes don't pass any POST value
+ // so we must check for them specially. At this
+ // point we know that there is no $_POST value set
+ // for this option. If it is a checkbox, this means
+ // it is unchecked, so record that in $flags so we
+ // can later generate an #undef for this option.
+ $flags[$flag] = "off";
+ }
+ }
+ return $flags;
+}
+
+/**
+ * Output given value in appropriate format for iPXE config file
+ *
+ * iPXE config/*.h files use C pre-processor syntax. Output the given
+ * compile option in a format appropriate to its type
+ *
+ * @param string $key index into $flag_table for given compile option
+ * @param string $value value we wish to set compile option to
+ *
+ * @return string code to set compile option to given value
+ */
+function pprint_flag ( $key, $value )
+{
+ global $flag_table;
+
+ // Determine type of given compile option (flag)
+ $type = $flag_table[$key]["type"];
+ $s = "";
+
+ if ( $type == "on/off" && $value == "on" ) {
+ $s = "#define $key";
+ } else if ( $type == "on/off" && $value != "on" ) {
+ $s = "#undef $key";
+ } else if ( $type == "string" ) {
+ $s = ( "#define $key \"" . cleanstring ( $value ) . "\"" );
+ } else if ($type == "qstring" ) {
+ $s = ( "#define $key \\\"" . cleanstring ( $value ) . "\\\"" );
+ } else {
+ $s = "#define $key " . cleanstring ( $value );
+ }
+
+ return $s;
+}
+
+/**
+ * Output html code to display all compile options as a table
+ *
+ * @param array $flags array of compile options
+ *
+ * @return void
+ */
+function echo_flags ( $flags )
+{
+ global $flag_table;
+
+ echo "<table>\n";
+
+ foreach ( $flag_table as $key => $props ) {
+
+ // Hide parameters from users that should not be changed.
+ $hide_from_user = isset ( $props["hide_from_user"] ) ? $props["hide_from_user"] : "no";
+
+ $flag = $props["flag"];
+ $type = $props["type"];
+
+ $value = isset ( $flags[$flag] ) ? $flags[$flag] : '';
+
+ if ( $hide_from_user == "yes" ) {
+
+ // Hidden flags cannot not be set by the user. We use hidden form
+ // fields to keep them at their default values.
+ if ( $type != "header" ) {
+ echo hidden ( $flag, $value );
+ }
+
+ } else {
+
+ // Flag (iPXE compile option) should be displayed to user
+
+ if ( $type == "header" ) {
+
+ $label = $props["label"];
+ echo "<td colspan=2><hr><h3>$label</h3><hr></td>";
+
+ } else if ($type == "on/off" ) {
+
+ echo "<td>", checkbox ( $flag, $value ), "</td><td><strong>$flag</strong></td>";
+
+ } else { // don't display checkbox for non-on/off flags
+
+ echo "<td>&nbsp;</td><td><strong>$flag: </strong>";
+
+ if ($type == "choice" ) {
+ $options = $props["options"];
+ echo menubox($flag, $options, $value);
+
+ } else {
+
+ echo textbox($flag, $value, ($type == "integer" ||
+ $type == "integer-hex"
+ ? 7 : 25));
+ }
+ echo "</td>";
+ }
+ echo "</tr>\n";
+
+ if ( $type != "header" ) {
+ echo "<tr><td>&nbsp;</td>";
+ echo "<td>\n";
+ if ( is_file ( "doc/$flag.html" ) ) {
+ include_once "doc/$flag.html";
+ }
+ echo "\n</td></tr>\n";
+ }
+ }
+ }
+ echo "</table>";
+}
+
+/**
+ * Return an array of configuration sections used in all compile options
+ *
+ * $flag_table, the global list of compile options contains a 'cfgsec'
+ * property for each flag we are interested in. We return a list of
+ * all the unique cfgsec options we find in $flag_table.
+ *
+ * @return array an array of strings representing all unique cfgsec values
+ * found in $flag_table
+ */
+function get_flag_cfgsecs ()
+{
+ global $flag_table;
+ $cfgsecs = array ();
+
+ foreach ( $flag_table as $key => $props ) {
+ if ( isset ( $props['cfgsec'] ) ) {
+ $cfgsec = $props["cfgsec"];
+ $cfgsecs[$cfgsec] = $cfgsec;
+ }
+ }
+ return $cfgsecs;
+}
+
+////
+// File and directory handling functions
+////
+
+/**
+ * Create a copy of a given source directory to a given destination
+ *
+ * Since we are going to modify the source directory, we create a copy
+ * of the directory with a unique name in the given destination directory.
+ * We supply a prefix for the tempnam call to prepend to the random filename
+ * it generates.
+ *
+ * @param string $src source directory
+ * @param string $dst destination directory
+ * @param string $prefix string to append to directory created
+ *
+ * @return string absolute path to destination directory
+ */
+function mktempcopy ( $src, $dst, $prefix )
+{
+ if ( $src[0] != "/" ) {
+ $src = dirname ( $_SERVER['SCRIPT_FILENAME'] ) . "/" . $src;
+ }
+
+ // Create a file in the given destination directory with a unique name
+ $dir = tempnam ( $dst, $prefix );
+
+ // Delete the file just created, since it would interfere with the copy we
+ // are about to do. We only care that the dir name we copy to is unique.
+ unlink ( $dir );
+
+ exec ( "/bin/cp -a '$src' '$dir' 2>&1", $cpytxt, $status );
+
+ if ( $status != 0 ) {
+ die ( "src directory copy failed!" );
+ }
+ return $dir;
+}
+
+/**
+ * Write iPXE config files based on value of given flags
+ *
+ * iPXE compile options are stored in src/config/*.h .
+ * We write out a config file for each set of options.
+ *
+ * @param string $config_dir directory to write .h files to
+ * @param array $flags array of compile options for this build
+ *
+ * @return void
+ */
+function write_ipxe_config_files ( $config_dir, $flags )
+{
+ global $flag_table;
+
+ $cfgsecs = get_flag_cfgsecs ();
+
+ foreach ( $cfgsecs as $cfgsec ) {
+
+ $fname = $config_dir . "/" . $cfgsec . ".h";
+
+ $fp = fopen ( $fname, "wb" );
+ if ( $fp <= 0 ) {
+ die ( "Unable to open $fname file for output!" );
+ }
+
+ $ifdef_secname = "CONFIG_" . strtoupper ( $cfgsec ) . "_H";
+
+ fwrite ( $fp, "#ifndef ${ifdef_secname}\n" );
+ fwrite ( $fp, "#define ${ifdef_secname}\n" );
+ fwrite ( $fp, "#include <config/defaults.h>\n" );
+
+ foreach ( $flags as $key => $value ) {
+ // When the flag matches this section name, write it out
+ if ( $flag_table[$key]["cfgsec"] == $cfgsec ) {
+ fwrite ( $fp, pprint_flag ( $key, $value ) . "\n" );
+ }
+ }
+ fwrite ( $fp, "#endif /* ${ifdef_secname} */\n" );
+ fclose ( $fp );
+ }
+}
+
+/**
+ * Output a string to a file
+ *
+ * Output a given string to a given pathname. The file will be created if
+ * necessary, and the string will replace the file's contents in all cases.
+ *
+ * @param string $fname pathname of file to output string to
+ * @param string $ftext text to output to file
+ *
+ * @return void
+ */
+function write_file_from_string ( $fname, $ftext )
+{
+ $fp = fopen ( $fname, "wb" );
+ if ( ! $fp ) {
+ die ( "Unable to open $fname file for output!" );
+ }
+ fwrite ( $fp, $ftext );
+ fclose ( $fp );
+}
+
+/**
+ * Delete a file or recursively delete a directory tree
+ *
+ * @param string $file_or_dir_name name of file or directory to delete
+ * @return bool Returns TRUE on success, FALSE on failure
+ */
+function rm_file_or_dir ( $file_or_dir_name )
+{
+ if ( ! file_exists ( $file_or_dir_name ) ) {
+ return false;
+ }
+
+ if ( is_file ( $file_or_dir_name ) || is_link ( $file_or_dir_name ) ) {
+ return unlink ( $file_or_dir_name );
+ }
+
+ $dir = dir ( $file_or_dir_name );
+ while ( ( $dir_entry = $dir->read () ) !== false ) {
+
+ if ( $dir_entry == '.' || $dir_entry == '..') {
+ continue;
+ }
+ rm_file_or_dir ( $file_or_dir_name . '/' . $dir_entry );
+ }
+ $dir->close();
+
+ return rmdir ( $file_or_dir_name );
+}
+
+////
+// Debugging functions
+////
+
+/**
+ * Emit html code to display given array of compile options (flags)
+ *
+ * @param array $flags array of compile options for this build
+ *
+ * @return void
+ */
+function show_flags ( $flags )
+{
+ echo ( "\$flags contains " . count ( $flags ) . " elements:" . "<br>" );
+
+ foreach ( $flags as $key => $flag ) {
+ echo ( "\$flags[" . $key . "]=" . "\"$flag\"" . "<br>" );
+ }
+}
+
+/**
+ * Emit HTML code to display default array of compile options (flags)
+ *
+ * $flag_table contains default compile options and properties. This
+ * routine outputs HTML code to display all properties of $flag_table.
+ *
+ * @return void
+ */
+function dump_flag_table ()
+{
+ global $flag_table;
+
+ echo ( "\$flag_table contains " . count ( $flag_table ) . " elements:" . "<br>" );
+
+ foreach ( $flag_table as $key => $props ) {
+ print ( "flag_table[" . $key . "] = " . "<br>" );
+
+ foreach ( $props as $key2 => $props2 ) {
+ print ( "&nbsp;&nbsp;&nbsp;" . $key2 . " = " . $props2 . "<br>" );
+ }
+ }
+}
+
+// Parse src/bin/NIC file
+list ( $nics, $roms ) = parse_nic_file ();
+
+// For emacs:
+// Local variables:
+// c-basic-offset: 4
+// c-indent-level: 4
+// tab-width: 4
+// End:
+
+?>
diff --git a/src/VBox/Devices/PC/ipxe/contrib/vm/Makefile b/src/VBox/Devices/PC/ipxe/contrib/vm/Makefile
new file mode 100644
index 00000000..3c0e645a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/vm/Makefile
@@ -0,0 +1,7 @@
+all : serial-console.1
+
+%.1 : %
+ pod2man $< > $@
+
+clean :
+ rm -f serial-console.1
diff --git a/src/VBox/Devices/PC/ipxe/contrib/vm/bochs-writable-ROM-patch b/src/VBox/Devices/PC/ipxe/contrib/vm/bochs-writable-ROM-patch
new file mode 100644
index 00000000..dc586dde
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/vm/bochs-writable-ROM-patch
@@ -0,0 +1,15 @@
+--- memory/memory.cc 18 Oct 2008 18:10:14 -0000 1.71
++++ memory/memory.cc 21 Oct 2008 19:47:07 -0000
+@@ -172,7 +172,11 @@
+ break;
+
+ case 0x0: // Writes to ROM, Inhibit
+- BX_DEBUG(("Write to ROM ignored: address 0x" FMT_PHY_ADDRX ", data %02x", a20addr, *data_ptr));
++ if ((a20addr & 0xfffe0000) == 0x000e0000) {
++ BX_DEBUG(("Write to ROM ignored: address 0x" FMT_PHY_ADDRX ", data %02x", a20addr, *data_ptr));
++ } else {
++ BX_MEM_THIS rom[(a20addr & EXROM_MASK) + BIOSROMSZ] = *data_ptr;
++ }
+ break;
+
+ default:
diff --git a/src/VBox/Devices/PC/ipxe/contrib/vm/bochsrc.txt b/src/VBox/Devices/PC/ipxe/contrib/vm/bochsrc.txt
new file mode 100644
index 00000000..32842a3b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/vm/bochsrc.txt
@@ -0,0 +1,751 @@
+# You may now use double quotes around pathnames, in case
+# your pathname includes spaces.
+
+#=======================================================================
+# CONFIG_INTERFACE
+#
+# The configuration interface is a series of menus or dialog boxes that
+# allows you to change all the settings that control Bochs's behavior.
+# There are two choices of configuration interface: a text mode version
+# called "textconfig" and a graphical version called "wx". The text
+# mode version uses stdin/stdout and is always compiled in. The graphical
+# version is only available when you use "--with-wx" on the configure
+# command. If you do not write a config_interface line, Bochs will
+# choose a default for you.
+#
+# NOTE: if you use the "wx" configuration interface, you must also use
+# the "wx" display library.
+#=======================================================================
+#config_interface: textconfig
+#config_interface: wx
+
+#=======================================================================
+# DISPLAY_LIBRARY
+#
+# The display library is the code that displays the Bochs VGA screen. Bochs
+# has a selection of about 10 different display library implementations for
+# different platforms. If you run configure with multiple --with-* options,
+# the display_library command lets you choose which one you want to run with.
+# If you do not write a display_library line, Bochs will choose a default for
+# you.
+#
+# The choices are:
+# x use X windows interface, cross platform
+# win32 use native win32 libraries
+# carbon use Carbon library (for MacOS X)
+# beos use native BeOS libraries
+# macintosh use MacOS pre-10
+# amigaos use native AmigaOS libraries
+# sdl use SDL library, cross platform
+# svga use SVGALIB library for Linux, allows graphics without X11
+# term text only, uses curses/ncurses library, cross platform
+# rfb provides an interface to AT&T's VNC viewer, cross platform
+# wx use wxWidgets library, cross platform
+# nogui no display at all
+#
+# NOTE: if you use the "wx" configuration interface, you must also use
+# the "wx" display library.
+#
+# Specific options:
+# Some display libraries now support specific option to control their
+# behaviour. See the examples below for currently supported options.
+#=======================================================================
+#display_library: amigaos
+#display_library: beos
+#display_library: carbon
+#display_library: macintosh
+#display_library: nogui
+#display_library: rfb, options="timeout=60" # time to wait for client
+#display_library: sdl, options="fullscreen" # startup in fullscreen mode
+#display_library: term
+#display_library: win32, options="legacyF12" # use F12 to toggle mouse
+#display_library: wx
+#display_library: x
+
+#=======================================================================
+# ROMIMAGE:
+# The ROM BIOS controls what the PC does when it first powers on.
+# Normally, you can use a precompiled BIOS in the source or binary
+# distribution called BIOS-bochs-latest. The ROM BIOS is usually loaded
+# starting at address 0xf0000, and it is exactly 64k long.
+# You can also use the environment variable $BXSHARE to specify the
+# location of the BIOS.
+# The usage of external large BIOS images (up to 512k) at memory top is
+# now supported, but we still recommend to use the BIOS distributed with
+# Bochs. Now the start address can be calculated from image size.
+#=======================================================================
+romimage: file=bochs/bios/BIOS-bochs-latest, address=0xe0000
+#romimage: file=mybios.bin, address=0xfff80000 # 512k at memory top
+#romimage: file=mybios.bin # calculate start address from image size
+
+#=======================================================================
+# CPU:
+# This defines cpu-related parameters inside Bochs:
+#
+# COUNT:
+# Set the number of processors:cores per processor:threads per core
+# when Bochs is compiled for SMP emulation.
+# Bochs currently supports up to 8 threads running simultaniosly.
+# If Bochs is compiled without SMP support, it won't accept values
+# different from 1.
+#
+# RESET_ON_TRIPLE_FAULT:
+# Reset the CPU when triple fault occur (highly recommended) rather than
+# PANIC. Remember that if you trying to continue after triple fault the
+# simulation will be completely bogus !
+#
+# IPS:
+# Emulated Instructions Per Second. This is the number of IPS that bochs
+# is capable of running on your machine. You can recompile Bochs with
+# --enable-show-ips option enabled, to find your workstation's capability.
+# Measured IPS value will then be logged into your log file or status bar
+# (if supported by the gui).
+#
+# IPS is used to calibrate many time-dependent events within the bochs
+# simulation. For example, changing IPS affects the frequency of VGA
+# updates, the duration of time before a key starts to autorepeat, and
+# the measurement of BogoMips and other benchmarks.
+#
+# Examples:
+# Machine Mips
+# ________________________________________________________________
+# 2.1Ghz Athlon XP with Linux 2.6/g++ 3.4 12 to 15 Mips
+# 1.6Ghz Intel P4 with Win2000/g++ 3.3 5 to 7 Mips
+# 650Mhz Athlon K-7 with Linux 2.4.4/egcs-2.91.66 2 to 2.5 Mips
+# 400Mhz Pentium II with Linux 2.0.36/egcs-1.0.3 1 to 1.8 Mips
+#=======================================================================
+cpu: count=1, ips=10000000, reset_on_triple_fault=1
+
+#=======================================================================
+# MEGS
+# Set the number of Megabytes of physical memory you want to emulate.
+# The default is 32MB, most OS's won't need more than that.
+# The maximum amount of memory supported is 2048Mb.
+#=======================================================================
+#megs: 256
+#megs: 128
+#megs: 64
+megs: 32
+#megs: 16
+#megs: 8
+
+#=======================================================================
+# OPTROMIMAGE[1-4]:
+# You may now load up to 4 optional ROM images. Be sure to use a
+# read-only area, typically between C8000 and EFFFF. These optional
+# ROM images should not overwrite the rombios (located at
+# F0000-FFFFF) and the videobios (located at C0000-C7FFF).
+# Those ROM images will be initialized by the bios if they contain
+# the right signature (0x55AA) and a valid checksum.
+# It can also be a convenient way to upload some arbitrary code/data
+# in the simulation, that can be retrieved by the boot loader
+#=======================================================================
+#optromimage1: file=optionalrom.bin, address=0xd0000
+#optromimage2: file=optionalrom.bin, address=0xd1000
+#optromimage3: file=optionalrom.bin, address=0xd2000
+#optromimage4: file=optionalrom.bin, address=0xd3000
+optromimage1: file=../../src/bin/pnic.rom, address=0xd0000
+#optromimage1: file=../../src/bin/rtl8029.rom, address=0xd0000
+
+#optramimage1: file=/path/file1.img, address=0x0010000
+#optramimage2: file=/path/file2.img, address=0x0020000
+#optramimage3: file=/path/file3.img, address=0x0030000
+#optramimage4: file=/path/file4.img, address=0x0040000
+
+#=======================================================================
+# VGAROMIMAGE
+# You now need to load a VGA ROM BIOS into C0000.
+#=======================================================================
+#vgaromimage: file=bios/VGABIOS-elpin-2.40
+vgaromimage: file=bochs/bios/VGABIOS-lgpl-latest
+#vgaromimage: file=bios/VGABIOS-lgpl-latest-cirrus
+
+#=======================================================================
+# VGA:
+# Here you can specify the display extension to be used. With the value
+# 'none' you can use standard VGA with no extension. Other supported
+# values are 'vbe' for Bochs VBE and 'cirrus' for Cirrus SVGA support.
+#=======================================================================
+#vga: extension=cirrus
+#vga: extension=vbe
+vga: extension=none
+
+#=======================================================================
+# FLOPPYA:
+# Point this to pathname of floppy image file or device
+# This should be of a bootable floppy(image/device) if you're
+# booting from 'a' (or 'floppy').
+#
+# You can set the initial status of the media to 'ejected' or 'inserted'.
+# floppya: 2_88=path, status=ejected (2.88M 3.5" floppy)
+# floppya: 1_44=path, status=inserted (1.44M 3.5" floppy)
+# floppya: 1_2=path, status=ejected (1.2M 5.25" floppy)
+# floppya: 720k=path, status=inserted (720K 3.5" floppy)
+# floppya: 360k=path, status=inserted (360K 5.25" floppy)
+# floppya: 320k=path, status=inserted (320K 5.25" floppy)
+# floppya: 180k=path, status=inserted (180K 5.25" floppy)
+# floppya: 160k=path, status=inserted (160K 5.25" floppy)
+# floppya: image=path, status=inserted (guess type from image size)
+#
+# The path should be the name of a disk image file. On Unix, you can use a raw
+# device name such as /dev/fd0 on Linux. On win32 platforms, use drive letters
+# such as a: or b: as the path. The parameter 'image' works with image files
+# only. In that case the size must match one of the supported types.
+#=======================================================================
+#floppya: 1_44=/dev/fd0, status=inserted
+#floppya: image=../1.44, status=inserted
+#floppya: 1_44=/dev/fd0H1440, status=inserted
+#floppya: 1_2=../1_2, status=inserted
+#floppya: 1_44=a:, status=inserted
+#floppya: 1_44=a.img, status=inserted
+#floppya: 1_44=/dev/rfd0a, status=inserted
+floppya: 1_44=../../src/bin/pnic.dsk, status=inserted
+
+#=======================================================================
+# FLOPPYB:
+# See FLOPPYA above for syntax
+#=======================================================================
+#floppyb: 1_44=b:, status=inserted
+floppyb: 1_44=b.img, status=inserted
+
+#=======================================================================
+# ATA0, ATA1, ATA2, ATA3
+# ATA controller for hard disks and cdroms
+#
+# ata[0-3]: enabled=[0|1], ioaddr1=addr, ioaddr2=addr, irq=number
+#
+# These options enables up to 4 ata channels. For each channel
+# the two base io addresses and the irq must be specified.
+#
+# ata0 and ata1 are enabled by default with the values shown below
+#
+# Examples:
+# ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
+# ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
+# ata2: enabled=1, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
+# ata3: enabled=1, ioaddr1=0x168, ioaddr2=0x360, irq=9
+#=======================================================================
+ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
+ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
+ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
+ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9
+
+#=======================================================================
+# ATA[0-3]-MASTER, ATA[0-3]-SLAVE
+#
+# This defines the type and characteristics of all attached ata devices:
+# type= type of attached device [disk|cdrom]
+# mode= only valid for disks [flat|concat|external|dll|sparse|vmware3]
+# mode= only valid for disks [undoable|growing|volatile]
+# path= path of the image
+# cylinders= only valid for disks
+# heads= only valid for disks
+# spt= only valid for disks
+# status= only valid for cdroms [inserted|ejected]
+# biosdetect= type of biosdetection [none|auto], only for disks on ata0 [cmos]
+# translation=type of translation of the bios, only for disks [none|lba|large|rechs|auto]
+# model= string returned by identify device command
+# journal= optional filename of the redolog for undoable and volatile disks
+#
+# Point this at a hard disk image file, cdrom iso file, or physical cdrom
+# device. To create a hard disk image, try running bximage. It will help you
+# choose the size and then suggest a line that works with it.
+#
+# In UNIX it may be possible to use a raw device as a Bochs hard disk,
+# but WE DON'T RECOMMEND IT. In Windows there is no easy way.
+#
+# In windows, the drive letter + colon notation should be used for cdroms.
+# Depending on versions of windows and drivers, you may only be able to
+# access the "first" cdrom in the system. On MacOSX, use path="drive"
+# to access the physical drive.
+#
+# The path is always mandatory. For flat hard disk images created with
+# bximage geometry autodetection can be used (cylinders=0 -> cylinders are
+# calculated using heads=16 and spt=63). For other hard disk images and modes
+# the cylinders, heads, and spt are mandatory.
+#
+# Default values are:
+# mode=flat, biosdetect=auto, translation=auto, model="Generic 1234"
+#
+# The biosdetect option has currently no effect on the bios
+#
+# Examples:
+# ata0-master: type=disk, mode=flat, path=10M.sample, cylinders=306, heads=4, spt=17
+# ata0-slave: type=disk, mode=flat, path=20M.sample, cylinders=615, heads=4, spt=17
+# ata1-master: type=disk, mode=flat, path=30M.sample, cylinders=615, heads=6, spt=17
+# ata1-slave: type=disk, mode=flat, path=46M.sample, cylinders=940, heads=6, spt=17
+# ata2-master: type=disk, mode=flat, path=62M.sample, cylinders=940, heads=8, spt=17
+# ata2-slave: type=disk, mode=flat, path=112M.sample, cylinders=900, heads=15, spt=17
+# ata3-master: type=disk, mode=flat, path=483M.sample, cylinders=1024, heads=15, spt=63
+# ata3-slave: type=cdrom, path=iso.sample, status=inserted
+#=======================================================================
+#ata0-master: type=disk, mode=flat, path="30M.sample", cylinders=615, heads=6, spt=17
+#ata0-slave: type=cdrom, path=D:, status=inserted
+#ata0-slave: type=cdrom, path=/dev/cdrom, status=inserted
+#ata0-slave: type=cdrom, path="drive", status=inserted
+#ata0-slave: type=cdrom, path=/dev/rcd0d, status=inserted
+
+#=======================================================================
+# BOOT:
+# This defines the boot sequence. Now you can specify up to 3 boot drives.
+# You can either boot from 'floppy', 'disk' or 'cdrom'
+# legacy 'a' and 'c' are also supported
+# Examples:
+# boot: floppy
+# boot: disk
+# boot: cdrom
+# boot: c
+# boot: a
+# boot: cdrom, floppy, disk
+#=======================================================================
+#boot: floppy
+#boot: disk
+boot: network, floppy
+
+#=======================================================================
+# CLOCK:
+# This defines the parameters of the clock inside Bochs:
+#
+# SYNC:
+# TO BE COMPLETED (see Greg explanation in feature request #536329)
+#
+# TIME0:
+# Specifies the start (boot) time of the virtual machine. Use a time
+# value as returned by the time(2) system call. If no time0 value is
+# set or if time0 equal to 1 (special case) or if time0 equal 'local',
+# the simulation will be started at the current local host time.
+# If time0 equal to 2 (special case) or if time0 equal 'utc',
+# the simulation will be started at the current utc time.
+#
+# Syntax:
+# clock: sync=[none|slowdown|realtime|both], time0=[timeValue|local|utc]
+#
+# Example:
+# clock: sync=none, time0=local # Now (localtime)
+# clock: sync=slowdown, time0=315529200 # Tue Jan 1 00:00:00 1980
+# clock: sync=none, time0=631148400 # Mon Jan 1 00:00:00 1990
+# clock: sync=realtime, time0=938581955 # Wed Sep 29 07:12:35 1999
+# clock: sync=realtime, time0=946681200 # Sat Jan 1 00:00:00 2000
+# clock: sync=none, time0=1 # Now (localtime)
+# clock: sync=none, time0=utc # Now (utc/gmt)
+#
+# Default value are sync=none, time0=local
+#=======================================================================
+#clock: sync=none, time0=local
+
+
+#=======================================================================
+# FLOPPY_BOOTSIG_CHECK: disabled=[0|1]
+# Enables or disables the 0xaa55 signature check on boot floppies
+# Defaults to disabled=0
+# Examples:
+# floppy_bootsig_check: disabled=0
+# floppy_bootsig_check: disabled=1
+#=======================================================================
+#floppy_bootsig_check: disabled=1
+floppy_bootsig_check: disabled=0
+
+#=======================================================================
+# LOG:
+# Give the path of the log file you'd like Bochs debug and misc. verbiage
+# to be written to. If you don't use this option or set the filename to
+# '-' the output is written to the console. If you really don't want it,
+# make it "/dev/null" (Unix) or "nul" (win32). :^(
+#
+# Examples:
+# log: ./bochs.out
+# log: /dev/tty
+#=======================================================================
+#log: /dev/null
+log: bochsout.txt
+
+#=======================================================================
+# LOGPREFIX:
+# This handles the format of the string prepended to each log line.
+# You may use those special tokens :
+# %t : 11 decimal digits timer tick
+# %i : 8 hexadecimal digits of cpu current eip (ignored in SMP configuration)
+# %e : 1 character event type ('i'nfo, 'd'ebug, 'p'anic, 'e'rror)
+# %d : 5 characters string of the device, between brackets
+#
+# Default : %t%e%d
+# Examples:
+# logprefix: %t-%e-@%i-%d
+# logprefix: %i%e%d
+#=======================================================================
+#logprefix: %t%e%d
+
+#=======================================================================
+# LOG CONTROLS
+#
+# Bochs now has four severity levels for event logging.
+# panic: cannot proceed. If you choose to continue after a panic,
+# don't be surprised if you get strange behavior or crashes.
+# error: something went wrong, but it is probably safe to continue the
+# simulation.
+# info: interesting or useful messages.
+# debug: messages useful only when debugging the code. This may
+# spit out thousands per second.
+#
+# For events of each level, you can choose to crash, report, or ignore.
+# TODO: allow choice based on the facility: e.g. crash on panics from
+# everything except the cdrom, and only report those.
+#
+# If you are experiencing many panics, it can be helpful to change
+# the panic action to report instead of fatal. However, be aware
+# that anything executed after a panic is uncharted territory and can
+# cause bochs to become unstable. The panic is a "graceful exit," so
+# if you disable it you may get a spectacular disaster instead.
+#=======================================================================
+panic: action=ask
+error: action=report
+info: action=report
+debug: action=ignore
+#pass: action=fatal
+
+#=======================================================================
+# DEBUGGER_LOG:
+# Give the path of the log file you'd like Bochs to log debugger output.
+# If you really don't want it, make it /dev/null or '-'. :^(
+#
+# Examples:
+# debugger_log: ./debugger.out
+#=======================================================================
+#debugger_log: /dev/null
+#debugger_log: debugger.out
+debugger_log: -
+
+#=======================================================================
+# COM1, COM2, COM3, COM4:
+# This defines a serial port (UART type 16550A). In the 'term' you can specify
+# a device to use as com1. This can be a real serial line, or a pty. To use
+# a pty (under X/Unix), create two windows (xterms, usually). One of them will
+# run bochs, and the other will act as com1. Find out the tty the com1
+# window using the `tty' command, and use that as the `dev' parameter.
+# Then do `sleep 1000000' in the com1 window to keep the shell from
+# messing with things, and run bochs in the other window. Serial I/O to
+# com1 (port 0x3f8) will all go to the other window.
+# Other serial modes are 'null' (no input/output), 'file' (output to a file
+# specified as the 'dev' parameter), 'raw' (use the real serial port - under
+# construction for win32), 'mouse' (standard serial mouse - requires
+# mouse option setting 'type=serial' or 'type=serial_wheel') and 'socket'
+# (connect a networking socket).
+#
+# Examples:
+# com1: enabled=1, mode=null
+# com1: enabled=1, mode=mouse
+# com2: enabled=1, mode=file, dev=serial.out
+# com3: enabled=1, mode=raw, dev=com1
+# com3: enabled=1, mode=socket, dev=localhost:8888
+#=======================================================================
+#com1: enabled=1, mode=term, dev=/dev/ttyp9
+
+
+#=======================================================================
+# PARPORT1, PARPORT2:
+# This defines a parallel (printer) port. When turned on and an output file is
+# defined the emulated printer port sends characters printed by the guest OS
+# into the output file. On some platforms a device filename can be used to
+# send the data to the real parallel port (e.g. "/dev/lp0" on Linux, "lpt1" on
+# win32 platforms).
+#
+# Examples:
+# parport1: enabled=1, file="parport.out"
+# parport2: enabled=1, file="/dev/lp0"
+# parport1: enabled=0
+#=======================================================================
+parport1: enabled=1, file="parport.out"
+
+#=======================================================================
+# SB16:
+# This defines the SB16 sound emulation. It can have several of the
+# following properties.
+# All properties are in the format sb16: property=value
+# midi: The filename is where the midi data is sent. This can be a
+# device or just a file if you want to record the midi data.
+# midimode:
+# 0=no data
+# 1=output to device (system dependent. midi denotes the device driver)
+# 2=SMF file output, including headers
+# 3=output the midi data stream to the file (no midi headers and no
+# delta times, just command and data bytes)
+# wave: This is the device/file where wave output is stored
+# wavemode:
+# 0=no data
+# 1=output to device (system dependent. wave denotes the device driver)
+# 2=VOC file output, incl. headers
+# 3=output the raw wave stream to the file
+# log: The file to write the sb16 emulator messages to.
+# loglevel:
+# 0=no log
+# 1=resource changes, midi program and bank changes
+# 2=severe errors
+# 3=all errors
+# 4=all errors plus all port accesses
+# 5=all errors and port accesses plus a lot of extra info
+# dmatimer:
+# microseconds per second for a DMA cycle. Make it smaller to fix
+# non-continuous sound. 750000 is usually a good value. This needs a
+# reasonably correct setting for the IPS parameter of the CPU option.
+#
+# For an example look at the next line:
+#=======================================================================
+
+#sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp, loglevel=2, log=sb16.log, dmatimer=600000
+
+#=======================================================================
+# VGA_UPDATE_INTERVAL:
+# Video memory is scanned for updates and screen updated every so many
+# virtual seconds. The default is 40000, about 25Hz. Keep in mind that
+# you must tweak the 'cpu: ips=N' directive to be as close to the number
+# of emulated instructions-per-second your workstation can do, for this
+# to be accurate.
+#
+# Examples:
+# vga_update_interval: 250000
+#=======================================================================
+vga_update_interval: 300000
+
+# using for Winstone '98 tests
+#vga_update_interval: 100000
+
+#=======================================================================
+# KEYBOARD_SERIAL_DELAY:
+# Approximate time in microseconds that it takes one character to
+# be transfered from the keyboard to controller over the serial path.
+# Examples:
+# keyboard_serial_delay: 200
+#=======================================================================
+keyboard_serial_delay: 250
+
+#=======================================================================
+# KEYBOARD_PASTE_DELAY:
+# Approximate time in microseconds between attempts to paste
+# characters to the keyboard controller. This leaves time for the
+# guest os to deal with the flow of characters. The ideal setting
+# depends on how your operating system processes characters. The
+# default of 100000 usec (.1 seconds) was chosen because it works
+# consistently in Windows.
+#
+# If your OS is losing characters during a paste, increase the paste
+# delay until it stops losing characters.
+#
+# Examples:
+# keyboard_paste_delay: 100000
+#=======================================================================
+keyboard_paste_delay: 100000
+
+#=======================================================================
+# MOUSE:
+# This option prevents Bochs from creating mouse "events" unless a mouse
+# is enabled. The hardware emulation itself is not disabled by this.
+# You can turn the mouse on by setting enabled to 1, or turn it off by
+# setting enabled to 0. Unless you have a particular reason for enabling
+# the mouse by default, it is recommended that you leave it off.
+# You can also toggle the mouse usage at runtime (control key + middle
+# mouse button on X11, SDL, wxWidgets and Win32).
+# With the mouse type option you can select the type of mouse to emulate.
+# The default value is 'ps2'. The other choices are 'imps2' (wheel mouse
+# on PS/2), 'serial', 'serial_wheel' (one com port requires setting
+# 'mode=mouse') and 'usb' (3-button mouse - one of the USB ports must be
+# connected with the 'mouse' device - requires PCI and USB support).
+#
+# Examples:
+# mouse: enabled=1
+# mouse: enabled=1, type=imps2
+# mouse: enabled=1, type=serial
+# mouse: enabled=0
+#=======================================================================
+mouse: enabled=0
+
+#=======================================================================
+# private_colormap: Request that the GUI create and use it's own
+# non-shared colormap. This colormap will be used
+# when in the bochs window. If not enabled, a
+# shared colormap scheme may be used. Not implemented
+# on all GUI's.
+#
+# Examples:
+# private_colormap: enabled=1
+# private_colormap: enabled=0
+#=======================================================================
+private_colormap: enabled=0
+
+#=======================================================================
+# fullscreen: ONLY IMPLEMENTED ON AMIGA
+# Request that Bochs occupy the entire screen instead of a
+# window.
+#
+# Examples:
+# fullscreen: enabled=0
+# fullscreen: enabled=1
+#=======================================================================
+#fullscreen: enabled=0
+#screenmode: name="sample"
+
+#=======================================================================
+# ne2k: NE2000 compatible ethernet adapter
+#
+# Examples:
+# ne2k: ioaddr=IOADDR, irq=IRQ, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT
+#
+# ioaddr, irq: You probably won't need to change ioaddr and irq, unless there
+# are IRQ conflicts.
+#
+# mac: The MAC address MUST NOT match the address of any machine on the net.
+# Also, the first byte must be an even number (bit 0 set means a multicast
+# address), and you cannot use ff:ff:ff:ff:ff:ff because that's the broadcast
+# address. For the ethertap module, you must use fe:fd:00:00:00:01. There may
+# be other restrictions too. To be safe, just use the b0:c4... address.
+#
+# ethdev: The ethdev value is the name of the network interface on your host
+# platform. On UNIX machines, you can get the name by running ifconfig. On
+# Windows machines, you must run niclist to get the name of the ethdev.
+# Niclist source code is in misc/niclist.c and it is included in Windows
+# binary releases.
+#
+# script: The script value is optional, and is the name of a script that
+# is executed after bochs initialize the network interface. You can use
+# this script to configure this network interface, or enable masquerading.
+# This is mainly useful for the tun/tap devices that only exist during
+# Bochs execution. The network interface name is supplied to the script
+# as first parameter
+#
+# If you don't want to make connections to any physical networks,
+# you can use the following 'ethmod's to simulate a virtual network.
+# null: All packets are discarded, but logged to a few files.
+# arpback: ARP is simulated. Disabled by default.
+# vde: Virtual Distributed Ethernet
+# vnet: ARP, ICMP-echo(ping), DHCP and read/write TFTP are simulated.
+# The virtual host uses 192.168.10.1.
+# DHCP assigns 192.168.10.2 to the guest.
+# TFTP uses the ethdev value for the root directory and doesn't
+# overwrite files.
+#
+#=======================================================================
+# ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=fbsd, ethdev=en0 #macosx
+# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:00, ethmod=fbsd, ethdev=xl0
+# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0
+# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=win32, ethdev=MYCARD
+# ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0
+# ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun0, script=./tunconfig
+# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=null, ethdev=eth0
+# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=vde, ethdev="/tmp/vde.ctl"
+# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=vnet, ethdev="c:/temp"
+pnic: mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun:tap0
+#ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun:tap0
+
+#=======================================================================
+# KEYBOARD_MAPPING:
+# This enables a remap of a physical localized keyboard to a
+# virtualized us keyboard, as the PC architecture expects.
+# If enabled, the keymap file must be specified.
+#
+# Examples:
+# keyboard_mapping: enabled=1, map=gui/keymaps/x11-pc-de.map
+#=======================================================================
+keyboard_mapping: enabled=0, map=
+
+#=======================================================================
+# KEYBOARD_TYPE:
+# Type of keyboard return by a "identify keyboard" command to the
+# keyboard controler. It must be one of "xt", "at" or "mf".
+# Defaults to "mf". It should be ok for almost everybody. A known
+# exception is french macs, that do have a "at"-like keyboard.
+#
+# Examples:
+# keyboard_type: mf
+#=======================================================================
+#keyboard_type: mf
+
+#=======================================================================
+# USER_SHORTCUT:
+# This defines the keyboard shortcut to be sent when you press the "user"
+# button in the headerbar. The shortcut string is a combination of maximum
+# 3 key names (listed below) separated with a '-' character. The old-style
+# syntax (without the '-') still works for the key combinations supported
+# in Bochs 2.2.1.
+# Valid key names:
+# "alt", "bksl", "bksp", "ctrl", "del", "down", "end", "enter", "esc",
+# "f1", ... "f12", "home", "ins", "left", "menu", "minus", "pgdwn", "pgup",
+# "plus", "right", "shift", "space", "tab", "up", and "win".
+#
+# Example:
+# user_shortcut: keys=ctrl-alt-del
+#=======================================================================
+user_shortcut: keys=ctrl-alt-del
+
+#=======================================================================
+# I440FXSUPPORT:
+# This option controls the presence of the i440FX PCI chipset. You can
+# also specify the devices connected to PCI slots. Up to 5 slots are
+# available now. These devices are currently supported: ne2k, pcivga,
+# pcidev and pcipnic. If Bochs is compiled with Cirrus SVGA support
+# you'll have the additional choice 'cirrus'.
+#
+# Example:
+# i440fxsupport: enabled=1, slot1=pcivga, slot2=ne2k
+#=======================================================================
+i440fxsupport: enabled=1, slot1=pcipnic
+#i440fxsupport: enabled=1, slot1=ne2k
+
+#=======================================================================
+# USB1:
+# This option controls the presence of the USB root hub which is a part
+# of the i440FX PCI chipset. With the portX option you can connect devices
+# to the hub (currently supported: 'mouse' and 'keypad'). If you connect
+# the mouse to one of the ports and use the mouse option 'type=usb' you'll
+# have a 3-button USB mouse.
+#
+# Example:
+# usb1: enabled=1, port1=mouse, port2=keypad
+#=======================================================================
+#usb1: enabled=1
+
+#=======================================================================
+# CMOSIMAGE:
+# This defines image file that can be loaded into the CMOS RAM at startup.
+# The rtc_init parameter controls whether initialize the RTC with values stored
+# in the image. By default the time0 argument given to the clock option is used.
+# With 'rtc_init=image' the image is the source for the initial time.
+#
+# Example:
+# cmosimage: file=cmos.img, rtc_init=image
+#=======================================================================
+#cmosimage: file=cmos.img, rtc_init=time0
+
+#=======================================================================
+# other stuff
+#=======================================================================
+magic_break: enabled=1
+#load32bitOSImage: os=nullkernel, path=../kernel.img, iolog=../vga_io.log
+#load32bitOSImage: os=linux, path=../linux.img, iolog=../vga_io.log, initrd=../initrd.img
+#text_snapshot_check: enable
+
+#-------------------------
+# PCI host device mapping
+#-------------------------
+#pcidev: vendor=0x1234, device=0x5678
+
+#=======================================================================
+# GDBSTUB:
+# Enable GDB stub. See user documentation for details.
+# Default value is enabled=0.
+#=======================================================================
+#gdbstub: enabled=0, port=1234, text_base=0, data_base=0, bss_base=0
+
+#=======================================================================
+# IPS:
+# The IPS directive is DEPRECATED. Use the parameter IPS of the CPU
+# directive instead.
+#=======================================================================
+#ips: 10000000
+
+#=======================================================================
+# for Macintosh, use the style of pathnames in the following
+# examples.
+#
+# vgaromimage: :bios:VGABIOS-elpin-2.40
+# romimage: file=:bios:BIOS-bochs-latest, address=0xf0000
+# floppya: 1_44=[fd:], status=inserted
+#=======================================================================
diff --git a/src/VBox/Devices/PC/ipxe/contrib/vm/cow b/src/VBox/Devices/PC/ipxe/contrib/vm/cow
new file mode 100755
index 00000000..054ffdde
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/vm/cow
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+set -e
+
+imgloop=
+tmpfile=
+tmploop=
+dmname=
+cowlink=
+
+function cleanup () {
+ set +e
+ [ -n "$cowlink" ] && rm $cowlink
+ [ -n "$dmname" ] && dmsetup remove $dmname
+ [ -n "$tmploop" ] && losetup -d $tmploop
+ [ -n "$tmpfile" ] && rm $tmpfile
+ [ -n "$imgloop" ] && losetup -d $imgloop
+}
+
+trap cleanup EXIT
+
+imgfile=$1 ; shift
+command=$1 ; shift
+if [ -z "$imgfile" -o -z "$command" ] ; then
+ echo Syntax: $0 /path/to/image/file command [args..]
+ exit 1
+fi
+
+# Set up image loop device
+x=`losetup -f` ; losetup -r $x $imgfile ; imgloop=$x
+
+# Create temporary file and set up temporary loop device
+tmpfile=`mktemp $imgfile.XXXXXXXXXX`
+truncate -r $imgfile $tmpfile
+x=`losetup -f` ; losetup $x $tmpfile ; tmploop=$x
+
+# Create snapshot device
+imgsize=`blockdev --getsz $imgloop`
+x=`basename $imgfile` ; echo 0 $imgsize snapshot $imgloop $tmploop N 16 | \
+ dmsetup create $x ; dmname=$x
+chown --reference=$imgfile /dev/mapper/$dmname
+chmod --reference=$imgfile /dev/mapper/$dmname
+
+# Create symlink
+x=$imgfile.cow ; ln -s /dev/mapper/$dmname $x ; cowlink=$x
+
+# Wait until killed
+echo "Created $cowlink"
+$command "$@" $cowlink
diff --git a/src/VBox/Devices/PC/ipxe/contrib/vm/serial-console b/src/VBox/Devices/PC/ipxe/contrib/vm/serial-console
new file mode 100755
index 00000000..5d09876e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/vm/serial-console
@@ -0,0 +1,278 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+serial-console
+
+=head1 SYNOPSIS
+
+serial-console [options]
+
+Options:
+
+ -h,--help Display brief help message
+ -v,--verbose Increase verbosity
+ -q,--quiet Decrease verbosity
+ -l,--log FILE Log output to file
+ -r,--rcfile FILE Modify specified bochsrc file
+
+=head1 DESCRIPTION
+
+C<serial-console> provides a virtual serial console for use with
+Bochs. Running C<serial-console> creates a pseudo-tty. The master
+side of this pty is made available to the user for interaction; the
+slave device is written to the Bochs configuration file
+(C<bochsrc.txt>) for use by a subsequent Bochs session.
+
+=head1 EXAMPLES
+
+=over 4
+
+=item C<serial-console>
+
+Create a virtual serial console for Bochs, modify C<bochsrc.txt>
+appropriately.
+
+=item C<serial-console -r ../.bochsrc -l serial.log>
+
+Create a virtual serial console for Bochs, modify C<../.bochsrc>
+appropriately, log output to C<serial.log>.
+
+=back
+
+=head1 INVOCATION
+
+Before starting Bochs, run C<serial-console> in a different session
+(e.g. a different xterm window). When you subsequently start Bochs,
+anything that the emulated machine writes to its serial port will
+appear in the window running C<serial-console>, and anything typed in
+the C<serial-console> window will arrive on the emulated machine's
+serial port.
+
+You do B<not> need to rerun C<serial-console> afresh for each Bochs
+session.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-l,--log FILE>
+
+Log all output (i.e. everything that is printed in the
+C<serial-console> window) to the specified file.
+
+=item B<-r,--rcfile FILE>
+
+Modify the specified bochsrc file. The file will be updated to
+contain the path to the slave side of the psuedo tty that we create.
+The original file will be restored when C<serial-console> exits. The
+default is to modify the file C<bochsrc.txt> in the current directory.
+
+To avoid modifying any bochsrc file, use C<--norcfile>.
+
+=back
+
+=cut
+
+use IO::Pty;
+use IO::Select;
+use File::Spec::Functions qw ( :ALL );
+use Getopt::Long;
+use Pod::Usage;
+use POSIX qw ( :termios_h );
+use strict;
+use warnings;
+
+my $o;
+my $restore_file = {};
+my $restore_termios;
+use constant BLOCKSIZE => 8192;
+
+##############################################################################
+#
+# Parse command line options into options hash ($o)
+#
+# $o = parse_opts();
+
+sub parse_opts {
+ # $o is the hash that will hold the options
+ my $o = {
+ verbosity => 1,
+ rcfile => 'bochsrc.txt',
+ };
+ # Special handlers for some options
+ my $opt_handlers = {
+ verbose => sub { $o->{verbosity}++; },
+ quiet => sub { $o->{verbosity}--; },
+ help => sub { pod2usage(1); },
+ norcfile => sub { delete $o->{rcfile}; },
+ };
+ # Merge handlers into main options hash (so that Getopt::Long can find them)
+ $o->{$_} = $opt_handlers->{$_} foreach keys %$opt_handlers;
+ # Option specifiers for Getopt::Long
+ my @optspec = ( 'help|h|?',
+ 'quiet|q+',
+ 'verbose|v+',
+ 'log|l=s',
+ 'rcfile|r=s',
+ 'norcfile',
+ );
+ # Do option parsing
+ Getopt::Long::Configure ( 'bundling' );
+ pod2usage("Error parsing command-line options") unless GetOptions (
+ $o, @optspec );
+ # Clean up $o by removing the handlers
+ delete $o->{$_} foreach keys %$opt_handlers;
+ return $o;
+}
+
+##############################################################################
+#
+# Modify bochsrc file
+
+sub patch_bochsrc {
+ my $active = shift;
+ my $pty = shift;
+
+ # Rename active file to backup file
+ ( my $vol, my $dir, my $file ) = splitpath ( $active );
+ $file = '.'.$file.".serial-console";
+ my $backup = catpath ( $vol, $dir, $file );
+ rename $active, $backup
+ or die "Could not back up $active to $backup: $!\n";
+
+ # Derive line to be inserted
+ my $patch = "com1: enabled=1, mode=term, dev=$pty\n";
+
+ # Modify file
+ open my $old, "<$backup" or die "Could not open $backup: $!\n";
+ open my $new, ">$active" or die "Could not open $active: $!\n";
+ print $new <<"EOF";
+##################################################
+#
+# This file has been modified by serial-console.
+#
+# Do not modify this file; it will be erased when
+# serial-console (pid $$) exits and will be
+# replaced with the backup copy held in
+# $backup.
+#
+##################################################
+
+
+EOF
+ my $patched;
+ while ( my $line = <$old> ) {
+ if ( $line =~ /^\s*\#?\s*com1:\s*\S/ ) {
+ if ( ! $patched ) {
+ $line = $patch;
+ $patched = 1;
+ } else {
+ $line = '# '.$line unless $line =~ /^\s*\#/;
+ }
+ }
+ print $new $line;
+ }
+ print $new $patch unless $patched;
+ close $old;
+ close $new;
+
+ return $backup;
+}
+
+##############################################################################
+#
+# Attach/detach message printing and terminal settings
+
+sub bochs_attached {
+ print STDERR "Bochs attached.\n\n\n"
+ if $o->{verbosity} >= 1;
+}
+
+sub bochs_detached {
+ print STDERR "\n\nWaiting for bochs to attach...\n"
+ if $o->{verbosity} >= 1;
+}
+
+##############################################################################
+#
+# Main program
+
+$o = parse_opts();
+pod2usage(1) if @ARGV;
+
+# Catch signals
+my $sigdie = sub { die "Exiting via signal\n"; };
+$SIG{INT} = $sigdie;
+
+# Create Pty, close slave side
+my $pty = IO::Pty->new();
+$pty->close_slave();
+$pty->set_raw();
+print STDERR "Slave pty is ".$pty->ttyname."\n" if $o->{verbosity} >= 1;
+
+# Open logfile
+my $log;
+if ( $o->{log} ) {
+ open $log, ">$o->{log}" or die "Could not open $o->{log}: $!\n";
+}
+
+# Set up terminal
+my $termios;
+if ( -t STDIN ) {
+ $termios = POSIX::Termios->new;
+ $restore_termios = POSIX::Termios->new;
+ $termios->getattr ( fileno(STDIN) );
+ $restore_termios->getattr ( fileno(STDIN) );
+ $termios->setlflag ( $termios->getlflag & ~(ICANON) & ~(ECHO) );
+ $termios->setiflag ( $termios->getiflag & ~(ICRNL) );
+ $termios->setattr ( fileno(STDIN), TCSANOW );
+}
+
+# Modify bochsrc file
+$restore_file = { $o->{rcfile} =>
+ patch_bochsrc ( $o->{rcfile}, $pty->ttyname ) }
+ if $o->{rcfile};
+
+# Start character shunt
+my $attached = 1;
+my $select = IO::Select->new ( \*STDIN, $pty );
+while ( 1 ) {
+ my %can_read = map { $_ => 1 }
+ $select->can_read ( $attached ? undef : 1 );
+ if ( $can_read{\*STDIN} ) {
+ sysread ( STDIN, my $data, BLOCKSIZE )
+ or die "Cannot read from STDIN: $!\n";
+ $pty->syswrite ( $data );
+ }
+ if ( $can_read{$pty} ) {
+ if ( $pty->sysread ( my $data, BLOCKSIZE ) ) {
+ # Actual data available
+ bochs_attached() if $attached == 0;
+ $attached = 1;
+ syswrite ( STDOUT, $data );
+ $log->syswrite ( $data ) if $log;
+ } else {
+ # No data available but select() says we can read. This almost
+ # certainly indicates that nothing is attached to the slave.
+ bochs_detached() if $attached == 1;
+ $attached = 0;
+ sleep ( 1 );
+ }
+ } else {
+ bochs_attached() if $attached == 0;
+ $attached = 1;
+ }
+}
+
+END {
+ # Restore bochsrc file if applicable
+ if ( ( my $orig_file, my $backup_file ) = %$restore_file ) {
+ unlink $orig_file;
+ rename $backup_file, $orig_file;
+ }
+ # Restore terminal settings if applicable
+ if ( $restore_termios ) {
+ $restore_termios->setattr ( fileno(STDIN), TCSANOW );
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/contrib/vm/serial-console.1 b/src/VBox/Devices/PC/ipxe/contrib/vm/serial-console.1
new file mode 100644
index 00000000..6d19a7d9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/contrib/vm/serial-console.1
@@ -0,0 +1,190 @@
+.\" Automatically generated by Pod::Man 2.22 (Pod::Simple 3.07)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. \*(C+ will
+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.ie \nF \{\
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. nr % 0
+. rr F
+.\}
+.el \{\
+. de IX
+..
+.\}
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "SERIAL-CONSOLE 1"
+.TH SERIAL-CONSOLE 1 "2010-09-22" "perl v5.10.1" "User Contributed Perl Documentation"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+serial\-console
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+serial-console [options]
+.PP
+Options:
+.PP
+.Vb 5
+\& \-h,\-\-help Display brief help message
+\& \-v,\-\-verbose Increase verbosity
+\& \-q,\-\-quiet Decrease verbosity
+\& \-l,\-\-log FILE Log output to file
+\& \-r,\-\-rcfile FILE Modify specified bochsrc file
+.Ve
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+\&\f(CW\*(C`serial\-console\*(C'\fR provides a virtual serial console for use with
+Bochs. Running \f(CW\*(C`serial\-console\*(C'\fR creates a pseudo-tty. The master
+side of this pty is made available to the user for interaction; the
+slave device is written to the Bochs configuration file
+(\f(CW\*(C`bochsrc.txt\*(C'\fR) for use by a subsequent Bochs session.
+.SH "EXAMPLES"
+.IX Header "EXAMPLES"
+.ie n .IP """serial\-console""" 4
+.el .IP "\f(CWserial\-console\fR" 4
+.IX Item "serial-console"
+Create a virtual serial console for Bochs, modify \f(CW\*(C`bochsrc.txt\*(C'\fR
+appropriately.
+.ie n .IP """serial\-console \-r ../.bochsrc \-l serial.log""" 4
+.el .IP "\f(CWserial\-console \-r ../.bochsrc \-l serial.log\fR" 4
+.IX Item "serial-console -r ../.bochsrc -l serial.log"
+Create a virtual serial console for Bochs, modify \f(CW\*(C`../.bochsrc\*(C'\fR
+appropriately, log output to \f(CW\*(C`serial.log\*(C'\fR.
+.SH "INVOCATION"
+.IX Header "INVOCATION"
+Before starting Bochs, run \f(CW\*(C`serial\-console\*(C'\fR in a different session
+(e.g. a different xterm window). When you subsequently start Bochs,
+anything that the emulated machine writes to its serial port will
+appear in the window running \f(CW\*(C`serial\-console\*(C'\fR, and anything typed in
+the \f(CW\*(C`serial\-console\*(C'\fR window will arrive on the emulated machine's
+serial port.
+.PP
+You do \fBnot\fR need to rerun \f(CW\*(C`serial\-console\*(C'\fR afresh for each Bochs
+session.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+.IP "\fB\-l,\-\-log \s-1FILE\s0\fR" 4
+.IX Item "-l,--log FILE"
+Log all output (i.e. everything that is printed in the
+\&\f(CW\*(C`serial\-console\*(C'\fR window) to the specified file.
+.IP "\fB\-r,\-\-rcfile \s-1FILE\s0\fR" 4
+.IX Item "-r,--rcfile FILE"
+Modify the specified bochsrc file. The file will be updated to
+contain the path to the slave side of the psuedo tty that we create.
+The original file will be restored when \f(CW\*(C`serial\-console\*(C'\fR exits. The
+default is to modify the file \f(CW\*(C`bochsrc.txt\*(C'\fR in the current directory.
+.Sp
+To avoid modifying any bochsrc file, use \f(CW\*(C`\-\-norcfile\*(C'\fR.
diff --git a/src/VBox/Devices/PC/ipxe/iPxeBiosBin.rom b/src/VBox/Devices/PC/ipxe/iPxeBiosBin.rom
new file mode 100644
index 00000000..25668e3e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/iPxeBiosBin.rom
Binary files differ
diff --git a/src/VBox/Devices/PC/ipxe/src/Makefile b/src/VBox/Devices/PC/ipxe/src/Makefile
new file mode 100644
index 00000000..6537ecb4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/Makefile
@@ -0,0 +1,182 @@
+###############################################################################
+#
+# Initialise various variables
+#
+
+CLEANUP :=
+CFLAGS :=
+ASFLAGS :=
+LDFLAGS :=
+HOST_CFLAGS :=
+MAKEDEPS := Makefile
+
+###############################################################################
+#
+# Locations of tools
+#
+HOST_CC := gcc
+RM := rm -f
+TOUCH := touch
+MKDIR := mkdir
+CP := cp
+ECHO := echo
+PRINTF := printf
+PERL := perl
+TRUE := true
+CC := $(CROSS_COMPILE)gcc
+CPP := $(CC) -E
+AS := $(CROSS_COMPILE)as
+LD := $(CROSS_COMPILE)ld
+SIZE := $(CROSS_COMPILE)size
+AR := $(CROSS_COMPILE)ar
+RANLIB := $(CROSS_COMPILE)ranlib
+OBJCOPY := $(CROSS_COMPILE)objcopy
+NM := $(CROSS_COMPILE)nm
+OBJDUMP := $(CROSS_COMPILE)objdump
+OPENSSL := openssl
+PARSEROM := ./util/parserom.pl
+FIXROM := ./util/fixrom.pl
+SYMCHECK := ./util/symcheck.pl
+SORTOBJDUMP := ./util/sortobjdump.pl
+PADIMG := ./util/padimg.pl
+LICENCE := ./util/licence.pl
+NRV2B := ./util/nrv2b
+ZBIN := ./util/zbin
+ELF2EFI32 := ./util/elf2efi32
+ELF2EFI64 := ./util/elf2efi64
+EFIROM := ./util/efirom
+ICCFIX := ./util/iccfix
+EINFO := ./util/einfo
+GENKEYMAP := ./util/genkeymap.pl
+DOXYGEN := doxygen
+BINUTILS_DIR := /usr
+BFD_DIR := $(BINUTILS_DIR)
+ZLIB_DIR := /usr
+
+###############################################################################
+#
+# SRCDIRS lists all directories containing source files.
+#
+SRCDIRS :=
+SRCDIRS += libgcc
+SRCDIRS += core
+SRCDIRS += net net/tcp net/udp net/infiniband net/80211
+SRCDIRS += image
+SRCDIRS += drivers/bus
+SRCDIRS += drivers/net
+SRCDIRS += drivers/net/e1000
+SRCDIRS += drivers/net/e1000e
+SRCDIRS += drivers/net/igb
+SRCDIRS += drivers/net/igbvf
+SRCDIRS += drivers/net/phantom
+SRCDIRS += drivers/net/rtl818x
+SRCDIRS += drivers/net/ath
+SRCDIRS += drivers/net/ath/ath5k
+SRCDIRS += drivers/net/ath/ath9k
+SRCDIRS += drivers/net/vxge
+SRCDIRS += drivers/net/efi
+SRCDIRS += drivers/net/tg3
+SRCDIRS += drivers/block
+SRCDIRS += drivers/nvs
+SRCDIRS += drivers/bitbash
+SRCDIRS += drivers/infiniband
+SRCDIRS += interface/pxe interface/efi interface/smbios
+SRCDIRS += interface/bofm
+SRCDIRS += tests
+SRCDIRS += crypto crypto/axtls crypto/matrixssl
+SRCDIRS += hci hci/commands hci/tui
+SRCDIRS += hci/mucurses hci/mucurses/widgets
+SRCDIRS += hci/keymap
+SRCDIRS += usr
+SRCDIRS += config
+
+# NON_AUTO_SRCS lists files that are excluded from the normal
+# automatic build system.
+#
+NON_AUTO_SRCS :=
+NON_AUTO_SRCS += drivers/net/prism2.c
+
+# INCDIRS lists the include path
+#
+INCDIRS :=
+INCDIRS += include .
+
+###############################################################################
+#
+# Default build target: build the most common targets and print out a
+# helpfully suggestive message
+#
+ALL := bin/blib.a bin/ipxe.dsk bin/ipxe.lkrn bin/ipxe.iso \
+ bin/ipxe.usb bin/undionly.kpxe bin/rtl8139.rom
+all : $(ALL)
+ @$(ECHO) '==========================================================='
+ @$(ECHO)
+ @$(ECHO) 'To create a bootable floppy, type'
+ @$(ECHO) ' cat bin/ipxe.dsk > /dev/fd0'
+ @$(ECHO) 'where /dev/fd0 is your floppy drive. This will erase any'
+ @$(ECHO) 'data already on the disk.'
+ @$(ECHO)
+ @$(ECHO) 'To create a bootable USB key, type'
+ @$(ECHO) ' cat bin/ipxe.usb > /dev/sdX'
+ @$(ECHO) 'where /dev/sdX is your USB key, and is *not* a real hard'
+ @$(ECHO) 'disk on your system. This will erase any data already on'
+ @$(ECHO) 'the USB key.'
+ @$(ECHO)
+ @$(ECHO) 'To create a bootable CD-ROM, burn the ISO image '
+ @$(ECHO) 'bin/ipxe.iso to a blank CD-ROM.'
+ @$(ECHO)
+ @$(ECHO) 'These images contain drivers for all supported cards. You'
+ @$(ECHO) 'can build more customised images, and ROM images, using'
+ @$(ECHO) ' make bin/<rom-name>.<output-format>'
+ @$(ECHO)
+ @$(ECHO) '==========================================================='
+
+###############################################################################
+#
+# Comprehensive build target: build a selection of cross-platform
+# targets to expose potential build errors that show up only on
+# certain platforms
+#
+everything :
+ $(Q)$(MAKE) --no-print-directory $(ALL) \
+ bin-i386-efi/ipxe.efi bin-i386-efi/ipxe.efidrv \
+ bin-i386-efi/ipxe.efirom \
+ bin-x86_64-efi/ipxe.efi bin-x86_64-efi/ipxe.efidrv \
+ bin-x86_64-efi/ipxe.efirom \
+ bin-i386-linux/tap.linux bin-x86_64-linux/tap.linux
+
+###############################################################################
+#
+# Build targets that do nothing but might be tried by users
+#
+configure :
+ @$(ECHO) "No configuration needed."
+
+install :
+ @$(ECHO) "No installation required."
+
+###############################################################################
+#
+# Version number calculations
+#
+VERSION_MAJOR = 1
+VERSION_MINOR = 0
+VERSION_PATCH = 0
+EXTRAVERSION = +
+MM_VERSION = $(VERSION_MAJOR).$(VERSION_MINOR)
+VERSION = $(MM_VERSION).$(VERSION_PATCH)$(EXTRAVERSION)
+CFLAGS += -DVERSION_MAJOR=$(VERSION_MAJOR) \
+ -DVERSION_MINOR=$(VERSION_MINOR) \
+ -DVERSION_PATCH=$(VERSION_PATCH) \
+ -DVERSION=\"$(VERSION)\"
+IDENT = '$(@F) $(VERSION) (GPL) ipxe.org'
+version :
+ @$(ECHO) $(VERSION)
+
+###############################################################################
+#
+# Drag in the bulk of the build system
+#
+
+MAKEDEPS += Makefile.housekeeping
+include Makefile.housekeeping
diff --git a/src/VBox/Devices/PC/ipxe/src/Makefile.housekeeping b/src/VBox/Devices/PC/ipxe/src/Makefile.housekeeping
new file mode 100644
index 00000000..822fa277
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/Makefile.housekeeping
@@ -0,0 +1,1254 @@
+# -*- makefile -*- : Force emacs to use Makefile mode
+#
+# This file contains various boring housekeeping functions that would
+# otherwise seriously clutter up the main Makefile.
+
+###############################################################################
+#
+# Find a usable "echo -e" substitute.
+#
+TAB := $(shell $(PRINTF) '\t')
+ECHO_E_ECHO := $(ECHO)
+ECHO_E_ECHO_E := $(ECHO) -e
+ECHO_E_BIN_ECHO := /bin/echo
+ECHO_E_BIN_ECHO_E := /bin/echo -e
+ECHO_E_ECHO_TAB := $(shell $(ECHO_E_ECHO) '\t' | cat)
+ECHO_E_ECHO_E_TAB := $(shell $(ECHO_E_ECHO_E) '\t' | cat)
+ECHO_E_BIN_ECHO_TAB := $(shell $(ECHO_E_BIN_ECHO) '\t')
+ECHO_E_BIN_ECHO_E_TAB := $(shell $(ECHO_E_BIN_ECHO_E) '\t')
+
+ifeq ($(ECHO_E_ECHO_TAB),$(TAB))
+ECHO_E := $(ECHO_E_ECHO)
+endif
+ifeq ($(ECHO_E_ECHO_E_TAB),$(TAB))
+ECHO_E := $(ECHO_E_ECHO_E)
+endif
+ifeq ($(ECHO_E_BIN_ECHO_TAB),$(TAB))
+ECHO_E := $(ECHO_E_BIN_ECHO)
+endif
+ifeq ($(ECHO_E_BIN_ECHO_E_TAB),$(TAB))
+ECHO_E := $(ECHO_E_BIN_ECHO_E)
+endif
+
+.echocheck :
+ifdef ECHO_E
+ @$(TOUCH) $@
+else
+ @$(PRINTF) '%24s : x%sx\n' 'tab' '$(TAB)'
+ @$(PRINTF) '%24s : x%sx\n' '"$(ECHO_E_ECHO) \t"' \
+ '$(ECHO_E_ECHO_TAB)'
+ @$(PRINTF) '%24s : x%sx\n' '"$(ECHO_E_ECHO_E) \t"' \
+ '$(ECHO_E_ECHO_E_TAB)'
+ @$(PRINTF) '%24s : x%sx\n' '"$(ECHO_E_BIN_ECHO) \t"' \
+ '$(ECHO_E_BIN_ECHO_TAB)'
+ @$(PRINTF) '%24s : x%sx\n' '"$(ECHO_E_BIN_ECHO_E) \t"' \
+ '$(ECHO_E_BIN_ECHO_E_TAB)'
+ @$(ECHO) "No usable \"echo -e\" substitute found"
+ @exit 1
+endif
+MAKEDEPS += .echocheck
+VERYCLEANUP += .echocheck
+
+echo :
+ @$(ECHO) "Using \"$(ECHO_E)\" for \"echo -e\""
+
+###############################################################################
+#
+# Generate a usable "seq" substitute
+#
+define seq
+ $(shell awk 'BEGIN { for ( i = $(1) ; i <= $(2) ; i++ ) print i }')
+endef
+
+###############################################################################
+#
+# Determine host OS
+#
+HOST_OS := $(shell uname -s)
+hostos :
+ @$(ECHO) $(HOST_OS)
+
+###############################################################################
+#
+# Determine compiler
+
+CCDEFS := $(shell $(CC) -E -x c -c /dev/null -dM | cut -d" " -f2)
+ccdefs:
+ @$(ECHO) $(CCDEFS)
+
+ifeq ($(filter __ICC,$(CCDEFS)),__ICC)
+CCTYPE := icc
+else
+CCTYPE := gcc
+endif
+cctype:
+ @$(ECHO) $(CCTYPE)
+
+###############################################################################
+#
+# Check for tools that can cause failed builds
+#
+
+ifeq ($(CCTYPE),gcc)
+GCC_2_96_BANNER := $(shell $(CC) -v 2>&1 | grep -is 'gcc version 2\.96')
+ifneq ($(GCC_2_96_BANNER),)
+$(warning gcc 2.96 is unsuitable for compiling iPXE)
+$(warning Use gcc 2.95 or a newer version instead)
+$(error Unsuitable build environment found)
+endif
+endif
+
+PERL_UNICODE_CHECK := $(shell $(PERL) -e 'use bytes; print chr(255)' | wc -c)
+ifeq ($(PERL_UNICODE_CHECK),2)
+$(warning Your Perl version has a Unicode handling bug)
+$(warning Execute this command before building iPXE:)
+$(warning export LANG=$${LANG%.UTF-8})
+$(error Unsuitable build environment found)
+endif
+
+LD_GOLD_BANNER := $(shell $(LD) -v 2>&1 | grep 'GNU gold')
+ifneq ($(LD_GOLD_BANNER),)
+$(warning GNU gold is unsuitable for building iPXE)
+$(warning Use GNU ld instead)
+$(error Unsuitable build environment found)
+endif
+
+###############################################################################
+#
+# Check for various tool workarounds
+#
+
+WORKAROUND_CFLAGS :=
+WORKAROUND_ASFLAGS :=
+WORKAROUND_LDFLAGS :=
+
+# Make syntax does not allow use of comma or space in certain places.
+# This ugly workaround is suggested in the manual.
+#
+COMMA := ,
+EMPTY :=
+SPACE := $(EMPTY) $(EMPTY)
+
+# Check for an old version of gas (binutils 2.9.1)
+#
+OLDGAS := $(shell $(AS) --version | grep -q '2\.9\.1' && $(ECHO) -DGAS291)
+WORKAROUND_CFLAGS += $(OLDGAS)
+oldgas :
+ @$(ECHO) $(oldgas)
+
+# Some widespread patched versions of gcc include -fstack-protector by
+# default, even when -ffreestanding is specified. We therefore need
+# to disable -fstack-protector if the compiler supports it.
+#
+ifeq ($(CCTYPE),gcc)
+SP_TEST = $(CC) -fno-stack-protector -x c -c /dev/null \
+ -o /dev/null >/dev/null 2>&1
+SP_FLAGS := $(shell $(SP_TEST) && $(ECHO) '-fno-stack-protector')
+WORKAROUND_CFLAGS += $(SP_FLAGS)
+endif
+
+# Some widespread patched versions of gcc include -fPIE -Wl,-pie by
+# default. Note that gcc will exit *successfully* if it fails to
+# recognise an option that starts with "no", so we have to test for
+# output on stderr instead of checking the exit status.
+#
+ifeq ($(CCTYPE),gcc)
+PIE_TEST = [ -z "`$(CC) -fno-PIE -nopie -x c -c /dev/null -o /dev/null 2>&1`" ]
+PIE_FLAGS := $(shell $(PIE_TEST) && $(ECHO) '-fno-PIE -nopie')
+WORKAROUND_CFLAGS += $(PIE_FLAGS)
+endif
+
+# gcc 4.4 generates .eh_frame sections by default, which distort the
+# output of "size". Inhibit this.
+#
+ifeq ($(CCTYPE),gcc)
+CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -x c -c /dev/null \
+ -o /dev/null >/dev/null 2>&1
+CFI_FLAGS := $(shell $(CFI_TEST) && $(ECHO) '-fno-dwarf2-cfi-asm')
+WORKAROUND_CFLAGS += $(CFI_FLAGS)
+endif
+
+# gcc 4.6 generates spurious warnings if -Waddress is in force.
+# Inhibit this.
+#
+ifeq ($(CCTYPE),gcc)
+WNA_TEST = $(CC) -Wno-address -x c -c /dev/null -o /dev/null >/dev/null 2>&1
+WNA_FLAGS := $(shell $(WNA_TEST) && $(ECHO) '-Wno-address')
+WORKAROUND_CFLAGS += $(WNA_FLAGS)
+endif
+
+# Some versions of gas choke on division operators, treating them as
+# comment markers. Specifying --divide will work around this problem,
+# but isn't available on older gas versions.
+#
+DIVIDE_TEST = $(AS) --divide /dev/null -o /dev/null 2>/dev/null
+DIVIDE_FLAGS := $(shell $(DIVIDE_TEST) && $(ECHO) '--divide')
+WORKAROUND_ASFLAGS += $(DIVIDE_FLAGS)
+
+###############################################################################
+#
+# Build verbosity
+#
+ifeq ($(V),1)
+Q :=
+QM := @\#
+else
+Q := @
+QM := @
+endif
+
+###############################################################################
+#
+# Set BIN according to whatever was specified on the command line as
+# the build target.
+#
+
+# Determine how many different BIN directories are mentioned in the
+# make goals.
+#
+BIN_GOALS := $(filter bin/% bin-%,$(MAKECMDGOALS))
+BIN_GOALS_BINS := $(sort $(foreach BG,$(BIN_GOALS),\
+ $(firstword $(subst /, ,$(BG)))))
+NUM_BINS := $(words $(BIN_GOALS_BINS))
+
+ifeq ($(NUM_BINS),0)
+
+# No BIN directory was specified. Set BIN to "bin" as a sensible
+# default.
+
+BIN := bin
+
+else # NUM_BINS == 0
+
+ifeq ($(NUM_BINS),1)
+
+# If exactly one BIN directory was specified, set BIN to match this
+# directory.
+#
+BIN := $(firstword $(BIN_GOALS_BINS))
+
+else # NUM_BINS == 1
+
+# More than one BIN directory was specified. We cannot handle the
+# latter case within a single make invocation, so set up recursive
+# targets for each BIN directory. Use exactly one target for each BIN
+# directory since running multiple make invocations within the same
+# BIN directory is likely to cause problems.
+#
+# Leave $(BIN) undefined. This has implications for any target that
+# depends on $(BIN); such targets should be made conditional upon the
+# existence of $(BIN).
+#
+BIN_GOALS_FIRST := $(foreach BGB,$(BIN_GOALS_BINS),\
+ $(firstword $(filter $(BGB)/%,$(BIN_GOALS))))
+BIN_GOALS_OTHER := $(filter-out $(BIN_GOALS_FIRST),$(BIN_GOALS))
+
+$(BIN_GOALS_FIRST) : % : BIN_RECURSE
+ $(Q)$(MAKE) --no-print-directory BIN=$(firstword $(subst /, ,$@)) \
+ $(filter $(firstword $(subst /, ,$@))/%, $(BIN_GOALS))
+$(BIN_GOALS_OTHER) : % : BIN_RECURSE
+ $(Q)$(TRUE)
+.PHONY : BIN_RECURSE
+
+endif # NUM_BINS == 1
+endif # NUM_BINS == 0
+
+ifdef BIN
+
+# Create $(BIN) directory if it doesn't exist yet
+#
+ifeq ($(wildcard $(BIN)),)
+$(shell $(MKDIR) -p $(BIN))
+endif
+
+# Target to allow e.g. "make bin-efi arch"
+#
+$(BIN) :
+ @# Do nothing, silently
+.PHONY : $(BIN)
+
+# Remove everything in $(BIN) for a "make clean"
+#
+CLEANUP += $(BIN)/*.* # Avoid picking up directories
+
+endif # defined(BIN)
+
+# Determine whether or not we need to include the dependency files
+#
+NO_DEP_TARGETS := $(BIN) clean veryclean
+ifeq ($(MAKECMDGOALS),)
+NEED_DEPS := 1
+endif
+ifneq ($(strip $(filter-out $(NO_DEP_TARGETS),$(MAKECMDGOALS))),)
+NEED_DEPS := 1
+endif
+
+###############################################################################
+#
+# Select build architecture and platform based on $(BIN)
+#
+# BIN has the form bin[-[arch-]platform]
+
+ARCHS := $(patsubst arch/%,%,$(wildcard arch/*))
+PLATFORMS := $(patsubst config/defaults/%.h,%,\
+ $(wildcard config/defaults/*.h))
+archs :
+ @$(ECHO) $(ARCHS)
+
+platforms :
+ @$(ECHO) $(PLATFORMS)
+
+ifdef BIN
+
+# Determine architecture portion of $(BIN), if present
+BIN_ARCH := $(strip $(foreach A,$(ARCHS),\
+ $(patsubst bin-$(A)-%,$(A),\
+ $(filter bin-$(A)-%,$(BIN)))))
+
+# Determine platform portion of $(BIN), if present
+ifeq ($(BIN_ARCH),)
+BIN_PLATFORM := $(patsubst bin-%,%,$(filter bin-%,$(BIN)))
+else
+BIN_PLATFORM := $(patsubst bin-$(BIN_ARCH)-%,%,$(BIN))
+endif
+
+# Determine build architecture
+DEFAULT_ARCH := i386
+ARCH := $(firstword $(BIN_ARCH) $(DEFAULT_ARCH))
+CFLAGS += -DARCH=$(ARCH)
+arch :
+ @$(ECHO) $(ARCH)
+.PHONY : arch
+
+# Determine build platform
+DEFAULT_PLATFORM := pcbios
+PLATFORM := $(firstword $(BIN_PLATFORM) $(DEFAULT_PLATFORM))
+CFLAGS += -DPLATFORM=$(PLATFORM)
+platform :
+ @$(ECHO) $(PLATFORM)
+
+endif # defined(BIN)
+
+# Include architecture-specific Makefile
+ifdef ARCH
+MAKEDEPS += arch/$(ARCH)/Makefile
+include arch/$(ARCH)/Makefile
+endif
+
+# Include architecture-specific include path
+ifdef ARCH
+INCDIRS += arch/$(ARCH)/include
+INCDIRS += arch/$(ARCH)/include/$(PLATFORM)
+endif
+
+###############################################################################
+#
+# Source file handling
+
+# SRCDIRS lists all directories containing source files.
+srcdirs :
+ @$(ECHO) $(SRCDIRS)
+
+# SRCS lists all .c or .S files found in any SRCDIR
+#
+SRCS += $(wildcard $(patsubst %,%/*.c,$(SRCDIRS)))
+SRCS += $(wildcard $(patsubst %,%/*.S,$(SRCDIRS)))
+srcs :
+ @$(ECHO) $(SRCS)
+
+# AUTO_SRCS lists all files in SRCS that are not mentioned in
+# NON_AUTO_SRCS. Files should be added to NON_AUTO_SRCS if they
+# cannot be built using the standard build template.
+#
+AUTO_SRCS = $(filter-out $(NON_AUTO_SRCS),$(SRCS))
+autosrcs :
+ @$(ECHO) $(AUTO_SRCS)
+
+# Just about everything else in this section depends upon having
+# $(BIN) set
+
+ifdef BIN
+
+# INCDIRS lists the include path
+incdirs :
+ @$(ECHO) $(INCDIRS)
+
+# Common flags
+#
+CFLAGS += $(foreach INC,$(INCDIRS),-I$(INC))
+CFLAGS += -Os
+CFLAGS += -g
+ifeq ($(CCTYPE),gcc)
+CFLAGS += -ffreestanding
+CFLAGS += -Wall -W -Wformat-nonliteral
+HOST_CFLAGS += -Wall -W -Wformat-nonliteral
+endif
+ifeq ($(CCTYPE),icc)
+CFLAGS += -fno-builtin
+CFLAGS += -no-ip
+CFLAGS += -no-gcc
+CFLAGS += -diag-disable 111 # Unreachable code
+CFLAGS += -diag-disable 128 # Unreachable loop
+CFLAGS += -diag-disable 170 # Array boundary checks
+CFLAGS += -diag-disable 177 # Unused functions
+CFLAGS += -diag-disable 181 # printf() format checks
+CFLAGS += -diag-disable 188 # enum strictness
+CFLAGS += -diag-disable 193 # Undefined preprocessor identifiers
+CFLAGS += -diag-disable 280 # switch ( constant )
+CFLAGS += -diag-disable 310 # K&R parameter lists
+CFLAGS += -diag-disable 424 # Extra semicolon
+CFLAGS += -diag-disable 589 # Declarations mid-code
+CFLAGS += -diag-disable 593 # Unused variables
+CFLAGS += -diag-disable 810 # Casting ints to smaller ints
+CFLAGS += -diag-disable 981 # Sequence point violations
+CFLAGS += -diag-disable 1292 # Ignored attributes
+CFLAGS += -diag-disable 1338 # void pointer arithmetic
+CFLAGS += -diag-disable 1361 # Variable-length arrays
+CFLAGS += -diag-disable 1418 # Missing prototypes
+CFLAGS += -diag-disable 1419 # Missing prototypes
+CFLAGS += -diag-disable 1599 # Hidden variables
+CFLAGS += -Wall -Wmissing-declarations
+endif
+CFLAGS += $(WORKAROUND_CFLAGS) $(EXTRA_CFLAGS)
+ASFLAGS += $(WORKAROUND_ASFLAGS) $(EXTRA_ASFLAGS)
+LDFLAGS += $(WORKAROUND_LDFLAGS) $(EXTRA_LDFLAGS)
+HOST_CFLAGS += -O2 -g
+
+# Inhibit -Werror if NO_WERROR is specified on make command line
+#
+ifneq ($(NO_WERROR),1)
+#CFLAGS += -Werror -Wno-error=array-bounds
+#ASFLAGS += --fatal-warnings
+#HOST_CFLAGS += -Werror
+endif
+
+# Function trace recorder state in the last build. This is needed
+# in order to correctly rebuild whenever the function recorder is
+# enabled/disabled.
+#
+FNREC_STATE := $(BIN)/.fnrec.state
+ifeq ($(wildcard $(FNREC_STATE)),)
+FNREC_OLD := <invalid>
+else
+FNREC_OLD := $(shell cat $(FNREC_STATE))
+endif
+ifeq ($(FNREC_OLD),$(FNREC))
+$(FNREC_STATE) :
+else
+$(FNREC_STATE) : clean
+$(shell $(ECHO) "$(FNREC)" > $(FNREC_STATE))
+endif
+
+VERYCLEANUP += $(FNREC_STATE)
+MAKEDEPS += $(FNREC_STATE)
+
+ifeq ($(FNREC),1)
+# Enabling -finstrument-functions affects gcc's analysis and leads to spurious
+# warnings about use of uninitialised variables.
+#
+CFLAGS += -Wno-uninitialized
+CFLAGS += -finstrument-functions
+CFLAGS += -finstrument-functions-exclude-file-list=core/fnrec.c
+endif
+
+# Enable per-item sections and section garbage collection. Note that
+# some older versions of gcc support -fdata-sections but treat it as
+# implying -fno-common, which would break our build. Some other older
+# versions issue a spurious and uninhibitable warning if
+# -ffunction-sections is used with -g, which would also break our
+# build since we use -Werror.
+#
+ifeq ($(CCTYPE),gcc)
+DS_TEST = $(ECHO) 'char x;' | \
+ $(CC) -fdata-sections -S -x c - -o - 2>/dev/null | \
+ grep -E '\.comm' > /dev/null
+DS_FLAGS := $(shell $(DS_TEST) && $(ECHO) '-fdata-sections')
+FS_TEST = $(CC) -ffunction-sections -g -c -x c /dev/null \
+ -o /dev/null 2>/dev/null
+FS_FLAGS := $(shell $(FS_TEST) && $(ECHO) '-ffunction-sections')
+CFLAGS += $(FS_FLAGS) $(DS_FLAGS)
+endif
+LDFLAGS += --gc-sections
+
+# compiler.h is needed for our linking and debugging system
+#
+CFLAGS += -include compiler.h
+
+# CFLAGS for specific object types
+#
+CFLAGS_c +=
+CFLAGS_S += -DASSEMBLY
+
+# Base object name of the current target
+#
+OBJECT = $(firstword $(subst ., ,$(@F)))
+
+# CFLAGS for specific object files. You can define
+# e.g. CFLAGS_rtl8139, and have those flags automatically used when
+# compiling bin/rtl8139.o.
+#
+OBJ_CFLAGS = $(CFLAGS_$(OBJECT)) -DOBJECT=$(subst -,_,$(OBJECT))
+$(BIN)/%.flags :
+ @$(ECHO) $(OBJ_CFLAGS)
+
+# ICC requires postprocessing objects to fix up table alignments
+#
+ifeq ($(CCTYPE),icc)
+POST_O = && $(ICCFIX) $@
+POST_O_DEPS := $(ICCFIX)
+else
+POST_O :=
+POST_O_DEPS :=
+endif
+
+# Rules for specific object types.
+#
+COMPILE_c = $(CC) $(CFLAGS) $(CFLAGS_c) $(OBJ_CFLAGS)
+RULE_c = $(Q)$(COMPILE_c) -c $< -o $@ $(POST_O)
+RULE_c_to_dbg%.o = $(Q)$(COMPILE_c) -Ddebug_$(subst -,_,$(OBJECT))=$* -c $< -o $@ $(POST_O)
+RULE_c_to_c = $(Q)$(COMPILE_c) -E -c $< > $@
+RULE_c_to_s = $(Q)$(COMPILE_c) -S -g0 -c $< -o $@
+
+PREPROCESS_S = $(CPP) $(CFLAGS) $(CFLAGS_S) $(OBJ_CFLAGS)
+ASSEMBLE_S = $(AS) $(ASFLAGS)
+RULE_S = $(Q)$(PREPROCESS_S) $< | $(ASSEMBLE_S) -o $@
+RULE_S_to_dbg%.o = $(Q)$(PREPROCESS_S) -Ddebug_$(subst -,_,$(OBJECT))=$* $< | $(ASSEMBLE_S) -o $@
+RULE_S_to_s = $(Q)$(PREPROCESS_S) $< > $@
+
+DEBUG_TARGETS += dbg%.o c s
+
+# List of embedded images included in the last build of embedded.o.
+# This is needed in order to correctly rebuild embedded.o whenever the
+# list of objects changes.
+#
+EMBED := $(EMBEDDED_IMAGE) # Maintain backwards compatibility
+EMBEDDED_LIST := $(BIN)/.embedded.list
+ifeq ($(wildcard $(EMBEDDED_LIST)),)
+EMBED_OLD := <invalid>
+else
+EMBED_OLD := $(shell cat $(EMBEDDED_LIST))
+endif
+ifneq ($(EMBED_OLD),$(EMBED))
+$(shell $(ECHO) "$(EMBED)" > $(EMBEDDED_LIST))
+endif
+
+$(EMBEDDED_LIST) :
+
+VERYCLEANUP += $(EMBEDDED_LIST)
+
+EMBEDDED_FILES := $(subst $(COMMA), ,$(EMBED))
+EMBED_ALL := $(foreach i,$(call seq,1,$(words $(EMBEDDED_FILES))),\
+ EMBED ( $(i), \"$(word $(i), $(EMBEDDED_FILES))\",\
+ \"$(notdir $(word $(i),$(EMBEDDED_FILES)))\" ))
+
+embedded_DEPS += $(EMBEDDED_FILES) $(EMBEDDED_LIST)
+
+CFLAGS_embedded = -DEMBED_ALL="$(EMBED_ALL)"
+
+# List of trusted root certificates
+#
+TRUSTED_LIST := $(BIN)/.trusted.list
+ifeq ($(wildcard $(TRUSTED_LIST)),)
+TRUST_OLD := <invalid>
+else
+TRUST_OLD := $(shell cat $(TRUSTED_LIST))
+endif
+ifneq ($(TRUST_OLD),$(TRUST))
+$(shell $(ECHO) "$(TRUST)" > $(TRUSTED_LIST))
+endif
+
+$(TRUSTED_LIST) :
+
+VERYCLEANUP += $(TRUSTED_LIST)
+
+# Trusted root certificate fingerprints
+#
+TRUSTED_CERTS := $(subst $(COMMA), ,$(TRUST))
+TRUSTED_FPS := $(foreach CERT,$(TRUSTED_CERTS),\
+ 0x$(subst :,$(COMMA) 0x,$(lastword $(subst =, ,\
+ $(shell $(OPENSSL) x509 -in $(CERT) -noout -sha256 \
+ -fingerprint))))$(COMMA))
+
+rootcert_DEPS += $(TRUSTED_FILES) $(TRUSTED_LIST)
+
+CFLAGS_rootcert = $(if $(TRUSTED_FPS),-DTRUSTED="$(TRUSTED_FPS)")
+
+# (Single-element) list of client certificates
+#
+CERT_LIST := $(BIN)/.certificate.list
+ifeq ($(wildcard $(CERT_LIST)),)
+CERT_OLD := <invalid>
+else
+CERT_OLD := $(shell cat $(CERT_LIST))
+endif
+ifneq ($(CERT_OLD),$(CERT))
+$(shell $(ECHO) "$(CERT)" > $(CERT_LIST))
+endif
+
+$(CERT_LIST) :
+
+VERYCLEANUP += $(CERT_LIST)
+
+# Embedded client certificate
+#
+CERT_INC := $(BIN)/.certificate.der
+
+ifdef CERT
+$(CERT_INC) : $(CERT) $(CERT_LIST)
+ $(Q)$(OPENSSL) x509 -in $< -outform DER -out $@
+
+clientcert_DEPS += $(CERT_INC)
+endif
+
+CLEANUP += $(CERT_INC)
+
+clientcert_DEPS += $(CERT_LIST)
+
+CFLAGS_clientcert += $(if $(CERT),-DCERTIFICATE="\"$(CERT_INC)\"")
+
+# (Single-element) list of client private keys
+#
+KEY_LIST := $(BIN)/.private_key.list
+ifeq ($(wildcard $(KEY_LIST)),)
+KEY_OLD := <invalid>
+else
+KEY_OLD := $(shell cat $(KEY_LIST))
+endif
+ifneq ($(KEY_OLD),$(KEY))
+$(shell $(ECHO) "$(KEY)" > $(KEY_LIST))
+endif
+
+$(KEY_LIST) :
+
+VERYCLEANUP += $(KEY_LIST)
+
+# Embedded client private key
+#
+KEY_INC := $(BIN)/.private_key.der
+
+ifdef KEY
+$(KEY_INC) : $(KEY) $(KEY_LIST)
+ $(Q)$(OPENSSL) rsa -in $< -outform DER -out $@
+
+clientcert_DEPS += $(KEY_INC)
+endif
+
+CLEANUP += $(KEY_INC)
+
+clientcert_DEPS += $(KEY_LIST)
+
+CFLAGS_clientcert += $(if $(KEY),-DPRIVATE_KEY="\"$(KEY_INC)\"")
+
+# These files use .incbin inline assembly to include a binary file.
+# Unfortunately ccache does not detect this dependency and caches
+# builds even when the binary file has changed.
+#
+$(BIN)/embedded.o : override CC := env CCACHE_DISABLE=1 $(CC)
+
+$(BIN)/clientcert.o : override CC := env CCACHE_DISABLE=1 $(CC)
+
+# We automatically generate rules for any file mentioned in AUTO_SRCS
+# using the following set of templates. It would be cleaner to use
+# $(eval ...), but this function exists only in GNU make >= 3.80.
+
+# deps_template : generate dependency list for a given source file
+#
+# $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c")
+# $(2) is the source type (e.g. "c")
+# $(3) is the source base name (e.g. "rtl8139")
+#
+define deps_template
+ @$(ECHO) " [DEPS] $(1)"
+ @$(MKDIR) -p $(BIN)/deps/$(dir $(1))
+ @$(CPP) $(CFLAGS) $(CFLAGS_$(2)) $(CFLAGS_$(3)) -DOBJECT=$(3) \
+ -Wno-error -M $(1) -MG -MP | \
+ sed 's/\.o\s*:/_DEPS +=/' > $(BIN)/deps/$(1).d
+endef
+
+# rules_template : generate rules for a given source file
+#
+# $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c")
+# $(2) is the source type (e.g. "c")
+# $(3) is the source base name (e.g. "rtl8139")
+#
+define rules_template
+ @$(ECHO) " [RULES] $(1)"
+ @$(MKDIR) -p $(BIN)/rules/$(dir $(1))
+ @$(ECHO_E) '\n$$(BIN)/$(3).o :' \
+ '$(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(3)_DEPS)' \
+ '\n\t$$(QM)$(ECHO) " [BUILD] $$@"' \
+ '\n\t$$(RULE_$(2))\n' \
+ '\nBOBJS += $$(BIN)/$(3).o\n' \
+ $(foreach TGT,$(DEBUG_TARGETS), \
+ $(if $(RULE_$(2)_to_$(TGT)), \
+ '\n$$(BIN)/$(3).$(TGT) :' \
+ '$(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(3)_DEPS)' \
+ '\n\t$$(QM)$(ECHO) " [BUILD] $$@"' \
+ '\n\t$$(RULE_$(2)_to_$(TGT))\n' \
+ '\n$(TGT)_OBJS += $$(BIN)/$(3).$(TGT)\n' ) ) \
+ '\n$(BIN)/deps/$(1).d : $$($(3)_DEPS)\n' \
+ '\nTAGS : $$($(3)_DEPS)\n' > $(BIN)/rules/$(1).r
+ @$(if $(findstring drivers/,$(1)),\
+ $(PERL) $(PARSEROM) $(1) >> $(BIN)/rules/$(1).r)
+endef
+
+# Rule to generate the dependency list file
+#
+$(BIN)/deps/%.d : % $(MAKEDEPS)
+ $(call deps_template,$<,$(subst .,,$(suffix $<)),$(basename $(notdir $<)))
+
+# Calculate and include the list of dependency list files
+#
+AUTO_DEPS = $(patsubst %,$(BIN)/deps/%.d,$(AUTO_SRCS))
+ifdef NEED_DEPS
+ifneq ($(AUTO_DEPS),)
+-include $(AUTO_DEPS)
+endif
+endif
+autodeps :
+ @$(ECHO) $(AUTO_DEPS)
+VERYCLEANUP += $(BIN)/deps
+
+# Rule to generate the rules file
+#
+$(BIN)/rules/%.r : % $(MAKEDEPS) $(PARSEROM)
+ $(call rules_template,$<,$(subst .,,$(suffix $<)),$(basename $(notdir $<)))
+
+# Calculate and include the list of rules files
+#
+AUTO_RULES = $(patsubst %,$(BIN)/rules/%.r,$(AUTO_SRCS))
+ifdef NEED_DEPS
+ifneq ($(AUTO_RULES),)
+-include $(AUTO_RULES)
+endif
+endif
+autorules :
+ @$(ECHO) $(AUTO_RULES)
+VERYCLEANUP += $(BIN)/rules
+
+# The following variables are created by the rules files
+#
+bobjs :
+ @$(ECHO) $(BOBJS)
+drivers :
+ @$(ECHO) $(DRIVERS)
+.PHONY : drivers
+roms :
+ @$(ECHO) $(ROMS)
+
+# Generate error usage information
+#
+$(BIN)/%.einfo : $(BIN)/%.o
+ $(QM)$(ECHO) " [EINFO] $@"
+ $(Q)$(OBJCOPY) -O binary -j .einfo --set-section-flags .einfo=alloc \
+ $< $@
+
+EINFOS := $(patsubst $(BIN)/%.o,$(BIN)/%.einfo,$(BOBJS))
+$(BIN)/errors : $(EINFOS) $(EINFO)
+ $(QM)$(ECHO) " [EINFO] $@"
+ $(Q)$(EINFO) $(EINFOS) | sort > $@
+CLEANUP += $(BIN)/errors # Doesn't match the $(BIN)/*.* pattern
+
+# Generate the NIC file from the parsed source files. The NIC file is
+# only for rom-o-matic.
+#
+$(BIN)/NIC : $(AUTO_DEPS)
+ @$(ECHO) '# This is an automatically generated file, do not edit' > $@
+ @$(ECHO) '# It does not affect anything in the build, ' \
+ 'it is only for rom-o-matic' >> $@
+ @$(ECHO) >> $@
+ @perl -ne 'chomp; print "$$1\n" if /\# NIC\t(.*)$$/' $^ >> $@
+CLEANUP += $(BIN)/NIC # Doesn't match the $(BIN)/*.* pattern
+
+# Analyse a target name (e.g. "bin/dfe538--prism2_pci.zrom.tmp") and
+# derive the variables:
+#
+# TGT_ELEMENTS : the elements of the target (e.g. "dfe538 prism2_pci")
+# TGT_PREFIX : the prefix type (e.g. "zrom")
+# TGT_DRIVERS : the driver for each element (e.g. "rtl8139 prism2_pci")
+# TGT_ROM_NAME : the ROM name (e.g. "dfe538")
+# TGT_MEDIA : the media type (e.g. "rom")
+#
+DRIVERS_ipxe = $(DRIVERS)
+CARD_DRIVER = $(firstword $(DRIVER_$(1)) $(1))
+TGT_ELEMENTS = $(subst --, ,$(firstword $(subst ., ,$(notdir $@))))
+TGT_PREFIX = $(word 2,$(subst ., ,$(notdir $@)))
+TGT_ROM_NAME = $(firstword $(TGT_ELEMENTS))
+TGT_DRIVERS = $(strip $(if $(DRIVERS_$(TGT_ROM_NAME)), \
+ $(DRIVERS_$(TGT_ROM_NAME)), \
+ $(foreach TGT_ELEMENT,$(TGT_ELEMENTS), \
+ $(call CARD_DRIVER,$(TGT_ELEMENT))) ))
+TGT_MEDIA = $(subst z,,$(TGT_PREFIX))
+
+# Look up ROM IDs for the current target
+# (e.g. "bin/dfe538--prism2_pci.zrom.tmp") and derive the variables:
+#
+# TGT_PCI_VENDOR : the PCI vendor ID (e.g. "0x1186")
+# TGT_PCI_DEVICE : the PCI device ID (e.g. "0x1300")
+#
+TGT_PCI_VENDOR = $(PCI_VENDOR_$(TGT_ROM_NAME))
+TGT_PCI_DEVICE = $(PCI_DEVICE_$(TGT_ROM_NAME))
+
+# Calculate link-time options for the current target
+# (e.g. "bin/dfe538--prism2_pci.zrom.tmp") and derive the variables:
+#
+# TGT_LD_DRIVERS : symbols to require in order to drag in the relevant drivers
+# (e.g. "obj_rtl8139 obj_prism2_pci")
+# TGT_LD_IDS : symbols to define in order to fill in ID structures in the
+# ROM header (e.g."pci_vendor_id=0x1186 pci_device_id=0x1300")
+#
+TGT_LD_DRIVERS = $(subst -,_,$(patsubst %,obj_%,$(TGT_DRIVERS)))
+TGT_LD_IDS = pci_vendor_id=$(firstword $(TGT_PCI_VENDOR) 0) \
+ pci_device_id=$(firstword $(TGT_PCI_DEVICE) 0)
+TGT_LD_ENTRY = _$(TGT_PREFIX)_start
+
+# Calculate linker flags based on link-time options for the current
+# target type (e.g. "bin/dfe538--prism2_pci.zrom.tmp") and derive the
+# variables:
+#
+# TGT_LD_FLAGS : target-specific flags to pass to linker (e.g.
+# "-u obj_zpciprefix -u obj_rtl8139 -u obj_prism2_pci
+# --defsym pci_vendor=0x1186 --defsym pci_device=0x1300")
+#
+TGT_LD_FLAGS = $(foreach SYM,$(TGT_LD_ENTRY) $(TGT_LD_DRIVERS) obj_config,\
+ -u $(SYM) --defsym check_$(SYM)=$(SYM) ) \
+ $(patsubst %,--defsym %,$(TGT_LD_IDS)) \
+ -e $(TGT_LD_ENTRY)
+
+# Calculate list of debugging versions of objects to be included in
+# the target.
+#
+DEBUG_LIST = $(subst $(COMMA), ,$(DEBUG))
+DEBUG_OBJ_LEVEL = $(firstword $(word 2,$(subst :, ,$(1))) 1)
+DEBUG_OBJ_BASE = $(word 1,$(subst :, ,$(1))).dbg$(call DEBUG_OBJ_LEVEL,$(1))
+DEBUG_OBJ = $(BIN)/$(call DEBUG_OBJ_BASE,$(1)).o
+DEBUG_ORIG_OBJ = $(BIN)/$(word 1,$(subst :, ,$(1))).o
+DEBUG_OBJS = $(foreach D,$(DEBUG_LIST),$(call DEBUG_OBJ,$(D)))
+DEBUG_ORIG_OBJS = $(foreach D,$(DEBUG_LIST),$(call DEBUG_ORIG_OBJ,$(D)))
+BLIB_OBJS = $(DEBUG_OBJS) $(filter-out $(DEBUG_ORIG_OBJS),$(BOBJS))
+
+# Print out all derived information for a given target.
+#
+$(BIN)/%.info :
+ @$(ECHO) 'Elements : $(TGT_ELEMENTS)'
+ @$(ECHO) 'Prefix : $(TGT_PREFIX)'
+ @$(ECHO) 'Drivers : $(TGT_DRIVERS)'
+ @$(ECHO) 'ROM name : $(TGT_ROM_NAME)'
+ @$(ECHO) 'Media : $(TGT_MEDIA)'
+ @$(ECHO)
+ @$(ECHO) 'PCI vendor : $(TGT_PCI_VENDOR)'
+ @$(ECHO) 'PCI device : $(TGT_PCI_DEVICE)'
+ @$(ECHO)
+ @$(ECHO) 'LD driver symbols : $(TGT_LD_DRIVERS)'
+ @$(ECHO) 'LD ID symbols : $(TGT_LD_IDS)'
+ @$(ECHO) 'LD entry point : $(TGT_LD_ENTRY)'
+ @$(ECHO)
+ @$(ECHO) 'LD target flags : $(TGT_LD_FLAGS)'
+ @$(ECHO)
+ @$(ECHO) 'Debugging objects : $(DEBUG_OBJS)'
+ @$(ECHO) 'Replaced objects : $(DEBUG_ORIG_OBJS)'
+
+# List of objects included in the last build of blib. This is needed
+# in order to correctly rebuild blib whenever the list of objects
+# changes.
+#
+BLIB_LIST := $(BIN)/.blib.list
+ifeq ($(wildcard $(BLIB_LIST)),)
+BLIB_OBJS_OLD := <invalid>
+else
+BLIB_OBJS_OLD := $(shell cat $(BLIB_LIST))
+endif
+ifneq ($(BLIB_OBJS_OLD),$(BLIB_OBJS))
+$(shell $(ECHO) "$(BLIB_OBJS)" > $(BLIB_LIST))
+endif
+
+$(BLIB_LIST) :
+
+VERYCLEANUP += $(BLIB_LIST)
+
+# Library of all objects
+#
+BLIB = $(BIN)/blib.a
+$(BLIB) : $(BLIB_OBJS) $(BLIB_LIST) $(MAKEDEPS)
+ $(Q)$(RM) $(BLIB)
+ $(QM)$(ECHO) " [AR] $@"
+ $(Q)$(AR) r $@ $(BLIB_OBJS)
+ $(Q)$(RANLIB) $@
+blib : $(BLIB)
+
+# Command to generate build ID. Must be unique for each $(BIN)/%.tmp,
+# even within the same build run.
+#
+BUILD_ID_CMD := perl -e 'printf "0x%08x", int ( rand ( 0xffffffff ) );'
+
+# Build an intermediate object file from the objects required for the
+# specified target.
+#
+$(BIN)/%.tmp : $(BLIB) $(MAKEDEPS) $(LDSCRIPT)
+ $(QM)$(ECHO) " [LD] $@"
+ $(Q)$(LD) $(LDFLAGS) -T $(LDSCRIPT) $(TGT_LD_FLAGS) $(BLIB) -o $@ \
+ --defsym _build_id=`$(BUILD_ID_CMD)` -Map $(BIN)/$*.tmp.map
+ $(Q)$(OBJDUMP) -ht $@ | $(PERL) $(SORTOBJDUMP) >> $(BIN)/$*.tmp.map
+
+# Keep intermediate object file (useful for debugging)
+.PRECIOUS : $(BIN)/%.tmp
+
+# Show a linker map for the specified target
+#
+$(BIN)/%.map : $(BIN)/%.tmp
+ @less $(BIN)/$*.tmp.map
+
+# Get objects list for the specified target
+#
+define objs_list
+ $(sort $(foreach OBJ_SYMBOL,\
+ $(filter obj_%,$(shell $(NM) $(1) | cut -d" " -f3)),\
+ $(patsubst obj_%,%,$(OBJ_SYMBOL))))
+endef
+$(BIN)/%.objs : $(BIN)/%.tmp
+ $(Q)$(ECHO) $(call objs_list,$<)
+$(BIN)/%.sizes : $(BIN)/%.tmp
+ $(Q)$(SIZE) -t $(foreach OBJ,$(call objs_list,$<),$(wildcard $(BIN)/$(subst _,?,$(OBJ)).o)) | \
+ sort -g
+
+# Get dependency list for the specified target
+#
+define deps_list
+ $(sort $(foreach OBJ,$(call objs_list,$(1)),$($(OBJ)_DEPS)))
+endef
+$(BIN)/%.deps : $(BIN)/%.tmp
+ $(Q)$(ECHO) $(call deps_list,$<)
+
+# Get unneeded source files for the specified target
+#
+define nodeps_list
+ $(sort $(filter-out $(call deps_list,$(1)),\
+ $(foreach BOBJ,$(BOBJS),\
+ $($(basename $(notdir $(BOBJ)))_DEPS))))
+endef
+$(BIN)/%.nodeps : $(BIN)/%.tmp
+ $(Q)$(ECHO) $(call nodeps_list,$<)
+
+# Get licensing verdict for the specified target
+#
+define licensable_deps_list
+ $(filter-out config/local/%.h,$(call deps_list,$(1)))
+endef
+define unlicensed_deps_list
+ $(shell grep -L FILE_LICENCE $(call licensable_deps_list,$(1)))
+endef
+define licence_list
+ $(patsubst __licence_%,%,\
+ $(filter __licence_%,$(shell $(NM) $(1) | cut -d" " -f3)))
+endef
+$(BIN)/%.licence : $(BIN)/%.tmp
+ $(QM)$(ECHO) " [LICENCE] $@"
+ $(Q)$(if $(strip $(call unlicensed_deps_list,$<)),\
+ echo -n "Unable to determine licence because the following " ;\
+ echo "files are missing a licence declaration:" ;\
+ echo $(call unlicensed_deps_list,$<);\
+ exit 1,\
+ $(PERL) $(LICENCE) $(call licence_list,$<))
+
+# Extract compression information from intermediate object file
+#
+$(BIN)/%.zinfo : $(BIN)/%.tmp
+ $(QM)$(ECHO) " [ZINFO] $@"
+ $(Q)$(OBJCOPY) -O binary -j .zinfo $< $@
+
+# Build raw binary file from intermediate object file
+#
+$(BIN)/%.bin : $(BIN)/%.tmp
+ $(QM)$(ECHO) " [BIN] $@"
+ $(Q)$(OBJCOPY) -O binary -R .zinfo $< $@
+
+# Compress raw binary file
+#
+$(BIN)/%.zbin : $(BIN)/%.bin $(BIN)/%.zinfo $(ZBIN)
+ $(QM)$(ECHO) " [ZBIN] $@"
+ $(Q)$(ZBIN) $(BIN)/$*.bin $(BIN)/$*.zinfo > $@
+
+# Rules for each media format. These are generated and placed in an
+# external Makefile fragment. We could do this via $(eval ...), but
+# that would require make >= 3.80.
+#
+# Note that there's an alternative way to generate most .rom images:
+# they can be copied from their 'master' ROM image using cp and
+# reprocessed with makerom to add the PCI IDs and ident string. The
+# relevant rule would look something like:
+#
+# $(BIN)/dfe538%rom : $(BIN)/rtl8139%rom
+# cat $< $@
+# $(FINALISE_rom)
+#
+# You can derive the ROM/driver relationships using the variables
+# DRIVER_<rom> and/or ROMS_<driver>.
+#
+# We don't currently do this, because (a) it would require generating
+# yet more Makefile fragments (since you need a rule for each ROM in
+# ROMS), and (b) the linker is so fast that it probably wouldn't make
+# much difference to the overall build time.
+
+# Add NON_AUTO_MEDIA to the media list, so that they show up in the
+# output of "make"
+#
+MEDIA += $(NON_AUTO_MEDIA)
+
+media :
+ @$(ECHO) $(MEDIA)
+
+AUTO_MEDIA = $(filter-out $(NON_AUTO_MEDIA),$(MEDIA))
+automedia :
+ @$(ECHO) $(AUTO_MEDIA)
+
+# media_template : create Makefile rules for specified media
+#
+# $(1) is the media name (e.g. "rom")
+#
+define media_template
+ @$(ECHO) " [MEDIARULES] $(1)"
+ @$(MKDIR) -p $(BIN)/rules/$(dir $(1))
+ @$(ECHO_E) '$$(BIN)/%.$(1) : $$(BIN)/%.$(1).zbin' \
+ '\n\t$$(QM)$(ECHO) " [FINISH] $$@"' \
+ '\n\t$$(Q)$$(CP) $$< $$@' \
+ '\n\t$$(Q)$$(PAD_$(1))' \
+ '\n\t$$(Q)$$(FINALISE_$(1))' \
+ > $(BIN)/rules/$(1).media.r
+endef
+
+# Rule to generate the Makefile rules to be included
+#
+$(BIN)/rules/%.media.r : $(MAKEDEPS)
+ $(call media_template,$*)
+
+# Calculate and include the list of Makefile rules files
+#
+MEDIA_RULES = $(patsubst %,$(BIN)/rules/%.media.r,$(AUTO_MEDIA))
+mediarules :
+ @$(ECHO) $(MEDIA_RULES)
+ifdef NEED_DEPS
+ifneq ($(MEDIA_RULES),)
+-include $(MEDIA_RULES)
+endif
+endif
+
+# Wrap up binary blobs (for embedded images)
+#
+$(BIN)/%.o : payload/%.img
+ $(QM)echo " [WRAP] $@"
+ $(Q)$(LD) -b binary -r -o $@ $< --undefined obj_payload \
+ --defsym obj_$*=0
+
+BOBJS += $(patsubst payload/%.img,$(BIN)/%.o,$(wildcard payload/*.img))
+
+# The "allXXXs" targets for each suffix
+#
+allall: allroms allmroms allpxes allisos alldsks
+allroms allmroms : all%s : $(foreach ROM,$(ROMS),$(BIN)/$(ROM).%)
+allpxes allisos alldsks : all%s : $(foreach DRIVER,$(DRIVERS),$(BIN)/$(DRIVER).%)
+
+# Alias for ipxe.%
+#
+$(BIN)/etherboot.% : $(BIN)/ipxe.%
+ ln -sf $(notdir $<) $@
+
+endif # defined(BIN)
+
+###############################################################################
+#
+# The compression utilities
+#
+$(NRV2B) : util/nrv2b.c $(MAKEDEPS)
+ $(QM)$(ECHO) " [HOSTCC] $@"
+ $(Q)$(HOST_CC) $(HOST_CFLAGS) -DENCODE -DDECODE -DMAIN -DVERBOSE \
+ -DNDEBUG -DBITSIZE=32 -DENDIAN=0 -o $@ $<
+CLEANUP += $(NRV2B)
+
+$(ZBIN) : util/zbin.c util/nrv2b.c $(MAKEDEPS)
+ $(QM)$(ECHO) " [HOSTCC] $@"
+ $(Q)$(HOST_CC) $(HOST_CFLAGS) -o $@ $<
+CLEANUP += $(ZBIN)
+
+###############################################################################
+#
+# The EFI image converter
+#
+ELF2EFI_CFLAGS := -I$(BINUTILS_DIR)/include -I$(BFD_DIR)/include \
+ -I$(ZLIB_DIR)/include -idirafter include
+ELF2EFI_LDFLAGS := -L$(BINUTILS_DIR)/lib -L$(BFD_DIR)/lib -L$(ZLIB_DIR)/lib \
+ -lbfd -ldl -liberty -lz -Wl,--no-warn-search-mismatch
+
+$(ELF2EFI32) : util/elf2efi.c $(MAKEDEPS)
+ $(QM)$(ECHO) " [HOSTCC] $@"
+ $(Q)$(HOST_CC) $(HOST_CFLAGS) $(ELF2EFI_CFLAGS) -DEFI_TARGET_IA32 $< \
+ $(ELF2EFI_LDFLAGS) -o $@
+CLEANUP += $(ELF2EFI32)
+
+$(ELF2EFI64) : util/elf2efi.c $(MAKEDEPS)
+ $(QM)$(ECHO) " [HOSTCC] $@"
+ $(Q)$(HOST_CC) $(HOST_CFLAGS) $(ELF2EFI_CFLAGS) -DEFI_TARGET_X64 $< \
+ $(ELF2EFI_LDFLAGS) -o $@
+CLEANUP += $(ELF2EFI64)
+
+$(EFIROM) : util/efirom.c $(MAKEDEPS)
+ $(QM)$(ECHO) " [HOSTCC] $@"
+ $(Q)$(HOST_CC) $(HOST_CFLAGS) -idirafter include -o $@ $<
+CLEANUP += $(EFIROM)
+
+###############################################################################
+#
+# The ICC fixup utility
+#
+$(ICCFIX) : util/iccfix.c $(MAKEDEPS)
+ $(QM)$(ECHO) " [HOSTCC] $@"
+ $(Q)$(HOST_CC) $(HOST_CFLAGS) -idirafter include -o $@ $<
+CLEANUP += $(ICCFIX)
+
+###############################################################################
+#
+# The error usage information utility
+#
+$(EINFO) : util/einfo.c $(MAKEDEPS)
+ $(QM)$(ECHO) " [HOSTCC] $@"
+ $(Q)$(HOST_CC) $(HOST_CFLAGS) -idirafter include -o $@ $<
+CLEANUP += $(EINFO)
+
+###############################################################################
+#
+# Local configs
+#
+config/local/%.h :
+ $(Q)touch $@
+
+###############################################################################
+#
+# Auto-incrementing build serial number. Append "bs" to your list of
+# build targets to get a serial number printed at the end of the
+# build. Enable -DBUILD_SERIAL in order to see it when the code runs.
+#
+BUILDSERIAL_H = config/.buildserial.h
+BUILDSERIAL_NOW = config/.buildserial.now
+BUILDSERIAL_NEXT = config/.buildserial.next
+
+$(BUILDSERIAL_NOW) $(BUILDSERIAL_NEXT) :
+ $(ECHO) 1 > $@
+
+$(BUILDSERIAL_H) : $(BUILDSERIAL_NOW) $(BUILDSERIAL_NEXT)
+ $(ECHO) '#define BUILD_SERIAL_NUM $(shell cat $<)' > $@
+
+ifeq ($(filter bs,$(MAKECMDGOALS)),bs)
+$(shell diff -q $(BUILDSERIAL_NOW) $(BUILDSERIAL_NEXT) > /dev/null || \
+ cp -f $(BUILDSERIAL_NEXT) $(BUILDSERIAL_NOW))
+endif
+
+bs : $(BUILDSERIAL_NOW)
+ @$(ECHO) $$(( $(shell cat $<) + 1 )) > $(BUILDSERIAL_NEXT)
+ @$(ECHO) "Build serial number is $(shell cat $<)"
+
+###############################################################################
+#
+# Build the TAGS file(s) for emacs
+#
+TAGS :
+ ctags -e -R -f $@ --exclude=bin
+
+CLEANUP += TAGS
+
+###############################################################################
+#
+# Force rebuild for any given target
+#
+%.rebuild :
+ rm -f $*
+ $(Q)$(MAKE) $*
+
+###############################################################################
+#
+# Symbol table checks
+#
+
+ifdef BIN
+
+SYMTAB = $(BIN)/symtab
+$(SYMTAB) : $(BLIB)
+ $(OBJDUMP) -w -t $< > $@
+
+CLEANUP += $(BIN)/symtab
+
+symcheck : $(SYMTAB)
+ $(PERL) $(SYMCHECK) $<
+
+endif # defined(BIN)
+
+###############################################################################
+#
+# Build bochs symbol table
+#
+
+ifdef BIN
+
+$(BIN)/%.bxs : $(BIN)/%.tmp
+ $(NM) $< | cut -d" " -f1,3 > $@
+
+endif # defined(BIN)
+
+###############################################################################
+#
+# Documentation
+#
+
+ifdef BIN
+
+$(BIN)/doxygen.cfg : doxygen.cfg $(MAKEDEPS)
+ $(Q)$(PERL) -pe 's{\@SRCDIRS\@}{$(SRCDIRS)}; ' \
+ -e 's{\@INCDIRS\@}{$(filter-out .,$(INCDIRS))}; ' \
+ -e 's{\@BIN\@}{$(BIN)}; ' \
+ -e 's{\@ARCH\@}{$(ARCH)}; ' \
+ $< > $@
+
+$(BIN)/doc : $(BIN)/doxygen.cfg
+ $(Q)$(DOXYGEN) $<
+
+.PHONY : $(BIN)/doc
+
+doc : $(BIN)/doc
+
+doc-clean :
+ $(Q)$(RM) -r $(BIN)/doc
+
+VERYCLEANUP += $(BIN)/doc
+
+docview :
+ @[ -f $(BIN)/doc/html/index.html ] || $(MAKE) $(BIN)/doc
+ @if [ -n "$$BROWSER" ] ; then \
+ ( $$BROWSER $(BIN)/doc/html/index.html & ) ; \
+ else \
+ $(ECHO) "Documentation index in $(BIN)/doc/html/index.html" ; \
+ fi
+
+endif # defined(BIN)
+
+###############################################################################
+#
+# Keyboard maps
+#
+
+hci/keymap/keymap_%.c :
+ $(Q)$(PERL) $(GENKEYMAP) $* > $@
+
+###############################################################################
+#
+# Force deletion of incomplete targets
+#
+
+.DELETE_ON_ERROR :
+
+###############################################################################
+#
+# Clean-up
+#
+clean :
+ $(RM) $(CLEANUP)
+
+veryclean : clean
+ $(RM) -r $(VERYCLEANUP)
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile b/src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile
new file mode 100644
index 00000000..ca258330
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile
@@ -0,0 +1,99 @@
+# Force i386-only instructions
+#
+CFLAGS += -march=i386
+
+# Code size reduction.
+#
+CFLAGS += -fomit-frame-pointer
+
+# Code size reduction.
+#
+ifeq ($(CCTYPE),gcc)
+CFLAGS += -fstrength-reduce
+endif
+
+# Code size reduction. gcc3 needs a different syntax to gcc2 if you
+# want to avoid spurious warnings.
+#
+ifeq ($(CCTYPE),gcc)
+GCC_VERSION := $(subst ., ,$(shell $(CC) -dumpversion))
+GCC_MAJOR := $(firstword $(GCC_VERSION))
+ifeq ($(GCC_MAJOR),2)
+CFLAGS += -malign-jumps=1 -malign-loops=1 -malign-functions=1
+else
+CFLAGS += -falign-jumps=1 -falign-loops=1 -falign-functions=1
+endif # gcc2
+endif # gcc
+
+# Code size reduction. This is almost always a win. The kernel uses
+# it, too.
+#
+ifeq ($(CCTYPE),gcc)
+CFLAGS += -mpreferred-stack-boundary=2
+endif
+
+# Code size reduction. Use regparm for all functions - C functions
+# called from assembly (or vice versa) need __asmcall now
+#
+CFLAGS += -mregparm=3
+
+# Code size reduction. Use -mrtd (same __asmcall requirements as above)
+ifeq ($(CCTYPE),gcc)
+CFLAGS += -mrtd
+endif
+
+# Code size reduction. This is the logical complement to -mregparm=3.
+# It doesn't currently buy us anything, but if anything ever tries to
+# return small structures, let's be prepared
+#
+CFLAGS += -freg-struct-return
+
+# Force 32-bit code even on an x86-64 machine
+#
+CFLAGS += -m32
+ASFLAGS += --32
+ifeq ($(HOST_OS),FreeBSD)
+LDFLAGS += -m elf_i386_fbsd
+else
+LDFLAGS += -m elf_i386
+endif
+
+# EFI requires -fshort-wchar, and nothing else currently uses wchar_t
+#
+CFLAGS += -fshort-wchar
+
+# We need to undefine the default macro "i386" when compiling .S
+# files, otherwise ".arch i386" translates to ".arch 1"...
+#
+CFLAGS += -Ui386
+
+# Locations of utilities
+#
+ISOLINUX_BIN_LIST := \
+ $(ISOLINUX_BIN) \
+ /usr/lib/syslinux/isolinux.bin \
+ /usr/share/syslinux/isolinux.bin \
+ /usr/local/share/syslinux/isolinux.bin
+ISOLINUX_BIN = $(firstword $(wildcard $(ISOLINUX_BIN_LIST)))
+
+# i386-specific directories containing source files
+#
+SRCDIRS += arch/i386/core arch/i386/transitions arch/i386/prefix
+SRCDIRS += arch/i386/firmware/pcbios
+SRCDIRS += arch/i386/image
+SRCDIRS += arch/i386/interface/pcbios
+SRCDIRS += arch/i386/interface/pxe
+SRCDIRS += arch/i386/interface/pxeparent
+SRCDIRS += arch/i386/interface/syslinux
+SRCDIRS += arch/i386/interface/vmware
+SRCDIRS += arch/i386/hci/commands
+
+# Include common x86 Makefile
+#
+MAKEDEPS += arch/x86/Makefile
+include arch/x86/Makefile
+
+# Include platform-specific Makefile
+#
+MAKEDEPS += arch/i386/Makefile.$(PLATFORM)
+include arch/i386/Makefile.$(PLATFORM)
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile.efi b/src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile.efi
new file mode 100644
index 00000000..8d651b04
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile.efi
@@ -0,0 +1,10 @@
+# -*- makefile -*- : Force emacs to use Makefile mode
+
+# Specify EFI image builder
+#
+ELF2EFI = $(ELF2EFI32)
+
+# Include generic EFI Makefile
+#
+MAKEDEPS += arch/x86/Makefile.efi
+include arch/x86/Makefile.efi
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile.linux b/src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile.linux
new file mode 100644
index 00000000..46328c83
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile.linux
@@ -0,0 +1,6 @@
+LDSCRIPT = arch/i386/scripts/linux.lds
+
+SRCDIRS += arch/i386/core/linux
+
+MAKEDEPS += arch/x86/Makefile.linux
+include arch/x86/Makefile.linux
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile.pcbios b/src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile.pcbios
new file mode 100644
index 00000000..e1b226f5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/Makefile.pcbios
@@ -0,0 +1,87 @@
+# -*- makefile -*- : Force emacs to use Makefile mode
+
+# The i386 linker script
+#
+LDSCRIPT = arch/i386/scripts/i386.lds
+
+# Stop ld from complaining about our customised linker script
+#
+LDFLAGS += -N --no-check-sections
+
+# pcbios specific drivers
+SRCDIRS += arch/i386/drivers
+SRCDIRS += arch/i386/drivers/net
+
+# Media types.
+#
+MEDIA += rom
+MEDIA += mrom
+MEDIA += pxe
+MEDIA += kpxe
+MEDIA += kkpxe
+MEDIA += kkkpxe
+MEDIA += lkrn
+MEDIA += dsk
+MEDIA += nbi
+MEDIA += hd
+MEDIA += raw
+MEDIA += exe
+
+# Padding rules
+#
+PAD_rom = $(PERL) $(PADIMG) --blksize=512 --byte=0xff $@
+PAD_mrom = $(PAD_rom)
+PAD_dsk = $(PERL) $(PADIMG) --blksize=512 $@
+PAD_hd = $(PERL) $(PADIMG) --blksize=32768 $@
+PAD_exe = $(PERL) $(PADIMG) --blksize=512 $@
+
+# Finalisation rules
+#
+FINALISE_rom = $(PERL) $(FIXROM) $@
+FINALISE_mrom = $(FINALISE_rom)
+
+# rule to make a non-emulation ISO boot image
+NON_AUTO_MEDIA += iso
+%iso: %lkrn util/geniso
+ $(QM)$(ECHO) " [GENISO] $@"
+ $(Q)ISOLINUX_BIN=$(ISOLINUX_BIN) bash util/geniso $@ $<
+
+# rule to make a floppy emulation ISO boot image
+NON_AUTO_MEDIA += liso
+%liso: %lkrn util/genliso
+ $(QM)$(ECHO) " [GENLISO] $@"
+ $(Q)bash util/genliso $@ $<
+
+# rule to make a syslinux floppy image (mountable, bootable)
+NON_AUTO_MEDIA += sdsk
+%sdsk: %lkrn util/gensdsk
+ $(QM)$(ECHO) " [GENSDSK] $@"
+ $(Q)bash util/gensdsk $@ $<
+
+# rule to write disk images to /dev/fd0
+NON_AUTO_MEDIA += fd0
+%fd0 : %dsk
+ $(QM)$(ECHO) " [DD] $@"
+ $(Q)dd if=$< bs=512 conv=sync of=/dev/fd0
+ $(Q)sync
+
+# Special target for building Master Boot Record binary
+$(BIN)/mbr.bin : $(BIN)/mbr.o
+ $(QM)$(ECHO) " [OBJCOPY] $@"
+ $(Q)$(OBJCOPY) -O binary $< $@
+
+# rule to make a USB disk image
+$(BIN)/usbdisk.bin : $(BIN)/usbdisk.o
+ $(QM)$(ECHO) " [OBJCOPY] $@"
+ $(Q)$(OBJCOPY) -O binary $< $@
+
+NON_AUTO_MEDIA += usb
+%usb: $(BIN)/usbdisk.bin %hd
+ $(QM)$(ECHO) " [FINISH] $@"
+ $(Q)cat $^ > $@
+
+# Padded floppy image (e.g. for iLO)
+NON_AUTO_MEDIA += pdsk
+%pdsk : %dsk
+ $(Q)cp $< $@
+ $(Q)$(PADIMG) --blksize=1474560 $@
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/README.i386 b/src/VBox/Devices/PC/ipxe/src/arch/i386/README.i386
new file mode 100644
index 00000000..b9b79cc4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/README.i386
@@ -0,0 +1,197 @@
+Etherboot/NILO i386 initialisation path and external call interface
+===================================================================
+
+1. Background
+
+GCC compiles 32-bit code. It is capable of producing
+position-independent code, but the resulting binary is about 25%
+bigger than the corresponding fixed-position code. Since one main use
+of Etherboot is as firmware to be burned into an EPROM, code size must
+be kept as small as possible.
+
+This means that we want to compile fixed-position code with GCC, and
+link it to have a predetermined start address. The problem then is
+that we must know the address that the code will be loaded to when it
+runs. There are several ways to solve this:
+
+1. Pick an address, link the code with this start address, then make
+ sure that the code gets loaded at that location. This is
+ problematic, because we may pick an address that we later end up
+ wanting to use to load the operating system that we're booting.
+
+2. Pick an address, link the code with this start address, then set up
+ virtual addressing so that the virtual addresses match the
+ link-time addresses regardless of the real physical address that
+ the code is loaded to. This enables us to relocate Etherboot to
+ the top of high memory, where it will be out of the way of any
+ loading operating system.
+
+3. Link the code with a text start address of zero and a data start
+ address also of zero. Use 16-bit real mode and the
+ quasi-position-independence it gives you via segment addressing.
+ Doing this requires that we generate 16-bit code, rather than
+ 32-bit code, and restricts us to a maximum of 64kB in each segment.
+
+There are other possible approaches (e.g. including a relocation table
+and code that performs standard dynamic relocation), but the three
+options listed above are probably the best available.
+
+Etherboot can be invoked in a variety of ways (ROM, floppy, as a PXE
+NBP, etc). Several of these ways involve control being passed to
+Etherboot with the CPU in 16-bit real mode. Some will involve the CPU
+being in 32-bit protected mode, and there's an outside chance that
+some may involve the CPU being in 16-bit protected mode. We will
+almost certainly have to effect a CPU mode change in order to reach
+the mode we want to be in to execute the C code.
+
+Additionally, Etherboot may wish to call external routines, such as
+BIOS interrupts, which must be called in 16-bit real mode. When
+providing a PXE API, Etherboot must provide a mechanism for external
+code to call it from 16-bit real mode.
+
+Not all i386 builds of Etherboot will want to make real-mode calls.
+For example, when built for LinuxBIOS rather than the standard PCBIOS,
+no real-mode calls are necessary.
+
+For the ultimate in PXE compatibility, we may want to build Etherboot
+to run permanently in real mode.
+
+There is a wide variety of potential combinations of mode switches
+that we may wish to implement. There are additional complications,
+such as the inability to access a high-memory stack when running in
+real mode.
+
+2. Transition libraries
+
+To handle all these various combinations of mode switches, we have
+several "transition" libraries in Etherboot. We also have the concept
+of an "internal" and an "external" environment. The internal
+environment is the environment within which we can execute C code.
+The external environment is the environment of whatever external code
+we're trying to interface to, such as the system BIOS or a PXE NBP.
+
+As well as having a separate addressing scheme, the internal
+environment also has a separate stack.
+
+The transition libraries are:
+
+a) librm
+
+librm handles transitions between an external 16-bit real-mode
+environment and an internal 32-bit protected-mode environment with
+virtual addresses.
+
+b) libkir
+
+libkir handles transitions between an external 16-bit real-mode (or
+16:16 or 16:32 protected-mode) environment and an internal 16-bit
+real-mode (or 16:16 protected-mode) environment.
+
+c) libpm
+
+libpm handles transitions between an external 32-bit protected-mode
+environment with flat physical addresses and an internal 32-bit
+protected-mode environment with virtual addresses.
+
+The transition libraries handle the transitions required when
+Etherboot is started up for the first time, the transitions required
+to execute any external code, and the transitions required when
+Etherboot exits (if it exits). When Etherboot provides a PXE API,
+they also handle the transitions required when a PXE client makes a
+PXE API call to Etherboot.
+
+Etherboot may use multiple transition libraries. For example, an
+Etherboot ELF image does not require librm for its initial transitions
+from prefix to runtime, but may require librm for calling external
+real-mode functions.
+
+3. Setup and initialisation
+
+Etherboot is conceptually divided into the prefix, the decompressor,
+and the runtime image. (For non-compressed images, the decompressor
+is a no-op.) The complete image comprises all three parts and is
+distinct from the runtime image, which exclude the prefix and the
+decompressor.
+
+The prefix does several tasks:
+
+ Load the complete image into memory. (For example, the floppy
+ prefix issues BIOS calls to load the remainder of the complete image
+ from the floppy disk into RAM, and the ISA ROM prefix copies the ROM
+ contents into RAM for faster access.)
+
+ Call the decompressor, if the runtime image is compressed. This
+ decompresses the runtime image.
+
+ Call the runtime image's setup() routine. This is a routine
+ implemented in assembly code which sets up the internal environment
+ so that C code can execute.
+
+ Call the runtime image's arch_initialise() routine. This is a
+ routine implemented in C which does some basic startup tasks, such
+ as initialising the console device, obtaining a memory map and
+ relocating the runtime image to high memory.
+
+ Call the runtime image's arch_main() routine. This records the exit
+ mechanism requested by the prefix and calls main(). (The prefix
+ needs to register an exit mechanism because by the time main()
+ returns, the memory occupied by the prefix has most likely been
+ overwritten.)
+
+When acting as a PXE ROM, the ROM prefix contains an UNDI loader
+routine in addition to its usual code. The UNDI loader performs a
+similar sequence of steps:
+
+ Load the complete image into memory.
+
+ Call the decompressor.
+
+ Call the runtime image's setup() routine.
+
+ Call the runtime image's arch_initialise() routine.
+
+ Call the runtime image's install_pxe_stack() routine.
+
+ Return to caller.
+
+The runtime image's setup() routine will perform the following steps:
+
+ Switch to the internal environment using an appropriate transition
+ library. This will record the parameters of the external
+ environment.
+
+ Set up the internal environment: load a stack, and set up a GDT for
+ virtual addressing if virtual addressing is to be used.
+
+ Switch back to the external environment using the transition
+ library. This will record the parameters of the internal
+ environment.
+
+Once the setup() routine has returned, the internal environment has been
+set up ready for C code to run. The prefix can call C routines using
+a function from the transition library.
+
+The runtime image's arch_initialise() routine will perform the
+following steps:
+
+ Zero the bss
+
+ Initialise the console device(s) and print a welcome message.
+
+ Obtain a memory map via the INT 15,E820 BIOS call or suitable
+ fallback mechanism. [not done if libkir is being used]
+
+ Relocate the runtime image to the top of high memory. [not done if
+ libkir is being used]
+
+ Install librm to base memory. [done only if librm is being used]
+
+ Call initialise().
+
+ Return to the prefix, setting registers to indicate to the prefix
+ the new location of the transition library, if applicable. Which
+ registers these are is specific to the transition library being
+ used.
+
+Once the arch_initialise() routine has returned, the prefix will
+probably call arch_main().
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/basemem_packet.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/basemem_packet.c
new file mode 100644
index 00000000..d487cce3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/basemem_packet.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Packet buffer in base memory. Used by various components which
+ * need to pass packets to and from external real-mode code.
+ *
+ */
+
+#include <basemem_packet.h>
+
+#undef basemem_packet
+char __bss16_array ( basemem_packet, [BASEMEM_PACKET_LEN] );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/cpu.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/cpu.c
new file mode 100644
index 00000000..c24fa4e6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/cpu.c
@@ -0,0 +1,73 @@
+#include <stdint.h>
+#include <string.h>
+#include <cpu.h>
+
+/** @file
+ *
+ * CPU identification
+ *
+ */
+
+/**
+ * Test to see if CPU flag is changeable
+ *
+ * @v flag Flag to test
+ * @ret can_change Flag is changeable
+ */
+static inline int flag_is_changeable ( unsigned int flag ) {
+ uint32_t f1, f2;
+
+ __asm__ ( "pushfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "movl %0,%1\n\t"
+ "xorl %2,%0\n\t"
+ "pushl %0\n\t"
+ "popfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "popfl\n\t"
+ : "=&r" ( f1 ), "=&r" ( f2 )
+ : "ir" ( flag ) );
+
+ return ( ( ( f1 ^ f2 ) & flag ) != 0 );
+}
+
+/**
+ * Get CPU information
+ *
+ * @v cpu CPU information structure to fill in
+ */
+void get_cpuinfo ( struct cpuinfo_x86 *cpu ) {
+ unsigned int cpuid_level;
+ unsigned int cpuid_extlevel;
+ unsigned int discard_1, discard_2, discard_3;
+
+ memset ( cpu, 0, sizeof ( *cpu ) );
+
+ /* Check for CPUID instruction */
+ if ( ! flag_is_changeable ( X86_EFLAGS_ID ) ) {
+ DBG ( "CPUID not supported\n" );
+ return;
+ }
+
+ /* Get features, if present */
+ cpuid ( 0x00000000, &cpuid_level, &discard_1,
+ &discard_2, &discard_3 );
+ if ( cpuid_level >= 0x00000001 ) {
+ cpuid ( 0x00000001, &discard_1, &discard_2,
+ &discard_3, &cpu->features );
+ } else {
+ DBG ( "CPUID cannot return capabilities\n" );
+ }
+
+ /* Get 64-bit features, if present */
+ cpuid ( 0x80000000, &cpuid_extlevel, &discard_1,
+ &discard_2, &discard_3 );
+ if ( ( cpuid_extlevel & 0xffff0000 ) == 0x80000000 ) {
+ if ( cpuid_extlevel >= 0x80000001 ) {
+ cpuid ( 0x80000001, &discard_1, &discard_2,
+ &discard_3, &cpu->amd_features );
+ }
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/dumpregs.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/dumpregs.c
new file mode 100644
index 00000000..82dc2184
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/dumpregs.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <realmode.h>
+
+void __asmcall _dump_regs ( struct i386_all_regs *ix86 ) {
+
+ __asm__ __volatile__ (
+ TEXT16_CODE ( ".globl dump_regs\n\t"
+ "\ndump_regs:\n\t"
+ "pushl $_dump_regs\n\t"
+ "pushw %%cs\n\t"
+ "call prot_call\n\t"
+ "addr32 leal 4(%%esp), %%esp\n\t"
+ "ret\n\t" ) : : );
+
+ printf ( "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
+ "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
+ "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
+ ix86->regs.eax, ix86->regs.ebx, ix86->regs.ecx,
+ ix86->regs.edx, ix86->regs.esi, ix86->regs.edi,
+ ix86->regs.ebp, ix86->regs.esp,
+ ix86->segs.cs, ix86->segs.ss, ix86->segs.ds,
+ ix86->segs.es, ix86->segs.fs, ix86->segs.gs );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/gdbidt.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/gdbidt.S
new file mode 100644
index 00000000..cd8b38a9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/gdbidt.S
@@ -0,0 +1,215 @@
+/*
+ * Interrupt Descriptor Table (IDT) setup and interrupt handlers for GDB stub.
+ */
+
+#include <librm.h>
+
+#define SIZEOF_I386_REGS 32
+#define SIZEOF_I386_FLAGS 4
+
+/****************************************************************************
+ * Interrupt Descriptor Table
+ ****************************************************************************
+ */
+ .section ".data16", "aw", @progbits
+ .globl idtr
+idtr:
+idt_limit:
+ .word idt_length - 1
+idt_base:
+ .long 0
+
+/* IDT entries have the following format:
+ * offset_lo, segment selector, flags, offset_hi
+ *
+ * Since it is not possible to specify relocations in arbitrary
+ * expressions like (int_overflow & 0xffff), we initialise the
+ * IDT with entries in an incorrect format.
+ *
+ * The entries are shuffled into the correct format in init_librm().
+ */
+#define IDT_ENTRY_EMPTY(name) .word 0, 0, 0, 0
+#define IDT_ENTRY_PRESENT(name) \
+ .long int_##name; \
+ .word 0x8e00, VIRTUAL_CS
+
+.align 16
+idt:
+ IDT_ENTRY_PRESENT(divide_error)
+ IDT_ENTRY_PRESENT(debug_trap)
+ IDT_ENTRY_EMPTY(non_maskable_interrupt)
+ IDT_ENTRY_PRESENT(breakpoint)
+ IDT_ENTRY_PRESENT(overflow)
+ IDT_ENTRY_PRESENT(bound_range_exceeded)
+ IDT_ENTRY_PRESENT(invalid_opcode)
+ IDT_ENTRY_EMPTY(device_not_available)
+ IDT_ENTRY_PRESENT(double_fault)
+ IDT_ENTRY_EMPTY(coprocessor_segment_overrun)
+ IDT_ENTRY_PRESENT(invalid_tss)
+ IDT_ENTRY_PRESENT(segment_not_present)
+ IDT_ENTRY_PRESENT(stack_segment_fault)
+ IDT_ENTRY_PRESENT(general_protection)
+ IDT_ENTRY_PRESENT(page_fault)
+idt_end:
+ .equ idt_length, idt_end - idt
+
+/* The IDT entries are fixed up (once) in init_librm() */
+idt_fixed:
+ .byte 0
+
+/****************************************************************************
+ * idt_init (real-mode near call, 16-bit real-mode near return address)
+ *
+ * Initialise the IDT, called from init_librm.
+ *
+ * Parameters:
+ * %eax : IDT base address
+ *
+ * Destroys %ax, %bx, and %di.
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+ .code16
+ .globl idt_init
+idt_init:
+ movl %eax, idt_base
+ addl $idt, idt_base
+
+ /* IDT entries are only fixed up once */
+ movb idt_fixed, %al
+ orb %al, %al
+ jnz 2f
+ movb $1, idt_fixed
+
+ /* Shuffle IDT entries into the correct format */
+ movb $(idt_length / 8), %al
+ movw $idt, %bx
+ or %al, %al
+ jz 2f
+1:
+ movw 2(%bx), %di
+ xchg %di, 6(%bx)
+ movw %di, 2(%bx)
+ addw $8, %bx
+ dec %al
+ jnz 1b
+2:
+ ret
+
+/****************************************************************************
+ * Interrupt handlers
+ ****************************************************************************
+ */
+ .section ".text", "ax", @progbits
+ .code32
+
+/* POSIX signal numbers for reporting traps to GDB */
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGBUS 7
+#define SIGFPE 8
+#define SIGSEGV 11
+#define SIGSTKFLT 16
+
+int_divide_error:
+ pushl $SIGFPE
+ jmp do_interrupt
+
+int_debug_trap:
+int_breakpoint:
+ pushl $SIGTRAP
+ jmp do_interrupt
+
+int_overflow:
+int_bound_range_exceeded:
+ pushl $SIGSTKFLT
+ jmp do_interrupt
+
+int_invalid_opcode:
+ pushl $SIGILL
+ jmp do_interrupt
+
+int_double_fault:
+ movl $SIGBUS, (%esp)
+ jmp do_interrupt
+
+int_invalid_tss:
+int_segment_not_present:
+int_stack_segment_fault:
+int_general_protection:
+int_page_fault:
+ movl $SIGSEGV, (%esp)
+ jmp do_interrupt
+
+/* When invoked, the stack contains: eflags, cs, eip, signo. */
+#define IH_OFFSET_GDB_REGS ( 0 )
+#define IH_OFFSET_GDB_EIP ( IH_OFFSET_GDB_REGS + SIZEOF_I386_REGS )
+#define IH_OFFSET_GDB_EFLAGS ( IH_OFFSET_GDB_EIP + 4 )
+#define IH_OFFSET_GDB_SEG_REGS ( IH_OFFSET_GDB_EFLAGS + SIZEOF_I386_FLAGS )
+#define IH_OFFSET_GDB_END ( IH_OFFSET_GDB_SEG_REGS + 6 * 4 )
+#define IH_OFFSET_SIGNO ( IH_OFFSET_GDB_END )
+#define IH_OFFSET_OLD_EIP ( IH_OFFSET_SIGNO + 4 )
+#define IH_OFFSET_OLD_CS ( IH_OFFSET_OLD_EIP + 4 )
+#define IH_OFFSET_OLD_EFLAGS ( IH_OFFSET_OLD_CS + 4 )
+#define IH_OFFSET_END ( IH_OFFSET_OLD_EFLAGS + 4 )
+
+/* We also access the stack whilst still storing or restoring
+ * the register snapshot. Since ESP is in flux, we need
+ * special offsets.
+ */
+#define IH_OFFSET_FLUX_OLD_CS ( IH_OFFSET_OLD_CS - 44 )
+#define IH_OFFSET_FLUX_OLD_EFLAGS ( IH_OFFSET_OLD_EFLAGS - 40 )
+#define IH_OFFSET_FLUX_OLD_EIP ( IH_OFFSET_OLD_EIP - 36 )
+#define IH_OFFSET_FLUX_END ( IH_OFFSET_END - 20 )
+do_interrupt:
+ /* Store CPU state in GDB register snapshot */
+ pushw $0
+ pushw %gs
+ pushw $0
+ pushw %fs
+ pushw $0
+ pushw %es
+ pushw $0
+ pushw %ds
+ pushw $0
+ pushw %ss
+ pushw $0
+ pushw IH_OFFSET_FLUX_OLD_CS + 2(%esp)
+ pushl IH_OFFSET_FLUX_OLD_EFLAGS(%esp)
+ pushl IH_OFFSET_FLUX_OLD_EIP(%esp)
+ pushl %edi
+ pushl %esi
+ pushl %ebp
+ leal IH_OFFSET_FLUX_END(%esp), %edi
+ pushl %edi /* old ESP */
+ pushl %ebx
+ pushl %edx
+ pushl %ecx
+ pushl %eax
+
+ /* Call GDB stub exception handler */
+ pushl %esp
+ pushl (IH_OFFSET_SIGNO + 4)(%esp)
+ call gdbmach_handler
+ addl $8, %esp
+
+ /* Restore CPU state from GDB register snapshot */
+ popl %eax
+ popl %ecx
+ popl %edx
+ popl %ebx
+ addl $4, %esp /* Changing ESP currently not supported */
+ popl %ebp
+ popl %esi
+ popl %edi
+ popl IH_OFFSET_FLUX_OLD_EIP(%esp)
+ popl IH_OFFSET_FLUX_OLD_EFLAGS(%esp)
+ popl IH_OFFSET_FLUX_OLD_CS(%esp)
+ popl %ss
+ popl %ds
+ popl %es
+ popl %fs
+ popl %gs
+
+ addl $4, %esp /* drop signo */
+ iret
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/gdbmach.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/gdbmach.c
new file mode 100644
index 00000000..68b37c04
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/gdbmach.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2008 Stefan Hajnoczi <stefanha@gmail.com>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdio.h>
+#include <assert.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/gdbstub.h>
+#include <gdbmach.h>
+
+/** @file
+ *
+ * GDB architecture-specific bits for i386
+ *
+ */
+
+enum {
+ DR7_CLEAR = 0x00000400, /* disable hardware breakpoints */
+ DR6_CLEAR = 0xffff0ff0, /* clear breakpoint status */
+};
+
+/** Hardware breakpoint, fields stored in x86 bit pattern form */
+struct hwbp {
+ int type; /* type (1=write watchpoint, 3=access watchpoint) */
+ unsigned long addr; /* linear address */
+ size_t len; /* length (0=1-byte, 1=2-byte, 3=4-byte) */
+ int enabled;
+};
+
+static struct hwbp hwbps [ 4 ];
+static gdbreg_t dr7 = DR7_CLEAR;
+
+static struct hwbp *gdbmach_find_hwbp ( int type, unsigned long addr, size_t len ) {
+ struct hwbp *available = NULL;
+ unsigned int i;
+ for ( i = 0; i < sizeof hwbps / sizeof hwbps [ 0 ]; i++ ) {
+ if ( hwbps [ i ].type == type && hwbps [ i ].addr == addr && hwbps [ i ].len == len ) {
+ return &hwbps [ i ];
+ }
+ if ( !hwbps [ i ].enabled ) {
+ available = &hwbps [ i ];
+ }
+ }
+ return available;
+}
+
+static void gdbmach_commit_hwbp ( struct hwbp *bp ) {
+ unsigned int regnum = bp - hwbps;
+
+ /* Set breakpoint address */
+ assert ( regnum < ( sizeof hwbps / sizeof hwbps [ 0 ] ) );
+ switch ( regnum ) {
+ case 0:
+ __asm__ __volatile__ ( "movl %0, %%dr0\n" : : "r" ( bp->addr ) );
+ break;
+ case 1:
+ __asm__ __volatile__ ( "movl %0, %%dr1\n" : : "r" ( bp->addr ) );
+ break;
+ case 2:
+ __asm__ __volatile__ ( "movl %0, %%dr2\n" : : "r" ( bp->addr ) );
+ break;
+ case 3:
+ __asm__ __volatile__ ( "movl %0, %%dr3\n" : : "r" ( bp->addr ) );
+ break;
+ }
+
+ /* Set type */
+ dr7 &= ~( 0x3 << ( 16 + 4 * regnum ) );
+ dr7 |= bp->type << ( 16 + 4 * regnum );
+
+ /* Set length */
+ dr7 &= ~( 0x3 << ( 18 + 4 * regnum ) );
+ dr7 |= bp->len << ( 18 + 4 * regnum );
+
+ /* Set/clear local enable bit */
+ dr7 &= ~( 0x3 << 2 * regnum );
+ dr7 |= bp->enabled << 2 * regnum;
+}
+
+int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len, int enable ) {
+ struct hwbp *bp;
+
+ /* Check and convert breakpoint type to x86 type */
+ switch ( type ) {
+ case GDBMACH_WATCH:
+ type = 0x1;
+ break;
+ case GDBMACH_AWATCH:
+ type = 0x3;
+ break;
+ default:
+ return 0; /* unsupported breakpoint type */
+ }
+
+ /* Only lengths 1, 2, and 4 are supported */
+ if ( len != 2 && len != 4 ) {
+ len = 1;
+ }
+ len--; /* convert to x86 breakpoint length bit pattern */
+
+ /* Calculate linear address by adding segment base */
+ addr += virt_offset;
+
+ /* Set up the breakpoint */
+ bp = gdbmach_find_hwbp ( type, addr, len );
+ if ( !bp ) {
+ return 0; /* ran out of hardware breakpoints */
+ }
+ bp->type = type;
+ bp->addr = addr;
+ bp->len = len;
+ bp->enabled = enable;
+ gdbmach_commit_hwbp ( bp );
+ return 1;
+}
+
+static void gdbmach_disable_hwbps ( void ) {
+ /* Store and clear hardware breakpoints */
+ __asm__ __volatile__ ( "movl %0, %%dr7\n" : : "r" ( DR7_CLEAR ) );
+}
+
+static void gdbmach_enable_hwbps ( void ) {
+ /* Clear breakpoint status register */
+ __asm__ __volatile__ ( "movl %0, %%dr6\n" : : "r" ( DR6_CLEAR ) );
+
+ /* Restore hardware breakpoints */
+ __asm__ __volatile__ ( "movl %0, %%dr7\n" : : "r" ( dr7 ) );
+}
+
+__asmcall void gdbmach_handler ( int signo, gdbreg_t *regs ) {
+ gdbmach_disable_hwbps();
+ gdbstub_handler ( signo, regs );
+ gdbmach_enable_hwbps();
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/linux/linux_syscall.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/linux/linux_syscall.S
new file mode 100644
index 00000000..38a3e74b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/linux/linux_syscall.S
@@ -0,0 +1,45 @@
+
+ .section ".data"
+ .globl linux_errno
+
+linux_errno: .int 0
+
+ .section ".text"
+ .code32
+ .globl linux_syscall
+ .type linux_syscall, @function
+
+linux_syscall:
+ /* Save registers */
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ pushl %ebp
+
+ movl 20(%esp), %eax // C arg1 -> syscall number
+ movl 24(%esp), %ebx // C arg2 -> syscall arg1
+ movl 28(%esp), %ecx // C arg3 -> syscall arg2
+ movl 32(%esp), %edx // C arg4 -> syscall arg3
+ movl 36(%esp), %esi // C arg5 -> syscall arg4
+ movl 40(%esp), %edi // C arg6 -> syscall arg5
+ movl 44(%esp), %ebp // C arg7 -> syscall arg6
+
+ int $0x80
+
+ /* Restore registers */
+ popl %ebp
+ popl %edi
+ popl %esi
+ popl %ebx
+
+ cmpl $-4095, %eax
+ jae 1f
+ ret
+
+1:
+ negl %eax
+ movl %eax, linux_errno
+ movl $-1, %eax
+ ret
+
+ .size linux_syscall, . - linux_syscall
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/linux/linuxprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/linux/linuxprefix.S
new file mode 100644
index 00000000..398d3cb2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/linux/linuxprefix.S
@@ -0,0 +1,28 @@
+#include <linux/unistd.h>
+
+ .section ".text"
+ .code32
+ .globl _linux_start
+ .type _linux_start, @function
+
+_linux_start:
+ xorl %ebp, %ebp
+
+ popl %esi // save argc
+ movl %esp, %edi // save argv
+
+ andl $~15, %esp // 16-byte align the stack
+
+ pushl %edi // argv -> C arg2
+ pushl %esi // argc -> C arg1
+
+ call save_args
+
+ /* Our main doesn't use any arguments */
+ call main
+
+ movl %eax, %ebx // rc -> syscall arg1
+ movl $__NR_exit, %eax
+ int $0x80
+
+ .size _linux_start, . - _linux_start
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/nulltrap.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/nulltrap.c
new file mode 100644
index 00000000..3046fbec
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/nulltrap.c
@@ -0,0 +1,51 @@
+#include <stdint.h>
+#include <stdio.h>
+
+__attribute__ (( noreturn, section ( ".text.null_trap" ) ))
+void null_function_trap ( void ) {
+ void *stack;
+
+ /* 128 bytes of NOPs; the idea of this is that if something
+ * dereferences a NULL pointer and overwrites us, we at least
+ * have some chance of still getting to execute the printf()
+ * statement.
+ */
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+ __asm__ __volatile__ ( "nop ; nop ; nop ; nop" );
+
+ __asm__ __volatile__ ( "movl %%esp, %0" : "=r" ( stack ) );
+ printf ( "NULL method called from %p (stack %p)\n",
+ __builtin_return_address ( 0 ), stack );
+ DBG_HD ( stack, 256 );
+ while ( 1 ) {}
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/patch_cf.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/patch_cf.S
new file mode 100644
index 00000000..97a62f49
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/patch_cf.S
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 H. Peter Anvin <hpa@zytor.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .text
+ .arch i386
+ .code16
+
+/****************************************************************************
+ * Set/clear CF on the stack as appropriate, assumes stack is as it should
+ * be immediately before IRET
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+ .globl patch_cf
+patch_cf:
+ pushw %bp
+ movw %sp, %bp
+ setc 8(%bp) /* Set/reset CF; clears PF, AF, ZF, SF */
+ popw %bp
+ ret
+ .size patch_cf, . - patch_cf
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/pic8259.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/pic8259.c
new file mode 100644
index 00000000..0264c0c1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/pic8259.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/io.h>
+#include <pic8259.h>
+
+/** @file
+ *
+ * Minimal support for the 8259 Programmable Interrupt Controller
+ *
+ */
+
+/**
+ * Send non-specific EOI(s)
+ *
+ * @v irq IRQ number
+ *
+ * This seems to be inherently unsafe.
+ */
+static inline void send_nonspecific_eoi ( unsigned int irq ) {
+ DBG ( "Sending non-specific EOI for IRQ %d\n", irq );
+ if ( irq >= IRQ_PIC_CUTOFF ) {
+ outb ( ICR_EOI_NON_SPECIFIC, PIC2_ICR );
+ }
+ outb ( ICR_EOI_NON_SPECIFIC, PIC1_ICR );
+}
+
+/**
+ * Send specific EOI(s)
+ *
+ * @v irq IRQ number
+ */
+static inline void send_specific_eoi ( unsigned int irq ) {
+ DBG ( "Sending specific EOI for IRQ %d\n", irq );
+ if ( irq >= IRQ_PIC_CUTOFF ) {
+ outb ( ( ICR_EOI_SPECIFIC | ICR_VALUE ( CHAINED_IRQ ) ),
+ ICR_REG ( CHAINED_IRQ ) );
+ }
+ outb ( ( ICR_EOI_SPECIFIC | ICR_VALUE ( irq ) ), ICR_REG ( irq ) );
+}
+
+/**
+ * Send End-Of-Interrupt to the PIC
+ *
+ * @v irq IRQ number
+ */
+void send_eoi ( unsigned int irq ) {
+ send_specific_eoi ( irq );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/rdtsc_timer.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/rdtsc_timer.c
new file mode 100644
index 00000000..d2a8cc84
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/rdtsc_timer.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * RDTSC timer
+ *
+ */
+
+#include <assert.h>
+#include <ipxe/timer.h>
+#include <ipxe/timer2.h>
+
+/**
+ * Number of TSC ticks per microsecond
+ *
+ * This is calibrated on the first use of the timer.
+ */
+static unsigned long rdtsc_ticks_per_usec;
+
+/**
+ * Delay for a fixed number of microseconds
+ *
+ * @v usecs Number of microseconds for which to delay
+ */
+static void rdtsc_udelay ( unsigned long usecs ) {
+ unsigned long start;
+ unsigned long elapsed;
+
+ /* Sanity guard, since we may divide by this */
+ if ( ! usecs )
+ usecs = 1;
+
+ start = currticks();
+ if ( rdtsc_ticks_per_usec ) {
+ /* Already calibrated; busy-wait until done */
+ do {
+ elapsed = ( currticks() - start );
+ } while ( elapsed < ( usecs * rdtsc_ticks_per_usec ) );
+ } else {
+ /* Not yet calibrated; use timer2 and calibrate
+ * based on result.
+ */
+ timer2_udelay ( usecs );
+ elapsed = ( currticks() - start );
+ rdtsc_ticks_per_usec = ( elapsed / usecs );
+ DBG ( "RDTSC timer calibrated: %ld ticks in %ld usecs "
+ "(%ld MHz)\n", elapsed, usecs,
+ ( rdtsc_ticks_per_usec << TSC_SHIFT ) );
+ }
+}
+
+/**
+ * Get number of ticks per second
+ *
+ * @ret ticks_per_sec Number of ticks per second
+ */
+static unsigned long rdtsc_ticks_per_sec ( void ) {
+
+ /* Calibrate timer, if not already done */
+ if ( ! rdtsc_ticks_per_usec )
+ udelay ( 1 );
+
+ /* Sanity check */
+ assert ( rdtsc_ticks_per_usec != 0 );
+
+ return ( rdtsc_ticks_per_usec * 1000 * 1000 );
+}
+
+PROVIDE_TIMER ( rdtsc, udelay, rdtsc_udelay );
+PROVIDE_TIMER_INLINE ( rdtsc, currticks );
+PROVIDE_TIMER ( rdtsc, ticks_per_sec, rdtsc_ticks_per_sec );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/relocate.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/relocate.c
new file mode 100644
index 00000000..b9b02944
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/relocate.c
@@ -0,0 +1,136 @@
+#include <ipxe/io.h>
+#include <registers.h>
+
+/*
+ * Originally by Eric Biederman
+ *
+ * Heavily modified by Michael Brown
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * The linker passes in the symbol _max_align, which is the alignment
+ * that we must preserve, in bytes.
+ *
+ */
+extern char _max_align[];
+#define max_align ( ( unsigned int ) _max_align )
+
+/* Linker symbols */
+extern char _textdata[];
+extern char _etextdata[];
+
+/* within 1MB of 4GB is too close.
+ * MAX_ADDR is the maximum address we can easily do DMA to.
+ *
+ * Not sure where this constraint comes from, but kept it from Eric's
+ * old code - mcb30
+ */
+#define MAX_ADDR (0xfff00000UL)
+
+/**
+ * Relocate iPXE
+ *
+ * @v ix86 x86 register dump from prefix
+ * @ret ix86 x86 registers to return to prefix
+ *
+ * This finds a suitable location for iPXE near the top of 32-bit
+ * address space, and returns the physical address of the new location
+ * to the prefix in %edi.
+ */
+__asmcall void relocate ( struct i386_all_regs *ix86 ) {
+ struct memory_map memmap;
+ unsigned long start, end, size, padded_size, max;
+ unsigned long new_start, new_end;
+ unsigned i;
+
+ /* Get memory map and current location */
+ get_memmap ( &memmap );
+ start = virt_to_phys ( _textdata );
+ end = virt_to_phys ( _etextdata );
+ size = ( end - start );
+ padded_size = ( size + max_align - 1 );
+
+ DBG ( "Relocate: currently at [%lx,%lx)\n"
+ "...need %lx bytes for %d-byte alignment\n",
+ start, end, padded_size, max_align );
+
+ /* Determine maximum usable address */
+ max = MAX_ADDR;
+ if ( ix86->regs.ebp && ( ix86->regs.ebp < max ) ) {
+ max = ix86->regs.ebp;
+ DBG ( "Limiting relocation to [0,%lx)\n", max );
+ }
+
+ /* Walk through the memory map and find the highest address
+ * below 4GB that iPXE will fit into.
+ */
+ new_end = end;
+ for ( i = 0 ; i < memmap.count ; i++ ) {
+ struct memory_region *region = &memmap.regions[i];
+ unsigned long r_start, r_end;
+
+ DBG ( "Considering [%llx,%llx)\n", region->start, region->end);
+
+ /* Truncate block to maximum address. This will be
+ * less than 4GB, which means that we can get away
+ * with using just 32-bit arithmetic after this stage.
+ */
+ if ( region->start > max ) {
+ DBG ( "...starts after max=%lx\n", max );
+ continue;
+ }
+ r_start = region->start;
+ if ( region->end > max ) {
+ DBG ( "...end truncated to max=%lx\n", max );
+ r_end = max;
+ } else {
+ r_end = region->end;
+ }
+ DBG ( "...usable portion is [%lx,%lx)\n", r_start, r_end );
+
+ /* If we have rounded down r_end below r_ start, skip
+ * this block.
+ */
+ if ( r_end < r_start ) {
+ DBG ( "...truncated to negative size\n" );
+ continue;
+ }
+
+ /* Check that there is enough space to fit in iPXE */
+ if ( ( r_end - r_start ) < size ) {
+ DBG ( "...too small (need %lx bytes)\n", size );
+ continue;
+ }
+
+ /* If the start address of the iPXE we would
+ * place in this block is higher than the end address
+ * of the current highest block, use this block.
+ *
+ * Note that this avoids overlaps with the current
+ * iPXE, as well as choosing the highest of all viable
+ * blocks.
+ */
+ if ( ( r_end - size ) > new_end ) {
+ new_end = r_end;
+ DBG ( "...new best block found.\n" );
+ }
+ }
+
+ /* Calculate new location of iPXE, and align it to the
+ * required alignemnt.
+ */
+ new_start = new_end - padded_size;
+ new_start += ( start - new_start ) & ( max_align - 1 );
+ new_end = new_start + size;
+
+ DBG ( "Relocating from [%lx,%lx) to [%lx,%lx)\n",
+ start, end, new_start, new_end );
+
+ /* Let prefix know what to copy */
+ ix86->regs.esi = start;
+ ix86->regs.edi = new_start;
+ ix86->regs.ecx = size;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/runtime.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/runtime.c
new file mode 100644
index 00000000..fcfec060
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/runtime.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Command line and initrd passed to iPXE at runtime
+ *
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/init.h>
+#include <ipxe/image.h>
+#include <ipxe/script.h>
+#include <ipxe/umalloc.h>
+#include <realmode.h>
+
+/** Command line physical address
+ *
+ * This can be set by the prefix.
+ */
+uint32_t __bss16 ( cmdline_phys );
+#define cmdline_phys __use_data16 ( cmdline_phys )
+
+/** initrd physical address
+ *
+ * This can be set by the prefix.
+ */
+uint32_t __bss16 ( initrd_phys );
+#define initrd_phys __use_data16 ( initrd_phys )
+
+/** initrd length
+ *
+ * This can be set by the prefix.
+ */
+uint32_t __bss16 ( initrd_len );
+#define initrd_len __use_data16 ( initrd_len )
+
+/** Internal copy of the command line */
+static char *cmdline_copy;
+
+/** Free command line image */
+static void cmdline_image_free ( struct refcnt *refcnt ) {
+ struct image *image = container_of ( refcnt, struct image, refcnt );
+
+ DBGC ( image, "RUNTIME freeing command line\n" );
+ free ( cmdline_copy );
+}
+
+/** Embedded script representing the command line */
+static struct image cmdline_image = {
+ .refcnt = REF_INIT ( cmdline_image_free ),
+ .name = "<CMDLINE>",
+ .type = &script_image_type,
+};
+
+/** Colour for debug messages */
+#define colour &cmdline_image
+
+/**
+ * Strip unwanted cruft from command line
+ *
+ * @v cmdline Command line
+ * @v cruft Initial substring of cruft to strip
+ */
+static void cmdline_strip ( char *cmdline, const char *cruft ) {
+ char *strip;
+ char *strip_end;
+
+ /* Find unwanted cruft, if present */
+ if ( ! ( strip = strstr ( cmdline, cruft ) ) )
+ return;
+
+ /* Strip unwanted cruft */
+ strip_end = strchr ( strip, ' ' );
+ if ( strip_end ) {
+ *strip_end = '\0';
+ DBGC ( colour, "RUNTIME stripping \"%s\"\n", strip );
+ strcpy ( strip, ( strip_end + 1 ) );
+ } else {
+ DBGC ( colour, "RUNTIME stripping \"%s\"\n", strip );
+ *strip = '\0';
+ }
+}
+
+/**
+ * Initialise command line
+ *
+ * @ret rc Return status code
+ */
+static int cmdline_init ( void ) {
+ userptr_t cmdline_user;
+ char *cmdline;
+ size_t len;
+ int rc;
+
+ /* Do nothing if no command line was specified */
+ if ( ! cmdline_phys ) {
+ DBGC ( colour, "RUNTIME found no command line\n" );
+ return 0;
+ }
+ cmdline_user = phys_to_user ( cmdline_phys );
+ len = ( strlen_user ( cmdline_user, 0 ) + 1 /* NUL */ );
+
+ /* Allocate and copy command line */
+ cmdline_copy = malloc ( len );
+ if ( ! cmdline_copy ) {
+ DBGC ( colour, "RUNTIME could not allocate %zd bytes for "
+ "command line\n", len );
+ rc = -ENOMEM;
+ goto err_alloc_cmdline_copy;
+ }
+ cmdline = cmdline_copy;
+ copy_from_user ( cmdline, cmdline_user, 0, len );
+ DBGC ( colour, "RUNTIME found command line \"%s\" at %08x\n",
+ cmdline, cmdline_phys );
+
+ /* Mark command line as consumed */
+ cmdline_phys = 0;
+
+ /* Strip unwanted cruft from the command line */
+ cmdline_strip ( cmdline, "BOOT_IMAGE=" );
+ cmdline_strip ( cmdline, "initrd=" );
+ while ( isspace ( *cmdline ) )
+ cmdline++;
+ DBGC ( colour, "RUNTIME using command line \"%s\"\n", cmdline );
+
+ /* Prepare and register image */
+ cmdline_image.data = virt_to_user ( cmdline );
+ cmdline_image.len = strlen ( cmdline );
+ if ( cmdline_image.len ) {
+ if ( ( rc = register_image ( &cmdline_image ) ) != 0 ) {
+ DBGC ( colour, "RUNTIME could not register command "
+ "line: %s\n", strerror ( rc ) );
+ goto err_register_image;
+ }
+ }
+
+ /* Drop our reference to the image */
+ image_put ( &cmdline_image );
+
+ return 0;
+
+ err_register_image:
+ image_put ( &cmdline_image );
+ err_alloc_cmdline_copy:
+ return rc;
+}
+
+/**
+ * Initialise initrd
+ *
+ * @ret rc Return status code
+ */
+static int initrd_init ( void ) {
+ struct image *image;
+ int rc;
+
+ /* Do nothing if no initrd was specified */
+ if ( ! initrd_phys ) {
+ DBGC ( colour, "RUNTIME found no initrd\n" );
+ return 0;
+ }
+ if ( ! initrd_len ) {
+ DBGC ( colour, "RUNTIME found empty initrd\n" );
+ return 0;
+ }
+ DBGC ( colour, "RUNTIME found initrd at [%x,%x)\n",
+ initrd_phys, ( initrd_phys + initrd_len ) );
+
+ /* Allocate image */
+ image = alloc_image ( NULL );
+ if ( ! image ) {
+ DBGC ( colour, "RUNTIME could not allocate image for "
+ "initrd\n" );
+ rc = -ENOMEM;
+ goto err_alloc_image;
+ }
+ if ( ( rc = image_set_name ( image, "<INITRD>" ) ) != 0 ) {
+ DBGC ( colour, "RUNTIME could not set image name: %s\n",
+ strerror ( rc ) );
+ goto err_set_name;
+ }
+
+ /* Allocate and copy initrd content */
+ image->data = umalloc ( initrd_len );
+ if ( ! image->data ) {
+ DBGC ( colour, "RUNTIME could not allocate %d bytes for "
+ "initrd\n", initrd_len );
+ rc = -ENOMEM;
+ goto err_umalloc;
+ }
+ image->len = initrd_len;
+ memcpy_user ( image->data, 0, phys_to_user ( initrd_phys ), 0,
+ initrd_len );
+
+ /* Mark initrd as consumed */
+ initrd_phys = 0;
+
+ /* Register image */
+ if ( ( rc = register_image ( image ) ) != 0 ) {
+ DBGC ( colour, "RUNTIME could not register initrd: %s\n",
+ strerror ( rc ) );
+ goto err_register_image;
+ }
+
+ /* Drop our reference to the image */
+ image_put ( image );
+
+ return 0;
+
+ err_register_image:
+ err_umalloc:
+ err_set_name:
+ image_put ( image );
+ err_alloc_image:
+ return rc;
+}
+
+/**
+ * Initialise command line and initrd
+ *
+ */
+static void runtime_init ( void ) {
+ int rc;
+
+ /* Initialise command line */
+ if ( ( rc = cmdline_init() ) != 0 ) {
+ /* No way to report failure */
+ return;
+ }
+
+ /* Initialise initrd */
+ if ( ( rc = initrd_init() ) != 0 ) {
+ /* No way to report failure */
+ return;
+ }
+}
+
+/** Command line and initrd initialisation function */
+struct startup_fn runtime_startup_fn __startup_fn ( STARTUP_NORMAL ) = {
+ .startup = runtime_init,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/setjmp.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/setjmp.S
new file mode 100644
index 00000000..03727148
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/setjmp.S
@@ -0,0 +1,42 @@
+/* setjmp and longjmp. Use of these functions is deprecated. */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .text
+ .arch i386
+ .code32
+
+/**************************************************************************
+SETJMP - Save stack context for non-local goto
+**************************************************************************/
+ .globl setjmp
+setjmp:
+ movl 4(%esp),%ecx /* jmpbuf */
+ movl 0(%esp),%edx /* return address */
+ movl %edx,0(%ecx)
+ movl %ebx,4(%ecx)
+ movl %esp,8(%ecx)
+ movl %ebp,12(%ecx)
+ movl %esi,16(%ecx)
+ movl %edi,20(%ecx)
+ movl $0,%eax
+ ret
+
+/**************************************************************************
+LONGJMP - Non-local jump to a saved stack context
+**************************************************************************/
+ .globl longjmp
+longjmp:
+ movl 4(%esp),%edx /* jumpbuf */
+ movl 8(%esp),%eax /* result */
+ movl 0(%edx),%ecx
+ movl 4(%edx),%ebx
+ movl 8(%edx),%esp
+ movl 12(%edx),%ebp
+ movl 16(%edx),%esi
+ movl 20(%edx),%edi
+ cmpl $0,%eax
+ jne 1f
+ movl $1,%eax
+1: movl %ecx,0(%esp)
+ ret
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/stack.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/stack.S
new file mode 100644
index 00000000..737ec0ee
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/stack.S
@@ -0,0 +1,15 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .arch i386
+
+/****************************************************************************
+ * Internal stack
+ ****************************************************************************
+ */
+ .section ".stack", "aw", @nobits
+ .align 8
+ .globl _stack
+_stack:
+ .space 4096
+ .globl _estack
+_estack:
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/stack16.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/stack16.S
new file mode 100644
index 00000000..523f0288
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/stack16.S
@@ -0,0 +1,15 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .arch i386
+
+/****************************************************************************
+ * Internal stack
+ ****************************************************************************
+ */
+ .section ".stack16", "aw", @nobits
+ .align 8
+ .globl _stack16
+_stack16:
+ .space 4096
+ .globl _estack16
+_estack16:
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/timer2.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/timer2.c
new file mode 100644
index 00000000..a0d0cba9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/timer2.c
@@ -0,0 +1,96 @@
+/*
+ * arch/i386/core/i386_timer.c
+ *
+ * Use the "System Timer 2" to implement the udelay callback in
+ * the BIOS timer driver. Also used to calibrate the clock rate
+ * in the RTDSC timer driver.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <ipxe/timer2.h>
+#include <ipxe/io.h>
+
+/* Timers tick over at this rate */
+#define TIMER2_TICKS_PER_SEC 1193180U
+
+/* Parallel Peripheral Controller Port B */
+#define PPC_PORTB 0x61
+
+/* Meaning of the port bits */
+#define PPCB_T2OUT 0x20 /* Bit 5 */
+#define PPCB_SPKR 0x02 /* Bit 1 */
+#define PPCB_T2GATE 0x01 /* Bit 0 */
+
+/* Ports for the 8254 timer chip */
+#define TIMER2_PORT 0x42
+#define TIMER_MODE_PORT 0x43
+
+/* Meaning of the mode bits */
+#define TIMER0_SEL 0x00
+#define TIMER1_SEL 0x40
+#define TIMER2_SEL 0x80
+#define READBACK_SEL 0xC0
+
+#define LATCH_COUNT 0x00
+#define LOBYTE_ACCESS 0x10
+#define HIBYTE_ACCESS 0x20
+#define WORD_ACCESS 0x30
+
+#define MODE0 0x00
+#define MODE1 0x02
+#define MODE2 0x04
+#define MODE3 0x06
+#define MODE4 0x08
+#define MODE5 0x0A
+
+#define BINARY_COUNT 0x00
+#define BCD_COUNT 0x01
+
+static void load_timer2 ( unsigned int ticks ) {
+ /*
+ * Now let's take care of PPC channel 2
+ *
+ * Set the Gate high, program PPC channel 2 for mode 0,
+ * (interrupt on terminal count mode), binary count,
+ * load 5 * LATCH count, (LSB and MSB) to begin countdown.
+ *
+ * Note some implementations have a bug where the high bits byte
+ * of channel 2 is ignored.
+ */
+ /* Set up the timer gate, turn off the speaker */
+ /* Set the Gate high, disable speaker */
+ outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
+ /* binary, mode 0, LSB/MSB, Ch 2 */
+ outb(TIMER2_SEL|WORD_ACCESS|MODE0|BINARY_COUNT, TIMER_MODE_PORT);
+ /* LSB of ticks */
+ outb(ticks & 0xFF, TIMER2_PORT);
+ /* MSB of ticks */
+ outb(ticks >> 8, TIMER2_PORT);
+}
+
+static int timer2_running ( void ) {
+ return ((inb(PPC_PORTB) & PPCB_T2OUT) == 0);
+}
+
+void timer2_udelay ( unsigned long usecs ) {
+ load_timer2 ( ( usecs * TIMER2_TICKS_PER_SEC ) / ( 1000 * 1000 ) );
+ while (timer2_running()) {
+ /* Do nothing */
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/video_subr.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/video_subr.c
new file mode 100644
index 00000000..306c6d56
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/video_subr.c
@@ -0,0 +1,113 @@
+/*
+ *
+ * modified from linuxbios code
+ * by Cai Qiang <rimy2000@hotmail.com>
+ *
+ */
+
+#include "stddef.h"
+#include "string.h"
+#include <ipxe/io.h>
+#include <ipxe/console.h>
+#include <ipxe/init.h>
+#include "vga.h"
+#include <config/console.h>
+
+/* Set default console usage if applicable */
+#if ! ( defined ( CONSOLE_DIRECT_VGA ) && \
+ CONSOLE_EXPLICIT ( CONSOLE_DIRECT_VGA ) )
+#undef CONSOLE_DIRECT_VGA
+#define CONSOLE_DIRECT_VGA ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
+#endif
+
+struct console_driver vga_console __console_driver;
+
+static char *vidmem; /* The video buffer */
+static int video_line, video_col;
+
+#define VIDBUFFER 0xB8000
+
+static void memsetw(void *s, int c, unsigned int n)
+{
+ unsigned int i;
+ u16 *ss = (u16 *) s;
+
+ for (i = 0; i < n; i++) {
+ ss[i] = ( u16 ) c;
+ }
+}
+
+static void video_init(void)
+{
+ static int inited=0;
+
+ vidmem = (char *)phys_to_virt(VIDBUFFER);
+
+ if (!inited) {
+ video_line = 0;
+ video_col = 0;
+
+ memsetw(vidmem, VGA_ATTR_CLR_WHT, 2*1024); //
+
+ inited=1;
+ }
+}
+
+static void video_scroll(void)
+{
+ int i;
+
+ memcpy(vidmem, vidmem + COLS * 2, (LINES - 1) * COLS * 2);
+ for (i = (LINES - 1) * COLS * 2; i < LINES * COLS * 2; i += 2)
+ vidmem[i] = ' ';
+}
+
+static void vga_putc(int byte)
+{
+ if (byte == '\n') {
+ video_line++;
+ video_col = 0;
+
+ } else if (byte == '\r') {
+ video_col = 0;
+
+ } else if (byte == '\b') {
+ video_col--;
+
+ } else if (byte == '\t') {
+ video_col += 4;
+
+ } else if (byte == '\a') {
+ //beep
+ //beep(500);
+
+ } else {
+ vidmem[((video_col + (video_line *COLS)) * 2)] = byte;
+ vidmem[((video_col + (video_line *COLS)) * 2) +1] = VGA_ATTR_CLR_WHT;
+ video_col++;
+ }
+ if (video_col < 0) {
+ video_col = 0;
+ }
+ if (video_col >= COLS) {
+ video_line++;
+ video_col = 0;
+ }
+ if (video_line >= LINES) {
+ video_scroll();
+ video_line--;
+ }
+ // move the cursor
+ write_crtc((video_col + (video_line *COLS)) >> 8, CRTC_CURSOR_HI);
+ write_crtc((video_col + (video_line *COLS)) & 0x0ff, CRTC_CURSOR_LO);
+}
+
+struct console_driver vga_console __console_driver = {
+ .putchar = vga_putc,
+ .disabled = 1,
+ .usage = CONSOLE_DIRECT_VGA,
+};
+
+struct init_fn video_init_fn __init_fn ( INIT_EARLY ) = {
+ .initialise = video_init,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/virtaddr.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/virtaddr.S
new file mode 100644
index 00000000..aae1e1ed
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/virtaddr.S
@@ -0,0 +1,103 @@
+/*
+ * Functions to support the virtual addressing method of relocation
+ * that Etherboot uses.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#include "librm.h"
+
+ .arch i386
+ .text
+ .code32
+
+/****************************************************************************
+ * _virt_to_phys (virtual addressing)
+ *
+ * Switch from virtual to flat physical addresses. %esp is adjusted
+ * to a physical value. Segment registers are set to flat physical
+ * selectors. All other registers are preserved. Flags are
+ * preserved.
+ *
+ * Parameters: none
+ * Returns: none
+ ****************************************************************************
+ */
+ .globl _virt_to_phys
+_virt_to_phys:
+ /* Preserve registers and flags */
+ pushfl
+ pushl %eax
+ pushl %ebp
+
+ /* Change return address to a physical address */
+ movl virt_offset, %ebp
+ addl %ebp, 12(%esp)
+
+ /* Switch to physical code segment */
+ pushl $PHYSICAL_CS
+ leal 1f(%ebp), %eax
+ pushl %eax
+ lret
+1:
+ /* Reload other segment registers and adjust %esp */
+ movl $PHYSICAL_DS, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %fs
+ movl %eax, %gs
+ movl %eax, %ss
+ addl %ebp, %esp
+
+ /* Restore registers and flags, and return */
+ popl %ebp
+ popl %eax
+ popfl
+ ret
+
+/****************************************************************************
+ * _phys_to_virt (flat physical addressing)
+ *
+ * Switch from flat physical to virtual addresses. %esp is adjusted
+ * to a virtual value. Segment registers are set to virtual
+ * selectors. All other registers are preserved. Flags are
+ * preserved.
+ *
+ * Note that this depends on the GDT already being correctly set up
+ * (e.g. by a call to run_here()).
+ *
+ * Parameters: none
+ * Returns: none
+ ****************************************************************************
+ */
+ .globl _phys_to_virt
+_phys_to_virt:
+ /* Preserve registers and flags */
+ pushfl
+ pushl %eax
+ pushl %ebp
+
+ /* Switch to virtual code segment */
+ ljmp $VIRTUAL_CS, $1f
+1:
+ /* Reload data segment registers */
+ movl $VIRTUAL_DS, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* Reload stack segment and adjust %esp */
+ movl virt_offset, %ebp
+ movl %eax, %ss
+ subl %ebp, %esp
+
+ /* Change the return address to a virtual address */
+ subl %ebp, 12(%esp)
+
+ /* Restore registers and flags, and return */
+ popl %ebp
+ popl %eax
+ popfl
+ ret
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/core/x86_io.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/x86_io.c
new file mode 100644
index 00000000..2fba0680
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/core/x86_io.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/io.h>
+#include <ipxe/x86_io.h>
+
+/** @file
+ *
+ * iPXE I/O API for x86
+ *
+ */
+
+/**
+ * Read 64-bit qword from memory-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ *
+ * This routine uses MMX instructions.
+ */
+static uint64_t x86_readq ( volatile uint64_t *io_addr ) {
+ uint64_t data;
+ __asm__ __volatile__ ( "pushl %%edx\n\t"
+ "pushl %%eax\n\t"
+ "movq (%1), %%mm0\n\t"
+ "movq %%mm0, (%%esp)\n\t"
+ "popl %%eax\n\t"
+ "popl %%edx\n\t"
+ "emms\n\t"
+ : "=A" ( data ) : "r" ( io_addr ) );
+ return data;
+}
+
+/**
+ * Write 64-bit qword to memory-mapped device
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ *
+ * This routine uses MMX instructions.
+ */
+static void x86_writeq ( uint64_t data, volatile uint64_t *io_addr ) {
+ __asm__ __volatile__ ( "pushl %%edx\n\t"
+ "pushl %%eax\n\t"
+ "movq (%%esp), %%mm0\n\t"
+ "movq %%mm0, (%1)\n\t"
+ "popl %%eax\n\t"
+ "popl %%edx\n\t"
+ "emms\n\t"
+ : : "A" ( data ), "r" ( io_addr ) );
+}
+
+PROVIDE_IOAPI_INLINE ( x86, phys_to_bus );
+PROVIDE_IOAPI_INLINE ( x86, bus_to_phys );
+PROVIDE_IOAPI_INLINE ( x86, ioremap );
+PROVIDE_IOAPI_INLINE ( x86, iounmap );
+PROVIDE_IOAPI_INLINE ( x86, io_to_bus );
+PROVIDE_IOAPI_INLINE ( x86, readb );
+PROVIDE_IOAPI_INLINE ( x86, readw );
+PROVIDE_IOAPI_INLINE ( x86, readl );
+PROVIDE_IOAPI ( x86, readq, x86_readq );
+PROVIDE_IOAPI_INLINE ( x86, writeb );
+PROVIDE_IOAPI_INLINE ( x86, writew );
+PROVIDE_IOAPI_INLINE ( x86, writel );
+PROVIDE_IOAPI ( x86, writeq, x86_writeq );
+PROVIDE_IOAPI_INLINE ( x86, inb );
+PROVIDE_IOAPI_INLINE ( x86, inw );
+PROVIDE_IOAPI_INLINE ( x86, inl );
+PROVIDE_IOAPI_INLINE ( x86, outb );
+PROVIDE_IOAPI_INLINE ( x86, outw );
+PROVIDE_IOAPI_INLINE ( x86, outl );
+PROVIDE_IOAPI_INLINE ( x86, insb );
+PROVIDE_IOAPI_INLINE ( x86, insw );
+PROVIDE_IOAPI_INLINE ( x86, insl );
+PROVIDE_IOAPI_INLINE ( x86, outsb );
+PROVIDE_IOAPI_INLINE ( x86, outsw );
+PROVIDE_IOAPI_INLINE ( x86, outsl );
+PROVIDE_IOAPI_INLINE ( x86, iodelay );
+PROVIDE_IOAPI_INLINE ( x86, mb );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undi.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undi.c
new file mode 100644
index 00000000..ad655620
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undi.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ipxe/pci.h>
+#include <undi.h>
+#include <undirom.h>
+#include <undiload.h>
+#include <undinet.h>
+#include <undipreload.h>
+
+/** @file
+ *
+ * UNDI PCI driver
+ *
+ */
+
+/**
+ * Find UNDI ROM for PCI device
+ *
+ * @v pci PCI device
+ * @ret undirom UNDI ROM, or NULL
+ *
+ * Try to find a driver for this device. Try an exact match on the
+ * ROM address first, then fall back to a vendor/device ID match only
+ */
+static struct undi_rom * undipci_find_rom ( struct pci_device *pci ) {
+ struct undi_rom *undirom;
+ unsigned long rombase;
+
+ rombase = pci_bar_start ( pci, PCI_ROM_ADDRESS );
+ undirom = undirom_find_pci ( pci->vendor, pci->device, rombase );
+ if ( ! undirom )
+ undirom = undirom_find_pci ( pci->vendor, pci->device, 0 );
+ return undirom;
+}
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @v id PCI ID
+ * @ret rc Return status code
+ */
+static int undipci_probe ( struct pci_device *pci ) {
+ struct undi_device *undi;
+ struct undi_rom *undirom;
+ int rc;
+
+ /* Ignore non-network devices */
+ if ( PCI_BASE_CLASS ( pci->class ) != PCI_BASE_CLASS_NETWORK )
+ return -ENOTTY;
+
+ /* Allocate UNDI device structure */
+ undi = zalloc ( sizeof ( *undi ) );
+ if ( ! undi )
+ return -ENOMEM;
+ pci_set_drvdata ( pci, undi );
+
+ /* Find/create our pixie */
+ if ( preloaded_undi.pci_busdevfn == pci->busdevfn ) {
+ /* Claim preloaded UNDI device */
+ DBGC ( undi, "UNDI %p using preloaded UNDI device\n", undi );
+ memcpy ( undi, &preloaded_undi, sizeof ( *undi ) );
+ memset ( &preloaded_undi, 0, sizeof ( preloaded_undi ) );
+ } else {
+ /* Find UNDI ROM for PCI device */
+ if ( ! ( undirom = undipci_find_rom ( pci ) ) ) {
+ rc = -ENODEV;
+ goto err_find_rom;
+ }
+
+ /* Call UNDI ROM loader to create pixie */
+ if ( ( rc = undi_load_pci ( undi, undirom,
+ pci->busdevfn ) ) != 0 ) {
+ goto err_load_pci;
+ }
+ }
+
+ /* Add to device hierarchy */
+ snprintf ( undi->dev.name, sizeof ( undi->dev.name ),
+ "UNDI-%s", pci->dev.name );
+ memcpy ( &undi->dev.desc, &pci->dev.desc, sizeof ( undi->dev.desc ) );
+ undi->dev.parent = &pci->dev;
+ INIT_LIST_HEAD ( &undi->dev.children );
+ list_add ( &undi->dev.siblings, &pci->dev.children );
+
+ /* Create network device */
+ if ( ( rc = undinet_probe ( undi ) ) != 0 )
+ goto err_undinet_probe;
+
+ return 0;
+
+ err_undinet_probe:
+ undi_unload ( undi );
+ list_del ( &undi->dev.siblings );
+ err_find_rom:
+ err_load_pci:
+ free ( undi );
+ pci_set_drvdata ( pci, NULL );
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void undipci_remove ( struct pci_device *pci ) {
+ struct undi_device *undi = pci_get_drvdata ( pci );
+
+ undinet_remove ( undi );
+ undi_unload ( undi );
+ list_del ( &undi->dev.siblings );
+ free ( undi );
+ pci_set_drvdata ( pci, NULL );
+}
+
+static struct pci_device_id undipci_nics[] = {
+PCI_ROM ( 0xffff, 0xffff, "undipci", "UNDI (PCI)", 0 ),
+};
+
+struct pci_driver undipci_driver __pci_driver_fallback = {
+ .ids = undipci_nics,
+ .id_count = ( sizeof ( undipci_nics ) / sizeof ( undipci_nics[0] ) ),
+ .probe = undipci_probe,
+ .remove = undipci_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undiisr.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undiisr.S
new file mode 100644
index 00000000..b27effe1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undiisr.S
@@ -0,0 +1,87 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#define PXENV_UNDI_ISR 0x0014
+#define PXENV_UNDI_ISR_IN_START 1
+#define PXENV_UNDI_ISR_OUT_OURS 0
+#define PXENV_UNDI_ISR_OUT_NOT_OURS 1
+
+#define IRQ_PIC_CUTOFF 8
+#define ICR_EOI_NON_SPECIFIC 0x20
+#define PIC1_ICR 0x20
+#define PIC2_ICR 0xa0
+
+ .text
+ .arch i386
+ .code16
+
+ .section ".text16", "ax", @progbits
+ .globl undiisr
+undiisr:
+
+ /* Preserve registers */
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+ pushfl
+ pushal
+
+ /* Set up our segment registers */
+ movw %cs:rm_ds, %ax
+ movw %ax, %ds
+
+ /* Check that we have an UNDI entry point */
+ cmpw $0, pxeparent_entry_point
+ je chain
+
+ /* Issue UNDI API call */
+ movw %ax, %es
+ movw $undinet_params, %di
+ movw $PXENV_UNDI_ISR, %bx
+ movw $PXENV_UNDI_ISR_IN_START, funcflag
+ pushw %es
+ pushw %di
+ pushw %bx
+ lcall *pxeparent_entry_point
+ cli /* Just in case */
+ addw $6, %sp
+ cmpw $PXENV_UNDI_ISR_OUT_OURS, funcflag
+ jne eoi
+
+trig: /* Record interrupt occurence */
+ incb undiisr_trigger_count
+
+eoi: /* Send EOI */
+ movb $ICR_EOI_NON_SPECIFIC, %al
+ cmpb $IRQ_PIC_CUTOFF, undiisr_irq
+ jb 1f
+ outb %al, $PIC2_ICR
+1: outb %al, $PIC1_ICR
+ jmp exit
+
+chain: /* Chain to next handler */
+ pushfw
+ lcall *undiisr_next_handler
+
+exit: /* Restore registers and return */
+ cli
+ popal
+ movzwl %sp, %esp
+ addr32 movl -20(%esp), %esp /* %esp isn't restored by popal */
+ popfl
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ iret
+
+ .section ".data16", "aw", @progbits
+undinet_params:
+status: .word 0
+funcflag: .word 0
+bufferlength: .word 0
+framelength: .word 0
+frameheaderlength: .word 0
+frame: .word 0, 0
+prottype: .byte 0
+pkttype: .byte 0
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undiload.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undiload.c
new file mode 100644
index 00000000..7746d1c5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undiload.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pxe.h>
+#include <realmode.h>
+#include <bios.h>
+#include <pnpbios.h>
+#include <basemem.h>
+#include <ipxe/pci.h>
+#include <undi.h>
+#include <undirom.h>
+#include <undiload.h>
+
+/** @file
+ *
+ * UNDI load/unload
+ *
+ */
+
+/** Parameter block for calling UNDI loader */
+static struct s_UNDI_LOADER __bss16 ( undi_loader );
+#define undi_loader __use_data16 ( undi_loader )
+
+/** UNDI loader entry point */
+static SEGOFF16_t __bss16 ( undi_loader_entry );
+#define undi_loader_entry __use_data16 ( undi_loader_entry )
+
+/**
+ * Call UNDI loader to create a pixie
+ *
+ * @v undi UNDI device
+ * @v undirom UNDI ROM
+ * @ret rc Return status code
+ */
+int undi_load ( struct undi_device *undi, struct undi_rom *undirom ) {
+ struct s_PXE ppxe;
+ unsigned int fbms_seg;
+ uint16_t exit;
+ int rc;
+
+ /* Only one UNDI instance may be loaded at any given time */
+ if ( undi_loader_entry.segment ) {
+ DBG ( "UNDI %p cannot load multiple instances\n", undi );
+ return -EBUSY;
+ }
+
+ /* Set up START_UNDI parameters */
+ memset ( &undi_loader, 0, sizeof ( undi_loader ) );
+ undi_loader.AX = undi->pci_busdevfn;
+ undi_loader.BX = undi->isapnp_csn;
+ undi_loader.DX = undi->isapnp_read_port;
+ undi_loader.ES = BIOS_SEG;
+ undi_loader.DI = find_pnp_bios();
+
+ /* Allocate base memory for PXE stack */
+ undi->restore_fbms = get_fbms();
+ fbms_seg = ( undi->restore_fbms << 6 );
+ fbms_seg -= ( ( undirom->code_size + 0x0f ) >> 4 );
+ undi_loader.UNDI_CS = fbms_seg;
+ fbms_seg -= ( ( undirom->data_size + 0x0f ) >> 4 );
+ undi_loader.UNDI_DS = fbms_seg;
+
+ /* Debug info */
+ DBGC ( undi, "UNDI %p loading UNDI ROM %p to CS %04x DS %04x for ",
+ undi, undirom, undi_loader.UNDI_CS, undi_loader.UNDI_DS );
+ if ( undi->pci_busdevfn != UNDI_NO_PCI_BUSDEVFN ) {
+ unsigned int bus = ( undi->pci_busdevfn >> 8 );
+ unsigned int devfn = ( undi->pci_busdevfn & 0xff );
+ DBGC ( undi, "PCI %02x:%02x.%x\n",
+ bus, PCI_SLOT ( devfn ), PCI_FUNC ( devfn ) );
+ }
+ if ( undi->isapnp_csn != UNDI_NO_ISAPNP_CSN ) {
+ DBGC ( undi, "ISAPnP(%04x) CSN %04x\n",
+ undi->isapnp_read_port, undi->isapnp_csn );
+ }
+
+ /* Call loader */
+ undi_loader_entry = undirom->loader_entry;
+ __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
+ "pushw %%ds\n\t"
+ "pushw %%ax\n\t"
+ "lcall *undi_loader_entry\n\t"
+ "popl %%ebp\n\t" /* discard */
+ "popl %%ebp\n\t" /* gcc bug */ )
+ : "=a" ( exit )
+ : "a" ( __from_data16 ( &undi_loader ) )
+ : "ebx", "ecx", "edx", "esi", "edi" );
+
+ if ( exit != PXENV_EXIT_SUCCESS ) {
+ /* Clear entry point */
+ memset ( &undi_loader_entry, 0, sizeof ( undi_loader_entry ) );
+
+ rc = -undi_loader.Status;
+ if ( rc == 0 ) /* Paranoia */
+ rc = -EIO;
+ DBGC ( undi, "UNDI %p loader failed: %s\n",
+ undi, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Populate PXE device structure */
+ undi->pxenv = undi_loader.PXENVptr;
+ undi->ppxe = undi_loader.PXEptr;
+ copy_from_real ( &ppxe, undi->ppxe.segment, undi->ppxe.offset,
+ sizeof ( ppxe ) );
+ undi->entry = ppxe.EntryPointSP;
+ DBGC ( undi, "UNDI %p loaded PXENV+ %04x:%04x !PXE %04x:%04x "
+ "entry %04x:%04x\n", undi, undi->pxenv.segment,
+ undi->pxenv.offset, undi->ppxe.segment, undi->ppxe.offset,
+ undi->entry.segment, undi->entry.offset );
+
+ /* Update free base memory counter */
+ undi->fbms = ( fbms_seg >> 6 );
+ set_fbms ( undi->fbms );
+ DBGC ( undi, "UNDI %p using [%d,%d) kB of base memory\n",
+ undi, undi->fbms, undi->restore_fbms );
+
+ return 0;
+}
+
+/**
+ * Unload a pixie
+ *
+ * @v undi UNDI device
+ * @ret rc Return status code
+ *
+ * Erases the PXENV+ and !PXE signatures, and frees the used base
+ * memory (if possible).
+ */
+int undi_unload ( struct undi_device *undi ) {
+ static uint32_t dead = 0xdeaddead;
+
+ DBGC ( undi, "UNDI %p unloading\n", undi );
+
+ /* Clear entry point */
+ memset ( &undi_loader_entry, 0, sizeof ( undi_loader_entry ) );
+
+ /* Erase signatures */
+ if ( undi->pxenv.segment )
+ put_real ( dead, undi->pxenv.segment, undi->pxenv.offset );
+ if ( undi->ppxe.segment )
+ put_real ( dead, undi->ppxe.segment, undi->ppxe.offset );
+
+ /* Free base memory, if possible */
+ if ( undi->fbms == get_fbms() ) {
+ DBGC ( undi, "UNDI %p freeing [%d,%d) kB of base memory\n",
+ undi, undi->fbms, undi->restore_fbms );
+ set_fbms ( undi->restore_fbms );
+ return 0;
+ } else {
+ DBGC ( undi, "UNDI %p leaking [%d,%d) kB of base memory\n",
+ undi, undi->fbms, undi->restore_fbms );
+ return -EBUSY;
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undinet.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undinet.c
new file mode 100644
index 00000000..19014415
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undinet.c
@@ -0,0 +1,722 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <pxe.h>
+#include <realmode.h>
+#include <pic8259.h>
+#include <biosint.h>
+#include <pnpbios.h>
+#include <basemem_packet.h>
+#include <ipxe/io.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <undi.h>
+#include <undinet.h>
+#include <pxeparent.h>
+
+/** @file
+ *
+ * UNDI network device driver
+ *
+ */
+
+/** An UNDI NIC */
+struct undi_nic {
+ /** Device supports IRQs */
+ int irq_supported;
+ /** Assigned IRQ number */
+ unsigned int irq;
+ /** Currently processing ISR */
+ int isr_processing;
+ /** Bug workarounds */
+ int hacks;
+};
+
+/**
+ * @defgroup undi_hacks UNDI workarounds
+ * @{
+ */
+
+/** Work around Etherboot 5.4 bugs */
+#define UNDI_HACK_EB54 0x0001
+
+/** @} */
+
+/** Maximum number of times to retry PXENV_UNDI_INITIALIZE */
+#define UNDI_INITIALIZE_RETRY_MAX 10
+
+/** Delay between retries of PXENV_UNDI_INITIALIZE */
+#define UNDI_INITIALIZE_RETRY_DELAY_MS 200
+
+static void undinet_close ( struct net_device *netdev );
+
+/** Address of UNDI entry point */
+static SEGOFF16_t undinet_entry;
+
+/*****************************************************************************
+ *
+ * UNDI interrupt service routine
+ *
+ *****************************************************************************
+ */
+
+/**
+ * UNDI interrupt service routine
+ *
+ * The UNDI ISR increments a counter (@c trigger_count) and exits.
+ */
+extern void undiisr ( void );
+
+/** IRQ number */
+uint8_t __data16 ( undiisr_irq );
+#define undiisr_irq __use_data16 ( undiisr_irq )
+
+/** IRQ chain vector */
+struct segoff __data16 ( undiisr_next_handler );
+#define undiisr_next_handler __use_data16 ( undiisr_next_handler )
+
+/** IRQ trigger count */
+volatile uint8_t __data16 ( undiisr_trigger_count ) = 0;
+#define undiisr_trigger_count __use_data16 ( undiisr_trigger_count )
+
+/** Last observed trigger count */
+static unsigned int last_trigger_count = 0;
+
+/**
+ * Hook UNDI interrupt service routine
+ *
+ * @v irq IRQ number
+ */
+static void undinet_hook_isr ( unsigned int irq ) {
+
+ assert ( irq <= IRQ_MAX );
+ assert ( undiisr_irq == 0 );
+
+ undiisr_irq = irq;
+ hook_bios_interrupt ( IRQ_INT ( irq ),
+ ( ( unsigned int ) undiisr ),
+ &undiisr_next_handler );
+}
+
+/**
+ * Unhook UNDI interrupt service routine
+ *
+ * @v irq IRQ number
+ */
+static void undinet_unhook_isr ( unsigned int irq ) {
+
+ assert ( irq <= IRQ_MAX );
+
+ unhook_bios_interrupt ( IRQ_INT ( irq ),
+ ( ( unsigned int ) undiisr ),
+ &undiisr_next_handler );
+ undiisr_irq = 0;
+}
+
+/**
+ * Test to see if UNDI ISR has been triggered
+ *
+ * @ret triggered ISR has been triggered since last check
+ */
+static int undinet_isr_triggered ( void ) {
+ unsigned int this_trigger_count;
+
+ /* Read trigger_count. Do this only once; it is volatile */
+ this_trigger_count = undiisr_trigger_count;
+
+ if ( this_trigger_count == last_trigger_count ) {
+ /* Not triggered */
+ return 0;
+ } else {
+ /* Triggered */
+ last_trigger_count = this_trigger_count;
+ return 1;
+ }
+}
+
+/*****************************************************************************
+ *
+ * UNDI network device interface
+ *
+ *****************************************************************************
+ */
+
+/** UNDI transmit buffer descriptor */
+static struct s_PXENV_UNDI_TBD __data16 ( undinet_tbd );
+#define undinet_tbd __use_data16 ( undinet_tbd )
+
+/** UNDI transmit destination address */
+static uint8_t __data16_array ( undinet_destaddr, [ETH_ALEN] );
+#define undinet_destaddr __use_data16 ( undinet_destaddr )
+
+/**
+ * Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int undinet_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct undi_nic *undinic = netdev->priv;
+ struct s_PXENV_UNDI_TRANSMIT undi_transmit;
+ const void *ll_dest;
+ const void *ll_source;
+ uint16_t net_proto;
+ unsigned int flags;
+ uint8_t protocol;
+ size_t len;
+ int rc;
+
+ /* Technically, we ought to make sure that the previous
+ * transmission has completed before we re-use the buffer.
+ * However, many PXE stacks (including at least some Intel PXE
+ * stacks and Etherboot 5.4) fail to generate TX completions.
+ * In practice this won't be a problem, since our TX datapath
+ * has a very low packet volume and we can get away with
+ * assuming that a TX will be complete by the time we want to
+ * transmit the next packet.
+ */
+
+ /* Some PXE stacks are unable to cope with P_UNKNOWN, and will
+ * always try to prepend a link-layer header. Work around
+ * these stacks by stripping the existing link-layer header
+ * and allowing the PXE stack to (re)construct the link-layer
+ * header itself.
+ */
+ if ( ( rc = eth_pull ( netdev, iobuf, &ll_dest, &ll_source,
+ &net_proto, &flags ) ) != 0 ) {
+ DBGC ( undinic, "UNDINIC %p could not strip Ethernet header: "
+ "%s\n", undinic, strerror ( rc ) );
+ return rc;
+ }
+ memcpy ( undinet_destaddr, ll_dest, sizeof ( undinet_destaddr ) );
+ switch ( net_proto ) {
+ case htons ( ETH_P_IP ) :
+ protocol = P_IP;
+ break;
+ case htons ( ETH_P_ARP ) :
+ protocol = P_ARP;
+ break;
+ case htons ( ETH_P_RARP ) :
+ protocol = P_RARP;
+ break;
+ default:
+ /* Unknown protocol; restore the original link-layer header */
+ iob_push ( iobuf, sizeof ( struct ethhdr ) );
+ protocol = P_UNKNOWN;
+ break;
+ }
+
+ /* Copy packet to UNDI I/O buffer */
+ len = iob_len ( iobuf );
+ if ( len > sizeof ( basemem_packet ) )
+ len = sizeof ( basemem_packet );
+ memcpy ( &basemem_packet, iobuf->data, len );
+
+ /* Create PXENV_UNDI_TRANSMIT data structure */
+ memset ( &undi_transmit, 0, sizeof ( undi_transmit ) );
+ undi_transmit.Protocol = protocol;
+ undi_transmit.XmitFlag = ( ( flags & LL_BROADCAST ) ?
+ XMT_BROADCAST : XMT_DESTADDR );
+ undi_transmit.DestAddr.segment = rm_ds;
+ undi_transmit.DestAddr.offset = __from_data16 ( &undinet_destaddr );
+ undi_transmit.TBD.segment = rm_ds;
+ undi_transmit.TBD.offset = __from_data16 ( &undinet_tbd );
+
+ /* Create PXENV_UNDI_TBD data structure */
+ undinet_tbd.ImmedLength = len;
+ undinet_tbd.Xmit.segment = rm_ds;
+ undinet_tbd.Xmit.offset = __from_data16 ( basemem_packet );
+
+ /* Issue PXE API call */
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_TRANSMIT,
+ &undi_transmit,
+ sizeof ( undi_transmit ) ) ) != 0 )
+ goto done;
+
+ /* Free I/O buffer */
+ netdev_tx_complete ( netdev, iobuf );
+
+ done:
+ return rc;
+}
+
+/**
+ * Poll for received packets
+ *
+ * @v netdev Network device
+ *
+ * Fun, fun, fun. UNDI drivers don't use polling; they use
+ * interrupts. We therefore cheat and pretend that an interrupt has
+ * occurred every time undinet_poll() is called. This isn't too much
+ * of a hack; PCI devices share IRQs and so the first thing that a
+ * proper ISR should do is call PXENV_UNDI_ISR to determine whether or
+ * not the UNDI NIC generated the interrupt; there is no harm done by
+ * spurious calls to PXENV_UNDI_ISR. Similarly, we wouldn't be
+ * handling them any more rapidly than the usual rate of
+ * undinet_poll() being called even if we did implement a full ISR.
+ * So it should work. Ha!
+ *
+ * Addendum (21/10/03). Some cards don't play nicely with this trick,
+ * so instead of doing it the easy way we have to go to all the hassle
+ * of installing a genuine interrupt service routine and dealing with
+ * the wonderful 8259 Programmable Interrupt Controller. Joy.
+ *
+ * Addendum (10/07/07). When doing things such as iSCSI boot, in
+ * which we have to co-operate with a running OS, we can't get away
+ * with the "ISR-just-increments-a-counter-and-returns" trick at all,
+ * because it involves tying up the PIC for far too long, and other
+ * interrupt-dependent components (e.g. local disks) start breaking.
+ * We therefore implement a "proper" ISR which calls PXENV_UNDI_ISR
+ * from within interrupt context in order to deassert the device
+ * interrupt, and sends EOI if applicable.
+ */
+static void undinet_poll ( struct net_device *netdev ) {
+ struct undi_nic *undinic = netdev->priv;
+ struct s_PXENV_UNDI_ISR undi_isr;
+ struct io_buffer *iobuf = NULL;
+ size_t len;
+ size_t frag_len;
+ size_t max_frag_len;
+ int rc;
+
+ if ( ! undinic->isr_processing ) {
+ /* Allow interrupt to occur. Do this even if
+ * interrupts are not known to be supported, since
+ * some cards erroneously report that they do not
+ * support interrupts.
+ */
+ if ( ! undinet_isr_triggered() ) {
+ /* Allow interrupt to occur */
+ __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "cli\n\t" ) : : );
+
+ /* If interrupts are known to be supported,
+ * then do nothing on this poll; wait for the
+ * interrupt to be triggered.
+ */
+ if ( undinic->irq_supported )
+ return;
+ }
+
+ /* Start ISR processing */
+ undinic->isr_processing = 1;
+ undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
+ } else {
+ /* Continue ISR processing */
+ undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
+ }
+
+ /* Run through the ISR loop */
+ while ( 1 ) {
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_ISR,
+ &undi_isr,
+ sizeof ( undi_isr ) ) ) != 0 )
+ break;
+ switch ( undi_isr.FuncFlag ) {
+ case PXENV_UNDI_ISR_OUT_TRANSMIT:
+ /* We don't care about transmit completions */
+ break;
+ case PXENV_UNDI_ISR_OUT_RECEIVE:
+ /* Packet fragment received */
+ len = undi_isr.FrameLength;
+ frag_len = undi_isr.BufferLength;
+ if ( ( len == 0 ) || ( len < frag_len ) ) {
+ /* Don't laugh. VMWare does it. */
+ DBGC ( undinic, "UNDINIC %p reported insane "
+ "fragment (%zd of %zd bytes)\n",
+ undinic, frag_len, len );
+ netdev_rx_err ( netdev, NULL, -EINVAL );
+ break;
+ }
+ if ( ! iobuf )
+ iobuf = alloc_iob ( len );
+ if ( ! iobuf ) {
+ DBGC ( undinic, "UNDINIC %p could not "
+ "allocate %zd bytes for RX buffer\n",
+ undinic, len );
+ /* Fragment will be dropped */
+ netdev_rx_err ( netdev, NULL, -ENOMEM );
+ goto done;
+ }
+ max_frag_len = iob_tailroom ( iobuf );
+ if ( frag_len > max_frag_len ) {
+ DBGC ( undinic, "UNDINIC %p fragment too big "
+ "(%zd+%zd does not fit into %zd)\n",
+ undinic, iob_len ( iobuf ), frag_len,
+ ( iob_len ( iobuf ) + max_frag_len ) );
+ frag_len = max_frag_len;
+ }
+ copy_from_real ( iob_put ( iobuf, frag_len ),
+ undi_isr.Frame.segment,
+ undi_isr.Frame.offset, frag_len );
+ if ( iob_len ( iobuf ) == len ) {
+ /* Whole packet received; deliver it */
+ netdev_rx ( netdev, iob_disown ( iobuf ) );
+ /* Etherboot 5.4 fails to return all packets
+ * under mild load; pretend it retriggered.
+ */
+ if ( undinic->hacks & UNDI_HACK_EB54 )
+ --last_trigger_count;
+ }
+ break;
+ case PXENV_UNDI_ISR_OUT_DONE:
+ /* Processing complete */
+ undinic->isr_processing = 0;
+ goto done;
+ default:
+ /* Should never happen. VMWare does it routinely. */
+ DBGC ( undinic, "UNDINIC %p ISR returned invalid "
+ "FuncFlag %04x\n", undinic, undi_isr.FuncFlag );
+ undinic->isr_processing = 0;
+ goto done;
+ }
+ undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
+ }
+
+ done:
+ if ( iobuf ) {
+ DBGC ( undinic, "UNDINIC %p returned incomplete packet "
+ "(%zd of %zd)\n", undinic, iob_len ( iobuf ),
+ ( iob_len ( iobuf ) + iob_tailroom ( iobuf ) ) );
+ netdev_rx_err ( netdev, iobuf, -EINVAL );
+ }
+}
+
+/**
+ * Open NIC
+ *
+ * @v netdev Net device
+ * @ret rc Return status code
+ */
+static int undinet_open ( struct net_device *netdev ) {
+ struct undi_nic *undinic = netdev->priv;
+ struct s_PXENV_UNDI_SET_STATION_ADDRESS undi_set_address;
+ struct s_PXENV_UNDI_OPEN undi_open;
+ int rc;
+
+ /* Hook interrupt service routine and enable interrupt if applicable */
+ if ( undinic->irq ) {
+ undinet_hook_isr ( undinic->irq );
+ enable_irq ( undinic->irq );
+ send_eoi ( undinic->irq );
+ }
+
+ /* Set station address. Required for some PXE stacks; will
+ * spuriously fail on others. Ignore failures. We only ever
+ * use it to set the MAC address to the card's permanent value
+ * anyway.
+ */
+ memcpy ( undi_set_address.StationAddress, netdev->ll_addr,
+ sizeof ( undi_set_address.StationAddress ) );
+ pxeparent_call ( undinet_entry, PXENV_UNDI_SET_STATION_ADDRESS,
+ &undi_set_address, sizeof ( undi_set_address ) );
+
+ /* Open NIC. We ask for promiscuous operation, since it's the
+ * only way to ask for all multicast addresses. On any
+ * switched network, it shouldn't really make a difference to
+ * performance.
+ */
+ memset ( &undi_open, 0, sizeof ( undi_open ) );
+ undi_open.PktFilter = ( FLTR_DIRECTED | FLTR_BRDCST | FLTR_PRMSCS );
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_OPEN,
+ &undi_open, sizeof ( undi_open ) ) ) != 0 )
+ goto err;
+
+ DBGC ( undinic, "UNDINIC %p opened\n", undinic );
+ return 0;
+
+ err:
+ undinet_close ( netdev );
+ return rc;
+}
+
+/**
+ * Close NIC
+ *
+ * @v netdev Net device
+ */
+static void undinet_close ( struct net_device *netdev ) {
+ struct undi_nic *undinic = netdev->priv;
+ struct s_PXENV_UNDI_ISR undi_isr;
+ struct s_PXENV_UNDI_CLOSE undi_close;
+ int rc;
+
+ /* Ensure ISR has exited cleanly */
+ while ( undinic->isr_processing ) {
+ undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_ISR,
+ &undi_isr,
+ sizeof ( undi_isr ) ) ) != 0 )
+ break;
+ switch ( undi_isr.FuncFlag ) {
+ case PXENV_UNDI_ISR_OUT_TRANSMIT:
+ case PXENV_UNDI_ISR_OUT_RECEIVE:
+ /* Continue draining */
+ break;
+ default:
+ /* Stop processing */
+ undinic->isr_processing = 0;
+ break;
+ }
+ }
+
+ /* Close NIC */
+ pxeparent_call ( undinet_entry, PXENV_UNDI_CLOSE,
+ &undi_close, sizeof ( undi_close ) );
+
+ /* Disable interrupt and unhook ISR if applicable */
+ if ( undinic->irq ) {
+ disable_irq ( undinic->irq );
+ undinet_unhook_isr ( undinic->irq );
+ }
+
+ DBGC ( undinic, "UNDINIC %p closed\n", undinic );
+}
+
+/**
+ * Enable/disable interrupts
+ *
+ * @v netdev Net device
+ * @v enable Interrupts should be enabled
+ */
+static void undinet_irq ( struct net_device *netdev, int enable ) {
+ struct undi_nic *undinic = netdev->priv;
+
+ /* Cannot support interrupts yet */
+ DBGC ( undinic, "UNDINIC %p cannot %s interrupts\n",
+ undinic, ( enable ? "enable" : "disable" ) );
+}
+
+/** UNDI network device operations */
+static struct net_device_operations undinet_operations = {
+ .open = undinet_open,
+ .close = undinet_close,
+ .transmit = undinet_transmit,
+ .poll = undinet_poll,
+ .irq = undinet_irq,
+};
+
+/**
+ * Probe UNDI device
+ *
+ * @v undi UNDI device
+ * @ret rc Return status code
+ */
+int undinet_probe ( struct undi_device *undi ) {
+ struct net_device *netdev;
+ struct undi_nic *undinic;
+ struct s_PXENV_START_UNDI start_undi;
+ struct s_PXENV_UNDI_STARTUP undi_startup;
+ struct s_PXENV_UNDI_INITIALIZE undi_init;
+ struct s_PXENV_UNDI_GET_INFORMATION undi_info;
+ struct s_PXENV_UNDI_GET_IFACE_INFO undi_iface;
+ struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
+ struct s_PXENV_UNDI_CLEANUP undi_cleanup;
+ struct s_PXENV_STOP_UNDI stop_undi;
+ unsigned int retry;
+ int rc;
+
+ /* Allocate net device */
+ netdev = alloc_etherdev ( sizeof ( *undinic ) );
+ if ( ! netdev )
+ return -ENOMEM;
+ netdev_init ( netdev, &undinet_operations );
+ undinic = netdev->priv;
+ undi_set_drvdata ( undi, netdev );
+ netdev->dev = &undi->dev;
+ memset ( undinic, 0, sizeof ( *undinic ) );
+ undinet_entry = undi->entry;
+ DBGC ( undinic, "UNDINIC %p using UNDI %p\n", undinic, undi );
+
+ /* Hook in UNDI stack */
+ if ( ! ( undi->flags & UNDI_FL_STARTED ) ) {
+ memset ( &start_undi, 0, sizeof ( start_undi ) );
+ start_undi.AX = undi->pci_busdevfn;
+ start_undi.BX = undi->isapnp_csn;
+ start_undi.DX = undi->isapnp_read_port;
+ start_undi.ES = BIOS_SEG;
+ start_undi.DI = find_pnp_bios();
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_START_UNDI,
+ &start_undi,
+ sizeof ( start_undi ) ) ) != 0 )
+ goto err_start_undi;
+ }
+ undi->flags |= UNDI_FL_STARTED;
+
+ /* Bring up UNDI stack */
+ if ( ! ( undi->flags & UNDI_FL_INITIALIZED ) ) {
+ memset ( &undi_startup, 0, sizeof ( undi_startup ) );
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_STARTUP,
+ &undi_startup,
+ sizeof ( undi_startup ) ) ) != 0 )
+ goto err_undi_startup;
+ /* On some PXE stacks, PXENV_UNDI_INITIALIZE may fail
+ * due to a transient condition (e.g. media test
+ * failing because the link has only just come out of
+ * reset). We may therefore need to retry this call
+ * several times.
+ */
+ for ( retry = 0 ; ; ) {
+ memset ( &undi_init, 0, sizeof ( undi_init ) );
+ if ( ( rc = pxeparent_call ( undinet_entry,
+ PXENV_UNDI_INITIALIZE,
+ &undi_init,
+ sizeof ( undi_init ))) ==0)
+ break;
+ if ( ++retry > UNDI_INITIALIZE_RETRY_MAX )
+ goto err_undi_initialize;
+ DBGC ( undinic, "UNDINIC %p retrying "
+ "PXENV_UNDI_INITIALIZE (retry %d)\n",
+ undinic, retry );
+ /* Delay to allow link to settle if necessary */
+ mdelay ( UNDI_INITIALIZE_RETRY_DELAY_MS );
+ }
+ }
+ undi->flags |= UNDI_FL_INITIALIZED;
+
+ /* Get device information */
+ memset ( &undi_info, 0, sizeof ( undi_info ) );
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_GET_INFORMATION,
+ &undi_info, sizeof ( undi_info ) ) ) != 0 )
+ goto err_undi_get_information;
+ memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN );
+ memcpy ( netdev->ll_addr, undi_info.CurrentNodeAddress, ETH_ALEN );
+ undinic->irq = undi_info.IntNumber;
+ if ( undinic->irq > IRQ_MAX ) {
+ DBGC ( undinic, "UNDINIC %p has invalid IRQ %d\n",
+ undinic, undinic->irq );
+ rc = -EINVAL;
+ goto err_bad_irq;
+ }
+ DBGC ( undinic, "UNDINIC %p has MAC address %s and IRQ %d\n",
+ undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq );
+
+ /* Get interface information */
+ memset ( &undi_iface, 0, sizeof ( undi_iface ) );
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_GET_IFACE_INFO,
+ &undi_iface,
+ sizeof ( undi_iface ) ) ) != 0 )
+ goto err_undi_get_iface_info;
+ DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n",
+ undinic, undi_iface.IfaceType, undi_iface.LinkSpeed,
+ undi_iface.ServiceFlags );
+ if ( ( undi_iface.ServiceFlags & SUPPORTED_IRQ ) &&
+ ( undinic->irq != 0 ) ) {
+ undinic->irq_supported = 1;
+ }
+ DBGC ( undinic, "UNDINIC %p using %s mode\n", undinic,
+ ( undinic->irq_supported ? "interrupt" : "polling" ) );
+ if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot",
+ sizeof ( undi_iface.IfaceType ) ) == 0 ) {
+ DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n",
+ undinic );
+ undinic->hacks |= UNDI_HACK_EB54;
+ }
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register;
+
+ /* Mark as link up; we don't handle link state */
+ netdev_link_up ( netdev );
+
+ DBGC ( undinic, "UNDINIC %p added\n", undinic );
+ return 0;
+
+ err_register:
+ err_undi_get_iface_info:
+ err_bad_irq:
+ err_undi_get_information:
+ err_undi_initialize:
+ /* Shut down UNDI stack */
+ memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
+ pxeparent_call ( undinet_entry, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
+ sizeof ( undi_shutdown ) );
+ memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
+ pxeparent_call ( undinet_entry, PXENV_UNDI_CLEANUP, &undi_cleanup,
+ sizeof ( undi_cleanup ) );
+ undi->flags &= ~UNDI_FL_INITIALIZED;
+ err_undi_startup:
+ /* Unhook UNDI stack */
+ memset ( &stop_undi, 0, sizeof ( stop_undi ) );
+ pxeparent_call ( undinet_entry, PXENV_STOP_UNDI, &stop_undi,
+ sizeof ( stop_undi ) );
+ undi->flags &= ~UNDI_FL_STARTED;
+ err_start_undi:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ undi_set_drvdata ( undi, NULL );
+ return rc;
+}
+
+/**
+ * Remove UNDI device
+ *
+ * @v undi UNDI device
+ */
+void undinet_remove ( struct undi_device *undi ) {
+ struct net_device *netdev = undi_get_drvdata ( undi );
+ struct undi_nic *undinic = netdev->priv;
+ struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
+ struct s_PXENV_UNDI_CLEANUP undi_cleanup;
+ struct s_PXENV_STOP_UNDI stop_undi;
+
+ /* Unregister net device */
+ unregister_netdev ( netdev );
+
+ /* If we are preparing for an OS boot, or if we cannot exit
+ * via the PXE stack, then shut down the PXE stack.
+ */
+ if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) {
+
+ /* Shut down UNDI stack */
+ memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
+ pxeparent_call ( undinet_entry, PXENV_UNDI_SHUTDOWN,
+ &undi_shutdown, sizeof ( undi_shutdown ) );
+ memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
+ pxeparent_call ( undinet_entry, PXENV_UNDI_CLEANUP,
+ &undi_cleanup, sizeof ( undi_cleanup ) );
+ undi->flags &= ~UNDI_FL_INITIALIZED;
+
+ /* Unhook UNDI stack */
+ memset ( &stop_undi, 0, sizeof ( stop_undi ) );
+ pxeparent_call ( undinet_entry, PXENV_STOP_UNDI, &stop_undi,
+ sizeof ( stop_undi ) );
+ undi->flags &= ~UNDI_FL_STARTED;
+ }
+
+ /* Clear entry point */
+ memset ( &undinet_entry, 0, sizeof ( undinet_entry ) );
+
+ /* Free network device */
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+
+ DBGC ( undinic, "UNDINIC %p removed\n", undinic );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undionly.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undionly.c
new file mode 100644
index 00000000..a0012c88
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undionly.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ipxe/device.h>
+#include <ipxe/init.h>
+#include <ipxe/pci.h>
+#include <undi.h>
+#include <undinet.h>
+#include <undipreload.h>
+
+/** @file
+ *
+ * "Pure" UNDI driver
+ *
+ * This is the UNDI driver without explicit support for PCI or any
+ * other bus type. It is capable only of using the preloaded UNDI
+ * device. It must not be combined in an image with any other
+ * drivers.
+ *
+ * If you want a PXE-loadable image that contains only the UNDI
+ * driver, build "bin/undionly.kpxe".
+ *
+ * If you want any other image format, or any other drivers in
+ * addition to the UNDI driver, build e.g. "bin/undi.dsk".
+ */
+
+/**
+ * Probe UNDI root bus
+ *
+ * @v rootdev UNDI bus root device
+ *
+ * Scans the UNDI bus for devices and registers all devices it can
+ * find.
+ */
+static int undibus_probe ( struct root_device *rootdev ) {
+ struct undi_device *undi = &preloaded_undi;
+ int rc;
+
+ /* Check for a valie preloaded UNDI device */
+ if ( ! undi->entry.segment ) {
+ DBG ( "No preloaded UNDI device found!\n" );
+ return -ENODEV;
+ }
+
+ /* Add to device hierarchy */
+ undi->dev.driver_name = "undionly";
+ if ( undi->pci_busdevfn != UNDI_NO_PCI_BUSDEVFN ) {
+ undi->dev.desc.bus_type = BUS_TYPE_PCI;
+ undi->dev.desc.location = undi->pci_busdevfn;
+ undi->dev.desc.vendor = undi->pci_vendor;
+ undi->dev.desc.device = undi->pci_device;
+ snprintf ( undi->dev.name, sizeof ( undi->dev.name ),
+ "UNDI-PCI%02x:%02x.%x",
+ PCI_BUS ( undi->pci_busdevfn ),
+ PCI_SLOT ( undi->pci_busdevfn ),
+ PCI_FUNC ( undi->pci_busdevfn ) );
+ } else if ( undi->isapnp_csn != UNDI_NO_ISAPNP_CSN ) {
+ undi->dev.desc.bus_type = BUS_TYPE_ISAPNP;
+ snprintf ( undi->dev.name, sizeof ( undi->dev.name ),
+ "UNDI-ISAPNP" );
+ }
+ undi->dev.parent = &rootdev->dev;
+ list_add ( &undi->dev.siblings, &rootdev->dev.children);
+ INIT_LIST_HEAD ( &undi->dev.children );
+
+ /* Create network device */
+ if ( ( rc = undinet_probe ( undi ) ) != 0 )
+ goto err;
+
+ return 0;
+
+ err:
+ list_del ( &undi->dev.siblings );
+ return rc;
+}
+
+/**
+ * Remove UNDI root bus
+ *
+ * @v rootdev UNDI bus root device
+ */
+static void undibus_remove ( struct root_device *rootdev __unused ) {
+ struct undi_device *undi = &preloaded_undi;
+
+ undinet_remove ( undi );
+ list_del ( &undi->dev.siblings );
+}
+
+/** UNDI bus root device driver */
+static struct root_driver undi_root_driver = {
+ .probe = undibus_probe,
+ .remove = undibus_remove,
+};
+
+/** UNDI bus root device */
+struct root_device undi_root_device __root_device = {
+ .dev = { .name = "UNDI" },
+ .driver = &undi_root_driver,
+};
+
+/**
+ * Prepare for exit
+ *
+ * @v booting System is shutting down for OS boot
+ */
+static void undionly_shutdown ( int booting ) {
+ /* If we are shutting down to boot an OS, clear the "keep PXE
+ * stack" flag.
+ */
+ if ( booting )
+ preloaded_undi.flags &= ~UNDI_FL_KEEP_ALL;
+}
+
+struct startup_fn startup_undionly __startup_fn ( STARTUP_LATE ) = {
+ .shutdown = undionly_shutdown,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undipreload.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undipreload.c
new file mode 100644
index 00000000..a4b2f4ac
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undipreload.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <realmode.h>
+#include <undipreload.h>
+
+/** @file
+ *
+ * Preloaded UNDI stack
+ *
+ */
+
+/**
+ * Preloaded UNDI device
+ *
+ * This is the UNDI device that was present when Etherboot started
+ * execution (i.e. when loading a .kpxe image). The first driver to
+ * claim this device must zero out this data structure.
+ */
+struct undi_device __data16 ( preloaded_undi );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undirom.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undirom.c
new file mode 100644
index 00000000..2463d969
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/drivers/net/undirom.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pxe.h>
+#include <realmode.h>
+#include <undirom.h>
+
+/** @file
+ *
+ * UNDI expansion ROMs
+ *
+ */
+
+/** List of all UNDI ROMs */
+static LIST_HEAD ( undiroms );
+
+/**
+ * Parse PXE ROM ID structure
+ *
+ * @v undirom UNDI ROM
+ * @v pxeromid Offset within ROM to PXE ROM ID structure
+ * @ret rc Return status code
+ */
+static int undirom_parse_pxeromid ( struct undi_rom *undirom,
+ unsigned int pxeromid ) {
+ struct undi_rom_id undi_rom_id;
+ unsigned int undiloader;
+
+ DBGC ( undirom, "UNDIROM %p has PXE ROM ID at %04x:%04x\n", undirom,
+ undirom->rom_segment, pxeromid );
+
+ /* Read PXE ROM ID structure and verify */
+ copy_from_real ( &undi_rom_id, undirom->rom_segment, pxeromid,
+ sizeof ( undi_rom_id ) );
+ if ( undi_rom_id.Signature != UNDI_ROM_ID_SIGNATURE ) {
+ DBGC ( undirom, "UNDIROM %p has bad PXE ROM ID signature "
+ "%08x\n", undirom, undi_rom_id.Signature );
+ return -EINVAL;
+ }
+
+ /* Check for UNDI loader */
+ undiloader = undi_rom_id.UNDILoader;
+ if ( ! undiloader ) {
+ DBGC ( undirom, "UNDIROM %p has no UNDI loader\n", undirom );
+ return -EINVAL;
+ }
+
+ /* Fill in UNDI ROM loader fields */
+ undirom->loader_entry.segment = undirom->rom_segment;
+ undirom->loader_entry.offset = undiloader;
+ undirom->code_size = undi_rom_id.CodeSize;
+ undirom->data_size = undi_rom_id.DataSize;
+
+ DBGC ( undirom, "UNDIROM %p has UNDI loader at %04x:%04x "
+ "(code %04zx data %04zx)\n", undirom,
+ undirom->loader_entry.segment, undirom->loader_entry.offset,
+ undirom->code_size, undirom->data_size );
+ return 0;
+}
+
+/**
+ * Parse PCI expansion header
+ *
+ * @v undirom UNDI ROM
+ * @v pcirheader Offset within ROM to PCI expansion header
+ */
+static int undirom_parse_pcirheader ( struct undi_rom *undirom,
+ unsigned int pcirheader ) {
+ struct pcir_header pcir_header;
+
+ DBGC ( undirom, "UNDIROM %p has PCI expansion header at %04x:%04x\n",
+ undirom, undirom->rom_segment, pcirheader );
+
+ /* Read PCI expansion header and verify */
+ copy_from_real ( &pcir_header, undirom->rom_segment, pcirheader,
+ sizeof ( pcir_header ) );
+ if ( pcir_header.signature != PCIR_SIGNATURE ) {
+ DBGC ( undirom, "UNDIROM %p has bad PCI expansion header "
+ "signature %08x\n", undirom, pcir_header.signature );
+ return -EINVAL;
+ }
+
+ /* Fill in UNDI ROM PCI device fields */
+ undirom->bus_type = PCI_NIC;
+ undirom->bus_id.pci.vendor_id = pcir_header.vendor_id;
+ undirom->bus_id.pci.device_id = pcir_header.device_id;
+
+ DBGC ( undirom, "UNDIROM %p is for PCI devices %04x:%04x\n", undirom,
+ undirom->bus_id.pci.vendor_id, undirom->bus_id.pci.device_id );
+ return 0;
+
+}
+
+/**
+ * Probe UNDI ROM
+ *
+ * @v rom_segment ROM segment address
+ * @ret rc Return status code
+ */
+static int undirom_probe ( unsigned int rom_segment ) {
+ struct undi_rom *undirom = NULL;
+ struct undi_rom_header romheader;
+ size_t rom_len;
+ unsigned int pxeromid;
+ unsigned int pcirheader;
+ int rc;
+
+ /* Read expansion ROM header and verify */
+ copy_from_real ( &romheader, rom_segment, 0, sizeof ( romheader ) );
+ if ( romheader.Signature != ROM_SIGNATURE ) {
+ rc = -EINVAL;
+ goto err;
+ }
+ rom_len = ( romheader.ROMLength * 512 );
+
+ /* Allocate memory for UNDI ROM */
+ undirom = zalloc ( sizeof ( *undirom ) );
+ if ( ! undirom ) {
+ DBG ( "Could not allocate UNDI ROM structure\n" );
+ rc = -ENOMEM;
+ goto err;
+ }
+ DBGC ( undirom, "UNDIROM %p trying expansion ROM at %04x:0000 "
+ "(%zdkB)\n", undirom, rom_segment, ( rom_len / 1024 ) );
+ undirom->rom_segment = rom_segment;
+
+ /* Check for and parse PXE ROM ID */
+ pxeromid = romheader.PXEROMID;
+ if ( ! pxeromid ) {
+ DBGC ( undirom, "UNDIROM %p has no PXE ROM ID\n", undirom );
+ rc = -EINVAL;
+ goto err;
+ }
+ if ( pxeromid > rom_len ) {
+ DBGC ( undirom, "UNDIROM %p PXE ROM ID outside ROM\n",
+ undirom );
+ rc = -EINVAL;
+ goto err;
+ }
+ if ( ( rc = undirom_parse_pxeromid ( undirom, pxeromid ) ) != 0 )
+ goto err;
+
+ /* Parse PCIR header, if present */
+ pcirheader = romheader.PCIRHeader;
+ if ( pcirheader )
+ undirom_parse_pcirheader ( undirom, pcirheader );
+
+ /* Add to UNDI ROM list and return */
+ DBGC ( undirom, "UNDIROM %p registered\n", undirom );
+ list_add ( &undirom->list, &undiroms );
+ return 0;
+
+ err:
+ free ( undirom );
+ return rc;
+}
+
+/**
+ * Create UNDI ROMs for all possible expansion ROMs
+ *
+ * @ret
+ */
+static void undirom_probe_all_roms ( void ) {
+ static int probed = 0;
+ unsigned int rom_segment;
+
+ /* Perform probe only once */
+ if ( probed )
+ return;
+
+ DBG ( "Scanning for PXE expansion ROMs\n" );
+
+ /* Scan through expansion ROM region at 512 byte intervals */
+ for ( rom_segment = 0xc000 ; rom_segment < 0x10000 ;
+ rom_segment += 0x20 ) {
+ undirom_probe ( rom_segment );
+ }
+
+ probed = 1;
+}
+
+/**
+ * Find UNDI ROM for PCI device
+ *
+ * @v vendor_id PCI vendor ID
+ * @v device_id PCI device ID
+ * @v rombase ROM base address, or 0 for any
+ * @ret undirom UNDI ROM, or NULL
+ */
+struct undi_rom * undirom_find_pci ( unsigned int vendor_id,
+ unsigned int device_id,
+ unsigned int rombase ) {
+ struct undi_rom *undirom;
+
+ undirom_probe_all_roms();
+
+ list_for_each_entry ( undirom, &undiroms, list ) {
+ if ( undirom->bus_type != PCI_NIC )
+ continue;
+ if ( undirom->bus_id.pci.vendor_id != vendor_id )
+ continue;
+ if ( undirom->bus_id.pci.device_id != device_id )
+ continue;
+ if ( rombase && ( ( undirom->rom_segment << 4 ) != rombase ) )
+ continue;
+ DBGC ( undirom, "UNDIROM %p matched PCI %04x:%04x (%08x)\n",
+ undirom, vendor_id, device_id, rombase );
+ return undirom;
+ }
+
+ DBG ( "No UNDI ROM matched PCI %04x:%04x (%08x)\n",
+ vendor_id, device_id, rombase );
+ return NULL;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/basemem.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/basemem.c
new file mode 100644
index 00000000..d18e8b80
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/basemem.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <realmode.h>
+#include <bios.h>
+#include <basemem.h>
+#include <ipxe/hidemem.h>
+
+/** @file
+ *
+ * Base memory allocation
+ *
+ */
+
+/**
+ * Set the BIOS free base memory counter
+ *
+ * @v new_fbms New free base memory counter (in kB)
+ */
+void set_fbms ( unsigned int new_fbms ) {
+ uint16_t fbms = new_fbms;
+
+ /* Update the BIOS memory counter */
+ put_real ( fbms, BDA_SEG, BDA_FBMS );
+
+ /* Update our hidden memory region map */
+ hide_basemem();
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/bios_console.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/bios_console.c
new file mode 100644
index 00000000..76a46dfa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/bios_console.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <assert.h>
+#include <realmode.h>
+#include <ipxe/console.h>
+#include <ipxe/ansiesc.h>
+#include <ipxe/keymap.h>
+#include <config/console.h>
+
+#define ATTR_BOLD 0x08
+
+#define ATTR_FCOL_MASK 0x07
+#define ATTR_FCOL_BLACK 0x00
+#define ATTR_FCOL_BLUE 0x01
+#define ATTR_FCOL_GREEN 0x02
+#define ATTR_FCOL_CYAN 0x03
+#define ATTR_FCOL_RED 0x04
+#define ATTR_FCOL_MAGENTA 0x05
+#define ATTR_FCOL_YELLOW 0x06
+#define ATTR_FCOL_WHITE 0x07
+
+#define ATTR_BCOL_MASK 0x70
+#define ATTR_BCOL_BLACK 0x00
+#define ATTR_BCOL_BLUE 0x10
+#define ATTR_BCOL_GREEN 0x20
+#define ATTR_BCOL_CYAN 0x30
+#define ATTR_BCOL_RED 0x40
+#define ATTR_BCOL_MAGENTA 0x50
+#define ATTR_BCOL_YELLOW 0x60
+#define ATTR_BCOL_WHITE 0x70
+
+#define ATTR_DEFAULT ATTR_FCOL_WHITE
+
+/* Set default console usage if applicable */
+#if ! ( defined ( CONSOLE_PCBIOS ) && CONSOLE_EXPLICIT ( CONSOLE_PCBIOS ) )
+#undef CONSOLE_PCBIOS
+#define CONSOLE_PCBIOS ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
+#endif
+
+/** Current character attribute */
+static unsigned int bios_attr = ATTR_DEFAULT;
+
+/**
+ * Handle ANSI CUP (cursor position)
+ *
+ * @v count Parameter count
+ * @v params[0] Row (1 is top)
+ * @v params[1] Column (1 is left)
+ */
+static void bios_handle_cup ( unsigned int count __unused, int params[] ) {
+ int cx = ( params[1] - 1 );
+ int cy = ( params[0] - 1 );
+
+ if ( cx < 0 )
+ cx = 0;
+ if ( cy < 0 )
+ cy = 0;
+
+ __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
+ "int $0x10\n\t"
+ "cli\n\t" )
+ : : "a" ( 0x0200 ), "b" ( 1 ),
+ "d" ( ( cy << 8 ) | cx ) );
+}
+
+/**
+ * Handle ANSI ED (erase in page)
+ *
+ * @v count Parameter count
+ * @v params[0] Region to erase
+ */
+static void bios_handle_ed ( unsigned int count __unused,
+ int params[] __unused ) {
+ /* We assume that we always clear the whole screen */
+ assert ( params[0] == ANSIESC_ED_ALL );
+
+ __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
+ "int $0x10\n\t"
+ "cli\n\t" )
+ : : "a" ( 0x0600 ), "b" ( bios_attr << 8 ),
+ "c" ( 0 ), "d" ( 0xffff ) );
+}
+
+/**
+ * Handle ANSI SGR (set graphics rendition)
+ *
+ * @v count Parameter count
+ * @v params List of graphic rendition aspects
+ */
+static void bios_handle_sgr ( unsigned int count, int params[] ) {
+ static const uint8_t bios_attr_fcols[10] = {
+ ATTR_FCOL_BLACK, ATTR_FCOL_RED, ATTR_FCOL_GREEN,
+ ATTR_FCOL_YELLOW, ATTR_FCOL_BLUE, ATTR_FCOL_MAGENTA,
+ ATTR_FCOL_CYAN, ATTR_FCOL_WHITE,
+ ATTR_FCOL_WHITE, ATTR_FCOL_WHITE /* defaults */
+ };
+ static const uint8_t bios_attr_bcols[10] = {
+ ATTR_BCOL_BLACK, ATTR_BCOL_RED, ATTR_BCOL_GREEN,
+ ATTR_BCOL_YELLOW, ATTR_BCOL_BLUE, ATTR_BCOL_MAGENTA,
+ ATTR_BCOL_CYAN, ATTR_BCOL_WHITE,
+ ATTR_BCOL_BLACK, ATTR_BCOL_BLACK /* defaults */
+ };
+ unsigned int i;
+ int aspect;
+
+ for ( i = 0 ; i < count ; i++ ) {
+ aspect = params[i];
+ if ( aspect == 0 ) {
+ bios_attr = ATTR_DEFAULT;
+ } else if ( aspect == 1 ) {
+ bios_attr |= ATTR_BOLD;
+ } else if ( aspect == 22 ) {
+ bios_attr &= ~ATTR_BOLD;
+ } else if ( ( aspect >= 30 ) && ( aspect <= 39 ) ) {
+ bios_attr &= ~ATTR_FCOL_MASK;
+ bios_attr |= bios_attr_fcols[ aspect - 30 ];
+ } else if ( ( aspect >= 40 ) && ( aspect <= 49 ) ) {
+ bios_attr &= ~ATTR_BCOL_MASK;
+ bios_attr |= bios_attr_bcols[ aspect - 40 ];
+ }
+ }
+}
+
+/** BIOS console ANSI escape sequence handlers */
+static struct ansiesc_handler bios_ansiesc_handlers[] = {
+ { ANSIESC_CUP, bios_handle_cup },
+ { ANSIESC_ED, bios_handle_ed },
+ { ANSIESC_SGR, bios_handle_sgr },
+ { 0, NULL }
+};
+
+/** BIOS console ANSI escape sequence context */
+static struct ansiesc_context bios_ansiesc_ctx = {
+ .handlers = bios_ansiesc_handlers,
+};
+
+/**
+ * Print a character to BIOS console
+ *
+ * @v character Character to be printed
+ */
+static void bios_putchar ( int character ) {
+ int discard_a, discard_b, discard_c;
+
+ /* Intercept ANSI escape sequences */
+ character = ansiesc_process ( &bios_ansiesc_ctx, character );
+ if ( character < 0 )
+ return;
+
+ /* Print character with attribute */
+ __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
+ "sti\n\t"
+ /* Skip non-printable characters */
+ "cmpb $0x20, %%al\n\t"
+ "jb 1f\n\t"
+ /* Read attribute */
+ "movb %%al, %%cl\n\t"
+ "movb $0x08, %%ah\n\t"
+ "int $0x10\n\t"
+ "xchgb %%al, %%cl\n\t"
+ /* Skip if attribute matches */
+ "cmpb %%ah, %%bl\n\t"
+ "je 1f\n\t"
+ /* Set attribute */
+ "movw $0x0001, %%cx\n\t"
+ "movb $0x09, %%ah\n\t"
+ "int $0x10\n\t"
+ "\n1:\n\t"
+ /* Print character */
+ "xorw %%bx, %%bx\n\t"
+ "movb $0x0e, %%ah\n\t"
+ "int $0x10\n\t"
+ "cli\n\t"
+ "popl %%ebp\n\t" /* gcc bug */ )
+ : "=a" ( discard_a ), "=b" ( discard_b ),
+ "=c" ( discard_c )
+ : "a" ( character ), "b" ( bios_attr ) );
+}
+
+/**
+ * Pointer to current ANSI output sequence
+ *
+ * While we are in the middle of returning an ANSI sequence for a
+ * special key, this will point to the next character to return. When
+ * not in the middle of such a sequence, this will point to a NUL
+ * (note: not "will be NULL").
+ */
+static const char *ansi_input = "";
+
+/** A mapping from a BIOS scan code to an ANSI escape sequence */
+#define BIOS_KEY( key, ansi ) key ansi "\0"
+
+/** Mapping from BIOS scan codes to ANSI escape sequences */
+static const char ansi_sequences[] = {
+ BIOS_KEY ( "\x53", "[3~" ) /* Delete */
+ BIOS_KEY ( "\x48", "[A" ) /* Up arrow */
+ BIOS_KEY ( "\x50", "[B" ) /* Down arrow */
+ BIOS_KEY ( "\x4b", "[D" ) /* Left arrow */
+ BIOS_KEY ( "\x4d", "[C" ) /* Right arrow */
+ BIOS_KEY ( "\x47", "[H" ) /* Home */
+ BIOS_KEY ( "\x4f", "[F" ) /* End */
+ BIOS_KEY ( "\x49", "[5~" ) /* Page up */
+ BIOS_KEY ( "\x51", "[6~" ) /* Page down */
+ BIOS_KEY ( "\x3f", "[15~" ) /* F5 */
+ BIOS_KEY ( "\x40", "[17~" ) /* F6 */
+ BIOS_KEY ( "\x41", "[18~" ) /* F7 */
+ BIOS_KEY ( "\x42", "[19~" ) /* F8 (required for PXE) */
+ BIOS_KEY ( "\x43", "[20~" ) /* F9 */
+ BIOS_KEY ( "\x44", "[21~" ) /* F10 */
+ BIOS_KEY ( "\x85", "[23~" ) /* F11 */
+ BIOS_KEY ( "\x86", "[24~" ) /* F12 */
+};
+
+/**
+ * Get ANSI escape sequence corresponding to BIOS scancode
+ *
+ * @v scancode BIOS scancode
+ * @ret ansi_seq ANSI escape sequence, if any, otherwise NULL
+ */
+static const char * scancode_to_ansi_seq ( unsigned int scancode ) {
+ const char *seq = ansi_sequences;
+
+ while ( *seq ) {
+ if ( *(seq++) == ( ( char ) scancode ) )
+ return seq;
+ seq += ( strlen ( seq ) + 1 );
+ }
+ DBG ( "Unrecognised BIOS scancode %02x\n", scancode );
+ return NULL;
+}
+
+/**
+ * Map a key
+ *
+ * @v character Character read from console
+ * @ret character Mapped character
+ */
+static int bios_keymap ( unsigned int character ) {
+ struct key_mapping *mapping;
+
+ for_each_table_entry ( mapping, KEYMAP ) {
+ if ( mapping->from == character )
+ return mapping->to;
+ }
+ return character;
+}
+
+/**
+ * Get character from BIOS console
+ *
+ * @ret character Character read from console
+ */
+static int bios_getchar ( void ) {
+ uint16_t keypress;
+ unsigned int character;
+ const char *ansi_seq;
+
+ /* If we are mid-sequence, pass out the next byte */
+ if ( ( character = *ansi_input ) ) {
+ ansi_input++;
+ return character;
+ }
+
+ /* Read character from real BIOS console */
+ __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
+ "int $0x16\n\t"
+ "cli\n\t" )
+ : "=a" ( keypress ) : "a" ( 0x1000 ) );
+ character = ( keypress & 0xff );
+
+ /* If it's a normal character, just map and return it */
+ if ( character && ( character < 0x80 ) )
+ return bios_keymap ( character );
+
+ /* Otherwise, check for a special key that we know about */
+ if ( ( ansi_seq = scancode_to_ansi_seq ( keypress >> 8 ) ) ) {
+ /* Start of escape sequence: return ESC (0x1b) */
+ ansi_input = ansi_seq;
+ return 0x1b;
+ }
+
+ return 0;
+}
+
+/**
+ * Check for character ready to read from BIOS console
+ *
+ * @ret True Character available to read
+ * @ret False No character available to read
+ */
+static int bios_iskey ( void ) {
+ unsigned int discard_a;
+ unsigned int flags;
+
+ /* If we are mid-sequence, we are always ready */
+ if ( *ansi_input )
+ return 1;
+
+ /* Otherwise check the real BIOS console */
+ __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
+ "int $0x16\n\t"
+ "pushfw\n\t"
+ "popw %w0\n\t"
+ "cli\n\t" )
+ : "=r" ( flags ), "=a" ( discard_a )
+ : "a" ( 0x1100 ) );
+ return ( ! ( flags & ZF ) );
+}
+
+struct console_driver bios_console __console_driver = {
+ .putchar = bios_putchar,
+ .getchar = bios_getchar,
+ .iskey = bios_iskey,
+ .usage = CONSOLE_PCBIOS,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/e820mangler.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/e820mangler.S
new file mode 100644
index 00000000..eeed51f8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/e820mangler.S
@@ -0,0 +1,584 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .text
+ .arch i386
+ .code16
+
+#define SMAP 0x534d4150
+
+/* Most documentation refers to the E820 buffer as being 20 bytes, and
+ * the API makes it perfectly legitimate to pass only a 20-byte buffer
+ * and expect to get valid data. However, some morons at ACPI decided
+ * to extend the data structure by adding an extra "extended
+ * attributes" field and by including critical information within this
+ * field, such as whether or not the region is enabled. A caller who
+ * passes in only a 20-byte buffer therefore risks getting very, very
+ * misleading information.
+ *
+ * I have personally witnessed an HP BIOS that returns a value of
+ * 0x0009 in the extended attributes field. If we don't pass this
+ * value through to the caller, 32-bit WinPE will die, usually with a
+ * PAGE_FAULT_IN_NONPAGED_AREA blue screen of death.
+ *
+ * Allow a ridiculously large maximum value (64 bytes) for the E820
+ * buffer as a guard against insufficiently creative idiots in the
+ * future.
+ */
+#define E820MAXSIZE 64
+
+/****************************************************************************
+ *
+ * Allowed memory windows
+ *
+ * There are two ways to view this list. The first is as a list of
+ * (non-overlapping) allowed memory regions, sorted by increasing
+ * address. The second is as a list of (non-overlapping) hidden
+ * memory regions, again sorted by increasing address. The second
+ * view is offset by half an entry from the first: think about this
+ * for a moment and it should make sense.
+ *
+ * xxx_memory_window is used to indicate an "allowed region"
+ * structure, hidden_xxx_memory is used to indicate a "hidden region"
+ * structure. Each structure is 16 bytes in length.
+ *
+ ****************************************************************************
+ */
+ .section ".data16", "aw", @progbits
+ .align 16
+ .globl hidemem_base
+ .globl hidemem_umalloc
+ .globl hidemem_textdata
+memory_windows:
+base_memory_window: .long 0x00000000, 0x00000000 /* Start of memory */
+
+hidemem_base: .long 0x000a0000, 0x00000000 /* Changes at runtime */
+ext_memory_window: .long 0x000a0000, 0x00000000 /* 640kB mark */
+
+hidemem_umalloc: .long 0xffffffff, 0xffffffff /* Changes at runtime */
+ .long 0xffffffff, 0xffffffff /* Changes at runtime */
+
+hidemem_textdata: .long 0xffffffff, 0xffffffff /* Changes at runtime */
+ .long 0xffffffff, 0xffffffff /* Changes at runtime */
+
+ .long 0xffffffff, 0xffffffff /* End of memory */
+memory_windows_end:
+
+/****************************************************************************
+ * Truncate region to memory window
+ *
+ * Parameters:
+ * %edx:%eax Start of region
+ * %ecx:%ebx Length of region
+ * %si Memory window
+ * Returns:
+ * %edx:%eax Start of windowed region
+ * %ecx:%ebx Length of windowed region
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+window_region:
+ /* Convert (start,len) to (start, end) */
+ addl %eax, %ebx
+ adcl %edx, %ecx
+ /* Truncate to window start */
+ cmpl 4(%si), %edx
+ jne 1f
+ cmpl 0(%si), %eax
+1: jae 2f
+ movl 4(%si), %edx
+ movl 0(%si), %eax
+2: /* Truncate to window end */
+ cmpl 12(%si), %ecx
+ jne 1f
+ cmpl 8(%si), %ebx
+1: jbe 2f
+ movl 12(%si), %ecx
+ movl 8(%si), %ebx
+2: /* Convert (start, end) back to (start, len) */
+ subl %eax, %ebx
+ sbbl %edx, %ecx
+ /* If length is <0, set length to 0 */
+ jae 1f
+ xorl %ebx, %ebx
+ xorl %ecx, %ecx
+ ret
+ .size window_region, . - window_region
+
+/****************************************************************************
+ * Patch "memory above 1MB" figure
+ *
+ * Parameters:
+ * %ax Memory above 1MB, in 1kB blocks
+ * Returns:
+ * %ax Modified memory above 1M in 1kB blocks
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+patch_1m:
+ pushal
+ /* Convert to (start,len) format and call truncate */
+ xorl %ecx, %ecx
+ movzwl %ax, %ebx
+ shll $10, %ebx
+ xorl %edx, %edx
+ movl $0x100000, %eax
+ movw $ext_memory_window, %si
+ call window_region
+ /* Convert back to "memory above 1MB" format and return via %ax */
+ pushfw
+ shrl $10, %ebx
+ popfw
+ movw %sp, %bp
+ movw %bx, 28(%bp)
+ popal
+ ret
+ .size patch_1m, . - patch_1m
+
+/****************************************************************************
+ * Patch "memory above 16MB" figure
+ *
+ * Parameters:
+ * %bx Memory above 16MB, in 64kB blocks
+ * Returns:
+ * %bx Modified memory above 16M in 64kB blocks
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+patch_16m:
+ pushal
+ /* Convert to (start,len) format and call truncate */
+ xorl %ecx, %ecx
+ shll $16, %ebx
+ xorl %edx, %edx
+ movl $0x1000000, %eax
+ movw $ext_memory_window, %si
+ call window_region
+ /* Convert back to "memory above 16MB" format and return via %bx */
+ pushfw
+ shrl $16, %ebx
+ popfw
+ movw %sp, %bp
+ movw %bx, 16(%bp)
+ popal
+ ret
+ .size patch_16m, . - patch_16m
+
+/****************************************************************************
+ * Patch "memory between 1MB and 16MB" and "memory above 16MB" figures
+ *
+ * Parameters:
+ * %ax Memory between 1MB and 16MB, in 1kB blocks
+ * %bx Memory above 16MB, in 64kB blocks
+ * Returns:
+ * %ax Modified memory between 1MB and 16MB, in 1kB blocks
+ * %bx Modified memory above 16MB, in 64kB blocks
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+patch_1m_16m:
+ call patch_1m
+ call patch_16m
+ /* If 1M region is no longer full-length, kill off the 16M region */
+ cmpw $( 15 * 1024 ), %ax
+ je 1f
+ xorw %bx, %bx
+1: ret
+ .size patch_1m_16m, . - patch_1m_16m
+
+/****************************************************************************
+ * Get underlying e820 memory region to underlying_e820 buffer
+ *
+ * Parameters:
+ * As for INT 15,e820
+ * Returns:
+ * As for INT 15,e820
+ *
+ * Wraps the underlying INT 15,e820 call so that the continuation
+ * value (%ebx) is a 16-bit simple sequence counter (with the high 16
+ * bits ignored), and termination is always via CF=1 rather than
+ * %ebx=0.
+ *
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+get_underlying_e820:
+
+ /* If the requested region is in the cache, return it */
+ cmpw %bx, underlying_e820_index
+ jne 2f
+ pushw %di
+ pushw %si
+ movw $underlying_e820_cache, %si
+ cmpl underlying_e820_cache_size, %ecx
+ jbe 1f
+ movl underlying_e820_cache_size, %ecx
+1: pushl %ecx
+ rep movsb
+ popl %ecx
+ popw %si
+ popw %di
+ incw %bx
+ movl %edx, %eax
+ clc
+ ret
+2:
+ /* If the requested region is earlier than the cached region,
+ * invalidate the cache.
+ */
+ cmpw %bx, underlying_e820_index
+ jbe 1f
+ movw $0xffff, underlying_e820_index
+1:
+ /* If the cache is invalid, reset the underlying %ebx */
+ cmpw $0xffff, underlying_e820_index
+ jne 1f
+ andl $0, underlying_e820_ebx
+1:
+ /* If the cache is valid but the continuation value is zero,
+ * this means that the previous underlying call returned with
+ * %ebx=0. Return with CF=1 in this case.
+ */
+ cmpw $0xffff, underlying_e820_index
+ je 1f
+ cmpl $0, underlying_e820_ebx
+ jne 1f
+ stc
+ ret
+1:
+ /* Get the next region into the cache */
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ pushl %esi /* Some implementations corrupt %esi, so we */
+ pushl %edi /* preserve %esi, %edi and %ebp to be paranoid */
+ pushl %ebp
+ pushw %es
+ pushw %ds
+ popw %es
+ movw $underlying_e820_cache, %di
+ cmpl $E820MAXSIZE, %ecx
+ jbe 1f
+ movl $E820MAXSIZE, %ecx
+1: movl underlying_e820_ebx, %ebx
+ stc
+ pushfw
+ lcall *%cs:int15_vector
+ popw %es
+ popl %ebp
+ popl %edi
+ popl %esi
+ /* Check for error return from underlying e820 call */
+ jc 2f /* CF set: error */
+ cmpl $SMAP, %eax
+ je 3f /* 'SMAP' missing: error */
+2: /* An error occurred: return values returned by underlying e820 call */
+ stc /* Force CF set if SMAP was missing */
+ addr32 leal 16(%esp), %esp /* avoid changing other flags */
+ ret
+3: /* No error occurred */
+ movl %ebx, underlying_e820_ebx
+ movl %ecx, underlying_e820_cache_size
+ popl %edx
+ popl %ecx
+ popl %ebx
+ popl %eax
+ /* Mark cache as containing this result */
+ incw underlying_e820_index
+
+ /* Loop until found */
+ jmp get_underlying_e820
+ .size get_underlying_e820, . - get_underlying_e820
+
+ .section ".data16", "aw", @progbits
+underlying_e820_index:
+ .word 0xffff /* Initialise to an invalid value */
+ .size underlying_e820_index, . - underlying_e820_index
+
+ .section ".bss16", "aw", @nobits
+underlying_e820_ebx:
+ .long 0
+ .size underlying_e820_ebx, . - underlying_e820_ebx
+
+ .section ".bss16", "aw", @nobits
+underlying_e820_cache:
+ .space E820MAXSIZE
+ .size underlying_e820_cache, . - underlying_e820_cache
+
+ .section ".bss16", "aw", @nobits
+underlying_e820_cache_size:
+ .long 0
+ .size underlying_e820_cache_size, . - underlying_e820_cache_size
+
+/****************************************************************************
+ * Get windowed e820 region, without empty region stripping
+ *
+ * Parameters:
+ * As for INT 15,e820
+ * Returns:
+ * As for INT 15,e820
+ *
+ * Wraps the underlying INT 15,e820 call so that each underlying
+ * region is returned N times, windowed to fit within N visible-memory
+ * windows. Termination is always via CF=1.
+ *
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+get_windowed_e820:
+
+ /* Preserve registers */
+ pushl %esi
+ pushw %bp
+
+ /* Split %ebx into %si:%bx, store original %bx in %bp */
+ pushl %ebx
+ popw %bp
+ popw %si
+
+ /* %si == 0 => start of memory_windows list */
+ testw %si, %si
+ jne 1f
+ movw $memory_windows, %si
+1:
+ /* Get (cached) underlying e820 region to buffer */
+ call get_underlying_e820
+ jc 99f /* Abort on error */
+
+ /* Preserve registers */
+ pushal
+ /* start => %edx:%eax, len => %ecx:%ebx */
+ movl %es:0(%di), %eax
+ movl %es:4(%di), %edx
+ movl %es:8(%di), %ebx
+ movl %es:12(%di), %ecx
+ /* Truncate region to current window */
+ call window_region
+1: /* Store modified values in e820 map entry */
+ movl %eax, %es:0(%di)
+ movl %edx, %es:4(%di)
+ movl %ebx, %es:8(%di)
+ movl %ecx, %es:12(%di)
+ /* Restore registers */
+ popal
+
+ /* Derive continuation value for next call */
+ addw $16, %si
+ cmpw $memory_windows_end, %si
+ jne 1f
+ /* End of memory windows: reset %si and allow %bx to continue */
+ xorw %si, %si
+ jmp 2f
+1: /* More memory windows to go: restore original %bx */
+ movw %bp, %bx
+2: /* Construct %ebx from %si:%bx */
+ pushw %si
+ pushw %bx
+ popl %ebx
+
+98: /* Clear CF */
+ clc
+99: /* Restore registers and return */
+ popw %bp
+ popl %esi
+ ret
+ .size get_windowed_e820, . - get_windowed_e820
+
+/****************************************************************************
+ * Get windowed e820 region, with empty region stripping
+ *
+ * Parameters:
+ * As for INT 15,e820
+ * Returns:
+ * As for INT 15,e820
+ *
+ * Wraps the underlying INT 15,e820 call so that each underlying
+ * region is returned up to N times, windowed to fit within N
+ * visible-memory windows. Empty windows are never returned.
+ * Termination is always via CF=1.
+ *
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+get_nonempty_e820:
+
+ /* Record entry parameters */
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+
+ /* Get next windowed region */
+ call get_windowed_e820
+ jc 99f /* abort on error */
+
+ /* If region is non-empty, finish here */
+ cmpl $0, %es:8(%di)
+ jne 98f
+ cmpl $0, %es:12(%di)
+ jne 98f
+
+ /* Region was empty: restore entry parameters and go to next region */
+ popl %edx
+ popl %ecx
+ popl %eax
+ jmp get_nonempty_e820
+
+98: /* Clear CF */
+ clc
+99: /* Return values from underlying call */
+ addr32 leal 12(%esp), %esp /* avoid changing flags */
+ ret
+ .size get_nonempty_e820, . - get_nonempty_e820
+
+/****************************************************************************
+ * Get mangled e820 region, with empty region stripping
+ *
+ * Parameters:
+ * As for INT 15,e820
+ * Returns:
+ * As for INT 15,e820
+ *
+ * Wraps the underlying INT 15,e820 call so that underlying regions
+ * are windowed to the allowed memory regions. Empty regions are
+ * stripped from the map. Termination is always via %ebx=0.
+ *
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+get_mangled_e820:
+
+ /* Get a nonempty region */
+ call get_nonempty_e820
+ jc 99f /* Abort on error */
+
+ /* Peek ahead to see if there are any further nonempty regions */
+ pushal
+ pushw %es
+ movw %sp, %bp
+ subw %cx, %sp
+ movl $0xe820, %eax
+ movl $SMAP, %edx
+ pushw %ss
+ popw %es
+ movw %sp, %di
+ call get_nonempty_e820
+ movw %bp, %sp
+ popw %es
+ popal
+ jnc 99f /* There are further nonempty regions */
+
+ /* No futher nonempty regions: zero %ebx and clear CF */
+ xorl %ebx, %ebx
+
+99: /* Return */
+ ret
+ .size get_mangled_e820, . - get_mangled_e820
+
+/****************************************************************************
+ * INT 15,e820 handler
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+int15_e820:
+ pushw %ds
+ pushw %cs:rm_ds
+ popw %ds
+ call get_mangled_e820
+ popw %ds
+ call patch_cf
+ iret
+ .size int15_e820, . - int15_e820
+
+/****************************************************************************
+ * INT 15,e801 handler
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+int15_e801:
+ /* Call previous handler */
+ pushfw
+ lcall *%cs:int15_vector
+ call patch_cf
+ /* Edit result */
+ pushw %ds
+ pushw %cs:rm_ds
+ popw %ds
+ call patch_1m_16m
+ xchgw %ax, %cx
+ xchgw %bx, %dx
+ call patch_1m_16m
+ xchgw %ax, %cx
+ xchgw %bx, %dx
+ popw %ds
+ iret
+ .size int15_e801, . - int15_e801
+
+/****************************************************************************
+ * INT 15,88 handler
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+int15_88:
+ /* Call previous handler */
+ pushfw
+ lcall *%cs:int15_vector
+ call patch_cf
+ /* Edit result */
+ pushw %ds
+ pushw %cs:rm_ds
+ popw %ds
+ call patch_1m
+ popw %ds
+ iret
+ .size int15_88, . - int15_88
+
+/****************************************************************************
+ * INT 15 handler
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+ .globl int15
+int15:
+ /* See if we want to intercept this call */
+ pushfw
+ cmpw $0xe820, %ax
+ jne 1f
+ cmpl $SMAP, %edx
+ jne 1f
+ popfw
+ jmp int15_e820
+1: cmpw $0xe801, %ax
+ jne 2f
+ popfw
+ jmp int15_e801
+2: cmpb $0x88, %ah
+ jne 3f
+ popfw
+ jmp int15_88
+3: popfw
+ ljmp *%cs:int15_vector
+ .size int15, . - int15
+
+ .section ".text16.data", "aw", @progbits
+ .globl int15_vector
+int15_vector:
+ .long 0
+ .size int15_vector, . - int15_vector
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/fakee820.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/fakee820.c
new file mode 100644
index 00000000..ea116fe5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/fakee820.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <realmode.h>
+#include <biosint.h>
+
+/** Assembly routine in inline asm */
+extern void int15_fakee820();
+
+/** Original INT 15 handler */
+static struct segoff __text16 ( real_int15_vector );
+#define real_int15_vector __use_text16 ( real_int15_vector )
+
+/** An INT 15,e820 memory map entry */
+struct e820_entry {
+ /** Start of region */
+ uint64_t start;
+ /** Length of region */
+ uint64_t len;
+ /** Type of region */
+ uint32_t type;
+} __attribute__ (( packed ));
+
+#define E820_TYPE_RAM 1 /**< Normal memory */
+#define E820_TYPE_RSVD 2 /**< Reserved and unavailable */
+#define E820_TYPE_ACPI 3 /**< ACPI reclaim memory */
+#define E820_TYPE_NVS 4 /**< ACPI NVS memory */
+
+/** Fake e820 map */
+static struct e820_entry __text16_array ( e820map, [] ) __used = {
+ { 0x00000000ULL, ( 0x000a0000ULL - 0x00000000ULL ), E820_TYPE_RAM },
+ { 0x00100000ULL, ( 0xcfb50000ULL - 0x00100000ULL ), E820_TYPE_RAM },
+ { 0xcfb50000ULL, ( 0xcfb64000ULL - 0xcfb50000ULL ), E820_TYPE_RSVD },
+ { 0xcfb64000ULL, ( 0xcfb66000ULL - 0xcfb64000ULL ), E820_TYPE_RSVD },
+ { 0xcfb66000ULL, ( 0xcfb85c00ULL - 0xcfb66000ULL ), E820_TYPE_ACPI },
+ { 0xcfb85c00ULL, ( 0xd0000000ULL - 0xcfb85c00ULL ), E820_TYPE_RSVD },
+ { 0xe0000000ULL, ( 0xf0000000ULL - 0xe0000000ULL ), E820_TYPE_RSVD },
+ { 0xfe000000ULL, (0x100000000ULL - 0xfe000000ULL ), E820_TYPE_RSVD },
+ {0x100000000ULL, (0x230000000ULL -0x100000000ULL ), E820_TYPE_RAM },
+};
+#define e820map __use_text16 ( e820map )
+
+void fake_e820 ( void ) {
+ __asm__ __volatile__ (
+ TEXT16_CODE ( "\nint15_fakee820:\n\t"
+ "pushfw\n\t"
+ "cmpl $0xe820, %%eax\n\t"
+ "jne 99f\n\t"
+ "cmpl $0x534d4150, %%edx\n\t"
+ "jne 99f\n\t"
+ "pushaw\n\t"
+ "movw %%sp, %%bp\n\t"
+ "andb $~0x01, 22(%%bp)\n\t" /* Clear return CF */
+ "leaw e820map(%%bx), %%si\n\t"
+ "cs rep movsb\n\t"
+ "popaw\n\t"
+ "movl %%edx, %%eax\n\t"
+ "addl $20, %%ebx\n\t"
+ "cmpl %0, %%ebx\n\t"
+ "jne 1f\n\t"
+ "xorl %%ebx,%%ebx\n\t"
+ "\n1:\n\t"
+ "popfw\n\t"
+ "iret\n\t"
+ "\n99:\n\t"
+ "popfw\n\t"
+ "ljmp *%%cs:real_int15_vector\n\t" )
+ : : "i" ( sizeof ( e820map ) ) );
+
+ hook_bios_interrupt ( 0x15, ( unsigned int ) int15_fakee820,
+ &real_int15_vector );
+}
+
+void unfake_e820 ( void ) {
+ unhook_bios_interrupt ( 0x15, ( unsigned int ) int15_fakee820,
+ &real_int15_vector );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/hidemem.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/hidemem.c
new file mode 100644
index 00000000..cc5fc28f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/hidemem.c
@@ -0,0 +1,220 @@
+/* Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <assert.h>
+#include <realmode.h>
+#include <biosint.h>
+#include <basemem.h>
+#include <fakee820.h>
+#include <ipxe/init.h>
+#include <ipxe/io.h>
+#include <ipxe/hidemem.h>
+
+/** Set to true if you want to test a fake E820 map */
+#define FAKE_E820 0
+
+/** Alignment for hidden memory regions */
+#define ALIGN_HIDDEN 4096 /* 4kB page alignment should be enough */
+
+/**
+ * A hidden region of iPXE
+ *
+ * This represents a region that will be edited out of the system's
+ * memory map.
+ *
+ * This structure is accessed by assembly code, so must not be
+ * changed.
+ */
+struct hidden_region {
+ /** Physical start address */
+ uint64_t start;
+ /** Physical end address */
+ uint64_t end;
+};
+
+/** Hidden base memory */
+extern struct hidden_region __data16 ( hidemem_base );
+#define hidemem_base __use_data16 ( hidemem_base )
+
+/** Hidden umalloc memory */
+extern struct hidden_region __data16 ( hidemem_umalloc );
+#define hidemem_umalloc __use_data16 ( hidemem_umalloc )
+
+/** Hidden text memory */
+extern struct hidden_region __data16 ( hidemem_textdata );
+#define hidemem_textdata __use_data16 ( hidemem_textdata )
+
+/** Assembly routine in e820mangler.S */
+extern void int15();
+
+/** Vector for storing original INT 15 handler */
+extern struct segoff __text16 ( int15_vector );
+#define int15_vector __use_text16 ( int15_vector )
+
+/* The linker defines these symbols for us */
+extern char _textdata[];
+extern char _etextdata[];
+extern char _text16_memsz[];
+#define _text16_memsz ( ( unsigned int ) _text16_memsz )
+extern char _data16_memsz[];
+#define _data16_memsz ( ( unsigned int ) _data16_memsz )
+
+/**
+ * Hide region of memory from system memory map
+ *
+ * @v region Hidden memory region
+ * @v start Start of region
+ * @v end End of region
+ */
+static void hide_region ( struct hidden_region *region,
+ physaddr_t start, physaddr_t end ) {
+
+ /* Some operating systems get a nasty shock if a region of the
+ * E820 map seems to start on a non-page boundary. Make life
+ * safer by rounding out our edited region.
+ */
+ region->start = ( start & ~( ALIGN_HIDDEN - 1 ) );
+ region->end = ( ( end + ALIGN_HIDDEN - 1 ) & ~( ALIGN_HIDDEN - 1 ) );
+
+ DBG ( "Hiding region [%llx,%llx)\n", region->start, region->end );
+}
+
+/**
+ * Hide used base memory
+ *
+ */
+void hide_basemem ( void ) {
+ /* Hide from the top of free base memory to 640kB. Don't use
+ * hide_region(), because we don't want this rounded to the
+ * nearest page boundary.
+ */
+ hidemem_base.start = ( get_fbms() * 1024 );
+}
+
+/**
+ * Hide umalloc() region
+ *
+ */
+void hide_umalloc ( physaddr_t start, physaddr_t end ) {
+ assert ( end <= virt_to_phys ( _textdata ) );
+ hide_region ( &hidemem_umalloc, start, end );
+}
+
+/**
+ * Hide .text and .data
+ *
+ */
+void hide_textdata ( void ) {
+ hide_region ( &hidemem_textdata, virt_to_phys ( _textdata ),
+ virt_to_phys ( _etextdata ) );
+}
+
+/**
+ * Hide Etherboot
+ *
+ * Installs an INT 15 handler to edit Etherboot out of the memory map
+ * returned by the BIOS.
+ */
+static void hide_etherboot ( void ) {
+ struct memory_map memmap;
+ unsigned int rm_ds_top;
+ unsigned int rm_cs_top;
+ unsigned int fbms;
+
+ /* Dump memory map before mangling */
+ DBG ( "Hiding iPXE from system memory map\n" );
+ get_memmap ( &memmap );
+
+ /* Hook in fake E820 map, if we're testing one */
+ if ( FAKE_E820 ) {
+ DBG ( "Hooking in fake E820 map\n" );
+ fake_e820();
+ get_memmap ( &memmap );
+ }
+
+ /* Initialise the hidden regions */
+ hide_basemem();
+ hide_umalloc ( virt_to_phys ( _textdata ), virt_to_phys ( _textdata ) );
+ hide_textdata();
+
+ /* Some really moronic BIOSes bring up the PXE stack via the
+ * UNDI loader entry point and then don't bother to unload it
+ * before overwriting the code and data segments. If this
+ * happens, we really don't want to leave INT 15 hooked,
+ * because that will cause any loaded OS to die horribly as
+ * soon as it attempts to fetch the system memory map.
+ *
+ * We use a heuristic to guess whether or not we are being
+ * loaded sensibly.
+ */
+ rm_cs_top = ( ( ( rm_cs << 4 ) + _text16_memsz + 1024 - 1 ) >> 10 );
+ rm_ds_top = ( ( ( rm_ds << 4 ) + _data16_memsz + 1024 - 1 ) >> 10 );
+ fbms = get_fbms();
+ if ( ( rm_cs_top < fbms ) && ( rm_ds_top < fbms ) ) {
+ DBG ( "Detected potentially unsafe UNDI load at CS=%04x "
+ "DS=%04x FBMS=%dkB\n", rm_cs, rm_ds, fbms );
+ DBG ( "Disabling INT 15 memory hiding\n" );
+ return;
+ }
+
+ /* Hook INT 15 */
+ hook_bios_interrupt ( 0x15, ( unsigned int ) int15,
+ &int15_vector );
+
+ /* Dump memory map after mangling */
+ DBG ( "Hidden iPXE from system memory map\n" );
+ get_memmap ( &memmap );
+}
+
+/**
+ * Unhide Etherboot
+ *
+ * Uninstalls the INT 15 handler installed by hide_etherboot(), if
+ * possible.
+ */
+static void unhide_etherboot ( int flags __unused ) {
+
+ /* If we have more than one hooked interrupt at this point, it
+ * means that some other vector is still hooked, in which case
+ * we can't safely unhook INT 15 because we need to keep our
+ * memory protected. (We expect there to be at least one
+ * hooked interrupt, because INT 15 itself is still hooked).
+ */
+ if ( hooked_bios_interrupts > 1 ) {
+ DBG ( "Cannot unhide: %d interrupt vectors still hooked\n",
+ hooked_bios_interrupts );
+ return;
+ }
+
+ /* Try to unhook INT 15. If it fails, then just leave it
+ * hooked; it takes care of protecting itself. :)
+ */
+ unhook_bios_interrupt ( 0x15, ( unsigned int ) int15,
+ &int15_vector );
+
+ /* Unhook fake E820 map, if used */
+ if ( FAKE_E820 )
+ unfake_e820();
+}
+
+/** Hide Etherboot startup function */
+struct startup_fn hide_etherboot_startup_fn __startup_fn ( STARTUP_EARLY ) = {
+ .startup = hide_etherboot,
+ .shutdown = unhide_etherboot,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/memmap.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/memmap.c
new file mode 100644
index 00000000..493d2c20
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/memmap.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <errno.h>
+#include <realmode.h>
+#include <bios.h>
+#include <memsizes.h>
+#include <ipxe/io.h>
+
+/**
+ * @file
+ *
+ * Memory mapping
+ *
+ */
+
+/** Magic value for INT 15,e820 calls */
+#define SMAP ( 0x534d4150 )
+
+/** An INT 15,e820 memory map entry */
+struct e820_entry {
+ /** Start of region */
+ uint64_t start;
+ /** Length of region */
+ uint64_t len;
+ /** Type of region */
+ uint32_t type;
+ /** Extended attributes (optional) */
+ uint32_t attrs;
+} __attribute__ (( packed ));
+
+#define E820_TYPE_RAM 1 /**< Normal memory */
+#define E820_TYPE_RESERVED 2 /**< Reserved and unavailable */
+#define E820_TYPE_ACPI 3 /**< ACPI reclaim memory */
+#define E820_TYPE_NVS 4 /**< ACPI NVS memory */
+
+#define E820_ATTR_ENABLED 0x00000001UL
+#define E820_ATTR_NONVOLATILE 0x00000002UL
+#define E820_ATTR_UNKNOWN 0xfffffffcUL
+
+#define E820_MIN_SIZE 20
+
+/** Buffer for INT 15,e820 calls */
+static struct e820_entry __bss16 ( e820buf );
+#define e820buf __use_data16 ( e820buf )
+
+/**
+ * Get size of extended memory via INT 15,e801
+ *
+ * @ret extmem Extended memory size, in kB, or 0
+ */
+static unsigned int extmemsize_e801 ( void ) {
+ uint16_t extmem_1m_to_16m_k, extmem_16m_plus_64k;
+ uint16_t confmem_1m_to_16m_k, confmem_16m_plus_64k;
+ unsigned int flags;
+ unsigned int extmem;
+
+ __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
+ "int $0x15\n\t"
+ "pushfw\n\t"
+ "popw %w0\n\t" )
+ : "=r" ( flags ),
+ "=a" ( extmem_1m_to_16m_k ),
+ "=b" ( extmem_16m_plus_64k ),
+ "=c" ( confmem_1m_to_16m_k ),
+ "=d" ( confmem_16m_plus_64k )
+ : "a" ( 0xe801 ) );
+
+ if ( flags & CF ) {
+ DBG ( "INT 15,e801 failed with CF set\n" );
+ return 0;
+ }
+
+ if ( ! ( extmem_1m_to_16m_k | extmem_16m_plus_64k ) ) {
+ DBG ( "INT 15,e801 extmem=0, using confmem\n" );
+ extmem_1m_to_16m_k = confmem_1m_to_16m_k;
+ extmem_16m_plus_64k = confmem_16m_plus_64k;
+ }
+
+ extmem = ( extmem_1m_to_16m_k + ( extmem_16m_plus_64k * 64 ) );
+ DBG ( "INT 15,e801 extended memory size %d+64*%d=%d kB "
+ "[100000,%llx)\n", extmem_1m_to_16m_k, extmem_16m_plus_64k,
+ extmem, ( 0x100000 + ( ( ( uint64_t ) extmem ) * 1024 ) ) );
+
+ /* Sanity check. Some BIOSes report the entire 4GB address
+ * space as available, which cannot be correct (since that
+ * would leave no address space available for 32-bit PCI
+ * BARs).
+ */
+ if ( extmem == ( 0x400000 - 0x400 ) ) {
+ DBG ( "INT 15,e801 reported whole 4GB; assuming insane\n" );
+ return 0;
+ }
+
+ return extmem;
+}
+
+/**
+ * Get size of extended memory via INT 15,88
+ *
+ * @ret extmem Extended memory size, in kB
+ */
+static unsigned int extmemsize_88 ( void ) {
+ uint16_t extmem;
+
+ /* Ignore CF; it is not reliable for this call */
+ __asm__ __volatile__ ( REAL_CODE ( "int $0x15" )
+ : "=a" ( extmem ) : "a" ( 0x8800 ) );
+
+ DBG ( "INT 15,88 extended memory size %d kB [100000, %x)\n",
+ extmem, ( 0x100000 + ( extmem * 1024 ) ) );
+ return extmem;
+}
+
+/**
+ * Get size of extended memory
+ *
+ * @ret extmem Extended memory size, in kB
+ *
+ * Note that this is only an approximation; for an accurate picture,
+ * use the E820 memory map obtained via get_memmap();
+ */
+unsigned int extmemsize ( void ) {
+ unsigned int extmem_e801;
+ unsigned int extmem_88;
+
+ /* Try INT 15,e801 first, then fall back to INT 15,88 */
+ extmem_88 = extmemsize_88();
+ extmem_e801 = extmemsize_e801();
+ return ( extmem_e801 ? extmem_e801 : extmem_88 );
+}
+
+/**
+ * Get e820 memory map
+ *
+ * @v memmap Memory map to fill in
+ * @ret rc Return status code
+ */
+static int meme820 ( struct memory_map *memmap ) {
+ struct memory_region *region = memmap->regions;
+ struct memory_region *prev_region = NULL;
+ uint32_t next = 0;
+ uint32_t smap;
+ size_t size;
+ unsigned int flags;
+ unsigned int discard_D;
+
+ /* Clear the E820 buffer. Do this once before starting,
+ * rather than on each call; some BIOSes rely on the contents
+ * being preserved between calls.
+ */
+ memset ( &e820buf, 0, sizeof ( e820buf ) );
+
+ do {
+ /* Some BIOSes corrupt %esi for fun. Guard against
+ * this by telling gcc that all non-output registers
+ * may be corrupted.
+ */
+ __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t"
+ "stc\n\t"
+ "int $0x15\n\t"
+ "pushfw\n\t"
+ "popw %%dx\n\t"
+ "popl %%ebp\n\t" )
+ : "=a" ( smap ), "=b" ( next ),
+ "=c" ( size ), "=d" ( flags ),
+ "=D" ( discard_D )
+ : "a" ( 0xe820 ), "b" ( next ),
+ "D" ( __from_data16 ( &e820buf ) ),
+ "c" ( sizeof ( e820buf ) ),
+ "d" ( SMAP )
+ : "esi", "memory" );
+
+ if ( smap != SMAP ) {
+ DBG ( "INT 15,e820 failed SMAP signature check\n" );
+ return -ENOTSUP;
+ }
+
+ if ( size < E820_MIN_SIZE ) {
+ DBG ( "INT 15,e820 returned only %zd bytes\n", size );
+ return -EINVAL;
+ }
+
+ if ( flags & CF ) {
+ DBG ( "INT 15,e820 terminated on CF set\n" );
+ break;
+ }
+
+ /* If first region is not RAM, assume map is invalid */
+ if ( ( memmap->count == 0 ) &&
+ ( e820buf.type != E820_TYPE_RAM ) ) {
+ DBG ( "INT 15,e820 failed, first entry not RAM\n" );
+ return -EINVAL;
+ }
+
+ DBG ( "INT 15,e820 region [%llx,%llx) type %d",
+ e820buf.start, ( e820buf.start + e820buf.len ),
+ ( int ) e820buf.type );
+ if ( size > offsetof ( typeof ( e820buf ), attrs ) ) {
+ DBG ( " (%s", ( ( e820buf.attrs & E820_ATTR_ENABLED )
+ ? "enabled" : "disabled" ) );
+ if ( e820buf.attrs & E820_ATTR_NONVOLATILE )
+ DBG ( ", non-volatile" );
+ if ( e820buf.attrs & E820_ATTR_UNKNOWN )
+ DBG ( ", other [%08x]", e820buf.attrs );
+ DBG ( ")" );
+ }
+ DBG ( "\n" );
+
+ /* Discard non-RAM regions */
+ if ( e820buf.type != E820_TYPE_RAM )
+ continue;
+
+ /* Check extended attributes, if present */
+ if ( size > offsetof ( typeof ( e820buf ), attrs ) ) {
+ if ( ! ( e820buf.attrs & E820_ATTR_ENABLED ) )
+ continue;
+ if ( e820buf.attrs & E820_ATTR_NONVOLATILE )
+ continue;
+ }
+
+ region->start = e820buf.start;
+ region->end = e820buf.start + e820buf.len;
+
+ /* Check for adjacent regions and merge them */
+ if ( prev_region && ( region->start == prev_region->end ) ) {
+ prev_region->end = region->end;
+ } else {
+ prev_region = region;
+ region++;
+ memmap->count++;
+ }
+
+ if ( memmap->count >= ( sizeof ( memmap->regions ) /
+ sizeof ( memmap->regions[0] ) ) ) {
+ DBG ( "INT 15,e820 too many regions returned\n" );
+ /* Not a fatal error; what we've got so far at
+ * least represents valid regions of memory,
+ * even if we couldn't get them all.
+ */
+ break;
+ }
+ } while ( next != 0 );
+
+ /* Sanity checks. Some BIOSes report complete garbage via INT
+ * 15,e820 (especially at POST time), despite passing the
+ * signature checks. We currently check for a base memory
+ * region (starting at 0) and at least one high memory region
+ * (starting at 0x100000).
+ */
+ if ( memmap->count < 2 ) {
+ DBG ( "INT 15,e820 returned only %d regions; assuming "
+ "insane\n", memmap->count );
+ return -EINVAL;
+ }
+ if ( memmap->regions[0].start != 0 ) {
+ DBG ( "INT 15,e820 region 0 starts at %llx (expected 0); "
+ "assuming insane\n", memmap->regions[0].start );
+ return -EINVAL;
+ }
+ if ( memmap->regions[1].start != 0x100000 ) {
+ DBG ( "INT 15,e820 region 1 starts at %llx (expected 100000); "
+ "assuming insane\n", memmap->regions[0].start );
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * Get memory map
+ *
+ * @v memmap Memory map to fill in
+ */
+void x86_get_memmap ( struct memory_map *memmap ) {
+ unsigned int basemem, extmem;
+ int rc;
+
+ DBG ( "Fetching system memory map\n" );
+
+ /* Clear memory map */
+ memset ( memmap, 0, sizeof ( *memmap ) );
+
+ /* Get base and extended memory sizes */
+ basemem = basememsize();
+ DBG ( "FBMS base memory size %d kB [0,%x)\n",
+ basemem, ( basemem * 1024 ) );
+ extmem = extmemsize();
+
+ /* Try INT 15,e820 first */
+ if ( ( rc = meme820 ( memmap ) ) == 0 ) {
+ DBG ( "Obtained system memory map via INT 15,e820\n" );
+ return;
+ }
+
+ /* Fall back to constructing a map from basemem and extmem sizes */
+ DBG ( "INT 15,e820 failed; constructing map\n" );
+ memmap->regions[0].end = ( basemem * 1024 );
+ memmap->regions[1].start = 0x100000;
+ memmap->regions[1].end = 0x100000 + ( extmem * 1024 );
+ memmap->count = 2;
+}
+
+PROVIDE_IOAPI ( x86, get_memmap, x86_get_memmap );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c
new file mode 100644
index 00000000..c572914f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <realmode.h>
+#include <pnpbios.h>
+
+/** @file
+ *
+ * PnP BIOS
+ *
+ */
+
+/** PnP BIOS structure */
+struct pnp_bios {
+ /** Signature
+ *
+ * Must be equal to @c PNP_BIOS_SIGNATURE
+ */
+ uint32_t signature;
+ /** Version as BCD (e.g. 1.0 is 0x10) */
+ uint8_t version;
+ /** Length of this structure */
+ uint8_t length;
+ /** System capabilities */
+ uint16_t control;
+ /** Checksum */
+ uint8_t checksum;
+} __attribute__ (( packed ));
+
+/** Signature for a PnP BIOS structure */
+#define PNP_BIOS_SIGNATURE \
+ ( ( '$' << 0 ) + ( 'P' << 8 ) + ( 'n' << 16 ) + ( 'P' << 24 ) )
+
+/**
+ * Test address for PnP BIOS structure
+ *
+ * @v offset Offset within BIOS segment to test
+ * @ret rc Return status code
+ */
+static int is_pnp_bios ( unsigned int offset ) {
+ union {
+ struct pnp_bios pnp_bios;
+ uint8_t bytes[256]; /* 256 is maximum length possible */
+ } u;
+ size_t len;
+ unsigned int i;
+ uint8_t sum = 0;
+
+ /* Read start of header and verify signature */
+ copy_from_real ( &u.pnp_bios, BIOS_SEG, offset, sizeof ( u.pnp_bios ));
+ if ( u.pnp_bios.signature != PNP_BIOS_SIGNATURE )
+ return -EINVAL;
+
+ /* Read whole header and verify checksum */
+ len = u.pnp_bios.length;
+ copy_from_real ( &u.bytes, BIOS_SEG, offset, len );
+ for ( i = 0 ; i < len ; i++ ) {
+ sum += u.bytes[i];
+ }
+ if ( sum != 0 )
+ return -EINVAL;
+
+ DBG ( "Found PnP BIOS at %04x:%04x\n", BIOS_SEG, offset );
+
+ return 0;
+}
+
+/**
+ * Locate Plug-and-Play BIOS
+ *
+ * @ret pnp_offset Offset of PnP BIOS structure within BIOS segment
+ *
+ * The PnP BIOS structure will be at BIOS_SEG:pnp_offset. If no PnP
+ * BIOS is found, -1 is returned.
+ */
+int find_pnp_bios ( void ) {
+ static int pnp_offset = 0;
+
+ if ( pnp_offset )
+ return pnp_offset;
+
+ for ( pnp_offset = 0 ; pnp_offset < 0x10000 ; pnp_offset += 0x10 ) {
+ if ( is_pnp_bios ( pnp_offset ) == 0 )
+ return pnp_offset;
+ }
+
+ pnp_offset = -1;
+ return pnp_offset;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/hci/commands/pxe_cmd.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/hci/commands/pxe_cmd.c
new file mode 100644
index 00000000..79585cde
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/hci/commands/pxe_cmd.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <ipxe/netdevice.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <hci/ifmgmt_cmd.h>
+#include <pxe_call.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * PXE commands
+ *
+ */
+
+/** "startpxe" command descriptor */
+static struct command_descriptor startpxe_cmd =
+ COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
+ "[<interface>]" );
+
+/**
+ * "startpxe" payload
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int startpxe_payload ( struct net_device *netdev ) {
+
+ if ( netdev_is_open ( netdev ) )
+ pxe_activate ( netdev );
+
+ return 0;
+}
+
+/**
+ * The "startpxe" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int startpxe_exec ( int argc, char **argv ) {
+ return ifcommon_exec ( argc, argv, &startpxe_cmd, startpxe_payload, 0 );
+}
+
+/** "stoppxe" options */
+struct stoppxe_options {};
+
+/** "stoppxe" option list */
+static struct option_descriptor stoppxe_opts[] = {};
+
+/** "stoppxe" command descriptor */
+static struct command_descriptor stoppxe_cmd =
+ COMMAND_DESC ( struct stoppxe_options, stoppxe_opts, 0, 0, "" );
+
+/**
+ * The "stoppxe" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int stoppxe_exec ( int argc __unused, char **argv __unused ) {
+ struct stoppxe_options opts;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &stoppxe_cmd, &opts ) ) != 0 )
+ return rc;
+
+ pxe_deactivate();
+
+ return 0;
+}
+
+/** PXE commands */
+struct command pxe_commands[] __command = {
+ {
+ .name = "startpxe",
+ .exec = startpxe_exec,
+ },
+ {
+ .name = "stoppxe",
+ .exec = stoppxe_exec,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/hci/commands/reboot_cmd.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/hci/commands/reboot_cmd.c
new file mode 100644
index 00000000..d6a1d9a3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/hci/commands/reboot_cmd.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <realmode.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Reboot command
+ *
+ */
+
+/** "reboot" options */
+struct reboot_options {};
+
+/** "reboot" option list */
+static struct option_descriptor reboot_opts[] = {};
+
+/** "reboot" command descriptor */
+static struct command_descriptor reboot_cmd =
+ COMMAND_DESC ( struct reboot_options, reboot_opts, 0, 0, "" );
+
+/**
+ * The "reboot" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int reboot_exec ( int argc, char **argv ) {
+ struct reboot_options opts;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &reboot_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Reboot system */
+ __asm__ __volatile__ ( REAL_CODE ( "ljmp $0xf000, $0xfff0" ) : : );
+
+ return 0;
+}
+
+/** "reboot" command */
+struct command reboot_command __command = {
+ .name = "reboot",
+ .exec = reboot_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/image/bootsector.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/bootsector.c
new file mode 100644
index 00000000..16a66d83
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/bootsector.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * x86 bootsector image format
+ *
+ */
+
+#include <errno.h>
+#include <realmode.h>
+#include <biosint.h>
+#include <bootsector.h>
+
+/** Vector for storing original INT 18 handler
+ *
+ * We do not chain to this vector, so there is no need to place it in
+ * .text16.
+ */
+static struct segoff int18_vector;
+
+/** Vector for storing original INT 19 handler
+ *
+ * We do not chain to this vector, so there is no need to place it in
+ * .text16.
+ */
+static struct segoff int19_vector;
+
+/** Restart point for INT 18 or 19 */
+extern void bootsector_exec_fail ( void );
+
+/**
+ * Jump to preloaded bootsector
+ *
+ * @v segment Real-mode segment
+ * @v offset Real-mode offset
+ * @v drive Drive number to pass to boot sector
+ * @ret rc Return status code
+ */
+int call_bootsector ( unsigned int segment, unsigned int offset,
+ unsigned int drive ) {
+ int discard_b, discard_D, discard_d;
+
+ DBG ( "Booting from boot sector at %04x:%04x\n", segment, offset );
+
+ /* Hook INTs 18 and 19 to capture failure paths */
+ hook_bios_interrupt ( 0x18, ( unsigned int ) bootsector_exec_fail,
+ &int18_vector );
+ hook_bios_interrupt ( 0x19, ( unsigned int ) bootsector_exec_fail,
+ &int19_vector );
+
+ /* Boot the loaded sector
+ *
+ * We assume that the boot sector may completely destroy our
+ * real-mode stack, so we preserve everything we need in
+ * static storage.
+ */
+ __asm__ __volatile__ ( REAL_CODE ( /* Save return address off-stack */
+ "popw %%cs:saved_retaddr\n\t"
+ /* Save stack pointer */
+ "movw %%ss, %%ax\n\t"
+ "movw %%ax, %%cs:saved_ss\n\t"
+ "movw %%sp, %%cs:saved_sp\n\t"
+ /* Save frame pointer (gcc bug) */
+ "movl %%ebp, %%cs:saved_ebp\n\t"
+ /* Prepare jump to boot sector */
+ "pushw %%bx\n\t"
+ "pushw %%di\n\t"
+ "sti\n\t"
+ "lret\n\t"
+ /* Preserved variables */
+ "\nsaved_ebp: .long 0\n\t"
+ "\nsaved_ss: .word 0\n\t"
+ "\nsaved_sp: .word 0\n\t"
+ "\nsaved_retaddr: .word 0\n\t"
+ /* Boot failure return point */
+ "\nbootsector_exec_fail:\n\t"
+ /* Restore frame pointer (gcc bug) */
+ "movl %%cs:saved_ebp, %%ebp\n\t"
+ /* Restore stack pointer */
+ "movw %%cs:saved_ss, %%ax\n\t"
+ "movw %%ax, %%ss\n\t"
+ "movw %%cs:saved_sp, %%sp\n\t"
+ /* Return via saved address */
+ "jmp *%%cs:saved_retaddr\n\t" )
+ : "=b" ( discard_b ), "=D" ( discard_D ),
+ "=d" ( discard_d )
+ : "b" ( segment ), "D" ( offset ),
+ "d" ( drive )
+ : "eax", "ecx", "esi" );
+
+ DBG ( "Booted disk returned via INT 18 or 19\n" );
+
+ /* Unhook INTs 18 and 19 */
+ unhook_bios_interrupt ( 0x18, ( unsigned int ) bootsector_exec_fail,
+ &int18_vector );
+ unhook_bios_interrupt ( 0x19, ( unsigned int ) bootsector_exec_fail,
+ &int19_vector );
+
+ return -ECANCELED;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/image/bzimage.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/bzimage.c
new file mode 100644
index 00000000..cc7aecab
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/bzimage.c
@@ -0,0 +1,551 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Linux bzImage image format
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <realmode.h>
+#include <bzimage.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/image.h>
+#include <ipxe/segment.h>
+#include <ipxe/init.h>
+#include <ipxe/cpio.h>
+#include <ipxe/features.h>
+
+FEATURE ( FEATURE_IMAGE, "bzImage", DHCP_EB_FEATURE_BZIMAGE, 1 );
+
+/**
+ * bzImage context
+ */
+struct bzimage_context {
+ /** Boot protocol version */
+ unsigned int version;
+ /** Real-mode kernel portion load segment address */
+ unsigned int rm_kernel_seg;
+ /** Real-mode kernel portion load address */
+ userptr_t rm_kernel;
+ /** Real-mode kernel portion file size */
+ size_t rm_filesz;
+ /** Real-mode heap top (offset from rm_kernel) */
+ size_t rm_heap;
+ /** Command line (offset from rm_kernel) */
+ size_t rm_cmdline;
+ /** Command line maximum length */
+ size_t cmdline_size;
+ /** Real-mode kernel portion total memory size */
+ size_t rm_memsz;
+ /** Non-real-mode kernel portion load address */
+ userptr_t pm_kernel;
+ /** Non-real-mode kernel portion file and memory size */
+ size_t pm_sz;
+ /** Video mode */
+ unsigned int vid_mode;
+ /** Memory limit */
+ uint64_t mem_limit;
+ /** Initrd address */
+ physaddr_t ramdisk_image;
+ /** Initrd size */
+ physaddr_t ramdisk_size;
+
+ /** Command line magic block */
+ struct bzimage_cmdline cmdline_magic;
+ /** bzImage header */
+ struct bzimage_header bzhdr;
+};
+
+/**
+ * Parse bzImage header
+ *
+ * @v image bzImage file
+ * @v bzimg bzImage context
+ * @v src bzImage to parse
+ * @ret rc Return status code
+ */
+static int bzimage_parse_header ( struct image *image,
+ struct bzimage_context *bzimg,
+ userptr_t src ) {
+ unsigned int syssize;
+ int is_bzimage;
+
+ /* Sanity check */
+ if ( image->len < ( BZI_HDR_OFFSET + sizeof ( bzimg->bzhdr ) ) ) {
+ DBGC ( image, "bzImage %p too short for kernel header\n",
+ image );
+ return -ENOEXEC;
+ }
+
+ /* Read in header structures */
+ memset ( bzimg, 0, sizeof ( *bzimg ) );
+ copy_from_user ( &bzimg->cmdline_magic, src, BZI_CMDLINE_OFFSET,
+ sizeof ( bzimg->cmdline_magic ) );
+ copy_from_user ( &bzimg->bzhdr, src, BZI_HDR_OFFSET,
+ sizeof ( bzimg->bzhdr ) );
+
+ /* Calculate size of real-mode portion */
+ bzimg->rm_filesz = ( ( ( bzimg->bzhdr.setup_sects ?
+ bzimg->bzhdr.setup_sects : 4 ) + 1 ) << 9 );
+ if ( bzimg->rm_filesz > image->len ) {
+ DBGC ( image, "bzImage %p too short for %zd byte of setup\n",
+ image, bzimg->rm_filesz );
+ return -ENOEXEC;
+ }
+ bzimg->rm_memsz = BZI_ASSUMED_RM_SIZE;
+
+ /* Calculate size of protected-mode portion */
+ bzimg->pm_sz = ( image->len - bzimg->rm_filesz );
+ syssize = ( ( bzimg->pm_sz + 15 ) / 16 );
+
+ /* Check for signatures and determine version */
+ if ( bzimg->bzhdr.boot_flag != BZI_BOOT_FLAG ) {
+ DBGC ( image, "bzImage %p missing 55AA signature\n", image );
+ return -ENOEXEC;
+ }
+ if ( bzimg->bzhdr.header == BZI_SIGNATURE ) {
+ /* 2.00+ */
+ bzimg->version = bzimg->bzhdr.version;
+ } else {
+ /* Pre-2.00. Check that the syssize field is correct,
+ * as a guard against accepting arbitrary binary data,
+ * since the 55AA check is pretty lax. Note that the
+ * syssize field is unreliable for protocols between
+ * 2.00 and 2.03 inclusive, so we should not always
+ * check this field.
+ */
+ bzimg->version = 0x0100;
+ if ( bzimg->bzhdr.syssize != syssize ) {
+ DBGC ( image, "bzImage %p bad syssize %x (expected "
+ "%x)\n", image, bzimg->bzhdr.syssize, syssize );
+ return -ENOEXEC;
+ }
+ }
+
+ /* Determine image type */
+ is_bzimage = ( ( bzimg->version >= 0x0200 ) ?
+ ( bzimg->bzhdr.loadflags & BZI_LOAD_HIGH ) : 0 );
+
+ /* Calculate load address of real-mode portion */
+ bzimg->rm_kernel_seg = ( is_bzimage ? 0x1000 : 0x9000 );
+ bzimg->rm_kernel = real_to_user ( bzimg->rm_kernel_seg, 0 );
+
+ /* Allow space for the stack and heap */
+ bzimg->rm_memsz += BZI_STACK_SIZE;
+ bzimg->rm_heap = bzimg->rm_memsz;
+
+ /* Allow space for the command line */
+ bzimg->rm_cmdline = bzimg->rm_memsz;
+ bzimg->rm_memsz += BZI_CMDLINE_SIZE;
+
+ /* Calculate load address of protected-mode portion */
+ bzimg->pm_kernel = phys_to_user ( is_bzimage ? BZI_LOAD_HIGH_ADDR
+ : BZI_LOAD_LOW_ADDR );
+
+ /* Extract video mode */
+ bzimg->vid_mode = bzimg->bzhdr.vid_mode;
+
+ /* Extract memory limit */
+ bzimg->mem_limit = ( ( bzimg->version >= 0x0203 ) ?
+ bzimg->bzhdr.initrd_addr_max : BZI_INITRD_MAX );
+
+ /* Extract command line size */
+ bzimg->cmdline_size = ( ( bzimg->version >= 0x0206 ) ?
+ bzimg->bzhdr.cmdline_size : BZI_CMDLINE_SIZE );
+
+ DBGC ( image, "bzImage %p version %04x RM %#lx+%#zx PM %#lx+%#zx "
+ "cmdlen %zd\n", image, bzimg->version,
+ user_to_phys ( bzimg->rm_kernel, 0 ), bzimg->rm_filesz,
+ user_to_phys ( bzimg->pm_kernel, 0 ), bzimg->pm_sz,
+ bzimg->cmdline_size );
+
+ return 0;
+}
+
+/**
+ * Update bzImage header in loaded kernel
+ *
+ * @v image bzImage file
+ * @v bzimg bzImage context
+ * @v dst bzImage to update
+ */
+static void bzimage_update_header ( struct image *image,
+ struct bzimage_context *bzimg,
+ userptr_t dst ) {
+
+ /* Set loader type */
+ if ( bzimg->version >= 0x0200 )
+ bzimg->bzhdr.type_of_loader = BZI_LOADER_TYPE_IPXE;
+
+ /* Set heap end pointer */
+ if ( bzimg->version >= 0x0201 ) {
+ bzimg->bzhdr.heap_end_ptr = ( bzimg->rm_heap - 0x200 );
+ bzimg->bzhdr.loadflags |= BZI_CAN_USE_HEAP;
+ }
+
+ /* Set command line */
+ if ( bzimg->version >= 0x0202 ) {
+ bzimg->bzhdr.cmd_line_ptr = user_to_phys ( bzimg->rm_kernel,
+ bzimg->rm_cmdline );
+ } else {
+ bzimg->cmdline_magic.magic = BZI_CMDLINE_MAGIC;
+ bzimg->cmdline_magic.offset = bzimg->rm_cmdline;
+ bzimg->bzhdr.setup_move_size = bzimg->rm_memsz;
+ }
+
+ /* Set video mode */
+ bzimg->bzhdr.vid_mode = bzimg->vid_mode;
+
+ /* Set initrd address */
+ if ( bzimg->version >= 0x0200 ) {
+ bzimg->bzhdr.ramdisk_image = bzimg->ramdisk_image;
+ bzimg->bzhdr.ramdisk_size = bzimg->ramdisk_size;
+ }
+
+ /* Write out header structures */
+ copy_to_user ( dst, BZI_CMDLINE_OFFSET, &bzimg->cmdline_magic,
+ sizeof ( bzimg->cmdline_magic ) );
+ copy_to_user ( dst, BZI_HDR_OFFSET, &bzimg->bzhdr,
+ sizeof ( bzimg->bzhdr ) );
+
+ DBGC ( image, "bzImage %p vidmode %d\n", image, bzimg->vid_mode );
+}
+
+/**
+ * Parse kernel command line for bootloader parameters
+ *
+ * @v image bzImage file
+ * @v bzimg bzImage context
+ * @v cmdline Kernel command line
+ * @ret rc Return status code
+ */
+static int bzimage_parse_cmdline ( struct image *image,
+ struct bzimage_context *bzimg,
+ const char *cmdline ) {
+ char *vga;
+ char *mem;
+
+ /* Look for "vga=" */
+ if ( ( vga = strstr ( cmdline, "vga=" ) ) ) {
+ vga += 4;
+ if ( strcmp ( vga, "normal" ) == 0 ) {
+ bzimg->vid_mode = BZI_VID_MODE_NORMAL;
+ } else if ( strcmp ( vga, "ext" ) == 0 ) {
+ bzimg->vid_mode = BZI_VID_MODE_EXT;
+ } else if ( strcmp ( vga, "ask" ) == 0 ) {
+ bzimg->vid_mode = BZI_VID_MODE_ASK;
+ } else {
+ bzimg->vid_mode = strtoul ( vga, &vga, 0 );
+ if ( *vga && ( *vga != ' ' ) ) {
+ DBGC ( image, "bzImage %p strange \"vga=\""
+ "terminator '%c'\n", image, *vga );
+ }
+ }
+ }
+
+ /* Look for "mem=" */
+ if ( ( mem = strstr ( cmdline, "mem=" ) ) ) {
+ mem += 4;
+ bzimg->mem_limit = strtoul ( mem, &mem, 0 );
+ switch ( *mem ) {
+ case 'G':
+ case 'g':
+ bzimg->mem_limit <<= 10;
+ case 'M':
+ case 'm':
+ bzimg->mem_limit <<= 10;
+ case 'K':
+ case 'k':
+ bzimg->mem_limit <<= 10;
+ break;
+ case '\0':
+ case ' ':
+ break;
+ default:
+ DBGC ( image, "bzImage %p strange \"mem=\" "
+ "terminator '%c'\n", image, *mem );
+ break;
+ }
+ bzimg->mem_limit -= 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Set command line
+ *
+ * @v image bzImage image
+ * @v bzimg bzImage context
+ * @v cmdline Kernel command line
+ * @ret rc Return status code
+ */
+static int bzimage_set_cmdline ( struct image *image,
+ struct bzimage_context *bzimg,
+ const char *cmdline ) {
+ size_t cmdline_len;
+
+ /* Copy command line down to real-mode portion */
+ cmdline_len = ( strlen ( cmdline ) + 1 );
+ if ( cmdline_len > bzimg->cmdline_size )
+ cmdline_len = bzimg->cmdline_size;
+ copy_to_user ( bzimg->rm_kernel, bzimg->rm_cmdline,
+ cmdline, cmdline_len );
+ DBGC ( image, "bzImage %p command line \"%s\"\n", image, cmdline );
+
+ return 0;
+}
+
+/**
+ * Load initrd
+ *
+ * @v image bzImage image
+ * @v initrd initrd image
+ * @v address Address at which to load, or UNULL
+ * @ret len Length of loaded image, rounded up to 4 bytes
+ */
+static size_t bzimage_load_initrd ( struct image *image,
+ struct image *initrd,
+ userptr_t address ) {
+ char *filename = initrd->cmdline;
+ struct cpio_header cpio;
+ size_t offset = 0;
+
+ /* Do not include kernel image itself as an initrd */
+ if ( initrd == image )
+ return 0;
+
+ /* Create cpio header before non-prebuilt images */
+ if ( filename && filename[0] ) {
+ size_t name_len = ( strlen ( filename ) + 1 );
+
+ DBGC ( image, "bzImage %p inserting initrd %p as %s\n",
+ image, initrd, filename );
+ memset ( &cpio, '0', sizeof ( cpio ) );
+ memcpy ( cpio.c_magic, CPIO_MAGIC, sizeof ( cpio.c_magic ) );
+ cpio_set_field ( cpio.c_mode, 0100644 );
+ cpio_set_field ( cpio.c_nlink, 1 );
+ cpio_set_field ( cpio.c_filesize, initrd->len );
+ cpio_set_field ( cpio.c_namesize, name_len );
+ if ( address ) {
+ copy_to_user ( address, offset, &cpio,
+ sizeof ( cpio ) );
+ }
+ offset += sizeof ( cpio );
+ if ( address ) {
+ copy_to_user ( address, offset, filename,
+ name_len );
+ }
+ offset += name_len;
+ offset = ( ( offset + 0x03 ) & ~0x03 );
+ }
+
+ /* Copy in initrd image body */
+ if ( address )
+ memcpy_user ( address, offset, initrd->data, 0, initrd->len );
+ offset += initrd->len;
+ if ( address ) {
+ DBGC ( image, "bzImage %p has initrd %p at [%lx,%lx)\n",
+ image, initrd, user_to_phys ( address, 0 ),
+ user_to_phys ( address, offset ) );
+ }
+
+ /* Round up to 4-byte boundary */
+ offset = ( ( offset + 0x03 ) & ~0x03 );
+ return offset;
+}
+
+/**
+ * Load initrds, if any
+ *
+ * @v image bzImage image
+ * @v bzimg bzImage context
+ * @ret rc Return status code
+ */
+static int bzimage_load_initrds ( struct image *image,
+ struct bzimage_context *bzimg ) {
+ struct image *initrd;
+ size_t total_len = 0;
+ physaddr_t address;
+ int rc;
+
+ /* Add up length of all initrd images */
+ for_each_image ( initrd )
+ total_len += bzimage_load_initrd ( image, initrd, UNULL );
+
+ /* Give up if no initrd images found */
+ if ( ! total_len )
+ return 0;
+
+ /* Find a suitable start address. Try 1MB boundaries,
+ * starting from the downloaded kernel image itself and
+ * working downwards until we hit an available region.
+ */
+ for ( address = ( user_to_phys ( image->data, 0 ) & ~0xfffff ) ; ;
+ address -= 0x100000 ) {
+ /* Check that we're not going to overwrite the
+ * kernel itself. This check isn't totally
+ * accurate, but errs on the side of caution.
+ */
+ if ( address <= ( BZI_LOAD_HIGH_ADDR + image->len ) ) {
+ DBGC ( image, "bzImage %p could not find a location "
+ "for initrd\n", image );
+ return -ENOBUFS;
+ }
+ /* Check that we are within the kernel's range */
+ if ( ( address + total_len - 1 ) > bzimg->mem_limit )
+ continue;
+ /* Prepare and verify segment */
+ if ( ( rc = prep_segment ( phys_to_user ( address ), 0,
+ total_len ) ) != 0 )
+ continue;
+ /* Use this address */
+ break;
+ }
+
+ /* Record initrd location */
+ bzimg->ramdisk_image = address;
+ bzimg->ramdisk_size = total_len;
+
+ /* Construct initrd */
+ DBGC ( image, "bzImage %p constructing initrd at [%lx,%lx)\n",
+ image, address, ( address + total_len ) );
+ for_each_image ( initrd ) {
+ address += bzimage_load_initrd ( image, initrd,
+ phys_to_user ( address ) );
+ }
+
+ return 0;
+}
+
+/**
+ * Execute bzImage image
+ *
+ * @v image bzImage image
+ * @ret rc Return status code
+ */
+static int bzimage_exec ( struct image *image ) {
+ struct bzimage_context bzimg;
+ const char *cmdline = ( image->cmdline ? image->cmdline : "" );
+ int rc;
+
+ /* Read and parse header from image */
+ if ( ( rc = bzimage_parse_header ( image, &bzimg,
+ image->data ) ) != 0 )
+ return rc;
+
+ /* Prepare segments */
+ if ( ( rc = prep_segment ( bzimg.rm_kernel, bzimg.rm_filesz,
+ bzimg.rm_memsz ) ) != 0 ) {
+ DBGC ( image, "bzImage %p could not prepare RM segment: %s\n",
+ image, strerror ( rc ) );
+ return rc;
+ }
+ if ( ( rc = prep_segment ( bzimg.pm_kernel, bzimg.pm_sz,
+ bzimg.pm_sz ) ) != 0 ) {
+ DBGC ( image, "bzImage %p could not prepare PM segment: %s\n",
+ image, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Load segments */
+ memcpy_user ( bzimg.rm_kernel, 0, image->data,
+ 0, bzimg.rm_filesz );
+ memcpy_user ( bzimg.pm_kernel, 0, image->data,
+ bzimg.rm_filesz, bzimg.pm_sz );
+
+ /* Update and write out header */
+ bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );
+
+ /* Parse command line for bootloader parameters */
+ if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0)
+ return rc;
+
+ /* Store command line */
+ if ( ( rc = bzimage_set_cmdline ( image, &bzimg, cmdline ) ) != 0 )
+ return rc;
+
+ /* Load any initrds */
+ if ( ( rc = bzimage_load_initrds ( image, &bzimg ) ) != 0 )
+ return rc;
+
+ /* Update kernel header */
+ bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );
+
+ /* Prepare for exiting */
+ shutdown_boot();
+
+ DBGC ( image, "bzImage %p jumping to RM kernel at %04x:0000 "
+ "(stack %04x:%04zx)\n", image, ( bzimg.rm_kernel_seg + 0x20 ),
+ bzimg.rm_kernel_seg, bzimg.rm_heap );
+
+ /* Jump to the kernel */
+ __asm__ __volatile__ ( REAL_CODE ( "movw %w0, %%ds\n\t"
+ "movw %w0, %%es\n\t"
+ "movw %w0, %%fs\n\t"
+ "movw %w0, %%gs\n\t"
+ "movw %w0, %%ss\n\t"
+ "movw %w1, %%sp\n\t"
+ "pushw %w2\n\t"
+ "pushw $0\n\t"
+ "lret\n\t" )
+ : : "r" ( bzimg.rm_kernel_seg ),
+ "r" ( bzimg.rm_heap ),
+ "r" ( bzimg.rm_kernel_seg + 0x20 ) );
+
+ /* There is no way for the image to return, since we provide
+ * no return address.
+ */
+ assert ( 0 );
+
+ return -ECANCELED; /* -EIMPOSSIBLE */
+}
+
+/**
+ * Probe bzImage image
+ *
+ * @v image bzImage file
+ * @ret rc Return status code
+ */
+int bzimage_probe ( struct image *image ) {
+ struct bzimage_context bzimg;
+ int rc;
+
+ /* Read and parse header from image */
+ if ( ( rc = bzimage_parse_header ( image, &bzimg,
+ image->data ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/** Linux bzImage image type */
+struct image_type bzimage_image_type __image_type ( PROBE_NORMAL ) = {
+ .name = "bzImage",
+ .probe = bzimage_probe,
+ .exec = bzimage_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/image/com32.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/com32.c
new file mode 100644
index 00000000..d6e48ebe
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/com32.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/**
+ * @file
+ *
+ * SYSLINUX COM32 image format
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <assert.h>
+#include <realmode.h>
+#include <basemem.h>
+#include <comboot.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/image.h>
+#include <ipxe/segment.h>
+#include <ipxe/init.h>
+#include <ipxe/io.h>
+
+struct idt_register com32_external_idtr = {
+ .limit = COM32_NUM_IDT_ENTRIES * sizeof ( struct idt_descriptor ) - 1,
+ .base = COM32_IDT
+};
+
+struct idt_register com32_internal_idtr;
+
+/**
+ * Execute COMBOOT image
+ *
+ * @v image COM32 image
+ * @ret rc Return status code
+ */
+static int com32_exec_loop ( struct image *image ) {
+ struct memory_map memmap;
+ unsigned int i;
+ int state;
+ uint32_t avail_mem_top;
+
+ state = rmsetjmp ( comboot_return );
+
+ switch ( state ) {
+ case 0: /* First time through; invoke COM32 program */
+
+ /* Get memory map */
+ get_memmap ( &memmap );
+
+ /* Find end of block covering COM32 image loading area */
+ for ( i = 0, avail_mem_top = 0 ; i < memmap.count ; i++ ) {
+ if ( (memmap.regions[i].start <= COM32_START_PHYS) &&
+ (memmap.regions[i].end > COM32_START_PHYS + image->len) ) {
+ avail_mem_top = memmap.regions[i].end;
+ break;
+ }
+ }
+
+ DBGC ( image, "COM32 %p: available memory top = 0x%x\n",
+ image, avail_mem_top );
+
+ assert ( avail_mem_top != 0 );
+
+ com32_external_esp = phys_to_virt ( avail_mem_top );
+
+ /* Hook COMBOOT API interrupts */
+ hook_comboot_interrupts();
+
+ /* Unregister image, so that a "boot" command doesn't
+ * throw us into an execution loop. We never
+ * reregister ourselves; COMBOOT images expect to be
+ * removed on exit.
+ */
+ unregister_image ( image );
+
+ __asm__ __volatile__ (
+ "sidt com32_internal_idtr\n\t"
+ "lidt com32_external_idtr\n\t" /* Set up IDT */
+ "movl %%esp, (com32_internal_esp)\n\t" /* Save internal virtual address space ESP */
+ "movl (com32_external_esp), %%esp\n\t" /* Switch to COM32 ESP (top of available memory) */
+ "call _virt_to_phys\n\t" /* Switch to flat physical address space */
+ "sti\n\t" /* Enable interrupts */
+ "pushl %0\n\t" /* Pointer to CDECL helper function */
+ "pushl %1\n\t" /* Pointer to FAR call helper function */
+ "pushl %2\n\t" /* Size of low memory bounce buffer */
+ "pushl %3\n\t" /* Pointer to low memory bounce buffer */
+ "pushl %4\n\t" /* Pointer to INT call helper function */
+ "pushl %5\n\t" /* Pointer to the command line arguments */
+ "pushl $6\n\t" /* Number of additional arguments */
+ "call *%6\n\t" /* Execute image */
+ "cli\n\t" /* Disable interrupts */
+ "call _phys_to_virt\n\t" /* Switch back to internal virtual address space */
+ "lidt com32_internal_idtr\n\t" /* Switch back to internal IDT (for debugging) */
+ "movl (com32_internal_esp), %%esp\n\t" /* Switch back to internal stack */
+ :
+ :
+ /* %0 */ "r" ( virt_to_phys ( com32_cfarcall_wrapper ) ),
+ /* %1 */ "r" ( virt_to_phys ( com32_farcall_wrapper ) ),
+ /* %2 */ "r" ( get_fbms() * 1024 - (COM32_BOUNCE_SEG << 4) ),
+ /* %3 */ "i" ( COM32_BOUNCE_SEG << 4 ),
+ /* %4 */ "r" ( virt_to_phys ( com32_intcall_wrapper ) ),
+ /* %5 */ "r" ( virt_to_phys ( image->cmdline ?
+ image->cmdline : "" ) ),
+ /* %6 */ "r" ( COM32_START_PHYS )
+ :
+ "memory" );
+ DBGC ( image, "COM32 %p: returned\n", image );
+ break;
+
+ case COMBOOT_EXIT:
+ DBGC ( image, "COM32 %p: exited\n", image );
+ break;
+
+ case COMBOOT_EXIT_RUN_KERNEL:
+ assert ( image->replacement );
+ DBGC ( image, "COM32 %p: exited to run kernel %s\n",
+ image, image->replacement->name );
+ break;
+
+ case COMBOOT_EXIT_COMMAND:
+ DBGC ( image, "COM32 %p: exited after executing command\n",
+ image );
+ break;
+
+ default:
+ assert ( 0 );
+ break;
+ }
+
+ unhook_comboot_interrupts();
+ comboot_force_text_mode();
+
+ return 0;
+}
+
+/**
+ * Check image name extension
+ *
+ * @v image COM32 image
+ * @ret rc Return status code
+ */
+static int com32_identify ( struct image *image ) {
+ const char *ext;
+ static const uint8_t magic[] = { 0xB8, 0xFF, 0x4C, 0xCD, 0x21 };
+ uint8_t buf[5];
+
+ if ( image->len >= 5 ) {
+ /* Check for magic number
+ * mov eax,21cd4cffh
+ * B8 FF 4C CD 21
+ */
+ copy_from_user ( buf, image->data, 0, sizeof(buf) );
+ if ( ! memcmp ( buf, magic, sizeof(buf) ) ) {
+ DBGC ( image, "COM32 %p: found magic number\n",
+ image );
+ return 0;
+ }
+ }
+
+ /* Magic number not found; check filename extension */
+
+ ext = strrchr( image->name, '.' );
+
+ if ( ! ext ) {
+ DBGC ( image, "COM32 %p: no extension\n",
+ image );
+ return -ENOEXEC;
+ }
+
+ ++ext;
+
+ if ( strcasecmp( ext, "c32" ) ) {
+ DBGC ( image, "COM32 %p: unrecognized extension %s\n",
+ image, ext );
+ return -ENOEXEC;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Load COM32 image into memory and set up the IDT
+ * @v image COM32 image
+ * @ret rc Return status code
+ */
+static int com32_load_image ( struct image *image ) {
+ physaddr_t com32_irq_wrapper_phys;
+ struct idt_descriptor *idt;
+ struct ijb_entry *ijb;
+ size_t filesz, memsz;
+ userptr_t buffer;
+ int rc, i;
+
+ /* The interrupt descriptor table, interrupt jump buffer, and
+ * image data are all contiguous in memory. Prepare them all at once.
+ */
+ filesz = image->len +
+ COM32_NUM_IDT_ENTRIES * sizeof ( struct idt_descriptor ) +
+ COM32_NUM_IDT_ENTRIES * sizeof ( struct ijb_entry );
+ memsz = filesz;
+ buffer = phys_to_user ( COM32_IDT );
+ if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
+ DBGC ( image, "COM32 %p: could not prepare segment: %s\n",
+ image, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Write the IDT and IJB */
+ idt = phys_to_virt ( COM32_IDT );
+ ijb = phys_to_virt ( COM32_IJB );
+ com32_irq_wrapper_phys = virt_to_phys ( com32_irq_wrapper );
+
+ for ( i = 0; i < COM32_NUM_IDT_ENTRIES; i++ ) {
+ uint32_t ijb_address = virt_to_phys ( &ijb[i] );
+
+ idt[i].offset_low = ijb_address & 0xFFFF;
+ idt[i].selector = PHYSICAL_CS;
+ idt[i].flags = IDT_INTERRUPT_GATE_FLAGS;
+ idt[i].offset_high = ijb_address >> 16;
+
+ ijb[i].pusha_instruction = IJB_PUSHA;
+ ijb[i].mov_instruction = IJB_MOV_AL_IMM8;
+ ijb[i].mov_value = i;
+ ijb[i].jump_instruction = IJB_JMP_REL32;
+ ijb[i].jump_destination = com32_irq_wrapper_phys -
+ virt_to_phys ( &ijb[i + 1] );
+ }
+
+ /* Copy image to segment */
+ buffer = phys_to_user ( COM32_START_PHYS );
+ memcpy_user ( buffer, 0, image->data, 0, filesz );
+
+ return 0;
+}
+
+/**
+ * Prepare COM32 low memory bounce buffer
+ * @v image COM32 image
+ * @ret rc Return status code
+ */
+static int com32_prepare_bounce_buffer ( struct image * image ) {
+ unsigned int seg;
+ userptr_t seg_userptr;
+ size_t filesz, memsz;
+ int rc;
+
+ seg = COM32_BOUNCE_SEG;
+ seg_userptr = real_to_user ( seg, 0 );
+
+ /* Ensure the entire 64k segment is free */
+ memsz = 0xFFFF;
+ filesz = 0;
+
+ /* Prepare, verify, and load the real-mode segment */
+ if ( ( rc = prep_segment ( seg_userptr, filesz, memsz ) ) != 0 ) {
+ DBGC ( image, "COM32 %p: could not prepare bounce buffer segment: %s\n",
+ image, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Probe COM32 image
+ *
+ * @v image COM32 image
+ * @ret rc Return status code
+ */
+static int com32_probe ( struct image *image ) {
+ int rc;
+
+ DBGC ( image, "COM32 %p: name '%s'\n", image, image->name );
+
+ /* Check if this is a COMBOOT image */
+ if ( ( rc = com32_identify ( image ) ) != 0 ) {
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Execute COMBOOT image
+ *
+ * @v image COM32 image
+ * @ret rc Return status code
+ */
+static int com32_exec ( struct image *image ) {
+ int rc;
+
+ /* Load image */
+ if ( ( rc = com32_load_image ( image ) ) != 0 ) {
+ return rc;
+ }
+
+ /* Prepare bounce buffer segment */
+ if ( ( rc = com32_prepare_bounce_buffer ( image ) ) != 0 ) {
+ return rc;
+ }
+
+ return com32_exec_loop ( image );
+}
+
+/** SYSLINUX COM32 image type */
+struct image_type com32_image_type __image_type ( PROBE_NORMAL ) = {
+ .name = "COM32",
+ .probe = com32_probe,
+ .exec = com32_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/image/comboot.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/comboot.c
new file mode 100644
index 00000000..0b924cce
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/comboot.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/**
+ * @file
+ *
+ * SYSLINUX COMBOOT (16-bit) image format
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <assert.h>
+#include <realmode.h>
+#include <basemem.h>
+#include <comboot.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/image.h>
+#include <ipxe/segment.h>
+#include <ipxe/init.h>
+#include <ipxe/features.h>
+
+FEATURE ( FEATURE_IMAGE, "COMBOOT", DHCP_EB_FEATURE_COMBOOT, 1 );
+
+/**
+ * COMBOOT PSP, copied to offset 0 of code segment
+ */
+struct comboot_psp {
+ /** INT 20 instruction, executed if COMBOOT image returns with RET */
+ uint16_t int20;
+ /** Segment of first non-free paragraph of memory */
+ uint16_t first_non_free_para;
+};
+
+/** Offset in PSP of command line */
+#define COMBOOT_PSP_CMDLINE_OFFSET 0x81
+
+/** Maximum length of command line in PSP
+ * (127 bytes minus space and CR) */
+#define COMBOOT_MAX_CMDLINE_LEN 125
+
+
+/**
+ * Copy command line to PSP
+ *
+ * @v image COMBOOT image
+ */
+static void comboot_copy_cmdline ( struct image * image, userptr_t seg_userptr ) {
+ const char *cmdline = ( image->cmdline ? image->cmdline : "" );
+ int cmdline_len = strlen ( cmdline );
+ if( cmdline_len > COMBOOT_MAX_CMDLINE_LEN )
+ cmdline_len = COMBOOT_MAX_CMDLINE_LEN;
+ uint8_t len_byte = cmdline_len;
+ char spc = ' ', cr = '\r';
+
+ /* Copy length to byte before command line */
+ copy_to_user ( seg_userptr, COMBOOT_PSP_CMDLINE_OFFSET - 1,
+ &len_byte, 1 );
+
+ /* Command line starts with space */
+ copy_to_user ( seg_userptr,
+ COMBOOT_PSP_CMDLINE_OFFSET,
+ &spc, 1 );
+
+ /* Copy command line */
+ copy_to_user ( seg_userptr,
+ COMBOOT_PSP_CMDLINE_OFFSET + 1,
+ cmdline, cmdline_len );
+
+ /* Command line ends with CR */
+ copy_to_user ( seg_userptr,
+ COMBOOT_PSP_CMDLINE_OFFSET + cmdline_len + 1,
+ &cr, 1 );
+}
+
+/**
+ * Initialize PSP
+ *
+ * @v image COMBOOT image
+ * @v seg_userptr segment to initialize
+ */
+static void comboot_init_psp ( struct image * image, userptr_t seg_userptr ) {
+ struct comboot_psp psp;
+
+ /* Fill PSP */
+
+ /* INT 20h instruction, byte order reversed */
+ psp.int20 = 0x20CD;
+
+ /* get_fbms() returns BIOS free base memory counter, which is in
+ * kilobytes; x * 1024 / 16 == x * 64 == x << 6 */
+ psp.first_non_free_para = get_fbms() << 6;
+
+ DBGC ( image, "COMBOOT %p: first non-free paragraph = 0x%x\n",
+ image, psp.first_non_free_para );
+
+ /* Copy the PSP to offset 0 of segment.
+ * The rest of the PSP was already zeroed by
+ * comboot_prepare_segment. */
+ copy_to_user ( seg_userptr, 0, &psp, sizeof( psp ) );
+
+ /* Copy the command line to the PSP */
+ comboot_copy_cmdline ( image, seg_userptr );
+}
+
+/**
+ * Execute COMBOOT image
+ *
+ * @v image COMBOOT image
+ * @ret rc Return status code
+ */
+static int comboot_exec_loop ( struct image *image ) {
+ userptr_t seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 );
+ int state;
+
+ state = rmsetjmp ( comboot_return );
+
+ switch ( state ) {
+ case 0: /* First time through; invoke COMBOOT program */
+
+ /* Initialize PSP */
+ comboot_init_psp ( image, seg_userptr );
+
+ /* Hook COMBOOT API interrupts */
+ hook_comboot_interrupts();
+
+ DBGC ( image, "executing 16-bit COMBOOT image at %4x:0100\n",
+ COMBOOT_PSP_SEG );
+
+ /* Unregister image, so that a "boot" command doesn't
+ * throw us into an execution loop. We never
+ * reregister ourselves; COMBOOT images expect to be
+ * removed on exit.
+ */
+ unregister_image ( image );
+
+ /* Store stack segment at 0x38 and stack pointer at 0x3A
+ * in the PSP and jump to the image */
+ __asm__ __volatile__ (
+ REAL_CODE ( /* Save return address with segment on old stack */
+ "popw %%ax\n\t"
+ "pushw %%cs\n\t"
+ "pushw %%ax\n\t"
+ /* Set DS=ES=segment with image */
+ "movw %w0, %%ds\n\t"
+ "movw %w0, %%es\n\t"
+ /* Set SS:SP to new stack (end of image segment) */
+ "movw %w0, %%ss\n\t"
+ "xor %%sp, %%sp\n\t"
+ "pushw $0\n\t"
+ "pushw %w0\n\t"
+ "pushw $0x100\n\t"
+ /* Zero registers (some COM files assume GP regs are 0) */
+ "xorw %%ax, %%ax\n\t"
+ "xorw %%bx, %%bx\n\t"
+ "xorw %%cx, %%cx\n\t"
+ "xorw %%dx, %%dx\n\t"
+ "xorw %%si, %%si\n\t"
+ "xorw %%di, %%di\n\t"
+ "xorw %%bp, %%bp\n\t"
+ "lret\n\t" )
+ : : "r" ( COMBOOT_PSP_SEG ) : "eax" );
+ DBGC ( image, "COMBOOT %p: returned\n", image );
+ break;
+
+ case COMBOOT_EXIT:
+ DBGC ( image, "COMBOOT %p: exited\n", image );
+ break;
+
+ case COMBOOT_EXIT_RUN_KERNEL:
+ assert ( image->replacement );
+ DBGC ( image, "COMBOOT %p: exited to run kernel %s\n",
+ image, image->replacement->name );
+ break;
+
+ case COMBOOT_EXIT_COMMAND:
+ DBGC ( image, "COMBOOT %p: exited after executing command\n",
+ image );
+ break;
+
+ default:
+ assert ( 0 );
+ break;
+ }
+
+ unhook_comboot_interrupts();
+ comboot_force_text_mode();
+
+ return 0;
+}
+
+/**
+ * Check image name extension
+ *
+ * @v image COMBOOT image
+ * @ret rc Return status code
+ */
+static int comboot_identify ( struct image *image ) {
+ const char *ext;
+
+ ext = strrchr( image->name, '.' );
+
+ if ( ! ext ) {
+ DBGC ( image, "COMBOOT %p: no extension\n",
+ image );
+ return -ENOEXEC;
+ }
+
+ ++ext;
+
+ if ( strcasecmp( ext, "com" ) && strcasecmp( ext, "cbt" ) ) {
+ DBGC ( image, "COMBOOT %p: unrecognized extension %s\n",
+ image, ext );
+ return -ENOEXEC;
+ }
+
+ return 0;
+}
+
+/**
+ * Load COMBOOT image into memory, preparing a segment and returning it
+ * @v image COMBOOT image
+ * @ret rc Return status code
+ */
+static int comboot_prepare_segment ( struct image *image )
+{
+ userptr_t seg_userptr;
+ size_t filesz, memsz;
+ int rc;
+
+ /* Load image in segment */
+ seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 );
+
+ /* Allow etra 0x100 bytes before image for PSP */
+ filesz = image->len + 0x100;
+
+ /* Ensure the entire 64k segment is free */
+ memsz = 0xFFFF;
+
+ /* Prepare, verify, and load the real-mode segment */
+ if ( ( rc = prep_segment ( seg_userptr, filesz, memsz ) ) != 0 ) {
+ DBGC ( image, "COMBOOT %p: could not prepare segment: %s\n",
+ image, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Zero PSP */
+ memset_user ( seg_userptr, 0, 0, 0x100 );
+
+ /* Copy image to segment:0100 */
+ memcpy_user ( seg_userptr, 0x100, image->data, 0, image->len );
+
+ return 0;
+}
+
+/**
+ * Probe COMBOOT image
+ *
+ * @v image COMBOOT image
+ * @ret rc Return status code
+ */
+static int comboot_probe ( struct image *image ) {
+ int rc;
+
+ DBGC ( image, "COMBOOT %p: name '%s'\n",
+ image, image->name );
+
+ /* Check if this is a COMBOOT image */
+ if ( ( rc = comboot_identify ( image ) ) != 0 ) {
+
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Execute COMBOOT image
+ *
+ * @v image COMBOOT image
+ * @ret rc Return status code
+ */
+static int comboot_exec ( struct image *image ) {
+ int rc;
+
+ /* Sanity check for filesize */
+ if( image->len >= 0xFF00 ) {
+ DBGC( image, "COMBOOT %p: image too large\n",
+ image );
+ return -ENOEXEC;
+ }
+
+ /* Prepare segment and load image */
+ if ( ( rc = comboot_prepare_segment ( image ) ) != 0 ) {
+ return rc;
+ }
+
+ return comboot_exec_loop ( image );
+}
+
+/** SYSLINUX COMBOOT (16-bit) image type */
+struct image_type comboot_image_type __image_type ( PROBE_NORMAL ) = {
+ .name = "COMBOOT",
+ .probe = comboot_probe,
+ .exec = comboot_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/image/elfboot.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/elfboot.c
new file mode 100644
index 00000000..6507e186
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/elfboot.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <elf.h>
+#include <ipxe/image.h>
+#include <ipxe/elf.h>
+#include <ipxe/features.h>
+#include <ipxe/init.h>
+
+/**
+ * @file
+ *
+ * ELF bootable image
+ *
+ */
+
+FEATURE ( FEATURE_IMAGE, "ELF", DHCP_EB_FEATURE_ELF, 1 );
+
+/**
+ * Execute ELF image
+ *
+ * @v image ELF image
+ * @ret rc Return status code
+ */
+static int elfboot_exec ( struct image *image ) {
+ physaddr_t entry;
+ physaddr_t max;
+ int rc;
+
+ /* Load the image using core ELF support */
+ if ( ( rc = elf_load ( image, &entry, &max ) ) != 0 ) {
+ DBGC ( image, "ELF %p could not load: %s\n",
+ image, strerror ( rc ) );
+ return rc;
+ }
+
+ /* An ELF image has no callback interface, so we need to shut
+ * down before invoking it.
+ */
+ shutdown_boot();
+
+ /* Jump to OS with flat physical addressing */
+ DBGC ( image, "ELF %p starting execution at %lx\n", image, entry );
+ __asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t" /* gcc bug */
+ "call *%%edi\n\t"
+ "popl %%ebp\n\t" /* gcc bug */ )
+ : : "D" ( entry )
+ : "eax", "ebx", "ecx", "edx", "esi", "memory" );
+
+ DBGC ( image, "ELF %p returned\n", image );
+
+ /* It isn't safe to continue after calling shutdown() */
+ while ( 1 ) {}
+
+ return -ECANCELED; /* -EIMPOSSIBLE, anyone? */
+}
+
+/**
+ * Probe ELF image
+ *
+ * @v image ELF file
+ * @ret rc Return status code
+ */
+static int elfboot_probe ( struct image *image ) {
+ Elf32_Ehdr ehdr;
+ static const uint8_t e_ident[] = {
+ [EI_MAG0] = ELFMAG0,
+ [EI_MAG1] = ELFMAG1,
+ [EI_MAG2] = ELFMAG2,
+ [EI_MAG3] = ELFMAG3,
+ [EI_CLASS] = ELFCLASS32,
+ [EI_DATA] = ELFDATA2LSB,
+ [EI_VERSION] = EV_CURRENT,
+ };
+
+ /* Read ELF header */
+ copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
+ if ( memcmp ( ehdr.e_ident, e_ident, sizeof ( e_ident ) ) != 0 ) {
+ DBG ( "Invalid ELF identifier\n" );
+ return -ENOEXEC;
+ }
+
+ return 0;
+}
+
+/** ELF image type */
+struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ) = {
+ .name = "ELF",
+ .probe = elfboot_probe,
+ .exec = elfboot_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/image/multiboot.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/multiboot.c
new file mode 100644
index 00000000..004a01b1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/multiboot.c
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Multiboot image format
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+#include <realmode.h>
+#include <multiboot.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/image.h>
+#include <ipxe/segment.h>
+#include <ipxe/io.h>
+#include <ipxe/elf.h>
+#include <ipxe/init.h>
+#include <ipxe/features.h>
+#include <ipxe/uri.h>
+
+FEATURE ( FEATURE_IMAGE, "MBOOT", DHCP_EB_FEATURE_MULTIBOOT, 1 );
+
+/**
+ * Maximum number of modules we will allow for
+ *
+ * If this has bitten you: sorry. I did have a perfect scheme with a
+ * dynamically allocated list of modules on the protected-mode stack,
+ * but it was incompatible with some broken OSes that can only access
+ * low memory at boot time (even though we kindly set up 4GB flat
+ * physical addressing as per the multiboot specification.
+ *
+ */
+#define MAX_MODULES 8
+
+/**
+ * Maximum combined length of command lines
+ *
+ * Again; sorry. Some broken OSes zero out any non-base memory that
+ * isn't part of the loaded module set, so we can't just use
+ * virt_to_phys(cmdline) to point to the command lines, even though
+ * this would comply with the Multiboot spec.
+ */
+#define MB_MAX_CMDLINE 512
+
+/** Multiboot flags that we support */
+#define MB_SUPPORTED_FLAGS ( MB_FLAG_PGALIGN | MB_FLAG_MEMMAP | \
+ MB_FLAG_VIDMODE | MB_FLAG_RAW )
+
+/** Compulsory feature multiboot flags */
+#define MB_COMPULSORY_FLAGS 0x0000ffff
+
+/** Optional feature multiboot flags */
+#define MB_OPTIONAL_FLAGS 0xffff0000
+
+/**
+ * Multiboot flags that we don't support
+ *
+ * We only care about the compulsory feature flags (bits 0-15); we are
+ * allowed to ignore the optional feature flags.
+ */
+#define MB_UNSUPPORTED_FLAGS ( MB_COMPULSORY_FLAGS & ~MB_SUPPORTED_FLAGS )
+
+/** A multiboot header descriptor */
+struct multiboot_header_info {
+ /** The actual multiboot header */
+ struct multiboot_header mb;
+ /** Offset of header within the multiboot image */
+ size_t offset;
+};
+
+/** Multiboot module command lines */
+static char __bss16_array ( mb_cmdlines, [MB_MAX_CMDLINE] );
+#define mb_cmdlines __use_data16 ( mb_cmdlines )
+
+/** Offset within module command lines */
+static unsigned int mb_cmdline_offset;
+
+/**
+ * Build multiboot memory map
+ *
+ * @v image Multiboot image
+ * @v mbinfo Multiboot information structure
+ * @v mbmemmap Multiboot memory map
+ * @v limit Maxmimum number of memory map entries
+ */
+static void multiboot_build_memmap ( struct image *image,
+ struct multiboot_info *mbinfo,
+ struct multiboot_memory_map *mbmemmap,
+ unsigned int limit ) {
+ struct memory_map memmap;
+ unsigned int i;
+
+ /* Get memory map */
+ get_memmap ( &memmap );
+
+ /* Translate into multiboot format */
+ memset ( mbmemmap, 0, sizeof ( *mbmemmap ) );
+ for ( i = 0 ; i < memmap.count ; i++ ) {
+ if ( i >= limit ) {
+ DBGC ( image, "MULTIBOOT %p limit of %d memmap "
+ "entries reached\n", image, limit );
+ break;
+ }
+ mbmemmap[i].size = ( sizeof ( mbmemmap[i] ) -
+ sizeof ( mbmemmap[i].size ) );
+ mbmemmap[i].base_addr = memmap.regions[i].start;
+ mbmemmap[i].length = ( memmap.regions[i].end -
+ memmap.regions[i].start );
+ mbmemmap[i].type = MBMEM_RAM;
+ mbinfo->mmap_length += sizeof ( mbmemmap[i] );
+ if ( memmap.regions[i].start == 0 )
+ mbinfo->mem_lower = ( memmap.regions[i].end / 1024 );
+ if ( memmap.regions[i].start == 0x100000 )
+ mbinfo->mem_upper = ( ( memmap.regions[i].end -
+ 0x100000 ) / 1024 );
+ }
+}
+
+/**
+ * Add command line in base memory
+ *
+ * @v image Image
+ * @ret physaddr Physical address of command line
+ */
+static physaddr_t multiboot_add_cmdline ( struct image *image ) {
+ char *mb_cmdline = ( mb_cmdlines + mb_cmdline_offset );
+ size_t remaining = ( sizeof ( mb_cmdlines ) - mb_cmdline_offset );
+ char *buf = mb_cmdline;
+ size_t len;
+
+ /* Copy image URI to base memory buffer as start of command line */
+ len = ( unparse_uri ( buf, remaining, image->uri,
+ URI_ALL ) + 1 /* NUL */ );
+ if ( len > remaining )
+ len = remaining;
+ mb_cmdline_offset += len;
+ buf += len;
+ remaining -= len;
+
+ /* Copy command line to base memory buffer, if present */
+ if ( image->cmdline ) {
+ mb_cmdline_offset--; /* Strip NUL */
+ buf--;
+ remaining++;
+ len = ( snprintf ( buf, remaining, " %s",
+ image->cmdline ) + 1 /* NUL */ );
+ if ( len > remaining )
+ len = remaining;
+ mb_cmdline_offset += len;
+ }
+
+ return virt_to_phys ( mb_cmdline );
+}
+
+/**
+ * Add multiboot modules
+ *
+ * @v image Multiboot image
+ * @v start Start address for modules
+ * @v mbinfo Multiboot information structure
+ * @v modules Multiboot module list
+ * @ret rc Return status code
+ */
+static int multiboot_add_modules ( struct image *image, physaddr_t start,
+ struct multiboot_info *mbinfo,
+ struct multiboot_module *modules,
+ unsigned int limit ) {
+ struct image *module_image;
+ struct multiboot_module *module;
+ int rc;
+
+ /* Add each image as a multiboot module */
+ for_each_image ( module_image ) {
+
+ if ( mbinfo->mods_count >= limit ) {
+ DBGC ( image, "MULTIBOOT %p limit of %d modules "
+ "reached\n", image, limit );
+ break;
+ }
+
+ /* Do not include kernel image itself as a module */
+ if ( module_image == image )
+ continue;
+
+ /* Page-align the module */
+ start = ( ( start + 0xfff ) & ~0xfff );
+
+ /* Prepare segment */
+ if ( ( rc = prep_segment ( phys_to_user ( start ),
+ module_image->len,
+ module_image->len ) ) != 0 ) {
+ DBGC ( image, "MULTIBOOT %p could not prepare module "
+ "%s: %s\n", image, module_image->name,
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Copy module */
+ memcpy_user ( phys_to_user ( start ), 0,
+ module_image->data, 0, module_image->len );
+
+ /* Add module to list */
+ module = &modules[mbinfo->mods_count++];
+ module->mod_start = start;
+ module->mod_end = ( start + module_image->len );
+ module->string = multiboot_add_cmdline ( module_image );
+ module->reserved = 0;
+ DBGC ( image, "MULTIBOOT %p module %s is [%x,%x)\n",
+ image, module_image->name, module->mod_start,
+ module->mod_end );
+ start += module_image->len;
+ }
+
+ return 0;
+}
+
+/**
+ * The multiboot information structure
+ *
+ * Kept in base memory because some OSes won't find it elsewhere,
+ * along with the other structures belonging to the Multiboot
+ * information table.
+ */
+static struct multiboot_info __bss16 ( mbinfo );
+#define mbinfo __use_data16 ( mbinfo )
+
+/** The multiboot bootloader name */
+static char __data16_array ( mb_bootloader_name, [] ) = "iPXE " VERSION;
+#define mb_bootloader_name __use_data16 ( mb_bootloader_name )
+
+/** The multiboot memory map */
+static struct multiboot_memory_map
+ __bss16_array ( mbmemmap, [MAX_MEMORY_REGIONS] );
+#define mbmemmap __use_data16 ( mbmemmap )
+
+/** The multiboot module list */
+static struct multiboot_module __bss16_array ( mbmodules, [MAX_MODULES] );
+#define mbmodules __use_data16 ( mbmodules )
+
+/**
+ * Find multiboot header
+ *
+ * @v image Multiboot file
+ * @v hdr Multiboot header descriptor to fill in
+ * @ret rc Return status code
+ */
+static int multiboot_find_header ( struct image *image,
+ struct multiboot_header_info *hdr ) {
+ uint32_t buf[64];
+ size_t offset;
+ unsigned int buf_idx;
+ uint32_t checksum;
+
+ /* Scan through first 8kB of image file 256 bytes at a time.
+ * (Use the buffering to avoid the overhead of a
+ * copy_from_user() for every dword.)
+ */
+ for ( offset = 0 ; offset < 8192 ; offset += sizeof ( buf[0] ) ) {
+ /* Check for end of image */
+ if ( offset > image->len )
+ break;
+ /* Refill buffer if applicable */
+ buf_idx = ( ( offset % sizeof ( buf ) ) / sizeof ( buf[0] ) );
+ if ( buf_idx == 0 ) {
+ copy_from_user ( buf, image->data, offset,
+ sizeof ( buf ) );
+ }
+ /* Check signature */
+ if ( buf[buf_idx] != MULTIBOOT_HEADER_MAGIC )
+ continue;
+ /* Copy header and verify checksum */
+ copy_from_user ( &hdr->mb, image->data, offset,
+ sizeof ( hdr->mb ) );
+ checksum = ( hdr->mb.magic + hdr->mb.flags +
+ hdr->mb.checksum );
+ if ( checksum != 0 )
+ continue;
+ /* Record offset of multiboot header and return */
+ hdr->offset = offset;
+ return 0;
+ }
+
+ /* No multiboot header found */
+ return -ENOEXEC;
+}
+
+/**
+ * Load raw multiboot image into memory
+ *
+ * @v image Multiboot file
+ * @v hdr Multiboot header descriptor
+ * @ret entry Entry point
+ * @ret max Maximum used address
+ * @ret rc Return status code
+ */
+static int multiboot_load_raw ( struct image *image,
+ struct multiboot_header_info *hdr,
+ physaddr_t *entry, physaddr_t *max ) {
+ size_t offset;
+ size_t filesz;
+ size_t memsz;
+ userptr_t buffer;
+ int rc;
+
+ /* Sanity check */
+ if ( ! ( hdr->mb.flags & MB_FLAG_RAW ) ) {
+ DBGC ( image, "MULTIBOOT %p is not flagged as a raw image\n",
+ image );
+ return -EINVAL;
+ }
+
+ /* Verify and prepare segment */
+ offset = ( hdr->offset - hdr->mb.header_addr + hdr->mb.load_addr );
+ filesz = ( hdr->mb.load_end_addr ?
+ ( hdr->mb.load_end_addr - hdr->mb.load_addr ) :
+ ( image->len - offset ) );
+ memsz = ( hdr->mb.bss_end_addr ?
+ ( hdr->mb.bss_end_addr - hdr->mb.load_addr ) : filesz );
+ buffer = phys_to_user ( hdr->mb.load_addr );
+ if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
+ DBGC ( image, "MULTIBOOT %p could not prepare segment: %s\n",
+ image, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Copy image to segment */
+ memcpy_user ( buffer, 0, image->data, offset, filesz );
+
+ /* Record execution entry point and maximum used address */
+ *entry = hdr->mb.entry_addr;
+ *max = ( hdr->mb.load_addr + memsz );
+
+ return 0;
+}
+
+/**
+ * Load ELF multiboot image into memory
+ *
+ * @v image Multiboot file
+ * @ret entry Entry point
+ * @ret max Maximum used address
+ * @ret rc Return status code
+ */
+static int multiboot_load_elf ( struct image *image, physaddr_t *entry,
+ physaddr_t *max ) {
+ int rc;
+
+ /* Load ELF image*/
+ if ( ( rc = elf_load ( image, entry, max ) ) != 0 ) {
+ DBGC ( image, "MULTIBOOT %p ELF image failed to load: %s\n",
+ image, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Execute multiboot image
+ *
+ * @v image Multiboot image
+ * @ret rc Return status code
+ */
+static int multiboot_exec ( struct image *image ) {
+ struct multiboot_header_info hdr;
+ physaddr_t entry;
+ physaddr_t max;
+ int rc;
+
+ /* Locate multiboot header, if present */
+ if ( ( rc = multiboot_find_header ( image, &hdr ) ) != 0 ) {
+ DBGC ( image, "MULTIBOOT %p has no multiboot header\n",
+ image );
+ return rc;
+ }
+
+ /* Abort if we detect flags that we cannot support */
+ if ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) {
+ DBGC ( image, "MULTIBOOT %p flags %08x not supported\n",
+ image, ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) );
+ return -ENOTSUP;
+ }
+
+ /* There is technically a bit MB_FLAG_RAW to indicate whether
+ * this is an ELF or a raw image. In practice, grub will use
+ * the ELF header if present, and Solaris relies on this
+ * behaviour.
+ */
+ if ( ( ( rc = multiboot_load_elf ( image, &entry, &max ) ) != 0 ) &&
+ ( ( rc = multiboot_load_raw ( image, &hdr, &entry, &max ) ) != 0 ))
+ return rc;
+
+ /* Populate multiboot information structure */
+ memset ( &mbinfo, 0, sizeof ( mbinfo ) );
+ mbinfo.flags = ( MBI_FLAG_LOADER | MBI_FLAG_MEM | MBI_FLAG_MMAP |
+ MBI_FLAG_CMDLINE | MBI_FLAG_MODS );
+ mb_cmdline_offset = 0;
+ mbinfo.cmdline = multiboot_add_cmdline ( image );
+ mbinfo.mods_addr = virt_to_phys ( mbmodules );
+ mbinfo.mmap_addr = virt_to_phys ( mbmemmap );
+ mbinfo.boot_loader_name = virt_to_phys ( mb_bootloader_name );
+ if ( ( rc = multiboot_add_modules ( image, max, &mbinfo, mbmodules,
+ ( sizeof ( mbmodules ) /
+ sizeof ( mbmodules[0] ) ) ) ) !=0)
+ return rc;
+
+ /* Multiboot images may not return and have no callback
+ * interface, so shut everything down prior to booting the OS.
+ */
+ shutdown_boot();
+
+ /* Build memory map after unhiding bootloader memory regions as part of
+ * shutting everything down.
+ */
+ multiboot_build_memmap ( image, &mbinfo, mbmemmap,
+ ( sizeof(mbmemmap) / sizeof(mbmemmap[0]) ) );
+
+ /* Jump to OS with flat physical addressing */
+ DBGC ( image, "MULTIBOOT %p starting execution at %lx\n",
+ image, entry );
+ __asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t"
+ "call *%%edi\n\t"
+ "popl %%ebp\n\t" )
+ : : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
+ "b" ( virt_to_phys ( &mbinfo ) ),
+ "D" ( entry )
+ : "ecx", "edx", "esi", "memory" );
+
+ DBGC ( image, "MULTIBOOT %p returned\n", image );
+
+ /* It isn't safe to continue after calling shutdown() */
+ while ( 1 ) {}
+
+ return -ECANCELED; /* -EIMPOSSIBLE, anyone? */
+}
+
+/**
+ * Probe multiboot image
+ *
+ * @v image Multiboot file
+ * @ret rc Return status code
+ */
+static int multiboot_probe ( struct image *image ) {
+ struct multiboot_header_info hdr;
+ int rc;
+
+ /* Locate multiboot header, if present */
+ if ( ( rc = multiboot_find_header ( image, &hdr ) ) != 0 ) {
+ DBGC ( image, "MULTIBOOT %p has no multiboot header\n",
+ image );
+ return rc;
+ }
+ DBGC ( image, "MULTIBOOT %p found header with flags %08x\n",
+ image, hdr.mb.flags );
+
+ return 0;
+}
+
+/** Multiboot image type */
+struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT ) = {
+ .name = "Multiboot",
+ .probe = multiboot_probe,
+ .exec = multiboot_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/image/nbi.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/nbi.c
new file mode 100644
index 00000000..6d44edf7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/nbi.c
@@ -0,0 +1,428 @@
+#include <errno.h>
+#include <assert.h>
+#include <realmode.h>
+#include <memsizes.h>
+#include <basemem_packet.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/segment.h>
+#include <ipxe/init.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/fakedhcp.h>
+#include <ipxe/image.h>
+#include <ipxe/features.h>
+
+/** @file
+ *
+ * NBI image format.
+ *
+ * The Net Boot Image format is defined by the "Draft Net Boot Image
+ * Proposal 0.3" by Jamie Honan, Gero Kuhlmann and Ken Yap. It is now
+ * considered to be a legacy format, but it still included because a
+ * large amount of software (e.g. nymph, LTSP) makes use of NBI files.
+ *
+ * Etherboot does not implement the INT 78 callback interface
+ * described by the NBI specification. For a callback interface on
+ * x86 architecture, use PXE.
+ *
+ */
+
+FEATURE ( FEATURE_IMAGE, "NBI", DHCP_EB_FEATURE_NBI, 1 );
+
+/**
+ * An NBI image header
+ *
+ * Note that the length field uses a peculiar encoding; use the
+ * NBI_LENGTH() macro to decode the actual header length.
+ *
+ */
+struct imgheader {
+ unsigned long magic; /**< Magic number (NBI_MAGIC) */
+ union {
+ unsigned char length; /**< Nibble-coded header length */
+ unsigned long flags; /**< Image flags */
+ };
+ segoff_t location; /**< 16-bit seg:off header location */
+ union {
+ segoff_t segoff; /**< 16-bit seg:off entry point */
+ unsigned long linear; /**< 32-bit entry point */
+ } execaddr;
+} __attribute__ (( packed ));
+
+/** NBI magic number */
+#define NBI_MAGIC 0x1B031336UL
+
+/* Interpretation of the "length" fields */
+#define NBI_NONVENDOR_LENGTH(len) ( ( (len) & 0x0f ) << 2 )
+#define NBI_VENDOR_LENGTH(len) ( ( (len) & 0xf0 ) >> 2 )
+#define NBI_LENGTH(len) ( NBI_NONVENDOR_LENGTH(len) + NBI_VENDOR_LENGTH(len) )
+
+/* Interpretation of the "flags" fields */
+#define NBI_PROGRAM_RETURNS(flags) ( (flags) & ( 1 << 8 ) )
+#define NBI_LINEAR_EXEC_ADDR(flags) ( (flags) & ( 1 << 31 ) )
+
+/** NBI header length */
+#define NBI_HEADER_LENGTH 512
+
+/**
+ * An NBI segment header
+ *
+ * Note that the length field uses a peculiar encoding; use the
+ * NBI_LENGTH() macro to decode the actual header length.
+ *
+ */
+struct segheader {
+ unsigned char length; /**< Nibble-coded header length */
+ unsigned char vendortag; /**< Vendor-defined private tag */
+ unsigned char reserved;
+ unsigned char flags; /**< Segment flags */
+ unsigned long loadaddr; /**< Load address */
+ unsigned long imglength; /**< Segment length in NBI file */
+ unsigned long memlength; /**< Segment length in memory */
+};
+
+/* Interpretation of the "flags" fields */
+#define NBI_LOADADDR_FLAGS(flags) ( (flags) & 0x03 )
+#define NBI_LOADADDR_ABS 0x00
+#define NBI_LOADADDR_AFTER 0x01
+#define NBI_LOADADDR_END 0x02
+#define NBI_LOADADDR_BEFORE 0x03
+#define NBI_LAST_SEGHEADER(flags) ( (flags) & ( 1 << 2 ) )
+
+/* Define a type for passing info to a loaded program */
+struct ebinfo {
+ uint8_t major, minor; /* Version */
+ uint16_t flags; /* Bit flags */
+};
+
+/** Info passed to NBI image */
+static struct ebinfo loaderinfo = {
+ VERSION_MAJOR, VERSION_MINOR,
+ 0
+};
+
+/**
+ * Prepare a segment for an NBI image
+ *
+ * @v image NBI image
+ * @v offset Offset within NBI image
+ * @v filesz Length of initialised-data portion of the segment
+ * @v memsz Total length of the segment
+ * @v src Source for initialised data
+ * @ret rc Return status code
+ */
+static int nbi_prepare_segment ( struct image *image, size_t offset __unused,
+ userptr_t dest, size_t filesz, size_t memsz ){
+ int rc;
+
+ if ( ( rc = prep_segment ( dest, filesz, memsz ) ) != 0 ) {
+ DBGC ( image, "NBI %p could not prepare segment: %s\n",
+ image, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Load a segment for an NBI image
+ *
+ * @v image NBI image
+ * @v offset Offset within NBI image
+ * @v filesz Length of initialised-data portion of the segment
+ * @v memsz Total length of the segment
+ * @v src Source for initialised data
+ * @ret rc Return status code
+ */
+static int nbi_load_segment ( struct image *image, size_t offset,
+ userptr_t dest, size_t filesz,
+ size_t memsz __unused ) {
+ memcpy_user ( dest, 0, image->data, offset, filesz );
+ return 0;
+}
+
+/**
+ * Process segments of an NBI image
+ *
+ * @v image NBI image
+ * @v imgheader Image header information
+ * @v process Function to call for each segment
+ * @ret rc Return status code
+ */
+static int nbi_process_segments ( struct image *image,
+ struct imgheader *imgheader,
+ int ( * process ) ( struct image *image,
+ size_t offset,
+ userptr_t dest,
+ size_t filesz,
+ size_t memsz ) ) {
+ struct segheader sh;
+ size_t offset = 0;
+ size_t sh_off;
+ userptr_t dest;
+ size_t filesz;
+ size_t memsz;
+ int rc;
+
+ /* Copy image header to target location */
+ dest = real_to_user ( imgheader->location.segment,
+ imgheader->location.offset );
+ filesz = memsz = NBI_HEADER_LENGTH;
+ if ( ( rc = process ( image, offset, dest, filesz, memsz ) ) != 0 )
+ return rc;
+ offset += filesz;
+
+ /* Process segments in turn */
+ sh_off = NBI_LENGTH ( imgheader->length );
+ do {
+ /* Read segment header */
+ copy_from_user ( &sh, image->data, sh_off, sizeof ( sh ) );
+ if ( sh.length == 0 ) {
+ /* Avoid infinite loop? */
+ DBGC ( image, "NBI %p invalid segheader length 0\n",
+ image );
+ return -ENOEXEC;
+ }
+
+ /* Calculate segment load address */
+ switch ( NBI_LOADADDR_FLAGS ( sh.flags ) ) {
+ case NBI_LOADADDR_ABS:
+ dest = phys_to_user ( sh.loadaddr );
+ break;
+ case NBI_LOADADDR_AFTER:
+ dest = userptr_add ( dest, memsz + sh.loadaddr );
+ break;
+ case NBI_LOADADDR_BEFORE:
+ dest = userptr_add ( dest, -sh.loadaddr );
+ break;
+ case NBI_LOADADDR_END:
+ /* Not correct according to the spec, but
+ * maintains backwards compatibility with
+ * previous versions of Etherboot.
+ */
+ dest = phys_to_user ( ( extmemsize() + 1024 ) * 1024
+ - sh.loadaddr );
+ break;
+ default:
+ /* Cannot be reached */
+ assert ( 0 );
+ }
+
+ /* Process this segment */
+ filesz = sh.imglength;
+ memsz = sh.memlength;
+ if ( ( offset + filesz ) > image->len ) {
+ DBGC ( image, "NBI %p segment outside file\n", image );
+ return -ENOEXEC;
+ }
+ if ( ( rc = process ( image, offset, dest,
+ filesz, memsz ) ) != 0 ) {
+ return rc;
+ }
+ offset += filesz;
+
+ /* Next segheader */
+ sh_off += NBI_LENGTH ( sh.length );
+ if ( sh_off >= NBI_HEADER_LENGTH ) {
+ DBGC ( image, "NBI %p header overflow\n", image );
+ return -ENOEXEC;
+ }
+
+ } while ( ! NBI_LAST_SEGHEADER ( sh.flags ) );
+
+ if ( offset != image->len ) {
+ DBGC ( image, "NBI %p length wrong (file %zd, metadata %zd)\n",
+ image, image->len, offset );
+ return -ENOEXEC;
+ }
+
+ return 0;
+}
+
+/**
+ * Boot a 16-bit NBI image
+ *
+ * @v imgheader Image header information
+ * @ret rc Return status code, if image returns
+ */
+static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) {
+ int discard_D, discard_S, discard_b;
+ int rc;
+
+ DBGC ( image, "NBI %p executing 16-bit image at %04x:%04x\n", image,
+ imgheader->execaddr.segoff.segment,
+ imgheader->execaddr.segoff.offset );
+
+ __asm__ __volatile__ (
+ REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
+ "pushw %%ds\n\t" /* far pointer to bootp data */
+ "pushw %%bx\n\t"
+ "pushl %%esi\n\t" /* location */
+ "pushw %%cs\n\t" /* lcall execaddr */
+ "call 1f\n\t"
+ "jmp 2f\n\t"
+ "\n1:\n\t"
+ "pushl %%edi\n\t"
+ "lret\n\t"
+ "\n2:\n\t"
+ "addw $8,%%sp\n\t" /* clean up stack */
+ "popl %%ebp\n\t" /* gcc bug */ )
+ : "=a" ( rc ), "=D" ( discard_D ), "=S" ( discard_S ),
+ "=b" ( discard_b )
+ : "D" ( imgheader->execaddr.segoff ),
+ "S" ( imgheader->location ),
+ "b" ( __from_data16 ( basemem_packet ) )
+ : "ecx", "edx" );
+
+ return rc;
+}
+
+/**
+ * Boot a 32-bit NBI image
+ *
+ * @v imgheader Image header information
+ * @ret rc Return status code, if image returns
+ */
+static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) {
+ int discard_D, discard_S, discard_b;
+ int rc;
+
+ DBGC ( image, "NBI %p executing 32-bit image at %lx\n",
+ image, imgheader->execaddr.linear );
+
+ /* Jump to OS with flat physical addressing */
+ __asm__ __volatile__ (
+ PHYS_CODE ( "pushl %%ebp\n\t" /* gcc bug */
+ "pushl %%ebx\n\t" /* bootp data */
+ "pushl %%esi\n\t" /* imgheader */
+ "pushl %%eax\n\t" /* loaderinfo */
+ "call *%%edi\n\t"
+ "addl $12, %%esp\n\t" /* clean up stack */
+ "popl %%ebp\n\t" /* gcc bug */ )
+ : "=a" ( rc ), "=D" ( discard_D ), "=S" ( discard_S ),
+ "=b" ( discard_b )
+ : "D" ( imgheader->execaddr.linear ),
+ "S" ( ( imgheader->location.segment << 4 ) +
+ imgheader->location.offset ),
+ "b" ( virt_to_phys ( basemem_packet ) ),
+ "a" ( virt_to_phys ( &loaderinfo ) )
+ : "ecx", "edx", "memory" );
+
+ return rc;
+}
+
+/**
+ * Prepare DHCP parameter block for NBI image
+ *
+ * @v image NBI image
+ * @ret rc Return status code
+ */
+static int nbi_prepare_dhcp ( struct image *image ) {
+ struct net_device *boot_netdev;
+ int rc;
+
+ boot_netdev = last_opened_netdev();
+ if ( ! boot_netdev ) {
+ DBGC ( image, "NBI %p could not identify a network device\n",
+ image );
+ return -ENODEV;
+ }
+
+ if ( ( rc = create_fakedhcpack ( boot_netdev, basemem_packet,
+ sizeof ( basemem_packet ) ) ) != 0 ) {
+ DBGC ( image, "NBI %p failed to build DHCP packet\n", image );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Execute a loaded NBI image
+ *
+ * @v image NBI image
+ * @ret rc Return status code
+ */
+static int nbi_exec ( struct image *image ) {
+ struct imgheader imgheader;
+ int may_return;
+ int rc;
+
+ /* Retrieve image header */
+ copy_from_user ( &imgheader, image->data, 0, sizeof ( imgheader ) );
+
+ DBGC ( image, "NBI %p placing header at %hx:%hx\n", image,
+ imgheader.location.segment, imgheader.location.offset );
+
+ /* NBI files can have overlaps between segments; the bss of
+ * one segment may overlap the initialised data of another. I
+ * assume this is a design flaw, but there are images out
+ * there that we need to work with. We therefore do two
+ * passes: first to initialise the segments, then to copy the
+ * data. This avoids zeroing out already-copied data.
+ */
+ if ( ( rc = nbi_process_segments ( image, &imgheader,
+ nbi_prepare_segment ) ) != 0 )
+ return rc;
+ if ( ( rc = nbi_process_segments ( image, &imgheader,
+ nbi_load_segment ) ) != 0 )
+ return rc;
+
+ /* Prepare DHCP option block */
+ if ( ( rc = nbi_prepare_dhcp ( image ) ) != 0 )
+ return rc;
+
+ /* Shut down now if NBI image will not return */
+ may_return = NBI_PROGRAM_RETURNS ( imgheader.flags );
+ if ( ! may_return )
+ shutdown_boot();
+
+ /* Execute NBI image */
+ if ( NBI_LINEAR_EXEC_ADDR ( imgheader.flags ) ) {
+ rc = nbi_boot32 ( image, &imgheader );
+ } else {
+ rc = nbi_boot16 ( image, &imgheader );
+ }
+
+ if ( ! may_return ) {
+ /* Cannot continue after shutdown() called */
+ DBGC ( image, "NBI %p returned %d from non-returnable image\n",
+ image, rc );
+ while ( 1 ) {}
+ }
+
+ DBGC ( image, "NBI %p returned %d\n", image, rc );
+
+ return rc;
+}
+
+/**
+ * Probe NBI image
+ *
+ * @v image NBI image
+ * @ret rc Return status code
+ */
+static int nbi_probe ( struct image *image ) {
+ struct imgheader imgheader;
+
+ /* If we don't have enough data give up */
+ if ( image->len < NBI_HEADER_LENGTH ) {
+ DBGC ( image, "NBI %p too short for an NBI image\n", image );
+ return -ENOEXEC;
+ }
+
+ /* Check image header */
+ copy_from_user ( &imgheader, image->data, 0, sizeof ( imgheader ) );
+ if ( imgheader.magic != NBI_MAGIC ) {
+ DBGC ( image, "NBI %p has no NBI signature\n", image );
+ return -ENOEXEC;
+ }
+
+ return 0;
+}
+
+/** NBI image type */
+struct image_type nbi_image_type __image_type ( PROBE_NORMAL ) = {
+ .name = "NBI",
+ .probe = nbi_probe,
+ .exec = nbi_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/image/pxe_image.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/pxe_image.c
new file mode 100644
index 00000000..bdccc93d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/image/pxe_image.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * PXE image format
+ *
+ */
+
+#include <pxe.h>
+#include <pxe_call.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/image.h>
+#include <ipxe/segment.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/features.h>
+
+FEATURE ( FEATURE_IMAGE, "PXE", DHCP_EB_FEATURE_PXE, 1 );
+
+/**
+ * Execute PXE image
+ *
+ * @v image PXE image
+ * @ret rc Return status code
+ */
+static int pxe_exec ( struct image *image ) {
+ userptr_t buffer = real_to_user ( 0, 0x7c00 );
+ struct net_device *netdev;
+ int rc;
+
+ /* Verify and prepare segment */
+ if ( ( rc = prep_segment ( buffer, image->len, image->len ) ) != 0 ) {
+ DBGC ( image, "IMAGE %p could not prepare segment: %s\n",
+ image, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Copy image to segment */
+ memcpy_user ( buffer, 0, image->data, 0, image->len );
+
+ /* Arbitrarily pick the most recently opened network device */
+ if ( ( netdev = last_opened_netdev() ) == NULL ) {
+ DBGC ( image, "IMAGE %p could not locate PXE net device\n",
+ image );
+ return -ENODEV;
+ }
+
+ /* Activate PXE */
+ pxe_activate ( netdev );
+
+ /* Start PXE NBP */
+ rc = pxe_start_nbp();
+
+ /* Deactivate PXE */
+ pxe_deactivate();
+
+ return rc;
+}
+
+/**
+ * Probe PXE image
+ *
+ * @v image PXE file
+ * @ret rc Return status code
+ */
+int pxe_probe ( struct image *image ) {
+
+ /* Images too large to fit in base memory cannot be PXE
+ * images. We include this check to help prevent unrecognised
+ * images from being marked as PXE images, since PXE images
+ * have no signature we can check against.
+ */
+ if ( image->len > ( 0xa0000 - 0x7c00 ) )
+ return -ENOEXEC;
+
+ /* Rejecting zero-length images is also useful, since these
+ * end up looking to the user like bugs in iPXE.
+ */
+ if ( ! image->len )
+ return -ENOEXEC;
+
+ return 0;
+}
+
+/** PXE image type */
+struct image_type pxe_image_type __image_type ( PROBE_PXE ) = {
+ .name = "PXE",
+ .probe = pxe_probe,
+ .exec = pxe_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/basemem.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/basemem.h
new file mode 100644
index 00000000..c477c7fe
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/basemem.h
@@ -0,0 +1,35 @@
+#ifndef _BASEMEM_H
+#define _BASEMEM_H
+
+/** @file
+ *
+ * Base memory allocation
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <realmode.h>
+#include <bios.h>
+
+/**
+ * Read the BIOS free base memory counter
+ *
+ * @ret fbms Free base memory counter (in kB)
+ */
+static inline unsigned int get_fbms ( void ) {
+ uint16_t fbms;
+
+ get_real ( fbms, BDA_SEG, BDA_FBMS );
+ return fbms;
+}
+
+extern void set_fbms ( unsigned int new_fbms );
+
+/* Actually in hidemem.c, but putting it here avoids polluting the
+ * architecture-independent include/hidemem.h.
+ */
+extern void hide_basemem ( void );
+
+#endif /* _BASEMEM_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/basemem_packet.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/basemem_packet.h
new file mode 100644
index 00000000..3cb47767
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/basemem_packet.h
@@ -0,0 +1,15 @@
+#ifndef BASEMEM_PACKET_H
+#define BASEMEM_PACKET_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <realmode.h>
+
+/** Maximum length of base memory packet buffer */
+#define BASEMEM_PACKET_LEN 1514
+
+/** Base memory packet buffer */
+extern char __bss16_array ( basemem_packet, [BASEMEM_PACKET_LEN] );
+#define basemem_packet __use_data16 ( basemem_packet )
+
+#endif /* BASEMEM_PACKET_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bios.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bios.h
new file mode 100644
index 00000000..fadb9f1b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bios.h
@@ -0,0 +1,11 @@
+#ifndef BIOS_H
+#define BIOS_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#define BDA_SEG 0x0040
+#define BDA_EQUIPMENT_WORD 0x0010
+#define BDA_FBMS 0x0013
+#define BDA_NUM_DRIVES 0x0075
+
+#endif /* BIOS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bios_disks.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bios_disks.h
new file mode 100644
index 00000000..0dd7c4eb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bios_disks.h
@@ -0,0 +1,69 @@
+#ifndef BIOS_DISKS_H
+#define BIOS_DISKS_H
+
+#include "dev.h"
+
+/*
+ * Constants
+ *
+ */
+
+#define BIOS_DISK_MAX_NAME_LEN 6
+
+struct bios_disk_sector {
+ char data[512];
+};
+
+/*
+ * The location of a BIOS disk
+ *
+ */
+struct bios_disk_loc {
+ uint8_t drive;
+};
+
+/*
+ * A physical BIOS disk device
+ *
+ */
+struct bios_disk_device {
+ char name[BIOS_DISK_MAX_NAME_LEN];
+ uint8_t drive;
+ uint8_t type;
+};
+
+/*
+ * A BIOS disk driver, with a valid device ID range and naming
+ * function.
+ *
+ */
+struct bios_disk_driver {
+ void ( *fill_drive_name ) ( char *buf, uint8_t drive );
+ uint8_t min_drive;
+ uint8_t max_drive;
+};
+
+/*
+ * Define a BIOS disk driver
+ *
+ */
+#define BIOS_DISK_DRIVER( _name, _fill_drive_name, _min_drive, _max_drive ) \
+ static struct bios_disk_driver _name = { \
+ .fill_drive_name = _fill_drive_name, \
+ .min_drive = _min_drive, \
+ .max_drive = _max_drive, \
+ }
+
+/*
+ * Functions in bios_disks.c
+ *
+ */
+
+
+/*
+ * bios_disk bus global definition
+ *
+ */
+extern struct bus_driver bios_disk_driver;
+
+#endif /* BIOS_DISKS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/biosint.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/biosint.h
new file mode 100644
index 00000000..ab466af3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/biosint.h
@@ -0,0 +1,33 @@
+#ifndef BIOSINT_H
+#define BIOSINT_H
+
+/**
+ * @file BIOS interrupts
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <realmode.h>
+
+struct segoff;
+
+/**
+ * Hooked interrupt count
+ *
+ * At exit, after unhooking all possible interrupts, this counter
+ * should be examined. If it is non-zero, it means that we failed to
+ * unhook at least one interrupt vector, and so must not free up the
+ * memory we are using. (Note that this also implies that we should
+ * re-hook INT 15 in order to hide ourselves from the memory map).
+ */
+extern uint16_t __text16 ( hooked_bios_interrupts );
+#define hooked_bios_interrupts __use_text16 ( hooked_bios_interrupts )
+
+extern void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
+ struct segoff *chain_vector );
+extern int unhook_bios_interrupt ( unsigned int interrupt,
+ unsigned int handler,
+ struct segoff *chain_vector );
+
+#endif /* BIOSINT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/byteswap.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/byteswap.h
new file mode 100644
index 00000000..f3d30a25
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/byteswap.h
@@ -0,0 +1,70 @@
+#ifndef _BITS_BYTESWAP_H
+#define _BITS_BYTESWAP_H
+
+/** @file
+ *
+ * Byte-order swapping functions
+ *
+ */
+
+#include <stdint.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+static inline __attribute__ (( always_inline, const )) uint16_t
+__bswap_variable_16 ( uint16_t x ) {
+ __asm__ ( "xchgb %b0,%h0" : "=q" ( x ) : "0" ( x ) );
+ return x;
+}
+
+static inline __attribute__ (( always_inline )) void
+__bswap_16s ( uint16_t *x ) {
+ __asm__ ( "rorw $8, %0" : "+m" ( *x ) );
+}
+
+static inline __attribute__ (( always_inline, const )) uint32_t
+__bswap_variable_32 ( uint32_t x ) {
+ __asm__ ( "bswapl %0" : "=r" ( x ) : "0" ( x ) );
+ return x;
+}
+
+static inline __attribute__ (( always_inline )) void
+__bswap_32s ( uint32_t *x ) {
+ __asm__ ( "bswapl %0" : "=r" ( *x ) : "0" ( *x ) );
+}
+
+static inline __attribute__ (( always_inline, const )) uint64_t
+__bswap_variable_64 ( uint64_t x ) {
+ uint32_t in_high = ( x >> 32 );
+ uint32_t in_low = ( x & 0xffffffffUL );
+ uint32_t out_high;
+ uint32_t out_low;
+
+ __asm__ ( "bswapl %0\n\t"
+ "bswapl %1\n\t"
+ "xchgl %0,%1\n\t"
+ : "=r" ( out_high ), "=r" ( out_low )
+ : "0" ( in_high ), "1" ( in_low ) );
+
+ return ( ( ( ( uint64_t ) out_high ) << 32 ) |
+ ( ( uint64_t ) out_low ) );
+}
+
+static inline __attribute__ (( always_inline )) void
+__bswap_64s ( uint64_t *x ) {
+ struct {
+ uint32_t low;
+ uint32_t high;
+ } __attribute__ (( may_alias )) *dwords = ( ( void * ) x );
+ uint32_t discard;
+
+ __asm__ ( "movl %0,%2\n\t"
+ "bswapl %2\n\t"
+ "xchgl %2,%1\n\t"
+ "bswapl %2\n\t"
+ "movl %2,%0\n\t"
+ : "+m" ( dwords->low ), "+m" ( dwords->high ),
+ "=r" ( discard ) );
+}
+
+#endif /* _BITS_BYTESWAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/compiler.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/compiler.h
new file mode 100644
index 00000000..000db0c1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/compiler.h
@@ -0,0 +1,27 @@
+#ifndef _BITS_COMPILER_H
+#define _BITS_COMPILER_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef ASSEMBLY
+
+/** Declare a function with standard calling conventions */
+#define __asmcall __attribute__ (( cdecl, regparm(0) ))
+
+/**
+ * Declare a function with libgcc implicit linkage
+ *
+ * It seems as though gcc expects its implicit arithmetic functions to
+ * be cdecl, even if -mrtd is specified. This is somewhat
+ * inconsistent; for example, if -mregparm=3 is used then the implicit
+ * functions do become regparm(3).
+ *
+ * The implicit calls to memcpy() and memset() which gcc can generate
+ * do not seem to have this inconsistency; -mregparm and -mrtd affect
+ * them in the same way as any other function.
+ */
+#define __libgcc __attribute__ (( cdecl ))
+
+#endif /* ASSEMBLY */
+
+#endif /* _BITS_COMPILER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/cpu.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/cpu.h
new file mode 100644
index 00000000..83339ddd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/cpu.h
@@ -0,0 +1,86 @@
+#ifndef I386_BITS_CPU_H
+#define I386_BITS_CPU_H
+
+/* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
+#define X86_FEATURE_FPU 0 /* Onboard FPU */
+#define X86_FEATURE_VME 1 /* Virtual Mode Extensions */
+#define X86_FEATURE_DE 2 /* Debugging Extensions */
+#define X86_FEATURE_PSE 3 /* Page Size Extensions */
+#define X86_FEATURE_TSC 4 /* Time Stamp Counter */
+#define X86_FEATURE_MSR 5 /* Model-Specific Registers, RDMSR, WRMSR */
+#define X86_FEATURE_PAE 6 /* Physical Address Extensions */
+#define X86_FEATURE_MCE 7 /* Machine Check Architecture */
+#define X86_FEATURE_CX8 8 /* CMPXCHG8 instruction */
+#define X86_FEATURE_APIC 9 /* Onboard APIC */
+#define X86_FEATURE_SEP 11 /* SYSENTER/SYSEXIT */
+#define X86_FEATURE_MTRR 12 /* Memory Type Range Registers */
+#define X86_FEATURE_PGE 13 /* Page Global Enable */
+#define X86_FEATURE_MCA 14 /* Machine Check Architecture */
+#define X86_FEATURE_CMOV 15 /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */
+#define X86_FEATURE_PAT 16 /* Page Attribute Table */
+#define X86_FEATURE_PSE36 17 /* 36-bit PSEs */
+#define X86_FEATURE_PN 18 /* Processor serial number */
+#define X86_FEATURE_CLFLSH 19 /* Supports the CLFLUSH instruction */
+#define X86_FEATURE_DTES 21 /* Debug Trace Store */
+#define X86_FEATURE_ACPI 22 /* ACPI via MSR */
+#define X86_FEATURE_MMX 23 /* Multimedia Extensions */
+#define X86_FEATURE_FXSR 24 /* FXSAVE and FXRSTOR instructions (fast save and restore */
+ /* of FPU context), and CR4.OSFXSR available */
+#define X86_FEATURE_XMM 25 /* Streaming SIMD Extensions */
+#define X86_FEATURE_XMM2 26 /* Streaming SIMD Extensions-2 */
+#define X86_FEATURE_SELFSNOOP 27 /* CPU self snoop */
+#define X86_FEATURE_HT 28 /* Hyper-Threading */
+#define X86_FEATURE_ACC 29 /* Automatic clock control */
+#define X86_FEATURE_IA64 30 /* IA-64 processor */
+
+/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
+/* Don't duplicate feature flags which are redundant with Intel! */
+#define X86_FEATURE_SYSCALL 11 /* SYSCALL/SYSRET */
+#define X86_FEATURE_MMXEXT 22 /* AMD MMX extensions */
+#define X86_FEATURE_LM 29 /* Long Mode (x86-64) */
+#define X86_FEATURE_3DNOWEXT 30 /* AMD 3DNow! extensions */
+#define X86_FEATURE_3DNOW 31 /* 3DNow! */
+
+/** x86 CPU information */
+struct cpuinfo_x86 {
+ /** CPU features */
+ unsigned int features;
+ /** 64-bit CPU features */
+ unsigned int amd_features;
+};
+
+/*
+ * EFLAGS bits
+ */
+#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */
+#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */
+#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */
+#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */
+#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */
+#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */
+#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */
+#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */
+#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */
+#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */
+#define X86_EFLAGS_NT 0x00004000 /* Nested Task */
+#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */
+#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */
+#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */
+#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */
+#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */
+#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */
+
+/*
+ * Generic CPUID function
+ */
+static inline __attribute__ (( always_inline )) void
+cpuid ( int op, unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx ) {
+ __asm__ ( "cpuid" :
+ "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx )
+ : "0" ( op ) );
+}
+
+extern void get_cpuinfo ( struct cpuinfo_x86 *cpu );
+
+#endif /* I386_BITS_CPU_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/endian.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/endian.h
new file mode 100644
index 00000000..84188542
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/endian.h
@@ -0,0 +1,8 @@
+#ifndef ETHERBOOT_BITS_ENDIAN_H
+#define ETHERBOOT_BITS_ENDIAN_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+#endif /* ETHERBOOT_BITS_ENDIAN_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/entropy.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/entropy.h
new file mode 100644
index 00000000..6dcceec6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/entropy.h
@@ -0,0 +1,14 @@
+#ifndef _BITS_ENTROPY_H
+#define _BITS_ENTROPY_H
+
+/** @file
+ *
+ * i386-specific entropy API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/rtc_entropy.h>
+
+#endif /* _BITS_ENTROPY_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/errfile.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/errfile.h
new file mode 100644
index 00000000..ccf00b86
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/errfile.h
@@ -0,0 +1,46 @@
+#ifndef _BITS_ERRFILE_H
+#define _BITS_ERRFILE_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @addtogroup errfile Error file identifiers
+ * @{
+ */
+
+#define ERRFILE_memtop_umalloc ( ERRFILE_ARCH | ERRFILE_CORE | 0x00000000 )
+#define ERRFILE_memmap ( ERRFILE_ARCH | ERRFILE_CORE | 0x00010000 )
+#define ERRFILE_pnpbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00020000 )
+#define ERRFILE_bios_smbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00030000 )
+#define ERRFILE_biosint ( ERRFILE_ARCH | ERRFILE_CORE | 0x00040000 )
+#define ERRFILE_int13 ( ERRFILE_ARCH | ERRFILE_CORE | 0x00050000 )
+#define ERRFILE_pxeparent ( ERRFILE_ARCH | ERRFILE_CORE | 0x00060000 )
+#define ERRFILE_runtime ( ERRFILE_ARCH | ERRFILE_CORE | 0x00070000 )
+#define ERRFILE_vmware ( ERRFILE_ARCH | ERRFILE_CORE | 0x00080000 )
+#define ERRFILE_guestrpc ( ERRFILE_ARCH | ERRFILE_CORE | 0x00090000 )
+#define ERRFILE_guestinfo ( ERRFILE_ARCH | ERRFILE_CORE | 0x000a0000 )
+
+#define ERRFILE_bootsector ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
+#define ERRFILE_bzimage ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )
+#define ERRFILE_eltorito ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00020000 )
+#define ERRFILE_multiboot ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00030000 )
+#define ERRFILE_nbi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00040000 )
+#define ERRFILE_pxe_image ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00050000 )
+#define ERRFILE_elfboot ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00060000 )
+#define ERRFILE_comboot ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00070000 )
+#define ERRFILE_com32 ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00080000 )
+#define ERRFILE_comboot_resolv ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00090000 )
+#define ERRFILE_comboot_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000a0000 )
+
+#define ERRFILE_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 )
+#define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 )
+#define ERRFILE_undinet ( ERRFILE_ARCH | ERRFILE_NET | 0x00020000 )
+#define ERRFILE_undionly ( ERRFILE_ARCH | ERRFILE_NET | 0x00030000 )
+#define ERRFILE_undirom ( ERRFILE_ARCH | ERRFILE_NET | 0x00040000 )
+
+#define ERRFILE_timer_rdtsc ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00000000 )
+#define ERRFILE_timer_bios ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00010000 )
+
+/** @} */
+
+#endif /* _BITS_ERRFILE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/io.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/io.h
new file mode 100644
index 00000000..f3ecf89b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/io.h
@@ -0,0 +1,14 @@
+#ifndef _BITS_IO_H
+#define _BITS_IO_H
+
+/** @file
+ *
+ * i386-specific I/O API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/x86_io.h>
+
+#endif /* _BITS_IO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/linux_api.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/linux_api.h
new file mode 100644
index 00000000..dc6e7416
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/linux_api.h
@@ -0,0 +1,6 @@
+#ifndef _I386_LINUX_API_H
+#define _I386_LINUX_API_H
+
+#define __SYSCALL_mmap __NR_mmap2
+
+#endif /* _I386_LINUX_API_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/nap.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/nap.h
new file mode 100644
index 00000000..64066e6a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/nap.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_NAP_H
+#define _BITS_NAP_H
+
+/** @file
+ *
+ * i386-specific CPU sleeping API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/bios_nap.h>
+#include <ipxe/efi/efix86_nap.h>
+
+#endif /* _BITS_MAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/sanboot.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/sanboot.h
new file mode 100644
index 00000000..9c77a4d4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/sanboot.h
@@ -0,0 +1,14 @@
+#ifndef _BITS_SANBOOT_H
+#define _BITS_SANBOOT_H
+
+/** @file
+ *
+ * i386-specific sanboot API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/bios_sanboot.h>
+
+#endif /* _BITS_SANBOOT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/smbios.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/smbios.h
new file mode 100644
index 00000000..cc79eec5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/smbios.h
@@ -0,0 +1,14 @@
+#ifndef _BITS_SMBIOS_H
+#define _BITS_SMBIOS_H
+
+/** @file
+ *
+ * i386-specific SMBIOS API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/bios_smbios.h>
+
+#endif /* _BITS_SMBIOS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/stdint.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/stdint.h
new file mode 100644
index 00000000..8edf1319
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/stdint.h
@@ -0,0 +1,23 @@
+#ifndef _BITS_STDINT_H
+#define _BITS_STDINT_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+typedef __SIZE_TYPE__ size_t;
+typedef signed long ssize_t;
+typedef signed long off_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+
+typedef unsigned long physaddr_t;
+typedef unsigned long intptr_t;
+
+#endif /* _BITS_STDINT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/time.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/time.h
new file mode 100644
index 00000000..24dd020e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/time.h
@@ -0,0 +1,14 @@
+#ifndef _BITS_TIME_H
+#define _BITS_TIME_H
+
+/** @file
+ *
+ * i386-specific time API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/rtc_time.h>
+
+#endif /* _BITS_TIME_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/timer.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/timer.h
new file mode 100644
index 00000000..50b676b7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/timer.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_TIMER_H
+#define _BITS_TIMER_H
+
+/** @file
+ *
+ * i386-specific timer API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/bios_timer.h>
+#include <ipxe/rdtsc_timer.h>
+
+#endif /* _BITS_TIMER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/uaccess.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/uaccess.h
new file mode 100644
index 00000000..2bb52e02
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/uaccess.h
@@ -0,0 +1,14 @@
+#ifndef _BITS_UACCESS_H
+#define _BITS_UACCESS_H
+
+/** @file
+ *
+ * i386-specific user access API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <librm.h>
+
+#endif /* _BITS_UACCESS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/umalloc.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/umalloc.h
new file mode 100644
index 00000000..54fb006f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bits/umalloc.h
@@ -0,0 +1,14 @@
+#ifndef _BITS_UMALLOC_H
+#define _BITS_UMALLOC_H
+
+/** @file
+ *
+ * i386-specific user memory allocation API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/memtop_umalloc.h>
+
+#endif /* _BITS_UMALLOC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bochs.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bochs.h
new file mode 100644
index 00000000..9d090fc1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bochs.h
@@ -0,0 +1,34 @@
+#ifndef BOCHS_H
+#define BOCHS_H
+
+/** @file
+ *
+ * bochs breakpoints
+ *
+ * This file defines @c bochsbp, the magic breakpoint instruction that
+ * is incredibly useful when debugging under bochs. This file should
+ * never be included in production code.
+ *
+ * Use the pseudo-instruction @c bochsbp in assembly code, or the
+ * bochsbp() function in C code.
+ *
+ */
+
+#ifdef ASSEMBLY
+
+/* Breakpoint for when debugging under bochs */
+#define bochsbp xchgw %bx, %bx
+#define BOCHSBP bochsbp
+
+#else /* ASSEMBLY */
+
+/** Breakpoint for when debugging under bochs */
+static inline void bochsbp ( void ) {
+ __asm__ __volatile__ ( "xchgw %bx, %bx" );
+}
+
+#endif /* ASSEMBLY */
+
+#warning "bochs.h should not be included into production code"
+
+#endif /* BOCHS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bootsector.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bootsector.h
new file mode 100644
index 00000000..8730fbfc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bootsector.h
@@ -0,0 +1,14 @@
+#ifndef _BOOTSECTOR_H
+#define _BOOTSECTOR_H
+
+/** @file
+ *
+ * x86 bootsector image format
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern int call_bootsector ( unsigned int segment, unsigned int offset,
+ unsigned int drive );
+
+#endif /* _BOOTSECTOR_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bzimage.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bzimage.h
new file mode 100644
index 00000000..7e42e318
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/bzimage.h
@@ -0,0 +1,142 @@
+#ifndef _BZIMAGE_H
+#define _BZIMAGE_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/**
+ * A bzImage header
+ *
+ * As documented in Documentation/i386/boot.txt
+ */
+struct bzimage_header {
+ /** The size of the setup in sectors
+ *
+ * If this field contains 0, assume it contains 4.
+ */
+ uint8_t setup_sects;
+ /** If set, the root is mounted readonly */
+ uint16_t root_flags;
+ /** DO NOT USE - for bootsect.S use only */
+ uint16_t syssize;
+ /** DO NOT USE - obsolete */
+ uint16_t swap_dev;
+ /** DO NOT USE - for bootsect.S use only */
+ uint16_t ram_size;
+ /** Video mode control */
+ uint16_t vid_mode;
+ /** Default root device number */
+ uint16_t root_dev;
+ /** 0xAA55 magic number */
+ uint16_t boot_flag;
+ /** Jump instruction */
+ uint16_t jump;
+ /** Magic signature "HdrS" */
+ uint32_t header;
+ /** Boot protocol version supported */
+ uint16_t version;
+ /** Boot loader hook (see below) */
+ uint32_t realmode_swtch;
+ /** The load-low segment (0x1000) (obsolete) */
+ uint16_t start_sys;
+ /** Pointer to kernel version string */
+ uint16_t kernel_version;
+ /** Boot loader identifier */
+ uint8_t type_of_loader;
+ /** Boot protocol option flags */
+ uint8_t loadflags;
+ /** Move to high memory size (used with hooks) */
+ uint16_t setup_move_size;
+ /** Boot loader hook (see below) */
+ uint32_t code32_start;
+ /** initrd load address (set by boot loader) */
+ uint32_t ramdisk_image;
+ /** initrd size (set by boot loader) */
+ uint32_t ramdisk_size;
+ /** DO NOT USE - for bootsect.S use only */
+ uint32_t bootsect_kludge;
+ /** Free memory after setup end */
+ uint16_t heap_end_ptr;
+ /** Unused */
+ uint16_t pad1;
+ /** 32-bit pointer to the kernel command line */
+ uint32_t cmd_line_ptr;
+ /** Highest legal initrd address */
+ uint32_t initrd_addr_max;
+ /** Physical addr alignment required for kernel */
+ uint32_t kernel_alignment;
+ /** Whether kernel is relocatable or not */
+ uint8_t relocatable_kernel;
+ /** Unused */
+ uint8_t pad2[3];
+ /** Maximum size of the kernel command line */
+ uint32_t cmdline_size;
+} __attribute__ (( packed ));
+
+/** Offset of bzImage header within kernel image */
+#define BZI_HDR_OFFSET 0x1f1
+
+/** bzImage boot flag value */
+#define BZI_BOOT_FLAG 0xaa55
+
+/** bzImage magic signature value */
+#define BZI_SIGNATURE 0x53726448
+
+/** bzImage boot loader identifier for Etherboot */
+#define BZI_LOADER_TYPE_ETHERBOOT 0x40
+
+/** bzImage boot loader identifier for iPXE
+ *
+ * We advertise ourselves as Etherboot version 6.
+ */
+#define BZI_LOADER_TYPE_IPXE ( BZI_LOADER_TYPE_ETHERBOOT | 0x06 )
+
+/** bzImage "load high" flag */
+#define BZI_LOAD_HIGH 0x01
+
+/** Load address for high-loaded kernels */
+#define BZI_LOAD_HIGH_ADDR 0x100000
+
+/** Load address for low-loaded kernels */
+#define BZI_LOAD_LOW_ADDR 0x10000
+
+/** bzImage "kernel can use heap" flag */
+#define BZI_CAN_USE_HEAP 0x80
+
+/** bzImage special video mode "normal" */
+#define BZI_VID_MODE_NORMAL 0xffff
+
+/** bzImage special video mode "ext" */
+#define BZI_VID_MODE_EXT 0xfffe
+
+/** bzImage special video mode "ask" */
+#define BZI_VID_MODE_ASK 0xfffd
+
+/** bzImage maximum initrd address for versions < 2.03 */
+#define BZI_INITRD_MAX 0x37ffffff
+
+/** bzImage command-line structure used by older kernels */
+struct bzimage_cmdline {
+ /** Magic signature */
+ uint16_t magic;
+ /** Offset to command line */
+ uint16_t offset;
+} __attribute__ (( packed ));
+
+/** Offset of bzImage command-line structure within kernel image */
+#define BZI_CMDLINE_OFFSET 0x20
+
+/** bzImage command line present magic marker value */
+#define BZI_CMDLINE_MAGIC 0xa33f
+
+/** Assumed size of real-mode portion (including .bss) */
+#define BZI_ASSUMED_RM_SIZE 0x8000
+
+/** Amount of stack space to provide */
+#define BZI_STACK_SIZE 0x1000
+
+/** Maximum size of command line */
+#define BZI_CMDLINE_SIZE 0x7ff
+
+#endif /* _BZIMAGE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/comboot.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/comboot.h
new file mode 100644
index 00000000..b3434139
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/comboot.h
@@ -0,0 +1,177 @@
+#ifndef COMBOOT_H
+#define COMBOOT_H
+
+/**
+ * @file
+ *
+ * SYSLINUX COMBOOT
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <setjmp.h>
+#include <ipxe/in.h>
+
+/** Descriptor in a 32-bit IDT */
+struct idt_descriptor {
+ uint16_t offset_low;
+ uint16_t selector;
+ uint16_t flags;
+ uint16_t offset_high;
+} __attribute__ (( packed ));
+
+/** Operand for the LIDT instruction */
+struct idt_register {
+ uint16_t limit;
+ uint32_t base;
+} __attribute__ (( packed ));
+
+/** Entry in the interrupt jump buffer */
+struct ijb_entry {
+ uint8_t pusha_instruction;
+ uint8_t mov_instruction;
+ uint8_t mov_value;
+ uint8_t jump_instruction;
+ uint32_t jump_destination;
+} __attribute__ (( packed ));
+
+/** The x86 opcode for "pushal" */
+#define IJB_PUSHA 0x60
+
+/** The x86 opcode for "movb $imm8,%al" */
+#define IJB_MOV_AL_IMM8 0xB0
+
+/** The x86 opcode for "jmp rel32" */
+#define IJB_JMP_REL32 0xE9
+
+/** Flags that specify a 32-bit interrupt gate with DPL=0 */
+#define IDT_INTERRUPT_GATE_FLAGS 0x8E00
+
+/** Address of COM32 interrupt descriptor table */
+#define COM32_IDT 0x100000
+
+/** Number of entries in a fully populated IDT */
+#define COM32_NUM_IDT_ENTRIES 256
+
+/** Address of COM32 interrupt jump buffer */
+#define COM32_IJB 0x100800
+
+/** Segment used for COMBOOT PSP and image */
+#define COMBOOT_PSP_SEG 0x07C0
+
+/** Entry point address of COM32 images */
+#define COM32_START_PHYS 0x101000
+
+/** COM32 bounce buffer segment */
+#define COM32_BOUNCE_SEG 0x07C0
+
+/** Size of SYSLINUX file block in bytes */
+#define COMBOOT_FILE_BLOCKSZ 512
+
+/** COMBOOT feature flags (INT 22h AX=15h) */
+#define COMBOOT_FEATURE_LOCAL_BOOT (1 << 0)
+#define COMBOOT_FEATURE_IDLE_LOOP (1 << 1)
+
+/** Maximum number of shuffle descriptors for
+ * shuffle and boot functions
+ * (INT 22h AX=0012h, 001Ah, 001Bh)
+ */
+#define COMBOOT_MAX_SHUFFLE_DESCRIPTORS 682
+
+typedef union {
+ uint32_t l;
+ uint16_t w[2];
+ uint8_t b[4];
+} com32_reg32_t;
+
+typedef struct {
+ uint16_t gs; /* Offset 0 */
+ uint16_t fs; /* Offset 2 */
+ uint16_t es; /* Offset 4 */
+ uint16_t ds; /* Offset 6 */
+
+ com32_reg32_t edi; /* Offset 8 */
+ com32_reg32_t esi; /* Offset 12 */
+ com32_reg32_t ebp; /* Offset 16 */
+ com32_reg32_t _unused_esp; /* Offset 20 */
+ com32_reg32_t ebx; /* Offset 24 */
+ com32_reg32_t edx; /* Offset 28 */
+ com32_reg32_t ecx; /* Offset 32 */
+ com32_reg32_t eax; /* Offset 36 */
+
+ com32_reg32_t eflags; /* Offset 40 */
+} com32sys_t;
+
+typedef struct {
+ uint32_t eax; /* Offset 0 */
+ uint32_t ecx; /* Offset 4 */
+ uint32_t edx; /* Offset 8 */
+ uint32_t ebx; /* Offset 12 */
+ uint32_t esp; /* Offset 16 */
+ uint32_t ebp; /* Offset 20 */
+ uint32_t esi; /* Offset 24 */
+ uint32_t edi; /* Offset 28 */
+
+ uint32_t eip; /* Offset 32 */
+} syslinux_pm_regs;
+
+typedef struct {
+ uint16_t es; /* Offset 0 */
+ uint16_t _unused_cs; /* Offset 2 */
+ uint16_t ds; /* Offset 4 */
+ uint16_t ss; /* Offset 6 */
+ uint16_t fs; /* Offset 8 */
+ uint16_t gs; /* Offset 10 */
+
+ uint32_t eax; /* Offset 12 */
+ uint32_t ecx; /* Offset 16 */
+ uint32_t edx; /* Offset 20 */
+ uint32_t ebx; /* Offset 24 */
+ uint32_t esp; /* Offset 28 */
+ uint32_t ebp; /* Offset 32 */
+ uint32_t esi; /* Offset 36 */
+ uint32_t edi; /* Offset 40 */
+
+ uint16_t ip; /* Offset 44 */
+ uint16_t cs; /* Offset 46 */
+} syslinux_rm_regs;
+
+typedef struct {
+ uint32_t dest;
+ uint32_t src;
+ uint32_t len;
+} comboot_shuffle_descriptor;
+
+extern void hook_comboot_interrupts ( );
+extern void unhook_comboot_interrupts ( );
+
+/* These are not the correct prototypes, but it doens't matter,
+ * as we only ever get the address of these functions;
+ * they are only called from COM32 code running in PHYS_CODE
+ */
+extern void com32_intcall_wrapper ( );
+extern void com32_farcall_wrapper ( );
+extern void com32_cfarcall_wrapper ( );
+extern void com32_irq_wrapper ( );
+
+/* Resolve a hostname to an (IPv4) address */
+extern int comboot_resolv ( const char *name, struct in_addr *address );
+
+/* setjmp/longjmp context buffer used to return after loading an image */
+extern rmjmp_buf comboot_return;
+
+extern void *com32_external_esp;
+
+#define COMBOOT_EXIT 1
+#define COMBOOT_EXIT_RUN_KERNEL 2
+#define COMBOOT_EXIT_COMMAND 3
+
+extern void comboot_force_text_mode ( void );
+
+#define COMBOOT_VIDEO_GRAPHICS 0x01
+#define COMBOOT_VIDEO_NONSTANDARD 0x02
+#define COMBOOT_VIDEO_VESA 0x04
+#define COMBOOT_VIDEO_NOTEXT 0x08
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/efi/ipxe/dhcp_arch.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/efi/ipxe/dhcp_arch.h
new file mode 100644
index 00000000..18417721
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/efi/ipxe/dhcp_arch.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _DHCP_ARCH_H
+#define _DHCP_ARCH_H
+
+/** @file
+ *
+ * Architecture-specific DHCP options
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/dhcp.h>
+
+#define DHCP_ARCH_VENDOR_CLASS_ID \
+ DHCP_STRING ( 'P', 'X', 'E', 'C', 'l', 'i', 'e', 'n', 't', ':', \
+ 'A', 'r', 'c', 'h', ':', '0', '0', '0', '0', '6', ':', \
+ 'U', 'N', 'D', 'I', ':', '0', '0', '3', '0', '1', '0' )
+
+#define DHCP_ARCH_CLIENT_ARCHITECTURE \
+ DHCP_WORD ( DHCP_CLIENT_ARCHITECTURE_IA32 )
+
+#define DHCP_ARCH_CLIENT_NDI DHCP_OPTION ( 1 /* UNDI */ , 3, 10 /* v3.10 */ )
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/fakee820.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/fakee820.h
new file mode 100644
index 00000000..9d00fb67
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/fakee820.h
@@ -0,0 +1,9 @@
+#ifndef _FAKEE820_H
+#define _FAKEE820_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern void fake_e820 ( void );
+extern void unfake_e820 ( void );
+
+#endif /* _FAKEE820_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/gdbmach.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/gdbmach.h
new file mode 100644
index 00000000..794dab19
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/gdbmach.h
@@ -0,0 +1,64 @@
+#ifndef GDBMACH_H
+#define GDBMACH_H
+
+/** @file
+ *
+ * GDB architecture specifics
+ *
+ * This file declares functions for manipulating the machine state and
+ * debugging context.
+ *
+ */
+
+#include <stdint.h>
+
+typedef unsigned long gdbreg_t;
+
+/* The register snapshot, this must be in sync with interrupt handler and the
+ * GDB protocol. */
+enum {
+ GDBMACH_EAX,
+ GDBMACH_ECX,
+ GDBMACH_EDX,
+ GDBMACH_EBX,
+ GDBMACH_ESP,
+ GDBMACH_EBP,
+ GDBMACH_ESI,
+ GDBMACH_EDI,
+ GDBMACH_EIP,
+ GDBMACH_EFLAGS,
+ GDBMACH_CS,
+ GDBMACH_SS,
+ GDBMACH_DS,
+ GDBMACH_ES,
+ GDBMACH_FS,
+ GDBMACH_GS,
+ GDBMACH_NREGS,
+ GDBMACH_SIZEOF_REGS = GDBMACH_NREGS * sizeof ( gdbreg_t )
+};
+
+/* Breakpoint types */
+enum {
+ GDBMACH_BPMEM,
+ GDBMACH_BPHW,
+ GDBMACH_WATCH,
+ GDBMACH_RWATCH,
+ GDBMACH_AWATCH,
+};
+
+static inline void gdbmach_set_pc ( gdbreg_t *regs, gdbreg_t pc ) {
+ regs [ GDBMACH_EIP ] = pc;
+}
+
+static inline void gdbmach_set_single_step ( gdbreg_t *regs, int step ) {
+ regs [ GDBMACH_EFLAGS ] &= ~( 1 << 8 ); /* Trace Flag (TF) */
+ regs [ GDBMACH_EFLAGS ] |= ( step << 8 );
+}
+
+static inline void gdbmach_breakpoint ( void ) {
+ __asm__ __volatile__ ( "int $3\n" );
+}
+
+extern int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len, int enable );
+
+#endif /* GDBMACH_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/int13.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/int13.h
new file mode 100644
index 00000000..5d36b637
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/int13.h
@@ -0,0 +1,449 @@
+#ifndef INT13_H
+#define INT13_H
+
+/** @file
+ *
+ * INT 13 emulation
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/list.h>
+#include <ipxe/edd.h>
+#include <realmode.h>
+
+/**
+ * @defgroup int13ops INT 13 operation codes
+ * @{
+ */
+
+/** Reset disk system */
+#define INT13_RESET 0x00
+/** Get status of last operation */
+#define INT13_GET_LAST_STATUS 0x01
+/** Read sectors */
+#define INT13_READ_SECTORS 0x02
+/** Write sectors */
+#define INT13_WRITE_SECTORS 0x03
+/** Get drive parameters */
+#define INT13_GET_PARAMETERS 0x08
+/** Get disk type */
+#define INT13_GET_DISK_TYPE 0x15
+/** Extensions installation check */
+#define INT13_EXTENSION_CHECK 0x41
+/** Extended read */
+#define INT13_EXTENDED_READ 0x42
+/** Extended write */
+#define INT13_EXTENDED_WRITE 0x43
+/** Verify sectors */
+#define INT13_EXTENDED_VERIFY 0x44
+/** Extended seek */
+#define INT13_EXTENDED_SEEK 0x47
+/** Get extended drive parameters */
+#define INT13_GET_EXTENDED_PARAMETERS 0x48
+/** Get CD-ROM status / terminate emulation */
+#define INT13_CDROM_STATUS_TERMINATE 0x4b
+/** Read CD-ROM boot catalog */
+#define INT13_CDROM_READ_BOOT_CATALOG 0x4d
+
+/** @} */
+
+/**
+ * @defgroup int13status INT 13 status codes
+ * @{
+ */
+
+/** Operation completed successfully */
+#define INT13_STATUS_SUCCESS 0x00
+/** Invalid function or parameter */
+#define INT13_STATUS_INVALID 0x01
+/** Read error */
+#define INT13_STATUS_READ_ERROR 0x04
+/** Reset failed */
+#define INT13_STATUS_RESET_FAILED 0x05
+/** Write error */
+#define INT13_STATUS_WRITE_ERROR 0xcc
+
+/** @} */
+
+/** Block size for non-extended INT 13 calls */
+#define INT13_BLKSIZE 512
+
+/** @defgroup int13fddtype INT 13 floppy disk drive types
+ * @{
+ */
+
+/** 360K */
+#define INT13_FDD_TYPE_360K 0x01
+/** 1.2M */
+#define INT13_FDD_TYPE_1M2 0x02
+/** 720K */
+#define INT13_FDD_TYPE_720K 0x03
+/** 1.44M */
+#define INT13_FDD_TYPE_1M44 0x04
+
+/** An INT 13 disk address packet */
+struct int13_disk_address {
+ /** Size of the packet, in bytes */
+ uint8_t bufsize;
+ /** Reserved */
+ uint8_t reserved_a;
+ /** Block count */
+ uint8_t count;
+ /** Reserved */
+ uint8_t reserved_b;
+ /** Data buffer */
+ struct segoff buffer;
+ /** Starting block number */
+ uint64_t lba;
+ /** Data buffer (EDD 3.0+ only) */
+ uint64_t buffer_phys;
+ /** Block count (EDD 4.0+ only) */
+ uint32_t long_count;
+ /** Reserved */
+ uint32_t reserved_c;
+} __attribute__ (( packed ));
+
+/** INT 13 disk parameters */
+struct int13_disk_parameters {
+ /** Size of this structure */
+ uint16_t bufsize;
+ /** Flags */
+ uint16_t flags;
+ /** Number of cylinders */
+ uint32_t cylinders;
+ /** Number of heads */
+ uint32_t heads;
+ /** Number of sectors per track */
+ uint32_t sectors_per_track;
+ /** Total number of sectors on drive */
+ uint64_t sectors;
+ /** Bytes per sector */
+ uint16_t sector_size;
+ /** Device parameter table extension */
+ struct segoff dpte;
+ /** Device path information */
+ struct edd_device_path_information dpi;
+} __attribute__ (( packed ));
+
+/**
+ * @defgroup int13types INT 13 disk types
+ * @{
+ */
+
+/** No such drive */
+#define INT13_DISK_TYPE_NONE 0x00
+/** Floppy without change-line support */
+#define INT13_DISK_TYPE_FDD 0x01
+/** Floppy with change-line support */
+#define INT13_DISK_TYPE_FDD_CL 0x02
+/** Hard disk */
+#define INT13_DISK_TYPE_HDD 0x03
+
+/** @} */
+
+/**
+ * @defgroup int13flags INT 13 disk parameter flags
+ * @{
+ */
+
+/** DMA boundary errors handled transparently */
+#define INT13_FL_DMA_TRANSPARENT 0x01
+/** CHS information is valid */
+#define INT13_FL_CHS_VALID 0x02
+/** Removable drive */
+#define INT13_FL_REMOVABLE 0x04
+/** Write with verify supported */
+#define INT13_FL_VERIFIABLE 0x08
+/** Has change-line supported (valid only for removable drives) */
+#define INT13_FL_CHANGE_LINE 0x10
+/** Drive can be locked (valid only for removable drives) */
+#define INT13_FL_LOCKABLE 0x20
+/** CHS is max possible, not current media (valid only for removable drives) */
+#define INT13_FL_CHS_MAX 0x40
+
+/** @} */
+
+/**
+ * @defgroup int13exts INT 13 extension flags
+ * @{
+ */
+
+/** Extended disk access functions supported */
+#define INT13_EXTENSION_LINEAR 0x01
+/** Removable drive functions supported */
+#define INT13_EXTENSION_REMOVABLE 0x02
+/** EDD functions supported */
+#define INT13_EXTENSION_EDD 0x04
+/** 64-bit extensions are present */
+#define INT13_EXTENSION_64BIT 0x08
+
+/** @} */
+
+/**
+ * @defgroup int13vers INT 13 extension versions
+ * @{
+ */
+
+/** INT13 extensions version 1.x */
+#define INT13_EXTENSION_VER_1_X 0x01
+/** INT13 extensions version 2.0 (EDD-1.0) */
+#define INT13_EXTENSION_VER_2_0 0x20
+/** INT13 extensions version 2.1 (EDD-1.1) */
+#define INT13_EXTENSION_VER_2_1 0x21
+/** INT13 extensions version 3.0 (EDD-3.0) */
+#define INT13_EXTENSION_VER_3_0 0x30
+
+/** @} */
+
+/** Maximum number of sectors for which CHS geometry is allowed to be valid
+ *
+ * This number is taken from the EDD specification.
+ */
+#define INT13_MAX_CHS_SECTORS 15482880
+
+/** Bootable CD-ROM specification packet */
+struct int13_cdrom_specification {
+ /** Size of packet in bytes */
+ uint8_t size;
+ /** Boot media type */
+ uint8_t media_type;
+ /** Drive number */
+ uint8_t drive;
+ /** CD-ROM controller number */
+ uint8_t controller;
+ /** LBA of disk image to emulate */
+ uint32_t lba;
+ /** Device specification */
+ uint16_t device;
+ /** Segment of 3K buffer for caching CD-ROM reads */
+ uint16_t cache_segment;
+ /** Load segment for initial boot image */
+ uint16_t load_segment;
+ /** Number of 512-byte sectors to load */
+ uint16_t load_sectors;
+ /** Low 8 bits of cylinder number */
+ uint8_t cyl;
+ /** Sector number, plus high 2 bits of cylinder number */
+ uint8_t cyl_sector;
+ /** Head number */
+ uint8_t head;
+} __attribute__ (( packed ));
+
+/** Bootable CD-ROM boot catalog command packet */
+struct int13_cdrom_boot_catalog_command {
+ /** Size of packet in bytes */
+ uint8_t size;
+ /** Number of sectors of boot catalog to read */
+ uint8_t count;
+ /** Buffer for boot catalog */
+ uint32_t buffer;
+ /** First sector in boot catalog to transfer */
+ uint16_t start;
+} __attribute__ (( packed ));
+
+/** A C/H/S address within a partition table entry */
+struct partition_chs {
+ /** Head number */
+ uint8_t head;
+ /** Sector number, plus high 2 bits of cylinder number */
+ uint8_t cyl_sector;
+ /** Low 8 bits of cylinder number */
+ uint8_t cyl;
+} __attribute__ (( packed ));
+
+#define PART_HEAD(chs) ( (chs).head )
+#define PART_SECTOR(chs) ( (chs).cyl_sector & 0x3f )
+#define PART_CYLINDER(chs) ( (chs).cyl | ( ( (chs).cyl_sector & 0xc0 ) << 2 ) )
+
+/** A partition table entry within the MBR */
+struct partition_table_entry {
+ /** Bootable flag */
+ uint8_t bootable;
+ /** C/H/S start address */
+ struct partition_chs chs_start;
+ /** System indicator (partition type) */
+ uint8_t type;
+ /** C/H/S end address */
+ struct partition_chs chs_end;
+ /** Linear start address */
+ uint32_t start;
+ /** Linear length */
+ uint32_t length;
+} __attribute__ (( packed ));
+
+/** A Master Boot Record */
+struct master_boot_record {
+ /** Code area */
+ uint8_t code[440];
+ /** Disk signature */
+ uint32_t signature;
+ /** Padding */
+ uint8_t pad[2];
+ /** Partition table */
+ struct partition_table_entry partitions[4];
+ /** 0x55aa MBR signature */
+ uint16_t magic;
+} __attribute__ (( packed ));
+
+/** MBR magic signature */
+#define INT13_MBR_MAGIC 0xaa55
+
+/** ISO9660 block size */
+#define ISO9660_BLKSIZE 2048
+
+/** An ISO9660 Primary Volume Descriptor (fixed portion) */
+struct iso9660_primary_descriptor_fixed {
+ /** Descriptor type */
+ uint8_t type;
+ /** Identifier ("CD001") */
+ uint8_t id[5];
+} __attribute__ (( packed ));
+
+/** An ISO9660 Primary Volume Descriptor */
+struct iso9660_primary_descriptor {
+ /** Fixed portion */
+ struct iso9660_primary_descriptor_fixed fixed;
+} __attribute__ (( packed ));
+
+/** ISO9660 Primary Volume Descriptor type */
+#define ISO9660_TYPE_PRIMARY 0x01
+
+/** ISO9660 identifier */
+#define ISO9660_ID "CD001"
+
+/** ISO9660 Primary Volume Descriptor block address */
+#define ISO9660_PRIMARY_LBA 16
+
+/** An El Torito Boot Record Volume Descriptor (fixed portion) */
+struct eltorito_descriptor_fixed {
+ /** Descriptor type */
+ uint8_t type;
+ /** Identifier ("CD001") */
+ uint8_t id[5];
+ /** Version, must be 1 */
+ uint8_t version;
+ /** Boot system indicator; must be "EL TORITO SPECIFICATION" */
+ uint8_t system_id[32];
+} __attribute__ (( packed ));
+
+/** An El Torito Boot Record Volume Descriptor */
+struct eltorito_descriptor {
+ /** Fixed portion */
+ struct eltorito_descriptor_fixed fixed;
+ /** Unused */
+ uint8_t unused[32];
+ /** Boot catalog sector */
+ uint32_t sector;
+} __attribute__ (( packed ));
+
+/** ISO9660 Boot Volume Descriptor type */
+#define ISO9660_TYPE_BOOT 0x00
+
+/** El Torito Boot Record Volume Descriptor block address */
+#define ELTORITO_LBA 17
+
+/** An El Torito Boot Catalog Validation Entry */
+struct eltorito_validation_entry {
+ /** Header ID; must be 1 */
+ uint8_t header_id;
+ /** Platform ID
+ *
+ * 0 = 80x86
+ * 1 = PowerPC
+ * 2 = Mac
+ */
+ uint8_t platform_id;
+ /** Reserved */
+ uint16_t reserved;
+ /** ID string */
+ uint8_t id_string[24];
+ /** Checksum word */
+ uint16_t checksum;
+ /** Signature; must be 0xaa55 */
+ uint16_t signature;
+} __attribute__ (( packed ));
+
+/** El Torito platform IDs */
+enum eltorito_platform_id {
+ ELTORITO_PLATFORM_X86 = 0x00,
+ ELTORITO_PLATFORM_POWERPC = 0x01,
+ ELTORITO_PLATFORM_MAC = 0x02,
+};
+
+/** A bootable entry in the El Torito Boot Catalog */
+struct eltorito_boot_entry {
+ /** Boot indicator
+ *
+ * Must be @c ELTORITO_BOOTABLE for a bootable ISO image
+ */
+ uint8_t indicator;
+ /** Media type
+ *
+ */
+ uint8_t media_type;
+ /** Load segment */
+ uint16_t load_segment;
+ /** System type */
+ uint8_t filesystem;
+ /** Unused */
+ uint8_t reserved_a;
+ /** Sector count */
+ uint16_t length;
+ /** Starting sector */
+ uint32_t start;
+ /** Unused */
+ uint8_t reserved_b[20];
+} __attribute__ (( packed ));
+
+/** Boot indicator for a bootable ISO image */
+#define ELTORITO_BOOTABLE 0x88
+
+/** El Torito media types */
+enum eltorito_media_type {
+ /** No emulation */
+ ELTORITO_NO_EMULATION = 0,
+};
+
+/** A floppy disk geometry */
+struct int13_fdd_geometry {
+ /** Number of tracks */
+ uint8_t tracks;
+ /** Number of heads and sectors per track */
+ uint8_t heads_spt;
+};
+
+/** Define a floppy disk geometry */
+#define INT13_FDD_GEOMETRY( cylinders, heads, sectors ) \
+ { \
+ .tracks = (cylinders), \
+ .heads_spt = ( ( (heads) << 6 ) | (sectors) ), \
+ }
+
+/** Get floppy disk number of cylinders */
+#define INT13_FDD_CYLINDERS( geometry ) ( (geometry)->tracks )
+
+/** Get floppy disk number of heads */
+#define INT13_FDD_HEADS( geometry ) ( (geometry)->heads_spt >> 6 )
+
+/** Get floppy disk number of sectors per track */
+#define INT13_FDD_SECTORS( geometry ) ( (geometry)->heads_spt & 0x3f )
+
+/** A floppy drive parameter table */
+struct int13_fdd_parameters {
+ uint8_t step_rate__head_unload;
+ uint8_t head_load__ndma;
+ uint8_t motor_off_delay;
+ uint8_t bytes_per_sector;
+ uint8_t sectors_per_track;
+ uint8_t gap_length;
+ uint8_t data_length;
+ uint8_t format_gap_length;
+ uint8_t format_filler;
+ uint8_t head_settle_time;
+ uint8_t motor_start_time;
+} __attribute__ (( packed ));
+
+#endif /* INT13_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_nap.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_nap.h
new file mode 100644
index 00000000..5b684c04
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_nap.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_BIOS_NAP_H
+#define _IPXE_BIOS_NAP_H
+
+/** @file
+ *
+ * BIOS CPU sleeping
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef NAP_PCBIOS
+#define NAP_PREFIX_pcbios
+#else
+#define NAP_PREFIX_pcbios __pcbios_
+#endif
+
+#endif /* _IPXE_BIOS_NAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_sanboot.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_sanboot.h
new file mode 100644
index 00000000..689227b7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_sanboot.h
@@ -0,0 +1,29 @@
+#ifndef _IPXE_BIOS_SANBOOT_H
+#define _IPXE_BIOS_SANBOOT_H
+
+/** @file
+ *
+ * Standard PC-BIOS sanboot interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef SANBOOT_PCBIOS
+#define SANBOOT_PREFIX_pcbios
+#else
+#define SANBOOT_PREFIX_pcbios __pcbios_
+#endif
+
+/**
+ * Get default SAN drive number
+ *
+ * @ret drive Default drive number
+ */
+static inline __always_inline unsigned int
+SANBOOT_INLINE ( pcbios, san_default_drive ) ( void ) {
+ /* Default to booting from first hard disk */
+ return 0x80;
+}
+
+#endif /* _IPXE_BIOS_SANBOOT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_smbios.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_smbios.h
new file mode 100644
index 00000000..d8c7f648
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_smbios.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_BIOS_SMBIOS_H
+#define _IPXE_BIOS_SMBIOS_H
+
+/** @file
+ *
+ * Standard PC-BIOS SMBIOS interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef SMBIOS_PCBIOS
+#define SMBIOS_PREFIX_pcbios
+#else
+#define SMBIOS_PREFIX_pcbios __pcbios_
+#endif
+
+#endif /* _IPXE_BIOS_SMBIOS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_timer.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_timer.h
new file mode 100644
index 00000000..f9fc8041
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/bios_timer.h
@@ -0,0 +1,44 @@
+#ifndef _IPXE_BIOS_TIMER_H
+#define _IPXE_BIOS_TIMER_H
+
+/** @file
+ *
+ * BIOS timer
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef TIMER_PCBIOS
+#define TIMER_PREFIX_pcbios
+#else
+#define TIMER_PREFIX_pcbios __pcbios_
+#endif
+
+#include <ipxe/timer2.h>
+
+/**
+ * Delay for a fixed number of microseconds
+ *
+ * @v usecs Number of microseconds for which to delay
+ */
+static inline __always_inline void
+TIMER_INLINE ( pcbios, udelay ) ( unsigned long usecs ) {
+ /* BIOS timer is not high-resolution enough for udelay(), so
+ * we use timer2
+ */
+ timer2_udelay ( usecs );
+}
+
+/**
+ * Get number of ticks per second
+ *
+ * @ret ticks_per_sec Number of ticks per second
+ */
+static inline __always_inline unsigned long
+TIMER_INLINE ( pcbios, ticks_per_sec ) ( void ) {
+ /* BIOS timer ticks over at 18.2 ticks per second */
+ return 18;
+}
+
+#endif /* _IPXE_BIOS_TIMER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/guestrpc.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/guestrpc.h
new file mode 100644
index 00000000..72a0f714
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/guestrpc.h
@@ -0,0 +1,68 @@
+#ifndef _IPXE_GUESTRPC_H
+#define _IPXE_GUESTRPC_H
+
+/** @file
+ *
+ * VMware GuestRPC mechanism
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/vmware.h>
+
+/** GuestRPC magic number */
+#define GUESTRPC_MAGIC 0x49435052 /* "RPCI" */
+
+/** Open RPC channel */
+#define GUESTRPC_OPEN 0x00
+
+/** Open RPC channel success status */
+#define GUESTRPC_OPEN_SUCCESS 0x00010000
+
+/** Send RPC command length */
+#define GUESTRPC_COMMAND_LEN 0x01
+
+/** Send RPC command length success status */
+#define GUESTRPC_COMMAND_LEN_SUCCESS 0x00810000
+
+/** Send RPC command data */
+#define GUESTRPC_COMMAND_DATA 0x02
+
+/** Send RPC command data success status */
+#define GUESTRPC_COMMAND_DATA_SUCCESS 0x00010000
+
+/** Receive RPC reply length */
+#define GUESTRPC_REPLY_LEN 0x03
+
+/** Receive RPC reply length success status */
+#define GUESTRPC_REPLY_LEN_SUCCESS 0x00830000
+
+/** Receive RPC reply data */
+#define GUESTRPC_REPLY_DATA 0x04
+
+/** Receive RPC reply data success status */
+#define GUESTRPC_REPLY_DATA_SUCCESS 0x00010000
+
+/** Finish receiving RPC reply */
+#define GUESTRPC_REPLY_FINISH 0x05
+
+/** Finish receiving RPC reply success status */
+#define GUESTRPC_REPLY_FINISH_SUCCESS 0x00010000
+
+/** Close RPC channel */
+#define GUESTRPC_CLOSE 0x06
+
+/** Close RPC channel success status */
+#define GUESTRPC_CLOSE_SUCCESS 0x00010000
+
+/** RPC command success status */
+#define GUESTRPC_SUCCESS 0x2031 /* "1 " */
+
+extern int guestrpc_open ( void );
+extern void guestrpc_close ( int channel );
+extern int guestrpc_command ( int channel, const char *command, char *reply,
+ size_t reply_len );
+
+#endif /* _IPXE_GUESTRPC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/memtop_umalloc.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/memtop_umalloc.h
new file mode 100644
index 00000000..001648fe
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/memtop_umalloc.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_MEMTOP_UMALLOC_H
+#define _IPXE_MEMTOP_UMALLOC_H
+
+/** @file
+ *
+ * External memory allocation
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef UMALLOC_MEMTOP
+#define UMALLOC_PREFIX_memtop
+#else
+#define UMALLOC_PREFIX_memtop __memtop_
+#endif
+
+#endif /* _IPXE_MEMTOP_UMALLOC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/rdtsc_timer.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/rdtsc_timer.h
new file mode 100644
index 00000000..472e1400
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/rdtsc_timer.h
@@ -0,0 +1,39 @@
+#ifndef _IPXE_RDTSC_TIMER_H
+#define _IPXE_RDTSC_TIMER_H
+
+/** @file
+ *
+ * RDTSC timer
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef TIMER_RDTSC
+#define TIMER_PREFIX_rdtsc
+#else
+#define TIMER_PREFIX_rdtsc __rdtsc_
+#endif
+
+/**
+ * RDTSC values can easily overflow an unsigned long. We discard the
+ * low-order bits in order to obtain sensibly-scaled values.
+ */
+#define TSC_SHIFT 8
+
+/**
+ * Get current system time in ticks
+ *
+ * @ret ticks Current time, in ticks
+ */
+static inline __always_inline unsigned long
+TIMER_INLINE ( rdtsc, currticks ) ( void ) {
+ unsigned long ticks;
+
+ __asm__ __volatile__ ( "rdtsc\n\t"
+ "shrdl %1, %%edx, %%eax\n\t"
+ : "=a" ( ticks ) : "i" ( TSC_SHIFT ) : "edx" );
+ return ticks;
+}
+
+#endif /* _IPXE_RDTSC_TIMER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/rtc_entropy.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/rtc_entropy.h
new file mode 100644
index 00000000..6c3cf210
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/rtc_entropy.h
@@ -0,0 +1,62 @@
+#ifndef _IPXE_RTC_ENTROPY_H
+#define _IPXE_RTC_ENTROPY_H
+
+/** @file
+ *
+ * RTC-based entropy source
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+#ifdef ENTROPY_RTC
+#define ENTROPY_PREFIX_rtc
+#else
+#define ENTROPY_PREFIX_rtc __rtc_
+#endif
+
+/**
+ * min-entropy per sample
+ *
+ * @ret min_entropy min-entropy of each sample
+ */
+static inline __always_inline double
+ENTROPY_INLINE ( rtc, min_entropy_per_sample ) ( void ) {
+
+ /* The min-entropy has been measured on several platforms
+ * using the entropy_sample test code. Modelling the samples
+ * as independent, and using a confidence level of 99.99%, the
+ * measurements were as follows:
+ *
+ * qemu-kvm : 7.38 bits
+ * VMware : 7.46 bits
+ * Physical hardware : 2.67 bits
+ *
+ * We choose the lowest of these (2.67 bits) and apply a 50%
+ * safety margin to allow for some potential non-independence
+ * of samples.
+ */
+ return 1.3;
+}
+
+extern uint8_t rtc_sample ( void );
+
+/**
+ * Get noise sample
+ *
+ * @ret noise Noise sample
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+ENTROPY_INLINE ( rtc, get_noise ) ( noise_sample_t *noise ) {
+
+ /* Get sample */
+ *noise = rtc_sample();
+
+ /* Always successful */
+ return 0;
+}
+
+#endif /* _IPXE_RTC_ENTROPY_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/rtc_time.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/rtc_time.h
new file mode 100644
index 00000000..c0dfe3f8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/rtc_time.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_RTC_TIME_H
+#define _IPXE_RTC_TIME_H
+
+/** @file
+ *
+ * RTC-based time source
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef TIME_RTC
+#define TIME_PREFIX_rtc
+#else
+#define TIME_PREFIX_rtc __rtc_
+#endif
+
+#endif /* _IPXE_RTC_TIME_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/timer2.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/timer2.h
new file mode 100644
index 00000000..322a3ed5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/timer2.h
@@ -0,0 +1,14 @@
+#ifndef _IPXE_TIMER2_H
+#define _IPXE_TIMER2_H
+
+/** @file
+ *
+ * Timer chip control
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern void timer2_udelay ( unsigned long usecs );
+
+#endif /* _IPXE_TIMER2_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/vmware.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/vmware.h
new file mode 100644
index 00000000..2ac65f43
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/vmware.h
@@ -0,0 +1,81 @@
+#ifndef _IPXE_VMWARE_H
+#define _IPXE_VMWARE_H
+
+/** @file
+ *
+ * VMware backdoor mechanism
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/** VMware backdoor I/O port */
+#define VMW_PORT 0x5658
+
+/** VMware backdoor magic value */
+#define VMW_MAGIC 0x564d5868 /* "VMXh" */
+
+/** VMware backdoor magic instruction */
+#define VMW_BACKDOOR "inl %%dx, %%eax"
+
+/** Get VMware version */
+#define VMW_CMD_GET_VERSION 0x0a
+
+/** Issue GuestRPC command */
+#define VMW_CMD_GUESTRPC 0x1e
+
+/**
+ * Get VMware version
+ *
+ * @ret version VMware version(?)
+ * @ret magic VMware magic number, if present
+ * @ret product_type VMware product type
+ */
+static inline __attribute__ (( always_inline )) void
+vmware_cmd_get_version ( uint32_t *version, uint32_t *magic,
+ uint32_t *product_type ) {
+ uint32_t discard_d;
+
+ /* Perform backdoor call */
+ __asm__ __volatile__ ( VMW_BACKDOOR
+ : "=a" ( *version ), "=b" ( *magic ),
+ "=c" ( *product_type ), "=d" ( discard_d )
+ : "0" ( VMW_MAGIC ), "1" ( 0 ),
+ "2" ( VMW_CMD_GET_VERSION ),
+ "3" ( VMW_PORT ) );
+}
+
+/**
+ * Issue GuestRPC command
+ *
+ * @v channel Channel number
+ * @v subcommand GuestRPC subcommand
+ * @v parameter Subcommand-specific parameter
+ * @ret edxhi Subcommand-specific result
+ * @ret ebx Subcommand-specific result
+ * @ret status Command status
+ */
+static inline __attribute__ (( always_inline )) uint32_t
+vmware_cmd_guestrpc ( int channel, uint16_t subcommand, uint32_t parameter,
+ uint16_t *edxhi, uint32_t *ebx ) {
+ uint32_t discard_a;
+ uint32_t status;
+ uint32_t edx;
+
+ /* Perform backdoor call */
+ __asm__ __volatile__ ( VMW_BACKDOOR
+ : "=a" ( discard_a ), "=b" ( *ebx ),
+ "=c" ( status ), "=d" ( edx )
+ : "0" ( VMW_MAGIC ), "1" ( parameter ),
+ "2" ( VMW_CMD_GUESTRPC | ( subcommand << 16 )),
+ "3" ( VMW_PORT | ( channel << 16 ) ) );
+ *edxhi = ( edx >> 16 );
+
+ return status;
+}
+
+extern int vmware_present ( void );
+
+#endif /* _IPXE_VMWARE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/x86_io.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/x86_io.h
new file mode 100644
index 00000000..a79501e2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/ipxe/x86_io.h
@@ -0,0 +1,153 @@
+#ifndef _IPXE_X86_IO_H
+#define _IPXE_X86_IO_H
+
+/** @file
+ *
+ * iPXE I/O API for x86
+ *
+ * i386 uses direct pointer dereferences for accesses to memory-mapped
+ * I/O space, and the inX/outX instructions for accesses to
+ * port-mapped I/O space.
+ *
+ * 64-bit atomic accesses (readq() and writeq()) use MMX instructions,
+ * and will crash original Pentium and earlier CPUs. Fortunately, no
+ * hardware that requires atomic 64-bit accesses will physically fit
+ * into a machine with such an old CPU anyway.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef IOAPI_X86
+#define IOAPI_PREFIX_x86
+#else
+#define IOAPI_PREFIX_x86 __x86_
+#endif
+
+/*
+ * Memory space mappings
+ *
+ */
+
+/*
+ * Physical<->Bus and Bus<->I/O address mappings
+ *
+ */
+
+static inline __always_inline unsigned long
+IOAPI_INLINE ( x86, phys_to_bus ) ( unsigned long phys_addr ) {
+ return phys_addr;
+}
+
+static inline __always_inline unsigned long
+IOAPI_INLINE ( x86, bus_to_phys ) ( unsigned long bus_addr ) {
+ return bus_addr;
+}
+
+static inline __always_inline void *
+IOAPI_INLINE ( x86, ioremap ) ( unsigned long bus_addr, size_t len __unused ) {
+ return phys_to_virt ( bus_addr );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( x86, iounmap ) ( volatile const void *io_addr __unused ) {
+ /* Nothing to do */
+}
+
+static inline __always_inline unsigned long
+IOAPI_INLINE ( x86, io_to_bus ) ( volatile const void *io_addr ) {
+ return virt_to_phys ( io_addr );
+}
+
+/*
+ * MMIO reads and writes up to 32 bits
+ *
+ */
+
+#define X86_READX( _api_func, _type ) \
+static inline __always_inline _type \
+IOAPI_INLINE ( x86, _api_func ) ( volatile _type *io_addr ) { \
+ return *io_addr; \
+}
+X86_READX ( readb, uint8_t );
+X86_READX ( readw, uint16_t );
+X86_READX ( readl, uint32_t );
+
+#define X86_WRITEX( _api_func, _type ) \
+static inline __always_inline void \
+IOAPI_INLINE ( x86, _api_func ) ( _type data, \
+ volatile _type *io_addr ) { \
+ *io_addr = data; \
+}
+X86_WRITEX ( writeb, uint8_t );
+X86_WRITEX ( writew, uint16_t );
+X86_WRITEX ( writel, uint32_t );
+
+/*
+ * PIO reads and writes up to 32 bits
+ *
+ */
+
+#define X86_INX( _insn_suffix, _type, _reg_prefix ) \
+static inline __always_inline _type \
+IOAPI_INLINE ( x86, in ## _insn_suffix ) ( volatile _type *io_addr ) { \
+ _type data; \
+ __asm__ __volatile__ ( "in" #_insn_suffix " %w1, %" _reg_prefix "0" \
+ : "=a" ( data ) : "Nd" ( io_addr ) ); \
+ return data; \
+} \
+static inline __always_inline void \
+IOAPI_INLINE ( x86, ins ## _insn_suffix ) ( volatile _type *io_addr, \
+ _type *data, \
+ unsigned int count ) { \
+ unsigned int discard_D; \
+ __asm__ __volatile__ ( "rep ins" #_insn_suffix \
+ : "=D" ( discard_D ) \
+ : "d" ( io_addr ), "c" ( count ), \
+ "0" ( data ) ); \
+}
+X86_INX ( b, uint8_t, "b" );
+X86_INX ( w, uint16_t, "w" );
+X86_INX ( l, uint32_t, "k" );
+
+#define X86_OUTX( _insn_suffix, _type, _reg_prefix ) \
+static inline __always_inline void \
+IOAPI_INLINE ( x86, out ## _insn_suffix ) ( _type data, \
+ volatile _type *io_addr ) { \
+ __asm__ __volatile__ ( "out" #_insn_suffix " %" _reg_prefix "0, %w1" \
+ : : "a" ( data ), "Nd" ( io_addr ) ); \
+} \
+static inline __always_inline void \
+IOAPI_INLINE ( x86, outs ## _insn_suffix ) ( volatile _type *io_addr, \
+ const _type *data, \
+ unsigned int count ) { \
+ unsigned int discard_S; \
+ __asm__ __volatile__ ( "rep outs" #_insn_suffix \
+ : "=S" ( discard_S ) \
+ : "d" ( io_addr ), "c" ( count ), \
+ "0" ( data ) ); \
+}
+X86_OUTX ( b, uint8_t, "b" );
+X86_OUTX ( w, uint16_t, "w" );
+X86_OUTX ( l, uint32_t, "k" );
+
+/*
+ * Slow down I/O
+ *
+ */
+
+static inline __always_inline void
+IOAPI_INLINE ( x86, iodelay ) ( void ) {
+ __asm__ __volatile__ ( "outb %al, $0x80" );
+}
+
+/*
+ * Memory barrier
+ *
+ */
+
+static inline __always_inline void
+IOAPI_INLINE ( x86, mb ) ( void ) {
+ __asm__ __volatile__ ( "lock; addl $0, 0(%%esp)" : : : "memory" );
+}
+
+#endif /* _IPXE_X86_IO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/kir.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/kir.h
new file mode 100644
index 00000000..84633d26
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/kir.h
@@ -0,0 +1,18 @@
+#ifndef KIR_H
+#define KIR_H
+
+#ifndef KEEP_IT_REAL
+#error "kir.h can be used only with -DKEEP_IT_REAL"
+#endif
+
+#ifdef ASSEMBLY
+
+#define code32 code16gcc
+
+#else /* ASSEMBLY */
+
+__asm__ ( ".code16gcc" );
+
+#endif /* ASSEMBLY */
+
+#endif /* KIR_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/libkir.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/libkir.h
new file mode 100644
index 00000000..1f5b1350
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/libkir.h
@@ -0,0 +1,233 @@
+#ifndef LIBKIR_H
+#define LIBKIR_H
+
+#include "realmode.h"
+
+#ifndef ASSEMBLY
+
+/*
+ * Full API documentation for these functions is in realmode.h.
+ *
+ */
+
+/* Access to variables in .data16 and .text16 in a way compatible with librm */
+#define __data16( variable ) variable
+#define __data16_array( variable, array ) variable array
+#define __bss16( variable ) variable
+#define __bss16_array( variable, array ) variable array
+#define __text16( variable ) variable
+#define __text16_array( variable,array ) variable array
+#define __use_data16( variable ) variable
+#define __use_text16( variable ) variable
+#define __from_data16( pointer ) pointer
+#define __from_text16( pointer ) pointer
+
+/* Real-mode data and code segments */
+static inline __attribute__ (( always_inline )) unsigned int _rm_cs ( void ) {
+ uint16_t cs;
+ __asm__ __volatile__ ( "movw %%cs, %w0" : "=r" ( cs ) );
+ return cs;
+}
+
+static inline __attribute__ (( always_inline )) unsigned int _rm_ds ( void ) {
+ uint16_t ds;
+ __asm__ __volatile__ ( "movw %%ds, %w0" : "=r" ( ds ) );
+ return ds;
+}
+
+#define rm_cs ( _rm_cs() )
+#define rm_ds ( _rm_ds() )
+
+/* Copy to/from base memory */
+
+static inline void copy_to_real_libkir ( unsigned int dest_seg,
+ unsigned int dest_off,
+ const void *src, size_t n ) {
+ unsigned int discard_D, discard_S, discard_c;
+
+ __asm__ __volatile__ ( "pushw %%es\n\t"
+ "movw %3, %%es\n\t"
+ "rep movsb\n\t"
+ "popw %%es\n\t"
+ : "=D" ( discard_D ), "=S" ( discard_S ),
+ "=c" ( discard_c )
+ : "r" ( dest_seg ), "D" ( dest_off ),
+ "S" ( src ),
+ "c" ( n )
+ : "memory" );
+}
+
+static inline void copy_from_real_libkir ( void *dest,
+ unsigned int src_seg,
+ unsigned int src_off,
+ size_t n ) {
+ unsigned int discard_D, discard_S, discard_c;
+
+ __asm__ __volatile__ ( "pushw %%ds\n\t"
+ "movw %4, %%ds\n\t"
+ "rep movsb\n\t"
+ "popw %%ds\n\t"
+ : "=D" ( discard_D ), "=S" ( discard_S ),
+ "=c" ( discard_c )
+ : "D" ( dest ),
+ "r" ( src_seg ), "S" ( src_off ),
+ "c" ( n )
+ : "memory" );
+}
+
+#define copy_to_real copy_to_real_libkir
+#define copy_from_real copy_from_real_libkir
+
+/*
+ * Transfer individual values to/from base memory. There may well be
+ * a neater way to do this. We have two versions: one for constant
+ * offsets (where the mov instruction must be of the form "mov
+ * %es:123, %xx") and one for non-constant offsets (where the mov
+ * instruction must be of the form "mov %es:(%xx), %yx". If it's
+ * possible to incorporate both forms into one __asm__ instruction, I
+ * don't know how to do it.
+ *
+ * Ideally, the mov instruction should be "mov%z0"; the "%z0" is meant
+ * to expand to either "b", "w" or "l" depending on the size of
+ * operand 0. This would remove the (minor) ambiguity in the mov
+ * instruction. However, gcc on at least my system barfs with an
+ * "internal compiler error" when confronted with %z0.
+ *
+ */
+
+#define put_real_kir_const_off( var, seg, off ) \
+ __asm__ ( "movw %w1, %%es\n\t" \
+ "mov %0, %%es:%c2\n\t" \
+ "pushw %%ds\n\t" /* restore %es */ \
+ "popw %%es\n\t" \
+ : \
+ : "r,r" ( var ), "rm,rm" ( seg ), "i,!r" ( off ) \
+ )
+
+#define put_real_kir_nonconst_off( var, seg, off ) \
+ __asm__ ( "movw %w1, %%es\n\t" \
+ "mov %0, %%es:(%2)\n\t" \
+ "pushw %%ds\n\t" /* restore %es */ \
+ "popw %%es\n\t" \
+ : \
+ : "r" ( var ), "rm" ( seg ), "r" ( off ) \
+ )
+
+#define put_real_kir( var, seg, off ) \
+ do { \
+ if ( __builtin_constant_p ( off ) ) \
+ put_real_kir_const_off ( var, seg, off ); \
+ else \
+ put_real_kir_nonconst_off ( var, seg, off ); \
+ } while ( 0 )
+
+#define get_real_kir_const_off( var, seg, off ) \
+ __asm__ ( "movw %w1, %%es\n\t" \
+ "mov %%es:%c2, %0\n\t" \
+ "pushw %%ds\n\t" /* restore %es */ \
+ "popw %%es\n\t" \
+ : "=r,r" ( var ) \
+ : "rm,rm" ( seg ), "i,!r" ( off ) \
+ )
+
+#define get_real_kir_nonconst_off( var, seg, off ) \
+ __asm__ ( "movw %w1, %%es\n\t" \
+ "mov %%es:(%2), %0\n\t" \
+ "pushw %%ds\n\t" /* restore %es */ \
+ "popw %%es\n\t" \
+ : "=r" ( var ) \
+ : "rm" ( seg ), "r" ( off ) \
+ )
+
+#define get_real_kir( var, seg, off ) \
+ do { \
+ if ( __builtin_constant_p ( off ) ) \
+ get_real_kir_const_off ( var, seg, off ); \
+ else \
+ get_real_kir_nonconst_off ( var, seg, off ); \
+ } while ( 0 )
+
+#define put_real put_real_kir
+#define get_real get_real_kir
+
+/**
+ * A pointer to a user buffer
+ *
+ * This is actually a struct segoff, but encoded as a uint32_t to
+ * ensure that gcc passes it around efficiently.
+ */
+typedef uint32_t userptr_t;
+
+/**
+ * Copy data to user buffer
+ *
+ * @v buffer User buffer
+ * @v offset Offset within user buffer
+ * @v src Source
+ * @v len Length
+ */
+static inline __attribute__ (( always_inline )) void
+copy_to_user ( userptr_t buffer, off_t offset, const void *src, size_t len ) {
+ copy_to_real ( ( buffer >> 16 ), ( ( buffer & 0xffff ) + offset ),
+ src, len );
+}
+
+/**
+ * Copy data from user buffer
+ *
+ * @v dest Destination
+ * @v buffer User buffer
+ * @v offset Offset within user buffer
+ * @v len Length
+ */
+static inline __attribute__ (( always_inline )) void
+copy_from_user ( void *dest, userptr_t buffer, off_t offset, size_t len ) {
+ copy_from_real ( dest, ( buffer >> 16 ),
+ ( ( buffer & 0xffff ) + offset ), len );
+}
+
+/**
+ * Convert segment:offset address to user buffer
+ *
+ * @v segment Real-mode segment
+ * @v offset Real-mode offset
+ * @ret buffer User buffer
+ */
+static inline __attribute__ (( always_inline )) userptr_t
+real_to_user ( unsigned int segment, unsigned int offset ) {
+ return ( ( segment << 16 ) | offset );
+}
+
+/**
+ * Convert virtual address to user buffer
+ *
+ * @v virtual Virtual address
+ * @ret buffer User buffer
+ *
+ * This constructs a user buffer from an ordinary pointer. Use it
+ * when you need to pass a pointer to an internal buffer to a function
+ * that expects a @c userptr_t.
+ */
+static inline __attribute__ (( always_inline )) userptr_t
+virt_to_user ( void * virtual ) {
+ return real_to_user ( rm_ds, ( intptr_t ) virtual );
+}
+
+/* TEXT16_CODE: declare a fragment of code that resides in .text16 */
+#define TEXT16_CODE( asm_code_str ) \
+ ".section \".text16\", \"ax\", @progbits\n\t" \
+ ".code16\n\t" \
+ ".arch i386\n\t" \
+ asm_code_str "\n\t" \
+ ".code16gcc\n\t" \
+ ".previous\n\t"
+
+/* REAL_CODE: declare a fragment of code that executes in real mode */
+#define REAL_CODE( asm_code_str ) \
+ ".code16\n\t" \
+ asm_code_str "\n\t" \
+ ".code16gcc\n\t"
+
+#endif /* ASSEMBLY */
+
+#endif /* LIBKIR_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/librm.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/librm.h
new file mode 100644
index 00000000..c6992f64
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/librm.h
@@ -0,0 +1,201 @@
+#ifndef LIBRM_H
+#define LIBRM_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* Segment selectors as used in our protected-mode GDTs.
+ *
+ * Don't change these unless you really know what you're doing.
+ */
+
+#define VIRTUAL_CS 0x08
+#define VIRTUAL_DS 0x10
+#define PHYSICAL_CS 0x18
+#define PHYSICAL_DS 0x20
+#define REAL_CS 0x28
+#define REAL_DS 0x30
+#if 0
+#define LONG_CS 0x38
+#define LONG_DS 0x40
+#endif
+
+#ifndef ASSEMBLY
+
+#ifdef UACCESS_LIBRM
+#define UACCESS_PREFIX_librm
+#else
+#define UACCESS_PREFIX_librm __librm_
+#endif
+
+/* Variables in librm.S */
+extern unsigned long virt_offset;
+
+/**
+ * Convert physical address to user pointer
+ *
+ * @v phys_addr Physical address
+ * @ret userptr User pointer
+ */
+static inline __always_inline userptr_t
+UACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) {
+ return ( phys_addr - virt_offset );
+}
+
+/**
+ * Convert user buffer to physical address
+ *
+ * @v userptr User pointer
+ * @v offset Offset from user pointer
+ * @ret phys_addr Physical address
+ */
+static inline __always_inline unsigned long
+UACCESS_INLINE ( librm, user_to_phys ) ( userptr_t userptr, off_t offset ) {
+ return ( userptr + offset + virt_offset );
+}
+
+static inline __always_inline userptr_t
+UACCESS_INLINE ( librm, virt_to_user ) ( volatile const void *addr ) {
+ return trivial_virt_to_user ( addr );
+}
+
+static inline __always_inline void *
+UACCESS_INLINE ( librm, user_to_virt ) ( userptr_t userptr, off_t offset ) {
+ return trivial_user_to_virt ( userptr, offset );
+}
+
+static inline __always_inline userptr_t
+UACCESS_INLINE ( librm, userptr_add ) ( userptr_t userptr, off_t offset ) {
+ return trivial_userptr_add ( userptr, offset );
+}
+
+static inline __always_inline void
+UACCESS_INLINE ( librm, memcpy_user ) ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off,
+ size_t len ) {
+ trivial_memcpy_user ( dest, dest_off, src, src_off, len );
+}
+
+static inline __always_inline void
+UACCESS_INLINE ( librm, memmove_user ) ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off,
+ size_t len ) {
+ trivial_memmove_user ( dest, dest_off, src, src_off, len );
+}
+
+static inline __always_inline void
+UACCESS_INLINE ( librm, memset_user ) ( userptr_t buffer, off_t offset,
+ int c, size_t len ) {
+ trivial_memset_user ( buffer, offset, c, len );
+}
+
+static inline __always_inline size_t
+UACCESS_INLINE ( librm, strlen_user ) ( userptr_t buffer, off_t offset ) {
+ return trivial_strlen_user ( buffer, offset );
+}
+
+static inline __always_inline off_t
+UACCESS_INLINE ( librm, memchr_user ) ( userptr_t buffer, off_t offset,
+ int c, size_t len ) {
+ return trivial_memchr_user ( buffer, offset, c, len );
+}
+
+
+/******************************************************************************
+ *
+ * Access to variables in .data16 and .text16
+ *
+ */
+
+extern char *data16;
+extern char *text16;
+
+#define __data16( variable ) \
+ __attribute__ (( section ( ".data16" ) )) \
+ _data16_ ## variable __asm__ ( #variable )
+
+#define __data16_array( variable, array ) \
+ __attribute__ (( section ( ".data16" ) )) \
+ _data16_ ## variable array __asm__ ( #variable )
+
+#define __bss16( variable ) \
+ __attribute__ (( section ( ".bss16" ) )) \
+ _data16_ ## variable __asm__ ( #variable )
+
+#define __bss16_array( variable, array ) \
+ __attribute__ (( section ( ".bss16" ) )) \
+ _data16_ ## variable array __asm__ ( #variable )
+
+#define __text16( variable ) \
+ __attribute__ (( section ( ".text16.data" ) )) \
+ _text16_ ## variable __asm__ ( #variable )
+
+#define __text16_array( variable, array ) \
+ __attribute__ (( section ( ".text16.data" ) )) \
+ _text16_ ## variable array __asm__ ( #variable )
+
+#define __use_data16( variable ) \
+ ( * ( ( typeof ( _data16_ ## variable ) * ) \
+ & ( data16 [ ( size_t ) & ( _data16_ ## variable ) ] ) ) )
+
+#define __use_text16( variable ) \
+ ( * ( ( typeof ( _text16_ ## variable ) * ) \
+ & ( text16 [ ( size_t ) & ( _text16_ ## variable ) ] ) ) )
+
+#define __from_data16( pointer ) \
+ ( ( unsigned int ) \
+ ( ( ( void * ) (pointer) ) - ( ( void * ) data16 ) ) )
+
+#define __from_text16( pointer ) \
+ ( ( unsigned int ) \
+ ( ( ( void * ) (pointer) ) - ( ( void * ) text16 ) ) )
+
+/* Variables in librm.S, present in the normal data segment */
+extern uint16_t rm_sp;
+extern uint16_t rm_ss;
+extern uint16_t __data16 ( rm_cs );
+#define rm_cs __use_data16 ( rm_cs )
+extern uint16_t __text16 ( rm_ds );
+#define rm_ds __use_text16 ( rm_ds )
+
+/**
+ * Convert segment:offset address to user buffer
+ *
+ * @v segment Real-mode segment
+ * @v offset Real-mode offset
+ * @ret buffer User buffer
+ */
+static inline __always_inline userptr_t
+real_to_user ( unsigned int segment, unsigned int offset ) {
+ return ( phys_to_user ( ( segment << 4 ) + offset ) );
+}
+
+extern uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size );
+extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
+
+/* TEXT16_CODE: declare a fragment of code that resides in .text16 */
+#define TEXT16_CODE( asm_code_str ) \
+ ".section \".text16\", \"ax\", @progbits\n\t" \
+ ".code16\n\t" \
+ asm_code_str "\n\t" \
+ ".code32\n\t" \
+ ".previous\n\t"
+
+/* REAL_CODE: declare a fragment of code that executes in real mode */
+#define REAL_CODE( asm_code_str ) \
+ "pushl $1f\n\t" \
+ "call real_call\n\t" \
+ "addl $4, %%esp\n\t" \
+ TEXT16_CODE ( "\n1:\n\t" \
+ asm_code_str \
+ "\n\t" \
+ "ret\n\t" )
+
+/* PHYS_CODE: declare a fragment of code that executes in flat physical mode */
+#define PHYS_CODE( asm_code_str ) \
+ "call _virt_to_phys\n\t" \
+ asm_code_str \
+ "call _phys_to_virt\n\t"
+
+#endif /* ASSEMBLY */
+
+#endif /* LIBRM_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/limits.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/limits.h
new file mode 100644
index 00000000..031b6c57
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/limits.h
@@ -0,0 +1,61 @@
+#ifndef LIMITS_H
+#define LIMITS_H 1
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* Number of bits in a `char' */
+#define CHAR_BIT 8
+
+/* Minimum and maximum values a `signed char' can hold */
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX 127
+
+/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
+#define UCHAR_MAX 255
+
+/* Minimum and maximum values a `char' can hold */
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX SCHAR_MAX
+
+/* Minimum and maximum values a `signed short int' can hold */
+#define SHRT_MIN (-32768)
+#define SHRT_MAX 32767
+
+/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */
+#define USHRT_MAX 65535
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MAX 2147483647
+#define INT_MIN (-INT_MAX - 1)
+
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+
+/* Minimum and maximum values a `signed long' can hold */
+#define LONG_MAX 2147483647
+#define LONG_MIN (-LONG_MAX - 1L)
+
+/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */
+#define ULONG_MAX 4294967295UL
+
+/* Minimum and maximum values a `signed long long' can hold */
+#define LLONG_MAX 9223372036854775807LL
+#define LLONG_MIN (-LONG_MAX - 1LL)
+
+
+/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */
+#define ULLONG_MAX 18446744073709551615ULL
+
+
+#endif /* LIMITS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/memsizes.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/memsizes.h
new file mode 100644
index 00000000..7b217494
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/memsizes.h
@@ -0,0 +1,19 @@
+#ifndef _MEMSIZES_H
+#define _MEMSIZES_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <basemem.h>
+
+/**
+ * Get size of base memory from BIOS free base memory counter
+ *
+ * @ret basemem Base memory size, in kB
+ */
+static inline unsigned int basememsize ( void ) {
+ return get_fbms();
+}
+
+extern unsigned int extmemsize ( void );
+
+#endif /* _MEMSIZES_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/multiboot.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/multiboot.h
new file mode 100644
index 00000000..44614c73
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/multiboot.h
@@ -0,0 +1,149 @@
+#ifndef _MULTIBOOT_H
+#define _MULTIBOOT_H
+
+/**
+ * @file
+ *
+ * Multiboot operating systems
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/** The magic number for the Multiboot header */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/** Boot modules must be page aligned */
+#define MB_FLAG_PGALIGN 0x00000001
+
+/** Memory map must be provided */
+#define MB_FLAG_MEMMAP 0x00000002
+
+/** Video mode information must be provided */
+#define MB_FLAG_VIDMODE 0x00000004
+
+/** Image is a raw multiboot image (not ELF) */
+#define MB_FLAG_RAW 0x00010000
+
+/**
+ * The magic number passed by a Multiboot-compliant boot loader
+ *
+ * Must be passed in register %eax when jumping to the Multiboot OS
+ * image.
+ */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/** Multiboot information structure mem_* fields are valid */
+#define MBI_FLAG_MEM 0x00000001
+
+/** Multiboot information structure boot_device field is valid */
+#define MBI_FLAG_BOOTDEV 0x00000002
+
+/** Multiboot information structure cmdline field is valid */
+#define MBI_FLAG_CMDLINE 0x00000004
+
+/** Multiboot information structure module fields are valid */
+#define MBI_FLAG_MODS 0x00000008
+
+/** Multiboot information structure a.out symbol table is valid */
+#define MBI_FLAG_AOUT 0x00000010
+
+/** Multiboot information struture ELF section header table is valid */
+#define MBI_FLAG_ELF 0x00000020
+
+/** Multiboot information structure memory map is valid */
+#define MBI_FLAG_MMAP 0x00000040
+
+/** Multiboot information structure drive list is valid */
+#define MBI_FLAG_DRIVES 0x00000080
+
+/** Multiboot information structure ROM configuration field is valid */
+#define MBI_FLAG_CFGTBL 0x00000100
+
+/** Multiboot information structure boot loader name field is valid */
+#define MBI_FLAG_LOADER 0x00000200
+
+/** Multiboot information structure APM table is valid */
+#define MBI_FLAG_APM 0x00000400
+
+/** Multiboot information structure video information is valid */
+#define MBI_FLAG_VBE 0x00000800
+
+/** A multiboot header */
+struct multiboot_header {
+ uint32_t magic;
+ uint32_t flags;
+ uint32_t checksum;
+ uint32_t header_addr;
+ uint32_t load_addr;
+ uint32_t load_end_addr;
+ uint32_t bss_end_addr;
+ uint32_t entry_addr;
+} __attribute__ (( packed, may_alias ));
+
+/** A multiboot a.out symbol table */
+struct multiboot_aout_symbol_table {
+ uint32_t tabsize;
+ uint32_t strsize;
+ uint32_t addr;
+ uint32_t reserved;
+} __attribute__ (( packed, may_alias ));
+
+/** A multiboot ELF section header table */
+struct multiboot_elf_section_header_table {
+ uint32_t num;
+ uint32_t size;
+ uint32_t addr;
+ uint32_t shndx;
+} __attribute__ (( packed, may_alias ));
+
+/** A multiboot information structure */
+struct multiboot_info {
+ uint32_t flags;
+ uint32_t mem_lower;
+ uint32_t mem_upper;
+ uint32_t boot_device;
+ uint32_t cmdline;
+ uint32_t mods_count;
+ uint32_t mods_addr;
+ union {
+ struct multiboot_aout_symbol_table aout_syms;
+ struct multiboot_elf_section_header_table elf_sections;
+ } syms;
+ uint32_t mmap_length;
+ uint32_t mmap_addr;
+ uint32_t drives_length;
+ uint32_t drives_addr;
+ uint32_t config_table;
+ uint32_t boot_loader_name;
+ uint32_t apm_table;
+ uint32_t vbe_control_info;
+ uint32_t vbe_mode_info;
+ uint16_t vbe_mode;
+ uint16_t vbe_interface_seg;
+ uint16_t vbe_interface_off;
+ uint16_t vbe_interface_len;
+} __attribute__ (( packed, may_alias ));
+
+/** A multiboot module structure */
+struct multiboot_module {
+ uint32_t mod_start;
+ uint32_t mod_end;
+ uint32_t string;
+ uint32_t reserved;
+} __attribute__ (( packed, may_alias ));
+
+/** A multiboot memory map entry */
+struct multiboot_memory_map {
+ uint32_t size;
+ uint64_t base_addr;
+ uint64_t length;
+ uint32_t type;
+} __attribute__ (( packed, may_alias ));
+
+/** Usable RAM */
+#define MBMEM_RAM 1
+
+#endif /* _MULTIBOOT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h
new file mode 100644
index 00000000..a36d9cfa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _DHCP_ARCH_H
+#define _DHCP_ARCH_H
+
+/** @file
+ *
+ * Architecture-specific DHCP options
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/dhcp.h>
+
+#define DHCP_ARCH_VENDOR_CLASS_ID \
+ DHCP_STRING ( 'P', 'X', 'E', 'C', 'l', 'i', 'e', 'n', 't', ':', \
+ 'A', 'r', 'c', 'h', ':', '0', '0', '0', '0', '0', ':', \
+ 'U', 'N', 'D', 'I', ':', '0', '0', '2', '0', '0', '1' )
+
+#define DHCP_ARCH_CLIENT_ARCHITECTURE \
+ DHCP_WORD ( DHCP_CLIENT_ARCHITECTURE_X86 )
+
+#define DHCP_ARCH_CLIENT_NDI DHCP_OPTION ( 1 /* UNDI */ , 2, 1 /* v2.1 */ )
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pic8259.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pic8259.h
new file mode 100644
index 00000000..a07e97d3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pic8259.h
@@ -0,0 +1,73 @@
+/*
+ * Basic support for controlling the 8259 Programmable Interrupt Controllers.
+ *
+ * Initially written by Michael Brown (mcb30).
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef PIC8259_H
+#define PIC8259_H
+
+#include <ipxe/io.h>
+
+/* For segoff_t */
+#include "realmode.h"
+
+#define IRQ_PIC_CUTOFF 8
+
+/* 8259 register locations */
+#define PIC1_ICW1 0x20
+#define PIC1_OCW2 0x20
+#define PIC1_OCW3 0x20
+#define PIC1_ICR 0x20
+#define PIC1_IRR 0x20
+#define PIC1_ISR 0x20
+#define PIC1_ICW2 0x21
+#define PIC1_ICW3 0x21
+#define PIC1_ICW4 0x21
+#define PIC1_IMR 0x21
+#define PIC2_ICW1 0xa0
+#define PIC2_OCW2 0xa0
+#define PIC2_OCW3 0xa0
+#define PIC2_ICR 0xa0
+#define PIC2_IRR 0xa0
+#define PIC2_ISR 0xa0
+#define PIC2_ICW2 0xa1
+#define PIC2_ICW3 0xa1
+#define PIC2_ICW4 0xa1
+#define PIC2_IMR 0xa1
+
+/* Register command values */
+#define OCW3_ID 0x08
+#define OCW3_READ_IRR 0x03
+#define OCW3_READ_ISR 0x02
+#define ICR_EOI_NON_SPECIFIC 0x20
+#define ICR_EOI_NOP 0x40
+#define ICR_EOI_SPECIFIC 0x60
+#define ICR_EOI_SET_PRIORITY 0xc0
+
+/* Macros to enable/disable IRQs */
+#define IMR_REG(x) ( (x) < IRQ_PIC_CUTOFF ? PIC1_IMR : PIC2_IMR )
+#define IMR_BIT(x) ( 1 << ( (x) % IRQ_PIC_CUTOFF ) )
+#define irq_enabled(x) ( ( inb ( IMR_REG(x) ) & IMR_BIT(x) ) == 0 )
+#define enable_irq(x) outb ( inb( IMR_REG(x) ) & ~IMR_BIT(x), IMR_REG(x) )
+#define disable_irq(x) outb ( inb( IMR_REG(x) ) | IMR_BIT(x), IMR_REG(x) )
+
+/* Macros for acknowledging IRQs */
+#define ICR_REG( irq ) ( (irq) < IRQ_PIC_CUTOFF ? PIC1_ICR : PIC2_ICR )
+#define ICR_VALUE( irq ) ( (irq) % IRQ_PIC_CUTOFF )
+#define CHAINED_IRQ 2
+
+/* Utility macros to convert IRQ numbers to INT numbers and INT vectors */
+#define IRQ_INT( irq ) ( ( ( (irq) - IRQ_PIC_CUTOFF ) ^ 0x70 ) & 0x7f )
+
+/* Other constants */
+#define IRQ_MAX 15
+#define IRQ_NONE -1U
+
+/* Function prototypes
+ */
+void send_eoi ( unsigned int irq );
+
+#endif /* PIC8259_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pnpbios.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pnpbios.h
new file mode 100644
index 00000000..4c20e73e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pnpbios.h
@@ -0,0 +1,17 @@
+#ifndef _PNPBIOS_H
+#define _PNPBIOS_H
+
+/** @file
+ *
+ * PnP BIOS
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* BIOS segment address */
+#define BIOS_SEG 0xf000
+
+extern int find_pnp_bios ( void );
+
+#endif /* _PNPBIOS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe.h
new file mode 100644
index 00000000..a6bb65c0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe.h
@@ -0,0 +1,197 @@
+#ifndef PXE_H
+#define PXE_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "pxe_types.h"
+#include "pxe_api.h"
+#include <ipxe/device.h>
+#include <ipxe/tables.h>
+
+/** PXE API invalid function code */
+#define PXENV_UNKNOWN 0xffff
+
+/** Parameter block for pxenv_unknown() */
+struct s_PXENV_UNKNOWN {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNKNOWN PXENV_UNKNOWN_t;
+
+/* Union used for PXE API calls; we don't know the type of the
+ * structure until we interpret the opcode. Also, Status is available
+ * in the same location for any opcode, and it's convenient to have
+ * non-specific access to it.
+ */
+union u_PXENV_ANY {
+ /* Make it easy to read status for any operation */
+ PXENV_STATUS_t Status;
+ struct s_PXENV_UNKNOWN unknown;
+ struct s_PXENV_UNLOAD_STACK unload_stack;
+ struct s_PXENV_GET_CACHED_INFO get_cached_info;
+ struct s_PXENV_TFTP_READ_FILE restart_tftp;
+ struct s_PXENV_START_UNDI start_undi;
+ struct s_PXENV_STOP_UNDI stop_undi;
+ struct s_PXENV_START_BASE start_base;
+ struct s_PXENV_STOP_BASE stop_base;
+ struct s_PXENV_TFTP_OPEN tftp_open;
+ struct s_PXENV_TFTP_CLOSE tftp_close;
+ struct s_PXENV_TFTP_READ tftp_read;
+ struct s_PXENV_TFTP_READ_FILE tftp_read_file;
+ struct s_PXENV_TFTP_GET_FSIZE tftp_get_fsize;
+ struct s_PXENV_UDP_OPEN udp_open;
+ struct s_PXENV_UDP_CLOSE udp_close;
+ struct s_PXENV_UDP_WRITE udp_write;
+ struct s_PXENV_UDP_READ udp_read;
+ struct s_PXENV_UNDI_STARTUP undi_startup;
+ struct s_PXENV_UNDI_CLEANUP undi_cleanup;
+ struct s_PXENV_UNDI_INITIALIZE undi_initialize;
+ struct s_PXENV_UNDI_RESET undi_reset_adapter;
+ struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
+ struct s_PXENV_UNDI_OPEN undi_open;
+ struct s_PXENV_UNDI_CLOSE undi_close;
+ struct s_PXENV_UNDI_TRANSMIT undi_transmit;
+ struct s_PXENV_UNDI_SET_MCAST_ADDRESS undi_set_mcast_address;
+ struct s_PXENV_UNDI_SET_STATION_ADDRESS undi_set_station_address;
+ struct s_PXENV_UNDI_SET_PACKET_FILTER undi_set_packet_filter;
+ struct s_PXENV_UNDI_GET_INFORMATION undi_get_information;
+ struct s_PXENV_UNDI_GET_STATISTICS undi_get_statistics;
+ struct s_PXENV_UNDI_CLEAR_STATISTICS undi_clear_statistics;
+ struct s_PXENV_UNDI_INITIATE_DIAGS undi_initiate_diags;
+ struct s_PXENV_UNDI_FORCE_INTERRUPT undi_force_interrupt;
+ struct s_PXENV_UNDI_GET_MCAST_ADDRESS undi_get_mcast_address;
+ struct s_PXENV_UNDI_GET_NIC_TYPE undi_get_nic_type;
+ struct s_PXENV_UNDI_GET_IFACE_INFO undi_get_iface_info;
+ struct s_PXENV_UNDI_GET_STATE undi_get_state;
+ struct s_PXENV_UNDI_ISR undi_isr;
+ struct s_PXENV_FILE_OPEN file_open;
+ struct s_PXENV_FILE_CLOSE file_close;
+ struct s_PXENV_FILE_SELECT file_select;
+ struct s_PXENV_FILE_READ file_read;
+ struct s_PXENV_GET_FILE_SIZE get_file_size;
+ struct s_PXENV_FILE_EXEC file_exec;
+ struct s_PXENV_FILE_API_CHECK file_api_check;
+ struct s_PXENV_FILE_EXIT_HOOK file_exit_hook;
+};
+
+typedef union u_PXENV_ANY PXENV_ANY_t;
+
+/** A PXE API call */
+struct pxe_api_call {
+ /** Entry point
+ *
+ * @v params PXE API call parameters
+ * @ret exit PXE API call exit code
+ */
+ PXENV_EXIT_t ( * entry ) ( union u_PXENV_ANY *params );
+ /** Length of parameters */
+ uint16_t params_len;
+ /** Opcode */
+ uint16_t opcode;
+};
+
+/** PXE API call table */
+#define PXE_API_CALLS __table ( struct pxe_api_call, "pxe_api_calls" )
+
+/** Declare a PXE API call */
+#define __pxe_api_call __table_entry ( PXE_API_CALLS, 01 )
+
+/**
+ * Define a PXE API call
+ *
+ * @v _opcode Opcode
+ * @v _entry Entry point
+ * @v _params_type Type of parameter structure
+ * @ret call PXE API call
+ */
+#define PXE_API_CALL( _opcode, _entry, _params_type ) { \
+ .entry = ( ( ( ( PXENV_EXIT_t ( * ) ( _params_type *params ) ) NULL ) \
+ == ( ( typeof ( _entry ) * ) NULL ) ) \
+ ? ( ( PXENV_EXIT_t ( * ) \
+ ( union u_PXENV_ANY *params ) ) _entry ) \
+ : ( ( PXENV_EXIT_t ( * ) \
+ ( union u_PXENV_ANY *params ) ) _entry ) ), \
+ .params_len = sizeof ( _params_type ), \
+ .opcode = _opcode, \
+ }
+
+/** An UNDI expansion ROM header */
+struct undi_rom_header {
+ /** Signature
+ *
+ * Must be equal to @c ROM_SIGNATURE
+ */
+ UINT16_t Signature;
+ /** ROM length in 512-byte blocks */
+ UINT8_t ROMLength;
+ /** Unused */
+ UINT8_t unused[0x13];
+ /** Offset of the PXE ROM ID structure */
+ UINT16_t PXEROMID;
+ /** Offset of the PCI ROM structure */
+ UINT16_t PCIRHeader;
+} __attribute__ (( packed ));
+
+/** Signature for an expansion ROM */
+#define ROM_SIGNATURE 0xaa55
+
+/** An UNDI ROM ID structure */
+struct undi_rom_id {
+ /** Signature
+ *
+ * Must be equal to @c UNDI_ROM_ID_SIGNATURE
+ */
+ UINT32_t Signature;
+ /** Length of structure */
+ UINT8_t StructLength;
+ /** Checksum */
+ UINT8_t StructCksum;
+ /** Structure revision
+ *
+ * Must be zero.
+ */
+ UINT8_t StructRev;
+ /** UNDI revision
+ *
+ * Version 2.1.0 is encoded as the byte sequence 0x00, 0x01, 0x02.
+ */
+ UINT8_t UNDIRev[3];
+ /** Offset to UNDI loader */
+ UINT16_t UNDILoader;
+ /** Minimum required stack segment size */
+ UINT16_t StackSize;
+ /** Minimum required data segment size */
+ UINT16_t DataSize;
+ /** Minimum required code segment size */
+ UINT16_t CodeSize;
+} __attribute__ (( packed ));
+
+/** Signature for an UNDI ROM ID structure */
+#define UNDI_ROM_ID_SIGNATURE \
+ ( ( 'U' << 0 ) + ( 'N' << 8 ) + ( 'D' << 16 ) + ( 'I' << 24 ) )
+
+/** A PCI expansion header */
+struct pcir_header {
+ /** Signature
+ *
+ * Must be equal to @c PCIR_SIGNATURE
+ */
+ uint32_t signature;
+ /** PCI vendor ID */
+ uint16_t vendor_id;
+ /** PCI device ID */
+ uint16_t device_id;
+} __attribute__ (( packed ));
+
+/** Signature for an UNDI ROM ID structure */
+#define PCIR_SIGNATURE \
+ ( ( 'P' << 0 ) + ( 'C' << 8 ) + ( 'I' << 16 ) + ( 'R' << 24 ) )
+
+extern struct net_device *pxe_netdev;
+
+extern void pxe_set_netdev ( struct net_device *netdev );
+extern PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
+ *tftp_read_file );
+extern PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader );
+
+#endif /* PXE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe_api.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe_api.h
new file mode 100644
index 00000000..d01c262d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe_api.h
@@ -0,0 +1,1797 @@
+#ifndef PXE_API_H
+#define PXE_API_H
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * As an alternative, at your option, you may use this file under the
+ * following terms, known as the "MIT license":
+ *
+ * Copyright (c) 2005-2009 Michael Brown <mbrown@fensystems.co.uk>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/** @file
+ *
+ * Preboot eXecution Environment (PXE) API
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "pxe_types.h"
+
+/** @addtogroup pxe Preboot eXecution Environment (PXE) API
+ * @{
+ */
+
+/** @defgroup pxe_api_call PXE entry points
+ *
+ * PXE entry points and calling conventions
+ *
+ * @{
+ */
+
+/** The PXENV+ structure */
+struct s_PXENV {
+ /** Signature
+ *
+ * Contains the bytes 'P', 'X', 'E', 'N', 'V', '+'.
+ */
+ UINT8_t Signature[6];
+ /** PXE API version
+ *
+ * MSB is major version number, LSB is minor version number.
+ * If the API version number is 0x0201 or greater, the !PXE
+ * structure pointed to by #PXEPtr should be used instead of
+ * this data structure.
+ */
+ UINT16_t Version;
+ UINT8_t Length; /**< Length of this structure */
+ /** Checksum
+ *
+ * The byte checksum of this structure (using the length in
+ * #Length) must be zero.
+ */
+ UINT8_t Checksum;
+ SEGOFF16_t RMEntry; /**< Real-mode PXENV+ entry point */
+ /** Protected-mode PXENV+ entry point offset
+ *
+ * PXE 2.1 deprecates this entry point. For protected-mode
+ * API calls, use the !PXE structure pointed to by #PXEPtr
+ * instead.
+ */
+ UINT32_t PMOffset;
+ /** Protected-mode PXENV+ entry point segment selector
+ *
+ * PXE 2.1 deprecates this entry point. For protected-mode
+ * API calls, use the !PXE structure pointed to by #PXEPtr
+ * instead.
+ */
+ SEGSEL_t PMSelector;
+ SEGSEL_t StackSeg; /**< Stack segment selector */
+ UINT16_t StackSize; /**< Stack segment size */
+ SEGSEL_t BC_CodeSeg; /**< Base-code code segment selector */
+ UINT16_t BC_CodeSize; /**< Base-code code segment size */
+ SEGSEL_t BC_DataSeg; /**< Base-code data segment selector */
+ UINT16_t BC_DataSize; /**< Base-code data segment size */
+ SEGSEL_t UNDIDataSeg; /**< UNDI data segment selector */
+ UINT16_t UNDIDataSize; /**< UNDI data segment size */
+ SEGSEL_t UNDICodeSeg; /**< UNDI code segment selector */
+ UINT16_t UNDICodeSize; /**< UNDI code segment size */
+ /** Address of the !PXE structure
+ *
+ * This field is present only if #Version is 0x0201 or
+ * greater. If present, it points to a struct s_PXE.
+ */
+ SEGOFF16_t PXEPtr;
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV PXENV_t;
+
+/** The !PXE structure */
+struct s_PXE {
+ /** Signature
+ *
+ * Contains the bytes '!', 'P', 'X', 'E'.
+ */
+ UINT8_t Signature[4];
+ UINT8_t StructLength; /**< Length of this structure */
+ /** Checksum
+ *
+ * The byte checksum of this structure (using the length in
+ * #StructLength) must be zero.
+ */
+ UINT8_t StructCksum;
+ /** Revision of this structure
+ *
+ * For PXE version 2.1, this field must be zero.
+ */
+ UINT8_t StructRev;
+ UINT8_t reserved_1; /**< Must be zero */
+ /** Address of the UNDI ROM ID structure
+ *
+ * This is a pointer to a struct s_UNDI_ROM_ID.
+ */
+ SEGOFF16_t UNDIROMID;
+ /** Address of the Base Code ROM ID structure
+ *
+ * This is a pointer to a struct s_BC_ROM_ID.
+ */
+ SEGOFF16_t BaseROMID;
+ /** 16-bit !PXE entry point
+ *
+ * This is the entry point for either real mode, or protected
+ * mode with a 16-bit stack segment.
+ */
+ SEGOFF16_t EntryPointSP;
+ /** 32-bit !PXE entry point
+ *
+ * This is the entry point for protected mode with a 32-bit
+ * stack segment.
+ */
+ SEGOFF16_t EntryPointESP;
+ /** Status call-out function
+ *
+ * @v 0 (if in a time-out loop)
+ * @v n Number of a received TFTP packet
+ * @ret 0 Continue operation
+ * @ret 1 Cancel operation
+ *
+ * This function will be called whenever the PXE stack is in
+ * protected mode, is waiting for an event (e.g. a DHCP reply)
+ * and wishes to allow the user to cancel the operation.
+ * Parameters are passed in register %ax; the return value
+ * must also be placed in register %ax. All other registers
+ * and flags @b must be preserved.
+ *
+ * In real mode, an internal function (that checks for a
+ * keypress) will be used.
+ *
+ * If this field is set to -1, no status call-out function
+ * will be used and consequently the user will not be allowed
+ * to interrupt operations.
+ *
+ * @note The PXE specification version 2.1 defines the
+ * StatusCallout field, mentions it 11 times, but nowhere
+ * defines what it actually does or how it gets called.
+ * Fortunately, the WfM specification version 1.1a deigns to
+ * inform us of such petty details.
+ */
+ SEGOFF16_t StatusCallout;
+ UINT8_t reserved_2; /**< Must be zero */
+ /** Number of segment descriptors
+ *
+ * If this number is greater than 7, the remaining descriptors
+ * follow immediately after #BC_CodeWrite.
+ */
+ UINT8_t SegDescCnt;
+ /** First protected-mode selector
+ *
+ * This is the segment selector value for the first segment
+ * assigned to PXE. Protected-mode selectors must be
+ * consecutive, according to the PXE 2.1 specification, though
+ * no reason is given. Each #SEGDESC_t includes a field for
+ * the segment selector, so this information is entirely
+ * redundant.
+ */
+ SEGSEL_t FirstSelector;
+ /** Stack segment descriptor */
+ SEGDESC_t Stack;
+ /** UNDI data segment descriptor */
+ SEGDESC_t UNDIData;
+ /** UNDI code segment descriptor */
+ SEGDESC_t UNDICode;
+ /** UNDI writable code segment descriptor */
+ SEGDESC_t UNDICodeWrite;
+ /** Base-code data segment descriptor */
+ SEGDESC_t BC_Data;
+ /** Base-code code segment descriptor */
+ SEGDESC_t BC_Code;
+ /** Base-code writable code segment descriptor */
+ SEGDESC_t BC_CodeWrite;
+} __attribute__ (( packed ));
+
+typedef struct s_PXE PXE_t;
+
+/** @} */ /* pxe_api_call */
+
+/** @defgroup pxe_preboot_api PXE Preboot API
+ *
+ * General high-level functions: #PXENV_UNLOAD_STACK, #PXENV_START_UNDI etc.
+ *
+ * @{
+ */
+
+/** @defgroup pxenv_unload_stack PXENV_UNLOAD_STACK
+ *
+ * UNLOAD BASE CODE STACK
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_unload_stack() */
+#define PXENV_UNLOAD_STACK 0x0070
+
+/** Parameter block for pxenv_unload_stack() */
+struct s_PXENV_UNLOAD_STACK {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT8_t reserved[10]; /**< Must be zero */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNLOAD_STACK PXENV_UNLOAD_STACK_t;
+
+/** @} */ /* pxenv_unload_stack */
+
+/** @defgroup pxenv_get_cached_info PXENV_GET_CACHED_INFO
+ *
+ * GET CACHED INFO
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_get_cached_info() */
+#define PXENV_GET_CACHED_INFO 0x0071
+
+/** The client's DHCPDISCOVER packet */
+#define PXENV_PACKET_TYPE_DHCP_DISCOVER 1
+
+/** The DHCP server's DHCPACK packet */
+#define PXENV_PACKET_TYPE_DHCP_ACK 2
+
+/** The Boot Server's Discover Reply packet
+ *
+ * This packet contains DHCP option 60 set to "PXEClient", a valid
+ * boot file name, and may or may not contain MTFTP options.
+ */
+#define PXENV_PACKET_TYPE_CACHED_REPLY 3
+
+/** Parameter block for pxenv_get_cached_info() */
+struct s_PXENV_GET_CACHED_INFO {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Packet type.
+ *
+ * Valid values are #PXENV_PACKET_TYPE_DHCP_DISCOVER,
+ * #PXENV_PACKET_TYPE_DHCP_ACK or #PXENV_PACKET_TYPE_CACHED_REPLY
+ */
+ UINT16_t PacketType;
+ UINT16_t BufferSize; /**< Buffer size */
+ SEGOFF16_t Buffer; /**< Buffer address */
+ UINT16_t BufferLimit; /**< Maximum buffer size */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_GET_CACHED_INFO PXENV_GET_CACHED_INFO_t;
+
+#define BOOTP_REQ 1 /**< A BOOTP request packet */
+#define BOOTP_REP 2 /**< A BOOTP reply packet */
+
+/** DHCP broadcast flag
+ *
+ * Request a broadcast response (DHCPOFFER or DHCPACK) from the DHCP
+ * server.
+ */
+#define BOOTP_BCAST 0x8000
+
+#define VM_RFC1048 0x63825363L /**< DHCP magic cookie */
+
+/** Maximum length of DHCP options */
+#define BOOTP_DHCPVEND 1024
+
+/** Format of buffer filled in by pxenv_get_cached_info()
+ *
+ * This somewhat convoluted data structure simply describes the layout
+ * of a DHCP packet. Refer to RFC2131 section 2 for a full
+ * description.
+ */
+struct bootph {
+ /** Message opcode.
+ *
+ * Valid values are #BOOTP_REQ and #BOOTP_REP.
+ */
+ UINT8_t opcode;
+ /** NIC hardware type.
+ *
+ * Valid values are as for s_PXENV_UNDI_GET_INFORMATION::HwType.
+ */
+ UINT8_t Hardware;
+ UINT8_t Hardlen; /**< MAC address length */
+ /** Gateway hops
+ *
+ * Zero in packets sent by the client. May be non-zero in
+ * replies from the DHCP server, if the reply comes via a DHCP
+ * relay agent.
+ */
+ UINT8_t Gatehops;
+ UINT32_t ident; /**< DHCP transaction id (xid) */
+ /** Elapsed time
+ *
+ * Number of seconds since the client began the DHCP
+ * transaction.
+ */
+ UINT16_t seconds;
+ /** Flags
+ *
+ * This is the bitwise-OR of any of the following values:
+ * #BOOTP_BCAST.
+ */
+ UINT16_t Flags;
+ /** Client IP address
+ *
+ * Set only if the client already has an IP address.
+ */
+ IP4_t cip;
+ /** Your IP address
+ *
+ * This is the IP address that the server assigns to the
+ * client.
+ */
+ IP4_t yip;
+ /** Server IP address
+ *
+ * This is the IP address of the BOOTP/DHCP server.
+ */
+ IP4_t sip;
+ /** Gateway IP address
+ *
+ * This is the IP address of the BOOTP/DHCP relay agent, if
+ * any. It is @b not (necessarily) the address of the default
+ * gateway for routing purposes.
+ */
+ IP4_t gip;
+ MAC_ADDR_t CAddr; /**< Client MAC address */
+ UINT8_t Sname[64]; /**< Server host name */
+ UINT8_t bootfile[128]; /**< Boot file name */
+ /** DHCP options
+ *
+ * Don't ask. Just laugh. Then burn a copy of the PXE
+ * specification and send Intel an e-mail asking them if
+ * they've figured out what a "union" does in C yet.
+ */
+ union bootph_vendor {
+ UINT8_t d[BOOTP_DHCPVEND]; /**< DHCP options */
+ /** DHCP options */
+ struct bootph_vendor_v {
+ /** DHCP magic cookie
+ *
+ * Should have the value #VM_RFC1048.
+ */
+ UINT8_t magic[4];
+ UINT32_t flags; /**< BOOTP flags/opcodes */
+ /** "End of BOOTP vendor extensions"
+ *
+ * Abandon hope, all ye who consider the
+ * purpose of this field.
+ */
+ UINT8_t pad[56];
+ } v;
+ } vendor;
+} __attribute__ (( packed ));
+
+typedef struct bootph BOOTPLAYER_t;
+
+/** @} */ /* pxenv_get_cached_info */
+
+/** @defgroup pxenv_restart_tftp PXENV_RESTART_TFTP
+ *
+ * RESTART TFTP
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_restart_tftp() */
+#define PXENV_RESTART_TFTP 0x0073
+
+/** Parameter block for pxenv_restart_tftp() */
+struct s_PXENV_TFTP_READ_FILE;
+
+typedef struct s_PXENV_RESTART_TFTP PXENV_RESTART_TFTP_t;
+
+/** @} */ /* pxenv_restart_tftp */
+
+/** @defgroup pxenv_start_undi PXENV_START_UNDI
+ *
+ * START UNDI
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_start_undi() */
+#define PXENV_START_UNDI 0x0000
+
+/** Parameter block for pxenv_start_undi() */
+struct s_PXENV_START_UNDI {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** %ax register as passed to the Option ROM initialisation routine.
+ *
+ * For a PCI device, this should contain the bus:dev:fn value
+ * that uniquely identifies the PCI device in the system. For
+ * a non-PCI device, this field is not defined.
+ */
+ UINT16_t AX;
+ /** %bx register as passed to the Option ROM initialisation routine.
+ *
+ * For an ISAPnP device, this should contain the Card Select
+ * Number assigned to the ISAPnP card. For non-ISAPnP
+ * devices, this should contain 0xffff.
+ */
+ UINT16_t BX;
+ /** %dx register as passed to the Option ROM initialisation routine.
+ *
+ * For an ISAPnP device, this should contain the ISAPnP Read
+ * Port address as currently set in all ISAPnP cards. If
+ * there are no ISAPnP cards, this should contain 0xffff. (If
+ * this is a non-ISAPnP device, but there are ISAPnP cards in
+ * the system, this value is not well defined.)
+ */
+ UINT16_t DX;
+ /** %di register as passed to the Option ROM initialisation routine.
+ *
+ * This contains the #OFF16_t portion of a struct #s_SEGOFF16
+ * that points to the System BIOS Plug and Play Installation
+ * Check Structure. (Refer to section 4.4 of the Plug and
+ * Play BIOS specification for a description of this
+ * structure.)
+ *
+ * @note The PXE specification defines the type of this field
+ * as #UINT16_t. For x86, #OFF16_t and #UINT16_t are
+ * equivalent anyway; for other architectures #OFF16_t makes
+ * more sense.
+ */
+ OFF16_t DI;
+ /** %es register as passed to the Option ROM initialisation routine.
+ *
+ * This contains the #SEGSEL_t portion of a struct #s_SEGOFF16
+ * that points to the System BIOS Plug and Play Installation
+ * Check Structure. (Refer to section 4.4 of the Plug and
+ * Play BIOS specification for a description of this
+ * structure.)
+ *
+ * @note The PXE specification defines the type of this field
+ * as #UINT16_t. For x86, #SEGSEL_t and #UINT16_t are
+ * equivalent anyway; for other architectures #SEGSEL_t makes
+ * more sense.
+ */
+ SEGSEL_t ES;
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_START_UNDI PXENV_START_UNDI_t;
+
+/** @} */ /* pxenv_start_undi */
+
+/** @defgroup pxenv_stop_undi PXENV_STOP_UNDI
+ *
+ * STOP UNDI
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_stop_undi() */
+#define PXENV_STOP_UNDI 0x0015
+
+/** Parameter block for pxenv_stop_undi() */
+struct s_PXENV_STOP_UNDI {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_STOP_UNDI PXENV_STOP_UNDI_t;
+
+/** @} */ /* pxenv_stop_undi */
+
+/** @defgroup pxenv_start_base PXENV_START_BASE
+ *
+ * START BASE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_start_base() */
+#define PXENV_START_BASE 0x0075
+
+/** Parameter block for pxenv_start_base() */
+struct s_PXENV_START_BASE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_START_BASE PXENV_START_BASE_t;
+
+/** @} */ /* pxenv_start_base */
+
+/** @defgroup pxenv_stop_base PXENV_STOP_BASE
+ *
+ * STOP BASE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_stop_base() */
+#define PXENV_STOP_BASE 0x0076
+
+/** Parameter block for pxenv_stop_base() */
+struct s_PXENV_STOP_BASE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_STOP_BASE PXENV_STOP_BASE_t;
+
+/** @} */ /* pxenv_stop_base */
+
+/** @} */ /* pxe_preboot_api */
+
+/** @defgroup pxe_tftp_api PXE TFTP API
+ *
+ * Download files via TFTP or MTFTP
+ *
+ * @{
+ */
+
+/** @defgroup pxenv_tftp_open PXENV_TFTP_OPEN
+ *
+ * TFTP OPEN
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_tftp_open() */
+#define PXENV_TFTP_OPEN 0x0020
+
+/** Parameter block for pxenv_tftp_open() */
+struct s_PXENV_TFTP_OPEN {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ IP4_t ServerIPAddress; /**< TFTP server IP address */
+ IP4_t GatewayIPAddress; /**< Relay agent IP address */
+ UINT8_t FileName[128]; /**< File name */
+ UDP_PORT_t TFTPPort; /**< TFTP server UDP port */
+ /** Requested size of TFTP packets
+ *
+ * This is the TFTP "blksize" option. This must be at least
+ * 512, since servers that do not support TFTP options cannot
+ * negotiate blocksizes smaller than this.
+ */
+ UINT16_t PacketSize;
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_TFTP_OPEN PXENV_TFTP_OPEN_t;
+
+/** @} */ /* pxenv_tftp_open */
+
+/** @defgroup pxenv_tftp_close PXENV_TFTP_CLOSE
+ *
+ * TFTP CLOSE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_tftp_close() */
+#define PXENV_TFTP_CLOSE 0x0021
+
+/** Parameter block for pxenv_tftp_close() */
+struct s_PXENV_TFTP_CLOSE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_TFTP_CLOSE PXENV_TFTP_CLOSE_t;
+
+/** @} */ /* pxenv_tftp_close */
+
+/** @defgroup pxenv_tftp_read PXENV_TFTP_READ
+ *
+ * TFTP READ
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_tftp_read() */
+#define PXENV_TFTP_READ 0x0022
+
+/** Parameter block for pxenv_tftp_read() */
+struct s_PXENV_TFTP_READ {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t PacketNumber; /**< TFTP packet number */
+ UINT16_t BufferSize; /**< Size of data buffer */
+ SEGOFF16_t Buffer; /**< Address of data buffer */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_TFTP_READ PXENV_TFTP_READ_t;
+
+/** @} */ /* pxenv_tftp_read */
+
+/** @defgroup pxenv_tftp_read_file PXENV_TFTP_READ_FILE
+ *
+ * TFTP/MTFTP READ FILE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_tftp_read_file() */
+#define PXENV_TFTP_READ_FILE 0x0023
+
+/** Parameter block for pxenv_tftp_read_file() */
+struct s_PXENV_TFTP_READ_FILE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT8_t FileName[128]; /**< File name */
+ UINT32_t BufferSize; /**< Size of data buffer */
+ ADDR32_t Buffer; /**< Address of data buffer */
+ IP4_t ServerIPAddress; /**< TFTP server IP address */
+ IP4_t GatewayIPAddress; /**< Relay agent IP address */
+ /** File multicast IP address */
+ IP4_t McastIPAddress;
+ /** Client multicast listening port */
+ UDP_PORT_t TFTPClntPort;
+ /** Server multicast listening port */
+ UDP_PORT_t TFTPSrvPort;
+ /** TFTP open timeout.
+ *
+ * This is the timeout for receiving the first DATA or ACK
+ * packets during the MTFTP Listen phase.
+ */
+ UINT16_t TFTPOpenTimeOut;
+ /** TFTP reopen timeout.
+ *
+ * This is the timeout for receiving an ACK packet while in
+ * the MTFTP Listen phase (when at least one ACK packet has
+ * already been seen).
+ */
+ UINT16_t TFTPReopenDelay;
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_TFTP_READ_FILE PXENV_TFTP_READ_FILE_t;
+
+/** @} */ /* pxenv_tftp_read_file */
+
+/** @defgroup pxenv_tftp_get_fsize PXENV_TFTP_GET_FSIZE
+ *
+ * TFTP GET FILE SIZE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_tftp_get_fsize() */
+#define PXENV_TFTP_GET_FSIZE 0x0025
+
+/** Parameter block for pxenv_tftp_get_fsize() */
+struct s_PXENV_TFTP_GET_FSIZE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ IP4_t ServerIPAddress; /**< TFTP server IP address */
+ IP4_t GatewayIPAddress; /**< Relay agent IP address */
+ UINT8_t FileName[128]; /**< File name */
+ UINT32_t FileSize; /**< Size of the file */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_TFTP_GET_FSIZE PXENV_TFTP_GET_FSIZE_t;
+
+/** @} */ /* pxenv_tftp_get_fsize */
+
+/** @} */ /* pxe_tftp_api */
+
+/** @defgroup pxe_udp_api PXE UDP API
+ *
+ * Transmit and receive UDP packets
+ *
+ * @{
+ */
+
+/** @defgroup pxenv_udp_open PXENV_UDP_OPEN
+ *
+ * UDP OPEN
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_udp_open() */
+#define PXENV_UDP_OPEN 0x0030
+
+/** Parameter block for pxenv_udp_open() */
+struct s_PXENV_UDP_OPEN {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ IP4_t src_ip; /**< IP address of this station */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UDP_OPEN PXENV_UDP_OPEN_t;
+
+/** @} */ /* pxenv_udp_open */
+
+/** @defgroup pxenv_udp_close PXENV_UDP_CLOSE
+ *
+ * UDP CLOSE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_udp_close() */
+#define PXENV_UDP_CLOSE 0x0031
+
+/** Parameter block for pxenv_udp_close() */
+struct s_PXENV_UDP_CLOSE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UDP_CLOSE PXENV_UDP_CLOSE_t;
+
+/** @} */ /* pxenv_udp_close */
+
+/** @defgroup pxenv_udp_write PXENV_UDP_WRITE
+ *
+ * UDP WRITE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_udp_write() */
+#define PXENV_UDP_WRITE 0x0033
+
+/** Parameter block for pxenv_udp_write() */
+struct s_PXENV_UDP_WRITE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ IP4_t ip; /**< Destination IP address */
+ IP4_t gw; /**< Relay agent IP address */
+ UDP_PORT_t src_port; /**< Source UDP port */
+ UDP_PORT_t dst_port; /**< Destination UDP port */
+ UINT16_t buffer_size; /**< UDP payload buffer size */
+ SEGOFF16_t buffer; /**< UDP payload buffer address */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UDP_WRITE PXENV_UDP_WRITE_t;
+
+/** @} */ /* pxenv_udp_write */
+
+/** @defgroup pxenv_udp_read PXENV_UDP_READ
+ *
+ * UDP READ
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_udp_read() */
+#define PXENV_UDP_READ 0x0032
+
+/** Parameter block for pxenv_udp_read() */
+struct s_PXENV_UDP_READ {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ IP4_t src_ip; /**< Source IP address */
+ IP4_t dest_ip; /**< Destination IP address */
+ UDP_PORT_t s_port; /**< Source UDP port */
+ UDP_PORT_t d_port; /**< Destination UDP port */
+ UINT16_t buffer_size; /**< UDP payload buffer size */
+ SEGOFF16_t buffer; /**< UDP payload buffer address */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UDP_READ PXENV_UDP_READ_t;
+
+/** @} */ /* pxenv_udp_read */
+
+/** @} */ /* pxe_udp_api */
+
+/** @defgroup pxe_undi_api PXE UNDI API
+ *
+ * Direct control of the network interface card
+ *
+ * @{
+ */
+
+/** @defgroup pxenv_undi_startup PXENV_UNDI_STARTUP
+ *
+ * UNDI STARTUP
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_startup() */
+#define PXENV_UNDI_STARTUP 0x0001
+
+#define PXENV_BUS_ISA 0 /**< ISA bus type */
+#define PXENV_BUS_EISA 1 /**< EISA bus type */
+#define PXENV_BUS_MCA 2 /**< MCA bus type */
+#define PXENV_BUS_PCI 3 /**< PCI bus type */
+#define PXENV_BUS_VESA 4 /**< VESA bus type */
+#define PXENV_BUS_PCMCIA 5 /**< PCMCIA bus type */
+
+/** Parameter block for pxenv_undi_startup() */
+struct s_PXENV_UNDI_STARTUP {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_STARTUP PXENV_UNDI_STARTUP_t;
+
+/** @} */ /* pxenv_undi_startup */
+
+/** @defgroup pxenv_undi_cleanup PXENV_UNDI_CLEANUP
+ *
+ * UNDI CLEANUP
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_cleanup() */
+#define PXENV_UNDI_CLEANUP 0x0002
+
+/** Parameter block for pxenv_undi_cleanup() */
+struct s_PXENV_UNDI_CLEANUP {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_CLEANUP PXENV_UNDI_CLEANUP_t;
+
+/** @} */ /* pxenv_undi_cleanup */
+
+/** @defgroup pxenv_undi_initialize PXENV_UNDI_INITIALIZE
+ *
+ * UNDI INITIALIZE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_initialize() */
+#define PXENV_UNDI_INITIALIZE 0x0003
+
+/** Parameter block for pxenv_undi_initialize() */
+struct s_PXENV_UNDI_INITIALIZE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** NDIS 2.0 configuration information, or NULL
+ *
+ * This is a pointer to the data structure returned by the
+ * NDIS 2.0 GetProtocolManagerInfo() API call. The data
+ * structure is documented, in a rather haphazard way, in
+ * section 4-17 of the NDIS 2.0 specification.
+ */
+ ADDR32_t ProtocolIni;
+ UINT8_t reserved[8]; /**< Must be zero */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_INITIALIZE PXENV_UNDI_INITIALIZE_t;
+
+/** @} */ /* pxenv_undi_initialize */
+
+/** @defgroup pxenv_undi_reset_adapter PXENV_UNDI_RESET_ADAPTER
+ *
+ * UNDI RESET ADAPTER
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_reset_adapter() */
+#define PXENV_UNDI_RESET_ADAPTER 0x0004
+
+/** Maximum number of multicast MAC addresses */
+#define MAXNUM_MCADDR 8
+
+/** List of multicast MAC addresses */
+struct s_PXENV_UNDI_MCAST_ADDRESS {
+ /** Number of multicast MAC addresses */
+ UINT16_t MCastAddrCount;
+ /** List of up to #MAXNUM_MCADDR multicast MAC addresses */
+ MAC_ADDR_t McastAddr[MAXNUM_MCADDR];
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_MCAST_ADDRESS PXENV_UNDI_MCAST_ADDRESS_t;
+
+/** Parameter block for pxenv_undi_reset_adapter() */
+struct s_PXENV_UNDI_RESET {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Multicast MAC addresses */
+ struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_RESET PXENV_UNDI_RESET_t;
+
+/** @} */ /* pxenv_undi_reset_adapter */
+
+/** @defgroup pxenv_undi_shutdown PXENV_UNDI_SHUTDOWN
+ *
+ * UNDI SHUTDOWN
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_shutdown() */
+#define PXENV_UNDI_SHUTDOWN 0x0005
+
+/** Parameter block for pxenv_undi_shutdown() */
+struct s_PXENV_UNDI_SHUTDOWN {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_SHUTDOWN PXENV_UNDI_SHUTDOWN_t;
+
+/** @} */ /* pxenv_undi_shutdown */
+
+/** @defgroup pxenv_undi_open PXENV_UNDI_OPEN
+ *
+ * UNDI OPEN
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_open() */
+#define PXENV_UNDI_OPEN 0x0006
+
+/** Accept "directed" packets
+ *
+ * These are packets addresses to either this adapter's MAC address or
+ * to any of the configured multicast MAC addresses (see
+ * #s_PXENV_UNDI_MCAST_ADDRESS).
+ */
+#define FLTR_DIRECTED 0x0001
+/** Accept broadcast packets */
+#define FLTR_BRDCST 0x0002
+/** Accept all packets; listen in promiscuous mode */
+#define FLTR_PRMSCS 0x0004
+/** Accept source-routed packets */
+#define FLTR_SRC_RTG 0x0008
+
+/** Parameter block for pxenv_undi_open() */
+struct s_PXENV_UNDI_OPEN {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Open flags as defined in NDIS 2.0
+ *
+ * This is the OpenOptions field as passed to the NDIS 2.0
+ * OpenAdapter() API call. It is defined to be "adapter
+ * specific", though 0 is guaranteed to be a valid value.
+ */
+ UINT16_t OpenFlag;
+ /** Receive packet filter
+ *
+ * This is the bitwise-OR of any of the following flags:
+ * #FLTR_DIRECTED, #FLTR_BRDCST, #FLTR_PRMSCS and
+ * #FLTR_SRC_RTG.
+ */
+ UINT16_t PktFilter;
+ /** Multicast MAC addresses */
+ struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_OPEN PXENV_UNDI_OPEN_t;
+
+/** @} */ /* pxenv_undi_open */
+
+/** @defgroup pxenv_undi_close PXENV_UNDI_CLOSE
+ *
+ * UNDI CLOSE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_close() */
+#define PXENV_UNDI_CLOSE 0x0007
+
+/** Parameter block for pxenv_undi_close() */
+struct s_PXENV_UNDI_CLOSE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_CLOSE PXENV_UNDI_CLOSE_t;
+
+/** @} */ /* pxenv_undi_close */
+
+/** @defgroup pxenv_undi_transmit PXENV_UNDI_TRANSMIT
+ *
+ * UNDI TRANSMIT PACKET
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_transmit() */
+#define PXENV_UNDI_TRANSMIT 0x0008
+
+#define P_UNKNOWN 0 /**< Media header already filled in */
+#define P_IP 1 /**< IP protocol */
+#define P_ARP 2 /**< ARP protocol */
+#define P_RARP 3 /**< RARP protocol */
+#define P_OTHER 4 /**< Other protocol */
+
+#define XMT_DESTADDR 0x0000 /**< Unicast packet */
+#define XMT_BROADCAST 0x0001 /**< Broadcast packet */
+
+/** Maximum number of data blocks in a transmit buffer descriptor */
+#define MAX_DATA_BLKS 8
+
+/** A transmit buffer descriptor, as pointed to by s_PXENV_UNDI_TRANSMIT::TBD
+ */
+struct s_PXENV_UNDI_TBD {
+ UINT16_t ImmedLength; /**< Length of the transmit buffer */
+ SEGOFF16_t Xmit; /**< Address of the transmit buffer */
+ UINT16_t DataBlkCount;
+ /** Array of up to #MAX_DATA_BLKS additional transmit buffers */
+ struct DataBlk {
+ /** Always 1
+ *
+ * A value of 0 would indicate that #TDDataPtr were an
+ * #ADDR32_t rather than a #SEGOFF16_t. The PXE
+ * specification version 2.1 explicitly states that
+ * this is not supported; #TDDataPtr will always be a
+ * #SEGOFF16_t.
+ */
+ UINT8_t TDPtrType;
+ UINT8_t TDRsvdByte; /**< Must be zero */
+ UINT16_t TDDataLen; /**< Length of this transmit buffer */
+ SEGOFF16_t TDDataPtr; /**< Address of this transmit buffer */
+ } DataBlock[MAX_DATA_BLKS];
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_TBD PXENV_UNDI_TBD_t;
+
+/** Parameter block for pxenv_undi_transmit() */
+struct s_PXENV_UNDI_TRANSMIT {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Protocol
+ *
+ * Valid values are #P_UNKNOWN, #P_IP, #P_ARP or #P_RARP. If
+ * the caller has already filled in the media header, this
+ * field must be set to #P_UNKNOWN.
+ */
+ UINT8_t Protocol;
+ /** Unicast/broadcast flag
+ *
+ * Valid values are #XMT_DESTADDR or #XMT_BROADCAST.
+ */
+ UINT8_t XmitFlag;
+ SEGOFF16_t DestAddr; /**< Destination MAC address */
+ /** Address of the Transmit Buffer Descriptor
+ *
+ * This is a pointer to a struct s_PXENV_UNDI_TBD.
+ */
+ SEGOFF16_t TBD;
+ UINT32_t Reserved[2]; /**< Must be zero */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_TRANSMIT PXENV_UNDI_TRANSMIT_t;
+
+/** @} */ /* pxenv_undi_transmit */
+
+/** @defgroup pxenv_undi_set_mcast_address PXENV_UNDI_SET_MCAST_ADDRESS
+ *
+ * UNDI SET MULTICAST ADDRESS
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_set_mcast_address() */
+#define PXENV_UNDI_SET_MCAST_ADDRESS 0x0009
+
+/** Parameter block for pxenv_undi_set_mcast_address() */
+struct s_PXENV_UNDI_SET_MCAST_ADDRESS {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** List of multicast addresses */
+ struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_SET_MCAST_ADDRESS PXENV_UNDI_SET_MCAST_ADDRESS_t;
+
+/** @} */ /* pxenv_undi_set_mcast_address */
+
+/** @defgroup pxenv_undi_set_station_address PXENV_UNDI_SET_STATION_ADDRESS
+ *
+ * UNDI SET STATION ADDRESS
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_set_station_address() */
+#define PXENV_UNDI_SET_STATION_ADDRESS 0x000a
+
+/** Parameter block for pxenv_undi_set_station_address() */
+struct s_PXENV_UNDI_SET_STATION_ADDRESS {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ MAC_ADDR_t StationAddress; /**< Station MAC address */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_SET_STATION_ADDRESS PXENV_UNDI_SET_STATION_ADDRESS_t;
+
+/** @} */ /* pxenv_undi_set_station_address */
+
+/** @defgroup pxenv_undi_set_packet_filter PXENV_UNDI_SET_PACKET_FILTER
+ *
+ * UNDI SET PACKET FILTER
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_set_packet_filter() */
+#define PXENV_UNDI_SET_PACKET_FILTER 0x000b
+
+/** Parameter block for pxenv_undi_set_packet_filter() */
+struct s_PXENV_UNDI_SET_PACKET_FILTER {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Receive packet filter
+ *
+ * This field takes the same values as
+ * s_PXENV_UNDI_OPEN::PktFilter.
+ *
+ * @note Yes, this field is a different size to
+ * s_PXENV_UNDI_OPEN::PktFilter. Blame "the managers at Intel
+ * who apparently let a consultant come up with the spec
+ * without any kind of adult supervision" (quote from hpa).
+ */
+ UINT8_t filter;
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_SET_PACKET_FILTER PXENV_UNDI_SET_PACKET_FILTER_t;
+
+/** @} */ /* pxenv_undi_set_packet_filter */
+
+/** @defgroup pxenv_undi_get_information PXENV_UNDI_GET_INFORMATION
+ *
+ * UNDI GET INFORMATION
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_get_information() */
+#define PXENV_UNDI_GET_INFORMATION 0x000c
+
+#define ETHER_TYPE 1 /**< Ethernet (10Mb) */
+#define EXP_ETHER_TYPE 2 /**< Experimental Ethernet (3Mb) */
+#define AX25_TYPE 3 /**< Amateur Radio AX.25 */
+#define TOKEN_RING_TYPE 4 /**< Proteon ProNET Token Ring */
+#define CHAOS_TYPE 5 /**< Chaos */
+#define IEEE_TYPE 6 /**< IEEE 802 Networks */
+#define ARCNET_TYPE 7 /**< ARCNET */
+
+/** Parameter block for pxenv_undi_get_information() */
+struct s_PXENV_UNDI_GET_INFORMATION {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t BaseIo; /**< I/O base address */
+ UINT16_t IntNumber; /**< IRQ number */
+ UINT16_t MaxTranUnit; /**< Adapter MTU */
+ /** Hardware type
+ *
+ * Valid values are defined in RFC1010 ("Assigned numbers"),
+ * and are #ETHER_TYPE, #EXP_ETHER_TYPE, #AX25_TYPE,
+ * #TOKEN_RING_TYPE, #CHAOS_TYPE, #IEEE_TYPE or #ARCNET_TYPE.
+ */
+ UINT16_t HwType;
+ UINT16_t HwAddrLen; /**< MAC address length */
+ MAC_ADDR_t CurrentNodeAddress; /**< Current MAC address */
+ MAC_ADDR_t PermNodeAddress; /**< Permanent (EEPROM) MAC address */
+ SEGSEL_t ROMAddress; /**< Real-mode ROM segment address */
+ UINT16_t RxBufCt; /**< Receive queue length */
+ UINT16_t TxBufCt; /**< Transmit queue length */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_GET_INFORMATION PXENV_UNDI_GET_INFORMATION_t;
+
+/** @} */ /* pxenv_undi_get_information */
+
+/** @defgroup pxenv_undi_get_statistics PXENV_UNDI_GET_STATISTICS
+ *
+ * UNDI GET STATISTICS
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_get_statistics() */
+#define PXENV_UNDI_GET_STATISTICS 0x000d
+
+/** Parameter block for pxenv_undi_get_statistics() */
+struct s_PXENV_UNDI_GET_STATISTICS {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT32_t XmtGoodFrames; /**< Successful transmission count */
+ UINT32_t RcvGoodFrames; /**< Successful reception count */
+ UINT32_t RcvCRCErrors; /**< Receive CRC error count */
+ UINT32_t RcvResourceErrors; /**< Receive queue overflow count */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_GET_STATISTICS PXENV_UNDI_GET_STATISTICS_t;
+
+/** @} */ /* pxenv_undi_get_statistics */
+
+/** @defgroup pxenv_undi_clear_statistics PXENV_UNDI_CLEAR_STATISTICS
+ *
+ * UNDI CLEAR STATISTICS
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_clear_statistics() */
+#define PXENV_UNDI_CLEAR_STATISTICS 0x000e
+
+/** Parameter block for pxenv_undi_clear_statistics() */
+struct s_PXENV_UNDI_CLEAR_STATISTICS {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_CLEAR_STATISTICS PXENV_UNDI_CLEAR_STATISTICS_t;
+
+/** @} */ /* pxenv_undi_clear_statistics */
+
+/** @defgroup pxenv_undi_initiate_diags PXENV_UNDI_INITIATE_DIAGS
+ *
+ * UNDI INITIATE DIAGS
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_initiate_diags() */
+#define PXENV_UNDI_INITIATE_DIAGS 0x000f
+
+/** Parameter block for pxenv_undi_initiate_diags() */
+struct s_PXENV_UNDI_INITIATE_DIAGS {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_INITIATE_DIAGS PXENV_UNDI_INITIATE_DIAGS_t;
+
+/** @} */ /* pxenv_undi_initiate_diags */
+
+/** @defgroup pxenv_undi_force_interrupt PXENV_UNDI_FORCE_INTERRUPT
+ *
+ * UNDI FORCE INTERRUPT
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_force_interrupt() */
+#define PXENV_UNDI_FORCE_INTERRUPT 0x0010
+
+/** Parameter block for pxenv_undi_force_interrupt() */
+struct s_PXENV_UNDI_FORCE_INTERRUPT {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_FORCE_INTERRUPT PXENV_UNDI_FORCE_INTERRUPT_t;
+
+/** @} */ /* pxenv_undi_force_interrupt */
+
+/** @defgroup pxenv_undi_get_mcast_address PXENV_UNDI_GET_MCAST_ADDRESS
+ *
+ * UNDI GET MULTICAST ADDRESS
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_get_mcast_address() */
+#define PXENV_UNDI_GET_MCAST_ADDRESS 0x0011
+
+/** Parameter block for pxenv_undi_get_mcast_address() */
+struct s_PXENV_UNDI_GET_MCAST_ADDRESS {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ IP4_t InetAddr; /**< Multicast IP address */
+ MAC_ADDR_t MediaAddr; /**< Multicast MAC address */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_GET_MCAST_ADDRESS PXENV_UNDI_GET_MCAST_ADDRESS_t;
+
+/** @} */ /* pxenv_undi_get_mcast_address */
+
+/** @defgroup pxenv_undi_get_nic_type PXENV_UNDI_GET_NIC_TYPE
+ *
+ * UNDI GET NIC TYPE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_get_nic_type() */
+#define PXENV_UNDI_GET_NIC_TYPE 0x0012
+
+#define PCI_NIC 2 /**< PCI network card */
+#define PnP_NIC 3 /**< ISAPnP network card */
+#define CardBus_NIC 4 /**< CardBus network card */
+
+/** Information for a PCI or equivalent NIC */
+struct pci_nic_info {
+ UINT16_t Vendor_ID; /**< PCI vendor ID */
+ UINT16_t Dev_ID; /**< PCI device ID */
+ UINT8_t Base_Class; /**< PCI base class */
+ UINT8_t Sub_Class; /**< PCI sub class */
+ UINT8_t Prog_Intf; /**< PCI programming interface */
+ UINT8_t Rev; /**< PCI revision */
+ UINT16_t BusDevFunc; /**< PCI bus:dev:fn address */
+ UINT16_t SubVendor_ID; /**< PCI subvendor ID */
+ UINT16_t SubDevice_ID; /**< PCI subdevice ID */
+} __attribute__ (( packed ));
+
+/** Information for an ISAPnP or equivalent NIC */
+struct pnp_nic_info {
+ UINT32_t EISA_Dev_ID; /**< EISA device ID */
+ UINT8_t Base_Class; /**< Base class */
+ UINT8_t Sub_Class; /**< Sub class */
+ UINT8_t Prog_Intf; /**< Programming interface */
+ /** Card Select Number assigned to card */
+ UINT16_t CardSelNum;
+} __attribute__ (( packed ));
+
+/** Parameter block for pxenv_undi_get_nic_type() */
+struct s_PXENV_UNDI_GET_NIC_TYPE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** NIC type
+ *
+ * Valid values are #PCI_NIC, #PnP_NIC or #CardBus_NIC.
+ */
+ UINT8_t NicType;
+ /** NIC information */
+ union nic_type_info {
+ /** NIC information (if #NicType==#PCI_NIC) */
+ struct pci_nic_info pci;
+ /** NIC information (if #NicType==#CardBus_NIC) */
+ struct pci_nic_info cardbus;
+ /** NIC information (if #NicType==#PnP_NIC) */
+ struct pnp_nic_info pnp;
+ } info;
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_GET_NIC_TYPE PXENV_UNDI_GET_NIC_TYPE_t;
+
+/** @} */ /* pxenv_undi_get_nic_type */
+
+/** @defgroup pxenv_undi_get_iface_info PXENV_UNDI_GET_IFACE_INFO
+ *
+ * UNDI GET IFACE INFO
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_get_iface_info() */
+#define PXENV_UNDI_GET_IFACE_INFO 0x0013
+
+/** Broadcast supported */
+#define SUPPORTED_BROADCAST 0x0001
+/** Multicast supported */
+#define SUPPORTED_MULTICAST 0x0002
+/** Functional/group addressing supported */
+#define SUPPORTED_GROUP 0x0004
+/** Promiscuous mode supported */
+#define SUPPORTED_PROMISCUOUS 0x0008
+/** Software settable station address */
+#define SUPPORTED_SET_STATION_ADDRESS 0x0010
+/** InitiateDiagnostics supported */
+#define SUPPORTED_DIAGNOSTICS 0x0040
+/** Reset MAC supported */
+#define SUPPORTED_RESET 0x0400
+/** Open / Close Adapter supported */
+#define SUPPORTED_OPEN_CLOSE 0x0800
+/** Interrupt Request supported */
+#define SUPPORTED_IRQ 0x1000
+
+/** Parameter block for pxenv_undi_get_iface_info() */
+struct s_PXENV_UNDI_GET_IFACE_INFO {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Interface type
+ *
+ * This is defined in the NDIS 2.0 specification to be one of
+ * the strings "802.3", "802.4", "802.5", "802.6", "DIX",
+ * "DIX+802.3", "APPLETALK", "ARCNET", "FDDI", "SDLC", "BSC",
+ * "HDLC", or "ISDN".
+ *
+ * "Normal" Ethernet, for various historical reasons, is
+ * "DIX+802.3".
+ */
+ UINT8_t IfaceType[16];
+ UINT32_t LinkSpeed; /**< Link speed, in bits per second */
+ /** Service flags
+ *
+ * These are the "service flags" defined in the "MAC
+ * Service-Specific Characteristics" table in the NDIS 2.0
+ * specification. Almost all of them are irrelevant to PXE.
+ */
+ UINT32_t ServiceFlags;
+ UINT32_t Reserved[4]; /**< Must be zero */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_GET_IFACE_INFO PXENV_UNDI_GET_IFACE_INFO_t;
+
+/** @} */ /* pxenv_undi_get_iface_info */
+
+/** @defgroup pxenv_undi_get_state PXENV_UNDI_GET_STATE
+ *
+ * UNDI GET STATE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_get_state() */
+#define PXENV_UNDI_GET_STATE 0x0015
+
+/** pxenv_start_undi() has been called */
+#define PXE_UNDI_GET_STATE_STARTED 1
+/** pxenv_undi_initialize() has been called */
+#define PXE_UNDI_GET_STATE_INITIALIZED 2
+/** pxenv_undi_open() has been called */
+#define PXE_UNDI_GET_STATE_OPENED 3
+
+/** Parameter block for pxenv_undi_get_state() */
+struct s_PXENV_UNDI_GET_STATE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Current state of the UNDI driver
+ *
+ * Valid values are #PXE_UNDI_GET_STATE_STARTED,
+ * #PXE_UNDI_GET_STATE_INITIALIZED or
+ * #PXE_UNDI_GET_STATE_OPENED.
+ */
+ UINT8_t UNDIstate;
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_GET_STATE PXENV_UNDI_GET_STATE_t;
+
+/** @} */ /* pxenv_undi_get_state */
+
+/** @defgroup pxenv_undi_isr PXENV_UNDI_ISR
+ *
+ * UNDI ISR
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_isr() */
+#define PXENV_UNDI_ISR 0x0014
+
+/** Determine whether or not this is our interrupt */
+#define PXENV_UNDI_ISR_IN_START 1
+/** Start processing interrupt */
+#define PXENV_UNDI_ISR_IN_PROCESS 2
+/** Continue processing interrupt */
+#define PXENV_UNDI_ISR_IN_GET_NEXT 3
+/** This interrupt was ours */
+#define PXENV_UNDI_ISR_OUT_OURS 0
+/** This interrupt was not ours */
+#define PXENV_UNDI_ISR_OUT_NOT_OURS 1
+/** Finished processing interrupt */
+#define PXENV_UNDI_ISR_OUT_DONE 0
+/** A packet transmission has completed */
+#define PXENV_UNDI_ISR_OUT_TRANSMIT 2
+/** A packet has been received */
+#define PXENV_UNDI_ISR_OUT_RECEIVE 3
+/** We are already in the middle of processing an interrupt */
+#define PXENV_UNDI_ISR_OUT_BUSY 4
+
+/** Unicast packet (or packet captured in promiscuous mode) */
+#define P_DIRECTED 0
+/** Broadcast packet */
+#define P_BROADCAST 1
+/** Multicast packet */
+#define P_MULTICAST 2
+
+/** Parameter block for pxenv_undi_isr() */
+struct s_PXENV_UNDI_ISR {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Function flag
+ *
+ * Valid values are #PXENV_UNDI_ISR_IN_START,
+ * #PXENV_UNDI_ISR_IN_PROCESS, #PXENV_UNDI_ISR_IN_GET_NEXT,
+ * #PXENV_UNDI_ISR_OUT_OURS, #PXENV_UNDI_ISR_OUT_NOT_OURS,
+ * #PXENV_UNDI_ISR_OUT_DONE, #PXENV_UNDI_ISR_OUT_TRANSMIT,
+ * #PXENV_UNDI_ISR_OUT_RECEIVE or #PXENV_UNDI_ISR_OUT_BUSY.
+ */
+ UINT16_t FuncFlag;
+ UINT16_t BufferLength; /**< Data buffer length */
+ UINT16_t FrameLength; /**< Total frame length */
+ UINT16_t FrameHeaderLength; /**< Frame header length */
+ SEGOFF16_t Frame; /**< Data buffer address */
+ /** Protocol type
+ *
+ * Valid values are #P_IP, #P_ARP, #P_RARP or #P_OTHER.
+ */
+ UINT8_t ProtType;
+ /** Packet type
+ *
+ * Valid values are #P_DIRECTED, #P_BROADCAST or #P_MULTICAST.
+ */
+ UINT8_t PktType;
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_UNDI_ISR PXENV_UNDI_ISR_t;
+
+/** @} */ /* pxenv_undi_isr */
+
+/** @} */ /* pxe_undi_api */
+
+/** @defgroup pxe_file_api PXE FILE API
+ *
+ * POSIX-like file operations
+ *
+ * @{
+ */
+
+/** Minimum possible opcode used within PXE FILE API */
+#define PXENV_FILE_MIN 0x00e0
+
+/** Minimum possible opcode used within PXE FILE API */
+#define PXENV_FILE_MAX 0x00ef
+
+/** @defgroup pxenv_file_open PXENV_FILE_OPEN
+ *
+ * FILE OPEN
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_open() */
+#define PXENV_FILE_OPEN 0x00e0
+
+/** Parameter block for pxenv_file_open() */
+struct s_PXENV_FILE_OPEN {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t FileHandle; /**< File handle */
+ SEGOFF16_t FileName; /**< File URL */
+ UINT32_t Reserved; /**< Reserved */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_FILE_OPEN PXENV_FILE_OPEN_t;
+
+/** @} */ /* pxenv_file_open */
+
+/** @defgroup pxenv_file_close PXENV_FILE_CLOSE
+ *
+ * FILE CLOSE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_close() */
+#define PXENV_FILE_CLOSE 0x00e1
+
+/** Parameter block for pxenv_file_close() */
+struct s_PXENV_FILE_CLOSE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t FileHandle; /**< File handle */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_FILE_CLOSE PXENV_FILE_CLOSE_t;
+
+/** @} */ /* pxenv_file_close */
+
+/** @defgroup pxenv_file_select PXENV_FILE_SELECT
+ *
+ * FILE SELECT
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_select() */
+#define PXENV_FILE_SELECT 0x00e2
+
+/** File is ready for reading */
+#define RDY_READ 0x0001
+
+/** Parameter block for pxenv_file_select() */
+struct s_PXENV_FILE_SELECT {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t FileHandle; /**< File handle */
+ UINT16_t Ready; /**< Indication of readiness */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_FILE_SELECT PXENV_FILE_SELECT_t;
+
+/** @} */ /* pxenv_file_select */
+
+/** @defgroup pxenv_file_read PXENV_FILE_READ
+ *
+ * FILE READ
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_read() */
+#define PXENV_FILE_READ 0x00e3
+
+/** Parameter block for pxenv_file_read() */
+struct s_PXENV_FILE_READ {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t FileHandle; /**< File handle */
+ UINT16_t BufferSize; /**< Data buffer size */
+ SEGOFF16_t Buffer; /**< Data buffer */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_FILE_READ PXENV_FILE_READ_t;
+
+/** @} */ /* pxenv_file_read */
+
+/** @defgroup pxenv_get_file_size PXENV_GET_FILE_SIZE
+ *
+ * GET FILE SIZE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_get_file_size() */
+#define PXENV_GET_FILE_SIZE 0x00e4
+
+/** Parameter block for pxenv_get_file_size() */
+struct s_PXENV_GET_FILE_SIZE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t FileHandle; /**< File handle */
+ UINT32_t FileSize; /**< File size */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_GET_FILE_SIZE PXENV_GET_FILE_SIZE_t;
+
+/** @} */ /* pxenv_get_file_size */
+
+/** @defgroup pxenv_file_exec PXENV_FILE_EXEC
+ *
+ * FILE EXEC
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_exec() */
+#define PXENV_FILE_EXEC 0x00e5
+
+/** Parameter block for pxenv_file_exec() */
+struct s_PXENV_FILE_EXEC {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ SEGOFF16_t Command; /**< Command to execute */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_FILE_EXEC PXENV_FILE_EXEC_t;
+
+/** @} */ /* pxenv_file_exec */
+
+/** @defgroup pxenv_file_api_check PXENV_FILE_API_CHECK
+ *
+ * FILE API CHECK
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_api_check() */
+#define PXENV_FILE_API_CHECK 0x00e6
+
+/** Parameter block for pxenv_file_api_check() */
+struct s_PXENV_FILE_API_CHECK {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t Size; /**< Size of structure */
+ UINT32_t Magic; /**< Magic number */
+ UINT32_t Provider; /**< Implementation identifier */
+ UINT32_t APIMask; /**< Supported API functions */
+ UINT32_t Flags; /**< Reserved for the future */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_FILE_API_CHECK PXENV_FILE_API_CHECK_t;
+
+/** @} */ /* pxenv_file_api_check */
+
+/** @defgroup pxenv_file_exit_hook PXENV_FILE_EXIT_HOOK
+ *
+ * FILE EXIT HOOK
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_exit_hook() */
+#define PXENV_FILE_EXIT_HOOK 0x00e7
+
+/** Parameter block for pxenv_file_exit_hook() */
+struct s_PXENV_FILE_EXIT_HOOK {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ SEGOFF16_t Hook; /**< SEG16:OFF16 to jump to */
+} __attribute__ (( packed ));
+
+typedef struct s_PXENV_FILE_EXIT_HOOK PXENV_FILE_EXIT_HOOK_t;
+
+/** @} */ /* pxenv_file_exit_hook */
+
+/** @} */ /* pxe_file_api */
+
+/** @defgroup pxe_loader_api PXE Loader API
+ *
+ * The UNDI ROM loader API
+ *
+ * @{
+ */
+
+/** Parameter block for undi_loader() */
+struct s_UNDI_LOADER {
+ /** PXE status code */
+ PXENV_STATUS_t Status;
+ /** %ax register as for PXENV_START_UNDI */
+ UINT16_t AX;
+ /** %bx register as for PXENV_START_UNDI */
+ UINT16_t BX;
+ /** %dx register as for PXENV_START_UNDI */
+ UINT16_t DX;
+ /** %di register as for PXENV_START_UNDI */
+ OFF16_t DI;
+ /** %es register as for PXENV_START_UNDI */
+ SEGSEL_t ES;
+ /** UNDI data segment
+ *
+ * @note The PXE specification defines the type of this field
+ * as #UINT16_t. For x86, #SEGSEL_t and #UINT16_t are
+ * equivalent anyway; for other architectures #SEGSEL_t makes
+ * more sense.
+ */
+ SEGSEL_t UNDI_DS;
+ /** UNDI code segment
+ *
+ * @note The PXE specification defines the type of this field
+ * as #UINT16_t. For x86, #SEGSEL_t and #UINT16_t are
+ * equivalent anyway; for other architectures #SEGSEL_t makes
+ * more sense.
+ */
+ SEGSEL_t UNDI_CS;
+ /** Address of the !PXE structure (a struct s_PXE) */
+ SEGOFF16_t PXEptr;
+ /** Address of the PXENV+ structure (a struct s_PXENV) */
+ SEGOFF16_t PXENVptr;
+} __attribute__ (( packed ));
+
+typedef struct s_UNDI_LOADER UNDI_LOADER_t;
+
+/** @} */ /* pxe_loader_api */
+
+/** @} */ /* pxe */
+
+/** @page pxe_notes Etherboot PXE implementation notes
+
+@section pxe_routing IP routing
+
+Several PXE API calls (e.g. pxenv_tftp_open() and pxenv_udp_write())
+allow for the caller to specify a "relay agent IP address", often in a
+field called "gateway" or similar. The PXE specification states that
+"The IP layer should provide space for a minimum of four routing
+entries obtained from the default router and static route DHCP option
+tags in the DHCPACK message, plus any non-zero giaddr field from the
+DHCPOFFER message(s) accepted by the client".
+
+The DHCP static route option ("option static-routes" in dhcpd.conf)
+works only for classed IP routing (i.e. it provides no way to specify
+a subnet mask). Since virtually everything now uses classless IP
+routing, the DHCP static route option is almost totally useless, and
+is (according to the dhcp-options man page) not implemented by any of
+the popular DHCP clients.
+
+This leaves the caller-specified "relay agent IP address", the giaddr
+field from the DHCPOFFER message(s) and the default gateway(s)
+provided via the routers option ("option routers" in dhcpd.conf) in
+the DHCPACK message. Each of these is a default gateway address.
+It's a fair bet that the routers option should take priority over the
+giaddr field, since the routers option has to be explicitly specified
+by the DHCP server operator. Similarly, it's fair to assume that the
+caller-specified "relay agent IP address", if present, should take
+priority over any other routing table entries.
+
+@bug Etherboot currently ignores all potential sources of routing
+information other than the first router provided to it by a DHCP
+routers option.
+
+@section pxe_x86_modes x86 processor mode restrictions
+
+On the x86 platform, different PXE API calls have different
+restrictions on the processor modes (real or protected) that can be
+used. See the individual API call descriptions for the restrictions
+that apply to any particular call.
+
+@subsection pxe_x86_pmode16 Real mode, or protected-mode with 16-bit stack
+
+The PXE specification states that the API function can be called in
+protected mode only if the s_PXE::StatusCallout field is set to a
+non-zero value, and that the API function cannot be called with a
+32-bit stack segment.
+
+Etherboot does not enforce either of these restrictions; they seem (as
+with so much of the PXE specification) to be artifacts of the Intel
+implementation.
+
+*/
+
+#endif /* PXE_API_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe_call.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe_call.h
new file mode 100644
index 00000000..45af4654
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe_call.h
@@ -0,0 +1,43 @@
+#ifndef _PXE_CALL_H
+#define _PXE_CALL_H
+
+/** @file
+ *
+ * PXE API entry point
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <pxe_api.h>
+#include <realmode.h>
+#include <setjmp.h>
+
+struct net_device;
+
+/** PXE load address segment */
+#define PXE_LOAD_SEGMENT 0
+
+/** PXE load address offset */
+#define PXE_LOAD_OFFSET 0x7c00
+
+/** PXE physical load address */
+#define PXE_LOAD_PHYS ( ( PXE_LOAD_SEGMENT << 4 ) + PXE_LOAD_OFFSET )
+
+/** !PXE structure */
+extern struct s_PXE __text16 ( ppxe );
+#define ppxe __use_text16 ( ppxe )
+
+/** PXENV+ structure */
+extern struct s_PXENV __text16 ( pxenv );
+#define pxenv __use_text16 ( pxenv )
+
+/** PXENV_RESTART_TFTP jump buffer */
+extern rmjmp_buf pxe_restart_nbp;
+
+extern void pxe_activate ( struct net_device *netdev );
+extern int pxe_deactivate ( void );
+extern int pxe_start_nbp ( void );
+extern __asmcall void pxe_api_call ( struct i386_all_regs *ix86 );
+extern int pxe_api_call_weak ( struct i386_all_regs *ix86 );
+
+#endif /* _PXE_CALL_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe_types.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe_types.h
new file mode 100644
index 00000000..db821459
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxe_types.h
@@ -0,0 +1,127 @@
+#ifndef PXE_TYPES_H
+#define PXE_TYPES_H
+
+/** @file
+ *
+ * PXE data types
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <errno.h> /* PXE status codes */
+
+/** @addtogroup pxe Preboot eXecution Environment (PXE) API
+ * @{
+ */
+
+/** @defgroup pxe_types PXE data types
+ *
+ * Basic PXE data types such as #UINT16_t, #ADDR32_t, #SEGSEL_t etc.
+ *
+ * These definitions are based on Table 1-1 ("Data Type Definitions")
+ * in the Intel PXE specification version 2.1. They have been
+ * generalised to non-x86 architectures where possible.
+ *
+ * @{
+ */
+
+/** An 8-bit unsigned integer */
+typedef uint8_t UINT8_t;
+
+/** A 16-bit unsigned integer */
+typedef uint16_t UINT16_t;
+
+/** A 32-bit unsigned integer */
+typedef uint32_t UINT32_t;
+
+/** A PXE exit code.
+ *
+ * Permitted values are #PXENV_EXIT_SUCCESS and #PXENV_EXIT_FAILURE.
+ *
+ */
+typedef UINT16_t PXENV_EXIT_t;
+#define PXENV_EXIT_SUCCESS 0x0000 /**< No error occurred */
+#define PXENV_EXIT_FAILURE 0x0001 /**< An error occurred */
+
+/** A PXE status code.
+ *
+ * Status codes are defined in errno.h.
+ *
+ */
+typedef UINT16_t PXENV_STATUS_t;
+
+/** An IPv4 address.
+ *
+ * @note This data type is in network (big-endian) byte order.
+ *
+ */
+typedef UINT32_t IP4_t;
+
+/** A UDP port.
+ *
+ * @note This data type is in network (big-endian) byte order.
+ *
+ */
+typedef UINT16_t UDP_PORT_t;
+
+/** Maximum length of a MAC address */
+#define MAC_ADDR_LEN 16
+
+/** A MAC address */
+typedef UINT8_t MAC_ADDR_t[MAC_ADDR_LEN];
+
+#ifndef HAVE_ARCH_ADDR32
+/** A physical address.
+ *
+ * For x86, this is a 32-bit physical address, and is therefore
+ * limited to the low 4GB.
+ *
+ */
+typedef UINT32_t ADDR32_t;
+#endif
+
+#ifndef HAVE_ARCH_SEGSEL
+/** A segment selector.
+ *
+ * For x86, this is a real mode segment (0x0000-0xffff), or a
+ * protected-mode segment selector, such as could be loaded into a
+ * segment register.
+ *
+ */
+typedef UINT16_t SEGSEL_t;
+#endif
+
+#ifndef HAVE_ARCH_OFF16
+/** An offset within a segment identified by #SEGSEL
+ *
+ * For x86, this is a 16-bit offset.
+ *
+ */
+typedef UINT16_t OFF16_t;
+#endif
+
+/** A segment:offset address
+ *
+ * For x86, this is a 16-bit real-mode or protected-mode
+ * segment:offset address.
+ *
+ */
+typedef struct s_SEGOFF16 {
+ OFF16_t offset; /**< Offset within the segment */
+ SEGSEL_t segment; /**< Segment selector */
+} __attribute__ (( packed )) SEGOFF16_t;
+
+/** A segment descriptor */
+typedef struct s_SEGDESC {
+ SEGSEL_t segment_address; /**< Segment selector */
+ ADDR32_t Physical_address; /**< Segment base address */
+ OFF16_t Seg_size; /**< Size of the segment */
+} __attribute__ (( packed )) SEGDESC_t;
+
+/** @} */ /* pxe_types */
+
+/** @} */ /* pxe */
+
+#endif /* PXE_TYPES_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxeparent.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxeparent.h
new file mode 100644
index 00000000..b31e24a7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/pxeparent.h
@@ -0,0 +1,11 @@
+#ifndef PXEPARENT_H
+#define PXEPARENT_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <pxe_types.h>
+
+extern int pxeparent_call ( SEGOFF16_t entry, unsigned int function,
+ void *params, size_t params_len );
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/realmode.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/realmode.h
new file mode 100644
index 00000000..dafc5a32
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/realmode.h
@@ -0,0 +1,127 @@
+#ifndef REALMODE_H
+#define REALMODE_H
+
+#include <stdint.h>
+#include <registers.h>
+#include <ipxe/uaccess.h>
+
+/*
+ * Data structures and type definitions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * Declaration of variables in .data16
+ *
+ * To place a variable in the .data16 segment, declare it using the
+ * pattern:
+ *
+ * int __data16 ( foo );
+ * #define foo __use_data16 ( foo );
+ *
+ * extern uint32_t __data16 ( bar );
+ * #define bar __use_data16 ( bar );
+ *
+ * static long __data16 ( baz ) = 0xff000000UL;
+ * #define baz __use_data16 ( baz );
+ *
+ * i.e. take a normal declaration, add __data16() around the variable
+ * name, and add a line saying "#define <name> __use_data16 ( <name> )
+ *
+ * You can then access them just like any other variable, for example
+ *
+ * int x = foo + bar;
+ *
+ * This magic is achieved at a cost of only around 7 extra bytes per
+ * group of accesses to .data16 variables. When using KEEP_IT_REAL,
+ * there is no extra cost.
+ *
+ * You should place variables in .data16 when they need to be accessed
+ * by real-mode code. Real-mode assembly (e.g. as created by
+ * REAL_CODE()) can access these variables via the usual data segment.
+ * You can therefore write something like
+ *
+ * static uint16_t __data16 ( foo );
+ * #define foo __use_data16 ( foo )
+ *
+ * int bar ( void ) {
+ * __asm__ __volatile__ ( REAL_CODE ( "int $0xff\n\t"
+ * "movw %ax, foo" )
+ * : : );
+ * return foo;
+ * }
+ *
+ * Variables may also be placed in .text16 using __text16 and
+ * __use_text16. Some variables (e.g. chained interrupt vectors) fit
+ * most naturally in .text16; most should be in .data16.
+ *
+ * If you have only a pointer to a magic symbol within .data16 or
+ * .text16, rather than the symbol itself, you can attempt to extract
+ * the underlying symbol name using __from_data16() or
+ * __from_text16(). This is not for the faint-hearted; check the
+ * assembler output to make sure that it's doing the right thing.
+ */
+
+/**
+ * Copy data to base memory
+ *
+ * @v dest_seg Destination segment
+ * @v dest_off Destination offset
+ * @v src Source
+ * @v len Length
+ */
+static inline __always_inline void
+copy_to_real ( unsigned int dest_seg, unsigned int dest_off,
+ void *src, size_t n ) {
+ copy_to_user ( real_to_user ( dest_seg, dest_off ), 0, src, n );
+}
+
+/**
+ * Copy data to base memory
+ *
+ * @v dest Destination
+ * @v src_seg Source segment
+ * @v src_off Source offset
+ * @v len Length
+ */
+static inline __always_inline void
+copy_from_real ( void *dest, unsigned int src_seg,
+ unsigned int src_off, size_t n ) {
+ copy_from_user ( dest, real_to_user ( src_seg, src_off ), 0, n );
+}
+
+/**
+ * Write a single variable to base memory
+ *
+ * @v var Variable to write
+ * @v dest_seg Destination segment
+ * @v dest_off Destination offset
+ */
+#define put_real( var, dest_seg, dest_off ) \
+ copy_to_real ( (dest_seg), (dest_off), &(var), sizeof (var) )
+
+/**
+ * Read a single variable from base memory
+ *
+ * @v var Variable to read
+ * @v src_seg Source segment
+ * @v src_off Source offset
+ */
+#define get_real( var, src_seg, src_off ) \
+ copy_from_real ( &(var), (src_seg), (src_off), sizeof (var) )
+
+/*
+ * REAL_CODE ( asm_code_str )
+ *
+ * This can be used in inline assembly to create a fragment of code
+ * that will execute in real mode. For example: to write a character
+ * to the BIOS console using INT 10, you would do something like:
+ *
+ * __asm__ __volatile__ ( REAL_CODE ( "int $0x16" )
+ * : "=a" ( character ) : "a" ( 0x0000 ) );
+ *
+ */
+
+#endif /* REALMODE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/registers.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/registers.h
new file mode 100644
index 00000000..06d23652
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/registers.h
@@ -0,0 +1,198 @@
+#ifndef REGISTERS_H
+#define REGISTERS_H
+
+/** @file
+ *
+ * i386 registers.
+ *
+ * This file defines data structures that allow easy access to i386
+ * register dumps.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/**
+ * A 16-bit general register.
+ *
+ * This type encapsulates a 16-bit register such as %ax, %bx, %cx,
+ * %dx, %si, %di, %bp or %sp.
+ *
+ */
+typedef union {
+ struct {
+ union {
+ uint8_t l;
+ uint8_t byte;
+ };
+ uint8_t h;
+ } __attribute__ (( packed ));
+ uint16_t word;
+} __attribute__ (( packed )) reg16_t;
+
+/**
+ * A 32-bit general register.
+ *
+ * This type encapsulates a 32-bit register such as %eax, %ebx, %ecx,
+ * %edx, %esi, %edi, %ebp or %esp.
+ *
+ */
+typedef union {
+ struct {
+ union {
+ uint8_t l;
+ uint8_t byte;
+ };
+ uint8_t h;
+ } __attribute__ (( packed ));
+ uint16_t word;
+ uint32_t dword;
+} __attribute__ (( packed )) reg32_t;
+
+/**
+ * A 32-bit general register dump.
+ *
+ * This is the data structure that is created on the stack by the @c
+ * pushal instruction, and can be read back using the @c popal
+ * instruction.
+ *
+ */
+struct i386_regs {
+ union {
+ uint16_t di;
+ uint32_t edi;
+ };
+ union {
+ uint16_t si;
+ uint32_t esi;
+ };
+ union {
+ uint16_t bp;
+ uint32_t ebp;
+ };
+ union {
+ uint16_t sp;
+ uint32_t esp;
+ };
+ union {
+ struct {
+ uint8_t bl;
+ uint8_t bh;
+ } __attribute__ (( packed ));
+ uint16_t bx;
+ uint32_t ebx;
+ };
+ union {
+ struct {
+ uint8_t dl;
+ uint8_t dh;
+ } __attribute__ (( packed ));
+ uint16_t dx;
+ uint32_t edx;
+ };
+ union {
+ struct {
+ uint8_t cl;
+ uint8_t ch;
+ } __attribute__ (( packed ));
+ uint16_t cx;
+ uint32_t ecx;
+ };
+ union {
+ struct {
+ uint8_t al;
+ uint8_t ah;
+ } __attribute__ (( packed ));
+ uint16_t ax;
+ uint32_t eax;
+ };
+} __attribute__ (( packed ));
+
+/**
+ * A segment register dump.
+ *
+ * The i386 has no equivalent of the @c pushal or @c popal
+ * instructions for the segment registers. We adopt the convention of
+ * always using the sequences
+ *
+ * @code
+ *
+ * pushw %gs ; pushw %fs ; pushw %es ; pushw %ds ; pushw %ss ; pushw %cs
+ *
+ * @endcode
+ *
+ * and
+ *
+ * @code
+ *
+ * addw $4, %sp ; popw %ds ; popw %es ; popw %fs ; popw %gs
+ *
+ * @endcode
+ *
+ * This is the data structure that is created and read back by these
+ * instruction sequences.
+ *
+ */
+struct i386_seg_regs {
+ uint16_t cs;
+ uint16_t ss;
+ uint16_t ds;
+ uint16_t es;
+ uint16_t fs;
+ uint16_t gs;
+} __attribute__ (( packed ));
+
+/**
+ * A full register dump.
+ *
+ * This data structure is created by the instructions
+ *
+ * @code
+ *
+ * pushfl
+ * pushal
+ * pushw %gs ; pushw %fs ; pushw %es ; pushw %ds ; pushw %ss ; pushw %cs
+ *
+ * @endcode
+ *
+ * and can be read back using the instructions
+ *
+ * @code
+ *
+ * addw $4, %sp ; popw %ds ; popw %es ; popw %fs ; popw %gs
+ * popal
+ * popfl
+ *
+ * @endcode
+ *
+ * prot_call() and kir_call() create this data structure on the stack
+ * and pass in a pointer to this structure.
+ *
+ */
+struct i386_all_regs {
+ struct i386_seg_regs segs;
+ struct i386_regs regs;
+ uint32_t flags;
+} __attribute__ (( packed ));
+
+/* Flags */
+#define CF ( 1 << 0 )
+#define PF ( 1 << 2 )
+#define AF ( 1 << 4 )
+#define ZF ( 1 << 6 )
+#define SF ( 1 << 7 )
+#define OF ( 1 << 11 )
+
+/* Segment:offset structure. Note that the order within the structure
+ * is offset:segment.
+ */
+struct segoff {
+ uint16_t offset;
+ uint16_t segment;
+} __attribute__ (( packed ));
+
+typedef struct segoff segoff_t;
+
+#endif /* REGISTERS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/rtc.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/rtc.h
new file mode 100644
index 00000000..2a6abbae
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/rtc.h
@@ -0,0 +1,83 @@
+#ifndef _RTC_H
+#define _RTC_H
+
+/** @file
+ *
+ * CMOS Real-Time Clock (RTC)
+ *
+ * The CMOS/RTC registers are documented (with varying degrees of
+ * accuracy and consistency) at
+ *
+ * http://www.nondot.org/sabre/os/files/MiscHW/RealtimeClockFAQ.txt
+ * http://wiki.osdev.org/RTC
+ * http://wiki.osdev.org/CMOS
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <pic8259.h>
+
+/** RTC IRQ */
+#define RTC_IRQ 8
+
+/** RTC interrupt vector */
+#define RTC_INT IRQ_INT ( RTC_IRQ )
+
+/** CMOS/RTC address (and NMI) register */
+#define CMOS_ADDRESS 0x70
+
+/** NMI disable bit */
+#define CMOS_DISABLE_NMI 0x80
+
+/** CMOS/RTC data register */
+#define CMOS_DATA 0x71
+
+/** RTC seconds */
+#define RTC_SEC 0x00
+
+/** RTC minutes */
+#define RTC_MIN 0x02
+
+/** RTC hours */
+#define RTC_HOUR 0x04
+
+/** RTC weekday */
+#define RTC_WDAY 0x06
+
+/** RTC day of month */
+#define RTC_MDAY 0x07
+
+/** RTC month */
+#define RTC_MON 0x08
+
+/** RTC year */
+#define RTC_YEAR 0x09
+
+/** RTC status register A */
+#define RTC_STATUS_A 0x0a
+
+/** RTC update in progress bit */
+#define RTC_STATUS_A_UPDATE_IN_PROGRESS 0x80
+
+/** RTC status register B */
+#define RTC_STATUS_B 0x0b
+
+/** RTC 24 hour format bit */
+#define RTC_STATUS_B_24_HOUR 0x02
+
+/** RTC binary mode bit */
+#define RTC_STATUS_B_BINARY 0x04
+
+/** RTC Periodic Interrupt Enabled bit */
+#define RTC_STATUS_B_PIE 0x40
+
+/** RTC status register C */
+#define RTC_STATUS_C 0x0c
+
+/** RTC status register D */
+#define RTC_STATUS_D 0x0d
+
+/** CMOS default address */
+#define CMOS_DEFAULT_ADDRESS RTC_STATUS_D
+
+#endif /* _RTC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/setjmp.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/setjmp.h
new file mode 100644
index 00000000..5d3c11b6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/setjmp.h
@@ -0,0 +1,40 @@
+#ifndef ETHERBOOT_SETJMP_H
+#define ETHERBOOT_SETJMP_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <realmode.h>
+
+/** A jump buffer */
+typedef struct {
+ uint32_t retaddr;
+ uint32_t ebx;
+ uint32_t esp;
+ uint32_t ebp;
+ uint32_t esi;
+ uint32_t edi;
+} jmp_buf[1];
+
+/** A real-mode-extended jump buffer */
+typedef struct {
+ jmp_buf env;
+ uint16_t rm_ss;
+ uint16_t rm_sp;
+} rmjmp_buf[1];
+
+extern int __asmcall setjmp ( jmp_buf env );
+extern void __asmcall longjmp ( jmp_buf env, int val );
+
+#define rmsetjmp( _env ) ( { \
+ (_env)->rm_ss = rm_ss; \
+ (_env)->rm_sp = rm_sp; \
+ setjmp ( (_env)->env ); } ) \
+
+#define rmlongjmp( _env, _val ) do { \
+ rm_ss = (_env)->rm_ss; \
+ rm_sp = (_env)->rm_sp; \
+ longjmp ( (_env)->env, (_val) ); \
+ } while ( 0 )
+
+#endif /* ETHERBOOT_SETJMP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undi.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undi.h
new file mode 100644
index 00000000..325fcbbf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undi.h
@@ -0,0 +1,106 @@
+#ifndef _UNDI_H
+#define _UNDI_H
+
+/** @file
+ *
+ * UNDI driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef ASSEMBLY
+
+#include <ipxe/device.h>
+#include <pxe_types.h>
+
+/** An UNDI device
+ *
+ * This structure is used by assembly code as well as C; do not alter
+ * this structure without editing pxeprefix.S to match.
+ */
+struct undi_device {
+ /** PXENV+ structure address */
+ SEGOFF16_t pxenv;
+ /** !PXE structure address */
+ SEGOFF16_t ppxe;
+ /** Entry point */
+ SEGOFF16_t entry;
+ /** Free base memory after load */
+ UINT16_t fbms;
+ /** Free base memory prior to load */
+ UINT16_t restore_fbms;
+ /** PCI bus:dev.fn, or @c UNDI_NO_PCI_BUSDEVFN */
+ UINT16_t pci_busdevfn;
+ /** ISAPnP card select number, or @c UNDI_NO_ISAPNP_CSN */
+ UINT16_t isapnp_csn;
+ /** ISAPnP read port, or @c UNDI_NO_ISAPNP_READ_PORT */
+ UINT16_t isapnp_read_port;
+ /** PCI vendor ID
+ *
+ * Filled in only for the preloaded UNDI device by pxeprefix.S
+ */
+ UINT16_t pci_vendor;
+ /** PCI device ID
+ *
+ * Filled in only for the preloaded UNDI device by pxeprefix.S
+ */
+ UINT16_t pci_device;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more UNDI_FL_XXX
+ * constants.
+ */
+ UINT16_t flags;
+
+ /** Generic device */
+ struct device dev;
+ /** Driver-private data
+ *
+ * Use undi_set_drvdata() and undi_get_drvdata() to access this
+ * field.
+ */
+ void *priv;
+} __attribute__ (( packed ));
+
+/**
+ * Set UNDI driver-private data
+ *
+ * @v undi UNDI device
+ * @v priv Private data
+ */
+static inline void undi_set_drvdata ( struct undi_device *undi, void *priv ) {
+ undi->priv = priv;
+}
+
+/**
+ * Get UNDI driver-private data
+ *
+ * @v undi UNDI device
+ * @ret priv Private data
+ */
+static inline void * undi_get_drvdata ( struct undi_device *undi ) {
+ return undi->priv;
+}
+
+#endif /* ASSEMBLY */
+
+/** PCI bus:dev.fn field is invalid */
+#define UNDI_NO_PCI_BUSDEVFN 0xffff
+
+/** ISAPnP card select number field is invalid */
+#define UNDI_NO_ISAPNP_CSN 0xffff
+
+/** ISAPnP read port field is invalid */
+#define UNDI_NO_ISAPNP_READ_PORT 0xffff
+
+/** UNDI flag: START_UNDI has been called */
+#define UNDI_FL_STARTED 0x0001
+
+/** UNDI flag: UNDI_STARTUP and UNDI_INITIALIZE have been called */
+#define UNDI_FL_INITIALIZED 0x0002
+
+/** UNDI flag: keep stack resident */
+#define UNDI_FL_KEEP_ALL 0x0004
+
+#endif /* _UNDI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undiload.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undiload.h
new file mode 100644
index 00000000..426830e8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undiload.h
@@ -0,0 +1,35 @@
+#ifndef _UNDILOAD_H
+#define _UNDILOAD_H
+
+/** @file
+ *
+ * UNDI load/unload
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct undi_device;
+struct undi_rom;
+
+extern int undi_load ( struct undi_device *undi, struct undi_rom *undirom );
+extern int undi_unload ( struct undi_device *undi );
+
+/**
+ * Call UNDI loader to create a pixie
+ *
+ * @v undi UNDI device
+ * @v undirom UNDI ROM
+ * @v pci_busdevfn PCI bus:dev.fn
+ * @ret rc Return status code
+ */
+static inline int undi_load_pci ( struct undi_device *undi,
+ struct undi_rom *undirom,
+ unsigned int pci_busdevfn ) {
+ undi->pci_busdevfn = pci_busdevfn;
+ undi->isapnp_csn = UNDI_NO_ISAPNP_CSN;
+ undi->isapnp_read_port = UNDI_NO_ISAPNP_READ_PORT;
+ return undi_load ( undi, undirom );
+}
+
+#endif /* _UNDILOAD_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undinet.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undinet.h
new file mode 100644
index 00000000..c3c17c11
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undinet.h
@@ -0,0 +1,17 @@
+#ifndef _UNDINET_H
+#define _UNDINET_H
+
+/** @file
+ *
+ * UNDI network device driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct undi_device;
+
+extern int undinet_probe ( struct undi_device *undi );
+extern void undinet_remove ( struct undi_device *undi );
+
+#endif /* _UNDINET_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undipreload.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undipreload.h
new file mode 100644
index 00000000..de9b8fb5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undipreload.h
@@ -0,0 +1,18 @@
+#ifndef _UNDIPRELOAD_H
+#define _UNDIPRELOAD_H
+
+/** @file
+ *
+ * Preloaded UNDI stack
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <realmode.h>
+#include <undi.h>
+
+extern struct undi_device __data16 ( preloaded_undi );
+#define preloaded_undi __use_data16 ( preloaded_undi )
+
+#endif /* _UNDIPRELOAD_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undirom.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undirom.h
new file mode 100644
index 00000000..86d7077b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/undirom.h
@@ -0,0 +1,53 @@
+#ifndef _UNDIROM_H
+#define _UNDIROM_H
+
+/** @file
+ *
+ * UNDI expansion ROMs
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <pxe_types.h>
+
+/** An UNDI PCI device ID */
+struct undi_pci_device_id {
+ /** PCI vendor ID */
+ unsigned int vendor_id;
+ /** PCI device ID */
+ unsigned int device_id;
+};
+
+/** An UNDI device ID */
+union undi_device_id {
+ /** PCI device ID */
+ struct undi_pci_device_id pci;
+};
+
+/** An UNDI ROM */
+struct undi_rom {
+ /** List of UNDI ROMs */
+ struct list_head list;
+ /** ROM segment address */
+ unsigned int rom_segment;
+ /** UNDI loader entry point */
+ SEGOFF16_t loader_entry;
+ /** Code segment size */
+ size_t code_size;
+ /** Data segment size */
+ size_t data_size;
+ /** Bus type
+ *
+ * Values are as used by @c PXENV_UNDI_GET_NIC_TYPE
+ */
+ unsigned int bus_type;
+ /** Device ID */
+ union undi_device_id bus_id;
+};
+
+extern struct undi_rom * undirom_find_pci ( unsigned int vendor_id,
+ unsigned int device_id,
+ unsigned int rombase );
+
+#endif /* _UNDIROM_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/include/vga.h b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/vga.h
new file mode 100644
index 00000000..01fc39d8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/include/vga.h
@@ -0,0 +1,228 @@
+/*
+ *
+ * modified
+ * by Steve M. Gehlbach <steve@kesa.com>
+ *
+ * Originally from linux/drivers/video/vga16.c by
+ * Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
+ * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ */
+
+#ifndef VGA_H_INCL
+#define VGA_H_INCL 1
+
+//#include <cpu/p5/io.h>
+
+#define u8 unsigned char
+#define u16 unsigned short
+#define u32 unsigned int
+#define __u32 u32
+
+#define VERROR -1
+#define CHAR_HEIGHT 16
+#define LINES 25
+#define COLS 80
+
+// macros for writing to vga regs
+#define write_crtc(data,addr) outb(addr,CRT_IC); outb(data,CRT_DC)
+#define write_att(data,addr) inb(IS1_RC); inb(0x80); outb(addr,ATT_IW); inb(0x80); outb(data,ATT_IW); inb(0x80)
+#define write_seq(data,addr) outb(addr,SEQ_I); outb(data,SEQ_D)
+#define write_gra(data,addr) outb(addr,GRA_I); outb(data,GRA_D)
+u8 read_seq_b(u16 addr);
+u8 read_gra_b(u16 addr);
+u8 read_crtc_b(u16 addr);
+u8 read_att_b(u16 addr);
+
+
+#ifdef VGA_HARDWARE_FIXUP
+void vga_hardware_fixup(void);
+#else
+#define vga_hardware_fixup() do{} while(0)
+#endif
+
+#define SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */
+#define SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
+#define SYNC_EXT 4 /* external sync */
+#define SYNC_COMP_HIGH_ACT 8 /* composite sync high active */
+#define SYNC_BROADCAST 16 /* broadcast video timings */
+ /* vtotal = 144d/288n/576i => PAL */
+ /* vtotal = 121d/242n/484i => NTSC */
+
+#define SYNC_ON_GREEN 32 /* sync on green */
+
+#define VMODE_NONINTERLACED 0 /* non interlaced */
+#define VMODE_INTERLACED 1 /* interlaced */
+#define VMODE_DOUBLE 2 /* double scan */
+#define VMODE_MASK 255
+
+#define VMODE_YWRAP 256 /* ywrap instead of panning */
+#define VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */
+#define VMODE_CONUPDATE 512 /* don't update x/yoffset */
+
+/* VGA data register ports */
+#define CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */
+#define CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */
+#define ATT_R 0x3C1 /* Attribute Controller Data Read Register */
+#define GRA_D 0x3CF /* Graphics Controller Data Register */
+#define SEQ_D 0x3C5 /* Sequencer Data Register */
+
+#define MIS_R 0x3CC // Misc Output Read Register
+#define MIS_W 0x3C2 // Misc Output Write Register
+
+#define IS1_RC 0x3DA /* Input Status Register 1 - color emulation */
+#define IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */
+#define PEL_D 0x3C9 /* PEL Data Register */
+#define PEL_MSK 0x3C6 /* PEL mask register */
+
+/* EGA-specific registers */
+#define GRA_E0 0x3CC /* Graphics enable processor 0 */
+#define GRA_E1 0x3CA /* Graphics enable processor 1 */
+
+
+/* VGA index register ports */
+#define CRT_IC 0x3D4 /* CRT Controller Index - color emulation */
+#define CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */
+#define ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */
+#define GRA_I 0x3CE /* Graphics Controller Index */
+#define SEQ_I 0x3C4 /* Sequencer Index */
+#define PEL_IW 0x3C8 /* PEL Write Index */
+#define PEL_IR 0x3C7 /* PEL Read Index */
+
+/* standard VGA indexes max counts */
+#define CRTC_C 25 /* 25 CRT Controller Registers sequentially set*/
+ // the remainder are not in the par array
+#define ATT_C 21 /* 21 Attribute Controller Registers */
+#define GRA_C 9 /* 9 Graphics Controller Registers */
+#define SEQ_C 5 /* 5 Sequencer Registers */
+#define MIS_C 1 /* 1 Misc Output Register */
+
+#define CRTC_H_TOTAL 0
+#define CRTC_H_DISP 1
+#define CRTC_H_BLANK_START 2
+#define CRTC_H_BLANK_END 3
+#define CRTC_H_SYNC_START 4
+#define CRTC_H_SYNC_END 5
+#define CRTC_V_TOTAL 6
+#define CRTC_OVERFLOW 7
+#define CRTC_PRESET_ROW 8
+#define CRTC_MAX_SCAN 9
+#define CRTC_CURSOR_START 0x0A
+#define CRTC_CURSOR_END 0x0B
+#define CRTC_START_HI 0x0C
+#define CRTC_START_LO 0x0D
+#define CRTC_CURSOR_HI 0x0E
+#define CRTC_CURSOR_LO 0x0F
+#define CRTC_V_SYNC_START 0x10
+#define CRTC_V_SYNC_END 0x11
+#define CRTC_V_DISP_END 0x12
+#define CRTC_OFFSET 0x13
+#define CRTC_UNDERLINE 0x14
+#define CRTC_V_BLANK_START 0x15
+#define CRTC_V_BLANK_END 0x16
+#define CRTC_MODE 0x17
+#define CRTC_LINE_COMPARE 0x18
+
+#define ATC_MODE 0x10
+#define ATC_OVERSCAN 0x11
+#define ATC_PLANE_ENABLE 0x12
+#define ATC_PEL 0x13
+#define ATC_COLOR_PAGE 0x14
+
+#define SEQ_CLOCK_MODE 0x01
+#define SEQ_PLANE_WRITE 0x02
+#define SEQ_CHARACTER_MAP 0x03
+#define SEQ_MEMORY_MODE 0x04
+
+#define GDC_SR_VALUE 0x00
+#define GDC_SR_ENABLE 0x01
+#define GDC_COMPARE_VALUE 0x02
+#define GDC_DATA_ROTATE 0x03
+#define GDC_PLANE_READ 0x04
+#define GDC_MODE 0x05
+#define GDC_MISC 0x06
+#define GDC_COMPARE_MASK 0x07
+#define GDC_BIT_MASK 0x08
+
+// text attributes
+#define VGA_ATTR_CLR_RED 0x4
+#define VGA_ATTR_CLR_GRN 0x2
+#define VGA_ATTR_CLR_BLU 0x1
+#define VGA_ATTR_CLR_YEL (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN)
+#define VGA_ATTR_CLR_CYN (VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU)
+#define VGA_ATTR_CLR_MAG (VGA_ATTR_CLR_BLU | VGA_ATTR_CLR_RED)
+#define VGA_ATTR_CLR_BLK 0
+#define VGA_ATTR_CLR_WHT (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU)
+#define VGA_ATTR_BNK 0x80
+#define VGA_ATTR_ITN 0x08
+
+/*
+ * vga register parameters
+ * these are copied to the
+ * registers.
+ *
+ */
+struct vga_par {
+ u8 crtc[CRTC_C];
+ u8 atc[ATT_C];
+ u8 gdc[GRA_C];
+ u8 seq[SEQ_C];
+ u8 misc; // the misc register, MIS_W
+ u8 vss;
+};
+
+
+/* Interpretation of offset for color fields: All offsets are from the right,
+ * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
+ * can use the offset as right argument to <<). A pixel afterwards is a bit
+ * stream and is written to video memory as that unmodified. This implies
+ * big-endian byte order if bits_per_pixel is greater than 8.
+ */
+struct fb_bitfield {
+ __u32 offset; /* beginning of bitfield */
+ __u32 length; /* length of bitfield */
+ __u32 msb_right; /* != 0 : Most significant bit is */
+ /* right */
+};
+
+struct screeninfo {
+ __u32 xres; /* visible resolution */
+ __u32 yres;
+ __u32 xres_virtual; /* virtual resolution */
+ __u32 yres_virtual;
+ __u32 xoffset; /* offset from virtual to visible */
+ __u32 yoffset; /* resolution */
+
+ __u32 bits_per_pixel; /* guess what */
+ __u32 grayscale; /* != 0 Graylevels instead of colors */
+
+ struct fb_bitfield red; /* bitfield in fb mem if true color, */
+ struct fb_bitfield green; /* else only length is significant */
+ struct fb_bitfield blue;
+ struct fb_bitfield transp; /* transparency */
+
+ __u32 nonstd; /* != 0 Non standard pixel format */
+
+ __u32 activate; /* see FB_ACTIVATE_* */
+
+ __u32 height; /* height of picture in mm */
+ __u32 width; /* width of picture in mm */
+
+ __u32 accel_flags; /* acceleration flags (hints) */
+
+ /* Timing: All values in pixclocks, except pixclock (of course) */
+ __u32 pixclock; /* pixel clock in ps (pico seconds) */
+ __u32 left_margin; /* time from sync to picture */
+ __u32 right_margin; /* time from picture to sync */
+ __u32 upper_margin; /* time from sync to picture */
+ __u32 lower_margin;
+ __u32 hsync_len; /* length of horizontal sync */
+ __u32 vsync_len; /* length of vertical sync */
+ __u32 sync; /* sync polarity */
+ __u32 vmode; /* interlaced etc */
+ __u32 reserved[6]; /* Reserved for future compatibility */
+};
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/bios_nap.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/bios_nap.c
new file mode 100644
index 00000000..7f461466
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/bios_nap.c
@@ -0,0 +1,16 @@
+#include <ipxe/nap.h>
+#include <realmode.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Save power by halting the CPU until the next interrupt
+ *
+ */
+static void bios_cpu_nap ( void ) {
+ __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
+ "hlt\n\t"
+ "cli\n\t" ) : : );
+}
+
+PROVIDE_NAP ( pcbios, cpu_nap, bios_cpu_nap );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c
new file mode 100644
index 00000000..cde3d060
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/smbios.h>
+#include <realmode.h>
+#include <pnpbios.h>
+
+/** @file
+ *
+ * System Management BIOS
+ *
+ */
+
+/**
+ * Find SMBIOS
+ *
+ * @v smbios SMBIOS entry point descriptor structure to fill in
+ * @ret rc Return status code
+ */
+static int bios_find_smbios ( struct smbios *smbios ) {
+ union {
+ struct smbios_entry entry;
+ uint8_t bytes[256]; /* 256 is maximum length possible */
+ } u;
+ static unsigned int offset = 0;
+ size_t len;
+ unsigned int i;
+ uint8_t sum;
+
+ /* Try to find SMBIOS */
+ for ( ; offset < 0x10000 ; offset += 0x10 ) {
+
+ /* Read start of header and verify signature */
+ copy_from_real ( &u.entry, BIOS_SEG, offset,
+ sizeof ( u.entry ));
+ if ( u.entry.signature != SMBIOS_SIGNATURE )
+ continue;
+
+ /* Read whole header and verify checksum */
+ len = u.entry.len;
+ copy_from_real ( &u.bytes, BIOS_SEG, offset, len );
+ for ( i = 0 , sum = 0 ; i < len ; i++ ) {
+ sum += u.bytes[i];
+ }
+ if ( sum != 0 ) {
+ DBG ( "SMBIOS at %04x:%04x has bad checksum %02x\n",
+ BIOS_SEG, offset, sum );
+ continue;
+ }
+
+ /* Fill result structure */
+ DBG ( "Found SMBIOS v%d.%d entry point at %04x:%04x\n",
+ u.entry.major, u.entry.minor, BIOS_SEG, offset );
+ smbios->address = phys_to_user ( u.entry.smbios_address );
+ smbios->len = u.entry.smbios_len;
+ smbios->count = u.entry.smbios_count;
+ return 0;
+ }
+
+ DBG ( "No SMBIOS found\n" );
+ return -ENODEV;
+}
+
+PROVIDE_SMBIOS ( pcbios, find_smbios, bios_find_smbios );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/bios_timer.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/bios_timer.c
new file mode 100644
index 00000000..70c3986b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/bios_timer.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * BIOS timer
+ *
+ */
+
+#include <ipxe/timer.h>
+#include <realmode.h>
+#include <bios.h>
+
+/**
+ * Get current system time in ticks
+ *
+ * @ret ticks Current time, in ticks
+ *
+ * Use direct memory access to BIOS variables, longword 0040:006C
+ * (ticks today) and byte 0040:0070 (midnight crossover flag) instead
+ * of calling timeofday BIOS interrupt.
+ */
+static unsigned long bios_currticks ( void ) {
+ static int days = 0;
+ uint32_t ticks;
+ uint8_t midnight;
+
+ /* Re-enable interrupts so that the timer interrupt can occur */
+ __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "cli\n\t" ) : : );
+
+ get_real ( ticks, BDA_SEG, 0x006c );
+ get_real ( midnight, BDA_SEG, 0x0070 );
+
+ if ( midnight ) {
+ midnight = 0;
+ put_real ( midnight, BDA_SEG, 0x0070 );
+ days += 0x1800b0;
+ }
+
+ return ( days + ticks );
+}
+
+PROVIDE_TIMER_INLINE ( pcbios, udelay );
+PROVIDE_TIMER ( pcbios, currticks, bios_currticks );
+PROVIDE_TIMER_INLINE ( pcbios, ticks_per_sec );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/biosint.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/biosint.c
new file mode 100644
index 00000000..a193defa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/biosint.c
@@ -0,0 +1,92 @@
+#include <errno.h>
+#include <realmode.h>
+#include <biosint.h>
+
+/**
+ * @file BIOS interrupts
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Hook INT vector
+ *
+ * @v interrupt INT number
+ * @v handler Offset within .text16 to interrupt handler
+ * @v chain_vector Vector for chaining to previous handler
+ *
+ * Hooks in an i386 INT handler. The handler itself must reside
+ * within the .text16 segment. @c chain_vector will be filled in with
+ * the address of the previously-installed handler for this interrupt;
+ * the handler should probably exit by ljmping via this vector.
+ */
+void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
+ struct segoff *chain_vector ) {
+ struct segoff vector = {
+ .segment = rm_cs,
+ .offset = handler,
+ };
+
+ DBG ( "Hooking INT %#02x to %04x:%04x\n",
+ interrupt, rm_cs, handler );
+
+ if ( ( chain_vector->segment != 0 ) ||
+ ( chain_vector->offset != 0 ) ) {
+ /* Already hooked; do nothing */
+ DBG ( "...already hooked\n" );
+ return;
+ }
+
+ copy_from_real ( chain_vector, 0, ( interrupt * 4 ),
+ sizeof ( *chain_vector ) );
+ DBG ( "...chaining to %04x:%04x\n",
+ chain_vector->segment, chain_vector->offset );
+ if ( DBG_LOG ) {
+ char code[64];
+ copy_from_real ( code, chain_vector->segment,
+ chain_vector->offset, sizeof ( code ) );
+ DBG_HDA ( *chain_vector, code, sizeof ( code ) );
+ }
+
+ copy_to_real ( 0, ( interrupt * 4 ), &vector, sizeof ( vector ) );
+ hooked_bios_interrupts++;
+}
+
+/**
+ * Unhook INT vector
+ *
+ * @v interrupt INT number
+ * @v handler Offset within .text16 to interrupt handler
+ * @v chain_vector Vector containing address of previous handler
+ *
+ * Unhooks an i386 interrupt handler hooked by hook_i386_vector().
+ * Note that this operation may fail, if some external code has hooked
+ * the vector since we hooked in our handler. If it fails, it means
+ * that it is not possible to unhook our handler, and we must leave it
+ * (and its chaining vector) resident in memory.
+ */
+int unhook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
+ struct segoff *chain_vector ) {
+ struct segoff vector;
+
+ DBG ( "Unhooking INT %#02x from %04x:%04x\n",
+ interrupt, rm_cs, handler );
+
+ copy_from_real ( &vector, 0, ( interrupt * 4 ), sizeof ( vector ) );
+ if ( ( vector.segment != rm_cs ) || ( vector.offset != handler ) ) {
+ DBG ( "...cannot unhook; vector points to %04x:%04x\n",
+ vector.segment, vector.offset );
+ return -EBUSY;
+ }
+
+ DBG ( "...restoring to %04x:%04x\n",
+ chain_vector->segment, chain_vector->offset );
+ copy_to_real ( 0, ( interrupt * 4 ), chain_vector,
+ sizeof ( *chain_vector ) );
+
+ chain_vector->segment = 0;
+ chain_vector->offset = 0;
+ hooked_bios_interrupts--;
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/int13.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/int13.c
new file mode 100644
index 00000000..0a1e7748
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/int13.c
@@ -0,0 +1,1986 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/list.h>
+#include <ipxe/blockdev.h>
+#include <ipxe/io.h>
+#include <ipxe/open.h>
+#include <ipxe/uri.h>
+#include <ipxe/process.h>
+#include <ipxe/xfer.h>
+#include <ipxe/retry.h>
+#include <ipxe/timer.h>
+#include <ipxe/acpi.h>
+#include <ipxe/sanboot.h>
+#include <ipxe/device.h>
+#include <ipxe/pci.h>
+#include <realmode.h>
+#include <bios.h>
+#include <biosint.h>
+#include <bootsector.h>
+#include <int13.h>
+
+/** @file
+ *
+ * INT 13 emulation
+ *
+ * This module provides a mechanism for exporting block devices via
+ * the BIOS INT 13 disk interrupt interface.
+ *
+ */
+
+/**
+ * Overall timeout for INT 13 commands (independent of underlying device
+ *
+ * Underlying devices should ideally never become totally stuck.
+ * However, if they do, then the INT 13 mechanism provides no means
+ * for the caller to cancel the operation, and the machine appears to
+ * hang. Use an overall timeout for all commands to avoid this
+ * problem and bounce timeout failures to the caller.
+ */
+#define INT13_COMMAND_TIMEOUT ( 15 * TICKS_PER_SEC )
+
+/** An INT 13 emulated drive */
+struct int13_drive {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** List of all registered drives */
+ struct list_head list;
+
+ /** Block device URI */
+ struct uri *uri;
+ /** Underlying block device interface */
+ struct interface block;
+
+ /** BIOS in-use drive number (0x00-0xff) */
+ unsigned int drive;
+ /** BIOS natural drive number (0x00-0xff)
+ *
+ * This is the drive number that would have been assigned by
+ * 'naturally' appending the drive to the end of the BIOS
+ * drive list.
+ *
+ * If the emulated drive replaces a preexisting drive, this is
+ * the drive number that the preexisting drive gets remapped
+ * to.
+ */
+ unsigned int natural_drive;
+
+ /** Block device capacity */
+ struct block_device_capacity capacity;
+ /** INT 13 emulated blocksize shift
+ *
+ * To allow for emulation of CD-ROM access, this represents
+ * the left-shift required to translate from INT 13 blocks to
+ * underlying blocks.
+ */
+ unsigned int blksize_shift;
+
+ /** Number of cylinders
+ *
+ * The cylinder number field in an INT 13 call is ten bits
+ * wide, giving a maximum of 1024 cylinders. Conventionally,
+ * when the 7.8GB limit of a CHS address is exceeded, it is
+ * the number of cylinders that is increased beyond the
+ * addressable limit.
+ */
+ unsigned int cylinders;
+ /** Number of heads
+ *
+ * The head number field in an INT 13 call is eight bits wide,
+ * giving a maximum of 256 heads. However, apparently all
+ * versions of MS-DOS up to and including Win95 fail with 256
+ * heads, so the maximum encountered in practice is 255.
+ */
+ unsigned int heads;
+ /** Number of sectors per track
+ *
+ * The sector number field in an INT 13 call is six bits wide,
+ * giving a maximum of 63 sectors, since sector numbering
+ * (unlike head and cylinder numbering) starts at 1, not 0.
+ */
+ unsigned int sectors_per_track;
+
+ /** Drive is a CD-ROM */
+ int is_cdrom;
+ /** Address of El Torito boot catalog (if any) */
+ unsigned int boot_catalog;
+
+ /** Underlying device status, if in error */
+ int block_rc;
+ /** Status of last operation */
+ int last_status;
+};
+
+/** Vector for chaining to other INT 13 handlers */
+static struct segoff __text16 ( int13_vector );
+#define int13_vector __use_text16 ( int13_vector )
+
+/** Assembly wrapper */
+extern void int13_wrapper ( void );
+
+/** Dummy floppy disk parameter table */
+static struct int13_fdd_parameters __data16 ( int13_fdd_params ) = {
+ /* 512 bytes per sector */
+ .bytes_per_sector = 0x02,
+ /* Highest sectors per track that we ever return */
+ .sectors_per_track = 48,
+};
+#define int13_fdd_params __use_data16 ( int13_fdd_params )
+
+/** List of registered emulated drives */
+static LIST_HEAD ( int13s );
+
+/**
+ * Equipment word
+ *
+ * This is a cached copy of the BIOS Data Area equipment word at
+ * 40:10.
+ */
+static uint16_t equipment_word;
+
+/**
+ * Number of BIOS floppy disk drives
+ *
+ * This is derived from the equipment word. It is held in .text16 to
+ * allow for easy access by the INT 13,08 wrapper.
+ */
+static uint8_t __text16 ( num_fdds );
+#define num_fdds __use_text16 ( num_fdds )
+
+/**
+ * Number of BIOS hard disk drives
+ *
+ * This is a cached copy of the BIOS Data Area number of hard disk
+ * drives at 40:75. It is held in .text16 to allow for easy access by
+ * the INT 13,08 wrapper.
+ */
+static uint8_t __text16 ( num_drives );
+#define num_drives __use_text16 ( num_drives )
+
+/**
+ * Calculate INT 13 drive sector size
+ *
+ * @v int13 Emulated drive
+ * @ret blksize Sector size
+ */
+static inline size_t int13_blksize ( struct int13_drive *int13 ) {
+ return ( int13->capacity.blksize << int13->blksize_shift );
+}
+
+/**
+ * Calculate INT 13 drive capacity
+ *
+ * @v int13 Emulated drive
+ * @ret blocks Number of blocks
+ */
+static inline uint64_t int13_capacity ( struct int13_drive *int13 ) {
+ return ( int13->capacity.blocks >> int13->blksize_shift );
+}
+
+/**
+ * Calculate INT 13 drive capacity (limited to 32 bits)
+ *
+ * @v int13 Emulated drive
+ * @ret blocks Number of blocks
+ */
+static inline uint32_t int13_capacity32 ( struct int13_drive *int13 ) {
+ uint64_t capacity = int13_capacity ( int13 );
+ return ( ( capacity <= 0xffffffffUL ) ? capacity : 0xffffffff );
+}
+
+/**
+ * Test if INT 13 drive is a floppy disk drive
+ *
+ * @v int13 Emulated drive
+ * @ret is_fdd Emulated drive is a floppy disk
+ */
+static inline int int13_is_fdd ( struct int13_drive *int13 ) {
+ return ( ! ( int13->drive & 0x80 ) );
+}
+
+/** An INT 13 command */
+struct int13_command {
+ /** Status */
+ int rc;
+ /** INT 13 drive */
+ struct int13_drive *int13;
+ /** Underlying block device interface */
+ struct interface block;
+ /** Command timeout timer */
+ struct retry_timer timer;
+};
+
+/**
+ * Record INT 13 drive capacity
+ *
+ * @v command INT 13 command
+ * @v capacity Block device capacity
+ */
+static void int13_command_capacity ( struct int13_command *command,
+ struct block_device_capacity *capacity ) {
+ memcpy ( &command->int13->capacity, capacity,
+ sizeof ( command->int13->capacity ) );
+}
+
+/**
+ * Close INT 13 command
+ *
+ * @v command INT 13 command
+ * @v rc Reason for close
+ */
+static void int13_command_close ( struct int13_command *command, int rc ) {
+ intf_restart ( &command->block, rc );
+ stop_timer ( &command->timer );
+ command->rc = rc;
+}
+
+/**
+ * Handle INT 13 command timer expiry
+ *
+ * @v timer Timer
+ */
+static void int13_command_expired ( struct retry_timer *timer,
+ int over __unused ) {
+ struct int13_command *command =
+ container_of ( timer, struct int13_command, timer );
+
+ int13_command_close ( command, -ETIMEDOUT );
+}
+
+/** INT 13 command interface operations */
+static struct interface_operation int13_command_op[] = {
+ INTF_OP ( intf_close, struct int13_command *, int13_command_close ),
+ INTF_OP ( block_capacity, struct int13_command *,
+ int13_command_capacity ),
+};
+
+/** INT 13 command interface descriptor */
+static struct interface_descriptor int13_command_desc =
+ INTF_DESC ( struct int13_command, block, int13_command_op );
+
+/**
+ * Open (or reopen) INT 13 emulated drive underlying block device
+ *
+ * @v int13 Emulated drive
+ * @ret rc Return status code
+ */
+static int int13_reopen_block ( struct int13_drive *int13 ) {
+ int rc;
+
+ /* Close any existing block device */
+ intf_restart ( &int13->block, -ECONNRESET );
+
+ /* Open block device */
+ if ( ( rc = xfer_open_uri ( &int13->block, int13->uri ) ) != 0 ) {
+ DBGC ( int13, "INT13 drive %02x could not reopen block "
+ "device: %s\n", int13->drive, strerror ( rc ) );
+ int13->block_rc = rc;
+ return rc;
+ }
+
+ /* Clear block device error status */
+ int13->block_rc = 0;
+
+ return 0;
+}
+
+/**
+ * Prepare to issue INT 13 command
+ *
+ * @v command INT 13 command
+ * @v int13 Emulated drive
+ * @ret rc Return status code
+ */
+static int int13_command_start ( struct int13_command *command,
+ struct int13_drive *int13 ) {
+ int rc;
+
+ /* Sanity check */
+ assert ( command->int13 == NULL );
+ assert ( ! timer_running ( &command->timer ) );
+
+ /* Reopen block device if necessary */
+ if ( ( int13->block_rc != 0 ) &&
+ ( ( rc = int13_reopen_block ( int13 ) ) != 0 ) )
+ return rc;
+
+ /* Initialise command */
+ command->rc = -EINPROGRESS;
+ command->int13 = int13;
+ start_timer_fixed ( &command->timer, INT13_COMMAND_TIMEOUT );
+
+ /* Wait for block control interface to become ready */
+ while ( ( command->rc == -EINPROGRESS ) &&
+ ( xfer_window ( &int13->block ) == 0 ) ) {
+ step();
+ }
+
+ return ( ( command->rc == -EINPROGRESS ) ?
+ int13->block_rc : command->rc );
+}
+
+/**
+ * Wait for INT 13 command to complete
+ *
+ * @v command INT 13 command
+ * @ret rc Return status code
+ */
+static int int13_command_wait ( struct int13_command *command ) {
+
+ /* Sanity check */
+ assert ( timer_running ( &command->timer ) );
+
+ /* Wait for command to complete */
+ while ( command->rc == -EINPROGRESS )
+ step();
+
+ assert ( ! timer_running ( &command->timer ) );
+ return command->rc;
+}
+
+/**
+ * Terminate INT 13 command
+ *
+ * @v command INT 13 command
+ */
+static void int13_command_stop ( struct int13_command *command ) {
+ stop_timer ( &command->timer );
+ command->int13 = NULL;
+}
+
+/** The single active INT 13 command */
+static struct int13_command int13_command = {
+ .block = INTF_INIT ( int13_command_desc ),
+ .timer = TIMER_INIT ( int13_command_expired ),
+};
+
+/**
+ * Read from or write to INT 13 drive
+ *
+ * @v int13 Emulated drive
+ * @v lba Starting logical block address
+ * @v count Number of logical blocks
+ * @v buffer Data buffer
+ * @v block_rw Block read/write method
+ * @ret rc Return status code
+ */
+static int int13_rw ( struct int13_drive *int13, uint64_t lba,
+ unsigned int count, userptr_t buffer,
+ int ( * block_rw ) ( struct interface *control,
+ struct interface *data,
+ uint64_t lba, unsigned int count,
+ userptr_t buffer, size_t len ) ) {
+ struct int13_command *command = &int13_command;
+ unsigned int frag_count;
+ size_t frag_len;
+ int rc;
+
+ /* Translate to underlying blocksize */
+ lba <<= int13->blksize_shift;
+ count <<= int13->blksize_shift;
+
+ while ( count ) {
+
+ /* Determine fragment length */
+ frag_count = count;
+ if ( frag_count > int13->capacity.max_count )
+ frag_count = int13->capacity.max_count;
+ frag_len = ( int13->capacity.blksize * frag_count );
+
+ /* Issue command */
+ if ( ( ( rc = int13_command_start ( command, int13 ) ) != 0 ) ||
+ ( ( rc = block_rw ( &int13->block, &command->block, lba,
+ frag_count, buffer,
+ frag_len ) ) != 0 ) ||
+ ( ( rc = int13_command_wait ( command ) ) != 0 ) ) {
+ int13_command_stop ( command );
+ return rc;
+ }
+ int13_command_stop ( command );
+
+ /* Move to next fragment */
+ lba += frag_count;
+ count -= frag_count;
+ buffer = userptr_add ( buffer, frag_len );
+ }
+
+ return 0;
+}
+
+/**
+ * Read INT 13 drive capacity
+ *
+ * @v int13 Emulated drive
+ * @ret rc Return status code
+ */
+static int int13_read_capacity ( struct int13_drive *int13 ) {
+ struct int13_command *command = &int13_command;
+ int rc;
+
+ /* Issue command */
+ if ( ( ( rc = int13_command_start ( command, int13 ) ) != 0 ) ||
+ ( ( rc = block_read_capacity ( &int13->block,
+ &command->block ) ) != 0 ) ||
+ ( ( rc = int13_command_wait ( command ) ) != 0 ) ) {
+ int13_command_stop ( command );
+ return rc;
+ }
+
+ int13_command_stop ( command );
+ return 0;
+}
+
+/**
+ * Parse ISO9660 parameters
+ *
+ * @v int13 Emulated drive
+ * @v scratch Scratch area for single-sector reads
+ * @ret rc Return status code
+ *
+ * Reads and parses ISO9660 parameters, if present.
+ */
+static int int13_parse_iso9660 ( struct int13_drive *int13, void *scratch ) {
+ static const struct iso9660_primary_descriptor_fixed primary_check = {
+ .type = ISO9660_TYPE_PRIMARY,
+ .id = ISO9660_ID,
+ };
+ struct iso9660_primary_descriptor *primary = scratch;
+ static const struct eltorito_descriptor_fixed boot_check = {
+ .type = ISO9660_TYPE_BOOT,
+ .id = ISO9660_ID,
+ .version = 1,
+ .system_id = "EL TORITO SPECIFICATION",
+ };
+ struct eltorito_descriptor *boot = scratch;
+ unsigned int blksize;
+ unsigned int blksize_shift;
+ int rc;
+
+ /* Calculate required blocksize shift */
+ blksize = int13_blksize ( int13 );
+ blksize_shift = 0;
+ while ( blksize < ISO9660_BLKSIZE ) {
+ blksize <<= 1;
+ blksize_shift++;
+ }
+ if ( blksize > ISO9660_BLKSIZE ) {
+ /* Do nothing if the blksize is invalid for CD-ROM access */
+ return 0;
+ }
+
+ /* Read primary volume descriptor */
+ if ( ( rc = int13_rw ( int13,
+ ( ISO9660_PRIMARY_LBA << blksize_shift ), 1,
+ virt_to_user ( primary ), block_read ) ) != 0 ){
+ DBGC ( int13, "INT13 drive %02x could not read ISO9660 "
+ "primary volume descriptor: %s\n",
+ int13->drive, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Do nothing unless this is an ISO image */
+ if ( memcmp ( primary, &primary_check, sizeof ( primary_check ) ) != 0 )
+ return 0;
+ DBGC ( int13, "INT13 drive %02x contains an ISO9660 filesystem; "
+ "treating as CD-ROM\n", int13->drive );
+ int13->is_cdrom = 1;
+
+ /* Read boot record volume descriptor */
+ if ( ( rc = int13_rw ( int13,
+ ( ELTORITO_LBA << blksize_shift ), 1,
+ virt_to_user ( boot ), block_read ) ) != 0 ) {
+ DBGC ( int13, "INT13 drive %02x could not read El Torito boot "
+ "record volume descriptor: %s\n",
+ int13->drive, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Check for an El Torito boot catalog */
+ if ( memcmp ( boot, &boot_check, sizeof ( boot_check ) ) == 0 ) {
+ int13->boot_catalog = boot->sector;
+ DBGC ( int13, "INT13 drive %02x has an El Torito boot catalog "
+ "at LBA %08x\n", int13->drive, int13->boot_catalog );
+ } else {
+ DBGC ( int13, "INT13 drive %02x has no El Torito boot "
+ "catalog\n", int13->drive );
+ }
+
+ /* Configure drive for no-emulation CD-ROM access */
+ int13->blksize_shift += blksize_shift;
+
+ return 0;
+}
+
+/**
+ * Guess INT 13 hard disk drive geometry
+ *
+ * @v int13 Emulated drive
+ * @v scratch Scratch area for single-sector reads
+ * @ret heads Guessed number of heads
+ * @ret sectors Guessed number of sectors per track
+ * @ret rc Return status code
+ *
+ * Guesses the drive geometry by inspecting the partition table.
+ */
+static int int13_guess_geometry_hdd ( struct int13_drive *int13, void *scratch,
+ unsigned int *heads,
+ unsigned int *sectors ) {
+ struct master_boot_record *mbr = scratch;
+ struct partition_table_entry *partition;
+ unsigned int i;
+ int rc;
+
+ /* Default guess is xx/255/63 */
+ *heads = 255;
+ *sectors = 63;
+
+ /* Read partition table */
+ if ( ( rc = int13_rw ( int13, 0, 1, virt_to_user ( mbr ),
+ block_read ) ) != 0 ) {
+ DBGC ( int13, "INT13 drive %02x could not read "
+ "partition table to guess geometry: %s\n",
+ int13->drive, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( int13, "INT13 drive %02x has MBR:\n", int13->drive );
+ DBGC2_HDA ( int13, 0, mbr, sizeof ( *mbr ) );
+ DBGC ( int13, "INT13 drive %02x has signature %08x\n",
+ int13->drive, mbr->signature );
+
+ /* Scan through partition table and modify guesses for
+ * heads and sectors_per_track if we find any used
+ * partitions.
+ */
+ for ( i = 0 ; i < 4 ; i++ ) {
+ partition = &mbr->partitions[i];
+ if ( ! partition->type )
+ continue;
+ *heads = ( PART_HEAD ( partition->chs_end ) + 1 );
+ *sectors = PART_SECTOR ( partition->chs_end );
+ DBGC ( int13, "INT13 drive %02x guessing C/H/S xx/%d/%d based "
+ "on partition %d\n",
+ int13->drive, *heads, *sectors, ( i + 1 ) );
+ }
+
+ return 0;
+}
+
+/** Recognised floppy disk geometries */
+static const struct int13_fdd_geometry int13_fdd_geometries[] = {
+ INT13_FDD_GEOMETRY ( 40, 1, 8 ),
+ INT13_FDD_GEOMETRY ( 40, 1, 9 ),
+ INT13_FDD_GEOMETRY ( 40, 2, 8 ),
+ INT13_FDD_GEOMETRY ( 40, 1, 9 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 8 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 9 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 15 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 18 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 20 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 21 ),
+ INT13_FDD_GEOMETRY ( 82, 2, 21 ),
+ INT13_FDD_GEOMETRY ( 83, 2, 21 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 22 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 23 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 24 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 36 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 39 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 40 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 44 ),
+ INT13_FDD_GEOMETRY ( 80, 2, 48 ),
+};
+
+/**
+ * Guess INT 13 floppy disk drive geometry
+ *
+ * @v int13 Emulated drive
+ * @ret heads Guessed number of heads
+ * @ret sectors Guessed number of sectors per track
+ * @ret rc Return status code
+ *
+ * Guesses the drive geometry by inspecting the disk size.
+ */
+static int int13_guess_geometry_fdd ( struct int13_drive *int13,
+ unsigned int *heads,
+ unsigned int *sectors ) {
+ unsigned int blocks = int13_blksize ( int13 );
+ const struct int13_fdd_geometry *geometry;
+ unsigned int cylinders;
+ unsigned int i;
+
+ /* Look for a match against a known geometry */
+ for ( i = 0 ; i < ( sizeof ( int13_fdd_geometries ) /
+ sizeof ( int13_fdd_geometries[0] ) ) ; i++ ) {
+ geometry = &int13_fdd_geometries[i];
+ cylinders = INT13_FDD_CYLINDERS ( geometry );
+ *heads = INT13_FDD_HEADS ( geometry );
+ *sectors = INT13_FDD_SECTORS ( geometry );
+ if ( ( cylinders * (*heads) * (*sectors) ) == blocks ) {
+ DBGC ( int13, "INT13 drive %02x guessing C/H/S "
+ "%d/%d/%d based on size %dK\n", int13->drive,
+ cylinders, *heads, *sectors, ( blocks / 2 ) );
+ return 0;
+ }
+ }
+
+ /* Otherwise, assume a partial disk image in the most common
+ * format (1440K, 80/2/18).
+ */
+ *heads = 2;
+ *sectors = 18;
+ DBGC ( int13, "INT13 drive %02x guessing C/H/S xx/%d/%d based on size "
+ "%dK\n", int13->drive, *heads, *sectors, ( blocks / 2 ) );
+ return 0;
+}
+
+/**
+ * Guess INT 13 drive geometry
+ *
+ * @v int13 Emulated drive
+ * @v scratch Scratch area for single-sector reads
+ * @ret rc Return status code
+ */
+static int int13_guess_geometry ( struct int13_drive *int13, void *scratch ) {
+ unsigned int guessed_heads;
+ unsigned int guessed_sectors;
+ unsigned int blocks;
+ unsigned int blocks_per_cyl;
+ int rc;
+
+ /* Don't even try when the blksize is invalid for C/H/S access */
+ if ( int13_blksize ( int13 ) != INT13_BLKSIZE )
+ return 0;
+
+ /* Guess geometry according to drive type */
+ if ( int13_is_fdd ( int13 ) ) {
+ if ( ( rc = int13_guess_geometry_fdd ( int13, &guessed_heads,
+ &guessed_sectors )) != 0)
+ return rc;
+ } else {
+ if ( ( rc = int13_guess_geometry_hdd ( int13, scratch,
+ &guessed_heads,
+ &guessed_sectors )) != 0)
+ return rc;
+ }
+
+ /* Apply guesses if no geometry already specified */
+ if ( ! int13->heads )
+ int13->heads = guessed_heads;
+ if ( ! int13->sectors_per_track )
+ int13->sectors_per_track = guessed_sectors;
+ if ( ! int13->cylinders ) {
+ /* Avoid attempting a 64-bit divide on a 32-bit system */
+ blocks = int13_capacity32 ( int13 );
+ blocks_per_cyl = ( int13->heads * int13->sectors_per_track );
+ assert ( blocks_per_cyl != 0 );
+ int13->cylinders = ( blocks / blocks_per_cyl );
+ if ( int13->cylinders > 1024 )
+ int13->cylinders = 1024;
+ }
+
+ return 0;
+}
+
+/**
+ * Update BIOS drive count
+ */
+static void int13_sync_num_drives ( void ) {
+ struct int13_drive *int13;
+ uint8_t *counter;
+ uint8_t max_drive;
+ uint8_t required;
+
+ /* Get current drive counts */
+ get_real ( equipment_word, BDA_SEG, BDA_EQUIPMENT_WORD );
+ get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
+ num_fdds = ( ( equipment_word & 0x0001 ) ?
+ ( ( ( equipment_word >> 6 ) & 0x3 ) + 1 ) : 0 );
+
+ /* Ensure count is large enough to cover all of our emulated drives */
+ list_for_each_entry ( int13, &int13s, list ) {
+ counter = ( int13_is_fdd ( int13 ) ? &num_fdds : &num_drives );
+ max_drive = int13->drive;
+ if ( max_drive < int13->natural_drive )
+ max_drive = int13->natural_drive;
+ required = ( ( max_drive & 0x7f ) + 1 );
+ if ( *counter < required ) {
+ *counter = required;
+ DBGC ( int13, "INT13 drive %02x added to drive count: "
+ "%d HDDs, %d FDDs\n",
+ int13->drive, num_drives, num_fdds );
+ }
+ }
+
+ /* Update current drive count */
+ equipment_word &= ~( ( 0x3 << 6 ) | 0x0001 );
+ if ( num_fdds ) {
+ equipment_word |= ( 0x0001 |
+ ( ( ( num_fdds - 1 ) & 0x3 ) << 6 ) );
+ }
+ put_real ( equipment_word, BDA_SEG, BDA_EQUIPMENT_WORD );
+ put_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
+}
+
+/**
+ * Check number of drives
+ */
+static void int13_check_num_drives ( void ) {
+ uint16_t check_equipment_word;
+ uint8_t check_num_drives;
+
+ get_real ( check_equipment_word, BDA_SEG, BDA_EQUIPMENT_WORD );
+ get_real ( check_num_drives, BDA_SEG, BDA_NUM_DRIVES );
+ if ( ( check_equipment_word != equipment_word ) ||
+ ( check_num_drives != num_drives ) ) {
+ int13_sync_num_drives();
+ }
+}
+
+/**
+ * INT 13, 00 - Reset disk system
+ *
+ * @v int13 Emulated drive
+ * @ret status Status code
+ */
+static int int13_reset ( struct int13_drive *int13,
+ struct i386_all_regs *ix86 __unused ) {
+ int rc;
+
+ DBGC2 ( int13, "Reset drive\n" );
+
+ /* Reopen underlying block device */
+ if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
+ return -INT13_STATUS_RESET_FAILED;
+
+ /* Check that block device is functional */
+ if ( ( rc = int13_read_capacity ( int13 ) ) != 0 )
+ return -INT13_STATUS_RESET_FAILED;
+
+ return 0;
+}
+
+/**
+ * INT 13, 01 - Get status of last operation
+ *
+ * @v int13 Emulated drive
+ * @ret status Status code
+ */
+static int int13_get_last_status ( struct int13_drive *int13,
+ struct i386_all_regs *ix86 __unused ) {
+ DBGC2 ( int13, "Get status of last operation\n" );
+ return int13->last_status;
+}
+
+/**
+ * Read / write sectors
+ *
+ * @v int13 Emulated drive
+ * @v al Number of sectors to read or write (must be nonzero)
+ * @v ch Low bits of cylinder number
+ * @v cl (bits 7:6) High bits of cylinder number
+ * @v cl (bits 5:0) Sector number
+ * @v dh Head number
+ * @v es:bx Data buffer
+ * @v block_rw Block read/write method
+ * @ret status Status code
+ * @ret al Number of sectors read or written
+ */
+static int int13_rw_sectors ( struct int13_drive *int13,
+ struct i386_all_regs *ix86,
+ int ( * block_rw ) ( struct interface *control,
+ struct interface *data,
+ uint64_t lba,
+ unsigned int count,
+ userptr_t buffer,
+ size_t len ) ) {
+ unsigned int cylinder, head, sector;
+ unsigned long lba;
+ unsigned int count;
+ userptr_t buffer;
+ int rc;
+
+ /* Validate blocksize */
+ if ( int13_blksize ( int13 ) != INT13_BLKSIZE ) {
+ DBGC ( int13, "\nINT 13 drive %02x invalid blocksize (%zd) "
+ "for non-extended read/write\n",
+ int13->drive, int13_blksize ( int13 ) );
+ return -INT13_STATUS_INVALID;
+ }
+
+ /* Calculate parameters */
+ cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 2 ) | ix86->regs.ch );
+ head = ix86->regs.dh;
+ sector = ( ix86->regs.cl & 0x3f );
+ if ( ( cylinder >= int13->cylinders ) ||
+ ( head >= int13->heads ) ||
+ ( sector < 1 ) || ( sector > int13->sectors_per_track ) ) {
+ DBGC ( int13, "C/H/S %d/%d/%d out of range for geometry "
+ "%d/%d/%d\n", cylinder, head, sector, int13->cylinders,
+ int13->heads, int13->sectors_per_track );
+ return -INT13_STATUS_INVALID;
+ }
+ lba = ( ( ( ( cylinder * int13->heads ) + head )
+ * int13->sectors_per_track ) + sector - 1 );
+ count = ix86->regs.al;
+ buffer = real_to_user ( ix86->segs.es, ix86->regs.bx );
+
+ DBGC2 ( int13, "C/H/S %d/%d/%d = LBA %08lx <-> %04x:%04x (count %d)\n",
+ cylinder, head, sector, lba, ix86->segs.es, ix86->regs.bx,
+ count );
+
+ /* Read from / write to block device */
+ if ( ( rc = int13_rw ( int13, lba, count, buffer, block_rw ) ) != 0 ) {
+ DBGC ( int13, "INT13 drive %02x I/O failed: %s\n",
+ int13->drive, strerror ( rc ) );
+ return -INT13_STATUS_READ_ERROR;
+ }
+
+ return 0;
+}
+
+/**
+ * INT 13, 02 - Read sectors
+ *
+ * @v int13 Emulated drive
+ * @v al Number of sectors to read (must be nonzero)
+ * @v ch Low bits of cylinder number
+ * @v cl (bits 7:6) High bits of cylinder number
+ * @v cl (bits 5:0) Sector number
+ * @v dh Head number
+ * @v es:bx Data buffer
+ * @ret status Status code
+ * @ret al Number of sectors read
+ */
+static int int13_read_sectors ( struct int13_drive *int13,
+ struct i386_all_regs *ix86 ) {
+ DBGC2 ( int13, "Read: " );
+ return int13_rw_sectors ( int13, ix86, block_read );
+}
+
+/**
+ * INT 13, 03 - Write sectors
+ *
+ * @v int13 Emulated drive
+ * @v al Number of sectors to write (must be nonzero)
+ * @v ch Low bits of cylinder number
+ * @v cl (bits 7:6) High bits of cylinder number
+ * @v cl (bits 5:0) Sector number
+ * @v dh Head number
+ * @v es:bx Data buffer
+ * @ret status Status code
+ * @ret al Number of sectors written
+ */
+static int int13_write_sectors ( struct int13_drive *int13,
+ struct i386_all_regs *ix86 ) {
+ DBGC2 ( int13, "Write: " );
+ return int13_rw_sectors ( int13, ix86, block_write );
+}
+
+/**
+ * INT 13, 08 - Get drive parameters
+ *
+ * @v int13 Emulated drive
+ * @ret status Status code
+ * @ret ch Low bits of maximum cylinder number
+ * @ret cl (bits 7:6) High bits of maximum cylinder number
+ * @ret cl (bits 5:0) Maximum sector number
+ * @ret dh Maximum head number
+ * @ret dl Number of drives
+ */
+static int int13_get_parameters ( struct int13_drive *int13,
+ struct i386_all_regs *ix86 ) {
+ unsigned int max_cylinder = int13->cylinders - 1;
+ unsigned int max_head = int13->heads - 1;
+ unsigned int max_sector = int13->sectors_per_track; /* sic */
+
+ DBGC2 ( int13, "Get drive parameters\n" );
+
+ /* Validate blocksize */
+ if ( int13_blksize ( int13 ) != INT13_BLKSIZE ) {
+ DBGC ( int13, "\nINT 13 drive %02x invalid blocksize (%zd) "
+ "for non-extended parameters\n",
+ int13->drive, int13_blksize ( int13 ) );
+ return -INT13_STATUS_INVALID;
+ }
+
+ /* Common parameters */
+ ix86->regs.ch = ( max_cylinder & 0xff );
+ ix86->regs.cl = ( ( ( max_cylinder >> 8 ) << 6 ) | max_sector );
+ ix86->regs.dh = max_head;
+ ix86->regs.dl = ( int13_is_fdd ( int13 ) ? num_fdds : num_drives );
+
+ /* Floppy-specific parameters */
+ if ( int13_is_fdd ( int13 ) ) {
+ ix86->regs.bl = INT13_FDD_TYPE_1M44;
+ ix86->segs.es = rm_ds;
+ ix86->regs.di = __from_data16 ( &int13_fdd_params );
+ }
+
+ return 0;
+}
+
+/**
+ * INT 13, 15 - Get disk type
+ *
+ * @v int13 Emulated drive
+ * @ret ah Type code
+ * @ret cx:dx Sector count
+ * @ret status Status code / disk type
+ */
+static int int13_get_disk_type ( struct int13_drive *int13,
+ struct i386_all_regs *ix86 ) {
+ uint32_t blocks;
+
+ DBGC2 ( int13, "Get disk type\n" );
+
+ if ( int13_is_fdd ( int13 ) ) {
+ return INT13_DISK_TYPE_FDD;
+ } else {
+ blocks = int13_capacity32 ( int13 );
+ ix86->regs.cx = ( blocks >> 16 );
+ ix86->regs.dx = ( blocks & 0xffff );
+ return INT13_DISK_TYPE_HDD;
+ }
+}
+
+/**
+ * INT 13, 41 - Extensions installation check
+ *
+ * @v int13 Emulated drive
+ * @v bx 0x55aa
+ * @ret bx 0xaa55
+ * @ret cx Extensions API support bitmap
+ * @ret status Status code / API version
+ */
+static int int13_extension_check ( struct int13_drive *int13 __unused,
+ struct i386_all_regs *ix86 ) {
+ if ( ix86->regs.bx == 0x55aa ) {
+ DBGC2 ( int13, "INT13 extensions installation check\n" );
+ ix86->regs.bx = 0xaa55;
+ ix86->regs.cx = ( INT13_EXTENSION_LINEAR |
+ INT13_EXTENSION_EDD |
+ INT13_EXTENSION_64BIT );
+ return INT13_EXTENSION_VER_3_0;
+ } else {
+ return -INT13_STATUS_INVALID;
+ }
+}
+
+/**
+ * Extended read / write
+ *
+ * @v int13 Emulated drive
+ * @v ds:si Disk address packet
+ * @v block_rw Block read/write method
+ * @ret status Status code
+ */
+static int int13_extended_rw ( struct int13_drive *int13,
+ struct i386_all_regs *ix86,
+ int ( * block_rw ) ( struct interface *control,
+ struct interface *data,
+ uint64_t lba,
+ unsigned int count,
+ userptr_t buffer,
+ size_t len ) ) {
+ struct int13_disk_address addr;
+ uint8_t bufsize;
+ uint64_t lba;
+ unsigned long count;
+ userptr_t buffer;
+ int rc;
+
+ /* Extended reads are not allowed on floppy drives.
+ * ELTORITO.SYS seems to assume that we are really a CD-ROM if
+ * we support extended reads for a floppy drive.
+ */
+ if ( int13_is_fdd ( int13 ) )
+ return -INT13_STATUS_INVALID;
+
+ /* Get buffer size */
+ get_real ( bufsize, ix86->segs.ds,
+ ( ix86->regs.si + offsetof ( typeof ( addr ), bufsize ) ) );
+ if ( bufsize < offsetof ( typeof ( addr ), buffer_phys ) ) {
+ DBGC2 ( int13, "<invalid buffer size %#02x\n>\n", bufsize );
+ return -INT13_STATUS_INVALID;
+ }
+
+ /* Read parameters from disk address structure */
+ memset ( &addr, 0, sizeof ( addr ) );
+ copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si, bufsize );
+ lba = addr.lba;
+ DBGC2 ( int13, "LBA %08llx <-> ", ( ( unsigned long long ) lba ) );
+ if ( ( addr.count == 0xff ) ||
+ ( ( addr.buffer.segment == 0xffff ) &&
+ ( addr.buffer.offset == 0xffff ) ) ) {
+ buffer = phys_to_user ( addr.buffer_phys );
+ DBGC2 ( int13, "%08llx",
+ ( ( unsigned long long ) addr.buffer_phys ) );
+ } else {
+ buffer = real_to_user ( addr.buffer.segment,
+ addr.buffer.offset );
+ DBGC2 ( int13, "%04x:%04x", addr.buffer.segment,
+ addr.buffer.offset );
+ }
+ if ( addr.count <= 0x7f ) {
+ count = addr.count;
+ } else if ( addr.count == 0xff ) {
+ count = addr.long_count;
+ } else {
+ DBGC2 ( int13, " <invalid count %#02x>\n", addr.count );
+ return -INT13_STATUS_INVALID;
+ }
+ DBGC2 ( int13, " (count %ld)\n", count );
+
+ /* Read from / write to block device */
+ if ( ( rc = int13_rw ( int13, lba, count, buffer, block_rw ) ) != 0 ) {
+ DBGC ( int13, "INT13 drive %02x extended I/O failed: %s\n",
+ int13->drive, strerror ( rc ) );
+ /* Record that no blocks were transferred successfully */
+ addr.count = 0;
+ put_real ( addr.count, ix86->segs.ds,
+ ( ix86->regs.si +
+ offsetof ( typeof ( addr ), count ) ) );
+ return -INT13_STATUS_READ_ERROR;
+ }
+
+ return 0;
+}
+
+/**
+ * INT 13, 42 - Extended read
+ *
+ * @v int13 Emulated drive
+ * @v ds:si Disk address packet
+ * @ret status Status code
+ */
+static int int13_extended_read ( struct int13_drive *int13,
+ struct i386_all_regs *ix86 ) {
+ DBGC2 ( int13, "Extended read: " );
+ return int13_extended_rw ( int13, ix86, block_read );
+}
+
+/**
+ * INT 13, 43 - Extended write
+ *
+ * @v int13 Emulated drive
+ * @v ds:si Disk address packet
+ * @ret status Status code
+ */
+static int int13_extended_write ( struct int13_drive *int13,
+ struct i386_all_regs *ix86 ) {
+ DBGC2 ( int13, "Extended write: " );
+ return int13_extended_rw ( int13, ix86, block_write );
+}
+
+/**
+ * INT 13, 44 - Verify sectors
+ *
+ * @v int13 Emulated drive
+ * @v ds:si Disk address packet
+ * @ret status Status code
+ */
+static int int13_extended_verify ( struct int13_drive *int13,
+ struct i386_all_regs *ix86 ) {
+ struct int13_disk_address addr;
+ uint64_t lba;
+ unsigned long count;
+
+ /* Read parameters from disk address structure */
+ if ( DBG_EXTRA ) {
+ copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si,
+ sizeof ( addr ));
+ lba = addr.lba;
+ count = addr.count;
+ DBGC2 ( int13, "Verify: LBA %08llx (count %ld)\n",
+ ( ( unsigned long long ) lba ), count );
+ }
+
+ /* We have no mechanism for verifying sectors */
+ return -INT13_STATUS_INVALID;
+}
+
+/**
+ * INT 13, 44 - Extended seek
+ *
+ * @v int13 Emulated drive
+ * @v ds:si Disk address packet
+ * @ret status Status code
+ */
+static int int13_extended_seek ( struct int13_drive *int13,
+ struct i386_all_regs *ix86 ) {
+ struct int13_disk_address addr;
+ uint64_t lba;
+ unsigned long count;
+
+ /* Read parameters from disk address structure */
+ if ( DBG_EXTRA ) {
+ copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si,
+ sizeof ( addr ));
+ lba = addr.lba;
+ count = addr.count;
+ DBGC2 ( int13, "Seek: LBA %08llx (count %ld)\n",
+ ( ( unsigned long long ) lba ), count );
+ }
+
+ /* Ignore and return success */
+ return 0;
+}
+
+/**
+ * Build device path information
+ *
+ * @v int13 Emulated drive
+ * @v dpi Device path information
+ * @ret rc Return status code
+ */
+static int int13_device_path_info ( struct int13_drive *int13,
+ struct edd_device_path_information *dpi ) {
+ struct device *device;
+ struct device_description *desc;
+ unsigned int i;
+ uint8_t sum = 0;
+ int rc;
+
+ /* Reopen block device if necessary */
+ if ( ( int13->block_rc != 0 ) &&
+ ( ( rc = int13_reopen_block ( int13 ) ) != 0 ) )
+ return rc;
+
+ /* Get underlying hardware device */
+ device = identify_device ( &int13->block );
+ if ( ! device ) {
+ DBGC ( int13, "INT13 drive %02x cannot identify hardware "
+ "device\n", int13->drive );
+ return -ENODEV;
+ }
+
+ /* Fill in bus type and interface path */
+ desc = &device->desc;
+ switch ( desc->bus_type ) {
+ case BUS_TYPE_PCI:
+ dpi->host_bus_type.type = EDD_BUS_TYPE_PCI;
+ dpi->interface_path.pci.bus = PCI_BUS ( desc->location );
+ dpi->interface_path.pci.slot = PCI_SLOT ( desc->location );
+ dpi->interface_path.pci.function = PCI_FUNC ( desc->location );
+ dpi->interface_path.pci.channel = 0xff; /* unused */
+ break;
+ default:
+ DBGC ( int13, "INT13 drive %02x unrecognised bus type %d\n",
+ int13->drive, desc->bus_type );
+ return -ENOTSUP;
+ }
+
+ /* Get EDD block device description */
+ if ( ( rc = edd_describe ( &int13->block, &dpi->interface_type,
+ &dpi->device_path ) ) != 0 ) {
+ DBGC ( int13, "INT13 drive %02x cannot identify block device: "
+ "%s\n", int13->drive, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Fill in common fields and fix checksum */
+ dpi->key = EDD_DEVICE_PATH_INFO_KEY;
+ dpi->len = sizeof ( *dpi );
+ for ( i = 0 ; i < sizeof ( *dpi ) ; i++ )
+ sum += *( ( ( uint8_t * ) dpi ) + i );
+ dpi->checksum -= sum;
+
+ return 0;
+}
+
+/**
+ * INT 13, 48 - Get extended parameters
+ *
+ * @v int13 Emulated drive
+ * @v ds:si Drive parameter table
+ * @ret status Status code
+ */
+static int int13_get_extended_parameters ( struct int13_drive *int13,
+ struct i386_all_regs *ix86 ) {
+ struct int13_disk_parameters params;
+ struct segoff address;
+ size_t len = sizeof ( params );
+ uint16_t bufsize;
+ int rc;
+
+ /* Get buffer size */
+ get_real ( bufsize, ix86->segs.ds,
+ ( ix86->regs.si + offsetof ( typeof ( params ), bufsize )));
+
+ DBGC2 ( int13, "Get extended drive parameters to %04x:%04x+%02x\n",
+ ix86->segs.ds, ix86->regs.si, bufsize );
+
+ /* Build drive parameters */
+ memset ( &params, 0, sizeof ( params ) );
+ params.flags = INT13_FL_DMA_TRANSPARENT;
+ if ( ( int13->cylinders < 1024 ) &&
+ ( int13_capacity ( int13 ) <= INT13_MAX_CHS_SECTORS ) ) {
+ params.flags |= INT13_FL_CHS_VALID;
+ }
+ params.cylinders = int13->cylinders;
+ params.heads = int13->heads;
+ params.sectors_per_track = int13->sectors_per_track;
+ params.sectors = int13_capacity ( int13 );
+ params.sector_size = int13_blksize ( int13 );
+ memset ( &params.dpte, 0xff, sizeof ( params.dpte ) );
+ if ( ( rc = int13_device_path_info ( int13, &params.dpi ) ) != 0 ) {
+ DBGC ( int13, "INT13 drive %02x could not provide device "
+ "path information: %s\n",
+ int13->drive, strerror ( rc ) );
+ len = offsetof ( typeof ( params ), dpi );
+ }
+
+ /* Calculate returned "buffer size" (which will be less than
+ * the length actually copied if device path information is
+ * present).
+ */
+ if ( bufsize < offsetof ( typeof ( params ), dpte ) )
+ return -INT13_STATUS_INVALID;
+ if ( bufsize < offsetof ( typeof ( params ), dpi ) ) {
+ params.bufsize = offsetof ( typeof ( params ), dpte );
+ } else {
+ params.bufsize = offsetof ( typeof ( params ), dpi );
+ }
+
+ DBGC ( int13, "INT 13 drive %02x described using extended "
+ "parameters:\n", int13->drive );
+ address.segment = ix86->segs.ds;
+ address.offset = ix86->regs.si;
+ DBGC_HDA ( int13, address, &params, len );
+
+ /* Return drive parameters */
+ if ( len > bufsize )
+ len = bufsize;
+ copy_to_real ( ix86->segs.ds, ix86->regs.si, &params, len );
+
+ return 0;
+}
+
+/**
+ * INT 13, 4b - Get status or terminate CD-ROM emulation
+ *
+ * @v int13 Emulated drive
+ * @v ds:si Specification packet
+ * @ret status Status code
+ */
+static int int13_cdrom_status_terminate ( struct int13_drive *int13,
+ struct i386_all_regs *ix86 ) {
+ struct int13_cdrom_specification specification;
+
+ DBGC2 ( int13, "Get CD-ROM emulation status to %04x:%04x%s\n",
+ ix86->segs.ds, ix86->regs.si,
+ ( ix86->regs.al ? "" : " and terminate" ) );
+
+ /* Fail if we are not a CD-ROM */
+ if ( ! int13->is_cdrom ) {
+ DBGC ( int13, "INT13 drive %02x is not a CD-ROM\n",
+ int13->drive );
+ return -INT13_STATUS_INVALID;
+ }
+
+ /* Build specification packet */
+ memset ( &specification, 0, sizeof ( specification ) );
+ specification.size = sizeof ( specification );
+ specification.drive = int13->drive;
+
+ /* Return specification packet */
+ copy_to_real ( ix86->segs.ds, ix86->regs.si, &specification,
+ sizeof ( specification ) );
+
+ return 0;
+}
+
+
+/**
+ * INT 13, 4d - Read CD-ROM boot catalog
+ *
+ * @v int13 Emulated drive
+ * @v ds:si Command packet
+ * @ret status Status code
+ */
+static int int13_cdrom_read_boot_catalog ( struct int13_drive *int13,
+ struct i386_all_regs *ix86 ) {
+ struct int13_cdrom_boot_catalog_command command;
+ int rc;
+
+ /* Read parameters from command packet */
+ copy_from_real ( &command, ix86->segs.ds, ix86->regs.si,
+ sizeof ( command ) );
+ DBGC2 ( int13, "Read CD-ROM boot catalog to %08x\n", command.buffer );
+
+ /* Fail if we have no boot catalog */
+ if ( ! int13->boot_catalog ) {
+ DBGC ( int13, "INT13 drive %02x has no boot catalog\n",
+ int13->drive );
+ return -INT13_STATUS_INVALID;
+ }
+
+ /* Read from boot catalog */
+ if ( ( rc = int13_rw ( int13, ( int13->boot_catalog + command.start ),
+ command.count, phys_to_user ( command.buffer ),
+ block_read ) ) != 0 ) {
+ DBGC ( int13, "INT13 drive %02x could not read boot catalog: "
+ "%s\n", int13->drive, strerror ( rc ) );
+ return -INT13_STATUS_READ_ERROR;
+ }
+
+ return 0;
+}
+
+/**
+ * INT 13 handler
+ *
+ */
+static __asmcall void int13 ( struct i386_all_regs *ix86 ) {
+ int command = ix86->regs.ah;
+ unsigned int bios_drive = ix86->regs.dl;
+ struct int13_drive *int13;
+ int status;
+
+ /* Check BIOS hasn't killed off our drive */
+ int13_check_num_drives();
+
+ list_for_each_entry ( int13, &int13s, list ) {
+
+ if ( bios_drive != int13->drive ) {
+ /* Remap any accesses to this drive's natural number */
+ if ( bios_drive == int13->natural_drive ) {
+ DBGC2 ( int13, "INT13,%02x (%02x) remapped to "
+ "(%02x)\n", ix86->regs.ah,
+ bios_drive, int13->drive );
+ ix86->regs.dl = int13->drive;
+ return;
+ } else if ( ( ( bios_drive & 0x7f ) == 0x7f ) &&
+ ( command == INT13_CDROM_STATUS_TERMINATE )
+ && int13->is_cdrom ) {
+ /* Catch non-drive-specific CD-ROM calls */
+ } else {
+ continue;
+ }
+ }
+
+ DBGC2 ( int13, "INT13,%02x (%02x): ",
+ ix86->regs.ah, bios_drive );
+
+ switch ( command ) {
+ case INT13_RESET:
+ status = int13_reset ( int13, ix86 );
+ break;
+ case INT13_GET_LAST_STATUS:
+ status = int13_get_last_status ( int13, ix86 );
+ break;
+ case INT13_READ_SECTORS:
+ status = int13_read_sectors ( int13, ix86 );
+ break;
+ case INT13_WRITE_SECTORS:
+ status = int13_write_sectors ( int13, ix86 );
+ break;
+ case INT13_GET_PARAMETERS:
+ status = int13_get_parameters ( int13, ix86 );
+ break;
+ case INT13_GET_DISK_TYPE:
+ status = int13_get_disk_type ( int13, ix86 );
+ break;
+ case INT13_EXTENSION_CHECK:
+ status = int13_extension_check ( int13, ix86 );
+ break;
+ case INT13_EXTENDED_READ:
+ status = int13_extended_read ( int13, ix86 );
+ break;
+ case INT13_EXTENDED_WRITE:
+ status = int13_extended_write ( int13, ix86 );
+ break;
+ case INT13_EXTENDED_VERIFY:
+ status = int13_extended_verify ( int13, ix86 );
+ break;
+ case INT13_EXTENDED_SEEK:
+ status = int13_extended_seek ( int13, ix86 );
+ break;
+ case INT13_GET_EXTENDED_PARAMETERS:
+ status = int13_get_extended_parameters ( int13, ix86 );
+ break;
+ case INT13_CDROM_STATUS_TERMINATE:
+ status = int13_cdrom_status_terminate ( int13, ix86 );
+ break;
+ case INT13_CDROM_READ_BOOT_CATALOG:
+ status = int13_cdrom_read_boot_catalog ( int13, ix86 );
+ break;
+ default:
+ DBGC2 ( int13, "*** Unrecognised INT13 ***\n" );
+ status = -INT13_STATUS_INVALID;
+ break;
+ }
+
+ /* Store status for INT 13,01 */
+ int13->last_status = status;
+
+ /* Negative status indicates an error */
+ if ( status < 0 ) {
+ status = -status;
+ DBGC ( int13, "INT13,%02x (%02x) failed with status "
+ "%02x\n", ix86->regs.ah, int13->drive, status );
+ } else {
+ ix86->flags &= ~CF;
+ }
+ ix86->regs.ah = status;
+
+ /* Set OF to indicate to wrapper not to chain this call */
+ ix86->flags |= OF;
+
+ return;
+ }
+}
+
+/**
+ * Hook INT 13 handler
+ *
+ */
+static void int13_hook_vector ( void ) {
+ /* Assembly wrapper to call int13(). int13() sets OF if we
+ * should not chain to the previous handler. (The wrapper
+ * clears CF and OF before calling int13()).
+ */
+ __asm__ __volatile__ (
+ TEXT16_CODE ( "\nint13_wrapper:\n\t"
+ /* Preserve %ax and %dx for future reference */
+ "pushw %%bp\n\t"
+ "movw %%sp, %%bp\n\t"
+ "pushw %%ax\n\t"
+ "pushw %%dx\n\t"
+ /* Clear OF, set CF, call int13() */
+ "orb $0, %%al\n\t"
+ "stc\n\t"
+ "pushl %0\n\t"
+ "pushw %%cs\n\t"
+ "call prot_call\n\t"
+ /* Chain if OF not set */
+ "jo 1f\n\t"
+ "pushfw\n\t"
+ "lcall *%%cs:int13_vector\n\t"
+ "\n1:\n\t"
+ /* Overwrite flags for iret */
+ "pushfw\n\t"
+ "popw 6(%%bp)\n\t"
+ /* Fix up %dl:
+ *
+ * INT 13,15 : do nothing if hard disk
+ * INT 13,08 : load with number of drives
+ * all others: restore original value
+ */
+ "cmpb $0x15, -1(%%bp)\n\t"
+ "jne 2f\n\t"
+ "testb $0x80, -4(%%bp)\n\t"
+ "jnz 3f\n\t"
+ "\n2:\n\t"
+ "movb -4(%%bp), %%dl\n\t"
+ "cmpb $0x08, -1(%%bp)\n\t"
+ "jne 3f\n\t"
+ "testb $0x80, %%dl\n\t"
+ "movb %%cs:num_drives, %%dl\n\t"
+ "jnz 3f\n\t"
+ "movb %%cs:num_fdds, %%dl\n\t"
+ /* Return */
+ "\n3:\n\t"
+ "movw %%bp, %%sp\n\t"
+ "popw %%bp\n\t"
+ "iret\n\t" )
+ : : "i" ( int13 ) );
+
+ hook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper,
+ &int13_vector );
+}
+
+/**
+ * Unhook INT 13 handler
+ */
+static void int13_unhook_vector ( void ) {
+ unhook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper,
+ &int13_vector );
+}
+
+/**
+ * Check INT13 emulated drive flow control window
+ *
+ * @v int13 Emulated drive
+ */
+static size_t int13_block_window ( struct int13_drive *int13 __unused ) {
+
+ /* We are never ready to receive data via this interface.
+ * This prevents objects that support both block and stream
+ * interfaces from attempting to send us stream data.
+ */
+ return 0;
+}
+
+/**
+ * Handle INT 13 emulated drive underlying block device closing
+ *
+ * @v int13 Emulated drive
+ * @v rc Reason for close
+ */
+static void int13_block_close ( struct int13_drive *int13, int rc ) {
+
+ /* Any closing is an error from our point of view */
+ if ( rc == 0 )
+ rc = -ENOTCONN;
+
+ DBGC ( int13, "INT13 drive %02x went away: %s\n",
+ int13->drive, strerror ( rc ) );
+
+ /* Record block device error code */
+ int13->block_rc = rc;
+
+ /* Shut down interfaces */
+ intf_restart ( &int13->block, rc );
+}
+
+/** INT 13 drive interface operations */
+static struct interface_operation int13_block_op[] = {
+ INTF_OP ( xfer_window, struct int13_drive *, int13_block_window ),
+ INTF_OP ( intf_close, struct int13_drive *, int13_block_close ),
+};
+
+/** INT 13 drive interface descriptor */
+static struct interface_descriptor int13_block_desc =
+ INTF_DESC ( struct int13_drive, block, int13_block_op );
+
+/**
+ * Free INT 13 emulated drive
+ *
+ * @v refcnt Reference count
+ */
+static void int13_free ( struct refcnt *refcnt ) {
+ struct int13_drive *int13 =
+ container_of ( refcnt, struct int13_drive, refcnt );
+
+ uri_put ( int13->uri );
+ free ( int13 );
+}
+
+/**
+ * Hook INT 13 emulated drive
+ *
+ * @v uri URI
+ * @v drive Drive number
+ * @ret rc Return status code
+ *
+ * Registers the drive with the INT 13 emulation subsystem, and hooks
+ * the INT 13 interrupt vector (if not already hooked).
+ */
+static int int13_hook ( struct uri *uri, unsigned int drive ) {
+ struct int13_drive *int13;
+ unsigned int natural_drive;
+ void *scratch;
+ int rc;
+
+ /* Calculate natural drive number */
+ int13_sync_num_drives();
+ natural_drive = ( ( drive & 0x80 ) ? ( num_drives | 0x80 ) : num_fdds );
+
+ /* Check that drive number is not in use */
+ list_for_each_entry ( int13, &int13s, list ) {
+ if ( int13->drive == drive ) {
+ rc = -EADDRINUSE;
+ goto err_in_use;
+ }
+ }
+
+ /* Allocate and initialise structure */
+ int13 = zalloc ( sizeof ( *int13 ) );
+ if ( ! int13 ) {
+ rc = -ENOMEM;
+ goto err_zalloc;
+ }
+ ref_init ( &int13->refcnt, int13_free );
+ intf_init ( &int13->block, &int13_block_desc, &int13->refcnt );
+ int13->uri = uri_get ( uri );
+ int13->drive = drive;
+ int13->natural_drive = natural_drive;
+
+ /* Open block device interface */
+ if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
+ goto err_reopen_block;
+
+ /* Read device capacity */
+ if ( ( rc = int13_read_capacity ( int13 ) ) != 0 )
+ goto err_read_capacity;
+
+ /* Allocate scratch area */
+ scratch = malloc ( int13_blksize ( int13 ) );
+ if ( ! scratch )
+ goto err_alloc_scratch;
+
+ /* Parse parameters, if present */
+ if ( ( rc = int13_parse_iso9660 ( int13, scratch ) ) != 0 )
+ goto err_parse_iso9660;
+
+ /* Give drive a default geometry */
+ if ( ( rc = int13_guess_geometry ( int13, scratch ) ) != 0 )
+ goto err_guess_geometry;
+
+ DBGC ( int13, "INT13 drive %02x (naturally %02x) registered with C/H/S "
+ "geometry %d/%d/%d\n", int13->drive, int13->natural_drive,
+ int13->cylinders, int13->heads, int13->sectors_per_track );
+
+ /* Hook INT 13 vector if not already hooked */
+ if ( list_empty ( &int13s ) ) {
+ int13_hook_vector();
+ devices_get();
+ }
+
+ /* Add to list of emulated drives */
+ list_add ( &int13->list, &int13s );
+
+ /* Update BIOS drive count */
+ int13_sync_num_drives();
+
+ free ( scratch );
+ return 0;
+
+ err_guess_geometry:
+ err_parse_iso9660:
+ free ( scratch );
+ err_alloc_scratch:
+ err_read_capacity:
+ err_reopen_block:
+ intf_shutdown ( &int13->block, rc );
+ ref_put ( &int13->refcnt );
+ err_zalloc:
+ err_in_use:
+ return rc;
+}
+
+/**
+ * Find INT 13 emulated drive by drive number
+ *
+ * @v drive Drive number
+ * @ret int13 Emulated drive, or NULL
+ */
+static struct int13_drive * int13_find ( unsigned int drive ) {
+ struct int13_drive *int13;
+
+ list_for_each_entry ( int13, &int13s, list ) {
+ if ( int13->drive == drive )
+ return int13;
+ }
+ return NULL;
+}
+
+/**
+ * Unhook INT 13 emulated drive
+ *
+ * @v drive Drive number
+ *
+ * Unregisters the drive from the INT 13 emulation subsystem. If this
+ * is the last emulated drive, the INT 13 vector is unhooked (if
+ * possible).
+ */
+static void int13_unhook ( unsigned int drive ) {
+ struct int13_drive *int13;
+
+ /* Find drive */
+ int13 = int13_find ( drive );
+ if ( ! int13 ) {
+ DBG ( "INT13 cannot find emulated drive %02x\n", drive );
+ return;
+ }
+
+ /* Shut down interfaces */
+ intf_shutdown ( &int13->block, 0 );
+
+ /* Remove from list of emulated drives */
+ list_del ( &int13->list );
+
+ /* Should adjust BIOS drive count, but it's difficult
+ * to do so reliably.
+ */
+
+ DBGC ( int13, "INT13 drive %02x unregistered\n", int13->drive );
+
+ /* Unhook INT 13 vector if no more drives */
+ if ( list_empty ( &int13s ) ) {
+ devices_put();
+ int13_unhook_vector();
+ }
+
+ /* Drop list's reference to drive */
+ ref_put ( &int13->refcnt );
+}
+
+/**
+ * Load and verify master boot record from INT 13 drive
+ *
+ * @v drive Drive number
+ * @v address Boot code address to fill in
+ * @ret rc Return status code
+ */
+static int int13_load_mbr ( unsigned int drive, struct segoff *address ) {
+ uint8_t status;
+ int discard_b, discard_c, discard_d;
+ uint16_t magic;
+
+ /* Use INT 13, 02 to read the MBR */
+ address->segment = 0;
+ address->offset = 0x7c00;
+ __asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t"
+ "pushl %%ebx\n\t"
+ "popw %%bx\n\t"
+ "popw %%es\n\t"
+ "stc\n\t"
+ "sti\n\t"
+ "int $0x13\n\t"
+ "sti\n\t" /* BIOS bugs */
+ "jc 1f\n\t"
+ "xorw %%ax, %%ax\n\t"
+ "\n1:\n\t"
+ "popw %%es\n\t" )
+ : "=a" ( status ), "=b" ( discard_b ),
+ "=c" ( discard_c ), "=d" ( discard_d )
+ : "a" ( 0x0201 ), "b" ( *address ),
+ "c" ( 1 ), "d" ( drive ) );
+ if ( status ) {
+ DBG ( "INT13 drive %02x could not read MBR (status %02x)\n",
+ drive, status );
+ return -EIO;
+ }
+
+ /* Check magic signature */
+ get_real ( magic, address->segment,
+ ( address->offset +
+ offsetof ( struct master_boot_record, magic ) ) );
+ if ( magic != INT13_MBR_MAGIC ) {
+ DBG ( "INT13 drive %02x does not contain a valid MBR\n",
+ drive );
+ return -ENOEXEC;
+ }
+
+ return 0;
+}
+
+/** El Torito boot catalog command packet */
+static struct int13_cdrom_boot_catalog_command __data16 ( eltorito_cmd ) = {
+ .size = sizeof ( struct int13_cdrom_boot_catalog_command ),
+ .count = 1,
+ .buffer = 0x7c00,
+ .start = 0,
+};
+#define eltorito_cmd __use_data16 ( eltorito_cmd )
+
+/** El Torito disk address packet */
+static struct int13_disk_address __bss16 ( eltorito_address );
+#define eltorito_address __use_data16 ( eltorito_address )
+
+/**
+ * Load and verify El Torito boot record from INT 13 drive
+ *
+ * @v drive Drive number
+ * @v address Boot code address to fill in
+ * @ret rc Return status code
+ */
+static int int13_load_eltorito ( unsigned int drive, struct segoff *address ) {
+ struct {
+ struct eltorito_validation_entry valid;
+ struct eltorito_boot_entry boot;
+ } __attribute__ (( packed )) catalog;
+ uint8_t status;
+
+ /* Use INT 13, 4d to read the boot catalog */
+ __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
+ "sti\n\t"
+ "int $0x13\n\t"
+ "sti\n\t" /* BIOS bugs */
+ "jc 1f\n\t"
+ "xorw %%ax, %%ax\n\t"
+ "\n1:\n\t" )
+ : "=a" ( status )
+ : "a" ( 0x4d00 ), "d" ( drive ),
+ "S" ( __from_data16 ( &eltorito_cmd ) ) );
+ if ( status ) {
+ DBG ( "INT13 drive %02x could not read El Torito boot catalog "
+ "(status %02x)\n", drive, status );
+ return -EIO;
+ }
+ copy_from_user ( &catalog, phys_to_user ( eltorito_cmd.buffer ), 0,
+ sizeof ( catalog ) );
+
+ /* Sanity checks */
+ if ( catalog.valid.platform_id != ELTORITO_PLATFORM_X86 ) {
+ DBG ( "INT13 drive %02x El Torito specifies unknown platform "
+ "%02x\n", drive, catalog.valid.platform_id );
+ return -ENOEXEC;
+ }
+ if ( catalog.boot.indicator != ELTORITO_BOOTABLE ) {
+ DBG ( "INT13 drive %02x El Torito is not bootable\n", drive );
+ return -ENOEXEC;
+ }
+ if ( catalog.boot.media_type != ELTORITO_NO_EMULATION ) {
+ DBG ( "INT13 drive %02x El Torito requires emulation "
+ "type %02x\n", drive, catalog.boot.media_type );
+ return -ENOTSUP;
+ }
+ DBG ( "INT13 drive %02x El Torito boot image at LBA %08x (count %d)\n",
+ drive, catalog.boot.start, catalog.boot.length );
+ address->segment = ( catalog.boot.load_segment ?
+ catalog.boot.load_segment : 0x7c0 );
+ address->offset = 0;
+ DBG ( "INT13 drive %02x El Torito boot image loads at %04x:%04x\n",
+ drive, address->segment, address->offset );
+
+ /* Use INT 13, 42 to read the boot image */
+ eltorito_address.bufsize =
+ offsetof ( typeof ( eltorito_address ), buffer_phys );
+ eltorito_address.count = catalog.boot.length;
+ eltorito_address.buffer = *address;
+ eltorito_address.lba = catalog.boot.start;
+ __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
+ "sti\n\t"
+ "int $0x13\n\t"
+ "sti\n\t" /* BIOS bugs */
+ "jc 1f\n\t"
+ "xorw %%ax, %%ax\n\t"
+ "\n1:\n\t" )
+ : "=a" ( status )
+ : "a" ( 0x4200 ), "d" ( drive ),
+ "S" ( __from_data16 ( &eltorito_address ) ) );
+ if ( status ) {
+ DBG ( "INT13 drive %02x could not read El Torito boot image "
+ "(status %02x)\n", drive, status );
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * Attempt to boot from an INT 13 drive
+ *
+ * @v drive Drive number
+ * @ret rc Return status code
+ *
+ * This boots from the specified INT 13 drive by loading the Master
+ * Boot Record to 0000:7c00 and jumping to it. INT 18 is hooked to
+ * capture an attempt by the MBR to boot the next device. (This is
+ * the closest thing to a return path from an MBR).
+ *
+ * Note that this function can never return success, by definition.
+ */
+static int int13_boot ( unsigned int drive ) {
+ struct memory_map memmap;
+ struct segoff address;
+ int rc;
+
+ /* Look for a usable boot sector */
+ if ( ( ( rc = int13_load_mbr ( drive, &address ) ) != 0 ) &&
+ ( ( rc = int13_load_eltorito ( drive, &address ) ) != 0 ) )
+ return rc;
+
+ /* Dump out memory map prior to boot, if memmap debugging is
+ * enabled. Not required for program flow, but we have so
+ * many problems that turn out to be memory-map related that
+ * it's worth doing.
+ */
+ get_memmap ( &memmap );
+
+ /* Jump to boot sector */
+ if ( ( rc = call_bootsector ( address.segment, address.offset,
+ drive ) ) != 0 ) {
+ DBG ( "INT13 drive %02x boot returned: %s\n",
+ drive, strerror ( rc ) );
+ return rc;
+ }
+
+ return -ECANCELED; /* -EIMPOSSIBLE */
+}
+
+/** A boot firmware table generated by iPXE */
+union xbft_table {
+ /** ACPI header */
+ struct acpi_description_header acpi;
+ /** Padding */
+ char pad[768];
+};
+
+/** The boot firmware table generated by iPXE */
+static union xbft_table __bss16 ( xbftab ) __attribute__ (( aligned ( 16 ) ));
+#define xbftab __use_data16 ( xbftab )
+
+/**
+ * Describe INT 13 emulated drive for SAN-booted operating system
+ *
+ * @v drive Drive number
+ * @ret rc Return status code
+ */
+static int int13_describe ( unsigned int drive ) {
+ struct int13_drive *int13;
+ struct segoff xbft_address;
+ int rc;
+
+ /* Find drive */
+ int13 = int13_find ( drive );
+ if ( ! int13 ) {
+ DBG ( "INT13 cannot find emulated drive %02x\n", drive );
+ return -ENODEV;
+ }
+
+ /* Reopen block device if necessary */
+ if ( ( int13->block_rc != 0 ) &&
+ ( ( rc = int13_reopen_block ( int13 ) ) != 0 ) )
+ return rc;
+
+ /* Clear table */
+ memset ( &xbftab, 0, sizeof ( xbftab ) );
+
+ /* Fill in common parameters */
+ strncpy ( xbftab.acpi.oem_id, "FENSYS",
+ sizeof ( xbftab.acpi.oem_id ) );
+ strncpy ( xbftab.acpi.oem_table_id, "iPXE",
+ sizeof ( xbftab.acpi.oem_table_id ) );
+
+ /* Fill in remaining parameters */
+ if ( ( rc = acpi_describe ( &int13->block, &xbftab.acpi,
+ sizeof ( xbftab ) ) ) != 0 ) {
+ DBGC ( int13, "INT13 drive %02x could not create ACPI "
+ "description: %s\n", int13->drive, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Fix up ACPI checksum */
+ acpi_fix_checksum ( &xbftab.acpi );
+ xbft_address.segment = rm_ds;
+ xbft_address.offset = __from_data16 ( &xbftab );
+ DBGC ( int13, "INT13 drive %02x described using boot firmware "
+ "table:\n", int13->drive );
+ DBGC_HDA ( int13, xbft_address, &xbftab,
+ le32_to_cpu ( xbftab.acpi.length ) );
+
+ return 0;
+}
+
+PROVIDE_SANBOOT_INLINE ( pcbios, san_default_drive );
+PROVIDE_SANBOOT ( pcbios, san_hook, int13_hook );
+PROVIDE_SANBOOT ( pcbios, san_unhook, int13_unhook );
+PROVIDE_SANBOOT ( pcbios, san_boot, int13_boot );
+PROVIDE_SANBOOT ( pcbios, san_describe, int13_describe );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
new file mode 100644
index 00000000..dba4a23a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * External memory allocation
+ *
+ */
+
+#include <limits.h>
+#include <errno.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/hidemem.h>
+#include <ipxe/io.h>
+#include <ipxe/umalloc.h>
+
+/** Alignment of external allocated memory */
+#define EM_ALIGN ( 4 * 1024 )
+
+/** Equivalent of NOWHERE for user pointers */
+#define UNOWHERE ( ~UNULL )
+
+/** An external memory block */
+struct external_memory {
+ /** Size of this memory block (excluding this header) */
+ size_t size;
+ /** Block is currently in use */
+ int used;
+};
+
+/** Top of heap */
+static userptr_t top = UNULL;
+
+/** Bottom of heap (current lowest allocated block) */
+static userptr_t bottom = UNULL;
+
+/** Remaining space on heap */
+static size_t heap_size;
+
+/**
+ * Initialise external heap
+ *
+ * @ret rc Return status code
+ */
+static int init_eheap ( void ) {
+ struct memory_map memmap;
+ unsigned int i;
+
+ DBG ( "Allocating external heap\n" );
+
+ get_memmap ( &memmap );
+ heap_size = 0;
+ for ( i = 0 ; i < memmap.count ; i++ ) {
+ struct memory_region *region = &memmap.regions[i];
+ unsigned long r_start, r_end;
+ unsigned long r_size;
+
+ DBG ( "Considering [%llx,%llx)\n", region->start, region->end);
+
+ /* Truncate block to 4GB */
+ if ( region->start > UINT_MAX ) {
+ DBG ( "...starts after 4GB\n" );
+ continue;
+ }
+ r_start = region->start;
+ if ( region->end > UINT_MAX ) {
+ DBG ( "...end truncated to 4GB\n" );
+ r_end = 0; /* =4GB, given the wraparound */
+ } else {
+ r_end = region->end;
+ }
+
+ /* Use largest block */
+ r_size = ( r_end - r_start );
+ if ( r_size > heap_size ) {
+ DBG ( "...new best block found\n" );
+ top = bottom = phys_to_user ( r_end );
+ heap_size = r_size;
+ }
+ }
+
+ if ( ! heap_size ) {
+ DBG ( "No external heap available\n" );
+ return -ENOMEM;
+ }
+
+ DBG ( "External heap grows downwards from %lx (size %zx)\n",
+ user_to_phys ( top, 0 ), heap_size );
+ return 0;
+}
+
+/**
+ * Collect free blocks
+ *
+ */
+static void ecollect_free ( void ) {
+ struct external_memory extmem;
+ size_t len;
+
+ /* Walk the free list and collect empty blocks */
+ while ( bottom != top ) {
+ copy_from_user ( &extmem, bottom, -sizeof ( extmem ),
+ sizeof ( extmem ) );
+ if ( extmem.used )
+ break;
+ DBG ( "EXTMEM freeing [%lx,%lx)\n", user_to_phys ( bottom, 0 ),
+ user_to_phys ( bottom, extmem.size ) );
+ len = ( extmem.size + sizeof ( extmem ) );
+ bottom = userptr_add ( bottom, len );
+ heap_size += len;
+ }
+}
+
+/**
+ * Reallocate external memory
+ *
+ * @v old_ptr Memory previously allocated by umalloc(), or UNULL
+ * @v new_size Requested size
+ * @ret new_ptr Allocated memory, or UNULL
+ *
+ * Calling realloc() with a new size of zero is a valid way to free a
+ * memory block.
+ */
+static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
+ struct external_memory extmem;
+ userptr_t new = ptr;
+ size_t align;
+ int rc;
+
+ /* Initialise external memory allocator if necessary */
+ if ( bottom == top ) {
+ if ( ( rc = init_eheap() ) != 0 )
+ return UNULL;
+ }
+
+ /* Get block properties into extmem */
+ if ( ptr && ( ptr != UNOWHERE ) ) {
+ /* Determine old size */
+ copy_from_user ( &extmem, ptr, -sizeof ( extmem ),
+ sizeof ( extmem ) );
+ } else {
+ /* Create a zero-length block */
+ if ( heap_size < sizeof ( extmem ) ) {
+ DBG ( "EXTMEM out of space\n" );
+ return UNULL;
+ }
+ ptr = bottom = userptr_add ( bottom, -sizeof ( extmem ) );
+ heap_size -= sizeof ( extmem );
+ DBG ( "EXTMEM allocating [%lx,%lx)\n",
+ user_to_phys ( ptr, 0 ), user_to_phys ( ptr, 0 ) );
+ extmem.size = 0;
+ }
+ extmem.used = ( new_size > 0 );
+
+ /* Expand/shrink block if possible */
+ if ( ptr == bottom ) {
+ /* Update block */
+ if ( new_size > ( heap_size - extmem.size ) ) {
+ DBG ( "EXTMEM out of space\n" );
+ return UNULL;
+ }
+ new = userptr_add ( ptr, - ( new_size - extmem.size ) );
+ align = ( user_to_phys ( new, 0 ) & ( EM_ALIGN - 1 ) );
+ new_size += align;
+ new = userptr_add ( new, -align );
+ DBG ( "EXTMEM expanding [%lx,%lx) to [%lx,%lx)\n",
+ user_to_phys ( ptr, 0 ),
+ user_to_phys ( ptr, extmem.size ),
+ user_to_phys ( new, 0 ),
+ user_to_phys ( new, new_size ));
+ memmove_user ( new, 0, ptr, 0, ( ( extmem.size < new_size ) ?
+ extmem.size : new_size ) );
+ bottom = new;
+ heap_size -= ( new_size - extmem.size );
+ extmem.size = new_size;
+ } else {
+ /* Cannot expand; can only pretend to shrink */
+ if ( new_size > extmem.size ) {
+ /* Refuse to expand */
+ DBG ( "EXTMEM cannot expand [%lx,%lx)\n",
+ user_to_phys ( ptr, 0 ),
+ user_to_phys ( ptr, extmem.size ) );
+ return UNULL;
+ }
+ }
+
+ /* Write back block properties */
+ copy_to_user ( new, -sizeof ( extmem ), &extmem,
+ sizeof ( extmem ) );
+
+ /* Collect any free blocks and update hidden memory region */
+ ecollect_free();
+ hide_umalloc ( user_to_phys ( bottom, ( ( bottom == top ) ?
+ 0 : -sizeof ( extmem ) ) ),
+ user_to_phys ( top, 0 ) );
+
+ return ( new_size ? new : UNOWHERE );
+}
+
+PROVIDE_UMALLOC ( memtop, urealloc, memtop_urealloc );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/pcibios.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/pcibios.c
new file mode 100644
index 00000000..511ec623
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/pcibios.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/pci.h>
+#include <realmode.h>
+
+/** @file
+ *
+ * PCI configuration space access via PCI BIOS
+ *
+ */
+
+/**
+ * Determine number of PCI buses within system
+ *
+ * @ret num_bus Number of buses
+ */
+static int pcibios_num_bus ( void ) {
+ int discard_a, discard_D;
+ uint8_t max_bus;
+
+ __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
+ "int $0x1a\n\t"
+ "jnc 1f\n\t"
+ "xorw %%cx, %%cx\n\t"
+ "\n1:\n\t" )
+ : "=c" ( max_bus ), "=a" ( discard_a ),
+ "=D" ( discard_D )
+ : "a" ( PCIBIOS_INSTALLATION_CHECK >> 16 ),
+ "D" ( 0 )
+ : "ebx", "edx" );
+
+ return ( max_bus + 1 );
+}
+
+/**
+ * Read configuration space via PCI BIOS
+ *
+ * @v pci PCI device
+ * @v command PCI BIOS command
+ * @v value Value read
+ * @ret rc Return status code
+ */
+int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){
+ int discard_b, discard_D;
+ int status;
+
+ __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
+ "int $0x1a\n\t"
+ "jnc 1f\n\t"
+ "xorl %%eax, %%eax\n\t"
+ "decl %%eax\n\t"
+ "movl %%eax, %%ecx\n\t"
+ "\n1:\n\t" )
+ : "=a" ( status ), "=b" ( discard_b ),
+ "=c" ( *value ), "=D" ( discard_D )
+ : "a" ( command >> 16 ), "D" ( command ),
+ "b" ( pci->busdevfn )
+ : "edx" );
+
+ return ( ( status >> 8 ) & 0xff );
+}
+
+/**
+ * Write configuration space via PCI BIOS
+ *
+ * @v pci PCI device
+ * @v command PCI BIOS command
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){
+ int discard_b, discard_c, discard_D;
+ int status;
+
+ __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
+ "int $0x1a\n\t"
+ "jnc 1f\n\t"
+ "movb $0xff, %%ah\n\t"
+ "\n1:\n\t" )
+ : "=a" ( status ), "=b" ( discard_b ),
+ "=c" ( discard_c ), "=D" ( discard_D )
+ : "a" ( command >> 16 ), "D" ( command ),
+ "b" ( pci->busdevfn ), "c" ( value )
+ : "edx" );
+
+ return ( ( status >> 8 ) & 0xff );
+}
+
+PROVIDE_PCIAPI ( pcbios, pci_num_bus, pcibios_num_bus );
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_byte );
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_word );
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_dword );
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_byte );
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_word );
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_dword );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c
new file mode 100644
index 00000000..3f2a7c78
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * RTC-based entropy source
+ *
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <biosint.h>
+#include <pic8259.h>
+#include <rtc.h>
+#include <ipxe/entropy.h>
+
+/** RTC "interrupt triggered" flag */
+static uint8_t __text16 ( rtc_flag );
+#define rtc_flag __use_text16 ( rtc_flag )
+
+/** RTC interrupt handler */
+extern void rtc_isr ( void );
+
+/** Previous RTC interrupt handler */
+static struct segoff rtc_old_handler;
+
+/**
+ * Hook RTC interrupt handler
+ *
+ */
+static void rtc_hook_isr ( void ) {
+
+ /* RTC interrupt handler */
+ __asm__ __volatile__ (
+ TEXT16_CODE ( "\nrtc_isr:\n\t"
+ /* Preserve registers */
+ "pushw %%ax\n\t"
+ /* Set "interrupt triggered" flag */
+ "cs movb $0x01, %c0\n\t"
+ /* Read RTC status register C to
+ * acknowledge interrupt
+ */
+ "movb %3, %%al\n\t"
+ "outb %%al, %1\n\t"
+ "inb %2\n\t"
+ /* Send EOI */
+ "movb $0x20, %%al\n\t"
+ "outb %%al, $0xa0\n\t"
+ "outb %%al, $0x20\n\t"
+ /* Restore registers and return */
+ "popw %%ax\n\t"
+ "iret\n\t" )
+ :
+ : "p" ( __from_text16 ( &rtc_flag ) ),
+ "i" ( CMOS_ADDRESS ), "i" ( CMOS_DATA ),
+ "i" ( RTC_STATUS_C ) );
+
+ hook_bios_interrupt ( RTC_INT, ( unsigned int ) rtc_isr,
+ &rtc_old_handler );
+}
+
+/**
+ * Unhook RTC interrupt handler
+ *
+ */
+static void rtc_unhook_isr ( void ) {
+ int rc;
+
+ rc = unhook_bios_interrupt ( RTC_INT, ( unsigned int ) rtc_isr,
+ &rtc_old_handler );
+ assert ( rc == 0 ); /* Should always be able to unhook */
+}
+
+/**
+ * Enable RTC interrupts
+ *
+ */
+static void rtc_enable_int ( void ) {
+ uint8_t status_b;
+
+ /* Set Periodic Interrupt Enable bit in status register B */
+ outb ( ( RTC_STATUS_B | CMOS_DISABLE_NMI ), CMOS_ADDRESS );
+ status_b = inb ( CMOS_DATA );
+ outb ( ( RTC_STATUS_B | CMOS_DISABLE_NMI ), CMOS_ADDRESS );
+ outb ( ( status_b | RTC_STATUS_B_PIE ), CMOS_DATA );
+
+ /* Re-enable NMI and reset to default address */
+ outb ( CMOS_DEFAULT_ADDRESS, CMOS_ADDRESS );
+ inb ( CMOS_DATA ); /* Discard; may be needed on some platforms */
+}
+
+/**
+ * Disable RTC interrupts
+ *
+ */
+static void rtc_disable_int ( void ) {
+ uint8_t status_b;
+
+ /* Clear Periodic Interrupt Enable bit in status register B */
+ outb ( ( RTC_STATUS_B | CMOS_DISABLE_NMI ), CMOS_ADDRESS );
+ status_b = inb ( CMOS_DATA );
+ outb ( ( RTC_STATUS_B | CMOS_DISABLE_NMI ), CMOS_ADDRESS );
+ outb ( ( status_b & ~RTC_STATUS_B_PIE ), CMOS_DATA );
+
+ /* Re-enable NMI and reset to default address */
+ outb ( CMOS_DEFAULT_ADDRESS, CMOS_ADDRESS );
+ inb ( CMOS_DATA ); /* Discard; may be needed on some platforms */
+}
+
+/**
+ * Enable entropy gathering
+ *
+ * @ret rc Return status code
+ */
+static int rtc_entropy_enable ( void ) {
+
+ rtc_hook_isr();
+ enable_irq ( RTC_IRQ );
+ rtc_enable_int();
+
+ return 0;
+}
+
+/**
+ * Disable entropy gathering
+ *
+ */
+static void rtc_entropy_disable ( void ) {
+
+ rtc_disable_int();
+ disable_irq ( RTC_IRQ );
+ rtc_unhook_isr();
+}
+
+/**
+ * Measure a single RTC tick
+ *
+ * @ret delta Length of RTC tick (in TSC units)
+ */
+uint8_t rtc_sample ( void ) {
+ uint32_t before;
+ uint32_t after;
+ uint32_t temp;
+
+ __asm__ __volatile__ (
+ REAL_CODE ( /* Enable interrupts */
+ "sti\n\t"
+ /* Wait for RTC interrupt */
+ "cs movb %b2, %c4\n\t"
+ "\n1:\n\t"
+ "cs xchgb %b2, %c4\n\t" /* Serialize */
+ "testb %b2, %b2\n\t"
+ "jz 1b\n\t"
+ /* Read "before" TSC */
+ "rdtsc\n\t"
+ /* Store "before" TSC on stack */
+ "pushl %0\n\t"
+ /* Wait for another RTC interrupt */
+ "xorb %b2, %b2\n\t"
+ "cs movb %b2, %c4\n\t"
+ "\n1:\n\t"
+ "cs xchgb %b2, %c4\n\t" /* Serialize */
+ "testb %b2, %b2\n\t"
+ "jz 1b\n\t"
+ /* Read "after" TSC */
+ "rdtsc\n\t"
+ /* Retrieve "before" TSC on stack */
+ "popl %1\n\t"
+ /* Disable interrupts */
+ "cli\n\t"
+ )
+ : "=a" ( after ), "=d" ( before ), "=q" ( temp )
+ : "2" ( 0 ), "p" ( __from_text16 ( &rtc_flag ) ) );
+
+ return ( after - before );
+}
+
+PROVIDE_ENTROPY_INLINE ( rtc, min_entropy_per_sample );
+PROVIDE_ENTROPY ( rtc, entropy_enable, rtc_entropy_enable );
+PROVIDE_ENTROPY ( rtc, entropy_disable, rtc_entropy_disable );
+PROVIDE_ENTROPY_INLINE ( rtc, get_noise );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/rtc_time.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/rtc_time.c
new file mode 100644
index 00000000..b5b46ff4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pcbios/rtc_time.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * RTC-based time source
+ *
+ */
+
+#include <stdint.h>
+#include <time.h>
+#include <rtc.h>
+#include <ipxe/time.h>
+
+/**
+ * Read RTC register
+ *
+ * @v address Register address
+ * @ret data Data
+ */
+static unsigned int rtc_readb ( int address ) {
+ outb ( address, CMOS_ADDRESS );
+ return inb ( CMOS_DATA );
+}
+
+/**
+ * Check if RTC update is in progress
+ *
+ * @ret is_busy RTC update is in progress
+ */
+static int rtc_is_busy ( void ) {
+ return ( rtc_readb ( RTC_STATUS_A ) & RTC_STATUS_A_UPDATE_IN_PROGRESS );
+}
+
+/**
+ * Read RTC BCD register
+ *
+ * @v address Register address
+ * @ret value Value
+ */
+static unsigned int rtc_readb_bcd ( int address ) {
+ unsigned int bcd;
+
+ bcd = rtc_readb ( address );
+ return ( bcd - ( 6 * ( bcd >> 4 ) ) );
+}
+
+/**
+ * Read RTC time
+ *
+ * @ret time Time, in seconds
+ */
+static time_t rtc_read_time ( void ) {
+ unsigned int status_b;
+ int is_binary;
+ int is_24hour;
+ unsigned int ( * read_component ) ( int address );
+ struct tm tm;
+ int is_pm;
+ unsigned int hour;
+ time_t time;
+
+ /* Wait for any in-progress update to complete */
+ while ( rtc_is_busy() ) {}
+
+ /* Determine RTC mode */
+ status_b = rtc_readb ( RTC_STATUS_B );
+ is_binary = ( status_b & RTC_STATUS_B_BINARY );
+ is_24hour = ( status_b & RTC_STATUS_B_24_HOUR );
+ read_component = ( is_binary ? rtc_readb : rtc_readb_bcd );
+
+ /* Read time values */
+ tm.tm_sec = read_component ( RTC_SEC );
+ tm.tm_min = read_component ( RTC_MIN );
+ hour = read_component ( RTC_HOUR );
+ if ( ! is_24hour ) {
+ is_pm = ( hour >= 80 );
+ hour = ( ( ( ( hour & 0x7f ) % 80 ) % 12 ) +
+ ( is_pm ? 12 : 0 ) );
+ }
+ tm.tm_hour = hour;
+ tm.tm_mday = read_component ( RTC_MDAY );
+ tm.tm_mon = ( read_component ( RTC_MON ) - 1 );
+ tm.tm_year = ( read_component ( RTC_YEAR ) +
+ 100 /* Assume we are in the 21st century, since
+ * this code was written in 2012 */ );
+
+ DBGC ( RTC_STATUS_A, "RTCTIME is %04d-%02d-%02d %02d:%02d:%02d "
+ "(%s,%d-hour)\n", ( tm.tm_year + 1900 ), ( tm.tm_mon + 1 ),
+ tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
+ ( is_binary ? "binary" : "BCD" ), ( is_24hour ? 24 : 12 ) );
+
+ /* Convert to seconds since the Epoch */
+ time = mktime ( &tm );
+
+ return time;
+}
+
+/**
+ * Get current time in seconds
+ *
+ * @ret time Time, in seconds
+ */
+static time_t rtc_now ( void ) {
+ time_t time = 0;
+ time_t last_time;
+
+ /* Read time until we get two matching values in a row, in
+ * case we end up reading a corrupted value in the middle of
+ * an update.
+ */
+ do {
+ last_time = time;
+ time = rtc_read_time();
+ } while ( time != last_time );
+
+ return time;
+}
+
+PROVIDE_TIME ( rtc, time_now, rtc_now );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_call.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_call.c
new file mode 100644
index 00000000..73b4fe33
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_call.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/uaccess.h>
+#include <ipxe/init.h>
+#include <setjmp.h>
+#include <registers.h>
+#include <biosint.h>
+#include <pxe.h>
+#include <pxe_call.h>
+
+/** @file
+ *
+ * PXE API entry point
+ */
+
+/** Vector for chaining INT 1A */
+extern struct segoff __text16 ( pxe_int_1a_vector );
+#define pxe_int_1a_vector __use_text16 ( pxe_int_1a_vector )
+
+/** INT 1A handler */
+extern void pxe_int_1a ( void );
+
+/** INT 1A hooked flag */
+static int int_1a_hooked = 0;
+
+/**
+ * Handle an unknown PXE API call
+ *
+ * @v pxenv_unknown Pointer to a struct s_PXENV_UNKNOWN
+ * @ret #PXENV_EXIT_FAILURE Always
+ * @err #PXENV_STATUS_UNSUPPORTED Always
+ */
+static PXENV_EXIT_t pxenv_unknown ( struct s_PXENV_UNKNOWN *pxenv_unknown ) {
+ pxenv_unknown->Status = PXENV_STATUS_UNSUPPORTED;
+ return PXENV_EXIT_FAILURE;
+}
+
+/** Unknown PXE API call list */
+struct pxe_api_call pxenv_unknown_api __pxe_api_call =
+ PXE_API_CALL ( PXENV_UNKNOWN, pxenv_unknown, struct s_PXENV_UNKNOWN );
+
+/**
+ * Locate PXE API call
+ *
+ * @v opcode Opcode
+ * @ret call PXE API call, or NULL
+ */
+static struct pxe_api_call * find_pxe_api_call ( uint16_t opcode ) {
+ struct pxe_api_call *call;
+
+ for_each_table_entry ( call, PXE_API_CALLS ) {
+ if ( call->opcode == opcode )
+ return call;
+ }
+ return NULL;
+}
+
+/**
+ * Dispatch PXE API call
+ *
+ * @v bx PXE opcode
+ * @v es:di Address of PXE parameter block
+ * @ret ax PXE exit code
+ */
+__asmcall void pxe_api_call ( struct i386_all_regs *ix86 ) {
+ uint16_t opcode = ix86->regs.bx;
+ userptr_t uparams = real_to_user ( ix86->segs.es, ix86->regs.di );
+ struct pxe_api_call *call;
+ union u_PXENV_ANY params;
+ PXENV_EXIT_t ret;
+
+ /* Locate API call */
+ call = find_pxe_api_call ( opcode );
+ if ( ! call ) {
+ DBGC ( &pxe_netdev, "PXENV_UNKNOWN_%04x\n", opcode );
+ call = &pxenv_unknown_api;
+ }
+
+ /* Copy parameter block from caller */
+ copy_from_user ( &params, uparams, 0, call->params_len );
+
+ /* Set default status in case child routine fails to do so */
+ params.Status = PXENV_STATUS_FAILURE;
+
+ /* Hand off to relevant API routine */
+ ret = call->entry ( &params );
+
+ /* Copy modified parameter block back to caller and return */
+ copy_to_user ( uparams, 0, &params, call->params_len );
+ ix86->regs.ax = ret;
+}
+
+/**
+ * Dispatch weak PXE API call with PXE stack available
+ *
+ * @v ix86 Registers for PXE call
+ * @ret present Zero (PXE stack present)
+ */
+int pxe_api_call_weak ( struct i386_all_regs *ix86 ) {
+ pxe_api_call ( ix86 );
+ return 0;
+}
+
+/**
+ * Dispatch PXE loader call
+ *
+ * @v es:di Address of PXE parameter block
+ * @ret ax PXE exit code
+ */
+__asmcall void pxe_loader_call ( struct i386_all_regs *ix86 ) {
+ userptr_t uparams = real_to_user ( ix86->segs.es, ix86->regs.di );
+ struct s_UNDI_LOADER params;
+ PXENV_EXIT_t ret;
+
+ /* Copy parameter block from caller */
+ copy_from_user ( &params, uparams, 0, sizeof ( params ) );
+
+ /* Fill in ROM segment address */
+ ppxe.UNDIROMID.segment = ix86->segs.ds;
+
+ /* Set default status in case child routine fails to do so */
+ params.Status = PXENV_STATUS_FAILURE;
+
+ /* Call UNDI loader */
+ ret = undi_loader ( &params );
+
+ /* Copy modified parameter block back to caller and return */
+ copy_to_user ( uparams, 0, &params, sizeof ( params ) );
+ ix86->regs.ax = ret;
+}
+
+/**
+ * Calculate byte checksum as used by PXE
+ *
+ * @v data Data
+ * @v size Length of data
+ * @ret sum Checksum
+ */
+static uint8_t pxe_checksum ( void *data, size_t size ) {
+ uint8_t *bytes = data;
+ uint8_t sum = 0;
+
+ while ( size-- ) {
+ sum += *bytes++;
+ }
+ return sum;
+}
+
+/**
+ * Initialise !PXE and PXENV+ structures
+ *
+ */
+static void pxe_init_structures ( void ) {
+ uint32_t rm_cs_phys = ( rm_cs << 4 );
+ uint32_t rm_ds_phys = ( rm_ds << 4 );
+
+ /* Fill in missing segment fields */
+ ppxe.EntryPointSP.segment = rm_cs;
+ ppxe.EntryPointESP.segment = rm_cs;
+ ppxe.Stack.segment_address = rm_ds;
+ ppxe.Stack.Physical_address = rm_ds_phys;
+ ppxe.UNDIData.segment_address = rm_ds;
+ ppxe.UNDIData.Physical_address = rm_ds_phys;
+ ppxe.UNDICode.segment_address = rm_cs;
+ ppxe.UNDICode.Physical_address = rm_cs_phys;
+ ppxe.UNDICodeWrite.segment_address = rm_cs;
+ ppxe.UNDICodeWrite.Physical_address = rm_cs_phys;
+ pxenv.RMEntry.segment = rm_cs;
+ pxenv.StackSeg = rm_ds;
+ pxenv.UNDIDataSeg = rm_ds;
+ pxenv.UNDICodeSeg = rm_cs;
+ pxenv.PXEPtr.segment = rm_cs;
+
+ /* Update checksums */
+ ppxe.StructCksum -= pxe_checksum ( &ppxe, sizeof ( ppxe ) );
+ pxenv.Checksum -= pxe_checksum ( &pxenv, sizeof ( pxenv ) );
+}
+
+/** PXE structure initialiser */
+struct init_fn pxe_init_fn __init_fn ( INIT_NORMAL ) = {
+ .initialise = pxe_init_structures,
+};
+
+/**
+ * Activate PXE stack
+ *
+ * @v netdev Net device to use as PXE net device
+ */
+void pxe_activate ( struct net_device *netdev ) {
+
+ /* Ensure INT 1A is hooked */
+ if ( ! int_1a_hooked ) {
+ hook_bios_interrupt ( 0x1a, ( unsigned int ) pxe_int_1a,
+ &pxe_int_1a_vector );
+ devices_get();
+ int_1a_hooked = 1;
+ }
+
+ /* Set PXE network device */
+ pxe_set_netdev ( netdev );
+}
+
+/**
+ * Deactivate PXE stack
+ *
+ * @ret rc Return status code
+ */
+int pxe_deactivate ( void ) {
+ int rc;
+
+ /* Clear PXE network device */
+ pxe_set_netdev ( NULL );
+
+ /* Ensure INT 1A is unhooked, if possible */
+ if ( int_1a_hooked ) {
+ if ( ( rc = unhook_bios_interrupt ( 0x1a,
+ (unsigned int) pxe_int_1a,
+ &pxe_int_1a_vector ))!= 0){
+ DBG ( "Could not unhook INT 1A: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+ devices_put();
+ int_1a_hooked = 0;
+ }
+
+ return 0;
+}
+
+/** Jump buffer for PXENV_RESTART_TFTP */
+rmjmp_buf pxe_restart_nbp;
+
+/**
+ * Start PXE NBP at 0000:7c00
+ *
+ * @ret rc Return status code
+ */
+int pxe_start_nbp ( void ) {
+ int jmp;
+ int discard_b, discard_c, discard_d, discard_D;
+ uint16_t rc;
+
+ /* Allow restarting NBP via PXENV_RESTART_TFTP */
+ jmp = rmsetjmp ( pxe_restart_nbp );
+ if ( jmp )
+ DBG ( "Restarting NBP (%x)\n", jmp );
+
+ /* Far call to PXE NBP */
+ __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
+ "movw %%cx, %%es\n\t"
+ "pushw %%es\n\t"
+ "pushw %%di\n\t"
+ "sti\n\t"
+ "lcall $0, $0x7c00\n\t"
+ "popl %%ebp\n\t" /* discard */
+ "popl %%ebp\n\t" /* gcc bug */ )
+ : "=a" ( rc ), "=b" ( discard_b ),
+ "=c" ( discard_c ), "=d" ( discard_d ),
+ "=D" ( discard_D )
+ : "a" ( 0 ), "b" ( __from_text16 ( &pxenv ) ),
+ "c" ( rm_cs ),
+ "d" ( virt_to_phys ( &pxenv ) ),
+ "D" ( __from_text16 ( &ppxe ) )
+ : "esi", "memory" );
+
+ return rc;
+}
+
+REQUIRE_OBJECT ( pxe_preboot );
+REQUIRE_OBJECT ( pxe_undi );
+REQUIRE_OBJECT ( pxe_udp );
+REQUIRE_OBJECT ( pxe_tftp );
+REQUIRE_OBJECT ( pxe_file );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_entry.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_entry.S
new file mode 100644
index 00000000..0d3a57cd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_entry.S
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .arch i386
+
+/****************************************************************************
+ * !PXE structure
+ ****************************************************************************
+ */
+ .section ".text16.data", "aw", @progbits
+ .globl ppxe
+ .align 16
+ppxe:
+ .ascii "!PXE" /* Signature */
+ .byte pxe_length /* StructLength */
+ .byte 0 /* StructCksum */
+ .byte 0 /* StructRev */
+ .byte 0 /* reserved_1 */
+ .word undiheader, 0 /* UNDIROMID */
+ .word 0, 0 /* BaseROMID */
+ .word pxe_entry_sp, 0 /* EntryPointSP */
+ .word pxe_entry_esp, 0 /* EntryPointESP */
+ .word -1, -1 /* StatusCallout */
+ .byte 0 /* reserved_2 */
+ .byte SegDescCnt /* SegDescCnt */
+ .word 0 /* FirstSelector */
+pxe_segments:
+ .word 0, 0, 0, _data16_memsz /* Stack */
+ .word 0, 0, 0, _data16_memsz /* UNDIData */
+ .word 0, 0, 0, _text16_memsz /* UNDICode */
+ .word 0, 0, 0, _text16_memsz /* UNDICodeWrite */
+ .word 0, 0, 0, 0 /* BC_Data */
+ .word 0, 0, 0, 0 /* BC_Code */
+ .word 0, 0, 0, 0 /* BC_CodeWrite */
+ .equ SegDescCnt, ( ( . - pxe_segments ) / 8 )
+ .equ pxe_length, . - ppxe
+ .size ppxe, . - ppxe
+
+ /* Define undiheader=0 as a weak symbol for non-ROM builds */
+ .section ".weak", "a", @nobits
+ .weak undiheader
+undiheader:
+
+/****************************************************************************
+ * PXENV+ structure
+ ****************************************************************************
+ */
+ .section ".text16.data", "aw", @progbits
+ .globl pxenv
+ .align 16
+pxenv:
+ .ascii "PXENV+" /* Signature */
+ .word 0x0201 /* Version */
+ .byte pxenv_length /* Length */
+ .byte 0 /* Checksum */
+ .word pxenv_entry, 0 /* RMEntry */
+ .long 0 /* PMEntry */
+ .word 0 /* PMSelector */
+ .word 0 /* StackSeg */
+ .word _data16_memsz /* StackSize */
+ .word 0 /* BC_CodeSeg */
+ .word 0 /* BC_CodeSize */
+ .word 0 /* BC_DataSeg */
+ .word 0 /* BC_DataSize */
+ .word 0 /* UNDIDataSeg */
+ .word _data16_memsz /* UNDIDataSize */
+ .word 0 /* UNDICodeSeg */
+ .word _text16_memsz /* UNDICodeSize */
+ .word ppxe, 0 /* PXEPtr */
+ .equ pxenv_length, . - pxenv
+ .size pxenv, . - pxenv
+
+/****************************************************************************
+ * pxenv_entry (16-bit far call)
+ *
+ * PXE API call PXENV+ entry point
+ *
+ * Parameters:
+ * %es:di : Far pointer to PXE parameter structure
+ * %bx : PXE API call
+ * Returns:
+ * %ax : PXE exit status
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ /* Wyse Streaming Manager server (WLDRM13.BIN) assumes that
+ * the PXENV+ entry point is at UNDI_CS:0000; apparently,
+ * somebody at Wyse has difficulty distinguishing between the
+ * words "may" and "must"...
+ */
+ .section ".text16.null", "ax", @progbits
+ .code16
+pxenv_null_entry:
+ jmp pxenv_entry
+
+ .section ".text16", "ax", @progbits
+ .code16
+pxenv_entry:
+ pushl $pxe_api_call
+ pushw %cs
+ call prot_call
+ addl $4, %esp
+ lret
+ .size pxenv_entry, . - pxenv_entry
+
+/****************************************************************************
+ * pxe_entry
+ *
+ * PXE API call !PXE entry point
+ *
+ * Parameters:
+ * stack : Far pointer to PXE parameter structure
+ * stack : PXE API call
+ * Returns:
+ * %ax : PXE exit status
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+ .code16
+pxe_entry:
+pxe_entry_sp:
+ /* Preserve original %esp */
+ pushl %esp
+ /* Zero high word of %esp to allow use of common code */
+ movzwl %sp, %esp
+ jmp pxe_entry_common
+pxe_entry_esp:
+ /* Preserve %esp to match behaviour of pxe_entry_sp */
+ pushl %esp
+pxe_entry_common:
+ /* Save PXENV+ API call registers */
+ pushw %es
+ pushw %di
+ pushw %bx
+ /* Load !PXE parameters from stack into PXENV+ registers */
+ addr32 movw 18(%esp), %bx
+ movw %bx, %es
+ addr32 movw 16(%esp), %di
+ addr32 movw 14(%esp), %bx
+ /* Make call as for PXENV+ */
+ pushw %cs
+ call pxenv_entry
+ /* Restore PXENV+ registers */
+ popw %bx
+ popw %di
+ popw %es
+ /* Restore original %esp and return */
+ popl %esp
+ lret
+ .size pxe_entry, . - pxe_entry
+
+/****************************************************************************
+ * pxe_int_1a
+ *
+ * PXE INT 1A handler
+ *
+ * Parameters:
+ * %ax : 0x5650
+ * Returns:
+ * %ax : 0x564e
+ * %es:bx : Far pointer to the PXENV+ structure
+ * %edx : Physical address of the PXENV+ structure
+ * CF cleared
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+ .code16
+ .globl pxe_int_1a
+pxe_int_1a:
+ pushfw
+ cmpw $0x5650, %ax
+ jne 1f
+ /* INT 1A,5650 - PXE installation check */
+ xorl %edx, %edx
+ movw %cs, %dx
+ movw %dx, %es
+ movw $pxenv, %bx
+ shll $4, %edx
+ addl $pxenv, %edx
+ movw $0x564e, %ax
+ pushw %bp
+ movw %sp, %bp
+ andb $~0x01, 8(%bp) /* Clear CF on return */
+ popw %bp
+ popfw
+ iret
+1: /* INT 1A,other - pass through */
+ popfw
+ ljmp *%cs:pxe_int_1a_vector
+
+ .section ".text16.data", "aw", @progbits
+ .globl pxe_int_1a_vector
+pxe_int_1a_vector: .long 0
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c
new file mode 100644
index 00000000..507229d8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c
@@ -0,0 +1,60 @@
+/** @file
+ *
+ * PXE exit hook
+ *
+ */
+
+/*
+ * Copyright (C) 2010 Shao Miller <shao.miller@yrdsb.edu.on.ca>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <realmode.h>
+#include <pxe.h>
+
+/** PXE exit hook */
+extern segoff_t __data16 ( pxe_exit_hook );
+#define pxe_exit_hook __use_data16 ( pxe_exit_hook )
+
+/**
+ * FILE EXIT HOOK
+ *
+ * @v file_exit_hook Pointer to a struct
+ * s_PXENV_FILE_EXIT_HOOK
+ * @v s_PXENV_FILE_EXIT_HOOK::Hook SEG16:OFF16 to jump to
+ * @ret #PXENV_EXIT_SUCCESS Successfully set hook
+ * @ret #PXENV_EXIT_FAILURE We're not an NBP build
+ * @ret s_PXENV_FILE_EXIT_HOOK::Status PXE status code
+ *
+ */
+static PXENV_EXIT_t
+pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK *file_exit_hook ) {
+ DBG ( "PXENV_FILE_EXIT_HOOK" );
+
+ /* We'll jump to the specified SEG16:OFF16 during exit */
+ pxe_exit_hook.segment = file_exit_hook->Hook.segment;
+ pxe_exit_hook.offset = file_exit_hook->Hook.offset;
+ file_exit_hook->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/** PXE file API */
+struct pxe_api_call pxe_file_api_exit_hook __pxe_api_call =
+ PXE_API_CALL ( PXENV_FILE_EXIT_HOOK, pxenv_file_exit_hook,
+ struct s_PXENV_FILE_EXIT_HOOK );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_file.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_file.c
new file mode 100644
index 00000000..7daaf919
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_file.c
@@ -0,0 +1,303 @@
+/** @file
+ *
+ * PXE FILE API
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/posix_io.h>
+#include <ipxe/features.h>
+#include <pxe.h>
+#include <realmode.h>
+
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+FEATURE ( FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 2 );
+
+/**
+ * FILE OPEN
+ *
+ * @v file_open Pointer to a struct s_PXENV_FILE_OPEN
+ * @v s_PXENV_FILE_OPEN::FileName URL of file to open
+ * @ret #PXENV_EXIT_SUCCESS File was opened
+ * @ret #PXENV_EXIT_FAILURE File was not opened
+ * @ret s_PXENV_FILE_OPEN::Status PXE status code
+ * @ret s_PXENV_FILE_OPEN::FileHandle Handle of opened file
+ *
+ */
+static PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open ) {
+ userptr_t filename;
+ size_t filename_len;
+ int fd;
+
+ DBG ( "PXENV_FILE_OPEN" );
+
+ /* Copy name from external program, and open it */
+ filename = real_to_user ( file_open->FileName.segment,
+ file_open->FileName.offset );
+ filename_len = strlen_user ( filename, 0 );
+ {
+ char uri_string[ filename_len + 1 ];
+
+ copy_from_user ( uri_string, filename, 0,
+ sizeof ( uri_string ) );
+ DBG ( " %s", uri_string );
+ fd = open ( uri_string );
+ }
+
+ if ( fd < 0 ) {
+ file_open->Status = PXENV_STATUS ( fd );
+ return PXENV_EXIT_FAILURE;
+ }
+
+ DBG ( " as file %d", fd );
+
+ file_open->FileHandle = fd;
+ file_open->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * FILE CLOSE
+ *
+ * @v file_close Pointer to a struct s_PXENV_FILE_CLOSE
+ * @v s_PXENV_FILE_CLOSE::FileHandle File handle
+ * @ret #PXENV_EXIT_SUCCESS File was closed
+ * @ret #PXENV_EXIT_FAILURE File was not closed
+ * @ret s_PXENV_FILE_CLOSE::Status PXE status code
+ *
+ */
+static PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE *file_close ) {
+
+ DBG ( "PXENV_FILE_CLOSE %d", file_close->FileHandle );
+
+ close ( file_close->FileHandle );
+ file_close->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * FILE SELECT
+ *
+ * @v file_select Pointer to a struct s_PXENV_FILE_SELECT
+ * @v s_PXENV_FILE_SELECT::FileHandle File handle
+ * @ret #PXENV_EXIT_SUCCESS File has been checked for readiness
+ * @ret #PXENV_EXIT_FAILURE File has not been checked for readiness
+ * @ret s_PXENV_FILE_SELECT::Status PXE status code
+ * @ret s_PXENV_FILE_SELECT::Ready Indication of readiness
+ *
+ */
+static PXENV_EXIT_t
+pxenv_file_select ( struct s_PXENV_FILE_SELECT *file_select ) {
+ fd_set fdset;
+ int ready;
+
+ DBG ( "PXENV_FILE_SELECT %d", file_select->FileHandle );
+
+ FD_ZERO ( &fdset );
+ FD_SET ( file_select->FileHandle, &fdset );
+ if ( ( ready = select ( &fdset, 0 ) ) < 0 ) {
+ file_select->Status = PXENV_STATUS ( ready );
+ return PXENV_EXIT_FAILURE;
+ }
+
+ file_select->Ready = ( ready ? RDY_READ : 0 );
+ file_select->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * FILE READ
+ *
+ * @v file_read Pointer to a struct s_PXENV_FILE_READ
+ * @v s_PXENV_FILE_READ::FileHandle File handle
+ * @v s_PXENV_FILE_READ::BufferSize Size of data buffer
+ * @v s_PXENV_FILE_READ::Buffer Data buffer
+ * @ret #PXENV_EXIT_SUCCESS Data has been read from file
+ * @ret #PXENV_EXIT_FAILURE Data has not been read from file
+ * @ret s_PXENV_FILE_READ::Status PXE status code
+ * @ret s_PXENV_FILE_READ::Ready Indication of readiness
+ * @ret s_PXENV_FILE_READ::BufferSize Length of data read
+ *
+ */
+static PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read ) {
+ userptr_t buffer;
+ ssize_t len;
+
+ DBG ( "PXENV_FILE_READ %d to %04x:%04x+%04x", file_read->FileHandle,
+ file_read->Buffer.segment, file_read->Buffer.offset,
+ file_read->BufferSize );
+
+ buffer = real_to_user ( file_read->Buffer.segment,
+ file_read->Buffer.offset );
+ if ( ( len = read_user ( file_read->FileHandle, buffer, 0,
+ file_read->BufferSize ) ) < 0 ) {
+ file_read->Status = PXENV_STATUS ( len );
+ return PXENV_EXIT_FAILURE;
+ }
+
+ DBG ( " read %04zx", ( ( size_t ) len ) );
+
+ file_read->BufferSize = len;
+ file_read->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * GET FILE SIZE
+ *
+ * @v get_file_size Pointer to a struct s_PXENV_GET_FILE_SIZE
+ * @v s_PXENV_GET_FILE_SIZE::FileHandle File handle
+ * @ret #PXENV_EXIT_SUCCESS File size has been determined
+ * @ret #PXENV_EXIT_FAILURE File size has not been determined
+ * @ret s_PXENV_GET_FILE_SIZE::Status PXE status code
+ * @ret s_PXENV_GET_FILE_SIZE::FileSize Size of file
+ */
+static PXENV_EXIT_t
+pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE *get_file_size ) {
+ ssize_t filesize;
+
+ DBG ( "PXENV_GET_FILE_SIZE %d", get_file_size->FileHandle );
+
+ filesize = fsize ( get_file_size->FileHandle );
+ if ( filesize < 0 ) {
+ get_file_size->Status = PXENV_STATUS ( filesize );
+ return PXENV_EXIT_FAILURE;
+ }
+
+ DBG ( " is %zd", ( ( size_t ) filesize ) );
+
+ get_file_size->FileSize = filesize;
+ get_file_size->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * FILE EXEC
+ *
+ * @v file_exec Pointer to a struct s_PXENV_FILE_EXEC
+ * @v s_PXENV_FILE_EXEC::Command Command to execute
+ * @ret #PXENV_EXIT_SUCCESS Command was executed successfully
+ * @ret #PXENV_EXIT_FAILURE Command was not executed successfully
+ * @ret s_PXENV_FILE_EXEC::Status PXE status code
+ *
+ */
+static PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) {
+ userptr_t command;
+ size_t command_len;
+ int rc;
+
+ DBG ( "PXENV_FILE_EXEC" );
+
+ /* Copy name from external program, and exec it */
+ command = real_to_user ( file_exec->Command.segment,
+ file_exec->Command.offset );
+ command_len = strlen_user ( command, 0 );
+ {
+ char command_string[ command_len + 1 ];
+
+ copy_from_user ( command_string, command, 0,
+ sizeof ( command_string ) );
+ DBG ( " %s", command_string );
+
+ if ( ( rc = system ( command_string ) ) != 0 ) {
+ file_exec->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+ }
+
+ file_exec->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * FILE API CHECK
+ *
+ * @v file_exec Pointer to a struct s_PXENV_FILE_API_CHECK
+ * @v s_PXENV_FILE_API_CHECK::Magic Inbound magic number (0x91d447b2)
+ * @ret #PXENV_EXIT_SUCCESS Command was executed successfully
+ * @ret #PXENV_EXIT_FAILURE Command was not executed successfully
+ * @ret s_PXENV_FILE_API_CHECK::Status PXE status code
+ * @ret s_PXENV_FILE_API_CHECK::Magic Outbound magic number (0xe9c17b20)
+ * @ret s_PXENV_FILE_API_CHECK::Provider "iPXE" (0x45585067)
+ * @ret s_PXENV_FILE_API_CHECK::APIMask API function bitmask
+ * @ret s_PXENV_FILE_API_CHECK::Flags Reserved
+ *
+ */
+static PXENV_EXIT_t
+pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_api_check ) {
+ struct pxe_api_call *call;
+ unsigned int mask = 0;
+ unsigned int offset;
+
+ DBG ( "PXENV_FILE_API_CHECK" );
+
+ /* Check for magic value */
+ if ( file_api_check->Magic != 0x91d447b2 ) {
+ file_api_check->Status = PXENV_STATUS_BAD_FUNC;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Check for required parameter size */
+ if ( file_api_check->Size < sizeof ( *file_api_check ) ) {
+ file_api_check->Status = PXENV_STATUS_OUT_OF_RESOURCES;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Determine supported calls */
+ for_each_table_entry ( call, PXE_API_CALLS ) {
+ offset = ( call->opcode - PXENV_FILE_MIN );
+ if ( offset <= ( PXENV_FILE_MAX - PXENV_FILE_MIN ) )
+ mask |= ( 1 << offset );
+ }
+
+ /* Fill in parameters */
+ file_api_check->Size = sizeof ( *file_api_check );
+ file_api_check->Magic = 0xe9c17b20;
+ file_api_check->Provider = 0x45585067; /* "iPXE" */
+ file_api_check->APIMask = mask;
+ file_api_check->Flags = 0; /* None defined */
+
+ file_api_check->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/** PXE file API */
+struct pxe_api_call pxe_file_api[] __pxe_api_call = {
+ PXE_API_CALL ( PXENV_FILE_OPEN, pxenv_file_open,
+ struct s_PXENV_FILE_OPEN ),
+ PXE_API_CALL ( PXENV_FILE_CLOSE, pxenv_file_close,
+ struct s_PXENV_FILE_CLOSE ),
+ PXE_API_CALL ( PXENV_FILE_SELECT, pxenv_file_select,
+ struct s_PXENV_FILE_SELECT ),
+ PXE_API_CALL ( PXENV_FILE_READ, pxenv_file_read,
+ struct s_PXENV_FILE_READ ),
+ PXE_API_CALL ( PXENV_GET_FILE_SIZE, pxenv_get_file_size,
+ struct s_PXENV_GET_FILE_SIZE ),
+ PXE_API_CALL ( PXENV_FILE_EXEC, pxenv_file_exec,
+ struct s_PXENV_FILE_EXEC ),
+ PXE_API_CALL ( PXENV_FILE_API_CHECK, pxenv_file_api_check,
+ struct s_PXENV_FILE_API_CHECK ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_loader.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_loader.c
new file mode 100644
index 00000000..63858be2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_loader.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/init.h>
+#include "pxe.h"
+#include "pxe_call.h"
+
+/** @file
+ *
+ * PXE UNDI loader
+ *
+ */
+
+/* PXENV_UNDI_LOADER
+ *
+ */
+PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader ) {
+
+ /* Perform one-time initialisation (e.g. heap) */
+ initialise();
+
+ DBG ( "[PXENV_UNDI_LOADER to CS %04x DS %04x]",
+ undi_loader->UNDI_CS, undi_loader->UNDI_DS );
+
+ /* Fill in UNDI loader structure */
+ undi_loader->PXEptr.segment = rm_cs;
+ undi_loader->PXEptr.offset = __from_text16 ( &ppxe );
+ undi_loader->PXENVptr.segment = rm_cs;
+ undi_loader->PXENVptr.offset = __from_text16 ( &pxenv );
+
+ undi_loader->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c
new file mode 100644
index 00000000..839e4faf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c
@@ -0,0 +1,384 @@
+/** @file
+ *
+ * PXE Preboot API
+ *
+ */
+
+/* PXE API interface for Etherboot.
+ *
+ * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/fakedhcp.h>
+#include <ipxe/device.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/isapnp.h>
+#include <ipxe/init.h>
+#include <ipxe/if_ether.h>
+#include <basemem_packet.h>
+#include <biosint.h>
+#include "pxe.h"
+#include "pxe_call.h"
+
+/* Avoid dragging in isapnp.o unnecessarily */
+uint16_t isapnp_read_port;
+
+/** Zero-based versions of PXENV_GET_CACHED_INFO::PacketType */
+enum pxe_cached_info_indices {
+ CACHED_INFO_DHCPDISCOVER = ( PXENV_PACKET_TYPE_DHCP_DISCOVER - 1 ),
+ CACHED_INFO_DHCPACK = ( PXENV_PACKET_TYPE_DHCP_ACK - 1 ),
+ CACHED_INFO_BINL = ( PXENV_PACKET_TYPE_CACHED_REPLY - 1 ),
+ NUM_CACHED_INFOS
+};
+
+/** A cached DHCP packet */
+union pxe_cached_info {
+ struct dhcphdr dhcphdr;
+ /* This buffer must be *exactly* the size of a BOOTPLAYER_t
+ * structure, otherwise WinPE will die horribly. It takes the
+ * size of *our* buffer and feeds it in to us as the size of
+ * one of *its* buffers. If our buffer is larger than it
+ * expects, we therefore end up overwriting part of its data
+ * segment, since it tells us to do so. (D'oh!)
+ *
+ * Note that a BOOTPLAYER_t is not necessarily large enough to
+ * hold a DHCP packet; this is a flaw in the PXE spec.
+ */
+ BOOTPLAYER_t packet;
+} __attribute__ (( packed ));
+
+/** A PXE DHCP packet creator */
+struct pxe_dhcp_packet_creator {
+ /** Create DHCP packet
+ *
+ * @v netdev Network device
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ */
+ int ( * create ) ( struct net_device *netdev, void *data,
+ size_t max_len );
+};
+
+/** PXE DHCP packet creators */
+static struct pxe_dhcp_packet_creator pxe_dhcp_packet_creators[] = {
+ [CACHED_INFO_DHCPDISCOVER] = { create_fakedhcpdiscover },
+ [CACHED_INFO_DHCPACK] = { create_fakedhcpack },
+ [CACHED_INFO_BINL] = { create_fakepxebsack },
+};
+
+/**
+ * Name PXENV_GET_CACHED_INFO packet type
+ *
+ * @v packet_type Packet type
+ * @ret name Name of packet type
+ */
+static inline __attribute__ (( always_inline )) const char *
+pxenv_get_cached_info_name ( int packet_type ) {
+ switch ( packet_type ) {
+ case PXENV_PACKET_TYPE_DHCP_DISCOVER:
+ return "DHCPDISCOVER";
+ case PXENV_PACKET_TYPE_DHCP_ACK:
+ return "DHCPACK";
+ case PXENV_PACKET_TYPE_CACHED_REPLY:
+ return "BINL";
+ default:
+ return "<INVALID>";
+ }
+}
+
+/* The case in which the caller doesn't supply a buffer is really
+ * awkward to support given that we have multiple sources of options,
+ * and that we don't actually store the DHCP packets. (We may not
+ * even have performed DHCP; we may have obtained all configuration
+ * from non-volatile stored options or from the command line.)
+ *
+ * Some NBPs rely on the buffers we provide being persistent, so we
+ * can't just use the temporary packet buffer. 4.5kB of base memory
+ * always wasted just because some clients are too lazy to provide
+ * their own buffers...
+ */
+static union pxe_cached_info __bss16_array ( cached_info, [NUM_CACHED_INFOS] );
+#define cached_info __use_data16 ( cached_info )
+
+/**
+ * UNLOAD BASE CODE STACK
+ *
+ * @v None -
+ * @ret ...
+ *
+ */
+static PXENV_EXIT_t
+pxenv_unload_stack ( struct s_PXENV_UNLOAD_STACK *unload_stack ) {
+ DBGC ( &pxe_netdev, "PXENV_UNLOAD_STACK\n" );
+
+ unload_stack->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_GET_CACHED_INFO
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
+ struct pxe_dhcp_packet_creator *creator;
+ union pxe_cached_info *info;
+ unsigned int idx;
+ size_t len;
+ userptr_t buffer;
+ int rc;
+
+ DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO %s to %04x:%04x+%x",
+ pxenv_get_cached_info_name ( get_cached_info->PacketType ),
+ get_cached_info->Buffer.segment,
+ get_cached_info->Buffer.offset, get_cached_info->BufferSize );
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO called with no "
+ "network device\n" );
+ get_cached_info->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Sanity check */
+ idx = ( get_cached_info->PacketType - 1 );
+ if ( idx >= NUM_CACHED_INFOS ) {
+ DBGC ( &pxe_netdev, " bad PacketType %d\n",
+ get_cached_info->PacketType );
+ goto err;
+ }
+ info = &cached_info[idx];
+
+ /* Construct cached version of packet, if not already constructed. */
+ if ( ! info->dhcphdr.op ) {
+ /* Construct DHCP packet */
+ creator = &pxe_dhcp_packet_creators[idx];
+ if ( ( rc = creator->create ( pxe_netdev, info,
+ sizeof ( *info ) ) ) != 0 ) {
+ DBGC ( &pxe_netdev, " failed to build packet: %s\n",
+ strerror ( rc ) );
+ goto err;
+ }
+ }
+
+ len = get_cached_info->BufferSize;
+ if ( len == 0 ) {
+ /* Point client at our cached buffer.
+ *
+ * To add to the fun, Intel decided at some point in
+ * the evolution of the PXE specification to add the
+ * BufferLimit field, which we are meant to fill in
+ * with the length of our packet buffer, so that the
+ * caller can safely modify the boot server reply
+ * packet stored therein. However, this field was not
+ * present in earlier versions of the PXE spec, and
+ * there is at least one PXE NBP (Altiris) which
+ * allocates only exactly enough space for this
+ * earlier, shorter version of the structure. If we
+ * actually fill in the BufferLimit field, we
+ * therefore risk trashing random areas of the
+ * caller's memory. If we *don't* fill it in, then
+ * the caller is at liberty to assume that whatever
+ * random value happened to be in that location
+ * represents the length of the buffer we've just
+ * passed back to it.
+ *
+ * Since older PXE stacks won't fill this field in
+ * anyway, it's probably safe to assume that no
+ * callers actually rely on it, so we choose to not
+ * fill it in.
+ */
+ get_cached_info->Buffer.segment = rm_ds;
+ get_cached_info->Buffer.offset = __from_data16 ( info );
+ get_cached_info->BufferSize = sizeof ( *info );
+ DBGC ( &pxe_netdev, " using %04x:%04x+%04x['%x']",
+ get_cached_info->Buffer.segment,
+ get_cached_info->Buffer.offset,
+ get_cached_info->BufferSize,
+ get_cached_info->BufferLimit );
+ } else {
+ /* Copy packet to client buffer */
+ if ( len > sizeof ( *info ) )
+ len = sizeof ( *info );
+ if ( len < sizeof ( *info ) )
+ DBGC ( &pxe_netdev, " buffer may be too short" );
+ buffer = real_to_user ( get_cached_info->Buffer.segment,
+ get_cached_info->Buffer.offset );
+ copy_to_user ( buffer, 0, info, len );
+ get_cached_info->BufferSize = len;
+ }
+
+ DBGC ( &pxe_netdev, "\n" );
+ get_cached_info->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+
+ err:
+ get_cached_info->Status = PXENV_STATUS_OUT_OF_RESOURCES;
+ return PXENV_EXIT_FAILURE;
+}
+
+/* PXENV_RESTART_TFTP
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE *restart_tftp ) {
+ PXENV_EXIT_t tftp_exit;
+
+ DBGC ( &pxe_netdev, "PXENV_RESTART_TFTP\n" );
+
+ /* Words cannot describe the complete mismatch between the PXE
+ * specification and any possible version of reality...
+ */
+ restart_tftp->Buffer = PXE_LOAD_PHYS; /* Fixed by spec, apparently */
+ restart_tftp->BufferSize = ( 0xa0000 - PXE_LOAD_PHYS ); /* Near enough */
+ tftp_exit = pxenv_tftp_read_file ( restart_tftp );
+ if ( tftp_exit != PXENV_EXIT_SUCCESS )
+ return tftp_exit;
+
+ /* Restart NBP */
+ rmlongjmp ( pxe_restart_nbp, PXENV_RESTART_TFTP );
+}
+
+/* PXENV_START_UNDI
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) {
+ unsigned int bus_type;
+ unsigned int location;
+ struct net_device *netdev;
+
+ DBGC ( &pxe_netdev, "PXENV_START_UNDI %04x:%04x:%04x\n",
+ start_undi->AX, start_undi->BX, start_undi->DX );
+
+ /* Determine bus type and location. Use a heuristic to decide
+ * whether we are PCI or ISAPnP
+ */
+ if ( ( start_undi->DX >= ISAPNP_READ_PORT_MIN ) &&
+ ( start_undi->DX <= ISAPNP_READ_PORT_MAX ) &&
+ ( start_undi->BX >= ISAPNP_CSN_MIN ) &&
+ ( start_undi->BX <= ISAPNP_CSN_MAX ) ) {
+ bus_type = BUS_TYPE_ISAPNP;
+ location = start_undi->BX;
+ /* Record ISAPnP read port for use by isapnp.c */
+ isapnp_read_port = start_undi->DX;
+ } else {
+ bus_type = BUS_TYPE_PCI;
+ location = start_undi->AX;
+ }
+
+ /* Probe for devices, etc. */
+ startup();
+
+ /* Look for a matching net device */
+ netdev = find_netdev_by_location ( bus_type, location );
+ if ( ! netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_START_UNDI could not find matching "
+ "net device\n" );
+ start_undi->Status = PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC;
+ return PXENV_EXIT_FAILURE;
+ }
+ DBGC ( &pxe_netdev, "PXENV_START_UNDI found net device %s\n",
+ netdev->name );
+
+ /* Activate PXE */
+ pxe_activate ( netdev );
+
+ start_undi->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_STOP_UNDI
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi ) {
+ DBGC ( &pxe_netdev, "PXENV_STOP_UNDI\n" );
+
+ /* Deactivate PXE */
+ pxe_deactivate();
+
+ /* Prepare for unload */
+ shutdown_boot();
+
+ /* Check to see if we still have any hooked interrupts */
+ if ( hooked_bios_interrupts != 0 ) {
+ DBGC ( &pxe_netdev, "PXENV_STOP_UNDI failed: %d interrupts "
+ "still hooked\n", hooked_bios_interrupts );
+ stop_undi->Status = PXENV_STATUS_KEEP_UNDI;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ stop_undi->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_START_BASE
+ *
+ * Status: won't implement (requires major structural changes)
+ */
+static PXENV_EXIT_t pxenv_start_base ( struct s_PXENV_START_BASE *start_base ) {
+ DBGC ( &pxe_netdev, "PXENV_START_BASE\n" );
+
+ start_base->Status = PXENV_STATUS_UNSUPPORTED;
+ return PXENV_EXIT_FAILURE;
+}
+
+/* PXENV_STOP_BASE
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t pxenv_stop_base ( struct s_PXENV_STOP_BASE *stop_base ) {
+ DBGC ( &pxe_netdev, "PXENV_STOP_BASE\n" );
+
+ /* The only time we will be called is when the NBP is trying
+ * to shut down the PXE stack. There's nothing we need to do
+ * in this call.
+ */
+
+ stop_base->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/** PXE preboot API */
+struct pxe_api_call pxe_preboot_api[] __pxe_api_call = {
+ PXE_API_CALL ( PXENV_UNLOAD_STACK, pxenv_unload_stack,
+ struct s_PXENV_UNLOAD_STACK ),
+ PXE_API_CALL ( PXENV_GET_CACHED_INFO, pxenv_get_cached_info,
+ struct s_PXENV_GET_CACHED_INFO ),
+ PXE_API_CALL ( PXENV_RESTART_TFTP, pxenv_restart_tftp,
+ struct s_PXENV_TFTP_READ_FILE ),
+ PXE_API_CALL ( PXENV_START_UNDI, pxenv_start_undi,
+ struct s_PXENV_START_UNDI ),
+ PXE_API_CALL ( PXENV_STOP_UNDI, pxenv_stop_undi,
+ struct s_PXENV_STOP_UNDI ),
+ PXE_API_CALL ( PXENV_START_BASE, pxenv_start_base,
+ struct s_PXENV_START_BASE ),
+ PXE_API_CALL ( PXENV_STOP_BASE, pxenv_stop_base,
+ struct s_PXENV_STOP_BASE ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c
new file mode 100644
index 00000000..2249fc83
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c
@@ -0,0 +1,578 @@
+/** @file
+ *
+ * PXE TFTP API
+ *
+ */
+
+/*
+ * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/in.h>
+#include <ipxe/tftp.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/process.h>
+#include <pxe.h>
+
+/** A PXE TFTP connection */
+struct pxe_tftp_connection {
+ /** Data transfer interface */
+ struct interface xfer;
+ /** Data buffer */
+ userptr_t buffer;
+ /** Size of data buffer */
+ size_t size;
+ /** Starting offset of data buffer */
+ size_t start;
+ /** File position */
+ size_t offset;
+ /** Maximum file position */
+ size_t max_offset;
+ /** Block size */
+ size_t blksize;
+ /** Block index */
+ unsigned int blkidx;
+ /** Overall return status code */
+ int rc;
+};
+
+/**
+ * Close PXE TFTP connection
+ *
+ * @v pxe_tftp PXE TFTP connection
+ * @v rc Final status code
+ */
+static void pxe_tftp_close ( struct pxe_tftp_connection *pxe_tftp, int rc ) {
+ intf_shutdown ( &pxe_tftp->xfer, rc );
+ pxe_tftp->rc = rc;
+}
+
+/**
+ * Receive new data
+ *
+ * @v pxe_tftp PXE TFTP connection
+ * @v iobuf I/O buffer
+ * @v meta Transfer metadata
+ * @ret rc Return status code
+ */
+static int pxe_tftp_xfer_deliver ( struct pxe_tftp_connection *pxe_tftp,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ size_t len = iob_len ( iobuf );
+ int rc = 0;
+
+ /* Calculate new buffer position */
+ if ( meta->flags & XFER_FL_ABS_OFFSET )
+ pxe_tftp->offset = 0;
+ pxe_tftp->offset += meta->offset;
+
+ /* Copy data block to buffer */
+ if ( len == 0 ) {
+ /* No data (pure seek); treat as success */
+ } else if ( pxe_tftp->offset < pxe_tftp->start ) {
+ DBG ( " buffer underrun at %zx (min %zx)",
+ pxe_tftp->offset, pxe_tftp->start );
+ rc = -ENOBUFS;
+ } else if ( ( pxe_tftp->offset + len ) >
+ ( pxe_tftp->start + pxe_tftp->size ) ) {
+ DBG ( " buffer overrun at %zx (max %zx)",
+ ( pxe_tftp->offset + len ),
+ ( pxe_tftp->start + pxe_tftp->size ) );
+ rc = -ENOBUFS;
+ } else {
+ copy_to_user ( pxe_tftp->buffer,
+ ( pxe_tftp->offset - pxe_tftp->start ),
+ iobuf->data, len );
+ }
+
+ /* Calculate new buffer position */
+ pxe_tftp->offset += len;
+
+ /* Record maximum offset as the file size */
+ if ( pxe_tftp->max_offset < pxe_tftp->offset )
+ pxe_tftp->max_offset = pxe_tftp->offset;
+
+ /* Terminate transfer on error */
+ if ( rc != 0 )
+ pxe_tftp_close ( pxe_tftp, rc );
+
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** PXE TFTP connection interface operations */
+static struct interface_operation pxe_tftp_xfer_ops[] = {
+ INTF_OP ( xfer_deliver, struct pxe_tftp_connection *,
+ pxe_tftp_xfer_deliver ),
+ INTF_OP ( intf_close, struct pxe_tftp_connection *, pxe_tftp_close ),
+};
+
+/** PXE TFTP connection interface descriptor */
+static struct interface_descriptor pxe_tftp_xfer_desc =
+ INTF_DESC ( struct pxe_tftp_connection, xfer, pxe_tftp_xfer_ops );
+
+/** The PXE TFTP connection */
+static struct pxe_tftp_connection pxe_tftp = {
+ .xfer = INTF_INIT ( pxe_tftp_xfer_desc ),
+};
+
+/**
+ * Maximum length of a PXE TFTP URI
+ *
+ * The PXE TFTP API provides 128 characters for the filename; the
+ * extra 128 bytes allow for the remainder of the URI.
+ */
+#define PXE_TFTP_URI_LEN 256
+
+/**
+ * Open PXE TFTP connection
+ *
+ * @v ipaddress IP address
+ * @v port TFTP server port
+ * @v filename File name
+ * @v blksize Requested block size
+ * @ret rc Return status code
+ */
+static int pxe_tftp_open ( uint32_t ipaddress, unsigned int port,
+ const unsigned char *filename, size_t blksize,
+ int sizeonly ) {
+ char uri_string[PXE_TFTP_URI_LEN];
+ struct in_addr address;
+ int rc;
+
+ /* Reset PXE TFTP connection structure */
+ memset ( &pxe_tftp, 0, sizeof ( pxe_tftp ) );
+ intf_init ( &pxe_tftp.xfer, &pxe_tftp_xfer_desc, NULL );
+ pxe_tftp.rc = -EINPROGRESS;
+
+ /* Construct URI string */
+ address.s_addr = ipaddress;
+ if ( ! port )
+ port = htons ( TFTP_PORT );
+ if ( blksize < TFTP_DEFAULT_BLKSIZE )
+ blksize = TFTP_DEFAULT_BLKSIZE;
+ snprintf ( uri_string, sizeof ( uri_string ),
+ "tftp%s://%s:%d%s%s?blksize=%zd",
+ sizeonly ? "size" : "",
+ inet_ntoa ( address ), ntohs ( port ),
+ ( ( filename[0] == '/' ) ? "" : "/" ), filename, blksize );
+ DBG ( " %s", uri_string );
+
+ /* Open PXE TFTP connection */
+ if ( ( rc = xfer_open_uri_string ( &pxe_tftp.xfer,
+ uri_string ) ) != 0 ) {
+ DBG ( " could not open (%s)\n", strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * TFTP OPEN
+ *
+ * @v tftp_open Pointer to a struct s_PXENV_TFTP_OPEN
+ * @v s_PXENV_TFTP_OPEN::ServerIPAddress TFTP server IP address
+ * @v s_PXENV_TFTP_OPEN::GatewayIPAddress Relay agent IP address, or 0.0.0.0
+ * @v s_PXENV_TFTP_OPEN::FileName Name of file to open
+ * @v s_PXENV_TFTP_OPEN::TFTPPort TFTP server UDP port
+ * @v s_PXENV_TFTP_OPEN::PacketSize TFTP blksize option to request
+ * @ret #PXENV_EXIT_SUCCESS File was opened
+ * @ret #PXENV_EXIT_FAILURE File was not opened
+ * @ret s_PXENV_TFTP_OPEN::Status PXE status code
+ * @ret s_PXENV_TFTP_OPEN::PacketSize Negotiated blksize
+ * @err #PXENV_STATUS_TFTP_INVALID_PACKET_SIZE Requested blksize too small
+ *
+ * Opens a TFTP connection for downloading a file a block at a time
+ * using pxenv_tftp_read().
+ *
+ * If s_PXENV_TFTP_OPEN::GatewayIPAddress is 0.0.0.0, normal IP
+ * routing will take place. See the relevant
+ * @ref pxe_routing "implementation note" for more details.
+ *
+ * On x86, you must set the s_PXE::StatusCallout field to a nonzero
+ * value before calling this function in protected mode. You cannot
+ * call this function with a 32-bit stack segment. (See the relevant
+ * @ref pxe_x86_pmode16 "implementation note" for more details.)
+ *
+ * @note According to the PXE specification version 2.1, this call
+ * "opens a file for reading/writing", though how writing is to be
+ * achieved without the existence of an API call %pxenv_tftp_write()
+ * is not made clear.
+ *
+ * @note Despite the existence of the numerous statements within the
+ * PXE specification of the form "...if a TFTP/MTFTP or UDP connection
+ * is active...", you cannot use pxenv_tftp_open() and
+ * pxenv_tftp_read() to read a file via MTFTP; only via plain old
+ * TFTP. If you want to use MTFTP, use pxenv_tftp_read_file()
+ * instead. Astute readers will note that, since
+ * pxenv_tftp_read_file() is an atomic operation from the point of
+ * view of the PXE API, it is conceptually impossible to issue any
+ * other PXE API call "if an MTFTP connection is active".
+ */
+static PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) {
+ int rc;
+
+ DBG ( "PXENV_TFTP_OPEN" );
+
+ /* Guard against callers that fail to close before re-opening */
+ pxe_tftp_close ( &pxe_tftp, 0 );
+
+ /* Open connection */
+ if ( ( rc = pxe_tftp_open ( tftp_open->ServerIPAddress,
+ tftp_open->TFTPPort,
+ tftp_open->FileName,
+ tftp_open->PacketSize,
+ 0) ) != 0 ) {
+ tftp_open->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Wait for OACK to arrive so that we have the block size */
+ while ( ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) &&
+ ( pxe_tftp.max_offset == 0 ) ) {
+ step();
+ }
+ pxe_tftp.blksize = xfer_window ( &pxe_tftp.xfer );
+ tftp_open->PacketSize = pxe_tftp.blksize;
+ DBG ( " blksize=%d", tftp_open->PacketSize );
+
+ /* EINPROGRESS is normal; we don't wait for the whole transfer */
+ if ( rc == -EINPROGRESS )
+ rc = 0;
+
+ tftp_open->Status = PXENV_STATUS ( rc );
+ return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS );
+}
+
+/**
+ * TFTP CLOSE
+ *
+ * @v tftp_close Pointer to a struct s_PXENV_TFTP_CLOSE
+ * @ret #PXENV_EXIT_SUCCESS File was closed successfully
+ * @ret #PXENV_EXIT_FAILURE File was not closed
+ * @ret s_PXENV_TFTP_CLOSE::Status PXE status code
+ * @err None -
+ *
+ * Close a connection previously opened with pxenv_tftp_open(). You
+ * must have previously opened a connection with pxenv_tftp_open().
+ *
+ * On x86, you must set the s_PXE::StatusCallout field to a nonzero
+ * value before calling this function in protected mode. You cannot
+ * call this function with a 32-bit stack segment. (See the relevant
+ * @ref pxe_x86_pmode16 "implementation note" for more details.)
+ */
+static PXENV_EXIT_t pxenv_tftp_close ( struct s_PXENV_TFTP_CLOSE *tftp_close ) {
+ DBG ( "PXENV_TFTP_CLOSE" );
+
+ pxe_tftp_close ( &pxe_tftp, 0 );
+ tftp_close->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * TFTP READ
+ *
+ * @v tftp_read Pointer to a struct s_PXENV_TFTP_READ
+ * @v s_PXENV_TFTP_READ::Buffer Address of data buffer
+ * @ret #PXENV_EXIT_SUCCESS Data was read successfully
+ * @ret #PXENV_EXIT_FAILURE Data was not read
+ * @ret s_PXENV_TFTP_READ::Status PXE status code
+ * @ret s_PXENV_TFTP_READ::PacketNumber TFTP packet number
+ * @ret s_PXENV_TFTP_READ::BufferSize Length of data written into buffer
+ *
+ * Reads a single packet from a connection previously opened with
+ * pxenv_tftp_open() into the data buffer pointed to by
+ * s_PXENV_TFTP_READ::Buffer. You must have previously opened a
+ * connection with pxenv_tftp_open(). The data written into
+ * s_PXENV_TFTP_READ::Buffer is just the file data; the various
+ * network headers have already been removed.
+ *
+ * The buffer must be large enough to contain a packet of the size
+ * negotiated via the s_PXENV_TFTP_OPEN::PacketSize field in the
+ * pxenv_tftp_open() call. It is worth noting that the PXE
+ * specification does @b not require the caller to fill in
+ * s_PXENV_TFTP_READ::BufferSize before calling pxenv_tftp_read(), so
+ * the PXE stack is free to ignore whatever value the caller might
+ * place there and just assume that the buffer is large enough. That
+ * said, it may be worth the caller always filling in
+ * s_PXENV_TFTP_READ::BufferSize to guard against PXE stacks that
+ * mistake it for an input parameter.
+ *
+ * The length of the TFTP data packet will be returned via
+ * s_PXENV_TFTP_READ::BufferSize. If this length is less than the
+ * blksize negotiated via s_PXENV_TFTP_OPEN::PacketSize in the call to
+ * pxenv_tftp_open(), this indicates that the block is the last block
+ * in the file. Note that zero is a valid length for
+ * s_PXENV_TFTP_READ::BufferSize, and will occur when the length of
+ * the file is a multiple of the blksize.
+ *
+ * The PXE specification doesn't actually state that calls to
+ * pxenv_tftp_read() will return the data packets in strict sequential
+ * order, though most PXE stacks will probably do so. The sequence
+ * number of the packet will be returned in
+ * s_PXENV_TFTP_READ::PacketNumber. The first packet in the file has
+ * a sequence number of one, not zero.
+ *
+ * To guard against flawed PXE stacks, the caller should probably set
+ * s_PXENV_TFTP_READ::PacketNumber to one less than the expected
+ * returned value (i.e. set it to zero for the first call to
+ * pxenv_tftp_read() and then re-use the returned s_PXENV_TFTP_READ
+ * parameter block for subsequent calls without modifying
+ * s_PXENV_TFTP_READ::PacketNumber between calls). The caller should
+ * also guard against potential problems caused by flawed
+ * implementations returning the occasional duplicate packet, by
+ * checking that the value returned in s_PXENV_TFTP_READ::PacketNumber
+ * is as expected (i.e. one greater than that returned from the
+ * previous call to pxenv_tftp_read()).
+ *
+ * On x86, you must set the s_PXE::StatusCallout field to a nonzero
+ * value before calling this function in protected mode. You cannot
+ * call this function with a 32-bit stack segment. (See the relevant
+ * @ref pxe_x86_pmode16 "implementation note" for more details.)
+ */
+static PXENV_EXIT_t pxenv_tftp_read ( struct s_PXENV_TFTP_READ *tftp_read ) {
+ int rc;
+
+ DBG ( "PXENV_TFTP_READ to %04x:%04x",
+ tftp_read->Buffer.segment, tftp_read->Buffer.offset );
+
+ /* Read single block into buffer */
+ pxe_tftp.buffer = real_to_user ( tftp_read->Buffer.segment,
+ tftp_read->Buffer.offset );
+ pxe_tftp.size = pxe_tftp.blksize;
+ pxe_tftp.start = pxe_tftp.offset;
+ while ( ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) &&
+ ( pxe_tftp.offset == pxe_tftp.start ) )
+ step();
+ pxe_tftp.buffer = UNULL;
+ tftp_read->BufferSize = ( pxe_tftp.offset - pxe_tftp.start );
+ tftp_read->PacketNumber = ++pxe_tftp.blkidx;
+
+ /* EINPROGRESS is normal if we haven't reached EOF yet */
+ if ( rc == -EINPROGRESS )
+ rc = 0;
+
+ tftp_read->Status = PXENV_STATUS ( rc );
+ return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS );
+}
+
+/**
+ * TFTP/MTFTP read file
+ *
+ * @v tftp_read_file Pointer to a struct s_PXENV_TFTP_READ_FILE
+ * @v s_PXENV_TFTP_READ_FILE::FileName File name
+ * @v s_PXENV_TFTP_READ_FILE::BufferSize Size of the receive buffer
+ * @v s_PXENV_TFTP_READ_FILE::Buffer Address of the receive buffer
+ * @v s_PXENV_TFTP_READ_FILE::ServerIPAddress TFTP server IP address
+ * @v s_PXENV_TFTP_READ_FILE::GatewayIPAddress Relay agent IP address
+ * @v s_PXENV_TFTP_READ_FILE::McastIPAddress File's multicast IP address
+ * @v s_PXENV_TFTP_READ_FILE::TFTPClntPort Client multicast UDP port
+ * @v s_PXENV_TFTP_READ_FILE::TFTPSrvPort Server multicast UDP port
+ * @v s_PXENV_TFTP_READ_FILE::TFTPOpenTimeOut Time to wait for first packet
+ * @v s_PXENV_TFTP_READ_FILE::TFTPReopenDelay MTFTP inactivity timeout
+ * @ret #PXENV_EXIT_SUCCESS File downloaded successfully
+ * @ret #PXENV_EXIT_FAILURE File not downloaded
+ * @ret s_PXENV_TFTP_READ_FILE::Status PXE status code
+ * @ret s_PXENV_TFTP_READ_FILE::BufferSize Length of downloaded file
+ *
+ * Downloads an entire file via either TFTP or MTFTP into the buffer
+ * pointed to by s_PXENV_TFTP_READ_FILE::Buffer.
+ *
+ * The PXE specification does not make it clear how the caller
+ * requests that MTFTP be used rather than TFTP (or vice versa). One
+ * reasonable guess is that setting
+ * s_PXENV_TFTP_READ_FILE::McastIPAddress to 0.0.0.0 would cause TFTP
+ * to be used instead of MTFTP, though it is conceivable that some PXE
+ * stacks would interpret that as "use the DHCP-provided multicast IP
+ * address" instead. Some PXE stacks will not implement MTFTP at all,
+ * and will always use TFTP.
+ *
+ * It is not specified whether or not
+ * s_PXENV_TFTP_READ_FILE::TFTPSrvPort will be used as the TFTP server
+ * port for TFTP (rather than MTFTP) downloads. Callers should assume
+ * that the only way to access a TFTP server on a non-standard port is
+ * to use pxenv_tftp_open() and pxenv_tftp_read().
+ *
+ * If s_PXENV_TFTP_READ_FILE::GatewayIPAddress is 0.0.0.0, normal IP
+ * routing will take place. See the relevant
+ * @ref pxe_routing "implementation note" for more details.
+ *
+ * It is interesting to note that s_PXENV_TFTP_READ_FILE::Buffer is an
+ * #ADDR32_t type, i.e. nominally a flat physical address. Some PXE
+ * NBPs (e.g. NTLDR) are known to call pxenv_tftp_read_file() in real
+ * mode with s_PXENV_TFTP_READ_FILE::Buffer set to an address above
+ * 1MB. This means that PXE stacks must be prepared to write to areas
+ * outside base memory. Exactly how this is to be achieved is not
+ * specified, though using INT 15,87 is as close to a standard method
+ * as any, and should probably be used. Switching to protected-mode
+ * in order to access high memory will fail if pxenv_tftp_read_file()
+ * is called in V86 mode; it is reasonably to expect that a V86
+ * monitor would intercept the relatively well-defined INT 15,87 if it
+ * wants the PXE stack to be able to write to high memory.
+ *
+ * Things get even more interesting if pxenv_tftp_read_file() is
+ * called in protected mode, because there is then absolutely no way
+ * for the PXE stack to write to an absolute physical address. You
+ * can't even get around the problem by creating a special "access
+ * everything" segment in the s_PXE data structure, because the
+ * #SEGDESC_t descriptors are limited to 64kB in size.
+ *
+ * Previous versions of the PXE specification (e.g. WfM 1.1a) provide
+ * a separate API call, %pxenv_tftp_read_file_pmode(), specifically to
+ * work around this problem. The s_PXENV_TFTP_READ_FILE_PMODE
+ * parameter block splits s_PXENV_TFTP_READ_FILE::Buffer into
+ * s_PXENV_TFTP_READ_FILE_PMODE::BufferSelector and
+ * s_PXENV_TFTP_READ_FILE_PMODE::BufferOffset, i.e. it provides a
+ * protected-mode segment:offset address for the data buffer. This
+ * API call is no longer present in version 2.1 of the PXE
+ * specification.
+ *
+ * Etherboot makes the assumption that s_PXENV_TFTP_READ_FILE::Buffer
+ * is an offset relative to the caller's data segment, when
+ * pxenv_tftp_read_file() is called in protected mode.
+ *
+ * On x86, you must set the s_PXE::StatusCallout field to a nonzero
+ * value before calling this function in protected mode. You cannot
+ * call this function with a 32-bit stack segment. (See the relevant
+ * @ref pxe_x86_pmode16 "implementation note" for more details.)
+ */
+PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
+ *tftp_read_file ) {
+ int rc;
+
+ DBG ( "PXENV_TFTP_READ_FILE to %08x+%x", tftp_read_file->Buffer,
+ tftp_read_file->BufferSize );
+
+ /* Open TFTP file */
+ if ( ( rc = pxe_tftp_open ( tftp_read_file->ServerIPAddress, 0,
+ tftp_read_file->FileName, 0, 0 ) ) != 0 ) {
+ tftp_read_file->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Read entire file */
+ pxe_tftp.buffer = phys_to_user ( tftp_read_file->Buffer );
+ pxe_tftp.size = tftp_read_file->BufferSize;
+ while ( ( rc = pxe_tftp.rc ) == -EINPROGRESS )
+ step();
+ pxe_tftp.buffer = UNULL;
+ tftp_read_file->BufferSize = pxe_tftp.max_offset;
+
+ /* Close TFTP file */
+ pxe_tftp_close ( &pxe_tftp, rc );
+
+ tftp_read_file->Status = PXENV_STATUS ( rc );
+ return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS );
+}
+
+/**
+ * TFTP GET FILE SIZE
+ *
+ * @v tftp_get_fsize Pointer to a struct s_PXENV_TFTP_GET_FSIZE
+ * @v s_PXENV_TFTP_GET_FSIZE::ServerIPAddress TFTP server IP address
+ * @v s_PXENV_TFTP_GET_FSIZE::GatewayIPAddress Relay agent IP address
+ * @v s_PXENV_TFTP_GET_FSIZE::FileName File name
+ * @ret #PXENV_EXIT_SUCCESS File size was determined successfully
+ * @ret #PXENV_EXIT_FAILURE File size was not determined
+ * @ret s_PXENV_TFTP_GET_FSIZE::Status PXE status code
+ * @ret s_PXENV_TFTP_GET_FSIZE::FileSize File size
+ *
+ * Determine the size of a file on a TFTP server. This uses the
+ * "tsize" TFTP option, and so will not work with a TFTP server that
+ * does not support TFTP options, or that does not support the "tsize"
+ * option.
+ *
+ * The PXE specification states that this API call will @b not open a
+ * TFTP connection for subsequent use with pxenv_tftp_read(). (This
+ * is somewhat daft, since the only way to obtain the file size via
+ * the "tsize" option involves issuing a TFTP open request, but that's
+ * life.)
+ *
+ * You cannot call pxenv_tftp_get_fsize() while a TFTP or UDP
+ * connection is open.
+ *
+ * If s_PXENV_TFTP_GET_FSIZE::GatewayIPAddress is 0.0.0.0, normal IP
+ * routing will take place. See the relevant
+ * @ref pxe_routing "implementation note" for more details.
+ *
+ * On x86, you must set the s_PXE::StatusCallout field to a nonzero
+ * value before calling this function in protected mode. You cannot
+ * call this function with a 32-bit stack segment. (See the relevant
+ * @ref pxe_x86_pmode16 "implementation note" for more details.)
+ *
+ * @note There is no way to specify the TFTP server port with this API
+ * call. Though you can open a file using a non-standard TFTP server
+ * port (via s_PXENV_TFTP_OPEN::TFTPPort or, potentially,
+ * s_PXENV_TFTP_READ_FILE::TFTPSrvPort), you can only get the size of
+ * a file from a TFTP server listening on the standard TFTP port.
+ * "Consistency" is not a word in Intel's vocabulary.
+ */
+static PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE
+ *tftp_get_fsize ) {
+ int rc;
+
+ DBG ( "PXENV_TFTP_GET_FSIZE" );
+
+ /* Open TFTP file */
+ if ( ( rc = pxe_tftp_open ( tftp_get_fsize->ServerIPAddress, 0,
+ tftp_get_fsize->FileName, 0, 1 ) ) != 0 ) {
+ tftp_get_fsize->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Wait for initial seek to arrive, and record size */
+ while ( ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) &&
+ ( pxe_tftp.max_offset == 0 ) ) {
+ step();
+ }
+ tftp_get_fsize->FileSize = pxe_tftp.max_offset;
+ DBG ( " fsize=%d", tftp_get_fsize->FileSize );
+
+ /* EINPROGRESS is normal; we don't wait for the whole transfer */
+ if ( rc == -EINPROGRESS )
+ rc = 0;
+
+ /* Close TFTP file */
+ pxe_tftp_close ( &pxe_tftp, rc );
+
+ tftp_get_fsize->Status = PXENV_STATUS ( rc );
+ return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS );
+}
+
+/** PXE TFTP API */
+struct pxe_api_call pxe_tftp_api[] __pxe_api_call = {
+ PXE_API_CALL ( PXENV_TFTP_OPEN, pxenv_tftp_open,
+ struct s_PXENV_TFTP_OPEN ),
+ PXE_API_CALL ( PXENV_TFTP_CLOSE, pxenv_tftp_close,
+ struct s_PXENV_TFTP_CLOSE ),
+ PXE_API_CALL ( PXENV_TFTP_READ, pxenv_tftp_read,
+ struct s_PXENV_TFTP_READ ),
+ PXE_API_CALL ( PXENV_TFTP_READ_FILE, pxenv_tftp_read_file,
+ struct s_PXENV_TFTP_READ_FILE ),
+ PXE_API_CALL ( PXENV_TFTP_GET_FSIZE, pxenv_tftp_get_fsize,
+ struct s_PXENV_TFTP_GET_FSIZE ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_udp.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_udp.c
new file mode 100644
index 00000000..a127f453
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_udp.c
@@ -0,0 +1,421 @@
+/** @file
+ *
+ * PXE UDP API
+ *
+ */
+
+#include <string.h>
+#include <byteswap.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/udp.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/process.h>
+#include <pxe.h>
+
+/*
+ * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** A PXE UDP connection */
+struct pxe_udp_connection {
+ /** Data transfer interface to UDP stack */
+ struct interface xfer;
+ /** Local address */
+ struct sockaddr_in local;
+ /** Current PXENV_UDP_READ parameter block */
+ struct s_PXENV_UDP_READ *pxenv_udp_read;
+};
+
+/**
+ * Receive PXE UDP data
+ *
+ * @v pxe_udp PXE UDP connection
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ *
+ * Receives a packet as part of the current pxenv_udp_read()
+ * operation.
+ */
+static int pxe_udp_deliver ( struct pxe_udp_connection *pxe_udp,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct s_PXENV_UDP_READ *pxenv_udp_read = pxe_udp->pxenv_udp_read;
+ struct sockaddr_in *sin_src;
+ struct sockaddr_in *sin_dest;
+ userptr_t buffer;
+ size_t len;
+ int rc = 0;
+
+ if ( ! pxenv_udp_read ) {
+ DBG ( "PXE discarded UDP packet\n" );
+ rc = -ENOBUFS;
+ goto done;
+ }
+
+ /* Copy packet to buffer and record length */
+ buffer = real_to_user ( pxenv_udp_read->buffer.segment,
+ pxenv_udp_read->buffer.offset );
+ len = iob_len ( iobuf );
+ if ( len > pxenv_udp_read->buffer_size )
+ len = pxenv_udp_read->buffer_size;
+ copy_to_user ( buffer, 0, iobuf->data, len );
+ pxenv_udp_read->buffer_size = len;
+
+ /* Fill in source/dest information */
+ assert ( meta );
+ sin_src = ( struct sockaddr_in * ) meta->src;
+ assert ( sin_src );
+ assert ( sin_src->sin_family == AF_INET );
+ pxenv_udp_read->src_ip = sin_src->sin_addr.s_addr;
+ pxenv_udp_read->s_port = sin_src->sin_port;
+ sin_dest = ( struct sockaddr_in * ) meta->dest;
+ assert ( sin_dest );
+ assert ( sin_dest->sin_family == AF_INET );
+ pxenv_udp_read->dest_ip = sin_dest->sin_addr.s_addr;
+ pxenv_udp_read->d_port = sin_dest->sin_port;
+
+ /* Mark as received */
+ pxe_udp->pxenv_udp_read = NULL;
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** PXE UDP data transfer interface operations */
+static struct interface_operation pxe_udp_xfer_operations[] = {
+ INTF_OP ( xfer_deliver, struct pxe_udp_connection *, pxe_udp_deliver ),
+};
+
+/** PXE UDP data transfer interface descriptor */
+static struct interface_descriptor pxe_udp_xfer_desc =
+ INTF_DESC ( struct pxe_udp_connection, xfer, pxe_udp_xfer_operations );
+
+/** The PXE UDP connection */
+static struct pxe_udp_connection pxe_udp = {
+ .xfer = INTF_INIT ( pxe_udp_xfer_desc ),
+ .local = {
+ .sin_family = AF_INET,
+ },
+};
+
+/**
+ * UDP OPEN
+ *
+ * @v pxenv_udp_open Pointer to a struct s_PXENV_UDP_OPEN
+ * @v s_PXENV_UDP_OPEN::src_ip IP address of this station, or 0.0.0.0
+ * @ret #PXENV_EXIT_SUCCESS Always
+ * @ret s_PXENV_UDP_OPEN::Status PXE status code
+ * @err #PXENV_STATUS_UDP_OPEN UDP connection already open
+ * @err #PXENV_STATUS_OUT_OF_RESOURCES Could not open connection
+ *
+ * Prepares the PXE stack for communication using pxenv_udp_write()
+ * and pxenv_udp_read().
+ *
+ * The IP address supplied in s_PXENV_UDP_OPEN::src_ip will be
+ * recorded and used as the local station's IP address for all further
+ * communication, including communication by means other than
+ * pxenv_udp_write() and pxenv_udp_read(). (If
+ * s_PXENV_UDP_OPEN::src_ip is 0.0.0.0, the local station's IP address
+ * will remain unchanged.)
+ *
+ * You can only have one open UDP connection at a time. This is not a
+ * meaningful restriction, since pxenv_udp_write() and
+ * pxenv_udp_read() allow you to specify arbitrary local and remote
+ * ports and an arbitrary remote address for each packet. According
+ * to the PXE specifiation, you cannot have a UDP connection open at
+ * the same time as a TFTP connection; this restriction does not apply
+ * to Etherboot.
+ *
+ * On x86, you must set the s_PXE::StatusCallout field to a nonzero
+ * value before calling this function in protected mode. You cannot
+ * call this function with a 32-bit stack segment. (See the relevant
+ * @ref pxe_x86_pmode16 "implementation note" for more details.)
+ *
+ * @note The PXE specification does not make it clear whether the IP
+ * address supplied in s_PXENV_UDP_OPEN::src_ip should be used only
+ * for this UDP connection, or retained for all future communication.
+ * The latter seems more consistent with typical PXE stack behaviour.
+ *
+ * @note Etherboot currently ignores the s_PXENV_UDP_OPEN::src_ip
+ * parameter.
+ *
+ */
+static PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) {
+ int rc;
+
+ DBG ( "PXENV_UDP_OPEN" );
+
+ /* Record source IP address */
+ pxe_udp.local.sin_addr.s_addr = pxenv_udp_open->src_ip;
+ DBG ( " %s\n", inet_ntoa ( pxe_udp.local.sin_addr ) );
+
+ /* Open promiscuous UDP connection */
+ intf_restart ( &pxe_udp.xfer, 0 );
+ if ( ( rc = udp_open_promisc ( &pxe_udp.xfer ) ) != 0 ) {
+ DBG ( "PXENV_UDP_OPEN could not open promiscuous socket: %s\n",
+ strerror ( rc ) );
+ pxenv_udp_open->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+
+ pxenv_udp_open->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * UDP CLOSE
+ *
+ * @v pxenv_udp_close Pointer to a struct s_PXENV_UDP_CLOSE
+ * @ret #PXENV_EXIT_SUCCESS Always
+ * @ret s_PXENV_UDP_CLOSE::Status PXE status code
+ * @err None -
+ *
+ * Closes a UDP connection opened with pxenv_udp_open().
+ *
+ * You can only have one open UDP connection at a time. You cannot
+ * have a UDP connection open at the same time as a TFTP connection.
+ * You cannot use pxenv_udp_close() to close a TFTP connection; use
+ * pxenv_tftp_close() instead.
+ *
+ * On x86, you must set the s_PXE::StatusCallout field to a nonzero
+ * value before calling this function in protected mode. You cannot
+ * call this function with a 32-bit stack segment. (See the relevant
+ * @ref pxe_x86_pmode16 "implementation note" for more details.)
+ *
+ */
+static PXENV_EXIT_t
+pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) {
+ DBG ( "PXENV_UDP_CLOSE\n" );
+
+ /* Close UDP connection */
+ intf_restart ( &pxe_udp.xfer, 0 );
+
+ pxenv_udp_close->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * UDP WRITE
+ *
+ * @v pxenv_udp_write Pointer to a struct s_PXENV_UDP_WRITE
+ * @v s_PXENV_UDP_WRITE::ip Destination IP address
+ * @v s_PXENV_UDP_WRITE::gw Relay agent IP address, or 0.0.0.0
+ * @v s_PXENV_UDP_WRITE::src_port Source UDP port, or 0
+ * @v s_PXENV_UDP_WRITE::dst_port Destination UDP port
+ * @v s_PXENV_UDP_WRITE::buffer_size Length of the UDP payload
+ * @v s_PXENV_UDP_WRITE::buffer Address of the UDP payload
+ * @ret #PXENV_EXIT_SUCCESS Packet was transmitted successfully
+ * @ret #PXENV_EXIT_FAILURE Packet could not be transmitted
+ * @ret s_PXENV_UDP_WRITE::Status PXE status code
+ * @err #PXENV_STATUS_UDP_CLOSED UDP connection is not open
+ * @err #PXENV_STATUS_UNDI_TRANSMIT_ERROR Could not transmit packet
+ *
+ * Transmits a single UDP packet. A valid IP and UDP header will be
+ * prepended to the payload in s_PXENV_UDP_WRITE::buffer; the buffer
+ * should not contain precomputed IP and UDP headers, nor should it
+ * contain space allocated for these headers. The first byte of the
+ * buffer will be transmitted as the first byte following the UDP
+ * header.
+ *
+ * If s_PXENV_UDP_WRITE::gw is 0.0.0.0, normal IP routing will take
+ * place. See the relevant @ref pxe_routing "implementation note" for
+ * more details.
+ *
+ * If s_PXENV_UDP_WRITE::src_port is 0, port 2069 will be used.
+ *
+ * You must have opened a UDP connection with pxenv_udp_open() before
+ * calling pxenv_udp_write().
+ *
+ * On x86, you must set the s_PXE::StatusCallout field to a nonzero
+ * value before calling this function in protected mode. You cannot
+ * call this function with a 32-bit stack segment. (See the relevant
+ * @ref pxe_x86_pmode16 "implementation note" for more details.)
+ *
+ * @note Etherboot currently ignores the s_PXENV_UDP_WRITE::gw
+ * parameter.
+ *
+ */
+static PXENV_EXIT_t
+pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) {
+ struct sockaddr_in dest;
+ struct xfer_metadata meta = {
+ .src = ( struct sockaddr * ) &pxe_udp.local,
+ .dest = ( struct sockaddr * ) &dest,
+ .netdev = pxe_netdev,
+ };
+ size_t len;
+ struct io_buffer *iobuf;
+ userptr_t buffer;
+ int rc;
+
+ DBG ( "PXENV_UDP_WRITE" );
+
+ /* Construct destination socket address */
+ memset ( &dest, 0, sizeof ( dest ) );
+ dest.sin_family = AF_INET;
+ dest.sin_addr.s_addr = pxenv_udp_write->ip;
+ dest.sin_port = pxenv_udp_write->dst_port;
+
+ /* Set local (source) port. PXE spec says source port is 2069
+ * if not specified. Really, this ought to be set at UDP open
+ * time but hey, we didn't design this API.
+ */
+ pxe_udp.local.sin_port = pxenv_udp_write->src_port;
+ if ( ! pxe_udp.local.sin_port )
+ pxe_udp.local.sin_port = htons ( 2069 );
+
+ /* FIXME: we ignore the gateway specified, since we're
+ * confident of being able to do our own routing. We should
+ * probably allow for multiple gateways.
+ */
+
+ /* Allocate and fill data buffer */
+ len = pxenv_udp_write->buffer_size;
+ iobuf = xfer_alloc_iob ( &pxe_udp.xfer, len );
+ if ( ! iobuf ) {
+ DBG ( " out of memory\n" );
+ pxenv_udp_write->Status = PXENV_STATUS_OUT_OF_RESOURCES;
+ return PXENV_EXIT_FAILURE;
+ }
+ buffer = real_to_user ( pxenv_udp_write->buffer.segment,
+ pxenv_udp_write->buffer.offset );
+ copy_from_user ( iob_put ( iobuf, len ), buffer, 0, len );
+
+ DBG ( " %04x:%04x+%x %d->%s:%d\n", pxenv_udp_write->buffer.segment,
+ pxenv_udp_write->buffer.offset, pxenv_udp_write->buffer_size,
+ ntohs ( pxenv_udp_write->src_port ),
+ inet_ntoa ( dest.sin_addr ),
+ ntohs ( pxenv_udp_write->dst_port ) );
+
+ /* Transmit packet */
+ if ( ( rc = xfer_deliver ( &pxe_udp.xfer, iobuf, &meta ) ) != 0 ) {
+ DBG ( "PXENV_UDP_WRITE could not transmit: %s\n",
+ strerror ( rc ) );
+ pxenv_udp_write->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+
+ pxenv_udp_write->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * UDP READ
+ *
+ * @v pxenv_udp_read Pointer to a struct s_PXENV_UDP_READ
+ * @v s_PXENV_UDP_READ::dest_ip Destination IP address, or 0.0.0.0
+ * @v s_PXENV_UDP_READ::d_port Destination UDP port, or 0
+ * @v s_PXENV_UDP_READ::buffer_size Size of the UDP payload buffer
+ * @v s_PXENV_UDP_READ::buffer Address of the UDP payload buffer
+ * @ret #PXENV_EXIT_SUCCESS A packet has been received
+ * @ret #PXENV_EXIT_FAILURE No packet has been received
+ * @ret s_PXENV_UDP_READ::Status PXE status code
+ * @ret s_PXENV_UDP_READ::src_ip Source IP address
+ * @ret s_PXENV_UDP_READ::dest_ip Destination IP address
+ * @ret s_PXENV_UDP_READ::s_port Source UDP port
+ * @ret s_PXENV_UDP_READ::d_port Destination UDP port
+ * @ret s_PXENV_UDP_READ::buffer_size Length of UDP payload
+ * @err #PXENV_STATUS_UDP_CLOSED UDP connection is not open
+ * @err #PXENV_STATUS_FAILURE No packet was ready to read
+ *
+ * Receive a single UDP packet. This is a non-blocking call; if no
+ * packet is ready to read, the call will return instantly with
+ * s_PXENV_UDP_READ::Status==PXENV_STATUS_FAILURE.
+ *
+ * If s_PXENV_UDP_READ::dest_ip is 0.0.0.0, UDP packets addressed to
+ * any IP address will be accepted and may be returned to the caller.
+ *
+ * If s_PXENV_UDP_READ::d_port is 0, UDP packets addressed to any UDP
+ * port will be accepted and may be returned to the caller.
+ *
+ * You must have opened a UDP connection with pxenv_udp_open() before
+ * calling pxenv_udp_read().
+ *
+ * On x86, you must set the s_PXE::StatusCallout field to a nonzero
+ * value before calling this function in protected mode. You cannot
+ * call this function with a 32-bit stack segment. (See the relevant
+ * @ref pxe_x86_pmode16 "implementation note" for more details.)
+ *
+ * @note The PXE specification (version 2.1) does not state that we
+ * should fill in s_PXENV_UDP_READ::dest_ip and
+ * s_PXENV_UDP_READ::d_port, but Microsoft Windows' NTLDR program
+ * expects us to do so, and will fail if we don't.
+ *
+ */
+static PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) {
+ struct in_addr dest_ip_wanted = { .s_addr = pxenv_udp_read->dest_ip };
+ struct in_addr dest_ip;
+ uint16_t d_port_wanted = pxenv_udp_read->d_port;
+ uint16_t d_port;
+
+ /* Try receiving a packet */
+ pxe_udp.pxenv_udp_read = pxenv_udp_read;
+ step();
+ if ( pxe_udp.pxenv_udp_read ) {
+ /* No packet received */
+ DBG2 ( "PXENV_UDP_READ\n" );
+ pxe_udp.pxenv_udp_read = NULL;
+ goto no_packet;
+ }
+ dest_ip.s_addr = pxenv_udp_read->dest_ip;
+ d_port = pxenv_udp_read->d_port;
+ DBG ( "PXENV_UDP_READ" );
+
+ /* Filter on destination address and/or port */
+ if ( dest_ip_wanted.s_addr &&
+ ( dest_ip_wanted.s_addr != dest_ip.s_addr ) ) {
+ DBG ( " wrong IP %s", inet_ntoa ( dest_ip ) );
+ DBG ( " (wanted %s)\n", inet_ntoa ( dest_ip_wanted ) );
+ goto no_packet;
+ }
+ if ( d_port_wanted && ( d_port_wanted != d_port ) ) {
+ DBG ( " wrong port %d", htons ( d_port ) );
+ DBG ( " (wanted %d)\n", htons ( d_port_wanted ) );
+ goto no_packet;
+ }
+
+ DBG ( " %04x:%04x+%x %s:", pxenv_udp_read->buffer.segment,
+ pxenv_udp_read->buffer.offset, pxenv_udp_read->buffer_size,
+ inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->src_ip ) ));
+ DBG ( "%d<-%s:%d\n", ntohs ( pxenv_udp_read->s_port ),
+ inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->dest_ip ) ),
+ ntohs ( pxenv_udp_read->d_port ) );
+
+ pxenv_udp_read->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+
+ no_packet:
+ pxenv_udp_read->Status = PXENV_STATUS_FAILURE;
+ return PXENV_EXIT_FAILURE;
+}
+
+/** PXE UDP API */
+struct pxe_api_call pxe_udp_api[] __pxe_api_call = {
+ PXE_API_CALL ( PXENV_UDP_OPEN, pxenv_udp_open,
+ struct s_PXENV_UDP_OPEN ),
+ PXE_API_CALL ( PXENV_UDP_CLOSE, pxenv_udp_close,
+ struct s_PXENV_UDP_CLOSE ),
+ PXE_API_CALL ( PXENV_UDP_WRITE, pxenv_udp_write,
+ struct s_PXENV_UDP_WRITE ),
+ PXE_API_CALL ( PXENV_UDP_READ, pxenv_udp_read,
+ struct s_PXENV_UDP_READ ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_undi.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_undi.c
new file mode 100644
index 00000000..d605c82f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxe/pxe_undi.c
@@ -0,0 +1,1068 @@
+/** @file
+ *
+ * PXE UNDI API
+ *
+ */
+
+/*
+ * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <byteswap.h>
+#include <basemem_packet.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/device.h>
+#include <ipxe/pci.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ip.h>
+#include <ipxe/arp.h>
+#include <ipxe/rarp.h>
+#include "pxe.h"
+
+/**
+ * Count of outstanding transmitted packets
+ *
+ * This is incremented each time PXENV_UNDI_TRANSMIT is called, and
+ * decremented each time that PXENV_UNDI_ISR is called with the TX
+ * queue empty, stopping when the count reaches zero. This allows us
+ * to provide a pessimistic approximation of TX completion events to
+ * the PXE NBP simply by monitoring the netdev's TX queue.
+ */
+static int undi_tx_count = 0;
+
+struct net_device *pxe_netdev = NULL;
+
+/**
+ * Set network device as current PXE network device
+ *
+ * @v netdev Network device, or NULL
+ */
+void pxe_set_netdev ( struct net_device *netdev ) {
+
+ if ( pxe_netdev ) {
+ netdev_rx_unfreeze ( pxe_netdev );
+ netdev_put ( pxe_netdev );
+ }
+
+ pxe_netdev = NULL;
+
+ if ( netdev )
+ pxe_netdev = netdev_get ( netdev );
+}
+
+/**
+ * Open PXE network device
+ *
+ * @ret rc Return status code
+ */
+static int pxe_netdev_open ( void ) {
+ int rc;
+
+ assert ( pxe_netdev != NULL );
+
+ if ( ( rc = netdev_open ( pxe_netdev ) ) != 0 )
+ return rc;
+
+ netdev_rx_freeze ( pxe_netdev );
+ netdev_irq ( pxe_netdev, 1 );
+
+ return 0;
+}
+
+/**
+ * Close PXE network device
+ *
+ */
+static void pxe_netdev_close ( void ) {
+
+ assert ( pxe_netdev != NULL );
+ netdev_rx_unfreeze ( pxe_netdev );
+ netdev_irq ( pxe_netdev, 0 );
+ netdev_close ( pxe_netdev );
+ undi_tx_count = 0;
+}
+
+/**
+ * Dump multicast address list
+ *
+ * @v mcast PXE multicast address list
+ */
+static void pxe_dump_mcast_list ( struct s_PXENV_UNDI_MCAST_ADDRESS *mcast ) {
+ struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
+ unsigned int i;
+
+ for ( i = 0 ; i < mcast->MCastAddrCount ; i++ ) {
+ DBGC ( &pxe_netdev, " %s",
+ ll_protocol->ntoa ( mcast->McastAddr[i] ) );
+ }
+}
+
+/* PXENV_UNDI_STARTUP
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP *undi_startup ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_STARTUP\n" );
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_STARTUP called with no "
+ "network device\n" );
+ undi_startup->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ undi_startup->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_CLEANUP
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_CLEANUP\n" );
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_CLEANUP called with no "
+ "network device\n" );
+ undi_cleanup->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Close network device */
+ pxe_netdev_close();
+
+ undi_cleanup->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_INITIALIZE
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_undi_initialize ( struct s_PXENV_UNDI_INITIALIZE *undi_initialize ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_INITIALIZE protocolini %08x\n",
+ undi_initialize->ProtocolIni );
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_INITIALIZE called with no "
+ "network device\n" );
+ undi_initialize->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ undi_initialize->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_RESET_ADAPTER
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET *undi_reset_adapter ) {
+ int rc;
+
+ DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER" );
+ pxe_dump_mcast_list ( &undi_reset_adapter->R_Mcast_Buf );
+ DBGC ( &pxe_netdev, "\n" );
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER called with no "
+ "network device\n" );
+ undi_reset_adapter->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Close and reopen network device */
+ pxe_netdev_close();
+ if ( ( rc = pxe_netdev_open() ) != 0 ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER could not "
+ "reopen %s: %s\n", pxe_netdev->name, strerror ( rc ) );
+ undi_reset_adapter->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+
+ undi_reset_adapter->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_SHUTDOWN
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN *undi_shutdown ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_SHUTDOWN\n" );
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_SHUTDOWN called with no "
+ "network device\n" );
+ undi_shutdown->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Close network device */
+ pxe_netdev_close();
+
+ undi_shutdown->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_OPEN
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) {
+ int rc;
+
+ DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN flag %04x filter %04x",
+ undi_open->OpenFlag, undi_open->PktFilter );
+ pxe_dump_mcast_list ( &undi_open->R_Mcast_Buf );
+ DBGC ( &pxe_netdev, "\n" );
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN called with no "
+ "network device\n" );
+ undi_open->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Open network device */
+ if ( ( rc = pxe_netdev_open() ) != 0 ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN could not open %s: %s\n",
+ pxe_netdev->name, strerror ( rc ) );
+ undi_open->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+
+ undi_open->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_CLOSE
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_CLOSE\n" );
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_CLOSE called with no "
+ "network device\n" );
+ undi_close->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Close network device */
+ pxe_netdev_close();
+
+ undi_close->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_TRANSMIT
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT *undi_transmit ) {
+ struct s_PXENV_UNDI_TBD tbd;
+ struct DataBlk *datablk;
+ struct io_buffer *iobuf;
+ struct net_protocol *net_protocol;
+ struct ll_protocol *ll_protocol;
+ char destaddr[MAX_LL_ADDR_LEN];
+ const void *ll_dest;
+ size_t len;
+ unsigned int i;
+ int rc;
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_TRANSMIT called with no "
+ "network device\n" );
+ undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ DBGC2 ( &pxe_netdev, "PXENV_UNDI_TRANSMIT" );
+
+ /* Forcibly enable interrupts and freeze receive queue
+ * processing at this point, to work around callers that never
+ * call PXENV_UNDI_OPEN before attempting to use the UNDI API.
+ */
+ netdev_rx_freeze ( pxe_netdev );
+ netdev_irq ( pxe_netdev, 1 );
+
+ /* Identify network-layer protocol */
+ switch ( undi_transmit->Protocol ) {
+ case P_IP: net_protocol = &ipv4_protocol; break;
+ case P_ARP: net_protocol = &arp_protocol; break;
+ case P_RARP: net_protocol = &rarp_protocol; break;
+ case P_UNKNOWN:
+ net_protocol = NULL;
+ break;
+ default:
+ DBGC2 ( &pxe_netdev, " %02x invalid protocol\n",
+ undi_transmit->Protocol );
+ undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
+ return PXENV_EXIT_FAILURE;
+ }
+ DBGC2 ( &pxe_netdev, " %s",
+ ( net_protocol ? net_protocol->name : "RAW" ) );
+
+ /* Calculate total packet length */
+ copy_from_real ( &tbd, undi_transmit->TBD.segment,
+ undi_transmit->TBD.offset, sizeof ( tbd ) );
+ len = tbd.ImmedLength;
+ DBGC2 ( &pxe_netdev, " %04x:%04x+%x", tbd.Xmit.segment, tbd.Xmit.offset,
+ tbd.ImmedLength );
+ for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) {
+ datablk = &tbd.DataBlock[i];
+ len += datablk->TDDataLen;
+ DBGC2 ( &pxe_netdev, " %04x:%04x+%x",
+ datablk->TDDataPtr.segment, datablk->TDDataPtr.offset,
+ datablk->TDDataLen );
+ }
+
+ /* Allocate and fill I/O buffer */
+ iobuf = alloc_iob ( MAX_LL_HEADER_LEN + len );
+ if ( ! iobuf ) {
+ DBGC2 ( &pxe_netdev, " could not allocate iobuf\n" );
+ undi_transmit->Status = PXENV_STATUS_OUT_OF_RESOURCES;
+ return PXENV_EXIT_FAILURE;
+ }
+ iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
+ copy_from_real ( iob_put ( iobuf, tbd.ImmedLength ), tbd.Xmit.segment,
+ tbd.Xmit.offset, tbd.ImmedLength );
+ for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) {
+ datablk = &tbd.DataBlock[i];
+ copy_from_real ( iob_put ( iobuf, datablk->TDDataLen ),
+ datablk->TDDataPtr.segment,
+ datablk->TDDataPtr.offset,
+ datablk->TDDataLen );
+ }
+
+ /* Add link-layer header, if required to do so */
+ if ( net_protocol != NULL ) {
+
+ /* Calculate destination address */
+ ll_protocol = pxe_netdev->ll_protocol;
+ if ( undi_transmit->XmitFlag == XMT_DESTADDR ) {
+ copy_from_real ( destaddr,
+ undi_transmit->DestAddr.segment,
+ undi_transmit->DestAddr.offset,
+ ll_protocol->ll_addr_len );
+ ll_dest = destaddr;
+ DBGC2 ( &pxe_netdev, " DEST %s",
+ ll_protocol->ntoa ( ll_dest ) );
+ } else {
+ ll_dest = pxe_netdev->ll_broadcast;
+ DBGC2 ( &pxe_netdev, " BCAST" );
+ }
+
+ /* Add link-layer header */
+ if ( ( rc = ll_protocol->push ( pxe_netdev, iobuf, ll_dest,
+ pxe_netdev->ll_addr,
+ net_protocol->net_proto ))!=0){
+ DBGC2 ( &pxe_netdev, " could not add link-layer "
+ "header: %s\n", strerror ( rc ) );
+ free_iob ( iobuf );
+ undi_transmit->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+ }
+
+ /* Flag transmission as in-progress. Do this before starting
+ * to transmit the packet, because the ISR may trigger before
+ * we return from netdev_tx().
+ */
+ undi_tx_count++;
+
+ /* Transmit packet */
+ DBGC2 ( &pxe_netdev, "\n" );
+ if ( ( rc = netdev_tx ( pxe_netdev, iobuf ) ) != 0 ) {
+ DBGC2 ( &pxe_netdev, "PXENV_UNDI_TRANSMIT could not transmit: "
+ "%s\n", strerror ( rc ) );
+ undi_tx_count--;
+ undi_transmit->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+
+ undi_transmit->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_SET_MCAST_ADDRESS
+ *
+ * Status: working (for NICs that support receive-all-multicast)
+ */
+static PXENV_EXIT_t
+pxenv_undi_set_mcast_address ( struct s_PXENV_UNDI_SET_MCAST_ADDRESS
+ *undi_set_mcast_address ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_SET_MCAST_ADDRESS" );
+ pxe_dump_mcast_list ( &undi_set_mcast_address->R_Mcast_Buf );
+ DBGC ( &pxe_netdev, "\n" );
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_SET_MCAST_ADDRESS called with "
+ "no network device\n" );
+ undi_set_mcast_address->Status =
+ PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ undi_set_mcast_address->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_SET_STATION_ADDRESS
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS
+ *undi_set_station_address ) {
+ struct ll_protocol *ll_protocol;
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_SET_STATION_ADDRESS called "
+ "with no network device\n" );
+ undi_set_station_address->Status =
+ PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ ll_protocol = pxe_netdev->ll_protocol;
+ DBGC ( &pxe_netdev, "PXENV_UNDI_SET_STATION_ADDRESS %s",
+ ll_protocol->ntoa ( undi_set_station_address->StationAddress ) );
+
+ /* If adapter is open, the change will have no effect; return
+ * an error
+ */
+ if ( netdev_is_open ( pxe_netdev ) ) {
+ DBGC ( &pxe_netdev, " failed: netdev is open\n" );
+ undi_set_station_address->Status =
+ PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Update MAC address */
+ memcpy ( pxe_netdev->ll_addr,
+ &undi_set_station_address->StationAddress,
+ ll_protocol->ll_addr_len );
+
+ DBGC ( &pxe_netdev, "\n" );
+ undi_set_station_address->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_SET_PACKET_FILTER
+ *
+ * Status: won't implement (would require driver API changes for no
+ * real benefit)
+ */
+static PXENV_EXIT_t
+pxenv_undi_set_packet_filter ( struct s_PXENV_UNDI_SET_PACKET_FILTER
+ *undi_set_packet_filter ) {
+
+ DBGC ( &pxe_netdev, "PXENV_UNDI_SET_PACKET_FILTER %02x\n",
+ undi_set_packet_filter->filter );
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_SET_PACKET_FILTER called with "
+ "no network device\n" );
+ undi_set_packet_filter->Status =
+ PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Pretend that we succeeded, otherwise the 3Com DOS UNDI
+ * driver refuses to load. (We ignore the filter value in the
+ * PXENV_UNDI_OPEN call anyway.)
+ */
+ undi_set_packet_filter->Status = PXENV_STATUS_SUCCESS;
+
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_GET_INFORMATION
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION
+ *undi_get_information ) {
+ struct device *dev;
+ struct ll_protocol *ll_protocol;
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_GET_INFORMATION called with no "
+ "network device\n" );
+ undi_get_information->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ DBGC ( &pxe_netdev, "PXENV_UNDI_GET_INFORMATION" );
+
+ /* Fill in information */
+ dev = pxe_netdev->dev;
+ ll_protocol = pxe_netdev->ll_protocol;
+ undi_get_information->BaseIo = dev->desc.ioaddr;
+ undi_get_information->IntNumber =
+ ( netdev_irq_supported ( pxe_netdev ) ? dev->desc.irq : 0 );
+ /* Cheat: assume all cards can cope with this */
+ undi_get_information->MaxTranUnit = ETH_MAX_MTU;
+ undi_get_information->HwType = ntohs ( ll_protocol->ll_proto );
+ undi_get_information->HwAddrLen = ll_protocol->ll_addr_len;
+ assert ( ll_protocol->ll_addr_len <=
+ sizeof ( undi_get_information->CurrentNodeAddress ) );
+ memcpy ( &undi_get_information->CurrentNodeAddress,
+ pxe_netdev->ll_addr,
+ sizeof ( undi_get_information->CurrentNodeAddress ) );
+ ll_protocol->init_addr ( pxe_netdev->hw_addr,
+ &undi_get_information->PermNodeAddress );
+ undi_get_information->ROMAddress = 0;
+ /* nic.rom_info->rom_segment; */
+ /* We only provide the ability to receive or transmit a single
+ * packet at a time. This is a bootloader, not an OS.
+ */
+ undi_get_information->RxBufCt = 1;
+ undi_get_information->TxBufCt = 1;
+
+ DBGC ( &pxe_netdev, " io %04x irq %d mtu %d %s %s\n",
+ undi_get_information->BaseIo, undi_get_information->IntNumber,
+ undi_get_information->MaxTranUnit, ll_protocol->name,
+ ll_protocol->ntoa ( &undi_get_information->CurrentNodeAddress ));
+ undi_get_information->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_GET_STATISTICS
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_undi_get_statistics ( struct s_PXENV_UNDI_GET_STATISTICS
+ *undi_get_statistics ) {
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATISTICS called with no "
+ "network device\n" );
+ undi_get_statistics->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATISTICS" );
+
+ /* Report statistics */
+ undi_get_statistics->XmtGoodFrames = pxe_netdev->tx_stats.good;
+ undi_get_statistics->RcvGoodFrames = pxe_netdev->rx_stats.good;
+ undi_get_statistics->RcvCRCErrors = pxe_netdev->rx_stats.bad;
+ undi_get_statistics->RcvResourceErrors = pxe_netdev->rx_stats.bad;
+ DBGC ( &pxe_netdev, " txok %d rxok %d rxcrc %d rxrsrc %d\n",
+ undi_get_statistics->XmtGoodFrames,
+ undi_get_statistics->RcvGoodFrames,
+ undi_get_statistics->RcvCRCErrors,
+ undi_get_statistics->RcvResourceErrors );
+
+ undi_get_statistics->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_CLEAR_STATISTICS
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_undi_clear_statistics ( struct s_PXENV_UNDI_CLEAR_STATISTICS
+ *undi_clear_statistics ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_CLEAR_STATISTICS\n" );
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_CLEAR_STATISTICS called with "
+ "no network device\n" );
+ undi_clear_statistics->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ /* Clear statistics */
+ memset ( &pxe_netdev->tx_stats, 0, sizeof ( pxe_netdev->tx_stats ) );
+ memset ( &pxe_netdev->rx_stats, 0, sizeof ( pxe_netdev->rx_stats ) );
+
+ undi_clear_statistics->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_INITIATE_DIAGS
+ *
+ * Status: won't implement (would require driver API changes for no
+ * real benefit)
+ */
+static PXENV_EXIT_t
+pxenv_undi_initiate_diags ( struct s_PXENV_UNDI_INITIATE_DIAGS
+ *undi_initiate_diags ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_INITIATE_DIAGS failed: unsupported\n" );
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_INITIATE_DIAGS called with no "
+ "network device\n" );
+ undi_initiate_diags->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ undi_initiate_diags->Status = PXENV_STATUS_UNSUPPORTED;
+ return PXENV_EXIT_FAILURE;
+}
+
+/* PXENV_UNDI_FORCE_INTERRUPT
+ *
+ * Status: won't implement (would require driver API changes for no
+ * perceptible benefit)
+ */
+static PXENV_EXIT_t
+pxenv_undi_force_interrupt ( struct s_PXENV_UNDI_FORCE_INTERRUPT
+ *undi_force_interrupt ) {
+ DBGC ( &pxe_netdev,
+ "PXENV_UNDI_FORCE_INTERRUPT failed: unsupported\n" );
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_FORCE_INTERRUPT called with no "
+ "network device\n" );
+ undi_force_interrupt->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ undi_force_interrupt->Status = PXENV_STATUS_UNSUPPORTED;
+ return PXENV_EXIT_FAILURE;
+}
+
+/* PXENV_UNDI_GET_MCAST_ADDRESS
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_undi_get_mcast_address ( struct s_PXENV_UNDI_GET_MCAST_ADDRESS
+ *undi_get_mcast_address ) {
+ struct ll_protocol *ll_protocol;
+ struct in_addr ip = { .s_addr = undi_get_mcast_address->InetAddr };
+ int rc;
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_GET_MCAST_ADDRESS called with "
+ "no network device\n" );
+ undi_get_mcast_address->Status =
+ PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ DBGC ( &pxe_netdev, "PXENV_UNDI_GET_MCAST_ADDRESS %s",
+ inet_ntoa ( ip ) );
+
+ /* Hash address using the network device's link-layer protocol */
+ ll_protocol = pxe_netdev->ll_protocol;
+ if ( ( rc = ll_protocol->mc_hash ( AF_INET, &ip,
+ undi_get_mcast_address->MediaAddr ))!=0){
+ DBGC ( &pxe_netdev, " failed: %s\n", strerror ( rc ) );
+ undi_get_mcast_address->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+ DBGC ( &pxe_netdev, "=>%s\n",
+ ll_protocol->ntoa ( undi_get_mcast_address->MediaAddr ) );
+
+ undi_get_mcast_address->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_GET_NIC_TYPE
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE
+ *undi_get_nic_type ) {
+ struct device *dev;
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_GET_NIC_TYPE called with "
+ "no network device\n" );
+ undi_get_nic_type->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ DBGC ( &pxe_netdev, "PXENV_UNDI_GET_NIC_TYPE" );
+
+ /* Fill in information */
+ memset ( &undi_get_nic_type->info, 0,
+ sizeof ( undi_get_nic_type->info ) );
+ dev = pxe_netdev->dev;
+ switch ( dev->desc.bus_type ) {
+ case BUS_TYPE_PCI: {
+ struct pci_nic_info *info = &undi_get_nic_type->info.pci;
+
+ undi_get_nic_type->NicType = PCI_NIC;
+ info->Vendor_ID = dev->desc.vendor;
+ info->Dev_ID = dev->desc.device;
+ info->Base_Class = PCI_BASE_CLASS ( dev->desc.class );
+ info->Sub_Class = PCI_SUB_CLASS ( dev->desc.class );
+ info->Prog_Intf = PCI_PROG_INTF ( dev->desc.class );
+ info->BusDevFunc = dev->desc.location;
+ /* Earlier versions of the PXE specification do not
+ * have the SubVendor_ID and SubDevice_ID fields. It
+ * is possible that some NBPs will not provide space
+ * for them, and so we must not fill them in.
+ */
+ DBGC ( &pxe_netdev, " PCI %02x:%02x.%x %04x:%04x "
+ "('%04x:%04x') %02x%02x%02x rev %02x\n",
+ PCI_BUS ( info->BusDevFunc ),
+ PCI_SLOT ( info->BusDevFunc ),
+ PCI_FUNC ( info->BusDevFunc ), info->Vendor_ID,
+ info->Dev_ID, info->SubVendor_ID, info->SubDevice_ID,
+ info->Base_Class, info->Sub_Class, info->Prog_Intf,
+ info->Rev );
+ break; }
+ case BUS_TYPE_ISAPNP: {
+ struct pnp_nic_info *info = &undi_get_nic_type->info.pnp;
+
+ undi_get_nic_type->NicType = PnP_NIC;
+ info->EISA_Dev_ID = ( ( dev->desc.vendor << 16 ) |
+ dev->desc.device );
+ info->CardSelNum = dev->desc.location;
+ /* Cheat: remaining fields are probably unnecessary,
+ * and would require adding extra code to isapnp.c.
+ */
+ DBGC ( &pxe_netdev, " ISAPnP CSN %04x %08x %02x%02x%02x\n",
+ info->CardSelNum, info->EISA_Dev_ID,
+ info->Base_Class, info->Sub_Class, info->Prog_Intf );
+ break; }
+ default:
+ DBGC ( &pxe_netdev, " failed: unknown bus type\n" );
+ undi_get_nic_type->Status = PXENV_STATUS_FAILURE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ undi_get_nic_type->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_GET_IFACE_INFO
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t
+pxenv_undi_get_iface_info ( struct s_PXENV_UNDI_GET_IFACE_INFO
+ *undi_get_iface_info ) {
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxe_netdev, "PXENV_UNDI_GET_IFACE_INFO called with "
+ "no network device\n" );
+ undi_get_iface_info->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ DBGC ( &pxe_netdev, "PXENV_UNDI_GET_IFACE_INFO" );
+
+ /* Just hand back some info, doesn't really matter what it is.
+ * Most PXE stacks seem to take this approach.
+ */
+ snprintf ( ( char * ) undi_get_iface_info->IfaceType,
+ sizeof ( undi_get_iface_info->IfaceType ), "DIX+802.3" );
+ undi_get_iface_info->LinkSpeed = 10000000; /* 10 Mbps */
+ undi_get_iface_info->ServiceFlags =
+ ( SUPPORTED_BROADCAST | SUPPORTED_MULTICAST |
+ SUPPORTED_SET_STATION_ADDRESS | SUPPORTED_RESET |
+ SUPPORTED_OPEN_CLOSE );
+ if ( netdev_irq_supported ( pxe_netdev ) )
+ undi_get_iface_info->ServiceFlags |= SUPPORTED_IRQ;
+ memset ( undi_get_iface_info->Reserved, 0,
+ sizeof(undi_get_iface_info->Reserved) );
+
+ DBGC ( &pxe_netdev, " %s %dbps flags %08x\n",
+ undi_get_iface_info->IfaceType, undi_get_iface_info->LinkSpeed,
+ undi_get_iface_info->ServiceFlags );
+ undi_get_iface_info->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/* PXENV_UNDI_GET_STATE
+ *
+ * Status: impossible due to opcode collision
+ */
+
+/* PXENV_UNDI_ISR
+ *
+ * Status: working
+ */
+static PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
+ struct io_buffer *iobuf;
+ size_t len;
+ struct ll_protocol *ll_protocol;
+ const void *ll_dest;
+ const void *ll_source;
+ uint16_t net_proto;
+ unsigned int flags;
+ size_t ll_hlen;
+ struct net_protocol *net_protocol;
+ unsigned int prottype;
+ int rc;
+
+ /* Use a different debug colour, since UNDI ISR messages are
+ * likely to be interspersed amongst other UNDI messages.
+ */
+
+ /* Sanity check */
+ if ( ! pxe_netdev ) {
+ DBGC ( &pxenv_undi_isr, "PXENV_UNDI_ISR called with "
+ "no network device\n" );
+ undi_isr->Status = PXENV_STATUS_UNDI_INVALID_STATE;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ DBGC2 ( &pxenv_undi_isr, "PXENV_UNDI_ISR" );
+
+ /* Just in case some idiot actually looks at these fields when
+ * we weren't meant to fill them in...
+ */
+ undi_isr->BufferLength = 0;
+ undi_isr->FrameLength = 0;
+ undi_isr->FrameHeaderLength = 0;
+ undi_isr->ProtType = 0;
+ undi_isr->PktType = 0;
+
+ switch ( undi_isr->FuncFlag ) {
+ case PXENV_UNDI_ISR_IN_START :
+ DBGC2 ( &pxenv_undi_isr, " START" );
+
+ /* Call poll(). This should acknowledge the device
+ * interrupt and queue up any received packet.
+ */
+ net_poll();
+
+ /* A 100% accurate determination of "OURS" vs "NOT
+ * OURS" is difficult to achieve without invasive and
+ * unpleasant changes to the driver model. We settle
+ * for always returning "OURS" if interrupts are
+ * currently enabled.
+ *
+ * Returning "NOT OURS" when interrupts are disabled
+ * allows us to avoid a potential interrupt storm when
+ * we are on a shared interrupt line; if we were to
+ * always return "OURS" then the other device's ISR
+ * may never be called.
+ */
+ if ( netdev_irq_enabled ( pxe_netdev ) ) {
+ DBGC2 ( &pxenv_undi_isr, " OURS" );
+ undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS;
+ } else {
+ DBGC2 ( &pxenv_undi_isr, " NOT OURS" );
+ undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_NOT_OURS;
+ }
+
+ /* Disable interrupts */
+ netdev_irq ( pxe_netdev, 0 );
+
+ break;
+ case PXENV_UNDI_ISR_IN_PROCESS :
+ case PXENV_UNDI_ISR_IN_GET_NEXT :
+ DBGC2 ( &pxenv_undi_isr, " %s",
+ ( ( undi_isr->FuncFlag == PXENV_UNDI_ISR_IN_PROCESS ) ?
+ "PROCESS" : "GET_NEXT" ) );
+
+ /* Some dumb NBPs (e.g. emBoot's winBoot/i) never call
+ * PXENV_UNDI_ISR with FuncFlag=PXENV_UNDI_ISR_START;
+ * they just sit in a tight polling loop merrily
+ * violating the PXE spec with repeated calls to
+ * PXENV_UNDI_ISR_IN_PROCESS. Force extra polls to
+ * cope with these out-of-spec clients.
+ */
+ net_poll();
+
+ /* If we have not yet marked a TX as complete, and the
+ * netdev TX queue is empty, report the TX completion.
+ */
+ if ( undi_tx_count && list_empty ( &pxe_netdev->tx_queue ) ) {
+ DBGC2 ( &pxenv_undi_isr, " TXC" );
+ undi_tx_count--;
+ undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_TRANSMIT;
+ break;
+ }
+
+ /* Remove first packet from netdev RX queue */
+ iobuf = netdev_rx_dequeue ( pxe_netdev );
+ if ( ! iobuf ) {
+ DBGC2 ( &pxenv_undi_isr, " DONE" );
+ /* No more packets remaining */
+ undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
+ /* Re-enable interrupts */
+ netdev_irq ( pxe_netdev, 1 );
+ break;
+ }
+
+ /* Copy packet to base memory buffer */
+ len = iob_len ( iobuf );
+ DBGC2 ( &pxenv_undi_isr, " RX" );
+ if ( len > sizeof ( basemem_packet ) ) {
+ /* Should never happen */
+ DBGC2 ( &pxenv_undi_isr, " overlength (%zx)", len );
+ len = sizeof ( basemem_packet );
+ }
+ memcpy ( basemem_packet, iobuf->data, len );
+
+ /* Strip link-layer header */
+ ll_protocol = pxe_netdev->ll_protocol;
+ if ( ( rc = ll_protocol->pull ( pxe_netdev, iobuf, &ll_dest,
+ &ll_source, &net_proto,
+ &flags ) ) != 0 ) {
+ /* Assume unknown net_proto and no ll_source */
+ net_proto = 0;
+ ll_source = NULL;
+ }
+ ll_hlen = ( len - iob_len ( iobuf ) );
+
+ /* Determine network-layer protocol */
+ switch ( net_proto ) {
+ case htons ( ETH_P_IP ):
+ net_protocol = &ipv4_protocol;
+ prottype = P_IP;
+ break;
+ case htons ( ETH_P_ARP ):
+ net_protocol = &arp_protocol;
+ prottype = P_ARP;
+ break;
+ case htons ( ETH_P_RARP ):
+ net_protocol = &rarp_protocol;
+ prottype = P_RARP;
+ break;
+ default:
+ net_protocol = NULL;
+ prottype = P_UNKNOWN;
+ break;
+ }
+
+ /* Fill in UNDI_ISR structure */
+ undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_RECEIVE;
+ undi_isr->BufferLength = len;
+ undi_isr->FrameLength = len;
+ undi_isr->FrameHeaderLength = ll_hlen;
+ undi_isr->Frame.segment = rm_ds;
+ undi_isr->Frame.offset = __from_data16 ( basemem_packet );
+ undi_isr->ProtType = prottype;
+ if ( flags & LL_BROADCAST ) {
+ undi_isr->PktType = P_BROADCAST;
+ } else if ( flags & LL_MULTICAST ) {
+ undi_isr->PktType = P_MULTICAST;
+ } else {
+ undi_isr->PktType = P_DIRECTED;
+ }
+ DBGC2 ( &pxenv_undi_isr, " %04x:%04x+%x(%x) %s hlen %d",
+ undi_isr->Frame.segment, undi_isr->Frame.offset,
+ undi_isr->BufferLength, undi_isr->FrameLength,
+ ( net_protocol ? net_protocol->name : "RAW" ),
+ undi_isr->FrameHeaderLength );
+
+ /* Free packet */
+ free_iob ( iobuf );
+ break;
+ default :
+ DBGC2 ( &pxenv_undi_isr, " INVALID(%04x)\n",
+ undi_isr->FuncFlag );
+
+ /* Should never happen */
+ undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
+ undi_isr->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
+ return PXENV_EXIT_FAILURE;
+ }
+
+ DBGC2 ( &pxenv_undi_isr, "\n" );
+ undi_isr->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}
+
+/** PXE UNDI API */
+struct pxe_api_call pxe_undi_api[] __pxe_api_call = {
+ PXE_API_CALL ( PXENV_UNDI_STARTUP, pxenv_undi_startup,
+ struct s_PXENV_UNDI_STARTUP ),
+ PXE_API_CALL ( PXENV_UNDI_CLEANUP, pxenv_undi_cleanup,
+ struct s_PXENV_UNDI_CLEANUP ),
+ PXE_API_CALL ( PXENV_UNDI_INITIALIZE, pxenv_undi_initialize,
+ struct s_PXENV_UNDI_INITIALIZE ),
+ PXE_API_CALL ( PXENV_UNDI_RESET_ADAPTER, pxenv_undi_reset_adapter,
+ struct s_PXENV_UNDI_RESET ),
+ PXE_API_CALL ( PXENV_UNDI_SHUTDOWN, pxenv_undi_shutdown,
+ struct s_PXENV_UNDI_SHUTDOWN ),
+ PXE_API_CALL ( PXENV_UNDI_OPEN, pxenv_undi_open,
+ struct s_PXENV_UNDI_OPEN ),
+ PXE_API_CALL ( PXENV_UNDI_CLOSE, pxenv_undi_close,
+ struct s_PXENV_UNDI_CLOSE ),
+ PXE_API_CALL ( PXENV_UNDI_TRANSMIT, pxenv_undi_transmit,
+ struct s_PXENV_UNDI_TRANSMIT ),
+ PXE_API_CALL ( PXENV_UNDI_SET_MCAST_ADDRESS,
+ pxenv_undi_set_mcast_address,
+ struct s_PXENV_UNDI_SET_MCAST_ADDRESS ),
+ PXE_API_CALL ( PXENV_UNDI_SET_STATION_ADDRESS,
+ pxenv_undi_set_station_address,
+ struct s_PXENV_UNDI_SET_STATION_ADDRESS ),
+ PXE_API_CALL ( PXENV_UNDI_SET_PACKET_FILTER,
+ pxenv_undi_set_packet_filter,
+ struct s_PXENV_UNDI_SET_PACKET_FILTER ),
+ PXE_API_CALL ( PXENV_UNDI_GET_INFORMATION, pxenv_undi_get_information,
+ struct s_PXENV_UNDI_GET_INFORMATION ),
+ PXE_API_CALL ( PXENV_UNDI_GET_STATISTICS, pxenv_undi_get_statistics,
+ struct s_PXENV_UNDI_GET_STATISTICS ),
+ PXE_API_CALL ( PXENV_UNDI_CLEAR_STATISTICS, pxenv_undi_clear_statistics,
+ struct s_PXENV_UNDI_CLEAR_STATISTICS ),
+ PXE_API_CALL ( PXENV_UNDI_INITIATE_DIAGS, pxenv_undi_initiate_diags,
+ struct s_PXENV_UNDI_INITIATE_DIAGS ),
+ PXE_API_CALL ( PXENV_UNDI_FORCE_INTERRUPT, pxenv_undi_force_interrupt,
+ struct s_PXENV_UNDI_FORCE_INTERRUPT ),
+ PXE_API_CALL ( PXENV_UNDI_GET_MCAST_ADDRESS,
+ pxenv_undi_get_mcast_address,
+ struct s_PXENV_UNDI_GET_MCAST_ADDRESS ),
+ PXE_API_CALL ( PXENV_UNDI_GET_NIC_TYPE, pxenv_undi_get_nic_type,
+ struct s_PXENV_UNDI_GET_NIC_TYPE ),
+ PXE_API_CALL ( PXENV_UNDI_GET_IFACE_INFO, pxenv_undi_get_iface_info,
+ struct s_PXENV_UNDI_GET_IFACE_INFO ),
+ PXE_API_CALL ( PXENV_UNDI_ISR, pxenv_undi_isr,
+ struct s_PXENV_UNDI_ISR ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxeparent/pxeparent.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxeparent/pxeparent.c
new file mode 100644
index 00000000..6f147256
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxeparent/pxeparent.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/dhcp.h>
+#include <pxeparent.h>
+#include <pxe_api.h>
+#include <pxe_types.h>
+#include <pxe.h>
+
+/** @file
+ *
+ * Call interface to parent PXE stack
+ *
+ */
+
+/**
+ * Name PXE API call
+ *
+ * @v function API call number
+ * @ret name API call name
+ */
+static inline __attribute__ (( always_inline )) const char *
+pxeparent_function_name ( unsigned int function ) {
+ switch ( function ) {
+ case PXENV_START_UNDI:
+ return "PXENV_START_UNDI";
+ case PXENV_STOP_UNDI:
+ return "PXENV_STOP_UNDI";
+ case PXENV_UNDI_STARTUP:
+ return "PXENV_UNDI_STARTUP";
+ case PXENV_UNDI_CLEANUP:
+ return "PXENV_UNDI_CLEANUP";
+ case PXENV_UNDI_INITIALIZE:
+ return "PXENV_UNDI_INITIALIZE";
+ case PXENV_UNDI_RESET_ADAPTER:
+ return "PXENV_UNDI_RESET_ADAPTER";
+ case PXENV_UNDI_SHUTDOWN:
+ return "PXENV_UNDI_SHUTDOWN";
+ case PXENV_UNDI_OPEN:
+ return "PXENV_UNDI_OPEN";
+ case PXENV_UNDI_CLOSE:
+ return "PXENV_UNDI_CLOSE";
+ case PXENV_UNDI_TRANSMIT:
+ return "PXENV_UNDI_TRANSMIT";
+ case PXENV_UNDI_SET_MCAST_ADDRESS:
+ return "PXENV_UNDI_SET_MCAST_ADDRESS";
+ case PXENV_UNDI_SET_STATION_ADDRESS:
+ return "PXENV_UNDI_SET_STATION_ADDRESS";
+ case PXENV_UNDI_SET_PACKET_FILTER:
+ return "PXENV_UNDI_SET_PACKET_FILTER";
+ case PXENV_UNDI_GET_INFORMATION:
+ return "PXENV_UNDI_GET_INFORMATION";
+ case PXENV_UNDI_GET_STATISTICS:
+ return "PXENV_UNDI_GET_STATISTICS";
+ case PXENV_UNDI_CLEAR_STATISTICS:
+ return "PXENV_UNDI_CLEAR_STATISTICS";
+ case PXENV_UNDI_INITIATE_DIAGS:
+ return "PXENV_UNDI_INITIATE_DIAGS";
+ case PXENV_UNDI_FORCE_INTERRUPT:
+ return "PXENV_UNDI_FORCE_INTERRUPT";
+ case PXENV_UNDI_GET_MCAST_ADDRESS:
+ return "PXENV_UNDI_GET_MCAST_ADDRESS";
+ case PXENV_UNDI_GET_NIC_TYPE:
+ return "PXENV_UNDI_GET_NIC_TYPE";
+ case PXENV_UNDI_GET_IFACE_INFO:
+ return "PXENV_UNDI_GET_IFACE_INFO";
+ /*
+ * Duplicate case value; this is a bug in the PXE specification.
+ *
+ * case PXENV_UNDI_GET_STATE:
+ * return "PXENV_UNDI_GET_STATE";
+ */
+ case PXENV_UNDI_ISR:
+ return "PXENV_UNDI_ISR";
+ case PXENV_GET_CACHED_INFO:
+ return "PXENV_GET_CACHED_INFO";
+ default:
+ return "UNKNOWN API CALL";
+ }
+}
+
+/**
+ * PXE parent parameter block
+ *
+ * Used as the paramter block for all parent PXE API calls. Resides in base
+ * memory.
+ */
+static union u_PXENV_ANY __bss16 ( pxeparent_params );
+#define pxeparent_params __use_data16 ( pxeparent_params )
+
+/** PXE parent entry point
+ *
+ * Used as the indirection vector for all parent PXE API calls. Resides in
+ * base memory.
+ */
+SEGOFF16_t __bss16 ( pxeparent_entry_point );
+#define pxeparent_entry_point __use_data16 ( pxeparent_entry_point )
+
+/**
+ * Issue parent PXE API call
+ *
+ * @v entry Parent PXE stack entry point
+ * @v function API call number
+ * @v params PXE parameter block
+ * @v params_len Length of PXE parameter block
+ * @ret rc Return status code
+ */
+int pxeparent_call ( SEGOFF16_t entry, unsigned int function,
+ void *params, size_t params_len ) {
+ PXENV_EXIT_t exit;
+ int discard_b, discard_D;
+ int rc;
+
+ /* Copy parameter block and entry point */
+ assert ( params_len <= sizeof ( pxeparent_params ) );
+ memcpy ( &pxeparent_params, params, params_len );
+ memcpy ( &pxeparent_entry_point, &entry, sizeof ( entry ) );
+
+ /* Call real-mode entry point. This calling convention will
+ * work with both the !PXE and the PXENV+ entry points.
+ */
+ __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
+ "pushw %%es\n\t"
+ "pushw %%di\n\t"
+ "pushw %%bx\n\t"
+ "lcall *pxeparent_entry_point\n\t"
+ "addw $6, %%sp\n\t"
+ "popl %%ebp\n\t" /* gcc bug */ )
+ : "=a" ( exit ), "=b" ( discard_b ),
+ "=D" ( discard_D )
+ : "b" ( function ),
+ "D" ( __from_data16 ( &pxeparent_params ) )
+ : "ecx", "edx", "esi" );
+
+ /* Determine return status code based on PXENV_EXIT and
+ * PXENV_STATUS
+ */
+ if ( exit == PXENV_EXIT_SUCCESS ) {
+ rc = 0;
+ } else {
+ rc = -pxeparent_params.Status;
+ /* Paranoia; don't return success for the combination
+ * of PXENV_EXIT_FAILURE but PXENV_STATUS_SUCCESS
+ */
+ if ( rc == 0 )
+ rc = -EIO;
+ }
+
+ /* If anything goes wrong, print as much debug information as
+ * it's possible to give.
+ */
+ if ( rc != 0 ) {
+ SEGOFF16_t rm_params = {
+ .segment = rm_ds,
+ .offset = __from_data16 ( &pxeparent_params ),
+ };
+
+ DBG ( "PXEPARENT %s failed: %s\n",
+ pxeparent_function_name ( function ), strerror ( rc ) );
+ DBG ( "PXEPARENT parameters at %04x:%04x length "
+ "%#02zx, entry point at %04x:%04x\n",
+ rm_params.segment, rm_params.offset, params_len,
+ pxeparent_entry_point.segment,
+ pxeparent_entry_point.offset );
+ DBG ( "PXEPARENT parameters provided:\n" );
+ DBG_HDA ( rm_params, params, params_len );
+ DBG ( "PXEPARENT parameters returned:\n" );
+ DBG_HDA ( rm_params, &pxeparent_params, params_len );
+ }
+
+ /* Copy parameter block back */
+ memcpy ( params, &pxeparent_params, params_len );
+
+ return rc;
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c
new file mode 100644
index 00000000..8fe1572f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/netdevice.h>
+#include <undipreload.h>
+#include <pxeparent.h>
+#include <realmode.h>
+#include <pxe_api.h>
+
+/**
+ * Present cached DHCP packet if it exists
+ */
+void get_cached_dhcpack ( void ) {
+ struct undi_device *undi;
+ struct s_PXENV_GET_CACHED_INFO get_cached_info;
+ int rc;
+
+ /* Use preloaded UNDI device to get at PXE entry point */
+ undi = &preloaded_undi;
+ if ( ! undi->entry.segment ) {
+ DBG ( "PXEDHCP no preloaded UNDI device found\n" );
+ return;
+ }
+
+ /* Check that stack is available to get cached info */
+ if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) {
+ DBG ( "PXEDHCP stack was unloaded, no cache available\n" );
+ return;
+ }
+
+ /* Obtain cached DHCP packet */
+ memset ( &get_cached_info, 0, sizeof ( get_cached_info ) );
+ get_cached_info.PacketType = PXENV_PACKET_TYPE_DHCP_ACK;
+
+ if ( ( rc = pxeparent_call ( undi->entry, PXENV_GET_CACHED_INFO,
+ &get_cached_info,
+ sizeof ( get_cached_info ) ) ) != 0 ) {
+ DBG ( "PXEDHCP GET_CACHED_INFO failed: %s\n", strerror ( rc ) );
+ return;
+ }
+
+ DBG ( "PXEDHCP got cached info at %04x:%04x length %d\n",
+ get_cached_info.Buffer.segment, get_cached_info.Buffer.offset,
+ get_cached_info.BufferSize );
+
+ /* Present cached DHCP packet */
+ store_cached_dhcpack ( real_to_user ( get_cached_info.Buffer.segment,
+ get_cached_info.Buffer.offset ),
+ get_cached_info.BufferSize );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/com32_call.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/com32_call.c
new file mode 100644
index 00000000..47df64cb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/com32_call.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/**
+ * @file SYSLINUX COM32 helpers
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <realmode.h>
+#include <comboot.h>
+#include <assert.h>
+#include <ipxe/uaccess.h>
+
+static com32sys_t __bss16 ( com32_regs );
+#define com32_regs __use_data16 ( com32_regs )
+
+static uint8_t __bss16 ( com32_int_vector );
+#define com32_int_vector __use_data16 ( com32_int_vector )
+
+static uint32_t __bss16 ( com32_farcall_proc );
+#define com32_farcall_proc __use_data16 ( com32_farcall_proc )
+
+uint16_t __bss16 ( com32_saved_sp );
+
+/**
+ * Interrupt call helper
+ */
+void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
+
+ memcpy_user ( virt_to_user( &com32_regs ), 0,
+ phys_to_user ( inregs_phys ), 0,
+ sizeof(com32sys_t) );
+
+ com32_int_vector = interrupt;
+
+ __asm__ __volatile__ (
+ REAL_CODE ( /* Save all registers */
+ "pushal\n\t"
+ "pushw %%ds\n\t"
+ "pushw %%es\n\t"
+ "pushw %%fs\n\t"
+ "pushw %%gs\n\t"
+ /* Mask off unsafe flags */
+ "movl (com32_regs + 40), %%eax\n\t"
+ "andl $0x200cd7, %%eax\n\t"
+ "movl %%eax, (com32_regs + 40)\n\t"
+ /* Load com32_regs into the actual registers */
+ "movw %%sp, %%ss:(com32_saved_sp)\n\t"
+ "movw $com32_regs, %%sp\n\t"
+ "popw %%gs\n\t"
+ "popw %%fs\n\t"
+ "popw %%es\n\t"
+ "popw %%ds\n\t"
+ "popal\n\t"
+ "popfl\n\t"
+ "movw %%ss:(com32_saved_sp), %%sp\n\t"
+ /* patch INT instruction */
+ "pushw %%ax\n\t"
+ "movb %%ss:(com32_int_vector), %%al\n\t"
+ "movb %%al, %%cs:(com32_intcall_instr + 1)\n\t"
+ /* perform a jump to avoid problems with cache
+ * consistency in self-modifying code on some CPUs (486)
+ */
+ "jmp 1f\n"
+ "1:\n\t"
+ "popw %%ax\n\t"
+ "com32_intcall_instr:\n\t"
+ /* INT instruction to be patched */
+ "int $0xFF\n\t"
+ /* Copy regs back to com32_regs */
+ "movw %%sp, %%ss:(com32_saved_sp)\n\t"
+ "movw $(com32_regs + 44), %%sp\n\t"
+ "pushfl\n\t"
+ "pushal\n\t"
+ "pushw %%ds\n\t"
+ "pushw %%es\n\t"
+ "pushw %%fs\n\t"
+ "pushw %%gs\n\t"
+ "movw %%ss:(com32_saved_sp), %%sp\n\t"
+ /* Restore registers */
+ "popw %%gs\n\t"
+ "popw %%fs\n\t"
+ "popw %%es\n\t"
+ "popw %%ds\n\t"
+ "popal\n\t")
+ : : );
+
+ if ( outregs_phys ) {
+ memcpy_user ( phys_to_user ( outregs_phys ), 0,
+ virt_to_user( &com32_regs ), 0,
+ sizeof(com32sys_t) );
+ }
+}
+
+/**
+ * Farcall helper
+ */
+void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
+
+ memcpy_user ( virt_to_user( &com32_regs ), 0,
+ phys_to_user ( inregs_phys ), 0,
+ sizeof(com32sys_t) );
+
+ com32_farcall_proc = proc;
+
+ __asm__ __volatile__ (
+ REAL_CODE ( /* Save all registers */
+ "pushal\n\t"
+ "pushw %%ds\n\t"
+ "pushw %%es\n\t"
+ "pushw %%fs\n\t"
+ "pushw %%gs\n\t"
+ /* Mask off unsafe flags */
+ "movl (com32_regs + 40), %%eax\n\t"
+ "andl $0x200cd7, %%eax\n\t"
+ "movl %%eax, (com32_regs + 40)\n\t"
+ /* Load com32_regs into the actual registers */
+ "movw %%sp, %%ss:(com32_saved_sp)\n\t"
+ "movw $com32_regs, %%sp\n\t"
+ "popw %%gs\n\t"
+ "popw %%fs\n\t"
+ "popw %%es\n\t"
+ "popw %%ds\n\t"
+ "popal\n\t"
+ "popfl\n\t"
+ "movw %%ss:(com32_saved_sp), %%sp\n\t"
+ /* Call procedure */
+ "lcall *%%ss:(com32_farcall_proc)\n\t"
+ /* Copy regs back to com32_regs */
+ "movw %%sp, %%ss:(com32_saved_sp)\n\t"
+ "movw $(com32_regs + 44), %%sp\n\t"
+ "pushfl\n\t"
+ "pushal\n\t"
+ "pushw %%ds\n\t"
+ "pushw %%es\n\t"
+ "pushw %%fs\n\t"
+ "pushw %%gs\n\t"
+ "movw %%ss:(com32_saved_sp), %%sp\n\t"
+ /* Restore registers */
+ "popw %%gs\n\t"
+ "popw %%fs\n\t"
+ "popw %%es\n\t"
+ "popw %%ds\n\t"
+ "popal\n\t")
+ : : );
+
+ if ( outregs_phys ) {
+ memcpy_user ( phys_to_user ( outregs_phys ), 0,
+ virt_to_user( &com32_regs ), 0,
+ sizeof(com32sys_t) );
+ }
+}
+
+/**
+ * CDECL farcall helper
+ */
+int __asmcall com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz ) {
+ int32_t eax;
+
+ copy_user_to_rm_stack ( phys_to_user ( stack ), stacksz );
+ com32_farcall_proc = proc;
+
+ __asm__ __volatile__ (
+ REAL_CODE ( "lcall *%%ss:(com32_farcall_proc)\n\t" )
+ : "=a" (eax)
+ :
+ : "ecx", "edx" );
+
+ remove_user_from_rm_stack ( 0, stacksz );
+
+ return eax;
+}
+
+/**
+ * IRQ handler
+ */
+void __asmcall com32_irq ( uint32_t vector ) {
+ uint32_t *ivt_entry = phys_to_virt( vector * 4 );
+
+ __asm__ __volatile__ (
+ REAL_CODE ( "pushfw\n\t"
+ "pushw %%cs\n\t"
+ "pushw $com32_irq_return\n\t"
+ "pushl %0\n\t"
+ "lret\n"
+ "com32_irq_return:\n\t" )
+ : /* no outputs */
+ : "r" ( *ivt_entry ) );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/com32_wrapper.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/com32_wrapper.S
new file mode 100644
index 00000000..4cd88221
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/com32_wrapper.S
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .text
+ .arch i386
+ .code32
+
+ /*
+ * This code is entered after running the following sequence out of
+ * the interrupt jump buffer:
+ *
+ * pushal
+ * movb $vector, %al
+ * jmp com32_irq_wrapper
+ */
+
+ .globl com32_irq_wrapper
+com32_irq_wrapper:
+
+ movzbl %al,%eax
+ pushl %eax
+ movl $com32_irq, %eax
+ call com32_wrapper
+ popl %eax
+ popal
+ iret
+
+ .globl com32_farcall_wrapper
+com32_farcall_wrapper:
+
+ movl $com32_farcall, %eax
+ jmp com32_wrapper
+
+
+ .globl com32_cfarcall_wrapper
+com32_cfarcall_wrapper:
+
+ movl $com32_cfarcall, %eax
+ jmp com32_wrapper
+
+
+ .globl com32_intcall_wrapper
+com32_intcall_wrapper:
+
+ movl $com32_intcall, %eax
+ /*jmp com32_wrapper*/ /* fall through */
+
+com32_wrapper:
+ cli
+
+ /* Switch to internal virtual address space */
+ call _phys_to_virt
+
+ /* Switch to internal IDT (if we have one for debugging) */
+ lidt com32_internal_idtr
+
+ mov %eax, (com32_helper_function)
+
+ /* Save external COM32 stack pointer */
+ movl %esp, (com32_external_esp)
+
+ /* Copy arguments to caller-save registers */
+ movl 12(%esp), %eax
+ movl 8(%esp), %ecx
+ movl 4(%esp), %edx
+
+ /* Switch to internal stack */
+ movl (com32_internal_esp), %esp
+
+ /* Copy arguments to internal stack */
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+
+ call *(com32_helper_function)
+
+ /* Clean up stack */
+ addl $12, %esp
+
+ /* Save internal stack pointer and restore external stack pointer */
+ movl %esp, (com32_internal_esp)
+ movl (com32_external_esp), %esp
+
+ /* Switch to com32 IDT */
+ lidt com32_external_idtr
+
+ /* Switch to external flat physical address space */
+ call _virt_to_phys
+
+ sti
+ ret
+
+
+ .data
+
+/* Internal iPXE virtual address space %esp */
+.globl com32_internal_esp
+.lcomm com32_internal_esp, 4
+
+/* External flat physical address space %esp */
+.globl com32_external_esp
+.lcomm com32_external_esp, 4
+
+/* Function pointer of helper to call */
+.lcomm com32_helper_function, 4
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/comboot_call.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/comboot_call.c
new file mode 100644
index 00000000..7ee5f61b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/comboot_call.c
@@ -0,0 +1,707 @@
+/*
+ * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/**
+ * @file SYSLINUX COMBOOT API
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <realmode.h>
+#include <biosint.h>
+#include <ipxe/console.h>
+#include <stdlib.h>
+#include <comboot.h>
+#include <bzimage.h>
+#include <pxe_call.h>
+#include <setjmp.h>
+#include <string.h>
+#include <ipxe/posix_io.h>
+#include <ipxe/process.h>
+#include <ipxe/serial.h>
+#include <ipxe/init.h>
+#include <ipxe/image.h>
+#include <usr/imgmgmt.h>
+#include "config/console.h"
+#include "config/serial.h"
+
+/** The "SYSLINUX" version string */
+static char __data16_array ( syslinux_version, [] ) = "\r\niPXE " VERSION;
+#define syslinux_version __use_data16 ( syslinux_version )
+
+/** The "SYSLINUX" copyright string */
+static char __data16_array ( syslinux_copyright, [] ) = " http://ipxe.org";
+#define syslinux_copyright __use_data16 ( syslinux_copyright )
+
+static char __data16_array ( syslinux_configuration_file, [] ) = "";
+#define syslinux_configuration_file __use_data16 ( syslinux_configuration_file )
+
+/** Feature flags */
+static uint8_t __data16 ( comboot_feature_flags ) = COMBOOT_FEATURE_IDLE_LOOP;
+#define comboot_feature_flags __use_data16 ( comboot_feature_flags )
+
+typedef union {
+ syslinux_pm_regs pm; syslinux_rm_regs rm;
+} syslinux_regs;
+
+/** Initial register values for INT 22h AX=1Ah and 1Bh */
+static syslinux_regs __text16 ( comboot_initial_regs );
+#define comboot_initial_regs __use_text16 ( comboot_initial_regs )
+
+static struct segoff __text16 ( int20_vector );
+#define int20_vector __use_text16 ( int20_vector )
+
+static struct segoff __text16 ( int21_vector );
+#define int21_vector __use_text16 ( int21_vector )
+
+static struct segoff __text16 ( int22_vector );
+#define int22_vector __use_text16 ( int22_vector )
+
+extern void int20_wrapper ( void );
+extern void int21_wrapper ( void );
+extern void int22_wrapper ( void );
+
+/* setjmp/longjmp context buffer used to return after loading an image */
+rmjmp_buf comboot_return;
+
+/* Mode flags set by INT 22h AX=0017h */
+static uint16_t comboot_graphics_mode = 0;
+
+
+/**
+ * Print a string with a particular terminator
+ */
+static void print_user_string ( unsigned int segment, unsigned int offset, char terminator ) {
+ int i = 0;
+ char c;
+ userptr_t str = real_to_user ( segment, offset );
+ for ( ; ; ) {
+ copy_from_user ( &c, str, i, 1 );
+ if ( c == terminator ) break;
+ putchar ( c );
+ i++;
+ }
+}
+
+
+/**
+ * Perform a series of memory copies from a list in low memory
+ */
+static void shuffle ( unsigned int list_segment, unsigned int list_offset, unsigned int count )
+{
+ comboot_shuffle_descriptor shuf[COMBOOT_MAX_SHUFFLE_DESCRIPTORS];
+ unsigned int i;
+
+ /* Copy shuffle descriptor list so it doesn't get overwritten */
+ copy_from_user ( shuf, real_to_user ( list_segment, list_offset ), 0,
+ count * sizeof( comboot_shuffle_descriptor ) );
+
+ /* Do the copies */
+ for ( i = 0; i < count; i++ ) {
+ userptr_t src_u = phys_to_user ( shuf[ i ].src );
+ userptr_t dest_u = phys_to_user ( shuf[ i ].dest );
+
+ if ( shuf[ i ].src == 0xFFFFFFFF ) {
+ /* Fill with 0 instead of copying */
+ memset_user ( dest_u, 0, 0, shuf[ i ].len );
+ } else if ( shuf[ i ].dest == 0xFFFFFFFF ) {
+ /* Copy new list of descriptors */
+ count = shuf[ i ].len / sizeof( comboot_shuffle_descriptor );
+ assert ( count <= COMBOOT_MAX_SHUFFLE_DESCRIPTORS );
+ copy_from_user ( shuf, src_u, 0, shuf[ i ].len );
+ i = -1;
+ } else {
+ /* Regular copy */
+ memmove_user ( dest_u, 0, src_u, 0, shuf[ i ].len );
+ }
+ }
+}
+
+
+/**
+ * Set default text mode
+ */
+void comboot_force_text_mode ( void ) {
+ if ( comboot_graphics_mode & COMBOOT_VIDEO_VESA ) {
+ /* Set VGA mode 3 via VESA VBE mode set */
+ __asm__ __volatile__ (
+ REAL_CODE (
+ "mov $0x4F02, %%ax\n\t"
+ "mov $0x03, %%bx\n\t"
+ "int $0x10\n\t"
+ )
+ : : );
+ } else if ( comboot_graphics_mode & COMBOOT_VIDEO_GRAPHICS ) {
+ /* Set VGA mode 3 via standard VGA mode set */
+ __asm__ __volatile__ (
+ REAL_CODE (
+ "mov $0x03, %%ax\n\t"
+ "int $0x10\n\t"
+ )
+ : : );
+ }
+
+ comboot_graphics_mode = 0;
+}
+
+
+/**
+ * Fetch kernel and optional initrd
+ */
+static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) {
+ struct image *kernel;
+ struct image *initrd;
+ char *initrd_file;
+ int rc;
+
+ /* Find initrd= parameter, if any */
+ if ( ( initrd_file = strstr ( cmdline, "initrd=" ) ) != NULL ) {
+ char *initrd_end;
+
+ /* skip "initrd=" */
+ initrd_file += 7;
+
+ /* Find terminating space, if any, and replace with NUL */
+ initrd_end = strchr ( initrd_file, ' ' );
+ if ( initrd_end )
+ *initrd_end = '\0';
+
+ DBG ( "COMBOOT: fetching initrd '%s'\n", initrd_file );
+
+ /* Fetch initrd */
+ if ( ( rc = imgdownload_string ( initrd_file, &initrd ) ) != 0){
+ DBG ( "COMBOOT: could not fetch initrd: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Restore space after initrd name, if applicable */
+ if ( initrd_end )
+ *initrd_end = ' ';
+ }
+
+ DBG ( "COMBOOT: fetching kernel '%s'\n", kernel_file );
+
+ /* Fetch kernel */
+ if ( ( rc = imgdownload_string ( kernel_file, &kernel ) ) != 0 ) {
+ DBG ( "COMBOOT: could not fetch kernel: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Replace comboot image with kernel */
+ if ( ( rc = image_replace ( kernel ) ) != 0 ) {
+ DBG ( "COMBOOT: could not replace with kernel: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Terminate program interrupt handler
+ */
+static __asmcall void int20 ( struct i386_all_regs *ix86 __unused ) {
+ rmlongjmp ( comboot_return, COMBOOT_EXIT );
+}
+
+
+/**
+ * DOS-compatible API
+ */
+static __asmcall void int21 ( struct i386_all_regs *ix86 ) {
+ ix86->flags |= CF;
+
+ switch ( ix86->regs.ah ) {
+ case 0x00:
+ case 0x4C: /* Terminate program */
+ rmlongjmp ( comboot_return, COMBOOT_EXIT );
+ break;
+
+ case 0x01: /* Get Key with Echo */
+ case 0x08: /* Get Key without Echo */
+ /* TODO: handle extended characters? */
+ ix86->regs.al = getchar( );
+
+ /* Enter */
+ if ( ix86->regs.al == 0x0A )
+ ix86->regs.al = 0x0D;
+
+ if ( ix86->regs.ah == 0x01 )
+ putchar ( ix86->regs.al );
+
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x02: /* Write Character */
+ putchar ( ix86->regs.dl );
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x04: /* Write Character to Serial Port */
+ serial_putc ( ix86->regs.dl );
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x09: /* Write DOS String to Console */
+ print_user_string ( ix86->segs.ds, ix86->regs.dx, '$' );
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x0B: /* Check Keyboard */
+ if ( iskey() )
+ ix86->regs.al = 0xFF;
+ else
+ ix86->regs.al = 0x00;
+
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x30: /* Check DOS Version */
+ /* Bottom halves all 0; top halves spell "SYSLINUX" */
+ ix86->regs.eax = 0x59530000;
+ ix86->regs.ebx = 0x4C530000;
+ ix86->regs.ecx = 0x4E490000;
+ ix86->regs.edx = 0x58550000;
+ ix86->flags &= ~CF;
+ break;
+
+ default:
+ DBG ( "COMBOOT unknown int21 function %02x\n", ix86->regs.ah );
+ break;
+ }
+}
+
+
+/**
+ * Dispatch PXE API call weakly
+ *
+ * @v ix86 Registers for PXE call
+ * @ret present Zero if the PXE stack is present, nonzero if not
+ *
+ * A successful return only indicates that the PXE stack was available
+ * for dispatching the call; it says nothing about the success of
+ * whatever the call asked for.
+ */
+__weak int pxe_api_call_weak ( struct i386_all_regs *ix86 __unused ) {
+ return -1;
+}
+
+/**
+ * SYSLINUX API
+ */
+static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
+ ix86->flags |= CF;
+
+ switch ( ix86->regs.ax ) {
+ case 0x0001: /* Get Version */
+
+ /* Number of INT 22h API functions available */
+ ix86->regs.ax = 0x001D;
+
+ /* SYSLINUX version number */
+ ix86->regs.ch = 0; /* major */
+ ix86->regs.cl = 0; /* minor */
+
+ /* SYSLINUX derivative ID */
+ ix86->regs.dl = BZI_LOADER_TYPE_IPXE;
+
+ /* SYSLINUX version and copyright strings */
+ ix86->segs.es = rm_ds;
+ ix86->regs.si = ( ( unsigned ) __from_data16 ( syslinux_version ) );
+ ix86->regs.di = ( ( unsigned ) __from_data16 ( syslinux_copyright ) );
+
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x0002: /* Write String */
+ print_user_string ( ix86->segs.es, ix86->regs.bx, '\0' );
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x0003: /* Run command */
+ {
+ userptr_t cmd_u = real_to_user ( ix86->segs.es, ix86->regs.bx );
+ int len = strlen_user ( cmd_u, 0 );
+ char cmd[len + 1];
+ copy_from_user ( cmd, cmd_u, 0, len + 1 );
+ DBG ( "COMBOOT: executing command '%s'\n", cmd );
+ system ( cmd );
+ DBG ( "COMBOOT: exiting after executing command...\n" );
+ rmlongjmp ( comboot_return, COMBOOT_EXIT_COMMAND );
+ }
+ break;
+
+ case 0x0004: /* Run default command */
+ /* FIXME: just exit for now */
+ rmlongjmp ( comboot_return, COMBOOT_EXIT_COMMAND );
+ break;
+
+ case 0x0005: /* Force text mode */
+ comboot_force_text_mode ( );
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x0006: /* Open file */
+ {
+ int fd;
+ userptr_t file_u = real_to_user ( ix86->segs.es, ix86->regs.si );
+ int len = strlen_user ( file_u, 0 );
+ char file[len + 1];
+
+ copy_from_user ( file, file_u, 0, len + 1 );
+
+ if ( file[0] == '\0' ) {
+ DBG ( "COMBOOT: attempted open with empty file name\n" );
+ break;
+ }
+
+ DBG ( "COMBOOT: opening file '%s'\n", file );
+
+ fd = open ( file );
+
+ if ( fd < 0 ) {
+ DBG ( "COMBOOT: error opening file %s\n", file );
+ break;
+ }
+
+ /* This relies on the fact that a iPXE POSIX fd will
+ * always fit in 16 bits.
+ */
+#if (POSIX_FD_MAX > 65535)
+#error POSIX_FD_MAX too large
+#endif
+ ix86->regs.si = (uint16_t) fd;
+
+ ix86->regs.cx = COMBOOT_FILE_BLOCKSZ;
+ ix86->regs.eax = fsize ( fd );
+ ix86->flags &= ~CF;
+ }
+ break;
+
+ case 0x0007: /* Read file */
+ {
+ int fd = ix86->regs.si;
+ int len = ix86->regs.cx * COMBOOT_FILE_BLOCKSZ;
+ int rc;
+ fd_set fds;
+ userptr_t buf = real_to_user ( ix86->segs.es, ix86->regs.bx );
+
+ /* Wait for data ready to read */
+ FD_ZERO ( &fds );
+ FD_SET ( fd, &fds );
+
+ select ( &fds, 1 );
+
+ rc = read_user ( fd, buf, 0, len );
+ if ( rc < 0 ) {
+ DBG ( "COMBOOT: read failed\n" );
+ ix86->regs.si = 0;
+ break;
+ }
+
+ ix86->regs.ecx = rc;
+ ix86->flags &= ~CF;
+ }
+ break;
+
+ case 0x0008: /* Close file */
+ {
+ int fd = ix86->regs.si;
+ close ( fd );
+ ix86->flags &= ~CF;
+ }
+ break;
+
+ case 0x0009: /* Call PXE Stack */
+ if ( pxe_api_call_weak ( ix86 ) != 0 )
+ ix86->flags |= CF;
+ else
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x000A: /* Get Derivative-Specific Information */
+
+ /* iPXE has its own derivative ID, so there is no defined
+ * output here; just return AL for now */
+ ix86->regs.al = BZI_LOADER_TYPE_IPXE;
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x000B: /* Get Serial Console Configuration */
+#if defined(CONSOLE_SERIAL) && !defined(COMPRESERVE)
+ ix86->regs.dx = COMCONSOLE;
+ ix86->regs.cx = 115200 / COMSPEED;
+ ix86->regs.bx = 0;
+#else
+ ix86->regs.dx = 0;
+#endif
+
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x000E: /* Get configuration file name */
+ /* FIXME: stub */
+ ix86->segs.es = rm_ds;
+ ix86->regs.bx = ( ( unsigned ) __from_data16 ( syslinux_configuration_file ) );
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x000F: /* Get IPAPPEND strings */
+ /* FIXME: stub */
+ ix86->regs.cx = 0;
+ ix86->segs.es = 0;
+ ix86->regs.bx = 0;
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x0010: /* Resolve hostname */
+ {
+ userptr_t hostname_u = real_to_user ( ix86->segs.es, ix86->regs.bx );
+ int len = strlen_user ( hostname_u, 0 );
+ char hostname[len];
+ struct in_addr addr;
+
+ copy_from_user ( hostname, hostname_u, 0, len + 1 );
+
+ /* TODO:
+ * "If the hostname does not contain a dot (.), the
+ * local domain name is automatically appended."
+ */
+
+ comboot_resolv ( hostname, &addr );
+
+ ix86->regs.eax = addr.s_addr;
+ ix86->flags &= ~CF;
+ }
+ break;
+
+ case 0x0011: /* Maximum number of shuffle descriptors */
+ ix86->regs.cx = COMBOOT_MAX_SHUFFLE_DESCRIPTORS;
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x0012: /* Cleanup, shuffle and boot */
+ if ( ix86->regs.cx > COMBOOT_MAX_SHUFFLE_DESCRIPTORS )
+ break;
+
+ /* Perform final cleanup */
+ shutdown_boot();
+
+ /* Perform sequence of copies */
+ shuffle ( ix86->segs.es, ix86->regs.di, ix86->regs.cx );
+
+ /* Jump to real-mode entry point */
+ __asm__ __volatile__ (
+ REAL_CODE (
+ "pushw %0\n\t"
+ "popw %%ds\n\t"
+ "pushl %1\n\t"
+ "lret\n\t"
+ )
+ :
+ : "r" ( ix86->segs.ds ),
+ "r" ( ix86->regs.ebp ),
+ "d" ( ix86->regs.ebx ),
+ "S" ( ix86->regs.esi ) );
+
+ assert ( 0 ); /* Execution should never reach this point */
+
+ break;
+
+ case 0x0013: /* Idle loop call */
+ step ( );
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x0015: /* Get feature flags */
+ ix86->segs.es = rm_ds;
+ ix86->regs.bx = ( ( unsigned ) __from_data16 ( &comboot_feature_flags ) );
+ ix86->regs.cx = 1; /* Number of feature flag bytes */
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x0016: /* Run kernel image */
+ {
+ userptr_t file_u = real_to_user ( ix86->segs.ds, ix86->regs.si );
+ userptr_t cmd_u = real_to_user ( ix86->segs.es, ix86->regs.bx );
+ int file_len = strlen_user ( file_u, 0 );
+ int cmd_len = strlen_user ( cmd_u, 0 );
+ char file[file_len + 1];
+ char cmd[cmd_len + 1];
+
+ copy_from_user ( file, file_u, 0, file_len + 1 );
+ copy_from_user ( cmd, cmd_u, 0, cmd_len + 1 );
+
+ DBG ( "COMBOOT: run kernel %s %s\n", file, cmd );
+ comboot_fetch_kernel ( file, cmd );
+ /* Technically, we should return if we
+ * couldn't load the kernel, but it's not safe
+ * to do that since we have just overwritten
+ * part of the COMBOOT program's memory space.
+ */
+ DBG ( "COMBOOT: exiting to run kernel...\n" );
+ rmlongjmp ( comboot_return, COMBOOT_EXIT_RUN_KERNEL );
+ }
+ break;
+
+ case 0x0017: /* Report video mode change */
+ comboot_graphics_mode = ix86->regs.bx;
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x0018: /* Query custom font */
+ /* FIXME: stub */
+ ix86->regs.al = 0;
+ ix86->segs.es = 0;
+ ix86->regs.bx = 0;
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x001B: /* Cleanup, shuffle and boot to real mode */
+ if ( ix86->regs.cx > COMBOOT_MAX_SHUFFLE_DESCRIPTORS )
+ break;
+
+ /* Perform final cleanup */
+ shutdown_boot();
+
+ /* Perform sequence of copies */
+ shuffle ( ix86->segs.es, ix86->regs.di, ix86->regs.cx );
+
+ /* Copy initial register values to .text16 */
+ memcpy_user ( real_to_user ( rm_cs, (unsigned) __from_text16 ( &comboot_initial_regs ) ), 0,
+ real_to_user ( ix86->segs.ds, ix86->regs.si ), 0,
+ sizeof(syslinux_rm_regs) );
+
+ /* Load initial register values */
+ __asm__ __volatile__ (
+ REAL_CODE (
+ /* Point SS:SP at the register value structure */
+ "pushw %%cs\n\t"
+ "popw %%ss\n\t"
+ "movw $comboot_initial_regs, %%sp\n\t"
+
+ /* Segment registers */
+ "popw %%es\n\t"
+ "popw %%ax\n\t" /* Skip CS */
+ "popw %%ds\n\t"
+ "popw %%ax\n\t" /* Skip SS for now */
+ "popw %%fs\n\t"
+ "popw %%gs\n\t"
+
+ /* GP registers */
+ "popl %%eax\n\t"
+ "popl %%ecx\n\t"
+ "popl %%edx\n\t"
+ "popl %%ebx\n\t"
+ "popl %%ebp\n\t" /* Skip ESP for now */
+ "popl %%ebp\n\t"
+ "popl %%esi\n\t"
+ "popl %%edi\n\t"
+
+ /* Load correct SS:ESP */
+ "movw $(comboot_initial_regs + 6), %%sp\n\t"
+ "popw %%ss\n\t"
+ "movl %%cs:(comboot_initial_regs + 28), %%esp\n\t"
+
+ "ljmp *%%cs:(comboot_initial_regs + 44)\n\t"
+ )
+ : : );
+
+ break;
+
+ case 0x001C: /* Get pointer to auxilliary data vector */
+ /* FIXME: stub */
+ ix86->regs.cx = 0; /* Size of the ADV */
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x001D: /* Write auxilliary data vector */
+ /* FIXME: stub */
+ ix86->flags &= ~CF;
+ break;
+
+ default:
+ DBG ( "COMBOOT unknown int22 function %04x\n", ix86->regs.ax );
+ break;
+ }
+}
+
+/**
+ * Hook BIOS interrupts related to COMBOOT API (INT 20h, 21h, 22h)
+ */
+void hook_comboot_interrupts ( ) {
+
+ __asm__ __volatile__ (
+ TEXT16_CODE ( "\nint20_wrapper:\n\t"
+ "pushl %0\n\t"
+ "pushw %%cs\n\t"
+ "call prot_call\n\t"
+ "addw $4, %%sp\n\t"
+ "call patch_cf\n\t"
+ "iret\n\t" )
+ : : "i" ( int20 ) );
+
+ hook_bios_interrupt ( 0x20, ( unsigned int ) int20_wrapper,
+ &int20_vector );
+
+ __asm__ __volatile__ (
+ TEXT16_CODE ( "\nint21_wrapper:\n\t"
+ "pushl %0\n\t"
+ "pushw %%cs\n\t"
+ "call prot_call\n\t"
+ "addw $4, %%sp\n\t"
+ "call patch_cf\n\t"
+ "iret\n\t" )
+ : : "i" ( int21 ) );
+
+ hook_bios_interrupt ( 0x21, ( unsigned int ) int21_wrapper,
+ &int21_vector );
+
+ __asm__ __volatile__ (
+ TEXT16_CODE ( "\nint22_wrapper:\n\t"
+ "pushl %0\n\t"
+ "pushw %%cs\n\t"
+ "call prot_call\n\t"
+ "addw $4, %%sp\n\t"
+ "call patch_cf\n\t"
+ "iret\n\t" )
+ : : "i" ( int22) );
+
+ hook_bios_interrupt ( 0x22, ( unsigned int ) int22_wrapper,
+ &int22_vector );
+}
+
+/**
+ * Unhook BIOS interrupts related to COMBOOT API (INT 20h, 21h, 22h)
+ */
+void unhook_comboot_interrupts ( ) {
+
+ unhook_bios_interrupt ( 0x20, ( unsigned int ) int20_wrapper,
+ &int20_vector );
+
+ unhook_bios_interrupt ( 0x21, ( unsigned int ) int21_wrapper,
+ &int21_vector );
+
+ unhook_bios_interrupt ( 0x22, ( unsigned int ) int22_wrapper,
+ &int22_vector );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/comboot_resolv.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/comboot_resolv.c
new file mode 100644
index 00000000..03bbfd04
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/syslinux/comboot_resolv.c
@@ -0,0 +1,61 @@
+#include <errno.h>
+#include <comboot.h>
+#include <ipxe/in.h>
+#include <ipxe/list.h>
+#include <ipxe/process.h>
+#include <ipxe/resolv.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct comboot_resolver {
+ struct interface intf;
+ int rc;
+ struct in_addr addr;
+};
+
+static void comboot_resolv_close ( struct comboot_resolver *comboot_resolver,
+ int rc ) {
+ comboot_resolver->rc = rc;
+ intf_shutdown ( &comboot_resolver->intf, rc );
+}
+
+static void comboot_resolv_done ( struct comboot_resolver *comboot_resolver,
+ struct sockaddr *sa ) {
+ struct sockaddr_in *sin;
+
+ if ( sa->sa_family == AF_INET ) {
+ sin = ( ( struct sockaddr_in * ) sa );
+ comboot_resolver->addr = sin->sin_addr;
+ }
+}
+
+static struct interface_operation comboot_resolv_op[] = {
+ INTF_OP ( intf_close, struct comboot_resolver *, comboot_resolv_close ),
+ INTF_OP ( resolv_done, struct comboot_resolver *, comboot_resolv_done ),
+};
+
+static struct interface_descriptor comboot_resolv_desc =
+ INTF_DESC ( struct comboot_resolver, intf, comboot_resolv_op );
+
+static struct comboot_resolver comboot_resolver = {
+ .intf = INTF_INIT ( comboot_resolv_desc ),
+};
+
+int comboot_resolv ( const char *name, struct in_addr *address ) {
+ int rc;
+
+ comboot_resolver.rc = -EINPROGRESS;
+ comboot_resolver.addr.s_addr = 0;
+
+ if ( ( rc = resolv ( &comboot_resolver.intf, name, NULL ) ) != 0 )
+ return rc;
+
+ while ( comboot_resolver.rc == -EINPROGRESS )
+ step();
+
+ if ( ! comboot_resolver.addr.s_addr )
+ return -EAFNOSUPPORT;
+
+ *address = comboot_resolver.addr;
+ return comboot_resolver.rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/guestinfo.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/guestinfo.c
new file mode 100644
index 00000000..5f73e949
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/guestinfo.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * VMware GuestInfo settings
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/init.h>
+#include <ipxe/settings.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/guestrpc.h>
+
+/** GuestInfo GuestRPC channel */
+static int guestinfo_channel;
+
+/**
+ * Fetch value of typed GuestInfo setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v type Setting type to attempt (or NULL for default)
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret found Setting found in GuestInfo
+ * @ret len Length of setting data, or negative error
+ */
+static int guestinfo_fetch_type ( struct settings *settings,
+ struct setting *setting,
+ struct setting_type *type,
+ void *data, size_t len, int *found ) {
+ const char *parent_name = settings->parent->name;
+ char command[ 24 /* "info-get guestinfo.ipxe." */ +
+ strlen ( parent_name ) + 1 /* "." */ +
+ strlen ( setting->name ) + 1 /* "." */ +
+ ( type ? strlen ( type->name ) : 0 ) + 1 /* NUL */ ];
+ struct setting *named_setting;
+ char *info;
+ int info_len;
+ int check_len;
+ int ret;
+
+ /* Construct info-get command */
+ snprintf ( command, sizeof ( command ),
+ "info-get guestinfo.ipxe.%s%s%s%s%s",
+ parent_name, ( parent_name[0] ? "." : "" ), setting->name,
+ ( type ? "." : "" ), ( type ? type->name : "" ) );
+
+ /* Check for existence and obtain length of GuestInfo value */
+ info_len = guestrpc_command ( guestinfo_channel, command, NULL, 0 );
+ if ( info_len < 0 ) {
+ ret = info_len;
+ goto err_get_info_len;
+ }
+
+ /* Mark as found */
+ *found = 1;
+
+ /* Determine default type if necessary */
+ if ( ! type ) {
+ named_setting = find_setting ( setting->name );
+ type = ( named_setting ?
+ named_setting->type : &setting_type_string );
+ }
+ assert ( type != NULL );
+
+ /* Allocate temporary block to hold GuestInfo value */
+ info = zalloc ( info_len + 1 /* NUL */ );
+ if ( ! info ) {
+ DBGC ( settings, "GuestInfo %p could not allocate %zd bytes\n",
+ settings, info_len );
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+ info[info_len] = '\0';
+
+ /* Fetch GuestInfo value */
+ check_len = guestrpc_command ( guestinfo_channel, command,
+ info, info_len );
+ if ( check_len < 0 ) {
+ ret = check_len;
+ goto err_get_info;
+ }
+ if ( check_len != info_len ) {
+ DBGC ( settings, "GuestInfo %p length mismatch (expected %d, "
+ "got %d)\n", settings, info_len, check_len );
+ ret = -EIO;
+ goto err_get_info;
+ }
+ DBGC2 ( settings, "GuestInfo %p found %s = \"%s\"\n",
+ settings, &command[9] /* Skip "info-get " */, info );
+
+ /* Parse GuestInfo value according to type */
+ ret = type->parse ( info, data, len );
+ if ( ret < 0 ) {
+ DBGC ( settings, "GuestInfo %p could not parse \"%s\" as %s: "
+ "%s\n", settings, info, type->name, strerror ( ret ) );
+ goto err_parse;
+ }
+
+ err_parse:
+ err_get_info:
+ free ( info );
+ err_alloc:
+ err_get_info_len:
+ return ret;
+}
+
+/**
+ * Fetch value of GuestInfo setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+static int guestinfo_fetch ( struct settings *settings,
+ struct setting *setting,
+ void *data, size_t len ) {
+ struct setting_type *type;
+ int found = 0;
+ int ret;
+
+ /* Try default type first */
+ ret = guestinfo_fetch_type ( settings, setting, NULL,
+ data, len, &found );
+ if ( found )
+ return ret;
+
+ /* Otherwise, try all possible types */
+ for_each_table_entry ( type, SETTING_TYPES ) {
+ ret = guestinfo_fetch_type ( settings, setting, type,
+ data, len, &found );
+ if ( found )
+ return ret;
+ }
+
+ /* Not found */
+ return -ENOENT;
+}
+
+/** GuestInfo settings operations */
+static struct settings_operations guestinfo_settings_operations = {
+ .fetch = guestinfo_fetch,
+};
+
+/** GuestInfo settings */
+static struct settings guestinfo_settings = {
+ .refcnt = NULL,
+ .siblings = LIST_HEAD_INIT ( guestinfo_settings.siblings ),
+ .children = LIST_HEAD_INIT ( guestinfo_settings.children ),
+ .op = &guestinfo_settings_operations,
+};
+
+/** Initialise GuestInfo settings */
+static void guestinfo_init ( void ) {
+ int rc;
+
+ /* Open GuestRPC channel */
+ guestinfo_channel = guestrpc_open();
+ if ( guestinfo_channel < 0 ) {
+ rc = guestinfo_channel;
+ DBG ( "GuestInfo could not open channel: %s\n",
+ strerror ( rc ) );
+ return;
+ }
+
+ /* Register root GuestInfo settings */
+ if ( ( rc = register_settings ( &guestinfo_settings, NULL,
+ "vmware" ) ) != 0 ) {
+ DBG ( "GuestInfo could not register settings: %s\n",
+ strerror ( rc ) );
+ return;
+ }
+}
+
+/** GuestInfo settings initialiser */
+struct init_fn guestinfo_init_fn __init_fn ( INIT_NORMAL ) = {
+ .initialise = guestinfo_init,
+};
+
+/**
+ * Create per-netdevice GuestInfo settings
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int guestinfo_net_probe ( struct net_device *netdev ) {
+ struct settings *settings;
+ int rc;
+
+ /* Do nothing unless we have a GuestInfo channel available */
+ if ( guestinfo_channel < 0 )
+ return 0;
+
+ /* Allocate and initialise settings block */
+ settings = zalloc ( sizeof ( *settings ) );
+ if ( ! settings ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ settings_init ( settings, &guestinfo_settings_operations, NULL, 0 );
+
+ /* Register settings */
+ if ( ( rc = register_settings ( settings, netdev_settings ( netdev ),
+ "vmware" ) ) != 0 ) {
+ DBGC ( settings, "GuestInfo %p could not register for %s: %s\n",
+ settings, netdev->name, strerror ( rc ) );
+ goto err_register;
+ }
+ DBGC ( settings, "GuestInfo %p registered for %s\n",
+ settings, netdev->name );
+
+ return 0;
+
+ err_register:
+ free ( settings );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Handle network device or link state change
+ *
+ * @v netdev Network device
+ */
+static void guestinfo_net_notify ( struct net_device *netdev __unused ) {
+ /* Nothing to do */
+}
+
+/**
+ * Remove per-netdevice GuestInfo settings
+ *
+ * @v netdev Network device
+ */
+static void guestinfo_net_remove ( struct net_device *netdev ) {
+ struct settings *parent = netdev_settings ( netdev );
+ struct settings *settings;
+
+ list_for_each_entry ( settings, &parent->children, siblings ) {
+ if ( settings->op == &guestinfo_settings_operations ) {
+ DBGC ( settings, "GuestInfo %p unregistered for %s\n",
+ settings, netdev->name );
+ unregister_settings ( settings );
+ free ( settings );
+ return;
+ }
+ }
+}
+
+/** GuestInfo per-netdevice driver */
+struct net_driver guestinfo_net_driver __net_driver = {
+ .name = "GuestInfo",
+ .probe = guestinfo_net_probe,
+ .notify = guestinfo_net_notify,
+ .remove = guestinfo_net_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/guestrpc.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/guestrpc.c
new file mode 100644
index 00000000..a19e5bff
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/guestrpc.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * VMware GuestRPC mechanism
+ *
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/vmware.h>
+#include <ipxe/guestrpc.h>
+
+/* Disambiguate the various error causes */
+#define EPROTO_OPEN __einfo_error ( EINFO_EPROTO_OPEN )
+#define EINFO_EPROTO_OPEN \
+ __einfo_uniqify ( EINFO_EPROTO, 0x00, "GuestRPC open failed" )
+#define EPROTO_COMMAND_LEN __einfo_error ( EINFO_EPROTO_COMMAND_LEN )
+#define EINFO_EPROTO_COMMAND_LEN \
+ __einfo_uniqify ( EINFO_EPROTO, 0x01, "GuestRPC command length failed" )
+#define EPROTO_COMMAND_DATA __einfo_error ( EINFO_EPROTO_COMMAND_DATA )
+#define EINFO_EPROTO_COMMAND_DATA \
+ __einfo_uniqify ( EINFO_EPROTO, 0x02, "GuestRPC command data failed" )
+#define EPROTO_REPLY_LEN __einfo_error ( EINFO_EPROTO_REPLY_LEN )
+#define EINFO_EPROTO_REPLY_LEN \
+ __einfo_uniqify ( EINFO_EPROTO, 0x03, "GuestRPC reply length failed" )
+#define EPROTO_REPLY_DATA __einfo_error ( EINFO_EPROTO_REPLY_DATA )
+#define EINFO_EPROTO_REPLY_DATA \
+ __einfo_uniqify ( EINFO_EPROTO, 0x04, "GuestRPC reply data failed" )
+#define EPROTO_REPLY_FINISH __einfo_error ( EINFO_EPROTO_REPLY_FINISH )
+#define EINFO_EPROTO_REPLY_FINISH \
+ __einfo_uniqify ( EINFO_EPROTO, 0x05, "GuestRPC reply finish failed" )
+#define EPROTO_CLOSE __einfo_error ( EINFO_EPROTO_CLOSE )
+#define EINFO_EPROTO_CLOSE \
+ __einfo_uniqify ( EINFO_EPROTO, 0x06, "GuestRPC close failed" )
+
+/**
+ * Open GuestRPC channel
+ *
+ * @ret channel Channel number, or negative error
+ */
+int guestrpc_open ( void ) {
+ uint16_t channel;
+ uint32_t discard_b;
+ uint32_t status;
+
+ /* Issue GuestRPC command */
+ status = vmware_cmd_guestrpc ( 0, GUESTRPC_OPEN, GUESTRPC_MAGIC,
+ &channel, &discard_b );
+ if ( status != GUESTRPC_OPEN_SUCCESS ) {
+ DBGC ( GUESTRPC_MAGIC, "GuestRPC open failed: status %08x\n",
+ status );
+ return -EPROTO_OPEN;
+ }
+
+ DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d opened\n", channel );
+ return channel;
+}
+
+/**
+ * Send GuestRPC command length
+ *
+ * @v channel Channel number
+ * @v len Command length
+ * @ret rc Return status code
+ */
+static int guestrpc_command_len ( int channel, size_t len ) {
+ uint16_t discard_d;
+ uint32_t discard_b;
+ uint32_t status;
+
+ /* Issue GuestRPC command */
+ status = vmware_cmd_guestrpc ( channel, GUESTRPC_COMMAND_LEN, len,
+ &discard_d, &discard_b );
+ if ( status != GUESTRPC_COMMAND_LEN_SUCCESS ) {
+ DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d send command "
+ "length %zd failed: status %08x\n",
+ channel, len, status );
+ return -EPROTO_COMMAND_LEN;
+ }
+
+ return 0;
+}
+
+/**
+ * Send GuestRPC command data
+ *
+ * @v channel Channel number
+ * @v data Command data
+ * @ret rc Return status code
+ */
+static int guestrpc_command_data ( int channel, uint32_t data ) {
+ uint16_t discard_d;
+ uint32_t discard_b;
+ uint32_t status;
+
+ /* Issue GuestRPC command */
+ status = vmware_cmd_guestrpc ( channel, GUESTRPC_COMMAND_DATA, data,
+ &discard_d, &discard_b );
+ if ( status != GUESTRPC_COMMAND_DATA_SUCCESS ) {
+ DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d send command "
+ "data %08x failed: status %08x\n",
+ channel, data, status );
+ return -EPROTO_COMMAND_DATA;
+ }
+
+ return 0;
+}
+
+/**
+ * Receive GuestRPC reply length
+ *
+ * @v channel Channel number
+ * @ret reply_id Reply ID
+ * @ret len Reply length, or negative error
+ */
+static int guestrpc_reply_len ( int channel, uint16_t *reply_id ) {
+ uint32_t len;
+ uint32_t status;
+
+ /* Issue GuestRPC command */
+ status = vmware_cmd_guestrpc ( channel, GUESTRPC_REPLY_LEN, 0,
+ reply_id, &len );
+ if ( status != GUESTRPC_REPLY_LEN_SUCCESS ) {
+ DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d receive reply "
+ "length failed: status %08x\n", channel, status );
+ return -EPROTO_REPLY_LEN;
+ }
+
+ return len;
+}
+
+/**
+ * Receive GuestRPC reply data
+ *
+ * @v channel Channel number
+ * @v reply_id Reply ID
+ * @ret data Reply data
+ * @ret rc Return status code
+ */
+static int guestrpc_reply_data ( int channel, uint16_t reply_id,
+ uint32_t *data ) {
+ uint16_t discard_d;
+ uint32_t status;
+
+ /* Issue GuestRPC command */
+ status = vmware_cmd_guestrpc ( channel, GUESTRPC_REPLY_DATA, reply_id,
+ &discard_d, data );
+ if ( status != GUESTRPC_REPLY_DATA_SUCCESS ) {
+ DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d receive reply "
+ "%d data failed: status %08x\n",
+ channel, reply_id, status );
+ return -EPROTO_REPLY_DATA;
+ }
+
+ return 0;
+}
+
+/**
+ * Finish receiving GuestRPC reply
+ *
+ * @v channel Channel number
+ * @v reply_id Reply ID
+ * @ret rc Return status code
+ */
+static int guestrpc_reply_finish ( int channel, uint16_t reply_id ) {
+ uint16_t discard_d;
+ uint32_t discard_b;
+ uint32_t status;
+
+ /* Issue GuestRPC command */
+ status = vmware_cmd_guestrpc ( channel, GUESTRPC_REPLY_FINISH, reply_id,
+ &discard_d, &discard_b );
+ if ( status != GUESTRPC_REPLY_FINISH_SUCCESS ) {
+ DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d finish reply %d "
+ "failed: status %08x\n", channel, reply_id, status );
+ return -EPROTO_REPLY_FINISH;
+ }
+
+ return 0;
+}
+
+/**
+ * Close GuestRPC channel
+ *
+ * @v channel Channel number
+ */
+void guestrpc_close ( int channel ) {
+ uint16_t discard_d;
+ uint32_t discard_b;
+ uint32_t status;
+
+ /* Issue GuestRPC command */
+ status = vmware_cmd_guestrpc ( channel, GUESTRPC_CLOSE, 0,
+ &discard_d, &discard_b );
+ if ( status != GUESTRPC_CLOSE_SUCCESS ) {
+ DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d close failed: "
+ "status %08x\n", channel, status );
+ return;
+ }
+
+ DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d closed\n", channel );
+}
+
+/**
+ * Issue GuestRPC command
+ *
+ * @v channel Channel number
+ * @v command Command
+ * @v reply Reply buffer
+ * @v reply_len Length of reply buffer
+ * @ret len Length of reply, or negative error
+ *
+ * The actual length of the reply will be returned even if the buffer
+ * was too small.
+ */
+int guestrpc_command ( int channel, const char *command, char *reply,
+ size_t reply_len ) {
+ const uint8_t *command_bytes = ( ( const void * ) command );
+ uint8_t *reply_bytes = ( ( void * ) reply );
+ size_t command_len = strlen ( command );
+ int orig_reply_len = reply_len;
+ uint16_t status;
+ uint8_t *status_bytes = ( ( void * ) &status );
+ size_t status_len = sizeof ( status );
+ uint32_t data;
+ uint16_t reply_id;
+ int len;
+ int remaining;
+ unsigned int i;
+ int rc;
+
+ DBGC2 ( GUESTRPC_MAGIC, "GuestRPC channel %d issuing command:\n",
+ channel );
+ DBGC2_HDA ( GUESTRPC_MAGIC, 0, command, command_len );
+
+ /* Sanity check */
+ assert ( ( reply != NULL ) || ( reply_len == 0 ) );
+
+ /* Send command length */
+ if ( ( rc = guestrpc_command_len ( channel, command_len ) ) < 0 )
+ return rc;
+
+ /* Send command data */
+ while ( command_len ) {
+ data = 0;
+ for ( i = sizeof ( data ) ; i ; i-- ) {
+ if ( command_len ) {
+ data = ( ( data & ~0xff ) |
+ *(command_bytes++) );
+ command_len--;
+ }
+ data = ( ( data << 24 ) | ( data >> 8 ) );
+ }
+ if ( ( rc = guestrpc_command_data ( channel, data ) ) < 0 )
+ return rc;
+ }
+
+ /* Receive reply length */
+ if ( ( len = guestrpc_reply_len ( channel, &reply_id ) ) < 0 ) {
+ rc = len;
+ return rc;
+ }
+
+ /* Receive reply */
+ for ( remaining = len ; remaining > 0 ; remaining -= sizeof ( data ) ) {
+ if ( ( rc = guestrpc_reply_data ( channel, reply_id,
+ &data ) ) < 0 ) {
+ return rc;
+ }
+ for ( i = sizeof ( data ) ; i ; i-- ) {
+ if ( status_len ) {
+ *(status_bytes++) = ( data & 0xff );
+ status_len--;
+ len--;
+ } else if ( reply_len ) {
+ *(reply_bytes++) = ( data & 0xff );
+ reply_len--;
+ }
+ data = ( ( data << 24 ) | ( data >> 8 ) );
+ }
+ }
+
+ /* Finish receiving RPC reply */
+ if ( ( rc = guestrpc_reply_finish ( channel, reply_id ) ) < 0 )
+ return rc;
+
+ DBGC2 ( GUESTRPC_MAGIC, "GuestRPC channel %d received reply (id %d, "
+ "length %d):\n", channel, reply_id, len );
+ DBGC2_HDA ( GUESTRPC_MAGIC, 0, &status, sizeof ( status ) );
+ DBGC2_HDA ( GUESTRPC_MAGIC, sizeof ( status ), reply,
+ ( ( len < orig_reply_len ) ? len : orig_reply_len ) );
+
+ /* Check reply status */
+ if ( status != GUESTRPC_SUCCESS ) {
+ DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d command failed "
+ "(status %04x, reply id %d, reply length %d):\n",
+ channel, status, reply_id, len );
+ DBGC_HDA ( GUESTRPC_MAGIC, 0, command, command_len );
+ DBGC_HDA ( GUESTRPC_MAGIC, 0, &status, sizeof ( status ) );
+ DBGC_HDA ( GUESTRPC_MAGIC, sizeof ( status ), reply,
+ ( ( len < orig_reply_len ) ? len : orig_reply_len ));
+ return -EIO;
+ }
+
+ return len;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/vmconsole.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/vmconsole.c
new file mode 100644
index 00000000..7f02c50e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/vmconsole.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * VMware logfile console
+ *
+ */
+
+#include <string.h>
+#include <ipxe/console.h>
+#include <ipxe/lineconsole.h>
+#include <ipxe/init.h>
+#include <ipxe/guestrpc.h>
+#include <config/console.h>
+
+/** VMware logfile console buffer size */
+#define VMCONSOLE_BUFSIZE 128
+
+/* Set default console usage if applicable */
+#if ! ( defined ( CONSOLE_VMWARE ) && CONSOLE_EXPLICIT ( CONSOLE_VMWARE ) )
+#undef CONSOLE_VMWARE
+#define CONSOLE_VMWARE ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_TUI )
+#endif
+
+/** VMware logfile console GuestRPC channel */
+static int vmconsole_channel;
+
+/** VMware logfile console line buffer */
+static struct {
+ char prefix[4];
+ char message[VMCONSOLE_BUFSIZE];
+} vmconsole_buffer = {
+ .prefix = "log ",
+};
+
+/** VMware logfile console ANSI escape sequence handlers */
+static struct ansiesc_handler vmconsole_handlers[] = {
+ { 0, NULL }
+};
+
+/** VMware logfile line console */
+static struct line_console vmconsole_line = {
+ .buffer = vmconsole_buffer.message,
+ .len = sizeof ( vmconsole_buffer.message ),
+ .ctx = {
+ .handlers = vmconsole_handlers,
+ },
+};
+
+/** VMware logfile console recursion marker */
+static int vmconsole_entered;
+
+/**
+ * Print a character to VMware logfile console
+ *
+ * @v character Character to be printed
+ */
+static void vmconsole_putchar ( int character ) {
+ int rc;
+
+ /* Ignore if we are already mid-logging */
+ if ( vmconsole_entered )
+ return;
+
+ /* Fill line buffer */
+ if ( line_putchar ( &vmconsole_line, character ) == 0 )
+ return;
+
+ /* Guard against re-entry */
+ vmconsole_entered = 1;
+
+ /* Send log message */
+ if ( ( rc = guestrpc_command ( vmconsole_channel,
+ vmconsole_buffer.prefix, NULL, 0 ) ) <0){
+ DBG ( "VMware console could not send log message: %s\n",
+ strerror ( rc ) );
+ }
+
+ /* Clear re-entry flag */
+ vmconsole_entered = 0;
+}
+
+/** VMware logfile console driver */
+struct console_driver vmconsole __console_driver = {
+ .putchar = vmconsole_putchar,
+ .disabled = 1,
+ .usage = CONSOLE_VMWARE,
+};
+
+/**
+ * Initialise VMware logfile console
+ *
+ */
+static void vmconsole_init ( void ) {
+ int rc;
+
+ /* Attempt to open console */
+ vmconsole_channel = guestrpc_open();
+ if ( vmconsole_channel < 0 ) {
+ rc = vmconsole_channel;
+ DBG ( "VMware console could not be initialised: %s\n",
+ strerror ( rc ) );
+ return;
+ }
+
+ /* Mark console as available */
+ vmconsole.disabled = 0;
+}
+
+/**
+ * VMware logfile console initialisation function
+ */
+struct init_fn vmconsole_init_fn __init_fn ( INIT_CONSOLE ) = {
+ .initialise = vmconsole_init,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/vmware.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/vmware.c
new file mode 100644
index 00000000..8cc26c94
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/interface/vmware/vmware.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * VMware backdoor mechanism
+ *
+ * Based on the unofficial documentation at
+ *
+ * http://sites.google.com/site/chitchatvmback/backdoor
+ *
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <ipxe/vmware.h>
+
+/**
+ * Detect VMware presence
+ *
+ * @ret rc Return status code
+ */
+int vmware_present ( void ) {
+ uint32_t version;
+ uint32_t magic;
+ uint32_t product_type;
+
+ /* Perform backdoor call */
+ vmware_cmd_get_version ( &version, &magic, &product_type );
+
+ /* Check for VMware presence */
+ if ( magic != VMW_MAGIC ) {
+ DBGC ( VMW_MAGIC, "VMware not present\n" );
+ return -ENOENT;
+ }
+
+ DBGC ( VMW_MAGIC, "VMware product type %04x version %08x detected\n",
+ product_type, version );
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/kir-Makefile b/src/VBox/Devices/PC/ipxe/src/arch/i386/kir-Makefile
new file mode 100644
index 00000000..bbfc1a3a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/kir-Makefile
@@ -0,0 +1,26 @@
+# Makefile to build a KEEP_IT_REAL flavour
+#
+# KEEP_IT_REAL, by its nature, requires a different build of every
+# single object file, since the inclusion of ".code16gcc" will
+# generate different machine code from the assembly. Unlike the other
+# config options, there is no way that this global dependency can ever
+# be reduced, so it makes sense to be able to build both the normal
+# and the KIR versions without having to force a full rebuild each
+# time.
+
+# Add this Makefile to MAKEDEPS
+#
+MAKEDEPS += arch/i386/kir-Makefile
+
+# Place binaries in bin-kir
+#
+BIN = bin-kir
+
+# Compile with -DKEEP_IT_REAL, forcibly include kir.h at the start of
+# each file to drag in ".code16gcc"
+#
+CFLAGS += -DKEEP_IT_REAL -include kir.h
+
+include Makefile
+
+LDSCRIPT = arch/i386/scripts/i386-kir.lds
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/bootpart.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/bootpart.S
new file mode 100644
index 00000000..968da1a3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/bootpart.S
@@ -0,0 +1,218 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#define BOOT_SEG 0x07c0
+#define EXEC_SEG 0x0100
+#define STACK_SEG 0x0200
+#define STACK_SIZE 0x2000
+
+ .text
+ .arch i386
+ .section ".prefix", "awx", @progbits
+ .code16
+
+/*
+ * Find active partition
+ *
+ * Parameters:
+ * %dl : BIOS drive number
+ * %bp : Active partition handler routine
+ */
+find_active_partition:
+ /* Set up stack at STACK_SEG:STACK_SIZE */
+ movw $STACK_SEG, %ax
+ movw %ax, %ss
+ movw $STACK_SIZE, %sp
+
+ /* Relocate self to EXEC_SEG */
+ pushw $BOOT_SEG
+ popw %ds
+ pushw $EXEC_SEG
+ popw %es
+ xorw %si, %si
+ xorw %di, %di
+ movw $0x200, %cx
+ rep movsb
+ ljmp $EXEC_SEG, $1f
+1: pushw %ds
+ popw %es
+ pushw %cs
+ popw %ds
+
+ /* Check for LBA extensions */
+ movb $0x41, %ah
+ movw $0x55aa, %bx
+ stc
+ int $0x13
+ jc 1f
+ cmpw $0xaa55, %bx
+ jne 1f
+ movw $read_lba, read_sectors
+1:
+ /* Read and process root partition table */
+ xorb %dh, %dh
+ movw $0x0001, %cx
+ xorl %esi, %esi
+ xorl %edi, %edi
+ call process_table
+
+ /* Print failure message */
+ movw $10f, %si
+ jmp boot_error
+10: .asciz "Could not locate active partition\r\n"
+
+/*
+ * Print failure message and boot next device
+ *
+ * Parameters:
+ * %si : Failure string
+ */
+boot_error:
+ cld
+ movw $0x0007, %bx
+ movb $0x0e, %ah
+1: lodsb
+ testb %al, %al
+ je 99f
+ int $0x10
+ jmp 1b
+99: /* Boot next device */
+ int $0x18
+
+/*
+ * Process partition table
+ *
+ * Parameters:
+ * %dl : BIOS drive number
+ * %dh : Head
+ * %cl : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
+ * %ch : Low eight bits of cylinder
+ * %esi:%edi : LBA address
+ * %bp : Active partition handler routine
+ *
+ * Returns:
+ * CF set on error
+ */
+process_table:
+ pushal
+ call read_boot_sector
+ jc 99f
+ movw $446, %bx
+1: call process_partition
+ addw $16, %bx
+ cmpw $510, %bx
+ jne 1b
+99: popal
+ ret
+
+/*
+ * Process partition
+ *
+ * Parameters:
+ * %dl : BIOS drive number
+ * %dh : Head
+ * %cl : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
+ * %ch : Low eight bits of cylinder
+ * %esi:%edi : LBA address
+ * %bx : Offset within partition table
+ * %bp : Active partition handler routine
+ */
+process_partition:
+ pushal
+ /* Load C/H/S values from partition entry */
+ movb %es:1(%bx), %dh
+ movw %es:2(%bx), %cx
+ /* Update LBA address from partition entry */
+ addl %es:8(%bx), %edi
+ adcl $0, %esi
+ /* Check active flag */
+ testb $0x80, %es:(%bx)
+ jz 1f
+ call read_boot_sector
+ jc 99f
+ jmp *%bp
+1: /* Check for extended partition */
+ movb %es:4(%bx), %al
+ cmpb $0x05, %al
+ je 2f
+ cmpb $0x0f, %al
+ je 2f
+ cmpb $0x85, %al
+ jne 99f
+2: call process_table
+99: popal
+ /* Reload original partition table */
+ call read_boot_sector
+ ret
+
+/*
+ * Read single sector to %es:0000 and verify 0x55aa signature
+ *
+ * Parameters:
+ * %dl : BIOS drive number
+ * %dh : Head
+ * %cl : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
+ * %ch : Low eight bits of cylinder
+ * %esi:%edi : LBA address
+ *
+ * Returns:
+ * CF set on error
+ */
+read_boot_sector:
+ pushw %ax
+ movw $1, %ax
+ call *read_sectors
+ jc 99f
+ cmpw $0xaa55, %es:(510)
+ je 99f
+ stc
+99: popw %ax
+ ret
+
+/*
+ * Read sectors to %es:0000
+ *
+ * Parameters:
+ * %dl : BIOS drive number
+ * %dh : Head
+ * %cl : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
+ * %ch : Low eight bits of cylinder
+ * %esi:%edi : LBA address
+ * %ax : Number of sectors (max 127)
+ *
+ * Returns:
+ * CF set on error
+ */
+read_sectors: .word read_chs
+
+read_chs:
+ /* Read sectors using C/H/S address */
+ pushal
+ xorw %bx, %bx
+ movb $0x02, %ah
+ stc
+ int $0x13
+ sti
+ popal
+ ret
+
+read_lba:
+ /* Read sectors using LBA address */
+ pushal
+ movw %ax, (lba_desc + 2)
+ pushw %es
+ popw (lba_desc + 6)
+ movl %edi, (lba_desc + 8)
+ movl %esi, (lba_desc + 12)
+ movw $lba_desc, %si
+ movb $0x42, %ah
+ int $0x13
+ popal
+ ret
+
+lba_desc:
+ .byte 0x10
+ .byte 0
+ .word 1
+ .word 0x0000
+ .word 0x0000
+ .long 0, 0
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/dskprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/dskprefix.S
new file mode 100644
index 00000000..7aa017cc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/dskprefix.S
@@ -0,0 +1,383 @@
+/* NOTE: this boot sector contains instructions that need at least an 80186.
+ * Yes, as86 has a bug somewhere in the valid instruction set checks.
+ *
+ */
+
+/* floppyload.S Copyright (C) 1991, 1992 Linus Torvalds
+ * modified by Drew Eckhardt
+ * modified by Bruce Evans (bde)
+ *
+ * floppyprefix.S is loaded at 0x0000:0x7c00 by the bios-startup routines.
+ *
+ * It then loads the system at SYSSEG<<4, using BIOS interrupts.
+ *
+ * The loader has been made as simple as possible, and continuous read errors
+ * will result in a unbreakable loop. Reboot by hand. It loads pretty fast by
+ * getting whole tracks at a time whenever possible.
+ */
+
+FILE_LICENCE ( GPL2_ONLY )
+
+.equ BOOTSEG, 0x07C0 /* original address of boot-sector */
+
+.equ SYSSEG, 0x1000 /* system loaded at SYSSEG<<4 */
+
+ .org 0
+ .arch i386
+ .text
+ .section ".prefix", "ax", @progbits
+ .code16
+ .globl _dsk_start
+_dsk_start:
+
+ jmp $BOOTSEG, $go /* reload cs:ip to match relocation addr */
+go:
+ movw $0x2000-12, %di /* 0x2000 is arbitrary value >= length */
+ /* of bootsect + room for stack + 12 for */
+ /* saved disk parm block */
+
+ movw $BOOTSEG, %ax
+ movw %ax,%ds
+ movw %ax,%es
+ movw %ax,%ss /* put stack at BOOTSEG:0x4000-12. */
+ movw %di,%sp
+
+/* Many BIOS's default disk parameter tables will not recognize multi-sector
+ * reads beyond the maximum sector number specified in the default diskette
+ * parameter tables - this may mean 7 sectors in some cases.
+ *
+ * Since single sector reads are slow and out of the question, we must take care
+ * of this by creating new parameter tables (for the first disk) in RAM. We
+ * will set the maximum sector count to 36 - the most we will encounter on an
+ * ED 2.88. High doesn't hurt. Low does.
+ *
+ * Segments are as follows: ds=es=ss=cs - BOOTSEG
+ */
+
+ xorw %cx,%cx
+ movw %cx,%es /* access segment 0 */
+ movw $0x78, %bx /* 0:bx is parameter table address */
+ pushw %ds /* save ds */
+/* 0:bx is parameter table address */
+ ldsw %es:(%bx),%si /* loads ds and si */
+
+ movw %ax,%es /* ax is BOOTSECT (loaded above) */
+ movb $6, %cl /* copy 12 bytes */
+ cld
+ pushw %di /* keep a copy for later */
+ rep
+ movsw /* ds:si is source, es:di is dest */
+ popw %di
+
+ movb $36,%es:4(%di)
+
+ movw %cx,%ds /* access segment 0 */
+ xchgw %di,(%bx)
+ movw %es,%si
+ xchgw %si,2(%bx)
+ popw %ds /* restore ds */
+ movw %di, dpoff /* save old parameters */
+ movw %si, dpseg /* to restore just before finishing */
+ pushw %ds
+ popw %es /* reload es */
+
+/* Note that es is already set up. Also cx is 0 from rep movsw above. */
+
+ xorb %ah,%ah /* reset FDC */
+ xorb %dl,%dl
+ int $0x13
+
+/* Get disk drive parameters, specifically number of sectors/track.
+ *
+ * It seems that there is no BIOS call to get the number of sectors. Guess
+ * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
+ * 15 if sector 15 can be read. Otherwise guess 9.
+ */
+
+ movw $disksizes, %si /* table of sizes to try */
+
+probe_loop:
+ lodsb
+ cbtw /* extend to word */
+ movw %ax, sectors
+ cmpw $disksizes+4, %si
+ jae got_sectors /* if all else fails, try 9 */
+ xchgw %cx,%ax /* cx = track and sector */
+ xorw %dx,%dx /* drive 0, head 0 */
+ movw $0x0200, %bx /* address after boot sector */
+ /* (512 bytes from origin, es = cs) */
+ movw $0x0201, %ax /* service 2, 1 sector */
+ int $0x13
+ jc probe_loop /* try next value */
+
+got_sectors:
+ movw $msg1end-msg1, %cx
+ movw $msg1, %si
+ call print_str
+
+/* ok, we've written the Loading... message, now we want to load the system */
+
+ movw $SYSSEG, %ax
+ movw %ax,%es /* segment of SYSSEG<<4 */
+ pushw %es
+ call read_it
+
+/* This turns off the floppy drive motor, so that we enter the kernel in a
+ * known state, and don't have to worry about it later.
+ */
+ movw $0x3f2, %dx
+ xorb %al,%al
+ outb %al,%dx
+
+ call print_nl
+ pop %es /* = SYSSEG */
+
+/* Restore original disk parameters */
+ movw $0x78, %bx
+ movw dpoff, %di
+ movw dpseg, %si
+ xorw %ax,%ax
+ movw %ax,%ds
+ movw %di,(%bx)
+ movw %si,2(%bx)
+
+ /* Everything now loaded. %es = SYSSEG, so %es:0000 points to
+ * start of loaded image.
+ */
+
+ /* Jump to loaded copy */
+ ljmp $SYSSEG, $start_runtime
+
+endseg: .word SYSSEG
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
+ .ascii "ADDW"
+ .long endseg
+ .long 16
+ .long 0
+ .previous
+
+/* This routine loads the system at address SYSSEG<<4, making sure no 64kB
+ * boundaries are crossed. We try to load it as fast as possible, loading whole
+ * tracks whenever we can.
+ *
+ * in: es - starting address segment (normally SYSSEG)
+ */
+read_it:
+ movw $0,sread /* load whole image including prefix */
+ movw %es,%ax
+ testw $0x0fff, %ax
+die: jne die /* es must be at 64kB boundary */
+ xorw %bx,%bx /* bx is starting address within segment */
+rp_read:
+ movw %es,%ax
+ movw %bx,%dx
+ movb $4, %cl
+ shrw %cl,%dx /* bx is always divisible by 16 */
+ addw %dx,%ax
+ cmpw endseg, %ax /* have we loaded all yet? */
+ jb ok1_read
+ ret
+ok1_read:
+ movw sectors, %ax
+ subw sread, %ax
+ movw %ax,%cx
+ shlw $9, %cx
+ addw %bx,%cx
+ jnc ok2_read
+ je ok2_read
+ xorw %ax,%ax
+ subw %bx,%ax
+ shrw $9, %ax
+ok2_read:
+ call read_track
+ movw %ax,%cx
+ addw sread, %ax
+ cmpw sectors, %ax
+ jne ok3_read
+ movw $1, %ax
+ subw head, %ax
+ jne ok4_read
+ incw track
+ok4_read:
+ movw %ax, head
+ xorw %ax,%ax
+ok3_read:
+ movw %ax, sread
+ shlw $9, %cx
+ addw %cx,%bx
+ jnc rp_read
+ movw %es,%ax
+ addb $0x10, %ah
+ movw %ax,%es
+ xorw %bx,%bx
+ jmp rp_read
+
+read_track:
+ pusha
+ pushw %ax
+ pushw %bx
+ pushw %bp /* just in case the BIOS is buggy */
+ movw $0x0e2e, %ax /* 0x2e = . */
+ movw $0x0007, %bx
+ int $0x10
+ popw %bp
+ popw %bx
+ popw %ax
+
+ movw track, %dx
+ movw sread, %cx
+ incw %cx
+ movb %dl,%ch
+ movw head, %dx
+ movb %dl,%dh
+ andw $0x0100, %dx
+ movb $2, %ah
+
+ pushw %dx /* save for error dump */
+ pushw %cx
+ pushw %bx
+ pushw %ax
+
+ int $0x13
+ jc bad_rt
+ addw $8, %sp
+ popa
+ ret
+
+bad_rt: pushw %ax /* save error code */
+ call print_all /* ah = error, al = read */
+
+ xorb %ah,%ah
+ xorb %dl,%dl
+ int $0x13
+
+ addw $10, %sp
+ popa
+ jmp read_track
+
+/* print_all is for debugging purposes. It will print out all of the registers.
+ * The assumption is that this is called from a routine, with a stack frame like
+ * dx
+ * cx
+ * bx
+ * ax
+ * error
+ * ret <- sp
+ */
+
+print_all:
+ call print_nl /* nl for readability */
+ movw $5, %cx /* error code + 4 registers */
+ movw %sp,%bp
+
+print_loop:
+ pushw %cx /* save count left */
+
+ cmpb $5, %cl
+ jae no_reg /* see if register name is needed */
+
+ movw $0x0007, %bx /* page 0, attribute 7 (normal) */
+ movw $0xe05+0x41-1, %ax
+ subb %cl,%al
+ int $0x10
+
+ movb $0x58, %al /* 'X' */
+ int $0x10
+
+ movb $0x3A, %al /* ':' */
+ int $0x10
+
+no_reg:
+ addw $2, %bp /* next register */
+ call print_hex /* print it */
+ movb $0x20, %al /* print a space */
+ int $0x10
+ popw %cx
+ loop print_loop
+ call print_nl /* nl for readability */
+ ret
+
+print_str:
+ movw $0x0007, %bx /* page 0, attribute 7 (normal) */
+ movb $0x0e, %ah /* write char, tty mode */
+prloop:
+ lodsb
+ int $0x10
+ loop prloop
+ ret
+
+print_nl:
+ movw $0x0007, %bx /* page 0, attribute 7 (normal) */
+ movw $0xe0d, %ax /* CR */
+ int $0x10
+ movb $0xa, %al /* LF */
+ int $0x10
+ ret
+
+/* print_hex prints the word pointed to by ss:bp in hexadecimal. */
+
+print_hex:
+ movw (%bp),%dx /* load word into dx */
+ movb $4, %cl
+ movb $0x0e, %ah /* write char, tty mode */
+ movw $0x0007, %bx /* page 0, attribute 7 (normal) */
+ call print_digit
+ call print_digit
+ call print_digit
+/* fall through */
+print_digit:
+ rol %cl,%dx /* rotate so that lowest 4 bits are used */
+ movb $0x0f, %al /* mask for nybble */
+ andb %dl,%al
+ addb $0x90, %al /* convert al to ascii hex (four instructions) */
+ daa
+ adcb $0x40, %al
+ daa
+ int $0x10
+ ret
+
+sread: .word 0 /* sectors read of current track */
+head: .word 0 /* current head */
+track: .word 0 /* current track */
+
+sectors:
+ .word 0
+
+dpseg: .word 0
+dpoff: .word 0
+
+disksizes:
+ .byte 36,18,15,9
+
+msg1:
+ .ascii "Loading ROM image"
+msg1end:
+
+ .org 510, 0
+ .word 0xAA55
+
+start_runtime:
+ /* Install iPXE */
+ call install
+
+ /* Set up real-mode stack */
+ movw %bx, %ss
+ movw $_estack16, %sp
+
+ /* Jump to .text16 segment */
+ pushw %ax
+ pushw $1f
+ lret
+ .section ".text16", "awx", @progbits
+1:
+ pushl $main
+ pushw %cs
+ call prot_call
+ popl %ecx /* discard */
+
+ /* Uninstall iPXE */
+ call uninstall
+
+ /* Boot next device */
+ int $0x18
+
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/exeprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/exeprefix.S
new file mode 100644
index 00000000..5ba0239a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/exeprefix.S
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+/* Initial temporary stack size */
+#define EXE_STACK_SIZE 0x400
+
+/* Temporary decompression area (avoid DOS high memory area) */
+#define EXE_DECOMPRESS_ADDRESS 0x110000
+
+/* Fields within the Program Segment Prefix */
+#define PSP_CMDLINE_LEN 0x80
+#define PSP_CMDLINE_START 0x81
+
+ .text
+ .arch i386
+ .org 0
+ .code16
+ .section ".prefix", "awx", @progbits
+
+signature:
+ /* "MZ" signature */
+ .ascii "MZ"
+
+last_block:
+ /* Number of bytes in last block that are really used */
+ .word 0
+
+blocks:
+ /* Number of 512-byte blocks */
+ .word 0
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
+ .ascii "ADDW"
+ .long blocks
+ .long 512
+ .long 0
+ .previous
+
+num_reloc:
+ /* Number of relocation entries stored after the header */
+ .word 0
+
+header_pgh:
+ /* Number of paragraphs in the header */
+ .word ( ( _exe_start - signature ) / 16 )
+
+min_bss_pgh:
+ /* Minimum number of paragraphs of additional (BSS) memory */
+ .word ( EXE_STACK_SIZE / 16 )
+
+max_bss_pgh:
+ /* Maximum number of paragraphs of additional (BSS) memory */
+ .word ( EXE_STACK_SIZE / 16 )
+
+init_ss:
+ /* Initial stack segment (relative to start of executable) */
+ .word -( ( _exe_start - signature ) / 16 )
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
+ .ascii "ADDW"
+ .long init_ss
+ .long 16
+ .long 0
+ .previous
+
+init_sp:
+ /* Initial stack pointer */
+ .word EXE_STACK_SIZE
+
+checksum:
+ /* Checksum (ignored) */
+ .word 0
+
+init_ip:
+ /* Initial instruction pointer */
+ .word _exe_start
+
+init_cs:
+ /* Initial code segment (relative to start of executable) */
+ .word -( ( _exe_start - signature ) / 16 )
+
+reloc_table:
+ /* Relocation table offset */
+ .word 0
+
+overlay:
+ /* Overlay number */
+ .word 0
+
+ .align 16, 0
+
+ .globl _exe_start
+_exe_start:
+ /* Install iPXE. Use a fixed temporary decompression area to
+ * avoid trashing the DOS high memory area.
+ */
+ call alloc_basemem
+ xorl %esi, %esi
+ movl $EXE_DECOMPRESS_ADDRESS, %edi
+ xorl %ebp, %ebp
+ call install_prealloc
+
+ /* Set up real-mode stack */
+ movw %bx, %ss
+ movw $_estack16, %sp
+
+ /* Jump to .text16 segment */
+ pushw %ax
+ pushw $1f
+ lret
+ .section ".text16", "awx", @progbits
+1:
+ /* Terminate command line with a NUL */
+ movzbw PSP_CMDLINE_LEN, %si
+ movb $0, PSP_CMDLINE_START(%si)
+
+ /* Calculate command line physical address */
+ xorl %esi, %esi
+ movw %ds, %si
+ shll $4, %esi
+ addl $PSP_CMDLINE_START, %esi
+
+ /* Set up %ds for access to .data16 */
+ movw %bx, %ds
+
+ /* Record command line address */
+ movl %esi, cmdline_phys
+
+ /* Run iPXE */
+ pushl $main
+ pushw %cs
+ call prot_call
+ popl %ecx /* discard */
+
+ /* Uninstall iPXE */
+ call uninstall
+
+ /* Exit back to DOS. This is very unlikely to work */
+ movw $0x4c00, %ax
+ int $0x21
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/hdprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/hdprefix.S
new file mode 100644
index 00000000..876bfe1b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/hdprefix.S
@@ -0,0 +1,111 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .text
+ .arch i386
+ .section ".prefix", "awx", @progbits
+ .code16
+ .org 0
+ .globl _hd_start
+_hd_start:
+
+ movw $load_image, %bp
+ jmp find_active_partition
+
+#include "bootpart.S"
+
+load_image:
+ /* Get disk geometry */
+ pushal
+ pushw %es
+ movb $0x08, %ah
+ int $0x13
+ jc load_failed
+ movb %cl, max_sector
+ movb %dh, max_head
+ popw %es
+ popal
+
+1: /* Read to end of current track */
+ movb %cl, %al
+ negb %al
+ addb max_sector, %al
+ incb %al
+ andb $0x3f, %al
+ movzbl %al, %eax
+ call *read_sectors
+ jc load_failed
+
+ /* Update %es */
+ movw %es, %bx
+ shll $5, %eax
+ addw %ax, %bx
+ movw %bx, %es
+ shrl $5, %eax
+
+ /* Update LBA address */
+ addl %eax, %edi
+ adcl $0, %esi
+
+ /* Update CHS address */
+ andb $0xc0, %cl
+ orb $0x01, %cl
+ incb %dh
+ cmpb max_head, %dh
+ jbe 2f
+ xorb %dh, %dh
+ incb %ch
+ jnc 2f
+ addb $0xc0, %cl
+2:
+ /* Loop until whole image is read */
+ subl %eax, load_length
+ ja 1b
+ ljmp $BOOT_SEG, $start_image
+
+max_sector:
+ .byte 0
+max_head:
+ .byte 0
+load_length:
+ .long 0
+
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
+ .ascii "ADDL"
+ .long load_length
+ .long 512
+ .long 0
+ .previous
+
+
+load_failed:
+ movw $10f, %si
+ jmp boot_error
+10: .asciz "Could not load iPXE\r\n"
+
+ .org 510
+ .byte 0x55, 0xaa
+
+start_image:
+ /* Install iPXE */
+ call install
+
+ /* Set up real-mode stack */
+ movw %bx, %ss
+ movw $_estack16, %sp
+
+ /* Jump to .text16 segment */
+ pushw %ax
+ pushw $1f
+ lret
+ .section ".text16", "awx", @progbits
+1:
+ pushl $main
+ pushw %cs
+ call prot_call
+ popl %ecx /* discard */
+
+ /* Uninstall iPXE */
+ call uninstall
+
+ /* Boot next device */
+ int $0x18
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/kkkpxeprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/kkkpxeprefix.S
new file mode 100644
index 00000000..27ed231e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/kkkpxeprefix.S
@@ -0,0 +1,19 @@
+/*****************************************************************************
+ * PXE prefix that keeps the whole PXE stack present and provides an exit hook
+ *
+ * This prefix is essentially intended solely for the case of ipxelinux.0
+ *****************************************************************************
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+/* Since we have the whole stack, we can use cached DHCP information */
+REQUIRE_OBJECT ( pxeparent_dhcp )
+
+/* Provide the PXENV_FILE_EXIT_HOOK API call */
+REQUIRE_OBJECT ( pxe_exit_hook )
+
+#define PXELOADER_KEEP_UNDI
+#define PXELOADER_KEEP_PXE
+#define _pxe_start _kkkpxe_start
+#include "pxeprefix.S"
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/kkpxeprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/kkpxeprefix.S
new file mode 100644
index 00000000..d177d7d6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/kkpxeprefix.S
@@ -0,0 +1,14 @@
+/*****************************************************************************
+ * PXE prefix that keeps the whole PXE stack present
+ *****************************************************************************
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+/* Since we have the whole stack, we can use cached DHCP information */
+REQUEST_OBJECT ( pxeparent_dhcp )
+
+#define PXELOADER_KEEP_UNDI
+#define PXELOADER_KEEP_PXE
+#define _pxe_start _kkpxe_start
+#include "pxeprefix.S"
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/kpxeprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/kpxeprefix.S
new file mode 100644
index 00000000..c7560817
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/kpxeprefix.S
@@ -0,0 +1,10 @@
+/*****************************************************************************
+ * PXE prefix that keep the UNDI portion of the PXE stack present
+ *****************************************************************************
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#define PXELOADER_KEEP_UNDI
+#define _pxe_start _kpxe_start
+#include "pxeprefix.S"
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/libprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/libprefix.S
new file mode 100644
index 00000000..0962debb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/libprefix.S
@@ -0,0 +1,929 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .arch i386
+
+/* Image compression enabled */
+#define COMPRESS 1
+
+/* Protected mode flag */
+#define CR0_PE 1
+
+/* Allow for DBG()-style messages within libprefix */
+#ifdef NDEBUG
+ .macro progress message
+ .endm
+#else
+ .macro progress message
+ pushfl
+ pushw %ds
+ pushw %si
+ pushw %di
+ pushw %cs
+ popw %ds
+ xorw %di, %di
+ movw $progress_\@, %si
+ call print_message
+ popw %di
+ popw %si
+ popw %ds
+ popfl
+ .section ".prefix.data", "aw", @progbits
+progress_\@:
+ .asciz "\message"
+ .size progress_\@, . - progress_\@
+ .previous
+ .endm
+#endif
+
+/*****************************************************************************
+ * Utility function: print character (with LF -> LF,CR translation)
+ *
+ * Parameters:
+ * %al : character to print
+ * %ds:di : output buffer (or %di=0 to print to console)
+ * Returns:
+ * %ds:di : next character in output buffer (if applicable)
+ *****************************************************************************
+ */
+ .section ".prefix.lib", "awx", @progbits
+ .code16
+ .globl print_character
+print_character:
+ /* Preserve registers */
+ pushw %ax
+ pushw %bx
+ pushw %bp
+ /* If %di is non-zero, write character to buffer and exit */
+ testw %di, %di
+ jz 1f
+ movb %al, %ds:(%di)
+ incw %di
+ jmp 3f
+1: /* Print character */
+ movw $0x0007, %bx /* page 0, attribute 7 (normal) */
+ movb $0x0e, %ah /* write char, tty mode */
+ cmpb $0x0a, %al /* '\n'? */
+ jne 2f
+ int $0x10
+ movb $0x0d, %al
+2: int $0x10
+ /* Restore registers and return */
+3: popw %bp
+ popw %bx
+ popw %ax
+ ret
+ .size print_character, . - print_character
+
+/*****************************************************************************
+ * Utility function: print a NUL-terminated string
+ *
+ * Parameters:
+ * %ds:si : string to print
+ * %ds:di : output buffer (or %di=0 to print to console)
+ * Returns:
+ * %ds:si : character after terminating NUL
+ * %ds:di : next character in output buffer (if applicable)
+ *****************************************************************************
+ */
+ .section ".prefix.lib", "awx", @progbits
+ .code16
+ .globl print_message
+print_message:
+ /* Preserve registers */
+ pushw %ax
+ /* Print string */
+1: lodsb
+ testb %al, %al
+ je 2f
+ call print_character
+ jmp 1b
+2: /* Restore registers and return */
+ popw %ax
+ ret
+ .size print_message, . - print_message
+
+/*****************************************************************************
+ * Utility functions: print hex digit/byte/word/dword
+ *
+ * Parameters:
+ * %al (low nibble) : digit to print
+ * %al : byte to print
+ * %ax : word to print
+ * %eax : dword to print
+ * %ds:di : output buffer (or %di=0 to print to console)
+ * Returns:
+ * %ds:di : next character in output buffer (if applicable)
+ *****************************************************************************
+ */
+ .section ".prefix.lib", "awx", @progbits
+ .code16
+ .globl print_hex_dword
+print_hex_dword:
+ rorl $16, %eax
+ call print_hex_word
+ rorl $16, %eax
+ /* Fall through */
+ .size print_hex_dword, . - print_hex_dword
+ .globl print_hex_word
+print_hex_word:
+ xchgb %al, %ah
+ call print_hex_byte
+ xchgb %al, %ah
+ /* Fall through */
+ .size print_hex_word, . - print_hex_word
+ .globl print_hex_byte
+print_hex_byte:
+ rorb $4, %al
+ call print_hex_nibble
+ rorb $4, %al
+ /* Fall through */
+ .size print_hex_byte, . - print_hex_byte
+ .globl print_hex_nibble
+print_hex_nibble:
+ /* Preserve registers */
+ pushw %ax
+ /* Print digit (technique by Norbert Juffa <norbert.juffa@amd.com> */
+ andb $0x0f, %al
+ cmpb $10, %al
+ sbbb $0x69, %al
+ das
+ call print_character
+ /* Restore registers and return */
+ popw %ax
+ ret
+ .size print_hex_nibble, . - print_hex_nibble
+
+/*****************************************************************************
+ * Utility function: print PCI bus:dev.fn
+ *
+ * Parameters:
+ * %ax : PCI bus:dev.fn to print
+ * %ds:di : output buffer (or %di=0 to print to console)
+ * Returns:
+ * %ds:di : next character in output buffer (if applicable)
+ *****************************************************************************
+ */
+ .section ".prefix.lib", "awx", @progbits
+ .code16
+ .globl print_pci_busdevfn
+print_pci_busdevfn:
+ /* Preserve registers */
+ pushw %ax
+ /* Print bus */
+ xchgb %al, %ah
+ call print_hex_byte
+ /* Print ":" */
+ movb $( ':' ), %al
+ call print_character
+ /* Print device */
+ movb %ah, %al
+ shrb $3, %al
+ call print_hex_byte
+ /* Print "." */
+ movb $( '.' ), %al
+ call print_character
+ /* Print function */
+ movb %ah, %al
+ andb $0x07, %al
+ call print_hex_nibble
+ /* Restore registers and return */
+ popw %ax
+ ret
+ .size print_pci_busdevfn, . - print_pci_busdevfn
+
+/*****************************************************************************
+ * Utility function: clear current line
+ *
+ * Parameters:
+ * %ds:di : output buffer (or %di=0 to print to console)
+ * Returns:
+ * %ds:di : next character in output buffer (if applicable)
+ *****************************************************************************
+ */
+ .section ".prefix.lib", "awx", @progbits
+ .code16
+ .globl print_kill_line
+print_kill_line:
+ /* Preserve registers */
+ pushw %ax
+ pushw %cx
+ /* Print CR */
+ movb $( '\r' ), %al
+ call print_character
+ /* Print 79 spaces */
+ movb $( ' ' ), %al
+ movw $79, %cx
+1: call print_character
+ loop 1b
+ /* Print CR */
+ movb $( '\r' ), %al
+ call print_character
+ /* Restore registers and return */
+ popw %cx
+ popw %ax
+ ret
+ .size print_kill_line, . - print_kill_line
+
+/****************************************************************************
+ * copy_bytes
+ *
+ * Copy bytes
+ *
+ * Parameters:
+ * %ds:esi : source address
+ * %es:edi : destination address
+ * %ecx : length
+ * Returns:
+ * %ds:esi : next source address
+ * %es:edi : next destination address
+ * Corrupts:
+ * None
+ ****************************************************************************
+ */
+ .section ".prefix.lib", "awx", @progbits
+ .code16
+copy_bytes:
+ pushl %ecx
+ rep addr32 movsb
+ popl %ecx
+ ret
+ .size copy_bytes, . - copy_bytes
+
+/****************************************************************************
+ * zero_bytes
+ *
+ * Zero bytes
+ *
+ * Parameters:
+ * %ds:esi : source address
+ * %es:edi : destination address
+ * %ecx : length
+ * Returns:
+ * %ds:esi : next source address
+ * %es:edi : next destination address
+ * Corrupts:
+ * None
+ ****************************************************************************
+ */
+ .section ".prefix.lib", "awx", @progbits
+ .code16
+zero_bytes:
+ pushl %ecx
+ pushw %ax
+ xorw %ax, %ax
+ rep addr32 stosb
+ popw %ax
+ popl %ecx
+ ret
+ .size zero_bytes, . - zero_bytes
+
+/****************************************************************************
+ * process_bytes
+ *
+ * Call memcpy()-like function
+ *
+ * Parameters:
+ * %esi : source physical address
+ * %edi : destination physical address
+ * %ecx : length
+ * %bx : memcpy()-like function to call, passing parameters:
+ * %ds:esi : source address
+ * %es:edi : destination address
+ * %ecx : length
+ * and returning:
+ * %ds:esi : next source address
+ * %es:edi : next destination address
+ * Returns:
+ * %esi : next source physical address
+ * %edi : next destination physical address
+ * Corrupts:
+ * None
+ ****************************************************************************
+ */
+ .section ".prefix.lib", "awx", @progbits
+ .code16
+process_bytes:
+
+#ifndef KEEP_IT_REAL
+
+ /* Preserve registers */
+ pushl %eax
+ pushl %ebp
+
+ /* Construct GDT on stack (since .prefix may not be writable) */
+ .equ PM_DS, 0x18 /* Flat data segment */
+ pushl $0x00cf9300
+ pushl $0x0000ffff
+ .equ PM_SS, 0x10 /* Stack segment based at %ss:0000 */
+ pushl $0x008f0930
+ pushw %ss
+ pushw $0xffff
+ .equ PM_CS, 0x08 /* Code segment based at %cs:0000 */
+ pushl $0x008f09b0
+ pushw %cs
+ pushw $0xffff
+ pushl $0 /* Base and length */
+ pushw %ss
+ pushw $0x1f
+ movzwl %sp, %ebp
+ shll $4, 0x02(%bp)
+ addl %ebp, 0x02(%bp)
+ shll $4, 0x0a(%bp)
+ shll $4, 0x12(%bp)
+ subw $8, %sp
+ sgdt -8(%bp)
+
+ /* Switch to protected mode */
+ pushw %gs
+ pushw %fs
+ pushw %es
+ pushw %ds
+ pushw %ss
+ pushw %cs
+ pushw $2f
+ cli
+ data32 lgdt (%bp)
+ movl %cr0, %eax
+ orb $CR0_PE, %al
+ movl %eax, %cr0
+ ljmp $PM_CS, $1f
+1: movw $PM_SS, %ax
+ movw %ax, %ss
+ movw $PM_DS, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+
+ /* Call memcpy()-like function */
+ call *%bx
+
+ /* Return to (flat) real mode */
+ movl %cr0, %eax
+ andb $0!CR0_PE, %al
+ movl %eax, %cr0
+ lret
+2: /* lret will ljmp to here */
+ popw %ss
+ popw %ds
+ popw %es
+ popw %fs
+ popw %gs
+
+ /* Restore GDT */
+ data32 lgdt -8(%bp)
+ addw $( 8 /* saved GDT */ + ( PM_DS + 8 ) /* GDT on stack */ ), %sp
+
+ /* Restore registers and return */
+ popl %ebp
+ popl %eax
+ ret
+
+#else /* KEEP_IT_REAL */
+
+ /* Preserve registers */
+ pushl %eax
+ pushw %ds
+ pushw %es
+
+ /* Convert %esi and %edi to %ds:esi and %es:edi */
+ shrl $4, %esi
+ movw %si, %ds
+ xorw %si, %si
+ shll $4, %esi
+ shrl $4, %edi
+ movw %di, %es
+ xorw %di, %di
+ shll $4, %edi
+
+ /* Call memcpy()-like function */
+ call *%bx
+
+ /* Convert %ds:esi and %es:edi back to physical addresses */
+ xorl %eax, %eax
+ movw %ds, %cx
+ shll $4, %eax
+ addl %eax, %esi
+ xorl %eax, %eax
+ movw %es, %cx
+ shll $4, %eax
+ addl %eax, %edi
+
+ /* Restore registers and return */
+ popw %es
+ popw %ds
+ popl %eax
+ ret
+
+#endif /* KEEP_IT_REAL */
+
+ .size process_bytes, . - process_bytes
+
+/****************************************************************************
+ * install_block
+ *
+ * Install block to specified address
+ *
+ * Parameters:
+ * %esi : source physical address (must be a multiple of 16)
+ * %edi : destination physical address (must be a multiple of 16)
+ * %ecx : length of (decompressed) data
+ * %edx : total length of block (including any uninitialised data portion)
+ * Returns:
+ * %esi : next source physical address (will be a multiple of 16)
+ * %edi : next destination physical address (will be a multiple of 16)
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ .section ".prefix.lib", "awx", @progbits
+ .code16
+install_block:
+ /* Preserve registers */
+ pushl %ecx
+ pushw %bx
+
+ /* Decompress (or copy) source to destination */
+#if COMPRESS
+ movw $decompress16, %bx
+#else
+ movw $copy_bytes, %bx
+#endif
+ call process_bytes
+
+ /* Zero .bss portion */
+ negl %ecx
+ addl %edx, %ecx
+ movw $zero_bytes, %bx
+ call process_bytes
+
+ /* Round up %esi and %edi to start of next blocks */
+ addl $0xf, %esi
+ andl $~0xf, %esi
+ addl $0xf, %edi
+ andl $~0xf, %edi
+
+ /* Restore registers and return */
+ popw %bx
+ popl %ecx
+ ret
+ .size install_block, . - install_block
+
+/****************************************************************************
+ * alloc_basemem
+ *
+ * Allocate space for .text16 and .data16 from top of base memory.
+ * Memory is allocated using the BIOS free base memory counter at
+ * 0x40:13.
+ *
+ * Parameters:
+ * none
+ * Returns:
+ * %ax : .text16 segment address
+ * %bx : .data16 segment address
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ .section ".prefix.lib", "awx", @progbits
+ .code16
+ .globl alloc_basemem
+alloc_basemem:
+ /* Preserve registers */
+ pushw %fs
+
+ /* FBMS => %ax as segment address */
+ pushw $0x40
+ popw %fs
+ movw %fs:0x13, %ax
+ shlw $6, %ax
+
+ /* Calculate .data16 segment address */
+ subw $_data16_memsz_pgh, %ax
+ pushw %ax
+
+ /* Calculate .text16 segment address */
+ subw $_text16_memsz_pgh, %ax
+ pushw %ax
+
+ /* Update FBMS */
+ shrw $6, %ax
+ movw %ax, %fs:0x13
+
+ /* Retrieve .text16 and .data16 segment addresses */
+ popw %ax
+ popw %bx
+
+ /* Restore registers and return */
+ popw %fs
+ ret
+ .size alloc_basemem, . - alloc_basemem
+
+/****************************************************************************
+ * free_basemem
+ *
+ * Free space allocated with alloc_basemem.
+ *
+ * Parameters:
+ * %ax : .text16 segment address
+ * %bx : .data16 segment address
+ * Returns:
+ * %ax : 0 if successfully freed
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+ .code16
+ .globl free_basemem
+free_basemem:
+ /* Preserve registers */
+ pushw %fs
+
+ /* Check FBMS counter */
+ pushw %ax
+ shrw $6, %ax
+ pushw $0x40
+ popw %fs
+ cmpw %ax, %fs:0x13
+ popw %ax
+ jne 1f
+
+ /* Check hooked interrupt count */
+ cmpw $0, %cs:hooked_bios_interrupts
+ jne 1f
+
+ /* OK to free memory */
+ addw $_text16_memsz_pgh, %ax
+ addw $_data16_memsz_pgh, %ax
+ shrw $6, %ax
+ movw %ax, %fs:0x13
+ xorw %ax, %ax
+
+1: /* Restore registers and return */
+ popw %fs
+ ret
+ .size free_basemem, . - free_basemem
+
+ .section ".text16.data", "aw", @progbits
+ .globl hooked_bios_interrupts
+hooked_bios_interrupts:
+ .word 0
+ .size hooked_bios_interrupts, . - hooked_bios_interrupts
+
+/****************************************************************************
+ * install
+ *
+ * Install all text and data segments.
+ *
+ * Parameters:
+ * none
+ * Returns:
+ * %ax : .text16 segment address
+ * %bx : .data16 segment address
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ .section ".prefix.lib", "awx", @progbits
+ .code16
+ .globl install
+install:
+ progress "install:\n"
+ /* Preserve registers */
+ pushl %esi
+ pushl %edi
+ pushl %ebp
+ /* Allocate space for .text16 and .data16 */
+ call alloc_basemem
+ /* Image source = %cs:0000 */
+ xorl %esi, %esi
+ /* Image destination = default */
+ xorl %edi, %edi
+ /* Allow arbitrary relocation */
+ xorl %ebp, %ebp
+ /* Install text and data segments */
+ call install_prealloc
+ /* Restore registers and return */
+ popl %ebp
+ popl %edi
+ popl %esi
+ ret
+ .size install, . - install
+
+/****************************************************************************
+ * install_prealloc
+ *
+ * Install all text and data segments.
+ *
+ * Parameters:
+ * %ax : .text16 segment address
+ * %bx : .data16 segment address
+ * %esi : Image source physical address (or zero for %cs:0000)
+ * %edi : Decompression temporary area physical address (or zero for default)
+ * %ebp : Maximum end address for relocation (or zero for no maximum)
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ .section ".prefix.lib", "awx", @progbits
+ .code16
+ .globl install_prealloc
+install_prealloc:
+ progress "install_prealloc:\n"
+ /* Save registers */
+ pushal
+ pushw %ds
+ pushw %es
+ cld /* Sanity: clear the direction flag asap */
+
+ /* Set up %ds for (read-only) access to .prefix */
+ pushw %cs
+ popw %ds
+
+ /* Save decompression temporary area physical address */
+ pushl %edi
+
+ /* Install .text16.early */
+ progress " .text16.early\n"
+ pushl %esi
+ xorl %esi, %esi
+ movw %cs, %si
+ shll $4, %esi
+ addl $_text16_early_lma, %esi
+ movzwl %ax, %edi
+ shll $4, %edi
+ movl $_text16_early_filesz, %ecx
+ movl $_text16_early_memsz, %edx
+ call install_block /* .text16.early */
+ popl %esi
+
+#ifndef KEEP_IT_REAL
+ /* Access high memory by enabling the A20 gate. (We will
+ * already have 4GB segment limits as a result of calling
+ * install_block.)
+ */
+ progress " access_highmem\n"
+ pushw %cs
+ pushw $1f
+ pushw %ax
+ pushw $access_highmem
+ lret
+1: /* Die if we could not access high memory */
+ jnc 3f
+ movw $a20_death_message, %si
+ xorw %di, %di
+ call print_message
+2: jmp 2b
+ .section ".prefix.data", "aw", @progbits
+a20_death_message:
+ .asciz "\nHigh memory inaccessible - cannot continue\n"
+ .size a20_death_message, . - a20_death_message
+ .previous
+3:
+#endif
+
+ /* Open payload (which may not yet be in memory) */
+ progress " open_payload\n"
+ pushw %cs
+ pushw $1f
+ pushw %ax
+ pushw $open_payload
+ lret
+1: /* Die if we could not access the payload */
+ jnc 3f
+ xorw %di, %di
+ movl %esi, %eax
+ call print_hex_dword
+ movw $payload_death_message, %si
+ call print_message
+2: jmp 2b
+ .section ".prefix.data", "aw", @progbits
+payload_death_message:
+ .asciz "\nPayload inaccessible - cannot continue\n"
+ .size payload_death_message, . - payload_death_message
+ .previous
+3:
+
+ /* Calculate physical address of payload (i.e. first source) */
+ testl %esi, %esi
+ jnz 1f
+ movw %cs, %si
+ shll $4, %esi
+1: addl payload_lma, %esi
+
+ /* Install .text16.late and .data16 */
+ progress " .text16.late\n"
+ movl $_text16_late_filesz, %ecx
+ movl $_text16_late_memsz, %edx
+ call install_block /* .text16.late */
+ progress " .data16\n"
+ movzwl %bx, %edi
+ shll $4, %edi
+ movl $_data16_filesz, %ecx
+ movl $_data16_memsz, %edx
+ call install_block /* .data16 */
+
+ /* Set up %ds for access to .data16 */
+ movw %bx, %ds
+
+ /* Restore decompression temporary area physical address */
+ popl %edi
+
+#ifdef KEEP_IT_REAL
+ /* Initialise libkir */
+ movw %ax, (init_libkir_vector+2)
+ lcall *init_libkir_vector
+#else
+ /* Find a suitable decompression temporary area, if none specified */
+ pushl %eax
+ testl %edi, %edi
+ jnz 1f
+ /* Use INT 15,88 to find the highest available address via INT
+ * 15,88. This limits us to around 64MB, which should avoid
+ * all of the POST-time memory map failure modes.
+ */
+ movb $0x88, %ah
+ int $0x15
+ movw %ax, %di
+ addl $0x400, %edi
+ subl $_textdata_memsz_kb, %edi
+ shll $10, %edi
+ /* Sanity check: if we have ended up below 1MB, use 1MB */
+ cmpl $0x100000, %edi
+ jae 1f
+ movl $0x100000, %edi
+1: popl %eax
+
+ /* Install .text and .data to temporary area in high memory,
+ * prior to reading the E820 memory map and relocating
+ * properly.
+ */
+ progress " .textdata\n"
+ pushl %edi
+ movl $_textdata_filesz, %ecx
+ movl $_textdata_memsz, %edx
+ call install_block
+ popl %edi
+
+ /* Initialise librm at current location */
+ progress " init_librm\n"
+ movw %ax, (init_librm_vector+2)
+ lcall *init_librm_vector
+
+ /* Call relocate() to determine target address for relocation.
+ * relocate() will return with %esi, %edi and %ecx set up
+ * ready for the copy to the new location.
+ */
+ progress " relocate\n"
+ movw %ax, (prot_call_vector+2)
+ pushl $relocate
+ lcall *prot_call_vector
+ popl %edx /* discard */
+
+ /* Copy code to new location */
+ progress " copy\n"
+ pushl %edi
+ pushw %bx
+ movw $copy_bytes, %bx
+ call process_bytes
+ popw %bx
+ popl %edi
+
+ /* Initialise librm at new location */
+ progress " init_librm\n"
+ lcall *init_librm_vector
+#endif
+
+ /* Close access to payload */
+ progress " close_payload\n"
+ movw %ax, (close_payload_vector+2)
+ lcall *close_payload_vector
+
+ /* Restore registers */
+ popw %es
+ popw %ds
+ popal
+ ret
+ .size install_prealloc, . - install_prealloc
+
+ /* Vectors for far calls to .text16 functions. Must be in
+ * .data16, since .prefix may not be writable.
+ */
+ .section ".data16", "aw", @progbits
+#ifdef KEEP_IT_REAL
+init_libkir_vector:
+ .word init_libkir
+ .word 0
+ .size init_libkir_vector, . - init_libkir_vector
+#else
+init_librm_vector:
+ .word init_librm
+ .word 0
+ .size init_librm_vector, . - init_librm_vector
+prot_call_vector:
+ .word prot_call
+ .word 0
+ .size prot_call_vector, . - prot_call_vector
+#endif
+close_payload_vector:
+ .word close_payload
+ .word 0
+ .size close_payload_vector, . - close_payload_vector
+
+ /* Payload address */
+ .section ".prefix.lib", "awx", @progbits
+payload_lma:
+ .long 0
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
+ .ascii "ADHL"
+ .long payload_lma
+ .long 1
+ .long 0
+ .previous
+
+ /* Dummy routines to open and close payload */
+ .section ".text16.early.data", "aw", @progbits
+ .weak open_payload
+ .weak close_payload
+open_payload:
+close_payload:
+ clc
+ lret
+ .size open_payload, . - open_payload
+ .size close_payload, . - close_payload
+
+/****************************************************************************
+ * uninstall
+ *
+ * Uninstall all text and data segments.
+ *
+ * Parameters:
+ * %ax : .text16 segment address
+ * %bx : .data16 segment address
+ * Returns:
+ * none
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+ .code16
+ .globl uninstall
+uninstall:
+ call free_basemem
+ ret
+ .size uninstall, . - uninstall
+
+
+
+ /* File split information for the compressor */
+#if COMPRESS
+#define PACK_OR_COPY "PACK"
+#else
+#define PACK_OR_COPY "COPY"
+#endif
+ .section ".zinfo", "a", @progbits
+ .ascii "COPY"
+ .long _prefix_lma
+ .long _prefix_filesz
+ .long _max_align
+ .ascii PACK_OR_COPY
+ .long _text16_early_lma
+ .long _text16_early_filesz
+ .long _max_align
+ .ascii "PAYL"
+ .long 0
+ .long 0
+ .long _max_align
+ .ascii PACK_OR_COPY
+ .long _text16_late_lma
+ .long _text16_late_filesz
+ .long _max_align
+ .ascii PACK_OR_COPY
+ .long _data16_lma
+ .long _data16_filesz
+ .long _max_align
+ .ascii PACK_OR_COPY
+ .long _textdata_lma
+ .long _textdata_filesz
+ .long _max_align
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/lkrnprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/lkrnprefix.S
new file mode 100644
index 00000000..76890332
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/lkrnprefix.S
@@ -0,0 +1,274 @@
+/*
+ Copyright (C) 2000, Entity Cyber, Inc.
+
+ Authors: Gary Byers (gb@thinguin.org)
+ Marty Connor (mdc@thinguin.org)
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License (GPL), incorporated herein by reference.
+
+ Description:
+
+ This is just a little bit of code and data that can get prepended
+ to a ROM image in order to allow bootloaders to load the result
+ as if it were a Linux kernel image.
+
+ A real Linux kernel image consists of a one-sector boot loader
+ (to load the image from a floppy disk), followed a few sectors
+ of setup code, followed by the kernel code itself. There's
+ a table in the first sector (starting at offset 497) that indicates
+ how many sectors of setup code follow the first sector and which
+ contains some other parameters that aren't interesting in this
+ case.
+
+ When a bootloader loads the sectors that comprise a kernel image,
+ it doesn't execute the code in the first sector (since that code
+ would try to load the image from a floppy disk.) The code in the
+ first sector below doesn't expect to get executed (and prints an
+ error message if it ever -is- executed.)
+
+ We don't require much in the way of setup code. Historically, the
+ Linux kernel required at least 4 sectors of setup code.
+ Therefore, at least 4 sectors must be present even though we don't
+ use them.
+
+*/
+
+FILE_LICENCE ( GPL_ANY )
+
+#define SETUPSECS 4 /* Minimal nr of setup-sectors */
+#define PREFIXSIZE ((SETUPSECS+1)*512)
+#define PREFIXPGH (PREFIXSIZE / 16 )
+#define BOOTSEG 0x07C0 /* original address of boot-sector */
+#define INITSEG 0x9000 /* we move boot here - out of the way */
+#define SETUPSEG 0x9020 /* setup starts here */
+#define SYSSEG 0x1000 /* system loaded at 0x10000 (65536). */
+
+ .text
+ .code16
+ .arch i386
+ .org 0
+ .section ".prefix", "ax", @progbits
+ .globl _lkrn_start
+_lkrn_start:
+/*
+ This is a minimal boot sector. If anyone tries to execute it (e.g., if
+ a .lilo file is dd'ed to a floppy), print an error message.
+*/
+
+bootsector:
+ jmp $BOOTSEG, $1f /* reload cs:ip to match relocation addr */
+1:
+ movw $0x2000, %di /* 0x2000 is arbitrary value >= length
+ of bootsect + room for stack */
+
+ movw $BOOTSEG, %ax
+ movw %ax,%ds
+ movw %ax,%es
+
+ cli
+ movw %ax, %ss /* put stack at BOOTSEG:0x2000. */
+ movw %di,%sp
+ sti
+
+ movw $why_end-why, %cx
+ movw $why, %si
+
+ movw $0x0007, %bx /* page 0, attribute 7 (normal) */
+ movb $0x0e, %ah /* write char, tty mode */
+prloop:
+ lodsb
+ int $0x10
+ loop prloop
+freeze: jmp freeze
+
+why: .ascii "This image cannot be loaded from a floppy disk.\r\n"
+why_end:
+
+
+/*
+ The following header is documented in the Linux source code at
+ Documentation/x86/boot.txt
+*/
+ .org 497
+setup_sects:
+ .byte SETUPSECS
+root_flags:
+ .word 0
+syssize:
+ .long -PREFIXPGH
+
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
+ .ascii "ADDL"
+ .long syssize
+ .long 16
+ .long 0
+ .previous
+
+ram_size:
+ .word 0
+vid_mode:
+ .word 0
+root_dev:
+ .word 0
+boot_flag:
+ .word 0xAA55
+jump:
+ /* Manually specify a two-byte jmp instruction here rather
+ * than leaving it up to the assembler. */
+ .byte 0xeb
+ .byte setup_code - header
+header:
+ .byte 'H', 'd', 'r', 'S'
+version:
+ .word 0x0207 /* 2.07 */
+realmode_swtch:
+ .long 0
+start_sys:
+ .word 0
+kernel_version:
+ .word 0
+type_of_loader:
+ .byte 0
+loadflags:
+ .byte 0
+setup_move_size:
+ .word 0
+code32_start:
+ .long 0
+ramdisk_image:
+ .long 0
+ramdisk_size:
+ .long 0
+bootsect_kludge:
+ .long 0
+heap_end_ptr:
+ .word 0
+pad1:
+ .word 0
+cmd_line_ptr:
+ .long 0
+initrd_addr_max:
+ /* We don't use an initrd but some bootloaders (e.g. SYSLINUX) have
+ * been known to require this field. Set the value to 2 GB. This
+ * value is also used by the Linux kernel. */
+ .long 0x7fffffff
+kernel_alignment:
+ .long 0
+relocatable_kernel:
+ .byte 0
+pad2:
+ .byte 0, 0, 0
+cmdline_size:
+ .long 0x7ff
+hardware_subarch:
+ .long 0
+hardware_subarch_data:
+ .byte 0, 0, 0, 0, 0, 0, 0, 0
+
+/*
+ We don't need to do too much setup.
+
+ This code gets loaded at SETUPSEG:0. It wants to start
+ executing the image that's loaded at SYSSEG:0 and
+ whose entry point is SYSSEG:0.
+*/
+setup_code:
+ /* We expect to be contiguous in memory once loaded. The Linux image
+ * boot process requires that setup code is loaded separately from
+ * "non-real code". Since we don't need any information that's left
+ * in the prefix, it doesn't matter: we just have to ensure that
+ * %cs:0000 is where the start of the image *would* be.
+ */
+ ljmp $(SYSSEG-(PREFIXSIZE/16)), $run_ipxe
+
+
+ .org PREFIXSIZE
+/*
+ We're now at the beginning of the kernel proper.
+ */
+run_ipxe:
+ /* Set up stack just below 0x7c00 and clear direction flag */
+ xorw %ax, %ax
+ movw %ax, %ss
+ movw $0x7c00, %sp
+ cld
+
+ /* Retrieve command-line pointer */
+ movl %ds:cmd_line_ptr, %edx
+ testl %edx, %edx
+ jz no_cmd_line
+
+ /* Set up %es:%di to point to command line */
+ movl %edx, %edi
+ andl $0xf, %edi
+ rorl $4, %edx
+ movw %dx, %es
+
+ /* Find length of command line */
+ pushw %di
+ movw $0xffff, %cx
+ repnz scasb
+ notw %cx
+ popw %si
+
+ /* Make space for command line on stack */
+ movw %sp, %di
+ subw %cx, %di
+ andw $~0xf, %di
+ movw %di, %sp
+
+ /* Copy command line to stack */
+ pushw %ds
+ pushw %es
+ popw %ds
+ pushw %ss
+ popw %es
+ rep movsb
+ popw %ds
+
+ /* Store new command-line pointer */
+ movzwl %sp, %edx
+no_cmd_line:
+
+ /* Retrieve initrd pointer and size */
+ movl %ds:ramdisk_image, %ebp
+ movl %ds:ramdisk_size, %ecx
+
+ /* Install iPXE */
+ call alloc_basemem
+ xorl %esi, %esi
+ xorl %edi, %edi
+ call install_prealloc
+
+ /* Set up real-mode stack */
+ movw %bx, %ss
+ movw $_estack16, %sp
+
+ /* Jump to .text16 segment */
+ pushw %ax
+ pushw $1f
+ lret
+ .section ".text16", "awx", @progbits
+1:
+ /* Set up %ds for access to .data16 */
+ movw %bx, %ds
+
+ /* Store command-line pointer */
+ movl %edx, cmdline_phys
+
+ /* Store initrd pointer and size */
+ movl %ebp, initrd_phys
+ movl %ecx, initrd_len
+
+ /* Run iPXE */
+ pushl $main
+ pushw %cs
+ call prot_call
+ popl %ecx /* discard */
+
+ /* Uninstall iPXE */
+ call uninstall
+
+ /* Boot next device */
+ int $0x18
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/mbr.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/mbr.S
new file mode 100644
index 00000000..adfe2041
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/mbr.S
@@ -0,0 +1,13 @@
+ .text
+ .arch i386
+ .section ".prefix", "awx", @progbits
+ .code16
+ .org 0
+
+mbr:
+ movw $exec_sector, %bp
+ jmp find_active_partition
+exec_sector:
+ ljmp $0x0000, $0x7c00
+
+#include "bootpart.S"
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/mromprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/mromprefix.S
new file mode 100644
index 00000000..7bbe44c4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/mromprefix.S
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#define PCIBIOS_READ_CONFIG_WORD 0xb109
+#define PCIBIOS_READ_CONFIG_DWORD 0xb10a
+#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c
+#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d
+#define PCI_COMMAND 0x04
+#define PCI_COMMAND_MEM 0x02
+#define PCI_BAR_0 0x10
+#define PCI_BAR_5 0x24
+#define PCI_BAR_EXPROM 0x30
+
+#define ROMPREFIX_EXCLUDE_PAYLOAD 1
+#define _rom_start _mrom_start
+#include "romprefix.S"
+
+ .text
+ .arch i386
+ .code16
+
+/* Obtain access to payload by exposing the expansion ROM BAR at the
+ * address currently used by a suitably large memory BAR on the same
+ * device. The memory BAR is temporarily disabled. Using a memory
+ * BAR on the same device means that we don't have to worry about the
+ * configuration of any intermediate PCI bridges.
+ *
+ * Parameters:
+ * %ds:0000 : Prefix
+ * %esi : Buffer for copy of image source (or zero if no buffer available)
+ * Returns:
+ * %esi : Valid image source address (buffered or unbuffered)
+ * CF set on error
+ */
+ .section ".text16.early", "awx", @progbits
+ .globl open_payload
+open_payload:
+ /* Preserve registers */
+ pushl %eax
+ pushw %bx
+ pushl %ecx
+ pushl %edx
+ pushl %edi
+ pushw %bp
+ pushw %ds
+
+ /* Retrieve bus:dev.fn and image source length from .prefix */
+ movw init_pci_busdevfn, %bx
+ movl image_source_len_dword, %ecx
+
+ /* Set up %ds for access to .text16.early */
+ pushw %cs
+ popw %ds
+
+ /* Store bus:dev.fn and image source length to .text16.early */
+ movw %bx, payload_pci_busdevfn
+ movl %ecx, rom_bar_copy_len_dword
+
+ /* Get expansion ROM BAR current value */
+ movw $PCI_BAR_EXPROM, %di
+ call pci_read_bar
+ movl %eax, rom_bar_orig_value
+
+ /* Get expansion ROM BAR size */
+ call pci_size_mem_bar_low
+ movl %ecx, rom_bar_size
+
+ /* Find a suitable memory BAR to use */
+ movw $PCI_BAR_0, %di /* %di is PCI BAR register */
+ xorw %bp, %bp /* %bp is increment */
+find_mem_bar:
+ /* Move to next BAR */
+ addw %bp, %di
+ cmpw $PCI_BAR_5, %di
+ jle 1f
+ stc
+ jmp 99f
+1: movw $4, %bp
+
+ /* Get BAR current value */
+ call pci_read_bar
+
+ /* Skip non-existent BARs */
+ notl %eax
+ testl %eax, %eax
+ notl %eax
+ jz find_mem_bar
+
+ /* Skip I/O BARs */
+ testb $0x01, %al
+ jnz find_mem_bar
+
+ /* Set increment to 8 for 64-bit BARs */
+ testb $0x04, %al
+ jz 1f
+ movw $8, %bp
+1:
+ /* Skip 64-bit BARs with high dword set; we couldn't use this
+ * address for the (32-bit) expansion ROM BAR anyway
+ */
+ testl %edx, %edx
+ jnz find_mem_bar
+
+ /* Get low dword of BAR size */
+ call pci_size_mem_bar_low
+
+ /* Skip BARs smaller than the expansion ROM BAR */
+ cmpl %ecx, rom_bar_size
+ ja find_mem_bar
+
+ /* We have a memory BAR with a 32-bit address that is large
+ * enough to use. Store BAR number and original value.
+ */
+ movw %di, stolen_bar_register
+ movl %eax, stolen_bar_orig_value
+
+ /* Remove flags from BAR address */
+ xorb %al, %al
+
+ /* Write zero to our stolen BAR. This doesn't technically
+ * disable it, but it's a pretty safe bet that the PCI bridge
+ * won't pass through accesses to this region anyway. Note
+ * that the high dword (if any) must already be zero.
+ */
+ xorl %ecx, %ecx
+ call pci_write_config_dword
+
+ /* Enable expansion ROM BAR at stolen BAR's address */
+ movl %eax, %ecx
+ orb $0x1, %cl
+ movw $PCI_BAR_EXPROM, %di
+ call pci_write_config_dword
+
+ /* Copy payload to buffer, or set buffer address to BAR address */
+ testl %esi, %esi
+ jz 1f
+ /* We have a buffer; copy payload to it. Since .mrom is
+ * designed specifically for real hardware, we assume that
+ * flat real mode is working properly. (In the unlikely event
+ * that this code is run inside a hypervisor that doesn't
+ * properly support flat real mode, it will die horribly.)
+ */
+ pushl %esi
+ pushw %es
+ movl %esi, %edi
+ movl %eax, %esi
+ movl rom_bar_copy_len_dword, %ecx
+ xorw %ax, %ax
+ movw %ax, %es
+ addr32 es rep movsl
+ popw %es
+ popl %esi
+ jmp 2f
+1: /* We have no buffer; set %esi to the BAR address */
+ movl %eax, %esi
+2:
+
+ clc
+ /* Restore registers and return */
+99: popw %ds
+ popw %bp
+ popl %edi
+ popl %edx
+ popl %ecx
+ popw %bx
+ popl %eax
+ lret
+ .size open_payload, . - open_payload
+
+ .section ".text16.early.data", "aw", @progbits
+payload_pci_busdevfn:
+ .word 0
+ .size payload_pci_busdevfn, . - payload_pci_busdevfn
+
+ .section ".text16.early.data", "aw", @progbits
+rom_bar_orig_value:
+ .long 0
+ .size rom_bar_orig_value, . - rom_bar_orig_value
+
+ .section ".text16.early.data", "aw", @progbits
+rom_bar_size:
+ .long 0
+ .size rom_bar_size, . - rom_bar_size
+
+ .section ".text16.early.data", "aw", @progbits
+rom_bar_copy_len_dword:
+ .long 0
+ .size rom_bar_copy_len_dword, . - rom_bar_copy_len_dword
+
+ .section ".text16.early.data", "aw", @progbits
+stolen_bar_register:
+ .word 0
+ .size stolen_bar_register, . - stolen_bar_register
+
+ .section ".text16.early.data", "aw", @progbits
+stolen_bar_orig_value:
+ .long 0
+ .size stolen_bar_orig_value, . - stolen_bar_orig_value
+
+/* Restore original BAR values
+ *
+ * Parameters:
+ * none
+ * Returns:
+ * none
+ */
+ .section ".text16.early", "awx", @progbits
+ .globl close_payload
+close_payload:
+ /* Preserve registers */
+ pushw %bx
+ pushw %di
+ pushl %ecx
+ pushw %ds
+
+ /* Set up %ds for access to .text16.early */
+ pushw %cs
+ popw %ds
+
+ /* Retrieve stored bus:dev.fn */
+ movw payload_pci_busdevfn, %bx
+
+ /* Restore expansion ROM BAR original value */
+ movw $PCI_BAR_EXPROM, %di
+ movl rom_bar_orig_value, %ecx
+ call pci_write_config_dword
+
+ /* Restore stolen BAR original value */
+ movw stolen_bar_register, %di
+ movl stolen_bar_orig_value, %ecx
+ call pci_write_config_dword
+
+ /* Restore registers and return */
+ popw %ds
+ popl %ecx
+ popw %di
+ popw %bx
+ lret
+ .size close_payload, . - close_payload
+
+/* Get PCI BAR value
+ *
+ * Parameters:
+ * %bx : PCI bus:dev.fn
+ * %di : PCI BAR register number
+ * Returns:
+ * %edx:%eax : PCI BAR value
+ */
+ .section ".text16.early", "awx", @progbits
+pci_read_bar:
+ /* Preserve registers */
+ pushl %ecx
+ pushw %di
+
+ /* Read low dword value */
+ call pci_read_config_dword
+ movl %ecx, %eax
+
+ /* Read high dword value, if applicable */
+ xorl %edx, %edx
+ andb $0x07, %cl
+ cmpb $0x04, %cl
+ jne 1f
+ addw $4, %di
+ call pci_read_config_dword
+ movl %ecx, %edx
+1:
+ /* Restore registers and return */
+ popw %di
+ popl %ecx
+ ret
+ .size pci_read_bar, . - pci_read_bar
+
+/* Get low dword of PCI memory BAR size
+ *
+ * Parameters:
+ * %bx : PCI bus:dev.fn
+ * %di : PCI BAR register number
+ * %eax : Low dword of current PCI BAR value
+ * Returns:
+ * %ecx : PCI BAR size
+ */
+ .section ".text16.early", "awx", @progbits
+pci_size_mem_bar_low:
+ /* Preserve registers */
+ pushw %dx
+
+ /* Disable memory accesses */
+ xorw %dx, %dx
+ call pci_set_mem_access
+
+ /* Write all ones to BAR */
+ xorl %ecx, %ecx
+ decl %ecx
+ call pci_write_config_dword
+
+ /* Read back BAR */
+ call pci_read_config_dword
+
+ /* Calculate size */
+ notl %ecx
+ orb $0x0f, %cl
+ incl %ecx
+
+ /* Restore original value */
+ pushl %ecx
+ movl %eax, %ecx
+ call pci_write_config_dword
+ popl %ecx
+
+ /* Enable memory accesses */
+ movw $PCI_COMMAND_MEM, %dx
+ call pci_set_mem_access
+
+ /* Restore registers and return */
+ popw %dx
+ ret
+ .size pci_size_mem_bar_low, . - pci_size_mem_bar_low
+
+/* Read PCI config dword
+ *
+ * Parameters:
+ * %bx : PCI bus:dev.fn
+ * %di : PCI register number
+ * Returns:
+ * %ecx : Dword value
+ */
+ .section ".text16.early", "awx", @progbits
+pci_read_config_dword:
+ /* Preserve registers */
+ pushl %eax
+ pushl %ebx
+ pushl %edx
+
+ /* Issue INT 0x1a,b10a */
+ movw $PCIBIOS_READ_CONFIG_DWORD, %ax
+ int $0x1a
+
+ /* Restore registers and return */
+ popl %edx
+ popl %ebx
+ popl %eax
+ ret
+ .size pci_read_config_dword, . - pci_read_config_dword
+
+/* Write PCI config dword
+ *
+ * Parameters:
+ * %bx : PCI bus:dev.fn
+ * %di : PCI register number
+ * %ecx : PCI BAR value
+ * Returns:
+ * none
+ */
+ .section ".text16.early", "awx", @progbits
+pci_write_config_dword:
+ /* Preserve registers */
+ pushal
+
+ /* Issue INT 0x1a,b10d */
+ movw $PCIBIOS_WRITE_CONFIG_DWORD, %ax
+ int $0x1a
+
+ /* Restore registers and return */
+ popal
+ ret
+ .size pci_write_config_dword, . - pci_write_config_dword
+
+/* Enable/disable memory access response in PCI command word
+ *
+ * Parameters:
+ * %bx : PCI bus:dev.fn
+ * %dx : PCI_COMMAND_MEM, or zero
+ * Returns:
+ * none
+ */
+ .section ".text16.early", "awx", @progbits
+pci_set_mem_access:
+ /* Preserve registers */
+ pushal
+
+ /* Read current value of command register */
+ pushw %bx
+ pushw %dx
+ movw $PCI_COMMAND, %di
+ movw $PCIBIOS_READ_CONFIG_WORD, %ax
+ int $0x1a
+ popw %dx
+ popw %bx
+
+ /* Set memory access enable as appropriate */
+ andw $~PCI_COMMAND_MEM, %cx
+ orw %dx, %cx
+
+ /* Write new value of command register */
+ movw $PCIBIOS_WRITE_CONFIG_WORD, %ax
+ int $0x1a
+
+ /* Restore registers and return */
+ popal
+ ret
+ .size pci_set_mem_access, . - pci_set_mem_access
+
+/* Image source area length (in dwords)
+ *
+ */
+ .section ".prefix", "ax", @progbits
+image_source_len_dword:
+ .long 0
+ .size image_source_len_dword, . - image_source_len_dword
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
+ .ascii "ADDL"
+ .long image_source_len_dword
+ .long 4
+ .long 0
+ .previous
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/nbiprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/nbiprefix.S
new file mode 100644
index 00000000..20d224d6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/nbiprefix.S
@@ -0,0 +1,78 @@
+ .text
+ .arch i386
+ .code16
+ .section ".prefix", "ax", @progbits
+ .org 0
+
+nbi_header:
+
+/*****************************************************************************
+ * NBI file header
+ *****************************************************************************
+ */
+file_header:
+ .long 0x1b031336 /* Signature */
+ .byte 0x04 /* 16 bytes header, no vendor info */
+ .byte 0
+ .byte 0
+ .byte 0 /* No flags */
+ .word 0x0000, 0x07c0 /* Load header to 0x07c0:0x0000 */
+ .word _nbi_start, 0x07c0 /* Start execution at 0x07c0:entry */
+ .size file_header, . - file_header
+
+/*****************************************************************************
+ * NBI segment header
+ *****************************************************************************
+ */
+segment_header:
+ .byte 0x04 /* 16 bytes header, no vendor info */
+ .byte 0
+ .byte 0
+ .byte 0x04 /* Last segment */
+ .long 0x00007e00
+imglen: .long -512
+memlen: .long -512
+ .size segment_header, . - segment_header
+
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
+ .ascii "ADDL"
+ .long imglen
+ .long 1
+ .long 0
+ .ascii "ADDL"
+ .long memlen
+ .long 1
+ .long 0
+ .previous
+
+/*****************************************************************************
+ * NBI entry point
+ *****************************************************************************
+ */
+ .globl _nbi_start
+_nbi_start:
+ /* Install iPXE */
+ call install
+
+ /* Jump to .text16 segment */
+ pushw %ax
+ pushw $1f
+ lret
+ .section ".text16", "awx", @progbits
+1:
+ pushl $main
+ pushw %cs
+ call prot_call
+ popl %ecx /* discard */
+
+ /* Uninstall iPXE */
+ call uninstall
+
+ /* Reboot system */
+ int $0x19
+
+ .previous
+ .size _nbi_start, . - _nbi_start
+
+nbi_header_end:
+ .org 512
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/nullprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/nullprefix.S
new file mode 100644
index 00000000..032d41e0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/nullprefix.S
@@ -0,0 +1,13 @@
+ .org 0
+ .text
+ .arch i386
+
+ .section ".prefix", "ax", @progbits
+ .code16
+_prefix:
+
+ .section ".text16", "ax", @progbits
+prefix_exit:
+
+prefix_exit_end:
+ .previous
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/pxeprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/pxeprefix.S
new file mode 100644
index 00000000..f59e347a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/pxeprefix.S
@@ -0,0 +1,766 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#define PXENV_UNDI_SHUTDOWN 0x0005
+#define PXENV_UNDI_GET_NIC_TYPE 0x0012
+#define PXENV_UNDI_GET_IFACE_INFO 0x0013
+#define PXENV_STOP_UNDI 0x0015
+#define PXENV_UNLOAD_STACK 0x0070
+
+#define PXE_HACK_EB54 0x0001
+
+ .text
+ .arch i386
+ .org 0
+ .code16
+
+#include <undi.h>
+
+#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
+#define EB_MAGIC_1 ( 'E' + ( 't' << 8 ) + ( 'h' << 16 ) + ( 'e' << 24 ) )
+#define EB_MAGIC_2 ( 'r' + ( 'b' << 8 ) + ( 'o' << 16 ) + ( 'o' << 24 ) )
+
+/*****************************************************************************
+ * Entry point: set operating context, print welcome message
+ *****************************************************************************
+ */
+ .section ".prefix", "ax", @progbits
+ .globl _pxe_start
+_pxe_start:
+ jmp $0x7c0, $1f
+1:
+ /* Preserve registers for possible return to PXE */
+ pushfl
+ pushal
+ pushw %gs
+ pushw %fs
+ pushw %es
+ pushw %ds
+
+ /* Store magic word on PXE stack and remember PXE %ss:esp */
+ pushl $STACK_MAGIC
+ movw %ss, %cs:pxe_ss
+ movl %esp, %cs:pxe_esp
+
+ /* Set up segments */
+ movw %cs, %ax
+ movw %ax, %ds
+ movw $0x40, %ax /* BIOS data segment access */
+ movw %ax, %fs
+ /* Set up stack just below 0x7c00 */
+ xorw %ax, %ax
+ movw %ax, %ss
+ movl $0x7c00, %esp
+ /* Clear direction flag, for the sake of sanity */
+ cld
+ /* Print welcome message */
+ movw $10f, %si
+ xorw %di, %di
+ call print_message
+ .section ".prefix.data", "aw", @progbits
+10: .asciz "PXE->EB:"
+ .previous
+
+/*****************************************************************************
+ * Find us a usable !PXE or PXENV+ entry point
+ *****************************************************************************
+ */
+detect_pxe:
+ /* Plan A: !PXE pointer from the stack */
+ lgsl pxe_esp, %ebp /* %gs:%bp -> original stack */
+ lesw %gs:52(%bp), %bx
+ call is_valid_ppxe
+ je have_ppxe
+
+ /* Plan B: PXENV+ pointer from initial ES:BX */
+ movw %gs:32(%bp),%bx
+ movw %gs:8(%bp),%es
+ call is_valid_pxenv
+ je have_pxenv
+
+ /* Plan C: PXENV+ structure via INT 1Ah */
+ movw $0x5650, %ax
+ int $0x1a
+ jc 1f
+ cmpw $0x564e, %ax
+ jne 1f
+ call is_valid_pxenv
+ je have_pxenv
+1:
+ /* Plan D: scan base memory for !PXE */
+ call memory_scan_ppxe
+ je have_ppxe
+
+ /* Plan E: scan base memory for PXENV+ */
+ call memory_scan_pxenv
+ jne stack_not_found
+
+have_pxenv:
+ movw %bx, pxenv_offset
+ movw %es, pxenv_segment
+
+ cmpw $0x201, %es:6(%bx) /* API version >= 2.01 */
+ jb 1f
+ cmpb $0x2c, %es:8(%bx) /* ... and structure long enough */
+ jb 2f
+
+ lesw %es:0x28(%bx), %bx /* Find !PXE from PXENV+ */
+ call is_valid_ppxe
+ je have_ppxe
+2:
+ call memory_scan_ppxe /* We are *supposed* to have !PXE... */
+ je have_ppxe
+1:
+ lesw pxenv_segoff, %bx /* Nope, we're stuck with PXENV+ */
+
+ /* Record entry point and UNDI segments */
+ pushl %es:0x0a(%bx) /* Entry point */
+ pushw %es:0x24(%bx) /* UNDI code segment */
+ pushw %es:0x26(%bx) /* UNDI code size */
+ pushw %es:0x20(%bx) /* UNDI data segment */
+ pushw %es:0x22(%bx) /* UNDI data size */
+
+ /* Print "PXENV+ at <address>" */
+ movw $10f, %si
+ jmp check_have_stack
+ .section ".prefix.data", "aw", @progbits
+10: .asciz " PXENV+ at "
+ .previous
+
+have_ppxe:
+ movw %bx, ppxe_offset
+ movw %es, ppxe_segment
+
+ pushl %es:0x10(%bx) /* Entry point */
+ pushw %es:0x30(%bx) /* UNDI code segment */
+ pushw %es:0x36(%bx) /* UNDI code size */
+ pushw %es:0x28(%bx) /* UNDI data segment */
+ pushw %es:0x2e(%bx) /* UNDI data size */
+
+ /* Print "!PXE at <address>" */
+ movw $10f, %si
+ jmp check_have_stack
+ .section ".prefix.data", "aw", @progbits
+10: .asciz " !PXE at "
+ .previous
+
+is_valid_ppxe:
+ cmpl $0x45585021, %es:(%bx)
+ jne 1f
+ movzbw %es:4(%bx), %cx
+ cmpw $0x58, %cx
+ jae is_valid_checksum
+1:
+ ret
+
+is_valid_pxenv:
+ cmpl $0x4e455850, %es:(%bx)
+ jne 1b
+ cmpw $0x2b56, %es:4(%bx)
+ jne 1b
+ movzbw %es:8(%bx), %cx
+ cmpw $0x28, %cx
+ jb 1b
+
+is_valid_checksum:
+ pushw %ax
+ movw %bx, %si
+ xorw %ax, %ax
+2:
+ es lodsb
+ addb %al, %ah
+ loopw 2b
+ popw %ax
+ ret
+
+memory_scan_ppxe:
+ movw $is_valid_ppxe, %dx
+ jmp memory_scan_common
+
+memory_scan_pxenv:
+ movw $is_valid_pxenv, %dx
+
+memory_scan_common:
+ movw %fs:(0x13), %ax
+ shlw $6, %ax
+ decw %ax
+1: incw %ax
+ cmpw $( 0xa000 - 1 ), %ax
+ ja 2f
+ movw %ax, %es
+ xorw %bx, %bx
+ call *%dx
+ jne 1b
+2: ret
+
+/*****************************************************************************
+ * Sanity check: we must have an entry point
+ *****************************************************************************
+ */
+check_have_stack:
+ /* Save common values pushed onto the stack */
+ popl undi_data_segoff
+ popl undi_code_segoff
+ popl entry_segoff
+
+ /* Print have !PXE/PXENV+ message; structure pointer in %es:%bx */
+ call print_message
+ call print_segoff
+ movb $( ',' ), %al
+ call print_character
+
+ /* Check for entry point */
+ movl entry_segoff, %eax
+ testl %eax, %eax
+ jnz 99f
+ /* No entry point: print message and skip everything else */
+stack_not_found:
+ movw $10f, %si
+ call print_message
+ jmp finished
+ .section ".prefix.data", "aw", @progbits
+10: .asciz " No PXE stack found!\n"
+ .previous
+99:
+
+/*****************************************************************************
+ * Calculate base memory usage by UNDI
+ *****************************************************************************
+ */
+find_undi_basemem_usage:
+ movw undi_code_segment, %ax
+ movw undi_code_size, %bx
+ movw undi_data_segment, %cx
+ movw undi_data_size, %dx
+ cmpw %ax, %cx
+ ja 1f
+ xchgw %ax, %cx
+ xchgw %bx, %dx
+1: /* %ax:%bx now describes the lower region, %cx:%dx the higher */
+ shrw $6, %ax /* Round down to nearest kB */
+ movw %ax, undi_fbms_start
+ addw $0x0f, %dx /* Round up to next segment */
+ shrw $4, %dx
+ addw %dx, %cx
+ addw $((1024 / 16) - 1), %cx /* Round up to next kB */
+ shrw $6, %cx
+ movw %cx, undi_fbms_end
+
+/*****************************************************************************
+ * Print information about detected PXE stack
+ *****************************************************************************
+ */
+print_structure_information:
+ /* Print entry point */
+ movw $10f, %si
+ call print_message
+ les entry_segoff, %bx
+ call print_segoff
+ .section ".prefix.data", "aw", @progbits
+10: .asciz " entry point at "
+ .previous
+ /* Print UNDI code segment */
+ movw $10f, %si
+ call print_message
+ les undi_code_segoff, %bx
+ call print_segoff
+ .section ".prefix.data", "aw", @progbits
+10: .asciz "\n UNDI code segment "
+ .previous
+ /* Print UNDI data segment */
+ movw $10f, %si
+ call print_message
+ les undi_data_segoff, %bx
+ call print_segoff
+ .section ".prefix.data", "aw", @progbits
+10: .asciz ", data segment "
+ .previous
+ /* Print UNDI memory usage */
+ movw $10f, %si
+ call print_message
+ movw undi_fbms_start, %ax
+ call print_word
+ movb $( '-' ), %al
+ call print_character
+ movw undi_fbms_end, %ax
+ call print_word
+ movw $20f, %si
+ call print_message
+ .section ".prefix.data", "aw", @progbits
+10: .asciz " ("
+20: .asciz "kB)\n"
+ .previous
+
+/*****************************************************************************
+ * Determine physical device
+ *****************************************************************************
+ */
+get_physical_device:
+ /* Issue PXENV_UNDI_GET_NIC_TYPE */
+ movw $PXENV_UNDI_GET_NIC_TYPE, %bx
+ call pxe_call
+ jnc 1f
+ call print_pxe_error
+ jmp no_physical_device
+1: /* Determine physical device type */
+ movb ( pxe_parameter_structure + 0x02 ), %al
+ cmpb $2, %al
+ je pci_physical_device
+ jmp no_physical_device
+
+pci_physical_device:
+ /* Record PCI bus:dev.fn and vendor/device IDs */
+ movl ( pxe_parameter_structure + 0x03 ), %eax
+ movl %eax, pci_vendor
+ movw ( pxe_parameter_structure + 0x0b ), %ax
+ movw %ax, pci_busdevfn
+ movw $10f, %si
+ call print_message
+ call print_pci_busdevfn
+ jmp 99f
+ .section ".prefix.data", "aw", @progbits
+10: .asciz " UNDI device is PCI "
+ .previous
+
+no_physical_device:
+ /* No device found, or device type not understood */
+ movw $10f, %si
+ call print_message
+ .section ".prefix.data", "aw", @progbits
+10: .asciz " Unable to determine UNDI physical device"
+ .previous
+
+99:
+
+/*****************************************************************************
+ * Determine interface type
+ *****************************************************************************
+ */
+get_iface_type:
+ /* Issue PXENV_UNDI_GET_IFACE_INFO */
+ movw $PXENV_UNDI_GET_IFACE_INFO, %bx
+ call pxe_call
+ jnc 1f
+ call print_pxe_error
+ jmp 99f
+1: /* Print interface type */
+ movw $10f, %si
+ call print_message
+ leaw ( pxe_parameter_structure + 0x02 ), %si
+ call print_message
+ .section ".prefix.data", "aw", @progbits
+10: .asciz ", type "
+ .previous
+ /* Check for "Etherboot" interface type */
+ cmpl $EB_MAGIC_1, ( pxe_parameter_structure + 0x02 )
+ jne 99f
+ cmpl $EB_MAGIC_2, ( pxe_parameter_structure + 0x06 )
+ jne 99f
+ movw $10f, %si
+ call print_message
+ .section ".prefix.data", "aw", @progbits
+10: .asciz " (workaround enabled)"
+ .previous
+ /* Flag Etherboot workarounds as required */
+ orw $PXE_HACK_EB54, pxe_hacks
+
+99: movb $0x0a, %al
+ call print_character
+
+/*****************************************************************************
+ * Leave NIC in a safe state
+ *****************************************************************************
+ */
+#ifndef PXELOADER_KEEP_PXE
+shutdown_nic:
+ /* Issue PXENV_UNDI_SHUTDOWN */
+ movw $PXENV_UNDI_SHUTDOWN, %bx
+ call pxe_call
+ jnc 1f
+ call print_pxe_error
+1:
+unload_base_code:
+ /* Etherboot treats PXENV_UNLOAD_STACK as PXENV_STOP_UNDI, so
+ * we must not issue this call if the underlying stack is
+ * Etherboot and we were not intending to issue a PXENV_STOP_UNDI.
+ */
+#ifdef PXELOADER_KEEP_UNDI
+ testw $PXE_HACK_EB54, pxe_hacks
+ jnz 99f
+#endif /* PXELOADER_KEEP_UNDI */
+ /* Issue PXENV_UNLOAD_STACK */
+ movw $PXENV_UNLOAD_STACK, %bx
+ call pxe_call
+ jnc 1f
+ call print_pxe_error
+ jmp 99f
+1: /* Free base memory used by PXE base code */
+ movw undi_fbms_start, %ax
+ movw %fs:(0x13), %bx
+ call free_basemem
+99:
+ andw $~( UNDI_FL_INITIALIZED | UNDI_FL_KEEP_ALL ), flags
+#endif /* PXELOADER_KEEP_PXE */
+
+/*****************************************************************************
+ * Unload UNDI driver
+ *****************************************************************************
+ */
+#ifndef PXELOADER_KEEP_UNDI
+unload_undi:
+ /* Issue PXENV_STOP_UNDI */
+ movw $PXENV_STOP_UNDI, %bx
+ call pxe_call
+ jnc 1f
+ call print_pxe_error
+ jmp 99f
+1: /* Free base memory used by UNDI */
+ movw undi_fbms_end, %ax
+ movw undi_fbms_start, %bx
+ call free_basemem
+ /* Clear UNDI_FL_STARTED */
+ andw $~UNDI_FL_STARTED, flags
+99:
+#endif /* PXELOADER_KEEP_UNDI */
+
+/*****************************************************************************
+ * Print remaining free base memory
+ *****************************************************************************
+ */
+print_free_basemem:
+ movw $10f, %si
+ call print_message
+ movw %fs:(0x13), %ax
+ call print_word
+ movw $20f, %si
+ call print_message
+ .section ".prefix.data", "aw", @progbits
+10: .asciz " "
+20: .asciz "kB free base memory after PXE unload\n"
+ .previous
+
+/*****************************************************************************
+ * Exit point
+ *****************************************************************************
+ */
+finished:
+ jmp run_ipxe
+
+/*****************************************************************************
+ * Subroutine: print segment:offset address
+ *
+ * Parameters:
+ * %es:%bx : segment:offset address to print
+ * %ds:di : output buffer (or %di=0 to print to console)
+ * Returns:
+ * %ds:di : next character in output buffer (if applicable)
+ *****************************************************************************
+ */
+print_segoff:
+ /* Preserve registers */
+ pushw %ax
+ /* Print "<segment>:offset" */
+ movw %es, %ax
+ call print_hex_word
+ movb $( ':' ), %al
+ call print_character
+ movw %bx, %ax
+ call print_hex_word
+ /* Restore registers and return */
+ popw %ax
+ ret
+
+/*****************************************************************************
+ * Subroutine: print decimal word
+ *
+ * Parameters:
+ * %ax : word to print
+ * %ds:di : output buffer (or %di=0 to print to console)
+ * Returns:
+ * %ds:di : next character in output buffer (if applicable)
+ *****************************************************************************
+ */
+print_word:
+ /* Preserve registers */
+ pushw %ax
+ pushw %bx
+ pushw %cx
+ pushw %dx
+ /* Build up digit sequence on stack */
+ movw $10, %bx
+ xorw %cx, %cx
+1: xorw %dx, %dx
+ divw %bx, %ax
+ pushw %dx
+ incw %cx
+ testw %ax, %ax
+ jnz 1b
+ /* Print digit sequence */
+1: popw %ax
+ call print_hex_nibble
+ loop 1b
+ /* Restore registers and return */
+ popw %dx
+ popw %cx
+ popw %bx
+ popw %ax
+ ret
+
+/*****************************************************************************
+ * Subroutine: zero 1kB block of base memory
+ *
+ * Parameters:
+ * %bx : block to zero (in kB)
+ * Returns:
+ * Nothing
+ *****************************************************************************
+ */
+zero_kb:
+ /* Preserve registers */
+ pushw %ax
+ pushw %cx
+ pushw %di
+ pushw %es
+ /* Zero block */
+ movw %bx, %ax
+ shlw $6, %ax
+ movw %ax, %es
+ movw $0x400, %cx
+ xorw %di, %di
+ xorw %ax, %ax
+ rep stosb
+ /* Restore registers and return */
+ popw %es
+ popw %di
+ popw %cx
+ popw %ax
+ ret
+
+/*****************************************************************************
+ * Subroutine: free and zero base memory
+ *
+ * Parameters:
+ * %ax : Desired new free base memory counter (in kB)
+ * %bx : Expected current free base memory counter (in kB)
+ * %fs : BIOS data segment (0x40)
+ * Returns:
+ * None
+ *
+ * The base memory from %bx kB to %ax kB is unconditionally zeroed.
+ * It will be freed if and only if the expected current free base
+ * memory counter (%bx) matches the actual current free base memory
+ * counter in 0x40:0x13; if this does not match then the memory will
+ * be leaked.
+ *****************************************************************************
+ */
+free_basemem:
+ /* Zero base memory */
+ pushw %bx
+1: cmpw %bx, %ax
+ je 2f
+ call zero_kb
+ incw %bx
+ jmp 1b
+2: popw %bx
+ /* Free base memory */
+ cmpw %fs:(0x13), %bx /* Update FBMS only if "old" value */
+ jne 1f /* is correct */
+1: movw %ax, %fs:(0x13)
+ ret
+
+/*****************************************************************************
+ * Subroutine: make a PXE API call. Works with either !PXE or PXENV+ API.
+ *
+ * Parameters:
+ * %bx : PXE API call number
+ * %ds:pxe_parameter_structure : Parameters for PXE API call
+ * Returns:
+ * %ax : PXE status code (not exit code)
+ * CF set if %ax is non-zero
+ *****************************************************************************
+ */
+pxe_call:
+ /* Preserve registers */
+ pushw %di
+ pushw %es
+ /* Set up registers for PXENV+ API. %bx already set up */
+ pushw %ds
+ popw %es
+ movw $pxe_parameter_structure, %di
+ /* Set up stack for !PXE API */
+ pushw %es
+ pushw %di
+ pushw %bx
+ /* Make the API call */
+ lcall *entry_segoff
+ /* Reset the stack */
+ addw $6, %sp
+ movw pxe_parameter_structure, %ax
+ clc
+ testw %ax, %ax
+ jz 1f
+ stc
+1: /* Clear direction flag, for the sake of sanity */
+ cld
+ /* Restore registers and return */
+ popw %es
+ popw %di
+ ret
+
+/*****************************************************************************
+ * Subroutine: print PXE API call error message
+ *
+ * Parameters:
+ * %ax : PXE status code
+ * %bx : PXE API call number
+ * Returns:
+ * Nothing
+ *****************************************************************************
+ */
+print_pxe_error:
+ pushw %si
+ movw $10f, %si
+ call print_message
+ xchgw %ax, %bx
+ call print_hex_word
+ movw $20f, %si
+ call print_message
+ xchgw %ax, %bx
+ call print_hex_word
+ movw $30f, %si
+ call print_message
+ popw %si
+ ret
+ .section ".prefix.data", "aw", @progbits
+10: .asciz " UNDI API call "
+20: .asciz " failed: status code "
+30: .asciz "\n"
+ .previous
+
+/*****************************************************************************
+ * PXE data structures
+ *****************************************************************************
+ */
+ .section ".prefix.data"
+
+pxe_esp: .long 0
+pxe_ss: .word 0
+
+pxe_parameter_structure: .fill 64
+
+undi_code_segoff:
+undi_code_size: .word 0
+undi_code_segment: .word 0
+
+undi_data_segoff:
+undi_data_size: .word 0
+undi_data_segment: .word 0
+
+pxe_hacks: .word 0
+
+/* The following fields are part of a struct undi_device */
+
+undi_device:
+
+pxenv_segoff:
+pxenv_offset: .word 0
+pxenv_segment: .word 0
+
+ppxe_segoff:
+ppxe_offset: .word 0
+ppxe_segment: .word 0
+
+entry_segoff:
+entry_offset: .word 0
+entry_segment: .word 0
+
+undi_fbms_start: .word 0
+undi_fbms_end: .word 0
+
+pci_busdevfn: .word UNDI_NO_PCI_BUSDEVFN
+isapnp_csn: .word UNDI_NO_ISAPNP_CSN
+isapnp_read_port: .word UNDI_NO_ISAPNP_READ_PORT
+
+pci_vendor: .word 0
+pci_device: .word 0
+flags:
+ .word ( UNDI_FL_INITIALIZED | UNDI_FL_STARTED | UNDI_FL_KEEP_ALL )
+
+ .equ undi_device_size, ( . - undi_device )
+
+/*****************************************************************************
+ * Run iPXE main code
+ *****************************************************************************
+ */
+ .section ".prefix"
+run_ipxe:
+ /* Install iPXE */
+ call install
+
+ /* Set up real-mode stack */
+ movw %bx, %ss
+ movw $_estack16, %sp
+
+#ifdef PXELOADER_KEEP_UNDI
+ /* Copy our undi_device structure to the preloaded_undi variable */
+ movw %bx, %es
+ movw $preloaded_undi, %di
+ movw $undi_device, %si
+ movw $undi_device_size, %cx
+ rep movsb
+#endif
+
+ /* Retrieve PXE %ss:esp */
+ movw pxe_ss, %di
+ movl pxe_esp, %ebp
+
+ /* Jump to .text16 segment with %ds pointing to .data16 */
+ movw %bx, %ds
+ pushw %ax
+ pushw $1f
+ lret
+ .section ".text16", "ax", @progbits
+1:
+ /* Update the exit hook */
+ movw %cs, ( pxe_exit_hook + 2 )
+
+ /* Run main program */
+ pushl $main
+ pushw %cs
+ call prot_call
+ popl %ecx /* discard */
+
+ /* Uninstall iPXE */
+ call uninstall
+
+ /* Restore PXE stack */
+ movw %di, %ss
+ movl %ebp, %esp
+
+ /* Jump to hook if applicable */
+ ljmpw *pxe_exit_hook
+
+ .section ".data16", "aw", @progbits
+ .globl pxe_exit_hook
+pxe_exit_hook:
+ .word exit_ipxe, 0
+ .previous
+
+exit_ipxe:
+ /* Check PXE stack magic */
+ popl %eax
+ cmpl $STACK_MAGIC, %eax
+ jne 1f
+
+ /* PXE stack OK: return to caller */
+ popw %ds
+ popw %es
+ popw %fs
+ popw %gs
+ popal
+ popfl
+ xorw %ax, %ax /* Return success */
+ lret
+
+1: /* PXE stack corrupt or removed: use INT 18 */
+ int $0x18
+ .previous
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/romprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/romprefix.S
new file mode 100644
index 00000000..dd1dc67d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/romprefix.S
@@ -0,0 +1,830 @@
+/* At entry, the processor is in 16 bit real mode and the code is being
+ * executed from an address it was not linked to. Code must be pic and
+ * 32 bit sensitive until things are fixed up.
+ *
+ * Also be very careful as the stack is at the rear end of the interrupt
+ * table so using a noticeable amount of stack space is a no-no.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#include <config/general.h>
+
+#define PNP_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'n' << 16 ) + ( 'P' << 24 ) )
+#define PMM_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'M' << 16 ) + ( 'M' << 24 ) )
+#define PCI_SIGNATURE ( 'P' + ( 'C' << 8 ) + ( 'I' << 16 ) + ( ' ' << 24 ) )
+#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
+#define PMM_ALLOCATE 0x0000
+#define PMM_FIND 0x0001
+#define PMM_HANDLE_BASE ( ( ( 'F' - 'A' + 1 ) << 26 ) + \
+ ( ( 'E' - 'A' + 1 ) << 21 ) + \
+ ( ( 'N' - 'A' + 1 ) << 16 ) )
+#define PMM_HANDLE_BASE_IMAGE_SOURCE \
+ ( PMM_HANDLE_BASE | 0x00001000 )
+#define PMM_HANDLE_BASE_DECOMPRESS_TO \
+ ( PMM_HANDLE_BASE | 0x00002000 )
+
+/* ROM banner timeout. Based on the configurable BANNER_TIMEOUT in
+ * config.h, but converted to a number of (18Hz) timer ticks, and
+ * doubled to allow for BIOSes that switch video modes immediately
+ * beforehand, so rendering the message almost invisible to the user.
+ */
+#define ROM_BANNER_TIMEOUT ( 2 * ( 18 * BANNER_TIMEOUT ) / 10 )
+
+/* Allow payload to be excluded from ROM size
+ */
+#if ROMPREFIX_EXCLUDE_PAYLOAD
+#define ZINFO_TYPE_ADxB "ADHB"
+#define ZINFO_TYPE_ADxW "ADHW"
+#else
+#define ZINFO_TYPE_ADxB "ADDB"
+#define ZINFO_TYPE_ADxW "ADDW"
+#endif
+
+ .text
+ .code16
+ .arch i386
+ .section ".prefix", "ax", @progbits
+ .globl _rom_start
+_rom_start:
+
+ .org 0x00
+romheader:
+ .word 0xAA55 /* BIOS extension signature */
+romheader_size: .byte 0 /* Size in 512-byte blocks */
+ jmp init /* Initialisation vector */
+checksum:
+ .byte 0
+ .org 0x16
+ .word undiheader
+ .org 0x18
+ .word pciheader
+ .org 0x1a
+ .word pnpheader
+ .size romheader, . - romheader
+
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
+ .ascii ZINFO_TYPE_ADxB
+ .long romheader_size
+ .long 512
+ .long 0
+ .previous
+
+build_id:
+ .long _build_id /* Randomly-generated build ID */
+
+pciheader:
+ .ascii "PCIR" /* Signature */
+ .word pci_vendor_id /* Vendor identification */
+ .word pci_device_id /* Device identification */
+ .word 0x0000 /* Device list pointer */
+ .word pciheader_len /* PCI data structure length */
+ .byte 0x03 /* PCI data structure revision */
+ .byte 0x02, 0x00, 0x00 /* Class code */
+pciheader_image_length:
+ .word 0 /* Image length */
+ .word 0x0001 /* Revision level */
+ .byte 0x00 /* Code type */
+ .byte 0x80 /* Last image indicator */
+pciheader_runtime_length:
+ .word 0 /* Maximum run-time image length */
+ .word 0x0000 /* Configuration utility code header */
+ .word 0x0000 /* DMTF CLP entry point */
+ .equ pciheader_len, . - pciheader
+ .size pciheader, . - pciheader
+
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
+ .ascii ZINFO_TYPE_ADxW
+ .long pciheader_image_length
+ .long 512
+ .long 0
+ .ascii ZINFO_TYPE_ADxW
+ .long pciheader_runtime_length
+ .long 512
+ .long 0
+ .previous
+
+ /* PnP doesn't require any particular alignment, but IBM
+ * BIOSes will scan on 16-byte boundaries rather than using
+ * the offset stored at 0x1a
+ */
+ .align 16
+pnpheader:
+ .ascii "$PnP" /* Signature */
+ .byte 0x01 /* Structure revision */
+ .byte ( pnpheader_len / 16 ) /* Length (in 16 byte increments) */
+ .word 0x0000 /* Offset of next header */
+ .byte 0x00 /* Reserved */
+ .byte 0x00 /* Checksum */
+ .long 0x00000000 /* Device identifier */
+ .word mfgstr /* Manufacturer string */
+ .word prodstr /* Product name */
+ .byte 0x02 /* Device base type code */
+ .byte 0x00 /* Device sub-type code */
+ .byte 0x00 /* Device interface type code */
+ .byte 0xf4 /* Device indicator */
+ .word 0x0000 /* Boot connection vector */
+ .word 0x0000 /* Disconnect vector */
+ .word bev_entry /* Boot execution vector */
+ .word 0x0000 /* Reserved */
+ .word 0x0000 /* Static resource information vector*/
+ .equ pnpheader_len, . - pnpheader
+ .size pnpheader, . - pnpheader
+
+/* Manufacturer string */
+mfgstr:
+ .asciz "http://ipxe.org"
+ .size mfgstr, . - mfgstr
+
+/* Product string
+ *
+ * Defaults to PRODUCT_SHORT_NAME. If the ROM image is writable at
+ * initialisation time, it will be filled in to include the PCI
+ * bus:dev.fn number of the card as well.
+ */
+prodstr:
+ .ascii PRODUCT_SHORT_NAME
+prodstr_separator:
+ .byte 0
+ .ascii "(PCI "
+prodstr_pci_id:
+ .asciz "xx:xx.x)" /* Filled in by init code */
+ .size prodstr, . - prodstr
+
+ .globl undiheader
+ .weak undiloader
+undiheader:
+ .ascii "UNDI" /* Signature */
+ .byte undiheader_len /* Length of structure */
+ .byte 0 /* Checksum */
+ .byte 0 /* Structure revision */
+ .byte 0,1,2 /* PXE version: 2.1.0 */
+ .word undiloader /* Offset to loader routine */
+ .word _data16_memsz /* Stack segment size */
+ .word _data16_memsz /* Data segment size */
+ .word _text16_memsz /* Code segment size */
+ .ascii "PCIR" /* Bus type */
+ .equ undiheader_len, . - undiheader
+ .size undiheader, . - undiheader
+
+/* Initialisation (called once during POST)
+ *
+ * Determine whether or not this is a PnP system via a signature
+ * check. If it is PnP, return to the PnP BIOS indicating that we are
+ * a boot-capable device; the BIOS will call our boot execution vector
+ * if it wants to boot us. If it is not PnP, hook INT 19.
+ */
+init:
+ /* Preserve registers, clear direction flag, set %ds=%cs */
+ pushaw
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+ cld
+ pushw %cs
+ popw %ds
+
+ /* Shuffle some registers around. We need %di available for
+ * the print_xxx functions, and in a register that's
+ * addressable from %es, so shuffle as follows:
+ *
+ * %di (pointer to PnP structure) => %bx
+ * %bx (runtime segment address, for PCI 3.0) => %gs
+ */
+ movw %bx, %gs
+ movw %di, %bx
+
+ /* Store PCI bus:dev.fn address */
+ movw %ax, init_pci_busdevfn
+
+ /* Print message as early as possible */
+ movw $init_message, %si
+ xorw %di, %di
+ call print_message
+ call print_pci_busdevfn
+
+ /* Fill in product name string, if possible */
+ movw $prodstr_pci_id, %di
+ call print_pci_busdevfn
+ movb $( ' ' ), prodstr_separator
+
+ /* Print segment address */
+ movb $( ' ' ), %al
+ xorw %di, %di
+ call print_character
+ movw %cs, %ax
+ call print_hex_word
+
+ /* Check for PCI BIOS version */
+ pushl %ebx
+ pushl %edx
+ pushl %edi
+ stc
+ movw $0xb101, %ax
+ int $0x1a
+ jc no_pci3
+ cmpl $PCI_SIGNATURE, %edx
+ jne no_pci3
+ testb %ah, %ah
+ jnz no_pci3
+ movw $init_message_pci, %si
+ xorw %di, %di
+ call print_message
+ movb %bh, %al
+ call print_hex_nibble
+ movb $( '.' ), %al
+ call print_character
+ movb %bl, %al
+ call print_hex_byte
+ cmpb $3, %bh
+ jb no_pci3
+ /* PCI >=3.0: leave %gs as-is if sane */
+ movw %gs, %ax
+ cmpw $0xa000, %ax /* Insane if %gs < 0xa000 */
+ jb pci3_insane
+ movw %cs, %bx /* Sane if %cs == %gs */
+ cmpw %bx, %ax
+ je 1f
+ movzbw romheader_size, %cx /* Sane if %cs+len <= %gs */
+ shlw $5, %cx
+ addw %cx, %bx
+ cmpw %bx, %ax
+ jae 1f
+ movw %cs, %bx /* Sane if %gs+len <= %cs */
+ addw %cx, %ax
+ cmpw %bx, %ax
+ jbe 1f
+pci3_insane: /* PCI 3.0 with insane %gs value: print error and ignore %gs */
+ movb $( '!' ), %al
+ call print_character
+ movw %gs, %ax
+ call print_hex_word
+no_pci3:
+ /* PCI <3.0: set %gs (runtime segment) = %cs (init-time segment) */
+ pushw %cs
+ popw %gs
+1: popl %edi
+ popl %edx
+ popl %ebx
+
+ /* Check for PnP BIOS. Although %es:di should point to the
+ * PnP BIOS signature on entry, some BIOSes fail to do this.
+ */
+ movw $( 0xf000 - 1 ), %bx
+pnp_scan:
+ incw %bx
+ jz no_pnp
+ movw %bx, %es
+ cmpl $PNP_SIGNATURE, %es:0
+ jne pnp_scan
+ xorw %dx, %dx
+ xorw %si, %si
+ movzbw %es:5, %cx
+1: es lodsb
+ addb %al, %dl
+ loop 1b
+ jnz pnp_scan
+ /* Is PnP: print PnP message */
+ movw $init_message_pnp, %si
+ xorw %di, %di
+ call print_message
+ jmp pnp_done
+no_pnp: /* Not PnP-compliant - hook INT 19 */
+#ifdef NONPNP_HOOK_INT19
+ movw $init_message_int19, %si
+ xorw %di, %di
+ call print_message
+ xorw %ax, %ax
+ movw %ax, %es
+ pushl %es:( 0x19 * 4 )
+ popl orig_int19
+ pushw %gs /* %gs contains runtime %cs */
+ pushw $int19_entry
+ popl %es:( 0x19 * 4 )
+#endif /* NONPNP_HOOK_INT19 */
+pnp_done:
+
+ /* Check for PMM */
+ movw $( 0xe000 - 1 ), %bx
+pmm_scan:
+ incw %bx
+ jz no_pmm
+ movw %bx, %es
+ cmpl $PMM_SIGNATURE, %es:0
+ jne pmm_scan
+ xorw %dx, %dx
+ xorw %si, %si
+ movzbw %es:5, %cx
+1: es lodsb
+ addb %al, %dl
+ loop 1b
+ jnz pmm_scan
+ /* PMM found: print PMM message */
+ movw $init_message_pmm, %si
+ xorw %di, %di
+ call print_message
+ /* We have PMM and so a 1kB stack: preserve whole registers */
+ pushal
+ /* Allocate image source PMM block */
+ movzwl image_source_size, %ecx
+ shll $5, %ecx
+ movl $PMM_HANDLE_BASE_IMAGE_SOURCE, %ebx
+ movw $get_pmm_image_source, %bp
+ call get_pmm
+ movl %esi, image_source
+ jc 1f
+ /* Copy ROM to image source PMM block */
+ pushw %es
+ xorw %ax, %ax
+ movw %ax, %es
+ movl %esi, %edi
+ xorl %esi, %esi
+ movzbl romheader_size, %ecx
+ shll $9, %ecx
+ addr32 rep movsb /* PMM presence implies flat real mode */
+ popw %es
+ /* Shrink ROM */
+ movb shrunk_rom_size, %al
+ movb %al, romheader_size
+1: /* Allocate decompression PMM block. Round up the size to the
+ * nearest 128kB and use the size within the PMM handle; this
+ * allows the same decompression area to be shared between
+ * multiple iPXE ROMs even with differing build IDs
+ */
+ movl $_textdata_memsz_pgh, %ecx
+ addl $0x00001fff, %ecx
+ andl $0xffffe000, %ecx
+ movl %ecx, %ebx
+ shrw $12, %bx
+ orl $PMM_HANDLE_BASE_DECOMPRESS_TO, %ebx
+ movw $get_pmm_decompress_to, %bp
+ call get_pmm
+ movl %esi, decompress_to
+ /* Restore registers */
+ popal
+no_pmm:
+
+ /* Update checksum */
+ xorw %bx, %bx
+ xorw %si, %si
+ movzbw romheader_size, %cx
+ shlw $9, %cx
+1: lodsb
+ addb %al, %bl
+ loop 1b
+ subb %bl, checksum
+
+ /* Copy self to option ROM space. Required for PCI3.0, which
+ * loads us to a temporary location in low memory. Will be a
+ * no-op for lower PCI versions.
+ */
+ movb $( ' ' ), %al
+ xorw %di, %di
+ call print_character
+ movw %gs, %ax
+ call print_hex_word
+ movzbw romheader_size, %cx
+ shlw $9, %cx
+ movw %ax, %es
+ xorw %si, %si
+ xorw %di, %di
+ cs rep movsb
+
+#ifndef VBOX /* Do NOT show the initial Ctrl-B message! */
+ /* Prompt for POST-time shell */
+ movw $init_message_prompt, %si
+ xorw %di, %di
+ call print_message
+ movw $prodstr, %si
+ call print_message
+ movw $init_message_dots, %si
+ call print_message
+ /* Wait for Ctrl-B */
+ movw $0xff02, %bx
+ call wait_for_key
+ /* Clear prompt */
+ pushf
+ xorw %di, %di
+ call print_kill_line
+ movw $init_message_done, %si
+ call print_message
+ popf
+ jnz 2f
+ /* Ctrl-B was pressed: invoke iPXE. The keypress will be
+ * picked up by the initial shell prompt, and we will drop
+ * into a shell.
+ */
+ movl $0xa0000, %ebp /* Inhibit relocation during POST */
+ pushw %cs
+ call exec
+2:
+#else
+ xorw %di, %di
+ movw $init_message_done, %si
+ call print_message
+#endif
+ /* Restore registers */
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popaw
+
+ /* Indicate boot capability to PnP BIOS, if present */
+ movw $0x20, %ax
+ lret
+ .size init, . - init
+
+/* Attempt to find or allocate PMM block
+ *
+ * Parameters:
+ * %ecx : size of block to allocate, in paragraphs
+ * %ebx : PMM handle base
+ * %bp : routine to check acceptability of found blocks
+ * %es:0000 : PMM structure
+ * Returns:
+ * %ebx : PMM handle
+ * %esi : allocated block address, or zero (with CF set) if allocation failed
+ */
+get_pmm:
+ /* Preserve registers */
+ pushl %eax
+ pushw %di
+ movw $( ' ' ), %di
+get_pmm_find:
+ /* Try to find existing block */
+ pushl %ebx /* PMM handle */
+ pushw $PMM_FIND
+ lcall *%es:7
+ addw $6, %sp
+ pushw %dx
+ pushw %ax
+ popl %esi
+ testl %esi, %esi
+ jz get_pmm_allocate
+ /* Block found - check acceptability */
+ call *%bp
+ jnc get_pmm_done
+ /* Block not acceptable - increment handle and retry */
+ incl %ebx
+ jmp get_pmm_find
+get_pmm_allocate:
+ /* Block not found - try to allocate new block */
+ pushw $0x0002 /* Extended memory */
+ pushl %ebx /* PMM handle */
+ pushl %ecx /* Length */
+ pushw $PMM_ALLOCATE
+ lcall *%es:7
+ addw $12, %sp
+ pushw %dx
+ pushw %ax
+ popl %esi
+ movw $( '+' ), %di /* Indicate allocation attempt */
+ testl %esi, %esi
+ jnz get_pmm_done
+ stc
+get_pmm_done:
+ /* Print block address */
+ pushfw
+ movw %di, %ax
+ xorw %di, %di
+ call print_character
+ movl %esi, %eax
+ call print_hex_dword
+ popfw
+ /* Restore registers and return */
+ popw %di
+ popl %eax
+ ret
+ .size get_pmm, . - get_pmm
+
+ /* Check acceptability of image source block */
+get_pmm_image_source:
+ pushw %es
+ xorw %ax, %ax
+ movw %ax, %es
+ movl build_id, %eax
+ addr32 cmpl %es:build_id(%esi), %eax
+ je 1f
+ stc
+1: popw %es
+ ret
+ .size get_pmm_image_source, . - get_pmm_image_source
+
+ /* Check acceptability of decompression block */
+get_pmm_decompress_to:
+ clc
+ ret
+ .size get_pmm_decompress_to, . - get_pmm_decompress_to
+
+/*
+ * Note to hardware vendors:
+ *
+ * If you wish to brand this boot ROM, please do so by defining the
+ * strings PRODUCT_NAME and PRODUCT_SHORT_NAME in config/general.h.
+ *
+ * While nothing in the GPL prevents you from removing all references
+ * to iPXE or http://ipxe.org, we prefer you not to do so.
+ *
+ * If you have an OEM-mandated branding requirement that cannot be
+ * satisfied simply by defining PRODUCT_NAME and PRODUCT_SHORT_NAME,
+ * please contact us.
+ *
+ * [ Including an ASCII NUL in PRODUCT_NAME is considered to be
+ * bypassing the spirit of this request! ]
+ */
+init_message:
+ .ascii "\n"
+ .ascii PRODUCT_NAME
+ .ascii "\n"
+ .asciz "iPXE (http://ipxe.org) "
+ .size init_message, . - init_message
+init_message_pci:
+ .asciz " PCI"
+ .size init_message_pci, . - init_message_pci
+init_message_pnp:
+ .asciz " PnP"
+ .size init_message_pnp, . - init_message_pnp
+init_message_pmm:
+ .asciz " PMM"
+ .size init_message_pmm, . - init_message_pmm
+init_message_int19:
+ .asciz " INT19"
+ .size init_message_int19, . - init_message_int19
+init_message_prompt:
+ .asciz "\nPress Ctrl-B to configure "
+ .size init_message_prompt, . - init_message_prompt
+init_message_dots:
+ .asciz "..."
+ .size init_message_dots, . - init_message_dots
+init_message_done:
+ .asciz "\n\n"
+ .size init_message_done, . - init_message_done
+
+/* PCI bus:dev.fn
+ *
+ */
+init_pci_busdevfn:
+ .word 0xffff
+ .size init_pci_busdevfn, . - init_pci_busdevfn
+
+/* Image source area
+ *
+ * May be either zero (indicating to use option ROM space as source),
+ * or within a PMM-allocated block.
+ */
+ .globl image_source
+image_source:
+ .long 0
+ .size image_source, . - image_source
+
+/* Image source size (in 512-byte sectors)
+ *
+ */
+image_source_size:
+ .word 0
+ .size image_source_size, . - image_source_size
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
+ .ascii "ADDW"
+ .long image_source_size
+ .long 512
+ .long 0
+ .previous
+
+/* Shrunk ROM size (in 512-byte sectors)
+ *
+ */
+shrunk_rom_size:
+ .byte 0
+ .size shrunk_rom_size, . - shrunk_rom_size
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
+ .ascii "ADHB"
+ .long shrunk_rom_size
+ .long 512
+ .long 0
+ .previous
+
+/* Temporary decompression area
+ *
+ * May be either zero (indicating to use default decompression area in
+ * high memory), or within a PMM-allocated block.
+ */
+ .globl decompress_to
+decompress_to:
+ .long 0
+ .size decompress_to, . - decompress_to
+
+/* Boot Execution Vector entry point
+ *
+ * Called by the PnP BIOS when it wants to boot us.
+ */
+bev_entry:
+#ifdef VBOX /* preserve the bp register for the calling BIOS! */
+ pushw %bp
+ pushw %ds
+#endif
+ xorl %ebp, %ebp /* Allow relocation */
+ pushw %cs
+ call exec
+#ifdef VBOX
+ popw %ds
+ popw %bp
+#endif
+ lret
+ .size bev_entry, . - bev_entry
+
+/* INT19 entry point
+ *
+ * Called via the hooked INT 19 if we detected a non-PnP BIOS. We
+ * attempt to return via the original INT 19 vector (if we were able
+ * to store it).
+ */
+int19_entry:
+ pushw %cs
+ popw %ds
+ /* Prompt user to press B to boot */
+ movw $int19_message_prompt, %si
+ xorw %di, %di
+ call print_message
+ movw $prodstr, %si
+ call print_message
+ movw $int19_message_dots, %si
+ call print_message
+ movw $0xdf4e, %bx
+ call wait_for_key
+ pushf
+ xorw %di, %di
+ call print_kill_line
+ movw $int19_message_done, %si
+ call print_message
+ popf
+ jz 1f
+ /* Leave keypress in buffer and start iPXE. The keypress will
+ * cause the usual initial Ctrl-B prompt to be skipped.
+ */
+ xorl %ebp, %ebp /* Allow relocation */
+ pushw %cs
+ call exec
+1: /* Try to call original INT 19 vector */
+ movl %cs:orig_int19, %eax
+ testl %eax, %eax
+ je 2f
+ ljmp *%cs:orig_int19
+2: /* No chained vector: issue INT 18 as a last resort */
+ int $0x18
+ .size int19_entry, . - int19_entry
+orig_int19:
+ .long 0
+ .size orig_int19, . - orig_int19
+
+int19_message_prompt:
+ .asciz "Press N to skip booting from "
+ .size int19_message_prompt, . - int19_message_prompt
+int19_message_dots:
+ .asciz "..."
+ .size int19_message_dots, . - int19_message_dots
+int19_message_done:
+ .asciz "\n\n"
+ .size int19_message_done, . - int19_message_done
+
+/* Execute as a boot device
+ *
+ */
+exec: /* Set %ds = %cs */
+ pushw %cs
+ popw %ds
+
+ /* Print message as soon as possible */
+ movw $prodstr, %si
+ xorw %di, %di
+ call print_message
+ movw $exec_message_pre_install, %si
+ call print_message
+
+ /* Store magic word on BIOS stack and remember BIOS %ss:sp */
+ pushl $STACK_MAGIC
+ movw %ss, %cx
+ movw %sp, %dx
+
+ /* Obtain a reasonably-sized temporary stack */
+ xorw %bx, %bx
+ movw %bx, %ss
+
+#ifndef VBOX /* we are already using this stack, so don't overwrite it! */
+ movw $0x7c00, %sp
+#endif
+
+ /* Install iPXE */
+ call alloc_basemem
+ movl image_source, %esi
+ movl decompress_to, %edi
+ call install_prealloc
+
+ /* Print message indicating successful installation */
+ movw $exec_message_post_install, %si
+ xorw %di, %di
+ call print_message
+
+ /* Set up real-mode stack */
+ movw %bx, %ss
+ movw $_estack16, %sp
+
+ /* Jump to .text16 segment */
+ pushw %ax
+ pushw $1f
+ lret
+ .section ".text16", "awx", @progbits
+1: /* Call main() */
+ pushl $main
+ pushw %cs
+ call prot_call
+ popl %eax /* discard */
+
+ /* Uninstall iPXE */
+ call uninstall
+
+ /* Restore BIOS stack */
+ movw %cx, %ss
+ movw %dx, %sp
+
+ /* Check magic word on BIOS stack */
+ popl %eax
+ cmpl $STACK_MAGIC, %eax
+ jne 1f
+ /* BIOS stack OK: return to caller */
+ lret
+1: /* BIOS stack corrupt: use INT 18 */
+ int $0x18
+ .previous
+
+exec_message_pre_install:
+ .asciz " starting execution..."
+ .size exec_message_pre_install, . - exec_message_pre_install
+exec_message_post_install:
+ .asciz "ok\n"
+ .size exec_message_post_install, . - exec_message_post_install
+
+/* Wait for key press specified by %bl (masked by %bh)
+ *
+ * Used by init and INT19 code when prompting user. If the specified
+ * key is pressed, it is left in the keyboard buffer.
+ *
+ * Returns with ZF set iff specified key is pressed.
+ */
+wait_for_key:
+ /* Preserve registers */
+ pushw %cx
+ pushw %ax
+1: /* Empty the keyboard buffer before waiting for input */
+ movb $0x01, %ah
+ int $0x16
+ jz 2f
+ xorw %ax, %ax
+ int $0x16
+ jmp 1b
+2: /* Wait for a key press */
+ movw $ROM_BANNER_TIMEOUT, %cx
+3: decw %cx
+ js 99f /* Exit with ZF clear */
+ /* Wait for timer tick to be updated */
+ call wait_for_tick
+ /* Check to see if a key was pressed */
+ movb $0x01, %ah
+ int $0x16
+ jz 3b
+ /* Check to see if key was the specified key */
+ andb %bh, %al
+ cmpb %al, %bl
+ je 99f /* Exit with ZF set */
+ /* Not the specified key: remove from buffer and stop waiting */
+ pushfw
+ xorw %ax, %ax
+ int $0x16
+ popfw /* Exit with ZF clear */
+99: /* Restore registers and return */
+ popw %ax
+ popw %cx
+ ret
+ .size wait_for_key, . - wait_for_key
+
+/* Wait for timer tick
+ *
+ * Used by wait_for_key
+ */
+wait_for_tick:
+ pushl %eax
+ pushw %fs
+ movw $0x40, %ax
+ movw %ax, %fs
+ movl %fs:(0x6c), %eax
+1: pushf
+ sti
+ hlt
+ popf
+ cmpl %fs:(0x6c), %eax
+ je 1b
+ popw %fs
+ popl %eax
+ ret
+ .size wait_for_tick, . - wait_for_tick
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/undiloader.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/undiloader.S
new file mode 100644
index 00000000..bb3d469b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/undiloader.S
@@ -0,0 +1,54 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .text
+ .code16
+ .arch i386
+ .section ".prefix", "ax", @progbits
+
+/* UNDI loader
+ *
+ * Called by an external program to load our PXE stack.
+ */
+ .globl undiloader
+undiloader:
+ /* Save registers */
+ pushl %esi
+ pushl %edi
+ pushl %ebp
+ pushw %ds
+ pushw %es
+ pushw %bx
+ /* ROM segment address to %ds */
+ pushw %cs
+ popw %ds
+ /* UNDI loader parameter structure address into %es:%di */
+ movw %sp, %bx
+ movw %ss:18(%bx), %di
+ movw %ss:20(%bx), %es
+ /* Install to specified real-mode addresses */
+ pushw %di
+ movw %es:12(%di), %bx
+ movw %es:14(%di), %ax
+ movl image_source, %esi
+ movl decompress_to, %edi
+ xorl %ebp, %ebp /* Allow relocation */
+ call install_prealloc
+ popw %di
+ /* Call UNDI loader C code */
+ pushl $pxe_loader_call
+ pushw %cs
+ pushw $1f
+ pushw %ax
+ pushw $prot_call
+ lret
+1: popw %bx /* discard */
+ popw %bx /* discard */
+ /* Restore registers and return */
+ popw %bx
+ popw %es
+ popw %ds
+ popl %ebp
+ popl %edi
+ popl %esi
+ lret
+ .size undiloader, . - undiloader
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/unnrv2b.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/unnrv2b.S
new file mode 100644
index 00000000..f5724c13
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/unnrv2b.S
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Originally this code was part of ucl the data compression library
+ * for upx the ``Ultimate Packer of eXecutables''.
+ *
+ * - Converted to gas assembly, and refitted to work with etherboot.
+ * Eric Biederman 20 Aug 2002
+ *
+ * - Structure modified to be a subroutine call rather than an
+ * executable prefix.
+ * Michael Brown 30 Mar 2004
+ *
+ * - Modified to be compilable as either 16-bit or 32-bit code.
+ * Michael Brown 9 Mar 2005
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+/****************************************************************************
+ * This file provides the decompress() and decompress16() functions
+ * which can be called in order to decompress an image compressed with
+ * the nrv2b utility in src/util.
+ *
+ * These functions are designed to be called by the prefix. They are
+ * position-independent code.
+ *
+ * The same basic assembly code is used to compile both
+ * decompress() and decompress16().
+ ****************************************************************************
+ */
+
+ .text
+ .arch i386
+ .section ".prefix.lib", "ax", @progbits
+
+#ifdef CODE16
+/****************************************************************************
+ * decompress16 (real-mode near call, position independent)
+ *
+ * Decompress data in 16-bit mode
+ *
+ * Parameters (passed via registers):
+ * %ds:%esi - Start of compressed input data
+ * %es:%edi - Start of output buffer
+ * Returns:
+ * %ds:%esi - End of compressed input data
+ * %es:%edi - End of decompressed output data
+ * All other registers are preserved
+ *
+ * NOTE: It would be possible to build a smaller version of the
+ * decompression code for -DKEEP_IT_REAL by using
+ * #define REG(x) x
+ * to use 16-bit registers where possible. This would impose limits
+ * that the compressed data size must be in the range [1,65533-%si]
+ * and the uncompressed data size must be in the range [1,65536-%di]
+ * (where %si and %di are the input values for those registers). Note
+ * particularly that the lower limit is 1, not 0, and that the upper
+ * limit on the input (compressed) data really is 65533, since the
+ * algorithm may read up to three bytes beyond the end of the input
+ * data, since it reads dwords.
+ ****************************************************************************
+ */
+
+#define REG(x) e ## x
+#define ADDR32 addr32
+
+ .code16
+ .globl decompress16
+decompress16:
+
+#else /* CODE16 */
+
+/****************************************************************************
+ * decompress (32-bit protected-mode near call, position independent)
+ *
+ * Parameters (passed via registers):
+ * %ds:%esi - Start of compressed input data
+ * %es:%edi - Start of output buffer
+ * Returns:
+ * %ds:%esi - End of compressed input data
+ * %es:%edi - End of decompressed output data
+ * All other registers are preserved
+ ****************************************************************************
+ */
+
+#define REG(x) e ## x
+#define ADDR32
+
+ .code32
+ .globl decompress
+decompress:
+
+#endif /* CODE16 */
+
+#define xAX REG(ax)
+#define xCX REG(cx)
+#define xBP REG(bp)
+#define xSI REG(si)
+#define xDI REG(di)
+
+ /* Save registers */
+ push %xAX
+ pushl %ebx
+ push %xCX
+ push %xBP
+ /* Do the decompression */
+ cld
+ xor %xBP, %xBP
+ dec %xBP /* last_m_off = -1 */
+ jmp dcl1_n2b
+
+decompr_literals_n2b:
+ ADDR32 movsb
+decompr_loop_n2b:
+ addl %ebx, %ebx
+ jnz dcl2_n2b
+dcl1_n2b:
+ call getbit32
+dcl2_n2b:
+ jc decompr_literals_n2b
+ xor %xAX, %xAX
+ inc %xAX /* m_off = 1 */
+loop1_n2b:
+ call getbit1
+ adc %xAX, %xAX /* m_off = m_off*2 + getbit() */
+ call getbit1
+ jnc loop1_n2b /* while(!getbit()) */
+ sub $3, %xAX
+ jb decompr_ebpeax_n2b /* if (m_off == 2) goto decompr_ebpeax_n2b ? */
+ shl $8, %xAX
+ ADDR32 movb (%xSI), %al /* m_off = (m_off - 3)*256 + src[ilen++] */
+ inc %xSI
+ xor $-1, %xAX
+ jz decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */
+ mov %xAX, %xBP /* last_m_off = m_off ?*/
+decompr_ebpeax_n2b:
+ xor %xCX, %xCX
+ call getbit1
+ adc %xCX, %xCX /* m_len = getbit() */
+ call getbit1
+ adc %xCX, %xCX /* m_len = m_len*2 + getbit()) */
+ jnz decompr_got_mlen_n2b /* if (m_len == 0) goto decompr_got_mlen_n2b */
+ inc %xCX /* m_len++ */
+loop2_n2b:
+ call getbit1
+ adc %xCX, %xCX /* m_len = m_len*2 + getbit() */
+ call getbit1
+ jnc loop2_n2b /* while(!getbit()) */
+ inc %xCX
+ inc %xCX /* m_len += 2 */
+decompr_got_mlen_n2b:
+ cmp $-0xd00, %xBP
+ adc $1, %xCX /* m_len = m_len + 1 + (last_m_off > 0xd00) */
+ push %xSI
+ ADDR32 lea (%xBP,%xDI), %xSI /* m_pos = dst + olen + -m_off */
+ rep
+ es ADDR32 movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */
+ pop %xSI
+ jmp decompr_loop_n2b
+
+
+getbit1:
+ addl %ebx, %ebx
+ jnz 1f
+getbit32:
+ ADDR32 movl (%xSI), %ebx
+ sub $-4, %xSI /* sets carry flag */
+ adcl %ebx, %ebx
+1:
+ ret
+
+decompr_end_n2b:
+ /* Restore registers and return */
+ pop %xBP
+ pop %xCX
+ popl %ebx
+ pop %xAX
+ ret
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/unnrv2b16.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/unnrv2b16.S
new file mode 100644
index 00000000..b24c2846
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/unnrv2b16.S
@@ -0,0 +1,9 @@
+/*
+ * 16-bit version of the decompressor
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#define CODE16
+#include "unnrv2b.S"
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/usbdisk.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/usbdisk.S
new file mode 100644
index 00000000..fa7d1956
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/prefix/usbdisk.S
@@ -0,0 +1,23 @@
+ .text
+ .arch i386
+ .section ".prefix", "awx", @progbits
+ .code16
+ .org 0
+
+#include "mbr.S"
+
+/* Partition table: ZIP-compatible partition 4, 64 heads, 32 sectors/track */
+ .org 446
+ .space 16
+ .space 16
+ .space 16
+ .byte 0x80, 0x01, 0x01, 0x00
+ .byte 0xeb, 0x3f, 0x20, 0x01
+ .long 0x00000020
+ .long 0x00000fe0
+
+ .org 510
+ .byte 0x55, 0xaa
+
+/* Skip to start of partition */
+ .org 32 * 512
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/scripts/i386-kir.lds b/src/VBox/Devices/PC/ipxe/src/arch/i386/scripts/i386-kir.lds
new file mode 100644
index 00000000..338d6ee8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/scripts/i386-kir.lds
@@ -0,0 +1,200 @@
+/* -*- sh -*- */
+
+/*
+ * Linker script for i386 images
+ *
+ */
+
+OUTPUT_FORMAT ( "elf32-i386", "elf32-i386", "elf32-i386" )
+OUTPUT_ARCH ( i386 )
+
+SECTIONS {
+
+ /* All sections in the resulting file have consecutive load
+ * addresses, but may have individual link addresses depending on
+ * the memory model being used.
+ *
+ * The linker symbols _prefix_link_addr, load_addr, and
+ * _max_align may be specified explicitly. If not specified, they
+ * will default to:
+ *
+ * _prefix_link_addr = 0
+ * _load_addr = 0
+ * _max_align = 16
+ *
+ * We guarantee alignment of virtual addresses to any alignment
+ * specified by the constituent object files (e.g. via
+ * __attribute__((aligned(x)))). Load addresses are guaranteed
+ * only up to _max_align. Provided that all loader and relocation
+ * code honours _max_align, this means that physical addresses are
+ * also guaranteed up to _max_align.
+ *
+ * Note that when using -DKEEP_IT_REAL, the UNDI segments are only
+ * guaranteed to be loaded on a paragraph boundary (i.e. 16-byte
+ * alignment). Using _max_align>16 will therefore not guarantee
+ * >16-byte alignment of physical addresses when -DKEEP_IT_REAL is
+ * used (though virtual addresses will still be fully aligned).
+ *
+ */
+
+ /*
+ * The prefix
+ */
+
+ _prefix_link_addr = DEFINED ( _prefix_link_addr ) ? _prefix_link_addr : 0;
+ . = _prefix_link_addr;
+ _prefix = .;
+
+ .prefix : AT ( _prefix_load_offset + __prefix ) {
+ __prefix = .;
+ _entry = .;
+ *(.prefix)
+ *(.prefix.*)
+ _eprefix_progbits = .;
+ }
+
+ _eprefix = .;
+
+ /*
+ * The 16-bit sections
+ */
+
+ _text16_link_addr = 0;
+ . = _text16_link_addr;
+ _text16 = .;
+
+ . += 1; /* Prevent NULL being valid */
+
+ .text16 : AT ( _text16_load_offset + __text16 ) {
+ __text16 = .;
+ KEEP(*(.text.null_trap))
+ KEEP(*(.text.null_trap.*))
+ *(.text16)
+ *(.text16.*)
+ *(.text)
+ *(.text.*)
+ _etext16_progbits = .;
+ } = 0x9090
+
+ _etext16 = .;
+
+ _data16_link_addr = 0;
+ . = _data16_link_addr;
+ _data16 = .;
+
+ . += 1; /* Prevent NULL being valid */
+
+ .rodata16 : AT ( _data16_load_offset + __rodata16 ) {
+ __rodata16 = .;
+ *(.rodata16)
+ *(.rodata16.*)
+ *(.rodata)
+ *(.rodata.*)
+ }
+ .data16 : AT ( _data16_load_offset + __data16 ) {
+ __data16 = .;
+ *(.data16)
+ *(.data16.*)
+ *(.data)
+ *(.data.*)
+ KEEP(*(SORT(.tbl.*))) /* Various tables. See include/tables.h */
+ _edata16_progbits = .;
+ }
+ .bss16 : AT ( _data16_load_offset + __bss16 ) {
+ __bss16 = .;
+ _bss16 = .;
+ *(.bss16)
+ *(.bss16.*)
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ _ebss16 = .;
+ }
+ .stack16 : AT ( _data16_load_offset + __stack16 ) {
+ __stack16 = .;
+ *(.stack16)
+ *(.stack16.*)
+ *(.stack)
+ *(.stack.*)
+ }
+
+ _edata16 = .;
+
+ _end = .;
+
+ /*
+ * Dispose of the comment and note sections to make the link map
+ * easier to read
+ */
+
+ /DISCARD/ : {
+ *(.comment)
+ *(.comment.*)
+ *(.note)
+ *(.note.*)
+ *(.discard)
+ *(.discard.*)
+ }
+
+ /*
+ * Load address calculations. The slightly obscure nature of the
+ * calculations is because ALIGN(x) can only operate on the
+ * location counter.
+ */
+
+ _max_align = DEFINED ( _max_align ) ? _max_align : 16;
+ _load_addr = DEFINED ( _load_addr ) ? _load_addr : 0;
+
+ . = _load_addr;
+
+ . -= _prefix_link_addr;
+ _prefix_load_offset = ALIGN ( _max_align );
+ _prefix_load_addr = _prefix_link_addr + _prefix_load_offset;
+ _prefix_size = _eprefix - _prefix;
+ _prefix_progbits_size = _eprefix_progbits - _prefix;
+ . = _prefix_load_addr + _prefix_progbits_size;
+
+ . -= _text16_link_addr;
+ _text16_load_offset = ALIGN ( _max_align );
+ _text16_load_addr = _text16_link_addr + _text16_load_offset;
+ _text16_size = _etext16 - _text16;
+ _text16_progbits_size = _etext16_progbits - _text16;
+ . = _text16_load_addr + _text16_progbits_size;
+
+ . -= _data16_link_addr;
+ _data16_load_offset = ALIGN ( _max_align );
+ _data16_load_addr = _data16_link_addr + _data16_load_offset;
+ _data16_size = _edata16 - _data16;
+ _data16_progbits_size = _edata16_progbits - _data16;
+ . = _data16_load_addr + _data16_progbits_size;
+
+ . = ALIGN ( _max_align );
+
+ _load_size = . - _load_addr;
+
+ /*
+ * Alignment checks. ALIGN() can only operate on the location
+ * counter, so we set the location counter to each value we want
+ * to check.
+ */
+
+ . = _prefix_load_addr - _prefix_link_addr;
+ _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
+ "_prefix is badly aligned" );
+
+ . = _text16_load_addr - _text16_link_addr;
+ _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
+ "_text16 is badly aligned" );
+
+ . = _data16_load_addr - _data16_link_addr;
+ _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
+ "_data16 is badly aligned" );
+
+ /*
+ * Values calculated to save code from doing it
+ */
+ _text16_size_pgh = ( ( _text16_size + 15 ) / 16 );
+ _data16_size_pgh = ( ( _data16_size + 15 ) / 16 );
+ _load_size_pgh = ( ( _load_size + 15 ) / 16 );
+ _load_size_sect = ( ( _load_size + 511 ) / 512 );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/scripts/i386.lds b/src/VBox/Devices/PC/ipxe/src/arch/i386/scripts/i386.lds
new file mode 100644
index 00000000..763b80d6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/scripts/i386.lds
@@ -0,0 +1,220 @@
+/* -*- sh -*- */
+
+/*
+ * Linker script for i386 images
+ *
+ */
+
+SECTIONS {
+
+ /* Each section starts at a virtual address of zero.
+ *
+ * We guarantee alignment of virtual addresses to any alignment
+ * specified by the constituent object files (e.g. via
+ * __attribute__((aligned(x)))). Load addresses are guaranteed
+ * only up to _max_align. Provided that all loader and relocation
+ * code honours _max_align, this means that physical addresses are
+ * also guaranteed up to _max_align.
+ *
+ * Note that when using -DKEEP_IT_REAL, the UNDI segments are only
+ * guaranteed to be loaded on a paragraph boundary (i.e. 16-byte
+ * alignment). Using _max_align>16 will therefore not guarantee
+ * >16-byte alignment of physical addresses when -DKEEP_IT_REAL is
+ * used (though virtual addresses will still be fully aligned).
+ *
+ */
+
+ PROVIDE ( _max_align = 16 );
+
+ /*
+ * The prefix
+ *
+ */
+
+ .prefix 0x0 : AT ( _prefix_lma ) {
+ _prefix = .;
+ *(.prefix)
+ *(.prefix.*)
+ _mprefix = .;
+ } .bss.prefix (NOLOAD) : AT ( _end_lma ) {
+ _eprefix = .;
+ }
+ _prefix_filesz = ABSOLUTE ( _mprefix ) - ABSOLUTE ( _prefix );
+ _prefix_memsz = ABSOLUTE ( _eprefix ) - ABSOLUTE ( _prefix );
+
+ /*
+ * The 16-bit (real-mode) code section
+ *
+ */
+
+ .text16.early 0x0 : AT ( _text16_early_lma ) {
+ _text16 = .;
+ KEEP(*(.text16.null))
+ KEEP(*(.text16.null.*))
+ . += 1; /* Prevent NULL being valid */
+ *(.text16.early)
+ *(.text16.early.*)
+ _etext16_early = .;
+ } .text16.late ALIGN ( _max_align ) : AT ( _text16_late_lma ) {
+ _text16_late = .;
+ *(.text16)
+ *(.text16.*)
+ _mtext16 = .;
+ } .bss.text16 (NOLOAD) : AT ( _end_lma ) {
+ _etext16 = .;
+ }
+ _text16_early_filesz = ABSOLUTE ( _etext16_early ) - ABSOLUTE ( _text16 );
+ _text16_early_memsz = ABSOLUTE ( _etext16_early ) - ABSOLUTE ( _text16 );
+ _text16_late_filesz = ABSOLUTE ( _mtext16 ) - ABSOLUTE ( _text16_late );
+ _text16_late_memsz = ABSOLUTE ( _etext16 ) - ABSOLUTE ( _text16_late );
+ _text16_memsz = ABSOLUTE ( _etext16 ) - ABSOLUTE ( _text16 );
+
+ /*
+ * The 16-bit (real-mode) data section
+ *
+ */
+
+ .data16 0x0 : AT ( _data16_lma ) {
+ _data16 = .;
+ . += 1; /* Prevent NULL being valid */
+ *(.rodata16)
+ *(.rodata16.*)
+ *(.data16)
+ *(.data16.*)
+ _mdata16 = .;
+ } .bss.data16 (NOLOAD) : AT ( _end_lma ) {
+ *(.bss16)
+ *(.bss16.*)
+ *(.stack16)
+ *(.stack16.*)
+ _edata16 = .;
+ }
+ _data16_filesz = ABSOLUTE ( _mdata16 ) - ABSOLUTE ( _data16 );
+ _data16_memsz = ABSOLUTE ( _edata16 ) - ABSOLUTE ( _data16 );
+
+ /*
+ * The 32-bit sections
+ *
+ */
+
+ .textdata 0x0 : AT ( _textdata_lma ) {
+ _textdata = .;
+ KEEP(*(.text.null_trap))
+ KEEP(*(.text.null_trap.*))
+ . += 1; /* Prevent NULL being valid */
+ *(.text)
+ *(.text.*)
+ *(.rodata)
+ *(.rodata.*)
+ *(.data)
+ *(.data.*)
+ KEEP(*(SORT(.tbl.*))) /* Various tables. See include/tables.h */
+ _mtextdata = .;
+ } .bss.textdata (NOLOAD) : AT ( _end_lma ) {
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ *(.stack)
+ *(.stack.*)
+ _etextdata = .;
+ }
+ _textdata_filesz = ABSOLUTE ( _mtextdata ) - ABSOLUTE ( _textdata );
+ _textdata_memsz = ABSOLUTE ( _etextdata ) - ABSOLUTE ( _textdata );
+
+ /*
+ * Compressor information block
+ *
+ */
+
+ .zinfo 0x0 : AT ( _zinfo_lma ) {
+ _zinfo = .;
+ KEEP(*(.zinfo))
+ KEEP(*(.zinfo.*))
+ _mzinfo = .;
+ } .bss.zinfo (NOLOAD) : AT ( _end_lma ) {
+ _ezinfo = .;
+ }
+ _zinfo_filesz = ABSOLUTE ( _mzinfo ) - ABSOLUTE ( _zinfo );
+ _zinfo_memsz = ABSOLUTE ( _ezinfo ) - ABSOLUTE ( _zinfo );
+
+ /*
+ * Weak symbols that need zero values if not otherwise defined
+ *
+ */
+
+ .weak 0x0 : AT ( _end_lma ) {
+ _weak = .;
+ *(.weak)
+ *(.weak.*)
+ _eweak = .;
+ }
+ _assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
+
+ /*
+ * Dispose of the comment and note sections to make the link map
+ * easier to read
+ *
+ */
+
+ /DISCARD/ : {
+ *(.comment)
+ *(.comment.*)
+ *(.note)
+ *(.note.*)
+ *(.eh_frame)
+ *(.eh_frame.*)
+ *(.rel)
+ *(.rel.*)
+ *(.einfo)
+ *(.einfo.*)
+ *(.discard)
+ *(.discard.*)
+ }
+
+ /*
+ * Load address calculations. In older versions of ld, ALIGN()
+ * can operate only on the location counter, so we use that.
+ *
+ */
+
+ . = 0;
+
+ . = ALIGN ( _max_align );
+ _prefix_lma = .;
+ . += _prefix_filesz;
+
+ . = ALIGN ( _max_align );
+ _text16_early_lma = .;
+ . += _text16_early_filesz;
+
+ . = ALIGN ( _max_align );
+ _payload_lma = .;
+ _text16_late_lma = .;
+ . += _text16_late_filesz;
+
+ . = ALIGN ( _max_align );
+ _data16_lma = .;
+ . += _data16_filesz;
+
+ . = ALIGN ( _max_align );
+ _textdata_lma = .;
+ . += _textdata_filesz;
+
+ _filesz = .; /* Do not include zinfo block in file size */
+
+ . = ALIGN ( _max_align );
+ _zinfo_lma = .;
+ . += _zinfo_filesz;
+
+ . = ALIGN ( _max_align );
+ _end_lma = .;
+
+ /*
+ * Values calculated to save code from doing it
+ *
+ */
+ _text16_memsz_pgh = ( ( _text16_memsz + 15 ) / 16 );
+ _data16_memsz_pgh = ( ( _data16_memsz + 15 ) / 16 );
+ _textdata_memsz_pgh = ( ( _textdata_memsz + 15 ) / 16 );
+ _textdata_memsz_kb = ( ( _textdata_memsz + 1023 ) / 1024 );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/scripts/linux.lds b/src/VBox/Devices/PC/ipxe/src/arch/i386/scripts/linux.lds
new file mode 100644
index 00000000..64c9b97f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/scripts/linux.lds
@@ -0,0 +1,102 @@
+/* -*- sh -*- */
+
+/*
+ * Linker script for i386 Linux images
+ *
+ */
+
+OUTPUT_FORMAT ( "elf32-i386", "elf32-i386", "elf32-i386" )
+OUTPUT_ARCH ( i386 )
+
+SECTIONS {
+ _max_align = 32;
+
+ . = 0x08048000;
+
+ /*
+ * The text section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .text : {
+ _text = .;
+ *(.text)
+ *(.text.*)
+ _etext = .;
+ }
+
+ /*
+ * The rodata section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .rodata : {
+ _rodata = .;
+ *(.rodata)
+ *(.rodata.*)
+ _erodata = .;
+ }
+
+ /*
+ * The data section
+ *
+ * Adjust the address for the data segment. We want to adjust up to
+ * the same address within the page on the next page up.
+ */
+
+ . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1));
+ . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+ .data : {
+ _data = .;
+ *(.data)
+ *(.data.*)
+ KEEP(*(SORT(.tbl.*)))
+ _edata = .;
+ }
+
+ /*
+ * The bss section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .bss : {
+ _bss = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ _ebss = .;
+ }
+
+ /*
+ * Weak symbols that need zero values if not otherwise defined
+ *
+ */
+
+ .weak 0x0 : {
+ _weak = .;
+ *(.weak)
+ *(.weak.*)
+ _eweak = .;
+ }
+ _assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
+
+ /*
+ * Dispose of the comment and note sections to make the link map
+ * easier to read
+ *
+ */
+
+ /DISCARD/ : {
+ *(.comment)
+ *(.comment.*)
+ *(.note)
+ *(.note.*)
+ *(.rel)
+ *(.rel.*)
+ *(.discard)
+ *(.discard.*)
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/liba20.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/liba20.S
new file mode 100644
index 00000000..a60f1a54
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/liba20.S
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+ .arch i386
+
+/****************************************************************************
+ * test_a20_short, test_a20_long
+ *
+ * Check to see if A20 line is enabled
+ *
+ * Parameters:
+ * none
+ * Returns:
+ * CF set if A20 line is not enabled
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+#define TEST_A20_SHORT_MAX_RETRIES 0x20
+#define TEST_A20_LONG_MAX_RETRIES 0x200000
+ .section ".text16.early", "awx", @progbits
+ .code16
+test_a20_short:
+ pushl %ecx
+ movl $TEST_A20_SHORT_MAX_RETRIES, %ecx
+ jmp 1f
+ .size test_a20_short, . - test_a20_short
+test_a20_long:
+ pushl %ecx
+ movl $TEST_A20_LONG_MAX_RETRIES, %ecx
+1: pushw %ax
+ pushw %ds
+ pushw %es
+
+ /* Set up segment registers for access across the 1MB boundary */
+ xorw %ax, %ax
+ movw %ax, %ds
+ decw %ax
+ movw %ax, %es
+
+2: /* Modify and check test pattern; succeed if we see a difference */
+ pushfw
+ cli
+ xchgw %ds:0, %cx
+ movw %es:0x10, %ax
+ xchgw %ds:0, %cx
+ popfw
+ cmpw %ax, %cx
+ clc
+ jnz 99f
+
+ /* Delay and retry */
+ outb %al, $0x80
+ addr32 loop 2b
+ stc
+
+99: /* Restore registers and return */
+ popw %es
+ popw %ds
+ popw %ax
+ popl %ecx
+ ret
+ .size test_a20_long, . - test_a20_long
+
+/****************************************************************************
+ * enable_a20_bios
+ *
+ * Try enabling A20 line via BIOS
+ *
+ * Parameters:
+ * none
+ * Returns:
+ * CF set if A20 line is not enabled
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ .section ".text16.early", "awx", @progbits
+ .code16
+enable_a20_bios:
+
+ /* Preserve registers. Be very paranoid, since some BIOSes
+ * are reported to clobber %ebx
+ */
+ pushal
+
+ /* Attempt INT 15,2401 */
+ movw $0x2401, %ax
+ int $0x15
+ jc 99f
+
+ /* Check that success was really successful */
+ call test_a20_short
+
+99: /* Restore registers and return */
+ popal
+ ret
+ .size enable_a20_bios, . - enable_a20_bios
+
+/****************************************************************************
+ * enable_a20_kbc
+ *
+ * Try enabling A20 line via keyboard controller
+ *
+ * Parameters:
+ * none
+ * Returns:
+ * CF set if A20 line is not enabled
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+#define KC_RDWR 0x60
+#define KC_RDWR_SET_A20 0xdf
+#define KC_CMD 0x64
+#define KC_CMD_WOUT 0xd1
+#define KC_CMD_NULL 0xff
+#define KC_STATUS 0x64
+#define KC_STATUS_OBUF_FULL 0x01
+#define KC_STATUS_IBUF_FULL 0x02
+#define KC_MAX_RETRIES 100000
+ .section ".text16.early", "awx", @progbits
+ .code16
+enable_a20_kbc:
+ /* Preserve registers */
+ pushw %ax
+
+ /* Try keyboard controller */
+ call empty_kbc
+ movb $KC_CMD_WOUT, %al
+ outb %al, $KC_CMD
+ call empty_kbc
+ movb $KC_RDWR_SET_A20, %al
+ outb %al, $KC_RDWR
+ call empty_kbc
+ movb $KC_CMD_NULL, %al
+ outb %al, $KC_CMD
+ call empty_kbc
+
+ /* Check to see if it worked */
+ call test_a20_long
+
+ /* Restore registers and return */
+ popw %ax
+ ret
+ .size enable_a20_kbc, . - enable_a20_kbc
+
+ .section ".text16.early", "awx", @progbits
+ .code16
+empty_kbc:
+ /* Preserve registers */
+ pushl %ecx
+ pushw %ax
+
+ /* Wait for KBC to become empty */
+ movl $KC_MAX_RETRIES, %ecx
+1: outb %al, $0x80
+ inb $KC_STATUS, %al
+ testb $( KC_STATUS_OBUF_FULL | KC_STATUS_IBUF_FULL ), %al
+ jz 99f
+ testb $KC_STATUS_OBUF_FULL, %al
+ jz 2f
+ outb %al, $0x80
+ inb $KC_RDWR, %al
+2: addr32 loop 1b
+
+99: /* Restore registers and return */
+ popw %ax
+ popl %ecx
+ ret
+ .size empty_kbc, . - empty_kbc
+
+/****************************************************************************
+ * enable_a20_fast
+ *
+ * Try enabling A20 line via "Fast Gate A20"
+ *
+ * Parameters:
+ * none
+ * Returns:
+ * CF set if A20 line is not enabled
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+#define SCP_A 0x92
+ .section ".text16.early", "awx", @progbits
+ .code16
+enable_a20_fast:
+ /* Preserve registers */
+ pushw %ax
+
+ /* Try "Fast Gate A20" */
+ inb $SCP_A, %al
+ orb $0x02, %al
+ andb $~0x01, %al
+ outb %al, $SCP_A
+
+ /* Check to see if it worked */
+ call test_a20_long
+
+ /* Restore registers and return */
+ popw %ax
+ ret
+ .size enable_a20_fast, . - enable_a20_fast
+
+/****************************************************************************
+ * enable_a20
+ *
+ * Try enabling A20 line via any available method
+ *
+ * Parameters:
+ * none
+ * Returns:
+ * CF set if A20 line is not enabled
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+#define ENABLE_A20_RETRIES 255
+ .section ".text16.early", "awx", @progbits
+ .code16
+ .globl enable_a20
+enable_a20:
+ /* Preserve registers */
+ pushl %ecx
+ pushw %ax
+
+ /* Check to see if A20 is already enabled */
+ call test_a20_short
+ jnc 99f
+
+ /* Use known working method, if we have one */
+ movw %cs:enable_a20_method, %ax
+ testw %ax, %ax
+ jz 1f
+ call *%ax
+ jmp 99f
+1:
+ /* Try all methods in turn until one works */
+ movl $ENABLE_A20_RETRIES, %ecx
+2: movw $enable_a20_bios, %ax
+ movw %ax, %cs:enable_a20_method
+ call *%ax
+ jnc 99f
+ movw $enable_a20_kbc, %ax
+ movw %ax, %cs:enable_a20_method
+ call *%ax
+ jnc 99f
+ movw $enable_a20_fast, %ax
+ movw %ax, %cs:enable_a20_method
+ call *%ax
+ jnc 99f
+ addr32 loop 2b
+ /* Failure; exit with carry set */
+ movw $0, %cs:enable_a20_method
+ stc
+
+99: /* Restore registers and return */
+ popw %ax
+ popl %ecx
+ ret
+
+ .section ".text16.early.data", "aw", @progbits
+ .align 2
+enable_a20_method:
+ .word 0
+ .size enable_a20_method, . - enable_a20_method
+
+/****************************************************************************
+ * access_highmem (real mode far call)
+ *
+ * Open up access to high memory with A20 enabled
+ *
+ * Parameters:
+ * none
+ * Returns:
+ * CF set if high memory could not be accessed
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ .section ".text16.early", "awx", @progbits
+ .code16
+ .globl access_highmem
+access_highmem:
+ /* Enable A20 line */
+ call enable_a20
+ lret
+ .size access_highmem, . - access_highmem
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/libkir.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/libkir.S
new file mode 100644
index 00000000..1176fcce
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/libkir.S
@@ -0,0 +1,256 @@
+/*
+ * libkir: a transition library for -DKEEP_IT_REAL
+ *
+ * Michael Brown <mbrown@fensystems.co.uk>
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+/****************************************************************************
+ * This file defines libkir: an interface between external and
+ * internal environments when -DKEEP_IT_REAL is used, so that both
+ * internal and external environments are in real mode. It deals with
+ * switching data segments and the stack. It provides the following
+ * functions:
+ *
+ * ext_to_kir & switch between external and internal (kir)
+ * kir_to_ext environments, preserving all non-segment
+ * registers
+ *
+ * kir_call issue a call to an internal routine from external
+ * code
+ *
+ * libkir is written to avoid assuming that segments are anything
+ * other than opaque data types, and also avoids assuming that the
+ * stack pointer is 16-bit. This should enable it to run just as well
+ * in 16:16 or 16:32 protected mode as in real mode.
+ ****************************************************************************
+ */
+
+/* Breakpoint for when debugging under bochs */
+#define BOCHSBP xchgw %bx, %bx
+
+ .text
+ .arch i386
+ .section ".text16", "awx", @progbits
+ .code16
+
+/****************************************************************************
+ * init_libkir (real-mode or 16:xx protected-mode far call)
+ *
+ * Initialise libkir ready for transitions to the kir environment
+ *
+ * Parameters:
+ * %cs : .text16 segment
+ * %ds : .data16 segment
+ ****************************************************************************
+ */
+ .globl init_libkir
+init_libkir:
+ /* Record segment registers */
+ pushw %ds
+ popw %cs:kir_ds
+ lret
+
+/****************************************************************************
+ * ext_to_kir (real-mode or 16:xx protected-mode near call)
+ *
+ * Switch from external stack and segment registers to internal stack
+ * and segment registers. %ss:sp is restored from the saved kir_ds
+ * and kir_sp. %ds, %es, %fs and %gs are all restored from the saved
+ * kir_ds. All other registers are preserved.
+ *
+ * %cs:0000 must point to the start of the runtime image code segment
+ * on entry.
+ *
+ * Parameters: none
+ ****************************************************************************
+ */
+
+ .globl ext_to_kir
+ext_to_kir:
+ /* Record external segment registers */
+ movw %ds, %cs:ext_ds
+ pushw %cs
+ popw %ds /* Set %ds = %cs for easier access to variables */
+ movw %es, %ds:ext_es
+ movw %fs, %ds:ext_fs
+ movw %gs, %ds:ext_fs
+
+ /* Preserve registers */
+ movw %ax, %ds:save_ax
+
+ /* Extract near return address from stack */
+ popw %ds:save_retaddr
+
+ /* Record external %ss:esp */
+ movw %ss, %ds:ext_ss
+ movl %esp, %ds:ext_esp
+
+ /* Load internal segment registers and stack pointer */
+ movw %ds:kir_ds, %ax
+ movw %ax, %ss
+ movzwl %ds:kir_sp, %esp
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+1:
+
+ /* Place return address on new stack */
+ pushw %cs:save_retaddr
+
+ /* Restore registers and return */
+ movw %cs:save_ax, %ax
+ ret
+
+/****************************************************************************
+ * kir_to_ext (real-mode or 16:xx protected-mode near call)
+ *
+ * Switch from internal stack and segment registers to external stack
+ * and segment registers. %ss:%esp is restored from the saved ext_ss
+ * and ext_esp. Other segment registers are restored from the
+ * corresponding locations. All other registers are preserved.
+ *
+ * Note that it is actually %ss that is recorded as kir_ds, on the
+ * assumption that %ss == %ds when kir_to_ext is called.
+ *
+ * Parameters: none
+ ****************************************************************************
+ */
+
+ .globl kir_to_ext
+kir_to_ext:
+ /* Record near return address */
+ pushw %cs
+ popw %ds /* Set %ds = %cs for easier access to variables */
+ popw %ds:save_retaddr
+
+ /* Record internal segment registers and %sp */
+ movw %ss, %ds:kir_ds
+ movw %sp, %ds:kir_sp
+
+ /* Load external segment registers and stack pointer */
+ movw %ds:ext_ss, %ss
+ movl %ds:ext_esp, %esp
+ movw %ds:ext_gs, %gs
+ movw %ds:ext_fs, %fs
+ movw %ds:ext_es, %es
+ movw %ds:ext_ds, %ds
+
+ /* Return */
+ pushw %cs:save_retaddr
+ ret
+
+/****************************************************************************
+ * kir_call (real-mode or 16:xx protected-mode far call)
+ *
+ * Call a specific C function in the internal code. The prototype of
+ * the C function must be
+ * void function ( struct i386_all_resg *ix86 );
+ * ix86 will point to a struct containing the real-mode registers
+ * at entry to kir_call.
+ *
+ * All registers will be preserved across kir_call(), unless the C
+ * function explicitly overwrites values in ix86. Interrupt status
+ * will also be preserved.
+ *
+ * Parameters:
+ * function : (32-bit) virtual address of C function to call
+ *
+ * Example usage:
+ * pushl $pxe_api_call
+ * lcall $UNDI_CS, $kir_call
+ * addw $4, %sp
+ * to call in to the C function
+ * void pxe_api_call ( struct i386_all_regs *ix86 );
+ ****************************************************************************
+ */
+
+ .globl kir_call
+kir_call:
+ /* Preserve flags. Must do this before any operation that may
+ * affect flags.
+ */
+ pushfl
+ popl %cs:save_flags
+
+ /* Disable interrupts. We do funny things with the stack, and
+ * we're not re-entrant.
+ */
+ cli
+
+ /* Extract address of internal routine from stack. We must do
+ * this without using (%bp), because we may be called with
+ * either a 16-bit or a 32-bit stack segment.
+ */
+ popl %cs:save_retaddr /* Scratch location */
+ popl %cs:save_function
+ subl $8, %esp /* Restore %esp */
+
+ /* Switch to internal stack. Note that the external stack is
+ * inaccessible once we're running internally (since we have
+ * no concept of 48-bit far pointers)
+ */
+ call ext_to_kir
+
+ /* Store external registers on internal stack */
+ pushl %cs:save_flags
+ pushal
+ pushl %cs:ext_fs_and_gs
+ pushl %cs:ext_ds_and_es
+ pushl %cs:ext_cs_and_ss
+
+ /* Push &ix86 on stack and call function */
+ sti
+ pushl %esp
+ data32 call *%cs:save_function
+ popl %eax /* discard */
+
+ /* Restore external registers from internal stack */
+ popl %cs:ext_cs_and_ss
+ popl %cs:ext_ds_and_es
+ popl %cs:ext_fs_and_gs
+ popal
+ popl %cs:save_flags
+
+ /* Switch to external stack */
+ call kir_to_ext
+
+ /* Restore flags */
+ pushl %cs:save_flags
+ popfl
+
+ /* Return */
+ lret
+
+/****************************************************************************
+ * Stored internal and external stack and segment registers
+ ****************************************************************************
+ */
+
+ext_cs_and_ss:
+ext_cs: .word 0
+ext_ss: .word 0
+ext_ds_and_es:
+ext_ds: .word 0
+ext_es: .word 0
+ext_fs_and_gs:
+ext_fs: .word 0
+ext_gs: .word 0
+ext_esp: .long 0
+
+ .globl kir_ds
+kir_ds: .word 0
+ .globl kir_sp
+kir_sp: .word _estack
+
+/****************************************************************************
+ * Temporary variables
+ ****************************************************************************
+ */
+save_ax: .word 0
+save_retaddr: .long 0
+save_flags: .long 0
+save_function: .long 0
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/libpm.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/libpm.S
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/libpm.S
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/librm.S b/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/librm.S
new file mode 100644
index 00000000..02d25b22
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/librm.S
@@ -0,0 +1,571 @@
+/*
+ * librm: a library for interfacing to real-mode code
+ *
+ * Michael Brown <mbrown@fensystems.co.uk>
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+/* Drag in local definitions */
+#include "librm.h"
+
+/* For switches to/from protected mode */
+#define CR0_PE 1
+
+/* Size of various C data structures */
+#define SIZEOF_I386_SEG_REGS 12
+#define SIZEOF_I386_REGS 32
+#define SIZEOF_REAL_MODE_REGS ( SIZEOF_I386_SEG_REGS + SIZEOF_I386_REGS )
+#define SIZEOF_I386_FLAGS 4
+#define SIZEOF_I386_ALL_REGS ( SIZEOF_REAL_MODE_REGS + SIZEOF_I386_FLAGS )
+
+ .arch i386
+
+/****************************************************************************
+ * Global descriptor table
+ *
+ * Call init_librm to set up the GDT before attempting to use any
+ * protected-mode code.
+ *
+ * NOTE: This must be located before prot_to_real, otherwise gas
+ * throws a "can't handle non absolute segment in `ljmp'" error due to
+ * not knowing the value of REAL_CS when the ljmp is encountered.
+ *
+ * Note also that putting ".word gdt_end - gdt - 1" directly into
+ * gdt_limit, rather than going via gdt_length, will also produce the
+ * "non absolute segment" error. This is most probably a bug in gas.
+ ****************************************************************************
+ */
+ .section ".data16", "aw", @progbits
+ .align 16
+gdt:
+gdtr: /* The first GDT entry is unused, the GDTR can fit here. */
+gdt_limit: .word gdt_length - 1
+gdt_base: .long 0
+ .word 0 /* padding */
+
+ .org gdt + VIRTUAL_CS, 0
+virtual_cs: /* 32 bit protected mode code segment, virtual addresses */
+ .word 0xffff, 0
+ .byte 0, 0x9f, 0xcf, 0
+
+ .org gdt + VIRTUAL_DS, 0
+virtual_ds: /* 32 bit protected mode data segment, virtual addresses */
+ .word 0xffff, 0
+ .byte 0, 0x93, 0xcf, 0
+
+ .org gdt + PHYSICAL_CS, 0
+physical_cs: /* 32 bit protected mode code segment, physical addresses */
+ .word 0xffff, 0
+ .byte 0, 0x9f, 0xcf, 0
+
+ .org gdt + PHYSICAL_DS, 0
+physical_ds: /* 32 bit protected mode data segment, physical addresses */
+ .word 0xffff, 0
+ .byte 0, 0x93, 0xcf, 0
+
+ .org gdt + REAL_CS, 0
+real_cs: /* 16 bit flat real mode code segment */
+ .word 0xffff, 0
+ .byte 0, 0x9b, 0x8f, 0
+
+ .org gdt + REAL_DS
+real_ds: /* 16 bit flat real mode data segment */
+ .word 0xffff, 0
+ .byte 0, 0x93, 0x8f, 0
+
+gdt_end:
+ .equ gdt_length, gdt_end - gdt
+
+/****************************************************************************
+ * init_librm (real-mode far call, 16-bit real-mode far return address)
+ *
+ * Initialise the GDT ready for transitions to protected mode.
+ *
+ * Parameters:
+ * %cs : .text16 segment
+ * %ds : .data16 segment
+ * %edi : Physical base of protected-mode code (virt_offset)
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+ .code16
+ .globl init_librm
+init_librm:
+ /* Preserve registers */
+ pushl %eax
+ pushl %ebx
+
+ /* Store virt_offset and set up virtual_cs and virtual_ds segments */
+ movl %edi, %eax
+ movw $virtual_cs, %bx
+ call set_seg_base
+ movw $virtual_ds, %bx
+ call set_seg_base
+ movl %edi, rm_virt_offset
+
+ /* Negate virt_offset */
+ negl %edi
+
+ /* Store rm_cs and text16, set up real_cs segment */
+ xorl %eax, %eax
+ movw %cs, %ax
+ movw %ax, rm_cs
+ shll $4, %eax
+ movw $real_cs, %bx
+ call set_seg_base
+ addr32 leal (%eax, %edi), %ebx
+ movl %ebx, rm_text16
+
+ /* Store rm_ds and data16, set up real_ds segment */
+ xorl %eax, %eax
+ movw %ds, %ax
+ movw %ax, %cs:rm_ds
+ shll $4, %eax
+ movw $real_ds, %bx
+ call set_seg_base
+ addr32 leal (%eax, %edi), %ebx
+ movl %ebx, rm_data16
+
+ /* Set GDT and IDT base */
+ movl %eax, gdt_base
+ addl $gdt, gdt_base
+ call idt_init
+
+ /* Restore registers */
+ negl %edi
+ popl %ebx
+ popl %eax
+ lret
+
+ .section ".text16", "ax", @progbits
+ .code16
+ .weak idt_init
+set_seg_base:
+1: movw %ax, 2(%bx)
+ rorl $16, %eax
+ movb %al, 4(%bx)
+ movb %ah, 7(%bx)
+ roll $16, %eax
+idt_init: /* Reuse the return opcode here */
+ ret
+
+/****************************************************************************
+ * real_to_prot (real-mode near call, 32-bit virtual return address)
+ *
+ * Switch from 16-bit real-mode to 32-bit protected mode with virtual
+ * addresses. The real-mode %ss:sp is stored in rm_ss and rm_sp, and
+ * the protected-mode %esp is restored from the saved pm_esp.
+ * Interrupts are disabled. All other registers may be destroyed.
+ *
+ * The return address for this function should be a 32-bit virtual
+ * address.
+ *
+ * Parameters:
+ * %ecx : number of bytes to move from RM stack to PM stack
+ *
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+ .code16
+real_to_prot:
+ /* Enable A20 line */
+ call enable_a20
+ /* A failure at this point is fatal, and there's nothing we
+ * can do about it other than lock the machine to make the
+ * problem immediately visible.
+ */
+1: jc 1b
+
+ /* Make sure we have our data segment available */
+ movw %cs:rm_ds, %ax
+ movw %ax, %ds
+
+ /* Add virt_offset, text16 and data16 to stack to be
+ * copied, and also copy the return address.
+ */
+ pushl rm_virt_offset
+ pushl rm_text16
+ pushl rm_data16
+ addw $16, %cx /* %ecx must be less than 64kB anyway */
+
+ /* Real-mode %ss:%sp => %ebp:%edx and virtual address => %esi */
+ xorl %ebp, %ebp
+ movw %ss, %bp
+ movzwl %sp, %edx
+ movl %ebp, %eax
+ shll $4, %eax
+ addr32 leal (%eax,%edx), %esi
+ subl rm_virt_offset, %esi
+
+ /* Switch to protected mode */
+ cli
+ data32 lgdt gdtr
+ data32 lidt idtr
+ movl %cr0, %eax
+ orb $CR0_PE, %al
+ movl %eax, %cr0
+ data32 ljmp $VIRTUAL_CS, $1f
+ .section ".text", "ax", @progbits
+ .code32
+1:
+ /* Set up protected-mode data segments and stack pointer */
+ movw $VIRTUAL_DS, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+ movl pm_esp, %esp
+
+ /* Record real-mode %ss:sp (after removal of data) */
+ movw %bp, rm_ss
+ addl %ecx, %edx
+ movw %dx, rm_sp
+
+ /* Move data from RM stack to PM stack */
+ subl %ecx, %esp
+ movl %esp, %edi
+ rep movsb
+
+ /* Publish virt_offset, text16 and data16 for PM code to use */
+ popl data16
+ popl text16
+ popl virt_offset
+
+ /* Return to virtual address */
+ ret
+
+ /* Default IDTR with no interrupts */
+ .section ".data16", "aw", @progbits
+ .weak idtr
+idtr:
+rm_idtr:
+ .word 0xffff /* limit */
+ .long 0 /* base */
+
+/****************************************************************************
+ * prot_to_real (protected-mode near call, 32-bit real-mode return address)
+ *
+ * Switch from 32-bit protected mode with virtual addresses to 16-bit
+ * real mode. The protected-mode %esp is stored in pm_esp and the
+ * real-mode %ss:sp is restored from the saved rm_ss and rm_sp. The
+ * high word of the real-mode %esp is set to zero. All real-mode data
+ * segment registers are loaded from the saved rm_ds. Interrupts are
+ * *not* enabled, since we want to be able to use prot_to_real in an
+ * ISR. All other registers may be destroyed.
+ *
+ * The return address for this function should be a 32-bit (sic)
+ * real-mode offset within .code16.
+ *
+ * Parameters:
+ * %ecx : number of bytes to move from PM stack to RM stack
+ *
+ ****************************************************************************
+ */
+ .section ".text", "ax", @progbits
+ .code32
+prot_to_real:
+ /* Add return address to data to be moved to RM stack */
+ addl $4, %ecx
+
+ /* Real-mode %ss:sp => %ebp:edx and virtual address => %edi */
+ movzwl rm_ss, %ebp
+ movzwl rm_sp, %edx
+ subl %ecx, %edx
+ movl %ebp, %eax
+ shll $4, %eax
+ leal (%eax,%edx), %edi
+ subl virt_offset, %edi
+
+ /* Move data from PM stack to RM stack */
+ movl %esp, %esi
+ rep movsb
+
+ /* Record protected-mode %esp (after removal of data) */
+ movl %esi, pm_esp
+
+ /* Load real-mode segment limits */
+ movw $REAL_DS, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+ ljmp $REAL_CS, $1f
+ .section ".text16", "ax", @progbits
+ .code16
+1:
+ /* Switch to real mode */
+ movl %cr0, %eax
+ andb $0!CR0_PE, %al
+ movl %eax, %cr0
+ ljmp *p2r_jump_vector
+p2r_jump_target:
+
+ /* Set up real-mode data segments and stack pointer */
+ movw %cs:rm_ds, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %bp, %ss
+ movl %edx, %esp
+
+ /* Reset IDTR to the real-mode defaults */
+ data32 lidt rm_idtr
+
+ /* Return to real-mode address */
+ data32 ret
+
+
+ /* Real-mode code and data segments. Assigned by the call to
+ * init_librm. rm_cs doubles as the segment part of the jump
+ * vector used by prot_to_real. rm_ds is located in .text16
+ * rather than .data16 because code needs to be able to locate
+ * the data segment.
+ */
+ .section ".data16", "aw", @progbits
+p2r_jump_vector:
+ .word p2r_jump_target
+ .globl rm_cs
+rm_cs: .word 0
+ .globl rm_ds
+ .section ".text16.data", "aw", @progbits
+rm_ds: .word 0
+
+/****************************************************************************
+ * prot_call (real-mode far call, 16-bit real-mode far return address)
+ *
+ * Call a specific C function in the protected-mode code. The
+ * prototype of the C function must be
+ * void function ( struct i386_all_regs *ix86 );
+ * ix86 will point to a struct containing the real-mode registers
+ * at entry to prot_call.
+ *
+ * All registers will be preserved across prot_call(), unless the C
+ * function explicitly overwrites values in ix86. Interrupt status
+ * and GDT will also be preserved. Gate A20 will be enabled.
+ *
+ * Note that prot_call() does not rely on the real-mode stack
+ * remaining intact in order to return, since everything relevant is
+ * copied to the protected-mode stack for the duration of the call.
+ * In particular, this means that a real-mode prefix can make a call
+ * to main() which will return correctly even if the prefix's stack
+ * gets vapourised during the Etherboot run. (The prefix cannot rely
+ * on anything else on the stack being preserved, so should move any
+ * critical data to registers before calling main()).
+ *
+ * Parameters:
+ * function : virtual address of protected-mode function to call
+ *
+ * Example usage:
+ * pushl $pxe_api_call
+ * call prot_call
+ * addw $4, %sp
+ * to call in to the C function
+ * void pxe_api_call ( struct i386_all_regs *ix86 );
+ ****************************************************************************
+ */
+
+#define PC_OFFSET_GDT ( 0 )
+#define PC_OFFSET_IDT ( PC_OFFSET_GDT + 8 /* pad to 8 to keep alignment */ )
+#define PC_OFFSET_IX86 ( PC_OFFSET_IDT + 8 /* pad to 8 to keep alignment */ )
+#define PC_OFFSET_RETADDR ( PC_OFFSET_IX86 + SIZEOF_I386_ALL_REGS )
+#define PC_OFFSET_FUNCTION ( PC_OFFSET_RETADDR + 4 )
+#define PC_OFFSET_END ( PC_OFFSET_FUNCTION + 4 )
+
+ .section ".text16", "ax", @progbits
+ .code16
+ .globl prot_call
+prot_call:
+ /* Preserve registers, flags and GDT on external RM stack */
+ pushfl
+ pushal
+ pushw %gs
+ pushw %fs
+ pushw %es
+ pushw %ds
+ pushw %ss
+ pushw %cs
+ subw $16, %sp
+ movw %sp, %bp
+ sidt 8(%bp)
+ sgdt (%bp)
+
+ /* For sanity's sake, clear the direction flag as soon as possible */
+ cld
+
+ /* Switch to protected mode and move register dump to PM stack */
+ movl $PC_OFFSET_END, %ecx
+ pushl $1f
+ jmp real_to_prot
+ .section ".text", "ax", @progbits
+ .code32
+1:
+ /* Call function */
+ leal PC_OFFSET_IX86(%esp), %eax
+ pushl %eax
+ call *(PC_OFFSET_FUNCTION+4)(%esp)
+ popl %eax /* discard */
+
+ /* Switch to real mode and move register dump back to RM stack */
+ movl $PC_OFFSET_END, %ecx
+ pushl $1f
+ jmp prot_to_real
+ .section ".text16", "ax", @progbits
+ .code16
+1:
+ /* Reload GDT and IDT, restore registers and flags and return */
+ movw %sp, %bp
+ data32 lgdt (%bp)
+ data32 lidt 8(%bp)
+ addw $20, %sp /* also skip %cs and %ss */
+ popw %ds
+ popw %es
+ popw %fs
+ popw %gs
+ popal
+ /* popal skips %esp. We therefore want to do "movl -20(%sp),
+ * %esp", but -20(%sp) is not a valid 80386 expression.
+ * Fortunately, prot_to_real() zeroes the high word of %esp, so
+ * we can just use -20(%esp) instead.
+ */
+ addr32 movl -20(%esp), %esp
+ popfl
+ lret
+
+/****************************************************************************
+ * real_call (protected-mode near call, 32-bit virtual return address)
+ *
+ * Call a real-mode function from protected-mode code.
+ *
+ * The non-segment register values will be passed directly to the
+ * real-mode code. The segment registers will be set as per
+ * prot_to_real. The non-segment register values set by the real-mode
+ * function will be passed back to the protected-mode caller. A
+ * result of this is that this routine cannot be called directly from
+ * C code, since it clobbers registers that the C ABI expects the
+ * callee to preserve.
+ *
+ * librm.h defines a convenient macro REAL_CODE() for using real_call.
+ * See librm.h and realmode.h for details and examples.
+ *
+ * Parameters:
+ * (32-bit) near pointer to real-mode function to call
+ *
+ * Returns: none
+ ****************************************************************************
+ */
+
+#define RC_OFFSET_PRESERVE_REGS ( 0 )
+#define RC_OFFSET_RETADDR ( RC_OFFSET_PRESERVE_REGS + SIZEOF_I386_REGS )
+#define RC_OFFSET_FUNCTION ( RC_OFFSET_RETADDR + 4 )
+#define RC_OFFSET_END ( RC_OFFSET_FUNCTION + 4 )
+
+ .section ".text", "ax", @progbits
+ .code32
+ .globl real_call
+real_call:
+ /* Create register dump and function pointer copy on PM stack */
+ pushal
+ pushl RC_OFFSET_FUNCTION(%esp)
+
+ /* Switch to real mode and move register dump to RM stack */
+ movl $( RC_OFFSET_RETADDR + 4 /* function pointer copy */ ), %ecx
+ pushl $1f
+ jmp prot_to_real
+ .section ".text16", "ax", @progbits
+ .code16
+1:
+ /* Call real-mode function */
+ popl rc_function
+ popal
+ call *rc_function
+ pushal
+
+ /* For sanity's sake, clear the direction flag as soon as possible */
+ cld
+
+ /* Switch to protected mode and move register dump back to PM stack */
+ movl $RC_OFFSET_RETADDR, %ecx
+ pushl $1f
+ jmp real_to_prot
+ .section ".text", "ax", @progbits
+ .code32
+1:
+ /* Restore registers and return */
+ popal
+ ret
+
+
+ /* Function vector, used because "call xx(%sp)" is not a valid
+ * 16-bit expression.
+ */
+ .section ".data16", "aw", @progbits
+rc_function: .word 0, 0
+
+/****************************************************************************
+ * Stored real-mode and protected-mode stack pointers
+ *
+ * The real-mode stack pointer is stored here whenever real_to_prot
+ * is called and restored whenever prot_to_real is called. The
+ * converse happens for the protected-mode stack pointer.
+ *
+ * Despite initial appearances this scheme is, in fact re-entrant,
+ * because program flow dictates that we always return via the point
+ * we left by. For example:
+ * PXE API call entry
+ * 1 real => prot
+ * ...
+ * Print a text string
+ * ...
+ * 2 prot => real
+ * INT 10
+ * 3 real => prot
+ * ...
+ * ...
+ * 4 prot => real
+ * PXE API call exit
+ *
+ * At point 1, the RM mode stack value, say RPXE, is stored in
+ * rm_ss,sp. We want this value to still be present in rm_ss,sp when
+ * we reach point 4.
+ *
+ * At point 2, the RM stack value is restored from RPXE. At point 3,
+ * the RM stack value is again stored in rm_ss,sp. This *does*
+ * overwrite the RPXE that we have stored there, but it's the same
+ * value, since the code between points 2 and 3 has managed to return
+ * to us.
+ ****************************************************************************
+ */
+ .section ".data", "aw", @progbits
+ .globl rm_sp
+rm_sp: .word 0
+ .globl rm_ss
+rm_ss: .word 0
+pm_esp: .long _estack
+
+/****************************************************************************
+ * Virtual address offsets
+ *
+ * These are used by the protected-mode code to map between virtual
+ * and physical addresses, and to access variables in the .text16 or
+ * .data16 segments.
+ ****************************************************************************
+ */
+ /* Internal copies, created by init_librm (which runs in real mode) */
+ .section ".data16", "aw", @progbits
+rm_virt_offset: .long 0
+rm_text16: .long 0
+rm_data16: .long 0
+
+ /* Externally-visible copies, created by real_to_prot */
+ .section ".data", "aw", @progbits
+ .globl virt_offset
+virt_offset: .long 0
+ .globl text16
+text16: .long 0
+ .globl data16
+data16: .long 0
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/librm_mgmt.c b/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/librm_mgmt.c
new file mode 100644
index 00000000..f00be811
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/i386/transitions/librm_mgmt.c
@@ -0,0 +1,58 @@
+/*
+ * librm: a library for interfacing to real-mode code
+ *
+ * Michael Brown <mbrown@fensystems.co.uk>
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <realmode.h>
+
+/*
+ * This file provides functions for managing librm.
+ *
+ */
+
+/**
+ * Allocate space on the real-mode stack and copy data there from a
+ * user buffer
+ *
+ * @v data User buffer
+ * @v size Size of stack data
+ * @ret sp New value of real-mode stack pointer
+ */
+uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size ) {
+ userptr_t rm_stack;
+ rm_sp -= size;
+ rm_stack = real_to_user ( rm_ss, rm_sp );
+ memcpy_user ( rm_stack, 0, data, 0, size );
+ return rm_sp;
+};
+
+/**
+ * Deallocate space on the real-mode stack, optionally copying back
+ * data to a user buffer.
+ *
+ * @v data User buffer
+ * @v size Size of stack data
+ */
+void remove_user_from_rm_stack ( userptr_t data, size_t size ) {
+ if ( data ) {
+ userptr_t rm_stack = real_to_user ( rm_ss, rm_sp );
+ memcpy_user ( rm_stack, 0, data, 0, size );
+ }
+ rm_sp += size;
+};
+
+PROVIDE_UACCESS_INLINE ( librm, phys_to_user );
+PROVIDE_UACCESS_INLINE ( librm, user_to_phys );
+PROVIDE_UACCESS_INLINE ( librm, virt_to_user );
+PROVIDE_UACCESS_INLINE ( librm, user_to_virt );
+PROVIDE_UACCESS_INLINE ( librm, userptr_add );
+PROVIDE_UACCESS_INLINE ( librm, memcpy_user );
+PROVIDE_UACCESS_INLINE ( librm, memmove_user );
+PROVIDE_UACCESS_INLINE ( librm, memset_user );
+PROVIDE_UACCESS_INLINE ( librm, strlen_user );
+PROVIDE_UACCESS_INLINE ( librm, memchr_user );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/Makefile b/src/VBox/Devices/PC/ipxe/src/arch/x86/Makefile
new file mode 100644
index 00000000..37e03aaf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/Makefile
@@ -0,0 +1,15 @@
+# Include common x86 headers
+#
+INCDIRS += arch/x86/include
+
+# x86-specific directories containing source files
+#
+SRCDIRS += arch/x86/core
+SRCDIRS += arch/x86/interface/efi
+SRCDIRS += arch/x86/prefix
+
+# breaks building some of the linux-related objects
+CFLAGS += -Ulinux
+
+# disable valgrind
+CFLAGS += -DNVALGRIND
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/Makefile.efi b/src/VBox/Devices/PC/ipxe/src/arch/x86/Makefile.efi
new file mode 100644
index 00000000..bef8d59d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/Makefile.efi
@@ -0,0 +1,28 @@
+# -*- makefile -*- : Force emacs to use Makefile mode
+
+# The EFI linker script
+#
+LDSCRIPT = arch/x86/scripts/efi.lds
+
+# Retain relocation information for elf2efi
+#
+LDFLAGS += -q -S
+
+# Media types.
+#
+NON_AUTO_MEDIA += efi
+NON_AUTO_MEDIA += efidrv
+
+# Rules for building EFI files
+#
+$(BIN)/%.efi : $(BIN)/%.efi.tmp $(ELF2EFI)
+ $(QM)$(ECHO) " [FINISH] $@"
+ $(Q)$(ELF2EFI) --subsystem=10 $< $@
+
+$(BIN)/%.efidrv : $(BIN)/%.efidrv.tmp $(ELF2EFI)
+ $(QM)$(ECHO) " [FINISH] $@"
+ $(Q)$(ELF2EFI) --subsystem=11 $< $@
+
+$(BIN)/%.efirom : $(BIN)/%.efidrv $(EFIROM)
+ $(QM)$(ECHO) " [FINISH] $@"
+ $(Q)$(EFIROM) -v $(TGT_PCI_VENDOR) -d $(TGT_PCI_DEVICE) $< $@
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/Makefile.linux b/src/VBox/Devices/PC/ipxe/src/arch/x86/Makefile.linux
new file mode 100644
index 00000000..e35b04f0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/Makefile.linux
@@ -0,0 +1,13 @@
+MEDIA = linux
+
+# enable valgrind
+CFLAGS += -UNVALGRIND
+
+INCDIRS += arch/x86/include/linux
+SRCDIRS += interface/linux
+SRCDIRS += drivers/linux
+SRCDIRS += arch/x86/core/linux
+
+$(BIN)/%.linux : $(BIN)/%.linux.tmp
+ $(QM)$(ECHO) " [FINISH] $@"
+ $(Q)cp -p $< $@
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/core/linux/linux_api.c b/src/VBox/Devices/PC/ipxe/src/arch/x86/core/linux/linux_api.c
new file mode 100644
index 00000000..c8a09b7d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/core/linux/linux_api.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Implementation of most of the linux API.
+ */
+
+#include <linux_api.h>
+
+#include <stdarg.h>
+#include <asm/unistd.h>
+#include <string.h>
+
+int linux_open ( const char *pathname, int flags ) {
+ return linux_syscall ( __NR_open, pathname, flags );
+}
+
+int linux_close ( int fd ) {
+ return linux_syscall ( __NR_close, fd );
+}
+
+__kernel_ssize_t linux_read ( int fd, void *buf, __kernel_size_t count ) {
+ return linux_syscall ( __NR_read, fd, buf, count );
+}
+
+__kernel_ssize_t linux_write ( int fd, const void *buf,
+ __kernel_size_t count ) {
+ return linux_syscall ( __NR_write, fd, buf, count );
+}
+
+int linux_fcntl ( int fd, int cmd, ... ) {
+ long arg;
+ va_list list;
+
+ va_start ( list, cmd );
+ arg = va_arg ( list, long );
+ va_end ( list );
+
+ return linux_syscall ( __NR_fcntl, fd, cmd, arg );
+}
+
+int linux_ioctl ( int fd, int request, ... ) {
+ void *arg;
+ va_list list;
+
+ va_start ( list, request );
+ arg = va_arg ( list, void * );
+ va_end ( list );
+
+ return linux_syscall ( __NR_ioctl, fd, request, arg );
+}
+
+int linux_poll ( struct pollfd *fds, nfds_t nfds, int timeout ) {
+ return linux_syscall ( __NR_poll, fds, nfds, timeout );
+}
+
+int linux_nanosleep ( const struct timespec *req, struct timespec *rem ) {
+ return linux_syscall ( __NR_nanosleep, req, rem );
+}
+
+int linux_usleep ( useconds_t usec ) {
+ struct timespec ts = {
+ .tv_sec = ( ( long ) ( usec / 1000000 ) ),
+ .tv_nsec = ( ( long ) ( usec % 1000000 ) * 1000UL ),
+ };
+
+ return linux_nanosleep ( &ts, NULL );
+}
+
+int linux_gettimeofday ( struct timeval *tv, struct timezone *tz ) {
+ return linux_syscall ( __NR_gettimeofday, tv, tz );
+}
+
+void * linux_mmap ( void *addr, __kernel_size_t length, int prot, int flags,
+ int fd, __kernel_off_t offset ) {
+ return ( void * ) linux_syscall ( __SYSCALL_mmap, addr, length, prot,
+ flags, fd, offset );
+}
+
+void * linux_mremap ( void *old_address, __kernel_size_t old_size,
+ __kernel_size_t new_size, int flags ) {
+ return ( void * ) linux_syscall ( __NR_mremap, old_address, old_size,
+ new_size, flags );
+}
+
+int linux_munmap ( void *addr, __kernel_size_t length ) {
+ return linux_syscall ( __NR_munmap, addr, length );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/core/linux/linux_strerror.c b/src/VBox/Devices/PC/ipxe/src/arch/x86/core/linux/linux_strerror.c
new file mode 100644
index 00000000..24c9b773
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/core/linux/linux_strerror.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+/** @file
+ *
+ * linux_strerror implementation
+ */
+
+#include <linux_api.h>
+#include <stdio.h>
+
+/** Error names from glibc */
+static const char *errors[] = {
+ "Success",
+ "Operation not permitted",
+ "No such file or directory",
+ "No such process",
+ "Interrupted system call",
+ "Input/output error",
+ "No such device or address",
+ "Argument list too long",
+ "Exec format error",
+ "Bad file descriptor",
+ "No child processes",
+ "Resource temporarily unavailable",
+ "Cannot allocate memory",
+ "Permission denied",
+ "Bad address",
+ "Block device required",
+ "Device or resource busy",
+ "File exists",
+ "Invalid cross-device link",
+ "No such device",
+ "Not a directory",
+ "Is a directory",
+ "Invalid argument",
+ "Too many open files in system",
+ "Too many open files",
+ "Inappropriate ioctl for device",
+ "Text file busy",
+ "File too large",
+ "No space left on device",
+ "Illegal seek",
+ "Read-only file system",
+ "Too many links",
+ "Broken pipe",
+ "Numerical argument out of domain",
+ "Numerical result out of range",
+ "Resource deadlock avoided",
+ "File name too long",
+ "No locks available",
+ "Function not implemented",
+ "Directory not empty",
+ "Too many levels of symbolic links",
+ "",
+ "No message of desired type",
+ "Identifier removed",
+ "Channel number out of range",
+ "Level 2 not synchronized",
+ "Level 3 halted",
+ "Level 3 reset",
+ "Link number out of range",
+ "Protocol driver not attached",
+ "No CSI structure available",
+ "Level 2 halted",
+ "Invalid exchange",
+ "Invalid request descriptor",
+ "Exchange full",
+ "No anode",
+ "Invalid request code",
+ "Invalid slot",
+ "",
+ "Bad font file format",
+ "Device not a stream",
+ "No data available",
+ "Timer expired",
+ "Out of streams resources",
+ "Machine is not on the network",
+ "Package not installed",
+ "Object is remote",
+ "Link has been severed",
+ "Advertise error",
+ "Srmount error",
+ "Communication error on send",
+ "Protocol error",
+ "Multihop attempted",
+ "RFS specific error",
+ "Bad message",
+ "Value too large for defined data type",
+ "Name not unique on network",
+ "File descriptor in bad state",
+ "Remote address changed",
+ "Can not access a needed shared library",
+ "Accessing a corrupted shared library",
+ ".lib section in a.out corrupted",
+ "Attempting to link in too many shared libraries",
+ "Cannot exec a shared library directly",
+ "Invalid or incomplete multibyte or wide character",
+ "Interrupted system call should be restarted",
+ "Streams pipe error",
+ "Too many users",
+ "Socket operation on non-socket",
+ "Destination address required",
+ "Message too long",
+ "Protocol wrong type for socket",
+ "Protocol not available",
+ "Protocol not supported",
+ "Socket type not supported",
+ "Operation not supported",
+ "Protocol family not supported",
+ "Address family not supported by protocol",
+ "Address already in use",
+ "Cannot assign requested address",
+ "Network is down",
+ "Network is unreachable",
+ "Network dropped connection on reset",
+ "Software caused connection abort",
+ "Connection reset by peer",
+ "No buffer space available",
+ "Transport endpoint is already connected",
+ "Transport endpoint is not connected",
+ "Cannot send after transport endpoint shutdown",
+ "Too many references: cannot splice",
+ "Connection timed out",
+ "Connection refused",
+ "Host is down",
+ "No route to host",
+ "Operation already in progress",
+ "Operation now in progress",
+ "Stale NFS file handle",
+ "Structure needs cleaning",
+ "Not a XENIX named type file",
+ "No XENIX semaphores available",
+ "Is a named type file",
+ "Remote I/O error",
+ "Disk quota exceeded",
+ "No medium found",
+ "Wrong medium type",
+};
+
+const char *linux_strerror(int errnum)
+{
+ static char errbuf[64];
+ static int errors_size = sizeof(errors) / sizeof(*errors);
+
+ if (errnum >= errors_size || errnum < 0) {
+ snprintf(errbuf, sizeof(errbuf), "Error %#08x", errnum);
+ return errbuf;
+ } else {
+ return errors[errnum];
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/core/pcidirect.c b/src/VBox/Devices/PC/ipxe/src/arch/x86/core/pcidirect.c
new file mode 100644
index 00000000..a07f7d4b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/core/pcidirect.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/io.h>
+#include <ipxe/pci.h>
+
+/** @file
+ *
+ * PCI configuration space access via Type 1 accesses
+ *
+ */
+
+/**
+ * Prepare for Type 1 PCI configuration space access
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ */
+void pcidirect_prepare ( struct pci_device *pci, int where ) {
+ outl ( ( 0x80000000 | ( pci->busdevfn << 8 ) | ( where & ~3 ) ),
+ PCIDIRECT_CONFIG_ADDRESS );
+}
+
+PROVIDE_PCIAPI_INLINE ( direct, pci_num_bus );
+PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_byte );
+PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_word );
+PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_dword );
+PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_byte );
+PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_word );
+PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_dword );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/core/x86_bigint.c b/src/VBox/Devices/PC/ipxe/src/arch/x86/core/x86_bigint.c
new file mode 100644
index 00000000..cb6c67b1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/core/x86_bigint.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <ipxe/bigint.h>
+
+/** @file
+ *
+ * Big integer support
+ */
+
+/**
+ * Multiply big integers
+ *
+ * @v multiplicand0 Element 0 of big integer to be multiplied
+ * @v multiplier0 Element 0 of big integer to be multiplied
+ * @v result0 Element 0 of big integer to hold result
+ * @v size Number of elements
+ */
+void bigint_multiply_raw ( const uint32_t *multiplicand0,
+ const uint32_t *multiplier0,
+ uint32_t *result0, unsigned int size ) {
+ const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand =
+ ( ( const void * ) multiplicand0 );
+ const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier =
+ ( ( const void * ) multiplier0 );
+ bigint_t ( size * 2 ) __attribute__ (( may_alias )) *result =
+ ( ( void * ) result0 );
+ unsigned int i;
+ unsigned int j;
+ uint32_t multiplicand_element;
+ uint32_t multiplier_element;
+ uint32_t *result_elements;
+ uint32_t discard_a;
+ uint32_t discard_d;
+ long index;
+
+ /* Zero result */
+ memset ( result, 0, sizeof ( *result ) );
+
+ /* Multiply integers one element at a time */
+ for ( i = 0 ; i < size ; i++ ) {
+ multiplicand_element = multiplicand->element[i];
+ for ( j = 0 ; j < size ; j++ ) {
+ multiplier_element = multiplier->element[j];
+ result_elements = &result->element[ i + j ];
+ /* Perform a single multiply, and add the
+ * resulting double-element into the result,
+ * carrying as necessary. The carry can
+ * never overflow beyond the end of the
+ * result, since:
+ *
+ * a < 2^{n}, b < 2^{n} => ab < 2^{2n}
+ */
+ __asm__ __volatile__ ( "mull %4\n\t"
+ "addl %%eax, (%5,%2,4)\n\t"
+ "adcl %%edx, 4(%5,%2,4)\n\t"
+ "\n1:\n\t"
+ "adcl $0, 8(%5,%2,4)\n\t"
+ "inc %2\n\t"
+ /* Does not affect CF */
+ "jc 1b\n\t"
+ : "=&a" ( discard_a ),
+ "=&d" ( discard_d ),
+ "=&r" ( index )
+ : "0" ( multiplicand_element ),
+ "g" ( multiplier_element ),
+ "r" ( result_elements ),
+ "2" ( 0 ) );
+ }
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/core/x86_string.c b/src/VBox/Devices/PC/ipxe/src/arch/x86/core/x86_string.c
new file mode 100644
index 00000000..5838ebac
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/core/x86_string.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/** @file
+ *
+ * Optimised string operations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+
+/**
+ * Copy memory area
+ *
+ * @v dest Destination address
+ * @v src Source address
+ * @v len Length
+ * @ret dest Destination address
+ */
+void * __memcpy ( void *dest, const void *src, size_t len ) {
+ void *edi = dest;
+ const void *esi = src;
+ int discard_ecx;
+
+ /* We often do large dword-aligned and dword-length block
+ * moves. Using movsl rather than movsb speeds these up by
+ * around 32%.
+ */
+ if ( len >> 2 ) {
+ __asm__ __volatile__ ( "rep movsl"
+ : "=&D" ( edi ), "=&S" ( esi ),
+ "=&c" ( discard_ecx )
+ : "0" ( edi ), "1" ( esi ),
+ "2" ( len >> 2 )
+ : "memory" );
+ }
+ if ( len & 0x02 ) {
+ __asm__ __volatile__ ( "movsw" : "=&D" ( edi ), "=&S" ( esi )
+ : "0" ( edi ), "1" ( esi ) : "memory" );
+ }
+ if ( len & 0x01 ) {
+ __asm__ __volatile__ ( "movsb" : "=&D" ( edi ), "=&S" ( esi )
+ : "0" ( edi ), "1" ( esi ) : "memory" );
+ }
+ return dest;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/bigint.h b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/bigint.h
new file mode 100644
index 00000000..d3449af5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/bigint.h
@@ -0,0 +1,318 @@
+#ifndef _BITS_BIGINT_H
+#define _BITS_BIGINT_H
+
+/** @file
+ *
+ * Big integer support
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+
+/** Element of a big integer */
+typedef uint32_t bigint_element_t;
+
+/**
+ * Initialise big integer
+ *
+ * @v value0 Element 0 of big integer to initialise
+ * @v size Number of elements
+ * @v data Raw data
+ * @v len Length of raw data
+ */
+static inline __attribute__ (( always_inline )) void
+bigint_init_raw ( uint32_t *value0, unsigned int size,
+ const void *data, size_t len ) {
+ long pad_len = ( sizeof ( bigint_t ( size ) ) - len );
+ void *discard_D;
+ long discard_c;
+
+ /* Copy raw data in reverse order, padding with zeros */
+ __asm__ __volatile__ ( "\n1:\n\t"
+ "movb -1(%2,%1), %%al\n\t"
+ "stosb\n\t"
+ "loop 1b\n\t"
+ "xorl %%eax, %%eax\n\t"
+ "mov %3, %1\n\t"
+ "rep stosb\n\t"
+ : "=&D" ( discard_D ), "=&c" ( discard_c )
+ : "r" ( data ), "g" ( pad_len ), "0" ( value0 ),
+ "1" ( len )
+ : "eax" );
+}
+
+/**
+ * Add big integers
+ *
+ * @v addend0 Element 0 of big integer to add
+ * @v value0 Element 0 of big integer to be added to
+ * @v size Number of elements
+ */
+static inline __attribute__ (( always_inline )) void
+bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
+ unsigned int size ) {
+ long index;
+ void *discard_S;
+ long discard_c;
+
+ __asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
+ "\n1:\n\t"
+ "lodsl\n\t"
+ "adcl %%eax, (%3,%0,4)\n\t"
+ "inc %0\n\t" /* Does not affect CF */
+ "loop 1b\n\t"
+ : "=&r" ( index ), "=&S" ( discard_S ),
+ "=&c" ( discard_c )
+ : "r" ( value0 ), "1" ( addend0 ), "2" ( size )
+ : "eax" );
+}
+
+/**
+ * Subtract big integers
+ *
+ * @v subtrahend0 Element 0 of big integer to subtract
+ * @v value0 Element 0 of big integer to be subtracted from
+ * @v size Number of elements
+ */
+static inline __attribute__ (( always_inline )) void
+bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
+ unsigned int size ) {
+ long index;
+ void *discard_S;
+ long discard_c;
+
+ __asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
+ "\n1:\n\t"
+ "lodsl\n\t"
+ "sbbl %%eax, (%3,%0,4)\n\t"
+ "inc %0\n\t" /* Does not affect CF */
+ "loop 1b\n\t"
+ : "=&r" ( index ), "=&S" ( discard_S ),
+ "=&c" ( discard_c )
+ : "r" ( value0 ), "1" ( subtrahend0 ),
+ "2" ( size )
+ : "eax" );
+}
+
+/**
+ * Rotate big integer left
+ *
+ * @v value0 Element 0 of big integer
+ * @v size Number of elements
+ */
+static inline __attribute__ (( always_inline )) void
+bigint_rol_raw ( uint32_t *value0, unsigned int size ) {
+ long index;
+ long discard_c;
+
+ __asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
+ "\n1:\n\t"
+ "rcll $1, (%2,%0,4)\n\t"
+ "inc %0\n\t" /* Does not affect CF */
+ "loop 1b\n\t"
+ : "=&r" ( index ), "=&c" ( discard_c )
+ : "r" ( value0 ), "1" ( size ) );
+}
+
+/**
+ * Rotate big integer right
+ *
+ * @v value0 Element 0 of big integer
+ * @v size Number of elements
+ */
+static inline __attribute__ (( always_inline )) void
+bigint_ror_raw ( uint32_t *value0, unsigned int size ) {
+ long discard_c;
+
+ __asm__ __volatile__ ( "clc\n\t"
+ "\n1:\n\t"
+ "rcrl $1, -4(%1,%0,4)\n\t"
+ "loop 1b\n\t"
+ : "=&c" ( discard_c )
+ : "r" ( value0 ), "0" ( size ) );
+}
+
+/**
+ * Test if big integer is equal to zero
+ *
+ * @v value0 Element 0 of big integer
+ * @v size Number of elements
+ * @ret is_zero Big integer is equal to zero
+ */
+static inline __attribute__ (( always_inline, pure )) int
+bigint_is_zero_raw ( const uint32_t *value0, unsigned int size ) {
+ void *discard_D;
+ long discard_c;
+ int result;
+
+ __asm__ __volatile__ ( "xor %0, %0\n\t" /* Set ZF */
+ "repe scasl\n\t"
+ "sete %b0\n\t"
+ : "=&a" ( result ), "=&D" ( discard_D ),
+ "=&c" ( discard_c )
+ : "1" ( value0 ), "2" ( size ) );
+ return result;
+}
+
+/**
+ * Compare big integers
+ *
+ * @v value0 Element 0 of big integer
+ * @v reference0 Element 0 of reference big integer
+ * @v size Number of elements
+ * @ret geq Big integer is greater than or equal to the reference
+ */
+static inline __attribute__ (( always_inline, pure )) int
+bigint_is_geq_raw ( const uint32_t *value0, const uint32_t *reference0,
+ unsigned int size ) {
+ const bigint_t ( size ) __attribute__ (( may_alias )) *value =
+ ( ( const void * ) value0 );
+ const bigint_t ( size ) __attribute__ (( may_alias )) *reference =
+ ( ( const void * ) reference0 );
+ void *discard_S;
+ void *discard_D;
+ long discard_c;
+ int result;
+
+ __asm__ __volatile__ ( "std\n\t"
+ "\n1:\n\t"
+ "lodsl\n\t"
+ "scasl\n\t"
+ "loope 1b\n\t"
+ "setae %b0\n\t"
+ "cld\n\t"
+ : "=q" ( result ), "=&S" ( discard_S ),
+ "=&D" ( discard_D ), "=&c" ( discard_c )
+ : "0" ( 0 ), "1" ( &value->element[ size - 1 ] ),
+ "2" ( &reference->element[ size - 1 ] ),
+ "3" ( size )
+ : "eax" );
+ return result;
+}
+
+/**
+ * Test if bit is set in big integer
+ *
+ * @v value0 Element 0 of big integer
+ * @v size Number of elements
+ * @v bit Bit to test
+ * @ret is_set Bit is set
+ */
+static inline __attribute__ (( always_inline )) int
+bigint_bit_is_set_raw ( const uint32_t *value0, unsigned int size,
+ unsigned int bit ) {
+ const bigint_t ( size ) __attribute__ (( may_alias )) *value =
+ ( ( const void * ) value0 );
+ unsigned int index = ( bit / ( 8 * sizeof ( value->element[0] ) ) );
+ unsigned int subindex = ( bit % ( 8 * sizeof ( value->element[0] ) ) );
+
+ return ( value->element[index] & ( 1 << subindex ) );
+}
+
+/**
+ * Find highest bit set in big integer
+ *
+ * @v value0 Element 0 of big integer
+ * @v size Number of elements
+ * @ret max_bit Highest bit set + 1 (or 0 if no bits set)
+ */
+static inline __attribute__ (( always_inline )) int
+bigint_max_set_bit_raw ( const uint32_t *value0, unsigned int size ) {
+ long discard_c;
+ int result;
+
+ __asm__ __volatile__ ( "\n1:\n\t"
+ "bsrl -4(%2,%1,4), %0\n\t"
+ "loopz 1b\n\t"
+ "rol %1\n\t" /* Does not affect ZF */
+ "rol %1\n\t"
+ "leal 1(%k0,%k1,8), %k0\n\t"
+ "jnz 2f\n\t"
+ "xor %0, %0\n\t"
+ "\n2:\n\t"
+ : "=&r" ( result ), "=&c" ( discard_c )
+ : "r" ( value0 ), "1" ( size ) );
+ return result;
+}
+
+/**
+ * Grow big integer
+ *
+ * @v source0 Element 0 of source big integer
+ * @v source_size Number of elements in source big integer
+ * @v dest0 Element 0 of destination big integer
+ * @v dest_size Number of elements in destination big integer
+ */
+static inline __attribute__ (( always_inline )) void
+bigint_grow_raw ( const uint32_t *source0, unsigned int source_size,
+ uint32_t *dest0, unsigned int dest_size ) {
+ long pad_size = ( dest_size - source_size );
+ void *discard_D;
+ void *discard_S;
+ long discard_c;
+
+ __asm__ __volatile__ ( "rep movsl\n\t"
+ "xorl %%eax, %%eax\n\t"
+ "mov %3, %2\n\t"
+ "rep stosl\n\t"
+ : "=&D" ( discard_D ), "=&S" ( discard_S ),
+ "=&c" ( discard_c )
+ : "g" ( pad_size ), "0" ( dest0 ),
+ "1" ( source0 ), "2" ( source_size )
+ : "eax" );
+}
+
+/**
+ * Shrink big integer
+ *
+ * @v source0 Element 0 of source big integer
+ * @v source_size Number of elements in source big integer
+ * @v dest0 Element 0 of destination big integer
+ * @v dest_size Number of elements in destination big integer
+ */
+static inline __attribute__ (( always_inline )) void
+bigint_shrink_raw ( const uint32_t *source0, unsigned int source_size __unused,
+ uint32_t *dest0, unsigned int dest_size ) {
+ void *discard_D;
+ void *discard_S;
+ long discard_c;
+
+ __asm__ __volatile__ ( "rep movsl\n\t"
+ : "=&D" ( discard_D ), "=&S" ( discard_S ),
+ "=&c" ( discard_c )
+ : "0" ( dest0 ), "1" ( source0 ),
+ "2" ( dest_size )
+ : "eax" );
+}
+
+/**
+ * Finalise big integer
+ *
+ * @v value0 Element 0 of big integer to finalise
+ * @v size Number of elements
+ * @v out Output buffer
+ * @v len Length of output buffer
+ */
+static inline __attribute__ (( always_inline )) void
+bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
+ void *out, size_t len ) {
+ void *discard_D;
+ long discard_c;
+
+ /* Copy raw data in reverse order */
+ __asm__ __volatile__ ( "\n1:\n\t"
+ "movb -1(%2,%1), %%al\n\t"
+ "stosb\n\t"
+ "loop 1b\n\t"
+ : "=&D" ( discard_D ), "=&c" ( discard_c )
+ : "r" ( value0 ), "0" ( out ), "1" ( len )
+ : "eax" );
+}
+
+extern void bigint_multiply_raw ( const uint32_t *multiplicand0,
+ const uint32_t *multiplier0,
+ uint32_t *value0, unsigned int size );
+
+#endif /* _BITS_BIGINT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/linux_api_platform.h b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/linux_api_platform.h
new file mode 100644
index 00000000..4a9ced5e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/linux_api_platform.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_API_PLATFORM_H
+#define _LINUX_API_PLATFORM_H
+
+extern int linux_errno;
+
+#endif /* _LINUX_API_PLATFORM_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/pci_io.h b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/pci_io.h
new file mode 100644
index 00000000..01b12326
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/pci_io.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_PCI_IO_H
+#define _BITS_PCI_IO_H
+
+/** @file
+ *
+ * i386-specific PCI I/O API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/pcibios.h>
+#include <ipxe/pcidirect.h>
+
+#endif /* _BITS_PCI_IO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/string.h b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/string.h
new file mode 100644
index 00000000..f35cdab1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/bits/string.h
@@ -0,0 +1,252 @@
+#ifndef ETHERBOOT_BITS_STRING_H
+#define ETHERBOOT_BITS_STRING_H
+/*
+ * Taken from Linux /usr/include/asm/string.h
+ * All except memcpy, memmove, memset and memcmp removed.
+ *
+ * Non-standard memswap() function added because it saves quite a bit
+ * of code (mbrown@fensystems.co.uk).
+ */
+
+/*
+ * This string-include defines all string functions as inline
+ * functions. Use gcc. It also assumes ds=es=data space, this should be
+ * normal. Most of the string-functions are rather heavily hand-optimized,
+ * see especially strtok,strstr,str[c]spn. They should work, but are not
+ * very easy to understand. Everything is done entirely within the register
+ * set, making the functions fast and clean. String instructions have been
+ * used through-out, making for "slightly" unclear code :-)
+ *
+ * NO Copyright (C) 1991, 1992 Linus Torvalds,
+ * consider these trivial functions to be PD.
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#define __HAVE_ARCH_MEMCPY
+
+extern void * __memcpy ( void *dest, const void *src, size_t len );
+
+#if 0
+static inline __attribute__ (( always_inline )) void *
+__memcpy ( void *dest, const void *src, size_t len ) {
+ int d0, d1, d2;
+ __asm__ __volatile__ ( "rep ; movsb"
+ : "=&c" ( d0 ), "=&S" ( d1 ), "=&D" ( d2 )
+ : "0" ( len ), "1" ( src ), "2" ( dest )
+ : "memory" );
+ return dest;
+}
+#endif
+
+static inline __attribute__ (( always_inline )) void *
+__constant_memcpy ( void *dest, const void *src, size_t len ) {
+ union {
+ uint32_t u32[2];
+ uint16_t u16[4];
+ uint8_t u8[8];
+ } __attribute__ (( __may_alias__ )) *dest_u = dest;
+ const union {
+ uint32_t u32[2];
+ uint16_t u16[4];
+ uint8_t u8[8];
+ } __attribute__ (( __may_alias__ )) *src_u = src;
+ const void *esi;
+ void *edi;
+
+ switch ( len ) {
+ case 0 : /* 0 bytes */
+ return dest;
+ /*
+ * Single-register moves; these are always better than a
+ * string operation. We can clobber an arbitrary two
+ * registers (data, source, dest can re-use source register)
+ * instead of being restricted to esi and edi. There's also a
+ * much greater potential for optimising with nearby code.
+ *
+ */
+ case 1 : /* 4 bytes */
+ dest_u->u8[0] = src_u->u8[0];
+ return dest;
+ case 2 : /* 6 bytes */
+ dest_u->u16[0] = src_u->u16[0];
+ return dest;
+ case 4 : /* 4 bytes */
+ dest_u->u32[0] = src_u->u32[0];
+ return dest;
+ /*
+ * Double-register moves; these are probably still a win.
+ *
+ */
+ case 3 : /* 12 bytes */
+ dest_u->u16[0] = src_u->u16[0];
+ dest_u->u8[2] = src_u->u8[2];
+ return dest;
+ case 5 : /* 10 bytes */
+ dest_u->u32[0] = src_u->u32[0];
+ dest_u->u8[4] = src_u->u8[4];
+ return dest;
+ case 6 : /* 12 bytes */
+ dest_u->u32[0] = src_u->u32[0];
+ dest_u->u16[2] = src_u->u16[2];
+ return dest;
+ case 8 : /* 10 bytes */
+ dest_u->u32[0] = src_u->u32[0];
+ dest_u->u32[1] = src_u->u32[1];
+ return dest;
+ }
+
+ /* Even if we have to load up esi and edi ready for a string
+ * operation, we can sometimes save space by using multiple
+ * single-byte "movs" operations instead of loading up ecx and
+ * using "rep movsb".
+ *
+ * "load ecx, rep movsb" is 7 bytes, plus an average of 1 byte
+ * to allow for saving/restoring ecx 50% of the time.
+ *
+ * "movsl" and "movsb" are 1 byte each, "movsw" is two bytes.
+ * (In 16-bit mode, "movsl" is 2 bytes and "movsw" is 1 byte,
+ * but "movsl" moves twice as much data, so it balances out).
+ *
+ * The cutoff point therefore occurs around 26 bytes; the byte
+ * requirements for each method are:
+ *
+ * len 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ * #bytes (ecx) 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8
+ * #bytes (no ecx) 4 5 6 7 5 6 7 8 6 7 8 9 7 8 9 10
+ */
+
+ esi = src;
+ edi = dest;
+
+ if ( len >= 26 )
+ return __memcpy ( dest, src, len );
+
+ if ( len >= 6*4 )
+ __asm__ __volatile__ ( "movsl" : "=&D" ( edi ), "=&S" ( esi )
+ : "0" ( edi ), "1" ( esi ) : "memory" );
+ if ( len >= 5*4 )
+ __asm__ __volatile__ ( "movsl" : "=&D" ( edi ), "=&S" ( esi )
+ : "0" ( edi ), "1" ( esi ) : "memory" );
+ if ( len >= 4*4 )
+ __asm__ __volatile__ ( "movsl" : "=&D" ( edi ), "=&S" ( esi )
+ : "0" ( edi ), "1" ( esi ) : "memory" );
+ if ( len >= 3*4 )
+ __asm__ __volatile__ ( "movsl" : "=&D" ( edi ), "=&S" ( esi )
+ : "0" ( edi ), "1" ( esi ) : "memory" );
+ if ( len >= 2*4 )
+ __asm__ __volatile__ ( "movsl" : "=&D" ( edi ), "=&S" ( esi )
+ : "0" ( edi ), "1" ( esi ) : "memory" );
+ if ( len >= 1*4 )
+ __asm__ __volatile__ ( "movsl" : "=&D" ( edi ), "=&S" ( esi )
+ : "0" ( edi ), "1" ( esi ) : "memory" );
+ if ( ( len % 4 ) >= 2 )
+ __asm__ __volatile__ ( "movsw" : "=&D" ( edi ), "=&S" ( esi )
+ : "0" ( edi ), "1" ( esi ) : "memory" );
+ if ( ( len % 2 ) >= 1 )
+ __asm__ __volatile__ ( "movsb" : "=&D" ( edi ), "=&S" ( esi )
+ : "0" ( edi ), "1" ( esi ) : "memory" );
+
+ return dest;
+}
+
+#define memcpy( dest, src, len ) \
+ ( __builtin_constant_p ( (len) ) ? \
+ __constant_memcpy ( (dest), (src), (len) ) : \
+ __memcpy ( (dest), (src), (len) ) )
+
+#define __HAVE_ARCH_MEMMOVE
+static inline void * memmove(void * dest,const void * src, size_t n)
+{
+int d0, d1, d2;
+if (dest<src)
+__asm__ __volatile__(
+ "cld\n\t"
+ "rep\n\t"
+ "movsb"
+ : "=&c" (d0), "=&S" (d1), "=&D" (d2)
+ :"0" (n),"1" (src),"2" (dest)
+ : "memory");
+else
+__asm__ __volatile__(
+ "std\n\t"
+ "rep\n\t"
+ "movsb\n\t"
+ "cld"
+ : "=&c" (d0), "=&S" (d1), "=&D" (d2)
+ :"0" (n),
+ "1" (n-1+(const char *)src),
+ "2" (n-1+(char *)dest)
+ :"memory");
+return dest;
+}
+
+#define __HAVE_ARCH_MEMSET
+static inline void * memset(void *s, int c,size_t count)
+{
+int d0, d1;
+__asm__ __volatile__(
+ "cld\n\t"
+ "rep\n\t"
+ "stosb"
+ : "=&c" (d0), "=&D" (d1)
+ :"a" (c),"1" (s),"0" (count)
+ :"memory");
+return s;
+}
+
+#define __HAVE_ARCH_MEMSWAP
+static inline void * memswap(void *dest, void *src, size_t n)
+{
+long d0, d1, d2, d3;
+__asm__ __volatile__(
+ "\n1:\t"
+ "movb (%2),%%al\n\t"
+ "xchgb (%1),%%al\n\t"
+ "inc %1\n\t"
+ "stosb\n\t"
+ "loop 1b"
+ : "=&c" (d0), "=&S" (d1), "=&D" (d2), "=&a" (d3)
+ : "0" (n), "1" (src), "2" (dest)
+ : "memory" );
+return dest;
+}
+
+#define __HAVE_ARCH_STRNCMP
+static inline int strncmp(const char * cs,const char * ct,size_t count)
+{
+register int __res;
+int d0, d1, d2;
+__asm__ __volatile__(
+ "1:\tdecl %3\n\t"
+ "js 2f\n\t"
+ "lodsb\n\t"
+ "scasb\n\t"
+ "jne 3f\n\t"
+ "testb %%al,%%al\n\t"
+ "jne 1b\n"
+ "2:\txorl %%eax,%%eax\n\t"
+ "jmp 4f\n"
+ "3:\tsbbl %%eax,%%eax\n\t"
+ "orb $1,%%al\n"
+ "4:"
+ :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
+ :"1" (cs),"2" (ct),"3" (count));
+return __res;
+}
+
+#define __HAVE_ARCH_STRLEN
+static inline size_t strlen(const char * s)
+{
+int d0;
+register int __res;
+__asm__ __volatile__(
+ "repne\n\t"
+ "scasb\n\t"
+ "notl %0\n\t"
+ "decl %0"
+ :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
+return __res;
+}
+
+#endif /* ETHERBOOT_BITS_STRING_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/include/ipxe/efi/efix86_nap.h b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/ipxe/efi/efix86_nap.h
new file mode 100644
index 00000000..e85a272b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/ipxe/efi/efix86_nap.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_EFIX86_NAP_H
+#define _IPXE_EFIX86_NAP_H
+
+/** @file
+ *
+ * EFI CPU sleeping
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef NAP_EFIX86
+#define NAP_PREFIX_efix86
+#else
+#define NAP_PREFIX_efix86 __efix86_
+#endif
+
+#endif /* _IPXE_EFIX86_NAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/include/ipxe/pcibios.h b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/ipxe/pcibios.h
new file mode 100644
index 00000000..36af7fcd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/ipxe/pcibios.h
@@ -0,0 +1,135 @@
+#ifndef _IPXE_PCIBIOS_H
+#define _IPXE_PCIBIOS_H
+
+#include <stdint.h>
+
+/** @file
+ *
+ * PCI configuration space access via PCI BIOS
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef PCIAPI_PCBIOS
+#define PCIAPI_PREFIX_pcbios
+#else
+#define PCIAPI_PREFIX_pcbios __pcbios_
+#endif
+
+struct pci_device;
+
+#define PCIBIOS_INSTALLATION_CHECK 0xb1010000
+#define PCIBIOS_READ_CONFIG_BYTE 0xb1080000
+#define PCIBIOS_READ_CONFIG_WORD 0xb1090000
+#define PCIBIOS_READ_CONFIG_DWORD 0xb10a0000
+#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b0000
+#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c0000
+#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d0000
+
+extern int pcibios_read ( struct pci_device *pci, uint32_t command,
+ uint32_t *value );
+extern int pcibios_write ( struct pci_device *pci, uint32_t command,
+ uint32_t value );
+
+/**
+ * Read byte from PCI configuration space via PCI BIOS
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_read_config_byte ) ( struct pci_device *pci,
+ unsigned int where,
+ uint8_t *value ) {
+ uint32_t tmp;
+ int rc;
+
+ rc = pcibios_read ( pci, PCIBIOS_READ_CONFIG_BYTE | where, &tmp );
+ *value = tmp;
+ return rc;
+}
+
+/**
+ * Read word from PCI configuration space via PCI BIOS
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_read_config_word ) ( struct pci_device *pci,
+ unsigned int where,
+ uint16_t *value ) {
+ uint32_t tmp;
+ int rc;
+
+ rc = pcibios_read ( pci, PCIBIOS_READ_CONFIG_WORD | where, &tmp );
+ *value = tmp;
+ return rc;
+}
+
+/**
+ * Read dword from PCI configuration space via PCI BIOS
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_read_config_dword ) ( struct pci_device *pci,
+ unsigned int where,
+ uint32_t *value ) {
+ return pcibios_read ( pci, PCIBIOS_READ_CONFIG_DWORD | where, value );
+}
+
+/**
+ * Write byte to PCI configuration space via PCI BIOS
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_write_config_byte ) ( struct pci_device *pci,
+ unsigned int where,
+ uint8_t value ) {
+ return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_BYTE | where, value );
+}
+
+/**
+ * Write word to PCI configuration space via PCI BIOS
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_write_config_word ) ( struct pci_device *pci,
+ unsigned int where,
+ uint16_t value ) {
+ return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_WORD | where, value );
+}
+
+/**
+ * Write dword to PCI configuration space via PCI BIOS
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_write_config_dword ) ( struct pci_device *pci,
+ unsigned int where,
+ uint32_t value ) {
+ return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_DWORD | where, value);
+}
+
+#endif /* _IPXE_PCIBIOS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/include/ipxe/pcidirect.h b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/ipxe/pcidirect.h
new file mode 100644
index 00000000..7fa7c4fa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/ipxe/pcidirect.h
@@ -0,0 +1,141 @@
+#ifndef _PCIDIRECT_H
+#define _PCIDIRECT_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/io.h>
+
+#ifdef PCIAPI_DIRECT
+#define PCIAPI_PREFIX_direct
+#else
+#define PCIAPI_PREFIX_direct __direct_
+#endif
+
+/** @file
+ *
+ * PCI configuration space access via Type 1 accesses
+ *
+ */
+
+#define PCIDIRECT_CONFIG_ADDRESS 0xcf8
+#define PCIDIRECT_CONFIG_DATA 0xcfc
+
+struct pci_device;
+
+extern void pcidirect_prepare ( struct pci_device *pci, int where );
+
+/**
+ * Determine number of PCI buses within system
+ *
+ * @ret num_bus Number of buses
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_num_bus ) ( void ) {
+ /* No way to work this out via Type 1 accesses */
+ return 0x100;
+}
+
+/**
+ * Read byte from PCI configuration space via Type 1 access
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_read_config_byte ) ( struct pci_device *pci,
+ unsigned int where,
+ uint8_t *value ) {
+ pcidirect_prepare ( pci, where );
+ *value = inb ( PCIDIRECT_CONFIG_DATA + ( where & 3 ) );
+ return 0;
+}
+
+/**
+ * Read word from PCI configuration space via Type 1 access
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_read_config_word ) ( struct pci_device *pci,
+ unsigned int where,
+ uint16_t *value ) {
+ pcidirect_prepare ( pci, where );
+ *value = inw ( PCIDIRECT_CONFIG_DATA + ( where & 2 ) );
+ return 0;
+}
+
+/**
+ * Read dword from PCI configuration space via Type 1 access
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_read_config_dword ) ( struct pci_device *pci,
+ unsigned int where,
+ uint32_t *value ) {
+ pcidirect_prepare ( pci, where );
+ *value = inl ( PCIDIRECT_CONFIG_DATA );
+ return 0;
+}
+
+/**
+ * Write byte to PCI configuration space via Type 1 access
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_write_config_byte ) ( struct pci_device *pci,
+ unsigned int where,
+ uint8_t value ) {
+ pcidirect_prepare ( pci, where );
+ outb ( value, PCIDIRECT_CONFIG_DATA + ( where & 3 ) );
+ return 0;
+}
+
+/**
+ * Write word to PCI configuration space via Type 1 access
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_write_config_word ) ( struct pci_device *pci,
+ unsigned int where,
+ uint16_t value ) {
+ pcidirect_prepare ( pci, where );
+ outw ( value, PCIDIRECT_CONFIG_DATA + ( where & 2 ) );
+ return 0;
+}
+
+/**
+ * Write dword to PCI configuration space via Type 1 access
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_write_config_dword ) ( struct pci_device *pci,
+ unsigned int where,
+ uint32_t value ) {
+ pcidirect_prepare ( pci, where );
+ outl ( value, PCIDIRECT_CONFIG_DATA );
+ return 0;
+}
+
+#endif /* _PCIDIRECT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/include/linux/ipxe/dhcp_arch.h b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/linux/ipxe/dhcp_arch.h
new file mode 100644
index 00000000..e83fd9d8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/linux/ipxe/dhcp_arch.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _LINUX_DHCP_ARCH_H
+#define _LINUX_DHCP_ARCH_H
+
+/** @file
+ *
+ * Architecture-specific DHCP options
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <ipxe/dhcp.h>
+
+// Emulate one of the supported arch-platforms
+#include <arch/i386/include/pcbios/ipxe/dhcp_arch.h>
+//#include <arch/i386/include/efi/ipxe/dhcp_arch.h>
+//#include <arch/x86_64/include/efi/ipxe/dhcp_arch.h>
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/include/valgrind/memcheck.h b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/valgrind/memcheck.h
new file mode 100644
index 00000000..46d23432
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/valgrind/memcheck.h
@@ -0,0 +1,309 @@
+
+/*
+ ----------------------------------------------------------------
+
+ Notice that the following BSD-style license applies to this one
+ file (memcheck.h) only. The rest of Valgrind is licensed under the
+ terms of the GNU General Public License, version 2, unless
+ otherwise indicated. See the COPYING file in the source
+ distribution for details.
+
+ ----------------------------------------------------------------
+
+ This file is part of MemCheck, a heavyweight Valgrind tool for
+ detecting memory errors.
+
+ Copyright (C) 2000-2010 Julian Seward. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. The origin of this software must not be misrepresented; you must
+ not claim that you wrote the original software. If you use this
+ software in a product, an acknowledgment in the product
+ documentation would be appreciated but is not required.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ----------------------------------------------------------------
+
+ Notice that the above BSD-style license applies to this one file
+ (memcheck.h) only. The entire rest of Valgrind is licensed under
+ the terms of the GNU General Public License, version 2. See the
+ COPYING file in the source distribution for details.
+
+ ----------------------------------------------------------------
+*/
+
+
+#ifndef __MEMCHECK_H
+#define __MEMCHECK_H
+
+
+/* This file is for inclusion into client (your!) code.
+
+ You can use these macros to manipulate and query memory permissions
+ inside your own programs.
+
+ See comment near the top of valgrind.h on how to use them.
+*/
+
+#include "valgrind.h"
+
+/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
+ This enum comprises an ABI exported by Valgrind to programs
+ which use client requests. DO NOT CHANGE THE ORDER OF THESE
+ ENTRIES, NOR DELETE ANY -- add new ones at the end. */
+typedef
+ enum {
+ VG_USERREQ__MAKE_MEM_NOACCESS = VG_USERREQ_TOOL_BASE('M','C'),
+ VG_USERREQ__MAKE_MEM_UNDEFINED,
+ VG_USERREQ__MAKE_MEM_DEFINED,
+ VG_USERREQ__DISCARD,
+ VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE,
+ VG_USERREQ__CHECK_MEM_IS_DEFINED,
+ VG_USERREQ__DO_LEAK_CHECK,
+ VG_USERREQ__COUNT_LEAKS,
+
+ VG_USERREQ__GET_VBITS,
+ VG_USERREQ__SET_VBITS,
+
+ VG_USERREQ__CREATE_BLOCK,
+
+ VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE,
+
+ /* Not next to VG_USERREQ__COUNT_LEAKS because it was added later. */
+ VG_USERREQ__COUNT_LEAK_BLOCKS,
+
+ /* This is just for memcheck's internal use - don't use it */
+ _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR
+ = VG_USERREQ_TOOL_BASE('M','C') + 256
+ } Vg_MemCheckClientRequest;
+
+
+
+/* Client-code macros to manipulate the state of memory. */
+
+/* Mark memory at _qzz_addr as unaddressable for _qzz_len bytes. */
+#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr,_qzz_len) \
+ (__extension__({unsigned long _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \
+ VG_USERREQ__MAKE_MEM_NOACCESS, \
+ _qzz_addr, _qzz_len, 0, 0, 0); \
+ _qzz_res; \
+ }))
+
+/* Similarly, mark memory at _qzz_addr as addressable but undefined
+ for _qzz_len bytes. */
+#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr,_qzz_len) \
+ (__extension__({unsigned long _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \
+ VG_USERREQ__MAKE_MEM_UNDEFINED, \
+ _qzz_addr, _qzz_len, 0, 0, 0); \
+ _qzz_res; \
+ }))
+
+/* Similarly, mark memory at _qzz_addr as addressable and defined
+ for _qzz_len bytes. */
+#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr,_qzz_len) \
+ (__extension__({unsigned long _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \
+ VG_USERREQ__MAKE_MEM_DEFINED, \
+ _qzz_addr, _qzz_len, 0, 0, 0); \
+ _qzz_res; \
+ }))
+
+/* Similar to VALGRIND_MAKE_MEM_DEFINED except that addressability is
+ not altered: bytes which are addressable are marked as defined,
+ but those which are not addressable are left unchanged. */
+#define VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(_qzz_addr,_qzz_len) \
+ (__extension__({unsigned long _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \
+ VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE, \
+ _qzz_addr, _qzz_len, 0, 0, 0); \
+ _qzz_res; \
+ }))
+
+/* Create a block-description handle. The description is an ascii
+ string which is included in any messages pertaining to addresses
+ within the specified memory range. Has no other effect on the
+ properties of the memory range. */
+#define VALGRIND_CREATE_BLOCK(_qzz_addr,_qzz_len, _qzz_desc) \
+ (__extension__({unsigned long _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \
+ VG_USERREQ__CREATE_BLOCK, \
+ _qzz_addr, _qzz_len, _qzz_desc, \
+ 0, 0); \
+ _qzz_res; \
+ }))
+
+/* Discard a block-description-handle. Returns 1 for an
+ invalid handle, 0 for a valid handle. */
+#define VALGRIND_DISCARD(_qzz_blkindex) \
+ (__extension__ ({unsigned long _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \
+ VG_USERREQ__DISCARD, \
+ 0, _qzz_blkindex, 0, 0, 0); \
+ _qzz_res; \
+ }))
+
+
+/* Client-code macros to check the state of memory. */
+
+/* Check that memory at _qzz_addr is addressable for _qzz_len bytes.
+ If suitable addressibility is not established, Valgrind prints an
+ error message and returns the address of the first offending byte.
+ Otherwise it returns zero. */
+#define VALGRIND_CHECK_MEM_IS_ADDRESSABLE(_qzz_addr,_qzz_len) \
+ (__extension__({unsigned long _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE,\
+ _qzz_addr, _qzz_len, 0, 0, 0); \
+ _qzz_res; \
+ }))
+
+/* Check that memory at _qzz_addr is addressable and defined for
+ _qzz_len bytes. If suitable addressibility and definedness are not
+ established, Valgrind prints an error message and returns the
+ address of the first offending byte. Otherwise it returns zero. */
+#define VALGRIND_CHECK_MEM_IS_DEFINED(_qzz_addr,_qzz_len) \
+ (__extension__({unsigned long _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__CHECK_MEM_IS_DEFINED, \
+ _qzz_addr, _qzz_len, 0, 0, 0); \
+ _qzz_res; \
+ }))
+
+/* Use this macro to force the definedness and addressibility of an
+ lvalue to be checked. If suitable addressibility and definedness
+ are not established, Valgrind prints an error message and returns
+ the address of the first offending byte. Otherwise it returns
+ zero. */
+#define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) \
+ VALGRIND_CHECK_MEM_IS_DEFINED( \
+ (volatile unsigned char *)&(__lvalue), \
+ (unsigned long)(sizeof (__lvalue)))
+
+
+/* Do a full memory leak check (like --leak-check=full) mid-execution. */
+#define VALGRIND_DO_LEAK_CHECK \
+ {unsigned long _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__DO_LEAK_CHECK, \
+ 0, 0, 0, 0, 0); \
+ }
+
+/* Do a summary memory leak check (like --leak-check=summary) mid-execution. */
+#define VALGRIND_DO_QUICK_LEAK_CHECK \
+ {unsigned long _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__DO_LEAK_CHECK, \
+ 1, 0, 0, 0, 0); \
+ }
+
+/* Return number of leaked, dubious, reachable and suppressed bytes found by
+ all previous leak checks. They must be lvalues. */
+#define VALGRIND_COUNT_LEAKS(leaked, dubious, reachable, suppressed) \
+ /* For safety on 64-bit platforms we assign the results to private
+ unsigned long variables, then assign these to the lvalues the user
+ specified, which works no matter what type 'leaked', 'dubious', etc
+ are. We also initialise '_qzz_leaked', etc because
+ VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as
+ defined. */ \
+ {unsigned long _qzz_res; \
+ unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \
+ unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__COUNT_LEAKS, \
+ &_qzz_leaked, &_qzz_dubious, \
+ &_qzz_reachable, &_qzz_suppressed, 0); \
+ leaked = _qzz_leaked; \
+ dubious = _qzz_dubious; \
+ reachable = _qzz_reachable; \
+ suppressed = _qzz_suppressed; \
+ }
+
+/* Return number of leaked, dubious, reachable and suppressed bytes found by
+ all previous leak checks. They must be lvalues. */
+#define VALGRIND_COUNT_LEAK_BLOCKS(leaked, dubious, reachable, suppressed) \
+ /* For safety on 64-bit platforms we assign the results to private
+ unsigned long variables, then assign these to the lvalues the user
+ specified, which works no matter what type 'leaked', 'dubious', etc
+ are. We also initialise '_qzz_leaked', etc because
+ VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as
+ defined. */ \
+ {unsigned long _qzz_res; \
+ unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \
+ unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__COUNT_LEAK_BLOCKS, \
+ &_qzz_leaked, &_qzz_dubious, \
+ &_qzz_reachable, &_qzz_suppressed, 0); \
+ leaked = _qzz_leaked; \
+ dubious = _qzz_dubious; \
+ reachable = _qzz_reachable; \
+ suppressed = _qzz_suppressed; \
+ }
+
+
+/* Get the validity data for addresses [zza..zza+zznbytes-1] and copy it
+ into the provided zzvbits array. Return values:
+ 0 if not running on valgrind
+ 1 success
+ 2 [previously indicated unaligned arrays; these are now allowed]
+ 3 if any parts of zzsrc/zzvbits are not addressable.
+ The metadata is not copied in cases 0, 2 or 3 so it should be
+ impossible to segfault your system by using this call.
+*/
+#define VALGRIND_GET_VBITS(zza,zzvbits,zznbytes) \
+ (__extension__({unsigned long _qzz_res; \
+ char* czza = (char*)zza; \
+ char* czzvbits = (char*)zzvbits; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__GET_VBITS, \
+ czza, czzvbits, zznbytes, 0, 0 ); \
+ _qzz_res; \
+ }))
+
+/* Set the validity data for addresses [zza..zza+zznbytes-1], copying it
+ from the provided zzvbits array. Return values:
+ 0 if not running on valgrind
+ 1 success
+ 2 [previously indicated unaligned arrays; these are now allowed]
+ 3 if any parts of zza/zzvbits are not addressable.
+ The metadata is not copied in cases 0, 2 or 3 so it should be
+ impossible to segfault your system by using this call.
+*/
+#define VALGRIND_SET_VBITS(zza,zzvbits,zznbytes) \
+ (__extension__({unsigned int _qzz_res; \
+ char* czza = (char*)zza; \
+ char* czzvbits = (char*)zzvbits; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__SET_VBITS, \
+ czza, czzvbits, zznbytes, 0, 0 ); \
+ _qzz_res; \
+ }))
+
+#endif
+
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/include/valgrind/valgrind.h b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/valgrind/valgrind.h
new file mode 100644
index 00000000..d72754b0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/include/valgrind/valgrind.h
@@ -0,0 +1,4536 @@
+/* -*- c -*-
+ ----------------------------------------------------------------
+
+ Notice that the following BSD-style license applies to this one
+ file (valgrind.h) only. The rest of Valgrind is licensed under the
+ terms of the GNU General Public License, version 2, unless
+ otherwise indicated. See the COPYING file in the source
+ distribution for details.
+
+ ----------------------------------------------------------------
+
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2010 Julian Seward. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. The origin of this software must not be misrepresented; you must
+ not claim that you wrote the original software. If you use this
+ software in a product, an acknowledgment in the product
+ documentation would be appreciated but is not required.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ----------------------------------------------------------------
+
+ Notice that the above BSD-style license applies to this one file
+ (valgrind.h) only. The entire rest of Valgrind is licensed under
+ the terms of the GNU General Public License, version 2. See the
+ COPYING file in the source distribution for details.
+
+ ----------------------------------------------------------------
+*/
+
+
+/* This file is for inclusion into client (your!) code.
+
+ You can use these macros to manipulate and query Valgrind's
+ execution inside your own programs.
+
+ The resulting executables will still run without Valgrind, just a
+ little bit more slowly than they otherwise would, but otherwise
+ unchanged. When not running on valgrind, each client request
+ consumes very few (eg. 7) instructions, so the resulting performance
+ loss is negligible unless you plan to execute client requests
+ millions of times per second. Nevertheless, if that is still a
+ problem, you can compile with the NVALGRIND symbol defined (gcc
+ -DNVALGRIND) so that client requests are not even compiled in. */
+
+#ifndef __VALGRIND_H
+#define __VALGRIND_H
+
+
+/* ------------------------------------------------------------------ */
+/* VERSION NUMBER OF VALGRIND */
+/* ------------------------------------------------------------------ */
+
+/* Specify Valgrind's version number, so that user code can
+ conditionally compile based on our version number. Note that these
+ were introduced at version 3.6 and so do not exist in version 3.5
+ or earlier. The recommended way to use them to check for "version
+ X.Y or later" is (eg)
+
+#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \
+ && (__VALGRIND_MAJOR__ > 3 \
+ || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
+*/
+#define __VALGRIND_MAJOR__ 3
+#define __VALGRIND_MINOR__ 6
+
+
+#include <stdarg.h>
+
+/* Nb: this file might be included in a file compiled with -ansi. So
+ we can't use C++ style "//" comments nor the "asm" keyword (instead
+ use "__asm__"). */
+
+/* Derive some tags indicating what the target platform is. Note
+ that in this file we're using the compiler's CPP symbols for
+ identifying architectures, which are different to the ones we use
+ within the rest of Valgrind. Note, __powerpc__ is active for both
+ 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
+ latter (on Linux, that is).
+
+ Misc note: how to find out what's predefined in gcc by default:
+ gcc -Wp,-dM somefile.c
+*/
+#undef PLAT_ppc64_aix5
+#undef PLAT_ppc32_aix5
+#undef PLAT_x86_darwin
+#undef PLAT_amd64_darwin
+#undef PLAT_x86_linux
+#undef PLAT_amd64_linux
+#undef PLAT_ppc32_linux
+#undef PLAT_ppc64_linux
+#undef PLAT_arm_linux
+
+#if defined(_AIX) && defined(__64BIT__)
+# define PLAT_ppc64_aix5 1
+#elif defined(_AIX) && !defined(__64BIT__)
+# define PLAT_ppc32_aix5 1
+#elif defined(__APPLE__) && defined(__i386__)
+# define PLAT_x86_darwin 1
+#elif defined(__APPLE__) && defined(__x86_64__)
+# define PLAT_amd64_darwin 1
+#elif defined(__linux__) && defined(__i386__)
+# define PLAT_x86_linux 1
+#elif defined(__linux__) && defined(__x86_64__)
+# define PLAT_amd64_linux 1
+#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
+# define PLAT_ppc32_linux 1
+#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
+# define PLAT_ppc64_linux 1
+#elif defined(__linux__) && defined(__arm__)
+# define PLAT_arm_linux 1
+#else
+/* If we're not compiling for our target platform, don't generate
+ any inline asms. */
+# if !defined(NVALGRIND)
+# define NVALGRIND 1
+# endif
+#endif
+
+
+/* ------------------------------------------------------------------ */
+/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
+/* in here of use to end-users -- skip to the next section. */
+/* ------------------------------------------------------------------ */
+
+#if defined(NVALGRIND)
+
+/* Define NVALGRIND to completely remove the Valgrind magic sequence
+ from the compiled code (analogous to NDEBUG's effects on
+ assert()) */
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ { \
+ (_zzq_rlval) = (_zzq_default); \
+ }
+
+#else /* ! NVALGRIND */
+
+/* The following defines the magic code sequences which the JITter
+ spots and handles magically. Don't look too closely at them as
+ they will rot your brain.
+
+ The assembly code sequences for all architectures is in this one
+ file. This is because this file must be stand-alone, and we don't
+ want to have multiple files.
+
+ For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
+ value gets put in the return slot, so that everything works when
+ this is executed not under Valgrind. Args are passed in a memory
+ block, and so there's no intrinsic limit to the number that could
+ be passed, but it's currently five.
+
+ The macro args are:
+ _zzq_rlval result lvalue
+ _zzq_default default value (result returned when running on real CPU)
+ _zzq_request request code
+ _zzq_arg1..5 request params
+
+ The other two macros are used to support function wrapping, and are
+ a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
+ guest's NRADDR pseudo-register and whatever other information is
+ needed to safely run the call original from the wrapper: on
+ ppc64-linux, the R2 value at the divert point is also needed. This
+ information is abstracted into a user-visible type, OrigFn.
+
+ VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
+ guest, but guarantees that the branch instruction will not be
+ redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
+ branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
+ complete inline asm, since it needs to be combined with more magic
+ inline asm stuff to be useful.
+*/
+
+/* ------------------------- x86-{linux,darwin} ---------------- */
+
+#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "roll $3, %%edi ; roll $13, %%edi\n\t" \
+ "roll $29, %%edi ; roll $19, %%edi\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ { volatile unsigned int _zzq_args[6]; \
+ volatile unsigned int _zzq_result; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %EDX = client_request ( %EAX ) */ \
+ "xchgl %%ebx,%%ebx" \
+ : "=d" (_zzq_result) \
+ : "a" (&_zzq_args[0]), "0" (_zzq_default) \
+ : "cc", "memory" \
+ ); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ volatile unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %EAX = guest_NRADDR */ \
+ "xchgl %%ecx,%%ecx" \
+ : "=a" (__addr) \
+ : \
+ : "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_CALL_NOREDIR_EAX \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* call-noredir *%EAX */ \
+ "xchgl %%edx,%%edx\n\t"
+#endif /* PLAT_x86_linux || PLAT_x86_darwin */
+
+/* ------------------------ amd64-{linux,darwin} --------------- */
+
+#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
+
+typedef
+ struct {
+ unsigned long long int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
+ "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ { volatile unsigned long long int _zzq_args[6]; \
+ volatile unsigned long long int _zzq_result; \
+ _zzq_args[0] = (unsigned long long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %RDX = client_request ( %RAX ) */ \
+ "xchgq %%rbx,%%rbx" \
+ : "=d" (_zzq_result) \
+ : "a" (&_zzq_args[0]), "0" (_zzq_default) \
+ : "cc", "memory" \
+ ); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ volatile unsigned long long int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %RAX = guest_NRADDR */ \
+ "xchgq %%rcx,%%rcx" \
+ : "=a" (__addr) \
+ : \
+ : "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_CALL_NOREDIR_RAX \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* call-noredir *%RAX */ \
+ "xchgq %%rdx,%%rdx\n\t"
+#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
+
+/* ------------------------ ppc32-linux ------------------------ */
+
+#if defined(PLAT_ppc32_linux)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
+ "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned int _zzq_args[6]; \
+ unsigned int _zzq_result; \
+ unsigned int* _zzq_ptr; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ _zzq_ptr = _zzq_args; \
+ __asm__ volatile("mr 3,%1\n\t" /*default*/ \
+ "mr 4,%2\n\t" /*ptr*/ \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = client_request ( %R4 ) */ \
+ "or 1,1,1\n\t" \
+ "mr %0,3" /*result*/ \
+ : "=b" (_zzq_result) \
+ : "b" (_zzq_default), "b" (_zzq_ptr) \
+ : "cc", "memory", "r3", "r4"); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR */ \
+ "or 2,2,2\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "cc", "memory", "r3" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+#endif /* PLAT_ppc32_linux */
+
+/* ------------------------ ppc64-linux ------------------------ */
+
+#if defined(PLAT_ppc64_linux)
+
+typedef
+ struct {
+ unsigned long long int nraddr; /* where's the code? */
+ unsigned long long int r2; /* what tocptr do we need? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
+ "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned long long int _zzq_args[6]; \
+ register unsigned long long int _zzq_result __asm__("r3"); \
+ register unsigned long long int* _zzq_ptr __asm__("r4"); \
+ _zzq_args[0] = (unsigned long long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
+ _zzq_ptr = _zzq_args; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = client_request ( %R4 ) */ \
+ "or 1,1,1" \
+ : "=r" (_zzq_result) \
+ : "0" (_zzq_default), "r" (_zzq_ptr) \
+ : "cc", "memory"); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ register unsigned long long int __addr __asm__("r3"); \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR */ \
+ "or 2,2,2" \
+ : "=r" (__addr) \
+ : \
+ : "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR_GPR2 */ \
+ "or 4,4,4" \
+ : "=r" (__addr) \
+ : \
+ : "cc", "memory" \
+ ); \
+ _zzq_orig->r2 = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+
+#endif /* PLAT_ppc64_linux */
+
+/* ------------------------- arm-linux ------------------------- */
+
+#if defined(PLAT_arm_linux)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
+ "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { volatile unsigned int _zzq_args[6]; \
+ volatile unsigned int _zzq_result; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ __asm__ volatile("mov r3, %1\n\t" /*default*/ \
+ "mov r4, %2\n\t" /*ptr*/ \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* R3 = client_request ( R4 ) */ \
+ "orr r10, r10, r10\n\t" \
+ "mov %0, r3" /*result*/ \
+ : "=r" (_zzq_result) \
+ : "r" (_zzq_default), "r" (&_zzq_args[0]) \
+ : "cc","memory", "r3", "r4"); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* R3 = guest_NRADDR */ \
+ "orr r11, r11, r11\n\t" \
+ "mov %0, r3" \
+ : "=r" (__addr) \
+ : \
+ : "cc", "memory", "r3" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R4 */ \
+ "orr r12, r12, r12\n\t"
+
+#endif /* PLAT_arm_linux */
+
+/* ------------------------ ppc32-aix5 ------------------------- */
+
+#if defined(PLAT_ppc32_aix5)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ unsigned int r2; /* what tocptr do we need? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
+ "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned int _zzq_args[7]; \
+ register unsigned int _zzq_result; \
+ register unsigned int* _zzq_ptr; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ _zzq_args[6] = (unsigned int)(_zzq_default); \
+ _zzq_ptr = _zzq_args; \
+ __asm__ volatile("mr 4,%1\n\t" \
+ "lwz 3, 24(4)\n\t" \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = client_request ( %R4 ) */ \
+ "or 1,1,1\n\t" \
+ "mr %0,3" \
+ : "=b" (_zzq_result) \
+ : "b" (_zzq_ptr) \
+ : "r3", "r4", "cc", "memory"); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ register unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR */ \
+ "or 2,2,2\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR_GPR2 */ \
+ "or 4,4,4\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->r2 = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+
+#endif /* PLAT_ppc32_aix5 */
+
+/* ------------------------ ppc64-aix5 ------------------------- */
+
+#if defined(PLAT_ppc64_aix5)
+
+typedef
+ struct {
+ unsigned long long int nraddr; /* where's the code? */
+ unsigned long long int r2; /* what tocptr do we need? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
+ "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned long long int _zzq_args[7]; \
+ register unsigned long long int _zzq_result; \
+ register unsigned long long int* _zzq_ptr; \
+ _zzq_args[0] = (unsigned int long long)(_zzq_request); \
+ _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
+ _zzq_args[6] = (unsigned int long long)(_zzq_default); \
+ _zzq_ptr = _zzq_args; \
+ __asm__ volatile("mr 4,%1\n\t" \
+ "ld 3, 48(4)\n\t" \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = client_request ( %R4 ) */ \
+ "or 1,1,1\n\t" \
+ "mr %0,3" \
+ : "=b" (_zzq_result) \
+ : "b" (_zzq_ptr) \
+ : "r3", "r4", "cc", "memory"); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ register unsigned long long int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR */ \
+ "or 2,2,2\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR_GPR2 */ \
+ "or 4,4,4\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->r2 = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+
+#endif /* PLAT_ppc64_aix5 */
+
+/* Insert assembly code for other platforms here... */
+
+#endif /* NVALGRIND */
+
+
+/* ------------------------------------------------------------------ */
+/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
+/* ugly. It's the least-worst tradeoff I can think of. */
+/* ------------------------------------------------------------------ */
+
+/* This section defines magic (a.k.a appalling-hack) macros for doing
+ guaranteed-no-redirection macros, so as to get from function
+ wrappers to the functions they are wrapping. The whole point is to
+ construct standard call sequences, but to do the call itself with a
+ special no-redirect call pseudo-instruction that the JIT
+ understands and handles specially. This section is long and
+ repetitious, and I can't see a way to make it shorter.
+
+ The naming scheme is as follows:
+
+ CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
+
+ 'W' stands for "word" and 'v' for "void". Hence there are
+ different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
+ and for each, the possibility of returning a word-typed result, or
+ no result.
+*/
+
+/* Use these to write the name of your wrapper. NOTE: duplicates
+ VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
+
+/* Use an extra level of macroisation so as to ensure the soname/fnname
+ args are fully macro-expanded before pasting them together. */
+#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
+
+#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
+ VG_CONCAT4(_vgwZU_,soname,_,fnname)
+
+#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
+ VG_CONCAT4(_vgwZZ_,soname,_,fnname)
+
+/* Use this macro from within a wrapper function to collect the
+ context (address and possibly other info) of the original function.
+ Once you have that you can then use it in one of the CALL_FN_
+ macros. The type of the argument _lval is OrigFn. */
+#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
+
+/* Derivatives of the main macros below, for calling functions
+ returning void. */
+
+#define CALL_FN_v_v(fnptr) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_v(_junk,fnptr); } while (0)
+
+#define CALL_FN_v_W(fnptr, arg1) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
+
+#define CALL_FN_v_WW(fnptr, arg1,arg2) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
+
+#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
+
+#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
+
+#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
+
+#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
+
+#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
+
+/* ------------------------- x86-{linux,darwin} ---------------- */
+
+#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
+
+/* These regs are trashed by the hidden call. No need to mention eax
+ as gcc can already see that, plus causes gcc to bomb. */
+#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
+
+/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
+ long) == 4. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ __asm__ volatile( \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $4, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ __asm__ volatile( \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $8, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ __asm__ volatile( \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $12, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ __asm__ volatile( \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $16, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ __asm__ volatile( \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $20, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ __asm__ volatile( \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $24, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ __asm__ volatile( \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $28, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ __asm__ volatile( \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $32, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ __asm__ volatile( \
+ "pushl 36(%%eax)\n\t" \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $36, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ __asm__ volatile( \
+ "pushl 40(%%eax)\n\t" \
+ "pushl 36(%%eax)\n\t" \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $40, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ __asm__ volatile( \
+ "pushl 44(%%eax)\n\t" \
+ "pushl 40(%%eax)\n\t" \
+ "pushl 36(%%eax)\n\t" \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $44, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ _argvec[12] = (unsigned long)(arg12); \
+ __asm__ volatile( \
+ "pushl 48(%%eax)\n\t" \
+ "pushl 44(%%eax)\n\t" \
+ "pushl 40(%%eax)\n\t" \
+ "pushl 36(%%eax)\n\t" \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $48, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_x86_linux || PLAT_x86_darwin */
+
+/* ------------------------ amd64-{linux,darwin} --------------- */
+
+#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
+
+/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
+ "rdi", "r8", "r9", "r10", "r11"
+
+/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
+ long) == 8. */
+
+/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
+ macros. In order not to trash the stack redzone, we need to drop
+ %rsp by 128 before the hidden call, and restore afterwards. The
+ nastyness is that it is only by luck that the stack still appears
+ to be unwindable during the hidden call - since then the behaviour
+ of any routine using this macro does not match what the CFI data
+ says. Sigh.
+
+ Why is this important? Imagine that a wrapper has a stack
+ allocated local, and passes to the hidden call, a pointer to it.
+ Because gcc does not know about the hidden call, it may allocate
+ that local in the redzone. Unfortunately the hidden call may then
+ trash it before it comes to use it. So we must step clear of the
+ redzone, for the duration of the hidden call, to make it safe.
+
+ Probably the same problem afflicts the other redzone-style ABIs too
+ (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
+ self describing (none of this CFI nonsense) so at least messing
+ with the stack pointer doesn't give a danger of non-unwindable
+ stack. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ "addq $128,%%rsp\n\t" \
+ VALGRIND_CALL_NOREDIR_RAX \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $8, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $16, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $24, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 80(%%rax)\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $32, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 88(%%rax)\n\t" \
+ "pushq 80(%%rax)\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $40, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ _argvec[12] = (unsigned long)(arg12); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 96(%%rax)\n\t" \
+ "pushq 88(%%rax)\n\t" \
+ "pushq 80(%%rax)\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $48, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
+
+/* ------------------------ ppc32-linux ------------------------ */
+
+#if defined(PLAT_ppc32_linux)
+
+/* This is useful for finding out about the on-stack stuff:
+
+ extern int f9 ( int,int,int,int,int,int,int,int,int );
+ extern int f10 ( int,int,int,int,int,int,int,int,int,int );
+ extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
+ extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
+
+ int g9 ( void ) {
+ return f9(11,22,33,44,55,66,77,88,99);
+ }
+ int g10 ( void ) {
+ return f10(11,22,33,44,55,66,77,88,99,110);
+ }
+ int g11 ( void ) {
+ return f11(11,22,33,44,55,66,77,88,99,110,121);
+ }
+ int g12 ( void ) {
+ return f12(11,22,33,44,55,66,77,88,99,110,121,132);
+ }
+*/
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* These CALL_FN_ macros assume that on ppc32-linux,
+ sizeof(unsigned long) == 4. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "addi 1,1,-16\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,8(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "addi 1,1,16\n\t" \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "addi 1,1,-16\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,12(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,8(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "addi 1,1,16\n\t" \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ _argvec[11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "addi 1,1,-32\n\t" \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,16(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,12(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,8(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "addi 1,1,32\n\t" \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ _argvec[11] = (unsigned long)arg11; \
+ _argvec[12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "addi 1,1,-32\n\t" \
+ /* arg12 */ \
+ "lwz 3,48(11)\n\t" \
+ "stw 3,20(1)\n\t" \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,16(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,12(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,8(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "addi 1,1,32\n\t" \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_ppc32_linux */
+
+/* ------------------------ ppc64-linux ------------------------ */
+
+#if defined(PLAT_ppc64_linux)
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
+ long) == 8. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+0]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+1]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+2]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+3]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+4]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+5]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+6]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+7]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+8]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+9]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-128\n\t" /* expand stack frame */ \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ "addi 1,1,128" /* restore frame */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+10]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-128\n\t" /* expand stack frame */ \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ "addi 1,1,128" /* restore frame */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+11]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-144\n\t" /* expand stack frame */ \
+ /* arg11 */ \
+ "ld 3,88(11)\n\t" \
+ "std 3,128(1)\n\t" \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ "addi 1,1,144" /* restore frame */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+12]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ _argvec[2+12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-144\n\t" /* expand stack frame */ \
+ /* arg12 */ \
+ "ld 3,96(11)\n\t" \
+ "std 3,136(1)\n\t" \
+ /* arg11 */ \
+ "ld 3,88(11)\n\t" \
+ "std 3,128(1)\n\t" \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ "addi 1,1,144" /* restore frame */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_ppc64_linux */
+
+/* ------------------------- arm-linux ------------------------- */
+
+#if defined(PLAT_arm_linux)
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
+
+/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
+ long) == 4. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ "mov %0, r0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ __asm__ volatile( \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ "mov %0, r0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ __asm__ volatile( \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ "mov %0, r0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ __asm__ volatile( \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ "mov %0, r0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ __asm__ volatile( \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ __asm__ volatile( \
+ "ldr r0, [%1, #20] \n\t" \
+ "push {r0} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ "add sp, sp, #4 \n\t" \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ __asm__ volatile( \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "push {r0, r1} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ "add sp, sp, #8 \n\t" \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ __asm__ volatile( \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "ldr r2, [%1, #28] \n\t" \
+ "push {r0, r1, r2} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ "add sp, sp, #12 \n\t" \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ __asm__ volatile( \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "ldr r2, [%1, #28] \n\t" \
+ "ldr r3, [%1, #32] \n\t" \
+ "push {r0, r1, r2, r3} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ "add sp, sp, #16 \n\t" \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ __asm__ volatile( \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "ldr r2, [%1, #28] \n\t" \
+ "ldr r3, [%1, #32] \n\t" \
+ "ldr r4, [%1, #36] \n\t" \
+ "push {r0, r1, r2, r3, r4} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ "add sp, sp, #20 \n\t" \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ __asm__ volatile( \
+ "ldr r0, [%1, #40] \n\t" \
+ "push {r0} \n\t" \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "ldr r2, [%1, #28] \n\t" \
+ "ldr r3, [%1, #32] \n\t" \
+ "ldr r4, [%1, #36] \n\t" \
+ "push {r0, r1, r2, r3, r4} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ "add sp, sp, #24 \n\t" \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ __asm__ volatile( \
+ "ldr r0, [%1, #40] \n\t" \
+ "ldr r1, [%1, #44] \n\t" \
+ "push {r0, r1} \n\t" \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "ldr r2, [%1, #28] \n\t" \
+ "ldr r3, [%1, #32] \n\t" \
+ "ldr r4, [%1, #36] \n\t" \
+ "push {r0, r1, r2, r3, r4} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ "add sp, sp, #28 \n\t" \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ _argvec[12] = (unsigned long)(arg12); \
+ __asm__ volatile( \
+ "ldr r0, [%1, #40] \n\t" \
+ "ldr r1, [%1, #44] \n\t" \
+ "ldr r2, [%1, #48] \n\t" \
+ "push {r0, r1, r2} \n\t" \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "ldr r2, [%1, #28] \n\t" \
+ "ldr r3, [%1, #32] \n\t" \
+ "ldr r4, [%1, #36] \n\t" \
+ "push {r0, r1, r2, r3, r4} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ "add sp, sp, #32 \n\t" \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_arm_linux */
+
+/* ------------------------ ppc32-aix5 ------------------------- */
+
+#if defined(PLAT_ppc32_aix5)
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* Expand the stack frame, copying enough info that unwinding
+ still works. Trashes r3. */
+
+#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
+ "addi 1,1,-" #_n_fr "\n\t" \
+ "lwz 3," #_n_fr "(1)\n\t" \
+ "stw 3,0(1)\n\t"
+
+#define VG_CONTRACT_FRAME_BY(_n_fr) \
+ "addi 1,1," #_n_fr "\n\t"
+
+/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
+ long) == 4. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+0]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+1]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+2]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+3]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+4]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+5]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+6]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+7]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+8]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+9]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(64) \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(64) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+10]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(64) \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,60(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(64) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+11]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(72) \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,64(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,60(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(72) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+12]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ _argvec[2+12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(72) \
+ /* arg12 */ \
+ "lwz 3,48(11)\n\t" \
+ "stw 3,68(1)\n\t" \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,64(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,60(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(72) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_ppc32_aix5 */
+
+/* ------------------------ ppc64-aix5 ------------------------- */
+
+#if defined(PLAT_ppc64_aix5)
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* Expand the stack frame, copying enough info that unwinding
+ still works. Trashes r3. */
+
+#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
+ "addi 1,1,-" #_n_fr "\n\t" \
+ "ld 3," #_n_fr "(1)\n\t" \
+ "std 3,0(1)\n\t"
+
+#define VG_CONTRACT_FRAME_BY(_n_fr) \
+ "addi 1,1," #_n_fr "\n\t"
+
+/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
+ long) == 8. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+0]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+1]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+2]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+3]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+4]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+5]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+6]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+7]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+8]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+9]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(128) \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(128) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+10]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(128) \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(128) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+11]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(144) \
+ /* arg11 */ \
+ "ld 3,88(11)\n\t" \
+ "std 3,128(1)\n\t" \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(144) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+12]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ _argvec[2+12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(144) \
+ /* arg12 */ \
+ "ld 3,96(11)\n\t" \
+ "std 3,136(1)\n\t" \
+ /* arg11 */ \
+ "ld 3,88(11)\n\t" \
+ "std 3,128(1)\n\t" \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(144) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_ppc64_aix5 */
+
+
+/* ------------------------------------------------------------------ */
+/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
+/* */
+/* ------------------------------------------------------------------ */
+
+/* Some request codes. There are many more of these, but most are not
+ exposed to end-user view. These are the public ones, all of the
+ form 0x1000 + small_number.
+
+ Core ones are in the range 0x00000000--0x0000ffff. The non-public
+ ones start at 0x2000.
+*/
+
+/* These macros are used by tools -- they must be public, but don't
+ embed them into other programs. */
+#define VG_USERREQ_TOOL_BASE(a,b) \
+ ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
+#define VG_IS_TOOL_USERREQ(a, b, v) \
+ (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
+
+/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
+ This enum comprises an ABI exported by Valgrind to programs
+ which use client requests. DO NOT CHANGE THE ORDER OF THESE
+ ENTRIES, NOR DELETE ANY -- add new ones at the end. */
+typedef
+ enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
+ VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
+
+ /* These allow any function to be called from the simulated
+ CPU but run on the real CPU. Nb: the first arg passed to
+ the function is always the ThreadId of the running
+ thread! So CLIENT_CALL0 actually requires a 1 arg
+ function, etc. */
+ VG_USERREQ__CLIENT_CALL0 = 0x1101,
+ VG_USERREQ__CLIENT_CALL1 = 0x1102,
+ VG_USERREQ__CLIENT_CALL2 = 0x1103,
+ VG_USERREQ__CLIENT_CALL3 = 0x1104,
+
+ /* Can be useful in regression testing suites -- eg. can
+ send Valgrind's output to /dev/null and still count
+ errors. */
+ VG_USERREQ__COUNT_ERRORS = 0x1201,
+
+ /* These are useful and can be interpreted by any tool that
+ tracks malloc() et al, by using vg_replace_malloc.c. */
+ VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
+ VG_USERREQ__FREELIKE_BLOCK = 0x1302,
+ /* Memory pool support. */
+ VG_USERREQ__CREATE_MEMPOOL = 0x1303,
+ VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
+ VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
+ VG_USERREQ__MEMPOOL_FREE = 0x1306,
+ VG_USERREQ__MEMPOOL_TRIM = 0x1307,
+ VG_USERREQ__MOVE_MEMPOOL = 0x1308,
+ VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
+ VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
+
+ /* Allow printfs to valgrind log. */
+ /* The first two pass the va_list argument by value, which
+ assumes it is the same size as or smaller than a UWord,
+ which generally isn't the case. Hence are deprecated.
+ The second two pass the vargs by reference and so are
+ immune to this problem. */
+ /* both :: char* fmt, va_list vargs (DEPRECATED) */
+ VG_USERREQ__PRINTF = 0x1401,
+ VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
+ /* both :: char* fmt, va_list* vargs */
+ VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
+ VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
+
+ /* Stack support. */
+ VG_USERREQ__STACK_REGISTER = 0x1501,
+ VG_USERREQ__STACK_DEREGISTER = 0x1502,
+ VG_USERREQ__STACK_CHANGE = 0x1503,
+
+ /* Wine support */
+ VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601
+ } Vg_ClientRequest;
+
+#if !defined(__GNUC__)
+# define __extension__ /* */
+#endif
+
+/* Returns the number of Valgrinds this code is running under. That
+ is, 0 if running natively, 1 if running under Valgrind, 2 if
+ running under Valgrind which is running under another Valgrind,
+ etc. */
+#define RUNNING_ON_VALGRIND __extension__ \
+ ({unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
+ VG_USERREQ__RUNNING_ON_VALGRIND, \
+ 0, 0, 0, 0, 0); \
+ _qzz_res; \
+ })
+
+
+/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
+ _qzz_len - 1]. Useful if you are debugging a JITter or some such,
+ since it provides a way to make sure valgrind will retranslate the
+ invalidated area. Returns no value. */
+#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__DISCARD_TRANSLATIONS, \
+ _qzz_addr, _qzz_len, 0, 0, 0); \
+ }
+
+
+/* These requests are for getting Valgrind itself to print something.
+ Possibly with a backtrace. This is a really ugly hack. The return value
+ is the number of characters printed, excluding the "**<pid>** " part at the
+ start and the backtrace (if present). */
+
+#if defined(NVALGRIND)
+
+# define VALGRIND_PRINTF(...)
+# define VALGRIND_PRINTF_BACKTRACE(...)
+
+#else /* NVALGRIND */
+
+/* Modern GCC will optimize the static routine out if unused,
+ and unused attribute will shut down warnings about it. */
+static int VALGRIND_PRINTF(const char *format, ...)
+ __attribute__((format(__printf__, 1, 2), __unused__));
+static int
+VALGRIND_PRINTF(const char *format, ...)
+{
+ unsigned long _qzz_res;
+ va_list vargs;
+ va_start(vargs, format);
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
+ VG_USERREQ__PRINTF_VALIST_BY_REF,
+ (unsigned long)format,
+ (unsigned long)&vargs,
+ 0, 0, 0);
+ va_end(vargs);
+ return (int)_qzz_res;
+}
+
+static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
+ __attribute__((format(__printf__, 1, 2), __unused__));
+static int
+VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
+{
+ unsigned long _qzz_res;
+ va_list vargs;
+ va_start(vargs, format);
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
+ VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
+ (unsigned long)format,
+ (unsigned long)&vargs,
+ 0, 0, 0);
+ va_end(vargs);
+ return (int)_qzz_res;
+}
+
+#endif /* NVALGRIND */
+
+
+/* These requests allow control to move from the simulated CPU to the
+ real CPU, calling an arbitary function.
+
+ Note that the current ThreadId is inserted as the first argument.
+ So this call:
+
+ VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
+
+ requires f to have this signature:
+
+ Word f(Word tid, Word arg1, Word arg2)
+
+ where "Word" is a word-sized type.
+
+ Note that these client requests are not entirely reliable. For example,
+ if you call a function with them that subsequently calls printf(),
+ there's a high chance Valgrind will crash. Generally, your prospects of
+ these working are made higher if the called function does not refer to
+ any global variables, and does not refer to any libc or other functions
+ (printf et al). Any kind of entanglement with libc or dynamic linking is
+ likely to have a bad outcome, for tricky reasons which we've grappled
+ with a lot in the past.
+*/
+#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
+ __extension__ \
+ ({unsigned long _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL0, \
+ _qyy_fn, \
+ 0, 0, 0, 0); \
+ _qyy_res; \
+ })
+
+#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
+ __extension__ \
+ ({unsigned long _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL1, \
+ _qyy_fn, \
+ _qyy_arg1, 0, 0, 0); \
+ _qyy_res; \
+ })
+
+#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
+ __extension__ \
+ ({unsigned long _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL2, \
+ _qyy_fn, \
+ _qyy_arg1, _qyy_arg2, 0, 0); \
+ _qyy_res; \
+ })
+
+#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
+ __extension__ \
+ ({unsigned long _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL3, \
+ _qyy_fn, \
+ _qyy_arg1, _qyy_arg2, \
+ _qyy_arg3, 0); \
+ _qyy_res; \
+ })
+
+
+/* Counts the number of errors that have been recorded by a tool. Nb:
+ the tool must record the errors with VG_(maybe_record_error)() or
+ VG_(unique_error)() for them to be counted. */
+#define VALGRIND_COUNT_ERRORS \
+ __extension__ \
+ ({unsigned int _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__COUNT_ERRORS, \
+ 0, 0, 0, 0, 0); \
+ _qyy_res; \
+ })
+
+/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
+ when heap blocks are allocated in order to give accurate results. This
+ happens automatically for the standard allocator functions such as
+ malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
+ delete[], etc.
+
+ But if your program uses a custom allocator, this doesn't automatically
+ happen, and Valgrind will not do as well. For example, if you allocate
+ superblocks with mmap() and then allocates chunks of the superblocks, all
+ Valgrind's observations will be at the mmap() level and it won't know that
+ the chunks should be considered separate entities. In Memcheck's case,
+ that means you probably won't get heap block overrun detection (because
+ there won't be redzones marked as unaddressable) and you definitely won't
+ get any leak detection.
+
+ The following client requests allow a custom allocator to be annotated so
+ that it can be handled accurately by Valgrind.
+
+ VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
+ by a malloc()-like function. For Memcheck (an illustrative case), this
+ does two things:
+
+ - It records that the block has been allocated. This means any addresses
+ within the block mentioned in error messages will be
+ identified as belonging to the block. It also means that if the block
+ isn't freed it will be detected by the leak checker.
+
+ - It marks the block as being addressable and undefined (if 'is_zeroed' is
+ not set), or addressable and defined (if 'is_zeroed' is set). This
+ controls how accesses to the block by the program are handled.
+
+ 'addr' is the start of the usable block (ie. after any
+ redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
+ can apply redzones -- these are blocks of padding at the start and end of
+ each block. Adding redzones is recommended as it makes it much more likely
+ Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
+ zeroed (or filled with another predictable value), as is the case for
+ calloc().
+
+ VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
+ heap block -- that will be used by the client program -- is allocated.
+ It's best to put it at the outermost level of the allocator if possible;
+ for example, if you have a function my_alloc() which calls
+ internal_alloc(), and the client request is put inside internal_alloc(),
+ stack traces relating to the heap block will contain entries for both
+ my_alloc() and internal_alloc(), which is probably not what you want.
+
+ For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
+ custom blocks from within a heap block, B, that has been allocated with
+ malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
+ -- the custom blocks will take precedence.
+
+ VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
+ Memcheck, it does two things:
+
+ - It records that the block has been deallocated. This assumes that the
+ block was annotated as having been allocated via
+ VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
+
+ - It marks the block as being unaddressable.
+
+ VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
+ heap block is deallocated.
+
+ In many cases, these two client requests will not be enough to get your
+ allocator working well with Memcheck. More specifically, if your allocator
+ writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
+ will be necessary to mark the memory as addressable just before the zeroing
+ occurs, otherwise you'll get a lot of invalid write errors. For example,
+ you'll need to do this if your allocator recycles freed blocks, but it
+ zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
+ Alternatively, if your allocator reuses freed blocks for allocator-internal
+ data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
+
+ Really, what's happening is a blurring of the lines between the client
+ program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
+ memory should be considered unaddressable to the client program, but the
+ allocator knows more than the rest of the client program and so may be able
+ to safely access it. Extra client requests are necessary for Valgrind to
+ understand the distinction between the allocator and the rest of the
+ program.
+
+ Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
+ has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
+
+ Ignored if addr == 0.
+*/
+#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
+ {unsigned int __unused _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MALLOCLIKE_BLOCK, \
+ addr, sizeB, rzB, is_zeroed, 0); \
+ }
+
+/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
+ Ignored if addr == 0.
+*/
+#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
+ {unsigned int __unused _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__FREELIKE_BLOCK, \
+ addr, rzB, 0, 0, 0); \
+ }
+
+/* Create a memory pool. */
+#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__CREATE_MEMPOOL, \
+ pool, rzB, is_zeroed, 0, 0); \
+ }
+
+/* Destroy a memory pool. */
+#define VALGRIND_DESTROY_MEMPOOL(pool) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__DESTROY_MEMPOOL, \
+ pool, 0, 0, 0, 0); \
+ }
+
+/* Associate a piece of memory with a memory pool. */
+#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_ALLOC, \
+ pool, addr, size, 0, 0); \
+ }
+
+/* Disassociate a piece of memory from a memory pool. */
+#define VALGRIND_MEMPOOL_FREE(pool, addr) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_FREE, \
+ pool, addr, 0, 0, 0); \
+ }
+
+/* Disassociate any pieces outside a particular range. */
+#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_TRIM, \
+ pool, addr, size, 0, 0); \
+ }
+
+/* Resize and/or move a piece associated with a memory pool. */
+#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MOVE_MEMPOOL, \
+ poolA, poolB, 0, 0, 0); \
+ }
+
+/* Resize and/or move a piece associated with a memory pool. */
+#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_CHANGE, \
+ pool, addrA, addrB, size, 0); \
+ }
+
+/* Return 1 if a mempool exists, else 0. */
+#define VALGRIND_MEMPOOL_EXISTS(pool) \
+ __extension__ \
+ ({unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_EXISTS, \
+ pool, 0, 0, 0, 0); \
+ _qzz_res; \
+ })
+
+/* Mark a piece of memory as being a stack. Returns a stack id. */
+#define VALGRIND_STACK_REGISTER(start, end) \
+ __extension__ \
+ ({unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__STACK_REGISTER, \
+ start, end, 0, 0, 0); \
+ _qzz_res; \
+ })
+
+/* Unmark the piece of memory associated with a stack id as being a
+ stack. */
+#define VALGRIND_STACK_DEREGISTER(id) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__STACK_DEREGISTER, \
+ id, 0, 0, 0, 0); \
+ }
+
+/* Change the start and end address of the stack id. */
+#define VALGRIND_STACK_CHANGE(id, start, end) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__STACK_CHANGE, \
+ id, start, end, 0, 0); \
+ }
+
+/* Load PDB debug info for Wine PE image_map. */
+#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__LOAD_PDB_DEBUGINFO, \
+ fd, ptr, total_size, delta, 0); \
+ }
+
+
+#undef PLAT_x86_linux
+#undef PLAT_amd64_linux
+#undef PLAT_ppc32_linux
+#undef PLAT_ppc64_linux
+#undef PLAT_arm_linux
+#undef PLAT_ppc32_aix5
+#undef PLAT_ppc64_aix5
+
+#endif /* __VALGRIND_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/interface/efi/efix86_nap.c b/src/VBox/Devices/PC/ipxe/src/arch/x86/interface/efi/efix86_nap.c
new file mode 100644
index 00000000..b6bee627
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/interface/efi/efix86_nap.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/nap.h>
+#include <ipxe/efi/efi.h>
+
+/** @file
+ *
+ * iPXE CPU sleeping API for EFI
+ *
+ */
+
+/**
+ * Sleep until next interrupt
+ *
+ */
+static void efix86_cpu_nap ( void ) {
+ /*
+ * I can't find any EFI API that allows us to put the CPU to
+ * sleep. The CpuSleep() function is defined in CpuLib.h, but
+ * isn't part of any exposed protocol so we have no way to
+ * call it.
+ *
+ * The EFI shell doesn't seem to bother sleeping the CPU; it
+ * just sits there idly burning power.
+ *
+ */
+ __asm__ __volatile__ ( "hlt" );
+}
+
+PROVIDE_NAP ( efix86, cpu_nap, efix86_cpu_nap );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/prefix/efidrvprefix.c b/src/VBox/Devices/PC/ipxe/src/arch/x86/prefix/efidrvprefix.c
new file mode 100644
index 00000000..a96c5c43
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/prefix/efidrvprefix.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <ipxe/init.h>
+#include <ipxe/efi/efi.h>
+
+/**
+ * EFI entry point
+ *
+ * @v image_handle Image handle
+ * @v systab System table
+ * @ret efirc EFI return status code
+ */
+EFI_STATUS EFIAPI _efidrv_start ( EFI_HANDLE image_handle,
+ EFI_SYSTEM_TABLE *systab ) {
+ EFI_STATUS efirc;
+
+ /* Initialise EFI environment */
+ if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 )
+ return efirc;
+
+ /* Initialise iPXE environment */
+ initialise();
+ startup();
+
+ return 0;
+}
+
+REQUIRE_OBJECT ( efi_snp );
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/prefix/efiprefix.c b/src/VBox/Devices/PC/ipxe/src/arch/x86/prefix/efiprefix.c
new file mode 100644
index 00000000..1515c6fc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/prefix/efiprefix.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <ipxe/efi/efi.h>
+
+/**
+ * EFI entry point
+ *
+ * @v image_handle Image handle
+ * @v systab System table
+ * @ret efirc EFI return status code
+ */
+EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle,
+ EFI_SYSTEM_TABLE *systab ) {
+ EFI_STATUS efirc;
+
+ /* Initialise EFI environment */
+ if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 )
+ return efirc;
+
+ /* Call to main() */
+ return RC_TO_EFIRC ( main () );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86/scripts/efi.lds b/src/VBox/Devices/PC/ipxe/src/arch/x86/scripts/efi.lds
new file mode 100644
index 00000000..1a16c29b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86/scripts/efi.lds
@@ -0,0 +1,108 @@
+/* -*- sh -*- */
+
+/*
+ * Linker script for EFI images
+ *
+ */
+
+SECTIONS {
+
+ /* The file starts at a virtual address of zero, and sections are
+ * contiguous. Each section is aligned to at least _max_align,
+ * which defaults to 32. Load addresses are equal to virtual
+ * addresses.
+ */
+
+ _max_align = 32;
+
+ /* Allow plenty of space for file headers */
+ . = 0x1000;
+
+ /*
+ * The text section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .text : {
+ _text = .;
+ *(.text)
+ *(.text.*)
+ _etext = .;
+ }
+
+ /*
+ * The rodata section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .rodata : {
+ _rodata = .;
+ *(.rodata)
+ *(.rodata.*)
+ _erodata = .;
+ }
+
+ /*
+ * The data section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .data : {
+ _data = .;
+ *(.data)
+ *(.data.*)
+ KEEP(*(SORT(.tbl.*))) /* Various tables. See include/tables.h */
+ _edata = .;
+ }
+
+ /*
+ * The bss section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .bss : {
+ _bss = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ _ebss = .;
+ }
+
+ /*
+ * Weak symbols that need zero values if not otherwise defined
+ *
+ */
+
+ .weak 0x0 : {
+ _weak = .;
+ *(.weak)
+ *(.weak.*)
+ _eweak = .;
+ }
+ _assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
+
+ /*
+ * Dispose of the comment and note sections to make the link map
+ * easier to read
+ *
+ */
+
+ /DISCARD/ : {
+ *(.comment)
+ *(.comment.*)
+ *(.note)
+ *(.note.*)
+ *(.eh_frame)
+ *(.eh_frame.*)
+ *(.rel)
+ *(.rel.*)
+ *(.einfo)
+ *(.einfo.*)
+ *(.discard)
+ *(.discard.*)
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/Makefile b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/Makefile
new file mode 100644
index 00000000..d2c2ff53
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/Makefile
@@ -0,0 +1,41 @@
+# Code size reduction.
+#
+CFLAGS += -fstrength-reduce -fomit-frame-pointer
+
+# Code size reduction. gcc3 needs a different syntax to gcc2 if you
+# want to avoid spurious warnings.
+#
+CFLAGS += -falign-jumps=1 -falign-loops=1 -falign-functions=1
+
+# Use %rip-relative addressing wherever possible.
+#
+CFLAGS += -fpie
+
+# Force 64-bit code
+#
+CFLAGS += -m64
+ASFLAGS += --64
+LDFLAGS += -m elf_x86_64
+
+# EFI requires -fshort-wchar, and nothing else currently uses wchar_t
+#
+CFLAGS += -fshort-wchar
+
+# We need to undefine the default macro "i386" when compiling .S
+# files, otherwise ".arch i386" translates to ".arch 1"...
+#
+CFLAGS += -Ui386
+
+# x86_64-specific directories containing source files
+#
+SRCDIRS += arch/x86_64/prefix
+
+# Include common x86 Makefile
+#
+MAKEDEPS += arch/x86/Makefile
+include arch/x86/Makefile
+
+# Include platform-specific Makefile
+#
+MAKEDEPS += arch/x86_64/Makefile.$(PLATFORM)
+include arch/x86_64/Makefile.$(PLATFORM)
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/Makefile.efi b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/Makefile.efi
new file mode 100644
index 00000000..26b71278
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/Makefile.efi
@@ -0,0 +1,14 @@
+# -*- makefile -*- : Force emacs to use Makefile mode
+
+# EFI probably doesn't guarantee us a red zone, so let's not rely on it.
+#
+CFLAGS += -mno-red-zone
+
+# Specify EFI image builder
+#
+ELF2EFI = $(ELF2EFI64)
+
+# Include generic EFI Makefile
+#
+MAKEDEPS += arch/x86/Makefile.efi
+include arch/x86/Makefile.efi
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/Makefile.linux b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/Makefile.linux
new file mode 100644
index 00000000..154f9d40
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/Makefile.linux
@@ -0,0 +1,6 @@
+LDSCRIPT = arch/x86_64/scripts/linux.lds
+
+SRCDIRS += arch/x86_64/core/linux
+
+MAKEDEPS += arch/x86/Makefile.linux
+include arch/x86/Makefile.linux
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/core/linux/linux_syscall.S b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/core/linux/linux_syscall.S
new file mode 100644
index 00000000..d2805f94
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/core/linux/linux_syscall.S
@@ -0,0 +1,33 @@
+
+ .section ".data"
+ .globl linux_errno
+
+linux_errno: .int 0
+
+ .section ".text"
+ .code64
+ .globl linux_syscall
+ .type linux_syscall, @function
+
+linux_syscall:
+ movq %rdi, %rax // C arg1 -> syscall number
+ movq %rsi, %rdi // C arg2 -> syscall arg1
+ movq %rdx, %rsi // C arg3 -> syscall arg2
+ movq %rcx, %rdx // C arg4 -> syscall arg3
+ movq %r8, %r10 // C arg5 -> syscall arg4
+ movq %r9, %r8 // C arg6 -> syscall arg5
+ movq 8(%rsp), %r9 // C arg7 -> syscall arg6
+
+ syscall
+
+ cmpq $-4095, %rax
+ jae 1f
+ ret
+
+1:
+ negq %rax
+ movl %eax, linux_errno
+ movq $-1, %rax
+ ret
+
+ .size linux_syscall, . - linux_syscall
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/core/linux/linuxprefix.S b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/core/linux/linuxprefix.S
new file mode 100644
index 00000000..ec8a9dec
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/core/linux/linuxprefix.S
@@ -0,0 +1,25 @@
+#include <linux/unistd.h>
+
+ .section ".text"
+ .code64
+ .globl _linux_start
+ .type _linux_start, @function
+
+_linux_start:
+ xorq %rbp, %rbp
+
+ popq %rdi // argc -> C arg1
+ movq %rsp, %rsi // argv -> C arg2
+
+ andq $~15, %rsp // 16-byte align the stack
+
+ call save_args
+
+ /* Our main doesn't use any arguments */
+ call main
+
+ movq %rax, %rdi // rc -> syscall arg1
+ movq $__NR_exit, %rax
+ syscall
+
+ .size _linux_start, . - _linux_start
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/byteswap.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/byteswap.h
new file mode 100644
index 00000000..2e472d98
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/byteswap.h
@@ -0,0 +1,47 @@
+#ifndef _BITS_BYTESWAP_H
+#define _BITS_BYTESWAP_H
+
+/** @file
+ *
+ * Byte-order swapping functions
+ *
+ */
+
+#include <stdint.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+static inline __attribute__ (( always_inline, const )) uint16_t
+__bswap_variable_16 ( uint16_t x ) {
+ __asm__ ( "xchgb %b0,%h0" : "=Q" ( x ) : "0" ( x ) );
+ return x;
+}
+
+static inline __attribute__ (( always_inline )) void
+__bswap_16s ( uint16_t *x ) {
+ __asm__ ( "rorw $8, %0" : "+m" ( *x ) );
+}
+
+static inline __attribute__ (( always_inline, const )) uint32_t
+__bswap_variable_32 ( uint32_t x ) {
+ __asm__ ( "bswapl %k0" : "=r" ( x ) : "0" ( x ) );
+ return x;
+}
+
+static inline __attribute__ (( always_inline )) void
+__bswap_32s ( uint32_t *x ) {
+ __asm__ ( "bswapl %k0" : "=r" ( *x ) : "0" ( *x ) );
+}
+
+static inline __attribute__ (( always_inline, const )) uint64_t
+__bswap_variable_64 ( uint64_t x ) {
+ __asm__ ( "bswapq %q0" : "=r" ( x ) : "0" ( x ) );
+ return x;
+}
+
+static inline __attribute__ (( always_inline )) void
+__bswap_64s ( uint64_t *x ) {
+ __asm__ ( "bswapq %q0" : "=r" ( *x ) : "0" ( *x ) );
+}
+
+#endif /* _BITS_BYTESWAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/compiler.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/compiler.h
new file mode 100644
index 00000000..51a7eaae
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/compiler.h
@@ -0,0 +1,14 @@
+#ifndef _BITS_COMPILER_H
+#define _BITS_COMPILER_H
+
+#ifndef ASSEMBLY
+
+/** Declare a function with standard calling conventions */
+#define __asmcall __attribute__ (( regparm(0) ))
+
+/** Declare a function with libgcc implicit linkage */
+#define __libgcc
+
+#endif /* ASSEMBLY */
+
+#endif /* _BITS_COMPILER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/endian.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/endian.h
new file mode 100644
index 00000000..413e702d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/endian.h
@@ -0,0 +1,6 @@
+#ifndef ETHERBOOT_BITS_ENDIAN_H
+#define ETHERBOOT_BITS_ENDIAN_H
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+#endif /* ETHERBOOT_BITS_ENDIAN_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/entropy.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/entropy.h
new file mode 100644
index 00000000..9c64c833
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/entropy.h
@@ -0,0 +1,12 @@
+#ifndef _BITS_ENTROPY_H
+#define _BITS_ENTROPY_H
+
+/** @file
+ *
+ * x86_64-specific entropy API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#endif /* _BITS_ENTROPY_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/errfile.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/errfile.h
new file mode 100644
index 00000000..dcda26ba
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/errfile.h
@@ -0,0 +1,11 @@
+#ifndef _BITS_ERRFILE_H
+#define _BITS_ERRFILE_H
+
+/**
+ * @addtogroup errfile Error file identifiers
+ * @{
+ */
+
+/** @} */
+
+#endif /* _BITS_ERRFILE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/io.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/io.h
new file mode 100644
index 00000000..921fdcc0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/io.h
@@ -0,0 +1,10 @@
+#ifndef _BITS_IO_H
+#define _BITS_IO_H
+
+/** @file
+ *
+ * x86_64-specific I/O API implementations
+ *
+ */
+
+#endif /* _BITS_IO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/linux_api.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/linux_api.h
new file mode 100644
index 00000000..589fb580
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/linux_api.h
@@ -0,0 +1,6 @@
+#ifndef _X86_64_LINUX_API_H
+#define _X86_64_LINUX_API_H
+
+#define __SYSCALL_mmap __NR_mmap
+
+#endif /* _X86_64_LINUX_API_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/nap.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/nap.h
new file mode 100644
index 00000000..8b42c0a4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/nap.h
@@ -0,0 +1,12 @@
+#ifndef _BITS_NAP_H
+#define _BITS_NAP_H
+
+/** @file
+ *
+ * x86_64-specific CPU sleeping API implementations
+ *
+ */
+
+#include <ipxe/efi/efix86_nap.h>
+
+#endif /* _BITS_MAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/sanboot.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/sanboot.h
new file mode 100644
index 00000000..d33d03cb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/sanboot.h
@@ -0,0 +1,12 @@
+#ifndef _BITS_SANBOOT_H
+#define _BITS_SANBOOT_H
+
+/** @file
+ *
+ * x86_64-specific sanboot API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#endif /* _BITS_SANBOOT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/smbios.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/smbios.h
new file mode 100644
index 00000000..2f0118d0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/smbios.h
@@ -0,0 +1,10 @@
+#ifndef _BITS_SMBIOS_H
+#define _BITS_SMBIOS_H
+
+/** @file
+ *
+ * i386-specific SMBIOS API implementations
+ *
+ */
+
+#endif /* _BITS_SMBIOS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/stdint.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/stdint.h
new file mode 100644
index 00000000..9eb72e9c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/stdint.h
@@ -0,0 +1,21 @@
+#ifndef _BITS_STDINT_H
+#define _BITS_STDINT_H
+
+typedef __SIZE_TYPE__ size_t;
+typedef signed long ssize_t;
+typedef signed long off_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+
+typedef unsigned long physaddr_t;
+typedef unsigned long intptr_t;
+
+#endif /* _BITS_STDINT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/time.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/time.h
new file mode 100644
index 00000000..59b35535
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/time.h
@@ -0,0 +1,12 @@
+#ifndef _BITS_TIME_H
+#define _BITS_TIME_H
+
+/** @file
+ *
+ * x86_64-specific time API implementations
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#endif /* _BITS_TIME_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/timer.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/timer.h
new file mode 100644
index 00000000..dfa6c270
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/timer.h
@@ -0,0 +1,10 @@
+#ifndef _BITS_TIMER_H
+#define _BITS_TIMER_H
+
+/** @file
+ *
+ * x86_64-specific timer API implementations
+ *
+ */
+
+#endif /* _BITS_TIMER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/uaccess.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/uaccess.h
new file mode 100644
index 00000000..45582924
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/uaccess.h
@@ -0,0 +1,10 @@
+#ifndef _BITS_UACCESS_H
+#define _BITS_UACCESS_H
+
+/** @file
+ *
+ * x86_64-specific user access API implementations
+ *
+ */
+
+#endif /* _BITS_UACCESS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/umalloc.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/umalloc.h
new file mode 100644
index 00000000..12bf949d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/bits/umalloc.h
@@ -0,0 +1,10 @@
+#ifndef _BITS_UMALLOC_H
+#define _BITS_UMALLOC_H
+
+/** @file
+ *
+ * x86_64-specific user memory allocation API implementations
+ *
+ */
+
+#endif /* _BITS_UMALLOC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h
new file mode 100644
index 00000000..9a4790fd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _DHCP_ARCH_H
+#define _DHCP_ARCH_H
+
+/** @file
+ *
+ * Architecture-specific DHCP options
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/dhcp.h>
+
+#define DHCP_ARCH_VENDOR_CLASS_ID \
+ DHCP_STRING ( 'P', 'X', 'E', 'C', 'l', 'i', 'e', 'n', 't', ':', \
+ 'A', 'r', 'c', 'h', ':', '0', '0', '0', '0', '9', ':', \
+ 'U', 'N', 'D', 'I', ':', '0', '0', '3', '0', '1', '0' )
+
+#define DHCP_ARCH_CLIENT_ARCHITECTURE \
+ DHCP_WORD ( DHCP_CLIENT_ARCHITECTURE_X86_64 )
+
+#define DHCP_ARCH_CLIENT_NDI DHCP_OPTION ( 1 /* UNDI */ , 3, 10 /* v3.10 */ )
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/gdbmach.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/gdbmach.h
new file mode 100644
index 00000000..fcf8e94e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/gdbmach.h
@@ -0,0 +1,51 @@
+#ifndef GDBMACH_H
+#define GDBMACH_H
+
+/** @file
+ *
+ * GDB architecture specifics
+ *
+ * This file declares functions for manipulating the machine state and
+ * debugging context.
+ *
+ */
+
+#include <stdint.h>
+
+typedef unsigned long gdbreg_t;
+
+/* The register snapshot, this must be in sync with interrupt handler and the
+ * GDB protocol. */
+enum {
+ // STUB: don't expect this to work!
+ GDBMACH_EIP,
+ GDBMACH_EFLAGS,
+ GDBMACH_NREGS,
+ GDBMACH_SIZEOF_REGS = GDBMACH_NREGS * sizeof ( gdbreg_t )
+};
+
+/* Breakpoint types */
+enum {
+ GDBMACH_BPMEM,
+ GDBMACH_BPHW,
+ GDBMACH_WATCH,
+ GDBMACH_RWATCH,
+ GDBMACH_AWATCH,
+};
+
+static inline void gdbmach_set_pc ( gdbreg_t *regs, gdbreg_t pc ) {
+ regs [ GDBMACH_EIP ] = pc;
+}
+
+static inline void gdbmach_set_single_step ( gdbreg_t *regs, int step ) {
+ regs [ GDBMACH_EFLAGS ] &= ~( 1 << 8 ); /* Trace Flag (TF) */
+ regs [ GDBMACH_EFLAGS ] |= ( step << 8 );
+}
+
+static inline void gdbmach_breakpoint ( void ) {
+ __asm__ __volatile__ ( "int $3\n" );
+}
+
+extern int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len, int enable );
+
+#endif /* GDBMACH_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/limits.h b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/limits.h
new file mode 100644
index 00000000..8cf87b47
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/include/limits.h
@@ -0,0 +1,59 @@
+#ifndef LIMITS_H
+#define LIMITS_H 1
+
+/* Number of bits in a `char' */
+#define CHAR_BIT 8
+
+/* Minimum and maximum values a `signed char' can hold */
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX 127
+
+/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
+#define UCHAR_MAX 255
+
+/* Minimum and maximum values a `char' can hold */
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX SCHAR_MAX
+
+/* Minimum and maximum values a `signed short int' can hold */
+#define SHRT_MIN (-32768)
+#define SHRT_MAX 32767
+
+/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */
+#define USHRT_MAX 65535
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MAX 2147483647
+#define INT_MIN (-INT_MAX - 1)
+
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+
+/* Minimum and maximum values a `signed long' can hold */
+#define LONG_MAX 9223372036854775807L
+#define LONG_MIN (-LONG_MAX - 1L)
+
+/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */
+#define ULONG_MAX 18446744073709551615UL
+
+/* Minimum and maximum values a `signed long long' can hold */
+#define LLONG_MAX 9223372036854775807LL
+#define LLONG_MIN (-LONG_MAX - 1LL)
+
+
+/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */
+#define ULLONG_MAX 18446744073709551615ULL
+
+
+#endif /* LIMITS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/arch/x86_64/scripts/linux.lds b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/scripts/linux.lds
new file mode 100644
index 00000000..85e548ff
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/arch/x86_64/scripts/linux.lds
@@ -0,0 +1,102 @@
+/* -*- sh -*- */
+
+/*
+ * Linker script for x86_64 Linux images
+ *
+ */
+
+OUTPUT_FORMAT ( "elf64-x86-64", "elf64-x86-64", "elf64-x86-64" )
+OUTPUT_ARCH ( i386:x86-64 )
+
+SECTIONS {
+ _max_align = 32;
+
+ . = 0x400000;
+
+ /*
+ * The text section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .text : {
+ _text = .;
+ *(.text)
+ *(.text.*)
+ _etext = .;
+ }
+
+ /*
+ * The rodata section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .rodata : {
+ _rodata = .;
+ *(.rodata)
+ *(.rodata.*)
+ _erodata = .;
+ }
+
+ /*
+ * The data section
+ *
+ * Adjust the address for the data segment. We want to adjust up to
+ * the same address within the page on the next page up.
+ */
+
+ . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1));
+ . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+ .data : {
+ _data = .;
+ *(.data)
+ *(.data.*)
+ KEEP(*(SORT(.tbl.*)))
+ _edata = .;
+ }
+
+ /*
+ * The bss section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .bss : {
+ _bss = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ _ebss = .;
+ }
+
+ /*
+ * Weak symbols that need zero values if not otherwise defined
+ *
+ */
+
+ .weak 0x0 : {
+ _weak = .;
+ *(.weak)
+ *(.weak.*)
+ _eweak = .;
+ }
+ _assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
+
+ /*
+ * Dispose of the comment and note sections to make the link map
+ * easier to read
+ *
+ */
+
+ /DISCARD/ : {
+ *(.comment)
+ *(.comment.*)
+ *(.note)
+ *(.note.*)
+ *(.rel)
+ *(.rel.*)
+ *(.discard)
+ *(.discard.*)
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/config/config.c b/src/VBox/Devices/PC/ipxe/src/config/config.c
new file mode 100644
index 00000000..1fcbcd70
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/config.c
@@ -0,0 +1,301 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/general.h>
+#include <config/console.h>
+#include <config/sideband.h>
+
+/** @file
+ *
+ * Configuration options
+ *
+ * This file contains macros that pull various objects into the link
+ * based on definitions in configuration header files. Ideally it
+ * should be the only place in iPXE where one might need to use #ifdef
+ * for compile-time options.
+ *
+ * In the fairly common case where an object should only be considered
+ * for inclusion if the subsystem it depends on is present, its
+ * configuration macros should be placed in a file named
+ * <tt>config_<i>subsystem</i>.c</tt>, where @e subsystem is the
+ * object basename of the main source file for that subsystem. The
+ * build system will pull in that file if @c subsystem.c is included
+ * in the final iPXE executable built.
+ */
+
+/*
+ * Build ID string calculations
+ *
+ */
+#undef XSTR
+#undef STR
+#define XSTR(s) STR(s)
+#define STR(s) #s
+
+#ifdef BUILD_SERIAL
+#include "config/.buildserial.h"
+#define BUILD_SERIAL_STR " #" XSTR(BUILD_SERIAL_NUM)
+#else
+#define BUILD_SERIAL_STR ""
+#endif
+
+#ifdef BUILD_ID
+#define BUILD_ID_STR " " BUILD_ID
+#else
+#define BUILD_ID_STR ""
+#endif
+
+#if defined(BUILD_ID) || defined(BUILD_SERIAL)
+#define BUILD_STRING " [build" BUILD_ID_STR BUILD_SERIAL_STR "]"
+#else
+#define BUILD_STRING ""
+#endif
+
+/*
+ * Drag in all requested console types
+ *
+ */
+
+#ifdef CONSOLE_PCBIOS
+REQUIRE_OBJECT ( bios_console );
+#endif
+#ifdef CONSOLE_SERIAL
+REQUIRE_OBJECT ( serial_console );
+#endif
+#ifdef CONSOLE_DIRECT_VGA
+REQUIRE_OBJECT ( video_subr );
+#endif
+#ifdef CONSOLE_PC_KBD
+REQUIRE_OBJECT ( pc_kbd );
+#endif
+#ifdef CONSOLE_SYSLOG
+REQUIRE_OBJECT ( syslog );
+#endif
+#ifdef CONSOLE_SYSLOGS
+REQUIRE_OBJECT ( syslogs );
+#endif
+#ifdef CONSOLE_EFI
+REQUIRE_OBJECT ( efi_console );
+#endif
+#ifdef CONSOLE_LINUX
+REQUIRE_OBJECT ( linux_console );
+#endif
+#ifdef CONSOLE_VMWARE
+REQUIRE_OBJECT ( vmconsole );
+#endif
+
+/*
+ * Drag in all requested network protocols
+ *
+ */
+#ifdef NET_PROTO_IPV4
+REQUIRE_OBJECT ( ipv4 );
+#endif
+
+/*
+ * Drag in all requested PXE support
+ *
+ */
+#ifdef PXE_MENU
+REQUIRE_OBJECT ( pxemenu );
+#endif
+#ifdef PXE_STACK
+REQUIRE_OBJECT ( pxe_call );
+#endif
+
+/*
+ * Drag in all requested download protocols
+ *
+ */
+#ifdef DOWNLOAD_PROTO_TFTP
+REQUIRE_OBJECT ( tftp );
+#endif
+#ifdef DOWNLOAD_PROTO_HTTP
+REQUIRE_OBJECT ( http );
+#endif
+#ifdef DOWNLOAD_PROTO_HTTPS
+REQUIRE_OBJECT ( https );
+#endif
+#ifdef DOWNLOAD_PROTO_FTP
+REQUIRE_OBJECT ( ftp );
+#endif
+#ifdef DOWNLOAD_PROTO_SLAM
+REQUIRE_OBJECT ( slam );
+#endif
+
+/*
+ * Drag in all requested SAN boot protocols
+ *
+ */
+#ifdef SANBOOT_PROTO_ISCSI
+REQUIRE_OBJECT ( iscsi );
+#endif
+
+/*
+ * Drag in all requested resolvers
+ *
+ */
+#ifdef DNS_RESOLVER
+REQUIRE_OBJECT ( dns );
+#endif
+
+/*
+ * Drag in all requested image formats
+ *
+ */
+#ifdef IMAGE_NBI
+REQUIRE_OBJECT ( nbi );
+#endif
+#ifdef IMAGE_ELF
+REQUIRE_OBJECT ( elfboot );
+#endif
+#ifdef IMAGE_MULTIBOOT
+REQUIRE_OBJECT ( multiboot );
+#endif
+#ifdef IMAGE_PXE
+REQUIRE_OBJECT ( pxe_image );
+#endif
+#ifdef IMAGE_SCRIPT
+REQUIRE_OBJECT ( script );
+#endif
+#ifdef IMAGE_BZIMAGE
+REQUIRE_OBJECT ( bzimage );
+#endif
+#ifdef IMAGE_ELTORITO
+REQUIRE_OBJECT ( eltorito );
+#endif
+#ifdef IMAGE_COMBOOT
+REQUIRE_OBJECT ( comboot );
+REQUIRE_OBJECT ( com32 );
+REQUIRE_OBJECT ( comboot_call );
+REQUIRE_OBJECT ( com32_call );
+REQUIRE_OBJECT ( com32_wrapper );
+REQUIRE_OBJECT ( comboot_resolv );
+#endif
+#ifdef IMAGE_EFI
+REQUIRE_OBJECT ( efi_image );
+#endif
+
+/*
+ * Drag in all requested commands
+ *
+ */
+#ifdef AUTOBOOT_CMD
+REQUIRE_OBJECT ( autoboot_cmd );
+#endif
+#ifdef NVO_CMD
+REQUIRE_OBJECT ( nvo_cmd );
+#endif
+#ifdef CONFIG_CMD
+REQUIRE_OBJECT ( config_cmd );
+#endif
+#ifdef IFMGMT_CMD
+REQUIRE_OBJECT ( ifmgmt_cmd );
+#endif
+/* IWMGMT_CMD is brought in by net80211.c if requested */
+#ifdef ROUTE_CMD
+REQUIRE_OBJECT ( route_cmd );
+#endif
+#ifdef IMAGE_CMD
+REQUIRE_OBJECT ( image_cmd );
+#endif
+#ifdef IMAGE_TRUST_CMD
+REQUIRE_OBJECT ( image_trust_cmd );
+#endif
+#ifdef DHCP_CMD
+REQUIRE_OBJECT ( dhcp_cmd );
+#endif
+#ifdef SANBOOT_CMD
+REQUIRE_OBJECT ( sanboot_cmd );
+#endif
+#ifdef MENU_CMD
+REQUIRE_OBJECT ( menu_cmd );
+#endif
+#ifdef LOGIN_CMD
+REQUIRE_OBJECT ( login_cmd );
+#endif
+#ifdef TIME_CMD
+REQUIRE_OBJECT ( time_cmd );
+#endif
+#ifdef DIGEST_CMD
+REQUIRE_OBJECT ( digest_cmd );
+#endif
+#ifdef PXE_CMD
+REQUIRE_OBJECT ( pxe_cmd );
+#endif
+#ifdef LOTEST_CMD
+REQUIRE_OBJECT ( lotest_cmd );
+#endif
+#ifdef VLAN_CMD
+REQUIRE_OBJECT ( vlan_cmd );
+#endif
+#ifdef REBOOT_CMD
+REQUIRE_OBJECT ( reboot_cmd );
+#endif
+
+/*
+ * Drag in miscellaneous objects
+ *
+ */
+#ifdef NULL_TRAP
+REQUIRE_OBJECT ( nulltrap );
+#endif
+#ifdef GDBSERIAL
+REQUIRE_OBJECT ( gdbidt );
+REQUIRE_OBJECT ( gdbserial );
+REQUIRE_OBJECT ( gdbstub_cmd );
+#endif
+#ifdef GDBUDP
+REQUIRE_OBJECT ( gdbidt );
+REQUIRE_OBJECT ( gdbudp );
+REQUIRE_OBJECT ( gdbstub_cmd );
+#endif
+
+/*
+ * Drag in objects that are always required, but not dragged in via
+ * symbol dependencies.
+ *
+ */
+REQUIRE_OBJECT ( device );
+#ifndef VBOX
+REQUIRE_OBJECT ( embedded );
+#endif
+
+/* linux drivers aren't picked up by the parserom utility so drag them in here */
+#ifdef DRIVERS_LINUX
+REQUIRE_OBJECT ( tap );
+#endif
+
+/*
+ * Drag in relevant sideband entry points
+ */
+#ifdef CONFIG_BOFM
+#ifdef BOFM_EFI
+REQUIRE_OBJECT ( efi_bofm );
+#endif /* BOFM_EFI */
+#endif /* CONFIG_BOFM */
+#ifdef VMWARE_SETTINGS
+REQUIRE_OBJECT ( guestinfo );
+#endif /* VMWARE_SETTINGS */
+
+/*
+ * Drag in selected keyboard map
+ */
+#define REQUIRE_KEYMAP_OBJECT( _map ) REQUIRE_OBJECT ( keymap_ ## _map )
+#define REQUIRE_KEYMAP( _map ) REQUIRE_KEYMAP_OBJECT ( _map )
+REQUIRE_KEYMAP ( KEYBOARD_MAP );
diff --git a/src/VBox/Devices/PC/ipxe/src/config/config_ethernet.c b/src/VBox/Devices/PC/ipxe/src/config/config_ethernet.c
new file mode 100644
index 00000000..6295e2fc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/config_ethernet.c
@@ -0,0 +1,35 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/general.h>
+
+/** @file
+ *
+ * Ethernet configuration options
+ *
+ */
+
+/*
+ * Drag in Ethernet-specific protocols
+ */
+#ifdef SANBOOT_PROTO_AOE
+REQUIRE_OBJECT ( aoe );
+#endif
+#ifdef NET_PROTO_FCOE
+REQUIRE_OBJECT ( fcoe );
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/config/config_fc.c b/src/VBox/Devices/PC/ipxe/src/config/config_fc.c
new file mode 100644
index 00000000..ca6189fe
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/config_fc.c
@@ -0,0 +1,40 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/general.h>
+
+/** @file
+ *
+ * Fibre Channel configuration options
+ *
+ */
+
+/*
+ * Drag in Fibre Channel-specific commands
+ *
+ */
+#ifdef FCMGMT_CMD
+REQUIRE_OBJECT ( fcmgmt_cmd );
+#endif
+
+/*
+ * Drag in Fibre Channel-specific protocols
+ */
+#ifdef SANBOOT_PROTO_FCP
+REQUIRE_OBJECT ( fcp );
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/config/config_infiniband.c b/src/VBox/Devices/PC/ipxe/src/config/config_infiniband.c
new file mode 100644
index 00000000..82bd0147
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/config_infiniband.c
@@ -0,0 +1,32 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/general.h>
+
+/** @file
+ *
+ * Infiniband configuration options
+ *
+ */
+
+/*
+ * Drag in Infiniband-specific protocols
+ */
+#ifdef SANBOOT_PROTO_IB_SRP
+REQUIRE_OBJECT ( ib_srp );
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/config/config_net80211.c b/src/VBox/Devices/PC/ipxe/src/config/config_net80211.c
new file mode 100644
index 00000000..9c199154
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/config_net80211.c
@@ -0,0 +1,59 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/general.h>
+
+/** @file
+ *
+ * 802.11 configuration options
+ *
+ */
+
+/*
+ * Drag in 802.11-specific commands
+ *
+ */
+#ifdef IWMGMT_CMD
+REQUIRE_OBJECT ( iwmgmt_cmd );
+#endif
+
+/*
+ * Drag in 802.11 error message tables
+ *
+ */
+#ifdef ERRMSG_80211
+REQUIRE_OBJECT ( wireless_errors );
+#endif
+
+/*
+ * Drag in 802.11 cryptosystems and handshaking protocols
+ *
+ */
+#ifdef CRYPTO_80211_WEP
+REQUIRE_OBJECT ( wep );
+#endif
+
+#ifdef CRYPTO_80211_WPA2
+#define CRYPTO_80211_WPA
+REQUIRE_OBJECT ( wpa_ccmp );
+#endif
+
+#ifdef CRYPTO_80211_WPA
+REQUIRE_OBJECT ( wpa_psk );
+REQUIRE_OBJECT ( wpa_tkip );
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/config/config_romprefix.c b/src/VBox/Devices/PC/ipxe/src/config/config_romprefix.c
new file mode 100644
index 00000000..6a22f11c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/config_romprefix.c
@@ -0,0 +1,33 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/general.h>
+
+/** @file
+ *
+ * ROM prefix configuration options
+ *
+ */
+
+/*
+ * Provide UNDI loader if PXE stack is requested
+ *
+ */
+#ifdef PXE_STACK
+REQUIRE_OBJECT ( undiloader );
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/config/console.h b/src/VBox/Devices/PC/ipxe/src/config/console.h
new file mode 100644
index 00000000..95c32803
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/console.h
@@ -0,0 +1,31 @@
+#ifndef CONFIG_CONSOLE_H
+#define CONFIG_CONSOLE_H
+
+/** @file
+ *
+ * Console configuration
+ *
+ * These options specify the console types that Etherboot will use for
+ * interaction with the user.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/defaults.h>
+
+//#define CONSOLE_PCBIOS /* Default BIOS console */
+//#define CONSOLE_SERIAL /* Serial port */
+//#define CONSOLE_DIRECT_VGA /* Direct access to VGA card */
+//#define CONSOLE_PC_KBD /* Direct access to PC keyboard */
+//#define CONSOLE_SYSLOG /* Syslog console */
+//#define CONSOLE_SYSLOGS /* Encrypted syslog console */
+//#define CONSOLE_VMWARE /* VMware logfile console */
+
+#define KEYBOARD_MAP us
+
+#define LOG_LEVEL LOG_NONE
+
+#include <config/local/console.h>
+
+#endif /* CONFIG_CONSOLE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/defaults.h b/src/VBox/Devices/PC/ipxe/src/config/defaults.h
new file mode 100644
index 00000000..389c0b07
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/defaults.h
@@ -0,0 +1,10 @@
+#ifndef CONFIG_DEFAULTS_H
+#define CONFIG_DEFAULTS_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#define CONFIG_DEFAULTS(_platform) <config/defaults/_platform.h>
+
+#include CONFIG_DEFAULTS(PLATFORM)
+
+#endif /* CONFIG_DEFAULTS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/defaults/efi.h b/src/VBox/Devices/PC/ipxe/src/config/defaults/efi.h
new file mode 100644
index 00000000..16a44dd5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/defaults/efi.h
@@ -0,0 +1,26 @@
+#ifndef CONFIG_DEFAULTS_EFI_H
+#define CONFIG_DEFAULTS_EFI_H
+
+/** @file
+ *
+ * Configuration defaults for EFI
+ *
+ */
+
+#define UACCESS_EFI
+#define IOAPI_EFI
+#define PCIAPI_EFI
+#define CONSOLE_EFI
+#define TIMER_EFI
+#define NAP_EFIX86
+#define UMALLOC_EFI
+#define SMBIOS_EFI
+#define SANBOOT_NULL
+#define BOFM_EFI
+#define ENTROPY_NULL
+#define TIME_NULL
+
+#define IMAGE_EFI /* EFI image support */
+#define IMAGE_SCRIPT /* iPXE script image support */
+
+#endif /* CONFIG_DEFAULTS_EFI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/defaults/linux.h b/src/VBox/Devices/PC/ipxe/src/config/defaults/linux.h
new file mode 100644
index 00000000..50897560
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/defaults/linux.h
@@ -0,0 +1,24 @@
+#ifndef CONFIG_DEFAULTS_LINUX_H
+#define CONFIG_DEFAULTS_LINUX_H
+
+/** @file
+ *
+ * Configuration defaults for linux
+ *
+ */
+
+#define CONSOLE_LINUX
+#define TIMER_LINUX
+#define UACCESS_LINUX
+#define UMALLOC_LINUX
+#define NAP_LINUX
+#define SMBIOS_LINUX
+#define SANBOOT_NULL
+#define ENTROPY_LINUX
+#define TIME_LINUX
+
+#define DRIVERS_LINUX
+
+#define IMAGE_SCRIPT
+
+#endif /* CONFIG_DEFAULTS_LINUX_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/defaults/pcbios.h b/src/VBox/Devices/PC/ipxe/src/config/defaults/pcbios.h
new file mode 100644
index 00000000..7d03d236
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/defaults/pcbios.h
@@ -0,0 +1,45 @@
+#ifndef CONFIG_DEFAULTS_PCBIOS_H
+#define CONFIG_DEFAULTS_PCBIOS_H
+
+/** @file
+ *
+ * Configuration defaults for PCBIOS
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#define UACCESS_LIBRM
+#define IOAPI_X86
+#define PCIAPI_PCBIOS
+#define TIMER_PCBIOS
+#define CONSOLE_PCBIOS
+#define NAP_PCBIOS
+#define UMALLOC_MEMTOP
+#define SMBIOS_PCBIOS
+#ifndef VBOX
+#define SANBOOT_PCBIOS
+#else
+#undef SANBOOT_PCBIOS
+#endif
+
+#define ENTROPY_RTC
+#define TIME_RTC
+
+#undef IMAGE_ELF /* ELF image support */
+#undef IMAGE_MULTIBOOT /* MultiBoot image support */
+#define IMAGE_PXE /* PXE image support */
+#undef IMAGE_SCRIPT /* iPXE script image support */
+#undef IMAGE_BZIMAGE /* Linux bzImage image support */
+
+#define PXE_STACK /* PXE stack in iPXE - required for PXELINUX */
+#define PXE_MENU /* PXE menu booting */
+
+#undef SANBOOT_PROTO_ISCSI /* iSCSI protocol */
+#undef SANBOOT_PROTO_AOE /* AoE protocol */
+#undef SANBOOT_PROTO_IB_SRP /* Infiniband SCSI RDMA protocol */
+#undef SANBOOT_PROTO_FCP /* Fibre Channel protocol */
+
+#define REBOOT_CMD /* Reboot command */
+
+#endif /* CONFIG_DEFAULTS_PCBIOS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/entropy.h b/src/VBox/Devices/PC/ipxe/src/config/entropy.h
new file mode 100644
index 00000000..7de2f673
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/entropy.h
@@ -0,0 +1,16 @@
+#ifndef CONFIG_ENTROPY_H
+#define CONFIG_ENTROPY_H
+
+/** @file
+ *
+ * Entropy API configuration
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/defaults.h>
+
+#include <config/local/entropy.h>
+
+#endif /* CONFIG_ENTROPY_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/general.h b/src/VBox/Devices/PC/ipxe/src/config/general.h
new file mode 100644
index 00000000..c4aeb16e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/general.h
@@ -0,0 +1,161 @@
+#ifndef CONFIG_GENERAL_H
+#define CONFIG_GENERAL_H
+
+/** @file
+ *
+ * General configuration
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/defaults.h>
+
+/*
+ * Branding
+ *
+ * Vendors may use these strings to add their own branding to iPXE.
+ * PRODUCT_NAME is displayed prior to any iPXE branding in startup
+ * messages, and PRODUCT_SHORT_NAME is used where a brief product
+ * label is required (e.g. in BIOS boot selection menus).
+ *
+ * To minimise end-user confusion, it's probably a good idea to either
+ * make PRODUCT_SHORT_NAME a substring of PRODUCT_NAME or leave it as
+ * "iPXE".
+ *
+ */
+#define PRODUCT_NAME ""
+#define PRODUCT_SHORT_NAME "iPXE"
+
+/*
+ * Timer configuration
+ *
+ */
+#define BANNER_TIMEOUT 20 /* Tenths of a second for which the shell
+ banner should appear */
+
+/*
+ * Network protocols
+ *
+ */
+
+#define NET_PROTO_IPV4 /* IPv4 protocol */
+#undef NET_PROTO_FCOE /* Fibre Channel over Ethernet protocol */
+
+/*
+ * PXE support
+ *
+ */
+//#undef PXE_STACK /* PXE stack in iPXE - you want this! */
+//#undef PXE_MENU /* PXE menu booting */
+
+/*
+ * Download protocols
+ *
+ */
+
+#define DOWNLOAD_PROTO_TFTP /* Trivial File Transfer Protocol */
+#define DOWNLOAD_PROTO_HTTP /* Hypertext Transfer Protocol */
+#undef DOWNLOAD_PROTO_HTTPS /* Secure Hypertext Transfer Protocol */
+#undef DOWNLOAD_PROTO_FTP /* File Transfer Protocol */
+#undef DOWNLOAD_PROTO_SLAM /* Scalable Local Area Multicast */
+
+/*
+ * SAN boot protocols
+ *
+ */
+
+//#undef SANBOOT_PROTO_ISCSI /* iSCSI protocol */
+//#undef SANBOOT_PROTO_AOE /* AoE protocol */
+//#undef SANBOOT_PROTO_IB_SRP /* Infiniband SCSI RDMA protocol */
+//#undef SANBOOT_PROTO_FCP /* Fibre Channel protocol */
+
+/*
+ * 802.11 cryptosystems and handshaking protocols
+ *
+ */
+#undef CRYPTO_80211_WEP /* WEP encryption (deprecated and insecure!) */
+#undef CRYPTO_80211_WPA /* WPA Personal, authenticating with passphrase */
+#undef CRYPTO_80211_WPA2 /* Add support for stronger WPA cryptography */
+
+/*
+ * Name resolution modules
+ *
+ */
+
+#define DNS_RESOLVER /* DNS resolver */
+
+/*
+ * Image types
+ *
+ * Etherboot supports various image formats. Select whichever ones
+ * you want to use.
+ *
+ */
+//#define IMAGE_NBI /* NBI image support */
+//#define IMAGE_ELF /* ELF image support */
+//#define IMAGE_MULTIBOOT /* MultiBoot image support */
+//#define IMAGE_PXE /* PXE image support */
+//#define IMAGE_SCRIPT /* iPXE script image support */
+//#define IMAGE_BZIMAGE /* Linux bzImage image support */
+//#define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */
+//#define IMAGE_EFI /* EFI image support */
+
+/*
+ * Command-line commands to include
+ *
+ */
+#define AUTOBOOT_CMD /* Automatic booting */
+#define NVO_CMD /* Non-volatile option storage commands */
+#define CONFIG_CMD /* Option configuration console */
+#define IFMGMT_CMD /* Interface management commands */
+#undef IWMGMT_CMD /* Wireless interface management commands */
+#undef FCMGMT_CMD /* Fibre Channel management commands */
+#define ROUTE_CMD /* Routing table management commands */
+#define IMAGE_CMD /* Image management commands */
+#define DHCP_CMD /* DHCP management commands */
+#undef SANBOOT_CMD /* SAN boot commands */
+#define MENU_CMD /* Menu commands */
+#define LOGIN_CMD /* Login command */
+//#define TIME_CMD /* Time commands */
+//#define DIGEST_CMD /* Image crypto digest commands */
+//#define LOTEST_CMD /* Loopback testing commands */
+//#define VLAN_CMD /* VLAN commands */
+//#define PXE_CMD /* PXE commands */
+//#define REBOOT_CMD /* Reboot command */
+//#define IMAGE_TRUST_CMD /* Image trust management commands */
+
+/*
+ * ROM-specific options
+ *
+ */
+#undef NONPNP_HOOK_INT19 /* Hook INT19 on non-PnP BIOSes */
+
+/*
+ * Error message tables to include
+ *
+ */
+#undef ERRMSG_80211 /* All 802.11 error descriptions (~3.3kb) */
+
+/*
+ * Obscure configuration options
+ *
+ * You probably don't need to touch these.
+ *
+ */
+
+#define NETDEV_DISCARD_RATE 0 /* Drop every N packets (0=>no drop) */
+#undef BUILD_SERIAL /* Include an automatic build serial
+ * number. Add "bs" to the list of
+ * make targets. For example:
+ * "make bin/rtl8139.dsk bs" */
+#undef BUILD_ID /* Include a custom build ID string,
+ * e.g "test-foo" */
+#undef NULL_TRAP /* Attempt to catch NULL function calls */
+#undef GDBSERIAL /* Remote GDB debugging over serial */
+#undef GDBUDP /* Remote GDB debugging over UDP
+ * (both may be set) */
+
+#include <config/local/general.h>
+
+#endif /* CONFIG_GENERAL_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/ioapi.h b/src/VBox/Devices/PC/ipxe/src/config/ioapi.h
new file mode 100644
index 00000000..ce19c6d7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/ioapi.h
@@ -0,0 +1,19 @@
+#ifndef CONFIG_IOAPI_H
+#define CONFIG_IOAPI_H
+
+/** @file
+ *
+ * I/O API configuration
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/defaults.h>
+
+//#undef PCIAPI_PCBIOS /* Access via PCI BIOS */
+//#define PCIAPI_DIRECT /* Direct access via Type 1 accesses */
+
+#include <config/local/ioapi.h>
+
+#endif /* CONFIG_IOAPI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/isa.h b/src/VBox/Devices/PC/ipxe/src/config/isa.h
new file mode 100644
index 00000000..e2a05050
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/isa.h
@@ -0,0 +1,17 @@
+#ifndef CONFIG_ISA_H
+#define CONFIG_ISA_H
+
+/** @file
+ *
+ * ISA probe address configuration
+ *
+ * You can override the list of addresses that will be probed by any
+ * ISA drivers.
+ *
+ */
+#undef ISA_PROBE_ADDRS /* e.g. 0x200, 0x300 */
+#undef ISA_PROBE_ONLY /* Do not probe any other addresses */
+
+#include <config/local/isa.h>
+
+#endif /* CONFIG_ISA_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/local/console.h b/src/VBox/Devices/PC/ipxe/src/config/local/console.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/local/console.h
diff --git a/src/VBox/Devices/PC/ipxe/src/config/local/entropy.h b/src/VBox/Devices/PC/ipxe/src/config/local/entropy.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/local/entropy.h
diff --git a/src/VBox/Devices/PC/ipxe/src/config/local/general.h b/src/VBox/Devices/PC/ipxe/src/config/local/general.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/local/general.h
diff --git a/src/VBox/Devices/PC/ipxe/src/config/local/ioapi.h b/src/VBox/Devices/PC/ipxe/src/config/local/ioapi.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/local/ioapi.h
diff --git a/src/VBox/Devices/PC/ipxe/src/config/local/nap.h b/src/VBox/Devices/PC/ipxe/src/config/local/nap.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/local/nap.h
diff --git a/src/VBox/Devices/PC/ipxe/src/config/local/sanboot.h b/src/VBox/Devices/PC/ipxe/src/config/local/sanboot.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/local/sanboot.h
diff --git a/src/VBox/Devices/PC/ipxe/src/config/local/serial.h b/src/VBox/Devices/PC/ipxe/src/config/local/serial.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/local/serial.h
diff --git a/src/VBox/Devices/PC/ipxe/src/config/local/time.h b/src/VBox/Devices/PC/ipxe/src/config/local/time.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/local/time.h
diff --git a/src/VBox/Devices/PC/ipxe/src/config/local/timer.h b/src/VBox/Devices/PC/ipxe/src/config/local/timer.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/local/timer.h
diff --git a/src/VBox/Devices/PC/ipxe/src/config/local/umalloc.h b/src/VBox/Devices/PC/ipxe/src/config/local/umalloc.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/local/umalloc.h
diff --git a/src/VBox/Devices/PC/ipxe/src/config/nap.h b/src/VBox/Devices/PC/ipxe/src/config/nap.h
new file mode 100644
index 00000000..187af428
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/nap.h
@@ -0,0 +1,19 @@
+#ifndef CONFIG_NAP_H
+#define CONFIG_NAP_H
+
+/** @file
+ *
+ * CPU sleeping
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/defaults.h>
+
+//#undef NAP_PCBIOS
+//#define NAP_NULL
+
+#include <config/local/nap.h>
+
+#endif /* CONFIG_NAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/sanboot.h b/src/VBox/Devices/PC/ipxe/src/config/sanboot.h
new file mode 100644
index 00000000..1d7f5f17
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/sanboot.h
@@ -0,0 +1,16 @@
+#ifndef CONFIG_SANBOOT_H
+#define CONFIG_SANBOOT_H
+
+/** @file
+ *
+ * sanboot API configuration
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/defaults.h>
+
+#include <config/local/sanboot.h>
+
+#endif /* CONFIG_SANBOOT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/serial.h b/src/VBox/Devices/PC/ipxe/src/config/serial.h
new file mode 100644
index 00000000..8bb9311f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/serial.h
@@ -0,0 +1,37 @@
+#ifndef CONFIG_SERIAL_H
+#define CONFIG_SERIAL_H
+
+/** @file
+ *
+ * Serial port configuration
+ *
+ * These options affect the operation of the serial console. They
+ * take effect only if the serial console is included using the
+ * CONSOLE_SERIAL option.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#define COM1 0x3f8
+#define COM2 0x2f8
+#define COM3 0x3e8
+#define COM4 0x2e8
+
+#define COMCONSOLE COM1 /* I/O port address */
+
+/* Keep settings from a previous user of the serial port (e.g. lilo or
+ * LinuxBIOS), ignoring COMSPEED, COMDATA, COMPARITY and COMSTOP.
+ */
+#undef COMPRESERVE
+
+#ifndef COMPRESERVE
+#define COMSPEED 115200 /* Baud rate */
+#define COMDATA 8 /* Data bits */
+#define COMPARITY 0 /* Parity: 0=None, 1=Odd, 2=Even */
+#define COMSTOP 1 /* Stop bits */
+#endif
+
+#include <config/local/serial.h>
+
+#endif /* CONFIG_SERIAL_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/sideband.h b/src/VBox/Devices/PC/ipxe/src/config/sideband.h
new file mode 100644
index 00000000..a16c2e37
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/sideband.h
@@ -0,0 +1,15 @@
+#ifndef CONFIG_SIDEBAND_H
+#define CONFIG_SIDEBAND_H
+
+/** @file
+ *
+ * Sideband access by platform firmware
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+//#define CONFIG_BOFM /* IBM's BladeCenter Open Fabric Manager */
+//#define VMWARE_SETTINGS /* VMware GuestInfo settings */
+
+#endif /* CONFIG_SIDEBAND_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/time.h b/src/VBox/Devices/PC/ipxe/src/config/time.h
new file mode 100644
index 00000000..0576211f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/time.h
@@ -0,0 +1,16 @@
+#ifndef CONFIG_TIME_H
+#define CONFIG_TIME_H
+
+/** @file
+ *
+ * Time API configuration
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/defaults.h>
+
+#include <config/local/time.h>
+
+#endif /* CONFIG_TIME_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/timer.h b/src/VBox/Devices/PC/ipxe/src/config/timer.h
new file mode 100644
index 00000000..abd66985
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/timer.h
@@ -0,0 +1,19 @@
+#ifndef CONFIG_TIMER_H
+#define CONFIG_TIMER_H
+
+/** @file
+ *
+ * Timer configuration.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/defaults.h>
+
+//#undef TIMER_PCBIOS
+//#define TIMER_RDTSC
+
+#include <config/local/timer.h>
+
+#endif /* CONFIG_TIMER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/config/umalloc.h b/src/VBox/Devices/PC/ipxe/src/config/umalloc.h
new file mode 100644
index 00000000..245c6b4a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/config/umalloc.h
@@ -0,0 +1,16 @@
+#ifndef CONFIG_UMALLOC_H
+#define CONFIG_UMALLOC_H
+
+/** @file
+ *
+ * User memory allocation API configuration
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/defaults.h>
+
+#include <config/local/umalloc.h>
+
+#endif /* CONFIG_UMALLOC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/core/acpi.c b/src/VBox/Devices/PC/ipxe/src/core/acpi.c
new file mode 100644
index 00000000..223765f7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/acpi.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <ipxe/acpi.h>
+#include <ipxe/interface.h>
+
+/** @file
+ *
+ * ACPI support functions
+ *
+ */
+
+/******************************************************************************
+ *
+ * Utility functions
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Fix up ACPI table checksum
+ *
+ * @v acpi ACPI table header
+ */
+void acpi_fix_checksum ( struct acpi_description_header *acpi ) {
+ unsigned int i = 0;
+ uint8_t sum = 0;
+
+ for ( i = 0 ; i < acpi->length ; i++ ) {
+ sum += *( ( ( uint8_t * ) acpi ) + i );
+ }
+ acpi->checksum -= sum;
+}
+
+/******************************************************************************
+ *
+ * Interface methods
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Describe object in an ACPI table
+ *
+ * @v intf Interface
+ * @v acpi ACPI table
+ * @v len Length of ACPI table
+ * @ret rc Return status code
+ */
+int acpi_describe ( struct interface *intf,
+ struct acpi_description_header *acpi, size_t len ) {
+ struct interface *dest;
+ acpi_describe_TYPE ( void * ) *op =
+ intf_get_dest_op ( intf, acpi_describe, &dest );
+ void *object = intf_object ( dest );
+ int rc;
+
+ if ( op ) {
+ rc = op ( object, acpi, len );
+ } else {
+ /* Default is to fail to describe */
+ rc = -EOPNOTSUPP;
+ }
+
+ intf_put ( dest );
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/ansiesc.c b/src/VBox/Devices/PC/ipxe/src/core/ansiesc.c
new file mode 100644
index 00000000..05bbb869
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/ansiesc.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <assert.h>
+#include <ipxe/ansiesc.h>
+
+/** @file
+ *
+ * ANSI escape sequences
+ *
+ */
+
+/**
+ * Call ANSI escape sequence handler
+ *
+ * @v handlers List of escape sequence handlers
+ * @v function Control function identifier
+ * @v count Parameter count
+ * @v params Parameter list
+ */
+static void ansiesc_call_handler ( struct ansiesc_handler *handlers,
+ unsigned int function, int count,
+ int params[] ) {
+ struct ansiesc_handler *handler;
+
+ for ( handler = handlers ; handler->function ; handler++ ) {
+ if ( handler->function == function ) {
+ handler->handle ( count, params );
+ break;
+ }
+ }
+}
+
+/**
+ * Process character that may be part of ANSI escape sequence
+ *
+ * @v ctx ANSI escape sequence context
+ * @v c Character
+ * @ret c Original character if not part of escape sequence
+ * @ret <0 Character was part of escape sequence
+ *
+ * ANSI escape sequences will be plucked out of the character stream
+ * and interpreted; once complete they will be passed to the
+ * appropriate handler if one exists in this ANSI escape sequence
+ * context.
+ *
+ * In the interests of code size, we are rather liberal about the
+ * sequences we are prepared to accept as valid.
+ */
+int ansiesc_process ( struct ansiesc_context *ctx, int c ) {
+ if ( ctx->count == 0 ) {
+ if ( c == ESC ) {
+ /* First byte of CSI : begin escape sequence */
+ ctx->count = 1;
+ memset ( ctx->params, 0xff, sizeof ( ctx->params ) );
+ ctx->function = 0;
+ return -1;
+ } else {
+ /* Normal character */
+ return c;
+ }
+ } else {
+ if ( c == '[' ) {
+ /* Second byte of CSI : do nothing */
+ } else if ( ( c >= '0' ) && ( c <= '9' ) ) {
+ /* Parameter Byte : part of a parameter value */
+ int *param = &ctx->params[ctx->count - 1];
+ if ( *param < 0 )
+ *param = 0;
+ *param = ( ( *param * 10 ) + ( c - '0' ) );
+ } else if ( c == ';' ) {
+ /* Parameter Byte : parameter delimiter */
+ ctx->count++;
+ if ( ctx->count > ( sizeof ( ctx->params ) /
+ sizeof ( ctx->params[0] ) ) ) {
+ /* Excessive parameters : abort sequence */
+ ctx->count = 0;
+ DBG ( "Too many parameters in ANSI escape "
+ "sequence\n" );
+ }
+ } else if ( ( c >= 0x20 ) && ( c <= 0x2f ) ) {
+ /* Intermediate Byte */
+ ctx->function <<= 8;
+ ctx->function |= c;
+ } else {
+ /* Treat as Final Byte. Zero ctx->count before
+ * calling handler to avoid potential infinite loops.
+ */
+ int count = ctx->count;
+ ctx->count = 0;
+ ctx->function <<= 8;
+ ctx->function |= c;
+ ansiesc_call_handler ( ctx->handlers, ctx->function,
+ count, ctx->params );
+ }
+ return -1;
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/asprintf.c b/src/VBox/Devices/PC/ipxe/src/core/asprintf.c
new file mode 100644
index 00000000..03cf45cf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/asprintf.c
@@ -0,0 +1,49 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Write a formatted string to newly allocated memory.
+ *
+ * @v strp Pointer to hold allocated string
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+int vasprintf ( char **strp, const char *fmt, va_list args ) {
+ size_t len;
+ va_list args_tmp;
+
+ /* Calculate length needed for string */
+ va_copy ( args_tmp, args );
+ len = ( vsnprintf ( NULL, 0, fmt, args_tmp ) + 1 );
+ va_end ( args_tmp );
+
+ /* Allocate and fill string */
+ *strp = malloc ( len );
+ if ( ! *strp )
+ return -ENOMEM;
+ return vsnprintf ( *strp, len, fmt, args );
+}
+
+/**
+ * Write a formatted string to newly allocated memory.
+ *
+ * @v strp Pointer to hold allocated string
+ * @v fmt Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+int asprintf ( char **strp, const char *fmt, ... ) {
+ va_list args;
+ int len;
+
+ va_start ( args, fmt );
+ len = vasprintf ( strp, fmt, args );
+ va_end ( args );
+ return len;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/assert.c b/src/VBox/Devices/PC/ipxe/src/core/assert.c
new file mode 100644
index 00000000..45d3b9b7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/assert.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Assertions
+ *
+ */
+
+#include <assert.h>
+
+/** Number of assertion failures triggered */
+unsigned int assertion_failures = 0;
diff --git a/src/VBox/Devices/PC/ipxe/src/core/base16.c b/src/VBox/Devices/PC/ipxe/src/core/base16.c
new file mode 100644
index 00000000..14de7957
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/base16.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/base16.h>
+
+/** @file
+ *
+ * Base16 encoding
+ *
+ */
+
+/**
+ * Base16-encode data
+ *
+ * @v raw Raw data
+ * @v len Length of raw data
+ * @v encoded Buffer for encoded string
+ *
+ * The buffer must be the correct length for the encoded string. Use
+ * something like
+ *
+ * char buf[ base16_encoded_len ( len ) + 1 ];
+ *
+ * (the +1 is for the terminating NUL) to provide a buffer of the
+ * correct size.
+ */
+void base16_encode ( const uint8_t *raw, size_t len, char *encoded ) {
+ const uint8_t *raw_bytes = raw;
+ char *encoded_bytes = encoded;
+ size_t remaining = len;
+
+ for ( ; remaining-- ; encoded_bytes += 2 ) {
+ sprintf ( encoded_bytes, "%02x", *(raw_bytes++) );
+ }
+
+ DBG ( "Base16-encoded to \"%s\":\n", encoded );
+ DBG_HDA ( 0, raw, len );
+ assert ( strlen ( encoded ) == base16_encoded_len ( len ) );
+}
+
+/**
+ * Base16-decode data
+ *
+ * @v encoded Encoded string
+ * @v raw Raw data
+ * @ret len Length of raw data, or negative error
+ *
+ * The buffer must be large enough to contain the decoded data. Use
+ * something like
+ *
+ * char buf[ base16_decoded_max_len ( encoded ) ];
+ *
+ * to provide a buffer of the correct size.
+ */
+int base16_decode ( const char *encoded, uint8_t *raw ) {
+ const char *encoded_bytes = encoded;
+ uint8_t *raw_bytes = raw;
+ char buf[3];
+ char *endp;
+ size_t len;
+
+ while ( encoded_bytes[0] ) {
+ if ( ! encoded_bytes[1] ) {
+ DBG ( "Base16-encoded string \"%s\" has invalid "
+ "length\n", encoded );
+ return -EINVAL;
+ }
+ memcpy ( buf, encoded_bytes, 2 );
+ buf[2] = '\0';
+ *(raw_bytes++) = strtoul ( buf, &endp, 16 );
+ if ( *endp != '\0' ) {
+ DBG ( "Base16-encoded string \"%s\" has invalid "
+ "byte \"%s\"\n", encoded, buf );
+ return -EINVAL;
+ }
+ encoded_bytes += 2;
+ }
+ len = ( raw_bytes - raw );
+
+ DBG ( "Base16-decoded \"%s\" to:\n", encoded );
+ DBG_HDA ( 0, raw, len );
+ assert ( len <= base16_decoded_max_len ( encoded ) );
+
+ return ( len );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/base64.c b/src/VBox/Devices/PC/ipxe/src/core/base64.c
new file mode 100644
index 00000000..7514c1fa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/base64.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/base64.h>
+
+/** @file
+ *
+ * Base64 encoding
+ *
+ */
+
+static const char base64[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/**
+ * Base64-encode data
+ *
+ * @v raw Raw data
+ * @v len Length of raw data
+ * @v encoded Buffer for encoded string
+ *
+ * The buffer must be the correct length for the encoded string. Use
+ * something like
+ *
+ * char buf[ base64_encoded_len ( len ) + 1 ];
+ *
+ * (the +1 is for the terminating NUL) to provide a buffer of the
+ * correct size.
+ */
+void base64_encode ( const uint8_t *raw, size_t len, char *encoded ) {
+ const uint8_t *raw_bytes = ( ( const uint8_t * ) raw );
+ uint8_t *encoded_bytes = ( ( uint8_t * ) encoded );
+ size_t raw_bit_len = ( 8 * len );
+ unsigned int bit;
+ unsigned int tmp;
+
+ for ( bit = 0 ; bit < raw_bit_len ; bit += 6 ) {
+ tmp = ( ( raw_bytes[ bit / 8 ] << ( bit % 8 ) ) |
+ ( raw_bytes[ bit / 8 + 1 ] >> ( 8 - ( bit % 8 ) ) ) );
+ tmp = ( ( tmp >> 2 ) & 0x3f );
+ *(encoded_bytes++) = base64[tmp];
+ }
+ for ( ; ( bit % 8 ) != 0 ; bit += 6 )
+ *(encoded_bytes++) = '=';
+ *(encoded_bytes++) = '\0';
+
+ DBG ( "Base64-encoded to \"%s\":\n", encoded );
+ DBG_HDA ( 0, raw, len );
+ assert ( strlen ( encoded ) == base64_encoded_len ( len ) );
+}
+
+/**
+ * Base64-decode string
+ *
+ * @v encoded Encoded string
+ * @v raw Raw data
+ * @ret len Length of raw data, or negative error
+ *
+ * The buffer must be large enough to contain the decoded data. Use
+ * something like
+ *
+ * char buf[ base64_decoded_max_len ( encoded ) ];
+ *
+ * to provide a buffer of the correct size.
+ */
+int base64_decode ( const char *encoded, uint8_t *raw ) {
+ const uint8_t *encoded_bytes = ( ( const uint8_t * ) encoded );
+ uint8_t *raw_bytes = ( ( uint8_t * ) raw );
+ uint8_t encoded_byte;
+ char *match;
+ int decoded;
+ unsigned int bit = 0;
+ unsigned int pad_count = 0;
+ size_t len;
+
+ /* Zero the raw data */
+ memset ( raw, 0, base64_decoded_max_len ( encoded ) );
+
+ /* Decode string */
+ while ( ( encoded_byte = *(encoded_bytes++) ) ) {
+
+ /* Ignore whitespace characters */
+ if ( isspace ( encoded_byte ) )
+ continue;
+
+ /* Process pad characters */
+ if ( encoded_byte == '=' ) {
+ if ( pad_count >= 2 ) {
+ DBG ( "Base64-encoded string \"%s\" has too "
+ "many pad characters\n", encoded );
+ return -EINVAL;
+ }
+ pad_count++;
+ bit -= 2; /* unused_bits = ( 2 * pad_count ) */
+ continue;
+ }
+ if ( pad_count ) {
+ DBG ( "Base64-encoded string \"%s\" has invalid pad "
+ "sequence\n", encoded );
+ return -EINVAL;
+ }
+
+ /* Process normal characters */
+ match = strchr ( base64, encoded_byte );
+ if ( ! match ) {
+ DBG ( "Base64-encoded string \"%s\" contains invalid "
+ "character '%c'\n", encoded, encoded_byte );
+ return -EINVAL;
+ }
+ decoded = ( match - base64 );
+
+ /* Add to raw data */
+ decoded <<= 2;
+ raw_bytes[ bit / 8 ] |= ( decoded >> ( bit % 8 ) );
+ raw_bytes[ bit / 8 + 1 ] |= ( decoded << ( 8 - ( bit % 8 ) ) );
+ bit += 6;
+ }
+
+ /* Check that we decoded a whole number of bytes */
+ if ( ( bit % 8 ) != 0 ) {
+ DBG ( "Base64-encoded string \"%s\" has invalid bit length "
+ "%d\n", encoded, bit );
+ return -EINVAL;
+ }
+ len = ( bit / 8 );
+
+ DBG ( "Base64-decoded \"%s\" to:\n", encoded );
+ DBG_HDA ( 0, raw, len );
+ assert ( len <= base64_decoded_max_len ( encoded ) );
+
+ /* Return length in bytes */
+ return ( len );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/basename.c b/src/VBox/Devices/PC/ipxe/src/core/basename.c
new file mode 100644
index 00000000..a481c54f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/basename.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Get base name of path
+ *
+ */
+
+#include <string.h>
+#include <libgen.h>
+
+/**
+ * Return base name from path
+ *
+ * @v path Full path
+ * @ret basename Base name
+ */
+char * basename ( char *path ) {
+ char *basename;
+
+ basename = strrchr ( path, '/' );
+ return ( basename ? ( basename + 1 ) : path );
+}
+
+/**
+ * Return directory name from path
+ *
+ * @v path Full path
+ * @ret dirname Directory name
+ *
+ * Note that this function may modify its argument.
+ */
+char * dirname ( char *path ) {
+ char *separator;
+
+ separator = strrchr ( path, '/' );
+ if ( separator == path ) {
+ return "/";
+ } else if ( separator ) {
+ *separator = 0;
+ return path;
+ } else {
+ return ".";
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/bitmap.c b/src/VBox/Devices/PC/ipxe/src/core/bitmap.c
new file mode 100644
index 00000000..e9b6d904
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/bitmap.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <ipxe/bitmap.h>
+
+/** @file
+ *
+ * Bitmaps for multicast downloads
+ *
+ */
+
+/**
+ * Resize bitmap
+ *
+ * @v bitmap Bitmap
+ * @v new_length New length of bitmap, in bits
+ * @ret rc Return status code
+ */
+int bitmap_resize ( struct bitmap *bitmap, unsigned int new_length ) {
+ unsigned int old_num_blocks;
+ unsigned int new_num_blocks;
+ size_t new_size;
+ bitmap_block_t *new_blocks;
+
+ old_num_blocks = BITMAP_INDEX ( bitmap->length + BITMAP_BLKSIZE - 1 );
+ new_num_blocks = BITMAP_INDEX ( new_length + BITMAP_BLKSIZE - 1 );
+
+ if ( old_num_blocks != new_num_blocks ) {
+ new_size = ( new_num_blocks * sizeof ( bitmap->blocks[0] ) );
+ new_blocks = realloc ( bitmap->blocks, new_size );
+ if ( ! new_blocks ) {
+ DBGC ( bitmap, "Bitmap %p could not resize to %d "
+ "bits\n", bitmap, new_length );
+ return -ENOMEM;
+ }
+ bitmap->blocks = new_blocks;
+ }
+ bitmap->length = new_length;
+
+ while ( old_num_blocks < new_num_blocks ) {
+ bitmap->blocks[old_num_blocks++] = 0;
+ }
+
+ DBGC ( bitmap, "Bitmap %p resized to %d bits\n", bitmap, new_length );
+ return 0;
+}
+
+/**
+ * Test bit in bitmap
+ *
+ * @v bitmap Bitmap
+ * @v bit Bit index
+ * @ret is_set Bit is set
+ */
+int bitmap_test ( struct bitmap *bitmap, unsigned int bit ) {
+ unsigned int index = BITMAP_INDEX ( bit );
+ bitmap_block_t mask = BITMAP_MASK ( bit );
+
+ if ( bit >= bitmap->length )
+ return 0;
+ return ( ( bitmap->blocks[index] & mask ) != 0 );
+}
+
+/**
+ * Set bit in bitmap
+ *
+ * @v bitmap Bitmap
+ * @v bit Bit index
+ */
+void bitmap_set ( struct bitmap *bitmap, unsigned int bit ) {
+ unsigned int index = BITMAP_INDEX ( bit );
+ bitmap_block_t mask = BITMAP_MASK ( bit );
+
+ DBGC ( bitmap, "Bitmap %p setting bit %d\n", bitmap, bit );
+
+ /* Update bitmap */
+ bitmap->blocks[index] |= mask;
+
+ /* Update first gap counter */
+ while ( bitmap_test ( bitmap, bitmap->first_gap ) ) {
+ bitmap->first_gap++;
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/bitops.c b/src/VBox/Devices/PC/ipxe/src/core/bitops.c
new file mode 100644
index 00000000..1bca9e47
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/bitops.c
@@ -0,0 +1,13 @@
+#include <strings.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+int __flsl ( long x ) {
+ unsigned long value = x;
+ int ls = 0;
+
+ for ( ls = 0 ; value ; ls++ ) {
+ value >>= 1;
+ }
+ return ls;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/blockdev.c b/src/VBox/Devices/PC/ipxe/src/core/blockdev.c
new file mode 100644
index 00000000..182765e3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/blockdev.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <ipxe/interface.h>
+#include <ipxe/blockdev.h>
+
+/** @file
+ *
+ * Block devices
+ *
+ */
+
+/**
+ * Read from block device
+ *
+ * @v control Control interface
+ * @v data Data interface
+ * @v lba Starting logical block address
+ * @v count Number of logical blocks
+ * @v buffer Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int block_read ( struct interface *control, struct interface *data,
+ uint64_t lba, unsigned int count,
+ userptr_t buffer, size_t len ) {
+ struct interface *dest;
+ block_read_TYPE ( void * ) *op =
+ intf_get_dest_op ( control, block_read, &dest );
+ void *object = intf_object ( dest );
+ int rc;
+
+ if ( op ) {
+ rc = op ( object, data, lba, count, buffer, len );
+ } else {
+ /* Default is to fail to issue the command */
+ rc = -EOPNOTSUPP;
+ }
+
+ intf_put ( dest );
+ return rc;
+}
+
+/**
+ * Write to block device
+ *
+ * @v control Control interface
+ * @v data Data interface
+ * @v lba Starting logical block address
+ * @v count Number of logical blocks
+ * @v buffer Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int block_write ( struct interface *control, struct interface *data,
+ uint64_t lba, unsigned int count,
+ userptr_t buffer, size_t len ) {
+ struct interface *dest;
+ block_write_TYPE ( void * ) *op =
+ intf_get_dest_op ( control, block_write, &dest );
+ void *object = intf_object ( dest );
+ int rc;
+
+ if ( op ) {
+ rc = op ( object, data, lba, count, buffer, len );
+ } else {
+ /* Default is to fail to issue the command */
+ rc = -EOPNOTSUPP;
+ }
+
+ intf_put ( dest );
+ return rc;
+}
+
+/**
+ * Read block device capacity
+ *
+ * @v control Control interface
+ * @v data Data interface
+ * @ret rc Return status code
+ */
+int block_read_capacity ( struct interface *control, struct interface *data ) {
+ struct interface *dest;
+ block_read_capacity_TYPE ( void * ) *op =
+ intf_get_dest_op ( control, block_read_capacity, &dest );
+ void *object = intf_object ( dest );
+ int rc;
+
+ if ( op ) {
+ rc = op ( object, data );
+ } else {
+ /* Default is to fail to issue the command */
+ rc = -EOPNOTSUPP;
+ }
+
+ intf_put ( dest );
+ return rc;
+}
+
+/**
+ * Report block device capacity
+ *
+ * @v intf Interface
+ * @v capacity Block device capacity
+ */
+void block_capacity ( struct interface *intf,
+ struct block_device_capacity *capacity ) {
+ struct interface *dest;
+ block_capacity_TYPE ( void * ) *op =
+ intf_get_dest_op ( intf, block_capacity, &dest );
+ void *object = intf_object ( dest );
+
+ if ( op ) {
+ op ( object, capacity );
+ } else {
+ /* Default is to do nothing */
+ }
+
+ intf_put ( dest );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/console.c b/src/VBox/Devices/PC/ipxe/src/core/console.c
new file mode 100644
index 00000000..a26a3ef6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/console.c
@@ -0,0 +1,135 @@
+#include "stddef.h"
+#include <ipxe/console.h>
+#include <ipxe/process.h>
+#include <ipxe/nap.h>
+
+/** @file */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** Current console usage */
+int console_usage = CONSOLE_USAGE_STDOUT;
+
+/**
+ * Write a single character to each console device.
+ *
+ * @v character Character to be written
+ * @ret None -
+ * @err None -
+ *
+ * The character is written out to all enabled console devices, using
+ * each device's console_driver::putchar() method.
+ *
+ */
+void putchar ( int character ) {
+ struct console_driver *console;
+
+ /* Automatic LF -> CR,LF translation */
+ if ( character == '\n' )
+ putchar ( '\r' );
+
+ for_each_table_entry ( console, CONSOLES ) {
+ if ( ( ! console->disabled ) &&
+ ( console_usage & console->usage ) &&
+ console->putchar )
+ console->putchar ( character );
+ }
+}
+
+/**
+ * Check to see if any input is available on any console.
+ *
+ * @v None -
+ * @ret console Console device that has input available, if any.
+ * @ret NULL No console device has input available.
+ * @err None -
+ *
+ * All enabled console devices are checked once for available input
+ * using each device's console_driver::iskey() method. The first
+ * console device that has available input will be returned, if any.
+ *
+ */
+static struct console_driver * has_input ( void ) {
+ struct console_driver *console;
+
+ for_each_table_entry ( console, CONSOLES ) {
+ if ( ( ! console->disabled ) && console->iskey ) {
+ if ( console->iskey () )
+ return console;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Read a single character from any console.
+ *
+ * @v None -
+ * @ret character Character read from a console.
+ * @err None -
+ *
+ * A character will be read from the first enabled console device that
+ * has input available using that console's console_driver::getchar()
+ * method. If no console has input available to be read, this method
+ * will block. To perform a non-blocking read, use something like
+ *
+ * @code
+ *
+ * int key = iskey() ? getchar() : -1;
+ *
+ * @endcode
+ *
+ * The character read will not be echoed back to any console.
+ *
+ */
+int getchar ( void ) {
+ struct console_driver *console;
+ int character;
+
+ while ( 1 ) {
+ console = has_input();
+ if ( console && console->getchar ) {
+ character = console->getchar ();
+ break;
+ }
+
+ /* Doze for a while (until the next interrupt). This works
+ * fine, because the keyboard is interrupt-driven, and the
+ * timer interrupt (approx. every 50msec) takes care of the
+ * serial port, which is read by polling. This reduces the
+ * power dissipation of a modern CPU considerably, and also
+ * makes Etherboot waiting for user interaction waste a lot
+ * less CPU time in a VMware session.
+ */
+ cpu_nap();
+
+ /* Keep processing background tasks while we wait for
+ * input.
+ */
+ step();
+ }
+
+ /* CR -> LF translation */
+ if ( character == '\r' )
+ character = '\n';
+
+ return character;
+}
+
+/** Check for available input on any console.
+ *
+ * @v None -
+ * @ret True Input is available on a console
+ * @ret False Input is not available on any console
+ * @err None -
+ *
+ * All enabled console devices are checked once for available input
+ * using each device's console_driver::iskey() method. If any console
+ * device has input available, this call will return True. If this
+ * call returns True, you can then safely call getchar() without
+ * blocking.
+ *
+ */
+int iskey ( void ) {
+ return has_input() ? 1 : 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/cpio.c b/src/VBox/Devices/PC/ipxe/src/core/cpio.c
new file mode 100644
index 00000000..5b7b3aa1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/cpio.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * CPIO archives
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ipxe/cpio.h>
+
+/**
+ * Set field within a CPIO header
+ *
+ * @v field Field within CPIO header
+ * @v value Value to set
+ */
+void cpio_set_field ( char *field, unsigned long value ) {
+ char buf[9];
+
+ snprintf ( buf, sizeof ( buf ), "%08lx", value );
+ memcpy ( field, buf, 8 );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/ctype.c b/src/VBox/Devices/PC/ipxe/src/core/ctype.c
new file mode 100644
index 00000000..6185bb2f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/ctype.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Character types
+ *
+ */
+
+#include <ctype.h>
+
+/**
+ * Check to see if character is a space
+ *
+ * @v c Character
+ * @ret isspace Character is a space
+ */
+int isspace ( int c ) {
+ switch ( c ) {
+ case ' ' :
+ case '\f' :
+ case '\n' :
+ case '\r' :
+ case '\t' :
+ case '\v' :
+ return 1;
+ default:
+ return 0;
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/cwuri.c b/src/VBox/Devices/PC/ipxe/src/core/cwuri.c
new file mode 100644
index 00000000..893e2050
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/cwuri.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <ipxe/uri.h>
+
+/** @file
+ *
+ * Current working URI
+ *
+ * Somewhat analogous to the current working directory in a POSIX
+ * system.
+ */
+
+/** Current working URI */
+struct uri *cwuri = NULL;
+
+/**
+ * Change working URI
+ *
+ * @v uri New working URI, or NULL
+ */
+void churi ( struct uri *uri ) {
+ struct uri *new_uri = NULL;
+
+ if ( uri )
+ new_uri = resolve_uri ( cwuri, uri );
+
+ uri_put ( cwuri );
+ cwuri = new_uri;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/debug.c b/src/VBox/Devices/PC/ipxe/src/core/debug.c
new file mode 100644
index 00000000..fc90c64a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/debug.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <ipxe/console.h>
+
+/**
+ * Print debug message
+ *
+ * @v fmt Format string
+ * @v ... Arguments
+ */
+void dbg_printf ( const char *fmt, ... ) {
+ int saved_usage;
+ va_list args;
+
+ /* Mark console as in use for debugging messages */
+ saved_usage = console_set_usage ( CONSOLE_USAGE_DEBUG );
+
+ /* Print message */
+ va_start ( args, fmt );
+ vprintf ( fmt, args );
+ va_end ( args );
+
+ /* Restore console usage */
+ console_set_usage ( saved_usage );
+}
+
+/**
+ * Pause until a key is pressed
+ *
+ */
+void dbg_pause ( void ) {
+ dbg_printf ( "\nPress a key..." );
+ getchar();
+ dbg_printf ( "\r \r" );
+}
+
+/**
+ * Indicate more data to follow and pause until a key is pressed
+ *
+ */
+void dbg_more ( void ) {
+ dbg_printf ( "---more---" );
+ getchar();
+ dbg_printf ( "\r \r" );
+}
+
+/**
+ * Print row of a hex dump with specified display address
+ *
+ * @v dispaddr Display address
+ * @v data Data to print
+ * @v len Length of data
+ * @v offset Starting offset within data
+ */
+static void dbg_hex_dump_da_row ( unsigned long dispaddr, const void *data,
+ unsigned long len, unsigned int offset ) {
+ const uint8_t *bytes = data;
+ unsigned int i;
+ uint8_t byte;
+
+ dbg_printf ( "%08lx :", ( dispaddr + offset ) );
+ for ( i = offset ; i < ( offset + 16 ) ; i++ ) {
+ if ( i >= len ) {
+ dbg_printf ( " " );
+ continue;
+ }
+ dbg_printf ( "%c%02x",
+ ( ( ( i % 16 ) == 8 ) ? '-' : ' ' ), bytes[i] );
+ }
+ dbg_printf ( " : " );
+ for ( i = offset ; i < ( offset + 16 ) ; i++ ) {
+ if ( i >= len ) {
+ dbg_printf ( " " );
+ continue;
+ }
+ byte = bytes[i];
+ if ( ( byte < 0x20 ) || ( byte >= 0x7f ) )
+ byte = '.';
+ dbg_printf ( "%c", byte );
+ }
+ dbg_printf ( "\n" );
+}
+
+/**
+ * Print hex dump with specified display address
+ *
+ * @v dispaddr Display address
+ * @v data Data to print
+ * @v len Length of data
+ */
+void dbg_hex_dump_da ( unsigned long dispaddr, const void *data,
+ unsigned long len ) {
+ unsigned int offset;
+
+ for ( offset = 0 ; offset < len ; offset += 16 ) {
+ dbg_hex_dump_da_row ( dispaddr, data, len, offset );
+ }
+}
+
+/**
+ * Maximum number of separately coloured message streams
+ *
+ * Six is the realistic maximum; there are 8 basic ANSI colours, one
+ * of which will be the terminal default and one of which will be
+ * invisible on the terminal because it matches the background colour.
+ */
+#define NUM_AUTO_COLOURS 6
+
+/** A colour assigned to an autocolourised debug message stream */
+struct autocolour {
+ /** Message stream ID */
+ unsigned long stream;
+ /** Last recorded usage */
+ unsigned long last_used;
+};
+
+/**
+ * Choose colour index for debug autocolourisation
+ *
+ * @v stream Message stream ID
+ * @ret colour Colour ID
+ */
+static int dbg_autocolour ( unsigned long stream ) {
+ static struct autocolour acs[NUM_AUTO_COLOURS];
+ static unsigned long use;
+ unsigned int i;
+ unsigned int oldest;
+ unsigned int oldest_last_used;
+
+ /* Increment usage iteration counter */
+ use++;
+
+ /* Scan through list for a currently assigned colour */
+ for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) {
+ if ( acs[i].stream == stream ) {
+ acs[i].last_used = use;
+ return i;
+ }
+ }
+
+ /* No colour found; evict the oldest from the list */
+ oldest = 0;
+ oldest_last_used = use;
+ for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) {
+ if ( acs[i].last_used < oldest_last_used ) {
+ oldest_last_used = acs[i].last_used;
+ oldest = i;
+ }
+ }
+ acs[oldest].stream = stream;
+ acs[oldest].last_used = use;
+ return oldest;
+}
+
+/**
+ * Select automatic colour for debug messages
+ *
+ * @v stream Message stream ID
+ */
+void dbg_autocolourise ( unsigned long stream ) {
+ dbg_printf ( "\033[%dm",
+ ( stream ? ( 31 + dbg_autocolour ( stream ) ) : 0 ) );
+}
+
+/**
+ * Revert to normal colour
+ *
+ */
+void dbg_decolourise ( void ) {
+ dbg_printf ( "\033[0m" );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/debug_md5.c b/src/VBox/Devices/PC/ipxe/src/core/debug_md5.c
new file mode 100644
index 00000000..6214f611
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/debug_md5.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <stdint.h>
+#include <ipxe/crypto.h>
+#include <ipxe/md5.h>
+
+/**
+ * Print an MD5 checksum with specified display address
+ *
+ * @v dispaddr Display address
+ * @v data Data to checksum
+ * @v len Length of data
+ */
+void dbg_md5_da ( unsigned long dispaddr, const void *data,
+ unsigned long len ) {
+ struct digest_algorithm *digest = &md5_algorithm;
+ uint8_t digest_ctx[digest->ctxsize];
+ uint8_t digest_out[digest->digestsize];
+ unsigned int i;
+
+ printf ( "md5sum ( %#08lx, %#lx ) = ", dispaddr, len );
+ digest_init ( digest, digest_ctx );
+ digest_update ( digest, digest_ctx, data, len );
+ digest_final ( digest, digest_ctx, digest_out );
+ for ( i = 0 ; i < sizeof ( digest_out ) ; i++ )
+ printf ( "%02x", digest_out[i] );
+ printf ( "\n" );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/device.c b/src/VBox/Devices/PC/ipxe/src/core/device.c
new file mode 100644
index 00000000..dc182e03
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/device.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <ipxe/list.h>
+#include <ipxe/tables.h>
+#include <ipxe/init.h>
+#include <ipxe/interface.h>
+#include <ipxe/device.h>
+
+/**
+ * @file
+ *
+ * Device model
+ *
+ */
+
+/** Registered root devices */
+static LIST_HEAD ( devices );
+
+/** Device removal inhibition counter */
+int device_keep_count = 0;
+
+/**
+ * Probe a root device
+ *
+ * @v rootdev Root device
+ * @ret rc Return status code
+ */
+static int rootdev_probe ( struct root_device *rootdev ) {
+ int rc;
+
+ DBG ( "Adding %s root bus\n", rootdev->dev.name );
+ if ( ( rc = rootdev->driver->probe ( rootdev ) ) != 0 ) {
+ DBG ( "Failed to add %s root bus: %s\n",
+ rootdev->dev.name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Remove a root device
+ *
+ * @v rootdev Root device
+ */
+static void rootdev_remove ( struct root_device *rootdev ) {
+ rootdev->driver->remove ( rootdev );
+ DBG ( "Removed %s root bus\n", rootdev->dev.name );
+}
+
+/**
+ * Probe all devices
+ *
+ * This initiates probing for all devices in the system. After this
+ * call, the device hierarchy will be populated, and all hardware
+ * should be ready to use.
+ */
+static void probe_devices ( void ) {
+ struct root_device *rootdev;
+ int rc;
+
+ for_each_table_entry ( rootdev, ROOT_DEVICES ) {
+ list_add ( &rootdev->dev.siblings, &devices );
+ INIT_LIST_HEAD ( &rootdev->dev.children );
+ if ( ( rc = rootdev_probe ( rootdev ) ) != 0 )
+ list_del ( &rootdev->dev.siblings );
+ }
+}
+
+/**
+ * Remove all devices
+ *
+ */
+static void remove_devices ( int booting __unused ) {
+ struct root_device *rootdev;
+ struct root_device *tmp;
+
+ if ( device_keep_count != 0 ) {
+ DBG ( "Refusing to remove devices on shutdown\n" );
+ return;
+ }
+
+ list_for_each_entry_safe ( rootdev, tmp, &devices, dev.siblings ) {
+ rootdev_remove ( rootdev );
+ list_del ( &rootdev->dev.siblings );
+ }
+}
+
+struct startup_fn startup_devices __startup_fn ( STARTUP_NORMAL ) = {
+ .startup = probe_devices,
+ .shutdown = remove_devices,
+};
+
+/**
+ * Identify a device behind an interface
+ *
+ * @v intf Interface
+ * @ret device Device, or NULL
+ */
+struct device * identify_device ( struct interface *intf ) {
+ struct interface *dest;
+ identify_device_TYPE ( void * ) *op =
+ intf_get_dest_op ( intf, identify_device, &dest );
+ void *object = intf_object ( dest );
+ void *device;
+
+ if ( op ) {
+ device = op ( object );
+ } else {
+ /* Default is to return NULL */
+ device = NULL;
+ }
+
+ intf_put ( dest );
+ return device;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/downloader.c b/src/VBox/Devices/PC/ipxe/src/core/downloader.c
new file mode 100644
index 00000000..b4c5a5a7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/downloader.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <syslog.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/job.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/umalloc.h>
+#include <ipxe/image.h>
+#include <ipxe/downloader.h>
+
+/** @file
+ *
+ * Image downloader
+ *
+ */
+
+/** A downloader */
+struct downloader {
+ /** Reference count for this object */
+ struct refcnt refcnt;
+
+ /** Job control interface */
+ struct interface job;
+ /** Data transfer interface */
+ struct interface xfer;
+
+ /** Image to contain downloaded file */
+ struct image *image;
+ /** Current position within image buffer */
+ size_t pos;
+};
+
+/**
+ * Free downloader object
+ *
+ * @v refcnt Downloader reference counter
+ */
+static void downloader_free ( struct refcnt *refcnt ) {
+ struct downloader *downloader =
+ container_of ( refcnt, struct downloader, refcnt );
+
+ image_put ( downloader->image );
+ free ( downloader );
+}
+
+/**
+ * Terminate download
+ *
+ * @v downloader Downloader
+ * @v rc Reason for termination
+ */
+static void downloader_finished ( struct downloader *downloader, int rc ) {
+
+ /* Log download status */
+ if ( rc == 0 ) {
+ syslog ( LOG_NOTICE, "Downloaded \"%s\"\n",
+ downloader->image->name );
+ } else {
+ syslog ( LOG_ERR, "Download of \"%s\" failed: %s\n",
+ downloader->image->name, strerror ( rc ) );
+ }
+
+ /* Shut down interfaces */
+ intf_shutdown ( &downloader->xfer, rc );
+ intf_shutdown ( &downloader->job, rc );
+}
+
+/**
+ * Ensure that download buffer is large enough for the specified size
+ *
+ * @v downloader Downloader
+ * @v len Required minimum size
+ * @ret rc Return status code
+ */
+static int downloader_ensure_size ( struct downloader *downloader,
+ size_t len ) {
+ userptr_t new_buffer;
+
+ /* If buffer is already large enough, do nothing */
+ if ( len <= downloader->image->len )
+ return 0;
+
+ DBGC ( downloader, "Downloader %p extending to %zd bytes\n",
+ downloader, len );
+
+ /* Extend buffer */
+ new_buffer = urealloc ( downloader->image->data, len );
+ if ( ! new_buffer ) {
+ DBGC ( downloader, "Downloader %p could not extend buffer to "
+ "%zd bytes\n", downloader, len );
+ return -ENOSPC;
+ }
+ downloader->image->data = new_buffer;
+ downloader->image->len = len;
+
+ return 0;
+}
+
+/****************************************************************************
+ *
+ * Job control interface
+ *
+ */
+
+/**
+ * Report progress of download job
+ *
+ * @v downloader Downloader
+ * @v progress Progress report to fill in
+ */
+static void downloader_progress ( struct downloader *downloader,
+ struct job_progress *progress ) {
+
+ /* This is not entirely accurate, since downloaded data may
+ * arrive out of order (e.g. with multicast protocols), but
+ * it's a reasonable first approximation.
+ */
+ progress->completed = downloader->pos;
+ progress->total = downloader->image->len;
+}
+
+/****************************************************************************
+ *
+ * Data transfer interface
+ *
+ */
+
+/**
+ * Handle received data
+ *
+ * @v downloader Downloader
+ * @v iobuf Datagram I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int downloader_xfer_deliver ( struct downloader *downloader,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ size_t len;
+ size_t max;
+ int rc;
+
+ /* Calculate new buffer position */
+ if ( meta->flags & XFER_FL_ABS_OFFSET )
+ downloader->pos = 0;
+ downloader->pos += meta->offset;
+
+ /* Ensure that we have enough buffer space for this data */
+ len = iob_len ( iobuf );
+ max = ( downloader->pos + len );
+ if ( ( rc = downloader_ensure_size ( downloader, max ) ) != 0 )
+ goto done;
+
+ /* Copy data to buffer */
+ copy_to_user ( downloader->image->data, downloader->pos,
+ iobuf->data, len );
+
+ /* Update current buffer position */
+ downloader->pos += len;
+
+ done:
+ free_iob ( iobuf );
+ if ( rc != 0 )
+ downloader_finished ( downloader, rc );
+ return rc;
+}
+
+/** Downloader data transfer interface operations */
+static struct interface_operation downloader_xfer_operations[] = {
+ INTF_OP ( xfer_deliver, struct downloader *, downloader_xfer_deliver ),
+ INTF_OP ( intf_close, struct downloader *, downloader_finished ),
+};
+
+/** Downloader data transfer interface descriptor */
+static struct interface_descriptor downloader_xfer_desc =
+ INTF_DESC ( struct downloader, xfer, downloader_xfer_operations );
+
+/****************************************************************************
+ *
+ * Job control interface
+ *
+ */
+
+/** Downloader job control interface operations */
+static struct interface_operation downloader_job_op[] = {
+ INTF_OP ( job_progress, struct downloader *, downloader_progress ),
+ INTF_OP ( intf_close, struct downloader *, downloader_finished ),
+};
+
+/** Downloader job control interface descriptor */
+static struct interface_descriptor downloader_job_desc =
+ INTF_DESC ( struct downloader, job, downloader_job_op );
+
+/****************************************************************************
+ *
+ * Instantiator
+ *
+ */
+
+/**
+ * Instantiate a downloader
+ *
+ * @v job Job control interface
+ * @v image Image to fill with downloaded file
+ * @v type Location type to pass to xfer_open()
+ * @v ... Remaining arguments to pass to xfer_open()
+ * @ret rc Return status code
+ *
+ * Instantiates a downloader object to download the specified URI into
+ * the specified image object.
+ */
+int create_downloader ( struct interface *job, struct image *image,
+ int type, ... ) {
+ struct downloader *downloader;
+ va_list args;
+ int rc;
+
+ /* Allocate and initialise structure */
+ downloader = zalloc ( sizeof ( *downloader ) );
+ if ( ! downloader )
+ return -ENOMEM;
+ ref_init ( &downloader->refcnt, downloader_free );
+ intf_init ( &downloader->job, &downloader_job_desc,
+ &downloader->refcnt );
+ intf_init ( &downloader->xfer, &downloader_xfer_desc,
+ &downloader->refcnt );
+ downloader->image = image_get ( image );
+ va_start ( args, type );
+
+ /* Instantiate child objects and attach to our interfaces */
+ if ( ( rc = xfer_vopen ( &downloader->xfer, type, args ) ) != 0 )
+ goto err;
+
+ /* Attach parent interface, mortalise self, and return */
+ intf_plug_plug ( &downloader->job, job );
+ ref_put ( &downloader->refcnt );
+ va_end ( args );
+ return 0;
+
+ err:
+ downloader_finished ( downloader, rc );
+ ref_put ( &downloader->refcnt );
+ va_end ( args );
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/edd.c b/src/VBox/Devices/PC/ipxe/src/core/edd.c
new file mode 100644
index 00000000..8ba24b17
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/edd.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <ipxe/interface.h>
+#include <ipxe/edd.h>
+
+/** @file
+ *
+ * Enhanced Disk Drive specification
+ *
+ */
+
+/**
+ * Describe a disk device using EDD
+ *
+ * @v intf Interface
+ * @v type EDD interface type
+ * @v path EDD device path
+ * @ret rc Return status code
+ */
+int edd_describe ( struct interface *intf, struct edd_interface_type *type,
+ union edd_device_path *path ) {
+ struct interface *dest;
+ edd_describe_TYPE ( void * ) *op =
+ intf_get_dest_op ( intf, edd_describe, &dest );
+ void *object = intf_object ( dest );
+ int rc;
+
+ if ( op ) {
+ rc = op ( object, type, path );
+ } else {
+ /* Default is to not support this operation */
+ rc = -ENOTSUP;
+ }
+
+ intf_put ( dest );
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/errno.c b/src/VBox/Devices/PC/ipxe/src/core/errno.c
new file mode 100644
index 00000000..b4f44cec
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/errno.c
@@ -0,0 +1,18 @@
+#include <errno.h>
+
+/** @file
+ *
+ * Error codes
+ *
+ * This file provides the global variable #errno.
+ *
+ */
+
+/**
+ * Global "last error" number.
+ *
+ * This is valid only when a function has just returned indicating a
+ * failure.
+ *
+ */
+int errno;
diff --git a/src/VBox/Devices/PC/ipxe/src/core/exec.c b/src/VBox/Devices/PC/ipxe/src/core/exec.c
new file mode 100644
index 00000000..49261194
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/exec.c
@@ -0,0 +1,584 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/tables.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/settings.h>
+#include <ipxe/console.h>
+#include <ipxe/keys.h>
+#include <ipxe/process.h>
+#include <ipxe/nap.h>
+#include <ipxe/shell.h>
+
+/** @file
+ *
+ * Command execution
+ *
+ */
+
+/** Shell stop state */
+static int stop_state;
+
+/**
+ * Execute command
+ *
+ * @v command Command name
+ * @v argv Argument list
+ * @ret rc Return status code
+ *
+ * Execute the named command. Unlike a traditional POSIX execv(),
+ * this function returns the exit status of the command.
+ */
+int execv ( const char *command, char * const argv[] ) {
+ struct command *cmd;
+ int argc;
+
+ /* Count number of arguments */
+ for ( argc = 0 ; argv[argc] ; argc++ ) {}
+
+ /* An empty command is deemed to do nothing, successfully */
+ if ( command == NULL )
+ return 0;
+
+ /* Sanity checks */
+ if ( argc == 0 ) {
+ DBG ( "%s: empty argument list\n", command );
+ return -EINVAL;
+ }
+
+ /* Reset getopt() library ready for use by the command. This
+ * is an artefact of the POSIX getopt() API within the context
+ * of Etherboot; see the documentation for reset_getopt() for
+ * details.
+ */
+ reset_getopt();
+
+ /* Hand off to command implementation */
+ for_each_table_entry ( cmd, COMMANDS ) {
+ if ( strcmp ( command, cmd->name ) == 0 )
+ return cmd->exec ( argc, ( char ** ) argv );
+ }
+
+ printf ( "%s: command not found\n", command );
+ return -ENOEXEC;
+}
+
+/**
+ * Split command line into tokens
+ *
+ * @v command Command line
+ * @v tokens Token list to populate, or NULL
+ * @ret count Number of tokens
+ *
+ * Splits the command line into whitespace-delimited tokens. If @c
+ * tokens is non-NULL, any whitespace in the command line will be
+ * replaced with NULs.
+ */
+static int split_command ( char *command, char **tokens ) {
+ int count = 0;
+
+ while ( 1 ) {
+ /* Skip over any whitespace / convert to NUL */
+ while ( isspace ( *command ) ) {
+ if ( tokens )
+ *command = '\0';
+ command++;
+ }
+ /* Check for end of line */
+ if ( ! *command )
+ break;
+ /* We have found the start of the next argument */
+ if ( tokens )
+ tokens[count] = command;
+ count++;
+ /* Skip to start of next whitespace, if any */
+ while ( *command && ! isspace ( *command ) ) {
+ command++;
+ }
+ }
+ return count;
+}
+
+/**
+ * Process next command only if previous command succeeded
+ *
+ * @v rc Status of previous command
+ * @ret process Process next command
+ */
+static int process_on_success ( int rc ) {
+ return ( rc == 0 );
+}
+
+/**
+ * Process next command only if previous command failed
+ *
+ * @v rc Status of previous command
+ * @ret process Process next command
+ */
+static int process_on_failure ( int rc ) {
+ return ( rc != 0 );
+}
+
+/**
+ * Process next command regardless of status from previous command
+ *
+ * @v rc Status of previous command
+ * @ret process Process next command
+ */
+static int process_always ( int rc __unused ) {
+ return 1;
+}
+
+/**
+ * Find command terminator
+ *
+ * @v tokens Token list
+ * @ret process_next "Should next command be processed?" function
+ * @ret argc Argument count
+ */
+static int command_terminator ( char **tokens,
+ int ( **process_next ) ( int rc ) ) {
+ unsigned int i;
+
+ /* Find first terminating token */
+ for ( i = 0 ; tokens[i] ; i++ ) {
+ if ( tokens[i][0] == '#' ) {
+ /* Start of a comment */
+ break;
+ } else if ( strcmp ( tokens[i], "||" ) == 0 ) {
+ /* Short-circuit logical OR */
+ *process_next = process_on_failure;
+ return i;
+ } else if ( strcmp ( tokens[i], "&&" ) == 0 ) {
+ /* Short-circuit logical AND */
+ *process_next = process_on_success;
+ return i;
+ } else if ( strcmp ( tokens[i], ";" ) == 0 ) {
+ /* Process next command unconditionally */
+ *process_next = process_always;
+ return i;
+ }
+ }
+
+ /* End of token list */
+ *process_next = NULL;
+ return i;
+}
+
+/**
+ * Set shell stop state
+ *
+ * @v stop Shell stop state
+ */
+void shell_stop ( int stop ) {
+ stop_state = stop;
+}
+
+/**
+ * Test and consume shell stop state
+ *
+ * @v stop Shell stop state to consume
+ * @v stopped Shell had been stopped
+ */
+int shell_stopped ( int stop ) {
+ int stopped;
+
+ /* Test to see if we need to stop */
+ stopped = ( stop_state >= stop );
+
+ /* Consume stop state */
+ if ( stop_state <= stop )
+ stop_state = 0;
+
+ return stopped;
+}
+
+/**
+ * Expand settings within a token list
+ *
+ * @v argc Argument count
+ * @v tokens Token list
+ * @v argv Argument list to fill in
+ * @ret rc Return status code
+ */
+static int expand_tokens ( int argc, char **tokens, char **argv ) {
+ int i;
+
+ /* Expand each token in turn */
+ for ( i = 0 ; i < argc ; i++ ) {
+ argv[i] = expand_settings ( tokens[i] );
+ if ( ! argv[i] )
+ goto err_expand_settings;
+ }
+
+ return 0;
+
+ err_expand_settings:
+ assert ( argv[i] == NULL );
+ for ( ; i >= 0 ; i-- )
+ free ( argv[i] );
+ return -ENOMEM;
+}
+
+/**
+ * Free an expanded token list
+ *
+ * @v argv Argument list
+ */
+static void free_tokens ( char **argv ) {
+
+ /* Free each expanded argument */
+ while ( *argv )
+ free ( *(argv++) );
+}
+
+/**
+ * Execute command line
+ *
+ * @v command Command line
+ * @ret rc Return status code
+ *
+ * Execute the named command and arguments.
+ */
+int system ( const char *command ) {
+ int count = split_command ( ( char * ) command, NULL );
+ char *all_tokens[ count + 1 ];
+ int ( * process_next ) ( int rc );
+ char *command_copy;
+ char **tokens;
+ int argc;
+ int process;
+ int rc = 0;
+
+ /* Create modifiable copy of command */
+ command_copy = strdup ( command );
+ if ( ! command_copy )
+ return -ENOMEM;
+
+ /* Split command into tokens */
+ split_command ( command_copy, all_tokens );
+ all_tokens[count] = NULL;
+
+ /* Process individual commands */
+ process = 1;
+ for ( tokens = all_tokens ; ; tokens += ( argc + 1 ) ) {
+
+ /* Find command terminator */
+ argc = command_terminator ( tokens, &process_next );
+
+ /* Expand tokens and execute command */
+ if ( process ) {
+ char *argv[ argc + 1 ];
+
+ /* Expand tokens */
+ if ( ( rc = expand_tokens ( argc, tokens, argv ) ) != 0)
+ break;
+ argv[argc] = NULL;
+
+ /* Execute command */
+ rc = execv ( argv[0], argv );
+
+ /* Free tokens */
+ free_tokens ( argv );
+ }
+
+ /* Stop processing, if applicable */
+ if ( shell_stopped ( SHELL_STOP_COMMAND ) )
+ break;
+
+ /* Stop processing if we have reached the end of the
+ * command.
+ */
+ if ( ! process_next )
+ break;
+
+ /* Determine whether or not to process next command */
+ process = process_next ( rc );
+ }
+
+ /* Free modified copy of command */
+ free ( command_copy );
+
+ return rc;
+}
+
+/**
+ * Concatenate arguments
+ *
+ * @v args Argument list (NULL-terminated)
+ * @ret string Concatenated arguments
+ *
+ * The returned string is allocated with malloc(). The caller is
+ * responsible for eventually free()ing this string.
+ */
+char * concat_args ( char **args ) {
+ char **arg;
+ size_t len;
+ char *string;
+ char *ptr;
+
+ /* Calculate total string length */
+ len = 1 /* NUL */;
+ for ( arg = args ; *arg ; arg++ )
+ len += ( 1 /* possible space */ + strlen ( *arg ) );
+
+ /* Allocate string */
+ string = zalloc ( len );
+ if ( ! string )
+ return NULL;
+
+ /* Populate string */
+ ptr = string;
+ for ( arg = args ; *arg ; arg++ ) {
+ ptr += sprintf ( ptr, "%s%s",
+ ( ( ptr == string ) ? "" : " " ), *arg );
+ }
+ assert ( ptr < ( string + len ) );
+
+ return string;
+}
+
+/** "echo" options */
+struct echo_options {
+ /** Do not print trailing newline */
+ int no_newline;
+};
+
+/** "echo" option list */
+static struct option_descriptor echo_opts[] = {
+ OPTION_DESC ( "n", 'n', no_argument,
+ struct echo_options, no_newline, parse_flag ),
+};
+
+/** "echo" command descriptor */
+static struct command_descriptor echo_cmd =
+ COMMAND_DESC ( struct echo_options, echo_opts, 0, MAX_ARGUMENTS,
+ "[-n] [...]" );
+
+/**
+ * "echo" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int echo_exec ( int argc, char **argv ) {
+ struct echo_options opts;
+ char *text;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &echo_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse text */
+ text = concat_args ( &argv[optind] );
+ if ( ! text )
+ return -ENOMEM;
+
+ /* Print text */
+ printf ( "%s%s", text, ( opts.no_newline ? "" : "\n" ) );
+
+ free ( text );
+ return 0;
+}
+
+/** "echo" command */
+struct command echo_command __command = {
+ .name = "echo",
+ .exec = echo_exec,
+};
+
+/** "exit" options */
+struct exit_options {};
+
+/** "exit" option list */
+static struct option_descriptor exit_opts[] = {};
+
+/** "exit" command descriptor */
+static struct command_descriptor exit_cmd =
+ COMMAND_DESC ( struct exit_options, exit_opts, 0, 1, "[<status>]" );
+
+/**
+ * "exit" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int exit_exec ( int argc, char **argv ) {
+ struct exit_options opts;
+ unsigned int exit_code = 0;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &exit_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse exit status, if present */
+ if ( optind != argc ) {
+ if ( ( rc = parse_integer ( argv[optind], &exit_code ) ) != 0 )
+ return rc;
+ }
+
+ /* Stop shell processing */
+ shell_stop ( SHELL_STOP_COMMAND_SEQUENCE );
+
+ return exit_code;
+}
+
+/** "exit" command */
+struct command exit_command __command = {
+ .name = "exit",
+ .exec = exit_exec,
+};
+
+/** "isset" options */
+struct isset_options {};
+
+/** "isset" option list */
+static struct option_descriptor isset_opts[] = {};
+
+/** "isset" command descriptor */
+static struct command_descriptor isset_cmd =
+ COMMAND_DESC ( struct isset_options, isset_opts, 1, 1, "<value>" );
+
+/**
+ * "isset" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int isset_exec ( int argc, char **argv ) {
+ struct isset_options opts;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &isset_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Return success iff argument is non-empty */
+ return ( argv[optind][0] ? 0 : -ENOENT );
+}
+
+/** "isset" command */
+struct command isset_command __command = {
+ .name = "isset",
+ .exec = isset_exec,
+};
+
+/** "iseq" options */
+struct iseq_options {};
+
+/** "iseq" option list */
+static struct option_descriptor iseq_opts[] = {};
+
+/** "iseq" command descriptor */
+static struct command_descriptor iseq_cmd =
+ COMMAND_DESC ( struct iseq_options, iseq_opts, 2, 2,
+ "<value1> <value2>" );
+
+/**
+ * "iseq" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int iseq_exec ( int argc, char **argv ) {
+ struct iseq_options opts;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &iseq_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Return success iff arguments are equal */
+ return ( ( strcmp ( argv[optind], argv[ optind + 1 ] ) == 0 ) ?
+ 0 : -ERANGE );
+}
+
+/** "iseq" command */
+struct command iseq_command __command = {
+ .name = "iseq",
+ .exec = iseq_exec,
+};
+
+/** "sleep" options */
+struct sleep_options {};
+
+/** "sleep" option list */
+static struct option_descriptor sleep_opts[] = {};
+
+/** "sleep" command descriptor */
+static struct command_descriptor sleep_cmd =
+ COMMAND_DESC ( struct sleep_options, sleep_opts, 1, 1, "<seconds>" );
+
+/**
+ * "sleep" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int sleep_exec ( int argc, char **argv ) {
+ struct sleep_options opts;
+ unsigned int seconds;
+ unsigned long start;
+ unsigned long delay;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &sleep_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse number of seconds */
+ if ( ( rc = parse_integer ( argv[optind], &seconds ) ) != 0 )
+ return rc;
+
+ /* Delay for specified number of seconds */
+ start = currticks();
+ delay = ( seconds * TICKS_PER_SEC );
+ while ( ( currticks() - start ) <= delay ) {
+ step();
+ if ( iskey() && ( getchar() == CTRL_C ) )
+ return -ECANCELED;
+ cpu_nap();
+ }
+
+ return 0;
+}
+
+/** "sleep" command */
+struct command sleep_command __command = {
+ .name = "sleep",
+ .exec = sleep_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/core/fnrec.c b/src/VBox/Devices/PC/ipxe/src/core/fnrec.c
new file mode 100644
index 00000000..05d63aaa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/fnrec.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2010 Stefan Hajnoczi <stefanha@gmail.com>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ipxe/init.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/io.h>
+
+/** @file
+ *
+ * Function trace recorder for crash and hang debugging
+ *
+ */
+
+/** Constant for identifying valid trace buffers */
+#define FNREC_MAGIC ( 'f' << 24 | 'n' << 16 | 'r' << 8 | 'e' )
+
+/** Number of trace buffer entries */
+#define FNREC_NUM_ENTRIES 4096
+
+/** Trace buffer physical address
+ *
+ * Fixed at 17MB
+ */
+#define FNREC_PHYS_ADDRESS ( 17 * 1024 * 1024 )
+
+/** A trace buffer entry */
+struct fnrec_entry {
+ /** Called function address */
+ void *called_fn;
+ /** Call site */
+ void *call_site;
+ /** Entry count */
+ uint16_t entry_count;
+ /** Exit count */
+ uint16_t exit_count;
+ /** Checksum */
+ unsigned long checksum;
+};
+
+/** A trace buffer */
+struct fnrec_buffer {
+ /** Constant for identifying valid trace buffers */
+ uint32_t magic;
+
+ /** Next trace buffer entry to fill */
+ unsigned int idx;
+
+ /** Trace buffer */
+ struct fnrec_entry data[FNREC_NUM_ENTRIES]
+ __attribute__ (( aligned ( 64 ) ));
+};
+
+/** The trace buffer */
+static struct fnrec_buffer *fnrec_buffer;
+
+/**
+ * Test whether the trace buffer is valid
+ *
+ * @ret is_valid Buffer is valid
+ */
+static int fnrec_is_valid ( void ) {
+ return ( fnrec_buffer && ( fnrec_buffer->magic == FNREC_MAGIC ) );
+}
+
+/**
+ * Invalidate the trace buffer
+ *
+ */
+static void fnrec_invalidate ( void ) {
+ fnrec_buffer->magic = 0;
+}
+
+/**
+ * Reset the trace buffer and clear entries
+ */
+static void fnrec_reset ( void ) {
+ memset ( fnrec_buffer, 0, sizeof ( *fnrec_buffer ) );
+ fnrec_buffer->magic = FNREC_MAGIC;
+}
+
+/**
+ * Append an entry to the trace buffer
+ *
+ * @v called_fn Called function
+ * @v call_site Call site
+ * @ret entry Trace buffer entry
+ */
+static struct fnrec_entry * fnrec_append ( void *called_fn, void *call_site ) {
+ struct fnrec_entry *entry;
+
+ /* Re-use existing entry, if possible */
+ entry = &fnrec_buffer->data[ fnrec_buffer->idx ];
+ if ( ( entry->called_fn == called_fn ) &&
+ ( entry->call_site == call_site ) &&
+ ( entry->entry_count >= entry->exit_count ) ) {
+ return entry;
+ }
+
+ /* Otherwise, create a new entry */
+ fnrec_buffer->idx = ( ( fnrec_buffer->idx + 1 ) % FNREC_NUM_ENTRIES );
+ entry = &fnrec_buffer->data[ fnrec_buffer->idx ];
+ entry->called_fn = called_fn;
+ entry->call_site = call_site;
+ entry->entry_count = 0;
+ entry->exit_count = 0;
+ entry->checksum = ( ( ( unsigned long ) called_fn ) ^
+ ( ( unsigned long ) call_site ) );
+ return entry;
+}
+
+/**
+ * Print the contents of the trace buffer in chronological order
+ */
+static void fnrec_dump ( void ) {
+ struct fnrec_entry *entry;
+ unsigned int i;
+ unsigned int idx;
+ unsigned long checksum;
+
+ printf ( "fnrec buffer dump:\n" );
+ for ( i = 1 ; i <= FNREC_NUM_ENTRIES ; i++ ) {
+ idx = ( ( fnrec_buffer->idx + i ) % FNREC_NUM_ENTRIES );
+ entry = &fnrec_buffer->data[idx];
+ if ( ( entry->entry_count == 0 ) && ( entry->exit_count == 0 ) )
+ continue;
+ checksum = ( ( ( ( unsigned long ) entry->called_fn ) ^
+ ( ( unsigned long ) entry->call_site ) ) +
+ entry->entry_count + entry->exit_count );
+ printf ( "%p %p %d %d", entry->called_fn, entry->call_site,
+ entry->entry_count, entry->exit_count );
+ if ( entry->checksum != checksum ) {
+ printf ( " (checksum wrong at phys %08lx)",
+ virt_to_phys ( entry ) );
+ }
+ printf ( "\n");
+ }
+}
+
+/**
+ * Function tracer initialisation function
+ */
+static void fnrec_init ( void ) {
+
+ fnrec_buffer = phys_to_virt ( FNREC_PHYS_ADDRESS );
+ if ( fnrec_is_valid() ) {
+ fnrec_invalidate();
+ fnrec_dump();
+ } else {
+ printf ( "fnrec buffer not found\n" );
+ }
+ fnrec_reset();
+}
+
+struct init_fn fnrec_init_fn __init_fn ( INIT_NORMAL ) = {
+ .initialise = fnrec_init,
+};
+
+/*
+ * These functions are called from every C function. The compiler inserts
+ * these calls when -finstrument-functions is used.
+ */
+void __cyg_profile_func_enter ( void *called_fn, void *call_site ) {
+ struct fnrec_entry *entry;
+
+ if ( fnrec_is_valid() ) {
+ entry = fnrec_append ( called_fn, call_site );
+ entry->entry_count++;
+ entry->checksum++;
+ mb();
+ }
+}
+
+void __cyg_profile_func_exit ( void *called_fn, void *call_site ) {
+ struct fnrec_entry *entry;
+
+ if ( fnrec_is_valid() ) {
+ entry = fnrec_append ( called_fn, call_site );
+ entry->exit_count++;
+ entry->checksum++;
+ mb();
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/gdbserial.c b/src/VBox/Devices/PC/ipxe/src/core/gdbserial.c
new file mode 100644
index 00000000..ed217add
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/gdbserial.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 Stefan Hajnoczi <stefanha@gmail.com>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <assert.h>
+#include <ipxe/serial.h>
+#include <ipxe/gdbstub.h>
+#include <ipxe/gdbserial.h>
+
+struct gdb_transport serial_gdb_transport __gdb_transport;
+
+static size_t gdbserial_recv ( char *buf, size_t len ) {
+ assert ( len > 0 );
+ buf [ 0 ] = serial_getc();
+ return 1;
+}
+
+static void gdbserial_send ( const char *buf, size_t len ) {
+ while ( len-- > 0 ) {
+ serial_putc ( *buf++ );
+ }
+}
+
+struct gdb_transport serial_gdb_transport __gdb_transport = {
+ .name = "serial",
+ .recv = gdbserial_recv,
+ .send = gdbserial_send,
+};
+
+struct gdb_transport *gdbserial_configure ( void ) {
+ return &serial_gdb_transport;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/gdbstub.c b/src/VBox/Devices/PC/ipxe/src/core/gdbstub.c
new file mode 100644
index 00000000..34e6a037
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/gdbstub.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright (C) 2008 Stefan Hajnoczi <stefanha@gmail.com>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * GDB stub for remote debugging
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <byteswap.h>
+#include <ipxe/gdbstub.h>
+#include "gdbmach.h"
+
+enum {
+ POSIX_EINVAL = 0x1c, /* used to report bad arguments to GDB */
+ SIZEOF_PAYLOAD = 256, /* buffer size of GDB payload data */
+};
+
+struct gdbstub {
+ struct gdb_transport *trans;
+ int exit_handler; /* leave interrupt handler */
+
+ int signo;
+ gdbreg_t *regs;
+
+ void ( * parse ) ( struct gdbstub *stub, char ch );
+ uint8_t cksum1;
+
+ /* Buffer for payload data when parsing a packet. Once the
+ * packet has been received, this buffer is used to hold
+ * the reply payload. */
+ char buf [ SIZEOF_PAYLOAD + 4 ]; /* $...PAYLOAD...#XX */
+ char *payload; /* start of payload */
+ int len; /* length of payload */
+};
+
+/* Packet parser states */
+static void gdbstub_state_new ( struct gdbstub *stub, char ch );
+static void gdbstub_state_data ( struct gdbstub *stub, char ch );
+static void gdbstub_state_cksum1 ( struct gdbstub *stub, char ch );
+static void gdbstub_state_cksum2 ( struct gdbstub *stub, char ch );
+static void gdbstub_state_wait_ack ( struct gdbstub *stub, char ch );
+
+static uint8_t gdbstub_from_hex_digit ( char ch ) {
+ return ( isdigit ( ch ) ? ch - '0' : tolower ( ch ) - 'a' + 0xa ) & 0xf;
+}
+
+static uint8_t gdbstub_to_hex_digit ( uint8_t b ) {
+ b &= 0xf;
+ return ( b < 0xa ? '0' : 'a' - 0xa ) + b;
+}
+
+/*
+ * To make reading/writing device memory atomic, we check for
+ * 2- or 4-byte aligned operations and handle them specially.
+ */
+
+static void gdbstub_from_hex_buf ( char *dst, char *src, int lenbytes ) {
+ if ( lenbytes == 2 && ( ( unsigned long ) dst & 0x1 ) == 0 ) {
+ uint16_t i = gdbstub_from_hex_digit ( src [ 2 ] ) << 12 |
+ gdbstub_from_hex_digit ( src [ 3 ] ) << 8 |
+ gdbstub_from_hex_digit ( src [ 0 ] ) << 4 |
+ gdbstub_from_hex_digit ( src [ 1 ] );
+ * ( uint16_t * ) dst = cpu_to_le16 ( i );
+ } else if ( lenbytes == 4 && ( ( unsigned long ) dst & 0x3 ) == 0 ) {
+ uint32_t i = gdbstub_from_hex_digit ( src [ 6 ] ) << 28 |
+ gdbstub_from_hex_digit ( src [ 7 ] ) << 24 |
+ gdbstub_from_hex_digit ( src [ 4 ] ) << 20 |
+ gdbstub_from_hex_digit ( src [ 5 ] ) << 16 |
+ gdbstub_from_hex_digit ( src [ 2 ] ) << 12 |
+ gdbstub_from_hex_digit ( src [ 3 ] ) << 8 |
+ gdbstub_from_hex_digit ( src [ 0 ] ) << 4 |
+ gdbstub_from_hex_digit ( src [ 1 ] );
+ * ( uint32_t * ) dst = cpu_to_le32 ( i );
+ } else {
+ while ( lenbytes-- > 0 ) {
+ *dst++ = gdbstub_from_hex_digit ( src [ 0 ] ) << 4 |
+ gdbstub_from_hex_digit ( src [ 1 ] );
+ src += 2;
+ }
+ }
+}
+
+static void gdbstub_to_hex_buf ( char *dst, char *src, int lenbytes ) {
+ if ( lenbytes == 2 && ( ( unsigned long ) src & 0x1 ) == 0 ) {
+ uint16_t i = cpu_to_le16 ( * ( uint16_t * ) src );
+ dst [ 0 ] = gdbstub_to_hex_digit ( i >> 4 );
+ dst [ 1 ] = gdbstub_to_hex_digit ( i );
+ dst [ 2 ] = gdbstub_to_hex_digit ( i >> 12 );
+ dst [ 3 ] = gdbstub_to_hex_digit ( i >> 8 );
+ } else if ( lenbytes == 4 && ( ( unsigned long ) src & 0x3 ) == 0 ) {
+ uint32_t i = cpu_to_le32 ( * ( uint32_t * ) src );
+ dst [ 0 ] = gdbstub_to_hex_digit ( i >> 4 );
+ dst [ 1 ] = gdbstub_to_hex_digit ( i );
+ dst [ 2 ] = gdbstub_to_hex_digit ( i >> 12 );
+ dst [ 3 ] = gdbstub_to_hex_digit ( i >> 8 );
+ dst [ 4 ] = gdbstub_to_hex_digit ( i >> 20 );
+ dst [ 5 ] = gdbstub_to_hex_digit ( i >> 16);
+ dst [ 6 ] = gdbstub_to_hex_digit ( i >> 28 );
+ dst [ 7 ] = gdbstub_to_hex_digit ( i >> 24 );
+ } else {
+ while ( lenbytes-- > 0 ) {
+ *dst++ = gdbstub_to_hex_digit ( *src >> 4 );
+ *dst++ = gdbstub_to_hex_digit ( *src );
+ src++;
+ }
+ }
+}
+
+static uint8_t gdbstub_cksum ( char *data, int len ) {
+ uint8_t cksum = 0;
+ while ( len-- > 0 ) {
+ cksum += ( uint8_t ) *data++;
+ }
+ return cksum;
+}
+
+static void gdbstub_tx_packet ( struct gdbstub *stub ) {
+ uint8_t cksum = gdbstub_cksum ( stub->payload, stub->len );
+ stub->buf [ 0 ] = '$';
+ stub->buf [ stub->len + 1 ] = '#';
+ stub->buf [ stub->len + 2 ] = gdbstub_to_hex_digit ( cksum >> 4 );
+ stub->buf [ stub->len + 3 ] = gdbstub_to_hex_digit ( cksum );
+ stub->trans->send ( stub->buf, stub->len + 4 );
+ stub->parse = gdbstub_state_wait_ack;
+}
+
+/* GDB commands */
+static void gdbstub_send_ok ( struct gdbstub *stub ) {
+ stub->payload [ 0 ] = 'O';
+ stub->payload [ 1 ] = 'K';
+ stub->len = 2;
+ gdbstub_tx_packet ( stub );
+}
+
+static void gdbstub_send_num_packet ( struct gdbstub *stub, char reply, int num ) {
+ stub->payload [ 0 ] = reply;
+ stub->payload [ 1 ] = gdbstub_to_hex_digit ( ( char ) num >> 4 );
+ stub->payload [ 2 ] = gdbstub_to_hex_digit ( ( char ) num );
+ stub->len = 3;
+ gdbstub_tx_packet ( stub );
+}
+
+/* Format is arg1,arg2,...,argn:data where argn are hex integers and data is not an argument */
+static int gdbstub_get_packet_args ( struct gdbstub *stub, unsigned long *args, int nargs, int *stop_idx ) {
+ int i;
+ char ch = 0;
+ int argc = 0;
+ unsigned long val = 0;
+ for ( i = 1; i < stub->len && argc < nargs; i++ ) {
+ ch = stub->payload [ i ];
+ if ( ch == ':' ) {
+ break;
+ } else if ( ch == ',' ) {
+ args [ argc++ ] = val;
+ val = 0;
+ } else {
+ val = ( val << 4 ) | gdbstub_from_hex_digit ( ch );
+ }
+ }
+ if ( stop_idx ) {
+ *stop_idx = i;
+ }
+ if ( argc < nargs ) {
+ args [ argc++ ] = val;
+ }
+ return ( ( i == stub->len || ch == ':' ) && argc == nargs );
+}
+
+static void gdbstub_send_errno ( struct gdbstub *stub, int errno ) {
+ gdbstub_send_num_packet ( stub, 'E', errno );
+}
+
+static void gdbstub_report_signal ( struct gdbstub *stub ) {
+ gdbstub_send_num_packet ( stub, 'S', stub->signo );
+}
+
+static void gdbstub_read_regs ( struct gdbstub *stub ) {
+ gdbstub_to_hex_buf ( stub->payload, ( char * ) stub->regs, GDBMACH_SIZEOF_REGS );
+ stub->len = GDBMACH_SIZEOF_REGS * 2;
+ gdbstub_tx_packet ( stub );
+}
+
+static void gdbstub_write_regs ( struct gdbstub *stub ) {
+ if ( stub->len != 1 + GDBMACH_SIZEOF_REGS * 2 ) {
+ gdbstub_send_errno ( stub, POSIX_EINVAL );
+ return;
+ }
+ gdbstub_from_hex_buf ( ( char * ) stub->regs, &stub->payload [ 1 ], GDBMACH_SIZEOF_REGS );
+ gdbstub_send_ok ( stub );
+}
+
+static void gdbstub_read_mem ( struct gdbstub *stub ) {
+ unsigned long args [ 2 ];
+ if ( !gdbstub_get_packet_args ( stub, args, sizeof args / sizeof args [ 0 ], NULL ) ) {
+ gdbstub_send_errno ( stub, POSIX_EINVAL );
+ return;
+ }
+ args [ 1 ] = ( args [ 1 ] < SIZEOF_PAYLOAD / 2 ) ? args [ 1 ] : SIZEOF_PAYLOAD / 2;
+ gdbstub_to_hex_buf ( stub->payload, ( char * ) args [ 0 ], args [ 1 ] );
+ stub->len = args [ 1 ] * 2;
+ gdbstub_tx_packet ( stub );
+}
+
+static void gdbstub_write_mem ( struct gdbstub *stub ) {
+ unsigned long args [ 2 ];
+ int colon;
+ if ( !gdbstub_get_packet_args ( stub, args, sizeof args / sizeof args [ 0 ], &colon ) ||
+ colon >= stub->len || stub->payload [ colon ] != ':' ||
+ ( stub->len - colon - 1 ) % 2 != 0 ) {
+ gdbstub_send_errno ( stub, POSIX_EINVAL );
+ return;
+ }
+ gdbstub_from_hex_buf ( ( char * ) args [ 0 ], &stub->payload [ colon + 1 ], ( stub->len - colon - 1 ) / 2 );
+ gdbstub_send_ok ( stub );
+}
+
+static void gdbstub_continue ( struct gdbstub *stub, int single_step ) {
+ gdbreg_t pc;
+ if ( stub->len > 1 && gdbstub_get_packet_args ( stub, &pc, 1, NULL ) ) {
+ gdbmach_set_pc ( stub->regs, pc );
+ }
+ gdbmach_set_single_step ( stub->regs, single_step );
+ stub->exit_handler = 1;
+ /* Reply will be sent when we hit the next breakpoint or interrupt */
+}
+
+static void gdbstub_breakpoint ( struct gdbstub *stub ) {
+ unsigned long args [ 3 ];
+ int enable = stub->payload [ 0 ] == 'Z' ? 1 : 0;
+ if ( !gdbstub_get_packet_args ( stub, args, sizeof args / sizeof args [ 0 ], NULL ) ) {
+ gdbstub_send_errno ( stub, POSIX_EINVAL );
+ return;
+ }
+ if ( gdbmach_set_breakpoint ( args [ 0 ], args [ 1 ], args [ 2 ], enable ) ) {
+ gdbstub_send_ok ( stub );
+ } else {
+ /* Not supported */
+ stub->len = 0;
+ gdbstub_tx_packet ( stub );
+ }
+}
+
+static void gdbstub_rx_packet ( struct gdbstub *stub ) {
+ switch ( stub->payload [ 0 ] ) {
+ case '?':
+ gdbstub_report_signal ( stub );
+ break;
+ case 'g':
+ gdbstub_read_regs ( stub );
+ break;
+ case 'G':
+ gdbstub_write_regs ( stub );
+ break;
+ case 'm':
+ gdbstub_read_mem ( stub );
+ break;
+ case 'M':
+ gdbstub_write_mem ( stub );
+ break;
+ case 'c': /* Continue */
+ case 'k': /* Kill */
+ case 's': /* Step */
+ case 'D': /* Detach */
+ gdbstub_continue ( stub, stub->payload [ 0 ] == 's' );
+ if ( stub->payload [ 0 ] == 'D' ) {
+ gdbstub_send_ok ( stub );
+ }
+ break;
+ case 'Z': /* Insert breakpoint */
+ case 'z': /* Remove breakpoint */
+ gdbstub_breakpoint ( stub );
+ break;
+ default:
+ stub->len = 0;
+ gdbstub_tx_packet ( stub );
+ break;
+ }
+}
+
+/* GDB packet parser */
+static void gdbstub_state_new ( struct gdbstub *stub, char ch ) {
+ if ( ch == '$' ) {
+ stub->len = 0;
+ stub->parse = gdbstub_state_data;
+ }
+}
+
+static void gdbstub_state_data ( struct gdbstub *stub, char ch ) {
+ if ( ch == '#' ) {
+ stub->parse = gdbstub_state_cksum1;
+ } else if ( ch == '$' ) {
+ stub->len = 0; /* retry new packet */
+ } else {
+ /* If the length exceeds our buffer, let the checksum fail */
+ if ( stub->len < SIZEOF_PAYLOAD ) {
+ stub->payload [ stub->len++ ] = ch;
+ }
+ }
+}
+
+static void gdbstub_state_cksum1 ( struct gdbstub *stub, char ch ) {
+ stub->cksum1 = gdbstub_from_hex_digit ( ch ) << 4;
+ stub->parse = gdbstub_state_cksum2;
+}
+
+static void gdbstub_state_cksum2 ( struct gdbstub *stub, char ch ) {
+ uint8_t their_cksum;
+ uint8_t our_cksum;
+
+ stub->parse = gdbstub_state_new;
+ their_cksum = stub->cksum1 + gdbstub_from_hex_digit ( ch );
+ our_cksum = gdbstub_cksum ( stub->payload, stub->len );
+ if ( their_cksum == our_cksum ) {
+ stub->trans->send ( "+", 1 );
+ if ( stub->len > 0 ) {
+ gdbstub_rx_packet ( stub );
+ }
+ } else {
+ stub->trans->send ( "-", 1 );
+ }
+}
+
+static void gdbstub_state_wait_ack ( struct gdbstub *stub, char ch ) {
+ if ( ch == '+' ) {
+ stub->parse = gdbstub_state_new;
+ } else {
+ /* This retransmit is very aggressive but necessary to keep
+ * in sync with GDB. */
+ gdbstub_tx_packet ( stub );
+ }
+}
+
+static void gdbstub_parse ( struct gdbstub *stub, char ch ) {
+ stub->parse ( stub, ch );
+}
+
+static struct gdbstub stub = {
+ .parse = gdbstub_state_new
+};
+
+void gdbstub_handler ( int signo, gdbreg_t *regs ) {
+ char packet [ SIZEOF_PAYLOAD + 4 ];
+ size_t len, i;
+
+ /* A transport must be set up */
+ if ( !stub.trans ) {
+ return;
+ }
+
+ stub.signo = signo;
+ stub.regs = regs;
+ stub.exit_handler = 0;
+ gdbstub_report_signal ( &stub );
+ while ( !stub.exit_handler && ( len = stub.trans->recv ( packet, sizeof ( packet ) ) ) > 0 ) {
+ for ( i = 0; i < len; i++ ) {
+ gdbstub_parse ( &stub, packet [ i ] );
+ }
+ }
+}
+
+struct gdb_transport *find_gdb_transport ( const char *name ) {
+ struct gdb_transport *trans;
+
+ for_each_table_entry ( trans, GDB_TRANSPORTS ) {
+ if ( strcmp ( trans->name, name ) == 0 ) {
+ return trans;
+ }
+ }
+ return NULL;
+}
+
+void gdbstub_start ( struct gdb_transport *trans ) {
+ stub.trans = trans;
+ stub.payload = &stub.buf [ 1 ];
+ gdbmach_breakpoint();
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/gdbudp.c b/src/VBox/Devices/PC/ipxe/src/core/gdbudp.c
new file mode 100644
index 00000000..9cb6572b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/gdbudp.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2008 Stefan Hajnoczi <stefanha@gmail.com>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <string.h>
+#include <byteswap.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/in.h>
+#include <ipxe/if_arp.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ip.h>
+#include <ipxe/udp.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/nap.h>
+#include <ipxe/gdbstub.h>
+#include <ipxe/gdbudp.h>
+
+/** @file
+ *
+ * GDB over UDP transport
+ *
+ */
+
+enum {
+ DEFAULT_PORT = 43770, /* UDP listen port */
+};
+
+struct gdb_transport udp_gdb_transport __gdb_transport;
+
+static struct net_device *netdev;
+static uint8_t dest_eth[ETH_ALEN];
+static struct sockaddr_in dest_addr;
+static struct sockaddr_in source_addr;
+
+static void gdbudp_ensure_netdev_open ( struct net_device *netdev ) {
+ /* The device may have been closed between breakpoints */
+ assert ( netdev );
+ netdev_open ( netdev );
+
+ /* Strictly speaking, we may need to close the device when leaving the interrupt handler */
+}
+
+static size_t gdbudp_recv ( char *buf, size_t len ) {
+ struct io_buffer *iob;
+ struct ethhdr *ethhdr;
+ struct arphdr *arphdr;
+ struct iphdr *iphdr;
+ struct udp_header *udphdr;
+ size_t payload_len;
+
+ gdbudp_ensure_netdev_open ( netdev );
+
+ for ( ; ; ) {
+ netdev_poll ( netdev );
+ while ( ( iob = netdev_rx_dequeue ( netdev ) ) != NULL ) {
+ /* Ethernet header */
+ if ( iob_len ( iob ) < sizeof ( *ethhdr ) ) {
+ goto bad_packet;
+ }
+ ethhdr = iob->data;
+ iob_pull ( iob, sizeof ( *ethhdr ) );
+
+ /* Handle ARP requests so the client can find our MAC */
+ if ( ethhdr->h_protocol == htons ( ETH_P_ARP ) ) {
+ arphdr = iob->data;
+ if ( iob_len ( iob ) < sizeof ( *arphdr ) + 2 * ( ETH_ALEN + sizeof ( struct in_addr ) ) ||
+ arphdr->ar_hrd != htons ( ARPHRD_ETHER ) ||
+ arphdr->ar_pro != htons ( ETH_P_IP ) ||
+ arphdr->ar_hln != ETH_ALEN ||
+ arphdr->ar_pln != sizeof ( struct in_addr ) ||
+ arphdr->ar_op != htons ( ARPOP_REQUEST ) ||
+ * ( uint32_t * ) arp_target_pa ( arphdr ) != source_addr.sin_addr.s_addr ) {
+ goto bad_packet;
+ }
+
+ /* Generate an ARP reply */
+ arphdr->ar_op = htons ( ARPOP_REPLY );
+ memswap ( arp_sender_pa ( arphdr ), arp_target_pa ( arphdr ), sizeof ( struct in_addr ) );
+ memcpy ( arp_target_ha ( arphdr ), arp_sender_ha ( arphdr ), ETH_ALEN );
+ memcpy ( arp_sender_ha ( arphdr ), netdev->ll_addr, ETH_ALEN );
+
+ /* Fix up ethernet header */
+ ethhdr = iob_push ( iob, sizeof ( *ethhdr ) );
+ memcpy ( ethhdr->h_dest, ethhdr->h_source, ETH_ALEN );
+ memcpy ( ethhdr->h_source, netdev->ll_addr, ETH_ALEN );
+
+ netdev_tx ( netdev, iob );
+ continue; /* no need to free iob */
+ }
+
+ if ( ethhdr->h_protocol != htons ( ETH_P_IP ) ) {
+ goto bad_packet;
+ }
+
+ /* IP header */
+ if ( iob_len ( iob ) < sizeof ( *iphdr ) ) {
+ goto bad_packet;
+ }
+ iphdr = iob->data;
+ iob_pull ( iob, sizeof ( *iphdr ) );
+ if ( iphdr->protocol != IP_UDP || iphdr->dest.s_addr != source_addr.sin_addr.s_addr ) {
+ goto bad_packet;
+ }
+
+ /* UDP header */
+ if ( iob_len ( iob ) < sizeof ( *udphdr ) ) {
+ goto bad_packet;
+ }
+ udphdr = iob->data;
+ if ( udphdr->dest != source_addr.sin_port ) {
+ goto bad_packet;
+ }
+
+ /* Learn the remote connection details */
+ memcpy ( dest_eth, ethhdr->h_source, ETH_ALEN );
+ dest_addr.sin_addr.s_addr = iphdr->src.s_addr;
+ dest_addr.sin_port = udphdr->src;
+
+ /* Payload */
+ payload_len = ntohs ( udphdr->len );
+ if ( payload_len < sizeof ( *udphdr ) || payload_len > iob_len ( iob ) ) {
+ goto bad_packet;
+ }
+ payload_len -= sizeof ( *udphdr );
+ iob_pull ( iob, sizeof ( *udphdr ) );
+ if ( payload_len > len ) {
+ goto bad_packet;
+ }
+ memcpy ( buf, iob->data, payload_len );
+
+ free_iob ( iob );
+ return payload_len;
+
+bad_packet:
+ free_iob ( iob );
+ }
+ cpu_nap();
+ }
+}
+
+static void gdbudp_send ( const char *buf, size_t len ) {
+ struct io_buffer *iob;
+ struct ethhdr *ethhdr;
+ struct iphdr *iphdr;
+ struct udp_header *udphdr;
+
+ /* Check that we are connected */
+ if ( dest_addr.sin_port == 0 ) {
+ return;
+ }
+
+ gdbudp_ensure_netdev_open ( netdev );
+
+ iob = alloc_iob ( sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) + len );
+ if ( !iob ) {
+ return;
+ }
+
+ /* Payload */
+ iob_reserve ( iob, sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) );
+ memcpy ( iob_put ( iob, len ), buf, len );
+
+ /* UDP header */
+ udphdr = iob_push ( iob, sizeof ( *udphdr ) );
+ udphdr->src = source_addr.sin_port;
+ udphdr->dest = dest_addr.sin_port;
+ udphdr->len = htons ( iob_len ( iob ) );
+ udphdr->chksum = 0; /* optional and we are not using it */
+
+ /* IP header */
+ iphdr = iob_push ( iob, sizeof ( *iphdr ) );
+ memset ( iphdr, 0, sizeof ( *iphdr ) );
+ iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
+ iphdr->service = IP_TOS;
+ iphdr->len = htons ( iob_len ( iob ) );
+ iphdr->ttl = IP_TTL;
+ iphdr->protocol = IP_UDP;
+ iphdr->dest.s_addr = dest_addr.sin_addr.s_addr;
+ iphdr->src.s_addr = source_addr.sin_addr.s_addr;
+ iphdr->chksum = tcpip_chksum ( iphdr, sizeof ( *iphdr ) );
+
+ /* Ethernet header */
+ ethhdr = iob_push ( iob, sizeof ( *ethhdr ) );
+ memcpy ( ethhdr->h_dest, dest_eth, ETH_ALEN );
+ memcpy ( ethhdr->h_source, netdev->ll_addr, ETH_ALEN );
+ ethhdr->h_protocol = htons ( ETH_P_IP );
+
+ netdev_tx ( netdev, iob );
+}
+
+struct gdb_transport *gdbudp_configure ( const char *name, struct sockaddr_in *addr ) {
+ struct settings *settings;
+
+ /* Release old network device */
+ netdev_put ( netdev );
+
+ netdev = find_netdev ( name );
+ if ( !netdev ) {
+ return NULL;
+ }
+
+ /* Hold network device */
+ netdev_get ( netdev );
+
+ /* Source UDP port */
+ source_addr.sin_port = ( addr && addr->sin_port ) ? addr->sin_port : htons ( DEFAULT_PORT );
+
+ /* Source IP address */
+ if ( addr && addr->sin_addr.s_addr ) {
+ source_addr.sin_addr.s_addr = addr->sin_addr.s_addr;
+ } else {
+ settings = netdev_settings ( netdev );
+ fetch_ipv4_setting ( settings, &ip_setting, &source_addr.sin_addr );
+ if ( source_addr.sin_addr.s_addr == 0 ) {
+ netdev_put ( netdev );
+ netdev = NULL;
+ return NULL;
+ }
+ }
+
+ return &udp_gdb_transport;
+}
+
+static int gdbudp_init ( int argc, char **argv ) {
+ if ( argc != 1 ) {
+ printf ( "udp: missing <interface> argument\n" );
+ return 1;
+ }
+
+ if ( !gdbudp_configure ( argv[0], NULL ) ) {
+ printf ( "%s: device does not exist or has no IP address\n", argv[0] );
+ return 1;
+ }
+ return 0;
+}
+
+struct gdb_transport udp_gdb_transport __gdb_transport = {
+ .name = "udp",
+ .init = gdbudp_init,
+ .send = gdbudp_send,
+ .recv = gdbudp_recv,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/core/getkey.c b/src/VBox/Devices/PC/ipxe/src/core/getkey.c
new file mode 100644
index 00000000..d692b1bc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/getkey.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ctype.h>
+#include <ipxe/console.h>
+#include <ipxe/process.h>
+#include <ipxe/keys.h>
+#include <ipxe/timer.h>
+
+/** @file
+ *
+ * Special key interpretation
+ *
+ */
+
+#define GETKEY_TIMEOUT ( TICKS_PER_SEC / 4 )
+
+/**
+ * Read character from console if available within timeout period
+ *
+ * @v timeout Timeout period, in ticks (0=indefinite)
+ * @ret character Character read from console
+ */
+static int getchar_timeout ( unsigned long timeout ) {
+ unsigned long start = currticks();
+
+ while ( ( timeout == 0 ) || ( ( currticks() - start ) < timeout ) ) {
+ step();
+ if ( iskey() )
+ return getchar();
+ }
+
+ return -1;
+}
+
+/**
+ * Get single keypress
+ *
+ * @v timeout Timeout period, in ticks (0=indefinite)
+ * @ret key Key pressed
+ *
+ * The returned key will be an ASCII value or a KEY_XXX special
+ * constant. This function differs from getchar() in that getchar()
+ * will return "special" keys (e.g. cursor keys) as a series of
+ * characters forming an ANSI escape sequence.
+ */
+int getkey ( unsigned long timeout ) {
+ int character;
+ unsigned int n = 0;
+
+ character = getchar_timeout ( timeout );
+ if ( character != ESC )
+ return character;
+
+ while ( ( character = getchar_timeout ( GETKEY_TIMEOUT ) ) >= 0 ) {
+ if ( character == '[' )
+ continue;
+ if ( isdigit ( character ) ) {
+ n = ( ( n * 10 ) + ( character - '0' ) );
+ continue;
+ }
+ if ( character >= 0x40 )
+ return KEY_ANSI ( n, character );
+ }
+
+ return ESC;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/getopt.c b/src/VBox/Devices/PC/ipxe/src/core/getopt.c
new file mode 100644
index 00000000..8a0fa2d0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/getopt.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <getopt.h>
+
+/** @file
+ *
+ * Parse command-line options
+ *
+ */
+
+/**
+ * Option argument
+ *
+ * This will point to the argument for the most recently returned
+ * option, if applicable.
+ */
+char *optarg;
+
+/**
+ * Current option index
+ *
+ * This is an index into the argv[] array. When getopt() returns -1,
+ * @c optind is the index to the first element that is not an option.
+ */
+int optind;
+
+/**
+ * Current option character index
+ *
+ * This is an index into the current element of argv[].
+ */
+int nextchar;
+
+/**
+ * Unrecognised option
+ *
+ * When an unrecognised option is encountered, the actual option
+ * character is stored in @c optopt.
+ */
+int optopt;
+
+/**
+ * Get option argument from argv[] array
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret argument Option argument, or NULL
+ *
+ * Grab the next element of argv[], if it exists and is not an option.
+ */
+static const char * get_argv_argument ( int argc, char * const argv[] ) {
+ char *arg;
+
+ /* Don't overrun argv[] */
+ if ( optind >= argc )
+ return NULL;
+ arg = argv[optind];
+
+ /* If next argv element is an option, then it's not usable as
+ * an argument.
+ */
+ if ( *arg == '-' )
+ return NULL;
+
+ /** Consume this argv element, and return it */
+ optind++;
+ return arg;
+}
+
+/**
+ * Match long option
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v opttext Option text within current argv[] element
+ * @v longopt Long option specification
+ * @ret option Option to return from getopt()
+ * @ret matched Found a match for this long option
+ */
+static int match_long_option ( int argc, char * const argv[],
+ const char *opttext,
+ const struct option *longopt, int *option ) {
+ size_t optlen;
+ const char *argument = NULL;
+
+ /* Compare option name */
+ optlen = strlen ( longopt->name );
+ if ( strncmp ( opttext, longopt->name, optlen ) != 0 )
+ return 0;
+
+ /* Check for inline argument */
+ if ( opttext[optlen] == '=' ) {
+ argument = &opttext[ optlen + 1 ];
+ } else if ( opttext[optlen] ) {
+ /* Long option with trailing garbage - no match */
+ return 0;
+ }
+
+ /* Consume this argv element */
+ optind++;
+
+ /* If we want an argument but don't have one yet, try to grab
+ * the next argv element
+ */
+ if ( ( longopt->has_arg != no_argument ) && ( ! argument ) )
+ argument = get_argv_argument ( argc, argv );
+
+ /* If we need an argument but don't have one, sulk */
+ if ( ( longopt->has_arg == required_argument ) && ( ! argument ) ) {
+ printf ( "Option \"%s\" requires an argument\n",
+ longopt->name );
+ *option = ':';
+ return 1;
+ }
+
+ /* If we have an argument where we shouldn't have one, sulk */
+ if ( ( longopt->has_arg == no_argument ) && argument ) {
+ printf ( "Option \"%s\" takes no argument\n", longopt->name );
+ *option = ':';
+ return 1;
+ }
+
+ /* Store values and return success */
+ optarg = ( char * ) argument;
+ if ( longopt->flag ) {
+ *(longopt->flag) = longopt->val;
+ *option = 0;
+ } else {
+ *option = longopt->val;
+ }
+ return 1;
+}
+
+/**
+ * Match short option
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v opttext Option text within current argv[] element
+ * @v shortopt Option character from option specification
+ * @ret option Option to return from getopt()
+ * @ret matched Found a match for this short option
+ */
+static int match_short_option ( int argc, char * const argv[],
+ const char *opttext, int shortopt,
+ enum getopt_argument_requirement has_arg,
+ int *option ) {
+ const char *argument = NULL;
+
+ /* Compare option character */
+ if ( *opttext != shortopt )
+ return 0;
+
+ /* Consume option character */
+ opttext++;
+ nextchar++;
+ if ( *opttext ) {
+ if ( has_arg != no_argument ) {
+ /* Consume remainder of element as inline argument */
+ argument = opttext;
+ optind++;
+ nextchar = 0;
+ }
+ } else {
+ /* Reached end of argv element */
+ optind++;
+ nextchar = 0;
+ }
+
+ /* If we want an argument but don't have one yet, try to grab
+ * the next argv element
+ */
+ if ( ( has_arg != no_argument ) && ( ! argument ) )
+ argument = get_argv_argument ( argc, argv );
+
+ /* If we need an argument but don't have one, sulk */
+ if ( ( has_arg == required_argument ) && ( ! argument ) ) {
+ printf ( "Option \"%c\" requires an argument\n", shortopt );
+ *option = ':';
+ return 1;
+ }
+
+ /* Store values and return success */
+ optarg = ( char * ) argument;
+ *option = shortopt;
+ return 1;
+}
+
+/**
+ * Parse command-line options
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v optstring Option specification string
+ * @v longopts Long option specification table
+ * @ret longindex Index of long option (or NULL)
+ * @ret option Option found, or -1 for no more options
+ *
+ * Note that the caller must arrange for reset_getopt() to be called
+ * before each set of calls to getopt_long(). In Etherboot, this is
+ * done automatically by execv().
+ */
+int getopt_long ( int argc, char * const argv[], const char *optstring,
+ const struct option *longopts, int *longindex ) {
+ const char *opttext = argv[optind];
+ const struct option *longopt;
+ int shortopt;
+ enum getopt_argument_requirement has_arg;
+ int option;
+
+ /* Check for end of argv array */
+ if ( optind >= argc )
+ return -1;
+
+ /* Check for end of options */
+ if ( *(opttext++) != '-' )
+ return -1;
+
+ /* Check for long options */
+ if ( *(opttext++) == '-' ) {
+ /* "--" indicates end of options */
+ if ( *opttext == '\0' ) {
+ optind++;
+ return -1;
+ }
+ for ( longopt = longopts ; longopt->name ; longopt++ ) {
+ if ( ! match_long_option ( argc, argv, opttext,
+ longopt, &option ) )
+ continue;
+ if ( longindex )
+ *longindex = ( longopt - longopts );
+ return option;
+ }
+ optopt = '?';
+ printf ( "Unrecognised option \"--%s\"\n", opttext );
+ return '?';
+ }
+
+ /* Check for short options */
+ if ( nextchar < 1 )
+ nextchar = 1;
+ opttext = ( argv[optind] + nextchar );
+ while ( ( shortopt = *(optstring++) ) ) {
+ has_arg = no_argument;
+ while ( *optstring == ':' ) {
+ has_arg++;
+ optstring++;
+ }
+ if ( match_short_option ( argc, argv, opttext, shortopt,
+ has_arg, &option ) ) {
+ return option;
+ }
+ }
+ optopt = *opttext;
+ printf ( "Unrecognised option \"-%c\"\n", optopt );
+ return '?';
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/hw.c b/src/VBox/Devices/PC/ipxe/src/core/hw.c
new file mode 100644
index 00000000..91736a65
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/hw.c
@@ -0,0 +1,69 @@
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/process.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+
+/** @file
+ *
+ * "Hello World" data source
+ *
+ */
+
+struct hw {
+ struct refcnt refcnt;
+ struct interface xfer;
+ struct process process;
+};
+
+static const char hw_msg[] = "Hello world!\n";
+
+static void hw_finished ( struct hw *hw, int rc ) {
+ intf_shutdown ( &hw->xfer, rc );
+ process_del ( &hw->process );
+}
+
+static void hw_step ( struct hw *hw ) {
+ int rc;
+
+ if ( xfer_window ( &hw->xfer ) ) {
+ rc = xfer_deliver_raw ( &hw->xfer, hw_msg, sizeof ( hw_msg ) );
+ hw_finished ( hw, rc );
+ }
+}
+
+static struct interface_operation hw_xfer_operations[] = {
+ INTF_OP ( xfer_window_changed, struct hw *, hw_step ),
+ INTF_OP ( intf_close, struct hw *, hw_finished ),
+};
+
+static struct interface_descriptor hw_xfer_desc =
+ INTF_DESC ( struct hw, xfer, hw_xfer_operations );
+
+static struct process_descriptor hw_process_desc =
+ PROC_DESC_ONCE ( struct hw, process, hw_step );
+
+static int hw_open ( struct interface *xfer, struct uri *uri __unused ) {
+ struct hw *hw;
+
+ /* Allocate and initialise structure */
+ hw = zalloc ( sizeof ( *hw ) );
+ if ( ! hw )
+ return -ENOMEM;
+ ref_init ( &hw->refcnt, NULL );
+ intf_init ( &hw->xfer, &hw_xfer_desc, &hw->refcnt );
+ process_init ( &hw->process, &hw_process_desc, &hw->refcnt );
+
+ /* Attach parent interface, mortalise self, and return */
+ intf_plug_plug ( &hw->xfer, xfer );
+ ref_put ( &hw->refcnt );
+ return 0;
+}
+
+struct uri_opener hw_uri_opener __uri_opener = {
+ .scheme = "hw",
+ .open = hw_open,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/core/i82365.c b/src/VBox/Devices/PC/ipxe/src/core/i82365.c
new file mode 100644
index 00000000..c26639e0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/i82365.c
@@ -0,0 +1,656 @@
+#ifdef CONFIG_PCMCIA
+
+/*
+ * i82365.c
+ * Support for i82365 and similar ISA-to-PCMCIA bridges
+ *
+ * Taken from Linux kernel sources, distributed under GPL2
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * Ported by: Anselm Martin Hoffmeister, Stockholm Projekt Computer-Service, Sankt Augustin/Bonn, GERMANY
+ */
+
+/*
+ *
+ *
+ * ******************************
+ * PLEASE DO NOT YET WORK ON THIS
+ * ******************************
+ *
+ * I'm still fixing it up on every end, so we most probably would interfere
+ * at some point. If there's anything obvious or better, not-so-obvious,
+ * please contact me by e-mail: anselm (AT) hoffmeister (DOT) be *THANKS*
+ */
+#include "../include/pcmcia.h"
+#include "../include/pcmcia-opts.h"
+#include "../include/i82365.h"
+
+#ifndef CONFIG_ISA
+#error PCMCIA_I82365 only works with ISA defined - set CONFIG_ISA
+#endif
+
+typedef enum pcic_id {
+ IS_I82365A, IS_I82365B, IS_I82365DF,
+ IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469,
+ IS_PD6710, IS_PD672X, IS_VT83C469,
+} pcic_id;
+
+/* Flags for classifying groups of controllers */
+#define IS_VADEM 0x0001
+#define IS_CIRRUS 0x0002
+#define IS_TI 0x0004
+#define IS_O2MICRO 0x0008
+#define IS_VIA 0x0010
+#define IS_TOPIC 0x0020
+#define IS_RICOH 0x0040
+#define IS_UNKNOWN 0x0400
+#define IS_VG_PWR 0x0800
+#define IS_DF_PWR 0x1000
+#define IS_PCI 0x2000
+#define IS_ALIVE 0x8000
+
+typedef struct pcic_t {
+ char *name;
+ u_short flags;
+} pcic_t;
+
+static pcic_t pcic[] = {
+ { "Intel i82365sl A step", 0 },
+ { "Intel i82365sl B step", 0 },
+ { "Intel i82365sl DF", IS_DF_PWR },
+ { "IBM Clone", 0 },
+ { "Ricoh RF5C296/396", 0 },
+ { "VLSI 82C146", 0 },
+ { "Vadem VG-468", IS_VADEM },
+ { "Vadem VG-469", IS_VADEM|IS_VG_PWR },
+ { "Cirrus PD6710", IS_CIRRUS },
+ { "Cirrus PD672x", IS_CIRRUS },
+ { "VIA VT83C469", IS_CIRRUS|IS_VIA },
+};
+
+typedef struct cirrus_state_t {
+ u_char misc1, misc2;
+ u_char timer[6];
+} cirrus_state_t;
+
+typedef struct vg46x_state_t {
+ u_char ctl, ema;
+} vg46x_state_t;
+
+typedef struct socket_info_t {
+ u_short type, flags;
+ socket_cap_t cap;
+ ioaddr_t ioaddr;
+ u_short psock;
+ u_char cs_irq, intr;
+ void (*handler)(void *info, u_int events);
+ void *info;
+ union {
+ cirrus_state_t cirrus;
+ vg46x_state_t vg46x;
+ } state;
+} socket_info_t;
+
+//static socket_info_t socket[8];
+
+int i365_base = 0x3e0; // Default in Linux kernel
+int cycle_time = 120; // External clock time in ns, 120ns =~ 8.33 MHz
+int mydriverid = 0;
+
+void phex ( unsigned char c );
+/*static int to_cycles(int ns)
+{
+ return ns/cycle_time;
+}
+*/
+/*static int to_ns(int cycles)
+{
+ return cycle_time*cycles;
+}
+*/
+
+static u_char i365_get(u_short sock, u_short reg)
+{
+ //unsigned long flags;
+ //spin_lock_irqsave(&bus_lock,flags);
+ {
+ ioaddr_t port = pccsock[sock].ioaddr;
+ u_char val;
+ reg = I365_REG(pccsock[sock].internalid, reg);
+ outb(reg, port); val = inb(port+1);
+ //spin_unlock_irqrestore(&bus_lock,flags);
+ return val;
+ }
+}
+
+static void i365_set(u_short sock, u_short reg, u_char data)
+{
+ //unsigned long flags;
+ //spin_lock_irqsave(&bus_lock,flags);
+ {
+ ioaddr_t port = pccsock[sock].ioaddr;
+ u_char val = I365_REG(pccsock[sock].internalid, reg);
+ outb(val, port); outb(data, port+1);
+ //spin_unlock_irqrestore(&bus_lock,flags);
+ }
+}
+
+void add_socket_i365(u_short port, int psock, int type) {
+ pccsock[pccsocks].ioaddr = port;
+ pccsock[pccsocks].internalid = psock;
+ pccsock[pccsocks].type = type;
+ pccsock[pccsocks].flags = pcic[type].flags;
+ pccsock[pccsocks].drivernum = mydriverid;
+ pccsock[pccsocks].configoffset = -1;
+ // Find out if a card in inside that socket
+ pccsock[pccsocks].status = (( 12 == (i365_get(pccsocks,I365_STATUS)&12) ) ? HASCARD : EMPTY );
+ // *TODO* check if that's all
+ if ( 0 == (psock & 1) ) {
+ printf ( "Found a PCMCIA controller (i82365) at io %x, type '%s'\n", port, pcic[type].name );
+ // pccsock[pccsocks].status == HASCARD? "holds card":"empty" );
+ }
+ pccsocks++;
+ return;
+}
+
+void i365_bset(u_short sock, u_short reg, u_char mask) {
+ u_char d = i365_get(sock, reg);
+ d |= mask;
+ i365_set(sock, reg, d);
+}
+
+void i365_bclr(u_short sock, u_short reg, u_char mask) {
+ u_char d = i365_get(sock, reg);
+ d &= ~mask;
+ i365_set(sock, reg, d);
+}
+
+
+/*static void i365_bflip(u_short sock, u_short reg, u_char mask, int b)
+{
+ u_char d = i365_get(sock, reg);
+ if (b)
+ d |= mask;
+ else
+ d &= ~mask;
+ i365_set(sock, reg, d);
+}
+*/
+
+/*
+static u_short i365_get_pair(u_short sock, u_short reg)
+{
+ u_short a, b;
+ a = i365_get(sock, reg);
+ b = i365_get(sock, reg+1);
+ return (a + (b<<8));
+}
+*/
+
+/*
+static void i365_set_pair(u_short sock, u_short reg, u_short data)
+{
+ i365_set(sock, reg, data & 0xff);
+ i365_set(sock, reg+1, data >> 8);
+}
+*/
+int identify_i365 ( u_short port, u_short sock ) {
+ u_char val;
+ int type = -1;
+ /* Use the next free entry in the socket table */
+ pccsock[pccsocks].ioaddr = port;
+ pccsock[pccsocks].internalid = sock;
+ // *TODO* wakeup a sleepy cirrus controller?
+
+ if ((val = i365_get(pccsocks, I365_IDENT)) & 0x70)
+ return -1;
+ switch (val) {
+ case 0x82:
+ type = IS_I82365A; break;
+ case 0x83:
+ type = IS_I82365B; break;
+ case 0x84:
+ type = IS_I82365DF; break;
+ case 0x88: case 0x89: case 0x8a:
+ type = IS_IBM; break;
+ }
+ /* Check for Vadem VG-468 chips */
+ outb(0x0e, port);
+ outb(0x37, port);
+ i365_bset(pccsocks, VG468_MISC, VG468_MISC_VADEMREV);
+ val = i365_get(pccsocks, I365_IDENT);
+ if (val & I365_IDENT_VADEM) {
+ i365_bclr(pccsocks, VG468_MISC, VG468_MISC_VADEMREV);
+ type = ((val & 7) >= 4) ? IS_VG469 : IS_VG468;
+ }
+
+ /* Check for Ricoh chips */
+ val = i365_get(pccsocks, RF5C_CHIP_ID);
+ if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396)) type = IS_RF5Cx96;
+
+ /* Check for Cirrus CL-PD67xx chips */
+ i365_set(pccsocks, PD67_CHIP_INFO, 0);
+ val = i365_get(pccsocks, PD67_CHIP_INFO);
+ if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) {
+ val = i365_get(pccsocks, PD67_CHIP_INFO);
+ if ((val & PD67_INFO_CHIP_ID) == 0) {
+ type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710;
+ i365_set(pccsocks, PD67_EXT_INDEX, 0xe5);
+ if (i365_get(pccsocks, PD67_EXT_INDEX) != 0xe5) type = IS_VT83C469;
+ }
+ }
+ return type;
+}
+
+int init_i82365(void) {
+ int i, j, sock, k, ns, id;
+ //unsigned int ui,uj;
+ //unsigned char * upc;
+ ioaddr_t port;
+ int i82365s = 0;
+ // Change from kernel: No irq init, no check_region, no isapnp support
+ // No ignore socket, no extra sockets to check (so it's easier here :-/)
+ // Probably we don't need any of them; in case YOU do, SHOUT AT ME!
+ id = identify_i365(i365_base, 0);
+ if ((id == IS_I82365DF) && (identify_i365(i365_base, 1) != id)) {
+ for (i = 0; i < 4; i++) {
+ port = i365_base + ((i & 1) << 2) + ((i & 2) << 1);
+ sock = (i & 1) << 1;
+ if (identify_i365(port, sock) == IS_I82365DF) {
+ add_socket_i365(port, sock, IS_VLSI);
+ }
+ }
+ } else {
+ for (i = 0; i < 4; i += 2) {
+ port = i365_base + 2*(i>>2);
+ sock = (i & 3);
+ id = identify_i365(port, sock);
+ if (id < 0) continue;
+
+ for (j = ns = 0; j < 2; j++) {
+ /* Does the socket exist? */
+ if (identify_i365(port, sock+j) < 0) continue;
+ /* Check for bad socket decode */
+ for (k = 0; k <= i82365s; k++)
+ i365_set(k, I365_MEM(0)+I365_W_OFF, k);
+ for (k = 0; k <= i82365s; k++)
+ if (i365_get(k, I365_MEM(0)+I365_W_OFF) != k)
+ break;
+ if (k <= i82365s) break;
+ add_socket_i365(port, sock+j, id); ns++;
+ }
+ }
+ }
+ return 0;
+
+
+
+
+
+
+
+/* printf ( "Selecting config 1: io 0x300 @byte 87*2.." );
+ upc[(2*87)] = 2;
+ i365_bclr(1, I365_ADDRWIN, 1 );
+ i365_set(1,I365_INTCTL, 0x65 ); //no-reset, memory-card
+ i365_set(1, I365_IO(0)+0, 0x20 );
+ i365_set(1, I365_IO(0)+1, 0x03 );
+ i365_set(1, I365_IO(0)+2, 0x3f );
+ i365_set(1, I365_IO(0)+3, 0x03 );
+ i365_set(1, 0x3a, 0x05 );
+ i365_set(1, 0x3b, 0x05 );
+ i365_set(1, 0x3c, 0x05 );
+ i365_set(1, 0x3d, 0x05 );
+ i365_set(1, 0x3e, 0x05 );
+ i365_set(1, 0x3f, 0x05 );
+ i365_set(1, 0x07, 0x0a );
+ i365_set(1, I365_ADDRWIN, 0x40 ); // 0x40
+ printf ( "!\n" ); getchar();
+ printf ( "\n" );
+ return 0; */
+}
+
+void phex ( unsigned char c ) {
+ unsigned char a = 0, b = 0;
+ b = ( c & 0xf );
+ if ( b > 9 ) b += ('a'-'9'-1);
+ b += '0';
+ a = ( c & 0xf0 ) >> 4;
+ if ( a > 9 ) a += ('a'-'9'-1);
+ a += '0';
+ printf ( "%c%c ", a, b );
+ return;
+}
+
+int deinit_i82365(void) {
+ printf("Deinitializing i82365\n" );
+ return 0;
+}
+
+/*static int i365_get_status(u_short sock, u_int *value)
+{
+ u_int status;
+
+ status = i365_get(sock, I365_STATUS);
+ *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)
+ ? SS_DETECT : 0;
+
+ if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD)
+ *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
+ else {
+ *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
+ *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
+ }
+ *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
+ *value |= (status & I365_CS_READY) ? SS_READY : 0;
+ *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
+
+#ifdef CONFIG_ISA
+ if (pccsock[sock].type == IS_VG469) {
+ status = i365_get(sock, VG469_VSENSE);
+ if (pccsock[sock].internalid & 1) {
+ *value |= (status & VG469_VSENSE_B_VS1) ? 0 : SS_3VCARD;
+ *value |= (status & VG469_VSENSE_B_VS2) ? 0 : SS_XVCARD;
+ } else {
+ *value |= (status & VG469_VSENSE_A_VS1) ? 0 : SS_3VCARD;
+ *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;
+ }
+ }
+#endif
+
+ printf("i82365: GetStatus(%d) = %#4.4x\n", sock, *value);
+ return 0;
+} //i365_get_status
+*/
+
+/*static int i365_set_socket(u_short sock, socket_state_t *state)
+{
+ socket_info_t *t = &socket[sock];
+ u_char reg;
+
+ printf("i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
+ "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
+ state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
+printf ("\nERROR:UNIMPLEMENTED\n" );
+return 0;
+ // First set global controller options
+ // set_bridge_state(sock); *TODO* check: need this here?
+
+ // IO card, RESET flag, IO interrupt
+ reg = t->intr;
+ if (state->io_irq != t->cap.pci_irq) reg |= state->io_irq;
+ reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
+ reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
+ i365_set(sock, I365_INTCTL, reg);
+
+ reg = I365_PWR_NORESET;
+ if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
+ if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
+
+ if (t->flags & IS_CIRRUS) {
+ if (state->Vpp != 0) {
+ if (state->Vpp == 120)
+ reg |= I365_VPP1_12V;
+ else if (state->Vpp == state->Vcc)
+ reg |= I365_VPP1_5V;
+ else return -EINVAL;
+ }
+ if (state->Vcc != 0) {
+ reg |= I365_VCC_5V;
+ if (state->Vcc == 33)
+ i365_bset(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
+ else if (state->Vcc == 50)
+ i365_bclr(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
+ else return -EINVAL;
+ }
+ } else if (t->flags & IS_VG_PWR) {
+ if (state->Vpp != 0) {
+ if (state->Vpp == 120)
+ reg |= I365_VPP1_12V;
+ else if (state->Vpp == state->Vcc)
+ reg |= I365_VPP1_5V;
+ else return -EINVAL;
+ }
+ if (state->Vcc != 0) {
+ reg |= I365_VCC_5V;
+ if (state->Vcc == 33)
+ i365_bset(sock, VG469_VSELECT, VG469_VSEL_VCC);
+ else if (state->Vcc == 50)
+ i365_bclr(sock, VG469_VSELECT, VG469_VSEL_VCC);
+ else return -EINVAL;
+ }
+ } else if (t->flags & IS_DF_PWR) {
+ switch (state->Vcc) {
+ case 0: break;
+ case 33: reg |= I365_VCC_3V; break;
+ case 50: reg |= I365_VCC_5V; break;
+ default: return -EINVAL;
+ }
+ switch (state->Vpp) {
+ case 0: break;
+ case 50: reg |= I365_VPP1_5V; break;
+ case 120: reg |= I365_VPP1_12V; break;
+ default: return -EINVAL;
+ }
+ } else {
+ switch (state->Vcc) {
+ case 0: break;
+ case 50: reg |= I365_VCC_5V; break;
+ default: return -EINVAL;
+ }
+ switch (state->Vpp) {
+ case 0: break;
+ case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break;
+ case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break;
+ default: return -EINVAL;
+ }
+ }
+
+ if (reg != i365_get(sock, I365_POWER))
+ i365_set(sock, I365_POWER, reg);
+
+ // Chipset-specific functions
+ if (t->flags & IS_CIRRUS) {
+ // Speaker control
+ i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA,
+ state->flags & SS_SPKR_ENA);
+ }
+
+ // Card status change interrupt mask
+ reg = t->cs_irq << 4;
+ if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
+ if (state->flags & SS_IOCARD) {
+ if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
+ } else {
+ if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1;
+ if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2;
+ if (state->csc_mask & SS_READY) reg |= I365_CSC_READY;
+ }
+ i365_set(sock, I365_CSCINT, reg);
+ i365_get(sock, I365_CSC);
+
+ return 0;
+} // i365_set_socket
+*/
+
+/*static int i365_get_io_map(u_short sock, struct pccard_io_map *io)
+{
+ u_char map, ioctl, addr;
+ printf ( "GETIOMAP unimplemented\n" ); return 0;
+ map = io->map;
+ if (map > 1) return -EINVAL;
+ io->start = i365_get_pair(sock, I365_IO(map)+I365_W_START);
+ io->stop = i365_get_pair(sock, I365_IO(map)+I365_W_STOP);
+ ioctl = i365_get(sock, I365_IOCTL);
+ addr = i365_get(sock, I365_ADDRWIN);
+ io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0;
+ io->flags = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0;
+ io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0;
+ io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0;
+ io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0;
+ printf("i82365: GetIOMap(%d, %d) = %#2.2x, %d ns, "
+ "%#4.4x-%#4.4x\n", sock, map, io->flags, io->speed,
+ io->start, io->stop);
+ return 0;
+} // i365_get_io_map
+*/
+
+/*====================================================================*/
+
+/*static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
+{
+ u_char map, ioctl;
+
+ printf("i82365: SetIOMap(%d, %d, %#2.2x, %d ns, "
+ "%#4.4x-%#4.4x)\n", sock, io->map, io->flags,
+ io->speed, io->start, io->stop);
+printf ( "UNIMPLEMENTED\n" );
+ return 0;
+ map = io->map;
+ //if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
+ if ((map > 1) ||
+ (io->stop < io->start)) return -EINVAL;
+ // Turn off the window before changing anything
+ if (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(map))
+ i365_bclr(sock, I365_ADDRWIN, I365_ENA_IO(map));
+ i365_set_pair(sock, I365_IO(map)+I365_W_START, io->start);
+ i365_set_pair(sock, I365_IO(map)+I365_W_STOP, io->stop);
+ ioctl = i365_get(sock, I365_IOCTL) & ~I365_IOCTL_MASK(map);
+ if (io->speed) ioctl |= I365_IOCTL_WAIT(map);
+ if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
+ if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map);
+ if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map);
+ i365_set(sock, I365_IOCTL, ioctl);
+ // Turn on the window if necessary
+ if (io->flags & MAP_ACTIVE)
+ i365_bset(sock, I365_ADDRWIN, I365_ENA_IO(map));
+ return 0;
+} // i365_set_io_map
+*/
+
+/*
+static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
+{
+ u_short base, i;
+ u_char map;
+
+ printf("i82365: SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5"
+ "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed,
+ mem->sys_start, mem->sys_stop, mem->card_start);
+
+printf ( "UNIMPLEMENTED\n" );
+ return 0;
+ map = mem->map;
+ if ((map > 4) || (mem->card_start > 0x3ffffff) ||
+ (mem->sys_start > mem->sys_stop) || (mem->speed > 1000))
+ return -EINVAL;
+ if (!(socket[sock].flags & IS_PCI) &&
+ ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff)))
+ return -EINVAL;
+
+ // Turn off the window before changing anything
+ if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
+ i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
+
+ base = I365_MEM(map);
+ i = (mem->sys_start >> 12) & 0x0fff;
+ if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
+ if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
+ i365_set_pair(sock, base+I365_W_START, i);
+
+ i = (mem->sys_stop >> 12) & 0x0fff;
+ switch (to_cycles(mem->speed)) {
+ case 0: break;
+ case 1: i |= I365_MEM_WS0; break;
+ case 2: i |= I365_MEM_WS1; break;
+ default: i |= I365_MEM_WS1 | I365_MEM_WS0; break;
+ }
+ i365_set_pair(sock, base+I365_W_STOP, i);
+
+ i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
+ if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
+ if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
+ i365_set_pair(sock, base+I365_W_OFF, i);
+
+ // Turn on the window if necessary
+ if (mem->flags & MAP_ACTIVE)
+ i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map));
+ return 0;
+} // i365_set_mem_map
+*/
+
+
+int i82365_interfacer ( interface_func_t func, int sockno, int par1, int par2, void* par3 ) {
+ //int i, j, k;
+ //u_int ui;
+ u_char *upc;
+ struct pcc_config_t * pccc;
+ switch ( func ) {
+ case INIT:
+ mydriverid = par1;
+ return init_i82365();
+ case SHUTDOWN:
+ i365_set(sockno, I365_ADDRWIN, i365_get(sockno, I365_ADDRWIN) & 0x20 );
+ i365_set(sockno, I365_INTCTL, 0x05 );
+ sleepticks(2);
+ i365_set(sockno,I365_INTCTL, 0x45 ); //no-reset, memory-card
+ break;
+ case MAPATTRMEM:
+ i365_set(sockno,I365_POWER, 0xb1 );
+ i365_set(sockno, I365_INTCTL, 0x05 );
+ sleepticks(2);
+ i365_set(sockno,I365_INTCTL, 0x45 ); //no-reset, memory-card
+ i365_set(sockno, I365_ADDRWIN, i365_get(sockno, I365_ADDRWIN) & 0x20 );
+ //i365_bclr(sockno, I365_ADDRWIN, 1 );
+ i365_set(sockno, I365_MEM(0)+0, ( par1 >> 12 )& 0xff ); //start
+ i365_set(sockno, I365_MEM(0)+1, ( par1 >> 20 ) & 0x0f );
+ i365_set(sockno, I365_MEM(0)+2, ((par1 + par2 - 1 ) >> 12 ) & 0xff ); //end
+ i365_set(sockno, I365_MEM(0)+3, (( par1 + par2 - 1 ) >> 20 ) & 0x0f );
+ i365_set(sockno, I365_MEM(0)+4, ((0x4000000 - par1) >> 12) & 0xff ); //offset low
+ i365_set(sockno, I365_MEM(0)+5, 0x40 | (((0x40000000 - par1) >> 12) & 0x3f));
+ i365_bset(sockno, I365_ADDRWIN, 1 );
+ if ( ! ( 1 & i365_get ( sockno, I365_ADDRWIN ) ) ) return 1;
+ break;
+ case UNMAPATTRMEM:
+ i365_set(sockno, I365_ADDRWIN, i365_get(sockno, I365_ADDRWIN) & 0x20 );
+ i365_set(sockno,I365_INTCTL, 0x45 ); //no-reset, memory-card
+ break;
+ case SELECTCONFIG: // Params: par1: config number; par3 config pointer pointer
+ if ( 0 > pccsock[sockno].configoffset ) return 1;
+ if ( NULL == (pccc = par3 ) ) return 2;
+ // write config number to
+ upc = ioremap ( MAP_ATTRMEM_TO, MAP_ATTRMEM_LEN );
+ if ( pccsock[sockno].configoffset > MAP_ATTRMEM_LEN ) return 3;
+ if ( ( par1 & 0x7fffffc0 ) ) return 4;
+ if ( pccc->index != par1 ) return 5;
+ upc[pccsock[sockno].configoffset] = ( upc[pccsock[sockno].configoffset] & 0xc0 ) | ( par1 & 0x3f );
+ i365_set(sockno, I365_IOCTL, (i365_get(sockno, I365_IOCTL) & 0xfe) | 0x20 ); // 16bit autosize
+ i365_set(sockno, I365_IO(0)+0, pccc->iowin & 0xff);
+ i365_set(sockno, I365_IO(0)+1, (pccc->iowin >> 8) & 0xff);
+ i365_set(sockno, I365_IO(0)+2, (pccc->iowin+pccc->iolen - 1) & 0xff);
+ i365_set(sockno, I365_IO(0)+3, ((pccc->iowin+pccc->iolen- 1) >> 8) & 0xff);
+ // Disable mem mapping
+ i365_bclr(sockno, I365_ADDRWIN, 1);
+ i365_set(sockno, I365_INTCTL, 0x65);
+ i365_bset(sockno, I365_ADDRWIN,0x40);
+ break;
+ default:
+ return -1; // ERROR: Unknown function called
+ }
+ return 0;
+}
+
+// get_mem_map[1320]
+// cirrus_get_state/set/opts...
+// vg46x_get_state/...
+// get_bridge_state/...
+
+#endif /* CONFIG_PCMCIA */
diff --git a/src/VBox/Devices/PC/ipxe/src/core/image.c b/src/VBox/Devices/PC/ipxe/src/core/image.c
new file mode 100644
index 00000000..bf9bb7fa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/image.c
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+#include <libgen.h>
+#include <syslog.h>
+#include <ipxe/list.h>
+#include <ipxe/umalloc.h>
+#include <ipxe/uri.h>
+#include <ipxe/image.h>
+
+/** @file
+ *
+ * Executable images
+ *
+ */
+
+/* Disambiguate the various error causes */
+#define EACCES_UNTRUSTED \
+ __einfo_error ( EINFO_EACCES_UNTRUSTED )
+#define EINFO_EACCES_UNTRUSTED \
+ __einfo_uniqify ( EINFO_EACCES, 0x01, "Untrusted image" )
+#define EACCES_PERMANENT \
+ __einfo_error ( EINFO_EACCES_PERMANENT )
+#define EINFO_EACCES_PERMANENT \
+ __einfo_uniqify ( EINFO_EACCES, 0x02, "Trust requirement is permanent" )
+
+/** List of registered images */
+struct list_head images = LIST_HEAD_INIT ( images );
+
+/** Currently-executing image */
+struct image *current_image;
+
+/** Current image trust requirement */
+static int require_trusted_images = 0;
+
+/** Prevent changes to image trust requirement */
+static int require_trusted_images_permanent = 0;
+
+/**
+ * Free executable image
+ *
+ * @v refcnt Reference counter
+ */
+static void free_image ( struct refcnt *refcnt ) {
+ struct image *image = container_of ( refcnt, struct image, refcnt );
+
+ DBGC ( image, "IMAGE %s freed\n", image->name );
+ free ( image->name );
+ free ( image->cmdline );
+ uri_put ( image->uri );
+ ufree ( image->data );
+ image_put ( image->replacement );
+ free ( image );
+}
+
+/**
+ * Allocate executable image
+ *
+ * @v uri URI, or NULL
+ * @ret image Executable image
+ */
+struct image * alloc_image ( struct uri *uri ) {
+ const char *name;
+ struct image *image;
+ int rc;
+
+ /* Allocate image */
+ image = zalloc ( sizeof ( *image ) );
+ if ( ! image )
+ goto err_alloc;
+
+ /* Initialise image */
+ ref_init ( &image->refcnt, free_image );
+ if ( uri ) {
+ image->uri = uri_get ( uri );
+ if ( uri->path ) {
+ name = basename ( ( char * ) uri->path );
+ if ( ( rc = image_set_name ( image, name ) ) != 0 )
+ goto err_set_name;
+ }
+ }
+
+ return image;
+
+ err_set_name:
+ image_put ( image );
+ err_alloc:
+ return NULL;
+}
+
+/**
+ * Set image name
+ *
+ * @v image Image
+ * @v name New image name
+ * @ret rc Return status code
+ */
+int image_set_name ( struct image *image, const char *name ) {
+ char *name_copy;
+
+ /* Duplicate name */
+ name_copy = strdup ( name );
+ if ( ! name_copy )
+ return -ENOMEM;
+
+ /* Replace existing name */
+ free ( image->name );
+ image->name = name_copy;
+
+ return 0;
+}
+
+/**
+ * Set image command line
+ *
+ * @v image Image
+ * @v cmdline New image command line, or NULL
+ * @ret rc Return status code
+ */
+int image_set_cmdline ( struct image *image, const char *cmdline ) {
+
+ free ( image->cmdline );
+ image->cmdline = NULL;
+ if ( cmdline ) {
+ image->cmdline = strdup ( cmdline );
+ if ( ! image->cmdline )
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/**
+ * Register executable image
+ *
+ * @v image Executable image
+ * @ret rc Return status code
+ */
+int register_image ( struct image *image ) {
+ static unsigned int imgindex = 0;
+ char name[8]; /* "imgXXXX" */
+ int rc;
+
+ /* Create image name if it doesn't already have one */
+ if ( ! image->name ) {
+ snprintf ( name, sizeof ( name ), "img%d", imgindex++ );
+ if ( ( rc = image_set_name ( image, name ) ) != 0 )
+ return rc;
+ }
+
+ /* Avoid ending up with multiple "selected" images on
+ * re-registration
+ */
+ if ( image_find_selected() )
+ image->flags &= ~IMAGE_SELECTED;
+
+ /* Add to image list */
+ image_get ( image );
+ image->flags |= IMAGE_REGISTERED;
+ list_add_tail ( &image->list, &images );
+ DBGC ( image, "IMAGE %s at [%lx,%lx) registered\n",
+ image->name, user_to_phys ( image->data, 0 ),
+ user_to_phys ( image->data, image->len ) );
+
+ return 0;
+}
+
+/**
+ * Unregister executable image
+ *
+ * @v image Executable image
+ */
+void unregister_image ( struct image *image ) {
+
+ DBGC ( image, "IMAGE %s unregistered\n", image->name );
+ list_del ( &image->list );
+ image->flags &= ~IMAGE_REGISTERED;
+ image_put ( image );
+}
+
+/**
+ * Find image by name
+ *
+ * @v name Image name
+ * @ret image Executable image, or NULL
+ */
+struct image * find_image ( const char *name ) {
+ struct image *image;
+
+ list_for_each_entry ( image, &images, list ) {
+ if ( strcmp ( image->name, name ) == 0 )
+ return image;
+ }
+
+ return NULL;
+}
+
+/**
+ * Determine image type
+ *
+ * @v image Executable image
+ * @ret rc Return status code
+ */
+int image_probe ( struct image *image ) {
+ struct image_type *type;
+ int rc;
+
+ /* Succeed if we already have a type */
+ if ( image->type )
+ return 0;
+
+ /* Try each type in turn */
+ for_each_table_entry ( type, IMAGE_TYPES ) {
+ if ( ( rc = type->probe ( image ) ) == 0 ) {
+ image->type = type;
+ DBGC ( image, "IMAGE %s is %s\n",
+ image->name, type->name );
+ return 0;
+ }
+ DBGC ( image, "IMAGE %s is not %s: %s\n", image->name,
+ type->name, strerror ( rc ) );
+ }
+
+ DBGC ( image, "IMAGE %s format not recognised\n", image->name );
+ return -ENOEXEC;
+}
+
+/**
+ * Execute image
+ *
+ * @v image Executable image
+ * @ret rc Return status code
+ *
+ * The image must already be registered. Note that executing an image
+ * may cause it to unregister itself. The caller must therefore
+ * assume that the image pointer becomes invalid.
+ */
+int image_exec ( struct image *image ) {
+ struct image *saved_current_image;
+ struct image *replacement;
+ struct uri *old_cwuri;
+ int rc;
+
+ /* Sanity check */
+ assert ( image->flags & IMAGE_REGISTERED );
+
+ /* Check that this image can be selected for execution */
+ if ( ( rc = image_select ( image ) ) != 0 )
+ return rc;
+
+ /* Check that image is trusted (if applicable) */
+ if ( require_trusted_images && ! ( image->flags & IMAGE_TRUSTED ) ) {
+ DBGC ( image, "IMAGE %s is not trusted\n", image->name );
+ return -EACCES_UNTRUSTED;
+ }
+
+ /* Switch current working directory to be that of the image itself */
+ old_cwuri = uri_get ( cwuri );
+ churi ( image->uri );
+
+ /* Preserve record of any currently-running image */
+ saved_current_image = current_image;
+
+ /* Take out a temporary reference to the image. This allows
+ * the image to unregister itself if necessary, without
+ * automatically freeing itself.
+ */
+ current_image = image_get ( image );
+
+ /* Record boot attempt */
+ syslog ( LOG_NOTICE, "Executing \"%s\"\n", image->name );
+
+ /* Try executing the image */
+ if ( ( rc = image->type->exec ( image ) ) != 0 ) {
+ DBGC ( image, "IMAGE %s could not execute: %s\n",
+ image->name, strerror ( rc ) );
+ /* Do not return yet; we still have clean-up to do */
+ }
+
+ /* Record result of boot attempt */
+ if ( rc == 0 ) {
+ syslog ( LOG_NOTICE, "Execution of \"%s\" completed\n",
+ image->name );
+ } else {
+ syslog ( LOG_ERR, "Execution of \"%s\" failed: %s\n",
+ image->name, strerror ( rc ) );
+ }
+
+ /* Pick up replacement image before we drop the original
+ * image's temporary reference. The replacement image must
+ * already be registered, so we don't need to hold a temporary
+ * reference (which would complicate the tail-recursion).
+ */
+ replacement = image->replacement;
+ if ( replacement )
+ assert ( replacement->flags & IMAGE_REGISTERED );
+
+ /* Drop temporary reference to the original image */
+ image_put ( image );
+
+ /* Restore previous currently-running image */
+ current_image = saved_current_image;
+
+ /* Reset current working directory */
+ churi ( old_cwuri );
+ uri_put ( old_cwuri );
+
+ /* Tail-recurse into replacement image, if one exists */
+ if ( replacement ) {
+ DBGC ( image, "IMAGE <freed> replacing self with IMAGE %s\n",
+ replacement->name );
+ if ( ( rc = image_exec ( replacement ) ) != 0 )
+ return rc;
+ }
+
+ return rc;
+}
+
+/**
+ * Set replacement image
+ *
+ * @v replacement Replacement image
+ * @ret rc Return status code
+ *
+ * The replacement image must already be registered, and must remain
+ * registered until the currently-executing image returns.
+ */
+int image_replace ( struct image *replacement ) {
+ struct image *image = current_image;
+ int rc;
+
+ /* Sanity check */
+ assert ( replacement->flags & IMAGE_REGISTERED );
+
+ /* Fail unless there is a currently-executing image */
+ if ( ! image ) {
+ rc = -ENOTTY;
+ DBGC ( replacement, "IMAGE %s cannot replace non-existent "
+ "image: %s\n", replacement->name, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Check that the replacement image can be executed */
+ if ( ( rc = image_probe ( replacement ) ) != 0 )
+ return rc;
+
+ /* Clear any existing replacement */
+ image_put ( image->replacement );
+
+ /* Set replacement */
+ image->replacement = image_get ( replacement );
+ DBGC ( image, "IMAGE %s will replace self with IMAGE %s\n",
+ image->name, replacement->name );
+
+ return 0;
+}
+
+/**
+ * Select image for execution
+ *
+ * @v image Executable image
+ * @ret rc Return status code
+ */
+int image_select ( struct image *image ) {
+ struct image *tmp;
+ int rc;
+
+ /* Unselect all other images */
+ for_each_image ( tmp )
+ tmp->flags &= ~IMAGE_SELECTED;
+
+ /* Check that this image can be executed */
+ if ( ( rc = image_probe ( image ) ) != 0 )
+ return rc;
+
+ /* Mark image as selected */
+ image->flags |= IMAGE_SELECTED;
+
+ return 0;
+}
+
+/**
+ * Find selected image
+ *
+ * @ret image Executable image, or NULL
+ */
+struct image * image_find_selected ( void ) {
+ struct image *image;
+
+ for_each_image ( image ) {
+ if ( image->flags & IMAGE_SELECTED )
+ return image;
+ }
+ return NULL;
+}
+
+/**
+ * Change image trust requirement
+ *
+ * @v require_trusted Require trusted images
+ * @v permanent Make trust requirement permanent
+ * @ret rc Return status code
+ */
+int image_set_trust ( int require_trusted, int permanent ) {
+
+ /* Update trust requirement, if permitted to do so */
+ if ( ! require_trusted_images_permanent ) {
+ require_trusted_images = require_trusted;
+ require_trusted_images_permanent = permanent;
+ }
+
+ /* Fail if we attempted to change the trust requirement but
+ * were not permitted to do so.
+ */
+ if ( require_trusted_images != require_trusted )
+ return -EACCES_PERMANENT;
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/init.c b/src/VBox/Devices/PC/ipxe/src/core/init.c
new file mode 100644
index 00000000..4dc706f6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/init.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/device.h>
+#include <ipxe/init.h>
+
+/** @file
+ *
+ * Initialisation, startup and shutdown routines
+ *
+ */
+
+/** "startup() has been called" flag */
+static int started = 0;
+
+/**
+ * Initialise iPXE
+ *
+ * This function performs the one-time-only and irreversible
+ * initialisation steps, such as initialising the heap. It must be
+ * called before (almost) any other function.
+ *
+ * There is, by definition, no counterpart to this function on the
+ * shutdown path.
+ */
+void initialise ( void ) {
+ struct init_fn *init_fn;
+
+ /* Call registered initialisation functions */
+ for_each_table_entry ( init_fn, INIT_FNS )
+ init_fn->initialise ();
+}
+
+/**
+ * Start up iPXE
+ *
+ * This function performs the repeatable initialisation steps, such as
+ * probing devices. You may call startup() and shutdown() multiple
+ * times (as is done via the PXE API when PXENV_START_UNDI is used).
+ */
+void startup ( void ) {
+ struct startup_fn *startup_fn;
+
+ if ( started )
+ return;
+
+ /* Call registered startup functions */
+ for_each_table_entry ( startup_fn, STARTUP_FNS ) {
+ if ( startup_fn->startup )
+ startup_fn->startup();
+ }
+
+ started = 1;
+}
+
+/**
+ * Shut down iPXE
+ *
+ * @v flags Shutdown behaviour flags
+ *
+ * This function reverses the actions of startup(), and leaves iPXE in
+ * a state ready to be removed from memory. You may call startup()
+ * again after calling shutdown().
+ *
+ * Call this function only once, before either exiting main() or
+ * starting up a non-returnable image.
+ */
+void shutdown ( int flags ) {
+ struct startup_fn *startup_fn;
+
+ if ( ! started )
+ return;
+
+ /* Call registered shutdown functions (in reverse order) */
+ for_each_table_entry_reverse ( startup_fn, STARTUP_FNS ) {
+ if ( startup_fn->shutdown )
+ startup_fn->shutdown ( flags );
+ }
+
+ started = 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/interface.c b/src/VBox/Devices/PC/ipxe/src/core/interface.c
new file mode 100644
index 00000000..c69875ea
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/interface.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <ipxe/interface.h>
+
+/** @file
+ *
+ * Object interfaces
+ *
+ */
+
+/*****************************************************************************
+ *
+ * The null interface
+ *
+ */
+
+/** Null interface operations */
+static struct interface_operation null_intf_op[] = {};
+
+/** Null interface descriptor */
+struct interface_descriptor null_intf_desc =
+ INTF_DESC_PURE ( null_intf_op );
+
+/** The null interface */
+struct interface null_intf = INTF_INIT ( null_intf_desc );
+
+/*****************************************************************************
+ *
+ * Object interface plumbing
+ *
+ */
+
+/**
+ * Plug an object interface into a new destination object interface
+ *
+ * @v intf Object interface
+ * @v dest New destination object interface
+ *
+ * The reference to the existing destination interface is dropped, a
+ * reference to the new destination interface is obtained, and the
+ * interface is updated to point to the new destination interface.
+ *
+ * Note that there is no "unplug" call; instead you must plug the
+ * interface into a null interface.
+ */
+void intf_plug ( struct interface *intf, struct interface *dest ) {
+ DBGC ( INTF_COL ( intf ),
+ "INTF " INTF_INTF_FMT " replug to " INTF_FMT "\n",
+ INTF_INTF_DBG ( intf, intf->dest ), INTF_DBG ( dest ) );
+ intf_get ( dest );
+ intf_put ( intf->dest );
+ intf->dest = dest;
+}
+
+/**
+ * Plug two object interfaces together
+ *
+ * @v a Object interface A
+ * @v b Object interface B
+ *
+ * Plugs interface A into interface B, and interface B into interface
+ * A. (The basic plug() function is unidirectional; this function is
+ * merely a shorthand for two calls to plug(), hence the name.)
+ */
+void intf_plug_plug ( struct interface *a, struct interface *b ) {
+ intf_plug ( a, b );
+ intf_plug ( b, a );
+}
+
+/**
+ * Unplug an object interface
+ *
+ * @v intf Object interface
+ */
+void intf_unplug ( struct interface *intf ) {
+ intf_plug ( intf, &null_intf );
+}
+
+/**
+ * Ignore all further operations on an object interface
+ *
+ * @v intf Object interface
+ */
+void intf_nullify ( struct interface *intf ) {
+ intf->desc = &null_intf_desc;
+}
+
+/**
+ * Increment reference count on an object interface
+ *
+ * @v intf Object interface
+ * @ret intf Object interface
+ */
+struct interface * intf_get ( struct interface *intf ) {
+ ref_get ( intf->refcnt );
+ return intf;
+}
+
+/**
+ * Decrement reference count on an object interface
+ *
+ * @v intf Object interface
+ */
+void intf_put ( struct interface *intf ) {
+ ref_put ( intf->refcnt );
+}
+
+/**
+ * Get pointer to object containing object interface
+ *
+ * @v intf Object interface
+ * @ret object Containing object
+ */
+void * intf_object ( struct interface *intf ) {
+ return ( ( ( void * ) intf ) - intf->desc->offset );
+}
+
+/**
+ * Get pass-through interface
+ *
+ * @v intf Object interface
+ * @ret passthru Pass-through interface, or NULL
+ */
+static struct interface * intf_get_passthru ( struct interface *intf ) {
+ struct interface_descriptor *desc = intf->desc;
+
+ if ( desc->passthru_offset ) {
+ return ( ( ( void * ) intf ) + desc->passthru_offset );
+ } else {
+ return NULL;
+ }
+}
+
+/**
+ * Get object interface destination and operation method (without pass-through)
+ *
+ * @v intf Object interface
+ * @v type Operation type
+ * @ret dest Destination interface
+ * @ret func Implementing method, or NULL
+ */
+void * intf_get_dest_op_no_passthru_untyped ( struct interface *intf,
+ void *type,
+ struct interface **dest ) {
+ struct interface_descriptor *desc;
+ struct interface_operation *op;
+ unsigned int i;
+
+ *dest = intf_get ( intf->dest );
+ desc = (*dest)->desc;
+ for ( i = desc->num_op, op = desc->op ; i ; i--, op++ ) {
+ if ( op->type == type )
+ return op->func;
+ }
+
+ return NULL;
+}
+
+/**
+ * Get object interface destination and operation method
+ *
+ * @v intf Object interface
+ * @v type Operation type
+ * @ret dest Destination interface
+ * @ret func Implementing method, or NULL
+ */
+void * intf_get_dest_op_untyped ( struct interface *intf, void *type,
+ struct interface **dest ) {
+ void *func;
+
+ while ( 1 ) {
+
+ /* Search for an implementing method provided by the
+ * current destination interface.
+ */
+ func = intf_get_dest_op_no_passthru_untyped( intf, type, dest );
+ if ( func )
+ return func;
+
+ /* Pass through to the underlying interface, if applicable */
+ if ( ! ( intf = intf_get_passthru ( *dest ) ) )
+ return NULL;
+ intf_put ( *dest );
+ }
+}
+
+/*****************************************************************************
+ *
+ * Generic interface operations
+ *
+ */
+
+/**
+ * Close an object interface
+ *
+ * @v intf Object interface
+ * @v rc Reason for close
+ *
+ * Note that this function merely informs the destination object that
+ * the interface is about to be closed; it doesn't actually disconnect
+ * the interface. In most cases, you probably want to use
+ * intf_shutdown() or intf_restart() instead.
+ */
+void intf_close ( struct interface *intf, int rc ) {
+ struct interface *dest;
+ intf_close_TYPE ( void * ) *op =
+ intf_get_dest_op ( intf, intf_close, &dest );
+ void *object = intf_object ( dest );
+
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " close (%s)\n",
+ INTF_INTF_DBG ( intf, dest ), strerror ( rc ) );
+
+ if ( op ) {
+ op ( object, rc );
+ } else {
+ /* Default is to ignore intf_close() */
+ }
+
+ intf_put ( dest );
+}
+
+/**
+ * Shut down an object interface
+ *
+ * @v intf Object interface
+ * @v rc Reason for close
+ *
+ * Blocks further operations from being received via the interface,
+ * executes a close operation on the destination interface, and
+ * unplugs the interface.
+ */
+void intf_shutdown ( struct interface *intf, int rc ) {
+
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " shutting down (%s)\n",
+ INTF_DBG ( intf ), strerror ( rc ) );
+
+ /* Block further operations */
+ intf_nullify ( intf );
+
+ /* Notify destination of close */
+ intf_close ( intf, rc );
+
+ /* Unplug interface */
+ intf_unplug ( intf );
+}
+
+/**
+ * Shut down and restart an object interface
+ *
+ * @v intf Object interface
+ * @v rc Reason for close
+ *
+ * Shuts down the interface, then unblocks operations that were
+ * blocked during shutdown.
+ */
+void intf_restart ( struct interface *intf, int rc ) {
+ struct interface_descriptor *desc = intf->desc;
+
+ /* Shut down the interface */
+ intf_shutdown ( intf, rc );
+
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " restarting\n",
+ INTF_DBG ( intf ) );
+
+ /* Restore the interface descriptor. Must be done after
+ * shutdown (rather than inhibiting intf_shutdown() from
+ * nullifying the descriptor) in order to avoid a potential
+ * infinite loop as the intf_close() operations on each side
+ * of the link call each other recursively.
+ */
+ intf->desc = desc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/iobuf.c b/src/VBox/Devices/PC/ipxe/src/core/iobuf.c
new file mode 100644
index 00000000..d776d606
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/iobuf.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <errno.h>
+#include <ipxe/malloc.h>
+#include <ipxe/iobuf.h>
+
+/** @file
+ *
+ * I/O buffers
+ *
+ */
+
+/**
+ * Allocate I/O buffer
+ *
+ * @v len Required length of buffer
+ * @ret iobuf I/O buffer, or NULL if none available
+ *
+ * The I/O buffer will be physically aligned to a multiple of
+ * @c IOBUF_SIZE.
+ */
+struct io_buffer * alloc_iob ( size_t len ) {
+ struct io_buffer *iobuf = NULL;
+ void *data;
+
+ /* Pad to minimum length */
+ if ( len < IOB_ZLEN )
+ len = IOB_ZLEN;
+
+ /* Align buffer length */
+ len = ( len + __alignof__( *iobuf ) - 1 ) &
+ ~( __alignof__( *iobuf ) - 1 );
+
+ /* Allocate memory for buffer plus descriptor */
+ data = malloc_dma ( len + sizeof ( *iobuf ), IOB_ALIGN );
+ if ( ! data )
+ return NULL;
+
+ iobuf = ( struct io_buffer * ) ( data + len );
+ iobuf->head = iobuf->data = iobuf->tail = data;
+ iobuf->end = iobuf;
+ return iobuf;
+}
+
+/**
+ * Free I/O buffer
+ *
+ * @v iobuf I/O buffer
+ */
+void free_iob ( struct io_buffer *iobuf ) {
+ if ( iobuf ) {
+ assert ( iobuf->head <= iobuf->data );
+ assert ( iobuf->data <= iobuf->tail );
+ assert ( iobuf->tail <= iobuf->end );
+ free_dma ( iobuf->head,
+ ( iobuf->end - iobuf->head ) + sizeof ( *iobuf ) );
+ }
+}
+
+/**
+ * Ensure I/O buffer has sufficient headroom
+ *
+ * @v iobuf I/O buffer
+ * @v len Required headroom
+ *
+ * This function currently only checks for the required headroom; it
+ * does not reallocate the I/O buffer if required. If we ever have a
+ * code path that requires this functionality, it's a fairly trivial
+ * change to make.
+ */
+int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len ) {
+
+ if ( iob_headroom ( iobuf ) >= len )
+ return 0;
+ return -ENOBUFS;
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/core/job.c b/src/VBox/Devices/PC/ipxe/src/core/job.c
new file mode 100644
index 00000000..ac4e43e7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/job.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <errno.h>
+#include <ipxe/job.h>
+
+/** @file
+ *
+ * Job control interfaces
+ *
+ */
+
+/**
+ * Get job progress
+ *
+ * @v intf Object interface
+ * @v progress Progress data to fill in
+ */
+void job_progress ( struct interface *intf, struct job_progress *progress ) {
+ struct interface *dest;
+ job_progress_TYPE ( void * ) *op =
+ intf_get_dest_op ( intf, job_progress, &dest );
+ void *object = intf_object ( dest );
+
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " job_progress\n",
+ INTF_INTF_DBG ( intf, dest ) );
+
+ if ( op ) {
+ op ( object, progress );
+ } else {
+ /* Default is to mark progress as zero */
+ memset ( progress, 0, sizeof ( *progress ) );
+ }
+
+ intf_put ( dest );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/linebuf.c b/src/VBox/Devices/PC/ipxe/src/core/linebuf.c
new file mode 100644
index 00000000..f152bccb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/linebuf.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Line buffering
+ *
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ipxe/linebuf.h>
+
+/**
+ * Retrieve buffered-up line
+ *
+ * @v linebuf Line buffer
+ * @ret line Buffered line, or NULL if no line ready to read
+ */
+char * buffered_line ( struct line_buffer *linebuf ) {
+ return ( linebuf->ready ? linebuf->data : NULL );
+}
+
+/**
+ * Discard line buffer contents
+ *
+ * @v linebuf Line buffer
+ */
+void empty_line_buffer ( struct line_buffer *linebuf ) {
+ free ( linebuf->data );
+ linebuf->data = NULL;
+ linebuf->len = 0;
+ linebuf->ready = 0;
+}
+
+/**
+ * Buffer up received data by lines
+ *
+ * @v linebuf Line buffer
+ * @v data New data to add
+ * @v len Length of new data to add
+ * @ret len Consumed length, or negative error number
+ *
+ * After calling line_buffer(), use buffered_line() to determine
+ * whether or not a complete line is available. Carriage returns and
+ * newlines will have been stripped, and the line will be
+ * NUL-terminated. This buffered line is valid only until the next
+ * call to line_buffer() (or to empty_line_buffer()).
+ *
+ * Note that line buffers use dynamically allocated storage; you
+ * should call empty_line_buffer() before freeing a @c struct @c
+ * line_buffer.
+ */
+ssize_t line_buffer ( struct line_buffer *linebuf,
+ const char *data, size_t len ) {
+ const char *eol;
+ size_t consume;
+ size_t new_len;
+ char *new_data;
+
+ /* Free any completed line from previous iteration */
+ if ( linebuf->ready )
+ empty_line_buffer ( linebuf );
+
+ /* Search for line terminator */
+ if ( ( eol = memchr ( data, '\n', len ) ) ) {
+ consume = ( eol - data + 1 );
+ } else {
+ consume = len;
+ }
+
+ /* Reallocate data buffer and copy in new data */
+ new_len = ( linebuf->len + consume );
+ new_data = realloc ( linebuf->data, ( new_len + 1 ) );
+ if ( ! new_data )
+ return -ENOMEM;
+ memcpy ( ( new_data + linebuf->len ), data, consume );
+ new_data[new_len] = '\0';
+ linebuf->data = new_data;
+ linebuf->len = new_len;
+
+ /* If we have reached end of line, trim the line and mark as ready */
+ if ( eol ) {
+ linebuf->data[--linebuf->len] = '\0'; /* trim NL */
+ if ( linebuf->data[linebuf->len - 1] == '\r' )
+ linebuf->data[--linebuf->len] = '\0'; /* trim CR */
+ linebuf->ready = 1;
+ }
+
+ return consume;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/lineconsole.c b/src/VBox/Devices/PC/ipxe/src/core/lineconsole.c
new file mode 100644
index 00000000..71bc1f8b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/lineconsole.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Line-based console
+ *
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <ipxe/ansiesc.h>
+#include <ipxe/lineconsole.h>
+
+/**
+ * Print a character to a line-based console
+ *
+ * @v character Character to be printed
+ * @ret print Print line
+ */
+size_t line_putchar ( struct line_console *line, int character ) {
+
+ /* Strip ANSI escape sequences */
+ character = ansiesc_process ( &line->ctx, character );
+ if ( character < 0 )
+ return 0;
+
+ /* Ignore carriage return */
+ if ( character == '\r' )
+ return 0;
+
+ /* Treat newline as a terminator */
+ if ( character == '\n' )
+ character = 0;
+
+ /* Add character to buffer */
+ line->buffer[line->index++] = character;
+
+ /* Do nothing more unless we reach end-of-line (or end-of-buffer) */
+ if ( ( character != 0 ) &&
+ ( line->index < ( line->len - 1 /* NUL */ ) ) ) {
+ return 0;
+ }
+
+ /* Reset to start of buffer */
+ line->index = 0;
+
+ return 1;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/log.c b/src/VBox/Devices/PC/ipxe/src/core/log.c
new file mode 100644
index 00000000..c0c3656c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/log.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * System logger
+ *
+ */
+
+#include <stdarg.h>
+#include <syslog.h>
+#include <ipxe/console.h>
+
+/**
+ * Write message to system log
+ *
+ * @v fmt Format string
+ * @v args Arguments
+ */
+void log_vprintf ( const char *fmt, va_list args ) {
+ int saved_usage;
+
+ /* Mark console as in use for log messages */
+ saved_usage = console_set_usage ( CONSOLE_USAGE_LOG );
+
+ /* Print message */
+ vprintf ( fmt, args );
+
+ /* Restore console usage */
+ console_set_usage ( saved_usage );
+}
+
+/**
+ * Write message to system log
+ *
+ * @v fmt Format string
+ * @v ... Arguments
+ */
+void log_printf ( const char *fmt, ... ) {
+ va_list args;
+
+ va_start ( args, fmt );
+ log_vprintf ( fmt, args );
+ va_end ( args );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/main.c b/src/VBox/Devices/PC/ipxe/src/core/main.c
new file mode 100644
index 00000000..9ee94e02
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/main.c
@@ -0,0 +1,120 @@
+/**************************************************************************
+iPXE - Network Bootstrap Program
+
+Literature dealing with the network protocols:
+ ARP - RFC826
+ RARP - RFC903
+ UDP - RFC768
+ BOOTP - RFC951, RFC2132 (vendor extensions)
+ DHCP - RFC2131, RFC2132 (options)
+ TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)
+ RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)
+
+**************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ipxe/init.h>
+#include <ipxe/features.h>
+#include <ipxe/shell.h>
+#include <ipxe/image.h>
+#include <ipxe/keys.h>
+#include <usr/prompt.h>
+#include <usr/autoboot.h>
+#include <config/general.h>
+
+#define NORMAL "\033[0m"
+#define BOLD "\033[1m"
+#define CYAN "\033[36m"
+
+/** The "scriptlet" setting */
+struct setting scriptlet_setting __setting ( SETTING_MISC ) = {
+ .name = "scriptlet",
+ .description = "Boot scriptlet",
+ .tag = DHCP_EB_SCRIPTLET,
+ .type = &setting_type_string,
+};
+
+/**
+ * Prompt for shell entry
+ *
+ * @ret enter_shell User wants to enter shell
+ */
+static int shell_banner ( void ) {
+
+ /* Skip prompt if timeout is zero */
+ if ( BANNER_TIMEOUT <= 0 )
+ return 0;
+
+ return ( prompt ( "\nPress Ctrl-B for the iPXE command line...",
+ ( BANNER_TIMEOUT * 100 ), CTRL_B ) == 0 );
+}
+
+/**
+ * Main entry point
+ *
+ * @ret rc Return status code
+ */
+__asmcall int main ( void ) {
+ struct feature *feature;
+ struct image *image;
+ char *scriptlet;
+
+ /* Some devices take an unreasonably long time to initialise */
+ printf ( PRODUCT_SHORT_NAME " initialising devices..." );
+ initialise();
+ startup();
+ printf ( "ok\n" );
+
+ /*
+ * Print welcome banner
+ *
+ *
+ * If you wish to brand this build of iPXE, please do so by
+ * defining the string PRODUCT_NAME in config/general.h.
+ *
+ * While nothing in the GPL prevents you from removing all
+ * references to iPXE or http://ipxe.org, we prefer you not to
+ * do so.
+ *
+ */
+ printf ( NORMAL "\n\n" PRODUCT_NAME "\n" BOLD "iPXE " VERSION
+ NORMAL " -- Open Source Network Boot Firmware -- "
+ CYAN "http://ipxe.org" NORMAL "\n"
+ "Features:" );
+ for_each_table_entry ( feature, FEATURES )
+ printf ( " %s", feature->name );
+ printf ( "\n" );
+
+ /* Boot system */
+ if ( ( image = first_image() ) != NULL ) {
+ /* We have an embedded image; execute it */
+ image_exec ( image );
+ } else if ( shell_banner() ) {
+ /* User wants shell; just give them a shell */
+ shell();
+ } else {
+ fetch_string_setting_copy ( NULL, &scriptlet_setting,
+ &scriptlet );
+ if ( scriptlet ) {
+ /* User has defined a scriptlet; execute it */
+ system ( scriptlet );
+ free ( scriptlet );
+ } else {
+ /* Try booting. If booting fails, offer the
+ * user another chance to enter the shell.
+ */
+ autoboot();
+#ifndef VBOX
+ if ( shell_banner() )
+ shell();
+#endif
+ }
+ }
+
+ shutdown_exit();
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/malloc.c b/src/VBox/Devices/PC/ipxe/src/core/malloc.c
new file mode 100644
index 00000000..6633887b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/malloc.c
@@ -0,0 +1,557 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+#include <ipxe/io.h>
+#include <ipxe/list.h>
+#include <ipxe/init.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/malloc.h>
+#include <valgrind/memcheck.h>
+
+/** @file
+ *
+ * Dynamic memory allocation
+ *
+ */
+
+/** A free block of memory */
+struct memory_block {
+ /** Size of this block */
+ size_t size;
+ /** Padding
+ *
+ * This padding exists to cover the "count" field of a
+ * reference counter, in the common case where a reference
+ * counter is the first element of a dynamically-allocated
+ * object. It avoids clobbering the "count" field as soon as
+ * the memory is freed, and so allows for the possibility of
+ * detecting reference counting errors.
+ */
+ char pad[ offsetof ( struct refcnt, count ) +
+ sizeof ( ( ( struct refcnt * ) NULL )->count ) ];
+ /** List of free blocks */
+ struct list_head list;
+};
+
+#define MIN_MEMBLOCK_SIZE \
+ ( ( size_t ) ( 1 << ( fls ( sizeof ( struct memory_block ) - 1 ) ) ) )
+
+/** A block of allocated memory complete with size information */
+struct autosized_block {
+ /** Size of this block */
+ size_t size;
+ /** Remaining data */
+ char data[0];
+};
+
+/**
+ * Address for zero-length memory blocks
+ *
+ * @c malloc(0) or @c realloc(ptr,0) will return the special value @c
+ * NOWHERE. Calling @c free(NOWHERE) will have no effect.
+ *
+ * This is consistent with the ANSI C standards, which state that
+ * "either NULL or a pointer suitable to be passed to free()" must be
+ * returned in these cases. Using a special non-NULL value means that
+ * the caller can take a NULL return value to indicate failure,
+ * without first having to check for a requested size of zero.
+ *
+ * Code outside of malloc.c do not ever need to refer to the actual
+ * value of @c NOWHERE; this is an internal definition.
+ */
+#define NOWHERE ( ( void * ) ~( ( intptr_t ) 0 ) )
+
+/** List of free memory blocks */
+static LIST_HEAD ( free_blocks );
+
+/** Total amount of free memory */
+size_t freemem;
+
+/**
+ * Heap size
+ *
+ * Currently fixed at 128kB.
+ */
+#define HEAP_SIZE ( 128 * 1024 )
+
+/** The heap itself */
+static char heap[HEAP_SIZE] __attribute__ (( aligned ( __alignof__(void *) )));
+
+/**
+ * Mark all blocks in free list as defined
+ *
+ */
+static inline void valgrind_make_blocks_defined ( void ) {
+ struct memory_block *block;
+
+ if ( RUNNING_ON_VALGRIND <= 0 )
+ return;
+
+ /* Traverse free block list, marking each block structure as
+ * defined. Some contortions are necessary to avoid errors
+ * from list_check().
+ */
+
+ /* Mark block list itself as defined */
+ VALGRIND_MAKE_MEM_DEFINED ( &free_blocks, sizeof ( free_blocks ) );
+
+ /* Mark areas accessed by list_check() as defined */
+ VALGRIND_MAKE_MEM_DEFINED ( &free_blocks.prev->next,
+ sizeof ( free_blocks.prev->next ) );
+ VALGRIND_MAKE_MEM_DEFINED ( free_blocks.next,
+ sizeof ( *free_blocks.next ) );
+ VALGRIND_MAKE_MEM_DEFINED ( &free_blocks.next->next->prev,
+ sizeof ( free_blocks.next->next->prev ) );
+
+ /* Mark each block in list as defined */
+ list_for_each_entry ( block, &free_blocks, list ) {
+
+ /* Mark block as defined */
+ VALGRIND_MAKE_MEM_DEFINED ( block, sizeof ( *block ) );
+
+ /* Mark areas accessed by list_check() as defined */
+ VALGRIND_MAKE_MEM_DEFINED ( block->list.next,
+ sizeof ( *block->list.next ) );
+ VALGRIND_MAKE_MEM_DEFINED ( &block->list.next->next->prev,
+ sizeof ( block->list.next->next->prev ) );
+ }
+}
+
+/**
+ * Mark all blocks in free list as inaccessible
+ *
+ */
+static inline void valgrind_make_blocks_noaccess ( void ) {
+ struct memory_block *block;
+ struct memory_block *prev = NULL;
+
+ if ( RUNNING_ON_VALGRIND <= 0 )
+ return;
+
+ /* Traverse free block list, marking each block structure as
+ * inaccessible. Some contortions are necessary to avoid
+ * errors from list_check().
+ */
+
+ /* Mark each block in list as inaccessible */
+ list_for_each_entry ( block, &free_blocks, list ) {
+
+ /* Mark previous block (if any) as inaccessible. (Current
+ * block will be accessed by list_check().)
+ */
+ if ( prev )
+ VALGRIND_MAKE_MEM_NOACCESS ( prev, sizeof ( *prev ) );
+ prev = block;
+
+ /* At the end of the list, list_check() will end up
+ * accessing the first list item. Temporarily mark
+ * this area as defined.
+ */
+ VALGRIND_MAKE_MEM_DEFINED ( &free_blocks.next->prev,
+ sizeof ( free_blocks.next->prev ) );
+ }
+ /* Mark last block (if any) as inaccessible */
+ if ( prev )
+ VALGRIND_MAKE_MEM_NOACCESS ( prev, sizeof ( *prev ) );
+
+ /* Mark as inaccessible the area that was temporarily marked
+ * as defined to avoid errors from list_check().
+ */
+ VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks.next->prev,
+ sizeof ( free_blocks.next->prev ) );
+
+ /* Mark block list itself as inaccessible */
+ VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks, sizeof ( free_blocks ) );
+}
+
+/**
+ * Discard some cached data
+ *
+ * @ret discarded Number of cached items discarded
+ */
+static unsigned int discard_cache ( void ) {
+ struct cache_discarder *discarder;
+ unsigned int discarded = 0;
+
+ for_each_table_entry ( discarder, CACHE_DISCARDERS ) {
+ discarded += discarder->discard();
+ }
+ return discarded;
+}
+
+/**
+ * Discard all cached data
+ *
+ */
+static void discard_all_cache ( void ) {
+ unsigned int discarded;
+
+ do {
+ discarded = discard_cache();
+ } while ( discarded );
+}
+
+/**
+ * Allocate a memory block
+ *
+ * @v size Requested size
+ * @v align Physical alignment
+ * @ret ptr Memory block, or NULL
+ *
+ * Allocates a memory block @b physically aligned as requested. No
+ * guarantees are provided for the alignment of the virtual address.
+ *
+ * @c align must be a power of two. @c size may not be zero.
+ */
+void * alloc_memblock ( size_t size, size_t align ) {
+ struct memory_block *block;
+ size_t align_mask;
+ size_t pre_size;
+ ssize_t post_size;
+ struct memory_block *pre;
+ struct memory_block *post;
+ struct memory_block *ptr;
+
+ valgrind_make_blocks_defined();
+
+ /* Round up size to multiple of MIN_MEMBLOCK_SIZE and
+ * calculate alignment mask.
+ */
+ size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 );
+ align_mask = ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 );
+
+ DBG ( "Allocating %#zx (aligned %#zx)\n", size, align );
+ while ( 1 ) {
+ /* Search through blocks for the first one with enough space */
+ list_for_each_entry ( block, &free_blocks, list ) {
+ pre_size = ( - virt_to_phys ( block ) ) & align_mask;
+ post_size = block->size - pre_size - size;
+ if ( post_size >= 0 ) {
+ /* Split block into pre-block, block, and
+ * post-block. After this split, the "pre"
+ * block is the one currently linked into the
+ * free list.
+ */
+ pre = block;
+ block = ( ( ( void * ) pre ) + pre_size );
+ post = ( ( ( void * ) block ) + size );
+ DBG ( "[%p,%p) -> [%p,%p) + [%p,%p)\n", pre,
+ ( ( ( void * ) pre ) + pre->size ),
+ pre, block, post,
+ ( ( ( void * ) pre ) + pre->size ) );
+ /* If there is a "post" block, add it in to
+ * the free list. Leak it if it is too small
+ * (which can happen only at the very end of
+ * the heap).
+ */
+ if ( (size_t) post_size >= MIN_MEMBLOCK_SIZE ) {
+ VALGRIND_MAKE_MEM_DEFINED ( post,
+ sizeof ( *post ) );
+ post->size = post_size;
+ list_add ( &post->list, &pre->list );
+ }
+ /* Shrink "pre" block, leaving the main block
+ * isolated and no longer part of the free
+ * list.
+ */
+ pre->size = pre_size;
+ /* If there is no "pre" block, remove it from
+ * the list. Also remove it (i.e. leak it) if
+ * it is too small, which can happen only at
+ * the very start of the heap.
+ */
+ if ( pre_size < MIN_MEMBLOCK_SIZE )
+ list_del ( &pre->list );
+ /* Update total free memory */
+ freemem -= size;
+ /* Return allocated block */
+ DBG ( "Allocated [%p,%p)\n", block,
+ ( ( ( void * ) block ) + size ) );
+ ptr = block;
+ goto done;
+ }
+ }
+
+ /* Try discarding some cached data to free up memory */
+ if ( ! discard_cache() ) {
+ /* Nothing available to discard */
+ DBG ( "Failed to allocate %#zx (aligned %#zx)\n",
+ size, align );
+ ptr = NULL;
+ goto done;
+ }
+ }
+
+ done:
+ valgrind_make_blocks_noaccess();
+ return ptr;
+}
+
+/**
+ * Free a memory block
+ *
+ * @v ptr Memory allocated by alloc_memblock(), or NULL
+ * @v size Size of the memory
+ *
+ * If @c ptr is NULL, no action is taken.
+ */
+void free_memblock ( void *ptr, size_t size ) {
+ struct memory_block *freeing;
+ struct memory_block *block;
+ struct memory_block *tmp;
+ ssize_t gap_before;
+ ssize_t gap_after = -1;
+
+ /* Allow for ptr==NULL */
+ if ( ! ptr )
+ return;
+
+ valgrind_make_blocks_defined();
+
+ /* Round up size to match actual size that alloc_memblock()
+ * would have used.
+ */
+ size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 );
+ freeing = ptr;
+ VALGRIND_MAKE_MEM_DEFINED ( freeing, sizeof ( *freeing ) );
+ freeing->size = size;
+ DBG ( "Freeing [%p,%p)\n", freeing, ( ( ( void * ) freeing ) + size ));
+
+ /* Insert/merge into free list */
+ list_for_each_entry_safe ( block, tmp, &free_blocks, list ) {
+ /* Calculate gaps before and after the "freeing" block */
+ gap_before = ( ( ( void * ) freeing ) -
+ ( ( ( void * ) block ) + block->size ) );
+ gap_after = ( ( ( void * ) block ) -
+ ( ( ( void * ) freeing ) + freeing->size ) );
+ /* Merge with immediately preceding block, if possible */
+ if ( gap_before == 0 ) {
+ DBG ( "[%p,%p) + [%p,%p) -> [%p,%p)\n", block,
+ ( ( ( void * ) block ) + block->size ), freeing,
+ ( ( ( void * ) freeing ) + freeing->size ),block,
+ ( ( ( void * ) freeing ) + freeing->size ) );
+ block->size += size;
+ list_del ( &block->list );
+ freeing = block;
+ }
+ /* Stop processing as soon as we reach a following block */
+ if ( gap_after >= 0 )
+ break;
+ }
+
+ /* Insert before the immediately following block. If
+ * possible, merge the following block into the "freeing"
+ * block.
+ */
+ DBG ( "[%p,%p)\n", freeing, ( ( ( void * ) freeing ) + freeing->size));
+ list_add_tail ( &freeing->list, &block->list );
+ if ( gap_after == 0 ) {
+ DBG ( "[%p,%p) + [%p,%p) -> [%p,%p)\n", freeing,
+ ( ( ( void * ) freeing ) + freeing->size ), block,
+ ( ( ( void * ) block ) + block->size ), freeing,
+ ( ( ( void * ) block ) + block->size ) );
+ freeing->size += block->size;
+ list_del ( &block->list );
+ }
+
+ /* Update free memory counter */
+ freemem += size;
+
+ valgrind_make_blocks_noaccess();
+}
+
+/**
+ * Reallocate memory
+ *
+ * @v old_ptr Memory previously allocated by malloc(), or NULL
+ * @v new_size Requested size
+ * @ret new_ptr Allocated memory, or NULL
+ *
+ * Allocates memory with no particular alignment requirement. @c
+ * new_ptr will be aligned to at least a multiple of sizeof(void*).
+ * If @c old_ptr is non-NULL, then the contents of the newly allocated
+ * memory will be the same as the contents of the previously allocated
+ * memory, up to the minimum of the old and new sizes. The old memory
+ * will be freed.
+ *
+ * If allocation fails the previously allocated block is left
+ * untouched and NULL is returned.
+ *
+ * Calling realloc() with a new size of zero is a valid way to free a
+ * memory block.
+ */
+void * realloc ( void *old_ptr, size_t new_size ) {
+ struct autosized_block *old_block;
+ struct autosized_block *new_block;
+ size_t old_total_size;
+ size_t new_total_size;
+ size_t old_size;
+ void *new_ptr = NOWHERE;
+
+ /* Allocate new memory if necessary. If allocation fails,
+ * return without touching the old block.
+ */
+ if ( new_size ) {
+ new_total_size = ( new_size +
+ offsetof ( struct autosized_block, data ) );
+ new_block = alloc_memblock ( new_total_size, 1 );
+ if ( ! new_block )
+ return NULL;
+ VALGRIND_MAKE_MEM_UNDEFINED ( new_block, offsetof ( struct autosized_block, data ) );
+ new_block->size = new_total_size;
+ VALGRIND_MAKE_MEM_NOACCESS ( new_block, offsetof ( struct autosized_block, data ) );
+ new_ptr = &new_block->data;
+ VALGRIND_MALLOCLIKE_BLOCK ( new_ptr, new_size, 0, 0 );
+ }
+
+ /* Copy across relevant part of the old data region (if any),
+ * then free it. Note that at this point either (a) new_ptr
+ * is valid, or (b) new_size is 0; either way, the memcpy() is
+ * valid.
+ */
+ if ( old_ptr && ( old_ptr != NOWHERE ) ) {
+ old_block = container_of ( old_ptr, struct autosized_block,
+ data );
+ VALGRIND_MAKE_MEM_DEFINED ( old_block, offsetof ( struct autosized_block, data ) );
+ old_total_size = old_block->size;
+ old_size = ( old_total_size -
+ offsetof ( struct autosized_block, data ) );
+ memcpy ( new_ptr, old_ptr,
+ ( ( old_size < new_size ) ? old_size : new_size ) );
+ free_memblock ( old_block, old_total_size );
+ VALGRIND_MAKE_MEM_NOACCESS ( old_block, offsetof ( struct autosized_block, data ) );
+ VALGRIND_FREELIKE_BLOCK ( old_ptr, 0 );
+ }
+
+ return new_ptr;
+}
+
+/**
+ * Allocate memory
+ *
+ * @v size Requested size
+ * @ret ptr Memory, or NULL
+ *
+ * Allocates memory with no particular alignment requirement. @c ptr
+ * will be aligned to at least a multiple of sizeof(void*).
+ */
+void * malloc ( size_t size ) {
+ return realloc ( NULL, size );
+}
+
+/**
+ * Free memory
+ *
+ * @v ptr Memory allocated by malloc(), or NULL
+ *
+ * Memory allocated with malloc_dma() cannot be freed with free(); it
+ * must be freed with free_dma() instead.
+ *
+ * If @c ptr is NULL, no action is taken.
+ */
+void free ( void *ptr ) {
+ realloc ( ptr, 0 );
+}
+
+/**
+ * Allocate cleared memory
+ *
+ * @v size Requested size
+ * @ret ptr Allocated memory
+ *
+ * Allocate memory as per malloc(), and zero it.
+ *
+ * This function name is non-standard, but pretty intuitive.
+ * zalloc(size) is always equivalent to calloc(1,size)
+ */
+void * zalloc ( size_t size ) {
+ void *data;
+
+ data = malloc ( size );
+ if ( data )
+ memset ( data, 0, size );
+ return data;
+}
+
+/**
+ * Add memory to allocation pool
+ *
+ * @v start Start address
+ * @v end End address
+ *
+ * Adds a block of memory [start,end) to the allocation pool. This is
+ * a one-way operation; there is no way to reclaim this memory.
+ *
+ * @c start must be aligned to at least a multiple of sizeof(void*).
+ */
+void mpopulate ( void *start, size_t len ) {
+ /* Prevent free_memblock() from rounding up len beyond the end
+ * of what we were actually given...
+ */
+ free_memblock ( start, ( len & ~( MIN_MEMBLOCK_SIZE - 1 ) ) );
+}
+
+/**
+ * Initialise the heap
+ *
+ */
+static void init_heap ( void ) {
+ VALGRIND_MAKE_MEM_NOACCESS ( heap, sizeof ( heap ) );
+ mpopulate ( heap, sizeof ( heap ) );
+}
+
+/** Memory allocator initialisation function */
+struct init_fn heap_init_fn __init_fn ( INIT_EARLY ) = {
+ .initialise = init_heap,
+};
+
+/**
+ * Discard all cached data on shutdown
+ *
+ */
+static void shutdown_cache ( int booting __unused ) {
+ discard_all_cache();
+}
+
+/** Memory allocator shutdown function */
+struct startup_fn heap_startup_fn __startup_fn ( STARTUP_EARLY ) = {
+ .shutdown = shutdown_cache,
+};
+
+#if 0
+#include <stdio.h>
+/**
+ * Dump free block list
+ *
+ */
+void mdumpfree ( void ) {
+ struct memory_block *block;
+
+ printf ( "Free block list:\n" );
+ list_for_each_entry ( block, &free_blocks, list ) {
+ printf ( "[%p,%p] (size %#zx)\n", block,
+ ( ( ( void * ) block ) + block->size ), block->size );
+ }
+}
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/core/menu.c b/src/VBox/Devices/PC/ipxe/src/core/menu.c
new file mode 100644
index 00000000..1d1678f3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/menu.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Menu selection
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ipxe/list.h>
+#include <ipxe/menu.h>
+
+/** List of all menus */
+static LIST_HEAD ( menus );
+
+/**
+ * Create menu
+ *
+ * @v name Menu name, or NULL
+ * @v title Menu title, or NULL
+ * @ret menu Menu, or NULL on failure
+ */
+struct menu * create_menu ( const char *name, const char *title ) {
+ size_t name_len;
+ size_t title_len;
+ size_t len;
+ struct menu *menu;
+ char *name_copy;
+ char *title_copy;
+
+ /* Destroy any existing menu of this name */
+ menu = find_menu ( name );
+ if ( menu )
+ destroy_menu ( menu );
+
+ /* Use empty title if none given */
+ if ( ! title )
+ title = "";
+
+ /* Allocate menu */
+ name_len = ( name ? ( strlen ( name ) + 1 /* NUL */ ) : 0 );
+ title_len = ( strlen ( title ) + 1 /* NUL */ );
+ len = ( sizeof ( *menu ) + name_len + title_len );
+ menu = zalloc ( len );
+ if ( ! menu )
+ return NULL;
+ name_copy = ( ( void * ) ( menu + 1 ) );
+ title_copy = ( name_copy + name_len );
+
+ /* Initialise menu */
+ if ( name ) {
+ strcpy ( name_copy, name );
+ menu->name = name_copy;
+ }
+ strcpy ( title_copy, title );
+ menu->title = title_copy;
+ INIT_LIST_HEAD ( &menu->items );
+
+ /* Add to list of menus */
+ list_add_tail ( &menu->list, &menus );
+
+ DBGC ( menu, "MENU %s created with title \"%s\"\n",
+ menu->name, menu->title );
+
+ return menu;
+}
+
+/**
+ * Add menu item
+ *
+ * @v menu Menu
+ * @v label Label, or NULL
+ * @v text Text, or NULL
+ * @v shortcut Shortcut key
+ * @v is_default Item is the default item
+ * @ret item Menu item, or NULL on failure
+ */
+struct menu_item * add_menu_item ( struct menu *menu, const char *label,
+ const char *text, int shortcut,
+ int is_default ) {
+ size_t label_len;
+ size_t text_len;
+ size_t len;
+ struct menu_item *item;
+ char *label_copy;
+ char *text_copy;
+
+ /* Use empty text if none given */
+ if ( ! text )
+ text = "";
+
+ /* Allocate item */
+ label_len = ( label ? ( strlen ( label ) + 1 /* NUL */ ) : 0 );
+ text_len = ( strlen ( text ) + 1 /* NUL */ );
+ len = ( sizeof ( *item ) + label_len + text_len );
+ item = zalloc ( len );
+ if ( ! item )
+ return NULL;
+ label_copy = ( ( void * ) ( item + 1 ) );
+ text_copy = ( label_copy + label_len );
+
+ /* Initialise item */
+ if ( label ) {
+ strcpy ( label_copy, label );
+ item->label = label_copy;
+ }
+ strcpy ( text_copy, text );
+ item->text = text_copy;
+ item->shortcut = shortcut;
+ item->is_default = is_default;
+
+ /* Add to list of items */
+ list_add_tail ( &item->list, &menu->items );
+
+ return item;
+}
+
+/**
+ * Destroy menu
+ *
+ * @v menu Menu
+ */
+void destroy_menu ( struct menu *menu ) {
+ struct menu_item *item;
+ struct menu_item *tmp;
+
+ /* Remove from list of menus */
+ list_del ( &menu->list );
+
+ /* Free items */
+ list_for_each_entry_safe ( item, tmp, &menu->items, list ) {
+ list_del ( &item->list );
+ free ( item );
+ }
+
+ /* Free menu */
+ free ( menu );
+}
+
+/**
+ * Find menu
+ *
+ * @v name Menu name, or NULL
+ * @ret menu Menu, or NULL if not found
+ */
+struct menu * find_menu ( const char *name ) {
+ struct menu *menu;
+
+ list_for_each_entry ( menu, &menus, list ) {
+ if ( ( menu->name == name ) ||
+ ( strcmp ( menu->name, name ) == 0 ) ) {
+ return menu;
+ }
+ }
+
+ return NULL;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/misc.c b/src/VBox/Devices/PC/ipxe/src/core/misc.c
new file mode 100644
index 00000000..11342481
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/misc.c
@@ -0,0 +1,72 @@
+/**************************************************************************
+MISC Support Routines
+**************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <byteswap.h>
+#include <ipxe/in.h>
+#include <ipxe/timer.h>
+
+/**************************************************************************
+INET_ATON - Convert an ascii x.x.x.x to binary form
+**************************************************************************/
+int inet_aton ( const char *cp, struct in_addr *inp ) {
+ const char *p = cp;
+ const char *digits_start;
+ unsigned long ip = 0;
+ unsigned long val;
+ int j;
+ for(j = 0; j <= 3; j++) {
+ digits_start = p;
+ val = strtoul(p, ( char ** ) &p, 10);
+ if ((p == digits_start) || (val > 255)) return 0;
+ if ( ( j < 3 ) && ( *(p++) != '.' ) ) return 0;
+ ip = (ip << 8) | val;
+ }
+ if ( *p == '\0' ) {
+ inp->s_addr = htonl(ip);
+ return 1;
+ }
+ return 0;
+}
+
+unsigned long strtoul ( const char *p, char **endp, int base ) {
+ unsigned long ret = 0;
+ int negative = 0;
+ unsigned int charval;
+
+ while ( isspace ( *p ) )
+ p++;
+
+ if ( *p == '-' ) {
+ negative = 1;
+ p++;
+ }
+
+ base = strtoul_base ( &p, base );
+
+ while ( 1 ) {
+ charval = strtoul_charval ( *p );
+ if ( charval >= ( unsigned int ) base )
+ break;
+ ret = ( ( ret * base ) + charval );
+ p++;
+ }
+
+ if ( negative )
+ ret = -ret;
+
+ if ( endp )
+ *endp = ( char * ) p;
+
+ return ( ret );
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/core/monojob.c b/src/VBox/Devices/PC/ipxe/src/core/monojob.c
new file mode 100644
index 00000000..7431f88a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/monojob.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/process.h>
+#include <ipxe/console.h>
+#include <ipxe/keys.h>
+#include <ipxe/job.h>
+#include <ipxe/monojob.h>
+#include <ipxe/timer.h>
+
+/** @file
+ *
+ * Single foreground job
+ *
+ */
+
+static int monojob_rc;
+
+static void monojob_close ( struct interface *intf, int rc ) {
+ monojob_rc = rc;
+ intf_restart ( intf, rc );
+}
+
+static struct interface_operation monojob_intf_op[] = {
+ INTF_OP ( intf_close, struct interface *, monojob_close ),
+};
+
+static struct interface_descriptor monojob_intf_desc =
+ INTF_DESC_PURE ( monojob_intf_op );
+
+struct interface monojob = INTF_INIT ( monojob_intf_desc );
+
+/**
+ * Wait for single foreground job to complete
+ *
+ * @v string Job description to display
+ * @ret rc Job final status code
+ */
+int monojob_wait ( const char *string ) {
+ struct job_progress progress;
+ int key;
+ int rc;
+ unsigned long last_progress;
+ unsigned long elapsed;
+ unsigned long completed;
+ unsigned long total;
+ unsigned int percentage;
+ int shown_percentage = 0;
+
+ printf ( "%s...", string );
+ monojob_rc = -EINPROGRESS;
+ last_progress = currticks();
+ while ( monojob_rc == -EINPROGRESS ) {
+ step();
+ if ( iskey() ) {
+ key = getchar();
+ switch ( key ) {
+ case CTRL_C:
+ monojob_close ( &monojob, -ECANCELED );
+ break;
+ default:
+ break;
+ }
+ }
+ elapsed = ( currticks() - last_progress );
+ if ( elapsed >= TICKS_PER_SEC ) {
+ if ( shown_percentage )
+ printf ( "\b\b\b\b \b\b\b\b" );
+ job_progress ( &monojob, &progress );
+ /* Normalise progress figures to avoid overflow */
+ completed = ( progress.completed / 128 );
+ total = ( progress.total / 128 );
+ if ( total ) {
+ percentage = ( ( 100 * completed ) / total );
+ printf ( "%3d%%", percentage );
+ shown_percentage = 1;
+ } else {
+ printf ( "." );
+ shown_percentage = 0;
+ }
+ last_progress = currticks();
+ }
+ }
+ rc = monojob_rc;
+
+ if ( shown_percentage )
+ printf ( "\b\b\b\b \b\b\b\b" );
+
+ if ( rc ) {
+ printf ( " %s\n", strerror ( rc ) );
+ } else {
+ printf ( " ok\n" );
+ }
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/null_nap.c b/src/VBox/Devices/PC/ipxe/src/core/null_nap.c
new file mode 100644
index 00000000..c886f548
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/null_nap.c
@@ -0,0 +1,3 @@
+#include <ipxe/nap.h>
+
+PROVIDE_NAP_INLINE ( null, cpu_nap );
diff --git a/src/VBox/Devices/PC/ipxe/src/core/null_sanboot.c b/src/VBox/Devices/PC/ipxe/src/core/null_sanboot.c
new file mode 100644
index 00000000..6584e7a1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/null_sanboot.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <ipxe/sanboot.h>
+
+static int null_san_hook ( struct uri *uri __unused,
+ unsigned int drive __unused ) {
+ return -EOPNOTSUPP;
+}
+
+static void null_san_unhook ( unsigned int drive __unused ) {
+ /* Do nothing */
+}
+
+static int null_san_boot ( unsigned int drive __unused ) {
+ return -EOPNOTSUPP;
+}
+
+static int null_san_describe ( unsigned int drive __unused ) {
+ return -EOPNOTSUPP;
+}
+
+PROVIDE_SANBOOT_INLINE ( null, san_default_drive );
+PROVIDE_SANBOOT ( null, san_hook, null_san_hook );
+PROVIDE_SANBOOT ( null, san_unhook, null_san_unhook );
+PROVIDE_SANBOOT ( null, san_boot, null_san_boot );
+PROVIDE_SANBOOT ( null, san_describe, null_san_describe );
diff --git a/src/VBox/Devices/PC/ipxe/src/core/null_time.c b/src/VBox/Devices/PC/ipxe/src/core/null_time.c
new file mode 100644
index 00000000..f9c48a95
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/null_time.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Nonexistent time source
+ *
+ */
+
+#include <ipxe/time.h>
+
+PROVIDE_TIME_INLINE ( null, time_now );
diff --git a/src/VBox/Devices/PC/ipxe/src/core/nvo.c b/src/VBox/Devices/PC/ipxe/src/core/nvo.c
new file mode 100644
index 00000000..ea58bade
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/nvo.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/nvs.h>
+#include <ipxe/nvo.h>
+
+/** @file
+ *
+ * Non-volatile stored options
+ *
+ */
+
+/**
+ * Calculate checksum over non-volatile stored options
+ *
+ * @v nvo Non-volatile options block
+ * @ret sum Checksum
+ */
+static unsigned int nvo_checksum ( struct nvo_block *nvo ) {
+ uint8_t *data = nvo->data;
+ uint8_t sum = 0;
+ unsigned int i;
+
+ for ( i = 0 ; i < nvo->len ; i++ ) {
+ sum += *(data++);
+ }
+ return sum;
+}
+
+/**
+ * Reallocate non-volatile stored options block
+ *
+ * @v nvo Non-volatile options block
+ * @v len New length
+ * @ret rc Return status code
+ */
+static int nvo_realloc ( struct nvo_block *nvo, size_t len ) {
+ void *new_data;
+
+ /* Reallocate data */
+ new_data = realloc ( nvo->data, len );
+ if ( ! new_data ) {
+ DBGC ( nvo, "NVO %p could not allocate %zd bytes\n",
+ nvo, len );
+ return -ENOMEM;
+ }
+ nvo->data = new_data;
+ nvo->len = len;
+
+ /* Update DHCP option block */
+ if ( len ) {
+ nvo->dhcpopts.data = ( nvo->data + 1 /* checksum */ );
+ nvo->dhcpopts.alloc_len = ( len - 1 /* checksum */ );
+ } else {
+ nvo->dhcpopts.data = NULL;
+ nvo->dhcpopts.used_len = 0;
+ nvo->dhcpopts.alloc_len = 0;
+ }
+
+ return 0;
+}
+
+/**
+ * Reallocate non-volatile stored options DHCP option block
+ *
+ * @v options DHCP option block
+ * @v len New length
+ * @ret rc Return status code
+ */
+static int nvo_realloc_dhcpopt ( struct dhcp_options *options, size_t len ) {
+ struct nvo_block *nvo =
+ container_of ( options, struct nvo_block, dhcpopts );
+ int rc;
+
+ /* Refuse to reallocate if we have no way to resize the block */
+ if ( ! nvo->resize )
+ return dhcpopt_no_realloc ( options, len );
+
+ /* Allow one byte for the checksum (if any data is present) */
+ if ( len )
+ len += 1;
+
+ /* Resize underlying non-volatile options block */
+ if ( ( rc = nvo->resize ( nvo, len ) ) != 0 ) {
+ DBGC ( nvo, "NVO %p could not resize to %zd bytes: %s\n",
+ nvo, len, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Reallocate in-memory options block */
+ if ( ( rc = nvo_realloc ( nvo, len ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Load non-volatile stored options from non-volatile storage device
+ *
+ * @v nvo Non-volatile options block
+ * @ret rc Return status code
+ */
+static int nvo_load ( struct nvo_block *nvo ) {
+ uint8_t *options_data = nvo->dhcpopts.data;
+ int rc;
+
+ /* Skip reading zero-length NVO fields */
+ if ( nvo->len == 0 ) {
+ DBGC ( nvo, "NVO %p is empty; skipping load\n", nvo );
+ return 0;
+ }
+
+ /* Read data */
+ if ( ( rc = nvs_read ( nvo->nvs, nvo->address, nvo->data,
+ nvo->len ) ) != 0 ) {
+ DBGC ( nvo, "NVO %p could not read %zd bytes at %#04x: %s\n",
+ nvo, nvo->len, nvo->address, strerror ( rc ) );
+ return rc;
+ }
+
+ /* If checksum fails, or options data starts with a zero,
+ * assume the whole block is invalid. This should capture the
+ * case of random initial contents.
+ */
+ if ( ( nvo_checksum ( nvo ) != 0 ) || ( options_data[0] == 0 ) ) {
+ DBGC ( nvo, "NVO %p has checksum %02x and initial byte %02x; "
+ "assuming empty\n", nvo, nvo_checksum ( nvo ),
+ options_data[0] );
+ memset ( nvo->data, 0, nvo->len );
+ }
+
+ /* Rescan DHCP option block */
+ dhcpopt_update_used_len ( &nvo->dhcpopts );
+
+ DBGC ( nvo, "NVO %p loaded from non-volatile storage\n", nvo );
+ return 0;
+}
+
+/**
+ * Save non-volatile stored options back to non-volatile storage device
+ *
+ * @v nvo Non-volatile options block
+ * @ret rc Return status code
+ */
+static int nvo_save ( struct nvo_block *nvo ) {
+ uint8_t *checksum = nvo->data;
+ int rc;
+
+ /* Recalculate checksum, if applicable */
+ if ( nvo->len > 0 )
+ *checksum -= nvo_checksum ( nvo );
+
+ /* Write data */
+ if ( ( rc = nvs_write ( nvo->nvs, nvo->address, nvo->data,
+ nvo->len ) ) != 0 ) {
+ DBGC ( nvo, "NVO %p could not write %zd bytes at %#04x: %s\n",
+ nvo, nvo->len, nvo->address, strerror ( rc ) );
+ return rc;
+ }
+
+ DBGC ( nvo, "NVO %p saved to non-volatile storage\n", nvo );
+ return 0;
+}
+
+/**
+ * Check applicability of NVO setting
+ *
+ * @v settings Settings block
+ * @v setting Setting
+ * @ret applies Setting applies within this settings block
+ */
+static int nvo_applies ( struct settings *settings __unused,
+ struct setting *setting ) {
+
+ return dhcpopt_applies ( setting->tag );
+}
+
+/**
+ * Store value of NVO setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+static int nvo_store ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len ) {
+ struct nvo_block *nvo =
+ container_of ( settings, struct nvo_block, settings );
+ int rc;
+
+ /* Update stored options */
+ if ( ( rc = dhcpopt_store ( &nvo->dhcpopts, setting->tag,
+ data, len ) ) != 0 ) {
+ DBGC ( nvo, "NVO %p could not store %zd bytes: %s\n",
+ nvo, len, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Save updated options to NVS */
+ if ( ( rc = nvo_save ( nvo ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Fetch value of NVO setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ *
+ * The actual length of the setting will be returned even if
+ * the buffer was too small.
+ */
+static int nvo_fetch ( struct settings *settings, struct setting *setting,
+ void *data, size_t len ) {
+ struct nvo_block *nvo =
+ container_of ( settings, struct nvo_block, settings );
+
+ return dhcpopt_fetch ( &nvo->dhcpopts, setting->tag, data, len );
+}
+
+/** NVO settings operations */
+static struct settings_operations nvo_settings_operations = {
+ .applies = nvo_applies,
+ .store = nvo_store,
+ .fetch = nvo_fetch,
+};
+
+/**
+ * Initialise non-volatile stored options
+ *
+ * @v nvo Non-volatile options block
+ * @v nvs Underlying non-volatile storage device
+ * @v address Address within NVS device
+ * @v len Length of non-volatile options data
+ * @v resize Resize method
+ * @v refcnt Containing object reference counter, or NULL
+ */
+void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
+ size_t address, size_t len,
+ int ( * resize ) ( struct nvo_block *nvo, size_t len ),
+ struct refcnt *refcnt ) {
+ nvo->nvs = nvs;
+ nvo->address = address;
+ nvo->len = len;
+ nvo->resize = resize;
+ dhcpopt_init ( &nvo->dhcpopts, NULL, 0, nvo_realloc_dhcpopt );
+ settings_init ( &nvo->settings, &nvo_settings_operations, refcnt, 0 );
+}
+
+/**
+ * Register non-volatile stored options
+ *
+ * @v nvo Non-volatile options block
+ * @v parent Parent settings block, or NULL
+ * @ret rc Return status code
+ */
+int register_nvo ( struct nvo_block *nvo, struct settings *parent ) {
+ int rc;
+
+ /* Allocate memory for options */
+ if ( ( rc = nvo_realloc ( nvo, nvo->len ) ) != 0 )
+ goto err_realloc;
+
+ /* Read data from NVS */
+ if ( ( rc = nvo_load ( nvo ) ) != 0 )
+ goto err_load;
+
+ /* Register settings */
+ if ( ( rc = register_settings ( &nvo->settings, parent, "nvo" ) ) != 0 )
+ goto err_register;
+
+ DBGC ( nvo, "NVO %p registered\n", nvo );
+ return 0;
+
+ err_register:
+ err_load:
+ nvo_realloc ( nvo, 0 );
+ err_realloc:
+ return rc;
+}
+
+/**
+ * Unregister non-volatile stored options
+ *
+ * @v nvo Non-volatile options block
+ */
+void unregister_nvo ( struct nvo_block *nvo ) {
+ unregister_settings ( &nvo->settings );
+ nvo_realloc ( nvo, 0 );
+ DBGC ( nvo, "NVO %p unregistered\n", nvo );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/open.c b/src/VBox/Devices/PC/ipxe/src/core/open.c
new file mode 100644
index 00000000..b026efcd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/open.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/xfer.h>
+#include <ipxe/uri.h>
+#include <ipxe/socket.h>
+#include <ipxe/open.h>
+
+/** @file
+ *
+ * Data transfer interface opening
+ *
+ */
+
+/**
+ * Find opener for URI scheme
+ *
+ * @v scheme URI scheme
+ * @ret opener Opener, or NULL
+ */
+struct uri_opener * xfer_uri_opener ( const char *scheme ) {
+ struct uri_opener *opener;
+
+ for_each_table_entry ( opener, URI_OPENERS ) {
+ if ( strcmp ( scheme, opener->scheme ) == 0 )
+ return opener;
+ }
+ return NULL;
+}
+
+/**
+ * Open URI
+ *
+ * @v intf Data transfer interface
+ * @v uri URI
+ * @ret rc Return status code
+ *
+ * The URI will be regarded as being relative to the current working
+ * URI (see churi()).
+ */
+int xfer_open_uri ( struct interface *intf, struct uri *uri ) {
+ struct uri_opener *opener;
+ struct uri *resolved_uri;
+ int rc;
+
+ /* Resolve URI */
+ resolved_uri = resolve_uri ( cwuri, uri );
+ if ( ! resolved_uri ) {
+ rc = -ENOMEM;
+ goto err_resolve_uri;
+ }
+
+ /* Find opener which supports this URI scheme */
+ opener = xfer_uri_opener ( resolved_uri->scheme );
+ if ( ! opener ) {
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to open "
+ "unsupported URI scheme \"%s\"\n",
+ INTF_DBG ( intf ), resolved_uri->scheme );
+ rc = -ENOTSUP;
+ goto err_opener;
+ }
+
+ /* Call opener */
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " opening %s URI\n",
+ INTF_DBG ( intf ), resolved_uri->scheme );
+ if ( ( rc = opener->open ( intf, resolved_uri ) ) != 0 ) {
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " could not open: "
+ "%s\n", INTF_DBG ( intf ), strerror ( rc ) );
+ goto err_open;
+ }
+
+ err_open:
+ err_opener:
+ uri_put ( resolved_uri );
+ err_resolve_uri:
+ return rc;
+}
+
+/**
+ * Open URI string
+ *
+ * @v intf Data transfer interface
+ * @v uri_string URI string (e.g. "http://ipxe.org/kernel")
+ * @ret rc Return status code
+ *
+ * The URI will be regarded as being relative to the current working
+ * URI (see churi()).
+ */
+int xfer_open_uri_string ( struct interface *intf,
+ const char *uri_string ) {
+ struct uri *uri;
+ int rc;
+
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " opening URI %s\n",
+ INTF_DBG ( intf ), uri_string );
+
+ uri = parse_uri ( uri_string );
+ if ( ! uri )
+ return -ENOMEM;
+
+ rc = xfer_open_uri ( intf, uri );
+
+ uri_put ( uri );
+ return rc;
+}
+
+/**
+ * Open socket
+ *
+ * @v intf Data transfer interface
+ * @v semantics Communication semantics (e.g. SOCK_STREAM)
+ * @v peer Peer socket address
+ * @v local Local socket address, or NULL
+ * @ret rc Return status code
+ */
+int xfer_open_socket ( struct interface *intf, int semantics,
+ struct sockaddr *peer, struct sockaddr *local ) {
+ struct socket_opener *opener;
+
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " opening (%s,%s) socket\n",
+ INTF_DBG ( intf ), socket_semantics_name ( semantics ),
+ socket_family_name ( peer->sa_family ) );
+
+ for_each_table_entry ( opener, SOCKET_OPENERS ) {
+ if ( ( opener->semantics == semantics ) &&
+ ( opener->family == peer->sa_family ) ) {
+ return opener->open ( intf, peer, local );
+ }
+ }
+
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to open "
+ "unsupported socket type (%s,%s)\n",
+ INTF_DBG ( intf ), socket_semantics_name ( semantics ),
+ socket_family_name ( peer->sa_family ) );
+ return -ENOTSUP;
+}
+
+/**
+ * Open location
+ *
+ * @v intf Data transfer interface
+ * @v type Location type
+ * @v args Remaining arguments depend upon location type
+ * @ret rc Return status code
+ */
+int xfer_vopen ( struct interface *intf, int type, va_list args ) {
+ switch ( type ) {
+ case LOCATION_URI_STRING: {
+ const char *uri_string = va_arg ( args, const char * );
+
+ return xfer_open_uri_string ( intf, uri_string ); }
+ case LOCATION_URI: {
+ struct uri *uri = va_arg ( args, struct uri * );
+
+ return xfer_open_uri ( intf, uri ); }
+ case LOCATION_SOCKET: {
+ int semantics = va_arg ( args, int );
+ struct sockaddr *peer = va_arg ( args, struct sockaddr * );
+ struct sockaddr *local = va_arg ( args, struct sockaddr * );
+
+ return xfer_open_socket ( intf, semantics, peer, local ); }
+ default:
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to "
+ "open unsupported location type %d\n",
+ INTF_DBG ( intf ), type );
+ return -ENOTSUP;
+ }
+}
+
+/**
+ * Open location
+ *
+ * @v intf Data transfer interface
+ * @v type Location type
+ * @v ... Remaining arguments depend upon location type
+ * @ret rc Return status code
+ */
+int xfer_open ( struct interface *intf, int type, ... ) {
+ va_list args;
+ int rc;
+
+ va_start ( args, type );
+ rc = xfer_vopen ( intf, type, args );
+ va_end ( args );
+ return rc;
+}
+
+/**
+ * Reopen location
+ *
+ * @v intf Data transfer interface
+ * @v type Location type
+ * @v args Remaining arguments depend upon location type
+ * @ret rc Return status code
+ *
+ * This will close the existing connection and open a new connection
+ * using xfer_vopen(). It is intended to be used as a .vredirect
+ * method handler.
+ */
+int xfer_vreopen ( struct interface *intf, int type, va_list args ) {
+
+ /* Close existing connection */
+ intf_restart ( intf, 0 );
+
+ /* Open new location */
+ return xfer_vopen ( intf, type, args );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/parseopt.c b/src/VBox/Devices/PC/ipxe/src/core/parseopt.c
new file mode 100644
index 00000000..432e856d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/parseopt.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/menu.h>
+#include <ipxe/parseopt.h>
+
+/** @file
+ *
+ * Command line option parsing
+ *
+ */
+
+/** Return status code for "--help" option */
+#define ECANCELED_NO_OP __einfo_error ( EINFO_ECANCELED_NO_OP )
+#define EINFO_ECANCELED_NO_OP \
+ __einfo_uniqify ( EINFO_ECANCELED, 0x01, "Nothing to do" )
+
+/* Disambiguate the various error codes */
+#define EINVAL_INTEGER __einfo_error ( EINFO_EINVAL_INTEGER )
+#define EINFO_EINVAL_INTEGER \
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid integer value" )
+#define EINVAL_UNKNOWN_OPTION __einfo_error ( EINFO_EINVAL_UNKNOWN_OPTION )
+#define EINFO_EINVAL_UNKNOWN_OPTION \
+ __einfo_uniqify ( EINFO_EINVAL, 0x02, "Unrecognised option" )
+#define EINVAL_MISSING_ARGUMENT __einfo_error ( EINFO_EINVAL_MISSING_ARGUMENT )
+#define EINFO_EINVAL_MISSING_ARGUMENT \
+ __einfo_uniqify ( EINFO_EINVAL, 0x03, "Missing argument" )
+
+/**
+* Parse string value
+ *
+ * @v text Text
+ * @ret value String value
+ * @ret rc Return status code
+ */
+int parse_string ( const char *text, const char **value ) {
+
+ /* Sanity check */
+ assert ( text != NULL );
+
+ /* Parse string */
+ *value = text;
+
+ return 0;
+}
+
+/**
+ * Parse integer value
+ *
+ * @v text Text
+ * @ret value Integer value
+ * @ret rc Return status code
+ */
+int parse_integer ( const char *text, unsigned int *value ) {
+ char *endp;
+
+ /* Sanity check */
+ assert ( text != NULL );
+
+ /* Parse integer */
+ *value = strtoul ( text, &endp, 0 );
+ if ( *endp ) {
+ printf ( "\"%s\": invalid integer value\n", text );
+ return -EINVAL_INTEGER;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse network device name
+ *
+ * @v text Text
+ * @ret netdev Network device
+ * @ret rc Return status code
+ */
+int parse_netdev ( const char *text, struct net_device **netdev ) {
+
+ /* Sanity check */
+ assert ( text != NULL );
+
+ /* Find network device */
+ *netdev = find_netdev ( text );
+ if ( ! *netdev ) {
+ printf ( "\"%s\": no such network device\n", text );
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse menu name
+ *
+ * @v text Text
+ * @ret menu Menu
+ * @ret rc Return status code
+ */
+int parse_menu ( const char *text, struct menu **menu ) {
+
+ /* Find menu */
+ *menu = find_menu ( text );
+ if ( ! *menu ) {
+ if ( text ) {
+ printf ( "\"%s\": no such menu\n", text );
+ } else {
+ printf ( "No default menu\n" );
+ }
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse flag
+ *
+ * @v text Text (ignored)
+ * @ret flag Flag to set
+ * @ret rc Return status code
+ */
+int parse_flag ( const char *text __unused, int *flag ) {
+
+ /* Set flag */
+ *flag = 1;
+
+ return 0;
+}
+
+/**
+ * Parse key
+ *
+ * @v text Text
+ * @ret key Key
+ * @ret rc Return status code
+ */
+int parse_key ( const char *text, unsigned int *key ) {
+
+ /* Interpret single characters as being a literal key character */
+ if ( text[0] && ! text[1] ) {
+ *key = text[0];
+ return 0;
+ }
+
+ /* Otherwise, interpret as an integer */
+ return parse_integer ( text, key );
+}
+
+/**
+ * Print command usage message
+ *
+ * @v cmd Command descriptor
+ * @v argv Argument list
+ */
+void print_usage ( struct command_descriptor *cmd, char **argv ) {
+ printf ( "Usage:\n\n %s %s\n\nSee http://ipxe.org/cmd/%s for further "
+ "information\n", argv[0], cmd->usage, argv[0] );
+}
+
+/**
+ * Reparse command-line options
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v cmd Command descriptor
+ * @v opts Options (already initialised with default values)
+ * @ret rc Return status code
+ */
+int reparse_options ( int argc, char **argv, struct command_descriptor *cmd,
+ void *opts ) {
+ struct option longopts[ cmd->num_options + 1 /* help */ + 1 /* end */ ];
+ char shortopts[ cmd->num_options * 3 /* possible "::" */ + 1 /* "h" */
+ + 1 /* NUL */ ];
+ unsigned int shortopt_idx = 0;
+ int ( * parse ) ( const char *text, void *value );
+ void *value;
+ unsigned int i;
+ unsigned int j;
+ unsigned int num_args;
+ int c;
+ int rc;
+
+ /* Construct long and short option lists for getopt_long() */
+ memset ( longopts, 0, sizeof ( longopts ) );
+ for ( i = 0 ; i < cmd->num_options ; i++ ) {
+ longopts[i].name = cmd->options[i].longopt;
+ longopts[i].has_arg = cmd->options[i].has_arg;
+ longopts[i].val = cmd->options[i].shortopt;
+ shortopts[shortopt_idx++] = cmd->options[i].shortopt;
+ assert ( cmd->options[i].has_arg <= optional_argument );
+ for ( j = cmd->options[i].has_arg ; j > 0 ; j-- )
+ shortopts[shortopt_idx++] = ':';
+ }
+ longopts[i].name = "help";
+ longopts[i].val = 'h';
+ shortopts[shortopt_idx++] = 'h';
+ shortopts[shortopt_idx++] = '\0';
+ assert ( shortopt_idx <= sizeof ( shortopts ) );
+ DBGC ( cmd, "Command \"%s\" has options \"%s\", %d-%d args, len %d\n",
+ argv[0], shortopts, cmd->min_args, cmd->max_args, cmd->len );
+
+ /* Parse options */
+ while ( ( c = getopt_long ( argc, argv, shortopts, longopts,
+ NULL ) ) >= 0 ) {
+ switch ( c ) {
+ case 'h' :
+ /* Print help */
+ print_usage ( cmd, argv );
+ return -ECANCELED_NO_OP;
+ case '?' :
+ /* Print usage message */
+ print_usage ( cmd, argv );
+ return -EINVAL_UNKNOWN_OPTION;
+ case ':' :
+ /* Print usage message */
+ print_usage ( cmd, argv );
+ return -EINVAL_MISSING_ARGUMENT;
+ default:
+ /* Search for an option to parse */
+ for ( i = 0 ; i < cmd->num_options ; i++ ) {
+ if ( c != cmd->options[i].shortopt )
+ continue;
+ parse = cmd->options[i].parse;
+ value = ( opts + cmd->options[i].offset );
+ if ( ( rc = parse ( optarg, value ) ) != 0 )
+ return rc;
+ break;
+ }
+ assert ( i < cmd->num_options );
+ }
+ }
+
+ /* Check remaining arguments */
+ num_args = ( argc - optind );
+ if ( ( num_args < cmd->min_args ) || ( num_args > cmd->max_args ) ) {
+ print_usage ( cmd, argv );
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse command-line options
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v cmd Command descriptor
+ * @v opts Options (may be uninitialised)
+ * @ret rc Return status code
+ */
+int parse_options ( int argc, char **argv, struct command_descriptor *cmd,
+ void *opts ) {
+
+ /* Clear options */
+ memset ( opts, 0, cmd->len );
+
+ return reparse_options ( argc, argv, cmd, opts );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/pc_kbd.c b/src/VBox/Devices/PC/ipxe/src/core/pc_kbd.c
new file mode 100644
index 00000000..42df755b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/pc_kbd.c
@@ -0,0 +1,112 @@
+/* Minimal polling PC keyboard driver
+ * - No interrupt
+ * - No LED
+ * - No special keys
+ *
+ * still Enough For Me to type a filename.
+ *
+ * 2003-07 by SONE Takesh
+ * 2004-04 moved by LYH From filo to Etherboot
+ * yhlu@tyan.com
+ */
+
+#include <ipxe/io.h>
+#include <ipxe/console.h>
+
+static char key_map[][128] = {
+ {
+ "\0\x1b""1234567890-=\b\t"
+ "qwertyuiop[]\r\0as"
+ "dfghjkl;'`\0\\zxcv"
+ "bnm,./\0*\0 \0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0""789-456+1"
+ "230."
+ },{
+ "\0\x1b""!@#$%^&*()_+\b\t"
+ "QWERTYUIOP{}\r\0AS"
+ "DFGHJKL:\"~\0|ZXCV"
+ "BNM<>?\0\0\0 \0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0""789-456+1"
+ "230."
+ }
+};
+
+static int cur_scan;
+static unsigned int shift_state;
+#define SHIFT 1
+#define CONTROL 2
+#define CAPS 4
+
+static int get_scancode(void)
+{
+ int scan;
+
+ if ((inb(0x64) & 1) == 0)
+ return 0;
+ scan = inb(0x60);
+
+ switch (scan) {
+ case 0x2a:
+ case 0x36:
+ shift_state |= SHIFT;
+ break;
+ case 0xaa:
+ case 0xb6:
+ shift_state &= ~SHIFT;
+ break;
+ case 0x1d:
+ shift_state |= CONTROL;
+ break;
+ case 0x9d:
+ shift_state &= ~CONTROL;
+ break;
+ case 0x3a:
+ shift_state ^= CAPS;
+ break;
+ }
+
+ if (scan & 0x80)
+ return 0; /* ignore break code or 0xe0 etc! */
+ return scan;
+}
+
+static int kbd_havekey(void)
+{
+ if (!cur_scan)
+ cur_scan = get_scancode();
+ return cur_scan != 0;
+}
+
+static int kbd_ischar(void)
+{
+ if (!kbd_havekey())
+ return 0;
+ if (!key_map[shift_state & SHIFT][cur_scan]) {
+ cur_scan = 0;
+ return 0;
+ }
+ return 1;
+}
+
+static int kbd_getc(void)
+{
+ int c;
+
+ while (!kbd_ischar())
+ ;
+ c = key_map[shift_state & SHIFT][cur_scan];
+ if (shift_state & (CONTROL | CAPS)) {
+ if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
+ if (shift_state & CONTROL)
+ c &= 0x1f;
+ else if (shift_state & CAPS)
+ c ^= ('A' ^ 'a');
+ }
+ }
+ cur_scan = 0;
+ return c;
+}
+
+struct console_driver pc_kbd_console __console_driver = {
+ .getchar = kbd_getc,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/core/pcmcia.c b/src/VBox/Devices/PC/ipxe/src/core/pcmcia.c
new file mode 100644
index 00000000..5fd21f4a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/pcmcia.c
@@ -0,0 +1,269 @@
+#if 0
+
+/*
+ * pcmcia.c
+ *
+ * PCMCIA support routines for etherboot - generic stuff
+ *
+ * This code has partly be taken from the linux kernel sources, .../drivers/pcmcia/
+ * Started & put together by
+ * Anselm Martin Hoffmeister
+ * Stockholm Projekt Computer-Service
+ * Sankt Augustin / Bonn, Germany
+ *
+ * Distributed under GPL2
+ */
+
+/*
+ *
+ *
+ * ******************************
+ * PLEASE DO NOT YET WORK ON THIS
+ * ******************************
+ *
+ * I'm still fixing it up on every end, so we most probably would interfere
+ * at some point. If there's anything obvious or better, not-so-obvious,
+ * please contact me by e-mail: anselm (AT) hoffmeister (DOT) be *THANKS*
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include <stdio.h>
+#include <pcmcia.h>
+#include <i82365.h>
+#define CODE_STATUS "alpha"
+#define CODE_VERSION "0.1.3"
+#include <pcmcia-opts.h>
+#include <ipxe/init.h>
+
+int sockets; /* AHTODO: Phase this out! */
+u_int pccsocks;
+struct pccsock_t pccsock[MAXPCCSOCKS];
+int inited = -1;
+struct pcc_config_t pccconfig[MAXPCCCONFIGS];
+
+struct driver_interact_t driver[] = {
+#ifdef SUPPORT_I82365
+ { I82365, i82365_interfacer, "Intel_82365" },
+#endif
+};
+
+#define NUM_DRIVERS (sizeof(driver)/(sizeof(struct driver_interact_t)))
+
+void sleepticks(int numticks ) {
+ u_int tmo;
+ for (tmo = currticks()+numticks; currticks() < tmo; ) {
+ }
+ return;
+}
+
+static void pcmcia_init_all(void) {
+ u_int i, j, k, l, m, n, ui, configs = 0;
+ u_int multicard[8];
+ u_char *uc, upc;
+ if ( PDEBUG > 0 ) printf("Initializing PCMCIA subsystem (code-status: " CODE_STATUS ", Version " CODE_VERSION ")\n");
+ if ( PDEBUG > 2 ) {
+ printf ( "Supporting %d driver(s): ", NUM_DRIVERS );
+ for ( i = 0; i < NUM_DRIVERS; ++i ) {
+ printf ( "[%s] ", driver[i].name );
+ }
+ printf ( "\n" );
+ }
+ pccsocks = 0;
+ sockets = 0;
+ // Init all drivers in the driver[] array:
+ for ( i = 0; i < NUM_DRIVERS; ++i ) {
+ driver[i].f(INIT,0,i,0,0); // init needs no params. It uses pccsocks and pccsock[].
+ // Only i tells it which driver_id itself is.
+ }
+ for ( i = 0; i < pccsocks; ++i ) {
+ printf ( "Socket %d: ", i );
+ if ( pccsock[i].status != HASCARD ) {
+ printf ( "is %s: skipping\n", pccsock[i].status == EMPTY? "empty":"[status unknown]" );
+ continue;
+ }
+ if ( 0 != driver[pccsock[i].drivernum].f(MAPATTRMEM,pccsock[i].internalid,MAP_ATTRMEM_TO, MAP_ATTRMEM_LEN,0 ) ) {
+ printf ("PCMCIA controller failed to map attribute memory.\n**** SEVERE ERROR CONDITION. Skipping controller.\n" );
+ if ( PDEBUG > 2 ) {
+ printf ( "<press key. THIS CONDITION SHOULD BE REPORTED!>\n" ); getchar();
+ }
+ continue;
+ }
+ // parse configuration information
+ uc = ioremap ( MAP_ATTRMEM_TO, MAP_ATTRMEM_LEN );
+ pccsock[i].stringoffset = pccsock[i].configoffset = pccsock[i].stringlength = 0;
+ pccsock[i].type = 0xff;
+ for ( l = 0; l < 8; ++l ) multicard[l] = 0;
+ sleepticks(2);
+ for ( l = ui = 0; ui < 0x800; ui += uc[(2*ui)+2] + 2 ) {
+ if ( uc[(2*ui)] == 0xff ) {
+ break;
+ }
+ // This loop is complete rubbish AFAICS.
+ // But without it, my test system won't come up.
+ // It's too bad to develop on broken hardware
+ // - Anselm
+ }
+ sleepticks(2);
+ configs = 0;
+ inited = -1;
+ for ( l = ui = 0; ui < 0x800; ui += uc[(2*ui)+2] + 2 ) {
+ if ( uc[(2*ui)] == 0xff ) break;
+ else if ( uc[2*ui] == 0x15 ) {
+ for ( k = 2 * ( ui + 2 ); ( uc[k] <= ' ' ) && ( k < ( 2 * ( uc[2*(ui+1)] + ui + 2 ) ) ) ; k += 2 ) { ; }
+ pccsock[i].stringoffset = k;
+ pccsock[i].stringlength = ( 2 * ( ui + 2 + uc[(2*ui)+2] ) - k ) / 2;
+ } else if ( uc[2*ui] == 0x21 ) {
+ pccsock[i].type = uc[(2*ui)+4];
+ } else if ( uc[2*ui] == 0x1a ) { // Configuration map
+ printf ( "\nConfig map 0x1a found [" );
+ for ( k = 0; k < uc[2*(ui+1)]; ++k ) {
+ printf ( "%02x ", uc[2*(ui+k+2)] );
+ }
+ printf ( "]\nHighest config available is %d\n", uc[2*(ui+3)] );
+ m = uc[2*(ui+2)];
+ pccsock[i].configoffset = 0;
+ for ( j = 0; j <= (m & 3); ++j ) {
+ pccsock[i].configoffset += uc[2*(ui+4+j)] << (8*j);
+ }
+ pccsock[i].rmask0 = 0;
+ for ( j = 0; j <= ( ( ( m & 0x3c ) >> 2 ) & 3 ); ++j ) {
+ pccsock[i].rmask0 += uc[2*(ui+5+(m&3)+j)] << (8*j);
+ }
+ j = pccsock[i].rmask0;
+ printf ( "Config offset is %x, card has regs: < %s%s%s%s%s>\n", pccsock[i].configoffset,
+ j & 1 ? "COR ":"", j & 2 ? "CCSR ":"", j & 4 ? "PRR ":"", j & 8 ? "SCR ":"", j & 16? "ESR ":"" );
+ printf ( "COR + CCSR contents (si/du) %x %x/%x %x\n", uc[pccsock[i].configoffset+0],
+ uc[pccsock[i].configoffset+2],uc[pccsock[i].configoffset*2],uc[(pccsock[i].configoffset*2)+2] );
+ printf ( " " );
+ } else if ( uc[2*ui] == 0x1b ) { // Configuration data entry
+ //printf ( "Config data 0x1b found [\n" );getchar();
+ for ( k = 0; k < uc[2*(ui+1)]; ++k ) {
+ // printf ( "%02x ", uc[2*(ui+k+2)] );
+ }
+ // Parse this tuple into pccconfig[configs]
+ // printf ( "]\n" );
+ if ( configs == MAXPCCCONFIGS ) continue;
+ k = 2*ui+4;
+ pccconfig[configs].index = uc[k] & 0x3f;
+ if ( uc[k] & 0x80 ) {
+ // printf ( "Special config, unsupp. for now\n" );
+ continue;
+ }
+ k+=2;
+ // printf ( "Features: %2x\n", uc[k] );
+ if ( uc[k] & 0x7 ) {
+ // printf ( "Cannot work with Vcc/Timing configs right now\n" );
+ continue;
+ }
+ pccconfig[configs].iowin = pccconfig[configs].iolen = 0;
+ if ( 0 != ( uc[k] & 0x8 ) ) {
+ k+=2;
+ // printf ( "Reading IO config: " );
+ if ( 0 == ( uc[k] & 0x80 ) ) {
+ // printf ( "Cannot work with auto/io config\n" );
+ continue;
+ }
+ k+=2;
+ if ( 0 != ( uc[k] & 0x0f ) ) {
+ // printf ( "Don't support more than 1 iowin right now\n" );
+ continue;
+ }
+ j = (uc[k] & 0x30) >> 4;
+ m = (uc[k] & 0xc0) >> 6;
+ if ( 3 == j ) ++j;
+ if ( 3 == m ) ++m;
+ k += 2;
+ pccconfig[configs].iowin = 0;
+ pccconfig[configs].iolen = 1;
+ for ( n = 0; n < j; ++n, k+=2 ) {
+ pccconfig[configs].iowin += uc[k] << (n*8);
+ }
+ for ( n = 0; n < m; ++n, k+=2 ) {
+ pccconfig[configs].iolen += uc[k] << (n*8);
+ }
+ // printf ( "io %x len %d (%d)\n", pccconfig[configs].iowin, pccconfig[configs].iolen,configs );
+ }
+ for ( j = 0; j < (uc[k] & 3); ++j ) {
+ // pccconfig[configs].iowin += (uc[k+(2*j)+2]) << (8*j);
+ }
+ ++configs;
+ }
+ }
+ if ( pccsock[i].stringoffset > 0 ) { // If no identifier, it's not a valid CIS (as of documentation...)
+ printf ( "[" );
+ for ( k = 0; ( k < pccsock[i].stringlength ) && ( k < 64 ); ++k ) {
+ j = uc[pccsock[i].stringoffset + 2 * k];
+ printf ( "%c", (j>=' '? j:' ' ) );
+ }
+ printf ("]\n is type %d (", pccsock[i].type );
+ switch ( pccsock[i].type ) {
+ case 0x00:
+ printf ( "MULTI" ); break;
+ case 0x01:
+ printf ( "Memory" ); break;
+ case 0x02:
+ printf ( "Serial" ); break;
+ case 0x03:
+ printf ( "Parallel" ); break;
+ case 0x04:
+ printf ( "Fixed" ); break;
+ case 0x05:
+ printf ( "Video" ); break;
+ case 0x06:
+ printf ( "Network" ); break;
+ case 0x07:
+ printf ( "AIMS" ); break;
+ case 0x08:
+ printf ( "SCSI" ); break;
+ case 0x106: // Special / homebrew to say "Multi/network"
+ printf ( "MULTI, with Network" ); break; // AHTODO find a card for this
+ default:
+ printf ( "UNSUPPORTED/UNKNOWN" );
+ }
+ printf ( ") with %d possible configuration(s)\n", configs );
+ // Now set dependency: If it's Network or multi->network, accept
+ if ( (inited <= 0 ) && (6 == (0xff & pccsock[i].type) ) && (0 < configs ) ) {
+ printf ( "activating this device with ioport %x-%x (config #%d)\n",
+ pccconfig[0].iowin, pccconfig[0].iowin+pccconfig[0].iolen-1, pccconfig[0].index );
+ inited = i;
+ // And unmap attrmem ourselves!
+ printf ( "Activating config..." );
+ if ( m=driver[pccsock[i].drivernum].f(SELECTCONFIG,pccsock[i].internalid,pccconfig[0].index,0,&pccconfig[0]) ) {
+ printf ("Failure(%d)!",m); inited = -1;
+ driver[pccsock[i].drivernum].f(UNMAPATTRMEM,pccsock[i].internalid,0,0,0);
+ }
+ printf ( "done!\n" );
+ continue;
+ }
+ } else {
+ printf ( "unsupported - no identifier string found in CIS\n" );
+ }
+ // unmap the PCMCIA device
+ if ( i != inited ) {
+ if ( 0 != driver[pccsock[i].drivernum].f(UNMAPATTRMEM,pccsock[i].internalid,0,0,0) ) {
+ printf ("PCMCIA controller failed to unmap attribute memory.\n**** SEVERE ERROR CONDITION ****\n" );
+ if ( PDEBUG > 2 ) {
+ printf ( "<press key. THIS CONDITION SHOULD BE REPORTED!>\n" ); getchar();
+ }
+ continue;
+ }
+ }
+ }
+ if ( PDEBUG > 2 ) {
+ printf ( "<press key to exit the pcmcia_init_all routine>\n" );
+ getchar();
+ }
+
+}
+
+static void pcmcia_shutdown_all(void) {
+ int i;
+ //if ( PDEBUG > 2 ) {printf("<press key to continue>\n" ); getchar(); }
+ for ( i = 0; i < pccsocks; ++i ) {
+ driver[pccsock[i].drivernum].f(SHUTDOWN,pccsock[i].internalid,0,0,0);
+ }
+ printf("Shutdown of PCMCIA subsystem completed");
+}
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/core/posix_io.c b/src/VBox/Devices/PC/ipxe/src/core/posix_io.c
new file mode 100644
index 00000000..38bd727b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/posix_io.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/list.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/process.h>
+#include <ipxe/posix_io.h>
+
+/** @file
+ *
+ * POSIX-like I/O
+ *
+ * These functions provide traditional blocking I/O semantics. They
+ * are designed to be used by the PXE TFTP API. Because they block,
+ * they may not be used by most other portions of the iPXE codebase.
+ */
+
+/** An open file */
+struct posix_file {
+ /** Reference count for this object */
+ struct refcnt refcnt;
+ /** List of open files */
+ struct list_head list;
+ /** File descriptor */
+ int fd;
+ /** Overall status
+ *
+ * Set to -EINPROGRESS while data transfer is in progress.
+ */
+ int rc;
+ /** Data transfer interface */
+ struct interface xfer;
+ /** Current seek position */
+ size_t pos;
+ /** File size */
+ size_t filesize;
+ /** Received data queue */
+ struct list_head data;
+};
+
+/** List of open files */
+static LIST_HEAD ( posix_files );
+
+/**
+ * Free open file
+ *
+ * @v refcnt Reference counter
+ */
+static void posix_file_free ( struct refcnt *refcnt ) {
+ struct posix_file *file =
+ container_of ( refcnt, struct posix_file, refcnt );
+ struct io_buffer *iobuf;
+ struct io_buffer *tmp;
+
+ list_for_each_entry_safe ( iobuf, tmp, &file->data, list ) {
+ list_del ( &iobuf->list );
+ free_iob ( iobuf );
+ }
+ free ( file );
+}
+
+/**
+ * Terminate file data transfer
+ *
+ * @v file POSIX file
+ * @v rc Reason for termination
+ */
+static void posix_file_finished ( struct posix_file *file, int rc ) {
+ intf_shutdown ( &file->xfer, rc );
+ file->rc = rc;
+}
+
+/**
+ * Handle deliver_iob() event
+ *
+ * @v file POSIX file
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int posix_file_xfer_deliver ( struct posix_file *file,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+
+ /* Keep track of file position solely for the filesize */
+ if ( meta->flags & XFER_FL_ABS_OFFSET )
+ file->pos = 0;
+ file->pos += meta->offset;
+ if ( file->filesize < file->pos )
+ file->filesize = file->pos;
+
+ if ( iob_len ( iobuf ) ) {
+ list_add_tail ( &iobuf->list, &file->data );
+ } else {
+ free_iob ( iobuf );
+ }
+
+ return 0;
+}
+
+/** POSIX file data transfer interface operations */
+static struct interface_operation posix_file_xfer_operations[] = {
+ INTF_OP ( xfer_deliver, struct posix_file *, posix_file_xfer_deliver ),
+ INTF_OP ( intf_close, struct posix_file *, posix_file_finished ),
+};
+
+/** POSIX file data transfer interface descriptor */
+static struct interface_descriptor posix_file_xfer_desc =
+ INTF_DESC ( struct posix_file, xfer, posix_file_xfer_operations );
+
+/**
+ * Identify file by file descriptor
+ *
+ * @v fd File descriptor
+ * @ret file Corresponding file, or NULL
+ */
+static struct posix_file * posix_fd_to_file ( int fd ) {
+ struct posix_file *file;
+
+ list_for_each_entry ( file, &posix_files, list ) {
+ if ( file->fd == fd )
+ return file;
+ }
+ return NULL;
+}
+
+/**
+ * Find an available file descriptor
+ *
+ * @ret fd File descriptor, or negative error number
+ */
+static int posix_find_free_fd ( void ) {
+ int fd;
+
+ for ( fd = POSIX_FD_MIN ; fd <= POSIX_FD_MAX ; fd++ ) {
+ if ( ! posix_fd_to_file ( fd ) )
+ return fd;
+ }
+ DBG ( "POSIX could not find free file descriptor\n" );
+ return -ENFILE;
+}
+
+/**
+ * Open file
+ *
+ * @v uri_string URI string
+ * @ret fd File descriptor, or negative error number
+ */
+int open ( const char *uri_string ) {
+ struct posix_file *file;
+ int fd;
+ int rc;
+
+ /* Find a free file descriptor to use */
+ fd = posix_find_free_fd();
+ if ( fd < 0 )
+ return fd;
+
+ /* Allocate and initialise structure */
+ file = zalloc ( sizeof ( *file ) );
+ if ( ! file )
+ return -ENOMEM;
+ ref_init ( &file->refcnt, posix_file_free );
+ file->fd = fd;
+ file->rc = -EINPROGRESS;
+ intf_init ( &file->xfer, &posix_file_xfer_desc, &file->refcnt );
+ INIT_LIST_HEAD ( &file->data );
+
+ /* Open URI on data transfer interface */
+ if ( ( rc = xfer_open_uri_string ( &file->xfer, uri_string ) ) != 0 )
+ goto err;
+
+ /* Wait for open to succeed or fail */
+ while ( list_empty ( &file->data ) ) {
+ step();
+ if ( file->rc == 0 )
+ break;
+ if ( file->rc != -EINPROGRESS ) {
+ rc = file->rc;
+ goto err;
+ }
+ }
+
+ /* Add to list of open files. List takes reference ownership. */
+ list_add ( &file->list, &posix_files );
+ DBG ( "POSIX opened %s as file %d\n", uri_string, fd );
+ return fd;
+
+ err:
+ posix_file_finished ( file, rc );
+ ref_put ( &file->refcnt );
+ return rc;
+}
+
+/**
+ * Check file descriptors for readiness
+ *
+ * @v readfds File descriptors to check
+ * @v wait Wait until data is ready
+ * @ret nready Number of ready file descriptors
+ */
+int select ( fd_set *readfds, int wait ) {
+ struct posix_file *file;
+ int fd;
+
+ do {
+ for ( fd = POSIX_FD_MIN ; fd <= POSIX_FD_MAX ; fd++ ) {
+ if ( ! FD_ISSET ( fd, readfds ) )
+ continue;
+ file = posix_fd_to_file ( fd );
+ if ( ! file )
+ return -EBADF;
+ if ( ( list_empty ( &file->data ) ) &&
+ ( file->rc == -EINPROGRESS ) )
+ continue;
+ /* Data is available or status has changed */
+ FD_ZERO ( readfds );
+ FD_SET ( fd, readfds );
+ return 1;
+ }
+ step();
+ } while ( wait );
+
+ return 0;
+}
+
+/**
+ * Read data from file
+ *
+ * @v buffer Data buffer
+ * @v offset Starting offset within data buffer
+ * @v len Maximum length to read
+ * @ret len Actual length read, or negative error number
+ *
+ * This call is non-blocking; if no data is available to read then
+ * -EWOULDBLOCK will be returned.
+ */
+ssize_t read_user ( int fd, userptr_t buffer, off_t offset, size_t max_len ) {
+ struct posix_file *file;
+ struct io_buffer *iobuf;
+ size_t len;
+
+ /* Identify file */
+ file = posix_fd_to_file ( fd );
+ if ( ! file )
+ return -EBADF;
+
+ /* Try to fetch more data if none available */
+ if ( list_empty ( &file->data ) )
+ step();
+
+ /* Dequeue at most one received I/O buffer into user buffer */
+ list_for_each_entry ( iobuf, &file->data, list ) {
+ len = iob_len ( iobuf );
+ if ( len > max_len )
+ len = max_len;
+ copy_to_user ( buffer, offset, iobuf->data, len );
+ iob_pull ( iobuf, len );
+ if ( ! iob_len ( iobuf ) ) {
+ list_del ( &iobuf->list );
+ free_iob ( iobuf );
+ }
+ file->pos += len;
+ assert ( len != 0 );
+ return len;
+ }
+
+ /* If file has completed, return (after returning all data) */
+ if ( file->rc != -EINPROGRESS ) {
+ assert ( list_empty ( &file->data ) );
+ return file->rc;
+ }
+
+ /* No data ready and file still in progress; return -WOULDBLOCK */
+ return -EWOULDBLOCK;
+}
+
+/**
+ * Determine file size
+ *
+ * @v fd File descriptor
+ * @ret size File size, or negative error number
+ */
+ssize_t fsize ( int fd ) {
+ struct posix_file *file;
+
+ /* Identify file */
+ file = posix_fd_to_file ( fd );
+ if ( ! file )
+ return -EBADF;
+
+ return file->filesize;
+}
+
+/**
+ * Close file
+ *
+ * @v fd File descriptor
+ * @ret rc Return status code
+ */
+int close ( int fd ) {
+ struct posix_file *file;
+
+ /* Identify file */
+ file = posix_fd_to_file ( fd );
+ if ( ! file )
+ return -EBADF;
+
+ /* Terminate data transfer */
+ posix_file_finished ( file, 0 );
+
+ /* Remove from list of open files and drop reference */
+ list_del ( &file->list );
+ ref_put ( &file->refcnt );
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/process.c b/src/VBox/Devices/PC/ipxe/src/core/process.c
new file mode 100644
index 00000000..4a705ef6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/process.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/list.h>
+#include <ipxe/init.h>
+#include <ipxe/process.h>
+
+/** @file
+ *
+ * Processes
+ *
+ * We implement a trivial form of cooperative multitasking, in which
+ * all processes share a single stack and address space.
+ */
+
+/** Process run queue */
+static LIST_HEAD ( run_queue );
+
+/**
+ * Get pointer to object containing process
+ *
+ * @v process Process
+ * @ret object Containing object
+ */
+void * process_object ( struct process *process ) {
+ return ( ( ( void * ) process ) - process->desc->offset );
+}
+
+/**
+ * Add process to process list
+ *
+ * @v process Process
+ *
+ * It is safe to call process_add() multiple times; further calls will
+ * have no effect.
+ */
+void process_add ( struct process *process ) {
+ if ( ! process_running ( process ) ) {
+ DBGC ( PROC_COL ( process ), "PROCESS " PROC_FMT
+ " starting\n", PROC_DBG ( process ) );
+ ref_get ( process->refcnt );
+ list_add_tail ( &process->list, &run_queue );
+ } else {
+ DBGC ( PROC_COL ( process ), "PROCESS " PROC_FMT
+ " already started\n", PROC_DBG ( process ) );
+ }
+}
+
+/**
+ * Remove process from process list
+ *
+ * @v process Process
+ *
+ * It is safe to call process_del() multiple times; further calls will
+ * have no effect.
+ */
+void process_del ( struct process *process ) {
+ if ( process_running ( process ) ) {
+ DBGC ( PROC_COL ( process ), "PROCESS " PROC_FMT
+ " stopping\n", PROC_DBG ( process ) );
+ list_del ( &process->list );
+ INIT_LIST_HEAD ( &process->list );
+ ref_put ( process->refcnt );
+ } else {
+ DBGC ( PROC_COL ( process ), "PROCESS " PROC_FMT
+ " already stopped\n", PROC_DBG ( process ) );
+ }
+}
+
+/**
+ * Single-step a single process
+ *
+ * This executes a single step of the first process in the run queue,
+ * and moves the process to the end of the run queue.
+ */
+void step ( void ) {
+ struct process *process;
+ struct process_descriptor *desc;
+ void *object;
+
+ if ( ( process = list_first_entry ( &run_queue, struct process,
+ list ) ) ) {
+ ref_get ( process->refcnt ); /* Inhibit destruction mid-step */
+ desc = process->desc;
+ object = process_object ( process );
+ if ( desc->reschedule ) {
+ list_del ( &process->list );
+ list_add_tail ( &process->list, &run_queue );
+ } else {
+ process_del ( process );
+ }
+ DBGC2 ( PROC_COL ( process ), "PROCESS " PROC_FMT
+ " executing\n", PROC_DBG ( process ) );
+ desc->step ( object );
+ DBGC2 ( PROC_COL ( process ), "PROCESS " PROC_FMT
+ " finished executing\n", PROC_DBG ( process ) );
+ ref_put ( process->refcnt ); /* Allow destruction */
+ }
+}
+
+/**
+ * Initialise processes
+ *
+ */
+static void init_processes ( void ) {
+ struct process *process;
+
+ for_each_table_entry ( process, PERMANENT_PROCESSES )
+ process_add ( process );
+}
+
+/** Process initialiser */
+struct init_fn process_init_fn __init_fn ( INIT_NORMAL ) = {
+ .initialise = init_processes,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/core/random.c b/src/VBox/Devices/PC/ipxe/src/core/random.c
new file mode 100644
index 00000000..8824dca3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/random.c
@@ -0,0 +1,41 @@
+/** @file
+ *
+ * Random number generation
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <ipxe/timer.h>
+
+static int32_t rnd_seed = 0;
+
+/**
+ * Seed the pseudo-random number generator
+ *
+ * @v seed Seed value
+ */
+void srandom ( unsigned int seed ) {
+ rnd_seed = seed;
+}
+
+/**
+ * Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
+ *
+ * @ret rand Pseudo-random number
+ */
+long int random ( void ) {
+ int32_t q;
+
+ if ( ! rnd_seed ) /* Initialize linear congruential generator */
+ srandom ( currticks() );
+
+ /* simplified version of the LCG given in Bruce Schneier's
+ "Applied Cryptography" */
+ q = ( rnd_seed / 53668 );
+ rnd_seed = ( 40014 * ( rnd_seed - 53668 * q ) - 12211 * q );
+ if ( rnd_seed < 0 )
+ rnd_seed += 2147483563L;
+ return rnd_seed;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/refcnt.c b/src/VBox/Devices/PC/ipxe/src/core/refcnt.c
new file mode 100644
index 00000000..6117d741
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/refcnt.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <ipxe/refcnt.h>
+
+/** @file
+ *
+ * Reference counting
+ *
+ */
+
+/**
+ * Increment reference count
+ *
+ * @v refcnt Reference counter, or NULL
+ *
+ * If @c refcnt is NULL, no action is taken.
+ */
+void ref_increment ( struct refcnt *refcnt ) {
+
+ if ( refcnt ) {
+ refcnt->count++;
+ DBGC2 ( refcnt, "REFCNT %p incremented to %d\n",
+ refcnt, refcnt->count );
+ }
+}
+
+/**
+ * Decrement reference count
+ *
+ * @v refcnt Reference counter, or NULL
+ *
+ * If the reference count decreases below zero, the object's free()
+ * method will be called.
+ *
+ * If @c refcnt is NULL, no action is taken.
+ */
+void ref_decrement ( struct refcnt *refcnt ) {
+
+ if ( ! refcnt )
+ return;
+
+ refcnt->count--;
+ DBGC2 ( refcnt, "REFCNT %p decremented to %d\n",
+ refcnt, refcnt->count );
+
+ if ( refcnt->count >= 0 )
+ return;
+
+ if ( refcnt->count < -1 ) {
+ DBGC ( refcnt, "REFCNT %p decremented too far (%d)!\n",
+ refcnt, refcnt->count );
+ /* Avoid multiple calls to free(), which typically
+ * result in memory corruption that is very hard to
+ * track down.
+ */
+ return;
+ }
+
+ if ( refcnt->free ) {
+ DBGC ( refcnt, "REFCNT %p being freed via method %p\n",
+ refcnt, refcnt->free );
+ refcnt->free ( refcnt );
+ } else {
+ DBGC ( refcnt, "REFCNT %p being freed\n", refcnt );
+ free ( refcnt );
+ }
+}
+
+/**
+ * Do not free reference-counted object
+ *
+ * @v refcnt Reference counter
+ *
+ * This is meant for initializing a reference counter structure in a
+ * statically allocated object.
+ */
+void ref_no_free ( struct refcnt *refcnt __unused ) {
+ /* Do nothing */
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/resolv.c b/src/VBox/Devices/PC/ipxe/src/core/resolv.c
new file mode 100644
index 00000000..31e80aab
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/resolv.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/in.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/process.h>
+#include <ipxe/resolv.h>
+
+/** @file
+ *
+ * Name resolution
+ *
+ */
+
+/***************************************************************************
+ *
+ * Name resolution interfaces
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Name resolved
+ *
+ * @v intf Object interface
+ * @v sa Completed socket address (if successful)
+ */
+void resolv_done ( struct interface *intf, struct sockaddr *sa ) {
+ struct interface *dest;
+ resolv_done_TYPE ( void * ) *op =
+ intf_get_dest_op ( intf, resolv_done, &dest );
+ void *object = intf_object ( dest );
+
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " resolv_done\n",
+ INTF_INTF_DBG ( intf, dest ) );
+
+ if ( op ) {
+ op ( object, sa );
+ } else {
+ /* Default is to ignore resolutions */
+ }
+
+ intf_put ( dest );
+}
+
+/***************************************************************************
+ *
+ * Numeric name resolver
+ *
+ ***************************************************************************
+ */
+
+/** A numeric name resolver */
+struct numeric_resolv {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Name resolution interface */
+ struct interface resolv;
+ /** Process */
+ struct process process;
+ /** Completed socket address */
+ struct sockaddr sa;
+ /** Overall status code */
+ int rc;
+};
+
+static void numeric_step ( struct numeric_resolv *numeric ) {
+
+ if ( numeric->rc == 0 )
+ resolv_done ( &numeric->resolv, &numeric->sa );
+ intf_shutdown ( &numeric->resolv, numeric->rc );
+}
+
+static struct process_descriptor numeric_process_desc =
+ PROC_DESC_ONCE ( struct numeric_resolv, process, numeric_step );
+
+static int numeric_resolv ( struct interface *resolv,
+ const char *name, struct sockaddr *sa ) {
+ struct numeric_resolv *numeric;
+ struct sockaddr_in *sin;
+
+ /* Allocate and initialise structure */
+ numeric = zalloc ( sizeof ( *numeric ) );
+ if ( ! numeric )
+ return -ENOMEM;
+ ref_init ( &numeric->refcnt, NULL );
+ intf_init ( &numeric->resolv, &null_intf_desc, &numeric->refcnt );
+ process_init ( &numeric->process, &numeric_process_desc,
+ &numeric->refcnt );
+ memcpy ( &numeric->sa, sa, sizeof ( numeric->sa ) );
+
+ DBGC ( numeric, "NUMERIC %p attempting to resolve \"%s\"\n",
+ numeric, name );
+
+ /* Attempt to resolve name */
+ sin = ( ( struct sockaddr_in * ) &numeric->sa );
+ if ( inet_aton ( name, &sin->sin_addr ) != 0 ) {
+ sin->sin_family = AF_INET;
+ } else {
+ numeric->rc = -EINVAL;
+ }
+
+ /* Attach to parent interface, mortalise self, and return */
+ intf_plug_plug ( &numeric->resolv, resolv );
+ ref_put ( &numeric->refcnt );
+ return 0;
+}
+
+struct resolver numeric_resolver __resolver ( RESOLV_NUMERIC ) = {
+ .name = "NUMERIC",
+ .resolv = numeric_resolv,
+};
+
+/***************************************************************************
+ *
+ * Name resolution multiplexer
+ *
+ ***************************************************************************
+ */
+
+/** A name resolution multiplexer */
+struct resolv_mux {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Parent name resolution interface */
+ struct interface parent;
+
+ /** Child name resolution interface */
+ struct interface child;
+ /** Current child resolver */
+ struct resolver *resolver;
+
+ /** Socket address to complete */
+ struct sockaddr sa;
+ /** Name to be resolved
+ *
+ * Must be at end of structure
+ */
+ char name[0];
+};
+
+/**
+ * Try current child name resolver
+ *
+ * @v mux Name resolution multiplexer
+ * @ret rc Return status code
+ */
+static int resmux_try ( struct resolv_mux *mux ) {
+ struct resolver *resolver = mux->resolver;
+ int rc;
+
+ DBGC ( mux, "RESOLV %p trying method %s\n", mux, resolver->name );
+
+ if ( ( rc = resolver->resolv ( &mux->child, mux->name,
+ &mux->sa ) ) != 0 ) {
+ DBGC ( mux, "RESOLV %p could not use method %s: %s\n",
+ mux, resolver->name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Child resolved name
+ *
+ * @v mux Name resolution multiplexer
+ * @v sa Completed socket address
+ */
+static void resmux_child_resolv_done ( struct resolv_mux *mux,
+ struct sockaddr *sa ) {
+
+ DBGC ( mux, "RESOLV %p resolved \"%s\" using method %s\n",
+ mux, mux->name, mux->resolver->name );
+
+ /* Pass resolution to parent */
+ resolv_done ( &mux->parent, sa );
+}
+
+/**
+ * Child finished resolution
+ *
+ * @v mux Name resolution multiplexer
+ * @v rc Return status code
+ */
+static void resmux_child_close ( struct resolv_mux *mux, int rc ) {
+
+ /* Restart child interface */
+ intf_restart ( &mux->child, rc );
+
+ /* If this resolution succeeded, stop now */
+ if ( rc == 0 ) {
+ DBGC ( mux, "RESOLV %p succeeded using method %s\n",
+ mux, mux->resolver->name );
+ goto finished;
+ }
+
+ /* Attempt next child resolver, if possible */
+ mux->resolver++;
+ if ( mux->resolver >= table_end ( RESOLVERS ) ) {
+ DBGC ( mux, "RESOLV %p failed to resolve name\n", mux );
+ goto finished;
+ }
+ if ( ( rc = resmux_try ( mux ) ) != 0 )
+ goto finished;
+
+ /* Next resolver is now running */
+ return;
+
+ finished:
+ intf_shutdown ( &mux->parent, rc );
+}
+
+/** Name resolution multiplexer child interface operations */
+static struct interface_operation resmux_child_op[] = {
+ INTF_OP ( resolv_done, struct resolv_mux *, resmux_child_resolv_done ),
+ INTF_OP ( intf_close, struct resolv_mux *, resmux_child_close ),
+};
+
+/** Name resolution multiplexer child interface descriptor */
+static struct interface_descriptor resmux_child_desc =
+ INTF_DESC ( struct resolv_mux, child, resmux_child_op );
+
+/**
+ * Start name resolution
+ *
+ * @v resolv Name resolution interface
+ * @v name Name to resolve
+ * @v sa Socket address to complete
+ * @ret rc Return status code
+ */
+int resolv ( struct interface *resolv, const char *name,
+ struct sockaddr *sa ) {
+ struct resolv_mux *mux;
+ size_t name_len = ( strlen ( name ) + 1 );
+ int rc;
+
+ /* Allocate and initialise structure */
+ mux = zalloc ( sizeof ( *mux ) + name_len );
+ if ( ! mux )
+ return -ENOMEM;
+ ref_init ( &mux->refcnt, NULL );
+ intf_init ( &mux->parent, &null_intf_desc, &mux->refcnt );
+ intf_init ( &mux->child, &resmux_child_desc, &mux->refcnt );
+ mux->resolver = table_start ( RESOLVERS );
+ if ( sa )
+ memcpy ( &mux->sa, sa, sizeof ( mux->sa ) );
+ memcpy ( mux->name, name, name_len );
+
+ DBGC ( mux, "RESOLV %p attempting to resolve \"%s\"\n", mux, name );
+
+ /* Start first resolver in chain. There will always be at
+ * least one resolver (the numeric resolver), so no need to
+ * check for the zero-resolvers-available case.
+ */
+ if ( ( rc = resmux_try ( mux ) ) != 0 )
+ goto err;
+
+ /* Attach parent interface, mortalise self, and return */
+ intf_plug_plug ( &mux->parent, resolv );
+ ref_put ( &mux->refcnt );
+ return 0;
+
+ err:
+ ref_put ( &mux->refcnt );
+ return rc;
+}
+
+/***************************************************************************
+ *
+ * Named socket opening
+ *
+ ***************************************************************************
+ */
+
+/** A named socket */
+struct named_socket {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Data transfer interface */
+ struct interface xfer;
+ /** Name resolution interface */
+ struct interface resolv;
+ /** Communication semantics (e.g. SOCK_STREAM) */
+ int semantics;
+ /** Stored local socket address, if applicable */
+ struct sockaddr local;
+ /** Stored local socket address exists */
+ int have_local;
+};
+
+/**
+ * Terminate named socket opener
+ *
+ * @v named Named socket
+ * @v rc Reason for termination
+ */
+static void named_close ( struct named_socket *named, int rc ) {
+ /* Shut down interfaces */
+ intf_shutdown ( &named->resolv, rc );
+ intf_shutdown ( &named->xfer, rc );
+}
+
+/**
+ * Check flow control window
+ *
+ * @v named Named socket
+ * @ret len Length of window
+ */
+static size_t named_window ( struct named_socket *named __unused ) {
+ /* Not ready for data until we have redirected away */
+ return 0;
+}
+
+/** Named socket opener data transfer interface operations */
+static struct interface_operation named_xfer_ops[] = {
+ INTF_OP ( xfer_window, struct named_socket *, named_window ),
+ INTF_OP ( intf_close, struct named_socket *, named_close ),
+};
+
+/** Named socket opener data transfer interface descriptor */
+static struct interface_descriptor named_xfer_desc =
+ INTF_DESC ( struct named_socket, xfer, named_xfer_ops );
+
+/**
+ * Name resolved
+ *
+ * @v named Named socket
+ * @v sa Completed socket address
+ */
+static void named_resolv_done ( struct named_socket *named,
+ struct sockaddr *sa ) {
+ int rc;
+
+ /* Nullify data transfer interface */
+ intf_nullify ( &named->xfer );
+
+ /* Redirect data-xfer interface */
+ if ( ( rc = xfer_redirect ( &named->xfer, LOCATION_SOCKET,
+ named->semantics, sa,
+ ( named->have_local ?
+ &named->local : NULL ) ) ) != 0 ) {
+ /* Redirection failed - do not unplug data-xfer interface */
+ DBGC ( named, "NAMED %p could not redirect: %s\n",
+ named, strerror ( rc ) );
+ } else {
+ /* Redirection succeeded - unplug data-xfer interface */
+ DBGC ( named, "NAMED %p redirected successfully\n", named );
+ intf_unplug ( &named->xfer );
+ }
+
+ /* Terminate named socket opener */
+ named_close ( named, rc );
+}
+
+/** Named socket opener resolver interface operations */
+static struct interface_operation named_resolv_op[] = {
+ INTF_OP ( intf_close, struct named_socket *, named_close ),
+ INTF_OP ( resolv_done, struct named_socket *, named_resolv_done ),
+};
+
+/** Named socket opener resolver interface descriptor */
+static struct interface_descriptor named_resolv_desc =
+ INTF_DESC ( struct named_socket, resolv, named_resolv_op );
+
+/**
+ * Open named socket
+ *
+ * @v semantics Communication semantics (e.g. SOCK_STREAM)
+ * @v peer Peer socket address to complete
+ * @v name Name to resolve
+ * @v local Local socket address, or NULL
+ * @ret rc Return status code
+ */
+int xfer_open_named_socket ( struct interface *xfer, int semantics,
+ struct sockaddr *peer, const char *name,
+ struct sockaddr *local ) {
+ struct named_socket *named;
+ int rc;
+
+ /* Allocate and initialise structure */
+ named = zalloc ( sizeof ( *named ) );
+ if ( ! named )
+ return -ENOMEM;
+ ref_init ( &named->refcnt, NULL );
+ intf_init ( &named->xfer, &named_xfer_desc, &named->refcnt );
+ intf_init ( &named->resolv, &named_resolv_desc, &named->refcnt );
+ named->semantics = semantics;
+ if ( local ) {
+ memcpy ( &named->local, local, sizeof ( named->local ) );
+ named->have_local = 1;
+ }
+
+ DBGC ( named, "NAMED %p opening \"%s\"\n",
+ named, name );
+
+ /* Start name resolution */
+ if ( ( rc = resolv ( &named->resolv, name, peer ) ) != 0 )
+ goto err;
+
+ /* Attach parent interface, mortalise self, and return */
+ intf_plug_plug ( &named->xfer, xfer );
+ ref_put ( &named->refcnt );
+ return 0;
+
+ err:
+ ref_put ( &named->refcnt );
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/serial.c b/src/VBox/Devices/PC/ipxe/src/core/serial.c
new file mode 100644
index 00000000..a5551b13
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/serial.c
@@ -0,0 +1,254 @@
+/*
+ * The serial port interface routines implement a simple polled i/o
+ * interface to a standard serial port. Due to the space restrictions
+ * for the boot blocks, no BIOS support is used (since BIOS requires
+ * expensive real/protected mode switches), instead the rudimentary
+ * BIOS support is duplicated here.
+ *
+ * The base address and speed for the i/o port are passed from the
+ * Makefile in the COMCONSOLE and CONSPEED preprocessor macros. The
+ * line control parameters are currently hard-coded to 8 bits, no
+ * parity, 1 stop bit (8N1). This can be changed in init_serial().
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "stddef.h"
+#include <ipxe/init.h>
+#include <ipxe/io.h>
+#include <unistd.h>
+#include <ipxe/serial.h>
+#include "config/serial.h"
+
+/* Set default values if none specified */
+
+#ifndef COMCONSOLE
+#define COMCONSOLE 0x3f8
+#endif
+
+#ifndef COMSPEED
+#define COMSPEED 9600
+#endif
+
+#ifndef COMDATA
+#define COMDATA 8
+#endif
+
+#ifndef COMPARITY
+#define COMPARITY 0
+#endif
+
+#ifndef COMSTOP
+#define COMSTOP 1
+#endif
+
+#undef UART_BASE
+#define UART_BASE ( COMCONSOLE )
+
+#undef UART_BAUD
+#define UART_BAUD ( COMSPEED )
+
+#if ((115200%UART_BAUD) != 0)
+#error Bad ttys0 baud rate
+#endif
+
+#define COMBRD (115200/UART_BAUD)
+
+/* Line Control Settings */
+#define UART_LCS ( ( ( (COMDATA) - 5 ) << 0 ) | \
+ ( ( (COMPARITY) ) << 3 ) | \
+ ( ( (COMSTOP) - 1 ) << 2 ) )
+
+/* Data */
+#define UART_RBR 0x00
+#define UART_TBR 0x00
+
+/* Control */
+#define UART_IER 0x01
+#define UART_IIR 0x02
+#define UART_FCR 0x02
+#define UART_LCR 0x03
+#define UART_MCR 0x04
+#define UART_DLL 0x00
+#define UART_DLM 0x01
+
+/* Status */
+#define UART_LSR 0x05
+#define UART_LSR_TEMPT 0x40 /* Transmitter empty */
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
+#define UART_LSR_BI 0x10 /* Break interrupt indicator */
+#define UART_LSR_FE 0x08 /* Frame error indicator */
+#define UART_LSR_PE 0x04 /* Parity error indicator */
+#define UART_LSR_OE 0x02 /* Overrun error indicator */
+#define UART_LSR_DR 0x01 /* Receiver data ready */
+
+#define UART_MSR 0x06
+#define UART_SCR 0x07
+
+#if defined(UART_MEM)
+#define uart_readb(addr) readb((addr))
+#define uart_writeb(val,addr) writeb((val),(addr))
+#else
+#define uart_readb(addr) inb((addr))
+#define uart_writeb(val,addr) outb((val),(addr))
+#endif
+
+/*
+ * void serial_putc(int ch);
+ * Write character `ch' to port UART_BASE.
+ */
+void serial_putc ( int ch ) {
+ int i;
+ int status;
+ i = 1000; /* timeout */
+ while(--i > 0) {
+ status = uart_readb(UART_BASE + UART_LSR);
+ if (status & UART_LSR_THRE) {
+ /* TX buffer emtpy */
+ uart_writeb(ch, UART_BASE + UART_TBR);
+ break;
+ }
+ mdelay(2);
+ }
+}
+
+/*
+ * int serial_getc(void);
+ * Read a character from port UART_BASE.
+ */
+int serial_getc ( void ) {
+ int status;
+ int ch;
+ do {
+ status = uart_readb(UART_BASE + UART_LSR);
+ } while((status & 1) == 0);
+ ch = uart_readb(UART_BASE + UART_RBR); /* fetch (first) character */
+ ch &= 0x7f; /* remove any parity bits we get */
+ if (ch == 0x7f) { /* Make DEL... look like BS */
+ ch = 0x08;
+ }
+ return ch;
+}
+
+/*
+ * int serial_ischar(void);
+ * If there is a character in the input buffer of port UART_BASE,
+ * return nonzero; otherwise return 0.
+ */
+int serial_ischar ( void ) {
+ int status;
+ status = uart_readb(UART_BASE + UART_LSR); /* line status reg; */
+ return status & 1; /* rx char available */
+}
+
+/*
+ * int serial_init(void);
+ * Initialize port UART_BASE to speed COMSPEED, line settings 8N1.
+ */
+static void serial_init ( void ) {
+ int status;
+ int divisor, lcs;
+
+ DBG ( "Serial port %#x initialising\n", UART_BASE );
+
+ divisor = COMBRD;
+ lcs = UART_LCS;
+
+
+#ifdef COMPRESERVE
+ lcs = uart_readb(UART_BASE + UART_LCR) & 0x7f;
+ uart_writeb(0x80 | lcs, UART_BASE + UART_LCR);
+ divisor = (uart_readb(UART_BASE + UART_DLM) << 8) | uart_readb(UART_BASE + UART_DLL);
+ uart_writeb(lcs, UART_BASE + UART_LCR);
+#endif
+
+ /* Set Baud Rate Divisor to COMSPEED, and test to see if the
+ * serial port appears to be present.
+ */
+ uart_writeb(0x80 | lcs, UART_BASE + UART_LCR);
+ uart_writeb(0xaa, UART_BASE + UART_DLL);
+ if (uart_readb(UART_BASE + UART_DLL) != 0xaa) {
+ DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE );
+ goto out;
+ }
+ uart_writeb(0x55, UART_BASE + UART_DLL);
+ if (uart_readb(UART_BASE + UART_DLL) != 0x55) {
+ DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE );
+ goto out;
+ }
+ uart_writeb(divisor & 0xff, UART_BASE + UART_DLL);
+ if (uart_readb(UART_BASE + UART_DLL) != (divisor & 0xff)) {
+ DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE );
+ goto out;
+ }
+ uart_writeb(0xaa, UART_BASE + UART_DLM);
+ if (uart_readb(UART_BASE + UART_DLM) != 0xaa) {
+ DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE );
+ goto out;
+ }
+ uart_writeb(0x55, UART_BASE + UART_DLM);
+ if (uart_readb(UART_BASE + UART_DLM) != 0x55) {
+ DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE );
+ goto out;
+ }
+ uart_writeb((divisor >> 8) & 0xff, UART_BASE + UART_DLM);
+ if (uart_readb(UART_BASE + UART_DLM) != ((divisor >> 8) & 0xff)) {
+ DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE );
+ goto out;
+ }
+ uart_writeb(lcs, UART_BASE + UART_LCR);
+
+ /* disable interrupts */
+ uart_writeb(0x0, UART_BASE + UART_IER);
+
+ /* disable fifo's */
+ uart_writeb(0x00, UART_BASE + UART_FCR);
+
+ /* Set clear to send, so flow control works... */
+ uart_writeb((1<<1), UART_BASE + UART_MCR);
+
+
+ /* Flush the input buffer. */
+ do {
+ /* rx buffer reg
+ * throw away (unconditionally the first time)
+ */
+ (void) uart_readb(UART_BASE + UART_RBR);
+ /* line status reg */
+ status = uart_readb(UART_BASE + UART_LSR);
+ } while(status & UART_LSR_DR);
+ out:
+ return;
+}
+
+/*
+ * void serial_fini(void);
+ * Cleanup our use of the serial port, in particular flush the
+ * output buffer so we don't accidentially lose characters.
+ */
+static void serial_fini ( int flags __unused ) {
+ int i, status;
+ /* Flush the output buffer to avoid dropping characters,
+ * if we are reinitializing the serial port.
+ */
+ i = 10000; /* timeout */
+ do {
+ status = uart_readb(UART_BASE + UART_LSR);
+ } while((--i > 0) && !(status & UART_LSR_TEMPT));
+ /* Don't mark it as disabled; it's still usable */
+}
+
+/**
+ * Serial driver initialisation function
+ *
+ * Initialise serial port early on so that it is available to capture
+ * early debug messages.
+ */
+struct init_fn serial_init_fn __init_fn ( INIT_SERIAL ) = {
+ .initialise = serial_init,
+};
+
+/** Serial driver startup function */
+struct startup_fn serial_startup_fn __startup_fn ( STARTUP_EARLY ) = {
+ .shutdown = serial_fini,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/core/serial_console.c b/src/VBox/Devices/PC/ipxe/src/core/serial_console.c
new file mode 100644
index 00000000..bbddd6b2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/serial_console.c
@@ -0,0 +1,39 @@
+#include <ipxe/init.h>
+#include <ipxe/serial.h>
+#include <ipxe/console.h>
+#include <config/console.h>
+
+/** @file
+ *
+ * Serial console
+ *
+ */
+
+/* Set default console usage if applicable */
+#if ! ( defined ( CONSOLE_SERIAL ) && CONSOLE_EXPLICIT ( CONSOLE_SERIAL ) )
+#undef CONSOLE_SERIAL
+#define CONSOLE_SERIAL ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
+#endif
+
+struct console_driver serial_console __console_driver;
+
+static void serial_console_init ( void ) {
+ /* Serial driver initialization should already be done,
+ * time to enable the serial console. */
+ serial_console.disabled = 0;
+}
+
+struct console_driver serial_console __console_driver = {
+ .putchar = serial_putc,
+ .getchar = serial_getc,
+ .iskey = serial_ischar,
+ .disabled = 1,
+ .usage = CONSOLE_SERIAL,
+};
+
+/**
+ * Serial console initialisation function
+ */
+struct init_fn serial_console_init_fn __init_fn ( INIT_CONSOLE ) = {
+ .initialise = serial_console_init,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/core/settings.c b/src/VBox/Devices/PC/ipxe/src/core/settings.c
new file mode 100644
index 00000000..c84e1bc2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/settings.c
@@ -0,0 +1,1887 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/in.h>
+#include <ipxe/vsprintf.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/uuid.h>
+#include <ipxe/uri.h>
+#include <ipxe/settings.h>
+
+/** @file
+ *
+ * Configuration settings
+ *
+ */
+
+/******************************************************************************
+ *
+ * Generic settings blocks
+ *
+ ******************************************************************************
+ */
+
+/**
+ * A generic setting
+ *
+ */
+struct generic_setting {
+ /** List of generic settings */
+ struct list_head list;
+ /** Setting */
+ struct setting setting;
+ /** Size of setting name */
+ size_t name_len;
+ /** Size of setting data */
+ size_t data_len;
+};
+
+/**
+ * Get generic setting name
+ *
+ * @v generic Generic setting
+ * @ret name Generic setting name
+ */
+static inline void * generic_setting_name ( struct generic_setting *generic ) {
+ return ( ( ( void * ) generic ) + sizeof ( *generic ) );
+}
+
+/**
+ * Get generic setting data
+ *
+ * @v generic Generic setting
+ * @ret data Generic setting data
+ */
+static inline void * generic_setting_data ( struct generic_setting *generic ) {
+ return ( ( ( void * ) generic ) + sizeof ( *generic ) +
+ generic->name_len );
+}
+
+/**
+ * Find generic setting
+ *
+ * @v generics Generic settings block
+ * @v setting Setting to find
+ * @ret generic Generic setting, or NULL
+ */
+static struct generic_setting *
+find_generic_setting ( struct generic_settings *generics,
+ struct setting *setting ) {
+ struct generic_setting *generic;
+
+ list_for_each_entry ( generic, &generics->list, list ) {
+ if ( setting_cmp ( &generic->setting, setting ) == 0 )
+ return generic;
+ }
+ return NULL;
+}
+
+/**
+ * Store value of generic setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+int generic_settings_store ( struct settings *settings,
+ struct setting *setting,
+ const void *data, size_t len ) {
+ struct generic_settings *generics =
+ container_of ( settings, struct generic_settings, settings );
+ struct generic_setting *old;
+ struct generic_setting *new = NULL;
+ size_t name_len;
+
+ /* Identify existing generic setting, if any */
+ old = find_generic_setting ( generics, setting );
+
+ /* Create new generic setting, if required */
+ if ( len ) {
+ /* Allocate new generic setting */
+ name_len = ( strlen ( setting->name ) + 1 );
+ new = zalloc ( sizeof ( *new ) + name_len + len );
+ if ( ! new )
+ return -ENOMEM;
+
+ /* Populate new generic setting */
+ new->name_len = name_len;
+ new->data_len = len;
+ memcpy ( &new->setting, setting, sizeof ( new->setting ) );
+ new->setting.name = generic_setting_name ( new );
+ memcpy ( generic_setting_name ( new ),
+ setting->name, name_len );
+ memcpy ( generic_setting_data ( new ), data, len );
+ }
+
+ /* Delete existing generic setting, if any */
+ if ( old ) {
+ list_del ( &old->list );
+ free ( old );
+ }
+
+ /* Add new setting to list, if any */
+ if ( new )
+ list_add ( &new->list, &generics->list );
+
+ return 0;
+}
+
+/**
+ * Fetch value of generic setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+int generic_settings_fetch ( struct settings *settings,
+ struct setting *setting,
+ void *data, size_t len ) {
+ struct generic_settings *generics =
+ container_of ( settings, struct generic_settings, settings );
+ struct generic_setting *generic;
+
+ /* Find generic setting */
+ generic = find_generic_setting ( generics, setting );
+ if ( ! generic )
+ return -ENOENT;
+
+ /* Copy out generic setting data */
+ if ( len > generic->data_len )
+ len = generic->data_len;
+ memcpy ( data, generic_setting_data ( generic ), len );
+ return generic->data_len;
+}
+
+/**
+ * Clear generic settings block
+ *
+ * @v settings Settings block
+ */
+void generic_settings_clear ( struct settings *settings ) {
+ struct generic_settings *generics =
+ container_of ( settings, struct generic_settings, settings );
+ struct generic_setting *generic;
+ struct generic_setting *tmp;
+
+ list_for_each_entry_safe ( generic, tmp, &generics->list, list ) {
+ list_del ( &generic->list );
+ free ( generic );
+ }
+ assert ( list_empty ( &generics->list ) );
+}
+
+/** Generic settings operations */
+struct settings_operations generic_settings_operations = {
+ .store = generic_settings_store,
+ .fetch = generic_settings_fetch,
+ .clear = generic_settings_clear,
+};
+
+/******************************************************************************
+ *
+ * Registered settings blocks
+ *
+ ******************************************************************************
+ */
+
+/** Root generic settings block */
+struct generic_settings generic_settings_root = {
+ .settings = {
+ .refcnt = NULL,
+ .name = "",
+ .siblings =
+ LIST_HEAD_INIT ( generic_settings_root.settings.siblings ),
+ .children =
+ LIST_HEAD_INIT ( generic_settings_root.settings.children ),
+ .op = &generic_settings_operations,
+ },
+ .list = LIST_HEAD_INIT ( generic_settings_root.list ),
+};
+
+/** Root settings block */
+#define settings_root generic_settings_root.settings
+
+/** Autovivified settings block */
+struct autovivified_settings {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Generic settings block */
+ struct generic_settings generic;
+};
+
+/**
+ * Free autovivified settings block
+ *
+ * @v refcnt Reference count
+ */
+static void autovivified_settings_free ( struct refcnt *refcnt ) {
+ struct autovivified_settings *autovivified =
+ container_of ( refcnt, struct autovivified_settings, refcnt );
+
+ generic_settings_clear ( &autovivified->generic.settings );
+ free ( autovivified );
+}
+
+/**
+ * Find child named settings block
+ *
+ * @v parent Parent settings block
+ * @v name Name within this parent
+ * @ret settings Settings block, or NULL
+ */
+static struct settings * find_child_settings ( struct settings *parent,
+ const char *name ) {
+ struct settings *settings;
+
+ /* Treat empty name as meaning "this block" */
+ if ( ! *name )
+ return parent;
+
+ /* Look for child with matching name */
+ list_for_each_entry ( settings, &parent->children, siblings ) {
+ if ( strcmp ( settings->name, name ) == 0 )
+ return settings;
+ }
+
+ return NULL;
+}
+
+/**
+ * Find or create child named settings block
+ *
+ * @v parent Parent settings block
+ * @v name Name within this parent
+ * @ret settings Settings block, or NULL
+ */
+static struct settings * autovivify_child_settings ( struct settings *parent,
+ const char *name ) {
+ struct {
+ struct autovivified_settings autovivified;
+ char name[ strlen ( name ) + 1 /* NUL */ ];
+ } *new_child;
+ struct settings *settings;
+
+ /* Return existing settings, if existent */
+ if ( ( settings = find_child_settings ( parent, name ) ) != NULL )
+ return settings;
+
+ /* Create new generic settings block */
+ new_child = zalloc ( sizeof ( *new_child ) );
+ if ( ! new_child ) {
+ DBGC ( parent, "Settings %p could not create child %s\n",
+ parent, name );
+ return NULL;
+ }
+ memcpy ( new_child->name, name, sizeof ( new_child->name ) );
+ ref_init ( &new_child->autovivified.refcnt,
+ autovivified_settings_free );
+ generic_settings_init ( &new_child->autovivified.generic,
+ &new_child->autovivified.refcnt );
+ settings = &new_child->autovivified.generic.settings;
+ register_settings ( settings, parent, new_child->name );
+ return settings;
+}
+
+/**
+ * Return settings block name
+ *
+ * @v settings Settings block
+ * @ret name Settings block name
+ */
+const char * settings_name ( struct settings *settings ) {
+ static char buf[16];
+ char tmp[ sizeof ( buf ) ];
+
+ for ( buf[2] = buf[0] = 0 ; settings ; settings = settings->parent ) {
+ memcpy ( tmp, buf, sizeof ( tmp ) );
+ snprintf ( buf, sizeof ( buf ), ".%s%s", settings->name, tmp );
+ }
+ return ( buf + 2 );
+}
+
+/**
+ * Parse settings block name
+ *
+ * @v name Name
+ * @v get_child Function to find or create child settings block
+ * @ret settings Settings block, or NULL
+ */
+static struct settings *
+parse_settings_name ( const char *name,
+ struct settings * ( * get_child ) ( struct settings *,
+ const char * ) ) {
+ struct settings *settings = &settings_root;
+ char name_copy[ strlen ( name ) + 1 ];
+ char *subname;
+ char *remainder;
+
+ /* Create modifiable copy of name */
+ memcpy ( name_copy, name, sizeof ( name_copy ) );
+ remainder = name_copy;
+
+ /* Parse each name component in turn */
+ while ( remainder ) {
+ struct net_device *netdev;
+
+ subname = remainder;
+ remainder = strchr ( subname, '.' );
+ if ( remainder )
+ *(remainder++) = '\0';
+
+ /* Special case "netX" root settings block */
+ if ( ( subname == name_copy ) && ! strcmp ( subname, "netX" ) &&
+ ( ( netdev = last_opened_netdev() ) != NULL ) )
+ settings = get_child ( settings, netdev->name );
+ else
+ settings = get_child ( settings, subname );
+
+ if ( ! settings )
+ break;
+ }
+
+ return settings;
+}
+
+/**
+ * Find named settings block
+ *
+ * @v name Name
+ * @ret settings Settings block, or NULL
+ */
+struct settings * find_settings ( const char *name ) {
+
+ return parse_settings_name ( name, find_child_settings );
+}
+
+/**
+ * Apply all settings
+ *
+ * @ret rc Return status code
+ */
+static int apply_settings ( void ) {
+ struct settings_applicator *applicator;
+ int rc;
+
+ /* Call all settings applicators */
+ for_each_table_entry ( applicator, SETTINGS_APPLICATORS ) {
+ if ( ( rc = applicator->apply() ) != 0 ) {
+ DBG ( "Could not apply settings using applicator "
+ "%p: %s\n", applicator, strerror ( rc ) );
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Reprioritise settings
+ *
+ * @v settings Settings block
+ *
+ * Reorders the settings block amongst its siblings according to its
+ * priority.
+ */
+static void reprioritise_settings ( struct settings *settings ) {
+ struct settings *parent = settings->parent;
+ long priority;
+ struct settings *tmp;
+ long tmp_priority;
+
+ /* Stop when we reach the top of the tree */
+ if ( ! parent )
+ return;
+
+ /* Read priority, if present */
+ priority = fetch_intz_setting ( settings, &priority_setting );
+
+ /* Remove from siblings list */
+ list_del ( &settings->siblings );
+
+ /* Reinsert after any existing blocks which have a higher priority */
+ list_for_each_entry ( tmp, &parent->children, siblings ) {
+ tmp_priority = fetch_intz_setting ( tmp, &priority_setting );
+ if ( priority > tmp_priority )
+ break;
+ }
+ list_add_tail ( &settings->siblings, &tmp->siblings );
+
+ /* Recurse up the tree */
+ reprioritise_settings ( parent );
+}
+
+/**
+ * Register settings block
+ *
+ * @v settings Settings block
+ * @v parent Parent settings block, or NULL
+ * @v name Settings block name
+ * @ret rc Return status code
+ */
+int register_settings ( struct settings *settings, struct settings *parent,
+ const char *name ) {
+ struct settings *old_settings;
+
+ /* NULL parent => add to settings root */
+ assert ( settings != NULL );
+ if ( parent == NULL )
+ parent = &settings_root;
+
+ /* Apply settings block name */
+ settings->name = name;
+
+ /* Remove any existing settings with the same name */
+ if ( ( old_settings = find_child_settings ( parent, settings->name ) ))
+ unregister_settings ( old_settings );
+
+ /* Add to list of settings */
+ ref_get ( settings->refcnt );
+ ref_get ( parent->refcnt );
+ settings->parent = parent;
+ list_add_tail ( &settings->siblings, &parent->children );
+ DBGC ( settings, "Settings %p (\"%s\") registered\n",
+ settings, settings_name ( settings ) );
+
+ /* Fix up settings priority */
+ reprioritise_settings ( settings );
+
+ /* Apply potentially-updated settings */
+ apply_settings();
+
+ return 0;
+}
+
+/**
+ * Unregister settings block
+ *
+ * @v settings Settings block
+ */
+void unregister_settings ( struct settings *settings ) {
+ struct settings *child;
+ struct settings *tmp;
+
+ /* Unregister child settings */
+ list_for_each_entry_safe ( child, tmp, &settings->children, siblings ) {
+ unregister_settings ( child );
+ }
+
+ DBGC ( settings, "Settings %p (\"%s\") unregistered\n",
+ settings, settings_name ( settings ) );
+
+ /* Remove from list of settings */
+ ref_put ( settings->parent->refcnt );
+ settings->parent = NULL;
+ list_del ( &settings->siblings );
+ ref_put ( settings->refcnt );
+
+ /* Apply potentially-updated settings */
+ apply_settings();
+}
+
+/******************************************************************************
+ *
+ * Core settings routines
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Check applicability of setting
+ *
+ * @v settings Settings block
+ * @v setting Setting
+ * @ret applies Setting applies within this settings block
+ */
+int setting_applies ( struct settings *settings, struct setting *setting ) {
+
+ return ( settings->op->applies ?
+ settings->op->applies ( settings, setting ) : 1 );
+}
+
+/**
+ * Store value of setting
+ *
+ * @v settings Settings block, or NULL
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+int store_setting ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len ) {
+ int rc;
+
+ /* NULL settings implies storing into the global settings root */
+ if ( ! settings )
+ settings = &settings_root;
+
+ /* Fail if tag does not apply to this settings block */
+ if ( ! setting_applies ( settings, setting ) )
+ return -ENOTTY;
+
+ /* Sanity check */
+ if ( ! settings->op->store )
+ return -ENOTSUP;
+
+ /* Store setting */
+ if ( ( rc = settings->op->store ( settings, setting,
+ data, len ) ) != 0 )
+ return rc;
+
+ /* Reprioritise settings if necessary */
+ if ( setting_cmp ( setting, &priority_setting ) == 0 )
+ reprioritise_settings ( settings );
+
+ /* If these settings are registered, apply potentially-updated
+ * settings
+ */
+ for ( ; settings ; settings = settings->parent ) {
+ if ( settings == &settings_root ) {
+ if ( ( rc = apply_settings() ) != 0 )
+ return rc;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Fetch value and origin of setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v origin Origin of setting to fill in
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ *
+ * The actual length of the setting will be returned even if
+ * the buffer was too small.
+ */
+static int fetch_setting_and_origin ( struct settings *settings,
+ struct setting *setting,
+ struct settings **origin,
+ void *data, size_t len ) {
+ struct settings *child;
+ int ret;
+
+ /* Avoid returning uninitialised data on error */
+ memset ( data, 0, len );
+ if ( origin )
+ *origin = NULL;
+
+ /* NULL settings implies starting at the global settings root */
+ if ( ! settings )
+ settings = &settings_root;
+
+ /* Sanity check */
+ if ( ! settings->op->fetch )
+ return -ENOTSUP;
+
+ /* Try this block first, if applicable */
+ if ( setting_applies ( settings, setting ) &&
+ ( ( ret = settings->op->fetch ( settings, setting,
+ data, len ) ) >= 0 ) ) {
+ if ( origin )
+ *origin = settings;
+ return ret;
+ }
+
+ /* Recurse into each child block in turn */
+ list_for_each_entry ( child, &settings->children, siblings ) {
+ if ( ( ret = fetch_setting_and_origin ( child, setting, origin,
+ data, len ) ) >= 0 )
+ return ret;
+ }
+
+ return -ENOENT;
+}
+
+/**
+ * Fetch value of setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ *
+ * The actual length of the setting will be returned even if
+ * the buffer was too small.
+ */
+int fetch_setting ( struct settings *settings, struct setting *setting,
+ void *data, size_t len ) {
+ return fetch_setting_and_origin ( settings, setting, NULL, data, len );
+}
+
+/**
+ * Fetch origin of setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @ret origin Origin of setting, or NULL if not found
+ *
+ * This function can also be used as an existence check for the
+ * setting.
+ */
+struct settings * fetch_setting_origin ( struct settings *settings,
+ struct setting *setting ) {
+ struct settings *origin;
+
+ fetch_setting_and_origin ( settings, setting, &origin, NULL, 0 );
+ return origin;
+}
+
+/**
+ * Fetch length of setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @ret len Length of setting data, or negative error
+ *
+ * This function can also be used as an existence check for the
+ * setting.
+ */
+int fetch_setting_len ( struct settings *settings, struct setting *setting ) {
+ return fetch_setting ( settings, setting, NULL, 0 );
+}
+
+/**
+ * Fetch copy of setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v data Buffer to allocate and fill with setting data
+ * @ret len Length of setting, or negative error
+ *
+ * The caller is responsible for eventually freeing the allocated
+ * buffer.
+ *
+ * To allow the caller to distinguish between a non-existent setting
+ * and an error in allocating memory for the copy, this function will
+ * return success (and a NULL buffer pointer) for a non-existent
+ * setting.
+ */
+int fetch_setting_copy ( struct settings *settings, struct setting *setting,
+ void **data ) {
+ int len;
+ int check_len = 0;
+
+ /* Avoid returning uninitialised data on error */
+ *data = NULL;
+
+ /* Fetch setting length, and return success if non-existent */
+ len = fetch_setting_len ( settings, setting );
+ if ( len < 0 )
+ return 0;
+
+ /* Allocate buffer */
+ *data = malloc ( len );
+ if ( ! *data )
+ return -ENOMEM;
+
+ /* Fetch setting */
+ check_len = fetch_setting ( settings, setting, *data, len );
+ assert ( check_len == len );
+ return len;
+}
+
+/**
+ * Fetch value of string setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting string data
+ * @v len Length of buffer
+ * @ret len Length of string setting, or negative error
+ *
+ * The resulting string is guaranteed to be correctly NUL-terminated.
+ * The returned length will be the length of the underlying setting
+ * data.
+ */
+int fetch_string_setting ( struct settings *settings, struct setting *setting,
+ char *data, size_t len ) {
+ memset ( data, 0, len );
+ return fetch_setting ( settings, setting, data,
+ ( ( len > 0 ) ? ( len - 1 ) : 0 ) );
+}
+
+/**
+ * Fetch value of string setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v data Buffer to allocate and fill with setting string data
+ * @ret len Length of string setting, or negative error
+ *
+ * The resulting string is guaranteed to be correctly NUL-terminated.
+ * The returned length will be the length of the underlying setting
+ * data. The caller is responsible for eventually freeing the
+ * allocated buffer.
+ *
+ * To allow the caller to distinguish between a non-existent setting
+ * and an error in allocating memory for the copy, this function will
+ * return success (and a NULL buffer pointer) for a non-existent
+ * setting.
+ */
+int fetch_string_setting_copy ( struct settings *settings,
+ struct setting *setting,
+ char **data ) {
+ int len;
+ int check_len = 0;
+
+ /* Avoid returning uninitialised data on error */
+ *data = NULL;
+
+ /* Fetch setting length, and return success if non-existent */
+ len = fetch_setting_len ( settings, setting );
+ if ( len < 0 )
+ return 0;
+
+ /* Allocate string buffer */
+ *data = malloc ( len + 1 );
+ if ( ! *data )
+ return -ENOMEM;
+
+ /* Fetch setting */
+ check_len = fetch_string_setting ( settings, setting, *data,
+ ( len + 1 ) );
+ assert ( check_len == len );
+ return len;
+}
+
+/**
+ * Fetch value of IPv4 address setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v inp IPv4 addresses to fill in
+ * @v count Maximum number of IPv4 addresses
+ * @ret len Length of setting, or negative error
+ */
+int fetch_ipv4_array_setting ( struct settings *settings,
+ struct setting *setting,
+ struct in_addr *inp, unsigned int count ) {
+ int len;
+
+ len = fetch_setting ( settings, setting, inp,
+ ( sizeof ( *inp ) * count ) );
+ if ( len < 0 )
+ return len;
+ if ( ( len % sizeof ( *inp ) ) != 0 )
+ return -ERANGE;
+ return len;
+}
+
+/**
+ * Fetch value of IPv4 address setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v inp IPv4 address to fill in
+ * @ret len Length of setting, or negative error
+ */
+int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
+ struct in_addr *inp ) {
+ return fetch_ipv4_array_setting ( settings, setting, inp, 1 );
+}
+
+/**
+ * Extract numeric value of setting
+ *
+ * @v raw Raw setting data
+ * @v len Length of raw setting data
+ * @ret signed_value Value, when interpreted as a signed integer
+ * @ret unsigned_value Value, when interpreted as an unsigned integer
+ * @ret len Length of setting, or negative error
+ */
+static int numeric_setting_value ( const void *raw, size_t len,
+ signed long *signed_value,
+ unsigned long *unsigned_value ) {
+ const uint8_t *unsigned_bytes = raw;
+ const int8_t *signed_bytes = raw;
+ int is_negative;
+ unsigned int i;
+ uint8_t byte;
+
+ /* Range check */
+ if ( len > sizeof ( long ) )
+ return -ERANGE;
+
+ /* Convert to host-ordered longs */
+ is_negative = ( len && ( signed_bytes[0] < 0 ) );
+ *signed_value = ( is_negative ? -1L : 0 );
+ *unsigned_value = 0;
+ for ( i = 0 ; i < len ; i++ ) {
+ byte = unsigned_bytes[i];
+ *signed_value = ( ( *signed_value << 8 ) | byte );
+ *unsigned_value = ( ( *unsigned_value << 8 ) | byte );
+ }
+
+ return len;
+}
+
+/**
+ * Fetch value of signed integer setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v value Integer value to fill in
+ * @ret len Length of setting, or negative error
+ */
+int fetch_int_setting ( struct settings *settings, struct setting *setting,
+ long *value ) {
+ unsigned long dummy;
+ long tmp;
+ int len;
+
+ /* Avoid returning uninitialised data on error */
+ *value = 0;
+
+ /* Fetch raw (network-ordered, variable-length) setting */
+ len = fetch_setting ( settings, setting, &tmp, sizeof ( tmp ) );
+ if ( len < 0 )
+ return len;
+
+ /* Extract numeric value */
+ return numeric_setting_value ( &tmp, len, value, &dummy );
+}
+
+/**
+ * Fetch value of unsigned integer setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v value Integer value to fill in
+ * @ret len Length of setting, or negative error
+ */
+int fetch_uint_setting ( struct settings *settings, struct setting *setting,
+ unsigned long *value ) {
+ signed long dummy;
+ long tmp;
+ int len;
+
+ /* Avoid returning uninitialised data on error */
+ *value = 0;
+
+ /* Fetch raw (network-ordered, variable-length) setting */
+ len = fetch_setting ( settings, setting, &tmp, sizeof ( tmp ) );
+ if ( len < 0 )
+ return len;
+
+ /* Extract numeric value */
+ return numeric_setting_value ( &tmp, len, &dummy, value );
+}
+
+/**
+ * Fetch value of signed integer setting, or zero
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @ret value Setting value, or zero
+ */
+long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
+ long value;
+
+ fetch_int_setting ( settings, setting, &value );
+ return value;
+}
+
+/**
+ * Fetch value of unsigned integer setting, or zero
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @ret value Setting value, or zero
+ */
+unsigned long fetch_uintz_setting ( struct settings *settings,
+ struct setting *setting ) {
+ unsigned long value;
+
+ fetch_uint_setting ( settings, setting, &value );
+ return value;
+}
+
+/**
+ * Fetch value of UUID setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v uuid UUID to fill in
+ * @ret len Length of setting, or negative error
+ */
+int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
+ union uuid *uuid ) {
+ int len;
+
+ len = fetch_setting ( settings, setting, uuid, sizeof ( *uuid ) );
+ if ( len < 0 )
+ return len;
+ if ( len != sizeof ( *uuid ) )
+ return -ERANGE;
+ return len;
+}
+
+/**
+ * Clear settings block
+ *
+ * @v settings Settings block
+ */
+void clear_settings ( struct settings *settings ) {
+ if ( settings->op->clear )
+ settings->op->clear ( settings );
+}
+
+/**
+ * Compare two settings
+ *
+ * @v a Setting to compare
+ * @v b Setting to compare
+ * @ret 0 Settings are the same
+ * @ret non-zero Settings are not the same
+ */
+int setting_cmp ( struct setting *a, struct setting *b ) {
+
+ /* If the settings have tags, compare them */
+ if ( a->tag && ( a->tag == b->tag ) )
+ return 0;
+
+ /* Otherwise, if the settings have names, compare them */
+ if ( a->name && b->name && a->name[0] )
+ return strcmp ( a->name, b->name );
+
+ /* Otherwise, return a non-match */
+ return ( ! 0 );
+}
+
+/******************************************************************************
+ *
+ * Formatted setting routines
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Fetch and format value of setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v type Settings type
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+int fetchf_setting ( struct settings *settings, struct setting *setting,
+ char *buf, size_t len ) {
+ int raw_len;
+ int check_len;
+ int rc;
+
+ /* Fetch raw value */
+ raw_len = fetch_setting_len ( settings, setting );
+ if ( raw_len < 0 ) {
+ rc = raw_len;
+ return rc;
+ } else {
+ uint8_t raw[raw_len];
+
+ /* Fetch raw value */
+ check_len = fetch_setting ( settings, setting, raw,
+ sizeof ( raw ) );
+ if ( check_len < 0 )
+ return check_len;
+ assert ( check_len == raw_len );
+
+ /* Format value */
+ return setting->type->format ( raw, sizeof ( raw ), buf, len );
+ }
+}
+
+/**
+ * Store formatted value of setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v value Formatted setting data, or NULL
+ * @ret rc Return status code
+ */
+int storef_setting ( struct settings *settings, struct setting *setting,
+ const char *value ) {
+ int raw_len;
+ int check_len;
+ int rc;
+
+ /* NULL value implies deletion */
+ if ( ! value )
+ return delete_setting ( settings, setting );
+
+ /* Parse formatted value */
+ raw_len = setting->type->parse ( value, NULL, 0 );
+ if ( raw_len < 0 ) {
+ rc = raw_len;
+ return rc;
+ } else {
+ uint8_t raw[raw_len];
+
+ /* Parse formatted value */
+ check_len = setting->type->parse ( value, raw, sizeof ( raw ) );
+ assert ( check_len == raw_len );
+
+ /* Store raw value */
+ return store_setting ( settings, setting, raw, sizeof ( raw ) );
+ }
+}
+
+/******************************************************************************
+ *
+ * Named settings
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Find named setting
+ *
+ * @v name Name
+ * @ret setting Named setting, or NULL
+ */
+struct setting * find_setting ( const char *name ) {
+ struct setting *setting;
+
+ for_each_table_entry ( setting, SETTINGS ) {
+ if ( strcmp ( name, setting->name ) == 0 )
+ return setting;
+ }
+ return NULL;
+}
+
+/**
+ * Parse setting name as tag number
+ *
+ * @v settings Settings block
+ * @v name Name
+ * @ret tag Tag number, or 0 if not a valid number
+ */
+static unsigned int parse_setting_tag ( struct settings *settings,
+ const char *name ) {
+ char *tmp = ( ( char * ) name );
+ unsigned int tag = 0;
+
+ while ( 1 ) {
+ tag = ( ( tag << 8 ) | strtoul ( tmp, &tmp, 0 ) );
+ if ( *tmp == 0 )
+ return ( tag | settings->tag_magic );
+ if ( *tmp != '.' )
+ return 0;
+ tmp++;
+ }
+}
+
+/**
+ * Find setting type
+ *
+ * @v name Name
+ * @ret type Setting type, or NULL
+ */
+static struct setting_type * find_setting_type ( const char *name ) {
+ struct setting_type *type;
+
+ for_each_table_entry ( type, SETTING_TYPES ) {
+ if ( strcmp ( name, type->name ) == 0 )
+ return type;
+ }
+ return NULL;
+}
+
+/**
+ * Parse setting name
+ *
+ * @v name Name of setting
+ * @v get_child Function to find or create child settings block
+ * @v settings Settings block to fill in
+ * @v setting Setting to fill in
+ * @v tmp_name Buffer for copy of setting name
+ * @ret rc Return status code
+ *
+ * Interprets a name of the form
+ * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
+ * fields.
+ *
+ * The @c tmp_name buffer must be large enough to hold a copy of the
+ * setting name.
+ */
+static int
+parse_setting_name ( const char *name,
+ struct settings * ( * get_child ) ( struct settings *,
+ const char * ),
+ struct settings **settings, struct setting *setting,
+ char *tmp_name ) {
+ char *settings_name;
+ char *setting_name;
+ char *type_name;
+ struct setting *named_setting;
+
+ /* Set defaults */
+ *settings = &settings_root;
+ memset ( setting, 0, sizeof ( *setting ) );
+ setting->name = "";
+ setting->type = &setting_type_string;
+
+ /* Split name into "[settings_name/]setting_name[:type_name]" */
+ strcpy ( tmp_name, name );
+ if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
+ *(setting_name++) = 0;
+ settings_name = tmp_name;
+ } else {
+ setting_name = tmp_name;
+ settings_name = NULL;
+ }
+ if ( ( type_name = strchr ( setting_name, ':' ) ) != NULL )
+ *(type_name++) = 0;
+
+ /* Identify settings block, if specified */
+ if ( settings_name ) {
+ *settings = parse_settings_name ( settings_name, get_child );
+ if ( *settings == NULL ) {
+ DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
+ settings_name, name );
+ return -ENODEV;
+ }
+ }
+
+ /* Identify setting */
+ setting->tag = parse_setting_tag ( *settings, setting_name );
+ setting->name = setting_name;
+ for_each_table_entry ( named_setting, SETTINGS ) {
+ /* Matches a defined named setting; use that setting */
+ if ( setting_cmp ( named_setting, setting ) == 0 ) {
+ memcpy ( setting, named_setting, sizeof ( *setting ) );
+ break;
+ }
+ }
+
+ /* Identify setting type, if specified */
+ if ( type_name ) {
+ setting->type = find_setting_type ( type_name );
+ if ( setting->type == NULL ) {
+ DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
+ type_name, name );
+ return -ENOTSUP;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Return full setting name
+ *
+ * @v settings Settings block, or NULL
+ * @v setting Setting
+ * @v buf Buffer
+ * @v len Length of buffer
+ * @ret len Length of setting name, or negative error
+ */
+int setting_name ( struct settings *settings, struct setting *setting,
+ char *buf, size_t len ) {
+ const char *name;
+
+ if ( ! settings )
+ settings = &settings_root;
+
+ name = settings_name ( settings );
+ return snprintf ( buf, len, "%s%s%s:%s", name, ( name[0] ? "/" : "" ),
+ setting->name, setting->type->name );
+}
+
+/**
+ * Parse and store value of named setting
+ *
+ * @v name Name of setting
+ * @v value Formatted setting data, or NULL
+ * @ret rc Return status code
+ */
+int storef_named_setting ( const char *name, const char *value ) {
+ struct settings *settings;
+ struct setting setting;
+ char tmp_name[ strlen ( name ) + 1 ];
+ int rc;
+
+ /* Parse setting name */
+ if ( ( rc = parse_setting_name ( name, autovivify_child_settings,
+ &settings, &setting, tmp_name )) != 0)
+ return rc;
+
+ /* Store setting */
+ if ( ( rc = storef_setting ( settings, &setting, value ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Fetch and format value of named setting
+ *
+ * @v name Name of setting
+ * @v name_buf Buffer to contain canonicalised name
+ * @v name_len Length of canonicalised name buffer
+ * @v value_buf Buffer to contain formatted value
+ * @v value_len Length of formatted value buffer
+ * @ret len Length of formatted value, or negative error
+ */
+int fetchf_named_setting ( const char *name,
+ char *name_buf, size_t name_len,
+ char *value_buf, size_t value_len ) {
+ struct settings *settings;
+ struct setting setting;
+ struct settings *origin;
+ char tmp_name[ strlen ( name ) + 1 ];
+ int len;
+ int rc;
+
+ /* Parse setting name */
+ if ( ( rc = parse_setting_name ( name, find_child_settings,
+ &settings, &setting, tmp_name )) != 0)
+ return rc;
+
+ /* Fetch setting */
+ if ( ( len = fetchf_setting ( settings, &setting, value_buf,
+ value_len ) ) < 0 )
+ return len;
+
+ /* Construct setting name */
+ origin = fetch_setting_origin ( settings, &setting );
+ assert ( origin != NULL );
+ setting_name ( origin, &setting, name_buf, name_len );
+
+ return len;
+}
+
+/******************************************************************************
+ *
+ * Setting types
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Parse string setting value
+ *
+ * @v value Formatted setting value
+ * @v buf Buffer to contain raw value
+ * @v len Length of buffer
+ * @ret len Length of raw value, or negative error
+ */
+static int parse_string_setting ( const char *value, void *buf, size_t len ) {
+ size_t raw_len = strlen ( value ); /* Exclude terminating NUL */
+
+ /* Copy string to buffer */
+ if ( len > raw_len )
+ len = raw_len;
+ memcpy ( buf, value, len );
+
+ return raw_len;
+}
+
+/**
+ * Format string setting value
+ *
+ * @v raw Raw setting value
+ * @v raw_len Length of raw setting value
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int format_string_setting ( const void *raw, size_t raw_len, char *buf,
+ size_t len ) {
+
+ /* Copy string to buffer, and terminate */
+ memset ( buf, 0, len );
+ if ( len > raw_len )
+ len = raw_len;
+ memcpy ( buf, raw, len );
+
+ return raw_len;
+}
+
+/** A string setting type */
+struct setting_type setting_type_string __setting_type = {
+ .name = "string",
+ .parse = parse_string_setting,
+ .format = format_string_setting,
+};
+
+/**
+ * Parse URI-encoded string setting value
+ *
+ * @v value Formatted setting value
+ * @v buf Buffer to contain raw value
+ * @v len Length of buffer
+ * @ret len Length of raw value, or negative error
+ */
+static int parse_uristring_setting ( const char *value, void *buf,
+ size_t len ) {
+ char tmp[ len + 1 /* NUL */ ];
+ size_t raw_len;
+
+ /* Decode to temporary buffer (including NUL) */
+ raw_len = uri_decode ( value, tmp, sizeof ( tmp ) );
+
+ /* Copy to output buffer (excluding NUL) */
+ if ( len > raw_len )
+ len = raw_len;
+ memcpy ( buf, tmp, len );
+
+ return raw_len;
+}
+
+/**
+ * Format URI-encoded string setting value
+ *
+ * @v raw Raw setting value
+ * @v raw_len Length of raw setting value
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int format_uristring_setting ( const void *raw, size_t raw_len,
+ char *buf, size_t len ) {
+ char tmp[ raw_len + 1 /* NUL */ ];
+
+ /* Copy to temporary buffer and terminate */
+ memcpy ( tmp, raw, raw_len );
+ tmp[raw_len] = '\0';
+
+ /* Encode directly into output buffer */
+ return uri_encode ( tmp, buf, len, URI_FRAGMENT );
+}
+
+/** A URI-encoded string setting type */
+struct setting_type setting_type_uristring __setting_type = {
+ .name = "uristring",
+ .parse = parse_uristring_setting,
+ .format = format_uristring_setting,
+};
+
+/**
+ * Parse IPv4 address setting value
+ *
+ * @v value Formatted setting value
+ * @v buf Buffer to contain raw value
+ * @v len Length of buffer
+ * @ret len Length of raw value, or negative error
+ */
+static int parse_ipv4_setting ( const char *value, void *buf, size_t len ) {
+ struct in_addr ipv4;
+
+ /* Parse IPv4 address */
+ if ( inet_aton ( value, &ipv4 ) == 0 )
+ return -EINVAL;
+
+ /* Copy to buffer */
+ if ( len > sizeof ( ipv4 ) )
+ len = sizeof ( ipv4 );
+ memcpy ( buf, &ipv4, len );
+
+ return ( sizeof ( ipv4 ) );
+}
+
+/**
+ * Format IPv4 address setting value
+ *
+ * @v raw Raw setting value
+ * @v raw_len Length of raw setting value
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int format_ipv4_setting ( const void *raw, size_t raw_len, char *buf,
+ size_t len ) {
+ const struct in_addr *ipv4 = raw;
+
+ if ( raw_len < sizeof ( *ipv4 ) )
+ return -EINVAL;
+ return snprintf ( buf, len, "%s", inet_ntoa ( *ipv4 ) );
+}
+
+/** An IPv4 address setting type */
+struct setting_type setting_type_ipv4 __setting_type = {
+ .name = "ipv4",
+ .parse = parse_ipv4_setting,
+ .format = format_ipv4_setting,
+};
+
+/**
+ * Parse integer setting value
+ *
+ * @v value Formatted setting value
+ * @v buf Buffer to contain raw value
+ * @v len Length of buffer
+ * @v size Integer size, in bytes
+ * @ret len Length of raw value, or negative error
+ */
+static int parse_int_setting ( const char *value, void *buf, size_t len,
+ unsigned int size ) {
+ union {
+ uint32_t num;
+ uint8_t bytes[4];
+ } u;
+ char *endp;
+
+ /* Parse value */
+ u.num = htonl ( strtoul ( value, &endp, 0 ) );
+ if ( *endp )
+ return -EINVAL;
+
+ /* Copy to buffer */
+ if ( len > size )
+ len = size;
+ memcpy ( buf, &u.bytes[ sizeof ( u ) - size ], len );
+
+ return size;
+}
+
+/**
+ * Parse 8-bit integer setting value
+ *
+ * @v value Formatted setting value
+ * @v buf Buffer to contain raw value
+ * @v len Length of buffer
+ * @v size Integer size, in bytes
+ * @ret len Length of raw value, or negative error
+ */
+static int parse_int8_setting ( const char *value, void *buf, size_t len ) {
+ return parse_int_setting ( value, buf, len, sizeof ( uint8_t ) );
+}
+
+/**
+ * Parse 16-bit integer setting value
+ *
+ * @v value Formatted setting value
+ * @v buf Buffer to contain raw value
+ * @v len Length of buffer
+ * @v size Integer size, in bytes
+ * @ret len Length of raw value, or negative error
+ */
+static int parse_int16_setting ( const char *value, void *buf, size_t len ) {
+ return parse_int_setting ( value, buf, len, sizeof ( uint16_t ) );
+}
+
+/**
+ * Parse 32-bit integer setting value
+ *
+ * @v value Formatted setting value
+ * @v buf Buffer to contain raw value
+ * @v len Length of buffer
+ * @v size Integer size, in bytes
+ * @ret len Length of raw value, or negative error
+ */
+static int parse_int32_setting ( const char *value, void *buf, size_t len ) {
+ return parse_int_setting ( value, buf, len, sizeof ( uint32_t ) );
+}
+
+/**
+ * Format signed integer setting value
+ *
+ * @v raw Raw setting value
+ * @v raw_len Length of raw setting value
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int format_int_setting ( const void *raw, size_t raw_len, char *buf,
+ size_t len ) {
+ signed long value;
+ unsigned long dummy;
+ int check_len;
+
+ /* Extract numeric value */
+ check_len = numeric_setting_value ( raw, raw_len, &value, &dummy );
+ if ( check_len < 0 )
+ return check_len;
+ assert ( check_len == ( int ) raw_len );
+
+ /* Format value */
+ return snprintf ( buf, len, "%ld", value );
+}
+
+/**
+ * Format unsigned integer setting value
+ *
+ * @v raw Raw setting value
+ * @v raw_len Length of raw setting value
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int format_uint_setting ( const void *raw, size_t raw_len, char *buf,
+ size_t len ) {
+ signed long dummy;
+ unsigned long value;
+ int check_len;
+
+ /* Extract numeric value */
+ check_len = numeric_setting_value ( raw, raw_len, &dummy, &value );
+ if ( check_len < 0 )
+ return check_len;
+ assert ( check_len == ( int ) raw_len );
+
+ /* Format value */
+ return snprintf ( buf, len, "%#lx", value );
+}
+
+/** A signed 8-bit integer setting type */
+struct setting_type setting_type_int8 __setting_type = {
+ .name = "int8",
+ .parse = parse_int8_setting,
+ .format = format_int_setting,
+};
+
+/** A signed 16-bit integer setting type */
+struct setting_type setting_type_int16 __setting_type = {
+ .name = "int16",
+ .parse = parse_int16_setting,
+ .format = format_int_setting,
+};
+
+/** A signed 32-bit integer setting type */
+struct setting_type setting_type_int32 __setting_type = {
+ .name = "int32",
+ .parse = parse_int32_setting,
+ .format = format_int_setting,
+};
+
+/** An unsigned 8-bit integer setting type */
+struct setting_type setting_type_uint8 __setting_type = {
+ .name = "uint8",
+ .parse = parse_int8_setting,
+ .format = format_uint_setting,
+};
+
+/** An unsigned 16-bit integer setting type */
+struct setting_type setting_type_uint16 __setting_type = {
+ .name = "uint16",
+ .parse = parse_int16_setting,
+ .format = format_uint_setting,
+};
+
+/** An unsigned 32-bit integer setting type */
+struct setting_type setting_type_uint32 __setting_type = {
+ .name = "uint32",
+ .parse = parse_int32_setting,
+ .format = format_uint_setting,
+};
+
+/**
+ * Parse hex string setting value
+ *
+ * @v value Formatted setting value
+ * @v buf Buffer to contain raw value
+ * @v len Length of buffer
+ * @ret len Length of raw value, or negative error
+ */
+static int parse_hex_setting ( const char *value, void *buf, size_t len ) {
+ char *ptr = ( char * ) value;
+ uint8_t *bytes = buf;
+ unsigned int count = 0;
+ uint8_t byte;
+
+ while ( 1 ) {
+ byte = strtoul ( ptr, &ptr, 16 );
+ if ( count++ < len )
+ *bytes++ = byte;
+ switch ( *ptr ) {
+ case '\0' :
+ return count;
+ case ':' :
+ case '-' :
+ ptr++;
+ break;
+ default :
+ return -EINVAL;
+ }
+ }
+}
+
+/**
+ * Format hex string setting value
+ *
+ * @v raw Raw setting value
+ * @v raw_len Length of raw setting value
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @v delimiter Byte delimiter
+ * @ret len Length of formatted value, or negative error
+ */
+static int format_hex_setting ( const void *raw, size_t raw_len, char *buf,
+ size_t len, const char *delimiter ) {
+ const uint8_t *bytes = raw;
+ int used = 0;
+ unsigned int i;
+
+ if ( len )
+ buf[0] = 0; /* Ensure that a terminating NUL exists */
+ for ( i = 0 ; i < raw_len ; i++ ) {
+ used += ssnprintf ( ( buf + used ), ( len - used ),
+ "%s%02x", ( used ? delimiter : "" ),
+ bytes[i] );
+ }
+ return used;
+}
+
+/**
+ * Format hex string setting value (using colon delimiter)
+ *
+ * @v raw Raw setting value
+ * @v raw_len Length of raw setting value
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int format_hex_colon_setting ( const void *raw, size_t raw_len,
+ char *buf, size_t len ) {
+ return format_hex_setting ( raw, raw_len, buf, len, ":" );
+}
+
+/**
+ * Format hex string setting value (using hyphen delimiter)
+ *
+ * @v raw Raw setting value
+ * @v raw_len Length of raw setting value
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int format_hex_hyphen_setting ( const void *raw, size_t raw_len,
+ char *buf, size_t len ) {
+ return format_hex_setting ( raw, raw_len, buf, len, "-" );
+}
+
+/** A hex-string setting (colon-delimited) */
+struct setting_type setting_type_hex __setting_type = {
+ .name = "hex",
+ .parse = parse_hex_setting,
+ .format = format_hex_colon_setting,
+};
+
+/** A hex-string setting (hyphen-delimited) */
+struct setting_type setting_type_hexhyp __setting_type = {
+ .name = "hexhyp",
+ .parse = parse_hex_setting,
+ .format = format_hex_hyphen_setting,
+};
+
+/**
+ * Parse UUID setting value
+ *
+ * @v value Formatted setting value
+ * @v buf Buffer to contain raw value
+ * @v len Length of buffer
+ * @ret len Length of raw value, or negative error
+ */
+static int parse_uuid_setting ( const char *value __unused,
+ void *buf __unused, size_t len __unused ) {
+ return -ENOTSUP;
+}
+
+/**
+ * Format UUID setting value
+ *
+ * @v raw Raw setting value
+ * @v raw_len Length of raw setting value
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int format_uuid_setting ( const void *raw, size_t raw_len, char *buf,
+ size_t len ) {
+ const union uuid *uuid = raw;
+
+ /* Range check */
+ if ( raw_len != sizeof ( *uuid ) )
+ return -ERANGE;
+
+ /* Format value */
+ return snprintf ( buf, len, "%s", uuid_ntoa ( uuid ) );
+}
+
+/** UUID setting type */
+struct setting_type setting_type_uuid __setting_type = {
+ .name = "uuid",
+ .parse = parse_uuid_setting,
+ .format = format_uuid_setting,
+};
+
+/******************************************************************************
+ *
+ * Setting expansion
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Expand variables within string
+ *
+ * @v string String
+ * @ret expstr Expanded string
+ *
+ * The expanded string is allocated with malloc() and the caller must
+ * eventually free() it.
+ */
+char * expand_settings ( const char *string ) {
+ char *expstr;
+ char *start;
+ char *end;
+ char *head;
+ char *name;
+ char *tail;
+ int setting_len;
+ int new_len;
+ char *tmp;
+
+ /* Obtain temporary modifiable copy of string */
+ expstr = strdup ( string );
+ if ( ! expstr )
+ return NULL;
+
+ /* Expand while expansions remain */
+ while ( 1 ) {
+
+ head = expstr;
+
+ /* Locate setting to be expanded */
+ start = NULL;
+ end = NULL;
+ for ( tmp = expstr ; *tmp ; tmp++ ) {
+ if ( ( tmp[0] == '$' ) && ( tmp[1] == '{' ) )
+ start = tmp;
+ if ( start && ( tmp[0] == '}' ) ) {
+ end = tmp;
+ break;
+ }
+ }
+ if ( ! end )
+ break;
+ *start = '\0';
+ name = ( start + 2 );
+ *end = '\0';
+ tail = ( end + 1 );
+
+ /* Determine setting length */
+ setting_len = fetchf_named_setting ( name, NULL, 0, NULL, 0 );
+ if ( setting_len < 0 )
+ setting_len = 0; /* Treat error as empty setting */
+
+ /* Read setting into temporary buffer */
+ {
+ char setting_buf[ setting_len + 1 ];
+
+ setting_buf[0] = '\0';
+ fetchf_named_setting ( name, NULL, 0, setting_buf,
+ sizeof ( setting_buf ) );
+
+ /* Construct expanded string and discard old string */
+ tmp = expstr;
+ new_len = asprintf ( &expstr, "%s%s%s",
+ head, setting_buf, tail );
+ free ( tmp );
+ if ( new_len < 0 )
+ return NULL;
+ }
+ }
+
+ return expstr;
+}
+
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** Hostname setting */
+struct setting hostname_setting __setting ( SETTING_HOST ) = {
+ .name = "hostname",
+ .description = "Host name",
+ .tag = DHCP_HOST_NAME,
+ .type = &setting_type_string,
+};
+
+/** TFTP server setting */
+struct setting next_server_setting __setting ( SETTING_BOOT ) = {
+ .name = "next-server",
+ .description = "TFTP server",
+ .tag = DHCP_EB_SIADDR,
+ .type = &setting_type_ipv4,
+};
+
+/** Filename setting */
+struct setting filename_setting __setting ( SETTING_BOOT ) = {
+ .name = "filename",
+ .description = "Boot filename",
+ .tag = DHCP_BOOTFILE_NAME,
+ .type = &setting_type_string,
+};
+
+/** Root path setting */
+struct setting root_path_setting __setting ( SETTING_SANBOOT ) = {
+ .name = "root-path",
+ .description = "SAN root path",
+ .tag = DHCP_ROOT_PATH,
+ .type = &setting_type_string,
+};
+
+/** Username setting */
+struct setting username_setting __setting ( SETTING_AUTH ) = {
+ .name = "username",
+ .description = "User name",
+ .tag = DHCP_EB_USERNAME,
+ .type = &setting_type_string,
+};
+
+/** Password setting */
+struct setting password_setting __setting ( SETTING_AUTH ) = {
+ .name = "password",
+ .description = "Password",
+ .tag = DHCP_EB_PASSWORD,
+ .type = &setting_type_string,
+};
+
+/** Priority setting */
+struct setting priority_setting __setting ( SETTING_MISC ) = {
+ .name = "priority",
+ .description = "Settings priority",
+ .tag = DHCP_EB_PRIORITY,
+ .type = &setting_type_int8,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/core/string.c b/src/VBox/Devices/PC/ipxe/src/core/string.c
new file mode 100644
index 00000000..190007a4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/string.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * string handling functions
+ * based on linux/lib/string.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/*
+ * stupid library routines.. The optimized versions should generally be found
+ * as inline code in <asm-xx/string.h>
+ *
+ * These are buggy as well..
+ *
+ * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
+ * - Added strsep() which will replace strtok() soon (because strsep() is
+ * reentrant and should be faster). Use only strsep() in new code, please.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+/* *** FROM string.c *** */
+
+#ifndef __HAVE_ARCH_STRCPY
+/**
+ * strcpy - Copy a %NUL terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ */
+char * strcpy(char * dest,const char *src)
+{
+ char *tmp = dest;
+
+ while ((*dest++ = *src++) != '\0')
+ /* nothing */;
+ return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNCPY
+/**
+ * strncpy - Copy a length-limited, %NUL-terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @count: The maximum number of bytes to copy
+ *
+ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
+ * However, the result is not %NUL-terminated if the source exceeds
+ * @count bytes.
+ */
+char * strncpy(char * dest,const char *src,size_t count)
+{
+ char *tmp = dest;
+
+ while (count-- && (*dest++ = *src++) != '\0')
+ /* nothing */;
+
+ return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCAT
+/**
+ * strcat - Append one %NUL-terminated string to another
+ * @dest: The string to be appended to
+ * @src: The string to append to it
+ */
+char * strcat(char * dest, const char * src)
+{
+ char *tmp = dest;
+
+ while (*dest)
+ dest++;
+ while ((*dest++ = *src++) != '\0')
+ ;
+
+ return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCMP
+/**
+ * strcmp - Compare two strings
+ * @cs: One string
+ * @ct: Another string
+ */
+int strcmp(const char * cs,const char * ct)
+{
+ register signed char __res;
+
+ while (1) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ }
+
+ return __res;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNCMP
+/**
+ * strncmp - Compare two length-limited strings
+ * @cs: One string
+ * @ct: Another string
+ * @count: The maximum number of bytes to compare
+ */
+int strncmp(const char * cs,const char * ct,size_t count)
+{
+ register signed char __res = 0;
+
+ while (count) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ count--;
+ }
+
+ return __res;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCASECMP
+int strcasecmp(const char *a, const char *b)
+{
+ while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; }
+ return((*a & ~0x20) - (*b & ~0x20));
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCHR
+/**
+ * strchr - Find the first occurrence of a character in a string
+ * @s: The string to be searched
+ * @c: The character to search for
+ */
+char * strchr(const char * s, int c)
+{
+ for(; *s != (char) c; ++s)
+ if (*s == '\0')
+ return NULL;
+ return (char *) s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRRCHR
+/**
+ * strrchr - Find the last occurrence of a character in a string
+ * @s: The string to be searched
+ * @c: The character to search for
+ */
+char * strrchr(const char * s, int c)
+{
+ const char *p = s + strlen(s);
+ do {
+ if (*p == (char)c)
+ return (char *)p;
+ } while (--p >= s);
+ return NULL;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRLEN
+/**
+ * strlen - Find the length of a string
+ * @s: The string to be sized
+ */
+size_t strlen(const char * s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNLEN
+/**
+ * strnlen - Find the length of a length-limited string
+ * @s: The string to be sized
+ * @count: The maximum number of bytes to search
+ */
+size_t strnlen(const char * s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMSET
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void * memset(void * s,int c,size_t count)
+{
+ char *xs = (char *) s;
+
+ while (count--)
+ *xs++ = c;
+
+ return s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMCPY
+/**
+ * memcpy - Copy one area of memory to another
+ * @dest: Where to copy to
+ * @src: Where to copy from
+ * @count: The size of the area.
+ *
+ * You should not use this function to access IO space, use memcpy_toio()
+ * or memcpy_fromio() instead.
+ */
+void * memcpy(void * dest,const void *src,size_t count)
+{
+ char *tmp = (char *) dest, *s = (char *) src;
+
+ while (count--)
+ *tmp++ = *s++;
+
+ return dest;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMMOVE
+/**
+ * memmove - Copy one area of memory to another
+ * @dest: Where to copy to
+ * @src: Where to copy from
+ * @count: The size of the area.
+ *
+ * Unlike memcpy(), memmove() copes with overlapping areas.
+ */
+void * memmove(void * dest,const void *src,size_t count)
+{
+ char *tmp, *s;
+
+ if (dest <= src) {
+ tmp = (char *) dest;
+ s = (char *) src;
+ while (count--)
+ *tmp++ = *s++;
+ }
+ else {
+ tmp = (char *) dest + count;
+ s = (char *) src + count;
+ while (count--)
+ *--tmp = *--s;
+ }
+
+ return dest;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMCMP
+/**
+ * memcmp - Compare two areas of memory
+ * @cs: One area of memory
+ * @ct: Another area of memory
+ * @count: The size of the area.
+ */
+int memcmp(const void * cs,const void * ct,size_t count)
+{
+ const unsigned char *su1, *su2;
+ int res = 0;
+
+ for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ if ((res = *su1 - *su2) != 0)
+ break;
+ return res;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRSTR
+/**
+ * strstr - Find the first substring in a %NUL terminated string
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ */
+char * strstr(const char * s1,const char * s2)
+{
+ int l1, l2;
+
+ l2 = strlen(s2);
+ if (!l2)
+ return (char *) s1;
+ l1 = strlen(s1);
+ while (l1 >= l2) {
+ l1--;
+ if (!memcmp(s1,s2,l2))
+ return (char *) s1;
+ s1++;
+ }
+ return NULL;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMCHR
+/**
+ * memchr - Find a character in an area of memory.
+ * @s: The memory area
+ * @c: The byte to search for
+ * @n: The size of the area.
+ *
+ * returns the address of the first occurrence of @c, or %NULL
+ * if @c is not found
+ */
+void * memchr(const void *s, int c, size_t n)
+{
+ const unsigned char *p = s;
+ while (n-- != 0) {
+ if ((unsigned char)c == *p++) {
+ return (void *)(p-1);
+ }
+ }
+ return NULL;
+}
+
+#endif
+
+char * strndup(const char *s, size_t n)
+{
+ size_t len = strlen(s);
+ char *new;
+
+ if (len>n)
+ len = n;
+ new = malloc(len+1);
+ if (new) {
+ new[len] = '\0';
+ memcpy(new,s,len);
+ }
+ return new;
+}
+
+char * strdup(const char *s) {
+ return strndup(s, ~((size_t)0));
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/stringextra.c b/src/VBox/Devices/PC/ipxe/src/core/stringextra.c
new file mode 100644
index 00000000..0a509852
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/stringextra.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * string handling functions
+ * based on linux/lib/string.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/*
+ * stupid library routines.. The optimized versions should generally be found
+ * as inline code in <asm-xx/string.h>
+ *
+ * These are buggy as well..
+ *
+ * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
+ * - Added strsep() which will replace strtok() soon (because strsep() is
+ * reentrant and should be faster). Use only strsep() in new code, please.
+ */
+
+/*
+ * these are the standard string functions that are currently not used by
+ * any code in etherboot. put into a separate file to avoid linking them in
+ * with the rest of string.o
+ * if anything ever does want to use a function of these, consider moving
+ * the function in question back into string.c
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+/* *** FROM string.c *** */
+
+#ifndef __HAVE_ARCH_STRNICMP
+/**
+ * strnicmp - Case insensitive, length-limited string comparison
+ * @s1: One string
+ * @s2: The other string
+ * @len: the maximum number of characters to compare
+ */
+int strnicmp(const char *s1, const char *s2, size_t len)
+{
+ /* Yes, Virginia, it had better be unsigned */
+ unsigned char c1, c2;
+
+ c1 = 0; c2 = 0;
+ if (len) {
+ do {
+ c1 = *s1; c2 = *s2;
+ s1++; s2++;
+ if (!c1)
+ break;
+ if (!c2)
+ break;
+ if (c1 == c2)
+ continue;
+ c1 = tolower(c1);
+ c2 = tolower(c2);
+ if (c1 != c2)
+ break;
+ } while (--len);
+ }
+ return (int)c1 - (int)c2;
+}
+#endif
+
+char * ___strtok;
+
+#ifndef __HAVE_ARCH_STRNCAT
+/**
+ * strncat - Append a length-limited, %NUL-terminated string to another
+ * @dest: The string to be appended to
+ * @src: The string to append to it
+ * @count: The maximum numbers of bytes to copy
+ *
+ * Note that in contrast to strncpy, strncat ensures the result is
+ * terminated.
+ */
+char * strncat(char *dest, const char *src, size_t count)
+{
+ char *tmp = dest;
+
+ if (count) {
+ while (*dest)
+ dest++;
+ while ((*dest++ = *src++)) {
+ if (--count == 0) {
+ *dest = '\0';
+ break;
+ }
+ }
+ }
+
+ return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRSPN
+/**
+ * strspn - Calculate the length of the initial substring of @s which only
+ * contain letters in @accept
+ * @s: The string to be searched
+ * @accept: The string to search for
+ */
+size_t strspn(const char *s, const char *accept)
+{
+ const char *p;
+ const char *a;
+ size_t count = 0;
+
+ for (p = s; *p != '\0'; ++p) {
+ for (a = accept; *a != '\0'; ++a) {
+ if (*p == *a)
+ break;
+ }
+ if (*a == '\0')
+ return count;
+ ++count;
+ }
+
+ return count;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCSPN
+/**
+ * strcspn - Calculate the length of the initial substring of @s which only
+ * contain letters not in @reject
+ * @s: The string to be searched
+ * @accept: The string to search for
+ */
+size_t strcspn(const char *s, const char *reject)
+{
+ const char *p;
+ const char *r;
+ size_t count = 0;
+
+ for (p = s; *p != '\0'; ++p) {
+ for (r = reject; *r != '\0'; ++r) {
+ if (*p == *r)
+ return count;
+ }
+ ++count;
+ }
+
+ return count;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRPBRK
+/**
+ * strpbrk - Find the first occurrence of a set of characters
+ * @cs: The string to be searched
+ * @ct: The characters to search for
+ */
+char * strpbrk(const char * cs,const char * ct)
+{
+ const char *sc1,*sc2;
+
+ for( sc1 = cs; *sc1 != '\0'; ++sc1) {
+ for( sc2 = ct; *sc2 != '\0'; ++sc2) {
+ if (*sc1 == *sc2)
+ return (char *) sc1;
+ }
+ }
+ return NULL;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRTOK
+/**
+ * strtok - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ *
+ * WARNING: strtok is deprecated, use strsep instead.
+ */
+char * strtok(char * s,const char * ct)
+{
+ char *sbegin, *send;
+
+ sbegin = s ? s : ___strtok;
+ if (!sbegin) {
+ return NULL;
+ }
+ sbegin += strspn(sbegin,ct);
+ if (*sbegin == '\0') {
+ ___strtok = NULL;
+ return( NULL );
+ }
+ send = strpbrk( sbegin, ct);
+ if (send && *send != '\0')
+ *send++ = '\0';
+ ___strtok = send;
+ return (sbegin);
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRSEP
+/**
+ * strsep - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ *
+ * strsep() updates @s to point after the token, ready for the next call.
+ *
+ * It returns empty tokens, too, behaving exactly like the libc function
+ * of that name. In fact, it was stolen from glibc2 and de-fancy-fied.
+ * Same semantics, slimmer shape. ;)
+ */
+char * strsep(char **s, const char *ct)
+{
+ char *sbegin = *s, *end;
+
+ if (sbegin == NULL)
+ return NULL;
+
+ end = strpbrk(sbegin, ct);
+ if (end)
+ *end++ = '\0';
+ *s = end;
+
+ return sbegin;
+}
+#endif
+
+#ifndef __HAVE_ARCH_BCOPY
+/**
+ * bcopy - Copy one area of memory to another
+ * @src: Where to copy from
+ * @dest: Where to copy to
+ * @count: The size of the area.
+ *
+ * Note that this is the same as memcpy(), with the arguments reversed.
+ * memcpy() is the standard, bcopy() is a legacy BSD function.
+ *
+ * You should not use this function to access IO space, use memcpy_toio()
+ * or memcpy_fromio() instead.
+ */
+char * bcopy(const char * src, char * dest, int count)
+{
+ return memmove(dest,src,count);
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMSCAN
+/**
+ * memscan - Find a character in an area of memory.
+ * @addr: The memory area
+ * @c: The byte to search for
+ * @size: The size of the area.
+ *
+ * returns the address of the first occurrence of @c, or 1 byte past
+ * the area if @c is not found
+ */
+void * memscan(const void * addr, int c, size_t size)
+{
+ unsigned char * p = (unsigned char *) addr;
+
+ while (size) {
+ if (*p == c)
+ return (void *) p;
+ p++;
+ size--;
+ }
+ return (void *) p;
+}
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/core/strtoull.c b/src/VBox/Devices/PC/ipxe/src/core/strtoull.c
new file mode 100644
index 00000000..00986eef
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/strtoull.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <ctype.h>
+
+/*
+ * Despite being exactly the same as strtoul() except the long long instead of
+ * long it ends up being much bigger so provide a separate implementation in a
+ * separate object so that it won't be linked in if not used.
+ */
+unsigned long long strtoull ( const char *p, char **endp, int base ) {
+ unsigned long long ret = 0;
+ int negative = 0;
+ unsigned int charval;
+
+ while ( isspace ( *p ) )
+ p++;
+
+ if ( *p == '-' ) {
+ negative = 1;
+ p++;
+ }
+
+ base = strtoul_base ( &p, base );
+
+ while ( 1 ) {
+ charval = strtoul_charval ( *p );
+ if ( charval >= ( unsigned int ) base )
+ break;
+ ret = ( ( ret * base ) + charval );
+ p++;
+ }
+
+ if ( negative )
+ ret = -ret;
+
+ if ( endp )
+ *endp = ( char * ) p;
+
+ return ( ret );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/time.c b/src/VBox/Devices/PC/ipxe/src/core/time.c
new file mode 100644
index 00000000..52ae3ee9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/time.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <time.h>
+
+/** @file
+ *
+ * Date and time
+ *
+ * POSIX:2008 section 4.15 defines "seconds since the Epoch" as an
+ * abstract measure approximating the number of seconds that have
+ * elapsed since the Epoch, excluding leap seconds. The formula given
+ * is
+ *
+ * tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
+ * (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
+ * ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400
+ *
+ * This calculation assumes that leap years occur in each year that is
+ * either divisible by 4 but not divisible by 100, or is divisible by
+ * 400.
+ */
+
+/** Days of week (for debugging) */
+static const char *weekdays[] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
+/**
+ * Determine whether or not year is a leap year
+ *
+ * @v tm_year Years since 1900
+ * @v is_leap_year Year is a leap year
+ */
+static int is_leap_year ( int tm_year ) {
+ int leap_year = 0;
+
+ if ( ( tm_year % 4 ) == 0 )
+ leap_year = 1;
+ if ( ( tm_year % 100 ) == 0 )
+ leap_year = 0;
+ if ( ( tm_year % 400 ) == 100 )
+ leap_year = 1;
+
+ return leap_year;
+}
+
+/**
+ * Calculate number of leap years since 1900
+ *
+ * @v tm_year Years since 1900
+ * @v num_leap_years Number of leap years
+ */
+static int leap_years_to_end ( int tm_year ) {
+ int leap_years = 0;
+
+ leap_years += ( tm_year / 4 );
+ leap_years -= ( tm_year / 100 );
+ leap_years += ( ( tm_year + 300 ) / 400 );
+
+ return leap_years;
+}
+
+/**
+ * Calculate day of week
+ *
+ * @v tm_year Years since 1900
+ * @v tm_mon Month of year [0,11]
+ * @v tm_day Day of month [1,31]
+ */
+static int day_of_week ( int tm_year, int tm_mon, int tm_mday ) {
+ static const uint8_t offset[12] =
+ { 1, 4, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5 };
+ int pseudo_year = tm_year;
+
+ if ( tm_mon < 2 )
+ pseudo_year--;
+ return ( ( pseudo_year + leap_years_to_end ( pseudo_year ) +
+ offset[tm_mon] + tm_mday ) % 7 );
+}
+
+/** Days from start of year until start of months (in non-leap years) */
+static const uint16_t days_to_month_start[] =
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+/**
+ * Calculate seconds since the Epoch
+ *
+ * @v tm Broken-down time
+ * @ret time Seconds since the Epoch
+ */
+time_t mktime ( struct tm *tm ) {
+ int days_since_epoch;
+ int seconds_since_day;
+ time_t seconds;
+
+ /* Calculate day of year */
+ tm->tm_yday = ( ( tm->tm_mday - 1 ) +
+ days_to_month_start[ tm->tm_mon ] );
+ if ( ( tm->tm_mon >= 2 ) && is_leap_year ( tm->tm_year ) )
+ tm->tm_yday++;
+
+ /* Calculate day of week */
+ tm->tm_wday = day_of_week ( tm->tm_year, tm->tm_mon, tm->tm_mday );
+
+ /* Calculate seconds since the Epoch */
+ days_since_epoch = ( tm->tm_yday + ( 365 * tm->tm_year ) - 25567 +
+ leap_years_to_end ( tm->tm_year - 1 ) );
+ seconds_since_day =
+ ( ( ( ( tm->tm_hour * 60 ) + tm->tm_min ) * 60 ) + tm->tm_sec );
+ seconds = ( ( ( ( time_t ) days_since_epoch ) * ( ( time_t ) 86400 ) ) +
+ seconds_since_day );
+
+ DBGC ( &weekdays, "TIME %04d-%02d-%02d %02d:%02d:%02d => %lld (%s, "
+ "day %d)\n", ( tm->tm_year + 1900 ), ( tm->tm_mon + 1 ),
+ tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, seconds,
+ weekdays[ tm->tm_wday ], tm->tm_yday );
+
+ return seconds;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/timer.c b/src/VBox/Devices/PC/ipxe/src/core/timer.c
new file mode 100644
index 00000000..096d07ec
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/timer.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <unistd.h>
+
+/**
+ * Delay for a fixed number of milliseconds
+ *
+ * @v msecs Number of milliseconds for which to delay
+ */
+void mdelay ( unsigned long msecs ) {
+ while ( msecs-- )
+ udelay ( 1000 );
+}
+
+/**
+ * Delay for a fixed number of seconds
+ *
+ * @v secs Number of seconds for which to delay
+ */
+unsigned int sleep ( unsigned int secs ) {
+ while ( secs-- )
+ mdelay ( 1000 );
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/uri.c b/src/VBox/Devices/PC/ipxe/src/core/uri.c
new file mode 100644
index 00000000..ff49e47a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/uri.c
@@ -0,0 +1,500 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Uniform Resource Identifiers
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libgen.h>
+#include <ctype.h>
+#include <ipxe/vsprintf.h>
+#include <ipxe/uri.h>
+
+/**
+ * Dump URI for debugging
+ *
+ * @v uri URI
+ */
+static void dump_uri ( struct uri *uri ) {
+ if ( ! uri )
+ return;
+ if ( uri->scheme )
+ DBG ( " scheme \"%s\"", uri->scheme );
+ if ( uri->opaque )
+ DBG ( " opaque \"%s\"", uri->opaque );
+ if ( uri->user )
+ DBG ( " user \"%s\"", uri->user );
+ if ( uri->password )
+ DBG ( " password \"%s\"", uri->password );
+ if ( uri->host )
+ DBG ( " host \"%s\"", uri->host );
+ if ( uri->port )
+ DBG ( " port \"%s\"", uri->port );
+ if ( uri->path )
+ DBG ( " path \"%s\"", uri->path );
+ if ( uri->query )
+ DBG ( " query \"%s\"", uri->query );
+ if ( uri->fragment )
+ DBG ( " fragment \"%s\"", uri->fragment );
+}
+
+/**
+ * Parse URI
+ *
+ * @v uri_string URI as a string
+ * @ret uri URI
+ *
+ * Splits a URI into its component parts. The return URI structure is
+ * dynamically allocated and must eventually be freed by calling
+ * uri_put().
+ */
+struct uri * parse_uri ( const char *uri_string ) {
+ struct uri *uri;
+ char *raw;
+ char *tmp;
+ char *path;
+ char *authority;
+ int i;
+ size_t raw_len;
+
+ /* Allocate space for URI struct and a copy of the string */
+ raw_len = ( strlen ( uri_string ) + 1 /* NUL */ );
+ uri = zalloc ( sizeof ( *uri ) + raw_len );
+ if ( ! uri )
+ return NULL;
+ raw = ( ( ( char * ) uri ) + sizeof ( *uri ) );
+
+ /* Copy in the raw string */
+ memcpy ( raw, uri_string, raw_len );
+
+ /* Start by chopping off the fragment, if it exists */
+ if ( ( tmp = strchr ( raw, '#' ) ) ) {
+ *(tmp++) = '\0';
+ uri->fragment = tmp;
+ }
+
+ /* Identify absolute/relative URI. We ignore schemes that are
+ * apparently only a single character long, since otherwise we
+ * misinterpret a DOS-style path name ("C:\path\to\file") as a
+ * URI with scheme="C",opaque="\path\to\file".
+ */
+ if ( ( tmp = strchr ( raw, ':' ) ) && ( tmp > ( raw + 1 ) ) ) {
+ /* Absolute URI: identify hierarchical/opaque */
+ uri->scheme = raw;
+ *(tmp++) = '\0';
+ if ( *tmp == '/' ) {
+ /* Absolute URI with hierarchical part */
+ path = tmp;
+ } else {
+ /* Absolute URI with opaque part */
+ uri->opaque = tmp;
+ path = NULL;
+ }
+ } else {
+ /* Relative URI */
+ path = raw;
+ }
+
+ /* If we don't have a path (i.e. we have an absolute URI with
+ * an opaque portion, we're already finished processing
+ */
+ if ( ! path )
+ goto done;
+
+ /* Chop off the query, if it exists */
+ if ( ( tmp = strchr ( path, '?' ) ) ) {
+ *(tmp++) = '\0';
+ uri->query = tmp;
+ }
+
+ /* Identify net/absolute/relative path */
+ if ( strncmp ( path, "//", 2 ) == 0 ) {
+ /* Net path. If this is terminated by the first '/'
+ * of an absolute path, then we have no space for a
+ * terminator after the authority field, so shuffle
+ * the authority down by one byte, overwriting one of
+ * the two slashes.
+ */
+ authority = ( path + 2 );
+ if ( ( tmp = strchr ( authority, '/' ) ) ) {
+ /* Shuffle down */
+ uri->path = tmp;
+ memmove ( ( authority - 1 ), authority,
+ ( tmp - authority ) );
+ authority--;
+ *(--tmp) = '\0';
+ }
+ } else {
+ /* Absolute/relative path */
+ uri->path = path;
+ authority = NULL;
+ }
+
+ /* If we don't have an authority (i.e. we have a non-net
+ * path), we're already finished processing
+ */
+ if ( ! authority )
+ goto done;
+
+ /* Split authority into user[:password] and host[:port] portions */
+ if ( ( tmp = strchr ( authority, '@' ) ) ) {
+ /* Has user[:password] */
+ *(tmp++) = '\0';
+ uri->host = tmp;
+ uri->user = authority;
+ if ( ( tmp = strchr ( authority, ':' ) ) ) {
+ /* Has password */
+ *(tmp++) = '\0';
+ uri->password = tmp;
+ }
+ } else {
+ /* No user:password */
+ uri->host = authority;
+ }
+
+ /* Split host into host[:port] */
+ if ( ( tmp = strchr ( uri->host, ':' ) ) ) {
+ *(tmp++) = '\0';
+ uri->port = tmp;
+ }
+
+ /* Decode fields that should be decoded */
+ for ( i = URI_FIRST_FIELD; i <= URI_LAST_FIELD; i++ ) {
+ const char *field = uri_get_field ( uri, i );
+ if ( field && ( URI_ENCODED & ( 1 << i ) ) )
+ uri_decode ( field, ( char * ) field,
+ strlen ( field ) + 1 /* NUL */ );
+ }
+
+ done:
+ DBG ( "URI \"%s\" split into", uri_string );
+ dump_uri ( uri );
+ DBG ( "\n" );
+
+ return uri;
+}
+
+/**
+ * Get port from URI
+ *
+ * @v uri URI, or NULL
+ * @v default_port Default port to use if none specified in URI
+ * @ret port Port
+ */
+unsigned int uri_port ( struct uri *uri, unsigned int default_port ) {
+ if ( ( ! uri ) || ( ! uri->port ) )
+ return default_port;
+ return ( strtoul ( uri->port, NULL, 0 ) );
+}
+
+/**
+ * Unparse URI
+ *
+ * @v buf Buffer to fill with URI string
+ * @v size Size of buffer
+ * @v uri URI to write into buffer, or NULL
+ * @v fields Bitmask of fields to include in URI string, or URI_ALL
+ * @ret len Length of URI string
+ */
+int unparse_uri ( char *buf, size_t size, struct uri *uri,
+ unsigned int fields ) {
+ /* List of characters that typically go before certain fields */
+ static char separators[] = { /* scheme */ 0, /* opaque */ ':',
+ /* user */ 0, /* password */ ':',
+ /* host */ '@', /* port */ ':',
+ /* path */ 0, /* query */ '?',
+ /* fragment */ '#' };
+ int used = 0;
+ int i;
+
+ DBG ( "URI unparsing" );
+ dump_uri ( uri );
+ DBG ( "\n" );
+
+ /* Ensure buffer is NUL-terminated */
+ if ( size )
+ buf[0] = '\0';
+
+ /* Special-case NULL URI */
+ if ( ! uri )
+ return 0;
+
+ /* Iterate through requested fields */
+ for ( i = URI_FIRST_FIELD; i <= URI_LAST_FIELD; i++ ) {
+ const char *field = uri_get_field ( uri, i );
+ char sep = separators[i];
+
+ /* Ensure `fields' only contains bits for fields that exist */
+ if ( ! field )
+ fields &= ~( 1 << i );
+
+ /* Store this field if we were asked to */
+ if ( fields & ( 1 << i ) ) {
+ /* Print :// if we're non-opaque and had a scheme */
+ if ( ( fields & URI_SCHEME_BIT ) &&
+ ( i > URI_OPAQUE ) ) {
+ used += ssnprintf ( buf + used, size - used,
+ "://" );
+ /* Only print :// once */
+ fields &= ~URI_SCHEME_BIT;
+ }
+
+ /* Only print separator if an earlier field exists */
+ if ( sep && ( fields & ( ( 1 << i ) - 1 ) ) )
+ used += ssnprintf ( buf + used, size - used,
+ "%c", sep );
+
+ /* Print contents of field, possibly encoded */
+ if ( URI_ENCODED & ( 1 << i ) )
+ used += uri_encode ( field, buf + used,
+ size - used, i );
+ else
+ used += ssnprintf ( buf + used, size - used,
+ "%s", field );
+ }
+ }
+
+ return used;
+}
+
+/**
+ * Duplicate URI
+ *
+ * @v uri URI
+ * @ret uri Duplicate URI
+ *
+ * Creates a modifiable copy of a URI.
+ */
+struct uri * uri_dup ( struct uri *uri ) {
+ size_t len = ( unparse_uri ( NULL, 0, uri, URI_ALL ) + 1 );
+ char buf[len];
+
+ unparse_uri ( buf, len, uri, URI_ALL );
+ return parse_uri ( buf );
+}
+
+/**
+ * Resolve base+relative path
+ *
+ * @v base_uri Base path
+ * @v relative_uri Relative path
+ * @ret resolved_uri Resolved path
+ *
+ * Takes a base path (e.g. "/var/lib/tftpboot/vmlinuz" and a relative
+ * path (e.g. "initrd.gz") and produces a new path
+ * (e.g. "/var/lib/tftpboot/initrd.gz"). Note that any non-directory
+ * portion of the base path will automatically be stripped; this
+ * matches the semantics used when resolving the path component of
+ * URIs.
+ */
+char * resolve_path ( const char *base_path,
+ const char *relative_path ) {
+ size_t base_len = ( strlen ( base_path ) + 1 );
+ char base_path_copy[base_len];
+ char *base_tmp = base_path_copy;
+ char *resolved;
+
+ /* If relative path is absolute, just re-use it */
+ if ( relative_path[0] == '/' )
+ return strdup ( relative_path );
+
+ /* Create modifiable copy of path for dirname() */
+ memcpy ( base_tmp, base_path, base_len );
+ base_tmp = dirname ( base_tmp );
+
+ /* Process "./" and "../" elements */
+ while ( *relative_path == '.' ) {
+ relative_path++;
+ if ( *relative_path == 0 ) {
+ /* Do nothing */
+ } else if ( *relative_path == '/' ) {
+ relative_path++;
+ } else if ( *relative_path == '.' ) {
+ relative_path++;
+ if ( *relative_path == 0 ) {
+ base_tmp = dirname ( base_tmp );
+ } else if ( *relative_path == '/' ) {
+ base_tmp = dirname ( base_tmp );
+ relative_path++;
+ } else {
+ relative_path -= 2;
+ break;
+ }
+ } else {
+ relative_path--;
+ break;
+ }
+ }
+
+ /* Create and return new path */
+ if ( asprintf ( &resolved, "%s%s%s", base_tmp,
+ ( ( base_tmp[ strlen ( base_tmp ) - 1 ] == '/' ) ?
+ "" : "/" ), relative_path ) < 0 )
+ return NULL;
+
+ return resolved;
+}
+
+/**
+ * Resolve base+relative URI
+ *
+ * @v base_uri Base URI, or NULL
+ * @v relative_uri Relative URI
+ * @ret resolved_uri Resolved URI
+ *
+ * Takes a base URI (e.g. "http://ipxe.org/kernels/vmlinuz" and a
+ * relative URI (e.g. "../initrds/initrd.gz") and produces a new URI
+ * (e.g. "http://ipxe.org/initrds/initrd.gz").
+ */
+struct uri * resolve_uri ( struct uri *base_uri,
+ struct uri *relative_uri ) {
+ struct uri tmp_uri;
+ char *tmp_path = NULL;
+ struct uri *new_uri;
+
+ /* If relative URI is absolute, just re-use it */
+ if ( uri_is_absolute ( relative_uri ) || ( ! base_uri ) )
+ return uri_get ( relative_uri );
+
+ /* Mangle URI */
+ memcpy ( &tmp_uri, base_uri, sizeof ( tmp_uri ) );
+ if ( relative_uri->path ) {
+ tmp_path = resolve_path ( ( base_uri->path ?
+ base_uri->path : "/" ),
+ relative_uri->path );
+ tmp_uri.path = tmp_path;
+ tmp_uri.query = relative_uri->query;
+ tmp_uri.fragment = relative_uri->fragment;
+ } else if ( relative_uri->query ) {
+ tmp_uri.query = relative_uri->query;
+ tmp_uri.fragment = relative_uri->fragment;
+ } else if ( relative_uri->fragment ) {
+ tmp_uri.fragment = relative_uri->fragment;
+ }
+
+ /* Create demangled URI */
+ new_uri = uri_dup ( &tmp_uri );
+ free ( tmp_path );
+ return new_uri;
+}
+
+/**
+ * Test for unreserved URI characters
+ *
+ * @v c Character to test
+ * @v field Field of URI in which character lies
+ * @ret is_unreserved Character is an unreserved character
+ */
+static int is_unreserved_uri_char ( int c, int field ) {
+ /* According to RFC3986, the unreserved character set is
+ *
+ * A-Z a-z 0-9 - _ . ~
+ *
+ * but we also pass & ; = in queries, / in paths,
+ * and everything in opaques
+ */
+ int ok = ( isupper ( c ) || islower ( c ) || isdigit ( c ) ||
+ ( c == '-' ) || ( c == '_' ) ||
+ ( c == '.' ) || ( c == '~' ) );
+
+ if ( field == URI_QUERY )
+ ok = ok || ( c == ';' ) || ( c == '&' ) || ( c == '=' );
+
+ if ( field == URI_PATH )
+ ok = ok || ( c == '/' );
+
+ if ( field == URI_OPAQUE )
+ ok = 1;
+
+ return ok;
+}
+
+/**
+ * URI-encode string
+ *
+ * @v raw_string String to be URI-encoded
+ * @v buf Buffer to contain encoded string
+ * @v len Length of buffer
+ * @v field Field of URI in which string lies
+ * @ret len Length of encoded string (excluding NUL)
+ */
+size_t uri_encode ( const char *raw_string, char *buf, ssize_t len,
+ int field ) {
+ ssize_t remaining = len;
+ size_t used;
+ unsigned char c;
+
+ if ( len > 0 )
+ buf[0] = '\0';
+
+ while ( ( c = *(raw_string++) ) ) {
+ if ( is_unreserved_uri_char ( c, field ) ) {
+ used = ssnprintf ( buf, remaining, "%c", c );
+ } else {
+ used = ssnprintf ( buf, remaining, "%%%02X", c );
+ }
+ buf += used;
+ remaining -= used;
+ }
+
+ return ( len - remaining );
+}
+
+/**
+ * Decode URI-encoded string
+ *
+ * @v encoded_string URI-encoded string
+ * @v buf Buffer to contain decoded string
+ * @v len Length of buffer
+ * @ret len Length of decoded string (excluding NUL)
+ *
+ * This function may be used in-place, with @a buf the same as
+ * @a encoded_string.
+ */
+size_t uri_decode ( const char *encoded_string, char *buf, ssize_t len ) {
+ ssize_t remaining;
+ char hexbuf[3];
+ char *hexbuf_end;
+ unsigned char c;
+
+ for ( remaining = len; *encoded_string; remaining-- ) {
+ if ( *encoded_string == '%' ) {
+ encoded_string++;
+ snprintf ( hexbuf, sizeof ( hexbuf ), "%s",
+ encoded_string );
+ c = strtoul ( hexbuf, &hexbuf_end, 16 );
+ encoded_string += ( hexbuf_end - hexbuf );
+ } else {
+ c = *(encoded_string++);
+ }
+ if ( remaining > 1 )
+ *buf++ = c;
+ }
+
+ if ( len )
+ *buf = 0;
+
+ return ( len - remaining );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/uuid.c b/src/VBox/Devices/PC/ipxe/src/core/uuid.c
new file mode 100644
index 00000000..cc41afda
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/uuid.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <byteswap.h>
+#include <ipxe/uuid.h>
+
+/** @file
+ *
+ * Universally unique IDs
+ *
+ */
+
+/**
+ * Convert UUID to printable string
+ *
+ * @v uuid UUID
+ * @ret string UUID in canonical form
+ */
+char * uuid_ntoa ( const union uuid *uuid ) {
+ static char buf[37]; /* "00000000-0000-0000-0000-000000000000" */
+
+ sprintf ( buf, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ be32_to_cpu ( uuid->canonical.a ),
+ be16_to_cpu ( uuid->canonical.b ),
+ be16_to_cpu ( uuid->canonical.c ),
+ be16_to_cpu ( uuid->canonical.d ),
+ uuid->canonical.e[0], uuid->canonical.e[1],
+ uuid->canonical.e[2], uuid->canonical.e[3],
+ uuid->canonical.e[4], uuid->canonical.e[5] );
+ return buf;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/vsprintf.c b/src/VBox/Devices/PC/ipxe/src/core/vsprintf.c
new file mode 100644
index 00000000..b721b024
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/vsprintf.c
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/vsprintf.h>
+
+/** @file */
+
+#define CHAR_LEN 0 /**< "hh" length modifier */
+#define SHORT_LEN 1 /**< "h" length modifier */
+#define INT_LEN 2 /**< no length modifier */
+#define LONG_LEN 3 /**< "l" length modifier */
+#define LONGLONG_LEN 4 /**< "ll" length modifier */
+#define SIZE_T_LEN 5 /**< "z" length modifier */
+
+static uint8_t type_sizes[] = {
+ [CHAR_LEN] = sizeof ( char ),
+ [SHORT_LEN] = sizeof ( short ),
+ [INT_LEN] = sizeof ( int ),
+ [LONG_LEN] = sizeof ( long ),
+ [LONGLONG_LEN] = sizeof ( long long ),
+ [SIZE_T_LEN] = sizeof ( size_t ),
+};
+
+/**
+ * Use lower-case for hexadecimal digits
+ *
+ * Note that this value is set to 0x20 since that makes for very
+ * efficient calculations. (Bitwise-ORing with @c LCASE converts to a
+ * lower-case character, for example.)
+ */
+#define LCASE 0x20
+
+/**
+ * Use "alternate form"
+ *
+ * For hexadecimal numbers, this means to add a "0x" or "0X" prefix to
+ * the number.
+ */
+#define ALT_FORM 0x02
+
+/**
+ * Use zero padding
+ *
+ * Note that this value is set to 0x10 since that allows the pad
+ * character to be calculated as @c 0x20|(flags&ZPAD)
+ */
+#define ZPAD 0x10
+
+/**
+ * Format a hexadecimal number
+ *
+ * @v end End of buffer to contain number
+ * @v num Number to format
+ * @v width Minimum field width
+ * @v flags Format flags
+ * @ret ptr End of buffer
+ *
+ * Fills a buffer in reverse order with a formatted hexadecimal
+ * number. The number will be zero-padded to the specified width.
+ * Lower-case and "alternate form" (i.e. "0x" prefix) flags may be
+ * set.
+ *
+ * There must be enough space in the buffer to contain the largest
+ * number that this function can format.
+ */
+static char * format_hex ( char *end, unsigned long long num, int width,
+ int flags ) {
+ char *ptr = end;
+ int case_mod = ( flags & LCASE );
+ int pad = ( ( flags & ZPAD ) | ' ' );
+
+ /* Generate the number */
+ do {
+ *(--ptr) = "0123456789ABCDEF"[ num & 0xf ] | case_mod;
+ num >>= 4;
+ } while ( num );
+
+ /* Pad to width */
+ while ( ( end - ptr ) < width )
+ *(--ptr) = pad;
+
+ /* Add "0x" or "0X" if alternate form specified */
+ if ( flags & ALT_FORM ) {
+ *(--ptr) = 'X' | case_mod;
+ *(--ptr) = '0';
+ }
+
+ return ptr;
+}
+
+/**
+ * Format a decimal number
+ *
+ * @v end End of buffer to contain number
+ * @v num Number to format
+ * @v width Minimum field width
+ * @v flags Format flags
+ * @ret ptr End of buffer
+ *
+ * Fills a buffer in reverse order with a formatted decimal number.
+ * The number will be space-padded to the specified width.
+ *
+ * There must be enough space in the buffer to contain the largest
+ * number that this function can format.
+ */
+static char * format_decimal ( char *end, signed long num, int width,
+ int flags ) {
+ char *ptr = end;
+ int negative = 0;
+ int zpad = ( flags & ZPAD );
+ int pad = ( zpad | ' ' );
+
+ /* Generate the number */
+ if ( num < 0 ) {
+ negative = 1;
+ num = -num;
+ }
+ do {
+ *(--ptr) = '0' + ( num % 10 );
+ num /= 10;
+ } while ( num );
+
+ /* Add "-" if necessary */
+ if ( negative && ( ! zpad ) )
+ *(--ptr) = '-';
+
+ /* Pad to width */
+ while ( ( end - ptr ) < width )
+ *(--ptr) = pad;
+
+ /* Add "-" if necessary */
+ if ( negative && zpad )
+ *ptr = '-';
+
+ return ptr;
+}
+
+/**
+ * Print character via a printf context
+ *
+ * @v ctx Context
+ * @v c Character
+ *
+ * Call's the printf_context::handler() method and increments
+ * printf_context::len.
+ */
+static inline void cputchar ( struct printf_context *ctx, unsigned int c ) {
+ ctx->handler ( ctx, c );
+ ++ctx->len;
+}
+
+/**
+ * Write a formatted string to a printf context
+ *
+ * @v ctx Context
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
+ int flags;
+ int width;
+ uint8_t *length;
+ char *ptr;
+ char tmp_buf[32]; /* 32 is enough for all numerical formats.
+ * Insane width fields could overflow this buffer. */
+
+ /* Initialise context */
+ ctx->len = 0;
+
+ for ( ; *fmt ; fmt++ ) {
+ /* Pass through ordinary characters */
+ if ( *fmt != '%' ) {
+ cputchar ( ctx, *fmt );
+ continue;
+ }
+ fmt++;
+ /* Process flag characters */
+ flags = 0;
+ for ( ; ; fmt++ ) {
+ if ( *fmt == '#' ) {
+ flags |= ALT_FORM;
+ } else if ( *fmt == '0' ) {
+ flags |= ZPAD;
+ } else {
+ /* End of flag characters */
+ break;
+ }
+ }
+ /* Process field width */
+ width = 0;
+ for ( ; ; fmt++ ) {
+ if ( ( ( unsigned ) ( *fmt - '0' ) ) < 10 ) {
+ width = ( width * 10 ) + ( *fmt - '0' );
+ } else {
+ break;
+ }
+ }
+ /* We don't do floating point */
+ /* Process length modifier */
+ length = &type_sizes[INT_LEN];
+ for ( ; ; fmt++ ) {
+ if ( *fmt == 'h' ) {
+ length--;
+ } else if ( *fmt == 'l' ) {
+ length++;
+ } else if ( *fmt == 'z' ) {
+ length = &type_sizes[SIZE_T_LEN];
+ } else {
+ break;
+ }
+ }
+ /* Process conversion specifier */
+ ptr = tmp_buf + sizeof ( tmp_buf ) - 1;
+ *ptr = '\0';
+ if ( *fmt == 'c' ) {
+ cputchar ( ctx, va_arg ( args, unsigned int ) );
+ } else if ( *fmt == 's' ) {
+ ptr = va_arg ( args, char * );
+ if ( ! ptr )
+ ptr = "<NULL>";
+ } else if ( *fmt == 'p' ) {
+ intptr_t ptrval;
+
+ ptrval = ( intptr_t ) va_arg ( args, void * );
+ ptr = format_hex ( ptr, ptrval, width,
+ ( ALT_FORM | LCASE ) );
+ } else if ( ( *fmt & ~0x20 ) == 'X' ) {
+ unsigned long long hex;
+
+ flags |= ( *fmt & 0x20 ); /* LCASE */
+ if ( *length >= sizeof ( unsigned long long ) ) {
+ hex = va_arg ( args, unsigned long long );
+ } else if ( *length >= sizeof ( unsigned long ) ) {
+ hex = va_arg ( args, unsigned long );
+ } else {
+ hex = va_arg ( args, unsigned int );
+ }
+ ptr = format_hex ( ptr, hex, width, flags );
+ } else if ( ( *fmt == 'd' ) || ( *fmt == 'i' ) ){
+ signed long decimal;
+
+ if ( *length >= sizeof ( signed long ) ) {
+ decimal = va_arg ( args, signed long );
+ } else {
+ decimal = va_arg ( args, signed int );
+ }
+ ptr = format_decimal ( ptr, decimal, width, flags );
+ } else {
+ *(--ptr) = *fmt;
+ }
+ /* Write out conversion result */
+ for ( ; *ptr ; ptr++ ) {
+ cputchar ( ctx, *ptr );
+ }
+ }
+
+ return ctx->len;
+}
+
+/** Context used by vsnprintf() and friends */
+struct sputc_context {
+ struct printf_context ctx;
+ /** Buffer for formatted string (used by printf_sputc()) */
+ char *buf;
+ /** Buffer length (used by printf_sputc()) */
+ size_t max_len;
+};
+
+/**
+ * Write character to buffer
+ *
+ * @v ctx Context
+ * @v c Character
+ */
+static void printf_sputc ( struct printf_context *ctx, unsigned int c ) {
+ struct sputc_context * sctx =
+ container_of ( ctx, struct sputc_context, ctx );
+
+ if ( ctx->len < sctx->max_len )
+ sctx->buf[ctx->len] = c;
+}
+
+/**
+ * Write a formatted string to a buffer
+ *
+ * @v buf Buffer into which to write the string
+ * @v size Size of buffer
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ *
+ * If the buffer is too small to contain the string, the returned
+ * length is the length that would have been written had enough space
+ * been available.
+ */
+int vsnprintf ( char *buf, size_t size, const char *fmt, va_list args ) {
+ struct sputc_context sctx;
+ size_t len;
+ size_t end;
+
+ /* Hand off to vcprintf */
+ sctx.ctx.handler = printf_sputc;
+ sctx.buf = buf;
+ sctx.max_len = size;
+ len = vcprintf ( &sctx.ctx, fmt, args );
+
+ /* Add trailing NUL */
+ if ( size ) {
+ end = size - 1;
+ if ( len < end )
+ end = len;
+ buf[end] = '\0';
+ }
+
+ return len;
+}
+
+/**
+ * Write a formatted string to a buffer
+ *
+ * @v buf Buffer into which to write the string
+ * @v size Size of buffer
+ * @v fmt Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+int snprintf ( char *buf, size_t size, const char *fmt, ... ) {
+ va_list args;
+ int i;
+
+ va_start ( args, fmt );
+ i = vsnprintf ( buf, size, fmt, args );
+ va_end ( args );
+ return i;
+}
+
+/**
+ * Version of vsnprintf() that accepts a signed buffer size
+ *
+ * @v buf Buffer into which to write the string
+ * @v size Size of buffer
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+int vssnprintf ( char *buf, ssize_t ssize, const char *fmt, va_list args ) {
+
+ /* Treat negative buffer size as zero buffer size */
+ if ( ssize < 0 )
+ ssize = 0;
+
+ /* Hand off to vsnprintf */
+ return vsnprintf ( buf, ssize, fmt, args );
+}
+
+/**
+ * Version of vsnprintf() that accepts a signed buffer size
+ *
+ * @v buf Buffer into which to write the string
+ * @v size Size of buffer
+ * @v fmt Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+int ssnprintf ( char *buf, ssize_t ssize, const char *fmt, ... ) {
+ va_list args;
+ int len;
+
+ /* Hand off to vssnprintf */
+ va_start ( args, fmt );
+ len = vssnprintf ( buf, ssize, fmt, args );
+ va_end ( args );
+ return len;
+}
+
+/**
+ * Write character to console
+ *
+ * @v ctx Context
+ * @v c Character
+ */
+static void printf_putchar ( struct printf_context *ctx __unused,
+ unsigned int c ) {
+ putchar ( c );
+}
+
+/**
+ * Write a formatted string to the console
+ *
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+int vprintf ( const char *fmt, va_list args ) {
+ struct printf_context ctx;
+
+ /* Hand off to vcprintf */
+ ctx.handler = printf_putchar;
+ return vcprintf ( &ctx, fmt, args );
+}
+
+/**
+ * Write a formatted string to the console.
+ *
+ * @v fmt Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+int printf ( const char *fmt, ... ) {
+ va_list args;
+ int i;
+
+ va_start ( args, fmt );
+ i = vprintf ( fmt, args );
+ va_end ( args );
+ return i;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/xfer.c b/src/VBox/Devices/PC/ipxe/src/core/xfer.c
new file mode 100644
index 00000000..037c089a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/xfer.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+
+/** @file
+ *
+ * Data transfer interfaces
+ *
+ */
+
+/**
+ * Dummy transfer metadata
+ *
+ * This gets passed to xfer_interface::deliver() and equivalents when
+ * no metadata is available.
+ */
+static struct xfer_metadata dummy_metadata;
+
+/*****************************************************************************
+ *
+ * Data transfer interface operations
+ *
+ */
+
+/**
+ * Send redirection event
+ *
+ * @v intf Data transfer interface
+ * @v type New location type
+ * @v args Remaining arguments depend upon location type
+ * @ret rc Return status code
+ */
+int xfer_vredirect ( struct interface *intf, int type, va_list args ) {
+ struct interface tmp = INTF_INIT ( null_intf_desc );
+ struct interface *dest;
+ xfer_vredirect_TYPE ( void * ) *op =
+ intf_get_dest_op_no_passthru ( intf, xfer_vredirect, &dest );
+ void *object = intf_object ( dest );
+ int rc;
+
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect\n",
+ INTF_INTF_DBG ( intf, dest ) );
+
+ if ( op ) {
+ rc = op ( object, type, args );
+ } else {
+ /* Default is to reopen the interface as instructed,
+ * then send xfer_window_changed() messages to both
+ * new child and parent interfaces. Since our
+ * original child interface is likely to be closed and
+ * unplugged as a result of the call to
+ * xfer_vreopen(), we create a temporary interface in
+ * order to be able to send xfer_window_changed() to
+ * the parent.
+ */
+ intf_plug ( &tmp, dest );
+ rc = xfer_vreopen ( dest, type, args );
+ if ( rc == 0 ) {
+ xfer_window_changed ( dest );
+ xfer_window_changed ( &tmp );
+ }
+ intf_unplug ( &tmp );
+ }
+
+ if ( rc != 0 ) {
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect "
+ "failed: %s\n", INTF_INTF_DBG ( intf, dest ),
+ strerror ( rc ) );
+ }
+
+ intf_put ( dest );
+ return rc;
+}
+
+/**
+ * Check flow control window
+ *
+ * @v intf Data transfer interface
+ * @ret len Length of window
+ */
+size_t xfer_window ( struct interface *intf ) {
+ struct interface *dest;
+ xfer_window_TYPE ( void * ) *op =
+ intf_get_dest_op ( intf, xfer_window, &dest );
+ void *object = intf_object ( dest );
+ size_t len;
+
+ if ( op ) {
+ len = op ( object );
+ } else {
+ /* Default is to provide an unlimited window */
+ len = ~( ( size_t ) 0 );
+ }
+
+ intf_put ( dest );
+ return len;
+}
+
+/**
+ * Report change of flow control window
+ *
+ * @v intf Data transfer interface
+ *
+ * Note that this method is used to indicate only unsolicited changes
+ * in the flow control window. In particular, this method must not be
+ * called as part of the response to xfer_deliver(), since that could
+ * easily lead to an infinite loop. Callers of xfer_deliver() should
+ * assume that the flow control window will have changed without
+ * generating an xfer_window_changed() message.
+ */
+void xfer_window_changed ( struct interface *intf ) {
+ struct interface *dest;
+ xfer_window_changed_TYPE ( void * ) *op =
+ intf_get_dest_op ( intf, xfer_window_changed, &dest );
+ void *object = intf_object ( dest );
+
+ if ( op ) {
+ op ( object );
+ } else {
+ /* Default is to do nothing */
+ }
+
+ intf_put ( dest );
+}
+
+/**
+ * Allocate I/O buffer
+ *
+ * @v intf Data transfer interface
+ * @v len I/O buffer payload length
+ * @ret iobuf I/O buffer
+ */
+struct io_buffer * xfer_alloc_iob ( struct interface *intf, size_t len ) {
+ struct interface *dest;
+ xfer_alloc_iob_TYPE ( void * ) *op =
+ intf_get_dest_op ( intf, xfer_alloc_iob, &dest );
+ void *object = intf_object ( dest );
+ struct io_buffer *iobuf;
+
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " alloc_iob %zd\n",
+ INTF_INTF_DBG ( intf, dest ), len );
+
+ if ( op ) {
+ iobuf = op ( object, len );
+ } else {
+ /* Default is to allocate an I/O buffer with no
+ * reserved space.
+ */
+ iobuf = alloc_iob ( len );
+ }
+
+ if ( ! iobuf ) {
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " alloc_iob "
+ "failed\n", INTF_INTF_DBG ( intf, dest ) );
+ }
+
+ intf_put ( dest );
+ return iobuf;
+}
+
+/**
+ * Deliver datagram
+ *
+ * @v intf Data transfer interface
+ * @v iobuf Datagram I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+int xfer_deliver ( struct interface *intf,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct interface *dest;
+ xfer_deliver_TYPE ( void * ) *op =
+ intf_get_dest_op ( intf, xfer_deliver, &dest );
+ void *object = intf_object ( dest );
+ int rc;
+
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " deliver %zd\n",
+ INTF_INTF_DBG ( intf, dest ), iob_len ( iobuf ) );
+
+ if ( op ) {
+ rc = op ( object, iobuf, meta );
+ } else {
+ /* Default is to discard the I/O buffer */
+ free_iob ( iobuf );
+ rc = -EPIPE;
+ }
+
+ if ( rc != 0 ) {
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT
+ " deliver failed: %s\n",
+ INTF_INTF_DBG ( intf, dest ), strerror ( rc ) );
+ }
+
+ intf_put ( dest );
+ return rc;
+}
+
+/*****************************************************************************
+ *
+ * Data transfer interface helper functions
+ *
+ */
+
+/**
+ * Send redirection event
+ *
+ * @v intf Data transfer interface
+ * @v type New location type
+ * @v ... Remaining arguments depend upon location type
+ * @ret rc Return status code
+ */
+int xfer_redirect ( struct interface *intf, int type, ... ) {
+ va_list args;
+ int rc;
+
+ va_start ( args, type );
+ rc = xfer_vredirect ( intf, type, args );
+ va_end ( args );
+ return rc;
+}
+
+/**
+ * Deliver datagram as I/O buffer without metadata
+ *
+ * @v intf Data transfer interface
+ * @v iobuf Datagram I/O buffer
+ * @ret rc Return status code
+ */
+int xfer_deliver_iob ( struct interface *intf, struct io_buffer *iobuf ) {
+ return xfer_deliver ( intf, iobuf, &dummy_metadata );
+}
+
+/**
+ * Deliver datagram as raw data
+ *
+ * @v intf Data transfer interface
+ * @v data Data
+ * @v len Length of data
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+int xfer_deliver_raw_meta ( struct interface *intf, const void *data,
+ size_t len, struct xfer_metadata *meta ) {
+ struct io_buffer *iobuf;
+
+ iobuf = xfer_alloc_iob ( intf, len );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ memcpy ( iob_put ( iobuf, len ), data, len );
+ return xfer_deliver ( intf, iobuf, meta );
+}
+
+/**
+ * Deliver datagram as raw data without metadata
+ *
+ * @v intf Data transfer interface
+ * @v data Data
+ * @v len Length of data
+ * @ret rc Return status code
+ */
+int xfer_deliver_raw ( struct interface *intf, const void *data, size_t len ) {
+ return xfer_deliver_raw_meta ( intf, data, len, &dummy_metadata );
+}
+
+/**
+ * Deliver formatted string
+ *
+ * @v intf Data transfer interface
+ * @v format Format string
+ * @v args Arguments corresponding to the format string
+ * @ret rc Return status code
+ */
+int xfer_vprintf ( struct interface *intf, const char *format,
+ va_list args ) {
+ va_list args_tmp;
+ char *buf;
+ int len;
+ int rc;
+
+ /* Create temporary string */
+ va_copy ( args_tmp, args );
+ len = vasprintf ( &buf, format, args );
+ if ( len < 0 ) {
+ rc = len;
+ goto err_asprintf;
+ }
+ va_end ( args_tmp );
+
+ /* Transmit string */
+ if ( ( rc = xfer_deliver_raw ( intf, buf, len ) ) != 0 )
+ goto err_deliver;
+
+ err_deliver:
+ free ( buf );
+ err_asprintf:
+ return rc;
+}
+
+/**
+ * Deliver formatted string
+ *
+ * @v intf Data transfer interface
+ * @v format Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret rc Return status code
+ */
+int xfer_printf ( struct interface *intf, const char *format, ... ) {
+ va_list args;
+ int rc;
+
+ va_start ( args, format );
+ rc = xfer_vprintf ( intf, format, args );
+ va_end ( args );
+ return rc;
+}
+
+/**
+ * Seek to position
+ *
+ * @v intf Data transfer interface
+ * @v offset Offset to new position
+ * @ret rc Return status code
+ */
+int xfer_seek ( struct interface *intf, off_t offset ) {
+ struct io_buffer *iobuf;
+ struct xfer_metadata meta = {
+ .flags = XFER_FL_ABS_OFFSET,
+ .offset = offset,
+ };
+
+ DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " seek to %ld\n",
+ INTF_DBG ( intf ), offset );
+
+ /* Allocate and send a zero-length data buffer */
+ iobuf = xfer_alloc_iob ( intf, 0 );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ return xfer_deliver ( intf, iobuf, &meta );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/core/xferbuf.c b/src/VBox/Devices/PC/ipxe/src/core/xferbuf.c
new file mode 100644
index 00000000..b82bce86
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/core/xferbuf.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/xfer.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xferbuf.h>
+
+/** @file
+ *
+ * Data transfer buffer
+ *
+ */
+
+/**
+ * Finish using data transfer buffer
+ *
+ * @v xferbuf Data transfer buffer
+ */
+void xferbuf_done ( struct xfer_buffer *xferbuf ) {
+ free ( xferbuf->data );
+ xferbuf->data = NULL;
+ xferbuf->len = 0;
+ xferbuf->pos = 0;
+}
+
+/**
+ * Ensure that data transfer buffer is large enough for the specified size
+ *
+ * @v xferbuf Data transfer buffer
+ * @v len Required minimum size
+ * @ret rc Return status code
+ */
+static int xferbuf_ensure_size ( struct xfer_buffer *xferbuf, size_t len ) {
+ void *new_data;
+
+ /* If buffer is already large enough, do nothing */
+ if ( len <= xferbuf->len )
+ return 0;
+
+ /* Extend buffer */
+ new_data = realloc ( xferbuf->data, len );
+ if ( ! new_data ) {
+ DBGC ( xferbuf, "XFERBUF %p could not extend buffer to "
+ "%zd bytes\n", xferbuf, len );
+ return -ENOSPC;
+ }
+ xferbuf->data = new_data;
+ xferbuf->len = len;
+
+ return 0;
+}
+
+/**
+ * Add received data to data transfer buffer
+ *
+ * @v xferbuf Data transfer buffer
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+int xferbuf_deliver ( struct xfer_buffer *xferbuf, struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ size_t len;
+ size_t max;
+ int rc;
+
+ /* Calculate new buffer position */
+ if ( meta->flags & XFER_FL_ABS_OFFSET )
+ xferbuf->pos = 0;
+ xferbuf->pos += meta->offset;
+
+ /* Ensure that we have enough buffer space for this data */
+ len = iob_len ( iobuf );
+ max = ( xferbuf->pos + len );
+ if ( ( rc = xferbuf_ensure_size ( xferbuf, max ) ) != 0 )
+ goto done;
+
+ /* Copy data to buffer */
+ memcpy ( ( xferbuf->data + xferbuf->pos ), iobuf->data, len );
+
+ /* Update current buffer position */
+ xferbuf->pos += len;
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/aes_wrap.c b/src/VBox/Devices/PC/ipxe/src/crypto/aes_wrap.c
new file mode 100644
index 00000000..f59fbf91
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/aes_wrap.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <string.h>
+#include <ipxe/crypto.h>
+#include <ipxe/aes.h>
+
+/**
+ * Wrap a key or other data using AES Key Wrap (RFC 3394)
+ *
+ * @v kek Key Encryption Key, 16 bytes
+ * @v src Data to encrypt
+ * @v nblk Number of 8-byte blocks in @a data
+ * @ret dest Encrypted data (8 bytes longer than input)
+ *
+ * The algorithm is implemented such that @a src and @a dest may point
+ * to the same buffer.
+ */
+int aes_wrap ( const void *kek, const void *src, void *dest, int nblk )
+{
+ u8 *A = dest;
+ u8 B[16];
+ u8 *R;
+ int i, j;
+ void *aes_ctx = malloc ( AES_CTX_SIZE );
+
+ if ( ! aes_ctx )
+ return -1;
+
+ cipher_setkey ( &aes_algorithm, aes_ctx, kek, 16 );
+
+ /* Set up */
+ memset ( A, 0xA6, 8 );
+ memmove ( dest + 8, src, nblk * 8 );
+
+ /* Wrap */
+ for ( j = 0; j < 6; j++ ) {
+ R = dest + 8;
+ for ( i = 1; i <= nblk; i++ ) {
+ memcpy ( B, A, 8 );
+ memcpy ( B + 8, R, 8 );
+ cipher_encrypt ( &aes_algorithm, aes_ctx, B, B, 16 );
+ memcpy ( A, B, 8 );
+ A[7] ^= ( nblk * j ) + i;
+ memcpy ( R, B + 8, 8 );
+ R += 8;
+ }
+ }
+
+ free ( aes_ctx );
+ return 0;
+}
+
+/**
+ * Unwrap a key or other data using AES Key Wrap (RFC 3394)
+ *
+ * @v kek Key Encryption Key, 16 bytes
+ * @v src Data to decrypt
+ * @v nblk Number of 8-byte blocks in @e plaintext key
+ * @ret dest Decrypted data (8 bytes shorter than input)
+ * @ret rc Zero on success, nonzero on IV mismatch
+ *
+ * The algorithm is implemented such that @a src and @a dest may point
+ * to the same buffer.
+ */
+int aes_unwrap ( const void *kek, const void *src, void *dest, int nblk )
+{
+ u8 A[8], B[16];
+ u8 *R;
+ int i, j;
+ void *aes_ctx = malloc ( AES_CTX_SIZE );
+
+ if ( ! aes_ctx )
+ return -1;
+
+ cipher_setkey ( &aes_algorithm, aes_ctx, kek, 16 );
+
+ /* Set up */
+ memcpy ( A, src, 8 );
+ memmove ( dest, src + 8, nblk * 8 );
+
+ /* Unwrap */
+ for ( j = 5; j >= 0; j-- ) {
+ R = dest + ( nblk - 1 ) * 8;
+ for ( i = nblk; i >= 1; i-- ) {
+ memcpy ( B, A, 8 );
+ memcpy ( B + 8, R, 8 );
+ B[7] ^= ( nblk * j ) + i;
+ cipher_decrypt ( &aes_algorithm, aes_ctx, B, B, 16 );
+ memcpy ( A, B, 8 );
+ memcpy ( R, B + 8, 8 );
+ R -= 8;
+ }
+ }
+
+ free ( aes_ctx );
+
+ /* Check IV */
+ for ( i = 0; i < 8; i++ ) {
+ if ( A[i] != 0xA6 )
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/arc4.c b/src/VBox/Devices/PC/ipxe/src/crypto/arc4.c
new file mode 100644
index 00000000..ab3325c8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/arc4.c
@@ -0,0 +1,131 @@
+/*
+ * The ARC4 stream cipher.
+ *
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/crypto.h>
+#include <ipxe/arc4.h>
+
+#define SWAP( ary, i, j ) \
+ ({ u8 temp = ary[i]; ary[i] = ary[j]; ary[j] = temp; })
+
+/**
+ * Set ARC4 key
+ *
+ * @v ctxv ARC4 encryption context
+ * @v keyv Key to set
+ * @v keylen Length of key
+ *
+ * If an initialisation vector is to be used, it should be prepended
+ * to the key; ARC4 does not implement the @c setiv function because
+ * there is no standard length for an initialisation vector in the
+ * cipher.
+ */
+static int arc4_setkey ( void *ctxv, const void *keyv, size_t keylen )
+{
+ struct arc4_ctx *ctx = ctxv;
+ const u8 *key = keyv;
+ u8 *S = ctx->state;
+ int i, j;
+
+ for ( i = 0; i < 256; i++ ) {
+ S[i] = i;
+ }
+
+ for ( i = j = 0; i < 256; i++ ) {
+ j = ( j + S[i] + key[i % keylen] ) & 0xff;
+ SWAP ( S, i, j );
+ }
+
+ ctx->i = ctx->j = 0;
+ return 0;
+}
+
+/**
+ * Perform ARC4 encryption or decryption
+ *
+ * @v ctxv ARC4 encryption context
+ * @v srcv Data to encrypt or decrypt
+ * @v dstv Location to store encrypted or decrypted data
+ * @v len Length of data to operate on
+ *
+ * ARC4 is a stream cipher that works by generating a stream of PRNG
+ * data based on the key, and XOR'ing it with the data to be
+ * encrypted. Since XOR is symmetric, encryption and decryption in
+ * ARC4 are the same operation.
+ *
+ * If you pass a @c NULL source or destination pointer, @a len
+ * keystream bytes will be consumed without encrypting any data.
+ */
+static void arc4_xor ( void *ctxv, const void *srcv, void *dstv,
+ size_t len )
+{
+ struct arc4_ctx *ctx = ctxv;
+ const u8 *src = srcv;
+ u8 *dst = dstv;
+ u8 *S = ctx->state;
+ int i = ctx->i, j = ctx->j;
+
+ while ( len-- ) {
+ i = ( i + 1 ) & 0xff;
+ j = ( j + S[i] ) & 0xff;
+ SWAP ( S, i, j );
+ if ( srcv && dstv )
+ *dst++ = *src++ ^ S[(S[i] + S[j]) & 0xff];
+ }
+
+ ctx->i = i;
+ ctx->j = j;
+}
+
+static void arc4_setiv ( void *ctx __unused, const void *iv __unused )
+{
+ /* ARC4 does not use a fixed-length IV */
+}
+
+
+/**
+ * Perform ARC4 encryption or decryption, skipping initial keystream bytes
+ *
+ * @v key ARC4 encryption key
+ * @v keylen Key length
+ * @v skip Number of bytes of keystream to skip
+ * @v src Message to encrypt or decrypt
+ * @v msglen Length of message
+ * @ret dst Encrypted or decrypted message
+ */
+void arc4_skip ( const void *key, size_t keylen, size_t skip,
+ const void *src, void *dst, size_t msglen )
+{
+ struct arc4_ctx ctx;
+ arc4_setkey ( &ctx, key, keylen );
+ arc4_xor ( &ctx, NULL, NULL, skip );
+ arc4_xor ( &ctx, src, dst, msglen );
+}
+
+struct cipher_algorithm arc4_algorithm = {
+ .name = "ARC4",
+ .ctxsize = ARC4_CTX_SIZE,
+ .blocksize = 1,
+ .setkey = arc4_setkey,
+ .setiv = arc4_setiv,
+ .encrypt = arc4_xor,
+ .decrypt = arc4_xor,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/asn1.c b/src/VBox/Devices/PC/ipxe/src/crypto/asn1.c
new file mode 100644
index 00000000..5fc37849
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/asn1.c
@@ -0,0 +1,840 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <time.h>
+#include <ipxe/tables.h>
+#include <ipxe/asn1.h>
+
+/** @file
+ *
+ * ASN.1 encoding
+ *
+ */
+
+/* Disambiguate the various error causes */
+#define EINVAL_ASN1_EMPTY \
+ __einfo_error ( EINFO_EINVAL_ASN1_EMPTY )
+#define EINFO_EINVAL_ASN1_EMPTY \
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, "Empty or underlength cursor" )
+#define EINVAL_ASN1_LEN_LEN \
+ __einfo_error ( EINFO_EINVAL_ASN1_LEN_LEN )
+#define EINFO_EINVAL_ASN1_LEN_LEN \
+ __einfo_uniqify ( EINFO_EINVAL, 0x02, "Length field overruns cursor" )
+#define EINVAL_ASN1_LEN \
+ __einfo_error ( EINFO_EINVAL_ASN1_LEN )
+#define EINFO_EINVAL_ASN1_LEN \
+ __einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )
+#define EINVAL_ASN1_BOOLEAN \
+ __einfo_error ( EINFO_EINVAL_ASN1_BOOLEAN )
+#define EINFO_EINVAL_ASN1_BOOLEAN \
+ __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid boolean" )
+#define EINVAL_ASN1_INTEGER \
+ __einfo_error ( EINFO_EINVAL_ASN1_INTEGER )
+#define EINFO_EINVAL_ASN1_INTEGER \
+ __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" )
+#define EINVAL_ASN1_TIME \
+ __einfo_error ( EINFO_EINVAL_ASN1_TIME )
+#define EINFO_EINVAL_ASN1_TIME \
+ __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid time" )
+#define EINVAL_ASN1_ALGORITHM \
+ __einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM )
+#define EINFO_EINVAL_ASN1_ALGORITHM \
+ __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" )
+#define EINVAL_BIT_STRING \
+ __einfo_error ( EINFO_EINVAL_BIT_STRING )
+#define EINFO_EINVAL_BIT_STRING \
+ __einfo_uniqify ( EINFO_EINVAL, 0x07, "Invalid bit string" )
+#define ENOTSUP_ALGORITHM \
+ __einfo_error ( EINFO_ENOTSUP_ALGORITHM )
+#define EINFO_ENOTSUP_ALGORITHM \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" )
+#define ENOTTY_ALGORITHM \
+ __einfo_error ( EINFO_ENOTTY_ALGORITHM )
+#define EINFO_ENOTTY_ALGORITHM \
+ __einfo_uniqify ( EINFO_ENOTTY, 0x01, "Inappropriate algorithm" )
+
+/**
+ * Invalidate ASN.1 object cursor
+ *
+ * @v cursor ASN.1 object cursor
+ */
+void asn1_invalidate_cursor ( struct asn1_cursor *cursor ) {
+ static uint8_t asn1_invalid_object[] = { ASN1_END, 0 };
+
+ cursor->data = asn1_invalid_object;
+ cursor->len = 0;
+}
+
+/**
+ * Start parsing ASN.1 object
+ *
+ * @v cursor ASN.1 object cursor
+ * @v type Expected type, or ASN1_ANY
+ * @ret len Length of object body, or negative error
+ *
+ * The object cursor will be updated to point to the start of the
+ * object body (i.e. the first byte following the length byte(s)), and
+ * the length of the object body (i.e. the number of bytes until the
+ * following object tag, if any) is returned.
+ */
+static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
+ unsigned int len_len;
+ unsigned int len;
+
+ /* Sanity check */
+ if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
+ if ( cursor->len )
+ DBGC ( cursor, "ASN1 %p too short\n", cursor );
+ return -EINVAL_ASN1_EMPTY;
+ }
+
+ /* Check the tag byte */
+ if ( ( type != ASN1_ANY ) && ( type != asn1_type ( cursor ) ) ) {
+ DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
+ cursor, type, *( ( uint8_t * ) cursor->data ) );
+ return -ENXIO;
+ }
+ cursor->data++;
+ cursor->len--;
+
+ /* Extract length of the length field and sanity check */
+ len_len = *( ( uint8_t * ) cursor->data );
+ if ( len_len & 0x80 ) {
+ len_len = ( len_len & 0x7f );
+ cursor->data++;
+ cursor->len--;
+ } else {
+ len_len = 1;
+ }
+ if ( cursor->len < len_len ) {
+ DBGC ( cursor, "ASN1 %p bad length field length %d (max "
+ "%zd)\n", cursor, len_len, cursor->len );
+ return -EINVAL_ASN1_LEN_LEN;
+ }
+
+ /* Extract the length and sanity check */
+ for ( len = 0 ; len_len ; len_len-- ) {
+ len <<= 8;
+ len |= *( ( uint8_t * ) cursor->data );
+ cursor->data++;
+ cursor->len--;
+ }
+ if ( cursor->len < len ) {
+ DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
+ cursor, len, cursor->len );
+ return -EINVAL_ASN1_LEN;
+ }
+
+ return len;
+}
+
+/**
+ * Enter ASN.1 object
+ *
+ * @v cursor ASN.1 object cursor
+ * @v type Expected type, or ASN1_ANY
+ * @ret rc Return status code
+ *
+ * The object cursor will be updated to point to the body of the
+ * current ASN.1 object. If any error occurs, the object cursor will
+ * be invalidated.
+ */
+int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
+ int len;
+
+ len = asn1_start ( cursor, type );
+ if ( len < 0 ) {
+ asn1_invalidate_cursor ( cursor );
+ return len;
+ }
+
+ cursor->len = len;
+ DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
+ cursor, type, len );
+
+ return 0;
+}
+
+/**
+ * Skip ASN.1 object if present
+ *
+ * @v cursor ASN.1 object cursor
+ * @v type Expected type, or ASN1_ANY
+ * @ret rc Return status code
+ *
+ * The object cursor will be updated to point to the next ASN.1
+ * object. If any error occurs, the object cursor will not be
+ * modified.
+ */
+int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
+ int len;
+
+ len = asn1_start ( cursor, type );
+ if ( len < 0 )
+ return len;
+
+ cursor->data += len;
+ cursor->len -= len;
+ DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
+ cursor, type, len );
+
+ if ( ! cursor->len ) {
+ DBGC ( cursor, "ASN1 %p reached end of object\n", cursor );
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+/**
+ * Skip ASN.1 object
+ *
+ * @v cursor ASN.1 object cursor
+ * @v type Expected type, or ASN1_ANY
+ * @ret rc Return status code
+ *
+ * The object cursor will be updated to point to the next ASN.1
+ * object. If any error occurs, the object cursor will be
+ * invalidated.
+ */
+int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
+ int rc;
+
+ if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) != 0 ) {
+ asn1_invalidate_cursor ( cursor );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Shrink ASN.1 cursor to fit object
+ *
+ * @v cursor ASN.1 object cursor
+ * @v type Expected type, or ASN1_ANY
+ * @ret rc Return status code
+ *
+ * The object cursor will be shrunk to contain only the current ASN.1
+ * object. If any error occurs, the object cursor will be
+ * invalidated.
+ */
+int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type ) {
+ struct asn1_cursor temp;
+ const void *end;
+ int len;
+
+ /* Find end of object */
+ memcpy ( &temp, cursor, sizeof ( temp ) );
+ len = asn1_start ( &temp, type );
+ if ( len < 0 ) {
+ asn1_invalidate_cursor ( cursor );
+ return len;
+ }
+ end = ( temp.data + len );
+
+ /* Shrink original cursor to contain only its first object */
+ cursor->len = ( end - cursor->data );
+
+ return 0;
+}
+
+/**
+ * Enter ASN.1 object of any type
+ *
+ * @v cursor ASN.1 object cursor
+ * @ret rc Return status code
+ */
+int asn1_enter_any ( struct asn1_cursor *cursor ) {
+ return asn1_enter ( cursor, ASN1_ANY );
+}
+
+/**
+ * Skip ASN.1 object of any type
+ *
+ * @v cursor ASN.1 object cursor
+ * @ret rc Return status code
+ */
+int asn1_skip_any ( struct asn1_cursor *cursor ) {
+ return asn1_skip ( cursor, ASN1_ANY );
+}
+
+/**
+ * Shrink ASN.1 object of any type
+ *
+ * @v cursor ASN.1 object cursor
+ * @ret rc Return status code
+ */
+int asn1_shrink_any ( struct asn1_cursor *cursor ) {
+ return asn1_shrink ( cursor, ASN1_ANY );
+}
+
+/**
+ * Parse value of ASN.1 boolean
+ *
+ * @v cursor ASN.1 object cursor
+ * @ret value Value, or negative error
+ */
+int asn1_boolean ( const struct asn1_cursor *cursor ) {
+ struct asn1_cursor contents;
+ const struct {
+ uint8_t value;
+ } __attribute__ (( packed )) *boolean;
+
+ /* Enter boolean */
+ memcpy ( &contents, cursor, sizeof ( contents ) );
+ asn1_enter ( &contents, ASN1_BOOLEAN );
+ if ( contents.len != sizeof ( *boolean ) )
+ return -EINVAL_ASN1_BOOLEAN;
+
+ /* Extract value */
+ boolean = contents.data;
+ return boolean->value;
+}
+
+/**
+ * Parse value of ASN.1 integer
+ *
+ * @v cursor ASN.1 object cursor
+ * @v value Value to fill in
+ * @ret rc Return status code
+ */
+int asn1_integer ( const struct asn1_cursor *cursor, int *value ) {
+ struct asn1_cursor contents;
+ uint8_t high_byte;
+ int rc;
+
+ /* Enter integer */
+ memcpy ( &contents, cursor, sizeof ( contents ) );
+ if ( ( rc = asn1_enter ( &contents, ASN1_INTEGER ) ) != 0 )
+ return rc;
+ if ( contents.len < 1 )
+ return -EINVAL_ASN1_INTEGER;
+
+ /* Initialise value according to sign byte */
+ *value = *( ( int8_t * ) contents.data );
+ contents.data++;
+ contents.len--;
+
+ /* Process value */
+ while ( contents.len ) {
+ high_byte = ( (*value) >> ( 8 * ( sizeof ( *value ) - 1 ) ) );
+ if ( ( high_byte != 0x00 ) && ( high_byte != 0xff ) ) {
+ DBGC ( cursor, "ASN1 %p integer overflow\n", cursor );
+ return -EINVAL_ASN1_INTEGER;
+ }
+ *value = ( ( *value << 8 ) | *( ( uint8_t * ) contents.data ) );
+ contents.data++;
+ contents.len--;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse ASN.1 bit string
+ *
+ * @v cursor ASN.1 cursor
+ * @v bits Bit string to fill in
+ * @ret rc Return status code
+ */
+int asn1_bit_string ( const struct asn1_cursor *cursor,
+ struct asn1_bit_string *bits ) {
+ struct asn1_cursor contents;
+ const struct {
+ uint8_t unused;
+ uint8_t data[0];
+ } __attribute__ (( packed )) *bit_string;
+ size_t len;
+ unsigned int unused;
+ uint8_t unused_mask;
+ const uint8_t *last;
+ int rc;
+
+ /* Enter bit string */
+ memcpy ( &contents, cursor, sizeof ( contents ) );
+ if ( ( rc = asn1_enter ( &contents, ASN1_BIT_STRING ) ) != 0 ) {
+ DBGC ( cursor, "ASN1 %p cannot locate bit string:\n", cursor );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return rc;
+ }
+
+ /* Validity checks */
+ if ( contents.len < sizeof ( *bit_string ) ) {
+ DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -EINVAL_BIT_STRING;
+ }
+ bit_string = contents.data;
+ len = ( contents.len - offsetof ( typeof ( *bit_string ), data ) );
+ unused = bit_string->unused;
+ unused_mask = ( 0xff >> ( 8 - unused ) );
+ last = ( bit_string->data + len - 1 );
+ if ( ( unused >= 8 ) ||
+ ( ( unused > 0 ) && ( len == 0 ) ) ||
+ ( ( *last & unused_mask ) != 0 ) ) {
+ DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -EINVAL_BIT_STRING;
+ }
+
+ /* Populate bit string */
+ bits->data = &bit_string->data;
+ bits->len = len;
+ bits->unused = unused;
+
+ return 0;
+}
+
+/**
+ * Parse ASN.1 bit string that must be an integral number of bytes
+ *
+ * @v cursor ASN.1 cursor
+ * @v bits Bit string to fill in
+ * @ret rc Return status code
+ */
+int asn1_integral_bit_string ( const struct asn1_cursor *cursor,
+ struct asn1_bit_string *bits ) {
+ int rc;
+
+ /* Parse bit string */
+ if ( ( rc = asn1_bit_string ( cursor, bits ) ) != 0 )
+ return rc;
+
+ /* Check that there are no unused bits at end of string */
+ if ( bits->unused ) {
+ DBGC ( cursor, "ASN1 %p invalid integral bit string:\n",
+ cursor );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -EINVAL_BIT_STRING;
+ }
+
+ return 0;
+}
+
+/**
+ * Compare two ASN.1 objects
+ *
+ * @v cursor1 ASN.1 object cursor
+ * @v cursor2 ASN.1 object cursor
+ * @ret difference Difference as returned by memcmp()
+ *
+ * Note that invalid and empty cursors will compare as equal with each
+ * other.
+ */
+int asn1_compare ( const struct asn1_cursor *cursor1,
+ const struct asn1_cursor *cursor2 ) {
+ int difference;
+
+ difference = ( cursor2->len - cursor1->len );
+ return ( difference ? difference :
+ memcmp ( cursor1->data, cursor2->data, cursor1->len ) );
+}
+
+/**
+ * Identify ASN.1 algorithm by OID
+ *
+ * @v cursor ASN.1 object cursor
+
+ * @ret algorithm Algorithm, or NULL
+ */
+static struct asn1_algorithm *
+asn1_find_algorithm ( const struct asn1_cursor *cursor ) {
+ struct asn1_algorithm *algorithm;
+
+ for_each_table_entry ( algorithm, ASN1_ALGORITHMS ) {
+ if ( asn1_compare ( &algorithm->oid, cursor ) == 0 )
+ return algorithm;
+ }
+
+ return NULL;
+}
+
+/**
+ * Parse ASN.1 OID-identified algorithm
+ *
+ * @v cursor ASN.1 object cursor
+ * @ret algorithm Algorithm
+ * @ret rc Return status code
+ */
+int asn1_algorithm ( const struct asn1_cursor *cursor,
+ struct asn1_algorithm **algorithm ) {
+ struct asn1_cursor contents;
+ int rc;
+
+ /* Enter signatureAlgorithm */
+ memcpy ( &contents, cursor, sizeof ( contents ) );
+ asn1_enter ( &contents, ASN1_SEQUENCE );
+
+ /* Enter algorithm */
+ if ( ( rc = asn1_enter ( &contents, ASN1_OID ) ) != 0 ) {
+ DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n",
+ cursor );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -EINVAL_ASN1_ALGORITHM;
+ }
+
+ /* Identify algorithm */
+ *algorithm = asn1_find_algorithm ( &contents );
+ if ( ! *algorithm ) {
+ DBGC ( cursor, "ASN1 %p unrecognised algorithm:\n", cursor );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -ENOTSUP_ALGORITHM;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse ASN.1 OID-identified public-key algorithm
+ *
+ * @v cursor ASN.1 object cursor
+ * @ret algorithm Algorithm
+ * @ret rc Return status code
+ */
+int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor,
+ struct asn1_algorithm **algorithm ) {
+ int rc;
+
+ /* Parse algorithm */
+ if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
+ return rc;
+
+ /* Check algorithm has a public key */
+ if ( ! (*algorithm)->pubkey ) {
+ DBGC ( cursor, "ASN1 %p algorithm %s is not a public-key "
+ "algorithm:\n", cursor, (*algorithm)->name );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -ENOTTY_ALGORITHM;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse ASN.1 OID-identified digest algorithm
+ *
+ * @v cursor ASN.1 object cursor
+ * @ret algorithm Algorithm
+ * @ret rc Return status code
+ */
+int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
+ struct asn1_algorithm **algorithm ) {
+ int rc;
+
+ /* Parse algorithm */
+ if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
+ return rc;
+
+ /* Check algorithm has a digest */
+ if ( ! (*algorithm)->digest ) {
+ DBGC ( cursor, "ASN1 %p algorithm %s is not a digest "
+ "algorithm:\n", cursor, (*algorithm)->name );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -ENOTTY_ALGORITHM;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse ASN.1 OID-identified signature algorithm
+ *
+ * @v cursor ASN.1 object cursor
+ * @ret algorithm Algorithm
+ * @ret rc Return status code
+ */
+int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
+ struct asn1_algorithm **algorithm ) {
+ int rc;
+
+ /* Parse algorithm */
+ if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
+ return rc;
+
+ /* Check algorithm has a public key */
+ if ( ! (*algorithm)->pubkey ) {
+ DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
+ "algorithm:\n", cursor, (*algorithm)->name );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -ENOTTY_ALGORITHM;
+ }
+
+ /* Check algorithm has a digest */
+ if ( ! (*algorithm)->digest ) {
+ DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
+ "algorithm:\n", cursor, (*algorithm)->name );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -ENOTTY_ALGORITHM;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse ASN.1 GeneralizedTime
+ *
+ * @v cursor ASN.1 cursor
+ * @v time Time to fill in
+ * @ret rc Return status code
+ *
+ * RFC 5280 section 4.1.2.5 places several restrictions on the allowed
+ * formats for UTCTime and GeneralizedTime, and mandates the
+ * interpretation of centuryless year values.
+ */
+int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) {
+ struct asn1_cursor contents;
+ unsigned int have_century;
+ unsigned int type;
+ union {
+ struct {
+ uint8_t century;
+ uint8_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+ } __attribute__ (( packed )) named;
+ uint8_t raw[7];
+ } pairs;
+ struct tm tm;
+ const uint8_t *data;
+ size_t remaining;
+ unsigned int tens;
+ unsigned int units;
+ unsigned int i;
+ int rc;
+
+ /* Determine time format utcTime/generalizedTime */
+ memcpy ( &contents, cursor, sizeof ( contents ) );
+ type = asn1_type ( &contents );
+ switch ( type ) {
+ case ASN1_UTC_TIME:
+ have_century = 0;
+ break;
+ case ASN1_GENERALIZED_TIME:
+ have_century = 1;
+ break;
+ default:
+ DBGC ( cursor, "ASN1 %p invalid time type %02x\n",
+ cursor, type );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -EINVAL_ASN1_TIME;
+ }
+
+ /* Enter utcTime/generalizedTime */
+ if ( ( rc = asn1_enter ( &contents, type ) ) != 0 ) {
+ DBGC ( cursor, "ASN1 %p cannot locate %s time:\n", cursor,
+ ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return rc;
+ }
+
+ /* Parse digit string a pair at a time */
+ data = contents.data;
+ remaining = contents.len;
+ for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) {
+ if ( remaining < 2 ) {
+ DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -EINVAL_ASN1_TIME;
+ }
+ tens = data[0];
+ units = data[1];
+ if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) {
+ DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -EINVAL_ASN1_TIME;
+ }
+ pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) );
+ data += 2;
+ remaining -= 2;
+ }
+
+ /* Determine century if applicable */
+ if ( ! have_century )
+ pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 );
+
+ /* Check for trailing "Z" */
+ if ( ( remaining != 1 ) || ( data[0] != 'Z' ) ) {
+ DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -EINVAL_ASN1_TIME;
+ }
+
+ /* Fill in time */
+ tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) +
+ pairs.named.year );
+ tm.tm_mon = ( pairs.named.month - 1 );
+ tm.tm_mday = pairs.named.day;
+ tm.tm_hour = pairs.named.hour;
+ tm.tm_min = pairs.named.minute;
+ tm.tm_sec = pairs.named.second;
+
+ /* Convert to seconds since the Epoch */
+ *time = mktime ( &tm );
+
+ return 0;
+}
+
+/**
+ * Construct ASN.1 header
+ *
+ * @v header ASN.1 builder header
+ * @v type Type
+ * @v len Content length
+ * @ret header_len Header length
+ */
+static size_t asn1_header ( struct asn1_builder_header *header,
+ unsigned int type, size_t len ) {
+ unsigned int header_len = 2;
+ unsigned int len_len = 0;
+ size_t temp;
+
+ /* Construct header */
+ header->type = type;
+ if ( len < 0x80 ) {
+ header->length[0] = len;
+ } else {
+ for ( temp = len ; temp ; temp >>= 8 )
+ len_len++;
+ header->length[0] = ( 0x80 | len_len );
+ header_len += len_len;
+ for ( temp = len ; temp ; temp >>= 8 )
+ header->length[len_len--] = ( temp & 0xff );
+ }
+
+ return header_len;
+}
+
+/**
+ * Grow ASN.1 builder
+ *
+ * @v builder ASN.1 builder
+ * @v extra Extra space to prepend
+ * @ret rc Return status code
+ */
+static int asn1_grow ( struct asn1_builder *builder, size_t extra ) {
+ size_t new_len;
+ void *new;
+
+ /* As with the ASN1 parsing functions, make errors permanent */
+ if ( builder->len && ! builder->data )
+ return -ENOMEM;
+
+ /* Reallocate data buffer */
+ new_len = ( builder->len + extra );
+ new = realloc ( builder->data, new_len );
+ if ( ! new ) {
+ free ( builder->data );
+ builder->data = NULL;
+ return -ENOMEM;
+ }
+ builder->data = new;
+
+ /* Move existing data to end of buffer */
+ memmove ( ( builder->data + extra ), builder->data, builder->len );
+ builder->len = new_len;
+
+ return 0;
+}
+
+/**
+ * Prepend raw data to ASN.1 builder
+ *
+ * @v builder ASN.1 builder
+ * @v data Data to prepend
+ * @v len Length of data to prepend
+ * @ret rc Return status code
+ */
+int asn1_prepend_raw ( struct asn1_builder *builder, const void *data,
+ size_t len ) {
+ int rc;
+
+ /* Grow buffer */
+ if ( ( rc = asn1_grow ( builder, len ) ) != 0 )
+ return rc;
+
+ /* Populate data buffer */
+ memcpy ( builder->data, data, len );
+
+ return 0;
+}
+
+/**
+ * Prepend data to ASN.1 builder
+ *
+ * @v builder ASN.1 builder
+ * @v type Type
+ * @v data Data to prepend
+ * @v len Length of data to prepend
+ * @ret rc Return status code
+ */
+int asn1_prepend ( struct asn1_builder *builder, unsigned int type,
+ const void *data, size_t len ) {
+ struct asn1_builder_header header;
+ size_t header_len;
+ int rc;
+
+ /* Construct header */
+ header_len = asn1_header ( &header, type, len );
+
+ /* Grow buffer */
+ if ( ( rc = asn1_grow ( builder, header_len + len ) ) != 0 )
+ return rc;
+
+ /* Populate data buffer */
+ memcpy ( builder->data, &header, header_len );
+ memcpy ( ( builder->data + header_len ), data, len );
+
+ return 0;
+}
+
+/**
+ * Wrap ASN.1 builder
+ *
+ * @v builder ASN.1 builder
+ * @v type Type
+ * @ret rc Return status code
+ */
+int asn1_wrap ( struct asn1_builder *builder, unsigned int type ) {
+ struct asn1_builder_header header;
+ size_t header_len;
+ int rc;
+
+ /* Construct header */
+ header_len = asn1_header ( &header, type, builder->len );
+
+ /* Grow buffer */
+ if ( ( rc = asn1_grow ( builder, header_len ) ) != 0 )
+ return rc;
+
+ /* Populate data buffer */
+ memcpy ( builder->data, &header, header_len );
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/axtls/aes.c b/src/VBox/Devices/PC/ipxe/src/crypto/axtls/aes.c
new file mode 100644
index 00000000..bd99a709
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/axtls/aes.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * AES implementation - this is a small code version. There are much faster
+ * versions around but they are much larger in size (i.e. they use large
+ * submix tables).
+ */
+
+#include <string.h>
+#include "os_port.h"
+#include "crypto.h"
+
+/* all commented out in skeleton mode */
+#ifndef CONFIG_SSL_SKELETON_MODE
+
+#define rot1(x) (((x) << 24) | ((x) >> 8))
+#define rot2(x) (((x) << 16) | ((x) >> 16))
+#define rot3(x) (((x) << 8) | ((x) >> 24))
+
+/*
+ * This cute trick does 4 'mul by two' at once. Stolen from
+ * Dr B. R. Gladman <brg@gladman.uk.net> but I'm sure the u-(u>>7) is
+ * a standard graphics trick
+ * The key to this is that we need to xor with 0x1b if the top bit is set.
+ * a 1xxx xxxx 0xxx 0xxx First we mask the 7bit,
+ * b 1000 0000 0000 0000 then we shift right by 7 putting the 7bit in 0bit,
+ * c 0000 0001 0000 0000 we then subtract (c) from (b)
+ * d 0111 1111 0000 0000 and now we and with our mask
+ * e 0001 1011 0000 0000
+ */
+#define mt 0x80808080
+#define ml 0x7f7f7f7f
+#define mh 0xfefefefe
+#define mm 0x1b1b1b1b
+#define mul2(x,t) ((t)=((x)&mt), \
+ ((((x)+(x))&mh)^(((t)-((t)>>7))&mm)))
+
+#define inv_mix_col(x,f2,f4,f8,f9) (\
+ (f2)=mul2(x,f2), \
+ (f4)=mul2(f2,f4), \
+ (f8)=mul2(f4,f8), \
+ (f9)=(x)^(f8), \
+ (f8)=((f2)^(f4)^(f8)), \
+ (f2)^=(f9), \
+ (f4)^=(f9), \
+ (f8)^=rot3(f2), \
+ (f8)^=rot2(f4), \
+ (f8)^rot1(f9))
+
+/*
+ * AES S-box
+ */
+static const uint8_t aes_sbox[256] =
+{
+ 0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,
+ 0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
+ 0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,
+ 0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
+ 0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,
+ 0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
+ 0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,
+ 0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
+ 0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,
+ 0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
+ 0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,
+ 0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
+ 0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,
+ 0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
+ 0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,
+ 0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
+ 0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,
+ 0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
+ 0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,
+ 0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
+ 0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,
+ 0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
+ 0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,
+ 0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
+ 0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,
+ 0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
+ 0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,
+ 0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
+ 0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,
+ 0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
+ 0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,
+ 0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16,
+};
+
+/*
+ * AES is-box
+ */
+static const uint8_t aes_isbox[256] =
+{
+ 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
+ 0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
+ 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,
+ 0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
+ 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,
+ 0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
+ 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,
+ 0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
+ 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,
+ 0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
+ 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,
+ 0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
+ 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,
+ 0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
+ 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,
+ 0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
+ 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,
+ 0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
+ 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,
+ 0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
+ 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,
+ 0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
+ 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,
+ 0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
+ 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,
+ 0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
+ 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,
+ 0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
+ 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,
+ 0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
+ 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
+ 0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+};
+
+static const unsigned char Rcon[30]=
+{
+ 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
+ 0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f,
+ 0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4,
+ 0xb3,0x7d,0xfa,0xef,0xc5,0x91,
+};
+
+/* ----- static functions ----- */
+static void AES_encrypt(const AES_CTX *ctx, uint32_t *data);
+static void AES_decrypt(const AES_CTX *ctx, uint32_t *data);
+
+/* Perform doubling in Galois Field GF(2^8) using the irreducible polynomial
+ x^8+x^4+x^3+x+1 */
+static unsigned char AES_xtime(uint32_t x)
+{
+ return (x&0x80) ? (x<<1)^0x1b : x<<1;
+}
+
+/**
+ * Set up AES with the key/iv and cipher size.
+ */
+void AES_set_key(AES_CTX *ctx, const uint8_t *key,
+ const uint8_t *iv, AES_MODE mode)
+{
+ int i, ii;
+ uint32_t *W, tmp, tmp2;
+ const unsigned char *ip;
+ int words;
+
+ switch (mode)
+ {
+ case AES_MODE_128:
+ i = 10;
+ words = 4;
+ break;
+
+ case AES_MODE_256:
+ i = 14;
+ words = 8;
+ break;
+
+ default: /* fail silently */
+ return;
+ }
+
+ ctx->rounds = i;
+ ctx->key_size = words;
+ W = ctx->ks;
+ for (i = 0; i < words; i+=2)
+ {
+ W[i+0]= ((uint32_t)key[ 0]<<24)|
+ ((uint32_t)key[ 1]<<16)|
+ ((uint32_t)key[ 2]<< 8)|
+ ((uint32_t)key[ 3] );
+ W[i+1]= ((uint32_t)key[ 4]<<24)|
+ ((uint32_t)key[ 5]<<16)|
+ ((uint32_t)key[ 6]<< 8)|
+ ((uint32_t)key[ 7] );
+ key += 8;
+ }
+
+ ip = Rcon;
+ ii = 4 * (ctx->rounds+1);
+ for (i = words; i<ii; i++)
+ {
+ tmp = W[i-1];
+
+ if ((i % words) == 0)
+ {
+ tmp2 =(uint32_t)aes_sbox[(tmp )&0xff]<< 8;
+ tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<<16;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<24;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>24) ];
+ tmp=tmp2^(((unsigned int)*ip)<<24);
+ ip++;
+ }
+
+ if ((words == 8) && ((i % words) == 4))
+ {
+ tmp2 =(uint32_t)aes_sbox[(tmp )&0xff] ;
+ tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<< 8;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<16;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>24) ]<<24;
+ tmp=tmp2;
+ }
+
+ W[i]=W[i-words]^tmp;
+ }
+
+ /* copy the iv across */
+ memcpy(ctx->iv, iv, 16);
+}
+
+/**
+ * Change a key for decryption.
+ */
+void AES_convert_key(AES_CTX *ctx)
+{
+ int i;
+ uint32_t *k,w,t1,t2,t3,t4;
+
+ k = ctx->ks;
+ k += 4;
+
+ for (i= ctx->rounds*4; i > 4; i--)
+ {
+ w= *k;
+ w = inv_mix_col(w,t1,t2,t3,t4);
+ *k++ =w;
+ }
+}
+
+/**
+ * Encrypt a byte sequence (with a block size 16) using the AES cipher.
+ */
+void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
+{
+ int i;
+ uint32_t tin[4], tout[4], iv[4];
+
+ memcpy(iv, ctx->iv, AES_IV_SIZE);
+ for (i = 0; i < 4; i++)
+ tout[i] = ntohl(iv[i]);
+
+ for (length -= AES_BLOCKSIZE; length >= 0; length -= AES_BLOCKSIZE)
+ {
+ uint32_t msg_32[4];
+ uint32_t out_32[4];
+ memcpy(msg_32, msg, AES_BLOCKSIZE);
+ msg += AES_BLOCKSIZE;
+
+ for (i = 0; i < 4; i++)
+ tin[i] = ntohl(msg_32[i])^tout[i];
+
+ AES_encrypt(ctx, tin);
+
+ for (i = 0; i < 4; i++)
+ {
+ tout[i] = tin[i];
+ out_32[i] = htonl(tout[i]);
+ }
+
+ memcpy(out, out_32, AES_BLOCKSIZE);
+ out += AES_BLOCKSIZE;
+ }
+
+ for (i = 0; i < 4; i++)
+ iv[i] = htonl(tout[i]);
+ memcpy(ctx->iv, iv, AES_IV_SIZE);
+}
+
+/**
+ * Decrypt a byte sequence (with a block size 16) using the AES cipher.
+ */
+void AES_cbc_decrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
+{
+ int i;
+ uint32_t tin[4], xor[4], tout[4], data[4], iv[4];
+
+ memcpy(iv, ctx->iv, AES_IV_SIZE);
+ for (i = 0; i < 4; i++)
+ xor[i] = ntohl(iv[i]);
+
+ for (length -= 16; length >= 0; length -= 16)
+ {
+ uint32_t msg_32[4];
+ uint32_t out_32[4];
+ memcpy(msg_32, msg, AES_BLOCKSIZE);
+ msg += AES_BLOCKSIZE;
+
+ for (i = 0; i < 4; i++)
+ {
+ tin[i] = ntohl(msg_32[i]);
+ data[i] = tin[i];
+ }
+
+ AES_decrypt(ctx, data);
+
+ for (i = 0; i < 4; i++)
+ {
+ tout[i] = data[i]^xor[i];
+ xor[i] = tin[i];
+ out_32[i] = htonl(tout[i]);
+ }
+
+ memcpy(out, out_32, AES_BLOCKSIZE);
+ out += AES_BLOCKSIZE;
+ }
+
+ for (i = 0; i < 4; i++)
+ iv[i] = htonl(xor[i]);
+ memcpy(ctx->iv, iv, AES_IV_SIZE);
+}
+
+/**
+ * Encrypt a single block (16 bytes) of data
+ */
+static void AES_encrypt(const AES_CTX *ctx, uint32_t *data)
+{
+ /* To make this code smaller, generate the sbox entries on the fly.
+ * This will have a really heavy effect upon performance.
+ */
+ uint32_t tmp[4];
+ uint32_t tmp1, old_a0, a0, a1, a2, a3, row;
+ int curr_rnd;
+ int rounds = ctx->rounds;
+ const uint32_t *k = ctx->ks;
+
+ /* Pre-round key addition */
+ for (row = 0; row < 4; row++)
+ data[row] ^= *(k++);
+
+ /* Encrypt one block. */
+ for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
+ {
+ /* Perform ByteSub and ShiftRow operations together */
+ for (row = 0; row < 4; row++)
+ {
+ a0 = (uint32_t)aes_sbox[(data[row%4]>>24)&0xFF];
+ a1 = (uint32_t)aes_sbox[(data[(row+1)%4]>>16)&0xFF];
+ a2 = (uint32_t)aes_sbox[(data[(row+2)%4]>>8)&0xFF];
+ a3 = (uint32_t)aes_sbox[(data[(row+3)%4])&0xFF];
+
+ /* Perform MixColumn iff not last round */
+ if (curr_rnd < (rounds - 1))
+ {
+ tmp1 = a0 ^ a1 ^ a2 ^ a3;
+ old_a0 = a0;
+ a0 ^= tmp1 ^ AES_xtime(a0 ^ a1);
+ a1 ^= tmp1 ^ AES_xtime(a1 ^ a2);
+ a2 ^= tmp1 ^ AES_xtime(a2 ^ a3);
+ a3 ^= tmp1 ^ AES_xtime(a3 ^ old_a0);
+ }
+
+ tmp[row] = ((a0 << 24) | (a1 << 16) | (a2 << 8) | a3);
+ }
+
+ /* KeyAddition - note that it is vital that this loop is separate from
+ the MixColumn operation, which must be atomic...*/
+ for (row = 0; row < 4; row++)
+ data[row] = tmp[row] ^ *(k++);
+ }
+}
+
+/**
+ * Decrypt a single block (16 bytes) of data
+ */
+static void AES_decrypt(const AES_CTX *ctx, uint32_t *data)
+{
+ uint32_t tmp[4];
+ uint32_t xt0,xt1,xt2,xt3,xt4,xt5,xt6;
+ uint32_t a0, a1, a2, a3, row;
+ int curr_rnd;
+ int rounds = ctx->rounds;
+ const uint32_t *k = ctx->ks + ((rounds+1)*4);
+
+ /* pre-round key addition */
+ for (row=4; row > 0;row--)
+ data[row-1] ^= *(--k);
+
+ /* Decrypt one block */
+ for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
+ {
+ /* Perform ByteSub and ShiftRow operations together */
+ for (row = 4; row > 0; row--)
+ {
+ a0 = aes_isbox[(data[(row+3)%4]>>24)&0xFF];
+ a1 = aes_isbox[(data[(row+2)%4]>>16)&0xFF];
+ a2 = aes_isbox[(data[(row+1)%4]>>8)&0xFF];
+ a3 = aes_isbox[(data[row%4])&0xFF];
+
+ /* Perform MixColumn iff not last round */
+ if (curr_rnd<(rounds-1))
+ {
+ /* The MDS cofefficients (0x09, 0x0B, 0x0D, 0x0E)
+ are quite large compared to encryption; this
+ operation slows decryption down noticeably. */
+ xt0 = AES_xtime(a0^a1);
+ xt1 = AES_xtime(a1^a2);
+ xt2 = AES_xtime(a2^a3);
+ xt3 = AES_xtime(a3^a0);
+ xt4 = AES_xtime(xt0^xt1);
+ xt5 = AES_xtime(xt1^xt2);
+ xt6 = AES_xtime(xt4^xt5);
+
+ xt0 ^= a1^a2^a3^xt4^xt6;
+ xt1 ^= a0^a2^a3^xt5^xt6;
+ xt2 ^= a0^a1^a3^xt4^xt6;
+ xt3 ^= a0^a1^a2^xt5^xt6;
+ tmp[row-1] = ((xt0<<24)|(xt1<<16)|(xt2<<8)|xt3);
+ }
+ else
+ tmp[row-1] = ((a0<<24)|(a1<<16)|(a2<<8)|a3);
+ }
+
+ for (row = 4; row > 0; row--)
+ data[row-1] = tmp[row-1] ^ *(--k);
+ }
+}
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/axtls/bigint.h b/src/VBox/Devices/PC/ipxe/src/crypto/axtls/bigint.h
new file mode 100644
index 00000000..1f38c53d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/axtls/bigint.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BIGINT_HEADER
+#define BIGINT_HEADER
+
+#include "crypto.h"
+
+BI_CTX *bi_initialize(void);
+void bi_terminate(BI_CTX *ctx);
+void bi_permanent(bigint *bi);
+void bi_depermanent(bigint *bi);
+void bi_clear_cache(BI_CTX *ctx);
+void bi_free(BI_CTX *ctx, bigint *bi);
+bigint *bi_copy(bigint *bi);
+bigint *bi_clone(BI_CTX *ctx, const bigint *bi);
+void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size);
+bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len);
+bigint *int_to_bi(BI_CTX *ctx, comp i);
+
+/* the functions that actually do something interesting */
+bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib);
+bigint *bi_subtract(BI_CTX *ctx, bigint *bia,
+ bigint *bib, int *is_negative);
+bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod);
+bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib);
+bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp);
+bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp);
+int bi_compare(bigint *bia, bigint *bib);
+void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset);
+void bi_free_mod(BI_CTX *ctx, int mod_offset);
+
+#ifdef CONFIG_SSL_FULL_MODE
+void bi_print(const char *label, bigint *bi);
+bigint *bi_str_import(BI_CTX *ctx, const char *data);
+#endif
+
+/**
+ * @def bi_mod
+ * Find the residue of B. bi_set_mod() must be called before hand.
+ */
+#define bi_mod(A, B) bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1)
+
+/**
+ * bi_residue() is technically the same as bi_mod(), but it uses the
+ * appropriate reduction technique (which is bi_mod() when doing classical
+ * reduction).
+ */
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+#define bi_residue(A, B) bi_mont(A, B)
+bigint *bi_mont(BI_CTX *ctx, bigint *bixy);
+#elif defined(CONFIG_BIGINT_BARRETT)
+#define bi_residue(A, B) bi_barrett(A, B)
+bigint *bi_barrett(BI_CTX *ctx, bigint *bi);
+#else /* if defined(CONFIG_BIGINT_CLASSICAL) */
+#define bi_residue(A, B) bi_mod(A, B)
+#endif
+
+#ifdef CONFIG_BIGINT_SQUARE
+bigint *bi_square(BI_CTX *ctx, bigint *bi);
+#else
+#define bi_square(A, B) bi_multiply(A, bi_copy(B), B)
+#endif
+
+#ifdef CONFIG_BIGINT_CRT
+bigint *bi_crt(BI_CTX *ctx, bigint *bi,
+ bigint *dP, bigint *dQ,
+ bigint *p, bigint *q,
+ bigint *qInv);
+#endif
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/axtls/bigint_impl.h b/src/VBox/Devices/PC/ipxe/src/crypto/axtls/bigint_impl.h
new file mode 100644
index 00000000..09d8550e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/axtls/bigint_impl.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BIGINT_IMPL_HEADER
+#define BIGINT_IMPL_HEADER
+
+/* Maintain a number of precomputed variables when doing reduction */
+#define BIGINT_M_OFFSET 0 /**< Normal modulo offset. */
+#ifdef CONFIG_BIGINT_CRT
+#define BIGINT_P_OFFSET 1 /**< p modulo offset. */
+#define BIGINT_Q_OFFSET 2 /**< q module offset. */
+#define BIGINT_NUM_MODS 3 /**< The number of modulus constants used. */
+#else
+#define BIGINT_NUM_MODS 1
+#endif
+
+/* Architecture specific functions for big ints */
+#if defined(CONFIG_INTEGER_8BIT)
+#define COMP_RADIX 256U /**< Max component + 1 */
+#define COMP_MAX 0xFFFFU/**< (Max dbl comp -1) */
+#define COMP_BIT_SIZE 8 /**< Number of bits in a component. */
+#define COMP_BYTE_SIZE 1 /**< Number of bytes in a component. */
+#define COMP_NUM_NIBBLES 2 /**< Used For diagnostics only. */
+typedef uint8_t comp; /**< A single precision component. */
+typedef uint16_t long_comp; /**< A double precision component. */
+typedef int16_t slong_comp; /**< A signed double precision component. */
+#elif defined(CONFIG_INTEGER_16BIT)
+#define COMP_RADIX 65536U /**< Max component + 1 */
+#define COMP_MAX 0xFFFFFFFFU/**< (Max dbl comp -1) */
+#define COMP_BIT_SIZE 16 /**< Number of bits in a component. */
+#define COMP_BYTE_SIZE 2 /**< Number of bytes in a component. */
+#define COMP_NUM_NIBBLES 4 /**< Used For diagnostics only. */
+typedef uint16_t comp; /**< A single precision component. */
+typedef uint32_t long_comp; /**< A double precision component. */
+typedef int32_t slong_comp; /**< A signed double precision component. */
+#else /* regular 32 bit */
+#ifdef WIN32
+#define COMP_RADIX 4294967296i64
+#define COMP_MAX 0xFFFFFFFFFFFFFFFFui64
+#else
+#define COMP_RADIX 4294967296ULL /**< Max component + 1 */
+#define COMP_MAX 0xFFFFFFFFFFFFFFFFULL/**< (Max dbl comp -1) */
+#endif
+#define COMP_BIT_SIZE 32 /**< Number of bits in a component. */
+#define COMP_BYTE_SIZE 4 /**< Number of bytes in a component. */
+#define COMP_NUM_NIBBLES 8 /**< Used For diagnostics only. */
+typedef uint32_t comp; /**< A single precision component. */
+typedef uint64_t long_comp; /**< A double precision component. */
+typedef int64_t slong_comp; /**< A signed double precision component. */
+#endif
+
+/**
+ * @struct _bigint
+ * @brief A big integer basic object
+ */
+struct _bigint
+{
+ struct _bigint* next; /**< The next bigint in the cache. */
+ short size; /**< The number of components in this bigint. */
+ short max_comps; /**< The heapsize allocated for this bigint */
+ int refs; /**< An internal reference count. */
+ comp* comps; /**< A ptr to the actual component data */
+};
+
+typedef struct _bigint bigint; /**< An alias for _bigint */
+
+/**
+ * Maintains the state of the cache, and a number of variables used in
+ * reduction.
+ */
+typedef struct /**< A big integer "session" context. */
+{
+ bigint *active_list; /**< Bigints currently used. */
+ bigint *free_list; /**< Bigints not used. */
+ bigint *bi_radix; /**< The radix used. */
+ bigint *bi_mod[BIGINT_NUM_MODS]; /**< modulus */
+
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+ bigint *bi_RR_mod_m[BIGINT_NUM_MODS]; /**< R^2 mod m */
+ bigint *bi_R_mod_m[BIGINT_NUM_MODS]; /**< R mod m */
+ comp N0_dash[BIGINT_NUM_MODS];
+#elif defined(CONFIG_BIGINT_BARRETT)
+ bigint *bi_mu[BIGINT_NUM_MODS]; /**< Storage for mu */
+#endif
+ bigint *bi_normalised_mod[BIGINT_NUM_MODS]; /**< Normalised mod storage. */
+ bigint **g; /**< Used by sliding-window. */
+ int window; /**< The size of the sliding window */
+ int active_count; /**< Number of active bigints. */
+ int free_count; /**< Number of free bigints. */
+
+#ifdef CONFIG_BIGINT_MONTGOMERY
+ uint8_t use_classical; /**< Use classical reduction. */
+#endif
+ uint8_t mod_offset; /**< The mod offset we are using */
+} BI_CTX;
+
+#ifndef WIN32
+#define max(a,b) ((a)>(b)?(a):(b)) /**< Find the maximum of 2 numbers. */
+#define min(a,b) ((a)<(b)?(a):(b)) /**< Find the minimum of 2 numbers. */
+#endif
+
+#define PERMANENT 0x7FFF55AA /**< A magic number for permanents. */
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/axtls/config.h b/src/VBox/Devices/PC/ipxe/src/crypto/axtls/config.h
new file mode 100644
index 00000000..32fa3bf0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/axtls/config.h
@@ -0,0 +1,13 @@
+#ifndef AXTLS_CONFIG_H
+#define AXTLS_CONFIG_H
+
+/**
+ * @file config.h
+ *
+ * Trick the axtls code into building within our build environment.
+ */
+
+#define CONFIG_SSL_ENABLE_CLIENT 1
+#define CONFIG_BIGINT_CLASSICAL 1
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/axtls/crypto.h b/src/VBox/Devices/PC/ipxe/src/crypto/axtls/crypto.h
new file mode 100644
index 00000000..2c4cda4d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/axtls/crypto.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file crypto.h
+ */
+
+#ifndef HEADER_CRYPTO_H
+#define HEADER_CRYPTO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "config.h"
+#include "bigint_impl.h"
+#include "bigint.h"
+
+#ifndef STDCALL
+#define STDCALL
+#endif
+#ifndef EXP_FUNC
+#define EXP_FUNC
+#endif
+
+
+/* enable features based on a 'super-set' capbaility. */
+#if defined(CONFIG_SSL_FULL_MODE)
+#define CONFIG_SSL_ENABLE_CLIENT
+#define CONFIG_SSL_CERT_VERIFICATION
+#elif defined(CONFIG_SSL_ENABLE_CLIENT)
+#define CONFIG_SSL_CERT_VERIFICATION
+#endif
+
+/**************************************************************************
+ * AES declarations
+ **************************************************************************/
+
+#define AES_MAXROUNDS 14
+#define AES_BLOCKSIZE 16
+#define AES_IV_SIZE 16
+
+typedef struct aes_key_st
+{
+ uint16_t rounds;
+ uint16_t key_size;
+ uint32_t ks[(AES_MAXROUNDS+1)*8];
+ uint8_t iv[AES_IV_SIZE];
+} AES_CTX;
+
+typedef enum
+{
+ AES_MODE_128,
+ AES_MODE_256
+} AES_MODE;
+
+void AES_set_key(AES_CTX *ctx, const uint8_t *key,
+ const uint8_t *iv, AES_MODE mode);
+void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg,
+ uint8_t *out, int length);
+void AES_cbc_decrypt(AES_CTX *ks, const uint8_t *in, uint8_t *out, int length);
+void AES_convert_key(AES_CTX *ctx);
+
+/**************************************************************************
+ * RC4 declarations
+ **************************************************************************/
+
+typedef struct
+{
+ uint8_t x, y, m[256];
+} RC4_CTX;
+
+void RC4_setup(RC4_CTX *s, const uint8_t *key, int length);
+void RC4_crypt(RC4_CTX *s, const uint8_t *msg, uint8_t *data, int length);
+
+/**************************************************************************
+ * SHA1 declarations
+ **************************************************************************/
+
+#define SHA1_SIZE 20
+
+/*
+ * This structure will hold context information for the SHA-1
+ * hashing operation
+ */
+typedef struct
+{
+ uint32_t Intermediate_Hash[SHA1_SIZE/4]; /* Message Digest */
+ uint32_t Length_Low; /* Message length in bits */
+ uint32_t Length_High; /* Message length in bits */
+ uint16_t Message_Block_Index; /* Index into message block array */
+ uint8_t Message_Block[64]; /* 512-bit message blocks */
+} SHA1_CTX;
+
+void SHA1_Init(SHA1_CTX *);
+void SHA1_Update(SHA1_CTX *, const uint8_t * msg, int len);
+void SHA1_Final(uint8_t *digest, SHA1_CTX *);
+
+/**************************************************************************
+ * MD2 declarations
+ **************************************************************************/
+
+#define MD2_SIZE 16
+
+typedef struct
+{
+ unsigned char cksum[16]; /* checksum of the data block */
+ unsigned char state[48]; /* intermediate digest state */
+ unsigned char buffer[16]; /* data block being processed */
+ int left; /* amount of data in buffer */
+} MD2_CTX;
+
+EXP_FUNC void STDCALL MD2_Init(MD2_CTX *ctx);
+EXP_FUNC void STDCALL MD2_Update(MD2_CTX *ctx, const uint8_t *input, int ilen);
+EXP_FUNC void STDCALL MD2_Final(uint8_t *digest, MD2_CTX *ctx);
+
+/**************************************************************************
+ * MD5 declarations
+ **************************************************************************/
+
+#define MD5_SIZE 16
+
+typedef struct
+{
+ uint32_t state[4]; /* state (ABCD) */
+ uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ uint8_t buffer[64]; /* input buffer */
+} MD5_CTX;
+
+EXP_FUNC void STDCALL MD5_Init(MD5_CTX *);
+EXP_FUNC void STDCALL MD5_Update(MD5_CTX *, const uint8_t *msg, int len);
+EXP_FUNC void STDCALL MD5_Final(uint8_t *digest, MD5_CTX *);
+
+/**************************************************************************
+ * HMAC declarations
+ **************************************************************************/
+void hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
+ int key_len, uint8_t *digest);
+void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
+ int key_len, uint8_t *digest);
+
+/**************************************************************************
+ * RSA declarations
+ **************************************************************************/
+
+typedef struct
+{
+ bigint *m; /* modulus */
+ bigint *e; /* public exponent */
+ bigint *d; /* private exponent */
+#ifdef CONFIG_BIGINT_CRT
+ bigint *p; /* p as in m = pq */
+ bigint *q; /* q as in m = pq */
+ bigint *dP; /* d mod (p-1) */
+ bigint *dQ; /* d mod (q-1) */
+ bigint *qInv; /* q^-1 mod p */
+#endif
+ int num_octets;
+ BI_CTX *bi_ctx;
+} RSA_CTX;
+
+void RSA_priv_key_new(RSA_CTX **rsa_ctx,
+ const uint8_t *modulus, int mod_len,
+ const uint8_t *pub_exp, int pub_len,
+ const uint8_t *priv_exp, int priv_len
+#ifdef CONFIG_BIGINT_CRT
+ , const uint8_t *p, int p_len,
+ const uint8_t *q, int q_len,
+ const uint8_t *dP, int dP_len,
+ const uint8_t *dQ, int dQ_len,
+ const uint8_t *qInv, int qInv_len
+#endif
+ );
+void RSA_pub_key_new(RSA_CTX **rsa_ctx,
+ const uint8_t *modulus, int mod_len,
+ const uint8_t *pub_exp, int pub_len);
+void RSA_free(RSA_CTX *ctx);
+int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data,
+ int is_decryption);
+bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg);
+#if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT)
+bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
+ bigint *modulus, bigint *pub_exp);
+bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg);
+int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len,
+ uint8_t *out_data, int is_signing);
+void RSA_print(const RSA_CTX *ctx);
+#endif
+
+/**************************************************************************
+ * RNG declarations
+ **************************************************************************/
+EXP_FUNC void STDCALL RNG_initialize(const uint8_t *seed_buf, int size);
+EXP_FUNC void STDCALL RNG_terminate(void);
+EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data);
+void get_random_NZ(int num_rand_bytes, uint8_t *rand_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/axtls/os_port.h b/src/VBox/Devices/PC/ipxe/src/crypto/axtls/os_port.h
new file mode 100644
index 00000000..76313e20
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/axtls/os_port.h
@@ -0,0 +1,54 @@
+#ifndef AXTLS_OS_PORT_H
+#define AXTLS_OS_PORT_H
+
+/**
+ * @file os_port.h
+ *
+ * Trick the axtls code into building within our build environment.
+ */
+
+#include <stdint.h>
+#include <byteswap.h>
+
+/** All imported axTLS files are licensed using the three-clause BSD licence */
+FILE_LICENCE ( BSD3 );
+
+/** We can't actually abort, since we are effectively a kernel... */
+#define abort() assert ( 0 )
+
+/** rsa.c uses alloca() */
+#define alloca( size ) __builtin_alloca ( size )
+
+#include <ipxe/random_nz.h>
+static inline void get_random_NZ ( int num_rand_bytes, uint8_t *rand_data ) {
+ /* AXTLS does not check for failures when generating random
+ * data. Rely on the fact that get_random_nz() does not
+ * request prediction resistance (and so cannot introduce new
+ * failures) and therefore any potential failure must already
+ * have been encountered by e.g. tls_generate_random(), which
+ * does check for failures.
+ */
+ get_random_nz ( rand_data, num_rand_bytes );
+}
+
+/* Expose AES_encrypt() and AES_decrypt() in aes.o */
+#define aes 1
+#if OBJECT
+
+struct aes_key_st;
+
+static void AES_encrypt ( const struct aes_key_st *ctx, uint32_t *data );
+static void AES_decrypt ( const struct aes_key_st *ctx, uint32_t *data );
+
+void axtls_aes_encrypt ( void *ctx, uint32_t *data ) {
+ AES_encrypt ( ctx, data );
+}
+
+void axtls_aes_decrypt ( void *ctx, uint32_t *data ) {
+ AES_decrypt ( ctx, data );
+}
+
+#endif
+#undef aes
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/axtls_aes.c b/src/VBox/Devices/PC/ipxe/src/crypto/axtls_aes.c
new file mode 100644
index 00000000..3f1d668a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/axtls_aes.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/crypto.h>
+#include <ipxe/cbc.h>
+#include <ipxe/aes.h>
+#include "crypto/axtls/crypto.h"
+
+/** @file
+ *
+ * AES algorithm
+ *
+ */
+
+/**
+ * Set key
+ *
+ * @v ctx Context
+ * @v key Key
+ * @v keylen Key length
+ * @ret rc Return status code
+ */
+static int aes_setkey ( void *ctx, const void *key, size_t keylen ) {
+ struct aes_context *aes_ctx = ctx;
+ AES_MODE mode;
+ void *iv;
+
+ switch ( keylen ) {
+ case ( 128 / 8 ):
+ mode = AES_MODE_128;
+ break;
+ case ( 256 / 8 ):
+ mode = AES_MODE_256;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* IV is not a relevant concept at this stage; use a dummy
+ * value that will have no side-effects.
+ */
+ iv = &aes_ctx->axtls_ctx.iv;
+
+ AES_set_key ( &aes_ctx->axtls_ctx, key, iv, mode );
+
+ aes_ctx->decrypting = 0;
+
+ return 0;
+}
+
+/**
+ * Set initialisation vector
+ *
+ * @v ctx Context
+ * @v iv Initialisation vector
+ */
+static void aes_setiv ( void *ctx __unused, const void *iv __unused ) {
+ /* Nothing to do */
+}
+
+/**
+ * Call AXTLS' AES_encrypt() or AES_decrypt() functions
+ *
+ * @v axtls_ctx AXTLS AES context
+ * @v src Data to process
+ * @v dst Buffer for output
+ * @v func AXTLS AES function to call
+ */
+static void aes_call_axtls ( AES_CTX *axtls_ctx, const void *src, void *dst,
+ void ( * func ) ( const AES_CTX *axtls_ctx,
+ uint32_t *data ) ){
+ const uint32_t *srcl = src;
+ uint32_t *dstl = dst;
+ unsigned int i;
+
+ /* AXTLS' AES_encrypt() and AES_decrypt() functions both
+ * expect to deal with an array of four dwords in host-endian
+ * order.
+ */
+ for ( i = 0 ; i < 4 ; i++ )
+ dstl[i] = ntohl ( srcl[i] );
+ func ( axtls_ctx, dstl );
+ for ( i = 0 ; i < 4 ; i++ )
+ dstl[i] = htonl ( dstl[i] );
+}
+
+/**
+ * Encrypt data
+ *
+ * @v ctx Context
+ * @v src Data to encrypt
+ * @v dst Buffer for encrypted data
+ * @v len Length of data
+ */
+static void aes_encrypt ( void *ctx, const void *src, void *dst,
+ size_t len ) {
+ struct aes_context *aes_ctx = ctx;
+
+ assert ( len == AES_BLOCKSIZE );
+ if ( aes_ctx->decrypting )
+ assert ( 0 );
+ aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, axtls_aes_encrypt );
+}
+
+/**
+ * Decrypt data
+ *
+ * @v ctx Context
+ * @v src Data to decrypt
+ * @v dst Buffer for decrypted data
+ * @v len Length of data
+ */
+static void aes_decrypt ( void *ctx, const void *src, void *dst,
+ size_t len ) {
+ struct aes_context *aes_ctx = ctx;
+
+ assert ( len == AES_BLOCKSIZE );
+ if ( ! aes_ctx->decrypting ) {
+ AES_convert_key ( &aes_ctx->axtls_ctx );
+ aes_ctx->decrypting = 1;
+ }
+ aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, axtls_aes_decrypt );
+}
+
+/** Basic AES algorithm */
+struct cipher_algorithm aes_algorithm = {
+ .name = "aes",
+ .ctxsize = sizeof ( struct aes_context ),
+ .blocksize = AES_BLOCKSIZE,
+ .setkey = aes_setkey,
+ .setiv = aes_setiv,
+ .encrypt = aes_encrypt,
+ .decrypt = aes_decrypt,
+};
+
+/* AES with cipher-block chaining */
+CBC_CIPHER ( aes_cbc, aes_cbc_algorithm,
+ aes_algorithm, struct aes_context, AES_BLOCKSIZE );
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/bigint.c b/src/VBox/Devices/PC/ipxe/src/crypto/bigint.c
new file mode 100644
index 00000000..b13b0ac6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/bigint.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <ipxe/bigint.h>
+
+/** @file
+ *
+ * Big integer support
+ */
+
+/**
+ * Perform modular multiplication of big integers
+ *
+ * @v multiplicand0 Element 0 of big integer to be multiplied
+ * @v multiplier0 Element 0 of big integer to be multiplied
+ * @v modulus0 Element 0 of big integer modulus
+ * @v result0 Element 0 of big integer to hold result
+ * @v size Number of elements in base, modulus, and result
+ * @v tmp Temporary working space
+ */
+void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0,
+ const bigint_element_t *multiplier0,
+ const bigint_element_t *modulus0,
+ bigint_element_t *result0,
+ unsigned int size, void *tmp ) {
+ const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand =
+ ( ( const void * ) multiplicand0 );
+ const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier =
+ ( ( const void * ) multiplier0 );
+ const bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
+ ( ( const void * ) modulus0 );
+ bigint_t ( size ) __attribute__ (( may_alias )) *result =
+ ( ( void * ) result0 );
+ struct {
+ bigint_t ( size * 2 ) result;
+ bigint_t ( size * 2 ) modulus;
+ } *temp = tmp;
+ int rotation;
+ int i;
+
+ /* Sanity check */
+ assert ( sizeof ( *temp ) == bigint_mod_multiply_tmp_len ( modulus ) );
+
+ /* Perform multiplication */
+ bigint_multiply ( multiplicand, multiplier, &temp->result );
+
+ /* Rescale modulus to match result */
+ bigint_grow ( modulus, &temp->modulus );
+ rotation = ( bigint_max_set_bit ( &temp->result ) -
+ bigint_max_set_bit ( &temp->modulus ) );
+ for ( i = 0 ; i < rotation ; i++ )
+ bigint_rol ( &temp->modulus );
+
+ /* Subtract multiples of modulus */
+ for ( i = 0 ; i <= rotation ; i++ ) {
+ if ( bigint_is_geq ( &temp->result, &temp->modulus ) )
+ bigint_subtract ( &temp->modulus, &temp->result );
+ bigint_ror ( &temp->modulus );
+ }
+
+ /* Resize result */
+ bigint_shrink ( &temp->result, result );
+
+ /* Sanity check */
+ assert ( bigint_is_geq ( modulus, result ) );
+}
+
+/**
+ * Perform modular exponentiation of big integers
+ *
+ * @v base0 Element 0 of big integer base
+ * @v modulus0 Element 0 of big integer modulus
+ * @v exponent0 Element 0 of big integer exponent
+ * @v result0 Element 0 of big integer to hold result
+ * @v size Number of elements in base, modulus, and result
+ * @v exponent_size Number of elements in exponent
+ * @v tmp Temporary working space
+ */
+void bigint_mod_exp_raw ( const bigint_element_t *base0,
+ const bigint_element_t *modulus0,
+ const bigint_element_t *exponent0,
+ bigint_element_t *result0,
+ unsigned int size, unsigned int exponent_size,
+ void *tmp ) {
+ const bigint_t ( size ) __attribute__ (( may_alias )) *base =
+ ( ( const void * ) base0 );
+ const bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
+ ( ( const void * ) modulus0 );
+ const bigint_t ( exponent_size ) __attribute__ (( may_alias ))
+ *exponent = ( ( const void * ) exponent0 );
+ bigint_t ( size ) __attribute__ (( may_alias )) *result =
+ ( ( void * ) result0 );
+ size_t mod_multiply_len = bigint_mod_multiply_tmp_len ( modulus );
+ struct {
+ bigint_t ( size ) base;
+ bigint_t ( exponent_size ) exponent;
+ uint8_t mod_multiply[mod_multiply_len];
+ } *temp = tmp;
+ static const uint8_t start[1] = { 0x01 };
+
+ memcpy ( &temp->base, base, sizeof ( temp->base ) );
+ memcpy ( &temp->exponent, exponent, sizeof ( temp->exponent ) );
+ bigint_init ( result, start, sizeof ( start ) );
+
+ while ( ! bigint_is_zero ( &temp->exponent ) ) {
+ if ( bigint_bit_is_set ( &temp->exponent, 0 ) ) {
+ bigint_mod_multiply ( result, &temp->base, modulus,
+ result, temp->mod_multiply );
+ }
+ bigint_ror ( &temp->exponent );
+ bigint_mod_multiply ( &temp->base, &temp->base, modulus,
+ &temp->base, temp->mod_multiply );
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/cbc.c b/src/VBox/Devices/PC/ipxe/src/crypto/cbc.c
new file mode 100644
index 00000000..c00ebb0a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/cbc.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <assert.h>
+#include <ipxe/crypto.h>
+#include <ipxe/cbc.h>
+
+/** @file
+ *
+ * Cipher-block chaining
+ *
+ */
+
+/**
+ * XOR data blocks
+ *
+ * @v src Input data
+ * @v dst Second input data and output data buffer
+ * @v len Length of data
+ */
+static void cbc_xor ( const void *src, void *dst, size_t len ) {
+ const uint32_t *srcl = src;
+ uint32_t *dstl = dst;
+ unsigned int i;
+
+ /* Assume that block sizes will always be dword-aligned, for speed */
+ assert ( ( len % sizeof ( *srcl ) ) == 0 );
+
+ for ( i = 0 ; i < ( len / sizeof ( *srcl ) ) ; i++ )
+ dstl[i] ^= srcl[i];
+}
+
+/**
+ * Encrypt data
+ *
+ * @v ctx Context
+ * @v src Data to encrypt
+ * @v dst Buffer for encrypted data
+ * @v len Length of data
+ * @v raw_cipher Underlying cipher algorithm
+ * @v cbc_ctx CBC context
+ */
+void cbc_encrypt ( void *ctx, const void *src, void *dst, size_t len,
+ struct cipher_algorithm *raw_cipher, void *cbc_ctx ) {
+ size_t blocksize = raw_cipher->blocksize;
+
+ assert ( ( len % blocksize ) == 0 );
+
+ while ( len ) {
+ cbc_xor ( src, cbc_ctx, blocksize );
+ cipher_encrypt ( raw_cipher, ctx, cbc_ctx, dst, blocksize );
+ memcpy ( cbc_ctx, dst, blocksize );
+ dst += blocksize;
+ src += blocksize;
+ len -= blocksize;
+ }
+}
+
+/**
+ * Decrypt data
+ *
+ * @v ctx Context
+ * @v src Data to decrypt
+ * @v dst Buffer for decrypted data
+ * @v len Length of data
+ * @v raw_cipher Underlying cipher algorithm
+ * @v cbc_ctx CBC context
+ */
+void cbc_decrypt ( void *ctx, const void *src, void *dst, size_t len,
+ struct cipher_algorithm *raw_cipher, void *cbc_ctx ) {
+ size_t blocksize = raw_cipher->blocksize;
+
+ assert ( ( len % blocksize ) == 0 );
+
+ while ( len ) {
+ cipher_decrypt ( raw_cipher, ctx, src, dst, blocksize );
+ cbc_xor ( cbc_ctx, dst, blocksize );
+ memcpy ( cbc_ctx, src, blocksize );
+ dst += blocksize;
+ src += blocksize;
+ len -= blocksize;
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/chap.c b/src/VBox/Devices/PC/ipxe/src/crypto/chap.c
new file mode 100644
index 00000000..492d2216
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/chap.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/crypto.h>
+#include <ipxe/chap.h>
+
+/** @file
+ *
+ * CHAP protocol
+ *
+ */
+
+/**
+ * Initialise CHAP challenge/response
+ *
+ * @v chap CHAP challenge/response
+ * @v digest Digest algorithm to use
+ * @ret rc Return status code
+ *
+ * Initialises a CHAP challenge/response structure. This routine
+ * allocates memory, and so may fail. The allocated memory must
+ * eventually be freed by a call to chap_finish().
+ */
+int chap_init ( struct chap_response *chap,
+ struct digest_algorithm *digest ) {
+ size_t state_len;
+ void *state;
+
+ assert ( chap->digest == NULL );
+ assert ( chap->digest_context == NULL );
+ assert ( chap->response == NULL );
+
+ DBG ( "CHAP %p initialising with %s digest\n", chap, digest->name );
+
+ state_len = ( digest->ctxsize + digest->digestsize );
+ state = malloc ( state_len );
+ if ( ! state ) {
+ DBG ( "CHAP %p could not allocate %zd bytes for state\n",
+ chap, state_len );
+ return -ENOMEM;
+ }
+
+ chap->digest = digest;
+ chap->digest_context = state;
+ chap->response = ( state + digest->ctxsize );
+ chap->response_len = digest->digestsize;
+ digest_init ( chap->digest, chap->digest_context );
+ return 0;
+}
+
+/**
+ * Add data to the CHAP challenge
+ *
+ * @v chap CHAP response
+ * @v data Data to add
+ * @v len Length of data to add
+ */
+void chap_update ( struct chap_response *chap, const void *data,
+ size_t len ) {
+ assert ( chap->digest != NULL );
+ assert ( chap->digest_context != NULL );
+
+ if ( ! chap->digest )
+ return;
+
+ digest_update ( chap->digest, chap->digest_context, data, len );
+}
+
+/**
+ * Respond to the CHAP challenge
+ *
+ * @v chap CHAP response
+ *
+ * Calculates the final CHAP response value, and places it in @c
+ * chap->response, with a length of @c chap->response_len.
+ */
+void chap_respond ( struct chap_response *chap ) {
+ assert ( chap->digest != NULL );
+ assert ( chap->digest_context != NULL );
+ assert ( chap->response != NULL );
+
+ DBG ( "CHAP %p responding to challenge\n", chap );
+
+ if ( ! chap->digest )
+ return;
+
+ digest_final ( chap->digest, chap->digest_context, chap->response );
+}
+
+/**
+ * Free resources used by a CHAP response
+ *
+ * @v chap CHAP response
+ */
+void chap_finish ( struct chap_response *chap ) {
+ void *state = chap->digest_context;
+
+ DBG ( "CHAP %p finished\n", chap );
+
+ free ( state );
+ memset ( chap, 0, sizeof ( *chap ) );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/clientcert.c b/src/VBox/Devices/PC/ipxe/src/crypto/clientcert.c
new file mode 100644
index 00000000..159a3f4e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/clientcert.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/settings.h>
+#include <ipxe/clientcert.h>
+
+/** @file
+ *
+ * Client certificate store
+ *
+ * Life would in theory be easier if we could use a single file to
+ * hold both the certificate and corresponding private key.
+ * Unfortunately, the only common format which supports this is
+ * PKCS#12 (aka PFX), which is too ugly to be allowed anywhere near my
+ * codebase. See, for reference and amusement:
+ *
+ * http://www.cs.auckland.ac.nz/~pgut001/pubs/pfx.html
+ *
+ */
+
+/* Sanity checks */
+#if defined(CERTIFICATE) && ! defined(PRIVATE_KEY)
+#warning "Attempting to embed certificate with no corresponding private key"
+#endif
+#if defined(PRIVATE_KEY) && ! defined(CERTIFICATE)
+#warning "Attempting to embed private key with no corresponding certificate"
+#endif
+
+/* Allow client certificates to be overridden if not explicitly specified */
+#ifdef CERTIFICATE
+#define ALLOW_CERT_OVERRIDE 0
+#else
+#define ALLOW_CERT_OVERRIDE 1
+#endif
+
+/* Raw client certificate data */
+extern char client_certificate_data[];
+extern char client_certificate_len[];
+__asm__ ( ".section \".rodata\", \"a\", @progbits\n\t"
+ "\nclient_certificate_data:\n\t"
+#ifdef CERTIFICATE
+ ".incbin \"" CERTIFICATE "\"\n\t"
+#endif /* CERTIFICATE */
+ ".size client_certificate_data, ( . - client_certificate_data )\n\t"
+ ".equ client_certificate_len, ( . - client_certificate_data )\n\t"
+ ".previous\n\t" );
+
+/* Raw client private key data */
+extern char client_private_key_data[];
+extern char client_private_key_len[];
+__asm__ ( ".section \".rodata\", \"a\", @progbits\n\t"
+ "\nclient_private_key_data:\n\t"
+#ifdef PRIVATE_KEY
+ ".incbin \"" PRIVATE_KEY "\"\n\t"
+#endif /* PRIVATE_KEY */
+ ".size client_private_key_data, ( . - client_private_key_data )\n\t"
+ ".equ client_private_key_len, ( . - client_private_key_data )\n\t"
+ ".previous\n\t" );
+
+/** Client certificate */
+struct client_certificate client_certificate = {
+ .data = client_certificate_data,
+ .len = ( ( size_t ) client_certificate_len ),
+};
+
+/** Client private key */
+struct client_private_key client_private_key = {
+ .data = client_private_key_data,
+ .len = ( ( size_t ) client_private_key_len ),
+};
+
+/** Client certificate setting */
+static struct setting cert_setting __setting ( SETTING_CRYPTO ) = {
+ .name = "cert",
+ .description = "Client certificate",
+ .tag = DHCP_EB_CERT,
+ .type = &setting_type_hex,
+};
+
+/** Client private key setting */
+static struct setting key_setting __setting ( SETTING_CRYPTO ) = {
+ .name = "key",
+ .description = "Client private key",
+ .tag = DHCP_EB_KEY,
+ .type = &setting_type_hex,
+};
+
+/**
+ * Apply client certificate store configuration settings
+ *
+ * @ret rc Return status code
+ */
+static int clientcert_apply_settings ( void ) {
+ static void *cert = NULL;
+ static void *key = NULL;
+ int len;
+ int rc;
+
+ /* Allow client certificate to be overridden only if
+ * not explicitly specified at build time.
+ */
+ if ( ALLOW_CERT_OVERRIDE ) {
+
+ /* Restore default client certificate */
+ client_certificate.data = client_certificate_data;
+ client_certificate.len = ( ( size_t ) client_certificate_len );
+
+ /* Fetch new client certificate, if any */
+ free ( cert );
+ len = fetch_setting_copy ( NULL, &cert_setting, &cert );
+ if ( len < 0 ) {
+ rc = len;
+ DBGC ( &client_certificate, "CLIENTCERT cannot fetch "
+ "client certificate: %s\n", strerror ( rc ) );
+ return rc;
+ }
+ if ( cert ) {
+ client_certificate.data = cert;
+ client_certificate.len = len;
+ }
+
+ /* Restore default client private key */
+ client_private_key.data = client_private_key_data;
+ client_private_key.len = ( ( size_t ) client_private_key_len );
+
+ /* Fetch new client private key, if any */
+ free ( key );
+ len = fetch_setting_copy ( NULL, &key_setting, &key );
+ if ( len < 0 ) {
+ rc = len;
+ DBGC ( &client_certificate, "CLIENTCERT cannot fetch "
+ "client private key: %s\n", strerror ( rc ) );
+ return rc;
+ }
+ if ( key ) {
+ client_private_key.data = key;
+ client_private_key.len = len;
+ }
+ }
+
+ /* Debug */
+ if ( have_client_certificate() ) {
+ DBGC ( &client_certificate, "CLIENTCERT using %s "
+ "certificate:\n", ( cert ? "external" : "built-in" ) );
+ DBGC_HDA ( &client_certificate, 0, client_certificate.data,
+ client_certificate.len );
+ DBGC ( &client_certificate, "CLIENTCERT using %s private "
+ "key:\n", ( key ? "external" : "built-in" ) );
+ DBGC_HDA ( &client_certificate, 0, client_private_key.data,
+ client_private_key.len );
+ } else {
+ DBGC ( &client_certificate, "CLIENTCERT has no certificate\n" );
+ }
+
+ return 0;
+}
+
+/** Client certificate store settings applicator */
+struct settings_applicator clientcert_applicator __settings_applicator = {
+ .apply = clientcert_apply_settings,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/cms.c b/src/VBox/Devices/PC/ipxe/src/crypto/cms.c
new file mode 100644
index 00000000..2083433e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/cms.c
@@ -0,0 +1,704 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Cryptographic Message Syntax (PKCS #7)
+ *
+ * The format of CMS messages is defined in RFC 5652.
+ *
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <ipxe/asn1.h>
+#include <ipxe/x509.h>
+#include <ipxe/malloc.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/cms.h>
+
+/* Disambiguate the various error causes */
+#define EACCES_NON_SIGNING \
+ __einfo_error ( EINFO_EACCES_NON_SIGNING )
+#define EINFO_EACCES_NON_SIGNING \
+ __einfo_uniqify ( EINFO_EACCES, 0x01, "Not a signing certificate" )
+#define EACCES_NON_CODE_SIGNING \
+ __einfo_error ( EINFO_EACCES_NON_CODE_SIGNING )
+#define EINFO_EACCES_NON_CODE_SIGNING \
+ __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a code-signing certificate" )
+#define EACCES_WRONG_NAME \
+ __einfo_error ( EINFO_EACCES_WRONG_NAME )
+#define EINFO_EACCES_WRONG_NAME \
+ __einfo_uniqify ( EINFO_EACCES, 0x04, "Incorrect certificate name" )
+#define EACCES_NO_SIGNATURES \
+ __einfo_error ( EINFO_EACCES_NO_SIGNATURES )
+#define EINFO_EACCES_NO_SIGNATURES \
+ __einfo_uniqify ( EINFO_EACCES, 0x05, "No signatures present" )
+#define EINVAL_DIGEST \
+ __einfo_error ( EINFO_EINVAL_DIGEST )
+#define EINFO_EINVAL_DIGEST \
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, "Not a digest algorithm" )
+#define EINVAL_PUBKEY \
+ __einfo_error ( EINFO_EINVAL_PUBKEY )
+#define EINFO_EINVAL_PUBKEY \
+ __einfo_uniqify ( EINFO_EINVAL, 0x02, "Not a public-key algorithm" )
+#define ENOTSUP_SIGNEDDATA \
+ __einfo_error ( EINFO_ENOTSUP_SIGNEDDATA )
+#define EINFO_ENOTSUP_SIGNEDDATA \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Not a digital signature" )
+
+/** "pkcs7-signedData" object identifier */
+static uint8_t oid_signeddata[] = { ASN1_OID_SIGNEDDATA };
+
+/** "pkcs7-signedData" object identifier cursor */
+static struct asn1_cursor oid_signeddata_cursor =
+ ASN1_OID_CURSOR ( oid_signeddata );
+
+/**
+ * Parse CMS signature content type
+ *
+ * @v sig CMS signature
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int cms_parse_content_type ( struct cms_signature *sig,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+
+ /* Enter contentType */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_OID );
+
+ /* Check OID is pkcs7-signedData */
+ if ( asn1_compare ( &cursor, &oid_signeddata_cursor ) != 0 ) {
+ DBGC ( sig, "CMS %p does not contain signedData:\n", sig );
+ DBGC_HDA ( sig, 0, raw->data, raw->len );
+ return -ENOTSUP_SIGNEDDATA;
+ }
+
+ DBGC ( sig, "CMS %p contains signedData\n", sig );
+ return 0;
+}
+
+/**
+ * Parse CMS signature certificate list
+ *
+ * @v sig CMS signature
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int cms_parse_certificates ( struct cms_signature *sig,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ struct x509_certificate *cert;
+ int rc;
+
+ /* Enter certificates */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
+
+ /* Add each certificate */
+ while ( cursor.len ) {
+
+ /* Add certificate to chain */
+ if ( ( rc = x509_append_raw ( sig->certificates, cursor.data,
+ cursor.len ) ) != 0 ) {
+ DBGC ( sig, "CMS %p could not append certificate: %s\n",
+ sig, strerror ( rc) );
+ DBGC_HDA ( sig, 0, cursor.data, cursor.len );
+ return rc;
+ }
+ cert = x509_last ( sig->certificates );
+ DBGC ( sig, "CMS %p found certificate %s\n",
+ sig, cert->subject.name );
+
+ /* Move to next certificate */
+ asn1_skip_any ( &cursor );
+ }
+
+ return 0;
+}
+
+/**
+ * Identify CMS signature certificate by issuer and serial number
+ *
+ * @v sig CMS signature
+ * @v issuer Issuer
+ * @v serial Serial number
+ * @ret cert X.509 certificate, or NULL if not found
+ */
+static struct x509_certificate *
+cms_find_issuer_serial ( struct cms_signature *sig,
+ const struct asn1_cursor *issuer,
+ const struct asn1_cursor *serial ) {
+ struct x509_link *link;
+ struct x509_certificate *cert;
+
+ /* Scan through certificate list */
+ list_for_each_entry ( link, &sig->certificates->links, list ) {
+
+ /* Check issuer and serial number */
+ cert = link->cert;
+ if ( ( asn1_compare ( issuer, &cert->issuer.raw ) == 0 ) &&
+ ( asn1_compare ( serial, &cert->serial.raw ) == 0 ) )
+ return cert;
+ }
+
+ return NULL;
+}
+
+/**
+ * Parse CMS signature signer identifier
+ *
+ * @v sig CMS signature
+ * @v info Signer information to fill in
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int cms_parse_signer_identifier ( struct cms_signature *sig,
+ struct cms_signer_info *info,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ struct asn1_cursor serial;
+ struct asn1_cursor issuer;
+ struct x509_certificate *cert;
+ int rc;
+
+ /* Enter issuerAndSerialNumber */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Identify issuer */
+ memcpy ( &issuer, &cursor, sizeof ( issuer ) );
+ if ( ( rc = asn1_shrink ( &issuer, ASN1_SEQUENCE ) ) != 0 ) {
+ DBGC ( sig, "CMS %p/%p could not locate issuer: %s\n",
+ sig, info, strerror ( rc ) );
+ DBGC_HDA ( sig, 0, raw->data, raw->len );
+ return rc;
+ }
+ DBGC ( sig, "CMS %p/%p issuer is:\n", sig, info );
+ DBGC_HDA ( sig, 0, issuer.data, issuer.len );
+ asn1_skip_any ( &cursor );
+
+ /* Identify serialNumber */
+ memcpy ( &serial, &cursor, sizeof ( serial ) );
+ if ( ( rc = asn1_shrink ( &serial, ASN1_INTEGER ) ) != 0 ) {
+ DBGC ( sig, "CMS %p/%p could not locate serialNumber: %s\n",
+ sig, info, strerror ( rc ) );
+ DBGC_HDA ( sig, 0, raw->data, raw->len );
+ return rc;
+ }
+ DBGC ( sig, "CMS %p/%p serial number is:\n", sig, info );
+ DBGC_HDA ( sig, 0, serial.data, serial.len );
+
+ /* Identify certificate */
+ cert = cms_find_issuer_serial ( sig, &issuer, &serial );
+ if ( ! cert ) {
+ DBGC ( sig, "CMS %p/%p could not identify signer's "
+ "certificate\n", sig, info );
+ return -ENOENT;
+ }
+
+ /* Append certificate to chain */
+ if ( ( rc = x509_append ( info->chain, cert ) ) != 0 ) {
+ DBGC ( sig, "CMS %p/%p could not append certificate: %s\n",
+ sig, info, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Append remaining certificates to chain */
+ if ( ( rc = x509_auto_append ( info->chain,
+ sig->certificates ) ) != 0 ) {
+ DBGC ( sig, "CMS %p/%p could not append certificates: %s\n",
+ sig, info, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse CMS signature digest algorithm
+ *
+ * @v sig CMS signature
+ * @v info Signer information to fill in
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int cms_parse_digest_algorithm ( struct cms_signature *sig,
+ struct cms_signer_info *info,
+ const struct asn1_cursor *raw ) {
+ struct asn1_algorithm *algorithm;
+ int rc;
+
+ /* Identify algorithm */
+ if ( ( rc = asn1_digest_algorithm ( raw, &algorithm ) ) != 0 ) {
+ DBGC ( sig, "CMS %p/%p could not identify digest algorithm: "
+ "%s\n", sig, info, strerror ( rc ) );
+ DBGC_HDA ( sig, 0, raw->data, raw->len );
+ return rc;
+ }
+
+ /* Record digest algorithm */
+ info->digest = algorithm->digest;
+ DBGC ( sig, "CMS %p/%p digest algorithm is %s\n",
+ sig, info, algorithm->name );
+
+ return 0;
+}
+
+/**
+ * Parse CMS signature algorithm
+ *
+ * @v sig CMS signature
+ * @v info Signer information to fill in
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int cms_parse_signature_algorithm ( struct cms_signature *sig,
+ struct cms_signer_info *info,
+ const struct asn1_cursor *raw ) {
+ struct asn1_algorithm *algorithm;
+ int rc;
+
+ /* Identify algorithm */
+ if ( ( rc = asn1_pubkey_algorithm ( raw, &algorithm ) ) != 0 ) {
+ DBGC ( sig, "CMS %p/%p could not identify public-key "
+ "algorithm: %s\n", sig, info, strerror ( rc ) );
+ DBGC_HDA ( sig, 0, raw->data, raw->len );
+ return rc;
+ }
+
+ /* Record signature algorithm */
+ info->pubkey = algorithm->pubkey;
+ DBGC ( sig, "CMS %p/%p public-key algorithm is %s\n",
+ sig, info, algorithm->name );
+
+ return 0;
+}
+
+/**
+ * Parse CMS signature value
+ *
+ * @v sig CMS signature
+ * @v info Signer information to fill in
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int cms_parse_signature_value ( struct cms_signature *sig,
+ struct cms_signer_info *info,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter signature */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ if ( ( rc = asn1_enter ( &cursor, ASN1_OCTET_STRING ) ) != 0 ) {
+ DBGC ( sig, "CMS %p/%p could not locate signature:\n",
+ sig, info );
+ DBGC_HDA ( sig, 0, raw->data, raw->len );
+ return rc;
+ }
+
+ /* Record signature */
+ info->signature_len = cursor.len;
+ info->signature = malloc ( info->signature_len );
+ if ( ! info->signature )
+ return -ENOMEM;
+ memcpy ( info->signature, cursor.data, info->signature_len );
+ DBGC ( sig, "CMS %p/%p signature value is:\n", sig, info );
+ DBGC_HDA ( sig, 0, info->signature, info->signature_len );
+
+ return 0;
+}
+
+/**
+ * Parse CMS signature signer information
+ *
+ * @v sig CMS signature
+ * @v info Signer information to fill in
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int cms_parse_signer_info ( struct cms_signature *sig,
+ struct cms_signer_info *info,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter signerInfo */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Skip version */
+ asn1_skip ( &cursor, ASN1_INTEGER );
+
+ /* Parse sid */
+ if ( ( rc = cms_parse_signer_identifier ( sig, info, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Parse digestAlgorithm */
+ if ( ( rc = cms_parse_digest_algorithm ( sig, info, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Skip signedAttrs, if present */
+ asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
+
+ /* Parse signatureAlgorithm */
+ if ( ( rc = cms_parse_signature_algorithm ( sig, info, &cursor ) ) != 0)
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Parse signature */
+ if ( ( rc = cms_parse_signature_value ( sig, info, &cursor ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Parse CMS signature from ASN.1 data
+ *
+ * @v sig CMS signature
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int cms_parse ( struct cms_signature *sig,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ struct cms_signer_info *info;
+ int rc;
+
+ /* Enter contentInfo */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse contentType */
+
+ if ( ( rc = cms_parse_content_type ( sig, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Enter content */
+ asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
+
+ /* Enter signedData */
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Skip version */
+ asn1_skip ( &cursor, ASN1_INTEGER );
+
+ /* Skip digestAlgorithms */
+ asn1_skip ( &cursor, ASN1_SET );
+
+ /* Skip encapContentInfo */
+ asn1_skip ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse certificates */
+ if ( ( rc = cms_parse_certificates ( sig, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Skip crls, if present */
+ asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 1 ) );
+
+ /* Enter signerInfos */
+ asn1_enter ( &cursor, ASN1_SET );
+
+ /* Add each signerInfo. Errors are handled by ensuring that
+ * cms_put() will always be able to free any allocated memory.
+ */
+ while ( cursor.len ) {
+
+ /* Allocate signer information block */
+ info = zalloc ( sizeof ( *info ) );
+ if ( ! info )
+ return -ENOMEM;
+ list_add ( &info->list, &sig->info );
+
+ /* Allocate certificate chain */
+ info->chain = x509_alloc_chain();
+ if ( ! info->chain )
+ return -ENOMEM;
+
+ /* Parse signerInfo */
+ if ( ( rc = cms_parse_signer_info ( sig, info,
+ &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+ }
+
+ return 0;
+}
+
+/**
+ * Free CMS signature
+ *
+ * @v refcnt Reference count
+ */
+static void cms_free ( struct refcnt *refcnt ) {
+ struct cms_signature *sig =
+ container_of ( refcnt, struct cms_signature, refcnt );
+ struct cms_signer_info *info;
+ struct cms_signer_info *tmp;
+
+ list_for_each_entry_safe ( info, tmp, &sig->info, list ) {
+ list_del ( &info->list );
+ x509_chain_put ( info->chain );
+ free ( info->signature );
+ free ( info );
+ }
+ x509_chain_put ( sig->certificates );
+ free ( sig );
+}
+
+/**
+ * Create CMS signature
+ *
+ * @v data Raw signature data
+ * @v len Length of raw data
+ * @ret sig CMS signature
+ * @ret rc Return status code
+ *
+ * On success, the caller holds a reference to the CMS signature, and
+ * is responsible for ultimately calling cms_put().
+ */
+int cms_signature ( const void *data, size_t len, struct cms_signature **sig ) {
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Allocate and initialise signature */
+ *sig = zalloc ( sizeof ( **sig ) );
+ if ( ! *sig ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ ref_init ( &(*sig)->refcnt, cms_free );
+ INIT_LIST_HEAD ( &(*sig)->info );
+
+ /* Allocate certificate list */
+ (*sig)->certificates = x509_alloc_chain();
+ if ( ! (*sig)->certificates ) {
+ rc = -ENOMEM;
+ goto err_alloc_chain;
+ }
+
+ /* Initialise cursor */
+ cursor.data = data;
+ cursor.len = len;
+ asn1_shrink_any ( &cursor );
+
+ /* Parse signature */
+ if ( ( rc = cms_parse ( *sig, &cursor ) ) != 0 )
+ goto err_parse;
+
+ return 0;
+
+ err_parse:
+ err_alloc_chain:
+ cms_put ( *sig );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Calculate digest of CMS-signed data
+ *
+ * @v sig CMS signature
+ * @v info Signer information
+ * @v data Signed data
+ * @v len Length of signed data
+ * @v out Digest output
+ */
+static void cms_digest ( struct cms_signature *sig,
+ struct cms_signer_info *info,
+ userptr_t data, size_t len, void *out ) {
+ struct digest_algorithm *digest = info->digest;
+ uint8_t ctx[ digest->ctxsize ];
+ uint8_t block[ digest->blocksize ];
+ size_t offset = 0;
+ size_t frag_len;
+
+ /* Initialise digest */
+ digest_init ( digest, ctx );
+
+ /* Process data one block at a time */
+ while ( len ) {
+ frag_len = len;
+ if ( frag_len > sizeof ( block ) )
+ frag_len = sizeof ( block );
+ copy_from_user ( block, data, offset, frag_len );
+ digest_update ( digest, ctx, block, frag_len );
+ offset += frag_len;
+ len -= frag_len;
+ }
+
+ /* Finalise digest */
+ digest_final ( digest, ctx, out );
+
+ DBGC ( sig, "CMS %p/%p digest value:\n", sig, info );
+ DBGC_HDA ( sig, 0, out, digest->digestsize );
+}
+
+/**
+ * Verify digest of CMS-signed data
+ *
+ * @v sig CMS signature
+ * @v info Signer information
+ * @v cert Corresponding certificate
+ * @v data Signed data
+ * @v len Length of signed data
+ * @ret rc Return status code
+ */
+static int cms_verify_digest ( struct cms_signature *sig,
+ struct cms_signer_info *info,
+ struct x509_certificate *cert,
+ userptr_t data, size_t len ) {
+ struct digest_algorithm *digest = info->digest;
+ struct pubkey_algorithm *pubkey = info->pubkey;
+ struct x509_public_key *public_key = &cert->subject.public_key;
+ uint8_t digest_out[ digest->digestsize ];
+ uint8_t ctx[ pubkey->ctxsize ];
+ int rc;
+
+ /* Generate digest */
+ cms_digest ( sig, info, data, len, digest_out );
+
+ /* Initialise public-key algorithm */
+ if ( ( rc = pubkey_init ( pubkey, ctx, public_key->raw.data,
+ public_key->raw.len ) ) != 0 ) {
+ DBGC ( sig, "CMS %p/%p could not initialise public key: %s\n",
+ sig, info, strerror ( rc ) );
+ goto err_init;
+ }
+
+ /* Verify digest */
+ if ( ( rc = pubkey_verify ( pubkey, ctx, digest, digest_out,
+ info->signature,
+ info->signature_len ) ) != 0 ) {
+ DBGC ( sig, "CMS %p/%p signature verification failed: %s\n",
+ sig, info, strerror ( rc ) );
+ goto err_verify;
+ }
+
+ err_verify:
+ pubkey_final ( pubkey, ctx );
+ err_init:
+ return rc;
+}
+
+/**
+ * Verify CMS signature signer information
+ *
+ * @v sig CMS signature
+ * @v info Signer information
+ * @v data Signed data
+ * @v len Length of signed data
+ * @v time Time at which to validate certificates
+ * @v root Root certificate store, or NULL to use default
+ * @ret rc Return status code
+ */
+static int cms_verify_signer_info ( struct cms_signature *sig,
+ struct cms_signer_info *info,
+ userptr_t data, size_t len,
+ time_t time, struct x509_root *root ) {
+ struct x509_certificate *cert;
+ int rc;
+
+ /* Validate certificate chain */
+ if ( ( rc = x509_validate_chain ( info->chain, time, root ) ) != 0 ) {
+ DBGC ( sig, "CMS %p/%p could not validate chain: %s\n",
+ sig, info, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Extract code-signing certificate */
+ cert = x509_first ( info->chain );
+ assert ( cert != NULL );
+
+ /* Check that certificate can create digital signatures */
+ if ( ! ( cert->extensions.usage.bits & X509_DIGITAL_SIGNATURE ) ) {
+ DBGC ( sig, "CMS %p/%p certificate cannot create signatures\n",
+ sig, info );
+ return -EACCES_NON_SIGNING;
+ }
+
+ /* Check that certificate can sign code */
+ if ( ! ( cert->extensions.ext_usage.bits & X509_CODE_SIGNING ) ) {
+ DBGC ( sig, "CMS %p/%p certificate is not code-signing\n",
+ sig, info );
+ return -EACCES_NON_CODE_SIGNING;
+ }
+
+ /* Verify digest */
+ if ( ( rc = cms_verify_digest ( sig, info, cert, data, len ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Verify CMS signature
+ *
+ * @v sig CMS signature
+ * @v data Signed data
+ * @v len Length of signed data
+ * @v name Required common name, or NULL to check all signatures
+ * @v time Time at which to validate certificates
+ * @v root Root certificate store, or NULL to use default
+ * @ret rc Return status code
+ */
+int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len,
+ const char *name, time_t time, struct x509_root *root ) {
+ struct cms_signer_info *info;
+ struct x509_certificate *cert;
+ int count = 0;
+ int rc;
+
+ /* Verify using all signerInfos */
+ list_for_each_entry ( info, &sig->info, list ) {
+ cert = x509_first ( info->chain );
+ if ( name && ( ( cert->subject.name == NULL ) ||
+ ( strcmp ( cert->subject.name, name ) != 0 ) ) )
+ continue;
+ if ( ( rc = cms_verify_signer_info ( sig, info, data, len,
+ time, root ) ) != 0 )
+ return rc;
+ count++;
+ }
+
+ /* Check that we have verified at least one signature */
+ if ( count == 0 ) {
+ if ( name ) {
+ DBGC ( sig, "CMS %p had no signatures matching name "
+ "%s\n", sig, name );
+ return -EACCES_WRONG_NAME;
+ } else {
+ DBGC ( sig, "CMS %p had no signatures\n", sig );
+ return -EACCES_NO_SIGNATURES;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/crc32.c b/src/VBox/Devices/PC/ipxe/src/crypto/crc32.c
new file mode 100644
index 00000000..71ec1d66
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/crc32.c
@@ -0,0 +1,54 @@
+/*
+ * Little-endian CRC32 implementation.
+ *
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/crc32.h>
+
+#define CRCPOLY 0xedb88320
+
+/**
+ * Calculate 32-bit little-endian CRC checksum
+ *
+ * @v seed Initial value
+ * @v data Data to checksum
+ * @v len Length of data
+ *
+ * Usually @a seed is initially zero or all one bits, depending on the
+ * protocol. To continue a CRC checksum over multiple calls, pass the
+ * return value from one call as the @a seed parameter to the next.
+ */
+u32 crc32_le ( u32 seed, const void *data, size_t len )
+{
+ u32 crc = seed;
+ const u8 *src = data;
+ u32 mult;
+ int i;
+
+ while ( len-- ) {
+ crc ^= *src++;
+ for ( i = 0; i < 8; i++ ) {
+ mult = ( crc & 1 ) ? CRCPOLY : 0;
+ crc = ( crc >> 1 ) ^ mult;
+ }
+ }
+
+ return crc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/crypto_null.c b/src/VBox/Devices/PC/ipxe/src/crypto/crypto_null.c
new file mode 100644
index 00000000..590ac560
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/crypto_null.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Null crypto algorithm
+ */
+
+#include <string.h>
+#include <ipxe/crypto.h>
+
+static void digest_null_init ( void *ctx __unused ) {
+ /* Do nothing */
+}
+
+static void digest_null_update ( void *ctx __unused, const void *src __unused,
+ size_t len __unused ) {
+ /* Do nothing */
+}
+
+static void digest_null_final ( void *ctx __unused, void *out __unused ) {
+ /* Do nothing */
+}
+
+struct digest_algorithm digest_null = {
+ .name = "null",
+ .ctxsize = 0,
+ .blocksize = 1,
+ .digestsize = 0,
+ .init = digest_null_init,
+ .update = digest_null_update,
+ .final = digest_null_final,
+};
+
+static int cipher_null_setkey ( void *ctx __unused, const void *key __unused,
+ size_t keylen __unused ) {
+ /* Do nothing */
+ return 0;
+}
+
+static void cipher_null_setiv ( void *ctx __unused,
+ const void *iv __unused ) {
+ /* Do nothing */
+}
+
+static void cipher_null_encrypt ( void *ctx __unused, const void *src,
+ void *dst, size_t len ) {
+ memcpy ( dst, src, len );
+}
+
+static void cipher_null_decrypt ( void *ctx __unused, const void *src,
+ void *dst, size_t len ) {
+ memcpy ( dst, src, len );
+}
+
+struct cipher_algorithm cipher_null = {
+ .name = "null",
+ .ctxsize = 0,
+ .blocksize = 1,
+ .setkey = cipher_null_setkey,
+ .setiv = cipher_null_setiv,
+ .encrypt = cipher_null_encrypt,
+ .decrypt = cipher_null_decrypt,
+};
+
+static int pubkey_null_init ( void *ctx __unused, const void *key __unused,
+ size_t key_len __unused ) {
+ return 0;
+}
+
+static size_t pubkey_null_max_len ( void *ctx __unused ) {
+ return 0;
+}
+
+static int pubkey_null_encrypt ( void *ctx __unused,
+ const void *plaintext __unused,
+ size_t plaintext_len __unused,
+ void *ciphertext __unused ) {
+ return 0;
+}
+
+static int pubkey_null_decrypt ( void *ctx __unused,
+ const void *ciphertext __unused,
+ size_t ciphertext_len __unused,
+ void *plaintext __unused ) {
+ return 0;
+}
+
+static int pubkey_null_sign ( void *ctx __unused,
+ struct digest_algorithm *digest __unused,
+ const void *value __unused,
+ void *signature __unused ) {
+ return 0;
+}
+
+static int pubkey_null_verify ( void *ctx __unused,
+ struct digest_algorithm *digest __unused,
+ const void *value __unused,
+ const void *signature __unused ,
+ size_t signature_len __unused ) {
+ return 0;
+}
+
+static void pubkey_null_final ( void *ctx __unused ) {
+ /* Do nothing */
+}
+
+struct pubkey_algorithm pubkey_null = {
+ .name = "null",
+ .ctxsize = 0,
+ .init = pubkey_null_init,
+ .max_len = pubkey_null_max_len,
+ .encrypt = pubkey_null_encrypt,
+ .decrypt = pubkey_null_decrypt,
+ .sign = pubkey_null_sign,
+ .verify = pubkey_null_verify,
+ .final = pubkey_null_final,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/drbg.c b/src/VBox/Devices/PC/ipxe/src/crypto/drbg.c
new file mode 100644
index 00000000..809de372
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/drbg.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * DRBG mechanism
+ *
+ * This mechanism is designed to comply with ANS X9.82 Part 3-2007
+ * Section 9. This standard is not freely available, but most of the
+ * text appears to be shared with NIST SP 800-90, which can be
+ * downloaded from
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
+ *
+ * Where possible, references are given to both documents. In the
+ * case of any disagreement, ANS X9.82 takes priority over NIST SP
+ * 800-90. (In particular, note that some algorithms that are
+ * Approved by NIST SP 800-90 are not Approved by ANS X9.82.)
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/entropy.h>
+#include <ipxe/drbg.h>
+
+/**
+ * Instantiate DRBG
+ *
+ * @v state Algorithm state to be initialised
+ * @v personal Personalisation string
+ * @v personal_len Length of personalisation string
+ * @ret rc Return status code
+ *
+ * This is the Instantiate_function defined in ANS X9.82 Part 3-2007
+ * Section 9.2 (NIST SP 800-90 Section 9.1).
+ *
+ * Only a single security strength is supported, and prediction
+ * resistance is always enabled. The nonce is accounted for by
+ * increasing the entropy input, as per ANS X9.82 Part 3-2007 Section
+ * 8.4.2 (NIST SP 800-90 Section 8.6.7).
+ */
+int drbg_instantiate ( struct drbg_state *state, const void *personal,
+ size_t personal_len ) {
+ unsigned int entropy_bits = ( ( 3 * DRBG_SECURITY_STRENGTH + 1 ) / 2 );
+ size_t min_len = DRBG_MIN_ENTROPY_LEN_BYTES;
+ size_t max_len = DRBG_MAX_ENTROPY_LEN_BYTES;
+ uint8_t data[max_len];
+ int len;
+ int rc;
+
+ DBGC ( state, "DRBG %p instantiate\n", state );
+
+ /* Sanity checks */
+ assert ( state != NULL );
+
+ /* 1. If requested_instantiation_security_strength >
+ * highest_supported_security_strength, then return an
+ * ERROR_FLAG
+ */
+ if ( DRBG_SECURITY_STRENGTH > DRBG_MAX_SECURITY_STRENGTH ) {
+ DBGC ( state, "DRBG %p cannot support security strength %d\n",
+ state, DRBG_SECURITY_STRENGTH );
+ return -ENOTSUP;
+ }
+
+ /* 2. If prediction_resistance_flag is set, and prediction
+ * resistance is not supported, then return an ERROR_FLAG
+ *
+ * (Nothing to do since prediction resistance is always
+ * supported.)
+ */
+
+ /* 3. If the length of the personalization_string >
+ * max_personalization_string_length, return an ERROR_FLAG
+ */
+ if ( personal_len > DRBG_MAX_PERSONAL_LEN_BYTES ) {
+ DBGC ( state, "DRBG %p personalisation string too long (%zd "
+ "bytes)\n", state, personal_len );
+ return -ERANGE;
+ }
+
+ /* 4. Set security_strength to the nearest security strength
+ * greater than or equal to
+ * requested_instantiation_security_strength.
+ *
+ * (Nothing to do since we support only a single security
+ * strength.)
+ */
+
+ /* 5. Using the security_strength, select appropriate DRBG
+ * mechanism parameters.
+ *
+ * (Nothing to do since we support only a single security
+ * strength.)
+ */
+
+ /* 6. ( status, entropy_input ) = Get_entropy_input (
+ * security_strength, min_length, max_length,
+ * prediction_resistance_request )
+ * 7. If an ERROR is returned in step 6, return a
+ * CATASTROPHIC_ERROR_FLAG.
+ * 8. Obtain a nonce.
+ */
+ len = get_entropy_input ( entropy_bits, data, min_len,
+ sizeof ( data ) );
+ if ( len < 0 ) {
+ rc = len;
+ DBGC ( state, "DRBG %p could not get entropy input: %s\n",
+ state, strerror ( rc ) );
+ return rc;
+ }
+ assert ( len >= ( int ) min_len );
+ assert ( len <= ( int ) sizeof ( data ) );
+
+ /* 9. initial_working_state = Instantiate_algorithm (
+ * entropy_input, nonce, personalization_string ).
+ */
+ drbg_instantiate_algorithm ( state, data, len, personal, personal_len );
+
+ /* 10. Get a state_handle for a currently empty state. If an
+ * empty internal state cannot be found, return an
+ * ERROR_FLAG.
+ * 11. Set the internal state indicated by state_handle to
+ * the initial values for the internal state (i.e. set
+ * the working_state to the values returned as
+ * initial_working_state in step 9 and any other values
+ * required for the working_state, and set the
+ * administrative information to the appropriate values.
+ *
+ * (Almost nothing to do since the memory to hold the state
+ * was passed in by the caller and has already been updated
+ * in-situ.)
+ */
+ state->reseed_required = 0;
+ state->valid = 1;
+
+ /* 12. Return SUCCESS and state_handle. */
+ return 0;
+}
+
+/**
+ * Reseed DRBG
+ *
+ * @v state Algorithm state
+ * @v additional Additional input
+ * @v additional_len Length of additional input
+ * @ret rc Return status code
+ *
+ * This is the Reseed_function defined in ANS X9.82 Part 3-2007
+ * Section 9.3 (NIST SP 800-90 Section 9.2).
+ *
+ * Prediction resistance is always enabled.
+ */
+int drbg_reseed ( struct drbg_state *state, const void *additional,
+ size_t additional_len ) {
+ unsigned int entropy_bits = DRBG_SECURITY_STRENGTH;
+ size_t min_len = DRBG_MIN_ENTROPY_LEN_BYTES;
+ size_t max_len = DRBG_MAX_ENTROPY_LEN_BYTES;
+ uint8_t data[max_len];
+ int len;
+ int rc;
+
+ DBGC ( state, "DRBG %p reseed\n", state );
+
+ /* Sanity checks */
+ assert ( state != NULL );
+
+ /* 1. Using state_handle, obtain the current internal state.
+ * If state_handle indicates an invalid or empty internal
+ * state, return an ERROR_FLAG.
+ *
+ * (Almost nothing to do since the memory holding the internal
+ * state was passed in by the caller.)
+ */
+ if ( ! state->valid ) {
+ DBGC ( state, "DRBG %p not valid\n", state );
+ return -EINVAL;
+ }
+
+ /* 2. If prediction_resistance_request is set, and
+ * prediction_resistance_flag is not set, then return an
+ * ERROR_FLAG.
+ *
+ * (Nothing to do since prediction resistance is always
+ * supported.)
+ */
+
+ /* 3. If the length of the additional_input >
+ * max_additional_input_length, return an ERROR_FLAG.
+ */
+ if ( additional_len > DRBG_MAX_ADDITIONAL_LEN_BYTES ) {
+ DBGC ( state, "DRBG %p additional input too long (%zd bytes)\n",
+ state, additional_len );
+ return -ERANGE;
+ }
+
+ /* 4. ( status, entropy_input ) = Get_entropy_input (
+ * security_strength, min_length, max_length,
+ * prediction_resistance_request ).
+ *
+ * 5. If an ERROR is returned in step 4, return a
+ * CATASTROPHIC_ERROR_FLAG.
+ */
+ len = get_entropy_input ( entropy_bits, data, min_len,
+ sizeof ( data ) );
+ if ( len < 0 ) {
+ rc = len;
+ DBGC ( state, "DRBG %p could not get entropy input: %s\n",
+ state, strerror ( rc ) );
+ return rc;
+ }
+
+ /* 6. new_working_state = Reseed_algorithm ( working_state,
+ * entropy_input, additional_input ).
+ */
+ drbg_reseed_algorithm ( state, data, len, additional, additional_len );
+
+ /* 7. Replace the working_state in the internal state
+ * indicated by state_handle with the values of
+ * new_working_state obtained in step 6.
+ *
+ * (Nothing to do since the state has already been updated in-situ.)
+ */
+
+ /* 8. Return SUCCESS. */
+ return 0;
+}
+
+/**
+ * Generate pseudorandom bits using DRBG
+ *
+ * @v state Algorithm state
+ * @v additional Additional input
+ * @v additional_len Length of additional input
+ * @v prediction_resist Prediction resistance is required
+ * @v data Output buffer
+ * @v len Length of output buffer
+ * @ret rc Return status code
+ *
+ * This is the Generate_function defined in ANS X9.82 Part 3-2007
+ * Section 9.4 (NIST SP 800-90 Section 9.3).
+ *
+ * Requests must be for an integral number of bytes. Only a single
+ * security strength is supported. Prediction resistance is supported
+ * if requested.
+ */
+int drbg_generate ( struct drbg_state *state, const void *additional,
+ size_t additional_len, int prediction_resist,
+ void *data, size_t len ) {
+ int rc;
+
+ DBGC ( state, "DRBG %p generate\n", state );
+
+ /* Sanity checks */
+ assert ( state != NULL );
+ assert ( data != NULL );
+
+ /* 1. Using state_handle, obtain the current internal state
+ * for the instantiation. If state_handle indicates an
+ * invalid or empty internal state, then return an ERROR_FLAG.
+ *
+ * (Almost nothing to do since the memory holding the internal
+ * state was passed in by the caller.)
+ */
+ if ( ! state->valid ) {
+ DBGC ( state, "DRBG %p not valid\n", state );
+ return -EINVAL;
+ }
+
+ /* 2. If requested_number_of_bits >
+ * max_number_of_bits_per_request, then return an
+ * ERROR_FLAG.
+ */
+ if ( len > DRBG_MAX_GENERATED_LEN_BYTES ) {
+ DBGC ( state, "DRBG %p request too long (%zd bytes)\n",
+ state, len );
+ return -ERANGE;
+ }
+
+ /* 3. If requested_security_strength > the security_strength
+ * indicated in the internal state, then return an
+ * ERROR_FLAG.
+ *
+ * (Nothing to do since only a single security strength is
+ * supported.)
+ */
+
+ /* 4. If the length of the additional_input >
+ * max_additional_input_length, then return an ERROR_FLAG.
+ */
+ if ( additional_len > DRBG_MAX_ADDITIONAL_LEN_BYTES ) {
+ DBGC ( state, "DRBG %p additional input too long (%zd bytes)\n",
+ state, additional_len );
+ return -ERANGE;
+ }
+
+ /* 5. If prediction_resistance_request is set, and
+ * prediction_resistance_flag is not set, then return an
+ * ERROR_FLAG.
+ *
+ * (Nothing to do since prediction resistance is always
+ * supported.)
+ */
+
+ /* 6. Clear the reseed_required_flag. */
+ state->reseed_required = 0;
+
+ step_7:
+ /* 7. If reseed_required_flag is set, or if
+ * prediction_resistance_request is set, then
+ */
+ if ( state->reseed_required || prediction_resist ) {
+
+ /* 7.1 status = Reseed_function ( state_handle,
+ * prediction_resistance_request,
+ * additional_input )
+ * 7.2 If status indicates an ERROR, then return
+ * status.
+ */
+ if ( ( rc = drbg_reseed ( state, additional,
+ additional_len ) ) != 0 ) {
+ DBGC ( state, "DRBG %p could not reseed: %s\n",
+ state, strerror ( rc ) );
+ return rc;
+ }
+
+ /* 7.3 Using state_handle, obtain the new internal
+ * state.
+ *
+ * (Nothing to do since the internal state has been
+ * updated in-situ.)
+ */
+
+ /* 7.4 additional_input = the Null string. */
+ additional = NULL;
+ additional_len = 0;
+
+ /* 7.5 Clear the reseed_required_flag. */
+ state->reseed_required = 0;
+ }
+
+ /* 8. ( status, pseudorandom_bits, new_working_state ) =
+ * Generate_algorithm ( working_state,
+ * requested_number_of_bits, additional_input ).
+ */
+ rc = drbg_generate_algorithm ( state, additional, additional_len,
+ data, len );
+
+ /* 9. If status indicates that a reseed is required before
+ * the requested bits can be generated, then
+ */
+ if ( rc != 0 ) {
+
+ /* 9.1 Set the reseed_required_flag. */
+ state->reseed_required = 1;
+
+ /* 9.2 If the prediction_resistance_flag is set, then
+ * set the prediction_resistance_request
+ * indication.
+ */
+ prediction_resist = 1;
+
+ /* 9.3 Go to step 7. */
+ goto step_7;
+ }
+
+ /* 10. Replace the old working_state in the internal state
+ * indicated by state_handle with the values of
+ * new_working_state.
+ *
+ * (Nothing to do since the working state has already been
+ * updated in-situ.)
+ */
+
+ /* 11. Return SUCCESS and pseudorandom_bits. */
+ return 0;
+}
+
+/**
+ * Uninstantiate DRBG
+ *
+ * @v state Algorithm state
+ *
+ * This is the Uninstantiate_function defined in ANS X9.82 Part 3-2007
+ * Section 9.5 (NIST SP 800-90 Section 9.4).
+ */
+void drbg_uninstantiate ( struct drbg_state *state ) {
+
+ DBGC ( state, "DRBG %p uninstantiate\n", state );
+
+ /* Sanity checks */
+ assert ( state != NULL );
+
+ /* 1. If state_handle indicates an invalid state, then return
+ * an ERROR_FLAG.
+ *
+ * (Nothing to do since the memory holding the internal state
+ * was passed in by the caller.)
+ */
+
+ /* 2. Erase the contents of the internal state indicated by
+ * state_handle.
+ */
+ memset ( state, 0, sizeof ( *state ) );
+
+ /* 3. Return SUCCESS. */
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/entropy.c b/src/VBox/Devices/PC/ipxe/src/crypto/entropy.c
new file mode 100644
index 00000000..03e7290a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/entropy.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Entropy source
+ *
+ * This algorithm is designed to comply with ANS X9.82 Part 4 (April
+ * 2011 Draft) Section 13.3. This standard is unfortunately not
+ * freely available.
+ */
+
+#include <stdint.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/crypto.h>
+#include <ipxe/hash_df.h>
+#include <ipxe/entropy.h>
+
+/* Disambiguate the various error causes */
+#define EPIPE_REPETITION_COUNT_TEST \
+ __einfo_error ( EINFO_EPIPE_REPETITION_COUNT_TEST )
+#define EINFO_EPIPE_REPETITION_COUNT_TEST \
+ __einfo_uniqify ( EINFO_EPIPE, 0x01, "Repetition count test failed" )
+#define EPIPE_ADAPTIVE_PROPORTION_TEST \
+ __einfo_error ( EINFO_EPIPE_ADAPTIVE_PROPORTION_TEST )
+#define EINFO_EPIPE_ADAPTIVE_PROPORTION_TEST \
+ __einfo_uniqify ( EINFO_EPIPE, 0x02, "Adaptive proportion test failed" )
+
+/**
+ * Calculate cutoff value for the repetition count test
+ *
+ * @ret cutoff Cutoff value
+ *
+ * This is the cutoff value for the Repetition Count Test defined in
+ * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.2.
+ */
+static inline __attribute__ (( always_inline )) unsigned int
+repetition_count_cutoff ( void ) {
+ double max_repetitions;
+ unsigned int cutoff;
+
+ /* The cutoff formula for the repetition test is:
+ *
+ * C = ( 1 + ( -log2(W) / H_min ) )
+ *
+ * where W is set at 2^(-30) (in ANS X9.82 Part 2 (October
+ * 2011 Draft) Section 8.5.2.1.3.1).
+ */
+ max_repetitions = ( 1 + ( 30 / min_entropy_per_sample() ) );
+
+ /* Round up to a whole number of repetitions. We don't have
+ * the ceil() function available, so do the rounding by hand.
+ */
+ cutoff = max_repetitions;
+ if ( cutoff < max_repetitions )
+ cutoff++;
+ linker_assert ( ( cutoff >= max_repetitions ), rounding_error );
+
+ /* Floating-point operations are not allowed in iPXE since we
+ * never set up a suitable environment. Abort the build
+ * unless the calculated number of repetitions is a
+ * compile-time constant.
+ */
+ linker_assert ( __builtin_constant_p ( cutoff ),
+ repetition_count_cutoff_not_constant );
+
+ return cutoff;
+}
+
+/**
+ * Perform repetition count test
+ *
+ * @v sample Noise sample
+ * @ret rc Return status code
+ *
+ * This is the Repetition Count Test defined in ANS X9.82 Part 2
+ * (October 2011 Draft) Section 8.5.2.1.2.
+ */
+static int repetition_count_test ( noise_sample_t sample ) {
+ static noise_sample_t most_recent_sample;
+ static unsigned int repetition_count = 0;
+
+ /* A = the most recently seen sample value
+ * B = the number of times that value A has been seen in a row
+ * C = the cutoff value above which the repetition test should fail
+ */
+
+ /* 1. For each new sample processed:
+ *
+ * (Note that the test for "repetition_count > 0" ensures that
+ * the initial value of most_recent_sample is treated as being
+ * undefined.)
+ */
+ if ( ( sample == most_recent_sample ) && ( repetition_count > 0 ) ) {
+
+ /* a) If the new sample = A, then B is incremented by one. */
+ repetition_count++;
+
+ /* i. If B >= C, then an error condition is raised
+ * due to a failure of the test
+ */
+ if ( repetition_count >= repetition_count_cutoff() )
+ return -EPIPE_REPETITION_COUNT_TEST;
+
+ } else {
+
+ /* b) Else:
+ * i. A = new sample
+ */
+ most_recent_sample = sample;
+
+ /* ii. B = 1 */
+ repetition_count = 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Window size for the adaptive proportion test
+ *
+ * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.1.1 allows
+ * five possible window sizes: 16, 64, 256, 4096 and 65536.
+ *
+ * We expect to generate relatively few (<256) entropy samples during
+ * a typical iPXE run; the use of a large window size would mean that
+ * the test would never complete a single cycle. We use a window size
+ * of 64, which is the smallest window size that permits values of
+ * H_min down to one bit per sample.
+ */
+#define ADAPTIVE_PROPORTION_WINDOW_SIZE 64
+
+/**
+ * Combine adaptive proportion test window size and min-entropy
+ *
+ * @v n N (window size)
+ * @v h H (min-entropy)
+ * @ret n_h (N,H) combined value
+ */
+#define APC_N_H( n, h ) ( ( (n) << 8 ) | (h) )
+
+/**
+ * Define a row of the adaptive proportion cutoff table
+ *
+ * @v h H (min-entropy)
+ * @v c16 Cutoff for N=16
+ * @v c64 Cutoff for N=64
+ * @v c256 Cutoff for N=256
+ * @v c4096 Cutoff for N=4096
+ * @v c65536 Cutoff for N=65536
+ */
+#define APC_TABLE_ROW( h, c16, c64, c256, c4096, c65536) \
+ case APC_N_H ( 16, h ) : return c16; \
+ case APC_N_H ( 64, h ) : return c64; \
+ case APC_N_H ( 256, h ) : return c256; \
+ case APC_N_H ( 4096, h ) : return c4096; \
+ case APC_N_H ( 65536, h ) : return c65536;
+
+/** Value used to represent "N/A" in adaptive proportion cutoff table */
+#define APC_NA 0
+
+/**
+ * Look up value in adaptive proportion test cutoff table
+ *
+ * @v n N (window size)
+ * @v h H (min-entropy)
+ * @ret cutoff Cutoff
+ *
+ * This is the table of cutoff values defined in ANS X9.82 Part 2
+ * (October 2011 Draft) Section 8.5.2.1.3.1.2.
+ */
+static inline __attribute__ (( always_inline )) unsigned int
+adaptive_proportion_cutoff_lookup ( unsigned int n, unsigned int h ) {
+ switch ( APC_N_H ( n, h ) ) {
+ APC_TABLE_ROW ( 1, APC_NA, 51, 168, 2240, 33537 );
+ APC_TABLE_ROW ( 2, APC_NA, 35, 100, 1193, 17053 );
+ APC_TABLE_ROW ( 3, 10, 24, 61, 643, 8705 );
+ APC_TABLE_ROW ( 4, 8, 16, 38, 354, 4473 );
+ APC_TABLE_ROW ( 5, 6, 12, 25, 200, 2321 );
+ APC_TABLE_ROW ( 6, 5, 9, 17, 117, 1220 );
+ APC_TABLE_ROW ( 7, 4, 7, 15, 71, 653 );
+ APC_TABLE_ROW ( 8, 4, 5, 9, 45, 358 );
+ APC_TABLE_ROW ( 9, 3, 4, 7, 30, 202 );
+ APC_TABLE_ROW ( 10, 3, 4, 5, 21, 118 );
+ APC_TABLE_ROW ( 11, 2, 3, 4, 15, 71 );
+ APC_TABLE_ROW ( 12, 2, 3, 4, 11, 45 );
+ APC_TABLE_ROW ( 13, 2, 2, 3, 9, 30 );
+ APC_TABLE_ROW ( 14, 2, 2, 3, 7, 21 );
+ APC_TABLE_ROW ( 15, 1, 2, 2, 6, 15 );
+ APC_TABLE_ROW ( 16, 1, 2, 2, 5, 11 );
+ APC_TABLE_ROW ( 17, 1, 1, 2, 4, 9 );
+ APC_TABLE_ROW ( 18, 1, 1, 2, 4, 7 );
+ APC_TABLE_ROW ( 19, 1, 1, 1, 3, 6 );
+ APC_TABLE_ROW ( 20, 1, 1, 1, 3, 5 );
+ default:
+ return APC_NA;
+ }
+}
+
+/**
+ * Calculate cutoff value for the adaptive proportion test
+ *
+ * @ret cutoff Cutoff value
+ *
+ * This is the cutoff value for the Adaptive Proportion Test defined
+ * in ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.1.2.
+ */
+static inline __attribute__ (( always_inline )) unsigned int
+adaptive_proportion_cutoff ( void ) {
+ unsigned int h;
+ unsigned int n;
+ unsigned int cutoff;
+
+ /* Look up cutoff value in cutoff table */
+ n = ADAPTIVE_PROPORTION_WINDOW_SIZE;
+ h = min_entropy_per_sample();
+ cutoff = adaptive_proportion_cutoff_lookup ( n, h );
+
+ /* Fail unless cutoff value is a build-time constant */
+ linker_assert ( __builtin_constant_p ( cutoff ),
+ adaptive_proportion_cutoff_not_constant );
+
+ /* Fail if cutoff value is N/A */
+ linker_assert ( ( cutoff != APC_NA ),
+ adaptive_proportion_cutoff_not_applicable );
+
+ return cutoff;
+}
+
+/**
+ * Perform adaptive proportion test
+ *
+ * @v sample Noise sample
+ * @ret rc Return status code
+ *
+ * This is the Adaptive Proportion Test for the Most Common Value
+ * defined in ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.
+ */
+static int adaptive_proportion_test ( noise_sample_t sample ) {
+ static noise_sample_t current_counted_sample;
+ static unsigned int sample_count = ADAPTIVE_PROPORTION_WINDOW_SIZE;
+ static unsigned int repetition_count;
+
+ /* A = the sample value currently being counted
+ * B = the number of samples examined in this run of the test so far
+ * N = the total number of samples that must be observed in
+ * one run of the test, also known as the "window size" of
+ * the test
+ * B = the current number of times that S (sic) has been seen
+ * in the W (sic) samples examined so far
+ * C = the cutoff value above which the repetition test should fail
+ * W = the probability of a false positive: 2^-30
+ */
+
+ /* 1. The entropy source draws the current sample from the
+ * noise source.
+ *
+ * (Nothing to do; we already have the current sample.)
+ */
+
+ /* 2. If S = N, then a new run of the test begins: */
+ if ( sample_count == ADAPTIVE_PROPORTION_WINDOW_SIZE ) {
+
+ /* a. A = the current sample */
+ current_counted_sample = sample;
+
+ /* b. S = 0 */
+ sample_count = 0;
+
+ /* c. B = 0 */
+ repetition_count = 0;
+
+ } else {
+
+ /* Else: (the test is already running)
+ * a. S = S + 1
+ */
+ sample_count++;
+
+ /* b. If A = the current sample, then: */
+ if ( sample == current_counted_sample ) {
+
+ /* i. B = B + 1 */
+ repetition_count++;
+
+ /* ii. If S (sic) > C then raise an error
+ * condition, because the test has
+ * detected a failure
+ */
+ if ( repetition_count > adaptive_proportion_cutoff() )
+ return -EPIPE_ADAPTIVE_PROPORTION_TEST;
+
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Get entropy sample
+ *
+ * @ret entropy Entropy sample
+ * @ret rc Return status code
+ *
+ * This is the GetEntropy function defined in ANS X9.82 Part 2
+ * (October 2011 Draft) Section 6.5.1.
+ */
+static int get_entropy ( entropy_sample_t *entropy ) {
+ static int rc = 0;
+ noise_sample_t noise;
+
+ /* Any failure is permanent */
+ if ( rc != 0 )
+ return rc;
+
+ /* Get noise sample */
+ if ( ( rc = get_noise ( &noise ) ) != 0 )
+ return rc;
+
+ /* Perform Repetition Count Test and Adaptive Proportion Test
+ * as mandated by ANS X9.82 Part 2 (October 2011 Draft)
+ * Section 8.5.2.1.1.
+ */
+ if ( ( rc = repetition_count_test ( noise ) ) != 0 )
+ return rc;
+ if ( ( rc = adaptive_proportion_test ( noise ) ) != 0 )
+ return rc;
+
+ /* We do not use any optional conditioning component */
+ *entropy = noise;
+
+ return 0;
+}
+
+/**
+ * Calculate number of samples required for startup tests
+ *
+ * @ret num_samples Number of samples required
+ *
+ * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.5 requires
+ * that at least one full cycle of the continuous tests must be
+ * performed at start-up.
+ */
+static inline __attribute__ (( always_inline )) unsigned int
+startup_test_count ( void ) {
+ unsigned int num_samples;
+
+ /* At least max(N,C) samples shall be generated by the noise
+ * source for start-up testing.
+ */
+ num_samples = repetition_count_cutoff();
+ if ( num_samples < adaptive_proportion_cutoff() )
+ num_samples = adaptive_proportion_cutoff();
+ linker_assert ( __builtin_constant_p ( num_samples ),
+ startup_test_count_not_constant );
+
+ return num_samples;
+}
+
+/**
+ * Create next nonce value
+ *
+ * @ret nonce Nonce
+ *
+ * This is the MakeNextNonce function defined in ANS X9.82 Part 4
+ * (April 2011 Draft) Section 13.3.4.2.
+ */
+static uint32_t make_next_nonce ( void ) {
+ static uint32_t nonce;
+
+ /* The simplest implementation of a nonce uses a large counter */
+ nonce++;
+
+ return nonce;
+}
+
+/**
+ * Obtain entropy input temporary buffer
+ *
+ * @v num_samples Number of entropy samples
+ * @v tmp Temporary buffer
+ * @v tmp_len Length of temporary buffer
+ * @ret rc Return status code
+ *
+ * This is (part of) the implementation of the Get_entropy_input
+ * function (using an entropy source as the source of entropy input
+ * and condensing each entropy source output after each GetEntropy
+ * call) as defined in ANS X9.82 Part 4 (April 2011 Draft) Section
+ * 13.3.4.2.
+ *
+ * To minimise code size, the number of samples required is calculated
+ * at compilation time.
+ */
+int get_entropy_input_tmp ( unsigned int num_samples, uint8_t *tmp,
+ size_t tmp_len ) {
+ static unsigned int startup_tested = 0;
+ struct {
+ uint32_t nonce;
+ entropy_sample_t sample;
+ } __attribute__ (( packed )) data;;
+ uint8_t df_buf[tmp_len];
+ unsigned int i;
+ int rc;
+
+ /* Enable entropy gathering */
+ if ( ( rc = entropy_enable() ) != 0 )
+ return rc;
+
+ /* Perform mandatory startup tests, if not yet performed */
+ for ( ; startup_tested < startup_test_count() ; startup_tested++ ) {
+ if ( ( rc = get_entropy ( &data.sample ) ) != 0 )
+ goto err_get_entropy;
+ }
+
+ /* 3. entropy_total = 0
+ *
+ * (Nothing to do; the number of entropy samples required has
+ * already been precalculated.)
+ */
+
+ /* 4. tmp = a fixed n-bit value, such as 0^n */
+ memset ( tmp, 0, tmp_len );
+
+ /* 5. While ( entropy_total < min_entropy ) */
+ while ( num_samples-- ) {
+ /* 5.1. ( status, entropy_bitstring, assessed_entropy )
+ * = GetEntropy()
+ * 5.2. If status indicates an error, return ( status, Null )
+ */
+ if ( ( rc = get_entropy ( &data.sample ) ) != 0 )
+ goto err_get_entropy;
+
+ /* 5.3. nonce = MakeNextNonce() */
+ data.nonce = make_next_nonce();
+
+ /* 5.4. tmp = tmp XOR
+ * df ( ( nonce || entropy_bitstring ), n )
+ */
+ hash_df ( &entropy_hash_df_algorithm, &data, sizeof ( data ),
+ df_buf, sizeof ( df_buf ) );
+ for ( i = 0 ; i < tmp_len ; i++ )
+ tmp[i] ^= df_buf[i];
+
+ /* 5.5. entropy_total = entropy_total + assessed_entropy
+ *
+ * (Nothing to do; the number of entropy samples
+ * required has already been precalculated.)
+ */
+ }
+
+ /* Disable entropy gathering */
+ entropy_disable();
+
+ return 0;
+
+ err_get_entropy:
+ entropy_disable();
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/hash_df.c b/src/VBox/Devices/PC/ipxe/src/crypto/hash_df.c
new file mode 100644
index 00000000..250c2ffc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/hash_df.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Hash-based derivation function (Hash_df)
+ *
+ * This algorithm is designed to comply with ANS X9.82 Part 3-2007
+ * Section 10.5.2. This standard is not freely available, but most of
+ * the text appears to be shared with NIST SP 800-90, which can be
+ * downloaded from
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
+ *
+ * Where possible, references are given to both documents. In the
+ * case of any disagreement, ANS X9.82 takes priority over NIST SP
+ * 800-90. (In particular, note that some algorithms that are
+ * Approved by NIST SP 800-90 are not Approved by ANS X9.82.)
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/crypto.h>
+#include <ipxe/hash_df.h>
+
+/**
+ * Distribute entropy throughout a buffer
+ *
+ * @v hash Underlying hash algorithm
+ * @v input Input data
+ * @v input_len Length of input data, in bytes
+ * @v output Output buffer
+ * @v output_len Length of output buffer, in bytes
+ *
+ * This is the Hash_df function defined in ANS X9.82 Part 3-2007
+ * Section 10.5.2 (NIST SP 800-90 Section 10.4.1).
+ *
+ * The number of bits requested is implicit in the length of the
+ * output buffer. Requests must be for an integral number of bytes.
+ *
+ * The output buffer is filled incrementally with each iteration of
+ * the central loop, rather than constructing an overall "temp" and
+ * then taking the leftmost(no_of_bits_to_return) bits.
+ *
+ * There is no way for the Hash_df function to fail. The returned
+ * status SUCCESS is implicit.
+ */
+void hash_df ( struct digest_algorithm *hash, const void *input,
+ size_t input_len, void *output, size_t output_len ) {
+ uint8_t context[hash->ctxsize];
+ uint8_t digest[hash->digestsize];
+ size_t frag_len;
+ struct {
+ uint8_t pad[3];
+ uint8_t counter;
+ uint32_t no_of_bits_to_return;
+ } __attribute__ (( packed )) prefix;
+ void *temp;
+ size_t remaining;
+
+ DBGC ( &hash_df, "HASH_DF input:\n" );
+ DBGC_HDA ( &hash_df, 0, input, input_len );
+
+ /* Sanity checks */
+ assert ( input != NULL );
+ assert ( output != NULL );
+
+ /* 1. temp = the Null string
+ * 2. len = ceil ( no_of_bits_to_return / outlen )
+ *
+ * (Nothing to do. We fill the output buffer incrementally,
+ * rather than constructing the complete "temp" in-memory.
+ * "len" is implicit in the number of iterations required to
+ * fill the output buffer, and so is not calculated
+ * explicitly.)
+ */
+
+ /* 3. counter = an 8-bit binary value representing the integer "1" */
+ prefix.counter = 1;
+
+ /* 4. For i = 1 to len do */
+ for ( temp = output, remaining = output_len ; remaining > 0 ; ) {
+
+ /* Comment: in step 5.1 (sic), no_of_bits_to_return is
+ * used as a 32-bit string.
+ *
+ * 4.1 temp = temp || Hash ( counter || no_of_bits_to_return
+ * || input_string )
+ */
+ prefix.no_of_bits_to_return = htonl ( output_len * 8 );
+ digest_init ( hash, context );
+ digest_update ( hash, context, &prefix.counter,
+ ( sizeof ( prefix ) -
+ offsetof ( typeof ( prefix ), counter ) ) );
+ digest_update ( hash, context, input, input_len );
+ digest_final ( hash, context, digest );
+
+ /* 4.2 counter = counter + 1 */
+ prefix.counter++;
+
+ /* 5. requested_bits = Leftmost ( no_of_bits_to_return )
+ * of temp
+ *
+ * (We fill the output buffer incrementally.)
+ */
+ frag_len = sizeof ( digest );
+ if ( frag_len > remaining )
+ frag_len = remaining;
+ memcpy ( temp, digest, frag_len );
+ temp += frag_len;
+ remaining -= frag_len;
+ }
+
+ /* 6. Return SUCCESS and requested_bits */
+ DBGC ( &hash_df, "HASH_DF output:\n" );
+ DBGC_HDA ( &hash_df, 0, output, output_len );
+ return;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/hmac.c b/src/VBox/Devices/PC/ipxe/src/crypto/hmac.c
new file mode 100644
index 00000000..6b61dc44
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/hmac.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Keyed-Hashing for Message Authentication
+ */
+
+#include <string.h>
+#include <assert.h>
+#include <ipxe/crypto.h>
+#include <ipxe/hmac.h>
+
+/**
+ * Reduce HMAC key length
+ *
+ * @v digest Digest algorithm to use
+ * @v digest_ctx Digest context
+ * @v key Key
+ * @v key_len Length of key
+ */
+static void hmac_reduce_key ( struct digest_algorithm *digest,
+ void *key, size_t *key_len ) {
+ uint8_t digest_ctx[digest->ctxsize];
+
+ digest_init ( digest, digest_ctx );
+ digest_update ( digest, digest_ctx, key, *key_len );
+ digest_final ( digest, digest_ctx, key );
+ *key_len = digest->digestsize;
+}
+
+/**
+ * Initialise HMAC
+ *
+ * @v digest Digest algorithm to use
+ * @v digest_ctx Digest context
+ * @v key Key
+ * @v key_len Length of key
+ *
+ * The length of the key should be less than the block size of the
+ * digest algorithm being used. (If the key length is greater, it
+ * will be replaced with its own digest, and key_len will be updated
+ * accordingly).
+ */
+void hmac_init ( struct digest_algorithm *digest, void *digest_ctx,
+ void *key, size_t *key_len ) {
+ unsigned char k_ipad[digest->blocksize];
+ unsigned int i;
+
+ /* Reduce key if necessary */
+ if ( *key_len > sizeof ( k_ipad ) )
+ hmac_reduce_key ( digest, key, key_len );
+
+ /* Construct input pad */
+ memset ( k_ipad, 0, sizeof ( k_ipad ) );
+ memcpy ( k_ipad, key, *key_len );
+ for ( i = 0 ; i < sizeof ( k_ipad ) ; i++ ) {
+ k_ipad[i] ^= 0x36;
+ }
+
+ /* Start inner hash */
+ digest_init ( digest, digest_ctx );
+ digest_update ( digest, digest_ctx, k_ipad, sizeof ( k_ipad ) );
+}
+
+/**
+ * Finalise HMAC
+ *
+ * @v digest Digest algorithm to use
+ * @v digest_ctx Digest context
+ * @v key Key
+ * @v key_len Length of key
+ * @v hmac HMAC digest to fill in
+ *
+ * The length of the key should be less than the block size of the
+ * digest algorithm being used. (If the key length is greater, it
+ * will be replaced with its own digest, and key_len will be updated
+ * accordingly).
+ */
+void hmac_final ( struct digest_algorithm *digest, void *digest_ctx,
+ void *key, size_t *key_len, void *hmac ) {
+ unsigned char k_opad[digest->blocksize];
+ unsigned int i;
+
+ /* Reduce key if necessary */
+ if ( *key_len > sizeof ( k_opad ) )
+ hmac_reduce_key ( digest, key, key_len );
+
+ /* Construct output pad */
+ memset ( k_opad, 0, sizeof ( k_opad ) );
+ memcpy ( k_opad, key, *key_len );
+ for ( i = 0 ; i < sizeof ( k_opad ) ; i++ ) {
+ k_opad[i] ^= 0x5c;
+ }
+
+ /* Finish inner hash */
+ digest_final ( digest, digest_ctx, hmac );
+
+ /* Perform outer hash */
+ digest_init ( digest, digest_ctx );
+ digest_update ( digest, digest_ctx, k_opad, sizeof ( k_opad ) );
+ digest_update ( digest, digest_ctx, hmac, digest->digestsize );
+ digest_final ( digest, digest_ctx, hmac );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/hmac_drbg.c b/src/VBox/Devices/PC/ipxe/src/crypto/hmac_drbg.c
new file mode 100644
index 00000000..3f56e1b7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/hmac_drbg.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * HMAC_DRBG algorithm
+ *
+ * This algorithm is designed to comply with ANS X9.82 Part 3-2007
+ * Section 10.2.2.2. This standard is not freely available, but most
+ * of the text appears to be shared with NIST SP 800-90, which can be
+ * downloaded from
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
+ *
+ * Where possible, references are given to both documents. In the
+ * case of any disagreement, ANS X9.82 takes priority over NIST SP
+ * 800-90. (In particular, note that some algorithms that are
+ * Approved by NIST SP 800-90 are not Approved by ANS X9.82.)
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/crypto.h>
+#include <ipxe/hmac.h>
+#include <ipxe/hmac_drbg.h>
+
+/**
+ * Update the HMAC_DRBG key
+ *
+ * @v hash Underlying hash algorithm
+ * @v state HMAC_DRBG internal state
+ * @v data Provided data
+ * @v len Length of provided data
+ * @v single Single byte used in concatenation
+ *
+ * This function carries out the operation
+ *
+ * K = HMAC ( K, V || single || provided_data )
+ *
+ * as used by hmac_drbg_update()
+ */
+static void hmac_drbg_update_key ( struct digest_algorithm *hash,
+ struct hmac_drbg_state *state,
+ const void *data, size_t len,
+ const uint8_t single ) {
+ uint8_t context[ hash->ctxsize ];
+ size_t out_len = hash->digestsize;
+
+ DBGC ( state, "HMAC_DRBG_%s %p provided data :\n", hash->name, state );
+ DBGC_HDA ( state, 0, data, len );
+
+ /* Sanity checks */
+ assert ( hash != NULL );
+ assert ( state != NULL );
+ assert ( ( data != NULL ) || ( len == 0 ) );
+ assert ( ( single == 0x00 ) || ( single == 0x01 ) );
+
+ /* K = HMAC ( K, V || single || provided_data ) */
+ hmac_init ( hash, context, state->key, &out_len );
+ assert ( out_len == hash->digestsize );
+ hmac_update ( hash, context, state->value, out_len );
+ hmac_update ( hash, context, &single, sizeof ( single ) );
+ hmac_update ( hash, context, data, len );
+ hmac_final ( hash, context, state->key, &out_len, state->key );
+ assert ( out_len == hash->digestsize );
+
+ DBGC ( state, "HMAC_DRBG_%s %p K = HMAC ( K, V || %#02x || "
+ "provided_data ) :\n", hash->name, state, single );
+ DBGC_HDA ( state, 0, state->key, out_len );
+}
+
+/**
+ * Update the HMAC_DRBG value
+ *
+ * @v hash Underlying hash algorithm
+ * @v state HMAC_DRBG internal state
+ * @v data Provided data
+ * @v len Length of provided data
+ * @v single Single byte used in concatenation
+ *
+ * This function carries out the operation
+ *
+ * V = HMAC ( K, V )
+ *
+ * as used by hmac_drbg_update() and hmac_drbg_generate()
+ */
+static void hmac_drbg_update_value ( struct digest_algorithm *hash,
+ struct hmac_drbg_state *state ) {
+ uint8_t context[ hash->ctxsize ];
+ size_t out_len = hash->digestsize;
+
+ /* Sanity checks */
+ assert ( hash != NULL );
+ assert ( state != NULL );
+
+ /* V = HMAC ( K, V ) */
+ hmac_init ( hash, context, state->key, &out_len );
+ assert ( out_len == hash->digestsize );
+ hmac_update ( hash, context, state->value, out_len );
+ hmac_final ( hash, context, state->key, &out_len, state->value );
+ assert ( out_len == hash->digestsize );
+
+ DBGC ( state, "HMAC_DRBG_%s %p V = HMAC ( K, V ) :\n",
+ hash->name, state );
+ DBGC_HDA ( state, 0, state->value, out_len );
+}
+
+/**
+ * Update HMAC_DRBG internal state
+ *
+ * @v hash Underlying hash algorithm
+ * @v state HMAC_DRBG internal state
+ * @v data Provided data
+ * @v len Length of provided data
+ *
+ * This is the HMAC_DRBG_Update function defined in ANS X9.82 Part
+ * 3-2007 Section 10.2.2.2.2 (NIST SP 800-90 Section 10.1.2.2).
+ *
+ * The key and value are updated in-place within the HMAC_DRBG
+ * internal state.
+ */
+static void hmac_drbg_update ( struct digest_algorithm *hash,
+ struct hmac_drbg_state *state,
+ const void *data, size_t len ) {
+
+ DBGC ( state, "HMAC_DRBG_%s %p update\n", hash->name, state );
+
+ /* Sanity checks */
+ assert ( hash != NULL );
+ assert ( state != NULL );
+ assert ( ( data != NULL ) || ( len == 0 ) );
+
+ /* 1. K = HMAC ( K, V || 0x00 || provided_data ) */
+ hmac_drbg_update_key ( hash, state, data, len, 0x00 );
+
+ /* 2. V = HMAC ( K, V ) */
+ hmac_drbg_update_value ( hash, state );
+
+ /* 3. If ( provided_data = Null ), then return K and V */
+ if ( ! len )
+ return;
+
+ /* 4. K = HMAC ( K, V || 0x01 || provided_data ) */
+ hmac_drbg_update_key ( hash, state, data, len, 0x01 );
+
+ /* 5. V = HMAC ( K, V ) */
+ hmac_drbg_update_value ( hash, state );
+
+ /* 6. Return K and V */
+}
+
+/**
+ * Instantiate HMAC_DRBG
+ *
+ * @v hash Underlying hash algorithm
+ * @v state HMAC_DRBG internal state to be initialised
+ * @v entropy Entropy input
+ * @v entropy_len Length of entropy input
+ * @v personal Personalisation string
+ * @v personal_len Length of personalisation string
+ *
+ * This is the HMAC_DRBG_Instantiate_algorithm function defined in ANS
+ * X9.82 Part 3-2007 Section 10.2.2.2.3 (NIST SP 800-90 Section
+ * 10.1.2.3).
+ *
+ * The nonce must be included within the entropy input (i.e. the
+ * entropy input must contain at least 3/2 * security_strength bits of
+ * entropy, as per ANS X9.82 Part 3-2007 Section 8.4.2 (NIST SP 800-90
+ * Section 8.6.7).
+ *
+ * The key, value and reseed counter are updated in-place within the
+ * HMAC_DRBG internal state.
+ */
+void hmac_drbg_instantiate ( struct digest_algorithm *hash,
+ struct hmac_drbg_state *state,
+ const void *entropy, size_t entropy_len,
+ const void *personal, size_t personal_len ){
+ size_t out_len = hash->digestsize;
+
+ DBGC ( state, "HMAC_DRBG_%s %p instantiate\n", hash->name, state );
+
+ /* Sanity checks */
+ assert ( hash != NULL );
+ assert ( state != NULL );
+ assert ( entropy != NULL );
+ assert ( ( personal != NULL ) || ( personal_len == 0 ) );
+
+ /* 1. seed_material = entropy_input || nonce ||
+ * personalisation_string
+ */
+
+ /* 2. Key = 0x00 00..00 */
+ memset ( state->key, 0x00, out_len );
+
+ /* 3. V = 0x01 01...01 */
+ memset ( state->value, 0x01, out_len );
+
+ /* 4. ( Key, V ) = HMAC_DBRG_Update ( seed_material, Key, V )
+ * 5. reseed_counter = 1
+ * 6. Return V, Key and reseed_counter as the
+ * initial_working_state
+ */
+ hmac_drbg_reseed ( hash, state, entropy, entropy_len,
+ personal, personal_len );
+}
+
+/**
+ * Reseed HMAC_DRBG
+ *
+ * @v hash Underlying hash algorithm
+ * @v state HMAC_DRBG internal state
+ * @v entropy Entropy input
+ * @v entropy_len Length of entropy input
+ * @v additional Additional input
+ * @v additional_len Length of additional input
+ *
+ * This is the HMAC_DRBG_Reseed_algorithm function defined in ANS X9.82
+ * Part 3-2007 Section 10.2.2.2.4 (NIST SP 800-90 Section 10.1.2.4).
+ *
+ * The key, value and reseed counter are updated in-place within the
+ * HMAC_DRBG internal state.
+ */
+void hmac_drbg_reseed ( struct digest_algorithm *hash,
+ struct hmac_drbg_state *state,
+ const void *entropy, size_t entropy_len,
+ const void *additional, size_t additional_len ) {
+ uint8_t seed_material[ entropy_len + additional_len ];
+
+ DBGC ( state, "HMAC_DRBG_%s %p (re)seed\n", hash->name, state );
+
+ /* Sanity checks */
+ assert ( hash != NULL );
+ assert ( state != NULL );
+ assert ( entropy != NULL );
+ assert ( ( additional != NULL ) || ( additional_len == 0 ) );
+
+ /* 1. seed_material = entropy_input || additional_input */
+ memcpy ( seed_material, entropy, entropy_len );
+ memcpy ( ( seed_material + entropy_len ), additional, additional_len );
+ DBGC ( state, "HMAC_DRBG_%s %p seed material :\n", hash->name, state );
+ DBGC_HDA ( state, 0, seed_material, sizeof ( seed_material ) );
+
+ /* 2. ( Key, V ) = HMAC_DBRG_Update ( seed_material, Key, V ) */
+ hmac_drbg_update ( hash, state, seed_material,
+ sizeof ( seed_material ) );
+
+ /* 3. reseed_counter = 1 */
+ state->reseed_counter = 1;
+
+ /* 4. Return V, Key and reseed_counter as the new_working_state */
+}
+
+/**
+ * Generate pseudorandom bits using HMAC_DRBG
+ *
+ * @v hash Underlying hash algorithm
+ * @v state HMAC_DRBG internal state
+ * @v additional Additional input
+ * @v additional_len Length of additional input
+ * @v data Output buffer
+ * @v len Length of output buffer
+ * @ret rc Return status code
+ *
+ * This is the HMAC_DRBG_Generate_algorithm function defined in ANS X9.82
+ * Part 3-2007 Section 10.2.2.2.5 (NIST SP 800-90 Section 10.1.2.5).
+ *
+ * Requests must be for an integral number of bytes.
+ *
+ * The key, value and reseed counter are updated in-place within the
+ * HMAC_DRBG internal state.
+ *
+ * Note that the only permitted error is "reseed required".
+ */
+int hmac_drbg_generate ( struct digest_algorithm *hash,
+ struct hmac_drbg_state *state,
+ const void *additional, size_t additional_len,
+ void *data, size_t len ) {
+ size_t out_len = hash->digestsize;
+ void *orig_data = data;
+ size_t orig_len = len;
+ size_t frag_len;
+
+ DBGC ( state, "HMAC_DRBG_%s %p generate\n", hash->name, state );
+
+ /* Sanity checks */
+ assert ( hash != NULL );
+ assert ( state != NULL );
+ assert ( data != NULL );
+ assert ( ( additional != NULL ) || ( additional_len == 0 ) );
+
+ /* 1. If reseed_counter > reseed_interval, then return an
+ * indication that a reseed is required
+ */
+ if ( state->reseed_counter > HMAC_DRBG_RESEED_INTERVAL ) {
+ DBGC ( state, "HMAC_DRBG_%s %p reseed interval exceeded\n",
+ hash->name, state );
+ return -ESTALE;
+ }
+
+ /* 2. If additional_input != Null, then
+ * ( Key, V ) = HMAC_DRBG_Update ( additional_input, Key, V )
+ */
+ if ( additional_len )
+ hmac_drbg_update ( hash, state, additional, additional_len );
+
+ /* 3. temp = Null
+ * 4. While ( len ( temp ) < requested_number_of_bits ) do:
+ */
+ while ( len ) {
+
+ /* 4.1 V = HMAC ( Key, V ) */
+ hmac_drbg_update_value ( hash, state );
+
+ /* 4.2. temp = temp || V
+ * 5. returned_bits = Leftmost requested_number_of_bits
+ * of temp
+ */
+ frag_len = len;
+ if ( frag_len > out_len )
+ frag_len = out_len;
+ memcpy ( data, state->value, frag_len );
+ data += frag_len;
+ len -= frag_len;
+ }
+
+ /* 6. ( Key, V ) = HMAC_DRBG_Update ( additional_input, Key, V ) */
+ hmac_drbg_update ( hash, state, additional, additional_len );
+
+ /* 7. reseed_counter = reseed_counter + 1 */
+ state->reseed_counter++;
+
+ DBGC ( state, "HMAC_DRBG_%s %p generated :\n", hash->name, state );
+ DBGC_HDA ( state, 0, orig_data, orig_len );
+
+ /* 8. Return SUCCESS, returned_bits, and the new values of
+ * Key, V and reseed_counter as the new_working_state
+ */
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/md5.c b/src/VBox/Devices/PC/ipxe/src/crypto/md5.c
new file mode 100644
index 00000000..b8b7b43d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/md5.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * MD5 algorithm
+ *
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <byteswap.h>
+#include <assert.h>
+#include <ipxe/rotate.h>
+#include <ipxe/crypto.h>
+#include <ipxe/asn1.h>
+#include <ipxe/md5.h>
+
+/** MD5 variables */
+struct md5_variables {
+ /* This layout matches that of struct md5_digest_data,
+ * allowing for efficient endianness-conversion,
+ */
+ uint32_t a;
+ uint32_t b;
+ uint32_t c;
+ uint32_t d;
+ uint32_t w[16];
+} __attribute__ (( packed ));
+
+/** MD5 constants */
+static const uint32_t k[64] = {
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,
+ 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340,
+ 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,
+ 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,
+ 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,
+ 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+};
+
+/** MD5 shift amounts */
+static const uint8_t r[64] = {
+ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
+ 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
+ 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
+ 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
+};
+
+/**
+ * f(b,c,d) for steps 0 to 15
+ *
+ * @v v MD5 variables
+ * @ret f f(b,c,d)
+ */
+static uint32_t md5_f_0_15 ( struct md5_variables *v ) {
+ return ( v->d ^ ( v->b & ( v->c ^ v->d ) ) );
+}
+
+/**
+ * f(b,c,d) for steps 16 to 31
+ *
+ * @v v MD5 variables
+ * @ret f f(b,c,d)
+ */
+static uint32_t md5_f_16_31 ( struct md5_variables *v ) {
+ return ( v->c ^ ( v->d & ( v->b ^ v->c ) ) );
+}
+
+/**
+ * f(b,c,d) for steps 32 to 47
+ *
+ * @v v MD5 variables
+ * @ret f f(b,c,d)
+ */
+static uint32_t md5_f_32_47 ( struct md5_variables *v ) {
+ return ( v->b ^ v->c ^ v->d );
+}
+
+/**
+ * f(b,c,d) for steps 48 to 63
+ *
+ * @v v MD5 variables
+ * @ret f f(b,c,d)
+ */
+static uint32_t md5_f_48_63 ( struct md5_variables *v ) {
+ return ( v->c ^ ( v->b | (~v->d) ) );
+}
+
+/** An MD5 step function */
+struct md5_step {
+ /**
+ * Calculate f(b,c,d)
+ *
+ * @v v MD5 variables
+ * @ret f f(b,c,d)
+ */
+ uint32_t ( * f ) ( struct md5_variables *v );
+ /** Coefficient of i in g=ni+m */
+ uint8_t coefficient;
+ /** Constant term in g=ni+m */
+ uint8_t constant;
+};
+
+/** MD5 steps */
+static struct md5_step md5_steps[4] = {
+ /** 0 to 15 */
+ { .f = md5_f_0_15, .coefficient = 1, .constant = 0 },
+ /** 16 to 31 */
+ { .f = md5_f_16_31, .coefficient = 5, .constant = 1 },
+ /** 32 to 47 */
+ { .f = md5_f_32_47, .coefficient = 3, .constant = 5 },
+ /** 48 to 63 */
+ { .f = md5_f_48_63, .coefficient = 7, .constant = 0 },
+};
+
+/**
+ * Initialise MD5 algorithm
+ *
+ * @v ctx MD5 context
+ */
+static void md5_init ( void *ctx ) {
+ struct md5_context *context = ctx;
+
+ context->ddd.dd.digest.h[0] = cpu_to_le32 ( 0x67452301 );
+ context->ddd.dd.digest.h[1] = cpu_to_le32 ( 0xefcdab89 );
+ context->ddd.dd.digest.h[2] = cpu_to_le32 ( 0x98badcfe );
+ context->ddd.dd.digest.h[3] = cpu_to_le32 ( 0x10325476 );
+ context->len = 0;
+}
+
+/**
+ * Calculate MD5 digest of accumulated data
+ *
+ * @v context MD5 context
+ */
+static void md5_digest ( struct md5_context *context ) {
+ union {
+ union md5_digest_data_dwords ddd;
+ struct md5_variables v;
+ } u;
+ uint32_t *a = &u.v.a;
+ uint32_t *b = &u.v.b;
+ uint32_t *c = &u.v.c;
+ uint32_t *d = &u.v.d;
+ uint32_t *w = u.v.w;
+ uint32_t f;
+ uint32_t g;
+ uint32_t temp;
+ struct md5_step *step;
+ unsigned int i;
+
+ /* Sanity checks */
+ assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 );
+ linker_assert ( &u.ddd.dd.digest.h[0] == a, md5_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[1] == b, md5_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[2] == c, md5_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[3] == d, md5_bad_layout );
+ linker_assert ( &u.ddd.dd.data.dword[0] == w, md5_bad_layout );
+
+ DBGC ( context, "MD5 digesting:\n" );
+ DBGC_HDA ( context, 0, &context->ddd.dd.digest,
+ sizeof ( context->ddd.dd.digest ) );
+ DBGC_HDA ( context, context->len, &context->ddd.dd.data,
+ sizeof ( context->ddd.dd.data ) );
+
+ /* Convert h[0..3] to host-endian, and initialise a, b, c, d,
+ * and w[0..15]
+ */
+ for ( i = 0 ; i < ( sizeof ( u.ddd.dword ) /
+ sizeof ( u.ddd.dword[0] ) ) ; i++ ) {
+ le32_to_cpus ( &context->ddd.dword[i] );
+ u.ddd.dword[i] = context->ddd.dword[i];
+ }
+
+ /* Main loop */
+ for ( i = 0 ; i < 64 ; i++ ) {
+ step = &md5_steps[ i / 16 ];
+ f = step->f ( &u.v );
+ g = ( ( ( step->coefficient * i ) + step->constant ) % 16 );
+ temp = *d;
+ *d = *c;
+ *c = *b;
+ *b = ( *b + rol32 ( ( *a + f + k[i] + w[g] ), r[i] ) );
+ *a = temp;
+ DBGC2 ( context, "%2d : %08x %08x %08x %08x\n",
+ i, *a, *b, *c, *d );
+ }
+
+ /* Add chunk to hash and convert back to big-endian */
+ for ( i = 0 ; i < 4 ; i++ ) {
+ context->ddd.dd.digest.h[i] =
+ cpu_to_le32 ( context->ddd.dd.digest.h[i] +
+ u.ddd.dd.digest.h[i] );
+ }
+
+ DBGC ( context, "MD5 digested:\n" );
+ DBGC_HDA ( context, 0, &context->ddd.dd.digest,
+ sizeof ( context->ddd.dd.digest ) );
+}
+
+/**
+ * Accumulate data with MD5 algorithm
+ *
+ * @v ctx MD5 context
+ * @v data Data
+ * @v len Length of data
+ */
+static void md5_update ( void *ctx, const void *data, size_t len ) {
+ struct md5_context *context = ctx;
+ const uint8_t *byte = data;
+ size_t offset;
+
+ /* Accumulate data a byte at a time, performing the digest
+ * whenever we fill the data buffer
+ */
+ while ( len-- ) {
+ offset = ( context->len % sizeof ( context->ddd.dd.data ) );
+ context->ddd.dd.data.byte[offset] = *(byte++);
+ context->len++;
+ if ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 )
+ md5_digest ( context );
+ }
+}
+
+/**
+ * Generate MD5 digest
+ *
+ * @v ctx MD5 context
+ * @v out Output buffer
+ */
+static void md5_final ( void *ctx, void *out ) {
+ struct md5_context *context = ctx;
+ uint64_t len_bits;
+ uint8_t pad;
+
+ /* Record length before pre-processing */
+ len_bits = cpu_to_le64 ( ( ( uint64_t ) context->len ) * 8 );
+
+ /* Pad with a single "1" bit followed by as many "0" bits as required */
+ pad = 0x80;
+ do {
+ md5_update ( ctx, &pad, sizeof ( pad ) );
+ pad = 0x00;
+ } while ( ( context->len % sizeof ( context->ddd.dd.data ) ) !=
+ offsetof ( typeof ( context->ddd.dd.data ), final.len ) );
+
+ /* Append length (in bits) */
+ md5_update ( ctx, &len_bits, sizeof ( len_bits ) );
+ assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 );
+
+ /* Copy out final digest */
+ memcpy ( out, &context->ddd.dd.digest,
+ sizeof ( context->ddd.dd.digest ) );
+}
+
+/** MD5 algorithm */
+struct digest_algorithm md5_algorithm = {
+ .name = "md5",
+ .ctxsize = sizeof ( struct md5_context ),
+ .blocksize = sizeof ( union md5_block ),
+ .digestsize = sizeof ( struct md5_digest ),
+ .init = md5_init,
+ .update = md5_update,
+ .final = md5_final,
+};
+
+/** "md5" object identifier */
+static uint8_t oid_md5[] = { ASN1_OID_MD5 };
+
+/** "md5" OID-identified algorithm */
+struct asn1_algorithm oid_md5_algorithm __asn1_algorithm = {
+ .name = "md5",
+ .digest = &md5_algorithm,
+ .oid = ASN1_OID_CURSOR ( oid_md5 ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/null_entropy.c b/src/VBox/Devices/PC/ipxe/src/crypto/null_entropy.c
new file mode 100644
index 00000000..be2acae3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/null_entropy.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Nonexistent entropy source
+ *
+ *
+ * This source provides no entropy and must NOT be used in a
+ * security-sensitive environment.
+ */
+
+#include <ipxe/entropy.h>
+
+PROVIDE_ENTROPY_INLINE ( null, min_entropy_per_sample );
+PROVIDE_ENTROPY_INLINE ( null, entropy_enable );
+PROVIDE_ENTROPY_INLINE ( null, entropy_disable );
+PROVIDE_ENTROPY_INLINE ( null, get_noise );
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/ocsp.c b/src/VBox/Devices/PC/ipxe/src/crypto/ocsp.c
new file mode 100644
index 00000000..aac203d6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/ocsp.c
@@ -0,0 +1,758 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/asn1.h>
+#include <ipxe/x509.h>
+#include <ipxe/sha1.h>
+#include <ipxe/ocsp.h>
+
+/** @file
+ *
+ * Online Certificate Status Protocol
+ *
+ */
+
+/* Disambiguate the various error causes */
+#define EACCES_CERT_STATUS \
+ __einfo_error ( EINFO_EACCES_CERT_STATUS )
+#define EINFO_EACCES_CERT_STATUS \
+ __einfo_uniqify ( EINFO_EACCES, 0x01, \
+ "Certificate status not good" )
+#define EACCES_CERT_MISMATCH \
+ __einfo_error ( EINFO_EACCES_CERT_MISMATCH )
+#define EINFO_EACCES_CERT_MISMATCH \
+ __einfo_uniqify ( EINFO_EACCES, 0x02, \
+ "Certificate ID mismatch" )
+#define EACCES_NON_OCSP_SIGNING \
+ __einfo_error ( EINFO_EACCES_NON_OCSP_SIGNING )
+#define EINFO_EACCES_NON_OCSP_SIGNING \
+ __einfo_uniqify ( EINFO_EACCES, 0x03, \
+ "Not an OCSP signing certificate" )
+#define EACCES_STALE \
+ __einfo_error ( EINFO_EACCES_STALE )
+#define EINFO_EACCES_STALE \
+ __einfo_uniqify ( EINFO_EACCES, 0x04, \
+ "Stale (or premature) OCSP repsonse" )
+#define EPROTO_MALFORMED_REQUEST \
+ __einfo_error ( EINFO_EPROTO_MALFORMED_REQUEST )
+#define EINFO_EPROTO_MALFORMED_REQUEST \
+ __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_MALFORMED_REQUEST, \
+ "Illegal confirmation request" )
+#define EPROTO_INTERNAL_ERROR \
+ __einfo_error ( EINFO_EPROTO_INTERNAL_ERROR )
+#define EINFO_EPROTO_INTERNAL_ERROR \
+ __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_INTERNAL_ERROR, \
+ "Internal error in issuer" )
+#define EPROTO_TRY_LATER \
+ __einfo_error ( EINFO_EPROTO_TRY_LATER )
+#define EINFO_EPROTO_TRY_LATER \
+ __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_TRY_LATER, \
+ "Try again later" )
+#define EPROTO_SIG_REQUIRED \
+ __einfo_error ( EINFO_EPROTO_SIG_REQUIRED )
+#define EINFO_EPROTO_SIG_REQUIRED \
+ __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_SIG_REQUIRED, \
+ "Must sign the request" )
+#define EPROTO_UNAUTHORIZED \
+ __einfo_error ( EINFO_EPROTO_UNAUTHORIZED )
+#define EINFO_EPROTO_UNAUTHORIZED \
+ __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_UNAUTHORIZED, \
+ "Request unauthorized" )
+#define EPROTO_STATUS( status ) \
+ EUNIQ ( EPROTO, (status), EPROTO_MALFORMED_REQUEST, \
+ EPROTO_INTERNAL_ERROR, EPROTO_TRY_LATER, \
+ EPROTO_SIG_REQUIRED, EPROTO_UNAUTHORIZED )
+
+/** OCSP digest algorithm */
+#define ocsp_digest_algorithm sha1_algorithm
+
+/** OCSP digest algorithm identifier */
+static const uint8_t ocsp_algorithm_id[] =
+ { OCSP_ALGORITHM_IDENTIFIER ( ASN1_OID_SHA1 ) };
+
+/** OCSP basic response type */
+static const uint8_t oid_basic_response_type[] = { ASN1_OID_OCSP_BASIC };
+
+/** OCSP basic response type cursor */
+static struct asn1_cursor oid_basic_response_type_cursor =
+ ASN1_OID_CURSOR ( oid_basic_response_type );
+
+/**
+ * Free OCSP check
+ *
+ * @v refcnt Reference count
+ */
+static void ocsp_free ( struct refcnt *refcnt ) {
+ struct ocsp_check *ocsp =
+ container_of ( refcnt, struct ocsp_check, refcnt );
+
+ x509_put ( ocsp->cert );
+ x509_put ( ocsp->issuer );
+ free ( ocsp->request.builder.data );
+ free ( ocsp->response.data );
+ x509_put ( ocsp->response.signer );
+ free ( ocsp );
+}
+
+/**
+ * Build OCSP request
+ *
+ * @v ocsp OCSP check
+ * @ret rc Return status code
+ */
+static int ocsp_request ( struct ocsp_check *ocsp ) {
+ struct digest_algorithm *digest = &ocsp_digest_algorithm;
+ struct asn1_builder *builder = &ocsp->request.builder;
+ struct asn1_cursor *cert_id = &ocsp->request.cert_id;
+ uint8_t digest_ctx[digest->ctxsize];
+ uint8_t name_digest[digest->digestsize];
+ uint8_t pubkey_digest[digest->digestsize];
+ int rc;
+
+ /* Generate digests */
+ digest_init ( digest, digest_ctx );
+ digest_update ( digest, digest_ctx, ocsp->cert->issuer.raw.data,
+ ocsp->cert->issuer.raw.len );
+ digest_final ( digest, digest_ctx, name_digest );
+ digest_init ( digest, digest_ctx );
+ digest_update ( digest, digest_ctx,
+ ocsp->issuer->subject.public_key.raw_bits.data,
+ ocsp->issuer->subject.public_key.raw_bits.len );
+ digest_final ( digest, digest_ctx, pubkey_digest );
+
+ /* Construct request */
+ if ( ( rc = ( asn1_prepend_raw ( builder, ocsp->cert->serial.raw.data,
+ ocsp->cert->serial.raw.len ),
+ asn1_prepend ( builder, ASN1_OCTET_STRING,
+ pubkey_digest, sizeof ( pubkey_digest ) ),
+ asn1_prepend ( builder, ASN1_OCTET_STRING,
+ name_digest, sizeof ( name_digest ) ),
+ asn1_prepend ( builder, ASN1_SEQUENCE,
+ ocsp_algorithm_id,
+ sizeof ( ocsp_algorithm_id ) ),
+ asn1_wrap ( builder, ASN1_SEQUENCE ),
+ asn1_wrap ( builder, ASN1_SEQUENCE ),
+ asn1_wrap ( builder, ASN1_SEQUENCE ),
+ asn1_wrap ( builder, ASN1_SEQUENCE ),
+ asn1_wrap ( builder, ASN1_SEQUENCE ) ) ) != 0 ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" could not build request: %s\n",
+ ocsp, ocsp->cert->subject.name, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( ocsp, "OCSP %p \"%s\" request is:\n",
+ ocsp, ocsp->cert->subject.name );
+ DBGC2_HDA ( ocsp, 0, builder->data, builder->len );
+
+ /* Parse certificate ID for comparison with response */
+ cert_id->data = builder->data;
+ cert_id->len = builder->len;
+ if ( ( rc = ( asn1_enter ( cert_id, ASN1_SEQUENCE ),
+ asn1_enter ( cert_id, ASN1_SEQUENCE ),
+ asn1_enter ( cert_id, ASN1_SEQUENCE ),
+ asn1_enter ( cert_id, ASN1_SEQUENCE ) ) ) != 0 ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" could not locate certID: %s\n",
+ ocsp, ocsp->cert->subject.name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Create OCSP check
+ *
+ * @v cert Certificate to check
+ * @v issuer Issuing certificate
+ * @ret ocsp OCSP check
+ * @ret rc Return status code
+ */
+int ocsp_check ( struct x509_certificate *cert,
+ struct x509_certificate *issuer,
+ struct ocsp_check **ocsp ) {
+ int rc;
+
+ /* Sanity checks */
+ assert ( cert != NULL );
+ assert ( issuer != NULL );
+ assert ( issuer->valid );
+
+ /* Allocate and initialise check */
+ *ocsp = zalloc ( sizeof ( **ocsp ) );
+ if ( ! *ocsp ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ ref_init ( &(*ocsp)->refcnt, ocsp_free );
+ (*ocsp)->cert = x509_get ( cert );
+ (*ocsp)->issuer = x509_get ( issuer );
+
+ /* Build request */
+ if ( ( rc = ocsp_request ( *ocsp ) ) != 0 )
+ goto err_request;
+
+ return 0;
+
+ err_request:
+ ocsp_put ( *ocsp );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Parse OCSP response status
+ *
+ * @v ocsp OCSP check
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int ocsp_parse_response_status ( struct ocsp_check *ocsp,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ uint8_t status;
+ int rc;
+
+ /* Enter responseStatus */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ if ( ( rc = asn1_enter ( &cursor, ASN1_ENUMERATED ) ) != 0 ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" could not locate responseStatus: "
+ "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc ));
+ return rc;
+ }
+
+ /* Extract response status */
+ if ( cursor.len != sizeof ( status ) ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" invalid status:\n",
+ ocsp, ocsp->cert->subject.name );
+ DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
+ return -EINVAL;
+ }
+ memcpy ( &status, cursor.data, sizeof ( status ) );
+
+ /* Check response status */
+ if ( status != OCSP_STATUS_SUCCESSFUL ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" response status %d\n",
+ ocsp, ocsp->cert->subject.name, status );
+ return EPROTO_STATUS ( status );
+ }
+
+ return 0;
+}
+
+/**
+ * Parse OCSP response type
+ *
+ * @v ocsp OCSP check
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int ocsp_parse_response_type ( struct ocsp_check *ocsp,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+
+ /* Enter responseType */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_OID );
+
+ /* Check responseType is "basic" */
+ if ( asn1_compare ( &oid_basic_response_type_cursor, &cursor ) != 0 ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" response type not supported:\n",
+ ocsp, ocsp->cert->subject.name );
+ DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
+ return -ENOTSUP;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse OCSP certificate ID
+ *
+ * @v ocsp OCSP check
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int ocsp_parse_cert_id ( struct ocsp_check *ocsp,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+
+ /* Check certID matches request */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_shrink_any ( &cursor );
+ if ( asn1_compare ( &cursor, &ocsp->request.cert_id ) != 0 ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" certID mismatch:\n",
+ ocsp, ocsp->cert->subject.name );
+ DBGC_HDA ( ocsp, 0, ocsp->request.cert_id.data,
+ ocsp->request.cert_id.len );
+ DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
+ return -EACCES_CERT_MISMATCH;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse OCSP responses
+ *
+ * @v ocsp OCSP check
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int ocsp_parse_responses ( struct ocsp_check *ocsp,
+ const struct asn1_cursor *raw ) {
+ struct ocsp_response *response = &ocsp->response;
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter responses */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Enter first singleResponse */
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse certID */
+ if ( ( rc = ocsp_parse_cert_id ( ocsp, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Check certStatus */
+ if ( asn1_type ( &cursor ) != ASN1_IMPLICIT_TAG ( 0 ) ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" non-good certStatus:\n",
+ ocsp, ocsp->cert->subject.name );
+ DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
+ return -EACCES_CERT_STATUS;
+ }
+ asn1_skip_any ( &cursor );
+
+ /* Parse thisUpdate */
+ if ( ( rc = asn1_generalized_time ( &cursor,
+ &response->this_update ) ) != 0 ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" could not parse thisUpdate: %s\n",
+ ocsp, ocsp->cert->subject.name, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( ocsp, "OCSP %p \"%s\" this update was at time %lld\n",
+ ocsp, ocsp->cert->subject.name, response->this_update );
+ asn1_skip_any ( &cursor );
+
+ /* Parse nextUpdate, if present */
+ if ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) {
+ asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
+ if ( ( rc = asn1_generalized_time ( &cursor,
+ &response->next_update ) ) != 0 ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" could not parse "
+ "nextUpdate: %s\n", ocsp,
+ ocsp->cert->subject.name, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( ocsp, "OCSP %p \"%s\" next update is at time %lld\n",
+ ocsp, ocsp->cert->subject.name, response->next_update );
+ } else {
+ /* If no nextUpdate is present, this indicates that
+ * "newer revocation information is available all the
+ * time". Actually, this indicates that there is no
+ * point to performing the OCSP check, since an
+ * attacker could replay the response at any future
+ * time and it would still be valid.
+ */
+ DBGC ( ocsp, "OCSP %p \"%s\" responder is a moron\n",
+ ocsp, ocsp->cert->subject.name );
+ response->next_update = time ( NULL );
+ }
+
+ return 0;
+}
+
+/**
+ * Parse OCSP response data
+ *
+ * @v ocsp OCSP check
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int ocsp_parse_tbs_response_data ( struct ocsp_check *ocsp,
+ const struct asn1_cursor *raw ) {
+ struct ocsp_response *response = &ocsp->response;
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Record raw tbsResponseData */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_shrink_any ( &cursor );
+ memcpy ( &response->tbs, &cursor, sizeof ( response->tbs ) );
+
+ /* Enter tbsResponseData */
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Skip version, if present */
+ asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
+
+ /* Skip responderID */
+ asn1_skip_any ( &cursor );
+
+ /* Skip producedAt */
+ asn1_skip_any ( &cursor );
+
+ /* Parse responses */
+ if ( ( rc = ocsp_parse_responses ( ocsp, &cursor ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Parse OCSP certificates
+ *
+ * @v ocsp OCSP check
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int ocsp_parse_certs ( struct ocsp_check *ocsp,
+ const struct asn1_cursor *raw ) {
+ struct ocsp_response *response = &ocsp->response;
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter certs */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse certificate, if present. The data structure permits
+ * multiple certificates, but the protocol requires that the
+ * OCSP signing certificate must either be the issuer itself,
+ * or must be directly issued by the issuer (see RFC2560
+ * section 4.2.2.2 "Authorized Responders").
+ */
+ if ( ( cursor.len != 0 ) &&
+ ( ( rc = x509_certificate ( cursor.data, cursor.len,
+ &response->signer ) ) != 0 ) ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" could not parse certificate: "
+ "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc ));
+ DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
+ return rc;
+ }
+ DBGC2 ( ocsp, "OCSP %p \"%s\" response is signed by \"%s\"\n", ocsp,
+ ocsp->cert->subject.name, response->signer->subject.name );
+
+ return 0;
+}
+
+/**
+ * Parse OCSP basic response
+ *
+ * @v ocsp OCSP check
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int ocsp_parse_basic_response ( struct ocsp_check *ocsp,
+ const struct asn1_cursor *raw ) {
+ struct ocsp_response *response = &ocsp->response;
+ struct asn1_algorithm **algorithm = &response->algorithm;
+ struct asn1_bit_string *signature = &response->signature;
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter BasicOCSPResponse */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse tbsResponseData */
+ if ( ( rc = ocsp_parse_tbs_response_data ( ocsp, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Parse signatureAlgorithm */
+ if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature "
+ "algorithm: %s\n",
+ ocsp, ocsp->cert->subject.name, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( ocsp, "OCSP %p \"%s\" signature algorithm is %s\n",
+ ocsp, ocsp->cert->subject.name, (*algorithm)->name );
+ asn1_skip_any ( &cursor );
+
+ /* Parse signature */
+ if ( ( rc = asn1_integral_bit_string ( &cursor, signature ) ) != 0 ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature: %s\n",
+ ocsp, ocsp->cert->subject.name, strerror ( rc ) );
+ return rc;
+ }
+ asn1_skip_any ( &cursor );
+
+ /* Parse certs, if present */
+ if ( ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) &&
+ ( ( rc = ocsp_parse_certs ( ocsp, &cursor ) ) != 0 ) )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Parse OCSP response bytes
+ *
+ * @v ocsp OCSP check
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int ocsp_parse_response_bytes ( struct ocsp_check *ocsp,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter responseBytes */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse responseType */
+ if ( ( rc = ocsp_parse_response_type ( ocsp, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Enter response */
+ asn1_enter ( &cursor, ASN1_OCTET_STRING );
+
+ /* Parse response */
+ if ( ( rc = ocsp_parse_basic_response ( ocsp, &cursor ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Parse OCSP response
+ *
+ * @v ocsp OCSP check
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int ocsp_parse_response ( struct ocsp_check *ocsp,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter OCSPResponse */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse responseStatus */
+ if ( ( rc = ocsp_parse_response_status ( ocsp, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Parse responseBytes */
+ if ( ( rc = ocsp_parse_response_bytes ( ocsp, &cursor ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Receive OCSP response
+ *
+ * @v ocsp OCSP check
+ * @v data Response data
+ * @v len Length of response data
+ * @ret rc Return status code
+ */
+int ocsp_response ( struct ocsp_check *ocsp, const void *data, size_t len ) {
+ struct ocsp_response *response = &ocsp->response;
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Duplicate data */
+ x509_put ( response->signer );
+ response->signer = NULL;
+ free ( response->data );
+ response->data = malloc ( len );
+ if ( ! response->data )
+ return -ENOMEM;
+ memcpy ( response->data, data, len );
+ cursor.data = response->data;
+ cursor.len = len;
+
+ /* Parse response */
+ if ( ( rc = ocsp_parse_response ( ocsp, &cursor ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * OCSP dummy root certificate store
+ *
+ * OCSP validation uses no root certificates, since it takes place
+ * only when there already exists a validated issuer certificate.
+ */
+static struct x509_root ocsp_root = {
+ .digest = &ocsp_digest_algorithm,
+ .count = 0,
+ .fingerprints = NULL,
+};
+
+/**
+ * Check OCSP response signature
+ *
+ * @v ocsp OCSP check
+ * @v signer Signing certificate
+ * @ret rc Return status code
+ */
+static int ocsp_check_signature ( struct ocsp_check *ocsp,
+ struct x509_certificate *signer ) {
+ struct ocsp_response *response = &ocsp->response;
+ struct digest_algorithm *digest = response->algorithm->digest;
+ struct pubkey_algorithm *pubkey = response->algorithm->pubkey;
+ struct x509_public_key *public_key = &signer->subject.public_key;
+ uint8_t digest_ctx[ digest->ctxsize ];
+ uint8_t digest_out[ digest->digestsize ];
+ uint8_t pubkey_ctx[ pubkey->ctxsize ];
+ int rc;
+
+ /* Generate digest */
+ digest_init ( digest, digest_ctx );
+ digest_update ( digest, digest_ctx, response->tbs.data,
+ response->tbs.len );
+ digest_final ( digest, digest_ctx, digest_out );
+
+ /* Initialise public-key algorithm */
+ if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data,
+ public_key->raw.len ) ) != 0 ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" could not initialise public key: "
+ "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc ));
+ goto err_init;
+ }
+
+ /* Verify digest */
+ if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out,
+ response->signature.data,
+ response->signature.len ) ) != 0 ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" signature verification failed: "
+ "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc ));
+ goto err_verify;
+ }
+
+ DBGC2 ( ocsp, "OCSP %p \"%s\" signature is correct\n",
+ ocsp, ocsp->cert->subject.name );
+
+ err_verify:
+ pubkey_final ( pubkey, pubkey_ctx );
+ err_init:
+ return rc;
+}
+
+/**
+ * Validate OCSP response
+ *
+ * @v ocsp OCSP check
+ * @v time Time at which to validate response
+ * @ret rc Return status code
+ */
+int ocsp_validate ( struct ocsp_check *ocsp, time_t time ) {
+ struct ocsp_response *response = &ocsp->response;
+ struct x509_certificate *signer = response->signer;
+ int rc;
+
+ /* Sanity checks */
+ assert ( response->data != NULL );
+ assert ( signer != NULL );
+
+ /* Validate signer, if applicable. If the signer is not the
+ * issuer, then it must be signed directly by the issuer.
+ */
+ if ( signer != ocsp->issuer ) {
+ /* Forcibly invalidate the signer, since we need to
+ * ensure that it was signed by our issuer (and not
+ * some other issuer). This prevents a sub-CA's OCSP
+ * certificate from fraudulently signing OCSP
+ * responses from the parent CA.
+ */
+ x509_invalidate ( signer );
+ if ( ( rc = x509_validate ( signer, ocsp->issuer, time,
+ &ocsp_root ) ) != 0 ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" could not validate "
+ "signer \"%s\": %s\n", ocsp,
+ ocsp->cert->subject.name, signer->subject.name,
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* If signer is not the issuer, then it must have the
+ * extendedKeyUsage id-kp-OCSPSigning.
+ */
+ if ( ! ( signer->extensions.ext_usage.bits &
+ X509_OCSP_SIGNING ) ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" signer \"%s\" is "
+ "not an OCSP-signing certificate\n", ocsp,
+ ocsp->cert->subject.name, signer->subject.name );
+ return -EACCES_NON_OCSP_SIGNING;
+ }
+ }
+
+ /* Check OCSP response signature */
+ if ( ( rc = ocsp_check_signature ( ocsp, signer ) ) != 0 )
+ return rc;
+
+ /* Check OCSP response is valid at the specified time
+ * (allowing for some margin of error).
+ */
+ if ( response->this_update > ( time - OCSP_ERROR_MARGIN_TIME ) ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" response is not yet valid (at "
+ "time %lld)\n", ocsp, ocsp->cert->subject.name, time );
+ return -EACCES_STALE;
+ }
+ if ( response->next_update < ( time + OCSP_ERROR_MARGIN_TIME ) ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" response is stale (at time "
+ "%lld)\n", ocsp, ocsp->cert->subject.name, time );
+ return -EACCES_STALE;
+ }
+ DBGC2 ( ocsp, "OCSP %p \"%s\" response is valid (at time %lld)\n",
+ ocsp, ocsp->cert->subject.name, time );
+
+ /* Mark certificate as passing OCSP verification */
+ ocsp->cert->extensions.auth_info.ocsp.good = 1;
+
+ /* Validate certificate against issuer */
+ if ( ( rc = x509_validate ( ocsp->cert, ocsp->issuer, time,
+ &ocsp_root ) ) != 0 ) {
+ DBGC ( ocsp, "OCSP %p \"%s\" could not validate certificate: "
+ "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc ));
+ return rc;
+ }
+ DBGC ( ocsp, "OCSP %p \"%s\" successfully validated using \"%s\"\n",
+ ocsp, ocsp->cert->subject.name, signer->subject.name );
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/random_nz.c b/src/VBox/Devices/PC/ipxe/src/crypto/random_nz.c
new file mode 100644
index 00000000..7b54aad7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/random_nz.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Random non-zero bytes
+ *
+ * The RSA algorithm requires the generation of random non-zero bytes,
+ * i.e. bytes in the range [0x01,0xff].
+ *
+ * This algorithm is designed to comply with ANS X9.82 Part 1-2006
+ * Section 9.2.1. This standard is not freely available, but most of
+ * the text appears to be shared with NIST SP 800-90, which can be
+ * downloaded from
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
+ *
+ * Where possible, references are given to both documents. In the
+ * case of any disagreement, ANS X9.82 takes priority over NIST SP
+ * 800-90. (In particular, note that some algorithms that are
+ * Approved by NIST SP 800-90 are not Approved by ANS X9.82.)
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <ipxe/rbg.h>
+#include <ipxe/random_nz.h>
+
+/**
+ * Get random non-zero bytes
+ *
+ * @v data Output buffer
+ * @v len Length of output buffer
+ * @ret rc Return status code
+ *
+ * This algorithm is designed to be isomorphic to the Simple Discard
+ * Method described in ANS X9.82 Part 1-2006 Section 9.2.1 (NIST SP
+ * 800-90 Section B.5.1.1).
+ */
+int get_random_nz ( void *data, size_t len ) {
+ uint8_t *bytes = data;
+ int rc;
+
+ while ( len ) {
+
+ /* Generate random byte */
+ if ( ( rc = rbg_generate ( NULL, 0, 0, bytes, 1 ) ) != 0 )
+ return rc;
+
+ /* Move to next byte if this byte is acceptable */
+ if ( *bytes != 0 ) {
+ bytes++;
+ len--;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/rbg.c b/src/VBox/Devices/PC/ipxe/src/crypto/rbg.c
new file mode 100644
index 00000000..da0ad5df
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/rbg.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * RBG mechanism
+ *
+ * This mechanism is designed to comply with ANS X9.82 Part 4 (April
+ * 2011 Draft) Section 10. This standard is unfortunately not freely
+ * available.
+ *
+ * The chosen RBG design is that of a DRBG with a live entropy source
+ * with no conditioning function. Only a single security strength is
+ * supported. No seedfile is used since there may be no non-volatile
+ * storage available. The system UUID is used as the personalisation
+ * string.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <ipxe/init.h>
+#include <ipxe/settings.h>
+#include <ipxe/uuid.h>
+#include <ipxe/crypto.h>
+#include <ipxe/drbg.h>
+#include <ipxe/rbg.h>
+
+/** The RBG */
+struct random_bit_generator rbg;
+
+/**
+ * Start up RBG
+ *
+ * @ret rc Return status code
+ *
+ * This is the RBG_Startup function defined in ANS X9.82 Part 4 (April
+ * 2011 Draft) Section 9.1.2.2.
+ */
+static int rbg_startup ( void ) {
+ union uuid uuid;
+ int len;
+ int rc;
+
+ /* Try to obtain system UUID for use as personalisation
+ * string, in accordance with ANS X9.82 Part 3-2007 Section
+ * 8.5.2. If no UUID is available, proceed without a
+ * personalisation string.
+ */
+ if ( ( len = fetch_uuid_setting ( NULL, &uuid_setting, &uuid ) ) < 0 ) {
+ rc = len;
+ DBGC ( &rbg, "RBG could not fetch personalisation string: "
+ "%s\n", strerror ( rc ) );
+ len = 0;
+ }
+
+ /* Instantiate DRBG */
+ if ( ( rc = drbg_instantiate ( &rbg.state, &uuid, len ) ) != 0 ) {
+ DBGC ( &rbg, "RBG could not instantiate DRBG: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Shut down RBG
+ *
+ */
+static void rbg_shutdown ( void ) {
+
+ /* Uninstantiate DRBG */
+ drbg_uninstantiate ( &rbg.state );
+}
+
+/** RBG startup function */
+static void rbg_startup_fn ( void ) {
+
+ /* Start up RBG. There is no way to report an error at this
+ * stage, but a failed startup will result in an invalid DRBG
+ * that refuses to generate bits.
+ */
+ rbg_startup();
+}
+
+/** RBG shutdown function */
+static void rbg_shutdown_fn ( int booting __unused ) {
+
+ /* Shut down RBG */
+ rbg_shutdown();
+}
+
+/** RBG startup table entry */
+struct startup_fn startup_rbg __startup_fn ( STARTUP_NORMAL ) = {
+ .startup = rbg_startup_fn,
+ .shutdown = rbg_shutdown_fn,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/rootcert.c b/src/VBox/Devices/PC/ipxe/src/crypto/rootcert.c
new file mode 100644
index 00000000..ee2a3454
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/rootcert.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <ipxe/crypto.h>
+#include <ipxe/sha256.h>
+#include <ipxe/x509.h>
+#include <ipxe/settings.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/init.h>
+#include <ipxe/rootcert.h>
+
+/** @file
+ *
+ * Root certificate store
+ *
+ */
+
+/** Length of a root certificate fingerprint */
+#define FINGERPRINT_LEN SHA256_DIGEST_SIZE
+
+/* Allow trusted certificates to be overridden if not explicitly specified */
+#ifdef TRUSTED
+#define ALLOW_TRUST_OVERRIDE 0
+#else
+#define ALLOW_TRUST_OVERRIDE 1
+#endif
+
+/* Use iPXE root CA if no trusted certificates are explicitly specified */
+#ifndef TRUSTED
+#define TRUSTED \
+ /* iPXE root CA */ \
+ 0x9f, 0xaf, 0x71, 0x7b, 0x7f, 0x8c, 0xa2, 0xf9, 0x3c, 0x25, \
+ 0x6c, 0x79, 0xf8, 0xac, 0x55, 0x91, 0x89, 0x5d, 0x66, 0xd1, \
+ 0xff, 0x3b, 0xee, 0x63, 0x97, 0xa7, 0x0d, 0x29, 0xc6, 0x5e, \
+ 0xed, 0x1a,
+#endif
+
+/** Root certificate fingerprints */
+static const uint8_t fingerprints[] = { TRUSTED };
+
+/** Root certificate fingerprint setting */
+static struct setting trust_setting __setting ( SETTING_CRYPTO ) = {
+ .name = "trust",
+ .description = "Trusted root certificate fingerprints",
+ .tag = DHCP_EB_TRUST,
+ .type = &setting_type_hex,
+};
+
+/** Root certificates */
+struct x509_root root_certificates = {
+ .digest = &sha256_algorithm,
+ .count = ( sizeof ( fingerprints ) / FINGERPRINT_LEN ),
+ .fingerprints = fingerprints,
+};
+
+/**
+ * Initialise root certificate
+ *
+ * The list of trusted root certificates can be specified at build
+ * time using the TRUST= build parameter. If no certificates are
+ * specified, then the default iPXE root CA certificate is trusted.
+ *
+ * If no certificates were explicitly specified, then we allow the
+ * list of trusted root certificate fingerprints to be overridden
+ * using the "trust" setting, but only at the point of iPXE
+ * initialisation. This prevents untrusted sources of settings
+ * (e.g. DHCP) from subverting the chain of trust, while allowing
+ * trustworthy sources (e.g. VMware GuestInfo or non-volatile stored
+ * options) to specify the trusted root certificate without requiring
+ * a rebuild.
+ */
+static void rootcert_init ( void ) {
+ void *external = NULL;
+ int len;
+ int rc;
+
+ /* Allow trusted root certificates to be overridden only if
+ * not explicitly specified at build time.
+ */
+ if ( ALLOW_TRUST_OVERRIDE ) {
+
+ /* Fetch copy of "trust" setting, if it exists. This
+ * memory will never be freed.
+ */
+ len = fetch_setting_copy ( NULL, &trust_setting, &external );
+ if ( len < 0 ) {
+ rc = len;
+ DBGC ( &root_certificates, "ROOTCERT cannot fetch "
+ "trusted root certificate fingerprints: %s\n",
+ strerror ( rc ) );
+ /* No way to prevent startup; fail safe by
+ * trusting no certificates.
+ */
+ root_certificates.count = 0;
+ return;
+ }
+
+ /* Use certificates from "trust" setting, if present */
+ if ( external ) {
+ root_certificates.fingerprints = external;
+ root_certificates.count = ( len / FINGERPRINT_LEN );
+ }
+ }
+
+ DBGC ( &root_certificates, "ROOTCERT using %d %s certificate(s):\n",
+ root_certificates.count, ( external ? "external" : "built-in" ));
+ DBGC_HDA ( &root_certificates, 0, root_certificates.fingerprints,
+ ( root_certificates.count * FINGERPRINT_LEN ) );
+}
+
+/** Root certificate initialiser */
+struct init_fn rootcert_init_fn __init_fn ( INIT_LATE ) = {
+ .initialise = rootcert_init,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/rsa.c b/src/VBox/Devices/PC/ipxe/src/crypto/rsa.c
new file mode 100644
index 00000000..563d6b9b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/rsa.c
@@ -0,0 +1,641 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/asn1.h>
+#include <ipxe/crypto.h>
+#include <ipxe/bigint.h>
+#include <ipxe/random_nz.h>
+#include <ipxe/md5.h>
+#include <ipxe/sha1.h>
+#include <ipxe/sha256.h>
+#include <ipxe/rsa.h>
+
+/** @file
+ *
+ * RSA public-key cryptography
+ *
+ * RSA is documented in RFC 3447.
+ */
+
+/* Disambiguate the various error causes */
+#define EACCES_VERIFY \
+ __einfo_error ( EINFO_EACCES_VERIFY )
+#define EINFO_EACCES_VERIFY \
+ __einfo_uniqify ( EINFO_EACCES, 0x01, "RSA signature incorrect" )
+
+/** "rsaEncryption" object identifier */
+static uint8_t oid_rsa_encryption[] = { ASN1_OID_RSAENCRYPTION };
+
+/** "md5WithRSAEncryption" object identifier */
+static uint8_t oid_md5_with_rsa_encryption[] =
+ { ASN1_OID_MD5WITHRSAENCRYPTION };
+
+/** "sha1WithRSAEncryption" object identifier */
+static uint8_t oid_sha1_with_rsa_encryption[] =
+ { ASN1_OID_SHA1WITHRSAENCRYPTION };
+
+/** "sha256WithRSAEncryption" object identifier */
+static uint8_t oid_sha256_with_rsa_encryption[] =
+ { ASN1_OID_SHA256WITHRSAENCRYPTION };
+
+/** "rsaEncryption" OID-identified algorithm */
+struct asn1_algorithm rsa_encryption_algorithm __asn1_algorithm = {
+ .name = "rsaEncryption",
+ .pubkey = &rsa_algorithm,
+ .digest = NULL,
+ .oid = ASN1_OID_CURSOR ( oid_rsa_encryption ),
+};
+
+/** "md5WithRSAEncryption" OID-identified algorithm */
+struct asn1_algorithm md5_with_rsa_encryption_algorithm __asn1_algorithm = {
+ .name = "md5WithRSAEncryption",
+ .pubkey = &rsa_algorithm,
+ .digest = &md5_algorithm,
+ .oid = ASN1_OID_CURSOR ( oid_md5_with_rsa_encryption ),
+};
+
+/** "sha1WithRSAEncryption" OID-identified algorithm */
+struct asn1_algorithm sha1_with_rsa_encryption_algorithm __asn1_algorithm = {
+ .name = "sha1WithRSAEncryption",
+ .pubkey = &rsa_algorithm,
+ .digest = &sha1_algorithm,
+ .oid = ASN1_OID_CURSOR ( oid_sha1_with_rsa_encryption ),
+};
+
+/** "sha256WithRSAEncryption" OID-identified algorithm */
+struct asn1_algorithm sha256_with_rsa_encryption_algorithm __asn1_algorithm = {
+ .name = "sha256WithRSAEncryption",
+ .pubkey = &rsa_algorithm,
+ .digest = &sha256_algorithm,
+ .oid = ASN1_OID_CURSOR ( oid_sha256_with_rsa_encryption ),
+};
+
+/** MD5 digestInfo prefix */
+static const uint8_t rsa_md5_prefix_data[] =
+ { RSA_DIGESTINFO_PREFIX ( MD5_DIGEST_SIZE, ASN1_OID_MD5 ) };
+
+/** SHA-1 digestInfo prefix */
+static const uint8_t rsa_sha1_prefix_data[] =
+ { RSA_DIGESTINFO_PREFIX ( SHA1_DIGEST_SIZE, ASN1_OID_SHA1 ) };
+
+/** SHA-256 digestInfo prefix */
+static const uint8_t rsa_sha256_prefix_data[] =
+ { RSA_DIGESTINFO_PREFIX ( SHA256_DIGEST_SIZE, ASN1_OID_SHA256 ) };
+
+/** MD5 digestInfo prefix */
+struct rsa_digestinfo_prefix rsa_md5_prefix __rsa_digestinfo_prefix = {
+ .digest = &md5_algorithm,
+ .data = rsa_md5_prefix_data,
+ .len = sizeof ( rsa_md5_prefix_data ),
+};
+
+/** SHA-1 digestInfo prefix */
+struct rsa_digestinfo_prefix rsa_sha1_prefix __rsa_digestinfo_prefix = {
+ .digest = &sha1_algorithm,
+ .data = rsa_sha1_prefix_data,
+ .len = sizeof ( rsa_sha1_prefix_data ),
+};
+
+/** SHA-256 digestInfo prefix */
+struct rsa_digestinfo_prefix rsa_sha256_prefix __rsa_digestinfo_prefix = {
+ .digest = &sha256_algorithm,
+ .data = rsa_sha256_prefix_data,
+ .len = sizeof ( rsa_sha256_prefix_data ),
+};
+
+/**
+ * Identify RSA prefix
+ *
+ * @v digest Digest algorithm
+ * @ret prefix RSA prefix, or NULL
+ */
+static struct rsa_digestinfo_prefix *
+rsa_find_prefix ( struct digest_algorithm *digest ) {
+ struct rsa_digestinfo_prefix *prefix;
+
+ for_each_table_entry ( prefix, RSA_DIGESTINFO_PREFIXES ) {
+ if ( prefix->digest == digest )
+ return prefix;
+ }
+ return NULL;
+}
+
+/**
+ * Free RSA dynamic storage
+ *
+ * @v context RSA context
+ */
+static void rsa_free ( struct rsa_context *context ) {
+
+ free ( context->dynamic );
+ context->dynamic = NULL;
+}
+
+/**
+ * Allocate RSA dynamic storage
+ *
+ * @v context RSA context
+ * @v modulus_len Modulus length
+ * @v exponent_len Exponent length
+ * @ret rc Return status code
+ */
+static int rsa_alloc ( struct rsa_context *context, size_t modulus_len,
+ size_t exponent_len ) {
+ unsigned int size = bigint_required_size ( modulus_len );
+ unsigned int exponent_size = bigint_required_size ( exponent_len );
+ bigint_t ( size ) *modulus;
+ bigint_t ( exponent_size ) *exponent;
+ size_t tmp_len = bigint_mod_exp_tmp_len ( modulus, exponent );
+ struct {
+ bigint_t ( size ) modulus;
+ bigint_t ( exponent_size ) exponent;
+ bigint_t ( size ) input;
+ bigint_t ( size ) output;
+ uint8_t tmp[tmp_len];
+ } __attribute__ (( packed )) *dynamic;
+
+ /* Free any existing dynamic storage */
+ rsa_free ( context );
+
+ /* Allocate dynamic storage */
+ dynamic = malloc ( sizeof ( *dynamic ) );
+ if ( ! dynamic )
+ return -ENOMEM;
+
+ /* Assign dynamic storage */
+ context->dynamic = dynamic;
+ context->modulus0 = &dynamic->modulus.element[0];
+ context->size = size;
+ context->max_len = modulus_len;
+ context->exponent0 = &dynamic->exponent.element[0];
+ context->exponent_size = exponent_size;
+ context->input0 = &dynamic->input.element[0];
+ context->output0 = &dynamic->output.element[0];
+ context->tmp = &dynamic->tmp;
+
+ return 0;
+}
+
+/**
+ * Parse RSA integer
+ *
+ * @v context RSA context
+ * @v integer Integer to fill in
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int rsa_parse_integer ( struct rsa_context *context,
+ struct asn1_cursor *integer,
+ const struct asn1_cursor *raw ) {
+
+ /* Enter integer */
+ memcpy ( integer, raw, sizeof ( *integer ) );
+ asn1_enter ( integer, ASN1_INTEGER );
+
+ /* Skip initial sign byte if applicable */
+ if ( ( integer->len > 1 ) &&
+ ( *( ( uint8_t * ) integer->data ) == 0x00 ) ) {
+ integer->data++;
+ integer->len--;
+ }
+
+ /* Fail if cursor or integer are invalid */
+ if ( ! integer->len ) {
+ DBGC ( context, "RSA %p invalid integer:\n", context );
+ DBGC_HDA ( context, 0, raw->data, raw->len );
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * Initialise RSA cipher
+ *
+ * @v ctx RSA context
+ * @v key Key
+ * @v key_len Length of key
+ * @ret rc Return status code
+ */
+static int rsa_init ( void *ctx, const void *key, size_t key_len ) {
+ struct rsa_context *context = ctx;
+ struct asn1_bit_string bits;
+ struct asn1_cursor modulus;
+ struct asn1_cursor exponent;
+ struct asn1_cursor cursor;
+ int is_private;
+ int rc;
+
+ /* Initialise context */
+ memset ( context, 0, sizeof ( *context ) );
+
+ /* Initialise cursor */
+ cursor.data = key;
+ cursor.len = key_len;
+
+ /* Enter subjectPublicKeyInfo/RSAPrivateKey */
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Determine key format */
+ if ( asn1_type ( &cursor ) == ASN1_INTEGER ) {
+ /* Private key */
+ is_private = 1;
+
+ /* Skip version */
+ asn1_skip_any ( &cursor );
+
+ } else {
+ /* Public key */
+ is_private = 0;
+
+ /* Skip algorithm */
+ asn1_skip ( &cursor, ASN1_SEQUENCE );
+
+ /* Enter subjectPublicKey */
+ if ( ( rc = asn1_integral_bit_string ( &cursor, &bits ) ) != 0 )
+ goto err_parse;
+ cursor.data = bits.data;
+ cursor.len = bits.len;
+
+ /* Enter RSAPublicKey */
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+ }
+
+ /* Extract modulus */
+ if ( ( rc = rsa_parse_integer ( context, &modulus, &cursor ) ) != 0 )
+ goto err_parse;
+ asn1_skip_any ( &cursor );
+
+ /* Skip public exponent, if applicable */
+ if ( is_private )
+ asn1_skip ( &cursor, ASN1_INTEGER );
+
+ /* Extract publicExponent/privateExponent */
+ if ( ( rc = rsa_parse_integer ( context, &exponent, &cursor ) ) != 0 )
+ goto err_parse;
+
+ DBGC ( context, "RSA %p modulus:\n", context );
+ DBGC_HDA ( context, 0, modulus.data, modulus.len );
+ DBGC ( context, "RSA %p exponent:\n", context );
+ DBGC_HDA ( context, 0, exponent.data, exponent.len );
+
+ /* Allocate dynamic storage */
+ if ( ( rc = rsa_alloc ( context, modulus.len, exponent.len ) ) != 0 )
+ goto err_alloc;
+
+ /* Construct big integers */
+ bigint_init ( ( ( bigint_t ( context->size ) * ) context->modulus0 ),
+ modulus.data, modulus.len );
+ bigint_init ( ( ( bigint_t ( context->exponent_size ) * )
+ context->exponent0 ), exponent.data, exponent.len );
+
+ return 0;
+
+ rsa_free ( context );
+ err_alloc:
+ err_parse:
+ return rc;
+}
+
+/**
+ * Calculate RSA maximum output length
+ *
+ * @v ctx RSA context
+ * @ret max_len Maximum output length
+ */
+static size_t rsa_max_len ( void *ctx ) {
+ struct rsa_context *context = ctx;
+
+ return context->max_len;
+}
+
+/**
+ * Perform RSA cipher operation
+ *
+ * @v context RSA context
+ * @v in Input buffer
+ * @v out Output buffer
+ */
+static void rsa_cipher ( struct rsa_context *context,
+ const void *in, void *out ) {
+ bigint_t ( context->size ) *input = ( ( void * ) context->input0 );
+ bigint_t ( context->size ) *output = ( ( void * ) context->output0 );
+ bigint_t ( context->size ) *modulus = ( ( void * ) context->modulus0 );
+ bigint_t ( context->exponent_size ) *exponent =
+ ( ( void * ) context->exponent0 );
+
+ /* Initialise big integer */
+ bigint_init ( input, in, context->max_len );
+
+ /* Perform modular exponentiation */
+ bigint_mod_exp ( input, modulus, exponent, output, context->tmp );
+
+ /* Copy out result */
+ bigint_done ( output, out, context->max_len );
+}
+
+/**
+ * Encrypt using RSA
+ *
+ * @v ctx RSA context
+ * @v plaintext Plaintext
+ * @v plaintext_len Length of plaintext
+ * @v ciphertext Ciphertext
+ * @ret ciphertext_len Length of ciphertext, or negative error
+ */
+static int rsa_encrypt ( void *ctx, const void *plaintext,
+ size_t plaintext_len, void *ciphertext ) {
+ struct rsa_context *context = ctx;
+ void *temp;
+ uint8_t *encoded;
+ size_t max_len = ( context->max_len - 11 );
+ size_t random_nz_len = ( max_len - plaintext_len + 8 );
+ int rc;
+
+ /* Sanity check */
+ if ( plaintext_len > max_len ) {
+ DBGC ( context, "RSA %p plaintext too long (%zd bytes, max "
+ "%zd)\n", context, plaintext_len, max_len );
+ return -ERANGE;
+ }
+ DBGC ( context, "RSA %p encrypting:\n", context );
+ DBGC_HDA ( context, 0, plaintext, plaintext_len );
+
+ /* Construct encoded message (using the big integer output
+ * buffer as temporary storage)
+ */
+ temp = context->output0;
+ encoded = temp;
+ encoded[0] = 0x00;
+ encoded[1] = 0x02;
+ if ( ( rc = get_random_nz ( &encoded[2], random_nz_len ) ) != 0 ) {
+ DBGC ( context, "RSA %p could not generate random data: %s\n",
+ context, strerror ( rc ) );
+ return rc;
+ }
+ encoded[ 2 + random_nz_len ] = 0x00;
+ memcpy ( &encoded[ context->max_len - plaintext_len ],
+ plaintext, plaintext_len );
+
+ /* Encipher the encoded message */
+ rsa_cipher ( context, encoded, ciphertext );
+ DBGC ( context, "RSA %p encrypted:\n", context );
+ DBGC_HDA ( context, 0, ciphertext, context->max_len );
+
+ return context->max_len;
+}
+
+/**
+ * Decrypt using RSA
+ *
+ * @v ctx RSA context
+ * @v ciphertext Ciphertext
+ * @v ciphertext_len Ciphertext length
+ * @v plaintext Plaintext
+ * @ret plaintext_len Plaintext length, or negative error
+ */
+static int rsa_decrypt ( void *ctx, const void *ciphertext,
+ size_t ciphertext_len, void *plaintext ) {
+ struct rsa_context *context = ctx;
+ void *temp;
+ uint8_t *encoded;
+ uint8_t *end;
+ uint8_t *zero;
+ uint8_t *start;
+ size_t plaintext_len;
+
+ /* Sanity check */
+ if ( ciphertext_len != context->max_len ) {
+ DBGC ( context, "RSA %p ciphertext incorrect length (%zd "
+ "bytes, should be %zd)\n",
+ context, ciphertext_len, context->max_len );
+ return -ERANGE;
+ }
+ DBGC ( context, "RSA %p decrypting:\n", context );
+ DBGC_HDA ( context, 0, ciphertext, ciphertext_len );
+
+ /* Decipher the message (using the big integer input buffer as
+ * temporary storage)
+ */
+ temp = context->input0;
+ encoded = temp;
+ rsa_cipher ( context, ciphertext, encoded );
+
+ /* Parse the message */
+ end = ( encoded + context->max_len );
+ if ( ( encoded[0] != 0x00 ) || ( encoded[1] != 0x02 ) )
+ goto invalid;
+ zero = memchr ( &encoded[2], 0, ( end - &encoded[2] ) );
+ if ( ! zero )
+ goto invalid;
+ start = ( zero + 1 );
+ plaintext_len = ( end - start );
+
+ /* Copy out message */
+ memcpy ( plaintext, start, plaintext_len );
+ DBGC ( context, "RSA %p decrypted:\n", context );
+ DBGC_HDA ( context, 0, plaintext, plaintext_len );
+
+ return plaintext_len;
+
+ invalid:
+ DBGC ( context, "RSA %p invalid decrypted message:\n", context );
+ DBGC_HDA ( context, 0, encoded, context->max_len );
+ return -EINVAL;
+}
+
+/**
+ * Encode RSA digest
+ *
+ * @v context RSA context
+ * @v digest Digest algorithm
+ * @v value Digest value
+ * @v encoded Encoded digest
+ * @ret rc Return status code
+ */
+static int rsa_encode_digest ( struct rsa_context *context,
+ struct digest_algorithm *digest,
+ const void *value, void *encoded ) {
+ struct rsa_digestinfo_prefix *prefix;
+ size_t digest_len = digest->digestsize;
+ uint8_t *temp = encoded;
+ size_t digestinfo_len;
+ size_t max_len;
+ size_t pad_len;
+
+ /* Identify prefix */
+ prefix = rsa_find_prefix ( digest );
+ if ( ! prefix ) {
+ DBGC ( context, "RSA %p has no prefix for %s\n",
+ context, digest->name );
+ return -ENOTSUP;
+ }
+ digestinfo_len = ( prefix->len + digest_len );
+
+ /* Sanity check */
+ max_len = ( context->max_len - 11 );
+ if ( digestinfo_len > max_len ) {
+ DBGC ( context, "RSA %p %s digestInfo too long (%zd bytes, max"
+ "%zd)\n",
+ context, digest->name, digestinfo_len, max_len );
+ return -ERANGE;
+ }
+ DBGC ( context, "RSA %p encoding %s digest:\n",
+ context, digest->name );
+ DBGC_HDA ( context, 0, value, digest_len );
+
+ /* Construct encoded message */
+ *(temp++) = 0x00;
+ *(temp++) = 0x01;
+ pad_len = ( max_len - digestinfo_len + 8 );
+ memset ( temp, 0xff, pad_len );
+ temp += pad_len;
+ *(temp++) = 0x00;
+ memcpy ( temp, prefix->data, prefix->len );
+ temp += prefix->len;
+ memcpy ( temp, value, digest_len );
+ temp += digest_len;
+ assert ( temp == ( encoded + context->max_len ) );
+ DBGC ( context, "RSA %p encoded %s digest:\n", context, digest->name );
+ DBGC_HDA ( context, 0, encoded, context->max_len );
+
+ return 0;
+}
+
+/**
+ * Sign digest value using RSA
+ *
+ * @v ctx RSA context
+ * @v digest Digest algorithm
+ * @v value Digest value
+ * @v signature Signature
+ * @ret signature_len Signature length, or negative error
+ */
+static int rsa_sign ( void *ctx, struct digest_algorithm *digest,
+ const void *value, void *signature ) {
+ struct rsa_context *context = ctx;
+ void *temp;
+ int rc;
+
+ DBGC ( context, "RSA %p signing %s digest:\n", context, digest->name );
+ DBGC_HDA ( context, 0, value, digest->digestsize );
+
+ /* Encode digest (using the big integer output buffer as
+ * temporary storage)
+ */
+ temp = context->output0;
+ if ( ( rc = rsa_encode_digest ( context, digest, value, temp ) ) != 0 )
+ return rc;
+
+ /* Encipher the encoded digest */
+ rsa_cipher ( context, temp, signature );
+ DBGC ( context, "RSA %p signed %s digest:\n", context, digest->name );
+ DBGC_HDA ( context, 0, signature, context->max_len );
+
+ return context->max_len;
+}
+
+/**
+ * Verify signed digest value using RSA
+ *
+ * @v ctx RSA context
+ * @v digest Digest algorithm
+ * @v value Digest value
+ * @v signature Signature
+ * @v signature_len Signature length
+ * @ret rc Return status code
+ */
+static int rsa_verify ( void *ctx, struct digest_algorithm *digest,
+ const void *value, const void *signature,
+ size_t signature_len ) {
+ struct rsa_context *context = ctx;
+ void *temp;
+ void *expected;
+ void *actual;
+ int rc;
+
+ /* Sanity check */
+ if ( signature_len != context->max_len ) {
+ DBGC ( context, "RSA %p signature incorrect length (%zd "
+ "bytes, should be %zd)\n",
+ context, signature_len, context->max_len );
+ return -ERANGE;
+ }
+ DBGC ( context, "RSA %p verifying %s digest:\n",
+ context, digest->name );
+ DBGC_HDA ( context, 0, value, digest->digestsize );
+ DBGC_HDA ( context, 0, signature, signature_len );
+
+ /* Decipher the signature (using the big integer input buffer
+ * as temporary storage)
+ */
+ temp = context->input0;
+ expected = temp;
+ rsa_cipher ( context, signature, expected );
+ DBGC ( context, "RSA %p deciphered signature:\n", context );
+ DBGC_HDA ( context, 0, expected, context->max_len );
+
+ /* Encode digest (using the big integer output buffer as
+ * temporary storage)
+ */
+ temp = context->output0;
+ actual = temp;
+ if ( ( rc = rsa_encode_digest ( context, digest, value, actual ) ) !=0 )
+ return rc;
+
+ /* Verify the signature */
+ if ( memcmp ( actual, expected, context->max_len ) != 0 ) {
+ DBGC ( context, "RSA %p signature verification failed\n",
+ context );
+ return -EACCES_VERIFY;
+ }
+
+ DBGC ( context, "RSA %p signature verified successfully\n", context );
+ return 0;
+}
+
+/**
+ * Finalise RSA cipher
+ *
+ * @v ctx RSA context
+ */
+static void rsa_final ( void *ctx ) {
+ struct rsa_context *context = ctx;
+
+ rsa_free ( context );
+}
+
+/** RSA public-key algorithm */
+struct pubkey_algorithm rsa_algorithm = {
+ .name = "rsa",
+ .ctxsize = sizeof ( struct rsa_context ),
+ .init = rsa_init,
+ .max_len = rsa_max_len,
+ .encrypt = rsa_encrypt,
+ .decrypt = rsa_decrypt,
+ .sign = rsa_sign,
+ .verify = rsa_verify,
+ .final = rsa_final,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/sha1.c b/src/VBox/Devices/PC/ipxe/src/crypto/sha1.c
new file mode 100644
index 00000000..7f287d3c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/sha1.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * SHA-1 algorithm
+ *
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <byteswap.h>
+#include <assert.h>
+#include <ipxe/rotate.h>
+#include <ipxe/crypto.h>
+#include <ipxe/asn1.h>
+#include <ipxe/sha1.h>
+
+/** SHA-1 variables */
+struct sha1_variables {
+ /* This layout matches that of struct sha1_digest_data,
+ * allowing for efficient endianness-conversion,
+ */
+ uint32_t a;
+ uint32_t b;
+ uint32_t c;
+ uint32_t d;
+ uint32_t e;
+ uint32_t w[80];
+} __attribute__ (( packed ));
+
+/**
+ * f(a,b,c,d) for steps 0 to 19
+ *
+ * @v v SHA-1 variables
+ * @ret f f(a,b,c,d)
+ */
+static uint32_t sha1_f_0_19 ( struct sha1_variables *v ) {
+ return ( ( v->b & v->c ) | ( (~v->b) & v->d ) );
+}
+
+/**
+ * f(a,b,c,d) for steps 20 to 39 and 60 to 79
+ *
+ * @v v SHA-1 variables
+ * @ret f f(a,b,c,d)
+ */
+static uint32_t sha1_f_20_39_60_79 ( struct sha1_variables *v ) {
+ return ( v->b ^ v->c ^ v->d );
+}
+
+/**
+ * f(a,b,c,d) for steps 40 to 59
+ *
+ * @v v SHA-1 variables
+ * @ret f f(a,b,c,d)
+ */
+static uint32_t sha1_f_40_59 ( struct sha1_variables *v ) {
+ return ( ( v->b & v->c ) | ( v->b & v->d ) | ( v->c & v->d ) );
+}
+
+/** An SHA-1 step function */
+struct sha1_step {
+ /**
+ * Calculate f(a,b,c,d)
+ *
+ * @v v SHA-1 variables
+ * @ret f f(a,b,c,d)
+ */
+ uint32_t ( * f ) ( struct sha1_variables *v );
+ /** Constant k */
+ uint32_t k;
+};
+
+/** SHA-1 steps */
+static struct sha1_step sha1_steps[4] = {
+ /** 0 to 19 */
+ { .f = sha1_f_0_19, .k = 0x5a827999 },
+ /** 20 to 39 */
+ { .f = sha1_f_20_39_60_79, .k = 0x6ed9eba1 },
+ /** 40 to 59 */
+ { .f = sha1_f_40_59, .k = 0x8f1bbcdc },
+ /** 60 to 79 */
+ { .f = sha1_f_20_39_60_79, .k = 0xca62c1d6 },
+};
+
+/**
+ * Initialise SHA-1 algorithm
+ *
+ * @v ctx SHA-1 context
+ */
+static void sha1_init ( void *ctx ) {
+ struct sha1_context *context = ctx;
+
+ context->ddd.dd.digest.h[0] = cpu_to_be32 ( 0x67452301 );
+ context->ddd.dd.digest.h[1] = cpu_to_be32 ( 0xefcdab89 );
+ context->ddd.dd.digest.h[2] = cpu_to_be32 ( 0x98badcfe );
+ context->ddd.dd.digest.h[3] = cpu_to_be32 ( 0x10325476 );
+ context->ddd.dd.digest.h[4] = cpu_to_be32 ( 0xc3d2e1f0 );
+ context->len = 0;
+}
+
+/**
+ * Calculate SHA-1 digest of accumulated data
+ *
+ * @v context SHA-1 context
+ */
+static void sha1_digest ( struct sha1_context *context ) {
+ union {
+ union sha1_digest_data_dwords ddd;
+ struct sha1_variables v;
+ } u;
+ uint32_t *a = &u.v.a;
+ uint32_t *b = &u.v.b;
+ uint32_t *c = &u.v.c;
+ uint32_t *d = &u.v.d;
+ uint32_t *e = &u.v.e;
+ uint32_t *w = u.v.w;
+ uint32_t f;
+ uint32_t k;
+ uint32_t temp;
+ struct sha1_step *step;
+ unsigned int i;
+
+ /* Sanity checks */
+ assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 );
+ linker_assert ( &u.ddd.dd.digest.h[0] == a, sha1_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[1] == b, sha1_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[2] == c, sha1_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[3] == d, sha1_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[4] == e, sha1_bad_layout );
+ linker_assert ( &u.ddd.dd.data.dword[0] == w, sha1_bad_layout );
+
+ DBGC ( context, "SHA1 digesting:\n" );
+ DBGC_HDA ( context, 0, &context->ddd.dd.digest,
+ sizeof ( context->ddd.dd.digest ) );
+ DBGC_HDA ( context, context->len, &context->ddd.dd.data,
+ sizeof ( context->ddd.dd.data ) );
+
+ /* Convert h[0..4] to host-endian, and initialise a, b, c, d,
+ * e, and w[0..15]
+ */
+ for ( i = 0 ; i < ( sizeof ( u.ddd.dword ) /
+ sizeof ( u.ddd.dword[0] ) ) ; i++ ) {
+ be32_to_cpus ( &context->ddd.dword[i] );
+ u.ddd.dword[i] = context->ddd.dword[i];
+ }
+
+ /* Initialise w[16..79] */
+ for ( i = 16 ; i < 80 ; i++ )
+ w[i] = rol32 ( ( w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16] ), 1 );
+
+ /* Main loop */
+ for ( i = 0 ; i < 80 ; i++ ) {
+ step = &sha1_steps[ i / 20 ];
+ f = step->f ( &u.v );
+ k = step->k;
+ temp = ( rol32 ( *a, 5 ) + f + *e + k + w[i] );
+ *e = *d;
+ *d = *c;
+ *c = rol32 ( *b, 30 );
+ *b = *a;
+ *a = temp;
+ DBGC2 ( context, "%2d : %08x %08x %08x %08x %08x\n",
+ i, *a, *b, *c, *d, *e );
+ }
+
+ /* Add chunk to hash and convert back to big-endian */
+ for ( i = 0 ; i < 5 ; i++ ) {
+ context->ddd.dd.digest.h[i] =
+ cpu_to_be32 ( context->ddd.dd.digest.h[i] +
+ u.ddd.dd.digest.h[i] );
+ }
+
+ DBGC ( context, "SHA1 digested:\n" );
+ DBGC_HDA ( context, 0, &context->ddd.dd.digest,
+ sizeof ( context->ddd.dd.digest ) );
+}
+
+/**
+ * Accumulate data with SHA-1 algorithm
+ *
+ * @v ctx SHA-1 context
+ * @v data Data
+ * @v len Length of data
+ */
+static void sha1_update ( void *ctx, const void *data, size_t len ) {
+ struct sha1_context *context = ctx;
+ const uint8_t *byte = data;
+ size_t offset;
+
+ /* Accumulate data a byte at a time, performing the digest
+ * whenever we fill the data buffer
+ */
+ while ( len-- ) {
+ offset = ( context->len % sizeof ( context->ddd.dd.data ) );
+ context->ddd.dd.data.byte[offset] = *(byte++);
+ context->len++;
+ if ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 )
+ sha1_digest ( context );
+ }
+}
+
+/**
+ * Generate SHA-1 digest
+ *
+ * @v ctx SHA-1 context
+ * @v out Output buffer
+ */
+static void sha1_final ( void *ctx, void *out ) {
+ struct sha1_context *context = ctx;
+ uint64_t len_bits;
+ uint8_t pad;
+
+ /* Record length before pre-processing */
+ len_bits = cpu_to_be64 ( ( ( uint64_t ) context->len ) * 8 );
+
+ /* Pad with a single "1" bit followed by as many "0" bits as required */
+ pad = 0x80;
+ do {
+ sha1_update ( ctx, &pad, sizeof ( pad ) );
+ pad = 0x00;
+ } while ( ( context->len % sizeof ( context->ddd.dd.data ) ) !=
+ offsetof ( typeof ( context->ddd.dd.data ), final.len ) );
+
+ /* Append length (in bits) */
+ sha1_update ( ctx, &len_bits, sizeof ( len_bits ) );
+ assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 );
+
+ /* Copy out final digest */
+ memcpy ( out, &context->ddd.dd.digest,
+ sizeof ( context->ddd.dd.digest ) );
+}
+
+/** SHA-1 algorithm */
+struct digest_algorithm sha1_algorithm = {
+ .name = "sha1",
+ .ctxsize = sizeof ( struct sha1_context ),
+ .blocksize = sizeof ( union sha1_block ),
+ .digestsize = sizeof ( struct sha1_digest ),
+ .init = sha1_init,
+ .update = sha1_update,
+ .final = sha1_final,
+};
+
+/** "sha1" object identifier */
+static uint8_t oid_sha1[] = { ASN1_OID_SHA1 };
+
+/** "sha1" OID-identified algorithm */
+struct asn1_algorithm oid_sha1_algorithm __asn1_algorithm = {
+ .name = "sha1",
+ .digest = &sha1_algorithm,
+ .oid = ASN1_OID_CURSOR ( oid_sha1 ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/sha1extra.c b/src/VBox/Devices/PC/ipxe/src/crypto/sha1extra.c
new file mode 100644
index 00000000..01d5f89c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/sha1extra.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <ipxe/crypto.h>
+#include <ipxe/sha1.h>
+#include <ipxe/hmac.h>
+#include <stdint.h>
+#include <byteswap.h>
+
+/**
+ * SHA1 pseudorandom function for creating derived keys
+ *
+ * @v key Master key with which this call is associated
+ * @v key_len Length of key
+ * @v label NUL-terminated ASCII string describing purpose of PRF data
+ * @v data Further data that should be included in the PRF
+ * @v data_len Length of further PRF data
+ * @v prf_len Bytes of PRF to generate
+ * @ret prf Pseudorandom function bytes
+ *
+ * This is the PRF variant used by 802.11, defined in IEEE 802.11-2007
+ * 8.5.5.1. EAP-FAST uses a different SHA1-based PRF, and TLS uses an
+ * MD5-based PRF.
+ */
+void prf_sha1 ( const void *key, size_t key_len, const char *label,
+ const void *data, size_t data_len, void *prf, size_t prf_len )
+{
+ u32 blk;
+ u8 keym[key_len]; /* modifiable copy of key */
+ u8 in[strlen ( label ) + 1 + data_len + 1]; /* message to HMAC */
+ u8 *in_blknr; /* pointer to last byte of in, block number */
+ u8 out[SHA1_DIGEST_SIZE]; /* HMAC-SHA1 result */
+ u8 sha1_ctx[SHA1_CTX_SIZE]; /* SHA1 context */
+ const size_t label_len = strlen ( label );
+
+ /* The HMAC-SHA-1 is calculated using the given key on the
+ message text `label', followed by a NUL, followed by one
+ byte indicating the block number (0 for first). */
+
+ memcpy ( keym, key, key_len );
+
+ memcpy ( in, label, strlen ( label ) + 1 );
+ memcpy ( in + label_len + 1, data, data_len );
+ in_blknr = in + label_len + 1 + data_len;
+
+ for ( blk = 0 ;; blk++ ) {
+ *in_blknr = blk;
+
+ hmac_init ( &sha1_algorithm, sha1_ctx, keym, &key_len );
+ hmac_update ( &sha1_algorithm, sha1_ctx, in, sizeof ( in ) );
+ hmac_final ( &sha1_algorithm, sha1_ctx, keym, &key_len, out );
+
+ if ( prf_len <= sizeof ( out ) ) {
+ memcpy ( prf, out, prf_len );
+ break;
+ }
+
+ memcpy ( prf, out, sizeof ( out ) );
+ prf_len -= sizeof ( out );
+ prf += sizeof ( out );
+ }
+}
+
+/**
+ * PBKDF2 key derivation function inner block operation
+ *
+ * @v passphrase Passphrase from which to derive key
+ * @v pass_len Length of passphrase
+ * @v salt Salt to include in key
+ * @v salt_len Length of salt
+ * @v iterations Number of iterations of SHA1 to perform
+ * @v blocknr Index of this block, starting at 1
+ * @ret block SHA1_SIZE bytes of PBKDF2 data
+ *
+ * The operation of this function is described in RFC 2898.
+ */
+static void pbkdf2_sha1_f ( const void *passphrase, size_t pass_len,
+ const void *salt, size_t salt_len,
+ int iterations, u32 blocknr, u8 *block )
+{
+ u8 pass[pass_len]; /* modifiable passphrase */
+ u8 in[salt_len + 4]; /* input buffer to first round */
+ u8 last[SHA1_DIGEST_SIZE]; /* output of round N, input of N+1 */
+ u8 sha1_ctx[SHA1_CTX_SIZE];
+ u8 *next_in = in; /* changed to `last' after first round */
+ int next_size = sizeof ( in );
+ int i;
+ unsigned int j;
+
+ blocknr = htonl ( blocknr );
+
+ memcpy ( pass, passphrase, pass_len );
+ memcpy ( in, salt, salt_len );
+ memcpy ( in + salt_len, &blocknr, 4 );
+ memset ( block, 0, sizeof ( last ) );
+
+ for ( i = 0; i < iterations; i++ ) {
+ hmac_init ( &sha1_algorithm, sha1_ctx, pass, &pass_len );
+ hmac_update ( &sha1_algorithm, sha1_ctx, next_in, next_size );
+ hmac_final ( &sha1_algorithm, sha1_ctx, pass, &pass_len, last );
+
+ for ( j = 0; j < sizeof ( last ); j++ ) {
+ block[j] ^= last[j];
+ }
+
+ next_in = last;
+ next_size = sizeof ( last );
+ }
+}
+
+/**
+ * PBKDF2 key derivation function using SHA1
+ *
+ * @v passphrase Passphrase from which to derive key
+ * @v pass_len Length of passphrase
+ * @v salt Salt to include in key
+ * @v salt_len Length of salt
+ * @v iterations Number of iterations of SHA1 to perform
+ * @v key_len Length of key to generate
+ * @ret key Generated key bytes
+ *
+ * This is used most notably in 802.11 WPA passphrase hashing, in
+ * which case the salt is the SSID, 4096 iterations are used, and a
+ * 32-byte key is generated that serves as the Pairwise Master Key for
+ * EAPOL authentication.
+ *
+ * The operation of this function is further described in RFC 2898.
+ */
+void pbkdf2_sha1 ( const void *passphrase, size_t pass_len,
+ const void *salt, size_t salt_len,
+ int iterations, void *key, size_t key_len )
+{
+ u32 blocks = ( key_len + SHA1_DIGEST_SIZE - 1 ) / SHA1_DIGEST_SIZE;
+ u32 blk;
+ u8 buf[SHA1_DIGEST_SIZE];
+
+ for ( blk = 1; blk <= blocks; blk++ ) {
+ pbkdf2_sha1_f ( passphrase, pass_len, salt, salt_len,
+ iterations, blk, buf );
+ if ( key_len <= sizeof ( buf ) ) {
+ memcpy ( key, buf, key_len );
+ break;
+ }
+
+ memcpy ( key, buf, sizeof ( buf ) );
+ key_len -= sizeof ( buf );
+ key += sizeof ( buf );
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/sha256.c b/src/VBox/Devices/PC/ipxe/src/crypto/sha256.c
new file mode 100644
index 00000000..e85d2006
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/sha256.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * SHA-256 algorithm
+ *
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <byteswap.h>
+#include <assert.h>
+#include <ipxe/rotate.h>
+#include <ipxe/crypto.h>
+#include <ipxe/asn1.h>
+#include <ipxe/sha256.h>
+
+/** SHA-256 variables */
+struct sha256_variables {
+ /* This layout matches that of struct sha256_digest_data,
+ * allowing for efficient endianness-conversion,
+ */
+ uint32_t a;
+ uint32_t b;
+ uint32_t c;
+ uint32_t d;
+ uint32_t e;
+ uint32_t f;
+ uint32_t g;
+ uint32_t h;
+ uint32_t w[64];
+} __attribute__ (( packed ));
+
+/** SHA-256 constants */
+static const uint32_t k[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
+ 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
+ 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+ 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
+ 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
+ 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+/**
+ * Initialise SHA-256 algorithm
+ *
+ * @v ctx SHA-256 context
+ */
+static void sha256_init ( void *ctx ) {
+ struct sha256_context *context = ctx;
+
+ context->ddd.dd.digest.h[0] = cpu_to_be32 ( 0x6a09e667 );
+ context->ddd.dd.digest.h[1] = cpu_to_be32 ( 0xbb67ae85 );
+ context->ddd.dd.digest.h[2] = cpu_to_be32 ( 0x3c6ef372 );
+ context->ddd.dd.digest.h[3] = cpu_to_be32 ( 0xa54ff53a );
+ context->ddd.dd.digest.h[4] = cpu_to_be32 ( 0x510e527f );
+ context->ddd.dd.digest.h[5] = cpu_to_be32 ( 0x9b05688c );
+ context->ddd.dd.digest.h[6] = cpu_to_be32 ( 0x1f83d9ab );
+ context->ddd.dd.digest.h[7] = cpu_to_be32 ( 0x5be0cd19 );
+ context->len = 0;
+}
+
+/**
+ * Calculate SHA-256 digest of accumulated data
+ *
+ * @v context SHA-256 context
+ */
+static void sha256_digest ( struct sha256_context *context ) {
+ union {
+ union sha256_digest_data_dwords ddd;
+ struct sha256_variables v;
+ } u;
+ uint32_t *a = &u.v.a;
+ uint32_t *b = &u.v.b;
+ uint32_t *c = &u.v.c;
+ uint32_t *d = &u.v.d;
+ uint32_t *e = &u.v.e;
+ uint32_t *f = &u.v.f;
+ uint32_t *g = &u.v.g;
+ uint32_t *h = &u.v.h;
+ uint32_t *w = u.v.w;
+ uint32_t s0;
+ uint32_t s1;
+ uint32_t maj;
+ uint32_t t1;
+ uint32_t t2;
+ uint32_t ch;
+ unsigned int i;
+
+ /* Sanity checks */
+ assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 );
+ linker_assert ( &u.ddd.dd.digest.h[0] == a, sha256_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[1] == b, sha256_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[2] == c, sha256_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[3] == d, sha256_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[4] == e, sha256_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[5] == f, sha256_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[6] == g, sha256_bad_layout );
+ linker_assert ( &u.ddd.dd.digest.h[7] == h, sha256_bad_layout );
+ linker_assert ( &u.ddd.dd.data.dword[0] == w, sha256_bad_layout );
+
+ DBGC ( context, "SHA256 digesting:\n" );
+ DBGC_HDA ( context, 0, &context->ddd.dd.digest,
+ sizeof ( context->ddd.dd.digest ) );
+ DBGC_HDA ( context, context->len, &context->ddd.dd.data,
+ sizeof ( context->ddd.dd.data ) );
+
+ /* Convert h[0..7] to host-endian, and initialise a, b, c, d,
+ * e, f, g, h, and w[0..15]
+ */
+ for ( i = 0 ; i < ( sizeof ( u.ddd.dword ) /
+ sizeof ( u.ddd.dword[0] ) ) ; i++ ) {
+ be32_to_cpus ( &context->ddd.dword[i] );
+ u.ddd.dword[i] = context->ddd.dword[i];
+ }
+
+ /* Initialise w[16..63] */
+ for ( i = 16 ; i < 64 ; i++ ) {
+ s0 = ( ror32 ( w[i-15], 7 ) ^ ror32 ( w[i-15], 18 ) ^
+ ( w[i-15] >> 3 ) );
+ s1 = ( ror32 ( w[i-2], 17 ) ^ ror32 ( w[i-2], 19 ) ^
+ ( w[i-2] >> 10 ) );
+ w[i] = ( w[i-16] + s0 + w[i-7] + s1 );
+ }
+
+ /* Main loop */
+ for ( i = 0 ; i < 64 ; i++ ) {
+ s0 = ( ror32 ( *a, 2 ) ^ ror32 ( *a, 13 ) ^ ror32 ( *a, 22 ) );
+ maj = ( ( *a & *b ) ^ ( *a & *c ) ^ ( *b & *c ) );
+ t2 = ( s0 + maj );
+ s1 = ( ror32 ( *e, 6 ) ^ ror32 ( *e, 11 ) ^ ror32 ( *e, 25 ) );
+ ch = ( ( *e & *f ) ^ ( (~*e) & *g ) );
+ t1 = ( *h + s1 + ch + k[i] + w[i] );
+ *h = *g;
+ *g = *f;
+ *f = *e;
+ *e = ( *d + t1 );
+ *d = *c;
+ *c = *b;
+ *b = *a;
+ *a = ( t1 + t2 );
+ DBGC2 ( context, "%2d : %08x %08x %08x %08x %08x %08x %08x "
+ "%08x\n", i, *a, *b, *c, *d, *e, *f, *g, *h );
+ }
+
+ /* Add chunk to hash and convert back to big-endian */
+ for ( i = 0 ; i < 8 ; i++ ) {
+ context->ddd.dd.digest.h[i] =
+ cpu_to_be32 ( context->ddd.dd.digest.h[i] +
+ u.ddd.dd.digest.h[i] );
+ }
+
+ DBGC ( context, "SHA256 digested:\n" );
+ DBGC_HDA ( context, 0, &context->ddd.dd.digest,
+ sizeof ( context->ddd.dd.digest ) );
+}
+
+/**
+ * Accumulate data with SHA-256 algorithm
+ *
+ * @v ctx SHA-256 context
+ * @v data Data
+ * @v len Length of data
+ */
+static void sha256_update ( void *ctx, const void *data, size_t len ) {
+ struct sha256_context *context = ctx;
+ const uint8_t *byte = data;
+ size_t offset;
+
+ /* Accumulate data a byte at a time, performing the digest
+ * whenever we fill the data buffer
+ */
+ while ( len-- ) {
+ offset = ( context->len % sizeof ( context->ddd.dd.data ) );
+ context->ddd.dd.data.byte[offset] = *(byte++);
+ context->len++;
+ if ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 )
+ sha256_digest ( context );
+ }
+}
+
+/**
+ * Generate SHA-256 digest
+ *
+ * @v ctx SHA-256 context
+ * @v out Output buffer
+ */
+static void sha256_final ( void *ctx, void *out ) {
+ struct sha256_context *context = ctx;
+ uint64_t len_bits;
+ uint8_t pad;
+
+ /* Record length before pre-processing */
+ len_bits = cpu_to_be64 ( ( ( uint64_t ) context->len ) * 8 );
+
+ /* Pad with a single "1" bit followed by as many "0" bits as required */
+ pad = 0x80;
+ do {
+ sha256_update ( ctx, &pad, sizeof ( pad ) );
+ pad = 0x00;
+ } while ( ( context->len % sizeof ( context->ddd.dd.data ) ) !=
+ offsetof ( typeof ( context->ddd.dd.data ), final.len ) );
+
+ /* Append length (in bits) */
+ sha256_update ( ctx, &len_bits, sizeof ( len_bits ) );
+ assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 );
+
+ /* Copy out final digest */
+ memcpy ( out, &context->ddd.dd.digest,
+ sizeof ( context->ddd.dd.digest ) );
+}
+
+/** SHA-256 algorithm */
+struct digest_algorithm sha256_algorithm = {
+ .name = "sha256",
+ .ctxsize = sizeof ( struct sha256_context ),
+ .blocksize = sizeof ( union sha256_block ),
+ .digestsize = sizeof ( struct sha256_digest ),
+ .init = sha256_init,
+ .update = sha256_update,
+ .final = sha256_final,
+};
+
+/** "sha256" object identifier */
+static uint8_t oid_sha256[] = { ASN1_OID_SHA256 };
+
+/** "sha256" OID-identified algorithm */
+struct asn1_algorithm oid_sha256_algorithm __asn1_algorithm = {
+ .name = "sha256",
+ .digest = &sha256_algorithm,
+ .oid = ASN1_OID_CURSOR ( oid_sha256 ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/crypto/x509.c b/src/VBox/Devices/PC/ipxe/src/crypto/x509.c
new file mode 100644
index 00000000..18a8cebe
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/crypto/x509.c
@@ -0,0 +1,1577 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/list.h>
+#include <ipxe/malloc.h>
+#include <ipxe/asn1.h>
+#include <ipxe/crypto.h>
+#include <ipxe/md5.h>
+#include <ipxe/sha1.h>
+#include <ipxe/sha256.h>
+#include <ipxe/rsa.h>
+#include <ipxe/rootcert.h>
+#include <ipxe/x509.h>
+
+/** @file
+ *
+ * X.509 certificates
+ *
+ * The structure of X.509v3 certificates is documented in RFC 5280
+ * section 4.1.
+ */
+
+/* Disambiguate the various error causes */
+#define ENOTSUP_ALGORITHM \
+ __einfo_error ( EINFO_ENOTSUP_ALGORITHM )
+#define EINFO_ENOTSUP_ALGORITHM \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" )
+#define ENOTSUP_EXTENSION \
+ __einfo_error ( EINFO_ENOTSUP_EXTENSION )
+#define EINFO_ENOTSUP_EXTENSION \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported extension" )
+#define EINVAL_ALGORITHM \
+ __einfo_error ( EINFO_EINVAL_ALGORITHM )
+#define EINFO_EINVAL_ALGORITHM \
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid algorithm type" )
+#define EINVAL_ALGORITHM_MISMATCH \
+ __einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH )
+#define EINFO_EINVAL_ALGORITHM_MISMATCH \
+ __einfo_uniqify ( EINFO_EINVAL, 0x04, "Signature algorithm mismatch" )
+#define EINVAL_PATH_LEN \
+ __einfo_error ( EINFO_EINVAL_PATH_LEN )
+#define EINFO_EINVAL_PATH_LEN \
+ __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid pathLenConstraint" )
+#define EINVAL_VERSION \
+ __einfo_error ( EINFO_EINVAL_VERSION )
+#define EINFO_EINVAL_VERSION \
+ __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid version" )
+#define EACCES_WRONG_ISSUER \
+ __einfo_error ( EINFO_EACCES_WRONG_ISSUER )
+#define EINFO_EACCES_WRONG_ISSUER \
+ __einfo_uniqify ( EINFO_EACCES, 0x01, "Wrong issuer" )
+#define EACCES_NOT_CA \
+ __einfo_error ( EINFO_EACCES_NOT_CA )
+#define EINFO_EACCES_NOT_CA \
+ __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a CA certificate" )
+#define EACCES_KEY_USAGE \
+ __einfo_error ( EINFO_EACCES_KEY_USAGE )
+#define EINFO_EACCES_KEY_USAGE \
+ __einfo_uniqify ( EINFO_EACCES, 0x03, "Incorrect key usage" )
+#define EACCES_EXPIRED \
+ __einfo_error ( EINFO_EACCES_EXPIRED )
+#define EINFO_EACCES_EXPIRED \
+ __einfo_uniqify ( EINFO_EACCES, 0x04, "Expired (or not yet valid)" )
+#define EACCES_PATH_LEN \
+ __einfo_error ( EINFO_EACCES_PATH_LEN )
+#define EINFO_EACCES_PATH_LEN \
+ __einfo_uniqify ( EINFO_EACCES, 0x05, "Maximum path length exceeded" )
+#define EACCES_UNTRUSTED \
+ __einfo_error ( EINFO_EACCES_UNTRUSTED )
+#define EINFO_EACCES_UNTRUSTED \
+ __einfo_uniqify ( EINFO_EACCES, 0x06, "Untrusted root certificate" )
+#define EACCES_OUT_OF_ORDER \
+ __einfo_error ( EINFO_EACCES_OUT_OF_ORDER )
+#define EINFO_EACCES_OUT_OF_ORDER \
+ __einfo_uniqify ( EINFO_EACCES, 0x07, "Validation out of order" )
+#define EACCES_EMPTY \
+ __einfo_error ( EINFO_EACCES_EMPTY )
+#define EINFO_EACCES_EMPTY \
+ __einfo_uniqify ( EINFO_EACCES, 0x08, "Empty certificate chain" )
+
+/** Certificate cache */
+static LIST_HEAD ( x509_cache );
+
+/**
+ * Free X.509 certificate
+ *
+ * @v refcnt Reference count
+ */
+static void x509_free ( struct refcnt *refcnt ) {
+ struct x509_certificate *cert =
+ container_of ( refcnt, struct x509_certificate, refcnt );
+
+ DBGC2 ( cert, "X509 %p freed\n", cert );
+ free ( cert->subject.name );
+ free ( cert->extensions.auth_info.ocsp.uri );
+ free ( cert );
+}
+
+/**
+ * Discard a cached certificate
+ *
+ * @ret discarded Number of cached items discarded
+ */
+static unsigned int x509_discard ( void ) {
+ struct x509_certificate *cert;
+
+ /* Discard the least recently used certificate for which the
+ * only reference is held by the cache itself.
+ */
+ list_for_each_entry_reverse ( cert, &x509_cache, list ) {
+ if ( cert->refcnt.count == 0 ) {
+ list_del ( &cert->list );
+ x509_put ( cert );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/** X.509 cache discarder */
+struct cache_discarder x509_cache_discarder __cache_discarder = {
+ .discard = x509_discard,
+};
+
+/** "commonName" object identifier */
+static uint8_t oid_common_name[] = { ASN1_OID_COMMON_NAME };
+
+/** "commonName" object identifier cursor */
+static struct asn1_cursor oid_common_name_cursor =
+ ASN1_OID_CURSOR ( oid_common_name );
+
+/**
+ * Parse X.509 certificate version
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_version ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ int version;
+ int rc;
+
+ /* Enter version */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
+
+ /* Parse integer */
+ if ( ( rc = asn1_integer ( &cursor, &version ) ) != 0 ) {
+ DBGC ( cert, "X509 %p cannot parse version: %s\n",
+ cert, strerror ( rc ) );
+ DBGC_HDA ( cert, 0, raw->data, raw->len );
+ return rc;
+ }
+
+ /* Sanity check */
+ if ( version < 0 ) {
+ DBGC ( cert, "X509 %p invalid version %d\n", cert, version );
+ DBGC_HDA ( cert, 0, raw->data, raw->len );
+ return -EINVAL_VERSION;
+ }
+
+ /* Record version */
+ cert->version = version;
+ DBGC2 ( cert, "X509 %p is a version %d certificate\n",
+ cert, ( cert->version + 1 ) );
+
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate serial number
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_serial ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct x509_serial *serial = &cert->serial;
+ int rc;
+
+ /* Record raw serial number */
+ memcpy ( &serial->raw, raw, sizeof ( serial->raw ) );
+ if ( ( rc = asn1_shrink ( &serial->raw, ASN1_INTEGER ) ) != 0 ) {
+ DBGC ( cert, "X509 %p cannot shrink serialNumber: %s\n",
+ cert, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( cert, "X509 %p issuer is:\n", cert );
+ DBGC2_HDA ( cert, 0, serial->raw.data, serial->raw.len );
+
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate issuer
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_issuer ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct x509_issuer *issuer = &cert->issuer;
+ int rc;
+
+ /* Record raw issuer */
+ memcpy ( &issuer->raw, raw, sizeof ( issuer->raw ) );
+ if ( ( rc = asn1_shrink ( &issuer->raw, ASN1_SEQUENCE ) ) != 0 ) {
+ DBGC ( cert, "X509 %p cannot shrink issuer: %s\n",
+ cert, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( cert, "X509 %p issuer is:\n", cert );
+ DBGC2_HDA ( cert, 0, issuer->raw.data, issuer->raw.len );
+
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate validity
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_validity ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct x509_validity *validity = &cert->validity;
+ struct x509_time *not_before = &validity->not_before;
+ struct x509_time *not_after = &validity->not_after;
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter validity */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse notBefore */
+ if ( ( rc = asn1_generalized_time ( &cursor,
+ &not_before->time ) ) != 0 ) {
+ DBGC ( cert, "X509 %p cannot parse notBefore: %s\n",
+ cert, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( cert, "X509 %p valid from time %lld\n",
+ cert, not_before->time );
+ asn1_skip_any ( &cursor );
+
+ /* Parse notAfter */
+ if ( ( rc = asn1_generalized_time ( &cursor,
+ &not_after->time ) ) != 0 ) {
+ DBGC ( cert, "X509 %p cannot parse notAfter: %s\n",
+ cert, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( cert, "X509 %p valid until time %lld\n",
+ cert, not_after->time );
+
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate common name
+ *
+ * @v cert X.509 certificate
+ * @v name Common name to fill in
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_common_name ( struct x509_certificate *cert, char **name,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ struct asn1_cursor oid_cursor;
+ struct asn1_cursor name_cursor;
+ int rc;
+
+ /* Enter name */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Scan through name list */
+ for ( ; cursor.len ; asn1_skip_any ( &cursor ) ) {
+
+ /* Check for "commonName" OID */
+ memcpy ( &oid_cursor, &cursor, sizeof ( oid_cursor ) );
+ asn1_enter ( &oid_cursor, ASN1_SET );
+ asn1_enter ( &oid_cursor, ASN1_SEQUENCE );
+ memcpy ( &name_cursor, &oid_cursor, sizeof ( name_cursor ) );
+ asn1_enter ( &oid_cursor, ASN1_OID );
+ if ( asn1_compare ( &oid_common_name_cursor, &oid_cursor ) != 0)
+ continue;
+ asn1_skip_any ( &name_cursor );
+ if ( ( rc = asn1_enter_any ( &name_cursor ) ) != 0 ) {
+ DBGC ( cert, "X509 %p cannot locate name:\n", cert );
+ DBGC_HDA ( cert, 0, raw->data, raw->len );
+ return rc;
+ }
+
+ /* Allocate and copy name */
+ *name = zalloc ( name_cursor.len + 1 /* NUL */ );
+ if ( ! *name )
+ return -ENOMEM;
+ memcpy ( *name, name_cursor.data, name_cursor.len );
+
+ /* Check that name contains no NULs */
+ if ( strlen ( *name ) != name_cursor.len ) {
+ DBGC ( cert, "X509 %p contains malicious commonName:\n",
+ cert );
+ DBGC_HDA ( cert, 0, raw->data, raw->len );
+ return rc;
+ }
+
+ return 0;
+ }
+
+ /* Certificates may not have a commonName */
+ DBGC2 ( cert, "X509 %p no commonName found:\n", cert );
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate subject
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_subject ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct x509_subject *subject = &cert->subject;
+ char **name = &subject->name;
+ int rc;
+
+ /* Record raw subject */
+ memcpy ( &subject->raw, raw, sizeof ( subject->raw ) );
+ asn1_shrink_any ( &subject->raw );
+ DBGC2 ( cert, "X509 %p subject is:\n", cert );
+ DBGC2_HDA ( cert, 0, subject->raw.data, subject->raw.len );
+
+ /* Parse common name */
+ if ( ( rc = x509_parse_common_name ( cert, name, raw ) ) != 0 )
+ return rc;
+ DBGC2 ( cert, "X509 %p common name is \"%s\":\n", cert, *name );
+
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate public key information
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_public_key ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct x509_public_key *public_key = &cert->subject.public_key;
+ struct asn1_algorithm **algorithm = &public_key->algorithm;
+ struct asn1_bit_string *raw_bits = &public_key->raw_bits;
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Record raw subjectPublicKeyInfo */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_shrink_any ( &cursor );
+ memcpy ( &public_key->raw, &cursor, sizeof ( public_key->raw ) );
+ DBGC2 ( cert, "X509 %p public key is:\n", cert );
+ DBGC2_HDA ( cert, 0, public_key->raw.data, public_key->raw.len );
+
+ /* Enter subjectPublicKeyInfo */
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse algorithm */
+ if ( ( rc = asn1_pubkey_algorithm ( &cursor, algorithm ) ) != 0 ) {
+ DBGC ( cert, "X509 %p could not parse public key algorithm: "
+ "%s\n", cert, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( cert, "X509 %p public key algorithm is %s\n",
+ cert, (*algorithm)->name );
+ asn1_skip_any ( &cursor );
+
+ /* Parse bit string */
+ if ( ( rc = asn1_bit_string ( &cursor, raw_bits ) ) != 0 ) {
+ DBGC ( cert, "X509 %p could not parse public key bits: %s\n",
+ cert, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate basic constraints
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_basic_constraints ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct x509_basic_constraints *basic = &cert->extensions.basic;
+ struct asn1_cursor cursor;
+ int ca = 0;
+ int path_len;
+ int rc;
+
+ /* Enter basicConstraints */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse "cA", if present */
+ if ( asn1_type ( &cursor ) == ASN1_BOOLEAN ) {
+ ca = asn1_boolean ( &cursor );
+ if ( ca < 0 ) {
+ rc = ca;
+ DBGC ( cert, "X509 %p cannot parse cA: %s\n",
+ cert, strerror ( rc ) );
+ DBGC_HDA ( cert, 0, raw->data, raw->len );
+ return rc;
+ }
+ asn1_skip_any ( &cursor );
+ }
+ basic->ca = ca;
+ DBGC2 ( cert, "X509 %p is %sa CA certificate\n",
+ cert, ( basic->ca ? "" : "not " ) );
+
+ /* Ignore everything else unless "cA" is true */
+ if ( ! ca )
+ return 0;
+
+ /* Parse "pathLenConstraint", if present and applicable */
+ basic->path_len = X509_PATH_LEN_UNLIMITED;
+ if ( asn1_type ( &cursor ) == ASN1_INTEGER ) {
+ if ( ( rc = asn1_integer ( &cursor, &path_len ) ) != 0 ) {
+ DBGC ( cert, "X509 %p cannot parse pathLenConstraint: "
+ "%s\n", cert, strerror ( rc ) );
+ DBGC_HDA ( cert, 0, raw->data, raw->len );
+ return rc;
+ }
+ if ( path_len < 0 ) {
+ DBGC ( cert, "X509 %p invalid pathLenConstraint %d\n",
+ cert, path_len );
+ DBGC_HDA ( cert, 0, raw->data, raw->len );
+ return -EINVAL;
+ }
+ basic->path_len = path_len;
+ DBGC2 ( cert, "X509 %p path length constraint is %u\n",
+ cert, basic->path_len );
+ }
+
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate key usage
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_key_usage ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct x509_key_usage *usage = &cert->extensions.usage;
+ struct asn1_bit_string bit_string;
+ const uint8_t *bytes;
+ size_t len;
+ unsigned int i;
+ int rc;
+
+ /* Mark extension as present */
+ usage->present = 1;
+
+ /* Parse bit string */
+ if ( ( rc = asn1_bit_string ( raw, &bit_string ) ) != 0 ) {
+ DBGC ( cert, "X509 %p could not parse key usage: %s\n",
+ cert, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Parse key usage bits */
+ bytes = bit_string.data;
+ len = bit_string.len;
+ if ( len > sizeof ( usage->bits ) )
+ len = sizeof ( usage->bits );
+ for ( i = 0 ; i < len ; i++ ) {
+ usage->bits |= ( *(bytes++) << ( 8 * i ) );
+ }
+ DBGC2 ( cert, "X509 %p key usage is %08x\n", cert, usage->bits );
+
+ return 0;
+}
+
+/** "id-kp-codeSigning" object identifier */
+static uint8_t oid_code_signing[] = { ASN1_OID_CODESIGNING };
+
+/** "id-kp-OCSPSigning" object identifier */
+static uint8_t oid_ocsp_signing[] = { ASN1_OID_OCSPSIGNING };
+
+/** Supported key purposes */
+static struct x509_key_purpose x509_key_purposes[] = {
+ {
+ .name = "codeSigning",
+ .bits = X509_CODE_SIGNING,
+ .oid = ASN1_OID_CURSOR ( oid_code_signing ),
+ },
+ {
+ .name = "ocspSigning",
+ .bits = X509_OCSP_SIGNING,
+ .oid = ASN1_OID_CURSOR ( oid_ocsp_signing ),
+ },
+};
+
+/**
+ * Parse X.509 certificate key purpose identifier
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_key_purpose ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct x509_extended_key_usage *ext_usage = &cert->extensions.ext_usage;
+ struct x509_key_purpose *purpose;
+ struct asn1_cursor cursor;
+ unsigned int i;
+ int rc;
+
+ /* Enter keyPurposeId */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ if ( ( rc = asn1_enter ( &cursor, ASN1_OID ) ) != 0 ) {
+ DBGC ( cert, "X509 %p invalid keyPurposeId:\n", cert );
+ DBGC_HDA ( cert, 0, raw->data, raw->len );
+ return rc;
+ }
+
+ /* Identify key purpose */
+ for ( i = 0 ; i < ( sizeof ( x509_key_purposes ) /
+ sizeof ( x509_key_purposes[0] ) ) ; i++ ) {
+ purpose = &x509_key_purposes[i];
+ if ( asn1_compare ( &cursor, &purpose->oid ) == 0 ) {
+ DBGC2 ( cert, "X509 %p has key purpose %s\n",
+ cert, purpose->name );
+ ext_usage->bits |= purpose->bits;
+ return 0;
+ }
+ }
+
+ /* Ignore unrecognised key purposes */
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate extended key usage
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_extended_key_usage ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter extKeyUsage */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse each extended key usage in turn */
+ while ( cursor.len ) {
+ if ( ( rc = x509_parse_key_purpose ( cert, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+ }
+
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate OCSP access method
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_ocsp ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct x509_ocsp_responder *ocsp = &cert->extensions.auth_info.ocsp;
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter accessLocation */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ if ( ( rc = asn1_enter ( &cursor, ASN1_IMPLICIT_TAG ( 6 ) ) ) != 0 ) {
+ DBGC ( cert, "X509 %p OCSP does not contain "
+ "uniformResourceIdentifier:\n", cert );
+ DBGC_HDA ( cert, 0, raw->data, raw->len );
+ return rc;
+ }
+
+ /* Record URI */
+ ocsp->uri = zalloc ( cursor.len + 1 /* NUL */ );
+ if ( ! ocsp->uri )
+ return -ENOMEM;
+ memcpy ( ocsp->uri, cursor.data, cursor.len );
+ DBGC2 ( cert, "X509 %p OCSP URI is %s:\n", cert, ocsp->uri );
+
+ return 0;
+}
+
+/** "id-ad-ocsp" object identifier */
+static uint8_t oid_ad_ocsp[] = { ASN1_OID_OCSP };
+
+/** Supported access methods */
+static struct x509_access_method x509_access_methods[] = {
+ {
+ .name = "OCSP",
+ .oid = ASN1_OID_CURSOR ( oid_ad_ocsp ),
+ .parse = x509_parse_ocsp,
+ },
+};
+
+/**
+ * Identify X.509 access method by OID
+ *
+ * @v oid OID
+ * @ret method Access method, or NULL
+ */
+static struct x509_access_method *
+x509_find_access_method ( const struct asn1_cursor *oid ) {
+ struct x509_access_method *method;
+ unsigned int i;
+
+ for ( i = 0 ; i < ( sizeof ( x509_access_methods ) /
+ sizeof ( x509_access_methods[0] ) ) ; i++ ) {
+ method = &x509_access_methods[i];
+ if ( asn1_compare ( &method->oid, oid ) == 0 )
+ return method;
+ }
+
+ return NULL;
+}
+
+/**
+ * Parse X.509 certificate access description
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_access_description ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ struct asn1_cursor subcursor;
+ struct x509_access_method *method;
+ int rc;
+
+ /* Enter keyPurposeId */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Try to identify access method */
+ memcpy ( &subcursor, &cursor, sizeof ( subcursor ) );
+ asn1_enter ( &subcursor, ASN1_OID );
+ method = x509_find_access_method ( &subcursor );
+ asn1_skip_any ( &cursor );
+ DBGC2 ( cert, "X509 %p found access method %s\n",
+ cert, ( method ? method->name : "<unknown>" ) );
+
+ /* Parse access location, if applicable */
+ if ( method && ( ( rc = method->parse ( cert, &cursor ) ) != 0 ) )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate authority information access
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_authority_info_access ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter authorityInfoAccess */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse each access description in turn */
+ while ( cursor.len ) {
+ if ( ( rc = x509_parse_access_description ( cert,
+ &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+ }
+
+ return 0;
+}
+
+/** "id-ce-basicConstraints" object identifier */
+static uint8_t oid_ce_basic_constraints[] =
+ { ASN1_OID_BASICCONSTRAINTS };
+
+/** "id-ce-keyUsage" object identifier */
+static uint8_t oid_ce_key_usage[] =
+ { ASN1_OID_KEYUSAGE };
+
+/** "id-ce-extKeyUsage" object identifier */
+static uint8_t oid_ce_ext_key_usage[] =
+ { ASN1_OID_EXTKEYUSAGE };
+
+/** "id-pe-authorityInfoAccess" object identifier */
+static uint8_t oid_pe_authority_info_access[] =
+ { ASN1_OID_AUTHORITYINFOACCESS };
+
+/** Supported certificate extensions */
+static struct x509_extension x509_extensions[] = {
+ {
+ .name = "basicConstraints",
+ .oid = ASN1_OID_CURSOR ( oid_ce_basic_constraints ),
+ .parse = x509_parse_basic_constraints,
+ },
+ {
+ .name = "keyUsage",
+ .oid = ASN1_OID_CURSOR ( oid_ce_key_usage ),
+ .parse = x509_parse_key_usage,
+ },
+ {
+ .name = "extKeyUsage",
+ .oid = ASN1_OID_CURSOR ( oid_ce_ext_key_usage ),
+ .parse = x509_parse_extended_key_usage,
+ },
+ {
+ .name = "authorityInfoAccess",
+ .oid = ASN1_OID_CURSOR ( oid_pe_authority_info_access ),
+ .parse = x509_parse_authority_info_access,
+ },
+};
+
+/**
+ * Identify X.509 extension by OID
+ *
+ * @v oid OID
+ * @ret extension Extension, or NULL
+ */
+static struct x509_extension *
+x509_find_extension ( const struct asn1_cursor *oid ) {
+ struct x509_extension *extension;
+ unsigned int i;
+
+ for ( i = 0 ; i < ( sizeof ( x509_extensions ) /
+ sizeof ( x509_extensions[0] ) ) ; i++ ) {
+ extension = &x509_extensions[i];
+ if ( asn1_compare ( &extension->oid, oid ) == 0 )
+ return extension;
+ }
+
+ return NULL;
+}
+
+/**
+ * Parse X.509 certificate extension
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_extension ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ struct asn1_cursor subcursor;
+ struct x509_extension *extension;
+ int is_critical = 0;
+ int rc;
+
+ /* Enter extension */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Try to identify extension */
+ memcpy ( &subcursor, &cursor, sizeof ( subcursor ) );
+ asn1_enter ( &subcursor, ASN1_OID );
+ extension = x509_find_extension ( &subcursor );
+ asn1_skip_any ( &cursor );
+ DBGC2 ( cert, "X509 %p found extension %s\n",
+ cert, ( extension ? extension->name : "<unknown>" ) );
+
+ /* Identify criticality */
+ if ( asn1_type ( &cursor ) == ASN1_BOOLEAN ) {
+ is_critical = asn1_boolean ( &cursor );
+ if ( is_critical < 0 ) {
+ rc = is_critical;
+ DBGC ( cert, "X509 %p cannot parse extension "
+ "criticality: %s\n", cert, strerror ( rc ) );
+ DBGC_HDA ( cert, 0, raw->data, raw->len );
+ return rc;
+ }
+ asn1_skip_any ( &cursor );
+ }
+
+ /* Handle unknown extensions */
+ if ( ! extension ) {
+ if ( is_critical ) {
+ /* Fail if we cannot handle a critical extension */
+ DBGC ( cert, "X509 %p cannot handle critical "
+ "extension:\n", cert );
+ DBGC_HDA ( cert, 0, raw->data, raw->len );
+ return -ENOTSUP_EXTENSION;
+ } else {
+ /* Ignore unknown non-critical extensions */
+ return 0;
+ }
+ };
+
+ /* Extract extnValue */
+ if ( ( rc = asn1_enter ( &cursor, ASN1_OCTET_STRING ) ) != 0 ) {
+ DBGC ( cert, "X509 %p extension missing extnValue:\n", cert );
+ DBGC_HDA ( cert, 0, raw->data, raw->len );
+ return rc;
+ }
+
+ /* Parse extension */
+ if ( ( rc = extension->parse ( cert, &cursor ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate extensions, if present
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_extensions ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter extensions, if present */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 3 ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse each extension in turn */
+ while ( cursor.len ) {
+ if ( ( rc = x509_parse_extension ( cert, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+ }
+
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate tbsCertificate
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse_tbscertificate ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct asn1_algorithm **algorithm = &cert->signature_algorithm;
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Record raw tbsCertificate */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_shrink_any ( &cursor );
+ memcpy ( &cert->tbs, &cursor, sizeof ( cert->tbs ) );
+
+ /* Enter tbsCertificate */
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse version, if present */
+ if ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) {
+ if ( ( rc = x509_parse_version ( cert, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+ }
+
+ /* Parse serialNumber */
+ if ( ( rc = x509_parse_serial ( cert, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Parse signature */
+ if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) {
+ DBGC ( cert, "X509 %p could not parse signature algorithm: "
+ "%s\n", cert, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( cert, "X509 %p tbsCertificate signature algorithm is %s\n",
+ cert, (*algorithm)->name );
+ asn1_skip_any ( &cursor );
+
+ /* Parse issuer */
+ if ( ( rc = x509_parse_issuer ( cert, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Parse validity */
+ if ( ( rc = x509_parse_validity ( cert, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Parse subject */
+ if ( ( rc = x509_parse_subject ( cert, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Parse subjectPublicKeyInfo */
+ if ( ( rc = x509_parse_public_key ( cert, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Parse extensions, if present */
+ if ( ( rc = x509_parse_extensions ( cert, &cursor ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Parse X.509 certificate from ASN.1 data
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int x509_parse ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw ) {
+ struct x509_signature *signature = &cert->signature;
+ struct asn1_algorithm **signature_algorithm = &signature->algorithm;
+ struct asn1_bit_string *signature_value = &signature->value;
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Record raw certificate */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ memcpy ( &cert->raw, &cursor, sizeof ( cert->raw ) );
+
+ /* Enter certificate */
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse tbsCertificate */
+ if ( ( rc = x509_parse_tbscertificate ( cert, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Parse signatureAlgorithm */
+ if ( ( rc = asn1_signature_algorithm ( &cursor,
+ signature_algorithm ) ) != 0 ) {
+ DBGC ( cert, "X509 %p could not parse signature algorithm: "
+ "%s\n", cert, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( cert, "X509 %p signatureAlgorithm is %s\n",
+ cert, (*signature_algorithm)->name );
+ asn1_skip_any ( &cursor );
+
+ /* Parse signatureValue */
+ if ( ( rc = asn1_integral_bit_string ( &cursor,
+ signature_value ) ) != 0 ) {
+ DBGC ( cert, "X509 %p could not parse signature value: %s\n",
+ cert, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( cert, "X509 %p signatureValue is:\n", cert );
+ DBGC2_HDA ( cert, 0, signature_value->data, signature_value->len );
+
+ /* Check that algorithm in tbsCertificate matches algorithm in
+ * signature
+ */
+ if ( signature->algorithm != (*signature_algorithm) ) {
+ DBGC ( cert, "X509 %p signature algorithm %s does not match "
+ "signatureAlgorithm %s\n",
+ cert, signature->algorithm->name,
+ (*signature_algorithm)->name );
+ return -EINVAL_ALGORITHM_MISMATCH;
+ }
+
+ return 0;
+}
+
+/**
+ * Create X.509 certificate
+ *
+ * @v data Raw certificate data
+ * @v len Length of raw data
+ * @ret cert X.509 certificate
+ * @ret rc Return status code
+ *
+ * On success, the caller holds a reference to the X.509 certificate,
+ * and is responsible for ultimately calling x509_put().
+ */
+int x509_certificate ( const void *data, size_t len,
+ struct x509_certificate **cert ) {
+ struct asn1_cursor cursor;
+ void *raw;
+ int rc;
+
+ /* Initialise cursor */
+ cursor.data = data;
+ cursor.len = len;
+ asn1_shrink_any ( &cursor );
+
+ /* Search for certificate within cache */
+ list_for_each_entry ( (*cert), &x509_cache, list ) {
+ if ( asn1_compare ( &cursor, &(*cert)->raw ) == 0 ) {
+
+ DBGC2 ( *cert, "X509 %p \"%s\" cache hit\n",
+ *cert, (*cert)->subject.name );
+
+ /* Mark as most recently used */
+ list_del ( &(*cert)->list );
+ list_add ( &(*cert)->list, &x509_cache );
+
+ /* Add caller's reference */
+ x509_get ( *cert );
+
+ return 0;
+ }
+ }
+
+ /* Allocate and initialise certificate */
+ *cert = zalloc ( sizeof ( **cert ) + cursor.len );
+ if ( ! *cert )
+ return -ENOMEM;
+ ref_init ( &(*cert)->refcnt, x509_free );
+ INIT_LIST_HEAD ( &(*cert)->list );
+ raw = ( *cert + 1 );
+
+ /* Copy raw data */
+ memcpy ( raw, cursor.data, cursor.len );
+ cursor.data = raw;
+
+ /* Parse certificate */
+ if ( ( rc = x509_parse ( *cert, &cursor ) ) != 0 ) {
+ x509_put ( *cert );
+ return rc;
+ }
+
+ /* Add certificate to cache */
+ x509_get ( *cert );
+ list_add ( &(*cert)->list, &x509_cache );
+
+ return 0;
+}
+
+/**
+ * Check X.509 certificate signature
+ *
+ * @v cert X.509 certificate
+ * @v public_key X.509 public key
+ * @ret rc Return status code
+ */
+static int x509_check_signature ( struct x509_certificate *cert,
+ struct x509_public_key *public_key ) {
+ struct x509_signature *signature = &cert->signature;
+ struct asn1_algorithm *algorithm = signature->algorithm;
+ struct digest_algorithm *digest = algorithm->digest;
+ struct pubkey_algorithm *pubkey = algorithm->pubkey;
+ uint8_t digest_ctx[ digest->ctxsize ];
+ uint8_t digest_out[ digest->digestsize ];
+ uint8_t pubkey_ctx[ pubkey->ctxsize ];
+ int rc;
+
+ /* Sanity check */
+ assert ( cert->signature_algorithm == cert->signature.algorithm );
+
+ /* Calculate certificate digest */
+ digest_init ( digest, digest_ctx );
+ digest_update ( digest, digest_ctx, cert->tbs.data, cert->tbs.len );
+ digest_final ( digest, digest_ctx, digest_out );
+ DBGC2 ( cert, "X509 %p \"%s\" digest:\n", cert, cert->subject.name );
+ DBGC2_HDA ( cert, 0, digest_out, sizeof ( digest_out ) );
+
+ /* Check that signature public key algorithm matches signer */
+ if ( public_key->algorithm->pubkey != pubkey ) {
+ DBGC ( cert, "X509 %p \"%s\" signature algorithm %s does not "
+ "match signer's algorithm %s\n",
+ cert, cert->subject.name, algorithm->name,
+ public_key->algorithm->name );
+ rc = -EINVAL_ALGORITHM_MISMATCH;
+ goto err_mismatch;
+ }
+
+ /* Verify signature using signer's public key */
+ if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data,
+ public_key->raw.len ) ) != 0 ) {
+ DBGC ( cert, "X509 %p \"%s\" cannot initialise public key: "
+ "%s\n", cert, cert->subject.name, strerror ( rc ) );
+ goto err_pubkey_init;
+ }
+ if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out,
+ signature->value.data,
+ signature->value.len ) ) != 0 ) {
+ DBGC ( cert, "X509 %p \"%s\" signature verification failed: "
+ "%s\n", cert, cert->subject.name, strerror ( rc ) );
+ goto err_pubkey_verify;
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_pubkey_verify:
+ pubkey_final ( pubkey, pubkey_ctx );
+ err_pubkey_init:
+ err_mismatch:
+ return rc;
+}
+
+/**
+ * Check X.509 certificate against issuer certificate
+ *
+ * @v cert X.509 certificate
+ * @v issuer X.509 issuer certificate
+ * @ret rc Return status code
+ */
+int x509_check_issuer ( struct x509_certificate *cert,
+ struct x509_certificate *issuer ) {
+ struct x509_public_key *public_key = &issuer->subject.public_key;
+ int rc;
+
+ /* Check issuer. In theory, this should be a full X.500 DN
+ * comparison, which would require support for a plethora of
+ * abominations such as TeletexString (which allows the
+ * character set to be changed mid-string using escape codes).
+ * In practice, we assume that anyone who deliberately changes
+ * the encoding of the issuer DN is probably a masochist who
+ * will rather enjoy the process of figuring out exactly why
+ * their certificate doesn't work.
+ *
+ * See http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
+ * for some enjoyable ranting on this subject.
+ */
+ if ( asn1_compare ( &cert->issuer.raw, &issuer->subject.raw ) != 0 ) {
+ DBGC ( cert, "X509 %p \"%s\" issuer does not match X509 %p "
+ "\"%s\" subject\n", cert, cert->subject.name,
+ issuer, issuer->subject.name );
+ DBGC_HDA ( cert, 0, cert->issuer.raw.data,
+ cert->issuer.raw.len );
+ DBGC_HDA ( issuer, 0, issuer->subject.raw.data,
+ issuer->subject.raw.len );
+ return -EACCES_WRONG_ISSUER;
+ }
+
+ /* Check that issuer is allowed to sign certificates */
+ if ( ! issuer->extensions.basic.ca ) {
+ DBGC ( issuer, "X509 %p \"%s\" cannot sign X509 %p \"%s\": "
+ "not a CA certificate\n", issuer, issuer->subject.name,
+ cert, cert->subject.name );
+ return -EACCES_NOT_CA;
+ }
+ if ( issuer->extensions.usage.present &&
+ ( ! ( issuer->extensions.usage.bits & X509_KEY_CERT_SIGN ) ) ) {
+ DBGC ( issuer, "X509 %p \"%s\" cannot sign X509 %p \"%s\": "
+ "no keyCertSign usage\n", issuer, issuer->subject.name,
+ cert, cert->subject.name );
+ return -EACCES_KEY_USAGE;
+ }
+
+ /* Check signature */
+ if ( ( rc = x509_check_signature ( cert, public_key ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Calculate X.509 certificate fingerprint
+ *
+ * @v cert X.509 certificate
+ * @v digest Digest algorithm
+ * @v fingerprint Fingerprint buffer
+ */
+void x509_fingerprint ( struct x509_certificate *cert,
+ struct digest_algorithm *digest,
+ void *fingerprint ) {
+ uint8_t ctx[ digest->ctxsize ];
+
+ /* Calculate fingerprint */
+ digest_init ( digest, ctx );
+ digest_update ( digest, ctx, cert->raw.data, cert->raw.len );
+ digest_final ( digest, ctx, fingerprint );
+}
+
+/**
+ * Check X.509 root certificate
+ *
+ * @v cert X.509 certificate
+ * @v root X.509 root certificate store
+ * @ret rc Return status code
+ */
+int x509_check_root ( struct x509_certificate *cert, struct x509_root *root ) {
+ struct digest_algorithm *digest = root->digest;
+ uint8_t fingerprint[ digest->digestsize ];
+ const uint8_t *root_fingerprint = root->fingerprints;
+ unsigned int i;
+
+ /* Calculate certificate fingerprint */
+ x509_fingerprint ( cert, digest, fingerprint );
+
+ /* Check fingerprint against all root certificates */
+ for ( i = 0 ; i < root->count ; i++ ) {
+ if ( memcmp ( fingerprint, root_fingerprint,
+ sizeof ( fingerprint ) ) == 0 ) {
+ DBGC ( cert, "X509 %p \"%s\" is a root certificate\n",
+ cert, cert->subject.name );
+ return 0;
+ }
+ root_fingerprint += sizeof ( fingerprint );
+ }
+
+ DBGC2 ( cert, "X509 %p \"%s\" is not a root certificate\n",
+ cert, cert->subject.name );
+ return -ENOENT;
+}
+
+/**
+ * Check X.509 certificate validity period
+ *
+ * @v cert X.509 certificate
+ * @v time Time at which to check certificate
+ * @ret rc Return status code
+ */
+int x509_check_time ( struct x509_certificate *cert, time_t time ) {
+ struct x509_validity *validity = &cert->validity;
+
+ /* Check validity period */
+ if ( time < validity->not_before.time ) {
+ DBGC ( cert, "X509 %p \"%s\" is not yet valid (at time %lld)\n",
+ cert, cert->subject.name, time );
+ return -EACCES_EXPIRED;
+ }
+ if ( time > validity->not_after.time ) {
+ DBGC ( cert, "X509 %p \"%s\" has expired (at time %lld)\n",
+ cert, cert->subject.name, time );
+ return -EACCES_EXPIRED;
+ }
+
+ DBGC2 ( cert, "X509 %p \"%s\" is valid (at time %lld)\n",
+ cert, cert->subject.name, time );
+ return 0;
+}
+
+/**
+ * Validate X.509 certificate
+ *
+ * @v cert X.509 certificate
+ * @v issuer Issuing X.509 certificate (or NULL)
+ * @v time Time at which to validate certificate
+ * @v root Root certificate store, or NULL to use default
+ * @ret rc Return status code
+ *
+ * The issuing certificate must have already been validated.
+ *
+ * Validation results are cached: if a certificate has already been
+ * successfully validated then @c issuer, @c time, and @c root will be
+ * ignored.
+ */
+int x509_validate ( struct x509_certificate *cert,
+ struct x509_certificate *issuer,
+ time_t time, struct x509_root *root ) {
+ unsigned int max_path_remaining;
+ int rc;
+
+ /* Use default root certificate store if none specified */
+ if ( ! root )
+ root = &root_certificates;
+
+ /* Return success if certificate has already been validated */
+ if ( cert->valid )
+ return 0;
+
+ /* Fail if certificate is invalid at specified time */
+ if ( ( rc = x509_check_time ( cert, time ) ) != 0 )
+ return rc;
+
+ /* Succeed if certificate is a trusted root certificate */
+ if ( x509_check_root ( cert, root ) == 0 ) {
+ cert->valid = 1;
+ cert->path_remaining = ( cert->extensions.basic.path_len + 1 );
+ return 0;
+ }
+
+ /* Fail unless we have an issuer */
+ if ( ! issuer ) {
+ DBGC2 ( cert, "X509 %p \"%s\" has no issuer\n",
+ cert, cert->subject.name );
+ return -EACCES_UNTRUSTED;
+ }
+
+ /* Fail unless issuer has already been validated */
+ if ( ! issuer->valid ) {
+ DBGC ( cert, "X509 %p \"%s\" issuer %p \"%s\" has not yet "
+ "been validated\n", cert, cert->subject.name,
+ issuer, issuer->subject.name );
+ return -EACCES_OUT_OF_ORDER;
+ }
+
+ /* Fail if issuing certificate cannot validate this certificate */
+ if ( ( rc = x509_check_issuer ( cert, issuer ) ) != 0 )
+ return rc;
+
+ /* Fail if path length constraint is violated */
+ if ( issuer->path_remaining == 0 ) {
+ DBGC ( cert, "X509 %p \"%s\" issuer %p \"%s\" path length "
+ "exceeded\n", cert, cert->subject.name,
+ issuer, issuer->subject.name );
+ return -EACCES_PATH_LEN;
+ }
+
+ /* Calculate effective path length */
+ cert->path_remaining = ( issuer->path_remaining - 1 );
+ max_path_remaining = ( cert->extensions.basic.path_len + 1 );
+ if ( cert->path_remaining > max_path_remaining )
+ cert->path_remaining = max_path_remaining;
+
+ /* Mark certificate as valid */
+ cert->valid = 1;
+
+ DBGC ( cert, "X509 %p \"%s\" successfully validated using issuer %p "
+ "\"%s\"\n", cert, cert->subject.name,
+ issuer, issuer->subject.name );
+ return 0;
+}
+
+/**
+ * Free X.509 certificate chain
+ *
+ * @v refcnt Reference count
+ */
+static void x509_free_chain ( struct refcnt *refcnt ) {
+ struct x509_chain *chain =
+ container_of ( refcnt, struct x509_chain, refcnt );
+ struct x509_link *link;
+ struct x509_link *tmp;
+
+ DBGC2 ( chain, "X509 chain %p freed\n", chain );
+
+ /* Free each link in the chain */
+ list_for_each_entry_safe ( link, tmp, &chain->links, list ) {
+ x509_put ( link->cert );
+ list_del ( &link->list );
+ free ( link );
+ }
+
+ /* Free chain */
+ free ( chain );
+}
+
+/**
+ * Allocate X.509 certificate chain
+ *
+ * @ret chain X.509 certificate chain, or NULL
+ */
+struct x509_chain * x509_alloc_chain ( void ) {
+ struct x509_chain *chain;
+
+ /* Allocate chain */
+ chain = zalloc ( sizeof ( *chain ) );
+ if ( ! chain )
+ return NULL;
+
+ /* Initialise chain */
+ ref_init ( &chain->refcnt, x509_free_chain );
+ INIT_LIST_HEAD ( &chain->links );
+
+ DBGC2 ( chain, "X509 chain %p allocated\n", chain );
+ return chain;
+}
+
+/**
+ * Append X.509 certificate to X.509 certificate chain
+ *
+ * @v chain X.509 certificate chain
+ * @v cert X.509 certificate
+ * @ret rc Return status code
+ */
+int x509_append ( struct x509_chain *chain, struct x509_certificate *cert ) {
+ struct x509_link *link;
+
+ /* Allocate link */
+ link = zalloc ( sizeof ( *link ) );
+ if ( ! link )
+ return -ENOMEM;
+
+ /* Add link to chain */
+ link->cert = x509_get ( cert );
+ list_add_tail ( &link->list, &chain->links );
+ DBGC ( chain, "X509 chain %p added X509 %p \"%s\"\n",
+ chain, cert, cert->subject.name );
+
+ return 0;
+}
+
+/**
+ * Append X.509 certificate to X.509 certificate chain
+ *
+ * @v chain X.509 certificate chain
+ * @v data Raw certificate data
+ * @v len Length of raw data
+ * @ret rc Return status code
+ */
+int x509_append_raw ( struct x509_chain *chain, const void *data,
+ size_t len ) {
+ struct x509_certificate *cert;
+ int rc;
+
+ /* Parse certificate */
+ if ( ( rc = x509_certificate ( data, len, &cert ) ) != 0 )
+ goto err_parse;
+
+ /* Append certificate to chain */
+ if ( ( rc = x509_append ( chain, cert ) ) != 0 )
+ goto err_append;
+
+ /* Drop reference to certificate */
+ x509_put ( cert );
+
+ return 0;
+
+ err_append:
+ x509_put ( cert );
+ err_parse:
+ return rc;
+}
+
+/**
+ * Identify X.509 certificate by subject
+ *
+ * @v certs X.509 certificate list
+ * @v subject Subject
+ * @ret cert X.509 certificate, or NULL if not found
+ */
+static struct x509_certificate *
+x509_find_subject ( struct x509_chain *certs,
+ const struct asn1_cursor *subject ) {
+ struct x509_link *link;
+ struct x509_certificate *cert;
+
+ /* Scan through certificate list */
+ list_for_each_entry ( link, &certs->links, list ) {
+
+ /* Check subject */
+ cert = link->cert;
+ if ( asn1_compare ( subject, &cert->subject.raw ) == 0 )
+ return cert;
+ }
+
+ return NULL;
+}
+
+/**
+ * Append X.509 certificates to X.509 certificate chain
+ *
+ * @v chain X.509 certificate chain
+ * @v certs X.509 certificate list
+ * @ret rc Return status code
+ *
+ * Certificates will be automatically appended to the chain based upon
+ * the subject and issuer names.
+ */
+int x509_auto_append ( struct x509_chain *chain, struct x509_chain *certs ) {
+ struct x509_certificate *cert;
+ struct x509_certificate *previous;
+ int rc;
+
+ /* Get current certificate */
+ cert = x509_last ( chain );
+ if ( ! cert ) {
+ DBGC ( chain, "X509 chain %p has no certificates\n", chain );
+ return -EINVAL;
+ }
+
+ /* Append certificates, in order */
+ while ( 1 ) {
+
+ /* Find issuing certificate */
+ previous = cert;
+ cert = x509_find_subject ( certs, &cert->issuer.raw );
+ if ( ! cert )
+ break;
+ if ( cert == previous )
+ break;
+
+ /* Append certificate to chain */
+ if ( ( rc = x509_append ( chain, cert ) ) != 0 )
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Validate X.509 certificate chain
+ *
+ * @v chain X.509 certificate chain
+ * @v time Time at which to validate certificates
+ * @v root Root certificate store, or NULL to use default
+ * @ret rc Return status code
+ */
+int x509_validate_chain ( struct x509_chain *chain, time_t time,
+ struct x509_root *root ) {
+ struct x509_certificate *issuer = NULL;
+ struct x509_link *link;
+ int rc;
+
+ /* Sanity check */
+ if ( list_empty ( &chain->links ) ) {
+ DBGC ( chain, "X509 chain %p is empty\n", chain );
+ return -EACCES_EMPTY;
+ }
+
+ /* Find first certificate that can be validated as a
+ * standalone (i.e. is already valid, or can be validated as
+ * a trusted root certificate).
+ */
+ list_for_each_entry ( link, &chain->links, list ) {
+
+ /* Try validating this certificate as a standalone */
+ if ( ( rc = x509_validate ( link->cert, NULL, time,
+ root ) ) != 0 )
+ continue;
+
+ /* Work back up to start of chain, performing pairwise
+ * validation.
+ */
+ issuer = link->cert;
+ list_for_each_entry_continue_reverse ( link, &chain->links,
+ list ) {
+
+ /* Validate this certificate against its issuer */
+ if ( ( rc = x509_validate ( link->cert, issuer, time,
+ root ) ) != 0 )
+ return rc;
+ issuer = link->cert;
+ }
+
+ return 0;
+ }
+
+ DBGC ( chain, "X509 chain %p found no valid certificates\n", chain );
+ return -EACCES_UNTRUSTED;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/doc/build_sys.dox b/src/VBox/Devices/PC/ipxe/src/doc/build_sys.dox
new file mode 100644
index 00000000..9466f662
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/doc/build_sys.dox
@@ -0,0 +1,419 @@
+/** @page build_sys Build system
+
+@section overview Overview
+
+Building an Etherboot image consists of three stages:
+
+ -# @ref compilation : Compiling all the source files into object files
+ -# @ref linking : Linking a particular image from selected object files
+ -# @ref finalisation : Producing the final output binary
+
+Though this is a remarkably complex process, it is important to note
+that it all happens automatically. Whatever state your build tree is
+in, you can always type, for example
+
+@code
+
+ make bin/rtl8139.dsk
+
+@endcode
+
+and know that you will get a floppy disk image with an RTL8139 driver
+built from the current sources.
+
+@section compilation Compilation
+
+@subsection comp_overview Overview
+
+Each source file (a @c .c or a @c .S file) is compiled into a @c .o
+file in the @c bin/ directory. Etherboot makes minimal use of
+conditional compilation (see @ref ifdef_harmful), and so you will find
+that all objects get built, even the objects that correspond to
+features that you are not intending to include in your image. For
+example, all network card drivers will be compiled even if you are
+just building a ROM for a 3c509 card. This is a deliberate design
+decision; please do @b not attempt to "fix" the build system to avoid
+doing this.
+
+Source files are defined to be any @c .c or @c .S files found in a
+directory listed in the Makefile variable #SRCDIRS. You therefore do
+@b not need to edit the Makefile just because you have added a new
+source file (although you will need to edit the Makefile if you have
+added a new source directory). To see a list of all source
+directories and source files that the build system currently knows
+about, you can use the commands
+
+@code
+
+ make srcdirs
+ make srcs
+
+@endcode
+
+Rules for compiling @c .c and @c .S files are defined in the Makefile
+variables #RULE_c and #RULE_S. Makefile rules are automatically
+generated for each source file using these rules. The generated rules
+can be found in the @c .d file corresponding to each source file;
+these are located in <tt>bin/deps/</tt>. For example, the rules
+generated for <tt>drivers/net/rtl8139.c</tt> can be found in
+<tt>bin/deps/drivers/net/rtl8139.c.d</tt>. These rules allow you to
+type, for example
+
+@code
+
+ make bin/rtl8139.o
+
+@endcode
+
+and have <tt>rtl8139.o</tt> be built from
+<tt>drivers/net/rtl8139.c</tt> using the generic rule #RULE_c for
+compiling @c .c files.
+
+You can see the full list of object files that will be built using
+
+@code
+
+ make bobjs
+
+@endcode
+
+@subsection comp_ar After compilation
+
+Once all objects have been compiled, they will be collected into a
+build library ("blib") in <tt>bin/blib.a</tt>.
+
+@subsection comp_custom Customising compilation
+
+The Makefile rules for a particular object can be customised to a
+certain extent by defining the Makefile variable CFLAGS_@<object@>.
+For example, if you were to set
+
+@code
+
+ CFLAGS_rtl8139 = -DFOO
+
+@endcode
+
+then <tt>bin/rtl8139.o</tt> would be compiled with the additional
+flags <tt>-DFOO</tt>. To see the flags that will be used when
+compiling a particular object, you can use e.g.
+
+@code
+
+ make bin/rtl8139.flags
+
+@endcode
+
+If you need more flexibility than the CFLAGS_@<object@> mechanism
+provides, then you can exclude source files from the automatic rule
+generation process by listing them in the Makefile variable
+#NON_AUTO_SRCS. The command
+
+@code
+
+ make autosrcs
+
+@endcode
+
+will show you which files are currently part of the automatic rule
+generation process.
+
+@subsection comp_multiobj Multiple objects
+
+A single source file can be used to generate multiple object files.
+This is used, for example, to generate the decompressing and the
+non-decompressing prefixes from the same source files.
+
+By default, a single object will be built from each source file. To
+override the list of objects for a source file, you can define the
+Makefile variable OBJS_@<object@>. For example, the
+<tt>arch/i386/prefix/dskprefix.S</tt> source file is built into two
+objects, <tt>bin/dskprefix.o</tt> and <tt>zdskprefix.o</tt> by
+defining the Makefile variable
+
+@code
+
+ OBJS_dskprefix = dskprefix zdskprefix
+
+@endcode
+
+Since there would be little point in building two identical objects,
+customised compilation flags (see @ref comp_custom) are defined as
+
+@code
+
+ CFLAGS_zdskprefix = -DCOMPRESS
+
+@endcode
+
+Thus, <tt>arch/i386/prefix/dskprefix.S</tt> is built into @c
+dskprefix.o using the normal set of flags, and into @c zdskprefix.o
+using the normal set of flags plus <tt>-DCOMPRESS</tt>.
+
+@subsection comp_debug Special debugging targets
+
+In addition to the basic rules #RULE_c and #RULE_S for compiling
+source files into object files, there are various other rules that can
+be useful for debugging.
+
+@subsubsection comp_debug_c_to_c Preprocessed C
+
+You can see the results of preprocessing a @c .c file (including the
+per-object flags defined via CFLAGS_@<object@> if applicable) using
+e.g.
+
+@code
+
+ make bin/rtl8139.c
+
+@endcode
+
+and examining the resulting file (<tt>bin/rtl8139.c</tt> in this
+case).
+
+@subsubsection comp_debug_x_to_s Assembler
+
+You can see the results of assembling a @c .c file, or of
+preprocessing a @c .S file, using e.g.
+
+@code
+
+ make bin/rtl8139.s
+ make bin/zdskprefix.s
+
+@endcode
+
+@subsubsection comp_debug_dbg Debugging-enabled targets
+
+You can build targets with debug messages (DBG()) enabled using e.g.
+
+@code
+
+ make bin/rtl8139.dbg.o
+ make bin/rtl8139.dbg2.o
+
+@endcode
+
+You will probably not need to use these targets directly, since a
+mechanism exists to select debugging levels at build time; see @ref
+debug.
+
+@section linking Linking
+
+@subsection link_overview Overview
+
+Etherboot is designed to be small and extremely customisable. This is
+achieved by linking in only the features that are really wanted in any
+particular build.
+
+There are two places from which the list of desired features is
+obtained:
+
+ -# @ref link_config_h
+ -# @ref link_cmdline
+
+@subsection link_config_h config.h
+
+The config.h file is used to define global build options that are
+likely to apply to all images that you build, such as the console
+types, supported download protocols etc. See the documentation for
+config.h for more details.
+
+@subsection link_cmdline The make command line
+
+When you type a command such as
+
+@code
+
+ make bin/dfe538.zrom
+
+@endcode
+
+it is used to derive the following information:
+
+ - We are building a compressed ROM image
+ - The DFE538 is a PCI NIC, so we need the decompressing PCI ROM prefix
+ - The PCI IDs for the DFE538 are 1186:1300
+ - The DFE538 is an rtl8139-based card, therefore we need the rtl8139 driver
+
+You can see this process in action using the command
+
+@code
+
+ make bin/dfe538.zrom.info
+
+@endcode
+
+which will print
+
+@code
+
+ Elements : dfe538
+ Prefix : zrom
+ Drivers : rtl8139
+ ROM name : dfe538
+ Media : rom
+
+ ROM type : pci
+ PCI vendor : 0x1186
+ PCI device : 0x1300
+
+ LD driver symbols : obj_rtl8139
+ LD prefix symbols : obj_zpciprefix
+ LD ID symbols : pci_vendor_id=0x1186 pci_device_id=0x1300
+
+ LD target flags : -u obj_zpciprefix --defsym check_obj_zpciprefix=obj_zpciprefix -u obj_rtl8139 --defsym check_obj_rtl8139=obj_rtl8139 -u obj_config --defsym check_obj_config=obj_config --defsym pci_vendor_id=0x1186 --defsym pci_device_id=0x1300
+
+@endcode
+
+This should be interpreted as follows:
+
+@code
+
+ Elements : dfe538
+ Prefix : zrom
+
+@endcode
+
+"Elements" is the list of components preceding the first dot in the
+target name. "Prefix" is the component following the first dot in the
+target name. (It's called a "prefix" because the code that makes it a
+@c .zrom (rather than a @c .dsk, @c .zpxe or any other type of target)
+usually ends up at the start of the resulting binary image.)
+
+@code
+
+ Drivers : rtl8139
+
+@endcode
+
+"Drivers" is the list of drivers corresponding to the "Elements".
+Most drivers support several network cards. The PCI_ROM() and
+ISA_ROM() macros are used in the driver source files to list the cards
+that a particular driver can support.
+
+@code
+
+ ROM name : dfe538
+
+@endcode
+
+"ROM name" is the first element in the "Elements" list. It is used to
+select the PCI IDs for a PCI ROM.
+
+@code
+
+ Media : rom
+
+@endcode
+
+"Media" is the "Prefix" minus the leading @c z, if any.
+
+@code
+
+ ROM type : pci
+ PCI vendor : 0x1186
+ PCI device : 0x1300
+
+@endcode
+
+These are derived from the "ROM name" and the PCI_ROM() or ISA_ROM()
+macros in the driver source files.
+
+@code
+
+ LD driver symbols : obj_rtl8139
+ LD prefix symbols : obj_zpciprefix
+
+@endcode
+
+This is the interesting part. At this point, we have established that
+we need the rtl8139 driver (i.e. @c rtl8139.o) and the decompressing
+PCI prefix (i.e. @c zpciprefix.o). Our build system (via the
+compiler.h header file) arranges that every object exports a symbol
+obj_@<object@>; this can be seen by e.g.
+
+@code
+
+ objdump -t bin/rtl8139.o
+
+@endcode
+
+which will show the line
+
+@code
+
+ 00000000 g *ABS* 00000000 obj_rtl8139
+
+@endcode
+
+By instructing the linker that we need the symbols @c obj_rtl8139 and
+@c obj_zpciprefix, we can therefore ensure that these two objects are
+included in our build. (The linker will also include any objects that
+these two objects require, since that's the whole purpose of the
+linker.)
+
+In a similar way, we always instruct the linker that we need the
+symbol @c obj_config, in order to include the object @c config.o. @c
+config.o is used to drag in the objects that were specified via
+config.h; see @ref link_config_h.
+
+@code
+
+ LD target flags : -u obj_zpciprefix --defsym check_obj_zpciprefix=obj_zpciprefix -u obj_rtl8139 --defsym check_obj_rtl8139=obj_rtl8139 -u obj_config --defsym check_obj_config=obj_config --defsym pci_vendor_id=0x1186 --defsym pci_device_id=0x1300
+
+@endcode
+
+These are the flags that we pass to the linker in order to include the
+objects that we want in our build, and to check that they really get
+included. (This latter check is needed to work around what seems to
+be a bug in @c ld).
+
+The linker does its job of linking all the required objects together
+into a coherent build. The best way to see what is happening is to
+look at one of the resulting linker maps; try, for example
+
+@code
+
+ make bin/dfe538.dsk.map
+
+@endcode
+
+The linker map includes, amongst others:
+
+ - A list of which objects are included in the build, and why.
+ - The results of processing the linker script, line-by-line.
+ - A complete symbol table of the resulting build.
+
+It is worth spending time examining the linker map to see how an
+Etherboot image is assembled.
+
+Whatever format is selected, the Etherboot image is built into an ELF
+file, simply because this is the default format used by @c ld.
+
+@section finalisation Finalisation
+
+@subsection final_overview Overview
+
+The ELF file resulting from @ref linking "linking" needs to be
+converted into the final binary image. Usually, this is just a case
+of running
+
+@code
+
+ objcopy -O binary <elf file> <output file>
+
+@endcode
+
+to convert the ELF file into a raw binary image. Certain image
+formats require special additional treatment.
+
+@subsection final_rom ROM images
+
+ROM images must be rounded up to a suitable ROM size (e.g. 16kB or
+32kB), and certain header information such as checksums needs to be
+filled in. This is done by the @c makerom.pl program.
+
+@section debug Debugging-enabled builds
+
+*/
diff --git a/src/VBox/Devices/PC/ipxe/src/doc/pxe_extensions b/src/VBox/Devices/PC/ipxe/src/doc/pxe_extensions
new file mode 100644
index 00000000..2411486d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/doc/pxe_extensions
@@ -0,0 +1,312 @@
+FILE OPEN
+
+Op-Code: PXENV_FILE_OPEN (00e0h)
+
+Input: Far pointer to a t_PXENV_FILE_OPEN parameter structure
+ that has been initialised by the caller.
+
+Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be
+ returned in AX. The status field in the parameter
+ structure must be set to one of the values represented
+ by the PXENV_STATUS_xxx constants.
+
+Description: Opens a file specified by a URL for reading. Multiple
+ files may be opened and used concurrently.
+
+
+typedef struct s_PXENV_FILE_OPEN {
+ PXENV_STATUS Status;
+ UINT16 FileHandle;
+ SEGOFF16 FileName;
+ UINT32 Reserved;
+} t_PXENV_FILE_OPEN;
+
+
+Set before calling API service:
+
+FileName: URL of file to be opened. Null terminated.
+
+Reserved: Must be zero.
+
+
+Returned from API service:
+
+FileHandle: Handle for use in subsequent PXE FILE API calls.
+
+Status: See PXENV_STATUS_xxx constants.
+
+
+
+
+FILE CLOSE
+
+Op-Code: PXENV_FILE_CLOSE (00e1h)
+
+Input: Far pointer to a t_PXENV_FILE_CLOSE parameter structure
+ that has been initialised by the caller.
+
+Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be
+ returned in AX. The status field in the parameter
+ structure must be set to one of the values represented
+ by the PXENV_STATUS_xxx constants.
+
+Description: Closes a previously opened file.
+
+
+typedef struct s_PXENV_FILE_CLOSE {
+ PXENV_STATUS Status;
+ UINT16 FileHandle;
+} t_PXENV_FILE_CLOSE;
+
+
+Set before calling API service:
+
+FileHandle: Handle obtained when file was opened.
+
+
+Returned from API service:
+
+Status: See PXENV_STATUS_xxx constants.
+
+
+
+
+FILE SELECT
+
+Op-Code: PXENV_FILE_SELECT (00e2h)
+
+Input: Far pointer to a t_PXENV_FILE_SELECT parameter structure
+ that has been initialised by the caller.
+
+Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be
+ returned in AX. The status field in the parameter
+ structure must be set to one of the values represented
+ by the PXENV_STATUS_xxx constants.
+
+Description: Check a previously opened file's readiness for I/O.
+
+
+typedef struct s_PXENV_FILE_SELECT {
+ PXENV_STATUS Status;
+ UINT16 FileHandle;
+ UINT16 Ready;
+#define RDY_READ 0x0001
+} t_PXENV_FILE_SELECT;
+
+
+Set before calling API service:
+
+FileHandle: Handle obtained when file was opened.
+
+
+Returned from API service:
+
+Ready: Indication of readiness. This can be zero, or more,
+ of the RDY_xxx constants. Multiple values are
+ arithmetically or-ed together.
+
+Status: See PXENV_STATUS_xxx constants.
+
+
+
+
+FILE READ
+
+Op-Code: PXENV_FILE_READ (00e3h)
+
+Input: Far pointer to a t_PXENV_FILE_READ parameter structure
+ that has been initialised by the caller.
+
+Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be
+ returned in AX. The status field in the parameter
+ structure must be set to one of the values represented
+ by the PXENV_STATUS_xxx constants.
+
+ This API function is non-blocking. PXENV_EXIT_SUCCESS
+ and PXENV_STATUS_SUCCESS is returned if a data block
+ has been transferred into the caller's buffer.
+ PXENV_EXIT_FAILURE and PXENV_STATUS_TFTP_OPEN is
+ returned if no data is available to transfer; any
+ other status code reflects an error.
+
+Description: Read from a previously opened file.
+
+
+typedef struct s_PXENV_FILE_READ {
+ PXENV_STATUS Status;
+ UINT16 FileHandle;
+ UINT16 BufferSize;
+ SEGOFF16 Buffer;
+} t_PXENV_FILE_READ;
+
+
+Set before calling API service:
+
+FileHandle: Handle obtained when file was opened.
+
+BufferSize: Maximum number of data bytes that can be copied into
+ Buffer.
+
+Buffer: Segment:Offset address of data buffer.
+
+
+Returned from API service:
+
+BufferSize: Number of bytes written to the data buffer. End of
+ file if this is zero.
+
+Status: See PXENV_STATUS_xxx constants.
+
+
+
+
+GET FILE SIZE
+
+Op-Code: PXENV_GET_FILE_SIZE (00e4h)
+
+Input: Far pointer to a t_PXENV_GET_FILE_SIZE parameter
+ structure that has been initialised by the caller.
+
+Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be
+ returned in AX. The status field in the parameter
+ structure must be set to one of the values represented
+ by the PXENV_STATUS_xxx constants.
+
+Description: Determine size of a previously opened file.
+
+
+typedef struct s_PXENV_GET_FILE_SIZE {
+ PXENV_STATUS Status;
+ UINT16 FileHandle;
+ UINT32 FileSize;
+} t_PXENV_GET_FILE_SIZE;
+
+
+Set before calling API service:
+
+FileHandle: Handle obtained when file was opened.
+
+
+Returned from API service:
+
+FileSize: Size of the file in bytes.
+
+Status: See PXENV_STATUS_xxx constants.
+
+
+
+
+FILE EXEC
+
+Op-Code: PXENV_FILE_EXEC (00e5h)
+
+Input: Far pointer to a t_PXENV_FILE_EXEC parameter
+ structure that has been initialized by the caller.
+
+Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be
+ returned in AX. The Status field in the parameter
+ structure must be set to one of the values represented
+ by the PXENV_STATUS_xxx constants.
+
+Description: Execute a iPXE command.
+
+typedef struct s_PXENV_FILE_EXEC {
+ PXENV_STATUS_t Status;
+ SEGOFF16_t Command;
+} t_PXENV_FILE_EXEC;
+
+
+Set before calling API service:
+
+Command: Command to execute. Null terminated.
+
+
+Returned from API service:
+
+Status: See PXENV_STATUS_xxx constants.
+
+
+
+
+FILE API CHECK
+
+Op-Code: PXENV_FILE_API_CHECK (00e6h)
+
+Input: Far pointer to a t_PXENV_FILE_CHECK_API parameter
+ structure that has been initialized by the caller.
+
+ On entry, the Magic field should contain the number
+ 0x91d447b2 or the call will fail.
+
+Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be
+ returned in AX. The Status field in the parameter
+ structure must be set to one of the values represented
+ by the PXENV_STATUS_xxx constants.
+
+ If this API is present and the Magic field contains the
+ proper value on entry, AX will contain PXENV_EXIT_SUCCESS,
+ the Status field PXENV_STATUS_SUCCESS, and the Magic field
+ the number 0xe9c17b20. Any other combination should be
+ considered a failure.
+
+Description: Detect presence of this API.
+
+
+typedef struct s_PXENV_FILE_CHECK_API {
+ PXENV_STATUS Status;
+ UINT16 Size;
+ UINT32 Magic;
+ UINT32 Provider;
+ UINT32 APIMask;
+ UINT32 Flags;
+} t_PXENV_FILE_CHECK_API;
+
+Set before calling API service:
+
+Size: Set to sizeof(t_PXENV_FILE_CHECK_API) (20).
+Magic: Set to 0x91d447b2.
+
+
+Returned from API service:
+
+Size: Set to the number of bytes filled in (20).
+Magic: Set to 0xe9c17b20.
+Provider: Set to 0x45585067 ("iPXE"). Another implementation of this
+ API can use another value, e.g. to indicate a different
+ command set supported by FILE EXEC.
+APIMask: Bitmask of supported API functions (one bit for each function
+ in the range 00e0h to 00ffh).
+Flags: Set to zero, reserved for future use.
+
+
+
+
+FILE EXIT HOOK
+
+Op-Code: PXENV_FILE_EXIT_HOOK (00e7h)
+
+Input: Far pointer to a t_PXENV_FILE_EXIT_HOOK parameter
+ structure that has been initialized by the caller.
+
+Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be
+ returned in AX. The Status field in the parameter
+ structure must be set to one of the values represented
+ by the PXENV_STATUS_xxx constants.
+
+Description: Modify the exit path to jump to the specified code.
+ Only valid for pxeprefix-based builds.
+
+typedef struct s_PXENV_FILE_EXIT_HOOK {
+ PXENV_STATUS_t Status;
+ SEGOFF16_t Hook;
+} t_PXENV_FILE_EXIT_HOOK;
+
+
+Set before calling API service:
+
+Hook: The SEG16:OFF16 of the code to jump to.
+
+
+Returned from API service:
+
+Status: See PXENV_STATUS_xxx constants.
diff --git a/src/VBox/Devices/PC/ipxe/src/doxygen.cfg b/src/VBox/Devices/PC/ipxe/src/doxygen.cfg
new file mode 100644
index 00000000..4fc9f1ec
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/doxygen.cfg
@@ -0,0 +1,1486 @@
+# Doxyfile 1.5.7.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = iPXE
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = @BIN@/doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene,
+# Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES = v=@param \
+ ret=@retval \
+ err=@exception
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = YES
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page. This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT =
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = @SRCDIRS@ \
+ @INCDIRS@ \
+ config \
+ doc
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.c \
+ *.h \
+ *.dox
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT =
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION =
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = YES
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#namespace">Qt Help Project / Namespace</a>.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#virtual-folders">Qt Help Project / Virtual Folders</a>.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file .
+
+QHG_LOCATION =
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature. Other possible values
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW = NONE
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT =
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = YES
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = YES
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT =
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT =
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION =
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH = @INCDIRS@
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = DOXYGEN=1
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED = __attribute__ \
+ __unused \
+ __used \
+ __aligned \
+ __table \
+ __table_start \
+ __table_end
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = NO
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bitbash/bitbash.c b/src/VBox/Devices/PC/ipxe/src/drivers/bitbash/bitbash.c
new file mode 100644
index 00000000..ac914075
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bitbash/bitbash.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/bitbash.h>
+
+/** @file
+ *
+ * Bit-bashing interfaces
+ *
+ */
+
+/**
+ * Set/clear output bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @v data Value to write
+ *
+ * If @c data is 0, a logic 0 will be written. If @c data is
+ * non-zero, a logic 1 will be written.
+ */
+void write_bit ( struct bit_basher *basher, unsigned int bit_id,
+ unsigned long data ) {
+ basher->op->write ( basher, bit_id, ( data ? -1UL : 0 ) );
+}
+
+/**
+ * Read input bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @ret data Value read
+ *
+ * @c data will always be either 0 or -1UL. The idea is that the
+ * caller can simply binary-AND the returned value with whatever mask
+ * it needs to apply.
+ */
+int read_bit ( struct bit_basher *basher, unsigned int bit_id ) {
+ return ( basher->op->read ( basher, bit_id ) ? -1UL : 0 );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bitbash/i2c_bit.c b/src/VBox/Devices/PC/ipxe/src/drivers/bitbash/i2c_bit.c
new file mode 100644
index 00000000..ccf82db8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bitbash/i2c_bit.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdint.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <ipxe/bitbash.h>
+#include <ipxe/i2c.h>
+
+/** @file
+ *
+ * I2C bit-bashing interface
+ *
+ * This implements a simple I2C master via a bit-bashing interface
+ * that provides two lines: SCL (clock) and SDA (data).
+ */
+
+/**
+ * Delay between output state changes
+ *
+ * Max rated i2c speed (for the basic i2c protocol) is 100kbps,
+ * i.e. 200k clock transitions per second.
+ */
+static void i2c_delay ( void ) {
+ udelay ( I2C_UDELAY );
+}
+
+/**
+ * Set state of I2C SCL line
+ *
+ * @v basher Bit-bashing interface
+ * @v state New state of SCL
+ */
+static void setscl ( struct bit_basher *basher, int state ) {
+ DBG2 ( "%c", ( state ? '/' : '\\' ) );
+ write_bit ( basher, I2C_BIT_SCL, state );
+ i2c_delay();
+}
+
+/**
+ * Set state of I2C SDA line
+ *
+ * @v basher Bit-bashing interface
+ * @v state New state of SDA
+ */
+static void setsda ( struct bit_basher *basher, int state ) {
+ DBG2 ( "%c", ( state ? '1' : '0' ) );
+ write_bit ( basher, I2C_BIT_SDA, state );
+ i2c_delay();
+}
+
+/**
+ * Get state of I2C SDA line
+ *
+ * @v basher Bit-bashing interface
+ * @ret state State of SDA
+ */
+static int getsda ( struct bit_basher *basher ) {
+ int state;
+ state = read_bit ( basher, I2C_BIT_SDA );
+ DBG2 ( "%c", ( state ? '+' : '-' ) );
+ return state;
+}
+
+/**
+ * Send an I2C start condition
+ *
+ * @v basher Bit-bashing interface
+ */
+static void i2c_start ( struct bit_basher *basher ) {
+ setscl ( basher, 1 );
+ setsda ( basher, 0 );
+ setscl ( basher, 0 );
+ setsda ( basher, 1 );
+}
+
+/**
+ * Send an I2C data bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit Bit to send
+ */
+static void i2c_send_bit ( struct bit_basher *basher, int bit ) {
+ setsda ( basher, bit );
+ setscl ( basher, 1 );
+ setscl ( basher, 0 );
+ setsda ( basher, 1 );
+}
+
+/**
+ * Receive an I2C data bit
+ *
+ * @v basher Bit-bashing interface
+ * @ret bit Received bit
+ */
+static int i2c_recv_bit ( struct bit_basher *basher ) {
+ int bit;
+
+ setscl ( basher, 1 );
+ bit = getsda ( basher );
+ setscl ( basher, 0 );
+ return bit;
+}
+
+/**
+ * Send an I2C stop condition
+ *
+ * @v basher Bit-bashing interface
+ */
+static void i2c_stop ( struct bit_basher *basher ) {
+ setsda ( basher, 0 );
+ setscl ( basher, 1 );
+ setsda ( basher, 1 );
+}
+
+/**
+ * Send byte via I2C bus and check for acknowledgement
+ *
+ * @v basher Bit-bashing interface
+ * @v byte Byte to send
+ * @ret rc Return status code
+ *
+ * Sends a byte via the I2C bus and checks for an acknowledgement from
+ * the slave device.
+ */
+static int i2c_send_byte ( struct bit_basher *basher, uint8_t byte ) {
+ int i;
+ int ack;
+
+ /* Send byte */
+ DBG2 ( "[send %02x]", byte );
+ for ( i = 8 ; i ; i-- ) {
+ i2c_send_bit ( basher, byte & 0x80 );
+ byte <<= 1;
+ }
+
+ /* Check for acknowledgement from slave */
+ ack = ( i2c_recv_bit ( basher ) == 0 );
+ DBG2 ( "%s", ( ack ? "[acked]" : "[not acked]" ) );
+
+ return ( ack ? 0 : -EIO );
+}
+
+/**
+ * Receive byte via I2C bus
+ *
+ * @v basher Bit-bashing interface
+ * @ret byte Received byte
+ *
+ * Receives a byte via the I2C bus and sends NACK to the slave device.
+ */
+static uint8_t i2c_recv_byte ( struct bit_basher *basher ) {
+ uint8_t byte = 0;
+ int i;
+
+ /* Receive byte */
+ for ( i = 8 ; i ; i-- ) {
+ byte <<= 1;
+ byte |= ( i2c_recv_bit ( basher ) & 0x1 );
+ }
+
+ /* Send NACK */
+ i2c_send_bit ( basher, 1 );
+
+ DBG2 ( "[rcvd %02x]", byte );
+ return byte;
+}
+
+/**
+ * Select I2C device for reading or writing
+ *
+ * @v basher Bit-bashing interface
+ * @v i2cdev I2C device
+ * @v offset Starting offset within the device
+ * @v direction I2C_READ or I2C_WRITE
+ * @ret rc Return status code
+ */
+static int i2c_select ( struct bit_basher *basher, struct i2c_device *i2cdev,
+ unsigned int offset, unsigned int direction ) {
+ unsigned int address;
+ int shift;
+ unsigned int byte;
+ int rc;
+
+ i2c_start ( basher );
+
+ /* Calculate address to appear on bus */
+ address = ( ( ( i2cdev->dev_addr |
+ ( offset >> ( 8 * i2cdev->word_addr_len ) ) ) << 1 )
+ | direction );
+
+ /* Send address a byte at a time */
+ for ( shift = ( 8 * ( i2cdev->dev_addr_len - 1 ) ) ;
+ shift >= 0 ; shift -= 8 ) {
+ byte = ( ( address >> shift ) & 0xff );
+ if ( ( rc = i2c_send_byte ( basher, byte ) ) != 0 )
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Reset I2C bus
+ *
+ * @v basher Bit-bashing interface
+ * @ret rc Return status code
+ *
+ * i2c devices often don't have a reset line, so even a reboot or
+ * system power cycle is sometimes not enough to bring them back to a
+ * known state.
+ */
+static int i2c_reset ( struct bit_basher *basher ) {
+ unsigned int i;
+ int sda;
+
+ /* Clock through several cycles, waiting for an opportunity to
+ * pull SDA low while SCL is high (which creates a start
+ * condition).
+ */
+ setscl ( basher, 0 );
+ setsda ( basher, 1 );
+ for ( i = 0 ; i < I2C_RESET_MAX_CYCLES ; i++ ) {
+ setscl ( basher, 1 );
+ sda = getsda ( basher );
+ if ( sda ) {
+ /* Now that the device will see a start, issue it */
+ i2c_start ( basher );
+ /* Stop the bus to leave it in a known good state */
+ i2c_stop ( basher );
+ DBGC ( basher, "I2CBIT %p reset after %d attempts\n",
+ basher, ( i + 1 ) );
+ return 0;
+ }
+ setscl ( basher, 0 );
+ }
+
+ DBGC ( basher, "I2CBIT %p could not reset after %d attempts\n",
+ basher, i );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Read data from I2C device via bit-bashing interface
+ *
+ * @v i2c I2C interface
+ * @v i2cdev I2C device
+ * @v offset Starting offset within the device
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ *
+ * Note that attempting to read zero bytes of data is a valid way to
+ * check for I2C device presence.
+ */
+static int i2c_bit_read ( struct i2c_interface *i2c,
+ struct i2c_device *i2cdev, unsigned int offset,
+ uint8_t *data, unsigned int len ) {
+ struct i2c_bit_basher *i2cbit
+ = container_of ( i2c, struct i2c_bit_basher, i2c );
+ struct bit_basher *basher = &i2cbit->basher;
+ int rc = 0;
+
+ DBGC ( basher, "I2CBIT %p reading from device %x: ",
+ basher, i2cdev->dev_addr );
+
+ for ( ; ; data++, offset++ ) {
+
+ /* Select device for writing */
+ if ( ( rc = i2c_select ( basher, i2cdev, offset,
+ I2C_WRITE ) ) != 0 )
+ break;
+
+ /* Abort at end of data */
+ if ( ! ( len-- ) )
+ break;
+
+ /* Select offset */
+ if ( ( rc = i2c_send_byte ( basher, offset ) ) != 0 )
+ break;
+
+ /* Select device for reading */
+ if ( ( rc = i2c_select ( basher, i2cdev, offset,
+ I2C_READ ) ) != 0 )
+ break;
+
+ /* Read byte */
+ *data = i2c_recv_byte ( basher );
+ DBGC ( basher, "%02x ", *data );
+ }
+
+ DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) );
+ i2c_stop ( basher );
+ return rc;
+}
+
+/**
+ * Write data to I2C device via bit-bashing interface
+ *
+ * @v i2c I2C interface
+ * @v i2cdev I2C device
+ * @v offset Starting offset within the device
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ *
+ * Note that attempting to write zero bytes of data is a valid way to
+ * check for I2C device presence.
+ */
+static int i2c_bit_write ( struct i2c_interface *i2c,
+ struct i2c_device *i2cdev, unsigned int offset,
+ const uint8_t *data, unsigned int len ) {
+ struct i2c_bit_basher *i2cbit
+ = container_of ( i2c, struct i2c_bit_basher, i2c );
+ struct bit_basher *basher = &i2cbit->basher;
+ int rc = 0;
+
+ DBGC ( basher, "I2CBIT %p writing to device %x: ",
+ basher, i2cdev->dev_addr );
+
+ for ( ; ; data++, offset++ ) {
+
+ /* Select device for writing */
+ if ( ( rc = i2c_select ( basher, i2cdev, offset,
+ I2C_WRITE ) ) != 0 )
+ break;
+
+ /* Abort at end of data */
+ if ( ! ( len-- ) )
+ break;
+
+ /* Select offset */
+ if ( ( rc = i2c_send_byte ( basher, offset ) ) != 0 )
+ break;
+
+ /* Write data to device */
+ DBGC ( basher, "%02x ", *data );
+ if ( ( rc = i2c_send_byte ( basher, *data ) ) != 0 )
+ break;
+ }
+
+ DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) );
+ i2c_stop ( basher );
+ return rc;
+}
+
+/**
+ * Initialise I2C bit-bashing interface
+ *
+ * @v i2cbit I2C bit-bashing interface
+ * @v bash_op Bit-basher operations
+ */
+int init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit,
+ struct bit_basher_operations *bash_op ) {
+ struct bit_basher *basher = &i2cbit->basher;
+ int rc;
+
+ /* Initialise data structures */
+ basher->op = bash_op;
+ assert ( basher->op->read != NULL );
+ assert ( basher->op->write != NULL );
+ i2cbit->i2c.read = i2c_bit_read;
+ i2cbit->i2c.write = i2c_bit_write;
+
+ /* Reset I2C bus */
+ if ( ( rc = i2c_reset ( basher ) ) != 0 ) {
+ DBGC ( basher, "I2CBIT %p could not reset I2C bus: %s\n",
+ basher, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bitbash/spi_bit.c b/src/VBox/Devices/PC/ipxe/src/drivers/bitbash/spi_bit.c
new file mode 100644
index 00000000..b64ffb82
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bitbash/spi_bit.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <unistd.h>
+#include <ipxe/bitbash.h>
+#include <ipxe/spi_bit.h>
+
+/** @file
+ *
+ * SPI bit-bashing interface
+ *
+ */
+
+/** Delay between SCLK changes and around SS changes */
+static void spi_bit_delay ( void ) {
+ udelay ( SPI_BIT_UDELAY );
+}
+
+/** Chip select line will be asserted */
+#define SELECT_SLAVE 0
+
+/** Chip select line will be deasserted */
+#define DESELECT_SLAVE SPI_MODE_SSPOL
+
+/**
+ * Select/deselect slave
+ *
+ * @v spibit SPI bit-bashing interface
+ * @v slave Slave number
+ * @v state Slave select state
+ *
+ * @c state must be @c SELECT_SLAVE or @c DESELECT_SLAVE.
+ */
+static void spi_bit_set_slave_select ( struct spi_bit_basher *spibit,
+ unsigned int slave,
+ unsigned int state ) {
+ struct bit_basher *basher = &spibit->basher;
+
+ state ^= ( spibit->bus.mode & SPI_MODE_SSPOL );
+ DBGC2 ( spibit, "SPIBIT %p setting slave %d select %s\n",
+ spibit, slave, ( state ? "high" : "low" ) );
+
+ spi_bit_delay();
+ write_bit ( basher, SPI_BIT_SS ( slave ), state );
+ spi_bit_delay();
+}
+
+/**
+ * Transfer bits over SPI bit-bashing bus
+ *
+ * @v bus SPI bus
+ * @v data_out TX data buffer (or NULL)
+ * @v data_in RX data buffer (or NULL)
+ * @v len Length of transfer (in @b bits)
+ * @v endianness Endianness of this data transfer
+ *
+ * This issues @c len clock cycles on the SPI bus, shifting out data
+ * from the @c data_out buffer to the MOSI line and shifting in data
+ * from the MISO line to the @c data_in buffer. If @c data_out is
+ * NULL, then the data sent will be all zeroes. If @c data_in is
+ * NULL, then the incoming data will be discarded.
+ */
+static void spi_bit_transfer ( struct spi_bit_basher *spibit,
+ const void *data_out, void *data_in,
+ unsigned int len, int endianness ) {
+ struct spi_bus *bus = &spibit->bus;
+ struct bit_basher *basher = &spibit->basher;
+ unsigned int sclk = ( ( bus->mode & SPI_MODE_CPOL ) ? 1 : 0 );
+ unsigned int cpha = ( ( bus->mode & SPI_MODE_CPHA ) ? 1 : 0 );
+ unsigned int bit_offset;
+ unsigned int byte_offset;
+ unsigned int byte_mask;
+ unsigned int bit;
+ unsigned int step;
+
+ DBGC2 ( spibit, "SPIBIT %p transferring %d bits in mode %#x\n",
+ spibit, len, bus->mode );
+
+ for ( step = 0 ; step < ( len * 2 ) ; step++ ) {
+ /* Calculate byte offset and byte mask */
+ bit_offset = ( ( endianness == SPI_BIT_BIG_ENDIAN ) ?
+ ( len - ( step / 2 ) - 1 ) : ( step / 2 ) );
+ byte_offset = ( bit_offset / 8 );
+ byte_mask = ( 1 << ( bit_offset % 8 ) );
+
+ /* Shift data in or out */
+ if ( sclk == cpha ) {
+ const uint8_t *byte;
+
+ /* Shift data out */
+ if ( data_out ) {
+ byte = ( data_out + byte_offset );
+ bit = ( *byte & byte_mask );
+ DBGCP ( spibit, "SPIBIT %p wrote bit %d\n",
+ spibit, ( bit ? 1 : 0 ) );
+ } else {
+ bit = 0;
+ }
+ write_bit ( basher, SPI_BIT_MOSI, bit );
+ } else {
+ uint8_t *byte;
+
+ /* Shift data in */
+ bit = read_bit ( basher, SPI_BIT_MISO );
+ if ( data_in ) {
+ DBGCP ( spibit, "SPIBIT %p read bit %d\n",
+ spibit, ( bit ? 1 : 0 ) );
+ byte = ( data_in + byte_offset );
+ *byte &= ~byte_mask;
+ *byte |= ( bit & byte_mask );
+ }
+ }
+
+ /* Toggle clock line */
+ spi_bit_delay();
+ sclk ^= 1;
+ write_bit ( basher, SPI_BIT_SCLK, sclk );
+ }
+}
+
+/**
+ * Read/write data via SPI bit-bashing bus
+ *
+ * @v bus SPI bus
+ * @v device SPI device
+ * @v command Command
+ * @v address Address to read/write (<0 for no address)
+ * @v data_out TX data buffer (or NULL)
+ * @v data_in RX data buffer (or NULL)
+ * @v len Length of transfer
+ * @ret rc Return status code
+ */
+static int spi_bit_rw ( struct spi_bus *bus, struct spi_device *device,
+ unsigned int command, int address,
+ const void *data_out, void *data_in, size_t len ) {
+ struct spi_bit_basher *spibit
+ = container_of ( bus, struct spi_bit_basher, bus );
+ uint32_t tmp_command;
+ uint32_t tmp_address;
+ uint32_t tmp_address_detect;
+
+ /* Deassert chip select to reset specified slave */
+ spi_bit_set_slave_select ( spibit, device->slave, DESELECT_SLAVE );
+
+ /* Set clock line to idle state */
+ write_bit ( &spibit->basher, SPI_BIT_SCLK,
+ ( bus->mode & SPI_MODE_CPOL ) );
+
+ /* Assert chip select on specified slave */
+ spi_bit_set_slave_select ( spibit, device->slave, SELECT_SLAVE );
+
+ /* Transmit command */
+ assert ( device->command_len <= ( 8 * sizeof ( tmp_command ) ) );
+ tmp_command = cpu_to_le32 ( command );
+ spi_bit_transfer ( spibit, &tmp_command, NULL, device->command_len,
+ SPI_BIT_BIG_ENDIAN );
+
+ /* Transmit address, if present */
+ if ( address >= 0 ) {
+ assert ( device->address_len <= ( 8 * sizeof ( tmp_address )));
+ tmp_address = cpu_to_le32 ( address );
+ if ( device->address_len == SPI_AUTODETECT_ADDRESS_LEN ) {
+ /* Autodetect address length. This relies on
+ * the device responding with a dummy zero
+ * data bit before the first real data bit.
+ */
+ DBGC ( spibit, "SPIBIT %p autodetecting device "
+ "address length\n", spibit );
+ assert ( address == 0 );
+ device->address_len = 0;
+ do {
+ spi_bit_transfer ( spibit, &tmp_address,
+ &tmp_address_detect, 1,
+ SPI_BIT_BIG_ENDIAN );
+ device->address_len++;
+ } while ( le32_to_cpu ( tmp_address_detect ) & 1 );
+ DBGC ( spibit, "SPIBIT %p autodetected device address "
+ "length %d\n", spibit, device->address_len );
+ } else {
+ spi_bit_transfer ( spibit, &tmp_address, NULL,
+ device->address_len,
+ SPI_BIT_BIG_ENDIAN );
+ }
+ }
+
+ /* Transmit/receive data */
+ spi_bit_transfer ( spibit, data_out, data_in, ( len * 8 ),
+ spibit->endianness );
+
+ /* Deassert chip select on specified slave */
+ spi_bit_set_slave_select ( spibit, device->slave, DESELECT_SLAVE );
+
+ return 0;
+}
+
+/**
+ * Initialise SPI bit-bashing interface
+ *
+ * @v spibit SPI bit-bashing interface
+ */
+void init_spi_bit_basher ( struct spi_bit_basher *spibit ) {
+ assert ( &spibit->basher.op->read != NULL );
+ assert ( &spibit->basher.op->write != NULL );
+ spibit->bus.rw = spi_bit_rw;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/block/ata.c b/src/VBox/Devices/PC/ipxe/src/drivers/block/ata.c
new file mode 100644
index 00000000..56740012
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/block/ata.c
@@ -0,0 +1,678 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/list.h>
+#include <ipxe/interface.h>
+#include <ipxe/blockdev.h>
+#include <ipxe/edd.h>
+#include <ipxe/ata.h>
+
+/** @file
+ *
+ * ATA block device
+ *
+ */
+
+/******************************************************************************
+ *
+ * Interface methods
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Issue ATA command
+ *
+ * @v control ATA control interface
+ * @v data ATA data interface
+ * @v command ATA command
+ * @ret tag Command tag, or negative error
+ */
+int ata_command ( struct interface *control, struct interface *data,
+ struct ata_cmd *command ) {
+ struct interface *dest;
+ ata_command_TYPE ( void * ) *op =
+ intf_get_dest_op ( control, ata_command, &dest );
+ void *object = intf_object ( dest );
+ int tag;
+
+ if ( op ) {
+ tag = op ( object, data, command );
+ } else {
+ /* Default is to fail to issue the command */
+ tag = -EOPNOTSUPP;
+ }
+
+ intf_put ( dest );
+ return tag;
+}
+
+/******************************************************************************
+ *
+ * ATA devices and commands
+ *
+ ******************************************************************************
+ */
+
+/** List of all ATA commands */
+static LIST_HEAD ( ata_commands );
+
+/** An ATA device */
+struct ata_device {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Block control interface */
+ struct interface block;
+ /** ATA control interface */
+ struct interface ata;
+
+ /** Device number
+ *
+ * Must be ATA_DEV_MASTER or ATA_DEV_SLAVE.
+ */
+ unsigned int device;
+ /** Maximum number of blocks per single transfer */
+ unsigned int max_count;
+ /** Device uses LBA48 extended addressing */
+ int lba48;
+};
+
+/** An ATA command */
+struct ata_command {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** ATA device */
+ struct ata_device *atadev;
+ /** List of ATA commands */
+ struct list_head list;
+
+ /** Block data interface */
+ struct interface block;
+ /** ATA data interface */
+ struct interface ata;
+
+ /** Command type */
+ struct ata_command_type *type;
+ /** Command tag */
+ uint32_t tag;
+
+ /** Private data */
+ uint8_t priv[0];
+};
+
+/** An ATA command type */
+struct ata_command_type {
+ /** Name */
+ const char *name;
+ /** Additional working space */
+ size_t priv_len;
+ /** Command for non-LBA48-capable devices */
+ uint8_t cmd_lba;
+ /** Command for LBA48-capable devices */
+ uint8_t cmd_lba48;
+ /**
+ * Calculate data-in buffer
+ *
+ * @v atacmd ATA command
+ * @v buffer Available buffer
+ * @v len Available buffer length
+ * @ret data_in Data-in buffer
+ * @ret data_in_len Data-in buffer length
+ */
+ void ( * data_in ) ( struct ata_command *atacmd, userptr_t buffer,
+ size_t len, userptr_t *data_in,
+ size_t *data_in_len );
+ /**
+ * Calculate data-out buffer
+ *
+ *
+ * @v atacmd ATA command
+ * @v buffer Available buffer
+ * @v len Available buffer length
+ * @ret data_out Data-out buffer
+ * @ret data_out_len Data-out buffer length
+ */
+ void ( * data_out ) ( struct ata_command *atacmd, userptr_t buffer,
+ size_t len, userptr_t *data_out,
+ size_t *data_out_len );
+ /**
+ * Handle ATA command completion
+ *
+ * @v atacmd ATA command
+ * @v rc Reason for completion
+ */
+ void ( * done ) ( struct ata_command *atacmd, int rc );
+};
+
+/**
+ * Get reference to ATA device
+ *
+ * @v atadev ATA device
+ * @ret atadev ATA device
+ */
+static inline __attribute__ (( always_inline )) struct ata_device *
+atadev_get ( struct ata_device *atadev ) {
+ ref_get ( &atadev->refcnt );
+ return atadev;
+}
+
+/**
+ * Drop reference to ATA device
+ *
+ * @v atadev ATA device
+ */
+static inline __attribute__ (( always_inline )) void
+atadev_put ( struct ata_device *atadev ) {
+ ref_put ( &atadev->refcnt );
+}
+
+/**
+ * Get reference to ATA command
+ *
+ * @v atacmd ATA command
+ * @ret atacmd ATA command
+ */
+static inline __attribute__ (( always_inline )) struct ata_command *
+atacmd_get ( struct ata_command *atacmd ) {
+ ref_get ( &atacmd->refcnt );
+ return atacmd;
+}
+
+/**
+ * Drop reference to ATA command
+ *
+ * @v atacmd ATA command
+ */
+static inline __attribute__ (( always_inline )) void
+atacmd_put ( struct ata_command *atacmd ) {
+ ref_put ( &atacmd->refcnt );
+}
+
+/**
+ * Get ATA command private data
+ *
+ * @v atacmd ATA command
+ * @ret priv Private data
+ */
+static inline __attribute__ (( always_inline )) void *
+atacmd_priv ( struct ata_command *atacmd ) {
+ return atacmd->priv;
+}
+
+/**
+ * Free ATA command
+ *
+ * @v refcnt Reference count
+ */
+static void atacmd_free ( struct refcnt *refcnt ) {
+ struct ata_command *atacmd =
+ container_of ( refcnt, struct ata_command, refcnt );
+
+ /* Remove from list of commands */
+ list_del ( &atacmd->list );
+ atadev_put ( atacmd->atadev );
+
+ /* Free command */
+ free ( atacmd );
+}
+
+/**
+ * Close ATA command
+ *
+ * @v atacmd ATA command
+ * @v rc Reason for close
+ */
+static void atacmd_close ( struct ata_command *atacmd, int rc ) {
+ struct ata_device *atadev = atacmd->atadev;
+
+ if ( rc != 0 ) {
+ DBGC ( atadev, "ATA %p tag %08x closed: %s\n",
+ atadev, atacmd->tag, strerror ( rc ) );
+ }
+
+ /* Shut down interfaces */
+ intf_shutdown ( &atacmd->ata, rc );
+ intf_shutdown ( &atacmd->block, rc );
+}
+
+/**
+ * Handle ATA command completion
+ *
+ * @v atacmd ATA command
+ * @v rc Reason for close
+ */
+static void atacmd_done ( struct ata_command *atacmd, int rc ) {
+
+ /* Hand over to the command completion handler */
+ atacmd->type->done ( atacmd, rc );
+}
+
+/**
+ * Use provided data buffer for ATA command
+ *
+ * @v atacmd ATA command
+ * @v buffer Available buffer
+ * @v len Available buffer length
+ * @ret data Data buffer
+ * @ret data_len Data buffer length
+ */
+static void atacmd_data_buffer ( struct ata_command *atacmd __unused,
+ userptr_t buffer, size_t len,
+ userptr_t *data, size_t *data_len ) {
+ *data = buffer;
+ *data_len = len;
+}
+
+/**
+ * Use no data buffer for ATA command
+ *
+ * @v atacmd ATA command
+ * @v buffer Available buffer
+ * @v len Available buffer length
+ * @ret data Data buffer
+ * @ret data_len Data buffer length
+ */
+static void atacmd_data_none ( struct ata_command *atacmd __unused,
+ userptr_t buffer __unused, size_t len __unused,
+ userptr_t *data __unused,
+ size_t *data_len __unused ) {
+ /* Nothing to do */
+}
+
+/**
+ * Use private data buffer for ATA command
+ *
+ * @v atacmd ATA command
+ * @v buffer Available buffer
+ * @v len Available buffer length
+ * @ret data Data buffer
+ * @ret data_len Data buffer length
+ */
+static void atacmd_data_priv ( struct ata_command *atacmd,
+ userptr_t buffer __unused, size_t len __unused,
+ userptr_t *data, size_t *data_len ) {
+ *data = virt_to_user ( atacmd_priv ( atacmd ) );
+ *data_len = atacmd->type->priv_len;
+}
+
+/** ATA READ command type */
+static struct ata_command_type atacmd_read = {
+ .name = "READ",
+ .cmd_lba = ATA_CMD_READ,
+ .cmd_lba48 = ATA_CMD_READ_EXT,
+ .data_in = atacmd_data_buffer,
+ .data_out = atacmd_data_none,
+ .done = atacmd_close,
+};
+
+/** ATA WRITE command type */
+static struct ata_command_type atacmd_write = {
+ .name = "WRITE",
+ .cmd_lba = ATA_CMD_WRITE,
+ .cmd_lba48 = ATA_CMD_WRITE_EXT,
+ .data_in = atacmd_data_none,
+ .data_out = atacmd_data_buffer,
+ .done = atacmd_close,
+};
+
+/** ATA IDENTIFY private data */
+struct ata_identify_private {
+ /** Identity data */
+ struct ata_identity identity;
+};
+
+/**
+ * Return ATA model string (for debugging)
+ *
+ * @v identify ATA identity data
+ * @ret model Model string
+ */
+static const char * ata_model ( struct ata_identity *identity ) {
+ static union {
+ uint16_t words[ sizeof ( identity->model ) / 2 ];
+ char text[ sizeof ( identity->model ) + 1 /* NUL */ ];
+ } buf;
+ unsigned int i;
+
+ for ( i = 0 ; i < ( sizeof ( identity->model ) / 2 ) ; i++ )
+ buf.words[i] = bswap_16 ( identity->model[i] );
+
+ return buf.text;
+}
+
+/**
+ * Handle ATA IDENTIFY command completion
+ *
+ * @v atacmd ATA command
+ * @v rc Reason for completion
+ */
+static void atacmd_identify_done ( struct ata_command *atacmd, int rc ) {
+ struct ata_device *atadev = atacmd->atadev;
+ struct ata_identify_private *priv = atacmd_priv ( atacmd );
+ struct ata_identity *identity = &priv->identity;
+ struct block_device_capacity capacity;
+
+ /* Close if command failed */
+ if ( rc != 0 ) {
+ atacmd_close ( atacmd, rc );
+ return;
+ }
+
+ /* Extract capacity */
+ if ( identity->supports_lba48 & cpu_to_le16 ( ATA_SUPPORTS_LBA48 ) ) {
+ atadev->lba48 = 1;
+ capacity.blocks = le64_to_cpu ( identity->lba48_sectors );
+ } else {
+ capacity.blocks = le32_to_cpu ( identity->lba_sectors );
+ }
+ capacity.blksize = ATA_SECTOR_SIZE;
+ capacity.max_count = atadev->max_count;
+ DBGC ( atadev, "ATA %p is a %s\n", atadev, ata_model ( identity ) );
+ DBGC ( atadev, "ATA %p has %#llx blocks (%ld MB) and uses %s\n",
+ atadev, capacity.blocks,
+ ( ( signed long ) ( capacity.blocks >> 11 ) ),
+ ( atadev->lba48 ? "LBA48" : "LBA" ) );
+
+ /* Return capacity to caller */
+ block_capacity ( &atacmd->block, &capacity );
+
+ /* Close command */
+ atacmd_close ( atacmd, 0 );
+}
+
+/** ATA IDENTITY command type */
+static struct ata_command_type atacmd_identify = {
+ .name = "IDENTIFY",
+ .priv_len = sizeof ( struct ata_identify_private ),
+ .cmd_lba = ATA_CMD_IDENTIFY,
+ .cmd_lba48 = ATA_CMD_IDENTIFY,
+ .data_in = atacmd_data_priv,
+ .data_out = atacmd_data_none,
+ .done = atacmd_identify_done,
+};
+
+/** ATA command block interface operations */
+static struct interface_operation atacmd_block_op[] = {
+ INTF_OP ( intf_close, struct ata_command *, atacmd_close ),
+};
+
+/** ATA command block interface descriptor */
+static struct interface_descriptor atacmd_block_desc =
+ INTF_DESC_PASSTHRU ( struct ata_command, block,
+ atacmd_block_op, ata );
+
+/** ATA command ATA interface operations */
+static struct interface_operation atacmd_ata_op[] = {
+ INTF_OP ( intf_close, struct ata_command *, atacmd_done ),
+};
+
+/** ATA command ATA interface descriptor */
+static struct interface_descriptor atacmd_ata_desc =
+ INTF_DESC_PASSTHRU ( struct ata_command, ata,
+ atacmd_ata_op, block );
+
+/**
+ * Create ATA command
+ *
+ * @v atadev ATA device
+ * @v block Block data interface
+ * @v type ATA command type
+ * @v lba Starting logical block address
+ * @v count Number of blocks to transfer
+ * @v buffer Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int atadev_command ( struct ata_device *atadev,
+ struct interface *block,
+ struct ata_command_type *type,
+ uint64_t lba, unsigned int count,
+ userptr_t buffer, size_t len ) {
+ struct ata_command *atacmd;
+ struct ata_cmd command;
+ int tag;
+ int rc;
+
+ /* Allocate and initialise structure */
+ atacmd = zalloc ( sizeof ( *atacmd ) + type->priv_len );
+ if ( ! atacmd ) {
+ rc = -ENOMEM;
+ goto err_zalloc;
+ }
+ ref_init ( &atacmd->refcnt, atacmd_free );
+ intf_init ( &atacmd->block, &atacmd_block_desc, &atacmd->refcnt );
+ intf_init ( &atacmd->ata, &atacmd_ata_desc,
+ &atacmd->refcnt );
+ atacmd->atadev = atadev_get ( atadev );
+ list_add ( &atacmd->list, &ata_commands );
+ atacmd->type = type;
+
+ /* Sanity check */
+ if ( len != ( count * ATA_SECTOR_SIZE ) ) {
+ DBGC ( atadev, "ATA %p tag %08x buffer length mismatch (count "
+ "%d len %zd)\n", atadev, atacmd->tag, count, len );
+ rc = -EINVAL;
+ goto err_len;
+ }
+
+ /* Construct command */
+ memset ( &command, 0, sizeof ( command ) );
+ command.cb.lba.native = lba;
+ command.cb.count.native = count;
+ command.cb.device = ( atadev->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
+ command.cb.lba48 = atadev->lba48;
+ if ( ! atadev->lba48 )
+ command.cb.device |= command.cb.lba.bytes.low_prev;
+ command.cb.cmd_stat =
+ ( atadev->lba48 ? type->cmd_lba48 : type->cmd_lba );
+ type->data_in ( atacmd, buffer, len,
+ &command.data_in, &command.data_in_len );
+ type->data_out ( atacmd, buffer, len,
+ &command.data_out, &command.data_out_len );
+
+ /* Issue command */
+ if ( ( tag = ata_command ( &atadev->ata, &atacmd->ata,
+ &command ) ) < 0 ) {
+ rc = tag;
+ DBGC ( atadev, "ATA %p tag %08x could not issue command: %s\n",
+ atadev, atacmd->tag, strerror ( rc ) );
+ goto err_command;
+ }
+ atacmd->tag = tag;
+
+ DBGC2 ( atadev, "ATA %p tag %08x %s cmd %02x dev %02x LBA%s %08llx "
+ "count %04x\n", atadev, atacmd->tag, atacmd->type->name,
+ command.cb.cmd_stat, command.cb.device,
+ ( command.cb.lba48 ? "48" : "" ),
+ ( unsigned long long ) command.cb.lba.native,
+ command.cb.count.native );
+
+ /* Attach to parent interface, mortalise self, and return */
+ intf_plug_plug ( &atacmd->block, block );
+ ref_put ( &atacmd->refcnt );
+ return 0;
+
+ err_command:
+ err_len:
+ atacmd_close ( atacmd, rc );
+ ref_put ( &atacmd->refcnt );
+ err_zalloc:
+ return rc;
+}
+
+/**
+ * Issue ATA block read
+ *
+ * @v atadev ATA device
+ * @v block Block data interface
+ * @v lba Starting logical block address
+ * @v count Number of blocks to transfer
+ * @v buffer Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+
+ */
+static int atadev_read ( struct ata_device *atadev,
+ struct interface *block,
+ uint64_t lba, unsigned int count,
+ userptr_t buffer, size_t len ) {
+ return atadev_command ( atadev, block, &atacmd_read,
+ lba, count, buffer, len );
+}
+
+/**
+ * Issue ATA block write
+ *
+ * @v atadev ATA device
+ * @v block Block data interface
+ * @v lba Starting logical block address
+ * @v count Number of blocks to transfer
+ * @v buffer Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int atadev_write ( struct ata_device *atadev,
+ struct interface *block,
+ uint64_t lba, unsigned int count,
+ userptr_t buffer, size_t len ) {
+ return atadev_command ( atadev, block, &atacmd_write,
+ lba, count, buffer, len );
+}
+
+/**
+ * Read ATA device capacity
+ *
+ * @v atadev ATA device
+ * @v block Block data interface
+ * @ret rc Return status code
+ */
+static int atadev_read_capacity ( struct ata_device *atadev,
+ struct interface *block ) {
+ struct ata_identity *identity;
+
+ assert ( atacmd_identify.priv_len == sizeof ( *identity ) );
+ assert ( atacmd_identify.priv_len == ATA_SECTOR_SIZE );
+ return atadev_command ( atadev, block, &atacmd_identify,
+ 0, 1, UNULL, ATA_SECTOR_SIZE );
+}
+
+/**
+ * Close ATA device
+ *
+ * @v atadev ATA device
+ * @v rc Reason for close
+ */
+static void atadev_close ( struct ata_device *atadev, int rc ) {
+ struct ata_command *atacmd;
+ struct ata_command *tmp;
+
+ /* Shut down interfaces */
+ intf_shutdown ( &atadev->block, rc );
+ intf_shutdown ( &atadev->ata, rc );
+
+ /* Shut down any remaining commands */
+ list_for_each_entry_safe ( atacmd, tmp, &ata_commands, list ) {
+ if ( atacmd->atadev != atadev )
+ continue;
+ atacmd_get ( atacmd );
+ atacmd_close ( atacmd, rc );
+ atacmd_put ( atacmd );
+ }
+}
+
+/**
+ * Describe ATA device using EDD
+ *
+ * @v atadev ATA device
+ * @v type EDD interface type
+ * @v path EDD device path
+ * @ret rc Return status code
+ */
+static int atadev_edd_describe ( struct ata_device *atadev,
+ struct edd_interface_type *type,
+ union edd_device_path *path ) {
+
+ type->type = cpu_to_le64 ( EDD_INTF_TYPE_ATA );
+ path->ata.slave = ( ( atadev->device == ATA_DEV_SLAVE ) ? 0x01 : 0x00 );
+ return 0;
+}
+
+/** ATA device block interface operations */
+static struct interface_operation atadev_block_op[] = {
+ INTF_OP ( block_read, struct ata_device *, atadev_read ),
+ INTF_OP ( block_write, struct ata_device *, atadev_write ),
+ INTF_OP ( block_read_capacity, struct ata_device *,
+ atadev_read_capacity ),
+ INTF_OP ( intf_close, struct ata_device *, atadev_close ),
+ INTF_OP ( edd_describe, struct ata_device *, atadev_edd_describe ),
+};
+
+/** ATA device block interface descriptor */
+static struct interface_descriptor atadev_block_desc =
+ INTF_DESC_PASSTHRU ( struct ata_device, block,
+ atadev_block_op, ata );
+
+/** ATA device ATA interface operations */
+static struct interface_operation atadev_ata_op[] = {
+ INTF_OP ( intf_close, struct ata_device *, atadev_close ),
+};
+
+/** ATA device ATA interface descriptor */
+static struct interface_descriptor atadev_ata_desc =
+ INTF_DESC_PASSTHRU ( struct ata_device, ata,
+ atadev_ata_op, block );
+
+/**
+ * Open ATA device
+ *
+ * @v block Block control interface
+ * @v ata ATA control interface
+ * @v device ATA device number
+ * @v max_count Maximum number of blocks per single transfer
+ * @ret rc Return status code
+ */
+int ata_open ( struct interface *block, struct interface *ata,
+ unsigned int device, unsigned int max_count ) {
+ struct ata_device *atadev;
+
+ /* Allocate and initialise structure */
+ atadev = zalloc ( sizeof ( *atadev ) );
+ if ( ! atadev )
+ return -ENOMEM;
+ ref_init ( &atadev->refcnt, NULL );
+ intf_init ( &atadev->block, &atadev_block_desc, &atadev->refcnt );
+ intf_init ( &atadev->ata, &atadev_ata_desc, &atadev->refcnt );
+ atadev->device = device;
+ atadev->max_count = max_count;
+
+ /* Attach to ATA and parent and interfaces, mortalise self,
+ * and return
+ */
+ intf_plug_plug ( &atadev->ata, ata );
+ intf_plug_plug ( &atadev->block, block );
+ ref_put ( &atadev->refcnt );
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/block/ibft.c b/src/VBox/Devices/PC/ipxe/src/drivers/block/ibft.c
new file mode 100644
index 00000000..f1609637
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/block/ibft.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright Fen Systems Ltd. 2007. Portions of this code are derived
+ * from IBM Corporation Sample Programs. Copyright IBM Corporation
+ * 2004, 2007. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include <ipxe/acpi.h>
+#include <ipxe/in.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/iscsi.h>
+#include <ipxe/ibft.h>
+
+/** @file
+ *
+ * iSCSI boot firmware table
+ *
+ * The information in this file is derived from the document "iSCSI
+ * Boot Firmware Table (iBFT)" as published by IBM at
+ *
+ * ftp://ftp.software.ibm.com/systems/support/system_x_pdf/ibm_iscsi_boot_firmware_table_v1.02.pdf
+ *
+ */
+
+/**
+ * An iBFT created by iPXE
+ *
+ */
+struct ipxe_ibft {
+ /** The fixed section */
+ struct ibft_table table;
+ /** The Initiator section */
+ struct ibft_initiator initiator __attribute__ (( aligned ( 16 ) ));
+ /** The NIC section */
+ struct ibft_nic nic __attribute__ (( aligned ( 16 ) ));
+ /** The Target section */
+ struct ibft_target target __attribute__ (( aligned ( 16 ) ));
+ /** Strings block */
+ char strings[0];
+} __attribute__ (( packed, aligned ( 16 ) ));
+
+/**
+ * iSCSI string block descriptor
+ *
+ * This is an internal structure that we use to keep track of the
+ * allocation of string data.
+ */
+struct ibft_strings {
+ /** The iBFT containing these strings */
+ struct ibft_table *table;
+ /** Offset of first free byte within iBFT */
+ size_t offset;
+ /** Total length of the iBFT */
+ size_t len;
+};
+
+/**
+ * Fill in an IP address field within iBFT
+ *
+ * @v ipaddr IP address field
+ * @v in IPv4 address
+ */
+static void ibft_set_ipaddr ( struct ibft_ipaddr *ipaddr, struct in_addr in ) {
+ memset ( ipaddr, 0, sizeof ( *ipaddr ) );
+ if ( in.s_addr ) {
+ ipaddr->in = in;
+ ipaddr->ones = 0xffff;
+ }
+}
+
+/**
+ * Fill in an IP address within iBFT from configuration setting
+ *
+ * @v ipaddr IP address field
+ * @v setting Configuration setting
+ * @v count Maximum number of IP addresses
+ */
+static void ibft_set_ipaddr_setting ( struct ibft_ipaddr *ipaddr,
+ struct setting *setting,
+ unsigned int count ) {
+ struct in_addr in[count];
+ unsigned int i;
+
+ fetch_ipv4_array_setting ( NULL, setting, in, count );
+ for ( i = 0 ; i < count ; i++ ) {
+ ibft_set_ipaddr ( &ipaddr[i], in[i] );
+ }
+}
+
+/**
+ * Read IP address from iBFT (for debugging)
+ *
+ * @v strings iBFT string block descriptor
+ * @v string String field
+ * @ret ipaddr IP address string
+ */
+static const char * ibft_ipaddr ( struct ibft_ipaddr *ipaddr ) {
+ return inet_ntoa ( ipaddr->in );
+}
+
+/**
+ * Allocate a string within iBFT
+ *
+ * @v strings iBFT string block descriptor
+ * @v string String field to fill in
+ * @v len Length of string to allocate (excluding NUL)
+ * @ret dest String destination, or NULL
+ */
+static char * ibft_alloc_string ( struct ibft_strings *strings,
+ struct ibft_string *string, size_t len ) {
+
+ if ( ( strings->offset + len ) >= strings->len )
+ return NULL;
+
+ string->offset = cpu_to_le16 ( strings->offset );
+ string->len = cpu_to_le16 ( len );
+ strings->offset += ( len + 1 );
+
+ return ( ( ( char * ) strings->table ) + string->offset );
+}
+
+/**
+ * Fill in a string field within iBFT
+ *
+ * @v strings iBFT string block descriptor
+ * @v string String field
+ * @v data String to fill in, or NULL
+ * @ret rc Return status code
+ */
+static int ibft_set_string ( struct ibft_strings *strings,
+ struct ibft_string *string, const char *data ) {
+ char *dest;
+
+ if ( ! data )
+ return 0;
+
+ dest = ibft_alloc_string ( strings, string, strlen ( data ) );
+ if ( ! dest )
+ return -ENOBUFS;
+ strcpy ( dest, data );
+
+ return 0;
+}
+
+/**
+ * Fill in a string field within iBFT from configuration setting
+ *
+ * @v strings iBFT string block descriptor
+ * @v string String field
+ * @v setting Configuration setting
+ * @ret rc Return status code
+ */
+static int ibft_set_string_setting ( struct ibft_strings *strings,
+ struct ibft_string *string,
+ struct setting *setting ) {
+ int len;
+ char *dest;
+
+ len = fetch_setting_len ( NULL, setting );
+ if ( len < 0 ) {
+ string->offset = 0;
+ string->len = 0;
+ return 0;
+ }
+
+ dest = ibft_alloc_string ( strings, string, len );
+ if ( ! dest )
+ return -ENOBUFS;
+ fetch_string_setting ( NULL, setting, dest, ( len + 1 ) );
+
+ return 0;
+}
+
+/**
+ * Read string from iBFT (for debugging)
+ *
+ * @v strings iBFT string block descriptor
+ * @v string String field
+ * @ret data String content (or "<empty>")
+ */
+static const char * ibft_string ( struct ibft_strings *strings,
+ struct ibft_string *string ) {
+ return ( string->offset ?
+ ( ( ( char * ) strings->table ) + string->offset ) : NULL );
+}
+
+/**
+ * Fill in NIC portion of iBFT
+ *
+ * @v nic NIC portion of iBFT
+ * @v strings iBFT string block descriptor
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int ibft_fill_nic ( struct ibft_nic *nic,
+ struct ibft_strings *strings,
+ struct net_device *netdev ) {
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+ struct in_addr netmask_addr = { 0 };
+ unsigned int netmask_count = 0;
+ int rc;
+
+ /* Fill in common header */
+ nic->header.structure_id = IBFT_STRUCTURE_ID_NIC;
+ nic->header.version = 1;
+ nic->header.length = cpu_to_le16 ( sizeof ( *nic ) );
+ nic->header.flags = ( IBFT_FL_NIC_BLOCK_VALID |
+ IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED );
+
+ /* Extract values from configuration settings */
+ ibft_set_ipaddr_setting ( &nic->ip_address, &ip_setting, 1 );
+ DBG ( "iBFT NIC IP = %s\n", ibft_ipaddr ( &nic->ip_address ) );
+ ibft_set_ipaddr_setting ( &nic->gateway, &gateway_setting, 1 );
+ DBG ( "iBFT NIC gateway = %s\n", ibft_ipaddr ( &nic->gateway ) );
+ ibft_set_ipaddr_setting ( &nic->dns[0], &dns_setting,
+ ( sizeof ( nic->dns ) /
+ sizeof ( nic->dns[0] ) ) );
+ DBG ( "iBFT NIC DNS = %s", ibft_ipaddr ( &nic->dns[0] ) );
+ DBG ( ", %s\n", ibft_ipaddr ( &nic->dns[1] ) );
+ if ( ( rc = ibft_set_string_setting ( strings, &nic->hostname,
+ &hostname_setting ) ) != 0 )
+ return rc;
+ DBG ( "iBFT NIC hostname = %s\n",
+ ibft_string ( strings, &nic->hostname ) );
+
+ /* Derive subnet mask prefix from subnet mask */
+ fetch_ipv4_setting ( NULL, &netmask_setting, &netmask_addr );
+ while ( netmask_addr.s_addr ) {
+ if ( netmask_addr.s_addr & 0x1 )
+ netmask_count++;
+ netmask_addr.s_addr >>= 1;
+ }
+ nic->subnet_mask_prefix = netmask_count;
+ DBG ( "iBFT NIC subnet = /%d\n", nic->subnet_mask_prefix );
+
+ /* Extract values from net-device configuration */
+ if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr,
+ nic->mac_address ) ) != 0 ) {
+ DBG ( "Could not determine iBFT MAC: %s\n", strerror ( rc ) );
+ return rc;
+ }
+ DBG ( "iBFT NIC MAC = %s\n", eth_ntoa ( nic->mac_address ) );
+ nic->pci_bus_dev_func = cpu_to_le16 ( netdev->dev->desc.location );
+ DBG ( "iBFT NIC PCI = %04x\n", le16_to_cpu ( nic->pci_bus_dev_func ) );
+
+ return 0;
+}
+
+/**
+ * Fill in Initiator portion of iBFT
+ *
+ * @v initiator Initiator portion of iBFT
+ * @v strings iBFT string block descriptor
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int ibft_fill_initiator ( struct ibft_initiator *initiator,
+ struct ibft_strings *strings,
+ struct iscsi_session *iscsi ) {
+ int rc;
+
+ /* Fill in common header */
+ initiator->header.structure_id = IBFT_STRUCTURE_ID_INITIATOR;
+ initiator->header.version = 1;
+ initiator->header.length = cpu_to_le16 ( sizeof ( *initiator ) );
+ initiator->header.flags = ( IBFT_FL_INITIATOR_BLOCK_VALID |
+ IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED );
+
+ /* Fill in hostname */
+ if ( ( rc = ibft_set_string ( strings, &initiator->initiator_name,
+ iscsi->initiator_iqn ) ) != 0 )
+ return rc;
+ DBG ( "iBFT initiator hostname = %s\n",
+ ibft_string ( strings, &initiator->initiator_name ) );
+
+ return 0;
+}
+
+/**
+ * Fill in Target CHAP portion of iBFT
+ *
+ * @v target Target portion of iBFT
+ * @v strings iBFT string block descriptor
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int ibft_fill_target_chap ( struct ibft_target *target,
+ struct ibft_strings *strings,
+ struct iscsi_session *iscsi ) {
+ int rc;
+
+ if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_FORWARD_REQUIRED ) )
+ return 0;
+
+ assert ( iscsi->initiator_username );
+ assert ( iscsi->initiator_password );
+
+ target->chap_type = IBFT_CHAP_ONE_WAY;
+ if ( ( rc = ibft_set_string ( strings, &target->chap_name,
+ iscsi->initiator_username ) ) != 0 )
+ return rc;
+ DBG ( "iBFT target username = %s\n",
+ ibft_string ( strings, &target->chap_name ) );
+ if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
+ iscsi->initiator_password ) ) != 0 )
+ return rc;
+ DBG ( "iBFT target password = <redacted>\n" );
+
+ return 0;
+}
+
+/**
+ * Fill in Target Reverse CHAP portion of iBFT
+ *
+ * @v target Target portion of iBFT
+ * @v strings iBFT string block descriptor
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int ibft_fill_target_reverse_chap ( struct ibft_target *target,
+ struct ibft_strings *strings,
+ struct iscsi_session *iscsi ) {
+ int rc;
+
+ if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) )
+ return 0;
+
+ assert ( iscsi->initiator_username );
+ assert ( iscsi->initiator_password );
+ assert ( iscsi->target_username );
+ assert ( iscsi->target_password );
+
+ target->chap_type = IBFT_CHAP_MUTUAL;
+ if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name,
+ iscsi->target_username ) ) != 0 )
+ return rc;
+ DBG ( "iBFT target reverse username = %s\n",
+ ibft_string ( strings, &target->chap_name ) );
+ if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret,
+ iscsi->target_password ) ) != 0 )
+ return rc;
+ DBG ( "iBFT target reverse password = <redacted>\n" );
+
+ return 0;
+}
+
+/**
+ * Fill in Target portion of iBFT
+ *
+ * @v target Target portion of iBFT
+ * @v strings iBFT string block descriptor
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int ibft_fill_target ( struct ibft_target *target,
+ struct ibft_strings *strings,
+ struct iscsi_session *iscsi ) {
+ struct sockaddr_in *sin_target =
+ ( struct sockaddr_in * ) &iscsi->target_sockaddr;
+ int rc;
+
+ /* Fill in common header */
+ target->header.structure_id = IBFT_STRUCTURE_ID_TARGET;
+ target->header.version = 1;
+ target->header.length = cpu_to_le16 ( sizeof ( *target ) );
+ target->header.flags = ( IBFT_FL_TARGET_BLOCK_VALID |
+ IBFT_FL_TARGET_FIRMWARE_BOOT_SELECTED );
+
+ /* Fill in Target values */
+ ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr );
+ DBG ( "iBFT target IP = %s\n", ibft_ipaddr ( &target->ip_address ) );
+ target->socket = cpu_to_le16 ( ntohs ( sin_target->sin_port ) );
+ DBG ( "iBFT target port = %d\n", target->socket );
+ memcpy ( &target->boot_lun, &iscsi->lun, sizeof ( target->boot_lun ) );
+ DBG ( "iBFT target boot LUN = " SCSI_LUN_FORMAT "\n",
+ SCSI_LUN_DATA ( target->boot_lun ) );
+ if ( ( rc = ibft_set_string ( strings, &target->target_name,
+ iscsi->target_iqn ) ) != 0 )
+ return rc;
+ DBG ( "iBFT target name = %s\n",
+ ibft_string ( strings, &target->target_name ) );
+ if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 )
+ return rc;
+ if ( ( rc = ibft_fill_target_reverse_chap ( target, strings,
+ iscsi ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Fill in iBFT
+ *
+ * @v iscsi iSCSI session
+ * @v acpi ACPI table
+ * @v len Length of ACPI table
+ * @ret rc Return status code
+ */
+int ibft_describe ( struct iscsi_session *iscsi,
+ struct acpi_description_header *acpi,
+ size_t len ) {
+ struct ipxe_ibft *ibft =
+ container_of ( acpi, struct ipxe_ibft, table.acpi );
+ struct ibft_strings strings = {
+ .table = &ibft->table,
+ .offset = offsetof ( typeof ( *ibft ), strings ),
+ .len = len,
+ };
+ struct net_device *netdev;
+ int rc;
+
+ /* Ugly hack. Now that we have a generic interface mechanism
+ * that can support ioctls, we can potentially eliminate this.
+ */
+ netdev = last_opened_netdev();
+ if ( ! netdev ) {
+ DBGC ( iscsi, "iSCSI %p cannot guess network device\n",
+ iscsi );
+ return -ENODEV;
+ }
+
+ /* Fill in ACPI header */
+ ibft->table.acpi.signature = cpu_to_le32 ( IBFT_SIG );
+ ibft->table.acpi.length = cpu_to_le32 ( len );
+ ibft->table.acpi.revision = 1;
+
+ /* Fill in Control block */
+ ibft->table.control.header.structure_id = IBFT_STRUCTURE_ID_CONTROL;
+ ibft->table.control.header.version = 1;
+ ibft->table.control.header.length =
+ cpu_to_le16 ( sizeof ( ibft->table.control ) );
+ ibft->table.control.initiator =
+ cpu_to_le16 ( offsetof ( typeof ( *ibft ), initiator ) );
+ ibft->table.control.nic_0 =
+ cpu_to_le16 ( offsetof ( typeof ( *ibft ), nic ) );
+ ibft->table.control.target_0 =
+ cpu_to_le16 ( offsetof ( typeof ( *ibft ), target ) );
+
+ /* Fill in NIC, Initiator and Target blocks */
+ if ( ( rc = ibft_fill_nic ( &ibft->nic, &strings, netdev ) ) != 0 )
+ return rc;
+ if ( ( rc = ibft_fill_initiator ( &ibft->initiator, &strings,
+ iscsi ) ) != 0 )
+ return rc;
+ if ( ( rc = ibft_fill_target ( &ibft->target, &strings,
+ iscsi ) ) != 0 )
+ return rc;
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/block/scsi.c b/src/VBox/Devices/PC/ipxe/src/drivers/block/scsi.c
new file mode 100644
index 00000000..fb90fbce
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/block/scsi.c
@@ -0,0 +1,970 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/list.h>
+#include <ipxe/process.h>
+#include <ipxe/xfer.h>
+#include <ipxe/blockdev.h>
+#include <ipxe/scsi.h>
+
+/** @file
+ *
+ * SCSI block device
+ *
+ */
+
+/** Maximum number of command retries */
+#define SCSICMD_MAX_RETRIES 10
+
+/* Error numbers generated by SCSI sense data */
+#define EIO_NO_SENSE __einfo_error ( EINFO_EIO_NO_SENSE )
+#define EINFO_EIO_NO_SENSE \
+ __einfo_uniqify ( EINFO_EIO, 0x00, "No sense" )
+#define EIO_RECOVERED_ERROR __einfo_error ( EINFO_EIO_RECOVERED_ERROR )
+#define EINFO_EIO_RECOVERED_ERROR \
+ __einfo_uniqify ( EINFO_EIO, 0x01, "Recovered error" )
+#define EIO_NOT_READY __einfo_error ( EINFO_EIO_NOT_READY )
+#define EINFO_EIO_NOT_READY \
+ __einfo_uniqify ( EINFO_EIO, 0x02, "Not ready" )
+#define EIO_MEDIUM_ERROR __einfo_error ( EINFO_EIO_MEDIUM_ERROR )
+#define EINFO_EIO_MEDIUM_ERROR \
+ __einfo_uniqify ( EINFO_EIO, 0x03, "Medium error" )
+#define EIO_HARDWARE_ERROR __einfo_error ( EINFO_EIO_HARDWARE_ERROR )
+#define EINFO_EIO_HARDWARE_ERROR \
+ __einfo_uniqify ( EINFO_EIO, 0x04, "Hardware error" )
+#define EIO_ILLEGAL_REQUEST __einfo_error ( EINFO_EIO_ILLEGAL_REQUEST )
+#define EINFO_EIO_ILLEGAL_REQUEST \
+ __einfo_uniqify ( EINFO_EIO, 0x05, "Illegal request" )
+#define EIO_UNIT_ATTENTION __einfo_error ( EINFO_EIO_UNIT_ATTENTION )
+#define EINFO_EIO_UNIT_ATTENTION \
+ __einfo_uniqify ( EINFO_EIO, 0x06, "Unit attention" )
+#define EIO_DATA_PROTECT __einfo_error ( EINFO_EIO_DATA_PROTECT )
+#define EINFO_EIO_DATA_PROTECT \
+ __einfo_uniqify ( EINFO_EIO, 0x07, "Data protect" )
+#define EIO_BLANK_CHECK __einfo_error ( EINFO_EIO_BLANK_CHECK )
+#define EINFO_EIO_BLANK_CHECK \
+ __einfo_uniqify ( EINFO_EIO, 0x08, "Blank check" )
+#define EIO_VENDOR_SPECIFIC __einfo_error ( EINFO_EIO_VENDOR_SPECIFIC )
+#define EINFO_EIO_VENDOR_SPECIFIC \
+ __einfo_uniqify ( EINFO_EIO, 0x09, "Vendor specific" )
+#define EIO_COPY_ABORTED __einfo_error ( EINFO_EIO_COPY_ABORTED )
+#define EINFO_EIO_COPY_ABORTED \
+ __einfo_uniqify ( EINFO_EIO, 0x0a, "Copy aborted" )
+#define EIO_ABORTED_COMMAND __einfo_error ( EINFO_EIO_ABORTED_COMMAND )
+#define EINFO_EIO_ABORTED_COMMAND \
+ __einfo_uniqify ( EINFO_EIO, 0x0b, "Aborted command" )
+#define EIO_RESERVED __einfo_error ( EINFO_EIO_RESERVED )
+#define EINFO_EIO_RESERVED \
+ __einfo_uniqify ( EINFO_EIO, 0x0c, "Reserved" )
+#define EIO_VOLUME_OVERFLOW __einfo_error ( EINFO_EIO_VOLUME_OVERFLOW )
+#define EINFO_EIO_VOLUME_OVERFLOW \
+ __einfo_uniqify ( EINFO_EIO, 0x0d, "Volume overflow" )
+#define EIO_MISCOMPARE __einfo_error ( EINFO_EIO_MISCOMPARE )
+#define EINFO_EIO_MISCOMPARE \
+ __einfo_uniqify ( EINFO_EIO, 0x0e, "Miscompare" )
+#define EIO_COMPLETED __einfo_error ( EINFO_EIO_COMPLETED )
+#define EINFO_EIO_COMPLETED \
+ __einfo_uniqify ( EINFO_EIO, 0x0f, "Completed" )
+#define EIO_SENSE( key ) \
+ EUNIQ ( EIO, (key), EIO_NO_SENSE, EIO_RECOVERED_ERROR, \
+ EIO_NOT_READY, EIO_MEDIUM_ERROR, EIO_HARDWARE_ERROR, \
+ EIO_ILLEGAL_REQUEST, EIO_UNIT_ATTENTION, \
+ EIO_DATA_PROTECT, EIO_BLANK_CHECK, EIO_VENDOR_SPECIFIC, \
+ EIO_COPY_ABORTED, EIO_ABORTED_COMMAND, EIO_RESERVED, \
+ EIO_VOLUME_OVERFLOW, EIO_MISCOMPARE, EIO_COMPLETED )
+
+/******************************************************************************
+ *
+ * Utility functions
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Parse SCSI LUN
+ *
+ * @v lun_string LUN string representation
+ * @v lun LUN to fill in
+ * @ret rc Return status code
+ */
+int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun ) {
+ char *p;
+ int i;
+
+ memset ( lun, 0, sizeof ( *lun ) );
+ if ( lun_string ) {
+ p = ( char * ) lun_string;
+ for ( i = 0 ; i < 4 ; i++ ) {
+ lun->u16[i] = htons ( strtoul ( p, &p, 16 ) );
+ if ( *p == '\0' )
+ break;
+ if ( *p != '-' )
+ return -EINVAL;
+ p++;
+ }
+ if ( *p )
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/******************************************************************************
+ *
+ * Interface methods
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Issue SCSI command
+ *
+ * @v control SCSI control interface
+ * @v data SCSI data interface
+ * @v command SCSI command
+ * @ret tag Command tag, or negative error
+ */
+int scsi_command ( struct interface *control, struct interface *data,
+ struct scsi_cmd *command ) {
+ struct interface *dest;
+ scsi_command_TYPE ( void * ) *op =
+ intf_get_dest_op ( control, scsi_command, &dest );
+ void *object = intf_object ( dest );
+ int tap;
+
+ if ( op ) {
+ tap = op ( object, data, command );
+ } else {
+ /* Default is to fail to issue the command */
+ tap = -EOPNOTSUPP;
+ }
+
+ intf_put ( dest );
+ return tap;
+}
+
+/**
+ * Report SCSI response
+ *
+ * @v interface SCSI command interface
+ * @v response SCSI response
+ */
+void scsi_response ( struct interface *intf, struct scsi_rsp *response ) {
+ struct interface *dest;
+ scsi_response_TYPE ( void * ) *op =
+ intf_get_dest_op ( intf, scsi_response, &dest );
+ void *object = intf_object ( dest );
+
+ if ( op ) {
+ op ( object, response );
+ } else {
+ /* Default is to ignore the response */
+ }
+
+ intf_put ( dest );
+}
+
+/******************************************************************************
+ *
+ * SCSI devices and commands
+ *
+ ******************************************************************************
+ */
+
+/** A SCSI device */
+struct scsi_device {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Block control interface */
+ struct interface block;
+ /** SCSI control interface */
+ struct interface scsi;
+
+ /** SCSI LUN */
+ struct scsi_lun lun;
+ /** Flags */
+ unsigned int flags;
+
+ /** TEST UNIT READY interface */
+ struct interface ready;
+ /** TEST UNIT READY process */
+ struct process process;
+
+ /** List of commands */
+ struct list_head cmds;
+};
+
+/** SCSI device flags */
+enum scsi_device_flags {
+ /** TEST UNIT READY has been issued */
+ SCSIDEV_UNIT_TESTED = 0x0001,
+ /** TEST UNIT READY has completed successfully */
+ SCSIDEV_UNIT_READY = 0x0002,
+};
+
+/** A SCSI command */
+struct scsi_command {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** SCSI device */
+ struct scsi_device *scsidev;
+ /** List of SCSI commands */
+ struct list_head list;
+
+ /** Block data interface */
+ struct interface block;
+ /** SCSI data interface */
+ struct interface scsi;
+
+ /** Command type */
+ struct scsi_command_type *type;
+ /** Starting logical block address */
+ uint64_t lba;
+ /** Number of blocks */
+ unsigned int count;
+ /** Data buffer */
+ userptr_t buffer;
+ /** Length of data buffer */
+ size_t len;
+ /** Command tag */
+ uint32_t tag;
+
+ /** Retry count */
+ unsigned int retries;
+
+ /** Private data */
+ uint8_t priv[0];
+};
+
+/** A SCSI command type */
+struct scsi_command_type {
+ /** Name */
+ const char *name;
+ /** Additional working space */
+ size_t priv_len;
+ /**
+ * Construct SCSI command IU
+ *
+ * @v scsicmd SCSI command
+ * @v command SCSI command IU
+ */
+ void ( * cmd ) ( struct scsi_command *scsicmd,
+ struct scsi_cmd *command );
+ /**
+ * Handle SCSI command completion
+ *
+ * @v scsicmd SCSI command
+ * @v rc Reason for completion
+ */
+ void ( * done ) ( struct scsi_command *scsicmd, int rc );
+};
+
+/**
+ * Get reference to SCSI device
+ *
+ * @v scsidev SCSI device
+ * @ret scsidev SCSI device
+ */
+static inline __attribute__ (( always_inline )) struct scsi_device *
+scsidev_get ( struct scsi_device *scsidev ) {
+ ref_get ( &scsidev->refcnt );
+ return scsidev;
+}
+
+/**
+ * Drop reference to SCSI device
+ *
+ * @v scsidev SCSI device
+ */
+static inline __attribute__ (( always_inline )) void
+scsidev_put ( struct scsi_device *scsidev ) {
+ ref_put ( &scsidev->refcnt );
+}
+
+/**
+ * Get reference to SCSI command
+ *
+ * @v scsicmd SCSI command
+ * @ret scsicmd SCSI command
+ */
+static inline __attribute__ (( always_inline )) struct scsi_command *
+scsicmd_get ( struct scsi_command *scsicmd ) {
+ ref_get ( &scsicmd->refcnt );
+ return scsicmd;
+}
+
+/**
+ * Drop reference to SCSI command
+ *
+ * @v scsicmd SCSI command
+ */
+static inline __attribute__ (( always_inline )) void
+scsicmd_put ( struct scsi_command *scsicmd ) {
+ ref_put ( &scsicmd->refcnt );
+}
+
+/**
+ * Get SCSI command private data
+ *
+ * @v scsicmd SCSI command
+ * @ret priv Private data
+ */
+static inline __attribute__ (( always_inline )) void *
+scsicmd_priv ( struct scsi_command *scsicmd ) {
+ return scsicmd->priv;
+}
+
+/**
+ * Free SCSI command
+ *
+ * @v refcnt Reference count
+ */
+static void scsicmd_free ( struct refcnt *refcnt ) {
+ struct scsi_command *scsicmd =
+ container_of ( refcnt, struct scsi_command, refcnt );
+
+ /* Remove from list of commands */
+ list_del ( &scsicmd->list );
+ scsidev_put ( scsicmd->scsidev );
+
+ /* Free command */
+ free ( scsicmd );
+}
+
+/**
+ * Close SCSI command
+ *
+ * @v scsicmd SCSI command
+ * @v rc Reason for close
+ */
+static void scsicmd_close ( struct scsi_command *scsicmd, int rc ) {
+ struct scsi_device *scsidev = scsicmd->scsidev;
+
+ if ( rc != 0 ) {
+ DBGC ( scsidev, "SCSI %p tag %08x closed: %s\n",
+ scsidev, scsicmd->tag, strerror ( rc ) );
+ }
+
+ /* Shut down interfaces */
+ intf_shutdown ( &scsicmd->scsi, rc );
+ intf_shutdown ( &scsicmd->block, rc );
+}
+
+/**
+ * Construct and issue SCSI command
+ *
+ * @ret rc Return status code
+ */
+static int scsicmd_command ( struct scsi_command *scsicmd ) {
+ struct scsi_device *scsidev = scsicmd->scsidev;
+ struct scsi_cmd command;
+ int tag;
+ int rc;
+
+ /* Construct command */
+ memset ( &command, 0, sizeof ( command ) );
+ memcpy ( &command.lun, &scsidev->lun, sizeof ( command.lun ) );
+ scsicmd->type->cmd ( scsicmd, &command );
+
+ /* Issue command */
+ if ( ( tag = scsi_command ( &scsidev->scsi, &scsicmd->scsi,
+ &command ) ) < 0 ) {
+ rc = tag;
+ DBGC ( scsidev, "SCSI %p could not issue command: %s\n",
+ scsidev, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Record tag */
+ if ( scsicmd->tag ) {
+ DBGC ( scsidev, "SCSI %p tag %08x is now tag %08x\n",
+ scsidev, scsicmd->tag, tag );
+ }
+ scsicmd->tag = tag;
+ DBGC2 ( scsidev, "SCSI %p tag %08x %s " SCSI_CDB_FORMAT "\n",
+ scsidev, scsicmd->tag, scsicmd->type->name,
+ SCSI_CDB_DATA ( command.cdb ) );
+
+ return 0;
+}
+
+/**
+ * Handle SCSI command completion
+ *
+ * @v scsicmd SCSI command
+ * @v rc Reason for close
+ */
+static void scsicmd_done ( struct scsi_command *scsicmd, int rc ) {
+ struct scsi_device *scsidev = scsicmd->scsidev;
+
+ /* Restart SCSI interface */
+ intf_restart ( &scsicmd->scsi, rc );
+
+ /* SCSI targets have an annoying habit of returning occasional
+ * pointless "error" messages such as "power-on occurred", so
+ * we have to be prepared to retry commands.
+ */
+ if ( ( rc != 0 ) && ( scsicmd->retries++ < SCSICMD_MAX_RETRIES ) ) {
+ /* Retry command */
+ DBGC ( scsidev, "SCSI %p tag %08x failed: %s\n",
+ scsidev, scsicmd->tag, strerror ( rc ) );
+ DBGC ( scsidev, "SCSI %p tag %08x retrying (retry %d)\n",
+ scsidev, scsicmd->tag, scsicmd->retries );
+ if ( ( rc = scsicmd_command ( scsicmd ) ) == 0 )
+ return;
+ }
+
+ /* If we didn't (successfully) reissue the command, hand over
+ * to the command completion handler.
+ */
+ scsicmd->type->done ( scsicmd, rc );
+}
+
+/**
+ * Handle SCSI response
+ *
+ * @v scsicmd SCSI command
+ * @v response SCSI response
+ */
+static void scsicmd_response ( struct scsi_command *scsicmd,
+ struct scsi_rsp *response ) {
+ struct scsi_device *scsidev = scsicmd->scsidev;
+ size_t overrun;
+ size_t underrun;
+ int rc;
+
+ if ( response->status == 0 ) {
+ scsicmd_done ( scsicmd, 0 );
+ } else {
+ DBGC ( scsidev, "SCSI %p tag %08x status %02x",
+ scsidev, scsicmd->tag, response->status );
+ if ( response->overrun > 0 ) {
+ overrun = response->overrun;
+ DBGC ( scsidev, " overrun +%zd", overrun );
+ } else if ( response->overrun < 0 ) {
+ underrun = -(response->overrun);
+ DBGC ( scsidev, " underrun -%zd", underrun );
+ }
+ DBGC ( scsidev, " sense %02x:%02x:%08x\n",
+ response->sense.code, response->sense.key,
+ ntohl ( response->sense.info ) );
+
+ /* Construct error number from sense data */
+ rc = -EIO_SENSE ( response->sense.key & SCSI_SENSE_KEY_MASK );
+ scsicmd_done ( scsicmd, rc );
+ }
+}
+
+/**
+ * Construct SCSI READ command
+ *
+ * @v scsicmd SCSI command
+ * @v command SCSI command IU
+ */
+static void scsicmd_read_cmd ( struct scsi_command *scsicmd,
+ struct scsi_cmd *command ) {
+
+ if ( ( scsicmd->lba + scsicmd->count ) > SCSI_MAX_BLOCK_10 ) {
+ /* Use READ (16) */
+ command->cdb.read16.opcode = SCSI_OPCODE_READ_16;
+ command->cdb.read16.lba = cpu_to_be64 ( scsicmd->lba );
+ command->cdb.read16.len = cpu_to_be32 ( scsicmd->count );
+ } else {
+ /* Use READ (10) */
+ command->cdb.read10.opcode = SCSI_OPCODE_READ_10;
+ command->cdb.read10.lba = cpu_to_be32 ( scsicmd->lba );
+ command->cdb.read10.len = cpu_to_be16 ( scsicmd->count );
+ }
+ command->data_in = scsicmd->buffer;
+ command->data_in_len = scsicmd->len;
+}
+
+/** SCSI READ command type */
+static struct scsi_command_type scsicmd_read = {
+ .name = "READ",
+ .cmd = scsicmd_read_cmd,
+ .done = scsicmd_close,
+};
+
+/**
+ * Construct SCSI WRITE command
+ *
+ * @v scsicmd SCSI command
+ * @v command SCSI command IU
+ */
+static void scsicmd_write_cmd ( struct scsi_command *scsicmd,
+ struct scsi_cmd *command ) {
+
+ if ( ( scsicmd->lba + scsicmd->count ) > SCSI_MAX_BLOCK_10 ) {
+ /* Use WRITE (16) */
+ command->cdb.write16.opcode = SCSI_OPCODE_WRITE_16;
+ command->cdb.write16.lba = cpu_to_be64 ( scsicmd->lba );
+ command->cdb.write16.len = cpu_to_be32 ( scsicmd->count );
+ } else {
+ /* Use WRITE (10) */
+ command->cdb.write10.opcode = SCSI_OPCODE_WRITE_10;
+ command->cdb.write10.lba = cpu_to_be32 ( scsicmd->lba );
+ command->cdb.write10.len = cpu_to_be16 ( scsicmd->count );
+ }
+ command->data_out = scsicmd->buffer;
+ command->data_out_len = scsicmd->len;
+}
+
+/** SCSI WRITE command type */
+static struct scsi_command_type scsicmd_write = {
+ .name = "WRITE",
+ .cmd = scsicmd_write_cmd,
+ .done = scsicmd_close,
+};
+
+/** SCSI READ CAPACITY private data */
+struct scsi_read_capacity_private {
+ /** Use READ CAPACITY (16) */
+ int use16;
+ /** Data buffer for READ CAPACITY commands */
+ union {
+ /** Data buffer for READ CAPACITY (10) */
+ struct scsi_capacity_10 capacity10;
+ /** Data buffer for READ CAPACITY (16) */
+ struct scsi_capacity_16 capacity16;
+ } capacity;
+};
+
+/**
+ * Construct SCSI READ CAPACITY command
+ *
+ * @v scsicmd SCSI command
+ * @v command SCSI command IU
+ */
+static void scsicmd_read_capacity_cmd ( struct scsi_command *scsicmd,
+ struct scsi_cmd *command ) {
+ struct scsi_read_capacity_private *priv = scsicmd_priv ( scsicmd );
+ struct scsi_cdb_read_capacity_16 *readcap16 = &command->cdb.readcap16;
+ struct scsi_cdb_read_capacity_10 *readcap10 = &command->cdb.readcap10;
+ struct scsi_capacity_16 *capacity16 = &priv->capacity.capacity16;
+ struct scsi_capacity_10 *capacity10 = &priv->capacity.capacity10;
+
+ if ( priv->use16 ) {
+ /* Use READ CAPACITY (16) */
+ readcap16->opcode = SCSI_OPCODE_SERVICE_ACTION_IN;
+ readcap16->service_action =
+ SCSI_SERVICE_ACTION_READ_CAPACITY_16;
+ readcap16->len = cpu_to_be32 ( sizeof ( *capacity16 ) );
+ command->data_in = virt_to_user ( capacity16 );
+ command->data_in_len = sizeof ( *capacity16 );
+ } else {
+ /* Use READ CAPACITY (10) */
+ readcap10->opcode = SCSI_OPCODE_READ_CAPACITY_10;
+ command->data_in = virt_to_user ( capacity10 );
+ command->data_in_len = sizeof ( *capacity10 );
+ }
+}
+
+/**
+ * Handle SCSI READ CAPACITY command completion
+ *
+ * @v scsicmd SCSI command
+ * @v rc Reason for completion
+ */
+static void scsicmd_read_capacity_done ( struct scsi_command *scsicmd,
+ int rc ) {
+ struct scsi_read_capacity_private *priv = scsicmd_priv ( scsicmd );
+ struct scsi_capacity_16 *capacity16 = &priv->capacity.capacity16;
+ struct scsi_capacity_10 *capacity10 = &priv->capacity.capacity10;
+ struct block_device_capacity capacity;
+
+ /* Close if command failed */
+ if ( rc != 0 ) {
+ scsicmd_close ( scsicmd, rc );
+ return;
+ }
+
+ /* Extract capacity */
+ if ( priv->use16 ) {
+ capacity.blocks = ( be64_to_cpu ( capacity16->lba ) + 1 );
+ capacity.blksize = be32_to_cpu ( capacity16->blksize );
+ } else {
+ capacity.blocks = ( be32_to_cpu ( capacity10->lba ) + 1 );
+ capacity.blksize = be32_to_cpu ( capacity10->blksize );
+
+ /* If capacity range was exceeded (i.e. capacity.lba
+ * was 0xffffffff, meaning that blockdev->blocks is
+ * now zero), use READ CAPACITY (16) instead. READ
+ * CAPACITY (16) is not mandatory, so we can't just
+ * use it straight off.
+ */
+ if ( capacity.blocks == 0 ) {
+ priv->use16 = 1;
+ if ( ( rc = scsicmd_command ( scsicmd ) ) != 0 ) {
+ scsicmd_close ( scsicmd, rc );
+ return;
+ }
+ return;
+ }
+ }
+ capacity.max_count = -1U;
+
+ /* Return capacity to caller */
+ block_capacity ( &scsicmd->block, &capacity );
+
+ /* Close command */
+ scsicmd_close ( scsicmd, 0 );
+}
+
+/** SCSI READ CAPACITY command type */
+static struct scsi_command_type scsicmd_read_capacity = {
+ .name = "READ CAPACITY",
+ .priv_len = sizeof ( struct scsi_read_capacity_private ),
+ .cmd = scsicmd_read_capacity_cmd,
+ .done = scsicmd_read_capacity_done,
+};
+
+/**
+ * Construct SCSI TEST UNIT READY command
+ *
+ * @v scsicmd SCSI command
+ * @v command SCSI command IU
+ */
+static void scsicmd_test_unit_ready_cmd ( struct scsi_command *scsicmd __unused,
+ struct scsi_cmd *command ) {
+ struct scsi_cdb_test_unit_ready *testready = &command->cdb.testready;
+
+ testready->opcode = SCSI_OPCODE_TEST_UNIT_READY;
+}
+
+/** SCSI TEST UNIT READY command type */
+static struct scsi_command_type scsicmd_test_unit_ready = {
+ .name = "TEST UNIT READY",
+ .cmd = scsicmd_test_unit_ready_cmd,
+ .done = scsicmd_close,
+};
+
+/** SCSI command block interface operations */
+static struct interface_operation scsicmd_block_op[] = {
+ INTF_OP ( intf_close, struct scsi_command *, scsicmd_close ),
+};
+
+/** SCSI command block interface descriptor */
+static struct interface_descriptor scsicmd_block_desc =
+ INTF_DESC_PASSTHRU ( struct scsi_command, block,
+ scsicmd_block_op, scsi );
+
+/** SCSI command SCSI interface operations */
+static struct interface_operation scsicmd_scsi_op[] = {
+ INTF_OP ( intf_close, struct scsi_command *, scsicmd_done ),
+ INTF_OP ( scsi_response, struct scsi_command *, scsicmd_response ),
+};
+
+/** SCSI command SCSI interface descriptor */
+static struct interface_descriptor scsicmd_scsi_desc =
+ INTF_DESC_PASSTHRU ( struct scsi_command, scsi,
+ scsicmd_scsi_op, block );
+
+/**
+ * Create SCSI command
+ *
+ * @v scsidev SCSI device
+ * @v block Block data interface
+ * @v type SCSI command type
+ * @v lba Starting logical block address
+ * @v count Number of blocks to transfer
+ * @v buffer Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int scsidev_command ( struct scsi_device *scsidev,
+ struct interface *block,
+ struct scsi_command_type *type,
+ uint64_t lba, unsigned int count,
+ userptr_t buffer, size_t len ) {
+ struct scsi_command *scsicmd;
+ int rc;
+
+ /* Allocate and initialise structure */
+ scsicmd = zalloc ( sizeof ( *scsicmd ) + type->priv_len );
+ if ( ! scsicmd ) {
+ rc = -ENOMEM;
+ goto err_zalloc;
+ }
+ ref_init ( &scsicmd->refcnt, scsicmd_free );
+ intf_init ( &scsicmd->block, &scsicmd_block_desc, &scsicmd->refcnt );
+ intf_init ( &scsicmd->scsi, &scsicmd_scsi_desc,
+ &scsicmd->refcnt );
+ scsicmd->scsidev = scsidev_get ( scsidev );
+ list_add ( &scsicmd->list, &scsidev->cmds );
+ scsicmd->type = type;
+ scsicmd->lba = lba;
+ scsicmd->count = count;
+ scsicmd->buffer = buffer;
+ scsicmd->len = len;
+
+ /* Issue SCSI command */
+ if ( ( rc = scsicmd_command ( scsicmd ) ) != 0 )
+ goto err_command;
+
+ /* Attach to parent interface, mortalise self, and return */
+ intf_plug_plug ( &scsicmd->block, block );
+ ref_put ( &scsicmd->refcnt );
+ return 0;
+
+ err_command:
+ scsicmd_close ( scsicmd, rc );
+ ref_put ( &scsicmd->refcnt );
+ err_zalloc:
+ return rc;
+}
+
+/**
+ * Issue SCSI block read
+ *
+ * @v scsidev SCSI device
+ * @v block Block data interface
+ * @v lba Starting logical block address
+ * @v count Number of blocks to transfer
+ * @v buffer Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+
+ */
+static int scsidev_read ( struct scsi_device *scsidev,
+ struct interface *block,
+ uint64_t lba, unsigned int count,
+ userptr_t buffer, size_t len ) {
+ return scsidev_command ( scsidev, block, &scsicmd_read,
+ lba, count, buffer, len );
+}
+
+/**
+ * Issue SCSI block write
+ *
+ * @v scsidev SCSI device
+ * @v block Block data interface
+ * @v lba Starting logical block address
+ * @v count Number of blocks to transfer
+ * @v buffer Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int scsidev_write ( struct scsi_device *scsidev,
+ struct interface *block,
+ uint64_t lba, unsigned int count,
+ userptr_t buffer, size_t len ) {
+ return scsidev_command ( scsidev, block, &scsicmd_write,
+ lba, count, buffer, len );
+}
+
+/**
+ * Read SCSI device capacity
+ *
+ * @v scsidev SCSI device
+ * @v block Block data interface
+ * @ret rc Return status code
+ */
+static int scsidev_read_capacity ( struct scsi_device *scsidev,
+ struct interface *block ) {
+ return scsidev_command ( scsidev, block, &scsicmd_read_capacity,
+ 0, 0, UNULL, 0 );
+}
+
+/**
+ * Test to see if SCSI device is ready
+ *
+ * @v scsidev SCSI device
+ * @v block Block data interface
+ * @ret rc Return status code
+ */
+static int scsidev_test_unit_ready ( struct scsi_device *scsidev,
+ struct interface *block ) {
+ return scsidev_command ( scsidev, block, &scsicmd_test_unit_ready,
+ 0, 0, UNULL, 0 );
+}
+
+/**
+ * Check SCSI device flow-control window
+ *
+ * @v scsidev SCSI device
+ * @ret len Length of window
+ */
+static size_t scsidev_window ( struct scsi_device *scsidev ) {
+
+ /* Refuse commands until unit is confirmed ready */
+ if ( ! ( scsidev->flags & SCSIDEV_UNIT_READY ) )
+ return 0;
+
+ return xfer_window ( &scsidev->scsi );
+}
+
+/**
+ * Close SCSI device
+ *
+ * @v scsidev SCSI device
+ * @v rc Reason for close
+ */
+static void scsidev_close ( struct scsi_device *scsidev, int rc ) {
+ struct scsi_command *scsicmd;
+ struct scsi_command *tmp;
+
+ /* Stop process */
+ process_del ( &scsidev->process );
+
+ /* Shut down interfaces */
+ intf_shutdown ( &scsidev->block, rc );
+ intf_shutdown ( &scsidev->scsi, rc );
+ intf_shutdown ( &scsidev->ready, rc );
+
+ /* Shut down any remaining commands */
+ list_for_each_entry_safe ( scsicmd, tmp, &scsidev->cmds, list ) {
+ scsicmd_get ( scsicmd );
+ scsicmd_close ( scsicmd, rc );
+ scsicmd_put ( scsicmd );
+ }
+}
+
+/** SCSI device block interface operations */
+static struct interface_operation scsidev_block_op[] = {
+ INTF_OP ( xfer_window, struct scsi_device *, scsidev_window ),
+ INTF_OP ( block_read, struct scsi_device *, scsidev_read ),
+ INTF_OP ( block_write, struct scsi_device *, scsidev_write ),
+ INTF_OP ( block_read_capacity, struct scsi_device *,
+ scsidev_read_capacity ),
+ INTF_OP ( intf_close, struct scsi_device *, scsidev_close ),
+};
+
+/** SCSI device block interface descriptor */
+static struct interface_descriptor scsidev_block_desc =
+ INTF_DESC_PASSTHRU ( struct scsi_device, block,
+ scsidev_block_op, scsi );
+
+/**
+ * Handle SCSI TEST UNIT READY response
+ *
+ * @v scsidev SCSI device
+ * @v rc Reason for close
+ */
+static void scsidev_ready ( struct scsi_device *scsidev, int rc ) {
+
+ /* Shut down interface */
+ intf_shutdown ( &scsidev->ready, rc );
+
+ /* Close device on failure */
+ if ( rc != 0 ) {
+ DBGC ( scsidev, "SCSI %p not ready: %s\n",
+ scsidev, strerror ( rc ) );
+ scsidev_close ( scsidev, rc );
+ return;
+ }
+
+ /* Mark device as ready */
+ scsidev->flags |= SCSIDEV_UNIT_READY;
+ xfer_window_changed ( &scsidev->block );
+ DBGC ( scsidev, "SCSI %p unit is ready\n", scsidev );
+}
+
+/** SCSI device TEST UNIT READY interface operations */
+static struct interface_operation scsidev_ready_op[] = {
+ INTF_OP ( intf_close, struct scsi_device *, scsidev_ready ),
+};
+
+/** SCSI device TEST UNIT READY interface descriptor */
+static struct interface_descriptor scsidev_ready_desc =
+ INTF_DESC ( struct scsi_device, ready, scsidev_ready_op );
+
+/**
+ * SCSI TEST UNIT READY process
+ *
+ * @v scsidev SCSI device
+ */
+static void scsidev_step ( struct scsi_device *scsidev ) {
+ int rc;
+
+ /* Do nothing if we have already issued TEST UNIT READY */
+ if ( scsidev->flags & SCSIDEV_UNIT_TESTED )
+ return;
+
+ /* Wait until underlying SCSI device is ready */
+ if ( xfer_window ( &scsidev->scsi ) == 0 )
+ return;
+
+ DBGC ( scsidev, "SCSI %p waiting for unit to become ready\n",
+ scsidev );
+
+ /* Mark TEST UNIT READY as sent */
+ scsidev->flags |= SCSIDEV_UNIT_TESTED;
+
+ /* Issue TEST UNIT READY command */
+ if ( ( rc = scsidev_test_unit_ready ( scsidev, &scsidev->ready )) !=0){
+ scsidev_close ( scsidev, rc );
+ return;
+ }
+}
+
+/** SCSI device SCSI interface operations */
+static struct interface_operation scsidev_scsi_op[] = {
+ INTF_OP ( xfer_window_changed, struct scsi_device *, scsidev_step ),
+ INTF_OP ( intf_close, struct scsi_device *, scsidev_close ),
+};
+
+/** SCSI device SCSI interface descriptor */
+static struct interface_descriptor scsidev_scsi_desc =
+ INTF_DESC_PASSTHRU ( struct scsi_device, scsi,
+ scsidev_scsi_op, block );
+
+/** SCSI device process descriptor */
+static struct process_descriptor scsidev_process_desc =
+ PROC_DESC_ONCE ( struct scsi_device, process, scsidev_step );
+
+/**
+ * Open SCSI device
+ *
+ * @v block Block control interface
+ * @v scsi SCSI control interface
+ * @v lun SCSI LUN
+ * @ret rc Return status code
+ */
+int scsi_open ( struct interface *block, struct interface *scsi,
+ struct scsi_lun *lun ) {
+ struct scsi_device *scsidev;
+
+ /* Allocate and initialise structure */
+ scsidev = zalloc ( sizeof ( *scsidev ) );
+ if ( ! scsidev )
+ return -ENOMEM;
+ ref_init ( &scsidev->refcnt, NULL );
+ intf_init ( &scsidev->block, &scsidev_block_desc, &scsidev->refcnt );
+ intf_init ( &scsidev->scsi, &scsidev_scsi_desc, &scsidev->refcnt );
+ intf_init ( &scsidev->ready, &scsidev_ready_desc, &scsidev->refcnt );
+ process_init ( &scsidev->process, &scsidev_process_desc,
+ &scsidev->refcnt );
+ INIT_LIST_HEAD ( &scsidev->cmds );
+ memcpy ( &scsidev->lun, lun, sizeof ( scsidev->lun ) );
+ DBGC ( scsidev, "SCSI %p created for LUN " SCSI_LUN_FORMAT "\n",
+ scsidev, SCSI_LUN_DATA ( scsidev->lun ) );
+
+ /* Attach to SCSI and parent interfaces, mortalise self, and return */
+ intf_plug_plug ( &scsidev->scsi, scsi );
+ intf_plug_plug ( &scsidev->block, block );
+ ref_put ( &scsidev->refcnt );
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/block/srp.c b/src/VBox/Devices/PC/ipxe/src/drivers/block/srp.c
new file mode 100644
index 00000000..098a973e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/block/srp.c
@@ -0,0 +1,828 @@
+/*
+ * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/scsi.h>
+#include <ipxe/xfer.h>
+#include <ipxe/features.h>
+#include <ipxe/srp.h>
+
+/**
+ * @file
+ *
+ * SCSI RDMA Protocol
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "SRP", DHCP_EB_FEATURE_SRP, 1 );
+
+/** Maximum length of any initiator-to-target IU that we will send
+ *
+ * The longest IU is a SRP_CMD with no additional CDB and two direct
+ * data buffer descriptors, which comes to 80 bytes.
+ */
+#define SRP_MAX_I_T_IU_LEN 80
+
+/* Error numbers generated by SRP login rejection */
+#define EINFO_SRP_LOGIN_REJ( reason, desc ) \
+ __einfo_uniqify ( EINFO_EPERM, ( (reason) & 0x0f ), desc )
+#define EPERM_UNKNOWN \
+ __einfo_error ( EINFO_EPERM_UNKNOWN )
+#define EINFO_EPERM_UNKNOWN EINFO_SRP_LOGIN_REJ ( \
+ SRP_LOGIN_REJ_REASON_UNKNOWN, \
+ "Unable to establish RDMA channel, no reason specified" )
+#define EPERM_INSUFFICIENT_RESOURCES \
+ __einfo_error ( EINFO_EPERM_INSUFFICIENT_RESOURCES )
+#define EINFO_EPERM_INSUFFICIENT_RESOURCES EINFO_SRP_LOGIN_REJ ( \
+ SRP_LOGIN_REJ_REASON_INSUFFICIENT_RESOURCES, \
+ "Insufficient RDMA channel resources" )
+#define EPERM_BAD_MAX_I_T_IU_LEN \
+ __einfo_error ( EINFO_EPERM_BAD_MAX_I_T_IU_LEN )
+#define EINFO_EPERM_BAD_MAX_I_T_IU_LEN EINFO_SRP_LOGIN_REJ ( \
+ SRP_LOGIN_REJ_REASON_BAD_MAX_I_T_IU_LEN, \
+ "Requested maximum initiator to target IU length value too large" )
+#define EPERM_CANNOT_ASSOCIATE \
+ __einfo_error ( EINFO_EPERM_CANNOT_ASSOCIATE )
+#define EINFO_EPERM_CANNOT_ASSOCIATE EINFO_SRP_LOGIN_REJ ( \
+ SRP_LOGIN_REJ_REASON_CANNOT_ASSOCIATE, \
+ "Unable to associate RDMA channel with specified I_T nexus" )
+#define EPERM_UNSUPPORTED_BUFFER_FORMAT \
+ __einfo_error ( EINFO_EPERM_UNSUPPORTED_BUFFER_FORMAT )
+#define EINFO_EPERM_UNSUPPORTED_BUFFER_FORMAT EINFO_SRP_LOGIN_REJ ( \
+ SRP_LOGIN_REJ_REASON_UNSUPPORTED_BUFFER_FORMAT, \
+ "One or more requested data buffer descriptor formats not supported" )
+#define EPERM_NO_MULTIPLE_CHANNELS \
+ __einfo_error ( EINFO_EPERM_NO_MULTIPLE_CHANNELS )
+#define EINFO_EPERM_NO_MULTIPLE_CHANNELS EINFO_SRP_LOGIN_REJ ( \
+ SRP_LOGIN_REJ_REASON_NO_MULTIPLE_CHANNELS, \
+ "SRP target does not support multiple RDMA channels per I_T nexus" )
+#define EPERM_NO_MORE_CHANNELS \
+ __einfo_error ( EINFO_EPERM_NO_MORE_CHANNELS )
+#define EINFO_EPERM_NO_MORE_CHANNELS EINFO_SRP_LOGIN_REJ ( \
+ SRP_LOGIN_REJ_REASON_NO_MORE_CHANNELS, \
+ "RDMA channel limit reached for this initiator" )
+#define EPERM_LOGIN_REJ( reason_nibble ) \
+ EUNIQ ( EPERM, (reason_nibble), EPERM_UNKNOWN, \
+ EPERM_INSUFFICIENT_RESOURCES, EPERM_BAD_MAX_I_T_IU_LEN, \
+ EPERM_CANNOT_ASSOCIATE, EPERM_UNSUPPORTED_BUFFER_FORMAT, \
+ EPERM_NO_MULTIPLE_CHANNELS, EPERM_NO_MORE_CHANNELS )
+
+/** An SRP device */
+struct srp_device {
+ /** Reference count */
+ struct refcnt refcnt;
+
+ /** SCSI command issuing interface */
+ struct interface scsi;
+ /** Underlying data transfer interface */
+ struct interface socket;
+
+ /** RDMA memory handle */
+ uint32_t memory_handle;
+ /** Login completed successfully */
+ int logged_in;
+
+ /** Initiator port ID (for boot firmware table) */
+ union srp_port_id initiator;
+ /** Target port ID (for boot firmware table) */
+ union srp_port_id target;
+ /** SCSI LUN (for boot firmware table) */
+ struct scsi_lun lun;
+
+ /** List of active commands */
+ struct list_head commands;
+};
+
+/** An SRP command */
+struct srp_command {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** SRP device */
+ struct srp_device *srpdev;
+ /** List of active commands */
+ struct list_head list;
+
+ /** SCSI command interface */
+ struct interface scsi;
+ /** Command tag */
+ uint32_t tag;
+};
+
+/**
+ * Get reference to SRP device
+ *
+ * @v srpdev SRP device
+ * @ret srpdev SRP device
+ */
+static inline __attribute__ (( always_inline )) struct srp_device *
+srpdev_get ( struct srp_device *srpdev ) {
+ ref_get ( &srpdev->refcnt );
+ return srpdev;
+}
+
+/**
+ * Drop reference to SRP device
+ *
+ * @v srpdev SRP device
+ */
+static inline __attribute__ (( always_inline )) void
+srpdev_put ( struct srp_device *srpdev ) {
+ ref_put ( &srpdev->refcnt );
+}
+
+/**
+ * Get reference to SRP command
+ *
+ * @v srpcmd SRP command
+ * @ret srpcmd SRP command
+ */
+static inline __attribute__ (( always_inline )) struct srp_command *
+srpcmd_get ( struct srp_command *srpcmd ) {
+ ref_get ( &srpcmd->refcnt );
+ return srpcmd;
+}
+
+/**
+ * Drop reference to SRP command
+ *
+ * @v srpcmd SRP command
+ */
+static inline __attribute__ (( always_inline )) void
+srpcmd_put ( struct srp_command *srpcmd ) {
+ ref_put ( &srpcmd->refcnt );
+}
+
+/**
+ * Free SRP command
+ *
+ * @v refcnt Reference count
+ */
+static void srpcmd_free ( struct refcnt *refcnt ) {
+ struct srp_command *srpcmd =
+ container_of ( refcnt, struct srp_command, refcnt );
+
+ assert ( list_empty ( &srpcmd->list ) );
+
+ srpdev_put ( srpcmd->srpdev );
+ free ( srpcmd );
+}
+
+/**
+ * Close SRP command
+ *
+ * @v srpcmd SRP command
+ * @v rc Reason for close
+ */
+static void srpcmd_close ( struct srp_command *srpcmd, int rc ) {
+ struct srp_device *srpdev = srpcmd->srpdev;
+
+ if ( rc != 0 ) {
+ DBGC ( srpdev, "SRP %p tag %08x closed: %s\n",
+ srpdev, srpcmd->tag, strerror ( rc ) );
+ }
+
+ /* Remove from list of commands */
+ if ( ! list_empty ( &srpcmd->list ) ) {
+ list_del ( &srpcmd->list );
+ INIT_LIST_HEAD ( &srpcmd->list );
+ srpcmd_put ( srpcmd );
+ }
+
+ /* Shut down interfaces */
+ intf_shutdown ( &srpcmd->scsi, rc );
+}
+
+/**
+ * Close SRP device
+ *
+ * @v srpdev SRP device
+ * @v rc Reason for close
+ */
+static void srpdev_close ( struct srp_device *srpdev, int rc ) {
+ struct srp_command *srpcmd;
+ struct srp_command *tmp;
+
+ if ( rc != 0 ) {
+ DBGC ( srpdev, "SRP %p closed: %s\n",
+ srpdev, strerror ( rc ) );
+ }
+
+ /* Shut down interfaces */
+ intf_shutdown ( &srpdev->socket, rc );
+ intf_shutdown ( &srpdev->scsi, rc );
+
+ /* Shut down any active commands */
+ list_for_each_entry_safe ( srpcmd, tmp, &srpdev->commands, list ) {
+ srpcmd_get ( srpcmd );
+ srpcmd_close ( srpcmd, rc );
+ srpcmd_put ( srpcmd );
+ }
+}
+
+/**
+ * Identify SRP command by tag
+ *
+ * @v srpdev SRP device
+ * @v tag Command tag
+ * @ret srpcmd SRP command, or NULL
+ */
+static struct srp_command * srp_find_tag ( struct srp_device *srpdev,
+ uint32_t tag ) {
+ struct srp_command *srpcmd;
+
+ list_for_each_entry ( srpcmd, &srpdev->commands, list ) {
+ if ( srpcmd->tag == tag )
+ return srpcmd;
+ }
+ return NULL;
+}
+
+/**
+ * Choose an SRP command tag
+ *
+ * @v srpdev SRP device
+ * @ret tag New tag, or negative error
+ */
+static int srp_new_tag ( struct srp_device *srpdev ) {
+ static uint16_t tag_idx;
+ unsigned int i;
+
+ for ( i = 0 ; i < 65536 ; i++ ) {
+ tag_idx++;
+ if ( srp_find_tag ( srpdev, tag_idx ) == NULL )
+ return tag_idx;
+ }
+ return -EADDRINUSE;
+}
+
+/**
+ * Transmit SRP login request
+ *
+ * @v srpdev SRP device
+ * @v initiator Initiator port ID
+ * @v target Target port ID
+ * @v tag Command tag
+ * @ret rc Return status code
+ */
+static int srp_login ( struct srp_device *srpdev, union srp_port_id *initiator,
+ union srp_port_id *target, uint32_t tag ) {
+ struct io_buffer *iobuf;
+ struct srp_login_req *login_req;
+ int rc;
+
+ /* Allocate I/O buffer */
+ iobuf = xfer_alloc_iob ( &srpdev->socket, sizeof ( *login_req ) );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ /* Construct login request IU */
+ login_req = iob_put ( iobuf, sizeof ( *login_req ) );
+ memset ( login_req, 0, sizeof ( *login_req ) );
+ login_req->type = SRP_LOGIN_REQ;
+ login_req->tag.dwords[0] = htonl ( SRP_TAG_MAGIC );
+ login_req->tag.dwords[1] = htonl ( tag );
+ login_req->max_i_t_iu_len = htonl ( SRP_MAX_I_T_IU_LEN );
+ login_req->required_buffer_formats = SRP_LOGIN_REQ_FMT_DDBD;
+ memcpy ( &login_req->initiator, initiator,
+ sizeof ( login_req->initiator ) );
+ memcpy ( &login_req->target, target, sizeof ( login_req->target ) );
+
+ DBGC ( srpdev, "SRP %p tag %08x LOGIN_REQ:\n", srpdev, tag );
+ DBGC_HDA ( srpdev, 0, iobuf->data, iob_len ( iobuf ) );
+
+ /* Send login request IU */
+ if ( ( rc = xfer_deliver_iob ( &srpdev->socket, iobuf ) ) != 0 ) {
+ DBGC ( srpdev, "SRP %p tag %08x could not send LOGIN_REQ: "
+ "%s\n", srpdev, tag, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Receive SRP login response
+ *
+ * @v srpdev SRP device
+ * @v data SRP IU
+ * @v len Length of SRP IU
+ * @ret rc Return status code
+ */
+static int srp_login_rsp ( struct srp_device *srpdev,
+ const void *data, size_t len ) {
+ const struct srp_login_rsp *login_rsp = data;
+
+ /* Sanity check */
+ if ( len < sizeof ( *login_rsp ) ) {
+ DBGC ( srpdev, "SRP %p LOGIN_RSP too short (%zd bytes)\n",
+ srpdev, len );
+ return -EINVAL;
+ }
+ DBGC ( srpdev, "SRP %p tag %08x LOGIN_RSP:\n",
+ srpdev, ntohl ( login_rsp->tag.dwords[1] ) );
+ DBGC_HDA ( srpdev, 0, data, len );
+
+ /* Mark as logged in */
+ srpdev->logged_in = 1;
+ DBGC ( srpdev, "SRP %p logged in\n", srpdev );
+
+ /* Notify of window change */
+ xfer_window_changed ( &srpdev->scsi );
+
+ return 0;
+}
+
+/**
+ * Receive SRP login rejection
+ *
+ * @v srpdev SRP device
+ * @v data SRP IU
+ * @v len Length of SRP IU
+ * @ret rc Return status code
+ */
+static int srp_login_rej ( struct srp_device *srpdev,
+ const void *data, size_t len ) {
+ const struct srp_login_rej *login_rej = data;
+ uint32_t reason;
+
+ /* Sanity check */
+ if ( len < sizeof ( *login_rej ) ) {
+ DBGC ( srpdev, "SRP %p LOGIN_REJ too short (%zd bytes)\n",
+ srpdev, len );
+ return -EINVAL;
+ }
+ reason = ntohl ( login_rej->reason );
+ DBGC ( srpdev, "SRP %p tag %08x LOGIN_REJ reason %08x:\n",
+ srpdev, ntohl ( login_rej->tag.dwords[1] ), reason );
+ DBGC_HDA ( srpdev, 0, data, len );
+
+ /* Login rejection always indicates an error */
+ return ( SRP_LOGIN_REJ_REASON_DEFINED ( reason ) ?
+ -EPERM_LOGIN_REJ ( reason ) : -EACCES );
+}
+
+/**
+ * Transmit SRP SCSI command
+ *
+ * @v srpdev SRP device
+ * @v command SCSI command
+ * @v tag Command tag
+ * @ret rc Return status code
+ */
+static int srp_cmd ( struct srp_device *srpdev,
+ struct scsi_cmd *command,
+ uint32_t tag ) {
+ struct io_buffer *iobuf;
+ struct srp_cmd *cmd;
+ struct srp_memory_descriptor *data_out;
+ struct srp_memory_descriptor *data_in;
+ int rc;
+
+ /* Sanity check */
+ if ( ! srpdev->logged_in ) {
+ DBGC ( srpdev, "SRP %p tag %08x cannot send CMD before "
+ "login completes\n", srpdev, tag );
+ return -EBUSY;
+ }
+
+ /* Allocate I/O buffer */
+ iobuf = xfer_alloc_iob ( &srpdev->socket, SRP_MAX_I_T_IU_LEN );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ /* Construct base portion */
+ cmd = iob_put ( iobuf, sizeof ( *cmd ) );
+ memset ( cmd, 0, sizeof ( *cmd ) );
+ cmd->type = SRP_CMD;
+ cmd->tag.dwords[0] = htonl ( SRP_TAG_MAGIC );
+ cmd->tag.dwords[1] = htonl ( tag );
+ memcpy ( &cmd->lun, &command->lun, sizeof ( cmd->lun ) );
+ memcpy ( &cmd->cdb, &command->cdb, sizeof ( cmd->cdb ) );
+
+ /* Construct data-out descriptor, if present */
+ if ( command->data_out ) {
+ cmd->data_buffer_formats |= SRP_CMD_DO_FMT_DIRECT;
+ data_out = iob_put ( iobuf, sizeof ( *data_out ) );
+ data_out->address =
+ cpu_to_be64 ( user_to_phys ( command->data_out, 0 ) );
+ data_out->handle = ntohl ( srpdev->memory_handle );
+ data_out->len = ntohl ( command->data_out_len );
+ }
+
+ /* Construct data-in descriptor, if present */
+ if ( command->data_in ) {
+ cmd->data_buffer_formats |= SRP_CMD_DI_FMT_DIRECT;
+ data_in = iob_put ( iobuf, sizeof ( *data_in ) );
+ data_in->address =
+ cpu_to_be64 ( user_to_phys ( command->data_in, 0 ) );
+ data_in->handle = ntohl ( srpdev->memory_handle );
+ data_in->len = ntohl ( command->data_in_len );
+ }
+
+ DBGC2 ( srpdev, "SRP %p tag %08x CMD " SCSI_CDB_FORMAT "\n",
+ srpdev, tag, SCSI_CDB_DATA ( cmd->cdb ) );
+
+ /* Send IU */
+ if ( ( rc = xfer_deliver_iob ( &srpdev->socket, iobuf ) ) != 0 ) {
+ DBGC ( srpdev, "SRP %p tag %08x could not send CMD: %s\n",
+ srpdev, tag, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Receive SRP SCSI response
+ *
+ * @v srpdev SRP device
+ * @v data SRP IU
+ * @v len Length of SRP IU
+ * @ret rc Returns status code
+ */
+static int srp_rsp ( struct srp_device *srpdev,
+ const void *data, size_t len ) {
+ const struct srp_rsp *rsp = data;
+ struct srp_command *srpcmd;
+ struct scsi_rsp response;
+ const void *sense;
+ ssize_t data_out_residual_count;
+ ssize_t data_in_residual_count;
+
+ /* Sanity check */
+ if ( len < sizeof ( *rsp ) ) {
+ DBGC ( srpdev, "SRP %p RSP too short (%zd bytes)\n",
+ srpdev, len );
+ return -EINVAL;
+ }
+ DBGC2 ( srpdev, "SRP %p tag %08x RSP stat %02x dores %08x dires "
+ "%08x valid %02x%s%s%s%s%s%s\n",
+ srpdev, ntohl ( rsp->tag.dwords[1] ), rsp->status,
+ ntohl ( rsp->data_out_residual_count ),
+ ntohl ( rsp->data_in_residual_count ), rsp->valid,
+ ( ( rsp->valid & SRP_RSP_VALID_DIUNDER ) ? " diunder" : "" ),
+ ( ( rsp->valid & SRP_RSP_VALID_DIOVER ) ? " diover" : "" ),
+ ( ( rsp->valid & SRP_RSP_VALID_DOUNDER ) ? " dounder" : "" ),
+ ( ( rsp->valid & SRP_RSP_VALID_DOOVER ) ? " doover" : "" ),
+ ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ? " sns" : "" ),
+ ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ? " rsp" : "" ) );
+
+ /* Identify command by tag */
+ srpcmd = srp_find_tag ( srpdev, ntohl ( rsp->tag.dwords[1] ) );
+ if ( ! srpcmd ) {
+ DBGC ( srpdev, "SRP %p tag %08x unrecognised RSP\n",
+ srpdev, ntohl ( rsp->tag.dwords[1] ) );
+ return -ENOENT;
+ }
+
+ /* Hold command reference for remainder of function */
+ srpcmd_get ( srpcmd );
+
+ /* Build SCSI response */
+ memset ( &response, 0, sizeof ( response ) );
+ response.status = rsp->status;
+ data_out_residual_count = ntohl ( rsp->data_out_residual_count );
+ data_in_residual_count = ntohl ( rsp->data_in_residual_count );
+ if ( rsp->valid & SRP_RSP_VALID_DOOVER ) {
+ response.overrun = data_out_residual_count;
+ } else if ( rsp->valid & SRP_RSP_VALID_DOUNDER ) {
+ response.overrun = -(data_out_residual_count);
+ } else if ( rsp->valid & SRP_RSP_VALID_DIOVER ) {
+ response.overrun = data_in_residual_count;
+ } else if ( rsp->valid & SRP_RSP_VALID_DIUNDER ) {
+ response.overrun = -(data_in_residual_count);
+ }
+ sense = srp_rsp_sense_data ( rsp );
+ if ( sense )
+ memcpy ( &response.sense, sense, sizeof ( response.sense ) );
+
+ /* Report SCSI response */
+ scsi_response ( &srpcmd->scsi, &response );
+
+ /* Close SCSI command */
+ srpcmd_close ( srpcmd, 0 );
+
+ /* Drop temporary command reference */
+ srpcmd_put ( srpcmd );
+
+ return 0;
+}
+
+/**
+ * Receive SRP unrecognised response IU
+ *
+ * @v srpdev SRP device
+ * @v data SRP IU
+ * @v len Length of SRP IU
+ * @ret rc Returns status code
+ */
+static int srp_unrecognised ( struct srp_device *srpdev,
+ const void *data, size_t len ) {
+ const struct srp_common *common = data;
+
+ DBGC ( srpdev, "SRP %p tag %08x unrecognised IU type %02x:\n",
+ srpdev, ntohl ( common->tag.dwords[1] ), common->type );
+ DBGC_HDA ( srpdev, 0, data, len );
+
+ return -ENOTSUP;
+}
+
+/** SRP command SCSI interface operations */
+static struct interface_operation srpcmd_scsi_op[] = {
+ INTF_OP ( intf_close, struct srp_command *, srpcmd_close ),
+};
+
+/** SRP command SCSI interface descriptor */
+static struct interface_descriptor srpcmd_scsi_desc =
+ INTF_DESC ( struct srp_command, scsi, srpcmd_scsi_op );
+
+/**
+ * Issue SRP SCSI command
+ *
+ * @v srpdev SRP device
+ * @v parent Parent interface
+ * @v command SCSI command
+ * @ret tag Command tag, or negative error
+ */
+static int srpdev_scsi_command ( struct srp_device *srpdev,
+ struct interface *parent,
+ struct scsi_cmd *command ) {
+ struct srp_command *srpcmd;
+ int tag;
+ int rc;
+
+ /* Allocate command tag */
+ tag = srp_new_tag ( srpdev );
+ if ( tag < 0 ) {
+ rc = tag;
+ goto err_tag;
+ }
+
+ /* Allocate and initialise structure */
+ srpcmd = zalloc ( sizeof ( *srpcmd ) );
+ if ( ! srpcmd ) {
+ rc = -ENOMEM;
+ goto err_zalloc;
+ }
+ ref_init ( &srpcmd->refcnt, srpcmd_free );
+ intf_init ( &srpcmd->scsi, &srpcmd_scsi_desc, &srpcmd->refcnt );
+ srpcmd->srpdev = srpdev_get ( srpdev );
+ list_add ( &srpcmd->list, &srpdev->commands );
+ srpcmd->tag = tag;
+
+ /* Send command IU */
+ if ( ( rc = srp_cmd ( srpdev, command, srpcmd->tag ) ) != 0 )
+ goto err_cmd;
+
+ /* Attach to parent interface, leave reference with command
+ * list, and return.
+ */
+ intf_plug_plug ( &srpcmd->scsi, parent );
+ return srpcmd->tag;
+
+ err_cmd:
+ srpcmd_close ( srpcmd, rc );
+ err_zalloc:
+ err_tag:
+ return rc;
+}
+
+/**
+ * Receive data from SRP socket
+ *
+ * @v srpdev SRP device
+ * @v iobuf Datagram I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int srpdev_deliver ( struct srp_device *srpdev,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ struct srp_common *common = iobuf->data;
+ int ( * type ) ( struct srp_device *srp, const void *data, size_t len );
+ int rc;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *common ) ) {
+ DBGC ( srpdev, "SRP %p IU too short (%zd bytes)\n",
+ srpdev, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto err;
+ }
+
+ /* Determine IU type */
+ switch ( common->type ) {
+ case SRP_LOGIN_RSP:
+ type = srp_login_rsp;
+ break;
+ case SRP_LOGIN_REJ:
+ type = srp_login_rej;
+ break;
+ case SRP_RSP:
+ type = srp_rsp;
+ break;
+ default:
+ type = srp_unrecognised;
+ break;
+ }
+
+ /* Handle IU */
+ if ( ( rc = type ( srpdev, iobuf->data, iob_len ( iobuf ) ) ) != 0 )
+ goto err;
+
+ free_iob ( iobuf );
+ return 0;
+
+ err:
+ DBGC ( srpdev, "SRP %p closing due to received IU (%s):\n",
+ srpdev, strerror ( rc ) );
+ DBGC_HDA ( srpdev, 0, iobuf->data, iob_len ( iobuf ) );
+ free_iob ( iobuf );
+ srpdev_close ( srpdev, rc );
+ return rc;
+}
+
+/**
+ * Check SRP device flow-control window
+ *
+ * @v srpdev SRP device
+ * @ret len Length of window
+ */
+static size_t srpdev_window ( struct srp_device *srpdev ) {
+ return ( srpdev->logged_in ? ~( ( size_t ) 0 ) : 0 );
+}
+
+/**
+ * A (transport-independent) sBFT created by iPXE
+ */
+struct ipxe_sbft {
+ /** The table header */
+ struct sbft_table table;
+ /** The SCSI subtable */
+ struct sbft_scsi_subtable scsi;
+ /** The SRP subtable */
+ struct sbft_srp_subtable srp;
+} __attribute__ (( packed, aligned ( 16 ) ));
+
+/**
+ * Describe SRP device in an ACPI table
+ *
+ * @v srpdev SRP device
+ * @v acpi ACPI table
+ * @v len Length of ACPI table
+ * @ret rc Return status code
+ */
+static int srpdev_describe ( struct srp_device *srpdev,
+ struct acpi_description_header *acpi,
+ size_t len ) {
+ struct ipxe_sbft *sbft =
+ container_of ( acpi, struct ipxe_sbft, table.acpi );
+ int rc;
+
+ /* Sanity check */
+ if ( len < sizeof ( *sbft ) )
+ return -ENOBUFS;
+
+ /* Populate table */
+ sbft->table.acpi.signature = cpu_to_le32 ( SBFT_SIG );
+ sbft->table.acpi.length = cpu_to_le32 ( sizeof ( *sbft ) );
+ sbft->table.acpi.revision = 1;
+ sbft->table.scsi_offset =
+ cpu_to_le16 ( offsetof ( typeof ( *sbft ), scsi ) );
+ memcpy ( &sbft->scsi.lun, &srpdev->lun, sizeof ( sbft->scsi.lun ) );
+ sbft->table.srp_offset =
+ cpu_to_le16 ( offsetof ( typeof ( *sbft ), srp ) );
+ memcpy ( &sbft->srp.initiator, &srpdev->initiator,
+ sizeof ( sbft->srp.initiator ) );
+ memcpy ( &sbft->srp.target, &srpdev->target,
+ sizeof ( sbft->srp.target ) );
+
+ /* Ask transport layer to describe transport-specific portions */
+ if ( ( rc = acpi_describe ( &srpdev->socket, acpi, len ) ) != 0 ) {
+ DBGC ( srpdev, "SRP %p cannot describe transport layer: %s\n",
+ srpdev, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/** SRP device socket interface operations */
+static struct interface_operation srpdev_socket_op[] = {
+ INTF_OP ( xfer_deliver, struct srp_device *, srpdev_deliver ),
+ INTF_OP ( intf_close, struct srp_device *, srpdev_close ),
+};
+
+/** SRP device socket interface descriptor */
+static struct interface_descriptor srpdev_socket_desc =
+ INTF_DESC_PASSTHRU ( struct srp_device, socket, srpdev_socket_op,
+ scsi );
+
+/** SRP device SCSI interface operations */
+static struct interface_operation srpdev_scsi_op[] = {
+ INTF_OP ( scsi_command, struct srp_device *, srpdev_scsi_command ),
+ INTF_OP ( xfer_window, struct srp_device *, srpdev_window ),
+ INTF_OP ( intf_close, struct srp_device *, srpdev_close ),
+ INTF_OP ( acpi_describe, struct srp_device *, srpdev_describe ),
+};
+
+/** SRP device SCSI interface descriptor */
+static struct interface_descriptor srpdev_scsi_desc =
+ INTF_DESC_PASSTHRU ( struct srp_device, scsi, srpdev_scsi_op, socket );
+
+/**
+ * Open SRP device
+ *
+ * @v block Block control interface
+ * @v socket Socket interface
+ * @v initiator Initiator port ID
+ * @v target Target port ID
+ * @v memory_handle RDMA memory handle
+ * @v lun SCSI LUN
+ * @ret rc Return status code
+ */
+int srp_open ( struct interface *block, struct interface *socket,
+ union srp_port_id *initiator, union srp_port_id *target,
+ uint32_t memory_handle, struct scsi_lun *lun ) {
+ struct srp_device *srpdev;
+ int tag;
+ int rc;
+
+ /* Allocate and initialise structure */
+ srpdev = zalloc ( sizeof ( *srpdev ) );
+ if ( ! srpdev ) {
+ rc = -ENOMEM;
+ goto err_zalloc;
+ }
+ ref_init ( &srpdev->refcnt, NULL );
+ intf_init ( &srpdev->scsi, &srpdev_scsi_desc, &srpdev->refcnt );
+ intf_init ( &srpdev->socket, &srpdev_socket_desc, &srpdev->refcnt );
+ INIT_LIST_HEAD ( &srpdev->commands );
+ srpdev->memory_handle = memory_handle;
+ DBGC ( srpdev, "SRP %p %08x%08x%08x%08x->%08x%08x%08x%08x\n", srpdev,
+ ntohl ( initiator->dwords[0] ), ntohl ( initiator->dwords[1] ),
+ ntohl ( initiator->dwords[2] ), ntohl ( initiator->dwords[3] ),
+ ntohl ( target->dwords[0] ), ntohl ( target->dwords[1] ),
+ ntohl ( target->dwords[2] ), ntohl ( target->dwords[3] ) );
+
+ /* Preserve parameters required for boot firmware table */
+ memcpy ( &srpdev->initiator, initiator, sizeof ( srpdev->initiator ) );
+ memcpy ( &srpdev->target, target, sizeof ( srpdev->target ) );
+ memcpy ( &srpdev->lun, lun, sizeof ( srpdev->lun ) );
+
+ /* Attach to socket interface and initiate login */
+ intf_plug_plug ( &srpdev->socket, socket );
+ tag = srp_new_tag ( srpdev );
+ assert ( tag >= 0 ); /* Cannot fail when no commands in progress */
+ if ( ( rc = srp_login ( srpdev, initiator, target, tag ) ) != 0 )
+ goto err_login;
+
+ /* Attach SCSI device to parent interface */
+ if ( ( rc = scsi_open ( block, &srpdev->scsi, lun ) ) != 0 ) {
+ DBGC ( srpdev, "SRP %p could not create SCSI device: %s\n",
+ srpdev, strerror ( rc ) );
+ goto err_scsi_open;
+ }
+
+ /* Mortalise self and return */
+ ref_put ( &srpdev->refcnt );
+ return 0;
+
+ err_scsi_open:
+ err_login:
+ srpdev_close ( srpdev, rc );
+ ref_put ( &srpdev->refcnt );
+ err_zalloc:
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bus/eisa.c b/src/VBox/Devices/PC/ipxe/src/drivers/bus/eisa.c
new file mode 100644
index 00000000..a4efe262
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bus/eisa.c
@@ -0,0 +1,182 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/io.h>
+#include <unistd.h>
+#include <ipxe/eisa.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+static void eisabus_remove ( struct root_device *rootdev );
+
+/**
+ * Reset and enable/disable an EISA device
+ *
+ * @v eisa EISA device
+ * @v enabled 1=enable, 0=disable
+ */
+void eisa_device_enabled ( struct eisa_device *eisa, int enabled ) {
+ /* Set reset line high for 1000 µs. Spec says 500 µs, but
+ * this doesn't work for all cards, so we are conservative.
+ */
+ outb ( EISA_CMD_RESET, eisa->ioaddr + EISA_GLOBAL_CONFIG );
+ udelay ( 1000 ); /* Must wait 800 */
+
+ /* Set reset low and write a 1 to ENABLE. Delay again, in
+ * case the card takes a while to wake up.
+ */
+ outb ( enabled ? EISA_CMD_ENABLE : 0,
+ eisa->ioaddr + EISA_GLOBAL_CONFIG );
+ udelay ( 1000 ); /* Must wait 800 */
+
+ DBG ( "EISA %s device %02x\n", ( enabled ? "enabled" : "disabled" ),
+ eisa->slot );
+}
+
+/**
+ * Probe an EISA device
+ *
+ * @v eisa EISA device
+ * @ret rc Return status code
+ *
+ * Searches for a driver for the EISA device. If a driver is found,
+ * its probe() routine is called.
+ */
+static int eisa_probe ( struct eisa_device *eisa ) {
+ struct eisa_driver *driver;
+ struct eisa_device_id *id;
+ unsigned int i;
+ int rc;
+
+ DBG ( "Adding EISA device %02x (%04x:%04x (\"%s\") io %x)\n",
+ eisa->slot, eisa->vendor_id, eisa->prod_id,
+ isa_id_string ( eisa->vendor_id, eisa->prod_id ), eisa->ioaddr );
+
+ for_each_table_entry ( driver, EISA_DRIVERS ) {
+ for ( i = 0 ; i < driver->id_count ; i++ ) {
+ id = &driver->ids[i];
+ if ( id->vendor_id != eisa->vendor_id )
+ continue;
+ if ( ISA_PROD_ID ( id->prod_id ) !=
+ ISA_PROD_ID ( eisa->prod_id ) )
+ continue;
+ eisa->driver = driver;
+ eisa->dev.driver_name = id->name;
+ DBG ( "...using driver %s\n", eisa->dev.driver_name );
+ if ( ( rc = driver->probe ( eisa, id ) ) != 0 ) {
+ DBG ( "......probe failed\n" );
+ continue;
+ }
+ return 0;
+ }
+ }
+
+ DBG ( "...no driver found\n" );
+ return -ENOTTY;
+}
+
+/**
+ * Remove an EISA device
+ *
+ * @v eisa EISA device
+ */
+static void eisa_remove ( struct eisa_device *eisa ) {
+ eisa->driver->remove ( eisa );
+ DBG ( "Removed EISA device %02x\n", eisa->slot );
+}
+
+/**
+ * Probe EISA root bus
+ *
+ * @v rootdev EISA bus root device
+ *
+ * Scans the EISA bus for devices and registers all devices it can
+ * find.
+ */
+static int eisabus_probe ( struct root_device *rootdev ) {
+ struct eisa_device *eisa = NULL;
+ unsigned int slot;
+ int rc;
+
+ for ( slot = EISA_MIN_SLOT ; slot <= EISA_MAX_SLOT ; slot++ ) {
+ /* Allocate struct eisa_device */
+ if ( ! eisa )
+ eisa = malloc ( sizeof ( *eisa ) );
+ if ( ! eisa ) {
+ rc = -ENOMEM;
+ goto err;
+ }
+ memset ( eisa, 0, sizeof ( *eisa ) );
+ eisa->slot = slot;
+ eisa->ioaddr = EISA_SLOT_BASE ( eisa->slot );
+
+ /* Test for board present */
+ outb ( 0xff, eisa->ioaddr + EISA_VENDOR_ID );
+ eisa->vendor_id =
+ le16_to_cpu ( inw ( eisa->ioaddr + EISA_VENDOR_ID ) );
+ eisa->prod_id =
+ le16_to_cpu ( inw ( eisa->ioaddr + EISA_PROD_ID ) );
+ if ( eisa->vendor_id & 0x80 ) {
+ /* No board present */
+ continue;
+ }
+
+ /* Add to device hierarchy */
+ snprintf ( eisa->dev.name, sizeof ( eisa->dev.name ),
+ "EISA%02x", slot );
+ eisa->dev.desc.bus_type = BUS_TYPE_EISA;
+ eisa->dev.desc.vendor = eisa->vendor_id;
+ eisa->dev.desc.device = eisa->prod_id;
+ eisa->dev.parent = &rootdev->dev;
+ list_add ( &eisa->dev.siblings, &rootdev->dev.children );
+ INIT_LIST_HEAD ( &eisa->dev.children );
+
+ /* Look for a driver */
+ if ( eisa_probe ( eisa ) == 0 ) {
+ /* eisadev registered, we can drop our ref */
+ eisa = NULL;
+ } else {
+ /* Not registered; re-use struct */
+ list_del ( &eisa->dev.siblings );
+ }
+ }
+
+ free ( eisa );
+ return 0;
+
+ err:
+ free ( eisa );
+ eisabus_remove ( rootdev );
+ return rc;
+}
+
+/**
+ * Remove EISA root bus
+ *
+ * @v rootdev EISA bus root device
+ */
+static void eisabus_remove ( struct root_device *rootdev ) {
+ struct eisa_device *eisa;
+ struct eisa_device *tmp;
+
+ list_for_each_entry_safe ( eisa, tmp, &rootdev->dev.children,
+ dev.siblings ) {
+ eisa_remove ( eisa );
+ list_del ( &eisa->dev.siblings );
+ free ( eisa );
+ }
+}
+
+/** EISA bus root device driver */
+static struct root_driver eisa_root_driver = {
+ .probe = eisabus_probe,
+ .remove = eisabus_remove,
+};
+
+/** EISA bus root device */
+struct root_device eisa_root_device __root_device = {
+ .dev = { .name = "EISA" },
+ .driver = &eisa_root_driver,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bus/isa.c b/src/VBox/Devices/PC/ipxe/src/drivers/bus/isa.c
new file mode 100644
index 00000000..9b562c66
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bus/isa.c
@@ -0,0 +1,173 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/io.h>
+#include <ipxe/isa.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * isa.c implements a "classical" port-scanning method of ISA device
+ * detection. The driver must provide a list of probe addresses
+ * (probe_addrs), together with a function (probe_addr) that can be
+ * used to test for the physical presence of a device at any given
+ * address.
+ *
+ * Note that this should probably be considered the "last resort" for
+ * device probing. If the card supports ISAPnP or EISA, use that
+ * instead. Some cards (e.g. the 3c509) implement a proprietary
+ * ISAPnP-like mechanism.
+ *
+ * The ISA probe address list can be overridden by config.h; if the
+ * user specifies ISA_PROBE_ADDRS then that list will be used first.
+ * (If ISA_PROBE_ONLY is defined, the driver's own list will never be
+ * used).
+ */
+
+/*
+ * User-supplied probe address list
+ *
+ */
+static isa_probe_addr_t isa_extra_probe_addrs[] = {
+#ifdef ISA_PROBE_ADDRS
+ ISA_PROBE_ADDRS
+#endif
+};
+#define ISA_EXTRA_PROBE_ADDR_COUNT \
+ ( sizeof ( isa_extra_probe_addrs ) / sizeof ( isa_extra_probe_addrs[0] ) )
+
+#define ISA_IOIDX_MIN( driver ) ( -ISA_EXTRA_PROBE_ADDR_COUNT )
+#ifdef ISA_PROBE_ONLY
+#define ISA_IOIDX_MAX( driver ) ( -1 )
+#else
+#define ISA_IOIDX_MAX( driver ) ( (int) (driver)->addr_count - 1 )
+#endif
+
+#define ISA_IOADDR( driver, ioidx ) \
+ ( ( (ioidx) < 0 ) ? \
+ isa_extra_probe_addrs[ (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ] : \
+ (driver)->probe_addrs[(ioidx)] )
+
+static void isabus_remove ( struct root_device *rootdev );
+
+/**
+ * Probe an ISA device
+ *
+ * @v isa ISA device
+ * @ret rc Return status code
+ */
+static int isa_probe ( struct isa_device *isa ) {
+ int rc;
+
+ DBG ( "Trying ISA driver %s at I/O %04x\n",
+ isa->driver->name, isa->ioaddr );
+
+ if ( ( rc = isa->driver->probe ( isa ) ) != 0 ) {
+ DBG ( "...probe failed\n" );
+ return rc;
+ }
+
+ DBG ( "...device found\n" );
+ return 0;
+}
+
+/**
+ * Remove an ISA device
+ *
+ * @v isa ISA device
+ */
+static void isa_remove ( struct isa_device *isa ) {
+ isa->driver->remove ( isa );
+ DBG ( "Removed ISA%04x\n", isa->ioaddr );
+}
+
+/**
+ * Probe ISA root bus
+ *
+ * @v rootdev ISA bus root device
+ *
+ * Scans the ISA bus for devices and registers all devices it can
+ * find.
+ */
+static int isabus_probe ( struct root_device *rootdev ) {
+ struct isa_device *isa = NULL;
+ struct isa_driver *driver;
+ int ioidx;
+ int rc;
+
+ for_each_table_entry ( driver, ISA_DRIVERS ) {
+ for ( ioidx = ISA_IOIDX_MIN ( driver ) ;
+ ioidx <= ISA_IOIDX_MAX ( driver ) ; ioidx++ ) {
+ /* Allocate struct isa_device */
+ if ( ! isa )
+ isa = malloc ( sizeof ( *isa ) );
+ if ( ! isa ) {
+ rc = -ENOMEM;
+ goto err;
+ }
+ memset ( isa, 0, sizeof ( *isa ) );
+ isa->driver = driver;
+ isa->ioaddr = ISA_IOADDR ( driver, ioidx );
+
+ /* Add to device hierarchy */
+ snprintf ( isa->dev.name, sizeof ( isa->dev.name ),
+ "ISA%04x", isa->ioaddr );
+ isa->dev.driver_name = driver->name;
+ isa->dev.desc.bus_type = BUS_TYPE_ISA;
+ isa->dev.desc.vendor = driver->vendor_id;
+ isa->dev.desc.device = driver->prod_id;
+ isa->dev.parent = &rootdev->dev;
+ list_add ( &isa->dev.siblings,
+ &rootdev->dev.children );
+ INIT_LIST_HEAD ( &isa->dev.children );
+
+ /* Try probing at this I/O address */
+ if ( isa_probe ( isa ) == 0 ) {
+ /* isadev registered, we can drop our ref */
+ isa = NULL;
+ } else {
+ /* Not registered; re-use struct */
+ list_del ( &isa->dev.siblings );
+ }
+ }
+ }
+
+ free ( isa );
+ return 0;
+
+ err:
+ free ( isa );
+ isabus_remove ( rootdev );
+ return rc;
+}
+
+/**
+ * Remove ISA root bus
+ *
+ * @v rootdev ISA bus root device
+ */
+static void isabus_remove ( struct root_device *rootdev ) {
+ struct isa_device *isa;
+ struct isa_device *tmp;
+
+ list_for_each_entry_safe ( isa, tmp, &rootdev->dev.children,
+ dev.siblings ) {
+ isa_remove ( isa );
+ list_del ( &isa->dev.siblings );
+ free ( isa );
+ }
+}
+
+/** ISA bus root device driver */
+static struct root_driver isa_root_driver = {
+ .probe = isabus_probe,
+ .remove = isabus_remove,
+};
+
+/** ISA bus root device */
+struct root_device isa_root_device __root_device = {
+ .dev = { .name = "ISA" },
+ .driver = &isa_root_driver,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bus/isa_ids.c b/src/VBox/Devices/PC/ipxe/src/drivers/bus/isa_ids.c
new file mode 100644
index 00000000..e72b233f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bus/isa_ids.c
@@ -0,0 +1,26 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <byteswap.h>
+#include <ipxe/isa_ids.h>
+
+/*
+ * EISA and ISAPnP IDs are actually mildly human readable, though in a
+ * somewhat brain-damaged way.
+ *
+ */
+char * isa_id_string ( unsigned int vendor, unsigned int product ) {
+ static char buf[7];
+ int i;
+
+ /* Vendor ID is a compressed ASCII string */
+ vendor = bswap_16 ( vendor );
+ for ( i = 2 ; i >= 0 ; i-- ) {
+ buf[i] = ( 'A' - 1 + ( vendor & 0x1f ) );
+ vendor >>= 5;
+ }
+
+ /* Product ID is a 4-digit hex string */
+ sprintf ( &buf[3], "%04x", bswap_16 ( product ) );
+
+ return buf;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bus/isapnp.c b/src/VBox/Devices/PC/ipxe/src/drivers/bus/isapnp.c
new file mode 100644
index 00000000..c6b81679
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bus/isapnp.c
@@ -0,0 +1,764 @@
+/**************************************************************************
+*
+* isapnp.c -- Etherboot isapnp support for the 3Com 3c515
+* Written 2002-2003 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code:
+* Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk)
+*
+*
+* REVISION HISTORY:
+* ================
+* Version 0.1 April 26, 2002 TJL
+* Version 0.2 01/08/2003 TJL Moved outside the 3c515.c driver file
+* Version 0.3 Sept 23, 2003 timlegge Change delay to currticks
+*
+*
+* Generalised into an ISAPnP bus that can be used by more than just
+* the 3c515 by Michael Brown <mbrown@fensystems.co.uk>
+*
+***************************************************************************/
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+/** @file
+ *
+ * ISAPnP bus support
+ *
+ * Etherboot orignally gained ISAPnP support in a very limited way for
+ * the 3c515 NIC. The current implementation is almost a complete
+ * rewrite based on the ISAPnP specification, with passing reference
+ * to the Linux ISAPnP code.
+ *
+ * There can be only one ISAPnP bus in a system. Once the read port
+ * is known and all cards have been allocated CSNs, there's nothing to
+ * be gained by re-scanning for cards.
+ *
+ * External code (e.g. the ISAPnP ROM prefix) may already know the
+ * read port address, in which case it can store it in
+ * #isapnp_read_port. Note that setting the read port address in this
+ * way will prevent further isolation from taking place; you should
+ * set the read port address only if you know that devices have
+ * already been allocated CSNs.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/io.h>
+#include <unistd.h>
+#include <ipxe/isapnp.h>
+
+/**
+ * ISAPnP Read Port address.
+ *
+ * ROM prefix may be able to set this address, which is why this is
+ * non-static.
+ */
+uint16_t isapnp_read_port;
+
+static void isapnpbus_remove ( struct root_device *rootdev );
+
+/*
+ * ISAPnP utility functions
+ *
+ */
+
+#define ISAPNP_CARD_ID_FMT "ID %04x:%04x (\"%s\") serial %x"
+#define ISAPNP_CARD_ID_DATA(identifier) \
+ (identifier)->vendor_id, (identifier)->prod_id, \
+ isa_id_string ( (identifier)->vendor_id, (identifier)->prod_id ), \
+ (identifier)->serial
+#define ISAPNP_DEV_ID_FMT "ID %04x:%04x (\"%s\")"
+#define ISAPNP_DEV_ID_DATA(isapnp) \
+ (isapnp)->vendor_id, (isapnp)->prod_id, \
+ isa_id_string ( (isapnp)->vendor_id, (isapnp)->prod_id )
+
+static inline void isapnp_write_address ( unsigned int address ) {
+ outb ( address, ISAPNP_ADDRESS );
+}
+
+static inline void isapnp_write_data ( unsigned int data ) {
+ outb ( data, ISAPNP_WRITE_DATA );
+}
+
+static inline unsigned int isapnp_read_data ( void ) {
+ return inb ( isapnp_read_port );
+}
+
+static inline void isapnp_write_byte ( unsigned int address,
+ unsigned int value ) {
+ isapnp_write_address ( address );
+ isapnp_write_data ( value );
+}
+
+static inline unsigned int isapnp_read_byte ( unsigned int address ) {
+ isapnp_write_address ( address );
+ return isapnp_read_data ();
+}
+
+static inline unsigned int isapnp_read_word ( unsigned int address ) {
+ /* Yes, they're in big-endian order */
+ return ( ( isapnp_read_byte ( address ) << 8 )
+ | isapnp_read_byte ( address + 1 ) );
+}
+
+/** Inform cards of a new read port address */
+static inline void isapnp_set_read_port ( void ) {
+ isapnp_write_byte ( ISAPNP_READPORT, ( isapnp_read_port >> 2 ) );
+}
+
+/**
+ * Enter the Isolation state.
+ *
+ * Only cards currently in the Sleep state will respond to this
+ * command.
+ */
+static inline void isapnp_serialisolation ( void ) {
+ isapnp_write_address ( ISAPNP_SERIALISOLATION );
+}
+
+/**
+ * Enter the Wait for Key state.
+ *
+ * All cards will respond to this command, regardless of their current
+ * state.
+ */
+static inline void isapnp_wait_for_key ( void ) {
+ isapnp_write_byte ( ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_WAIT_FOR_KEY );
+}
+
+/**
+ * Reset (i.e. remove) Card Select Number.
+ *
+ * Only cards currently in the Sleep state will respond to this
+ * command.
+ */
+static inline void isapnp_reset_csn ( void ) {
+ isapnp_write_byte ( ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_RESET_CSN );
+}
+
+/**
+ * Place a specified card into the Config state.
+ *
+ * @v csn Card Select Number
+ * @ret None -
+ * @err None -
+ *
+ * Only cards currently in the Sleep, Isolation, or Config states will
+ * respond to this command. The card that has the specified CSN will
+ * enter the Config state, all other cards will enter the Sleep state.
+ */
+static inline void isapnp_wake ( uint8_t csn ) {
+ isapnp_write_byte ( ISAPNP_WAKE, csn );
+}
+
+static inline unsigned int isapnp_read_resourcedata ( void ) {
+ return isapnp_read_byte ( ISAPNP_RESOURCEDATA );
+}
+
+static inline unsigned int isapnp_read_status ( void ) {
+ return isapnp_read_byte ( ISAPNP_STATUS );
+}
+
+/**
+ * Assign a Card Select Number to a card, and enter the Config state.
+ *
+ * @v csn Card Select Number
+ *
+ * Only cards in the Isolation state will respond to this command.
+ * The isolation protocol is designed so that only one card will
+ * remain in the Isolation state by the time the isolation protocol
+ * completes.
+ */
+static inline void isapnp_write_csn ( unsigned int csn ) {
+ isapnp_write_byte ( ISAPNP_CARDSELECTNUMBER, csn );
+}
+
+static inline void isapnp_logicaldevice ( unsigned int logdev ) {
+ isapnp_write_byte ( ISAPNP_LOGICALDEVICENUMBER, logdev );
+}
+
+static inline void isapnp_activate ( unsigned int logdev ) {
+ isapnp_logicaldevice ( logdev );
+ isapnp_write_byte ( ISAPNP_ACTIVATE, 1 );
+}
+
+static inline void isapnp_deactivate ( unsigned int logdev ) {
+ isapnp_logicaldevice ( logdev );
+ isapnp_write_byte ( ISAPNP_ACTIVATE, 0 );
+}
+
+static inline unsigned int isapnp_read_iobase ( unsigned int index ) {
+ return isapnp_read_word ( ISAPNP_IOBASE ( index ) );
+}
+
+static inline unsigned int isapnp_read_irqno ( unsigned int index ) {
+ return isapnp_read_byte ( ISAPNP_IRQNO ( index ) );
+}
+
+static void isapnp_delay ( void ) {
+ udelay ( 1000 );
+}
+
+/**
+ * Linear feedback shift register.
+ *
+ * @v lfsr Current value of the LFSR
+ * @v input_bit Current input bit to the LFSR
+ * @ret lfsr Next value of the LFSR
+ *
+ * This routine implements the linear feedback shift register as
+ * described in Appendix B of the PnP ISA spec. The hardware
+ * implementation uses eight D-type latches and two XOR gates. I
+ * think this is probably the smallest possible implementation in
+ * software. Six instructions when input_bit is a constant 0 (for
+ * isapnp_send_key). :)
+ */
+static inline unsigned int isapnp_lfsr_next ( unsigned int lfsr,
+ unsigned int input_bit ) {
+ register uint8_t lfsr_next;
+
+ lfsr_next = lfsr >> 1;
+ lfsr_next |= ( ( ( lfsr ^ lfsr_next ) ^ input_bit ) ) << 7;
+ return lfsr_next;
+}
+
+/**
+ * Send the ISAPnP initiation key.
+ *
+ * Sending the key causes all ISAPnP cards that are currently in the
+ * Wait for Key state to transition into the Sleep state.
+ */
+static void isapnp_send_key ( void ) {
+ unsigned int i;
+ unsigned int lfsr;
+
+ isapnp_delay();
+ isapnp_write_address ( 0x00 );
+ isapnp_write_address ( 0x00 );
+
+ lfsr = ISAPNP_LFSR_SEED;
+ for ( i = 0 ; i < 32 ; i++ ) {
+ isapnp_write_address ( lfsr );
+ lfsr = isapnp_lfsr_next ( lfsr, 0 );
+ }
+}
+
+/**
+ * Compute ISAPnP identifier checksum
+ *
+ * @v identifier ISAPnP identifier
+ * @ret checksum Expected checksum value
+ */
+static unsigned int isapnp_checksum ( struct isapnp_identifier *identifier ) {
+ unsigned int i, j;
+ unsigned int lfsr;
+ unsigned int byte;
+
+ lfsr = ISAPNP_LFSR_SEED;
+ for ( i = 0 ; i < 8 ; i++ ) {
+ byte = * ( ( ( uint8_t * ) identifier ) + i );
+ for ( j = 0 ; j < 8 ; j++ ) {
+ lfsr = isapnp_lfsr_next ( lfsr, byte );
+ byte >>= 1;
+ }
+ }
+ return lfsr;
+}
+
+/*
+ * Read a byte of resource data from the current location
+ *
+ * @ret byte Byte of resource data
+ */
+static inline unsigned int isapnp_peek_byte ( void ) {
+ unsigned int i;
+
+ /* Wait for data to be ready */
+ for ( i = 0 ; i < 20 ; i++ ) {
+ if ( isapnp_read_status() & 0x01 ) {
+ /* Byte ready - read it */
+ return isapnp_read_resourcedata();
+ }
+ isapnp_delay();
+ }
+ /* Data never became ready - return 0xff */
+ return 0xff;
+}
+
+/**
+ * Read resource data.
+ *
+ * @v buf Buffer in which to store data, or NULL
+ * @v bytes Number of bytes to read
+ *
+ * Resource data is read from the current location. If #buf is NULL,
+ * the data is discarded.
+ */
+static void isapnp_peek ( void *buf, size_t len ) {
+ unsigned int i;
+ unsigned int byte;
+
+ for ( i = 0 ; i < len ; i++) {
+ byte = isapnp_peek_byte();
+ if ( buf )
+ * ( ( uint8_t * ) buf + i ) = byte;
+ }
+}
+
+/**
+ * Find a tag within the resource data.
+ *
+ * @v wanted_tag The tag that we're looking for
+ * @v buf Buffer in which to store the tag's contents
+ * @v len Length of buffer
+ * @ret rc Return status code
+ *
+ * Scan through the resource data until we find a particular tag, and
+ * read its contents into a buffer.
+ */
+static int isapnp_find_tag ( unsigned int wanted_tag, void *buf, size_t len ) {
+ unsigned int tag;
+ unsigned int tag_len;
+
+ DBG2 ( "ISAPnP read tag" );
+ do {
+ tag = isapnp_peek_byte();
+ if ( ISAPNP_IS_SMALL_TAG ( tag ) ) {
+ tag_len = ISAPNP_SMALL_TAG_LEN ( tag );
+ tag = ISAPNP_SMALL_TAG_NAME ( tag );
+ } else {
+ tag_len = ( isapnp_peek_byte() +
+ ( isapnp_peek_byte() << 8 ) );
+ tag = ISAPNP_LARGE_TAG_NAME ( tag );
+ }
+ DBG2 ( " %02x (%02x)", tag, tag_len );
+ if ( tag == wanted_tag ) {
+ if ( len > tag_len )
+ len = tag_len;
+ isapnp_peek ( buf, len );
+ DBG2 ( "\n" );
+ return 0;
+ } else {
+ isapnp_peek ( NULL, tag_len );
+ }
+ } while ( tag != ISAPNP_TAG_END );
+ DBG2 ( "\n" );
+ return -ENOENT;
+}
+
+/**
+ * Find specified Logical Device ID tag
+ *
+ * @v logdev Logical device ID
+ * @v logdevid Logical device ID structure to fill in
+ * @ret rc Return status code
+ */
+static int isapnp_find_logdevid ( unsigned int logdev,
+ struct isapnp_logdevid *logdevid ) {
+ unsigned int i;
+ int rc;
+
+ for ( i = 0 ; i <= logdev ; i++ ) {
+ if ( ( rc = isapnp_find_tag ( ISAPNP_TAG_LOGDEVID, logdevid,
+ sizeof ( *logdevid ) ) ) != 0 )
+ return rc;
+ }
+ return 0;
+}
+
+/**
+ * Try isolating ISAPnP cards at the current read port.
+ *
+ * @ret \>0 Number of ISAPnP cards found
+ * @ret 0 There are no ISAPnP cards in the system
+ * @ret \<0 A conflict was detected; try a new read port
+ * @err None -
+ *
+ * The state diagram on page 18 (PDF page 24) of the PnP ISA spec
+ * gives the best overview of what happens here.
+ */
+static int isapnp_try_isolate ( void ) {
+ struct isapnp_identifier identifier;
+ unsigned int i, j;
+ unsigned int seen_55aa, seen_life;
+ unsigned int csn = 0;
+ unsigned int data;
+ unsigned int byte;
+
+ DBG ( "ISAPnP attempting isolation at read port %04x\n",
+ isapnp_read_port );
+
+ /* Place all cards into the Sleep state, whatever state
+ * they're currently in.
+ */
+ isapnp_wait_for_key();
+ isapnp_send_key();
+
+ /* Reset all assigned CSNs */
+ isapnp_reset_csn();
+ isapnp_delay();
+ isapnp_delay();
+
+ /* Place all cards into the Isolation state */
+ isapnp_wait_for_key ();
+ isapnp_send_key();
+ isapnp_wake ( 0x00 );
+
+ /* Set the read port */
+ isapnp_set_read_port();
+ isapnp_delay();
+
+ while ( 1 ) {
+
+ /* All cards that do not have assigned CSNs are
+ * currently in the Isolation state, each time we go
+ * through this loop.
+ */
+
+ /* Initiate serial isolation */
+ isapnp_serialisolation();
+ isapnp_delay();
+
+ /* Read identifier serially via the ISAPnP read port. */
+ memset ( &identifier, 0, sizeof ( identifier ) );
+ seen_55aa = seen_life = 0;
+ for ( i = 0 ; i < 9 ; i++ ) {
+ byte = 0;
+ for ( j = 0 ; j < 8 ; j++ ) {
+ data = isapnp_read_data();
+ isapnp_delay();
+ data = ( ( data << 8 ) | isapnp_read_data() );
+ isapnp_delay();
+ byte >>= 1;
+ if ( data != 0xffff ) {
+ seen_life++;
+ if ( data == 0x55aa ) {
+ byte |= 0x80;
+ seen_55aa++;
+ }
+ }
+ }
+ *( ( ( uint8_t * ) &identifier ) + i ) = byte;
+ }
+
+ /* If we didn't see any 55aa patterns, stop here */
+ if ( ! seen_55aa ) {
+ if ( csn ) {
+ DBG ( "ISAPnP found no more cards\n" );
+ } else {
+ if ( seen_life ) {
+ DBG ( "ISAPnP saw life but no cards, "
+ "trying new read port\n" );
+ csn = -1;
+ } else {
+ DBG ( "ISAPnP saw no signs of life, "
+ "abandoning isolation\n" );
+ }
+ }
+ break;
+ }
+
+ /* If the checksum was invalid stop here */
+ if ( identifier.checksum != isapnp_checksum ( &identifier) ) {
+ DBG ( "ISAPnP found malformed card "
+ ISAPNP_CARD_ID_FMT "\n with checksum %02x "
+ "(should be %02x), trying new read port\n",
+ ISAPNP_CARD_ID_DATA ( &identifier ),
+ identifier.checksum,
+ isapnp_checksum ( &identifier) );
+ csn = -1;
+ break;
+ }
+
+ /* Give the device a CSN */
+ csn++;
+ DBG ( "ISAPnP found card " ISAPNP_CARD_ID_FMT
+ ", assigning CSN %02x\n",
+ ISAPNP_CARD_ID_DATA ( &identifier ), csn );
+
+ isapnp_write_csn ( csn );
+ isapnp_delay();
+
+ /* Send this card back to Sleep and force all cards
+ * without a CSN into Isolation state
+ */
+ isapnp_wake ( 0x00 );
+ isapnp_delay();
+ }
+
+ /* Place all cards in Wait for Key state */
+ isapnp_wait_for_key();
+
+ /* Return number of cards found */
+ if ( csn > 0 ) {
+ DBG ( "ISAPnP found %d cards at read port %04x\n",
+ csn, isapnp_read_port );
+ }
+ return csn;
+}
+
+/**
+ * Find a valid read port and isolate all ISAPnP cards.
+ *
+ */
+static void isapnp_isolate ( void ) {
+ for ( isapnp_read_port = ISAPNP_READ_PORT_START ;
+ isapnp_read_port <= ISAPNP_READ_PORT_MAX ;
+ isapnp_read_port += ISAPNP_READ_PORT_STEP ) {
+ /* Avoid problematic locations such as the NE2000
+ * probe space
+ */
+ if ( ( isapnp_read_port >= 0x280 ) &&
+ ( isapnp_read_port <= 0x380 ) )
+ continue;
+
+ /* If we detect any ISAPnP cards at this location, stop */
+ if ( isapnp_try_isolate() >= 0 )
+ return;
+ }
+}
+
+/**
+ * Activate or deactivate an ISAPnP device.
+ *
+ * @v isapnp ISAPnP device
+ * @v activation True to enable, False to disable the device
+ * @ret None -
+ * @err None -
+ *
+ * This routine simply activates the device in its current
+ * configuration, or deactivates the device. It does not attempt any
+ * kind of resource arbitration.
+ *
+ */
+void isapnp_device_activation ( struct isapnp_device *isapnp,
+ int activation ) {
+ /* Wake the card and select the logical device */
+ isapnp_wait_for_key ();
+ isapnp_send_key ();
+ isapnp_wake ( isapnp->csn );
+ isapnp_logicaldevice ( isapnp->logdev );
+
+ /* Activate/deactivate the logical device */
+ isapnp_activate ( activation );
+ isapnp_delay();
+
+ /* Return all cards to Wait for Key state */
+ isapnp_wait_for_key ();
+
+ DBG ( "ISAPnP %s device %02x:%02x\n",
+ ( activation ? "activated" : "deactivated" ),
+ isapnp->csn, isapnp->logdev );
+}
+
+/**
+ * Probe an ISAPnP device
+ *
+ * @v isapnp ISAPnP device
+ * @ret rc Return status code
+ *
+ * Searches for a driver for the ISAPnP device. If a driver is found,
+ * its probe() routine is called.
+ */
+static int isapnp_probe ( struct isapnp_device *isapnp ) {
+ struct isapnp_driver *driver;
+ struct isapnp_device_id *id;
+ unsigned int i;
+ int rc;
+
+ DBG ( "Adding ISAPnP device %02x:%02x (%04x:%04x (\"%s\") "
+ "io %x irq %d)\n", isapnp->csn, isapnp->logdev,
+ isapnp->vendor_id, isapnp->prod_id,
+ isa_id_string ( isapnp->vendor_id, isapnp->prod_id ),
+ isapnp->ioaddr, isapnp->irqno );
+
+ for_each_table_entry ( driver, ISAPNP_DRIVERS ) {
+ for ( i = 0 ; i < driver->id_count ; i++ ) {
+ id = &driver->ids[i];
+ if ( id->vendor_id != isapnp->vendor_id )
+ continue;
+ if ( ISA_PROD_ID ( id->prod_id ) !=
+ ISA_PROD_ID ( isapnp->prod_id ) )
+ continue;
+ isapnp->driver = driver;
+ isapnp->dev.driver_name = id->name;
+ DBG ( "...using driver %s\n", isapnp->dev.driver_name );
+ if ( ( rc = driver->probe ( isapnp, id ) ) != 0 ) {
+ DBG ( "......probe failed\n" );
+ continue;
+ }
+ return 0;
+ }
+ }
+
+ DBG ( "...no driver found\n" );
+ return -ENOTTY;
+}
+
+/**
+ * Remove an ISAPnP device
+ *
+ * @v isapnp ISAPnP device
+ */
+static void isapnp_remove ( struct isapnp_device *isapnp ) {
+ isapnp->driver->remove ( isapnp );
+ DBG ( "Removed ISAPnP device %02x:%02x\n",
+ isapnp->csn, isapnp->logdev );
+}
+
+/**
+ * Probe ISAPnP root bus
+ *
+ * @v rootdev ISAPnP bus root device
+ *
+ * Scans the ISAPnP bus for devices and registers all devices it can
+ * find.
+ */
+static int isapnpbus_probe ( struct root_device *rootdev ) {
+ struct isapnp_device *isapnp = NULL;
+ struct isapnp_identifier identifier;
+ struct isapnp_logdevid logdevid;
+ unsigned int csn;
+ unsigned int logdev;
+ int rc;
+
+ /* Perform isolation if it hasn't yet been done */
+ if ( ! isapnp_read_port )
+ isapnp_isolate();
+
+ for ( csn = 1 ; csn <= 0xff ; csn++ ) {
+ for ( logdev = 0 ; logdev <= 0xff ; logdev++ ) {
+
+ /* Allocate struct isapnp_device */
+ if ( ! isapnp )
+ isapnp = malloc ( sizeof ( *isapnp ) );
+ if ( ! isapnp ) {
+ rc = -ENOMEM;
+ goto err;
+ }
+ memset ( isapnp, 0, sizeof ( *isapnp ) );
+ isapnp->csn = csn;
+ isapnp->logdev = logdev;
+
+ /* Wake the card */
+ isapnp_wait_for_key();
+ isapnp_send_key();
+ isapnp_wake ( csn );
+
+ /* Read the card identifier */
+ isapnp_peek ( &identifier, sizeof ( identifier ) );
+
+ /* No card with this CSN; stop here */
+ if ( identifier.vendor_id & 0x80 )
+ goto done;
+
+ /* Find the Logical Device ID tag */
+ if ( ( rc = isapnp_find_logdevid ( logdev,
+ &logdevid ) ) != 0){
+ /* No more logical devices; go to next CSN */
+ break;
+ }
+
+ /* Select the logical device */
+ isapnp_logicaldevice ( logdev );
+
+ /* Populate struct isapnp_device */
+ isapnp->vendor_id = logdevid.vendor_id;
+ isapnp->prod_id = logdevid.prod_id;
+ isapnp->ioaddr = isapnp_read_iobase ( 0 );
+ isapnp->irqno = isapnp_read_irqno ( 0 );
+
+ /* Return all cards to Wait for Key state */
+ isapnp_wait_for_key();
+
+ /* Add to device hierarchy */
+ snprintf ( isapnp->dev.name,
+ sizeof ( isapnp->dev.name ),
+ "ISAPnP%02x:%02x", csn, logdev );
+ isapnp->dev.desc.bus_type = BUS_TYPE_ISAPNP;
+ isapnp->dev.desc.vendor = isapnp->vendor_id;
+ isapnp->dev.desc.device = isapnp->prod_id;
+ isapnp->dev.desc.ioaddr = isapnp->ioaddr;
+ isapnp->dev.desc.irq = isapnp->irqno;
+ isapnp->dev.parent = &rootdev->dev;
+ list_add ( &isapnp->dev.siblings,
+ &rootdev->dev.children );
+ INIT_LIST_HEAD ( &isapnp->dev.children );
+
+ /* Look for a driver */
+ if ( isapnp_probe ( isapnp ) == 0 ) {
+ /* isapnpdev registered, we can drop our ref */
+ isapnp = NULL;
+ } else {
+ /* Not registered; re-use struct */
+ list_del ( &isapnp->dev.siblings );
+ }
+ }
+ }
+
+ done:
+ free ( isapnp );
+ return 0;
+
+ err:
+ free ( isapnp );
+ isapnpbus_remove ( rootdev );
+ return rc;
+}
+
+/**
+ * Remove ISAPnP root bus
+ *
+ * @v rootdev ISAPnP bus root device
+ */
+static void isapnpbus_remove ( struct root_device *rootdev ) {
+ struct isapnp_device *isapnp;
+ struct isapnp_device *tmp;
+
+ list_for_each_entry_safe ( isapnp, tmp, &rootdev->dev.children,
+ dev.siblings ) {
+ isapnp_remove ( isapnp );
+ list_del ( &isapnp->dev.siblings );
+ free ( isapnp );
+ }
+}
+
+/** ISAPnP bus root device driver */
+static struct root_driver isapnp_root_driver = {
+ .probe = isapnpbus_probe,
+ .remove = isapnpbus_remove,
+};
+
+/** ISAPnP bus root device */
+struct root_device isapnp_root_device __root_device = {
+ .dev = { .name = "ISAPnP" },
+ .driver = &isapnp_root_driver,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bus/mca.c b/src/VBox/Devices/PC/ipxe/src/drivers/bus/mca.c
new file mode 100644
index 00000000..0405c3b8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bus/mca.c
@@ -0,0 +1,177 @@
+/*
+ * MCA bus driver code
+ *
+ * Abstracted from 3c509.c.
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/io.h>
+#include <ipxe/mca.h>
+
+static void mcabus_remove ( struct root_device *rootdev );
+
+/**
+ * Probe an MCA device
+ *
+ * @v mca MCA device
+ * @ret rc Return status code
+ *
+ * Searches for a driver for the MCA device. If a driver is found,
+ * its probe() routine is called.
+ */
+static int mca_probe ( struct mca_device *mca ) {
+ struct mca_driver *driver;
+ struct mca_device_id *id;
+ unsigned int i;
+ int rc;
+
+ DBG ( "Adding MCA slot %02x (ID %04x POS "
+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x)\n",
+ mca->slot, MCA_ID ( mca ),
+ mca->pos[0], mca->pos[1], mca->pos[2], mca->pos[3],
+ mca->pos[4], mca->pos[5], mca->pos[6], mca->pos[7] );
+
+ for_each_table_entry ( driver, MCA_DRIVERS ) {
+ for ( i = 0 ; i < driver->id_count ; i++ ) {
+ id = &driver->ids[i];
+ if ( id->id != MCA_ID ( mca ) )
+ continue;
+ mca->driver = driver;
+ mca->dev.driver_name = id->name;
+ DBG ( "...using driver %s\n", mca->dev.driver_name );
+ if ( ( rc = driver->probe ( mca, id ) ) != 0 ) {
+ DBG ( "......probe failed\n" );
+ continue;
+ }
+ return 0;
+ }
+ }
+
+ DBG ( "...no driver found\n" );
+ return -ENOTTY;
+}
+
+/**
+ * Remove an MCA device
+ *
+ * @v mca MCA device
+ */
+static void mca_remove ( struct mca_device *mca ) {
+ mca->driver->remove ( mca );
+ DBG ( "Removed MCA device %02x\n", mca->slot );
+}
+
+/**
+ * Probe MCA root bus
+ *
+ * @v rootdev MCA bus root device
+ *
+ * Scans the MCA bus for devices and registers all devices it can
+ * find.
+ */
+static int mcabus_probe ( struct root_device *rootdev ) {
+ struct mca_device *mca = NULL;
+ unsigned int slot;
+ int seen_non_ff;
+ unsigned int i;
+ int rc;
+
+ for ( slot = 0 ; slot <= MCA_MAX_SLOT_NR ; slot++ ) {
+ /* Allocate struct mca_device */
+ if ( ! mca )
+ mca = malloc ( sizeof ( *mca ) );
+ if ( ! mca ) {
+ rc = -ENOMEM;
+ goto err;
+ }
+ memset ( mca, 0, sizeof ( *mca ) );
+ mca->slot = slot;
+
+ /* Make sure motherboard setup is off */
+ outb_p ( 0xff, MCA_MOTHERBOARD_SETUP_REG );
+
+ /* Select the slot */
+ outb_p ( 0x8 | ( mca->slot & 0xf ), MCA_ADAPTER_SETUP_REG );
+
+ /* Read the POS registers */
+ seen_non_ff = 0;
+ for ( i = 0 ; i < ( sizeof ( mca->pos ) /
+ sizeof ( mca->pos[0] ) ) ; i++ ) {
+ mca->pos[i] = inb_p ( MCA_POS_REG ( i ) );
+ if ( mca->pos[i] != 0xff )
+ seen_non_ff = 1;
+ }
+
+ /* Kill all setup modes */
+ outb_p ( 0, MCA_ADAPTER_SETUP_REG );
+
+ /* If all POS registers are 0xff, this means there's no device
+ * present
+ */
+ if ( ! seen_non_ff )
+ continue;
+
+ /* Add to device hierarchy */
+ snprintf ( mca->dev.name, sizeof ( mca->dev.name ),
+ "MCA%02x", slot );
+ mca->dev.desc.bus_type = BUS_TYPE_MCA;
+ mca->dev.desc.vendor = GENERIC_MCA_VENDOR;
+ mca->dev.desc.device = MCA_ID ( mca );
+ mca->dev.parent = &rootdev->dev;
+ list_add ( &mca->dev.siblings, &rootdev->dev.children );
+ INIT_LIST_HEAD ( &mca->dev.children );
+
+ /* Look for a driver */
+ if ( mca_probe ( mca ) == 0 ) {
+ /* mcadev registered, we can drop our ref */
+ mca = NULL;
+ } else {
+ /* Not registered; re-use struct */
+ list_del ( &mca->dev.siblings );
+ }
+ }
+
+ free ( mca );
+ return 0;
+
+ err:
+ free ( mca );
+ mcabus_remove ( rootdev );
+ return rc;
+}
+
+/**
+ * Remove MCA root bus
+ *
+ * @v rootdev MCA bus root device
+ */
+static void mcabus_remove ( struct root_device *rootdev ) {
+ struct mca_device *mca;
+ struct mca_device *tmp;
+
+ list_for_each_entry_safe ( mca, tmp, &rootdev->dev.children,
+ dev.siblings ) {
+ mca_remove ( mca );
+ list_del ( &mca->dev.siblings );
+ free ( mca );
+ }
+}
+
+/** MCA bus root device driver */
+static struct root_driver mca_root_driver = {
+ .probe = mcabus_probe,
+ .remove = mcabus_remove,
+};
+
+/** MCA bus root device */
+struct root_device mca_root_device __root_device = {
+ .dev = { .name = "MCA" },
+ .driver = &mca_root_driver,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bus/pci.c b/src/VBox/Devices/PC/ipxe/src/drivers/bus/pci.c
new file mode 100644
index 00000000..3ae17e5c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bus/pci.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * Based in part on pci.c from Etherboot 5.4, by Ken Yap and David
+ * Munro, in turn based on the Linux kernel's PCI implementation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/tables.h>
+#include <ipxe/device.h>
+#include <ipxe/pci.h>
+
+/** @file
+ *
+ * PCI bus
+ *
+ */
+
+static void pcibus_remove ( struct root_device *rootdev );
+
+/**
+ * Read PCI BAR
+ *
+ * @v pci PCI device
+ * @v reg PCI register number
+ * @ret bar Base address register
+ *
+ * Reads the specified PCI base address register, including the flags
+ * portion. 64-bit BARs will be handled automatically. If the value
+ * of the 64-bit BAR exceeds the size of an unsigned long (i.e. if the
+ * high dword is non-zero on a 32-bit platform), then the value
+ * returned will be zero plus the flags for a 64-bit BAR. Unreachable
+ * 64-bit BARs are therefore returned as uninitialised 64-bit BARs.
+ */
+static unsigned long pci_bar ( struct pci_device *pci, unsigned int reg ) {
+ uint32_t low;
+ uint32_t high;
+
+ pci_read_config_dword ( pci, reg, &low );
+ if ( ( low & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK) )
+ == (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64) ){
+ pci_read_config_dword ( pci, reg + 4, &high );
+ if ( high ) {
+ if ( sizeof ( unsigned long ) > sizeof ( uint32_t ) ) {
+ return ( ( ( uint64_t ) high << 32 ) | low );
+ } else {
+ DBGC ( pci, PCI_FMT " unhandled 64-bit BAR "
+ "%08x%08x\n",
+ PCI_ARGS ( pci ), high, low );
+ return PCI_BASE_ADDRESS_MEM_TYPE_64;
+ }
+ }
+ }
+ return low;
+}
+
+/**
+ * Find the start of a PCI BAR
+ *
+ * @v pci PCI device
+ * @v reg PCI register number
+ * @ret start BAR start address
+ *
+ * Reads the specified PCI base address register, and returns the
+ * address portion of the BAR (i.e. without the flags).
+ *
+ * If the address exceeds the size of an unsigned long (i.e. if a
+ * 64-bit BAR has a non-zero high dword on a 32-bit machine), the
+ * return value will be zero.
+ */
+unsigned long pci_bar_start ( struct pci_device *pci, unsigned int reg ) {
+ unsigned long bar;
+
+ bar = pci_bar ( pci, reg );
+ if ( (bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY ){
+ return ( bar & PCI_BASE_ADDRESS_MEM_MASK );
+ } else {
+ return ( bar & PCI_BASE_ADDRESS_IO_MASK );
+ }
+}
+
+/**
+ * Read membase and ioaddr for a PCI device
+ *
+ * @v pci PCI device
+ *
+ * This scans through all PCI BARs on the specified device. The first
+ * valid memory BAR is recorded as pci_device::membase, and the first
+ * valid IO BAR is recorded as pci_device::ioaddr.
+ *
+ * 64-bit BARs are handled automatically. On a 32-bit platform, if a
+ * 64-bit BAR has a non-zero high dword, it will be regarded as
+ * invalid.
+ */
+static void pci_read_bases ( struct pci_device *pci ) {
+ unsigned long bar;
+ int reg;
+
+ for ( reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4 ) {
+ bar = pci_bar ( pci, reg );
+ if ( bar & PCI_BASE_ADDRESS_SPACE_IO ) {
+ if ( ! pci->ioaddr )
+ pci->ioaddr =
+ ( bar & PCI_BASE_ADDRESS_IO_MASK );
+ } else {
+ if ( ! pci->membase )
+ pci->membase =
+ ( bar & PCI_BASE_ADDRESS_MEM_MASK );
+ /* Skip next BAR if 64-bit */
+ if ( bar & PCI_BASE_ADDRESS_MEM_TYPE_64 )
+ reg += 4;
+ }
+ }
+}
+
+/**
+ * Enable PCI device
+ *
+ * @v pci PCI device
+ *
+ * Set device to be a busmaster in case BIOS neglected to do so. Also
+ * adjust PCI latency timer to a reasonable value, 32.
+ */
+void adjust_pci_device ( struct pci_device *pci ) {
+ unsigned short new_command, pci_command;
+ unsigned char pci_latency;
+
+ pci_read_config_word ( pci, PCI_COMMAND, &pci_command );
+ new_command = ( pci_command | PCI_COMMAND_MASTER |
+ PCI_COMMAND_MEM | PCI_COMMAND_IO );
+ if ( pci_command != new_command ) {
+ DBGC ( pci, PCI_FMT " device not enabled by BIOS! Updating "
+ "PCI command %04x->%04x\n",
+ PCI_ARGS ( pci ), pci_command, new_command );
+ pci_write_config_word ( pci, PCI_COMMAND, new_command );
+ }
+
+ pci_read_config_byte ( pci, PCI_LATENCY_TIMER, &pci_latency);
+ if ( pci_latency < 32 ) {
+ DBGC ( pci, PCI_FMT " latency timer is unreasonably low at "
+ "%d. Setting to 32.\n", PCI_ARGS ( pci ), pci_latency );
+ pci_write_config_byte ( pci, PCI_LATENCY_TIMER, 32);
+ }
+}
+
+/**
+ * Read PCI device configuration
+ *
+ * @v pci PCI device
+ * @ret rc Return status code
+ */
+int pci_read_config ( struct pci_device *pci ) {
+ uint32_t tmp;
+
+ /* Check for physical device presence */
+ pci_read_config_dword ( pci, PCI_VENDOR_ID, &tmp );
+ if ( ( tmp == 0xffffffff ) || ( tmp == 0 ) )
+ return -ENODEV;
+
+ /* Populate struct pci_device */
+ pci->vendor = ( tmp & 0xffff );
+ pci->device = ( tmp >> 16 );
+ pci_read_config_dword ( pci, PCI_REVISION, &tmp );
+ pci->class = ( tmp >> 8 );
+ pci_read_config_byte ( pci, PCI_INTERRUPT_LINE, &pci->irq );
+ pci_read_bases ( pci );
+
+ /* Initialise generic device component */
+ snprintf ( pci->dev.name, sizeof ( pci->dev.name ),
+ "PCI%02x:%02x.%x", PCI_BUS ( pci->busdevfn ),
+ PCI_SLOT ( pci->busdevfn ), PCI_FUNC ( pci->busdevfn ) );
+ pci->dev.desc.bus_type = BUS_TYPE_PCI;
+ pci->dev.desc.location = pci->busdevfn;
+ pci->dev.desc.vendor = pci->vendor;
+ pci->dev.desc.device = pci->device;
+ pci->dev.desc.class = pci->class;
+ pci->dev.desc.ioaddr = pci->ioaddr;
+ pci->dev.desc.irq = pci->irq;
+ INIT_LIST_HEAD ( &pci->dev.siblings );
+ INIT_LIST_HEAD ( &pci->dev.children );
+
+ return 0;
+}
+
+/**
+ * Find driver for PCI device
+ *
+ * @v pci PCI device
+ * @ret rc Return status code
+ */
+int pci_find_driver ( struct pci_device *pci ) {
+ struct pci_driver *driver;
+ struct pci_device_id *id;
+ unsigned int i;
+
+ for_each_table_entry ( driver, PCI_DRIVERS ) {
+ for ( i = 0 ; i < driver->id_count ; i++ ) {
+ id = &driver->ids[i];
+ if ( ( id->vendor != PCI_ANY_ID ) &&
+ ( id->vendor != pci->vendor ) )
+ continue;
+ if ( ( id->device != PCI_ANY_ID ) &&
+ ( id->device != pci->device ) )
+ continue;
+ pci_set_driver ( pci, driver, id );
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+/**
+ * Probe a PCI device
+ *
+ * @v pci PCI device
+ * @ret rc Return status code
+ *
+ * Searches for a driver for the PCI device. If a driver is found,
+ * its probe() routine is called.
+ */
+int pci_probe ( struct pci_device *pci ) {
+ int rc;
+
+ DBGC ( pci, PCI_FMT " (%04x:%04x) has driver \"%s\"\n",
+ PCI_ARGS ( pci ), pci->vendor, pci->device, pci->id->name );
+ DBGC ( pci, PCI_FMT " has mem %lx io %lx irq %d\n",
+ PCI_ARGS ( pci ), pci->membase, pci->ioaddr, pci->irq );
+
+ if ( ( rc = pci->driver->probe ( pci ) ) != 0 ) {
+ DBGC ( pci, PCI_FMT " probe failed: %s\n",
+ PCI_ARGS ( pci ), strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Remove a PCI device
+ *
+ * @v pci PCI device
+ */
+void pci_remove ( struct pci_device *pci ) {
+ pci->driver->remove ( pci );
+ DBGC ( pci, PCI_FMT " removed\n", PCI_ARGS ( pci ) );
+}
+
+/**
+ * Probe PCI root bus
+ *
+ * @v rootdev PCI bus root device
+ *
+ * Scans the PCI bus for devices and registers all devices it can
+ * find.
+ */
+static int pcibus_probe ( struct root_device *rootdev ) {
+ struct pci_device *pci = NULL;
+ unsigned int num_bus;
+ unsigned int busdevfn;
+ uint8_t hdrtype = 0;
+ int rc;
+
+ num_bus = pci_num_bus();
+ for ( busdevfn = 0 ; busdevfn < PCI_BUSDEVFN ( num_bus, 0, 0 ) ;
+ busdevfn++ ) {
+
+ /* Allocate struct pci_device */
+ if ( ! pci )
+ pci = malloc ( sizeof ( *pci ) );
+ if ( ! pci ) {
+ rc = -ENOMEM;
+ goto err;
+ }
+ memset ( pci, 0, sizeof ( *pci ) );
+ pci_init ( pci, busdevfn );
+
+ /* Skip all but the first function on
+ * non-multifunction cards
+ */
+ if ( PCI_FUNC ( busdevfn ) == 0 ) {
+ pci_read_config_byte ( pci, PCI_HEADER_TYPE,
+ &hdrtype );
+ } else if ( ! ( hdrtype & 0x80 ) ) {
+ continue;
+ }
+
+ /* Read device configuration */
+ if ( ( rc = pci_read_config ( pci ) ) != 0 )
+ continue;
+
+ /* Look for a driver */
+ if ( ( rc = pci_find_driver ( pci ) ) != 0 ) {
+ DBGC ( pci, PCI_FMT " (%04x:%04x) has no driver\n",
+ PCI_ARGS ( pci ), pci->vendor, pci->device );
+ continue;
+ }
+
+ /* Add to device hierarchy */
+ pci->dev.parent = &rootdev->dev;
+ list_add ( &pci->dev.siblings, &rootdev->dev.children);
+
+ /* Look for a driver */
+ if ( ( rc = pci_probe ( pci ) ) == 0 ) {
+ /* pcidev registered, we can drop our ref */
+ pci = NULL;
+ } else {
+ /* Not registered; re-use struct pci_device */
+ list_del ( &pci->dev.siblings );
+ }
+ }
+
+ free ( pci );
+ return 0;
+
+ err:
+ free ( pci );
+ pcibus_remove ( rootdev );
+ return rc;
+}
+
+/**
+ * Remove PCI root bus
+ *
+ * @v rootdev PCI bus root device
+ */
+static void pcibus_remove ( struct root_device *rootdev ) {
+ struct pci_device *pci;
+ struct pci_device *tmp;
+
+ list_for_each_entry_safe ( pci, tmp, &rootdev->dev.children,
+ dev.siblings ) {
+ pci_remove ( pci );
+ list_del ( &pci->dev.siblings );
+ free ( pci );
+ }
+}
+
+/** PCI bus root device driver */
+static struct root_driver pci_root_driver = {
+ .probe = pcibus_probe,
+ .remove = pcibus_remove,
+};
+
+/** PCI bus root device */
+struct root_device pci_root_device __root_device = {
+ .dev = { .name = "PCI" },
+ .driver = &pci_root_driver,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bus/pcibackup.c b/src/VBox/Devices/PC/ipxe/src/drivers/bus/pcibackup.c
new file mode 100644
index 00000000..6719c53c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bus/pcibackup.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/pci.h>
+#include <ipxe/pcibackup.h>
+
+/** @file
+ *
+ * PCI configuration space backup and restoration
+ *
+ */
+
+/**
+ * Check PCI configuration space offset against exclusion list
+ *
+ * @v pci PCI device
+ * @v offset Offset within PCI configuration space
+ * @v exclude PCI configuration space backup exclusion list, or NULL
+ */
+static int
+pci_backup_excluded ( struct pci_device *pci, unsigned int offset,
+ const uint8_t *exclude ) {
+
+ if ( ! exclude )
+ return 0;
+ for ( ; *exclude != PCI_CONFIG_BACKUP_EXCLUDE_END ; exclude++ ) {
+ if ( offset == *exclude ) {
+ DBGC ( pci, "PCI %p skipping configuration offset "
+ "%02x\n", pci, offset );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Back up PCI configuration space
+ *
+ * @v pci PCI device
+ * @v backup PCI configuration space backup
+ * @v exclude PCI configuration space backup exclusion list, or NULL
+ */
+void pci_backup ( struct pci_device *pci, struct pci_config_backup *backup,
+ const uint8_t *exclude ) {
+ unsigned int offset;
+ uint32_t *dword;
+
+ for ( offset = 0, dword = backup->dwords ; offset < 0x100 ;
+ offset += sizeof ( *dword ) , dword++ ) {
+ if ( ! pci_backup_excluded ( pci, offset, exclude ) )
+ pci_read_config_dword ( pci, offset, dword );
+ }
+}
+
+/**
+ * Restore PCI configuration space
+ *
+ * @v pci PCI device
+ * @v backup PCI configuration space backup
+ * @v exclude PCI configuration space backup exclusion list, or NULL
+ */
+void pci_restore ( struct pci_device *pci, struct pci_config_backup *backup,
+ const uint8_t *exclude ) {
+ unsigned int offset;
+ uint32_t *dword;
+
+ for ( offset = 0, dword = backup->dwords ; offset < 0x100 ;
+ offset += sizeof ( *dword ) , dword++ ) {
+ if ( ! pci_backup_excluded ( pci, offset, exclude ) )
+ pci_write_config_dword ( pci, offset, *dword );
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bus/pciextra.c b/src/VBox/Devices/PC/ipxe/src/drivers/bus/pciextra.c
new file mode 100644
index 00000000..c4417e0c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bus/pciextra.c
@@ -0,0 +1,86 @@
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/pci.h>
+
+/**
+ * Look for a PCI capability
+ *
+ * @v pci PCI device to query
+ * @v cap Capability code
+ * @ret address Address of capability, or 0 if not found
+ *
+ * Determine whether or not a device supports a given PCI capability.
+ * Returns the address of the requested capability structure within
+ * the device's PCI configuration space, or 0 if the device does not
+ * support it.
+ */
+int pci_find_capability ( struct pci_device *pci, int cap ) {
+ uint16_t status;
+ uint8_t pos, id;
+ uint8_t hdr_type;
+ int ttl = 48;
+
+ pci_read_config_word ( pci, PCI_STATUS, &status );
+ if ( ! ( status & PCI_STATUS_CAP_LIST ) )
+ return 0;
+
+ pci_read_config_byte ( pci, PCI_HEADER_TYPE, &hdr_type );
+ switch ( hdr_type & 0x7F ) {
+ case PCI_HEADER_TYPE_NORMAL:
+ case PCI_HEADER_TYPE_BRIDGE:
+ default:
+ pci_read_config_byte ( pci, PCI_CAPABILITY_LIST, &pos );
+ break;
+ case PCI_HEADER_TYPE_CARDBUS:
+ pci_read_config_byte ( pci, PCI_CB_CAPABILITY_LIST, &pos );
+ break;
+ }
+ while ( ttl-- && pos >= 0x40 ) {
+ pos &= ~3;
+ pci_read_config_byte ( pci, pos + PCI_CAP_LIST_ID, &id );
+ DBG ( "PCI Capability: %d\n", id );
+ if ( id == 0xff )
+ break;
+ if ( id == cap )
+ return pos;
+ pci_read_config_byte ( pci, pos + PCI_CAP_LIST_NEXT, &pos );
+ }
+ return 0;
+}
+
+/**
+ * Find the size of a PCI BAR
+ *
+ * @v pci PCI device
+ * @v reg PCI register number
+ * @ret size BAR size
+ *
+ * It should not be necessary for any Etherboot code to call this
+ * function.
+ */
+unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ) {
+ uint16_t cmd;
+ uint32_t start, size;
+
+ /* Save the original command register */
+ pci_read_config_word ( pci, PCI_COMMAND, &cmd );
+ /* Save the original bar */
+ pci_read_config_dword ( pci, reg, &start );
+ /* Compute which bits can be set */
+ pci_write_config_dword ( pci, reg, ~0 );
+ pci_read_config_dword ( pci, reg, &size );
+ /* Restore the original size */
+ pci_write_config_dword ( pci, reg, start );
+ /* Find the significant bits */
+ /* Restore the original command register. This reenables decoding. */
+ pci_write_config_word ( pci, PCI_COMMAND, cmd );
+ if ( start & PCI_BASE_ADDRESS_SPACE_IO ) {
+ size &= PCI_BASE_ADDRESS_IO_MASK;
+ } else {
+ size &= PCI_BASE_ADDRESS_MEM_MASK;
+ }
+ /* Find the lowest bit set */
+ size = size & ~( size - 1 );
+ return size;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bus/pcivpd.c b/src/VBox/Devices/PC/ipxe/src/drivers/bus/pcivpd.c
new file mode 100644
index 00000000..15cf9059
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bus/pcivpd.c
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include <ipxe/isapnp.h>
+#include <ipxe/pcivpd.h>
+
+/** @file
+ *
+ * PCI Vital Product Data
+ *
+ */
+
+/**
+ * Initialise PCI Vital Product Data
+ *
+ * @v vpd PCI VPD
+ * @v pci PCI device
+ * @ret rc Return status code
+ */
+int pci_vpd_init ( struct pci_vpd *vpd, struct pci_device *pci ) {
+
+ /* Initialise structure */
+ vpd->pci = pci;
+ pci_vpd_invalidate_cache ( vpd );
+
+ /* Locate VPD capability */
+ vpd->cap = pci_find_capability ( pci, PCI_CAP_ID_VPD );
+ if ( ! vpd->cap ) {
+ DBGC ( vpd, PCI_FMT " does not support VPD\n",
+ PCI_ARGS ( pci ) );
+ return -ENOTTY;
+ }
+
+ DBGC ( vpd, PCI_FMT " VPD is at offset %02x\n",
+ PCI_ARGS ( pci ), vpd->cap );
+ return 0;
+}
+
+/**
+ * Read one dword of PCI Vital Product Data
+ *
+ * @v vpd PCI VPD
+ * @v address Address to read
+ * @ret data Read data
+ * @ret rc Return status code
+ */
+static int pci_vpd_read_dword ( struct pci_vpd *vpd, int address,
+ uint32_t *data ) {
+ struct pci_device *pci = vpd->pci;
+ unsigned int cap = vpd->cap;
+ unsigned int retries;
+ uint16_t flag;
+
+ /* Fail if no VPD present */
+ if ( ! cap )
+ return -ENOTTY;
+
+ /* Return cached value, if present */
+ if ( pci_vpd_cache_is_valid ( vpd ) &&
+ ( vpd->cache.address == address ) ) {
+ *data = vpd->cache.data;
+ return 0;
+ }
+
+ /* Initiate read */
+ pci_write_config_word ( pci, ( cap + PCI_VPD_ADDRESS ), address );
+
+ /* Wait for read to complete */
+ for ( retries = 0 ; retries < PCI_VPD_MAX_WAIT_MS ; retries++ ) {
+
+ /* Check if data is ready */
+ pci_read_config_word ( pci, ( cap + PCI_VPD_ADDRESS ), &flag );
+ if ( flag & PCI_VPD_FLAG ) {
+
+ /* Read data */
+ pci_read_config_dword ( pci, ( cap + PCI_VPD_DATA ),
+ data );
+ DBGC2 ( vpd, PCI_FMT " VPD %04x => %08x\n",
+ PCI_ARGS ( pci ), address, htonl ( *data ) );
+
+ /* Populate cache */
+ vpd->cache.address = address;
+ vpd->cache.data = *data;
+
+ return 0;
+ }
+
+ /* Wait 1ms before retrying */
+ mdelay ( 1 );
+ }
+
+ DBGC ( vpd, PCI_FMT " VPD %04x read via %02x timed out\n",
+ PCI_ARGS ( pci ), address, cap );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Write one dword of PCI Vital Product Data
+ *
+ * @v vpd PCI VPD
+ * @v address Address to write
+ * @v data Data to write
+ * @ret rc Return status code
+ */
+static int pci_vpd_write_dword ( struct pci_vpd *vpd, int address,
+ uint32_t data ) {
+ struct pci_device *pci = vpd->pci;
+ unsigned int cap = vpd->cap;
+ unsigned int retries;
+ uint16_t flag;
+
+ /* Fail if no VPD present */
+ if ( ! cap )
+ return -ENOTTY;
+
+ /* Invalidate cache */
+ pci_vpd_invalidate_cache ( vpd );
+
+ DBGC2 ( vpd, PCI_FMT " VPD %04x <= %08x\n",
+ PCI_ARGS ( pci ), address, htonl ( data ) );
+
+ /* Write data */
+ pci_write_config_dword ( pci, ( cap + PCI_VPD_DATA ), data );
+
+ /* Initiate write */
+ pci_write_config_word ( pci, ( cap + PCI_VPD_ADDRESS ),
+ ( address | PCI_VPD_FLAG ) );
+
+ /* Wait for write to complete */
+ for ( retries = 0 ; retries < PCI_VPD_MAX_WAIT_MS ; retries++ ) {
+
+ /* Check if write has completed */
+ pci_read_config_word ( pci, ( cap + PCI_VPD_ADDRESS ), &flag );
+ if ( ! ( flag & PCI_VPD_FLAG ) )
+ return 0;
+
+ /* Wait 1ms before retrying */
+ mdelay ( 1 );
+ }
+
+ DBGC ( vpd, PCI_FMT " VPD %04x write via %02x timed out\n",
+ PCI_ARGS ( pci ), address, cap );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Read PCI VPD
+ *
+ * @v vpd PCI VPD
+ * @v address Starting address
+ * @v buf Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int pci_vpd_read ( struct pci_vpd *vpd, unsigned int address, void *buf,
+ size_t len ) {
+ uint8_t *bytes = buf;
+ uint32_t data;
+ size_t skip_len;
+ unsigned int i;
+ int rc;
+
+ /* Calculate length to skip at start of data */
+ skip_len = ( address & 0x03 );
+
+ /* Read data, a dword at a time */
+ for ( address &= ~0x03 ; len ; address += 4 ) {
+
+ /* Read whole dword */
+ if ( ( rc = pci_vpd_read_dword ( vpd, address, &data ) ) != 0 )
+ return rc;
+
+ /* Copy data to buffer */
+ for ( i = 4 ; i ; i-- ) {
+ if ( skip_len ) {
+ skip_len--;
+ } else if ( len ) {
+ *(bytes++) = data;
+ len--;
+ }
+ data = ( ( data << 24 ) | ( data >> 8 ) );
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Write PCI VPD
+ *
+ * @v vpd PCI VPD
+ * @v address Starting address
+ * @v buf Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int pci_vpd_write ( struct pci_vpd *vpd, unsigned int address, const void *buf,
+ size_t len ) {
+ const uint8_t *bytes = buf;
+ uint32_t data;
+ size_t skip_len;
+ unsigned int i;
+ int rc;
+
+ /* Calculate length to skip at start of data */
+ skip_len = ( address & 0x03 );
+
+ /* Write data, a dword at a time */
+ for ( address &= ~0x03 ; len ; address += 4 ) {
+
+ /* Read existing dword, if necessary */
+ if ( skip_len || ( len <= 0x03 ) ) {
+ if ( ( rc = pci_vpd_read_dword ( vpd, address,
+ &data ) ) != 0 )
+ return rc;
+ }
+
+ /* Copy data from buffer */
+ for ( i = 4 ; i ; i-- ) {
+ if ( skip_len ) {
+ skip_len--;
+ } else if ( len ) {
+ data = ( ( data & ~0xff ) | *(bytes++) );
+ len--;
+ }
+ data = ( ( data << 24 ) | ( data >> 8 ) );
+ }
+
+ /* Write whole dword */
+ if ( ( rc = pci_vpd_write_dword ( vpd, address, data ) ) != 0 )
+ return rc;
+ }
+ return 0;
+}
+
+/**
+ * Dump PCI VPD region (for debugging)
+ *
+ * @v vpd PCI VPD
+ * @v address Starting address
+ * @v len Length of data
+ */
+static void pci_vpd_dump ( struct pci_vpd *vpd, unsigned int address,
+ size_t len ) {
+ int rc;
+
+ /* Do nothing in non-debug builds */
+ if ( ! DBG_LOG )
+ return;
+
+ /* Read data */
+ {
+ char buf[len];
+ if ( ( rc = pci_vpd_read ( vpd, address, buf,
+ sizeof ( buf ) ) ) != 0 )
+ return;
+ DBGC_HDA ( vpd, address, buf, sizeof ( buf ) );
+ }
+}
+
+/**
+ * Locate PCI VPD tag
+ *
+ * @v vpd PCI VPD
+ * @v tag ISAPnP tag
+ * @ret address Address of tag body
+ * @ret len Length of tag body
+ * @ret rc Return status code
+ */
+static int pci_vpd_find_tag ( struct pci_vpd *vpd, unsigned int tag,
+ unsigned int *address, size_t *len ) {
+ uint8_t read_tag;
+ uint16_t read_len;
+ int rc;
+
+ /* Scan through tags looking for a match */
+ *address = 0;
+ do {
+ /* Read tag byte */
+ if ( ( rc = pci_vpd_read ( vpd, (*address)++, &read_tag,
+ sizeof ( read_tag ) ) ) != 0 )
+ return rc;
+
+ /* Extract tag and length */
+ if ( ISAPNP_IS_LARGE_TAG ( read_tag ) ) {
+ if ( ( rc = pci_vpd_read ( vpd, *address, &read_len,
+ sizeof ( read_len ) ) ) != 0)
+ return rc;
+ *address += sizeof ( read_len );
+ read_len = le16_to_cpu ( read_len );
+ read_tag = ISAPNP_LARGE_TAG_NAME ( read_tag );
+ } else {
+ read_len = ISAPNP_SMALL_TAG_LEN ( read_tag );
+ read_tag = ISAPNP_SMALL_TAG_NAME ( read_tag );
+ }
+
+ /* Check for tag match */
+ if ( tag == read_tag ) {
+ *len = read_len;
+ DBGC ( vpd, PCI_FMT " VPD tag %02x is at "
+ "[%04x,%04zx)\n", PCI_ARGS ( vpd->pci ), tag,
+ *address, ( *address + *len ) );
+ return 0;
+ }
+
+ /* Move to next tag */
+ *address += read_len;
+
+ } while ( read_tag != ISAPNP_TAG_END );
+
+ DBGC ( vpd, PCI_FMT " VPD tag %02x not found\n",
+ PCI_ARGS ( vpd->pci ), tag );
+ return -ENOENT;
+}
+
+/**
+ * Locate PCI VPD field
+ *
+ * @v vpd PCI VPD
+ * @v field VPD field descriptor
+ * @ret address Address of field body
+ * @ret len Length of field body
+ * @ret rc Return status code
+ */
+int pci_vpd_find ( struct pci_vpd *vpd, unsigned int field,
+ unsigned int *address, size_t *len ) {
+ struct pci_vpd_field read_field;
+ int rc;
+
+ /* Locate containing tag */
+ if ( ( rc = pci_vpd_find_tag ( vpd, PCI_VPD_TAG ( field ),
+ address, len ) ) != 0 )
+ return rc;
+
+ /* Return immediately if we are searching for a whole-tag field */
+ if ( ! PCI_VPD_KEYWORD ( field ) ) {
+ pci_vpd_dump ( vpd, *address, *len );
+ return 0;
+ }
+
+ /* Scan through fields looking for a match */
+ while ( *len >= sizeof ( read_field ) ) {
+
+ /* Read field header */
+ if ( ( rc = pci_vpd_read ( vpd, *address, &read_field,
+ sizeof ( read_field ) ) ) != 0 )
+ return rc;
+ *address += sizeof ( read_field );
+ *len -= sizeof ( read_field );
+
+ /* Check for keyword match */
+ if ( read_field.keyword == PCI_VPD_KEYWORD ( field ) ) {
+ *len = read_field.len;
+ DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT
+ " is at [%04x,%04zx)\n", PCI_ARGS ( vpd->pci ),
+ PCI_VPD_FIELD_ARGS ( field ),
+ *address, ( *address + *len ) );
+ pci_vpd_dump ( vpd, *address, *len );
+ return 0;
+ }
+
+ /* Move to next field */
+ if ( read_field.len > *len )
+ break;
+ *address += read_field.len;
+ *len -= read_field.len;
+ }
+
+ DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT " not found\n",
+ PCI_ARGS ( vpd->pci ), PCI_VPD_FIELD_ARGS ( field ) );
+ return -ENOENT;
+}
+
+/**
+ * Resize VPD field
+ *
+ * @v vpd PCI VPD
+ * @v field VPD field descriptor
+ * @v len New length of field body
+ * @ret address Address of field body
+ * @ret rc Return status code
+ */
+int pci_vpd_resize ( struct pci_vpd *vpd, unsigned int field, size_t len,
+ unsigned int *address ) {
+ struct pci_vpd_field rw_field;
+ struct pci_vpd_field old_field;
+ struct pci_vpd_field new_field;
+ unsigned int rw_address;
+ unsigned int old_address;
+ unsigned int copy_address;
+ unsigned int dst_address;
+ unsigned int dump_address;
+ size_t rw_len;
+ size_t old_len;
+ size_t available_len;
+ size_t copy_len;
+ size_t dump_len;
+ void *copy;
+ int rc;
+
+ /* Sanity checks */
+ assert ( PCI_VPD_TAG ( field ) == PCI_VPD_TAG_RW );
+ assert ( PCI_VPD_KEYWORD ( field ) != 0 );
+ assert ( field != PCI_VPD_FIELD_RW );
+
+ /* Locate 'RW' field */
+ if ( ( rc = pci_vpd_find ( vpd, PCI_VPD_FIELD_RW, &rw_address,
+ &rw_len ) ) != 0 )
+ goto err_no_rw;
+
+ /* Locate old field, if any */
+ if ( ( rc = pci_vpd_find ( vpd, field, &old_address,
+ &old_len ) ) == 0 ) {
+
+ /* Field already exists */
+ if ( old_address > rw_address ) {
+ DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT
+ " at [%04x,%04zx) is after field "
+ PCI_VPD_FIELD_FMT " at [%04x,%04zx)\n",
+ PCI_ARGS ( vpd->pci ),
+ PCI_VPD_FIELD_ARGS ( field ),
+ old_address, ( old_address + old_len ),
+ PCI_VPD_FIELD_ARGS ( PCI_VPD_FIELD_RW ),
+ rw_address, ( rw_address + rw_len ) );
+ rc = -ENXIO;
+ goto err_after_rw;
+ }
+ dst_address = ( old_address - sizeof ( old_field ) );
+ copy_address = ( old_address + old_len );
+ copy_len = ( rw_address - sizeof ( rw_field ) - copy_address );
+
+ /* Calculate available length */
+ available_len = ( rw_len + old_len );
+
+ } else {
+
+ /* Field does not yet exist */
+ dst_address = ( rw_address - sizeof ( rw_field ) );
+ copy_address = dst_address;
+ copy_len = 0;
+
+ /* Calculate available length */
+ available_len = ( ( rw_len > sizeof ( new_field ) ) ?
+ ( rw_len - sizeof ( new_field ) ) : 0 );
+ }
+
+ /* Dump region before changes */
+ dump_address = dst_address;
+ dump_len = ( rw_address + rw_len - dump_address );
+ DBGC ( vpd, PCI_FMT " VPD before resizing field " PCI_VPD_FIELD_FMT
+ " to %zd bytes:\n", PCI_ARGS ( vpd->pci ),
+ PCI_VPD_FIELD_ARGS ( field ), len );
+ pci_vpd_dump ( vpd, dump_address, dump_len );
+
+ /* Check available length */
+ if ( available_len > PCI_VPD_MAX_LEN )
+ available_len = PCI_VPD_MAX_LEN;
+ if ( len > available_len ) {
+ DBGC ( vpd, PCI_FMT " VPD no space for field "
+ PCI_VPD_FIELD_FMT " (need %02zx, have %02zx)\n",
+ PCI_ARGS ( vpd->pci ), PCI_VPD_FIELD_ARGS ( field ),
+ len, available_len );
+ rc = -ENOSPC;
+ goto err_no_space;
+ }
+
+ /* Preserve intermediate fields, if any */
+ copy = malloc ( copy_len );
+ if ( ! copy ) {
+ rc = -ENOMEM;
+ goto err_copy_alloc;
+ }
+ if ( ( rc = pci_vpd_read ( vpd, copy_address, copy, copy_len ) ) != 0 )
+ goto err_copy_read;
+
+ /* Create new field, if applicable */
+ if ( len ) {
+ new_field.keyword = PCI_VPD_KEYWORD ( field );
+ new_field.len = len;
+ if ( ( rc = pci_vpd_write ( vpd, dst_address, &new_field,
+ sizeof ( new_field ) ) ) != 0 )
+ goto err_new_write;
+ dst_address += sizeof ( new_field );
+ *address = dst_address;
+ DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT " is now "
+ "at [%04x,%04x)\n", PCI_ARGS ( vpd->pci ),
+ PCI_VPD_FIELD_ARGS ( field ), dst_address,
+ ( dst_address + new_field.len ) );
+ dst_address += len;
+ } else {
+ DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT
+ " no longer exists\n", PCI_ARGS ( vpd->pci ),
+ PCI_VPD_FIELD_ARGS ( field ) );
+ }
+
+ /* Restore intermediate fields, if any */
+ if ( ( rc = pci_vpd_write ( vpd, dst_address, copy, copy_len ) ) != 0 )
+ goto err_copy_write;
+ dst_address += copy_len;
+
+ /* Create 'RW' field */
+ rw_field.keyword = PCI_VPD_KEYWORD ( PCI_VPD_FIELD_RW );
+ rw_field.len = ( rw_len +
+ ( rw_address - sizeof ( rw_field ) ) - dst_address );
+ if ( ( rc = pci_vpd_write ( vpd, dst_address, &rw_field,
+ sizeof ( rw_field ) ) ) != 0 )
+ goto err_rw_write;
+ dst_address += sizeof ( rw_field );
+ DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT " is now "
+ "at [%04x,%04x)\n", PCI_ARGS ( vpd->pci ),
+ PCI_VPD_FIELD_ARGS ( PCI_VPD_FIELD_RW ), dst_address,
+ ( dst_address + rw_field.len ) );
+
+ /* Dump region after changes */
+ DBGC ( vpd, PCI_FMT " VPD after resizing field " PCI_VPD_FIELD_FMT
+ " to %zd bytes:\n", PCI_ARGS ( vpd->pci ),
+ PCI_VPD_FIELD_ARGS ( field ), len );
+ pci_vpd_dump ( vpd, dump_address, dump_len );
+
+ rc = 0;
+
+ err_rw_write:
+ err_new_write:
+ err_copy_write:
+ err_copy_read:
+ free ( copy );
+ err_copy_alloc:
+ err_no_space:
+ err_after_rw:
+ err_no_rw:
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bus/virtio-pci.c b/src/VBox/Devices/PC/ipxe/src/drivers/bus/virtio-pci.c
new file mode 100644
index 00000000..fbef067b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bus/virtio-pci.c
@@ -0,0 +1,64 @@
+/* virtio-pci.c - pci interface for virtio interface
+ *
+ * (c) Copyright 2008 Bull S.A.S.
+ *
+ * Author: Laurent Vivier <Laurent.Vivier@bull.net>
+ *
+ * some parts from Linux Virtio PCI driver
+ *
+ * Copyright IBM Corp. 2007
+ * Authors: Anthony Liguori <aliguori@us.ibm.com>
+ *
+ */
+
+#include "etherboot.h"
+#include "ipxe/io.h"
+#include "ipxe/virtio-ring.h"
+#include "ipxe/virtio-pci.h"
+
+int vp_find_vq(unsigned int ioaddr, int queue_index,
+ struct vring_virtqueue *vq)
+{
+ struct vring * vr = &vq->vring;
+ u16 num;
+
+ /* select the queue */
+
+ outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
+
+ /* check if the queue is available */
+
+ num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM);
+ if (!num) {
+ printf("ERROR: queue size is 0\n");
+ return -1;
+ }
+
+ if (num > MAX_QUEUE_NUM) {
+ printf("ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM);
+ return -1;
+ }
+
+ /* check if the queue is already active */
+
+ if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) {
+ printf("ERROR: queue already active\n");
+ return -1;
+ }
+
+ vq->queue_index = queue_index;
+
+ /* initialize the queue */
+
+ vring_init(vr, num, (unsigned char*)&vq->queue);
+
+ /* activate the queue
+ *
+ * NOTE: vr->desc is initialized by vring_init()
+ */
+
+ outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT,
+ ioaddr + VIRTIO_PCI_QUEUE_PFN);
+
+ return num;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/bus/virtio-ring.c b/src/VBox/Devices/PC/ipxe/src/drivers/bus/virtio-ring.c
new file mode 100644
index 00000000..e55b6d0e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/bus/virtio-ring.c
@@ -0,0 +1,136 @@
+/* virtio-pci.c - virtio ring management
+ *
+ * (c) Copyright 2008 Bull S.A.S.
+ *
+ * Author: Laurent Vivier <Laurent.Vivier@bull.net>
+ *
+ * some parts from Linux Virtio Ring
+ *
+ * Copyright Rusty Russell IBM Corporation 2007
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "etherboot.h"
+#include "ipxe/io.h"
+#include "ipxe/virtio-ring.h"
+#include "ipxe/virtio-pci.h"
+
+#define BUG() do { \
+ printf("BUG: failure at %s:%d/%s()!\n", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ while(1); \
+} while (0)
+#define BUG_ON(condition) do { if (condition) BUG(); } while (0)
+
+/*
+ * vring_free
+ *
+ * put at the begin of the free list the current desc[head]
+ */
+
+void vring_detach(struct vring_virtqueue *vq, unsigned int head)
+{
+ struct vring *vr = &vq->vring;
+ unsigned int i;
+
+ /* find end of given descriptor */
+
+ i = head;
+ while (vr->desc[i].flags & VRING_DESC_F_NEXT)
+ i = vr->desc[i].next;
+
+ /* link it with free list and point to it */
+
+ vr->desc[i].next = vq->free_head;
+ wmb();
+ vq->free_head = head;
+}
+
+/*
+ * vring_get_buf
+ *
+ * get a buffer from the used list
+ *
+ */
+
+void *vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
+{
+ struct vring *vr = &vq->vring;
+ struct vring_used_elem *elem;
+ u32 id;
+ void *opaque;
+
+ BUG_ON(!vring_more_used(vq));
+
+ elem = &vr->used->ring[vq->last_used_idx % vr->num];
+ wmb();
+ id = elem->id;
+ if (len != NULL)
+ *len = elem->len;
+
+ opaque = vq->vdata[id];
+
+ vring_detach(vq, id);
+
+ vq->last_used_idx++;
+
+ return opaque;
+}
+
+void vring_add_buf(struct vring_virtqueue *vq,
+ struct vring_list list[],
+ unsigned int out, unsigned int in,
+ void *opaque, int num_added)
+{
+ struct vring *vr = &vq->vring;
+ int i, avail, head, prev;
+
+ BUG_ON(out + in == 0);
+
+ prev = 0;
+ head = vq->free_head;
+ for (i = head; out; i = vr->desc[i].next, out--) {
+
+ vr->desc[i].flags = VRING_DESC_F_NEXT;
+ vr->desc[i].addr = (u64)virt_to_phys(list->addr);
+ vr->desc[i].len = list->length;
+ prev = i;
+ list++;
+ }
+ for ( ; in; i = vr->desc[i].next, in--) {
+
+ vr->desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
+ vr->desc[i].addr = (u64)virt_to_phys(list->addr);
+ vr->desc[i].len = list->length;
+ prev = i;
+ list++;
+ }
+ vr->desc[prev].flags &= ~VRING_DESC_F_NEXT;
+
+ vq->free_head = i;
+
+ vq->vdata[head] = opaque;
+
+ avail = (vr->avail->idx + num_added) % vr->num;
+ vr->avail->ring[avail] = head;
+ wmb();
+}
+
+void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
+{
+ struct vring *vr = &vq->vring;
+
+ wmb();
+ vr->avail->idx += num_added;
+
+ mb();
+ if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY))
+ vp_notify(ioaddr, vq->queue_index);
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/MT25218_PRM.h b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/MT25218_PRM.h
new file mode 100644
index 00000000..4011bd0b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/MT25218_PRM.h
@@ -0,0 +1,3460 @@
+/*
+ This software is available to you under a choice of one of two
+ licenses. You may choose to be licensed under the terms of the GNU
+ General Public License (GPL) Version 2, available at
+ <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD
+ license, available in the LICENSE.TXT file accompanying this
+ software. These details are also available at
+ <http://openib.org/license.html>.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+ Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
+*/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/***
+ *** This file was generated at "Tue Nov 22 15:21:23 2005"
+ *** by:
+ *** % csp_bf -copyright=/mswg/misc/license-header.txt -prefix arbelprm_ -bits -fixnames MT25218_PRM.csp
+ ***/
+
+#ifndef H_prefix_arbelprm_bits_fixnames_MT25218_PRM_csp_H
+#define H_prefix_arbelprm_bits_fixnames_MT25218_PRM_csp_H
+
+/* UD Address Vector */
+
+struct arbelprm_ud_address_vector_st { /* Little Endian */
+ pseudo_bit_t pd[0x00018]; /* Protection Domain */
+ pseudo_bit_t port_number[0x00002]; /* Port number
+ 1 - Port 1
+ 2 - Port 2
+ other - reserved */
+ pseudo_bit_t reserved0[0x00006];
+/* -------------- */
+ pseudo_bit_t rlid[0x00010]; /* Remote (Destination) LID */
+ pseudo_bit_t my_lid_path_bits[0x00007];/* Source LID - the lower 7 bits (upper bits are taken from PortInfo) */
+ pseudo_bit_t g[0x00001]; /* Global address enable - if set, GRH will be formed for packet header */
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t hop_limit[0x00008]; /* IPv6 hop limit */
+ pseudo_bit_t max_stat_rate[0x00003];/* Maximum static rate control.
+ 0 - 4X injection rate
+ 1 - 1X injection rate
+ other - reserved
+ */
+ pseudo_bit_t reserved2[0x00001];
+ pseudo_bit_t msg[0x00002]; /* Max Message size, size is 256*2^MSG bytes */
+ pseudo_bit_t reserved3[0x00002];
+ pseudo_bit_t mgid_index[0x00006]; /* Index to port GID table
+ mgid_index = (port_number-1) * 2^log_max_gid + gid_index
+ Where:
+ 1. log_max_gid is taken from QUERY_DEV_LIM command
+ 2. gid_index is the index to the GID table */
+ pseudo_bit_t reserved4[0x0000a];
+/* -------------- */
+ pseudo_bit_t flow_label[0x00014]; /* IPv6 flow label */
+ pseudo_bit_t tclass[0x00008]; /* IPv6 TClass */
+ pseudo_bit_t sl[0x00004]; /* InfiniBand Service Level (SL) */
+/* -------------- */
+ pseudo_bit_t rgid_127_96[0x00020]; /* Remote GID[127:96] */
+/* -------------- */
+ pseudo_bit_t rgid_95_64[0x00020]; /* Remote GID[95:64] */
+/* -------------- */
+ pseudo_bit_t rgid_63_32[0x00020]; /* Remote GID[63:32] */
+/* -------------- */
+ pseudo_bit_t rgid_31_0[0x00020]; /* Remote GID[31:0] if G bit is set. Must be set to 0x2 if G bit is cleared. */
+/* -------------- */
+};
+
+/* Send doorbell */
+
+struct arbelprm_send_doorbell_st { /* Little Endian */
+ pseudo_bit_t nopcode[0x00005]; /* Opcode of descriptor to be executed */
+ pseudo_bit_t f[0x00001]; /* Fence bit. If set, descriptor is fenced */
+ pseudo_bit_t reserved0[0x00002];
+ pseudo_bit_t wqe_counter[0x00010]; /* Modulo-64K counter of WQEs posted to the QP since its creation excluding the newly posted WQEs in this doorbell. Should be zero for the first doorbell on the QP */
+ pseudo_bit_t wqe_cnt[0x00008]; /* Number of WQEs posted with this doorbell. Must be grater then zero. */
+/* -------------- */
+ pseudo_bit_t nds[0x00006]; /* Next descriptor size (in 16-byte chunks) */
+ pseudo_bit_t reserved1[0x00002];
+ pseudo_bit_t qpn[0x00018]; /* QP number this doorbell is rung on */
+/* -------------- */
+};
+
+/* ACCESS_LAM_inject_errors_input_modifier */
+
+struct arbelprm_access_lam_inject_errors_input_modifier_st { /* Little Endian */
+ pseudo_bit_t index3[0x00007];
+ pseudo_bit_t q3[0x00001];
+ pseudo_bit_t index2[0x00007];
+ pseudo_bit_t q2[0x00001];
+ pseudo_bit_t index1[0x00007];
+ pseudo_bit_t q1[0x00001];
+ pseudo_bit_t index0[0x00007];
+ pseudo_bit_t q0[0x00001];
+/* -------------- */
+};
+
+/* ACCESS_LAM_inject_errors_input_parameter */
+
+struct arbelprm_access_lam_inject_errors_input_parameter_st { /* Little Endian */
+ pseudo_bit_t ba[0x00002]; /* Bank Address */
+ pseudo_bit_t da[0x00002]; /* Dimm Address */
+ pseudo_bit_t reserved0[0x0001c];
+/* -------------- */
+ pseudo_bit_t ra[0x00010]; /* Row Address */
+ pseudo_bit_t ca[0x00010]; /* Column Address */
+/* -------------- */
+};
+
+/* */
+
+struct arbelprm_recv_wqe_segment_next_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00006];
+ pseudo_bit_t nda_31_6[0x0001a]; /* Next WQE address, low 32 bit. WQE address must be aligned to 64-byte boundary (6 LSB are forced ZERO). */
+/* -------------- */
+ pseudo_bit_t nds[0x00006]; /* Next WQE size in OctoWords (16 bytes).
+ Zero value in NDS field signals end of WQEs? chain.
+ */
+ pseudo_bit_t reserved1[0x0001a];
+/* -------------- */
+};
+
+/* Send wqe segment data inline */
+
+struct arbelprm_wqe_segment_data_inline_st { /* Little Endian */
+ pseudo_bit_t byte_count[0x0000a]; /* Not including padding for 16Byte chunks */
+ pseudo_bit_t reserved0[0x00015];
+ pseudo_bit_t always1[0x00001];
+/* -------------- */
+ pseudo_bit_t data[0x00018]; /* Data may be more this segment size - in 16Byte chunks */
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved2[0x00040];
+/* -------------- */
+};
+
+/* Send wqe segment data ptr */
+
+struct arbelprm_wqe_segment_data_ptr_st { /* Little Endian */
+ pseudo_bit_t byte_count[0x0001f];
+ pseudo_bit_t always0[0x00001];
+/* -------------- */
+ pseudo_bit_t l_key[0x00020];
+/* -------------- */
+ pseudo_bit_t local_address_h[0x00020];
+/* -------------- */
+ pseudo_bit_t local_address_l[0x00020];
+/* -------------- */
+};
+
+/* Send wqe segment rd */
+
+struct arbelprm_local_invalidate_segment_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00040];
+/* -------------- */
+ pseudo_bit_t mem_key[0x00018];
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved2[0x000a0];
+/* -------------- */
+};
+
+/* Fast_Registration_Segment */
+
+struct arbelprm_fast_registration_segment_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x0001b];
+ pseudo_bit_t lr[0x00001]; /* If set - Local Read access will be enabled */
+ pseudo_bit_t lw[0x00001]; /* If set - Local Write access will be enabled */
+ pseudo_bit_t rr[0x00001]; /* If set - Remote Read access will be enabled */
+ pseudo_bit_t rw[0x00001]; /* If set - Remote Write access will be enabled */
+ pseudo_bit_t a[0x00001]; /* If set - Remote Atomic access will be enabled */
+/* -------------- */
+ pseudo_bit_t pbl_ptr_63_32[0x00020];/* Physical address pointer [63:32] to the physical buffer list */
+/* -------------- */
+ pseudo_bit_t mem_key[0x00020]; /* Memory Key on which the fast registration is executed on. */
+/* -------------- */
+ pseudo_bit_t page_size[0x00005]; /* Page size used for the region. Actual size is [4K]*2^Page_size bytes.
+ page_size should be less than 20. */
+ pseudo_bit_t reserved1[0x00002];
+ pseudo_bit_t zb[0x00001]; /* Zero Based Region */
+ pseudo_bit_t pbl_ptr_31_8[0x00018]; /* Physical address pointer [31:8] to the physical buffer list */
+/* -------------- */
+ pseudo_bit_t start_address_h[0x00020];/* Start Address[63:32] - Virtual Address where this region starts */
+/* -------------- */
+ pseudo_bit_t start_address_l[0x00020];/* Start Address[31:0] - Virtual Address where this region starts */
+/* -------------- */
+ pseudo_bit_t reg_len_h[0x00020]; /* Region Length[63:32] */
+/* -------------- */
+ pseudo_bit_t reg_len_l[0x00020]; /* Region Length[31:0] */
+/* -------------- */
+};
+
+/* Send wqe segment atomic */
+
+struct arbelprm_wqe_segment_atomic_st { /* Little Endian */
+ pseudo_bit_t swap_add_h[0x00020];
+/* -------------- */
+ pseudo_bit_t swap_add_l[0x00020];
+/* -------------- */
+ pseudo_bit_t compare_h[0x00020];
+/* -------------- */
+ pseudo_bit_t compare_l[0x00020];
+/* -------------- */
+};
+
+/* Send wqe segment remote address */
+
+struct arbelprm_wqe_segment_remote_address_st { /* Little Endian */
+ pseudo_bit_t remote_virt_addr_h[0x00020];
+/* -------------- */
+ pseudo_bit_t remote_virt_addr_l[0x00020];
+/* -------------- */
+ pseudo_bit_t rkey[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+};
+
+/* end wqe segment bind */
+
+struct arbelprm_wqe_segment_bind_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x0001d];
+ pseudo_bit_t rr[0x00001]; /* If set, Remote Read Enable for bound window. */
+ pseudo_bit_t rw[0x00001]; /* If set, Remote Write Enable for bound window.
+ */
+ pseudo_bit_t a[0x00001]; /* If set, Atomic Enable for bound window. */
+/* -------------- */
+ pseudo_bit_t reserved1[0x0001e];
+ pseudo_bit_t zb[0x00001]; /* If set, Window is Zero Based. */
+ pseudo_bit_t type[0x00001]; /* Window type.
+ 0 - Type one window
+ 1 - Type two window
+ */
+/* -------------- */
+ pseudo_bit_t new_rkey[0x00020]; /* The new RKey of window to bind */
+/* -------------- */
+ pseudo_bit_t region_lkey[0x00020]; /* Local key of region, which window will be bound to */
+/* -------------- */
+ pseudo_bit_t start_address_h[0x00020];
+/* -------------- */
+ pseudo_bit_t start_address_l[0x00020];
+/* -------------- */
+ pseudo_bit_t length_h[0x00020];
+/* -------------- */
+ pseudo_bit_t length_l[0x00020];
+/* -------------- */
+};
+
+/* Send wqe segment ud */
+
+struct arbelprm_wqe_segment_ud_st { /* Little Endian */
+ struct arbelprm_ud_address_vector_st ud_address_vector;/* UD Address Vector */
+/* -------------- */
+ pseudo_bit_t destination_qp[0x00018];
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t q_key[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00040];
+/* -------------- */
+};
+
+/* Send wqe segment rd */
+
+struct arbelprm_wqe_segment_rd_st { /* Little Endian */
+ pseudo_bit_t destination_qp[0x00018];
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t q_key[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00040];
+/* -------------- */
+};
+
+/* Send wqe segment ctrl */
+
+struct arbelprm_wqe_segment_ctrl_send_st { /* Little Endian */
+ pseudo_bit_t always1[0x00001];
+ pseudo_bit_t s[0x00001]; /* Solicited Event bit. If set, SE (Solicited Event) bit is set in the (last packet of) message. */
+ pseudo_bit_t e[0x00001]; /* Event bit. If set, event is generated upon WQE?s completion, if QP is allowed to generate an event. Every WQE with E-bit set generates an event. The C bit must be set on unsignalled QPs if the E bit is set. */
+ pseudo_bit_t c[0x00001]; /* Completion Queue bit. Valid for unsignalled QPs only. If set, the CQ is updated upon WQE?s completion */
+ pseudo_bit_t ip[0x00001]; /* When set, InfiniHost III Ex will calculate the IP checksum of the IP header that is present immediately after the IPoverIB encapsulation header. In the case of multiple headers (encapsulation), InfiniHost III Ex will calculate the checksum only for the first IP header following the IPoverIB encapsulation header. Not Valid for IPv6 packets */
+ pseudo_bit_t tcp_udp[0x00001]; /* When set, InfiniHost III Ex will calculate the TCP/UDP checksum of the packet that is present immediately after the IP header. In the case of multiple headers (encapsulation), InfiniHost III Ex will calculate the checksum only for the first TCP header following the IP header. This bit may be set only if the entire TCP/UDP segment is present in one IB packet */
+ pseudo_bit_t reserved0[0x00001];
+ pseudo_bit_t so[0x00001]; /* Strong Ordering - when set, the WQE will be executed only after all previous WQEs have been executed. Can be set for RC WQEs only. This bit must be set in type two BIND, Fast Registration and Local invalidate operations. */
+ pseudo_bit_t reserved1[0x00018];
+/* -------------- */
+ pseudo_bit_t immediate[0x00020]; /* If the OpCode encodes an operation with Immediate (RDMA-write/SEND), This field will hold the Immediate data to be sent. If the OpCode encodes send and invalidate operations, this field holds the Invalidation key to be inserted into the packet; otherwise, this field is reserved. */
+/* -------------- */
+};
+
+/* Send wqe segment next */
+
+struct arbelprm_wqe_segment_next_st { /* Little Endian */
+ pseudo_bit_t nopcode[0x00005]; /* Next Opcode: OpCode to be used in the next WQE. Encodes the type of operation to be executed on the QP:
+ ?00000? - NOP. WQE with this opcode creates a completion, but does nothing else
+ ?01000? - RDMA-write
+ ?01001? - RDMA-Write with Immediate
+ ?10000? - RDMA-read
+ ?10001? - Atomic Compare & swap
+ ?10010? - Atomic Fetch & Add
+ ?11000? - Bind memory window
+
+ The encoding for the following operations depends on the QP type:
+ For RC, UC and RD QP:
+ ?01010? - SEND
+ ?01011? - SEND with Immediate
+
+ For UD QP:
+ the encoding depends on the values of bit[31] of the Q_key field in the Datagram Segment (see Table 39, ?Unreliable Datagram Segment Format - Pointers,? on page 101) of
+ both the current WQE and the next WQE, as follows:
+
+ If the last WQE Q_Key bit[31] is clear and the next WQE Q_key bit[31] is set :
+ ?01000? - SEND
+ ?01001? - SEND with Immediate
+
+ otherwise (if the next WQE Q_key bit[31] is cleared, or the last WQE Q_Key bit[31] is set):
+ ?01010? - SEND
+ ?01011? - SEND with Immediate
+
+ All other opcode values are RESERVED, and will result in invalid operation execution. */
+ pseudo_bit_t reserved0[0x00001];
+ pseudo_bit_t nda_31_6[0x0001a]; /* Next WQE address, low 32 bit. WQE address must be aligned to 64-byte boundary (6 LSB are forced ZERO). */
+/* -------------- */
+ pseudo_bit_t nds[0x00006]; /* Next WQE size in OctoWords (16 bytes).
+ Zero value in NDS field signals end of WQEs? chain.
+ */
+ pseudo_bit_t f[0x00001]; /* Fence bit. If set, next WQE will start execution only after all previous Read/Atomic WQEs complete. */
+ pseudo_bit_t always1[0x00001];
+ pseudo_bit_t reserved1[0x00018];
+/* -------------- */
+};
+
+/* Address Path */
+
+struct arbelprm_address_path_st { /* Little Endian */
+ pseudo_bit_t pkey_index[0x00007]; /* PKey table index */
+ pseudo_bit_t reserved0[0x00011];
+ pseudo_bit_t port_number[0x00002]; /* Specific port associated with this QP/EE.
+ 1 - Port 1
+ 2 - Port 2
+ other - reserved */
+ pseudo_bit_t reserved1[0x00006];
+/* -------------- */
+ pseudo_bit_t rlid[0x00010]; /* Remote (Destination) LID */
+ pseudo_bit_t my_lid_path_bits[0x00007];/* Source LID - the lower 7 bits (upper bits are taken from PortInfo) */
+ pseudo_bit_t g[0x00001]; /* Global address enable - if set, GRH will be formed for packet header */
+ pseudo_bit_t reserved2[0x00005];
+ pseudo_bit_t rnr_retry[0x00003]; /* RNR retry count (see C9-132 in IB spec Vol 1)
+ 0-6 - number of retries
+ 7 - infinite */
+/* -------------- */
+ pseudo_bit_t hop_limit[0x00008]; /* IPv6 hop limit */
+ pseudo_bit_t max_stat_rate[0x00003];/* Maximum static rate control.
+ 0 - 100% injection rate
+ 1 - 25% injection rate
+ 2 - 12.5% injection rate
+ 3 - 50% injection rate
+ other - reserved */
+ pseudo_bit_t reserved3[0x00005];
+ pseudo_bit_t mgid_index[0x00006]; /* Index to port GID table */
+ pseudo_bit_t reserved4[0x00005];
+ pseudo_bit_t ack_timeout[0x00005]; /* Local ACK timeout - Transport timer for activation of retransmission mechanism. Refer to IB spec Vol1 9.7.6.1.3 for further details.
+ The transport timer is set to 4.096us*2^ack_timeout, if ack_timeout is 0 then transport timer is disabled. */
+/* -------------- */
+ pseudo_bit_t flow_label[0x00014]; /* IPv6 flow label */
+ pseudo_bit_t tclass[0x00008]; /* IPv6 TClass */
+ pseudo_bit_t sl[0x00004]; /* InfiniBand Service Level (SL) */
+/* -------------- */
+ pseudo_bit_t rgid_127_96[0x00020]; /* Remote GID[127:96] */
+/* -------------- */
+ pseudo_bit_t rgid_95_64[0x00020]; /* Remote GID[95:64] */
+/* -------------- */
+ pseudo_bit_t rgid_63_32[0x00020]; /* Remote GID[63:32] */
+/* -------------- */
+ pseudo_bit_t rgid_31_0[0x00020]; /* Remote GID[31:0] */
+/* -------------- */
+};
+
+/* HCA Command Register (HCR) */
+
+struct arbelprm_hca_command_register_st { /* Little Endian */
+ pseudo_bit_t in_param_h[0x00020]; /* Input Parameter: parameter[63:32] or pointer[63:32] to input mailbox (see command description) */
+/* -------------- */
+ pseudo_bit_t in_param_l[0x00020]; /* Input Parameter: parameter[31:0] or pointer[31:0] to input mailbox (see command description) */
+/* -------------- */
+ pseudo_bit_t input_modifier[0x00020];/* Input Parameter Modifier */
+/* -------------- */
+ pseudo_bit_t out_param_h[0x00020]; /* Output Parameter: parameter[63:32] or pointer[63:32] to output mailbox (see command description) */
+/* -------------- */
+ pseudo_bit_t out_param_l[0x00020]; /* Output Parameter: parameter[31:0] or pointer[31:0] to output mailbox (see command description) */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00010];
+ pseudo_bit_t token[0x00010]; /* Software assigned token to the command, to uniquely identify it. The token is returned to the software in the EQE reported. */
+/* -------------- */
+ pseudo_bit_t opcode[0x0000c]; /* Command opcode */
+ pseudo_bit_t opcode_modifier[0x00004];/* Opcode Modifier, see specific description for each command. */
+ pseudo_bit_t reserved1[0x00006];
+ pseudo_bit_t e[0x00001]; /* Event Request
+ 0 - Don't report event (software will poll the GO bit)
+ 1 - Report event to EQ when the command completes */
+ pseudo_bit_t go[0x00001]; /* Go (0=Software ownership for the HCR, 1=Hardware ownership for the HCR)
+ Software can write to the HCR only if Go bit is cleared.
+ Software must set the Go bit to trigger the HW to execute the command. Software must not write to this register value other than 1 for the Go bit. */
+ pseudo_bit_t status[0x00008]; /* Command execution status report. Valid only if command interface in under SW ownership (Go bit is cleared)
+ 0 - command completed without error. If different than zero, command execution completed with error. Syndrom encoding is depended on command executed and is defined for each command */
+/* -------------- */
+};
+
+/* CQ Doorbell */
+
+struct arbelprm_cq_cmd_doorbell_st { /* Little Endian */
+ pseudo_bit_t cqn[0x00018]; /* CQ number accessed */
+ pseudo_bit_t cmd[0x00003]; /* Command to be executed on CQ
+ 0x0 - Reserved
+ 0x1 - Request notification for next Solicited completion event. CQ_param specifies the current CQ Consumer Counter.
+ 0x2 - Request notification for next Solicited or Unsolicited completion event. CQ_param specifies the current CQ Consumer Counter.
+ 0x3 - Request notification for multiple completions (Arm-N). CQ_param specifies the value of the CQ Counter that when reached by HW (i.e. HW generates a CQE into this Counter) Event will be generated
+ Other - Reserved */
+ pseudo_bit_t reserved0[0x00001];
+ pseudo_bit_t cmd_sn[0x00002]; /* Command Sequence Number - This field should be incremented upon receiving completion notification of the respective CQ.
+ This transition is done by ringing Request notification for next Solicited, Request notification for next Solicited or Unsolicited
+ completion or Request notification for multiple completions doorbells after receiving completion notification.
+ This field is initialized to Zero */
+ pseudo_bit_t reserved1[0x00002];
+/* -------------- */
+ pseudo_bit_t cq_param[0x00020]; /* parameter to be used by CQ command */
+/* -------------- */
+};
+
+/* RD-send doorbell */
+
+struct arbelprm_rd_send_doorbell_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t een[0x00018]; /* End-to-end context number (reliable datagram)
+ Must be zero for Nop and Bind operations */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00008];
+ pseudo_bit_t qpn[0x00018]; /* QP number this doorbell is rung on */
+/* -------------- */
+ struct arbelprm_send_doorbell_st send_doorbell;/* Send Parameters */
+/* -------------- */
+};
+
+/* Multicast Group Member QP */
+
+struct arbelprm_mgmqp_st { /* Little Endian */
+ pseudo_bit_t qpn_i[0x00018]; /* QPN_i: QP number which is a member in this multicast group. Valid only if Qi bit is set. Length of the QPN_i list is set in INIT_HCA */
+ pseudo_bit_t reserved0[0x00007];
+ pseudo_bit_t qi[0x00001]; /* Qi: QPN_i is valid */
+/* -------------- */
+};
+
+/* vsd */
+
+struct arbelprm_vsd_st { /* Little Endian */
+ pseudo_bit_t vsd_dw0[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw1[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw2[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw3[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw4[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw5[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw6[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw7[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw8[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw9[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw10[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw11[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw12[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw13[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw14[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw15[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw16[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw17[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw18[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw19[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw20[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw21[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw22[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw23[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw24[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw25[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw26[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw27[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw28[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw29[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw30[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw31[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw32[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw33[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw34[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw35[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw36[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw37[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw38[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw39[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw40[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw41[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw42[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw43[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw44[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw45[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw46[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw47[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw48[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw49[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw50[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw51[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw52[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw53[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw54[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw55[0x00020];
+/* -------------- */
+};
+
+/* ACCESS_LAM_inject_errors */
+
+struct arbelprm_access_lam_inject_errors_st { /* Little Endian */
+ struct arbelprm_access_lam_inject_errors_input_parameter_st access_lam_inject_errors_input_parameter;
+/* -------------- */
+ struct arbelprm_access_lam_inject_errors_input_modifier_st access_lam_inject_errors_input_modifier;
+/* -------------- */
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+};
+
+/* Logical DIMM Information */
+
+struct arbelprm_dimminfo_st { /* Little Endian */
+ pseudo_bit_t dimmsize[0x00010]; /* Size of DIMM in units of 2^20 Bytes. This value is valid only when DIMMStatus is 0. */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t dimmstatus[0x00001]; /* DIMM Status
+ 0 - Enabled
+ 1 - Disabled
+ */
+ pseudo_bit_t dh[0x00001]; /* When set, the DIMM is Hidden and can not be accessed from the PCI bus. */
+ pseudo_bit_t wo[0x00001]; /* When set, the DIMM is write only.
+ If data integrity is configured (other than none), the DIMM must be
+ only targeted by write transactions where the address and size are multiples of 16 bytes. */
+ pseudo_bit_t reserved1[0x00005];
+/* -------------- */
+ pseudo_bit_t spd[0x00001]; /* 0 - DIMM SPD was read from DIMM
+ 1 - DIMM SPD was read from InfiniHost-III-EX NVMEM */
+ pseudo_bit_t sladr[0x00003]; /* SPD Slave Address 3 LSBits.
+ Valid only if spd bit is 0. */
+ pseudo_bit_t sock_num[0x00002]; /* DIMM socket number (for double sided DIMM one of the two numbers will be reported) */
+ pseudo_bit_t syn[0x00004]; /* Error syndrome (valid regardless of status value)
+ 0 - DIMM has no error
+ 1 - SPD error (e.g. checksum error, no response, error while reading)
+ 2 - DIMM out of bounds (e.g. DIMM rows number is not between 7 and 14, DIMM type is not 2)
+ 3 - DIMM conflict (e.g. mix of registered and unbuffered DIMMs, CAS latency conflict)
+ 5 - DIMM size trimmed due to configuration (size exceeds)
+ other - Error, reserved
+ */
+ pseudo_bit_t reserved2[0x00016];
+/* -------------- */
+ pseudo_bit_t reserved3[0x00040];
+/* -------------- */
+ pseudo_bit_t dimm_start_adr_h[0x00020];/* DIMM memory start address [63:32]. This value is valid only when DIMMStatus is 0. */
+/* -------------- */
+ pseudo_bit_t dimm_start_adr_l[0x00020];/* DIMM memory start address [31:0]. This value is valid only when DIMMStatus is 0. */
+/* -------------- */
+ pseudo_bit_t reserved4[0x00040];
+/* -------------- */
+};
+
+/* UAR Parameters */
+
+struct arbelprm_uar_params_st { /* Little Endian */
+ pseudo_bit_t uar_base_addr_h[0x00020];/* UAR Base (pyhsical) Address [63:32] (QUERY_HCA only) */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00014];
+ pseudo_bit_t uar_base_addr_l[0x0000c];/* UAR Base (pyhsical) Address [31:20] (QUERY_HCA only) */
+/* -------------- */
+ pseudo_bit_t uar_page_sz[0x00008]; /* This field defines the size of each UAR page.
+ Size of UAR Page is 4KB*2^UAR_Page_Size */
+ pseudo_bit_t log_max_uars[0x00004]; /* Number of UARs supported is 2^log_max_UARs */
+ pseudo_bit_t reserved1[0x00004];
+ pseudo_bit_t log_uar_entry_sz[0x00006];/* Size of UAR Context entry is 2^log_uar_sz in 4KByte pages */
+ pseudo_bit_t reserved2[0x0000a];
+/* -------------- */
+ pseudo_bit_t reserved3[0x00020];
+/* -------------- */
+ pseudo_bit_t uar_scratch_base_addr_h[0x00020];/* Base address of UAR scratchpad [63:32].
+ Number of entries in table is 2^log_max_uars.
+ Table must be aligned to its size */
+/* -------------- */
+ pseudo_bit_t uar_scratch_base_addr_l[0x00020];/* Base address of UAR scratchpad [31:0].
+ Number of entries in table is 2^log_max_uars.
+ Table must be aligned to its size. */
+/* -------------- */
+ pseudo_bit_t uar_context_base_addr_h[0x00020];/* Base address of UAR Context [63:32].
+ Number of entries in table is 2^log_max_uars.
+ Table must be aligned to its size. */
+/* -------------- */
+ pseudo_bit_t uar_context_base_addr_l[0x00020];/* Base address of UAR Context [31:0].
+ Number of entries in table is 2^log_max_uars.
+ Table must be aligned to its size. */
+/* -------------- */
+};
+
+/* Translation and Protection Tables Parameters */
+
+struct arbelprm_tptparams_st { /* Little Endian */
+ pseudo_bit_t mpt_base_adr_h[0x00020];/* MPT - Memory Protection Table base physical address [63:32].
+ Entry size is 64 bytes.
+ Table must be aligned to its size.
+ Address may be set to 0xFFFFFFFF if address translation and protection is not supported. */
+/* -------------- */
+ pseudo_bit_t mpt_base_adr_l[0x00020];/* MPT - Memory Protection Table base physical address [31:0].
+ Entry size is 64 bytes.
+ Table must be aligned to its size.
+ Address may be set to 0xFFFFFFFF if address translation and protection is not supported. */
+/* -------------- */
+ pseudo_bit_t log_mpt_sz[0x00006]; /* Log (base 2) of the number of region/windows entries in the MPT table. */
+ pseudo_bit_t reserved0[0x00002];
+ pseudo_bit_t pfto[0x00005]; /* Page Fault RNR Timeout -
+ The field returned in RNR Naks generated when a page fault is detected.
+ It has no effect when on-demand-paging is not used. */
+ pseudo_bit_t reserved1[0x00013];
+/* -------------- */
+ pseudo_bit_t reserved2[0x00020];
+/* -------------- */
+ pseudo_bit_t mtt_base_addr_h[0x00020];/* MTT - Memory Translation table base physical address [63:32].
+ Table must be aligned to its size.
+ Address may be set to 0xFFFFFFFF if address translation and protection is not supported. */
+/* -------------- */
+ pseudo_bit_t mtt_base_addr_l[0x00020];/* MTT - Memory Translation table base physical address [31:0].
+ Table must be aligned to its size.
+ Address may be set to 0xFFFFFFFF if address translation and protection is not supported. */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00040];
+/* -------------- */
+};
+
+/* Multicast Support Parameters */
+
+struct arbelprm_multicastparam_st { /* Little Endian */
+ pseudo_bit_t mc_base_addr_h[0x00020];/* Base Address of the Multicast Table [63:32].
+ The base address must be aligned to the entry size.
+ Address may be set to 0xFFFFFFFF if multicast is not supported. */
+/* -------------- */
+ pseudo_bit_t mc_base_addr_l[0x00020];/* Base Address of the Multicast Table [31:0].
+ The base address must be aligned to the entry size.
+ Address may be set to 0xFFFFFFFF if multicast is not supported. */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00040];
+/* -------------- */
+ pseudo_bit_t log_mc_table_entry_sz[0x00010];/* Log2 of the Size of multicast group member (MGM) entry.
+ Must be greater than 5 (to allow CTRL and GID sections).
+ That implies the number of QPs per MC table entry. */
+ pseudo_bit_t reserved1[0x00010];
+/* -------------- */
+ pseudo_bit_t mc_table_hash_sz[0x00011];/* Number of entries in multicast DGID hash table (must be power of 2)
+ INIT_HCA - the required number of entries
+ QUERY_HCA - the actual number of entries assigned by firmware (will be less than or equal to the amount required in INIT_HCA) */
+ pseudo_bit_t reserved2[0x0000f];
+/* -------------- */
+ pseudo_bit_t log_mc_table_sz[0x00005];/* Log2 of the overall number of MC entries in the MCG table (includes both hash and auxiliary tables) */
+ pseudo_bit_t reserved3[0x00013];
+ pseudo_bit_t mc_hash_fn[0x00003]; /* Multicast hash function
+ 0 - Default hash function
+ other - reserved */
+ pseudo_bit_t reserved4[0x00005];
+/* -------------- */
+ pseudo_bit_t reserved5[0x00020];
+/* -------------- */
+};
+
+/* QPC/EEC/CQC/EQC/RDB Parameters */
+
+struct arbelprm_qpcbaseaddr_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00080];
+/* -------------- */
+ pseudo_bit_t qpc_base_addr_h[0x00020];/* QPC Base Address [63:32]
+ Table must be aligned on its size */
+/* -------------- */
+ pseudo_bit_t log_num_of_qp[0x00005];/* Log base 2 of number of supported QPs */
+ pseudo_bit_t reserved1[0x00002];
+ pseudo_bit_t qpc_base_addr_l[0x00019];/* QPC Base Address [31:7]
+ Table must be aligned on its size */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00040];
+/* -------------- */
+ pseudo_bit_t eec_base_addr_h[0x00020];/* EEC Base Address [63:32]
+ Table must be aligned on its size.
+ Address may be set to 0xFFFFFFFF if RD is not supported. */
+/* -------------- */
+ pseudo_bit_t log_num_of_ee[0x00005];/* Log base 2 of number of supported EEs. */
+ pseudo_bit_t reserved3[0x00002];
+ pseudo_bit_t eec_base_addr_l[0x00019];/* EEC Base Address [31:7]
+ Table must be aligned on its size
+ Address may be set to 0xFFFFFFFF if RD is not supported. */
+/* -------------- */
+ pseudo_bit_t srqc_base_addr_h[0x00020];/* SRQ Context Base Address [63:32]
+ Table must be aligned on its size
+ Address may be set to 0xFFFFFFFF if SRQ is not supported. */
+/* -------------- */
+ pseudo_bit_t log_num_of_srq[0x00005];/* Log base 2 of number of supported SRQs. */
+ pseudo_bit_t srqc_base_addr_l[0x0001b];/* SRQ Context Base Address [31:5]
+ Table must be aligned on its size
+ Address may be set to 0xFFFFFFFF if SRQ is not supported. */
+/* -------------- */
+ pseudo_bit_t cqc_base_addr_h[0x00020];/* CQC Base Address [63:32]
+ Table must be aligned on its size */
+/* -------------- */
+ pseudo_bit_t log_num_of_cq[0x00005];/* Log base 2 of number of supported CQs. */
+ pseudo_bit_t reserved4[0x00001];
+ pseudo_bit_t cqc_base_addr_l[0x0001a];/* CQC Base Address [31:6]
+ Table must be aligned on its size */
+/* -------------- */
+ pseudo_bit_t reserved5[0x00040];
+/* -------------- */
+ pseudo_bit_t eqpc_base_addr_h[0x00020];/* Extended QPC Base Address [63:32]
+ Table has same number of entries as QPC table.
+ Table must be aligned to entry size. */
+/* -------------- */
+ pseudo_bit_t eqpc_base_addr_l[0x00020];/* Extended QPC Base Address [31:0]
+ Table has same number of entries as QPC table.
+ Table must be aligned to entry size. */
+/* -------------- */
+ pseudo_bit_t reserved6[0x00040];
+/* -------------- */
+ pseudo_bit_t eeec_base_addr_h[0x00020];/* Extended EEC Base Address [63:32]
+ Table has same number of entries as EEC table.
+ Table must be aligned to entry size.
+ Address may be set to 0xFFFFFFFF if RD is not supported. */
+/* -------------- */
+ pseudo_bit_t eeec_base_addr_l[0x00020];/* Extended EEC Base Address [31:0]
+ Table has same number of entries as EEC table.
+ Table must be aligned to entry size.
+ Address may be set to 0xFFFFFFFF if RD is not supported. */
+/* -------------- */
+ pseudo_bit_t reserved7[0x00040];
+/* -------------- */
+ pseudo_bit_t eqc_base_addr_h[0x00020];/* EQC Base Address [63:32]
+ Address may be set to 0xFFFFFFFF if EQs are not supported.
+ Table must be aligned to entry size. */
+/* -------------- */
+ pseudo_bit_t log_num_eq[0x00004]; /* Log base 2 of number of supported EQs.
+ Must be 6 or less in InfiniHost-III-EX. */
+ pseudo_bit_t reserved8[0x00002];
+ pseudo_bit_t eqc_base_addr_l[0x0001a];/* EQC Base Address [31:6]
+ Address may be set to 0xFFFFFFFF if EQs are not supported.
+ Table must be aligned to entry size. */
+/* -------------- */
+ pseudo_bit_t reserved9[0x00040];
+/* -------------- */
+ pseudo_bit_t rdb_base_addr_h[0x00020];/* Base address of table that holds remote read and remote atomic requests [63:32].
+ Address may be set to 0xFFFFFFFF if remote RDMA reads are not supported.
+ Please refer to QP and EE chapter for further explanation on RDB allocation. */
+/* -------------- */
+ pseudo_bit_t rdb_base_addr_l[0x00020];/* Base address of table that holds remote read and remote atomic requests [31:0].
+ Table must be aligned to RDB entry size (32 bytes).
+ Address may be set to zero if remote RDMA reads are not supported.
+ Please refer to QP and EE chapter for further explanation on RDB allocation. */
+/* -------------- */
+ pseudo_bit_t reserved10[0x00040];
+/* -------------- */
+};
+
+/* Header_Log_Register */
+
+struct arbelprm_header_log_register_st { /* Little Endian */
+ pseudo_bit_t place_holder[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved0[0x00060];
+/* -------------- */
+};
+
+/* Performance Monitors */
+
+struct arbelprm_performance_monitors_st { /* Little Endian */
+ pseudo_bit_t e0[0x00001]; /* Enables counting of respective performance counter */
+ pseudo_bit_t e1[0x00001]; /* Enables counting of respective performance counter */
+ pseudo_bit_t e2[0x00001]; /* Enables counting of respective performance counter */
+ pseudo_bit_t reserved0[0x00001];
+ pseudo_bit_t r0[0x00001]; /* If written to as '1 - resets respective performance counter, if written to az '0 - no change to matter */
+ pseudo_bit_t r1[0x00001]; /* If written to as '1 - resets respective performance counter, if written to az '0 - no change to matter */
+ pseudo_bit_t r2[0x00001]; /* If written to as '1 - resets respective performance counter, if written to az '0 - no change to matter */
+ pseudo_bit_t reserved1[0x00001];
+ pseudo_bit_t i0[0x00001]; /* Interrupt enable on respective counter overflow. '1 - interrupt enabled, '0 - interrupt disabled. */
+ pseudo_bit_t i1[0x00001]; /* Interrupt enable on respective counter overflow. '1 - interrupt enabled, '0 - interrupt disabled. */
+ pseudo_bit_t i2[0x00001]; /* Interrupt enable on respective counter overflow. '1 - interrupt enabled, '0 - interrupt disabled. */
+ pseudo_bit_t reserved2[0x00001];
+ pseudo_bit_t f0[0x00001]; /* Overflow flag. If set, overflow occurred on respective counter. Cleared if written to as '1 */
+ pseudo_bit_t f1[0x00001]; /* Overflow flag. If set, overflow occurred on respective counter. Cleared if written to as '1 */
+ pseudo_bit_t f2[0x00001]; /* Overflow flag. If set, overflow occurred on respective counter. Cleared if written to as '1 */
+ pseudo_bit_t reserved3[0x00001];
+ pseudo_bit_t ev_cnt1[0x00005]; /* Specifies event to be counted by Event_counter1 See XXX for events' definition. */
+ pseudo_bit_t reserved4[0x00003];
+ pseudo_bit_t ev_cnt2[0x00005]; /* Specifies event to be counted by Event_counter2 See XXX for events' definition. */
+ pseudo_bit_t reserved5[0x00003];
+/* -------------- */
+ pseudo_bit_t clock_counter[0x00020];
+/* -------------- */
+ pseudo_bit_t event_counter1[0x00020];
+/* -------------- */
+ pseudo_bit_t event_counter2[0x00020];/* Read/write event counter, counting events specified by EvCntl and EvCnt2 fields repsectively. When the event counter reaches is maximum value of 0xFFFFFF, the next event will cause it to roll over to zero, set F1 or F2 bit respectively and generate interrupt by I1 I2 bit respectively. */
+/* -------------- */
+};
+
+/* Receive segment format */
+
+struct arbelprm_wqe_segment_ctrl_recv_st { /* Little Endian */
+ struct arbelprm_recv_wqe_segment_next_st wqe_segment_next;
+/* -------------- */
+ pseudo_bit_t reserved0[0x00002];
+ pseudo_bit_t reserved1[0x00001];
+ pseudo_bit_t reserved2[0x00001];
+ pseudo_bit_t reserved3[0x0001c];
+/* -------------- */
+ pseudo_bit_t reserved4[0x00020];
+/* -------------- */
+};
+
+/* MLX WQE segment format */
+
+struct arbelprm_wqe_segment_ctrl_mlx_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00002];
+ pseudo_bit_t e[0x00001]; /* WQE event */
+ pseudo_bit_t c[0x00001]; /* Create CQE (for "requested signalling" QP) */
+ pseudo_bit_t icrc[0x00002]; /* icrc field detemines what to do with the last dword of the packet: 0 - Calculate ICRC and put it instead of last dword. Last dword must be 0x0. 1,2 - reserved. 3 - Leave last dword as is. Last dword must not be 0x0. */
+ pseudo_bit_t reserved1[0x00002];
+ pseudo_bit_t sl[0x00004];
+ pseudo_bit_t max_statrate[0x00004];
+ pseudo_bit_t slr[0x00001]; /* 0= take slid from port. 1= take slid from given headers */
+ pseudo_bit_t v15[0x00001]; /* Send packet over VL15 */
+ pseudo_bit_t reserved2[0x0000e];
+/* -------------- */
+ pseudo_bit_t vcrc[0x00010]; /* Packet's VCRC (if not 0 - otherwise computed by HW) */
+ pseudo_bit_t rlid[0x00010]; /* Destination LID (must match given headers) */
+/* -------------- */
+};
+
+/* Send WQE segment format */
+
+struct arbelprm_send_wqe_segment_st { /* Little Endian */
+ struct arbelprm_wqe_segment_next_st wqe_segment_next;/* Send wqe segment next */
+/* -------------- */
+ struct arbelprm_wqe_segment_ctrl_send_st wqe_segment_ctrl_send;/* Send wqe segment ctrl */
+/* -------------- */
+ struct arbelprm_wqe_segment_rd_st wqe_segment_rd;/* Send wqe segment rd */
+/* -------------- */
+ struct arbelprm_wqe_segment_ud_st wqe_segment_ud;/* Send wqe segment ud */
+/* -------------- */
+ struct arbelprm_wqe_segment_bind_st wqe_segment_bind;/* Send wqe segment bind */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00180];
+/* -------------- */
+ struct arbelprm_wqe_segment_remote_address_st wqe_segment_remote_address;/* Send wqe segment remote address */
+/* -------------- */
+ struct arbelprm_wqe_segment_atomic_st wqe_segment_atomic;/* Send wqe segment atomic */
+/* -------------- */
+ struct arbelprm_fast_registration_segment_st fast_registration_segment;/* Fast Registration Segment */
+/* -------------- */
+ struct arbelprm_local_invalidate_segment_st local_invalidate_segment;/* local invalidate segment */
+/* -------------- */
+ struct arbelprm_wqe_segment_data_ptr_st wqe_segment_data_ptr;/* Send wqe segment data ptr */
+/* -------------- */
+ struct arbelprm_wqe_segment_data_inline_st wqe_segment_data_inline;/* Send wqe segment data inline */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00200];
+/* -------------- */
+};
+
+/* QP and EE Context Entry */
+
+struct arbelprm_queue_pair_ee_context_entry_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t de[0x00001]; /* Send/Receive Descriptor Event enable - if set, events can be generated upon descriptors' completion on send/receive queue (controlled by E bit in WQE). Invalid in EE context */
+ pseudo_bit_t reserved1[0x00002];
+ pseudo_bit_t pm_state[0x00002]; /* Path migration state (Migrated, Armed or Rearm)
+ 11-Migrated
+ 00-Armed
+ 01-Rearm
+ 10-Reserved
+ Should be set to 11 for UD QPs and for QPs which do not support APM */
+ pseudo_bit_t reserved2[0x00003];
+ pseudo_bit_t st[0x00003]; /* Service type (invalid in EE context):
+ 000-Reliable Connection
+ 001-Unreliable Connection
+ 010-Reliable Datagram
+ 011-Unreliable Datagram
+ 111-MLX transport (raw bits injection). Used for management QPs and RAW */
+ pseudo_bit_t reserved3[0x00009];
+ pseudo_bit_t state[0x00004]; /* QP/EE state:
+ 0 - RST
+ 1 - INIT
+ 2 - RTR
+ 3 - RTS
+ 4 - SQEr
+ 5 - SQD (Send Queue Drained)
+ 6 - ERR
+ 7 - Send Queue Draining
+ 8 - Reserved
+ 9 - Suspended
+ A- F - Reserved
+ (Valid for QUERY_QPEE and ERR2RST_QPEE commands only) */
+/* -------------- */
+ pseudo_bit_t reserved4[0x00020];
+/* -------------- */
+ pseudo_bit_t sched_queue[0x00004]; /* Schedule queue to be used for WQE scheduling to execution. Determines QOS for this QP. */
+ pseudo_bit_t rlky[0x00001]; /* When set this QP can use the Reserved L_Key */
+ pseudo_bit_t reserved5[0x00003];
+ pseudo_bit_t log_sq_stride[0x00003];/* Stride on the send queue. WQ entry is 16*(2^log_SQ_stride) bytes.
+ Stride must be equal or bigger then 64 bytes (minimum log_RQ_stride value allowed is 2). */
+ pseudo_bit_t log_sq_size[0x00004]; /* Log2 of the Number of WQEs in the Send Queue. */
+ pseudo_bit_t reserved6[0x00001];
+ pseudo_bit_t log_rq_stride[0x00003];/* Stride on the receive queue. WQ entry is 16*(2^log_RQ_stride) bytes.
+ Stride must be equal or bigger then 64 bytes (minimum log_RQ_stride value allowed is 2). */
+ pseudo_bit_t log_rq_size[0x00004]; /* Log2 of the Number of WQEs in the Receive Queue. */
+ pseudo_bit_t reserved7[0x00001];
+ pseudo_bit_t msg_max[0x00005]; /* Max message size allowed on the QP. Maximum message size is 2^msg_Max.
+ Must be equal to MTU for UD and MLX QPs. */
+ pseudo_bit_t mtu[0x00003]; /* MTU of the QP (Must be the same for both paths: primary and alternative):
+ 0x1 - 256 bytes
+ 0x2 - 512
+ 0x3 - 1024
+ 0x4 - 2048
+ other - reserved
+
+ Should be configured to 0x4 for UD and MLX QPs. */
+/* -------------- */
+ pseudo_bit_t usr_page[0x00018]; /* QP (see "non_privileged Access to the HCA Hardware"). Not valid (reserved) in EE context. */
+ pseudo_bit_t reserved8[0x00008];
+/* -------------- */
+ pseudo_bit_t local_qpn_een[0x00018];/* Local QP/EE number Lower bits determine position of this record in QPC table, and - thus - constrained
+ This field is valid for QUERY and ERR2RST commands only. */
+ pseudo_bit_t reserved9[0x00008];
+/* -------------- */
+ pseudo_bit_t remote_qpn_een[0x00018];/* Remote QP/EE number */
+ pseudo_bit_t reserved10[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved11[0x00040];
+/* -------------- */
+ struct arbelprm_address_path_st primary_address_path;/* Primary address path for the QP/EE */
+/* -------------- */
+ struct arbelprm_address_path_st alternative_address_path;/* Alternate address path for the QP/EE */
+/* -------------- */
+ pseudo_bit_t rdd[0x00018]; /* Reliable Datagram Domain */
+ pseudo_bit_t reserved12[0x00008];
+/* -------------- */
+ pseudo_bit_t pd[0x00018]; /* QP protection domain. Not valid (reserved) in EE context. */
+ pseudo_bit_t reserved13[0x00008];
+/* -------------- */
+ pseudo_bit_t wqe_base_adr_h[0x00020];/* Bits 63:32 of WQE address for both SQ and RQ.
+ Reserved for EE context. */
+/* -------------- */
+ pseudo_bit_t wqe_lkey[0x00020]; /* memory key (L-Key) to be used to access WQEs. Not valid (reserved) in EE context. */
+/* -------------- */
+ pseudo_bit_t reserved14[0x00003];
+ pseudo_bit_t ssc[0x00001]; /* Send Signaled Completion
+ 1 - all send WQEs generate CQEs.
+ 0 - only send WQEs with C bit set generate completion.
+ Not valid (reserved) in EE context. */
+ pseudo_bit_t sic[0x00001]; /* If set - Ignore end to end credits on send queue. Not valid (reserved) in EE context. */
+ pseudo_bit_t cur_retry_cnt[0x00003];/* Current transport retry counter (QUERY_QPEE only).
+ The current transport retry counter can vary from retry_count down to 1, where 1 means that the last retry attempt is currently executing. */
+ pseudo_bit_t cur_rnr_retry[0x00003];/* Current RNR retry counter (QUERY_QPEE only).
+ The current RNR retry counter can vary from rnr_retry to 1, where 1 means that the last retry attempt is currently executing. */
+ pseudo_bit_t fre[0x00001]; /* Fast Registration Work Request Enabled. (Reserved for EE) */
+ pseudo_bit_t reserved15[0x00001];
+ pseudo_bit_t sae[0x00001]; /* If set - Atomic operations enabled on send queue. Not valid (reserved) in EE context. */
+ pseudo_bit_t swe[0x00001]; /* If set - RDMA - write enabled on send queue. Not valid (reserved) in EE context. */
+ pseudo_bit_t sre[0x00001]; /* If set - RDMA - read enabled on send queue. Not valid (reserved) in EE context. */
+ pseudo_bit_t retry_count[0x00003]; /* Transport timeout Retry count */
+ pseudo_bit_t reserved16[0x00002];
+ pseudo_bit_t sra_max[0x00003]; /* Maximum number of outstanding RDMA-read/Atomic operations allowed in the send queue. Maximum number is 2^SRA_Max. Must be zero in EE context. */
+ pseudo_bit_t flight_lim[0x00004]; /* Number of outstanding (in-flight) messages on the wire allowed for this send queue.
+ Number of outstanding messages is 2^Flight_Lim.
+ Use 0xF for unlimited number of outstanding messages. */
+ pseudo_bit_t ack_req_freq[0x00004]; /* ACK required frequency. ACK required bit will be set in every 2^AckReqFreq packets at least. Not valid for RD QP. */
+/* -------------- */
+ pseudo_bit_t reserved17[0x00020];
+/* -------------- */
+ pseudo_bit_t next_send_psn[0x00018];/* Next PSN to be sent */
+ pseudo_bit_t reserved18[0x00008];
+/* -------------- */
+ pseudo_bit_t cqn_snd[0x00018]; /* CQ number completions from the send queue to be reported to. Not valid (reserved) in EE context. */
+ pseudo_bit_t reserved19[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved20[0x00006];
+ pseudo_bit_t snd_wqe_base_adr_l[0x0001a];/* While opening (creating) the WQ, this field should contain the address of first descriptor to be posted. Not valid (reserved) in EE context. */
+/* -------------- */
+ pseudo_bit_t snd_db_record_index[0x00020];/* Index in the UAR Context Table Entry.
+ HW uses this index as an offset from the UAR Context Table Entry in order to read this SQ doorbell record.
+ The entry is obtained via the usr_page field.
+ Not valid for EE. */
+/* -------------- */
+ pseudo_bit_t last_acked_psn[0x00018];/* The last acknowledged PSN for the requester (QUERY_QPEE only) */
+ pseudo_bit_t reserved21[0x00008];
+/* -------------- */
+ pseudo_bit_t ssn[0x00018]; /* Requester Send Sequence Number (QUERY_QPEE only) */
+ pseudo_bit_t reserved22[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved23[0x00003];
+ pseudo_bit_t rsc[0x00001]; /* 1 - all receive WQEs generate CQEs.
+ 0 - only receive WQEs with C bit set generate completion.
+ Not valid (reserved) in EE context.
+ */
+ pseudo_bit_t ric[0x00001]; /* Invalid Credits.
+ 1 - place "Invalid Credits" to ACKs sent from this queue.
+ 0 - ACKs report the actual number of end to end credits on the connection.
+ Not valid (reserved) in EE context.
+ Must be set to 1 on QPs which are attached to SRQ. */
+ pseudo_bit_t reserved24[0x00008];
+ pseudo_bit_t rae[0x00001]; /* If set - Atomic operations enabled. on receive queue. Not valid (reserved) in EE context. */
+ pseudo_bit_t rwe[0x00001]; /* If set - RDMA - write enabled on receive queue. Not valid (reserved) in EE context. */
+ pseudo_bit_t rre[0x00001]; /* If set - RDMA - read enabled on receive queue. Not valid (reserved) in EE context. */
+ pseudo_bit_t reserved25[0x00005];
+ pseudo_bit_t rra_max[0x00003]; /* Maximum number of outstanding RDMA-read/Atomic operations allowed on receive queue is 2^RRA_Max.
+ Must be 0 for EE context. */
+ pseudo_bit_t reserved26[0x00008];
+/* -------------- */
+ pseudo_bit_t next_rcv_psn[0x00018]; /* Next (expected) PSN on receive */
+ pseudo_bit_t min_rnr_nak[0x00005]; /* Minimum RNR NAK timer value (TTTTT field encoding according to the IB spec Vol1 9.7.5.2.8).
+ Not valid (reserved) in EE context. */
+ pseudo_bit_t reserved27[0x00003];
+/* -------------- */
+ pseudo_bit_t reserved28[0x00005];
+ pseudo_bit_t ra_buff_indx[0x0001b]; /* Index to outstanding read/atomic buffer.
+ This field constructs the address to the RDB for maintaining the incoming RDMA read and atomic requests. */
+/* -------------- */
+ pseudo_bit_t cqn_rcv[0x00018]; /* CQ number completions from receive queue to be reported to. Not valid (reserved) in EE context. */
+ pseudo_bit_t reserved29[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved30[0x00006];
+ pseudo_bit_t rcv_wqe_base_adr_l[0x0001a];/* While opening (creating) the WQ, this field should contain the address of first descriptor to be posted. Not valid (reserved) in EE context. */
+/* -------------- */
+ pseudo_bit_t rcv_db_record_index[0x00020];/* Index in the UAR Context Table Entry containing the doorbell record for the receive queue.
+ HW uses this index as an offset from the UAR Context Table Entry in order to read this RQ doorbell record.
+ The entry is obtained via the usr_page field.
+ Not valid for EE. */
+/* -------------- */
+ pseudo_bit_t q_key[0x00020]; /* Q_Key to be validated against received datagrams.
+ On send datagrams, if Q_Key[31] specified in the WQE is set, then this Q_Key will be transmitted in the outgoing message.
+ Not valid (reserved) in EE context. */
+/* -------------- */
+ pseudo_bit_t srqn[0x00018]; /* SRQN - Shared Receive Queue Number - specifies the SRQ number from which the QP dequeues receive descriptors.
+ SRQN is valid only if SRQ bit is set. Not valid (reserved) in EE context. */
+ pseudo_bit_t srq[0x00001]; /* SRQ - Shared Receive Queue. If this bit is set, then the QP is associated with a SRQ. Not valid (reserved) in EE context. */
+ pseudo_bit_t reserved31[0x00007];
+/* -------------- */
+ pseudo_bit_t rmsn[0x00018]; /* Responder current message sequence number (QUERY_QPEE only) */
+ pseudo_bit_t reserved32[0x00008];
+/* -------------- */
+ pseudo_bit_t sq_wqe_counter[0x00010];/* A 16bits counter that is incremented for each WQE posted to the SQ.
+ Must be 0x0 in SQ initialization.
+ (QUERY_QPEE only). */
+ pseudo_bit_t rq_wqe_counter[0x00010];/* A 16bits counter that is incremented for each WQE posted to the RQ.
+ Must be 0x0 in RQ initialization.
+ (QUERY_QPEE only). */
+/* -------------- */
+ pseudo_bit_t reserved33[0x00040];
+/* -------------- */
+};
+
+/* Clear Interrupt [63:0] */
+
+struct arbelprm_clr_int_st { /* Little Endian */
+ pseudo_bit_t clr_int_h[0x00020]; /* Clear Interrupt [63:32]
+ Write transactions to this register will clear (de-assert) the virtual interrupt output pins of InfiniHost-III-EX. The value to be written in this register is obtained by executing QUERY_ADAPTER command on command interface after system boot.
+ This register is write-only. Reading from this register will cause undefined result
+ */
+/* -------------- */
+ pseudo_bit_t clr_int_l[0x00020]; /* Clear Interrupt [31:0]
+ Write transactions to this register will clear (de-assert) the virtual interrupt output pins of InfiniHost-III-EX. The value to be written in this register is obtained by executing QUERY_ADAPTER command on command interface after system boot.
+ This register is write-only. Reading from this register will cause undefined result */
+/* -------------- */
+};
+
+/* EQ_Arm_DB_Region */
+
+struct arbelprm_eq_arm_db_region_st { /* Little Endian */
+ pseudo_bit_t eq_x_arm_h[0x00020]; /* EQ[63:32] X state.
+ This register is used to Arm EQs when setting the appropriate bits. */
+/* -------------- */
+ pseudo_bit_t eq_x_arm_l[0x00020]; /* EQ[31:0] X state.
+ This register is used to Arm EQs when setting the appropriate bits. */
+/* -------------- */
+};
+
+/* EQ Set CI DBs Table */
+
+struct arbelprm_eq_set_ci_table_st { /* Little Endian */
+ pseudo_bit_t eq0_set_ci[0x00020]; /* EQ0_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+ pseudo_bit_t eq1_set_ci[0x00020]; /* EQ1_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00020];
+/* -------------- */
+ pseudo_bit_t eq2_set_ci[0x00020]; /* EQ2_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00020];
+/* -------------- */
+ pseudo_bit_t eq3_set_ci[0x00020]; /* EQ3_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00020];
+/* -------------- */
+ pseudo_bit_t eq4_set_ci[0x00020]; /* EQ4_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved4[0x00020];
+/* -------------- */
+ pseudo_bit_t eq5_set_ci[0x00020]; /* EQ5_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved5[0x00020];
+/* -------------- */
+ pseudo_bit_t eq6_set_ci[0x00020]; /* EQ6_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved6[0x00020];
+/* -------------- */
+ pseudo_bit_t eq7_set_ci[0x00020]; /* EQ7_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved7[0x00020];
+/* -------------- */
+ pseudo_bit_t eq8_set_ci[0x00020]; /* EQ8_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved8[0x00020];
+/* -------------- */
+ pseudo_bit_t eq9_set_ci[0x00020]; /* EQ9_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved9[0x00020];
+/* -------------- */
+ pseudo_bit_t eq10_set_ci[0x00020]; /* EQ10_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved10[0x00020];
+/* -------------- */
+ pseudo_bit_t eq11_set_ci[0x00020]; /* EQ11_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved11[0x00020];
+/* -------------- */
+ pseudo_bit_t eq12_set_ci[0x00020]; /* EQ12_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved12[0x00020];
+/* -------------- */
+ pseudo_bit_t eq13_set_ci[0x00020]; /* EQ13_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved13[0x00020];
+/* -------------- */
+ pseudo_bit_t eq14_set_ci[0x00020]; /* EQ14_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved14[0x00020];
+/* -------------- */
+ pseudo_bit_t eq15_set_ci[0x00020]; /* EQ15_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved15[0x00020];
+/* -------------- */
+ pseudo_bit_t eq16_set_ci[0x00020]; /* EQ16_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved16[0x00020];
+/* -------------- */
+ pseudo_bit_t eq17_set_ci[0x00020]; /* EQ17_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved17[0x00020];
+/* -------------- */
+ pseudo_bit_t eq18_set_ci[0x00020]; /* EQ18_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved18[0x00020];
+/* -------------- */
+ pseudo_bit_t eq19_set_ci[0x00020]; /* EQ19_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved19[0x00020];
+/* -------------- */
+ pseudo_bit_t eq20_set_ci[0x00020]; /* EQ20_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved20[0x00020];
+/* -------------- */
+ pseudo_bit_t eq21_set_ci[0x00020]; /* EQ21_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved21[0x00020];
+/* -------------- */
+ pseudo_bit_t eq22_set_ci[0x00020]; /* EQ22_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved22[0x00020];
+/* -------------- */
+ pseudo_bit_t eq23_set_ci[0x00020]; /* EQ23_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved23[0x00020];
+/* -------------- */
+ pseudo_bit_t eq24_set_ci[0x00020]; /* EQ24_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved24[0x00020];
+/* -------------- */
+ pseudo_bit_t eq25_set_ci[0x00020]; /* EQ25_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved25[0x00020];
+/* -------------- */
+ pseudo_bit_t eq26_set_ci[0x00020]; /* EQ26_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved26[0x00020];
+/* -------------- */
+ pseudo_bit_t eq27_set_ci[0x00020]; /* EQ27_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved27[0x00020];
+/* -------------- */
+ pseudo_bit_t eq28_set_ci[0x00020]; /* EQ28_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved28[0x00020];
+/* -------------- */
+ pseudo_bit_t eq29_set_ci[0x00020]; /* EQ29_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved29[0x00020];
+/* -------------- */
+ pseudo_bit_t eq30_set_ci[0x00020]; /* EQ30_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved30[0x00020];
+/* -------------- */
+ pseudo_bit_t eq31_set_ci[0x00020]; /* EQ31_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved31[0x00020];
+/* -------------- */
+ pseudo_bit_t eq32_set_ci[0x00020]; /* EQ32_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved32[0x00020];
+/* -------------- */
+ pseudo_bit_t eq33_set_ci[0x00020]; /* EQ33_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved33[0x00020];
+/* -------------- */
+ pseudo_bit_t eq34_set_ci[0x00020]; /* EQ34_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved34[0x00020];
+/* -------------- */
+ pseudo_bit_t eq35_set_ci[0x00020]; /* EQ35_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved35[0x00020];
+/* -------------- */
+ pseudo_bit_t eq36_set_ci[0x00020]; /* EQ36_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved36[0x00020];
+/* -------------- */
+ pseudo_bit_t eq37_set_ci[0x00020]; /* EQ37_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved37[0x00020];
+/* -------------- */
+ pseudo_bit_t eq38_set_ci[0x00020]; /* EQ38_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved38[0x00020];
+/* -------------- */
+ pseudo_bit_t eq39_set_ci[0x00020]; /* EQ39_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved39[0x00020];
+/* -------------- */
+ pseudo_bit_t eq40_set_ci[0x00020]; /* EQ40_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved40[0x00020];
+/* -------------- */
+ pseudo_bit_t eq41_set_ci[0x00020]; /* EQ41_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved41[0x00020];
+/* -------------- */
+ pseudo_bit_t eq42_set_ci[0x00020]; /* EQ42_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved42[0x00020];
+/* -------------- */
+ pseudo_bit_t eq43_set_ci[0x00020]; /* EQ43_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved43[0x00020];
+/* -------------- */
+ pseudo_bit_t eq44_set_ci[0x00020]; /* EQ44_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved44[0x00020];
+/* -------------- */
+ pseudo_bit_t eq45_set_ci[0x00020]; /* EQ45_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved45[0x00020];
+/* -------------- */
+ pseudo_bit_t eq46_set_ci[0x00020]; /* EQ46_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved46[0x00020];
+/* -------------- */
+ pseudo_bit_t eq47_set_ci[0x00020]; /* EQ47_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved47[0x00020];
+/* -------------- */
+ pseudo_bit_t eq48_set_ci[0x00020]; /* EQ48_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved48[0x00020];
+/* -------------- */
+ pseudo_bit_t eq49_set_ci[0x00020]; /* EQ49_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved49[0x00020];
+/* -------------- */
+ pseudo_bit_t eq50_set_ci[0x00020]; /* EQ50_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved50[0x00020];
+/* -------------- */
+ pseudo_bit_t eq51_set_ci[0x00020]; /* EQ51_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved51[0x00020];
+/* -------------- */
+ pseudo_bit_t eq52_set_ci[0x00020]; /* EQ52_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved52[0x00020];
+/* -------------- */
+ pseudo_bit_t eq53_set_ci[0x00020]; /* EQ53_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved53[0x00020];
+/* -------------- */
+ pseudo_bit_t eq54_set_ci[0x00020]; /* EQ54_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved54[0x00020];
+/* -------------- */
+ pseudo_bit_t eq55_set_ci[0x00020]; /* EQ55_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved55[0x00020];
+/* -------------- */
+ pseudo_bit_t eq56_set_ci[0x00020]; /* EQ56_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved56[0x00020];
+/* -------------- */
+ pseudo_bit_t eq57_set_ci[0x00020]; /* EQ57_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved57[0x00020];
+/* -------------- */
+ pseudo_bit_t eq58_set_ci[0x00020]; /* EQ58_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved58[0x00020];
+/* -------------- */
+ pseudo_bit_t eq59_set_ci[0x00020]; /* EQ59_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved59[0x00020];
+/* -------------- */
+ pseudo_bit_t eq60_set_ci[0x00020]; /* EQ60_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved60[0x00020];
+/* -------------- */
+ pseudo_bit_t eq61_set_ci[0x00020]; /* EQ61_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved61[0x00020];
+/* -------------- */
+ pseudo_bit_t eq62_set_ci[0x00020]; /* EQ62_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved62[0x00020];
+/* -------------- */
+ pseudo_bit_t eq63_set_ci[0x00020]; /* EQ63_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved63[0x00020];
+/* -------------- */
+};
+
+/* InfiniHost-III-EX Configuration Registers */
+
+struct arbelprm_configuration_registers_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x403400];
+/* -------------- */
+ struct arbelprm_hca_command_register_st hca_command_interface_register;/* HCA Command Register */
+/* -------------- */
+ pseudo_bit_t reserved1[0x3fcb20];
+/* -------------- */
+};
+
+/* QP_DB_Record */
+
+struct arbelprm_qp_db_record_st { /* Little Endian */
+ pseudo_bit_t counter[0x00010]; /* Modulo-64K counter of WQEs posted to the QP since its creation. Should be initialized to zero. */
+ pseudo_bit_t reserved0[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00005];
+ pseudo_bit_t res[0x00003]; /* 0x3 for SQ
+ 0x4 for RQ
+ 0x5 for SRQ */
+ pseudo_bit_t qp_number[0x00018]; /* QP number */
+/* -------------- */
+};
+
+/* CQ_ARM_DB_Record */
+
+struct arbelprm_cq_arm_db_record_st { /* Little Endian */
+ pseudo_bit_t counter[0x00020]; /* CQ counter for the arming request */
+/* -------------- */
+ pseudo_bit_t cmd[0x00003]; /* 0x0 - No command
+ 0x1 - Request notification for next Solicited completion event. Counter filed specifies the current CQ Consumer Counter.
+ 0x2 - Request notification for next Solicited or Unsolicited completion event. Counter filed specifies the current CQ Consumer counter.
+ 0x3 - Request notification for multiple completions (Arm-N). Counter filed specifies the value of the CQ Index that when reached by HW (i.e. HW generates a CQE into this Index) Event will be generated
+ Other - Reserved */
+ pseudo_bit_t cmd_sn[0x00002]; /* Command Sequence Number - See Table 35, "CQ Doorbell Layout" for definition of this filed */
+ pseudo_bit_t res[0x00003]; /* Must be 0x2 */
+ pseudo_bit_t cq_number[0x00018]; /* CQ number */
+/* -------------- */
+};
+
+/* CQ_CI_DB_Record */
+
+struct arbelprm_cq_ci_db_record_st { /* Little Endian */
+ pseudo_bit_t counter[0x00020]; /* CQ counter */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00005];
+ pseudo_bit_t res[0x00003]; /* Must be 0x1 */
+ pseudo_bit_t cq_number[0x00018]; /* CQ number */
+/* -------------- */
+};
+
+/* Virtual_Physical_Mapping */
+
+struct arbelprm_virtual_physical_mapping_st { /* Little Endian */
+ pseudo_bit_t va_h[0x00020]; /* Virtual Address[63:32]. Valid only for MAP_ICM command. */
+/* -------------- */
+ pseudo_bit_t reserved0[0x0000c];
+ pseudo_bit_t va_l[0x00014]; /* Virtual Address[31:12]. Valid only for MAP_ICM command. */
+/* -------------- */
+ pseudo_bit_t pa_h[0x00020]; /* Physical Address[63:32] */
+/* -------------- */
+ pseudo_bit_t log2size[0x00006]; /* Log2 of the size in 4KB pages of the physical and virtual contiguous memory that starts at PA_L/H and VA_L/H */
+ pseudo_bit_t reserved1[0x00006];
+ pseudo_bit_t pa_l[0x00014]; /* Physical Address[31:12] */
+/* -------------- */
+};
+
+/* MOD_STAT_CFG */
+
+struct arbelprm_mod_stat_cfg_st { /* Little Endian */
+ pseudo_bit_t log_max_srqs[0x00005]; /* Log (base 2) of the number of SRQs to allocate (0 if no SRQs are required), valid only if srq bit is set. */
+ pseudo_bit_t reserved0[0x00001];
+ pseudo_bit_t srq[0x00001]; /* When set SRQs are supported */
+ pseudo_bit_t srq_m[0x00001]; /* Modify SRQ parameters */
+ pseudo_bit_t reserved1[0x00018];
+/* -------------- */
+ pseudo_bit_t reserved2[0x007e0];
+/* -------------- */
+};
+
+/* SRQ Context */
+
+struct arbelprm_srq_context_st { /* Little Endian */
+ pseudo_bit_t srqn[0x00018]; /* SRQ number */
+ pseudo_bit_t log_srq_size[0x00004]; /* Log2 of the Number of WQEs in the Receive Queue.
+ Maximum value is 0x10, i.e. 16M WQEs. */
+ pseudo_bit_t state[0x00004]; /* SRQ State:
+ 1111 - SW Ownership
+ 0000 - HW Ownership
+ 0001 - Error
+ Valid only on QUERY_SRQ and HW2SW_SRQ commands. */
+/* -------------- */
+ pseudo_bit_t l_key[0x00020]; /* memory key (L-Key) to be used to access WQEs. */
+/* -------------- */
+ pseudo_bit_t srq_db_record_index[0x00020];/* Index in the UAR Context Table Entry containing the doorbell record for the receive queue.
+ HW uses this index as an offset from the UAR Context Table Entry in order to read this SRQ doorbell record.
+ The entry is obtained via the usr_page field. */
+/* -------------- */
+ pseudo_bit_t usr_page[0x00018]; /* Index (offset) of user page allocated for this SRQ (see "non_privileged Access to the HCA Hardware"). Not valid (reserved) in EE context. */
+ pseudo_bit_t reserved0[0x00005];
+ pseudo_bit_t log_rq_stride[0x00003];/* Stride (max WQE size) on the receive queue. WQ entry is 16*(2^log_RQ_stride) bytes. */
+/* -------------- */
+ pseudo_bit_t wqe_addr_h[0x00020]; /* Bits 63:32 of WQE address (WQE base address) */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00006];
+ pseudo_bit_t srq_wqe_base_adr_l[0x0001a];/* While opening (creating) the SRQ, this field should contain the address of first descriptor to be posted. */
+/* -------------- */
+ pseudo_bit_t pd[0x00018]; /* SRQ protection domain. */
+ pseudo_bit_t reserved2[0x00008];
+/* -------------- */
+ pseudo_bit_t wqe_cnt[0x00010]; /* WQE count on the SRQ.
+ Valid only on QUERY_SRQ and HW2SW_SRQ commands. */
+ pseudo_bit_t lwm[0x00010]; /* Limit Water Mark - if the LWM is not zero, and the wqe_cnt drops below LWM when a WQE is dequeued from the SRQ, then a SRQ limit event is fired and the LWM is set to zero. */
+/* -------------- */
+ pseudo_bit_t srq_wqe_counter[0x00010];/* A 16bits counter that is incremented for each WQE posted to the SQ.
+ Must be 0x0 in SRQ initialization.
+ (QUERY_SRQ only). */
+ pseudo_bit_t reserved3[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved4[0x00060];
+/* -------------- */
+};
+
+/* PBL */
+
+struct arbelprm_pbl_st { /* Little Endian */
+ pseudo_bit_t mtt_0_h[0x00020]; /* First MTT[63:32] */
+/* -------------- */
+ pseudo_bit_t mtt_0_l[0x00020]; /* First MTT[31:0] */
+/* -------------- */
+ pseudo_bit_t mtt_1_h[0x00020]; /* Second MTT[63:32] */
+/* -------------- */
+ pseudo_bit_t mtt_1_l[0x00020]; /* Second MTT[31:0] */
+/* -------------- */
+ pseudo_bit_t mtt_2_h[0x00020]; /* Third MTT[63:32] */
+/* -------------- */
+ pseudo_bit_t mtt_2_l[0x00020]; /* Third MTT[31:0] */
+/* -------------- */
+ pseudo_bit_t mtt_3_h[0x00020]; /* Fourth MTT[63:32] */
+/* -------------- */
+ pseudo_bit_t mtt_3_l[0x00020]; /* Fourth MTT[31:0] */
+/* -------------- */
+};
+
+/* Performance Counters */
+
+struct arbelprm_performance_counters_st { /* Little Endian */
+ pseudo_bit_t sqpc_access_cnt[0x00020];/* SQPC cache access count */
+/* -------------- */
+ pseudo_bit_t sqpc_miss_cnt[0x00020];/* SQPC cache miss count */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00040];
+/* -------------- */
+ pseudo_bit_t rqpc_access_cnt[0x00020];/* RQPC cache access count */
+/* -------------- */
+ pseudo_bit_t rqpc_miss_cnt[0x00020];/* RQPC cache miss count */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00040];
+/* -------------- */
+ pseudo_bit_t cqc_access_cnt[0x00020];/* CQC cache access count */
+/* -------------- */
+ pseudo_bit_t cqc_miss_cnt[0x00020]; /* CQC cache miss count */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00040];
+/* -------------- */
+ pseudo_bit_t tpt_access_cnt[0x00020];/* TPT cache access count */
+/* -------------- */
+ pseudo_bit_t mpt_miss_cnt[0x00020]; /* MPT cache miss count */
+/* -------------- */
+ pseudo_bit_t mtt_miss_cnt[0x00020]; /* MTT cache miss count */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00620];
+/* -------------- */
+};
+
+/* Transport and CI Error Counters */
+
+struct arbelprm_transport_and_ci_error_counters_st { /* Little Endian */
+ pseudo_bit_t rq_num_lle[0x00020]; /* Responder - number of local length errors */
+/* -------------- */
+ pseudo_bit_t sq_num_lle[0x00020]; /* Requester - number of local length errors */
+/* -------------- */
+ pseudo_bit_t rq_num_lqpoe[0x00020]; /* Responder - number local QP operation error */
+/* -------------- */
+ pseudo_bit_t sq_num_lqpoe[0x00020]; /* Requester - number local QP operation error */
+/* -------------- */
+ pseudo_bit_t rq_num_leeoe[0x00020]; /* Responder - number local EE operation error */
+/* -------------- */
+ pseudo_bit_t sq_num_leeoe[0x00020]; /* Requester - number local EE operation error */
+/* -------------- */
+ pseudo_bit_t rq_num_lpe[0x00020]; /* Responder - number of local protection errors */
+/* -------------- */
+ pseudo_bit_t sq_num_lpe[0x00020]; /* Requester - number of local protection errors */
+/* -------------- */
+ pseudo_bit_t rq_num_wrfe[0x00020]; /* Responder - number of CQEs with error.
+ Incremented each time a CQE with error is generated */
+/* -------------- */
+ pseudo_bit_t sq_num_wrfe[0x00020]; /* Requester - number of CQEs with error.
+ Incremented each time a CQE with error is generated */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+ pseudo_bit_t sq_num_mwbe[0x00020]; /* Requester - number of memory window bind errors */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00020];
+/* -------------- */
+ pseudo_bit_t sq_num_bre[0x00020]; /* Requester - number of bad response errors */
+/* -------------- */
+ pseudo_bit_t rq_num_lae[0x00020]; /* Responder - number of local access errors */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00040];
+/* -------------- */
+ pseudo_bit_t sq_num_rire[0x00020]; /* Requester - number of remote invalid request errors
+ NAK-Invalid Request on:
+ 1. Unsupported OpCode: Responder detected an unsupported OpCode.
+ 2. Unexpected OpCode: Responder detected an error in the sequence of OpCodes, such
+ as a missing "Last" packet.
+ Note: there is no PSN error, thus this does not indicate a dropped packet. */
+/* -------------- */
+ pseudo_bit_t rq_num_rire[0x00020]; /* Responder - number of remote invalid request errors.
+ NAK may or may not be sent.
+ 1. QP Async Affiliated Error: Unsupported or Reserved OpCode (RC,RD only):
+ Inbound request OpCode was either reserved, or was for a function not supported by this
+ QP. (E.g. RDMA or ATOMIC on QP not set up for this).
+ 2. Misaligned ATOMIC: VA does not point to an aligned address on an atomic opera-tion.
+ 3. Too many RDMA READ or ATOMIC Requests: There were more requests received
+ and not ACKed than allowed for the connection.
+ 4. Out of Sequence OpCode, current packet is "First" or "Only": The Responder
+ detected an error in the sequence of OpCodes; a missing "Last" packet
+ 5. Out of Sequence OpCode, current packet is not "First" or "Only": The Responder
+ detected an error in the sequence of OpCodes; a missing "First" packet
+ 6. Local Length Error: Inbound "Send" request message exceeded the responder.s avail-able
+ buffer space.
+ 7. Length error: RDMA WRITE request message contained too much or too little pay-load
+ data compared to the DMA length advertised in the first or only packet.
+ 8. Length error: Payload length was not consistent with the opcode:
+ a: 0 byte <= "only" <= PMTU bytes
+ b: ("first" or "middle") == PMTU bytes
+ c: 1byte <= "last" <= PMTU bytes
+ 9. Length error: Inbound message exceeded the size supported by the CA port. */
+/* -------------- */
+ pseudo_bit_t sq_num_rae[0x00020]; /* Requester - number of remote access errors.
+ NAK-Remote Access Error on:
+ R_Key Violation: Responder detected an invalid R_Key while executing an RDMA
+ Request. */
+/* -------------- */
+ pseudo_bit_t rq_num_rae[0x00020]; /* Responder - number of remote access errors.
+ R_Key Violation Responder detected an R_Key violation while executing an RDMA
+ request.
+ NAK may or may not be sent. */
+/* -------------- */
+ pseudo_bit_t sq_num_roe[0x00020]; /* Requester - number of remote operation errors.
+ NAK-Remote Operation Error on:
+ Remote Operation Error: Responder encountered an error, (local to the responder),
+ which prevented it from completing the request. */
+/* -------------- */
+ pseudo_bit_t rq_num_roe[0x00020]; /* Responder - number of remote operation errors.
+ NAK-Remote Operation Error on:
+ 1. Malformed WQE: Responder detected a malformed Receive Queue WQE while pro-cessing
+ the packet.
+ 2. Remote Operation Error: Responder encountered an error, (local to the responder),
+ which prevented it from completing the request. */
+/* -------------- */
+ pseudo_bit_t sq_num_tree[0x00020]; /* Requester - number of transport retries exceeded errors */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00020];
+/* -------------- */
+ pseudo_bit_t sq_num_rree[0x00020]; /* Requester - number of RNR nak retries exceeded errors */
+/* -------------- */
+ pseudo_bit_t reserved4[0x00020];
+/* -------------- */
+ pseudo_bit_t sq_num_lrdve[0x00020]; /* Requester - number of local RDD violation errors */
+/* -------------- */
+ pseudo_bit_t rq_num_rirdre[0x00020];/* Responder - number of remote invalid RD request errors */
+/* -------------- */
+ pseudo_bit_t reserved5[0x00040];
+/* -------------- */
+ pseudo_bit_t sq_num_rabrte[0x00020];/* Requester - number of remote aborted errors */
+/* -------------- */
+ pseudo_bit_t reserved6[0x00020];
+/* -------------- */
+ pseudo_bit_t sq_num_ieecne[0x00020];/* Requester - number of invalid EE context number errors */
+/* -------------- */
+ pseudo_bit_t reserved7[0x00020];
+/* -------------- */
+ pseudo_bit_t sq_num_ieecse[0x00020];/* Requester - invalid EE context state errors */
+/* -------------- */
+ pseudo_bit_t reserved8[0x00380];
+/* -------------- */
+ pseudo_bit_t rq_num_oos[0x00020]; /* Responder - number of out of sequence requests received */
+/* -------------- */
+ pseudo_bit_t sq_num_oos[0x00020]; /* Requester - number of out of sequence Naks received */
+/* -------------- */
+ pseudo_bit_t rq_num_mce[0x00020]; /* Responder - number of bad multicast packets received */
+/* -------------- */
+ pseudo_bit_t reserved9[0x00020];
+/* -------------- */
+ pseudo_bit_t rq_num_rsync[0x00020]; /* Responder - number of RESYNC operations */
+/* -------------- */
+ pseudo_bit_t sq_num_rsync[0x00020]; /* Requester - number of RESYNC operations */
+/* -------------- */
+ pseudo_bit_t rq_num_udsdprd[0x00020];/* The number of UD packets silently discarded on the receive queue due to lack of receive descriptor. */
+/* -------------- */
+ pseudo_bit_t reserved10[0x00020];
+/* -------------- */
+ pseudo_bit_t rq_num_ucsdprd[0x00020];/* The number of UC packets silently discarded on the receive queue due to lack of receive descriptor. */
+/* -------------- */
+ pseudo_bit_t reserved11[0x003e0];
+/* -------------- */
+ pseudo_bit_t num_cqovf[0x00020]; /* Number of CQ overflows */
+/* -------------- */
+ pseudo_bit_t num_eqovf[0x00020]; /* Number of EQ overflows */
+/* -------------- */
+ pseudo_bit_t num_baddb[0x00020]; /* Number of bad doorbells */
+/* -------------- */
+ pseudo_bit_t reserved12[0x002a0];
+/* -------------- */
+};
+
+/* Event_data Field - HCR Completion Event */
+
+struct arbelprm_hcr_completion_event_st { /* Little Endian */
+ pseudo_bit_t token[0x00010]; /* HCR Token */
+ pseudo_bit_t reserved0[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00020];
+/* -------------- */
+ pseudo_bit_t status[0x00008]; /* HCR Status */
+ pseudo_bit_t reserved2[0x00018];
+/* -------------- */
+ pseudo_bit_t out_param_h[0x00020]; /* HCR Output Parameter [63:32] */
+/* -------------- */
+ pseudo_bit_t out_param_l[0x00020]; /* HCR Output Parameter [31:0] */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00020];
+/* -------------- */
+};
+
+/* Completion with Error CQE */
+
+struct arbelprm_completion_with_error_st { /* Little Endian */
+ pseudo_bit_t myqpn[0x00018]; /* Indicates the QP for which completion is being reported */
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00060];
+/* -------------- */
+ pseudo_bit_t reserved2[0x00010];
+ pseudo_bit_t vendor_code[0x00008];
+ pseudo_bit_t syndrome[0x00008]; /* Completion with error syndrome:
+ 0x01 - Local Length Error
+ 0x02 - Local QP Operation Error
+ 0x03 - Local EE Context Operation Error
+ 0x04 - Local Protection Error
+ 0x05 - Work Request Flushed Error
+ 0x06 - Memory Window Bind Error
+ 0x10 - Bad Response Error
+ 0x11 - Local Access Error
+ 0x12 - Remote Invalid Request Error
+ 0x13 - Remote Access Error
+ 0x14 - Remote Operation Error
+ 0x15 - Transport Retry Counter Exceeded
+ 0x16 - RNR Retry Counter Exceeded
+ 0x20 - Local RDD Violation Error
+ 0x21 - Remote Invalid RD Request
+ 0x22 - Remote Aborted Error
+ 0x23 - Invalid EE Context Number
+ 0x24 - Invalid EE Context State
+ other - Reserved
+ Syndrome is defined according to the IB specification volume 1. For detailed explanation of the syndromes, refer to chapters 10-11 of the IB specification rev 1.1. */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved4[0x00006];
+ pseudo_bit_t wqe_addr[0x0001a]; /* Bits 31:6 of WQE virtual address completion is reported for. The 6 least significant bits are zero. */
+/* -------------- */
+ pseudo_bit_t reserved5[0x00007];
+ pseudo_bit_t owner[0x00001]; /* Owner field. Zero value of this field means SW ownership of CQE. */
+ pseudo_bit_t reserved6[0x00010];
+ pseudo_bit_t opcode[0x00008]; /* The opcode of WQE completion is reported for.
+
+ The following values are reported in case of completion with error:
+ 0xFE - For completion with error on Receive Queues
+ 0xFF - For completion with error on Send Queues */
+/* -------------- */
+};
+
+/* Resize CQ Input Mailbox */
+
+struct arbelprm_resize_cq_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+ pseudo_bit_t start_addr_h[0x00020]; /* Start address of CQ[63:32].
+ Must be aligned on CQE size (32 bytes) */
+/* -------------- */
+ pseudo_bit_t start_addr_l[0x00020]; /* Start address of CQ[31:0].
+ Must be aligned on CQE size (32 bytes) */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00018];
+ pseudo_bit_t log_cq_size[0x00005]; /* Log (base 2) of the CQ size (in entries) */
+ pseudo_bit_t reserved2[0x00003];
+/* -------------- */
+ pseudo_bit_t reserved3[0x00060];
+/* -------------- */
+ pseudo_bit_t l_key[0x00020]; /* Memory key (L_Key) to be used to access CQ */
+/* -------------- */
+ pseudo_bit_t reserved4[0x00100];
+/* -------------- */
+};
+
+/* MAD_IFC Input Modifier */
+
+struct arbelprm_mad_ifc_input_modifier_st { /* Little Endian */
+ pseudo_bit_t port_number[0x00008]; /* The packet reception port number (1 or 2). */
+ pseudo_bit_t mad_extended_info[0x00001];/* Mad_Extended_Info valid bit (MAD_IFC Input Mailbox data from offset 00100h and down). MAD_Extended_Info is read only if this bit is set.
+ Required for trap generation when BKey check is enabled and for global routed packets. */
+ pseudo_bit_t reserved0[0x00007];
+ pseudo_bit_t rlid[0x00010]; /* Remote (source) LID from the received MAD.
+ This field is required for trap generation upon MKey/BKey validation. */
+/* -------------- */
+};
+
+/* MAD_IFC Input Mailbox */
+
+struct arbelprm_mad_ifc_st { /* Little Endian */
+ pseudo_bit_t request_mad_packet[64][0x00020];/* Request MAD Packet (256bytes) */
+/* -------------- */
+ pseudo_bit_t my_qpn[0x00018]; /* Destination QP number from the received MAD.
+ This field is reserved if Mad_extended_info indication in the input modifier is clear. */
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t rqpn[0x00018]; /* Remote (source) QP number from the received MAD.
+ This field is reserved if Mad_extended_info indication in the input modifier is clear. */
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t rlid[0x00010]; /* Remote (source) LID from the received MAD.
+ This field is reserved if Mad_extended_info indication in the input modifier is clear. */
+ pseudo_bit_t ml_path[0x00007]; /* My (destination) LID path bits from the received MAD.
+ This field is reserved if Mad_extended_info indication in the input modifier is clear. */
+ pseudo_bit_t g[0x00001]; /* If set, the GRH field in valid.
+ This field is reserved if Mad_extended_info indication in the input modifier is clear. */
+ pseudo_bit_t reserved2[0x00004];
+ pseudo_bit_t sl[0x00004]; /* Service Level of the received MAD.
+ This field is reserved if Mad_extended_info indication in the input modifier is clear. */
+/* -------------- */
+ pseudo_bit_t pkey_indx[0x00010]; /* Index in PKey table that matches PKey of the received MAD.
+ This field is reserved if Mad_extended_info indication in the input modifier is clear. */
+ pseudo_bit_t reserved3[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved4[0x00180];
+/* -------------- */
+ pseudo_bit_t grh[10][0x00020]; /* The GRH field of the MAD packet that was scattered to the first 40 bytes pointed to by the scatter list.
+ Valid if Mad_extended_info bit (in the input modifier) and g bit are set.
+ Otherwise this field is reserved. */
+/* -------------- */
+ pseudo_bit_t reserved5[0x004c0];
+/* -------------- */
+};
+
+/* Query Debug Message */
+
+struct arbelprm_query_debug_msg_st { /* Little Endian */
+ pseudo_bit_t phy_addr_h[0x00020]; /* Translation of the address in firmware area. High 32 bits. */
+/* -------------- */
+ pseudo_bit_t v[0x00001]; /* Physical translation is valid */
+ pseudo_bit_t reserved0[0x0000b];
+ pseudo_bit_t phy_addr_l[0x00014]; /* Translation of the address in firmware area. Low 32 bits. */
+/* -------------- */
+ pseudo_bit_t fw_area_base[0x00020]; /* Firmware area base address. The format strings and the trace buffers may be located starting from this address. */
+/* -------------- */
+ pseudo_bit_t fw_area_size[0x00020]; /* Firmware area size */
+/* -------------- */
+ pseudo_bit_t trc_hdr_sz[0x00020]; /* Trace message header size in dwords. */
+/* -------------- */
+ pseudo_bit_t trc_arg_num[0x00020]; /* The number of arguments per trace message. */
+/* -------------- */
+ pseudo_bit_t reserved1[0x000c0];
+/* -------------- */
+ pseudo_bit_t dbg_msk_h[0x00020]; /* Debug messages mask [63:32] */
+/* -------------- */
+ pseudo_bit_t dbg_msk_l[0x00020]; /* Debug messages mask [31:0] */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00040];
+/* -------------- */
+ pseudo_bit_t buff0_addr[0x00020]; /* Address in firmware area of Trace Buffer 0 */
+/* -------------- */
+ pseudo_bit_t buff0_size[0x00020]; /* Size of Trace Buffer 0 */
+/* -------------- */
+ pseudo_bit_t buff1_addr[0x00020]; /* Address in firmware area of Trace Buffer 1 */
+/* -------------- */
+ pseudo_bit_t buff1_size[0x00020]; /* Size of Trace Buffer 1 */
+/* -------------- */
+ pseudo_bit_t buff2_addr[0x00020]; /* Address in firmware area of Trace Buffer 2 */
+/* -------------- */
+ pseudo_bit_t buff2_size[0x00020]; /* Size of Trace Buffer 2 */
+/* -------------- */
+ pseudo_bit_t buff3_addr[0x00020]; /* Address in firmware area of Trace Buffer 3 */
+/* -------------- */
+ pseudo_bit_t buff3_size[0x00020]; /* Size of Trace Buffer 3 */
+/* -------------- */
+ pseudo_bit_t buff4_addr[0x00020]; /* Address in firmware area of Trace Buffer 4 */
+/* -------------- */
+ pseudo_bit_t buff4_size[0x00020]; /* Size of Trace Buffer 4 */
+/* -------------- */
+ pseudo_bit_t buff5_addr[0x00020]; /* Address in firmware area of Trace Buffer 5 */
+/* -------------- */
+ pseudo_bit_t buff5_size[0x00020]; /* Size of Trace Buffer 5 */
+/* -------------- */
+ pseudo_bit_t buff6_addr[0x00020]; /* Address in firmware area of Trace Buffer 6 */
+/* -------------- */
+ pseudo_bit_t buff6_size[0x00020]; /* Size of Trace Buffer 6 */
+/* -------------- */
+ pseudo_bit_t buff7_addr[0x00020]; /* Address in firmware area of Trace Buffer 7 */
+/* -------------- */
+ pseudo_bit_t buff7_size[0x00020]; /* Size of Trace Buffer 7 */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00400];
+/* -------------- */
+};
+
+/* User Access Region */
+
+struct arbelprm_uar_st { /* Little Endian */
+ struct arbelprm_rd_send_doorbell_st rd_send_doorbell;/* Reliable Datagram send doorbell */
+/* -------------- */
+ struct arbelprm_send_doorbell_st send_doorbell;/* Send doorbell */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00040];
+/* -------------- */
+ struct arbelprm_cq_cmd_doorbell_st cq_command_doorbell;/* CQ Doorbell */
+/* -------------- */
+ pseudo_bit_t reserved1[0x03ec0];
+/* -------------- */
+};
+
+/* Receive doorbell */
+
+struct arbelprm_receive_doorbell_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t wqe_counter[0x00010]; /* Modulo-64K counter of WQEs posted on this queue since its creation. Should be zero for the first doorbell on the QP */
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved2[0x00005];
+ pseudo_bit_t srq[0x00001]; /* If set, this is a Shared Receive Queue */
+ pseudo_bit_t reserved3[0x00002];
+ pseudo_bit_t qpn[0x00018]; /* QP number or SRQ number this doorbell is rung on */
+/* -------------- */
+};
+
+/* SET_IB Parameters */
+
+struct arbelprm_set_ib_st { /* Little Endian */
+ pseudo_bit_t rqk[0x00001]; /* Reset QKey Violation Counter */
+ pseudo_bit_t reserved0[0x00011];
+ pseudo_bit_t sig[0x00001]; /* Set System Image GUID to system_image_guid specified.
+ system_image_guid and sig must be the same for all ports. */
+ pseudo_bit_t reserved1[0x0000d];
+/* -------------- */
+ pseudo_bit_t capability_mask[0x00020];/* PortInfo Capability Mask */
+/* -------------- */
+ pseudo_bit_t system_image_guid_h[0x00020];/* System Image GUID[63:32], takes effect only if the SIG bit is set
+ Must be the same for both ports. */
+/* -------------- */
+ pseudo_bit_t system_image_guid_l[0x00020];/* System Image GUID[31:0], takes effect only if the SIG bit is set
+ Must be the same for both ports. */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00180];
+/* -------------- */
+};
+
+/* Multicast Group Member */
+
+struct arbelprm_mgm_entry_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00006];
+ pseudo_bit_t next_gid_index[0x0001a];/* Index of next Multicast Group Member whose GID maps to same MGID_HASH number.
+ The index is into the Multicast Group Table, which is the comprised the MGHT and AMGM tables.
+ next_gid_index=0 means end of the chain. */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00060];
+/* -------------- */
+ pseudo_bit_t mgid_128_96[0x00020]; /* Multicast group GID[128:96] in big endian format.
+ Use the Reserved GID 0:0:0:0:0:0:0:0 for an invalid entry. */
+/* -------------- */
+ pseudo_bit_t mgid_95_64[0x00020]; /* Multicast group GID[95:64] in big endian format.
+ Use the Reserved GID 0:0:0:0:0:0:0:0 for an invalid entry. */
+/* -------------- */
+ pseudo_bit_t mgid_63_32[0x00020]; /* Multicast group GID[63:32] in big endian format.
+ Use the Reserved GID 0:0:0:0:0:0:0:0 for an invalid entry. */
+/* -------------- */
+ pseudo_bit_t mgid_31_0[0x00020]; /* Multicast group GID[31:0] in big endian format.
+ Use the Reserved GID 0:0:0:0:0:0:0:0 for an invalid entry. */
+/* -------------- */
+ struct arbelprm_mgmqp_st mgmqp_0; /* Multicast Group Member QP */
+/* -------------- */
+ struct arbelprm_mgmqp_st mgmqp_1; /* Multicast Group Member QP */
+/* -------------- */
+ struct arbelprm_mgmqp_st mgmqp_2; /* Multicast Group Member QP */
+/* -------------- */
+ struct arbelprm_mgmqp_st mgmqp_3; /* Multicast Group Member QP */
+/* -------------- */
+ struct arbelprm_mgmqp_st mgmqp_4; /* Multicast Group Member QP */
+/* -------------- */
+ struct arbelprm_mgmqp_st mgmqp_5; /* Multicast Group Member QP */
+/* -------------- */
+ struct arbelprm_mgmqp_st mgmqp_6; /* Multicast Group Member QP */
+/* -------------- */
+ struct arbelprm_mgmqp_st mgmqp_7; /* Multicast Group Member QP */
+/* -------------- */
+};
+
+/* INIT_IB Parameters */
+
+struct arbelprm_init_ib_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00004];
+ pseudo_bit_t vl_cap[0x00004]; /* Maximum VLs supported on the port, excluding VL15.
+ Legal values are 1,2,4 and 8. */
+ pseudo_bit_t port_width_cap[0x00004];/* IB Port Width
+ 1 - 1x
+ 3 - 1x, 4x
+ 11 - 1x, 4x or 12x (must not be used in InfiniHost-III-EX MT25208)
+ else - Reserved */
+ pseudo_bit_t mtu_cap[0x00004]; /* Maximum MTU Supported
+ 0x0 - Reserved
+ 0x1 - 256
+ 0x2 - 512
+ 0x3 - 1024
+ 0x4 - 2048
+ 0x5 - 0xF Reserved */
+ pseudo_bit_t g0[0x00001]; /* Set port GUID0 to GUID0 specified */
+ pseudo_bit_t ng[0x00001]; /* Set node GUID to node_guid specified.
+ node_guid and ng must be the same for all ports. */
+ pseudo_bit_t sig[0x00001]; /* Set System Image GUID to system_image_guid specified.
+ system_image_guid and sig must be the same for all ports. */
+ pseudo_bit_t reserved1[0x0000d];
+/* -------------- */
+ pseudo_bit_t max_gid[0x00010]; /* Maximum number of GIDs for the port */
+ pseudo_bit_t reserved2[0x00010];
+/* -------------- */
+ pseudo_bit_t max_pkey[0x00010]; /* Maximum pkeys for the port.
+ Must be the same for both ports. */
+ pseudo_bit_t reserved3[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved4[0x00020];
+/* -------------- */
+ pseudo_bit_t guid0_h[0x00020]; /* EUI-64 GUID assigned by the manufacturer, takes effect only if the G0 bit is set (bits 63:32) */
+/* -------------- */
+ pseudo_bit_t guid0_l[0x00020]; /* EUI-64 GUID assigned by the manufacturer, takes effect only if the G0 bit is set (bits 31:0) */
+/* -------------- */
+ pseudo_bit_t node_guid_h[0x00020]; /* Node GUID[63:32], takes effect only if the NG bit is set
+ Must be the same for both ports. */
+/* -------------- */
+ pseudo_bit_t node_guid_l[0x00020]; /* Node GUID[31:0], takes effect only if the NG bit is set
+ Must be the same for both ports. */
+/* -------------- */
+ pseudo_bit_t system_image_guid_h[0x00020];/* System Image GUID[63:32], takes effect only if the SIG bit is set
+ Must be the same for both ports. */
+/* -------------- */
+ pseudo_bit_t system_image_guid_l[0x00020];/* System Image GUID[31:0], takes effect only if the SIG bit is set
+ Must be the same for both ports. */
+/* -------------- */
+ pseudo_bit_t reserved5[0x006c0];
+/* -------------- */
+};
+
+/* Query Device Limitations */
+
+struct arbelprm_query_dev_lim_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00080];
+/* -------------- */
+ pseudo_bit_t log_max_qp[0x00005]; /* Log2 of the Maximum number of QPs supported */
+ pseudo_bit_t reserved1[0x00003];
+ pseudo_bit_t log2_rsvd_qps[0x00004];/* Log (base 2) of the number of QPs reserved for firmware use
+ The reserved resources are numbered from 0 to 2^log2_rsvd_qps-1 */
+ pseudo_bit_t reserved2[0x00004];
+ pseudo_bit_t log_max_qp_sz[0x00008];/* The maximum number of WQEs allowed on the RQ or the SQ is 2^log_max_qp_sz-1 */
+ pseudo_bit_t log_max_srq_sz[0x00008];/* The maximum number of WQEs allowed on the SRQ is 2^log_max_srq_sz-1 */
+/* -------------- */
+ pseudo_bit_t log_max_ee[0x00005]; /* Log2 of the Maximum number of EE contexts supported */
+ pseudo_bit_t reserved3[0x00003];
+ pseudo_bit_t log2_rsvd_ees[0x00004];/* Log (base 2) of the number of EECs reserved for firmware use
+ The reserved resources are numbered from 0 to 2^log2_rsvd_ees-1 */
+ pseudo_bit_t reserved4[0x00004];
+ pseudo_bit_t log_max_srqs[0x00005]; /* Log base 2 of the maximum number of SRQs supported, valid only if SRQ bit is set.
+ */
+ pseudo_bit_t reserved5[0x00007];
+ pseudo_bit_t log2_rsvd_srqs[0x00004];/* Log (base 2) of the number of reserved SRQs for firmware use
+ The reserved resources are numbered from 0 to 2^log2_rsvd_srqs-1
+ This parameter is valid only if the SRQ bit is set. */
+/* -------------- */
+ pseudo_bit_t log_max_cq[0x00005]; /* Log2 of the Maximum number of CQs supported */
+ pseudo_bit_t reserved6[0x00003];
+ pseudo_bit_t log2_rsvd_cqs[0x00004];/* Log (base 2) of the number of CQs reserved for firmware use
+ The reserved resources are numbered from 0 to 2^log2_rsrvd_cqs-1 */
+ pseudo_bit_t reserved7[0x00004];
+ pseudo_bit_t log_max_cq_sz[0x00008];/* Log2 of the Maximum CQEs allowed in a CQ */
+ pseudo_bit_t reserved8[0x00008];
+/* -------------- */
+ pseudo_bit_t log_max_eq[0x00003]; /* Log2 of the Maximum number of EQs */
+ pseudo_bit_t reserved9[0x00005];
+ pseudo_bit_t num_rsvd_eqs[0x00004]; /* The number of EQs reserved for firmware use
+ The reserved resources are numbered from 0 to num_rsvd_eqs-1
+ If 0 - no resources are reserved. */
+ pseudo_bit_t reserved10[0x00004];
+ pseudo_bit_t log_max_mpts[0x00006]; /* Log (base 2) of the maximum number of MPT entries (the number of Regions/Windows) */
+ pseudo_bit_t reserved11[0x00002];
+ pseudo_bit_t log_max_eq_sz[0x00008];/* Log2 of the Maximum EQEs allowed in a EQ */
+/* -------------- */
+ pseudo_bit_t log_max_mtts[0x00006]; /* Log2 of the Maximum number of MTT entries */
+ pseudo_bit_t reserved12[0x00002];
+ pseudo_bit_t log2_rsvd_mrws[0x00004];/* Log (base 2) of the number of MPTs reserved for firmware use
+ The reserved resources are numbered from 0 to 2^log2_rsvd_mrws-1 */
+ pseudo_bit_t reserved13[0x00004];
+ pseudo_bit_t log_max_mrw_sz[0x00008];/* Log2 of the Maximum Size of Memory Region/Window */
+ pseudo_bit_t reserved14[0x00004];
+ pseudo_bit_t log2_rsvd_mtts[0x00004];/* Log (base 2) of the number of MTT entries reserved for firmware use
+ The reserved resources are numbered from 0 to 2^log2_rsvd_mtts-1
+ */
+/* -------------- */
+ pseudo_bit_t reserved15[0x00020];
+/* -------------- */
+ pseudo_bit_t log_max_ra_res_qp[0x00006];/* Log2 of the Maximum number of outstanding RDMA read/Atomic per QP as a responder */
+ pseudo_bit_t reserved16[0x0000a];
+ pseudo_bit_t log_max_ra_req_qp[0x00006];/* Log2 of the maximum number of outstanding RDMA read/Atomic per QP as a requester */
+ pseudo_bit_t reserved17[0x0000a];
+/* -------------- */
+ pseudo_bit_t log_max_ra_res_global[0x00006];/* Log2 of the maximum number of RDMA read/atomic operations the HCA responder can support globally. That implies the RDB table size. */
+ pseudo_bit_t reserved18[0x00016];
+ pseudo_bit_t log2_rsvd_rdbs[0x00004];/* Log (base 2) of the number of RDB entries reserved for firmware use
+ The reserved resources are numbered from 0 to 2^log2_rsvd_rdbs-1 */
+/* -------------- */
+ pseudo_bit_t rsz_srq[0x00001]; /* Ability to modify the maximum number of WRs per SRQ. */
+ pseudo_bit_t reserved19[0x0001f];
+/* -------------- */
+ pseudo_bit_t num_ports[0x00004]; /* Number of IB ports. */
+ pseudo_bit_t max_vl[0x00004]; /* Maximum VLs supported on each port, excluding VL15 */
+ pseudo_bit_t max_port_width[0x00004];/* IB Port Width
+ 1 - 1x
+ 3 - 1x, 4x
+ 11 - 1x, 4x or 12x
+ else - Reserved */
+ pseudo_bit_t max_mtu[0x00004]; /* Maximum MTU Supported
+ 0x0 - Reserved
+ 0x1 - 256
+ 0x2 - 512
+ 0x3 - 1024
+ 0x4 - 2048
+ 0x5 - 0xF Reserved */
+ pseudo_bit_t local_ca_ack_delay[0x00005];/* The Local CA ACK Delay. This is the value recommended to be returned in Query HCA verb.
+ The delay value in microseconds is computed using 4.096us * 2^(local_ca_ack_delay). */
+ pseudo_bit_t reserved20[0x0000b];
+/* -------------- */
+ pseudo_bit_t log_max_gid[0x00004]; /* Log2 of the maximum number of GIDs per port */
+ pseudo_bit_t reserved21[0x0001c];
+/* -------------- */
+ pseudo_bit_t log_max_pkey[0x00004]; /* Log2 of the max PKey Table Size (per IB port) */
+ pseudo_bit_t reserved22[0x0000c];
+ pseudo_bit_t stat_rate_support[0x00010];/* bit mask of stat rate supported
+ bit 0 - full bw
+ bit 1 - 1/4 bw
+ bit 2 - 1/8 bw
+ bit 3 - 1/2 bw; */
+/* -------------- */
+ pseudo_bit_t reserved23[0x00020];
+/* -------------- */
+ pseudo_bit_t rc[0x00001]; /* RC Transport supported */
+ pseudo_bit_t uc[0x00001]; /* UC Transport Supported */
+ pseudo_bit_t ud[0x00001]; /* UD Transport Supported */
+ pseudo_bit_t rd[0x00001]; /* RD Transport Supported */
+ pseudo_bit_t raw_ipv6[0x00001]; /* Raw IPv6 Transport Supported */
+ pseudo_bit_t raw_ether[0x00001]; /* Raw Ethertype Transport Supported */
+ pseudo_bit_t srq[0x00001]; /* SRQ is supported
+ */
+ pseudo_bit_t ipo_ib_checksum[0x00001];/* IP over IB checksum is supported */
+ pseudo_bit_t pkv[0x00001]; /* PKey Violation Counter Supported */
+ pseudo_bit_t qkv[0x00001]; /* QKey Violation Coutner Supported */
+ pseudo_bit_t reserved24[0x00006];
+ pseudo_bit_t mw[0x00001]; /* Memory windows supported */
+ pseudo_bit_t apm[0x00001]; /* Automatic Path Migration Supported */
+ pseudo_bit_t atm[0x00001]; /* Atomic operations supported (atomicity is guaranteed between QPs on this HCA) */
+ pseudo_bit_t rm[0x00001]; /* Raw Multicast Supported */
+ pseudo_bit_t avp[0x00001]; /* Address Vector Port checking supported */
+ pseudo_bit_t udm[0x00001]; /* UD Multicast Supported */
+ pseudo_bit_t reserved25[0x00002];
+ pseudo_bit_t pg[0x00001]; /* Paging on demand supported */
+ pseudo_bit_t r[0x00001]; /* Router mode supported */
+ pseudo_bit_t reserved26[0x00006];
+/* -------------- */
+ pseudo_bit_t log_pg_sz[0x00008]; /* Minimum system page size supported (log2).
+ For proper operation it must be less than or equal the hosting platform (CPU) minimum page size. */
+ pseudo_bit_t reserved27[0x00008];
+ pseudo_bit_t uar_sz[0x00006]; /* UAR Area Size = 1MB * 2^uar_sz */
+ pseudo_bit_t reserved28[0x00006];
+ pseudo_bit_t num_rsvd_uars[0x00004];/* The number of UARs reserved for firmware use
+ The reserved resources are numbered from 0 to num_reserved_uars-1
+ Note that UAR number num_reserved_uars is always for the kernel. */
+/* -------------- */
+ pseudo_bit_t reserved29[0x00020];
+/* -------------- */
+ pseudo_bit_t max_desc_sz_sq[0x00010];/* Max descriptor size in bytes for the send queue */
+ pseudo_bit_t max_sg_sq[0x00008]; /* The maximum S/G list elements in a SQ WQE (max_desc_sz/16 - 3) */
+ pseudo_bit_t reserved30[0x00008];
+/* -------------- */
+ pseudo_bit_t max_desc_sz_rq[0x00010];/* Max descriptor size in bytes for the receive queue */
+ pseudo_bit_t max_sg_rq[0x00008]; /* The maximum S/G list elements in a RQ WQE (max_desc_sz/16 - 3) */
+ pseudo_bit_t reserved31[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved32[0x00040];
+/* -------------- */
+ pseudo_bit_t log_max_mcg[0x00008]; /* Log2 of the maximum number of multicast groups */
+ pseudo_bit_t num_rsvd_mcgs[0x00004];/* The number of MGMs reserved for firmware use in the MGHT.
+ The reserved resources are numbered from 0 to num_reserved_mcgs-1
+ If 0 - no resources are reserved. */
+ pseudo_bit_t reserved33[0x00004];
+ pseudo_bit_t log_max_qp_mcg[0x00008];/* Log2 of the maximum number of QPs per multicast group */
+ pseudo_bit_t reserved34[0x00008];
+/* -------------- */
+ pseudo_bit_t log_max_rdds[0x00006]; /* Log2 of the maximum number of RDDs */
+ pseudo_bit_t reserved35[0x00006];
+ pseudo_bit_t num_rsvd_rdds[0x00004];/* The number of RDDs reserved for firmware use
+ The reserved resources are numbered from 0 to num_reserved_rdds-1.
+ If 0 - no resources are reserved. */
+ pseudo_bit_t log_max_pd[0x00006]; /* Log2 of the maximum number of PDs */
+ pseudo_bit_t reserved36[0x00006];
+ pseudo_bit_t num_rsvd_pds[0x00004]; /* The number of PDs reserved for firmware use
+ The reserved resources are numbered from 0 to num_reserved_pds-1
+ If 0 - no resources are reserved. */
+/* -------------- */
+ pseudo_bit_t reserved37[0x000c0];
+/* -------------- */
+ pseudo_bit_t qpc_entry_sz[0x00010]; /* QPC Entry Size for the device
+ For the InfiniHost-III-EX MT25208 entry size is 256 bytes */
+ pseudo_bit_t eec_entry_sz[0x00010]; /* EEC Entry Size for the device
+ For the InfiniHost-III-EX MT25208 entry size is 256 bytes */
+/* -------------- */
+ pseudo_bit_t eqpc_entry_sz[0x00010];/* Extended QPC entry size for the device
+ For the InfiniHost-III-EX MT25208 entry size is 32 bytes */
+ pseudo_bit_t eeec_entry_sz[0x00010];/* Extended EEC entry size for the device
+ For the InfiniHost-III-EX MT25208 entry size is 32 bytes */
+/* -------------- */
+ pseudo_bit_t cqc_entry_sz[0x00010]; /* CQC entry size for the device
+ For the InfiniHost-III-EX MT25208 entry size is 64 bytes */
+ pseudo_bit_t eqc_entry_sz[0x00010]; /* EQ context entry size for the device
+ For the InfiniHost-III-EX MT25208 entry size is 64 bytes */
+/* -------------- */
+ pseudo_bit_t uar_scratch_entry_sz[0x00010];/* UAR Scratchpad Entry Size
+ For the InfiniHost-III-EX MT25208 entry size is 32 bytes */
+ pseudo_bit_t srq_entry_sz[0x00010]; /* SRQ context entry size for the device
+ For the InfiniHost-III-EX MT25208 entry size is 32 bytes */
+/* -------------- */
+ pseudo_bit_t mpt_entry_sz[0x00010]; /* MPT entry size in Bytes for the device.
+ For the InfiniHost-III-EX MT25208 entry size is 64 bytes */
+ pseudo_bit_t mtt_entry_sz[0x00010]; /* MTT entry size in Bytes for the device.
+ For the InfiniHost-III-EX MT25208 entry size is 8 bytes */
+/* -------------- */
+ pseudo_bit_t bmme[0x00001]; /* Base Memory Management Extension Support */
+ pseudo_bit_t win_type[0x00001]; /* Bound Type 2 Memory Window Association mechanism:
+ 0 - Type 2A - QP Number Association; or
+ 1 - Type 2B - QP Number and PD Association. */
+ pseudo_bit_t mps[0x00001]; /* Ability of this HCA to support multiple page sizes per Memory Region. */
+ pseudo_bit_t bl[0x00001]; /* Ability of this HCA to support Block List Physical Buffer Lists. (The device does not supports Block List) */
+ pseudo_bit_t zb[0x00001]; /* Zero Based region/windows supported */
+ pseudo_bit_t lif[0x00001]; /* Ability of this HCA to support Local Invalidate Fencing. */
+ pseudo_bit_t reserved38[0x00002];
+ pseudo_bit_t log_pbl_sz[0x00006]; /* Log2 of the Maximum Physical Buffer List size in Bytes supported by this HCA when invoking the Allocate L_Key verb.
+ */
+ pseudo_bit_t reserved39[0x00012];
+/* -------------- */
+ pseudo_bit_t resd_lkey[0x00020]; /* The value of the reserved Lkey for Base Memory Management Extension */
+/* -------------- */
+ pseudo_bit_t lamr[0x00001]; /* When set the device requires local attached memory in order to operate.
+ When set, ICM pages, Firmware Area and ICM auxiliary pages must be allocated in the local attached memory. */
+ pseudo_bit_t reserved40[0x0001f];
+/* -------------- */
+ pseudo_bit_t max_icm_size_h[0x00020];/* Bits [63:32] of maximum ICM size InfiniHost III Ex support in bytes. */
+/* -------------- */
+ pseudo_bit_t max_icm_size_l[0x00020];/* Bits [31:0] of maximum ICM size InfiniHost III Ex support in bytes. */
+/* -------------- */
+ pseudo_bit_t reserved41[0x002c0];
+/* -------------- */
+};
+
+/* QUERY_ADAPTER Parameters Block */
+
+struct arbelprm_query_adapter_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00080];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00018];
+ pseudo_bit_t intapin[0x00008]; /* Driver should set this field to INTR value in the event queue in order to get Express interrupt messages. */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00060];
+/* -------------- */
+ struct arbelprm_vsd_st vsd;
+/* -------------- */
+};
+
+/* QUERY_FW Parameters Block */
+
+struct arbelprm_query_fw_st { /* Little Endian */
+ pseudo_bit_t fw_rev_major[0x00010]; /* Firmware Revision - Major */
+ pseudo_bit_t fw_pages[0x00010]; /* Amount of physical memory to be allocated for FW usage is in 4KByte pages. */
+/* -------------- */
+ pseudo_bit_t fw_rev_minor[0x00010]; /* Firmware Revision - Minor */
+ pseudo_bit_t fw_rev_subminor[0x00010];/* Firmware Sub-minor version (Patch level). */
+/* -------------- */
+ pseudo_bit_t cmd_interface_rev[0x00010];/* Command Interface Interpreter Revision ID */
+ pseudo_bit_t reserved0[0x0000e];
+ pseudo_bit_t wqe_h_mode[0x00001]; /* Hermon mode. If '1', then WQE and AV format is the advanced format */
+ pseudo_bit_t zb_wq_cq[0x00001]; /* If '1', then ZB mode of WQ and CQ are enabled (i.e. real Memfree PRM is supported) */
+/* -------------- */
+ pseudo_bit_t log_max_outstanding_cmd[0x00008];/* Log2 of the maximum number of commands the HCR can support simultaneously */
+ pseudo_bit_t reserved1[0x00017];
+ pseudo_bit_t dt[0x00001]; /* Debug Trace Support
+ 0 - Debug trace is not supported
+ 1 - Debug trace is supported */
+/* -------------- */
+ pseudo_bit_t cmd_interface_db[0x00001];/* Set if the device accepts commands by means of special doorbells */
+ pseudo_bit_t reserved2[0x0001f];
+/* -------------- */
+ pseudo_bit_t reserved3[0x00060];
+/* -------------- */
+ pseudo_bit_t clr_int_base_addr_h[0x00020];/* Bits [63:32] of Clear interrupt register physical address.
+ Points to 64 bit register. */
+/* -------------- */
+ pseudo_bit_t clr_int_base_addr_l[0x00020];/* Bits [31:0] of Clear interrupt register physical address.
+ Points to 64 bit register. */
+/* -------------- */
+ pseudo_bit_t reserved4[0x00040];
+/* -------------- */
+ pseudo_bit_t error_buf_start_h[0x00020];/* Read Only buffer for catastrophic error reports (physical address) */
+/* -------------- */
+ pseudo_bit_t error_buf_start_l[0x00020];/* Read Only buffer for catastrophic error reports (physical address) */
+/* -------------- */
+ pseudo_bit_t error_buf_size[0x00020];/* Size in words */
+/* -------------- */
+ pseudo_bit_t reserved5[0x00020];
+/* -------------- */
+ pseudo_bit_t eq_arm_base_addr_h[0x00020];/* Bits [63:32] of EQ Arm DBs physical address.
+ Points to 64 bit register.
+ Setting bit x in the offset, arms EQ number x.
+ */
+/* -------------- */
+ pseudo_bit_t eq_arm_base_addr_l[0x00020];/* Bits [31:0] of EQ Arm DBs physical address.
+ Points to 64 bit register.
+ Setting bit x in the offset, arms EQ number x. */
+/* -------------- */
+ pseudo_bit_t eq_set_ci_base_addr_h[0x00020];/* Bits [63:32] of EQ Set CI DBs Table physical address.
+ Points to a the EQ Set CI DBs Table base address. */
+/* -------------- */
+ pseudo_bit_t eq_set_ci_base_addr_l[0x00020];/* Bits [31:0] of EQ Set CI DBs Table physical address.
+ Points to a the EQ Set CI DBs Table base address. */
+/* -------------- */
+ pseudo_bit_t cmd_db_dw1[0x00010]; /* offset in bytes from cmd_db_addr_base where DWord 1 of a Command Interface Doorbell should be written. Valid only if CmdInterfaceDb bit is '1' */
+ pseudo_bit_t cmd_db_dw0[0x00010]; /* offset in bytes from cmd_db_addr_base where DWord 0 of a Command Interface Doorbell should be written. Valid only if CmdInterfaceDb bit is '1' */
+/* -------------- */
+ pseudo_bit_t cmd_db_dw3[0x00010]; /* offset in bytes from cmd_db_addr_base where DWord 3 of a Command Interface Doorbell should be written. Valid only if CmdInterfaceDb bit is '1' */
+ pseudo_bit_t cmd_db_dw2[0x00010]; /* offset in bytes from cmd_db_addr_base where DWord 2 of a Command Interface Doorbell should be written. Valid only if CmdInterfaceDb bit is '1' */
+/* -------------- */
+ pseudo_bit_t cmd_db_dw5[0x00010]; /* offset in bytes from cmd_db_addr_base where DWord 5 of a Command Interface Doorbell should be written. Valid only if CmdInterfaceDb bit is '1' */
+ pseudo_bit_t cmd_db_dw4[0x00010]; /* offset in bytes from cmd_db_addr_base where DWord 4 of a Command Interface Doorbell should be written. Valid only if CmdInterfaceDb bit is '1' */
+/* -------------- */
+ pseudo_bit_t cmd_db_dw7[0x00010]; /* offset in bytes from cmd_db_addr_base where DWord 7 of a Command Interface Doorbell should be written. Valid only if CmdInterfaceDb bit is '1' */
+ pseudo_bit_t cmd_db_dw6[0x00010]; /* offset in bytes from cmd_db_addr_base where DWord 6 of a Command Interface Doorbell should be written. Valid only if CmdInterfaceDb bit is '1' */
+/* -------------- */
+ pseudo_bit_t cmd_db_addr_base_h[0x00020];/* High bits of cmd_db_addr_base, which cmd_db_dw offsets refer to. Valid only if CmdInterfaceDb bit is '1' */
+/* -------------- */
+ pseudo_bit_t cmd_db_addr_base_l[0x00020];/* Low bits of cmd_db_addr_base, which cmd_db_dw offsets refer to. Valid only if CmdInterfaceDb bit is '1' */
+/* -------------- */
+ pseudo_bit_t reserved6[0x004c0];
+/* -------------- */
+};
+
+/* ACCESS_LAM */
+
+struct arbelprm_access_lam_st { /* Little Endian */
+ struct arbelprm_access_lam_inject_errors_st access_lam_inject_errors;
+/* -------------- */
+ pseudo_bit_t reserved0[0x00080];
+/* -------------- */
+};
+
+/* ENABLE_LAM Parameters Block */
+
+struct arbelprm_enable_lam_st { /* Little Endian */
+ pseudo_bit_t lam_start_adr_h[0x00020];/* LAM start address [63:32] */
+/* -------------- */
+ pseudo_bit_t lam_start_adr_l[0x00020];/* LAM start address [31:0] */
+/* -------------- */
+ pseudo_bit_t lam_end_adr_h[0x00020];/* LAM end address [63:32] */
+/* -------------- */
+ pseudo_bit_t lam_end_adr_l[0x00020];/* LAM end address [31:0] */
+/* -------------- */
+ pseudo_bit_t di[0x00002]; /* Data Integrity Configuration:
+ 00 - none
+ 01 - Parity
+ 10 - ECC Detection Only
+ 11 - ECC With Correction */
+ pseudo_bit_t ap[0x00002]; /* Auto Precharge Mode
+ 00 - No auto precharge
+ 01 - Auto precharge per transaction
+ 10 - Auto precharge per 64 bytes
+ 11 - reserved */
+ pseudo_bit_t dh[0x00001]; /* When set, LAM is Hidden and can not be accessed directly from the PCI bus. */
+ pseudo_bit_t reserved0[0x0001b];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00160];
+/* -------------- */
+ struct arbelprm_dimminfo_st dimm0; /* Logical DIMM 0 Parameters */
+/* -------------- */
+ struct arbelprm_dimminfo_st dimm1; /* Logical DIMM 1 Parameters */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00400];
+/* -------------- */
+};
+
+/* Memory Access Parameters for UD Address Vector Table */
+
+struct arbelprm_udavtable_memory_parameters_st { /* Little Endian */
+ pseudo_bit_t l_key[0x00020]; /* L_Key used to access TPT */
+/* -------------- */
+ pseudo_bit_t pd[0x00018]; /* PD used by TPT for matching against PD of region entry being accessed. */
+ pseudo_bit_t reserved0[0x00005];
+ pseudo_bit_t xlation_en[0x00001]; /* When cleared, address is physical address and no translation will be done. When set, address is virtual. */
+ pseudo_bit_t reserved1[0x00002];
+/* -------------- */
+};
+
+/* INIT_HCA & QUERY_HCA Parameters Block */
+
+struct arbelprm_init_hca_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00060];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00010];
+ pseudo_bit_t time_stamp_granularity[0x00008];/* This field controls the granularity in which CQE Timestamp counter is incremented.
+ The TimeStampGranularity units is 1/4 of a microseconds. (e.g is TimeStampGranularity is configured to 0x2, CQE Timestamp will be incremented every one microsecond)
+ When sets to Zero, timestamp reporting in the CQE is disabled.
+ This feature is currently not supported.
+ */
+ pseudo_bit_t hca_core_clock[0x00008];/* Internal Clock Period (in units of 1/16 ns) (QUERY_HCA only) */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00008];
+ pseudo_bit_t router_qp[0x00010]; /* Upper 16 bit to be used as a QP number for router mode. Low order 8 bits are taken from the TClass field of the incoming packet.
+ Valid only if RE bit is set */
+ pseudo_bit_t reserved3[0x00007];
+ pseudo_bit_t re[0x00001]; /* Router Mode Enable
+ If this bit is set, entire packet (including all headers and ICRC) will be considered as a data payload and will be scattered to memory as specified in the descriptor that is posted on the QP matching the TClass field of packet. */
+/* -------------- */
+ pseudo_bit_t udp[0x00001]; /* UD Port Check Enable
+ 0 - Port field in Address Vector is ignored
+ 1 - HCA will check the port field in AV entry (fetched for UD descriptor) against the Port of the UD QP executing the descriptor. */
+ pseudo_bit_t he[0x00001]; /* Host Endianess - Used for Atomic Operations
+ 0 - Host is Little Endian
+ 1 - Host is Big endian
+ */
+ pseudo_bit_t reserved4[0x00001];
+ pseudo_bit_t ce[0x00001]; /* Checksum Enabled - when Set IPoverIB checksum generation & checking is enabled */
+ pseudo_bit_t sph[0x00001]; /* 0 - SW calculates TCP/UDP Pseudo-Header checksum and inserts it into the TCP/UDP checksum field when sending a packet
+ 1 - HW calculates TCP/UDP Pseudo-Header checksum when sending a packet
+ */
+ pseudo_bit_t rph[0x00001]; /* 0 - Not HW calculation of TCP/UDP Pseudo-Header checksum are done when receiving a packet
+ 1 - HW calculates TCP/UDP Pseudo-Header checksum when receiving a packet
+ */
+ pseudo_bit_t reserved5[0x00002];
+ pseudo_bit_t responder_exu[0x00004];/* Indicate the relation between the execution enegines allocation dedicated for responder versus the engines dedicated for reqvester .
+ responder_exu/16 = (number of responder exu engines)/(total number of engines)
+ Legal values are 0x0-0xF. 0 is "auto".
+
+ */
+ pseudo_bit_t reserved6[0x00004];
+ pseudo_bit_t wqe_quota[0x0000f]; /* Maximum number of WQEs that are executed prior to preemption of execution unit. 0 - reserved. */
+ pseudo_bit_t wqe_quota_en[0x00001]; /* If set - wqe_quota field is used. If cleared - WQE quota is set to "auto" value */
+/* -------------- */
+ pseudo_bit_t reserved7[0x00040];
+/* -------------- */
+ struct arbelprm_qpcbaseaddr_st qpc_eec_cqc_eqc_rdb_parameters;
+/* -------------- */
+ pseudo_bit_t reserved8[0x00100];
+/* -------------- */
+ struct arbelprm_multicastparam_st multicast_parameters;
+/* -------------- */
+ pseudo_bit_t reserved9[0x00080];
+/* -------------- */
+ struct arbelprm_tptparams_st tpt_parameters;
+/* -------------- */
+ pseudo_bit_t reserved10[0x00080];
+/* -------------- */
+ struct arbelprm_uar_params_st uar_parameters;/* UAR Parameters */
+/* -------------- */
+ pseudo_bit_t reserved11[0x00600];
+/* -------------- */
+};
+
+/* Event Queue Context Table Entry */
+
+struct arbelprm_eqc_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t st[0x00004]; /* Event delivery state machine
+ 0x9 - Armed
+ 0xA - Fired
+ 0xB - Always_Armed (auto-rearm)
+ other - reserved */
+ pseudo_bit_t reserved1[0x00005];
+ pseudo_bit_t oi[0x00001]; /* Oerrun ignore.
+ If set, HW will not check EQ full condition when writing new EQEs. */
+ pseudo_bit_t tr[0x00001]; /* Translation Required. If set - EQ access undergo address translation. */
+ pseudo_bit_t reserved2[0x00005];
+ pseudo_bit_t owner[0x00004]; /* 0 - SW ownership
+ 1 - HW ownership
+ Valid for the QUERY_EQ and HW2SW_EQ commands only */
+ pseudo_bit_t status[0x00004]; /* EQ status:
+ 0000 - OK
+ 1010 - EQ write failure
+ Valid for the QUERY_EQ and HW2SW_EQ commands only */
+/* -------------- */
+ pseudo_bit_t start_address_h[0x00020];/* Start Address of Event Queue[63:32]. */
+/* -------------- */
+ pseudo_bit_t start_address_l[0x00020];/* Start Address of Event Queue[31:0].
+ Must be aligned on 32-byte boundary */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00018];
+ pseudo_bit_t log_eq_size[0x00005]; /* Amount of entries in this EQ is 2^log_eq_size.
+ Log_eq_size must be bigger than 1.
+ Maximum EQ size is 2^17 EQEs (max Log_eq_size is 17). */
+ pseudo_bit_t reserved4[0x00003];
+/* -------------- */
+ pseudo_bit_t reserved5[0x00020];
+/* -------------- */
+ pseudo_bit_t intr[0x00008]; /* Interrupt (message) to be generated to report event to INT layer.
+ 00iiiiii - set to INTA given in QUERY_ADAPTER in order to generate INTA messages on Express.
+ 10jjjjjj - specificies type of interrupt message to be generated (total 64 different messages supported).
+ All other values are reserved and should not be used.
+
+ If interrupt generation is not required, ST field must be set upon creation to Fired state. No EQ arming doorbell should be performed. In this case hardware will not generate any interrupt. */
+ pseudo_bit_t reserved6[0x00018];
+/* -------------- */
+ pseudo_bit_t pd[0x00018]; /* PD to be used to access EQ */
+ pseudo_bit_t reserved7[0x00008];
+/* -------------- */
+ pseudo_bit_t lkey[0x00020]; /* Memory key (L-Key) to be used to access EQ */
+/* -------------- */
+ pseudo_bit_t reserved8[0x00040];
+/* -------------- */
+ pseudo_bit_t consumer_indx[0x00020];/* Contains next entry to be read upon polling the event queue.
+ Must be initalized to zero while opening EQ */
+/* -------------- */
+ pseudo_bit_t producer_indx[0x00020];/* Contains next entry in EQ to be written by the HCA.
+ Must be initalized to zero while opening EQ. */
+/* -------------- */
+ pseudo_bit_t reserved9[0x00080];
+/* -------------- */
+};
+
+/* Memory Translation Table (MTT) Entry */
+
+struct arbelprm_mtt_st { /* Little Endian */
+ pseudo_bit_t ptag_h[0x00020]; /* High-order bits of physical tag. The size of the field depends on the page size of the region. Maximum PTAG size is 52 bits. */
+/* -------------- */
+ pseudo_bit_t p[0x00001]; /* Present bit. If set, page entry is valid. If cleared, access to this page will generate non-present page access fault. */
+ pseudo_bit_t reserved0[0x0000b];
+ pseudo_bit_t ptag_l[0x00014]; /* Low-order bits of Physical tag. The size of the field depends on the page size of the region. Maximum PTAG size is 52 bits. */
+/* -------------- */
+};
+
+/* Memory Protection Table (MPT) Entry */
+
+struct arbelprm_mpt_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t r_w[0x00001]; /* Defines whether this entry is Region (1) or Window (0) */
+ pseudo_bit_t pa[0x00001]; /* Physical address. If set, no virtual-to-physical address translation will be performed for this region */
+ pseudo_bit_t lr[0x00001]; /* If set - local read access enabled */
+ pseudo_bit_t lw[0x00001]; /* If set - local write access enabled */
+ pseudo_bit_t rr[0x00001]; /* If set - remote read access enabled. */
+ pseudo_bit_t rw[0x00001]; /* If set - remote write access enabled */
+ pseudo_bit_t a[0x00001]; /* If set - remote Atomic access is enabled */
+ pseudo_bit_t eb[0x00001]; /* If set - Bind is enabled. Valid for region entry only. */
+ pseudo_bit_t reserved1[0x0000c];
+ pseudo_bit_t status[0x00004]; /* Region/Window Status
+ 0xF - not valid (SW ownership)
+ 0x3 - FREE state
+ else - HW ownership
+ Unbound Type I windows are doneted reg_wnd_len field equals zero.
+ Unbound Type II windows are donated by Status=FREE. */
+/* -------------- */
+ pseudo_bit_t page_size[0x00005]; /* Page size used for the region. Actual size is [4K]*2^Page_size bytes.
+ page_size should be less than 20. */
+ pseudo_bit_t reserved2[0x00002];
+ pseudo_bit_t type[0x00001]; /* Applicable for windows only, must be zero for regions
+ 0 - Type one window
+ 1 - Type two window */
+ pseudo_bit_t qpn[0x00018]; /* QP number this MW is attached to. Valid for type2 memory windows and on QUERY_MPT only */
+/* -------------- */
+ pseudo_bit_t mem_key[0x00020]; /* The memory Key. The field holds the mem_key field in the following semantics: {key[7:0],key[31:8]}.
+ */
+/* -------------- */
+ pseudo_bit_t pd[0x00018]; /* Protection Domain */
+ pseudo_bit_t reserved3[0x00001];
+ pseudo_bit_t ei[0x00001]; /* Enable Invalidation - When set, Local/Remote invalidation can be executed on this window/region.
+ Must be set for type2 windows and non-shared physical memory regions.
+ Must be clear for regions that are used to access Work Queues, Completion Queues and Event Queues */
+ pseudo_bit_t zb[0x00001]; /* When set, this region is Zero Based Region */
+ pseudo_bit_t fre[0x00001]; /* When set, Fast Registration Operations can be executed on this region */
+ pseudo_bit_t rae[0x00001]; /* When set, remote access can be enabled on this region.
+ Used when executing Fast Registration Work Request to validate that remote access rights can be granted to this MPT.
+ If the bit is cleared, Fast Registration Work Request requesting remote access rights will fail.
+ */
+ pseudo_bit_t reserved4[0x00003];
+/* -------------- */
+ pseudo_bit_t start_address_h[0x00020];/* Start Address[63:32] - Virtual Address where this region/window starts */
+/* -------------- */
+ pseudo_bit_t start_address_l[0x00020];/* Start Address[31:0] - Virtual Address where this region/window starts */
+/* -------------- */
+ pseudo_bit_t reg_wnd_len_h[0x00020];/* Region/Window Length[63:32] */
+/* -------------- */
+ pseudo_bit_t reg_wnd_len_l[0x00020];/* Region/Window Length[31:0] */
+/* -------------- */
+ pseudo_bit_t lkey[0x00020]; /* Must be 0 for SW2HW_MPT.
+ On QUERY_MPT and HW2SW_MPT commands for Memory Window it reflects the LKey of the Region that the Window is bound to.
+ The field holds the lkey field in the following semantics: {key[7:0],key[31:8]}. */
+/* -------------- */
+ pseudo_bit_t win_cnt[0x00020]; /* Number of windows bound to this region. Valid for regions only.
+ The field is valid only for the QUERY_MPT and HW2SW_MPT commands. */
+/* -------------- */
+ pseudo_bit_t reserved5[0x00020];
+/* -------------- */
+ pseudo_bit_t mtt_adr_h[0x00006]; /* Base (first) address of the MTT relative to MTT base in the ICM */
+ pseudo_bit_t reserved6[0x0001a];
+/* -------------- */
+ pseudo_bit_t reserved7[0x00003];
+ pseudo_bit_t mtt_adr_l[0x0001d]; /* Base (first) address of the MTT relative to MTT base address in the ICM. Must be aligned on 8 bytes. */
+/* -------------- */
+ pseudo_bit_t mtt_sz[0x00020]; /* Number of MTT entries allocated for this MR.
+ When Fast Registration Operations can not be executed on this region (FRE bit is zero) this field is reserved.
+ When Fast Registration Operation is enabled (FRE bit is set) this field indicates the number of MTTs allocated for this MR. If mtt_sz value is zero, there is no limit for the numbers of MTTs and the HCA does not check this field when executing fast register WQE. */
+/* -------------- */
+ pseudo_bit_t reserved8[0x00040];
+/* -------------- */
+};
+
+/* Completion Queue Context Table Entry */
+
+struct arbelprm_completion_queue_context_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t st[0x00004]; /* Event delivery state machine
+ 0x0 - reserved
+ 0x9 - ARMED (Request for Notification)
+ 0x6 - ARMED SOLICITED (Request Solicited Notification)
+ 0xA - FIRED
+ other - reserved
+
+ Must be 0x0 in CQ initialization.
+ Valid for the QUERY_CQ and HW2SW_CQ commands only. */
+ pseudo_bit_t reserved1[0x00005];
+ pseudo_bit_t oi[0x00001]; /* When set, overrun ignore is enabled.
+ When set, Updates of CQ consumer counter (poll for completion) or Request completion notifications (Arm CQ) doorbells should not be rang on that CQ. */
+ pseudo_bit_t reserved2[0x0000a];
+ pseudo_bit_t status[0x00004]; /* CQ status
+ 0000 - OK
+ 1001 - CQ overflow
+ 1010 - CQ write failure
+ Valid for the QUERY_CQ and HW2SW_CQ commands only */
+/* -------------- */
+ pseudo_bit_t start_address_h[0x00020];/* Start address of CQ[63:32].
+ Must be aligned on CQE size (32 bytes) */
+/* -------------- */
+ pseudo_bit_t start_address_l[0x00020];/* Start address of CQ[31:0].
+ Must be aligned on CQE size (32 bytes) */
+/* -------------- */
+ pseudo_bit_t usr_page[0x00018]; /* UAR page this CQ can be accessed through (ringinig CQ doorbells) */
+ pseudo_bit_t log_cq_size[0x00005]; /* Log (base 2) of the CQ size (in entries).
+ Maximum CQ size is 2^17 CQEs (max log_cq_size is 17) */
+ pseudo_bit_t reserved3[0x00003];
+/* -------------- */
+ pseudo_bit_t reserved4[0x00020];
+/* -------------- */
+ pseudo_bit_t c_eqn[0x00008]; /* Event Queue this CQ reports completion events to.
+ Valid values are 0 to 63
+ If configured to value other than 0-63, completion events will not be reported on the CQ. */
+ pseudo_bit_t reserved5[0x00018];
+/* -------------- */
+ pseudo_bit_t pd[0x00018]; /* Protection Domain to be used to access CQ.
+ Must be the same PD of the CQ L_Key. */
+ pseudo_bit_t reserved6[0x00008];
+/* -------------- */
+ pseudo_bit_t l_key[0x00020]; /* Memory key (L_Key) to be used to access CQ */
+/* -------------- */
+ pseudo_bit_t last_notified_indx[0x00020];/* Maintained by HW.
+ Valid for QUERY_CQ and HW2SW_CQ commands only. */
+/* -------------- */
+ pseudo_bit_t solicit_producer_indx[0x00020];/* Maintained by HW.
+ Valid for QUERY_CQ and HW2SW_CQ commands only.
+ */
+/* -------------- */
+ pseudo_bit_t consumer_counter[0x00020];/* Consumer counter is a 32bits counter that is incremented for each CQE pooled from the CQ.
+ Must be 0x0 in CQ initialization.
+ Valid for the QUERY_CQ and HW2SW_CQ commands only. */
+/* -------------- */
+ pseudo_bit_t producer_counter[0x00020];/* Producer counter is a 32bits counter that is incremented for each CQE that is written by the HW to the CQ.
+ CQ overrun is reported if Producer_counter + 1 equals to Consumer_counter and a CQE needs to be added..
+ Maintained by HW (valid for the QUERY_CQ and HW2SW_CQ commands only) */
+/* -------------- */
+ pseudo_bit_t cqn[0x00018]; /* CQ number. Least significant bits are constrained by the position of this CQ in CQC table
+ Valid for the QUERY_CQ and HW2SW_CQ commands only */
+ pseudo_bit_t reserved7[0x00008];
+/* -------------- */
+ pseudo_bit_t cq_ci_db_record[0x00020];/* Index in the UAR Context Table Entry.
+ HW uses this index as an offset from the UAR Context Table Entry in order to read this CQ Consumer Counter doorbell record.
+ This value can be retrieved from the HW in the QUERY_CQ command. */
+/* -------------- */
+ pseudo_bit_t cq_state_db_record[0x00020];/* Index in the UAR Context Table Entry.
+ HW uses this index as an offset from the UAR Context Table Entry in order to read this CQ state doorbell record.
+ This value can be retrieved from the HW in the QUERY_CQ command. */
+/* -------------- */
+ pseudo_bit_t reserved8[0x00020];
+/* -------------- */
+};
+
+/* GPIO_event_data */
+
+struct arbelprm_gpio_event_data_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00060];
+/* -------------- */
+ pseudo_bit_t gpio_event_hi[0x00020];/* If any bit is set to 1, then a rising/falling event has occurred on the corrsponding GPIO pin. */
+/* -------------- */
+ pseudo_bit_t gpio_event_lo[0x00020];/* If any bit is set to 1, then a rising/falling event has occurred on the corrsponding GPIO pin. */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00020];
+/* -------------- */
+};
+
+/* Event_data Field - QP/EE Events */
+
+struct arbelprm_qp_ee_event_st { /* Little Endian */
+ pseudo_bit_t qpn_een[0x00018]; /* QP/EE/SRQ number event is reported for */
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved2[0x0001c];
+ pseudo_bit_t e_q[0x00001]; /* If set - EEN if cleared - QP in the QPN/EEN field
+ Not valid on SRQ events */
+ pseudo_bit_t reserved3[0x00003];
+/* -------------- */
+ pseudo_bit_t reserved4[0x00060];
+/* -------------- */
+};
+
+/* InfiniHost-III-EX Type0 Configuration Header */
+
+struct arbelprm_mt25208_type0_st { /* Little Endian */
+ pseudo_bit_t vendor_id[0x00010]; /* Hardwired to 0x15B3 */
+ pseudo_bit_t device_id[0x00010]; /* 25208 (decimal) - InfiniHost-III compatible mode
+ 25218 (decimal) - InfiniHost-III EX mode (the mode described in this manual)
+ 25209 (decimal) - Flash burner mode - see Flash burning application note for further details on this mode
+ */
+/* -------------- */
+ pseudo_bit_t command[0x00010]; /* PCI Command Register */
+ pseudo_bit_t status[0x00010]; /* PCI Status Register */
+/* -------------- */
+ pseudo_bit_t revision_id[0x00008];
+ pseudo_bit_t class_code_hca_class_code[0x00018];
+/* -------------- */
+ pseudo_bit_t cache_line_size[0x00008];/* Cache Line Size */
+ pseudo_bit_t latency_timer[0x00008];
+ pseudo_bit_t header_type[0x00008]; /* hardwired to zero */
+ pseudo_bit_t bist[0x00008];
+/* -------------- */
+ pseudo_bit_t bar0_ctrl[0x00004]; /* hard-wired to 0100 */
+ pseudo_bit_t reserved0[0x00010];
+ pseudo_bit_t bar0_l[0x0000c]; /* Lower bits of BAR0 (Device Configuration Space) */
+/* -------------- */
+ pseudo_bit_t bar0_h[0x00020]; /* Upper 32 bits of BAR0 (Device Configuration Space) */
+/* -------------- */
+ pseudo_bit_t bar1_ctrl[0x00004]; /* Hardwired to 1100 */
+ pseudo_bit_t reserved1[0x00010];
+ pseudo_bit_t bar1_l[0x0000c]; /* Lower bits of BAR1 (User Access Region - UAR - space) */
+/* -------------- */
+ pseudo_bit_t bar1_h[0x00020]; /* upper 32 bits of BAR1 (User Access Region - UAR - space) */
+/* -------------- */
+ pseudo_bit_t bar2_ctrl[0x00004]; /* Hardwired to 1100 */
+ pseudo_bit_t reserved2[0x00010];
+ pseudo_bit_t bar2_l[0x0000c]; /* Lower bits of BAR2 - Local Attached Memory if present and enabled. Else zeroed. */
+/* -------------- */
+ pseudo_bit_t bar2_h[0x00020]; /* Upper 32 bits of BAR2 - Local Attached Memory if present and enabled. Else zeroed. */
+/* -------------- */
+ pseudo_bit_t cardbus_cis_pointer[0x00020];
+/* -------------- */
+ pseudo_bit_t subsystem_vendor_id[0x00010];/* Specified by the device NVMEM configuration */
+ pseudo_bit_t subsystem_id[0x00010]; /* Specified by the device NVMEM configuration */
+/* -------------- */
+ pseudo_bit_t expansion_rom_enable[0x00001];/* Expansion ROM Enable. Hardwired to 0 if expansion ROM is disabled in the device NVMEM configuration. */
+ pseudo_bit_t reserved3[0x0000a];
+ pseudo_bit_t expansion_rom_base_address[0x00015];/* Expansion ROM Base Address (upper 21 bit). Hardwired to 0 if expansion ROM is disabled in the device NVMEM configuration. */
+/* -------------- */
+ pseudo_bit_t capabilities_pointer[0x00008];/* Specified by the device NVMEM configuration */
+ pseudo_bit_t reserved4[0x00018];
+/* -------------- */
+ pseudo_bit_t reserved5[0x00020];
+/* -------------- */
+ pseudo_bit_t interrupt_line[0x00008];
+ pseudo_bit_t interrupt_pin[0x00008];
+ pseudo_bit_t min_gnt[0x00008];
+ pseudo_bit_t max_latency[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved6[0x00100];
+/* -------------- */
+ pseudo_bit_t msi_cap_id[0x00008];
+ pseudo_bit_t msi_next_cap_ptr[0x00008];
+ pseudo_bit_t msi_en[0x00001];
+ pseudo_bit_t multiple_msg_cap[0x00003];
+ pseudo_bit_t multiple_msg_en[0x00003];
+ pseudo_bit_t cap_64_bit_addr[0x00001];
+ pseudo_bit_t reserved7[0x00008];
+/* -------------- */
+ pseudo_bit_t msg_addr_l[0x00020];
+/* -------------- */
+ pseudo_bit_t msg_addr_h[0x00020];
+/* -------------- */
+ pseudo_bit_t msg_data[0x00010];
+ pseudo_bit_t reserved8[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved9[0x00080];
+/* -------------- */
+ pseudo_bit_t pm_cap_id[0x00008]; /* Power management capability ID - 01h */
+ pseudo_bit_t pm_next_cap_ptr[0x00008];
+ pseudo_bit_t pm_cap[0x00010]; /* [2:0] Version - 02h
+ [3] PME clock - 0h
+ [4] RsvP
+ [5] Device specific initialization - 0h
+ [8:6] AUX current - 0h
+ [9] D1 support - 0h
+ [10] D2 support - 0h
+ [15:11] PME support - 0h */
+/* -------------- */
+ pseudo_bit_t pm_status_control[0x00010];/* [14:13] - Data scale - 0h */
+ pseudo_bit_t pm_control_status_brdg_ext[0x00008];
+ pseudo_bit_t data[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved10[0x00040];
+/* -------------- */
+ pseudo_bit_t vpd_cap_id[0x00008]; /* 03h */
+ pseudo_bit_t vpd_next_cap_id[0x00008];
+ pseudo_bit_t vpd_address[0x0000f];
+ pseudo_bit_t f[0x00001];
+/* -------------- */
+ pseudo_bit_t vpd_data[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved11[0x00040];
+/* -------------- */
+ pseudo_bit_t pciex_cap_id[0x00008]; /* PCI-Express capability ID - 10h */
+ pseudo_bit_t pciex_next_cap_ptr[0x00008];
+ pseudo_bit_t pciex_cap[0x00010]; /* [3:0] Capability version - 1h
+ [7:4] Device/Port Type - 0h
+ [8] Slot implemented - 0h
+ [13:9] Interrupt message number
+ */
+/* -------------- */
+ pseudo_bit_t device_cap[0x00020]; /* [2:0] Max_Payload_Size supported - 2h
+ [4:3] Phantom Function supported - 0h
+ [5] Extended Tag Filed supported - 0h
+ [8:6] Endpoint L0s Acceptable Latency - TBD
+ [11:9] Endpoint L1 Acceptable Latency - TBD
+ [12] Attention Button Present - configured through InfiniBurn
+ [13] Attention Indicator Present - configured through InfiniBurn
+ [14] Power Indicator Present - configured through InfiniBurn
+ [25:18] Captured Slot Power Limit Value
+ [27:26] Captured Slot Power Limit Scale */
+/* -------------- */
+ pseudo_bit_t device_control[0x00010];
+ pseudo_bit_t device_status[0x00010];
+/* -------------- */
+ pseudo_bit_t link_cap[0x00020]; /* [3:0] Maximum Link Speed - 1h
+ [9:4] Maximum Link Width - 8h
+ [11:10] Active State Power Management Support - 3h
+ [14:12] L0s Exit Latency - TBD
+ [17:15] L1 Exit Latency - TBD
+ [31:24] Port Number - 0h */
+/* -------------- */
+ pseudo_bit_t link_control[0x00010];
+ pseudo_bit_t link_status[0x00010]; /* [3:0] Link Speed - 1h
+ [9:4] Negotiated Link Width
+ [12] Slot clock configuration - 1h */
+/* -------------- */
+ pseudo_bit_t reserved12[0x00260];
+/* -------------- */
+ pseudo_bit_t advanced_error_reporting_cap_id[0x00010];/* 0001h. */
+ pseudo_bit_t capability_version[0x00004];/* 1h */
+ pseudo_bit_t next_capability_offset[0x0000c];/* 0h */
+/* -------------- */
+ pseudo_bit_t uncorrectable_error_status_register[0x00020];/* 0 Training Error Status
+ 4 Data Link Protocol Error Status
+ 12 Poisoned TLP Status
+ 13 Flow Control Protocol Error Status
+ 14 Completion Timeout Status
+ 15 Completer Abort Status
+ 16 Unexpected Completion Status
+ 17 Receiver Overflow Status
+ 18 Malformed TLP Status
+ 19 ECRC Error Status
+ 20 Unsupported Request Error Status */
+/* -------------- */
+ pseudo_bit_t uncorrectable_error_mask_register[0x00020];/* 0 Training Error Mask
+ 4 Data Link Protocol Error Mask
+ 12 Poisoned TLP Mask
+ 13 Flow Control Protocol Error Mask
+ 14 Completion Timeout Mask
+ 15 Completer Abort Mask
+ 16 Unexpected Completion Mask
+ 17 Receiver Overflow Mask
+ 18 Malformed TLP Mask
+ 19 ECRC Error Mask
+ 20 Unsupported Request Error Mask */
+/* -------------- */
+ pseudo_bit_t uncorrectable_severity_mask_register[0x00020];/* 0 Training Error Severity
+ 4 Data Link Protocol Error Severity
+ 12 Poisoned TLP Severity
+ 13 Flow Control Protocol Error Severity
+ 14 Completion Timeout Severity
+ 15 Completer Abort Severity
+ 16 Unexpected Completion Severity
+ 17 Receiver Overflow Severity
+ 18 Malformed TLP Severity
+ 19 ECRC Error Severity
+ 20 Unsupported Request Error Severity */
+/* -------------- */
+ pseudo_bit_t correctable_error_status_register[0x00020];/* 0 Receiver Error Status
+ 6 Bad TLP Status
+ 7 Bad DLLP Status
+ 8 REPLAY_NUM Rollover Status
+ 12 Replay Timer Timeout Status */
+/* -------------- */
+ pseudo_bit_t correctable_error_mask_register[0x00020];/* 0 Receiver Error Mask
+ 6 Bad TLP Mask
+ 7 Bad DLLP Mask
+ 8 REPLAY_NUM Rollover Mask
+ 12 Replay Timer Timeout Mask */
+/* -------------- */
+ pseudo_bit_t advance_error_capabilities_and_control_register[0x00020];
+/* -------------- */
+ struct arbelprm_header_log_register_st header_log_register;
+/* -------------- */
+ pseudo_bit_t reserved13[0x006a0];
+/* -------------- */
+};
+
+/* Event Data Field - Performance Monitor */
+
+struct arbelprm_performance_monitor_event_st { /* Little Endian */
+ struct arbelprm_performance_monitors_st performance_monitor_snapshot;/* Performance monitor snapshot */
+/* -------------- */
+ pseudo_bit_t monitor_number[0x00008];/* 0x01 - SQPC
+ 0x02 - RQPC
+ 0x03 - CQC
+ 0x04 - Rkey
+ 0x05 - TLB
+ 0x06 - port0
+ 0x07 - port1 */
+ pseudo_bit_t reserved0[0x00018];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00040];
+/* -------------- */
+};
+
+/* Event_data Field - Page Faults */
+
+struct arbelprm_page_fault_event_data_st { /* Little Endian */
+ pseudo_bit_t va_h[0x00020]; /* Virtual Address[63:32] this page fault is reported on */
+/* -------------- */
+ pseudo_bit_t va_l[0x00020]; /* Virtual Address[63:32] this page fault is reported on */
+/* -------------- */
+ pseudo_bit_t mem_key[0x00020]; /* Memory Key this page fault is reported on */
+/* -------------- */
+ pseudo_bit_t qp[0x00018]; /* QP this page fault is reported on */
+ pseudo_bit_t reserved0[0x00003];
+ pseudo_bit_t a[0x00001]; /* If set the memory access that caused the page fault was atomic */
+ pseudo_bit_t lw[0x00001]; /* If set the memory access that caused the page fault was local write */
+ pseudo_bit_t lr[0x00001]; /* If set the memory access that caused the page fault was local read */
+ pseudo_bit_t rw[0x00001]; /* If set the memory access that caused the page fault was remote write */
+ pseudo_bit_t rr[0x00001]; /* If set the memory access that caused the page fault was remote read */
+/* -------------- */
+ pseudo_bit_t pd[0x00018]; /* PD this page fault is reported on */
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t prefetch_len[0x00020]; /* Indicates how many subsequent pages in the same memory region/window will be accessed by the following transaction after this page fault is resolved. measured in bytes. SW can use this information in order to page-in the subsequent pages if they are not present. */
+/* -------------- */
+};
+
+/* WQE segments format */
+
+struct arbelprm_wqe_segment_st { /* Little Endian */
+ struct arbelprm_send_wqe_segment_st send_wqe_segment;/* Send WQE segment format */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00280];
+/* -------------- */
+ struct arbelprm_wqe_segment_ctrl_mlx_st mlx_wqe_segment_ctrl;/* MLX WQE segment format */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00100];
+/* -------------- */
+ struct arbelprm_wqe_segment_ctrl_recv_st recv_wqe_segment_ctrl;/* Receive segment format */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00080];
+/* -------------- */
+};
+
+/* Event_data Field - Port State Change */
+
+struct arbelprm_port_state_change_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00040];
+/* -------------- */
+ pseudo_bit_t reserved1[0x0001c];
+ pseudo_bit_t p[0x00002]; /* Port number (1 or 2) */
+ pseudo_bit_t reserved2[0x00002];
+/* -------------- */
+ pseudo_bit_t reserved3[0x00060];
+/* -------------- */
+};
+
+/* Event_data Field - Completion Queue Error */
+
+struct arbelprm_completion_queue_error_st { /* Little Endian */
+ pseudo_bit_t cqn[0x00018]; /* CQ number event is reported for */
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00020];
+/* -------------- */
+ pseudo_bit_t syndrome[0x00008]; /* Error syndrome
+ 0x01 - CQ overrun
+ 0x02 - CQ access violation error */
+ pseudo_bit_t reserved2[0x00018];
+/* -------------- */
+ pseudo_bit_t reserved3[0x00060];
+/* -------------- */
+};
+
+/* Event_data Field - Completion Event */
+
+struct arbelprm_completion_event_st { /* Little Endian */
+ pseudo_bit_t cqn[0x00018]; /* CQ number event is reported for */
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved1[0x000a0];
+/* -------------- */
+};
+
+/* Event Queue Entry */
+
+struct arbelprm_event_queue_entry_st { /* Little Endian */
+ pseudo_bit_t event_sub_type[0x00008];/* Event Sub Type.
+ Defined for events which have sub types, zero elsewhere. */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t event_type[0x00008]; /* Event Type */
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t event_data[6][0x00020];/* Delivers auxilary data to handle event. */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00007];
+ pseudo_bit_t owner[0x00001]; /* Owner of the entry
+ 0 SW
+ 1 HW */
+ pseudo_bit_t reserved3[0x00018];
+/* -------------- */
+};
+
+/* QP/EE State Transitions Command Parameters */
+
+struct arbelprm_qp_ee_state_transitions_st { /* Little Endian */
+ pseudo_bit_t opt_param_mask[0x00020];/* This field defines which optional parameters are passed. Each bit specifies whether optional parameter is passed (set) or not (cleared). The optparammask is defined for each QP/EE command. */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+ struct arbelprm_queue_pair_ee_context_entry_st qpc_eec_data;/* QPC/EEC data */
+/* -------------- */
+ pseudo_bit_t reserved1[0x009c0];
+/* -------------- */
+};
+
+/* Completion Queue Entry Format */
+
+struct arbelprm_completion_queue_entry_st { /* Little Endian */
+ pseudo_bit_t my_qpn[0x00018]; /* Indicates the QP for which completion is being reported */
+ pseudo_bit_t reserved0[0x00004];
+ pseudo_bit_t ver[0x00004]; /* CQE version.
+ 0 for InfiniHost-III-EX */
+/* -------------- */
+ pseudo_bit_t my_ee[0x00018]; /* EE context (for RD only).
+ Invalid for Bind and Nop operation on RD.
+ For non RD services this filed reports the CQE timestamp. The Timestamp is a free running counter that is incremented every TimeStampGranularity tick. The counter rolls-over when it reaches saturation. TimeStampGranularity is configured in the INIT_HCA command. This feature is currently not supported.
+ */
+ pseudo_bit_t checksum_15_8[0x00008];/* Checksum[15:8] - See IPoverIB checksum offloading chapter */
+/* -------------- */
+ pseudo_bit_t rqpn[0x00018]; /* Remote (source) QP number. Valid in Responder CQE only for Datagram QP. */
+ pseudo_bit_t checksum_7_0[0x00008]; /* Checksum[7:0] - See IPoverIB checksum offloading chapter */
+/* -------------- */
+ pseudo_bit_t rlid[0x00010]; /* Remote (source) LID of the message. Valid in Responder of UD QP CQE only. */
+ pseudo_bit_t ml_path[0x00007]; /* My (destination) LID path bits - these are the lowemost LMC bits of the DLID in an incoming UD packet, higher bits of this field, that are not part of the LMC bits are zeroed by HW.
+ Valid in responder of UD QP CQE only.
+ Invalid if incoming message DLID is the permissive LID or incoming message is multicast. */
+ pseudo_bit_t g[0x00001]; /* GRH present indicator. Valid in Responder of UD QP CQE only. */
+ pseudo_bit_t ipok[0x00001]; /* IP OK - See IPoverIB checksum offloading chapter */
+ pseudo_bit_t reserved1[0x00003];
+ pseudo_bit_t sl[0x00004]; /* Service Level of the message. Valid in Responder of UD QP CQE only. */
+/* -------------- */
+ pseudo_bit_t immediate_ethertype_pkey_indx_eecredits[0x00020];/* Valid for receive queue completion only.
+ If Opcode field indicates that this was send/write with immediate, this field contains immediate field of the packet.
+ If completion corresponds to RAW receive queue, bits 15:0 contain Ethertype field of the packet.
+ If completion corresponds to GSI receive queue, bits 31:16 contain index in PKey table that matches PKey of the message arrived.
+ If Opcode field indicates that this was send and invalidate, this field contains the key that was invalidated.
+ For CQE of send queue of the reliable connection service (but send and invalide), bits [4:0] of this field contain the encoded EEcredits received in last ACK of the message. */
+/* -------------- */
+ pseudo_bit_t byte_cnt[0x00020]; /* Byte count of data actually transferred (valid for receive queue completions only) */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00006];
+ pseudo_bit_t wqe_adr[0x0001a]; /* Bits 31:6 of WQE virtual address completion is reported for. The 6 least significant bits are zero. */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00007];
+ pseudo_bit_t owner[0x00001]; /* Owner field. Zero value of this field means SW ownership of CQE. */
+ pseudo_bit_t reserved4[0x0000f];
+ pseudo_bit_t s[0x00001]; /* If set, completion is reported for Send queue, if cleared - receive queue. */
+ pseudo_bit_t opcode[0x00008]; /* The opcode of WQE completion is reported for.
+ For CQEs corresponding to send completion, NOPCODE field of the WQE is copied to this field.
+ For CQEs corresponding to receive completions, opcode field of last packet in the message copied to this field.
+ For CQEs corresponding to the receive queue of QPs mapped to QP1, the opcode will be SEND with Immediate (messages are guaranteed to be SEND only)
+
+ The following values are reported in case of completion with error:
+ 0xFE - For completion with error on Receive Queues
+ 0xFF - For completion with error on Send Queues */
+/* -------------- */
+};
+
+/* */
+
+struct arbelprm_ecc_detect_event_data_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00080];
+/* -------------- */
+ pseudo_bit_t cause_lsb[0x00001];
+ pseudo_bit_t reserved1[0x00002];
+ pseudo_bit_t cause_msb[0x00001];
+ pseudo_bit_t reserved2[0x00002];
+ pseudo_bit_t err_rmw[0x00001];
+ pseudo_bit_t err_src_id[0x00003];
+ pseudo_bit_t err_da[0x00002];
+ pseudo_bit_t err_ba[0x00002];
+ pseudo_bit_t reserved3[0x00011];
+ pseudo_bit_t overflow[0x00001];
+/* -------------- */
+ pseudo_bit_t err_ra[0x00010];
+ pseudo_bit_t err_ca[0x00010];
+/* -------------- */
+};
+
+/* Event_data Field - ECC Detection Event */
+
+struct arbelprm_scrubbing_event_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00080];
+/* -------------- */
+ pseudo_bit_t cause_lsb[0x00001]; /* data integrity error cause:
+ single ECC error in the 64bit lsb data, on the rise edge of the clock */
+ pseudo_bit_t reserved1[0x00002];
+ pseudo_bit_t cause_msb[0x00001]; /* data integrity error cause:
+ single ECC error in the 64bit msb data, on the fall edge of the clock */
+ pseudo_bit_t reserved2[0x00002];
+ pseudo_bit_t err_rmw[0x00001]; /* transaction type:
+ 0 - read
+ 1 - read/modify/write */
+ pseudo_bit_t err_src_id[0x00003]; /* source of the transaction: 0x4 - PCI, other - internal or IB */
+ pseudo_bit_t err_da[0x00002]; /* Error DIMM address */
+ pseudo_bit_t err_ba[0x00002]; /* Error bank address */
+ pseudo_bit_t reserved3[0x00011];
+ pseudo_bit_t overflow[0x00001]; /* Fatal: ECC error FIFO overflow - ECC errors were detected, which may or may not have been corrected by InfiniHost-III-EX */
+/* -------------- */
+ pseudo_bit_t err_ra[0x00010]; /* Error row address */
+ pseudo_bit_t err_ca[0x00010]; /* Error column address */
+/* -------------- */
+};
+
+/* Miscellaneous Counters */
+
+struct arbelprm_misc_counters_st { /* Little Endian */
+ pseudo_bit_t ddr_scan_cnt[0x00020]; /* Number of times whole of LAM was scanned */
+/* -------------- */
+ pseudo_bit_t reserved0[0x007e0];
+/* -------------- */
+};
+
+/* LAM_EN Output Parameter */
+
+struct arbelprm_lam_en_out_param_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00040];
+/* -------------- */
+};
+
+/* Extended_Completion_Queue_Entry */
+
+struct arbelprm_extended_completion_queue_entry_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+};
+
+/* */
+
+struct arbelprm_eq_cmd_doorbell_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+};
+
+/* 0 */
+
+struct arbelprm_arbel_prm_st { /* Little Endian */
+ struct arbelprm_completion_queue_entry_st completion_queue_entry;/* Completion Queue Entry Format */
+/* -------------- */
+ pseudo_bit_t reserved0[0x7ff00];
+/* -------------- */
+ struct arbelprm_qp_ee_state_transitions_st qp_ee_state_transitions;/* QP/EE State Transitions Command Parameters */
+/* -------------- */
+ pseudo_bit_t reserved1[0x7f000];
+/* -------------- */
+ struct arbelprm_event_queue_entry_st event_queue_entry;/* Event Queue Entry */
+/* -------------- */
+ pseudo_bit_t reserved2[0x7ff00];
+/* -------------- */
+ struct arbelprm_completion_event_st completion_event;/* Event_data Field - Completion Event */
+/* -------------- */
+ pseudo_bit_t reserved3[0x7ff40];
+/* -------------- */
+ struct arbelprm_completion_queue_error_st completion_queue_error;/* Event_data Field - Completion Queue Error */
+/* -------------- */
+ pseudo_bit_t reserved4[0x7ff40];
+/* -------------- */
+ struct arbelprm_port_state_change_st port_state_change;/* Event_data Field - Port State Change */
+/* -------------- */
+ pseudo_bit_t reserved5[0x7ff40];
+/* -------------- */
+ struct arbelprm_wqe_segment_st wqe_segment;/* WQE segments format */
+/* -------------- */
+ pseudo_bit_t reserved6[0x7f000];
+/* -------------- */
+ struct arbelprm_page_fault_event_data_st page_fault_event_data;/* Event_data Field - Page Faults */
+/* -------------- */
+ pseudo_bit_t reserved7[0x7ff40];
+/* -------------- */
+ struct arbelprm_performance_monitor_event_st performance_monitor_event;/* Event Data Field - Performance Monitor */
+/* -------------- */
+ pseudo_bit_t reserved8[0xfff20];
+/* -------------- */
+ struct arbelprm_mt25208_type0_st mt25208_type0;/* InfiniHost-III-EX Type0 Configuration Header */
+/* -------------- */
+ pseudo_bit_t reserved9[0x7f000];
+/* -------------- */
+ struct arbelprm_qp_ee_event_st qp_ee_event;/* Event_data Field - QP/EE Events */
+/* -------------- */
+ pseudo_bit_t reserved10[0x00040];
+/* -------------- */
+ struct arbelprm_gpio_event_data_st gpio_event_data;
+/* -------------- */
+ pseudo_bit_t reserved11[0x7fe40];
+/* -------------- */
+ struct arbelprm_ud_address_vector_st ud_address_vector;/* UD Address Vector */
+/* -------------- */
+ pseudo_bit_t reserved12[0x7ff00];
+/* -------------- */
+ struct arbelprm_queue_pair_ee_context_entry_st queue_pair_ee_context_entry;/* QP and EE Context Entry */
+/* -------------- */
+ pseudo_bit_t reserved13[0x7fa00];
+/* -------------- */
+ struct arbelprm_address_path_st address_path;/* Address Path */
+/* -------------- */
+ pseudo_bit_t reserved14[0x7ff00];
+/* -------------- */
+ struct arbelprm_completion_queue_context_st completion_queue_context;/* Completion Queue Context Table Entry */
+/* -------------- */
+ pseudo_bit_t reserved15[0x7fe00];
+/* -------------- */
+ struct arbelprm_mpt_st mpt; /* Memory Protection Table (MPT) Entry */
+/* -------------- */
+ pseudo_bit_t reserved16[0x7fe00];
+/* -------------- */
+ struct arbelprm_mtt_st mtt; /* Memory Translation Table (MTT) Entry */
+/* -------------- */
+ pseudo_bit_t reserved17[0x7ffc0];
+/* -------------- */
+ struct arbelprm_eqc_st eqc; /* Event Queue Context Table Entry */
+/* -------------- */
+ pseudo_bit_t reserved18[0x7fe00];
+/* -------------- */
+ struct arbelprm_performance_monitors_st performance_monitors;/* Performance Monitors */
+/* -------------- */
+ pseudo_bit_t reserved19[0x7ff80];
+/* -------------- */
+ struct arbelprm_hca_command_register_st hca_command_register;/* HCA Command Register (HCR) */
+/* -------------- */
+ pseudo_bit_t reserved20[0xfff20];
+/* -------------- */
+ struct arbelprm_init_hca_st init_hca;/* INIT_HCA & QUERY_HCA Parameters Block */
+/* -------------- */
+ pseudo_bit_t reserved21[0x7f000];
+/* -------------- */
+ struct arbelprm_qpcbaseaddr_st qpcbaseaddr;/* QPC/EEC/CQC/EQC/RDB Parameters */
+/* -------------- */
+ pseudo_bit_t reserved22[0x7fc00];
+/* -------------- */
+ struct arbelprm_udavtable_memory_parameters_st udavtable_memory_parameters;/* Memory Access Parameters for UD Address Vector Table */
+/* -------------- */
+ pseudo_bit_t reserved23[0x7ffc0];
+/* -------------- */
+ struct arbelprm_multicastparam_st multicastparam;/* Multicast Support Parameters */
+/* -------------- */
+ pseudo_bit_t reserved24[0x7ff00];
+/* -------------- */
+ struct arbelprm_tptparams_st tptparams;/* Translation and Protection Tables Parameters */
+/* -------------- */
+ pseudo_bit_t reserved25[0x7ff00];
+/* -------------- */
+ struct arbelprm_enable_lam_st enable_lam;/* ENABLE_LAM Parameters Block */
+/* -------------- */
+ struct arbelprm_access_lam_st access_lam;
+/* -------------- */
+ pseudo_bit_t reserved26[0x7f700];
+/* -------------- */
+ struct arbelprm_dimminfo_st dimminfo;/* Logical DIMM Information */
+/* -------------- */
+ pseudo_bit_t reserved27[0x7ff00];
+/* -------------- */
+ struct arbelprm_query_fw_st query_fw;/* QUERY_FW Parameters Block */
+/* -------------- */
+ pseudo_bit_t reserved28[0x7f800];
+/* -------------- */
+ struct arbelprm_query_adapter_st query_adapter;/* QUERY_ADAPTER Parameters Block */
+/* -------------- */
+ pseudo_bit_t reserved29[0x7f800];
+/* -------------- */
+ struct arbelprm_query_dev_lim_st query_dev_lim;/* Query Device Limitations */
+/* -------------- */
+ pseudo_bit_t reserved30[0x7f800];
+/* -------------- */
+ struct arbelprm_uar_params_st uar_params;/* UAR Parameters */
+/* -------------- */
+ pseudo_bit_t reserved31[0x7ff00];
+/* -------------- */
+ struct arbelprm_init_ib_st init_ib; /* INIT_IB Parameters */
+/* -------------- */
+ pseudo_bit_t reserved32[0x7f800];
+/* -------------- */
+ struct arbelprm_mgm_entry_st mgm_entry;/* Multicast Group Member */
+/* -------------- */
+ pseudo_bit_t reserved33[0x7fe00];
+/* -------------- */
+ struct arbelprm_set_ib_st set_ib; /* SET_IB Parameters */
+/* -------------- */
+ pseudo_bit_t reserved34[0x7fe00];
+/* -------------- */
+ struct arbelprm_rd_send_doorbell_st rd_send_doorbell;/* RD-send doorbell */
+/* -------------- */
+ pseudo_bit_t reserved35[0x7ff80];
+/* -------------- */
+ struct arbelprm_send_doorbell_st send_doorbell;/* Send doorbell */
+/* -------------- */
+ pseudo_bit_t reserved36[0x7ffc0];
+/* -------------- */
+ struct arbelprm_receive_doorbell_st receive_doorbell;/* Receive doorbell */
+/* -------------- */
+ pseudo_bit_t reserved37[0x7ffc0];
+/* -------------- */
+ struct arbelprm_cq_cmd_doorbell_st cq_cmd_doorbell;/* CQ Doorbell */
+/* -------------- */
+ pseudo_bit_t reserved38[0xfffc0];
+/* -------------- */
+ struct arbelprm_uar_st uar; /* User Access Region */
+/* -------------- */
+ pseudo_bit_t reserved39[0x7c000];
+/* -------------- */
+ struct arbelprm_mgmqp_st mgmqp; /* Multicast Group Member QP */
+/* -------------- */
+ pseudo_bit_t reserved40[0x7ffe0];
+/* -------------- */
+ struct arbelprm_query_debug_msg_st query_debug_msg;/* Query Debug Message */
+/* -------------- */
+ pseudo_bit_t reserved41[0x7f800];
+/* -------------- */
+ struct arbelprm_mad_ifc_st mad_ifc; /* MAD_IFC Input Mailbox */
+/* -------------- */
+ pseudo_bit_t reserved42[0x00900];
+/* -------------- */
+ struct arbelprm_mad_ifc_input_modifier_st mad_ifc_input_modifier;/* MAD_IFC Input Modifier */
+/* -------------- */
+ pseudo_bit_t reserved43[0x7e6e0];
+/* -------------- */
+ struct arbelprm_resize_cq_st resize_cq;/* Resize CQ Input Mailbox */
+/* -------------- */
+ pseudo_bit_t reserved44[0x7fe00];
+/* -------------- */
+ struct arbelprm_completion_with_error_st completion_with_error;/* Completion with Error CQE */
+/* -------------- */
+ pseudo_bit_t reserved45[0x7ff00];
+/* -------------- */
+ struct arbelprm_hcr_completion_event_st hcr_completion_event;/* Event_data Field - HCR Completion Event */
+/* -------------- */
+ pseudo_bit_t reserved46[0x7ff40];
+/* -------------- */
+ struct arbelprm_transport_and_ci_error_counters_st transport_and_ci_error_counters;/* Transport and CI Error Counters */
+/* -------------- */
+ pseudo_bit_t reserved47[0x7f000];
+/* -------------- */
+ struct arbelprm_performance_counters_st performance_counters;/* Performance Counters */
+/* -------------- */
+ pseudo_bit_t reserved48[0x9ff800];
+/* -------------- */
+ struct arbelprm_fast_registration_segment_st fast_registration_segment;/* Fast Registration Segment */
+/* -------------- */
+ pseudo_bit_t reserved49[0x7ff00];
+/* -------------- */
+ struct arbelprm_pbl_st pbl; /* Physical Buffer List */
+/* -------------- */
+ pseudo_bit_t reserved50[0x7ff00];
+/* -------------- */
+ struct arbelprm_srq_context_st srq_context;/* SRQ Context */
+/* -------------- */
+ pseudo_bit_t reserved51[0x7fe80];
+/* -------------- */
+ struct arbelprm_mod_stat_cfg_st mod_stat_cfg;/* MOD_STAT_CFG */
+/* -------------- */
+ pseudo_bit_t reserved52[0x7f800];
+/* -------------- */
+ struct arbelprm_virtual_physical_mapping_st virtual_physical_mapping;/* Virtual and Physical Mapping */
+/* -------------- */
+ pseudo_bit_t reserved53[0x7ff80];
+/* -------------- */
+ struct arbelprm_cq_ci_db_record_st cq_ci_db_record;/* CQ_CI_DB_Record */
+/* -------------- */
+ pseudo_bit_t reserved54[0x7ffc0];
+/* -------------- */
+ struct arbelprm_cq_arm_db_record_st cq_arm_db_record;/* CQ_ARM_DB_Record */
+/* -------------- */
+ pseudo_bit_t reserved55[0x7ffc0];
+/* -------------- */
+ struct arbelprm_qp_db_record_st qp_db_record;/* QP_DB_Record */
+/* -------------- */
+ pseudo_bit_t reserved56[0x1fffc0];
+/* -------------- */
+ struct arbelprm_configuration_registers_st configuration_registers;/* InfiniHost III EX Configuration Registers */
+/* -------------- */
+ struct arbelprm_eq_set_ci_table_st eq_set_ci_table;/* EQ Set CI DBs Table */
+/* -------------- */
+ pseudo_bit_t reserved57[0x01000];
+/* -------------- */
+ struct arbelprm_eq_arm_db_region_st eq_arm_db_region;/* EQ Arm Doorbell Region */
+/* -------------- */
+ pseudo_bit_t reserved58[0x00fc0];
+/* -------------- */
+ struct arbelprm_clr_int_st clr_int; /* Clear Interrupt Register */
+/* -------------- */
+ pseudo_bit_t reserved59[0xffcfc0];
+/* -------------- */
+};
+#endif /* H_prefix_arbelprm_bits_fixnames_MT25218_PRM_csp_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/MT25408_PRM.h b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/MT25408_PRM.h
new file mode 100644
index 00000000..cc248daf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/MT25408_PRM.h
@@ -0,0 +1,3404 @@
+/*
+ This software is available to you under a choice of one of two
+ licenses. You may choose to be licensed under the terms of the GNU
+ General Public License (GPL) Version 2, available at
+ <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD
+ license, available in the LICENSE.TXT file accompanying this
+ software. These details are also available at
+ <http://openib.org/license.html>.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+ Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
+*/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/***
+ *** This file was generated at "Mon Apr 16 23:22:02 2007"
+ *** by:
+ *** % csp_bf -copyright=/mswg/misc/license-header.txt -prefix hermonprm_ -bits -fixnames MT25408_PRM.csp
+ ***/
+
+#ifndef H_prefix_hermonprm_bits_fixnames_MT25408_PRM_csp_H
+#define H_prefix_hermonprm_bits_fixnames_MT25408_PRM_csp_H
+
+/* UD Address Vector */
+
+struct hermonprm_ud_address_vector_st { /* Little Endian */
+ pseudo_bit_t pd[0x00018]; /* Protection Domain */
+ pseudo_bit_t port_number[0x00002]; /* Port number
+ 1 - Port 1
+ 2 - Port 2
+ other - reserved */
+ pseudo_bit_t reserved0[0x00005];
+ pseudo_bit_t fl[0x00001]; /* force loopback */
+/* -------------- */
+ pseudo_bit_t rlid[0x00010]; /* Remote (Destination) LID */
+ pseudo_bit_t my_lid_path_bits[0x00007];/* Source LID - the lower 7 bits (upper bits are taken from PortInfo) */
+ pseudo_bit_t g[0x00001]; /* Global address enable - if set, GRH will be formed for packet header */
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t hop_limit[0x00008]; /* IPv6 hop limit */
+ pseudo_bit_t max_stat_rate[0x00004];/* Maximum static rate control.
+ 0 - 4X injection rate
+ 1 - 1X injection rate
+ other - reserved
+ */
+ pseudo_bit_t reserved2[0x00004];
+ pseudo_bit_t mgid_index[0x00007]; /* Index to port GID table
+ mgid_index = (port_number-1) * 2^log_max_gid + gid_index
+ Where:
+ 1. log_max_gid is taken from QUERY_DEV_CAP command
+ 2. gid_index is the index to the GID table */
+ pseudo_bit_t reserved3[0x00009];
+/* -------------- */
+ pseudo_bit_t flow_label[0x00014]; /* IPv6 flow label */
+ pseudo_bit_t tclass[0x00008]; /* IPv6 TClass */
+ pseudo_bit_t sl[0x00004]; /* InfiniBand Service Level (SL) */
+/* -------------- */
+ pseudo_bit_t rgid_127_96[0x00020]; /* Remote GID[127:96] */
+/* -------------- */
+ pseudo_bit_t rgid_95_64[0x00020]; /* Remote GID[95:64] */
+/* -------------- */
+ pseudo_bit_t rgid_63_32[0x00020]; /* Remote GID[63:32] */
+/* -------------- */
+ pseudo_bit_t rgid_31_0[0x00020]; /* Remote GID[31:0] if G bit is set. Must be set to 0x2 if G bit is cleared. */
+/* -------------- */
+};
+
+/* Send doorbell */
+
+struct hermonprm_send_doorbell_st { /* Little Endian */
+ pseudo_bit_t nopcode[0x00005]; /* Opcode of descriptor to be executed */
+ pseudo_bit_t f[0x00001]; /* Fence bit. If set, descriptor is fenced */
+ pseudo_bit_t reserved0[0x00002];
+ pseudo_bit_t wqe_counter[0x00010]; /* Modulo-64K counter of WQEs posted to the QP since its creation excluding the newly posted WQEs in this doorbell. Should be zero for the first doorbell on the QP */
+ pseudo_bit_t wqe_cnt[0x00008]; /* Number of WQEs posted with this doorbell. Must be grater then zero. */
+/* -------------- */
+ pseudo_bit_t nds[0x00006]; /* Next descriptor size (in 16-byte chunks) */
+ pseudo_bit_t reserved1[0x00002];
+ pseudo_bit_t qpn[0x00018]; /* QP number this doorbell is rung on */
+/* -------------- */
+};
+
+/* Send wqe segment data inline */
+
+struct hermonprm_wqe_segment_data_inline_st { /* Little Endian */
+ pseudo_bit_t byte_count[0x0000a]; /* Not including padding for 16Byte chunks */
+ pseudo_bit_t reserved0[0x00015];
+ pseudo_bit_t always1[0x00001];
+/* -------------- */
+ pseudo_bit_t data[0x00018]; /* Data may be more this segment size - in 16Byte chunks */
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved2[0x00040];
+/* -------------- */
+};
+
+/* Send wqe segment data ptr */
+
+struct hermonprm_wqe_segment_data_ptr_st { /* Little Endian */
+ pseudo_bit_t byte_count[0x0001f];
+ pseudo_bit_t always0[0x00001];
+/* -------------- */
+ pseudo_bit_t l_key[0x00020];
+/* -------------- */
+ pseudo_bit_t local_address_h[0x00020];
+/* -------------- */
+ pseudo_bit_t local_address_l[0x00020];
+/* -------------- */
+};
+
+/* Send wqe segment rd */
+
+struct hermonprm_local_invalidate_segment_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00040];
+/* -------------- */
+ pseudo_bit_t mem_key[0x00018];
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved2[0x000a0];
+/* -------------- */
+};
+
+/* Fast_Registration_Segment ####michal - doesn't match PRM (fields were added, see below) new table size in bytes - 0x30 */
+
+struct hermonprm_fast_registration_segment_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x0001b];
+ pseudo_bit_t lr[0x00001]; /* If set - Local Read access will be enabled */
+ pseudo_bit_t lw[0x00001]; /* If set - Local Write access will be enabled */
+ pseudo_bit_t rr[0x00001]; /* If set - Remote Read access will be enabled */
+ pseudo_bit_t rw[0x00001]; /* If set - Remote Write access will be enabled */
+ pseudo_bit_t a[0x00001]; /* If set - Remote Atomic access will be enabled */
+/* -------------- */
+ pseudo_bit_t pbl_ptr_63_32[0x00020];/* Physical address pointer [63:32] to the physical buffer list ### michal - this field is replaced with mem_key .32 */
+/* -------------- */
+ pseudo_bit_t mem_key[0x00020]; /* Memory Key on which the fast registration is executed on. ###michal-this field is replaced with pbl_ptr_63_32 */
+/* -------------- */
+ pseudo_bit_t page_size[0x00005]; /* Page size used for the region. Actual size is [4K]*2^Page_size bytes.
+ page_size should be less than 20. ###michal - field doesn't exsist (see replacement above) */
+ pseudo_bit_t reserved1[0x00002];
+ pseudo_bit_t zb[0x00001]; /* Zero Based Region ###michal - field doesn't exsist (see replacement above) */
+ pseudo_bit_t pbl_ptr_31_8[0x00018]; /* Physical address pointer [31:8] to the physical buffer list ###michal - field doesn't exsist (see replacement above) */
+/* -------------- */
+ pseudo_bit_t start_address_h[0x00020];/* Start Address[63:32] - Virtual Address where this region starts */
+/* -------------- */
+ pseudo_bit_t start_address_l[0x00020];/* Start Address[31:0] - Virtual Address where this region starts */
+/* -------------- */
+ pseudo_bit_t reg_len_h[0x00020]; /* Region Length[63:32] */
+/* -------------- */
+ pseudo_bit_t reg_len_l[0x00020]; /* Region Length[31:0] */
+/* -------------- */
+};
+
+/* Send wqe segment atomic */
+
+struct hermonprm_wqe_segment_atomic_st { /* Little Endian */
+ pseudo_bit_t swap_add_h[0x00020];
+/* -------------- */
+ pseudo_bit_t swap_add_l[0x00020];
+/* -------------- */
+ pseudo_bit_t compare_h[0x00020];
+/* -------------- */
+ pseudo_bit_t compare_l[0x00020];
+/* -------------- */
+};
+
+/* Send wqe segment remote address */
+
+struct hermonprm_wqe_segment_remote_address_st { /* Little Endian */
+ pseudo_bit_t remote_virt_addr_h[0x00020];
+/* -------------- */
+ pseudo_bit_t remote_virt_addr_l[0x00020];
+/* -------------- */
+ pseudo_bit_t rkey[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+};
+
+/* end wqe segment bind */
+
+struct hermonprm_wqe_segment_bind_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x0001d];
+ pseudo_bit_t rr[0x00001]; /* If set, Remote Read Enable for bound window. */
+ pseudo_bit_t rw[0x00001]; /* If set, Remote Write Enable for bound window.
+ */
+ pseudo_bit_t a[0x00001]; /* If set, Atomic Enable for bound window. */
+/* -------------- */
+ pseudo_bit_t reserved1[0x0001e];
+ pseudo_bit_t zb[0x00001]; /* If set, Window is Zero Based. */
+ pseudo_bit_t type[0x00001]; /* Window type.
+ 0 - Type one window
+ 1 - Type two window
+ */
+/* -------------- */
+ pseudo_bit_t new_rkey[0x00020]; /* The new RKey of window to bind */
+/* -------------- */
+ pseudo_bit_t region_lkey[0x00020]; /* Local key of region, which window will be bound to */
+/* -------------- */
+ pseudo_bit_t start_address_h[0x00020];
+/* -------------- */
+ pseudo_bit_t start_address_l[0x00020];
+/* -------------- */
+ pseudo_bit_t length_h[0x00020];
+/* -------------- */
+ pseudo_bit_t length_l[0x00020];
+/* -------------- */
+};
+
+/* Send wqe segment ud */
+
+struct hermonprm_wqe_segment_ud_st { /* Little Endian */
+ struct hermonprm_ud_address_vector_st ud_address_vector;/* UD Address Vector */
+/* -------------- */
+ pseudo_bit_t destination_qp[0x00018];
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t q_key[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00040];
+/* -------------- */
+};
+
+/* Send wqe segment rd */
+
+struct hermonprm_wqe_segment_rd_st { /* Little Endian */
+ pseudo_bit_t destination_qp[0x00018];
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t q_key[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00040];
+/* -------------- */
+};
+
+/* Send wqe segment ctrl */
+
+struct hermonprm_wqe_segment_ctrl_send_st { /* Little Endian */
+ pseudo_bit_t opcode[0x00005];
+ pseudo_bit_t reserved0[0x0001a];
+ pseudo_bit_t owner[0x00001];
+/* -------------- */
+ pseudo_bit_t ds[0x00006]; /* descriptor (wqe) size in 16bytes chunk */
+ pseudo_bit_t f[0x00001]; /* fence */
+ pseudo_bit_t reserved1[0x00019];
+/* -------------- */
+ pseudo_bit_t fl[0x00001]; /* Force LoopBack */
+ pseudo_bit_t s[0x00001]; /* Remote Solicited Event */
+ pseudo_bit_t c[0x00002]; /* completion required: 0b00 - no 0b11 - yes */
+ pseudo_bit_t ip[0x00001]; /* When set, InfiniHost III Ex will calculate the IP checksum of the IP header that is present immediately after the IPoverIB encapsulation header. In the case of multiple headers (encapsulation), InfiniHost III Ex will calculate the checksum only for the first IP header following the IPoverIB encapsulation header. Not Valid for IPv6 packets */
+ pseudo_bit_t tcp_udp[0x00001]; /* When set, InfiniHost III Ex will calculate the TCP/UDP checksum of the packet that is present immediately after the IP header. In the case of multiple headers (encapsulation), InfiniHost III Ex will calculate the checksum only for the first TCP header following the IP header. This bit may be set only if the entire TCP/UDP segment is present in one IB packet */
+ pseudo_bit_t reserved2[0x00001];
+ pseudo_bit_t so[0x00001]; /* Strong Ordering - when set, the WQE will be executed only after all previous WQEs have been executed. Can be set for RC WQEs only. This bit must be set in type two BIND, Fast Registration and Local invalidate operations. */
+ pseudo_bit_t src_remote_buf[0x00018];
+/* -------------- */
+ pseudo_bit_t immediate[0x00020]; /* If the OpCode encodes an operation with Immediate (RDMA-write/SEND), This field will hold the Immediate data to be sent. If the OpCode encodes send and invalidate operations, this field holds the Invalidation key to be inserted into the packet; otherwise, this field is reserved. */
+/* -------------- */
+};
+
+/* Address Path # ###michal - match to PRM */
+
+struct hermonprm_address_path_st { /* Little Endian */
+ pseudo_bit_t pkey_index[0x00007]; /* PKey table index */
+ pseudo_bit_t reserved0[0x00016];
+ pseudo_bit_t sv[0x00001]; /* Service VLAN on QP */
+ pseudo_bit_t cv[0x00001]; /* Customer VLAN in QP */
+ pseudo_bit_t fl[0x00001]; /* Force LoopBack */
+/* -------------- */
+ pseudo_bit_t rlid[0x00010]; /* Remote (Destination) LID */
+ pseudo_bit_t my_lid_smac_idx[0x00007];/* Source LID - the lower 7 bits (upper bits are taken from PortInfo) */
+ pseudo_bit_t grh_ip[0x00001]; /* Global address enable - if set, GRH will be formed for packet header */
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t hop_limit[0x00008]; /* IPv6 hop limit */
+ pseudo_bit_t max_stat_rate[0x00004];/* Maximum static rate control.
+ 0 - 100% injection rate
+ 1 - 25% injection rate
+ 2 - 12.5% injection rate
+ 3 - 50% injection rate
+ 7: 2.5 Gb/s.
+ 8: 10 Gb/s.
+ 9: 30 Gb/s.
+ 10: 5 Gb/s.
+ 11: 20 Gb/s.
+ 12: 40 Gb/s.
+ 13: 60 Gb/s.
+ 14: 80 Gb/s.
+ 15: 120 Gb/s. */
+ pseudo_bit_t reserved2[0x00004];
+ pseudo_bit_t mgid_index[0x00007]; /* Index to port GID table */
+ pseudo_bit_t reserved3[0x00004];
+ pseudo_bit_t ack_timeout[0x00005]; /* Local ACK timeout - Transport timer for activation of retransmission mechanism. Refer to IB spec Vol1 9.7.6.1.3 for further details.
+ The transport timer is set to 4.096us*2^ack_timeout, if ack_timeout is 0 then transport timer is disabled. */
+/* -------------- */
+ pseudo_bit_t flow_label[0x00014]; /* IPv6 flow label */
+ pseudo_bit_t tclass[0x00008]; /* IPv6 TClass */
+ pseudo_bit_t reserved4[0x00004];
+/* -------------- */
+ pseudo_bit_t rgid_127_96[0x00020]; /* Remote GID[127:96] */
+/* -------------- */
+ pseudo_bit_t rgid_95_64[0x00020]; /* Remote GID[95:64] */
+/* -------------- */
+ pseudo_bit_t rgid_63_32[0x00020]; /* Remote GID[63:32] */
+/* -------------- */
+ pseudo_bit_t rgid_31_0[0x00020]; /* Remote GID[31:0] */
+/* -------------- */
+ pseudo_bit_t reserved5[0x00008];
+ pseudo_bit_t sp[0x00001]; /* if set, spoofing protection is enforced on this QP and Ethertype headers are restricted */
+ pseudo_bit_t reserved6[0x00002];
+ pseudo_bit_t fvl[0x00001]; /* force VLAN */
+ pseudo_bit_t fsip[0x00001]; /* force source IP */
+ pseudo_bit_t fsm[0x00001]; /* force source MAC */
+ pseudo_bit_t reserved7[0x0000a];
+ pseudo_bit_t sched_queue[0x00008];
+/* -------------- */
+ pseudo_bit_t dmac_47_32[0x00010];
+ pseudo_bit_t vlan_index[0x00007];
+ pseudo_bit_t reserved8[0x00001];
+ pseudo_bit_t counter_index[0x00008];/* Index to a table of counters that counts egress packets and bytes, 0xFF not valid */
+/* -------------- */
+ pseudo_bit_t dmac_31_0[0x00020];
+/* -------------- */
+};
+
+/* HCA Command Register (HCR) #### michal - match PRM */
+
+struct hermonprm_hca_command_register_st { /* Little Endian */
+ pseudo_bit_t in_param_h[0x00020]; /* Input Parameter: parameter[63:32] or pointer[63:32] to input mailbox (see command description) */
+/* -------------- */
+ pseudo_bit_t in_param_l[0x00020]; /* Input Parameter: parameter[31:0] or pointer[31:0] to input mailbox (see command description) */
+/* -------------- */
+ pseudo_bit_t input_modifier[0x00020];/* Input Parameter Modifier */
+/* -------------- */
+ pseudo_bit_t out_param_h[0x00020]; /* Output Parameter: parameter[63:32] or pointer[63:32] to output mailbox (see command description) */
+/* -------------- */
+ pseudo_bit_t out_param_l[0x00020]; /* Output Parameter: parameter[31:0] or pointer[31:0] to output mailbox (see command description) */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00010];
+ pseudo_bit_t token[0x00010]; /* Software assigned token to the command, to uniquely identify it. The token is returned to the software in the EQE reported. */
+/* -------------- */
+ pseudo_bit_t opcode[0x0000c]; /* Command opcode */
+ pseudo_bit_t opcode_modifier[0x00004];/* Opcode Modifier, see specific description for each command. */
+ pseudo_bit_t reserved1[0x00005];
+ pseudo_bit_t t[0x00001]; /* Toggle */
+ pseudo_bit_t e[0x00001]; /* Event Request
+ 0 - Don't report event (software will poll the GO bit)
+ 1 - Report event to EQ when the command completes */
+ pseudo_bit_t go[0x00001]; /* Go (0=Software ownership for the HCR, 1=Hardware ownership for the HCR)
+ Software can write to the HCR only if Go bit is cleared.
+ Software must set the Go bit to trigger the HW to execute the command. Software must not write to this register value other than 1 for the Go bit. */
+ pseudo_bit_t status[0x00008]; /* Command execution status report. Valid only if command interface in under SW ownership (Go bit is cleared)
+ 0 - command completed without error. If different than zero, command execution completed with error. Syndrom encoding is depended on command executed and is defined for each command */
+/* -------------- */
+};
+
+/* CQ Doorbell */
+
+struct hermonprm_cq_cmd_doorbell_st { /* Little Endian */
+ pseudo_bit_t cqn[0x00018]; /* CQ number accessed */
+ pseudo_bit_t cmd[0x00003]; /* Command to be executed on CQ
+ 0x0 - Reserved
+ 0x1 - Request notification for next Solicited completion event. CQ_param specifies the current CQ Consumer Counter.
+ 0x2 - Request notification for next Solicited or Unsolicited completion event. CQ_param specifies the current CQ Consumer Counter.
+ 0x3 - Request notification for multiple completions (Arm-N). CQ_param specifies the value of the CQ Counter that when reached by HW (i.e. HW generates a CQE into this Counter) Event will be generated
+ Other - Reserved */
+ pseudo_bit_t reserved0[0x00001];
+ pseudo_bit_t cmd_sn[0x00002]; /* Command Sequence Number - This field should be incremented upon receiving completion notification of the respective CQ.
+ This transition is done by ringing Request notification for next Solicited, Request notification for next Solicited or Unsolicited
+ completion or Request notification for multiple completions doorbells after receiving completion notification.
+ This field is initialized to Zero */
+ pseudo_bit_t reserved1[0x00002];
+/* -------------- */
+ pseudo_bit_t cq_param[0x00020]; /* parameter to be used by CQ command */
+/* -------------- */
+};
+
+/* RD-send doorbell */
+
+struct hermonprm_rd_send_doorbell_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t een[0x00018]; /* End-to-end context number (reliable datagram)
+ Must be zero for Nop and Bind operations */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00008];
+ pseudo_bit_t qpn[0x00018]; /* QP number this doorbell is rung on */
+/* -------------- */
+ struct hermonprm_send_doorbell_st send_doorbell;/* Send Parameters */
+/* -------------- */
+};
+
+/* Multicast Group Member QP #### michal - match PRM */
+
+struct hermonprm_mgmqp_st { /* Little Endian */
+ pseudo_bit_t qpn_i[0x00018]; /* QPN_i: QP number which is a member in this multicast group. Valid only if Qi bit is set. Length of the QPN_i list is set in INIT_HCA */
+ pseudo_bit_t reserved0[0x00006];
+ pseudo_bit_t blck_lb[0x00001]; /* Block self-loopback messages arriving to this qp */
+ pseudo_bit_t qi[0x00001]; /* Qi: QPN_i is valid */
+/* -------------- */
+};
+
+/* vsd */
+
+struct hermonprm_vsd_st { /* Little Endian */
+ pseudo_bit_t vsd_dw0[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw1[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw2[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw3[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw4[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw5[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw6[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw7[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw8[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw9[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw10[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw11[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw12[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw13[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw14[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw15[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw16[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw17[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw18[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw19[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw20[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw21[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw22[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw23[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw24[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw25[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw26[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw27[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw28[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw29[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw30[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw31[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw32[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw33[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw34[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw35[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw36[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw37[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw38[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw39[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw40[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw41[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw42[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw43[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw44[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw45[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw46[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw47[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw48[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw49[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw50[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw51[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw52[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw53[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw54[0x00020];
+/* -------------- */
+ pseudo_bit_t vsd_dw55[0x00020];
+/* -------------- */
+};
+
+/* UAR Parameters */
+
+struct hermonprm_uar_params_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00040];
+/* -------------- */
+ pseudo_bit_t uar_page_sz[0x00008]; /* This field defines the size of each UAR page.
+ Size of UAR Page is 4KB*2^UAR_Page_Size */
+ pseudo_bit_t log_max_uars[0x00004]; /* Number of UARs supported is 2^log_max_UARs */
+ pseudo_bit_t reserved1[0x00014];
+/* -------------- */
+ pseudo_bit_t reserved2[0x000a0];
+/* -------------- */
+};
+
+/* Translation and Protection Tables Parameters */
+
+struct hermonprm_tptparams_st { /* Little Endian */
+ pseudo_bit_t dmpt_base_adr_h[0x00020];/* dMPT - Memory Protection Table base physical address [63:32].
+ Entry size is 64 bytes.
+ Table must be aligned to its size.
+ Address may be set to 0xFFFFFFFF if address translation and protection is not supported. */
+/* -------------- */
+ pseudo_bit_t dmpt_base_adr_l[0x00020];/* dMPT - Memory Protection Table base physical address [31:0].
+ Entry size is 64 bytes.
+ Table must be aligned to its size.
+ Address may be set to 0xFFFFFFFF if address translation and protection is not supported. */
+/* -------------- */
+ pseudo_bit_t log_dmpt_sz[0x00006]; /* Log (base 2) of the number of region/windows entries in the dMPT table. */
+ pseudo_bit_t reserved0[0x00002];
+ pseudo_bit_t pfto[0x00005]; /* Page Fault RNR Timeout -
+ The field returned in RNR Naks generated when a page fault is detected.
+ It has no effect when on-demand-paging is not used. */
+ pseudo_bit_t reserved1[0x00013];
+/* -------------- */
+ pseudo_bit_t reserved2[0x00020];
+/* -------------- */
+ pseudo_bit_t mtt_base_addr_h[0x00020];/* MTT - Memory Translation table base physical address [63:32].
+ Table must be aligned to its size.
+ Address may be set to 0xFFFFFFFF if address translation and protection is not supported. */
+/* -------------- */
+ pseudo_bit_t mtt_base_addr_l[0x00020];/* MTT - Memory Translation table base physical address [31:0].
+ Table must be aligned to its size.
+ Address may be set to 0xFFFFFFFF if address translation and protection is not supported. */
+/* -------------- */
+ pseudo_bit_t cmpt_base_adr_h[0x00020];/* cMPT - Memory Protection Table base physical address [63:32].
+ Entry size is 64 bytes.
+ Table must be aligned to its size. */
+/* -------------- */
+ pseudo_bit_t cmpt_base_adr_l[0x00020];/* cMPT - Memory Protection Table base physical address [31:0].
+ Entry size is 64 bytes.
+ Table must be aligned to its size. */
+/* -------------- */
+};
+
+/* Multicast Support Parameters #### michal - match PRM */
+
+struct hermonprm_multicastparam_st { /* Little Endian */
+ pseudo_bit_t mc_base_addr_h[0x00020];/* Base Address of the Multicast Table [63:32].
+ The base address must be aligned to the entry size.
+ Address may be set to 0xFFFFFFFF if multicast is not supported. */
+/* -------------- */
+ pseudo_bit_t mc_base_addr_l[0x00020];/* Base Address of the Multicast Table [31:0].
+ The base address must be aligned to the entry size.
+ Address may be set to 0xFFFFFFFF if multicast is not supported. */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00040];
+/* -------------- */
+ pseudo_bit_t log_mc_table_entry_sz[0x00005];/* Log2 of the Size of multicast group member (MGM) entry.
+ Must be greater than 5 (to allow CTRL and GID sections).
+ That implies the number of QPs per MC table entry. */
+ pseudo_bit_t reserved1[0x0000b];
+ pseudo_bit_t reserved2[0x00010];
+/* -------------- */
+ pseudo_bit_t log_mc_table_hash_sz[0x00005];/* Number of entries in multicast DGID hash table (must be power of 2)
+ INIT_HCA - the required number of entries
+ QUERY_HCA - the actual number of entries assigned by firmware (will be less than or equal to the amount required in INIT_HCA) */
+ pseudo_bit_t reserved3[0x0001b];
+/* -------------- */
+ pseudo_bit_t log_mc_table_sz[0x00005];/* Log2 of the overall number of MC entries in the MCG table (includes both hash and auxiliary tables) */
+ pseudo_bit_t reserved4[0x00013];
+ pseudo_bit_t mc_hash_fn[0x00003]; /* Multicast hash function
+ 0 - Default hash function
+ other - reserved */
+ pseudo_bit_t uc_group_steering[0x00001];
+ pseudo_bit_t reserved5[0x00004];
+/* -------------- */
+ pseudo_bit_t reserved6[0x00020];
+/* -------------- */
+};
+
+/* QPC/EEC/CQC/EQC/RDB Parameters #### michal - doesn't match PRM (field name are differs. see below) */
+
+struct hermonprm_qpcbaseaddr_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00080];
+/* -------------- */
+ pseudo_bit_t qpc_base_addr_h[0x00020];/* QPC Base Address [63:32]
+ Table must be aligned on its size */
+/* -------------- */
+ pseudo_bit_t log_num_of_qp[0x00005];/* Log base 2 of number of supported QPs */
+ pseudo_bit_t qpc_base_addr_l[0x0001b];/* QPC Base Address [31:7]
+ Table must be aligned on its size */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00040];
+/* -------------- */
+ pseudo_bit_t reserved2[0x00040];
+/* -------------- */
+ pseudo_bit_t srqc_base_addr_h[0x00020];/* SRQ Context Base Address [63:32]
+ Table must be aligned on its size
+ Address may be set to 0xFFFFFFFF if SRQ is not supported. */
+/* -------------- */
+ pseudo_bit_t log_num_of_srq[0x00005];/* Log base 2 of number of supported SRQs. */
+ pseudo_bit_t srqc_base_addr_l[0x0001b];/* SRQ Context Base Address [31:5]
+ Table must be aligned on its size
+ Address may be set to 0xFFFFFFFF if SRQ is not supported. */
+/* -------------- */
+ pseudo_bit_t cqc_base_addr_h[0x00020];/* CQC Base Address [63:32]
+ Table must be aligned on its size */
+/* -------------- */
+ pseudo_bit_t log_num_of_cq[0x00005];/* Log base 2 of number of supported CQs. */
+ pseudo_bit_t cqc_base_addr_l[0x0001b];/* CQC Base Address [31:6]
+ Table must be aligned on its size */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00040];
+/* -------------- */
+ pseudo_bit_t altc_base_addr_h[0x00020];/* AltC Base Address (altc_base_addr_h) [63:32]
+ Table has same number of entries as QPC table.
+ Table must be aligned to entry size. */
+/* -------------- */
+ pseudo_bit_t altc_base_addr_l[0x00020];/* AltC Base Address (altc_base_addr_l) [31:0]
+ Table has same number of entries as QPC table.
+ Table must be aligned to entry size. */
+/* -------------- */
+ pseudo_bit_t reserved4[0x00040];
+/* -------------- */
+ pseudo_bit_t auxc_base_addr_h[0x00020];
+/* -------------- */
+ pseudo_bit_t auxc_base_addr_l[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved5[0x00040];
+/* -------------- */
+ pseudo_bit_t eqc_base_addr_h[0x00020];/* EQC Base Address [63:32]
+ Address may be set to 0xFFFFFFFF if EQs are not supported.
+ Table must be aligned to entry size. */
+/* -------------- */
+ pseudo_bit_t log_num_of_eq[0x00005];/* Log base 2 of number of supported EQs.
+ Must be 6 or less in InfiniHost-III-EX. */
+ pseudo_bit_t eqc_base_addr_l[0x0001b];/* EQC Base Address [31:6]
+ Address may be set to 0xFFFFFFFF if EQs are not supported.
+ Table must be aligned to entry size. */
+/* -------------- */
+ pseudo_bit_t reserved6[0x00040];
+/* -------------- */
+ pseudo_bit_t rdmardc_base_addr_h[0x00020];/* rdmardc_base_addr_h: Base address of table that holds remote read and remote atomic requests [63:32]. */
+/* -------------- */
+ pseudo_bit_t log_num_rd[0x00003]; /* Log (base 2) of the maximum number of RdmaRdC entries per QP. This denotes the maximum number of outstanding reads/atomics as a responder. */
+ pseudo_bit_t reserved7[0x00002];
+ pseudo_bit_t rdmardc_base_addr_l[0x0001b];/* rdmardc_base_addr_l: Base address of table that holds remote read and remote atomic requests [31:0].
+ Table must be aligned to RDB entry size (32 bytes). */
+/* -------------- */
+ pseudo_bit_t reserved8[0x00040];
+/* -------------- */
+};
+
+/* Header_Log_Register */
+
+struct hermonprm_header_log_register_st { /* Little Endian */
+ pseudo_bit_t place_holder[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved0[0x00060];
+/* -------------- */
+};
+
+/* Performance Monitors */
+
+struct hermonprm_performance_monitors_st { /* Little Endian */
+ pseudo_bit_t e0[0x00001]; /* Enables counting of respective performance counter */
+ pseudo_bit_t e1[0x00001]; /* Enables counting of respective performance counter */
+ pseudo_bit_t e2[0x00001]; /* Enables counting of respective performance counter */
+ pseudo_bit_t reserved0[0x00001];
+ pseudo_bit_t r0[0x00001]; /* If written to as '1 - resets respective performance counter, if written to az '0 - no change to matter */
+ pseudo_bit_t r1[0x00001]; /* If written to as '1 - resets respective performance counter, if written to az '0 - no change to matter */
+ pseudo_bit_t r2[0x00001]; /* If written to as '1 - resets respective performance counter, if written to az '0 - no change to matter */
+ pseudo_bit_t reserved1[0x00001];
+ pseudo_bit_t i0[0x00001]; /* Interrupt enable on respective counter overflow. '1 - interrupt enabled, '0 - interrupt disabled. */
+ pseudo_bit_t i1[0x00001]; /* Interrupt enable on respective counter overflow. '1 - interrupt enabled, '0 - interrupt disabled. */
+ pseudo_bit_t i2[0x00001]; /* Interrupt enable on respective counter overflow. '1 - interrupt enabled, '0 - interrupt disabled. */
+ pseudo_bit_t reserved2[0x00001];
+ pseudo_bit_t f0[0x00001]; /* Overflow flag. If set, overflow occurred on respective counter. Cleared if written to as '1 */
+ pseudo_bit_t f1[0x00001]; /* Overflow flag. If set, overflow occurred on respective counter. Cleared if written to as '1 */
+ pseudo_bit_t f2[0x00001]; /* Overflow flag. If set, overflow occurred on respective counter. Cleared if written to as '1 */
+ pseudo_bit_t reserved3[0x00001];
+ pseudo_bit_t ev_cnt1[0x00005]; /* Specifies event to be counted by Event_counter1 See XXX for events' definition. */
+ pseudo_bit_t reserved4[0x00003];
+ pseudo_bit_t ev_cnt2[0x00005]; /* Specifies event to be counted by Event_counter2 See XXX for events' definition. */
+ pseudo_bit_t reserved5[0x00003];
+/* -------------- */
+ pseudo_bit_t clock_counter[0x00020];
+/* -------------- */
+ pseudo_bit_t event_counter1[0x00020];
+/* -------------- */
+ pseudo_bit_t event_counter2[0x00020];/* Read/write event counter, counting events specified by EvCntl and EvCnt2 fields repsectively. When the event counter reaches is maximum value of 0xFFFFFF, the next event will cause it to roll over to zero, set F1 or F2 bit respectively and generate interrupt by I1 I2 bit respectively. */
+/* -------------- */
+};
+
+/* MLX WQE segment format */
+
+struct hermonprm_wqe_segment_ctrl_mlx_st { /* Little Endian */
+ pseudo_bit_t opcode[0x00005]; /* must be 0xA = SEND */
+ pseudo_bit_t reserved0[0x0001a];
+ pseudo_bit_t owner[0x00001];
+/* -------------- */
+ pseudo_bit_t ds[0x00006]; /* Descriptor Size */
+ pseudo_bit_t reserved1[0x0001a];
+/* -------------- */
+ pseudo_bit_t fl[0x00001]; /* Force LoopBack */
+ pseudo_bit_t reserved2[0x00001];
+ pseudo_bit_t c[0x00002]; /* Create CQE (for "requested signalling" QP) */
+ pseudo_bit_t icrc[0x00001]; /* last dword of the packet: 0 - Calculate ICRC and put it instead of last dword. 1 - Leave last dword as is. */
+ pseudo_bit_t reserved3[0x00003];
+ pseudo_bit_t sl[0x00004];
+ pseudo_bit_t max_statrate[0x00004];
+ pseudo_bit_t slr[0x00001]; /* 0= take slid from port. 1= take slid from given headers */
+ pseudo_bit_t v15[0x00001]; /* Send packet over VL15 */
+ pseudo_bit_t reserved4[0x0000e];
+/* -------------- */
+ pseudo_bit_t reserved5[0x00010];
+ pseudo_bit_t rlid[0x00010]; /* Destination LID (must match given headers) */
+/* -------------- */
+};
+
+/* Send WQE segment format */
+
+struct hermonprm_send_wqe_segment_st { /* Little Endian */
+ struct hermonprm_wqe_segment_ctrl_send_st wqe_segment_ctrl_send;/* Send wqe segment ctrl */
+/* -------------- */
+ struct hermonprm_wqe_segment_rd_st wqe_segment_rd;/* Send wqe segment rd */
+/* -------------- */
+ struct hermonprm_wqe_segment_ud_st wqe_segment_ud;/* Send wqe segment ud */
+/* -------------- */
+ struct hermonprm_wqe_segment_bind_st wqe_segment_bind;/* Send wqe segment bind */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00180];
+/* -------------- */
+ struct hermonprm_wqe_segment_remote_address_st wqe_segment_remote_address;/* Send wqe segment remote address */
+/* -------------- */
+ struct hermonprm_wqe_segment_atomic_st wqe_segment_atomic;/* Send wqe segment atomic */
+/* -------------- */
+ struct hermonprm_fast_registration_segment_st fast_registration_segment;/* Fast Registration Segment */
+/* -------------- */
+ struct hermonprm_local_invalidate_segment_st local_invalidate_segment;/* local invalidate segment */
+/* -------------- */
+ struct hermonprm_wqe_segment_data_ptr_st wqe_segment_data_ptr;/* Send wqe segment data ptr */
+/* -------------- */
+ struct hermonprm_wqe_segment_data_inline_st wqe_segment_data_inline;/* Send wqe segment data inline */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00200];
+/* -------------- */
+};
+
+/* QP and EE Context Entry */
+
+struct hermonprm_queue_pair_ee_context_entry_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t reserved1[0x00001];
+ pseudo_bit_t reserved2[0x00002];
+ pseudo_bit_t pm_state[0x00002]; /* Path migration state (Migrated, Armed or Rearm)
+ 11-Migrated
+ 00-Armed
+ 01-Rearm
+ 10-Reserved
+ Should be set to 11 for UD QPs and for QPs which do not support APM */
+ pseudo_bit_t reserved3[0x00003];
+ pseudo_bit_t st[0x00004]; /* Transport Service Type: RC: 0, UC: 1, RD: 2, UD: 3, FCMND:4, FEXCH:5, SRC:6, MLX 7, Raw Eth 11 */
+ pseudo_bit_t reserved4[0x00008];
+ pseudo_bit_t state[0x00004]; /* QP/EE state:
+ 0 - RST
+ 1 - INIT
+ 2 - RTR
+ 3 - RTS
+ 4 - SQEr
+ 5 - SQD (Send Queue Drained)
+ 6 - ERR
+ 7 - Send Queue Draining
+ 8 - Reserved
+ 9 - Suspended
+ A- F - Reserved
+ (Valid for QUERY_QPEE and ERR2RST_QPEE commands only) */
+/* -------------- */
+ pseudo_bit_t pd[0x00018];
+ pseudo_bit_t reserved5[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved6[0x00004];
+ pseudo_bit_t rlky[0x00001]; /* When set this QP can use the Reserved L_Key */
+ pseudo_bit_t reserved7[0x00003];
+ pseudo_bit_t log_sq_stride[0x00003];/* Stride on the send queue. WQ entry is 16*(2^log_SQ_stride) bytes.
+ Stride must be equal or bigger then 64 bytes (minimum log_RQ_stride value allowed is 2). */
+ pseudo_bit_t log_sq_size[0x00004]; /* Log2 of the Number of WQEs in the Send Queue. */
+ pseudo_bit_t reserved8[0x00001];
+ pseudo_bit_t log_rq_stride[0x00003];/* Stride on the receive queue. WQ entry is 16*(2^log_RQ_stride) bytes.
+ Stride must be equal or bigger then 64 bytes (minimum log_RQ_stride value allowed is 2). */
+ pseudo_bit_t log_rq_size[0x00004]; /* Log2 of the Number of WQEs in the Receive Queue. */
+ pseudo_bit_t reserved9[0x00001];
+ pseudo_bit_t msg_max[0x00005]; /* Max message size allowed on the QP. Maximum message size is 2^msg_Max.
+ Must be equal to MTU for UD and MLX QPs. */
+ pseudo_bit_t mtu[0x00003]; /* MTU of the QP (Must be the same for both paths: primary and alternative):
+ 0x1 - 256 bytes
+ 0x2 - 512
+ 0x3 - 1024
+ 0x4 - 2048
+ other - reserved
+
+ Should be configured to 0x4 for UD and MLX QPs. */
+/* -------------- */
+ pseudo_bit_t usr_page[0x00018]; /* UAR number to ring doorbells for this QP (aliased to doorbell and Blue Flame pages) */
+ pseudo_bit_t reserved10[0x00008];
+/* -------------- */
+ pseudo_bit_t local_qpn_een[0x00018];/* Local QP/EE number Lower bits determine position of this record in QPC table, and - thus - constrained
+ This field is valid for QUERY and ERR2RST commands only. */
+ pseudo_bit_t reserved11[0x00008];
+/* -------------- */
+ pseudo_bit_t remote_qpn_een[0x00018];/* Remote QP/EE number */
+ pseudo_bit_t reserved12[0x00008];
+/* -------------- */
+ struct hermonprm_address_path_st primary_address_path;/* Primary address path for the QP/EE */
+/* -------------- */
+ struct hermonprm_address_path_st alternative_address_path;/* Alternate address path for the QP/EE */
+/* -------------- */
+ pseudo_bit_t reserved13[0x00003];
+ pseudo_bit_t reserved14[0x00001];
+ pseudo_bit_t reserved15[0x00001];
+ pseudo_bit_t cur_retry_cnt[0x00003];/* Current transport retry counter (QUERY_QPEE only).
+ The current transport retry counter can vary from retry_count down to 1, where 1 means that the last retry attempt is currently executing. */
+ pseudo_bit_t cur_rnr_retry[0x00003];/* Current RNR retry counter (QUERY_QPEE only).
+ The current RNR retry counter can vary from rnr_retry to 1, where 1 means that the last retry attempt is currently executing. */
+ pseudo_bit_t fre[0x00001]; /* Fast Registration Work Request Enabled. (Reserved for EE) */
+ pseudo_bit_t reserved16[0x00001];
+ pseudo_bit_t rnr_retry[0x00003];
+ pseudo_bit_t retry_count[0x00003]; /* Transport timeout Retry count */
+ pseudo_bit_t reserved17[0x00002];
+ pseudo_bit_t sra_max[0x00003]; /* Maximum number of outstanding RDMA-read/Atomic operations allowed in the send queue. Maximum number is 2^SRA_Max. Must be zero in EE context. */
+ pseudo_bit_t reserved18[0x00004];
+ pseudo_bit_t ack_req_freq[0x00004]; /* ACK required frequency. ACK required bit will be set in every 2^AckReqFreq packets at least. Not valid for RD QP. */
+/* -------------- */
+ pseudo_bit_t reserved19[0x00020];
+/* -------------- */
+ pseudo_bit_t next_send_psn[0x00018];/* Next PSN to be sent */
+ pseudo_bit_t reserved20[0x00008];
+/* -------------- */
+ pseudo_bit_t cqn_snd[0x00018]; /* CQ number completions from the send queue to be reported to. Not valid (reserved) in EE context. */
+ pseudo_bit_t reserved21[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved22[0x00040];
+/* -------------- */
+ pseudo_bit_t last_acked_psn[0x00018];/* The last acknowledged PSN for the requester (QUERY_QPEE only) */
+ pseudo_bit_t reserved23[0x00008];
+/* -------------- */
+ pseudo_bit_t ssn[0x00018]; /* Requester Send Sequence Number (QUERY_QPEE only) */
+ pseudo_bit_t reserved24[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved25[0x00004];
+ pseudo_bit_t ric[0x00001]; /* Invalid Credits.
+ 1 - place "Invalid Credits" to ACKs sent from this queue.
+ 0 - ACKs report the actual number of end to end credits on the connection.
+ Not valid (reserved) in EE context.
+ Must be set to 1 on QPs which are attached to SRQ. */
+ pseudo_bit_t reserved26[0x00001];
+ pseudo_bit_t page_offset[0x00006]; /* start address of wqes in first page (11:6), bits [5:0] reserved */
+ pseudo_bit_t reserved27[0x00001];
+ pseudo_bit_t rae[0x00001]; /* If set - Atomic operations enabled. on receive queue. Not valid (reserved) in EE context. */
+ pseudo_bit_t rwe[0x00001]; /* If set - RDMA - write enabled on receive queue. Not valid (reserved) in EE context. */
+ pseudo_bit_t rre[0x00001]; /* If set - RDMA - read enabled on receive queue. Not valid (reserved) in EE context. */
+ pseudo_bit_t reserved28[0x00005];
+ pseudo_bit_t rra_max[0x00003]; /* Maximum number of outstanding RDMA-read/Atomic operations allowed on receive queue is 2^RRA_Max.
+ Must be 0 for EE context. */
+ pseudo_bit_t physical_function[0x00008];
+/* -------------- */
+ pseudo_bit_t next_rcv_psn[0x00018]; /* Next (expected) PSN on receive */
+ pseudo_bit_t min_rnr_nak[0x00005]; /* Minimum RNR NAK timer value (TTTTT field encoding according to the IB spec Vol1 9.7.5.2.8).
+ Not valid (reserved) in EE context. */
+ pseudo_bit_t reserved30[0x00003];
+/* -------------- */
+ pseudo_bit_t srcd[0x00010]; /* Scalable Reliable Connection Domain. Valid for SRC transport service */
+ pseudo_bit_t reserved31[0x00010];
+/* -------------- */
+ pseudo_bit_t cqn_rcv[0x00018]; /* CQ number completions from receive queue to be reported to. Not valid (reserved) in EE context. */
+ pseudo_bit_t reserved32[0x00008];
+/* -------------- */
+ pseudo_bit_t db_record_addr_h[0x00020];/* QP DB Record physical address */
+/* -------------- */
+ pseudo_bit_t reserved33[0x00002];
+ pseudo_bit_t db_record_addr_l[0x0001e];/* QP DB Record physical address */
+/* -------------- */
+ pseudo_bit_t q_key[0x00020]; /* Q_Key to be validated against received datagrams.
+ On send datagrams, if Q_Key[31] specified in the WQE is set, then this Q_Key will be transmitted in the outgoing message.
+ Not valid (reserved) in EE context. */
+/* -------------- */
+ pseudo_bit_t srqn[0x00018]; /* SRQN - Shared Receive Queue Number - specifies the SRQ number from which the QP dequeues receive descriptors.
+ SRQN is valid only if SRQ bit is set. Not valid (reserved) in EE context. */
+ pseudo_bit_t srq[0x00001]; /* SRQ - Shared Receive Queue. If this bit is set, then the QP is associated with a SRQ. Not valid (reserved) in EE context. */
+ pseudo_bit_t reserved34[0x00007];
+/* -------------- */
+ pseudo_bit_t rmsn[0x00018]; /* Responder current message sequence number (QUERY_QPEE only) */
+ pseudo_bit_t reserved35[0x00008];
+/* -------------- */
+ pseudo_bit_t sq_wqe_counter[0x00010];/* A 16bits counter that is incremented for each WQE posted to the SQ.
+ Must be 0x0 in SQ initialization.
+ (QUERY_QPEE only). */
+ pseudo_bit_t rq_wqe_counter[0x00010];/* A 16bits counter that is incremented for each WQE posted to the RQ.
+ Must be 0x0 in RQ initialization.
+ (QUERY_QPEE only). */
+/* -------------- */
+ pseudo_bit_t reserved36[0x00040];
+/* -------------- */
+ pseudo_bit_t rmc_parent_qpn[0x00018];/* reliable multicast parent queue number */
+ pseudo_bit_t hs[0x00001]; /* Header Separation. If set, the byte count of the first scatter entry will be ignored. The buffer specified by the first scatter entry will contain packet headers (up to TCP). CQE will report number of bytes scattered to the first scatter entry. Intended for use on IPoverIB on UD QP or Raw Ethernet QP. */
+ pseudo_bit_t is[0x00001]; /* when set - inline scatter is enabled for this RQ */
+ pseudo_bit_t reserved37[0x00001];
+ pseudo_bit_t rme[0x00002]; /* Reliable Multicast
+ 00 - disabled
+ 01 - parent QP (requester)
+ 10 - child QP (requester)
+ 11 - responder QP
+ Note that Reliable Multicast is a preliminary definition which can be subject to change. */
+ pseudo_bit_t reserved38[0x00002];
+ pseudo_bit_t mkey_rmp[0x00001]; /* If set, MKey used to access TPT for incoming RDMA-write request is calculated by adding MKey from the packet to base_MKey field in the QPC. Can be set only for QPs that are not target for RDMA-read request. */
+/* -------------- */
+ pseudo_bit_t base_mkey[0x00018]; /* Base Mkey bits [31:8]. Lower 8 bits must be zero. */
+ pseudo_bit_t num_rmc_peers[0x00008];/* Number of remote peers in Reliable Multicast group */
+/* -------------- */
+ pseudo_bit_t mtt_base_addr_h[0x00008];/* MTT Base Address [39:32] in ICM relative to INIT_HCA.mtt_base_addr */
+ pseudo_bit_t reserved39[0x00010];
+ pseudo_bit_t log2_page_size[0x00006];/* Log (base 2) of MTT page size in units of 4KByte */
+ pseudo_bit_t reserved40[0x00002];
+/* -------------- */
+ pseudo_bit_t reserved41[0x00003];
+ pseudo_bit_t mtt_base_addr_l[0x0001d];/* MTT Base Address [31:3] in ICM relative to INIT_HCA.mtt_base_addr */
+/* -------------- */
+ pseudo_bit_t vft_lan[0x0000c];
+ pseudo_bit_t vft_prio[0x00003]; /* The Priority filed in the VFT header for FCP */
+ pseudo_bit_t reserved42[0x00001];
+ pseudo_bit_t cs_ctl[0x00009]; /* The Priority filed in the VFT header for FCP */
+ pseudo_bit_t reserved43[0x00006];
+ pseudo_bit_t ve[0x00001]; /* Should we add/check the VFT header */
+/* -------------- */
+ pseudo_bit_t exch_base[0x00010]; /* For init QP only - The base exchanges */
+ pseudo_bit_t reserved44[0x00008];
+ pseudo_bit_t exch_size[0x00004]; /* For CMMD QP only - The size (from base) exchanges is 2exchanges_size */
+ pseudo_bit_t reserved45[0x00003];
+ pseudo_bit_t fc[0x00001]; /* When set it mean that this QP is used for FIBRE CHANNEL. */
+/* -------------- */
+ pseudo_bit_t remote_id[0x00018]; /* Peer NX port ID */
+ pseudo_bit_t reserved46[0x00008];
+/* -------------- */
+ pseudo_bit_t fcp_mtu[0x0000a]; /* In 4*Bytes units. The MTU Size */
+ pseudo_bit_t reserved47[0x00006];
+ pseudo_bit_t my_id_indx[0x00008]; /* Index to My NX port ID table */
+ pseudo_bit_t vft_hop_count[0x00008];/* HopCnt value for the VFT header */
+/* -------------- */
+ pseudo_bit_t reserved48[0x000c0];
+/* -------------- */
+};
+
+/* */
+
+struct hermonprm_mcg_qp_dw_st { /* Little Endian */
+ pseudo_bit_t qpn[0x00018];
+ pseudo_bit_t reserved0[0x00006];
+ pseudo_bit_t blck_lb[0x00001];
+ pseudo_bit_t reserved1[0x00001];
+/* -------------- */
+};
+
+/* Clear Interrupt [63:0] #### michal - match to PRM */
+
+struct hermonprm_clr_int_st { /* Little Endian */
+ pseudo_bit_t clr_int_h[0x00020]; /* Clear Interrupt [63:32]
+ Write transactions to this register will clear (de-assert) the virtual interrupt output pins of InfiniHost-III-EX. The value to be written in this register is obtained by executing QUERY_ADAPTER command on command interface after system boot.
+ This register is write-only. Reading from this register will cause undefined result
+ */
+/* -------------- */
+ pseudo_bit_t clr_int_l[0x00020]; /* Clear Interrupt [31:0]
+ Write transactions to this register will clear (de-assert) the virtual interrupt output pins of InfiniHost-III-EX. The value to be written in this register is obtained by executing QUERY_ADAPTER command on command interface after system boot.
+ This register is write-only. Reading from this register will cause undefined result */
+/* -------------- */
+};
+
+/* EQ Set CI DBs Table */
+
+struct hermonprm_eq_set_ci_table_st { /* Little Endian */
+ pseudo_bit_t eq0_set_ci[0x00020]; /* EQ0_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+ pseudo_bit_t eq1_set_ci[0x00020]; /* EQ1_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00020];
+/* -------------- */
+ pseudo_bit_t eq2_set_ci[0x00020]; /* EQ2_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00020];
+/* -------------- */
+ pseudo_bit_t eq3_set_ci[0x00020]; /* EQ3_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00020];
+/* -------------- */
+ pseudo_bit_t eq4_set_ci[0x00020]; /* EQ4_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved4[0x00020];
+/* -------------- */
+ pseudo_bit_t eq5_set_ci[0x00020]; /* EQ5_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved5[0x00020];
+/* -------------- */
+ pseudo_bit_t eq6_set_ci[0x00020]; /* EQ6_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved6[0x00020];
+/* -------------- */
+ pseudo_bit_t eq7_set_ci[0x00020]; /* EQ7_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved7[0x00020];
+/* -------------- */
+ pseudo_bit_t eq8_set_ci[0x00020]; /* EQ8_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved8[0x00020];
+/* -------------- */
+ pseudo_bit_t eq9_set_ci[0x00020]; /* EQ9_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved9[0x00020];
+/* -------------- */
+ pseudo_bit_t eq10_set_ci[0x00020]; /* EQ10_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved10[0x00020];
+/* -------------- */
+ pseudo_bit_t eq11_set_ci[0x00020]; /* EQ11_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved11[0x00020];
+/* -------------- */
+ pseudo_bit_t eq12_set_ci[0x00020]; /* EQ12_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved12[0x00020];
+/* -------------- */
+ pseudo_bit_t eq13_set_ci[0x00020]; /* EQ13_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved13[0x00020];
+/* -------------- */
+ pseudo_bit_t eq14_set_ci[0x00020]; /* EQ14_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved14[0x00020];
+/* -------------- */
+ pseudo_bit_t eq15_set_ci[0x00020]; /* EQ15_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved15[0x00020];
+/* -------------- */
+ pseudo_bit_t eq16_set_ci[0x00020]; /* EQ16_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved16[0x00020];
+/* -------------- */
+ pseudo_bit_t eq17_set_ci[0x00020]; /* EQ17_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved17[0x00020];
+/* -------------- */
+ pseudo_bit_t eq18_set_ci[0x00020]; /* EQ18_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved18[0x00020];
+/* -------------- */
+ pseudo_bit_t eq19_set_ci[0x00020]; /* EQ19_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved19[0x00020];
+/* -------------- */
+ pseudo_bit_t eq20_set_ci[0x00020]; /* EQ20_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved20[0x00020];
+/* -------------- */
+ pseudo_bit_t eq21_set_ci[0x00020]; /* EQ21_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved21[0x00020];
+/* -------------- */
+ pseudo_bit_t eq22_set_ci[0x00020]; /* EQ22_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved22[0x00020];
+/* -------------- */
+ pseudo_bit_t eq23_set_ci[0x00020]; /* EQ23_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved23[0x00020];
+/* -------------- */
+ pseudo_bit_t eq24_set_ci[0x00020]; /* EQ24_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved24[0x00020];
+/* -------------- */
+ pseudo_bit_t eq25_set_ci[0x00020]; /* EQ25_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved25[0x00020];
+/* -------------- */
+ pseudo_bit_t eq26_set_ci[0x00020]; /* EQ26_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved26[0x00020];
+/* -------------- */
+ pseudo_bit_t eq27_set_ci[0x00020]; /* EQ27_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved27[0x00020];
+/* -------------- */
+ pseudo_bit_t eq28_set_ci[0x00020]; /* EQ28_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved28[0x00020];
+/* -------------- */
+ pseudo_bit_t eq29_set_ci[0x00020]; /* EQ29_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved29[0x00020];
+/* -------------- */
+ pseudo_bit_t eq30_set_ci[0x00020]; /* EQ30_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved30[0x00020];
+/* -------------- */
+ pseudo_bit_t eq31_set_ci[0x00020]; /* EQ31_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved31[0x00020];
+/* -------------- */
+ pseudo_bit_t eq32_set_ci[0x00020]; /* EQ32_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved32[0x00020];
+/* -------------- */
+ pseudo_bit_t eq33_set_ci[0x00020]; /* EQ33_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved33[0x00020];
+/* -------------- */
+ pseudo_bit_t eq34_set_ci[0x00020]; /* EQ34_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved34[0x00020];
+/* -------------- */
+ pseudo_bit_t eq35_set_ci[0x00020]; /* EQ35_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved35[0x00020];
+/* -------------- */
+ pseudo_bit_t eq36_set_ci[0x00020]; /* EQ36_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved36[0x00020];
+/* -------------- */
+ pseudo_bit_t eq37_set_ci[0x00020]; /* EQ37_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved37[0x00020];
+/* -------------- */
+ pseudo_bit_t eq38_set_ci[0x00020]; /* EQ38_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved38[0x00020];
+/* -------------- */
+ pseudo_bit_t eq39_set_ci[0x00020]; /* EQ39_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved39[0x00020];
+/* -------------- */
+ pseudo_bit_t eq40_set_ci[0x00020]; /* EQ40_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved40[0x00020];
+/* -------------- */
+ pseudo_bit_t eq41_set_ci[0x00020]; /* EQ41_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved41[0x00020];
+/* -------------- */
+ pseudo_bit_t eq42_set_ci[0x00020]; /* EQ42_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved42[0x00020];
+/* -------------- */
+ pseudo_bit_t eq43_set_ci[0x00020]; /* EQ43_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved43[0x00020];
+/* -------------- */
+ pseudo_bit_t eq44_set_ci[0x00020]; /* EQ44_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved44[0x00020];
+/* -------------- */
+ pseudo_bit_t eq45_set_ci[0x00020]; /* EQ45_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved45[0x00020];
+/* -------------- */
+ pseudo_bit_t eq46_set_ci[0x00020]; /* EQ46_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved46[0x00020];
+/* -------------- */
+ pseudo_bit_t eq47_set_ci[0x00020]; /* EQ47_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved47[0x00020];
+/* -------------- */
+ pseudo_bit_t eq48_set_ci[0x00020]; /* EQ48_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved48[0x00020];
+/* -------------- */
+ pseudo_bit_t eq49_set_ci[0x00020]; /* EQ49_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved49[0x00020];
+/* -------------- */
+ pseudo_bit_t eq50_set_ci[0x00020]; /* EQ50_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved50[0x00020];
+/* -------------- */
+ pseudo_bit_t eq51_set_ci[0x00020]; /* EQ51_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved51[0x00020];
+/* -------------- */
+ pseudo_bit_t eq52_set_ci[0x00020]; /* EQ52_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved52[0x00020];
+/* -------------- */
+ pseudo_bit_t eq53_set_ci[0x00020]; /* EQ53_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved53[0x00020];
+/* -------------- */
+ pseudo_bit_t eq54_set_ci[0x00020]; /* EQ54_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved54[0x00020];
+/* -------------- */
+ pseudo_bit_t eq55_set_ci[0x00020]; /* EQ55_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved55[0x00020];
+/* -------------- */
+ pseudo_bit_t eq56_set_ci[0x00020]; /* EQ56_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved56[0x00020];
+/* -------------- */
+ pseudo_bit_t eq57_set_ci[0x00020]; /* EQ57_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved57[0x00020];
+/* -------------- */
+ pseudo_bit_t eq58_set_ci[0x00020]; /* EQ58_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved58[0x00020];
+/* -------------- */
+ pseudo_bit_t eq59_set_ci[0x00020]; /* EQ59_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved59[0x00020];
+/* -------------- */
+ pseudo_bit_t eq60_set_ci[0x00020]; /* EQ60_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved60[0x00020];
+/* -------------- */
+ pseudo_bit_t eq61_set_ci[0x00020]; /* EQ61_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved61[0x00020];
+/* -------------- */
+ pseudo_bit_t eq62_set_ci[0x00020]; /* EQ62_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved62[0x00020];
+/* -------------- */
+ pseudo_bit_t eq63_set_ci[0x00020]; /* EQ63_Set_CI */
+/* -------------- */
+ pseudo_bit_t reserved63[0x00020];
+/* -------------- */
+};
+
+/* InfiniHost-III-EX Configuration Registers #### michal - match to PRM */
+
+struct hermonprm_configuration_registers_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x403400];
+/* -------------- */
+ struct hermonprm_hca_command_register_st hca_command_interface_register;/* HCA Command Register */
+/* -------------- */
+ pseudo_bit_t reserved1[0x3fcb20];
+/* -------------- */
+};
+
+/* QP_DB_Record ### michal = gdror fixed */
+
+struct hermonprm_qp_db_record_st { /* Little Endian */
+ pseudo_bit_t receive_wqe_counter[0x00010];/* Modulo-64K counter of WQEs posted to the QP since its creation. Should be initialized to zero. */
+ pseudo_bit_t reserved0[0x00010];
+/* -------------- */
+};
+
+/* CQ_ARM_DB_Record */
+
+struct hermonprm_cq_arm_db_record_st { /* Little Endian */
+ pseudo_bit_t counter[0x00020]; /* CQ counter for the arming request */
+/* -------------- */
+ pseudo_bit_t cmd[0x00003]; /* 0x0 - No command
+ 0x1 - Request notification for next Solicited completion event. Counter filed specifies the current CQ Consumer Counter.
+ 0x2 - Request notification for next Solicited or Unsolicited completion event. Counter filed specifies the current CQ Consumer counter.
+ 0x3 - Request notification for multiple completions (Arm-N). Counter filed specifies the value of the CQ Index that when reached by HW (i.e. HW generates a CQE into this Index) Event will be generated
+ Other - Reserved */
+ pseudo_bit_t cmd_sn[0x00002]; /* Command Sequence Number - See Table 35, "CQ Doorbell Layout" for definition of this filed */
+ pseudo_bit_t res[0x00003]; /* Must be 0x2 */
+ pseudo_bit_t cq_number[0x00018]; /* CQ number */
+/* -------------- */
+};
+
+/* CQ_CI_DB_Record */
+
+struct hermonprm_cq_ci_db_record_st { /* Little Endian */
+ pseudo_bit_t counter[0x00020]; /* CQ counter */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00005];
+ pseudo_bit_t res[0x00003]; /* Must be 0x1 */
+ pseudo_bit_t cq_number[0x00018]; /* CQ number */
+/* -------------- */
+};
+
+/* Virtual_Physical_Mapping */
+
+struct hermonprm_virtual_physical_mapping_st { /* Little Endian */
+ pseudo_bit_t va_h[0x00020]; /* Virtual Address[63:32]. Valid only for MAP_ICM command. */
+/* -------------- */
+ pseudo_bit_t reserved0[0x0000c];
+ pseudo_bit_t va_l[0x00014]; /* Virtual Address[31:12]. Valid only for MAP_ICM command. */
+/* -------------- */
+ pseudo_bit_t pa_h[0x00020]; /* Physical Address[63:32] */
+/* -------------- */
+ pseudo_bit_t log2size[0x00006]; /* Log2 of the size in 4KB pages of the physical and virtual contiguous memory that starts at PA_L/H and VA_L/H */
+ pseudo_bit_t reserved1[0x00006];
+ pseudo_bit_t pa_l[0x00014]; /* Physical Address[31:12] */
+/* -------------- */
+};
+
+/* MOD_STAT_CFG #### michal - gdror fix */
+
+struct hermonprm_mod_stat_cfg_st { /* Little Endian */
+ pseudo_bit_t log_pg_sz[0x00008];
+ pseudo_bit_t log_pg_sz_m[0x00001];
+ pseudo_bit_t reserved0[0x00005];
+ pseudo_bit_t dife[0x00001];
+ pseudo_bit_t dife_m[0x00001];
+ pseudo_bit_t rx_options[0x00004]; /* number of RX options to sweep when doing SerDes parameters AutoNegotiation. */
+ pseudo_bit_t reserved1[0x00003];
+ pseudo_bit_t rx_options_m[0x00001]; /* Modify rx_options */
+ pseudo_bit_t tx_options[0x00004]; /* number of TX options to sweep when doing SerDes parameters AutoNegotiation. */
+ pseudo_bit_t reserved2[0x00003];
+ pseudo_bit_t tx_options_m[0x00001]; /* Modify tx_options */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00010];
+ pseudo_bit_t qdr_rx_options[0x00004];
+ pseudo_bit_t reserved4[0x00003];
+ pseudo_bit_t qdr_rx_options_m[0x00001];
+ pseudo_bit_t qdr_tx_options[0x00004];
+ pseudo_bit_t reserved5[0x00003];
+ pseudo_bit_t qdr_tx_options_m[0x00001];
+/* -------------- */
+ pseudo_bit_t reserved6[0x00020];
+/* -------------- */
+ pseudo_bit_t lid[0x00010]; /* default LID */
+ pseudo_bit_t lid_m[0x00001]; /* Modify default LID */
+ pseudo_bit_t reserved7[0x00003];
+ pseudo_bit_t port_en[0x00001]; /* enable port (E_Key) */
+ pseudo_bit_t port_en_m[0x00001]; /* Modify port_en */
+ pseudo_bit_t reserved8[0x00002];
+ pseudo_bit_t port_pause_mode[0x00002];
+ pseudo_bit_t reserved9[0x00001];
+ pseudo_bit_t port_pause_mode_m[0x00001];
+ pseudo_bit_t reserved10[0x00004];
+/* -------------- */
+ pseudo_bit_t reserved11[0x0001f];
+ pseudo_bit_t guid_hi_m[0x00001]; /* Modify guid_hi */
+/* -------------- */
+ pseudo_bit_t guid_hi[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved12[0x0001f];
+ pseudo_bit_t guid_lo_m[0x00001]; /* Modify guid_lo */
+/* -------------- */
+ pseudo_bit_t guid_lo[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved13[0x0001f];
+ pseudo_bit_t nodeguid_hi_m[0x00001];
+/* -------------- */
+ pseudo_bit_t nodeguid_hi[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved14[0x0001f];
+ pseudo_bit_t nodeguid_lo_m[0x00001];
+/* -------------- */
+ pseudo_bit_t nodeguid_lo[0x00020];
+/* -------------- */
+ pseudo_bit_t ob_preemp_pre[0x00005];
+ pseudo_bit_t reserved15[0x00003];
+ pseudo_bit_t ob_preemp_post[0x00005];
+ pseudo_bit_t reserved16[0x00003];
+ pseudo_bit_t ob_preemp_main[0x00005];
+ pseudo_bit_t reserved17[0x00003];
+ pseudo_bit_t ob_preemp[0x00005];
+ pseudo_bit_t reserved18[0x00002];
+ pseudo_bit_t serdes_m[0x00001];
+/* -------------- */
+ pseudo_bit_t inbuf_ind_en[0x00003];
+ pseudo_bit_t reserved19[0x00001];
+ pseudo_bit_t sd_main[0x00004];
+ pseudo_bit_t reserved20[0x00004];
+ pseudo_bit_t sd_equal[0x00004];
+ pseudo_bit_t reserved21[0x00004];
+ pseudo_bit_t sd_mux_main[0x00002];
+ pseudo_bit_t reserved22[0x00002];
+ pseudo_bit_t mux_eq[0x00002];
+ pseudo_bit_t reserved23[0x00002];
+ pseudo_bit_t sigdet_th[0x00003];
+ pseudo_bit_t reserved24[0x00001];
+/* -------------- */
+ pseudo_bit_t reserved25[0x00040];
+/* -------------- */
+ pseudo_bit_t port_protocol[0x00008];
+ pseudo_bit_t port_dual[0x00001];
+ pseudo_bit_t reserved26[0x00006];
+ pseudo_bit_t port_protocol_m[0x00001];
+ pseudo_bit_t num_port[0x00008];
+ pseudo_bit_t reserved27[0x00008];
+/* -------------- */
+ pseudo_bit_t port_protocol_vpi[0x00008];
+ pseudo_bit_t reserved28[0x00018];
+/* -------------- */
+ pseudo_bit_t reserved29[0x00180];
+/* -------------- */
+ pseudo_bit_t fw_rev_major[0x00010];
+ pseudo_bit_t reserved30[0x0000f];
+ pseudo_bit_t fw_rev_support[0x00001];
+/* -------------- */
+ pseudo_bit_t fw_rev_minor[0x00010];
+ pseudo_bit_t fw_rev_subminor[0x00010];
+/* -------------- */
+ pseudo_bit_t cmd_interface_rev[0x00010];
+ pseudo_bit_t reserved31[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved32[0x00060];
+/* -------------- */
+ pseudo_bit_t mac_high[0x00010];
+ pseudo_bit_t reserved33[0x0000f];
+ pseudo_bit_t mac_m[0x00001];
+/* -------------- */
+ pseudo_bit_t mac_low[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved34[0x00010];
+ pseudo_bit_t num_veps[0x00008];
+ pseudo_bit_t num_vep_groups[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved35[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved36[0x00018];
+ pseudo_bit_t outer_vlan_en[0x00001];
+ pseudo_bit_t reserved37[0x00002];
+ pseudo_bit_t outer_vlan_en_m[0x00001];
+ pseudo_bit_t port_net_boot[0x00001];
+ pseudo_bit_t reserved38[0x00002];
+ pseudo_bit_t port_net_boot_m[0x00001];
+/* -------------- */
+ pseudo_bit_t reserved39[0x00060];
+/* -------------- */
+ pseudo_bit_t port_eth_mode_capability[0x0001f];
+ pseudo_bit_t reserved40[0x00001];
+/* -------------- */
+ pseudo_bit_t port_eth_mode_enabled[0x0001f];
+ pseudo_bit_t port_eth_mod_m[0x00001];
+/* -------------- */
+ pseudo_bit_t port_eth_mode_current[0x0001f];
+ pseudo_bit_t reserved41[0x00001];
+/* -------------- */
+ pseudo_bit_t reserved42[0x00220];
+};
+
+/* SRQ Context */
+
+struct hermonprm_srq_context_st { /* Little Endian */
+ pseudo_bit_t srqn[0x00018]; /* SRQ number */
+ pseudo_bit_t log_srq_size[0x00004]; /* Log2 of the Number of WQEs in the Receive Queue.
+ Maximum value is 0x10, i.e. 16M WQEs. */
+ pseudo_bit_t state[0x00004]; /* SRQ State:
+ 1111 - SW Ownership
+ 0000 - HW Ownership
+ 0001 - Error
+ Valid only on QUERY_SRQ and HW2SW_SRQ commands. */
+/* -------------- */
+ pseudo_bit_t src_domain[0x00010]; /* The Scalable RC Domain. Messages coming to receive ports specifying this SRQ as receive queue will be served only if SRC_Domain of the SRQ matches SRC_Domain of the transport QP of this message. */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t log_srq_stride[0x00003];/* Stride (max WQE size) on the receive queue. WQ entry is 16*(2^log_RQ_stride) bytes. */
+ pseudo_bit_t reserved1[0x00005];
+/* -------------- */
+ pseudo_bit_t cqn[0x00018]; /* Completion Queue to report SRC messages directed to this SRQ. */
+ pseudo_bit_t page_offset[0x00006]; /* The offset of the first WQE from the beginning of 4Kbyte page (Figure 52,“Work Queue Buffer Structure”) */
+ pseudo_bit_t reserved2[0x00002];
+/* -------------- */
+ pseudo_bit_t reserved3[0x00020];
+/* -------------- */
+ pseudo_bit_t mtt_base_addr_h[0x00008];/* MTT Base Address [39:32] in ICM relative to INIT_HCA.mtt_base_addr */
+ pseudo_bit_t reserved4[0x00010];
+ pseudo_bit_t log2_page_size[0x00006];/* Log (base 2) of MTT page size in units of 4KByte */
+ pseudo_bit_t reserved5[0x00002];
+/* -------------- */
+ pseudo_bit_t reserved6[0x00003];
+ pseudo_bit_t mtt_base_addr_l[0x0001d];/* MTT Base Address [31:3] in ICM relative to INIT_HCA.mtt_base_addr */
+/* -------------- */
+ pseudo_bit_t pd[0x00018]; /* SRQ protection domain */
+ pseudo_bit_t reserved7[0x00008];
+/* -------------- */
+ pseudo_bit_t wqe_cnt[0x00010]; /* WQE count on the SRQ. Valid only upon QUERY_SRQ and HW2SW_SRQ commands. */
+ pseudo_bit_t lwm[0x00010]; /* Limit Water Mark - if the LWM is not zero, and the wqe_cnt drops below LWM when a WQE is dequeued from the SRQ, then an SRQ limit event is fired and the LWM is set to zero. Valid only upon QUERY_SRQ and HW2SW_SRQ commands. */
+/* -------------- */
+ pseudo_bit_t srq_wqe_counter[0x00010];/* A 16-bit counter incremented for each WQE posted to the SRQ. Must be 0x0 in SRQ initialization. Valid only upon the QUERY_SRQ command. */
+ pseudo_bit_t reserved8[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved9[0x00020];
+/* -------------- */
+ pseudo_bit_t db_record_addr_h[0x00020];/* SRQ DB Record physical address [63:32] */
+/* -------------- */
+ pseudo_bit_t reserved10[0x00002];
+ pseudo_bit_t db_record_addr_l[0x0001e];/* SRQ DB Record physical address [31:2] */
+/* -------------- */
+};
+
+/* PBL */
+
+struct hermonprm_pbl_st { /* Little Endian */
+ pseudo_bit_t mtt_0_h[0x00020]; /* First MTT[63:32] */
+/* -------------- */
+ pseudo_bit_t mtt_0_l[0x00020]; /* First MTT[31:0] */
+/* -------------- */
+ pseudo_bit_t mtt_1_h[0x00020]; /* Second MTT[63:32] */
+/* -------------- */
+ pseudo_bit_t mtt_1_l[0x00020]; /* Second MTT[31:0] */
+/* -------------- */
+ pseudo_bit_t mtt_2_h[0x00020]; /* Third MTT[63:32] */
+/* -------------- */
+ pseudo_bit_t mtt_2_l[0x00020]; /* Third MTT[31:0] */
+/* -------------- */
+ pseudo_bit_t mtt_3_h[0x00020]; /* Fourth MTT[63:32] */
+/* -------------- */
+ pseudo_bit_t mtt_3_l[0x00020]; /* Fourth MTT[31:0] */
+/* -------------- */
+};
+
+/* Performance Counters #### michal - gdror fixed */
+
+struct hermonprm_performance_counters_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00080];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00080];
+/* -------------- */
+ pseudo_bit_t reserved2[0x00080];
+/* -------------- */
+ pseudo_bit_t reserved3[0x00060];
+/* -------------- */
+ pseudo_bit_t reserved4[0x00620];
+/* -------------- */
+};
+
+/* Transport and CI Error Counters */
+
+struct hermonprm_transport_and_ci_error_counters_st { /* Little Endian */
+ pseudo_bit_t rq_num_lle[0x00020]; /* Responder - number of local length errors */
+/* -------------- */
+ pseudo_bit_t sq_num_lle[0x00020]; /* Requester - number of local length errors */
+/* -------------- */
+ pseudo_bit_t rq_num_lqpoe[0x00020]; /* Responder - number local QP operation error */
+/* -------------- */
+ pseudo_bit_t sq_num_lqpoe[0x00020]; /* Requester - number local QP operation error */
+/* -------------- */
+ pseudo_bit_t rq_num_leeoe[0x00020]; /* Responder - number local EE operation error */
+/* -------------- */
+ pseudo_bit_t sq_num_leeoe[0x00020]; /* Requester - number local EE operation error */
+/* -------------- */
+ pseudo_bit_t rq_num_lpe[0x00020]; /* Responder - number of local protection errors */
+/* -------------- */
+ pseudo_bit_t sq_num_lpe[0x00020]; /* Requester - number of local protection errors */
+/* -------------- */
+ pseudo_bit_t rq_num_wrfe[0x00020]; /* Responder - number of CQEs with error.
+ Incremented each time a CQE with error is generated */
+/* -------------- */
+ pseudo_bit_t sq_num_wrfe[0x00020]; /* Requester - number of CQEs with error.
+ Incremented each time a CQE with error is generated */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+ pseudo_bit_t sq_num_mwbe[0x00020]; /* Requester - number of memory window bind errors */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00020];
+/* -------------- */
+ pseudo_bit_t sq_num_bre[0x00020]; /* Requester - number of bad response errors */
+/* -------------- */
+ pseudo_bit_t rq_num_lae[0x00020]; /* Responder - number of local access errors */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00040];
+/* -------------- */
+ pseudo_bit_t sq_num_rire[0x00020]; /* Requester - number of remote invalid request errors
+ NAK-Invalid Request on:
+ 1. Unsupported OpCode: Responder detected an unsupported OpCode.
+ 2. Unexpected OpCode: Responder detected an error in the sequence of OpCodes, such
+ as a missing "Last" packet.
+ Note: there is no PSN error, thus this does not indicate a dropped packet. */
+/* -------------- */
+ pseudo_bit_t rq_num_rire[0x00020]; /* Responder - number of remote invalid request errors.
+ NAK may or may not be sent.
+ 1. QP Async Affiliated Error: Unsupported or Reserved OpCode (RC,RD only):
+ Inbound request OpCode was either reserved, or was for a function not supported by this
+ QP. (E.g. RDMA or ATOMIC on QP not set up for this).
+ 2. Misaligned ATOMIC: VA does not point to an aligned address on an atomic opera-tion.
+ 3. Too many RDMA READ or ATOMIC Requests: There were more requests received
+ and not ACKed than allowed for the connection.
+ 4. Out of Sequence OpCode, current packet is "First" or "Only": The Responder
+ detected an error in the sequence of OpCodes; a missing "Last" packet
+ 5. Out of Sequence OpCode, current packet is not "First" or "Only": The Responder
+ detected an error in the sequence of OpCodes; a missing "First" packet
+ 6. Local Length Error: Inbound "Send" request message exceeded the responder.s avail-able
+ buffer space.
+ 7. Length error: RDMA WRITE request message contained too much or too little pay-load
+ data compared to the DMA length advertised in the first or only packet.
+ 8. Length error: Payload length was not consistent with the opcode:
+ a: 0 byte <= "only" <= PMTU bytes
+ b: ("first" or "middle") == PMTU bytes
+ c: 1byte <= "last" <= PMTU bytes
+ 9. Length error: Inbound message exceeded the size supported by the CA port. */
+/* -------------- */
+ pseudo_bit_t sq_num_rae[0x00020]; /* Requester - number of remote access errors.
+ NAK-Remote Access Error on:
+ R_Key Violation: Responder detected an invalid R_Key while executing an RDMA
+ Request. */
+/* -------------- */
+ pseudo_bit_t rq_num_rae[0x00020]; /* Responder - number of remote access errors.
+ R_Key Violation Responder detected an R_Key violation while executing an RDMA
+ request.
+ NAK may or may not be sent. */
+/* -------------- */
+ pseudo_bit_t sq_num_roe[0x00020]; /* Requester - number of remote operation errors.
+ NAK-Remote Operation Error on:
+ Remote Operation Error: Responder encountered an error, (local to the responder),
+ which prevented it from completing the request. */
+/* -------------- */
+ pseudo_bit_t rq_num_roe[0x00020]; /* Responder - number of remote operation errors.
+ NAK-Remote Operation Error on:
+ 1. Malformed WQE: Responder detected a malformed Receive Queue WQE while pro-cessing
+ the packet.
+ 2. Remote Operation Error: Responder encountered an error, (local to the responder),
+ which prevented it from completing the request. */
+/* -------------- */
+ pseudo_bit_t sq_num_tree[0x00020]; /* Requester - number of transport retries exceeded errors */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00020];
+/* -------------- */
+ pseudo_bit_t sq_num_rree[0x00020]; /* Requester - number of RNR nak retries exceeded errors */
+/* -------------- */
+ pseudo_bit_t rq_num_rnr[0x00020]; /* Responder - the number of RNR Naks sent */
+/* -------------- */
+ pseudo_bit_t sq_num_rnr[0x00020]; /* Requester - the number of RNR Naks received */
+/* -------------- */
+ pseudo_bit_t reserved4[0x00040];
+/* -------------- */
+ pseudo_bit_t reserved5[0x00020];
+/* -------------- */
+ pseudo_bit_t sq_num_rabrte[0x00020];/* Requester - number of remote aborted errors */
+/* -------------- */
+ pseudo_bit_t reserved6[0x00020];
+/* -------------- */
+ pseudo_bit_t sq_num_ieecne[0x00020];/* Requester - number of invalid EE context number errors */
+/* -------------- */
+ pseudo_bit_t reserved7[0x00020];
+/* -------------- */
+ pseudo_bit_t sq_num_ieecse[0x00020];/* Requester - invalid EE context state errors */
+/* -------------- */
+ pseudo_bit_t reserved8[0x00380];
+/* -------------- */
+ pseudo_bit_t rq_num_oos[0x00020]; /* Responder - number of out of sequence requests received */
+/* -------------- */
+ pseudo_bit_t sq_num_oos[0x00020]; /* Requester - number of out of sequence Naks received */
+/* -------------- */
+ pseudo_bit_t rq_num_mce[0x00020]; /* Responder - number of bad multicast packets received */
+/* -------------- */
+ pseudo_bit_t reserved9[0x00020];
+/* -------------- */
+ pseudo_bit_t rq_num_rsync[0x00020]; /* Responder - number of RESYNC operations */
+/* -------------- */
+ pseudo_bit_t sq_num_rsync[0x00020]; /* Requester - number of RESYNC operations */
+/* -------------- */
+ pseudo_bit_t rq_num_udsdprd[0x00020];/* The number of UD packets silently discarded on the receive queue due to lack of receive descriptor. */
+/* -------------- */
+ pseudo_bit_t reserved10[0x00020];
+/* -------------- */
+ pseudo_bit_t rq_num_ucsdprd[0x00020];/* The number of UC packets silently discarded on the receive queue due to lack of receive descriptor. */
+/* -------------- */
+ pseudo_bit_t reserved11[0x003e0];
+/* -------------- */
+ pseudo_bit_t num_cqovf[0x00020]; /* Number of CQ overflows */
+/* -------------- */
+ pseudo_bit_t num_eqovf[0x00020]; /* Number of EQ overflows */
+/* -------------- */
+ pseudo_bit_t num_baddb[0x00020]; /* Number of bad doorbells */
+/* -------------- */
+ pseudo_bit_t reserved12[0x002a0];
+/* -------------- */
+};
+
+/* Event_data Field - HCR Completion Event #### michal - match PRM */
+
+struct hermonprm_hcr_completion_event_st { /* Little Endian */
+ pseudo_bit_t token[0x00010]; /* HCR Token */
+ pseudo_bit_t reserved0[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00020];
+/* -------------- */
+ pseudo_bit_t status[0x00008]; /* HCR Status */
+ pseudo_bit_t reserved2[0x00018];
+/* -------------- */
+ pseudo_bit_t out_param_h[0x00020]; /* HCR Output Parameter [63:32] */
+/* -------------- */
+ pseudo_bit_t out_param_l[0x00020]; /* HCR Output Parameter [31:0] */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00020];
+/* -------------- */
+};
+
+/* Completion with Error CQE #### michal - gdror fixed */
+
+struct hermonprm_completion_with_error_st { /* Little Endian */
+ pseudo_bit_t qpn[0x00018]; /* Indicates the QP for which completion is being reported */
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved1[0x000a0];
+/* -------------- */
+ pseudo_bit_t syndrome[0x00008]; /* Completion with error syndrome:
+ 0x01 - Local Length Error
+ 0x02 - Local QP Operation Error
+ 0x03 - Local EE Context Operation Error
+ 0x04 - Local Protection Error
+ 0x05 - Work Request Flushed Error
+ 0x06 - Memory Window Bind Error
+ 0x10 - Bad Response Error
+ 0x11 - Local Access Error
+ 0x12 - Remote Invalid Request Error
+ 0x13 - Remote Access Error
+ 0x14 - Remote Operation Error
+ 0x15 - Transport Retry Counter Exceeded
+ 0x16 - RNR Retry Counter Exceeded
+ 0x20 - Local RDD Violation Error
+ 0x21 - Remote Invalid RD Request
+ 0x22 - Remote Aborted Error
+ 0x23 - Invalid EE Context Number
+ 0x24 - Invalid EE Context State
+ other - Reserved
+ Syndrome is defined according to the IB specification volume 1. For detailed explanation of the syndromes, refer to chapters 10-11 of the IB specification rev 1.1. */
+ pseudo_bit_t vendor_error_syndrome[0x00008];
+ pseudo_bit_t wqe_counter[0x00010];
+/* -------------- */
+ pseudo_bit_t opcode[0x00005]; /* The opcode of WQE completion is reported for.
+
+ The following values are reported in case of completion with error:
+ 0xFE - For completion with error on Receive Queues
+ 0xFF - For completion with error on Send Queues */
+ pseudo_bit_t reserved2[0x00001];
+ pseudo_bit_t s_r[0x00001]; /* send 1 / receive 0 */
+ pseudo_bit_t owner[0x00001]; /* HW Flips this bit for every CQ warp around. Initialized to Zero. */
+ pseudo_bit_t reserved3[0x00018];
+/* -------------- */
+};
+
+/* Resize CQ Input Mailbox */
+
+struct hermonprm_resize_cq_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00040];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00006];
+ pseudo_bit_t page_offset[0x00006];
+ pseudo_bit_t reserved2[0x00014];
+/* -------------- */
+ pseudo_bit_t reserved3[0x00018];
+ pseudo_bit_t log_cq_size[0x00005]; /* Log (base 2) of the CQ size (in entries) */
+ pseudo_bit_t reserved4[0x00003];
+/* -------------- */
+ pseudo_bit_t reserved5[0x00020];
+/* -------------- */
+ pseudo_bit_t mtt_base_addr_h[0x00008];
+ pseudo_bit_t reserved6[0x00010];
+ pseudo_bit_t log2_page_size[0x00006];
+ pseudo_bit_t reserved7[0x00002];
+/* -------------- */
+ pseudo_bit_t reserved8[0x00003];
+ pseudo_bit_t mtt_base_addr_l[0x0001d];
+/* -------------- */
+ pseudo_bit_t reserved9[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved10[0x00100];
+/* -------------- */
+};
+
+/* MAD_IFC Input Modifier */
+
+struct hermonprm_mad_ifc_input_modifier_st { /* Little Endian */
+ pseudo_bit_t port_number[0x00008]; /* The packet reception port number (1 or 2). */
+ pseudo_bit_t mad_extended_info[0x00001];/* Mad_Extended_Info valid bit (MAD_IFC Input Mailbox data from offset 00100h and down). MAD_Extended_Info is read only if this bit is set.
+ Required for trap generation when BKey check is enabled and for global routed packets. */
+ pseudo_bit_t reserved0[0x00007];
+ pseudo_bit_t rlid[0x00010]; /* Remote (source) LID from the received MAD.
+ This field is required for trap generation upon MKey/BKey validation. */
+/* -------------- */
+};
+
+/* MAD_IFC Input Mailbox ###michal -gdror fixed */
+
+struct hermonprm_mad_ifc_st { /* Little Endian */
+ pseudo_bit_t request_mad_packet[64][0x00020];/* Request MAD Packet (256bytes) */
+/* -------------- */
+ pseudo_bit_t my_qpn[0x00018]; /* Destination QP number from the received MAD.
+ This field is reserved if Mad_extended_info indication in the input modifier is clear. */
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00020];
+/* -------------- */
+ pseudo_bit_t rqpn[0x00018]; /* Remote (source) QP number from the received MAD.
+ This field is reserved if Mad_extended_info indication in the input modifier is clear. */
+ pseudo_bit_t reserved2[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved3[0x00010];
+ pseudo_bit_t ml_path[0x00007]; /* My (destination) LID path bits from the received MAD.
+ This field is reserved if Mad_extended_info indication in the input modifier is clear. */
+ pseudo_bit_t g[0x00001]; /* If set, the GRH field in valid.
+ This field is reserved if Mad_extended_info indication in the input modifier is clear. */
+ pseudo_bit_t reserved4[0x00004];
+ pseudo_bit_t sl[0x00004]; /* Service Level of the received MAD.
+ This field is reserved if Mad_extended_info indication in the input modifier is clear. */
+/* -------------- */
+ pseudo_bit_t pkey_indx[0x00010]; /* Index in PKey table that matches PKey of the received MAD.
+ This field is reserved if Mad_extended_info indication in the input modifier is clear. */
+ pseudo_bit_t reserved5[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved6[0x00160];
+/* -------------- */
+ pseudo_bit_t grh[10][0x00020]; /* The GRH field of the MAD packet that was scattered to the first 40 bytes pointed to by the scatter list.
+ Valid if Mad_extended_info bit (in the input modifier) and g bit are set.
+ Otherwise this field is reserved. */
+/* -------------- */
+ pseudo_bit_t reserved7[0x004c0];
+/* -------------- */
+};
+
+/* Query Debug Message #### michal - gdror fixed */
+
+struct hermonprm_query_debug_msg_st { /* Little Endian */
+ pseudo_bit_t phy_addr_h[0x00020]; /* Translation of the address in firmware area. High 32 bits. */
+/* -------------- */
+ pseudo_bit_t v[0x00001]; /* Physical translation is valid */
+ pseudo_bit_t reserved0[0x0000b];
+ pseudo_bit_t phy_addr_l[0x00014]; /* Translation of the address in firmware area. Low 32 bits. */
+/* -------------- */
+ pseudo_bit_t fw_area_base[0x00020]; /* Firmware area base address. The format strings and the trace buffers may be located starting from this address. */
+/* -------------- */
+ pseudo_bit_t fw_area_size[0x00020]; /* Firmware area size */
+/* -------------- */
+ pseudo_bit_t trc_hdr_sz[0x00020]; /* Trace message header size in dwords. */
+/* -------------- */
+ pseudo_bit_t trc_arg_num[0x00020]; /* The number of arguments per trace message. */
+/* -------------- */
+ pseudo_bit_t reserved1[0x000c0];
+/* -------------- */
+ pseudo_bit_t dbg_msk_h[0x00020]; /* Debug messages mask [63:32] */
+/* -------------- */
+ pseudo_bit_t dbg_msk_l[0x00020]; /* Debug messages mask [31:0] */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00040];
+/* -------------- */
+ pseudo_bit_t buff0_addr[0x00020]; /* Address in firmware area of Trace Buffer 0 */
+/* -------------- */
+ pseudo_bit_t buff0_size[0x00020]; /* Size of Trace Buffer 0 */
+/* -------------- */
+ pseudo_bit_t buff1_addr[0x00020]; /* Address in firmware area of Trace Buffer 1 */
+/* -------------- */
+ pseudo_bit_t buff1_size[0x00020]; /* Size of Trace Buffer 1 */
+/* -------------- */
+ pseudo_bit_t buff2_addr[0x00020]; /* Address in firmware area of Trace Buffer 2 */
+/* -------------- */
+ pseudo_bit_t buff2_size[0x00020]; /* Size of Trace Buffer 2 */
+/* -------------- */
+ pseudo_bit_t buff3_addr[0x00020]; /* Address in firmware area of Trace Buffer 3 */
+/* -------------- */
+ pseudo_bit_t buff3_size[0x00020]; /* Size of Trace Buffer 3 */
+/* -------------- */
+ pseudo_bit_t buff4_addr[0x00020]; /* Address in firmware area of Trace Buffer 4 */
+/* -------------- */
+ pseudo_bit_t buff4_size[0x00020]; /* Size of Trace Buffer 4 */
+/* -------------- */
+ pseudo_bit_t buff5_addr[0x00020]; /* Address in firmware area of Trace Buffer 5 */
+/* -------------- */
+ pseudo_bit_t buff5_size[0x00020]; /* Size of Trace Buffer 5 */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00080];
+/* -------------- */
+ pseudo_bit_t hw_buff_addr[0x00020]; /* Dror Mux Bohrer tracer */
+/* -------------- */
+ pseudo_bit_t hw_buff_size[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved4[0x003c0];
+/* -------------- */
+};
+
+/* User Access Region */
+
+struct hermonprm_uar_st { /* Little Endian */
+ struct hermonprm_rd_send_doorbell_st rd_send_doorbell;/* Reliable Datagram send doorbell */
+/* -------------- */
+ struct hermonprm_send_doorbell_st send_doorbell;/* Send doorbell */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00040];
+/* -------------- */
+ struct hermonprm_cq_cmd_doorbell_st cq_command_doorbell;/* CQ Doorbell */
+/* -------------- */
+ pseudo_bit_t reserved1[0x03ec0];
+/* -------------- */
+};
+
+/* Receive doorbell */
+
+struct hermonprm_receive_doorbell_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t wqe_counter[0x00010]; /* Modulo-64K counter of WQEs posted on this queue since its creation. Should be zero for the first doorbell on the QP */
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved2[0x00005];
+ pseudo_bit_t srq[0x00001]; /* If set, this is a Shared Receive Queue */
+ pseudo_bit_t reserved3[0x00002];
+ pseudo_bit_t qpn[0x00018]; /* QP number or SRQ number this doorbell is rung on */
+/* -------------- */
+};
+
+/* SET_IB Parameters */
+
+struct hermonprm_set_ib_st { /* Little Endian */
+ pseudo_bit_t rqk[0x00001]; /* Reset QKey Violation Counter */
+ pseudo_bit_t reserved0[0x00011];
+ pseudo_bit_t sig[0x00001]; /* Set System Image GUID to system_image_guid specified.
+ system_image_guid and sig must be the same for all ports. */
+ pseudo_bit_t reserved1[0x0000d];
+/* -------------- */
+ pseudo_bit_t capability_mask[0x00020];/* PortInfo Capability Mask */
+/* -------------- */
+ pseudo_bit_t system_image_guid_h[0x00020];/* System Image GUID[63:32], takes effect only if the SIG bit is set
+ Must be the same for both ports. */
+/* -------------- */
+ pseudo_bit_t system_image_guid_l[0x00020];/* System Image GUID[31:0], takes effect only if the SIG bit is set
+ Must be the same for both ports. */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00180];
+/* -------------- */
+};
+
+/* Multicast Group Member #### michal - gdror fixed */
+
+struct hermonprm_mgm_entry_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00006];
+ pseudo_bit_t next_gid_index[0x0001a];/* Index of next Multicast Group Member whose GID maps to same MGID_HASH number.
+ The index is into the Multicast Group Table, which is the comprised the MGHT and AMGM tables.
+ next_gid_index=0 means end of the chain. */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00060];
+/* -------------- */
+ pseudo_bit_t mgid_128_96[0x00020]; /* Multicast group GID[128:96] in big endian format.
+ Use the Reserved GID 0:0:0:0:0:0:0:0 for an invalid entry. */
+/* -------------- */
+ pseudo_bit_t mgid_95_64[0x00020]; /* Multicast group GID[95:64] in big endian format.
+ Use the Reserved GID 0:0:0:0:0:0:0:0 for an invalid entry. */
+/* -------------- */
+ pseudo_bit_t mgid_63_32[0x00020]; /* Multicast group GID[63:32] in big endian format.
+ Use the Reserved GID 0:0:0:0:0:0:0:0 for an invalid entry. */
+/* -------------- */
+ pseudo_bit_t mgid_31_0[0x00020]; /* Multicast group GID[31:0] in big endian format.
+ Use the Reserved GID 0:0:0:0:0:0:0:0 for an invalid entry. */
+/* -------------- */
+ struct hermonprm_mgmqp_st mgmqp_0; /* Multicast Group Member QP */
+/* -------------- */
+ struct hermonprm_mgmqp_st mgmqp_1; /* Multicast Group Member QP */
+/* -------------- */
+ struct hermonprm_mgmqp_st mgmqp_2; /* Multicast Group Member QP */
+/* -------------- */
+ struct hermonprm_mgmqp_st mgmqp_3; /* Multicast Group Member QP */
+/* -------------- */
+ struct hermonprm_mgmqp_st mgmqp_4; /* Multicast Group Member QP */
+/* -------------- */
+ struct hermonprm_mgmqp_st mgmqp_5; /* Multicast Group Member QP */
+/* -------------- */
+ struct hermonprm_mgmqp_st mgmqp_6; /* Multicast Group Member QP */
+/* -------------- */
+ struct hermonprm_mgmqp_st mgmqp_7; /* Multicast Group Member QP */
+/* -------------- */
+};
+
+/* INIT_PORT Parameters #### michal - match PRM */
+
+struct hermonprm_init_port_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00004];
+ pseudo_bit_t vl_cap[0x00004]; /* Maximum VLs supported on the port, excluding VL15.
+ Legal values are 1,2,4 and 8. */
+ pseudo_bit_t port_width_cap[0x00004];/* IB Port Width
+ 1 - 1x
+ 3 - 1x, 4x
+ 11 - 1x, 4x or 12x (must not be used in InfiniHost-III-EX MT25208)
+ else - Reserved */
+ pseudo_bit_t reserved1[0x00004];
+ pseudo_bit_t g0[0x00001]; /* Set port GUID0 to GUID0 specified */
+ pseudo_bit_t ng[0x00001]; /* Set node GUID to node_guid specified.
+ node_guid and ng must be the same for all ports. */
+ pseudo_bit_t sig[0x00001]; /* Set System Image GUID to system_image_guid specified.
+ system_image_guid and sig must be the same for all ports. */
+ pseudo_bit_t reserved2[0x0000d];
+/* -------------- */
+ pseudo_bit_t max_gid[0x00010]; /* Maximum number of GIDs for the port */
+ pseudo_bit_t mtu[0x00010]; /* Maximum MTU Supported in bytes
+ must be: 256, 512, 1024, 2048 or 4096
+ For Eth port, can be any
+ Field must not cross device capabilities as reported
+ */
+/* -------------- */
+ pseudo_bit_t max_pkey[0x00010]; /* Maximum pkeys for the port.
+ Must be the same for both ports. */
+ pseudo_bit_t reserved3[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved4[0x00020];
+/* -------------- */
+ pseudo_bit_t guid0_h[0x00020]; /* EUI-64 GUID assigned by the manufacturer, takes effect only if the G0 bit is set (bits 63:32) */
+/* -------------- */
+ pseudo_bit_t guid0_l[0x00020]; /* EUI-64 GUID assigned by the manufacturer, takes effect only if the G0 bit is set (bits 31:0) */
+/* -------------- */
+ pseudo_bit_t node_guid_h[0x00020]; /* Node GUID[63:32], takes effect only if the NG bit is set
+ Must be the same for both ports. */
+/* -------------- */
+ pseudo_bit_t node_guid_l[0x00020]; /* Node GUID[31:0], takes effect only if the NG bit is set
+ Must be the same for both ports. */
+/* -------------- */
+ pseudo_bit_t system_image_guid_h[0x00020];/* System Image GUID[63:32], takes effect only if the SIG bit is set
+ Must be the same for both ports. */
+/* -------------- */
+ pseudo_bit_t system_image_guid_l[0x00020];/* System Image GUID[31:0], takes effect only if the SIG bit is set
+ Must be the same for both ports. */
+/* -------------- */
+ pseudo_bit_t reserved5[0x006c0];
+/* -------------- */
+};
+
+/* Query Device Capablities #### michal - gdror fixed */
+
+struct hermonprm_query_dev_cap_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00080];
+/* -------------- */
+ pseudo_bit_t log_max_qp[0x00005]; /* Log2 of the Maximum number of QPs supported */
+ pseudo_bit_t reserved1[0x00003];
+ pseudo_bit_t log2_rsvd_qps[0x00004];/* Log (base 2) of the number of QPs reserved for firmware use
+ The reserved resources are numbered from 0 to 2^log2_rsvd_qps-1 */
+ pseudo_bit_t reserved2[0x00004];
+ pseudo_bit_t log_max_qp_sz[0x00008];/* The maximum number of WQEs allowed on the RQ or the SQ is 2^log_max_qp_sz-1 */
+ pseudo_bit_t log_max_srq_sz[0x00008];/* The maximum number of WQEs allowed on the SRQ is 2^log_max_srq_sz-1 */
+/* -------------- */
+ pseudo_bit_t log_max_scqs[0x00004]; /* log base 2 of number of supported schedule queues */
+ pseudo_bit_t reserved3[0x00004];
+ pseudo_bit_t num_rsvd_scqs[0x00006];
+ pseudo_bit_t reserved4[0x00002];
+ pseudo_bit_t log_max_srqs[0x00005];
+ pseudo_bit_t reserved5[0x00007];
+ pseudo_bit_t log2_rsvd_srqs[0x00004];
+/* -------------- */
+ pseudo_bit_t log_max_cq[0x00005]; /* Log2 of the Maximum number of CQs supported */
+ pseudo_bit_t reserved6[0x00003];
+ pseudo_bit_t log2_rsvd_cqs[0x00004];/* Log (base 2) of the number of CQs reserved for firmware use
+ The reserved resources are numbered from 0 to 2^log2_rsrvd_cqs-1 */
+ pseudo_bit_t reserved7[0x00004];
+ pseudo_bit_t log_max_cq_sz[0x00008];/* Log2 of the Maximum CQEs allowed in a CQ */
+ pseudo_bit_t num_rsvd_eqs[0x00008]; /* The number of EQs reserved for firmware use
+ The reserved resources are numbered from 0 to num_rsvd_eqs-1
+ If 0 - no resources are reserved. */
+/* -------------- */
+ pseudo_bit_t log_max_eq[0x00004]; /* Log2 of the Maximum number of EQs */
+ pseudo_bit_t reserved9[0x00004];
+ pseudo_bit_t log2_rsvd_eqs[0x00004]; /* The number of EQs reserved for firmware use
+ The reserved resources are numbered from 0 to num_rsvd_eqs-1
+ If 0 - no resources are reserved. */
+ pseudo_bit_t reserved10[0x00004];
+ pseudo_bit_t log_max_d_mpts[0x00006];/* Log (base 2) of the maximum number of data MPT entries (the number of Regions/Windows) */
+ pseudo_bit_t reserved11[0x00002];
+ pseudo_bit_t log_max_eq_sz[0x00008];/* Log2 of the Maximum EQEs allowed in a EQ */
+/* -------------- */
+ pseudo_bit_t log_max_mtts[0x00006]; /* Log2 of the Maximum number of MTT entries */
+ pseudo_bit_t reserved12[0x00002];
+ pseudo_bit_t log2_rsvd_mrws[0x00004];/* Log (base 2) of the number of MPTs reserved for firmware use
+ The reserved resources are numbered from 0 to 2^log2_rsvd_mrws-1 */
+ pseudo_bit_t reserved13[0x00004];
+ pseudo_bit_t log_max_mrw_sz[0x00007];/* Log2 of the Maximum Size of Memory Region/Window. is it in PRM layout? */
+ pseudo_bit_t reserved14[0x00005];
+ pseudo_bit_t log2_rsvd_mtts[0x00004];/* Log (base 2) of the number of MTT entries reserved for firmware use
+ The reserved resources are numbered from 0 to 2^log2_rsvd_mtts-1
+ */
+/* -------------- */
+ pseudo_bit_t reserved15[0x00020];
+/* -------------- */
+ pseudo_bit_t log_max_ra_res_qp[0x00006];/* Log2 of the Maximum number of outstanding RDMA read/Atomic per QP as a responder */
+ pseudo_bit_t reserved16[0x0000a];
+ pseudo_bit_t log_max_ra_req_qp[0x00006];/* Log2 of the maximum number of outstanding RDMA read/Atomic per QP as a requester */
+ pseudo_bit_t reserved17[0x0000a];
+/* -------------- */
+ pseudo_bit_t log_max_ra_res_global[0x00006];/* Log2 of the maximum number of RDMA read/atomic operations the HCA responder can support globally. That implies the RDB table size. */
+ pseudo_bit_t reserved18[0x0001a];
+/* -------------- */
+ pseudo_bit_t rsz_srq[0x00001]; /* Ability to modify the maximum number of WRs per SRQ. */
+ pseudo_bit_t reserved19[0x0001f];
+/* -------------- */
+ pseudo_bit_t num_ports[0x00004]; /* Number of IB ports. */
+ pseudo_bit_t reserved47[0x00004];
+ pseudo_bit_t pci_pf_num[0x00008]; /* Number of supported physical functions */
+ pseudo_bit_t local_ca_ack_delay[0x00005];/* The Local CA ACK Delay. This is the value recommended to be returned in Query HCA verb.
+ The delay value in microseconds is computed using 4.096us * 2^(local_ca_ack_delay). */
+ pseudo_bit_t port_type[0x00004]; /* Hermon New. bit per port. bit0 is first port. value '1' is ehternet. '0' is IB */
+ pseudo_bit_t reserved20[0x00004];
+ pseudo_bit_t w[0x00001]; /* Hermon New. 10GB eth support */
+ pseudo_bit_t j[0x00001]; /* Hermon New. Jumbo frame support */
+ pseudo_bit_t reserved21[0x00001];
+/* -------------- */
+ pseudo_bit_t log_max_gid[0x00004]; /* Log2 of the maximum number of GIDs per port */
+ pseudo_bit_t reserved22[0x00004];
+ pseudo_bit_t log_ethtype[0x00004]; /* Hermon New. log2 eth type table size */
+ pseudo_bit_t reserved23[0x00004];
+ pseudo_bit_t log_drain_size[0x00008];/* Log (base 2) of minimum size of the NoDropVLDrain buffer, specified in 4Kpages units */
+ pseudo_bit_t log_max_msg[0x00005]; /* Log (base 2) of the maximum message size supported by the device */
+ pseudo_bit_t reserved24[0x00003];
+/* -------------- */
+ pseudo_bit_t log_max_pkey[0x00004]; /* Log2 of the max PKey Table Size (per IB port) */
+ pseudo_bit_t reserved25[0x0000c];
+ pseudo_bit_t stat_rate_support[0x00010];/* bit mask of stat rate supported
+ bit 0 - full bw
+ bit 1 - 1/4 bw
+ bit 2 - 1/8 bw
+ bit 3 - 1/2 bw; */
+/* -------------- */
+ pseudo_bit_t reserved26[0x00008];
+ pseudo_bit_t rss_udp[0x00001];
+ pseudo_bit_t vep_uc_steering[0x00001];
+ pseudo_bit_t vep_mc_steering[0x00001];
+ pseudo_bit_t reserved27[0x00015];
+
+/* -------------- */
+ pseudo_bit_t rc[0x00001]; /* RC Transport supported */
+ pseudo_bit_t uc[0x00001]; /* UC Transport Supported */
+ pseudo_bit_t ud[0x00001]; /* UD Transport Supported */
+ pseudo_bit_t src[0x00001]; /* SRC Transport Supported. Hermon New instead of RD. */
+ pseudo_bit_t rcm[0x00001]; /* Reliable Multicast support. Hermon New instead of IPv6 Transport Supported */
+ pseudo_bit_t fcoib[0x00001]; /* Hermon New */
+ pseudo_bit_t srq[0x00001]; /* SRQ is supported
+ */
+ pseudo_bit_t checksum[0x00001]; /* IP over IB checksum is supported */
+ pseudo_bit_t pkv[0x00001]; /* PKey Violation Counter Supported */
+ pseudo_bit_t qkv[0x00001]; /* QKey Violation Coutner Supported */
+ pseudo_bit_t vmm[0x00001]; /* Hermon New */
+ pseudo_bit_t fcoe[0x00001];
+ pseudo_bit_t dpdp[0x00001]; /* Dual Port Different Protocols */
+ pseudo_bit_t raw_ethertype[0x00001];
+ pseudo_bit_t raw_ipv6[0x00001];
+ pseudo_bit_t blh[0x00001];
+ pseudo_bit_t mw[0x00001]; /* Memory windows supported */
+ pseudo_bit_t apm[0x00001]; /* Automatic Path Migration Supported */
+ pseudo_bit_t atm[0x00001]; /* Atomic operations supported (atomicity is guaranteed between QPs on this HCA) */
+ pseudo_bit_t rm[0x00001]; /* Raw Multicast Supported */
+ pseudo_bit_t avp[0x00001]; /* Address Vector Port checking supported */
+ pseudo_bit_t udm[0x00001]; /* UD Multicast Supported */
+ pseudo_bit_t reserved28[0x00002];
+ pseudo_bit_t pg[0x00001]; /* Paging on demand supported */
+ pseudo_bit_t r[0x00001]; /* Router mode supported */
+ pseudo_bit_t reserved29[0x00006];
+/* -------------- */
+ pseudo_bit_t log_pg_sz[0x00008]; /* Minimum system page size supported (log2).
+ For proper operation it must be less than or equal the hosting platform (CPU) minimum page size. */
+ pseudo_bit_t reserved30[0x00008];
+ pseudo_bit_t uar_sz[0x00006]; /* UAR Area Size = 1MB * 2^uar_sz */
+ pseudo_bit_t reserved31[0x00006];
+ pseudo_bit_t num_rsvd_uars[0x00004];/* The number of UARs reserved for firmware use
+ The reserved resources are numbered from 0 to num_reserved_uars-1
+ Note that UAR number num_reserved_uars is always for the kernel. */
+/* -------------- */
+ pseudo_bit_t log_max_bf_pages[0x00006];/* Maximum number of BlueFlame pages is 2^log_max_bf_pages */
+ pseudo_bit_t reserved32[0x00002];
+ pseudo_bit_t log_max_bf_regs_per_page[0x00006];/* Maximum number of BlueFlame registers per page is 2^log_max_bf_regs_per_page. It may be that only the beginning of a page contains BlueFlame registers. */
+ pseudo_bit_t reserved33[0x00002];
+ pseudo_bit_t log_bf_reg_size[0x00005];/* BlueFlame register size in bytes is 2^log_bf_reg_size */
+ pseudo_bit_t reserved34[0x0000a];
+ pseudo_bit_t bf[0x00001]; /* If set to "1" then BlueFlame may be used. */
+/* -------------- */
+ pseudo_bit_t max_desc_sz_sq[0x00010];/* Max descriptor size in bytes for the send queue */
+ pseudo_bit_t max_sg_sq[0x00008]; /* The maximum S/G list elements in a SQ WQE (max_desc_sz/16 - 3) */
+ pseudo_bit_t reserved35[0x00008];
+/* -------------- */
+ pseudo_bit_t max_desc_sz_rq[0x00010];/* Max descriptor size in bytes for the receive queue */
+ pseudo_bit_t max_sg_rq[0x00008]; /* The maximum S/G list elements in a RQ WQE (max_desc_sz/16 - 3) */
+ pseudo_bit_t reserved36[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved37[0x00001];
+ pseudo_bit_t fexch_base_mpt_31_25[0x00007];/* Hermon New. FC mpt base mpt number */
+ pseudo_bit_t fcp_ud_base_23_8[0x00010];/* Hermon New. FC ud QP base QPN */
+ pseudo_bit_t fexch_base_qp_23_16[0x00008];/* Hermon New. FC Exchange QP base QPN */
+/* -------------- */
+ pseudo_bit_t reserved38[0x00020];
+/* -------------- */
+ pseudo_bit_t log_max_mcg[0x00008]; /* Log2 of the maximum number of multicast groups */
+ pseudo_bit_t num_rsvd_mcgs[0x00004];/* The number of MGMs reserved for firmware use in the MGHT.
+ The reserved resources are numbered from 0 to num_reserved_mcgs-1
+ If 0 - no resources are reserved. */
+ pseudo_bit_t reserved39[0x00004];
+ pseudo_bit_t log_max_qp_mcg[0x00008];/* Log2 of the maximum number of QPs per multicast group */
+ pseudo_bit_t reserved40[0x00008];
+/* -------------- */
+ pseudo_bit_t log_max_srcds[0x00004];/* Log2 of the maximum number of SRC Domains */
+ pseudo_bit_t reserved41[0x00008];
+ pseudo_bit_t num_rsvd_scrds[0x00004];/* The number of SRCDs reserved for firmware use
+ The reserved resources are numbered from 0 to num_reserved_rdds-1.
+ If 0 - no resources are reserved. */
+ pseudo_bit_t log_max_pd[0x00005]; /* Log2 of the maximum number of PDs */
+ pseudo_bit_t reserved42[0x00007];
+ pseudo_bit_t num_rsvd_pds[0x00004]; /* The number of PDs reserved for firmware use
+ The reserved resources are numbered from 0 to num_reserved_pds-1
+ If 0 - no resources are reserved. */
+/* -------------- */
+ pseudo_bit_t reserved43[0x000c0];
+/* -------------- */
+ pseudo_bit_t qpc_entry_sz[0x00010]; /* QPC Entry Size for the device
+ For the InfiniHost-III-EX MT25208 entry size is 256 bytes */
+ pseudo_bit_t rdmardc_entry_sz[0x00010];/* RdmaRdC Entry Size for the device
+ For the InfiniHost-III-EX MT25208 entry size is 256 bytes */
+/* -------------- */
+ pseudo_bit_t altc_entry_sz[0x00010];/* Extended QPC entry size for the device
+ For the InfiniHost-III-EX MT25208 entry size is 32 bytes */
+ pseudo_bit_t aux_entry_sz[0x00010]; /* Auxilary context entry size */
+/* -------------- */
+ pseudo_bit_t cqc_entry_sz[0x00010]; /* CQC entry size for the device
+ For the InfiniHost-III-EX MT25208 entry size is 64 bytes */
+ pseudo_bit_t eqc_entry_sz[0x00010]; /* EQ context entry size for the device
+ For the InfiniHost-III-EX MT25208 entry size is 64 bytes */
+/* -------------- */
+ pseudo_bit_t c_mpt_entry_sz[0x00010];/* cMPT entry size in Bytes for the device.
+ For the InfiniHost-III-EX MT25208 entry size is 64 bytes */
+ pseudo_bit_t srq_entry_sz[0x00010]; /* SRQ context entry size for the device
+ For the InfiniHost-III-EX MT25208 entry size is 32 bytes */
+/* -------------- */
+ pseudo_bit_t d_mpt_entry_sz[0x00010];/* dMPT entry size in Bytes for the device.
+ For the InfiniHost-III-EX MT25208 entry size is 64 bytes */
+ pseudo_bit_t mtt_entry_sz[0x00010]; /* MTT entry size in Bytes for the device.
+ For the InfiniHost-III-EX MT25208 entry size is 8 bytes */
+/* -------------- */
+ pseudo_bit_t bmme[0x00001]; /* Base Memory Management Extension Support */
+ pseudo_bit_t win_type[0x00001]; /* Bound Type 2 Memory Window Association mechanism:
+ 0 - Type 2A - QP Number Association; or
+ 1 - Type 2B - QP Number and PD Association. */
+ pseudo_bit_t mps[0x00001]; /* Ability of this HCA to support multiple page sizes per Memory Region. */
+ pseudo_bit_t bl[0x00001]; /* Ability of this HCA to support Block List Physical Buffer Lists. */
+ pseudo_bit_t zb[0x00001]; /* Zero Based region/windows supported */
+ pseudo_bit_t lif[0x00001]; /* Ability of this HCA to support Local Invalidate Fencing. */
+ pseudo_bit_t reserved44[0x0001a];
+/* -------------- */
+ pseudo_bit_t resd_lkey[0x00020]; /* The value of the reserved Lkey for Base Memory Management Extension */
+/* -------------- */
+ pseudo_bit_t reserved45[0x00020];
+/* -------------- */
+ pseudo_bit_t max_icm_size_h[0x00020];/* Bits [63:32] of maximum ICM size InfiniHost III Ex support in bytes. */
+/* -------------- */
+ pseudo_bit_t max_icm_size_l[0x00020];/* Bits [31:0] of maximum ICM size InfiniHost III Ex support in bytes. */
+/* -------------- */
+ pseudo_bit_t reserved46[0x002c0];
+/* -------------- */
+};
+
+/* QUERY_ADAPTER Parameters Block #### michal - gdror fixed */
+
+struct hermonprm_query_adapter_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00080];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00018];
+ pseudo_bit_t intapin[0x00008]; /* Driver should set this field to INTR value in the event queue in order to get Express interrupt messages. */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00060];
+/* -------------- */
+ struct hermonprm_vsd_st vsd; /* ###michal- this field was replaced by 2 fields : vsd .1664; vsd(continued/psid .128; */
+/* -------------- */
+};
+
+/* QUERY_FW Parameters Block #### michal - doesn't match PRM */
+
+struct hermonprm_query_fw_st { /* Little Endian */
+ pseudo_bit_t fw_rev_major[0x00010]; /* Firmware Revision - Major */
+ pseudo_bit_t fw_pages[0x00010]; /* Amount of physical memory to be allocated for FW usage is in 4KByte pages. */
+/* -------------- */
+ pseudo_bit_t fw_rev_minor[0x00010]; /* Firmware Revision - Minor */
+ pseudo_bit_t fw_rev_subminor[0x00010];/* Firmware Sub-minor version (Patch level). */
+/* -------------- */
+ pseudo_bit_t cmd_interface_rev[0x00010];/* Command Interface Interpreter Revision ID */
+ pseudo_bit_t reserved0[0x00010];
+/* -------------- */
+ pseudo_bit_t log_max_outstanding_cmd[0x00008];/* Log2 of the maximum number of commands the HCR can support simultaneously */
+ pseudo_bit_t reserved1[0x00017];
+ pseudo_bit_t dt[0x00001]; /* Debug Trace Support
+ 0 - Debug trace is not supported
+ 1 - Debug trace is supported */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00001];
+ pseudo_bit_t ccq[0x00001]; /* CCQ support */
+ pseudo_bit_t reserved3[0x00006];
+ pseudo_bit_t fw_seconds[0x00008]; /* FW timestamp - seconds. Dispalyed as Hexadecimal number */
+ pseudo_bit_t fw_minutes[0x00008]; /* FW timestamp - minutes. Dispalyed as Hexadecimal number */
+ pseudo_bit_t fw_hour[0x00008]; /* FW timestamp - hour. Dispalyed as Hexadecimal number */
+/* -------------- */
+ pseudo_bit_t fw_day[0x00008]; /* FW timestamp - day. Dispalyed as Hexadecimal number */
+ pseudo_bit_t fw_month[0x00008]; /* FW timestamp - month. Dispalyed as Hexadecimal number */
+ pseudo_bit_t fw_year[0x00010]; /* FW timestamp - year. Dispalyed as Hexadecimal number (e.g. 0x2005) */
+/* -------------- */
+ pseudo_bit_t reserved4[0x00040];
+/* -------------- */
+ pseudo_bit_t clr_int_base_offset_h[0x00020];/* Bits [63:32] of the Clear Interrupt registerÂ’s offset from clr_int_bar register in PCIaddress space. Points to a 64-bit register. */
+/* -------------- */
+ pseudo_bit_t clr_int_base_offset_l[0x00020];/* Bits [31:0] of the Clear Interrupt registerÂ’s offset from clr_int_bar register in PCIaddress space. Points to a 64-bit register. */
+/* -------------- */
+ pseudo_bit_t reserved5[0x0001e];
+ pseudo_bit_t clr_int_bar[0x00002]; /* PCI base address register (BAR) where clr_int register is located.
+ 00 - BAR 0-1
+ 01 - BAR 2-3
+ 10 - BAR 4-5
+ 11 - Reserved
+ The PCI BARs of ConnectX are 64 bit BARs.
+ In ConnectX, clr_int register is located on BAR 0-1. */
+/* -------------- */
+ pseudo_bit_t reserved6[0x00020];
+/* -------------- */
+ pseudo_bit_t error_buf_offset_h[0x00020];/* Read Only buffer for catastrophic error reports (bits [63:32] of offset from error_buf_bar register in PCI address space.) */
+/* -------------- */
+ pseudo_bit_t error_buf_offset_l[0x00020];/* Read Only buffer for catastrophic error reports (bits [31:0] of offset from error_buf_bar register in PCI address space.) */
+/* -------------- */
+ pseudo_bit_t error_buf_size[0x00020];/* Size in words */
+/* -------------- */
+ pseudo_bit_t reserved7[0x0001e];
+ pseudo_bit_t error_buf_bar[0x00002];/* PCI base address register (BAR) where error_buf register is located.
+ 00 - BAR 0-1
+ 01 - BAR 2-3
+ 10 - BAR 4-5
+ 11 - Reserved
+ The PCI BARs of ConnectX are 64 bit BARs.
+ In ConnectX, error_buf register is located on BAR 0-1. */
+/* -------------- */
+ pseudo_bit_t reserved8[0x00600];
+/* -------------- */
+};
+
+/* Memory Access Parameters for UD Address Vector Table */
+
+struct hermonprm_udavtable_memory_parameters_st { /* Little Endian */
+ pseudo_bit_t l_key[0x00020]; /* L_Key used to access TPT */
+/* -------------- */
+ pseudo_bit_t pd[0x00018]; /* PD used by TPT for matching against PD of region entry being accessed. */
+ pseudo_bit_t reserved0[0x00005];
+ pseudo_bit_t xlation_en[0x00001]; /* When cleared, address is physical address and no translation will be done. When set, address is virtual. */
+ pseudo_bit_t reserved1[0x00002];
+/* -------------- */
+};
+
+/* INIT_HCA & QUERY_HCA Parameters Block ####michal-doesn't match PRM (see differs below) new size in bytes:0x300 */
+
+struct hermonprm_init_hca_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00018];
+ pseudo_bit_t version[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00040];
+/* -------------- */
+ pseudo_bit_t reserved2[0x00010];
+ pseudo_bit_t hca_core_clock[0x00010];/* Internal Clock freq in MHz */
+/* -------------- */
+ pseudo_bit_t router_qp[0x00018]; /* QP number for router mode (8 LSBits should be 0). Low order 8 bits are taken from the TClass field of the incoming packet.
+ Valid only if RE bit is set */
+ pseudo_bit_t reserved3[0x00005];
+ pseudo_bit_t ipr2[0x00001]; /* Hermon New. IP router on port 2 */
+ pseudo_bit_t ipr1[0x00001]; /* Hermon New. IP router on port 1 */
+ pseudo_bit_t ibr[0x00001]; /* InfiniBand Router Mode */
+/* -------------- */
+ pseudo_bit_t udp[0x00001]; /* UD Port Check Enable
+ 0 - Port field in Address Vector is ignored
+ 1 - HCA will check the port field in AV entry (fetched for UD descriptor) against the Port of the UD QP executing the descriptor. */
+ pseudo_bit_t he[0x00001]; /* Host Endianess - Used for Atomic Operations
+ 0 - Host is Little Endian
+ 1 - Host is Big endian
+ */
+ pseudo_bit_t reserved4[0x00001];
+ pseudo_bit_t ce[0x00001]; /* Checksum Enabled - when Set IPoverIB checksum generation & checking is enabled */
+ pseudo_bit_t reserved5[0x0001c];
+/* -------------- */
+ pseudo_bit_t reserved6[0x00040];
+/* -------------- */
+ struct hermonprm_qpcbaseaddr_st qpc_eec_cqc_eqc_rdb_parameters;/* ## michal - this field has chenged to - "qpc_cqc_eqc_parameters" - gdror, this is ok for now */
+/* -------------- */
+ pseudo_bit_t reserved7[0x00100];
+/* -------------- */
+ struct hermonprm_multicastparam_st multicast_parameters;/* ##michal- this field has chenged to - "IBUD/IPv6_multicast_parameters" - gdror - this is OK for now */
+/* -------------- */
+ pseudo_bit_t reserved8[0x00080];
+/* -------------- */
+ struct hermonprm_tptparams_st tpt_parameters;
+/* -------------- */
+ pseudo_bit_t reserved9[0x00080];
+/* -------------- */
+ struct hermonprm_uar_params_st uar_parameters;/* UAR Parameters */
+/* -------------- */
+ pseudo_bit_t reserved10[0x00600];
+/* -------------- */
+};
+
+/* Event Queue Context Table Entry #### michal - gdror fixed */
+
+struct hermonprm_eqc_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t st[0x00004]; /* Event delivery state machine
+ 0x9 - Armed
+ 0xA - Fired
+ 0xB - Always_Armed (auto-rearm)
+ other - reserved */
+ pseudo_bit_t reserved1[0x00005];
+ pseudo_bit_t oi[0x00001]; /* Oerrun ignore.
+ If set, HW will not check EQ full condition when writing new EQEs. */
+ pseudo_bit_t ec[0x00001]; /* is set, all EQEs are written (coalesced) to first EQ entry */
+ pseudo_bit_t reserved2[0x00009];
+ pseudo_bit_t status[0x00004]; /* EQ status:
+ 0000 - OK
+ 1010 - EQ write failure
+ Valid for the QUERY_EQ and HW2SW_EQ commands only */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved4[0x00005];
+ pseudo_bit_t page_offset[0x00007]; /* offset bits[11:5] of first EQE in the EQ relative to the first page in memory region mapping this EQ */
+ pseudo_bit_t reserved5[0x00014];
+/* -------------- */
+ pseudo_bit_t reserved6[0x00018];
+ pseudo_bit_t log_eq_size[0x00005]; /* Log (base 2) of the EQ size (in entries). Maximum EQ size is 2^22 EQEs (max log_eq_size is 22) */
+ pseudo_bit_t reserved7[0x00003];
+/* -------------- */
+ pseudo_bit_t eq_max_count[0x00010]; /* Event Generation Moderation counter */
+ pseudo_bit_t eq_period[0x00010]; /* Event Generation moderation timed, microseconds */
+/* -------------- */
+ pseudo_bit_t intr[0x0000a]; /* MSI-X table entry index to be used to signal interrupts on this EQ. Reserved if MSI-X are not enabled in the PCI configuration header. */
+ pseudo_bit_t reserved8[0x00016];
+/* -------------- */
+ pseudo_bit_t mtt_base_addr_h[0x00008];/* MTT Base Address [39:32] relative to INIT_HCA.mtt_base_addr */
+ pseudo_bit_t reserved9[0x00010];
+ pseudo_bit_t log2_page_size[0x00006];/* Log (base 2) of MTT page size in units of 4KByte */
+ pseudo_bit_t reserved10[0x00002];
+/* -------------- */
+ pseudo_bit_t reserved11[0x00003];
+ pseudo_bit_t mtt_base_addr_l[0x0001d];/* MTT Base Address [31:3] relative to INIT_HCA.mtt_base_addr */
+/* -------------- */
+ pseudo_bit_t reserved12[0x00040];
+/* -------------- */
+ pseudo_bit_t consumer_counter[0x00018];/* Consumer counter. The counter is incremented for each EQE polled from the EQ.
+ Must be 0x0 in EQ initialization.
+ Maintained by HW (valid for the QUERY_EQ command only). */
+ pseudo_bit_t reserved13[0x00008];
+/* -------------- */
+ pseudo_bit_t producer_counter[0x00018];/* Producer Coutner. The counter is incremented for each EQE that is written by the HW to the EQ.
+ EQ overrun is reported if Producer_counter + 1 equals to Consumer_counter and a EQE needs to be added.
+ Maintained by HW (valid for the QUERY_EQ command only) */
+ pseudo_bit_t reserved14[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved15[0x00080];
+/* -------------- */
+};
+
+/* Memory Translation Table (MTT) Entry #### michal - match to PRM */
+
+struct hermonprm_mtt_st { /* Little Endian */
+ pseudo_bit_t ptag_h[0x00020]; /* High-order bits of physical tag. The size of the field depends on the page size of the region. Maximum PTAG size is 52 bits. */
+/* -------------- */
+ pseudo_bit_t p[0x00001]; /* Present bit. If set, page entry is valid. If cleared, access to this page will generate non-present page access fault. */
+ pseudo_bit_t reserved0[0x00002];
+ pseudo_bit_t ptag_l[0x0001d]; /* Low-order bits of Physical tag. The size of the field depends on the page size of the region. Maximum PTAG size is 52 bits. */
+/* -------------- */
+};
+
+/* Memory Protection Table (MPT) Entry ### doesn't match PRM (new fields were added). new size in bytes : 0x54 */
+
+struct hermonprm_mpt_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t r_w[0x00001]; /* Defines whether this entry is Region (1) or Window (0) */
+ pseudo_bit_t pa[0x00001]; /* Physical address. If set, no virtual-to-physical address translation is performed for this region */
+ pseudo_bit_t lr[0x00001]; /* If set - local read access is enabled. Must be set for all MPT Entries. */
+ pseudo_bit_t lw[0x00001]; /* If set - local write access is enabled */
+ pseudo_bit_t rr[0x00001]; /* If set - remote read access is enabled. */
+ pseudo_bit_t rw[0x00001]; /* If set - remote write access is enabled */
+ pseudo_bit_t atomic[0x00001]; /* If set - remote Atomic access is allowed. */
+ pseudo_bit_t eb[0x00001]; /* If set - bind is enabled. Valid only for regions. */
+ pseudo_bit_t atc_req[0x00001]; /* If set, second hop of address translation (PA to MA) to be performed in the device prior to issuing the uplink request. */
+ pseudo_bit_t atc_xlated[0x00001]; /* If set, uplink cycle to be issues with “ATC_translated” indicator to force bypass of the chipset IOMMU. */
+ pseudo_bit_t reserved1[0x00001];
+ pseudo_bit_t no_snoop[0x00001]; /* If set, issue PCIe cycle with ûno Snoopÿ attribute - cycle not to be snooped in CPU caches */
+ pseudo_bit_t reserved2[0x00008];
+ pseudo_bit_t status[0x00004]; /* 0xF - Not Valid 0x3 - Free. else - HW ownership.Unbound Type1 windows are denoted by reg_wnd_len=0. Unbound Type II windows are denoted by Status = Free. */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00007];
+ pseudo_bit_t bqp[0x00001]; /* 0 - not bound to qp (type 1 window, MR)1 - bound to qp (type 2 window) */
+ pseudo_bit_t qpn[0x00018]; /* QP number this MW is attached to. Valid for type2 memory windows and on QUERY_MPT only */
+/* -------------- */
+ pseudo_bit_t mem_key[0x00020]; /* The memory Key. The field holds the mem_key field in the following semantics: {key[7:0],key[31:8]}. */
+/* -------------- */
+ pseudo_bit_t pd[0x00018]; /* Protection Domain. If VMM support is enabled PD[17:23] specify Guest VM Identifier */
+ pseudo_bit_t en_rinv[0x00001]; /* Enable remote invalidation */
+ pseudo_bit_t ei[0x00001]; /* Enable Invalidation - When set, Local/Remote invalidation can be executed on this window/region. Must be set for type2 windows and non-shared physical memory regions. Must be clear for regions that are used to access Work Queues, Completion Queues and Event Queues */
+ pseudo_bit_t nce[0x00001]; /* Data can be cached in Network Cache (see ûNetwork Cacheÿ on page 81) */
+ pseudo_bit_t fre[0x00001]; /* When set, Fast Registration Operations can be executed on this region */
+ pseudo_bit_t rae[0x00001]; /* When set, remote access can be enabled on this region. Used when executing Fast Registration Work Request to validate that remote access rights can be granted to this MPT. If the bit is cleared, Fast Registration Work Request requesting remote access rights will fail */
+ pseudo_bit_t w_dif[0x00001]; /* Wire space contains dif */
+ pseudo_bit_t m_dif[0x00001]; /* Memory space contains dif */
+ pseudo_bit_t reserved4[0x00001];
+/* -------------- */
+ pseudo_bit_t start_addr_h[0x00020]; /* Start Address - Virtual Address where this region/window starts */
+/* -------------- */
+ pseudo_bit_t start_addr_l[0x00020]; /* Start Address - Virtual Address where this region/window starts */
+/* -------------- */
+ pseudo_bit_t len_h[0x00020]; /* Region/Window Length */
+/* -------------- */
+ pseudo_bit_t len_l[0x00020]; /* Region/Window Length */
+/* -------------- */
+ pseudo_bit_t lkey[0x00020]; /* Must be 0 for SW2HW_MPT. On QUERY_MPT and HW2SW_MPT commands for Memory Window it reflects the LKey of the Region that the Window is bound to.The field holds the lkey field in the following semantics: {key[7:0],key[31:8]}. */
+/* -------------- */
+ pseudo_bit_t win_cnt[0x00018]; /* Number of windows bound to this region. Valid for regions only.The field is valid only for the QUERY_MPT and HW2SW_MPT commands. */
+ pseudo_bit_t reserved5[0x00008];
+/* -------------- */
+ pseudo_bit_t mtt_rep[0x00004]; /* Log (base 2) of the number of time an MTT is replicated.E.g. for 64KB virtual blocks from 512B blocks, a replication factor of 2^7 is needed (MTT_REPLICATION_FACTOR=7).Up to 1MB of replicated block works */
+ pseudo_bit_t reserved6[0x00011];
+ pseudo_bit_t block_mode[0x00001]; /* If set, the page size is not power of two, and entity_size is in bytes. */
+ pseudo_bit_t len64[0x00001]; /* Region/Window Length[64]. This bit added to enable registering 2^64 bytes per region */
+ pseudo_bit_t fbo_en[0x00001]; /* If set, mtt_fbo field is valid, otherwise it is calculated from least significant bytes of the address. Must be set when mtt_rep is used or MPT is block-mode region */
+ pseudo_bit_t reserved7[0x00008];
+/* -------------- */
+ pseudo_bit_t mtt_adr_h[0x00008]; /* Offset to MTT list for this region. Must be aligned on 8 bytes. */
+ pseudo_bit_t reserved8[0x00018];
+/* -------------- */
+ pseudo_bit_t mtt_adr_l[0x00020]; /* Offset to MTT list for this region. Must be aligned on 8 bytes.###michal-relpaced with: RESERVED .3;mtt_adr_l .29; gdror - this is OK to leave it this way. */
+/* -------------- */
+ pseudo_bit_t mtt_size[0x00020]; /* Number of MTT entries allocated for this MR.When Fast Registration Operations cannot be executed on this region (FRE bit is zero) this field is reserved.When Fast Registration Operation is enabled (FRE bit is set) this field indicates the number of MTTs allocated for this MR. If mtt_sz value cannot be zero. */
+/* -------------- */
+ pseudo_bit_t entity_size[0x00015]; /* Page/block size. If MPT maps pages, the page size is 2entiry_size. If MPT maps blocks, the entity_size field specifies block size in bytes. The minimum amount of memory that can be mapped with single MTT is 512 bytes. */
+ pseudo_bit_t reserved9[0x0000b];
+/* -------------- */
+ pseudo_bit_t mtt_fbo[0x00015]; /* First byte offset in the zero-based region - the first byte within the first block/page start address refers to. When mtt_rep is being used, fbo points within the replicated block (i.e. block-size x 2^mtt_rep) */
+ pseudo_bit_t reserved10[0x0000b];
+/* -------------- */
+};
+
+/* Completion Queue Context Table Entry #### michal - match PRM */
+
+struct hermonprm_completion_queue_context_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t st[0x00004]; /* Event delivery state machine
+ 0x0 - reserved
+ 0x9 - ARMED (Request for Notification)
+ 0x6 - ARMED SOLICITED (Request Solicited Notification)
+ 0xA - FIRED
+ other - reserved
+
+ Must be 0x0 in CQ initialization.
+ Valid for the QUERY_CQ and HW2SW_CQ commands only. */
+ pseudo_bit_t reserved1[0x00005];
+ pseudo_bit_t oi[0x00001]; /* When set, overrun ignore is enabled.
+ When set, Updates of CQ consumer counter (poll for completion) or Request completion notifications (Arm CQ) doorbells should not be rang on that CQ. */
+ pseudo_bit_t cc[0x00001]; /* is set, all CQEs are written (coalesced) to first CQ entry */
+ pseudo_bit_t reserved2[0x00009];
+ pseudo_bit_t status[0x00004]; /* CQ status
+ 0000 - OK
+ 1001 - CQ overflow
+ 1010 - CQ write failure
+ Valid for the QUERY_CQ and HW2SW_CQ commands only */
+/* -------------- */
+ pseudo_bit_t reserved3[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved4[0x00005];
+ pseudo_bit_t page_offset[0x00007]; /* offset of first CQE in the CQ relative to the first page in memory region mapping this CQ */
+ pseudo_bit_t reserved5[0x00014];
+/* -------------- */
+ pseudo_bit_t usr_page[0x00018]; /* UAR page this CQ can be accessed through (ringinig CQ doorbells) */
+ pseudo_bit_t log_cq_size[0x00005]; /* Log (base 2) of the CQ size (in entries).
+ Maximum CQ size is 2^17 CQEs (max log_cq_size is 17) */
+ pseudo_bit_t reserved6[0x00003];
+/* -------------- */
+ pseudo_bit_t cq_max_count[0x00010]; /* Event Generation Moderation counter */
+ pseudo_bit_t cq_period[0x00010]; /* Event Generation moderation timed, microseconds */
+/* -------------- */
+ pseudo_bit_t c_eqn[0x00009]; /* Event Queue this CQ reports completion events to.
+ Valid values are 0 to 63
+ If configured to value other than 0-63, completion events will not be reported on the CQ. */
+ pseudo_bit_t reserved7[0x00017];
+/* -------------- */
+ pseudo_bit_t mtt_base_addr_h[0x00008];/* MTT Base Address [39:32] in ICM relative to INIT_HCA.mtt_base_addr */
+ pseudo_bit_t reserved8[0x00010];
+ pseudo_bit_t log2_page_size[0x00006];
+ pseudo_bit_t reserved9[0x00002];
+/* -------------- */
+ pseudo_bit_t reserved10[0x00003];
+ pseudo_bit_t mtt_base_addr_l[0x0001d];/* MTT Base Address [31:3] in ICM relative to INIT_HCA.mtt_base_addr */
+/* -------------- */
+ pseudo_bit_t last_notified_indx[0x00018];/* Maintained by HW.
+ Valid for QUERY_CQ and HW2SW_CQ commands only. */
+ pseudo_bit_t reserved11[0x00008];
+/* -------------- */
+ pseudo_bit_t solicit_producer_indx[0x00018];/* Maintained by HW.
+ Valid for QUERY_CQ and HW2SW_CQ commands only.
+ */
+ pseudo_bit_t reserved12[0x00008];
+/* -------------- */
+ pseudo_bit_t consumer_counter[0x00018];/* Consumer counter is a 32bits counter that is incremented for each CQE pooled from the CQ.
+ */
+ pseudo_bit_t reserved13[0x00008];
+/* -------------- */
+ pseudo_bit_t producer_counter[0x00018];/* Producer counter is a 32bits counter that is incremented for each CQE that is written by the HW to the CQ.
+ CQ overrun is reported if Producer_counter + 1 equals to Consumer_counter and a CQE needs to be added..
+ Maintained by HW (valid for the QUERY_CQ and HW2SW_CQ commands only) */
+ pseudo_bit_t reserved14[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved15[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved16[0x00020];
+/* -------------- */
+ pseudo_bit_t db_record_addr_h[0x00020];/* CQ DB Record physical address [63:32] */
+/* -------------- */
+ pseudo_bit_t reserved17[0x00003];
+ pseudo_bit_t db_record_addr_l[0x0001d];/* CQ DB Record physical address [31:3] */
+/* -------------- */
+};
+
+/* GPIO_event_data #### michal - gdror fixed */
+
+struct hermonprm_gpio_event_data_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00060];
+/* -------------- */
+ pseudo_bit_t gpio_event_hi[0x00020];/* If any bit is set to 1, then a rising/falling event has occurred on the corrsponding GPIO pin. */
+/* -------------- */
+ pseudo_bit_t gpio_event_lo[0x00020];/* If any bit is set to 1, then a rising/falling event has occurred on the corrsponding GPIO pin. */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00020];
+/* -------------- */
+};
+
+/* Event_data Field - QP/EE Events #### michal - doesn't match PRM */
+
+struct hermonprm_qp_ee_event_st { /* Little Endian */
+ pseudo_bit_t qpn_een[0x00018]; /* QP/EE/SRQ number event is reported for ###michal - field changed to QP number */
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved2[0x0001c];
+ pseudo_bit_t e_q[0x00001]; /* If set - EEN if cleared - QP in the QPN/EEN field
+ Not valid on SRQ events ###michal - field replaced with RESERVED */
+ pseudo_bit_t reserved3[0x00003];
+/* -------------- */
+ pseudo_bit_t reserved4[0x00060];
+/* -------------- */
+};
+
+/* InfiniHost-III-EX Type0 Configuration Header ####michal - doesn't match PRM (new fields added, see below) */
+
+struct hermonprm_mt25208_type0_st { /* Little Endian */
+ pseudo_bit_t vendor_id[0x00010]; /* Hardwired to 0x15B3 */
+ pseudo_bit_t device_id[0x00010]; /* 25208 (decimal) - InfiniHost-III compatible mode
+ 25408 (decimal) - InfiniHost-III EX mode (the mode described in this manual)
+ 25209 (decimal) - Flash burner mode - see Flash burning application note for further details on this mode
+ */
+/* -------------- */
+ pseudo_bit_t command[0x00010]; /* PCI Command Register */
+ pseudo_bit_t status[0x00010]; /* PCI Status Register */
+/* -------------- */
+ pseudo_bit_t revision_id[0x00008];
+ pseudo_bit_t class_code_hca_class_code[0x00018];
+/* -------------- */
+ pseudo_bit_t cache_line_size[0x00008];/* Cache Line Size */
+ pseudo_bit_t latency_timer[0x00008];
+ pseudo_bit_t header_type[0x00008]; /* hardwired to zero */
+ pseudo_bit_t bist[0x00008];
+/* -------------- */
+ pseudo_bit_t bar0_ctrl[0x00004]; /* hard-wired to 0100 */
+ pseudo_bit_t reserved0[0x00010];
+ pseudo_bit_t bar0_l[0x0000c]; /* Lower bits of BAR0 (Device Configuration Space) */
+/* -------------- */
+ pseudo_bit_t bar0_h[0x00020]; /* Upper 32 bits of BAR0 (Device Configuration Space) */
+/* -------------- */
+ pseudo_bit_t bar1_ctrl[0x00004]; /* Hardwired to 1100 */
+ pseudo_bit_t reserved1[0x00010];
+ pseudo_bit_t bar1_l[0x0000c]; /* Lower bits of BAR1 (User Access Region - UAR - space) */
+/* -------------- */
+ pseudo_bit_t bar1_h[0x00020]; /* upper 32 bits of BAR1 (User Access Region - UAR - space) */
+/* -------------- */
+ pseudo_bit_t bar2_ctrl[0x00004]; /* Hardwired to 1100 */
+ pseudo_bit_t reserved2[0x00010];
+ pseudo_bit_t bar2_l[0x0000c]; /* Lower bits of BAR2 - Local Attached Memory if present and enabled. Else zeroed. */
+/* -------------- */
+ pseudo_bit_t bar2_h[0x00020]; /* Upper 32 bits of BAR2 - Local Attached Memory if present and enabled. Else zeroed. */
+/* -------------- */
+ pseudo_bit_t cardbus_cis_pointer[0x00020];
+/* -------------- */
+ pseudo_bit_t subsystem_vendor_id[0x00010];/* Specified by the device NVMEM configuration */
+ pseudo_bit_t subsystem_id[0x00010]; /* Specified by the device NVMEM configuration */
+/* -------------- */
+ pseudo_bit_t expansion_rom_enable[0x00001];/* Expansion ROM Enable. Hardwired to 0 if expansion ROM is disabled in the device NVMEM configuration. */
+ pseudo_bit_t reserved3[0x0000a];
+ pseudo_bit_t expansion_rom_base_address[0x00015];/* Expansion ROM Base Address (upper 21 bit). Hardwired to 0 if expansion ROM is disabled in the device NVMEM configuration. */
+/* -------------- */
+ pseudo_bit_t capabilities_pointer[0x00008];/* Specified by the device NVMEM configuration */
+ pseudo_bit_t reserved4[0x00018];
+/* -------------- */
+ pseudo_bit_t reserved5[0x00020];
+/* -------------- */
+ pseudo_bit_t interrupt_line[0x00008];
+ pseudo_bit_t interrupt_pin[0x00008];
+ pseudo_bit_t min_gnt[0x00008];
+ pseudo_bit_t max_latency[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved6[0x00100];
+/* -------------- */
+ pseudo_bit_t msi_cap_id[0x00008];
+ pseudo_bit_t msi_next_cap_ptr[0x00008];
+ pseudo_bit_t msi_en[0x00001];
+ pseudo_bit_t multiple_msg_cap[0x00003];
+ pseudo_bit_t multiple_msg_en[0x00003];
+ pseudo_bit_t cap_64_bit_addr[0x00001];
+ pseudo_bit_t reserved7[0x00008];
+/* -------------- */
+ pseudo_bit_t msg_addr_l[0x00020];
+/* -------------- */
+ pseudo_bit_t msg_addr_h[0x00020];
+/* -------------- */
+ pseudo_bit_t msg_data[0x00010];
+ pseudo_bit_t reserved8[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved9[0x00080];
+/* -------------- */
+ pseudo_bit_t pm_cap_id[0x00008]; /* Power management capability ID - 01h */
+ pseudo_bit_t pm_next_cap_ptr[0x00008];
+ pseudo_bit_t pm_cap[0x00010]; /* [2:0] Version - 02h
+ [3] PME clock - 0h
+ [4] RsvP
+ [5] Device specific initialization - 0h
+ [8:6] AUX current - 0h
+ [9] D1 support - 0h
+ [10] D2 support - 0h
+ [15:11] PME support - 0h */
+/* -------------- */
+ pseudo_bit_t pm_status_control[0x00010];/* [14:13] - Data scale - 0h */
+ pseudo_bit_t pm_control_status_brdg_ext[0x00008];
+ pseudo_bit_t data[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved10[0x00040];
+/* -------------- */
+ pseudo_bit_t vpd_cap_id[0x00008]; /* 03h */
+ pseudo_bit_t vpd_next_cap_id[0x00008];
+ pseudo_bit_t vpd_address[0x0000f];
+ pseudo_bit_t f[0x00001];
+/* -------------- */
+ pseudo_bit_t vpd_data[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved11[0x00040];
+/* -------------- */
+ pseudo_bit_t pciex_cap_id[0x00008]; /* PCI-Express capability ID - 10h */
+ pseudo_bit_t pciex_next_cap_ptr[0x00008];
+ pseudo_bit_t pciex_cap[0x00010]; /* [3:0] Capability version - 1h
+ [7:4] Device/Port Type - 0h
+ [8] Slot implemented - 0h
+ [13:9] Interrupt message number
+ */
+/* -------------- */
+ pseudo_bit_t device_cap[0x00020]; /* [2:0] Max_Payload_Size supported - 2h
+ [4:3] Phantom Function supported - 0h
+ [5] Extended Tag Filed supported - 0h
+ [8:6] Endpoint L0s Acceptable Latency - TBD
+ [11:9] Endpoint L1 Acceptable Latency - TBD
+ [12] Attention Button Present - configured through InfiniBurn
+ [13] Attention Indicator Present - configured through InfiniBurn
+ [14] Power Indicator Present - configured through InfiniBurn
+ [25:18] Captured Slot Power Limit Value
+ [27:26] Captured Slot Power Limit Scale */
+/* -------------- */
+ pseudo_bit_t device_control[0x00010];
+ pseudo_bit_t device_status[0x00010];
+/* -------------- */
+ pseudo_bit_t link_cap[0x00020]; /* [3:0] Maximum Link Speed - 1h
+ [9:4] Maximum Link Width - 8h
+ [11:10] Active State Power Management Support - 3h
+ [14:12] L0s Exit Latency - TBD
+ [17:15] L1 Exit Latency - TBD
+ [31:24] Port Number - 0h */
+/* -------------- */
+ pseudo_bit_t link_control[0x00010];
+ pseudo_bit_t link_status[0x00010]; /* [3:0] Link Speed - 1h
+ [9:4] Negotiated Link Width
+ [12] Slot clock configuration - 1h */
+/* -------------- */
+ pseudo_bit_t reserved12[0x00260];
+/* -------------- */
+ pseudo_bit_t advanced_error_reporting_cap_id[0x00010];/* 0001h. */
+ pseudo_bit_t capability_version[0x00004];/* 1h */
+ pseudo_bit_t next_capability_offset[0x0000c];/* 0h */
+/* -------------- */
+ pseudo_bit_t uncorrectable_error_status_register[0x00020];/* 0 Training Error Status
+ 4 Data Link Protocol Error Status
+ 12 Poisoned TLP Status
+ 13 Flow Control Protocol Error Status
+ 14 Completion Timeout Status
+ 15 Completer Abort Status
+ 16 Unexpected Completion Status
+ 17 Receiver Overflow Status
+ 18 Malformed TLP Status
+ 19 ECRC Error Status
+ 20 Unsupported Request Error Status */
+/* -------------- */
+ pseudo_bit_t uncorrectable_error_mask_register[0x00020];/* 0 Training Error Mask
+ 4 Data Link Protocol Error Mask
+ 12 Poisoned TLP Mask
+ 13 Flow Control Protocol Error Mask
+ 14 Completion Timeout Mask
+ 15 Completer Abort Mask
+ 16 Unexpected Completion Mask
+ 17 Receiver Overflow Mask
+ 18 Malformed TLP Mask
+ 19 ECRC Error Mask
+ 20 Unsupported Request Error Mask */
+/* -------------- */
+ pseudo_bit_t uncorrectable_severity_mask_register[0x00020];/* 0 Training Error Severity
+ 4 Data Link Protocol Error Severity
+ 12 Poisoned TLP Severity
+ 13 Flow Control Protocol Error Severity
+ 14 Completion Timeout Severity
+ 15 Completer Abort Severity
+ 16 Unexpected Completion Severity
+ 17 Receiver Overflow Severity
+ 18 Malformed TLP Severity
+ 19 ECRC Error Severity
+ 20 Unsupported Request Error Severity */
+/* -------------- */
+ pseudo_bit_t correctable_error_status_register[0x00020];/* 0 Receiver Error Status
+ 6 Bad TLP Status
+ 7 Bad DLLP Status
+ 8 REPLAY_NUM Rollover Status
+ 12 Replay Timer Timeout Status */
+/* -------------- */
+ pseudo_bit_t correctable_error_mask_register[0x00020];/* 0 Receiver Error Mask
+ 6 Bad TLP Mask
+ 7 Bad DLLP Mask
+ 8 REPLAY_NUM Rollover Mask
+ 12 Replay Timer Timeout Mask */
+/* -------------- */
+ pseudo_bit_t advance_error_capabilities_and_control_register[0x00020];
+/* -------------- */
+ struct hermonprm_header_log_register_st header_log_register;
+/* -------------- */
+ pseudo_bit_t reserved13[0x006a0];
+/* -------------- */
+};
+
+/* Event Data Field - Performance Monitor */
+
+struct hermonprm_performance_monitor_event_st { /* Little Endian */
+ struct hermonprm_performance_monitors_st performance_monitor_snapshot;/* Performance monitor snapshot */
+/* -------------- */
+ pseudo_bit_t monitor_number[0x00008];/* 0x01 - SQPC
+ 0x02 - RQPC
+ 0x03 - CQC
+ 0x04 - Rkey
+ 0x05 - TLB
+ 0x06 - port0
+ 0x07 - port1 */
+ pseudo_bit_t reserved0[0x00018];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00040];
+/* -------------- */
+};
+
+/* Event_data Field - Page Faults */
+
+struct hermonprm_page_fault_event_data_st { /* Little Endian */
+ pseudo_bit_t va_h[0x00020]; /* Virtual Address[63:32] this page fault is reported on */
+/* -------------- */
+ pseudo_bit_t va_l[0x00020]; /* Virtual Address[63:32] this page fault is reported on */
+/* -------------- */
+ pseudo_bit_t mem_key[0x00020]; /* Memory Key this page fault is reported on */
+/* -------------- */
+ pseudo_bit_t qp[0x00018]; /* QP this page fault is reported on */
+ pseudo_bit_t reserved0[0x00003];
+ pseudo_bit_t a[0x00001]; /* If set the memory access that caused the page fault was atomic */
+ pseudo_bit_t lw[0x00001]; /* If set the memory access that caused the page fault was local write */
+ pseudo_bit_t lr[0x00001]; /* If set the memory access that caused the page fault was local read */
+ pseudo_bit_t rw[0x00001]; /* If set the memory access that caused the page fault was remote write */
+ pseudo_bit_t rr[0x00001]; /* If set the memory access that caused the page fault was remote read */
+/* -------------- */
+ pseudo_bit_t pd[0x00018]; /* PD this page fault is reported on */
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t prefetch_len[0x00020]; /* Indicates how many subsequent pages in the same memory region/window will be accessed by the following transaction after this page fault is resolved. measured in bytes. SW can use this information in order to page-in the subsequent pages if they are not present. */
+/* -------------- */
+};
+
+/* WQE segments format */
+
+struct hermonprm_wqe_segment_st { /* Little Endian */
+ struct hermonprm_send_wqe_segment_st send_wqe_segment;/* Send WQE segment format */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00280];
+/* -------------- */
+ struct hermonprm_wqe_segment_ctrl_mlx_st mlx_wqe_segment_ctrl;/* MLX WQE segment format */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00100];
+/* -------------- */
+ pseudo_bit_t recv_wqe_segment_ctrl[4][0x00020];/* Receive segment format */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00080];
+/* -------------- */
+};
+
+/* Event_data Field - Port State Change #### michal - match PRM */
+
+struct hermonprm_port_state_change_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00040];
+/* -------------- */
+ pseudo_bit_t reserved1[0x0001c];
+ pseudo_bit_t p[0x00002]; /* Port number (1 or 2) */
+ pseudo_bit_t reserved2[0x00002];
+/* -------------- */
+ pseudo_bit_t reserved3[0x00060];
+/* -------------- */
+};
+
+/* Event_data Field - Completion Queue Error #### michal - match PRM */
+
+struct hermonprm_completion_queue_error_st { /* Little Endian */
+ pseudo_bit_t cqn[0x00018]; /* CQ number event is reported for */
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved1[0x00020];
+/* -------------- */
+ pseudo_bit_t syndrome[0x00008]; /* Error syndrome
+ 0x01 - CQ overrun
+ 0x02 - CQ access violation error */
+ pseudo_bit_t reserved2[0x00018];
+/* -------------- */
+ pseudo_bit_t reserved3[0x00060];
+/* -------------- */
+};
+
+/* Event_data Field - Completion Event #### michal - match PRM */
+
+struct hermonprm_completion_event_st { /* Little Endian */
+ pseudo_bit_t cqn[0x00018]; /* CQ number event is reported for */
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved1[0x000a0];
+/* -------------- */
+};
+
+/* Event Queue Entry #### michal - match to PRM */
+
+struct hermonprm_event_queue_entry_st { /* Little Endian */
+ pseudo_bit_t event_sub_type[0x00008];/* Event Sub Type.
+ Defined for events which have sub types, zero elsewhere. */
+ pseudo_bit_t reserved0[0x00008];
+ pseudo_bit_t event_type[0x00008]; /* Event Type */
+ pseudo_bit_t reserved1[0x00008];
+/* -------------- */
+ pseudo_bit_t event_data[6][0x00020];/* Delivers auxilary data to handle event. */
+/* -------------- */
+ pseudo_bit_t reserved2[0x00007];
+ pseudo_bit_t owner[0x00001]; /* Owner of the entry
+ 0 SW
+ 1 HW */
+ pseudo_bit_t reserved3[0x00018];
+/* -------------- */
+};
+
+/* QP/EE State Transitions Command Parameters ###michal - doesn't match PRM (field name changed) */
+
+struct hermonprm_qp_ee_state_transitions_st { /* Little Endian */
+ pseudo_bit_t opt_param_mask[0x00020];/* This field defines which optional parameters are passed. Each bit specifies whether optional parameter is passed (set) or not (cleared). The optparammask is defined for each QP/EE command. */
+/* -------------- */
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+ struct hermonprm_queue_pair_ee_context_entry_st qpc_eec_data;/* QPC/EEC data ###michal - field has replaced with "qpc_data" (size .1948) */
+/* -------------- */
+ pseudo_bit_t reserved1[0x00800];
+/* -------------- */
+};
+
+/* Completion Queue Entry Format #### michal - fixed by gdror */
+
+struct hermonprm_completion_queue_entry_st { /* Little Endian */
+ pseudo_bit_t qpn[0x00018]; /* Indicates the QP for which completion is being reported */
+ pseudo_bit_t reserved0[0x00002];
+ pseudo_bit_t d2s[0x00001]; /* Duplicate to Sniffer. This bit is set if both Send and Receive queues are subject for sniffer queue. The HW delivers
+ packet only to send-associated sniffer receive queue. */
+ pseudo_bit_t fcrc_sd[0x00001]; /* FCRC: If set, FC CRC is correct in FC frame encapsulated in payload. Valid for Raw Frame FC receive queue only.
+ SD: CQ associated with Sniffer receive queue. If set, packets were skipped due to lack of receive buffers on the Sniffer receive queue */
+ pseudo_bit_t fl[0x00001]; /* Force Loopback Valid for responder RawEth and UD only. */
+ pseudo_bit_t vlan[0x00002]; /* Valid for RawEth and UD over Ethernet only. Applicable for RawEth and UD over Ethernet Receive queue
+ 00 - No VLAN header was present in the packet
+ 01 - C-VLAN (802.1q) Header was present in the frame.
+ 10 - S-VLAN (802.1ad) Header was present in the frame. */
+ pseudo_bit_t dife[0x00001]; /* DIF Error */
+/* -------------- */
+ pseudo_bit_t immediate_rssvalue_invalidatekey[0x00020];/* For a responder CQE, if completed WQE Opcode is Send With Immediate or Write With Immediate, this field contains immediate field of the received message.
+ For a responder CQE, if completed WQE Opcode is Send With Invalidate, this field contains the R_key that was invalidated.
+ For a responder CQE of a GSI packet this filed contains the Pkey Index of the packet.
+ For IPoIB (UD) and RawEth CQEs this field contains the RSS hash function value.
+ Otherwise, this field is reserved. */
+/* -------------- */
+ pseudo_bit_t srq_rqpn[0x00018]; /* For Responder UD QPs, Remote (source) QP number.
+ For Responder SRC QPs, SRQ number.
+ Otherwise, this field is reserved. */
+ pseudo_bit_t ml_path_mac_index[0x00007];/* For responder UD over IB CQE: These are the lower LMC bits of the DLID in an incoming UD packet, higher bits of this field, that are not part of the LMC bits are zeroed by HW. Invalid if incoming message DLID is the permissive LID or incoming message is multicast.
+ For responder UD over Ethernet and RawEth CQEs: Index of the MAC Table entry that the packet DMAC was matched against.
+ Otherwise, this field is reserved. */
+ pseudo_bit_t g[0x00001]; /* For responder UD over IB CQE this bit indicates the presence of a GRH
+ For responder UD over Ethernet CQE this bit is set if IPv6 L3 header was present in the packet, this bit is cleared if IPv4 L3 Header was present in the packet.
+ Otherwise, this field is reserved. */
+/* -------------- */
+ pseudo_bit_t slid_smac47_32[0x00010];/* For responder UD over IB CQE it is the source LID of the packet.
+ For responder UD over Ethernet and RawEth CQEs it is the source-MAC[47:32] of the packet.
+ Otherwise, this field is reserved. */
+ pseudo_bit_t vid[0x0000c]; /* Frame VID, valid for Responder Raw Ethernet and UD over Ethernet QP. Otherwise, this field is reserved. */
+ pseudo_bit_t sl[0x00004]; /* For responder UD over IB - the Service Level of the packet.
+ For responder UD over Ethernet and RawEth - it is VLAN-header[15:12]
+ Otherwise, this field is reserved. */
+/* -------------- */
+ pseudo_bit_t smac31_0_rawether_ipoib_status[0x00020];/* For responder UD over Ethernet - source MAC[31:0] of the packet.
+ For responder RawEth and UD over IB - RawEth-IPoIB status {3 reserved, ipok,udp,tcp,ipv4opt,ipv6,ipv4vf,ipv4,rht(6),ipv6extmask(6),reserved(2),l2am,reserved(2),bfcs,reserved(2),enc}
+ Otherwise, this field is reserved. */
+/* -------------- */
+ pseudo_bit_t byte_cnt[0x00020]; /* Byte count of data transferred. Applicable for RDMA-read, Atomic and all receive operations. completions.
+ For Receive Queue that is subject for headers. separation, byte_cnt[31:24] specify number of bytes scattered to the first scatter entry (headers. length). Byte_cnt[23:0] specify total byte count received (including headers). */
+/* -------------- */
+ pseudo_bit_t checksum[0x00010]; /* Valid for RawEth and IPoIB only. */
+ pseudo_bit_t wqe_counter[0x00010];
+/* -------------- */
+ pseudo_bit_t opcode[0x00005]; /* Send completions - same encoding as WQE.
+ Error coding is 0x1F
+ Receive:
+ 0x0 - RDMA-Write with Immediate
+ 0x1 - Send
+ 0x2 - Send with Immediate
+ 0x3 - Send & Invalidate
+ */
+ pseudo_bit_t is[0x00001]; /* inline scatter */
+ pseudo_bit_t s_r[0x00001]; /* send 1 / receive 0 */
+ pseudo_bit_t owner[0x00001]; /* HW Flips this bit for every CQ warp around. Initialized to Zero. */
+ pseudo_bit_t reserved1[0x00010];
+ pseudo_bit_t reserved2[0x00008];
+/* -------------- */
+};
+
+/* */
+
+struct hermonprm_mcg_qps_st { /* Little Endian */
+ struct hermonprm_mcg_qp_dw_st dw[128];
+/* -------------- */
+};
+
+/* */
+
+struct hermonprm_mcg_hdr_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00006];
+ pseudo_bit_t next_mcg[0x0001a];
+/* -------------- */
+ pseudo_bit_t members_count[0x00018];
+ pseudo_bit_t member_remove[0x00001];
+ pseudo_bit_t reserved1[0x00005];
+ pseudo_bit_t protocol[0x00002];
+/* -------------- */
+ pseudo_bit_t reserved2[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved3[0x00020];
+/* -------------- */
+ pseudo_bit_t gid3[0x00020];
+/* -------------- */
+ pseudo_bit_t gid2[0x00020];
+/* -------------- */
+ pseudo_bit_t gid1[0x00020];
+/* -------------- */
+ pseudo_bit_t gid0[0x00020];
+/* -------------- */
+};
+
+/* */
+
+struct hermonprm_sched_queue_context_st { /* Little Endian */
+ pseudo_bit_t policy[0x00003]; /* Schedule Queue Policy - 0 - LLSQ, 1 - GBSQ, 2 - BESQ */
+ pseudo_bit_t vl15[0x00001];
+ pseudo_bit_t sl[0x00004]; /* SL this Schedule Queue is associated with (if vl15 bit is 0) */
+ pseudo_bit_t port[0x00002]; /* Port this Schedule Queue is associated with */
+ pseudo_bit_t reserved0[0x00006];
+ pseudo_bit_t weight[0x00010]; /* Weight of this SchQ */
+/* -------------- */
+};
+
+/* */
+
+struct hermonprm_ecc_detect_event_data_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00080];
+/* -------------- */
+ pseudo_bit_t cause_lsb[0x00001];
+ pseudo_bit_t reserved1[0x00002];
+ pseudo_bit_t cause_msb[0x00001];
+ pseudo_bit_t reserved2[0x00002];
+ pseudo_bit_t err_rmw[0x00001];
+ pseudo_bit_t err_src_id[0x00003];
+ pseudo_bit_t err_da[0x00002];
+ pseudo_bit_t err_ba[0x00002];
+ pseudo_bit_t reserved3[0x00011];
+ pseudo_bit_t overflow[0x00001];
+/* -------------- */
+ pseudo_bit_t err_ra[0x00010];
+ pseudo_bit_t err_ca[0x00010];
+/* -------------- */
+};
+
+/* Event_data Field - ECC Detection Event */
+
+struct hermonprm_scrubbing_event_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00080];
+/* -------------- */
+ pseudo_bit_t cause_lsb[0x00001]; /* data integrity error cause:
+ single ECC error in the 64bit lsb data, on the rise edge of the clock */
+ pseudo_bit_t reserved1[0x00002];
+ pseudo_bit_t cause_msb[0x00001]; /* data integrity error cause:
+ single ECC error in the 64bit msb data, on the fall edge of the clock */
+ pseudo_bit_t reserved2[0x00002];
+ pseudo_bit_t err_rmw[0x00001]; /* transaction type:
+ 0 - read
+ 1 - read/modify/write */
+ pseudo_bit_t err_src_id[0x00003]; /* source of the transaction: 0x4 - PCI, other - internal or IB */
+ pseudo_bit_t err_da[0x00002]; /* Error DIMM address */
+ pseudo_bit_t err_ba[0x00002]; /* Error bank address */
+ pseudo_bit_t reserved3[0x00011];
+ pseudo_bit_t overflow[0x00001]; /* Fatal: ECC error FIFO overflow - ECC errors were detected, which may or may not have been corrected by InfiniHost-III-EX */
+/* -------------- */
+ pseudo_bit_t err_ra[0x00010]; /* Error row address */
+ pseudo_bit_t err_ca[0x00010]; /* Error column address */
+/* -------------- */
+};
+
+/* */
+
+struct hermonprm_eq_cmd_doorbell_st { /* Little Endian */
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+};
+
+/* 0 */
+
+struct hermonprm_hermon_prm_st { /* Little Endian */
+ struct hermonprm_completion_queue_entry_st completion_queue_entry;/* Completion Queue Entry Format */
+/* -------------- */
+ pseudo_bit_t reserved0[0x7ff00];
+/* -------------- */
+ struct hermonprm_qp_ee_state_transitions_st qp_ee_state_transitions;/* QP/EE State Transitions Command Parameters */
+/* -------------- */
+ pseudo_bit_t reserved1[0x7f000];
+/* -------------- */
+ struct hermonprm_event_queue_entry_st event_queue_entry;/* Event Queue Entry */
+/* -------------- */
+ pseudo_bit_t reserved2[0x7ff00];
+/* -------------- */
+ struct hermonprm_completion_event_st completion_event;/* Event_data Field - Completion Event */
+/* -------------- */
+ pseudo_bit_t reserved3[0x7ff40];
+/* -------------- */
+ struct hermonprm_completion_queue_error_st completion_queue_error;/* Event_data Field - Completion Queue Error */
+/* -------------- */
+ pseudo_bit_t reserved4[0x7ff40];
+/* -------------- */
+ struct hermonprm_port_state_change_st port_state_change;/* Event_data Field - Port State Change */
+/* -------------- */
+ pseudo_bit_t reserved5[0x7ff40];
+/* -------------- */
+ struct hermonprm_wqe_segment_st wqe_segment;/* WQE segments format */
+/* -------------- */
+ pseudo_bit_t reserved6[0x7f000];
+/* -------------- */
+ struct hermonprm_page_fault_event_data_st page_fault_event_data;/* Event_data Field - Page Faults */
+/* -------------- */
+ pseudo_bit_t reserved7[0x7ff40];
+/* -------------- */
+ struct hermonprm_performance_monitor_event_st performance_monitor_event;/* Event Data Field - Performance Monitor */
+/* -------------- */
+ pseudo_bit_t reserved8[0xfff20];
+/* -------------- */
+ struct hermonprm_mt25208_type0_st mt25208_type0;/* InfiniHost-III-EX Type0 Configuration Header */
+/* -------------- */
+ pseudo_bit_t reserved9[0x7f000];
+/* -------------- */
+ struct hermonprm_qp_ee_event_st qp_ee_event;/* Event_data Field - QP/EE Events */
+/* -------------- */
+ pseudo_bit_t reserved10[0x00040];
+/* -------------- */
+ struct hermonprm_gpio_event_data_st gpio_event_data;
+/* -------------- */
+ pseudo_bit_t reserved11[0x7fe40];
+/* -------------- */
+ struct hermonprm_ud_address_vector_st ud_address_vector;/* UD Address Vector */
+/* -------------- */
+ pseudo_bit_t reserved12[0x7ff00];
+/* -------------- */
+ struct hermonprm_queue_pair_ee_context_entry_st queue_pair_ee_context_entry;/* QP and EE Context Entry */
+/* -------------- */
+ pseudo_bit_t reserved13[0x7f840];
+/* -------------- */
+ struct hermonprm_address_path_st address_path;/* Address Path */
+/* -------------- */
+ pseudo_bit_t reserved14[0x7fea0];
+/* -------------- */
+ struct hermonprm_completion_queue_context_st completion_queue_context;/* Completion Queue Context Table Entry */
+/* -------------- */
+ pseudo_bit_t reserved15[0x7fe00];
+/* -------------- */
+ struct hermonprm_mpt_st mpt; /* Memory Protection Table (MPT) Entry */
+/* -------------- */
+ pseudo_bit_t reserved16[0x7fe00];
+/* -------------- */
+ struct hermonprm_mtt_st mtt; /* Memory Translation Table (MTT) Entry */
+/* -------------- */
+ pseudo_bit_t reserved17[0x7ffc0];
+/* -------------- */
+ struct hermonprm_eqc_st eqc; /* Event Queue Context Table Entry */
+/* -------------- */
+ pseudo_bit_t reserved18[0x7fe00];
+/* -------------- */
+ struct hermonprm_performance_monitors_st performance_monitors;/* Performance Monitors */
+/* -------------- */
+ pseudo_bit_t reserved19[0x7ff80];
+/* -------------- */
+ struct hermonprm_hca_command_register_st hca_command_register;/* HCA Command Register (HCR) */
+/* -------------- */
+ pseudo_bit_t reserved20[0xfff20];
+/* -------------- */
+ struct hermonprm_init_hca_st init_hca;/* INIT_HCA & QUERY_HCA Parameters Block */
+/* -------------- */
+ pseudo_bit_t reserved21[0x7f000];
+/* -------------- */
+ struct hermonprm_qpcbaseaddr_st qpcbaseaddr;/* QPC/EEC/CQC/EQC/RDB Parameters */
+/* -------------- */
+ pseudo_bit_t reserved22[0x7fc00];
+/* -------------- */
+ struct hermonprm_udavtable_memory_parameters_st udavtable_memory_parameters;/* Memory Access Parameters for UD Address Vector Table */
+/* -------------- */
+ pseudo_bit_t reserved23[0x7ffc0];
+/* -------------- */
+ struct hermonprm_multicastparam_st multicastparam;/* Multicast Support Parameters */
+/* -------------- */
+ pseudo_bit_t reserved24[0x7ff00];
+/* -------------- */
+ struct hermonprm_tptparams_st tptparams;/* Translation and Protection Tables Parameters */
+/* -------------- */
+ pseudo_bit_t reserved25[0x7ff00];
+/* -------------- */
+ pseudo_bit_t reserved26[0x00800];
+/* -------------- */
+ pseudo_bit_t reserved27[0x00100];
+/* -------------- */
+ pseudo_bit_t reserved28[0x7f700];
+/* -------------- */
+ pseudo_bit_t reserved29[0x00100];
+/* -------------- */
+ pseudo_bit_t reserved30[0x7ff00];
+/* -------------- */
+ struct hermonprm_query_fw_st query_fw;/* QUERY_FW Parameters Block */
+/* -------------- */
+ pseudo_bit_t reserved31[0x7f800];
+/* -------------- */
+ struct hermonprm_query_adapter_st query_adapter;/* QUERY_ADAPTER Parameters Block */
+/* -------------- */
+ pseudo_bit_t reserved32[0x7f800];
+/* -------------- */
+ struct hermonprm_query_dev_cap_st query_dev_cap;/* Query Device Limitations */
+/* -------------- */
+ pseudo_bit_t reserved33[0x7f800];
+/* -------------- */
+ struct hermonprm_uar_params_st uar_params;/* UAR Parameters */
+/* -------------- */
+ pseudo_bit_t reserved34[0x7ff00];
+/* -------------- */
+ struct hermonprm_init_port_st init_port;/* INIT_PORT Parameters */
+/* -------------- */
+ pseudo_bit_t reserved35[0x7f800];
+/* -------------- */
+ struct hermonprm_mgm_entry_st mgm_entry;/* Multicast Group Member */
+/* -------------- */
+ pseudo_bit_t reserved36[0x7fe00];
+/* -------------- */
+ struct hermonprm_set_ib_st set_ib; /* SET_IB Parameters */
+/* -------------- */
+ pseudo_bit_t reserved37[0x7fe00];
+/* -------------- */
+ struct hermonprm_rd_send_doorbell_st rd_send_doorbell;/* RD-send doorbell */
+/* -------------- */
+ pseudo_bit_t reserved38[0x7ff80];
+/* -------------- */
+ struct hermonprm_send_doorbell_st send_doorbell;/* Send doorbell */
+/* -------------- */
+ pseudo_bit_t reserved39[0x7ffc0];
+/* -------------- */
+ struct hermonprm_receive_doorbell_st receive_doorbell;/* Receive doorbell */
+/* -------------- */
+ pseudo_bit_t reserved40[0x7ffc0];
+/* -------------- */
+ struct hermonprm_cq_cmd_doorbell_st cq_cmd_doorbell;/* CQ Doorbell */
+/* -------------- */
+ pseudo_bit_t reserved41[0xfffc0];
+/* -------------- */
+ struct hermonprm_uar_st uar; /* User Access Region */
+/* -------------- */
+ pseudo_bit_t reserved42[0x7c000];
+/* -------------- */
+ struct hermonprm_mgmqp_st mgmqp; /* Multicast Group Member QP */
+/* -------------- */
+ pseudo_bit_t reserved43[0x7ffe0];
+/* -------------- */
+ struct hermonprm_query_debug_msg_st query_debug_msg;/* Query Debug Message */
+/* -------------- */
+ pseudo_bit_t reserved44[0x7f800];
+/* -------------- */
+ struct hermonprm_mad_ifc_st mad_ifc; /* MAD_IFC Input Mailbox */
+/* -------------- */
+ pseudo_bit_t reserved45[0x00900];
+/* -------------- */
+ struct hermonprm_mad_ifc_input_modifier_st mad_ifc_input_modifier;/* MAD_IFC Input Modifier */
+/* -------------- */
+ pseudo_bit_t reserved46[0x7e6e0];
+/* -------------- */
+ struct hermonprm_resize_cq_st resize_cq;/* Resize CQ Input Mailbox */
+/* -------------- */
+ pseudo_bit_t reserved47[0x7fe00];
+/* -------------- */
+ struct hermonprm_completion_with_error_st completion_with_error;/* Completion with Error CQE */
+/* -------------- */
+ pseudo_bit_t reserved48[0x7ff00];
+/* -------------- */
+ struct hermonprm_hcr_completion_event_st hcr_completion_event;/* Event_data Field - HCR Completion Event */
+/* -------------- */
+ pseudo_bit_t reserved49[0x7ff40];
+/* -------------- */
+ struct hermonprm_transport_and_ci_error_counters_st transport_and_ci_error_counters;/* Transport and CI Error Counters */
+/* -------------- */
+ pseudo_bit_t reserved50[0x7f000];
+/* -------------- */
+ struct hermonprm_performance_counters_st performance_counters;/* Performance Counters */
+/* -------------- */
+ pseudo_bit_t reserved51[0x9ff800];
+/* -------------- */
+ struct hermonprm_fast_registration_segment_st fast_registration_segment;/* Fast Registration Segment */
+/* -------------- */
+ pseudo_bit_t reserved52[0x7ff00];
+/* -------------- */
+ struct hermonprm_pbl_st pbl; /* Physical Buffer List */
+/* -------------- */
+ pseudo_bit_t reserved53[0x7ff00];
+/* -------------- */
+ struct hermonprm_srq_context_st srq_context;/* SRQ Context */
+/* -------------- */
+ pseudo_bit_t reserved54[0x7fe80];
+/* -------------- */
+ struct hermonprm_mod_stat_cfg_st mod_stat_cfg;/* MOD_STAT_CFG */
+/* -------------- */
+ pseudo_bit_t reserved55[0x7f800];
+/* -------------- */
+ struct hermonprm_virtual_physical_mapping_st virtual_physical_mapping;/* Virtual and Physical Mapping */
+/* -------------- */
+ pseudo_bit_t reserved56[0x7ff80];
+/* -------------- */
+ struct hermonprm_cq_ci_db_record_st cq_ci_db_record;/* CQ_CI_DB_Record */
+/* -------------- */
+ pseudo_bit_t reserved57[0x7ffc0];
+/* -------------- */
+ struct hermonprm_cq_arm_db_record_st cq_arm_db_record;/* CQ_ARM_DB_Record */
+/* -------------- */
+ pseudo_bit_t reserved58[0x7ffc0];
+/* -------------- */
+ struct hermonprm_qp_db_record_st qp_db_record;/* QP_DB_Record */
+/* -------------- */
+ pseudo_bit_t reserved59[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved60[0x1fffc0];
+/* -------------- */
+ struct hermonprm_configuration_registers_st configuration_registers;/* InfiniHost III EX Configuration Registers */
+/* -------------- */
+ struct hermonprm_eq_set_ci_table_st eq_set_ci_table;/* EQ Set CI DBs Table */
+/* -------------- */
+ pseudo_bit_t reserved61[0x01000];
+/* -------------- */
+ pseudo_bit_t reserved62[0x00040];
+/* -------------- */
+ pseudo_bit_t reserved63[0x00fc0];
+/* -------------- */
+ struct hermonprm_clr_int_st clr_int; /* Clear Interrupt Register */
+/* -------------- */
+ pseudo_bit_t reserved64[0xffcfc0];
+/* -------------- */
+};
+#endif /* H_prefix_hermonprm_bits_fixnames_MT25408_PRM_csp_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/arbel.c b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/arbel.c
new file mode 100644
index 00000000..0a801856
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/arbel.c
@@ -0,0 +1,3096 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * Based in part upon the original driver by Mellanox Technologies
+ * Ltd. Portions may be Copyright (c) Mellanox Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/io.h>
+#include <ipxe/pci.h>
+#include <ipxe/pcibackup.h>
+#include <ipxe/malloc.h>
+#include <ipxe/umalloc.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/ib_smc.h>
+#include "arbel.h"
+
+/**
+ * @file
+ *
+ * Mellanox Arbel Infiniband HCA
+ *
+ */
+
+/***************************************************************************
+ *
+ * Queue number allocation
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Allocate offset within usage bitmask
+ *
+ * @v bits Usage bitmask
+ * @v bits_len Length of usage bitmask
+ * @ret bit First free bit within bitmask, or negative error
+ */
+static int arbel_bitmask_alloc ( arbel_bitmask_t *bits,
+ unsigned int bits_len ) {
+ unsigned int bit = 0;
+ arbel_bitmask_t mask = 1;
+
+ while ( bit < bits_len ) {
+ if ( ( mask & *bits ) == 0 ) {
+ *bits |= mask;
+ return bit;
+ }
+ bit++;
+ mask = ( mask << 1 ) | ( mask >> ( 8 * sizeof ( mask ) - 1 ) );
+ if ( mask == 1 )
+ bits++;
+ }
+ return -ENFILE;
+}
+
+/**
+ * Free offset within usage bitmask
+ *
+ * @v bits Usage bitmask
+ * @v bit Bit within bitmask
+ */
+static void arbel_bitmask_free ( arbel_bitmask_t *bits, int bit ) {
+ arbel_bitmask_t mask;
+
+ mask = ( 1 << ( bit % ( 8 * sizeof ( mask ) ) ) );
+ bits += ( bit / ( 8 * sizeof ( mask ) ) );
+ *bits &= ~mask;
+}
+
+/***************************************************************************
+ *
+ * HCA commands
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Wait for Arbel command completion
+ *
+ * @v arbel Arbel device
+ * @ret rc Return status code
+ */
+static int arbel_cmd_wait ( struct arbel *arbel,
+ struct arbelprm_hca_command_register *hcr ) {
+ unsigned int wait;
+
+ for ( wait = ARBEL_HCR_MAX_WAIT_MS ; wait ; wait-- ) {
+ hcr->u.dwords[6] =
+ readl ( arbel->config + ARBEL_HCR_REG ( 6 ) );
+ if ( MLX_GET ( hcr, go ) == 0 )
+ return 0;
+ mdelay ( 1 );
+ }
+ return -EBUSY;
+}
+
+/**
+ * Issue HCA command
+ *
+ * @v arbel Arbel device
+ * @v command Command opcode, flags and input/output lengths
+ * @v op_mod Opcode modifier (0 if no modifier applicable)
+ * @v in Input parameters
+ * @v in_mod Input modifier (0 if no modifier applicable)
+ * @v out Output parameters
+ * @ret rc Return status code
+ */
+static int arbel_cmd ( struct arbel *arbel, unsigned long command,
+ unsigned int op_mod, const void *in,
+ unsigned int in_mod, void *out ) {
+ struct arbelprm_hca_command_register hcr;
+ unsigned int opcode = ARBEL_HCR_OPCODE ( command );
+ size_t in_len = ARBEL_HCR_IN_LEN ( command );
+ size_t out_len = ARBEL_HCR_OUT_LEN ( command );
+ void *in_buffer;
+ void *out_buffer;
+ unsigned int status;
+ unsigned int i;
+ int rc;
+
+ assert ( in_len <= ARBEL_MBOX_SIZE );
+ assert ( out_len <= ARBEL_MBOX_SIZE );
+
+ DBGC2 ( arbel, "Arbel %p command %02x in %zx%s out %zx%s\n",
+ arbel, opcode, in_len,
+ ( ( command & ARBEL_HCR_IN_MBOX ) ? "(mbox)" : "" ), out_len,
+ ( ( command & ARBEL_HCR_OUT_MBOX ) ? "(mbox)" : "" ) );
+
+ /* Check that HCR is free */
+ if ( ( rc = arbel_cmd_wait ( arbel, &hcr ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p command interface locked\n", arbel );
+ return rc;
+ }
+
+ /* Prepare HCR */
+ memset ( &hcr, 0, sizeof ( hcr ) );
+ in_buffer = &hcr.u.dwords[0];
+ if ( in_len && ( command & ARBEL_HCR_IN_MBOX ) ) {
+ in_buffer = arbel->mailbox_in;
+ MLX_FILL_H ( &hcr, 0, in_param_h, virt_to_bus ( in_buffer ) );
+ MLX_FILL_1 ( &hcr, 1, in_param_l, virt_to_bus ( in_buffer ) );
+ }
+ memcpy ( in_buffer, in, in_len );
+ MLX_FILL_1 ( &hcr, 2, input_modifier, in_mod );
+ out_buffer = &hcr.u.dwords[3];
+ if ( out_len && ( command & ARBEL_HCR_OUT_MBOX ) ) {
+ out_buffer = arbel->mailbox_out;
+ MLX_FILL_H ( &hcr, 3, out_param_h,
+ virt_to_bus ( out_buffer ) );
+ MLX_FILL_1 ( &hcr, 4, out_param_l,
+ virt_to_bus ( out_buffer ) );
+ }
+ MLX_FILL_3 ( &hcr, 6,
+ opcode, opcode,
+ opcode_modifier, op_mod,
+ go, 1 );
+ DBGC ( arbel, "Arbel %p issuing command %04x\n", arbel, opcode );
+ DBGC2_HDA ( arbel, virt_to_phys ( arbel->config + ARBEL_HCR_BASE ),
+ &hcr, sizeof ( hcr ) );
+ if ( in_len && ( command & ARBEL_HCR_IN_MBOX ) ) {
+ DBGC2 ( arbel, "Input mailbox:\n" );
+ DBGC2_HDA ( arbel, virt_to_phys ( in_buffer ), in_buffer,
+ ( ( in_len < 512 ) ? in_len : 512 ) );
+ }
+
+ /* Issue command */
+ for ( i = 0 ; i < ( sizeof ( hcr ) / sizeof ( hcr.u.dwords[0] ) ) ;
+ i++ ) {
+ writel ( hcr.u.dwords[i],
+ arbel->config + ARBEL_HCR_REG ( i ) );
+ barrier();
+ }
+
+ /* Wait for command completion */
+ if ( ( rc = arbel_cmd_wait ( arbel, &hcr ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p timed out waiting for command:\n",
+ arbel );
+ DBGC_HD ( arbel, &hcr, sizeof ( hcr ) );
+ return rc;
+ }
+
+ /* Check command status */
+ status = MLX_GET ( &hcr, status );
+ if ( status != 0 ) {
+ DBGC ( arbel, "Arbel %p command failed with status %02x:\n",
+ arbel, status );
+ DBGC_HD ( arbel, &hcr, sizeof ( hcr ) );
+ return -EIO;
+ }
+
+ /* Read output parameters, if any */
+ hcr.u.dwords[3] = readl ( arbel->config + ARBEL_HCR_REG ( 3 ) );
+ hcr.u.dwords[4] = readl ( arbel->config + ARBEL_HCR_REG ( 4 ) );
+ memcpy ( out, out_buffer, out_len );
+ if ( out_len ) {
+ DBGC2 ( arbel, "Output%s:\n",
+ ( command & ARBEL_HCR_OUT_MBOX ) ? " mailbox" : "" );
+ DBGC2_HDA ( arbel, virt_to_phys ( out_buffer ), out_buffer,
+ ( ( out_len < 512 ) ? out_len : 512 ) );
+ }
+
+ return 0;
+}
+
+static inline int
+arbel_cmd_query_dev_lim ( struct arbel *arbel,
+ struct arbelprm_query_dev_lim *dev_lim ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_OUT_CMD ( ARBEL_HCR_QUERY_DEV_LIM,
+ 1, sizeof ( *dev_lim ) ),
+ 0, NULL, 0, dev_lim );
+}
+
+static inline int
+arbel_cmd_query_fw ( struct arbel *arbel, struct arbelprm_query_fw *fw ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_OUT_CMD ( ARBEL_HCR_QUERY_FW,
+ 1, sizeof ( *fw ) ),
+ 0, NULL, 0, fw );
+}
+
+static inline int
+arbel_cmd_init_hca ( struct arbel *arbel,
+ const struct arbelprm_init_hca *init_hca ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_INIT_HCA,
+ 1, sizeof ( *init_hca ) ),
+ 0, init_hca, 0, NULL );
+}
+
+static inline int
+arbel_cmd_close_hca ( struct arbel *arbel ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_VOID_CMD ( ARBEL_HCR_CLOSE_HCA ),
+ 0, NULL, 0, NULL );
+}
+
+static inline int
+arbel_cmd_init_ib ( struct arbel *arbel, unsigned int port,
+ const struct arbelprm_init_ib *init_ib ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_INIT_IB,
+ 1, sizeof ( *init_ib ) ),
+ 0, init_ib, port, NULL );
+}
+
+static inline int
+arbel_cmd_close_ib ( struct arbel *arbel, unsigned int port ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_VOID_CMD ( ARBEL_HCR_CLOSE_IB ),
+ 0, NULL, port, NULL );
+}
+
+static inline int
+arbel_cmd_sw2hw_mpt ( struct arbel *arbel, unsigned int index,
+ const struct arbelprm_mpt *mpt ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_SW2HW_MPT,
+ 1, sizeof ( *mpt ) ),
+ 0, mpt, index, NULL );
+}
+
+static inline int
+arbel_cmd_map_eq ( struct arbel *arbel, unsigned long index_map,
+ const struct arbelprm_event_mask *mask ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_MAP_EQ,
+ 0, sizeof ( *mask ) ),
+ 0, mask, index_map, NULL );
+}
+
+static inline int
+arbel_cmd_sw2hw_eq ( struct arbel *arbel, unsigned int index,
+ const struct arbelprm_eqc *eqctx ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_SW2HW_EQ,
+ 1, sizeof ( *eqctx ) ),
+ 0, eqctx, index, NULL );
+}
+
+static inline int
+arbel_cmd_hw2sw_eq ( struct arbel *arbel, unsigned int index,
+ struct arbelprm_eqc *eqctx ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_OUT_CMD ( ARBEL_HCR_HW2SW_EQ,
+ 1, sizeof ( *eqctx ) ),
+ 1, NULL, index, eqctx );
+}
+
+static inline int
+arbel_cmd_sw2hw_cq ( struct arbel *arbel, unsigned long cqn,
+ const struct arbelprm_completion_queue_context *cqctx ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_SW2HW_CQ,
+ 1, sizeof ( *cqctx ) ),
+ 0, cqctx, cqn, NULL );
+}
+
+static inline int
+arbel_cmd_hw2sw_cq ( struct arbel *arbel, unsigned long cqn,
+ struct arbelprm_completion_queue_context *cqctx) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_OUT_CMD ( ARBEL_HCR_HW2SW_CQ,
+ 1, sizeof ( *cqctx ) ),
+ 0, NULL, cqn, cqctx );
+}
+
+static inline int
+arbel_cmd_query_cq ( struct arbel *arbel, unsigned long cqn,
+ struct arbelprm_completion_queue_context *cqctx ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_OUT_CMD ( ARBEL_HCR_QUERY_CQ,
+ 1, sizeof ( *cqctx ) ),
+ 0, NULL, cqn, cqctx );
+}
+
+static inline int
+arbel_cmd_rst2init_qpee ( struct arbel *arbel, unsigned long qpn,
+ const struct arbelprm_qp_ee_state_transitions *ctx ){
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_RST2INIT_QPEE,
+ 1, sizeof ( *ctx ) ),
+ 0, ctx, qpn, NULL );
+}
+
+static inline int
+arbel_cmd_init2rtr_qpee ( struct arbel *arbel, unsigned long qpn,
+ const struct arbelprm_qp_ee_state_transitions *ctx ){
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_INIT2RTR_QPEE,
+ 1, sizeof ( *ctx ) ),
+ 0, ctx, qpn, NULL );
+}
+
+static inline int
+arbel_cmd_rtr2rts_qpee ( struct arbel *arbel, unsigned long qpn,
+ const struct arbelprm_qp_ee_state_transitions *ctx ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_RTR2RTS_QPEE,
+ 1, sizeof ( *ctx ) ),
+ 0, ctx, qpn, NULL );
+}
+
+static inline int
+arbel_cmd_rts2rts_qpee ( struct arbel *arbel, unsigned long qpn,
+ const struct arbelprm_qp_ee_state_transitions *ctx ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_RTS2RTS_QPEE,
+ 1, sizeof ( *ctx ) ),
+ 0, ctx, qpn, NULL );
+}
+
+static inline int
+arbel_cmd_2rst_qpee ( struct arbel *arbel, unsigned long qpn ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_VOID_CMD ( ARBEL_HCR_2RST_QPEE ),
+ 0x03, NULL, qpn, NULL );
+}
+
+static inline int
+arbel_cmd_query_qpee ( struct arbel *arbel, unsigned long qpn,
+ struct arbelprm_qp_ee_state_transitions *ctx ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_OUT_CMD ( ARBEL_HCR_QUERY_QPEE,
+ 1, sizeof ( *ctx ) ),
+ 0, NULL, qpn, ctx );
+}
+
+static inline int
+arbel_cmd_conf_special_qp ( struct arbel *arbel, unsigned int qp_type,
+ unsigned long base_qpn ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_VOID_CMD ( ARBEL_HCR_CONF_SPECIAL_QP ),
+ qp_type, NULL, base_qpn, NULL );
+}
+
+static inline int
+arbel_cmd_mad_ifc ( struct arbel *arbel, unsigned int port,
+ union arbelprm_mad *mad ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_INOUT_CMD ( ARBEL_HCR_MAD_IFC,
+ 1, sizeof ( *mad ),
+ 1, sizeof ( *mad ) ),
+ 0x03, mad, port, mad );
+}
+
+static inline int
+arbel_cmd_read_mgm ( struct arbel *arbel, unsigned int index,
+ struct arbelprm_mgm_entry *mgm ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_OUT_CMD ( ARBEL_HCR_READ_MGM,
+ 1, sizeof ( *mgm ) ),
+ 0, NULL, index, mgm );
+}
+
+static inline int
+arbel_cmd_write_mgm ( struct arbel *arbel, unsigned int index,
+ const struct arbelprm_mgm_entry *mgm ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_WRITE_MGM,
+ 1, sizeof ( *mgm ) ),
+ 0, mgm, index, NULL );
+}
+
+static inline int
+arbel_cmd_mgid_hash ( struct arbel *arbel, const union ib_gid *gid,
+ struct arbelprm_mgm_hash *hash ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_INOUT_CMD ( ARBEL_HCR_MGID_HASH,
+ 1, sizeof ( *gid ),
+ 0, sizeof ( *hash ) ),
+ 0, gid, 0, hash );
+}
+
+static inline int
+arbel_cmd_run_fw ( struct arbel *arbel ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_VOID_CMD ( ARBEL_HCR_RUN_FW ),
+ 0, NULL, 0, NULL );
+}
+
+static inline int
+arbel_cmd_disable_lam ( struct arbel *arbel ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_VOID_CMD ( ARBEL_HCR_DISABLE_LAM ),
+ 0, NULL, 0, NULL );
+}
+
+static inline int
+arbel_cmd_enable_lam ( struct arbel *arbel, struct arbelprm_access_lam *lam ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_OUT_CMD ( ARBEL_HCR_ENABLE_LAM,
+ 1, sizeof ( *lam ) ),
+ 1, NULL, 0, lam );
+}
+
+static inline int
+arbel_cmd_unmap_icm ( struct arbel *arbel, unsigned int page_count,
+ const struct arbelprm_scalar_parameter *offset ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_UNMAP_ICM, 0,
+ sizeof ( *offset ) ),
+ 0, offset, page_count, NULL );
+}
+
+static inline int
+arbel_cmd_map_icm ( struct arbel *arbel,
+ const struct arbelprm_virtual_physical_mapping *map ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_MAP_ICM,
+ 1, sizeof ( *map ) ),
+ 0, map, 1, NULL );
+}
+
+static inline int
+arbel_cmd_unmap_icm_aux ( struct arbel *arbel ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_VOID_CMD ( ARBEL_HCR_UNMAP_ICM_AUX ),
+ 0, NULL, 0, NULL );
+}
+
+static inline int
+arbel_cmd_map_icm_aux ( struct arbel *arbel,
+ const struct arbelprm_virtual_physical_mapping *map ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_MAP_ICM_AUX,
+ 1, sizeof ( *map ) ),
+ 0, map, 1, NULL );
+}
+
+static inline int
+arbel_cmd_set_icm_size ( struct arbel *arbel,
+ const struct arbelprm_scalar_parameter *icm_size,
+ struct arbelprm_scalar_parameter *icm_aux_size ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_INOUT_CMD ( ARBEL_HCR_SET_ICM_SIZE,
+ 0, sizeof ( *icm_size ),
+ 0, sizeof ( *icm_aux_size ) ),
+ 0, icm_size, 0, icm_aux_size );
+}
+
+static inline int
+arbel_cmd_unmap_fa ( struct arbel *arbel ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_VOID_CMD ( ARBEL_HCR_UNMAP_FA ),
+ 0, NULL, 0, NULL );
+}
+
+static inline int
+arbel_cmd_map_fa ( struct arbel *arbel,
+ const struct arbelprm_virtual_physical_mapping *map ) {
+ return arbel_cmd ( arbel,
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_MAP_FA,
+ 1, sizeof ( *map ) ),
+ 0, map, 1, NULL );
+}
+
+/***************************************************************************
+ *
+ * MAD operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Issue management datagram
+ *
+ * @v ibdev Infiniband device
+ * @v mad Management datagram
+ * @ret rc Return status code
+ */
+static int arbel_mad ( struct ib_device *ibdev, union ib_mad *mad ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ union arbelprm_mad mad_ifc;
+ int rc;
+
+ linker_assert ( sizeof ( *mad ) == sizeof ( mad_ifc.mad ),
+ mad_size_mismatch );
+
+ /* Copy in request packet */
+ memcpy ( &mad_ifc.mad, mad, sizeof ( mad_ifc.mad ) );
+
+ /* Issue MAD */
+ if ( ( rc = arbel_cmd_mad_ifc ( arbel, ibdev->port,
+ &mad_ifc ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p port %d could not issue MAD IFC: %s\n",
+ arbel, ibdev->port, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Copy out reply packet */
+ memcpy ( mad, &mad_ifc.mad, sizeof ( *mad ) );
+
+ if ( mad->hdr.status != 0 ) {
+ DBGC ( arbel, "Arbel %p port %d MAD IFC status %04x\n",
+ arbel, ibdev->port, ntohs ( mad->hdr.status ) );
+ return -EIO;
+ }
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * Completion queue operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Dump completion queue context (for debugging only)
+ *
+ * @v arbel Arbel device
+ * @v cq Completion queue
+ * @ret rc Return status code
+ */
+static __attribute__ (( unused )) int
+arbel_dump_cqctx ( struct arbel *arbel, struct ib_completion_queue *cq ) {
+ struct arbelprm_completion_queue_context cqctx;
+ int rc;
+
+ memset ( &cqctx, 0, sizeof ( cqctx ) );
+ if ( ( rc = arbel_cmd_query_cq ( arbel, cq->cqn, &cqctx ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p CQN %#lx QUERY_CQ failed: %s\n",
+ arbel, cq->cqn, strerror ( rc ) );
+ return rc;
+ }
+ DBGC ( arbel, "Arbel %p CQN %#lx context:\n", arbel, cq->cqn );
+ DBGC_HDA ( arbel, 0, &cqctx, sizeof ( cqctx ) );
+
+ return 0;
+}
+
+/**
+ * Create completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ * @ret rc Return status code
+ */
+static int arbel_create_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct arbel_completion_queue *arbel_cq;
+ struct arbelprm_completion_queue_context cqctx;
+ struct arbelprm_cq_ci_db_record *ci_db_rec;
+ struct arbelprm_cq_arm_db_record *arm_db_rec;
+ int cqn_offset;
+ unsigned int i;
+ int rc;
+
+ /* Find a free completion queue number */
+ cqn_offset = arbel_bitmask_alloc ( arbel->cq_inuse, ARBEL_MAX_CQS );
+ if ( cqn_offset < 0 ) {
+ DBGC ( arbel, "Arbel %p out of completion queues\n", arbel );
+ rc = cqn_offset;
+ goto err_cqn_offset;
+ }
+ cq->cqn = ( arbel->limits.reserved_cqs + cqn_offset );
+
+ /* Allocate control structures */
+ arbel_cq = zalloc ( sizeof ( *arbel_cq ) );
+ if ( ! arbel_cq ) {
+ rc = -ENOMEM;
+ goto err_arbel_cq;
+ }
+ arbel_cq->ci_doorbell_idx = arbel_cq_ci_doorbell_idx ( arbel, cq );
+ arbel_cq->arm_doorbell_idx = arbel_cq_arm_doorbell_idx ( arbel, cq );
+
+ /* Allocate completion queue itself */
+ arbel_cq->cqe_size = ( cq->num_cqes * sizeof ( arbel_cq->cqe[0] ) );
+ arbel_cq->cqe = malloc_dma ( arbel_cq->cqe_size,
+ sizeof ( arbel_cq->cqe[0] ) );
+ if ( ! arbel_cq->cqe ) {
+ rc = -ENOMEM;
+ goto err_cqe;
+ }
+ memset ( arbel_cq->cqe, 0, arbel_cq->cqe_size );
+ for ( i = 0 ; i < cq->num_cqes ; i++ ) {
+ MLX_FILL_1 ( &arbel_cq->cqe[i].normal, 7, owner, 1 );
+ }
+ barrier();
+
+ /* Initialise doorbell records */
+ ci_db_rec = &arbel->db_rec[arbel_cq->ci_doorbell_idx].cq_ci;
+ MLX_FILL_1 ( ci_db_rec, 0, counter, 0 );
+ MLX_FILL_2 ( ci_db_rec, 1,
+ res, ARBEL_UAR_RES_CQ_CI,
+ cq_number, cq->cqn );
+ arm_db_rec = &arbel->db_rec[arbel_cq->arm_doorbell_idx].cq_arm;
+ MLX_FILL_1 ( arm_db_rec, 0, counter, 0 );
+ MLX_FILL_2 ( arm_db_rec, 1,
+ res, ARBEL_UAR_RES_CQ_ARM,
+ cq_number, cq->cqn );
+
+ /* Hand queue over to hardware */
+ memset ( &cqctx, 0, sizeof ( cqctx ) );
+ MLX_FILL_1 ( &cqctx, 0, st, 0xa /* "Event fired" */ );
+ MLX_FILL_H ( &cqctx, 1, start_address_h,
+ virt_to_bus ( arbel_cq->cqe ) );
+ MLX_FILL_1 ( &cqctx, 2, start_address_l,
+ virt_to_bus ( arbel_cq->cqe ) );
+ MLX_FILL_2 ( &cqctx, 3,
+ usr_page, arbel->limits.reserved_uars,
+ log_cq_size, fls ( cq->num_cqes - 1 ) );
+ MLX_FILL_1 ( &cqctx, 5, c_eqn, arbel->eq.eqn );
+ MLX_FILL_1 ( &cqctx, 6, pd, ARBEL_GLOBAL_PD );
+ MLX_FILL_1 ( &cqctx, 7, l_key, arbel->lkey );
+ MLX_FILL_1 ( &cqctx, 12, cqn, cq->cqn );
+ MLX_FILL_1 ( &cqctx, 13,
+ cq_ci_db_record, arbel_cq->ci_doorbell_idx );
+ MLX_FILL_1 ( &cqctx, 14,
+ cq_state_db_record, arbel_cq->arm_doorbell_idx );
+ if ( ( rc = arbel_cmd_sw2hw_cq ( arbel, cq->cqn, &cqctx ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p CQN %#lx SW2HW_CQ failed: %s\n",
+ arbel, cq->cqn, strerror ( rc ) );
+ goto err_sw2hw_cq;
+ }
+
+ DBGC ( arbel, "Arbel %p CQN %#lx ring [%08lx,%08lx), doorbell %08lx\n",
+ arbel, cq->cqn, virt_to_phys ( arbel_cq->cqe ),
+ ( virt_to_phys ( arbel_cq->cqe ) + arbel_cq->cqe_size ),
+ virt_to_phys ( ci_db_rec ) );
+ ib_cq_set_drvdata ( cq, arbel_cq );
+ return 0;
+
+ err_sw2hw_cq:
+ MLX_FILL_1 ( ci_db_rec, 1, res, ARBEL_UAR_RES_NONE );
+ MLX_FILL_1 ( arm_db_rec, 1, res, ARBEL_UAR_RES_NONE );
+ free_dma ( arbel_cq->cqe, arbel_cq->cqe_size );
+ err_cqe:
+ free ( arbel_cq );
+ err_arbel_cq:
+ arbel_bitmask_free ( arbel->cq_inuse, cqn_offset );
+ err_cqn_offset:
+ return rc;
+}
+
+/**
+ * Destroy completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+static void arbel_destroy_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq );
+ struct arbelprm_completion_queue_context cqctx;
+ struct arbelprm_cq_ci_db_record *ci_db_rec;
+ struct arbelprm_cq_arm_db_record *arm_db_rec;
+ int cqn_offset;
+ int rc;
+
+ /* Take ownership back from hardware */
+ if ( ( rc = arbel_cmd_hw2sw_cq ( arbel, cq->cqn, &cqctx ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p CQN %#lx FATAL HW2SW_CQ failed: "
+ "%s\n", arbel, cq->cqn, strerror ( rc ) );
+ /* Leak memory and return; at least we avoid corruption */
+ return;
+ }
+
+ /* Clear doorbell records */
+ ci_db_rec = &arbel->db_rec[arbel_cq->ci_doorbell_idx].cq_ci;
+ arm_db_rec = &arbel->db_rec[arbel_cq->arm_doorbell_idx].cq_arm;
+ MLX_FILL_1 ( ci_db_rec, 1, res, ARBEL_UAR_RES_NONE );
+ MLX_FILL_1 ( arm_db_rec, 1, res, ARBEL_UAR_RES_NONE );
+
+ /* Free memory */
+ free_dma ( arbel_cq->cqe, arbel_cq->cqe_size );
+ free ( arbel_cq );
+
+ /* Mark queue number as free */
+ cqn_offset = ( cq->cqn - arbel->limits.reserved_cqs );
+ arbel_bitmask_free ( arbel->cq_inuse, cqn_offset );
+
+ ib_cq_set_drvdata ( cq, NULL );
+}
+
+/***************************************************************************
+ *
+ * Queue pair operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Assign queue pair number
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static int arbel_alloc_qpn ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ unsigned int port_offset;
+ int qpn_offset;
+
+ /* Calculate queue pair number */
+ port_offset = ( ibdev->port - ARBEL_PORT_BASE );
+
+ switch ( qp->type ) {
+ case IB_QPT_SMI:
+ qp->qpn = ( arbel->special_qpn_base + port_offset );
+ return 0;
+ case IB_QPT_GSI:
+ qp->qpn = ( arbel->special_qpn_base + 2 + port_offset );
+ return 0;
+ case IB_QPT_UD:
+ case IB_QPT_RC:
+ /* Find a free queue pair number */
+ qpn_offset = arbel_bitmask_alloc ( arbel->qp_inuse,
+ ARBEL_MAX_QPS );
+ if ( qpn_offset < 0 ) {
+ DBGC ( arbel, "Arbel %p out of queue pairs\n",
+ arbel );
+ return qpn_offset;
+ }
+ qp->qpn = ( ( random() & ARBEL_QPN_RANDOM_MASK ) |
+ ( arbel->qpn_base + qpn_offset ) );
+ return 0;
+ default:
+ DBGC ( arbel, "Arbel %p unsupported QP type %d\n",
+ arbel, qp->type );
+ return -ENOTSUP;
+ }
+}
+
+/**
+ * Free queue pair number
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+static void arbel_free_qpn ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ int qpn_offset;
+
+ qpn_offset = ( ( qp->qpn & ~ARBEL_QPN_RANDOM_MASK ) - arbel->qpn_base );
+ if ( qpn_offset >= 0 )
+ arbel_bitmask_free ( arbel->qp_inuse, qpn_offset );
+}
+
+/**
+ * Calculate transmission rate
+ *
+ * @v av Address vector
+ * @ret arbel_rate Arbel rate
+ */
+static unsigned int arbel_rate ( struct ib_address_vector *av ) {
+ return ( ( ( av->rate >= IB_RATE_2_5 ) && ( av->rate <= IB_RATE_120 ) )
+ ? ( av->rate + 5 ) : 0 );
+}
+
+/** Queue pair transport service type map */
+static uint8_t arbel_qp_st[] = {
+ [IB_QPT_SMI] = ARBEL_ST_MLX,
+ [IB_QPT_GSI] = ARBEL_ST_MLX,
+ [IB_QPT_UD] = ARBEL_ST_UD,
+ [IB_QPT_RC] = ARBEL_ST_RC,
+};
+
+/**
+ * Dump queue pair context (for debugging only)
+ *
+ * @v arbel Arbel device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static __attribute__ (( unused )) int
+arbel_dump_qpctx ( struct arbel *arbel, struct ib_queue_pair *qp ) {
+ struct arbelprm_qp_ee_state_transitions qpctx;
+ int rc;
+
+ memset ( &qpctx, 0, sizeof ( qpctx ) );
+ if ( ( rc = arbel_cmd_query_qpee ( arbel, qp->qpn, &qpctx ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p QPN %#lx QUERY_QPEE failed: %s\n",
+ arbel, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+ DBGC ( arbel, "Arbel %p QPN %#lx context:\n", arbel, qp->qpn );
+ DBGC_HDA ( arbel, 0, &qpctx.u.dwords[2], ( sizeof ( qpctx ) - 8 ) );
+
+ return 0;
+}
+
+/**
+ * Create send work queue
+ *
+ * @v arbel_send_wq Send work queue
+ * @v num_wqes Number of work queue entries
+ * @ret rc Return status code
+ */
+static int arbel_create_send_wq ( struct arbel_send_work_queue *arbel_send_wq,
+ unsigned int num_wqes ) {
+ union arbel_send_wqe *wqe;
+ union arbel_send_wqe *next_wqe;
+ unsigned int wqe_idx_mask;
+ unsigned int i;
+
+ /* Allocate work queue */
+ arbel_send_wq->wqe_size = ( num_wqes *
+ sizeof ( arbel_send_wq->wqe[0] ) );
+ arbel_send_wq->wqe = malloc_dma ( arbel_send_wq->wqe_size,
+ sizeof ( arbel_send_wq->wqe[0] ) );
+ if ( ! arbel_send_wq->wqe )
+ return -ENOMEM;
+ memset ( arbel_send_wq->wqe, 0, arbel_send_wq->wqe_size );
+
+ /* Link work queue entries */
+ wqe_idx_mask = ( num_wqes - 1 );
+ for ( i = 0 ; i < num_wqes ; i++ ) {
+ wqe = &arbel_send_wq->wqe[i];
+ next_wqe = &arbel_send_wq->wqe[ ( i + 1 ) & wqe_idx_mask ];
+ MLX_FILL_1 ( &wqe->next, 0, nda_31_6,
+ ( virt_to_bus ( next_wqe ) >> 6 ) );
+ MLX_FILL_1 ( &wqe->next, 1, always1, 1 );
+ }
+
+ return 0;
+}
+
+/**
+ * Create receive work queue
+ *
+ * @v arbel_recv_wq Receive work queue
+ * @v num_wqes Number of work queue entries
+ * @ret rc Return status code
+ */
+static int arbel_create_recv_wq ( struct arbel_recv_work_queue *arbel_recv_wq,
+ unsigned int num_wqes ) {
+ struct arbelprm_recv_wqe *wqe;
+ struct arbelprm_recv_wqe *next_wqe;
+ unsigned int wqe_idx_mask;
+ size_t nds;
+ unsigned int i;
+ unsigned int j;
+
+ /* Allocate work queue */
+ arbel_recv_wq->wqe_size = ( num_wqes *
+ sizeof ( arbel_recv_wq->wqe[0] ) );
+ arbel_recv_wq->wqe = malloc_dma ( arbel_recv_wq->wqe_size,
+ sizeof ( arbel_recv_wq->wqe[0] ) );
+ if ( ! arbel_recv_wq->wqe )
+ return -ENOMEM;
+ memset ( arbel_recv_wq->wqe, 0, arbel_recv_wq->wqe_size );
+
+ /* Link work queue entries */
+ wqe_idx_mask = ( num_wqes - 1 );
+ nds = ( ( offsetof ( typeof ( *wqe ), data ) +
+ sizeof ( wqe->data[0] ) ) >> 4 );
+ for ( i = 0 ; i < num_wqes ; i++ ) {
+ wqe = &arbel_recv_wq->wqe[i].recv;
+ next_wqe = &arbel_recv_wq->wqe[( i + 1 ) & wqe_idx_mask].recv;
+ MLX_FILL_1 ( &wqe->next, 0, nda_31_6,
+ ( virt_to_bus ( next_wqe ) >> 6 ) );
+ MLX_FILL_1 ( &wqe->next, 1, nds, nds );
+ for ( j = 0 ; ( ( ( void * ) &wqe->data[j] ) <
+ ( ( void * ) ( wqe + 1 ) ) ) ; j++ ) {
+ MLX_FILL_1 ( &wqe->data[j], 1,
+ l_key, ARBEL_INVALID_LKEY );
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Create queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static int arbel_create_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct arbel_queue_pair *arbel_qp;
+ struct arbelprm_qp_ee_state_transitions qpctx;
+ struct arbelprm_qp_db_record *send_db_rec;
+ struct arbelprm_qp_db_record *recv_db_rec;
+ physaddr_t send_wqe_base_adr;
+ physaddr_t recv_wqe_base_adr;
+ physaddr_t wqe_base_adr;
+ int rc;
+
+ /* Warn about dysfunctional code
+ *
+ * Arbel seems to crash the system as soon as the first send
+ * WQE completes on an RC queue pair. (NOPs complete
+ * successfully, so this is a problem specific to the work
+ * queue rather than the completion queue.) The cause of this
+ * problem has remained unknown for over a year. Patches to
+ * fix this are welcome.
+ */
+ if ( qp->type == IB_QPT_RC )
+ DBG ( "*** WARNING: Arbel RC support is non-functional ***\n" );
+
+ /* Calculate queue pair number */
+ if ( ( rc = arbel_alloc_qpn ( ibdev, qp ) ) != 0 )
+ goto err_alloc_qpn;
+
+ /* Allocate control structures */
+ arbel_qp = zalloc ( sizeof ( *arbel_qp ) );
+ if ( ! arbel_qp ) {
+ rc = -ENOMEM;
+ goto err_arbel_qp;
+ }
+ arbel_qp->send.doorbell_idx = arbel_send_doorbell_idx ( arbel, qp );
+ arbel_qp->recv.doorbell_idx = arbel_recv_doorbell_idx ( arbel, qp );
+
+ /* Create send and receive work queues */
+ if ( ( rc = arbel_create_send_wq ( &arbel_qp->send,
+ qp->send.num_wqes ) ) != 0 )
+ goto err_create_send_wq;
+ if ( ( rc = arbel_create_recv_wq ( &arbel_qp->recv,
+ qp->recv.num_wqes ) ) != 0 )
+ goto err_create_recv_wq;
+
+ /* Send and receive work queue entries must be within the same 4GB */
+ send_wqe_base_adr = virt_to_bus ( arbel_qp->send.wqe );
+ recv_wqe_base_adr = virt_to_bus ( arbel_qp->recv.wqe );
+ if ( ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) &&
+ ( ( ( ( uint64_t ) send_wqe_base_adr ) >> 32 ) !=
+ ( ( ( uint64_t ) recv_wqe_base_adr ) >> 32 ) ) ) {
+ DBGC ( arbel, "Arbel %p QPN %#lx cannot support send %08lx "
+ "recv %08lx\n", arbel, qp->qpn,
+ send_wqe_base_adr, recv_wqe_base_adr );
+ rc = -ENOTSUP;
+ goto err_unsupported_address_split;
+ }
+ wqe_base_adr = send_wqe_base_adr;
+
+ /* Initialise doorbell records */
+ send_db_rec = &arbel->db_rec[arbel_qp->send.doorbell_idx].qp;
+ MLX_FILL_1 ( send_db_rec, 0, counter, 0 );
+ MLX_FILL_2 ( send_db_rec, 1,
+ res, ARBEL_UAR_RES_SQ,
+ qp_number, qp->qpn );
+ recv_db_rec = &arbel->db_rec[arbel_qp->recv.doorbell_idx].qp;
+ MLX_FILL_1 ( recv_db_rec, 0, counter, 0 );
+ MLX_FILL_2 ( recv_db_rec, 1,
+ res, ARBEL_UAR_RES_RQ,
+ qp_number, qp->qpn );
+
+ /* Transition queue to INIT state */
+ memset ( &qpctx, 0, sizeof ( qpctx ) );
+ MLX_FILL_3 ( &qpctx, 2,
+ qpc_eec_data.de, 1,
+ qpc_eec_data.pm_state, ARBEL_PM_STATE_MIGRATED,
+ qpc_eec_data.st, arbel_qp_st[qp->type] );
+ MLX_FILL_4 ( &qpctx, 4,
+ qpc_eec_data.log_rq_size, fls ( qp->recv.num_wqes - 1 ),
+ qpc_eec_data.log_rq_stride,
+ ( fls ( sizeof ( arbel_qp->recv.wqe[0] ) - 1 ) - 4 ),
+ qpc_eec_data.log_sq_size, fls ( qp->send.num_wqes - 1 ),
+ qpc_eec_data.log_sq_stride,
+ ( fls ( sizeof ( arbel_qp->send.wqe[0] ) - 1 ) - 4 ) );
+ MLX_FILL_1 ( &qpctx, 5,
+ qpc_eec_data.usr_page, arbel->limits.reserved_uars );
+ MLX_FILL_1 ( &qpctx, 10, qpc_eec_data.primary_address_path.port_number,
+ ibdev->port );
+ MLX_FILL_1 ( &qpctx, 27, qpc_eec_data.pd, ARBEL_GLOBAL_PD );
+ MLX_FILL_H ( &qpctx, 28, qpc_eec_data.wqe_base_adr_h, wqe_base_adr );
+ MLX_FILL_1 ( &qpctx, 29, qpc_eec_data.wqe_lkey, arbel->lkey );
+ MLX_FILL_1 ( &qpctx, 30, qpc_eec_data.ssc, 1 );
+ MLX_FILL_1 ( &qpctx, 33, qpc_eec_data.cqn_snd, qp->send.cq->cqn );
+ MLX_FILL_1 ( &qpctx, 34, qpc_eec_data.snd_wqe_base_adr_l,
+ ( send_wqe_base_adr >> 6 ) );
+ MLX_FILL_1 ( &qpctx, 35, qpc_eec_data.snd_db_record_index,
+ arbel_qp->send.doorbell_idx );
+ MLX_FILL_4 ( &qpctx, 38,
+ qpc_eec_data.rre, 1,
+ qpc_eec_data.rwe, 1,
+ qpc_eec_data.rae, 1,
+ qpc_eec_data.rsc, 1 );
+ MLX_FILL_1 ( &qpctx, 41, qpc_eec_data.cqn_rcv, qp->recv.cq->cqn );
+ MLX_FILL_1 ( &qpctx, 42, qpc_eec_data.rcv_wqe_base_adr_l,
+ ( recv_wqe_base_adr >> 6 ) );
+ MLX_FILL_1 ( &qpctx, 43, qpc_eec_data.rcv_db_record_index,
+ arbel_qp->recv.doorbell_idx );
+ if ( ( rc = arbel_cmd_rst2init_qpee ( arbel, qp->qpn, &qpctx )) != 0 ){
+ DBGC ( arbel, "Arbel %p QPN %#lx RST2INIT_QPEE failed: %s\n",
+ arbel, qp->qpn, strerror ( rc ) );
+ goto err_rst2init_qpee;
+ }
+ arbel_qp->state = ARBEL_QP_ST_INIT;
+
+ DBGC ( arbel, "Arbel %p QPN %#lx send ring [%08lx,%08lx), doorbell "
+ "%08lx\n", arbel, qp->qpn, virt_to_phys ( arbel_qp->send.wqe ),
+ ( virt_to_phys ( arbel_qp->send.wqe ) +
+ arbel_qp->send.wqe_size ),
+ virt_to_phys ( send_db_rec ) );
+ DBGC ( arbel, "Arbel %p QPN %#lx receive ring [%08lx,%08lx), doorbell "
+ "%08lx\n", arbel, qp->qpn, virt_to_phys ( arbel_qp->recv.wqe ),
+ ( virt_to_phys ( arbel_qp->recv.wqe ) +
+ arbel_qp->recv.wqe_size ),
+ virt_to_phys ( recv_db_rec ) );
+ DBGC ( arbel, "Arbel %p QPN %#lx send CQN %#lx receive CQN %#lx\n",
+ arbel, qp->qpn, qp->send.cq->cqn, qp->recv.cq->cqn );
+ ib_qp_set_drvdata ( qp, arbel_qp );
+ return 0;
+
+ arbel_cmd_2rst_qpee ( arbel, qp->qpn );
+ err_rst2init_qpee:
+ MLX_FILL_1 ( send_db_rec, 1, res, ARBEL_UAR_RES_NONE );
+ MLX_FILL_1 ( recv_db_rec, 1, res, ARBEL_UAR_RES_NONE );
+ err_unsupported_address_split:
+ free_dma ( arbel_qp->recv.wqe, arbel_qp->recv.wqe_size );
+ err_create_recv_wq:
+ free_dma ( arbel_qp->send.wqe, arbel_qp->send.wqe_size );
+ err_create_send_wq:
+ free ( arbel_qp );
+ err_arbel_qp:
+ arbel_free_qpn ( ibdev, qp );
+ err_alloc_qpn:
+ return rc;
+}
+
+/**
+ * Modify queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static int arbel_modify_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp );
+ struct arbelprm_qp_ee_state_transitions qpctx;
+ int rc;
+
+ /* Transition queue to RTR state, if applicable */
+ if ( arbel_qp->state < ARBEL_QP_ST_RTR ) {
+ memset ( &qpctx, 0, sizeof ( qpctx ) );
+ MLX_FILL_2 ( &qpctx, 4,
+ qpc_eec_data.mtu, ARBEL_MTU_2048,
+ qpc_eec_data.msg_max, 31 );
+ MLX_FILL_1 ( &qpctx, 7,
+ qpc_eec_data.remote_qpn_een, qp->av.qpn );
+ MLX_FILL_2 ( &qpctx, 11,
+ qpc_eec_data.primary_address_path.rnr_retry,
+ ARBEL_RETRY_MAX,
+ qpc_eec_data.primary_address_path.rlid,
+ qp->av.lid );
+ MLX_FILL_2 ( &qpctx, 12,
+ qpc_eec_data.primary_address_path.ack_timeout,
+ 14 /* 4.096us * 2^(14) = 67ms */,
+ qpc_eec_data.primary_address_path.max_stat_rate,
+ arbel_rate ( &qp->av ) );
+ memcpy ( &qpctx.u.dwords[14], &qp->av.gid,
+ sizeof ( qp->av.gid ) );
+ MLX_FILL_1 ( &qpctx, 30,
+ qpc_eec_data.retry_count, ARBEL_RETRY_MAX );
+ MLX_FILL_1 ( &qpctx, 39,
+ qpc_eec_data.next_rcv_psn, qp->recv.psn );
+ MLX_FILL_1 ( &qpctx, 40,
+ qpc_eec_data.ra_buff_indx,
+ ( arbel->limits.reserved_rdbs +
+ ( ( qp->qpn & ~ARBEL_QPN_RANDOM_MASK ) -
+ arbel->special_qpn_base ) ) );
+ if ( ( rc = arbel_cmd_init2rtr_qpee ( arbel, qp->qpn,
+ &qpctx ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p QPN %#lx INIT2RTR_QPEE failed:"
+ " %s\n", arbel, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+ arbel_qp->state = ARBEL_QP_ST_RTR;
+ }
+
+ /* Transition queue to RTS state, if applicable */
+ if ( arbel_qp->state < ARBEL_QP_ST_RTS ) {
+ memset ( &qpctx, 0, sizeof ( qpctx ) );
+ MLX_FILL_1 ( &qpctx, 11,
+ qpc_eec_data.primary_address_path.rnr_retry,
+ ARBEL_RETRY_MAX );
+ MLX_FILL_1 ( &qpctx, 12,
+ qpc_eec_data.primary_address_path.ack_timeout,
+ 14 /* 4.096us * 2^(14) = 67ms */ );
+ MLX_FILL_2 ( &qpctx, 30,
+ qpc_eec_data.retry_count, ARBEL_RETRY_MAX,
+ qpc_eec_data.sic, 1 );
+ MLX_FILL_1 ( &qpctx, 32,
+ qpc_eec_data.next_send_psn, qp->send.psn );
+ if ( ( rc = arbel_cmd_rtr2rts_qpee ( arbel, qp->qpn,
+ &qpctx ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p QPN %#lx RTR2RTS_QPEE failed: "
+ "%s\n", arbel, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+ arbel_qp->state = ARBEL_QP_ST_RTS;
+ }
+
+ /* Update parameters in RTS state */
+ memset ( &qpctx, 0, sizeof ( qpctx ) );
+ MLX_FILL_1 ( &qpctx, 0, opt_param_mask, ARBEL_QPEE_OPT_PARAM_QKEY );
+ MLX_FILL_1 ( &qpctx, 44, qpc_eec_data.q_key, qp->qkey );
+ if ( ( rc = arbel_cmd_rts2rts_qpee ( arbel, qp->qpn, &qpctx ) ) != 0 ){
+ DBGC ( arbel, "Arbel %p QPN %#lx RTS2RTS_QPEE failed: %s\n",
+ arbel, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Destroy queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+static void arbel_destroy_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp );
+ struct arbelprm_qp_db_record *send_db_rec;
+ struct arbelprm_qp_db_record *recv_db_rec;
+ int rc;
+
+ /* Take ownership back from hardware */
+ if ( ( rc = arbel_cmd_2rst_qpee ( arbel, qp->qpn ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p QPN %#lx FATAL 2RST_QPEE failed: "
+ "%s\n", arbel, qp->qpn, strerror ( rc ) );
+ /* Leak memory and return; at least we avoid corruption */
+ return;
+ }
+
+ /* Clear doorbell records */
+ send_db_rec = &arbel->db_rec[arbel_qp->send.doorbell_idx].qp;
+ recv_db_rec = &arbel->db_rec[arbel_qp->recv.doorbell_idx].qp;
+ MLX_FILL_1 ( send_db_rec, 1, res, ARBEL_UAR_RES_NONE );
+ MLX_FILL_1 ( recv_db_rec, 1, res, ARBEL_UAR_RES_NONE );
+
+ /* Free memory */
+ free_dma ( arbel_qp->send.wqe, arbel_qp->send.wqe_size );
+ free_dma ( arbel_qp->recv.wqe, arbel_qp->recv.wqe_size );
+ free ( arbel_qp );
+
+ /* Mark queue number as free */
+ arbel_free_qpn ( ibdev, qp );
+
+ ib_qp_set_drvdata ( qp, NULL );
+}
+
+/***************************************************************************
+ *
+ * Work request operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Ring doorbell register in UAR
+ *
+ * @v arbel Arbel device
+ * @v db_reg Doorbell register structure
+ * @v offset Address of doorbell
+ */
+static void arbel_ring_doorbell ( struct arbel *arbel,
+ union arbelprm_doorbell_register *db_reg,
+ unsigned int offset ) {
+
+ DBGC2 ( arbel, "Arbel %p ringing doorbell %08x:%08x at %lx\n",
+ arbel, ntohl ( db_reg->dword[0] ), ntohl ( db_reg->dword[1] ),
+ virt_to_phys ( arbel->uar + offset ) );
+
+ barrier();
+ writel ( db_reg->dword[0], ( arbel->uar + offset + 0 ) );
+ barrier();
+ writel ( db_reg->dword[1], ( arbel->uar + offset + 4 ) );
+}
+
+/** GID used for GID-less send work queue entries */
+static const union ib_gid arbel_no_gid = {
+ .bytes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 },
+};
+
+/**
+ * Construct UD send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @v wqe Send work queue entry
+ * @ret nds Work queue entry size
+ */
+static size_t arbel_fill_ud_send_wqe ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp __unused,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf,
+ union arbel_send_wqe *wqe ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ const union ib_gid *gid;
+
+ /* Construct this work queue entry */
+ MLX_FILL_1 ( &wqe->ud.ctrl, 0, always1, 1 );
+ MLX_FILL_2 ( &wqe->ud.ud, 0,
+ ud_address_vector.pd, ARBEL_GLOBAL_PD,
+ ud_address_vector.port_number, ibdev->port );
+ MLX_FILL_2 ( &wqe->ud.ud, 1,
+ ud_address_vector.rlid, av->lid,
+ ud_address_vector.g, av->gid_present );
+ MLX_FILL_2 ( &wqe->ud.ud, 2,
+ ud_address_vector.max_stat_rate, arbel_rate ( av ),
+ ud_address_vector.msg, 3 );
+ MLX_FILL_1 ( &wqe->ud.ud, 3, ud_address_vector.sl, av->sl );
+ gid = ( av->gid_present ? &av->gid : &arbel_no_gid );
+ memcpy ( &wqe->ud.ud.u.dwords[4], gid, sizeof ( *gid ) );
+ MLX_FILL_1 ( &wqe->ud.ud, 8, destination_qp, av->qpn );
+ MLX_FILL_1 ( &wqe->ud.ud, 9, q_key, av->qkey );
+ MLX_FILL_1 ( &wqe->ud.data[0], 0, byte_count, iob_len ( iobuf ) );
+ MLX_FILL_1 ( &wqe->ud.data[0], 1, l_key, arbel->lkey );
+ MLX_FILL_H ( &wqe->ud.data[0], 2,
+ local_address_h, virt_to_bus ( iobuf->data ) );
+ MLX_FILL_1 ( &wqe->ud.data[0], 3,
+ local_address_l, virt_to_bus ( iobuf->data ) );
+
+ return ( offsetof ( typeof ( wqe->ud ), data[1] ) >> 4 );
+}
+
+/**
+ * Construct MLX send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @v wqe Send work queue entry
+ * @v next Previous work queue entry's "next" field
+ * @ret nds Work queue entry size
+ */
+static size_t arbel_fill_mlx_send_wqe ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf,
+ union arbel_send_wqe *wqe ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct io_buffer headers;
+
+ /* Construct IB headers */
+ iob_populate ( &headers, &wqe->mlx.headers, 0,
+ sizeof ( wqe->mlx.headers ) );
+ iob_reserve ( &headers, sizeof ( wqe->mlx.headers ) );
+ ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), av );
+
+ /* Construct this work queue entry */
+ MLX_FILL_5 ( &wqe->mlx.ctrl, 0,
+ c, 1 /* generate completion */,
+ icrc, 0 /* generate ICRC */,
+ max_statrate, arbel_rate ( av ),
+ slr, 0,
+ v15, ( ( qp->ext_qpn == IB_QPN_SMI ) ? 1 : 0 ) );
+ MLX_FILL_1 ( &wqe->mlx.ctrl, 1, rlid, av->lid );
+ MLX_FILL_1 ( &wqe->mlx.data[0], 0,
+ byte_count, iob_len ( &headers ) );
+ MLX_FILL_1 ( &wqe->mlx.data[0], 1, l_key, arbel->lkey );
+ MLX_FILL_H ( &wqe->mlx.data[0], 2,
+ local_address_h, virt_to_bus ( headers.data ) );
+ MLX_FILL_1 ( &wqe->mlx.data[0], 3,
+ local_address_l, virt_to_bus ( headers.data ) );
+ MLX_FILL_1 ( &wqe->mlx.data[1], 0,
+ byte_count, ( iob_len ( iobuf ) + 4 /* ICRC */ ) );
+ MLX_FILL_1 ( &wqe->mlx.data[1], 1, l_key, arbel->lkey );
+ MLX_FILL_H ( &wqe->mlx.data[1], 2,
+ local_address_h, virt_to_bus ( iobuf->data ) );
+ MLX_FILL_1 ( &wqe->mlx.data[1], 3,
+ local_address_l, virt_to_bus ( iobuf->data ) );
+
+ return ( offsetof ( typeof ( wqe->mlx ), data[2] ) >> 4 );
+}
+
+/**
+ * Construct RC send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @v wqe Send work queue entry
+ * @v next Previous work queue entry's "next" field
+ * @ret nds Work queue entry size
+ */
+static size_t arbel_fill_rc_send_wqe ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp __unused,
+ struct ib_address_vector *av __unused,
+ struct io_buffer *iobuf,
+ union arbel_send_wqe *wqe ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+
+ /* Construct this work queue entry */
+ MLX_FILL_1 ( &wqe->rc.ctrl, 0, always1, 1 );
+ MLX_FILL_1 ( &wqe->rc.data[0], 0, byte_count, iob_len ( iobuf ) );
+ MLX_FILL_1 ( &wqe->rc.data[0], 1, l_key, arbel->lkey );
+ MLX_FILL_H ( &wqe->rc.data[0], 2,
+ local_address_h, virt_to_bus ( iobuf->data ) );
+ MLX_FILL_1 ( &wqe->rc.data[0], 3,
+ local_address_l, virt_to_bus ( iobuf->data ) );
+
+ return ( offsetof ( typeof ( wqe->rc ), data[1] ) >> 4 );
+}
+
+/** Work queue entry constructors */
+static size_t
+( * arbel_fill_send_wqe[] ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf,
+ union arbel_send_wqe *wqe ) = {
+ [IB_QPT_SMI] = arbel_fill_mlx_send_wqe,
+ [IB_QPT_GSI] = arbel_fill_mlx_send_wqe,
+ [IB_QPT_UD] = arbel_fill_ud_send_wqe,
+ [IB_QPT_RC] = arbel_fill_rc_send_wqe,
+};
+
+/**
+ * Post send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int arbel_post_send ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp );
+ struct ib_work_queue *wq = &qp->send;
+ struct arbel_send_work_queue *arbel_send_wq = &arbel_qp->send;
+ union arbel_send_wqe *prev_wqe;
+ union arbel_send_wqe *wqe;
+ struct arbelprm_qp_db_record *qp_db_rec;
+ union arbelprm_doorbell_register db_reg;
+ unsigned long wqe_idx_mask;
+ size_t nds;
+
+ /* Allocate work queue entry */
+ wqe_idx_mask = ( wq->num_wqes - 1 );
+ if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) {
+ DBGC ( arbel, "Arbel %p QPN %#lx send queue full",
+ arbel, qp->qpn );
+ return -ENOBUFS;
+ }
+ wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf;
+ prev_wqe = &arbel_send_wq->wqe[(wq->next_idx - 1) & wqe_idx_mask];
+ wqe = &arbel_send_wq->wqe[wq->next_idx & wqe_idx_mask];
+
+ /* Construct work queue entry */
+ memset ( ( ( ( void * ) wqe ) + sizeof ( wqe->next ) ), 0,
+ ( sizeof ( *wqe ) - sizeof ( wqe->next ) ) );
+ assert ( qp->type < ( sizeof ( arbel_fill_send_wqe ) /
+ sizeof ( arbel_fill_send_wqe[0] ) ) );
+ assert ( arbel_fill_send_wqe[qp->type] != NULL );
+ nds = arbel_fill_send_wqe[qp->type] ( ibdev, qp, av, iobuf, wqe );
+ DBGCP ( arbel, "Arbel %p QPN %#lx posting send WQE %#lx:\n",
+ arbel, qp->qpn, ( wq->next_idx & wqe_idx_mask ) );
+ DBGCP_HDA ( arbel, virt_to_phys ( wqe ), wqe, sizeof ( *wqe ) );
+
+ /* Update previous work queue entry's "next" field */
+ MLX_SET ( &prev_wqe->next, nopcode, ARBEL_OPCODE_SEND );
+ MLX_FILL_3 ( &prev_wqe->next, 1,
+ nds, nds,
+ f, 0,
+ always1, 1 );
+
+ /* Update doorbell record */
+ barrier();
+ qp_db_rec = &arbel->db_rec[arbel_send_wq->doorbell_idx].qp;
+ MLX_FILL_1 ( qp_db_rec, 0,
+ counter, ( ( wq->next_idx + 1 ) & 0xffff ) );
+
+ /* Ring doorbell register */
+ MLX_FILL_4 ( &db_reg.send, 0,
+ nopcode, ARBEL_OPCODE_SEND,
+ f, 0,
+ wqe_counter, ( wq->next_idx & 0xffff ),
+ wqe_cnt, 1 );
+ MLX_FILL_2 ( &db_reg.send, 1,
+ nds, nds,
+ qpn, qp->qpn );
+ arbel_ring_doorbell ( arbel, &db_reg, ARBEL_DB_POST_SND_OFFSET );
+
+ /* Update work queue's index */
+ wq->next_idx++;
+
+ return 0;
+}
+
+/**
+ * Post receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int arbel_post_recv ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp );
+ struct ib_work_queue *wq = &qp->recv;
+ struct arbel_recv_work_queue *arbel_recv_wq = &arbel_qp->recv;
+ struct arbelprm_recv_wqe *wqe;
+ union arbelprm_doorbell_record *db_rec;
+ unsigned int wqe_idx_mask;
+
+ /* Allocate work queue entry */
+ wqe_idx_mask = ( wq->num_wqes - 1 );
+ if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) {
+ DBGC ( arbel, "Arbel %p QPN %#lx receive queue full\n",
+ arbel, qp->qpn );
+ return -ENOBUFS;
+ }
+ wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf;
+ wqe = &arbel_recv_wq->wqe[wq->next_idx & wqe_idx_mask].recv;
+
+ /* Construct work queue entry */
+ MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_tailroom ( iobuf ) );
+ MLX_FILL_1 ( &wqe->data[0], 1, l_key, arbel->lkey );
+ MLX_FILL_H ( &wqe->data[0], 2,
+ local_address_h, virt_to_bus ( iobuf->data ) );
+ MLX_FILL_1 ( &wqe->data[0], 3,
+ local_address_l, virt_to_bus ( iobuf->data ) );
+
+ /* Update doorbell record */
+ barrier();
+ db_rec = &arbel->db_rec[arbel_recv_wq->doorbell_idx];
+ MLX_FILL_1 ( &db_rec->qp, 0,
+ counter, ( ( wq->next_idx + 1 ) & 0xffff ) );
+
+ /* Update work queue's index */
+ wq->next_idx++;
+
+ return 0;
+}
+
+/**
+ * Handle completion
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ * @v cqe Hardware completion queue entry
+ * @ret rc Return status code
+ */
+static int arbel_complete ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq,
+ union arbelprm_completion_entry *cqe ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq;
+ struct ib_queue_pair *qp;
+ struct arbel_queue_pair *arbel_qp;
+ struct arbel_send_work_queue *arbel_send_wq;
+ struct arbel_recv_work_queue *arbel_recv_wq;
+ struct arbelprm_recv_wqe *recv_wqe;
+ struct io_buffer *iobuf;
+ struct ib_address_vector recv_av;
+ struct ib_global_route_header *grh;
+ struct ib_address_vector *av;
+ unsigned int opcode;
+ unsigned long qpn;
+ int is_send;
+ unsigned long wqe_adr;
+ unsigned long wqe_idx;
+ size_t len;
+ int rc = 0;
+
+ /* Parse completion */
+ qpn = MLX_GET ( &cqe->normal, my_qpn );
+ is_send = MLX_GET ( &cqe->normal, s );
+ wqe_adr = ( MLX_GET ( &cqe->normal, wqe_adr ) << 6 );
+ opcode = MLX_GET ( &cqe->normal, opcode );
+ if ( opcode >= ARBEL_OPCODE_RECV_ERROR ) {
+ /* "s" field is not valid for error opcodes */
+ is_send = ( opcode == ARBEL_OPCODE_SEND_ERROR );
+ DBGC ( arbel, "Arbel %p CQN %#lx %s QPN %#lx syndrome %#x "
+ "vendor %#x\n", arbel, cq->cqn,
+ ( is_send ? "send" : "recv" ), qpn,
+ MLX_GET ( &cqe->error, syndrome ),
+ MLX_GET ( &cqe->error, vendor_code ) );
+ DBGC_HDA ( arbel, virt_to_phys ( cqe ), cqe, sizeof ( *cqe ) );
+ rc = -EIO;
+ /* Don't return immediately; propagate error to completer */
+ }
+
+ /* Identify work queue */
+ wq = ib_find_wq ( cq, qpn, is_send );
+ if ( ! wq ) {
+ DBGC ( arbel, "Arbel %p CQN %#lx unknown %s QPN %#lx\n",
+ arbel, cq->cqn, ( is_send ? "send" : "recv" ), qpn );
+ return -EIO;
+ }
+ qp = wq->qp;
+ arbel_qp = ib_qp_get_drvdata ( qp );
+ arbel_send_wq = &arbel_qp->send;
+ arbel_recv_wq = &arbel_qp->recv;
+
+ /* Identify work queue entry index */
+ if ( is_send ) {
+ wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_send_wq->wqe ) ) /
+ sizeof ( arbel_send_wq->wqe[0] ) );
+ assert ( wqe_idx < qp->send.num_wqes );
+ } else {
+ wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_recv_wq->wqe ) ) /
+ sizeof ( arbel_recv_wq->wqe[0] ) );
+ assert ( wqe_idx < qp->recv.num_wqes );
+ }
+
+ DBGCP ( arbel, "Arbel %p CQN %#lx QPN %#lx %s WQE %#lx completed:\n",
+ arbel, cq->cqn, qp->qpn, ( is_send ? "send" : "recv" ),
+ wqe_idx );
+ DBGCP_HDA ( arbel, virt_to_phys ( cqe ), cqe, sizeof ( *cqe ) );
+
+ /* Identify I/O buffer */
+ iobuf = wq->iobufs[wqe_idx];
+ if ( ! iobuf ) {
+ DBGC ( arbel, "Arbel %p CQN %#lx QPN %#lx empty %s WQE %#lx\n",
+ arbel, cq->cqn, qp->qpn, ( is_send ? "send" : "recv" ),
+ wqe_idx );
+ return -EIO;
+ }
+ wq->iobufs[wqe_idx] = NULL;
+
+ if ( is_send ) {
+ /* Hand off to completion handler */
+ ib_complete_send ( ibdev, qp, iobuf, rc );
+ } else {
+ /* Set received length */
+ len = MLX_GET ( &cqe->normal, byte_cnt );
+ recv_wqe = &arbel_recv_wq->wqe[wqe_idx].recv;
+ assert ( MLX_GET ( &recv_wqe->data[0], local_address_l ) ==
+ virt_to_bus ( iobuf->data ) );
+ assert ( MLX_GET ( &recv_wqe->data[0], byte_count ) ==
+ iob_tailroom ( iobuf ) );
+ MLX_FILL_1 ( &recv_wqe->data[0], 0, byte_count, 0 );
+ MLX_FILL_1 ( &recv_wqe->data[0], 1,
+ l_key, ARBEL_INVALID_LKEY );
+ assert ( len <= iob_tailroom ( iobuf ) );
+ iob_put ( iobuf, len );
+ switch ( qp->type ) {
+ case IB_QPT_SMI:
+ case IB_QPT_GSI:
+ case IB_QPT_UD:
+ assert ( iob_len ( iobuf ) >= sizeof ( *grh ) );
+ grh = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *grh ) );
+ /* Construct address vector */
+ av = &recv_av;
+ memset ( av, 0, sizeof ( *av ) );
+ av->qpn = MLX_GET ( &cqe->normal, rqpn );
+ av->lid = MLX_GET ( &cqe->normal, rlid );
+ av->sl = MLX_GET ( &cqe->normal, sl );
+ av->gid_present = MLX_GET ( &cqe->normal, g );
+ memcpy ( &av->gid, &grh->sgid, sizeof ( av->gid ) );
+ break;
+ case IB_QPT_RC:
+ av = &qp->av;
+ break;
+ default:
+ assert ( 0 );
+ return -EINVAL;
+ }
+ /* Hand off to completion handler */
+ ib_complete_recv ( ibdev, qp, av, iobuf, rc );
+ }
+
+ return rc;
+}
+
+/**
+ * Poll completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+static void arbel_poll_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq );
+ struct arbelprm_cq_ci_db_record *ci_db_rec;
+ union arbelprm_completion_entry *cqe;
+ unsigned int cqe_idx_mask;
+ int rc;
+
+ while ( 1 ) {
+ /* Look for completion entry */
+ cqe_idx_mask = ( cq->num_cqes - 1 );
+ cqe = &arbel_cq->cqe[cq->next_idx & cqe_idx_mask];
+ if ( MLX_GET ( &cqe->normal, owner ) != 0 ) {
+ /* Entry still owned by hardware; end of poll */
+ break;
+ }
+
+ /* Handle completion */
+ if ( ( rc = arbel_complete ( ibdev, cq, cqe ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p CQN %#lx failed to complete: "
+ "%s\n", arbel, cq->cqn, strerror ( rc ) );
+ DBGC_HD ( arbel, cqe, sizeof ( *cqe ) );
+ }
+
+ /* Return ownership to hardware */
+ MLX_FILL_1 ( &cqe->normal, 7, owner, 1 );
+ barrier();
+ /* Update completion queue's index */
+ cq->next_idx++;
+ /* Update doorbell record */
+ ci_db_rec = &arbel->db_rec[arbel_cq->ci_doorbell_idx].cq_ci;
+ MLX_FILL_1 ( ci_db_rec, 0,
+ counter, ( cq->next_idx & 0xffffffffUL ) );
+ }
+}
+
+/***************************************************************************
+ *
+ * Event queues
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Create event queue
+ *
+ * @v arbel Arbel device
+ * @ret rc Return status code
+ */
+static int arbel_create_eq ( struct arbel *arbel ) {
+ struct arbel_event_queue *arbel_eq = &arbel->eq;
+ struct arbelprm_eqc eqctx;
+ struct arbelprm_event_mask mask;
+ unsigned int i;
+ int rc;
+
+ /* Select event queue number */
+ arbel_eq->eqn = arbel->limits.reserved_eqs;
+
+ /* Calculate doorbell address */
+ arbel_eq->doorbell = ( arbel->eq_ci_doorbells +
+ ARBEL_DB_EQ_OFFSET ( arbel_eq->eqn ) );
+
+ /* Allocate event queue itself */
+ arbel_eq->eqe_size =
+ ( ARBEL_NUM_EQES * sizeof ( arbel_eq->eqe[0] ) );
+ arbel_eq->eqe = malloc_dma ( arbel_eq->eqe_size,
+ sizeof ( arbel_eq->eqe[0] ) );
+ if ( ! arbel_eq->eqe ) {
+ rc = -ENOMEM;
+ goto err_eqe;
+ }
+ memset ( arbel_eq->eqe, 0, arbel_eq->eqe_size );
+ for ( i = 0 ; i < ARBEL_NUM_EQES ; i++ ) {
+ MLX_FILL_1 ( &arbel_eq->eqe[i].generic, 7, owner, 1 );
+ }
+ barrier();
+
+ /* Hand queue over to hardware */
+ memset ( &eqctx, 0, sizeof ( eqctx ) );
+ MLX_FILL_1 ( &eqctx, 0, st, 0xa /* "Fired" */ );
+ MLX_FILL_H ( &eqctx, 1,
+ start_address_h, virt_to_phys ( arbel_eq->eqe ) );
+ MLX_FILL_1 ( &eqctx, 2,
+ start_address_l, virt_to_phys ( arbel_eq->eqe ) );
+ MLX_FILL_1 ( &eqctx, 3, log_eq_size, fls ( ARBEL_NUM_EQES - 1 ) );
+ MLX_FILL_1 ( &eqctx, 6, pd, ARBEL_GLOBAL_PD );
+ MLX_FILL_1 ( &eqctx, 7, lkey, arbel->lkey );
+ if ( ( rc = arbel_cmd_sw2hw_eq ( arbel, arbel_eq->eqn,
+ &eqctx ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p EQN %#lx SW2HW_EQ failed: %s\n",
+ arbel, arbel_eq->eqn, strerror ( rc ) );
+ goto err_sw2hw_eq;
+ }
+
+ /* Map events to this event queue */
+ memset ( &mask, 0xff, sizeof ( mask ) );
+ if ( ( rc = arbel_cmd_map_eq ( arbel,
+ ( ARBEL_MAP_EQ | arbel_eq->eqn ),
+ &mask ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p EQN %#lx MAP_EQ failed: %s\n",
+ arbel, arbel_eq->eqn, strerror ( rc ) );
+ goto err_map_eq;
+ }
+
+ DBGC ( arbel, "Arbel %p EQN %#lx ring [%08lx,%08lx), doorbell %08lx\n",
+ arbel, arbel_eq->eqn, virt_to_phys ( arbel_eq->eqe ),
+ ( virt_to_phys ( arbel_eq->eqe ) + arbel_eq->eqe_size ),
+ virt_to_phys ( arbel_eq->doorbell ) );
+ return 0;
+
+ err_map_eq:
+ arbel_cmd_hw2sw_eq ( arbel, arbel_eq->eqn, &eqctx );
+ err_sw2hw_eq:
+ free_dma ( arbel_eq->eqe, arbel_eq->eqe_size );
+ err_eqe:
+ memset ( arbel_eq, 0, sizeof ( *arbel_eq ) );
+ return rc;
+}
+
+/**
+ * Destroy event queue
+ *
+ * @v arbel Arbel device
+ */
+static void arbel_destroy_eq ( struct arbel *arbel ) {
+ struct arbel_event_queue *arbel_eq = &arbel->eq;
+ struct arbelprm_eqc eqctx;
+ struct arbelprm_event_mask mask;
+ int rc;
+
+ /* Unmap events from event queue */
+ memset ( &mask, 0, sizeof ( mask ) );
+ MLX_FILL_1 ( &mask, 1, port_state_change, 1 );
+ if ( ( rc = arbel_cmd_map_eq ( arbel,
+ ( ARBEL_UNMAP_EQ | arbel_eq->eqn ),
+ &mask ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p EQN %#lx FATAL MAP_EQ failed to "
+ "unmap: %s\n", arbel, arbel_eq->eqn, strerror ( rc ) );
+ /* Continue; HCA may die but system should survive */
+ }
+
+ /* Take ownership back from hardware */
+ if ( ( rc = arbel_cmd_hw2sw_eq ( arbel, arbel_eq->eqn,
+ &eqctx ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p EQN %#lx FATAL HW2SW_EQ failed: %s\n",
+ arbel, arbel_eq->eqn, strerror ( rc ) );
+ /* Leak memory and return; at least we avoid corruption */
+ return;
+ }
+
+ /* Free memory */
+ free_dma ( arbel_eq->eqe, arbel_eq->eqe_size );
+ memset ( arbel_eq, 0, sizeof ( *arbel_eq ) );
+}
+
+/**
+ * Handle port state event
+ *
+ * @v arbel Arbel device
+ * @v eqe Port state change event queue entry
+ */
+static void arbel_event_port_state_change ( struct arbel *arbel,
+ union arbelprm_event_entry *eqe){
+ unsigned int port;
+ int link_up;
+
+ /* Get port and link status */
+ port = ( MLX_GET ( &eqe->port_state_change, data.p ) - 1 );
+ link_up = ( MLX_GET ( &eqe->generic, event_sub_type ) & 0x04 );
+ DBGC ( arbel, "Arbel %p port %d link %s\n", arbel, ( port + 1 ),
+ ( link_up ? "up" : "down" ) );
+
+ /* Sanity check */
+ if ( port >= ARBEL_NUM_PORTS ) {
+ DBGC ( arbel, "Arbel %p port %d does not exist!\n",
+ arbel, ( port + 1 ) );
+ return;
+ }
+
+ /* Update MAD parameters */
+ ib_smc_update ( arbel->ibdev[port], arbel_mad );
+}
+
+/**
+ * Poll event queue
+ *
+ * @v ibdev Infiniband device
+ */
+static void arbel_poll_eq ( struct ib_device *ibdev ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct arbel_event_queue *arbel_eq = &arbel->eq;
+ union arbelprm_event_entry *eqe;
+ union arbelprm_eq_doorbell_register db_reg;
+ unsigned int eqe_idx_mask;
+ unsigned int event_type;
+
+ /* No event is generated upon reaching INIT, so we must poll
+ * separately for link state changes while we remain DOWN.
+ */
+ if ( ib_is_open ( ibdev ) &&
+ ( ibdev->port_state == IB_PORT_STATE_DOWN ) ) {
+ ib_smc_update ( ibdev, arbel_mad );
+ }
+
+ /* Poll event queue */
+ while ( 1 ) {
+ /* Look for event entry */
+ eqe_idx_mask = ( ARBEL_NUM_EQES - 1 );
+ eqe = &arbel_eq->eqe[arbel_eq->next_idx & eqe_idx_mask];
+ if ( MLX_GET ( &eqe->generic, owner ) != 0 ) {
+ /* Entry still owned by hardware; end of poll */
+ break;
+ }
+ DBGCP ( arbel, "Arbel %p EQN %#lx event:\n",
+ arbel, arbel_eq->eqn );
+ DBGCP_HDA ( arbel, virt_to_phys ( eqe ),
+ eqe, sizeof ( *eqe ) );
+
+ /* Handle event */
+ event_type = MLX_GET ( &eqe->generic, event_type );
+ switch ( event_type ) {
+ case ARBEL_EV_PORT_STATE_CHANGE:
+ arbel_event_port_state_change ( arbel, eqe );
+ break;
+ default:
+ DBGC ( arbel, "Arbel %p EQN %#lx unrecognised event "
+ "type %#x:\n",
+ arbel, arbel_eq->eqn, event_type );
+ DBGC_HDA ( arbel, virt_to_phys ( eqe ),
+ eqe, sizeof ( *eqe ) );
+ break;
+ }
+
+ /* Return ownership to hardware */
+ MLX_FILL_1 ( &eqe->generic, 7, owner, 1 );
+ barrier();
+
+ /* Update event queue's index */
+ arbel_eq->next_idx++;
+
+ /* Ring doorbell */
+ MLX_FILL_1 ( &db_reg.ci, 0, ci, arbel_eq->next_idx );
+ writel ( db_reg.dword[0], arbel_eq->doorbell );
+ }
+}
+
+/***************************************************************************
+ *
+ * Firmware control
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Map virtual to physical address for firmware usage
+ *
+ * @v arbel Arbel device
+ * @v map Mapping function
+ * @v va Virtual address
+ * @v pa Physical address
+ * @v len Length of region
+ * @ret rc Return status code
+ */
+static int arbel_map_vpm ( struct arbel *arbel,
+ int ( *map ) ( struct arbel *arbel,
+ const struct arbelprm_virtual_physical_mapping* ),
+ uint64_t va, physaddr_t pa, size_t len ) {
+ struct arbelprm_virtual_physical_mapping mapping;
+ physaddr_t start;
+ physaddr_t low;
+ physaddr_t high;
+ physaddr_t end;
+ size_t size;
+ int rc;
+
+ /* Sanity checks */
+ assert ( ( va & ( ARBEL_PAGE_SIZE - 1 ) ) == 0 );
+ assert ( ( pa & ( ARBEL_PAGE_SIZE - 1 ) ) == 0 );
+ assert ( ( len & ( ARBEL_PAGE_SIZE - 1 ) ) == 0 );
+
+ /* Calculate starting points */
+ start = pa;
+ end = ( start + len );
+ size = ( 1UL << ( fls ( start ^ end ) - 1 ) );
+ low = high = ( end & ~( size - 1 ) );
+ assert ( start < low );
+ assert ( high <= end );
+
+ /* These mappings tend to generate huge volumes of
+ * uninteresting debug data, which basically makes it
+ * impossible to use debugging otherwise.
+ */
+ DBG_DISABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
+
+ /* Map blocks in descending order of size */
+ while ( size >= ARBEL_PAGE_SIZE ) {
+
+ /* Find the next candidate block */
+ if ( ( low - size ) >= start ) {
+ low -= size;
+ pa = low;
+ } else if ( ( high + size ) <= end ) {
+ pa = high;
+ high += size;
+ } else {
+ size >>= 1;
+ continue;
+ }
+ assert ( ( va & ( size - 1 ) ) == 0 );
+ assert ( ( pa & ( size - 1 ) ) == 0 );
+
+ /* Map this block */
+ memset ( &mapping, 0, sizeof ( mapping ) );
+ MLX_FILL_1 ( &mapping, 0, va_h, ( va >> 32 ) );
+ MLX_FILL_1 ( &mapping, 1, va_l, ( va >> 12 ) );
+ MLX_FILL_H ( &mapping, 2, pa_h, pa );
+ MLX_FILL_2 ( &mapping, 3,
+ log2size, ( ( fls ( size ) - 1 ) - 12 ),
+ pa_l, ( pa >> 12 ) );
+ if ( ( rc = map ( arbel, &mapping ) ) != 0 ) {
+ DBG_ENABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
+ DBGC ( arbel, "Arbel %p could not map %08llx+%zx to "
+ "%08lx: %s\n",
+ arbel, va, size, pa, strerror ( rc ) );
+ return rc;
+ }
+ va += size;
+ }
+ assert ( low == start );
+ assert ( high == end );
+
+ DBG_ENABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
+ return 0;
+}
+
+/**
+ * Start firmware running
+ *
+ * @v arbel Arbel device
+ * @ret rc Return status code
+ */
+static int arbel_start_firmware ( struct arbel *arbel ) {
+ struct arbelprm_query_fw fw;
+ struct arbelprm_access_lam lam;
+ unsigned int fw_pages;
+ size_t fw_len;
+ physaddr_t fw_base;
+ uint64_t eq_set_ci_base_addr;
+ int rc;
+
+ /* Get firmware parameters */
+ if ( ( rc = arbel_cmd_query_fw ( arbel, &fw ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not query firmware: %s\n",
+ arbel, strerror ( rc ) );
+ goto err_query_fw;
+ }
+ DBGC ( arbel, "Arbel %p firmware version %d.%d.%d\n", arbel,
+ MLX_GET ( &fw, fw_rev_major ), MLX_GET ( &fw, fw_rev_minor ),
+ MLX_GET ( &fw, fw_rev_subminor ) );
+ fw_pages = MLX_GET ( &fw, fw_pages );
+ DBGC ( arbel, "Arbel %p requires %d kB for firmware\n",
+ arbel, ( fw_pages * 4 ) );
+ eq_set_ci_base_addr =
+ ( ( (uint64_t) MLX_GET ( &fw, eq_set_ci_base_addr_h ) << 32 ) |
+ ( (uint64_t) MLX_GET ( &fw, eq_set_ci_base_addr_l ) ) );
+ arbel->eq_ci_doorbells = ioremap ( eq_set_ci_base_addr, 0x200 );
+
+ /* Enable locally-attached memory. Ignore failure; there may
+ * be no attached memory.
+ */
+ arbel_cmd_enable_lam ( arbel, &lam );
+
+ /* Allocate firmware pages and map firmware area */
+ fw_len = ( fw_pages * ARBEL_PAGE_SIZE );
+ if ( ! arbel->firmware_area ) {
+ arbel->firmware_len = fw_len;
+ arbel->firmware_area = umalloc ( arbel->firmware_len );
+ if ( ! arbel->firmware_area ) {
+ rc = -ENOMEM;
+ goto err_alloc_fa;
+ }
+ } else {
+ assert ( arbel->firmware_len == fw_len );
+ }
+ fw_base = user_to_phys ( arbel->firmware_area, 0 );
+ DBGC ( arbel, "Arbel %p firmware area at [%08lx,%08lx)\n",
+ arbel, fw_base, ( fw_base + fw_len ) );
+ if ( ( rc = arbel_map_vpm ( arbel, arbel_cmd_map_fa,
+ 0, fw_base, fw_len ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not map firmware: %s\n",
+ arbel, strerror ( rc ) );
+ goto err_map_fa;
+ }
+
+ /* Start firmware */
+ if ( ( rc = arbel_cmd_run_fw ( arbel ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not run firmware: %s\n",
+ arbel, strerror ( rc ) );
+ goto err_run_fw;
+ }
+
+ DBGC ( arbel, "Arbel %p firmware started\n", arbel );
+ return 0;
+
+ err_run_fw:
+ arbel_cmd_unmap_fa ( arbel );
+ err_map_fa:
+ err_alloc_fa:
+ err_query_fw:
+ return rc;
+}
+
+/**
+ * Stop firmware running
+ *
+ * @v arbel Arbel device
+ */
+static void arbel_stop_firmware ( struct arbel *arbel ) {
+ int rc;
+
+ if ( ( rc = arbel_cmd_unmap_fa ( arbel ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p FATAL could not stop firmware: %s\n",
+ arbel, strerror ( rc ) );
+ /* Leak memory and return; at least we avoid corruption */
+ arbel->firmware_area = UNULL;
+ return;
+ }
+}
+
+/***************************************************************************
+ *
+ * Infinihost Context Memory management
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Get device limits
+ *
+ * @v arbel Arbel device
+ * @ret rc Return status code
+ */
+static int arbel_get_limits ( struct arbel *arbel ) {
+ struct arbelprm_query_dev_lim dev_lim;
+ int rc;
+
+ if ( ( rc = arbel_cmd_query_dev_lim ( arbel, &dev_lim ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not get device limits: %s\n",
+ arbel, strerror ( rc ) );
+ return rc;
+ }
+
+ arbel->limits.reserved_qps =
+ ( 1 << MLX_GET ( &dev_lim, log2_rsvd_qps ) );
+ arbel->limits.qpc_entry_size = MLX_GET ( &dev_lim, qpc_entry_sz );
+ arbel->limits.eqpc_entry_size = MLX_GET ( &dev_lim, eqpc_entry_sz );
+ arbel->limits.reserved_srqs =
+ ( 1 << MLX_GET ( &dev_lim, log2_rsvd_srqs ) );
+ arbel->limits.srqc_entry_size = MLX_GET ( &dev_lim, srq_entry_sz );
+ arbel->limits.reserved_ees =
+ ( 1 << MLX_GET ( &dev_lim, log2_rsvd_ees ) );
+ arbel->limits.eec_entry_size = MLX_GET ( &dev_lim, eec_entry_sz );
+ arbel->limits.eeec_entry_size = MLX_GET ( &dev_lim, eeec_entry_sz );
+ arbel->limits.reserved_cqs =
+ ( 1 << MLX_GET ( &dev_lim, log2_rsvd_cqs ) );
+ arbel->limits.cqc_entry_size = MLX_GET ( &dev_lim, cqc_entry_sz );
+ arbel->limits.reserved_mtts =
+ ( 1 << MLX_GET ( &dev_lim, log2_rsvd_mtts ) );
+ arbel->limits.mtt_entry_size = MLX_GET ( &dev_lim, mtt_entry_sz );
+ arbel->limits.reserved_mrws =
+ ( 1 << MLX_GET ( &dev_lim, log2_rsvd_mrws ) );
+ arbel->limits.mpt_entry_size = MLX_GET ( &dev_lim, mpt_entry_sz );
+ arbel->limits.reserved_rdbs =
+ ( 1 << MLX_GET ( &dev_lim, log2_rsvd_rdbs ) );
+ arbel->limits.reserved_eqs = MLX_GET ( &dev_lim, num_rsvd_eqs );
+ arbel->limits.eqc_entry_size = MLX_GET ( &dev_lim, eqc_entry_sz );
+ arbel->limits.reserved_uars = MLX_GET ( &dev_lim, num_rsvd_uars );
+ arbel->limits.uar_scratch_entry_size =
+ MLX_GET ( &dev_lim, uar_scratch_entry_sz );
+
+ DBGC ( arbel, "Arbel %p reserves %d x %#zx QPC, %d x %#zx EQPC, "
+ "%d x %#zx SRQC\n", arbel,
+ arbel->limits.reserved_qps, arbel->limits.qpc_entry_size,
+ arbel->limits.reserved_qps, arbel->limits.eqpc_entry_size,
+ arbel->limits.reserved_srqs, arbel->limits.srqc_entry_size );
+ DBGC ( arbel, "Arbel %p reserves %d x %#zx EEC, %d x %#zx EEEC, "
+ "%d x %#zx CQC\n", arbel,
+ arbel->limits.reserved_ees, arbel->limits.eec_entry_size,
+ arbel->limits.reserved_ees, arbel->limits.eeec_entry_size,
+ arbel->limits.reserved_cqs, arbel->limits.cqc_entry_size );
+ DBGC ( arbel, "Arbel %p reserves %d x %#zx EQC, %d x %#zx MTT, "
+ "%d x %#zx MPT\n", arbel,
+ arbel->limits.reserved_eqs, arbel->limits.eqc_entry_size,
+ arbel->limits.reserved_mtts, arbel->limits.mtt_entry_size,
+ arbel->limits.reserved_mrws, arbel->limits.mpt_entry_size );
+ DBGC ( arbel, "Arbel %p reserves %d x %#zx RDB, %d x %#zx UAR, "
+ "%d x %#zx UAR scratchpad\n", arbel,
+ arbel->limits.reserved_rdbs, ARBEL_RDB_ENTRY_SIZE,
+ arbel->limits.reserved_uars, ARBEL_PAGE_SIZE,
+ arbel->limits.reserved_uars,
+ arbel->limits.uar_scratch_entry_size );
+
+ return 0;
+}
+
+/**
+ * Align ICM table
+ *
+ * @v icm_offset Current ICM offset
+ * @v len ICM table length
+ * @ret icm_offset ICM offset
+ */
+static size_t icm_align ( size_t icm_offset, size_t len ) {
+
+ /* Round up to a multiple of the table size */
+ assert ( len == ( 1UL << ( fls ( len ) - 1 ) ) );
+ return ( ( icm_offset + len - 1 ) & ~( len - 1 ) );
+}
+
+/**
+ * Allocate ICM
+ *
+ * @v arbel Arbel device
+ * @v init_hca INIT_HCA structure to fill in
+ * @ret rc Return status code
+ */
+static int arbel_alloc_icm ( struct arbel *arbel,
+ struct arbelprm_init_hca *init_hca ) {
+ struct arbelprm_scalar_parameter icm_size;
+ struct arbelprm_scalar_parameter icm_aux_size;
+ struct arbelprm_scalar_parameter unmap_icm;
+ union arbelprm_doorbell_record *db_rec;
+ size_t icm_offset = 0;
+ unsigned int log_num_uars, log_num_qps, log_num_srqs, log_num_ees;
+ unsigned int log_num_cqs, log_num_mtts, log_num_mpts, log_num_rdbs;
+ unsigned int log_num_eqs, log_num_mcs;
+ size_t icm_len, icm_aux_len;
+ size_t len;
+ physaddr_t icm_phys;
+ int rc;
+
+ /* Calculate number of each object type within ICM */
+ log_num_qps = fls ( arbel->limits.reserved_qps +
+ ARBEL_RSVD_SPECIAL_QPS + ARBEL_MAX_QPS - 1 );
+ log_num_srqs = fls ( arbel->limits.reserved_srqs - 1 );
+ log_num_ees = fls ( arbel->limits.reserved_ees - 1 );
+ log_num_cqs = fls ( arbel->limits.reserved_cqs + ARBEL_MAX_CQS - 1 );
+ log_num_eqs = fls ( arbel->limits.reserved_eqs + ARBEL_MAX_EQS - 1 );
+ log_num_mtts = fls ( arbel->limits.reserved_mtts - 1 );
+ log_num_mpts = fls ( arbel->limits.reserved_mrws + 1 - 1 );
+ log_num_rdbs = fls ( arbel->limits.reserved_rdbs +
+ ARBEL_RSVD_SPECIAL_QPS + ARBEL_MAX_QPS - 1 );
+ log_num_uars = fls ( arbel->limits.reserved_uars +
+ 1 /* single UAR used */ - 1 );
+ log_num_mcs = ARBEL_LOG_MULTICAST_HASH_SIZE;
+
+ /* Queue pair contexts */
+ len = ( ( 1 << log_num_qps ) * arbel->limits.qpc_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_2 ( init_hca, 13,
+ qpc_eec_cqc_eqc_rdb_parameters.qpc_base_addr_l,
+ ( icm_offset >> 7 ),
+ qpc_eec_cqc_eqc_rdb_parameters.log_num_of_qp,
+ log_num_qps );
+ DBGC ( arbel, "Arbel %p ICM QPC is %d x %#zx at [%zx,%zx)\n",
+ arbel, ( 1 << log_num_qps ), arbel->limits.qpc_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Extended queue pair contexts */
+ len = ( ( 1 << log_num_qps ) * arbel->limits.eqpc_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 25,
+ qpc_eec_cqc_eqc_rdb_parameters.eqpc_base_addr_l,
+ icm_offset );
+ DBGC ( arbel, "Arbel %p ICM EQPC is %d x %#zx at [%zx,%zx)\n",
+ arbel, ( 1 << log_num_qps ), arbel->limits.eqpc_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Completion queue contexts */
+ len = ( ( 1 << log_num_cqs ) * arbel->limits.cqc_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_2 ( init_hca, 21,
+ qpc_eec_cqc_eqc_rdb_parameters.cqc_base_addr_l,
+ ( icm_offset >> 6 ),
+ qpc_eec_cqc_eqc_rdb_parameters.log_num_of_cq,
+ log_num_cqs );
+ DBGC ( arbel, "Arbel %p ICM CQC is %d x %#zx at [%zx,%zx)\n",
+ arbel, ( 1 << log_num_cqs ), arbel->limits.cqc_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Event queue contexts */
+ len = ( ( 1 << log_num_eqs ) * arbel->limits.eqc_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_2 ( init_hca, 33,
+ qpc_eec_cqc_eqc_rdb_parameters.eqc_base_addr_l,
+ ( icm_offset >> 6 ),
+ qpc_eec_cqc_eqc_rdb_parameters.log_num_eq,
+ log_num_eqs );
+ DBGC ( arbel, "Arbel %p ICM EQC is %d x %#zx at [%zx,%zx)\n",
+ arbel, ( 1 << log_num_eqs ), arbel->limits.eqc_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* End-to-end contexts */
+ len = ( ( 1 << log_num_ees ) * arbel->limits.eec_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_2 ( init_hca, 17,
+ qpc_eec_cqc_eqc_rdb_parameters.eec_base_addr_l,
+ ( icm_offset >> 7 ),
+ qpc_eec_cqc_eqc_rdb_parameters.log_num_of_ee,
+ log_num_ees );
+ DBGC ( arbel, "Arbel %p ICM EEC is %d x %#zx at [%zx,%zx)\n",
+ arbel, ( 1 << log_num_ees ), arbel->limits.eec_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Shared receive queue contexts */
+ len = ( ( 1 << log_num_srqs ) * arbel->limits.srqc_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_2 ( init_hca, 19,
+ qpc_eec_cqc_eqc_rdb_parameters.srqc_base_addr_l,
+ ( icm_offset >> 5 ),
+ qpc_eec_cqc_eqc_rdb_parameters.log_num_of_srq,
+ log_num_srqs );
+ DBGC ( arbel, "Arbel %p ICM SRQC is %d x %#zx at [%zx,%zx)\n",
+ arbel, ( 1 << log_num_srqs ), arbel->limits.srqc_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Memory protection table */
+ len = ( ( 1 << log_num_mpts ) * arbel->limits.mpt_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 61,
+ tpt_parameters.mpt_base_adr_l, icm_offset );
+ MLX_FILL_1 ( init_hca, 62,
+ tpt_parameters.log_mpt_sz, log_num_mpts );
+ DBGC ( arbel, "Arbel %p ICM MPT is %d x %#zx at [%zx,%zx)\n",
+ arbel, ( 1 << log_num_mpts ), arbel->limits.mpt_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Remote read data base table */
+ len = ( ( 1 << log_num_rdbs ) * ARBEL_RDB_ENTRY_SIZE );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 37,
+ qpc_eec_cqc_eqc_rdb_parameters.rdb_base_addr_l,
+ icm_offset );
+ DBGC ( arbel, "Arbel %p ICM RDB is %d x %#zx at [%zx,%zx)\n",
+ arbel, ( 1 << log_num_rdbs ), ARBEL_RDB_ENTRY_SIZE,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Extended end-to-end contexts */
+ len = ( ( 1 << log_num_ees ) * arbel->limits.eeec_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 29,
+ qpc_eec_cqc_eqc_rdb_parameters.eeec_base_addr_l,
+ icm_offset );
+ DBGC ( arbel, "Arbel %p ICM EEEC is %d x %#zx at [%zx,%zx)\n",
+ arbel, ( 1 << log_num_ees ), arbel->limits.eeec_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Multicast table */
+ len = ( ( 1 << log_num_mcs ) * sizeof ( struct arbelprm_mgm_entry ) );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 49,
+ multicast_parameters.mc_base_addr_l, icm_offset );
+ MLX_FILL_1 ( init_hca, 52,
+ multicast_parameters.log_mc_table_entry_sz,
+ fls ( sizeof ( struct arbelprm_mgm_entry ) - 1 ) );
+ MLX_FILL_1 ( init_hca, 53,
+ multicast_parameters.mc_table_hash_sz,
+ ( 1 << log_num_mcs ) );
+ MLX_FILL_1 ( init_hca, 54,
+ multicast_parameters.log_mc_table_sz,
+ log_num_mcs /* Only one entry per hash */ );
+ DBGC ( arbel, "Arbel %p ICM MC is %d x %#zx at [%zx,%zx)\n", arbel,
+ ( 1 << log_num_mcs ), sizeof ( struct arbelprm_mgm_entry ),
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Memory translation table */
+ len = ( ( 1 << log_num_mtts ) * arbel->limits.mtt_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 65,
+ tpt_parameters.mtt_base_addr_l, icm_offset );
+ DBGC ( arbel, "Arbel %p ICM MTT is %d x %#zx at [%zx,%zx)\n",
+ arbel, ( 1 << log_num_mtts ), arbel->limits.mtt_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* User access region scratchpads */
+ len = ( ( 1 << log_num_uars ) * arbel->limits.uar_scratch_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 77,
+ uar_parameters.uar_scratch_base_addr_l, icm_offset );
+ DBGC ( arbel, "Arbel %p UAR scratchpad is %d x %#zx at [%zx,%zx)\n",
+ arbel, ( 1 << log_num_uars ),
+ arbel->limits.uar_scratch_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Record amount of ICM to be allocated */
+ icm_offset = icm_align ( icm_offset, ARBEL_PAGE_SIZE );
+ icm_len = icm_offset;
+
+ /* User access region contexts
+ *
+ * The reserved UAR(s) do not need to be backed by physical
+ * memory, and our UAR is allocated separately; neither are
+ * part of the umalloc()ed ICM block, but both contribute to
+ * the total length of ICM virtual address space.
+ */
+ len = ( ( 1 << log_num_uars ) * ARBEL_PAGE_SIZE );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 74, uar_parameters.log_max_uars, log_num_uars );
+ MLX_FILL_1 ( init_hca, 79,
+ uar_parameters.uar_context_base_addr_l, icm_offset );
+ arbel->db_rec_offset =
+ ( icm_offset +
+ ( arbel->limits.reserved_uars * ARBEL_PAGE_SIZE ) );
+ DBGC ( arbel, "Arbel %p UAR is %d x %#zx at [%zx,%zx), doorbells "
+ "[%zx,%zx)\n", arbel, ( 1 << log_num_uars ), ARBEL_PAGE_SIZE,
+ icm_offset, ( icm_offset + len ), arbel->db_rec_offset,
+ ( arbel->db_rec_offset + ARBEL_PAGE_SIZE ) );
+ icm_offset += len;
+
+ /* Get ICM auxiliary area size */
+ memset ( &icm_size, 0, sizeof ( icm_size ) );
+ MLX_FILL_1 ( &icm_size, 1, value, icm_len );
+ if ( ( rc = arbel_cmd_set_icm_size ( arbel, &icm_size,
+ &icm_aux_size ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not set ICM size: %s\n",
+ arbel, strerror ( rc ) );
+ goto err_set_icm_size;
+ }
+ icm_aux_len = ( MLX_GET ( &icm_aux_size, value ) * ARBEL_PAGE_SIZE );
+
+ /* Allocate ICM data and auxiliary area */
+ DBGC ( arbel, "Arbel %p requires %zd kB ICM and %zd kB AUX ICM\n",
+ arbel, ( icm_len / 1024 ), ( icm_aux_len / 1024 ) );
+ if ( ! arbel->icm ) {
+ arbel->icm_len = icm_len;
+ arbel->icm_aux_len = icm_aux_len;
+ arbel->icm = umalloc ( arbel->icm_len + arbel->icm_aux_len );
+ if ( ! arbel->icm ) {
+ rc = -ENOMEM;
+ goto err_alloc_icm;
+ }
+ } else {
+ assert ( arbel->icm_len == icm_len );
+ assert ( arbel->icm_aux_len == icm_aux_len );
+ }
+ icm_phys = user_to_phys ( arbel->icm, 0 );
+
+ /* Allocate doorbell UAR */
+ arbel->db_rec = malloc_dma ( ARBEL_PAGE_SIZE, ARBEL_PAGE_SIZE );
+ if ( ! arbel->db_rec ) {
+ rc = -ENOMEM;
+ goto err_alloc_doorbell;
+ }
+
+ /* Map ICM auxiliary area */
+ DBGC ( arbel, "Arbel %p ICM AUX at [%08lx,%08lx)\n",
+ arbel, icm_phys, ( icm_phys + arbel->icm_aux_len ) );
+ if ( ( rc = arbel_map_vpm ( arbel, arbel_cmd_map_icm_aux,
+ 0, icm_phys, arbel->icm_aux_len ) ) != 0 ){
+ DBGC ( arbel, "Arbel %p could not map AUX ICM: %s\n",
+ arbel, strerror ( rc ) );
+ goto err_map_icm_aux;
+ }
+ icm_phys += arbel->icm_aux_len;
+
+ /* Map ICM area */
+ DBGC ( arbel, "Arbel %p ICM at [%08lx,%08lx)\n",
+ arbel, icm_phys, ( icm_phys + arbel->icm_len ) );
+ if ( ( rc = arbel_map_vpm ( arbel, arbel_cmd_map_icm,
+ 0, icm_phys, arbel->icm_len ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not map ICM: %s\n",
+ arbel, strerror ( rc ) );
+ goto err_map_icm;
+ }
+ icm_phys += arbel->icm_len;
+
+ /* Map doorbell UAR */
+ DBGC ( arbel, "Arbel %p UAR at [%08lx,%08lx)\n",
+ arbel, virt_to_phys ( arbel->db_rec ),
+ ( virt_to_phys ( arbel->db_rec ) + ARBEL_PAGE_SIZE ) );
+ if ( ( rc = arbel_map_vpm ( arbel, arbel_cmd_map_icm,
+ arbel->db_rec_offset,
+ virt_to_phys ( arbel->db_rec ),
+ ARBEL_PAGE_SIZE ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not map doorbell UAR: %s\n",
+ arbel, strerror ( rc ) );
+ goto err_map_doorbell;
+ }
+
+ /* Initialise doorbell records */
+ memset ( arbel->db_rec, 0, ARBEL_PAGE_SIZE );
+ db_rec = &arbel->db_rec[ARBEL_GROUP_SEPARATOR_DOORBELL];
+ MLX_FILL_1 ( &db_rec->qp, 1, res, ARBEL_UAR_RES_GROUP_SEP );
+
+ return 0;
+
+ memset ( &unmap_icm, 0, sizeof ( unmap_icm ) );
+ MLX_FILL_1 ( &unmap_icm, 1, value, arbel->db_rec_offset );
+ arbel_cmd_unmap_icm ( arbel, 1, &unmap_icm );
+ err_map_doorbell:
+ memset ( &unmap_icm, 0, sizeof ( unmap_icm ) );
+ arbel_cmd_unmap_icm ( arbel, ( arbel->icm_len / ARBEL_PAGE_SIZE ),
+ &unmap_icm );
+ err_map_icm:
+ arbel_cmd_unmap_icm_aux ( arbel );
+ err_map_icm_aux:
+ free_dma ( arbel->db_rec, ARBEL_PAGE_SIZE );
+ arbel->db_rec= NULL;
+ err_alloc_doorbell:
+ err_alloc_icm:
+ err_set_icm_size:
+ return rc;
+}
+
+/**
+ * Free ICM
+ *
+ * @v arbel Arbel device
+ */
+static void arbel_free_icm ( struct arbel *arbel ) {
+ struct arbelprm_scalar_parameter unmap_icm;
+
+ memset ( &unmap_icm, 0, sizeof ( unmap_icm ) );
+ MLX_FILL_1 ( &unmap_icm, 1, value, arbel->db_rec_offset );
+ arbel_cmd_unmap_icm ( arbel, 1, &unmap_icm );
+ memset ( &unmap_icm, 0, sizeof ( unmap_icm ) );
+ arbel_cmd_unmap_icm ( arbel, ( arbel->icm_len / ARBEL_PAGE_SIZE ),
+ &unmap_icm );
+ arbel_cmd_unmap_icm_aux ( arbel );
+ free_dma ( arbel->db_rec, ARBEL_PAGE_SIZE );
+ arbel->db_rec = NULL;
+}
+
+/***************************************************************************
+ *
+ * Initialisation and teardown
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Reset device
+ *
+ * @v arbel Arbel device
+ */
+static void arbel_reset ( struct arbel *arbel ) {
+ struct pci_device *pci = arbel->pci;
+ struct pci_config_backup backup;
+ static const uint8_t backup_exclude[] =
+ PCI_CONFIG_BACKUP_EXCLUDE ( 0x58, 0x5c );
+ uint16_t vendor;
+ unsigned int i;
+
+ /* Perform device reset and preserve PCI configuration */
+ pci_backup ( pci, &backup, backup_exclude );
+ writel ( ARBEL_RESET_MAGIC,
+ ( arbel->config + ARBEL_RESET_OFFSET ) );
+ for ( i = 0 ; i < ARBEL_RESET_WAIT_TIME_MS ; i++ ) {
+ mdelay ( 1 );
+ pci_read_config_word ( pci, PCI_VENDOR_ID, &vendor );
+ if ( vendor != 0xffff )
+ break;
+ }
+ pci_restore ( pci, &backup, backup_exclude );
+}
+
+/**
+ * Set up memory protection table
+ *
+ * @v arbel Arbel device
+ * @ret rc Return status code
+ */
+static int arbel_setup_mpt ( struct arbel *arbel ) {
+ struct arbelprm_mpt mpt;
+ uint32_t key;
+ int rc;
+
+ /* Derive key */
+ key = ( arbel->limits.reserved_mrws | ARBEL_MKEY_PREFIX );
+ arbel->lkey = ( ( key << 8 ) | ( key >> 24 ) );
+
+ /* Initialise memory protection table */
+ memset ( &mpt, 0, sizeof ( mpt ) );
+ MLX_FILL_7 ( &mpt, 0,
+ a, 1,
+ rw, 1,
+ rr, 1,
+ lw, 1,
+ lr, 1,
+ pa, 1,
+ r_w, 1 );
+ MLX_FILL_1 ( &mpt, 2, mem_key, key );
+ MLX_FILL_2 ( &mpt, 3,
+ pd, ARBEL_GLOBAL_PD,
+ rae, 1 );
+ MLX_FILL_1 ( &mpt, 6, reg_wnd_len_h, 0xffffffffUL );
+ MLX_FILL_1 ( &mpt, 7, reg_wnd_len_l, 0xffffffffUL );
+ if ( ( rc = arbel_cmd_sw2hw_mpt ( arbel, arbel->limits.reserved_mrws,
+ &mpt ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not set up MPT: %s\n",
+ arbel, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Configure special queue pairs
+ *
+ * @v arbel Arbel device
+ * @ret rc Return status code
+ */
+static int arbel_configure_special_qps ( struct arbel *arbel ) {
+ unsigned int smi_qpn_base;
+ unsigned int gsi_qpn_base;
+ int rc;
+
+ /* Special QP block must be aligned on an even number */
+ arbel->special_qpn_base = ( ( arbel->limits.reserved_qps + 1 ) & ~1 );
+ arbel->qpn_base = ( arbel->special_qpn_base +
+ ARBEL_NUM_SPECIAL_QPS );
+ DBGC ( arbel, "Arbel %p special QPs at [%lx,%lx]\n", arbel,
+ arbel->special_qpn_base, ( arbel->qpn_base - 1 ) );
+ smi_qpn_base = arbel->special_qpn_base;
+ gsi_qpn_base = ( smi_qpn_base + 2 );
+
+ /* Issue commands to configure special QPs */
+ if ( ( rc = arbel_cmd_conf_special_qp ( arbel, 0,
+ smi_qpn_base ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not configure SMI QPs: %s\n",
+ arbel, strerror ( rc ) );
+ return rc;
+ }
+ if ( ( rc = arbel_cmd_conf_special_qp ( arbel, 1,
+ gsi_qpn_base ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not configure GSI QPs: %s\n",
+ arbel, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Start Arbel device
+ *
+ * @v arbel Arbel device
+ * @v running Firmware is already running
+ * @ret rc Return status code
+ */
+static int arbel_start ( struct arbel *arbel, int running ) {
+ struct arbelprm_init_hca init_hca;
+ unsigned int i;
+ int rc;
+
+ /* Start firmware if not already running */
+ if ( ! running ) {
+ if ( ( rc = arbel_start_firmware ( arbel ) ) != 0 )
+ goto err_start_firmware;
+ }
+
+ /* Allocate ICM */
+ memset ( &init_hca, 0, sizeof ( init_hca ) );
+ if ( ( rc = arbel_alloc_icm ( arbel, &init_hca ) ) != 0 )
+ goto err_alloc_icm;
+
+ /* Initialise HCA */
+ if ( ( rc = arbel_cmd_init_hca ( arbel, &init_hca ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not initialise HCA: %s\n",
+ arbel, strerror ( rc ) );
+ goto err_init_hca;
+ }
+
+ /* Set up memory protection */
+ if ( ( rc = arbel_setup_mpt ( arbel ) ) != 0 )
+ goto err_setup_mpt;
+ for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ )
+ arbel->ibdev[i]->rdma_key = arbel->lkey;
+
+ /* Set up event queue */
+ if ( ( rc = arbel_create_eq ( arbel ) ) != 0 )
+ goto err_create_eq;
+
+ /* Configure special QPs */
+ if ( ( rc = arbel_configure_special_qps ( arbel ) ) != 0 )
+ goto err_conf_special_qps;
+
+ return 0;
+
+ err_conf_special_qps:
+ arbel_destroy_eq ( arbel );
+ err_create_eq:
+ err_setup_mpt:
+ arbel_cmd_close_hca ( arbel );
+ err_init_hca:
+ arbel_free_icm ( arbel );
+ err_alloc_icm:
+ arbel_stop_firmware ( arbel );
+ err_start_firmware:
+ return rc;
+}
+
+/**
+ * Stop Arbel device
+ *
+ * @v arbel Arbel device
+ */
+static void arbel_stop ( struct arbel *arbel ) {
+ arbel_destroy_eq ( arbel );
+ arbel_cmd_close_hca ( arbel );
+ arbel_free_icm ( arbel );
+ arbel_stop_firmware ( arbel );
+ arbel_reset ( arbel );
+}
+
+/**
+ * Open Arbel device
+ *
+ * @v arbel Arbel device
+ * @ret rc Return status code
+ */
+static int arbel_open ( struct arbel *arbel ) {
+ int rc;
+
+ /* Start device if applicable */
+ if ( arbel->open_count == 0 ) {
+ if ( ( rc = arbel_start ( arbel, 0 ) ) != 0 )
+ return rc;
+ }
+
+ /* Increment open counter */
+ arbel->open_count++;
+
+ return 0;
+}
+
+/**
+ * Close Arbel device
+ *
+ * @v arbel Arbel device
+ */
+static void arbel_close ( struct arbel *arbel ) {
+
+ /* Decrement open counter */
+ assert ( arbel->open_count != 0 );
+ arbel->open_count--;
+
+ /* Stop device if applicable */
+ if ( arbel->open_count == 0 )
+ arbel_stop ( arbel );
+}
+
+/***************************************************************************
+ *
+ * Infiniband link-layer operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Initialise Infiniband link
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+static int arbel_ib_open ( struct ib_device *ibdev ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct arbelprm_init_ib init_ib;
+ int rc;
+
+ /* Open hardware */
+ if ( ( rc = arbel_open ( arbel ) ) != 0 )
+ goto err_open;
+
+ /* Initialise IB */
+ memset ( &init_ib, 0, sizeof ( init_ib ) );
+ MLX_FILL_3 ( &init_ib, 0,
+ mtu_cap, ARBEL_MTU_2048,
+ port_width_cap, 3,
+ vl_cap, 1 );
+ MLX_FILL_1 ( &init_ib, 1, max_gid, 1 );
+ MLX_FILL_1 ( &init_ib, 2, max_pkey, 64 );
+ if ( ( rc = arbel_cmd_init_ib ( arbel, ibdev->port,
+ &init_ib ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p port %d could not intialise IB: %s\n",
+ arbel, ibdev->port, strerror ( rc ) );
+ goto err_init_ib;
+ }
+
+ /* Update MAD parameters */
+ ib_smc_update ( ibdev, arbel_mad );
+
+ return 0;
+
+ err_init_ib:
+ arbel_close ( arbel );
+ err_open:
+ return rc;
+}
+
+/**
+ * Close Infiniband link
+ *
+ * @v ibdev Infiniband device
+ */
+static void arbel_ib_close ( struct ib_device *ibdev ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ int rc;
+
+ /* Close IB */
+ if ( ( rc = arbel_cmd_close_ib ( arbel, ibdev->port ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p port %d could not close IB: %s\n",
+ arbel, ibdev->port, strerror ( rc ) );
+ /* Nothing we can do about this */
+ }
+
+ /* Close hardware */
+ arbel_close ( arbel );
+}
+
+/**
+ * Inform embedded subnet management agent of a received MAD
+ *
+ * @v ibdev Infiniband device
+ * @v mad MAD
+ * @ret rc Return status code
+ */
+static int arbel_inform_sma ( struct ib_device *ibdev, union ib_mad *mad ) {
+ int rc;
+
+ /* Send the MAD to the embedded SMA */
+ if ( ( rc = arbel_mad ( ibdev, mad ) ) != 0 )
+ return rc;
+
+ /* Update parameters held in software */
+ ib_smc_update ( ibdev, arbel_mad );
+
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * Multicast group operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Attach to multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ * @ret rc Return status code
+ */
+static int arbel_mcast_attach ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ union ib_gid *gid ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct arbelprm_mgm_hash hash;
+ struct arbelprm_mgm_entry mgm;
+ unsigned int index;
+ int rc;
+
+ /* Generate hash table index */
+ if ( ( rc = arbel_cmd_mgid_hash ( arbel, gid, &hash ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not hash GID: %s\n",
+ arbel, strerror ( rc ) );
+ return rc;
+ }
+ index = MLX_GET ( &hash, hash );
+
+ /* Check for existing hash table entry */
+ if ( ( rc = arbel_cmd_read_mgm ( arbel, index, &mgm ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not read MGM %#x: %s\n",
+ arbel, index, strerror ( rc ) );
+ return rc;
+ }
+ if ( MLX_GET ( &mgm, mgmqp_0.qi ) != 0 ) {
+ /* FIXME: this implementation allows only a single QP
+ * per multicast group, and doesn't handle hash
+ * collisions. Sufficient for IPoIB but may need to
+ * be extended in future.
+ */
+ DBGC ( arbel, "Arbel %p MGID index %#x already in use\n",
+ arbel, index );
+ return -EBUSY;
+ }
+
+ /* Update hash table entry */
+ MLX_FILL_2 ( &mgm, 8,
+ mgmqp_0.qpn_i, qp->qpn,
+ mgmqp_0.qi, 1 );
+ memcpy ( &mgm.u.dwords[4], gid, sizeof ( *gid ) );
+ if ( ( rc = arbel_cmd_write_mgm ( arbel, index, &mgm ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not write MGM %#x: %s\n",
+ arbel, index, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Detach from multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ */
+static void arbel_mcast_detach ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp __unused,
+ union ib_gid *gid ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ struct arbelprm_mgm_hash hash;
+ struct arbelprm_mgm_entry mgm;
+ unsigned int index;
+ int rc;
+
+ /* Generate hash table index */
+ if ( ( rc = arbel_cmd_mgid_hash ( arbel, gid, &hash ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not hash GID: %s\n",
+ arbel, strerror ( rc ) );
+ return;
+ }
+ index = MLX_GET ( &hash, hash );
+
+ /* Clear hash table entry */
+ memset ( &mgm, 0, sizeof ( mgm ) );
+ if ( ( rc = arbel_cmd_write_mgm ( arbel, index, &mgm ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not write MGM %#x: %s\n",
+ arbel, index, strerror ( rc ) );
+ return;
+ }
+}
+
+/** Arbel Infiniband operations */
+static struct ib_device_operations arbel_ib_operations = {
+ .create_cq = arbel_create_cq,
+ .destroy_cq = arbel_destroy_cq,
+ .create_qp = arbel_create_qp,
+ .modify_qp = arbel_modify_qp,
+ .destroy_qp = arbel_destroy_qp,
+ .post_send = arbel_post_send,
+ .post_recv = arbel_post_recv,
+ .poll_cq = arbel_poll_cq,
+ .poll_eq = arbel_poll_eq,
+ .open = arbel_ib_open,
+ .close = arbel_ib_close,
+ .mcast_attach = arbel_mcast_attach,
+ .mcast_detach = arbel_mcast_detach,
+ .set_port_info = arbel_inform_sma,
+ .set_pkey_table = arbel_inform_sma,
+};
+
+/***************************************************************************
+ *
+ * PCI interface
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Allocate Arbel device
+ *
+ * @ret arbel Arbel device
+ */
+static struct arbel * arbel_alloc ( void ) {
+ struct arbel *arbel;
+
+ /* Allocate Arbel device */
+ arbel = zalloc ( sizeof ( *arbel ) );
+ if ( ! arbel )
+ goto err_arbel;
+
+ /* Allocate space for mailboxes */
+ arbel->mailbox_in = malloc_dma ( ARBEL_MBOX_SIZE, ARBEL_MBOX_ALIGN );
+ if ( ! arbel->mailbox_in )
+ goto err_mailbox_in;
+ arbel->mailbox_out = malloc_dma ( ARBEL_MBOX_SIZE, ARBEL_MBOX_ALIGN );
+ if ( ! arbel->mailbox_out )
+ goto err_mailbox_out;
+
+ return arbel;
+
+ free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE );
+ err_mailbox_out:
+ free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
+ err_mailbox_in:
+ free ( arbel );
+ err_arbel:
+ return NULL;
+}
+
+/**
+ * Free Arbel device
+ *
+ * @v arbel Arbel device
+ */
+static void arbel_free ( struct arbel *arbel ) {
+
+ ufree ( arbel->icm );
+ ufree ( arbel->firmware_area );
+ free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE );
+ free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
+ free ( arbel );
+}
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @v id PCI ID
+ * @ret rc Return status code
+ */
+static int arbel_probe ( struct pci_device *pci ) {
+ struct arbel *arbel;
+ struct ib_device *ibdev;
+ int i;
+ int rc;
+
+ /* Allocate Arbel device */
+ arbel = arbel_alloc();
+ if ( ! arbel ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ pci_set_drvdata ( pci, arbel );
+ arbel->pci = pci;
+
+ /* Allocate Infiniband devices */
+ for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) {
+ ibdev = alloc_ibdev ( 0 );
+ if ( ! ibdev ) {
+ rc = -ENOMEM;
+ goto err_alloc_ibdev;
+ }
+ arbel->ibdev[i] = ibdev;
+ ibdev->op = &arbel_ib_operations;
+ ibdev->dev = &pci->dev;
+ ibdev->port = ( ARBEL_PORT_BASE + i );
+ ib_set_drvdata ( ibdev, arbel );
+ }
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* Get PCI BARs */
+ arbel->config = ioremap ( pci_bar_start ( pci, ARBEL_PCI_CONFIG_BAR ),
+ ARBEL_PCI_CONFIG_BAR_SIZE );
+ arbel->uar = ioremap ( ( pci_bar_start ( pci, ARBEL_PCI_UAR_BAR ) +
+ ARBEL_PCI_UAR_IDX * ARBEL_PCI_UAR_SIZE ),
+ ARBEL_PCI_UAR_SIZE );
+
+ /* Reset device */
+ arbel_reset ( arbel );
+
+ /* Start firmware */
+ if ( ( rc = arbel_start_firmware ( arbel ) ) != 0 )
+ goto err_start_firmware;
+
+ /* Get device limits */
+ if ( ( rc = arbel_get_limits ( arbel ) ) != 0 )
+ goto err_get_limits;
+
+ /* Start device */
+ if ( ( rc = arbel_start ( arbel, 1 ) ) != 0 )
+ goto err_start;
+
+ /* Initialise parameters using SMC */
+ for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ )
+ ib_smc_init ( arbel->ibdev[i], arbel_mad );
+
+ /* Register Infiniband devices */
+ for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) {
+ if ( ( rc = register_ibdev ( arbel->ibdev[i] ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p port %d could not register IB "
+ "device: %s\n", arbel,
+ arbel->ibdev[i]->port, strerror ( rc ) );
+ goto err_register_ibdev;
+ }
+ }
+
+ /* Leave device quiescent until opened */
+ if ( arbel->open_count == 0 )
+ arbel_stop ( arbel );
+
+ return 0;
+
+ i = ARBEL_NUM_PORTS;
+ err_register_ibdev:
+ for ( i-- ; i >= 0 ; i-- )
+ unregister_ibdev ( arbel->ibdev[i] );
+ arbel_stop ( arbel );
+ err_start:
+ err_get_limits:
+ arbel_stop_firmware ( arbel );
+ err_start_firmware:
+ i = ARBEL_NUM_PORTS;
+ err_alloc_ibdev:
+ for ( i-- ; i >= 0 ; i-- )
+ ibdev_put ( arbel->ibdev[i] );
+ arbel_free ( arbel );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void arbel_remove ( struct pci_device *pci ) {
+ struct arbel *arbel = pci_get_drvdata ( pci );
+ int i;
+
+ for ( i = ( ARBEL_NUM_PORTS - 1 ) ; i >= 0 ; i-- )
+ unregister_ibdev ( arbel->ibdev[i] );
+ for ( i = ( ARBEL_NUM_PORTS - 1 ) ; i >= 0 ; i-- )
+ ibdev_put ( arbel->ibdev[i] );
+ arbel_free ( arbel );
+}
+
+static struct pci_device_id arbel_nics[] = {
+ PCI_ROM ( 0x15b3, 0x6282, "mt25218", "MT25218 HCA driver", 0 ),
+ PCI_ROM ( 0x15b3, 0x6274, "mt25204", "MT25204 HCA driver", 0 ),
+};
+
+struct pci_driver arbel_driver __pci_driver = {
+ .ids = arbel_nics,
+ .id_count = ( sizeof ( arbel_nics ) / sizeof ( arbel_nics[0] ) ),
+ .probe = arbel_probe,
+ .remove = arbel_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/arbel.h b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/arbel.h
new file mode 100644
index 00000000..c0303f1b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/arbel.h
@@ -0,0 +1,655 @@
+#ifndef _ARBEL_H
+#define _ARBEL_H
+
+/** @file
+ *
+ * Mellanox Arbel Infiniband HCA driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/ib_packet.h>
+#include "mlx_bitops.h"
+#include "MT25218_PRM.h"
+
+/*
+ * Hardware constants
+ *
+ */
+
+/* Ports in existence */
+#define ARBEL_NUM_PORTS 2
+#define ARBEL_PORT_BASE 1
+
+/* PCI BARs */
+#define ARBEL_PCI_CONFIG_BAR PCI_BASE_ADDRESS_0
+#define ARBEL_PCI_CONFIG_BAR_SIZE 0x100000
+#define ARBEL_PCI_UAR_BAR PCI_BASE_ADDRESS_2
+#define ARBEL_PCI_UAR_IDX 1
+#define ARBEL_PCI_UAR_SIZE 0x1000
+
+/* Device reset */
+#define ARBEL_RESET_OFFSET 0x0f0010
+#define ARBEL_RESET_MAGIC 0x01000000UL
+#define ARBEL_RESET_WAIT_TIME_MS 1000
+
+/* UAR context table (UCE) resource types */
+#define ARBEL_UAR_RES_NONE 0x00
+#define ARBEL_UAR_RES_CQ_CI 0x01
+#define ARBEL_UAR_RES_CQ_ARM 0x02
+#define ARBEL_UAR_RES_SQ 0x03
+#define ARBEL_UAR_RES_RQ 0x04
+#define ARBEL_UAR_RES_GROUP_SEP 0x07
+
+/* Work queue entry and completion queue entry opcodes */
+#define ARBEL_OPCODE_SEND 0x0a
+#define ARBEL_OPCODE_RECV_ERROR 0xfe
+#define ARBEL_OPCODE_SEND_ERROR 0xff
+
+/* HCA command register opcodes */
+#define ARBEL_HCR_QUERY_DEV_LIM 0x0003
+#define ARBEL_HCR_QUERY_FW 0x0004
+#define ARBEL_HCR_INIT_HCA 0x0007
+#define ARBEL_HCR_CLOSE_HCA 0x0008
+#define ARBEL_HCR_INIT_IB 0x0009
+#define ARBEL_HCR_CLOSE_IB 0x000a
+#define ARBEL_HCR_SW2HW_MPT 0x000d
+#define ARBEL_HCR_MAP_EQ 0x0012
+#define ARBEL_HCR_SW2HW_EQ 0x0013
+#define ARBEL_HCR_HW2SW_EQ 0x0014
+#define ARBEL_HCR_SW2HW_CQ 0x0016
+#define ARBEL_HCR_HW2SW_CQ 0x0017
+#define ARBEL_HCR_QUERY_CQ 0x0018
+#define ARBEL_HCR_RST2INIT_QPEE 0x0019
+#define ARBEL_HCR_INIT2RTR_QPEE 0x001a
+#define ARBEL_HCR_RTR2RTS_QPEE 0x001b
+#define ARBEL_HCR_RTS2RTS_QPEE 0x001c
+#define ARBEL_HCR_2RST_QPEE 0x0021
+#define ARBEL_HCR_QUERY_QPEE 0x0022
+#define ARBEL_HCR_CONF_SPECIAL_QP 0x0023
+#define ARBEL_HCR_MAD_IFC 0x0024
+#define ARBEL_HCR_READ_MGM 0x0025
+#define ARBEL_HCR_WRITE_MGM 0x0026
+#define ARBEL_HCR_MGID_HASH 0x0027
+#define ARBEL_HCR_RUN_FW 0x0ff6
+#define ARBEL_HCR_DISABLE_LAM 0x0ff7
+#define ARBEL_HCR_ENABLE_LAM 0x0ff8
+#define ARBEL_HCR_UNMAP_ICM 0x0ff9
+#define ARBEL_HCR_MAP_ICM 0x0ffa
+#define ARBEL_HCR_UNMAP_ICM_AUX 0x0ffb
+#define ARBEL_HCR_MAP_ICM_AUX 0x0ffc
+#define ARBEL_HCR_SET_ICM_SIZE 0x0ffd
+#define ARBEL_HCR_UNMAP_FA 0x0ffe
+#define ARBEL_HCR_MAP_FA 0x0fff
+
+/* Service types */
+#define ARBEL_ST_RC 0x00
+#define ARBEL_ST_UD 0x03
+#define ARBEL_ST_MLX 0x07
+
+/* MTUs */
+#define ARBEL_MTU_2048 0x04
+
+#define ARBEL_NO_EQ 64
+
+#define ARBEL_INVALID_LKEY 0x00000100UL
+
+#define ARBEL_PAGE_SIZE ( ( size_t ) 4096 )
+
+#define ARBEL_RDB_ENTRY_SIZE ( ( size_t ) 32 )
+
+#define ARBEL_DB_POST_SND_OFFSET 0x10
+#define ARBEL_DB_EQ_OFFSET(_eqn) ( 0x08 * (_eqn) )
+
+#define ARBEL_QPEE_OPT_PARAM_QKEY 0x00000020UL
+
+#define ARBEL_MAP_EQ ( 0UL << 31 )
+#define ARBEL_UNMAP_EQ ( 1UL << 31 )
+
+#define ARBEL_EV_PORT_STATE_CHANGE 0x09
+
+#define ARBEL_LOG_MULTICAST_HASH_SIZE 3
+
+#define ARBEL_PM_STATE_ARMED 0x00
+#define ARBEL_PM_STATE_REARM 0x01
+#define ARBEL_PM_STATE_MIGRATED 0x03
+
+#define ARBEL_RETRY_MAX 0x07
+
+/*
+ * Datatypes that seem to be missing from the autogenerated documentation
+ *
+ */
+struct arbelprm_mgm_hash_st {
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+ pseudo_bit_t hash[0x00010];
+ pseudo_bit_t reserved1[0x00010];
+} __attribute__ (( packed ));
+
+struct arbelprm_scalar_parameter_st {
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+ pseudo_bit_t value[0x00020];
+} __attribute__ (( packed ));
+
+struct arbelprm_event_mask_st {
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+ pseudo_bit_t completion[0x00001];
+ pseudo_bit_t path_migration_succeeded[0x00001];
+ pseudo_bit_t communication_established[0x00001];
+ pseudo_bit_t send_queue_drained[0x00001];
+ pseudo_bit_t cq_error[0x00001];
+ pseudo_bit_t wq_catastrophe[0x00001];
+ pseudo_bit_t qpc_catastrophe[0x00001];
+ pseudo_bit_t path_migration_failed[0x00001];
+ pseudo_bit_t reserved1[0x00001];
+ pseudo_bit_t port_state_change[0x00001];
+ pseudo_bit_t command_done[0x00001];
+ pseudo_bit_t reserved2[0x00005];
+ pseudo_bit_t wq_invalid_request[0x00001];
+ pseudo_bit_t wq_access_violation[0x00001];
+ pseudo_bit_t srq_catastrophe[0x00001];
+ pseudo_bit_t srq_last_wqe[0x00001];
+ pseudo_bit_t srq_rq_limit[0x00001];
+ pseudo_bit_t gpio[0x00001];
+ pseudo_bit_t clientreregister[0x00001];
+ pseudo_bit_t path_migration_armed[0x00001];
+ pseudo_bit_t reserved3[0x00008];
+} __attribute__ (( packed ));
+
+struct arbelprm_eq_set_ci_st {
+ pseudo_bit_t ci[0x00020];
+} __attribute__ (( packed ));
+
+struct arbelprm_port_state_change_event_st {
+ pseudo_bit_t reserved[0x00020];
+ struct arbelprm_port_state_change_st data;
+} __attribute__ (( packed ));
+
+/*
+ * Wrapper structures for hardware datatypes
+ *
+ */
+
+struct MLX_DECLARE_STRUCT ( arbelprm_access_lam );
+struct MLX_DECLARE_STRUCT ( arbelprm_completion_queue_context );
+struct MLX_DECLARE_STRUCT ( arbelprm_completion_queue_entry );
+struct MLX_DECLARE_STRUCT ( arbelprm_completion_with_error );
+struct MLX_DECLARE_STRUCT ( arbelprm_cq_arm_db_record );
+struct MLX_DECLARE_STRUCT ( arbelprm_cq_ci_db_record );
+struct MLX_DECLARE_STRUCT ( arbelprm_event_mask );
+struct MLX_DECLARE_STRUCT ( arbelprm_event_queue_entry );
+struct MLX_DECLARE_STRUCT ( arbelprm_eq_set_ci );
+struct MLX_DECLARE_STRUCT ( arbelprm_eqc );
+struct MLX_DECLARE_STRUCT ( arbelprm_hca_command_register );
+struct MLX_DECLARE_STRUCT ( arbelprm_init_hca );
+struct MLX_DECLARE_STRUCT ( arbelprm_init_ib );
+struct MLX_DECLARE_STRUCT ( arbelprm_mad_ifc );
+struct MLX_DECLARE_STRUCT ( arbelprm_mgm_entry );
+struct MLX_DECLARE_STRUCT ( arbelprm_mgm_hash );
+struct MLX_DECLARE_STRUCT ( arbelprm_mpt );
+struct MLX_DECLARE_STRUCT ( arbelprm_port_state_change_event );
+struct MLX_DECLARE_STRUCT ( arbelprm_qp_db_record );
+struct MLX_DECLARE_STRUCT ( arbelprm_qp_ee_state_transitions );
+struct MLX_DECLARE_STRUCT ( arbelprm_query_dev_lim );
+struct MLX_DECLARE_STRUCT ( arbelprm_query_fw );
+struct MLX_DECLARE_STRUCT ( arbelprm_queue_pair_ee_context_entry );
+struct MLX_DECLARE_STRUCT ( arbelprm_recv_wqe_segment_next );
+struct MLX_DECLARE_STRUCT ( arbelprm_scalar_parameter );
+struct MLX_DECLARE_STRUCT ( arbelprm_send_doorbell );
+struct MLX_DECLARE_STRUCT ( arbelprm_ud_address_vector );
+struct MLX_DECLARE_STRUCT ( arbelprm_virtual_physical_mapping );
+struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ctrl_mlx );
+struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ctrl_send );
+struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_data_ptr );
+struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_next );
+struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ud );
+
+/*
+ * Composite hardware datatypes
+ *
+ */
+
+#define ARBEL_MAX_GATHER 2
+
+struct arbelprm_ud_send_wqe {
+ struct arbelprm_wqe_segment_next next;
+ struct arbelprm_wqe_segment_ctrl_send ctrl;
+ struct arbelprm_wqe_segment_ud ud;
+ struct arbelprm_wqe_segment_data_ptr data[ARBEL_MAX_GATHER];
+} __attribute__ (( packed ));
+
+struct arbelprm_mlx_send_wqe {
+ struct arbelprm_wqe_segment_next next;
+ struct arbelprm_wqe_segment_ctrl_mlx ctrl;
+ struct arbelprm_wqe_segment_data_ptr data[ARBEL_MAX_GATHER];
+ uint8_t headers[IB_MAX_HEADER_SIZE];
+} __attribute__ (( packed ));
+
+struct arbelprm_rc_send_wqe {
+ struct arbelprm_wqe_segment_next next;
+ struct arbelprm_wqe_segment_ctrl_send ctrl;
+ struct arbelprm_wqe_segment_data_ptr data[ARBEL_MAX_GATHER];
+} __attribute__ (( packed ));
+
+#define ARBEL_MAX_SCATTER 1
+
+struct arbelprm_recv_wqe {
+ /* The autogenerated header is inconsistent between send and
+ * receive WQEs. The "ctrl" structure for receive WQEs is
+ * defined to include the "next" structure. Since the "ctrl"
+ * part of the "ctrl" structure contains only "reserved, must
+ * be zero" bits, we ignore its definition and provide
+ * something more usable.
+ */
+ struct arbelprm_recv_wqe_segment_next next;
+ uint32_t ctrl[2]; /* All "reserved, must be zero" */
+ struct arbelprm_wqe_segment_data_ptr data[ARBEL_MAX_SCATTER];
+} __attribute__ (( packed ));
+
+union arbelprm_completion_entry {
+ struct arbelprm_completion_queue_entry normal;
+ struct arbelprm_completion_with_error error;
+} __attribute__ (( packed ));
+
+union arbelprm_event_entry {
+ struct arbelprm_event_queue_entry generic;
+ struct arbelprm_port_state_change_event port_state_change;
+} __attribute__ (( packed ));
+
+union arbelprm_doorbell_record {
+ struct arbelprm_cq_arm_db_record cq_arm;
+ struct arbelprm_cq_ci_db_record cq_ci;
+ struct arbelprm_qp_db_record qp;
+} __attribute__ (( packed ));
+
+union arbelprm_doorbell_register {
+ struct arbelprm_send_doorbell send;
+ uint32_t dword[2];
+} __attribute__ (( packed ));
+
+union arbelprm_eq_doorbell_register {
+ struct arbelprm_eq_set_ci ci;
+ uint32_t dword[1];
+} __attribute__ (( packed ));
+
+union arbelprm_mad {
+ struct arbelprm_mad_ifc ifc;
+ union ib_mad mad;
+} __attribute__ (( packed ));
+
+/*
+ * iPXE-specific definitions
+ *
+ */
+
+/** Arbel device limits */
+struct arbel_dev_limits {
+ /** Number of reserved QPs */
+ unsigned int reserved_qps;
+ /** QP context entry size */
+ size_t qpc_entry_size;
+ /** Extended QP context entry size */
+ size_t eqpc_entry_size;
+ /** Number of reserved SRQs */
+ unsigned int reserved_srqs;
+ /** SRQ context entry size */
+ size_t srqc_entry_size;
+ /** Number of reserved EEs */
+ unsigned int reserved_ees;
+ /** EE context entry size */
+ size_t eec_entry_size;
+ /** Extended EE context entry size */
+ size_t eeec_entry_size;
+ /** Number of reserved CQs */
+ unsigned int reserved_cqs;
+ /** CQ context entry size */
+ size_t cqc_entry_size;
+ /** Number of reserved EQs */
+ unsigned int reserved_eqs;
+ /** Number of reserved MTTs */
+ unsigned int reserved_mtts;
+ /** MTT entry size */
+ size_t mtt_entry_size;
+ /** Number of reserved MRWs */
+ unsigned int reserved_mrws;
+ /** MPT entry size */
+ size_t mpt_entry_size;
+ /** Number of reserved RDBs */
+ unsigned int reserved_rdbs;
+ /** EQ context entry size */
+ size_t eqc_entry_size;
+ /** Number of reserved UARs */
+ unsigned int reserved_uars;
+ /** UAR scratchpad entry size */
+ size_t uar_scratch_entry_size;
+};
+
+/** Alignment of Arbel send work queue entries */
+#define ARBEL_SEND_WQE_ALIGN 128
+
+/** An Arbel send work queue entry */
+union arbel_send_wqe {
+ struct arbelprm_wqe_segment_next next;
+ struct arbelprm_ud_send_wqe ud;
+ struct arbelprm_mlx_send_wqe mlx;
+ struct arbelprm_rc_send_wqe rc;
+ uint8_t force_align[ARBEL_SEND_WQE_ALIGN];
+} __attribute__ (( packed ));
+
+/** An Arbel send work queue */
+struct arbel_send_work_queue {
+ /** Doorbell record number */
+ unsigned int doorbell_idx;
+ /** Work queue entries */
+ union arbel_send_wqe *wqe;
+ /** Size of work queue */
+ size_t wqe_size;
+};
+
+/** Alignment of Arbel receive work queue entries */
+#define ARBEL_RECV_WQE_ALIGN 64
+
+/** An Arbel receive work queue entry */
+union arbel_recv_wqe {
+ struct arbelprm_recv_wqe recv;
+ uint8_t force_align[ARBEL_RECV_WQE_ALIGN];
+} __attribute__ (( packed ));
+
+/** An Arbel receive work queue */
+struct arbel_recv_work_queue {
+ /** Doorbell record number */
+ unsigned int doorbell_idx;
+ /** Work queue entries */
+ union arbel_recv_wqe *wqe;
+ /** Size of work queue */
+ size_t wqe_size;
+};
+
+/** Number of special queue pairs */
+#define ARBEL_NUM_SPECIAL_QPS 4
+
+/** Number of queue pairs reserved for the "special QP" block
+ *
+ * The special QPs must be in (2n,2n+1) pairs, hence we need to
+ * reserve one extra QP to allow for alignment.
+ */
+#define ARBEL_RSVD_SPECIAL_QPS ( ARBEL_NUM_SPECIAL_QPS + 1 )
+
+/** Maximum number of allocatable queue pairs
+ *
+ * This is a policy decision, not a device limit.
+ */
+#define ARBEL_MAX_QPS 8
+
+/** Queue pair number randomisation mask */
+#define ARBEL_QPN_RANDOM_MASK 0xfff000
+
+/** Arbel queue pair state */
+enum arbel_queue_pair_state {
+ ARBEL_QP_ST_RST = 0,
+ ARBEL_QP_ST_INIT,
+ ARBEL_QP_ST_RTR,
+ ARBEL_QP_ST_RTS,
+};
+
+/** An Arbel queue pair */
+struct arbel_queue_pair {
+ /** Send work queue */
+ struct arbel_send_work_queue send;
+ /** Receive work queue */
+ struct arbel_recv_work_queue recv;
+ /** Queue state */
+ enum arbel_queue_pair_state state;
+};
+
+/** Maximum number of allocatable completion queues
+ *
+ * This is a policy decision, not a device limit.
+ */
+#define ARBEL_MAX_CQS 8
+
+/** An Arbel completion queue */
+struct arbel_completion_queue {
+ /** Consumer counter doorbell record number */
+ unsigned int ci_doorbell_idx;
+ /** Arm queue doorbell record number */
+ unsigned int arm_doorbell_idx;
+ /** Completion queue entries */
+ union arbelprm_completion_entry *cqe;
+ /** Size of completion queue */
+ size_t cqe_size;
+};
+
+/** Maximum number of allocatable event queues
+ *
+ * This is a policy decision, not a device limit.
+ */
+#define ARBEL_MAX_EQS 64
+
+/** A Arbel event queue */
+struct arbel_event_queue {
+ /** Event queue entries */
+ union arbelprm_event_entry *eqe;
+ /** Size of event queue */
+ size_t eqe_size;
+ /** Event queue number */
+ unsigned long eqn;
+ /** Next event queue entry index */
+ unsigned long next_idx;
+ /** Doorbell register */
+ void *doorbell;
+};
+
+/** Number of event queue entries
+ *
+ * This is a policy decision.
+ */
+#define ARBEL_NUM_EQES 4
+
+
+/** An Arbel resource bitmask */
+typedef uint32_t arbel_bitmask_t;
+
+/** Size of an Arbel resource bitmask */
+#define ARBEL_BITMASK_SIZE(max_entries) \
+ ( ( (max_entries) + ( 8 * sizeof ( arbel_bitmask_t ) ) - 1 ) / \
+ ( 8 * sizeof ( arbel_bitmask_t ) ) )
+
+/** An Arbel device */
+struct arbel {
+ /** PCI device */
+ struct pci_device *pci;
+ /** PCI configuration registers */
+ void *config;
+ /** PCI user Access Region */
+ void *uar;
+ /** Event queue consumer index doorbells */
+ void *eq_ci_doorbells;
+
+ /** Command input mailbox */
+ void *mailbox_in;
+ /** Command output mailbox */
+ void *mailbox_out;
+
+ /** Device open request counter */
+ unsigned int open_count;
+
+ /** Firmware size */
+ size_t firmware_len;
+ /** Firmware area in external memory
+ *
+ * This is allocated when first needed, and freed only on
+ * final teardown, in order to avoid memory map changes at
+ * runtime.
+ */
+ userptr_t firmware_area;
+ /** ICM size */
+ size_t icm_len;
+ /** ICM AUX size */
+ size_t icm_aux_len;
+ /** ICM area
+ *
+ * This is allocated when first needed, and freed only on
+ * final teardown, in order to avoid memory map changes at
+ * runtime.
+ */
+ userptr_t icm;
+ /** Offset within ICM of doorbell records */
+ size_t db_rec_offset;
+ /** Doorbell records */
+ union arbelprm_doorbell_record *db_rec;
+ /** Event queue */
+ struct arbel_event_queue eq;
+ /** Unrestricted LKey
+ *
+ * Used to get unrestricted memory access.
+ */
+ unsigned long lkey;
+
+ /** Completion queue in-use bitmask */
+ arbel_bitmask_t cq_inuse[ ARBEL_BITMASK_SIZE ( ARBEL_MAX_CQS ) ];
+ /** Queue pair in-use bitmask */
+ arbel_bitmask_t qp_inuse[ ARBEL_BITMASK_SIZE ( ARBEL_MAX_QPS ) ];
+
+ /** Device limits */
+ struct arbel_dev_limits limits;
+ /** Special QPN base */
+ unsigned long special_qpn_base;
+ /** QPN base */
+ unsigned long qpn_base;
+
+ /** Infiniband devices */
+ struct ib_device *ibdev[ARBEL_NUM_PORTS];
+};
+
+/** Global protection domain */
+#define ARBEL_GLOBAL_PD 0x123456
+
+/** Memory key prefix */
+#define ARBEL_MKEY_PREFIX 0x77000000UL
+
+/*
+ * HCA commands
+ *
+ */
+
+#define ARBEL_HCR_BASE 0x80680
+#define ARBEL_HCR_REG(x) ( ARBEL_HCR_BASE + 4 * (x) )
+#define ARBEL_HCR_MAX_WAIT_MS 2000
+#define ARBEL_MBOX_ALIGN 4096
+#define ARBEL_MBOX_SIZE 512
+
+/* HCA command is split into
+ *
+ * bits 11:0 Opcode
+ * bit 12 Input uses mailbox
+ * bit 13 Output uses mailbox
+ * bits 22:14 Input parameter length (in dwords)
+ * bits 31:23 Output parameter length (in dwords)
+ *
+ * Encoding the information in this way allows us to cut out several
+ * parameters to the arbel_command() call.
+ */
+#define ARBEL_HCR_IN_MBOX 0x00001000UL
+#define ARBEL_HCR_OUT_MBOX 0x00002000UL
+#define ARBEL_HCR_OPCODE( _command ) ( (_command) & 0xfff )
+#define ARBEL_HCR_IN_LEN( _command ) ( ( (_command) >> 12 ) & 0x7fc )
+#define ARBEL_HCR_OUT_LEN( _command ) ( ( (_command) >> 21 ) & 0x7fc )
+
+/** Build HCR command from component parts */
+#define ARBEL_HCR_INOUT_CMD( _opcode, _in_mbox, _in_len, \
+ _out_mbox, _out_len ) \
+ ( (_opcode) | \
+ ( (_in_mbox) ? ARBEL_HCR_IN_MBOX : 0 ) | \
+ ( ( (_in_len) / 4 ) << 14 ) | \
+ ( (_out_mbox) ? ARBEL_HCR_OUT_MBOX : 0 ) | \
+ ( ( (_out_len) / 4 ) << 23 ) )
+
+#define ARBEL_HCR_IN_CMD( _opcode, _in_mbox, _in_len ) \
+ ARBEL_HCR_INOUT_CMD ( _opcode, _in_mbox, _in_len, 0, 0 )
+
+#define ARBEL_HCR_OUT_CMD( _opcode, _out_mbox, _out_len ) \
+ ARBEL_HCR_INOUT_CMD ( _opcode, 0, 0, _out_mbox, _out_len )
+
+#define ARBEL_HCR_VOID_CMD( _opcode ) \
+ ARBEL_HCR_INOUT_CMD ( _opcode, 0, 0, 0, 0 )
+
+/*
+ * Doorbell record allocation
+ *
+ * The doorbell record map looks like:
+ *
+ * ARBEL_MAX_CQS * Arm completion queue doorbell
+ * ARBEL_MAX_QPS * Send work request doorbell
+ * Group separator
+ * ...(empty space)...
+ * ARBEL_MAX_QPS * Receive work request doorbell
+ * ARBEL_MAX_CQS * Completion queue consumer counter update doorbell
+ */
+
+#define ARBEL_MAX_DOORBELL_RECORDS 512
+#define ARBEL_GROUP_SEPARATOR_DOORBELL \
+ ( ARBEL_MAX_CQS + ARBEL_RSVD_SPECIAL_QPS + ARBEL_MAX_QPS )
+
+/**
+ * Get arm completion queue doorbell index
+ *
+ * @v arbel Arbel device
+ * @v cq Completion queue
+ * @ret doorbell_idx Doorbell index
+ */
+static inline unsigned int
+arbel_cq_arm_doorbell_idx ( struct arbel *arbel,
+ struct ib_completion_queue *cq ) {
+ return ( cq->cqn - arbel->limits.reserved_cqs );
+}
+
+/**
+ * Get send work request doorbell index
+ *
+ * @v arbel Arbel device
+ * @v qp Queue pair
+ * @ret doorbell_idx Doorbell index
+ */
+static inline unsigned int
+arbel_send_doorbell_idx ( struct arbel *arbel, struct ib_queue_pair *qp ) {
+ return ( ARBEL_MAX_CQS +
+ ( ( qp->qpn & ~ARBEL_QPN_RANDOM_MASK ) -
+ arbel->special_qpn_base ) );
+}
+
+/**
+ * Get receive work request doorbell index
+ *
+ * @v arbel Arbel device
+ * @v qp Queue pair
+ * @ret doorbell_idx Doorbell index
+ */
+static inline unsigned int
+arbel_recv_doorbell_idx ( struct arbel *arbel, struct ib_queue_pair *qp ) {
+ return ( ARBEL_MAX_DOORBELL_RECORDS - ARBEL_MAX_CQS -
+ ( ( qp->qpn & ~ARBEL_QPN_RANDOM_MASK ) -
+ arbel->special_qpn_base ) - 1 );
+}
+
+/**
+ * Get completion queue consumer counter doorbell index
+ *
+ * @v arbel Arbel device
+ * @v cq Completion queue
+ * @ret doorbell_idx Doorbell index
+ */
+static inline unsigned int
+arbel_cq_ci_doorbell_idx ( struct arbel *arbel,
+ struct ib_completion_queue *cq ) {
+ return ( ARBEL_MAX_DOORBELL_RECORDS -
+ ( cq->cqn - arbel->limits.reserved_cqs ) - 1 );
+}
+
+#endif /* _ARBEL_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/hermon.c b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/hermon.c
new file mode 100644
index 00000000..dc3d413b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/hermon.c
@@ -0,0 +1,3952 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ * Copyright (C) 2008 Mellanox Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/io.h>
+#include <ipxe/pci.h>
+#include <ipxe/pcibackup.h>
+#include <ipxe/malloc.h>
+#include <ipxe/umalloc.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/ib_smc.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/fcoe.h>
+#include <ipxe/vlan.h>
+#include <ipxe/bofm.h>
+#include "hermon.h"
+
+/**
+ * @file
+ *
+ * Mellanox Hermon Infiniband HCA
+ *
+ */
+
+/***************************************************************************
+ *
+ * Queue number allocation
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Allocate offsets within usage bitmask
+ *
+ * @v bits Usage bitmask
+ * @v bits_len Length of usage bitmask
+ * @v num_bits Number of contiguous bits to allocate within bitmask
+ * @ret bit First free bit within bitmask, or negative error
+ */
+static int hermon_bitmask_alloc ( hermon_bitmask_t *bits,
+ unsigned int bits_len,
+ unsigned int num_bits ) {
+ unsigned int bit = 0;
+ hermon_bitmask_t mask = 1;
+ unsigned int found = 0;
+
+ /* Search bits for num_bits contiguous free bits */
+ while ( bit < bits_len ) {
+ if ( ( mask & *bits ) == 0 ) {
+ if ( ++found == num_bits )
+ goto found;
+ } else {
+ found = 0;
+ }
+ bit++;
+ mask = ( mask << 1 ) | ( mask >> ( 8 * sizeof ( mask ) - 1 ) );
+ if ( mask == 1 )
+ bits++;
+ }
+ return -ENFILE;
+
+ found:
+ /* Mark bits as in-use */
+ do {
+ *bits |= mask;
+ if ( mask == 1 )
+ bits--;
+ mask = ( mask >> 1 ) | ( mask << ( 8 * sizeof ( mask ) - 1 ) );
+ } while ( --found );
+
+ return ( bit - num_bits + 1 );
+}
+
+/**
+ * Free offsets within usage bitmask
+ *
+ * @v bits Usage bitmask
+ * @v bit Starting bit within bitmask
+ * @v num_bits Number of contiguous bits to free within bitmask
+ */
+static void hermon_bitmask_free ( hermon_bitmask_t *bits,
+ int bit, unsigned int num_bits ) {
+ hermon_bitmask_t mask;
+
+ for ( ; num_bits ; bit++, num_bits-- ) {
+ mask = ( 1 << ( bit % ( 8 * sizeof ( mask ) ) ) );
+ bits[ ( bit / ( 8 * sizeof ( mask ) ) ) ] &= ~mask;
+ }
+}
+
+/***************************************************************************
+ *
+ * HCA commands
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Wait for Hermon command completion
+ *
+ * @v hermon Hermon device
+ * @v hcr HCA command registers
+ * @ret rc Return status code
+ */
+static int hermon_cmd_wait ( struct hermon *hermon,
+ struct hermonprm_hca_command_register *hcr ) {
+ unsigned int wait;
+
+ for ( wait = HERMON_HCR_MAX_WAIT_MS ; wait ; wait-- ) {
+ hcr->u.dwords[6] =
+ readl ( hermon->config + HERMON_HCR_REG ( 6 ) );
+ if ( ( MLX_GET ( hcr, go ) == 0 ) &&
+ ( MLX_GET ( hcr, t ) == hermon->toggle ) )
+ return 0;
+ mdelay ( 1 );
+ }
+ return -EBUSY;
+}
+
+/**
+ * Issue HCA command
+ *
+ * @v hermon Hermon device
+ * @v command Command opcode, flags and input/output lengths
+ * @v op_mod Opcode modifier (0 if no modifier applicable)
+ * @v in Input parameters
+ * @v in_mod Input modifier (0 if no modifier applicable)
+ * @v out Output parameters
+ * @ret rc Return status code
+ */
+static int hermon_cmd ( struct hermon *hermon, unsigned long command,
+ unsigned int op_mod, const void *in,
+ unsigned int in_mod, void *out ) {
+ struct hermonprm_hca_command_register hcr;
+ unsigned int opcode = HERMON_HCR_OPCODE ( command );
+ size_t in_len = HERMON_HCR_IN_LEN ( command );
+ size_t out_len = HERMON_HCR_OUT_LEN ( command );
+ void *in_buffer;
+ void *out_buffer;
+ unsigned int status;
+ unsigned int i;
+ int rc;
+
+ assert ( in_len <= HERMON_MBOX_SIZE );
+ assert ( out_len <= HERMON_MBOX_SIZE );
+
+ DBGC2 ( hermon, "Hermon %p command %02x in %zx%s out %zx%s\n",
+ hermon, opcode, in_len,
+ ( ( command & HERMON_HCR_IN_MBOX ) ? "(mbox)" : "" ), out_len,
+ ( ( command & HERMON_HCR_OUT_MBOX ) ? "(mbox)" : "" ) );
+
+ /* Check that HCR is free */
+ if ( ( rc = hermon_cmd_wait ( hermon, &hcr ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p command interface locked\n",
+ hermon );
+ return rc;
+ }
+
+ /* Flip HCR toggle */
+ hermon->toggle = ( 1 - hermon->toggle );
+
+ /* Prepare HCR */
+ memset ( &hcr, 0, sizeof ( hcr ) );
+ in_buffer = &hcr.u.dwords[0];
+ if ( in_len && ( command & HERMON_HCR_IN_MBOX ) ) {
+ memset ( hermon->mailbox_in, 0, HERMON_MBOX_SIZE );
+ in_buffer = hermon->mailbox_in;
+ MLX_FILL_H ( &hcr, 0, in_param_h, virt_to_bus ( in_buffer ) );
+ MLX_FILL_1 ( &hcr, 1, in_param_l, virt_to_bus ( in_buffer ) );
+ }
+ memcpy ( in_buffer, in, in_len );
+ MLX_FILL_1 ( &hcr, 2, input_modifier, in_mod );
+ out_buffer = &hcr.u.dwords[3];
+ if ( out_len && ( command & HERMON_HCR_OUT_MBOX ) ) {
+ out_buffer = hermon->mailbox_out;
+ MLX_FILL_H ( &hcr, 3, out_param_h,
+ virt_to_bus ( out_buffer ) );
+ MLX_FILL_1 ( &hcr, 4, out_param_l,
+ virt_to_bus ( out_buffer ) );
+ }
+ MLX_FILL_4 ( &hcr, 6,
+ opcode, opcode,
+ opcode_modifier, op_mod,
+ go, 1,
+ t, hermon->toggle );
+ DBGC ( hermon, "Hermon %p issuing command %04x\n",
+ hermon, opcode );
+ DBGC2_HDA ( hermon, virt_to_phys ( hermon->config + HERMON_HCR_BASE ),
+ &hcr, sizeof ( hcr ) );
+ if ( in_len && ( command & HERMON_HCR_IN_MBOX ) ) {
+ DBGC2 ( hermon, "Input mailbox:\n" );
+ DBGC2_HDA ( hermon, virt_to_phys ( in_buffer ), in_buffer,
+ ( ( in_len < 512 ) ? in_len : 512 ) );
+ }
+
+ /* Issue command */
+ for ( i = 0 ; i < ( sizeof ( hcr ) / sizeof ( hcr.u.dwords[0] ) ) ;
+ i++ ) {
+ writel ( hcr.u.dwords[i],
+ hermon->config + HERMON_HCR_REG ( i ) );
+ barrier();
+ }
+
+ /* Wait for command completion */
+ if ( ( rc = hermon_cmd_wait ( hermon, &hcr ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p timed out waiting for command:\n",
+ hermon );
+ DBGC_HDA ( hermon,
+ virt_to_phys ( hermon->config + HERMON_HCR_BASE ),
+ &hcr, sizeof ( hcr ) );
+ return rc;
+ }
+
+ /* Check command status */
+ status = MLX_GET ( &hcr, status );
+ if ( status != 0 ) {
+ DBGC ( hermon, "Hermon %p command failed with status %02x:\n",
+ hermon, status );
+ DBGC_HDA ( hermon,
+ virt_to_phys ( hermon->config + HERMON_HCR_BASE ),
+ &hcr, sizeof ( hcr ) );
+ return -EIO;
+ }
+
+ /* Read output parameters, if any */
+ hcr.u.dwords[3] = readl ( hermon->config + HERMON_HCR_REG ( 3 ) );
+ hcr.u.dwords[4] = readl ( hermon->config + HERMON_HCR_REG ( 4 ) );
+ memcpy ( out, out_buffer, out_len );
+ if ( out_len ) {
+ DBGC2 ( hermon, "Output%s:\n",
+ ( command & HERMON_HCR_OUT_MBOX ) ? " mailbox" : "" );
+ DBGC2_HDA ( hermon, virt_to_phys ( out_buffer ), out_buffer,
+ ( ( out_len < 512 ) ? out_len : 512 ) );
+ }
+
+ return 0;
+}
+
+static inline int
+hermon_cmd_query_dev_cap ( struct hermon *hermon,
+ struct hermonprm_query_dev_cap *dev_cap ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_OUT_CMD ( HERMON_HCR_QUERY_DEV_CAP,
+ 1, sizeof ( *dev_cap ) ),
+ 0, NULL, 0, dev_cap );
+}
+
+static inline int
+hermon_cmd_query_fw ( struct hermon *hermon, struct hermonprm_query_fw *fw ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_OUT_CMD ( HERMON_HCR_QUERY_FW,
+ 1, sizeof ( *fw ) ),
+ 0, NULL, 0, fw );
+}
+
+static inline int
+hermon_cmd_init_hca ( struct hermon *hermon,
+ const struct hermonprm_init_hca *init_hca ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_INIT_HCA,
+ 1, sizeof ( *init_hca ) ),
+ 0, init_hca, 0, NULL );
+}
+
+static inline int
+hermon_cmd_close_hca ( struct hermon *hermon ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_VOID_CMD ( HERMON_HCR_CLOSE_HCA ),
+ 0, NULL, 0, NULL );
+}
+
+static inline int
+hermon_cmd_init_port ( struct hermon *hermon, unsigned int port ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_VOID_CMD ( HERMON_HCR_INIT_PORT ),
+ 0, NULL, port, NULL );
+}
+
+static inline int
+hermon_cmd_close_port ( struct hermon *hermon, unsigned int port ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_VOID_CMD ( HERMON_HCR_CLOSE_PORT ),
+ 0, NULL, port, NULL );
+}
+
+static inline int
+hermon_cmd_set_port ( struct hermon *hermon, int is_ethernet,
+ unsigned int port_selector,
+ const union hermonprm_set_port *set_port ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_SET_PORT,
+ 1, sizeof ( *set_port ) ),
+ is_ethernet, set_port, port_selector, NULL );
+}
+
+static inline int
+hermon_cmd_sw2hw_mpt ( struct hermon *hermon, unsigned int index,
+ const struct hermonprm_mpt *mpt ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_SW2HW_MPT,
+ 1, sizeof ( *mpt ) ),
+ 0, mpt, index, NULL );
+}
+
+static inline int
+hermon_cmd_write_mtt ( struct hermon *hermon,
+ const struct hermonprm_write_mtt *write_mtt ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_WRITE_MTT,
+ 1, sizeof ( *write_mtt ) ),
+ 0, write_mtt, 1, NULL );
+}
+
+static inline int
+hermon_cmd_map_eq ( struct hermon *hermon, unsigned long index_map,
+ const struct hermonprm_event_mask *mask ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_MAP_EQ,
+ 0, sizeof ( *mask ) ),
+ 0, mask, index_map, NULL );
+}
+
+static inline int
+hermon_cmd_sw2hw_eq ( struct hermon *hermon, unsigned int index,
+ const struct hermonprm_eqc *eqctx ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_SW2HW_EQ,
+ 1, sizeof ( *eqctx ) ),
+ 0, eqctx, index, NULL );
+}
+
+static inline int
+hermon_cmd_hw2sw_eq ( struct hermon *hermon, unsigned int index,
+ struct hermonprm_eqc *eqctx ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_OUT_CMD ( HERMON_HCR_HW2SW_EQ,
+ 1, sizeof ( *eqctx ) ),
+ 1, NULL, index, eqctx );
+}
+
+static inline int
+hermon_cmd_query_eq ( struct hermon *hermon, unsigned int index,
+ struct hermonprm_eqc *eqctx ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_OUT_CMD ( HERMON_HCR_QUERY_EQ,
+ 1, sizeof ( *eqctx ) ),
+ 0, NULL, index, eqctx );
+}
+
+static inline int
+hermon_cmd_sw2hw_cq ( struct hermon *hermon, unsigned long cqn,
+ const struct hermonprm_completion_queue_context *cqctx ){
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_SW2HW_CQ,
+ 1, sizeof ( *cqctx ) ),
+ 0, cqctx, cqn, NULL );
+}
+
+static inline int
+hermon_cmd_hw2sw_cq ( struct hermon *hermon, unsigned long cqn,
+ struct hermonprm_completion_queue_context *cqctx ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_OUT_CMD ( HERMON_HCR_HW2SW_CQ,
+ 1, sizeof ( *cqctx ) ),
+ 0, NULL, cqn, cqctx );
+}
+
+static inline int
+hermon_cmd_query_cq ( struct hermon *hermon, unsigned long cqn,
+ struct hermonprm_completion_queue_context *cqctx ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_OUT_CMD ( HERMON_HCR_QUERY_CQ,
+ 1, sizeof ( *cqctx ) ),
+ 0, NULL, cqn, cqctx );
+}
+
+static inline int
+hermon_cmd_rst2init_qp ( struct hermon *hermon, unsigned long qpn,
+ const struct hermonprm_qp_ee_state_transitions *ctx ){
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_RST2INIT_QP,
+ 1, sizeof ( *ctx ) ),
+ 0, ctx, qpn, NULL );
+}
+
+static inline int
+hermon_cmd_init2rtr_qp ( struct hermon *hermon, unsigned long qpn,
+ const struct hermonprm_qp_ee_state_transitions *ctx ){
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_INIT2RTR_QP,
+ 1, sizeof ( *ctx ) ),
+ 0, ctx, qpn, NULL );
+}
+
+static inline int
+hermon_cmd_rtr2rts_qp ( struct hermon *hermon, unsigned long qpn,
+ const struct hermonprm_qp_ee_state_transitions *ctx ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_RTR2RTS_QP,
+ 1, sizeof ( *ctx ) ),
+ 0, ctx, qpn, NULL );
+}
+
+static inline int
+hermon_cmd_rts2rts_qp ( struct hermon *hermon, unsigned long qpn,
+ const struct hermonprm_qp_ee_state_transitions *ctx ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_RTS2RTS_QP,
+ 1, sizeof ( *ctx ) ),
+ 0, ctx, qpn, NULL );
+}
+
+static inline int
+hermon_cmd_2rst_qp ( struct hermon *hermon, unsigned long qpn ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_VOID_CMD ( HERMON_HCR_2RST_QP ),
+ 0x03, NULL, qpn, NULL );
+}
+
+static inline int
+hermon_cmd_query_qp ( struct hermon *hermon, unsigned long qpn,
+ struct hermonprm_qp_ee_state_transitions *ctx ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_OUT_CMD ( HERMON_HCR_QUERY_QP,
+ 1, sizeof ( *ctx ) ),
+ 0, NULL, qpn, ctx );
+}
+
+static inline int
+hermon_cmd_conf_special_qp ( struct hermon *hermon, unsigned int internal_qps,
+ unsigned long base_qpn ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_VOID_CMD ( HERMON_HCR_CONF_SPECIAL_QP ),
+ internal_qps, NULL, base_qpn, NULL );
+}
+
+static inline int
+hermon_cmd_mad_ifc ( struct hermon *hermon, unsigned int port,
+ union hermonprm_mad *mad ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_INOUT_CMD ( HERMON_HCR_MAD_IFC,
+ 1, sizeof ( *mad ),
+ 1, sizeof ( *mad ) ),
+ 0x03, mad, port, mad );
+}
+
+static inline int
+hermon_cmd_read_mcg ( struct hermon *hermon, unsigned int index,
+ struct hermonprm_mcg_entry *mcg ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_OUT_CMD ( HERMON_HCR_READ_MCG,
+ 1, sizeof ( *mcg ) ),
+ 0, NULL, index, mcg );
+}
+
+static inline int
+hermon_cmd_write_mcg ( struct hermon *hermon, unsigned int index,
+ const struct hermonprm_mcg_entry *mcg ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_WRITE_MCG,
+ 1, sizeof ( *mcg ) ),
+ 0, mcg, index, NULL );
+}
+
+static inline int
+hermon_cmd_mgid_hash ( struct hermon *hermon, const union ib_gid *gid,
+ struct hermonprm_mgm_hash *hash ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_INOUT_CMD ( HERMON_HCR_MGID_HASH,
+ 1, sizeof ( *gid ),
+ 0, sizeof ( *hash ) ),
+ 0, gid, 0, hash );
+}
+
+static inline int
+hermon_cmd_mod_stat_cfg ( struct hermon *hermon, unsigned int mode,
+ unsigned int input_mod,
+ struct hermonprm_scalar_parameter *portion ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_INOUT_CMD ( HERMON_HCR_MOD_STAT_CFG,
+ 0, sizeof ( *portion ),
+ 0, sizeof ( *portion ) ),
+ mode, portion, input_mod, portion );
+}
+
+static inline int
+hermon_cmd_query_port ( struct hermon *hermon, unsigned int port,
+ struct hermonprm_query_port_cap *query_port ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_OUT_CMD ( HERMON_HCR_QUERY_PORT,
+ 1, sizeof ( *query_port ) ),
+ 0, NULL, port, query_port );
+}
+
+static inline int
+hermon_cmd_sense_port ( struct hermon *hermon, unsigned int port,
+ struct hermonprm_sense_port *port_type ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_OUT_CMD ( HERMON_HCR_SENSE_PORT,
+ 0, sizeof ( *port_type ) ),
+ 0, NULL, port, port_type );
+}
+
+static inline int
+hermon_cmd_run_fw ( struct hermon *hermon ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_VOID_CMD ( HERMON_HCR_RUN_FW ),
+ 0, NULL, 0, NULL );
+}
+
+static inline int
+hermon_cmd_unmap_icm ( struct hermon *hermon, unsigned int page_count,
+ const struct hermonprm_scalar_parameter *offset ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_UNMAP_ICM,
+ 0, sizeof ( *offset ) ),
+ 0, offset, page_count, NULL );
+}
+
+static inline int
+hermon_cmd_map_icm ( struct hermon *hermon,
+ const struct hermonprm_virtual_physical_mapping *map ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_MAP_ICM,
+ 1, sizeof ( *map ) ),
+ 0, map, 1, NULL );
+}
+
+static inline int
+hermon_cmd_unmap_icm_aux ( struct hermon *hermon ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_VOID_CMD ( HERMON_HCR_UNMAP_ICM_AUX ),
+ 0, NULL, 0, NULL );
+}
+
+static inline int
+hermon_cmd_map_icm_aux ( struct hermon *hermon,
+ const struct hermonprm_virtual_physical_mapping *map ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_MAP_ICM_AUX,
+ 1, sizeof ( *map ) ),
+ 0, map, 1, NULL );
+}
+
+static inline int
+hermon_cmd_set_icm_size ( struct hermon *hermon,
+ const struct hermonprm_scalar_parameter *icm_size,
+ struct hermonprm_scalar_parameter *icm_aux_size ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_INOUT_CMD ( HERMON_HCR_SET_ICM_SIZE,
+ 0, sizeof ( *icm_size ),
+ 0, sizeof (*icm_aux_size) ),
+ 0, icm_size, 0, icm_aux_size );
+}
+
+static inline int
+hermon_cmd_unmap_fa ( struct hermon *hermon ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_VOID_CMD ( HERMON_HCR_UNMAP_FA ),
+ 0, NULL, 0, NULL );
+}
+
+static inline int
+hermon_cmd_map_fa ( struct hermon *hermon,
+ const struct hermonprm_virtual_physical_mapping *map ) {
+ return hermon_cmd ( hermon,
+ HERMON_HCR_IN_CMD ( HERMON_HCR_MAP_FA,
+ 1, sizeof ( *map ) ),
+ 0, map, 1, NULL );
+}
+
+/***************************************************************************
+ *
+ * Memory translation table operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Allocate MTT entries
+ *
+ * @v hermon Hermon device
+ * @v memory Memory to map into MTT
+ * @v len Length of memory to map
+ * @v mtt MTT descriptor to fill in
+ * @ret rc Return status code
+ */
+static int hermon_alloc_mtt ( struct hermon *hermon,
+ const void *memory, size_t len,
+ struct hermon_mtt *mtt ) {
+ struct hermonprm_write_mtt write_mtt;
+ physaddr_t start;
+ physaddr_t addr;
+ unsigned int page_offset;
+ unsigned int num_pages;
+ int mtt_offset;
+ unsigned int mtt_base_addr;
+ unsigned int i;
+ int rc;
+
+ /* Find available MTT entries */
+ start = virt_to_phys ( memory );
+ page_offset = ( start & ( HERMON_PAGE_SIZE - 1 ) );
+ start -= page_offset;
+ len += page_offset;
+ num_pages = ( ( len + HERMON_PAGE_SIZE - 1 ) / HERMON_PAGE_SIZE );
+ mtt_offset = hermon_bitmask_alloc ( hermon->mtt_inuse, HERMON_MAX_MTTS,
+ num_pages );
+ if ( mtt_offset < 0 ) {
+ DBGC ( hermon, "Hermon %p could not allocate %d MTT entries\n",
+ hermon, num_pages );
+ rc = mtt_offset;
+ goto err_mtt_offset;
+ }
+ mtt_base_addr = ( ( hermon->cap.reserved_mtts + mtt_offset ) *
+ hermon->cap.mtt_entry_size );
+ addr = start;
+
+ /* Fill in MTT structure */
+ mtt->mtt_offset = mtt_offset;
+ mtt->num_pages = num_pages;
+ mtt->mtt_base_addr = mtt_base_addr;
+ mtt->page_offset = page_offset;
+
+ /* Construct and issue WRITE_MTT commands */
+ for ( i = 0 ; i < num_pages ; i++ ) {
+ memset ( &write_mtt, 0, sizeof ( write_mtt ) );
+ MLX_FILL_1 ( &write_mtt.mtt_base_addr, 1,
+ value, mtt_base_addr );
+ MLX_FILL_H ( &write_mtt.mtt, 0, ptag_h, addr );
+ MLX_FILL_2 ( &write_mtt.mtt, 1,
+ p, 1,
+ ptag_l, ( addr >> 3 ) );
+ if ( ( rc = hermon_cmd_write_mtt ( hermon,
+ &write_mtt ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not write MTT at %x\n",
+ hermon, mtt_base_addr );
+ goto err_write_mtt;
+ }
+ addr += HERMON_PAGE_SIZE;
+ mtt_base_addr += hermon->cap.mtt_entry_size;
+ }
+
+ DBGC ( hermon, "Hermon %p MTT entries [%#x,%#x] for "
+ "[%08lx,%08lx,%08lx,%08lx)\n", hermon, mtt->mtt_offset,
+ ( mtt->mtt_offset + mtt->num_pages - 1 ), start,
+ ( start + page_offset ), ( start + len ), addr );
+
+ return 0;
+
+ err_write_mtt:
+ hermon_bitmask_free ( hermon->mtt_inuse, mtt_offset, num_pages );
+ err_mtt_offset:
+ return rc;
+}
+
+/**
+ * Free MTT entries
+ *
+ * @v hermon Hermon device
+ * @v mtt MTT descriptor
+ */
+static void hermon_free_mtt ( struct hermon *hermon,
+ struct hermon_mtt *mtt ) {
+
+ DBGC ( hermon, "Hermon %p MTT entries [%#x,%#x] freed\n",
+ hermon, mtt->mtt_offset,
+ ( mtt->mtt_offset + mtt->num_pages - 1 ) );
+ hermon_bitmask_free ( hermon->mtt_inuse, mtt->mtt_offset,
+ mtt->num_pages );
+}
+
+/***************************************************************************
+ *
+ * Static configuration operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Calculate offset within static configuration
+ *
+ * @v field Field
+ * @ret offset Offset
+ */
+#define HERMON_MOD_STAT_CFG_OFFSET( field ) \
+ ( ( MLX_BIT_OFFSET ( struct hermonprm_mod_stat_cfg_st, field ) / 8 ) \
+ & ~( sizeof ( struct hermonprm_scalar_parameter ) - 1 ) )
+
+/**
+ * Query or modify static configuration
+ *
+ * @v hermon Hermon device
+ * @v port Port
+ * @v mode Command mode
+ * @v offset Offset within static configuration
+ * @v stat_cfg Static configuration
+ * @ret rc Return status code
+ */
+static int hermon_mod_stat_cfg ( struct hermon *hermon, unsigned int port,
+ unsigned int mode, unsigned int offset,
+ struct hermonprm_mod_stat_cfg *stat_cfg ) {
+ struct hermonprm_scalar_parameter *portion =
+ ( ( void * ) &stat_cfg->u.bytes[offset] );
+ struct hermonprm_mod_stat_cfg_input_mod mod;
+ int rc;
+
+ /* Sanity check */
+ assert ( ( offset % sizeof ( *portion ) ) == 0 );
+
+ /* Construct input modifier */
+ memset ( &mod, 0, sizeof ( mod ) );
+ MLX_FILL_2 ( &mod, 0,
+ portnum, port,
+ offset, offset );
+
+ /* Issue command */
+ if ( ( rc = hermon_cmd_mod_stat_cfg ( hermon, mode,
+ be32_to_cpu ( mod.u.dwords[0] ),
+ portion ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * MAD operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Issue management datagram
+ *
+ * @v ibdev Infiniband device
+ * @v mad Management datagram
+ * @ret rc Return status code
+ */
+static int hermon_mad ( struct ib_device *ibdev, union ib_mad *mad ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ union hermonprm_mad mad_ifc;
+ int rc;
+
+ linker_assert ( sizeof ( *mad ) == sizeof ( mad_ifc.mad ),
+ mad_size_mismatch );
+
+ /* Copy in request packet */
+ memcpy ( &mad_ifc.mad, mad, sizeof ( mad_ifc.mad ) );
+
+ /* Issue MAD */
+ if ( ( rc = hermon_cmd_mad_ifc ( hermon, ibdev->port,
+ &mad_ifc ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not issue MAD IFC: "
+ "%s\n", hermon, ibdev->port, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Copy out reply packet */
+ memcpy ( mad, &mad_ifc.mad, sizeof ( *mad ) );
+
+ if ( mad->hdr.status != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d MAD IFC status %04x\n",
+ hermon, ibdev->port, ntohs ( mad->hdr.status ) );
+ return -EIO;
+ }
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * Completion queue operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Dump completion queue context (for debugging only)
+ *
+ * @v hermon Hermon device
+ * @v cq Completion queue
+ * @ret rc Return status code
+ */
+static __attribute__ (( unused )) int
+hermon_dump_cqctx ( struct hermon *hermon, struct ib_completion_queue *cq ) {
+ struct hermonprm_completion_queue_context cqctx;
+ int rc;
+
+ memset ( &cqctx, 0, sizeof ( cqctx ) );
+ if ( ( rc = hermon_cmd_query_cq ( hermon, cq->cqn, &cqctx ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p CQN %#lx QUERY_CQ failed: %s\n",
+ hermon, cq->cqn, strerror ( rc ) );
+ return rc;
+ }
+ DBGC ( hermon, "Hermon %p CQN %#lx context:\n", hermon, cq->cqn );
+ DBGC_HDA ( hermon, 0, &cqctx, sizeof ( cqctx ) );
+
+ return 0;
+}
+
+/**
+ * Create completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ * @ret rc Return status code
+ */
+static int hermon_create_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_completion_queue *hermon_cq;
+ struct hermonprm_completion_queue_context cqctx;
+ int cqn_offset;
+ unsigned int i;
+ int rc;
+
+ /* Find a free completion queue number */
+ cqn_offset = hermon_bitmask_alloc ( hermon->cq_inuse,
+ HERMON_MAX_CQS, 1 );
+ if ( cqn_offset < 0 ) {
+ DBGC ( hermon, "Hermon %p out of completion queues\n",
+ hermon );
+ rc = cqn_offset;
+ goto err_cqn_offset;
+ }
+ cq->cqn = ( hermon->cap.reserved_cqs + cqn_offset );
+
+ /* Allocate control structures */
+ hermon_cq = zalloc ( sizeof ( *hermon_cq ) );
+ if ( ! hermon_cq ) {
+ rc = -ENOMEM;
+ goto err_hermon_cq;
+ }
+
+ /* Allocate doorbell */
+ hermon_cq->doorbell = malloc_dma ( sizeof ( hermon_cq->doorbell[0] ),
+ sizeof ( hermon_cq->doorbell[0] ) );
+ if ( ! hermon_cq->doorbell ) {
+ rc = -ENOMEM;
+ goto err_doorbell;
+ }
+ memset ( hermon_cq->doorbell, 0, sizeof ( hermon_cq->doorbell[0] ) );
+
+ /* Allocate completion queue itself */
+ hermon_cq->cqe_size = ( cq->num_cqes * sizeof ( hermon_cq->cqe[0] ) );
+ hermon_cq->cqe = malloc_dma ( hermon_cq->cqe_size,
+ sizeof ( hermon_cq->cqe[0] ) );
+ if ( ! hermon_cq->cqe ) {
+ rc = -ENOMEM;
+ goto err_cqe;
+ }
+ memset ( hermon_cq->cqe, 0, hermon_cq->cqe_size );
+ for ( i = 0 ; i < cq->num_cqes ; i++ ) {
+ MLX_FILL_1 ( &hermon_cq->cqe[i].normal, 7, owner, 1 );
+ }
+ barrier();
+
+ /* Allocate MTT entries */
+ if ( ( rc = hermon_alloc_mtt ( hermon, hermon_cq->cqe,
+ hermon_cq->cqe_size,
+ &hermon_cq->mtt ) ) != 0 )
+ goto err_alloc_mtt;
+
+ /* Hand queue over to hardware */
+ memset ( &cqctx, 0, sizeof ( cqctx ) );
+ MLX_FILL_1 ( &cqctx, 0, st, 0xa /* "Event fired" */ );
+ MLX_FILL_1 ( &cqctx, 2,
+ page_offset, ( hermon_cq->mtt.page_offset >> 5 ) );
+ MLX_FILL_2 ( &cqctx, 3,
+ usr_page, HERMON_UAR_NON_EQ_PAGE,
+ log_cq_size, fls ( cq->num_cqes - 1 ) );
+ MLX_FILL_1 ( &cqctx, 5, c_eqn, hermon->eq.eqn );
+ MLX_FILL_H ( &cqctx, 6, mtt_base_addr_h,
+ hermon_cq->mtt.mtt_base_addr );
+ MLX_FILL_1 ( &cqctx, 7, mtt_base_addr_l,
+ ( hermon_cq->mtt.mtt_base_addr >> 3 ) );
+ MLX_FILL_H ( &cqctx, 14, db_record_addr_h,
+ virt_to_phys ( hermon_cq->doorbell ) );
+ MLX_FILL_1 ( &cqctx, 15, db_record_addr_l,
+ ( virt_to_phys ( hermon_cq->doorbell ) >> 3 ) );
+ if ( ( rc = hermon_cmd_sw2hw_cq ( hermon, cq->cqn, &cqctx ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p CQN %#lx SW2HW_CQ failed: %s\n",
+ hermon, cq->cqn, strerror ( rc ) );
+ goto err_sw2hw_cq;
+ }
+
+ DBGC ( hermon, "Hermon %p CQN %#lx ring [%08lx,%08lx), doorbell "
+ "%08lx\n", hermon, cq->cqn, virt_to_phys ( hermon_cq->cqe ),
+ ( virt_to_phys ( hermon_cq->cqe ) + hermon_cq->cqe_size ),
+ virt_to_phys ( hermon_cq->doorbell ) );
+ ib_cq_set_drvdata ( cq, hermon_cq );
+ return 0;
+
+ err_sw2hw_cq:
+ hermon_free_mtt ( hermon, &hermon_cq->mtt );
+ err_alloc_mtt:
+ free_dma ( hermon_cq->cqe, hermon_cq->cqe_size );
+ err_cqe:
+ free_dma ( hermon_cq->doorbell, sizeof ( hermon_cq->doorbell[0] ) );
+ err_doorbell:
+ free ( hermon_cq );
+ err_hermon_cq:
+ hermon_bitmask_free ( hermon->cq_inuse, cqn_offset, 1 );
+ err_cqn_offset:
+ return rc;
+}
+
+/**
+ * Destroy completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+static void hermon_destroy_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
+ struct hermonprm_completion_queue_context cqctx;
+ int cqn_offset;
+ int rc;
+
+ /* Take ownership back from hardware */
+ if ( ( rc = hermon_cmd_hw2sw_cq ( hermon, cq->cqn, &cqctx ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p CQN %#lx FATAL HW2SW_CQ failed: "
+ "%s\n", hermon, cq->cqn, strerror ( rc ) );
+ /* Leak memory and return; at least we avoid corruption */
+ return;
+ }
+
+ /* Free MTT entries */
+ hermon_free_mtt ( hermon, &hermon_cq->mtt );
+
+ /* Free memory */
+ free_dma ( hermon_cq->cqe, hermon_cq->cqe_size );
+ free_dma ( hermon_cq->doorbell, sizeof ( hermon_cq->doorbell[0] ) );
+ free ( hermon_cq );
+
+ /* Mark queue number as free */
+ cqn_offset = ( cq->cqn - hermon->cap.reserved_cqs );
+ hermon_bitmask_free ( hermon->cq_inuse, cqn_offset, 1 );
+
+ ib_cq_set_drvdata ( cq, NULL );
+}
+
+/***************************************************************************
+ *
+ * Queue pair operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Assign queue pair number
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static int hermon_alloc_qpn ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ unsigned int port_offset;
+ int qpn_offset;
+
+ /* Calculate queue pair number */
+ port_offset = ( ibdev->port - HERMON_PORT_BASE );
+
+ switch ( qp->type ) {
+ case IB_QPT_SMI:
+ qp->qpn = ( hermon->special_qpn_base + port_offset );
+ return 0;
+ case IB_QPT_GSI:
+ qp->qpn = ( hermon->special_qpn_base + 2 + port_offset );
+ return 0;
+ case IB_QPT_UD:
+ case IB_QPT_RC:
+ case IB_QPT_ETH:
+ /* Find a free queue pair number */
+ qpn_offset = hermon_bitmask_alloc ( hermon->qp_inuse,
+ HERMON_MAX_QPS, 1 );
+ if ( qpn_offset < 0 ) {
+ DBGC ( hermon, "Hermon %p out of queue pairs\n",
+ hermon );
+ return qpn_offset;
+ }
+ qp->qpn = ( ( random() & HERMON_QPN_RANDOM_MASK ) |
+ ( hermon->qpn_base + qpn_offset ) );
+ return 0;
+ default:
+ DBGC ( hermon, "Hermon %p unsupported QP type %d\n",
+ hermon, qp->type );
+ return -ENOTSUP;
+ }
+}
+
+/**
+ * Free queue pair number
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+static void hermon_free_qpn ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ int qpn_offset;
+
+ qpn_offset = ( ( qp->qpn & ~HERMON_QPN_RANDOM_MASK )
+ - hermon->qpn_base );
+ if ( qpn_offset >= 0 )
+ hermon_bitmask_free ( hermon->qp_inuse, qpn_offset, 1 );
+}
+
+/**
+ * Calculate transmission rate
+ *
+ * @v av Address vector
+ * @ret hermon_rate Hermon rate
+ */
+static unsigned int hermon_rate ( struct ib_address_vector *av ) {
+ return ( ( ( av->rate >= IB_RATE_2_5 ) && ( av->rate <= IB_RATE_120 ) )
+ ? ( av->rate + 5 ) : 0 );
+}
+
+/**
+ * Calculate schedule queue
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret sched_queue Schedule queue
+ */
+static unsigned int hermon_sched_queue ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ return ( ( ( qp->type == IB_QPT_SMI ) ?
+ HERMON_SCHED_QP0 : HERMON_SCHED_DEFAULT ) |
+ ( ( ibdev->port - 1 ) << 6 ) );
+}
+
+/** Queue pair transport service type map */
+static uint8_t hermon_qp_st[] = {
+ [IB_QPT_SMI] = HERMON_ST_MLX,
+ [IB_QPT_GSI] = HERMON_ST_MLX,
+ [IB_QPT_UD] = HERMON_ST_UD,
+ [IB_QPT_RC] = HERMON_ST_RC,
+ [IB_QPT_ETH] = HERMON_ST_MLX,
+};
+
+/**
+ * Dump queue pair context (for debugging only)
+ *
+ * @v hermon Hermon device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static __attribute__ (( unused )) int
+hermon_dump_qpctx ( struct hermon *hermon, struct ib_queue_pair *qp ) {
+ struct hermonprm_qp_ee_state_transitions qpctx;
+ int rc;
+
+ memset ( &qpctx, 0, sizeof ( qpctx ) );
+ if ( ( rc = hermon_cmd_query_qp ( hermon, qp->qpn, &qpctx ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p QPN %#lx QUERY_QP failed: %s\n",
+ hermon, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+ DBGC ( hermon, "Hermon %p QPN %#lx context:\n", hermon, qp->qpn );
+ DBGC_HDA ( hermon, 0, &qpctx.u.dwords[2], ( sizeof ( qpctx ) - 8 ) );
+
+ return 0;
+}
+
+/**
+ * Create queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static int hermon_create_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_queue_pair *hermon_qp;
+ struct hermonprm_qp_ee_state_transitions qpctx;
+ int rc;
+
+ /* Calculate queue pair number */
+ if ( ( rc = hermon_alloc_qpn ( ibdev, qp ) ) != 0 )
+ goto err_alloc_qpn;
+
+ /* Allocate control structures */
+ hermon_qp = zalloc ( sizeof ( *hermon_qp ) );
+ if ( ! hermon_qp ) {
+ rc = -ENOMEM;
+ goto err_hermon_qp;
+ }
+
+ /* Allocate doorbells */
+ hermon_qp->recv.doorbell =
+ malloc_dma ( sizeof ( hermon_qp->recv.doorbell[0] ),
+ sizeof ( hermon_qp->recv.doorbell[0] ) );
+ if ( ! hermon_qp->recv.doorbell ) {
+ rc = -ENOMEM;
+ goto err_recv_doorbell;
+ }
+ memset ( hermon_qp->recv.doorbell, 0,
+ sizeof ( hermon_qp->recv.doorbell[0] ) );
+ hermon_qp->send.doorbell =
+ ( hermon->uar + HERMON_UAR_NON_EQ_PAGE * HERMON_PAGE_SIZE +
+ HERMON_DB_POST_SND_OFFSET );
+
+ /* Allocate work queue buffer */
+ hermon_qp->send.num_wqes = ( qp->send.num_wqes /* headroom */ + 1 +
+ ( 2048 / sizeof ( hermon_qp->send.wqe[0] ) ) );
+ hermon_qp->send.num_wqes =
+ ( 1 << fls ( hermon_qp->send.num_wqes - 1 ) ); /* round up */
+ hermon_qp->send.wqe_size = ( hermon_qp->send.num_wqes *
+ sizeof ( hermon_qp->send.wqe[0] ) );
+ hermon_qp->recv.wqe_size = ( qp->recv.num_wqes *
+ sizeof ( hermon_qp->recv.wqe[0] ) );
+ hermon_qp->wqe_size = ( hermon_qp->send.wqe_size +
+ hermon_qp->recv.wqe_size );
+ hermon_qp->wqe = malloc_dma ( hermon_qp->wqe_size,
+ sizeof ( hermon_qp->send.wqe[0] ) );
+ if ( ! hermon_qp->wqe ) {
+ rc = -ENOMEM;
+ goto err_alloc_wqe;
+ }
+ hermon_qp->send.wqe = hermon_qp->wqe;
+ memset ( hermon_qp->send.wqe, 0xff, hermon_qp->send.wqe_size );
+ hermon_qp->recv.wqe = ( hermon_qp->wqe + hermon_qp->send.wqe_size );
+ memset ( hermon_qp->recv.wqe, 0, hermon_qp->recv.wqe_size );
+
+ /* Allocate MTT entries */
+ if ( ( rc = hermon_alloc_mtt ( hermon, hermon_qp->wqe,
+ hermon_qp->wqe_size,
+ &hermon_qp->mtt ) ) != 0 ) {
+ goto err_alloc_mtt;
+ }
+
+ /* Transition queue to INIT state */
+ memset ( &qpctx, 0, sizeof ( qpctx ) );
+ MLX_FILL_2 ( &qpctx, 2,
+ qpc_eec_data.pm_state, HERMON_PM_STATE_MIGRATED,
+ qpc_eec_data.st, hermon_qp_st[qp->type] );
+ MLX_FILL_1 ( &qpctx, 3, qpc_eec_data.pd, HERMON_GLOBAL_PD );
+ MLX_FILL_4 ( &qpctx, 4,
+ qpc_eec_data.log_rq_size, fls ( qp->recv.num_wqes - 1 ),
+ qpc_eec_data.log_rq_stride,
+ ( fls ( sizeof ( hermon_qp->recv.wqe[0] ) - 1 ) - 4 ),
+ qpc_eec_data.log_sq_size,
+ fls ( hermon_qp->send.num_wqes - 1 ),
+ qpc_eec_data.log_sq_stride,
+ ( fls ( sizeof ( hermon_qp->send.wqe[0] ) - 1 ) - 4 ) );
+ MLX_FILL_1 ( &qpctx, 5,
+ qpc_eec_data.usr_page, HERMON_UAR_NON_EQ_PAGE );
+ MLX_FILL_1 ( &qpctx, 33, qpc_eec_data.cqn_snd, qp->send.cq->cqn );
+ MLX_FILL_4 ( &qpctx, 38,
+ qpc_eec_data.rre, 1,
+ qpc_eec_data.rwe, 1,
+ qpc_eec_data.rae, 1,
+ qpc_eec_data.page_offset,
+ ( hermon_qp->mtt.page_offset >> 6 ) );
+ MLX_FILL_1 ( &qpctx, 41, qpc_eec_data.cqn_rcv, qp->recv.cq->cqn );
+ MLX_FILL_H ( &qpctx, 42, qpc_eec_data.db_record_addr_h,
+ virt_to_phys ( hermon_qp->recv.doorbell ) );
+ MLX_FILL_1 ( &qpctx, 43, qpc_eec_data.db_record_addr_l,
+ ( virt_to_phys ( hermon_qp->recv.doorbell ) >> 2 ) );
+ MLX_FILL_H ( &qpctx, 52, qpc_eec_data.mtt_base_addr_h,
+ hermon_qp->mtt.mtt_base_addr );
+ MLX_FILL_1 ( &qpctx, 53, qpc_eec_data.mtt_base_addr_l,
+ ( hermon_qp->mtt.mtt_base_addr >> 3 ) );
+ if ( ( rc = hermon_cmd_rst2init_qp ( hermon, qp->qpn,
+ &qpctx ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p QPN %#lx RST2INIT_QP failed: %s\n",
+ hermon, qp->qpn, strerror ( rc ) );
+ goto err_rst2init_qp;
+ }
+ hermon_qp->state = HERMON_QP_ST_INIT;
+
+ DBGC ( hermon, "Hermon %p QPN %#lx send ring [%08lx,%08lx), doorbell "
+ "%08lx\n", hermon, qp->qpn,
+ virt_to_phys ( hermon_qp->send.wqe ),
+ ( virt_to_phys ( hermon_qp->send.wqe ) +
+ hermon_qp->send.wqe_size ),
+ virt_to_phys ( hermon_qp->send.doorbell ) );
+ DBGC ( hermon, "Hermon %p QPN %#lx receive ring [%08lx,%08lx), "
+ "doorbell %08lx\n", hermon, qp->qpn,
+ virt_to_phys ( hermon_qp->recv.wqe ),
+ ( virt_to_phys ( hermon_qp->recv.wqe ) +
+ hermon_qp->recv.wqe_size ),
+ virt_to_phys ( hermon_qp->recv.doorbell ) );
+ DBGC ( hermon, "Hermon %p QPN %#lx send CQN %#lx receive CQN %#lx\n",
+ hermon, qp->qpn, qp->send.cq->cqn, qp->recv.cq->cqn );
+ ib_qp_set_drvdata ( qp, hermon_qp );
+ return 0;
+
+ hermon_cmd_2rst_qp ( hermon, qp->qpn );
+ err_rst2init_qp:
+ hermon_free_mtt ( hermon, &hermon_qp->mtt );
+ err_alloc_mtt:
+ free_dma ( hermon_qp->wqe, hermon_qp->wqe_size );
+ err_alloc_wqe:
+ free_dma ( hermon_qp->recv.doorbell,
+ sizeof ( hermon_qp->recv.doorbell[0] ) );
+ err_recv_doorbell:
+ free ( hermon_qp );
+ err_hermon_qp:
+ hermon_free_qpn ( ibdev, qp );
+ err_alloc_qpn:
+ return rc;
+}
+
+/**
+ * Modify queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static int hermon_modify_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
+ struct hermonprm_qp_ee_state_transitions qpctx;
+ int rc;
+
+ /* Transition queue to RTR state, if applicable */
+ if ( hermon_qp->state < HERMON_QP_ST_RTR ) {
+ memset ( &qpctx, 0, sizeof ( qpctx ) );
+ MLX_FILL_2 ( &qpctx, 4,
+ qpc_eec_data.mtu,
+ ( ( qp->type == IB_QPT_ETH ) ?
+ HERMON_MTU_ETH : HERMON_MTU_2048 ),
+ qpc_eec_data.msg_max, 31 );
+ MLX_FILL_1 ( &qpctx, 7,
+ qpc_eec_data.remote_qpn_een, qp->av.qpn );
+ MLX_FILL_1 ( &qpctx, 9,
+ qpc_eec_data.primary_address_path.rlid,
+ qp->av.lid );
+ MLX_FILL_1 ( &qpctx, 10,
+ qpc_eec_data.primary_address_path.max_stat_rate,
+ hermon_rate ( &qp->av ) );
+ memcpy ( &qpctx.u.dwords[12], &qp->av.gid,
+ sizeof ( qp->av.gid ) );
+ MLX_FILL_1 ( &qpctx, 16,
+ qpc_eec_data.primary_address_path.sched_queue,
+ hermon_sched_queue ( ibdev, qp ) );
+ MLX_FILL_1 ( &qpctx, 39,
+ qpc_eec_data.next_rcv_psn, qp->recv.psn );
+ if ( ( rc = hermon_cmd_init2rtr_qp ( hermon, qp->qpn,
+ &qpctx ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p QPN %#lx INIT2RTR_QP failed:"
+ " %s\n", hermon, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+ hermon_qp->state = HERMON_QP_ST_RTR;
+ }
+
+ /* Transition queue to RTS state */
+ if ( hermon_qp->state < HERMON_QP_ST_RTS ) {
+ memset ( &qpctx, 0, sizeof ( qpctx ) );
+ MLX_FILL_1 ( &qpctx, 10,
+ qpc_eec_data.primary_address_path.ack_timeout,
+ 14 /* 4.096us * 2^(14) = 67ms */ );
+ MLX_FILL_2 ( &qpctx, 30,
+ qpc_eec_data.retry_count, HERMON_RETRY_MAX,
+ qpc_eec_data.rnr_retry, HERMON_RETRY_MAX );
+ MLX_FILL_1 ( &qpctx, 32,
+ qpc_eec_data.next_send_psn, qp->send.psn );
+ if ( ( rc = hermon_cmd_rtr2rts_qp ( hermon, qp->qpn,
+ &qpctx ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p QPN %#lx RTR2RTS_QP failed: "
+ "%s\n", hermon, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+ hermon_qp->state = HERMON_QP_ST_RTS;
+ }
+
+ /* Update parameters in RTS state */
+ memset ( &qpctx, 0, sizeof ( qpctx ) );
+ MLX_FILL_1 ( &qpctx, 0, opt_param_mask, HERMON_QP_OPT_PARAM_QKEY );
+ MLX_FILL_1 ( &qpctx, 44, qpc_eec_data.q_key, qp->qkey );
+ if ( ( rc = hermon_cmd_rts2rts_qp ( hermon, qp->qpn, &qpctx ) ) != 0 ){
+ DBGC ( hermon, "Hermon %p QPN %#lx RTS2RTS_QP failed: %s\n",
+ hermon, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Destroy queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+static void hermon_destroy_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
+ int rc;
+
+ /* Take ownership back from hardware */
+ if ( ( rc = hermon_cmd_2rst_qp ( hermon, qp->qpn ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p QPN %#lx FATAL 2RST_QP failed: %s\n",
+ hermon, qp->qpn, strerror ( rc ) );
+ /* Leak memory and return; at least we avoid corruption */
+ return;
+ }
+
+ /* Free MTT entries */
+ hermon_free_mtt ( hermon, &hermon_qp->mtt );
+
+ /* Free memory */
+ free_dma ( hermon_qp->wqe, hermon_qp->wqe_size );
+ free_dma ( hermon_qp->recv.doorbell,
+ sizeof ( hermon_qp->recv.doorbell[0] ) );
+ free ( hermon_qp );
+
+ /* Mark queue number as free */
+ hermon_free_qpn ( ibdev, qp );
+
+ ib_qp_set_drvdata ( qp, NULL );
+}
+
+/***************************************************************************
+ *
+ * Work request operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Construct UD send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @v wqe Send work queue entry
+ * @ret opcode Control opcode
+ */
+static __attribute__ (( unused )) unsigned int
+hermon_fill_nop_send_wqe ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp __unused,
+ struct ib_address_vector *av __unused,
+ struct io_buffer *iobuf __unused,
+ union hermon_send_wqe *wqe ) {
+
+ MLX_FILL_1 ( &wqe->ctrl, 1, ds, ( sizeof ( wqe->ctrl ) / 16 ) );
+ MLX_FILL_1 ( &wqe->ctrl, 2, c, 0x03 /* generate completion */ );
+ return HERMON_OPCODE_NOP;
+}
+
+/**
+ * Construct UD send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @v wqe Send work queue entry
+ * @ret opcode Control opcode
+ */
+static unsigned int
+hermon_fill_ud_send_wqe ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp __unused,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf,
+ union hermon_send_wqe *wqe ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+
+ MLX_FILL_1 ( &wqe->ud.ctrl, 1, ds,
+ ( ( offsetof ( typeof ( wqe->ud ), data[1] ) / 16 ) ) );
+ MLX_FILL_1 ( &wqe->ud.ctrl, 2, c, 0x03 /* generate completion */ );
+ MLX_FILL_2 ( &wqe->ud.ud, 0,
+ ud_address_vector.pd, HERMON_GLOBAL_PD,
+ ud_address_vector.port_number, ibdev->port );
+ MLX_FILL_2 ( &wqe->ud.ud, 1,
+ ud_address_vector.rlid, av->lid,
+ ud_address_vector.g, av->gid_present );
+ MLX_FILL_1 ( &wqe->ud.ud, 2,
+ ud_address_vector.max_stat_rate, hermon_rate ( av ) );
+ MLX_FILL_1 ( &wqe->ud.ud, 3, ud_address_vector.sl, av->sl );
+ memcpy ( &wqe->ud.ud.u.dwords[4], &av->gid, sizeof ( av->gid ) );
+ MLX_FILL_1 ( &wqe->ud.ud, 8, destination_qp, av->qpn );
+ MLX_FILL_1 ( &wqe->ud.ud, 9, q_key, av->qkey );
+ MLX_FILL_1 ( &wqe->ud.data[0], 0, byte_count, iob_len ( iobuf ) );
+ MLX_FILL_1 ( &wqe->ud.data[0], 1, l_key, hermon->lkey );
+ MLX_FILL_H ( &wqe->ud.data[0], 2,
+ local_address_h, virt_to_bus ( iobuf->data ) );
+ MLX_FILL_1 ( &wqe->ud.data[0], 3,
+ local_address_l, virt_to_bus ( iobuf->data ) );
+ return HERMON_OPCODE_SEND;
+}
+
+/**
+ * Construct MLX send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @v wqe Send work queue entry
+ * @ret opcode Control opcode
+ */
+static unsigned int
+hermon_fill_mlx_send_wqe ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf,
+ union hermon_send_wqe *wqe ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct io_buffer headers;
+
+ /* Construct IB headers */
+ iob_populate ( &headers, &wqe->mlx.headers, 0,
+ sizeof ( wqe->mlx.headers ) );
+ iob_reserve ( &headers, sizeof ( wqe->mlx.headers ) );
+ ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), av );
+
+ /* Fill work queue entry */
+ MLX_FILL_1 ( &wqe->mlx.ctrl, 1, ds,
+ ( ( offsetof ( typeof ( wqe->mlx ), data[2] ) / 16 ) ) );
+ MLX_FILL_5 ( &wqe->mlx.ctrl, 2,
+ c, 0x03 /* generate completion */,
+ icrc, 0 /* generate ICRC */,
+ max_statrate, hermon_rate ( av ),
+ slr, 0,
+ v15, ( ( qp->ext_qpn == IB_QPN_SMI ) ? 1 : 0 ) );
+ MLX_FILL_1 ( &wqe->mlx.ctrl, 3, rlid, av->lid );
+ MLX_FILL_1 ( &wqe->mlx.data[0], 0,
+ byte_count, iob_len ( &headers ) );
+ MLX_FILL_1 ( &wqe->mlx.data[0], 1, l_key, hermon->lkey );
+ MLX_FILL_H ( &wqe->mlx.data[0], 2,
+ local_address_h, virt_to_bus ( headers.data ) );
+ MLX_FILL_1 ( &wqe->mlx.data[0], 3,
+ local_address_l, virt_to_bus ( headers.data ) );
+ MLX_FILL_1 ( &wqe->mlx.data[1], 0,
+ byte_count, ( iob_len ( iobuf ) + 4 /* ICRC */ ) );
+ MLX_FILL_1 ( &wqe->mlx.data[1], 1, l_key, hermon->lkey );
+ MLX_FILL_H ( &wqe->mlx.data[1], 2,
+ local_address_h, virt_to_bus ( iobuf->data ) );
+ MLX_FILL_1 ( &wqe->mlx.data[1], 3,
+ local_address_l, virt_to_bus ( iobuf->data ) );
+ return HERMON_OPCODE_SEND;
+}
+
+/**
+ * Construct RC send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @v wqe Send work queue entry
+ * @ret opcode Control opcode
+ */
+static unsigned int
+hermon_fill_rc_send_wqe ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp __unused,
+ struct ib_address_vector *av __unused,
+ struct io_buffer *iobuf,
+ union hermon_send_wqe *wqe ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+
+ MLX_FILL_1 ( &wqe->rc.ctrl, 1, ds,
+ ( ( offsetof ( typeof ( wqe->rc ), data[1] ) / 16 ) ) );
+ MLX_FILL_1 ( &wqe->rc.ctrl, 2, c, 0x03 /* generate completion */ );
+ MLX_FILL_1 ( &wqe->rc.data[0], 0, byte_count, iob_len ( iobuf ) );
+ MLX_FILL_1 ( &wqe->rc.data[0], 1, l_key, hermon->lkey );
+ MLX_FILL_H ( &wqe->rc.data[0], 2,
+ local_address_h, virt_to_bus ( iobuf->data ) );
+ MLX_FILL_1 ( &wqe->rc.data[0], 3,
+ local_address_l, virt_to_bus ( iobuf->data ) );
+ return HERMON_OPCODE_SEND;
+}
+
+/**
+ * Construct Ethernet send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @v wqe Send work queue entry
+ * @ret opcode Control opcode
+ */
+static unsigned int
+hermon_fill_eth_send_wqe ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp __unused,
+ struct ib_address_vector *av __unused,
+ struct io_buffer *iobuf,
+ union hermon_send_wqe *wqe ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+
+ /* Fill work queue entry */
+ MLX_FILL_1 ( &wqe->eth.ctrl, 1, ds,
+ ( ( offsetof ( typeof ( wqe->mlx ), data[1] ) / 16 ) ) );
+ MLX_FILL_2 ( &wqe->eth.ctrl, 2,
+ c, 0x03 /* generate completion */,
+ s, 1 /* inhibit ICRC */ );
+ MLX_FILL_1 ( &wqe->eth.data[0], 0,
+ byte_count, iob_len ( iobuf ) );
+ MLX_FILL_1 ( &wqe->eth.data[0], 1, l_key, hermon->lkey );
+ MLX_FILL_H ( &wqe->eth.data[0], 2,
+ local_address_h, virt_to_bus ( iobuf->data ) );
+ MLX_FILL_1 ( &wqe->eth.data[0], 3,
+ local_address_l, virt_to_bus ( iobuf->data ) );
+ return HERMON_OPCODE_SEND;
+}
+
+/** Work queue entry constructors */
+static unsigned int
+( * hermon_fill_send_wqe[] ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf,
+ union hermon_send_wqe *wqe ) = {
+ [IB_QPT_SMI] = hermon_fill_mlx_send_wqe,
+ [IB_QPT_GSI] = hermon_fill_mlx_send_wqe,
+ [IB_QPT_UD] = hermon_fill_ud_send_wqe,
+ [IB_QPT_RC] = hermon_fill_rc_send_wqe,
+ [IB_QPT_ETH] = hermon_fill_eth_send_wqe,
+};
+
+/**
+ * Post send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int hermon_post_send ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
+ struct ib_work_queue *wq = &qp->send;
+ struct hermon_send_work_queue *hermon_send_wq = &hermon_qp->send;
+ union hermon_send_wqe *wqe;
+ union hermonprm_doorbell_register db_reg;
+ unsigned long wqe_idx_mask;
+ unsigned long wqe_idx;
+ unsigned int owner;
+ unsigned int opcode;
+
+ /* Allocate work queue entry */
+ wqe_idx = ( wq->next_idx & ( hermon_send_wq->num_wqes - 1 ) );
+ owner = ( ( wq->next_idx & hermon_send_wq->num_wqes ) ? 1 : 0 );
+ wqe_idx_mask = ( wq->num_wqes - 1 );
+ if ( wq->iobufs[ wqe_idx & wqe_idx_mask ] ) {
+ DBGC ( hermon, "Hermon %p QPN %#lx send queue full",
+ hermon, qp->qpn );
+ return -ENOBUFS;
+ }
+ wq->iobufs[ wqe_idx & wqe_idx_mask ] = iobuf;
+ wqe = &hermon_send_wq->wqe[wqe_idx];
+
+ /* Construct work queue entry */
+ memset ( ( ( ( void * ) wqe ) + 4 /* avoid ctrl.owner */ ), 0,
+ ( sizeof ( *wqe ) - 4 ) );
+ assert ( qp->type < ( sizeof ( hermon_fill_send_wqe ) /
+ sizeof ( hermon_fill_send_wqe[0] ) ) );
+ assert ( hermon_fill_send_wqe[qp->type] != NULL );
+ opcode = hermon_fill_send_wqe[qp->type] ( ibdev, qp, av, iobuf, wqe );
+ barrier();
+ MLX_FILL_2 ( &wqe->ctrl, 0,
+ opcode, opcode,
+ owner, owner );
+ DBGCP ( hermon, "Hermon %p QPN %#lx posting send WQE %#lx:\n",
+ hermon, qp->qpn, wqe_idx );
+ DBGCP_HDA ( hermon, virt_to_phys ( wqe ), wqe, sizeof ( *wqe ) );
+
+ /* Ring doorbell register */
+ MLX_FILL_1 ( &db_reg.send, 0, qn, qp->qpn );
+ barrier();
+ writel ( db_reg.dword[0], hermon_send_wq->doorbell );
+
+ /* Update work queue's index */
+ wq->next_idx++;
+
+ return 0;
+}
+
+/**
+ * Post receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int hermon_post_recv ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
+ struct ib_work_queue *wq = &qp->recv;
+ struct hermon_recv_work_queue *hermon_recv_wq = &hermon_qp->recv;
+ struct hermonprm_recv_wqe *wqe;
+ unsigned int wqe_idx_mask;
+
+ /* Allocate work queue entry */
+ wqe_idx_mask = ( wq->num_wqes - 1 );
+ if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) {
+ DBGC ( hermon, "Hermon %p QPN %#lx receive queue full",
+ hermon, qp->qpn );
+ return -ENOBUFS;
+ }
+ wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf;
+ wqe = &hermon_recv_wq->wqe[wq->next_idx & wqe_idx_mask].recv;
+
+ /* Construct work queue entry */
+ MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_tailroom ( iobuf ) );
+ MLX_FILL_1 ( &wqe->data[0], 1, l_key, hermon->lkey );
+ MLX_FILL_H ( &wqe->data[0], 2,
+ local_address_h, virt_to_bus ( iobuf->data ) );
+ MLX_FILL_1 ( &wqe->data[0], 3,
+ local_address_l, virt_to_bus ( iobuf->data ) );
+
+ /* Update work queue's index */
+ wq->next_idx++;
+
+ /* Update doorbell record */
+ barrier();
+ MLX_FILL_1 ( hermon_recv_wq->doorbell, 0, receive_wqe_counter,
+ ( wq->next_idx & 0xffff ) );
+
+ return 0;
+}
+
+/**
+ * Handle completion
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ * @v cqe Hardware completion queue entry
+ * @ret rc Return status code
+ */
+static int hermon_complete ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq,
+ union hermonprm_completion_entry *cqe ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq;
+ struct ib_queue_pair *qp;
+ struct io_buffer *iobuf;
+ struct ib_address_vector recv_av;
+ struct ib_global_route_header *grh;
+ struct ib_address_vector *av;
+ unsigned int opcode;
+ unsigned long qpn;
+ int is_send;
+ unsigned long wqe_idx;
+ unsigned long wqe_idx_mask;
+ size_t len;
+ int rc = 0;
+
+ /* Parse completion */
+ qpn = MLX_GET ( &cqe->normal, qpn );
+ is_send = MLX_GET ( &cqe->normal, s_r );
+ opcode = MLX_GET ( &cqe->normal, opcode );
+ if ( opcode >= HERMON_OPCODE_RECV_ERROR ) {
+ /* "s" field is not valid for error opcodes */
+ is_send = ( opcode == HERMON_OPCODE_SEND_ERROR );
+ DBGC ( hermon, "Hermon %p CQN %#lx syndrome %x vendor %x\n",
+ hermon, cq->cqn, MLX_GET ( &cqe->error, syndrome ),
+ MLX_GET ( &cqe->error, vendor_error_syndrome ) );
+ rc = -EIO;
+ /* Don't return immediately; propagate error to completer */
+ }
+
+ /* Identify work queue */
+ wq = ib_find_wq ( cq, qpn, is_send );
+ if ( ! wq ) {
+ DBGC ( hermon, "Hermon %p CQN %#lx unknown %s QPN %#lx\n",
+ hermon, cq->cqn, ( is_send ? "send" : "recv" ), qpn );
+ return -EIO;
+ }
+ qp = wq->qp;
+
+ /* Identify work queue entry */
+ wqe_idx = MLX_GET ( &cqe->normal, wqe_counter );
+ wqe_idx_mask = ( wq->num_wqes - 1 );
+ DBGCP ( hermon, "Hermon %p CQN %#lx QPN %#lx %s WQE %#lx completed:\n",
+ hermon, cq->cqn, qp->qpn, ( is_send ? "send" : "recv" ),
+ wqe_idx );
+ DBGCP_HDA ( hermon, virt_to_phys ( cqe ), cqe, sizeof ( *cqe ) );
+
+ /* Identify I/O buffer */
+ iobuf = wq->iobufs[ wqe_idx & wqe_idx_mask ];
+ if ( ! iobuf ) {
+ DBGC ( hermon, "Hermon %p CQN %#lx QPN %#lx empty %s WQE "
+ "%#lx\n", hermon, cq->cqn, qp->qpn,
+ ( is_send ? "send" : "recv" ), wqe_idx );
+ return -EIO;
+ }
+ wq->iobufs[ wqe_idx & wqe_idx_mask ] = NULL;
+
+ if ( is_send ) {
+ /* Hand off to completion handler */
+ ib_complete_send ( ibdev, qp, iobuf, rc );
+ } else {
+ /* Set received length */
+ len = MLX_GET ( &cqe->normal, byte_cnt );
+ assert ( len <= iob_tailroom ( iobuf ) );
+ iob_put ( iobuf, len );
+ memset ( &recv_av, 0, sizeof ( recv_av ) );
+ switch ( qp->type ) {
+ case IB_QPT_SMI:
+ case IB_QPT_GSI:
+ case IB_QPT_UD:
+ assert ( iob_len ( iobuf ) >= sizeof ( *grh ) );
+ grh = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *grh ) );
+ /* Construct address vector */
+ av = &recv_av;
+ av->qpn = MLX_GET ( &cqe->normal, srq_rqpn );
+ av->lid = MLX_GET ( &cqe->normal, slid_smac47_32 );
+ av->sl = MLX_GET ( &cqe->normal, sl );
+ av->gid_present = MLX_GET ( &cqe->normal, g );
+ memcpy ( &av->gid, &grh->sgid, sizeof ( av->gid ) );
+ break;
+ case IB_QPT_RC:
+ av = &qp->av;
+ break;
+ case IB_QPT_ETH:
+ /* Construct address vector */
+ av = &recv_av;
+ av->vlan_present = MLX_GET ( &cqe->normal, vlan );
+ av->vlan = MLX_GET ( &cqe->normal, vid );
+ break;
+ default:
+ assert ( 0 );
+ return -EINVAL;
+ }
+ /* Hand off to completion handler */
+ ib_complete_recv ( ibdev, qp, av, iobuf, rc );
+ }
+
+ return rc;
+}
+
+/**
+ * Poll completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+static void hermon_poll_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
+ union hermonprm_completion_entry *cqe;
+ unsigned int cqe_idx_mask;
+ int rc;
+
+ while ( 1 ) {
+ /* Look for completion entry */
+ cqe_idx_mask = ( cq->num_cqes - 1 );
+ cqe = &hermon_cq->cqe[cq->next_idx & cqe_idx_mask];
+ if ( MLX_GET ( &cqe->normal, owner ) ^
+ ( ( cq->next_idx & cq->num_cqes ) ? 1 : 0 ) ) {
+ /* Entry still owned by hardware; end of poll */
+ break;
+ }
+
+ /* Handle completion */
+ if ( ( rc = hermon_complete ( ibdev, cq, cqe ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p CQN %#lx failed to complete:"
+ " %s\n", hermon, cq->cqn, strerror ( rc ) );
+ DBGC_HDA ( hermon, virt_to_phys ( cqe ),
+ cqe, sizeof ( *cqe ) );
+ }
+
+ /* Update completion queue's index */
+ cq->next_idx++;
+
+ /* Update doorbell record */
+ MLX_FILL_1 ( hermon_cq->doorbell, 0, update_ci,
+ ( cq->next_idx & 0x00ffffffUL ) );
+ }
+}
+
+/***************************************************************************
+ *
+ * Event queues
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Create event queue
+ *
+ * @v hermon Hermon device
+ * @ret rc Return status code
+ */
+static int hermon_create_eq ( struct hermon *hermon ) {
+ struct hermon_event_queue *hermon_eq = &hermon->eq;
+ struct hermonprm_eqc eqctx;
+ struct hermonprm_event_mask mask;
+ unsigned int i;
+ int rc;
+
+ /* Select event queue number */
+ hermon_eq->eqn = ( 4 * hermon->cap.reserved_uars );
+ if ( hermon_eq->eqn < hermon->cap.reserved_eqs )
+ hermon_eq->eqn = hermon->cap.reserved_eqs;
+
+ /* Calculate doorbell address */
+ hermon_eq->doorbell =
+ ( hermon->uar + HERMON_DB_EQ_OFFSET ( hermon_eq->eqn ) );
+
+ /* Allocate event queue itself */
+ hermon_eq->eqe_size =
+ ( HERMON_NUM_EQES * sizeof ( hermon_eq->eqe[0] ) );
+ hermon_eq->eqe = malloc_dma ( hermon_eq->eqe_size,
+ sizeof ( hermon_eq->eqe[0] ) );
+ if ( ! hermon_eq->eqe ) {
+ rc = -ENOMEM;
+ goto err_eqe;
+ }
+ memset ( hermon_eq->eqe, 0, hermon_eq->eqe_size );
+ for ( i = 0 ; i < HERMON_NUM_EQES ; i++ ) {
+ MLX_FILL_1 ( &hermon_eq->eqe[i].generic, 7, owner, 1 );
+ }
+ barrier();
+
+ /* Allocate MTT entries */
+ if ( ( rc = hermon_alloc_mtt ( hermon, hermon_eq->eqe,
+ hermon_eq->eqe_size,
+ &hermon_eq->mtt ) ) != 0 )
+ goto err_alloc_mtt;
+
+ /* Hand queue over to hardware */
+ memset ( &eqctx, 0, sizeof ( eqctx ) );
+ MLX_FILL_2 ( &eqctx, 0,
+ st, 0xa /* "Fired" */,
+ oi, 1 );
+ MLX_FILL_1 ( &eqctx, 2,
+ page_offset, ( hermon_eq->mtt.page_offset >> 5 ) );
+ MLX_FILL_1 ( &eqctx, 3, log_eq_size, fls ( HERMON_NUM_EQES - 1 ) );
+ MLX_FILL_H ( &eqctx, 6, mtt_base_addr_h,
+ hermon_eq->mtt.mtt_base_addr );
+ MLX_FILL_1 ( &eqctx, 7, mtt_base_addr_l,
+ ( hermon_eq->mtt.mtt_base_addr >> 3 ) );
+ if ( ( rc = hermon_cmd_sw2hw_eq ( hermon, hermon_eq->eqn,
+ &eqctx ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p EQN %#lx SW2HW_EQ failed: %s\n",
+ hermon, hermon_eq->eqn, strerror ( rc ) );
+ goto err_sw2hw_eq;
+ }
+
+ /* Map all events to this event queue */
+ memset ( &mask, 0xff, sizeof ( mask ) );
+ if ( ( rc = hermon_cmd_map_eq ( hermon,
+ ( HERMON_MAP_EQ | hermon_eq->eqn ),
+ &mask ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p EQN %#lx MAP_EQ failed: %s\n",
+ hermon, hermon_eq->eqn, strerror ( rc ) );
+ goto err_map_eq;
+ }
+
+ DBGC ( hermon, "Hermon %p EQN %#lx ring [%08lx,%08lx), doorbell "
+ "%08lx\n", hermon, hermon_eq->eqn,
+ virt_to_phys ( hermon_eq->eqe ),
+ ( virt_to_phys ( hermon_eq->eqe ) + hermon_eq->eqe_size ),
+ virt_to_phys ( hermon_eq->doorbell ) );
+ return 0;
+
+ err_map_eq:
+ hermon_cmd_hw2sw_eq ( hermon, hermon_eq->eqn, &eqctx );
+ err_sw2hw_eq:
+ hermon_free_mtt ( hermon, &hermon_eq->mtt );
+ err_alloc_mtt:
+ free_dma ( hermon_eq->eqe, hermon_eq->eqe_size );
+ err_eqe:
+ memset ( hermon_eq, 0, sizeof ( *hermon_eq ) );
+ return rc;
+}
+
+/**
+ * Destroy event queue
+ *
+ * @v hermon Hermon device
+ */
+static void hermon_destroy_eq ( struct hermon *hermon ) {
+ struct hermon_event_queue *hermon_eq = &hermon->eq;
+ struct hermonprm_eqc eqctx;
+ struct hermonprm_event_mask mask;
+ int rc;
+
+ /* Unmap events from event queue */
+ memset ( &mask, 0xff, sizeof ( mask ) );
+ if ( ( rc = hermon_cmd_map_eq ( hermon,
+ ( HERMON_UNMAP_EQ | hermon_eq->eqn ),
+ &mask ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p EQN %#lx FATAL MAP_EQ failed to "
+ "unmap: %s\n", hermon, hermon_eq->eqn, strerror ( rc ) );
+ /* Continue; HCA may die but system should survive */
+ }
+
+ /* Take ownership back from hardware */
+ if ( ( rc = hermon_cmd_hw2sw_eq ( hermon, hermon_eq->eqn,
+ &eqctx ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p EQN %#lx FATAL HW2SW_EQ failed: %s\n",
+ hermon, hermon_eq->eqn, strerror ( rc ) );
+ /* Leak memory and return; at least we avoid corruption */
+ return;
+ }
+
+ /* Free MTT entries */
+ hermon_free_mtt ( hermon, &hermon_eq->mtt );
+
+ /* Free memory */
+ free_dma ( hermon_eq->eqe, hermon_eq->eqe_size );
+ memset ( hermon_eq, 0, sizeof ( *hermon_eq ) );
+}
+
+/**
+ * Handle port state event
+ *
+ * @v hermon Hermon device
+ * @v eqe Port state change event queue entry
+ */
+static void hermon_event_port_state_change ( struct hermon *hermon,
+ union hermonprm_event_entry *eqe){
+ unsigned int port;
+ int link_up;
+
+ /* Get port and link status */
+ port = ( MLX_GET ( &eqe->port_state_change, data.p ) - 1 );
+ link_up = ( MLX_GET ( &eqe->generic, event_sub_type ) & 0x04 );
+ DBGC ( hermon, "Hermon %p port %d link %s\n", hermon, ( port + 1 ),
+ ( link_up ? "up" : "down" ) );
+
+ /* Sanity check */
+ if ( port >= hermon->cap.num_ports ) {
+ DBGC ( hermon, "Hermon %p port %d does not exist!\n",
+ hermon, ( port + 1 ) );
+ return;
+ }
+
+ /* Notify device of port state change */
+ hermon->port[port].type->state_change ( hermon, &hermon->port[port],
+ link_up );
+}
+
+/**
+ * Poll event queue
+ *
+ * @v ibdev Infiniband device
+ */
+static void hermon_poll_eq ( struct ib_device *ibdev ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermon_event_queue *hermon_eq = &hermon->eq;
+ union hermonprm_event_entry *eqe;
+ union hermonprm_doorbell_register db_reg;
+ unsigned int eqe_idx_mask;
+ unsigned int event_type;
+
+ /* No event is generated upon reaching INIT, so we must poll
+ * separately for link state changes while we remain DOWN.
+ */
+ if ( ib_is_open ( ibdev ) &&
+ ( ibdev->port_state == IB_PORT_STATE_DOWN ) ) {
+ ib_smc_update ( ibdev, hermon_mad );
+ }
+
+ /* Poll event queue */
+ while ( 1 ) {
+ /* Look for event entry */
+ eqe_idx_mask = ( HERMON_NUM_EQES - 1 );
+ eqe = &hermon_eq->eqe[hermon_eq->next_idx & eqe_idx_mask];
+ if ( MLX_GET ( &eqe->generic, owner ) ^
+ ( ( hermon_eq->next_idx & HERMON_NUM_EQES ) ? 1 : 0 ) ) {
+ /* Entry still owned by hardware; end of poll */
+ break;
+ }
+ DBGCP ( hermon, "Hermon %p EQN %#lx event:\n",
+ hermon, hermon_eq->eqn );
+ DBGCP_HDA ( hermon, virt_to_phys ( eqe ),
+ eqe, sizeof ( *eqe ) );
+
+ /* Handle event */
+ event_type = MLX_GET ( &eqe->generic, event_type );
+ switch ( event_type ) {
+ case HERMON_EV_PORT_STATE_CHANGE:
+ hermon_event_port_state_change ( hermon, eqe );
+ break;
+ default:
+ DBGC ( hermon, "Hermon %p EQN %#lx unrecognised event "
+ "type %#x:\n",
+ hermon, hermon_eq->eqn, event_type );
+ DBGC_HDA ( hermon, virt_to_phys ( eqe ),
+ eqe, sizeof ( *eqe ) );
+ break;
+ }
+
+ /* Update event queue's index */
+ hermon_eq->next_idx++;
+
+ /* Ring doorbell */
+ MLX_FILL_1 ( &db_reg.event, 0,
+ ci, ( hermon_eq->next_idx & 0x00ffffffUL ) );
+ writel ( db_reg.dword[0], hermon_eq->doorbell );
+ }
+}
+
+/***************************************************************************
+ *
+ * Firmware control
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Map virtual to physical address for firmware usage
+ *
+ * @v hermon Hermon device
+ * @v map Mapping function
+ * @v va Virtual address
+ * @v pa Physical address
+ * @v len Length of region
+ * @ret rc Return status code
+ */
+static int hermon_map_vpm ( struct hermon *hermon,
+ int ( *map ) ( struct hermon *hermon,
+ const struct hermonprm_virtual_physical_mapping* ),
+ uint64_t va, physaddr_t pa, size_t len ) {
+ struct hermonprm_virtual_physical_mapping mapping;
+ physaddr_t start;
+ physaddr_t low;
+ physaddr_t high;
+ physaddr_t end;
+ size_t size;
+ int rc;
+
+ /* Sanity checks */
+ assert ( ( va & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
+ assert ( ( pa & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
+ assert ( ( len & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
+
+ /* Calculate starting points */
+ start = pa;
+ end = ( start + len );
+ size = ( 1UL << ( fls ( start ^ end ) - 1 ) );
+ low = high = ( end & ~( size - 1 ) );
+ assert ( start < low );
+ assert ( high <= end );
+
+ /* These mappings tend to generate huge volumes of
+ * uninteresting debug data, which basically makes it
+ * impossible to use debugging otherwise.
+ */
+ DBG_DISABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
+
+ /* Map blocks in descending order of size */
+ while ( size >= HERMON_PAGE_SIZE ) {
+
+ /* Find the next candidate block */
+ if ( ( low - size ) >= start ) {
+ low -= size;
+ pa = low;
+ } else if ( ( high + size ) <= end ) {
+ pa = high;
+ high += size;
+ } else {
+ size >>= 1;
+ continue;
+ }
+ assert ( ( va & ( size - 1 ) ) == 0 );
+ assert ( ( pa & ( size - 1 ) ) == 0 );
+
+ /* Map this block */
+ memset ( &mapping, 0, sizeof ( mapping ) );
+ MLX_FILL_1 ( &mapping, 0, va_h, ( va >> 32 ) );
+ MLX_FILL_1 ( &mapping, 1, va_l, ( va >> 12 ) );
+ MLX_FILL_H ( &mapping, 2, pa_h, pa );
+ MLX_FILL_2 ( &mapping, 3,
+ log2size, ( ( fls ( size ) - 1 ) - 12 ),
+ pa_l, ( pa >> 12 ) );
+ if ( ( rc = map ( hermon, &mapping ) ) != 0 ) {
+ DBG_ENABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
+ DBGC ( hermon, "Hermon %p could not map %08llx+%zx to "
+ "%08lx: %s\n",
+ hermon, va, size, pa, strerror ( rc ) );
+ return rc;
+ }
+ va += size;
+ }
+ assert ( low == start );
+ assert ( high == end );
+
+ DBG_ENABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
+ return 0;
+}
+
+/**
+ * Start firmware running
+ *
+ * @v hermon Hermon device
+ * @ret rc Return status code
+ */
+static int hermon_start_firmware ( struct hermon *hermon ) {
+ struct hermonprm_query_fw fw;
+ unsigned int fw_pages;
+ size_t fw_len;
+ physaddr_t fw_base;
+ int rc;
+
+ /* Get firmware parameters */
+ if ( ( rc = hermon_cmd_query_fw ( hermon, &fw ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not query firmware: %s\n",
+ hermon, strerror ( rc ) );
+ goto err_query_fw;
+ }
+ DBGC ( hermon, "Hermon %p firmware version %d.%d.%d\n", hermon,
+ MLX_GET ( &fw, fw_rev_major ), MLX_GET ( &fw, fw_rev_minor ),
+ MLX_GET ( &fw, fw_rev_subminor ) );
+ fw_pages = MLX_GET ( &fw, fw_pages );
+ DBGC ( hermon, "Hermon %p requires %d pages (%d kB) for firmware\n",
+ hermon, fw_pages, ( fw_pages * 4 ) );
+
+ /* Allocate firmware pages and map firmware area */
+ fw_len = ( fw_pages * HERMON_PAGE_SIZE );
+ if ( ! hermon->firmware_area ) {
+ hermon->firmware_len = fw_len;
+ hermon->firmware_area = umalloc ( hermon->firmware_len );
+ if ( ! hermon->firmware_area ) {
+ rc = -ENOMEM;
+ goto err_alloc_fa;
+ }
+ } else {
+ assert ( hermon->firmware_len == fw_len );
+ }
+ fw_base = user_to_phys ( hermon->firmware_area, 0 );
+ DBGC ( hermon, "Hermon %p firmware area at physical [%08lx,%08lx)\n",
+ hermon, fw_base, ( fw_base + fw_len ) );
+ if ( ( rc = hermon_map_vpm ( hermon, hermon_cmd_map_fa,
+ 0, fw_base, fw_len ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not map firmware: %s\n",
+ hermon, strerror ( rc ) );
+ goto err_map_fa;
+ }
+
+ /* Start firmware */
+ if ( ( rc = hermon_cmd_run_fw ( hermon ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not run firmware: %s\n",
+ hermon, strerror ( rc ) );
+ goto err_run_fw;
+ }
+
+ DBGC ( hermon, "Hermon %p firmware started\n", hermon );
+ return 0;
+
+ err_run_fw:
+ err_map_fa:
+ hermon_cmd_unmap_fa ( hermon );
+ err_alloc_fa:
+ err_query_fw:
+ return rc;
+}
+
+/**
+ * Stop firmware running
+ *
+ * @v hermon Hermon device
+ */
+static void hermon_stop_firmware ( struct hermon *hermon ) {
+ int rc;
+
+ if ( ( rc = hermon_cmd_unmap_fa ( hermon ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p FATAL could not stop firmware: %s\n",
+ hermon, strerror ( rc ) );
+ /* Leak memory and return; at least we avoid corruption */
+ hermon->firmware_area = UNULL;
+ return;
+ }
+}
+
+/***************************************************************************
+ *
+ * Infinihost Context Memory management
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Get device limits
+ *
+ * @v hermon Hermon device
+ * @ret rc Return status code
+ */
+static int hermon_get_cap ( struct hermon *hermon ) {
+ struct hermonprm_query_dev_cap dev_cap;
+ int rc;
+
+ if ( ( rc = hermon_cmd_query_dev_cap ( hermon, &dev_cap ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not get device limits: %s\n",
+ hermon, strerror ( rc ) );
+ return rc;
+ }
+
+ hermon->cap.cmpt_entry_size = MLX_GET ( &dev_cap, c_mpt_entry_sz );
+ hermon->cap.reserved_qps =
+ ( 1 << MLX_GET ( &dev_cap, log2_rsvd_qps ) );
+ hermon->cap.qpc_entry_size = MLX_GET ( &dev_cap, qpc_entry_sz );
+ hermon->cap.altc_entry_size = MLX_GET ( &dev_cap, altc_entry_sz );
+ hermon->cap.auxc_entry_size = MLX_GET ( &dev_cap, aux_entry_sz );
+ hermon->cap.reserved_srqs =
+ ( 1 << MLX_GET ( &dev_cap, log2_rsvd_srqs ) );
+ hermon->cap.srqc_entry_size = MLX_GET ( &dev_cap, srq_entry_sz );
+ hermon->cap.reserved_cqs =
+ ( 1 << MLX_GET ( &dev_cap, log2_rsvd_cqs ) );
+ hermon->cap.cqc_entry_size = MLX_GET ( &dev_cap, cqc_entry_sz );
+ hermon->cap.reserved_eqs = MLX_GET ( &dev_cap, num_rsvd_eqs );
+ if ( hermon->cap.reserved_eqs == 0 ) {
+ /* Backward compatibility */
+ hermon->cap.reserved_eqs =
+ ( 1 << MLX_GET ( &dev_cap, log2_rsvd_eqs ) );
+ }
+ hermon->cap.eqc_entry_size = MLX_GET ( &dev_cap, eqc_entry_sz );
+ hermon->cap.reserved_mtts =
+ ( 1 << MLX_GET ( &dev_cap, log2_rsvd_mtts ) );
+ hermon->cap.mtt_entry_size = MLX_GET ( &dev_cap, mtt_entry_sz );
+ hermon->cap.reserved_mrws =
+ ( 1 << MLX_GET ( &dev_cap, log2_rsvd_mrws ) );
+ hermon->cap.dmpt_entry_size = MLX_GET ( &dev_cap, d_mpt_entry_sz );
+ hermon->cap.reserved_uars = MLX_GET ( &dev_cap, num_rsvd_uars );
+ hermon->cap.num_ports = MLX_GET ( &dev_cap, num_ports );
+ hermon->cap.dpdp = MLX_GET ( &dev_cap, dpdp );
+
+ /* Sanity check */
+ if ( hermon->cap.num_ports > HERMON_MAX_PORTS ) {
+ DBGC ( hermon, "Hermon %p has %d ports (only %d supported)\n",
+ hermon, hermon->cap.num_ports, HERMON_MAX_PORTS );
+ hermon->cap.num_ports = HERMON_MAX_PORTS;
+ }
+
+ return 0;
+}
+
+/**
+ * Align ICM table
+ *
+ * @v icm_offset Current ICM offset
+ * @v len ICM table length
+ * @ret icm_offset ICM offset
+ */
+static uint64_t icm_align ( uint64_t icm_offset, size_t len ) {
+
+ /* Round up to a multiple of the table size */
+ assert ( len == ( 1UL << ( fls ( len ) - 1 ) ) );
+ return ( ( icm_offset + len - 1 ) & ~( ( ( uint64_t ) len ) - 1 ) );
+}
+
+/**
+ * Map ICM (allocating if necessary)
+ *
+ * @v hermon Hermon device
+ * @v init_hca INIT_HCA structure to fill in
+ * @ret rc Return status code
+ */
+static int hermon_map_icm ( struct hermon *hermon,
+ struct hermonprm_init_hca *init_hca ) {
+ struct hermonprm_scalar_parameter icm_size;
+ struct hermonprm_scalar_parameter icm_aux_size;
+ uint64_t icm_offset = 0;
+ unsigned int log_num_qps, log_num_srqs, log_num_cqs, log_num_eqs;
+ unsigned int log_num_mtts, log_num_mpts, log_num_mcs;
+ size_t cmpt_max_len;
+ size_t icm_len, icm_aux_len;
+ size_t len;
+ physaddr_t icm_phys;
+ int i;
+ int rc;
+
+ /*
+ * Start by carving up the ICM virtual address space
+ *
+ */
+
+ /* Calculate number of each object type within ICM */
+ log_num_qps = fls ( hermon->cap.reserved_qps +
+ HERMON_RSVD_SPECIAL_QPS + HERMON_MAX_QPS - 1 );
+ log_num_srqs = fls ( hermon->cap.reserved_srqs - 1 );
+ log_num_cqs = fls ( hermon->cap.reserved_cqs + HERMON_MAX_CQS - 1 );
+ log_num_eqs = fls ( hermon->cap.reserved_eqs + HERMON_MAX_EQS - 1 );
+ log_num_mtts = fls ( hermon->cap.reserved_mtts + HERMON_MAX_MTTS - 1 );
+ log_num_mpts = fls ( hermon->cap.reserved_mrws + 1 - 1 );
+ log_num_mcs = HERMON_LOG_MULTICAST_HASH_SIZE;
+
+ /* ICM starts with the cMPT tables, which are sparse */
+ cmpt_max_len = ( HERMON_CMPT_MAX_ENTRIES *
+ ( ( uint64_t ) hermon->cap.cmpt_entry_size ) );
+ len = ( ( ( ( 1 << log_num_qps ) * hermon->cap.cmpt_entry_size ) +
+ HERMON_PAGE_SIZE - 1 ) & ~( HERMON_PAGE_SIZE - 1 ) );
+ hermon->icm_map[HERMON_ICM_QP_CMPT].offset = icm_offset;
+ hermon->icm_map[HERMON_ICM_QP_CMPT].len = len;
+ icm_offset += cmpt_max_len;
+ len = ( ( ( ( 1 << log_num_srqs ) * hermon->cap.cmpt_entry_size ) +
+ HERMON_PAGE_SIZE - 1 ) & ~( HERMON_PAGE_SIZE - 1 ) );
+ hermon->icm_map[HERMON_ICM_SRQ_CMPT].offset = icm_offset;
+ hermon->icm_map[HERMON_ICM_SRQ_CMPT].len = len;
+ icm_offset += cmpt_max_len;
+ len = ( ( ( ( 1 << log_num_cqs ) * hermon->cap.cmpt_entry_size ) +
+ HERMON_PAGE_SIZE - 1 ) & ~( HERMON_PAGE_SIZE - 1 ) );
+ hermon->icm_map[HERMON_ICM_CQ_CMPT].offset = icm_offset;
+ hermon->icm_map[HERMON_ICM_CQ_CMPT].len = len;
+ icm_offset += cmpt_max_len;
+ len = ( ( ( ( 1 << log_num_eqs ) * hermon->cap.cmpt_entry_size ) +
+ HERMON_PAGE_SIZE - 1 ) & ~( HERMON_PAGE_SIZE - 1 ) );
+ hermon->icm_map[HERMON_ICM_EQ_CMPT].offset = icm_offset;
+ hermon->icm_map[HERMON_ICM_EQ_CMPT].len = len;
+ icm_offset += cmpt_max_len;
+
+ hermon->icm_map[HERMON_ICM_OTHER].offset = icm_offset;
+
+ /* Queue pair contexts */
+ len = ( ( 1 << log_num_qps ) * hermon->cap.qpc_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 12,
+ qpc_eec_cqc_eqc_rdb_parameters.qpc_base_addr_h,
+ ( icm_offset >> 32 ) );
+ MLX_FILL_2 ( init_hca, 13,
+ qpc_eec_cqc_eqc_rdb_parameters.qpc_base_addr_l,
+ ( icm_offset >> 5 ),
+ qpc_eec_cqc_eqc_rdb_parameters.log_num_of_qp,
+ log_num_qps );
+ DBGC ( hermon, "Hermon %p ICM QPC is %d x %#zx at [%08llx,%08llx)\n",
+ hermon, ( 1 << log_num_qps ), hermon->cap.qpc_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Extended alternate path contexts */
+ len = ( ( 1 << log_num_qps ) * hermon->cap.altc_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 24,
+ qpc_eec_cqc_eqc_rdb_parameters.altc_base_addr_h,
+ ( icm_offset >> 32 ) );
+ MLX_FILL_1 ( init_hca, 25,
+ qpc_eec_cqc_eqc_rdb_parameters.altc_base_addr_l,
+ icm_offset );
+ DBGC ( hermon, "Hermon %p ICM ALTC is %d x %#zx at [%08llx,%08llx)\n",
+ hermon, ( 1 << log_num_qps ), hermon->cap.altc_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Extended auxiliary contexts */
+ len = ( ( 1 << log_num_qps ) * hermon->cap.auxc_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 28,
+ qpc_eec_cqc_eqc_rdb_parameters.auxc_base_addr_h,
+ ( icm_offset >> 32 ) );
+ MLX_FILL_1 ( init_hca, 29,
+ qpc_eec_cqc_eqc_rdb_parameters.auxc_base_addr_l,
+ icm_offset );
+ DBGC ( hermon, "Hermon %p ICM AUXC is %d x %#zx at [%08llx,%08llx)\n",
+ hermon, ( 1 << log_num_qps ), hermon->cap.auxc_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Shared receive queue contexts */
+ len = ( ( 1 << log_num_srqs ) * hermon->cap.srqc_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 18,
+ qpc_eec_cqc_eqc_rdb_parameters.srqc_base_addr_h,
+ ( icm_offset >> 32 ) );
+ MLX_FILL_2 ( init_hca, 19,
+ qpc_eec_cqc_eqc_rdb_parameters.srqc_base_addr_l,
+ ( icm_offset >> 5 ),
+ qpc_eec_cqc_eqc_rdb_parameters.log_num_of_srq,
+ log_num_srqs );
+ DBGC ( hermon, "Hermon %p ICM SRQC is %d x %#zx at [%08llx,%08llx)\n",
+ hermon, ( 1 << log_num_srqs ), hermon->cap.srqc_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Completion queue contexts */
+ len = ( ( 1 << log_num_cqs ) * hermon->cap.cqc_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 20,
+ qpc_eec_cqc_eqc_rdb_parameters.cqc_base_addr_h,
+ ( icm_offset >> 32 ) );
+ MLX_FILL_2 ( init_hca, 21,
+ qpc_eec_cqc_eqc_rdb_parameters.cqc_base_addr_l,
+ ( icm_offset >> 5 ),
+ qpc_eec_cqc_eqc_rdb_parameters.log_num_of_cq,
+ log_num_cqs );
+ DBGC ( hermon, "Hermon %p ICM CQC is %d x %#zx at [%08llx,%08llx)\n",
+ hermon, ( 1 << log_num_cqs ), hermon->cap.cqc_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Event queue contexts */
+ len = ( ( 1 << log_num_eqs ) * hermon->cap.eqc_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 32,
+ qpc_eec_cqc_eqc_rdb_parameters.eqc_base_addr_h,
+ ( icm_offset >> 32 ) );
+ MLX_FILL_2 ( init_hca, 33,
+ qpc_eec_cqc_eqc_rdb_parameters.eqc_base_addr_l,
+ ( icm_offset >> 5 ),
+ qpc_eec_cqc_eqc_rdb_parameters.log_num_of_eq,
+ log_num_eqs );
+ DBGC ( hermon, "Hermon %p ICM EQC is %d x %#zx at [%08llx,%08llx)\n",
+ hermon, ( 1 << log_num_eqs ), hermon->cap.eqc_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Memory translation table */
+ len = ( ( 1 << log_num_mtts ) * hermon->cap.mtt_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 64,
+ tpt_parameters.mtt_base_addr_h, ( icm_offset >> 32 ) );
+ MLX_FILL_1 ( init_hca, 65,
+ tpt_parameters.mtt_base_addr_l, icm_offset );
+ DBGC ( hermon, "Hermon %p ICM MTT is %d x %#zx at [%08llx,%08llx)\n",
+ hermon, ( 1 << log_num_mtts ), hermon->cap.mtt_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Memory protection table */
+ len = ( ( 1 << log_num_mpts ) * hermon->cap.dmpt_entry_size );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 60,
+ tpt_parameters.dmpt_base_adr_h, ( icm_offset >> 32 ) );
+ MLX_FILL_1 ( init_hca, 61,
+ tpt_parameters.dmpt_base_adr_l, icm_offset );
+ MLX_FILL_1 ( init_hca, 62,
+ tpt_parameters.log_dmpt_sz, log_num_mpts );
+ DBGC ( hermon, "Hermon %p ICM DMPT is %d x %#zx at [%08llx,%08llx)\n",
+ hermon, ( 1 << log_num_mpts ), hermon->cap.dmpt_entry_size,
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+ /* Multicast table */
+ len = ( ( 1 << log_num_mcs ) * sizeof ( struct hermonprm_mcg_entry ) );
+ icm_offset = icm_align ( icm_offset, len );
+ MLX_FILL_1 ( init_hca, 48,
+ multicast_parameters.mc_base_addr_h,
+ ( icm_offset >> 32 ) );
+ MLX_FILL_1 ( init_hca, 49,
+ multicast_parameters.mc_base_addr_l, icm_offset );
+ MLX_FILL_1 ( init_hca, 52,
+ multicast_parameters.log_mc_table_entry_sz,
+ fls ( sizeof ( struct hermonprm_mcg_entry ) - 1 ) );
+ MLX_FILL_1 ( init_hca, 53,
+ multicast_parameters.log_mc_table_hash_sz, log_num_mcs );
+ MLX_FILL_1 ( init_hca, 54,
+ multicast_parameters.log_mc_table_sz, log_num_mcs );
+ DBGC ( hermon, "Hermon %p ICM MC is %d x %#zx at [%08llx,%08llx)\n",
+ hermon, ( 1 << log_num_mcs ),
+ sizeof ( struct hermonprm_mcg_entry ),
+ icm_offset, ( icm_offset + len ) );
+ icm_offset += len;
+
+
+ hermon->icm_map[HERMON_ICM_OTHER].len =
+ ( icm_offset - hermon->icm_map[HERMON_ICM_OTHER].offset );
+
+ /*
+ * Allocate and map physical memory for (portions of) ICM
+ *
+ * Map is:
+ * ICM AUX area (aligned to its own size)
+ * cMPT areas
+ * Other areas
+ */
+
+ /* Calculate physical memory required for ICM */
+ icm_len = 0;
+ for ( i = 0 ; i < HERMON_ICM_NUM_REGIONS ; i++ ) {
+ icm_len += hermon->icm_map[i].len;
+ }
+
+ /* Get ICM auxiliary area size */
+ memset ( &icm_size, 0, sizeof ( icm_size ) );
+ MLX_FILL_1 ( &icm_size, 0, value_hi, ( icm_offset >> 32 ) );
+ MLX_FILL_1 ( &icm_size, 1, value, icm_offset );
+ if ( ( rc = hermon_cmd_set_icm_size ( hermon, &icm_size,
+ &icm_aux_size ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not set ICM size: %s\n",
+ hermon, strerror ( rc ) );
+ goto err_set_icm_size;
+ }
+ icm_aux_len = ( MLX_GET ( &icm_aux_size, value ) * HERMON_PAGE_SIZE );
+
+ /* Allocate ICM data and auxiliary area */
+ DBGC ( hermon, "Hermon %p requires %zd kB ICM and %zd kB AUX ICM\n",
+ hermon, ( icm_len / 1024 ), ( icm_aux_len / 1024 ) );
+ if ( ! hermon->icm ) {
+ hermon->icm_len = icm_len;
+ hermon->icm_aux_len = icm_aux_len;
+ hermon->icm = umalloc ( hermon->icm_aux_len + hermon->icm_len );
+ if ( ! hermon->icm ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ } else {
+ assert ( hermon->icm_len == icm_len );
+ assert ( hermon->icm_aux_len == icm_aux_len );
+ }
+ icm_phys = user_to_phys ( hermon->icm, 0 );
+
+ /* Map ICM auxiliary area */
+ DBGC ( hermon, "Hermon %p mapping ICM AUX => %08lx\n",
+ hermon, icm_phys );
+ if ( ( rc = hermon_map_vpm ( hermon, hermon_cmd_map_icm_aux,
+ 0, icm_phys, icm_aux_len ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not map AUX ICM: %s\n",
+ hermon, strerror ( rc ) );
+ goto err_map_icm_aux;
+ }
+ icm_phys += icm_aux_len;
+
+ /* MAP ICM area */
+ for ( i = 0 ; i < HERMON_ICM_NUM_REGIONS ; i++ ) {
+ DBGC ( hermon, "Hermon %p mapping ICM %llx+%zx => %08lx\n",
+ hermon, hermon->icm_map[i].offset,
+ hermon->icm_map[i].len, icm_phys );
+ if ( ( rc = hermon_map_vpm ( hermon, hermon_cmd_map_icm,
+ hermon->icm_map[i].offset,
+ icm_phys,
+ hermon->icm_map[i].len ) ) != 0 ){
+ DBGC ( hermon, "Hermon %p could not map ICM: %s\n",
+ hermon, strerror ( rc ) );
+ goto err_map_icm;
+ }
+ icm_phys += hermon->icm_map[i].len;
+ }
+
+ return 0;
+
+ err_map_icm:
+ assert ( i == 0 ); /* We don't handle partial failure at present */
+ err_map_icm_aux:
+ hermon_cmd_unmap_icm_aux ( hermon );
+ err_alloc:
+ err_set_icm_size:
+ return rc;
+}
+
+/**
+ * Unmap ICM
+ *
+ * @v hermon Hermon device
+ */
+static void hermon_unmap_icm ( struct hermon *hermon ) {
+ struct hermonprm_scalar_parameter unmap_icm;
+ int i;
+
+ for ( i = ( HERMON_ICM_NUM_REGIONS - 1 ) ; i >= 0 ; i-- ) {
+ memset ( &unmap_icm, 0, sizeof ( unmap_icm ) );
+ MLX_FILL_1 ( &unmap_icm, 0, value_hi,
+ ( hermon->icm_map[i].offset >> 32 ) );
+ MLX_FILL_1 ( &unmap_icm, 1, value,
+ hermon->icm_map[i].offset );
+ hermon_cmd_unmap_icm ( hermon,
+ ( 1 << fls ( ( hermon->icm_map[i].len /
+ HERMON_PAGE_SIZE ) - 1)),
+ &unmap_icm );
+ }
+ hermon_cmd_unmap_icm_aux ( hermon );
+}
+
+/***************************************************************************
+ *
+ * Initialisation and teardown
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Reset device
+ *
+ * @v hermon Hermon device
+ */
+static void hermon_reset ( struct hermon *hermon ) {
+ struct pci_device *pci = hermon->pci;
+ struct pci_config_backup backup;
+ static const uint8_t backup_exclude[] =
+ PCI_CONFIG_BACKUP_EXCLUDE ( 0x58, 0x5c );
+
+ /* Perform device reset and preserve PCI configuration */
+ pci_backup ( pci, &backup, backup_exclude );
+ writel ( HERMON_RESET_MAGIC,
+ ( hermon->config + HERMON_RESET_OFFSET ) );
+ mdelay ( HERMON_RESET_WAIT_TIME_MS );
+ pci_restore ( pci, &backup, backup_exclude );
+
+ /* Reset command interface toggle */
+ hermon->toggle = 0;
+}
+
+/**
+ * Set up memory protection table
+ *
+ * @v hermon Hermon device
+ * @ret rc Return status code
+ */
+static int hermon_setup_mpt ( struct hermon *hermon ) {
+ struct hermonprm_mpt mpt;
+ uint32_t key;
+ int rc;
+
+ /* Derive key */
+ key = ( hermon->cap.reserved_mrws | HERMON_MKEY_PREFIX );
+ hermon->lkey = ( ( key << 8 ) | ( key >> 24 ) );
+
+ /* Initialise memory protection table */
+ memset ( &mpt, 0, sizeof ( mpt ) );
+ MLX_FILL_7 ( &mpt, 0,
+ atomic, 1,
+ rw, 1,
+ rr, 1,
+ lw, 1,
+ lr, 1,
+ pa, 1,
+ r_w, 1 );
+ MLX_FILL_1 ( &mpt, 2, mem_key, key );
+ MLX_FILL_1 ( &mpt, 3,
+ pd, HERMON_GLOBAL_PD );
+ MLX_FILL_1 ( &mpt, 10, len64, 1 );
+ if ( ( rc = hermon_cmd_sw2hw_mpt ( hermon,
+ hermon->cap.reserved_mrws,
+ &mpt ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not set up MPT: %s\n",
+ hermon, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Configure special queue pairs
+ *
+ * @v hermon Hermon device
+ * @ret rc Return status code
+ */
+static int hermon_configure_special_qps ( struct hermon *hermon ) {
+ int rc;
+
+ /* Special QP block must be aligned on its own size */
+ hermon->special_qpn_base = ( ( hermon->cap.reserved_qps +
+ HERMON_NUM_SPECIAL_QPS - 1 )
+ & ~( HERMON_NUM_SPECIAL_QPS - 1 ) );
+ hermon->qpn_base = ( hermon->special_qpn_base +
+ HERMON_NUM_SPECIAL_QPS );
+ DBGC ( hermon, "Hermon %p special QPs at [%lx,%lx]\n", hermon,
+ hermon->special_qpn_base, ( hermon->qpn_base - 1 ) );
+
+ /* Issue command to configure special QPs */
+ if ( ( rc = hermon_cmd_conf_special_qp ( hermon, 0x00,
+ hermon->special_qpn_base ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not configure special QPs: "
+ "%s\n", hermon, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Start Hermon device
+ *
+ * @v hermon Hermon device
+ * @v running Firmware is already running
+ * @ret rc Return status code
+ */
+static int hermon_start ( struct hermon *hermon, int running ) {
+ struct hermonprm_init_hca init_hca;
+ unsigned int i;
+ int rc;
+
+ /* Start firmware if not already running */
+ if ( ! running ) {
+ if ( ( rc = hermon_start_firmware ( hermon ) ) != 0 )
+ goto err_start_firmware;
+ }
+
+ /* Allocate and map ICM */
+ memset ( &init_hca, 0, sizeof ( init_hca ) );
+ if ( ( rc = hermon_map_icm ( hermon, &init_hca ) ) != 0 )
+ goto err_map_icm;
+
+ /* Initialise HCA */
+ MLX_FILL_1 ( &init_hca, 0, version, 0x02 /* "Must be 0x02" */ );
+ MLX_FILL_1 ( &init_hca, 5, udp, 1 );
+ MLX_FILL_1 ( &init_hca, 74, uar_parameters.log_max_uars, 8 );
+ if ( ( rc = hermon_cmd_init_hca ( hermon, &init_hca ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not initialise HCA: %s\n",
+ hermon, strerror ( rc ) );
+ goto err_init_hca;
+ }
+
+ /* Set up memory protection */
+ if ( ( rc = hermon_setup_mpt ( hermon ) ) != 0 )
+ goto err_setup_mpt;
+ for ( i = 0 ; i < hermon->cap.num_ports ; i++ )
+ hermon->port[i].ibdev->rdma_key = hermon->lkey;
+
+ /* Set up event queue */
+ if ( ( rc = hermon_create_eq ( hermon ) ) != 0 )
+ goto err_create_eq;
+
+ /* Configure special QPs */
+ if ( ( rc = hermon_configure_special_qps ( hermon ) ) != 0 )
+ goto err_conf_special_qps;
+
+ return 0;
+
+ err_conf_special_qps:
+ hermon_destroy_eq ( hermon );
+ err_create_eq:
+ err_setup_mpt:
+ hermon_cmd_close_hca ( hermon );
+ err_init_hca:
+ hermon_unmap_icm ( hermon );
+ err_map_icm:
+ hermon_stop_firmware ( hermon );
+ err_start_firmware:
+ return rc;
+}
+
+/**
+ * Stop Hermon device
+ *
+ * @v hermon Hermon device
+ */
+static void hermon_stop ( struct hermon *hermon ) {
+ hermon_destroy_eq ( hermon );
+ hermon_cmd_close_hca ( hermon );
+ hermon_unmap_icm ( hermon );
+ hermon_stop_firmware ( hermon );
+ hermon_reset ( hermon );
+}
+
+/**
+ * Open Hermon device
+ *
+ * @v hermon Hermon device
+ * @ret rc Return status code
+ */
+static int hermon_open ( struct hermon *hermon ) {
+ int rc;
+
+ /* Start device if applicable */
+ if ( hermon->open_count == 0 ) {
+ if ( ( rc = hermon_start ( hermon, 0 ) ) != 0 )
+ return rc;
+ }
+
+ /* Increment open counter */
+ hermon->open_count++;
+
+ return 0;
+}
+
+/**
+ * Close Hermon device
+ *
+ * @v hermon Hermon device
+ */
+static void hermon_close ( struct hermon *hermon ) {
+
+ /* Decrement open counter */
+ assert ( hermon->open_count != 0 );
+ hermon->open_count--;
+
+ /* Stop device if applicable */
+ if ( hermon->open_count == 0 )
+ hermon_stop ( hermon );
+}
+
+/***************************************************************************
+ *
+ * Infiniband link-layer operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Initialise Infiniband link
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+static int hermon_ib_open ( struct ib_device *ibdev ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ union hermonprm_set_port set_port;
+ int rc;
+
+ /* Open hardware */
+ if ( ( rc = hermon_open ( hermon ) ) != 0 )
+ goto err_open;
+
+ /* Set port parameters */
+ memset ( &set_port, 0, sizeof ( set_port ) );
+ MLX_FILL_8 ( &set_port.ib, 0,
+ mmc, 1,
+ mvc, 1,
+ mp, 1,
+ mg, 1,
+ mtu_cap, IB_MTU_2048,
+ vl_cap, IB_VL_0,
+ rcm, 1,
+ lss, 1 );
+ MLX_FILL_2 ( &set_port.ib, 10,
+ max_pkey, 1,
+ max_gid, 1 );
+ MLX_FILL_1 ( &set_port.ib, 28,
+ link_speed_supported, 1 );
+ if ( ( rc = hermon_cmd_set_port ( hermon, 0, ibdev->port,
+ &set_port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not set port: %s\n",
+ hermon, ibdev->port, strerror ( rc ) );
+ goto err_set_port;
+ }
+
+ /* Initialise port */
+ if ( ( rc = hermon_cmd_init_port ( hermon, ibdev->port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not initialise port: "
+ "%s\n", hermon, ibdev->port, strerror ( rc ) );
+ goto err_init_port;
+ }
+
+ /* Update MAD parameters */
+ ib_smc_update ( ibdev, hermon_mad );
+
+ return 0;
+
+ err_init_port:
+ err_set_port:
+ hermon_close ( hermon );
+ err_open:
+ return rc;
+}
+
+/**
+ * Close Infiniband link
+ *
+ * @v ibdev Infiniband device
+ */
+static void hermon_ib_close ( struct ib_device *ibdev ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ int rc;
+
+ /* Close port */
+ if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not close port: %s\n",
+ hermon, ibdev->port, strerror ( rc ) );
+ /* Nothing we can do about this */
+ }
+
+ /* Close hardware */
+ hermon_close ( hermon );
+}
+
+/**
+ * Inform embedded subnet management agent of a received MAD
+ *
+ * @v ibdev Infiniband device
+ * @v mad MAD
+ * @ret rc Return status code
+ */
+static int hermon_inform_sma ( struct ib_device *ibdev,
+ union ib_mad *mad ) {
+ int rc;
+
+ /* Send the MAD to the embedded SMA */
+ if ( ( rc = hermon_mad ( ibdev, mad ) ) != 0 )
+ return rc;
+
+ /* Update parameters held in software */
+ ib_smc_update ( ibdev, hermon_mad );
+
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * Multicast group operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Attach to multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ * @ret rc Return status code
+ */
+static int hermon_mcast_attach ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ union ib_gid *gid ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermonprm_mgm_hash hash;
+ struct hermonprm_mcg_entry mcg;
+ unsigned int index;
+ int rc;
+
+ /* Generate hash table index */
+ if ( ( rc = hermon_cmd_mgid_hash ( hermon, gid, &hash ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not hash GID: %s\n",
+ hermon, strerror ( rc ) );
+ return rc;
+ }
+ index = MLX_GET ( &hash, hash );
+
+ /* Check for existing hash table entry */
+ if ( ( rc = hermon_cmd_read_mcg ( hermon, index, &mcg ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not read MCG %#x: %s\n",
+ hermon, index, strerror ( rc ) );
+ return rc;
+ }
+ if ( MLX_GET ( &mcg, hdr.members_count ) != 0 ) {
+ /* FIXME: this implementation allows only a single QP
+ * per multicast group, and doesn't handle hash
+ * collisions. Sufficient for IPoIB but may need to
+ * be extended in future.
+ */
+ DBGC ( hermon, "Hermon %p MGID index %#x already in use\n",
+ hermon, index );
+ return -EBUSY;
+ }
+
+ /* Update hash table entry */
+ MLX_FILL_1 ( &mcg, 1, hdr.members_count, 1 );
+ MLX_FILL_1 ( &mcg, 8, qp[0].qpn, qp->qpn );
+ memcpy ( &mcg.u.dwords[4], gid, sizeof ( *gid ) );
+ if ( ( rc = hermon_cmd_write_mcg ( hermon, index, &mcg ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not write MCG %#x: %s\n",
+ hermon, index, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Detach from multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ */
+static void hermon_mcast_detach ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp __unused,
+ union ib_gid *gid ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermonprm_mgm_hash hash;
+ struct hermonprm_mcg_entry mcg;
+ unsigned int index;
+ int rc;
+
+ /* Generate hash table index */
+ if ( ( rc = hermon_cmd_mgid_hash ( hermon, gid, &hash ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not hash GID: %s\n",
+ hermon, strerror ( rc ) );
+ return;
+ }
+ index = MLX_GET ( &hash, hash );
+
+ /* Clear hash table entry */
+ memset ( &mcg, 0, sizeof ( mcg ) );
+ if ( ( rc = hermon_cmd_write_mcg ( hermon, index, &mcg ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not write MCG %#x: %s\n",
+ hermon, index, strerror ( rc ) );
+ return;
+ }
+}
+
+/** Hermon Infiniband operations */
+static struct ib_device_operations hermon_ib_operations = {
+ .create_cq = hermon_create_cq,
+ .destroy_cq = hermon_destroy_cq,
+ .create_qp = hermon_create_qp,
+ .modify_qp = hermon_modify_qp,
+ .destroy_qp = hermon_destroy_qp,
+ .post_send = hermon_post_send,
+ .post_recv = hermon_post_recv,
+ .poll_cq = hermon_poll_cq,
+ .poll_eq = hermon_poll_eq,
+ .open = hermon_ib_open,
+ .close = hermon_ib_close,
+ .mcast_attach = hermon_mcast_attach,
+ .mcast_detach = hermon_mcast_detach,
+ .set_port_info = hermon_inform_sma,
+ .set_pkey_table = hermon_inform_sma,
+};
+
+/**
+ * Register Hermon Infiniband device
+ *
+ * @v hermon Hermon device
+ * @v port Hermon port
+ * @ret rc Return status code
+ */
+static int hermon_register_ibdev ( struct hermon *hermon,
+ struct hermon_port *port ) {
+ struct ib_device *ibdev = port->ibdev;
+ int rc;
+
+ /* Initialise parameters using SMC */
+ ib_smc_init ( ibdev, hermon_mad );
+
+ /* Register Infiniband device */
+ if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not register IB "
+ "device: %s\n", hermon, ibdev->port, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle Hermon Infiniband device port state change
+ *
+ * @v hermon Hermon device
+ * @v port Hermon port
+ * @v link_up Link is up
+ */
+static void hermon_state_change_ibdev ( struct hermon *hermon __unused,
+ struct hermon_port *port,
+ int link_up __unused ) {
+ struct ib_device *ibdev = port->ibdev;
+
+ /* Update MAD parameters */
+ ib_smc_update ( ibdev, hermon_mad );
+}
+
+/**
+ * Unregister Hermon Infiniband device
+ *
+ * @v hermon Hermon device
+ * @v port Hermon port
+ */
+static void hermon_unregister_ibdev ( struct hermon *hermon __unused,
+ struct hermon_port *port ) {
+ struct ib_device *ibdev = port->ibdev;
+
+ unregister_ibdev ( ibdev );
+}
+
+/** Hermon Infiniband port type */
+static struct hermon_port_type hermon_port_type_ib = {
+ .register_dev = hermon_register_ibdev,
+ .state_change = hermon_state_change_ibdev,
+ .unregister_dev = hermon_unregister_ibdev,
+};
+
+/***************************************************************************
+ *
+ * Ethernet operation
+ *
+ ***************************************************************************
+ */
+
+/** Number of Hermon Ethernet send work queue entries */
+#define HERMON_ETH_NUM_SEND_WQES 2
+
+/** Number of Hermon Ethernet receive work queue entries */
+#define HERMON_ETH_NUM_RECV_WQES 4
+
+/** Number of Hermon Ethernet completion entries */
+#define HERMON_ETH_NUM_CQES 8
+
+/**
+ * Transmit packet via Hermon Ethernet device
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int hermon_eth_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct hermon_port *port = netdev->priv;
+ struct ib_device *ibdev = port->ibdev;
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ int rc;
+
+ /* Transmit packet */
+ if ( ( rc = ib_post_send ( ibdev, port->eth_qp, NULL,
+ iobuf ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not transmit: %s\n",
+ hermon, ibdev->port, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle Hermon Ethernet device send completion
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+static void hermon_eth_complete_send ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf, int rc ) {
+ struct net_device *netdev = ib_qp_get_ownerdata ( qp );
+
+ netdev_tx_complete_err ( netdev, iobuf, rc );
+}
+
+/**
+ * Handle Hermon Ethernet device receive completion
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector, or NULL
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+static void hermon_eth_complete_recv ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc ) {
+ struct net_device *netdev = ib_qp_get_ownerdata ( qp );
+ struct net_device *vlan;
+
+ /* Find VLAN device, if applicable */
+ if ( av->vlan_present ) {
+ if ( ( vlan = vlan_find ( netdev, av->vlan ) ) != NULL ) {
+ netdev = vlan;
+ } else if ( rc == 0 ) {
+ rc = -ENODEV;
+ }
+ }
+
+ /* Hand off to network layer */
+ if ( rc == 0 ) {
+ netdev_rx ( netdev, iobuf );
+ } else {
+ netdev_rx_err ( netdev, iobuf, rc );
+ }
+}
+
+/** Hermon Ethernet device completion operations */
+static struct ib_completion_queue_operations hermon_eth_cq_op = {
+ .complete_send = hermon_eth_complete_send,
+ .complete_recv = hermon_eth_complete_recv,
+};
+
+/**
+ * Poll Hermon Ethernet device
+ *
+ * @v netdev Network device
+ */
+static void hermon_eth_poll ( struct net_device *netdev ) {
+ struct hermon_port *port = netdev->priv;
+ struct ib_device *ibdev = port->ibdev;
+
+ ib_poll_eq ( ibdev );
+}
+
+/**
+ * Open Hermon Ethernet device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int hermon_eth_open ( struct net_device *netdev ) {
+ struct hermon_port *port = netdev->priv;
+ struct ib_device *ibdev = port->ibdev;
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ union hermonprm_set_port set_port;
+ int rc;
+
+ /* Open hardware */
+ if ( ( rc = hermon_open ( hermon ) ) != 0 )
+ goto err_open;
+
+ /* Allocate completion queue */
+ port->eth_cq = ib_create_cq ( ibdev, HERMON_ETH_NUM_CQES,
+ &hermon_eth_cq_op );
+ if ( ! port->eth_cq ) {
+ DBGC ( hermon, "Hermon %p port %d could not create completion "
+ "queue\n", hermon, ibdev->port );
+ rc = -ENOMEM;
+ goto err_create_cq;
+ }
+
+ /* Allocate queue pair */
+ port->eth_qp = ib_create_qp ( ibdev, IB_QPT_ETH,
+ HERMON_ETH_NUM_SEND_WQES, port->eth_cq,
+ HERMON_ETH_NUM_RECV_WQES, port->eth_cq );
+ if ( ! port->eth_qp ) {
+ DBGC ( hermon, "Hermon %p port %d could not create queue "
+ "pair\n", hermon, ibdev->port );
+ rc = -ENOMEM;
+ goto err_create_qp;
+ }
+ ib_qp_set_ownerdata ( port->eth_qp, netdev );
+
+ /* Activate queue pair */
+ if ( ( rc = ib_modify_qp ( ibdev, port->eth_qp ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not modify queue "
+ "pair: %s\n", hermon, ibdev->port, strerror ( rc ) );
+ goto err_modify_qp;
+ }
+
+ /* Fill receive rings */
+ ib_refill_recv ( ibdev, port->eth_qp );
+
+ /* Set port general parameters */
+ memset ( &set_port, 0, sizeof ( set_port ) );
+ MLX_FILL_3 ( &set_port.general, 0,
+ v_mtu, 1,
+ v_pprx, 1,
+ v_pptx, 1 );
+ MLX_FILL_1 ( &set_port.general, 1,
+ mtu, ( ETH_FRAME_LEN + 40 /* Used by card */ ) );
+ MLX_FILL_1 ( &set_port.general, 2,
+ pfctx, ( 1 << FCOE_VLAN_PRIORITY ) );
+ MLX_FILL_1 ( &set_port.general, 3,
+ pfcrx, ( 1 << FCOE_VLAN_PRIORITY ) );
+ if ( ( rc = hermon_cmd_set_port ( hermon, 1,
+ ( HERMON_SET_PORT_GENERAL_PARAM |
+ ibdev->port ),
+ &set_port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not set port general "
+ "parameters: %s\n",
+ hermon, ibdev->port, strerror ( rc ) );
+ goto err_set_port_general_params;
+ }
+
+ /* Set port receive QP */
+ memset ( &set_port, 0, sizeof ( set_port ) );
+ MLX_FILL_1 ( &set_port.rqp_calc, 0, base_qpn, port->eth_qp->qpn );
+ MLX_FILL_1 ( &set_port.rqp_calc, 2,
+ mac_miss_index, 128 /* MAC misses go to promisc QP */ );
+ MLX_FILL_2 ( &set_port.rqp_calc, 3,
+ vlan_miss_index, 127 /* VLAN misses go to promisc QP */,
+ no_vlan_index, 126 /* VLAN-free go to promisc QP */ );
+ MLX_FILL_2 ( &set_port.rqp_calc, 5,
+ promisc_qpn, port->eth_qp->qpn,
+ en_uc_promisc, 1 );
+ MLX_FILL_2 ( &set_port.rqp_calc, 6,
+ def_mcast_qpn, port->eth_qp->qpn,
+ mc_promisc_mode, 2 /* Receive all multicasts */ );
+ if ( ( rc = hermon_cmd_set_port ( hermon, 1,
+ ( HERMON_SET_PORT_RECEIVE_QP |
+ ibdev->port ),
+ &set_port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not set port receive "
+ "QP: %s\n", hermon, ibdev->port, strerror ( rc ) );
+ goto err_set_port_receive_qp;
+ }
+
+ /* Initialise port */
+ if ( ( rc = hermon_cmd_init_port ( hermon, ibdev->port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not initialise port: "
+ "%s\n", hermon, ibdev->port, strerror ( rc ) );
+ goto err_init_port;
+ }
+
+ return 0;
+
+ err_init_port:
+ err_set_port_receive_qp:
+ err_set_port_general_params:
+ err_modify_qp:
+ ib_destroy_qp ( ibdev, port->eth_qp );
+ err_create_qp:
+ ib_destroy_cq ( ibdev, port->eth_cq );
+ err_create_cq:
+ hermon_close ( hermon );
+ err_open:
+ return rc;
+}
+
+/**
+ * Close Hermon Ethernet device
+ *
+ * @v netdev Network device
+ */
+static void hermon_eth_close ( struct net_device *netdev ) {
+ struct hermon_port *port = netdev->priv;
+ struct ib_device *ibdev = port->ibdev;
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ int rc;
+
+ /* Close port */
+ if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not close port: %s\n",
+ hermon, ibdev->port, strerror ( rc ) );
+ /* Nothing we can do about this */
+ }
+
+ /* Tear down the queues */
+ ib_destroy_qp ( ibdev, port->eth_qp );
+ ib_destroy_cq ( ibdev, port->eth_cq );
+
+ /* Close hardware */
+ hermon_close ( hermon );
+}
+
+/** Hermon Ethernet network device operations */
+static struct net_device_operations hermon_eth_operations = {
+ .open = hermon_eth_open,
+ .close = hermon_eth_close,
+ .transmit = hermon_eth_transmit,
+ .poll = hermon_eth_poll,
+};
+
+/**
+ * Register Hermon Ethernet device
+ *
+ * @v hermon Hermon device
+ * @v port Hermon port
+ * @ret rc Return status code
+ */
+static int hermon_register_netdev ( struct hermon *hermon,
+ struct hermon_port *port ) {
+ struct net_device *netdev = port->netdev;
+ struct ib_device *ibdev = port->ibdev;
+ struct hermonprm_query_port_cap query_port;
+ union {
+ uint8_t bytes[8];
+ uint32_t dwords[2];
+ } mac;
+ int rc;
+
+ /* Retrieve MAC address */
+ if ( ( rc = hermon_cmd_query_port ( hermon, ibdev->port,
+ &query_port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not query port: %s\n",
+ hermon, ibdev->port, strerror ( rc ) );
+ return rc;
+ }
+ mac.dwords[0] = htonl ( MLX_GET ( &query_port, mac_47_32 ) );
+ mac.dwords[1] = htonl ( MLX_GET ( &query_port, mac_31_0 ) );
+ memcpy ( netdev->hw_addr,
+ &mac.bytes[ sizeof ( mac.bytes ) - ETH_ALEN ], ETH_ALEN );
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not register network "
+ "device: %s\n", hermon, ibdev->port, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle Hermon Ethernet device port state change
+ *
+ * @v hermon Hermon device
+ * @v port Hermon port
+ * @v link_up Link is up
+ */
+static void hermon_state_change_netdev ( struct hermon *hermon __unused,
+ struct hermon_port *port,
+ int link_up ) {
+ struct net_device *netdev = port->netdev;
+
+ if ( link_up ) {
+ netdev_link_up ( netdev );
+ } else {
+ netdev_link_down ( netdev );
+ }
+}
+
+/**
+ * Unregister Hermon Ethernet device
+ *
+ * @v hermon Hermon device
+ * @v port Hermon port
+ */
+static void hermon_unregister_netdev ( struct hermon *hermon __unused,
+ struct hermon_port *port ) {
+ struct net_device *netdev = port->netdev;
+
+ unregister_netdev ( netdev );
+}
+
+/** Hermon Ethernet port type */
+static struct hermon_port_type hermon_port_type_eth = {
+ .register_dev = hermon_register_netdev,
+ .state_change = hermon_state_change_netdev,
+ .unregister_dev = hermon_unregister_netdev,
+};
+
+/***************************************************************************
+ *
+ * Port type detection
+ *
+ ***************************************************************************
+ */
+
+/** Timeout for port sensing */
+#define HERMON_SENSE_PORT_TIMEOUT ( TICKS_PER_SEC / 2 )
+
+/**
+ * Name port type
+ *
+ * @v port_type Port type
+ * @v port_type_name Port type name
+ */
+static inline const char * hermon_name_port_type ( unsigned int port_type ) {
+ switch ( port_type ) {
+ case HERMON_PORT_TYPE_UNKNOWN: return "unknown";
+ case HERMON_PORT_TYPE_IB: return "Infiniband";
+ case HERMON_PORT_TYPE_ETH: return "Ethernet";
+ default: return "INVALID";
+ }
+}
+
+/**
+ * Sense port type
+ *
+ * @v hermon Hermon device
+ * @v port Hermon port
+ * @ret port_type Port type, or negative error
+ */
+static int hermon_sense_port_type ( struct hermon *hermon,
+ struct hermon_port *port ) {
+ struct ib_device *ibdev = port->ibdev;
+ struct hermonprm_sense_port sense_port;
+ int port_type;
+ int rc;
+
+ /* If DPDP is not supported, always assume Infiniband */
+ if ( ! hermon->cap.dpdp ) {
+ port_type = HERMON_PORT_TYPE_IB;
+ DBGC ( hermon, "Hermon %p port %d does not support DPDP; "
+ "assuming an %s network\n", hermon, ibdev->port,
+ hermon_name_port_type ( port_type ) );
+ return port_type;
+ }
+
+ /* Sense the port type */
+ if ( ( rc = hermon_cmd_sense_port ( hermon, ibdev->port,
+ &sense_port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d sense failed: %s\n",
+ hermon, ibdev->port, strerror ( rc ) );
+ return rc;
+ }
+ port_type = MLX_GET ( &sense_port, port_type );
+
+ DBGC ( hermon, "Hermon %p port %d sensed an %s network\n",
+ hermon, ibdev->port, hermon_name_port_type ( port_type ) );
+ return port_type;
+}
+
+/**
+ * Set port type
+ *
+ * @v hermon Hermon device
+ * @v port Hermon port
+ * @ret rc Return status code
+ */
+static int hermon_set_port_type ( struct hermon *hermon,
+ struct hermon_port *port ) {
+ struct ib_device *ibdev = port->ibdev;
+ struct hermonprm_query_port_cap query_port;
+ int ib_supported;
+ int eth_supported;
+ int port_type;
+ unsigned long start;
+ unsigned long elapsed;
+ int rc;
+
+ /* Check to see which types are supported */
+ if ( ( rc = hermon_cmd_query_port ( hermon, ibdev->port,
+ &query_port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not query port: %s\n",
+ hermon, ibdev->port, strerror ( rc ) );
+ return rc;
+ }
+ ib_supported = MLX_GET ( &query_port, ib );
+ eth_supported = MLX_GET ( &query_port, eth );
+ DBGC ( hermon, "Hermon %p port %d supports%s%s%s\n",
+ hermon, ibdev->port, ( ib_supported ? " Infiniband" : "" ),
+ ( ( ib_supported && eth_supported ) ? " and" : "" ),
+ ( eth_supported ? " Ethernet" : "" ) );
+
+ /* Sense network, if applicable */
+ if ( ib_supported && eth_supported ) {
+
+ /* Both types are supported; try sensing network */
+ start = currticks();
+ do {
+ /* Try sensing port */
+ port_type = hermon_sense_port_type ( hermon, port );
+ if ( port_type < 0 ) {
+ rc = port_type;
+ return rc;
+ }
+ } while ( ( port_type == HERMON_PORT_TYPE_UNKNOWN ) &&
+ ( ( elapsed = ( currticks() - start ) ) <
+ HERMON_SENSE_PORT_TIMEOUT ) );
+
+ /* Set port type based on sensed network, defaulting
+ * to Infiniband if nothing was sensed.
+ */
+ switch ( port_type ) {
+ case HERMON_PORT_TYPE_ETH:
+ port->type = &hermon_port_type_eth;
+ break;
+ case HERMON_PORT_TYPE_IB:
+ case HERMON_PORT_TYPE_UNKNOWN:
+ port->type = &hermon_port_type_ib;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ } else if ( eth_supported ) {
+ port->type = &hermon_port_type_eth;
+ } else {
+ port->type = &hermon_port_type_ib;
+ }
+
+ assert ( port->type != NULL );
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * BOFM interface
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Harvest Ethernet MAC for BOFM
+ *
+ * @v bofm BOFM device
+ * @v mport Multi-port index
+ * @v mac MAC to fill in
+ * @ret rc Return status code
+ */
+static int hermon_bofm_harvest ( struct bofm_device *bofm, unsigned int mport,
+ uint8_t *mac ) {
+ struct hermon *hermon = container_of ( bofm, struct hermon, bofm );
+ struct hermonprm_mod_stat_cfg stat_cfg;
+ union {
+ uint8_t bytes[8];
+ uint32_t dwords[2];
+ } buf;
+ int rc;
+
+ /* Query static configuration */
+ if ( ( rc = hermon_mod_stat_cfg ( hermon, mport,
+ HERMON_MOD_STAT_CFG_QUERY,
+ HERMON_MOD_STAT_CFG_OFFSET ( mac_m ),
+ &stat_cfg ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not query "
+ "configuration: %s\n", hermon, mport, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Retrieve MAC address */
+ buf.dwords[0] = htonl ( MLX_GET ( &stat_cfg, mac_high ) );
+ buf.dwords[1] = htonl ( MLX_GET ( &stat_cfg, mac_low ) );
+ memcpy ( mac, &buf.bytes[ sizeof ( buf.bytes ) - ETH_ALEN ],
+ ETH_ALEN );
+
+ DBGC ( hermon, "Hermon %p port %d harvested MAC address %s\n",
+ hermon, mport, eth_ntoa ( mac ) );
+
+ return 0;
+}
+
+/**
+ * Update Ethernet MAC for BOFM
+ *
+ * @v bofm BOFM device
+ * @v mport Multi-port index
+ * @v mac MAC to fill in
+ * @ret rc Return status code
+ */
+static int hermon_bofm_update ( struct bofm_device *bofm, unsigned int mport,
+ const uint8_t *mac ) {
+ struct hermon *hermon = container_of ( bofm, struct hermon, bofm );
+ struct hermonprm_mod_stat_cfg stat_cfg;
+ union {
+ uint8_t bytes[8];
+ uint32_t dwords[2];
+ } buf;
+ int rc;
+
+ /* Prepare MAC address */
+ memset ( &buf, 0, sizeof ( buf ) );
+ memcpy ( &buf.bytes[ sizeof ( buf.bytes ) - ETH_ALEN ], mac,
+ ETH_ALEN );
+
+ /* Modify static configuration */
+ memset ( &stat_cfg, 0, sizeof ( stat_cfg ) );
+ MLX_FILL_2 ( &stat_cfg, 36,
+ mac_m, 1,
+ mac_high, ntohl ( buf.dwords[0] ) );
+ MLX_FILL_1 ( &stat_cfg, 37, mac_low, ntohl ( buf.dwords[1] ) );
+ if ( ( rc = hermon_mod_stat_cfg ( hermon, mport,
+ HERMON_MOD_STAT_CFG_SET,
+ HERMON_MOD_STAT_CFG_OFFSET ( mac_m ),
+ &stat_cfg ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not modify "
+ "configuration: %s\n", hermon, mport, strerror ( rc ) );
+ return rc;
+ }
+
+ DBGC ( hermon, "Hermon %p port %d updated MAC address to %s\n",
+ hermon, mport, eth_ntoa ( mac ) );
+
+ return 0;
+}
+
+/** Hermon BOFM operations */
+static struct bofm_operations hermon_bofm_operations = {
+ .harvest = hermon_bofm_harvest,
+ .update = hermon_bofm_update,
+};
+
+/***************************************************************************
+ *
+ * PCI interface
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Allocate Hermon device
+ *
+ * @v pci PCI device
+ * @v id PCI ID
+ * @ret rc Return status code
+ */
+static struct hermon * hermon_alloc ( void ) {
+ struct hermon *hermon;
+
+ /* Allocate Hermon device */
+ hermon = zalloc ( sizeof ( *hermon ) );
+ if ( ! hermon )
+ goto err_hermon;
+
+ /* Allocate space for mailboxes */
+ hermon->mailbox_in = malloc_dma ( HERMON_MBOX_SIZE,
+ HERMON_MBOX_ALIGN );
+ if ( ! hermon->mailbox_in )
+ goto err_mailbox_in;
+ hermon->mailbox_out = malloc_dma ( HERMON_MBOX_SIZE,
+ HERMON_MBOX_ALIGN );
+ if ( ! hermon->mailbox_out )
+ goto err_mailbox_out;
+
+ return hermon;
+
+ free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
+ err_mailbox_out:
+ free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
+ err_mailbox_in:
+ free ( hermon );
+ err_hermon:
+ return NULL;
+}
+
+/**
+ * Free Hermon device
+ *
+ * @v hermon Hermon device
+ */
+static void hermon_free ( struct hermon *hermon ) {
+
+ ufree ( hermon->icm );
+ ufree ( hermon->firmware_area );
+ free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
+ free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
+ free ( hermon );
+}
+
+/**
+ * Initialise Hermon PCI parameters
+ *
+ * @v hermon Hermon device
+ */
+static void hermon_pci_init ( struct hermon *hermon ) {
+ struct pci_device *pci = hermon->pci;
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* Get PCI BARs */
+ hermon->config = ioremap ( pci_bar_start ( pci, HERMON_PCI_CONFIG_BAR),
+ HERMON_PCI_CONFIG_BAR_SIZE );
+ hermon->uar = ioremap ( pci_bar_start ( pci, HERMON_PCI_UAR_BAR ),
+ HERMON_UAR_NON_EQ_PAGE * HERMON_PAGE_SIZE );
+}
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @v id PCI ID
+ * @ret rc Return status code
+ */
+static int hermon_probe ( struct pci_device *pci ) {
+ struct hermon *hermon;
+ struct ib_device *ibdev;
+ struct net_device *netdev;
+ struct hermon_port *port;
+ unsigned int i;
+ int rc;
+
+ /* Allocate Hermon device */
+ hermon = hermon_alloc();
+ if ( ! hermon ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ pci_set_drvdata ( pci, hermon );
+ hermon->pci = pci;
+
+ /* Initialise PCI parameters */
+ hermon_pci_init ( hermon );
+
+ /* Reset device */
+ hermon_reset ( hermon );
+
+ /* Start firmware */
+ if ( ( rc = hermon_start_firmware ( hermon ) ) != 0 )
+ goto err_start_firmware;
+
+ /* Get device limits */
+ if ( ( rc = hermon_get_cap ( hermon ) ) != 0 )
+ goto err_get_cap;
+
+ /* Allocate Infiniband devices */
+ for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
+ ibdev = alloc_ibdev ( 0 );
+ if ( ! ibdev ) {
+ rc = -ENOMEM;
+ goto err_alloc_ibdev;
+ }
+ hermon->port[i].ibdev = ibdev;
+ ibdev->op = &hermon_ib_operations;
+ ibdev->dev = &pci->dev;
+ ibdev->port = ( HERMON_PORT_BASE + i );
+ ib_set_drvdata ( ibdev, hermon );
+ }
+
+ /* Allocate network devices */
+ for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
+ netdev = alloc_etherdev ( 0 );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ goto err_alloc_netdev;
+ }
+ hermon->port[i].netdev = netdev;
+ netdev_init ( netdev, &hermon_eth_operations );
+ netdev->dev = &pci->dev;
+ netdev->priv = &hermon->port[i];
+ }
+
+ /* Start device */
+ if ( ( rc = hermon_start ( hermon, 1 ) ) != 0 )
+ goto err_start;
+
+ /* Determine port types */
+ for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
+ port = &hermon->port[i];
+ if ( ( rc = hermon_set_port_type ( hermon, port ) ) != 0 )
+ goto err_set_port_type;
+ }
+
+ /* Register devices */
+ for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
+ port = &hermon->port[i];
+ if ( ( rc = port->type->register_dev ( hermon, port ) ) != 0 )
+ goto err_register;
+ }
+
+ /* Leave device quiescent until opened */
+ if ( hermon->open_count == 0 )
+ hermon_stop ( hermon );
+
+ return 0;
+
+ i = hermon->cap.num_ports;
+ err_register:
+ for ( i-- ; ( signed int ) i >= 0 ; i-- ) {
+ port = &hermon->port[i];
+ port->type->unregister_dev ( hermon, port );
+ }
+ err_set_port_type:
+ hermon_stop ( hermon );
+ err_start:
+ i = hermon->cap.num_ports;
+ err_alloc_netdev:
+ for ( i-- ; ( signed int ) i >= 0 ; i-- ) {
+ netdev_nullify ( hermon->port[i].netdev );
+ netdev_put ( hermon->port[i].netdev );
+ }
+ i = hermon->cap.num_ports;
+ err_alloc_ibdev:
+ for ( i-- ; ( signed int ) i >= 0 ; i-- )
+ ibdev_put ( hermon->port[i].ibdev );
+ err_get_cap:
+ hermon_stop_firmware ( hermon );
+ err_start_firmware:
+ hermon_free ( hermon );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void hermon_remove ( struct pci_device *pci ) {
+ struct hermon *hermon = pci_get_drvdata ( pci );
+ struct hermon_port *port;
+ int i;
+
+ for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- ) {
+ port = &hermon->port[i];
+ port->type->unregister_dev ( hermon, port );
+ }
+ for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- ) {
+ netdev_nullify ( hermon->port[i].netdev );
+ netdev_put ( hermon->port[i].netdev );
+ }
+ for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- )
+ ibdev_put ( hermon->port[i].ibdev );
+ hermon_free ( hermon );
+}
+
+/**
+ * Probe PCI device for BOFM
+ *
+ * @v pci PCI device
+ * @v id PCI ID
+ * @ret rc Return status code
+ */
+static int hermon_bofm_probe ( struct pci_device *pci ) {
+ struct hermon *hermon;
+ int rc;
+
+ /* Allocate Hermon device */
+ hermon = hermon_alloc();
+ if ( ! hermon ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ pci_set_drvdata ( pci, hermon );
+ hermon->pci = pci;
+
+ /* Initialise PCI parameters */
+ hermon_pci_init ( hermon );
+
+ /* Initialise BOFM device */
+ bofm_init ( &hermon->bofm, pci, &hermon_bofm_operations );
+
+ /* Register BOFM device */
+ if ( ( rc = bofm_register ( &hermon->bofm ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not register BOFM device: "
+ "%s\n", hermon, strerror ( rc ) );
+ goto err_bofm_register;
+ }
+
+ return 0;
+
+ err_bofm_register:
+ hermon_free ( hermon );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Remove PCI device for BOFM
+ *
+ * @v pci PCI device
+ */
+static void hermon_bofm_remove ( struct pci_device *pci ) {
+ struct hermon *hermon = pci_get_drvdata ( pci );
+
+ bofm_unregister ( &hermon->bofm );
+ hermon_free ( hermon );
+}
+
+static struct pci_device_id hermon_nics[] = {
+ PCI_ROM ( 0x15b3, 0x6340, "mt25408", "MT25408 HCA driver", 0 ),
+ PCI_ROM ( 0x15b3, 0x634a, "mt25418", "MT25418 HCA driver", 0 ),
+ PCI_ROM ( 0x15b3, 0x6732, "mt26418", "MT26418 HCA driver", 0 ),
+ PCI_ROM ( 0x15b3, 0x673c, "mt26428", "MT26428 HCA driver", 0 ),
+ PCI_ROM ( 0x15b3, 0x6746, "mt26438", "MT26438 HCA driver", 0 ),
+ PCI_ROM ( 0x15b3, 0x6778, "mt26488", "MT26488 HCA driver", 0 ),
+ PCI_ROM ( 0x15b3, 0x6368, "mt25448", "MT25448 HCA driver", 0 ),
+ PCI_ROM ( 0x15b3, 0x6750, "mt26448", "MT26448 HCA driver", 0 ),
+ PCI_ROM ( 0x15b3, 0x6372, "mt25458", "MT25458 HCA driver", 0 ),
+ PCI_ROM ( 0x15b3, 0x675a, "mt26458", "MT26458 HCA driver", 0 ),
+ PCI_ROM ( 0x15b3, 0x6764, "mt26468", "MT26468 HCA driver", 0 ),
+ PCI_ROM ( 0x15b3, 0x676e, "mt26478", "MT26478 HCA driver", 0 ),
+};
+
+struct pci_driver hermon_driver __pci_driver = {
+ .ids = hermon_nics,
+ .id_count = ( sizeof ( hermon_nics ) / sizeof ( hermon_nics[0] ) ),
+ .probe = hermon_probe,
+ .remove = hermon_remove,
+};
+
+struct pci_driver hermon_bofm_driver __bofm_driver = {
+ .ids = hermon_nics,
+ .id_count = ( sizeof ( hermon_nics ) / sizeof ( hermon_nics[0] ) ),
+ .probe = hermon_bofm_probe,
+ .remove = hermon_bofm_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/hermon.h b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/hermon.h
new file mode 100644
index 00000000..26940f6f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/hermon.h
@@ -0,0 +1,953 @@
+#ifndef _HERMON_H
+#define _HERMON_H
+
+/** @file
+ *
+ * Mellanox Hermon Infiniband HCA driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/ib_packet.h>
+#include <ipxe/bofm.h>
+#include "mlx_bitops.h"
+#include "MT25408_PRM.h"
+
+/*
+ * Hardware constants
+ *
+ */
+
+/* Ports in existence */
+#define HERMON_MAX_PORTS 2
+#define HERMON_PORT_BASE 1
+
+/* PCI BARs */
+#define HERMON_PCI_CONFIG_BAR PCI_BASE_ADDRESS_0
+#define HERMON_PCI_CONFIG_BAR_SIZE 0x100000
+#define HERMON_PCI_UAR_BAR PCI_BASE_ADDRESS_2
+
+/* Device reset */
+#define HERMON_RESET_OFFSET 0x0f0010
+#define HERMON_RESET_MAGIC 0x01000000UL
+#define HERMON_RESET_WAIT_TIME_MS 1000
+
+/* Work queue entry and completion queue entry opcodes */
+#define HERMON_OPCODE_NOP 0x00
+#define HERMON_OPCODE_SEND 0x0a
+#define HERMON_OPCODE_RECV_ERROR 0xfe
+#define HERMON_OPCODE_SEND_ERROR 0xff
+
+/* HCA command register opcodes */
+#define HERMON_HCR_QUERY_DEV_CAP 0x0003
+#define HERMON_HCR_QUERY_FW 0x0004
+#define HERMON_HCR_INIT_HCA 0x0007
+#define HERMON_HCR_CLOSE_HCA 0x0008
+#define HERMON_HCR_INIT_PORT 0x0009
+#define HERMON_HCR_CLOSE_PORT 0x000a
+#define HERMON_HCR_SET_PORT 0x000c
+#define HERMON_HCR_SW2HW_MPT 0x000d
+#define HERMON_HCR_WRITE_MTT 0x0011
+#define HERMON_HCR_MAP_EQ 0x0012
+#define HERMON_HCR_SW2HW_EQ 0x0013
+#define HERMON_HCR_HW2SW_EQ 0x0014
+#define HERMON_HCR_QUERY_EQ 0x0015
+#define HERMON_HCR_SW2HW_CQ 0x0016
+#define HERMON_HCR_HW2SW_CQ 0x0017
+#define HERMON_HCR_QUERY_CQ 0x0018
+#define HERMON_HCR_RST2INIT_QP 0x0019
+#define HERMON_HCR_INIT2RTR_QP 0x001a
+#define HERMON_HCR_RTR2RTS_QP 0x001b
+#define HERMON_HCR_RTS2RTS_QP 0x001c
+#define HERMON_HCR_2RST_QP 0x0021
+#define HERMON_HCR_QUERY_QP 0x0022
+#define HERMON_HCR_CONF_SPECIAL_QP 0x0023
+#define HERMON_HCR_MAD_IFC 0x0024
+#define HERMON_HCR_READ_MCG 0x0025
+#define HERMON_HCR_WRITE_MCG 0x0026
+#define HERMON_HCR_MGID_HASH 0x0027
+#define HERMON_HCR_MOD_STAT_CFG 0x0034
+#define HERMON_HCR_QUERY_PORT 0x0043
+#define HERMON_HCR_SENSE_PORT 0x004d
+#define HERMON_HCR_RUN_FW 0x0ff6
+#define HERMON_HCR_DISABLE_LAM 0x0ff7
+#define HERMON_HCR_ENABLE_LAM 0x0ff8
+#define HERMON_HCR_UNMAP_ICM 0x0ff9
+#define HERMON_HCR_MAP_ICM 0x0ffa
+#define HERMON_HCR_UNMAP_ICM_AUX 0x0ffb
+#define HERMON_HCR_MAP_ICM_AUX 0x0ffc
+#define HERMON_HCR_SET_ICM_SIZE 0x0ffd
+#define HERMON_HCR_UNMAP_FA 0x0ffe
+#define HERMON_HCR_MAP_FA 0x0fff
+
+/* Service types */
+#define HERMON_ST_RC 0x00
+#define HERMON_ST_UD 0x03
+#define HERMON_ST_MLX 0x07
+
+/* Port types */
+#define HERMON_PORT_TYPE_UNKNOWN 0
+#define HERMON_PORT_TYPE_IB 1
+#define HERMON_PORT_TYPE_ETH 2
+
+/* MTUs */
+#define HERMON_MTU_2048 0x04
+#define HERMON_MTU_ETH 0x07
+
+#define HERMON_INVALID_LKEY 0x00000100UL
+
+#define HERMON_PAGE_SIZE ( ( size_t ) 4096 )
+
+#define HERMON_DB_POST_SND_OFFSET 0x14
+#define HERMON_DB_EQ_OFFSET(_eqn) \
+ ( 0x800 + HERMON_PAGE_SIZE * ( (_eqn) / 4 ) + 0x08 * ( (_eqn) % 4 ) )
+
+#define HERMON_QP_OPT_PARAM_PM_STATE 0x00000400UL
+#define HERMON_QP_OPT_PARAM_QKEY 0x00000020UL
+#define HERMON_QP_OPT_PARAM_ALT_PATH 0x00000001UL
+
+#define HERMON_MAP_EQ ( 0UL << 31 )
+#define HERMON_UNMAP_EQ ( 1UL << 31 )
+
+#define HERMON_SET_PORT_GENERAL_PARAM 0x0000
+#define HERMON_SET_PORT_RECEIVE_QP 0x0100
+#define HERMON_SET_PORT_MAC_TABLE 0x0200
+#define HERMON_SET_PORT_VLAN_TABLE 0x0300
+#define HERMON_SET_PORT_PRIORITY_TABLE 0x0400
+#define HERMON_SET_PORT_GID_TABLE 0x0500
+
+#define HERMON_EV_PORT_STATE_CHANGE 0x09
+
+#define HERMON_SCHED_QP0 0x3f
+#define HERMON_SCHED_DEFAULT 0x83
+
+#define HERMON_LOG_MULTICAST_HASH_SIZE 7
+
+#define HERMON_PM_STATE_ARMED 0x00
+#define HERMON_PM_STATE_REARM 0x01
+#define HERMON_PM_STATE_MIGRATED 0x03
+
+#define HERMON_RETRY_MAX 0x07
+
+#define HERMON_MOD_STAT_CFG_SET 0x01
+#define HERMON_MOD_STAT_CFG_QUERY 0x03
+
+/*
+ * Datatypes that seem to be missing from the autogenerated documentation
+ *
+ */
+struct hermonprm_mgm_hash_st {
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+ pseudo_bit_t hash[0x00010];
+ pseudo_bit_t reserved1[0x00010];
+} __attribute__ (( packed ));
+
+struct hermonprm_mcg_entry_st {
+ struct hermonprm_mcg_hdr_st hdr;
+ struct hermonprm_mcg_qp_dw_st qp[8];
+} __attribute__ (( packed ));
+
+struct hermonprm_cq_db_record_st {
+ pseudo_bit_t update_ci[0x00018];
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t arm_ci[0x00018];
+ pseudo_bit_t cmd[0x00003];
+ pseudo_bit_t reserved1[0x00001];
+ pseudo_bit_t cmd_sn[0x00002];
+ pseudo_bit_t reserved2[0x00002];
+} __attribute__ (( packed ));
+
+struct hermonprm_send_db_register_st {
+ pseudo_bit_t reserved[0x00008];
+ pseudo_bit_t qn[0x00018];
+} __attribute__ (( packed ));
+
+struct hermonprm_event_db_register_st {
+ pseudo_bit_t ci[0x00018];
+ pseudo_bit_t reserver[0x00007];
+ pseudo_bit_t a[0x00001];
+} __attribute__ (( packed ));
+
+struct hermonprm_scalar_parameter_st {
+ pseudo_bit_t value_hi[0x00020];
+/* -------------- */
+ pseudo_bit_t value[0x00020];
+} __attribute__ (( packed ));
+
+struct hermonprm_event_mask_st {
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+ pseudo_bit_t completion[0x00001];
+ pseudo_bit_t path_migration_succeeded[0x00001];
+ pseudo_bit_t communication_established[0x00001];
+ pseudo_bit_t send_queue_drained[0x00001];
+ pseudo_bit_t cq_error[0x00001];
+ pseudo_bit_t wq_catastrophe[0x00001];
+ pseudo_bit_t qpc_catastrophe[0x00001];
+ pseudo_bit_t path_migration_failed[0x00001];
+ pseudo_bit_t internal_error[0x00001];
+ pseudo_bit_t port_state_change[0x00001];
+ pseudo_bit_t command_done[0x00001];
+ pseudo_bit_t fexch_error[0x00001];
+ pseudo_bit_t reserved1[0x00004];
+ pseudo_bit_t wq_invalid_request[0x00001];
+ pseudo_bit_t wq_access_violation[0x00001];
+ pseudo_bit_t srq_catastrophe[0x00001];
+ pseudo_bit_t srq_last_wqe[0x00001];
+ pseudo_bit_t srq_rq_limit[0x00001];
+ pseudo_bit_t gpio[0x00001];
+ pseudo_bit_t clientreregister[0x00001];
+ pseudo_bit_t reserved2[0x00009];
+} __attribute__ (( packed ));
+
+struct hermonprm_port_state_change_event_st {
+ pseudo_bit_t reserved[0x00020];
+/* -------------- */
+ struct hermonprm_port_state_change_st data;
+} __attribute__ (( packed ));
+
+struct hermonprm_sense_port_st {
+ pseudo_bit_t reserved0[0x00020];
+/* -------------- */
+ pseudo_bit_t port_type[0x00002];
+ pseudo_bit_t reserved1[0x0001e];
+} __attribute__ (( packed ));
+
+struct hermonprm_set_port_ib_st {
+ pseudo_bit_t rqk[0x00001];
+ pseudo_bit_t rcm[0x00001];
+ pseudo_bit_t reserved0[0x00002];
+ pseudo_bit_t vl_cap[0x00004];
+ pseudo_bit_t reserved1[0x00004];
+ pseudo_bit_t mtu_cap[0x00004];
+ pseudo_bit_t g0[0x00001];
+ pseudo_bit_t ng[0x00001];
+ pseudo_bit_t sig[0x00001];
+ pseudo_bit_t mg[0x00001];
+ pseudo_bit_t mp[0x00001];
+ pseudo_bit_t mvc[0x00001];
+ pseudo_bit_t mmc[0x00001];
+ pseudo_bit_t reserved2[0x00004];
+ pseudo_bit_t lws[0x00001];
+ pseudo_bit_t lss[0x00001];
+ pseudo_bit_t reserved3[0x00003];
+/* -------------- */
+ pseudo_bit_t capability_mask[0x00020];
+/* -------------- */
+ pseudo_bit_t system_image_guid_h[0x00020];
+/* -------------- */
+ pseudo_bit_t system_image_guid_l[0x00020];
+/* -------------- */
+ pseudo_bit_t guid0_h[0x00020];
+/* -------------- */
+ pseudo_bit_t guid0_l[0x00020];
+/* -------------- */
+ pseudo_bit_t node_guid_h[0x00020];
+/* -------------- */
+ pseudo_bit_t node_guid_l[0x00020];
+/* -------------- */
+ pseudo_bit_t egress_sniff_qpn[0x00018];
+ pseudo_bit_t egress_sniff_mode[0x00002];
+ pseudo_bit_t reserved4[0x00006];
+/* -------------- */
+ pseudo_bit_t ingress_sniff_qpn[0x00018];
+ pseudo_bit_t ingress_sniff_mode[0x00002];
+ pseudo_bit_t reserved5[0x00006];
+/* -------------- */
+ pseudo_bit_t max_gid[0x00010];
+ pseudo_bit_t max_pkey[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved6[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved7[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved8[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved9[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved10[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved11[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved12[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved13[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved14[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved15[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved16[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved17[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved18[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved19[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved20[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved21[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved22[0x00020];
+/* -------------- */
+ pseudo_bit_t link_width_supported[0x00004];
+ pseudo_bit_t link_speed_supported[0x00004];
+ pseudo_bit_t reserved23[0x00018];
+/* -------------- */
+} __attribute__ (( packed ));
+
+struct hermonprm_query_port_cap_st {
+ pseudo_bit_t eth_mtu[0x00010];
+ pseudo_bit_t ib_mtu[0x00004];
+ pseudo_bit_t reserved0[0x00004];
+ pseudo_bit_t ib[0x00001];
+ pseudo_bit_t eth[0x00001];
+ pseudo_bit_t reserved1[0x00005];
+ pseudo_bit_t link_state[0x00001];
+/* -------------- */
+ pseudo_bit_t log_max_pkey[0x00004];
+ pseudo_bit_t log_max_gid[0x00004];
+ pseudo_bit_t ib_port_width[0x00004];
+ pseudo_bit_t reserved2[0x00004];
+ pseudo_bit_t eth_link_speed[0x00004];
+ pseudo_bit_t reserved3[0x00004];
+ pseudo_bit_t ib_link_speed[0x00004];
+ pseudo_bit_t reserved4[0x00004];
+/* -------------- */
+ pseudo_bit_t max_vl_ib[0x00004];
+ pseudo_bit_t reserved5[0x00004];
+ pseudo_bit_t log_max_mac[0x00004];
+ pseudo_bit_t log_max_vlan[0x00004];
+ pseudo_bit_t reserved6[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved7[0x00020];
+/* -------------- */
+ pseudo_bit_t mac_47_32[0x00010];
+ pseudo_bit_t reserved8[0x00010];
+/* -------------- */
+ pseudo_bit_t mac_31_0[0x00020];
+/* -------------- */
+ pseudo_bit_t vendor_oui[0x00018];
+ pseudo_bit_t transceiver_type[0x00008];
+/* -------------- */
+ pseudo_bit_t reserved9[0x00010];
+ pseudo_bit_t wavelength[0x00010];
+/* -------------- */
+ pseudo_bit_t transceiver_code_hi[0x00020];
+/* -------------- */
+ pseudo_bit_t transceiver_code_lo[0x00020];
+/* -------------- */
+ pseudo_bit_t reserved10[0x000c0];
+} __attribute__ (( packed ));
+
+struct hermonprm_set_port_general_context_st {
+ pseudo_bit_t v_mtu[0x00001];
+ pseudo_bit_t v_pprx[0x00001];
+ pseudo_bit_t v_pptx[0x00001];
+ pseudo_bit_t reserved0[0x0001d];
+/* -------------- */
+ pseudo_bit_t mtu[0x00010];
+ pseudo_bit_t reserved1[0x00010];
+/* -------------- */
+ pseudo_bit_t reserved2[0x00010];
+ pseudo_bit_t pfctx[0x00008];
+ pseudo_bit_t reserved3[0x00007];
+ pseudo_bit_t pptx[0x00001];
+/* -------------- */
+ pseudo_bit_t reserved4[0x00010];
+ pseudo_bit_t pfcrx[0x00008];
+ pseudo_bit_t reserved5[0x00007];
+ pseudo_bit_t pprx[0x00001];
+/* -------------- */
+} __attribute__ (( packed ));
+
+struct hermonprm_set_port_rqp_calc_st {
+ pseudo_bit_t base_qpn[0x00018];
+ pseudo_bit_t reserved0[0x00008];
+/* -------------- */
+ pseudo_bit_t n_p[0x00002];
+ pseudo_bit_t reserved1[0x00006];
+ pseudo_bit_t n_v[0x00003];
+ pseudo_bit_t reserved2[0x00005];
+ pseudo_bit_t n_m[0x00004];
+ pseudo_bit_t reserved3[0x0000c];
+/* -------------- */
+ pseudo_bit_t mac_miss_index[0x00008];
+ pseudo_bit_t reserved4[0x00018];
+/* -------------- */
+ pseudo_bit_t vlan_miss_index[0x00007];
+ pseudo_bit_t reserved5[0x00008];
+ pseudo_bit_t intra_miss[0x00001];
+ pseudo_bit_t no_vlan_index[0x00007];
+ pseudo_bit_t reserved6[0x00008];
+ pseudo_bit_t intra_no_vlan[0x00001];
+/* -------------- */
+ pseudo_bit_t no_vlan_prio[0x00003];
+ pseudo_bit_t reserved7[0x0001d];
+/* -------------- */
+ pseudo_bit_t promisc_qpn[0x00018];
+ pseudo_bit_t reserved8[0x00007];
+ pseudo_bit_t en_uc_promisc[0x00001];
+/* -------------- */
+ pseudo_bit_t def_mcast_qpn[0x00018];
+ pseudo_bit_t reserved9[0x00005];
+ pseudo_bit_t mc_by_vlan[0x00001];
+ pseudo_bit_t mc_promisc_mode[0x00002];
+/* -------------- */
+ pseudo_bit_t reserved10[0x00020];
+/* -------------- */
+} __attribute__ (( packed ));
+
+struct hermonprm_set_port_mac_table_st {
+ pseudo_bit_t mac_h[0x00010];
+ pseudo_bit_t reserved0[0x0000f];
+ pseudo_bit_t v[0x00001];
+/* -------------- */
+ pseudo_bit_t mac_l[0x00020];
+/* -------------- */
+} __attribute__ (( packed ));
+
+struct hermonprm_set_port_vlan_st {
+ pseudo_bit_t vlan_id[0x0000c];
+ pseudo_bit_t reserved0[0x00012];
+ pseudo_bit_t intra[0x00001];
+ pseudo_bit_t v[0x00001];
+/* -------------- */
+} __attribute__ (( packed ));
+
+struct hermonprm_mod_stat_cfg_input_mod_st {
+ pseudo_bit_t offset[0x00008];
+ pseudo_bit_t portnum[0x00008];
+ pseudo_bit_t xnum[0x00004];
+ pseudo_bit_t linkspeed[0x00003];
+ pseudo_bit_t autoneg[0x00001];
+ pseudo_bit_t reserved[0x00004];
+ pseudo_bit_t setup_mode[0x00004];
+} __attribute__ (( packed ));
+
+/*
+ * Wrapper structures for hardware datatypes
+ *
+ */
+
+struct MLX_DECLARE_STRUCT ( hermonprm_completion_queue_context );
+struct MLX_DECLARE_STRUCT ( hermonprm_completion_queue_entry );
+struct MLX_DECLARE_STRUCT ( hermonprm_completion_with_error );
+struct MLX_DECLARE_STRUCT ( hermonprm_cq_db_record );
+struct MLX_DECLARE_STRUCT ( hermonprm_eqc );
+struct MLX_DECLARE_STRUCT ( hermonprm_event_db_register );
+struct MLX_DECLARE_STRUCT ( hermonprm_event_mask );
+struct MLX_DECLARE_STRUCT ( hermonprm_event_queue_entry );
+struct MLX_DECLARE_STRUCT ( hermonprm_hca_command_register );
+struct MLX_DECLARE_STRUCT ( hermonprm_init_hca );
+struct MLX_DECLARE_STRUCT ( hermonprm_mad_ifc );
+struct MLX_DECLARE_STRUCT ( hermonprm_mcg_entry );
+struct MLX_DECLARE_STRUCT ( hermonprm_mgm_hash );
+struct MLX_DECLARE_STRUCT ( hermonprm_mod_stat_cfg );
+struct MLX_DECLARE_STRUCT ( hermonprm_mod_stat_cfg_input_mod );
+struct MLX_DECLARE_STRUCT ( hermonprm_mpt );
+struct MLX_DECLARE_STRUCT ( hermonprm_mtt );
+struct MLX_DECLARE_STRUCT ( hermonprm_port_state_change_event );
+struct MLX_DECLARE_STRUCT ( hermonprm_qp_db_record );
+struct MLX_DECLARE_STRUCT ( hermonprm_qp_ee_state_transitions );
+struct MLX_DECLARE_STRUCT ( hermonprm_query_dev_cap );
+struct MLX_DECLARE_STRUCT ( hermonprm_query_fw );
+struct MLX_DECLARE_STRUCT ( hermonprm_query_port_cap );
+struct MLX_DECLARE_STRUCT ( hermonprm_queue_pair_ee_context_entry );
+struct MLX_DECLARE_STRUCT ( hermonprm_scalar_parameter );
+struct MLX_DECLARE_STRUCT ( hermonprm_sense_port );
+struct MLX_DECLARE_STRUCT ( hermonprm_send_db_register );
+struct MLX_DECLARE_STRUCT ( hermonprm_set_port_ib );
+struct MLX_DECLARE_STRUCT ( hermonprm_set_port_general_context );
+struct MLX_DECLARE_STRUCT ( hermonprm_set_port_mac_table );
+struct MLX_DECLARE_STRUCT ( hermonprm_set_port_rqp_calc );
+struct MLX_DECLARE_STRUCT ( hermonprm_set_port_vlan );
+struct MLX_DECLARE_STRUCT ( hermonprm_ud_address_vector );
+struct MLX_DECLARE_STRUCT ( hermonprm_virtual_physical_mapping );
+struct MLX_DECLARE_STRUCT ( hermonprm_wqe_segment_ctrl_mlx );
+struct MLX_DECLARE_STRUCT ( hermonprm_wqe_segment_ctrl_send );
+struct MLX_DECLARE_STRUCT ( hermonprm_wqe_segment_data_ptr );
+struct MLX_DECLARE_STRUCT ( hermonprm_wqe_segment_ud );
+
+/*
+ * Composite hardware datatypes
+ *
+ */
+
+struct hermonprm_write_mtt {
+ struct hermonprm_scalar_parameter mtt_base_addr;
+ struct hermonprm_scalar_parameter reserved;
+ struct hermonprm_mtt mtt;
+} __attribute__ (( packed ));
+
+#define HERMON_MAX_GATHER 2
+
+struct hermonprm_ud_send_wqe {
+ struct hermonprm_wqe_segment_ctrl_send ctrl;
+ struct hermonprm_wqe_segment_ud ud;
+ struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_GATHER];
+} __attribute__ (( packed ));
+
+struct hermonprm_mlx_send_wqe {
+ struct hermonprm_wqe_segment_ctrl_mlx ctrl;
+ struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_GATHER];
+ uint8_t headers[IB_MAX_HEADER_SIZE];
+} __attribute__ (( packed ));
+
+struct hermonprm_rc_send_wqe {
+ struct hermonprm_wqe_segment_ctrl_send ctrl;
+ struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_GATHER];
+} __attribute__ (( packed ));
+
+struct hermonprm_eth_send_wqe {
+ struct hermonprm_wqe_segment_ctrl_send ctrl;
+ struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_GATHER];
+} __attribute__ (( packed ));
+
+#define HERMON_MAX_SCATTER 1
+
+struct hermonprm_recv_wqe {
+ struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_SCATTER];
+} __attribute__ (( packed ));
+
+union hermonprm_completion_entry {
+ struct hermonprm_completion_queue_entry normal;
+ struct hermonprm_completion_with_error error;
+} __attribute__ (( packed ));
+
+union hermonprm_event_entry {
+ struct hermonprm_event_queue_entry generic;
+ struct hermonprm_port_state_change_event port_state_change;
+} __attribute__ (( packed ));
+
+union hermonprm_doorbell_register {
+ struct hermonprm_send_db_register send;
+ struct hermonprm_event_db_register event;
+ uint32_t dword[1];
+} __attribute__ (( packed ));
+
+union hermonprm_mad {
+ struct hermonprm_mad_ifc ifc;
+ union ib_mad mad;
+} __attribute__ (( packed ));
+
+union hermonprm_set_port {
+ struct hermonprm_set_port_ib ib;
+ struct hermonprm_set_port_general_context general;
+ struct hermonprm_set_port_rqp_calc rqp_calc;
+ struct hermonprm_set_port_mac_table mac_table[128];
+ struct hermonprm_set_port_vlan vlan;
+} __attribute__ (( packed ));
+
+/*
+ * iPXE-specific definitions
+ *
+ */
+
+/** Hermon device capabilitiess */
+struct hermon_dev_cap {
+ /** CMPT entry size */
+ size_t cmpt_entry_size;
+ /** Number of reserved QPs */
+ unsigned int reserved_qps;
+ /** QP context entry size */
+ size_t qpc_entry_size;
+ /** Alternate path context entry size */
+ size_t altc_entry_size;
+ /** Auxiliary context entry size */
+ size_t auxc_entry_size;
+ /** Number of reserved SRQs */
+ unsigned int reserved_srqs;
+ /** SRQ context entry size */
+ size_t srqc_entry_size;
+ /** Number of reserved CQs */
+ unsigned int reserved_cqs;
+ /** CQ context entry size */
+ size_t cqc_entry_size;
+ /** Number of reserved EQs */
+ unsigned int reserved_eqs;
+ /** EQ context entry size */
+ size_t eqc_entry_size;
+ /** Number of reserved MTTs */
+ unsigned int reserved_mtts;
+ /** MTT entry size */
+ size_t mtt_entry_size;
+ /** Number of reserved MRWs */
+ unsigned int reserved_mrws;
+ /** DMPT entry size */
+ size_t dmpt_entry_size;
+ /** Number of reserved UARs */
+ unsigned int reserved_uars;
+ /** Number of ports */
+ unsigned int num_ports;
+ /** Dual-port different protocol */
+ int dpdp;
+};
+
+/** Number of cMPT entries of each type */
+#define HERMON_CMPT_MAX_ENTRIES ( 1 << 24 )
+
+/** Hermon ICM memory map entry */
+struct hermon_icm_map {
+ /** Offset (virtual address within ICM) */
+ uint64_t offset;
+ /** Length */
+ size_t len;
+};
+
+/** Discontiguous regions within Hermon ICM */
+enum hermon_icm_map_regions {
+ HERMON_ICM_QP_CMPT = 0,
+ HERMON_ICM_SRQ_CMPT,
+ HERMON_ICM_CQ_CMPT,
+ HERMON_ICM_EQ_CMPT,
+ HERMON_ICM_OTHER,
+ HERMON_ICM_NUM_REGIONS
+};
+
+/** UAR page for doorbell accesses
+ *
+ * Pages 0-127 are reserved for event queue doorbells only, so we use
+ * page 128.
+ */
+#define HERMON_UAR_NON_EQ_PAGE 128
+
+/** Maximum number of allocatable MTT entries
+ *
+ * This is a policy decision, not a device limit.
+ */
+#define HERMON_MAX_MTTS 64
+
+/** A Hermon MTT descriptor */
+struct hermon_mtt {
+ /** MTT offset */
+ unsigned int mtt_offset;
+ /** Number of pages */
+ unsigned int num_pages;
+ /** MTT base address */
+ unsigned int mtt_base_addr;
+ /** Offset within page */
+ unsigned int page_offset;
+};
+
+/** Alignment of Hermon send work queue entries */
+#define HERMON_SEND_WQE_ALIGN 128
+
+/** A Hermon send work queue entry */
+union hermon_send_wqe {
+ struct hermonprm_wqe_segment_ctrl_send ctrl;
+ struct hermonprm_ud_send_wqe ud;
+ struct hermonprm_mlx_send_wqe mlx;
+ struct hermonprm_rc_send_wqe rc;
+ struct hermonprm_eth_send_wqe eth;
+ uint8_t force_align[HERMON_SEND_WQE_ALIGN];
+} __attribute__ (( packed ));
+
+/** A Hermon send work queue */
+struct hermon_send_work_queue {
+ /** Number of work queue entries, including headroom
+ *
+ * Hermon requires us to leave unused space within the send
+ * WQ, so we create a send WQ with more entries than are
+ * requested in the create_qp() call.
+ */
+ unsigned int num_wqes;
+ /** Work queue entries */
+ union hermon_send_wqe *wqe;
+ /** Size of work queue */
+ size_t wqe_size;
+ /** Doorbell register */
+ void *doorbell;
+};
+
+/** Alignment of Hermon receive work queue entries */
+#define HERMON_RECV_WQE_ALIGN 16
+
+/** A Hermon receive work queue entry */
+union hermon_recv_wqe {
+ struct hermonprm_recv_wqe recv;
+ uint8_t force_align[HERMON_RECV_WQE_ALIGN];
+} __attribute__ (( packed ));
+
+/** A Hermon receive work queue */
+struct hermon_recv_work_queue {
+ /** Work queue entries */
+ union hermon_recv_wqe *wqe;
+ /** Size of work queue */
+ size_t wqe_size;
+ /** Doorbell record */
+ struct hermonprm_qp_db_record *doorbell;
+};
+
+/** Number of special queue pairs */
+#define HERMON_NUM_SPECIAL_QPS 8
+
+/** Number of queue pairs reserved for the "special QP" block
+ *
+ * The special QPs must be within a contiguous block aligned on its
+ * own size.
+ */
+#define HERMON_RSVD_SPECIAL_QPS ( ( HERMON_NUM_SPECIAL_QPS << 1 ) - 1 )
+
+/** Maximum number of allocatable queue pairs
+ *
+ * This is a policy decision, not a device limit.
+ */
+#define HERMON_MAX_QPS 8
+
+/** Queue pair number randomisation mask */
+#define HERMON_QPN_RANDOM_MASK 0xfff000
+
+/** Hermon queue pair state */
+enum hermon_queue_pair_state {
+ HERMON_QP_ST_RST = 0,
+ HERMON_QP_ST_INIT,
+ HERMON_QP_ST_RTR,
+ HERMON_QP_ST_RTS,
+};
+
+/** A Hermon queue pair */
+struct hermon_queue_pair {
+ /** Work queue buffer */
+ void *wqe;
+ /** Size of work queue buffer */
+ size_t wqe_size;
+ /** MTT descriptor */
+ struct hermon_mtt mtt;
+ /** Send work queue */
+ struct hermon_send_work_queue send;
+ /** Receive work queue */
+ struct hermon_recv_work_queue recv;
+ /** Queue state */
+ enum hermon_queue_pair_state state;
+};
+
+/** Maximum number of allocatable completion queues
+ *
+ * This is a policy decision, not a device limit.
+ */
+#define HERMON_MAX_CQS 8
+
+/** A Hermon completion queue */
+struct hermon_completion_queue {
+ /** Completion queue entries */
+ union hermonprm_completion_entry *cqe;
+ /** Size of completion queue */
+ size_t cqe_size;
+ /** MTT descriptor */
+ struct hermon_mtt mtt;
+ /** Doorbell record */
+ struct hermonprm_cq_db_record *doorbell;
+};
+
+/** Maximum number of allocatable event queues
+ *
+ * This is a policy decision, not a device limit.
+ */
+#define HERMON_MAX_EQS 8
+
+/** A Hermon event queue */
+struct hermon_event_queue {
+ /** Event queue entries */
+ union hermonprm_event_entry *eqe;
+ /** Size of event queue */
+ size_t eqe_size;
+ /** MTT descriptor */
+ struct hermon_mtt mtt;
+ /** Event queue number */
+ unsigned long eqn;
+ /** Next event queue entry index */
+ unsigned long next_idx;
+ /** Doorbell register */
+ void *doorbell;
+};
+
+/** Number of event queue entries
+ *
+ * This is a policy decision.
+ */
+#define HERMON_NUM_EQES 8
+
+/** A Hermon resource bitmask */
+typedef uint32_t hermon_bitmask_t;
+
+/** Size of a hermon resource bitmask */
+#define HERMON_BITMASK_SIZE(max_entries) \
+ ( ( (max_entries) + ( 8 * sizeof ( hermon_bitmask_t ) ) - 1 ) / \
+ ( 8 * sizeof ( hermon_bitmask_t ) ) )
+
+struct hermon;
+struct hermon_port;
+
+/** A Hermon port type */
+struct hermon_port_type {
+ /** Register port
+ *
+ * @v hermon Hermon device
+ * @v port Hermon port
+ * @ret rc Return status code
+ */
+ int ( * register_dev ) ( struct hermon *hermon,
+ struct hermon_port *port );
+ /** Port state changed
+ *
+ * @v hermon Hermon device
+ * @v port Hermon port
+ * @v link_up Link is up
+ */
+ void ( * state_change ) ( struct hermon *hermon,
+ struct hermon_port *port,
+ int link_up );
+ /** Unregister port
+ *
+ * @v hermon Hermon device
+ * @v port Hermon port
+ */
+ void ( * unregister_dev ) ( struct hermon *hermon,
+ struct hermon_port *port );
+};
+
+/** A Hermon port */
+struct hermon_port {
+ /** Infiniband device */
+ struct ib_device *ibdev;
+ /** Network device */
+ struct net_device *netdev;
+ /** Ethernet completion queue */
+ struct ib_completion_queue *eth_cq;
+ /** Ethernet queue pair */
+ struct ib_queue_pair *eth_qp;
+ /** Port type */
+ struct hermon_port_type *type;
+};
+
+/** A Hermon device */
+struct hermon {
+ /** PCI device */
+ struct pci_device *pci;
+ /** PCI configuration registers */
+ void *config;
+ /** PCI user Access Region */
+ void *uar;
+
+ /** Command toggle */
+ unsigned int toggle;
+ /** Command input mailbox */
+ void *mailbox_in;
+ /** Command output mailbox */
+ void *mailbox_out;
+
+ /** Device open request counter */
+ unsigned int open_count;
+
+ /** Firmware size */
+ size_t firmware_len;
+ /** Firmware area in external memory
+ *
+ * This is allocated when first needed, and freed only on
+ * final teardown, in order to avoid memory map changes at
+ * runtime.
+ */
+ userptr_t firmware_area;
+ /** ICM map */
+ struct hermon_icm_map icm_map[HERMON_ICM_NUM_REGIONS];
+ /** ICM size */
+ size_t icm_len;
+ /** ICM AUX size */
+ size_t icm_aux_len;
+ /** ICM area
+ *
+ * This is allocated when first needed, and freed only on
+ * final teardown, in order to avoid memory map changes at
+ * runtime.
+ */
+ userptr_t icm;
+
+ /** Event queue */
+ struct hermon_event_queue eq;
+ /** Unrestricted LKey
+ *
+ * Used to get unrestricted memory access.
+ */
+ unsigned long lkey;
+
+ /** Completion queue in-use bitmask */
+ hermon_bitmask_t cq_inuse[ HERMON_BITMASK_SIZE ( HERMON_MAX_CQS ) ];
+ /** Queue pair in-use bitmask */
+ hermon_bitmask_t qp_inuse[ HERMON_BITMASK_SIZE ( HERMON_MAX_QPS ) ];
+ /** MTT entry in-use bitmask */
+ hermon_bitmask_t mtt_inuse[ HERMON_BITMASK_SIZE ( HERMON_MAX_MTTS ) ];
+
+ /** Device capabilities */
+ struct hermon_dev_cap cap;
+ /** Special QPN base */
+ unsigned long special_qpn_base;
+ /** QPN base */
+ unsigned long qpn_base;
+
+ /** Ports */
+ struct hermon_port port[HERMON_MAX_PORTS];
+
+ /** BOFM device */
+ struct bofm_device bofm;
+};
+
+/** Global protection domain */
+#define HERMON_GLOBAL_PD 0x123456
+
+/** Memory key prefix */
+#define HERMON_MKEY_PREFIX 0x77000000UL
+
+/*
+ * HCA commands
+ *
+ */
+
+#define HERMON_HCR_BASE 0x80680
+#define HERMON_HCR_REG(x) ( HERMON_HCR_BASE + 4 * (x) )
+#define HERMON_HCR_MAX_WAIT_MS 2000
+#define HERMON_MBOX_ALIGN 4096
+#define HERMON_MBOX_SIZE 1024
+
+/* HCA command is split into
+ *
+ * bits 11:0 Opcode
+ * bit 12 Input uses mailbox
+ * bit 13 Output uses mailbox
+ * bits 22:14 Input parameter length (in dwords)
+ * bits 31:23 Output parameter length (in dwords)
+ *
+ * Encoding the information in this way allows us to cut out several
+ * parameters to the hermon_command() call.
+ */
+#define HERMON_HCR_IN_MBOX 0x00001000UL
+#define HERMON_HCR_OUT_MBOX 0x00002000UL
+#define HERMON_HCR_OPCODE( _command ) ( (_command) & 0xfff )
+#define HERMON_HCR_IN_LEN( _command ) ( ( (_command) >> 12 ) & 0x7fc )
+#define HERMON_HCR_OUT_LEN( _command ) ( ( (_command) >> 21 ) & 0x7fc )
+
+/** Build HCR command from component parts */
+#define HERMON_HCR_INOUT_CMD( _opcode, _in_mbox, _in_len, \
+ _out_mbox, _out_len ) \
+ ( (_opcode) | \
+ ( (_in_mbox) ? HERMON_HCR_IN_MBOX : 0 ) | \
+ ( ( (_in_len) / 4 ) << 14 ) | \
+ ( (_out_mbox) ? HERMON_HCR_OUT_MBOX : 0 ) | \
+ ( ( (_out_len) / 4 ) << 23 ) )
+
+#define HERMON_HCR_IN_CMD( _opcode, _in_mbox, _in_len ) \
+ HERMON_HCR_INOUT_CMD ( _opcode, _in_mbox, _in_len, 0, 0 )
+
+#define HERMON_HCR_OUT_CMD( _opcode, _out_mbox, _out_len ) \
+ HERMON_HCR_INOUT_CMD ( _opcode, 0, 0, _out_mbox, _out_len )
+
+#define HERMON_HCR_VOID_CMD( _opcode ) \
+ HERMON_HCR_INOUT_CMD ( _opcode, 0, 0, 0, 0 )
+
+#endif /* _HERMON_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/linda.c b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/linda.c
new file mode 100644
index 00000000..6a6a2ec9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/linda.c
@@ -0,0 +1,2430 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+#include <ipxe/io.h>
+#include <ipxe/pci.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/i2c.h>
+#include <ipxe/bitbash.h>
+#include <ipxe/malloc.h>
+#include <ipxe/iobuf.h>
+#include "linda.h"
+
+/**
+ * @file
+ *
+ * QLogic Linda Infiniband HCA
+ *
+ */
+
+/** A Linda send work queue */
+struct linda_send_work_queue {
+ /** Send buffer usage */
+ uint8_t *send_buf;
+ /** Producer index */
+ unsigned int prod;
+ /** Consumer index */
+ unsigned int cons;
+};
+
+/** A Linda receive work queue */
+struct linda_recv_work_queue {
+ /** Receive header ring */
+ void *header;
+ /** Receive header producer offset (written by hardware) */
+ struct QIB_7220_scalar header_prod;
+ /** Receive header consumer offset */
+ unsigned int header_cons;
+ /** Offset within register space of the eager array */
+ unsigned long eager_array;
+ /** Number of entries in eager array */
+ unsigned int eager_entries;
+ /** Eager array producer index */
+ unsigned int eager_prod;
+ /** Eager array consumer index */
+ unsigned int eager_cons;
+};
+
+/** A Linda HCA */
+struct linda {
+ /** Registers */
+ void *regs;
+
+ /** In-use contexts */
+ uint8_t used_ctx[LINDA_NUM_CONTEXTS];
+ /** Send work queues */
+ struct linda_send_work_queue send_wq[LINDA_NUM_CONTEXTS];
+ /** Receive work queues */
+ struct linda_recv_work_queue recv_wq[LINDA_NUM_CONTEXTS];
+
+ /** Offset within register space of the first send buffer */
+ unsigned long send_buffer_base;
+ /** Send buffer availability (reported by hardware) */
+ struct QIB_7220_SendBufAvail *sendbufavail;
+ /** Send buffer availability (maintained by software) */
+ uint8_t send_buf[LINDA_MAX_SEND_BUFS];
+ /** Send buffer availability producer counter */
+ unsigned int send_buf_prod;
+ /** Send buffer availability consumer counter */
+ unsigned int send_buf_cons;
+ /** Number of reserved send buffers (across all QPs) */
+ unsigned int reserved_send_bufs;
+
+ /** I2C bit-bashing interface */
+ struct i2c_bit_basher i2c;
+ /** I2C serial EEPROM */
+ struct i2c_device eeprom;
+};
+
+/***************************************************************************
+ *
+ * Linda register access
+ *
+ ***************************************************************************
+ *
+ * This card requires atomic 64-bit accesses. Strange things happen
+ * if you try to use 32-bit accesses; sometimes they work, sometimes
+ * they don't, sometimes you get random data.
+ *
+ * These accessors use the "movq" MMX instruction, and so won't work
+ * on really old Pentiums (which won't have PCIe anyway, so this is
+ * something of a moot point).
+ */
+
+/**
+ * Read Linda qword register
+ *
+ * @v linda Linda device
+ * @v dwords Register buffer to read into
+ * @v offset Register offset
+ */
+static void linda_readq ( struct linda *linda, uint32_t *dwords,
+ unsigned long offset ) {
+ void *addr = ( linda->regs + offset );
+
+ __asm__ __volatile__ ( "movq (%1), %%mm0\n\t"
+ "movq %%mm0, (%0)\n\t"
+ : : "r" ( dwords ), "r" ( addr ) : "memory" );
+
+ DBGIO ( "[%08lx] => %08x%08x\n",
+ virt_to_phys ( addr ), dwords[1], dwords[0] );
+}
+#define linda_readq( _linda, _ptr, _offset ) \
+ linda_readq ( (_linda), (_ptr)->u.dwords, (_offset) )
+#define linda_readq_array8b( _linda, _ptr, _offset, _idx ) \
+ linda_readq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) )
+#define linda_readq_array64k( _linda, _ptr, _offset, _idx ) \
+ linda_readq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 65536 ) ) )
+
+/**
+ * Write Linda qword register
+ *
+ * @v linda Linda device
+ * @v dwords Register buffer to write
+ * @v offset Register offset
+ */
+static void linda_writeq ( struct linda *linda, const uint32_t *dwords,
+ unsigned long offset ) {
+ void *addr = ( linda->regs + offset );
+
+ DBGIO ( "[%08lx] <= %08x%08x\n",
+ virt_to_phys ( addr ), dwords[1], dwords[0] );
+
+ __asm__ __volatile__ ( "movq (%0), %%mm0\n\t"
+ "movq %%mm0, (%1)\n\t"
+ : : "r" ( dwords ), "r" ( addr ) : "memory" );
+}
+#define linda_writeq( _linda, _ptr, _offset ) \
+ linda_writeq ( (_linda), (_ptr)->u.dwords, (_offset) )
+#define linda_writeq_array8b( _linda, _ptr, _offset, _idx ) \
+ linda_writeq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) )
+#define linda_writeq_array64k( _linda, _ptr, _offset, _idx ) \
+ linda_writeq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 65536 ) ) )
+
+/**
+ * Write Linda dword register
+ *
+ * @v linda Linda device
+ * @v dword Value to write
+ * @v offset Register offset
+ */
+static void linda_writel ( struct linda *linda, uint32_t dword,
+ unsigned long offset ) {
+ writel ( dword, ( linda->regs + offset ) );
+}
+
+/***************************************************************************
+ *
+ * Link state management
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Textual representation of link state
+ *
+ * @v link_state Link state
+ * @ret link_text Link state text
+ */
+static const char * linda_link_state_text ( unsigned int link_state ) {
+ switch ( link_state ) {
+ case LINDA_LINK_STATE_DOWN: return "DOWN";
+ case LINDA_LINK_STATE_INIT: return "INIT";
+ case LINDA_LINK_STATE_ARM: return "ARM";
+ case LINDA_LINK_STATE_ACTIVE: return "ACTIVE";
+ case LINDA_LINK_STATE_ACT_DEFER:return "ACT_DEFER";
+ default: return "UNKNOWN";
+ }
+}
+
+/**
+ * Handle link state change
+ *
+ * @v linda Linda device
+ */
+static void linda_link_state_changed ( struct ib_device *ibdev ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+ struct QIB_7220_IBCStatus ibcstatus;
+ struct QIB_7220_EXTCtrl extctrl;
+ unsigned int link_state;
+ unsigned int link_width;
+ unsigned int link_speed;
+
+ /* Read link state */
+ linda_readq ( linda, &ibcstatus, QIB_7220_IBCStatus_offset );
+ link_state = BIT_GET ( &ibcstatus, LinkState );
+ link_width = BIT_GET ( &ibcstatus, LinkWidthActive );
+ link_speed = BIT_GET ( &ibcstatus, LinkSpeedActive );
+ DBGC ( linda, "Linda %p link state %s (%s %s)\n", linda,
+ linda_link_state_text ( link_state ),
+ ( link_speed ? "DDR" : "SDR" ), ( link_width ? "x4" : "x1" ) );
+
+ /* Set LEDs according to link state */
+ linda_readq ( linda, &extctrl, QIB_7220_EXTCtrl_offset );
+ BIT_SET ( &extctrl, LEDPriPortGreenOn,
+ ( ( link_state >= LINDA_LINK_STATE_INIT ) ? 1 : 0 ) );
+ BIT_SET ( &extctrl, LEDPriPortYellowOn,
+ ( ( link_state >= LINDA_LINK_STATE_ACTIVE ) ? 1 : 0 ) );
+ linda_writeq ( linda, &extctrl, QIB_7220_EXTCtrl_offset );
+
+ /* Notify Infiniband core of link state change */
+ ibdev->port_state = ( link_state + 1 );
+ ibdev->link_width_active =
+ ( link_width ? IB_LINK_WIDTH_4X : IB_LINK_WIDTH_1X );
+ ibdev->link_speed_active =
+ ( link_speed ? IB_LINK_SPEED_DDR : IB_LINK_SPEED_SDR );
+ ib_link_state_changed ( ibdev );
+}
+
+/**
+ * Wait for link state change to take effect
+ *
+ * @v linda Linda device
+ * @v new_link_state Expected link state
+ * @ret rc Return status code
+ */
+static int linda_link_state_check ( struct linda *linda,
+ unsigned int new_link_state ) {
+ struct QIB_7220_IBCStatus ibcstatus;
+ unsigned int link_state;
+ unsigned int i;
+
+ for ( i = 0 ; i < LINDA_LINK_STATE_MAX_WAIT_US ; i++ ) {
+ linda_readq ( linda, &ibcstatus, QIB_7220_IBCStatus_offset );
+ link_state = BIT_GET ( &ibcstatus, LinkState );
+ if ( link_state == new_link_state )
+ return 0;
+ udelay ( 1 );
+ }
+
+ DBGC ( linda, "Linda %p timed out waiting for link state %s\n",
+ linda, linda_link_state_text ( link_state ) );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Set port information
+ *
+ * @v ibdev Infiniband device
+ * @v mad Set port information MAD
+ */
+static int linda_set_port_info ( struct ib_device *ibdev, union ib_mad *mad ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+ struct ib_port_info *port_info = &mad->smp.smp_data.port_info;
+ struct QIB_7220_IBCCtrl ibcctrl;
+ unsigned int port_state;
+ unsigned int link_state;
+
+ /* Set new link state */
+ port_state = ( port_info->link_speed_supported__port_state & 0xf );
+ if ( port_state ) {
+ link_state = ( port_state - 1 );
+ DBGC ( linda, "Linda %p set link state to %s (%x)\n", linda,
+ linda_link_state_text ( link_state ), link_state );
+ linda_readq ( linda, &ibcctrl, QIB_7220_IBCCtrl_offset );
+ BIT_SET ( &ibcctrl, LinkCmd, link_state );
+ linda_writeq ( linda, &ibcctrl, QIB_7220_IBCCtrl_offset );
+
+ /* Wait for link state change to take effect. Ignore
+ * errors; the current link state will be returned via
+ * the GetResponse MAD.
+ */
+ linda_link_state_check ( linda, link_state );
+ }
+
+ /* Detect and report link state change */
+ linda_link_state_changed ( ibdev );
+
+ return 0;
+}
+
+/**
+ * Set partition key table
+ *
+ * @v ibdev Infiniband device
+ * @v mad Set partition key table MAD
+ */
+static int linda_set_pkey_table ( struct ib_device *ibdev __unused,
+ union ib_mad *mad __unused ) {
+ /* Nothing to do */
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * Context allocation
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Map context number to QPN
+ *
+ * @v ctx Context index
+ * @ret qpn Queue pair number
+ */
+static int linda_ctx_to_qpn ( unsigned int ctx ) {
+ /* This mapping is fixed by hardware */
+ return ( ctx * 2 );
+}
+
+/**
+ * Map QPN to context number
+ *
+ * @v qpn Queue pair number
+ * @ret ctx Context index
+ */
+static int linda_qpn_to_ctx ( unsigned int qpn ) {
+ /* This mapping is fixed by hardware */
+ return ( qpn / 2 );
+}
+
+/**
+ * Allocate a context
+ *
+ * @v linda Linda device
+ * @ret ctx Context index, or negative error
+ */
+static int linda_alloc_ctx ( struct linda *linda ) {
+ unsigned int ctx;
+
+ for ( ctx = 0 ; ctx < LINDA_NUM_CONTEXTS ; ctx++ ) {
+
+ if ( ! linda->used_ctx[ctx] ) {
+ linda->used_ctx[ctx ] = 1;
+ DBGC2 ( linda, "Linda %p CTX %d allocated\n",
+ linda, ctx );
+ return ctx;
+ }
+ }
+
+ DBGC ( linda, "Linda %p out of available contexts\n", linda );
+ return -ENOENT;
+}
+
+/**
+ * Free a context
+ *
+ * @v linda Linda device
+ * @v ctx Context index
+ */
+static void linda_free_ctx ( struct linda *linda, unsigned int ctx ) {
+
+ linda->used_ctx[ctx] = 0;
+ DBGC2 ( linda, "Linda %p CTX %d freed\n", linda, ctx );
+}
+
+/***************************************************************************
+ *
+ * Send datapath
+ *
+ ***************************************************************************
+ */
+
+/** Send buffer toggle bit
+ *
+ * We encode send buffers as 7 bits of send buffer index plus a single
+ * bit which should match the "check" bit in the SendBufAvail array.
+ */
+#define LINDA_SEND_BUF_TOGGLE 0x80
+
+/**
+ * Allocate a send buffer
+ *
+ * @v linda Linda device
+ * @ret send_buf Send buffer
+ *
+ * You must guarantee that a send buffer is available. This is done
+ * by refusing to allocate more TX WQEs in total than the number of
+ * available send buffers.
+ */
+static unsigned int linda_alloc_send_buf ( struct linda *linda ) {
+ unsigned int send_buf;
+
+ send_buf = linda->send_buf[linda->send_buf_cons];
+ send_buf ^= LINDA_SEND_BUF_TOGGLE;
+ linda->send_buf_cons = ( ( linda->send_buf_cons + 1 ) %
+ LINDA_MAX_SEND_BUFS );
+ return send_buf;
+}
+
+/**
+ * Free a send buffer
+ *
+ * @v linda Linda device
+ * @v send_buf Send buffer
+ */
+static void linda_free_send_buf ( struct linda *linda,
+ unsigned int send_buf ) {
+ linda->send_buf[linda->send_buf_prod] = send_buf;
+ linda->send_buf_prod = ( ( linda->send_buf_prod + 1 ) %
+ LINDA_MAX_SEND_BUFS );
+}
+
+/**
+ * Check to see if send buffer is in use
+ *
+ * @v linda Linda device
+ * @v send_buf Send buffer
+ * @ret in_use Send buffer is in use
+ */
+static int linda_send_buf_in_use ( struct linda *linda,
+ unsigned int send_buf ) {
+ unsigned int send_idx;
+ unsigned int send_check;
+ unsigned int inusecheck;
+ unsigned int inuse;
+ unsigned int check;
+
+ send_idx = ( send_buf & ~LINDA_SEND_BUF_TOGGLE );
+ send_check = ( !! ( send_buf & LINDA_SEND_BUF_TOGGLE ) );
+ inusecheck = BIT_GET ( linda->sendbufavail, InUseCheck[send_idx] );
+ inuse = ( !! ( inusecheck & 0x02 ) );
+ check = ( !! ( inusecheck & 0x01 ) );
+ return ( inuse || ( check != send_check ) );
+}
+
+/**
+ * Calculate starting offset for send buffer
+ *
+ * @v linda Linda device
+ * @v send_buf Send buffer
+ * @ret offset Starting offset
+ */
+static unsigned long linda_send_buffer_offset ( struct linda *linda,
+ unsigned int send_buf ) {
+ return ( linda->send_buffer_base +
+ ( ( send_buf & ~LINDA_SEND_BUF_TOGGLE ) *
+ LINDA_SEND_BUF_SIZE ) );
+}
+
+/**
+ * Create send work queue
+ *
+ * @v linda Linda device
+ * @v qp Queue pair
+ */
+static int linda_create_send_wq ( struct linda *linda,
+ struct ib_queue_pair *qp ) {
+ struct ib_work_queue *wq = &qp->send;
+ struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
+ int rc;
+
+ /* Reserve send buffers */
+ if ( ( linda->reserved_send_bufs + qp->send.num_wqes ) >
+ LINDA_MAX_SEND_BUFS ) {
+ DBGC ( linda, "Linda %p out of send buffers (have %d, used "
+ "%d, need %d)\n", linda, LINDA_MAX_SEND_BUFS,
+ linda->reserved_send_bufs, qp->send.num_wqes );
+ rc = -ENOBUFS;
+ goto err_reserve_bufs;
+ }
+ linda->reserved_send_bufs += qp->send.num_wqes;
+
+ /* Reset work queue */
+ linda_wq->prod = 0;
+ linda_wq->cons = 0;
+
+ /* Allocate space for send buffer uasge list */
+ linda_wq->send_buf = zalloc ( qp->send.num_wqes *
+ sizeof ( linda_wq->send_buf[0] ) );
+ if ( ! linda_wq->send_buf ) {
+ rc = -ENOBUFS;
+ goto err_alloc_send_buf;
+ }
+
+ return 0;
+
+ free ( linda_wq->send_buf );
+ err_alloc_send_buf:
+ linda->reserved_send_bufs -= qp->send.num_wqes;
+ err_reserve_bufs:
+ return rc;
+}
+
+/**
+ * Destroy send work queue
+ *
+ * @v linda Linda device
+ * @v qp Queue pair
+ */
+static void linda_destroy_send_wq ( struct linda *linda,
+ struct ib_queue_pair *qp ) {
+ struct ib_work_queue *wq = &qp->send;
+ struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
+
+ free ( linda_wq->send_buf );
+ linda->reserved_send_bufs -= qp->send.num_wqes;
+}
+
+/**
+ * Initialise send datapath
+ *
+ * @v linda Linda device
+ * @ret rc Return status code
+ */
+static int linda_init_send ( struct linda *linda ) {
+ struct QIB_7220_SendBufBase sendbufbase;
+ struct QIB_7220_SendBufAvailAddr sendbufavailaddr;
+ struct QIB_7220_SendCtrl sendctrl;
+ unsigned int i;
+ int rc;
+
+ /* Retrieve SendBufBase */
+ linda_readq ( linda, &sendbufbase, QIB_7220_SendBufBase_offset );
+ linda->send_buffer_base = BIT_GET ( &sendbufbase,
+ BaseAddr_SmallPIO );
+ DBGC ( linda, "Linda %p send buffers at %lx\n",
+ linda, linda->send_buffer_base );
+
+ /* Initialise the send_buf[] array */
+ for ( i = 0 ; i < LINDA_MAX_SEND_BUFS ; i++ )
+ linda->send_buf[i] = i;
+
+ /* Allocate space for the SendBufAvail array */
+ linda->sendbufavail = malloc_dma ( sizeof ( *linda->sendbufavail ),
+ LINDA_SENDBUFAVAIL_ALIGN );
+ if ( ! linda->sendbufavail ) {
+ rc = -ENOMEM;
+ goto err_alloc_sendbufavail;
+ }
+ memset ( linda->sendbufavail, 0, sizeof ( linda->sendbufavail ) );
+
+ /* Program SendBufAvailAddr into the hardware */
+ memset ( &sendbufavailaddr, 0, sizeof ( sendbufavailaddr ) );
+ BIT_FILL_1 ( &sendbufavailaddr, SendBufAvailAddr,
+ ( virt_to_bus ( linda->sendbufavail ) >> 6 ) );
+ linda_writeq ( linda, &sendbufavailaddr,
+ QIB_7220_SendBufAvailAddr_offset );
+
+ /* Enable sending and DMA of SendBufAvail */
+ memset ( &sendctrl, 0, sizeof ( sendctrl ) );
+ BIT_FILL_2 ( &sendctrl,
+ SendBufAvailUpd, 1,
+ SPioEnable, 1 );
+ linda_writeq ( linda, &sendctrl, QIB_7220_SendCtrl_offset );
+
+ return 0;
+
+ free_dma ( linda->sendbufavail, sizeof ( *linda->sendbufavail ) );
+ err_alloc_sendbufavail:
+ return rc;
+}
+
+/**
+ * Shut down send datapath
+ *
+ * @v linda Linda device
+ */
+static void linda_fini_send ( struct linda *linda ) {
+ struct QIB_7220_SendCtrl sendctrl;
+
+ /* Disable sending and DMA of SendBufAvail */
+ memset ( &sendctrl, 0, sizeof ( sendctrl ) );
+ linda_writeq ( linda, &sendctrl, QIB_7220_SendCtrl_offset );
+ mb();
+
+ /* Ensure hardware has seen this disable */
+ linda_readq ( linda, &sendctrl, QIB_7220_SendCtrl_offset );
+
+ free_dma ( linda->sendbufavail, sizeof ( *linda->sendbufavail ) );
+}
+
+/***************************************************************************
+ *
+ * Receive datapath
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Create receive work queue
+ *
+ * @v linda Linda device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static int linda_create_recv_wq ( struct linda *linda,
+ struct ib_queue_pair *qp ) {
+ struct ib_work_queue *wq = &qp->recv;
+ struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
+ struct QIB_7220_RcvHdrAddr0 rcvhdraddr;
+ struct QIB_7220_RcvHdrTailAddr0 rcvhdrtailaddr;
+ struct QIB_7220_RcvHdrHead0 rcvhdrhead;
+ struct QIB_7220_scalar rcvegrindexhead;
+ struct QIB_7220_RcvCtrl rcvctrl;
+ unsigned int ctx = linda_qpn_to_ctx ( qp->qpn );
+ int rc;
+
+ /* Reset context information */
+ memset ( &linda_wq->header_prod, 0,
+ sizeof ( linda_wq->header_prod ) );
+ linda_wq->header_cons = 0;
+ linda_wq->eager_prod = 0;
+ linda_wq->eager_cons = 0;
+
+ /* Allocate receive header buffer */
+ linda_wq->header = malloc_dma ( LINDA_RECV_HEADERS_SIZE,
+ LINDA_RECV_HEADERS_ALIGN );
+ if ( ! linda_wq->header ) {
+ rc = -ENOMEM;
+ goto err_alloc_header;
+ }
+
+ /* Enable context in hardware */
+ memset ( &rcvhdraddr, 0, sizeof ( rcvhdraddr ) );
+ BIT_FILL_1 ( &rcvhdraddr, RcvHdrAddr0,
+ ( virt_to_bus ( linda_wq->header ) >> 2 ) );
+ linda_writeq_array8b ( linda, &rcvhdraddr,
+ QIB_7220_RcvHdrAddr0_offset, ctx );
+ memset ( &rcvhdrtailaddr, 0, sizeof ( rcvhdrtailaddr ) );
+ BIT_FILL_1 ( &rcvhdrtailaddr, RcvHdrTailAddr0,
+ ( virt_to_bus ( &linda_wq->header_prod ) >> 2 ) );
+ linda_writeq_array8b ( linda, &rcvhdrtailaddr,
+ QIB_7220_RcvHdrTailAddr0_offset, ctx );
+ memset ( &rcvhdrhead, 0, sizeof ( rcvhdrhead ) );
+ BIT_FILL_1 ( &rcvhdrhead, counter, 1 );
+ linda_writeq_array64k ( linda, &rcvhdrhead,
+ QIB_7220_RcvHdrHead0_offset, ctx );
+ memset ( &rcvegrindexhead, 0, sizeof ( rcvegrindexhead ) );
+ BIT_FILL_1 ( &rcvegrindexhead, Value, 1 );
+ linda_writeq_array64k ( linda, &rcvegrindexhead,
+ QIB_7220_RcvEgrIndexHead0_offset, ctx );
+ linda_readq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset );
+ BIT_SET ( &rcvctrl, PortEnable[ctx], 1 );
+ BIT_SET ( &rcvctrl, IntrAvail[ctx], 1 );
+ linda_writeq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset );
+
+ DBGC ( linda, "Linda %p QPN %ld CTX %d hdrs [%lx,%lx) prod %lx\n",
+ linda, qp->qpn, ctx, virt_to_bus ( linda_wq->header ),
+ ( virt_to_bus ( linda_wq->header ) + LINDA_RECV_HEADERS_SIZE ),
+ virt_to_bus ( &linda_wq->header_prod ) );
+ return 0;
+
+ free_dma ( linda_wq->header, LINDA_RECV_HEADERS_SIZE );
+ err_alloc_header:
+ return rc;
+}
+
+/**
+ * Destroy receive work queue
+ *
+ * @v linda Linda device
+ * @v qp Queue pair
+ */
+static void linda_destroy_recv_wq ( struct linda *linda,
+ struct ib_queue_pair *qp ) {
+ struct ib_work_queue *wq = &qp->recv;
+ struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
+ struct QIB_7220_RcvCtrl rcvctrl;
+ unsigned int ctx = linda_qpn_to_ctx ( qp->qpn );
+
+ /* Disable context in hardware */
+ linda_readq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset );
+ BIT_SET ( &rcvctrl, PortEnable[ctx], 0 );
+ BIT_SET ( &rcvctrl, IntrAvail[ctx], 0 );
+ linda_writeq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset );
+
+ /* Make sure the hardware has seen that the context is disabled */
+ linda_readq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset );
+ mb();
+
+ /* Free headers ring */
+ free_dma ( linda_wq->header, LINDA_RECV_HEADERS_SIZE );
+
+ /* Free context */
+ linda_free_ctx ( linda, ctx );
+}
+
+/**
+ * Initialise receive datapath
+ *
+ * @v linda Linda device
+ * @ret rc Return status code
+ */
+static int linda_init_recv ( struct linda *linda ) {
+ struct QIB_7220_RcvCtrl rcvctrl;
+ struct QIB_7220_scalar rcvegrbase;
+ struct QIB_7220_scalar rcvhdrentsize;
+ struct QIB_7220_scalar rcvhdrcnt;
+ struct QIB_7220_RcvBTHQP rcvbthqp;
+ unsigned int portcfg;
+ unsigned long egrbase;
+ unsigned int eager_array_size_0;
+ unsigned int eager_array_size_other;
+ unsigned int ctx;
+
+ /* Select configuration based on number of contexts */
+ switch ( LINDA_NUM_CONTEXTS ) {
+ case 5:
+ portcfg = LINDA_PORTCFG_5CTX;
+ eager_array_size_0 = LINDA_EAGER_ARRAY_SIZE_5CTX_0;
+ eager_array_size_other = LINDA_EAGER_ARRAY_SIZE_5CTX_OTHER;
+ break;
+ case 9:
+ portcfg = LINDA_PORTCFG_9CTX;
+ eager_array_size_0 = LINDA_EAGER_ARRAY_SIZE_9CTX_0;
+ eager_array_size_other = LINDA_EAGER_ARRAY_SIZE_9CTX_OTHER;
+ break;
+ case 17:
+ portcfg = LINDA_PORTCFG_17CTX;
+ eager_array_size_0 = LINDA_EAGER_ARRAY_SIZE_17CTX_0;
+ eager_array_size_other = LINDA_EAGER_ARRAY_SIZE_17CTX_OTHER;
+ break;
+ default:
+ linker_assert ( 0, invalid_LINDA_NUM_CONTEXTS );
+ return -EINVAL;
+ }
+
+ /* Configure number of contexts */
+ memset ( &rcvctrl, 0, sizeof ( rcvctrl ) );
+ BIT_FILL_3 ( &rcvctrl,
+ TailUpd, 1,
+ PortCfg, portcfg,
+ RcvQPMapEnable, 1 );
+ linda_writeq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset );
+
+ /* Configure receive header buffer sizes */
+ memset ( &rcvhdrcnt, 0, sizeof ( rcvhdrcnt ) );
+ BIT_FILL_1 ( &rcvhdrcnt, Value, LINDA_RECV_HEADER_COUNT );
+ linda_writeq ( linda, &rcvhdrcnt, QIB_7220_RcvHdrCnt_offset );
+ memset ( &rcvhdrentsize, 0, sizeof ( rcvhdrentsize ) );
+ BIT_FILL_1 ( &rcvhdrentsize, Value, ( LINDA_RECV_HEADER_SIZE >> 2 ) );
+ linda_writeq ( linda, &rcvhdrentsize, QIB_7220_RcvHdrEntSize_offset );
+
+ /* Calculate eager array start addresses for each context */
+ linda_readq ( linda, &rcvegrbase, QIB_7220_RcvEgrBase_offset );
+ egrbase = BIT_GET ( &rcvegrbase, Value );
+ linda->recv_wq[0].eager_array = egrbase;
+ linda->recv_wq[0].eager_entries = eager_array_size_0;
+ egrbase += ( eager_array_size_0 * sizeof ( struct QIB_7220_RcvEgr ) );
+ for ( ctx = 1 ; ctx < LINDA_NUM_CONTEXTS ; ctx++ ) {
+ linda->recv_wq[ctx].eager_array = egrbase;
+ linda->recv_wq[ctx].eager_entries = eager_array_size_other;
+ egrbase += ( eager_array_size_other *
+ sizeof ( struct QIB_7220_RcvEgr ) );
+ }
+ for ( ctx = 0 ; ctx < LINDA_NUM_CONTEXTS ; ctx++ ) {
+ DBGC ( linda, "Linda %p CTX %d eager array at %lx (%d "
+ "entries)\n", linda, ctx,
+ linda->recv_wq[ctx].eager_array,
+ linda->recv_wq[ctx].eager_entries );
+ }
+
+ /* Set the BTH QP for Infinipath packets to an unused value */
+ memset ( &rcvbthqp, 0, sizeof ( rcvbthqp ) );
+ BIT_FILL_1 ( &rcvbthqp, RcvBTHQP, LINDA_QP_IDETH );
+ linda_writeq ( linda, &rcvbthqp, QIB_7220_RcvBTHQP_offset );
+
+ return 0;
+}
+
+/**
+ * Shut down receive datapath
+ *
+ * @v linda Linda device
+ */
+static void linda_fini_recv ( struct linda *linda __unused ) {
+ /* Nothing to do; all contexts were already disabled when the
+ * queue pairs were destroyed
+ */
+}
+
+/***************************************************************************
+ *
+ * Completion queue operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Create completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ * @ret rc Return status code
+ */
+static int linda_create_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+ static int cqn;
+
+ /* The hardware has no concept of completion queues. We
+ * simply use the association between CQs and WQs (already
+ * handled by the IB core) to decide which WQs to poll.
+ *
+ * We do set a CQN, just to avoid confusing debug messages
+ * from the IB core.
+ */
+ cq->cqn = ++cqn;
+ DBGC ( linda, "Linda %p CQN %ld created\n", linda, cq->cqn );
+
+ return 0;
+}
+
+/**
+ * Destroy completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+static void linda_destroy_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+
+ /* Nothing to do */
+ DBGC ( linda, "Linda %p CQN %ld destroyed\n", linda, cq->cqn );
+}
+
+/***************************************************************************
+ *
+ * Queue pair operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Create queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static int linda_create_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+ int ctx;
+ int rc;
+
+ /* Locate an available context */
+ ctx = linda_alloc_ctx ( linda );
+ if ( ctx < 0 ) {
+ rc = ctx;
+ goto err_alloc_ctx;
+ }
+
+ /* Set queue pair number based on context index */
+ qp->qpn = linda_ctx_to_qpn ( ctx );
+
+ /* Set work-queue private data pointers */
+ ib_wq_set_drvdata ( &qp->send, &linda->send_wq[ctx] );
+ ib_wq_set_drvdata ( &qp->recv, &linda->recv_wq[ctx] );
+
+ /* Create receive work queue */
+ if ( ( rc = linda_create_recv_wq ( linda, qp ) ) != 0 )
+ goto err_create_recv_wq;
+
+ /* Create send work queue */
+ if ( ( rc = linda_create_send_wq ( linda, qp ) ) != 0 )
+ goto err_create_send_wq;
+
+ return 0;
+
+ linda_destroy_send_wq ( linda, qp );
+ err_create_send_wq:
+ linda_destroy_recv_wq ( linda, qp );
+ err_create_recv_wq:
+ linda_free_ctx ( linda, ctx );
+ err_alloc_ctx:
+ return rc;
+}
+
+/**
+ * Modify queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static int linda_modify_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+
+ /* Nothing to do; the hardware doesn't have a notion of queue
+ * keys
+ */
+ DBGC ( linda, "Linda %p QPN %ld modified\n", linda, qp->qpn );
+ return 0;
+}
+
+/**
+ * Destroy queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+static void linda_destroy_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+
+ linda_destroy_send_wq ( linda, qp );
+ linda_destroy_recv_wq ( linda, qp );
+}
+
+/***************************************************************************
+ *
+ * Work request operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Post send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int linda_post_send ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->send;
+ struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
+ struct QIB_7220_SendPbc sendpbc;
+ uint8_t header_buf[IB_MAX_HEADER_SIZE];
+ struct io_buffer headers;
+ unsigned int send_buf;
+ unsigned long start_offset;
+ unsigned long offset;
+ size_t len;
+ ssize_t frag_len;
+ uint32_t *data;
+
+ /* Allocate send buffer and calculate offset */
+ send_buf = linda_alloc_send_buf ( linda );
+ start_offset = offset = linda_send_buffer_offset ( linda, send_buf );
+
+ /* Store I/O buffer and send buffer index */
+ assert ( wq->iobufs[linda_wq->prod] == NULL );
+ wq->iobufs[linda_wq->prod] = iobuf;
+ linda_wq->send_buf[linda_wq->prod] = send_buf;
+
+ /* Construct headers */
+ iob_populate ( &headers, header_buf, 0, sizeof ( header_buf ) );
+ iob_reserve ( &headers, sizeof ( header_buf ) );
+ ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), av );
+
+ /* Calculate packet length */
+ len = ( ( sizeof ( sendpbc ) + iob_len ( &headers ) +
+ iob_len ( iobuf ) + 3 ) & ~3 );
+
+ /* Construct send per-buffer control word */
+ memset ( &sendpbc, 0, sizeof ( sendpbc ) );
+ BIT_FILL_2 ( &sendpbc,
+ LengthP1_toibc, ( ( len >> 2 ) - 1 ),
+ VL15, 1 );
+
+ /* Write SendPbc */
+ DBG_DISABLE ( DBGLVL_IO );
+ linda_writeq ( linda, &sendpbc, offset );
+ offset += sizeof ( sendpbc );
+
+ /* Write headers */
+ for ( data = headers.data, frag_len = iob_len ( &headers ) ;
+ frag_len > 0 ; data++, offset += 4, frag_len -= 4 ) {
+ linda_writel ( linda, *data, offset );
+ }
+
+ /* Write data */
+ for ( data = iobuf->data, frag_len = iob_len ( iobuf ) ;
+ frag_len > 0 ; data++, offset += 4, frag_len -= 4 ) {
+ linda_writel ( linda, *data, offset );
+ }
+ DBG_ENABLE ( DBGLVL_IO );
+
+ assert ( ( start_offset + len ) == offset );
+ DBGC2 ( linda, "Linda %p QPN %ld TX %d(%d) posted [%lx,%lx)\n",
+ linda, qp->qpn, send_buf, linda_wq->prod,
+ start_offset, offset );
+
+ /* Increment producer counter */
+ linda_wq->prod = ( ( linda_wq->prod + 1 ) & ( wq->num_wqes - 1 ) );
+
+ return 0;
+}
+
+/**
+ * Complete send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v wqe_idx Work queue entry index
+ */
+static void linda_complete_send ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ unsigned int wqe_idx ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->send;
+ struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
+ struct io_buffer *iobuf;
+ unsigned int send_buf;
+
+ /* Parse completion */
+ send_buf = linda_wq->send_buf[wqe_idx];
+ DBGC2 ( linda, "Linda %p QPN %ld TX %d(%d) complete\n",
+ linda, qp->qpn, send_buf, wqe_idx );
+
+ /* Complete work queue entry */
+ iobuf = wq->iobufs[wqe_idx];
+ assert ( iobuf != NULL );
+ ib_complete_send ( ibdev, qp, iobuf, 0 );
+ wq->iobufs[wqe_idx] = NULL;
+
+ /* Free send buffer */
+ linda_free_send_buf ( linda, send_buf );
+}
+
+/**
+ * Poll send work queue
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+static void linda_poll_send_wq ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->send;
+ struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
+ unsigned int send_buf;
+
+ /* Look for completions */
+ while ( wq->fill ) {
+
+ /* Check to see if send buffer has completed */
+ send_buf = linda_wq->send_buf[linda_wq->cons];
+ if ( linda_send_buf_in_use ( linda, send_buf ) )
+ break;
+
+ /* Complete this buffer */
+ linda_complete_send ( ibdev, qp, linda_wq->cons );
+
+ /* Increment consumer counter */
+ linda_wq->cons = ( ( linda_wq->cons + 1 ) &
+ ( wq->num_wqes - 1 ) );
+ }
+}
+
+/**
+ * Post receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int linda_post_recv ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->recv;
+ struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
+ struct QIB_7220_RcvEgr rcvegr;
+ struct QIB_7220_scalar rcvegrindexhead;
+ unsigned int ctx = linda_qpn_to_ctx ( qp->qpn );
+ physaddr_t addr;
+ size_t len;
+ unsigned int wqe_idx;
+ unsigned int bufsize;
+
+ /* Sanity checks */
+ addr = virt_to_bus ( iobuf->data );
+ len = iob_tailroom ( iobuf );
+ if ( addr & ( LINDA_EAGER_BUFFER_ALIGN - 1 ) ) {
+ DBGC ( linda, "Linda %p QPN %ld misaligned RX buffer "
+ "(%08lx)\n", linda, qp->qpn, addr );
+ return -EINVAL;
+ }
+ if ( len != LINDA_RECV_PAYLOAD_SIZE ) {
+ DBGC ( linda, "Linda %p QPN %ld wrong RX buffer size (%zd)\n",
+ linda, qp->qpn, len );
+ return -EINVAL;
+ }
+
+ /* Calculate eager producer index and WQE index */
+ wqe_idx = ( linda_wq->eager_prod & ( wq->num_wqes - 1 ) );
+ assert ( wq->iobufs[wqe_idx] == NULL );
+
+ /* Store I/O buffer */
+ wq->iobufs[wqe_idx] = iobuf;
+
+ /* Calculate buffer size */
+ switch ( LINDA_RECV_PAYLOAD_SIZE ) {
+ case 2048: bufsize = LINDA_EAGER_BUFFER_2K; break;
+ case 4096: bufsize = LINDA_EAGER_BUFFER_4K; break;
+ case 8192: bufsize = LINDA_EAGER_BUFFER_8K; break;
+ case 16384: bufsize = LINDA_EAGER_BUFFER_16K; break;
+ case 32768: bufsize = LINDA_EAGER_BUFFER_32K; break;
+ case 65536: bufsize = LINDA_EAGER_BUFFER_64K; break;
+ default: linker_assert ( 0, invalid_rx_payload_size );
+ bufsize = LINDA_EAGER_BUFFER_NONE;
+ }
+
+ /* Post eager buffer */
+ memset ( &rcvegr, 0, sizeof ( rcvegr ) );
+ BIT_FILL_2 ( &rcvegr,
+ Addr, ( addr >> 11 ),
+ BufSize, bufsize );
+ linda_writeq_array8b ( linda, &rcvegr,
+ linda_wq->eager_array, linda_wq->eager_prod );
+ DBGC2 ( linda, "Linda %p QPN %ld RX egr %d(%d) posted [%lx,%lx)\n",
+ linda, qp->qpn, linda_wq->eager_prod, wqe_idx,
+ addr, ( addr + len ) );
+
+ /* Increment producer index */
+ linda_wq->eager_prod = ( ( linda_wq->eager_prod + 1 ) &
+ ( linda_wq->eager_entries - 1 ) );
+
+ /* Update head index */
+ memset ( &rcvegrindexhead, 0, sizeof ( rcvegrindexhead ) );
+ BIT_FILL_1 ( &rcvegrindexhead,
+ Value, ( ( linda_wq->eager_prod + 1 ) &
+ ( linda_wq->eager_entries - 1 ) ) );
+ linda_writeq_array64k ( linda, &rcvegrindexhead,
+ QIB_7220_RcvEgrIndexHead0_offset, ctx );
+
+ return 0;
+}
+
+/**
+ * Complete receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v header_offs Header offset
+ */
+static void linda_complete_recv ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ unsigned int header_offs ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->recv;
+ struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
+ struct QIB_7220_RcvHdrFlags *rcvhdrflags;
+ struct QIB_7220_RcvEgr rcvegr;
+ struct io_buffer headers;
+ struct io_buffer *iobuf;
+ struct ib_queue_pair *intended_qp;
+ struct ib_address_vector av;
+ unsigned int rcvtype;
+ unsigned int pktlen;
+ unsigned int egrindex;
+ unsigned int useegrbfr;
+ unsigned int iberr, mkerr, tiderr, khdrerr, mtuerr;
+ unsigned int lenerr, parityerr, vcrcerr, icrcerr;
+ unsigned int err;
+ unsigned int hdrqoffset;
+ unsigned int header_len;
+ unsigned int padded_payload_len;
+ unsigned int wqe_idx;
+ size_t payload_len;
+ int qp0;
+ int rc;
+
+ /* RcvHdrFlags are at the end of the header entry */
+ rcvhdrflags = ( linda_wq->header + header_offs +
+ LINDA_RECV_HEADER_SIZE - sizeof ( *rcvhdrflags ) );
+ rcvtype = BIT_GET ( rcvhdrflags, RcvType );
+ pktlen = ( BIT_GET ( rcvhdrflags, PktLen ) << 2 );
+ egrindex = BIT_GET ( rcvhdrflags, EgrIndex );
+ useegrbfr = BIT_GET ( rcvhdrflags, UseEgrBfr );
+ hdrqoffset = ( BIT_GET ( rcvhdrflags, HdrqOffset ) << 2 );
+ iberr = BIT_GET ( rcvhdrflags, IBErr );
+ mkerr = BIT_GET ( rcvhdrflags, MKErr );
+ tiderr = BIT_GET ( rcvhdrflags, TIDErr );
+ khdrerr = BIT_GET ( rcvhdrflags, KHdrErr );
+ mtuerr = BIT_GET ( rcvhdrflags, MTUErr );
+ lenerr = BIT_GET ( rcvhdrflags, LenErr );
+ parityerr = BIT_GET ( rcvhdrflags, ParityErr );
+ vcrcerr = BIT_GET ( rcvhdrflags, VCRCErr );
+ icrcerr = BIT_GET ( rcvhdrflags, ICRCErr );
+ header_len = ( LINDA_RECV_HEADER_SIZE - hdrqoffset -
+ sizeof ( *rcvhdrflags ) );
+ padded_payload_len = ( pktlen - header_len - 4 /* ICRC */ );
+ err = ( iberr | mkerr | tiderr | khdrerr | mtuerr |
+ lenerr | parityerr | vcrcerr | icrcerr );
+ /* IB header is placed immediately before RcvHdrFlags */
+ iob_populate ( &headers, ( ( ( void * ) rcvhdrflags ) - header_len ),
+ header_len, header_len );
+
+ /* Dump diagnostic information */
+ if ( err || ( ! useegrbfr ) ) {
+ DBGC ( linda, "Linda %p QPN %ld RX egr %d%s hdr %d type %d "
+ "len %d(%d+%d+4)%s%s%s%s%s%s%s%s%s%s%s\n", linda,
+ qp->qpn, egrindex, ( useegrbfr ? "" : "(unused)" ),
+ ( header_offs / LINDA_RECV_HEADER_SIZE ), rcvtype,
+ pktlen, header_len, padded_payload_len,
+ ( err ? " [Err" : "" ), ( iberr ? " IB" : "" ),
+ ( mkerr ? " MK" : "" ), ( tiderr ? " TID" : "" ),
+ ( khdrerr ? " KHdr" : "" ), ( mtuerr ? " MTU" : "" ),
+ ( lenerr ? " Len" : "" ), ( parityerr ? " Parity" : ""),
+ ( vcrcerr ? " VCRC" : "" ), ( icrcerr ? " ICRC" : "" ),
+ ( err ? "]" : "" ) );
+ } else {
+ DBGC2 ( linda, "Linda %p QPN %ld RX egr %d hdr %d type %d "
+ "len %d(%d+%d+4)\n", linda, qp->qpn, egrindex,
+ ( header_offs / LINDA_RECV_HEADER_SIZE ), rcvtype,
+ pktlen, header_len, padded_payload_len );
+ }
+ DBGCP_HDA ( linda, hdrqoffset, headers.data,
+ ( header_len + sizeof ( *rcvhdrflags ) ) );
+
+ /* Parse header to generate address vector */
+ qp0 = ( qp->qpn == 0 );
+ intended_qp = NULL;
+ if ( ( rc = ib_pull ( ibdev, &headers, ( qp0 ? &intended_qp : NULL ),
+ &payload_len, &av ) ) != 0 ) {
+ DBGC ( linda, "Linda %p could not parse headers: %s\n",
+ linda, strerror ( rc ) );
+ err = 1;
+ }
+ if ( ! intended_qp )
+ intended_qp = qp;
+
+ /* Complete this buffer and any skipped buffers. Note that
+ * when the hardware runs out of buffers, it will repeatedly
+ * report the same buffer (the tail) as a TID error, and that
+ * it also has a habit of sometimes skipping over several
+ * buffers at once.
+ */
+ while ( 1 ) {
+
+ /* If we have caught up to the producer counter, stop.
+ * This will happen when the hardware first runs out
+ * of buffers and starts reporting TID errors against
+ * the eager buffer it wants to use next.
+ */
+ if ( linda_wq->eager_cons == linda_wq->eager_prod )
+ break;
+
+ /* If we have caught up to where we should be after
+ * completing this egrindex, stop. We phrase the test
+ * this way to avoid completing the entire ring when
+ * we receive the same egrindex twice in a row.
+ */
+ if ( ( linda_wq->eager_cons ==
+ ( ( egrindex + 1 ) & ( linda_wq->eager_entries - 1 ) )))
+ break;
+
+ /* Identify work queue entry and corresponding I/O
+ * buffer.
+ */
+ wqe_idx = ( linda_wq->eager_cons & ( wq->num_wqes - 1 ) );
+ iobuf = wq->iobufs[wqe_idx];
+ assert ( iobuf != NULL );
+ wq->iobufs[wqe_idx] = NULL;
+
+ /* Complete the eager buffer */
+ if ( linda_wq->eager_cons == egrindex ) {
+ /* Completing the eager buffer described in
+ * this header entry.
+ */
+ iob_put ( iobuf, payload_len );
+ rc = ( err ? -EIO : ( useegrbfr ? 0 : -ECANCELED ) );
+ /* Redirect to target QP if necessary */
+ if ( qp != intended_qp ) {
+ DBGC ( linda, "Linda %p redirecting QPN %ld "
+ "=> %ld\n",
+ linda, qp->qpn, intended_qp->qpn );
+ /* Compensate for incorrect fill levels */
+ qp->recv.fill--;
+ intended_qp->recv.fill++;
+ }
+ ib_complete_recv ( ibdev, intended_qp, &av, iobuf, rc);
+ } else {
+ /* Completing on a skipped-over eager buffer */
+ ib_complete_recv ( ibdev, qp, &av, iobuf, -ECANCELED );
+ }
+
+ /* Clear eager buffer */
+ memset ( &rcvegr, 0, sizeof ( rcvegr ) );
+ linda_writeq_array8b ( linda, &rcvegr, linda_wq->eager_array,
+ linda_wq->eager_cons );
+
+ /* Increment consumer index */
+ linda_wq->eager_cons = ( ( linda_wq->eager_cons + 1 ) &
+ ( linda_wq->eager_entries - 1 ) );
+ }
+}
+
+/**
+ * Poll receive work queue
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+static void linda_poll_recv_wq ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->recv;
+ struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq );
+ struct QIB_7220_RcvHdrHead0 rcvhdrhead;
+ unsigned int ctx = linda_qpn_to_ctx ( qp->qpn );
+ unsigned int header_prod;
+
+ /* Check for received packets */
+ header_prod = ( BIT_GET ( &linda_wq->header_prod, Value ) << 2 );
+ if ( header_prod == linda_wq->header_cons )
+ return;
+
+ /* Process all received packets */
+ while ( linda_wq->header_cons != header_prod ) {
+
+ /* Complete the receive */
+ linda_complete_recv ( ibdev, qp, linda_wq->header_cons );
+
+ /* Increment the consumer offset */
+ linda_wq->header_cons += LINDA_RECV_HEADER_SIZE;
+ linda_wq->header_cons %= LINDA_RECV_HEADERS_SIZE;
+ }
+
+ /* Update consumer offset */
+ memset ( &rcvhdrhead, 0, sizeof ( rcvhdrhead ) );
+ BIT_FILL_2 ( &rcvhdrhead,
+ RcvHeadPointer, ( linda_wq->header_cons >> 2 ),
+ counter, 1 );
+ linda_writeq_array64k ( linda, &rcvhdrhead,
+ QIB_7220_RcvHdrHead0_offset, ctx );
+}
+
+/**
+ * Poll completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+static void linda_poll_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct ib_work_queue *wq;
+
+ /* Poll associated send and receive queues */
+ list_for_each_entry ( wq, &cq->work_queues, list ) {
+ if ( wq->is_send ) {
+ linda_poll_send_wq ( ibdev, wq->qp );
+ } else {
+ linda_poll_recv_wq ( ibdev, wq->qp );
+ }
+ }
+}
+
+/***************************************************************************
+ *
+ * Event queues
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Poll event queue
+ *
+ * @v ibdev Infiniband device
+ */
+static void linda_poll_eq ( struct ib_device *ibdev ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+ struct QIB_7220_ErrStatus errstatus;
+ struct QIB_7220_ErrClear errclear;
+
+ /* Check for link status changes */
+ DBG_DISABLE ( DBGLVL_IO );
+ linda_readq ( linda, &errstatus, QIB_7220_ErrStatus_offset );
+ DBG_ENABLE ( DBGLVL_IO );
+ if ( BIT_GET ( &errstatus, IBStatusChanged ) ) {
+ linda_link_state_changed ( ibdev );
+ memset ( &errclear, 0, sizeof ( errclear ) );
+ BIT_FILL_1 ( &errclear, IBStatusChangedClear, 1 );
+ linda_writeq ( linda, &errclear, QIB_7220_ErrClear_offset );
+ }
+}
+
+/***************************************************************************
+ *
+ * Infiniband link-layer operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Initialise Infiniband link
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+static int linda_open ( struct ib_device *ibdev ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+ struct QIB_7220_Control control;
+
+ /* Disable link */
+ linda_readq ( linda, &control, QIB_7220_Control_offset );
+ BIT_SET ( &control, LinkEn, 1 );
+ linda_writeq ( linda, &control, QIB_7220_Control_offset );
+ return 0;
+}
+
+/**
+ * Close Infiniband link
+ *
+ * @v ibdev Infiniband device
+ */
+static void linda_close ( struct ib_device *ibdev ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+ struct QIB_7220_Control control;
+
+ /* Disable link */
+ linda_readq ( linda, &control, QIB_7220_Control_offset );
+ BIT_SET ( &control, LinkEn, 0 );
+ linda_writeq ( linda, &control, QIB_7220_Control_offset );
+}
+
+/***************************************************************************
+ *
+ * Multicast group operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Attach to multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ * @ret rc Return status code
+ */
+static int linda_mcast_attach ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ union ib_gid *gid ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+
+ ( void ) linda;
+ ( void ) qp;
+ ( void ) gid;
+ return 0;
+}
+
+/**
+ * Detach from multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ */
+static void linda_mcast_detach ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ union ib_gid *gid ) {
+ struct linda *linda = ib_get_drvdata ( ibdev );
+
+ ( void ) linda;
+ ( void ) qp;
+ ( void ) gid;
+}
+
+/** Linda Infiniband operations */
+static struct ib_device_operations linda_ib_operations = {
+ .create_cq = linda_create_cq,
+ .destroy_cq = linda_destroy_cq,
+ .create_qp = linda_create_qp,
+ .modify_qp = linda_modify_qp,
+ .destroy_qp = linda_destroy_qp,
+ .post_send = linda_post_send,
+ .post_recv = linda_post_recv,
+ .poll_cq = linda_poll_cq,
+ .poll_eq = linda_poll_eq,
+ .open = linda_open,
+ .close = linda_close,
+ .mcast_attach = linda_mcast_attach,
+ .mcast_detach = linda_mcast_detach,
+ .set_port_info = linda_set_port_info,
+ .set_pkey_table = linda_set_pkey_table,
+};
+
+/***************************************************************************
+ *
+ * I2C bus operations
+ *
+ ***************************************************************************
+ */
+
+/** Linda I2C bit to GPIO mappings */
+static unsigned int linda_i2c_bits[] = {
+ [I2C_BIT_SCL] = ( 1 << LINDA_GPIO_SCL ),
+ [I2C_BIT_SDA] = ( 1 << LINDA_GPIO_SDA ),
+};
+
+/**
+ * Read Linda I2C line status
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @ret zero Input is a logic 0
+ * @ret non-zero Input is a logic 1
+ */
+static int linda_i2c_read_bit ( struct bit_basher *basher,
+ unsigned int bit_id ) {
+ struct linda *linda =
+ container_of ( basher, struct linda, i2c.basher );
+ struct QIB_7220_EXTStatus extstatus;
+ unsigned int status;
+
+ DBG_DISABLE ( DBGLVL_IO );
+
+ linda_readq ( linda, &extstatus, QIB_7220_EXTStatus_offset );
+ status = ( BIT_GET ( &extstatus, GPIOIn ) & linda_i2c_bits[bit_id] );
+
+ DBG_ENABLE ( DBGLVL_IO );
+
+ return status;
+}
+
+/**
+ * Write Linda I2C line status
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @v data Value to write
+ */
+static void linda_i2c_write_bit ( struct bit_basher *basher,
+ unsigned int bit_id, unsigned long data ) {
+ struct linda *linda =
+ container_of ( basher, struct linda, i2c.basher );
+ struct QIB_7220_EXTCtrl extctrl;
+ struct QIB_7220_GPIO gpioout;
+ unsigned int bit = linda_i2c_bits[bit_id];
+ unsigned int outputs = 0;
+ unsigned int output_enables = 0;
+
+ DBG_DISABLE ( DBGLVL_IO );
+
+ /* Read current GPIO mask and outputs */
+ linda_readq ( linda, &extctrl, QIB_7220_EXTCtrl_offset );
+ linda_readq ( linda, &gpioout, QIB_7220_GPIOOut_offset );
+
+ /* Update outputs and output enables. I2C lines are tied
+ * high, so we always set the output to 0 and use the output
+ * enable to control the line.
+ */
+ output_enables = BIT_GET ( &extctrl, GPIOOe );
+ output_enables = ( ( output_enables & ~bit ) | ( ~data & bit ) );
+ outputs = BIT_GET ( &gpioout, GPIO );
+ outputs = ( outputs & ~bit );
+ BIT_SET ( &extctrl, GPIOOe, output_enables );
+ BIT_SET ( &gpioout, GPIO, outputs );
+
+ /* Write the output enable first; that way we avoid logic
+ * hazards.
+ */
+ linda_writeq ( linda, &extctrl, QIB_7220_EXTCtrl_offset );
+ linda_writeq ( linda, &gpioout, QIB_7220_GPIOOut_offset );
+ mb();
+
+ DBG_ENABLE ( DBGLVL_IO );
+}
+
+/** Linda I2C bit-bashing interface operations */
+static struct bit_basher_operations linda_i2c_basher_ops = {
+ .read = linda_i2c_read_bit,
+ .write = linda_i2c_write_bit,
+};
+
+/**
+ * Initialise Linda I2C subsystem
+ *
+ * @v linda Linda device
+ * @ret rc Return status code
+ */
+static int linda_init_i2c ( struct linda *linda ) {
+ static int try_eeprom_address[] = { 0x51, 0x50 };
+ unsigned int i;
+ int rc;
+
+ /* Initialise bus */
+ if ( ( rc = init_i2c_bit_basher ( &linda->i2c,
+ &linda_i2c_basher_ops ) ) != 0 ) {
+ DBGC ( linda, "Linda %p could not initialise I2C bus: %s\n",
+ linda, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Probe for devices */
+ for ( i = 0 ; i < ( sizeof ( try_eeprom_address ) /
+ sizeof ( try_eeprom_address[0] ) ) ; i++ ) {
+ init_i2c_eeprom ( &linda->eeprom, try_eeprom_address[i] );
+ if ( ( rc = i2c_check_presence ( &linda->i2c.i2c,
+ &linda->eeprom ) ) == 0 ) {
+ DBGC2 ( linda, "Linda %p found EEPROM at %02x\n",
+ linda, try_eeprom_address[i] );
+ return 0;
+ }
+ }
+
+ DBGC ( linda, "Linda %p could not find EEPROM\n", linda );
+ return -ENODEV;
+}
+
+/**
+ * Read EEPROM parameters
+ *
+ * @v linda Linda device
+ * @v guid GUID to fill in
+ * @ret rc Return status code
+ */
+static int linda_read_eeprom ( struct linda *linda, union ib_guid *guid ) {
+ struct i2c_interface *i2c = &linda->i2c.i2c;
+ int rc;
+
+ /* Read GUID */
+ if ( ( rc = i2c->read ( i2c, &linda->eeprom, LINDA_EEPROM_GUID_OFFSET,
+ guid->bytes, sizeof ( *guid ) ) ) != 0 ) {
+ DBGC ( linda, "Linda %p could not read GUID: %s\n",
+ linda, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( linda, "Linda %p has GUID " IB_GUID_FMT "\n",
+ linda, IB_GUID_ARGS ( guid ) );
+
+ /* Read serial number (debug only) */
+ if ( DBG_LOG ) {
+ uint8_t serial[LINDA_EEPROM_SERIAL_SIZE + 1];
+
+ serial[ sizeof ( serial ) - 1 ] = '\0';
+ if ( ( rc = i2c->read ( i2c, &linda->eeprom,
+ LINDA_EEPROM_SERIAL_OFFSET, serial,
+ ( sizeof ( serial ) - 1 ) ) ) != 0 ) {
+ DBGC ( linda, "Linda %p could not read serial: %s\n",
+ linda, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( linda, "Linda %p has serial number \"%s\"\n",
+ linda, serial );
+ }
+
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * External parallel bus access
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Request ownership of the IB external parallel bus
+ *
+ * @v linda Linda device
+ * @ret rc Return status code
+ */
+static int linda_ib_epb_request ( struct linda *linda ) {
+ struct QIB_7220_ibsd_epb_access_ctrl access;
+ unsigned int i;
+
+ /* Request ownership */
+ memset ( &access, 0, sizeof ( access ) );
+ BIT_FILL_1 ( &access, sw_ib_epb_req, 1 );
+ linda_writeq ( linda, &access, QIB_7220_ibsd_epb_access_ctrl_offset );
+
+ /* Wait for ownership to be granted */
+ for ( i = 0 ; i < LINDA_EPB_REQUEST_MAX_WAIT_US ; i++ ) {
+ linda_readq ( linda, &access,
+ QIB_7220_ibsd_epb_access_ctrl_offset );
+ if ( BIT_GET ( &access, sw_ib_epb_req_granted ) )
+ return 0;
+ udelay ( 1 );
+ }
+
+ DBGC ( linda, "Linda %p timed out waiting for IB EPB request\n",
+ linda );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Wait for IB external parallel bus transaction to complete
+ *
+ * @v linda Linda device
+ * @v xact Buffer to hold transaction result
+ * @ret rc Return status code
+ */
+static int linda_ib_epb_wait ( struct linda *linda,
+ struct QIB_7220_ibsd_epb_transaction_reg *xact ) {
+ unsigned int i;
+
+ /* Discard first read to allow for signals crossing clock domains */
+ linda_readq ( linda, xact, QIB_7220_ibsd_epb_transaction_reg_offset );
+
+ for ( i = 0 ; i < LINDA_EPB_XACT_MAX_WAIT_US ; i++ ) {
+ linda_readq ( linda, xact,
+ QIB_7220_ibsd_epb_transaction_reg_offset );
+ if ( BIT_GET ( xact, ib_epb_rdy ) ) {
+ if ( BIT_GET ( xact, ib_epb_req_error ) ) {
+ DBGC ( linda, "Linda %p EPB transaction "
+ "failed\n", linda );
+ return -EIO;
+ } else {
+ return 0;
+ }
+ }
+ udelay ( 1 );
+ }
+
+ DBGC ( linda, "Linda %p timed out waiting for IB EPB transaction\n",
+ linda );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Release ownership of the IB external parallel bus
+ *
+ * @v linda Linda device
+ */
+static void linda_ib_epb_release ( struct linda *linda ) {
+ struct QIB_7220_ibsd_epb_access_ctrl access;
+
+ memset ( &access, 0, sizeof ( access ) );
+ BIT_FILL_1 ( &access, sw_ib_epb_req, 0 );
+ linda_writeq ( linda, &access, QIB_7220_ibsd_epb_access_ctrl_offset );
+}
+
+/**
+ * Read data via IB external parallel bus
+ *
+ * @v linda Linda device
+ * @v location EPB location
+ * @ret data Data read, or negative error
+ *
+ * You must have already acquired ownership of the IB external
+ * parallel bus.
+ */
+static int linda_ib_epb_read ( struct linda *linda, unsigned int location ) {
+ struct QIB_7220_ibsd_epb_transaction_reg xact;
+ unsigned int data;
+ int rc;
+
+ /* Ensure no transaction is currently in progress */
+ if ( ( rc = linda_ib_epb_wait ( linda, &xact ) ) != 0 )
+ return rc;
+
+ /* Process data */
+ memset ( &xact, 0, sizeof ( xact ) );
+ BIT_FILL_3 ( &xact,
+ ib_epb_address, LINDA_EPB_LOC_ADDRESS ( location ),
+ ib_epb_read_write, LINDA_EPB_READ,
+ ib_epb_cs, LINDA_EPB_LOC_CS ( location ) );
+ linda_writeq ( linda, &xact,
+ QIB_7220_ibsd_epb_transaction_reg_offset );
+
+ /* Wait for transaction to complete */
+ if ( ( rc = linda_ib_epb_wait ( linda, &xact ) ) != 0 )
+ return rc;
+
+ data = BIT_GET ( &xact, ib_epb_data );
+ return data;
+}
+
+/**
+ * Write data via IB external parallel bus
+ *
+ * @v linda Linda device
+ * @v location EPB location
+ * @v data Data to write
+ * @ret rc Return status code
+ *
+ * You must have already acquired ownership of the IB external
+ * parallel bus.
+ */
+static int linda_ib_epb_write ( struct linda *linda, unsigned int location,
+ unsigned int data ) {
+ struct QIB_7220_ibsd_epb_transaction_reg xact;
+ int rc;
+
+ /* Ensure no transaction is currently in progress */
+ if ( ( rc = linda_ib_epb_wait ( linda, &xact ) ) != 0 )
+ return rc;
+
+ /* Process data */
+ memset ( &xact, 0, sizeof ( xact ) );
+ BIT_FILL_4 ( &xact,
+ ib_epb_data, data,
+ ib_epb_address, LINDA_EPB_LOC_ADDRESS ( location ),
+ ib_epb_read_write, LINDA_EPB_WRITE,
+ ib_epb_cs, LINDA_EPB_LOC_CS ( location ) );
+ linda_writeq ( linda, &xact,
+ QIB_7220_ibsd_epb_transaction_reg_offset );
+
+ /* Wait for transaction to complete */
+ if ( ( rc = linda_ib_epb_wait ( linda, &xact ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Read/modify/write EPB register
+ *
+ * @v linda Linda device
+ * @v cs Chip select
+ * @v channel Channel
+ * @v element Element
+ * @v reg Register
+ * @v value Value to set
+ * @v mask Mask to apply to old value
+ * @ret rc Return status code
+ */
+static int linda_ib_epb_mod_reg ( struct linda *linda, unsigned int cs,
+ unsigned int channel, unsigned int element,
+ unsigned int reg, unsigned int value,
+ unsigned int mask ) {
+ unsigned int location;
+ int old_value;
+ int rc;
+
+ DBG_DISABLE ( DBGLVL_IO );
+
+ /* Sanity check */
+ assert ( ( value & mask ) == value );
+
+ /* Acquire bus ownership */
+ if ( ( rc = linda_ib_epb_request ( linda ) ) != 0 )
+ goto out;
+
+ /* Read existing value, if necessary */
+ location = LINDA_EPB_LOC ( cs, channel, element, reg );
+ if ( (~mask) & 0xff ) {
+ old_value = linda_ib_epb_read ( linda, location );
+ if ( old_value < 0 ) {
+ rc = old_value;
+ goto out_release;
+ }
+ } else {
+ old_value = 0;
+ }
+
+ /* Update value */
+ value = ( ( old_value & ~mask ) | value );
+ DBGCP ( linda, "Linda %p CS %d EPB(%d,%d,%#02x) %#02x => %#02x\n",
+ linda, cs, channel, element, reg, old_value, value );
+ if ( ( rc = linda_ib_epb_write ( linda, location, value ) ) != 0 )
+ goto out_release;
+
+ out_release:
+ /* Release bus */
+ linda_ib_epb_release ( linda );
+ out:
+ DBG_ENABLE ( DBGLVL_IO );
+ return rc;
+}
+
+/**
+ * Transfer data to/from microcontroller RAM
+ *
+ * @v linda Linda device
+ * @v address Starting address
+ * @v write Data to write, or NULL
+ * @v read Data to read, or NULL
+ * @v len Length of data
+ * @ret rc Return status code
+ */
+static int linda_ib_epb_ram_xfer ( struct linda *linda, unsigned int address,
+ const void *write, void *read,
+ size_t len ) {
+ unsigned int control;
+ unsigned int address_hi;
+ unsigned int address_lo;
+ int data;
+ int rc;
+
+ DBG_DISABLE ( DBGLVL_IO );
+
+ assert ( ! ( write && read ) );
+ assert ( ( address % LINDA_EPB_UC_CHUNK_SIZE ) == 0 );
+ assert ( ( len % LINDA_EPB_UC_CHUNK_SIZE ) == 0 );
+
+ /* Acquire bus ownership */
+ if ( ( rc = linda_ib_epb_request ( linda ) ) != 0 )
+ goto out;
+
+ /* Process data */
+ while ( len ) {
+
+ /* Reset the address for each new chunk */
+ if ( ( address % LINDA_EPB_UC_CHUNK_SIZE ) == 0 ) {
+
+ /* Write the control register */
+ control = ( read ? LINDA_EPB_UC_CTL_READ :
+ LINDA_EPB_UC_CTL_WRITE );
+ if ( ( rc = linda_ib_epb_write ( linda,
+ LINDA_EPB_UC_CTL,
+ control ) ) != 0 )
+ break;
+
+ /* Write the address registers */
+ address_hi = ( address >> 8 );
+ if ( ( rc = linda_ib_epb_write ( linda,
+ LINDA_EPB_UC_ADDR_HI,
+ address_hi ) ) != 0 )
+ break;
+ address_lo = ( address & 0xff );
+ if ( ( rc = linda_ib_epb_write ( linda,
+ LINDA_EPB_UC_ADDR_LO,
+ address_lo ) ) != 0 )
+ break;
+ }
+
+ /* Read or write the data */
+ if ( read ) {
+ data = linda_ib_epb_read ( linda, LINDA_EPB_UC_DATA );
+ if ( data < 0 ) {
+ rc = data;
+ break;
+ }
+ *( ( uint8_t * ) read++ ) = data;
+ } else {
+ data = *( ( uint8_t * ) write++ );
+ if ( ( rc = linda_ib_epb_write ( linda,
+ LINDA_EPB_UC_DATA,
+ data ) ) != 0 )
+ break;
+ }
+ address++;
+ len--;
+
+ /* Reset the control byte after each chunk */
+ if ( ( address % LINDA_EPB_UC_CHUNK_SIZE ) == 0 ) {
+ if ( ( rc = linda_ib_epb_write ( linda,
+ LINDA_EPB_UC_CTL,
+ 0 ) ) != 0 )
+ break;
+ }
+ }
+
+ /* Release bus */
+ linda_ib_epb_release ( linda );
+
+ out:
+ DBG_ENABLE ( DBGLVL_IO );
+ return rc;
+}
+
+/***************************************************************************
+ *
+ * Infiniband SerDes initialisation
+ *
+ ***************************************************************************
+ */
+
+/** A Linda SerDes parameter */
+struct linda_serdes_param {
+ /** EPB address as constructed by LINDA_EPB_ADDRESS() */
+ uint16_t address;
+ /** Value to set */
+ uint8_t value;
+ /** Mask to apply to old value */
+ uint8_t mask;
+} __packed;
+
+/** Magic "all channels" channel number */
+#define LINDA_EPB_ALL_CHANNELS 31
+
+/** End of SerDes parameter list marker */
+#define LINDA_SERDES_PARAM_END { 0, 0, 0 }
+
+/**
+ * Program IB SerDes register(s)
+ *
+ * @v linda Linda device
+ * @v param SerDes parameter
+ * @ret rc Return status code
+ */
+static int linda_set_serdes_param ( struct linda *linda,
+ struct linda_serdes_param *param ) {
+ unsigned int channel;
+ unsigned int channel_start;
+ unsigned int channel_end;
+ unsigned int element;
+ unsigned int reg;
+ int rc;
+
+ /* Break down the EPB address and determine channels */
+ channel = LINDA_EPB_ADDRESS_CHANNEL ( param->address );
+ element = LINDA_EPB_ADDRESS_ELEMENT ( param->address );
+ reg = LINDA_EPB_ADDRESS_REG ( param->address );
+ if ( channel == LINDA_EPB_ALL_CHANNELS ) {
+ channel_start = 0;
+ channel_end = 3;
+ } else {
+ channel_start = channel_end = channel;
+ }
+
+ /* Modify register for each specified channel */
+ for ( channel = channel_start ; channel <= channel_end ; channel++ ) {
+ if ( ( rc = linda_ib_epb_mod_reg ( linda, LINDA_EPB_CS_SERDES,
+ channel, element, reg,
+ param->value,
+ param->mask ) ) != 0 )
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Program IB SerDes registers
+ *
+ * @v linda Linda device
+ * @v param SerDes parameters
+ * @v count Number of parameters
+ * @ret rc Return status code
+ */
+static int linda_set_serdes_params ( struct linda *linda,
+ struct linda_serdes_param *params ) {
+ int rc;
+
+ for ( ; params->mask != 0 ; params++ ){
+ if ( ( rc = linda_set_serdes_param ( linda,
+ params ) ) != 0 )
+ return rc;
+ }
+
+ return 0;
+}
+
+#define LINDA_DDS_VAL( amp_d, main_d, ipst_d, ipre_d, \
+ amp_s, main_s, ipst_s, ipre_s ) \
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x00 ), \
+ ( ( ( amp_d & 0x1f ) << 1 ) | 1 ), 0xff }, \
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x01 ), \
+ ( ( ( amp_s & 0x1f ) << 1 ) | 1 ), 0xff }, \
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x09 ), \
+ ( ( main_d << 3 ) | 4 | ( ipre_d >> 2 ) ), 0xff }, \
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x0a ), \
+ ( ( main_s << 3 ) | 4 | ( ipre_s >> 2 ) ), 0xff }, \
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x06 ), \
+ ( ( ( ipst_d & 0xf ) << 1 ) | \
+ ( ( ipre_d & 3 ) << 6 ) | 0x21 ), 0xff }, \
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x07 ), \
+ ( ( ( ipst_s & 0xf ) << 1 ) | \
+ ( ( ipre_s & 3 ) << 6) | 0x21 ), 0xff }
+
+/**
+ * Linda SerDes default parameters
+ *
+ * These magic start-of-day values are taken from the Linux driver.
+ */
+static struct linda_serdes_param linda_serdes_defaults1[] = {
+ /* RXHSCTRL0 */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x00 ), 0xd4, 0xff },
+ /* VCDL_DAC2 */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x05 ), 0x2d, 0xff },
+ /* VCDL_CTRL2 */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x08 ), 0x03, 0x0f },
+ /* START_EQ1 */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x27 ), 0x10, 0xff },
+ /* START_EQ2 */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x28 ), 0x30, 0xff },
+ /* BACTRL */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x0e ), 0x40, 0xff },
+ /* LDOUTCTRL1 */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x06 ), 0x04, 0xff },
+ /* RXHSSTATUS */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x0f ), 0x04, 0xff },
+ /* End of this block */
+ LINDA_SERDES_PARAM_END
+};
+static struct linda_serdes_param linda_serdes_defaults2[] = {
+ /* LDOUTCTRL1 */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x06 ), 0x00, 0xff },
+ /* DDS values */
+ LINDA_DDS_VAL ( 31, 19, 12, 0, 29, 22, 9, 0 ),
+ /* Set Rcv Eq. to Preset node */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x27 ), 0x10, 0xff },
+ /* DFELTHFDR */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x08 ), 0x00, 0xff },
+ /* DFELTHHDR */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x21 ), 0x00, 0xff },
+ /* TLTHFDR */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x09 ), 0x02, 0xff },
+ /* TLTHHDR */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x23 ), 0x02, 0xff },
+ /* ZFR */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x1b ), 0x0c, 0xff },
+ /* ZCNT) */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x1c ), 0x0c, 0xff },
+ /* GFR */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x1e ), 0x10, 0xff },
+ /* GHR */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x1f ), 0x10, 0xff },
+ /* VCDL_CTRL0 toggle */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x06 ), 0x20, 0xff },
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x06 ), 0x00, 0xff },
+ /* CMUCTRL5 */
+ { LINDA_EPB_ADDRESS ( 7, 0, 0x15 ), 0x80, 0xff },
+ /* End of this block */
+ LINDA_SERDES_PARAM_END
+};
+static struct linda_serdes_param linda_serdes_defaults3[] = {
+ /* START_EQ1 */
+ { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x27 ), 0x00, 0x38 },
+ /* End of this block */
+ LINDA_SERDES_PARAM_END
+};
+
+/**
+ * Program the microcontroller RAM
+ *
+ * @v linda Linda device
+ * @ret rc Return status code
+ */
+static int linda_program_uc_ram ( struct linda *linda ) {
+ int rc;
+
+ if ( ( rc = linda_ib_epb_ram_xfer ( linda, 0, linda_ib_fw, NULL,
+ sizeof ( linda_ib_fw ) ) ) != 0 ){
+ DBGC ( linda, "Linda %p could not load IB firmware: %s\n",
+ linda, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Verify the microcontroller RAM
+ *
+ * @v linda Linda device
+ * @ret rc Return status code
+ */
+static int linda_verify_uc_ram ( struct linda *linda ) {
+ uint8_t verify[LINDA_EPB_UC_CHUNK_SIZE];
+ unsigned int offset;
+ int rc;
+
+ for ( offset = 0 ; offset < sizeof ( linda_ib_fw );
+ offset += sizeof ( verify ) ) {
+ if ( ( rc = linda_ib_epb_ram_xfer ( linda, offset,
+ NULL, verify,
+ sizeof (verify) )) != 0 ){
+ DBGC ( linda, "Linda %p could not read back IB "
+ "firmware: %s\n", linda, strerror ( rc ) );
+ return rc;
+ }
+ if ( memcmp ( ( linda_ib_fw + offset ), verify,
+ sizeof ( verify ) ) != 0 ) {
+ DBGC ( linda, "Linda %p firmware verification failed "
+ "at offset %#x\n", linda, offset );
+ DBGC_HDA ( linda, offset, ( linda_ib_fw + offset ),
+ sizeof ( verify ) );
+ DBGC_HDA ( linda, offset, verify, sizeof ( verify ) );
+ return -EIO;
+ }
+ }
+
+ DBGC2 ( linda, "Linda %p firmware verified ok\n", linda );
+ return 0;
+}
+
+/**
+ * Use the microcontroller to trim the IB link
+ *
+ * @v linda Linda device
+ * @ret rc Return status code
+ */
+static int linda_trim_ib ( struct linda *linda ) {
+ struct QIB_7220_IBSerDesCtrl ctrl;
+ struct QIB_7220_IntStatus intstatus;
+ unsigned int i;
+ int rc;
+
+ /* Bring the microcontroller out of reset */
+ linda_readq ( linda, &ctrl, QIB_7220_IBSerDesCtrl_offset );
+ BIT_SET ( &ctrl, ResetIB_uC_Core, 0 );
+ linda_writeq ( linda, &ctrl, QIB_7220_IBSerDesCtrl_offset );
+
+ /* Wait for the "trim done" signal */
+ for ( i = 0 ; i < LINDA_TRIM_DONE_MAX_WAIT_MS ; i++ ) {
+ linda_readq ( linda, &intstatus, QIB_7220_IntStatus_offset );
+ if ( BIT_GET ( &intstatus, IBSerdesTrimDone ) ) {
+ rc = 0;
+ goto out_reset;
+ }
+ mdelay ( 1 );
+ }
+
+ DBGC ( linda, "Linda %p timed out waiting for trim done\n", linda );
+ rc = -ETIMEDOUT;
+ out_reset:
+ /* Put the microcontroller back into reset */
+ BIT_SET ( &ctrl, ResetIB_uC_Core, 1 );
+ linda_writeq ( linda, &ctrl, QIB_7220_IBSerDesCtrl_offset );
+
+ return rc;
+}
+
+/**
+ * Initialise the IB SerDes
+ *
+ * @v linda Linda device
+ * @ret rc Return status code
+ */
+static int linda_init_ib_serdes ( struct linda *linda ) {
+ struct QIB_7220_Control control;
+ struct QIB_7220_IBCCtrl ibcctrl;
+ struct QIB_7220_IBCDDRCtrl ibcddrctrl;
+ struct QIB_7220_XGXSCfg xgxscfg;
+ int rc;
+
+ /* Disable link */
+ linda_readq ( linda, &control, QIB_7220_Control_offset );
+ BIT_SET ( &control, LinkEn, 0 );
+ linda_writeq ( linda, &control, QIB_7220_Control_offset );
+
+ /* Configure sensible defaults for IBC */
+ memset ( &ibcctrl, 0, sizeof ( ibcctrl ) );
+ BIT_FILL_6 ( &ibcctrl, /* Tuning values taken from Linux driver */
+ FlowCtrlPeriod, 0x03,
+ FlowCtrlWaterMark, 0x05,
+ MaxPktLen, ( ( LINDA_RECV_HEADER_SIZE +
+ LINDA_RECV_PAYLOAD_SIZE +
+ 4 /* ICRC */ ) >> 2 ),
+ PhyerrThreshold, 0xf,
+ OverrunThreshold, 0xf,
+ CreditScale, 0x4 );
+ linda_writeq ( linda, &ibcctrl, QIB_7220_IBCCtrl_offset );
+
+ /* Force SDR only to avoid needing all the DDR tuning,
+ * Mellanox compatibility hacks etc. SDR is plenty for
+ * boot-time operation.
+ */
+ linda_readq ( linda, &ibcddrctrl, QIB_7220_IBCDDRCtrl_offset );
+ BIT_SET ( &ibcddrctrl, IB_ENHANCED_MODE, 0 );
+ BIT_SET ( &ibcddrctrl, SD_SPEED_SDR, 1 );
+ BIT_SET ( &ibcddrctrl, SD_SPEED_DDR, 0 );
+ BIT_SET ( &ibcddrctrl, SD_SPEED_QDR, 0 );
+ BIT_SET ( &ibcddrctrl, HRTBT_ENB, 0 );
+ BIT_SET ( &ibcddrctrl, HRTBT_AUTO, 0 );
+ linda_writeq ( linda, &ibcddrctrl, QIB_7220_IBCDDRCtrl_offset );
+
+ /* Set default SerDes parameters */
+ if ( ( rc = linda_set_serdes_params ( linda,
+ linda_serdes_defaults1 ) ) != 0 )
+ return rc;
+ udelay ( 415 ); /* Magic delay while SerDes sorts itself out */
+ if ( ( rc = linda_set_serdes_params ( linda,
+ linda_serdes_defaults2 ) ) != 0 )
+ return rc;
+
+ /* Program the microcontroller RAM */
+ if ( ( rc = linda_program_uc_ram ( linda ) ) != 0 )
+ return rc;
+
+ /* Verify the microcontroller RAM contents */
+ if ( DBGLVL_LOG ) {
+ if ( ( rc = linda_verify_uc_ram ( linda ) ) != 0 )
+ return rc;
+ }
+
+ /* More SerDes tuning */
+ if ( ( rc = linda_set_serdes_params ( linda,
+ linda_serdes_defaults3 ) ) != 0 )
+ return rc;
+
+ /* Use the microcontroller to trim the IB link */
+ if ( ( rc = linda_trim_ib ( linda ) ) != 0 )
+ return rc;
+
+ /* Bring XGXS out of reset */
+ linda_readq ( linda, &xgxscfg, QIB_7220_XGXSCfg_offset );
+ BIT_SET ( &xgxscfg, tx_rx_reset, 0 );
+ BIT_SET ( &xgxscfg, xcv_reset, 0 );
+ linda_writeq ( linda, &xgxscfg, QIB_7220_XGXSCfg_offset );
+
+ return rc;
+}
+
+/***************************************************************************
+ *
+ * PCI layer interface
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @v id PCI ID
+ * @ret rc Return status code
+ */
+static int linda_probe ( struct pci_device *pci ) {
+ struct ib_device *ibdev;
+ struct linda *linda;
+ struct QIB_7220_Revision revision;
+ int rc;
+
+ /* Allocate Infiniband device */
+ ibdev = alloc_ibdev ( sizeof ( *linda ) );
+ if ( ! ibdev ) {
+ rc = -ENOMEM;
+ goto err_alloc_ibdev;
+ }
+ pci_set_drvdata ( pci, ibdev );
+ linda = ib_get_drvdata ( ibdev );
+ ibdev->op = &linda_ib_operations;
+ ibdev->dev = &pci->dev;
+ ibdev->port = 1;
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* Get PCI BARs */
+ linda->regs = ioremap ( pci->membase, LINDA_BAR0_SIZE );
+ DBGC2 ( linda, "Linda %p has BAR at %08lx\n", linda, pci->membase );
+
+ /* Print some general data */
+ linda_readq ( linda, &revision, QIB_7220_Revision_offset );
+ DBGC2 ( linda, "Linda %p board %02lx v%ld.%ld.%ld.%ld\n", linda,
+ BIT_GET ( &revision, BoardID ),
+ BIT_GET ( &revision, R_SW ),
+ BIT_GET ( &revision, R_Arch ),
+ BIT_GET ( &revision, R_ChipRevMajor ),
+ BIT_GET ( &revision, R_ChipRevMinor ) );
+
+ /* Record link capabilities. Note that we force SDR only to
+ * avoid having to carry extra code for DDR tuning etc.
+ */
+ ibdev->link_width_enabled = ibdev->link_width_supported =
+ ( IB_LINK_WIDTH_4X | IB_LINK_WIDTH_1X );
+ ibdev->link_speed_enabled = ibdev->link_speed_supported =
+ IB_LINK_SPEED_SDR;
+
+ /* Initialise I2C subsystem */
+ if ( ( rc = linda_init_i2c ( linda ) ) != 0 )
+ goto err_init_i2c;
+
+ /* Read EEPROM parameters */
+ if ( ( rc = linda_read_eeprom ( linda, &ibdev->node_guid ) ) != 0 )
+ goto err_read_eeprom;
+ memcpy ( &ibdev->gid.s.guid, &ibdev->node_guid,
+ sizeof ( ibdev->gid.s.guid ) );
+
+ /* Initialise send datapath */
+ if ( ( rc = linda_init_send ( linda ) ) != 0 )
+ goto err_init_send;
+
+ /* Initialise receive datapath */
+ if ( ( rc = linda_init_recv ( linda ) ) != 0 )
+ goto err_init_recv;
+
+ /* Initialise the IB SerDes */
+ if ( ( rc = linda_init_ib_serdes ( linda ) ) != 0 )
+ goto err_init_ib_serdes;
+
+ /* Register Infiniband device */
+ if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) {
+ DBGC ( linda, "Linda %p could not register IB "
+ "device: %s\n", linda, strerror ( rc ) );
+ goto err_register_ibdev;
+ }
+
+ return 0;
+
+ unregister_ibdev ( ibdev );
+ err_register_ibdev:
+ linda_fini_recv ( linda );
+ err_init_recv:
+ linda_fini_send ( linda );
+ err_init_send:
+ err_init_ib_serdes:
+ err_read_eeprom:
+ err_init_i2c:
+ ibdev_put ( ibdev );
+ err_alloc_ibdev:
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void linda_remove ( struct pci_device *pci ) {
+ struct ib_device *ibdev = pci_get_drvdata ( pci );
+ struct linda *linda = ib_get_drvdata ( ibdev );
+
+ unregister_ibdev ( ibdev );
+ linda_fini_recv ( linda );
+ linda_fini_send ( linda );
+ ibdev_put ( ibdev );
+}
+
+static struct pci_device_id linda_nics[] = {
+ PCI_ROM ( 0x1077, 0x7220, "iba7220", "QLE7240/7280 HCA driver", 0 ),
+};
+
+struct pci_driver linda_driver __pci_driver = {
+ .ids = linda_nics,
+ .id_count = ( sizeof ( linda_nics ) / sizeof ( linda_nics[0] ) ),
+ .probe = linda_probe,
+ .remove = linda_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/linda.h b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/linda.h
new file mode 100644
index 00000000..1450a6ad
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/linda.h
@@ -0,0 +1,276 @@
+#ifndef _LINDA_H
+#define _LINDA_H
+
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * QLogic Linda Infiniband HCA
+ *
+ */
+
+#define BITOPS_LITTLE_ENDIAN
+#include <ipxe/bitops.h>
+#include "qib_7220_regs.h"
+
+struct ib_device;
+
+/** A Linda GPIO register */
+struct QIB_7220_GPIO_pb {
+ pseudo_bit_t GPIO[16];
+ pseudo_bit_t Reserved[48];
+};
+struct QIB_7220_GPIO {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_GPIO_pb );
+};
+
+/** A Linda general scalar register */
+struct QIB_7220_scalar_pb {
+ pseudo_bit_t Value[64];
+};
+struct QIB_7220_scalar {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_scalar_pb );
+};
+
+/** Linda send per-buffer control word */
+struct QIB_7220_SendPbc_pb {
+ pseudo_bit_t LengthP1_toibc[11];
+ pseudo_bit_t Reserved1[4];
+ pseudo_bit_t LengthP1_trigger[11];
+ pseudo_bit_t Reserved2[3];
+ pseudo_bit_t TestEbp[1];
+ pseudo_bit_t Test[1];
+ pseudo_bit_t Intr[1];
+ pseudo_bit_t Reserved3[31];
+ pseudo_bit_t VL15[1];
+};
+struct QIB_7220_SendPbc {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendPbc_pb );
+};
+
+/** Linda send buffer availability */
+struct QIB_7220_SendBufAvail_pb {
+ pseudo_bit_t InUseCheck[144][2];
+ pseudo_bit_t Reserved[32];
+};
+struct QIB_7220_SendBufAvail {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufAvail_pb );
+};
+
+/** DMA alignment for send buffer availability */
+#define LINDA_SENDBUFAVAIL_ALIGN 64
+
+/** A Linda eager receive descriptor */
+struct QIB_7220_RcvEgr_pb {
+ pseudo_bit_t Addr[37];
+ pseudo_bit_t BufSize[3];
+ pseudo_bit_t Reserved[24];
+};
+struct QIB_7220_RcvEgr {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvEgr_pb );
+};
+
+/** Linda receive header flags */
+struct QIB_7220_RcvHdrFlags_pb {
+ pseudo_bit_t PktLen[11];
+ pseudo_bit_t RcvType[3];
+ pseudo_bit_t SoftB[1];
+ pseudo_bit_t SoftA[1];
+ pseudo_bit_t EgrIndex[12];
+ pseudo_bit_t Reserved1[3];
+ pseudo_bit_t UseEgrBfr[1];
+ pseudo_bit_t RcvSeq[4];
+ pseudo_bit_t HdrqOffset[11];
+ pseudo_bit_t Reserved2[8];
+ pseudo_bit_t IBErr[1];
+ pseudo_bit_t MKErr[1];
+ pseudo_bit_t TIDErr[1];
+ pseudo_bit_t KHdrErr[1];
+ pseudo_bit_t MTUErr[1];
+ pseudo_bit_t LenErr[1];
+ pseudo_bit_t ParityErr[1];
+ pseudo_bit_t VCRCErr[1];
+ pseudo_bit_t ICRCErr[1];
+};
+struct QIB_7220_RcvHdrFlags {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrFlags_pb );
+};
+
+/** Linda memory BAR size */
+#define LINDA_BAR0_SIZE 0x400000
+
+/** Linda I2C SCL line GPIO number */
+#define LINDA_GPIO_SCL 0
+
+/** Linda I2C SDA line GPIO number */
+#define LINDA_GPIO_SDA 1
+
+/** GUID offset within EEPROM */
+#define LINDA_EEPROM_GUID_OFFSET 3
+
+/** GUID size within EEPROM */
+#define LINDA_EEPROM_GUID_SIZE 8
+
+/** Board serial number offset within EEPROM */
+#define LINDA_EEPROM_SERIAL_OFFSET 12
+
+/** Board serial number size within EEPROM */
+#define LINDA_EEPROM_SERIAL_SIZE 12
+
+/** Maximum number of send buffers used
+ *
+ * This is a policy decision. Must be less than or equal to the total
+ * number of send buffers supported by the hardware (128).
+ */
+#define LINDA_MAX_SEND_BUFS 32
+
+/** Linda send buffer size */
+#define LINDA_SEND_BUF_SIZE 4096
+
+/** Number of contexts (including kernel context)
+ *
+ * This is a policy decision. Must be 5, 9 or 17.
+ */
+#define LINDA_NUM_CONTEXTS 5
+
+/** PortCfg values for different numbers of contexts */
+enum linda_portcfg {
+ LINDA_PORTCFG_5CTX = 0,
+ LINDA_PORTCFG_9CTX = 1,
+ LINDA_PORTCFG_17CTX = 2,
+};
+
+/** PortCfg values for different numbers of contexts */
+#define LINDA_EAGER_ARRAY_SIZE_5CTX_0 2048
+#define LINDA_EAGER_ARRAY_SIZE_5CTX_OTHER 4096
+#define LINDA_EAGER_ARRAY_SIZE_9CTX_0 2048
+#define LINDA_EAGER_ARRAY_SIZE_9CTX_OTHER 2048
+#define LINDA_EAGER_ARRAY_SIZE_17CTX_0 2048
+#define LINDA_EAGER_ARRAY_SIZE_17CTX_OTHER 1024
+
+/** Eager buffer required alignment */
+#define LINDA_EAGER_BUFFER_ALIGN 2048
+
+/** Eager buffer size encodings */
+enum linda_eager_buffer_size {
+ LINDA_EAGER_BUFFER_NONE = 0,
+ LINDA_EAGER_BUFFER_2K = 1,
+ LINDA_EAGER_BUFFER_4K = 2,
+ LINDA_EAGER_BUFFER_8K = 3,
+ LINDA_EAGER_BUFFER_16K = 4,
+ LINDA_EAGER_BUFFER_32K = 5,
+ LINDA_EAGER_BUFFER_64K = 6,
+};
+
+/** Number of RX headers per context
+ *
+ * This is a policy decision.
+ */
+#define LINDA_RECV_HEADER_COUNT 8
+
+/** Maximum size of each RX header
+ *
+ * This is a policy decision. Must be divisible by 4.
+ */
+#define LINDA_RECV_HEADER_SIZE 96
+
+/** Total size of an RX header ring */
+#define LINDA_RECV_HEADERS_SIZE \
+ ( LINDA_RECV_HEADER_SIZE * LINDA_RECV_HEADER_COUNT )
+
+/** RX header alignment */
+#define LINDA_RECV_HEADERS_ALIGN 64
+
+/** RX payload size
+ *
+ * This is a policy decision. Must be a valid eager buffer size.
+ */
+#define LINDA_RECV_PAYLOAD_SIZE 2048
+
+/** QPN used for Infinipath Packets
+ *
+ * This is a policy decision. Must have bit 0 clear. Must not be a
+ * QPN that we will use.
+ */
+#define LINDA_QP_IDETH 0xdead0
+
+/** Maximum time for wait for external parallel bus request, in us */
+#define LINDA_EPB_REQUEST_MAX_WAIT_US 500
+
+/** Maximum time for wait for external parallel bus transaction, in us */
+#define LINDA_EPB_XACT_MAX_WAIT_US 500
+
+/** Linda external parallel bus chip selects */
+#define LINDA_EPB_CS_SERDES 1
+#define LINDA_EPB_CS_UC 2
+
+/** Linda external parallel bus read/write operations */
+#define LINDA_EPB_WRITE 0
+#define LINDA_EPB_READ 1
+
+/** Linda external parallel bus register addresses */
+#define LINDA_EPB_ADDRESS( _channel, _element, _reg ) \
+ ( (_element) | ( (_channel) << 4 ) | ( (_reg) << 9 ) )
+#define LINDA_EPB_ADDRESS_CHANNEL( _address ) ( ( (_address) >> 4 ) & 0x1f )
+#define LINDA_EPB_ADDRESS_ELEMENT( _address ) ( ( (_address) >> 0 ) & 0x0f )
+#define LINDA_EPB_ADDRESS_REG( _address ) ( ( (_address) >> 9 ) & 0x3f )
+
+/** Linda external parallel bus locations
+ *
+ * The location is used by the driver to encode both the chip select
+ * and the EPB address.
+ */
+#define LINDA_EPB_LOC( _cs, _channel, _element, _reg) \
+ ( ( (_cs) << 16 ) | LINDA_EPB_ADDRESS ( _channel, _element, _reg ) )
+#define LINDA_EPB_LOC_ADDRESS( _loc ) ( (_loc) & 0xffff )
+#define LINDA_EPB_LOC_CS( _loc ) ( (_loc) >> 16 )
+
+/** Linda external parallel bus microcontroller register addresses */
+#define LINDA_EPB_UC_CHANNEL 6
+#define LINDA_EPB_UC_LOC( _reg ) \
+ LINDA_EPB_LOC ( LINDA_EPB_CS_UC, LINDA_EPB_UC_CHANNEL, 0, (_reg) )
+#define LINDA_EPB_UC_CTL LINDA_EPB_UC_LOC ( 0 )
+#define LINDA_EPB_UC_CTL_WRITE 1
+#define LINDA_EPB_UC_CTL_READ 2
+#define LINDA_EPB_UC_ADDR_LO LINDA_EPB_UC_LOC ( 2 )
+#define LINDA_EPB_UC_ADDR_HI LINDA_EPB_UC_LOC ( 3 )
+#define LINDA_EPB_UC_DATA LINDA_EPB_UC_LOC ( 4 )
+#define LINDA_EPB_UC_CHUNK_SIZE 64
+
+extern uint8_t linda_ib_fw[8192];
+
+/** Maximum time to wait for "trim done" signal, in ms */
+#define LINDA_TRIM_DONE_MAX_WAIT_MS 1000
+
+/** Linda link states */
+enum linda_link_state {
+ LINDA_LINK_STATE_DOWN = 0,
+ LINDA_LINK_STATE_INIT = 1,
+ LINDA_LINK_STATE_ARM = 2,
+ LINDA_LINK_STATE_ACTIVE = 3,
+ LINDA_LINK_STATE_ACT_DEFER = 4,
+};
+
+/** Maximum time to wait for link state changes, in us */
+#define LINDA_LINK_STATE_MAX_WAIT_US 20
+
+#endif /* _LINDA_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/linda_fw.c b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/linda_fw.c
new file mode 100644
index 00000000..968a5f8d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/linda_fw.c
@@ -0,0 +1,1069 @@
+/*
+ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/*
+ * This file contains the memory image from the vendor, to be copied into
+ * the IB SERDES of the IBA7220 during initialization.
+ * The file also includes the two functions which use this image.
+ */
+
+#include <stdint.h>
+#include "linda.h"
+
+uint8_t linda_ib_fw[8192] = {
+/*0000*/0x02, 0x0A, 0x29, 0x02, 0x0A, 0x87, 0xE5, 0xE6,
+ 0x30, 0xE6, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F,
+/*0010*/0x00, 0xE5, 0xE2, 0x30, 0xE4, 0x04, 0x7E, 0x01,
+ 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x08,
+/*0020*/0x53, 0xF9, 0xF7, 0xE4, 0xF5, 0xFE, 0x80, 0x08,
+ 0x7F, 0x0A, 0x12, 0x17, 0x31, 0x12, 0x0E, 0xA2,
+/*0030*/0x75, 0xFC, 0x08, 0xE4, 0xF5, 0xFD, 0xE5, 0xE7,
+ 0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0x22, 0x00,
+/*0040*/0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x75,
+ 0x51, 0x01, 0xE4, 0xF5, 0x52, 0xF5, 0x53, 0xF5,
+/*0050*/0x52, 0xF5, 0x7E, 0x7F, 0x04, 0x02, 0x04, 0x38,
+ 0xC2, 0x36, 0x05, 0x52, 0xE5, 0x52, 0xD3, 0x94,
+/*0060*/0x0C, 0x40, 0x05, 0x75, 0x52, 0x01, 0xD2, 0x36,
+ 0x90, 0x07, 0x0C, 0x74, 0x07, 0xF0, 0xA3, 0x74,
+/*0070*/0xFF, 0xF0, 0xE4, 0xF5, 0x0C, 0xA3, 0xF0, 0x90,
+ 0x07, 0x14, 0xF0, 0xA3, 0xF0, 0x75, 0x0B, 0x20,
+/*0080*/0xF5, 0x09, 0xE4, 0xF5, 0x08, 0xE5, 0x08, 0xD3,
+ 0x94, 0x30, 0x40, 0x03, 0x02, 0x04, 0x04, 0x12,
+/*0090*/0x00, 0x06, 0x15, 0x0B, 0xE5, 0x08, 0x70, 0x04,
+ 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x09,
+/*00A0*/0x70, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00,
+ 0xEE, 0x5F, 0x60, 0x05, 0x12, 0x18, 0x71, 0xD2,
+/*00B0*/0x35, 0x53, 0xE1, 0xF7, 0xE5, 0x08, 0x45, 0x09,
+ 0xFF, 0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24,
+/*00C0*/0x83, 0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83,
+ 0xEF, 0xF0, 0x85, 0xE2, 0x20, 0xE5, 0x52, 0xD3,
+/*00D0*/0x94, 0x01, 0x40, 0x0D, 0x12, 0x19, 0xF3, 0xE0,
+ 0x54, 0xA0, 0x64, 0x40, 0x70, 0x03, 0x02, 0x03,
+/*00E0*/0xFB, 0x53, 0xF9, 0xF8, 0x90, 0x94, 0x70, 0xE4,
+ 0xF0, 0xE0, 0xF5, 0x10, 0xAF, 0x09, 0x12, 0x1E,
+/*00F0*/0xB3, 0xAF, 0x08, 0xEF, 0x44, 0x08, 0xF5, 0x82,
+ 0x75, 0x83, 0x80, 0xE0, 0xF5, 0x29, 0xEF, 0x44,
+/*0100*/0x07, 0x12, 0x1A, 0x3C, 0xF5, 0x22, 0x54, 0x40,
+ 0xD3, 0x94, 0x00, 0x40, 0x1E, 0xE5, 0x29, 0x54,
+/*0110*/0xF0, 0x70, 0x21, 0x12, 0x19, 0xF3, 0xE0, 0x44,
+ 0x80, 0xF0, 0xE5, 0x22, 0x54, 0x30, 0x65, 0x08,
+/*0120*/0x70, 0x09, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xBF,
+ 0xF0, 0x80, 0x09, 0x12, 0x19, 0xF3, 0x74, 0x40,
+/*0130*/0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12, 0x75,
+ 0x83, 0xAE, 0x74, 0xFF, 0xF0, 0xAF, 0x08, 0x7E,
+/*0140*/0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0xE0, 0xFD,
+ 0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x81,
+/*0150*/0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83, 0xED,
+ 0xF0, 0x90, 0x07, 0x0E, 0xE0, 0x04, 0xF0, 0xEF,
+/*0160*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0x98, 0xE0,
+ 0xF5, 0x28, 0x12, 0x1A, 0x23, 0x40, 0x0C, 0x12,
+/*0170*/0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12, 0x1A, 0x32,
+ 0x02, 0x03, 0xF6, 0xAF, 0x08, 0x7E, 0x00, 0x74,
+/*0180*/0x80, 0xCD, 0xEF, 0xCD, 0x8D, 0x82, 0xF5, 0x83,
+ 0xE0, 0x30, 0xE0, 0x0A, 0x12, 0x19, 0xF3, 0xE0,
+/*0190*/0x44, 0x20, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x19,
+ 0xF3, 0xE0, 0x54, 0xDF, 0xF0, 0xEE, 0x44, 0xAE,
+/*01A0*/0x12, 0x1A, 0x43, 0x30, 0xE4, 0x03, 0x02, 0x03,
+ 0xFB, 0x74, 0x9E, 0x12, 0x1A, 0x05, 0x20, 0xE0,
+/*01B0*/0x03, 0x02, 0x03, 0xFB, 0x8F, 0x82, 0x8E, 0x83,
+ 0xE0, 0x20, 0xE0, 0x03, 0x02, 0x03, 0xFB, 0x12,
+/*01C0*/0x19, 0xF3, 0xE0, 0x44, 0x10, 0xF0, 0xE5, 0xE3,
+ 0x20, 0xE7, 0x08, 0xE5, 0x08, 0x12, 0x1A, 0x3A,
+/*01D0*/0x44, 0x04, 0xF0, 0xAF, 0x08, 0x7E, 0x00, 0xEF,
+ 0x12, 0x1A, 0x3A, 0x20, 0xE2, 0x34, 0x12, 0x19,
+/*01E0*/0xF3, 0xE0, 0x44, 0x08, 0xF0, 0xE5, 0xE4, 0x30,
+ 0xE6, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00,
+/*01F0*/0xE5, 0x7E, 0xC3, 0x94, 0x04, 0x50, 0x04, 0x7C,
+ 0x01, 0x80, 0x02, 0x7C, 0x00, 0xEC, 0x4D, 0x60,
+/*0200*/0x05, 0xC2, 0x35, 0x02, 0x03, 0xFB, 0xEE, 0x44,
+ 0xD2, 0x12, 0x1A, 0x43, 0x44, 0x40, 0xF0, 0x02,
+/*0210*/0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xF7,
+ 0xF0, 0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0,
+/*0220*/0x54, 0xBF, 0xF0, 0x90, 0x07, 0x14, 0xE0, 0x04,
+ 0xF0, 0xE5, 0x7E, 0x70, 0x03, 0x75, 0x7E, 0x01,
+/*0230*/0xAF, 0x08, 0x7E, 0x00, 0x12, 0x1A, 0x23, 0x40,
+ 0x12, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12,
+/*0240*/0x19, 0xF2, 0xE0, 0x54, 0x02, 0x12, 0x1A, 0x32,
+ 0x02, 0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x44,
+/*0250*/0x02, 0x12, 0x19, 0xF2, 0xE0, 0x54, 0xFE, 0xF0,
+ 0xC2, 0x35, 0xEE, 0x44, 0x8A, 0x8F, 0x82, 0xF5,
+/*0260*/0x83, 0xE0, 0xF5, 0x17, 0x54, 0x8F, 0x44, 0x40,
+ 0xF0, 0x74, 0x90, 0xFC, 0xE5, 0x08, 0x44, 0x07,
+/*0270*/0xFD, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0x54, 0x3F,
+ 0x90, 0x07, 0x02, 0xF0, 0xE0, 0x54, 0xC0, 0x8D,
+/*0280*/0x82, 0x8C, 0x83, 0xF0, 0x74, 0x92, 0x12, 0x1A,
+ 0x05, 0x90, 0x07, 0x03, 0x12, 0x1A, 0x19, 0x74,
+/*0290*/0x82, 0x12, 0x1A, 0x05, 0x90, 0x07, 0x04, 0x12,
+ 0x1A, 0x19, 0x74, 0xB4, 0x12, 0x1A, 0x05, 0x90,
+/*02A0*/0x07, 0x05, 0x12, 0x1A, 0x19, 0x74, 0x94, 0xFE,
+ 0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A, 0xF5,
+/*02B0*/0x10, 0x30, 0xE0, 0x04, 0xD2, 0x37, 0x80, 0x02,
+ 0xC2, 0x37, 0xE5, 0x10, 0x54, 0x7F, 0x8F, 0x82,
+/*02C0*/0x8E, 0x83, 0xF0, 0x30, 0x44, 0x30, 0x12, 0x1A,
+ 0x03, 0x54, 0x80, 0xD3, 0x94, 0x00, 0x40, 0x04,
+/*02D0*/0xD2, 0x39, 0x80, 0x02, 0xC2, 0x39, 0x8F, 0x82,
+ 0x8E, 0x83, 0xE0, 0x44, 0x80, 0xF0, 0x12, 0x1A,
+/*02E0*/0x03, 0x54, 0x40, 0xD3, 0x94, 0x00, 0x40, 0x04,
+ 0xD2, 0x3A, 0x80, 0x02, 0xC2, 0x3A, 0x8F, 0x82,
+/*02F0*/0x8E, 0x83, 0xE0, 0x44, 0x40, 0xF0, 0x74, 0x92,
+ 0xFE, 0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A,
+/*0300*/0x30, 0xE7, 0x04, 0xD2, 0x38, 0x80, 0x02, 0xC2,
+ 0x38, 0x8F, 0x82, 0x8E, 0x83, 0xE0, 0x54, 0x7F,
+/*0310*/0xF0, 0x12, 0x1E, 0x46, 0xE4, 0xF5, 0x0A, 0x20,
+ 0x03, 0x02, 0x80, 0x03, 0x30, 0x43, 0x03, 0x12,
+/*0320*/0x19, 0x95, 0x20, 0x02, 0x02, 0x80, 0x03, 0x30,
+ 0x42, 0x03, 0x12, 0x0C, 0x8F, 0x30, 0x30, 0x06,
+/*0330*/0x12, 0x19, 0x95, 0x12, 0x0C, 0x8F, 0x12, 0x0D,
+ 0x47, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xFB, 0xF0,
+/*0340*/0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40, 0x46, 0x43,
+ 0xE1, 0x08, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x04,
+/*0350*/0xF0, 0xE5, 0xE4, 0x20, 0xE7, 0x2A, 0x12, 0x1A,
+ 0x12, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3,
+/*0360*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
+ 0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40,
+/*0370*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF,
+ 0x5E, 0x60, 0x05, 0x12, 0x1D, 0xD7, 0x80, 0x17,
+/*0380*/0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0, 0x44,
+ 0x08, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12,
+/*0390*/0x75, 0x83, 0xD2, 0xE0, 0x54, 0xF7, 0xF0, 0x12,
+ 0x1E, 0x46, 0x7F, 0x08, 0x12, 0x17, 0x31, 0x74,
+/*03A0*/0x8E, 0xFE, 0x12, 0x1A, 0x12, 0x8E, 0x83, 0xE0,
+ 0xF5, 0x10, 0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44,
+/*03B0*/0x01, 0xFF, 0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07,
+ 0xF5, 0x82, 0xEF, 0xF0, 0xE5, 0x10, 0x54, 0xFE,
+/*03C0*/0xFF, 0xED, 0x44, 0x07, 0xF5, 0x82, 0xEF, 0x12,
+ 0x1A, 0x11, 0x75, 0x83, 0x86, 0xE0, 0x44, 0x10,
+/*03D0*/0x12, 0x1A, 0x11, 0xE0, 0x44, 0x10, 0xF0, 0x12,
+ 0x19, 0xF3, 0xE0, 0x54, 0xFD, 0x44, 0x01, 0xFF,
+/*03E0*/0x12, 0x19, 0xF3, 0xEF, 0x12, 0x1A, 0x32, 0x30,
+ 0x32, 0x0C, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82,
+/*03F0*/0x75, 0x83, 0x82, 0x74, 0x05, 0xF0, 0xAF, 0x0B,
+ 0x12, 0x18, 0xD7, 0x74, 0x10, 0x25, 0x08, 0xF5,
+/*0400*/0x08, 0x02, 0x00, 0x85, 0x05, 0x09, 0xE5, 0x09,
+ 0xD3, 0x94, 0x07, 0x50, 0x03, 0x02, 0x00, 0x82,
+/*0410*/0xE5, 0x7E, 0xD3, 0x94, 0x00, 0x40, 0x04, 0x7F,
+ 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x7E, 0xC3,
+/*0420*/0x94, 0xFA, 0x50, 0x04, 0x7E, 0x01, 0x80, 0x02,
+ 0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x02, 0x05, 0x7E,
+/*0430*/0x30, 0x35, 0x0B, 0x43, 0xE1, 0x01, 0x7F, 0x09,
+ 0x12, 0x17, 0x31, 0x02, 0x00, 0x58, 0x53, 0xE1,
+/*0440*/0xFE, 0x02, 0x00, 0x58, 0x8E, 0x6A, 0x8F, 0x6B,
+ 0x8C, 0x6C, 0x8D, 0x6D, 0x75, 0x6E, 0x01, 0x75,
+/*0450*/0x6F, 0x01, 0x75, 0x70, 0x01, 0xE4, 0xF5, 0x73,
+ 0xF5, 0x74, 0xF5, 0x75, 0x90, 0x07, 0x2F, 0xF0,
+/*0460*/0xF5, 0x3C, 0xF5, 0x3E, 0xF5, 0x46, 0xF5, 0x47,
+ 0xF5, 0x3D, 0xF5, 0x3F, 0xF5, 0x6F, 0xE5, 0x6F,
+/*0470*/0x70, 0x0F, 0xE5, 0x6B, 0x45, 0x6A, 0x12, 0x07,
+ 0x2A, 0x75, 0x83, 0x80, 0x74, 0x3A, 0xF0, 0x80,
+/*0480*/0x09, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74,
+ 0x1A, 0xF0, 0xE4, 0xF5, 0x6E, 0xC3, 0x74, 0x3F,
+/*0490*/0x95, 0x6E, 0xFF, 0x12, 0x08, 0x65, 0x75, 0x83,
+ 0x82, 0xEF, 0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x08,
+/*04A0*/0xC6, 0xE5, 0x33, 0xF0, 0x12, 0x08, 0xFA, 0x12,
+ 0x08, 0xB1, 0x40, 0xE1, 0xE5, 0x6F, 0x70, 0x0B,
+/*04B0*/0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74, 0x36,
+ 0xF0, 0x80, 0x09, 0x12, 0x07, 0x2A, 0x75, 0x83,
+/*04C0*/0x80, 0x74, 0x16, 0xF0, 0x75, 0x6E, 0x01, 0x12,
+ 0x07, 0x2A, 0x75, 0x83, 0xB4, 0xE5, 0x6E, 0xF0,
+/*04D0*/0x12, 0x1A, 0x4D, 0x74, 0x3F, 0x25, 0x6E, 0xF5,
+ 0x82, 0xE4, 0x34, 0x00, 0xF5, 0x83, 0xE5, 0x33,
+/*04E0*/0xF0, 0x74, 0xBF, 0x25, 0x6E, 0xF5, 0x82, 0xE4,
+ 0x34, 0x00, 0x12, 0x08, 0xB1, 0x40, 0xD8, 0xE4,
+/*04F0*/0xF5, 0x70, 0xF5, 0x46, 0xF5, 0x47, 0xF5, 0x6E,
+ 0x12, 0x08, 0xFA, 0xF5, 0x83, 0xE0, 0xFE, 0x12,
+/*0500*/0x08, 0xC6, 0xE0, 0x7C, 0x00, 0x24, 0x00, 0xFF,
+ 0xEC, 0x3E, 0xFE, 0xAD, 0x3B, 0xD3, 0xEF, 0x9D,
+/*0510*/0xEE, 0x9C, 0x50, 0x04, 0x7B, 0x01, 0x80, 0x02,
+ 0x7B, 0x00, 0xE5, 0x70, 0x70, 0x04, 0x7A, 0x01,
+/*0520*/0x80, 0x02, 0x7A, 0x00, 0xEB, 0x5A, 0x60, 0x06,
+ 0x85, 0x6E, 0x46, 0x75, 0x70, 0x01, 0xD3, 0xEF,
+/*0530*/0x9D, 0xEE, 0x9C, 0x50, 0x04, 0x7F, 0x01, 0x80,
+ 0x02, 0x7F, 0x00, 0xE5, 0x70, 0xB4, 0x01, 0x04,
+/*0540*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF, 0x5E,
+ 0x60, 0x03, 0x85, 0x6E, 0x47, 0x05, 0x6E, 0xE5,
+/*0550*/0x6E, 0x64, 0x7F, 0x70, 0xA3, 0xE5, 0x46, 0x60,
+ 0x05, 0xE5, 0x47, 0xB4, 0x7E, 0x03, 0x85, 0x46,
+/*0560*/0x47, 0xE5, 0x6F, 0x70, 0x08, 0x85, 0x46, 0x76,
+ 0x85, 0x47, 0x77, 0x80, 0x0E, 0xC3, 0x74, 0x7F,
+/*0570*/0x95, 0x46, 0xF5, 0x78, 0xC3, 0x74, 0x7F, 0x95,
+ 0x47, 0xF5, 0x79, 0xE5, 0x6F, 0x70, 0x37, 0xE5,
+/*0580*/0x46, 0x65, 0x47, 0x70, 0x0C, 0x75, 0x73, 0x01,
+ 0x75, 0x74, 0x01, 0xF5, 0x3C, 0xF5, 0x3D, 0x80,
+/*0590*/0x35, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5, 0x47, 0x95,
+ 0x46, 0xF5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25,
+/*05A0*/0x46, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05,
+ 0xE4, 0xF5, 0x3D, 0x80, 0x40, 0xC3, 0x74, 0x3F,
+/*05B0*/0x95, 0x72, 0xF5, 0x3D, 0x80, 0x37, 0xE5, 0x46,
+ 0x65, 0x47, 0x70, 0x0F, 0x75, 0x73, 0x01, 0x75,
+/*05C0*/0x75, 0x01, 0xF5, 0x3E, 0xF5, 0x3F, 0x75, 0x4E,
+ 0x01, 0x80, 0x22, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5,
+/*05D0*/0x47, 0x95, 0x46, 0xF5, 0x3E, 0xC3, 0x13, 0xF5,
+ 0x71, 0x25, 0x46, 0xF5, 0x72, 0xD3, 0x94, 0x3F,
+/*05E0*/0x50, 0x05, 0xE4, 0xF5, 0x3F, 0x80, 0x06, 0xE5,
+ 0x72, 0x24, 0xC1, 0xF5, 0x3F, 0x05, 0x6F, 0xE5,
+/*05F0*/0x6F, 0xC3, 0x94, 0x02, 0x50, 0x03, 0x02, 0x04,
+ 0x6E, 0xE5, 0x6D, 0x45, 0x6C, 0x70, 0x02, 0x80,
+/*0600*/0x04, 0xE5, 0x74, 0x45, 0x75, 0x90, 0x07, 0x2F,
+ 0xF0, 0x7F, 0x01, 0xE5, 0x3E, 0x60, 0x04, 0xE5,
+/*0610*/0x3C, 0x70, 0x14, 0xE4, 0xF5, 0x3C, 0xF5, 0x3D,
+ 0xF5, 0x3E, 0xF5, 0x3F, 0x12, 0x08, 0xD2, 0x70,
+/*0620*/0x04, 0xF0, 0x02, 0x06, 0xA4, 0x80, 0x7A, 0xE5,
+ 0x3C, 0xC3, 0x95, 0x3E, 0x40, 0x07, 0xE5, 0x3C,
+/*0630*/0x95, 0x3E, 0xFF, 0x80, 0x06, 0xC3, 0xE5, 0x3E,
+ 0x95, 0x3C, 0xFF, 0xE5, 0x76, 0xD3, 0x95, 0x79,
+/*0640*/0x40, 0x05, 0x85, 0x76, 0x7A, 0x80, 0x03, 0x85,
+ 0x79, 0x7A, 0xE5, 0x77, 0xC3, 0x95, 0x78, 0x50,
+/*0650*/0x05, 0x85, 0x77, 0x7B, 0x80, 0x03, 0x85, 0x78,
+ 0x7B, 0xE5, 0x7B, 0xD3, 0x95, 0x7A, 0x40, 0x30,
+/*0660*/0xE5, 0x7B, 0x95, 0x7A, 0xF5, 0x3C, 0xF5, 0x3E,
+ 0xC3, 0xE5, 0x7B, 0x95, 0x7A, 0x90, 0x07, 0x19,
+/*0670*/0xF0, 0xE5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25,
+ 0x7A, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05,
+/*0680*/0xE4, 0xF5, 0x3D, 0x80, 0x1F, 0xC3, 0x74, 0x3F,
+ 0x95, 0x72, 0xF5, 0x3D, 0xF5, 0x3F, 0x80, 0x14,
+/*0690*/0xE4, 0xF5, 0x3C, 0xF5, 0x3E, 0x90, 0x07, 0x19,
+ 0xF0, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80,
+/*06A0*/0x03, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x65, 0x75,
+ 0x83, 0xD0, 0xE0, 0x54, 0x0F, 0xFE, 0xAD, 0x3C,
+/*06B0*/0x70, 0x02, 0x7E, 0x07, 0xBE, 0x0F, 0x02, 0x7E,
+ 0x80, 0xEE, 0xFB, 0xEF, 0xD3, 0x9B, 0x74, 0x80,
+/*06C0*/0xF8, 0x98, 0x40, 0x1F, 0xE4, 0xF5, 0x3C, 0xF5,
+ 0x3E, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80,
+/*06D0*/0x12, 0x74, 0x01, 0xF0, 0xE5, 0x08, 0xFB, 0xEB,
+ 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xD2, 0xE0,
+/*06E0*/0x44, 0x10, 0xF0, 0xE5, 0x08, 0xFB, 0xEB, 0x44,
+ 0x09, 0xF5, 0x82, 0x75, 0x83, 0x9E, 0xED, 0xF0,
+/*06F0*/0xEB, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xCA,
+ 0xED, 0xF0, 0x12, 0x08, 0x65, 0x75, 0x83, 0xCC,
+/*0700*/0xEF, 0xF0, 0x22, 0xE5, 0x08, 0x44, 0x07, 0xF5,
+ 0x82, 0x75, 0x83, 0xBC, 0xE0, 0x54, 0xF0, 0xF0,
+/*0710*/0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83,
+ 0xBE, 0xE0, 0x54, 0xF0, 0xF0, 0xE5, 0x08, 0x44,
+/*0720*/0x07, 0xF5, 0x82, 0x75, 0x83, 0xC0, 0xE0, 0x54,
+ 0xF0, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82,
+/*0730*/0x22, 0xF0, 0x90, 0x07, 0x28, 0xE0, 0xFE, 0xA3,
+ 0xE0, 0xF5, 0x82, 0x8E, 0x83, 0x22, 0x85, 0x42,
+/*0740*/0x42, 0x85, 0x41, 0x41, 0x85, 0x40, 0x40, 0x74,
+ 0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E, 0xF5,
+/*0750*/0x83, 0xE5, 0x42, 0xF0, 0x74, 0xE0, 0x2F, 0xF5,
+ 0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xE5,
+/*0760*/0x42, 0x29, 0xFD, 0xE4, 0x33, 0xFC, 0xE5, 0x3C,
+ 0xC3, 0x9D, 0xEC, 0x64, 0x80, 0xF8, 0x74, 0x80,
+/*0770*/0x98, 0x22, 0xF5, 0x83, 0xE0, 0x90, 0x07, 0x22,
+ 0x54, 0x1F, 0xFD, 0xE0, 0xFA, 0xA3, 0xE0, 0xF5,
+/*0780*/0x82, 0x8A, 0x83, 0xED, 0xF0, 0x22, 0x90, 0x07,
+ 0x22, 0xE0, 0xFC, 0xA3, 0xE0, 0xF5, 0x82, 0x8C,
+/*0790*/0x83, 0x22, 0x90, 0x07, 0x24, 0xFF, 0xED, 0x44,
+ 0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22, 0x85,
+/*07A0*/0x38, 0x38, 0x85, 0x39, 0x39, 0x85, 0x3A, 0x3A,
+ 0x74, 0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E,
+/*07B0*/0xF5, 0x83, 0x22, 0x90, 0x07, 0x26, 0xFF, 0xED,
+ 0x44, 0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22,
+/*07C0*/0xF0, 0x74, 0xA0, 0x2F, 0xF5, 0x82, 0x74, 0x02,
+ 0x3E, 0xF5, 0x83, 0x22, 0x74, 0xC0, 0x25, 0x11,
+/*07D0*/0xF5, 0x82, 0xE4, 0x34, 0x01, 0xF5, 0x83, 0x22,
+ 0x74, 0x00, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
+/*07E0*/0x02, 0xF5, 0x83, 0x22, 0x74, 0x60, 0x25, 0x11,
+ 0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22,
+/*07F0*/0x74, 0x80, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
+ 0x03, 0xF5, 0x83, 0x22, 0x74, 0xE0, 0x25, 0x11,
+/*0800*/0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22,
+ 0x74, 0x40, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
+/*0810*/0x06, 0xF5, 0x83, 0x22, 0x74, 0x80, 0x2F, 0xF5,
+ 0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xAF,
+/*0820*/0x08, 0x7E, 0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82,
+ 0x22, 0xF5, 0x83, 0xE5, 0x82, 0x44, 0x07, 0xF5,
+/*0830*/0x82, 0xE5, 0x40, 0xF0, 0x22, 0x74, 0x40, 0x25,
+ 0x11, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83,
+/*0840*/0x22, 0x74, 0xC0, 0x25, 0x11, 0xF5, 0x82, 0xE4,
+ 0x34, 0x03, 0xF5, 0x83, 0x22, 0x74, 0x00, 0x25,
+/*0850*/0x11, 0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83,
+ 0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4,
+/*0860*/0x34, 0x06, 0xF5, 0x83, 0x22, 0xE5, 0x08, 0xFD,
+ 0xED, 0x44, 0x07, 0xF5, 0x82, 0x22, 0xE5, 0x41,
+/*0870*/0xF0, 0xE5, 0x65, 0x64, 0x01, 0x45, 0x64, 0x22,
+ 0x7E, 0x00, 0xFB, 0x7A, 0x00, 0xFD, 0x7C, 0x00,
+/*0880*/0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4,
+ 0x34, 0x02, 0x22, 0x74, 0xA0, 0x25, 0x11, 0xF5,
+/*0890*/0x82, 0xE4, 0x34, 0x03, 0x22, 0x85, 0x3E, 0x42,
+ 0x85, 0x3F, 0x41, 0x8F, 0x40, 0x22, 0x85, 0x3C,
+/*08A0*/0x42, 0x85, 0x3D, 0x41, 0x8F, 0x40, 0x22, 0x75,
+ 0x45, 0x3F, 0x90, 0x07, 0x20, 0xE4, 0xF0, 0xA3,
+/*08B0*/0x22, 0xF5, 0x83, 0xE5, 0x32, 0xF0, 0x05, 0x6E,
+ 0xE5, 0x6E, 0xC3, 0x94, 0x40, 0x22, 0xF0, 0xE5,
+/*08C0*/0x08, 0x44, 0x06, 0xF5, 0x82, 0x22, 0x74, 0x00,
+ 0x25, 0x6E, 0xF5, 0x82, 0xE4, 0x34, 0x00, 0xF5,
+/*08D0*/0x83, 0x22, 0xE5, 0x6D, 0x45, 0x6C, 0x90, 0x07,
+ 0x2F, 0x22, 0xE4, 0xF9, 0xE5, 0x3C, 0xD3, 0x95,
+/*08E0*/0x3E, 0x22, 0x74, 0x80, 0x2E, 0xF5, 0x82, 0xE4,
+ 0x34, 0x02, 0xF5, 0x83, 0xE0, 0x22, 0x74, 0xA0,
+/*08F0*/0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83,
+ 0xE0, 0x22, 0x74, 0x80, 0x25, 0x6E, 0xF5, 0x82,
+/*0900*/0xE4, 0x34, 0x00, 0x22, 0x25, 0x42, 0xFD, 0xE4,
+ 0x33, 0xFC, 0x22, 0x85, 0x42, 0x42, 0x85, 0x41,
+/*0910*/0x41, 0x85, 0x40, 0x40, 0x22, 0xED, 0x4C, 0x60,
+ 0x03, 0x02, 0x09, 0xE5, 0xEF, 0x4E, 0x70, 0x37,
+/*0920*/0x90, 0x07, 0x26, 0x12, 0x07, 0x89, 0xE0, 0xFD,
+ 0x12, 0x07, 0xCC, 0xED, 0xF0, 0x90, 0x07, 0x28,
+/*0930*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xD8,
+ 0xED, 0xF0, 0x12, 0x07, 0x86, 0xE0, 0x54, 0x1F,
+/*0940*/0xFD, 0x12, 0x08, 0x81, 0xF5, 0x83, 0xED, 0xF0,
+ 0x90, 0x07, 0x24, 0x12, 0x07, 0x89, 0xE0, 0x54,
+/*0950*/0x1F, 0xFD, 0x12, 0x08, 0x35, 0xED, 0xF0, 0xEF,
+ 0x64, 0x04, 0x4E, 0x70, 0x37, 0x90, 0x07, 0x26,
+/*0960*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xE4,
+ 0xED, 0xF0, 0x90, 0x07, 0x28, 0x12, 0x07, 0x89,
+/*0970*/0xE0, 0xFD, 0x12, 0x07, 0xF0, 0xED, 0xF0, 0x12,
+ 0x07, 0x86, 0xE0, 0x54, 0x1F, 0xFD, 0x12, 0x08,
+/*0980*/0x8B, 0xF5, 0x83, 0xED, 0xF0, 0x90, 0x07, 0x24,
+ 0x12, 0x07, 0x89, 0xE0, 0x54, 0x1F, 0xFD, 0x12,
+/*0990*/0x08, 0x41, 0xED, 0xF0, 0xEF, 0x64, 0x01, 0x4E,
+ 0x70, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00,
+/*09A0*/0xEF, 0x64, 0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01,
+ 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x78,
+/*09B0*/0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE0, 0xFF,
+ 0x12, 0x07, 0xFC, 0xEF, 0x12, 0x07, 0x31, 0xE0,
+/*09C0*/0xFF, 0x12, 0x08, 0x08, 0xEF, 0xF0, 0x90, 0x07,
+ 0x22, 0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF,
+/*09D0*/0x12, 0x08, 0x4D, 0xEF, 0xF0, 0x90, 0x07, 0x24,
+ 0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF, 0x12,
+/*09E0*/0x08, 0x59, 0xEF, 0xF0, 0x22, 0x12, 0x07, 0xCC,
+ 0xE4, 0xF0, 0x12, 0x07, 0xD8, 0xE4, 0xF0, 0x12,
+/*09F0*/0x08, 0x81, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08,
+ 0x35, 0x74, 0x14, 0xF0, 0x12, 0x07, 0xE4, 0xE4,
+/*0A00*/0xF0, 0x12, 0x07, 0xF0, 0xE4, 0xF0, 0x12, 0x08,
+ 0x8B, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08, 0x41,
+/*0A10*/0x74, 0x14, 0xF0, 0x12, 0x07, 0xFC, 0xE4, 0xF0,
+ 0x12, 0x08, 0x08, 0xE4, 0xF0, 0x12, 0x08, 0x4D,
+/*0A20*/0xE4, 0xF0, 0x12, 0x08, 0x59, 0x74, 0x14, 0xF0,
+ 0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFC, 0x10, 0xE4,
+/*0A30*/0xF5, 0xFD, 0x75, 0xFE, 0x30, 0xF5, 0xFF, 0xE5,
+ 0xE7, 0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0xE5,
+/*0A40*/0xE6, 0x20, 0xE7, 0x0B, 0x78, 0xFF, 0xE4, 0xF6,
+ 0xD8, 0xFD, 0x53, 0xE6, 0xFE, 0x80, 0x09, 0x78,
+/*0A50*/0x08, 0xE4, 0xF6, 0xD8, 0xFD, 0x53, 0xE6, 0xFE,
+ 0x75, 0x81, 0x80, 0xE4, 0xF5, 0xA8, 0xD2, 0xA8,
+/*0A60*/0xC2, 0xA9, 0xD2, 0xAF, 0xE5, 0xE2, 0x20, 0xE5,
+ 0x05, 0x20, 0xE6, 0x02, 0x80, 0x03, 0x43, 0xE1,
+/*0A70*/0x02, 0xE5, 0xE2, 0x20, 0xE0, 0x0E, 0x90, 0x00,
+ 0x00, 0x7F, 0x00, 0x7E, 0x08, 0xE4, 0xF0, 0xA3,
+/*0A80*/0xDF, 0xFC, 0xDE, 0xFA, 0x02, 0x0A, 0xDB, 0x43,
+ 0xFA, 0x01, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83,
+/*0A90*/0xC0, 0x82, 0xC0, 0xD0, 0x12, 0x1C, 0xE7, 0xD0,
+ 0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0,
+/*0AA0*/0xE0, 0x53, 0xFA, 0xFE, 0x32, 0x02, 0x1B, 0x55,
+ 0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0xF6,
+/*0AB0*/0x08, 0xDF, 0xF9, 0x80, 0x29, 0xE4, 0x93, 0xA3,
+ 0xF8, 0x54, 0x07, 0x24, 0x0C, 0xC8, 0xC3, 0x33,
+/*0AC0*/0xC4, 0x54, 0x0F, 0x44, 0x20, 0xC8, 0x83, 0x40,
+ 0x04, 0xF4, 0x56, 0x80, 0x01, 0x46, 0xF6, 0xDF,
+/*0AD0*/0xE4, 0x80, 0x0B, 0x01, 0x02, 0x04, 0x08, 0x10,
+ 0x20, 0x40, 0x80, 0x90, 0x00, 0x3F, 0xE4, 0x7E,
+/*0AE0*/0x01, 0x93, 0x60, 0xC1, 0xA3, 0xFF, 0x54, 0x3F,
+ 0x30, 0xE5, 0x09, 0x54, 0x1F, 0xFE, 0xE4, 0x93,
+/*0AF0*/0xA3, 0x60, 0x01, 0x0E, 0xCF, 0x54, 0xC0, 0x25,
+ 0xE0, 0x60, 0xAD, 0x40, 0xB8, 0x80, 0xFE, 0x8C,
+/*0B00*/0x64, 0x8D, 0x65, 0x8A, 0x66, 0x8B, 0x67, 0xE4,
+ 0xF5, 0x69, 0xEF, 0x4E, 0x70, 0x03, 0x02, 0x1D,
+/*0B10*/0x55, 0xE4, 0xF5, 0x68, 0xE5, 0x67, 0x45, 0x66,
+ 0x70, 0x32, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90,
+/*0B20*/0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE4,
+ 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4, 0x12,
+/*0B30*/0x08, 0x70, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75,
+ 0x83, 0x92, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83,
+/*0B40*/0xC6, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8,
+ 0xE4, 0xF0, 0x80, 0x11, 0x90, 0x07, 0x26, 0x12,
+/*0B50*/0x07, 0x35, 0xE4, 0x12, 0x08, 0x70, 0x70, 0x05,
+ 0x12, 0x07, 0x32, 0xE4, 0xF0, 0x12, 0x1D, 0x55,
+/*0B60*/0x12, 0x1E, 0xBF, 0xE5, 0x67, 0x45, 0x66, 0x70,
+ 0x33, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90, 0xE5,
+/*0B70*/0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5,
+ 0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x12,
+/*0B80*/0x08, 0x6E, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75,
+ 0x83, 0x92, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75,
+/*0B90*/0x83, 0xC6, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75,
+ 0x83, 0xC8, 0x80, 0x0E, 0x90, 0x07, 0x26, 0x12,
+/*0BA0*/0x07, 0x35, 0x12, 0x08, 0x6E, 0x70, 0x06, 0x12,
+ 0x07, 0x32, 0xE5, 0x40, 0xF0, 0xAF, 0x69, 0x7E,
+/*0BB0*/0x00, 0xAD, 0x67, 0xAC, 0x66, 0x12, 0x04, 0x44,
+ 0x12, 0x07, 0x2A, 0x75, 0x83, 0xCA, 0xE0, 0xD3,
+/*0BC0*/0x94, 0x00, 0x50, 0x0C, 0x05, 0x68, 0xE5, 0x68,
+ 0xC3, 0x94, 0x05, 0x50, 0x03, 0x02, 0x0B, 0x14,
+/*0BD0*/0x22, 0x8C, 0x60, 0x8D, 0x61, 0x12, 0x08, 0xDA,
+ 0x74, 0x20, 0x40, 0x0D, 0x2F, 0xF5, 0x82, 0x74,
+/*0BE0*/0x03, 0x3E, 0xF5, 0x83, 0xE5, 0x3E, 0xF0, 0x80,
+ 0x0B, 0x2F, 0xF5, 0x82, 0x74, 0x03, 0x3E, 0xF5,
+/*0BF0*/0x83, 0xE5, 0x3C, 0xF0, 0xE5, 0x3C, 0xD3, 0x95,
+ 0x3E, 0x40, 0x3C, 0xE5, 0x61, 0x45, 0x60, 0x70,
+/*0C00*/0x10, 0xE9, 0x12, 0x09, 0x04, 0xE5, 0x3E, 0x12,
+ 0x07, 0x68, 0x40, 0x3B, 0x12, 0x08, 0x95, 0x80,
+/*0C10*/0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40, 0x1D,
+ 0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05, 0x85,
+/*0C20*/0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39, 0x8F,
+ 0x3A, 0x12, 0x08, 0x14, 0xE5, 0x3E, 0x12, 0x07,
+/*0C30*/0xC0, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x43, 0xE5,
+ 0x61, 0x45, 0x60, 0x70, 0x19, 0x12, 0x07, 0x5F,
+/*0C40*/0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x27, 0x12,
+ 0x09, 0x0B, 0x12, 0x08, 0x14, 0xE5, 0x42, 0x12,
+/*0C50*/0x07, 0xC0, 0xE5, 0x41, 0xF0, 0x22, 0xE5, 0x3C,
+ 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C, 0x38,
+/*0C60*/0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39, 0x80,
+ 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x08,
+/*0C70*/0x14, 0xE5, 0x3C, 0x12, 0x07, 0xC0, 0xE5, 0x3D,
+ 0xF0, 0x22, 0x85, 0x38, 0x38, 0x85, 0x39, 0x39,
+/*0C80*/0x85, 0x3A, 0x3A, 0x12, 0x08, 0x14, 0xE5, 0x38,
+ 0x12, 0x07, 0xC0, 0xE5, 0x39, 0xF0, 0x22, 0x7F,
+/*0C90*/0x06, 0x12, 0x17, 0x31, 0x12, 0x1D, 0x23, 0x12,
+ 0x0E, 0x04, 0x12, 0x0E, 0x33, 0xE0, 0x44, 0x0A,
+/*0CA0*/0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E, 0x04, 0x12,
+ 0x0E, 0x0B, 0xEF, 0xF0, 0xE5, 0x28, 0x30, 0xE5,
+/*0CB0*/0x03, 0xD3, 0x80, 0x01, 0xC3, 0x40, 0x05, 0x75,
+ 0x14, 0x20, 0x80, 0x03, 0x75, 0x14, 0x08, 0x12,
+/*0CC0*/0x0E, 0x04, 0x75, 0x83, 0x8A, 0xE5, 0x14, 0xF0,
+ 0xB4, 0xFF, 0x05, 0x75, 0x12, 0x80, 0x80, 0x06,
+/*0CD0*/0xE5, 0x14, 0xC3, 0x13, 0xF5, 0x12, 0xE4, 0xF5,
+ 0x16, 0xF5, 0x7F, 0x12, 0x19, 0x36, 0x12, 0x13,
+/*0CE0*/0xA3, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x50, 0x09,
+ 0x05, 0x16, 0xE5, 0x16, 0xC3, 0x94, 0x14, 0x40,
+/*0CF0*/0xEA, 0xE5, 0xE4, 0x20, 0xE7, 0x28, 0x12, 0x0E,
+ 0x04, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3,
+/*0D00*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
+ 0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40,
+/*0D10*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF,
+ 0x5E, 0x60, 0x03, 0x12, 0x1D, 0xD7, 0xE5, 0x7F,
+/*0D20*/0xC3, 0x94, 0x11, 0x40, 0x14, 0x12, 0x0E, 0x04,
+ 0x75, 0x83, 0xD2, 0xE0, 0x44, 0x80, 0xF0, 0xE5,
+/*0D30*/0xE4, 0x20, 0xE7, 0x0F, 0x12, 0x1D, 0xD7, 0x80,
+ 0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0xD2, 0xE0,
+/*0D40*/0x54, 0x7F, 0xF0, 0x12, 0x1D, 0x23, 0x22, 0x74,
+ 0x8A, 0x85, 0x08, 0x82, 0xF5, 0x83, 0xE5, 0x17,
+/*0D50*/0xF0, 0x12, 0x0E, 0x3A, 0xE4, 0xF0, 0x90, 0x07,
+ 0x02, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x90,
+/*0D60*/0xEF, 0xF0, 0x74, 0x92, 0xFE, 0xE5, 0x08, 0x44,
+ 0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0, 0x54,
+/*0D70*/0xC0, 0xFD, 0x90, 0x07, 0x03, 0xE0, 0x54, 0x3F,
+ 0x4D, 0x8F, 0x82, 0x8E, 0x83, 0xF0, 0x90, 0x07,
+/*0D80*/0x04, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x82,
+ 0xEF, 0xF0, 0x90, 0x07, 0x05, 0xE0, 0xFF, 0xED,
+/*0D90*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xB4, 0xEF,
+ 0x12, 0x0E, 0x03, 0x75, 0x83, 0x80, 0xE0, 0x54,
+/*0DA0*/0xBF, 0xF0, 0x30, 0x37, 0x0A, 0x12, 0x0E, 0x91,
+ 0x75, 0x83, 0x94, 0xE0, 0x44, 0x80, 0xF0, 0x30,
+/*0DB0*/0x38, 0x0A, 0x12, 0x0E, 0x91, 0x75, 0x83, 0x92,
+ 0xE0, 0x44, 0x80, 0xF0, 0xE5, 0x28, 0x30, 0xE4,
+/*0DC0*/0x1A, 0x20, 0x39, 0x0A, 0x12, 0x0E, 0x04, 0x75,
+ 0x83, 0x88, 0xE0, 0x54, 0x7F, 0xF0, 0x20, 0x3A,
+/*0DD0*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x88, 0xE0,
+ 0x54, 0xBF, 0xF0, 0x74, 0x8C, 0xFE, 0x12, 0x0E,
+/*0DE0*/0x04, 0x8E, 0x83, 0xE0, 0x54, 0x0F, 0x12, 0x0E,
+ 0x03, 0x75, 0x83, 0x86, 0xE0, 0x54, 0xBF, 0xF0,
+/*0DF0*/0xE5, 0x08, 0x44, 0x06, 0x12, 0x0D, 0xFD, 0x75,
+ 0x83, 0x8A, 0xE4, 0xF0, 0x22, 0xF5, 0x82, 0x75,
+/*0E00*/0x83, 0x82, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07,
+ 0xF5, 0x82, 0x22, 0x8E, 0x83, 0xE0, 0xF5, 0x10,
+/*0E10*/0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44, 0x01, 0xFF,
+ 0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07, 0xF5, 0x82,
+/*0E20*/0x22, 0xE5, 0x15, 0xC4, 0x54, 0x07, 0xFF, 0xE5,
+ 0x08, 0xFD, 0xED, 0x44, 0x08, 0xF5, 0x82, 0x75,
+/*0E30*/0x83, 0x82, 0x22, 0x75, 0x83, 0x80, 0xE0, 0x44,
+ 0x40, 0xF0, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82,
+/*0E40*/0x75, 0x83, 0x8A, 0x22, 0xE5, 0x16, 0x25, 0xE0,
+ 0x25, 0xE0, 0x24, 0xAF, 0xF5, 0x82, 0xE4, 0x34,
+/*0E50*/0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0D, 0x22,
+ 0x43, 0xE1, 0x10, 0x43, 0xE1, 0x80, 0x53, 0xE1,
+/*0E60*/0xFD, 0x85, 0xE1, 0x10, 0x22, 0xE5, 0x16, 0x25,
+ 0xE0, 0x25, 0xE0, 0x24, 0xB2, 0xF5, 0x82, 0xE4,
+/*0E70*/0x34, 0x1A, 0xF5, 0x83, 0xE4, 0x93, 0x22, 0x85,
+ 0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15, 0xF0,
+/*0E80*/0x22, 0xE5, 0xE2, 0x54, 0x20, 0xD3, 0x94, 0x00,
+ 0x22, 0xE5, 0xE2, 0x54, 0x40, 0xD3, 0x94, 0x00,
+/*0E90*/0x22, 0xE5, 0x08, 0x44, 0x06, 0xF5, 0x82, 0x22,
+ 0xFD, 0xE5, 0x08, 0xFB, 0xEB, 0x44, 0x07, 0xF5,
+/*0EA0*/0x82, 0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFE, 0x30,
+ 0x22, 0xEF, 0x4E, 0x70, 0x26, 0x12, 0x07, 0xCC,
+/*0EB0*/0xE0, 0xFD, 0x90, 0x07, 0x26, 0x12, 0x07, 0x7B,
+ 0x12, 0x07, 0xD8, 0xE0, 0xFD, 0x90, 0x07, 0x28,
+/*0EC0*/0x12, 0x07, 0x7B, 0x12, 0x08, 0x81, 0x12, 0x07,
+ 0x72, 0x12, 0x08, 0x35, 0xE0, 0x90, 0x07, 0x24,
+/*0ED0*/0x12, 0x07, 0x78, 0xEF, 0x64, 0x04, 0x4E, 0x70,
+ 0x29, 0x12, 0x07, 0xE4, 0xE0, 0xFD, 0x90, 0x07,
+/*0EE0*/0x26, 0x12, 0x07, 0x7B, 0x12, 0x07, 0xF0, 0xE0,
+ 0xFD, 0x90, 0x07, 0x28, 0x12, 0x07, 0x7B, 0x12,
+/*0EF0*/0x08, 0x8B, 0x12, 0x07, 0x72, 0x12, 0x08, 0x41,
+ 0xE0, 0x54, 0x1F, 0xFD, 0x90, 0x07, 0x24, 0x12,
+/*0F00*/0x07, 0x7B, 0xEF, 0x64, 0x01, 0x4E, 0x70, 0x04,
+ 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0xEF, 0x64,
+/*0F10*/0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02,
+ 0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x35, 0x12, 0x07,
+/*0F20*/0xFC, 0xE0, 0xFF, 0x90, 0x07, 0x26, 0x12, 0x07,
+ 0x89, 0xEF, 0xF0, 0x12, 0x08, 0x08, 0xE0, 0xFF,
+/*0F30*/0x90, 0x07, 0x28, 0x12, 0x07, 0x89, 0xEF, 0xF0,
+ 0x12, 0x08, 0x4D, 0xE0, 0x54, 0x1F, 0xFF, 0x12,
+/*0F40*/0x07, 0x86, 0xEF, 0xF0, 0x12, 0x08, 0x59, 0xE0,
+ 0x54, 0x1F, 0xFF, 0x90, 0x07, 0x24, 0x12, 0x07,
+/*0F50*/0x89, 0xEF, 0xF0, 0x22, 0xE4, 0xF5, 0x53, 0x12,
+ 0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
+/*0F60*/0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40, 0x04, 0x7E,
+ 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x70,
+/*0F70*/0x03, 0x02, 0x0F, 0xF6, 0x85, 0xE1, 0x10, 0x43,
+ 0xE1, 0x02, 0x53, 0xE1, 0x0F, 0x85, 0xE1, 0x10,
+/*0F80*/0xE4, 0xF5, 0x51, 0xE5, 0xE3, 0x54, 0x3F, 0xF5,
+ 0x52, 0x12, 0x0E, 0x89, 0x40, 0x1D, 0xAD, 0x52,
+/*0F90*/0xAF, 0x51, 0x12, 0x11, 0x18, 0xEF, 0x60, 0x08,
+ 0x85, 0xE1, 0x10, 0x43, 0xE1, 0x40, 0x80, 0x0B,
+/*0FA0*/0x53, 0xE1, 0xBF, 0x12, 0x0E, 0x58, 0x12, 0x00,
+ 0x06, 0x80, 0xFB, 0xE5, 0xE3, 0x54, 0x3F, 0xF5,
+/*0FB0*/0x51, 0xE5, 0xE4, 0x54, 0x3F, 0xF5, 0x52, 0x12,
+ 0x0E, 0x81, 0x40, 0x1D, 0xAD, 0x52, 0xAF, 0x51,
+/*0FC0*/0x12, 0x11, 0x18, 0xEF, 0x60, 0x08, 0x85, 0xE1,
+ 0x10, 0x43, 0xE1, 0x20, 0x80, 0x0B, 0x53, 0xE1,
+/*0FD0*/0xDF, 0x12, 0x0E, 0x58, 0x12, 0x00, 0x06, 0x80,
+ 0xFB, 0x12, 0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01,
+/*0FE0*/0x80, 0x02, 0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40,
+ 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE,
+/*0FF0*/0x4F, 0x60, 0x03, 0x12, 0x0E, 0x5B, 0x22, 0x12,
+ 0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x22,
+/*1000*/0x02, 0x11, 0x00, 0x02, 0x10, 0x40, 0x02, 0x10,
+ 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1010*/0x01, 0x20, 0x01, 0x20, 0xE4, 0xF5, 0x57, 0x12,
+ 0x16, 0xBD, 0x12, 0x16, 0x44, 0xE4, 0x12, 0x10,
+/*1020*/0x56, 0x12, 0x14, 0xB7, 0x90, 0x07, 0x26, 0x12,
+ 0x07, 0x35, 0xE4, 0x12, 0x07, 0x31, 0xE4, 0xF0,
+/*1030*/0x12, 0x10, 0x56, 0x12, 0x14, 0xB7, 0x90, 0x07,
+ 0x26, 0x12, 0x07, 0x35, 0xE5, 0x41, 0x12, 0x07,
+/*1040*/0x31, 0xE5, 0x40, 0xF0, 0xAF, 0x57, 0x7E, 0x00,
+ 0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF,
+/*1050*/0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xFF, 0x90,
+ 0x07, 0x20, 0xA3, 0xE0, 0xFD, 0xE4, 0xF5, 0x56,
+/*1060*/0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x12,
+ 0x11, 0x51, 0x7F, 0x0F, 0x7D, 0x18, 0xE4, 0xF5,
+/*1070*/0x56, 0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA,
+ 0x12, 0x15, 0x41, 0xAF, 0x56, 0x7E, 0x00, 0x12,
+/*1080*/0x1A, 0xFF, 0xE4, 0xFF, 0xF5, 0x56, 0x7D, 0x1F,
+ 0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x22,
+/*1090*/0x22, 0xE4, 0xF5, 0x55, 0xE5, 0x08, 0xFD, 0x74,
+ 0xA0, 0xF5, 0x56, 0xED, 0x44, 0x07, 0xF5, 0x57,
+/*10A0*/0xE5, 0x28, 0x30, 0xE5, 0x03, 0xD3, 0x80, 0x01,
+ 0xC3, 0x40, 0x05, 0x7F, 0x28, 0xEF, 0x80, 0x04,
+/*10B0*/0x7F, 0x14, 0xEF, 0xC3, 0x13, 0xF5, 0x54, 0xE4,
+ 0xF9, 0x12, 0x0E, 0x18, 0x75, 0x83, 0x8E, 0xE0,
+/*10C0*/0xF5, 0x10, 0xCE, 0xEF, 0xCE, 0xEE, 0xD3, 0x94,
+ 0x00, 0x40, 0x26, 0xE5, 0x10, 0x54, 0xFE, 0x12,
+/*10D0*/0x0E, 0x98, 0x75, 0x83, 0x8E, 0xED, 0xF0, 0xE5,
+ 0x10, 0x44, 0x01, 0xFD, 0xEB, 0x44, 0x07, 0xF5,
+/*10E0*/0x82, 0xED, 0xF0, 0x85, 0x57, 0x82, 0x85, 0x56,
+ 0x83, 0xE0, 0x30, 0xE3, 0x01, 0x09, 0x1E, 0x80,
+/*10F0*/0xD4, 0xC2, 0x34, 0xE9, 0xC3, 0x95, 0x54, 0x40,
+ 0x02, 0xD2, 0x34, 0x22, 0x02, 0x00, 0x06, 0x22,
+/*1100*/0x30, 0x30, 0x11, 0x90, 0x10, 0x00, 0xE4, 0x93,
+ 0xF5, 0x10, 0x90, 0x10, 0x10, 0xE4, 0x93, 0xF5,
+/*1110*/0x10, 0x12, 0x10, 0x90, 0x12, 0x11, 0x50, 0x22,
+ 0xE4, 0xFC, 0xC3, 0xED, 0x9F, 0xFA, 0xEF, 0xF5,
+/*1120*/0x83, 0x75, 0x82, 0x00, 0x79, 0xFF, 0xE4, 0x93,
+ 0xCC, 0x6C, 0xCC, 0xA3, 0xD9, 0xF8, 0xDA, 0xF6,
+/*1130*/0xE5, 0xE2, 0x30, 0xE4, 0x02, 0x8C, 0xE5, 0xED,
+ 0x24, 0xFF, 0xFF, 0xEF, 0x75, 0x82, 0xFF, 0xF5,
+/*1140*/0x83, 0xE4, 0x93, 0x6C, 0x70, 0x03, 0x7F, 0x01,
+ 0x22, 0x7F, 0x00, 0x22, 0x22, 0x11, 0x00, 0x00,
+/*1150*/0x22, 0x8E, 0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D,
+ 0x5B, 0x8A, 0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01,
+/*1160*/0xE4, 0xF5, 0x5F, 0xF5, 0x60, 0xF5, 0x62, 0x12,
+ 0x07, 0x2A, 0x75, 0x83, 0xD0, 0xE0, 0xFF, 0xC4,
+/*1170*/0x54, 0x0F, 0xF5, 0x61, 0x12, 0x1E, 0xA5, 0x85,
+ 0x59, 0x5E, 0xD3, 0xE5, 0x5E, 0x95, 0x5B, 0xE5,
+/*1180*/0x5A, 0x12, 0x07, 0x6B, 0x50, 0x4B, 0x12, 0x07,
+ 0x03, 0x75, 0x83, 0xBC, 0xE0, 0x45, 0x5E, 0x12,
+/*1190*/0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x45, 0x5E,
+ 0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0, 0x45,
+/*11A0*/0x5E, 0xF0, 0xAF, 0x5F, 0xE5, 0x60, 0x12, 0x08,
+ 0x78, 0x12, 0x0A, 0xFF, 0xAF, 0x62, 0x7E, 0x00,
+/*11B0*/0xAD, 0x5D, 0xAC, 0x5C, 0x12, 0x04, 0x44, 0xE5,
+ 0x61, 0xAF, 0x5E, 0x7E, 0x00, 0xB4, 0x03, 0x05,
+/*11C0*/0x12, 0x1E, 0x21, 0x80, 0x07, 0xAD, 0x5D, 0xAC,
+ 0x5C, 0x12, 0x13, 0x17, 0x05, 0x5E, 0x02, 0x11,
+/*11D0*/0x7A, 0x12, 0x07, 0x03, 0x75, 0x83, 0xBC, 0xE0,
+ 0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBE,
+/*11E0*/0xE0, 0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83,
+ 0xC0, 0xE0, 0x45, 0x40, 0xF0, 0x22, 0x8E, 0x58,
+/*11F0*/0x8F, 0x59, 0x75, 0x5A, 0x01, 0x79, 0x01, 0x75,
+ 0x5B, 0x01, 0xE4, 0xFB, 0x12, 0x07, 0x2A, 0x75,
+/*1200*/0x83, 0xAE, 0xE0, 0x54, 0x1A, 0xFF, 0x12, 0x08,
+ 0x65, 0xE0, 0xC4, 0x13, 0x54, 0x07, 0xFE, 0xEF,
+/*1210*/0x70, 0x0C, 0xEE, 0x65, 0x35, 0x70, 0x07, 0x90,
+ 0x07, 0x2F, 0xE0, 0xB4, 0x01, 0x0D, 0xAF, 0x35,
+/*1220*/0x7E, 0x00, 0x12, 0x0E, 0xA9, 0xCF, 0xEB, 0xCF,
+ 0x02, 0x1E, 0x60, 0xE5, 0x59, 0x64, 0x02, 0x45,
+/*1230*/0x58, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F,
+ 0x00, 0xE5, 0x59, 0x45, 0x58, 0x70, 0x04, 0x7E,
+/*1240*/0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60,
+ 0x23, 0x85, 0x41, 0x49, 0x85, 0x40, 0x4B, 0xE5,
+/*1250*/0x59, 0x45, 0x58, 0x70, 0x2C, 0xAF, 0x5A, 0xFE,
+ 0xCD, 0xE9, 0xCD, 0xFC, 0xAB, 0x59, 0xAA, 0x58,
+/*1260*/0x12, 0x0A, 0xFF, 0xAF, 0x5B, 0x7E, 0x00, 0x12,
+ 0x1E, 0x60, 0x80, 0x15, 0xAF, 0x5B, 0x7E, 0x00,
+/*1270*/0x12, 0x1E, 0x60, 0x90, 0x07, 0x26, 0x12, 0x07,
+ 0x35, 0xE5, 0x49, 0x12, 0x07, 0x31, 0xE5, 0x4B,
+/*1280*/0xF0, 0xE4, 0xFD, 0xAF, 0x35, 0xFE, 0xFC, 0x12,
+ 0x09, 0x15, 0x22, 0x8C, 0x64, 0x8D, 0x65, 0x12,
+/*1290*/0x08, 0xDA, 0x40, 0x3C, 0xE5, 0x65, 0x45, 0x64,
+ 0x70, 0x10, 0x12, 0x09, 0x04, 0xC3, 0xE5, 0x3E,
+/*12A0*/0x12, 0x07, 0x69, 0x40, 0x3B, 0x12, 0x08, 0x95,
+ 0x80, 0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40,
+/*12B0*/0x1D, 0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05,
+ 0x85, 0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39,
+/*12C0*/0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3E, 0x12,
+ 0x07, 0x53, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x3B,
+/*12D0*/0xE5, 0x65, 0x45, 0x64, 0x70, 0x11, 0x12, 0x07,
+ 0x5F, 0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x1F,
+/*12E0*/0x12, 0x07, 0x3E, 0xE5, 0x41, 0xF0, 0x22, 0xE5,
+ 0x3C, 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C,
+/*12F0*/0x38, 0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39,
+ 0x80, 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12,
+/*1300*/0x07, 0xA8, 0xE5, 0x3C, 0x12, 0x07, 0x53, 0xE5,
+ 0x3D, 0xF0, 0x22, 0x12, 0x07, 0x9F, 0xE5, 0x38,
+/*1310*/0x12, 0x07, 0x53, 0xE5, 0x39, 0xF0, 0x22, 0x8C,
+ 0x63, 0x8D, 0x64, 0x12, 0x08, 0xDA, 0x40, 0x3C,
+/*1320*/0xE5, 0x64, 0x45, 0x63, 0x70, 0x10, 0x12, 0x09,
+ 0x04, 0xC3, 0xE5, 0x3E, 0x12, 0x07, 0x69, 0x40,
+/*1330*/0x3B, 0x12, 0x08, 0x95, 0x80, 0x18, 0xE5, 0x3E,
+ 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3E, 0x38,
+/*1340*/0xE5, 0x3E, 0x60, 0x05, 0x85, 0x3F, 0x39, 0x80,
+ 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x07,
+/*1350*/0xA8, 0xE5, 0x3E, 0x12, 0x07, 0x53, 0xE5, 0x3F,
+ 0xF0, 0x22, 0x80, 0x3B, 0xE5, 0x64, 0x45, 0x63,
+/*1360*/0x70, 0x11, 0x12, 0x07, 0x5F, 0x40, 0x05, 0x12,
+ 0x08, 0x9E, 0x80, 0x1F, 0x12, 0x07, 0x3E, 0xE5,
+/*1370*/0x41, 0xF0, 0x22, 0xE5, 0x3C, 0xC3, 0x95, 0x38,
+ 0x40, 0x1D, 0x85, 0x3C, 0x38, 0xE5, 0x3C, 0x60,
+/*1380*/0x05, 0x85, 0x3D, 0x39, 0x80, 0x03, 0x85, 0x39,
+ 0x39, 0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3C,
+/*1390*/0x12, 0x07, 0x53, 0xE5, 0x3D, 0xF0, 0x22, 0x12,
+ 0x07, 0x9F, 0xE5, 0x38, 0x12, 0x07, 0x53, 0xE5,
+/*13A0*/0x39, 0xF0, 0x22, 0xE5, 0x0D, 0xFE, 0xE5, 0x08,
+ 0x8E, 0x54, 0x44, 0x05, 0xF5, 0x55, 0x75, 0x15,
+/*13B0*/0x0F, 0xF5, 0x82, 0x12, 0x0E, 0x7A, 0x12, 0x17,
+ 0xA3, 0x20, 0x31, 0x05, 0x75, 0x15, 0x03, 0x80,
+/*13C0*/0x03, 0x75, 0x15, 0x0B, 0xE5, 0x0A, 0xC3, 0x94,
+ 0x01, 0x50, 0x38, 0x12, 0x14, 0x20, 0x20, 0x31,
+/*13D0*/0x06, 0x05, 0x15, 0x05, 0x15, 0x80, 0x04, 0x15,
+ 0x15, 0x15, 0x15, 0xE5, 0x0A, 0xC3, 0x94, 0x01,
+/*13E0*/0x50, 0x21, 0x12, 0x14, 0x20, 0x20, 0x31, 0x04,
+ 0x05, 0x15, 0x80, 0x02, 0x15, 0x15, 0xE5, 0x0A,
+/*13F0*/0xC3, 0x94, 0x01, 0x50, 0x0E, 0x12, 0x0E, 0x77,
+ 0x12, 0x17, 0xA3, 0x20, 0x31, 0x05, 0x05, 0x15,
+/*1400*/0x12, 0x0E, 0x77, 0xE5, 0x15, 0xB4, 0x08, 0x04,
+ 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x15,
+/*1410*/0xB4, 0x07, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E,
+ 0x00, 0xEE, 0x4F, 0x60, 0x02, 0x05, 0x7F, 0x22,
+/*1420*/0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15,
+ 0xF0, 0x12, 0x17, 0xA3, 0x22, 0x12, 0x07, 0x2A,
+/*1430*/0x75, 0x83, 0xAE, 0x74, 0xFF, 0x12, 0x07, 0x29,
+ 0xE0, 0x54, 0x1A, 0xF5, 0x34, 0xE0, 0xC4, 0x13,
+/*1440*/0x54, 0x07, 0xF5, 0x35, 0x24, 0xFE, 0x60, 0x24,
+ 0x24, 0xFE, 0x60, 0x3C, 0x24, 0x04, 0x70, 0x63,
+/*1450*/0x75, 0x31, 0x2D, 0xE5, 0x08, 0xFD, 0x74, 0xB6,
+ 0x12, 0x07, 0x92, 0x74, 0xBC, 0x90, 0x07, 0x22,
+/*1460*/0x12, 0x07, 0x95, 0x74, 0x90, 0x12, 0x07, 0xB3,
+ 0x74, 0x92, 0x80, 0x3C, 0x75, 0x31, 0x3A, 0xE5,
+/*1470*/0x08, 0xFD, 0x74, 0xBA, 0x12, 0x07, 0x92, 0x74,
+ 0xC0, 0x90, 0x07, 0x22, 0x12, 0x07, 0xB6, 0x74,
+/*1480*/0xC4, 0x12, 0x07, 0xB3, 0x74, 0xC8, 0x80, 0x20,
+ 0x75, 0x31, 0x35, 0xE5, 0x08, 0xFD, 0x74, 0xB8,
+/*1490*/0x12, 0x07, 0x92, 0x74, 0xBE, 0xFF, 0xED, 0x44,
+ 0x07, 0x90, 0x07, 0x22, 0xCF, 0xF0, 0xA3, 0xEF,
+/*14A0*/0xF0, 0x74, 0xC2, 0x12, 0x07, 0xB3, 0x74, 0xC6,
+ 0xFF, 0xED, 0x44, 0x07, 0xA3, 0xCF, 0xF0, 0xA3,
+/*14B0*/0xEF, 0xF0, 0x22, 0x75, 0x34, 0x01, 0x22, 0x8E,
+ 0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D, 0x5B, 0x8A,
+/*14C0*/0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01, 0xE4, 0xF5,
+ 0x5F, 0x12, 0x1E, 0xA5, 0x85, 0x59, 0x5E, 0xD3,
+/*14D0*/0xE5, 0x5E, 0x95, 0x5B, 0xE5, 0x5A, 0x12, 0x07,
+ 0x6B, 0x50, 0x57, 0xE5, 0x5D, 0x45, 0x5C, 0x70,
+/*14E0*/0x30, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x92, 0xE5,
+ 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC6, 0xE5,
+/*14F0*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8, 0xE5,
+ 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0x90, 0xE5,
+/*1500*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5,
+ 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x80,
+/*1510*/0x03, 0x12, 0x07, 0x32, 0xE5, 0x5E, 0xF0, 0xAF,
+ 0x5F, 0x7E, 0x00, 0xAD, 0x5D, 0xAC, 0x5C, 0x12,
+/*1520*/0x04, 0x44, 0xAF, 0x5E, 0x7E, 0x00, 0xAD, 0x5D,
+ 0xAC, 0x5C, 0x12, 0x0B, 0xD1, 0x05, 0x5E, 0x02,
+/*1530*/0x14, 0xCF, 0xAB, 0x5D, 0xAA, 0x5C, 0xAD, 0x5B,
+ 0xAC, 0x5A, 0xAF, 0x59, 0xAE, 0x58, 0x02, 0x1B,
+/*1540*/0xFB, 0x8C, 0x5C, 0x8D, 0x5D, 0x8A, 0x5E, 0x8B,
+ 0x5F, 0x75, 0x60, 0x01, 0xE4, 0xF5, 0x61, 0xF5,
+/*1550*/0x62, 0xF5, 0x63, 0x12, 0x1E, 0xA5, 0x8F, 0x60,
+ 0xD3, 0xE5, 0x60, 0x95, 0x5D, 0xE5, 0x5C, 0x12,
+/*1560*/0x07, 0x6B, 0x50, 0x61, 0xE5, 0x5F, 0x45, 0x5E,
+ 0x70, 0x27, 0x12, 0x07, 0x2A, 0x75, 0x83, 0xB6,
+/*1570*/0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xB8,
+ 0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBA,
+/*1580*/0xE5, 0x60, 0xF0, 0xAF, 0x61, 0x7E, 0x00, 0xE5,
+ 0x62, 0x12, 0x08, 0x7A, 0x12, 0x0A, 0xFF, 0x80,
+/*1590*/0x19, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE5,
+ 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0x8E, 0xE4,
+/*15A0*/0x12, 0x07, 0x29, 0x74, 0x01, 0x12, 0x07, 0x29,
+ 0xE4, 0xF0, 0xAF, 0x63, 0x7E, 0x00, 0xAD, 0x5F,
+/*15B0*/0xAC, 0x5E, 0x12, 0x04, 0x44, 0xAF, 0x60, 0x7E,
+ 0x00, 0xAD, 0x5F, 0xAC, 0x5E, 0x12, 0x12, 0x8B,
+/*15C0*/0x05, 0x60, 0x02, 0x15, 0x58, 0x22, 0x90, 0x11,
+ 0x4D, 0xE4, 0x93, 0x90, 0x07, 0x2E, 0xF0, 0x12,
+/*15D0*/0x08, 0x1F, 0x75, 0x83, 0xAE, 0xE0, 0x54, 0x1A,
+ 0xF5, 0x34, 0x70, 0x67, 0xEF, 0x44, 0x07, 0xF5,
+/*15E0*/0x82, 0x75, 0x83, 0xCE, 0xE0, 0xFF, 0x13, 0x13,
+ 0x13, 0x54, 0x07, 0xF5, 0x36, 0x54, 0x0F, 0xD3,
+/*15F0*/0x94, 0x00, 0x40, 0x06, 0x12, 0x14, 0x2D, 0x12,
+ 0x1B, 0xA9, 0xE5, 0x36, 0x54, 0x0F, 0x24, 0xFE,
+/*1600*/0x60, 0x0C, 0x14, 0x60, 0x0C, 0x14, 0x60, 0x19,
+ 0x24, 0x03, 0x70, 0x37, 0x80, 0x10, 0x02, 0x1E,
+/*1610*/0x91, 0x12, 0x1E, 0x91, 0x12, 0x07, 0x2A, 0x75,
+ 0x83, 0xCE, 0xE0, 0x54, 0xEF, 0xF0, 0x02, 0x1D,
+/*1620*/0xAE, 0x12, 0x10, 0x14, 0xE4, 0xF5, 0x55, 0x12,
+ 0x1D, 0x85, 0x05, 0x55, 0xE5, 0x55, 0xC3, 0x94,
+/*1630*/0x05, 0x40, 0xF4, 0x12, 0x07, 0x2A, 0x75, 0x83,
+ 0xCE, 0xE0, 0x54, 0xC7, 0x12, 0x07, 0x29, 0xE0,
+/*1640*/0x44, 0x08, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5,
+ 0x59, 0xAF, 0x08, 0xEF, 0x44, 0x07, 0xF5, 0x82,
+/*1650*/0x75, 0x83, 0xD0, 0xE0, 0xFD, 0xC4, 0x54, 0x0F,
+ 0xF5, 0x5A, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0x75,
+/*1660*/0x83, 0x80, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x21,
+ 0x75, 0x83, 0x82, 0xE5, 0x45, 0xF0, 0xEF, 0x44,
+/*1670*/0x07, 0xF5, 0x82, 0x75, 0x83, 0x8A, 0x74, 0xFF,
+ 0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x07, 0x2A, 0x75,
+/*1680*/0x83, 0xBC, 0xE0, 0x54, 0xEF, 0x12, 0x07, 0x29,
+ 0x75, 0x83, 0xBE, 0xE0, 0x54, 0xEF, 0x12, 0x07,
+/*1690*/0x29, 0x75, 0x83, 0xC0, 0xE0, 0x54, 0xEF, 0x12,
+ 0x07, 0x29, 0x75, 0x83, 0xBC, 0xE0, 0x44, 0x10,
+/*16A0*/0x12, 0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x44,
+ 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0,
+/*16B0*/0x44, 0x10, 0xF0, 0xAF, 0x58, 0xE5, 0x59, 0x12,
+ 0x08, 0x78, 0x02, 0x0A, 0xFF, 0xE4, 0xF5, 0x58,
+/*16C0*/0x7D, 0x01, 0xF5, 0x59, 0xAF, 0x35, 0xFE, 0xFC,
+ 0x12, 0x09, 0x15, 0x12, 0x07, 0x2A, 0x75, 0x83,
+/*16D0*/0xB6, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
+ 0xB8, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
+/*16E0*/0xBA, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
+ 0xBC, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
+/*16F0*/0xBE, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
+ 0xC0, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
+/*1700*/0x90, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2,
+ 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4,
+/*1710*/0x12, 0x07, 0x29, 0x75, 0x83, 0x92, 0xE4, 0x12,
+ 0x07, 0x29, 0x75, 0x83, 0xC6, 0xE4, 0x12, 0x07,
+/*1720*/0x29, 0x75, 0x83, 0xC8, 0xE4, 0xF0, 0xAF, 0x58,
+ 0xFE, 0xE5, 0x59, 0x12, 0x08, 0x7A, 0x02, 0x0A,
+/*1730*/0xFF, 0xE5, 0xE2, 0x30, 0xE4, 0x6C, 0xE5, 0xE7,
+ 0x54, 0xC0, 0x64, 0x40, 0x70, 0x64, 0xE5, 0x09,
+/*1740*/0xC4, 0x54, 0x30, 0xFE, 0xE5, 0x08, 0x25, 0xE0,
+ 0x25, 0xE0, 0x54, 0xC0, 0x4E, 0xFE, 0xEF, 0x54,
+/*1750*/0x3F, 0x4E, 0xFD, 0xE5, 0x2B, 0xAE, 0x2A, 0x78,
+ 0x02, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9,
+/*1760*/0xF5, 0x82, 0x8E, 0x83, 0xED, 0xF0, 0xE5, 0x2B,
+ 0xAE, 0x2A, 0x78, 0x02, 0xC3, 0x33, 0xCE, 0x33,
+/*1770*/0xCE, 0xD8, 0xF9, 0xFF, 0xF5, 0x82, 0x8E, 0x83,
+ 0xA3, 0xE5, 0xFE, 0xF0, 0x8F, 0x82, 0x8E, 0x83,
+/*1780*/0xA3, 0xA3, 0xE5, 0xFD, 0xF0, 0x8F, 0x82, 0x8E,
+ 0x83, 0xA3, 0xA3, 0xA3, 0xE5, 0xFC, 0xF0, 0xC3,
+/*1790*/0xE5, 0x2B, 0x94, 0xFA, 0xE5, 0x2A, 0x94, 0x00,
+ 0x50, 0x08, 0x05, 0x2B, 0xE5, 0x2B, 0x70, 0x02,
+/*17A0*/0x05, 0x2A, 0x22, 0xE4, 0xFF, 0xE4, 0xF5, 0x58,
+ 0xF5, 0x56, 0xF5, 0x57, 0x74, 0x82, 0xFC, 0x12,
+/*17B0*/0x0E, 0x04, 0x8C, 0x83, 0xE0, 0xF5, 0x10, 0x54,
+ 0x7F, 0xF0, 0xE5, 0x10, 0x44, 0x80, 0x12, 0x0E,
+/*17C0*/0x98, 0xED, 0xF0, 0x7E, 0x0A, 0x12, 0x0E, 0x04,
+ 0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0, 0x26, 0xDE,
+/*17D0*/0xF4, 0x05, 0x57, 0xE5, 0x57, 0x70, 0x02, 0x05,
+ 0x56, 0xE5, 0x14, 0x24, 0x01, 0xFD, 0xE4, 0x33,
+/*17E0*/0xFC, 0xD3, 0xE5, 0x57, 0x9D, 0xE5, 0x56, 0x9C,
+ 0x40, 0xD9, 0xE5, 0x0A, 0x94, 0x20, 0x50, 0x02,
+/*17F0*/0x05, 0x0A, 0x43, 0xE1, 0x08, 0xC2, 0x31, 0x12,
+ 0x0E, 0x04, 0x75, 0x83, 0xA6, 0xE0, 0x55, 0x12,
+/*1800*/0x65, 0x12, 0x70, 0x03, 0xD2, 0x31, 0x22, 0xC2,
+ 0x31, 0x22, 0x90, 0x07, 0x26, 0xE0, 0xFA, 0xA3,
+/*1810*/0xE0, 0xF5, 0x82, 0x8A, 0x83, 0xE0, 0xF5, 0x41,
+ 0xE5, 0x39, 0xC3, 0x95, 0x41, 0x40, 0x26, 0xE5,
+/*1820*/0x39, 0x95, 0x41, 0xC3, 0x9F, 0xEE, 0x12, 0x07,
+ 0x6B, 0x40, 0x04, 0x7C, 0x01, 0x80, 0x02, 0x7C,
+/*1830*/0x00, 0xE5, 0x41, 0x64, 0x3F, 0x60, 0x04, 0x7B,
+ 0x01, 0x80, 0x02, 0x7B, 0x00, 0xEC, 0x5B, 0x60,
+/*1840*/0x29, 0x05, 0x41, 0x80, 0x28, 0xC3, 0xE5, 0x41,
+ 0x95, 0x39, 0xC3, 0x9F, 0xEE, 0x12, 0x07, 0x6B,
+/*1850*/0x40, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00,
+ 0xE5, 0x41, 0x60, 0x04, 0x7E, 0x01, 0x80, 0x02,
+/*1860*/0x7E, 0x00, 0xEF, 0x5E, 0x60, 0x04, 0x15, 0x41,
+ 0x80, 0x03, 0x85, 0x39, 0x41, 0x85, 0x3A, 0x40,
+/*1870*/0x22, 0xE5, 0xE2, 0x30, 0xE4, 0x60, 0xE5, 0xE1,
+ 0x30, 0xE2, 0x5B, 0xE5, 0x09, 0x70, 0x04, 0x7F,
+/*1880*/0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x08, 0x70,
+ 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE,
+/*1890*/0x5F, 0x60, 0x43, 0x53, 0xF9, 0xF8, 0xE5, 0xE2,
+ 0x30, 0xE4, 0x3B, 0xE5, 0xE1, 0x30, 0xE2, 0x2E,
+/*18A0*/0x43, 0xFA, 0x02, 0x53, 0xFA, 0xFB, 0xE4, 0xF5,
+ 0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0xE5,
+/*18B0*/0xE1, 0x30, 0xE2, 0xE7, 0x90, 0x94, 0x70, 0xE0,
+ 0x65, 0x10, 0x60, 0x03, 0x43, 0xFA, 0x04, 0x05,
+/*18C0*/0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0x70,
+ 0xE6, 0x12, 0x00, 0x06, 0x80, 0xE1, 0x53, 0xFA,
+/*18D0*/0xFD, 0x53, 0xFA, 0xFB, 0x80, 0xC0, 0x22, 0x8F,
+ 0x54, 0x12, 0x00, 0x06, 0xE5, 0xE1, 0x30, 0xE0,
+/*18E0*/0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5,
+ 0x7E, 0xD3, 0x94, 0x05, 0x40, 0x04, 0x7E, 0x01,
+/*18F0*/0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60, 0x3D,
+ 0x85, 0x54, 0x11, 0xE5, 0xE2, 0x20, 0xE1, 0x32,
+/*1900*/0x74, 0xCE, 0x12, 0x1A, 0x05, 0x30, 0xE7, 0x04,
+ 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0x8F, 0x82,
+/*1910*/0x8E, 0x83, 0xE0, 0x30, 0xE6, 0x04, 0x7F, 0x01,
+ 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x5D, 0x70, 0x15,
+/*1920*/0x12, 0x15, 0xC6, 0x74, 0xCE, 0x12, 0x1A, 0x05,
+ 0x30, 0xE6, 0x07, 0xE0, 0x44, 0x80, 0xF0, 0x43,
+/*1930*/0xF9, 0x80, 0x12, 0x18, 0x71, 0x22, 0x12, 0x0E,
+ 0x44, 0xE5, 0x16, 0x25, 0xE0, 0x25, 0xE0, 0x24,
+/*1940*/0xB0, 0xF5, 0x82, 0xE4, 0x34, 0x1A, 0xF5, 0x83,
+ 0xE4, 0x93, 0xF5, 0x0F, 0xE5, 0x16, 0x25, 0xE0,
+/*1950*/0x25, 0xE0, 0x24, 0xB1, 0xF5, 0x82, 0xE4, 0x34,
+ 0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0E, 0x12,
+/*1960*/0x0E, 0x65, 0xF5, 0x10, 0xE5, 0x0F, 0x54, 0xF0,
+ 0x12, 0x0E, 0x17, 0x75, 0x83, 0x8C, 0xEF, 0xF0,
+/*1970*/0xE5, 0x0F, 0x30, 0xE0, 0x0C, 0x12, 0x0E, 0x04,
+ 0x75, 0x83, 0x86, 0xE0, 0x44, 0x40, 0xF0, 0x80,
+/*1980*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x86, 0xE0,
+ 0x54, 0xBF, 0xF0, 0x12, 0x0E, 0x91, 0x75, 0x83,
+/*1990*/0x82, 0xE5, 0x0E, 0xF0, 0x22, 0x7F, 0x05, 0x12,
+ 0x17, 0x31, 0x12, 0x0E, 0x04, 0x12, 0x0E, 0x33,
+/*19A0*/0x74, 0x02, 0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E,
+ 0x04, 0x12, 0x0E, 0x0B, 0xEF, 0xF0, 0x75, 0x15,
+/*19B0*/0x70, 0x12, 0x0F, 0xF7, 0x20, 0x34, 0x05, 0x75,
+ 0x15, 0x10, 0x80, 0x03, 0x75, 0x15, 0x50, 0x12,
+/*19C0*/0x0F, 0xF7, 0x20, 0x34, 0x04, 0x74, 0x10, 0x80,
+ 0x02, 0x74, 0xF0, 0x25, 0x15, 0xF5, 0x15, 0x12,
+/*19D0*/0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x20,
+ 0x34, 0x17, 0xE5, 0x15, 0x64, 0x30, 0x60, 0x0C,
+/*19E0*/0x74, 0x10, 0x25, 0x15, 0xF5, 0x15, 0xB4, 0x80,
+ 0x03, 0xE4, 0xF5, 0x15, 0x12, 0x0E, 0x21, 0xEF,
+/*19F0*/0xF0, 0x22, 0xF0, 0xE5, 0x0B, 0x25, 0xE0, 0x25,
+ 0xE0, 0x24, 0x82, 0xF5, 0x82, 0xE4, 0x34, 0x07,
+/*1A00*/0xF5, 0x83, 0x22, 0x74, 0x88, 0xFE, 0xE5, 0x08,
+ 0x44, 0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0,
+/*1A10*/0x22, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82,
+ 0x22, 0xF0, 0xE0, 0x54, 0xC0, 0x8F, 0x82, 0x8E,
+/*1A20*/0x83, 0xF0, 0x22, 0xEF, 0x44, 0x07, 0xF5, 0x82,
+ 0x75, 0x83, 0x86, 0xE0, 0x54, 0x10, 0xD3, 0x94,
+/*1A30*/0x00, 0x22, 0xF0, 0x90, 0x07, 0x15, 0xE0, 0x04,
+ 0xF0, 0x22, 0x44, 0x06, 0xF5, 0x82, 0x75, 0x83,
+/*1A40*/0x9E, 0xE0, 0x22, 0xFE, 0xEF, 0x44, 0x07, 0xF5,
+ 0x82, 0x8E, 0x83, 0xE0, 0x22, 0xE4, 0x90, 0x07,
+/*1A50*/0x2A, 0xF0, 0xA3, 0xF0, 0x12, 0x07, 0x2A, 0x75,
+ 0x83, 0x82, 0xE0, 0x54, 0x7F, 0x12, 0x07, 0x29,
+/*1A60*/0xE0, 0x44, 0x80, 0xF0, 0x12, 0x10, 0xFC, 0x12,
+ 0x08, 0x1F, 0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0,
+/*1A70*/0x1A, 0x90, 0x07, 0x2B, 0xE0, 0x04, 0xF0, 0x70,
+ 0x06, 0x90, 0x07, 0x2A, 0xE0, 0x04, 0xF0, 0x90,
+/*1A80*/0x07, 0x2A, 0xE0, 0xB4, 0x10, 0xE1, 0xA3, 0xE0,
+ 0xB4, 0x00, 0xDC, 0xEE, 0x44, 0xA6, 0xFC, 0xEF,
+/*1A90*/0x44, 0x07, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0xF5,
+ 0x32, 0xEE, 0x44, 0xA8, 0xFE, 0xEF, 0x44, 0x07,
+/*1AA0*/0xF5, 0x82, 0x8E, 0x83, 0xE0, 0xF5, 0x33, 0x22,
+ 0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x90,
+/*1AB0*/0x00, 0x20, 0x0F, 0x92, 0x00, 0x21, 0x0F, 0x94,
+ 0x00, 0x22, 0x0F, 0x96, 0x00, 0x23, 0x0F, 0x98,
+/*1AC0*/0x00, 0x24, 0x0F, 0x9A, 0x00, 0x25, 0x0F, 0x9C,
+ 0x00, 0x26, 0x0F, 0x9E, 0x00, 0x27, 0x0F, 0xA0,
+/*1AD0*/0x01, 0x20, 0x01, 0xA2, 0x01, 0x21, 0x01, 0xA4,
+ 0x01, 0x22, 0x01, 0xA6, 0x01, 0x23, 0x01, 0xA8,
+/*1AE0*/0x01, 0x24, 0x01, 0xAA, 0x01, 0x25, 0x01, 0xAC,
+ 0x01, 0x26, 0x01, 0xAE, 0x01, 0x27, 0x01, 0xB0,
+/*1AF0*/0x01, 0x28, 0x01, 0xB4, 0x00, 0x28, 0x0F, 0xB6,
+ 0x40, 0x28, 0x0F, 0xB8, 0x61, 0x28, 0x01, 0xCB,
+/*1B00*/0xEF, 0xCB, 0xCA, 0xEE, 0xCA, 0x7F, 0x01, 0xE4,
+ 0xFD, 0xEB, 0x4A, 0x70, 0x24, 0xE5, 0x08, 0xF5,
+/*1B10*/0x82, 0x74, 0xB6, 0x12, 0x08, 0x29, 0xE5, 0x08,
+ 0xF5, 0x82, 0x74, 0xB8, 0x12, 0x08, 0x29, 0xE5,
+/*1B20*/0x08, 0xF5, 0x82, 0x74, 0xBA, 0x12, 0x08, 0x29,
+ 0x7E, 0x00, 0x7C, 0x00, 0x12, 0x0A, 0xFF, 0x80,
+/*1B30*/0x12, 0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE5,
+ 0x41, 0xF0, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35,
+/*1B40*/0xE5, 0x40, 0xF0, 0x12, 0x07, 0x2A, 0x75, 0x83,
+ 0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74, 0x01, 0x12,
+/*1B50*/0x07, 0x29, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x26,
+ 0xF5, 0x27, 0x53, 0xE1, 0xFE, 0xF5, 0x2A, 0x75,
+/*1B60*/0x2B, 0x01, 0xF5, 0x08, 0x7F, 0x01, 0x12, 0x17,
+ 0x31, 0x30, 0x30, 0x1C, 0x90, 0x1A, 0xA9, 0xE4,
+/*1B70*/0x93, 0xF5, 0x10, 0x90, 0x1F, 0xF9, 0xE4, 0x93,
+ 0xF5, 0x10, 0x90, 0x00, 0x41, 0xE4, 0x93, 0xF5,
+/*1B80*/0x10, 0x90, 0x1E, 0xCA, 0xE4, 0x93, 0xF5, 0x10,
+ 0x7F, 0x02, 0x12, 0x17, 0x31, 0x12, 0x0F, 0x54,
+/*1B90*/0x7F, 0x03, 0x12, 0x17, 0x31, 0x12, 0x00, 0x06,
+ 0xE5, 0xE2, 0x30, 0xE7, 0x09, 0x12, 0x10, 0x00,
+/*1BA0*/0x30, 0x30, 0x03, 0x12, 0x11, 0x00, 0x02, 0x00,
+ 0x47, 0x12, 0x08, 0x1F, 0x75, 0x83, 0xD0, 0xE0,
+/*1BB0*/0xC4, 0x54, 0x0F, 0xFD, 0x75, 0x43, 0x01, 0x75,
+ 0x44, 0xFF, 0x12, 0x08, 0xAA, 0x74, 0x04, 0xF0,
+/*1BC0*/0x75, 0x3B, 0x01, 0xED, 0x14, 0x60, 0x0C, 0x14,
+ 0x60, 0x0B, 0x14, 0x60, 0x0F, 0x24, 0x03, 0x70,
+/*1BD0*/0x0B, 0x80, 0x09, 0x80, 0x00, 0x12, 0x08, 0xA7,
+ 0x04, 0xF0, 0x80, 0x06, 0x12, 0x08, 0xA7, 0x74,
+/*1BE0*/0x04, 0xF0, 0xEE, 0x44, 0x82, 0xFE, 0xEF, 0x44,
+ 0x07, 0xF5, 0x82, 0x8E, 0x83, 0xE5, 0x45, 0x12,
+/*1BF0*/0x08, 0xBE, 0x75, 0x83, 0x82, 0xE5, 0x31, 0xF0,
+ 0x02, 0x11, 0x4C, 0x8E, 0x60, 0x8F, 0x61, 0x12,
+/*1C00*/0x1E, 0xA5, 0xE4, 0xFF, 0xCE, 0xED, 0xCE, 0xEE,
+ 0xD3, 0x95, 0x61, 0xE5, 0x60, 0x12, 0x07, 0x6B,
+/*1C10*/0x40, 0x39, 0x74, 0x20, 0x2E, 0xF5, 0x82, 0xE4,
+ 0x34, 0x03, 0xF5, 0x83, 0xE0, 0x70, 0x03, 0xFF,
+/*1C20*/0x80, 0x26, 0x12, 0x08, 0xE2, 0xFD, 0xC3, 0x9F,
+ 0x40, 0x1E, 0xCF, 0xED, 0xCF, 0xEB, 0x4A, 0x70,
+/*1C30*/0x0B, 0x8D, 0x42, 0x12, 0x08, 0xEE, 0xF5, 0x41,
+ 0x8E, 0x40, 0x80, 0x0C, 0x12, 0x08, 0xE2, 0xF5,
+/*1C40*/0x38, 0x12, 0x08, 0xEE, 0xF5, 0x39, 0x8E, 0x3A,
+ 0x1E, 0x80, 0xBC, 0x22, 0x75, 0x58, 0x01, 0xE5,
+/*1C50*/0x35, 0x70, 0x0C, 0x12, 0x07, 0xCC, 0xE0, 0xF5,
+ 0x4A, 0x12, 0x07, 0xD8, 0xE0, 0xF5, 0x4C, 0xE5,
+/*1C60*/0x35, 0xB4, 0x04, 0x0C, 0x12, 0x07, 0xE4, 0xE0,
+ 0xF5, 0x4A, 0x12, 0x07, 0xF0, 0xE0, 0xF5, 0x4C,
+/*1C70*/0xE5, 0x35, 0xB4, 0x01, 0x04, 0x7F, 0x01, 0x80,
+ 0x02, 0x7F, 0x00, 0xE5, 0x35, 0xB4, 0x02, 0x04,
+/*1C80*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F,
+ 0x60, 0x0C, 0x12, 0x07, 0xFC, 0xE0, 0xF5, 0x4A,
+/*1C90*/0x12, 0x08, 0x08, 0xE0, 0xF5, 0x4C, 0x85, 0x41,
+ 0x49, 0x85, 0x40, 0x4B, 0x22, 0x75, 0x5B, 0x01,
+/*1CA0*/0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE0, 0x54,
+ 0x1F, 0xFF, 0xD3, 0x94, 0x02, 0x50, 0x04, 0x8F,
+/*1CB0*/0x58, 0x80, 0x05, 0xEF, 0x24, 0xFE, 0xF5, 0x58,
+ 0xEF, 0xC3, 0x94, 0x18, 0x40, 0x05, 0x75, 0x59,
+/*1CC0*/0x18, 0x80, 0x04, 0xEF, 0x04, 0xF5, 0x59, 0x85,
+ 0x43, 0x5A, 0xAF, 0x58, 0x7E, 0x00, 0xAD, 0x59,
+/*1CD0*/0x7C, 0x00, 0xAB, 0x5B, 0x7A, 0x00, 0x12, 0x15,
+ 0x41, 0xAF, 0x5A, 0x7E, 0x00, 0x12, 0x18, 0x0A,
+/*1CE0*/0xAF, 0x5B, 0x7E, 0x00, 0x02, 0x1A, 0xFF, 0xE5,
+ 0xE2, 0x30, 0xE7, 0x0E, 0x12, 0x10, 0x03, 0xC2,
+/*1CF0*/0x30, 0x30, 0x30, 0x03, 0x12, 0x10, 0xFF, 0x20,
+ 0x33, 0x28, 0xE5, 0xE7, 0x30, 0xE7, 0x05, 0x12,
+/*1D00*/0x0E, 0xA2, 0x80, 0x0D, 0xE5, 0xFE, 0xC3, 0x94,
+ 0x20, 0x50, 0x06, 0x12, 0x0E, 0xA2, 0x43, 0xF9,
+/*1D10*/0x08, 0xE5, 0xF2, 0x30, 0xE7, 0x03, 0x53, 0xF9,
+ 0x7F, 0xE5, 0xF1, 0x54, 0x70, 0xD3, 0x94, 0x00,
+/*1D20*/0x50, 0xD8, 0x22, 0x12, 0x0E, 0x04, 0x75, 0x83,
+ 0x80, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0x12,
+/*1D30*/0x0D, 0xFD, 0x75, 0x83, 0x84, 0x12, 0x0E, 0x02,
+ 0x75, 0x83, 0x86, 0x12, 0x0E, 0x02, 0x75, 0x83,
+/*1D40*/0x8C, 0xE0, 0x54, 0xF3, 0x12, 0x0E, 0x03, 0x75,
+ 0x83, 0x8E, 0x12, 0x0E, 0x02, 0x75, 0x83, 0x94,
+/*1D50*/0xE0, 0x54, 0xFB, 0xF0, 0x22, 0x12, 0x07, 0x2A,
+ 0x75, 0x83, 0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74,
+/*1D60*/0x01, 0x12, 0x07, 0x29, 0xE4, 0x12, 0x08, 0xBE,
+ 0x75, 0x83, 0x8C, 0xE0, 0x44, 0x20, 0x12, 0x08,
+/*1D70*/0xBE, 0xE0, 0x54, 0xDF, 0xF0, 0x74, 0x84, 0x85,
+ 0x08, 0x82, 0xF5, 0x83, 0xE0, 0x54, 0x7F, 0xF0,
+/*1D80*/0xE0, 0x44, 0x80, 0xF0, 0x22, 0x75, 0x56, 0x01,
+ 0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE, 0xFC,
+/*1D90*/0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12, 0x1E,
+ 0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E, 0x00,
+/*1DA0*/0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF,
+ 0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0x75, 0x56,
+/*1DB0*/0x01, 0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE,
+ 0xFC, 0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12,
+/*1DC0*/0x1E, 0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E,
+ 0x00, 0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44,
+/*1DD0*/0xAF, 0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xE4,
+ 0xF5, 0x16, 0x12, 0x0E, 0x44, 0xFE, 0xE5, 0x08,
+/*1DE0*/0x44, 0x05, 0xFF, 0x12, 0x0E, 0x65, 0x8F, 0x82,
+ 0x8E, 0x83, 0xF0, 0x05, 0x16, 0xE5, 0x16, 0xC3,
+/*1DF0*/0x94, 0x14, 0x40, 0xE6, 0xE5, 0x08, 0x12, 0x0E,
+ 0x2B, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5,
+/*1E00*/0x59, 0xF5, 0x5A, 0xFF, 0xFE, 0xAD, 0x58, 0xFC,
+ 0x12, 0x09, 0x15, 0x7F, 0x04, 0x7E, 0x00, 0xAD,
+/*1E10*/0x58, 0x7C, 0x00, 0x12, 0x09, 0x15, 0x7F, 0x02,
+ 0x7E, 0x00, 0xAD, 0x58, 0x7C, 0x00, 0x02, 0x09,
+/*1E20*/0x15, 0xE5, 0x3C, 0x25, 0x3E, 0xFC, 0xE5, 0x42,
+ 0x24, 0x00, 0xFB, 0xE4, 0x33, 0xFA, 0xEC, 0xC3,
+/*1E30*/0x9B, 0xEA, 0x12, 0x07, 0x6B, 0x40, 0x0B, 0x8C,
+ 0x42, 0xE5, 0x3D, 0x25, 0x3F, 0xF5, 0x41, 0x8F,
+/*1E40*/0x40, 0x22, 0x12, 0x09, 0x0B, 0x22, 0x74, 0x84,
+ 0xF5, 0x18, 0x85, 0x08, 0x19, 0x85, 0x19, 0x82,
+/*1E50*/0x85, 0x18, 0x83, 0xE0, 0x54, 0x7F, 0xF0, 0xE0,
+ 0x44, 0x80, 0xF0, 0xE0, 0x44, 0x80, 0xF0, 0x22,
+/*1E60*/0xEF, 0x4E, 0x70, 0x0B, 0x12, 0x07, 0x2A, 0x75,
+ 0x83, 0xD2, 0xE0, 0x54, 0xDF, 0xF0, 0x22, 0x12,
+/*1E70*/0x07, 0x2A, 0x75, 0x83, 0xD2, 0xE0, 0x44, 0x20,
+ 0xF0, 0x22, 0x75, 0x58, 0x01, 0x90, 0x07, 0x26,
+/*1E80*/0x12, 0x07, 0x35, 0xE0, 0x54, 0x3F, 0xF5, 0x41,
+ 0x12, 0x07, 0x32, 0xE0, 0x54, 0x3F, 0xF5, 0x40,
+/*1E90*/0x22, 0x75, 0x56, 0x02, 0xE4, 0xF5, 0x57, 0x12,
+ 0x1D, 0xFC, 0xAF, 0x57, 0x7E, 0x00, 0xAD, 0x56,
+/*1EA0*/0x7C, 0x00, 0x02, 0x04, 0x44, 0xE4, 0xF5, 0x42,
+ 0xF5, 0x41, 0xF5, 0x40, 0xF5, 0x38, 0xF5, 0x39,
+/*1EB0*/0xF5, 0x3A, 0x22, 0xEF, 0x54, 0x07, 0xFF, 0xE5,
+ 0xF9, 0x54, 0xF8, 0x4F, 0xF5, 0xF9, 0x22, 0x7F,
+/*1EC0*/0x01, 0xE4, 0xFE, 0x0F, 0x0E, 0xBE, 0xFF, 0xFB,
+ 0x22, 0x01, 0x20, 0x00, 0x01, 0x04, 0x20, 0x00,
+/*1ED0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1EE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1EF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1F00*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1F10*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1F20*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1F30*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1F40*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1F50*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1F60*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1F70*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1F80*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1F90*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1FA0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1FB0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1FC0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1FD0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1FE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*1FF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x81
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/mlx_bitops.h b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/mlx_bitops.h
new file mode 100644
index 00000000..490d5e3c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/mlx_bitops.h
@@ -0,0 +1,245 @@
+#ifndef _MLX_BITOPS_H
+#define _MLX_BITOPS_H
+
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Mellanox bit operations
+ *
+ */
+
+/* Datatype used to represent a bit in the Mellanox autogenerated headers */
+typedef unsigned char pseudo_bit_t;
+
+/**
+ * Wrapper structure for pseudo_bit_t structures
+ *
+ * This structure provides a wrapper around the autogenerated
+ * pseudo_bit_t structures. It has the correct size, and also
+ * encapsulates type information about the underlying pseudo_bit_t
+ * structure, which allows the MLX_FILL etc. macros to work without
+ * requiring explicit type information.
+ */
+#define MLX_DECLARE_STRUCT( _structure ) \
+ _structure { \
+ union { \
+ uint8_t bytes[ sizeof ( struct _structure ## _st ) / 8 ]; \
+ uint32_t dwords[ sizeof ( struct _structure ## _st ) / 32 ]; \
+ struct _structure ## _st *dummy[0]; \
+ } __attribute__ (( packed )) u; \
+ } __attribute__ (( packed ))
+
+/** Get pseudo_bit_t structure type from wrapper structure pointer */
+#define MLX_PSEUDO_STRUCT( _ptr ) \
+ typeof ( *((_ptr)->u.dummy[0]) )
+
+/** Bit offset of a field within a pseudo_bit_t structure */
+#define MLX_BIT_OFFSET( _structure_st, _field ) \
+ offsetof ( _structure_st, _field )
+
+/** Dword offset of a field within a pseudo_bit_t structure */
+#define MLX_DWORD_OFFSET( _structure_st, _field ) \
+ ( MLX_BIT_OFFSET ( _structure_st, _field ) / 32 )
+
+/** Dword bit offset of a field within a pseudo_bit_t structure
+ *
+ * Yes, using mod-32 would work, but would lose the check for the
+ * error of specifying a mismatched field name and dword index.
+ */
+#define MLX_DWORD_BIT_OFFSET( _structure_st, _index, _field ) \
+ ( MLX_BIT_OFFSET ( _structure_st, _field ) - ( 32 * (_index) ) )
+
+/** Bit width of a field within a pseudo_bit_t structure */
+#define MLX_BIT_WIDTH( _structure_st, _field ) \
+ sizeof ( ( ( _structure_st * ) NULL )->_field )
+
+/** Bit mask for a field within a pseudo_bit_t structure */
+#define MLX_BIT_MASK( _structure_st, _field ) \
+ ( ( ~( ( uint32_t ) 0 ) ) >> \
+ ( 32 - MLX_BIT_WIDTH ( _structure_st, _field ) ) )
+
+/*
+ * Assemble native-endian dword from named fields and values
+ *
+ */
+
+#define MLX_ASSEMBLE_1( _structure_st, _index, _field, _value ) \
+ ( (_value) << MLX_DWORD_BIT_OFFSET ( _structure_st, _index, _field ) )
+
+#define MLX_ASSEMBLE_2( _structure_st, _index, _field, _value, ... ) \
+ ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) | \
+ MLX_ASSEMBLE_1 ( _structure_st, _index, __VA_ARGS__ ) )
+
+#define MLX_ASSEMBLE_3( _structure_st, _index, _field, _value, ... ) \
+ ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) | \
+ MLX_ASSEMBLE_2 ( _structure_st, _index, __VA_ARGS__ ) )
+
+#define MLX_ASSEMBLE_4( _structure_st, _index, _field, _value, ... ) \
+ ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) | \
+ MLX_ASSEMBLE_3 ( _structure_st, _index, __VA_ARGS__ ) )
+
+#define MLX_ASSEMBLE_5( _structure_st, _index, _field, _value, ... ) \
+ ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) | \
+ MLX_ASSEMBLE_4 ( _structure_st, _index, __VA_ARGS__ ) )
+
+#define MLX_ASSEMBLE_6( _structure_st, _index, _field, _value, ... ) \
+ ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) | \
+ MLX_ASSEMBLE_5 ( _structure_st, _index, __VA_ARGS__ ) )
+
+#define MLX_ASSEMBLE_7( _structure_st, _index, _field, _value, ... ) \
+ ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) | \
+ MLX_ASSEMBLE_6 ( _structure_st, _index, __VA_ARGS__ ) )
+
+#define MLX_ASSEMBLE_8( _structure_st, _index, _field, _value, ... ) \
+ ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) | \
+ MLX_ASSEMBLE_7 ( _structure_st, _index, __VA_ARGS__ ) )
+
+/*
+ * Build native-endian (positive) dword bitmasks from named fields
+ *
+ */
+
+#define MLX_MASK_1( _structure_st, _index, _field ) \
+ ( MLX_BIT_MASK ( _structure_st, _field ) << \
+ MLX_DWORD_BIT_OFFSET ( _structure_st, _index, _field ) )
+
+#define MLX_MASK_2( _structure_st, _index, _field, ... ) \
+ ( MLX_MASK_1 ( _structure_st, _index, _field ) | \
+ MLX_MASK_1 ( _structure_st, _index, __VA_ARGS__ ) )
+
+#define MLX_MASK_3( _structure_st, _index, _field, ... ) \
+ ( MLX_MASK_1 ( _structure_st, _index, _field ) | \
+ MLX_MASK_2 ( _structure_st, _index, __VA_ARGS__ ) )
+
+#define MLX_MASK_4( _structure_st, _index, _field, ... ) \
+ ( MLX_MASK_1 ( _structure_st, _index, _field ) | \
+ MLX_MASK_3 ( _structure_st, _index, __VA_ARGS__ ) )
+
+#define MLX_MASK_5( _structure_st, _index, _field, ... ) \
+ ( MLX_MASK_1 ( _structure_st, _index, _field ) | \
+ MLX_MASK_4 ( _structure_st, _index, __VA_ARGS__ ) )
+
+#define MLX_MASK_6( _structure_st, _index, _field, ... ) \
+ ( MLX_MASK_1 ( _structure_st, _index, _field ) | \
+ MLX_MASK_5 ( _structure_st, _index, __VA_ARGS__ ) )
+
+#define MLX_MASK_7( _structure_st, _index, _field, ... ) \
+ ( MLX_MASK_1 ( _structure_st, _index, _field ) | \
+ MLX_MASK_6 ( _structure_st, _index, __VA_ARGS__ ) )
+
+#define MLX_MASK_8( _structure_st, _index, _field, ... ) \
+ ( MLX_MASK_1 ( _structure_st, _index, _field ) | \
+ MLX_MASK_7 ( _structure_st, _index, __VA_ARGS__ ) )
+
+/*
+ * Populate big-endian dwords from named fields and values
+ *
+ */
+
+#define MLX_FILL( _ptr, _index, _assembled ) \
+ do { \
+ uint32_t *__ptr = &(_ptr)->u.dwords[(_index)]; \
+ uint32_t __assembled = (_assembled); \
+ *__ptr = cpu_to_be32 ( __assembled ); \
+ } while ( 0 )
+
+#define MLX_FILL_1( _ptr, _index, ... ) \
+ MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ),\
+ _index, __VA_ARGS__ ) )
+
+#define MLX_FILL_2( _ptr, _index, ... ) \
+ MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_2 ( MLX_PSEUDO_STRUCT ( _ptr ),\
+ _index, __VA_ARGS__ ) )
+
+#define MLX_FILL_3( _ptr, _index, ... ) \
+ MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_3 ( MLX_PSEUDO_STRUCT ( _ptr ),\
+ _index, __VA_ARGS__ ) )
+
+#define MLX_FILL_4( _ptr, _index, ... ) \
+ MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_4 ( MLX_PSEUDO_STRUCT ( _ptr ),\
+ _index, __VA_ARGS__ ) )
+
+#define MLX_FILL_5( _ptr, _index, ... ) \
+ MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_5 ( MLX_PSEUDO_STRUCT ( _ptr ),\
+ _index, __VA_ARGS__ ) )
+
+#define MLX_FILL_6( _ptr, _index, ... ) \
+ MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_6 ( MLX_PSEUDO_STRUCT ( _ptr ),\
+ _index, __VA_ARGS__ ) )
+
+#define MLX_FILL_7( _ptr, _index, ... ) \
+ MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_7 ( MLX_PSEUDO_STRUCT ( _ptr ),\
+ _index, __VA_ARGS__ ) )
+
+#define MLX_FILL_8( _ptr, _index, ... ) \
+ MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_8 ( MLX_PSEUDO_STRUCT ( _ptr ),\
+ _index, __VA_ARGS__ ) )
+
+/*
+ * Modify big-endian dword using named field and value
+ *
+ */
+
+#define MLX_SET( _ptr, _field, _value ) \
+ do { \
+ unsigned int __index = \
+ MLX_DWORD_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \
+ uint32_t *__ptr = &(_ptr)->u.dwords[__index]; \
+ uint32_t __value = be32_to_cpu ( *__ptr ); \
+ __value &= ~( MLX_MASK_1 ( MLX_PSEUDO_STRUCT ( _ptr ), \
+ __index, _field ) ); \
+ __value |= MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ), \
+ __index, _field, _value ); \
+ *__ptr = cpu_to_be32 ( __value ); \
+ } while ( 0 )
+
+/*
+ * Extract value of named field
+ *
+ */
+
+#define MLX_GET( _ptr, _field ) \
+ ( { \
+ unsigned int __index = \
+ MLX_DWORD_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \
+ uint32_t *__ptr = &(_ptr)->u.dwords[__index]; \
+ uint32_t __value = be32_to_cpu ( *__ptr ); \
+ __value >>= \
+ MLX_DWORD_BIT_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), \
+ __index, _field ); \
+ __value &= \
+ MLX_BIT_MASK ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \
+ __value; \
+ } )
+
+/*
+ * Fill high dword of physical address, if necessary
+ *
+ */
+#define MLX_FILL_H( _structure_st, _index, _field, _address ) do { \
+ if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) { \
+ MLX_FILL_1 ( _structure_st, _index, _field, \
+ ( ( ( uint64_t ) (_address) ) >> 32 ) ); \
+ } } while ( 0 )
+
+#endif /* _MLX_BITOPS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib7322.c b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib7322.c
new file mode 100644
index 00000000..b66f8eff
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib7322.c
@@ -0,0 +1,2428 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+#include <ipxe/io.h>
+#include <ipxe/pci.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/i2c.h>
+#include <ipxe/bitbash.h>
+#include <ipxe/malloc.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/pcibackup.h>
+#include "qib7322.h"
+
+/**
+ * @file
+ *
+ * QLogic QIB7322 Infiniband HCA
+ *
+ */
+
+/** A QIB7322 send buffer set */
+struct qib7322_send_buffers {
+ /** Offset within register space of the first send buffer */
+ unsigned long base;
+ /** Send buffer size */
+ unsigned int size;
+ /** Index of first send buffer */
+ unsigned int start;
+ /** Number of send buffers
+ *
+ * Must be a power of two.
+ */
+ unsigned int count;
+ /** Send buffer availability producer counter */
+ unsigned int prod;
+ /** Send buffer availability consumer counter */
+ unsigned int cons;
+ /** Send buffer availability */
+ uint16_t avail[0];
+};
+
+/** A QIB7322 send work queue */
+struct qib7322_send_work_queue {
+ /** Send buffer set */
+ struct qib7322_send_buffers *send_bufs;
+ /** Send buffer usage */
+ uint16_t *used;
+ /** Producer index */
+ unsigned int prod;
+ /** Consumer index */
+ unsigned int cons;
+};
+
+/** A QIB7322 receive work queue */
+struct qib7322_recv_work_queue {
+ /** Receive header ring */
+ void *header;
+ /** Receive header producer offset (written by hardware) */
+ struct QIB_7322_scalar header_prod;
+ /** Receive header consumer offset */
+ unsigned int header_cons;
+ /** Offset within register space of the eager array */
+ unsigned long eager_array;
+ /** Number of entries in eager array */
+ unsigned int eager_entries;
+ /** Eager array producer index */
+ unsigned int eager_prod;
+ /** Eager array consumer index */
+ unsigned int eager_cons;
+};
+
+/** A QIB7322 HCA */
+struct qib7322 {
+ /** Registers */
+ void *regs;
+
+ /** In-use contexts */
+ uint8_t used_ctx[QIB7322_NUM_CONTEXTS];
+ /** Send work queues */
+ struct qib7322_send_work_queue send_wq[QIB7322_NUM_CONTEXTS];
+ /** Receive work queues */
+ struct qib7322_recv_work_queue recv_wq[QIB7322_NUM_CONTEXTS];
+
+ /** Send buffer availability (reported by hardware) */
+ struct QIB_7322_SendBufAvail *sendbufavail;
+ /** Small send buffers */
+ struct qib7322_send_buffers *send_bufs_small;
+ /** VL15 port 0 send buffers */
+ struct qib7322_send_buffers *send_bufs_vl15_port0;
+ /** VL15 port 1 send buffers */
+ struct qib7322_send_buffers *send_bufs_vl15_port1;
+
+ /** I2C bit-bashing interface */
+ struct i2c_bit_basher i2c;
+ /** I2C serial EEPROM */
+ struct i2c_device eeprom;
+
+ /** Base GUID */
+ union ib_guid guid;
+ /** Infiniband devices */
+ struct ib_device *ibdev[QIB7322_MAX_PORTS];
+};
+
+/***************************************************************************
+ *
+ * QIB7322 register access
+ *
+ ***************************************************************************
+ *
+ * This card requires atomic 64-bit accesses. Strange things happen
+ * if you try to use 32-bit accesses; sometimes they work, sometimes
+ * they don't, sometimes you get random data.
+ *
+ * These accessors use the "movq" MMX instruction, and so won't work
+ * on really old Pentiums (which won't have PCIe anyway, so this is
+ * something of a moot point).
+ */
+
+/**
+ * Read QIB7322 qword register
+ *
+ * @v qib7322 QIB7322 device
+ * @v dwords Register buffer to read into
+ * @v offset Register offset
+ */
+static void qib7322_readq ( struct qib7322 *qib7322, uint32_t *dwords,
+ unsigned long offset ) {
+ void *addr = ( qib7322->regs + offset );
+
+ __asm__ __volatile__ ( "movq (%1), %%mm0\n\t"
+ "movq %%mm0, (%0)\n\t"
+ : : "r" ( dwords ), "r" ( addr ) : "memory" );
+
+ DBGIO ( "[%08lx] => %08x%08x\n",
+ virt_to_phys ( addr ), dwords[1], dwords[0] );
+}
+#define qib7322_readq( _qib7322, _ptr, _offset ) \
+ qib7322_readq ( (_qib7322), (_ptr)->u.dwords, (_offset) )
+#define qib7322_readq_array8b( _qib7322, _ptr, _offset, _idx ) \
+ qib7322_readq ( (_qib7322), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) )
+#define qib7322_readq_array64k( _qib7322, _ptr, _offset, _idx ) \
+ qib7322_readq ( (_qib7322), (_ptr), ( (_offset) + ( (_idx) * 65536 ) ) )
+#define qib7322_readq_port( _qib7322, _ptr, _offset, _port ) \
+ qib7322_readq ( (_qib7322), (_ptr), ( (_offset) + ( (_port) * 4096 ) ) )
+
+/**
+ * Write QIB7322 qword register
+ *
+ * @v qib7322 QIB7322 device
+ * @v dwords Register buffer to write
+ * @v offset Register offset
+ */
+static void qib7322_writeq ( struct qib7322 *qib7322, const uint32_t *dwords,
+ unsigned long offset ) {
+ void *addr = ( qib7322->regs + offset );
+
+ DBGIO ( "[%08lx] <= %08x%08x\n",
+ virt_to_phys ( addr ), dwords[1], dwords[0] );
+
+ __asm__ __volatile__ ( "movq (%0), %%mm0\n\t"
+ "movq %%mm0, (%1)\n\t"
+ : : "r" ( dwords ), "r" ( addr ) : "memory" );
+}
+#define qib7322_writeq( _qib7322, _ptr, _offset ) \
+ qib7322_writeq ( (_qib7322), (_ptr)->u.dwords, (_offset) )
+#define qib7322_writeq_array8b( _qib7322, _ptr, _offset, _idx ) \
+ qib7322_writeq ( (_qib7322), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) )
+#define qib7322_writeq_array64k( _qib7322, _ptr, _offset, _idx ) \
+ qib7322_writeq ( (_qib7322), (_ptr), ( (_offset) + ( (_idx) * 65536 ) ))
+#define qib7322_writeq_port( _qib7322, _ptr, _offset, _port ) \
+ qib7322_writeq ( (_qib7322), (_ptr), ( (_offset) + ( (_port) * 4096 ) ))
+
+/**
+ * Write QIB7322 dword register
+ *
+ * @v qib7322 QIB7322 device
+ * @v dword Value to write
+ * @v offset Register offset
+ */
+static void qib7322_writel ( struct qib7322 *qib7322, uint32_t dword,
+ unsigned long offset ) {
+ writel ( dword, ( qib7322->regs + offset ) );
+}
+
+/***************************************************************************
+ *
+ * Link state management
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Textual representation of link state
+ *
+ * @v link_state Link state
+ * @ret link_text Link state text
+ */
+static const char * qib7322_link_state_text ( unsigned int link_state ) {
+ switch ( link_state ) {
+ case QIB7322_LINK_STATE_DOWN: return "DOWN";
+ case QIB7322_LINK_STATE_INIT: return "INIT";
+ case QIB7322_LINK_STATE_ARM: return "ARM";
+ case QIB7322_LINK_STATE_ACTIVE: return "ACTIVE";
+ case QIB7322_LINK_STATE_ACT_DEFER: return "ACT_DEFER";
+ default: return "UNKNOWN";
+ }
+}
+
+/**
+ * Handle link state change
+ *
+ * @v qib7322 QIB7322 device
+ */
+static void qib7322_link_state_changed ( struct ib_device *ibdev ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct QIB_7322_IBCStatusA_0 ibcstatusa;
+ struct QIB_7322_EXTCtrl extctrl;
+ unsigned int port = ( ibdev->port - QIB7322_PORT_BASE );
+ unsigned int link_training_state;
+ unsigned int link_state;
+ unsigned int link_width;
+ unsigned int link_speed;
+ unsigned int link_speed_qdr;
+ unsigned int green;
+ unsigned int yellow;
+
+ /* Read link state */
+ qib7322_readq_port ( qib7322, &ibcstatusa,
+ QIB_7322_IBCStatusA_0_offset, port );
+ link_training_state = BIT_GET ( &ibcstatusa, LinkTrainingState );
+ link_state = BIT_GET ( &ibcstatusa, LinkState );
+ link_width = BIT_GET ( &ibcstatusa, LinkWidthActive );
+ link_speed = BIT_GET ( &ibcstatusa, LinkSpeedActive );
+ link_speed_qdr = BIT_GET ( &ibcstatusa, LinkSpeedQDR );
+ DBGC ( qib7322, "QIB7322 %p port %d training state %#x link state %s "
+ "(%s %s)\n", qib7322, port, link_training_state,
+ qib7322_link_state_text ( link_state ),
+ ( link_speed_qdr ? "QDR" : ( link_speed ? "DDR" : "SDR" ) ),
+ ( link_width ? "x4" : "x1" ) );
+
+ /* Set LEDs according to link state */
+ qib7322_readq ( qib7322, &extctrl, QIB_7322_EXTCtrl_offset );
+ green = ( ( link_state >= QIB7322_LINK_STATE_INIT ) ? 1 : 0 );
+ yellow = ( ( link_state >= QIB7322_LINK_STATE_ACTIVE ) ? 1 : 0 );
+ if ( port == 0 ) {
+ BIT_SET ( &extctrl, LEDPort0GreenOn, green );
+ BIT_SET ( &extctrl, LEDPort0YellowOn, yellow );
+ } else {
+ BIT_SET ( &extctrl, LEDPort1GreenOn, green );
+ BIT_SET ( &extctrl, LEDPort1YellowOn, yellow );
+ }
+ qib7322_writeq ( qib7322, &extctrl, QIB_7322_EXTCtrl_offset );
+
+ /* Notify Infiniband core of link state change */
+ ibdev->port_state = ( link_state + 1 );
+ ibdev->link_width_active =
+ ( link_width ? IB_LINK_WIDTH_4X : IB_LINK_WIDTH_1X );
+ ibdev->link_speed_active =
+ ( link_speed ? IB_LINK_SPEED_DDR : IB_LINK_SPEED_SDR );
+ ib_link_state_changed ( ibdev );
+}
+
+/**
+ * Wait for link state change to take effect
+ *
+ * @v ibdev Infiniband device
+ * @v new_link_state Expected link state
+ * @ret rc Return status code
+ */
+static int qib7322_link_state_check ( struct ib_device *ibdev,
+ unsigned int new_link_state ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct QIB_7322_IBCStatusA_0 ibcstatusa;
+ unsigned int port = ( ibdev->port - QIB7322_PORT_BASE );
+ unsigned int link_state;
+ unsigned int i;
+
+ for ( i = 0 ; i < QIB7322_LINK_STATE_MAX_WAIT_US ; i++ ) {
+ qib7322_readq_port ( qib7322, &ibcstatusa,
+ QIB_7322_IBCStatusA_0_offset, port );
+ link_state = BIT_GET ( &ibcstatusa, LinkState );
+ if ( link_state == new_link_state )
+ return 0;
+ udelay ( 1 );
+ }
+
+ DBGC ( qib7322, "QIB7322 %p port %d timed out waiting for link state "
+ "%s\n", qib7322, port, qib7322_link_state_text ( link_state ) );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Set port information
+ *
+ * @v ibdev Infiniband device
+ * @v mad Set port information MAD
+ */
+static int qib7322_set_port_info ( struct ib_device *ibdev,
+ union ib_mad *mad ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct ib_port_info *port_info = &mad->smp.smp_data.port_info;
+ struct QIB_7322_IBCCtrlA_0 ibcctrla;
+ unsigned int port = ( ibdev->port - QIB7322_PORT_BASE );
+ unsigned int port_state;
+ unsigned int link_state;
+
+ /* Set new link state */
+ port_state = ( port_info->link_speed_supported__port_state & 0xf );
+ if ( port_state ) {
+ link_state = ( port_state - 1 );
+ DBGC ( qib7322, "QIB7322 %p set link state to %s (%x)\n",
+ qib7322, qib7322_link_state_text ( link_state ),
+ link_state );
+ qib7322_readq_port ( qib7322, &ibcctrla,
+ QIB_7322_IBCCtrlA_0_offset, port );
+ BIT_SET ( &ibcctrla, LinkCmd, link_state );
+ qib7322_writeq_port ( qib7322, &ibcctrla,
+ QIB_7322_IBCCtrlA_0_offset, port );
+
+ /* Wait for link state change to take effect. Ignore
+ * errors; the current link state will be returned via
+ * the GetResponse MAD.
+ */
+ qib7322_link_state_check ( ibdev, link_state );
+ }
+
+ /* Detect and report link state change */
+ qib7322_link_state_changed ( ibdev );
+
+ return 0;
+}
+
+/**
+ * Set partition key table
+ *
+ * @v ibdev Infiniband device
+ * @v mad Set partition key table MAD
+ */
+static int qib7322_set_pkey_table ( struct ib_device *ibdev __unused,
+ union ib_mad *mad __unused ) {
+ /* Nothing to do */
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * Context allocation
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Allocate a context and set queue pair number
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static int qib7322_alloc_ctx ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ unsigned int port = ( ibdev->port - QIB7322_PORT_BASE );
+ unsigned int ctx;
+
+ for ( ctx = port ; ctx < QIB7322_NUM_CONTEXTS ; ctx += 2 ) {
+
+ if ( ! qib7322->used_ctx[ctx] ) {
+ qib7322->used_ctx[ctx] = 1;
+ qp->qpn = ( ctx & ~0x01 );
+ DBGC2 ( qib7322, "QIB7322 %p port %d QPN %ld is CTX "
+ "%d\n", qib7322, port, qp->qpn, ctx );
+ return 0;
+ }
+ }
+
+ DBGC ( qib7322, "QIB7322 %p port %d out of available contexts\n",
+ qib7322, port );
+ return -ENOENT;
+}
+
+/**
+ * Get queue pair context number
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret ctx Context index
+ */
+static unsigned int qib7322_ctx ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ return ( qp->qpn + ( ibdev->port - QIB7322_PORT_BASE ) );
+}
+
+/**
+ * Free a context
+ *
+ * @v qib7322 QIB7322 device
+ * @v ctx Context index
+ */
+static void qib7322_free_ctx ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ unsigned int port = ( ibdev->port - QIB7322_PORT_BASE );
+ unsigned int ctx = qib7322_ctx ( ibdev, qp );
+
+ qib7322->used_ctx[ctx] = 0;
+ DBGC2 ( qib7322, "QIB7322 %p port %d CTX %d freed\n",
+ qib7322, port, ctx );
+}
+
+/***************************************************************************
+ *
+ * Send datapath
+ *
+ ***************************************************************************
+ */
+
+/** Send buffer toggle bit
+ *
+ * We encode send buffers as 15 bits of send buffer index plus a
+ * single bit which should match the "check" bit in the SendBufAvail
+ * array.
+ */
+#define QIB7322_SEND_BUF_TOGGLE 0x8000
+
+/**
+ * Create send buffer set
+ *
+ * @v qib7322 QIB7322 device
+ * @v base Send buffer base offset
+ * @v size Send buffer size
+ * @v start Index of first send buffer
+ * @v count Number of send buffers
+ * @ret send_bufs Send buffer set
+ */
+static struct qib7322_send_buffers *
+qib7322_create_send_bufs ( struct qib7322 *qib7322, unsigned long base,
+ unsigned int size, unsigned int start,
+ unsigned int count ) {
+ struct qib7322_send_buffers *send_bufs;
+ unsigned int i;
+
+ /* Allocate send buffer set */
+ send_bufs = zalloc ( sizeof ( *send_bufs ) +
+ ( count * sizeof ( send_bufs->avail[0] ) ) );
+ if ( ! send_bufs )
+ return NULL;
+
+ /* Populate send buffer set */
+ send_bufs->base = base;
+ send_bufs->size = size;
+ send_bufs->start = start;
+ send_bufs->count = count;
+ for ( i = 0 ; i < count ; i++ )
+ send_bufs->avail[i] = ( start + i );
+
+ DBGC2 ( qib7322, "QIB7322 %p send buffer set %p [%d,%d] at %lx\n",
+ qib7322, send_bufs, start, ( start + count - 1 ),
+ send_bufs->base );
+
+ return send_bufs;
+}
+
+/**
+ * Destroy send buffer set
+ *
+ * @v qib7322 QIB7322 device
+ * @v send_bufs Send buffer set
+ */
+static void
+qib7322_destroy_send_bufs ( struct qib7322 *qib7322 __unused,
+ struct qib7322_send_buffers *send_bufs ) {
+ free ( send_bufs );
+}
+
+/**
+ * Allocate a send buffer
+ *
+ * @v qib7322 QIB7322 device
+ * @v send_bufs Send buffer set
+ * @ret send_buf Send buffer, or negative error
+ */
+static int qib7322_alloc_send_buf ( struct qib7322 *qib7322,
+ struct qib7322_send_buffers *send_bufs ) {
+ unsigned int used;
+ unsigned int mask;
+ unsigned int send_buf;
+
+ used = ( send_bufs->cons - send_bufs->prod );
+ if ( used >= send_bufs->count ) {
+ DBGC ( qib7322, "QIB7322 %p send buffer set %p out of "
+ "buffers\n", qib7322, send_bufs );
+ return -ENOBUFS;
+ }
+
+ mask = ( send_bufs->count - 1 );
+ send_buf = send_bufs->avail[ send_bufs->cons++ & mask ];
+ send_buf ^= QIB7322_SEND_BUF_TOGGLE;
+ return send_buf;
+}
+
+/**
+ * Free a send buffer
+ *
+ * @v qib7322 QIB7322 device
+ * @v send_bufs Send buffer set
+ * @v send_buf Send buffer
+ */
+static void qib7322_free_send_buf ( struct qib7322 *qib7322 __unused,
+ struct qib7322_send_buffers *send_bufs,
+ unsigned int send_buf ) {
+ unsigned int mask;
+
+ mask = ( send_bufs->count - 1 );
+ send_bufs->avail[ send_bufs->prod++ & mask ] = send_buf;
+}
+
+/**
+ * Check to see if send buffer is in use
+ *
+ * @v qib7322 QIB7322 device
+ * @v send_buf Send buffer
+ * @ret in_use Send buffer is in use
+ */
+static int qib7322_send_buf_in_use ( struct qib7322 *qib7322,
+ unsigned int send_buf ) {
+ unsigned int send_idx;
+ unsigned int send_check;
+ unsigned int inusecheck;
+ unsigned int inuse;
+ unsigned int check;
+
+ send_idx = ( send_buf & ~QIB7322_SEND_BUF_TOGGLE );
+ send_check = ( !! ( send_buf & QIB7322_SEND_BUF_TOGGLE ) );
+ inusecheck = BIT_GET ( qib7322->sendbufavail, InUseCheck[send_idx] );
+ inuse = ( !! ( inusecheck & 0x02 ) );
+ check = ( !! ( inusecheck & 0x01 ) );
+ return ( inuse || ( check != send_check ) );
+}
+
+/**
+ * Calculate starting offset for send buffer
+ *
+ * @v qib7322 QIB7322 device
+ * @v send_buf Send buffer
+ * @ret offset Starting offset
+ */
+static unsigned long
+qib7322_send_buffer_offset ( struct qib7322 *qib7322 __unused,
+ struct qib7322_send_buffers *send_bufs,
+ unsigned int send_buf ) {
+ unsigned int index;
+
+ index = ( ( send_buf & ~QIB7322_SEND_BUF_TOGGLE ) - send_bufs->start );
+ return ( send_bufs->base + ( index * send_bufs->size ) );
+}
+
+/**
+ * Create send work queue
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+static int qib7322_create_send_wq ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->send;
+ struct qib7322_send_work_queue *qib7322_wq = ib_wq_get_drvdata ( wq );
+ unsigned int port = ( ibdev->port - QIB7322_PORT_BASE );
+
+ /* Select send buffer set */
+ if ( qp->type == IB_QPT_SMI ) {
+ if ( port == 0 ) {
+ qib7322_wq->send_bufs = qib7322->send_bufs_vl15_port0;
+ } else {
+ qib7322_wq->send_bufs = qib7322->send_bufs_vl15_port1;
+ }
+ } else {
+ qib7322_wq->send_bufs = qib7322->send_bufs_small;
+ }
+
+ /* Allocate space for send buffer usage list */
+ qib7322_wq->used = zalloc ( qp->send.num_wqes *
+ sizeof ( qib7322_wq->used[0] ) );
+ if ( ! qib7322_wq->used )
+ return -ENOMEM;
+
+ /* Reset work queue */
+ qib7322_wq->prod = 0;
+ qib7322_wq->cons = 0;
+
+ return 0;
+}
+
+/**
+ * Destroy send work queue
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+static void qib7322_destroy_send_wq ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp ) {
+ struct ib_work_queue *wq = &qp->send;
+ struct qib7322_send_work_queue *qib7322_wq = ib_wq_get_drvdata ( wq );
+
+ free ( qib7322_wq->used );
+}
+
+/**
+ * Initialise send datapath
+ *
+ * @v qib7322 QIB7322 device
+ * @ret rc Return status code
+ */
+static int qib7322_init_send ( struct qib7322 *qib7322 ) {
+ struct QIB_7322_SendBufBase sendbufbase;
+ struct QIB_7322_SendBufAvailAddr sendbufavailaddr;
+ struct QIB_7322_SendCtrl sendctrl;
+ struct QIB_7322_SendCtrl_0 sendctrlp;
+ unsigned long baseaddr_smallpio;
+ unsigned long baseaddr_largepio;
+ unsigned long baseaddr_vl15_port0;
+ unsigned long baseaddr_vl15_port1;
+ int rc;
+
+ /* Create send buffer sets */
+ qib7322_readq ( qib7322, &sendbufbase, QIB_7322_SendBufBase_offset );
+ baseaddr_smallpio = BIT_GET ( &sendbufbase, BaseAddr_SmallPIO );
+ baseaddr_largepio = BIT_GET ( &sendbufbase, BaseAddr_LargePIO );
+ baseaddr_vl15_port0 = ( baseaddr_largepio +
+ ( QIB7322_LARGE_SEND_BUF_SIZE *
+ QIB7322_LARGE_SEND_BUF_COUNT ) );
+ baseaddr_vl15_port1 = ( baseaddr_vl15_port0 +
+ QIB7322_VL15_PORT0_SEND_BUF_SIZE );
+ qib7322->send_bufs_small =
+ qib7322_create_send_bufs ( qib7322, baseaddr_smallpio,
+ QIB7322_SMALL_SEND_BUF_SIZE,
+ QIB7322_SMALL_SEND_BUF_START,
+ QIB7322_SMALL_SEND_BUF_USED );
+ if ( ! qib7322->send_bufs_small ) {
+ rc = -ENOMEM;
+ goto err_create_send_bufs_small;
+ }
+ qib7322->send_bufs_vl15_port0 =
+ qib7322_create_send_bufs ( qib7322, baseaddr_vl15_port0,
+ QIB7322_VL15_PORT0_SEND_BUF_SIZE,
+ QIB7322_VL15_PORT0_SEND_BUF_START,
+ QIB7322_VL15_PORT0_SEND_BUF_COUNT );
+ if ( ! qib7322->send_bufs_vl15_port0 ) {
+ rc = -ENOMEM;
+ goto err_create_send_bufs_vl15_port0;
+ }
+ qib7322->send_bufs_vl15_port1 =
+ qib7322_create_send_bufs ( qib7322, baseaddr_vl15_port1,
+ QIB7322_VL15_PORT1_SEND_BUF_SIZE,
+ QIB7322_VL15_PORT1_SEND_BUF_START,
+ QIB7322_VL15_PORT1_SEND_BUF_COUNT );
+ if ( ! qib7322->send_bufs_vl15_port1 ) {
+ rc = -ENOMEM;
+ goto err_create_send_bufs_vl15_port1;
+ }
+
+ /* Allocate space for the SendBufAvail array */
+ qib7322->sendbufavail = malloc_dma ( sizeof ( *qib7322->sendbufavail ),
+ QIB7322_SENDBUFAVAIL_ALIGN );
+ if ( ! qib7322->sendbufavail ) {
+ rc = -ENOMEM;
+ goto err_alloc_sendbufavail;
+ }
+ memset ( qib7322->sendbufavail, 0, sizeof ( qib7322->sendbufavail ) );
+
+ /* Program SendBufAvailAddr into the hardware */
+ memset ( &sendbufavailaddr, 0, sizeof ( sendbufavailaddr ) );
+ BIT_FILL_1 ( &sendbufavailaddr, SendBufAvailAddr,
+ ( virt_to_bus ( qib7322->sendbufavail ) >> 6 ) );
+ qib7322_writeq ( qib7322, &sendbufavailaddr,
+ QIB_7322_SendBufAvailAddr_offset );
+
+ /* Enable sending */
+ memset ( &sendctrlp, 0, sizeof ( sendctrlp ) );
+ BIT_FILL_1 ( &sendctrlp, SendEnable, 1 );
+ qib7322_writeq ( qib7322, &sendctrlp, QIB_7322_SendCtrl_0_offset );
+ qib7322_writeq ( qib7322, &sendctrlp, QIB_7322_SendCtrl_1_offset );
+
+ /* Enable DMA of SendBufAvail */
+ memset ( &sendctrl, 0, sizeof ( sendctrl ) );
+ BIT_FILL_1 ( &sendctrl, SendBufAvailUpd, 1 );
+ qib7322_writeq ( qib7322, &sendctrl, QIB_7322_SendCtrl_offset );
+
+ return 0;
+
+ free_dma ( qib7322->sendbufavail, sizeof ( *qib7322->sendbufavail ) );
+ err_alloc_sendbufavail:
+ qib7322_destroy_send_bufs ( qib7322, qib7322->send_bufs_vl15_port1 );
+ err_create_send_bufs_vl15_port1:
+ qib7322_destroy_send_bufs ( qib7322, qib7322->send_bufs_vl15_port0 );
+ err_create_send_bufs_vl15_port0:
+ qib7322_destroy_send_bufs ( qib7322, qib7322->send_bufs_small );
+ err_create_send_bufs_small:
+ return rc;
+}
+
+/**
+ * Shut down send datapath
+ *
+ * @v qib7322 QIB7322 device
+ */
+static void qib7322_fini_send ( struct qib7322 *qib7322 ) {
+ struct QIB_7322_SendCtrl sendctrl;
+
+ /* Disable sending and DMA of SendBufAvail */
+ memset ( &sendctrl, 0, sizeof ( sendctrl ) );
+ qib7322_writeq ( qib7322, &sendctrl, QIB_7322_SendCtrl_offset );
+ mb();
+
+ /* Ensure hardware has seen this disable */
+ qib7322_readq ( qib7322, &sendctrl, QIB_7322_SendCtrl_offset );
+
+ free_dma ( qib7322->sendbufavail, sizeof ( *qib7322->sendbufavail ) );
+ qib7322_destroy_send_bufs ( qib7322, qib7322->send_bufs_vl15_port1 );
+ qib7322_destroy_send_bufs ( qib7322, qib7322->send_bufs_vl15_port0 );
+ qib7322_destroy_send_bufs ( qib7322, qib7322->send_bufs_small );
+}
+
+/***************************************************************************
+ *
+ * Receive datapath
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Create receive work queue
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static int qib7322_create_recv_wq ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->recv;
+ struct qib7322_recv_work_queue *qib7322_wq = ib_wq_get_drvdata ( wq );
+ struct QIB_7322_RcvHdrAddr0 rcvhdraddr;
+ struct QIB_7322_RcvHdrTailAddr0 rcvhdrtailaddr;
+ struct QIB_7322_RcvHdrHead0 rcvhdrhead;
+ struct QIB_7322_scalar rcvegrindexhead;
+ struct QIB_7322_RcvCtrl rcvctrl;
+ struct QIB_7322_RcvCtrl_P rcvctrlp;
+ unsigned int port = ( ibdev->port - QIB7322_PORT_BASE );
+ unsigned int ctx = qib7322_ctx ( ibdev, qp );
+ int rc;
+
+ /* Reset context information */
+ memset ( &qib7322_wq->header_prod, 0,
+ sizeof ( qib7322_wq->header_prod ) );
+ qib7322_wq->header_cons = 0;
+ qib7322_wq->eager_prod = 0;
+ qib7322_wq->eager_cons = 0;
+
+ /* Allocate receive header buffer */
+ qib7322_wq->header = malloc_dma ( QIB7322_RECV_HEADERS_SIZE,
+ QIB7322_RECV_HEADERS_ALIGN );
+ if ( ! qib7322_wq->header ) {
+ rc = -ENOMEM;
+ goto err_alloc_header;
+ }
+
+ /* Enable context in hardware */
+ memset ( &rcvhdraddr, 0, sizeof ( rcvhdraddr ) );
+ BIT_FILL_1 ( &rcvhdraddr, RcvHdrAddr,
+ ( virt_to_bus ( qib7322_wq->header ) >> 2 ) );
+ qib7322_writeq_array8b ( qib7322, &rcvhdraddr,
+ QIB_7322_RcvHdrAddr0_offset, ctx );
+ memset ( &rcvhdrtailaddr, 0, sizeof ( rcvhdrtailaddr ) );
+ BIT_FILL_1 ( &rcvhdrtailaddr, RcvHdrTailAddr,
+ ( virt_to_bus ( &qib7322_wq->header_prod ) >> 2 ) );
+ qib7322_writeq_array8b ( qib7322, &rcvhdrtailaddr,
+ QIB_7322_RcvHdrTailAddr0_offset, ctx );
+ memset ( &rcvhdrhead, 0, sizeof ( rcvhdrhead ) );
+ BIT_FILL_1 ( &rcvhdrhead, counter, 1 );
+ qib7322_writeq_array64k ( qib7322, &rcvhdrhead,
+ QIB_7322_RcvHdrHead0_offset, ctx );
+ memset ( &rcvegrindexhead, 0, sizeof ( rcvegrindexhead ) );
+ BIT_FILL_1 ( &rcvegrindexhead, Value, 1 );
+ qib7322_writeq_array64k ( qib7322, &rcvegrindexhead,
+ QIB_7322_RcvEgrIndexHead0_offset, ctx );
+ qib7322_readq_port ( qib7322, &rcvctrlp,
+ QIB_7322_RcvCtrl_0_offset, port );
+ BIT_SET ( &rcvctrlp, ContextEnable[ctx], 1 );
+ qib7322_writeq_port ( qib7322, &rcvctrlp,
+ QIB_7322_RcvCtrl_0_offset, port );
+ qib7322_readq ( qib7322, &rcvctrl, QIB_7322_RcvCtrl_offset );
+ BIT_SET ( &rcvctrl, IntrAvail[ctx], 1 );
+ qib7322_writeq ( qib7322, &rcvctrl, QIB_7322_RcvCtrl_offset );
+
+ DBGC ( qib7322, "QIB7322 %p port %d QPN %ld CTX %d hdrs [%lx,%lx) prod "
+ "%lx\n", qib7322, port, qp->qpn, ctx,
+ virt_to_bus ( qib7322_wq->header ),
+ ( virt_to_bus ( qib7322_wq->header )
+ + QIB7322_RECV_HEADERS_SIZE ),
+ virt_to_bus ( &qib7322_wq->header_prod ) );
+ return 0;
+
+ free_dma ( qib7322_wq->header, QIB7322_RECV_HEADERS_SIZE );
+ err_alloc_header:
+ return rc;
+}
+
+/**
+ * Destroy receive work queue
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+static void qib7322_destroy_recv_wq ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->recv;
+ struct qib7322_recv_work_queue *qib7322_wq = ib_wq_get_drvdata ( wq );
+ struct QIB_7322_RcvCtrl rcvctrl;
+ struct QIB_7322_RcvCtrl_P rcvctrlp;
+ unsigned int port = ( ibdev->port - QIB7322_PORT_BASE );
+ unsigned int ctx = qib7322_ctx ( ibdev, qp );
+
+ /* Disable context in hardware */
+ qib7322_readq_port ( qib7322, &rcvctrlp,
+ QIB_7322_RcvCtrl_0_offset, port );
+ BIT_SET ( &rcvctrlp, ContextEnable[ctx], 0 );
+ qib7322_writeq_port ( qib7322, &rcvctrlp,
+ QIB_7322_RcvCtrl_0_offset, port );
+ qib7322_readq ( qib7322, &rcvctrl, QIB_7322_RcvCtrl_offset );
+ BIT_SET ( &rcvctrl, IntrAvail[ctx], 0 );
+ qib7322_writeq ( qib7322, &rcvctrl, QIB_7322_RcvCtrl_offset );
+
+ /* Make sure the hardware has seen that the context is disabled */
+ qib7322_readq ( qib7322, &rcvctrl, QIB_7322_RcvCtrl_offset );
+ mb();
+
+ /* Free headers ring */
+ free_dma ( qib7322_wq->header, QIB7322_RECV_HEADERS_SIZE );
+}
+
+/**
+ * Initialise receive datapath
+ *
+ * @v qib7322 QIB7322 device
+ * @ret rc Return status code
+ */
+static int qib7322_init_recv ( struct qib7322 *qib7322 ) {
+ struct QIB_7322_RcvCtrl rcvctrl;
+ struct QIB_7322_RcvCtrl_0 rcvctrlp;
+ struct QIB_7322_RcvQPMapTableA_0 rcvqpmaptablea0;
+ struct QIB_7322_RcvQPMapTableB_0 rcvqpmaptableb0;
+ struct QIB_7322_RcvQPMapTableA_1 rcvqpmaptablea1;
+ struct QIB_7322_RcvQPMapTableB_1 rcvqpmaptableb1;
+ struct QIB_7322_RcvQPMulticastContext_0 rcvqpmcastctx0;
+ struct QIB_7322_RcvQPMulticastContext_1 rcvqpmcastctx1;
+ struct QIB_7322_scalar rcvegrbase;
+ struct QIB_7322_scalar rcvhdrentsize;
+ struct QIB_7322_scalar rcvhdrcnt;
+ struct QIB_7322_RcvBTHQP_0 rcvbthqp;
+ struct QIB_7322_RxCreditVL0_0 rxcreditvl;
+ unsigned int contextcfg;
+ unsigned long egrbase;
+ unsigned int eager_array_size_kernel;
+ unsigned int eager_array_size_user;
+ unsigned int ctx;
+
+ /* Select configuration based on number of contexts */
+ switch ( QIB7322_NUM_CONTEXTS ) {
+ case 6:
+ contextcfg = QIB7322_CONTEXTCFG_6CTX;
+ eager_array_size_kernel = QIB7322_EAGER_ARRAY_SIZE_6CTX_KERNEL;
+ eager_array_size_user = QIB7322_EAGER_ARRAY_SIZE_6CTX_USER;
+ break;
+ case 10:
+ contextcfg = QIB7322_CONTEXTCFG_10CTX;
+ eager_array_size_kernel = QIB7322_EAGER_ARRAY_SIZE_10CTX_KERNEL;
+ eager_array_size_user = QIB7322_EAGER_ARRAY_SIZE_10CTX_USER;
+ break;
+ case 18:
+ contextcfg = QIB7322_CONTEXTCFG_18CTX;
+ eager_array_size_kernel = QIB7322_EAGER_ARRAY_SIZE_18CTX_KERNEL;
+ eager_array_size_user = QIB7322_EAGER_ARRAY_SIZE_18CTX_USER;
+ break;
+ default:
+ linker_assert ( 0, invalid_QIB7322_NUM_CONTEXTS );
+ return -EINVAL;
+ }
+
+ /* Configure number of contexts */
+ memset ( &rcvctrl, 0, sizeof ( rcvctrl ) );
+ BIT_FILL_2 ( &rcvctrl,
+ TailUpd, 1,
+ ContextCfg, contextcfg );
+ qib7322_writeq ( qib7322, &rcvctrl, QIB_7322_RcvCtrl_offset );
+
+ /* Map QPNs to contexts */
+ memset ( &rcvctrlp, 0, sizeof ( rcvctrlp ) );
+ BIT_FILL_3 ( &rcvctrlp,
+ RcvIBPortEnable, 1,
+ RcvQPMapEnable, 1,
+ RcvPartitionKeyDisable, 1 );
+ qib7322_writeq ( qib7322, &rcvctrlp, QIB_7322_RcvCtrl_0_offset );
+ qib7322_writeq ( qib7322, &rcvctrlp, QIB_7322_RcvCtrl_1_offset );
+ memset ( &rcvqpmaptablea0, 0, sizeof ( rcvqpmaptablea0 ) );
+ BIT_FILL_6 ( &rcvqpmaptablea0,
+ RcvQPMapContext0, 0,
+ RcvQPMapContext1, 2,
+ RcvQPMapContext2, 4,
+ RcvQPMapContext3, 6,
+ RcvQPMapContext4, 8,
+ RcvQPMapContext5, 10 );
+ qib7322_writeq ( qib7322, &rcvqpmaptablea0,
+ QIB_7322_RcvQPMapTableA_0_offset );
+ memset ( &rcvqpmaptableb0, 0, sizeof ( rcvqpmaptableb0 ) );
+ BIT_FILL_3 ( &rcvqpmaptableb0,
+ RcvQPMapContext6, 12,
+ RcvQPMapContext7, 14,
+ RcvQPMapContext8, 16 );
+ qib7322_writeq ( qib7322, &rcvqpmaptableb0,
+ QIB_7322_RcvQPMapTableB_0_offset );
+ memset ( &rcvqpmaptablea1, 0, sizeof ( rcvqpmaptablea1 ) );
+ BIT_FILL_6 ( &rcvqpmaptablea1,
+ RcvQPMapContext0, 1,
+ RcvQPMapContext1, 3,
+ RcvQPMapContext2, 5,
+ RcvQPMapContext3, 7,
+ RcvQPMapContext4, 9,
+ RcvQPMapContext5, 11 );
+ qib7322_writeq ( qib7322, &rcvqpmaptablea1,
+ QIB_7322_RcvQPMapTableA_1_offset );
+ memset ( &rcvqpmaptableb1, 0, sizeof ( rcvqpmaptableb1 ) );
+ BIT_FILL_3 ( &rcvqpmaptableb1,
+ RcvQPMapContext6, 13,
+ RcvQPMapContext7, 15,
+ RcvQPMapContext8, 17 );
+ qib7322_writeq ( qib7322, &rcvqpmaptableb1,
+ QIB_7322_RcvQPMapTableB_1_offset );
+
+ /* Map multicast QPNs to contexts */
+ memset ( &rcvqpmcastctx0, 0, sizeof ( rcvqpmcastctx0 ) );
+ BIT_FILL_1 ( &rcvqpmcastctx0, RcvQpMcContext, 0 );
+ qib7322_writeq ( qib7322, &rcvqpmcastctx0,
+ QIB_7322_RcvQPMulticastContext_0_offset );
+ memset ( &rcvqpmcastctx1, 0, sizeof ( rcvqpmcastctx1 ) );
+ BIT_FILL_1 ( &rcvqpmcastctx1, RcvQpMcContext, 1 );
+ qib7322_writeq ( qib7322, &rcvqpmcastctx1,
+ QIB_7322_RcvQPMulticastContext_1_offset );
+
+ /* Configure receive header buffer sizes */
+ memset ( &rcvhdrcnt, 0, sizeof ( rcvhdrcnt ) );
+ BIT_FILL_1 ( &rcvhdrcnt, Value, QIB7322_RECV_HEADER_COUNT );
+ qib7322_writeq ( qib7322, &rcvhdrcnt, QIB_7322_RcvHdrCnt_offset );
+ memset ( &rcvhdrentsize, 0, sizeof ( rcvhdrentsize ) );
+ BIT_FILL_1 ( &rcvhdrentsize, Value, ( QIB7322_RECV_HEADER_SIZE >> 2 ) );
+ qib7322_writeq ( qib7322, &rcvhdrentsize,
+ QIB_7322_RcvHdrEntSize_offset );
+
+ /* Calculate eager array start addresses for each context */
+ qib7322_readq ( qib7322, &rcvegrbase, QIB_7322_RcvEgrBase_offset );
+ egrbase = BIT_GET ( &rcvegrbase, Value );
+ for ( ctx = 0 ; ctx < QIB7322_MAX_PORTS ; ctx++ ) {
+ qib7322->recv_wq[ctx].eager_array = egrbase;
+ qib7322->recv_wq[ctx].eager_entries = eager_array_size_kernel;
+ egrbase += ( eager_array_size_kernel *
+ sizeof ( struct QIB_7322_RcvEgr ) );
+ }
+ for ( ; ctx < QIB7322_NUM_CONTEXTS ; ctx++ ) {
+ qib7322->recv_wq[ctx].eager_array = egrbase;
+ qib7322->recv_wq[ctx].eager_entries = eager_array_size_user;
+ egrbase += ( eager_array_size_user *
+ sizeof ( struct QIB_7322_RcvEgr ) );
+ }
+ for ( ctx = 0 ; ctx < QIB7322_NUM_CONTEXTS ; ctx++ ) {
+ DBGC ( qib7322, "QIB7322 %p CTX %d eager array at %lx (%d "
+ "entries)\n", qib7322, ctx,
+ qib7322->recv_wq[ctx].eager_array,
+ qib7322->recv_wq[ctx].eager_entries );
+ }
+
+ /* Set the BTH QP for Infinipath packets to an unused value */
+ memset ( &rcvbthqp, 0, sizeof ( rcvbthqp ) );
+ BIT_FILL_1 ( &rcvbthqp, RcvBTHQP, QIB7322_QP_IDETH );
+ qib7322_writeq ( qib7322, &rcvbthqp, QIB_7322_RcvBTHQP_0_offset );
+ qib7322_writeq ( qib7322, &rcvbthqp, QIB_7322_RcvBTHQP_1_offset );
+
+ /* Assign initial credits */
+ memset ( &rxcreditvl, 0, sizeof ( rxcreditvl ) );
+ BIT_FILL_1 ( &rxcreditvl, RxMaxCreditVL, QIB7322_MAX_CREDITS_VL0 );
+ qib7322_writeq_array8b ( qib7322, &rxcreditvl,
+ QIB_7322_RxCreditVL0_0_offset, 0 );
+ qib7322_writeq_array8b ( qib7322, &rxcreditvl,
+ QIB_7322_RxCreditVL0_1_offset, 0 );
+ BIT_FILL_1 ( &rxcreditvl, RxMaxCreditVL, QIB7322_MAX_CREDITS_VL15 );
+ qib7322_writeq_array8b ( qib7322, &rxcreditvl,
+ QIB_7322_RxCreditVL0_0_offset, 15 );
+ qib7322_writeq_array8b ( qib7322, &rxcreditvl,
+ QIB_7322_RxCreditVL0_1_offset, 15 );
+
+ return 0;
+}
+
+/**
+ * Shut down receive datapath
+ *
+ * @v qib7322 QIB7322 device
+ */
+static void qib7322_fini_recv ( struct qib7322 *qib7322 __unused ) {
+ /* Nothing to do; all contexts were already disabled when the
+ * queue pairs were destroyed
+ */
+}
+
+/***************************************************************************
+ *
+ * Completion queue operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Create completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ * @ret rc Return status code
+ */
+static int qib7322_create_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ static int cqn;
+
+ /* The hardware has no concept of completion queues. We
+ * simply use the association between CQs and WQs (already
+ * handled by the IB core) to decide which WQs to poll.
+ *
+ * We do set a CQN, just to avoid confusing debug messages
+ * from the IB core.
+ */
+ cq->cqn = ++cqn;
+ DBGC ( qib7322, "QIB7322 %p CQN %ld created\n", qib7322, cq->cqn );
+
+ return 0;
+}
+
+/**
+ * Destroy completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+static void qib7322_destroy_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+
+ /* Nothing to do */
+ DBGC ( qib7322, "QIB7322 %p CQN %ld destroyed\n", qib7322, cq->cqn );
+}
+
+/***************************************************************************
+ *
+ * Queue pair operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Create queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static int qib7322_create_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ unsigned int ctx;
+ int rc;
+
+ /* Allocate a context and QPN */
+ if ( ( rc = qib7322_alloc_ctx ( ibdev, qp ) ) != 0 )
+ goto err_alloc_ctx;
+ ctx = qib7322_ctx ( ibdev, qp );
+
+ /* Set work-queue private data pointers */
+ ib_wq_set_drvdata ( &qp->send, &qib7322->send_wq[ctx] );
+ ib_wq_set_drvdata ( &qp->recv, &qib7322->recv_wq[ctx] );
+
+ /* Create receive work queue */
+ if ( ( rc = qib7322_create_recv_wq ( ibdev, qp ) ) != 0 )
+ goto err_create_recv_wq;
+
+ /* Create send work queue */
+ if ( ( rc = qib7322_create_send_wq ( ibdev, qp ) ) != 0 )
+ goto err_create_send_wq;
+
+ return 0;
+
+ qib7322_destroy_send_wq ( ibdev, qp );
+ err_create_send_wq:
+ qib7322_destroy_recv_wq ( ibdev, qp );
+ err_create_recv_wq:
+ qib7322_free_ctx ( ibdev, qp );
+ err_alloc_ctx:
+ return rc;
+}
+
+/**
+ * Modify queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+static int qib7322_modify_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+
+ /* Nothing to do; the hardware doesn't have a notion of queue
+ * keys
+ */
+ DBGC2 ( qib7322, "QIB7322 %p QPN %ld modified\n", qib7322, qp->qpn );
+ return 0;
+}
+
+/**
+ * Destroy queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+static void qib7322_destroy_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+
+ qib7322_destroy_send_wq ( ibdev, qp );
+ qib7322_destroy_recv_wq ( ibdev, qp );
+ qib7322_free_ctx ( ibdev, qp );
+}
+
+/***************************************************************************
+ *
+ * Work request operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Post send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int qib7322_post_send ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->send;
+ struct qib7322_send_work_queue *qib7322_wq = ib_wq_get_drvdata ( wq );
+ struct QIB_7322_SendPbc sendpbc;
+ unsigned int port = ( ibdev->port - QIB7322_PORT_BASE );
+ uint8_t header_buf[IB_MAX_HEADER_SIZE];
+ struct io_buffer headers;
+ int send_buf;
+ unsigned long start_offset;
+ unsigned long offset;
+ size_t len;
+ ssize_t frag_len;
+ uint32_t *data;
+
+ /* Allocate send buffer and calculate offset */
+ send_buf = qib7322_alloc_send_buf ( qib7322, qib7322_wq->send_bufs );
+ if ( send_buf < 0 )
+ return send_buf;
+ start_offset = offset =
+ qib7322_send_buffer_offset ( qib7322, qib7322_wq->send_bufs,
+ send_buf );
+
+ /* Store I/O buffer and send buffer index */
+ assert ( wq->iobufs[qib7322_wq->prod] == NULL );
+ wq->iobufs[qib7322_wq->prod] = iobuf;
+ qib7322_wq->used[qib7322_wq->prod] = send_buf;
+
+ /* Construct headers */
+ iob_populate ( &headers, header_buf, 0, sizeof ( header_buf ) );
+ iob_reserve ( &headers, sizeof ( header_buf ) );
+ ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), av );
+
+ /* Calculate packet length */
+ len = ( ( sizeof ( sendpbc ) + iob_len ( &headers ) +
+ iob_len ( iobuf ) + 3 ) & ~3 );
+
+ /* Construct send per-buffer control word */
+ memset ( &sendpbc, 0, sizeof ( sendpbc ) );
+ BIT_FILL_3 ( &sendpbc,
+ LengthP1_toibc, ( ( len >> 2 ) - 1 ),
+ Port, port,
+ VL15, ( ( qp->type == IB_QPT_SMI ) ? 1 : 0 ) );
+
+ /* Write SendPbc */
+ DBG_DISABLE ( DBGLVL_IO );
+ qib7322_writeq ( qib7322, &sendpbc, offset );
+ offset += sizeof ( sendpbc );
+
+ /* Write headers */
+ for ( data = headers.data, frag_len = iob_len ( &headers ) ;
+ frag_len > 0 ; data++, offset += 4, frag_len -= 4 ) {
+ qib7322_writel ( qib7322, *data, offset );
+ }
+
+ /* Write data */
+ for ( data = iobuf->data, frag_len = iob_len ( iobuf ) ;
+ frag_len > 0 ; data++, offset += 4, frag_len -= 4 ) {
+ qib7322_writel ( qib7322, *data, offset );
+ }
+ DBG_ENABLE ( DBGLVL_IO );
+
+ assert ( ( start_offset + len ) == offset );
+ DBGC2 ( qib7322, "QIB7322 %p QPN %ld TX %04x(%04x) posted [%lx,%lx)\n",
+ qib7322, qp->qpn, send_buf, qib7322_wq->prod,
+ start_offset, offset );
+
+ /* Increment producer counter */
+ qib7322_wq->prod = ( ( qib7322_wq->prod + 1 ) & ( wq->num_wqes - 1 ) );
+
+ return 0;
+}
+
+/**
+ * Complete send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v wqe_idx Work queue entry index
+ */
+static void qib7322_complete_send ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ unsigned int wqe_idx ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->send;
+ struct qib7322_send_work_queue *qib7322_wq = ib_wq_get_drvdata ( wq );
+ struct io_buffer *iobuf;
+ unsigned int send_buf;
+
+ /* Parse completion */
+ send_buf = qib7322_wq->used[wqe_idx];
+ DBGC2 ( qib7322, "QIB7322 %p QPN %ld TX %04x(%04x) complete\n",
+ qib7322, qp->qpn, send_buf, wqe_idx );
+
+ /* Complete work queue entry */
+ iobuf = wq->iobufs[wqe_idx];
+ assert ( iobuf != NULL );
+ ib_complete_send ( ibdev, qp, iobuf, 0 );
+ wq->iobufs[wqe_idx] = NULL;
+
+ /* Free send buffer */
+ qib7322_free_send_buf ( qib7322, qib7322_wq->send_bufs, send_buf );
+}
+
+/**
+ * Poll send work queue
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+static void qib7322_poll_send_wq ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->send;
+ struct qib7322_send_work_queue *qib7322_wq = ib_wq_get_drvdata ( wq );
+ unsigned int send_buf;
+
+ /* Look for completions */
+ while ( wq->fill ) {
+
+ /* Check to see if send buffer has completed */
+ send_buf = qib7322_wq->used[qib7322_wq->cons];
+ if ( qib7322_send_buf_in_use ( qib7322, send_buf ) )
+ break;
+
+ /* Complete this buffer */
+ qib7322_complete_send ( ibdev, qp, qib7322_wq->cons );
+
+ /* Increment consumer counter */
+ qib7322_wq->cons = ( ( qib7322_wq->cons + 1 ) &
+ ( wq->num_wqes - 1 ) );
+ }
+}
+
+/**
+ * Post receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int qib7322_post_recv ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->recv;
+ struct qib7322_recv_work_queue *qib7322_wq = ib_wq_get_drvdata ( wq );
+ struct QIB_7322_RcvEgr rcvegr;
+ struct QIB_7322_scalar rcvegrindexhead;
+ unsigned int ctx = qib7322_ctx ( ibdev, qp );
+ physaddr_t addr;
+ size_t len;
+ unsigned int wqe_idx;
+ unsigned int bufsize;
+
+ /* Sanity checks */
+ addr = virt_to_bus ( iobuf->data );
+ len = iob_tailroom ( iobuf );
+ if ( addr & ( QIB7322_EAGER_BUFFER_ALIGN - 1 ) ) {
+ DBGC ( qib7322, "QIB7322 %p QPN %ld misaligned RX buffer "
+ "(%08lx)\n", qib7322, qp->qpn, addr );
+ return -EINVAL;
+ }
+ if ( len != QIB7322_RECV_PAYLOAD_SIZE ) {
+ DBGC ( qib7322, "QIB7322 %p QPN %ld wrong RX buffer size "
+ "(%zd)\n", qib7322, qp->qpn, len );
+ return -EINVAL;
+ }
+
+ /* Calculate eager producer index and WQE index */
+ wqe_idx = ( qib7322_wq->eager_prod & ( wq->num_wqes - 1 ) );
+ assert ( wq->iobufs[wqe_idx] == NULL );
+
+ /* Store I/O buffer */
+ wq->iobufs[wqe_idx] = iobuf;
+
+ /* Calculate buffer size */
+ switch ( QIB7322_RECV_PAYLOAD_SIZE ) {
+ case 2048: bufsize = QIB7322_EAGER_BUFFER_2K; break;
+ case 4096: bufsize = QIB7322_EAGER_BUFFER_4K; break;
+ case 8192: bufsize = QIB7322_EAGER_BUFFER_8K; break;
+ case 16384: bufsize = QIB7322_EAGER_BUFFER_16K; break;
+ case 32768: bufsize = QIB7322_EAGER_BUFFER_32K; break;
+ case 65536: bufsize = QIB7322_EAGER_BUFFER_64K; break;
+ default: linker_assert ( 0, invalid_rx_payload_size );
+ bufsize = QIB7322_EAGER_BUFFER_NONE;
+ }
+
+ /* Post eager buffer */
+ memset ( &rcvegr, 0, sizeof ( rcvegr ) );
+ BIT_FILL_2 ( &rcvegr,
+ Addr, ( addr >> 11 ),
+ BufSize, bufsize );
+ qib7322_writeq_array8b ( qib7322, &rcvegr, qib7322_wq->eager_array,
+ qib7322_wq->eager_prod );
+ DBGC2 ( qib7322, "QIB7322 %p QPN %ld RX egr %04x(%04x) posted "
+ "[%lx,%lx)\n", qib7322, qp->qpn, qib7322_wq->eager_prod,
+ wqe_idx, addr, ( addr + len ) );
+
+ /* Increment producer index */
+ qib7322_wq->eager_prod = ( ( qib7322_wq->eager_prod + 1 ) &
+ ( qib7322_wq->eager_entries - 1 ) );
+
+ /* Update head index */
+ memset ( &rcvegrindexhead, 0, sizeof ( rcvegrindexhead ) );
+ BIT_FILL_1 ( &rcvegrindexhead,
+ Value, ( ( qib7322_wq->eager_prod + 1 ) &
+ ( qib7322_wq->eager_entries - 1 ) ) );
+ qib7322_writeq_array64k ( qib7322, &rcvegrindexhead,
+ QIB_7322_RcvEgrIndexHead0_offset, ctx );
+
+ return 0;
+}
+
+/**
+ * Complete receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v header_offs Header offset
+ */
+static void qib7322_complete_recv ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ unsigned int header_offs ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->recv;
+ struct qib7322_recv_work_queue *qib7322_wq = ib_wq_get_drvdata ( wq );
+ struct QIB_7322_RcvHdrFlags *rcvhdrflags;
+ struct QIB_7322_RcvEgr rcvegr;
+ struct io_buffer headers;
+ struct io_buffer *iobuf;
+ struct ib_queue_pair *intended_qp;
+ struct ib_address_vector av;
+ unsigned int rcvtype;
+ unsigned int pktlen;
+ unsigned int egrindex;
+ unsigned int useegrbfr;
+ unsigned int iberr, mkerr, tiderr, khdrerr, mtuerr;
+ unsigned int lenerr, parityerr, vcrcerr, icrcerr;
+ unsigned int err;
+ unsigned int hdrqoffset;
+ unsigned int header_len;
+ unsigned int padded_payload_len;
+ unsigned int wqe_idx;
+ size_t payload_len;
+ int qp0;
+ int rc;
+
+ /* RcvHdrFlags are at the end of the header entry */
+ rcvhdrflags = ( qib7322_wq->header + header_offs +
+ QIB7322_RECV_HEADER_SIZE - sizeof ( *rcvhdrflags ) );
+ rcvtype = BIT_GET ( rcvhdrflags, RcvType );
+ pktlen = ( BIT_GET ( rcvhdrflags, PktLen ) << 2 );
+ egrindex = BIT_GET ( rcvhdrflags, EgrIndex );
+ useegrbfr = BIT_GET ( rcvhdrflags, UseEgrBfr );
+ hdrqoffset = ( BIT_GET ( rcvhdrflags, HdrqOffset ) << 2 );
+ iberr = BIT_GET ( rcvhdrflags, IBErr );
+ mkerr = BIT_GET ( rcvhdrflags, MKErr );
+ tiderr = BIT_GET ( rcvhdrflags, TIDErr );
+ khdrerr = BIT_GET ( rcvhdrflags, KHdrErr );
+ mtuerr = BIT_GET ( rcvhdrflags, MTUErr );
+ lenerr = BIT_GET ( rcvhdrflags, LenErr );
+ parityerr = BIT_GET ( rcvhdrflags, ParityErr );
+ vcrcerr = BIT_GET ( rcvhdrflags, VCRCErr );
+ icrcerr = BIT_GET ( rcvhdrflags, ICRCErr );
+ header_len = ( QIB7322_RECV_HEADER_SIZE - hdrqoffset -
+ sizeof ( *rcvhdrflags ) );
+ padded_payload_len = ( pktlen - header_len - 4 /* ICRC */ );
+ err = ( iberr | mkerr | tiderr | khdrerr | mtuerr |
+ lenerr | parityerr | vcrcerr | icrcerr );
+ /* IB header is placed immediately before RcvHdrFlags */
+ iob_populate ( &headers, ( ( ( void * ) rcvhdrflags ) - header_len ),
+ header_len, header_len );
+
+ /* Dump diagnostic information */
+ DBGC2 ( qib7322, "QIB7322 %p QPN %ld RX egr %04x%s hdr %d type %d len "
+ "%d(%d+%d+4)%s%s%s%s%s%s%s%s%s%s%s\n", qib7322, qp->qpn,
+ egrindex, ( useegrbfr ? "" : "(unused)" ),
+ ( header_offs / QIB7322_RECV_HEADER_SIZE ),
+ rcvtype, pktlen, header_len, padded_payload_len,
+ ( err ? " [Err" : "" ), ( iberr ? " IB" : "" ),
+ ( mkerr ? " MK" : "" ), ( tiderr ? " TID" : "" ),
+ ( khdrerr ? " KHdr" : "" ), ( mtuerr ? " MTU" : "" ),
+ ( lenerr ? " Len" : "" ), ( parityerr ? " Parity" : ""),
+ ( vcrcerr ? " VCRC" : "" ), ( icrcerr ? " ICRC" : "" ),
+ ( err ? "]" : "" ) );
+ DBGCP_HDA ( qib7322, hdrqoffset, headers.data,
+ ( header_len + sizeof ( *rcvhdrflags ) ) );
+
+ /* Parse header to generate address vector */
+ qp0 = ( qp->qpn == 0 );
+ intended_qp = NULL;
+ if ( ( rc = ib_pull ( ibdev, &headers, ( qp0 ? &intended_qp : NULL ),
+ &payload_len, &av ) ) != 0 ) {
+ DBGC ( qib7322, "QIB7322 %p could not parse headers: %s\n",
+ qib7322, strerror ( rc ) );
+ err = 1;
+ }
+ if ( ! intended_qp )
+ intended_qp = qp;
+
+ /* Complete this buffer and any skipped buffers. Note that
+ * when the hardware runs out of buffers, it will repeatedly
+ * report the same buffer (the tail) as a TID error, and that
+ * it also has a habit of sometimes skipping over several
+ * buffers at once.
+ */
+ while ( 1 ) {
+
+ /* If we have caught up to the producer counter, stop.
+ * This will happen when the hardware first runs out
+ * of buffers and starts reporting TID errors against
+ * the eager buffer it wants to use next.
+ */
+ if ( qib7322_wq->eager_cons == qib7322_wq->eager_prod )
+ break;
+
+ /* If we have caught up to where we should be after
+ * completing this egrindex, stop. We phrase the test
+ * this way to avoid completing the entire ring when
+ * we receive the same egrindex twice in a row.
+ */
+ if ( ( qib7322_wq->eager_cons ==
+ ( ( egrindex + 1 ) & ( qib7322_wq->eager_entries - 1 ))))
+ break;
+
+ /* Identify work queue entry and corresponding I/O
+ * buffer.
+ */
+ wqe_idx = ( qib7322_wq->eager_cons & ( wq->num_wqes - 1 ) );
+ iobuf = wq->iobufs[wqe_idx];
+ assert ( iobuf != NULL );
+ wq->iobufs[wqe_idx] = NULL;
+
+ /* Complete the eager buffer */
+ if ( qib7322_wq->eager_cons == egrindex ) {
+ /* Completing the eager buffer described in
+ * this header entry.
+ */
+ iob_put ( iobuf, payload_len );
+ rc = ( err ? -EIO : ( useegrbfr ? 0 : -ECANCELED ) );
+ /* Redirect to target QP if necessary */
+ if ( qp != intended_qp ) {
+ DBGC2 ( qib7322, "QIB7322 %p redirecting QPN "
+ "%ld => %ld\n",
+ qib7322, qp->qpn, intended_qp->qpn );
+ /* Compensate for incorrect fill levels */
+ qp->recv.fill--;
+ intended_qp->recv.fill++;
+ }
+ ib_complete_recv ( ibdev, intended_qp, &av, iobuf, rc);
+ } else {
+ /* Completing on a skipped-over eager buffer */
+ ib_complete_recv ( ibdev, qp, &av, iobuf, -ECANCELED );
+ }
+
+ /* Clear eager buffer */
+ memset ( &rcvegr, 0, sizeof ( rcvegr ) );
+ qib7322_writeq_array8b ( qib7322, &rcvegr,
+ qib7322_wq->eager_array,
+ qib7322_wq->eager_cons );
+
+ /* Increment consumer index */
+ qib7322_wq->eager_cons = ( ( qib7322_wq->eager_cons + 1 ) &
+ ( qib7322_wq->eager_entries - 1 ) );
+ }
+}
+
+/**
+ * Poll receive work queue
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+static void qib7322_poll_recv_wq ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct ib_work_queue *wq = &qp->recv;
+ struct qib7322_recv_work_queue *qib7322_wq = ib_wq_get_drvdata ( wq );
+ struct QIB_7322_RcvHdrHead0 rcvhdrhead;
+ unsigned int ctx = qib7322_ctx ( ibdev, qp );
+ unsigned int header_prod;
+
+ /* Check for received packets */
+ header_prod = ( BIT_GET ( &qib7322_wq->header_prod, Value ) << 2 );
+ if ( header_prod == qib7322_wq->header_cons )
+ return;
+
+ /* Process all received packets */
+ while ( qib7322_wq->header_cons != header_prod ) {
+
+ /* Complete the receive */
+ qib7322_complete_recv ( ibdev, qp, qib7322_wq->header_cons );
+
+ /* Increment the consumer offset */
+ qib7322_wq->header_cons += QIB7322_RECV_HEADER_SIZE;
+ qib7322_wq->header_cons %= QIB7322_RECV_HEADERS_SIZE;
+
+ /* QIB7322 has only one send buffer per port for VL15,
+ * which almost always leads to send buffer exhaustion
+ * and dropped MADs. Mitigate this by refusing to
+ * process more than one VL15 MAD per poll, which will
+ * enforce interleaved TX/RX polls.
+ */
+ if ( qp->type == IB_QPT_SMI )
+ break;
+ }
+
+ /* Update consumer offset */
+ memset ( &rcvhdrhead, 0, sizeof ( rcvhdrhead ) );
+ BIT_FILL_2 ( &rcvhdrhead,
+ RcvHeadPointer, ( qib7322_wq->header_cons >> 2 ),
+ counter, 1 );
+ qib7322_writeq_array64k ( qib7322, &rcvhdrhead,
+ QIB_7322_RcvHdrHead0_offset, ctx );
+}
+
+/**
+ * Poll completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+static void qib7322_poll_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct ib_work_queue *wq;
+
+ /* Poll associated send and receive queues */
+ list_for_each_entry ( wq, &cq->work_queues, list ) {
+ if ( wq->is_send ) {
+ qib7322_poll_send_wq ( ibdev, wq->qp );
+ } else {
+ qib7322_poll_recv_wq ( ibdev, wq->qp );
+ }
+ }
+}
+
+/***************************************************************************
+ *
+ * Event queues
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Poll event queue
+ *
+ * @v ibdev Infiniband device
+ */
+static void qib7322_poll_eq ( struct ib_device *ibdev ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct QIB_7322_ErrStatus_0 errstatus;
+ unsigned int port = ( ibdev->port - QIB7322_PORT_BASE );
+
+ /* Check for and clear status bits */
+ DBG_DISABLE ( DBGLVL_IO );
+ qib7322_readq_port ( qib7322, &errstatus,
+ QIB_7322_ErrStatus_0_offset, port );
+ if ( errstatus.u.qwords[0] ) {
+ DBGC ( qib7322, "QIB7322 %p port %d status %08x%08x\n", qib7322,
+ port, errstatus.u.dwords[1], errstatus.u.dwords[0] );
+ qib7322_writeq_port ( qib7322, &errstatus,
+ QIB_7322_ErrClear_0_offset, port );
+ }
+ DBG_ENABLE ( DBGLVL_IO );
+
+ /* Check for link status changes */
+ if ( BIT_GET ( &errstatus, IBStatusChanged ) )
+ qib7322_link_state_changed ( ibdev );
+}
+
+/***************************************************************************
+ *
+ * Infiniband link-layer operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Determine supported link speeds
+ *
+ * @v qib7322 QIB7322 device
+ * @ret supported Supported link speeds
+ */
+static unsigned int qib7322_link_speed_supported ( struct qib7322 *qib7322,
+ unsigned int port ) {
+ struct QIB_7322_feature_mask features;
+ struct QIB_7322_Revision revision;
+ unsigned int supported;
+ unsigned int boardid;
+
+ /* Read the active feature mask */
+ qib7322_readq ( qib7322, &features,
+ QIB_7322_active_feature_mask_offset );
+ switch ( port ) {
+ case 0 :
+ supported = BIT_GET ( &features, Port0_Link_Speed_Supported );
+ break;
+ case 1 :
+ supported = BIT_GET ( &features, Port1_Link_Speed_Supported );
+ break;
+ default:
+ DBGC ( qib7322, "QIB7322 %p port %d is invalid\n",
+ qib7322, port );
+ supported = 0;
+ break;
+ }
+
+ /* Apply hacks for specific board IDs */
+ qib7322_readq ( qib7322, &revision, QIB_7322_Revision_offset );
+ boardid = BIT_GET ( &revision, BoardID );
+ switch ( boardid ) {
+ case QIB7322_BOARD_QMH7342 :
+ DBGC2 ( qib7322, "QIB7322 %p is a QMH7342; forcing QDR-only\n",
+ qib7322 );
+ supported = IB_LINK_SPEED_QDR;
+ break;
+ default:
+ /* Do nothing */
+ break;
+ }
+
+ DBGC2 ( qib7322, "QIB7322 %p port %d %s%s%s%s\n", qib7322, port,
+ ( supported ? "supports" : "disabled" ),
+ ( ( supported & IB_LINK_SPEED_SDR ) ? " SDR" : "" ),
+ ( ( supported & IB_LINK_SPEED_DDR ) ? " DDR" : "" ),
+ ( ( supported & IB_LINK_SPEED_QDR ) ? " QDR" : "" ) );
+ return supported;
+}
+
+/**
+ * Initialise Infiniband link
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+static int qib7322_open ( struct ib_device *ibdev ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct QIB_7322_IBCCtrlA_0 ibcctrla;
+ unsigned int port = ( ibdev->port - QIB7322_PORT_BASE );
+
+ /* Enable link */
+ qib7322_readq_port ( qib7322, &ibcctrla,
+ QIB_7322_IBCCtrlA_0_offset, port );
+ BIT_SET ( &ibcctrla, IBLinkEn, 1 );
+ qib7322_writeq_port ( qib7322, &ibcctrla,
+ QIB_7322_IBCCtrlA_0_offset, port );
+
+ return 0;
+}
+
+/**
+ * Close Infiniband link
+ *
+ * @v ibdev Infiniband device
+ */
+static void qib7322_close ( struct ib_device *ibdev ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+ struct QIB_7322_IBCCtrlA_0 ibcctrla;
+ unsigned int port = ( ibdev->port - QIB7322_PORT_BASE );
+
+ /* Disable link */
+ qib7322_readq_port ( qib7322, &ibcctrla,
+ QIB_7322_IBCCtrlA_0_offset, port );
+ BIT_SET ( &ibcctrla, IBLinkEn, 0 );
+ qib7322_writeq_port ( qib7322, &ibcctrla,
+ QIB_7322_IBCCtrlA_0_offset, port );
+}
+
+/***************************************************************************
+ *
+ * Multicast group operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Attach to multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ * @ret rc Return status code
+ */
+static int qib7322_mcast_attach ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ union ib_gid *gid ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+
+ ( void ) qib7322;
+ ( void ) qp;
+ ( void ) gid;
+ return 0;
+}
+
+/**
+ * Detach from multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ */
+static void qib7322_mcast_detach ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ union ib_gid *gid ) {
+ struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
+
+ ( void ) qib7322;
+ ( void ) qp;
+ ( void ) gid;
+ }
+
+/** QIB7322 Infiniband operations */
+static struct ib_device_operations qib7322_ib_operations = {
+ .create_cq = qib7322_create_cq,
+ .destroy_cq = qib7322_destroy_cq,
+ .create_qp = qib7322_create_qp,
+ .modify_qp = qib7322_modify_qp,
+ .destroy_qp = qib7322_destroy_qp,
+ .post_send = qib7322_post_send,
+ .post_recv = qib7322_post_recv,
+ .poll_cq = qib7322_poll_cq,
+ .poll_eq = qib7322_poll_eq,
+ .open = qib7322_open,
+ .close = qib7322_close,
+ .mcast_attach = qib7322_mcast_attach,
+ .mcast_detach = qib7322_mcast_detach,
+ .set_port_info = qib7322_set_port_info,
+ .set_pkey_table = qib7322_set_pkey_table,
+};
+
+/***************************************************************************
+ *
+ * I2C bus operations
+ *
+ ***************************************************************************
+ */
+
+/** QIB7322 I2C bit to GPIO mappings */
+static unsigned int qib7322_i2c_bits[] = {
+ [I2C_BIT_SCL] = ( 1 << QIB7322_GPIO_SCL ),
+ [I2C_BIT_SDA] = ( 1 << QIB7322_GPIO_SDA ),
+};
+
+/**
+ * Read QIB7322 I2C line status
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @ret zero Input is a logic 0
+ * @ret non-zero Input is a logic 1
+ */
+static int qib7322_i2c_read_bit ( struct bit_basher *basher,
+ unsigned int bit_id ) {
+ struct qib7322 *qib7322 =
+ container_of ( basher, struct qib7322, i2c.basher );
+ struct QIB_7322_EXTStatus extstatus;
+ unsigned int status;
+
+ DBG_DISABLE ( DBGLVL_IO );
+
+ qib7322_readq ( qib7322, &extstatus, QIB_7322_EXTStatus_offset );
+ status = ( BIT_GET ( &extstatus, GPIOIn ) & qib7322_i2c_bits[bit_id] );
+
+ DBG_ENABLE ( DBGLVL_IO );
+
+ return status;
+}
+
+/**
+ * Write QIB7322 I2C line status
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @v data Value to write
+ */
+static void qib7322_i2c_write_bit ( struct bit_basher *basher,
+ unsigned int bit_id, unsigned long data ) {
+ struct qib7322 *qib7322 =
+ container_of ( basher, struct qib7322, i2c.basher );
+ struct QIB_7322_EXTCtrl extctrl;
+ struct QIB_7322_GPIO gpioout;
+ unsigned int bit = qib7322_i2c_bits[bit_id];
+ unsigned int outputs = 0;
+ unsigned int output_enables = 0;
+
+ DBG_DISABLE ( DBGLVL_IO );
+
+ /* Read current GPIO mask and outputs */
+ qib7322_readq ( qib7322, &extctrl, QIB_7322_EXTCtrl_offset );
+ qib7322_readq ( qib7322, &gpioout, QIB_7322_GPIOOut_offset );
+
+ /* Update outputs and output enables. I2C lines are tied
+ * high, so we always set the output to 0 and use the output
+ * enable to control the line.
+ */
+ output_enables = BIT_GET ( &extctrl, GPIOOe );
+ output_enables = ( ( output_enables & ~bit ) | ( ~data & bit ) );
+ outputs = BIT_GET ( &gpioout, GPIO );
+ outputs = ( outputs & ~bit );
+ BIT_SET ( &extctrl, GPIOOe, output_enables );
+ BIT_SET ( &gpioout, GPIO, outputs );
+
+ /* Write the output enable first; that way we avoid logic
+ * hazards.
+ */
+ qib7322_writeq ( qib7322, &extctrl, QIB_7322_EXTCtrl_offset );
+ qib7322_writeq ( qib7322, &gpioout, QIB_7322_GPIOOut_offset );
+ mb();
+
+ DBG_ENABLE ( DBGLVL_IO );
+}
+
+/** QIB7322 I2C bit-bashing interface operations */
+static struct bit_basher_operations qib7322_i2c_basher_ops = {
+ .read = qib7322_i2c_read_bit,
+ .write = qib7322_i2c_write_bit,
+};
+
+/**
+ * Initialise QIB7322 I2C subsystem
+ *
+ * @v qib7322 QIB7322 device
+ * @ret rc Return status code
+ */
+static int qib7322_init_i2c ( struct qib7322 *qib7322 ) {
+ static int try_eeprom_address[] = { 0x51, 0x50 };
+ unsigned int i;
+ int rc;
+
+ /* Initialise bus */
+ if ( ( rc = init_i2c_bit_basher ( &qib7322->i2c,
+ &qib7322_i2c_basher_ops ) ) != 0 ) {
+ DBGC ( qib7322, "QIB7322 %p could not initialise I2C bus: %s\n",
+ qib7322, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Probe for devices */
+ for ( i = 0 ; i < ( sizeof ( try_eeprom_address ) /
+ sizeof ( try_eeprom_address[0] ) ) ; i++ ) {
+ init_i2c_eeprom ( &qib7322->eeprom, try_eeprom_address[i] );
+ if ( ( rc = i2c_check_presence ( &qib7322->i2c.i2c,
+ &qib7322->eeprom ) ) == 0 ) {
+ DBGC2 ( qib7322, "QIB7322 %p found EEPROM at %02x\n",
+ qib7322, try_eeprom_address[i] );
+ return 0;
+ }
+ }
+
+ DBGC ( qib7322, "QIB7322 %p could not find EEPROM\n", qib7322 );
+ return -ENODEV;
+}
+
+/**
+ * Read EEPROM parameters
+ *
+ * @v qib7322 QIB7322 device
+ * @ret rc Return status code
+ */
+static int qib7322_read_eeprom ( struct qib7322 *qib7322 ) {
+ struct i2c_interface *i2c = &qib7322->i2c.i2c;
+ union ib_guid *guid = &qib7322->guid;
+ int rc;
+
+ /* Read GUID */
+ if ( ( rc = i2c->read ( i2c, &qib7322->eeprom,
+ QIB7322_EEPROM_GUID_OFFSET, guid->bytes,
+ sizeof ( *guid ) ) ) != 0 ) {
+ DBGC ( qib7322, "QIB7322 %p could not read GUID: %s\n",
+ qib7322, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( qib7322, "QIB7322 %p has GUID " IB_GUID_FMT "\n",
+ qib7322, IB_GUID_ARGS ( guid ) );
+
+ /* Read serial number (debug only) */
+ if ( DBG_LOG ) {
+ uint8_t serial[QIB7322_EEPROM_SERIAL_SIZE + 1];
+
+ serial[ sizeof ( serial ) - 1 ] = '\0';
+ if ( ( rc = i2c->read ( i2c, &qib7322->eeprom,
+ QIB7322_EEPROM_SERIAL_OFFSET, serial,
+ ( sizeof ( serial ) - 1 ) ) ) != 0 ) {
+ DBGC ( qib7322, "QIB7322 %p could not read serial: "
+ "%s\n", qib7322, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( qib7322, "QIB7322 %p has serial number \"%s\"\n",
+ qib7322, serial );
+ }
+
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * Advanced High-performance Bus (AHB) access
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Wait for AHB transaction to complete
+ *
+ * @v qib7322 QIB7322 device
+ * @ret rc Return status code
+ */
+static int qib7322_ahb_wait ( struct qib7322 *qib7322 ) {
+ struct QIB_7322_ahb_transaction_reg transaction;
+ unsigned int i;
+
+ /* Wait for Ready bit to be asserted */
+ for ( i = 0 ; i < QIB7322_AHB_MAX_WAIT_US ; i++ ) {
+ qib7322_readq ( qib7322, &transaction,
+ QIB_7322_ahb_transaction_reg_offset );
+ if ( BIT_GET ( &transaction, ahb_rdy ) )
+ return 0;
+ udelay ( 1 );
+ }
+
+ DBGC ( qib7322, "QIB7322 %p timed out waiting for AHB transaction\n",
+ qib7322 );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Request ownership of the AHB
+ *
+ * @v qib7322 QIB7322 device
+ * @v location AHB location
+ * @ret rc Return status code
+ */
+static int qib7322_ahb_request ( struct qib7322 *qib7322,
+ unsigned int location ) {
+ struct QIB_7322_ahb_access_ctrl access;
+ int rc;
+
+ /* Request ownership */
+ memset ( &access, 0, sizeof ( access ) );
+ BIT_FILL_2 ( &access,
+ sw_ahb_sel, 1,
+ sw_sel_ahb_trgt, QIB7322_AHB_LOC_TARGET ( location ) );
+ qib7322_writeq ( qib7322, &access, QIB_7322_ahb_access_ctrl_offset );
+
+ /* Wait for ownership to be granted */
+ if ( ( rc = qib7322_ahb_wait ( qib7322 ) ) != 0 ) {
+ DBGC ( qib7322, "QIB7322 %p could not obtain AHB ownership: "
+ "%s\n", qib7322, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Release ownership of the AHB
+ *
+ * @v qib7322 QIB7322 device
+ */
+static void qib7322_ahb_release ( struct qib7322 *qib7322 ) {
+ struct QIB_7322_ahb_access_ctrl access;
+
+ memset ( &access, 0, sizeof ( access ) );
+ qib7322_writeq ( qib7322, &access, QIB_7322_ahb_access_ctrl_offset );
+}
+
+/**
+ * Read data via AHB
+ *
+ * @v qib7322 QIB7322 device
+ * @v location AHB location
+ * @v data Data to read
+ * @ret rc Return status code
+ *
+ * You must have already acquired ownership of the AHB.
+ */
+static int qib7322_ahb_read ( struct qib7322 *qib7322, unsigned int location,
+ uint32_t *data ) {
+ struct QIB_7322_ahb_transaction_reg xact;
+ int rc;
+
+ /* Initiate transaction */
+ memset ( &xact, 0, sizeof ( xact ) );
+ BIT_FILL_2 ( &xact,
+ ahb_address, QIB7322_AHB_LOC_ADDRESS ( location ),
+ write_not_read, 0 );
+ qib7322_writeq ( qib7322, &xact, QIB_7322_ahb_transaction_reg_offset );
+
+ /* Wait for transaction to complete */
+ if ( ( rc = qib7322_ahb_wait ( qib7322 ) ) != 0 )
+ return rc;
+
+ /* Read transaction data */
+ qib7322_readq ( qib7322, &xact, QIB_7322_ahb_transaction_reg_offset );
+ *data = BIT_GET ( &xact, ahb_data );
+ return 0;
+}
+
+/**
+ * Write data via AHB
+ *
+ * @v qib7322 QIB7322 device
+ * @v location AHB location
+ * @v data Data to write
+ * @ret rc Return status code
+ *
+ * You must have already acquired ownership of the AHB.
+ */
+static int qib7322_ahb_write ( struct qib7322 *qib7322, unsigned int location,
+ uint32_t data ) {
+ struct QIB_7322_ahb_transaction_reg xact;
+ int rc;
+
+ /* Initiate transaction */
+ memset ( &xact, 0, sizeof ( xact ) );
+ BIT_FILL_3 ( &xact,
+ ahb_address, QIB7322_AHB_LOC_ADDRESS ( location ),
+ write_not_read, 1,
+ ahb_data, data );
+ qib7322_writeq ( qib7322, &xact, QIB_7322_ahb_transaction_reg_offset );
+
+ /* Wait for transaction to complete */
+ if ( ( rc = qib7322_ahb_wait ( qib7322 ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Read/modify/write AHB register
+ *
+ * @v qib7322 QIB7322 device
+ * @v location AHB location
+ * @v value Value to set
+ * @v mask Mask to apply to old value
+ * @ret rc Return status code
+ */
+static int qib7322_ahb_mod_reg ( struct qib7322 *qib7322, unsigned int location,
+ uint32_t value, uint32_t mask ) {
+ uint32_t old_value;
+ uint32_t new_value;
+ int rc;
+
+ DBG_DISABLE ( DBGLVL_IO );
+
+ /* Sanity check */
+ assert ( ( value & mask ) == value );
+
+ /* Acquire bus ownership */
+ if ( ( rc = qib7322_ahb_request ( qib7322, location ) ) != 0 )
+ goto out;
+
+ /* Read existing value */
+ if ( ( rc = qib7322_ahb_read ( qib7322, location, &old_value ) ) != 0 )
+ goto out_release;
+
+ /* Update value */
+ new_value = ( ( old_value & ~mask ) | value );
+ DBGCP ( qib7322, "QIB7322 %p AHB %x %#08x => %#08x\n",
+ qib7322, location, old_value, new_value );
+ if ( ( rc = qib7322_ahb_write ( qib7322, location, new_value ) ) != 0 )
+ goto out_release;
+
+ out_release:
+ /* Release bus */
+ qib7322_ahb_release ( qib7322 );
+ out:
+ DBG_ENABLE ( DBGLVL_IO );
+ return rc;
+}
+
+/**
+ * Read/modify/write AHB register across all ports and channels
+ *
+ * @v qib7322 QIB7322 device
+ * @v reg AHB register
+ * @v value Value to set
+ * @v mask Mask to apply to old value
+ * @ret rc Return status code
+ */
+static int qib7322_ahb_mod_reg_all ( struct qib7322 *qib7322, unsigned int reg,
+ uint32_t value, uint32_t mask ) {
+ unsigned int port;
+ unsigned int channel;
+ unsigned int location;
+ int rc;
+
+ for ( port = 0 ; port < QIB7322_MAX_PORTS ; port++ ) {
+ for ( channel = 0 ; channel < QIB7322_MAX_WIDTH ; channel++ ) {
+ location = QIB7322_AHB_LOCATION ( port, channel, reg );
+ if ( ( rc = qib7322_ahb_mod_reg ( qib7322, location,
+ value, mask ) ) != 0 )
+ return rc;
+ }
+ }
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * Infiniband SerDes initialisation
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Initialise the IB SerDes
+ *
+ * @v qib7322 QIB7322 device
+ * @ret rc Return status code
+ */
+static int qib7322_init_ib_serdes ( struct qib7322 *qib7322 ) {
+ struct QIB_7322_IBCCtrlA_0 ibcctrla;
+ struct QIB_7322_IBCCtrlB_0 ibcctrlb;
+ struct QIB_7322_IBPCSConfig_0 ibpcsconfig;
+
+ /* Configure sensible defaults for IBC */
+ memset ( &ibcctrla, 0, sizeof ( ibcctrla ) );
+ BIT_FILL_5 ( &ibcctrla, /* Tuning values taken from Linux driver */
+ FlowCtrlPeriod, 0x03,
+ FlowCtrlWaterMark, 0x05,
+ MaxPktLen, ( ( QIB7322_RECV_HEADER_SIZE +
+ QIB7322_RECV_PAYLOAD_SIZE +
+ 4 /* ICRC */ ) >> 2 ),
+ PhyerrThreshold, 0xf,
+ OverrunThreshold, 0xf );
+ qib7322_writeq ( qib7322, &ibcctrla, QIB_7322_IBCCtrlA_0_offset );
+ qib7322_writeq ( qib7322, &ibcctrla, QIB_7322_IBCCtrlA_1_offset );
+
+ /* Force SDR only to avoid needing all the DDR tuning,
+ * Mellanox compatibility hacks etc. SDR is plenty for
+ * boot-time operation.
+ */
+ qib7322_readq ( qib7322, &ibcctrlb, QIB_7322_IBCCtrlB_0_offset );
+ BIT_SET ( &ibcctrlb, IB_ENHANCED_MODE, 0 );
+ BIT_SET ( &ibcctrlb, SD_SPEED_SDR, 1 );
+ BIT_SET ( &ibcctrlb, SD_SPEED_DDR, 0 );
+ BIT_SET ( &ibcctrlb, SD_SPEED_QDR, 0 );
+ BIT_SET ( &ibcctrlb, IB_NUM_CHANNELS, 1 ); /* 4X only */
+ BIT_SET ( &ibcctrlb, IB_LANE_REV_SUPPORTED, 0 );
+ BIT_SET ( &ibcctrlb, HRTBT_ENB, 0 );
+ BIT_SET ( &ibcctrlb, HRTBT_AUTO, 0 );
+ qib7322_writeq ( qib7322, &ibcctrlb, QIB_7322_IBCCtrlB_0_offset );
+ qib7322_writeq ( qib7322, &ibcctrlb, QIB_7322_IBCCtrlB_1_offset );
+
+ /* Tune SerDes */
+ qib7322_ahb_mod_reg_all ( qib7322, 2, 0, 0x00000e00UL );
+
+ /* Bring XGXS out of reset */
+ memset ( &ibpcsconfig, 0, sizeof ( ibpcsconfig ) );
+ qib7322_writeq ( qib7322, &ibpcsconfig, QIB_7322_IBPCSConfig_0_offset );
+ qib7322_writeq ( qib7322, &ibpcsconfig, QIB_7322_IBPCSConfig_1_offset );
+
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * PCI layer interface
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Reset QIB7322
+ *
+ * @v qib7322 QIB7322 device
+ * @v pci PCI device
+ * @ret rc Return status code
+ */
+static void qib7322_reset ( struct qib7322 *qib7322, struct pci_device *pci ) {
+ struct QIB_7322_Control control;
+ struct pci_config_backup backup;
+
+ /* Back up PCI configuration space */
+ pci_backup ( pci, &backup, NULL );
+
+ /* Assert reset */
+ memset ( &control, 0, sizeof ( control ) );
+ BIT_FILL_1 ( &control, SyncReset, 1 );
+ qib7322_writeq ( qib7322, &control, QIB_7322_Control_offset );
+
+ /* Wait for reset to complete */
+ mdelay ( 1000 );
+
+ /* Restore PCI configuration space */
+ pci_restore ( pci, &backup, NULL );
+}
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @v id PCI ID
+ * @ret rc Return status code
+ */
+static int qib7322_probe ( struct pci_device *pci ) {
+ struct qib7322 *qib7322;
+ struct QIB_7322_Revision revision;
+ struct ib_device *ibdev;
+ unsigned int link_speed_supported;
+ int i;
+ int rc;
+
+ /* Allocate QIB7322 device */
+ qib7322 = zalloc ( sizeof ( *qib7322 ) );
+ if ( ! qib7322 ) {
+ rc = -ENOMEM;
+ goto err_alloc_qib7322;
+ }
+ pci_set_drvdata ( pci, qib7322 );
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* Get PCI BARs */
+ qib7322->regs = ioremap ( pci->membase, QIB7322_BAR0_SIZE );
+ DBGC2 ( qib7322, "QIB7322 %p has BAR at %08lx\n",
+ qib7322, pci->membase );
+
+ /* Reset device */
+ qib7322_reset ( qib7322, pci );
+
+ /* Print some general data */
+ qib7322_readq ( qib7322, &revision, QIB_7322_Revision_offset );
+ DBGC2 ( qib7322, "QIB7322 %p board %02lx v%ld.%ld.%ld.%ld\n", qib7322,
+ BIT_GET ( &revision, BoardID ),
+ BIT_GET ( &revision, R_SW ),
+ BIT_GET ( &revision, R_Arch ),
+ BIT_GET ( &revision, R_ChipRevMajor ),
+ BIT_GET ( &revision, R_ChipRevMinor ) );
+
+ /* Initialise I2C subsystem */
+ if ( ( rc = qib7322_init_i2c ( qib7322 ) ) != 0 )
+ goto err_init_i2c;
+
+ /* Read EEPROM parameters */
+ if ( ( rc = qib7322_read_eeprom ( qib7322 ) ) != 0 )
+ goto err_read_eeprom;
+
+ /* Initialise send datapath */
+ if ( ( rc = qib7322_init_send ( qib7322 ) ) != 0 )
+ goto err_init_send;
+
+ /* Initialise receive datapath */
+ if ( ( rc = qib7322_init_recv ( qib7322 ) ) != 0 )
+ goto err_init_recv;
+
+ /* Initialise the IB SerDes */
+ if ( ( rc = qib7322_init_ib_serdes ( qib7322 ) ) != 0 )
+ goto err_init_ib_serdes;
+
+ /* Allocate Infiniband devices */
+ for ( i = 0 ; i < QIB7322_MAX_PORTS ; i++ ) {
+ link_speed_supported =
+ qib7322_link_speed_supported ( qib7322, i );
+ if ( ! link_speed_supported )
+ continue;
+ ibdev = alloc_ibdev ( 0 );
+ if ( ! ibdev ) {
+ rc = -ENOMEM;
+ goto err_alloc_ibdev;
+ }
+ qib7322->ibdev[i] = ibdev;
+ ibdev->dev = &pci->dev;
+ ibdev->op = &qib7322_ib_operations;
+ ibdev->port = ( QIB7322_PORT_BASE + i );
+ ibdev->link_width_enabled = ibdev->link_width_supported =
+ IB_LINK_WIDTH_4X; /* 1x does not work */
+ ibdev->link_speed_enabled = ibdev->link_speed_supported =
+ IB_LINK_SPEED_SDR; /* to avoid need for link tuning */
+ memcpy ( &ibdev->node_guid, &qib7322->guid,
+ sizeof ( ibdev->node_guid ) );
+ memcpy ( &ibdev->gid.s.guid, &qib7322->guid,
+ sizeof ( ibdev->gid.s.guid ) );
+ assert ( ( ibdev->gid.s.guid.bytes[7] & i ) == 0 );
+ ibdev->gid.s.guid.bytes[7] |= i;
+ ib_set_drvdata ( ibdev, qib7322 );
+ }
+
+ /* Register Infiniband devices */
+ for ( i = 0 ; i < QIB7322_MAX_PORTS ; i++ ) {
+ if ( ! qib7322->ibdev[i] )
+ continue;
+ if ( ( rc = register_ibdev ( qib7322->ibdev[i] ) ) != 0 ) {
+ DBGC ( qib7322, "QIB7322 %p port %d could not register "
+ "IB device: %s\n", qib7322, i, strerror ( rc ) );
+ goto err_register_ibdev;
+ }
+ }
+
+ return 0;
+
+ i = QIB7322_MAX_PORTS;
+ err_register_ibdev:
+ for ( i-- ; i >= 0 ; i-- ) {
+ if ( qib7322->ibdev[i] )
+ unregister_ibdev ( qib7322->ibdev[i] );
+ }
+ i = QIB7322_MAX_PORTS;
+ err_alloc_ibdev:
+ for ( i-- ; i >= 0 ; i-- )
+ ibdev_put ( qib7322->ibdev[i] );
+ err_init_ib_serdes:
+ qib7322_fini_send ( qib7322 );
+ err_init_send:
+ qib7322_fini_recv ( qib7322 );
+ err_init_recv:
+ err_read_eeprom:
+ err_init_i2c:
+ free ( qib7322 );
+ err_alloc_qib7322:
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void qib7322_remove ( struct pci_device *pci ) {
+ struct qib7322 *qib7322 = pci_get_drvdata ( pci );
+ int i;
+
+ for ( i = ( QIB7322_MAX_PORTS - 1 ) ; i >= 0 ; i-- ) {
+ if ( qib7322->ibdev[i] )
+ unregister_ibdev ( qib7322->ibdev[i] );
+ }
+ for ( i = ( QIB7322_MAX_PORTS - 1 ) ; i >= 0 ; i-- )
+ ibdev_put ( qib7322->ibdev[i] );
+ qib7322_fini_send ( qib7322 );
+ qib7322_fini_recv ( qib7322 );
+ free ( qib7322 );
+}
+
+static struct pci_device_id qib7322_nics[] = {
+ PCI_ROM ( 0x1077, 0x7322, "iba7322", "IBA7322 QDR InfiniBand HCA", 0 ),
+};
+
+struct pci_driver qib7322_driver __pci_driver = {
+ .ids = qib7322_nics,
+ .id_count = ( sizeof ( qib7322_nics ) / sizeof ( qib7322_nics[0] ) ),
+ .probe = qib7322_probe,
+ .remove = qib7322_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib7322.h b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib7322.h
new file mode 100644
index 00000000..0dac09ef
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib7322.h
@@ -0,0 +1,364 @@
+#ifndef _QIB7322_H
+#define _QIB7322_H
+
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * QLogic QIB7322 Infiniband HCA
+ *
+ */
+
+#define BITOPS_LITTLE_ENDIAN
+#include <ipxe/bitops.h>
+#include "qib_7322_regs.h"
+
+/** A QIB7322 GPIO register */
+struct QIB_7322_GPIO_pb {
+ pseudo_bit_t GPIO[16];
+ pseudo_bit_t Reserved[48];
+};
+struct QIB_7322_GPIO {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_GPIO_pb );
+};
+
+/** A QIB7322 general scalar register */
+struct QIB_7322_scalar_pb {
+ pseudo_bit_t Value[64];
+};
+struct QIB_7322_scalar {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_scalar_pb );
+};
+
+/** QIB7322 feature mask */
+struct QIB_7322_feature_mask_pb {
+ pseudo_bit_t Port0_Link_Speed_Supported[3];
+ pseudo_bit_t Port1_Link_Speed_Supported[3];
+ pseudo_bit_t _unused_0[58];
+};
+struct QIB_7322_feature_mask {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_feature_mask_pb );
+};
+
+/** QIB7322 send per-buffer control word */
+struct QIB_7322_SendPbc_pb {
+ pseudo_bit_t LengthP1_toibc[11];
+ pseudo_bit_t Reserved1[4];
+ pseudo_bit_t LengthP1_trigger[11];
+ pseudo_bit_t Reserved2[3];
+ pseudo_bit_t TestEbp[1];
+ pseudo_bit_t Test[1];
+ pseudo_bit_t Intr[1];
+ pseudo_bit_t StaticRateControlCnt[14];
+ pseudo_bit_t Reserved3[12];
+ pseudo_bit_t Port[1];
+ pseudo_bit_t VLane[3];
+ pseudo_bit_t Reserved4[1];
+ pseudo_bit_t VL15[1];
+};
+struct QIB_7322_SendPbc {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendPbc_pb );
+};
+
+/** QIB7322 send buffer availability */
+struct QIB_7322_SendBufAvail_pb {
+ pseudo_bit_t InUseCheck[162][2];
+ pseudo_bit_t Reserved[60];
+};
+struct QIB_7322_SendBufAvail {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendBufAvail_pb );
+};
+
+/** DMA alignment for send buffer availability */
+#define QIB7322_SENDBUFAVAIL_ALIGN 64
+
+/** QIB7322 port-specific receive control */
+struct QIB_7322_RcvCtrl_P_pb {
+ pseudo_bit_t ContextEnable[18];
+ pseudo_bit_t _unused_1[21];
+ pseudo_bit_t RcvIBPortEnable[1];
+ pseudo_bit_t RcvQPMapEnable[1];
+ pseudo_bit_t RcvPartitionKeyDisable[1];
+ pseudo_bit_t RcvResetCredit[1];
+ pseudo_bit_t _unused_2[21];
+};
+struct QIB_7322_RcvCtrl_P {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvCtrl_P_pb );
+};
+
+/** A QIB7322 eager receive descriptor */
+struct QIB_7322_RcvEgr_pb {
+ pseudo_bit_t Addr[37];
+ pseudo_bit_t BufSize[3];
+ pseudo_bit_t Reserved[24];
+};
+struct QIB_7322_RcvEgr {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvEgr_pb );
+};
+
+/** QIB7322 receive header flags */
+struct QIB_7322_RcvHdrFlags_pb {
+ pseudo_bit_t PktLen[11];
+ pseudo_bit_t RcvType[3];
+ pseudo_bit_t SoftB[1];
+ pseudo_bit_t SoftA[1];
+ pseudo_bit_t EgrIndex[12];
+ pseudo_bit_t Reserved1[3];
+ pseudo_bit_t UseEgrBfr[1];
+ pseudo_bit_t RcvSeq[4];
+ pseudo_bit_t HdrqOffset[11];
+ pseudo_bit_t Reserved2[8];
+ pseudo_bit_t IBErr[1];
+ pseudo_bit_t MKErr[1];
+ pseudo_bit_t TIDErr[1];
+ pseudo_bit_t KHdrErr[1];
+ pseudo_bit_t MTUErr[1];
+ pseudo_bit_t LenErr[1];
+ pseudo_bit_t ParityErr[1];
+ pseudo_bit_t VCRCErr[1];
+ pseudo_bit_t ICRCErr[1];
+};
+struct QIB_7322_RcvHdrFlags {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrFlags_pb );
+};
+
+/** QIB7322 DDS tuning parameters */
+struct QIB_7322_IBSD_DDS_MAP_TABLE_pb {
+ pseudo_bit_t Pre[3];
+ pseudo_bit_t PreXtra[2];
+ pseudo_bit_t Post[4];
+ pseudo_bit_t Main[5];
+ pseudo_bit_t Amp[4];
+ pseudo_bit_t _unused_0[46];
+};
+struct QIB_7322_IBSD_DDS_MAP_TABLE {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBSD_DDS_MAP_TABLE_pb );
+};
+
+/** QIB7322 memory BAR size */
+#define QIB7322_BAR0_SIZE 0x400000
+
+/** QIB7322 base port number */
+#define QIB7322_PORT_BASE 1
+
+/** QIB7322 maximum number of ports */
+#define QIB7322_MAX_PORTS 2
+
+/** QIB7322 maximum width */
+#define QIB7322_MAX_WIDTH 4
+
+/** QIB7322 board identifiers */
+enum qib7322_board_id {
+ QIB7322_BOARD_QLE7342_EMULATION = 0,
+ QIB7322_BOARD_QLE7340 = 1,
+ QIB7322_BOARD_QLE7342 = 2,
+ QIB7322_BOARD_QMI7342 = 3,
+ QIB7322_BOARD_QMH7342_UNSUPPORTED = 4,
+ QIB7322_BOARD_QME7342 = 5,
+ QIB7322_BOARD_QMH7342 = 6,
+ QIB7322_BOARD_QLE7342_TEST = 15,
+};
+
+/** QIB7322 I2C SCL line GPIO number */
+#define QIB7322_GPIO_SCL 0
+
+/** QIB7322 I2C SDA line GPIO number */
+#define QIB7322_GPIO_SDA 1
+
+/** GUID offset within EEPROM */
+#define QIB7322_EEPROM_GUID_OFFSET 3
+
+/** GUID size within EEPROM */
+#define QIB7322_EEPROM_GUID_SIZE 8
+
+/** Board serial number offset within EEPROM */
+#define QIB7322_EEPROM_SERIAL_OFFSET 12
+
+/** Board serial number size within EEPROM */
+#define QIB7322_EEPROM_SERIAL_SIZE 12
+
+/** QIB7322 small send buffer size */
+#define QIB7322_SMALL_SEND_BUF_SIZE 4096
+
+/** QIB7322 small send buffer starting index */
+#define QIB7322_SMALL_SEND_BUF_START 0
+
+/** QIB7322 small send buffer count */
+#define QIB7322_SMALL_SEND_BUF_COUNT 128
+
+/** QIB7322 large send buffer size */
+#define QIB7322_LARGE_SEND_BUF_SIZE 8192
+
+/** QIB7322 large send buffer starting index */
+#define QIB7322_LARGE_SEND_BUF_START 128
+
+/** QIB7322 large send buffer count */
+#define QIB7322_LARGE_SEND_BUF_COUNT 32
+
+/** QIB7322 VL15 port 0 send buffer starting index */
+#define QIB7322_VL15_PORT0_SEND_BUF_START 160
+
+/** QIB7322 VL15 port 0 send buffer count */
+#define QIB7322_VL15_PORT0_SEND_BUF_COUNT 1
+
+/** QIB7322 VL15 port 0 send buffer size */
+#define QIB7322_VL15_PORT0_SEND_BUF_SIZE 8192
+
+/** QIB7322 VL15 port 0 send buffer starting index */
+#define QIB7322_VL15_PORT1_SEND_BUF_START 161
+
+/** QIB7322 VL15 port 0 send buffer count */
+#define QIB7322_VL15_PORT1_SEND_BUF_COUNT 1
+
+/** QIB7322 VL15 port 0 send buffer size */
+#define QIB7322_VL15_PORT1_SEND_BUF_SIZE 8192
+
+/** Number of small send buffers used
+ *
+ * This is a policy decision. Must be less than or equal to the total
+ * number of small send buffers supported by the hardware
+ * (QIB7322_SMALL_SEND_BUF_COUNT).
+ */
+#define QIB7322_SMALL_SEND_BUF_USED 32
+
+/** Number of contexts (including kernel context)
+ *
+ * This is a policy decision. Must be 6, 10 or 18.
+ */
+#define QIB7322_NUM_CONTEXTS 6
+
+/** ContextCfg values for different numbers of contexts */
+enum qib7322_contextcfg {
+ QIB7322_CONTEXTCFG_6CTX = 0,
+ QIB7322_CONTEXTCFG_10CTX = 1,
+ QIB7322_CONTEXTCFG_18CTX = 2,
+};
+
+/** ContextCfg values for different numbers of contexts */
+#define QIB7322_EAGER_ARRAY_SIZE_6CTX_KERNEL 1024
+#define QIB7322_EAGER_ARRAY_SIZE_6CTX_USER 4096
+#define QIB7322_EAGER_ARRAY_SIZE_10CTX_KERNEL 1024
+#define QIB7322_EAGER_ARRAY_SIZE_10CTX_USER 2048
+#define QIB7322_EAGER_ARRAY_SIZE_18CTX_KERNEL 1024
+#define QIB7322_EAGER_ARRAY_SIZE_18CTX_USER 1024
+
+/** Eager buffer required alignment */
+#define QIB7322_EAGER_BUFFER_ALIGN 2048
+
+/** Eager buffer size encodings */
+enum qib7322_eager_buffer_size {
+ QIB7322_EAGER_BUFFER_NONE = 0,
+ QIB7322_EAGER_BUFFER_2K = 1,
+ QIB7322_EAGER_BUFFER_4K = 2,
+ QIB7322_EAGER_BUFFER_8K = 3,
+ QIB7322_EAGER_BUFFER_16K = 4,
+ QIB7322_EAGER_BUFFER_32K = 5,
+ QIB7322_EAGER_BUFFER_64K = 6,
+};
+
+/** Number of RX headers per context
+ *
+ * This is a policy decision.
+ */
+#define QIB7322_RECV_HEADER_COUNT 8
+
+/** Maximum size of each RX header
+ *
+ * This is a policy decision. Must be divisible by 4.
+ */
+#define QIB7322_RECV_HEADER_SIZE 96
+
+/** Total size of an RX header ring */
+#define QIB7322_RECV_HEADERS_SIZE \
+ ( QIB7322_RECV_HEADER_SIZE * QIB7322_RECV_HEADER_COUNT )
+
+/** RX header alignment */
+#define QIB7322_RECV_HEADERS_ALIGN 64
+
+/** RX payload size
+ *
+ * This is a policy decision. Must be a valid eager buffer size.
+ */
+#define QIB7322_RECV_PAYLOAD_SIZE 2048
+
+/** Maximum number of credits per port
+ *
+ * 64kB of internal RX buffer space, in units of 64 bytes, split
+ * between two ports.
+ */
+#define QIB7322_MAX_CREDITS ( ( 65536 / 64 ) / QIB7322_MAX_PORTS )
+
+/** Number of credits to advertise for VL15
+ *
+ * This is a policy decision. Using 9 credits allows for 9*64=576
+ * bytes, which is enough for two MADs.
+ */
+#define QIB7322_MAX_CREDITS_VL15 9
+
+/** Number of credits to advertise for VL0
+ *
+ * This is a policy decision.
+ */
+#define QIB7322_MAX_CREDITS_VL0 \
+ ( QIB7322_MAX_CREDITS - QIB7322_MAX_CREDITS_VL15 )
+
+/** QPN used for Infinipath Packets
+ *
+ * This is a policy decision. Must have bit 0 clear. Must not be a
+ * QPN that we will use.
+ */
+#define QIB7322_QP_IDETH 0xdead0
+
+/** Maximum time for wait for AHB, in us */
+#define QIB7322_AHB_MAX_WAIT_US 500
+
+/** QIB7322 AHB locations */
+#define QIB7322_AHB_LOC_ADDRESS( _location ) ( (_location) & 0xffff )
+#define QIB7322_AHB_LOC_TARGET( _location ) ( (_location) >> 16 )
+#define QIB7322_AHB_CHAN_0 0
+#define QIB7322_AHB_CHAN_1 1
+#define QIB7322_AHB_PLL 2
+#define QIB7322_AHB_CHAN_2 3
+#define QIB7322_AHB_CHAN_3 4
+#define QIB7322_AHB_SUBSYS 5
+#define QIB7322_AHB_CHAN( _channel ) ( (_channel) + ( (_channel) >> 1 ) )
+#define QIB7322_AHB_TARGET_0 2
+#define QIB7322_AHB_TARGET_1 3
+#define QIB7322_AHB_TARGET( _port ) ( (_port) + 2 )
+#define QIB7322_AHB_LOCATION( _port, _channel, _register ) \
+ ( ( QIB7322_AHB_TARGET(_port) << 16 ) | \
+ ( QIB7322_AHB_CHAN(_channel) << 7 ) | \
+ ( (_register) << 1 ) )
+
+/** QIB7322 link states */
+enum qib7322_link_state {
+ QIB7322_LINK_STATE_DOWN = 0,
+ QIB7322_LINK_STATE_INIT = 1,
+ QIB7322_LINK_STATE_ARM = 2,
+ QIB7322_LINK_STATE_ACTIVE = 3,
+ QIB7322_LINK_STATE_ACT_DEFER = 4,
+};
+
+/** Maximum time to wait for link state changes, in us */
+#define QIB7322_LINK_STATE_MAX_WAIT_US 20
+
+#endif /* _QIB7322_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib_7220_regs.h b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib_7220_regs.h
new file mode 100644
index 00000000..0637ec80
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib_7220_regs.h
@@ -0,0 +1,1762 @@
+/*
+ * Copyright (c) 2008, 2009 QLogic Corporation. All rights reserved.
+ *
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+/* This file is mechanically generated from RTL. Any hand-edits will be lost! */
+
+/* This file has been further processed by ./drivers/infiniband/qib_genbits.pl */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#define QIB_7220_Revision_offset 0x00000000UL
+struct QIB_7220_Revision_pb {
+ pseudo_bit_t R_ChipRevMinor[8];
+ pseudo_bit_t R_ChipRevMajor[8];
+ pseudo_bit_t R_Arch[8];
+ pseudo_bit_t R_SW[8];
+ pseudo_bit_t BoardID[8];
+ pseudo_bit_t R_Emulation_Revcode[22];
+ pseudo_bit_t R_Emulation[1];
+ pseudo_bit_t R_Simulator[1];
+};
+struct QIB_7220_Revision {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_Revision_pb );
+};
+
+#define QIB_7220_Control_offset 0x00000008UL
+struct QIB_7220_Control_pb {
+ pseudo_bit_t SyncReset[1];
+ pseudo_bit_t FreezeMode[1];
+ pseudo_bit_t LinkEn[1];
+ pseudo_bit_t PCIERetryBufDiagEn[1];
+ pseudo_bit_t TxLatency[1];
+ pseudo_bit_t Reserved[1];
+ pseudo_bit_t PCIECplQDiagEn[1];
+ pseudo_bit_t SyncResetExceptPcieIRAMRST[1];
+ pseudo_bit_t _unused_0[56];
+};
+struct QIB_7220_Control {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_Control_pb );
+};
+
+#define QIB_7220_PageAlign_offset 0x00000010UL
+
+#define QIB_7220_PortCnt_offset 0x00000018UL
+
+#define QIB_7220_DbgPortSel_offset 0x00000020UL
+struct QIB_7220_DbgPortSel_pb {
+ pseudo_bit_t NibbleSel0[4];
+ pseudo_bit_t NibbleSel1[4];
+ pseudo_bit_t NibbleSel2[4];
+ pseudo_bit_t NibbleSel3[4];
+ pseudo_bit_t NibbleSel4[4];
+ pseudo_bit_t NibbleSel5[4];
+ pseudo_bit_t NibbleSel6[4];
+ pseudo_bit_t NibbleSel7[4];
+ pseudo_bit_t SrcMuxSel[14];
+ pseudo_bit_t DbgClkPortSel[5];
+ pseudo_bit_t EnDbgPort[1];
+ pseudo_bit_t EnEnhancedDebugMode[1];
+ pseudo_bit_t EnhMode_SrcMuxSelIndex[10];
+ pseudo_bit_t EnhMode_SrcMuxSelWrEn[1];
+};
+struct QIB_7220_DbgPortSel {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_DbgPortSel_pb );
+};
+
+#define QIB_7220_DebugSigsIntSel_offset 0x00000028UL
+struct QIB_7220_DebugSigsIntSel_pb {
+ pseudo_bit_t debug_port_sel_pcs_pipe_lane07[3];
+ pseudo_bit_t debug_port_sel_pcs_pipe_lane815[3];
+ pseudo_bit_t debug_port_sel_pcs_sdout[1];
+ pseudo_bit_t debug_port_sel_pcs_symlock_elfifo_lane[4];
+ pseudo_bit_t debug_port_sel_pcs_rxdet_encdec_lane[4];
+ pseudo_bit_t debug_port_sel_pcie_rx_tx[1];
+ pseudo_bit_t debug_port_sel_xgxs[4];
+ pseudo_bit_t debug_port_sel_epb_pcie[1];
+ pseudo_bit_t _unused_0[43];
+};
+struct QIB_7220_DebugSigsIntSel {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_DebugSigsIntSel_pb );
+};
+
+#define QIB_7220_SendRegBase_offset 0x00000030UL
+
+#define QIB_7220_UserRegBase_offset 0x00000038UL
+
+#define QIB_7220_CntrRegBase_offset 0x00000040UL
+
+#define QIB_7220_Scratch_offset 0x00000048UL
+
+#define QIB_7220_REG_000050_offset 0x00000050UL
+
+#define QIB_7220_IntBlocked_offset 0x00000060UL
+struct QIB_7220_IntBlocked_pb {
+ pseudo_bit_t RcvAvail0IntBlocked[1];
+ pseudo_bit_t RcvAvail1IntBlocked[1];
+ pseudo_bit_t RcvAvail2IntBlocked[1];
+ pseudo_bit_t RcvAvail3IntBlocked[1];
+ pseudo_bit_t RcvAvail4IntBlocked[1];
+ pseudo_bit_t RcvAvail5IntBlocked[1];
+ pseudo_bit_t RcvAvail6IntBlocked[1];
+ pseudo_bit_t RcvAvail7IntBlocked[1];
+ pseudo_bit_t RcvAvail8IntBlocked[1];
+ pseudo_bit_t RcvAvail9IntBlocked[1];
+ pseudo_bit_t RcvAvail10IntBlocked[1];
+ pseudo_bit_t RcvAvail11IntBlocked[1];
+ pseudo_bit_t RcvAvail12IntBlocked[1];
+ pseudo_bit_t RcvAvail13IntBlocked[1];
+ pseudo_bit_t RcvAvail14IntBlocked[1];
+ pseudo_bit_t RcvAvail15IntBlocked[1];
+ pseudo_bit_t RcvAvail16IntBlocked[1];
+ pseudo_bit_t Reserved1[9];
+ pseudo_bit_t JIntBlocked[1];
+ pseudo_bit_t IBSerdesTrimDoneIntBlocked[1];
+ pseudo_bit_t assertGPIOIntBlocked[1];
+ pseudo_bit_t PioBufAvailIntBlocked[1];
+ pseudo_bit_t PioSetIntBlocked[1];
+ pseudo_bit_t ErrorIntBlocked[1];
+ pseudo_bit_t RcvUrg0IntBlocked[1];
+ pseudo_bit_t RcvUrg1IntBlocked[1];
+ pseudo_bit_t RcvUrg2IntBlocked[1];
+ pseudo_bit_t RcvUrg3IntBlocked[1];
+ pseudo_bit_t RcvUrg4IntBlocked[1];
+ pseudo_bit_t RcvUrg5IntBlocked[1];
+ pseudo_bit_t RcvUrg6IntBlocked[1];
+ pseudo_bit_t RcvUrg7IntBlocked[1];
+ pseudo_bit_t RcvUrg8IntBlocked[1];
+ pseudo_bit_t RcvUrg9IntBlocked[1];
+ pseudo_bit_t RcvUrg10IntBlocked[1];
+ pseudo_bit_t RcvUrg11IntBlocked[1];
+ pseudo_bit_t RcvUrg12IntBlocked[1];
+ pseudo_bit_t RcvUrg13IntBlocked[1];
+ pseudo_bit_t RcvUrg14IntBlocked[1];
+ pseudo_bit_t RcvUrg15IntBlocked[1];
+ pseudo_bit_t RcvUrg16IntBlocked[1];
+ pseudo_bit_t Reserved[13];
+ pseudo_bit_t SDmaDisabledBlocked[1];
+ pseudo_bit_t SDmaIntBlocked[1];
+};
+struct QIB_7220_IntBlocked {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_IntBlocked_pb );
+};
+
+#define QIB_7220_IntMask_offset 0x00000068UL
+struct QIB_7220_IntMask_pb {
+ pseudo_bit_t RcvAvail0IntMask[1];
+ pseudo_bit_t RcvAvail1IntMask[1];
+ pseudo_bit_t RcvAvail2IntMask[1];
+ pseudo_bit_t RcvAvail3IntMask[1];
+ pseudo_bit_t RcvAvail4IntMask[1];
+ pseudo_bit_t RcvAvail5IntMask[1];
+ pseudo_bit_t RcvAvail6IntMask[1];
+ pseudo_bit_t RcvAvail7IntMask[1];
+ pseudo_bit_t RcvAvail8IntMask[1];
+ pseudo_bit_t RcvAvail9IntMask[1];
+ pseudo_bit_t RcvAvail10IntMask[1];
+ pseudo_bit_t RcvAvail11IntMask[1];
+ pseudo_bit_t RcvAvail12IntMask[1];
+ pseudo_bit_t RcvAvail13IntMask[1];
+ pseudo_bit_t RcvAvail14IntMask[1];
+ pseudo_bit_t RcvAvail15IntMask[1];
+ pseudo_bit_t RcvAvail16IntMask[1];
+ pseudo_bit_t Reserved1[9];
+ pseudo_bit_t JIntMask[1];
+ pseudo_bit_t IBSerdesTrimDoneIntMask[1];
+ pseudo_bit_t assertGPIOIntMask[1];
+ pseudo_bit_t PioBufAvailIntMask[1];
+ pseudo_bit_t PioSetIntMask[1];
+ pseudo_bit_t ErrorIntMask[1];
+ pseudo_bit_t RcvUrg0IntMask[1];
+ pseudo_bit_t RcvUrg1IntMask[1];
+ pseudo_bit_t RcvUrg2IntMask[1];
+ pseudo_bit_t RcvUrg3IntMask[1];
+ pseudo_bit_t RcvUrg4IntMask[1];
+ pseudo_bit_t RcvUrg5IntMask[1];
+ pseudo_bit_t RcvUrg6IntMask[1];
+ pseudo_bit_t RcvUrg7IntMask[1];
+ pseudo_bit_t RcvUrg8IntMask[1];
+ pseudo_bit_t RcvUrg9IntMask[1];
+ pseudo_bit_t RcvUrg10IntMask[1];
+ pseudo_bit_t RcvUrg11IntMask[1];
+ pseudo_bit_t RcvUrg12IntMask[1];
+ pseudo_bit_t RcvUrg13IntMask[1];
+ pseudo_bit_t RcvUrg14IntMask[1];
+ pseudo_bit_t RcvUrg15IntMask[1];
+ pseudo_bit_t RcvUrg16IntMask[1];
+ pseudo_bit_t Reserved[13];
+ pseudo_bit_t SDmaDisabledMasked[1];
+ pseudo_bit_t SDmaIntMask[1];
+};
+struct QIB_7220_IntMask {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_IntMask_pb );
+};
+
+#define QIB_7220_IntStatus_offset 0x00000070UL
+struct QIB_7220_IntStatus_pb {
+ pseudo_bit_t RcvAvail0[1];
+ pseudo_bit_t RcvAvail1[1];
+ pseudo_bit_t RcvAvail2[1];
+ pseudo_bit_t RcvAvail3[1];
+ pseudo_bit_t RcvAvail4[1];
+ pseudo_bit_t RcvAvail5[1];
+ pseudo_bit_t RcvAvail6[1];
+ pseudo_bit_t RcvAvail7[1];
+ pseudo_bit_t RcvAvail8[1];
+ pseudo_bit_t RcvAvail9[1];
+ pseudo_bit_t RcvAvail10[1];
+ pseudo_bit_t RcvAvail11[1];
+ pseudo_bit_t RcvAvail12[1];
+ pseudo_bit_t RcvAvail13[1];
+ pseudo_bit_t RcvAvail14[1];
+ pseudo_bit_t RcvAvail15[1];
+ pseudo_bit_t RcvAvail16[1];
+ pseudo_bit_t Reserved1[9];
+ pseudo_bit_t JInt[1];
+ pseudo_bit_t IBSerdesTrimDone[1];
+ pseudo_bit_t assertGPIO[1];
+ pseudo_bit_t PioBufAvail[1];
+ pseudo_bit_t PioSent[1];
+ pseudo_bit_t Error[1];
+ pseudo_bit_t RcvUrg0[1];
+ pseudo_bit_t RcvUrg1[1];
+ pseudo_bit_t RcvUrg2[1];
+ pseudo_bit_t RcvUrg3[1];
+ pseudo_bit_t RcvUrg4[1];
+ pseudo_bit_t RcvUrg5[1];
+ pseudo_bit_t RcvUrg6[1];
+ pseudo_bit_t RcvUrg7[1];
+ pseudo_bit_t RcvUrg8[1];
+ pseudo_bit_t RcvUrg9[1];
+ pseudo_bit_t RcvUrg10[1];
+ pseudo_bit_t RcvUrg11[1];
+ pseudo_bit_t RcvUrg12[1];
+ pseudo_bit_t RcvUrg13[1];
+ pseudo_bit_t RcvUrg14[1];
+ pseudo_bit_t RcvUrg15[1];
+ pseudo_bit_t RcvUrg16[1];
+ pseudo_bit_t Reserved[13];
+ pseudo_bit_t SDmaDisabled[1];
+ pseudo_bit_t SDmaInt[1];
+};
+struct QIB_7220_IntStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_IntStatus_pb );
+};
+
+#define QIB_7220_IntClear_offset 0x00000078UL
+struct QIB_7220_IntClear_pb {
+ pseudo_bit_t RcvAvail0IntClear[1];
+ pseudo_bit_t RcvAvail1IntClear[1];
+ pseudo_bit_t RcvAvail2IntClear[1];
+ pseudo_bit_t RcvAvail3IntClear[1];
+ pseudo_bit_t RcvAvail4IntClear[1];
+ pseudo_bit_t RcvAvail5IntClear[1];
+ pseudo_bit_t RcvAvail6IntClear[1];
+ pseudo_bit_t RcvAvail7IntClear[1];
+ pseudo_bit_t RcvAvail8IntClear[1];
+ pseudo_bit_t RcvAvail9IntClear[1];
+ pseudo_bit_t RcvAvail10IntClear[1];
+ pseudo_bit_t RcvAvail11IntClear[1];
+ pseudo_bit_t RcvAvail12IntClear[1];
+ pseudo_bit_t RcvAvail13IntClear[1];
+ pseudo_bit_t RcvAvail14IntClear[1];
+ pseudo_bit_t RcvAvail15IntClear[1];
+ pseudo_bit_t RcvAvail16IntClear[1];
+ pseudo_bit_t Reserved1[9];
+ pseudo_bit_t JIntClear[1];
+ pseudo_bit_t IBSerdesTrimDoneClear[1];
+ pseudo_bit_t assertGPIOIntClear[1];
+ pseudo_bit_t PioBufAvailIntClear[1];
+ pseudo_bit_t PioSetIntClear[1];
+ pseudo_bit_t ErrorIntClear[1];
+ pseudo_bit_t RcvUrg0IntClear[1];
+ pseudo_bit_t RcvUrg1IntClear[1];
+ pseudo_bit_t RcvUrg2IntClear[1];
+ pseudo_bit_t RcvUrg3IntClear[1];
+ pseudo_bit_t RcvUrg4IntClear[1];
+ pseudo_bit_t RcvUrg5IntClear[1];
+ pseudo_bit_t RcvUrg6IntClear[1];
+ pseudo_bit_t RcvUrg7IntClear[1];
+ pseudo_bit_t RcvUrg8IntClear[1];
+ pseudo_bit_t RcvUrg9IntClear[1];
+ pseudo_bit_t RcvUrg10IntClear[1];
+ pseudo_bit_t RcvUrg11IntClear[1];
+ pseudo_bit_t RcvUrg12IntClear[1];
+ pseudo_bit_t RcvUrg13IntClear[1];
+ pseudo_bit_t RcvUrg14IntClear[1];
+ pseudo_bit_t RcvUrg15IntClear[1];
+ pseudo_bit_t RcvUrg16IntClear[1];
+ pseudo_bit_t Reserved[13];
+ pseudo_bit_t SDmaDisabledClear[1];
+ pseudo_bit_t SDmaIntClear[1];
+};
+struct QIB_7220_IntClear {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_IntClear_pb );
+};
+
+#define QIB_7220_ErrMask_offset 0x00000080UL
+struct QIB_7220_ErrMask_pb {
+ pseudo_bit_t RcvFormatErrMask[1];
+ pseudo_bit_t RcvVCRCErrMask[1];
+ pseudo_bit_t RcvICRCErrMask[1];
+ pseudo_bit_t RcvMinPktLenErrMask[1];
+ pseudo_bit_t RcvMaxPktLenErrMask[1];
+ pseudo_bit_t RcvLongPktLenErrMask[1];
+ pseudo_bit_t RcvShortPktLenErrMask[1];
+ pseudo_bit_t RcvUnexpectedCharErrMask[1];
+ pseudo_bit_t RcvUnsupportedVLErrMask[1];
+ pseudo_bit_t RcvEBPErrMask[1];
+ pseudo_bit_t RcvIBFlowErrMask[1];
+ pseudo_bit_t RcvBadVersionErrMask[1];
+ pseudo_bit_t RcvEgrFullErrMask[1];
+ pseudo_bit_t RcvHdrFullErrMask[1];
+ pseudo_bit_t RcvBadTidErrMask[1];
+ pseudo_bit_t RcvHdrLenErrMask[1];
+ pseudo_bit_t RcvHdrErrMask[1];
+ pseudo_bit_t RcvIBLostLinkErrMask[1];
+ pseudo_bit_t Reserved1[9];
+ pseudo_bit_t SendSpecialTriggerErrMask[1];
+ pseudo_bit_t SDmaDisabledErrMask[1];
+ pseudo_bit_t SendMinPktLenErrMask[1];
+ pseudo_bit_t SendMaxPktLenErrMask[1];
+ pseudo_bit_t SendUnderRunErrMask[1];
+ pseudo_bit_t SendPktLenErrMask[1];
+ pseudo_bit_t SendDroppedSmpPktErrMask[1];
+ pseudo_bit_t SendDroppedDataPktErrMask[1];
+ pseudo_bit_t SendPioArmLaunchErrMask[1];
+ pseudo_bit_t SendUnexpectedPktNumErrMask[1];
+ pseudo_bit_t SendUnsupportedVLErrMask[1];
+ pseudo_bit_t SendBufMisuseErrMask[1];
+ pseudo_bit_t SDmaGenMismatchErrMask[1];
+ pseudo_bit_t SDmaOutOfBoundErrMask[1];
+ pseudo_bit_t SDmaTailOutOfBoundErrMask[1];
+ pseudo_bit_t SDmaBaseErrMask[1];
+ pseudo_bit_t SDma1stDescErrMask[1];
+ pseudo_bit_t SDmaRpyTagErrMask[1];
+ pseudo_bit_t SDmaDwEnErrMask[1];
+ pseudo_bit_t SDmaMissingDwErrMask[1];
+ pseudo_bit_t SDmaUnexpDataErrMask[1];
+ pseudo_bit_t IBStatusChangedMask[1];
+ pseudo_bit_t InvalidAddrErrMask[1];
+ pseudo_bit_t ResetNegatedMask[1];
+ pseudo_bit_t HardwareErrMask[1];
+ pseudo_bit_t SDmaDescAddrMisalignErrMask[1];
+ pseudo_bit_t InvalidEEPCmdMask[1];
+ pseudo_bit_t Reserved[10];
+};
+struct QIB_7220_ErrMask {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_ErrMask_pb );
+};
+
+#define QIB_7220_ErrStatus_offset 0x00000088UL
+struct QIB_7220_ErrStatus_pb {
+ pseudo_bit_t RcvFormatErr[1];
+ pseudo_bit_t RcvVCRCErr[1];
+ pseudo_bit_t RcvICRCErr[1];
+ pseudo_bit_t RcvMinPktLenErr[1];
+ pseudo_bit_t RcvMaxPktLenErr[1];
+ pseudo_bit_t RcvLongPktLenErr[1];
+ pseudo_bit_t RcvShortPktLenErr[1];
+ pseudo_bit_t RcvUnexpectedCharErr[1];
+ pseudo_bit_t RcvUnsupportedVLErr[1];
+ pseudo_bit_t RcvEBPErr[1];
+ pseudo_bit_t RcvIBFlowErr[1];
+ pseudo_bit_t RcvBadVersionErr[1];
+ pseudo_bit_t RcvEgrFullErr[1];
+ pseudo_bit_t RcvHdrFullErr[1];
+ pseudo_bit_t RcvBadTidErr[1];
+ pseudo_bit_t RcvHdrLenErr[1];
+ pseudo_bit_t RcvHdrErr[1];
+ pseudo_bit_t RcvIBLostLinkErr[1];
+ pseudo_bit_t Reserved1[9];
+ pseudo_bit_t SendSpecialTriggerErr[1];
+ pseudo_bit_t SDmaDisabledErr[1];
+ pseudo_bit_t SendMinPktLenErr[1];
+ pseudo_bit_t SendMaxPktLenErr[1];
+ pseudo_bit_t SendUnderRunErr[1];
+ pseudo_bit_t SendPktLenErr[1];
+ pseudo_bit_t SendDroppedSmpPktErr[1];
+ pseudo_bit_t SendDroppedDataPktErr[1];
+ pseudo_bit_t SendPioArmLaunchErr[1];
+ pseudo_bit_t SendUnexpectedPktNumErr[1];
+ pseudo_bit_t SendUnsupportedVLErr[1];
+ pseudo_bit_t SendBufMisuseErr[1];
+ pseudo_bit_t SDmaGenMismatchErr[1];
+ pseudo_bit_t SDmaOutOfBoundErr[1];
+ pseudo_bit_t SDmaTailOutOfBoundErr[1];
+ pseudo_bit_t SDmaBaseErr[1];
+ pseudo_bit_t SDma1stDescErr[1];
+ pseudo_bit_t SDmaRpyTagErr[1];
+ pseudo_bit_t SDmaDwEnErr[1];
+ pseudo_bit_t SDmaMissingDwErr[1];
+ pseudo_bit_t SDmaUnexpDataErr[1];
+ pseudo_bit_t IBStatusChanged[1];
+ pseudo_bit_t InvalidAddrErr[1];
+ pseudo_bit_t ResetNegated[1];
+ pseudo_bit_t HardwareErr[1];
+ pseudo_bit_t SDmaDescAddrMisalignErr[1];
+ pseudo_bit_t InvalidEEPCmdErr[1];
+ pseudo_bit_t Reserved[10];
+};
+struct QIB_7220_ErrStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_ErrStatus_pb );
+};
+
+#define QIB_7220_ErrClear_offset 0x00000090UL
+struct QIB_7220_ErrClear_pb {
+ pseudo_bit_t RcvFormatErrClear[1];
+ pseudo_bit_t RcvVCRCErrClear[1];
+ pseudo_bit_t RcvICRCErrClear[1];
+ pseudo_bit_t RcvMinPktLenErrClear[1];
+ pseudo_bit_t RcvMaxPktLenErrClear[1];
+ pseudo_bit_t RcvLongPktLenErrClear[1];
+ pseudo_bit_t RcvShortPktLenErrClear[1];
+ pseudo_bit_t RcvUnexpectedCharErrClear[1];
+ pseudo_bit_t RcvUnsupportedVLErrClear[1];
+ pseudo_bit_t RcvEBPErrClear[1];
+ pseudo_bit_t RcvIBFlowErrClear[1];
+ pseudo_bit_t RcvBadVersionErrClear[1];
+ pseudo_bit_t RcvEgrFullErrClear[1];
+ pseudo_bit_t RcvHdrFullErrClear[1];
+ pseudo_bit_t RcvBadTidErrClear[1];
+ pseudo_bit_t RcvHdrLenErrClear[1];
+ pseudo_bit_t RcvHdrErrClear[1];
+ pseudo_bit_t RcvIBLostLinkErrClear[1];
+ pseudo_bit_t Reserved1[9];
+ pseudo_bit_t SendSpecialTriggerErrClear[1];
+ pseudo_bit_t SDmaDisabledErrClear[1];
+ pseudo_bit_t SendMinPktLenErrClear[1];
+ pseudo_bit_t SendMaxPktLenErrClear[1];
+ pseudo_bit_t SendUnderRunErrClear[1];
+ pseudo_bit_t SendPktLenErrClear[1];
+ pseudo_bit_t SendDroppedSmpPktErrClear[1];
+ pseudo_bit_t SendDroppedDataPktErrClear[1];
+ pseudo_bit_t SendPioArmLaunchErrClear[1];
+ pseudo_bit_t SendUnexpectedPktNumErrClear[1];
+ pseudo_bit_t SendUnsupportedVLErrClear[1];
+ pseudo_bit_t SendBufMisuseErrClear[1];
+ pseudo_bit_t SDmaGenMismatchErrClear[1];
+ pseudo_bit_t SDmaOutOfBoundErrClear[1];
+ pseudo_bit_t SDmaTailOutOfBoundErrClear[1];
+ pseudo_bit_t SDmaBaseErrClear[1];
+ pseudo_bit_t SDma1stDescErrClear[1];
+ pseudo_bit_t SDmaRpyTagErrClear[1];
+ pseudo_bit_t SDmaDwEnErrClear[1];
+ pseudo_bit_t SDmaMissingDwErrClear[1];
+ pseudo_bit_t SDmaUnexpDataErrClear[1];
+ pseudo_bit_t IBStatusChangedClear[1];
+ pseudo_bit_t InvalidAddrErrClear[1];
+ pseudo_bit_t ResetNegatedClear[1];
+ pseudo_bit_t HardwareErrClear[1];
+ pseudo_bit_t SDmaDescAddrMisalignErrClear[1];
+ pseudo_bit_t InvalidEEPCmdErrClear[1];
+ pseudo_bit_t Reserved[10];
+};
+struct QIB_7220_ErrClear {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_ErrClear_pb );
+};
+
+#define QIB_7220_HwErrMask_offset 0x00000098UL
+struct QIB_7220_HwErrMask_pb {
+ pseudo_bit_t PCIeMemParityErrMask[8];
+ pseudo_bit_t Reserved3[20];
+ pseudo_bit_t SDmaMemReadErrMask[1];
+ pseudo_bit_t PoisonedTLPMask[1];
+ pseudo_bit_t PcieCplTimeoutMask[1];
+ pseudo_bit_t PCIeBusParityErrMask[3];
+ pseudo_bit_t Reserved2[2];
+ pseudo_bit_t PCIEOct0_uC_MemoryParityErrMask[1];
+ pseudo_bit_t PCIEOct1_uC_MemoryParityErrMask[1];
+ pseudo_bit_t IB_uC_MemoryParityErrMask[1];
+ pseudo_bit_t DDSRXEQMemoryParityErrMask[1];
+ pseudo_bit_t TXEMemParityErrMask[4];
+ pseudo_bit_t RXEMemParityErrMask[7];
+ pseudo_bit_t Reserved1[3];
+ pseudo_bit_t PowerOnBISTFailedMask[1];
+ pseudo_bit_t Reserved[1];
+ pseudo_bit_t PCIESerdesQ0PClkNotDetectMask[1];
+ pseudo_bit_t PCIESerdesQ1PClkNotDetectMask[1];
+ pseudo_bit_t PCIESerdesQ2PClkNotDetectMask[1];
+ pseudo_bit_t PCIESerdesQ3PClkNotDetectMask[1];
+ pseudo_bit_t IBSerdesPClkNotDetectMask[1];
+ pseudo_bit_t Clk_uC_PLLNotLockedMask[1];
+ pseudo_bit_t IBCBusToSPCParityErrMask[1];
+ pseudo_bit_t IBCBusFromSPCParityErrMask[1];
+};
+struct QIB_7220_HwErrMask {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_HwErrMask_pb );
+};
+
+#define QIB_7220_HwErrStatus_offset 0x000000a0UL
+struct QIB_7220_HwErrStatus_pb {
+ pseudo_bit_t PCIeMemParity[8];
+ pseudo_bit_t Reserved3[20];
+ pseudo_bit_t SDmaMemReadErr[1];
+ pseudo_bit_t PoisenedTLP[1];
+ pseudo_bit_t PcieCplTimeout[1];
+ pseudo_bit_t PCIeBusParity[3];
+ pseudo_bit_t Reserved2[2];
+ pseudo_bit_t PCIE_uC_Oct0MemoryParityErr[1];
+ pseudo_bit_t PCIE_uC_Oct1MemoryParityErr[1];
+ pseudo_bit_t IB_uC_MemoryParityErr[1];
+ pseudo_bit_t DDSRXEQMemoryParityErr[1];
+ pseudo_bit_t TXEMemParity[4];
+ pseudo_bit_t RXEMemParity[7];
+ pseudo_bit_t Reserved1[3];
+ pseudo_bit_t PowerOnBISTFailed[1];
+ pseudo_bit_t Reserved[1];
+ pseudo_bit_t PCIESerdesQ0PClkNotDetect[1];
+ pseudo_bit_t PCIESerdesQ1PClkNotDetect[1];
+ pseudo_bit_t PCIESerdesQ2PClkNotDetect[1];
+ pseudo_bit_t PCIESerdesQ3PClkNotDetect[1];
+ pseudo_bit_t IBSerdesPClkNotDetect[1];
+ pseudo_bit_t Clk_uC_PLLNotLocked[1];
+ pseudo_bit_t IBCBusToSPCParityErr[1];
+ pseudo_bit_t IBCBusFromSPCParityErr[1];
+};
+struct QIB_7220_HwErrStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_HwErrStatus_pb );
+};
+
+#define QIB_7220_HwErrClear_offset 0x000000a8UL
+struct QIB_7220_HwErrClear_pb {
+ pseudo_bit_t PCIeMemParityClr[8];
+ pseudo_bit_t Reserved3[20];
+ pseudo_bit_t SDmaMemReadErrClear[1];
+ pseudo_bit_t PoisonedTLPClear[1];
+ pseudo_bit_t PcieCplTimeoutClear[1];
+ pseudo_bit_t PCIeBusParityClr[3];
+ pseudo_bit_t Reserved2[2];
+ pseudo_bit_t PCIE_uC_Oct0MemoryParityErrClear[1];
+ pseudo_bit_t PCIE_uC_Oct1MemoryParityErrClear[1];
+ pseudo_bit_t IB_uC_MemoryParityErrClear[1];
+ pseudo_bit_t DDSRXEQMemoryParityErrClear[1];
+ pseudo_bit_t TXEMemParityClear[4];
+ pseudo_bit_t RXEMemParityClear[7];
+ pseudo_bit_t Reserved1[3];
+ pseudo_bit_t PowerOnBISTFailedClear[1];
+ pseudo_bit_t Reserved[1];
+ pseudo_bit_t PCIESerdesQ0PClkNotDetectClear[1];
+ pseudo_bit_t PCIESerdesQ1PClkNotDetectClear[1];
+ pseudo_bit_t PCIESerdesQ2PClkNotDetectClear[1];
+ pseudo_bit_t PCIESerdesQ3PClkNotDetectClear[1];
+ pseudo_bit_t IBSerdesPClkNotDetectClear[1];
+ pseudo_bit_t Clk_uC_PLLNotLockedClear[1];
+ pseudo_bit_t IBCBusToSPCparityErrClear[1];
+ pseudo_bit_t IBCBusFromSPCParityErrClear[1];
+};
+struct QIB_7220_HwErrClear {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_HwErrClear_pb );
+};
+
+#define QIB_7220_HwDiagCtrl_offset 0x000000b0UL
+struct QIB_7220_HwDiagCtrl_pb {
+ pseudo_bit_t forcePCIeMemParity[8];
+ pseudo_bit_t Reserved2[23];
+ pseudo_bit_t forcePCIeBusParity[4];
+ pseudo_bit_t Reserved1[1];
+ pseudo_bit_t ForcePCIE_uC_Oct0MemoryParityErr[1];
+ pseudo_bit_t ForcePCIE_uC_Oct1MemoryParityErr[1];
+ pseudo_bit_t ForceIB_uC_MemoryParityErr[1];
+ pseudo_bit_t ForceDDSRXEQMemoryParityErr[1];
+ pseudo_bit_t ForceTxMemparityErr[4];
+ pseudo_bit_t ForceRxMemParityErr[7];
+ pseudo_bit_t Reserved[9];
+ pseudo_bit_t CounterDisable[1];
+ pseudo_bit_t CounterWrEnable[1];
+ pseudo_bit_t ForceIBCBusToSPCParityErr[1];
+ pseudo_bit_t ForceIBCBusFromSPCParityErr[1];
+};
+struct QIB_7220_HwDiagCtrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_HwDiagCtrl_pb );
+};
+
+#define QIB_7220_REG_0000B8_offset 0x000000b8UL
+
+#define QIB_7220_IBCStatus_offset 0x000000c0UL
+struct QIB_7220_IBCStatus_pb {
+ pseudo_bit_t LinkTrainingState[5];
+ pseudo_bit_t LinkState[3];
+ pseudo_bit_t LinkSpeedActive[1];
+ pseudo_bit_t LinkWidthActive[1];
+ pseudo_bit_t DDS_RXEQ_FAIL[1];
+ pseudo_bit_t IB_SERDES_TRIM_DONE[1];
+ pseudo_bit_t IBRxLaneReversed[1];
+ pseudo_bit_t IBTxLaneReversed[1];
+ pseudo_bit_t Reserved[16];
+ pseudo_bit_t TxReady[1];
+ pseudo_bit_t TxCreditOk[1];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7220_IBCStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_IBCStatus_pb );
+};
+
+#define QIB_7220_IBCCtrl_offset 0x000000c8UL
+struct QIB_7220_IBCCtrl_pb {
+ pseudo_bit_t FlowCtrlPeriod[8];
+ pseudo_bit_t FlowCtrlWaterMark[8];
+ pseudo_bit_t LinkInitCmd[3];
+ pseudo_bit_t LinkCmd[2];
+ pseudo_bit_t MaxPktLen[11];
+ pseudo_bit_t PhyerrThreshold[4];
+ pseudo_bit_t OverrunThreshold[4];
+ pseudo_bit_t CreditScale[3];
+ pseudo_bit_t Reserved[19];
+ pseudo_bit_t LinkDownDefaultState[1];
+ pseudo_bit_t Loopback[1];
+};
+struct QIB_7220_IBCCtrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_IBCCtrl_pb );
+};
+
+#define QIB_7220_EXTStatus_offset 0x000000d0UL
+struct QIB_7220_EXTStatus_pb {
+ pseudo_bit_t Reserved2[14];
+ pseudo_bit_t MemBISTEndTest[1];
+ pseudo_bit_t MemBISTDisabled[1];
+ pseudo_bit_t Reserved1[16];
+ pseudo_bit_t Reserved[16];
+ pseudo_bit_t GPIOIn[16];
+};
+struct QIB_7220_EXTStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_EXTStatus_pb );
+};
+
+#define QIB_7220_EXTCtrl_offset 0x000000d8UL
+struct QIB_7220_EXTCtrl_pb {
+ pseudo_bit_t LEDGblErrRedOff[1];
+ pseudo_bit_t LEDGblOkGreenOn[1];
+ pseudo_bit_t LEDPriPortYellowOn[1];
+ pseudo_bit_t LEDPriPortGreenOn[1];
+ pseudo_bit_t Reserved[28];
+ pseudo_bit_t GPIOInvert[16];
+ pseudo_bit_t GPIOOe[16];
+};
+struct QIB_7220_EXTCtrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_EXTCtrl_pb );
+};
+
+#define QIB_7220_GPIOOut_offset 0x000000e0UL
+
+#define QIB_7220_GPIOMask_offset 0x000000e8UL
+
+#define QIB_7220_GPIOStatus_offset 0x000000f0UL
+
+#define QIB_7220_GPIOClear_offset 0x000000f8UL
+
+#define QIB_7220_RcvCtrl_offset 0x00000100UL
+struct QIB_7220_RcvCtrl_pb {
+ pseudo_bit_t PortEnable[17];
+ pseudo_bit_t IntrAvail[17];
+ pseudo_bit_t RcvPartitionKeyDisable[1];
+ pseudo_bit_t TailUpd[1];
+ pseudo_bit_t PortCfg[2];
+ pseudo_bit_t RcvQPMapEnable[1];
+ pseudo_bit_t Reserved[25];
+};
+struct QIB_7220_RcvCtrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvCtrl_pb );
+};
+
+#define QIB_7220_RcvBTHQP_offset 0x00000108UL
+struct QIB_7220_RcvBTHQP_pb {
+ pseudo_bit_t RcvBTHQP[24];
+ pseudo_bit_t Reserved[8];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7220_RcvBTHQP {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvBTHQP_pb );
+};
+
+#define QIB_7220_RcvHdrSize_offset 0x00000110UL
+
+#define QIB_7220_RcvHdrCnt_offset 0x00000118UL
+
+#define QIB_7220_RcvHdrEntSize_offset 0x00000120UL
+
+#define QIB_7220_RcvTIDBase_offset 0x00000128UL
+
+#define QIB_7220_RcvTIDCnt_offset 0x00000130UL
+
+#define QIB_7220_RcvEgrBase_offset 0x00000138UL
+
+#define QIB_7220_RcvEgrCnt_offset 0x00000140UL
+
+#define QIB_7220_RcvBufBase_offset 0x00000148UL
+
+#define QIB_7220_RcvBufSize_offset 0x00000150UL
+
+#define QIB_7220_RxIntMemBase_offset 0x00000158UL
+
+#define QIB_7220_RxIntMemSize_offset 0x00000160UL
+
+#define QIB_7220_RcvPartitionKey_offset 0x00000168UL
+
+#define QIB_7220_RcvQPMulticastPort_offset 0x00000170UL
+struct QIB_7220_RcvQPMulticastPort_pb {
+ pseudo_bit_t RcvQpMcPort[5];
+ pseudo_bit_t Reserved[59];
+};
+struct QIB_7220_RcvQPMulticastPort {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvQPMulticastPort_pb );
+};
+
+#define QIB_7220_RcvPktLEDCnt_offset 0x00000178UL
+struct QIB_7220_RcvPktLEDCnt_pb {
+ pseudo_bit_t OFFperiod[32];
+ pseudo_bit_t ONperiod[32];
+};
+struct QIB_7220_RcvPktLEDCnt {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvPktLEDCnt_pb );
+};
+
+#define QIB_7220_IBCDDRCtrl_offset 0x00000180UL
+struct QIB_7220_IBCDDRCtrl_pb {
+ pseudo_bit_t IB_ENHANCED_MODE[1];
+ pseudo_bit_t SD_SPEED[1];
+ pseudo_bit_t SD_SPEED_SDR[1];
+ pseudo_bit_t SD_SPEED_DDR[1];
+ pseudo_bit_t SD_SPEED_QDR[1];
+ pseudo_bit_t IB_NUM_CHANNELS[2];
+ pseudo_bit_t IB_POLARITY_REV_SUPP[1];
+ pseudo_bit_t IB_LANE_REV_SUPPORTED[1];
+ pseudo_bit_t SD_RX_EQUAL_ENABLE[1];
+ pseudo_bit_t SD_ADD_ENB[1];
+ pseudo_bit_t SD_DDSV[1];
+ pseudo_bit_t SD_DDS[4];
+ pseudo_bit_t HRTBT_ENB[1];
+ pseudo_bit_t HRTBT_AUTO[1];
+ pseudo_bit_t HRTBT_PORT[8];
+ pseudo_bit_t HRTBT_REQ[1];
+ pseudo_bit_t Reserved[5];
+ pseudo_bit_t IB_DLID[16];
+ pseudo_bit_t IB_DLID_MASK[16];
+};
+struct QIB_7220_IBCDDRCtrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_IBCDDRCtrl_pb );
+};
+
+#define QIB_7220_HRTBT_GUID_offset 0x00000188UL
+
+#define QIB_7220_IB_SDTEST_IF_TX_offset 0x00000190UL
+struct QIB_7220_IB_SDTEST_IF_TX_pb {
+ pseudo_bit_t TS_T_TX_VALID[1];
+ pseudo_bit_t TS_3_TX_VALID[1];
+ pseudo_bit_t Reserved1[9];
+ pseudo_bit_t TS_TX_OPCODE[2];
+ pseudo_bit_t TS_TX_SPEED[3];
+ pseudo_bit_t Reserved[16];
+ pseudo_bit_t TS_TX_TX_CFG[16];
+ pseudo_bit_t TS_TX_RX_CFG[16];
+};
+struct QIB_7220_IB_SDTEST_IF_TX {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_IB_SDTEST_IF_TX_pb );
+};
+
+#define QIB_7220_IB_SDTEST_IF_RX_offset 0x00000198UL
+struct QIB_7220_IB_SDTEST_IF_RX_pb {
+ pseudo_bit_t TS_T_RX_VALID[1];
+ pseudo_bit_t TS_3_RX_VALID[1];
+ pseudo_bit_t Reserved[14];
+ pseudo_bit_t TS_RX_A[8];
+ pseudo_bit_t TS_RX_B[8];
+ pseudo_bit_t TS_RX_TX_CFG[16];
+ pseudo_bit_t TS_RX_RX_CFG[16];
+};
+struct QIB_7220_IB_SDTEST_IF_RX {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_IB_SDTEST_IF_RX_pb );
+};
+
+#define QIB_7220_IBCDDRCtrl2_offset 0x000001a0UL
+struct QIB_7220_IBCDDRCtrl2_pb {
+ pseudo_bit_t IB_FRONT_PORCH[5];
+ pseudo_bit_t IB_BACK_PORCH[5];
+ pseudo_bit_t _unused_0[54];
+};
+struct QIB_7220_IBCDDRCtrl2 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_IBCDDRCtrl2_pb );
+};
+
+#define QIB_7220_IBCDDRStatus_offset 0x000001a8UL
+struct QIB_7220_IBCDDRStatus_pb {
+ pseudo_bit_t LinkRoundTripLatency[26];
+ pseudo_bit_t ReqDDSLocalFromRmt[4];
+ pseudo_bit_t RxEqLocalDevice[2];
+ pseudo_bit_t heartbeat_crosstalk[4];
+ pseudo_bit_t heartbeat_timed_out[1];
+ pseudo_bit_t _unused_0[27];
+};
+struct QIB_7220_IBCDDRStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_IBCDDRStatus_pb );
+};
+
+#define QIB_7220_JIntReload_offset 0x000001b0UL
+struct QIB_7220_JIntReload_pb {
+ pseudo_bit_t J_reload[16];
+ pseudo_bit_t J_limit_reload[16];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7220_JIntReload {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_JIntReload_pb );
+};
+
+#define QIB_7220_IBNCModeCtrl_offset 0x000001b8UL
+struct QIB_7220_IBNCModeCtrl_pb {
+ pseudo_bit_t TSMEnable_send_TS1[1];
+ pseudo_bit_t TSMEnable_send_TS2[1];
+ pseudo_bit_t TSMEnable_ignore_TSM_on_rx[1];
+ pseudo_bit_t Reserved1[5];
+ pseudo_bit_t TSMCode_TS1[9];
+ pseudo_bit_t TSMCode_TS2[9];
+ pseudo_bit_t Reserved[38];
+};
+struct QIB_7220_IBNCModeCtrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_IBNCModeCtrl_pb );
+};
+
+#define QIB_7220_SendCtrl_offset 0x000001c0UL
+struct QIB_7220_SendCtrl_pb {
+ pseudo_bit_t Abort[1];
+ pseudo_bit_t SendIntBufAvail[1];
+ pseudo_bit_t SendBufAvailUpd[1];
+ pseudo_bit_t SPioEnable[1];
+ pseudo_bit_t SSpecialTriggerEn[1];
+ pseudo_bit_t Reserved2[4];
+ pseudo_bit_t SDmaIntEnable[1];
+ pseudo_bit_t SDmaSingleDescriptor[1];
+ pseudo_bit_t SDmaEnable[1];
+ pseudo_bit_t SDmaHalt[1];
+ pseudo_bit_t Reserved1[3];
+ pseudo_bit_t DisarmPIOBuf[8];
+ pseudo_bit_t AvailUpdThld[5];
+ pseudo_bit_t Reserved[2];
+ pseudo_bit_t Disarm[1];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7220_SendCtrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendCtrl_pb );
+};
+
+#define QIB_7220_SendBufBase_offset 0x000001c8UL
+struct QIB_7220_SendBufBase_pb {
+ pseudo_bit_t BaseAddr_SmallPIO[21];
+ pseudo_bit_t Reserved1[11];
+ pseudo_bit_t BaseAddr_LargePIO[21];
+ pseudo_bit_t Reserved[11];
+};
+struct QIB_7220_SendBufBase {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufBase_pb );
+};
+
+#define QIB_7220_SendBufSize_offset 0x000001d0UL
+struct QIB_7220_SendBufSize_pb {
+ pseudo_bit_t Size_SmallPIO[12];
+ pseudo_bit_t Reserved1[20];
+ pseudo_bit_t Size_LargePIO[13];
+ pseudo_bit_t Reserved[19];
+};
+struct QIB_7220_SendBufSize {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufSize_pb );
+};
+
+#define QIB_7220_SendBufCnt_offset 0x000001d8UL
+struct QIB_7220_SendBufCnt_pb {
+ pseudo_bit_t Num_SmallBuffers[9];
+ pseudo_bit_t Reserved1[23];
+ pseudo_bit_t Num_LargeBuffers[4];
+ pseudo_bit_t Reserved[28];
+};
+struct QIB_7220_SendBufCnt {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufCnt_pb );
+};
+
+#define QIB_7220_SendBufAvailAddr_offset 0x000001e0UL
+struct QIB_7220_SendBufAvailAddr_pb {
+ pseudo_bit_t Reserved[6];
+ pseudo_bit_t SendBufAvailAddr[34];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7220_SendBufAvailAddr {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufAvailAddr_pb );
+};
+
+#define QIB_7220_TxIntMemBase_offset 0x000001e8UL
+
+#define QIB_7220_TxIntMemSize_offset 0x000001f0UL
+
+#define QIB_7220_SendDmaBase_offset 0x000001f8UL
+struct QIB_7220_SendDmaBase_pb {
+ pseudo_bit_t SendDmaBase[48];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_SendDmaBase {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaBase_pb );
+};
+
+#define QIB_7220_SendDmaLenGen_offset 0x00000200UL
+struct QIB_7220_SendDmaLenGen_pb {
+ pseudo_bit_t Length[16];
+ pseudo_bit_t Generation[3];
+ pseudo_bit_t Reserved[45];
+};
+struct QIB_7220_SendDmaLenGen {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaLenGen_pb );
+};
+
+#define QIB_7220_SendDmaTail_offset 0x00000208UL
+struct QIB_7220_SendDmaTail_pb {
+ pseudo_bit_t SendDmaTail[16];
+ pseudo_bit_t Reserved[48];
+};
+struct QIB_7220_SendDmaTail {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaTail_pb );
+};
+
+#define QIB_7220_SendDmaHead_offset 0x00000210UL
+struct QIB_7220_SendDmaHead_pb {
+ pseudo_bit_t SendDmaHead[16];
+ pseudo_bit_t Reserved1[16];
+ pseudo_bit_t InternalSendDmaHead[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_SendDmaHead {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaHead_pb );
+};
+
+#define QIB_7220_SendDmaHeadAddr_offset 0x00000218UL
+struct QIB_7220_SendDmaHeadAddr_pb {
+ pseudo_bit_t SendDmaHeadAddr[48];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_SendDmaHeadAddr {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaHeadAddr_pb );
+};
+
+#define QIB_7220_SendDmaBufMask0_offset 0x00000220UL
+struct QIB_7220_SendDmaBufMask0_pb {
+ pseudo_bit_t BufMask_63_0[0];
+ pseudo_bit_t _unused_0[64];
+};
+struct QIB_7220_SendDmaBufMask0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaBufMask0_pb );
+};
+
+#define QIB_7220_SendDmaStatus_offset 0x00000238UL
+struct QIB_7220_SendDmaStatus_pb {
+ pseudo_bit_t SplFifoDescIndex[16];
+ pseudo_bit_t SplFifoBufNum[8];
+ pseudo_bit_t SplFifoFull[1];
+ pseudo_bit_t SplFifoEmpty[1];
+ pseudo_bit_t SplFifoDisarmed[1];
+ pseudo_bit_t SplFifoReadyToGo[1];
+ pseudo_bit_t ScbFetchDescFlag[1];
+ pseudo_bit_t ScbEntryValid[1];
+ pseudo_bit_t ScbEmpty[1];
+ pseudo_bit_t ScbFull[1];
+ pseudo_bit_t RpyTag_7_0[8];
+ pseudo_bit_t RpyLowAddr_6_0[7];
+ pseudo_bit_t ScbDescIndex_13_0[14];
+ pseudo_bit_t InternalSDmaEnable[1];
+ pseudo_bit_t AbortInProg[1];
+ pseudo_bit_t ScoreBoardDrainInProg[1];
+};
+struct QIB_7220_SendDmaStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaStatus_pb );
+};
+
+#define QIB_7220_SendBufErr0_offset 0x00000240UL
+struct QIB_7220_SendBufErr0_pb {
+ pseudo_bit_t SendBufErr_63_0[0];
+ pseudo_bit_t _unused_0[64];
+};
+struct QIB_7220_SendBufErr0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufErr0_pb );
+};
+
+#define QIB_7220_REG_000258_offset 0x00000258UL
+
+#define QIB_7220_AvailUpdCount_offset 0x00000268UL
+struct QIB_7220_AvailUpdCount_pb {
+ pseudo_bit_t AvailUpdCount[5];
+ pseudo_bit_t _unused_0[59];
+};
+struct QIB_7220_AvailUpdCount {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_AvailUpdCount_pb );
+};
+
+#define QIB_7220_RcvHdrAddr0_offset 0x00000270UL
+struct QIB_7220_RcvHdrAddr0_pb {
+ pseudo_bit_t Reserved[2];
+ pseudo_bit_t RcvHdrAddr0[38];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7220_RcvHdrAddr0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrAddr0_pb );
+};
+
+#define QIB_7220_REG_0002F8_offset 0x000002f8UL
+
+#define QIB_7220_RcvHdrTailAddr0_offset 0x00000300UL
+struct QIB_7220_RcvHdrTailAddr0_pb {
+ pseudo_bit_t Reserved[2];
+ pseudo_bit_t RcvHdrTailAddr0[38];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7220_RcvHdrTailAddr0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrTailAddr0_pb );
+};
+
+#define QIB_7220_REG_000388_offset 0x00000388UL
+
+#define QIB_7220_ibsd_epb_access_ctrl_offset 0x000003c0UL
+struct QIB_7220_ibsd_epb_access_ctrl_pb {
+ pseudo_bit_t sw_ib_epb_req[1];
+ pseudo_bit_t Reserved[7];
+ pseudo_bit_t sw_ib_epb_req_granted[1];
+ pseudo_bit_t _unused_0[55];
+};
+struct QIB_7220_ibsd_epb_access_ctrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_ibsd_epb_access_ctrl_pb );
+};
+
+#define QIB_7220_ibsd_epb_transaction_reg_offset 0x000003c8UL
+struct QIB_7220_ibsd_epb_transaction_reg_pb {
+ pseudo_bit_t ib_epb_data[8];
+ pseudo_bit_t ib_epb_address[15];
+ pseudo_bit_t Reserved2[1];
+ pseudo_bit_t ib_epb_read_write[1];
+ pseudo_bit_t ib_epb_cs[2];
+ pseudo_bit_t Reserved1[1];
+ pseudo_bit_t mem_data_parity[1];
+ pseudo_bit_t Reserved[1];
+ pseudo_bit_t ib_epb_req_error[1];
+ pseudo_bit_t ib_epb_rdy[1];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7220_ibsd_epb_transaction_reg {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_ibsd_epb_transaction_reg_pb );
+};
+
+#define QIB_7220_REG_0003D0_offset 0x000003d0UL
+
+#define QIB_7220_XGXSCfg_offset 0x000003d8UL
+struct QIB_7220_XGXSCfg_pb {
+ pseudo_bit_t tx_rx_reset[1];
+ pseudo_bit_t Reserved2[1];
+ pseudo_bit_t xcv_reset[1];
+ pseudo_bit_t Reserved1[6];
+ pseudo_bit_t link_sync_mask[10];
+ pseudo_bit_t Reserved[44];
+ pseudo_bit_t sel_link_down_for_fctrl_lane_sync_reset[1];
+};
+struct QIB_7220_XGXSCfg {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_XGXSCfg_pb );
+};
+
+#define QIB_7220_IBSerDesCtrl_offset 0x000003e0UL
+struct QIB_7220_IBSerDesCtrl_pb {
+ pseudo_bit_t ResetIB_uC_Core[1];
+ pseudo_bit_t Reserved2[7];
+ pseudo_bit_t NumSerDesRegsToWrForDDS[5];
+ pseudo_bit_t NumSerDesRegsToWrForRXEQ[5];
+ pseudo_bit_t Reserved1[14];
+ pseudo_bit_t TXINV[1];
+ pseudo_bit_t RXINV[1];
+ pseudo_bit_t RXIDLE[1];
+ pseudo_bit_t TWC[1];
+ pseudo_bit_t TXOBPD[1];
+ pseudo_bit_t PLLM[3];
+ pseudo_bit_t PLLN[2];
+ pseudo_bit_t CKSEL_uC[2];
+ pseudo_bit_t INT_uC[1];
+ pseudo_bit_t Reserved[19];
+};
+struct QIB_7220_IBSerDesCtrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_IBSerDesCtrl_pb );
+};
+
+#define QIB_7220_EEPCtlStat_offset 0x000003e8UL
+struct QIB_7220_EEPCtlStat_pb {
+ pseudo_bit_t EPAccEn[2];
+ pseudo_bit_t EPReset[1];
+ pseudo_bit_t ByteProg[1];
+ pseudo_bit_t PageMode[1];
+ pseudo_bit_t LstDatWr[1];
+ pseudo_bit_t CmdWrErr[1];
+ pseudo_bit_t Reserved[24];
+ pseudo_bit_t CtlrStat[1];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7220_EEPCtlStat {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_EEPCtlStat_pb );
+};
+
+#define QIB_7220_EEPAddrCmd_offset 0x000003f0UL
+struct QIB_7220_EEPAddrCmd_pb {
+ pseudo_bit_t EPAddr[24];
+ pseudo_bit_t EPCmd[8];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7220_EEPAddrCmd {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_EEPAddrCmd_pb );
+};
+
+#define QIB_7220_EEPData_offset 0x000003f8UL
+
+#define QIB_7220_pciesd_epb_access_ctrl_offset 0x00000400UL
+struct QIB_7220_pciesd_epb_access_ctrl_pb {
+ pseudo_bit_t sw_pcie_epb_req[1];
+ pseudo_bit_t sw_pcieepb_star_en[2];
+ pseudo_bit_t Reserved[5];
+ pseudo_bit_t sw_pcie_epb_req_granted[1];
+ pseudo_bit_t _unused_0[55];
+};
+struct QIB_7220_pciesd_epb_access_ctrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_pciesd_epb_access_ctrl_pb );
+};
+
+#define QIB_7220_pciesd_epb_transaction_reg_offset 0x00000408UL
+struct QIB_7220_pciesd_epb_transaction_reg_pb {
+ pseudo_bit_t pcie_epb_data[8];
+ pseudo_bit_t pcie_epb_address[15];
+ pseudo_bit_t Reserved1[1];
+ pseudo_bit_t pcie_epb_read_write[1];
+ pseudo_bit_t pcie_epb_cs[3];
+ pseudo_bit_t mem_data_parity[1];
+ pseudo_bit_t Reserved[1];
+ pseudo_bit_t pcie_epb_req_error[1];
+ pseudo_bit_t pcie_epb_rdy[1];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7220_pciesd_epb_transaction_reg {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_pciesd_epb_transaction_reg_pb );
+};
+
+#define QIB_7220_efuse_control_reg_offset 0x00000410UL
+struct QIB_7220_efuse_control_reg_pb {
+ pseudo_bit_t start_op[1];
+ pseudo_bit_t operation[1];
+ pseudo_bit_t read_valid[1];
+ pseudo_bit_t req_error[1];
+ pseudo_bit_t Reserved[27];
+ pseudo_bit_t rdy[1];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7220_efuse_control_reg {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_efuse_control_reg_pb );
+};
+
+#define QIB_7220_efuse_rddata0_reg_offset 0x00000418UL
+
+#define QIB_7220_procmon_register_offset 0x00000438UL
+struct QIB_7220_procmon_register_pb {
+ pseudo_bit_t interval_time[12];
+ pseudo_bit_t Reserved1[2];
+ pseudo_bit_t clear_counter[1];
+ pseudo_bit_t start_counter[1];
+ pseudo_bit_t procmon_count[9];
+ pseudo_bit_t Reserved[6];
+ pseudo_bit_t procmon_count_valid[1];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7220_procmon_register {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_procmon_register_pb );
+};
+
+#define QIB_7220_PcieRbufTestReg0_offset 0x00000440UL
+
+#define QIB_7220_PcieRBufTestReg1_offset 0x00000448UL
+
+#define QIB_7220_SPC_JTAG_ACCESS_REG_offset 0x00000460UL
+struct QIB_7220_SPC_JTAG_ACCESS_REG_pb {
+ pseudo_bit_t rdy[1];
+ pseudo_bit_t tdo[1];
+ pseudo_bit_t tdi[1];
+ pseudo_bit_t opcode[2];
+ pseudo_bit_t bist_en[5];
+ pseudo_bit_t SPC_JTAG_ACCESS_EN[1];
+ pseudo_bit_t _unused_0[53];
+};
+struct QIB_7220_SPC_JTAG_ACCESS_REG {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SPC_JTAG_ACCESS_REG_pb );
+};
+
+#define QIB_7220_LAControlReg_offset 0x00000468UL
+struct QIB_7220_LAControlReg_pb {
+ pseudo_bit_t Finished[1];
+ pseudo_bit_t Address[8];
+ pseudo_bit_t Mode[2];
+ pseudo_bit_t Delay[20];
+ pseudo_bit_t Reserved[1];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7220_LAControlReg {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_LAControlReg_pb );
+};
+
+#define QIB_7220_GPIODebugSelReg_offset 0x00000470UL
+struct QIB_7220_GPIODebugSelReg_pb {
+ pseudo_bit_t GPIOSourceSelDebug[16];
+ pseudo_bit_t SelPulse[16];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7220_GPIODebugSelReg {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_GPIODebugSelReg_pb );
+};
+
+#define QIB_7220_DebugPortValueReg_offset 0x00000478UL
+
+#define QIB_7220_SendDmaBufUsed0_offset 0x00000480UL
+struct QIB_7220_SendDmaBufUsed0_pb {
+ pseudo_bit_t BufUsed_63_0[0];
+ pseudo_bit_t _unused_0[64];
+};
+struct QIB_7220_SendDmaBufUsed0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaBufUsed0_pb );
+};
+
+#define QIB_7220_SendDmaReqTagUsed_offset 0x00000498UL
+struct QIB_7220_SendDmaReqTagUsed_pb {
+ pseudo_bit_t ReqTagUsed_7_0[8];
+ pseudo_bit_t _unused_0[8];
+ pseudo_bit_t Reserved[48];
+};
+struct QIB_7220_SendDmaReqTagUsed {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaReqTagUsed_pb );
+};
+
+#define QIB_7220_efuse_pgm_data0_offset 0x000004a0UL
+
+#define QIB_7220_MEM_0004B0_offset 0x000004b0UL
+
+#define QIB_7220_SerDes_DDSRXEQ0_offset 0x00000500UL
+struct QIB_7220_SerDes_DDSRXEQ0_pb {
+ pseudo_bit_t element_num[4];
+ pseudo_bit_t reg_addr[6];
+ pseudo_bit_t _unused_0[54];
+};
+struct QIB_7220_SerDes_DDSRXEQ0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SerDes_DDSRXEQ0_pb );
+};
+
+#define QIB_7220_MEM_0005F0_offset 0x000005f0UL
+
+#define QIB_7220_LAMemory_offset 0x00000600UL
+
+#define QIB_7220_MEM_0007F0_offset 0x000007f0UL
+
+#define QIB_7220_SendBufAvail0_offset 0x00001000UL
+struct QIB_7220_SendBufAvail0_pb {
+ pseudo_bit_t SendBuf_31_0[0];
+ pseudo_bit_t _unused_0[64];
+};
+struct QIB_7220_SendBufAvail0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufAvail0_pb );
+};
+
+#define QIB_7220_MEM_001028_offset 0x00001028UL
+
+#define QIB_7220_LBIntCnt_offset 0x00013000UL
+
+#define QIB_7220_LBFlowStallCnt_offset 0x00013008UL
+
+#define QIB_7220_TxSDmaDescCnt_offset 0x00013010UL
+
+#define QIB_7220_TxUnsupVLErrCnt_offset 0x00013018UL
+
+#define QIB_7220_TxDataPktCnt_offset 0x00013020UL
+
+#define QIB_7220_TxFlowPktCnt_offset 0x00013028UL
+
+#define QIB_7220_TxDwordCnt_offset 0x00013030UL
+
+#define QIB_7220_TxLenErrCnt_offset 0x00013038UL
+
+#define QIB_7220_TxMaxMinLenErrCnt_offset 0x00013040UL
+
+#define QIB_7220_TxUnderrunCnt_offset 0x00013048UL
+
+#define QIB_7220_TxFlowStallCnt_offset 0x00013050UL
+
+#define QIB_7220_TxDroppedPktCnt_offset 0x00013058UL
+
+#define QIB_7220_RxDroppedPktCnt_offset 0x00013060UL
+
+#define QIB_7220_RxDataPktCnt_offset 0x00013068UL
+
+#define QIB_7220_RxFlowPktCnt_offset 0x00013070UL
+
+#define QIB_7220_RxDwordCnt_offset 0x00013078UL
+
+#define QIB_7220_RxLenErrCnt_offset 0x00013080UL
+
+#define QIB_7220_RxMaxMinLenErrCnt_offset 0x00013088UL
+
+#define QIB_7220_RxICRCErrCnt_offset 0x00013090UL
+
+#define QIB_7220_RxVCRCErrCnt_offset 0x00013098UL
+
+#define QIB_7220_RxFlowCtrlViolCnt_offset 0x000130a0UL
+
+#define QIB_7220_RxVersionErrCnt_offset 0x000130a8UL
+
+#define QIB_7220_RxLinkMalformCnt_offset 0x000130b0UL
+
+#define QIB_7220_RxEBPCnt_offset 0x000130b8UL
+
+#define QIB_7220_RxLPCRCErrCnt_offset 0x000130c0UL
+
+#define QIB_7220_RxBufOvflCnt_offset 0x000130c8UL
+
+#define QIB_7220_RxTIDFullErrCnt_offset 0x000130d0UL
+
+#define QIB_7220_RxTIDValidErrCnt_offset 0x000130d8UL
+
+#define QIB_7220_RxPKeyMismatchCnt_offset 0x000130e0UL
+
+#define QIB_7220_RxP0HdrEgrOvflCnt_offset 0x000130e8UL
+
+#define QIB_7220_IBStatusChangeCnt_offset 0x00013170UL
+
+#define QIB_7220_IBLinkErrRecoveryCnt_offset 0x00013178UL
+
+#define QIB_7220_IBLinkDownedCnt_offset 0x00013180UL
+
+#define QIB_7220_IBSymbolErrCnt_offset 0x00013188UL
+
+#define QIB_7220_RxVL15DroppedPktCnt_offset 0x00013190UL
+
+#define QIB_7220_RxOtherLocalPhyErrCnt_offset 0x00013198UL
+
+#define QIB_7220_PcieRetryBufDiagQwordCnt_offset 0x000131a0UL
+
+#define QIB_7220_ExcessBufferOvflCnt_offset 0x000131a8UL
+
+#define QIB_7220_LocalLinkIntegrityErrCnt_offset 0x000131b0UL
+
+#define QIB_7220_RxVlErrCnt_offset 0x000131b8UL
+
+#define QIB_7220_RxDlidFltrCnt_offset 0x000131c0UL
+
+#define QIB_7220_CNT_0131C8_offset 0x000131c8UL
+
+#define QIB_7220_PSStat_offset 0x00013200UL
+
+#define QIB_7220_PSStart_offset 0x00013208UL
+
+#define QIB_7220_PSInterval_offset 0x00013210UL
+
+#define QIB_7220_PSRcvDataCount_offset 0x00013218UL
+
+#define QIB_7220_PSRcvPktsCount_offset 0x00013220UL
+
+#define QIB_7220_PSXmitDataCount_offset 0x00013228UL
+
+#define QIB_7220_PSXmitPktsCount_offset 0x00013230UL
+
+#define QIB_7220_PSXmitWaitCount_offset 0x00013238UL
+
+#define QIB_7220_CNT_013240_offset 0x00013240UL
+
+#define QIB_7220_RcvEgrArray_offset 0x00014000UL
+
+#define QIB_7220_MEM_038000_offset 0x00038000UL
+
+#define QIB_7220_RcvTIDArray0_offset 0x00053000UL
+
+#define QIB_7220_PIOLaunchFIFO_offset 0x00064000UL
+
+#define QIB_7220_MEM_064480_offset 0x00064480UL
+
+#define QIB_7220_SendPIOpbcCache_offset 0x00064800UL
+
+#define QIB_7220_MEM_064C80_offset 0x00064c80UL
+
+#define QIB_7220_PreLaunchFIFO_offset 0x00065000UL
+
+#define QIB_7220_MEM_065080_offset 0x00065080UL
+
+#define QIB_7220_ScoreBoard_offset 0x00065400UL
+
+#define QIB_7220_MEM_065440_offset 0x00065440UL
+
+#define QIB_7220_DescriptorFIFO_offset 0x00065800UL
+
+#define QIB_7220_MEM_065880_offset 0x00065880UL
+
+#define QIB_7220_RcvBuf1_offset 0x00072000UL
+
+#define QIB_7220_MEM_074800_offset 0x00074800UL
+
+#define QIB_7220_RcvBuf2_offset 0x00075000UL
+
+#define QIB_7220_MEM_076400_offset 0x00076400UL
+
+#define QIB_7220_RcvFlags_offset 0x00077000UL
+
+#define QIB_7220_MEM_078400_offset 0x00078400UL
+
+#define QIB_7220_RcvLookupBuf1_offset 0x00079000UL
+
+#define QIB_7220_MEM_07A400_offset 0x0007a400UL
+
+#define QIB_7220_RcvDMADatBuf_offset 0x0007b000UL
+
+#define QIB_7220_RcvDMAHdrBuf_offset 0x0007b800UL
+
+#define QIB_7220_MiscRXEIntMem_offset 0x0007c000UL
+
+#define QIB_7220_MEM_07D400_offset 0x0007d400UL
+
+#define QIB_7220_PCIERcvBuf_offset 0x00080000UL
+
+#define QIB_7220_PCIERetryBuf_offset 0x00084000UL
+
+#define QIB_7220_PCIERcvBufRdToWrAddr_offset 0x00088000UL
+
+#define QIB_7220_PCIECplBuf_offset 0x00090000UL
+
+#define QIB_7220_IBSerDesMappTable_offset 0x00094000UL
+
+#define QIB_7220_MEM_095000_offset 0x00095000UL
+
+#define QIB_7220_SendBuf0_MA_offset 0x00100000UL
+
+#define QIB_7220_MEM_1A0000_offset 0x001a0000UL
+
+#define QIB_7220_RcvHdrTail0_offset 0x00200000UL
+
+#define QIB_7220_RcvHdrHead0_offset 0x00200008UL
+struct QIB_7220_RcvHdrHead0_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead0_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail0_offset 0x00200010UL
+
+#define QIB_7220_RcvEgrIndexHead0_offset 0x00200018UL
+
+#define QIB_7220_MEM_200020_offset 0x00200020UL
+
+#define QIB_7220_RcvHdrTail1_offset 0x00210000UL
+
+#define QIB_7220_RcvHdrHead1_offset 0x00210008UL
+struct QIB_7220_RcvHdrHead1_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead1_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail1_offset 0x00210010UL
+
+#define QIB_7220_RcvEgrIndexHead1_offset 0x00210018UL
+
+#define QIB_7220_MEM_210020_offset 0x00210020UL
+
+#define QIB_7220_RcvHdrTail2_offset 0x00220000UL
+
+#define QIB_7220_RcvHdrHead2_offset 0x00220008UL
+struct QIB_7220_RcvHdrHead2_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead2 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead2_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail2_offset 0x00220010UL
+
+#define QIB_7220_RcvEgrIndexHead2_offset 0x00220018UL
+
+#define QIB_7220_MEM_220020_offset 0x00220020UL
+
+#define QIB_7220_RcvHdrTail3_offset 0x00230000UL
+
+#define QIB_7220_RcvHdrHead3_offset 0x00230008UL
+struct QIB_7220_RcvHdrHead3_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead3 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead3_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail3_offset 0x00230010UL
+
+#define QIB_7220_RcvEgrIndexHead3_offset 0x00230018UL
+
+#define QIB_7220_MEM_230020_offset 0x00230020UL
+
+#define QIB_7220_RcvHdrTail4_offset 0x00240000UL
+
+#define QIB_7220_RcvHdrHead4_offset 0x00240008UL
+struct QIB_7220_RcvHdrHead4_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead4 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead4_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail4_offset 0x00240010UL
+
+#define QIB_7220_RcvEgrIndexHead4_offset 0x00240018UL
+
+#define QIB_7220_MEM_240020_offset 0x00240020UL
+
+#define QIB_7220_RcvHdrTail5_offset 0x00250000UL
+
+#define QIB_7220_RcvHdrHead5_offset 0x00250008UL
+struct QIB_7220_RcvHdrHead5_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead5 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead5_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail5_offset 0x00250010UL
+
+#define QIB_7220_RcvEgrIndexHead5_offset 0x00250018UL
+
+#define QIB_7220_MEM_250020_offset 0x00250020UL
+
+#define QIB_7220_RcvHdrTail6_offset 0x00260000UL
+
+#define QIB_7220_RcvHdrHead6_offset 0x00260008UL
+struct QIB_7220_RcvHdrHead6_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead6 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead6_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail6_offset 0x00260010UL
+
+#define QIB_7220_RcvEgrIndexHead6_offset 0x00260018UL
+
+#define QIB_7220_MEM_260020_offset 0x00260020UL
+
+#define QIB_7220_RcvHdrTail7_offset 0x00270000UL
+
+#define QIB_7220_RcvHdrHead7_offset 0x00270008UL
+struct QIB_7220_RcvHdrHead7_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead7 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead7_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail7_offset 0x00270010UL
+
+#define QIB_7220_RcvEgrIndexHead7_offset 0x00270018UL
+
+#define QIB_7220_MEM_270020_offset 0x00270020UL
+
+#define QIB_7220_RcvHdrTail8_offset 0x00280000UL
+
+#define QIB_7220_RcvHdrHead8_offset 0x00280008UL
+struct QIB_7220_RcvHdrHead8_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead8 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead8_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail8_offset 0x00280010UL
+
+#define QIB_7220_RcvEgrIndexHead8_offset 0x00280018UL
+
+#define QIB_7220_MEM_280020_offset 0x00280020UL
+
+#define QIB_7220_RcvHdrTail9_offset 0x00290000UL
+
+#define QIB_7220_RcvHdrHead9_offset 0x00290008UL
+struct QIB_7220_RcvHdrHead9_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead9 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead9_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail9_offset 0x00290010UL
+
+#define QIB_7220_RcvEgrIndexHead9_offset 0x00290018UL
+
+#define QIB_7220_MEM_290020_offset 0x00290020UL
+
+#define QIB_7220_RcvHdrTail10_offset 0x002a0000UL
+
+#define QIB_7220_RcvHdrHead10_offset 0x002a0008UL
+struct QIB_7220_RcvHdrHead10_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead10 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead10_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail10_offset 0x002a0010UL
+
+#define QIB_7220_RcvEgrIndexHead10_offset 0x002a0018UL
+
+#define QIB_7220_MEM_2A0020_offset 0x002a0020UL
+
+#define QIB_7220_RcvHdrTail11_offset 0x002b0000UL
+
+#define QIB_7220_RcvHdrHead11_offset 0x002b0008UL
+struct QIB_7220_RcvHdrHead11_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead11 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead11_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail11_offset 0x002b0010UL
+
+#define QIB_7220_RcvEgrIndexHead11_offset 0x002b0018UL
+
+#define QIB_7220_MEM_2B0020_offset 0x002b0020UL
+
+#define QIB_7220_RcvHdrTail12_offset 0x002c0000UL
+
+#define QIB_7220_RcvHdrHead12_offset 0x002c0008UL
+struct QIB_7220_RcvHdrHead12_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead12 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead12_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail12_offset 0x002c0010UL
+
+#define QIB_7220_RcvEgrIndexHead12_offset 0x002c0018UL
+
+#define QIB_7220_MEM_2C0020_offset 0x002c0020UL
+
+#define QIB_7220_RcvHdrTail13_offset 0x002d0000UL
+
+#define QIB_7220_RcvHdrHead13_offset 0x002d0008UL
+struct QIB_7220_RcvHdrHead13_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead13 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead13_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail13_offset 0x002d0010UL
+
+#define QIB_7220_RcvEgrIndexHead13_offset 0x002d0018UL
+
+#define QIB_7220_MEM_2D0020_offset 0x002d0020UL
+
+#define QIB_7220_RcvHdrTail14_offset 0x002e0000UL
+
+#define QIB_7220_RcvHdrHead14_offset 0x002e0008UL
+struct QIB_7220_RcvHdrHead14_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead14 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead14_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail14_offset 0x002e0010UL
+
+#define QIB_7220_RcvEgrIndexHead14_offset 0x002e0018UL
+
+#define QIB_7220_MEM_2E0020_offset 0x002e0020UL
+
+#define QIB_7220_RcvHdrTail15_offset 0x002f0000UL
+
+#define QIB_7220_RcvHdrHead15_offset 0x002f0008UL
+struct QIB_7220_RcvHdrHead15_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead15 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead15_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail15_offset 0x002f0010UL
+
+#define QIB_7220_RcvEgrIndexHead15_offset 0x002f0018UL
+
+#define QIB_7220_MEM_2F0020_offset 0x002f0020UL
+
+#define QIB_7220_RcvHdrTail16_offset 0x00300000UL
+
+#define QIB_7220_RcvHdrHead16_offset 0x00300008UL
+struct QIB_7220_RcvHdrHead16_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t Reserved[16];
+};
+struct QIB_7220_RcvHdrHead16 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead16_pb );
+};
+
+#define QIB_7220_RcvEgrIndexTail16_offset 0x00300010UL
+
+#define QIB_7220_RcvEgrIndexHead16_offset 0x00300018UL
+
+#define QIB_7220_MEM_300020_offset 0x00300020UL
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib_7322_regs.h b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib_7322_regs.h
new file mode 100644
index 00000000..06c4676f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib_7322_regs.h
@@ -0,0 +1,7261 @@
+/*
+ * Copyright (c) 2008, 2009 QLogic Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+/* This file is mechanically generated from RTL. Any hand-edits will be lost! */
+
+/* This file has been further processed by ./drivers/infiniband/qib_genbits.pl */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#define QIB_7322_Revision_offset 0x00000000UL
+struct QIB_7322_Revision_pb {
+ pseudo_bit_t R_ChipRevMinor[8];
+ pseudo_bit_t R_ChipRevMajor[8];
+ pseudo_bit_t R_Arch[8];
+ pseudo_bit_t R_SW[8];
+ pseudo_bit_t BoardID[8];
+ pseudo_bit_t R_Emulation_Revcode[22];
+ pseudo_bit_t R_Emulation[1];
+ pseudo_bit_t R_Simulator[1];
+};
+struct QIB_7322_Revision {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_Revision_pb );
+};
+/* Default value: 0x0000000002010601 */
+
+#define QIB_7322_Control_offset 0x00000008UL
+struct QIB_7322_Control_pb {
+ pseudo_bit_t SyncReset[1];
+ pseudo_bit_t FreezeMode[1];
+ pseudo_bit_t _unused_0[1];
+ pseudo_bit_t PCIERetryBufDiagEn[1];
+ pseudo_bit_t SDmaDescFetchPriorityEn[1];
+ pseudo_bit_t PCIEPostQDiagEn[1];
+ pseudo_bit_t PCIECplQDiagEn[1];
+ pseudo_bit_t _unused_1[57];
+};
+struct QIB_7322_Control {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_Control_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PageAlign_offset 0x00000010UL
+/* Default value: 0x0000000000001000 */
+
+#define QIB_7322_ContextCnt_offset 0x00000018UL
+/* Default value: 0x0000000000000012 */
+
+#define QIB_7322_Scratch_offset 0x00000020UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_CntrRegBase_offset 0x00000028UL
+/* Default value: 0x0000000000011000 */
+
+#define QIB_7322_SendRegBase_offset 0x00000030UL
+/* Default value: 0x0000000000003000 */
+
+#define QIB_7322_UserRegBase_offset 0x00000038UL
+/* Default value: 0x0000000000200000 */
+
+#define QIB_7322_DebugPortSel_offset 0x00000040UL
+struct QIB_7322_DebugPortSel_pb {
+ pseudo_bit_t DebugOutMuxSel[2];
+ pseudo_bit_t _unused_0[28];
+ pseudo_bit_t SrcMuxSel0[8];
+ pseudo_bit_t SrcMuxSel1[8];
+ pseudo_bit_t DbgClkPortSel[5];
+ pseudo_bit_t EnDbgPort[1];
+ pseudo_bit_t EnEnhancedDebugMode[1];
+ pseudo_bit_t EnhMode_SrcMuxSelIndex[10];
+ pseudo_bit_t EnhMode_SrcMuxSelWrEn[1];
+};
+struct QIB_7322_DebugPortSel {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_DebugPortSel_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_DebugPortNibbleSel_offset 0x00000048UL
+struct QIB_7322_DebugPortNibbleSel_pb {
+ pseudo_bit_t NibbleSel0[4];
+ pseudo_bit_t NibbleSel1[4];
+ pseudo_bit_t NibbleSel2[4];
+ pseudo_bit_t NibbleSel3[4];
+ pseudo_bit_t NibbleSel4[4];
+ pseudo_bit_t NibbleSel5[4];
+ pseudo_bit_t NibbleSel6[4];
+ pseudo_bit_t NibbleSel7[4];
+ pseudo_bit_t NibbleSel8[4];
+ pseudo_bit_t NibbleSel9[4];
+ pseudo_bit_t NibbleSel10[4];
+ pseudo_bit_t NibbleSel11[4];
+ pseudo_bit_t NibbleSel12[4];
+ pseudo_bit_t NibbleSel13[4];
+ pseudo_bit_t NibbleSel14[4];
+ pseudo_bit_t NibbleSel15[4];
+};
+struct QIB_7322_DebugPortNibbleSel {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_DebugPortNibbleSel_pb );
+};
+/* Default value: 0xFEDCBA9876543210 */
+
+#define QIB_7322_DebugSigsIntSel_offset 0x00000050UL
+struct QIB_7322_DebugSigsIntSel_pb {
+ pseudo_bit_t debug_port_sel_pcs_pipe_lane07[3];
+ pseudo_bit_t debug_port_sel_pcs_pipe_lane815[3];
+ pseudo_bit_t debug_port_sel_pcs_sdout[1];
+ pseudo_bit_t debug_port_sel_pcs_symlock_elfifo_lane[4];
+ pseudo_bit_t debug_port_sel_pcs_rxdet_encdec_lane[3];
+ pseudo_bit_t EnableSDma_SelfDrain[1];
+ pseudo_bit_t debug_port_sel_pcie_rx_tx[1];
+ pseudo_bit_t _unused_0[1];
+ pseudo_bit_t debug_port_sel_tx_ibport[1];
+ pseudo_bit_t debug_port_sel_tx_sdma[1];
+ pseudo_bit_t debug_port_sel_rx_ibport[1];
+ pseudo_bit_t _unused_1[12];
+ pseudo_bit_t debug_port_sel_xgxs_0[4];
+ pseudo_bit_t debug_port_sel_credit_a_0[3];
+ pseudo_bit_t debug_port_sel_credit_b_0[3];
+ pseudo_bit_t debug_port_sel_xgxs_1[4];
+ pseudo_bit_t debug_port_sel_credit_a_1[3];
+ pseudo_bit_t debug_port_sel_credit_b_1[3];
+ pseudo_bit_t _unused_2[12];
+};
+struct QIB_7322_DebugSigsIntSel {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_DebugSigsIntSel_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_DebugPortValueReg_offset 0x00000058UL
+
+#define QIB_7322_IntBlocked_offset 0x00000060UL
+struct QIB_7322_IntBlocked_pb {
+ pseudo_bit_t RcvAvail0IntBlocked[1];
+ pseudo_bit_t RcvAvail1IntBlocked[1];
+ pseudo_bit_t RcvAvail2IntBlocked[1];
+ pseudo_bit_t RcvAvail3IntBlocked[1];
+ pseudo_bit_t RcvAvail4IntBlocked[1];
+ pseudo_bit_t RcvAvail5IntBlocked[1];
+ pseudo_bit_t RcvAvail6IntBlocked[1];
+ pseudo_bit_t RcvAvail7IntBlocked[1];
+ pseudo_bit_t RcvAvail8IntBlocked[1];
+ pseudo_bit_t RcvAvail9IntBlocked[1];
+ pseudo_bit_t RcvAvail10IntBlocked[1];
+ pseudo_bit_t RcvAvail11IntBlocked[1];
+ pseudo_bit_t RcvAvail12IntBlocked[1];
+ pseudo_bit_t RcvAvail13IntBlocked[1];
+ pseudo_bit_t RcvAvail14IntBlocked[1];
+ pseudo_bit_t RcvAvail15IntBlocked[1];
+ pseudo_bit_t RcvAvail16IntBlocked[1];
+ pseudo_bit_t RcvAvail17IntBlocked[1];
+ pseudo_bit_t _unused_0[5];
+ pseudo_bit_t SendBufAvailIntBlocked[1];
+ pseudo_bit_t SendDoneIntBlocked_0[1];
+ pseudo_bit_t SendDoneIntBlocked_1[1];
+ pseudo_bit_t _unused_1[2];
+ pseudo_bit_t AssertGPIOIntBlocked[1];
+ pseudo_bit_t ErrIntBlocked[1];
+ pseudo_bit_t ErrIntBlocked_0[1];
+ pseudo_bit_t ErrIntBlocked_1[1];
+ pseudo_bit_t RcvUrg0IntBlocked[1];
+ pseudo_bit_t RcvUrg1IntBlocked[1];
+ pseudo_bit_t RcvUrg2IntBlocked[1];
+ pseudo_bit_t RcvUrg3IntBlocked[1];
+ pseudo_bit_t RcvUrg4IntBlocked[1];
+ pseudo_bit_t RcvUrg5IntBlocked[1];
+ pseudo_bit_t RcvUrg6IntBlocked[1];
+ pseudo_bit_t RcvUrg7IntBlocked[1];
+ pseudo_bit_t RcvUrg8IntBlocked[1];
+ pseudo_bit_t RcvUrg9IntBlocked[1];
+ pseudo_bit_t RcvUrg10IntBlocked[1];
+ pseudo_bit_t RcvUrg11IntBlocked[1];
+ pseudo_bit_t RcvUrg12IntBlocked[1];
+ pseudo_bit_t RcvUrg13IntBlocked[1];
+ pseudo_bit_t RcvUrg14IntBlocked[1];
+ pseudo_bit_t RcvUrg15IntBlocked[1];
+ pseudo_bit_t RcvUrg16IntBlocked[1];
+ pseudo_bit_t RcvUrg17IntBlocked[1];
+ pseudo_bit_t _unused_2[6];
+ pseudo_bit_t SDmaCleanupDoneBlocked_0[1];
+ pseudo_bit_t SDmaCleanupDoneBlocked_1[1];
+ pseudo_bit_t SDmaIdleIntBlocked_0[1];
+ pseudo_bit_t SDmaIdleIntBlocked_1[1];
+ pseudo_bit_t SDmaProgressIntBlocked_0[1];
+ pseudo_bit_t SDmaProgressIntBlocked_1[1];
+ pseudo_bit_t SDmaIntBlocked_0[1];
+ pseudo_bit_t SDmaIntBlocked_1[1];
+};
+struct QIB_7322_IntBlocked {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IntBlocked_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IntMask_offset 0x00000068UL
+struct QIB_7322_IntMask_pb {
+ pseudo_bit_t RcvAvail0IntMask[1];
+ pseudo_bit_t RcvAvail1IntMask[1];
+ pseudo_bit_t RcvAvail2IntMask[1];
+ pseudo_bit_t RcvAvail3IntMask[1];
+ pseudo_bit_t RcvAvail4IntMask[1];
+ pseudo_bit_t RcvAvail5IntMask[1];
+ pseudo_bit_t RcvAvail6IntMask[1];
+ pseudo_bit_t RcvAvail7IntMask[1];
+ pseudo_bit_t RcvAvail8IntMask[1];
+ pseudo_bit_t RcvAvail9IntMask[1];
+ pseudo_bit_t RcvAvail10IntMask[1];
+ pseudo_bit_t RcvAvail11IntMask[1];
+ pseudo_bit_t RcvAvail12IntMask[1];
+ pseudo_bit_t RcvAvail13IntMask[1];
+ pseudo_bit_t RcvAvail14IntMask[1];
+ pseudo_bit_t RcvAvail15IntMask[1];
+ pseudo_bit_t RcvAvail16IntMask[1];
+ pseudo_bit_t RcvAvail17IntMask[1];
+ pseudo_bit_t _unused_0[5];
+ pseudo_bit_t SendBufAvailIntMask[1];
+ pseudo_bit_t SendDoneIntMask_0[1];
+ pseudo_bit_t SendDoneIntMask_1[1];
+ pseudo_bit_t _unused_1[2];
+ pseudo_bit_t AssertGPIOIntMask[1];
+ pseudo_bit_t ErrIntMask[1];
+ pseudo_bit_t ErrIntMask_0[1];
+ pseudo_bit_t ErrIntMask_1[1];
+ pseudo_bit_t RcvUrg0IntMask[1];
+ pseudo_bit_t RcvUrg1IntMask[1];
+ pseudo_bit_t RcvUrg2IntMask[1];
+ pseudo_bit_t RcvUrg3IntMask[1];
+ pseudo_bit_t RcvUrg4IntMask[1];
+ pseudo_bit_t RcvUrg5IntMask[1];
+ pseudo_bit_t RcvUrg6IntMask[1];
+ pseudo_bit_t RcvUrg7IntMask[1];
+ pseudo_bit_t RcvUrg8IntMask[1];
+ pseudo_bit_t RcvUrg9IntMask[1];
+ pseudo_bit_t RcvUrg10IntMask[1];
+ pseudo_bit_t RcvUrg11IntMask[1];
+ pseudo_bit_t RcvUrg12IntMask[1];
+ pseudo_bit_t RcvUrg13IntMask[1];
+ pseudo_bit_t RcvUrg14IntMask[1];
+ pseudo_bit_t RcvUrg15IntMask[1];
+ pseudo_bit_t RcvUrg16IntMask[1];
+ pseudo_bit_t RcvUrg17IntMask[1];
+ pseudo_bit_t _unused_2[6];
+ pseudo_bit_t SDmaCleanupDoneMask_0[1];
+ pseudo_bit_t SDmaCleanupDoneMask_1[1];
+ pseudo_bit_t SDmaIdleIntMask_0[1];
+ pseudo_bit_t SDmaIdleIntMask_1[1];
+ pseudo_bit_t SDmaProgressIntMask_0[1];
+ pseudo_bit_t SDmaProgressIntMask_1[1];
+ pseudo_bit_t SDmaIntMask_0[1];
+ pseudo_bit_t SDmaIntMask_1[1];
+};
+struct QIB_7322_IntMask {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IntMask_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IntStatus_offset 0x00000070UL
+struct QIB_7322_IntStatus_pb {
+ pseudo_bit_t RcvAvail0[1];
+ pseudo_bit_t RcvAvail1[1];
+ pseudo_bit_t RcvAvail2[1];
+ pseudo_bit_t RcvAvail3[1];
+ pseudo_bit_t RcvAvail4[1];
+ pseudo_bit_t RcvAvail5[1];
+ pseudo_bit_t RcvAvail6[1];
+ pseudo_bit_t RcvAvail7[1];
+ pseudo_bit_t RcvAvail8[1];
+ pseudo_bit_t RcvAvail9[1];
+ pseudo_bit_t RcvAvail10[1];
+ pseudo_bit_t RcvAvail11[1];
+ pseudo_bit_t RcvAvail12[1];
+ pseudo_bit_t RcvAvail13[1];
+ pseudo_bit_t RcvAvail14[1];
+ pseudo_bit_t RcvAvail15[1];
+ pseudo_bit_t RcvAvail16[1];
+ pseudo_bit_t RcvAvail17[1];
+ pseudo_bit_t _unused_0[5];
+ pseudo_bit_t SendBufAvail[1];
+ pseudo_bit_t SendDone_0[1];
+ pseudo_bit_t SendDone_1[1];
+ pseudo_bit_t _unused_1[2];
+ pseudo_bit_t AssertGPIO[1];
+ pseudo_bit_t Err[1];
+ pseudo_bit_t Err_0[1];
+ pseudo_bit_t Err_1[1];
+ pseudo_bit_t RcvUrg0[1];
+ pseudo_bit_t RcvUrg1[1];
+ pseudo_bit_t RcvUrg2[1];
+ pseudo_bit_t RcvUrg3[1];
+ pseudo_bit_t RcvUrg4[1];
+ pseudo_bit_t RcvUrg5[1];
+ pseudo_bit_t RcvUrg6[1];
+ pseudo_bit_t RcvUrg7[1];
+ pseudo_bit_t RcvUrg8[1];
+ pseudo_bit_t RcvUrg9[1];
+ pseudo_bit_t RcvUrg10[1];
+ pseudo_bit_t RcvUrg11[1];
+ pseudo_bit_t RcvUrg12[1];
+ pseudo_bit_t RcvUrg13[1];
+ pseudo_bit_t RcvUrg14[1];
+ pseudo_bit_t RcvUrg15[1];
+ pseudo_bit_t RcvUrg16[1];
+ pseudo_bit_t RcvUrg17[1];
+ pseudo_bit_t _unused_2[6];
+ pseudo_bit_t SDmaCleanupDone_0[1];
+ pseudo_bit_t SDmaCleanupDone_1[1];
+ pseudo_bit_t SDmaIdleInt_0[1];
+ pseudo_bit_t SDmaIdleInt_1[1];
+ pseudo_bit_t SDmaProgressInt_0[1];
+ pseudo_bit_t SDmaProgressInt_1[1];
+ pseudo_bit_t SDmaInt_0[1];
+ pseudo_bit_t SDmaInt_1[1];
+};
+struct QIB_7322_IntStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IntStatus_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IntClear_offset 0x00000078UL
+struct QIB_7322_IntClear_pb {
+ pseudo_bit_t RcvAvail0IntClear[1];
+ pseudo_bit_t RcvAvail1IntClear[1];
+ pseudo_bit_t RcvAvail2IntClear[1];
+ pseudo_bit_t RcvAvail3IntClear[1];
+ pseudo_bit_t RcvAvail4IntClear[1];
+ pseudo_bit_t RcvAvail5IntClear[1];
+ pseudo_bit_t RcvAvail6IntClear[1];
+ pseudo_bit_t RcvAvail7IntClear[1];
+ pseudo_bit_t RcvAvail8IntClear[1];
+ pseudo_bit_t RcvAvail9IntClear[1];
+ pseudo_bit_t RcvAvail10IntClear[1];
+ pseudo_bit_t RcvAvail11IntClear[1];
+ pseudo_bit_t RcvAvail12IntClear[1];
+ pseudo_bit_t RcvAvail13IntClear[1];
+ pseudo_bit_t RcvAvail14IntClear[1];
+ pseudo_bit_t RcvAvail15IntClear[1];
+ pseudo_bit_t RcvAvail16IntClear[1];
+ pseudo_bit_t RcvAvail17IntClear[1];
+ pseudo_bit_t _unused_0[5];
+ pseudo_bit_t SendBufAvailIntClear[1];
+ pseudo_bit_t SendDoneIntClear_0[1];
+ pseudo_bit_t SendDoneIntClear_1[1];
+ pseudo_bit_t _unused_1[2];
+ pseudo_bit_t AssertGPIOIntClear[1];
+ pseudo_bit_t ErrIntClear[1];
+ pseudo_bit_t ErrIntClear_0[1];
+ pseudo_bit_t ErrIntClear_1[1];
+ pseudo_bit_t RcvUrg0IntClear[1];
+ pseudo_bit_t RcvUrg1IntClear[1];
+ pseudo_bit_t RcvUrg2IntClear[1];
+ pseudo_bit_t RcvUrg3IntClear[1];
+ pseudo_bit_t RcvUrg4IntClear[1];
+ pseudo_bit_t RcvUrg5IntClear[1];
+ pseudo_bit_t RcvUrg6IntClear[1];
+ pseudo_bit_t RcvUrg7IntClear[1];
+ pseudo_bit_t RcvUrg8IntClear[1];
+ pseudo_bit_t RcvUrg9IntClear[1];
+ pseudo_bit_t RcvUrg10IntClear[1];
+ pseudo_bit_t RcvUrg11IntClear[1];
+ pseudo_bit_t RcvUrg12IntClear[1];
+ pseudo_bit_t RcvUrg13IntClear[1];
+ pseudo_bit_t RcvUrg14IntClear[1];
+ pseudo_bit_t RcvUrg15IntClear[1];
+ pseudo_bit_t RcvUrg16IntClear[1];
+ pseudo_bit_t RcvUrg17IntClear[1];
+ pseudo_bit_t _unused_2[6];
+ pseudo_bit_t SDmaCleanupDoneClear_0[1];
+ pseudo_bit_t SDmaCleanupDoneClear_1[1];
+ pseudo_bit_t SDmaIdleIntClear_0[1];
+ pseudo_bit_t SDmaIdleIntClear_1[1];
+ pseudo_bit_t SDmaProgressIntClear_0[1];
+ pseudo_bit_t SDmaProgressIntClear_1[1];
+ pseudo_bit_t SDmaIntClear_0[1];
+ pseudo_bit_t SDmaIntClear_1[1];
+};
+struct QIB_7322_IntClear {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IntClear_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ErrMask_offset 0x00000080UL
+struct QIB_7322_ErrMask_pb {
+ pseudo_bit_t _unused_0[12];
+ pseudo_bit_t RcvEgrFullErrMask[1];
+ pseudo_bit_t RcvHdrFullErrMask[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t SDmaBufMaskDuplicateErrMask[1];
+ pseudo_bit_t SDmaWrongPortErrMask[1];
+ pseudo_bit_t SendSpecialTriggerErrMask[1];
+ pseudo_bit_t _unused_2[7];
+ pseudo_bit_t SendArmLaunchErrMask[1];
+ pseudo_bit_t SendVLMismatchErrMask[1];
+ pseudo_bit_t _unused_3[15];
+ pseudo_bit_t RcvContextShareErrMask[1];
+ pseudo_bit_t InvalidEEPCmdMask[1];
+ pseudo_bit_t _unused_4[1];
+ pseudo_bit_t SBufVL15MisUseErrMask[1];
+ pseudo_bit_t SDmaVL15ErrMask[1];
+ pseudo_bit_t _unused_5[4];
+ pseudo_bit_t InvalidAddrErrMask[1];
+ pseudo_bit_t HardwareErrMask[1];
+ pseudo_bit_t ResetNegatedMask[1];
+};
+struct QIB_7322_ErrMask {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ErrMask_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ErrStatus_offset 0x00000088UL
+struct QIB_7322_ErrStatus_pb {
+ pseudo_bit_t _unused_0[12];
+ pseudo_bit_t RcvEgrFullErr[1];
+ pseudo_bit_t RcvHdrFullErr[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t SDmaBufMaskDuplicateErr[1];
+ pseudo_bit_t SDmaWrongPortErr[1];
+ pseudo_bit_t SendSpecialTriggerErr[1];
+ pseudo_bit_t _unused_2[7];
+ pseudo_bit_t SendArmLaunchErr[1];
+ pseudo_bit_t SendVLMismatchErr[1];
+ pseudo_bit_t _unused_3[15];
+ pseudo_bit_t RcvContextShareErr[1];
+ pseudo_bit_t InvalidEEPCmdErr[1];
+ pseudo_bit_t _unused_4[1];
+ pseudo_bit_t SBufVL15MisUseErr[1];
+ pseudo_bit_t SDmaVL15Err[1];
+ pseudo_bit_t _unused_5[4];
+ pseudo_bit_t InvalidAddrErr[1];
+ pseudo_bit_t HardwareErr[1];
+ pseudo_bit_t ResetNegated[1];
+};
+struct QIB_7322_ErrStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ErrStatus_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ErrClear_offset 0x00000090UL
+struct QIB_7322_ErrClear_pb {
+ pseudo_bit_t _unused_0[12];
+ pseudo_bit_t RcvEgrFullErrClear[1];
+ pseudo_bit_t RcvHdrFullErrClear[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t SDmaBufMaskDuplicateErrClear[1];
+ pseudo_bit_t SDmaWrongPortErrClear[1];
+ pseudo_bit_t SendSpecialTriggerErrClear[1];
+ pseudo_bit_t _unused_2[7];
+ pseudo_bit_t SendArmLaunchErrClear[1];
+ pseudo_bit_t SendVLMismatchErrMask[1];
+ pseudo_bit_t _unused_3[15];
+ pseudo_bit_t RcvContextShareErrClear[1];
+ pseudo_bit_t InvalidEEPCmdErrClear[1];
+ pseudo_bit_t _unused_4[1];
+ pseudo_bit_t SBufVL15MisUseErrClear[1];
+ pseudo_bit_t SDmaVL15ErrClear[1];
+ pseudo_bit_t _unused_5[4];
+ pseudo_bit_t InvalidAddrErrClear[1];
+ pseudo_bit_t HardwareErrClear[1];
+ pseudo_bit_t ResetNegatedClear[1];
+};
+struct QIB_7322_ErrClear {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ErrClear_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_HwErrMask_offset 0x00000098UL
+struct QIB_7322_HwErrMask_pb {
+ pseudo_bit_t _unused_0[11];
+ pseudo_bit_t LATriggeredMask[1];
+ pseudo_bit_t statusValidNoEopMask_0[1];
+ pseudo_bit_t IBCBusFromSPCParityErrMask_0[1];
+ pseudo_bit_t statusValidNoEopMask_1[1];
+ pseudo_bit_t IBCBusFromSPCParityErrMask_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t SDmaMemReadErrMask_0[1];
+ pseudo_bit_t SDmaMemReadErrMask_1[1];
+ pseudo_bit_t PciePoisonedTLPMask[1];
+ pseudo_bit_t PcieCplTimeoutMask[1];
+ pseudo_bit_t PCIeBusParityErrMask[3];
+ pseudo_bit_t pcie_phy_txParityErr[1];
+ pseudo_bit_t _unused_2[13];
+ pseudo_bit_t MemoryErrMask[1];
+ pseudo_bit_t _unused_3[4];
+ pseudo_bit_t TempsenseTholdReachedMask[1];
+ pseudo_bit_t PowerOnBISTFailedMask[1];
+ pseudo_bit_t PCIESerdesPClkNotDetectMask[1];
+ pseudo_bit_t _unused_4[6];
+ pseudo_bit_t IBSerdesPClkNotDetectMask_0[1];
+ pseudo_bit_t IBSerdesPClkNotDetectMask_1[1];
+};
+struct QIB_7322_HwErrMask {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_HwErrMask_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_HwErrStatus_offset 0x000000a0UL
+struct QIB_7322_HwErrStatus_pb {
+ pseudo_bit_t _unused_0[11];
+ pseudo_bit_t LATriggered[1];
+ pseudo_bit_t statusValidNoEop_0[1];
+ pseudo_bit_t IBCBusFromSPCParityErr_0[1];
+ pseudo_bit_t statusValidNoEop_1[1];
+ pseudo_bit_t IBCBusFromSPCParityErr_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t SDmaMemReadErr_0[1];
+ pseudo_bit_t SDmaMemReadErr_1[1];
+ pseudo_bit_t PciePoisonedTLP[1];
+ pseudo_bit_t PcieCplTimeout[1];
+ pseudo_bit_t PCIeBusParity[3];
+ pseudo_bit_t pcie_phy_txParityErr[1];
+ pseudo_bit_t _unused_2[13];
+ pseudo_bit_t MemoryErr[1];
+ pseudo_bit_t _unused_3[4];
+ pseudo_bit_t TempsenseTholdReached[1];
+ pseudo_bit_t PowerOnBISTFailed[1];
+ pseudo_bit_t PCIESerdesPClkNotDetect[1];
+ pseudo_bit_t _unused_4[6];
+ pseudo_bit_t IBSerdesPClkNotDetect_0[1];
+ pseudo_bit_t IBSerdesPClkNotDetect_1[1];
+};
+struct QIB_7322_HwErrStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_HwErrStatus_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_HwErrClear_offset 0x000000a8UL
+struct QIB_7322_HwErrClear_pb {
+ pseudo_bit_t _unused_0[11];
+ pseudo_bit_t LATriggeredClear[1];
+ pseudo_bit_t IBCBusToSPCparityErrClear_0[1];
+ pseudo_bit_t IBCBusFromSPCParityErrClear_0[1];
+ pseudo_bit_t IBCBusToSPCparityErrClear_1[1];
+ pseudo_bit_t IBCBusFromSPCParityErrClear_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t SDmaMemReadErrClear_0[1];
+ pseudo_bit_t SDmaMemReadErrClear_1[1];
+ pseudo_bit_t PciePoisonedTLPClear[1];
+ pseudo_bit_t PcieCplTimeoutClear[1];
+ pseudo_bit_t PCIeBusParityClear[3];
+ pseudo_bit_t pcie_phy_txParityErr[1];
+ pseudo_bit_t _unused_2[13];
+ pseudo_bit_t MemoryErrClear[1];
+ pseudo_bit_t _unused_3[4];
+ pseudo_bit_t TempsenseTholdReachedClear[1];
+ pseudo_bit_t PowerOnBISTFailedClear[1];
+ pseudo_bit_t PCIESerdesPClkNotDetectClear[1];
+ pseudo_bit_t _unused_4[6];
+ pseudo_bit_t IBSerdesPClkNotDetectClear_0[1];
+ pseudo_bit_t IBSerdesPClkNotDetectClear_1[1];
+};
+struct QIB_7322_HwErrClear {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_HwErrClear_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_HwDiagCtrl_offset 0x000000b0UL
+struct QIB_7322_HwDiagCtrl_pb {
+ pseudo_bit_t _unused_0[12];
+ pseudo_bit_t ForcestatusValidNoEop_0[1];
+ pseudo_bit_t ForceIBCBusFromSPCParityErr_0[1];
+ pseudo_bit_t ForcestatusValidNoEop_1[1];
+ pseudo_bit_t ForceIBCBusFromSPCParityErr_1[1];
+ pseudo_bit_t _unused_1[15];
+ pseudo_bit_t forcePCIeBusParity[4];
+ pseudo_bit_t _unused_2[25];
+ pseudo_bit_t CounterDisable[1];
+ pseudo_bit_t CounterWrEnable[1];
+ pseudo_bit_t _unused_3[1];
+ pseudo_bit_t Diagnostic[1];
+};
+struct QIB_7322_HwDiagCtrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_HwDiagCtrl_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_EXTStatus_offset 0x000000c0UL
+struct QIB_7322_EXTStatus_pb {
+ pseudo_bit_t _unused_0[14];
+ pseudo_bit_t MemBISTEndTest[1];
+ pseudo_bit_t MemBISTDisabled[1];
+ pseudo_bit_t _unused_1[32];
+ pseudo_bit_t GPIOIn[16];
+};
+struct QIB_7322_EXTStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_EXTStatus_pb );
+};
+/* Default value: 0x000000000000X000 */
+
+#define QIB_7322_EXTCtrl_offset 0x000000c8UL
+struct QIB_7322_EXTCtrl_pb {
+ pseudo_bit_t LEDPort0YellowOn[1];
+ pseudo_bit_t LEDPort0GreenOn[1];
+ pseudo_bit_t LEDPort1YellowOn[1];
+ pseudo_bit_t LEDPort1GreenOn[1];
+ pseudo_bit_t _unused_0[28];
+ pseudo_bit_t GPIOInvert[16];
+ pseudo_bit_t GPIOOe[16];
+};
+struct QIB_7322_EXTCtrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_EXTCtrl_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_GPIODebugSelReg_offset 0x000000d8UL
+struct QIB_7322_GPIODebugSelReg_pb {
+ pseudo_bit_t GPIOSourceSelDebug[16];
+ pseudo_bit_t SelPulse[16];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7322_GPIODebugSelReg {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_GPIODebugSelReg_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_GPIOOut_offset 0x000000e0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_GPIOMask_offset 0x000000e8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_GPIOStatus_offset 0x000000f0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_GPIOClear_offset 0x000000f8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvCtrl_offset 0x00000100UL
+struct QIB_7322_RcvCtrl_pb {
+ pseudo_bit_t dontDropRHQFull[18];
+ pseudo_bit_t _unused_0[2];
+ pseudo_bit_t IntrAvail[18];
+ pseudo_bit_t _unused_1[3];
+ pseudo_bit_t ContextCfg[2];
+ pseudo_bit_t TidFlowEnable[1];
+ pseudo_bit_t XrcTypeCode[3];
+ pseudo_bit_t TailUpd[1];
+ pseudo_bit_t TidReDirect[16];
+};
+struct QIB_7322_RcvCtrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvCtrl_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrSize_offset 0x00000110UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrCnt_offset 0x00000118UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrEntSize_offset 0x00000120UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDBase_offset 0x00000128UL
+/* Default value: 0x0000000000050000 */
+
+#define QIB_7322_RcvTIDCnt_offset 0x00000130UL
+/* Default value: 0x0000000000000200 */
+
+#define QIB_7322_RcvEgrBase_offset 0x00000138UL
+/* Default value: 0x0000000000014000 */
+
+#define QIB_7322_RcvEgrCnt_offset 0x00000140UL
+/* Default value: 0x0000000000001000 */
+
+#define QIB_7322_RcvBufBase_offset 0x00000148UL
+/* Default value: 0x0000000000080000 */
+
+#define QIB_7322_RcvBufSize_offset 0x00000150UL
+/* Default value: 0x0000000000005000 */
+
+#define QIB_7322_RxIntMemBase_offset 0x00000158UL
+/* Default value: 0x0000000000077000 */
+
+#define QIB_7322_RxIntMemSize_offset 0x00000160UL
+/* Default value: 0x0000000000007000 */
+
+#define QIB_7322_encryption_key_low_offset 0x00000180UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_encryption_key_high_offset 0x00000188UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_feature_mask_offset 0x00000190UL
+/* Default value: 0x00000000000000XX */
+
+#define QIB_7322_active_feature_mask_offset 0x00000198UL
+struct QIB_7322_active_feature_mask_pb {
+ pseudo_bit_t Port0_SDR_Enabled[1];
+ pseudo_bit_t Port0_DDR_Enabled[1];
+ pseudo_bit_t Port0_QDR_Enabled[1];
+ pseudo_bit_t Port1_SDR_Enabled[1];
+ pseudo_bit_t Port1_DDR_Enabled[1];
+ pseudo_bit_t Port1_QDR_Enabled[1];
+ pseudo_bit_t _unused_0[58];
+};
+struct QIB_7322_active_feature_mask {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_active_feature_mask_pb );
+};
+/* Default value: 0x00000000000000XX */
+
+#define QIB_7322_SendCtrl_offset 0x000001c0UL
+struct QIB_7322_SendCtrl_pb {
+ pseudo_bit_t _unused_0[1];
+ pseudo_bit_t SendIntBufAvail[1];
+ pseudo_bit_t SendBufAvailUpd[1];
+ pseudo_bit_t _unused_1[1];
+ pseudo_bit_t SpecialTriggerEn[1];
+ pseudo_bit_t _unused_2[11];
+ pseudo_bit_t DisarmSendBuf[8];
+ pseudo_bit_t AvailUpdThld[5];
+ pseudo_bit_t SendBufAvailPad64Byte[1];
+ pseudo_bit_t _unused_3[1];
+ pseudo_bit_t Disarm[1];
+ pseudo_bit_t _unused_4[32];
+};
+struct QIB_7322_SendCtrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendCtrl_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufBase_offset 0x000001c8UL
+struct QIB_7322_SendBufBase_pb {
+ pseudo_bit_t BaseAddr_SmallPIO[21];
+ pseudo_bit_t _unused_0[11];
+ pseudo_bit_t BaseAddr_LargePIO[21];
+ pseudo_bit_t _unused_1[11];
+};
+struct QIB_7322_SendBufBase {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendBufBase_pb );
+};
+/* Default value: 0x0018000000100000 */
+
+#define QIB_7322_SendBufSize_offset 0x000001d0UL
+struct QIB_7322_SendBufSize_pb {
+ pseudo_bit_t Size_SmallPIO[12];
+ pseudo_bit_t _unused_0[20];
+ pseudo_bit_t Size_LargePIO[13];
+ pseudo_bit_t _unused_1[19];
+};
+struct QIB_7322_SendBufSize {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendBufSize_pb );
+};
+/* Default value: 0x0000108000000880 */
+
+#define QIB_7322_SendBufCnt_offset 0x000001d8UL
+struct QIB_7322_SendBufCnt_pb {
+ pseudo_bit_t Num_SmallBuffers[9];
+ pseudo_bit_t _unused_0[23];
+ pseudo_bit_t Num_LargeBuffers[6];
+ pseudo_bit_t _unused_1[26];
+};
+struct QIB_7322_SendBufCnt {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendBufCnt_pb );
+};
+/* Default value: 0x0000002000000080 */
+
+#define QIB_7322_SendBufAvailAddr_offset 0x000001e0UL
+struct QIB_7322_SendBufAvailAddr_pb {
+ pseudo_bit_t _unused_0[6];
+ pseudo_bit_t SendBufAvailAddr[34];
+ pseudo_bit_t _unused_1[24];
+};
+struct QIB_7322_SendBufAvailAddr {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendBufAvailAddr_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxIntMemBase_offset 0x000001e8UL
+/* Default value: 0x0000000000064000 */
+
+#define QIB_7322_TxIntMemSize_offset 0x000001f0UL
+/* Default value: 0x000000000000C000 */
+
+#define QIB_7322_SendBufErr0_offset 0x00000240UL
+struct QIB_7322_SendBufErr0_pb {
+ pseudo_bit_t SendBufErr_63_0[64];
+};
+struct QIB_7322_SendBufErr0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendBufErr0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_AvailUpdCount_offset 0x00000268UL
+struct QIB_7322_AvailUpdCount_pb {
+ pseudo_bit_t AvailUpdCount[5];
+ pseudo_bit_t _unused_0[59];
+};
+struct QIB_7322_AvailUpdCount {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_AvailUpdCount_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrAddr0_offset 0x00000280UL
+struct QIB_7322_RcvHdrAddr0_pb {
+ pseudo_bit_t _unused_0[2];
+ pseudo_bit_t RcvHdrAddr[38];
+ pseudo_bit_t _unused_1[24];
+};
+struct QIB_7322_RcvHdrAddr0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrAddr0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTailAddr0_offset 0x00000340UL
+struct QIB_7322_RcvHdrTailAddr0_pb {
+ pseudo_bit_t _unused_0[2];
+ pseudo_bit_t RcvHdrTailAddr[38];
+ pseudo_bit_t _unused_1[24];
+};
+struct QIB_7322_RcvHdrTailAddr0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrTailAddr0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_EEPCtlStat_offset 0x000003e8UL
+struct QIB_7322_EEPCtlStat_pb {
+ pseudo_bit_t EPAccEn[2];
+ pseudo_bit_t EPReset[1];
+ pseudo_bit_t ByteProg[1];
+ pseudo_bit_t PageMode[1];
+ pseudo_bit_t LstDatWr[1];
+ pseudo_bit_t CmdWrErr[1];
+ pseudo_bit_t _unused_0[24];
+ pseudo_bit_t CtlrStat[1];
+ pseudo_bit_t _unused_1[32];
+};
+struct QIB_7322_EEPCtlStat {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_EEPCtlStat_pb );
+};
+/* Default value: 0x0000000000000002 */
+
+#define QIB_7322_EEPAddrCmd_offset 0x000003f0UL
+struct QIB_7322_EEPAddrCmd_pb {
+ pseudo_bit_t EPAddr[24];
+ pseudo_bit_t EPCmd[8];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7322_EEPAddrCmd {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_EEPAddrCmd_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_EEPData_offset 0x000003f8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_efuse_control_reg_offset 0x00000410UL
+struct QIB_7322_efuse_control_reg_pb {
+ pseudo_bit_t address[11];
+ pseudo_bit_t last_program_address[11];
+ pseudo_bit_t operation[2];
+ pseudo_bit_t start_operation[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t req_err[1];
+ pseudo_bit_t read_data_valid[1];
+ pseudo_bit_t rdy[1];
+ pseudo_bit_t _unused_1[32];
+};
+struct QIB_7322_efuse_control_reg {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_efuse_control_reg_pb );
+};
+/* Default value: 0x0000000080000000 */
+
+#define QIB_7322_efuse_data_reg_offset 0x00000418UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_voltage_margin_reg_offset 0x00000428UL
+struct QIB_7322_voltage_margin_reg_pb {
+ pseudo_bit_t voltage_margin_settings_enable[1];
+ pseudo_bit_t voltage_margin_settings[2];
+ pseudo_bit_t _unused_0[61];
+};
+struct QIB_7322_voltage_margin_reg {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_voltage_margin_reg_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_VTSense_reg_offset 0x00000430UL
+struct QIB_7322_VTSense_reg_pb {
+ pseudo_bit_t temp_sense_select[3];
+ pseudo_bit_t adc_mode[1];
+ pseudo_bit_t start_busy[1];
+ pseudo_bit_t power_down[1];
+ pseudo_bit_t threshold[10];
+ pseudo_bit_t sensor_output_data[10];
+ pseudo_bit_t _unused_0[1];
+ pseudo_bit_t threshold_limbit[1];
+ pseudo_bit_t _unused_1[3];
+ pseudo_bit_t output_valid[1];
+ pseudo_bit_t _unused_2[32];
+};
+struct QIB_7322_VTSense_reg {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_VTSense_reg_pb );
+};
+/* Default value: 0x0000000000000020 */
+
+#define QIB_7322_procmon_reg_offset 0x00000438UL
+struct QIB_7322_procmon_reg_pb {
+ pseudo_bit_t ring_osc_select[3];
+ pseudo_bit_t _unused_0[12];
+ pseudo_bit_t start_counter[1];
+ pseudo_bit_t procmon_count[12];
+ pseudo_bit_t _unused_1[3];
+ pseudo_bit_t procmon_count_valid[1];
+ pseudo_bit_t _unused_2[32];
+};
+struct QIB_7322_procmon_reg {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_procmon_reg_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieRbufTestReg0_offset 0x00000440UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ahb_access_ctrl_offset 0x00000460UL
+struct QIB_7322_ahb_access_ctrl_pb {
+ pseudo_bit_t sw_ahb_sel[1];
+ pseudo_bit_t sw_sel_ahb_trgt[2];
+ pseudo_bit_t _unused_0[61];
+};
+struct QIB_7322_ahb_access_ctrl {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ahb_access_ctrl_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ahb_transaction_reg_offset 0x00000468UL
+struct QIB_7322_ahb_transaction_reg_pb {
+ pseudo_bit_t _unused_0[16];
+ pseudo_bit_t ahb_address[11];
+ pseudo_bit_t write_not_read[1];
+ pseudo_bit_t _unused_1[2];
+ pseudo_bit_t ahb_req_err[1];
+ pseudo_bit_t ahb_rdy[1];
+ pseudo_bit_t ahb_data[32];
+};
+struct QIB_7322_ahb_transaction_reg {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ahb_transaction_reg_pb );
+};
+/* Default value: 0x0000000080000000 */
+
+#define QIB_7322_SPC_JTAG_ACCESS_REG_offset 0x00000470UL
+struct QIB_7322_SPC_JTAG_ACCESS_REG_pb {
+ pseudo_bit_t rdy[1];
+ pseudo_bit_t tdo[1];
+ pseudo_bit_t tdi[1];
+ pseudo_bit_t opcode[2];
+ pseudo_bit_t bist_en[5];
+ pseudo_bit_t SPC_JTAG_ACCESS_EN[1];
+ pseudo_bit_t _unused_0[53];
+};
+struct QIB_7322_SPC_JTAG_ACCESS_REG {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SPC_JTAG_ACCESS_REG_pb );
+};
+/* Default value: 0x0000000000000001 */
+
+#define QIB_7322_LAControlReg_offset 0x00000478UL
+struct QIB_7322_LAControlReg_pb {
+ pseudo_bit_t Finished[1];
+ pseudo_bit_t Address[9];
+ pseudo_bit_t Mode[2];
+ pseudo_bit_t Delay[20];
+ pseudo_bit_t Finished_sc[1];
+ pseudo_bit_t Address_sc[9];
+ pseudo_bit_t Mode_sc[2];
+ pseudo_bit_t Delay_sc[20];
+};
+struct QIB_7322_LAControlReg {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_LAControlReg_pb );
+};
+/* Default value: 0x0000000100000001 */
+
+#define QIB_7322_PcieRhdrTestReg0_offset 0x00000480UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendCheckMask0_offset 0x000004c0UL
+struct QIB_7322_SendCheckMask0_pb {
+ pseudo_bit_t SendCheckMask_63_32[64];
+};
+struct QIB_7322_SendCheckMask0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendCheckMask0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendGRHCheckMask0_offset 0x000004e0UL
+struct QIB_7322_SendGRHCheckMask0_pb {
+ pseudo_bit_t SendGRHCheckMask_63_32[64];
+};
+struct QIB_7322_SendGRHCheckMask0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendGRHCheckMask0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendIBPacketMask0_offset 0x00000500UL
+struct QIB_7322_SendIBPacketMask0_pb {
+ pseudo_bit_t SendIBPacketMask_63_32[64];
+};
+struct QIB_7322_SendIBPacketMask0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendIBPacketMask0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IntRedirect0_offset 0x00000540UL
+struct QIB_7322_IntRedirect0_pb {
+ pseudo_bit_t vec0[5];
+ pseudo_bit_t vec1[5];
+ pseudo_bit_t vec2[5];
+ pseudo_bit_t vec3[5];
+ pseudo_bit_t vec4[5];
+ pseudo_bit_t vec5[5];
+ pseudo_bit_t vec6[5];
+ pseudo_bit_t vec7[5];
+ pseudo_bit_t vec8[5];
+ pseudo_bit_t vec9[5];
+ pseudo_bit_t vec10[5];
+ pseudo_bit_t vec11[5];
+ pseudo_bit_t _unused_0[4];
+};
+struct QIB_7322_IntRedirect0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IntRedirect0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_Int_Granted_offset 0x00000570UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_vec_clr_without_int_offset 0x00000578UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_DCACtrlA_offset 0x00000580UL
+struct QIB_7322_DCACtrlA_pb {
+ pseudo_bit_t RcvHdrqDCAEnable[1];
+ pseudo_bit_t EagerDCAEnable[1];
+ pseudo_bit_t RcvTailUpdDCAEnable[1];
+ pseudo_bit_t SendDMAHead0DCAEnable[1];
+ pseudo_bit_t SendDMAHead1DCAEnable[1];
+ pseudo_bit_t _unused_0[59];
+};
+struct QIB_7322_DCACtrlA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_DCACtrlA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_DCACtrlB_offset 0x00000588UL
+struct QIB_7322_DCACtrlB_pb {
+ pseudo_bit_t RcvHdrq0DCAOPH[8];
+ pseudo_bit_t RcvHdrq0DCAXfrCnt[6];
+ pseudo_bit_t RcvHdrq1DCAOPH[8];
+ pseudo_bit_t RcvHdrq1DCAXfrCnt[6];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t RcvHdrq2DCAOPH[8];
+ pseudo_bit_t RcvHdrq2DCAXfrCnt[6];
+ pseudo_bit_t RcvHdrq3DCAOPH[8];
+ pseudo_bit_t RcvHdrq3DCAXfrCnt[6];
+ pseudo_bit_t _unused_1[4];
+};
+struct QIB_7322_DCACtrlB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_DCACtrlB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_DCACtrlC_offset 0x00000590UL
+struct QIB_7322_DCACtrlC_pb {
+ pseudo_bit_t RcvHdrq4DCAOPH[8];
+ pseudo_bit_t RcvHdrq4DCAXfrCnt[6];
+ pseudo_bit_t RcvHdrq5DCAOPH[8];
+ pseudo_bit_t RcvHdrq5DCAXfrCnt[6];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t RcvHdrq6DCAOPH[8];
+ pseudo_bit_t RcvHdrq6DCAXfrCnt[6];
+ pseudo_bit_t RcvHdrq7DCAOPH[8];
+ pseudo_bit_t RcvHdrq7DCAXfrCnt[6];
+ pseudo_bit_t _unused_1[4];
+};
+struct QIB_7322_DCACtrlC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_DCACtrlC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_DCACtrlD_offset 0x00000598UL
+struct QIB_7322_DCACtrlD_pb {
+ pseudo_bit_t RcvHdrq8DCAOPH[8];
+ pseudo_bit_t RcvHdrq8DCAXfrCnt[6];
+ pseudo_bit_t RcvHdrq9DCAOPH[8];
+ pseudo_bit_t RcvHdrq9DCAXfrCnt[6];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t RcvHdrq10DCAOPH[8];
+ pseudo_bit_t RcvHdrq10DCAXfrCnt[6];
+ pseudo_bit_t RcvHdrq11DCAOPH[8];
+ pseudo_bit_t RcvHdrq11DCAXfrCnt[6];
+ pseudo_bit_t _unused_1[4];
+};
+struct QIB_7322_DCACtrlD {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_DCACtrlD_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_DCACtrlE_offset 0x000005a0UL
+struct QIB_7322_DCACtrlE_pb {
+ pseudo_bit_t RcvHdrq12DCAOPH[8];
+ pseudo_bit_t RcvHdrq12DCAXfrCnt[6];
+ pseudo_bit_t RcvHdrq13DCAOPH[8];
+ pseudo_bit_t RcvHdrq13DCAXfrCnt[6];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t RcvHdrq14DCAOPH[8];
+ pseudo_bit_t RcvHdrq14DCAXfrCnt[6];
+ pseudo_bit_t RcvHdrq15DCAOPH[8];
+ pseudo_bit_t RcvHdrq15DCAXfrCnt[6];
+ pseudo_bit_t _unused_1[4];
+};
+struct QIB_7322_DCACtrlE {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_DCACtrlE_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_DCACtrlF_offset 0x000005a8UL
+struct QIB_7322_DCACtrlF_pb {
+ pseudo_bit_t RcvHdrq16DCAOPH[8];
+ pseudo_bit_t RcvHdrq16DCAXfrCnt[6];
+ pseudo_bit_t RcvHdrq17DCAOPH[8];
+ pseudo_bit_t RcvHdrq17DCAXfrCnt[6];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SendDma0DCAOPH[8];
+ pseudo_bit_t SendDma1DCAOPH[8];
+ pseudo_bit_t _unused_1[16];
+};
+struct QIB_7322_DCACtrlF {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_DCACtrlF_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemErrCtrlA_offset 0x00000600UL
+struct QIB_7322_MemErrCtrlA_pb {
+ pseudo_bit_t FSSUncErrRcvBuf_0[1];
+ pseudo_bit_t FSSUncErrRcvFlags_0[1];
+ pseudo_bit_t FSSUncErrLookupiqBuf_0[1];
+ pseudo_bit_t FSSUncErrRcvDMAHdrBuf_0[1];
+ pseudo_bit_t FSSUncErrRcvDMADataBuf_0[1];
+ pseudo_bit_t FSSUncErrRcvBuf_1[1];
+ pseudo_bit_t FSSUncErrRcvFlags_1[1];
+ pseudo_bit_t FSSUncErrLookupiqBuf_1[1];
+ pseudo_bit_t FSSUncErrRcvDMAHdrBuf_1[1];
+ pseudo_bit_t FSSUncErrRcvDMADataBuf_1[1];
+ pseudo_bit_t FSSUncErrRcvTIDArray[1];
+ pseudo_bit_t FSSUncErrRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t FSSUncErrSendBufVL15[1];
+ pseudo_bit_t FSSUncErrSendBufMain[1];
+ pseudo_bit_t FSSUncErrSendBufExtra[1];
+ pseudo_bit_t FSSUncErrSendPbcArray[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO0_0[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO1_0[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO2_0[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO3_0[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO4_0[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO5_0[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO6_0[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO7_0[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO0_1[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO1_1[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO2_1[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO3_1[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO4_1[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO5_1[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO6_1[1];
+ pseudo_bit_t FSSUncErrSendLaFIFO7_1[1];
+ pseudo_bit_t FSSUncErrSendRmFIFO_0[1];
+ pseudo_bit_t FSSUncErrSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t FSSUncErrPCIeRetryBuf[1];
+ pseudo_bit_t FSSUncErrPCIePostHdrBuf[1];
+ pseudo_bit_t FSSUncErrPCIePostDataBuf[1];
+ pseudo_bit_t FSSUncErrPCIeCompHdrBuf[1];
+ pseudo_bit_t FSSUncErrPCIeCompDataBuf[1];
+ pseudo_bit_t FSSUncErrMsixTable0[1];
+ pseudo_bit_t FSSUncErrMsixTable1[1];
+ pseudo_bit_t FSSUncErrMsixTable2[1];
+ pseudo_bit_t _unused_2[4];
+ pseudo_bit_t SwapEccDataMsixBits[1];
+ pseudo_bit_t SwapEccDataExtraBits[1];
+ pseudo_bit_t DisableEccCorrection[1];
+ pseudo_bit_t SwapEccDataBits[1];
+};
+struct QIB_7322_MemErrCtrlA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemErrCtrlA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemErrCtrlB_offset 0x00000608UL
+struct QIB_7322_MemErrCtrlB_pb {
+ pseudo_bit_t FSSCorErrRcvBuf_0[1];
+ pseudo_bit_t FSSCorErrRcvFlags_0[1];
+ pseudo_bit_t FSSCorErrLookupiqBuf_0[1];
+ pseudo_bit_t FSSCorErrRcvDMAHdrBuf_0[1];
+ pseudo_bit_t FSSCorErrRcvDMADataBuf_0[1];
+ pseudo_bit_t FSSCorErrRcvBuf_1[1];
+ pseudo_bit_t FSSCorErrRcvFlags_1[1];
+ pseudo_bit_t FSSCorErrLookupiqBuf_1[1];
+ pseudo_bit_t FSSCorErrRcvDMAHdrBuf_1[1];
+ pseudo_bit_t FSSCorErrRcvDMADataBuf_1[1];
+ pseudo_bit_t FSSCorErrRcvTIDArray[1];
+ pseudo_bit_t FSSCorErrRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t FSSCorErrSendBufVL15[1];
+ pseudo_bit_t FSSCorErrSendBufMain[1];
+ pseudo_bit_t FSSCorErrSendBufExtra[1];
+ pseudo_bit_t FSSCorErrSendPbcArray[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO0_0[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO1_0[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO2_0[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO3_0[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO4_0[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO5_0[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO6_0[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO7_0[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO0_1[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO1_1[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO2_1[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO3_1[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO4_1[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO5_1[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO6_1[1];
+ pseudo_bit_t FSSCorErrSendLaFIFO7_1[1];
+ pseudo_bit_t FSSCorErrSendRmFIFO_0[1];
+ pseudo_bit_t FSSCorErrSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t FSSCorErrPCIeRetryBuf[1];
+ pseudo_bit_t FSSCorErrPCIePostHdrBuf[1];
+ pseudo_bit_t FSSCorErrPCIePostDataBuf[1];
+ pseudo_bit_t FSSCorErrPCIeCompHdrBuf[1];
+ pseudo_bit_t FSSCorErrPCIeCompDataBuf[1];
+ pseudo_bit_t FSSCorErrMsixTable0[1];
+ pseudo_bit_t FSSCorErrMsixTable1[1];
+ pseudo_bit_t FSSCorErrMsixTable2[1];
+ pseudo_bit_t _unused_2[8];
+};
+struct QIB_7322_MemErrCtrlB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemErrCtrlB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemMultiUnCorErrMask_offset 0x00000610UL
+struct QIB_7322_MemMultiUnCorErrMask_pb {
+ pseudo_bit_t MulUncErrMskRcvBuf_0[1];
+ pseudo_bit_t MulUncErrMskRcvFlags_0[1];
+ pseudo_bit_t MulUncErrMskLookupiqBuf_0[1];
+ pseudo_bit_t MulUncErrMskRcvDMAHdrBuf_0[1];
+ pseudo_bit_t MulUncErrMskRcvDMADataBuf_0[1];
+ pseudo_bit_t MulUncErrMskRcvBuf_1[1];
+ pseudo_bit_t MulUncErrMskRcvFlags_1[1];
+ pseudo_bit_t MulUncErrMskLookupiqBuf_1[1];
+ pseudo_bit_t MulUncErrMskRcvDMAHdrBuf_1[1];
+ pseudo_bit_t MulUncErrMskRcvDMADataBuf_1[1];
+ pseudo_bit_t MulUncErrMskRcvTIDArray[1];
+ pseudo_bit_t MulUncErrMskRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t MulUncErrMskSendBufVL15[1];
+ pseudo_bit_t MulUncErrMskSendBufMain[1];
+ pseudo_bit_t MulUncErrMskSendBufExtra[1];
+ pseudo_bit_t MulUncErrMskSendPbcArray[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO0_0[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO1_0[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO2_0[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO3_0[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO4_0[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO5_0[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO6_0[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO7_0[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO0_1[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO1_1[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO2_1[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO3_1[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO4_1[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO5_1[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO6_1[1];
+ pseudo_bit_t MulUncErrMskSendLaFIFO7_1[1];
+ pseudo_bit_t MulUncErrMskSendRmFIFO_0[1];
+ pseudo_bit_t MulUncErrMskSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t MulUncErrMskPCIeRetryBuf[1];
+ pseudo_bit_t MulUncErrMskPCIePostHdrBuf[1];
+ pseudo_bit_t MulUncErrMskPCIePostDataBuf[1];
+ pseudo_bit_t MulUncErrMskPCIeCompHdrBuf[1];
+ pseudo_bit_t MulUncErrMskPCIeCompDataBuf[1];
+ pseudo_bit_t MulUncErrMskMsixTable0[1];
+ pseudo_bit_t MulUncErrMskMsixTable1[1];
+ pseudo_bit_t MulUncErrMskMsixTable2[1];
+ pseudo_bit_t _unused_2[8];
+};
+struct QIB_7322_MemMultiUnCorErrMask {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemMultiUnCorErrMask_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemMultiUnCorErrStatus_offset 0x00000618UL
+struct QIB_7322_MemMultiUnCorErrStatus_pb {
+ pseudo_bit_t MulUncErrStatusRcvBuf_0[1];
+ pseudo_bit_t MulUncErrStatusRcvFlags_0[1];
+ pseudo_bit_t MulUncErrStatusLookupiqBuf_0[1];
+ pseudo_bit_t MulUncErrStatusRcvDMAHdrBuf_0[1];
+ pseudo_bit_t MulUncErrStatusRcvDMADataBuf_0[1];
+ pseudo_bit_t MulUncErrStatusRcvBuf_1[1];
+ pseudo_bit_t MulUncErrStatusRcvFlags_1[1];
+ pseudo_bit_t MulUncErrStatusLookupiqBuf_1[1];
+ pseudo_bit_t MulUncErrStatusRcvDMAHdrBuf_1[1];
+ pseudo_bit_t MulUncErrStatusRcvDMADataBuf_1[1];
+ pseudo_bit_t MulUncErrStatusRcvTIDArray[1];
+ pseudo_bit_t MulUncErrStatusRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t MulUncErrStatusSendBufVL15[1];
+ pseudo_bit_t MulUncErrStatusSendBufMain[1];
+ pseudo_bit_t MulUncErrStatusSendBufExtra[1];
+ pseudo_bit_t MulUncErrStatusSendPbcArray[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO0_0[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO1_0[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO2_0[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO3_0[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO4_0[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO5_0[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO6_0[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO7_0[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO0_1[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO1_1[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO2_1[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO3_1[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO4_1[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO5_1[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO6_1[1];
+ pseudo_bit_t MulUncErrStatusSendLaFIFO7_1[1];
+ pseudo_bit_t MulUncErrStatusSendRmFIFO_0[1];
+ pseudo_bit_t MulUncErrStatusSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t MulUncErrStatusPCIeRetryBuf[1];
+ pseudo_bit_t MulUncErrStatusPCIePostHdrBuf[1];
+ pseudo_bit_t MulUncErrStatusPCIePostDataBuf[1];
+ pseudo_bit_t MulUncErrStatusPCIeCompHdrBuf[1];
+ pseudo_bit_t MulUncErrStatusPCIeCompDataBuf[1];
+ pseudo_bit_t MulUncErrStatusMsixTable0[1];
+ pseudo_bit_t MulUncErrStatusMsixTable1[1];
+ pseudo_bit_t MulUncErrStatusMsixTable2[1];
+ pseudo_bit_t _unused_2[8];
+};
+struct QIB_7322_MemMultiUnCorErrStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemMultiUnCorErrStatus_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemMultiUnCorErrClear_offset 0x00000620UL
+struct QIB_7322_MemMultiUnCorErrClear_pb {
+ pseudo_bit_t MulUncErrClearRcvBuf_0[1];
+ pseudo_bit_t MulUncErrClearRcvFlags_0[1];
+ pseudo_bit_t MulUncErrClearLookupiqBuf_0[1];
+ pseudo_bit_t MulUncErrClearRcvDMAHdrBuf_0[1];
+ pseudo_bit_t MulUncErrClearRcvDMADataBuf_0[1];
+ pseudo_bit_t MulUncErrClearRcvBuf_1[1];
+ pseudo_bit_t MulUncErrClearRcvFlags_1[1];
+ pseudo_bit_t MulUncErrClearLookupiqBuf_1[1];
+ pseudo_bit_t MulUncErrClearRcvDMAHdrBuf_1[1];
+ pseudo_bit_t MulUncErrClearRcvDMADataBuf_1[1];
+ pseudo_bit_t MulUncErrClearRcvTIDArray[1];
+ pseudo_bit_t MulUncErrClearRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t MulUncErrClearSendBufVL15[1];
+ pseudo_bit_t MulUncErrClearSendBufMain[1];
+ pseudo_bit_t MulUncErrClearSendBufExtra[1];
+ pseudo_bit_t MulUncErrClearSendPbcArray[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO0_0[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO1_0[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO2_0[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO3_0[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO4_0[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO5_0[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO6_0[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO7_0[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO0_1[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO1_1[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO2_1[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO3_1[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO4_1[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO5_1[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO6_1[1];
+ pseudo_bit_t MulUncErrClearSendLaFIFO7_1[1];
+ pseudo_bit_t MulUncErrClearSendRmFIFO_0[1];
+ pseudo_bit_t MulUncErrClearSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t MulUncErrClearPCIeRetryBuf[1];
+ pseudo_bit_t MulUncErrClearPCIePostHdrBuf[1];
+ pseudo_bit_t MulUncErrClearPCIePostDataBuf[1];
+ pseudo_bit_t MulUncErrClearPCIeCompHdrBuf[1];
+ pseudo_bit_t MulUncErrClearPCIeCompDataBuf[1];
+ pseudo_bit_t MulUncErrClearMsixTable0[1];
+ pseudo_bit_t MulUncErrClearMsixTable1[1];
+ pseudo_bit_t MulUncErrClearMsixTable2[1];
+ pseudo_bit_t _unused_2[8];
+};
+struct QIB_7322_MemMultiUnCorErrClear {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemMultiUnCorErrClear_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemUnCorErrMask_offset 0x00000628UL
+struct QIB_7322_MemUnCorErrMask_pb {
+ pseudo_bit_t UncErrMskRcvBuf_0[1];
+ pseudo_bit_t UncErrMskRcvFlags_0[1];
+ pseudo_bit_t UncErrMskLookupiqBuf_0[1];
+ pseudo_bit_t UncErrMskRcvDMAHdrBuf_0[1];
+ pseudo_bit_t UncErrMskRcvDMADataBuf_0[1];
+ pseudo_bit_t UncErrMskRcvBuf_1[1];
+ pseudo_bit_t UncErrMskRcvFlags_1[1];
+ pseudo_bit_t UncErrMskLookupiqBuf_1[1];
+ pseudo_bit_t UncErrMskRcvDMAHdrBuf_1[1];
+ pseudo_bit_t UncErrMskRcvDMADataBuf_1[1];
+ pseudo_bit_t UncErrMskRcvTIDArray[1];
+ pseudo_bit_t UncErrMskRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t UncErrMskSendBufVL15[1];
+ pseudo_bit_t UncErrMskSendBufMain[1];
+ pseudo_bit_t UncErrMskSendBufExtra[1];
+ pseudo_bit_t UncErrMskSendPbcArray[1];
+ pseudo_bit_t UncErrMskSendLaFIFO0_0[1];
+ pseudo_bit_t UncErrMskSendLaFIFO1_0[1];
+ pseudo_bit_t UncErrMskSendLaFIFO2_0[1];
+ pseudo_bit_t UncErrMskSendLaFIFO3_0[1];
+ pseudo_bit_t UncErrMskSendLaFIFO4_0[1];
+ pseudo_bit_t UncErrMskSendLaFIFO5_0[1];
+ pseudo_bit_t UncErrMskSendLaFIFO6_0[1];
+ pseudo_bit_t UncErrMskSendLaFIFO7_0[1];
+ pseudo_bit_t UncErrMskSendLaFIFO0_1[1];
+ pseudo_bit_t UncErrMskSendLaFIFO1_1[1];
+ pseudo_bit_t UncErrMskSendLaFIFO2_1[1];
+ pseudo_bit_t UncErrMskSendLaFIFO3_1[1];
+ pseudo_bit_t UncErrMskSendLaFIFO4_1[1];
+ pseudo_bit_t UncErrMskSendLaFIFO5_1[1];
+ pseudo_bit_t UncErrMskSendLaFIFO6_1[1];
+ pseudo_bit_t UncErrMskSendLaFIFO7_1[1];
+ pseudo_bit_t UncErrMskSendRmFIFO_0[1];
+ pseudo_bit_t UncErrMskSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t UncErrMskPCIeRetryBuf[1];
+ pseudo_bit_t UncErrMskPCIePostHdrBuf[1];
+ pseudo_bit_t UncErrMskPCIePostDataBuf[1];
+ pseudo_bit_t UncErrMskPCIeCompHdrBuf[1];
+ pseudo_bit_t UncErrMskPCIeCompDataBuf[1];
+ pseudo_bit_t UncErrMskMsixTable0[1];
+ pseudo_bit_t UncErrMskMsixTable1[1];
+ pseudo_bit_t UncErrMskMsixTable2[1];
+ pseudo_bit_t _unused_2[8];
+};
+struct QIB_7322_MemUnCorErrMask {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemUnCorErrMask_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemUnCorErrStatus_offset 0x00000630UL
+struct QIB_7322_MemUnCorErrStatus_pb {
+ pseudo_bit_t UncErrStatusRcvBuf_0[1];
+ pseudo_bit_t UncErrStatusRcvFlags_0[1];
+ pseudo_bit_t UncErrStatusLookupiqBuf_0[1];
+ pseudo_bit_t UncErrStatusRcvDMAHdrBuf_0[1];
+ pseudo_bit_t UncErrStatusRcvDMADataBuf_0[1];
+ pseudo_bit_t UncErrStatusRcvBuf_1[1];
+ pseudo_bit_t UncErrStatusRcvFlags_1[1];
+ pseudo_bit_t UncErrStatusLookupiqBuf_1[1];
+ pseudo_bit_t UncErrStatusRcvDMAHdrBuf_1[1];
+ pseudo_bit_t UncErrStatusRcvDMADataBuf_1[1];
+ pseudo_bit_t UncErrStatusRcvTIDArray[1];
+ pseudo_bit_t UncErrStatusRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t UncErrStatusSendBufVL15[1];
+ pseudo_bit_t UncErrStatusSendBufMain[1];
+ pseudo_bit_t UncErrStatusSendBufExtra[1];
+ pseudo_bit_t UncErrStatusSendPbcArray[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO0_0[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO1_0[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO2_0[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO3_0[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO4_0[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO5_0[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO6_0[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO7_0[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO0_1[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO1_1[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO2_1[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO3_1[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO4_1[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO5_1[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO6_1[1];
+ pseudo_bit_t UncErrStatusSendLaFIFO7_1[1];
+ pseudo_bit_t UncErrStatusSendRmFIFO_0[1];
+ pseudo_bit_t UncErrStatusSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t UncErrStatusPCIeRetryBuf[1];
+ pseudo_bit_t UncErrStatusPCIePostHdrBuf[1];
+ pseudo_bit_t UncErrStatusPCIePostDataBuf[1];
+ pseudo_bit_t UncErrStatusPCIeCompHdrBuf[1];
+ pseudo_bit_t UncErrStatusPCIeCompDataBuf[1];
+ pseudo_bit_t UncErrStatusMsixTable0[1];
+ pseudo_bit_t UncErrStatusMsixTable1[1];
+ pseudo_bit_t UncErrStatusMsixTable2[1];
+ pseudo_bit_t _unused_2[8];
+};
+struct QIB_7322_MemUnCorErrStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemUnCorErrStatus_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemUnCorErrClear_offset 0x00000638UL
+struct QIB_7322_MemUnCorErrClear_pb {
+ pseudo_bit_t UncErrClearRcvBuf_0[1];
+ pseudo_bit_t UncErrClearRcvFlags_0[1];
+ pseudo_bit_t UncErrClearLookupiqBuf_0[1];
+ pseudo_bit_t UncErrClearRcvDMAHdrBuf_0[1];
+ pseudo_bit_t UncErrClearRcvDMADataBuf_0[1];
+ pseudo_bit_t UncErrClearRcvBuf_1[1];
+ pseudo_bit_t UncErrClearRcvFlags_1[1];
+ pseudo_bit_t UncErrClearLookupiqBuf_1[1];
+ pseudo_bit_t UncErrClearRcvDMAHdrBuf_1[1];
+ pseudo_bit_t UncErrClearRcvDMADataBuf_1[1];
+ pseudo_bit_t UncErrClearRcvTIDArray[1];
+ pseudo_bit_t UncErrClearRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t UncErrClearSendBufVL15[1];
+ pseudo_bit_t UncErrClearSendBufMain[1];
+ pseudo_bit_t UncErrClearSendBufExtra[1];
+ pseudo_bit_t UncErrClearSendPbcArray[1];
+ pseudo_bit_t UncErrClearSendLaFIFO0_0[1];
+ pseudo_bit_t UncErrClearSendLaFIFO1_0[1];
+ pseudo_bit_t UncErrClearSendLaFIFO2_0[1];
+ pseudo_bit_t UncErrClearSendLaFIFO3_0[1];
+ pseudo_bit_t UncErrClearSendLaFIFO4_0[1];
+ pseudo_bit_t UncErrClearSendLaFIFO5_0[1];
+ pseudo_bit_t UncErrClearSendLaFIFO6_0[1];
+ pseudo_bit_t UncErrClearSendLaFIFO7_0[1];
+ pseudo_bit_t UncErrClearSendLaFIFO0_1[1];
+ pseudo_bit_t UncErrClearSendLaFIFO1_1[1];
+ pseudo_bit_t UncErrClearSendLaFIFO2_1[1];
+ pseudo_bit_t UncErrClearSendLaFIFO3_1[1];
+ pseudo_bit_t UncErrClearSendLaFIFO4_1[1];
+ pseudo_bit_t UncErrClearSendLaFIFO5_1[1];
+ pseudo_bit_t UncErrClearSendLaFIFO6_1[1];
+ pseudo_bit_t UncErrClearSendLaFIFO7_1[1];
+ pseudo_bit_t UncErrClearSendRmFIFO_0[1];
+ pseudo_bit_t UncErrClearSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t UncErrClearPCIeRetryBuf[1];
+ pseudo_bit_t UncErrClearPCIePostHdrBuf[1];
+ pseudo_bit_t UncErrClearPCIePostDataBuf[1];
+ pseudo_bit_t UncErrClearPCIeCompHdrBuf[1];
+ pseudo_bit_t UncErrClearPCIeCompDataBuf[1];
+ pseudo_bit_t UncErrClearMsixTable0[1];
+ pseudo_bit_t UncErrClearMsixTable1[1];
+ pseudo_bit_t UncErrClearMsixTable2[1];
+ pseudo_bit_t _unused_2[8];
+};
+struct QIB_7322_MemUnCorErrClear {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemUnCorErrClear_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemMultiCorErrMask_offset 0x00000640UL
+struct QIB_7322_MemMultiCorErrMask_pb {
+ pseudo_bit_t MulCorErrMskRcvBuf_0[1];
+ pseudo_bit_t MulCorErrMskRcvFlags_0[1];
+ pseudo_bit_t MulCorErrMskLookupiqBuf_0[1];
+ pseudo_bit_t MulCorErrMskRcvDMAHdrBuf_0[1];
+ pseudo_bit_t MulCorErrMskRcvDMADataBuf_0[1];
+ pseudo_bit_t MulCorErrMskRcvBuf_1[1];
+ pseudo_bit_t MulCorErrMskRcvFlags_1[1];
+ pseudo_bit_t MulCorErrMskLookupiqBuf_1[1];
+ pseudo_bit_t MulCorErrMskRcvDMAHdrBuf_1[1];
+ pseudo_bit_t MulCorErrMskRcvDMADataBuf_1[1];
+ pseudo_bit_t MulCorErrMskRcvTIDArray[1];
+ pseudo_bit_t MulCorErrMskRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t MulCorErrMskSendBufVL15[1];
+ pseudo_bit_t MulCorErrMskSendBufMain[1];
+ pseudo_bit_t MulCorErrMskSendBufExtra[1];
+ pseudo_bit_t MulCorErrMskSendPbcArray[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO0_0[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO1_0[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO2_0[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO3_0[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO4_0[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO5_0[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO6_0[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO7_0[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO0_1[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO1_1[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO2_1[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO3_1[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO4_1[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO5_1[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO6_1[1];
+ pseudo_bit_t MulCorErrMskSendLaFIFO7_1[1];
+ pseudo_bit_t MulCorErrMskSendRmFIFO_0[1];
+ pseudo_bit_t MulCorErrMskSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t MulCorErrMskPCIeRetryBuf[1];
+ pseudo_bit_t MulCorErrMskPCIePostHdrBuf[1];
+ pseudo_bit_t MulCorErrMskPCIePostDataBuf[1];
+ pseudo_bit_t MulCorErrMskPCIeCompHdrBuf[1];
+ pseudo_bit_t MulCorErrMskPCIeCompDataBuf[1];
+ pseudo_bit_t MulCorErrMskMsixTable0[1];
+ pseudo_bit_t MulCorErrMskMsixTable1[1];
+ pseudo_bit_t MulCorErrMskMsixTable2[1];
+ pseudo_bit_t _unused_2[8];
+};
+struct QIB_7322_MemMultiCorErrMask {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemMultiCorErrMask_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemMultiCorErrStatus_offset 0x00000648UL
+struct QIB_7322_MemMultiCorErrStatus_pb {
+ pseudo_bit_t MulCorErrStatusRcvBuf_0[1];
+ pseudo_bit_t MulCorErrStatusRcvFlags_0[1];
+ pseudo_bit_t MulCorErrStatusLookupiqBuf_0[1];
+ pseudo_bit_t MulCorErrStatusRcvDMAHdrBuf_0[1];
+ pseudo_bit_t MulCorErrStatusRcvDMADataBuf_0[1];
+ pseudo_bit_t MulCorErrStatusRcvBuf_1[1];
+ pseudo_bit_t MulCorErrStatusRcvFlags_1[1];
+ pseudo_bit_t MulCorErrStatusLookupiqBuf_1[1];
+ pseudo_bit_t MulCorErrStatusRcvDMAHdrBuf_1[1];
+ pseudo_bit_t MulCorErrStatusRcvDMADataBuf_1[1];
+ pseudo_bit_t MulCorErrStatusRcvTIDArray[1];
+ pseudo_bit_t MulCorErrStatusRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t MulCorErrStatusSendBufVL15[1];
+ pseudo_bit_t MulCorErrStatusSendBufMain[1];
+ pseudo_bit_t MulCorErrStatusSendBufExtra[1];
+ pseudo_bit_t MulCorErrStatusSendPbcArray[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO0_0[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO1_0[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO2_0[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO3_0[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO4_0[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO5_0[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO6_0[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO7_0[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO0_1[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO1_1[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO2_1[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO3_1[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO4_1[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO5_1[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO6_1[1];
+ pseudo_bit_t MulCorErrStatusSendLaFIFO7_1[1];
+ pseudo_bit_t MulCorErrStatusSendRmFIFO_0[1];
+ pseudo_bit_t MulCorErrStatusSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t MulCorErrStatusPCIeRetryBuf[1];
+ pseudo_bit_t MulCorErrStatusPCIePostHdrBuf[1];
+ pseudo_bit_t MulCorErrStatusPCIePostDataBuf[1];
+ pseudo_bit_t MulCorErrStatusPCIeCompHdrBuf[1];
+ pseudo_bit_t MulCorErrStatusPCIeCompDataBuf[1];
+ pseudo_bit_t MulCorErrStatusMsixTable0[1];
+ pseudo_bit_t MulCorErrStatusMsixTable1[1];
+ pseudo_bit_t MulCorErrStatusMsixTable2[1];
+ pseudo_bit_t _unused_2[8];
+};
+struct QIB_7322_MemMultiCorErrStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemMultiCorErrStatus_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemMultiCorErrClear_offset 0x00000650UL
+struct QIB_7322_MemMultiCorErrClear_pb {
+ pseudo_bit_t MulCorErrClearRcvBuf_0[1];
+ pseudo_bit_t MulCorErrClearRcvFlags_0[1];
+ pseudo_bit_t MulCorErrClearLookupiqBuf_0[1];
+ pseudo_bit_t MulCorErrClearRcvDMAHdrBuf_0[1];
+ pseudo_bit_t MulCorErrClearRcvDMADataBuf_0[1];
+ pseudo_bit_t MulCorErrClearRcvBuf_1[1];
+ pseudo_bit_t MulCorErrClearRcvFlags_1[1];
+ pseudo_bit_t MulCorErrClearLookupiqBuf_1[1];
+ pseudo_bit_t MulCorErrClearRcvDMAHdrBuf_1[1];
+ pseudo_bit_t MulCorErrClearRcvDMADataBuf_1[1];
+ pseudo_bit_t MulCorErrClearRcvTIDArray[1];
+ pseudo_bit_t MulCorErrClearRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t MulCorErrClearSendBufVL15[1];
+ pseudo_bit_t MulCorErrClearSendBufMain[1];
+ pseudo_bit_t MulCorErrClearSendBufExtra[1];
+ pseudo_bit_t MulCorErrClearSendPbcArray[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO0_0[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO1_0[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO2_0[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO3_0[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO4_0[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO5_0[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO6_0[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO7_0[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO0_1[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO1_1[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO2_1[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO3_1[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO4_1[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO5_1[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO6_1[1];
+ pseudo_bit_t MulCorErrClearSendLaFIFO7_1[1];
+ pseudo_bit_t MulCorErrClearSendRmFIFO_0[1];
+ pseudo_bit_t MulCorErrClearSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t MulCorErrClearPCIeRetryBuf[1];
+ pseudo_bit_t MulCorErrClearPCIePostHdrBuf[1];
+ pseudo_bit_t MulCorErrClearPCIePostDataBuf[1];
+ pseudo_bit_t MulCorErrClearPCIeCompHdrBuf[1];
+ pseudo_bit_t MulCorErrClearPCIeCompDataBuf[1];
+ pseudo_bit_t MulCorErrClearMsixTable0[1];
+ pseudo_bit_t MulCorErrClearMsixTable1[1];
+ pseudo_bit_t MulCorErrClearMsixTable2[1];
+ pseudo_bit_t _unused_2[8];
+};
+struct QIB_7322_MemMultiCorErrClear {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemMultiCorErrClear_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemCorErrMask_offset 0x00000658UL
+struct QIB_7322_MemCorErrMask_pb {
+ pseudo_bit_t CorErrMskRcvBuf_0[1];
+ pseudo_bit_t CorErrMskRcvFlags_0[1];
+ pseudo_bit_t CorErrMskLookupiqBuf_0[1];
+ pseudo_bit_t CorErrMskRcvDMAHdrBuf_0[1];
+ pseudo_bit_t CorErrMskRcvDMADataBuf_0[1];
+ pseudo_bit_t CorErrMskRcvBuf_1[1];
+ pseudo_bit_t CorErrMskRcvFlags_1[1];
+ pseudo_bit_t CorErrMskLookupiqBuf_1[1];
+ pseudo_bit_t CorErrMskRcvDMAHdrBuf_1[1];
+ pseudo_bit_t CorErrMskRcvDMADataBuf_1[1];
+ pseudo_bit_t CorErrMskRcvTIDArray[1];
+ pseudo_bit_t CorErrMskRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t CorErrMskSendBufVL15[1];
+ pseudo_bit_t CorErrMskSendBufMain[1];
+ pseudo_bit_t CorErrMskSendBufExtra[1];
+ pseudo_bit_t CorErrMskSendPbcArray[1];
+ pseudo_bit_t CorErrMskSendLaFIFO0_0[1];
+ pseudo_bit_t CorErrMskSendLaFIFO1_0[1];
+ pseudo_bit_t CorErrMskSendLaFIFO2_0[1];
+ pseudo_bit_t CorErrMskSendLaFIFO3_0[1];
+ pseudo_bit_t CorErrMskSendLaFIFO4_0[1];
+ pseudo_bit_t CorErrMskSendLaFIFO5_0[1];
+ pseudo_bit_t CorErrMskSendLaFIFO6_0[1];
+ pseudo_bit_t CorErrMskSendLaFIFO7_0[1];
+ pseudo_bit_t CorErrMskSendLaFIFO0_1[1];
+ pseudo_bit_t CorErrMskSendLaFIFO1_1[1];
+ pseudo_bit_t CorErrMskSendLaFIFO2_1[1];
+ pseudo_bit_t CorErrMskSendLaFIFO3_1[1];
+ pseudo_bit_t CorErrMskSendLaFIFO4_1[1];
+ pseudo_bit_t CorErrMskSendLaFIFO5_1[1];
+ pseudo_bit_t CorErrMskSendLaFIFO6_1[1];
+ pseudo_bit_t CorErrMskSendLaFIFO7_1[1];
+ pseudo_bit_t CorErrMskSendRmFIFO_0[1];
+ pseudo_bit_t CorErrMskSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t CorErrMskPCIeRetryBuf[1];
+ pseudo_bit_t CorErrMskPCIePostHdrBuf[1];
+ pseudo_bit_t CorErrMskPCIePostDataBuf[1];
+ pseudo_bit_t CorErrMskPCIeCompHdrBuf[1];
+ pseudo_bit_t CorErrMskPCIeCompDataBuf[1];
+ pseudo_bit_t CorErrMskMsixTable0[1];
+ pseudo_bit_t CorErrMskMsixTable1[1];
+ pseudo_bit_t CorErrMskMsixTable2[1];
+ pseudo_bit_t _unused_2[8];
+};
+struct QIB_7322_MemCorErrMask {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemCorErrMask_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemCorErrStatus_offset 0x00000660UL
+struct QIB_7322_MemCorErrStatus_pb {
+ pseudo_bit_t CorErrStatusRcvBuf_0[1];
+ pseudo_bit_t CorErrStatusRcvFlags_0[1];
+ pseudo_bit_t CorErrStatusLookupiqBuf_0[1];
+ pseudo_bit_t CorErrStatusRcvDMAHdrBuf_0[1];
+ pseudo_bit_t CorErrStatusRcvDMADataBuf_0[1];
+ pseudo_bit_t CorErrStatusRcvBuf_1[1];
+ pseudo_bit_t CorErrStatusRcvFlags_1[1];
+ pseudo_bit_t CorErrStatusLookupiqBuf_1[1];
+ pseudo_bit_t CorErrStatusRcvDMAHdrBuf_1[1];
+ pseudo_bit_t CorErrStatusRcvDMADataBuf_1[1];
+ pseudo_bit_t CorErrStatusRcvTIDArray[1];
+ pseudo_bit_t CorErrStatusRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t CorErrStatusSendBufVL15[1];
+ pseudo_bit_t CorErrStatusSendBufMain[1];
+ pseudo_bit_t CorErrStatusSendBufExtra[1];
+ pseudo_bit_t CorErrStatusSendPbcArray[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO0_0[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO1_0[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO2_0[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO3_0[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO4_0[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO5_0[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO6_0[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO7_0[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO0_1[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO1_1[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO2_1[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO3_1[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO4_1[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO5_1[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO6_1[1];
+ pseudo_bit_t CorErrStatusSendLaFIFO7_1[1];
+ pseudo_bit_t CorErrStatusSendRmFIFO_0[1];
+ pseudo_bit_t CorErrStatusSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t CorErrStatusPCIeRetryBuf[1];
+ pseudo_bit_t CorErrStatusPCIePostHdrBuf[1];
+ pseudo_bit_t CorErrStatusPCIePostDataBuf[1];
+ pseudo_bit_t CorErrStatusPCIeCompHdrBuf[1];
+ pseudo_bit_t CorErrStatusPCIeCompDataBuf[1];
+ pseudo_bit_t CorErrStatusMsixTable0[1];
+ pseudo_bit_t CorErrStatusMsixTable1[1];
+ pseudo_bit_t CorErrStatusMsixTable2[1];
+ pseudo_bit_t _unused_2[8];
+};
+struct QIB_7322_MemCorErrStatus {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemCorErrStatus_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MemCorErrClear_offset 0x00000668UL
+struct QIB_7322_MemCorErrClear_pb {
+ pseudo_bit_t CorErrClearRcvBuf_0[1];
+ pseudo_bit_t CorErrClearRcvFlags_0[1];
+ pseudo_bit_t CorErrClearLookupiqBuf_0[1];
+ pseudo_bit_t CorErrClearRcvDMAHdrBuf_0[1];
+ pseudo_bit_t CorErrClearRcvDMADataBuf_0[1];
+ pseudo_bit_t CorErrClearRcvBuf_1[1];
+ pseudo_bit_t CorErrClearRcvFlags_1[1];
+ pseudo_bit_t CorErrClearLookupiqBuf_1[1];
+ pseudo_bit_t CorErrClearRcvDMAHdrBuf_1[1];
+ pseudo_bit_t CorErrClearRcvDMADataBuf_1[1];
+ pseudo_bit_t CorErrClearRcvTIDArray[1];
+ pseudo_bit_t CorErrClearRcvEgrArray[1];
+ pseudo_bit_t _unused_0[3];
+ pseudo_bit_t CorErrClearSendBufVL15[1];
+ pseudo_bit_t CorErrClearSendBufMain[1];
+ pseudo_bit_t CorErrClearSendBufExtra[1];
+ pseudo_bit_t CorErrClearSendPbcArray[1];
+ pseudo_bit_t CorErrClearSendLaFIFO0_0[1];
+ pseudo_bit_t CorErrClearSendLaFIFO1_0[1];
+ pseudo_bit_t CorErrClearSendLaFIFO2_0[1];
+ pseudo_bit_t CorErrClearSendLaFIFO3_0[1];
+ pseudo_bit_t CorErrClearSendLaFIFO4_0[1];
+ pseudo_bit_t CorErrClearSendLaFIFO5_0[1];
+ pseudo_bit_t CorErrClearSendLaFIFO6_0[1];
+ pseudo_bit_t CorErrClearSendLaFIFO7_0[1];
+ pseudo_bit_t CorErrClearSendLaFIFO0_1[1];
+ pseudo_bit_t CorErrClearSendLaFIFO1_1[1];
+ pseudo_bit_t CorErrClearSendLaFIFO2_1[1];
+ pseudo_bit_t CorErrClearSendLaFIFO3_1[1];
+ pseudo_bit_t CorErrClearSendLaFIFO4_1[1];
+ pseudo_bit_t CorErrClearSendLaFIFO5_1[1];
+ pseudo_bit_t CorErrClearSendLaFIFO6_1[1];
+ pseudo_bit_t CorErrClearSendLaFIFO7_1[1];
+ pseudo_bit_t CorErrClearSendRmFIFO_0[1];
+ pseudo_bit_t CorErrClearSendRmFIFO_1[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t CorErrClearPCIeRetryBuf[1];
+ pseudo_bit_t CorErrClearPCIePostHdrBuf[1];
+ pseudo_bit_t CorErrClearPCIePostDataBuf[1];
+ pseudo_bit_t CorErrClearPCIeCompHdrBuf[1];
+ pseudo_bit_t CorErrClearPCIeCompDataBuf[1];
+ pseudo_bit_t CorErrClearMsixTable0[1];
+ pseudo_bit_t CorErrClearMsixTable1[1];
+ pseudo_bit_t CorErrClearMsixTable2[1];
+ pseudo_bit_t _unused_2[8];
+};
+struct QIB_7322_MemCorErrClear {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MemCorErrClear_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MsixTableUnCorErrLogA_offset 0x00000680UL
+struct QIB_7322_MsixTableUnCorErrLogA_pb {
+ pseudo_bit_t MsixTable_1_0_UnCorErrData[64];
+};
+struct QIB_7322_MsixTableUnCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MsixTableUnCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MsixTableUnCorErrLogB_offset 0x00000688UL
+struct QIB_7322_MsixTableUnCorErrLogB_pb {
+ pseudo_bit_t MsixTable_2_UnCorErrData[32];
+ pseudo_bit_t MsixTable_0_UnCorErrCheckBits[7];
+ pseudo_bit_t MsixTable_1_UnCorErrCheckBits[7];
+ pseudo_bit_t MsixTable_2_UnCorErrCheckBits[7];
+ pseudo_bit_t _unused_0[11];
+};
+struct QIB_7322_MsixTableUnCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MsixTableUnCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MsixTableUnCorErrLogC_offset 0x00000690UL
+struct QIB_7322_MsixTableUnCorErrLogC_pb {
+ pseudo_bit_t MsixTable_0_UnCorErrAddr[7];
+ pseudo_bit_t MsixTable_1_UnCorErrAddr[7];
+ pseudo_bit_t MsixTable_2_UnCorErrAddr[7];
+ pseudo_bit_t _unused_0[43];
+};
+struct QIB_7322_MsixTableUnCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MsixTableUnCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MsixEntryWithUncorErr_offset 0x00000698UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MsixTableCorErrLogA_offset 0x000006a0UL
+struct QIB_7322_MsixTableCorErrLogA_pb {
+ pseudo_bit_t MsixTable_1_0_CorErrData[64];
+};
+struct QIB_7322_MsixTableCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MsixTableCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MsixTableCorErrLogB_offset 0x000006a8UL
+struct QIB_7322_MsixTableCorErrLogB_pb {
+ pseudo_bit_t MsixTable_2_CorErrData[32];
+ pseudo_bit_t MsixTable_0_CorErrCheckBits[7];
+ pseudo_bit_t MsixTable_1_CorErrCheckBits[7];
+ pseudo_bit_t MsixTable_2_CorErrCheckBits[7];
+ pseudo_bit_t _unused_0[11];
+};
+struct QIB_7322_MsixTableCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MsixTableCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MsixTableCorErrLogC_offset 0x000006b0UL
+struct QIB_7322_MsixTableCorErrLogC_pb {
+ pseudo_bit_t MsixTable_0_CorErrAddr[7];
+ pseudo_bit_t MsixTable_1_CorErrAddr[7];
+ pseudo_bit_t MsixTable_2_CorErrAddr[7];
+ pseudo_bit_t _unused_0[43];
+};
+struct QIB_7322_MsixTableCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_MsixTableCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieCplDataBufrUnCorErrLogA_offset 0x00000700UL
+struct QIB_7322_PcieCplDataBufrUnCorErrLogA_pb {
+ pseudo_bit_t PcieCplDataBufrUnCorErrData_63_0[64];
+};
+struct QIB_7322_PcieCplDataBufrUnCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieCplDataBufrUnCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieCplDataBufrUnCorErrLogB_offset 0x00000708UL
+struct QIB_7322_PcieCplDataBufrUnCorErrLogB_pb {
+ pseudo_bit_t PcieCplDataBufrUnCorErrData_127_64[64];
+};
+struct QIB_7322_PcieCplDataBufrUnCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieCplDataBufrUnCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieCplDataBufrUnCorErrLogC_offset 0x00000710UL
+struct QIB_7322_PcieCplDataBufrUnCorErrLogC_pb {
+ pseudo_bit_t PcieCplDataBufrUnCorErrData_136_128[9];
+ pseudo_bit_t PcieCplDataBufrUnCorErrCheckBit_21_0[22];
+ pseudo_bit_t PcieCplDataBufrUnCorErrAddr_13_0[14];
+ pseudo_bit_t _unused_0[19];
+};
+struct QIB_7322_PcieCplDataBufrUnCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieCplDataBufrUnCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieCplHdrBufrUnCorErrLogA_offset 0x00000720UL
+struct QIB_7322_PcieCplHdrBufrUnCorErrLogA_pb {
+ pseudo_bit_t PcieCplHdrBufrUnCorErrHdr_63_0[64];
+};
+struct QIB_7322_PcieCplHdrBufrUnCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieCplHdrBufrUnCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieCplHdrBufrUnCorErrLogB_offset 0x00000728UL
+struct QIB_7322_PcieCplHdrBufrUnCorErrLogB_pb {
+ pseudo_bit_t PcieCplHdrBufrUnCorErrHdr_103_64[40];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_PcieCplHdrBufrUnCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieCplHdrBufrUnCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieCplHdrBufrUnCorErrLogC_offset 0x00000730UL
+struct QIB_7322_PcieCplHdrBufrUnCorErrLogC_pb {
+ pseudo_bit_t PcieCplHdrBufrUnCorErrCheckBit_15_0[16];
+ pseudo_bit_t PcieCplHdrBufrUnCorErrAddr_8_0[9];
+ pseudo_bit_t _unused_0[39];
+};
+struct QIB_7322_PcieCplHdrBufrUnCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieCplHdrBufrUnCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PciePDataBufrUnCorErrLogA_offset 0x00000740UL
+struct QIB_7322_PciePDataBufrUnCorErrLogA_pb {
+ pseudo_bit_t PciePDataBufrUnCorErrData_63_0[64];
+};
+struct QIB_7322_PciePDataBufrUnCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PciePDataBufrUnCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PciePDataBufrUnCorErrLogB_offset 0x00000748UL
+struct QIB_7322_PciePDataBufrUnCorErrLogB_pb {
+ pseudo_bit_t PciePDataBufrUnCorErrData_127_64[64];
+};
+struct QIB_7322_PciePDataBufrUnCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PciePDataBufrUnCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PciePDataBufrUnCorErrLogC_offset 0x00000750UL
+struct QIB_7322_PciePDataBufrUnCorErrLogC_pb {
+ pseudo_bit_t PciePDataBufrUnCorErrData_136_128[9];
+ pseudo_bit_t PciePDataBufrUnCorErrCheckBit_21_0[22];
+ pseudo_bit_t PciePDataBufrUnCorErrAddr_13_0[14];
+ pseudo_bit_t _unused_0[19];
+};
+struct QIB_7322_PciePDataBufrUnCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PciePDataBufrUnCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PciePHdrBufrUnCorErrLogA_offset 0x00000760UL
+struct QIB_7322_PciePHdrBufrUnCorErrLogA_pb {
+ pseudo_bit_t PciePHdrBufrUnCorErrData_63_0[64];
+};
+struct QIB_7322_PciePHdrBufrUnCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PciePHdrBufrUnCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PciePHdrBufrUnCorErrLogB_offset 0x00000768UL
+struct QIB_7322_PciePHdrBufrUnCorErrLogB_pb {
+ pseudo_bit_t PciePHdrBufrUnCorErrData_107_64[44];
+ pseudo_bit_t _unused_0[20];
+};
+struct QIB_7322_PciePHdrBufrUnCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PciePHdrBufrUnCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PciePHdrBufrUnCorErrLogC_offset 0x00000770UL
+struct QIB_7322_PciePHdrBufrUnCorErrLogC_pb {
+ pseudo_bit_t PciePHdrBufrUnCorErrCheckBit_15_0[16];
+ pseudo_bit_t PciePHdrBufrUnCorErrAddr_8_0[9];
+ pseudo_bit_t _unused_0[39];
+};
+struct QIB_7322_PciePHdrBufrUnCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PciePHdrBufrUnCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieRetryBufrUnCorErrLogA_offset 0x00000780UL
+struct QIB_7322_PcieRetryBufrUnCorErrLogA_pb {
+ pseudo_bit_t PcieRetryBufrUnCorErrData_63_0[64];
+};
+struct QIB_7322_PcieRetryBufrUnCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieRetryBufrUnCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieRetryBufrUnCorErrLogB_offset 0x00000788UL
+struct QIB_7322_PcieRetryBufrUnCorErrLogB_pb {
+ pseudo_bit_t PcieRetryBufrUnCorErrData_127_64[64];
+};
+struct QIB_7322_PcieRetryBufrUnCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieRetryBufrUnCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieRetryBufrUnCorErrLogC_offset 0x00000790UL
+struct QIB_7322_PcieRetryBufrUnCorErrLogC_pb {
+ pseudo_bit_t PcieRetryBufrUnCorErrData_133_128[6];
+ pseudo_bit_t PcieRetryBufrUnCorErrCheckBit_20_0[21];
+ pseudo_bit_t PcieRetryBufrUnCorErrAddr_13_0[14];
+ pseudo_bit_t _unused_0[23];
+};
+struct QIB_7322_PcieRetryBufrUnCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieRetryBufrUnCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxTIDArrayUnCorErrLogA_offset 0x00000800UL
+struct QIB_7322_RxTIDArrayUnCorErrLogA_pb {
+ pseudo_bit_t RxTIDArrayUnCorErrData_39_0[40];
+ pseudo_bit_t RxTIDArrayUnCorErrCheckBit_11_0[12];
+ pseudo_bit_t _unused_0[12];
+};
+struct QIB_7322_RxTIDArrayUnCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxTIDArrayUnCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxTIDArrayUnCorErrLogB_offset 0x00000808UL
+struct QIB_7322_RxTIDArrayUnCorErrLogB_pb {
+ pseudo_bit_t RxTIDArrayUnCorErrAddr_16_0[17];
+ pseudo_bit_t _unused_0[47];
+};
+struct QIB_7322_RxTIDArrayUnCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxTIDArrayUnCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxEagerArrayUnCorErrLogA_offset 0x00000810UL
+struct QIB_7322_RxEagerArrayUnCorErrLogA_pb {
+ pseudo_bit_t RxEagerArrayUnCorErrData_39_0[40];
+ pseudo_bit_t RxEagerArrayUnCorErrCheckBit_11_0[12];
+ pseudo_bit_t _unused_0[12];
+};
+struct QIB_7322_RxEagerArrayUnCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxEagerArrayUnCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxEagerArrayUnCorErrLogB_offset 0x00000818UL
+struct QIB_7322_RxEagerArrayUnCorErrLogB_pb {
+ pseudo_bit_t RxEagerArrayUnCorErrAddr_17_0[18];
+ pseudo_bit_t _unused_0[46];
+};
+struct QIB_7322_RxEagerArrayUnCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxEagerArrayUnCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufMainArrayUnCorErrLogA_offset 0x00000880UL
+struct QIB_7322_SBufMainArrayUnCorErrLogA_pb {
+ pseudo_bit_t SBufMainArrayUnCorErrData_63_0[64];
+};
+struct QIB_7322_SBufMainArrayUnCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufMainArrayUnCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufMainArrayUnCorErrLogB_offset 0x00000888UL
+struct QIB_7322_SBufMainArrayUnCorErrLogB_pb {
+ pseudo_bit_t SBufMainArrayUnCorErrData_127_64[64];
+};
+struct QIB_7322_SBufMainArrayUnCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufMainArrayUnCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufMainArrayUnCorErrLogC_offset 0x00000890UL
+struct QIB_7322_SBufMainArrayUnCorErrLogC_pb {
+ pseudo_bit_t SBufMainArrayUnCorErrCheckBit_27_0[28];
+ pseudo_bit_t SBufMainArrayUnCorErrAddr_18_0[19];
+ pseudo_bit_t _unused_0[13];
+ pseudo_bit_t SBufMainArrayUnCorErrDword_3_0[4];
+};
+struct QIB_7322_SBufMainArrayUnCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufMainArrayUnCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufExtraArrayUnCorErrLogA_offset 0x00000898UL
+struct QIB_7322_SBufExtraArrayUnCorErrLogA_pb {
+ pseudo_bit_t SBufExtraArrayUnCorErrData_63_0[64];
+};
+struct QIB_7322_SBufExtraArrayUnCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufExtraArrayUnCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufExtraArrayUnCorErrLogB_offset 0x000008a0UL
+struct QIB_7322_SBufExtraArrayUnCorErrLogB_pb {
+ pseudo_bit_t SBufExtraArrayUnCorErrData_127_64[64];
+};
+struct QIB_7322_SBufExtraArrayUnCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufExtraArrayUnCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufExtraArrayUnCorErrLogC_offset 0x000008a8UL
+struct QIB_7322_SBufExtraArrayUnCorErrLogC_pb {
+ pseudo_bit_t SBufExtraArrayUnCorErrCheckBit_27_0[28];
+ pseudo_bit_t SBufExtraArrayUnCorErrAddr_14_0[15];
+ pseudo_bit_t _unused_0[17];
+ pseudo_bit_t SBufExtraArrayUnCorErrAdd_3_0[4];
+};
+struct QIB_7322_SBufExtraArrayUnCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufExtraArrayUnCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendPbcArrayUnCorErrLog_offset 0x000008b0UL
+struct QIB_7322_SendPbcArrayUnCorErrLog_pb {
+ pseudo_bit_t SendPbcArrayUnCorErrData_21_0[22];
+ pseudo_bit_t SendPbcArrayUnCorErrCheckBit_6_0[7];
+ pseudo_bit_t SendPbcArrayUnCorErrAddr_9_0[10];
+ pseudo_bit_t _unused_0[25];
+};
+struct QIB_7322_SendPbcArrayUnCorErrLog {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendPbcArrayUnCorErrLog_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufVL15ArrayUnCorErrLogA_offset 0x000008c0UL
+struct QIB_7322_SBufVL15ArrayUnCorErrLogA_pb {
+ pseudo_bit_t SBufVL15ArrayUnCorErrData_63_0[64];
+};
+struct QIB_7322_SBufVL15ArrayUnCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufVL15ArrayUnCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieCplDataBufrCorErrLogA_offset 0x00000900UL
+struct QIB_7322_PcieCplDataBufrCorErrLogA_pb {
+ pseudo_bit_t PcieCplDataBufrCorErrData_63_0[64];
+};
+struct QIB_7322_PcieCplDataBufrCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieCplDataBufrCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieCplDataBufrCorErrLogB_offset 0x00000908UL
+struct QIB_7322_PcieCplDataBufrCorErrLogB_pb {
+ pseudo_bit_t PcieCplDataBufrCorErrData_127_64[64];
+};
+struct QIB_7322_PcieCplDataBufrCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieCplDataBufrCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieCplDataBufrCorErrLogC_offset 0x00000910UL
+struct QIB_7322_PcieCplDataBufrCorErrLogC_pb {
+ pseudo_bit_t PcieCplDataBufrCorErrData_136_128[9];
+ pseudo_bit_t PcieCplDataBufrCorErrCheckBit_21_0[22];
+ pseudo_bit_t PcieCplDataBufrCorErrAddr_13_0[14];
+ pseudo_bit_t _unused_0[19];
+};
+struct QIB_7322_PcieCplDataBufrCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieCplDataBufrCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieCplHdrBufrCorErrLogA_offset 0x00000920UL
+struct QIB_7322_PcieCplHdrBufrCorErrLogA_pb {
+ pseudo_bit_t PcieCplHdrBufrCorErrHdr_63_0[64];
+};
+struct QIB_7322_PcieCplHdrBufrCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieCplHdrBufrCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieCplHdrBufrCorErrLogB_offset 0x00000928UL
+struct QIB_7322_PcieCplHdrBufrCorErrLogB_pb {
+ pseudo_bit_t PcieCplHdrBufrCorErrHdr_103_64[40];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_PcieCplHdrBufrCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieCplHdrBufrCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieCplHdrBufrCorErrLogC_offset 0x00000930UL
+struct QIB_7322_PcieCplHdrBufrCorErrLogC_pb {
+ pseudo_bit_t PcieCplHdrBufrCorErrCheckBit_15_0[16];
+ pseudo_bit_t PcieCplHdrBufrCorErrAddr_8_0[9];
+ pseudo_bit_t _unused_0[39];
+};
+struct QIB_7322_PcieCplHdrBufrCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieCplHdrBufrCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PciePDataBufrCorErrLogA_offset 0x00000940UL
+struct QIB_7322_PciePDataBufrCorErrLogA_pb {
+ pseudo_bit_t PciePDataBufrCorErrData_63_0[64];
+};
+struct QIB_7322_PciePDataBufrCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PciePDataBufrCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PciePDataBufrCorErrLogB_offset 0x00000948UL
+struct QIB_7322_PciePDataBufrCorErrLogB_pb {
+ pseudo_bit_t PciePDataBufrCorErrData_127_64[64];
+};
+struct QIB_7322_PciePDataBufrCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PciePDataBufrCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PciePDataBufrCorErrLogC_offset 0x00000950UL
+struct QIB_7322_PciePDataBufrCorErrLogC_pb {
+ pseudo_bit_t PciePDataBufrCorErrData_136_128[9];
+ pseudo_bit_t PciePDataBufrCorErrCheckBit_21_0[22];
+ pseudo_bit_t PciePDataBufrCorErrAddr_13_0[14];
+ pseudo_bit_t _unused_0[19];
+};
+struct QIB_7322_PciePDataBufrCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PciePDataBufrCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PciePHdrBufrCorErrLogA_offset 0x00000960UL
+struct QIB_7322_PciePHdrBufrCorErrLogA_pb {
+ pseudo_bit_t PciePHdrBufrCorErrData_63_0[64];
+};
+struct QIB_7322_PciePHdrBufrCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PciePHdrBufrCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PciePHdrBufrCorErrLogB_offset 0x00000968UL
+struct QIB_7322_PciePHdrBufrCorErrLogB_pb {
+ pseudo_bit_t PciePHdrBufrCorErrData_107_64[44];
+ pseudo_bit_t _unused_0[20];
+};
+struct QIB_7322_PciePHdrBufrCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PciePHdrBufrCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PciePHdrBufrCorErrLogC_offset 0x00000970UL
+struct QIB_7322_PciePHdrBufrCorErrLogC_pb {
+ pseudo_bit_t PciePHdrBufrCorErrCheckBit_15_0[16];
+ pseudo_bit_t PciePHdrBufrCorErrAddr_8_0[9];
+ pseudo_bit_t _unused_0[39];
+};
+struct QIB_7322_PciePHdrBufrCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PciePHdrBufrCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieRetryBufrCorErrLogA_offset 0x00000980UL
+struct QIB_7322_PcieRetryBufrCorErrLogA_pb {
+ pseudo_bit_t PcieRetryBufrCorErrData_63_0[64];
+};
+struct QIB_7322_PcieRetryBufrCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieRetryBufrCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieRetryBufrCorErrLogB_offset 0x00000988UL
+struct QIB_7322_PcieRetryBufrCorErrLogB_pb {
+ pseudo_bit_t PcieRetryBufrCorErrData_127_64[64];
+};
+struct QIB_7322_PcieRetryBufrCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieRetryBufrCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieRetryBufrCorErrLogC_offset 0x00000990UL
+struct QIB_7322_PcieRetryBufrCorErrLogC_pb {
+ pseudo_bit_t PcieRetryBufrCorErrData_133_128[6];
+ pseudo_bit_t PcieRetryBufrCorErrCheckBit_20_0[21];
+ pseudo_bit_t PcieRetryBufrCorErrAddr_13_0[14];
+ pseudo_bit_t _unused_0[23];
+};
+struct QIB_7322_PcieRetryBufrCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_PcieRetryBufrCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxTIDArrayCorErrLogA_offset 0x00000a00UL
+struct QIB_7322_RxTIDArrayCorErrLogA_pb {
+ pseudo_bit_t RxTIDArrayCorErrData_39_0[40];
+ pseudo_bit_t RxTIDArrayCorErrCheckBit_11_0[12];
+ pseudo_bit_t _unused_0[12];
+};
+struct QIB_7322_RxTIDArrayCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxTIDArrayCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxTIDArrayCorErrLogB_offset 0x00000a08UL
+struct QIB_7322_RxTIDArrayCorErrLogB_pb {
+ pseudo_bit_t RxTIDArrayCorErrAddr_16_0[17];
+ pseudo_bit_t _unused_0[47];
+};
+struct QIB_7322_RxTIDArrayCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxTIDArrayCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxEagerArrayCorErrLogA_offset 0x00000a10UL
+struct QIB_7322_RxEagerArrayCorErrLogA_pb {
+ pseudo_bit_t RxEagerArrayCorErrData_39_0[40];
+ pseudo_bit_t RxEagerArrayCorErrCheckBit_11_0[12];
+ pseudo_bit_t _unused_0[12];
+};
+struct QIB_7322_RxEagerArrayCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxEagerArrayCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxEagerArrayCorErrLogB_offset 0x00000a18UL
+struct QIB_7322_RxEagerArrayCorErrLogB_pb {
+ pseudo_bit_t RxEagerArrayCorErrAddr_17_0[18];
+ pseudo_bit_t _unused_0[46];
+};
+struct QIB_7322_RxEagerArrayCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxEagerArrayCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufMainArrayCorErrLogA_offset 0x00000a80UL
+struct QIB_7322_SBufMainArrayCorErrLogA_pb {
+ pseudo_bit_t SBufMainArrayCorErrData_63_0[64];
+};
+struct QIB_7322_SBufMainArrayCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufMainArrayCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufMainArrayCorErrLogB_offset 0x00000a88UL
+struct QIB_7322_SBufMainArrayCorErrLogB_pb {
+ pseudo_bit_t SBufMainArrayCorErrData_127_64[64];
+};
+struct QIB_7322_SBufMainArrayCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufMainArrayCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufMainArrayCorErrLogC_offset 0x00000a90UL
+struct QIB_7322_SBufMainArrayCorErrLogC_pb {
+ pseudo_bit_t SBufMainArrayCorErrCheckBit_27_0[28];
+ pseudo_bit_t SBufMainArrayCorErrAddr_18_0[19];
+ pseudo_bit_t _unused_0[13];
+ pseudo_bit_t SBufMainArrayCorErrDword_3_0[4];
+};
+struct QIB_7322_SBufMainArrayCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufMainArrayCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufExtraArrayCorErrLogA_offset 0x00000a98UL
+struct QIB_7322_SBufExtraArrayCorErrLogA_pb {
+ pseudo_bit_t SBufExtraArrayCorErrData_63_0[64];
+};
+struct QIB_7322_SBufExtraArrayCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufExtraArrayCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufExtraArrayCorErrLogB_offset 0x00000aa0UL
+struct QIB_7322_SBufExtraArrayCorErrLogB_pb {
+ pseudo_bit_t SBufExtraArrayCorErrData_127_64[64];
+};
+struct QIB_7322_SBufExtraArrayCorErrLogB {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufExtraArrayCorErrLogB_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufExtraArrayCorErrLogC_offset 0x00000aa8UL
+struct QIB_7322_SBufExtraArrayCorErrLogC_pb {
+ pseudo_bit_t SBufExtraArrayCorErrCheckBit_27_0[28];
+ pseudo_bit_t SBufExtraArrayCorErrAddr_14_0[15];
+ pseudo_bit_t _unused_0[17];
+ pseudo_bit_t SBufExtraArrayCorErrAdd_3_0[4];
+};
+struct QIB_7322_SBufExtraArrayCorErrLogC {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufExtraArrayCorErrLogC_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendPbcArrayCorErrLog_offset 0x00000ab0UL
+struct QIB_7322_SendPbcArrayCorErrLog_pb {
+ pseudo_bit_t SendPbcArrayCorErrData_21_0[22];
+ pseudo_bit_t SendPbcArrayCorErrCheckBit_6_0[7];
+ pseudo_bit_t SendPbcArrayCorErrAddr_9_0[10];
+ pseudo_bit_t _unused_0[25];
+};
+struct QIB_7322_SendPbcArrayCorErrLog {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendPbcArrayCorErrLog_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SBufVL15ArrayCorErrLogA_offset 0x00000ac0UL
+struct QIB_7322_SBufVL15ArrayCorErrLogA_pb {
+ pseudo_bit_t SBufVL15ArrayCorErrData_63_0[64];
+};
+struct QIB_7322_SBufVL15ArrayCorErrLogA {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SBufVL15ArrayCorErrLogA_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvAvailTimeOut0_offset 0x00000c00UL
+struct QIB_7322_RcvAvailTimeOut0_pb {
+ pseudo_bit_t RcvAvailTOReload[16];
+ pseudo_bit_t RcvAvailTOCount[16];
+ pseudo_bit_t _unused_0[32];
+};
+struct QIB_7322_RcvAvailTimeOut0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvAvailTimeOut0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_CntrRegBase_0_offset 0x00001028UL
+/* Default value: 0x0000000000012000 */
+
+#define QIB_7322_ErrMask_0_offset 0x00001080UL
+struct QIB_7322_ErrMask_0_pb {
+ pseudo_bit_t RcvFormatErrMask[1];
+ pseudo_bit_t RcvVCRCErrMask[1];
+ pseudo_bit_t RcvICRCErrMask[1];
+ pseudo_bit_t RcvMinPktLenErrMask[1];
+ pseudo_bit_t RcvMaxPktLenErrMask[1];
+ pseudo_bit_t RcvLongPktLenErrMask[1];
+ pseudo_bit_t RcvShortPktLenErrMask[1];
+ pseudo_bit_t RcvUnexpectedCharErrMask[1];
+ pseudo_bit_t RcvUnsupportedVLErrMask[1];
+ pseudo_bit_t RcvEBPErrMask[1];
+ pseudo_bit_t RcvIBFlowErrMask[1];
+ pseudo_bit_t RcvBadVersionErrMask[1];
+ pseudo_bit_t _unused_0[2];
+ pseudo_bit_t RcvBadTidErrMask[1];
+ pseudo_bit_t RcvHdrLenErrMask[1];
+ pseudo_bit_t RcvHdrErrMask[1];
+ pseudo_bit_t RcvIBLostLinkErrMask[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t SendMinPktLenErrMask[1];
+ pseudo_bit_t SendMaxPktLenErrMask[1];
+ pseudo_bit_t SendUnderRunErrMask[1];
+ pseudo_bit_t SendPktLenErrMask[1];
+ pseudo_bit_t SendDroppedSmpPktErrMask[1];
+ pseudo_bit_t SendDroppedDataPktErrMask[1];
+ pseudo_bit_t _unused_2[1];
+ pseudo_bit_t SendUnexpectedPktNumErrMask[1];
+ pseudo_bit_t SendUnsupportedVLErrMask[1];
+ pseudo_bit_t SendBufMisuseErrMask[1];
+ pseudo_bit_t SDmaGenMismatchErrMask[1];
+ pseudo_bit_t SDmaOutOfBoundErrMask[1];
+ pseudo_bit_t SDmaTailOutOfBoundErrMask[1];
+ pseudo_bit_t SDmaBaseErrMask[1];
+ pseudo_bit_t SDma1stDescErrMask[1];
+ pseudo_bit_t SDmaRpyTagErrMask[1];
+ pseudo_bit_t SDmaDwEnErrMask[1];
+ pseudo_bit_t SDmaMissingDwErrMask[1];
+ pseudo_bit_t SDmaUnexpDataErrMask[1];
+ pseudo_bit_t SDmaDescAddrMisalignErrMask[1];
+ pseudo_bit_t SDmaHaltErrMask[1];
+ pseudo_bit_t _unused_3[4];
+ pseudo_bit_t VL15BufMisuseErrMask[1];
+ pseudo_bit_t _unused_4[2];
+ pseudo_bit_t SHeadersErrMask[1];
+ pseudo_bit_t IBStatusChangedMask[1];
+ pseudo_bit_t _unused_5[5];
+};
+struct QIB_7322_ErrMask_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ErrMask_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ErrStatus_0_offset 0x00001088UL
+struct QIB_7322_ErrStatus_0_pb {
+ pseudo_bit_t RcvFormatErr[1];
+ pseudo_bit_t RcvVCRCErr[1];
+ pseudo_bit_t RcvICRCErr[1];
+ pseudo_bit_t RcvMinPktLenErr[1];
+ pseudo_bit_t RcvMaxPktLenErr[1];
+ pseudo_bit_t RcvLongPktLenErr[1];
+ pseudo_bit_t RcvShortPktLenErr[1];
+ pseudo_bit_t RcvUnexpectedCharErr[1];
+ pseudo_bit_t RcvUnsupportedVLErr[1];
+ pseudo_bit_t RcvEBPErr[1];
+ pseudo_bit_t RcvIBFlowErr[1];
+ pseudo_bit_t RcvBadVersionErr[1];
+ pseudo_bit_t _unused_0[2];
+ pseudo_bit_t RcvBadTidErr[1];
+ pseudo_bit_t RcvHdrLenErr[1];
+ pseudo_bit_t RcvHdrErr[1];
+ pseudo_bit_t RcvIBLostLinkErr[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t SendMinPktLenErr[1];
+ pseudo_bit_t SendMaxPktLenErr[1];
+ pseudo_bit_t SendUnderRunErr[1];
+ pseudo_bit_t SendPktLenErr[1];
+ pseudo_bit_t SendDroppedSmpPktErr[1];
+ pseudo_bit_t SendDroppedDataPktErr[1];
+ pseudo_bit_t _unused_2[1];
+ pseudo_bit_t SendUnexpectedPktNumErr[1];
+ pseudo_bit_t SendUnsupportedVLErr[1];
+ pseudo_bit_t SendBufMisuseErr[1];
+ pseudo_bit_t SDmaGenMismatchErr[1];
+ pseudo_bit_t SDmaOutOfBoundErr[1];
+ pseudo_bit_t SDmaTailOutOfBoundErr[1];
+ pseudo_bit_t SDmaBaseErr[1];
+ pseudo_bit_t SDma1stDescErr[1];
+ pseudo_bit_t SDmaRpyTagErr[1];
+ pseudo_bit_t SDmaDwEnErr[1];
+ pseudo_bit_t SDmaMissingDwErr[1];
+ pseudo_bit_t SDmaUnexpDataErr[1];
+ pseudo_bit_t SDmaDescAddrMisalignErr[1];
+ pseudo_bit_t SDmaHaltErr[1];
+ pseudo_bit_t _unused_3[4];
+ pseudo_bit_t VL15BufMisuseErr[1];
+ pseudo_bit_t _unused_4[2];
+ pseudo_bit_t SHeadersErr[1];
+ pseudo_bit_t IBStatusChanged[1];
+ pseudo_bit_t _unused_5[5];
+};
+struct QIB_7322_ErrStatus_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ErrStatus_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ErrClear_0_offset 0x00001090UL
+struct QIB_7322_ErrClear_0_pb {
+ pseudo_bit_t RcvFormatErrClear[1];
+ pseudo_bit_t RcvVCRCErrClear[1];
+ pseudo_bit_t RcvICRCErrClear[1];
+ pseudo_bit_t RcvMinPktLenErrClear[1];
+ pseudo_bit_t RcvMaxPktLenErrClear[1];
+ pseudo_bit_t RcvLongPktLenErrClear[1];
+ pseudo_bit_t RcvShortPktLenErrClear[1];
+ pseudo_bit_t RcvUnexpectedCharErrClear[1];
+ pseudo_bit_t RcvUnsupportedVLErrClear[1];
+ pseudo_bit_t RcvEBPErrClear[1];
+ pseudo_bit_t RcvIBFlowErrClear[1];
+ pseudo_bit_t RcvBadVersionErrClear[1];
+ pseudo_bit_t _unused_0[2];
+ pseudo_bit_t RcvBadTidErrClear[1];
+ pseudo_bit_t RcvHdrLenErrClear[1];
+ pseudo_bit_t RcvHdrErrClear[1];
+ pseudo_bit_t RcvIBLostLinkErrClear[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t SendMinPktLenErrClear[1];
+ pseudo_bit_t SendMaxPktLenErrClear[1];
+ pseudo_bit_t SendUnderRunErrClear[1];
+ pseudo_bit_t SendPktLenErrClear[1];
+ pseudo_bit_t SendDroppedSmpPktErrClear[1];
+ pseudo_bit_t SendDroppedDataPktErrClear[1];
+ pseudo_bit_t _unused_2[1];
+ pseudo_bit_t SendUnexpectedPktNumErrClear[1];
+ pseudo_bit_t SendUnsupportedVLErrClear[1];
+ pseudo_bit_t SendBufMisuseErrClear[1];
+ pseudo_bit_t SDmaGenMismatchErrClear[1];
+ pseudo_bit_t SDmaOutOfBoundErrClear[1];
+ pseudo_bit_t SDmaTailOutOfBoundErrClear[1];
+ pseudo_bit_t SDmaBaseErrClear[1];
+ pseudo_bit_t SDma1stDescErrClear[1];
+ pseudo_bit_t SDmaRpyTagErrClear[1];
+ pseudo_bit_t SDmaDwEnErrClear[1];
+ pseudo_bit_t SDmaMissingDwErrClear[1];
+ pseudo_bit_t SDmaUnexpDataErrClear[1];
+ pseudo_bit_t SDmaDescAddrMisalignErrClear[1];
+ pseudo_bit_t SDmaHaltErrClear[1];
+ pseudo_bit_t _unused_3[4];
+ pseudo_bit_t VL15BufMisuseErrClear[1];
+ pseudo_bit_t _unused_4[2];
+ pseudo_bit_t SHeadersErrClear[1];
+ pseudo_bit_t IBStatusChangedClear[1];
+ pseudo_bit_t _unused_5[5];
+};
+struct QIB_7322_ErrClear_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ErrClear_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TXEStatus_0_offset 0x000010b8UL
+struct QIB_7322_TXEStatus_0_pb {
+ pseudo_bit_t LaFifoEmpty_VL0[1];
+ pseudo_bit_t LaFifoEmpty_VL1[1];
+ pseudo_bit_t LaFifoEmpty_VL2[1];
+ pseudo_bit_t LaFifoEmpty_VL3[1];
+ pseudo_bit_t LaFifoEmpty_VL4[1];
+ pseudo_bit_t LaFifoEmpty_VL5[1];
+ pseudo_bit_t LaFifoEmpty_VL6[1];
+ pseudo_bit_t LaFifoEmpty_VL7[1];
+ pseudo_bit_t _unused_0[7];
+ pseudo_bit_t LaFifoEmpty_VL15[1];
+ pseudo_bit_t _unused_1[14];
+ pseudo_bit_t RmFifoEmpty[1];
+ pseudo_bit_t TXE_IBC_Idle[1];
+ pseudo_bit_t _unused_2[32];
+};
+struct QIB_7322_TXEStatus_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_TXEStatus_0_pb );
+};
+/* Default value: 0x0000000XC00080FF */
+
+#define QIB_7322_RcvCtrl_0_offset 0x00001100UL
+struct QIB_7322_RcvCtrl_0_pb {
+ pseudo_bit_t ContextEnableKernel[1];
+ pseudo_bit_t _unused_0[1];
+ pseudo_bit_t ContextEnableUser[16];
+ pseudo_bit_t _unused_1[21];
+ pseudo_bit_t RcvIBPortEnable[1];
+ pseudo_bit_t RcvQPMapEnable[1];
+ pseudo_bit_t RcvPartitionKeyDisable[1];
+ pseudo_bit_t RcvResetCredit[1];
+ pseudo_bit_t _unused_2[21];
+};
+struct QIB_7322_RcvCtrl_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvCtrl_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvBTHQP_0_offset 0x00001108UL
+struct QIB_7322_RcvBTHQP_0_pb {
+ pseudo_bit_t RcvBTHQP[24];
+ pseudo_bit_t _unused_0[40];
+};
+struct QIB_7322_RcvBTHQP_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvBTHQP_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMapTableA_0_offset 0x00001110UL
+struct QIB_7322_RcvQPMapTableA_0_pb {
+ pseudo_bit_t RcvQPMapContext0[5];
+ pseudo_bit_t RcvQPMapContext1[5];
+ pseudo_bit_t RcvQPMapContext2[5];
+ pseudo_bit_t RcvQPMapContext3[5];
+ pseudo_bit_t RcvQPMapContext4[5];
+ pseudo_bit_t RcvQPMapContext5[5];
+ pseudo_bit_t _unused_0[34];
+};
+struct QIB_7322_RcvQPMapTableA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMapTableA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMapTableB_0_offset 0x00001118UL
+struct QIB_7322_RcvQPMapTableB_0_pb {
+ pseudo_bit_t RcvQPMapContext6[5];
+ pseudo_bit_t RcvQPMapContext7[5];
+ pseudo_bit_t RcvQPMapContext8[5];
+ pseudo_bit_t RcvQPMapContext9[5];
+ pseudo_bit_t RcvQPMapContext10[5];
+ pseudo_bit_t RcvQPMapContext11[5];
+ pseudo_bit_t _unused_0[34];
+};
+struct QIB_7322_RcvQPMapTableB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMapTableB_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMapTableC_0_offset 0x00001120UL
+struct QIB_7322_RcvQPMapTableC_0_pb {
+ pseudo_bit_t RcvQPMapContext12[5];
+ pseudo_bit_t RcvQPMapContext13[5];
+ pseudo_bit_t RcvQPMapContext14[5];
+ pseudo_bit_t RcvQPMapContext15[5];
+ pseudo_bit_t RcvQPMapContext16[5];
+ pseudo_bit_t RcvQPMapContext17[5];
+ pseudo_bit_t _unused_0[34];
+};
+struct QIB_7322_RcvQPMapTableC_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMapTableC_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMapTableD_0_offset 0x00001128UL
+struct QIB_7322_RcvQPMapTableD_0_pb {
+ pseudo_bit_t RcvQPMapContext18[5];
+ pseudo_bit_t RcvQPMapContext19[5];
+ pseudo_bit_t RcvQPMapContext20[5];
+ pseudo_bit_t RcvQPMapContext21[5];
+ pseudo_bit_t RcvQPMapContext22[5];
+ pseudo_bit_t RcvQPMapContext23[5];
+ pseudo_bit_t _unused_0[34];
+};
+struct QIB_7322_RcvQPMapTableD_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMapTableD_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMapTableE_0_offset 0x00001130UL
+struct QIB_7322_RcvQPMapTableE_0_pb {
+ pseudo_bit_t RcvQPMapContext24[5];
+ pseudo_bit_t RcvQPMapContext25[5];
+ pseudo_bit_t RcvQPMapContext26[5];
+ pseudo_bit_t RcvQPMapContext27[5];
+ pseudo_bit_t RcvQPMapContext28[5];
+ pseudo_bit_t RcvQPMapContext29[5];
+ pseudo_bit_t _unused_0[34];
+};
+struct QIB_7322_RcvQPMapTableE_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMapTableE_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMapTableF_0_offset 0x00001138UL
+struct QIB_7322_RcvQPMapTableF_0_pb {
+ pseudo_bit_t RcvQPMapContext30[5];
+ pseudo_bit_t RcvQPMapContext31[5];
+ pseudo_bit_t _unused_0[54];
+};
+struct QIB_7322_RcvQPMapTableF_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMapTableF_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSStat_0_offset 0x00001140UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSStart_0_offset 0x00001148UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSInterval_0_offset 0x00001150UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvStatus_0_offset 0x00001160UL
+struct QIB_7322_RcvStatus_0_pb {
+ pseudo_bit_t RxPktInProgress[1];
+ pseudo_bit_t DmaeqBlockingContext[5];
+ pseudo_bit_t _unused_0[58];
+};
+struct QIB_7322_RcvStatus_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvStatus_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvPartitionKey_0_offset 0x00001168UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMulticastContext_0_offset 0x00001170UL
+struct QIB_7322_RcvQPMulticastContext_0_pb {
+ pseudo_bit_t RcvQpMcContext[5];
+ pseudo_bit_t _unused_0[59];
+};
+struct QIB_7322_RcvQPMulticastContext_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMulticastContext_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvPktLEDCnt_0_offset 0x00001178UL
+struct QIB_7322_RcvPktLEDCnt_0_pb {
+ pseudo_bit_t OFFperiod[32];
+ pseudo_bit_t ONperiod[32];
+};
+struct QIB_7322_RcvPktLEDCnt_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvPktLEDCnt_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaIdleCnt_0_offset 0x00001180UL
+struct QIB_7322_SendDmaIdleCnt_0_pb {
+ pseudo_bit_t SendDmaIdleCnt[16];
+ pseudo_bit_t _unused_0[48];
+};
+struct QIB_7322_SendDmaIdleCnt_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaIdleCnt_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaReloadCnt_0_offset 0x00001188UL
+struct QIB_7322_SendDmaReloadCnt_0_pb {
+ pseudo_bit_t SendDmaReloadCnt[16];
+ pseudo_bit_t _unused_0[48];
+};
+struct QIB_7322_SendDmaReloadCnt_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaReloadCnt_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaDescCnt_0_offset 0x00001190UL
+struct QIB_7322_SendDmaDescCnt_0_pb {
+ pseudo_bit_t SendDmaDescCnt[16];
+ pseudo_bit_t _unused_0[48];
+};
+struct QIB_7322_SendDmaDescCnt_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaDescCnt_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendCtrl_0_offset 0x000011c0UL
+struct QIB_7322_SendCtrl_0_pb {
+ pseudo_bit_t TxeAbortIbc[1];
+ pseudo_bit_t TxeBypassIbc[1];
+ pseudo_bit_t _unused_0[1];
+ pseudo_bit_t SendEnable[1];
+ pseudo_bit_t _unused_1[3];
+ pseudo_bit_t ForceCreditUpToDate[1];
+ pseudo_bit_t SDmaCleanup[1];
+ pseudo_bit_t SDmaIntEnable[1];
+ pseudo_bit_t SDmaSingleDescriptor[1];
+ pseudo_bit_t SDmaEnable[1];
+ pseudo_bit_t SDmaHalt[1];
+ pseudo_bit_t TxeDrainLaFifo[1];
+ pseudo_bit_t TxeDrainRmFifo[1];
+ pseudo_bit_t IBVLArbiterEn[1];
+ pseudo_bit_t _unused_2[48];
+};
+struct QIB_7322_SendCtrl_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendCtrl_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaBase_0_offset 0x000011f8UL
+struct QIB_7322_SendDmaBase_0_pb {
+ pseudo_bit_t SendDmaBase[48];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_SendDmaBase_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaBase_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaLenGen_0_offset 0x00001200UL
+struct QIB_7322_SendDmaLenGen_0_pb {
+ pseudo_bit_t Length[16];
+ pseudo_bit_t Generation[3];
+ pseudo_bit_t _unused_0[45];
+};
+struct QIB_7322_SendDmaLenGen_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaLenGen_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaTail_0_offset 0x00001208UL
+struct QIB_7322_SendDmaTail_0_pb {
+ pseudo_bit_t SendDmaTail[16];
+ pseudo_bit_t _unused_0[48];
+};
+struct QIB_7322_SendDmaTail_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaTail_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaHead_0_offset 0x00001210UL
+struct QIB_7322_SendDmaHead_0_pb {
+ pseudo_bit_t SendDmaHead[16];
+ pseudo_bit_t _unused_0[16];
+ pseudo_bit_t InternalSendDmaHead[16];
+ pseudo_bit_t _unused_1[16];
+};
+struct QIB_7322_SendDmaHead_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaHead_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaHeadAddr_0_offset 0x00001218UL
+struct QIB_7322_SendDmaHeadAddr_0_pb {
+ pseudo_bit_t SendDmaHeadAddr[48];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_SendDmaHeadAddr_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaHeadAddr_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaBufMask0_0_offset 0x00001220UL
+struct QIB_7322_SendDmaBufMask0_0_pb {
+ pseudo_bit_t BufMask_63_0[64];
+};
+struct QIB_7322_SendDmaBufMask0_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaBufMask0_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaStatus_0_offset 0x00001238UL
+struct QIB_7322_SendDmaStatus_0_pb {
+ pseudo_bit_t SplFifoDescIndex[16];
+ pseudo_bit_t SplFifoBufNum[8];
+ pseudo_bit_t SplFifoFull[1];
+ pseudo_bit_t SplFifoEmpty[1];
+ pseudo_bit_t SplFifoDisarmed[1];
+ pseudo_bit_t SplFifoReadyToGo[1];
+ pseudo_bit_t ScbFetchDescFlag[1];
+ pseudo_bit_t ScbEntryValid[1];
+ pseudo_bit_t ScbEmpty[1];
+ pseudo_bit_t ScbFull[1];
+ pseudo_bit_t RpyTag_7_0[8];
+ pseudo_bit_t RpyLowAddr_6_0[7];
+ pseudo_bit_t ScbDescIndex_13_0[14];
+ pseudo_bit_t InternalSDmaHalt[1];
+ pseudo_bit_t HaltInProg[1];
+ pseudo_bit_t ScoreBoardDrainInProg[1];
+};
+struct QIB_7322_SendDmaStatus_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaStatus_0_pb );
+};
+/* Default value: 0x0000000042000000 */
+
+#define QIB_7322_SendDmaPriorityThld_0_offset 0x00001258UL
+struct QIB_7322_SendDmaPriorityThld_0_pb {
+ pseudo_bit_t PriorityThreshold[4];
+ pseudo_bit_t _unused_0[60];
+};
+struct QIB_7322_SendDmaPriorityThld_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaPriorityThld_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendHdrErrSymptom_0_offset 0x00001260UL
+struct QIB_7322_SendHdrErrSymptom_0_pb {
+ pseudo_bit_t PacketTooSmall[1];
+ pseudo_bit_t RawIPV6[1];
+ pseudo_bit_t SLIDFail[1];
+ pseudo_bit_t QPFail[1];
+ pseudo_bit_t PkeyFail[1];
+ pseudo_bit_t GRHFail[1];
+ pseudo_bit_t NonKeyPacket[1];
+ pseudo_bit_t _unused_0[57];
+};
+struct QIB_7322_SendHdrErrSymptom_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendHdrErrSymptom_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxCreditVL0_0_offset 0x00001280UL
+struct QIB_7322_RxCreditVL0_0_pb {
+ pseudo_bit_t RxMaxCreditVL[12];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t RxBufrConsumedVL[12];
+ pseudo_bit_t _unused_1[36];
+};
+struct QIB_7322_RxCreditVL0_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxCreditVL0_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaBufUsed0_0_offset 0x00001480UL
+struct QIB_7322_SendDmaBufUsed0_0_pb {
+ pseudo_bit_t BufUsed_63_0[64];
+};
+struct QIB_7322_SendDmaBufUsed0_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaBufUsed0_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaReqTagUsed_0_offset 0x00001498UL
+struct QIB_7322_SendDmaReqTagUsed_0_pb {
+ pseudo_bit_t ReqTagUsed_7_0[8];
+ pseudo_bit_t _unused_0[56];
+};
+struct QIB_7322_SendDmaReqTagUsed_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaReqTagUsed_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendCheckControl_0_offset 0x000014a8UL
+struct QIB_7322_SendCheckControl_0_pb {
+ pseudo_bit_t PacketTooSmall_En[1];
+ pseudo_bit_t RawIPV6_En[1];
+ pseudo_bit_t SLID_En[1];
+ pseudo_bit_t BTHQP_En[1];
+ pseudo_bit_t PKey_En[1];
+ pseudo_bit_t _unused_0[59];
+};
+struct QIB_7322_SendCheckControl_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendCheckControl_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendIBSLIDMask_0_offset 0x000014b0UL
+struct QIB_7322_SendIBSLIDMask_0_pb {
+ pseudo_bit_t SendIBSLIDMask_15_0[16];
+ pseudo_bit_t _unused_0[48];
+};
+struct QIB_7322_SendIBSLIDMask_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendIBSLIDMask_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendIBSLIDAssign_0_offset 0x000014b8UL
+struct QIB_7322_SendIBSLIDAssign_0_pb {
+ pseudo_bit_t SendIBSLIDAssign_15_0[16];
+ pseudo_bit_t _unused_0[48];
+};
+struct QIB_7322_SendIBSLIDAssign_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendIBSLIDAssign_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBCStatusA_0_offset 0x00001540UL
+struct QIB_7322_IBCStatusA_0_pb {
+ pseudo_bit_t LinkTrainingState[5];
+ pseudo_bit_t LinkState[3];
+ pseudo_bit_t LinkSpeedActive[1];
+ pseudo_bit_t LinkWidthActive[1];
+ pseudo_bit_t DDS_RXEQ_FAIL[1];
+ pseudo_bit_t _unused_0[1];
+ pseudo_bit_t IBRxLaneReversed[1];
+ pseudo_bit_t IBTxLaneReversed[1];
+ pseudo_bit_t ScrambleEn[1];
+ pseudo_bit_t ScrambleCapRemote[1];
+ pseudo_bit_t _unused_1[13];
+ pseudo_bit_t LinkSpeedQDR[1];
+ pseudo_bit_t TxReady[1];
+ pseudo_bit_t _unused_2[1];
+ pseudo_bit_t TxCreditOk_VL0[1];
+ pseudo_bit_t TxCreditOk_VL1[1];
+ pseudo_bit_t TxCreditOk_VL2[1];
+ pseudo_bit_t TxCreditOk_VL3[1];
+ pseudo_bit_t TxCreditOk_VL4[1];
+ pseudo_bit_t TxCreditOk_VL5[1];
+ pseudo_bit_t TxCreditOk_VL6[1];
+ pseudo_bit_t TxCreditOk_VL7[1];
+ pseudo_bit_t _unused_3[24];
+};
+struct QIB_7322_IBCStatusA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBCStatusA_0_pb );
+};
+/* Default value: 0x0000000000000X02 */
+
+#define QIB_7322_IBCStatusB_0_offset 0x00001548UL
+struct QIB_7322_IBCStatusB_0_pb {
+ pseudo_bit_t LinkRoundTripLatency[26];
+ pseudo_bit_t ReqDDSLocalFromRmt[4];
+ pseudo_bit_t RxEqLocalDevice[2];
+ pseudo_bit_t heartbeat_crosstalk[4];
+ pseudo_bit_t heartbeat_timed_out[1];
+ pseudo_bit_t ibsd_adaptation_timer_started[1];
+ pseudo_bit_t ibsd_adaptation_timer_reached_threshold[1];
+ pseudo_bit_t ibsd_adaptation_timer_debug[1];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_IBCStatusB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBCStatusB_0_pb );
+};
+/* Default value: 0x00000000XXXXXXXX */
+
+#define QIB_7322_IBCCtrlA_0_offset 0x00001560UL
+struct QIB_7322_IBCCtrlA_0_pb {
+ pseudo_bit_t FlowCtrlPeriod[8];
+ pseudo_bit_t FlowCtrlWaterMark[8];
+ pseudo_bit_t LinkInitCmd[3];
+ pseudo_bit_t LinkCmd[2];
+ pseudo_bit_t MaxPktLen[11];
+ pseudo_bit_t PhyerrThreshold[4];
+ pseudo_bit_t OverrunThreshold[4];
+ pseudo_bit_t _unused_0[8];
+ pseudo_bit_t NumVLane[3];
+ pseudo_bit_t _unused_1[9];
+ pseudo_bit_t IBStatIntReductionEn[1];
+ pseudo_bit_t IBLinkEn[1];
+ pseudo_bit_t LinkDownDefaultState[1];
+ pseudo_bit_t Loopback[1];
+};
+struct QIB_7322_IBCCtrlA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBCCtrlA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBCCtrlB_0_offset 0x00001568UL
+struct QIB_7322_IBCCtrlB_0_pb {
+ pseudo_bit_t IB_ENHANCED_MODE[1];
+ pseudo_bit_t SD_SPEED[1];
+ pseudo_bit_t SD_SPEED_SDR[1];
+ pseudo_bit_t SD_SPEED_DDR[1];
+ pseudo_bit_t SD_SPEED_QDR[1];
+ pseudo_bit_t IB_NUM_CHANNELS[2];
+ pseudo_bit_t IB_POLARITY_REV_SUPP[1];
+ pseudo_bit_t IB_LANE_REV_SUPPORTED[1];
+ pseudo_bit_t SD_RX_EQUAL_ENABLE[1];
+ pseudo_bit_t SD_ADD_ENB[1];
+ pseudo_bit_t SD_DDSV[1];
+ pseudo_bit_t SD_DDS[4];
+ pseudo_bit_t HRTBT_ENB[1];
+ pseudo_bit_t HRTBT_AUTO[1];
+ pseudo_bit_t HRTBT_PORT[8];
+ pseudo_bit_t HRTBT_REQ[1];
+ pseudo_bit_t IB_ENABLE_FILT_DPKT[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t IB_DLID[16];
+ pseudo_bit_t IB_DLID_MASK[16];
+};
+struct QIB_7322_IBCCtrlB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBCCtrlB_0_pb );
+};
+/* Default value: 0x00000000000305FF */
+
+#define QIB_7322_IBCCtrlC_0_offset 0x00001570UL
+struct QIB_7322_IBCCtrlC_0_pb {
+ pseudo_bit_t IB_FRONT_PORCH[5];
+ pseudo_bit_t IB_BACK_PORCH[5];
+ pseudo_bit_t _unused_0[54];
+};
+struct QIB_7322_IBCCtrlC_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBCCtrlC_0_pb );
+};
+/* Default value: 0x0000000000000301 */
+
+#define QIB_7322_HRTBT_GUID_0_offset 0x00001588UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IB_SDTEST_IF_TX_0_offset 0x00001590UL
+struct QIB_7322_IB_SDTEST_IF_TX_0_pb {
+ pseudo_bit_t TS_T_TX_VALID[1];
+ pseudo_bit_t TS_3_TX_VALID[1];
+ pseudo_bit_t VL_CAP[2];
+ pseudo_bit_t CREDIT_CHANGE[1];
+ pseudo_bit_t _unused_0[6];
+ pseudo_bit_t TS_TX_OPCODE[2];
+ pseudo_bit_t TS_TX_SPEED[3];
+ pseudo_bit_t _unused_1[16];
+ pseudo_bit_t TS_TX_TX_CFG[16];
+ pseudo_bit_t TS_TX_RX_CFG[16];
+};
+struct QIB_7322_IB_SDTEST_IF_TX_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IB_SDTEST_IF_TX_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IB_SDTEST_IF_RX_0_offset 0x00001598UL
+struct QIB_7322_IB_SDTEST_IF_RX_0_pb {
+ pseudo_bit_t TS_T_RX_VALID[1];
+ pseudo_bit_t TS_3_RX_VALID[1];
+ pseudo_bit_t _unused_0[14];
+ pseudo_bit_t TS_RX_A[8];
+ pseudo_bit_t TS_RX_B[8];
+ pseudo_bit_t TS_RX_TX_CFG[16];
+ pseudo_bit_t TS_RX_RX_CFG[16];
+};
+struct QIB_7322_IB_SDTEST_IF_RX_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IB_SDTEST_IF_RX_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBNCModeCtrl_0_offset 0x000015b8UL
+struct QIB_7322_IBNCModeCtrl_0_pb {
+ pseudo_bit_t TSMEnable_send_TS1[1];
+ pseudo_bit_t TSMEnable_send_TS2[1];
+ pseudo_bit_t TSMEnable_ignore_TSM_on_rx[1];
+ pseudo_bit_t _unused_0[5];
+ pseudo_bit_t TSMCode_TS1[9];
+ pseudo_bit_t TSMCode_TS2[9];
+ pseudo_bit_t _unused_1[6];
+ pseudo_bit_t ScrambleCapLocal[1];
+ pseudo_bit_t ScrambleCapRemoteMask[1];
+ pseudo_bit_t ScrambleCapRemoteForce[1];
+ pseudo_bit_t _unused_2[29];
+};
+struct QIB_7322_IBNCModeCtrl_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBNCModeCtrl_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBSerdesStatus_0_offset 0x000015d0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBPCSConfig_0_offset 0x000015d8UL
+struct QIB_7322_IBPCSConfig_0_pb {
+ pseudo_bit_t tx_rx_reset[1];
+ pseudo_bit_t xcv_treset[1];
+ pseudo_bit_t xcv_rreset[1];
+ pseudo_bit_t _unused_0[6];
+ pseudo_bit_t link_sync_mask[10];
+ pseudo_bit_t _unused_1[45];
+};
+struct QIB_7322_IBPCSConfig_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBPCSConfig_0_pb );
+};
+/* Default value: 0x0000000000000007 */
+
+#define QIB_7322_IBSerdesCtrl_0_offset 0x000015e0UL
+struct QIB_7322_IBSerdesCtrl_0_pb {
+ pseudo_bit_t CMODE[7];
+ pseudo_bit_t _unused_0[1];
+ pseudo_bit_t TXIDLE[1];
+ pseudo_bit_t RXPD[1];
+ pseudo_bit_t TXPD[1];
+ pseudo_bit_t PLLPD[1];
+ pseudo_bit_t LPEN[1];
+ pseudo_bit_t RXLOSEN[1];
+ pseudo_bit_t _unused_1[1];
+ pseudo_bit_t IB_LAT_MODE[1];
+ pseudo_bit_t CGMODE[4];
+ pseudo_bit_t CHANNEL_RESET_N[4];
+ pseudo_bit_t DISABLE_RXLATOFF_SDR[1];
+ pseudo_bit_t DISABLE_RXLATOFF_DDR[1];
+ pseudo_bit_t DISABLE_RXLATOFF_QDR[1];
+ pseudo_bit_t _unused_2[37];
+};
+struct QIB_7322_IBSerdesCtrl_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBSerdesCtrl_0_pb );
+};
+/* Default value: 0x0000000000FFA00F */
+
+#define QIB_7322_IBSD_TX_DEEMPHASIS_OVERRIDE_0_offset 0x00001600UL
+struct QIB_7322_IBSD_TX_DEEMPHASIS_OVERRIDE_0_pb {
+ pseudo_bit_t txcn1_ena[3];
+ pseudo_bit_t txcn1_xtra_emph0[2];
+ pseudo_bit_t txcp1_ena[4];
+ pseudo_bit_t txc0_ena[5];
+ pseudo_bit_t txampcntl_d2a[4];
+ pseudo_bit_t _unused_0[12];
+ pseudo_bit_t reset_tx_deemphasis_override[1];
+ pseudo_bit_t tx_override_deemphasis_select[1];
+ pseudo_bit_t _unused_1[32];
+};
+struct QIB_7322_IBSD_TX_DEEMPHASIS_OVERRIDE_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBSD_TX_DEEMPHASIS_OVERRIDE_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_STATIC_SDR_0_offset 0x00001640UL
+struct QIB_7322_ADAPT_DISABLE_STATIC_SDR_0_pb {
+ pseudo_bit_t static_disable_rxenadfe_sdr_ch0[8];
+ pseudo_bit_t static_disable_rxenadfe_sdr_ch1[8];
+ pseudo_bit_t static_disable_rxenadfe_sdr_ch2[8];
+ pseudo_bit_t static_disable_rxenadfe_sdr_ch3[8];
+ pseudo_bit_t static_disable_rxenale_sdr_ch0[1];
+ pseudo_bit_t static_disable_rxenale_sdr_ch1[1];
+ pseudo_bit_t static_disable_rxenale_sdr_ch2[1];
+ pseudo_bit_t static_disable_rxenale_sdr_ch3[1];
+ pseudo_bit_t static_disable_rxenagain_sdr_ch0[1];
+ pseudo_bit_t static_disable_rxenagain_sdr_ch1[1];
+ pseudo_bit_t static_disable_rxenagain_sdr_ch2[1];
+ pseudo_bit_t static_disable_rxenagain_sdr_ch3[1];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_ADAPT_DISABLE_STATIC_SDR_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ADAPT_DISABLE_STATIC_SDR_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_DYNAMIC_SDR_0_offset 0x00001648UL
+struct QIB_7322_ADAPT_DISABLE_DYNAMIC_SDR_0_pb {
+ pseudo_bit_t dyn_disable_rxenadfe_sdr_ch0[8];
+ pseudo_bit_t dyn_disable_rxenadfe_sdr_ch1[8];
+ pseudo_bit_t dyn_disable_rxenadfe_sdr_ch2[8];
+ pseudo_bit_t dyn_disable_rxenadfe_sdr_ch3[8];
+ pseudo_bit_t dyn_disable_rxenale_sdr_ch0[1];
+ pseudo_bit_t dyn_disable_rxenale_sdr_ch1[1];
+ pseudo_bit_t dyn_disable_rxenale_sdr_ch2[1];
+ pseudo_bit_t dyn_disable_rxenale_sdr_ch3[1];
+ pseudo_bit_t dyn_disable_rxenagain_sdr_ch0[1];
+ pseudo_bit_t dyn_disable_rxenagain_sdr_ch1[1];
+ pseudo_bit_t dyn_disable_rxenagain_sdr_ch2[1];
+ pseudo_bit_t dyn_disable_rxenagain_sdr_ch3[1];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_ADAPT_DISABLE_DYNAMIC_SDR_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ADAPT_DISABLE_DYNAMIC_SDR_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_STATIC_DDR_0_offset 0x00001650UL
+struct QIB_7322_ADAPT_DISABLE_STATIC_DDR_0_pb {
+ pseudo_bit_t static_disable_rxenadfe_ddr_ch0[8];
+ pseudo_bit_t static_disable_rxenadfe_ddr_ch1[8];
+ pseudo_bit_t static_disable_rxenadfe_ddr_ch2[8];
+ pseudo_bit_t static_disable_rxenadfe_ddr_ch3[8];
+ pseudo_bit_t static_disable_rxenale_ddr_ch0[1];
+ pseudo_bit_t static_disable_rxenale_ddr_ch1[1];
+ pseudo_bit_t static_disable_rxenale_ddr_ch2[1];
+ pseudo_bit_t static_disable_rxenale_ddr_ch3[1];
+ pseudo_bit_t static_disable_rxenagain_ddr_ch0[1];
+ pseudo_bit_t static_disable_rxenagain_ddr_ch1[1];
+ pseudo_bit_t static_disable_rxenagain_ddr_ch2[1];
+ pseudo_bit_t static_disable_rxenagain_ddr_ch3[1];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_ADAPT_DISABLE_STATIC_DDR_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ADAPT_DISABLE_STATIC_DDR_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_DYNAMIC_DDR_0_offset 0x00001658UL
+struct QIB_7322_ADAPT_DISABLE_DYNAMIC_DDR_0_pb {
+ pseudo_bit_t dyn_disable_rxenadfe_ddr_ch0[8];
+ pseudo_bit_t dyn_disable_rxenadfe_ddr_ch1[8];
+ pseudo_bit_t dyn_disable_rxenadfe_ddr_ch2[8];
+ pseudo_bit_t dyn_disable_rxenadfe_ddr_ch3[8];
+ pseudo_bit_t dyn_disable_rxenale_ddr_ch0[1];
+ pseudo_bit_t dyn_disable_rxenale_ddr_ch1[1];
+ pseudo_bit_t dyn_disable_rxenale_ddr_ch2[1];
+ pseudo_bit_t dyn_disable_rxenale_ddr_ch3[1];
+ pseudo_bit_t dyn_disable_rxenagain_ddr_ch0[1];
+ pseudo_bit_t dyn_disable_rxenagain_ddr_ch1[1];
+ pseudo_bit_t dyn_disable_rxenagain_ddr_ch2[1];
+ pseudo_bit_t dyn_disable_rxenagain_ddr_ch3[1];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_ADAPT_DISABLE_DYNAMIC_DDR_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ADAPT_DISABLE_DYNAMIC_DDR_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_STATIC_QDR_0_offset 0x00001660UL
+struct QIB_7322_ADAPT_DISABLE_STATIC_QDR_0_pb {
+ pseudo_bit_t static_disable_rxenadfe_qdr_ch0[8];
+ pseudo_bit_t static_disable_rxenadfe_qdr_ch1[8];
+ pseudo_bit_t static_disable_rxenadfe_qdr_ch2[8];
+ pseudo_bit_t static_disable_rxenadfe_qdr_ch3[8];
+ pseudo_bit_t static_disable_rxenale_qdr_ch0[1];
+ pseudo_bit_t static_disable_rxenale_qdr_ch1[1];
+ pseudo_bit_t static_disable_rxenale_qdr_ch2[1];
+ pseudo_bit_t static_disable_rxenale_qdr_ch3[1];
+ pseudo_bit_t static_disable_rxenagain_qdr_ch0[1];
+ pseudo_bit_t static_disable_rxenagain_qdr_ch1[1];
+ pseudo_bit_t static_disable_rxenagain_qdr_ch2[1];
+ pseudo_bit_t static_disable_rxenagain_qdr_ch3[1];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_ADAPT_DISABLE_STATIC_QDR_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ADAPT_DISABLE_STATIC_QDR_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_DYNAMIC_QDR_0_offset 0x00001668UL
+struct QIB_7322_ADAPT_DISABLE_DYNAMIC_QDR_0_pb {
+ pseudo_bit_t dyn_disable_rxenadfe_qdr_ch0[8];
+ pseudo_bit_t dyn_disable_rxenadfe_qdr_ch1[8];
+ pseudo_bit_t dyn_disable_rxenadfe_qdr_ch2[8];
+ pseudo_bit_t dyn_disable_rxenadfe_qdr_ch3[8];
+ pseudo_bit_t dyn_disable_rxenale_qdr_ch0[1];
+ pseudo_bit_t dyn_disable_rxenale_qdr_ch1[1];
+ pseudo_bit_t dyn_disable_rxenale_qdr_ch2[1];
+ pseudo_bit_t dyn_disable_rxenale_qdr_ch3[1];
+ pseudo_bit_t dyn_disable_rxenagain_qdr_ch0[1];
+ pseudo_bit_t dyn_disable_rxenagain_qdr_ch1[1];
+ pseudo_bit_t dyn_disable_rxenagain_qdr_ch2[1];
+ pseudo_bit_t dyn_disable_rxenagain_qdr_ch3[1];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_ADAPT_DISABLE_DYNAMIC_QDR_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ADAPT_DISABLE_DYNAMIC_QDR_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_TIMER_THRESHOLD_0_offset 0x00001670UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrUnCorErrLogA_0_offset 0x00001800UL
+struct QIB_7322_RxBufrUnCorErrLogA_0_pb {
+ pseudo_bit_t RxBufrUnCorErrData_63_0[64];
+};
+struct QIB_7322_RxBufrUnCorErrLogA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrUnCorErrLogA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrUnCorErrLogB_0_offset 0x00001808UL
+struct QIB_7322_RxBufrUnCorErrLogB_0_pb {
+ pseudo_bit_t RxBufrUnCorErrData_127_64[64];
+};
+struct QIB_7322_RxBufrUnCorErrLogB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrUnCorErrLogB_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrUnCorErrLogC_0_offset 0x00001810UL
+struct QIB_7322_RxBufrUnCorErrLogC_0_pb {
+ pseudo_bit_t RxBufrUnCorErrData_191_128[64];
+};
+struct QIB_7322_RxBufrUnCorErrLogC_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrUnCorErrLogC_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrUnCorErrLogD_0_offset 0x00001818UL
+struct QIB_7322_RxBufrUnCorErrLogD_0_pb {
+ pseudo_bit_t RxBufrUnCorErrData_255_192[64];
+};
+struct QIB_7322_RxBufrUnCorErrLogD_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrUnCorErrLogD_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrUnCorErrLogE_0_offset 0x00001820UL
+struct QIB_7322_RxBufrUnCorErrLogE_0_pb {
+ pseudo_bit_t RxBufrUnCorErrData_258_256[3];
+ pseudo_bit_t RxBufrUnCorErrCheckBit_36_0[37];
+ pseudo_bit_t RxBufrUnCorErrAddr_15_0[16];
+ pseudo_bit_t _unused_0[8];
+};
+struct QIB_7322_RxBufrUnCorErrLogE_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrUnCorErrLogE_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxFlagUnCorErrLogA_0_offset 0x00001828UL
+struct QIB_7322_RxFlagUnCorErrLogA_0_pb {
+ pseudo_bit_t RxFlagUnCorErrData_63_0[64];
+};
+struct QIB_7322_RxFlagUnCorErrLogA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxFlagUnCorErrLogA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxFlagUnCorErrLogB_0_offset 0x00001830UL
+struct QIB_7322_RxFlagUnCorErrLogB_0_pb {
+ pseudo_bit_t RxFlagUnCorErrCheckBit_7_0[8];
+ pseudo_bit_t RxFlagUnCorErrAddr_12_0[13];
+ pseudo_bit_t _unused_0[43];
+};
+struct QIB_7322_RxFlagUnCorErrLogB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxFlagUnCorErrLogB_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLkupiqUnCorErrLogA_0_offset 0x00001840UL
+struct QIB_7322_RxLkupiqUnCorErrLogA_0_pb {
+ pseudo_bit_t RxLkupiqUnCorErrData_45_0[46];
+ pseudo_bit_t RxLkupiqUnCorErrCheckBit_7_0[8];
+ pseudo_bit_t _unused_0[10];
+};
+struct QIB_7322_RxLkupiqUnCorErrLogA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxLkupiqUnCorErrLogA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLkupiqUnCorErrLogB_0_offset 0x00001848UL
+struct QIB_7322_RxLkupiqUnCorErrLogB_0_pb {
+ pseudo_bit_t RxLkupiqUnCorErrAddr_12_0[13];
+ pseudo_bit_t _unused_0[51];
+};
+struct QIB_7322_RxLkupiqUnCorErrLogB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxLkupiqUnCorErrLogB_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxHdrFifoUnCorErrLogA_0_offset 0x00001850UL
+struct QIB_7322_RxHdrFifoUnCorErrLogA_0_pb {
+ pseudo_bit_t RxHdrFifoUnCorErrData_63_0[64];
+};
+struct QIB_7322_RxHdrFifoUnCorErrLogA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxHdrFifoUnCorErrLogA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxHdrFifoUnCorErrLogB_0_offset 0x00001858UL
+struct QIB_7322_RxHdrFifoUnCorErrLogB_0_pb {
+ pseudo_bit_t RxHdrFifoUnCorErrData_127_64[64];
+};
+struct QIB_7322_RxHdrFifoUnCorErrLogB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxHdrFifoUnCorErrLogB_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxHdrFifoUnCorErrLogC_0_offset 0x00001860UL
+struct QIB_7322_RxHdrFifoUnCorErrLogC_0_pb {
+ pseudo_bit_t RxHdrFifoUnCorErrCheckBit_15_0[16];
+ pseudo_bit_t RxHdrFifoUnCorErrAddr_10_0[11];
+ pseudo_bit_t _unused_0[37];
+};
+struct QIB_7322_RxHdrFifoUnCorErrLogC_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxHdrFifoUnCorErrLogC_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataFifoUnCorErrLogA_0_offset 0x00001868UL
+struct QIB_7322_RxDataFifoUnCorErrLogA_0_pb {
+ pseudo_bit_t RxDataFifoUnCorErrData_63_0[64];
+};
+struct QIB_7322_RxDataFifoUnCorErrLogA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxDataFifoUnCorErrLogA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataFifoUnCorErrLogB_0_offset 0x00001870UL
+struct QIB_7322_RxDataFifoUnCorErrLogB_0_pb {
+ pseudo_bit_t RxDataFifoUnCorErrData_127_64[64];
+};
+struct QIB_7322_RxDataFifoUnCorErrLogB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxDataFifoUnCorErrLogB_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataFifoUnCorErrLogC_0_offset 0x00001878UL
+struct QIB_7322_RxDataFifoUnCorErrLogC_0_pb {
+ pseudo_bit_t RxDataFifoUnCorErrCheckBit_15_0[16];
+ pseudo_bit_t RxDataFifoUnCorErrAddr_10_0[11];
+ pseudo_bit_t _unused_0[37];
+};
+struct QIB_7322_RxDataFifoUnCorErrLogC_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxDataFifoUnCorErrLogC_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LaFifoArray0UnCorErrLog_0_offset 0x00001880UL
+struct QIB_7322_LaFifoArray0UnCorErrLog_0_pb {
+ pseudo_bit_t LaFifoArray0UnCorErrData_34_0[35];
+ pseudo_bit_t LaFifoArray0UnCorErrCheckBit_10_0[11];
+ pseudo_bit_t LaFifoArray0UnCorErrAddr_10_0[11];
+ pseudo_bit_t _unused_0[7];
+};
+struct QIB_7322_LaFifoArray0UnCorErrLog_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_LaFifoArray0UnCorErrLog_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RmFifoArrayUnCorErrLogA_0_offset 0x000018c0UL
+struct QIB_7322_RmFifoArrayUnCorErrLogA_0_pb {
+ pseudo_bit_t RmFifoArrayUnCorErrData_63_0[64];
+};
+struct QIB_7322_RmFifoArrayUnCorErrLogA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RmFifoArrayUnCorErrLogA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RmFifoArrayUnCorErrLogB_0_offset 0x000018c8UL
+struct QIB_7322_RmFifoArrayUnCorErrLogB_0_pb {
+ pseudo_bit_t RmFifoArrayUnCorErrData_127_64[64];
+};
+struct QIB_7322_RmFifoArrayUnCorErrLogB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RmFifoArrayUnCorErrLogB_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RmFifoArrayUnCorErrLogC_0_offset 0x000018d0UL
+struct QIB_7322_RmFifoArrayUnCorErrLogC_0_pb {
+ pseudo_bit_t RmFifoArrayUnCorErrCheckBit_27_0[28];
+ pseudo_bit_t RmFifoArrayUnCorErrAddr_13_0[14];
+ pseudo_bit_t _unused_0[18];
+ pseudo_bit_t RmFifoArrayUnCorErrDword_3_0[4];
+};
+struct QIB_7322_RmFifoArrayUnCorErrLogC_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RmFifoArrayUnCorErrLogC_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrCorErrLogA_0_offset 0x00001900UL
+struct QIB_7322_RxBufrCorErrLogA_0_pb {
+ pseudo_bit_t RxBufrCorErrData_63_0[64];
+};
+struct QIB_7322_RxBufrCorErrLogA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrCorErrLogA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrCorErrLogB_0_offset 0x00001908UL
+struct QIB_7322_RxBufrCorErrLogB_0_pb {
+ pseudo_bit_t RxBufrCorErrData_127_64[64];
+};
+struct QIB_7322_RxBufrCorErrLogB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrCorErrLogB_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrCorErrLogC_0_offset 0x00001910UL
+struct QIB_7322_RxBufrCorErrLogC_0_pb {
+ pseudo_bit_t RxBufrCorErrData_191_128[64];
+};
+struct QIB_7322_RxBufrCorErrLogC_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrCorErrLogC_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrCorErrLogD_0_offset 0x00001918UL
+struct QIB_7322_RxBufrCorErrLogD_0_pb {
+ pseudo_bit_t RxBufrCorErrData_255_192[64];
+};
+struct QIB_7322_RxBufrCorErrLogD_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrCorErrLogD_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrCorErrLogE_0_offset 0x00001920UL
+struct QIB_7322_RxBufrCorErrLogE_0_pb {
+ pseudo_bit_t RxBufrCorErrData_258_256[3];
+ pseudo_bit_t RxBufrCorErrCheckBit_36_0[37];
+ pseudo_bit_t RxBufrCorErrAddr_15_0[16];
+ pseudo_bit_t _unused_0[8];
+};
+struct QIB_7322_RxBufrCorErrLogE_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrCorErrLogE_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxFlagCorErrLogA_0_offset 0x00001928UL
+struct QIB_7322_RxFlagCorErrLogA_0_pb {
+ pseudo_bit_t RxFlagCorErrData_63_0[64];
+};
+struct QIB_7322_RxFlagCorErrLogA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxFlagCorErrLogA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxFlagCorErrLogB_0_offset 0x00001930UL
+struct QIB_7322_RxFlagCorErrLogB_0_pb {
+ pseudo_bit_t RxFlagCorErrCheckBit_7_0[8];
+ pseudo_bit_t RxFlagCorErrAddr_12_0[13];
+ pseudo_bit_t _unused_0[43];
+};
+struct QIB_7322_RxFlagCorErrLogB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxFlagCorErrLogB_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLkupiqCorErrLogA_0_offset 0x00001940UL
+struct QIB_7322_RxLkupiqCorErrLogA_0_pb {
+ pseudo_bit_t RxLkupiqCorErrData_45_0[46];
+ pseudo_bit_t RxLkupiqCorErrCheckBit_7_0[8];
+ pseudo_bit_t _unused_0[10];
+};
+struct QIB_7322_RxLkupiqCorErrLogA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxLkupiqCorErrLogA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLkupiqCorErrLogB_0_offset 0x00001948UL
+struct QIB_7322_RxLkupiqCorErrLogB_0_pb {
+ pseudo_bit_t RxLkupiqCorErrAddr_12_0[13];
+ pseudo_bit_t _unused_0[51];
+};
+struct QIB_7322_RxLkupiqCorErrLogB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxLkupiqCorErrLogB_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxHdrFifoCorErrLogA_0_offset 0x00001950UL
+struct QIB_7322_RxHdrFifoCorErrLogA_0_pb {
+ pseudo_bit_t RxHdrFifoCorErrData_63_0[64];
+};
+struct QIB_7322_RxHdrFifoCorErrLogA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxHdrFifoCorErrLogA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxHdrFifoCorErrLogB_0_offset 0x00001958UL
+struct QIB_7322_RxHdrFifoCorErrLogB_0_pb {
+ pseudo_bit_t RxHdrFifoCorErrData_127_64[64];
+};
+struct QIB_7322_RxHdrFifoCorErrLogB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxHdrFifoCorErrLogB_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxHdrFifoCorErrLogC_0_offset 0x00001960UL
+struct QIB_7322_RxHdrFifoCorErrLogC_0_pb {
+ pseudo_bit_t RxHdrFifoCorErrCheckBit_15_0[16];
+ pseudo_bit_t RxHdrFifoCorErrAddr_10_0[11];
+ pseudo_bit_t _unused_0[37];
+};
+struct QIB_7322_RxHdrFifoCorErrLogC_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxHdrFifoCorErrLogC_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataFifoCorErrLogA_0_offset 0x00001968UL
+struct QIB_7322_RxDataFifoCorErrLogA_0_pb {
+ pseudo_bit_t RxDataFifoCorErrData_63_0[64];
+};
+struct QIB_7322_RxDataFifoCorErrLogA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxDataFifoCorErrLogA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataFifoCorErrLogB_0_offset 0x00001970UL
+struct QIB_7322_RxDataFifoCorErrLogB_0_pb {
+ pseudo_bit_t RxDataFifoCorErrData_127_64[64];
+};
+struct QIB_7322_RxDataFifoCorErrLogB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxDataFifoCorErrLogB_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataFifoCorErrLogC_0_offset 0x00001978UL
+struct QIB_7322_RxDataFifoCorErrLogC_0_pb {
+ pseudo_bit_t RxDataFifoCorErrCheckBit_15_0[16];
+ pseudo_bit_t RxDataFifoCorErrAddr_10_0[11];
+ pseudo_bit_t _unused_0[37];
+};
+struct QIB_7322_RxDataFifoCorErrLogC_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxDataFifoCorErrLogC_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LaFifoArray0CorErrLog_0_offset 0x00001980UL
+struct QIB_7322_LaFifoArray0CorErrLog_0_pb {
+ pseudo_bit_t LaFifoArray0CorErrData_34_0[35];
+ pseudo_bit_t LaFifoArray0CorErrCheckBit_10_0[11];
+ pseudo_bit_t LaFifoArray0CorErrAddr_10_0[11];
+ pseudo_bit_t _unused_0[7];
+};
+struct QIB_7322_LaFifoArray0CorErrLog_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_LaFifoArray0CorErrLog_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RmFifoArrayCorErrLogA_0_offset 0x000019c0UL
+struct QIB_7322_RmFifoArrayCorErrLogA_0_pb {
+ pseudo_bit_t RmFifoArrayCorErrData_63_0[64];
+};
+struct QIB_7322_RmFifoArrayCorErrLogA_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RmFifoArrayCorErrLogA_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RmFifoArrayCorErrLogB_0_offset 0x000019c8UL
+struct QIB_7322_RmFifoArrayCorErrLogB_0_pb {
+ pseudo_bit_t RmFifoArrayCorErrData_127_64[64];
+};
+struct QIB_7322_RmFifoArrayCorErrLogB_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RmFifoArrayCorErrLogB_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RmFifoArrayCorErrLogC_0_offset 0x000019d0UL
+struct QIB_7322_RmFifoArrayCorErrLogC_0_pb {
+ pseudo_bit_t RmFifoArrayCorErrCheckBit_27_0[28];
+ pseudo_bit_t RmFifoArrayCorErrAddr_13_0[14];
+ pseudo_bit_t _unused_0[18];
+ pseudo_bit_t RmFifoArrayCorErrDword_3_0[4];
+};
+struct QIB_7322_RmFifoArrayCorErrLogC_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RmFifoArrayCorErrLogC_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_HighPriorityLimit_0_offset 0x00001bc0UL
+struct QIB_7322_HighPriorityLimit_0_pb {
+ pseudo_bit_t Limit[8];
+ pseudo_bit_t _unused_0[56];
+};
+struct QIB_7322_HighPriorityLimit_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_HighPriorityLimit_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LowPriority0_0_offset 0x00001c00UL
+struct QIB_7322_LowPriority0_0_pb {
+ pseudo_bit_t Weight[8];
+ pseudo_bit_t _unused_0[8];
+ pseudo_bit_t VirtualLane[3];
+ pseudo_bit_t _unused_1[45];
+};
+struct QIB_7322_LowPriority0_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_LowPriority0_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_HighPriority0_0_offset 0x00001e00UL
+struct QIB_7322_HighPriority0_0_pb {
+ pseudo_bit_t Weight[8];
+ pseudo_bit_t _unused_0[8];
+ pseudo_bit_t VirtualLane[3];
+ pseudo_bit_t _unused_1[45];
+};
+struct QIB_7322_HighPriority0_0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_HighPriority0_0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_CntrRegBase_1_offset 0x00002028UL
+/* Default value: 0x0000000000013000 */
+
+#define QIB_7322_ErrMask_1_offset 0x00002080UL
+struct QIB_7322_ErrMask_1_pb {
+ pseudo_bit_t RcvFormatErrMask[1];
+ pseudo_bit_t RcvVCRCErrMask[1];
+ pseudo_bit_t RcvICRCErrMask[1];
+ pseudo_bit_t RcvMinPktLenErrMask[1];
+ pseudo_bit_t RcvMaxPktLenErrMask[1];
+ pseudo_bit_t RcvLongPktLenErrMask[1];
+ pseudo_bit_t RcvShortPktLenErrMask[1];
+ pseudo_bit_t RcvUnexpectedCharErrMask[1];
+ pseudo_bit_t RcvUnsupportedVLErrMask[1];
+ pseudo_bit_t RcvEBPErrMask[1];
+ pseudo_bit_t RcvIBFlowErrMask[1];
+ pseudo_bit_t RcvBadVersionErrMask[1];
+ pseudo_bit_t _unused_0[2];
+ pseudo_bit_t RcvBadTidErrMask[1];
+ pseudo_bit_t RcvHdrLenErrMask[1];
+ pseudo_bit_t RcvHdrErrMask[1];
+ pseudo_bit_t RcvIBLostLinkErrMask[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t SendMinPktLenErrMask[1];
+ pseudo_bit_t SendMaxPktLenErrMask[1];
+ pseudo_bit_t SendUnderRunErrMask[1];
+ pseudo_bit_t SendPktLenErrMask[1];
+ pseudo_bit_t SendDroppedSmpPktErrMask[1];
+ pseudo_bit_t SendDroppedDataPktErrMask[1];
+ pseudo_bit_t _unused_2[1];
+ pseudo_bit_t SendUnexpectedPktNumErrMask[1];
+ pseudo_bit_t SendUnsupportedVLErrMask[1];
+ pseudo_bit_t SendBufMisuseErrMask[1];
+ pseudo_bit_t SDmaGenMismatchErrMask[1];
+ pseudo_bit_t SDmaOutOfBoundErrMask[1];
+ pseudo_bit_t SDmaTailOutOfBoundErrMask[1];
+ pseudo_bit_t SDmaBaseErrMask[1];
+ pseudo_bit_t SDma1stDescErrMask[1];
+ pseudo_bit_t SDmaRpyTagErrMask[1];
+ pseudo_bit_t SDmaDwEnErrMask[1];
+ pseudo_bit_t SDmaMissingDwErrMask[1];
+ pseudo_bit_t SDmaUnexpDataErrMask[1];
+ pseudo_bit_t SDmaDescAddrMisalignErrMask[1];
+ pseudo_bit_t SDmaHaltErrMask[1];
+ pseudo_bit_t _unused_3[4];
+ pseudo_bit_t VL15BufMisuseErrMask[1];
+ pseudo_bit_t _unused_4[2];
+ pseudo_bit_t SHeadersErrMask[1];
+ pseudo_bit_t IBStatusChangedMask[1];
+ pseudo_bit_t _unused_5[5];
+};
+struct QIB_7322_ErrMask_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ErrMask_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ErrStatus_1_offset 0x00002088UL
+struct QIB_7322_ErrStatus_1_pb {
+ pseudo_bit_t RcvFormatErr[1];
+ pseudo_bit_t RcvVCRCErr[1];
+ pseudo_bit_t RcvICRCErr[1];
+ pseudo_bit_t RcvMinPktLenErr[1];
+ pseudo_bit_t RcvMaxPktLenErr[1];
+ pseudo_bit_t RcvLongPktLenErr[1];
+ pseudo_bit_t RcvShortPktLenErr[1];
+ pseudo_bit_t RcvUnexpectedCharErr[1];
+ pseudo_bit_t RcvUnsupportedVLErr[1];
+ pseudo_bit_t RcvEBPErr[1];
+ pseudo_bit_t RcvIBFlowErr[1];
+ pseudo_bit_t RcvBadVersionErr[1];
+ pseudo_bit_t _unused_0[2];
+ pseudo_bit_t RcvBadTidErr[1];
+ pseudo_bit_t RcvHdrLenErr[1];
+ pseudo_bit_t RcvHdrErr[1];
+ pseudo_bit_t RcvIBLostLinkErr[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t SendMinPktLenErr[1];
+ pseudo_bit_t SendMaxPktLenErr[1];
+ pseudo_bit_t SendUnderRunErr[1];
+ pseudo_bit_t SendPktLenErr[1];
+ pseudo_bit_t SendDroppedSmpPktErr[1];
+ pseudo_bit_t SendDroppedDataPktErr[1];
+ pseudo_bit_t _unused_2[1];
+ pseudo_bit_t SendUnexpectedPktNumErr[1];
+ pseudo_bit_t SendUnsupportedVLErr[1];
+ pseudo_bit_t SendBufMisuseErr[1];
+ pseudo_bit_t SDmaGenMismatchErr[1];
+ pseudo_bit_t SDmaOutOfBoundErr[1];
+ pseudo_bit_t SDmaTailOutOfBoundErr[1];
+ pseudo_bit_t SDmaBaseErr[1];
+ pseudo_bit_t SDma1stDescErr[1];
+ pseudo_bit_t SDmaRpyTagErr[1];
+ pseudo_bit_t SDmaDwEnErr[1];
+ pseudo_bit_t SDmaMissingDwErr[1];
+ pseudo_bit_t SDmaUnexpDataErr[1];
+ pseudo_bit_t SDmaDescAddrMisalignErr[1];
+ pseudo_bit_t SDmaHaltErr[1];
+ pseudo_bit_t _unused_3[4];
+ pseudo_bit_t VL15BufMisuseErr[1];
+ pseudo_bit_t _unused_4[2];
+ pseudo_bit_t SHeadersErr[1];
+ pseudo_bit_t IBStatusChanged[1];
+ pseudo_bit_t _unused_5[5];
+};
+struct QIB_7322_ErrStatus_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ErrStatus_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ErrClear_1_offset 0x00002090UL
+struct QIB_7322_ErrClear_1_pb {
+ pseudo_bit_t RcvFormatErrClear[1];
+ pseudo_bit_t RcvVCRCErrClear[1];
+ pseudo_bit_t RcvICRCErrClear[1];
+ pseudo_bit_t RcvMinPktLenErrClear[1];
+ pseudo_bit_t RcvMaxPktLenErrClear[1];
+ pseudo_bit_t RcvLongPktLenErrClear[1];
+ pseudo_bit_t RcvShortPktLenErrClear[1];
+ pseudo_bit_t RcvUnexpectedCharErrClear[1];
+ pseudo_bit_t RcvUnsupportedVLErrClear[1];
+ pseudo_bit_t RcvEBPErrClear[1];
+ pseudo_bit_t RcvIBFlowErrClear[1];
+ pseudo_bit_t RcvBadVersionErrClear[1];
+ pseudo_bit_t _unused_0[2];
+ pseudo_bit_t RcvBadTidErrClear[1];
+ pseudo_bit_t RcvHdrLenErrClear[1];
+ pseudo_bit_t RcvHdrErrClear[1];
+ pseudo_bit_t RcvIBLostLinkErrClear[1];
+ pseudo_bit_t _unused_1[11];
+ pseudo_bit_t SendMinPktLenErrClear[1];
+ pseudo_bit_t SendMaxPktLenErrClear[1];
+ pseudo_bit_t SendUnderRunErrClear[1];
+ pseudo_bit_t SendPktLenErrClear[1];
+ pseudo_bit_t SendDroppedSmpPktErrClear[1];
+ pseudo_bit_t SendDroppedDataPktErrClear[1];
+ pseudo_bit_t _unused_2[1];
+ pseudo_bit_t SendUnexpectedPktNumErrClear[1];
+ pseudo_bit_t SendUnsupportedVLErrClear[1];
+ pseudo_bit_t SendBufMisuseErrClear[1];
+ pseudo_bit_t SDmaGenMismatchErrClear[1];
+ pseudo_bit_t SDmaOutOfBoundErrClear[1];
+ pseudo_bit_t SDmaTailOutOfBoundErrClear[1];
+ pseudo_bit_t SDmaBaseErrClear[1];
+ pseudo_bit_t SDma1stDescErrClear[1];
+ pseudo_bit_t SDmaRpyTagErrClear[1];
+ pseudo_bit_t SDmaDwEnErrClear[1];
+ pseudo_bit_t SDmaMissingDwErrClear[1];
+ pseudo_bit_t SDmaUnexpDataErrClear[1];
+ pseudo_bit_t SDmaDescAddrMisalignErrClear[1];
+ pseudo_bit_t SDmaHaltErrClear[1];
+ pseudo_bit_t _unused_3[4];
+ pseudo_bit_t VL15BufMisuseErrClear[1];
+ pseudo_bit_t _unused_4[2];
+ pseudo_bit_t SHeadersErrClear[1];
+ pseudo_bit_t IBStatusChangedClear[1];
+ pseudo_bit_t _unused_5[5];
+};
+struct QIB_7322_ErrClear_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ErrClear_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TXEStatus_1_offset 0x000020b8UL
+struct QIB_7322_TXEStatus_1_pb {
+ pseudo_bit_t LaFifoEmpty_VL0[1];
+ pseudo_bit_t LaFifoEmpty_VL1[1];
+ pseudo_bit_t LaFifoEmpty_VL2[1];
+ pseudo_bit_t LaFifoEmpty_VL3[1];
+ pseudo_bit_t LaFifoEmpty_VL4[1];
+ pseudo_bit_t LaFifoEmpty_VL5[1];
+ pseudo_bit_t LaFifoEmpty_VL6[1];
+ pseudo_bit_t LaFifoEmpty_VL7[1];
+ pseudo_bit_t _unused_0[7];
+ pseudo_bit_t LaFifoEmpty_VL15[1];
+ pseudo_bit_t _unused_1[14];
+ pseudo_bit_t RmFifoEmpty[1];
+ pseudo_bit_t TXE_IBC_Idle[1];
+ pseudo_bit_t _unused_2[32];
+};
+struct QIB_7322_TXEStatus_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_TXEStatus_1_pb );
+};
+/* Default value: 0x0000000XC00080FF */
+
+#define QIB_7322_RcvCtrl_1_offset 0x00002100UL
+struct QIB_7322_RcvCtrl_1_pb {
+ pseudo_bit_t _unused_0[1];
+ pseudo_bit_t ContextEnableKernel[1];
+ pseudo_bit_t ContextEnableUser[16];
+ pseudo_bit_t _unused_1[21];
+ pseudo_bit_t RcvIBPortEnable[1];
+ pseudo_bit_t RcvQPMapEnable[1];
+ pseudo_bit_t RcvPartitionKeyDisable[1];
+ pseudo_bit_t RcvResetCredit[1];
+ pseudo_bit_t _unused_2[21];
+};
+struct QIB_7322_RcvCtrl_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvCtrl_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvBTHQP_1_offset 0x00002108UL
+struct QIB_7322_RcvBTHQP_1_pb {
+ pseudo_bit_t RcvBTHQP[24];
+ pseudo_bit_t _unused_0[40];
+};
+struct QIB_7322_RcvBTHQP_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvBTHQP_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMapTableA_1_offset 0x00002110UL
+struct QIB_7322_RcvQPMapTableA_1_pb {
+ pseudo_bit_t RcvQPMapContext0[5];
+ pseudo_bit_t RcvQPMapContext1[5];
+ pseudo_bit_t RcvQPMapContext2[5];
+ pseudo_bit_t RcvQPMapContext3[5];
+ pseudo_bit_t RcvQPMapContext4[5];
+ pseudo_bit_t RcvQPMapContext5[5];
+ pseudo_bit_t _unused_0[34];
+};
+struct QIB_7322_RcvQPMapTableA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMapTableA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMapTableB_1_offset 0x00002118UL
+struct QIB_7322_RcvQPMapTableB_1_pb {
+ pseudo_bit_t RcvQPMapContext6[5];
+ pseudo_bit_t RcvQPMapContext7[5];
+ pseudo_bit_t RcvQPMapContext8[5];
+ pseudo_bit_t RcvQPMapContext9[5];
+ pseudo_bit_t RcvQPMapContext10[5];
+ pseudo_bit_t RcvQPMapContext11[5];
+ pseudo_bit_t _unused_0[34];
+};
+struct QIB_7322_RcvQPMapTableB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMapTableB_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMapTableC_1_offset 0x00002120UL
+struct QIB_7322_RcvQPMapTableC_1_pb {
+ pseudo_bit_t RcvQPMapContext12[5];
+ pseudo_bit_t RcvQPMapContext13[5];
+ pseudo_bit_t RcvQPMapContext14[5];
+ pseudo_bit_t RcvQPMapContext15[5];
+ pseudo_bit_t RcvQPMapContext16[5];
+ pseudo_bit_t RcvQPMapContext17[5];
+ pseudo_bit_t _unused_0[34];
+};
+struct QIB_7322_RcvQPMapTableC_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMapTableC_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMapTableD_1_offset 0x00002128UL
+struct QIB_7322_RcvQPMapTableD_1_pb {
+ pseudo_bit_t RcvQPMapContext18[5];
+ pseudo_bit_t RcvQPMapContext19[5];
+ pseudo_bit_t RcvQPMapContext20[5];
+ pseudo_bit_t RcvQPMapContext21[5];
+ pseudo_bit_t RcvQPMapContext22[5];
+ pseudo_bit_t RcvQPMapContext23[5];
+ pseudo_bit_t _unused_0[34];
+};
+struct QIB_7322_RcvQPMapTableD_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMapTableD_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMapTableE_1_offset 0x00002130UL
+struct QIB_7322_RcvQPMapTableE_1_pb {
+ pseudo_bit_t RcvQPMapContext24[5];
+ pseudo_bit_t RcvQPMapContext25[5];
+ pseudo_bit_t RcvQPMapContext26[5];
+ pseudo_bit_t RcvQPMapContext27[5];
+ pseudo_bit_t RcvQPMapContext28[5];
+ pseudo_bit_t RcvQPMapContext29[5];
+ pseudo_bit_t _unused_0[34];
+};
+struct QIB_7322_RcvQPMapTableE_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMapTableE_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMapTableF_1_offset 0x00002138UL
+struct QIB_7322_RcvQPMapTableF_1_pb {
+ pseudo_bit_t RcvQPMapContext30[5];
+ pseudo_bit_t RcvQPMapContext31[5];
+ pseudo_bit_t _unused_0[54];
+};
+struct QIB_7322_RcvQPMapTableF_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMapTableF_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSStat_1_offset 0x00002140UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSStart_1_offset 0x00002148UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSInterval_1_offset 0x00002150UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvStatus_1_offset 0x00002160UL
+struct QIB_7322_RcvStatus_1_pb {
+ pseudo_bit_t RxPktInProgress[1];
+ pseudo_bit_t DmaeqBlockingContext[5];
+ pseudo_bit_t _unused_0[58];
+};
+struct QIB_7322_RcvStatus_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvStatus_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvPartitionKey_1_offset 0x00002168UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvQPMulticastContext_1_offset 0x00002170UL
+struct QIB_7322_RcvQPMulticastContext_1_pb {
+ pseudo_bit_t RcvQpMcContext[5];
+ pseudo_bit_t _unused_0[59];
+};
+struct QIB_7322_RcvQPMulticastContext_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvQPMulticastContext_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvPktLEDCnt_1_offset 0x00002178UL
+struct QIB_7322_RcvPktLEDCnt_1_pb {
+ pseudo_bit_t OFFperiod[32];
+ pseudo_bit_t ONperiod[32];
+};
+struct QIB_7322_RcvPktLEDCnt_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvPktLEDCnt_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaIdleCnt_1_offset 0x00002180UL
+struct QIB_7322_SendDmaIdleCnt_1_pb {
+ pseudo_bit_t SendDmaIdleCnt[16];
+ pseudo_bit_t _unused_0[48];
+};
+struct QIB_7322_SendDmaIdleCnt_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaIdleCnt_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaReloadCnt_1_offset 0x00002188UL
+struct QIB_7322_SendDmaReloadCnt_1_pb {
+ pseudo_bit_t SendDmaReloadCnt[16];
+ pseudo_bit_t _unused_0[48];
+};
+struct QIB_7322_SendDmaReloadCnt_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaReloadCnt_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaDescCnt_1_offset 0x00002190UL
+struct QIB_7322_SendDmaDescCnt_1_pb {
+ pseudo_bit_t SendDmaDescCnt[16];
+ pseudo_bit_t _unused_0[48];
+};
+struct QIB_7322_SendDmaDescCnt_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaDescCnt_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendCtrl_1_offset 0x000021c0UL
+struct QIB_7322_SendCtrl_1_pb {
+ pseudo_bit_t TxeAbortIbc[1];
+ pseudo_bit_t TxeBypassIbc[1];
+ pseudo_bit_t _unused_0[1];
+ pseudo_bit_t SendEnable[1];
+ pseudo_bit_t _unused_1[3];
+ pseudo_bit_t ForceCreditUpToDate[1];
+ pseudo_bit_t SDmaCleanup[1];
+ pseudo_bit_t SDmaIntEnable[1];
+ pseudo_bit_t SDmaSingleDescriptor[1];
+ pseudo_bit_t SDmaEnable[1];
+ pseudo_bit_t SDmaHalt[1];
+ pseudo_bit_t TxeDrainLaFifo[1];
+ pseudo_bit_t TxeDrainRmFifo[1];
+ pseudo_bit_t IBVLArbiterEn[1];
+ pseudo_bit_t _unused_2[48];
+};
+struct QIB_7322_SendCtrl_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendCtrl_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaBase_1_offset 0x000021f8UL
+struct QIB_7322_SendDmaBase_1_pb {
+ pseudo_bit_t SendDmaBase[48];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_SendDmaBase_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaBase_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaLenGen_1_offset 0x00002200UL
+struct QIB_7322_SendDmaLenGen_1_pb {
+ pseudo_bit_t Length[16];
+ pseudo_bit_t Generation[3];
+ pseudo_bit_t _unused_0[45];
+};
+struct QIB_7322_SendDmaLenGen_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaLenGen_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaTail_1_offset 0x00002208UL
+struct QIB_7322_SendDmaTail_1_pb {
+ pseudo_bit_t SendDmaTail[16];
+ pseudo_bit_t _unused_0[48];
+};
+struct QIB_7322_SendDmaTail_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaTail_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaHead_1_offset 0x00002210UL
+struct QIB_7322_SendDmaHead_1_pb {
+ pseudo_bit_t SendDmaHead[16];
+ pseudo_bit_t _unused_0[16];
+ pseudo_bit_t InternalSendDmaHead[16];
+ pseudo_bit_t _unused_1[16];
+};
+struct QIB_7322_SendDmaHead_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaHead_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaHeadAddr_1_offset 0x00002218UL
+struct QIB_7322_SendDmaHeadAddr_1_pb {
+ pseudo_bit_t SendDmaHeadAddr[48];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_SendDmaHeadAddr_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaHeadAddr_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaBufMask0_1_offset 0x00002220UL
+struct QIB_7322_SendDmaBufMask0_1_pb {
+ pseudo_bit_t BufMask_63_0[64];
+};
+struct QIB_7322_SendDmaBufMask0_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaBufMask0_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaStatus_1_offset 0x00002238UL
+struct QIB_7322_SendDmaStatus_1_pb {
+ pseudo_bit_t SplFifoDescIndex[16];
+ pseudo_bit_t SplFifoBufNum[8];
+ pseudo_bit_t SplFifoFull[1];
+ pseudo_bit_t SplFifoEmpty[1];
+ pseudo_bit_t SplFifoDisarmed[1];
+ pseudo_bit_t SplFifoReadyToGo[1];
+ pseudo_bit_t ScbFetchDescFlag[1];
+ pseudo_bit_t ScbEntryValid[1];
+ pseudo_bit_t ScbEmpty[1];
+ pseudo_bit_t ScbFull[1];
+ pseudo_bit_t RpyTag_7_0[8];
+ pseudo_bit_t RpyLowAddr_6_0[7];
+ pseudo_bit_t ScbDescIndex_13_0[14];
+ pseudo_bit_t InternalSDmaHalt[1];
+ pseudo_bit_t HaltInProg[1];
+ pseudo_bit_t ScoreBoardDrainInProg[1];
+};
+struct QIB_7322_SendDmaStatus_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaStatus_1_pb );
+};
+/* Default value: 0x0000000042000000 */
+
+#define QIB_7322_SendDmaPriorityThld_1_offset 0x00002258UL
+struct QIB_7322_SendDmaPriorityThld_1_pb {
+ pseudo_bit_t PriorityThreshold[4];
+ pseudo_bit_t _unused_0[60];
+};
+struct QIB_7322_SendDmaPriorityThld_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaPriorityThld_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendHdrErrSymptom_1_offset 0x00002260UL
+struct QIB_7322_SendHdrErrSymptom_1_pb {
+ pseudo_bit_t PacketTooSmall[1];
+ pseudo_bit_t RawIPV6[1];
+ pseudo_bit_t SLIDFail[1];
+ pseudo_bit_t QPFail[1];
+ pseudo_bit_t PkeyFail[1];
+ pseudo_bit_t GRHFail[1];
+ pseudo_bit_t NonKeyPacket[1];
+ pseudo_bit_t _unused_0[57];
+};
+struct QIB_7322_SendHdrErrSymptom_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendHdrErrSymptom_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxCreditVL0_1_offset 0x00002280UL
+struct QIB_7322_RxCreditVL0_1_pb {
+ pseudo_bit_t RxMaxCreditVL[12];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t RxBufrConsumedVL[12];
+ pseudo_bit_t _unused_1[36];
+};
+struct QIB_7322_RxCreditVL0_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxCreditVL0_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaBufUsed0_1_offset 0x00002480UL
+struct QIB_7322_SendDmaBufUsed0_1_pb {
+ pseudo_bit_t BufUsed_63_0[64];
+};
+struct QIB_7322_SendDmaBufUsed0_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaBufUsed0_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendDmaReqTagUsed_1_offset 0x00002498UL
+struct QIB_7322_SendDmaReqTagUsed_1_pb {
+ pseudo_bit_t ReqTagUsed_7_0[8];
+ pseudo_bit_t _unused_0[56];
+};
+struct QIB_7322_SendDmaReqTagUsed_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendDmaReqTagUsed_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendCheckControl_1_offset 0x000024a8UL
+struct QIB_7322_SendCheckControl_1_pb {
+ pseudo_bit_t PacketTooSmall_En[1];
+ pseudo_bit_t RawIPV6_En[1];
+ pseudo_bit_t SLID_En[1];
+ pseudo_bit_t BTHQP_En[1];
+ pseudo_bit_t PKey_En[1];
+ pseudo_bit_t _unused_0[59];
+};
+struct QIB_7322_SendCheckControl_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendCheckControl_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendIBSLIDMask_1_offset 0x000024b0UL
+struct QIB_7322_SendIBSLIDMask_1_pb {
+ pseudo_bit_t SendIBSLIDMask_15_0[16];
+ pseudo_bit_t _unused_0[48];
+};
+struct QIB_7322_SendIBSLIDMask_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendIBSLIDMask_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendIBSLIDAssign_1_offset 0x000024b8UL
+struct QIB_7322_SendIBSLIDAssign_1_pb {
+ pseudo_bit_t SendIBSLIDAssign_15_0[16];
+ pseudo_bit_t _unused_0[48];
+};
+struct QIB_7322_SendIBSLIDAssign_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendIBSLIDAssign_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBCStatusA_1_offset 0x00002540UL
+struct QIB_7322_IBCStatusA_1_pb {
+ pseudo_bit_t LinkTrainingState[5];
+ pseudo_bit_t LinkState[3];
+ pseudo_bit_t LinkSpeedActive[1];
+ pseudo_bit_t LinkWidthActive[1];
+ pseudo_bit_t DDS_RXEQ_FAIL[1];
+ pseudo_bit_t _unused_0[1];
+ pseudo_bit_t IBRxLaneReversed[1];
+ pseudo_bit_t IBTxLaneReversed[1];
+ pseudo_bit_t ScrambleEn[1];
+ pseudo_bit_t ScrambleCapRemote[1];
+ pseudo_bit_t _unused_1[13];
+ pseudo_bit_t LinkSpeedQDR[1];
+ pseudo_bit_t TxReady[1];
+ pseudo_bit_t _unused_2[1];
+ pseudo_bit_t TxCreditOk_VL0[1];
+ pseudo_bit_t TxCreditOk_VL1[1];
+ pseudo_bit_t TxCreditOk_VL2[1];
+ pseudo_bit_t TxCreditOk_VL3[1];
+ pseudo_bit_t TxCreditOk_VL4[1];
+ pseudo_bit_t TxCreditOk_VL5[1];
+ pseudo_bit_t TxCreditOk_VL6[1];
+ pseudo_bit_t TxCreditOk_VL7[1];
+ pseudo_bit_t _unused_3[24];
+};
+struct QIB_7322_IBCStatusA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBCStatusA_1_pb );
+};
+/* Default value: 0x0000000000000X02 */
+
+#define QIB_7322_IBCStatusB_1_offset 0x00002548UL
+struct QIB_7322_IBCStatusB_1_pb {
+ pseudo_bit_t LinkRoundTripLatency[26];
+ pseudo_bit_t ReqDDSLocalFromRmt[4];
+ pseudo_bit_t RxEqLocalDevice[2];
+ pseudo_bit_t heartbeat_crosstalk[4];
+ pseudo_bit_t heartbeat_timed_out[1];
+ pseudo_bit_t _unused_0[27];
+};
+struct QIB_7322_IBCStatusB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBCStatusB_1_pb );
+};
+/* Default value: 0x00000000XXXXXXXX */
+
+#define QIB_7322_IBCCtrlA_1_offset 0x00002560UL
+struct QIB_7322_IBCCtrlA_1_pb {
+ pseudo_bit_t FlowCtrlPeriod[8];
+ pseudo_bit_t FlowCtrlWaterMark[8];
+ pseudo_bit_t LinkInitCmd[3];
+ pseudo_bit_t LinkCmd[2];
+ pseudo_bit_t MaxPktLen[11];
+ pseudo_bit_t PhyerrThreshold[4];
+ pseudo_bit_t OverrunThreshold[4];
+ pseudo_bit_t _unused_0[8];
+ pseudo_bit_t NumVLane[3];
+ pseudo_bit_t _unused_1[9];
+ pseudo_bit_t IBStatIntReductionEn[1];
+ pseudo_bit_t IBLinkEn[1];
+ pseudo_bit_t LinkDownDefaultState[1];
+ pseudo_bit_t Loopback[1];
+};
+struct QIB_7322_IBCCtrlA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBCCtrlA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBCCtrlB_1_offset 0x00002568UL
+struct QIB_7322_IBCCtrlB_1_pb {
+ pseudo_bit_t IB_ENHANCED_MODE[1];
+ pseudo_bit_t SD_SPEED[1];
+ pseudo_bit_t SD_SPEED_SDR[1];
+ pseudo_bit_t SD_SPEED_DDR[1];
+ pseudo_bit_t SD_SPEED_QDR[1];
+ pseudo_bit_t IB_NUM_CHANNELS[2];
+ pseudo_bit_t IB_POLARITY_REV_SUPP[1];
+ pseudo_bit_t IB_LANE_REV_SUPPORTED[1];
+ pseudo_bit_t SD_RX_EQUAL_ENABLE[1];
+ pseudo_bit_t SD_ADD_ENB[1];
+ pseudo_bit_t SD_DDSV[1];
+ pseudo_bit_t SD_DDS[4];
+ pseudo_bit_t HRTBT_ENB[1];
+ pseudo_bit_t HRTBT_AUTO[1];
+ pseudo_bit_t HRTBT_PORT[8];
+ pseudo_bit_t HRTBT_REQ[1];
+ pseudo_bit_t IB_ENABLE_FILT_DPKT[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t IB_DLID[16];
+ pseudo_bit_t IB_DLID_MASK[16];
+};
+struct QIB_7322_IBCCtrlB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBCCtrlB_1_pb );
+};
+/* Default value: 0x00000000000305FF */
+
+#define QIB_7322_IBCCtrlC_1_offset 0x00002570UL
+struct QIB_7322_IBCCtrlC_1_pb {
+ pseudo_bit_t IB_FRONT_PORCH[5];
+ pseudo_bit_t IB_BACK_PORCH[5];
+ pseudo_bit_t _unused_0[54];
+};
+struct QIB_7322_IBCCtrlC_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBCCtrlC_1_pb );
+};
+/* Default value: 0x0000000000000301 */
+
+#define QIB_7322_HRTBT_GUID_1_offset 0x00002588UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IB_SDTEST_IF_TX_1_offset 0x00002590UL
+struct QIB_7322_IB_SDTEST_IF_TX_1_pb {
+ pseudo_bit_t TS_T_TX_VALID[1];
+ pseudo_bit_t TS_3_TX_VALID[1];
+ pseudo_bit_t VL_CAP[2];
+ pseudo_bit_t CREDIT_CHANGE[1];
+ pseudo_bit_t _unused_0[6];
+ pseudo_bit_t TS_TX_OPCODE[2];
+ pseudo_bit_t TS_TX_SPEED[3];
+ pseudo_bit_t _unused_1[16];
+ pseudo_bit_t TS_TX_TX_CFG[16];
+ pseudo_bit_t TS_TX_RX_CFG[16];
+};
+struct QIB_7322_IB_SDTEST_IF_TX_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IB_SDTEST_IF_TX_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IB_SDTEST_IF_RX_1_offset 0x00002598UL
+struct QIB_7322_IB_SDTEST_IF_RX_1_pb {
+ pseudo_bit_t TS_T_RX_VALID[1];
+ pseudo_bit_t TS_3_RX_VALID[1];
+ pseudo_bit_t _unused_0[14];
+ pseudo_bit_t TS_RX_A[8];
+ pseudo_bit_t TS_RX_B[8];
+ pseudo_bit_t TS_RX_TX_CFG[16];
+ pseudo_bit_t TS_RX_RX_CFG[16];
+};
+struct QIB_7322_IB_SDTEST_IF_RX_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IB_SDTEST_IF_RX_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBNCModeCtrl_1_offset 0x000025b8UL
+struct QIB_7322_IBNCModeCtrl_1_pb {
+ pseudo_bit_t TSMEnable_send_TS1[1];
+ pseudo_bit_t TSMEnable_send_TS2[1];
+ pseudo_bit_t TSMEnable_ignore_TSM_on_rx[1];
+ pseudo_bit_t _unused_0[5];
+ pseudo_bit_t TSMCode_TS1[9];
+ pseudo_bit_t TSMCode_TS2[9];
+ pseudo_bit_t _unused_1[6];
+ pseudo_bit_t ScrambleCapLocal[1];
+ pseudo_bit_t ScrambleCapRemoteMask[1];
+ pseudo_bit_t ScrambleCapRemoteForce[1];
+ pseudo_bit_t _unused_2[29];
+};
+struct QIB_7322_IBNCModeCtrl_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBNCModeCtrl_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBSerdesStatus_1_offset 0x000025d0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBPCSConfig_1_offset 0x000025d8UL
+struct QIB_7322_IBPCSConfig_1_pb {
+ pseudo_bit_t tx_rx_reset[1];
+ pseudo_bit_t xcv_treset[1];
+ pseudo_bit_t xcv_rreset[1];
+ pseudo_bit_t _unused_0[6];
+ pseudo_bit_t link_sync_mask[10];
+ pseudo_bit_t _unused_1[45];
+};
+struct QIB_7322_IBPCSConfig_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBPCSConfig_1_pb );
+};
+/* Default value: 0x0000000000000007 */
+
+#define QIB_7322_IBSerdesCtrl_1_offset 0x000025e0UL
+struct QIB_7322_IBSerdesCtrl_1_pb {
+ pseudo_bit_t CMODE[7];
+ pseudo_bit_t _unused_0[1];
+ pseudo_bit_t TXIDLE[1];
+ pseudo_bit_t RXPD[1];
+ pseudo_bit_t TXPD[1];
+ pseudo_bit_t PLLPD[1];
+ pseudo_bit_t LPEN[1];
+ pseudo_bit_t RXLOSEN[1];
+ pseudo_bit_t _unused_1[1];
+ pseudo_bit_t IB_LAT_MODE[1];
+ pseudo_bit_t CGMODE[4];
+ pseudo_bit_t CHANNEL_RESET_N[4];
+ pseudo_bit_t DISABLE_RXLATOFF_SDR[1];
+ pseudo_bit_t DISABLE_RXLATOFF_DDR[1];
+ pseudo_bit_t DISABLE_RXLATOFF_QDR[1];
+ pseudo_bit_t _unused_2[37];
+};
+struct QIB_7322_IBSerdesCtrl_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBSerdesCtrl_1_pb );
+};
+/* Default value: 0x0000000000FFA00F */
+
+#define QIB_7322_IBSD_TX_DEEMPHASIS_OVERRIDE_1_offset 0x00002600UL
+struct QIB_7322_IBSD_TX_DEEMPHASIS_OVERRIDE_1_pb {
+ pseudo_bit_t txcn1_ena[3];
+ pseudo_bit_t txcn1_xtra_emph0[2];
+ pseudo_bit_t txcp1_ena[4];
+ pseudo_bit_t txc0_ena[5];
+ pseudo_bit_t txampcntl_d2a[4];
+ pseudo_bit_t _unused_0[12];
+ pseudo_bit_t reset_tx_deemphasis_override[1];
+ pseudo_bit_t tx_override_deemphasis_select[1];
+ pseudo_bit_t _unused_1[32];
+};
+struct QIB_7322_IBSD_TX_DEEMPHASIS_OVERRIDE_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_IBSD_TX_DEEMPHASIS_OVERRIDE_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_STATIC_SDR_1_offset 0x00002640UL
+struct QIB_7322_ADAPT_DISABLE_STATIC_SDR_1_pb {
+ pseudo_bit_t static_disable_rxenadfe_sdr_ch0[8];
+ pseudo_bit_t static_disable_rxenadfe_sdr_ch1[8];
+ pseudo_bit_t static_disable_rxenadfe_sdr_ch2[8];
+ pseudo_bit_t static_disable_rxenadfe_sdr_ch3[8];
+ pseudo_bit_t static_disable_rxenale_sdr_ch0[1];
+ pseudo_bit_t static_disable_rxenale_sdr_ch1[1];
+ pseudo_bit_t static_disable_rxenale_sdr_ch2[1];
+ pseudo_bit_t static_disable_rxenale_sdr_ch3[1];
+ pseudo_bit_t static_disable_rxenagain_sdr_ch0[1];
+ pseudo_bit_t static_disable_rxenagain_sdr_ch1[1];
+ pseudo_bit_t static_disable_rxenagain_sdr_ch2[1];
+ pseudo_bit_t static_disable_rxenagain_sdr_ch3[1];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_ADAPT_DISABLE_STATIC_SDR_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ADAPT_DISABLE_STATIC_SDR_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_DYNAMIC_SDR_1_offset 0x00002648UL
+struct QIB_7322_ADAPT_DISABLE_DYNAMIC_SDR_1_pb {
+ pseudo_bit_t dyn_disable_rxenadfe_sdr_ch0[8];
+ pseudo_bit_t dyn_disable_rxenadfe_sdr_ch1[8];
+ pseudo_bit_t dyn_disable_rxenadfe_sdr_ch2[8];
+ pseudo_bit_t dyn_disable_rxenadfe_sdr_ch3[8];
+ pseudo_bit_t dyn_disable_rxenale_sdr_ch0[1];
+ pseudo_bit_t dyn_disable_rxenale_sdr_ch1[1];
+ pseudo_bit_t dyn_disable_rxenale_sdr_ch2[1];
+ pseudo_bit_t dyn_disable_rxenale_sdr_ch3[1];
+ pseudo_bit_t dyn_disable_rxenagain_sdr_ch0[1];
+ pseudo_bit_t dyn_disable_rxenagain_sdr_ch1[1];
+ pseudo_bit_t dyn_disable_rxenagain_sdr_ch2[1];
+ pseudo_bit_t dyn_disable_rxenagain_sdr_ch3[1];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_ADAPT_DISABLE_DYNAMIC_SDR_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ADAPT_DISABLE_DYNAMIC_SDR_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_STATIC_DDR_1_offset 0x00002650UL
+struct QIB_7322_ADAPT_DISABLE_STATIC_DDR_1_pb {
+ pseudo_bit_t static_disable_rxenadfe_ddr_ch0[8];
+ pseudo_bit_t static_disable_rxenadfe_ddr_ch1[8];
+ pseudo_bit_t static_disable_rxenadfe_ddr_ch2[8];
+ pseudo_bit_t static_disable_rxenadfe_ddr_ch3[8];
+ pseudo_bit_t static_disable_rxenale_ddr_ch0[1];
+ pseudo_bit_t static_disable_rxenale_ddr_ch1[1];
+ pseudo_bit_t static_disable_rxenale_ddr_ch2[1];
+ pseudo_bit_t static_disable_rxenale_ddr_ch3[1];
+ pseudo_bit_t static_disable_rxenagain_ddr_ch0[1];
+ pseudo_bit_t static_disable_rxenagain_ddr_ch1[1];
+ pseudo_bit_t static_disable_rxenagain_ddr_ch2[1];
+ pseudo_bit_t static_disable_rxenagain_ddr_ch3[1];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_ADAPT_DISABLE_STATIC_DDR_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ADAPT_DISABLE_STATIC_DDR_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_DYNAMIC_DDR_1_offset 0x00002658UL
+struct QIB_7322_ADAPT_DISABLE_DYNAMIC_DDR_1_pb {
+ pseudo_bit_t dyn_disable_rxenadfe_ddr_ch0[8];
+ pseudo_bit_t dyn_disable_rxenadfe_ddr_ch1[8];
+ pseudo_bit_t dyn_disable_rxenadfe_ddr_ch2[8];
+ pseudo_bit_t dyn_disable_rxenadfe_ddr_ch3[8];
+ pseudo_bit_t dyn_disable_rxenale_ddr_ch0[1];
+ pseudo_bit_t dyn_disable_rxenale_ddr_ch1[1];
+ pseudo_bit_t dyn_disable_rxenale_ddr_ch2[1];
+ pseudo_bit_t dyn_disable_rxenale_ddr_ch3[1];
+ pseudo_bit_t dyn_disable_rxenagain_ddr_ch0[1];
+ pseudo_bit_t dyn_disable_rxenagain_ddr_ch1[1];
+ pseudo_bit_t dyn_disable_rxenagain_ddr_ch2[1];
+ pseudo_bit_t dyn_disable_rxenagain_ddr_ch3[1];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_ADAPT_DISABLE_DYNAMIC_DDR_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ADAPT_DISABLE_DYNAMIC_DDR_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_STATIC_QDR_1_offset 0x00002660UL
+struct QIB_7322_ADAPT_DISABLE_STATIC_QDR_1_pb {
+ pseudo_bit_t static_disable_rxenadfe_qdr_ch0[8];
+ pseudo_bit_t static_disable_rxenadfe_qdr_ch1[8];
+ pseudo_bit_t static_disable_rxenadfe_qdr_ch2[8];
+ pseudo_bit_t static_disable_rxenadfe_qdr_ch3[8];
+ pseudo_bit_t static_disable_rxenale_qdr_ch0[1];
+ pseudo_bit_t static_disable_rxenale_qdr_ch1[1];
+ pseudo_bit_t static_disable_rxenale_qdr_ch2[1];
+ pseudo_bit_t static_disable_rxenale_qdr_ch3[1];
+ pseudo_bit_t static_disable_rxenagain_qdr_ch0[1];
+ pseudo_bit_t static_disable_rxenagain_qdr_ch1[1];
+ pseudo_bit_t static_disable_rxenagain_qdr_ch2[1];
+ pseudo_bit_t static_disable_rxenagain_qdr_ch3[1];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_ADAPT_DISABLE_STATIC_QDR_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ADAPT_DISABLE_STATIC_QDR_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_DYNAMIC_QDR_1_offset 0x00002668UL
+struct QIB_7322_ADAPT_DISABLE_DYNAMIC_QDR_1_pb {
+ pseudo_bit_t dyn_disable_rxenadfe_qdr_ch0[8];
+ pseudo_bit_t dyn_disable_rxenadfe_qdr_ch1[8];
+ pseudo_bit_t dyn_disable_rxenadfe_qdr_ch2[8];
+ pseudo_bit_t dyn_disable_rxenadfe_qdr_ch3[8];
+ pseudo_bit_t dyn_disable_rxenale_qdr_ch0[1];
+ pseudo_bit_t dyn_disable_rxenale_qdr_ch1[1];
+ pseudo_bit_t dyn_disable_rxenale_qdr_ch2[1];
+ pseudo_bit_t dyn_disable_rxenale_qdr_ch3[1];
+ pseudo_bit_t dyn_disable_rxenagain_qdr_ch0[1];
+ pseudo_bit_t dyn_disable_rxenagain_qdr_ch1[1];
+ pseudo_bit_t dyn_disable_rxenagain_qdr_ch2[1];
+ pseudo_bit_t dyn_disable_rxenagain_qdr_ch3[1];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_ADAPT_DISABLE_DYNAMIC_QDR_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_ADAPT_DISABLE_DYNAMIC_QDR_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ADAPT_DISABLE_TIMER_THRESHOLD_1_offset 0x00002670UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrUnCorErrLogA_1_offset 0x00002800UL
+struct QIB_7322_RxBufrUnCorErrLogA_1_pb {
+ pseudo_bit_t RxBufrUnCorErrData_63_0[64];
+};
+struct QIB_7322_RxBufrUnCorErrLogA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrUnCorErrLogA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrUnCorErrLogB_1_offset 0x00002808UL
+struct QIB_7322_RxBufrUnCorErrLogB_1_pb {
+ pseudo_bit_t RxBufrUnCorErrData_127_64[64];
+};
+struct QIB_7322_RxBufrUnCorErrLogB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrUnCorErrLogB_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrUnCorErrLogC_1_offset 0x00002810UL
+struct QIB_7322_RxBufrUnCorErrLogC_1_pb {
+ pseudo_bit_t RxBufrUnCorErrData_191_128[64];
+};
+struct QIB_7322_RxBufrUnCorErrLogC_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrUnCorErrLogC_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrUnCorErrLogD_1_offset 0x00002818UL
+struct QIB_7322_RxBufrUnCorErrLogD_1_pb {
+ pseudo_bit_t RxBufrUnCorErrData_255_192[64];
+};
+struct QIB_7322_RxBufrUnCorErrLogD_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrUnCorErrLogD_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrUnCorErrLogE_1_offset 0x00002820UL
+struct QIB_7322_RxBufrUnCorErrLogE_1_pb {
+ pseudo_bit_t RxBufrUnCorErrData_258_256[3];
+ pseudo_bit_t RxBufrUnCorErrCheckBit_36_0[37];
+ pseudo_bit_t RxBufrUnCorErrAddr_15_0[16];
+ pseudo_bit_t _unused_0[8];
+};
+struct QIB_7322_RxBufrUnCorErrLogE_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrUnCorErrLogE_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxFlagUnCorErrLogA_1_offset 0x00002828UL
+struct QIB_7322_RxFlagUnCorErrLogA_1_pb {
+ pseudo_bit_t RxFlagUnCorErrData_63_0[64];
+};
+struct QIB_7322_RxFlagUnCorErrLogA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxFlagUnCorErrLogA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxFlagUnCorErrLogB_1_offset 0x00002830UL
+struct QIB_7322_RxFlagUnCorErrLogB_1_pb {
+ pseudo_bit_t RxFlagUnCorErrCheckBit_7_0[8];
+ pseudo_bit_t RxFlagUnCorErrAddr_12_0[13];
+ pseudo_bit_t _unused_0[43];
+};
+struct QIB_7322_RxFlagUnCorErrLogB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxFlagUnCorErrLogB_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLkupiqUnCorErrLogA_1_offset 0x00002840UL
+struct QIB_7322_RxLkupiqUnCorErrLogA_1_pb {
+ pseudo_bit_t RxLkupiqUnCorErrData_45_0[46];
+ pseudo_bit_t RxLkupiqUnCorErrCheckBit_7_0[8];
+ pseudo_bit_t _unused_0[10];
+};
+struct QIB_7322_RxLkupiqUnCorErrLogA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxLkupiqUnCorErrLogA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLkupiqUnCorErrLogB_1_offset 0x00002848UL
+struct QIB_7322_RxLkupiqUnCorErrLogB_1_pb {
+ pseudo_bit_t RxLkupiqUnCorErrAddr_12_0[13];
+ pseudo_bit_t _unused_0[51];
+};
+struct QIB_7322_RxLkupiqUnCorErrLogB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxLkupiqUnCorErrLogB_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxHdrFifoUnCorErrLogA_1_offset 0x00002850UL
+struct QIB_7322_RxHdrFifoUnCorErrLogA_1_pb {
+ pseudo_bit_t RxHdrFifoUnCorErrData_63_0[64];
+};
+struct QIB_7322_RxHdrFifoUnCorErrLogA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxHdrFifoUnCorErrLogA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxHdrFifoUnCorErrLogB_1_offset 0x00002858UL
+struct QIB_7322_RxHdrFifoUnCorErrLogB_1_pb {
+ pseudo_bit_t RxHdrFifoUnCorErrData_127_64[64];
+};
+struct QIB_7322_RxHdrFifoUnCorErrLogB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxHdrFifoUnCorErrLogB_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxHdrFifoUnCorErrLogC_1_offset 0x00002860UL
+struct QIB_7322_RxHdrFifoUnCorErrLogC_1_pb {
+ pseudo_bit_t RxHdrFifoUnCorErrCheckBit_15_0[16];
+ pseudo_bit_t RxHdrFifoUnCorErrAddr_10_0[11];
+ pseudo_bit_t _unused_0[37];
+};
+struct QIB_7322_RxHdrFifoUnCorErrLogC_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxHdrFifoUnCorErrLogC_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataFifoUnCorErrLogA_1_offset 0x00002868UL
+struct QIB_7322_RxDataFifoUnCorErrLogA_1_pb {
+ pseudo_bit_t RxDataFifoUnCorErrData_63_0[64];
+};
+struct QIB_7322_RxDataFifoUnCorErrLogA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxDataFifoUnCorErrLogA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataFifoUnCorErrLogB_1_offset 0x00002870UL
+struct QIB_7322_RxDataFifoUnCorErrLogB_1_pb {
+ pseudo_bit_t RxDataFifoUnCorErrData_127_64[64];
+};
+struct QIB_7322_RxDataFifoUnCorErrLogB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxDataFifoUnCorErrLogB_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataFifoUnCorErrLogC_1_offset 0x00002878UL
+struct QIB_7322_RxDataFifoUnCorErrLogC_1_pb {
+ pseudo_bit_t RxDataFifoUnCorErrCheckBit_15_0[16];
+ pseudo_bit_t RxDataFifoUnCorErrAddr_10_0[11];
+ pseudo_bit_t _unused_0[37];
+};
+struct QIB_7322_RxDataFifoUnCorErrLogC_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxDataFifoUnCorErrLogC_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LaFifoArray0UnCorErrLog_1_offset 0x00002880UL
+struct QIB_7322_LaFifoArray0UnCorErrLog_1_pb {
+ pseudo_bit_t LaFifoArray0UnCorErrData_34_0[35];
+ pseudo_bit_t LaFifoArray0UnCorErrCheckBit_10_0[11];
+ pseudo_bit_t LaFifoArray0UnCorErrAddr_10_0[11];
+ pseudo_bit_t _unused_0[7];
+};
+struct QIB_7322_LaFifoArray0UnCorErrLog_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_LaFifoArray0UnCorErrLog_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RmFifoArrayUnCorErrLogA_1_offset 0x000028c0UL
+struct QIB_7322_RmFifoArrayUnCorErrLogA_1_pb {
+ pseudo_bit_t RmFifoArrayUnCorErrData_63_0[64];
+};
+struct QIB_7322_RmFifoArrayUnCorErrLogA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RmFifoArrayUnCorErrLogA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RmFifoArrayUnCorErrLogB_1_offset 0x000028c8UL
+struct QIB_7322_RmFifoArrayUnCorErrLogB_1_pb {
+ pseudo_bit_t RmFifoArrayUnCorErrData_127_64[64];
+};
+struct QIB_7322_RmFifoArrayUnCorErrLogB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RmFifoArrayUnCorErrLogB_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RmFifoArrayUnCorErrLogC_1_offset 0x000028d0UL
+struct QIB_7322_RmFifoArrayUnCorErrLogC_1_pb {
+ pseudo_bit_t RmFifoArrayUnCorErrCheckBit_27_0[28];
+ pseudo_bit_t RmFifoArrayUnCorErrAddr_13_0[14];
+ pseudo_bit_t _unused_0[18];
+ pseudo_bit_t RmFifoArrayUnCorErrDword_3_0[4];
+};
+struct QIB_7322_RmFifoArrayUnCorErrLogC_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RmFifoArrayUnCorErrLogC_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrCorErrLogA_1_offset 0x00002900UL
+struct QIB_7322_RxBufrCorErrLogA_1_pb {
+ pseudo_bit_t RxBufrCorErrData_63_0[64];
+};
+struct QIB_7322_RxBufrCorErrLogA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrCorErrLogA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrCorErrLogB_1_offset 0x00002908UL
+struct QIB_7322_RxBufrCorErrLogB_1_pb {
+ pseudo_bit_t RxBufrCorErrData_127_64[64];
+};
+struct QIB_7322_RxBufrCorErrLogB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrCorErrLogB_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrCorErrLogC_1_offset 0x00002910UL
+struct QIB_7322_RxBufrCorErrLogC_1_pb {
+ pseudo_bit_t RxBufrCorErrData_191_128[64];
+};
+struct QIB_7322_RxBufrCorErrLogC_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrCorErrLogC_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrCorErrLogD_1_offset 0x00002918UL
+struct QIB_7322_RxBufrCorErrLogD_1_pb {
+ pseudo_bit_t RxBufrCorErrData_255_192[64];
+};
+struct QIB_7322_RxBufrCorErrLogD_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrCorErrLogD_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufrCorErrLogE_1_offset 0x00002920UL
+struct QIB_7322_RxBufrCorErrLogE_1_pb {
+ pseudo_bit_t RxBufrCorErrData_258_256[3];
+ pseudo_bit_t RxBufrCorErrCheckBit_36_0[37];
+ pseudo_bit_t RxBufrCorErrAddr_15_0[16];
+ pseudo_bit_t _unused_0[8];
+};
+struct QIB_7322_RxBufrCorErrLogE_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxBufrCorErrLogE_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxFlagCorErrLogA_1_offset 0x00002928UL
+struct QIB_7322_RxFlagCorErrLogA_1_pb {
+ pseudo_bit_t RxFlagCorErrData_63_0[64];
+};
+struct QIB_7322_RxFlagCorErrLogA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxFlagCorErrLogA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxFlagCorErrLogB_1_offset 0x00002930UL
+struct QIB_7322_RxFlagCorErrLogB_1_pb {
+ pseudo_bit_t RxFlagCorErrCheckBit_7_0[8];
+ pseudo_bit_t RxFlagCorErrAddr_12_0[13];
+ pseudo_bit_t _unused_0[43];
+};
+struct QIB_7322_RxFlagCorErrLogB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxFlagCorErrLogB_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLkupiqCorErrLogA_1_offset 0x00002940UL
+struct QIB_7322_RxLkupiqCorErrLogA_1_pb {
+ pseudo_bit_t RxLkupiqCorErrData_45_0[46];
+ pseudo_bit_t RxLkupiqCorErrCheckBit_7_0[8];
+ pseudo_bit_t _unused_0[10];
+};
+struct QIB_7322_RxLkupiqCorErrLogA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxLkupiqCorErrLogA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLkupiqCorErrLogB_1_offset 0x00002948UL
+struct QIB_7322_RxLkupiqCorErrLogB_1_pb {
+ pseudo_bit_t RxLkupiqCorErrAddr_12_0[13];
+ pseudo_bit_t _unused_0[51];
+};
+struct QIB_7322_RxLkupiqCorErrLogB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxLkupiqCorErrLogB_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxHdrFifoCorErrLogA_1_offset 0x00002950UL
+struct QIB_7322_RxHdrFifoCorErrLogA_1_pb {
+ pseudo_bit_t RxHdrFifoCorErrData_63_0[64];
+};
+struct QIB_7322_RxHdrFifoCorErrLogA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxHdrFifoCorErrLogA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxHdrFifoCorErrLogB_1_offset 0x00002958UL
+struct QIB_7322_RxHdrFifoCorErrLogB_1_pb {
+ pseudo_bit_t RxHdrFifoCorErrData_127_64[64];
+};
+struct QIB_7322_RxHdrFifoCorErrLogB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxHdrFifoCorErrLogB_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxHdrFifoCorErrLogC_1_offset 0x00002960UL
+struct QIB_7322_RxHdrFifoCorErrLogC_1_pb {
+ pseudo_bit_t RxHdrFifoCorErrCheckBit_15_0[16];
+ pseudo_bit_t RxHdrFifoCorErrAddr_10_0[11];
+ pseudo_bit_t _unused_0[37];
+};
+struct QIB_7322_RxHdrFifoCorErrLogC_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxHdrFifoCorErrLogC_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataFifoCorErrLogA_1_offset 0x00002968UL
+struct QIB_7322_RxDataFifoCorErrLogA_1_pb {
+ pseudo_bit_t RxDataFifoCorErrData_63_0[64];
+};
+struct QIB_7322_RxDataFifoCorErrLogA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxDataFifoCorErrLogA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataFifoCorErrLogB_1_offset 0x00002970UL
+struct QIB_7322_RxDataFifoCorErrLogB_1_pb {
+ pseudo_bit_t RxDataFifoCorErrData_127_64[64];
+};
+struct QIB_7322_RxDataFifoCorErrLogB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxDataFifoCorErrLogB_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataFifoCorErrLogC_1_offset 0x00002978UL
+struct QIB_7322_RxDataFifoCorErrLogC_1_pb {
+ pseudo_bit_t RxDataFifoCorErrCheckBit_15_0[16];
+ pseudo_bit_t RxDataFifoCorErrAddr_10_0[11];
+ pseudo_bit_t _unused_0[37];
+};
+struct QIB_7322_RxDataFifoCorErrLogC_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RxDataFifoCorErrLogC_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LaFifoArray0CorErrLog_1_offset 0x00002980UL
+struct QIB_7322_LaFifoArray0CorErrLog_1_pb {
+ pseudo_bit_t LaFifoArray0CorErrData_34_0[35];
+ pseudo_bit_t LaFifoArray0CorErrCheckBit_10_0[11];
+ pseudo_bit_t LaFifoArray0CorErrAddr_10_0[11];
+ pseudo_bit_t _unused_0[7];
+};
+struct QIB_7322_LaFifoArray0CorErrLog_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_LaFifoArray0CorErrLog_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RmFifoArrayCorErrLogA_1_offset 0x000029c0UL
+struct QIB_7322_RmFifoArrayCorErrLogA_1_pb {
+ pseudo_bit_t RmFifoArrayCorErrData_63_0[64];
+};
+struct QIB_7322_RmFifoArrayCorErrLogA_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RmFifoArrayCorErrLogA_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RmFifoArrayCorErrLogB_1_offset 0x000029c8UL
+struct QIB_7322_RmFifoArrayCorErrLogB_1_pb {
+ pseudo_bit_t RmFifoArrayCorErrData_127_64[64];
+};
+struct QIB_7322_RmFifoArrayCorErrLogB_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RmFifoArrayCorErrLogB_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RmFifoArrayCorErrLogC_1_offset 0x000029d0UL
+struct QIB_7322_RmFifoArrayCorErrLogC_1_pb {
+ pseudo_bit_t RmFifoArrayCorErrCheckBit_27_0[28];
+ pseudo_bit_t RmFifoArrayCorErrAddr_13_0[14];
+ pseudo_bit_t _unused_0[18];
+ pseudo_bit_t RmFifoArrayCorErrDword_3_0[4];
+};
+struct QIB_7322_RmFifoArrayCorErrLogC_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RmFifoArrayCorErrLogC_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_HighPriorityLimit_1_offset 0x00002bc0UL
+struct QIB_7322_HighPriorityLimit_1_pb {
+ pseudo_bit_t Limit[8];
+ pseudo_bit_t _unused_0[56];
+};
+struct QIB_7322_HighPriorityLimit_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_HighPriorityLimit_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LowPriority0_1_offset 0x00002c00UL
+struct QIB_7322_LowPriority0_1_pb {
+ pseudo_bit_t Weight[8];
+ pseudo_bit_t _unused_0[8];
+ pseudo_bit_t VirtualLane[3];
+ pseudo_bit_t _unused_1[45];
+};
+struct QIB_7322_LowPriority0_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_LowPriority0_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_HighPriority0_1_offset 0x00002e00UL
+struct QIB_7322_HighPriority0_1_pb {
+ pseudo_bit_t Weight[8];
+ pseudo_bit_t _unused_0[8];
+ pseudo_bit_t VirtualLane[3];
+ pseudo_bit_t _unused_1[45];
+};
+struct QIB_7322_HighPriority0_1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_HighPriority0_1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufAvail0_offset 0x00003000UL
+struct QIB_7322_SendBufAvail0_pb {
+ pseudo_bit_t SendBuf_31_0[64];
+};
+struct QIB_7322_SendBufAvail0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_SendBufAvail0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MsixTable_offset 0x00008000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_MsixPba_offset 0x00009000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LAMemory_offset 0x0000a000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LBIntCnt_offset 0x00011000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LBFlowStallCnt_offset 0x00011008UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxTIDFullErrCnt_offset 0x000110d0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxTIDValidErrCnt_offset 0x000110d8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxP0HdrEgrOvflCnt_offset 0x000110e8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PcieRetryBufDiagQwordCnt_offset 0x000111a0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxTidFlowDropCnt_offset 0x000111e0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LBIntCnt_0_offset 0x00012000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxCreditUpToDateTimeOut_0_offset 0x00012008UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxSDmaDescCnt_0_offset 0x00012010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxUnsupVLErrCnt_0_offset 0x00012018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxDataPktCnt_0_offset 0x00012020UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxFlowPktCnt_0_offset 0x00012028UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxDwordCnt_0_offset 0x00012030UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxLenErrCnt_0_offset 0x00012038UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxMaxMinLenErrCnt_0_offset 0x00012040UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxUnderrunCnt_0_offset 0x00012048UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxFlowStallCnt_0_offset 0x00012050UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxDroppedPktCnt_0_offset 0x00012058UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDroppedPktCnt_0_offset 0x00012060UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataPktCnt_0_offset 0x00012068UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxFlowPktCnt_0_offset 0x00012070UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDwordCnt_0_offset 0x00012078UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLenErrCnt_0_offset 0x00012080UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxMaxMinLenErrCnt_0_offset 0x00012088UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxICRCErrCnt_0_offset 0x00012090UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxVCRCErrCnt_0_offset 0x00012098UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxFlowCtrlViolCnt_0_offset 0x000120a0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxVersionErrCnt_0_offset 0x000120a8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLinkMalformCnt_0_offset 0x000120b0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxEBPCnt_0_offset 0x000120b8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLPCRCErrCnt_0_offset 0x000120c0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufOvflCnt_0_offset 0x000120c8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLenTruncateCnt_0_offset 0x000120d0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxPKeyMismatchCnt_0_offset 0x000120e0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBLinkDownedCnt_0_offset 0x00012180UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBSymbolErrCnt_0_offset 0x00012188UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBStatusChangeCnt_0_offset 0x00012190UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBLinkErrRecoveryCnt_0_offset 0x00012198UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ExcessBufferOvflCnt_0_offset 0x000121a8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LocalLinkIntegrityErrCnt_0_offset 0x000121b0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxVlErrCnt_0_offset 0x000121b8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDlidFltrCnt_0_offset 0x000121c0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxVL15DroppedPktCnt_0_offset 0x000121c8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxOtherLocalPhyErrCnt_0_offset 0x000121d0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxQPInvalidContextCnt_0_offset 0x000121d8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxHeadersErrCnt_0_offset 0x000121f8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSRcvDataCount_0_offset 0x00012218UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSRcvPktsCount_0_offset 0x00012220UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSXmitDataCount_0_offset 0x00012228UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSXmitPktsCount_0_offset 0x00012230UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSXmitWaitCount_0_offset 0x00012238UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LBIntCnt_1_offset 0x00013000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxCreditUpToDateTimeOut_1_offset 0x00013008UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxSDmaDescCnt_1_offset 0x00013010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxUnsupVLErrCnt_1_offset 0x00013018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxDataPktCnt_1_offset 0x00013020UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxFlowPktCnt_1_offset 0x00013028UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxDwordCnt_1_offset 0x00013030UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxLenErrCnt_1_offset 0x00013038UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxMaxMinLenErrCnt_1_offset 0x00013040UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxUnderrunCnt_1_offset 0x00013048UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxFlowStallCnt_1_offset 0x00013050UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxDroppedPktCnt_1_offset 0x00013058UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDroppedPktCnt_1_offset 0x00013060UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDataPktCnt_1_offset 0x00013068UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxFlowPktCnt_1_offset 0x00013070UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDwordCnt_1_offset 0x00013078UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLenErrCnt_1_offset 0x00013080UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxMaxMinLenErrCnt_1_offset 0x00013088UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxICRCErrCnt_1_offset 0x00013090UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxVCRCErrCnt_1_offset 0x00013098UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxFlowCtrlViolCnt_1_offset 0x000130a0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxVersionErrCnt_1_offset 0x000130a8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLinkMalformCnt_1_offset 0x000130b0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxEBPCnt_1_offset 0x000130b8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLPCRCErrCnt_1_offset 0x000130c0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxBufOvflCnt_1_offset 0x000130c8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxLenTruncateCnt_1_offset 0x000130d0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxPKeyMismatchCnt_1_offset 0x000130e0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBLinkDownedCnt_1_offset 0x00013180UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBSymbolErrCnt_1_offset 0x00013188UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBStatusChangeCnt_1_offset 0x00013190UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBLinkErrRecoveryCnt_1_offset 0x00013198UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ExcessBufferOvflCnt_1_offset 0x000131a8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LocalLinkIntegrityErrCnt_1_offset 0x000131b0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxVlErrCnt_1_offset 0x000131b8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxDlidFltrCnt_1_offset 0x000131c0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxVL15DroppedPktCnt_1_offset 0x000131c8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxOtherLocalPhyErrCnt_1_offset 0x000131d0UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RxQPInvalidContextCnt_1_offset 0x000131d8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_TxHeadersErrCnt_1_offset 0x000131f8UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSRcvDataCount_1_offset 0x00013218UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSRcvPktsCount_1_offset 0x00013220UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSXmitDataCount_1_offset 0x00013228UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSXmitPktsCount_1_offset 0x00013230UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PSXmitWaitCount_1_offset 0x00013238UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrArray_offset 0x00014000UL
+struct QIB_7322_RcvEgrArray_pb {
+ pseudo_bit_t RT_Addr[37];
+ pseudo_bit_t RT_BufSize[3];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_RcvEgrArray {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvEgrArray_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDArray0_offset 0x00050000UL
+struct QIB_7322_RcvTIDArray0_pb {
+ pseudo_bit_t RT_Addr[37];
+ pseudo_bit_t RT_BufSize[3];
+ pseudo_bit_t _unused_0[24];
+};
+struct QIB_7322_RcvTIDArray0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDArray0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendPbcCache_offset 0x00070000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LaunchFIFO_v0p0_offset 0x00072000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LaunchElement_v15p0_offset 0x00076000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PreLaunchFIFO_0_offset 0x00076100UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ScoreBoard_0_offset 0x00076200UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_DescriptorFIFO_0_offset 0x00076300UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LaunchFIFO_v0p1_offset 0x00078000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_LaunchElement_v15p1_offset 0x0007c000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PreLaunchFIFO_1_offset 0x0007c100UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_ScoreBoard_1_offset 0x0007c200UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_DescriptorFIFO_1_offset 0x0007c300UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvBufA_0_offset 0x00080000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvBufB_0_offset 0x00088000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvFlags_0_offset 0x0008a000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvLookupiqBuf_0_offset 0x0008c000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvDMADatBuf_0_offset 0x0008e000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvDMAHdrBuf_0_offset 0x0008e800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvBufA_1_offset 0x00090000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvBufB_1_offset 0x00098000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvFlags_1_offset 0x0009a000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvLookupiqBuf_1_offset 0x0009c000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvDMADatBuf_1_offset 0x0009e000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvDMAHdrBuf_1_offset 0x0009e800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PCIERcvBuf_offset 0x000a0000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PCIERetryBuf_offset 0x000a4000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PCIERcvBufRdToWrAddr_offset 0x000a8000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PCIERcvHdrRdToWrAddr_offset 0x000b0000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PCIECplBuf_offset 0x000b8000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PCIECplHdr_offset 0x000bc000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_PCIERcvHdr_offset 0x000bc200UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_IBSD_DDS_MAP_TABLE_0_offset 0x000d0000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_0_offset 0x00100000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_0_offset 0x00100800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_1_offset 0x00101000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_1_offset 0x00101800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_2_offset 0x00102000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_2_offset 0x00102800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_3_offset 0x00103000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_3_offset 0x00103800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_4_offset 0x00104000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_4_offset 0x00104800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_5_offset 0x00105000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_5_offset 0x00105800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_6_offset 0x00106000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_6_offset 0x00106800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_7_offset 0x00107000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_7_offset 0x00107800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_8_offset 0x00108000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_8_offset 0x00108800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_9_offset 0x00109000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_9_offset 0x00109800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_10_offset 0x0010a000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_10_offset 0x0010a800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_11_offset 0x0010b000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_11_offset 0x0010b800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_12_offset 0x0010c000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_12_offset 0x0010c800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_13_offset 0x0010d000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_13_offset 0x0010d800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_14_offset 0x0010e000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_14_offset 0x0010e800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_15_offset 0x0010f000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_15_offset 0x0010f800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_16_offset 0x00110000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_16_offset 0x00110800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_17_offset 0x00111000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_17_offset 0x00111800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_18_offset 0x00112000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_18_offset 0x00112800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_19_offset 0x00113000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_19_offset 0x00113800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_20_offset 0x00114000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_20_offset 0x00114800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_21_offset 0x00115000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_21_offset 0x00115800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_22_offset 0x00116000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_22_offset 0x00116800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_23_offset 0x00117000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_23_offset 0x00117800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_24_offset 0x00118000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_24_offset 0x00118800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_25_offset 0x00119000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_25_offset 0x00119800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_26_offset 0x0011a000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_26_offset 0x0011a800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_27_offset 0x0011b000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_27_offset 0x0011b800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_28_offset 0x0011c000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_28_offset 0x0011c800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_29_offset 0x0011d000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_29_offset 0x0011d800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_30_offset 0x0011e000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_30_offset 0x0011e800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_31_offset 0x0011f000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_31_offset 0x0011f800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_32_offset 0x00120000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_32_offset 0x00120800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_33_offset 0x00121000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_33_offset 0x00121800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_34_offset 0x00122000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_34_offset 0x00122800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_35_offset 0x00123000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_35_offset 0x00123800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_36_offset 0x00124000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_36_offset 0x00124800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_37_offset 0x00125000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_37_offset 0x00125800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_38_offset 0x00126000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_38_offset 0x00126800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_39_offset 0x00127000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_39_offset 0x00127800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_40_offset 0x00128000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_40_offset 0x00128800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_41_offset 0x00129000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_41_offset 0x00129800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_42_offset 0x0012a000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_42_offset 0x0012a800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_43_offset 0x0012b000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_43_offset 0x0012b800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_44_offset 0x0012c000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_44_offset 0x0012c800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_45_offset 0x0012d000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_45_offset 0x0012d800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_46_offset 0x0012e000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_46_offset 0x0012e800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_47_offset 0x0012f000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_47_offset 0x0012f800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_48_offset 0x00130000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_48_offset 0x00130800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_49_offset 0x00131000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_49_offset 0x00131800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_50_offset 0x00132000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_50_offset 0x00132800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_51_offset 0x00133000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_51_offset 0x00133800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_52_offset 0x00134000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_52_offset 0x00134800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_53_offset 0x00135000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_53_offset 0x00135800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_54_offset 0x00136000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_54_offset 0x00136800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_55_offset 0x00137000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_55_offset 0x00137800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_56_offset 0x00138000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_56_offset 0x00138800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_57_offset 0x00139000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_57_offset 0x00139800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_58_offset 0x0013a000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_58_offset 0x0013a800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_59_offset 0x0013b000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_59_offset 0x0013b800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_60_offset 0x0013c000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_60_offset 0x0013c800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_61_offset 0x0013d000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_61_offset 0x0013d800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_62_offset 0x0013e000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_62_offset 0x0013e800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_63_offset 0x0013f000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_63_offset 0x0013f800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_64_offset 0x00140000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_64_offset 0x00140800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_65_offset 0x00141000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_65_offset 0x00141800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_66_offset 0x00142000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_66_offset 0x00142800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_67_offset 0x00143000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_67_offset 0x00143800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_68_offset 0x00144000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_68_offset 0x00144800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_69_offset 0x00145000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_69_offset 0x00145800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_70_offset 0x00146000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_70_offset 0x00146800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_71_offset 0x00147000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_71_offset 0x00147800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_72_offset 0x00148000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_72_offset 0x00148800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_73_offset 0x00149000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_73_offset 0x00149800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_74_offset 0x0014a000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_74_offset 0x0014a800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_75_offset 0x0014b000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_75_offset 0x0014b800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_76_offset 0x0014c000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_76_offset 0x0014c800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_77_offset 0x0014d000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_77_offset 0x0014d800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_78_offset 0x0014e000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_78_offset 0x0014e800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_79_offset 0x0014f000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_79_offset 0x0014f800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_80_offset 0x00150000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_80_offset 0x00150800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_81_offset 0x00151000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_81_offset 0x00151800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_82_offset 0x00152000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_82_offset 0x00152800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_83_offset 0x00153000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_83_offset 0x00153800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_84_offset 0x00154000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_84_offset 0x00154800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_85_offset 0x00155000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_85_offset 0x00155800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_86_offset 0x00156000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_86_offset 0x00156800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_87_offset 0x00157000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_87_offset 0x00157800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_88_offset 0x00158000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_88_offset 0x00158800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_89_offset 0x00159000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_89_offset 0x00159800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_90_offset 0x0015a000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_90_offset 0x0015a800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_91_offset 0x0015b000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_91_offset 0x0015b800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_92_offset 0x0015c000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_92_offset 0x0015c800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_93_offset 0x0015d000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_93_offset 0x0015d800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_94_offset 0x0015e000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_94_offset 0x0015e800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_95_offset 0x0015f000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_95_offset 0x0015f800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_96_offset 0x00160000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_96_offset 0x00160800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_97_offset 0x00161000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_97_offset 0x00161800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_98_offset 0x00162000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_98_offset 0x00162800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_99_offset 0x00163000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_99_offset 0x00163800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_100_offset 0x00164000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_100_offset 0x00164800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_101_offset 0x00165000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_101_offset 0x00165800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_102_offset 0x00166000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_102_offset 0x00166800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_103_offset 0x00167000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_103_offset 0x00167800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_104_offset 0x00168000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_104_offset 0x00168800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_105_offset 0x00169000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_105_offset 0x00169800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_106_offset 0x0016a000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_106_offset 0x0016a800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_107_offset 0x0016b000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_107_offset 0x0016b800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_108_offset 0x0016c000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_108_offset 0x0016c800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_109_offset 0x0016d000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_109_offset 0x0016d800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_110_offset 0x0016e000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_110_offset 0x0016e800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_111_offset 0x0016f000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_111_offset 0x0016f800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_112_offset 0x00170000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_112_offset 0x00170800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_113_offset 0x00171000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_113_offset 0x00171800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_114_offset 0x00172000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_114_offset 0x00172800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_115_offset 0x00173000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_115_offset 0x00173800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_116_offset 0x00174000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_116_offset 0x00174800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_117_offset 0x00175000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_117_offset 0x00175800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_118_offset 0x00176000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_118_offset 0x00176800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_119_offset 0x00177000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_119_offset 0x00177800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_120_offset 0x00178000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_120_offset 0x00178800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_121_offset 0x00179000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_121_offset 0x00179800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_122_offset 0x0017a000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_122_offset 0x0017a800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_123_offset 0x0017b000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_123_offset 0x0017b800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_124_offset 0x0017c000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_124_offset 0x0017c800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_125_offset 0x0017d000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_125_offset 0x0017d800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_126_offset 0x0017e000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_126_offset 0x0017e800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_127_offset 0x0017f000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_127_offset 0x0017f800UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_128_offset 0x00180000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_128_offset 0x00181000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_129_offset 0x00182000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_129_offset 0x00183000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_130_offset 0x00184000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_130_offset 0x00185000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_131_offset 0x00186000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_131_offset 0x00187000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_132_offset 0x00188000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_132_offset 0x00189000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_133_offset 0x0018a000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_133_offset 0x0018b000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_134_offset 0x0018c000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_134_offset 0x0018d000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_135_offset 0x0018e000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_135_offset 0x0018f000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_136_offset 0x00190000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_136_offset 0x00191000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_137_offset 0x00192000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_137_offset 0x00193000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_138_offset 0x00194000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_138_offset 0x00195000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_139_offset 0x00196000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_139_offset 0x00197000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_140_offset 0x00198000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_140_offset 0x00199000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_141_offset 0x0019a000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_141_offset 0x0019b000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_142_offset 0x0019c000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_142_offset 0x0019d000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_143_offset 0x0019e000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_143_offset 0x0019f000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_144_offset 0x001a0000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_144_offset 0x001a1000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_145_offset 0x001a2000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_145_offset 0x001a3000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_146_offset 0x001a4000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_146_offset 0x001a5000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_147_offset 0x001a6000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_147_offset 0x001a7000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_148_offset 0x001a8000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_148_offset 0x001a9000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_149_offset 0x001aa000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_149_offset 0x001ab000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_150_offset 0x001ac000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_150_offset 0x001ad000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_151_offset 0x001ae000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_151_offset 0x001af000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_152_offset 0x001b0000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_152_offset 0x001b1000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_153_offset 0x001b2000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_153_offset 0x001b3000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_154_offset 0x001b4000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_154_offset 0x001b5000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_155_offset 0x001b6000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_155_offset 0x001b7000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_156_offset 0x001b8000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_156_offset 0x001b9000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_157_offset 0x001ba000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_157_offset 0x001bb000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_158_offset 0x001bc000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_158_offset 0x001bd000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufMA_159_offset 0x001be000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufEA_159_offset 0x001bf000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_SendBufVL15_0_offset 0x001c0000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail0_offset 0x00200000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead0_offset 0x00200008UL
+struct QIB_7322_RcvHdrHead0_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail0_offset 0x00200010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead0_offset 0x00200018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable0_offset 0x00201000UL
+struct QIB_7322_RcvTIDFlowTable0_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable0 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable0_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail1_offset 0x00210000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead1_offset 0x00210008UL
+struct QIB_7322_RcvHdrHead1_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail1_offset 0x00210010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead1_offset 0x00210018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable1_offset 0x00211000UL
+struct QIB_7322_RcvTIDFlowTable1_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable1 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable1_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail2_offset 0x00220000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead2_offset 0x00220008UL
+struct QIB_7322_RcvHdrHead2_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead2 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead2_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail2_offset 0x00220010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead2_offset 0x00220018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable2_offset 0x00221000UL
+struct QIB_7322_RcvTIDFlowTable2_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable2 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable2_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail3_offset 0x00230000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead3_offset 0x00230008UL
+struct QIB_7322_RcvHdrHead3_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead3 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead3_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail3_offset 0x00230010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead3_offset 0x00230018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable3_offset 0x00231000UL
+struct QIB_7322_RcvTIDFlowTable3_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable3 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable3_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail4_offset 0x00240000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead4_offset 0x00240008UL
+struct QIB_7322_RcvHdrHead4_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead4 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead4_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail4_offset 0x00240010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead4_offset 0x00240018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable4_offset 0x00241000UL
+struct QIB_7322_RcvTIDFlowTable4_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable4 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable4_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail5_offset 0x00250000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead5_offset 0x00250008UL
+struct QIB_7322_RcvHdrHead5_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead5 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead5_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail5_offset 0x00250010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead5_offset 0x00250018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable5_offset 0x00251000UL
+struct QIB_7322_RcvTIDFlowTable5_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable5 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable5_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail6_offset 0x00260000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead6_offset 0x00260008UL
+struct QIB_7322_RcvHdrHead6_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead6 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead6_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail6_offset 0x00260010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead6_offset 0x00260018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable6_offset 0x00261000UL
+struct QIB_7322_RcvTIDFlowTable6_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable6 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable6_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail7_offset 0x00270000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead7_offset 0x00270008UL
+struct QIB_7322_RcvHdrHead7_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead7 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead7_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail7_offset 0x00270010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead7_offset 0x00270018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable7_offset 0x00271000UL
+struct QIB_7322_RcvTIDFlowTable7_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable7 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable7_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail8_offset 0x00280000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead8_offset 0x00280008UL
+struct QIB_7322_RcvHdrHead8_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead8 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead8_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail8_offset 0x00280010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead8_offset 0x00280018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable8_offset 0x00281000UL
+struct QIB_7322_RcvTIDFlowTable8_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable8 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable8_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail9_offset 0x00290000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead9_offset 0x00290008UL
+struct QIB_7322_RcvHdrHead9_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead9 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead9_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail9_offset 0x00290010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead9_offset 0x00290018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable9_offset 0x00291000UL
+struct QIB_7322_RcvTIDFlowTable9_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable9 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable9_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail10_offset 0x002a0000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead10_offset 0x002a0008UL
+struct QIB_7322_RcvHdrHead10_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead10 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead10_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail10_offset 0x002a0010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead10_offset 0x002a0018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable10_offset 0x002a1000UL
+struct QIB_7322_RcvTIDFlowTable10_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable10 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable10_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail11_offset 0x002b0000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead11_offset 0x002b0008UL
+struct QIB_7322_RcvHdrHead11_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead11 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead11_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail11_offset 0x002b0010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead11_offset 0x002b0018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable11_offset 0x002b1000UL
+struct QIB_7322_RcvTIDFlowTable11_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable11 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable11_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail12_offset 0x002c0000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead12_offset 0x002c0008UL
+struct QIB_7322_RcvHdrHead12_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead12 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead12_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail12_offset 0x002c0010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead12_offset 0x002c0018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable12_offset 0x002c1000UL
+struct QIB_7322_RcvTIDFlowTable12_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable12 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable12_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail13_offset 0x002d0000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead13_offset 0x002d0008UL
+struct QIB_7322_RcvHdrHead13_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead13 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead13_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail13_offset 0x002d0010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead13_offset 0x002d0018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable13_offset 0x002d1000UL
+struct QIB_7322_RcvTIDFlowTable13_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable13 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable13_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail14_offset 0x002e0000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead14_offset 0x002e0008UL
+struct QIB_7322_RcvHdrHead14_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead14 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead14_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail14_offset 0x002e0010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead14_offset 0x002e0018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable14_offset 0x002e1000UL
+struct QIB_7322_RcvTIDFlowTable14_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable14 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable14_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail15_offset 0x002f0000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead15_offset 0x002f0008UL
+struct QIB_7322_RcvHdrHead15_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead15 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead15_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail15_offset 0x002f0010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead15_offset 0x002f0018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable15_offset 0x002f1000UL
+struct QIB_7322_RcvTIDFlowTable15_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable15 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable15_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail16_offset 0x00300000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead16_offset 0x00300008UL
+struct QIB_7322_RcvHdrHead16_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead16 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead16_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail16_offset 0x00300010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead16_offset 0x00300018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable16_offset 0x00301000UL
+struct QIB_7322_RcvTIDFlowTable16_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable16 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable16_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrTail17_offset 0x00310000UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvHdrHead17_offset 0x00310008UL
+struct QIB_7322_RcvHdrHead17_pb {
+ pseudo_bit_t RcvHeadPointer[32];
+ pseudo_bit_t counter[16];
+ pseudo_bit_t _unused_0[16];
+};
+struct QIB_7322_RcvHdrHead17 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvHdrHead17_pb );
+};
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexTail17_offset 0x00310010UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvEgrIndexHead17_offset 0x00310018UL
+/* Default value: 0x0000000000000000 */
+
+#define QIB_7322_RcvTIDFlowTable17_offset 0x00311000UL
+struct QIB_7322_RcvTIDFlowTable17_pb {
+ pseudo_bit_t SeqNum[11];
+ pseudo_bit_t GenVal[8];
+ pseudo_bit_t FlowValid[1];
+ pseudo_bit_t HdrSuppEnabled[1];
+ pseudo_bit_t KeepAfterSeqErr[1];
+ pseudo_bit_t KeepOnGenErr[1];
+ pseudo_bit_t _unused_0[4];
+ pseudo_bit_t SeqMismatch[1];
+ pseudo_bit_t GenMismatch[1];
+ pseudo_bit_t _unused_1[35];
+};
+struct QIB_7322_RcvTIDFlowTable17 {
+ PSEUDO_BIT_STRUCT ( struct QIB_7322_RcvTIDFlowTable17_pb );
+};
+/* Default value: 0x0000000000000000 */
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib_genbits.pl b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib_genbits.pl
new file mode 100755
index 00000000..1d5eeded
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/infiniband/qib_genbits.pl
@@ -0,0 +1,116 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+use strict;
+use warnings;
+
+my $offsets = {};
+my $defaults = {};
+my $structures = {};
+my $structure = "";
+
+while ( <> ) {
+ chomp;
+ if ( /^\#define (\S+)_OFFS (\S+)$/ ) {
+ $structure = $1;
+ $offsets->{$structure} = $2;
+ } elsif ( /^\#define ${structure}_DEF (\S+)$/ ) {
+ $defaults->{$structure} = $1;
+ } elsif ( /^\#define ${structure}_(\S+)_LSB (\S+)$/ ) {
+ $structures->{$structure}->{$1}->{LSB} = $2;
+ } elsif ( /^\#define ${structure}_(\S+)_MSB (\S+)$/ ) {
+ $structures->{$structure}->{$1}->{MSB} = $2;
+ } elsif ( /^\#define ${structure}_(\S+)_RMASK (\S+)$/ ) {
+ $structures->{$structure}->{$1}->{RMASK} = $2;
+ } elsif ( /^\s*$/ ) {
+ # Do nothing
+ } else {
+ print "$_\n";
+ }
+}
+
+my $data = [ map { { name => $_, offset => $offsets->{$_},
+ default => $defaults->{$_} }; }
+ sort { hex ( $offsets->{$a} ) <=> hex ( $offsets->{$b} ) }
+ keys %$offsets ];
+
+foreach my $datum ( @$data ) {
+ next unless exists $structures->{$datum->{name}};
+ $structure = $structures->{$datum->{name}};
+ my $fields = [ map { { name => $_, lsb => $structure->{$_}->{LSB},
+ msb => $structure->{$_}->{MSB},
+ rmask => $structure->{$_}->{RMASK} }; }
+ sort { hex ( $structure->{$a}->{LSB} ) <=>
+ hex ( $structure->{$b}->{LSB} ) }
+ keys %$structure ];
+ $datum->{fields} = $fields;
+}
+
+print "\n/* This file has been further processed by $0 */\n\n";
+print "FILE_LICENCE ( GPL2_ONLY );\n\n";
+
+foreach my $datum ( @$data ) {
+ printf "#define %s_offset 0x%08xUL\n",
+ $datum->{name}, hex ( $datum->{offset} );
+ if ( exists $datum->{fields} ) {
+ my $lsb = 0;
+ my $reserved_idx = 0;
+ printf "struct %s_pb {\n", $datum->{name};
+ foreach my $field ( @{$datum->{fields}} ) {
+ my $pad_width = ( hex ( $field->{lsb} ) - $lsb );
+ die "Inconsistent LSB/RMASK in $datum->{name} before $field->{name}\n"
+ if $pad_width < 0;
+ printf "\tpseudo_bit_t _unused_%u[%u];\n", $reserved_idx++, $pad_width
+ if $pad_width;
+ $lsb += $pad_width;
+ # Damn Perl can't cope with 64-bit hex constants
+ my $width = 0;
+ die "Missing RMASK in $datum->{name}.$field->{name}\n"
+ unless defined $field->{rmask};
+ my $rmask = $field->{rmask};
+ while ( $rmask =~ /^(0x.+)f$/i ) {
+ $width += 4;
+ $rmask = $1;
+ }
+ $rmask = hex ( $rmask );
+ while ( $rmask ) {
+ $width++;
+ $rmask >>= 1;
+ }
+ if ( defined $field->{msb} ) {
+ my $msb_width = ( hex ( $field->{msb} ) - $lsb + 1 );
+ $width ||= $msb_width;
+ die "Inconsistent LSB/MSB/RMASK in $datum->{name}.$field->{name}\n"
+ unless $width == $msb_width;
+ }
+ printf "\tpseudo_bit_t %s[%u];\n", $field->{name}, $width;
+ $lsb += $width;
+ }
+ my $pad_width = ( 64 - $lsb );
+ die "Inconsistent LSB/RMASK in $datum->{name} final field\n"
+ if $pad_width < 0;
+ printf "\tpseudo_bit_t _unused_%u[%u];\n", $reserved_idx++, $pad_width
+ if $pad_width;
+ printf "};\n";
+ printf "struct %s {\n\tPSEUDO_BIT_STRUCT ( struct %s_pb );\n};\n",
+ $datum->{name}, $datum->{name};
+ }
+ printf "/* Default value: %s */\n", $datum->{default}
+ if defined $datum->{default};
+ print "\n";
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/linux/linux.c b/src/VBox/Devices/PC/ipxe/src/drivers/linux/linux.c
new file mode 100644
index 00000000..83546b27
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/linux/linux.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+/** @file
+ *
+ * Linux root_device and root_driver.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <ipxe/linux.h>
+#include <ipxe/malloc.h>
+#include <ipxe/settings.h>
+
+LIST_HEAD(linux_device_requests);
+LIST_HEAD(linux_global_settings);
+
+/** Go over the device requests looking for a matching linux driver to handle them. */
+static int linux_probe(struct root_device *rootdev)
+{
+ struct linux_device_request *request;
+ struct linux_driver *driver;
+ struct linux_device *device = NULL;
+ int rc;
+
+ /* Apply global settings */
+ linux_apply_settings(&linux_global_settings, NULL);
+
+ list_for_each_entry(request, &linux_device_requests, list) {
+ if (! device)
+ device = zalloc(sizeof(*device));
+
+ if (! device)
+ return -ENOMEM;
+
+ rc = 1;
+
+ for_each_table_entry(driver, LINUX_DRIVERS) {
+ if ((rc = strcmp(driver->name, request->driver)) == 0)
+ break;
+ }
+
+ if (rc != 0) {
+ printf("Linux driver '%s' not found\n", request->driver);
+ continue;
+ }
+
+ if (! driver->can_probe) {
+ printf("Driver '%s' cannot handle any more devices\n", driver->name);
+ continue;
+ }
+
+ /* We found a matching driver so add the device to the hierarchy */
+ list_add(&device->dev.siblings, &rootdev->dev.children);
+ device->dev.parent = &rootdev->dev;
+ INIT_LIST_HEAD(&device->dev.children);
+
+ if (driver->probe(device, request) == 0) {
+ device->driver = driver;
+ device->dev.driver_name = driver->name;
+ /* Driver handled the device so release ownership */
+ device = NULL;
+ } else {
+ /* Driver failed to handle the device so remove it from the hierarchy
+ * and reuse the object */
+ list_del(&device->dev.siblings);
+ }
+ };
+
+ free(device);
+
+ return 0;
+}
+
+/** Remove all the linux devices registered in probe() */
+static void linux_remove(struct root_device *rootdev)
+{
+ struct linux_device *device;
+ struct linux_device *tmp;
+
+ list_for_each_entry_safe(device, tmp, &rootdev->dev.children, dev.siblings) {
+ list_del(&device->dev.siblings);
+ device->driver->remove(device);
+ free(device);
+ }
+}
+
+/** Linux root driver */
+static struct root_driver linux_root_driver = {
+ .probe = linux_probe,
+ .remove = linux_remove,
+};
+
+/** Linux root device */
+struct root_device linux_root_device __root_device = {
+ .dev = { .name = "linux" },
+ .driver = &linux_root_driver,
+};
+
+struct linux_setting *linux_find_setting(char *name, struct list_head *settings)
+{
+ struct linux_setting *setting;
+ struct linux_setting *result = NULL;
+
+ /* Find the last occurrence of a setting with the specified name */
+ list_for_each_entry(setting, settings, list) {
+ if (strcmp(setting->name, name) == 0) {
+ result = setting;
+ }
+ }
+
+ return result;
+}
+
+void linux_apply_settings(struct list_head *new_settings, struct settings *settings_block)
+{
+ struct linux_setting *setting;
+ int rc;
+
+ list_for_each_entry(setting, new_settings, list) {
+ /* Skip already applied settings */
+ if (setting->applied)
+ continue;
+
+ struct setting *s = find_setting(setting->name);
+ if (s) {
+ rc = storef_setting(settings_block, find_setting(setting->name), setting->value);
+ if (rc != 0)
+ DBG("linux storing setting '%s' = '%s' failed\n", setting->name, setting->value);
+ setting->applied = 1;
+ } else {
+ DBG("linux unknown setting '%s'\n", setting->name);
+ }
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/linux/tap.c b/src/VBox/Devices/PC/ipxe/src/drivers/linux/tap.c
new file mode 100644
index 00000000..53bb16a3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/linux/tap.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <linux_api.h>
+#include <ipxe/list.h>
+#include <ipxe/linux.h>
+#include <ipxe/malloc.h>
+#include <ipxe/device.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/settings.h>
+#include <ipxe/socket.h>
+
+/* This hack prevents pre-2.6.32 headers from redefining struct sockaddr */
+#define __GLIBC__ 2
+#include <linux/socket.h>
+#undef __GLIBC__
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/if_tun.h>
+
+#define RX_BUF_SIZE 1536
+
+/** @file
+ *
+ * The TAP driver.
+ *
+ * The TAP is a Virtual Ethernet network device.
+ */
+
+struct tap_nic {
+ /** Tap interface name */
+ char * interface;
+ /** File descriptor of the opened tap device */
+ int fd;
+};
+
+/** Open the TAP device */
+static int tap_open(struct net_device * netdev)
+{
+ struct tap_nic * nic = netdev->priv;
+ struct ifreq ifr;
+ int ret;
+
+ nic->fd = linux_open("/dev/net/tun", O_RDWR);
+ if (nic->fd < 0) {
+ DBGC(nic, "tap %p open('/dev/net/tun') = %d (%s)\n", nic, nic->fd, linux_strerror(linux_errno));
+ return nic->fd;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ /* IFF_NO_PI for no extra packet information */
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ strncpy(ifr.ifr_name, nic->interface, IFNAMSIZ);
+ DBGC(nic, "tap %p interface = '%s'\n", nic, nic->interface);
+
+ ret = linux_ioctl(nic->fd, TUNSETIFF, &ifr);
+
+ if (ret != 0) {
+ DBGC(nic, "tap %p ioctl(%d, ...) = %d (%s)\n", nic, nic->fd, ret, linux_strerror(linux_errno));
+ linux_close(nic->fd);
+ return ret;
+ }
+
+ /* Set nonblocking mode to make tap_poll easier */
+ ret = linux_fcntl(nic->fd, F_SETFL, O_NONBLOCK);
+
+ if (ret != 0) {
+ DBGC(nic, "tap %p fcntl(%d, ...) = %d (%s)\n", nic, nic->fd, ret, linux_strerror(linux_errno));
+ linux_close(nic->fd);
+ return ret;
+ }
+
+ return 0;
+}
+
+/** Close the TAP device */
+static void tap_close(struct net_device *netdev)
+{
+ struct tap_nic * nic = netdev->priv;
+ linux_close(nic->fd);
+}
+
+/**
+ * Transmit an ethernet packet.
+ *
+ * The packet can be written to the TAP device and marked as complete immediately.
+ */
+static int tap_transmit(struct net_device *netdev, struct io_buffer *iobuf)
+{
+ struct tap_nic * nic = netdev->priv;
+ int rc;
+
+ /* Pad and align packet */
+ iob_pad(iobuf, ETH_ZLEN);
+
+ rc = linux_write(nic->fd, iobuf->data, iobuf->tail - iobuf->data);
+ DBGC2(nic, "tap %p wrote %d bytes\n", nic, rc);
+ netdev_tx_complete(netdev, iobuf);
+
+ return 0;
+}
+
+/** Poll for new packets */
+static void tap_poll(struct net_device *netdev)
+{
+ struct tap_nic * nic = netdev->priv;
+ struct pollfd pfd;
+ struct io_buffer * iobuf;
+ int r;
+
+ pfd.fd = nic->fd;
+ pfd.events = POLLIN;
+ if (linux_poll(&pfd, 1, 0) == -1) {
+ DBGC(nic, "tap %p poll failed (%s)\n", nic, linux_strerror(linux_errno));
+ return;
+ }
+ if ((pfd.revents & POLLIN) == 0)
+ return;
+
+ /* At this point we know there is at least one new packet to be read */
+
+ iobuf = alloc_iob(RX_BUF_SIZE);
+ if (! iobuf)
+ goto allocfail;
+
+ while ((r = linux_read(nic->fd, iobuf->data, RX_BUF_SIZE)) > 0) {
+ DBGC2(nic, "tap %p read %d bytes\n", nic, r);
+
+ iob_put(iobuf, r);
+ netdev_rx(netdev, iobuf);
+
+ iobuf = alloc_iob(RX_BUF_SIZE);
+ if (! iobuf)
+ goto allocfail;
+ }
+
+ free_iob(iobuf);
+ return;
+
+allocfail:
+ DBGC(nic, "tap %p alloc_iob failed\n", nic);
+}
+
+/**
+ * Set irq.
+ *
+ * Not used on linux, provide a dummy implementation.
+ */
+static void tap_irq(struct net_device *netdev, int enable)
+{
+ struct tap_nic *nic = netdev->priv;
+
+ DBGC(nic, "tap %p irq enable = %d\n", nic, enable);
+}
+
+/** Tap operations */
+static struct net_device_operations tap_operations = {
+ .open = tap_open,
+ .close = tap_close,
+ .transmit = tap_transmit,
+ .poll = tap_poll,
+ .irq = tap_irq,
+};
+
+/** Handle a device request for the tap driver */
+static int tap_probe(struct linux_device *device, struct linux_device_request *request)
+{
+ struct linux_setting *if_setting;
+ struct net_device *netdev;
+ struct tap_nic *nic;
+ int rc;
+
+ netdev = alloc_etherdev(sizeof(*nic));
+ if (! netdev)
+ return -ENOMEM;
+
+ netdev_init(netdev, &tap_operations);
+ nic = netdev->priv;
+ linux_set_drvdata(device, netdev);
+ netdev->dev = &device->dev;
+ memset(nic, 0, sizeof(*nic));
+
+ if ((rc = register_netdev(netdev)) != 0)
+ goto err_register;
+
+ netdev_link_up(netdev);
+
+ /* Look for the mandatory if setting */
+ if_setting = linux_find_setting("if", &request->settings);
+
+ /* No if setting */
+ if (! if_setting) {
+ printf("tap missing a mandatory if setting\n");
+ rc = -EINVAL;
+ goto err_settings;
+ }
+
+ nic->interface = if_setting->value;
+ if_setting->applied = 1;
+
+ /* Apply rest of the settings */
+ linux_apply_settings(&request->settings, &netdev->settings.settings);
+
+ return 0;
+
+err_settings:
+ unregister_netdev(netdev);
+err_register:
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+ return rc;
+}
+
+/** Remove the device */
+static void tap_remove(struct linux_device *device)
+{
+ struct net_device *netdev = linux_get_drvdata(device);
+ unregister_netdev(netdev);
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+}
+
+/** Tap linux_driver */
+struct linux_driver tap_driver __linux_driver = {
+ .name = "tap",
+ .probe = tap_probe,
+ .remove = tap_remove,
+ .can_probe = 1,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/3c503.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c503.c
new file mode 100644
index 00000000..1704dcda
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c503.c
@@ -0,0 +1,5 @@
+/* 3Com 3c503, a memory-mapped NS8390-based card */
+#if 0 /* Currently broken! */
+#define INCLUDE_3C503
+#include "ns8390.c"
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/3c509-eisa.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c509-eisa.c
new file mode 100644
index 00000000..81c60ee9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c509-eisa.c
@@ -0,0 +1,48 @@
+/*
+ * Split out from 3c509.c, since EISA cards are relatively rare, and
+ * ROM space in 3c509s is very limited.
+ *
+ */
+
+#include <ipxe/eisa.h>
+#include <ipxe/isa.h>
+#include "3c509.h"
+
+/*
+ * The EISA probe function
+ *
+ */
+static int el3_eisa_probe ( struct nic *nic, struct eisa_device *eisa ) {
+
+
+ nic->ioaddr = eisa->ioaddr;
+ nic->irqno = 0;
+ enable_eisa_device ( eisa );
+
+ /* Hand off to generic t5x9 probe routine */
+ return t5x9_probe ( nic, ISA_PROD_ID ( PROD_ID ), ISA_PROD_ID_MASK );
+}
+
+static void el3_eisa_disable ( struct nic *nic, struct eisa_device *eisa ) {
+ t5x9_disable ( nic );
+ disable_eisa_device ( eisa );
+}
+
+static struct eisa_device_id el3_eisa_adapters[] = {
+ { "3Com 3c509 EtherLink III (EISA)", MFG_ID, PROD_ID },
+};
+
+EISA_DRIVER ( el3_eisa_driver, el3_eisa_adapters );
+
+DRIVER ( "3c509 (EISA)", nic_driver, eisa_driver, el3_eisa_driver,
+ el3_eisa_probe, el3_eisa_disable );
+
+ISA_ROM ( "3c509-eisa","3c509 (EISA)" );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/3c509.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c509.c
new file mode 100644
index 00000000..4326a835
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c509.c
@@ -0,0 +1,432 @@
+/*
+ * Split out into 3c509.c and 3c5x9.c, to make it possible to build a
+ * 3c529 module without including ISA, ISAPnP and EISA code.
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/io.h>
+#include <unistd.h>
+#include <ipxe/device.h>
+#include <ipxe/isa.h>
+#include "3c509.h"
+
+/*
+ * 3c509 cards have their own method of contention resolution; this
+ * effectively defines another bus type similar to ISAPnP. Even the
+ * original ISA cards can be programatically mapped to any I/O address
+ * in the range 0x200-0x3e0.
+ *
+ * However, there is a small problem: once you've activated a card,
+ * the only ways to deactivate it will also wipe its tag, meaning that
+ * you won't be able to subsequently reactivate it without going
+ * through the whole ID sequence again. The solution we adopt is to
+ * isolate and tag all cards at the start, and to immediately
+ * re-isolate and re-tag a card after disabling it.
+ *
+ */
+
+static void t509bus_remove ( struct root_device *rootdev );
+
+static unsigned int t509_id_port = 0;
+static unsigned int t509_max_tag = 0;
+
+/** A 3c509 device */
+struct t509_device {
+ /** Generic device */
+ struct device dev;
+ /** Tag */
+ unsigned int tag;
+ /** I/O address */
+ uint16_t ioaddr;
+ /** Driver-private data
+ *
+ * Use t509_set_drvdata() and t509_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+};
+
+/**
+ * Set 3c509 driver-private data
+ *
+ * @v t509 3c509 device
+ * @v priv Private data
+ */
+static inline void t509_set_drvdata ( struct t509_device *t509, void *priv ) {
+ t509->priv = priv;
+}
+
+/**
+ * Get 3c509 driver-private data
+ *
+ * @v t509 3c509 device
+ * @ret priv Private data
+ */
+static inline void * t509_get_drvdata ( struct t509_device *t509 ) {
+ return t509->priv;
+}
+
+/*
+ * t509 utility functions
+ *
+ */
+
+static inline void t509_set_id_port ( void ) {
+ outb ( 0x00, t509_id_port );
+}
+
+static inline void t509_wait_for_id_sequence ( void ) {
+ outb ( 0x00, t509_id_port );
+}
+
+static inline void t509_global_reset ( void ) {
+ outb ( 0xc0, t509_id_port );
+}
+
+static inline void t509_reset_tag ( void ) {
+ outb ( 0xd0, t509_id_port );
+}
+
+static inline void t509_set_tag ( uint8_t tag ) {
+ outb ( 0xd0 | tag, t509_id_port );
+}
+
+static inline void t509_select_tag ( uint8_t tag ) {
+ outb ( 0xd8 | tag, t509_id_port );
+}
+
+static inline void t509_activate ( uint16_t ioaddr ) {
+ outb ( 0xe0 | ( ioaddr >> 4 ), t509_id_port );
+}
+
+static inline void t509_deactivate_and_reset_tag ( uint16_t ioaddr ) {
+ outb ( GLOBAL_RESET, ioaddr + EP_COMMAND );
+}
+
+static inline void t509_load_eeprom_word ( uint8_t offset ) {
+ outb ( 0x80 | offset, t509_id_port );
+}
+
+/*
+ * Find a suitable ID port
+ *
+ */
+static inline int t509_find_id_port ( void ) {
+
+ for ( t509_id_port = EP_ID_PORT_START ;
+ t509_id_port < EP_ID_PORT_END ;
+ t509_id_port += EP_ID_PORT_INC ) {
+ t509_set_id_port ();
+ /* See if anything's listening */
+ outb ( 0xff, t509_id_port );
+ if ( inb ( t509_id_port ) & 0x01 ) {
+ /* Found a suitable port */
+ DBG ( "T509 using ID port at %04x\n", t509_id_port );
+ return 0;
+ }
+ }
+ /* No id port available */
+ DBG ( "T509 found no available ID port\n" );
+ return -ENOENT;
+}
+
+/*
+ * Send ID sequence to the ID port
+ *
+ */
+static void t509_send_id_sequence ( void ) {
+ unsigned short lrs_state, i;
+
+ t509_set_id_port ();
+ /* Reset IDS on cards */
+ t509_wait_for_id_sequence ();
+ lrs_state = 0xff;
+ for ( i = 0; i < 255; i++ ) {
+ outb ( lrs_state, t509_id_port );
+ lrs_state <<= 1;
+ lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
+ }
+}
+
+/*
+ * We get eeprom data from the id_port given an offset into the eeprom.
+ * Basically; after the ID_sequence is sent to all of the cards; they enter
+ * the ID_CMD state where they will accept command requests. 0x80-0xbf loads
+ * the eeprom data. We then read the port 16 times and with every read; the
+ * cards check for contention (ie: if one card writes a 0 bit and another
+ * writes a 1 bit then the host sees a 0. At the end of the cycle; each card
+ * compares the data on the bus; if there is a difference then that card goes
+ * into ID_WAIT state again). In the meantime; one bit of data is returned in
+ * the AX register which is conveniently returned to us by inb(). Hence; we
+ * read 16 times getting one bit of data with each read.
+ */
+static uint16_t t509_id_read_eeprom ( int offset ) {
+ int i, data = 0;
+
+ t509_load_eeprom_word ( offset );
+ /* Do we really need this wait? Won't be noticeable anyway */
+ udelay(10000);
+
+ for ( i = 0; i < 16; i++ ) {
+ data = ( data << 1 ) | ( inw ( t509_id_port ) & 1 );
+ }
+ return data;
+}
+
+/*
+ * Isolate and tag all t509 cards
+ *
+ */
+static int t509_isolate ( void ) {
+ unsigned int i;
+ uint16_t contend[3];
+ int rc;
+
+ /* Find a suitable ID port */
+ if ( ( rc = t509_find_id_port() ) != 0 )
+ return rc;
+
+ while ( 1 ) {
+
+ /* All cards are in ID_WAIT state each time we go
+ * through this loop.
+ */
+
+ /* Send the ID sequence */
+ t509_send_id_sequence();
+
+ /* First time through, reset all tags. On subsequent
+ * iterations, kill off any already-tagged cards
+ */
+ if ( t509_max_tag == 0 ) {
+ t509_reset_tag();
+ } else {
+ t509_select_tag ( 0 );
+ }
+
+ /* Read the manufacturer ID, to see if there are any
+ * more cards
+ */
+ if ( t509_id_read_eeprom ( EEPROM_MFG_ID ) != MFG_ID ) {
+ DBG ( "T509 saw %s signs of life\n",
+ t509_max_tag ? "no further" : "no" );
+ break;
+ }
+
+ /* Perform contention selection on the MAC address */
+ for ( i = 0 ; i < 3 ; i++ ) {
+ contend[i] = t509_id_read_eeprom ( i );
+ }
+
+ /* Only one device will still be left alive. Tag it. */
+ ++t509_max_tag;
+ DBG ( "T509 found card %04x%04x%04x, assigning tag %02x\n",
+ contend[0], contend[1], contend[2], t509_max_tag );
+ t509_set_tag ( t509_max_tag );
+
+ /* Return all cards back to ID_WAIT state */
+ t509_wait_for_id_sequence();
+ }
+
+ DBG ( "T509 found %d cards using ID port %04x\n",
+ t509_max_tag, t509_id_port );
+ return 0;
+}
+
+/*
+ * Activate a T509 device
+ *
+ * The device will be enabled at whatever ioaddr is specified in the
+ * struct t509_device; there is no need to stick with the default
+ * ioaddr read from the EEPROM.
+ *
+ */
+static inline void activate_t509_device ( struct t509_device *t509 ) {
+ t509_send_id_sequence ();
+ t509_select_tag ( t509->tag );
+ t509_activate ( t509->ioaddr );
+ DBG ( "T509 activated device %02x at ioaddr %04x\n",
+ t509->tag, t509->ioaddr );
+}
+
+/*
+ * Deactivate a T509 device
+ *
+ * Disabling also clears the tag, so we immediately isolate and re-tag
+ * this card.
+ *
+ */
+static inline void deactivate_t509_device ( struct t509_device *t509 ) {
+ t509_deactivate_and_reset_tag ( t509->ioaddr );
+ udelay ( 1000 );
+ t509_send_id_sequence ();
+ t509_select_tag ( 0 );
+ t509_set_tag ( t509->tag );
+ t509_wait_for_id_sequence ();
+ DBG ( "T509 deactivated device at %04x and re-tagged as %02x\n",
+ t509->ioaddr, t509->tag );
+}
+
+/*
+ * The ISA probe function
+ *
+ */
+static int legacy_t509_probe ( struct nic *nic, void *hwdev ) {
+ struct t509_device *t509 = hwdev;
+
+ /* We could change t509->ioaddr if we wanted to */
+ activate_t509_device ( t509 );
+ nic->ioaddr = t509->ioaddr;
+
+ /* Hand off to generic t5x9 probe routine */
+ return t5x9_probe ( nic, ISA_PROD_ID ( PROD_ID ), ISA_PROD_ID_MASK );
+}
+
+static void legacy_t509_disable ( struct nic *nic, void *hwdev ) {
+ struct t509_device *t509 = hwdev;
+
+ t5x9_disable ( nic );
+ deactivate_t509_device ( t509 );
+}
+
+static inline void legacy_t509_set_drvdata ( void *hwdev, void *priv ) {
+ t509_set_drvdata ( hwdev, priv );
+}
+
+static inline void * legacy_t509_get_drvdata ( void *hwdev ) {
+ return t509_get_drvdata ( hwdev );
+}
+
+/**
+ * Probe a 3c509 device
+ *
+ * @v t509 3c509 device
+ * @ret rc Return status code
+ *
+ * Searches for a driver for the 3c509 device. If a driver is found,
+ * its probe() routine is called.
+ */
+static int t509_probe ( struct t509_device *t509 ) {
+ DBG ( "Adding 3c509 device %02x (I/O %04x)\n",
+ t509->tag, t509->ioaddr );
+ return legacy_probe ( t509, legacy_t509_set_drvdata, &t509->dev,
+ legacy_t509_probe, legacy_t509_disable );
+}
+
+/**
+ * Remove a 3c509 device
+ *
+ * @v t509 3c509 device
+ */
+static void t509_remove ( struct t509_device *t509 ) {
+ legacy_remove ( t509, legacy_t509_get_drvdata, legacy_t509_disable );
+ DBG ( "Removed 3c509 device %02x\n", t509->tag );
+}
+
+/**
+ * Probe 3c509 root bus
+ *
+ * @v rootdev 3c509 bus root device
+ *
+ * Scans the 3c509 bus for devices and registers all devices it can
+ * find.
+ */
+static int t509bus_probe ( struct root_device *rootdev ) {
+ struct t509_device *t509 = NULL;
+ unsigned int tag;
+ unsigned int iobase;
+ int rc;
+
+ /* Perform isolation and tagging */
+ if ( ( rc = t509_isolate() ) != 0 )
+ return rc;
+
+ for ( tag = 1 ; tag <= t509_max_tag ; tag++ ) {
+ /* Allocate struct t509_device */
+ if ( ! t509 )
+ t509 = malloc ( sizeof ( *t509 ) );
+ if ( ! t509 ) {
+ rc = -ENOMEM;
+ goto err;
+ }
+ memset ( t509, 0, sizeof ( *t509 ) );
+ t509->tag = tag;
+
+ /* Send the ID sequence */
+ t509_send_id_sequence ();
+
+ /* Select the specified tag */
+ t509_select_tag ( t509->tag );
+
+ /* Read the default I/O address */
+ iobase = t509_id_read_eeprom ( EEPROM_ADDR_CFG );
+ t509->ioaddr = 0x200 + ( ( iobase & 0x1f ) << 4 );
+
+ /* Send card back to ID_WAIT */
+ t509_wait_for_id_sequence();
+
+ /* Add to device hierarchy */
+ snprintf ( t509->dev.name, sizeof ( t509->dev.name ),
+ "t509%02x", tag );
+ t509->dev.desc.bus_type = BUS_TYPE_ISA;
+ t509->dev.desc.vendor = MFG_ID;
+ t509->dev.desc.device = PROD_ID;
+ t509->dev.parent = &rootdev->dev;
+ list_add ( &t509->dev.siblings, &rootdev->dev.children );
+ INIT_LIST_HEAD ( &t509->dev.children );
+
+ /* Look for a driver */
+ if ( t509_probe ( t509 ) == 0 ) {
+ /* t509dev registered, we can drop our ref */
+ t509 = NULL;
+ } else {
+ /* Not registered; re-use struct */
+ list_del ( &t509->dev.siblings );
+ }
+ }
+
+ free ( t509 );
+ return 0;
+
+ err:
+ free ( t509 );
+ t509bus_remove ( rootdev );
+ return rc;
+}
+
+/**
+ * Remove 3c509 root bus
+ *
+ * @v rootdev 3c509 bus root device
+ */
+static void t509bus_remove ( struct root_device *rootdev ) {
+ struct t509_device *t509;
+ struct t509_device *tmp;
+
+ list_for_each_entry_safe ( t509, tmp, &rootdev->dev.children,
+ dev.siblings ) {
+ t509_remove ( t509 );
+ list_del ( &t509->dev.siblings );
+ free ( t509 );
+ }
+}
+
+/** 3c509 bus root device driver */
+static struct root_driver t509_root_driver = {
+ .probe = t509bus_probe,
+ .remove = t509bus_remove,
+};
+
+/** 3c509 bus root device */
+struct root_device t509_root_device __root_device = {
+ .dev = { .name = "3c509" },
+ .driver = &t509_root_driver,
+};
+
+ISA_ROM ( "3c509", "3c509" );
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/3c509.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c509.h
new file mode 100644
index 00000000..90add6b6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c509.h
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2. The name
+ * of the author may not be used to endorse or promote products derived from
+ * this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * if_epreg.h,v 1.4 1994/11/13 10:12:37 gibbs Exp Modified by:
+ *
+ October 2, 1994
+
+ Modified by: Andres Vega Garcia
+
+ INRIA - Sophia Antipolis, France
+ e-mail: avega@sophia.inria.fr
+ finger: avega@pax.inria.fr
+
+ */
+
+FILE_LICENCE ( BSD3 );
+
+#include "nic.h"
+
+/*
+ * Ethernet software status per interface.
+ */
+/*
+ * Some global constants
+ */
+
+#define TX_INIT_RATE 16
+#define TX_INIT_MAX_RATE 64
+#define RX_INIT_LATENCY 64
+#define RX_INIT_EARLY_THRESH 64
+#define MIN_RX_EARLY_THRESHF 16 /* not less than ether_header */
+#define MIN_RX_EARLY_THRESHL 4
+
+#define EEPROMSIZE 0x40
+#define MAX_EEPROMBUSY 1000
+#define EP_ID_PORT_START 0x110 /* avoid 0x100 to avoid conflict with SB16 */
+#define EP_ID_PORT_INC 0x10
+#define EP_ID_PORT_END 0x200
+#define EP_TAG_MAX 0x7 /* must be 2^n - 1 */
+
+/*
+ * Commands to read/write EEPROM trough EEPROM command register (Window 0,
+ * Offset 0xa)
+ */
+#define EEPROM_CMD_RD 0x0080 /* Read: Address required (5 bits) */
+#define EEPROM_CMD_WR 0x0040 /* Write: Address required (5 bits) */
+#define EEPROM_CMD_ERASE 0x00c0 /* Erase: Address required (5 bits) */
+#define EEPROM_CMD_EWEN 0x0030 /* Erase/Write Enable: No data required */
+
+#define EEPROM_BUSY (1<<15)
+#define EEPROM_TST_MODE (1<<14)
+
+/*
+ * Some short functions, worth to let them be a macro
+ */
+#define is_eeprom_busy(b) (inw((b)+EP_W0_EEPROM_COMMAND)&EEPROM_BUSY)
+#define GO_WINDOW(b,x) outw(WINDOW_SELECT|(x), (b)+EP_COMMAND)
+
+/**************************************************************************
+ *
+ * These define the EEPROM data structure. They are used in the probe
+ * function to verify the existance of the adapter after having sent
+ * the ID_Sequence.
+ *
+ * There are others but only the ones we use are defined here.
+ *
+ **************************************************************************/
+
+#define EEPROM_NODE_ADDR_0 0x0 /* Word */
+#define EEPROM_NODE_ADDR_1 0x1 /* Word */
+#define EEPROM_NODE_ADDR_2 0x2 /* Word */
+#define EEPROM_PROD_ID 0x3 /* 0x9[0-f]50 */
+#define EEPROM_MFG_ID 0x7 /* 0x6d50 */
+#define EEPROM_ADDR_CFG 0x8 /* Base addr */
+#define EEPROM_RESOURCE_CFG 0x9 /* IRQ. Bits 12-15 */
+
+/**************************************************************************
+ *
+ * These are the registers for the 3Com 3c509 and their bit patterns when
+ * applicable. They have been taken out the "EtherLink III Parallel
+ * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual
+ * from 3com.
+ *
+ * Getting this document out of 3Com is almost impossible. However,
+ * archived copies are available at
+ * http://www.osdever.net/cottontail/downloads/docs/3c5x9b.zip and
+ * several other places on the web (search for 3c5x9b.pdf).
+ *
+ **************************************************************************/
+
+#define EP_COMMAND 0x0e /* Write. BASE+0x0e is always a
+ * command reg. */
+#define EP_STATUS 0x0e /* Read. BASE+0x0e is always status
+ * reg. */
+#define EP_WINDOW 0x0f /* Read. BASE+0x0f is always window
+ * reg. */
+/*
+ * Window 0 registers. Setup.
+ */
+/* Write */
+#define EP_W0_EEPROM_DATA 0x0c
+#define EP_W0_EEPROM_COMMAND 0x0a
+#define EP_W0_RESOURCE_CFG 0x08
+#define EP_W0_ADDRESS_CFG 0x06
+#define EP_W0_CONFIG_CTRL 0x04
+/* Read */
+#define EP_W0_PRODUCT_ID 0x02
+#define EP_W0_MFG_ID 0x00
+
+/*
+ * Window 1 registers. Operating Set.
+ */
+/* Write */
+#define EP_W1_TX_PIO_WR_2 0x02
+#define EP_W1_TX_PIO_WR_1 0x00
+/* Read */
+#define EP_W1_FREE_TX 0x0c
+#define EP_W1_TX_STATUS 0x0b /* byte */
+#define EP_W1_TIMER 0x0a /* byte */
+#define EP_W1_RX_STATUS 0x08
+#define EP_W1_RX_PIO_RD_2 0x02
+#define EP_W1_RX_PIO_RD_1 0x00
+
+/*
+ * Window 2 registers. Station Address Setup/Read
+ */
+/* Read/Write */
+#define EP_W2_ADDR_5 0x05
+#define EP_W2_ADDR_4 0x04
+#define EP_W2_ADDR_3 0x03
+#define EP_W2_ADDR_2 0x02
+#define EP_W2_ADDR_1 0x01
+#define EP_W2_ADDR_0 0x00
+
+/*
+ * Window 3 registers. FIFO Management.
+ */
+/* Read */
+#define EP_W3_FREE_TX 0x0c
+#define EP_W3_FREE_RX 0x0a
+
+/*
+ * Window 4 registers. Diagnostics.
+ */
+/* Read/Write */
+#define EP_W4_MEDIA_TYPE 0x0a
+#define EP_W4_CTRLR_STATUS 0x08
+#define EP_W4_NET_DIAG 0x06
+#define EP_W4_FIFO_DIAG 0x04
+#define EP_W4_HOST_DIAG 0x02
+#define EP_W4_TX_DIAG 0x00
+
+/*
+ * Window 5 Registers. Results and Internal status.
+ */
+/* Read */
+#define EP_W5_READ_0_MASK 0x0c
+#define EP_W5_INTR_MASK 0x0a
+#define EP_W5_RX_FILTER 0x08
+#define EP_W5_RX_EARLY_THRESH 0x06
+#define EP_W5_TX_AVAIL_THRESH 0x02
+#define EP_W5_TX_START_THRESH 0x00
+
+/*
+ * Window 6 registers. Statistics.
+ */
+/* Read/Write */
+#define TX_TOTAL_OK 0x0c
+#define RX_TOTAL_OK 0x0a
+#define TX_DEFERRALS 0x08
+#define RX_FRAMES_OK 0x07
+#define TX_FRAMES_OK 0x06
+#define RX_OVERRUNS 0x05
+#define TX_COLLISIONS 0x04
+#define TX_AFTER_1_COLLISION 0x03
+#define TX_AFTER_X_COLLISIONS 0x02
+#define TX_NO_SQE 0x01
+#define TX_CD_LOST 0x00
+
+/****************************************
+ *
+ * Register definitions.
+ *
+ ****************************************/
+
+/*
+ * Command register. All windows.
+ *
+ * 16 bit register.
+ * 15-11: 5-bit code for command to be executed.
+ * 10-0: 11-bit arg if any. For commands with no args;
+ * this can be set to anything.
+ */
+#define GLOBAL_RESET (unsigned short) 0x0000 /* Wait at least 1ms
+ * after issuing */
+#define WINDOW_SELECT (unsigned short) (0x1<<11)
+#define START_TRANSCEIVER (unsigned short) (0x2<<11) /* Read ADDR_CFG reg to
+ * determine whether
+ * this is needed. If
+ * so; wait 800 uSec
+ * before using trans-
+ * ceiver. */
+#define RX_DISABLE (unsigned short) (0x3<<11) /* state disabled on
+ * power-up */
+#define RX_ENABLE (unsigned short) (0x4<<11)
+#define RX_RESET (unsigned short) (0x5<<11)
+#define RX_DISCARD_TOP_PACK (unsigned short) (0x8<<11)
+#define TX_ENABLE (unsigned short) (0x9<<11)
+#define TX_DISABLE (unsigned short) (0xa<<11)
+#define TX_RESET (unsigned short) (0xb<<11)
+#define REQ_INTR (unsigned short) (0xc<<11)
+#define SET_INTR_MASK (unsigned short) (0xe<<11)
+#define SET_RD_0_MASK (unsigned short) (0xf<<11)
+#define SET_RX_FILTER (unsigned short) (0x10<<11)
+#define FIL_INDIVIDUAL (unsigned short) (0x1)
+#define FIL_GROUP (unsigned short) (0x2)
+#define FIL_BRDCST (unsigned short) (0x4)
+#define FIL_ALL (unsigned short) (0x8)
+#define SET_RX_EARLY_THRESH (unsigned short) (0x11<<11)
+#define SET_TX_AVAIL_THRESH (unsigned short) (0x12<<11)
+#define SET_TX_START_THRESH (unsigned short) (0x13<<11)
+#define STATS_ENABLE (unsigned short) (0x15<<11)
+#define STATS_DISABLE (unsigned short) (0x16<<11)
+#define STOP_TRANSCEIVER (unsigned short) (0x17<<11)
+/*
+ * The following C_* acknowledge the various interrupts. Some of them don't
+ * do anything. See the manual.
+ */
+#define ACK_INTR (unsigned short) (0x6800)
+#define C_INTR_LATCH (unsigned short) (ACK_INTR|0x1)
+#define C_CARD_FAILURE (unsigned short) (ACK_INTR|0x2)
+#define C_TX_COMPLETE (unsigned short) (ACK_INTR|0x4)
+#define C_TX_AVAIL (unsigned short) (ACK_INTR|0x8)
+#define C_RX_COMPLETE (unsigned short) (ACK_INTR|0x10)
+#define C_RX_EARLY (unsigned short) (ACK_INTR|0x20)
+#define C_INT_RQD (unsigned short) (ACK_INTR|0x40)
+#define C_UPD_STATS (unsigned short) (ACK_INTR|0x80)
+
+/*
+ * Status register. All windows.
+ *
+ * 15-13: Window number(0-7).
+ * 12: Command_in_progress.
+ * 11: reserved.
+ * 10: reserved.
+ * 9: reserved.
+ * 8: reserved.
+ * 7: Update Statistics.
+ * 6: Interrupt Requested.
+ * 5: RX Early.
+ * 4: RX Complete.
+ * 3: TX Available.
+ * 2: TX Complete.
+ * 1: Adapter Failure.
+ * 0: Interrupt Latch.
+ */
+#define S_INTR_LATCH (unsigned short) (0x1)
+#define S_CARD_FAILURE (unsigned short) (0x2)
+#define S_TX_COMPLETE (unsigned short) (0x4)
+#define S_TX_AVAIL (unsigned short) (0x8)
+#define S_RX_COMPLETE (unsigned short) (0x10)
+#define S_RX_EARLY (unsigned short) (0x20)
+#define S_INT_RQD (unsigned short) (0x40)
+#define S_UPD_STATS (unsigned short) (0x80)
+#define S_5_INTS (S_CARD_FAILURE|S_TX_COMPLETE|\
+ S_TX_AVAIL|S_RX_COMPLETE|S_RX_EARLY)
+#define S_COMMAND_IN_PROGRESS (unsigned short) (0x1000)
+
+/*
+ * FIFO Registers.
+ * RX Status. Window 1/Port 08
+ *
+ * 15: Incomplete or FIFO empty.
+ * 14: 1: Error in RX Packet 0: Incomplete or no error.
+ * 13-11: Type of error.
+ * 1000 = Overrun.
+ * 1011 = Run Packet Error.
+ * 1100 = Alignment Error.
+ * 1101 = CRC Error.
+ * 1001 = Oversize Packet Error (>1514 bytes)
+ * 0010 = Dribble Bits.
+ * (all other error codes, no errors.)
+ *
+ * 10-0: RX Bytes (0-1514)
+ */
+#define ERR_RX_INCOMPLETE (unsigned short) (0x1<<15)
+#define ERR_RX (unsigned short) (0x1<<14)
+#define ERR_RX_OVERRUN (unsigned short) (0x8<<11)
+#define ERR_RX_RUN_PKT (unsigned short) (0xb<<11)
+#define ERR_RX_ALIGN (unsigned short) (0xc<<11)
+#define ERR_RX_CRC (unsigned short) (0xd<<11)
+#define ERR_RX_OVERSIZE (unsigned short) (0x9<<11)
+#define ERR_RX_DRIBBLE (unsigned short) (0x2<<11)
+
+/*
+ * FIFO Registers.
+ * TX Status. Window 1/Port 0B
+ *
+ * Reports the transmit status of a completed transmission. Writing this
+ * register pops the transmit completion stack.
+ *
+ * Window 1/Port 0x0b.
+ *
+ * 7: Complete
+ * 6: Interrupt on successful transmission requested.
+ * 5: Jabber Error (TP Only, TX Reset required. )
+ * 4: Underrun (TX Reset required. )
+ * 3: Maximum Collisions.
+ * 2: TX Status Overflow.
+ * 1-0: Undefined.
+ *
+ */
+#define TXS_COMPLETE 0x80
+#define TXS_SUCCES_INTR_REQ 0x40
+#define TXS_JABBER 0x20
+#define TXS_UNDERRUN 0x10
+#define TXS_MAX_COLLISION 0x8
+#define TXS_STATUS_OVERFLOW 0x4
+
+/*
+ * Configuration control register.
+ * Window 0/Port 04
+ */
+/* Read */
+#define IS_AUI (1<<13)
+#define IS_BNC (1<<12)
+#define IS_UTP (1<<9)
+/* Write */
+#define ENABLE_DRQ_IRQ 0x0001
+#define W0_P4_CMD_RESET_ADAPTER 0x4
+#define W0_P4_CMD_ENABLE_ADAPTER 0x1
+/*
+ * Media type and status.
+ * Window 4/Port 0A
+ */
+#define ENABLE_UTP 0xc0
+#define DISABLE_UTP 0x0
+
+/*
+ * Resource control register
+ */
+
+#define SET_IRQ(i) ( ((i)<<12) | 0xF00) /* set IRQ i */
+
+/*
+ * Receive status register
+ */
+
+#define RX_BYTES_MASK (unsigned short) (0x07ff)
+#define RX_ERROR 0x4000
+#define RX_INCOMPLETE 0x8000
+
+/*
+ * Misc defines for various things.
+ */
+#define MFG_ID 0x6d50 /* in EEPROM and W0 ADDR_CONFIG */
+#define PROD_ID 0x9150
+
+#define AUI 0x1
+#define BNC 0x2
+#define UTP 0x4
+
+#define RX_BYTES_MASK (unsigned short) (0x07ff)
+
+/*
+ * Function shared between 3c509.c and 3c529.c
+ */
+extern int t5x9_probe ( struct nic *nic,
+ uint16_t prod_id_check, uint16_t prod_id_mask );
+extern void t5x9_disable ( struct nic *nic );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/3c515.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c515.c
new file mode 100644
index 00000000..8ed87081
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c515.c
@@ -0,0 +1,772 @@
+/*
+* 3c515.c -- 3COM 3C515 Fast Etherlink ISA 10/100BASE-TX driver for etherboot
+* Copyright (C) 2002 Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code:
+* Copyright (C) 1997-2002 Donald Becker 3c515.c: A 3Com ISA EtherLink XL "Corkscrew" ethernet driver for linux.
+* Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk) ISAPNP Tools
+* Copyright (c) 2002 Jaroslav Kysela <perex@suse.cz> ISA Plug & Play support Linux Kernel
+* Copyright (C) 2000 Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp> etherboot-5.0.5 3c595.c
+* Coptright (C) 1995 Martin Renters etherboot-5.0.5 3c509.c
+* Copyright (C) 1999 LightSys Technology Services, Inc. etherboot-5.0.5 3c90x.c
+* Portions Copyright (C) 1999 Steve Smith etherboot-5.0.5 3c90x.c
+*
+* The probe and reset functions and defines are direct copies from the
+* Becker code modified where necessary to make it work for etherboot
+*
+* The poll and transmit functions either contain code from or were written by referencing
+* the above referenced etherboot drivers. This driver would not have been
+* possible without this prior work
+*
+* REVISION HISTORY:
+* ================
+* v0.10 4-17-2002 TJL Initial implementation.
+* v0.11 4-17-2002 TJL Cleanup of the code
+* v0.12 4-26-2002 TJL Added ISA Plug and Play for Non-PNP Bioses
+* v0.13 6-10-2002 TJL Fixed ISA_PNP MAC Address problem
+* v0.14 9-23-2003 TJL Replaced delay with currticks
+*
+* Indent Options: indent -kr -i8
+* *********************************************************/
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* to get some global routines like printf */
+#include "etherboot.h"
+/* to get the interface to the body of the program */
+#include "nic.h"
+#include <ipxe/isapnp.h>
+#include <ipxe/isa.h> /* for ISA_ROM */
+#include <ipxe/ethernet.h>
+
+static void t3c515_wait(unsigned int nticks)
+{
+ unsigned int to = currticks() + nticks;
+ while (currticks() < to)
+ /* wait */ ;
+}
+
+/* TJL definations */
+#define HZ 100
+static int if_port;
+static struct corkscrew_private *vp;
+/* Brought directly from 3c515.c by Becker */
+#define CORKSCREW 1
+
+/* Maximum events (Rx packets, etc.) to handle at each interrupt.
+static int max_interrupt_work = 20;
+*/
+
+/* Enable the automatic media selection code -- usually set. */
+#define AUTOMEDIA 1
+
+/* Allow the use of fragment bus master transfers instead of only
+ programmed-I/O for Vortex cards. Full-bus-master transfers are always
+ enabled by default on Boomerang cards. If VORTEX_BUS_MASTER is defined,
+ the feature may be turned on using 'options'. */
+#define VORTEX_BUS_MASTER
+
+/* A few values that may be tweaked. */
+/* Keep the ring sizes a power of two for efficiency. */
+#define TX_RING_SIZE 16
+#define RX_RING_SIZE 16
+#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */
+
+/* "Knobs" for adjusting internal parameters. */
+/* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */
+#define DRIVER_DEBUG 1
+/* Some values here only for performance evaluation and path-coverage
+ debugging.
+static int rx_nocopy, rx_copy, queued_packet;
+*/
+
+#define CORKSCREW_ID 10
+
+#define EL3WINDOW(win_num) \
+ outw(SelectWindow + (win_num), nic->ioaddr + EL3_CMD)
+#define EL3_CMD 0x0e
+#define EL3_STATUS 0x0e
+#define RX_BYTES_MASK (unsigned short) (0x07ff)
+
+enum corkscrew_cmd {
+ TotalReset = 0 << 11, SelectWindow = 1 << 11, StartCoax = 2 << 11,
+ RxDisable = 3 << 11, RxEnable = 4 << 11, RxReset = 5 << 11,
+ UpStall = 6 << 11, UpUnstall = (6 << 11) + 1,
+ DownStall = (6 << 11) + 2, DownUnstall = (6 << 11) + 3,
+ RxDiscard = 8 << 11, TxEnable = 9 << 11, TxDisable =
+ 10 << 11, TxReset = 11 << 11,
+ FakeIntr = 12 << 11, AckIntr = 13 << 11, SetIntrEnb = 14 << 11,
+ SetStatusEnb = 15 << 11, SetRxFilter = 16 << 11, SetRxThreshold =
+ 17 << 11,
+ SetTxThreshold = 18 << 11, SetTxStart = 19 << 11,
+ StartDMAUp = 20 << 11, StartDMADown = (20 << 11) + 1, StatsEnable =
+ 21 << 11,
+ StatsDisable = 22 << 11, StopCoax = 23 << 11,
+};
+
+/* The SetRxFilter command accepts the following classes: */
+enum RxFilter {
+ RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
+};
+
+/* Bits in the general status register. */
+enum corkscrew_status {
+ IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
+ TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
+ IntReq = 0x0040, StatsFull = 0x0080,
+ DMADone = 1 << 8, DownComplete = 1 << 9, UpComplete = 1 << 10,
+ DMAInProgress = 1 << 11, /* DMA controller is still busy. */
+ CmdInProgress = 1 << 12, /* EL3_CMD is still busy. */
+};
+
+/* Register window 1 offsets, the window used in normal operation.
+ On the Corkscrew this window is always mapped at offsets 0x10-0x1f. */
+enum Window1 {
+ TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
+ RxStatus = 0x18, Timer = 0x1A, TxStatus = 0x1B,
+ TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */
+};
+enum Window0 {
+ Wn0IRQ = 0x08,
+#if defined(CORKSCREW)
+ Wn0EepromCmd = 0x200A, /* Corkscrew EEPROM command register. */
+ Wn0EepromData = 0x200C, /* Corkscrew EEPROM results register. */
+#else
+ Wn0EepromCmd = 10, /* Window 0: EEPROM command register. */
+ Wn0EepromData = 12, /* Window 0: EEPROM results register. */
+#endif
+};
+enum Win0_EEPROM_bits {
+ EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
+ EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */
+ EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */
+};
+
+enum Window3 { /* Window 3: MAC/config bits. */
+ Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
+};
+union wn3_config {
+ int i;
+ struct w3_config_fields {
+ unsigned int ram_size:3, ram_width:1, ram_speed:2,
+ rom_size:2;
+ int pad8:8;
+ unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1,
+ autoselect:1;
+ int pad24:7;
+ } u;
+};
+
+enum Window4 {
+ Wn4_NetDiag = 6, Wn4_Media = 10, /* Window 4: Xcvr/media bits. */
+};
+enum Win4_Media_bits {
+ Media_SQE = 0x0008, /* Enable SQE error counting for AUI. */
+ Media_10TP = 0x00C0, /* Enable link beat and jabber for 10baseT. */
+ Media_Lnk = 0x0080, /* Enable just link beat for 100TX/100FX. */
+ Media_LnkBeat = 0x0800,
+};
+enum Window7 { /* Window 7: Bus Master control. */
+ Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
+};
+
+/* Boomerang-style bus master control registers. Note ISA aliases! */
+enum MasterCtrl {
+ PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen =
+ 0x40c,
+ TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418,
+};
+
+/* The Rx and Tx descriptor lists.
+ Caution Alpha hackers: these types are 32 bits! Note also the 8 byte
+ alignment contraint on tx_ring[] and rx_ring[]. */
+struct boom_rx_desc {
+ u32 next;
+ s32 status;
+ u32 addr;
+ s32 length;
+};
+
+/* Values for the Rx status entry. */
+enum rx_desc_status {
+ RxDComplete = 0x00008000, RxDError = 0x4000,
+ /* See boomerang_rx() for actual error bits */
+};
+
+struct boom_tx_desc {
+ u32 next;
+ s32 status;
+ u32 addr;
+ s32 length;
+};
+
+struct corkscrew_private {
+ const char *product_name;
+ struct net_device *next_module;
+ /* The Rx and Tx rings are here to keep them quad-word-aligned. */
+ struct boom_rx_desc rx_ring[RX_RING_SIZE];
+ struct boom_tx_desc tx_ring[TX_RING_SIZE];
+ /* The addresses of transmit- and receive-in-place skbuffs. */
+ struct sk_buff *rx_skbuff[RX_RING_SIZE];
+ struct sk_buff *tx_skbuff[TX_RING_SIZE];
+ unsigned int cur_rx, cur_tx; /* The next free ring entry */
+ unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
+ struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */
+ int capabilities; /* Adapter capabilities word. */
+ int options; /* User-settable misc. driver options. */
+ int last_rx_packets; /* For media autoselection. */
+ unsigned int available_media:8, /* From Wn3_Options */
+ media_override:3, /* Passed-in media type. */
+ default_media:3, /* Read from the EEPROM. */
+ full_duplex:1, autoselect:1, bus_master:1, /* Vortex can only do a fragment bus-m. */
+ full_bus_master_tx:1, full_bus_master_rx:1, /* Boomerang */
+ tx_full:1;
+};
+
+/* The action to take with a media selection timer tick.
+ Note that we deviate from the 3Com order by checking 10base2 before AUI.
+ */
+enum xcvr_types {
+ XCVR_10baseT =
+ 0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
+ XCVR_100baseFx, XCVR_MII = 6, XCVR_Default = 8,
+};
+
+static struct media_table {
+ char *name;
+ unsigned int media_bits:16, /* Bits to set in Wn4_Media register. */
+ mask:8, /* The transceiver-present bit in Wn3_Config. */
+ next:8; /* The media type to try next. */
+ short wait; /* Time before we check media status. */
+} media_tbl[] = {
+ {
+ "10baseT", Media_10TP, 0x08, XCVR_10base2, (14 * HZ) / 10}
+ , {
+ "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1 * HZ) / 10}
+ , {
+ "undefined", 0, 0x80, XCVR_10baseT, 10000}
+ , {
+ "10base2", 0, 0x10, XCVR_AUI, (1 * HZ) / 10}
+ , {
+ "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx,
+ (14 * HZ) / 10}
+ , {
+ "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14 * HZ) / 10}
+ , {
+ "MII", 0, 0x40, XCVR_10baseT, 3 * HZ}
+ , {
+ "undefined", 0, 0x01, XCVR_10baseT, 10000}
+ , {
+ "Default", 0, 0xFF, XCVR_10baseT, 10000}
+,};
+
+/* TILEG Modified to remove reference to dev */
+static int corkscrew_found_device(int ioaddr, int irq, int product_index,
+ int options, struct nic *nic);
+static int corkscrew_probe1(int ioaddr, int irq, int product_index,
+ struct nic *nic);
+
+/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
+/* Note: this is the only limit on the number of cards supported!! */
+static int options = -1;
+
+/* End Brought directly from 3c515.c by Becker */
+
+/**************************************************************************
+RESET - Reset adapter
+***************************************************************************/
+static void t515_reset(struct nic *nic)
+{
+ union wn3_config config;
+ int i;
+
+ /* Before initializing select the active media port. */
+ EL3WINDOW(3);
+ if (vp->full_duplex)
+ outb(0x20, nic->ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */
+ config.i = inl(nic->ioaddr + Wn3_Config);
+
+ if (vp->media_override != 7) {
+ DBG ( "Media override to transceiver %d (%s).\n",
+ vp->media_override,
+ media_tbl[vp->media_override].name);
+ if_port = vp->media_override;
+ } else if (vp->autoselect) {
+ /* Find first available media type, starting with 100baseTx. */
+ if_port = 4;
+ while (!(vp->available_media & media_tbl[if_port].mask))
+ if_port = media_tbl[if_port].next;
+
+ DBG ( "Initial media type %s.\n",
+ media_tbl[if_port].name);
+ } else
+ if_port = vp->default_media;
+
+ config.u.xcvr = if_port;
+ outl(config.i, nic->ioaddr + Wn3_Config);
+
+ DBG ( "corkscrew_open() InternalConfig 0x%hX.\n",
+ config.i);
+
+ outw(TxReset, nic->ioaddr + EL3_CMD);
+ for (i = 20; i >= 0; i--)
+ if (!(inw(nic->ioaddr + EL3_STATUS) & CmdInProgress))
+ break;
+
+ outw(RxReset, nic->ioaddr + EL3_CMD);
+ /* Wait a few ticks for the RxReset command to complete. */
+ for (i = 20; i >= 0; i--)
+ if (!(inw(nic->ioaddr + EL3_STATUS) & CmdInProgress))
+ break;
+
+ outw(SetStatusEnb | 0x00, nic->ioaddr + EL3_CMD);
+
+#ifdef debug_3c515
+ EL3WINDOW(4);
+ DBG ( "FIXME: fix print for irq, not 9" );
+ DBG ( "corkscrew_open() irq %d media status 0x%hX.\n",
+ 9, inw(nic->ioaddr + Wn4_Media) );
+#endif
+
+ /* Set the station address and mask in window 2 each time opened. */
+ EL3WINDOW(2);
+ for (i = 0; i < 6; i++)
+ outb(nic->node_addr[i], nic->ioaddr + i);
+ for (; i < 12; i += 2)
+ outw(0, nic->ioaddr + i);
+
+ if (if_port == 3)
+ /* Start the thinnet transceiver. We should really wait 50ms... */
+ outw(StartCoax, nic->ioaddr + EL3_CMD);
+ EL3WINDOW(4);
+ outw((inw(nic->ioaddr + Wn4_Media) & ~(Media_10TP | Media_SQE)) |
+ media_tbl[if_port].media_bits, nic->ioaddr + Wn4_Media);
+
+ /* Switch to the stats window, and clear all stats by reading. */
+/* outw(StatsDisable, nic->ioaddr + EL3_CMD);*/
+ EL3WINDOW(6);
+ for (i = 0; i < 10; i++)
+ inb(nic->ioaddr + i);
+ inw(nic->ioaddr + 10);
+ inw(nic->ioaddr + 12);
+ /* New: On the Vortex we must also clear the BadSSD counter. */
+ EL3WINDOW(4);
+ inb(nic->ioaddr + 12);
+ /* ..and on the Boomerang we enable the extra statistics bits. */
+ outw(0x0040, nic->ioaddr + Wn4_NetDiag);
+
+ /* Switch to register set 7 for normal use. */
+ EL3WINDOW(7);
+
+ /* Temporarily left in place. If these FIXMEs are printed
+ it meand that special logic for that card may need to be added
+ see Becker's 3c515.c driver */
+ if (vp->full_bus_master_rx) { /* Boomerang bus master. */
+ printf("FIXME: Is this if necessary");
+ vp->cur_rx = vp->dirty_rx = 0;
+ DBG ( " Filling in the Rx ring.\n" );
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ printf("FIXME: Is this if necessary");
+ }
+ }
+ if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */
+ vp->cur_tx = vp->dirty_tx = 0;
+ outb(PKT_BUF_SZ >> 8, nic->ioaddr + TxFreeThreshold); /* Room for a packet. */
+ /* Clear the Tx ring. */
+ for (i = 0; i < TX_RING_SIZE; i++)
+ vp->tx_skbuff[i] = 0;
+ outl(0, nic->ioaddr + DownListPtr);
+ }
+ /* Set receiver mode: presumably accept b-case and phys addr only. */
+ outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
+ nic->ioaddr + EL3_CMD);
+
+ outw(RxEnable, nic->ioaddr + EL3_CMD); /* Enable the receiver. */
+ outw(TxEnable, nic->ioaddr + EL3_CMD); /* Enable transmitter. */
+ /* Allow status bits to be seen. */
+ outw(SetStatusEnb | AdapterFailure | IntReq | StatsFull |
+ (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
+ (vp->full_bus_master_rx ? UpComplete : RxComplete) |
+ (vp->bus_master ? DMADone : 0), nic->ioaddr + EL3_CMD);
+ /* Ack all pending events, and set active indicator mask. */
+ outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+ nic->ioaddr + EL3_CMD);
+ outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
+ | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
+ nic->ioaddr + EL3_CMD);
+
+}
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int t515_poll(struct nic *nic, int retrieve)
+{
+ short status, cst;
+ register short rx_fifo;
+
+ cst = inw(nic->ioaddr + EL3_STATUS);
+
+ if ((cst & RxComplete) == 0) {
+ /* Ack all pending events, and set active indicator mask. */
+ outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+ nic->ioaddr + EL3_CMD);
+ outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete |
+ StatsFull | (vp->
+ bus_master ? DMADone : 0) | UpComplete |
+ DownComplete, nic->ioaddr + EL3_CMD);
+ return 0;
+ }
+ status = inw(nic->ioaddr + RxStatus);
+
+ if (status & RxDError) {
+ printf("RxDError\n");
+ outw(RxDiscard, nic->ioaddr + EL3_CMD);
+ return 0;
+ }
+
+ rx_fifo = status & RX_BYTES_MASK;
+ if (rx_fifo == 0)
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+ DBG ( "[l=%d", rx_fifo );
+ insw(nic->ioaddr + RX_FIFO, nic->packet, rx_fifo / 2);
+ if (rx_fifo & 1)
+ nic->packet[rx_fifo - 1] = inb(nic->ioaddr + RX_FIFO);
+ nic->packetlen = rx_fifo;
+
+ while (1) {
+ status = inw(nic->ioaddr + RxStatus);
+ DBG ( "0x%hX*", status );
+ rx_fifo = status & RX_BYTES_MASK;
+
+ if (rx_fifo > 0) {
+ insw(nic->ioaddr + RX_FIFO, nic->packet + nic->packetlen,
+ rx_fifo / 2);
+ if (rx_fifo & 1)
+ nic->packet[nic->packetlen + rx_fifo - 1] =
+ inb(nic->ioaddr + RX_FIFO);
+ nic->packetlen += rx_fifo;
+ DBG ( "+%d", rx_fifo );
+ }
+ if ((status & RxComplete) == 0) {
+ DBG ( "=%d", nic->packetlen );
+ break;
+ }
+ udelay(1000);
+ }
+
+ /* acknowledge reception of packet */
+ outw(RxDiscard, nic->ioaddr + EL3_CMD);
+ while (inw(nic->ioaddr + EL3_STATUS) & CmdInProgress);
+#ifdef debug_3c515
+ {
+ unsigned short type = 0;
+ type = (nic->packet[12] << 8) | nic->packet[13];
+ if (nic->packet[0] + nic->packet[1] + nic->packet[2] +
+ nic->packet[3] + nic->packet[4] + nic->packet[5] ==
+ 0xFF * ETH_ALEN)
+ DBG ( ",t=0x%hX,b]", type );
+ else
+ DBG ( ",t=0x%hX]", type );
+ }
+#endif
+
+ return 1;
+}
+
+/*************************************************************************
+ 3Com 515 - specific routines
+**************************************************************************/
+static char padmap[] = {
+ 0, 3, 2, 1
+};
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void t515_transmit(struct nic *nic, const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p)
+{ /* Packet */
+ register int len;
+ int pad;
+ int status;
+
+ DBG ( "{l=%d,t=0x%hX}", s + ETH_HLEN, t );
+
+ /* swap bytes of type */
+ t = htons(t);
+
+ len = s + ETH_HLEN; /* actual length of packet */
+ pad = padmap[len & 3];
+
+ /*
+ * The 3c515 automatically pads short packets to minimum ethernet length,
+ * but we drop packets that are too large. Perhaps we should truncate
+ * them instead?
+ Copied from 3c595. Is this true for the 3c515?
+ */
+ if (len + pad > ETH_FRAME_LEN) {
+ return;
+ }
+ /* drop acknowledgements */
+ while ((status = inb(nic->ioaddr + TxStatus)) & TxComplete) {
+ /*if(status & (TXS_UNDERRUN|0x88|TXS_STATUS_OVERFLOW)) { */
+ outw(TxReset, nic->ioaddr + EL3_CMD);
+ outw(TxEnable, nic->ioaddr + EL3_CMD);
+/* } */
+
+ outb(0x0, nic->ioaddr + TxStatus);
+ }
+
+ while (inw(nic->ioaddr + TxFree) < len + pad + 4) {
+ /* no room in FIFO */
+ }
+
+ outw(len, nic->ioaddr + TX_FIFO);
+ outw(0x0, nic->ioaddr + TX_FIFO); /* Second dword meaningless */
+
+ /* write packet */
+ outsw(nic->ioaddr + TX_FIFO, d, ETH_ALEN / 2);
+ outsw(nic->ioaddr + TX_FIFO, nic->node_addr, ETH_ALEN / 2);
+ outw(t, nic->ioaddr + TX_FIFO);
+ outsw(nic->ioaddr + TX_FIFO, p, s / 2);
+
+ if (s & 1)
+ outb(*(p + s - 1), nic->ioaddr + TX_FIFO);
+
+ while (pad--)
+ outb(0, nic->ioaddr + TX_FIFO); /* Padding */
+
+ /* wait for Tx complete */
+ while ((inw(nic->ioaddr + EL3_STATUS) & CmdInProgress) != 0);
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void t515_disable ( struct nic *nic,
+ struct isapnp_device *isapnp ) {
+
+ t515_reset(nic);
+
+ /* This is a hack. Since ltsp worked on my
+ system without any disable functionality I
+ have no way to determine if this works */
+
+ /* Disable the receiver and transmitter. */
+ outw(RxDisable, nic->ioaddr + EL3_CMD);
+ outw(TxDisable, nic->ioaddr + EL3_CMD);
+
+ if (if_port == XCVR_10base2)
+ /* Turn off thinnet power. Green! */
+ outw(StopCoax, nic->ioaddr + EL3_CMD);
+
+
+ outw(SetIntrEnb | 0x0000, nic->ioaddr + EL3_CMD);
+
+ deactivate_isapnp_device ( isapnp );
+ return;
+}
+
+static void t515_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations t515_operations = {
+ .connect = dummy_connect,
+ .poll = t515_poll,
+ .transmit = t515_transmit,
+ .irq = t515_irq,
+
+};
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+You should omit the last argument struct pci_device * for a non-PCI NIC
+***************************************************************************/
+static int t515_probe ( struct nic *nic, struct isapnp_device *isapnp ) {
+
+ /* Direct copy from Beckers 3c515.c removing any ISAPNP sections */
+
+ nic->ioaddr = isapnp->ioaddr;
+ nic->irqno = isapnp->irqno;
+ activate_isapnp_device ( isapnp );
+
+ /* Check the resource configuration for a matching ioaddr. */
+ if ((unsigned)(inw(nic->ioaddr + 0x2002) & 0x1f0)
+ != (nic->ioaddr & 0x1f0)) {
+ DBG ( "3c515 ioaddr mismatch\n" );
+ return 0;
+ }
+
+ /* Verify by reading the device ID from the EEPROM. */
+ {
+ int timer;
+ outw(EEPROM_Read + 7, nic->ioaddr + Wn0EepromCmd);
+ /* Pause for at least 162 us. for the read to take place. */
+ for (timer = 4; timer >= 0; timer--) {
+ t3c515_wait(1);
+ if ((inw(nic->ioaddr + Wn0EepromCmd) & 0x0200) == 0)
+ break;
+ }
+ if (inw(nic->ioaddr + Wn0EepromData) != 0x6d50) {
+ DBG ( "3c515 read incorrect vendor ID from EEPROM" );
+ return 0;
+ }
+
+ }
+ DBG ( "3c515 Resource configuration register 0x%X, DCR 0x%hX.\n",
+ inl(nic->ioaddr + 0x2002), inw(nic->ioaddr + 0x2000) );
+ corkscrew_found_device(nic->ioaddr, nic->irqno, CORKSCREW_ID,
+ options, nic);
+
+ t515_reset(nic);
+ nic->nic_op = &t515_operations;
+ return 1;
+}
+
+static int
+corkscrew_found_device(int ioaddr, int irq,
+ int product_index, int options, struct nic *nic)
+{
+ /* Direct copy from Becker 3c515.c with unecessary parts removed */
+ vp->product_name = "3c515";
+ vp->options = options;
+ if (options >= 0) {
+ vp->media_override =
+ ((options & 7) == 2) ? 0 : options & 7;
+ vp->full_duplex = (options & 8) ? 1 : 0;
+ vp->bus_master = (options & 16) ? 1 : 0;
+ } else {
+ vp->media_override = 7;
+ vp->full_duplex = 0;
+ vp->bus_master = 0;
+ }
+
+ corkscrew_probe1(ioaddr, irq, product_index, nic);
+ return 0;
+}
+
+static int
+corkscrew_probe1(int ioaddr, int irq, int product_index __unused,
+ struct nic *nic)
+{
+ unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
+ int i;
+
+ printf("3Com %s at 0x%hX, ", vp->product_name, ioaddr);
+
+ /* Read the station address from the EEPROM. */
+ EL3WINDOW(0);
+ for (i = 0; i < 0x18; i++) {
+ short *phys_addr = (short *) nic->node_addr;
+ int timer;
+ outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
+ /* Pause for at least 162 us. for the read to take place. */
+ for (timer = 4; timer >= 0; timer--) {
+ t3c515_wait(1);
+ if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
+ break;
+ }
+ eeprom[i] = inw(ioaddr + Wn0EepromData);
+ DBG ( "Value %d: %hX ", i, eeprom[i] );
+ checksum ^= eeprom[i];
+ if (i < 3)
+ phys_addr[i] = htons(eeprom[i]);
+ }
+ checksum = (checksum ^ (checksum >> 8)) & 0xff;
+ if (checksum != 0x00)
+ printf(" ***INVALID CHECKSUM 0x%hX*** ", checksum);
+
+ DBG ( "%s", eth_ntoa ( nic->node_addr ) );
+
+ if (eeprom[16] == 0x11c7) { /* Corkscrew */
+
+ }
+ printf(", IRQ %d\n", irq);
+ /* Tell them about an invalid IRQ. */
+ if ( (irq <= 0 || irq > 15) ) {
+ DBG (" *** Warning: this IRQ is unlikely to work! ***\n" );
+ }
+
+ {
+ char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
+ union wn3_config config;
+ EL3WINDOW(3);
+ vp->available_media = inw(ioaddr + Wn3_Options);
+ config.i = inl(ioaddr + Wn3_Config);
+ DBG ( " Internal config register is %4.4x, "
+ "transceivers 0x%hX.\n",
+ config.i, inw(ioaddr + Wn3_Options) );
+ printf
+ (" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
+ 8 << config.u.ram_size,
+ config.u.ram_width ? "word" : "byte",
+ ram_split[config.u.ram_split],
+ config.u.autoselect ? "autoselect/" : "",
+ media_tbl[config.u.xcvr].name);
+ if_port = config.u.xcvr;
+ vp->default_media = config.u.xcvr;
+ vp->autoselect = config.u.autoselect;
+ }
+ if (vp->media_override != 7) {
+ printf(" Media override to transceiver type %d (%s).\n",
+ vp->media_override,
+ media_tbl[vp->media_override].name);
+ if_port = vp->media_override;
+ }
+
+ vp->capabilities = eeprom[16];
+ vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0;
+ /* Rx is broken at 10mbps, so we always disable it. */
+ /* vp->full_bus_master_rx = 0; */
+ vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
+
+ return 0;
+}
+
+static struct isapnp_device_id t515_adapters[] = {
+ { "3c515 (ISAPnP)", ISAPNP_VENDOR('T','C','M'), 0x5051 },
+};
+
+ISAPNP_DRIVER ( t515_driver, t515_adapters );
+
+DRIVER ( "3c515", nic_driver, isapnp_driver, t515_driver,
+ t515_probe, t515_disable );
+
+ISA_ROM ( "3c515", "3c515 Fast EtherLink ISAPnP" );
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/3c515.txt b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c515.txt
new file mode 100644
index 00000000..8f7b3a72
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c515.txt
@@ -0,0 +1,31 @@
+3c515.c -- 3COM 3C515 Fast Etherlink ISA 10/100BASE-TX driver for etherboot
+Copyright (C) 2002 Timothy Legge <tlegge@rogers.com>
+
+This driver is for the 3COM 3C515 Fast Etherlink ISA 10/100BASE-TX
+
+REVISION HISTORY:
+================
+v0.10 4-17-2002 TJL Initial implementation.
+v0.11 4-17-2002 TJL Cleanup of the code
+v0.12 4-26-2002 TJL Added ISA Plug and Play for Non-PNP Bioses
+v0.13 3-31-2003 TJL Fixed issue 1 and 2 below
+
+The driver is heavily based on the work of others are referenced in the 3c515.c file.
+
+ISA Plug and Play (ISAPNP) support has been added for Non-PNP Bioses. The ISAPNP code requires the defination of ISA_PNP as:
+
+#define ISA_PNP
+
+Issues:
+=======
+1) RESOLVED - When ISAPNP is defined, the etherboot probe is unable to find the card during the first probe. This is true even though the ISA PNP code actually found and activated the driver.
+
+2) RESOLVED - When ISA_PNP is defined, the etherboot probe finds the incorrect MAC address for the card. However, when the linux kernel boots and loads the linux 3c515 driver the correct MAC address is found. This means that with ISA_PNP defined, you require both MAC addresses defined in the /etc/dhcpd.conf file. The first MAC address allows the driver to load the LTSP Linux kernel. The second allows the Linux dhclient to resolve its IP address.
+
+3) Although the ISA PNP docs specify that the IRQ, DMA and IO Address needs to be assigned to the card before it is activated, Etherboot does not seem to care. Therefore the code does not assign the card with these values.
+
+If you can help address any of thse issues, please feel free.
+
+Timothy Legge
+timlegge@users.sourceforge.net
+April 9, 2003
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/3c529.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c529.c
new file mode 100644
index 00000000..d68f28ec
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c529.c
@@ -0,0 +1,62 @@
+/*
+ * Split out from 3c509.c to make build process more sane
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include "etherboot.h"
+#include <ipxe/mca.h>
+#include <ipxe/isa.h> /* for ISA_ROM */
+#include "nic.h"
+#include "3c509.h"
+
+/*
+ * Several other pieces of the MCA support code were shamelessly
+ * borrowed from the Linux kernel source.
+ *
+ * MCA support added by Adam Fritzler (mid@auk.cx)
+ *
+ * Generalised out of the 3c529 driver and into a bus type by Michael
+ * Brown <mbrown@fensystems.co.uk>
+ *
+ */
+
+static int t529_probe ( struct nic *nic, struct mca_device *mca ) {
+
+ /* Retrieve NIC parameters from MCA device parameters */
+ nic->ioaddr = ( ( mca->pos[4] & 0xfc ) | 0x02 ) << 8;
+ nic->irqno = mca->pos[5] & 0x0f;
+ printf ( "3c529 board found on MCA at %#hx IRQ %d -",
+ nic->ioaddr, nic->irqno );
+
+ /* Hand off to generic t5x9 probe routine */
+ return t5x9_probe ( nic, MCA_ID ( mca ), 0xffff );
+}
+
+static void t529_disable ( struct nic *nic, struct mca_device *mca __unused ) {
+ t5x9_disable ( nic );
+}
+
+static struct mca_device_id el3_mca_adapters[] = {
+ { "3Com 3c529 EtherLink III (10base2)", 0x627c },
+ { "3Com 3c529 EtherLink III (10baseT)", 0x627d },
+ { "3Com 3c529 EtherLink III (test mode)", 0x62db },
+ { "3Com 3c529 EtherLink III (TP or coax)", 0x62f6 },
+ { "3Com 3c529 EtherLink III (TP)", 0x62f7 },
+};
+
+MCA_DRIVER ( t529_driver, el3_mca_adapters );
+
+DRIVER ( "3c529", nic_driver, mca_driver, t529_driver,
+ t529_probe, t529_disable );
+
+ISA_ROM( "3c529", "3c529 == MCA 3c509" );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/3c595.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c595.c
new file mode 100644
index 00000000..3178178a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c595.c
@@ -0,0 +1,553 @@
+/*
+* 3c595.c -- 3COM 3C595 Fast Etherlink III PCI driver for etherboot
+*
+* Copyright (C) 2000 Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp>
+* All rights reserved.
+* Mar. 14, 2000
+*
+* This software may be used, modified, copied, distributed, and sold, in
+* both source and binary form provided that the above copyright and these
+* terms are retained. Under no circumstances are the authors responsible for
+* the proper functioning of this software, nor do the authors assume any
+* responsibility for damages incurred with its use.
+*
+* This code is based on Martin Renters' etherboot-4.4.3 3c509.c and
+* Herb Peyerl's FreeBSD 3.4-RELEASE if_vx.c driver.
+*
+* Copyright (C) 1993-1994, David Greenman, Martin Renters.
+* Copyright (C) 1993-1995, Andres Vega Garcia.
+* Copyright (C) 1995, Serge Babkin.
+*
+* Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
+*
+* timlegge 08-24-2003 Add Multicast Support
+*/
+
+FILE_LICENCE ( BSD2 );
+
+/* #define EDEBUG */
+
+#include "etherboot.h"
+#include "nic.h"
+#include <ipxe/pci.h>
+#include <ipxe/ethernet.h>
+#include "3c595.h"
+
+static struct nic_operations t595_operations;
+
+static unsigned short eth_nic_base;
+static unsigned short vx_connector, vx_connectors;
+
+static struct connector_entry {
+ int bit;
+ char *name;
+} conn_tab[VX_CONNECTORS] = {
+#define CONNECTOR_UTP 0
+ { 0x08, "utp"},
+#define CONNECTOR_AUI 1
+ { 0x20, "aui"},
+/* dummy */
+ { 0, "???"},
+#define CONNECTOR_BNC 3
+ { 0x10, "bnc"},
+#define CONNECTOR_TX 4
+ { 0x02, "tx"},
+#define CONNECTOR_FX 5
+ { 0x04, "fx"},
+#define CONNECTOR_MII 6
+ { 0x40, "mii"},
+ { 0, "???"}
+};
+
+static void vxgetlink(void);
+static void vxsetlink(void);
+
+/**************************************************************************
+ETH_RESET - Reset adapter
+***************************************************************************/
+static void t595_reset(struct nic *nic)
+{
+ int i;
+
+ /***********************************************************
+ Reset 3Com 595 card
+ *************************************************************/
+
+ /* stop card */
+ outw(RX_DISABLE, BASE + VX_COMMAND);
+ outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
+ VX_BUSY_WAIT;
+ outw(TX_DISABLE, BASE + VX_COMMAND);
+ outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
+ udelay(8000);
+ outw(RX_RESET, BASE + VX_COMMAND);
+ VX_BUSY_WAIT;
+ outw(TX_RESET, BASE + VX_COMMAND);
+ VX_BUSY_WAIT;
+ outw(C_INTR_LATCH, BASE + VX_COMMAND);
+ outw(SET_RD_0_MASK, BASE + VX_COMMAND);
+ outw(SET_INTR_MASK, BASE + VX_COMMAND);
+ outw(SET_RX_FILTER, BASE + VX_COMMAND);
+
+ /*
+ * initialize card
+ */
+ VX_BUSY_WAIT;
+
+ GO_WINDOW(0);
+
+ /* Disable the card */
+/* outw(0, BASE + VX_W0_CONFIG_CTRL); */
+
+ /* Configure IRQ to none */
+/* outw(SET_IRQ(0), BASE + VX_W0_RESOURCE_CFG); */
+
+ /* Enable the card */
+/* outw(ENABLE_DRQ_IRQ, BASE + VX_W0_CONFIG_CTRL); */
+
+ GO_WINDOW(2);
+
+ /* Reload the ether_addr. */
+ for (i = 0; i < ETH_ALEN; i++)
+ outb(nic->node_addr[i], BASE + VX_W2_ADDR_0 + i);
+
+ outw(RX_RESET, BASE + VX_COMMAND);
+ VX_BUSY_WAIT;
+ outw(TX_RESET, BASE + VX_COMMAND);
+ VX_BUSY_WAIT;
+
+ /* Window 1 is operating window */
+ GO_WINDOW(1);
+ for (i = 0; i < 31; i++)
+ inb(BASE + VX_W1_TX_STATUS);
+
+ outw(SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
+ S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND);
+ outw(SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
+ S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND);
+
+/*
+ * Attempt to get rid of any stray interrupts that occured during
+ * configuration. On the i386 this isn't possible because one may
+ * already be queued. However, a single stray interrupt is
+ * unimportant.
+ */
+
+ outw(ACK_INTR | 0xff, BASE + VX_COMMAND);
+
+ outw(SET_RX_FILTER | FIL_INDIVIDUAL |
+ FIL_BRDCST|FIL_MULTICAST, BASE + VX_COMMAND);
+
+ vxsetlink();
+/*{
+ int i,j;
+ i = CONNECTOR_TX;
+ GO_WINDOW(3);
+ j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK;
+ outl(BASE + VX_W3_INTERNAL_CFG, j | (i <<INTERNAL_CONNECTOR_BITS));
+ GO_WINDOW(4);
+ outw(LINKBEAT_ENABLE, BASE + VX_W4_MEDIA_TYPE);
+ GO_WINDOW(1);
+}*/
+
+ /* start tranciever and receiver */
+ outw(RX_ENABLE, BASE + VX_COMMAND);
+ outw(TX_ENABLE, BASE + VX_COMMAND);
+
+}
+
+/**************************************************************************
+ETH_TRANSMIT - Transmit a frame
+***************************************************************************/
+static char padmap[] = {
+ 0, 3, 2, 1};
+
+static void t595_transmit(
+struct nic *nic,
+const char *d, /* Destination */
+unsigned int t, /* Type */
+unsigned int s, /* size */
+const char *p) /* Packet */
+{
+ register int len;
+ int pad;
+ int status;
+
+#ifdef EDEBUG
+ printf("{l=%d,t=%hX}",s+ETH_HLEN,t);
+#endif
+
+ /* swap bytes of type */
+ t= htons(t);
+
+ len=s+ETH_HLEN; /* actual length of packet */
+ pad = padmap[len & 3];
+
+ /*
+ * The 3c595 automatically pads short packets to minimum ethernet length,
+ * but we drop packets that are too large. Perhaps we should truncate
+ * them instead?
+ */
+ if (len + pad > ETH_FRAME_LEN) {
+ return;
+ }
+
+ /* drop acknowledgements */
+ while(( status=inb(BASE + VX_W1_TX_STATUS) )& TXS_COMPLETE ) {
+ if(status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
+ outw(TX_RESET, BASE + VX_COMMAND);
+ outw(TX_ENABLE, BASE + VX_COMMAND);
+ }
+
+ outb(0x0, BASE + VX_W1_TX_STATUS);
+ }
+
+ while (inw(BASE + VX_W1_FREE_TX) < len + pad + 4) {
+ /* no room in FIFO */
+ }
+
+ outw(len, BASE + VX_W1_TX_PIO_WR_1);
+ outw(0x0, BASE + VX_W1_TX_PIO_WR_1); /* Second dword meaningless */
+
+ /* write packet */
+ outsw(BASE + VX_W1_TX_PIO_WR_1, d, ETH_ALEN/2);
+ outsw(BASE + VX_W1_TX_PIO_WR_1, nic->node_addr, ETH_ALEN/2);
+ outw(t, BASE + VX_W1_TX_PIO_WR_1);
+ outsw(BASE + VX_W1_TX_PIO_WR_1, p, s / 2);
+ if (s & 1)
+ outb(*(p+s - 1), BASE + VX_W1_TX_PIO_WR_1);
+
+ while (pad--)
+ outb(0, BASE + VX_W1_TX_PIO_WR_1); /* Padding */
+
+ /* wait for Tx complete */
+ while((inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS) != 0)
+ ;
+}
+
+/**************************************************************************
+ETH_POLL - Wait for a frame
+***************************************************************************/
+static int t595_poll(struct nic *nic, int retrieve)
+{
+ /* common variables */
+ /* variables for 3C595 */
+ short status, cst;
+ register short rx_fifo;
+
+ cst=inw(BASE + VX_STATUS);
+
+#ifdef EDEBUG
+ if(cst & 0x1FFF)
+ printf("-%hX-",cst);
+#endif
+
+ if( (cst & S_RX_COMPLETE)==0 ) {
+ /* acknowledge everything */
+ outw(ACK_INTR | cst, BASE + VX_COMMAND);
+ outw(C_INTR_LATCH, BASE + VX_COMMAND);
+
+ return 0;
+ }
+
+ status = inw(BASE + VX_W1_RX_STATUS);
+#ifdef EDEBUG
+ printf("*%hX*",status);
+#endif
+
+ if (status & ERR_RX) {
+ outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
+ return 0;
+ }
+
+ rx_fifo = status & RX_BYTES_MASK;
+ if (rx_fifo==0)
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+ /* read packet */
+#ifdef EDEBUG
+ printf("[l=%d",rx_fifo);
+#endif
+ insw(BASE + VX_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2);
+ if(rx_fifo & 1)
+ nic->packet[rx_fifo-1]=inb(BASE + VX_W1_RX_PIO_RD_1);
+ nic->packetlen=rx_fifo;
+
+ while(1) {
+ status = inw(BASE + VX_W1_RX_STATUS);
+#ifdef EDEBUG
+ printf("*%hX*",status);
+#endif
+ rx_fifo = status & RX_BYTES_MASK;
+
+ if(rx_fifo>0) {
+ insw(BASE + VX_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2);
+ if(rx_fifo & 1)
+ nic->packet[nic->packetlen+rx_fifo-1]=inb(BASE + VX_W1_RX_PIO_RD_1);
+ nic->packetlen+=rx_fifo;
+#ifdef EDEBUG
+ printf("+%d",rx_fifo);
+#endif
+ }
+ if(( status & RX_INCOMPLETE )==0) {
+#ifdef EDEBUG
+ printf("=%d",nic->packetlen);
+#endif
+ break;
+ }
+ udelay(1000);
+ }
+
+ /* acknowledge reception of packet */
+ outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
+ while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS);
+#ifdef EDEBUG
+{
+ unsigned short type = 0; /* used by EDEBUG */
+ type = (nic->packet[12]<<8) | nic->packet[13];
+ if(nic->packet[0]+nic->packet[1]+nic->packet[2]+nic->packet[3]+nic->packet[4]+
+ nic->packet[5] == 0xFF*ETH_ALEN)
+ printf(",t=%hX,b]",type);
+ else
+ printf(",t=%hX]",type);
+}
+#endif
+ return 1;
+}
+
+
+/*************************************************************************
+ 3Com 595 - specific routines
+**************************************************************************/
+
+static int
+eeprom_rdy()
+{
+ int i;
+
+ for (i = 0; is_eeprom_busy(BASE) && i < MAX_EEPROMBUSY; i++)
+ udelay(1000);
+ if (i >= MAX_EEPROMBUSY) {
+ /* printf("3c595: eeprom failed to come ready.\n"); */
+ printf("3c595: eeprom is busy.\n"); /* memory in EPROM is tight */
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * get_e: gets a 16 bits word from the EEPROM. we must have set the window
+ * before
+ */
+static int
+get_e(offset)
+int offset;
+{
+ if (!eeprom_rdy())
+ return (0xffff);
+ outw(EEPROM_CMD_RD | offset, BASE + VX_W0_EEPROM_COMMAND);
+ if (!eeprom_rdy())
+ return (0xffff);
+ return (inw(BASE + VX_W0_EEPROM_DATA));
+}
+
+static void
+vxgetlink(void)
+{
+ int n, k;
+
+ GO_WINDOW(3);
+ vx_connectors = inw(BASE + VX_W3_RESET_OPT) & 0x7f;
+ for (n = 0, k = 0; k < VX_CONNECTORS; k++) {
+ if (vx_connectors & conn_tab[k].bit) {
+ if (n > 0) {
+ printf("/");
+ }
+ printf("%s", conn_tab[k].name );
+ n++;
+ }
+ }
+ if (vx_connectors == 0) {
+ printf("no connectors!");
+ return;
+ }
+ GO_WINDOW(3);
+ vx_connector = (inl(BASE + VX_W3_INTERNAL_CFG)
+ & INTERNAL_CONNECTOR_MASK)
+ >> INTERNAL_CONNECTOR_BITS;
+ if (vx_connector & 0x10) {
+ vx_connector &= 0x0f;
+ printf("[*%s*]", conn_tab[vx_connector].name);
+ printf(": disable 'auto select' with DOS util!");
+ } else {
+ printf("[*%s*]", conn_tab[vx_connector].name);
+ }
+}
+
+static void
+vxsetlink(void)
+{
+ int i, j;
+ char *reason, *warning;
+ static char prev_conn = -1;
+
+ if (prev_conn == -1) {
+ prev_conn = vx_connector;
+ }
+
+ i = vx_connector; /* default in EEPROM */
+ reason = "default";
+ warning = 0;
+
+ if ((vx_connectors & conn_tab[vx_connector].bit) == 0) {
+ warning = "strange connector type in EEPROM.";
+ reason = "forced";
+ i = CONNECTOR_UTP;
+ }
+
+ if (warning != 0) {
+ printf("warning: %s\n", warning);
+ }
+ printf("selected %s. (%s)\n", conn_tab[i].name, reason);
+
+ /* Set the selected connector. */
+ GO_WINDOW(3);
+ j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK;
+ outl(j | (i <<INTERNAL_CONNECTOR_BITS), BASE + VX_W3_INTERNAL_CFG);
+
+ /* First, disable all. */
+ outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
+ udelay(8000);
+ GO_WINDOW(4);
+ outw(0, BASE + VX_W4_MEDIA_TYPE);
+
+ /* Second, enable the selected one. */
+ switch(i) {
+ case CONNECTOR_UTP:
+ GO_WINDOW(4);
+ outw(ENABLE_UTP, BASE + VX_W4_MEDIA_TYPE);
+ break;
+ case CONNECTOR_BNC:
+ outw(START_TRANSCEIVER,BASE + VX_COMMAND);
+ udelay(8000);
+ break;
+ case CONNECTOR_TX:
+ case CONNECTOR_FX:
+ GO_WINDOW(4);
+ outw(LINKBEAT_ENABLE, BASE + VX_W4_MEDIA_TYPE);
+ break;
+ default: /* AUI and MII fall here */
+ break;
+ }
+ GO_WINDOW(1);
+}
+
+static void t595_disable ( struct nic *nic ) {
+
+ t595_reset(nic);
+
+ outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
+ udelay(8000);
+ GO_WINDOW(4);
+ outw(0, BASE + VX_W4_MEDIA_TYPE);
+ GO_WINDOW(1);
+}
+
+static void t595_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+/**************************************************************************
+ETH_PROBE - Look for an adapter
+***************************************************************************/
+static int t595_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ int i;
+ unsigned short *p;
+
+ if (pci->ioaddr == 0)
+ return 0;
+ eth_nic_base = pci->ioaddr;
+
+ nic->irqno = 0;
+ nic->ioaddr = pci->ioaddr;
+
+ GO_WINDOW(0);
+ outw(GLOBAL_RESET, BASE + VX_COMMAND);
+ VX_BUSY_WAIT;
+
+ vxgetlink();
+
+/*
+ printf("\nEEPROM:");
+ for (i = 0; i < (EEPROMSIZE/2); i++) {
+ printf("%hX:", get_e(i));
+ }
+ printf("\n");
+*/
+ /*
+ * Read the station address from the eeprom
+ */
+ p = (unsigned short *) nic->node_addr;
+ for (i = 0; i < 3; i++) {
+ GO_WINDOW(0);
+ p[i] = htons(get_e(EEPROM_OEM_ADDR_0 + i));
+ GO_WINDOW(2);
+ outw(ntohs(p[i]), BASE + VX_W2_ADDR_0 + (i * 2));
+ }
+
+ DBG ( "Ethernet address: %s\n", eth_ntoa (nic->node_addr) );
+
+ t595_reset(nic);
+ nic->nic_op = &t595_operations;
+ return 1;
+
+}
+
+static struct nic_operations t595_operations = {
+ .connect = dummy_connect,
+ .poll = t595_poll,
+ .transmit = t595_transmit,
+ .irq = t595_irq,
+
+};
+
+static struct pci_device_id t595_nics[] = {
+PCI_ROM(0x10b7, 0x5900, "3c590", "3Com590", 0), /* Vortex 10Mbps */
+PCI_ROM(0x10b7, 0x5950, "3c595", "3Com595", 0), /* Vortex 100baseTx */
+PCI_ROM(0x10b7, 0x5951, "3c595-1", "3Com595", 0), /* Vortex 100baseT4 */
+PCI_ROM(0x10b7, 0x5952, "3c595-2", "3Com595", 0), /* Vortex 100base-MII */
+PCI_ROM(0x10b7, 0x9000, "3c900-tpo", "3Com900-TPO", 0), /* 10 Base TPO */
+PCI_ROM(0x10b7, 0x9001, "3c900-t4", "3Com900-Combo", 0), /* 10/100 T4 */
+PCI_ROM(0x10b7, 0x9004, "3c900b-tpo", "3Com900B-TPO", 0), /* 10 Base TPO */
+PCI_ROM(0x10b7, 0x9005, "3c900b-combo", "3Com900B-Combo", 0), /* 10 Base Combo */
+PCI_ROM(0x10b7, 0x9006, "3c900b-tpb2", "3Com900B-2/T", 0), /* 10 Base TP and Base2 */
+PCI_ROM(0x10b7, 0x900a, "3c900b-fl", "3Com900B-FL", 0), /* 10 Base F */
+PCI_ROM(0x10b7, 0x9800, "3c980-cyclone-1", "3Com980-Cyclone", 0), /* Cyclone */
+PCI_ROM(0x10b7, 0x9805, "3c9805-1", "3Com9805", 0), /* Dual Port Server Cyclone */
+PCI_ROM(0x10b7, 0x7646, "3csoho100-tx-1", "3CSOHO100-TX", 0), /* Hurricane */
+PCI_ROM(0x10b7, 0x4500, "3c450-1", "3Com450 HomePNA Tornado", 0),
+};
+
+PCI_DRIVER ( t595_driver, t595_nics, PCI_NO_CLASS );
+
+DRIVER ( "3C595", nic_driver, pci_driver, t595_driver,
+ t595_probe, t595_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/3c595.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c595.h
new file mode 100644
index 00000000..d62f9298
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c595.h
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2. The name
+ * of the author may not be used to endorse or promote products derived from
+ * this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ October 2, 1994
+
+ Modified by: Andres Vega Garcia
+
+ INRIA - Sophia Antipolis, France
+ e-mail: avega@sophia.inria.fr
+ finger: avega@pax.inria.fr
+
+ */
+
+FILE_LICENCE ( BSD3 );
+
+/*
+ * Created from if_epreg.h by Fred Gray (fgray@rice.edu) to support the
+ * 3c590 family.
+ */
+
+/*
+ * Modified by Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp>
+ * for etherboot
+ * Mar. 14, 2000
+*/
+
+/*
+ * Ethernet software status per interface.
+ */
+
+/*
+ * Some global constants
+ */
+
+#define TX_INIT_RATE 16
+#define TX_INIT_MAX_RATE 64
+#define RX_INIT_LATENCY 64
+#define RX_INIT_EARLY_THRESH 64
+#define MIN_RX_EARLY_THRESHF 16 /* not less than ether_header */
+#define MIN_RX_EARLY_THRESHL 4
+
+#define EEPROMSIZE 0x40
+#define MAX_EEPROMBUSY 1000
+#define VX_LAST_TAG 0xd7
+#define VX_MAX_BOARDS 16
+#define VX_ID_PORT 0x100
+
+/*
+ * some macros to acces long named fields
+ */
+#define BASE (eth_nic_base)
+
+/*
+ * Commands to read/write EEPROM trough EEPROM command register (Window 0,
+ * Offset 0xa)
+ */
+#define EEPROM_CMD_RD 0x0080 /* Read: Address required (5 bits) */
+#define EEPROM_CMD_WR 0x0040 /* Write: Address required (5 bits) */
+#define EEPROM_CMD_ERASE 0x00c0 /* Erase: Address required (5 bits) */
+#define EEPROM_CMD_EWEN 0x0030 /* Erase/Write Enable: No data required */
+
+#define EEPROM_BUSY (1<<15)
+
+/*
+ * Some short functions, worth to let them be a macro
+ */
+
+/**************************************************************************
+ * *
+ * These define the EEPROM data structure. They are used in the probe
+ * function to verify the existence of the adapter after having sent
+ * the ID_Sequence.
+ *
+ * There are others but only the ones we use are defined here.
+ *
+ **************************************************************************/
+
+#define EEPROM_NODE_ADDR_0 0x0 /* Word */
+#define EEPROM_NODE_ADDR_1 0x1 /* Word */
+#define EEPROM_NODE_ADDR_2 0x2 /* Word */
+#define EEPROM_PROD_ID 0x3 /* 0x9[0-f]50 */
+#define EEPROM_MFG_ID 0x7 /* 0x6d50 */
+#define EEPROM_ADDR_CFG 0x8 /* Base addr */
+#define EEPROM_RESOURCE_CFG 0x9 /* IRQ. Bits 12-15 */
+#define EEPROM_OEM_ADDR_0 0xa /* Word */
+#define EEPROM_OEM_ADDR_1 0xb /* Word */
+#define EEPROM_OEM_ADDR_2 0xc /* Word */
+#define EEPROM_SOFT_INFO_2 0xf /* Software information 2 */
+
+#define NO_RX_OVN_ANOMALY (1<<5)
+
+/**************************************************************************
+ * *
+ * These are the registers for the 3Com 3c509 and their bit patterns when *
+ * applicable. They have been taken out the "EtherLink III Parallel *
+ * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual *
+ * from 3com. *
+ * *
+ **************************************************************************/
+
+#define VX_COMMAND 0x0e /* Write. BASE+0x0e is always a
+ * command reg. */
+#define VX_STATUS 0x0e /* Read. BASE+0x0e is always status
+ * reg. */
+#define VX_WINDOW 0x0f /* Read. BASE+0x0f is always window
+ * reg. */
+/*
+ * Window 0 registers. Setup.
+ */
+/* Write */
+#define VX_W0_EEPROM_DATA 0x0c
+#define VX_W0_EEPROM_COMMAND 0x0a
+#define VX_W0_RESOURCE_CFG 0x08
+#define VX_W0_ADDRESS_CFG 0x06
+#define VX_W0_CONFIG_CTRL 0x04
+ /* Read */
+#define VX_W0_PRODUCT_ID 0x02
+#define VX_W0_MFG_ID 0x00
+
+
+/*
+ * Window 1 registers. Operating Set.
+ */
+/* Write */
+#define VX_W1_TX_PIO_WR_2 0x02
+#define VX_W1_TX_PIO_WR_1 0x00
+/* Read */
+#define VX_W1_FREE_TX 0x0c
+#define VX_W1_TX_STATUS 0x0b /* byte */
+#define VX_W1_TIMER 0x0a /* byte */
+#define VX_W1_RX_STATUS 0x08
+#define VX_W1_RX_PIO_RD_2 0x02
+#define VX_W1_RX_PIO_RD_1 0x00
+
+/*
+ * Window 2 registers. Station Address Setup/Read
+ */
+/* Read/Write */
+#define VX_W2_ADDR_5 0x05
+#define VX_W2_ADDR_4 0x04
+#define VX_W2_ADDR_3 0x03
+#define VX_W2_ADDR_2 0x02
+#define VX_W2_ADDR_1 0x01
+#define VX_W2_ADDR_0 0x00
+
+/*
+ * Window 3 registers. FIFO Management.
+ */
+/* Read */
+#define VX_W3_INTERNAL_CFG 0x00
+#define VX_W3_RESET_OPT 0x08
+#define VX_W3_FREE_TX 0x0c
+#define VX_W3_FREE_RX 0x0a
+
+/*
+ * Window 4 registers. Diagnostics.
+ */
+/* Read/Write */
+#define VX_W4_MEDIA_TYPE 0x0a
+#define VX_W4_CTRLR_STATUS 0x08
+#define VX_W4_NET_DIAG 0x06
+#define VX_W4_FIFO_DIAG 0x04
+#define VX_W4_HOST_DIAG 0x02
+#define VX_W4_TX_DIAG 0x00
+
+/*
+ * Window 5 Registers. Results and Internal status.
+ */
+/* Read */
+#define VX_W5_READ_0_MASK 0x0c
+#define VX_W5_INTR_MASK 0x0a
+#define VX_W5_RX_FILTER 0x08
+#define VX_W5_RX_EARLY_THRESH 0x06
+#define VX_W5_TX_AVAIL_THRESH 0x02
+#define VX_W5_TX_START_THRESH 0x00
+
+/*
+ * Window 6 registers. Statistics.
+ */
+/* Read/Write */
+#define TX_TOTAL_OK 0x0c
+#define RX_TOTAL_OK 0x0a
+#define TX_DEFERRALS 0x08
+#define RX_FRAMES_OK 0x07
+#define TX_FRAMES_OK 0x06
+#define RX_OVERRUNS 0x05
+#define TX_COLLISIONS 0x04
+#define TX_AFTER_1_COLLISION 0x03
+#define TX_AFTER_X_COLLISIONS 0x02
+#define TX_NO_SQE 0x01
+#define TX_CD_LOST 0x00
+
+/****************************************
+ *
+ * Register definitions.
+ *
+ ****************************************/
+
+/*
+ * Command register. All windows.
+ *
+ * 16 bit register.
+ * 15-11: 5-bit code for command to be executed.
+ * 10-0: 11-bit arg if any. For commands with no args;
+ * this can be set to anything.
+ */
+#define GLOBAL_RESET (unsigned short) 0x0000 /* Wait at least 1ms
+ * after issuing */
+#define WINDOW_SELECT (unsigned short) (0x1<<11)
+#define START_TRANSCEIVER (unsigned short) (0x2<<11) /* Read ADDR_CFG reg to
+ * determine whether
+ * this is needed. If
+ * so; wait 800 uSec
+ * before using trans-
+ * ceiver. */
+#define RX_DISABLE (unsigned short) (0x3<<11) /* state disabled on
+ * power-up */
+#define RX_ENABLE (unsigned short) (0x4<<11)
+#define RX_RESET (unsigned short) (0x5<<11)
+#define RX_DISCARD_TOP_PACK (unsigned short) (0x8<<11)
+#define TX_ENABLE (unsigned short) (0x9<<11)
+#define TX_DISABLE (unsigned short) (0xa<<11)
+#define TX_RESET (unsigned short) (0xb<<11)
+#define REQ_INTR (unsigned short) (0xc<<11)
+/*
+ * The following C_* acknowledge the various interrupts. Some of them don't
+ * do anything. See the manual.
+ */
+#define ACK_INTR (unsigned short) (0x6800)
+# define C_INTR_LATCH (unsigned short) (ACK_INTR|0x1)
+# define C_CARD_FAILURE (unsigned short) (ACK_INTR|0x2)
+# define C_TX_COMPLETE (unsigned short) (ACK_INTR|0x4)
+# define C_TX_AVAIL (unsigned short) (ACK_INTR|0x8)
+# define C_RX_COMPLETE (unsigned short) (ACK_INTR|0x10)
+# define C_RX_EARLY (unsigned short) (ACK_INTR|0x20)
+# define C_INT_RQD (unsigned short) (ACK_INTR|0x40)
+# define C_UPD_STATS (unsigned short) (ACK_INTR|0x80)
+#define SET_INTR_MASK (unsigned short) (0xe<<11)
+#define SET_RD_0_MASK (unsigned short) (0xf<<11)
+#define SET_RX_FILTER (unsigned short) (0x10<<11)
+# define FIL_INDIVIDUAL (unsigned short) (0x1)
+# define FIL_MULTICAST (unsigned short) (0x02)
+# define FIL_BRDCST (unsigned short) (0x04)
+# define FIL_PROMISC (unsigned short) (0x08)
+#define SET_RX_EARLY_THRESH (unsigned short) (0x11<<11)
+#define SET_TX_AVAIL_THRESH (unsigned short) (0x12<<11)
+#define SET_TX_START_THRESH (unsigned short) (0x13<<11)
+#define STATS_ENABLE (unsigned short) (0x15<<11)
+#define STATS_DISABLE (unsigned short) (0x16<<11)
+#define STOP_TRANSCEIVER (unsigned short) (0x17<<11)
+
+/*
+ * Status register. All windows.
+ *
+ * 15-13: Window number(0-7).
+ * 12: Command_in_progress.
+ * 11: reserved.
+ * 10: reserved.
+ * 9: reserved.
+ * 8: reserved.
+ * 7: Update Statistics.
+ * 6: Interrupt Requested.
+ * 5: RX Early.
+ * 4: RX Complete.
+ * 3: TX Available.
+ * 2: TX Complete.
+ * 1: Adapter Failure.
+ * 0: Interrupt Latch.
+ */
+#define S_INTR_LATCH (unsigned short) (0x1)
+#define S_CARD_FAILURE (unsigned short) (0x2)
+#define S_TX_COMPLETE (unsigned short) (0x4)
+#define S_TX_AVAIL (unsigned short) (0x8)
+#define S_RX_COMPLETE (unsigned short) (0x10)
+#define S_RX_EARLY (unsigned short) (0x20)
+#define S_INT_RQD (unsigned short) (0x40)
+#define S_UPD_STATS (unsigned short) (0x80)
+#define S_COMMAND_IN_PROGRESS (unsigned short) (0x1000)
+
+#define VX_BUSY_WAIT while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS)
+
+/* Address Config. Register.
+ * Window 0/Port 06
+ */
+
+#define ACF_CONNECTOR_BITS 14
+#define ACF_CONNECTOR_UTP 0
+#define ACF_CONNECTOR_AUI 1
+#define ACF_CONNECTOR_BNC 3
+
+#define INTERNAL_CONNECTOR_BITS 20
+#define INTERNAL_CONNECTOR_MASK 0x01700000
+
+/*
+ * FIFO Registers. RX Status.
+ *
+ * 15: Incomplete or FIFO empty.
+ * 14: 1: Error in RX Packet 0: Incomplete or no error.
+ * 13-11: Type of error.
+ * 1000 = Overrun.
+ * 1011 = Run Packet Error.
+ * 1100 = Alignment Error.
+ * 1101 = CRC Error.
+ * 1001 = Oversize Packet Error (>1514 bytes)
+ * 0010 = Dribble Bits.
+ * (all other error codes, no errors.)
+ *
+ * 10-0: RX Bytes (0-1514)
+ */
+#define ERR_INCOMPLETE (unsigned short) (0x8000)
+#define ERR_RX (unsigned short) (0x4000)
+#define ERR_MASK (unsigned short) (0x7800)
+#define ERR_OVERRUN (unsigned short) (0x4000)
+#define ERR_RUNT (unsigned short) (0x5800)
+#define ERR_ALIGNMENT (unsigned short) (0x6000)
+#define ERR_CRC (unsigned short) (0x6800)
+#define ERR_OVERSIZE (unsigned short) (0x4800)
+#define ERR_DRIBBLE (unsigned short) (0x1000)
+
+/*
+ * TX Status.
+ *
+ * Reports the transmit status of a completed transmission. Writing this
+ * register pops the transmit completion stack.
+ *
+ * Window 1/Port 0x0b.
+ *
+ * 7: Complete
+ * 6: Interrupt on successful transmission requested.
+ * 5: Jabber Error (TP Only, TX Reset required. )
+ * 4: Underrun (TX Reset required. )
+ * 3: Maximum Collisions.
+ * 2: TX Status Overflow.
+ * 1-0: Undefined.
+ *
+ */
+#define TXS_COMPLETE 0x80
+#define TXS_INTR_REQ 0x40
+#define TXS_JABBER 0x20
+#define TXS_UNDERRUN 0x10
+#define TXS_MAX_COLLISION 0x8
+#define TXS_STATUS_OVERFLOW 0x4
+
+#define RS_AUI (1<<5)
+#define RS_BNC (1<<4)
+#define RS_UTP (1<<3)
+#define RS_T4 (1<<0)
+#define RS_TX (1<<1)
+#define RS_FX (1<<2)
+#define RS_MII (1<<6)
+
+
+/*
+ * FIFO Status (Window 4)
+ *
+ * Supports FIFO diagnostics
+ *
+ * Window 4/Port 0x04.1
+ *
+ * 15: 1=RX receiving (RO). Set when a packet is being received
+ * into the RX FIFO.
+ * 14: Reserved
+ * 13: 1=RX underrun (RO). Generates Adapter Failure interrupt.
+ * Requires RX Reset or Global Reset command to recover.
+ * It is generated when you read past the end of a packet -
+ * reading past what has been received so far will give bad
+ * data.
+ * 12: 1=RX status overrun (RO). Set when there are already 8
+ * packets in the RX FIFO. While this bit is set, no additional
+ * packets are received. Requires no action on the part of
+ * the host. The condition is cleared once a packet has been
+ * read out of the RX FIFO.
+ * 11: 1=RX overrun (RO). Set when the RX FIFO is full (there
+ * may not be an overrun packet yet). While this bit is set,
+ * no additional packets will be received (some additional
+ * bytes can still be pending between the wire and the RX
+ * FIFO). Requires no action on the part of the host. The
+ * condition is cleared once a few bytes have been read out
+ * from the RX FIFO.
+ * 10: 1=TX overrun (RO). Generates adapter failure interrupt.
+ * Requires TX Reset or Global Reset command to recover.
+ * Disables Transmitter.
+ * 9-8: Unassigned.
+ * 7-0: Built in self test bits for the RX and TX FIFO's.
+ */
+#define FIFOS_RX_RECEIVING (unsigned short) 0x8000
+#define FIFOS_RX_UNDERRUN (unsigned short) 0x2000
+#define FIFOS_RX_STATUS_OVERRUN (unsigned short) 0x1000
+#define FIFOS_RX_OVERRUN (unsigned short) 0x0800
+#define FIFOS_TX_OVERRUN (unsigned short) 0x0400
+
+/*
+ * Misc defines for various things.
+ */
+#define TAG_ADAPTER 0xd0
+#define ACTIVATE_ADAPTER_TO_CONFIG 0xff
+#define ENABLE_DRQ_IRQ 0x0001
+#define MFG_ID 0x506d /* `TCM' */
+#define PROD_ID 0x5090
+#define GO_WINDOW(x) outw(WINDOW_SELECT|(x),BASE+VX_COMMAND)
+#define JABBER_GUARD_ENABLE 0x40
+#define LINKBEAT_ENABLE 0x80
+#define ENABLE_UTP (JABBER_GUARD_ENABLE | LINKBEAT_ENABLE)
+#define DISABLE_UTP 0x0
+#define RX_BYTES_MASK (unsigned short) (0x07ff)
+#define RX_ERROR 0x4000
+#define RX_INCOMPLETE 0x8000
+#define TX_INDICATE 1<<15
+#define is_eeprom_busy(b) (inw((b)+VX_W0_EEPROM_COMMAND)&EEPROM_BUSY)
+
+#define VX_IOSIZE 0x20
+
+#define VX_CONNECTORS 8
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/3c5x9.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c5x9.c
new file mode 100644
index 00000000..4d9bc8d9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c5x9.c
@@ -0,0 +1,416 @@
+/**************************************************************************
+ETHERBOOT - BOOTP/TFTP Bootstrap Program
+
+Author: Martin Renters.
+ Date: Mar 22 1995
+
+ This code is based heavily on David Greenman's if_ed.c driver and
+ Andres Vega Garcia's if_ep.c driver.
+
+ Copyright (C) 1993-1994, David Greenman, Martin Renters.
+ Copyright (C) 1993-1995, Andres Vega Garcia.
+ Copyright (C) 1995, Serge Babkin.
+ This software may be used, modified, copied, distributed, and sold, in
+ both source and binary form provided that the above copyright and these
+ terms are retained. Under no circumstances are the authors responsible for
+ the proper functioning of this software, nor do the authors assume any
+ responsibility for damages incurred with its use.
+
+3c509 support added by Serge Babkin (babkin@hq.icb.chel.su)
+
+$Id$
+
+***************************************************************************/
+
+FILE_LICENCE ( BSD2 );
+
+/* #define EDEBUG */
+
+#include <ipxe/ethernet.h>
+#include "etherboot.h"
+#include "nic.h"
+#include <ipxe/isa.h>
+#include "3c509.h"
+
+static enum { none, bnc, utp } connector = none; /* for 3C509 */
+
+/**************************************************************************
+ETH_RESET - Reset adapter
+***************************************************************************/
+void t5x9_disable ( struct nic *nic ) {
+ /* stop card */
+ outw(RX_DISABLE, nic->ioaddr + EP_COMMAND);
+ outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND);
+ while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS)
+ ;
+ outw(TX_DISABLE, nic->ioaddr + EP_COMMAND);
+ outw(STOP_TRANSCEIVER, nic->ioaddr + EP_COMMAND);
+ udelay(1000);
+ outw(RX_RESET, nic->ioaddr + EP_COMMAND);
+ outw(TX_RESET, nic->ioaddr + EP_COMMAND);
+ outw(C_INTR_LATCH, nic->ioaddr + EP_COMMAND);
+ outw(SET_RD_0_MASK, nic->ioaddr + EP_COMMAND);
+ outw(SET_INTR_MASK, nic->ioaddr + EP_COMMAND);
+ outw(SET_RX_FILTER, nic->ioaddr + EP_COMMAND);
+
+ /*
+ * wait for reset to complete
+ */
+ while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS)
+ ;
+
+ GO_WINDOW(nic->ioaddr,0);
+
+ /* Disable the card */
+ outw(0, nic->ioaddr + EP_W0_CONFIG_CTRL);
+
+ /* Configure IRQ to none */
+ outw(SET_IRQ(0), nic->ioaddr + EP_W0_RESOURCE_CFG);
+}
+
+static void t509_enable ( struct nic *nic ) {
+ int i;
+
+ /* Enable the card */
+ GO_WINDOW(nic->ioaddr,0);
+ outw(ENABLE_DRQ_IRQ, nic->ioaddr + EP_W0_CONFIG_CTRL);
+
+ GO_WINDOW(nic->ioaddr,2);
+
+ /* Reload the ether_addr. */
+ for (i = 0; i < ETH_ALEN; i++)
+ outb(nic->node_addr[i], nic->ioaddr + EP_W2_ADDR_0 + i);
+
+ outw(RX_RESET, nic->ioaddr + EP_COMMAND);
+ outw(TX_RESET, nic->ioaddr + EP_COMMAND);
+
+ /* Window 1 is operating window */
+ GO_WINDOW(nic->ioaddr,1);
+ for (i = 0; i < 31; i++)
+ inb(nic->ioaddr + EP_W1_TX_STATUS);
+
+ /* get rid of stray intr's */
+ outw(ACK_INTR | 0xff, nic->ioaddr + EP_COMMAND);
+
+ outw(SET_RD_0_MASK | S_5_INTS, nic->ioaddr + EP_COMMAND);
+
+ outw(SET_INTR_MASK, nic->ioaddr + EP_COMMAND);
+
+ outw(SET_RX_FILTER | FIL_GROUP | FIL_INDIVIDUAL | FIL_BRDCST,
+ nic->ioaddr + EP_COMMAND);
+
+ /* configure BNC */
+ if (connector == bnc) {
+ outw(START_TRANSCEIVER, nic->ioaddr + EP_COMMAND);
+ udelay(1000);
+ }
+ /* configure UTP */
+ else if (connector == utp) {
+ GO_WINDOW(nic->ioaddr,4);
+ outw(ENABLE_UTP, nic->ioaddr + EP_W4_MEDIA_TYPE);
+ sleep(2); /* Give time for media to negotiate */
+ GO_WINDOW(nic->ioaddr,1);
+ }
+
+ /* start transceiver and receiver */
+ outw(RX_ENABLE, nic->ioaddr + EP_COMMAND);
+ outw(TX_ENABLE, nic->ioaddr + EP_COMMAND);
+
+ /* set early threshold for minimal packet length */
+ outw(SET_RX_EARLY_THRESH | ETH_ZLEN, nic->ioaddr + EP_COMMAND);
+ outw(SET_TX_START_THRESH | 16, nic->ioaddr + EP_COMMAND);
+}
+
+static void t509_reset ( struct nic *nic ) {
+ t5x9_disable ( nic );
+ t509_enable ( nic );
+}
+
+/**************************************************************************
+ETH_TRANSMIT - Transmit a frame
+***************************************************************************/
+static char padmap[] = {
+ 0, 3, 2, 1};
+
+static void t509_transmit(
+struct nic *nic,
+const char *d, /* Destination */
+unsigned int t, /* Type */
+unsigned int s, /* size */
+const char *p) /* Packet */
+{
+ register unsigned int len;
+ int pad;
+ int status;
+
+#ifdef EDEBUG
+ printf("{l=%d,t=%hX}",s+ETH_HLEN,t);
+#endif
+
+ /* swap bytes of type */
+ t= htons(t);
+
+ len=s+ETH_HLEN; /* actual length of packet */
+ pad = padmap[len & 3];
+
+ /*
+ * The 3c509 automatically pads short packets to minimum ethernet length,
+ * but we drop packets that are too large. Perhaps we should truncate
+ * them instead?
+ */
+ if (len + pad > ETH_FRAME_LEN) {
+ return;
+ }
+
+ /* drop acknowledgements */
+ while ((status=inb(nic->ioaddr + EP_W1_TX_STATUS)) & TXS_COMPLETE ) {
+ if (status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
+ outw(TX_RESET, nic->ioaddr + EP_COMMAND);
+ outw(TX_ENABLE, nic->ioaddr + EP_COMMAND);
+ }
+ outb(0x0, nic->ioaddr + EP_W1_TX_STATUS);
+ }
+
+ while (inw(nic->ioaddr + EP_W1_FREE_TX) < (unsigned short)len + pad + 4)
+ ; /* no room in FIFO */
+
+ outw(len, nic->ioaddr + EP_W1_TX_PIO_WR_1);
+ outw(0x0, nic->ioaddr + EP_W1_TX_PIO_WR_1); /* Second dword meaningless */
+
+ /* write packet */
+ outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, d, ETH_ALEN/2);
+ outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, nic->node_addr, ETH_ALEN/2);
+ outw(t, nic->ioaddr + EP_W1_TX_PIO_WR_1);
+ outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, p, s / 2);
+ if (s & 1)
+ outb(*(p+s - 1), nic->ioaddr + EP_W1_TX_PIO_WR_1);
+
+ while (pad--)
+ outb(0, nic->ioaddr + EP_W1_TX_PIO_WR_1); /* Padding */
+
+ /* wait for Tx complete */
+ while((inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS) != 0)
+ ;
+}
+
+/**************************************************************************
+ETH_POLL - Wait for a frame
+***************************************************************************/
+static int t509_poll(struct nic *nic, int retrieve)
+{
+ /* common variables */
+ /* variables for 3C509 */
+ short status, cst;
+ register short rx_fifo;
+
+ cst=inw(nic->ioaddr + EP_STATUS);
+
+#ifdef EDEBUG
+ if(cst & 0x1FFF)
+ printf("-%hX-",cst);
+#endif
+
+ if( (cst & S_RX_COMPLETE)==0 ) {
+ /* acknowledge everything */
+ outw(ACK_INTR| (cst & S_5_INTS), nic->ioaddr + EP_COMMAND);
+ outw(C_INTR_LATCH, nic->ioaddr + EP_COMMAND);
+
+ return 0;
+ }
+
+ status = inw(nic->ioaddr + EP_W1_RX_STATUS);
+#ifdef EDEBUG
+ printf("*%hX*",status);
+#endif
+
+ if (status & ERR_RX) {
+ outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND);
+ return 0;
+ }
+
+ rx_fifo = status & RX_BYTES_MASK;
+ if (rx_fifo==0)
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+ /* read packet */
+#ifdef EDEBUG
+ printf("[l=%d",rx_fifo);
+#endif
+ insw(nic->ioaddr + EP_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2);
+ if(rx_fifo & 1)
+ nic->packet[rx_fifo-1]=inb(nic->ioaddr + EP_W1_RX_PIO_RD_1);
+ nic->packetlen=rx_fifo;
+
+ while(1) {
+ status = inw(nic->ioaddr + EP_W1_RX_STATUS);
+#ifdef EDEBUG
+ printf("*%hX*",status);
+#endif
+ rx_fifo = status & RX_BYTES_MASK;
+ if(rx_fifo>0) {
+ insw(nic->ioaddr + EP_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2);
+ if(rx_fifo & 1)
+ nic->packet[nic->packetlen+rx_fifo-1]=inb(nic->ioaddr + EP_W1_RX_PIO_RD_1);
+ nic->packetlen+=rx_fifo;
+#ifdef EDEBUG
+ printf("+%d",rx_fifo);
+#endif
+ }
+ if(( status & RX_INCOMPLETE )==0) {
+#ifdef EDEBUG
+ printf("=%d",nic->packetlen);
+#endif
+ break;
+ }
+ udelay(1000); /* if incomplete wait 1 ms */
+ }
+ /* acknowledge reception of packet */
+ outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND);
+ while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS)
+ ;
+#ifdef EDEBUG
+{
+ unsigned short type = 0; /* used by EDEBUG */
+ type = (nic->packet[12]<<8) | nic->packet[13];
+ if(nic->packet[0]+nic->packet[1]+nic->packet[2]+nic->packet[3]+nic->packet[4]+
+ nic->packet[5] == 0xFF*ETH_ALEN)
+ printf(",t=%hX,b]",type);
+ else
+ printf(",t=%hX]",type);
+}
+#endif
+ return (1);
+}
+
+/**************************************************************************
+ETH_IRQ - interrupt handling
+***************************************************************************/
+static void t509_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+/*************************************************************************
+ 3Com 509 - specific routines
+**************************************************************************/
+
+static int eeprom_rdy ( uint16_t ioaddr ) {
+ int i;
+
+ for (i = 0; is_eeprom_busy(ioaddr) && i < MAX_EEPROMBUSY; i++);
+ if (i >= MAX_EEPROMBUSY) {
+ /* printf("3c509: eeprom failed to come ready.\n"); */
+ /* memory in EPROM is tight */
+ /* printf("3c509: eeprom busy.\n"); */
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * get_e: gets a 16 bits word from the EEPROM.
+ */
+static int get_e ( uint16_t ioaddr, int offset ) {
+ GO_WINDOW(ioaddr,0);
+ if (!eeprom_rdy(ioaddr))
+ return (0xffff);
+ outw(EEPROM_CMD_RD | offset, ioaddr + EP_W0_EEPROM_COMMAND);
+ if (!eeprom_rdy(ioaddr))
+ return (0xffff);
+ return (inw(ioaddr + EP_W0_EEPROM_DATA));
+}
+
+static struct nic_operations t509_operations = {
+ .connect = dummy_connect,
+ .poll = t509_poll,
+ .transmit = t509_transmit,
+ .irq = t509_irq,
+};
+
+/**************************************************************************
+ETH_PROBE - Look for an adapter
+***************************************************************************/
+int t5x9_probe ( struct nic *nic,
+ uint16_t prod_id_check, uint16_t prod_id_mask ) {
+ uint16_t prod_id;
+ int i,j;
+ unsigned short *p;
+
+ /* Check product ID */
+ prod_id = get_e ( nic->ioaddr, EEPROM_PROD_ID );
+ if ( ( prod_id & prod_id_mask ) != prod_id_check ) {
+ printf ( "EEPROM Product ID is incorrect (%hx & %hx != %hx)\n",
+ prod_id, prod_id_mask, prod_id_check );
+ return 0;
+ }
+
+ /* test for presence of connectors */
+ GO_WINDOW(nic->ioaddr,0);
+ i = inw(nic->ioaddr + EP_W0_CONFIG_CTRL);
+ j = (inw(nic->ioaddr + EP_W0_ADDRESS_CFG) >> 14) & 0x3;
+
+ switch(j) {
+ case 0:
+ if (i & IS_UTP) {
+ printf("10baseT\n");
+ connector = utp;
+ } else {
+ printf("10baseT not present\n");
+ return 0;
+ }
+ break;
+ case 1:
+ if (i & IS_AUI) {
+ printf("10base5\n");
+ } else {
+ printf("10base5 not present\n");
+ return 0;
+ }
+ break;
+ case 3:
+ if (i & IS_BNC) {
+ printf("10base2\n");
+ connector = bnc;
+ } else {
+ printf("10base2 not present\n");
+ return 0;
+ }
+ break;
+ default:
+ printf("unknown connector\n");
+ return 0;
+ }
+
+ /*
+ * Read the station address from the eeprom
+ */
+ p = (unsigned short *) nic->node_addr;
+ for (i = 0; i < ETH_ALEN / 2; i++) {
+ p[i] = htons(get_e(nic->ioaddr,i));
+ GO_WINDOW(nic->ioaddr,2);
+ outw(ntohs(p[i]), nic->ioaddr + EP_W2_ADDR_0 + (i * 2));
+ }
+
+ DBG ( "Ethernet Address: %s\n", eth_ntoa ( nic->node_addr ) );
+
+ t509_reset(nic);
+
+ nic->nic_op = &t509_operations;
+ return 1;
+
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/3c90x.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c90x.c
new file mode 100644
index 00000000..c1900574
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c90x.c
@@ -0,0 +1,988 @@
+/*
+ * 3c90x.c -- This file implements a iPXE API 3c90x driver
+ *
+ * Originally written for etherboot by:
+ * Greg Beeley, Greg.Beeley@LightSys.org
+ * Modified by Steve Smith,
+ * Steve.Smith@Juno.Com. Alignment bug fix Neil Newell (nn@icenoir.net).
+ * Almost totally Rewritten to use iPXE API, implementation of tx/rx ring support
+ * by Thomas Miletich, thomas.miletich@gmail.com
+ * Thanks to Marty Connor and Stefan Hajnoczi for their help and feedback,
+ * and to Daniel Verkamp for his help with testing.
+ *
+ * Copyright (c) 2009 Thomas Miletich
+ *
+ * Copyright (c) 1999 LightSys Technology Services, Inc.
+ * Portions Copyright (c) 1999 Steve Smith
+ *
+ * This program may be re-distributed in source or binary form, modified,
+ * sold, or copied for any purpose, provided that the above copyright message
+ * and this text are included with all source copies or derivative works, and
+ * provided that the above copyright message and this text are included in the
+ * documentation of any binary-only distributions. This program is distributed
+ * WITHOUT ANY WARRANTY, without even the warranty of FITNESS FOR A PARTICULAR
+ * PURPOSE or MERCHANTABILITY. Please read the associated documentation
+ * "3c90x.txt" before compiling and using this driver.
+ *
+ * [ --mdc 20090313 The 3c90x.txt file is now at:
+ * http://etherboot.org/wiki/appnotes/3c90x_issues ]
+ *
+ * This program was written with the assistance of the 3com documentation for
+ * the 3c905B-TX card, as well as with some assistance from the 3c59x
+ * driver Donald Becker wrote for the Linux kernel, and with some assistance
+ * from the remainder of the Etherboot distribution.
+ *
+ * Indented with unix 'indent' command:
+ * $ indent -kr -i8 3c90x.c
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/io.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/pci.h>
+#include <ipxe/timer.h>
+#include <ipxe/nvs.h>
+
+#include "3c90x.h"
+
+/**
+ * a3c90x_internal_IssueCommand: sends a command to the 3c90x card
+ * and waits for it's completion
+ *
+ * @v ioaddr IOAddress of the NIC
+ * @v cmd Command to be issued
+ * @v param Command parameter
+ */
+static void a3c90x_internal_IssueCommand(int ioaddr, int cmd, int param)
+{
+ unsigned int val = (cmd << 11) | param;
+ int cnt = 0;
+
+ DBGP("a3c90x_internal_IssueCommand\n");
+
+ /* Send the cmd to the cmd register */
+ outw(val, ioaddr + regCommandIntStatus_w);
+
+ /* Wait for the cmd to complete */
+ for (cnt = 0; cnt < 100000; cnt++) {
+ if (inw(ioaddr + regCommandIntStatus_w) & INT_CMDINPROGRESS) {
+ continue;
+ } else {
+ DBG2("Command 0x%04X finished in time. cnt = %d.\n", cmd, cnt);
+ return;
+ }
+ }
+
+ DBG("Command 0x%04X DID NOT finish in time. cnt = %d.\n", cmd, cnt);
+}
+
+/**
+ * a3c90x_internal_SetWindow: selects a register window set.
+ *
+ * @v inf_3c90x private NIC data
+ * @v window window to be selected
+ */
+static void a3c90x_internal_SetWindow(struct INF_3C90X *inf_3c90x, int window)
+{
+ DBGP("a3c90x_internal_SetWindow\n");
+ /* Window already as set? */
+ if (inf_3c90x->CurrentWindow == window)
+ return;
+
+ /* Issue the window command. */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdSelectRegisterWindow, window);
+ inf_3c90x->CurrentWindow = window;
+
+ return;
+}
+
+static void a3c90x_internal_WaitForEeprom(struct INF_3C90X *inf_3c90x)
+{
+ int cnt = 0;
+
+ DBGP("a3c90x_internal_WaitForEeprom\n");
+
+ while (eepromBusy & inw(inf_3c90x->IOAddr + regEepromCommand_0_w)) {
+ if (cnt == EEPROM_TIMEOUT) {
+ DBG("Read from eeprom failed: timeout\n");
+ return;
+ }
+ udelay(1);
+ cnt++;
+ }
+}
+
+/**
+ * a3c90x_internal_ReadEeprom - nvs routine to read eeprom data
+ * We only support reading one word(2 byte). The nvs subsystem will make sure
+ * that the routine will never be called with len != 2.
+ *
+ * @v nvs nvs data.
+ * @v address eeprom address to read data from.
+ * @v data data is put here.
+ * @v len number of bytes to read.
+ */
+static int
+a3c90x_internal_ReadEeprom(struct nvs_device *nvs, unsigned int address, void *data, size_t len)
+{
+ unsigned short *dest = (unsigned short *) data;
+ struct INF_3C90X *inf_3c90x =
+ container_of(nvs, struct INF_3C90X, nvs);
+
+ DBGP("a3c90x_internal_ReadEeprom\n");
+
+ /* we support reading 2 bytes only */
+ assert(len == 2);
+
+ /* Select correct window */
+ a3c90x_internal_SetWindow(inf_3c90x, winEepromBios0);
+
+ /* set eepromRead bits in command sent to NIC */
+ address += (inf_3c90x->is3c556 ? eepromRead_556 : eepromRead);
+
+ a3c90x_internal_WaitForEeprom(inf_3c90x);
+ /* send address to NIC */
+ outw(address, inf_3c90x->IOAddr + regEepromCommand_0_w);
+ a3c90x_internal_WaitForEeprom(inf_3c90x);
+
+ /* read value */
+ *dest = inw(inf_3c90x->IOAddr + regEepromData_0_w);
+
+ return 0;
+}
+
+/**
+ * a3c90x_internal_WriteEeprom - nvs routine to write eeprom data
+ * currently not implemented
+ *
+ * @v nvs nvs data.
+ * @v address eeprom address to read data from.
+ * @v data data is put here.
+ * @v len number of bytes to read.
+ */
+static int
+a3c90x_internal_WriteEeprom(struct nvs_device *nvs __unused,
+ unsigned int address __unused,
+ const void *data __unused, size_t len __unused)
+{
+ return -ENOTSUP;
+}
+
+static void a3c90x_internal_ReadEepromContents(struct INF_3C90X *inf_3c90x)
+{
+ int eeprom_size = (inf_3c90x->isBrev ? 0x20 : 0x17) * 2;
+
+ DBGP("a3c90x_internal_ReadEepromContents\n");
+
+ nvs_read(&inf_3c90x->nvs, 0, inf_3c90x->eeprom, eeprom_size);
+}
+
+/**
+ * a3c90x_reset: exported function that resets the card to its default
+ * state. This is so the Linux driver can re-set the card up the way
+ * it wants to. If CFG_3C90X_PRESERVE_XCVR is defined, then the reset will
+ * not alter the selected transceiver that we used to download the boot
+ * image.
+ *
+ * @v inf_3c90x Private NIC data
+ */
+static void a3c90x_reset(struct INF_3C90X *inf_3c90x)
+{
+ DBGP("a3c90x_reset\n");
+ /* Send the reset command to the card */
+ DBG2("3c90x: Issuing RESET\n");
+
+ /* reset of the receiver on B-revision cards re-negotiates the link
+ * takes several seconds (a computer eternity), so we don't reset
+ * it here.
+ */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdGlobalReset,
+ globalResetMaskNetwork);
+
+ /* global reset command resets station mask, non-B revision cards
+ * require explicit reset of values
+ */
+ a3c90x_internal_SetWindow(inf_3c90x, winAddressing2);
+ outw(0, inf_3c90x->IOAddr + regStationMask_2_3w + 0);
+ outw(0, inf_3c90x->IOAddr + regStationMask_2_3w + 2);
+ outw(0, inf_3c90x->IOAddr + regStationMask_2_3w + 4);
+
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdTxEnable, 0);
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdRxEnable, 0);
+
+ /* enable rxComplete and txComplete indications */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdSetIndicationEnable,
+ INT_TXCOMPLETE | INT_UPCOMPLETE);
+
+ /* acknowledge any pending status flags */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdAcknowledgeInterrupt, 0x661);
+
+ return;
+}
+
+/**
+ * a3c90x_setup_tx_ring - Allocates TX ring, initialize tx_desc values
+ *
+ * @v p Private NIC data
+ *
+ * @ret Returns 0 on success, negative on failure
+ */
+static int a3c90x_setup_tx_ring(struct INF_3C90X *p)
+{
+ DBGP("a3c90x_setup_tx_ring\n");
+ p->tx_ring =
+ malloc_dma(TX_RING_SIZE * sizeof(struct TXD), TX_RING_ALIGN);
+
+ if (!p->tx_ring) {
+ DBG("Could not allocate TX-ring\n");
+ return -ENOMEM;
+ }
+
+ memset(p->tx_ring, 0, TX_RING_SIZE * sizeof(struct TXD));
+ p->tx_cur = 0;
+ p->tx_cnt = 0;
+ p->tx_tail = 0;
+
+ return 0;
+}
+
+/**
+ * a3c90x_process_tx_packets - Checks for successfully sent packets,
+ * reports them to iPXE with netdev_tx_complete();
+ *
+ * @v netdev Network device info
+ */
+static void a3c90x_process_tx_packets(struct net_device *netdev)
+{
+ struct INF_3C90X *p = netdev_priv(netdev);
+ unsigned int downlist_ptr;
+
+ DBGP("a3c90x_process_tx_packets\n");
+
+ DBG2(" tx_cnt: %d\n", p->tx_cnt);
+
+ while (p->tx_tail != p->tx_cur) {
+
+ downlist_ptr = inl(p->IOAddr + regDnListPtr_l);
+
+ DBG2(" downlist_ptr: %#08x\n", downlist_ptr);
+ DBG2(" tx_tail: %d tx_cur: %d\n", p->tx_tail, p->tx_cur);
+
+ /* NIC is currently working on this tx desc */
+ if(downlist_ptr == virt_to_bus(p->tx_ring + p->tx_tail))
+ return;
+
+ netdev_tx_complete(netdev, p->tx_iobuf[p->tx_tail]);
+
+ DBG2("transmitted packet\n");
+ DBG2(" size: %zd\n", iob_len(p->tx_iobuf[p->tx_tail]));
+
+ p->tx_tail = (p->tx_tail + 1) % TX_RING_SIZE;
+ p->tx_cnt--;
+ }
+}
+
+static void a3c90x_free_tx_ring(struct INF_3C90X *p)
+{
+ DBGP("a3c90x_free_tx_ring\n");
+
+ free_dma(p->tx_ring, TX_RING_SIZE * sizeof(struct TXD));
+ p->tx_ring = NULL;
+ /* io_buffers are free()ed by netdev_tx_complete[,_err]() */
+}
+
+/**
+ * a3c90x_transmit - Transmits a packet.
+ *
+ * @v netdev Network device info
+ * @v iob io_buffer containing the data to be send
+ *
+ * @ret Returns 0 on success, negative on failure
+ */
+static int a3c90x_transmit(struct net_device *netdev,
+ struct io_buffer *iob)
+{
+ struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+ struct TXD *tx_cur_desc;
+ struct TXD *tx_prev_desc;
+
+ unsigned int len;
+ unsigned int downlist_ptr;
+
+ DBGP("a3c90x_transmit\n");
+
+ if (inf_3c90x->tx_cnt == TX_RING_SIZE) {
+ DBG("TX-Ring overflow\n");
+ return -ENOBUFS;
+ }
+
+ inf_3c90x->tx_iobuf[inf_3c90x->tx_cur] = iob;
+ tx_cur_desc = inf_3c90x->tx_ring + inf_3c90x->tx_cur;
+
+ tx_prev_desc = inf_3c90x->tx_ring +
+ (((inf_3c90x->tx_cur + TX_RING_SIZE) - 1) % TX_RING_SIZE);
+
+ len = iob_len(iob);
+
+ /* Setup the DPD (download descriptor) */
+ tx_cur_desc->DnNextPtr = 0;
+
+ /* FrameStartHeader differs in 90x and >= 90xB
+ * It contains length in 90x and a round up boundary and packet ID for
+ * 90xB and 90xC. We can leave this to 0 for 90xB and 90xC.
+ */
+ tx_cur_desc->FrameStartHeader =
+ fshTxIndicate | (inf_3c90x->isBrev ? 0x00 : len);
+
+ tx_cur_desc->DataAddr = virt_to_bus(iob->data);
+ tx_cur_desc->DataLength = len | downLastFrag;
+
+ /* We have to stall the download engine, so the NIC won't access the
+ * tx descriptor while we modify it. There is a way around this
+ * from revision B and upwards. To stay compatible with older revisions
+ * we don't use it here.
+ */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdStallCtl,
+ dnStall);
+
+ tx_prev_desc->DnNextPtr = virt_to_bus(tx_cur_desc);
+
+ downlist_ptr = inl(inf_3c90x->IOAddr + regDnListPtr_l);
+ if (downlist_ptr == 0) {
+ /* currently no DownList, sending a new one */
+ outl(virt_to_bus(tx_cur_desc),
+ inf_3c90x->IOAddr + regDnListPtr_l);
+ }
+
+ /* End Stall */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdStallCtl,
+ dnUnStall);
+
+ inf_3c90x->tx_cur = (inf_3c90x->tx_cur + 1) % TX_RING_SIZE;
+ inf_3c90x->tx_cnt++;
+
+ return 0;
+}
+
+/**
+ * a3c90x_prepare_rx_desc - fills the rx desc with initial data
+ *
+ * @v p NIC private data
+ * @v index Index for rx_iobuf and rx_ring array
+ */
+
+static void a3c90x_prepare_rx_desc(struct INF_3C90X *p, unsigned int index)
+{
+ DBGP("a3c90x_prepare_rx_desc\n");
+ DBG2("Populating rx_desc %d\n", index);
+
+ /* We have to stall the upload engine, so the NIC won't access the
+ * rx descriptor while we modify it. There is a way around this
+ * from revision B and upwards. To stay compatible with older revisions
+ * we don't use it here.
+ */
+ a3c90x_internal_IssueCommand(p->IOAddr, cmdStallCtl, upStall);
+
+ p->rx_ring[index].DataAddr = virt_to_bus(p->rx_iobuf[index]->data);
+ p->rx_ring[index].DataLength = RX_BUF_SIZE | upLastFrag;
+ p->rx_ring[index].UpPktStatus = 0;
+
+ /* unstall upload engine */
+ a3c90x_internal_IssueCommand(p->IOAddr, cmdStallCtl, upUnStall);
+}
+
+/**
+ * a3c90x_refill_rx_ring -checks every entry in the rx ring and reallocates
+ * them as necessary. Then it calls a3c90x_prepare_rx_desc to fill the rx desc
+ * with initial data.
+ *
+ * @v p NIC private data
+ */
+static void a3c90x_refill_rx_ring(struct INF_3C90X *p)
+{
+ int i;
+ unsigned int status;
+ struct RXD *rx_cur_desc;
+
+ DBGP("a3c90x_refill_rx_ring\n");
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_cur_desc = p->rx_ring + i;
+ status = rx_cur_desc->UpPktStatus;
+
+ /* only refill used descriptor */
+ if (!(status & upComplete))
+ continue;
+
+ /* we still need to process this descriptor */
+ if (p->rx_iobuf[i] != NULL)
+ continue;
+
+ p->rx_iobuf[i] = alloc_iob(RX_BUF_SIZE);
+ if (p->rx_iobuf[i] == NULL) {
+ DBG("alloc_iob() failed\n");
+ break;
+ }
+
+ a3c90x_prepare_rx_desc(p, i);
+ }
+}
+
+/**
+ * a3c90x_setup_rx_ring - Allocates RX ring, initialize rx_desc values
+ *
+ * @v p Private NIC data
+ *
+ * @ret Returns 0 on success, negative on failure
+ */
+static int a3c90x_setup_rx_ring(struct INF_3C90X *p)
+{
+ int i;
+
+ DBGP("a3c90x_setup_rx_ring\n");
+
+ p->rx_ring =
+ malloc_dma(RX_RING_SIZE * sizeof(struct RXD), RX_RING_ALIGN);
+
+ if (!p->rx_ring) {
+ DBG("Could not allocate RX-ring\n");
+ return -ENOMEM;
+ }
+
+ p->rx_cur = 0;
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ p->rx_ring[i].UpNextPtr =
+ virt_to_bus(p->rx_ring + (i + 1));
+
+ /* these are needed so refill_rx_ring initializes the ring */
+ p->rx_ring[i].UpPktStatus = upComplete;
+ p->rx_iobuf[i] = NULL;
+ }
+
+ /* Loop the ring */
+ p->rx_ring[i - 1].UpNextPtr = virt_to_bus(p->rx_ring);
+
+ a3c90x_refill_rx_ring(p);
+
+ return 0;
+}
+
+static void a3c90x_free_rx_ring(struct INF_3C90X *p)
+{
+ DBGP("a3c90x_free_rx_ring\n");
+
+ free_dma(p->rx_ring, RX_RING_SIZE * sizeof(struct RXD));
+ p->rx_ring = NULL;
+}
+
+static void a3c90x_free_rx_iobuf(struct INF_3C90X *p)
+{
+ int i;
+
+ DBGP("a3c90x_free_rx_iobuf\n");
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ free_iob(p->rx_iobuf[i]);
+ p->rx_iobuf[i] = NULL;
+ }
+}
+
+/**
+ * a3c90x_process_rx_packets - Checks for received packets,
+ * reports them to iPXE with netdev_rx() or netdev_rx_err() if there was an
+ * error while receiving the packet
+ *
+ * @v netdev Network device info
+ */
+static void a3c90x_process_rx_packets(struct net_device *netdev)
+{
+ int i;
+ unsigned int rx_status;
+ struct INF_3C90X *p = netdev_priv(netdev);
+ struct RXD *rx_cur_desc;
+
+ DBGP("a3c90x_process_rx_packets\n");
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_cur_desc = p->rx_ring + p->rx_cur;
+ rx_status = rx_cur_desc->UpPktStatus;
+
+ if (!(rx_status & upComplete) && !(rx_status & upError))
+ break;
+
+ if (p->rx_iobuf[p->rx_cur] == NULL)
+ break;
+
+ if (rx_status & upError) {
+ DBG("Corrupted packet received: %#x\n", rx_status);
+ netdev_rx_err(netdev, p->rx_iobuf[p->rx_cur],
+ -EINVAL);
+ } else {
+ /* if we're here, we've got good packet */
+ int packet_len;
+
+ packet_len = rx_status & 0x1FFF;
+ iob_put(p->rx_iobuf[p->rx_cur], packet_len);
+
+ DBG2("received packet\n");
+ DBG2(" size: %d\n", packet_len);
+
+ netdev_rx(netdev, p->rx_iobuf[p->rx_cur]);
+ }
+
+ p->rx_iobuf[p->rx_cur] = NULL; /* invalidate rx desc */
+ p->rx_cur = (p->rx_cur + 1) % RX_RING_SIZE;
+ }
+ a3c90x_refill_rx_ring(p);
+
+}
+
+/**
+ * a3c90x_poll - Routine that gets called periodically.
+ * Here we hanle transmitted and received packets.
+ * We could also check the link status from time to time, which we
+ * currently don't do.
+ *
+ * @v netdev Network device info
+ */
+static void a3c90x_poll(struct net_device *netdev)
+{
+ struct INF_3C90X *p = netdev_priv(netdev);
+ uint16_t raw_status, int_status;
+
+ DBGP("a3c90x_poll\n");
+
+ raw_status = inw(p->IOAddr + regCommandIntStatus_w);
+ int_status = (raw_status & 0x0FFF);
+
+ if ( int_status == 0 )
+ return;
+
+ a3c90x_internal_IssueCommand(p->IOAddr, cmdAcknowledgeInterrupt,
+ int_status);
+
+ if (int_status & INT_TXCOMPLETE)
+ outb(0x00, p->IOAddr + regTxStatus_b);
+
+ DBG2("poll: status = %#04x\n", raw_status);
+
+ a3c90x_process_tx_packets(netdev);
+
+ a3c90x_process_rx_packets(netdev);
+}
+
+
+
+static void a3c90x_free_resources(struct INF_3C90X *p)
+{
+ DBGP("a3c90x_free_resources\n");
+
+ a3c90x_free_tx_ring(p);
+ a3c90x_free_rx_ring(p);
+ a3c90x_free_rx_iobuf(p);
+}
+
+/**
+ * a3c90x_remove - Routine to remove the card. Unregisters
+ * the NIC from iPXE, disables RX/TX and resets the card.
+ *
+ * @v pci PCI device info
+ */
+static void a3c90x_remove(struct pci_device *pci)
+{
+ struct net_device *netdev = pci_get_drvdata(pci);
+ struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+
+ DBGP("a3c90x_remove\n");
+
+ a3c90x_reset(inf_3c90x);
+
+ /* Disable the receiver and transmitter. */
+ outw(cmdRxDisable, inf_3c90x->IOAddr + regCommandIntStatus_w);
+ outw(cmdTxDisable, inf_3c90x->IOAddr + regCommandIntStatus_w);
+
+ unregister_netdev(netdev);
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+}
+
+static void a3c90x_irq(struct net_device *netdev, int enable)
+{
+ struct INF_3C90X *p = netdev_priv(netdev);
+
+ DBGP("a3c90x_irq\n");
+
+ if (enable == 0) {
+ /* disable interrupts */
+ a3c90x_internal_IssueCommand(p->IOAddr,
+ cmdSetInterruptEnable, 0);
+ } else {
+ a3c90x_internal_IssueCommand(p->IOAddr,
+ cmdSetInterruptEnable,
+ INT_TXCOMPLETE |
+ INT_UPCOMPLETE);
+ a3c90x_internal_IssueCommand(p->IOAddr,
+ cmdAcknowledgeInterrupt,
+ 0x661);
+ }
+}
+
+/**
+ * a3c90x_hw_start - Initialize hardware, copy MAC address
+ * to NIC registers, set default receiver
+ */
+static void a3c90x_hw_start(struct net_device *netdev)
+{
+ int i, c;
+ unsigned int cfg;
+ unsigned int mopt;
+ unsigned short linktype;
+ struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+
+ DBGP("a3c90x_hw_start\n");
+
+ /* 3C556: Invert MII power */
+ if (inf_3c90x->is3c556) {
+ unsigned int tmp;
+ a3c90x_internal_SetWindow(inf_3c90x, winAddressing2);
+ tmp = inw(inf_3c90x->IOAddr + regResetOptions_2_w);
+ tmp |= 0x4000;
+ outw(tmp, inf_3c90x->IOAddr + regResetOptions_2_w);
+ }
+
+ /* Copy MAC address into the NIC registers */
+ a3c90x_internal_SetWindow(inf_3c90x, winAddressing2);
+ for (i = 0; i < ETH_ALEN; i++)
+ outb(netdev->ll_addr[i],
+ inf_3c90x->IOAddr + regStationAddress_2_3w + i);
+ for (i = 0; i < ETH_ALEN; i++)
+ outb(0, inf_3c90x->IOAddr + regStationMask_2_3w + i);
+
+ /* Read the media options register, print a message and set default
+ * xcvr.
+ *
+ * Uses Media Option command on B revision, Reset Option on non-B
+ * revision cards -- same register address
+ */
+ a3c90x_internal_SetWindow(inf_3c90x, winTxRxOptions3);
+ mopt = inw(inf_3c90x->IOAddr + regResetMediaOptions_3_w);
+
+ /* mask out VCO bit that is defined as 10baseFL bit on B-rev cards */
+ if (!inf_3c90x->isBrev) {
+ mopt &= 0x7F;
+ }
+
+ DBG2("Connectors present: ");
+ c = 0;
+ linktype = 0x0008;
+ if (mopt & 0x01) {
+ DBG2("%s100Base-T4", (c++) ? ", " : "");
+ linktype = linkMII;
+ }
+ if (mopt & 0x04) {
+ DBG2("%s100Base-FX", (c++) ? ", " : "");
+ linktype = link100BaseFX;
+ }
+ if (mopt & 0x10) {
+ DBG2("%s10Base-2", (c++) ? ", " : "");
+ linktype = link10Base2;
+ }
+ if (mopt & 0x20) {
+ DBG2("%sAUI", (c++) ? ", " : "");
+ linktype = linkAUI;
+ }
+ if (mopt & 0x40) {
+ DBG2("%sMII", (c++) ? ", " : "");
+ linktype = linkMII;
+ }
+ if ((mopt & 0xA) == 0xA) {
+ DBG2("%s10Base-T / 100Base-TX", (c++) ? ", " : "");
+ linktype = linkAutoneg;
+ } else if ((mopt & 0xA) == 0x2) {
+ DBG2("%s100Base-TX", (c++) ? ", " : "");
+ linktype = linkAutoneg;
+ } else if ((mopt & 0xA) == 0x8) {
+ DBG2("%s10Base-T", (c++) ? ", " : "");
+ linktype = linkAutoneg;
+ }
+ DBG2(".\n");
+
+ /* Determine transceiver type to use, depending on value stored in
+ * eeprom 0x16
+ */
+ if (inf_3c90x->isBrev) {
+ if ((inf_3c90x->eeprom[0x16] & 0xFF00) == XCVR_MAGIC) {
+ /* User-defined */
+ linktype = inf_3c90x->eeprom[0x16] & 0x000F;
+ }
+ } else {
+ /* I don't know what MII MAC only mode is!!! */
+ if (linktype == linkExternalMII) {
+ if (inf_3c90x->isBrev)
+ DBG("WARNING: MII External MAC Mode only supported on B-revision " "cards!!!!\nFalling Back to MII Mode\n");
+ linktype = linkMII;
+ }
+ }
+
+ /* enable DC converter for 10-Base-T */
+ if (linktype == link10Base2) {
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdEnableDcConverter, 0);
+ }
+
+ /* Set the link to the type we just determined. */
+ a3c90x_internal_SetWindow(inf_3c90x, winTxRxOptions3);
+ cfg = inl(inf_3c90x->IOAddr + regInternalConfig_3_l);
+ cfg &= ~(0xF << 20);
+ cfg |= (linktype << 20);
+
+ DBG2("Setting internal cfg register: 0x%08X (linktype: 0x%02X)\n",
+ cfg, linktype);
+
+ outl(cfg, inf_3c90x->IOAddr + regInternalConfig_3_l);
+
+ /* Now that we set the xcvr type, reset the Tx and Rx */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdTxReset, 0x00);
+
+ if (!inf_3c90x->isBrev)
+ outb(0x01, inf_3c90x->IOAddr + regTxFreeThresh_b);
+
+ /* Set the RX filter = receive only individual pkts & multicast & bcast. */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdSetRxFilter,
+ 0x01 + 0x02 + 0x04);
+
+
+ /*
+ * set Indication and Interrupt flags , acknowledge any IRQ's
+ */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdSetInterruptEnable,
+ INT_TXCOMPLETE | INT_UPCOMPLETE);
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdSetIndicationEnable,
+ INT_TXCOMPLETE | INT_UPCOMPLETE);
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdAcknowledgeInterrupt, 0x661);
+}
+
+/**
+ * a3c90x_open - Routine to initialize the card. Initialize hardware,
+ * allocate TX and RX ring, send RX ring address to the NIC.
+ *
+ * @v netdev Network device info
+ *
+ * @ret Returns 0 on success, negative on failure
+ */
+static int a3c90x_open(struct net_device *netdev)
+{
+ int rc;
+ struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+
+ DBGP("a3c90x_open\n");
+
+ a3c90x_hw_start(netdev);
+
+ rc = a3c90x_setup_tx_ring(inf_3c90x);
+ if (rc != 0) {
+ DBG("Error setting up TX Ring\n");
+ goto error;
+ }
+
+ rc = a3c90x_setup_rx_ring(inf_3c90x);
+ if (rc != 0) {
+ DBG("Error setting up RX Ring\n");
+ goto error;
+ }
+
+ /* send rx_ring address to NIC */
+ outl(virt_to_bus(inf_3c90x->rx_ring),
+ inf_3c90x->IOAddr + regUpListPtr_l);
+
+ /* enable packet transmission and reception */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdTxEnable, 0);
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdRxEnable, 0);
+
+ return 0;
+
+ error:
+ a3c90x_free_resources(inf_3c90x);
+ a3c90x_reset(inf_3c90x);
+ return rc;
+}
+
+/**
+ * a3c90x_close - free()s TX and RX ring, disablex RX/TX, resets NIC
+ *
+ * @v netdev Network device info
+ */
+static void a3c90x_close(struct net_device *netdev)
+{
+ struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+
+ DBGP("a3c90x_close\n");
+
+ a3c90x_reset(inf_3c90x);
+ outw(cmdRxDisable, inf_3c90x->IOAddr + regCommandIntStatus_w);
+ outw(cmdTxDisable, inf_3c90x->IOAddr + regCommandIntStatus_w);
+ a3c90x_free_resources(inf_3c90x);
+}
+
+static struct net_device_operations a3c90x_operations = {
+ .open = a3c90x_open,
+ .close = a3c90x_close,
+ .poll = a3c90x_poll,
+ .transmit = a3c90x_transmit,
+ .irq = a3c90x_irq,
+};
+
+/**
+ * a3c90x_probe: exported routine to probe for the 3c905 card.
+ * If this routine is called, the pci functions did find the
+ * card. We read the eeprom here and get the MAC address.
+ * Initialization is done in a3c90x_open().
+ *
+ * @v pci PCI device info
+ * @ pci_id PCI device IDs
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ */
+static int a3c90x_probe(struct pci_device *pci)
+{
+
+ struct net_device *netdev;
+ struct INF_3C90X *inf_3c90x;
+ unsigned char *HWAddr;
+ int rc;
+
+ DBGP("a3c90x_probe\n");
+
+ if (pci->ioaddr == 0)
+ return -EINVAL;
+
+ netdev = alloc_etherdev(sizeof(*inf_3c90x));
+ if (!netdev)
+ return -ENOMEM;
+
+ netdev_init(netdev, &a3c90x_operations);
+ pci_set_drvdata(pci, netdev);
+ netdev->dev = &pci->dev;
+
+ inf_3c90x = netdev_priv(netdev);
+ memset(inf_3c90x, 0, sizeof(*inf_3c90x));
+
+ adjust_pci_device(pci);
+
+ inf_3c90x->is3c556 = (pci->device == 0x6055);
+ inf_3c90x->IOAddr = pci->ioaddr;
+ inf_3c90x->CurrentWindow = winNone;
+
+ inf_3c90x->isBrev = 1;
+ switch (pci->device) {
+ case 0x9000: /* 10 Base TPO */
+ case 0x9001: /* 10/100 T4 */
+ case 0x9050: /* 10/100 TPO */
+ case 0x9051: /* 10 Base Combo */
+ inf_3c90x->isBrev = 0;
+ break;
+ }
+
+ DBG2("[3c90x]: found NIC(0x%04X, 0x%04X), isBrev=%d, is3c556=%d\n",
+ pci->vendor, pci->device, inf_3c90x->isBrev,
+ inf_3c90x->is3c556);
+
+ /* initialize nvs device */
+ inf_3c90x->nvs.word_len_log2 = 1; /* word */
+ inf_3c90x->nvs.size = (inf_3c90x->isBrev ? 0x20 : 0x17);
+ inf_3c90x->nvs.block_size = 1;
+ inf_3c90x->nvs.read = a3c90x_internal_ReadEeprom;
+ inf_3c90x->nvs.write = a3c90x_internal_WriteEeprom;
+
+ /* reset NIC before accessing any data from it */
+ a3c90x_reset(inf_3c90x);
+
+ /* load eeprom contents to inf_3c90x->eeprom */
+ a3c90x_internal_ReadEepromContents(inf_3c90x);
+
+ HWAddr = netdev->hw_addr;
+
+ /* Retrieve the Hardware address */
+ HWAddr[0] = inf_3c90x->eeprom[eepromHwAddrOffset + 0] >> 8;
+ HWAddr[1] = inf_3c90x->eeprom[eepromHwAddrOffset + 0] & 0xFF;
+ HWAddr[2] = inf_3c90x->eeprom[eepromHwAddrOffset + 1] >> 8;
+ HWAddr[3] = inf_3c90x->eeprom[eepromHwAddrOffset + 1] & 0xFF;
+ HWAddr[4] = inf_3c90x->eeprom[eepromHwAddrOffset + 2] >> 8;
+ HWAddr[5] = inf_3c90x->eeprom[eepromHwAddrOffset + 2] & 0xFF;
+
+ if ((rc = register_netdev(netdev)) != 0) {
+ DBG("3c90x: register_netdev() failed\n");
+ netdev_put(netdev);
+ return rc;
+ }
+
+ /* we don't handle linkstates yet, so we're always up */
+ netdev_link_up(netdev);
+
+ return 0;
+}
+
+static struct pci_device_id a3c90x_nics[] = {
+/* Original 90x revisions: */
+ PCI_ROM(0x10b7, 0x6055, "3c556", "3C556", 0), /* Huricane */
+ PCI_ROM(0x10b7, 0x9000, "3c905-tpo", "3Com900-TPO", 0), /* 10 Base TPO */
+ PCI_ROM(0x10b7, 0x9001, "3c905-t4", "3Com900-Combo", 0), /* 10/100 T4 */
+ PCI_ROM(0x10b7, 0x9050, "3c905-tpo100", "3Com905-TX", 0), /* 100 Base TX / 10/100 TPO */
+ PCI_ROM(0x10b7, 0x9051, "3c905-combo", "3Com905-T4", 0), /* 100 Base T4 / 10 Base Combo */
+/* Newer 90xB revisions: */
+ PCI_ROM(0x10b7, 0x9004, "3c905b-tpo", "3Com900B-TPO", 0), /* 10 Base TPO */
+ PCI_ROM(0x10b7, 0x9005, "3c905b-combo", "3Com900B-Combo", 0), /* 10 Base Combo */
+ PCI_ROM(0x10b7, 0x9006, "3c905b-tpb2", "3Com900B-2/T", 0), /* 10 Base TP and Base2 */
+ PCI_ROM(0x10b7, 0x900a, "3c905b-fl", "3Com900B-FL", 0), /* 10 Base FL */
+ PCI_ROM(0x10b7, 0x9055, "3c905b-tpo100", "3Com905B-TX", 0), /* 10/100 TPO */
+ PCI_ROM(0x10b7, 0x9056, "3c905b-t4", "3Com905B-T4", 0), /* 10/100 T4 */
+ PCI_ROM(0x10b7, 0x9058, "3c905b-9058", "3Com905B-9058", 0), /* Cyclone 10/100/BNC */
+ PCI_ROM(0x10b7, 0x905a, "3c905b-fx", "3Com905B-FL", 0), /* 100 Base FX / 10 Base FX */
+/* Newer 90xC revision: */
+ PCI_ROM(0x10b7, 0x9200, "3c905c-tpo", "3Com905C-TXM", 0), /* 10/100 TPO (3C905C-TXM) */
+ PCI_ROM(0x10b7, 0x9202, "3c920b-emb-ati", "3c920B-EMB-WNM (ATI Radeon 9100 IGP)", 0), /* 3c920B-EMB-WNM (ATI Radeon 9100 IGP) */
+ PCI_ROM(0x10b7, 0x9210, "3c920b-emb-wnm", "3Com20B-EMB WNM", 0),
+ PCI_ROM(0x10b7, 0x9800, "3c980", "3Com980-Cyclone", 0), /* Cyclone */
+ PCI_ROM(0x10b7, 0x9805, "3c9805", "3Com9805", 0), /* Dual Port Server Cyclone */
+ PCI_ROM(0x10b7, 0x7646, "3csoho100-tx", "3CSOHO100-TX", 0), /* Hurricane */
+ PCI_ROM(0x10b7, 0x4500, "3c450", "3Com450 HomePNA Tornado", 0),
+ PCI_ROM(0x10b7, 0x1201, "3c982a", "3Com982A", 0),
+ PCI_ROM(0x10b7, 0x1202, "3c982b", "3Com982B", 0),
+};
+
+struct pci_driver a3c90x_driver __pci_driver = {
+ .ids = a3c90x_nics,
+ .id_count = (sizeof(a3c90x_nics) / sizeof(a3c90x_nics[0])),
+ .probe = a3c90x_probe,
+ .remove = a3c90x_remove,
+};
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/3c90x.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c90x.h
new file mode 100644
index 00000000..53fc522b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/3c90x.h
@@ -0,0 +1,308 @@
+/*
+ * 3c90x.c -- This file implements the 3c90x driver for etherboot. Written
+ * by Greg Beeley, Greg.Beeley@LightSys.org. Modified by Steve Smith,
+ * Steve.Smith@Juno.Com. Alignment bug fix Neil Newell (nn@icenoir.net).
+ *
+ * Port from etherboot to iPXE API, implementation of tx/rx ring support
+ * by Thomas Miletich, thomas.miletich@gmail.com
+ * Thanks to Marty Connor and Stefan Hajnoczi for their help and feedback.
+ *
+ * This program Copyright (C) 1999 LightSys Technology Services, Inc.
+ * Portions Copyright (C) 1999 Steve Smith
+ *
+ * This program may be re-distributed in source or binary form, modified,
+ * sold, or copied for any purpose, provided that the above copyright message
+ * and this text are included with all source copies or derivative works, and
+ * provided that the above copyright message and this text are included in the
+ * documentation of any binary-only distributions. This program is distributed
+ * WITHOUT ANY WARRANTY, without even the warranty of FITNESS FOR A PARTICULAR
+ * PURPOSE or MERCHANTABILITY. Please read the associated documentation
+ * "3c90x.txt" before compiling and using this driver.
+ *
+ * --------
+ *
+ * Program written with the assistance of the 3com documentation for
+ * the 3c905B-TX card, as well as with some assistance from the 3c59x
+ * driver Donald Becker wrote for the Linux kernel, and with some assistance
+ * from the remainder of the Etherboot distribution.
+ *
+ * REVISION HISTORY:
+ *
+ * v0.10 1-26-1998 GRB Initial implementation.
+ * v0.90 1-27-1998 GRB System works.
+ * v1.00pre1 2-11-1998 GRB Got prom boot issue fixed.
+ * v2.0 9-24-1999 SCS Modified for 3c905 (from 3c905b code)
+ * Re-wrote poll and transmit for
+ * better error recovery and heavy
+ * network traffic operation
+ * v2.01 5-26-2003 NN Fixed driver alignment issue which
+ * caused system lockups if driver structures
+ * not 8-byte aligned.
+ * v2.02 11-28-2007 GSt Got polling working again by replacing
+ * "for(i=0;i<40000;i++);" with "mdelay(1);"
+ *
+ *
+ * indent options: indent -kr -i8 3c90x.c
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#ifndef __3C90X_H_
+#define __3C90X_H_
+
+static struct net_device_operations a3c90x_operations;
+
+#define XCVR_MAGIC (0x5A00)
+
+/* Register definitions for the 3c905 */
+enum Registers {
+ regPowerMgmtCtrl_w = 0x7c, /* 905B Revision Only */
+ regUpMaxBurst_w = 0x7a, /* 905B Revision Only */
+ regDnMaxBurst_w = 0x78, /* 905B Revision Only */
+ regDebugControl_w = 0x74, /* 905B Revision Only */
+ regDebugData_l = 0x70, /* 905B Revision Only */
+ regRealTimeCnt_l = 0x40, /* Universal */
+ regUpBurstThresh_b = 0x3e, /* 905B Revision Only */
+ regUpPoll_b = 0x3d, /* 905B Revision Only */
+ regUpPriorityThresh_b = 0x3c, /* 905B Revision Only */
+ regUpListPtr_l = 0x38, /* Universal */
+ regCountdown_w = 0x36, /* Universal */
+ regFreeTimer_w = 0x34, /* Universal */
+ regUpPktStatus_l = 0x30, /* Universal with Exception, pg 130 */
+ regTxFreeThresh_b = 0x2f, /* 90X Revision Only */
+ regDnPoll_b = 0x2d, /* 905B Revision Only */
+ regDnPriorityThresh_b = 0x2c, /* 905B Revision Only */
+ regDnBurstThresh_b = 0x2a, /* 905B Revision Only */
+ regDnListPtr_l = 0x24, /* Universal with Exception, pg 107 */
+ regDmaCtrl_l = 0x20, /* Universal with Exception, pg 106 */
+ /* */
+ regIntStatusAuto_w = 0x1e, /* 905B Revision Only */
+ regTxStatus_b = 0x1b, /* Universal with Exception, pg 113 */
+ regTimer_b = 0x1a, /* Universal */
+ regTxPktId_b = 0x18, /* 905B Revision Only */
+ regCommandIntStatus_w = 0x0e, /* Universal (Command Variations) */
+};
+
+/* following are windowed registers */
+enum Registers7 {
+ regPowerMgmtEvent_7_w = 0x0c, /* 905B Revision Only */
+ regVlanEtherType_7_w = 0x04, /* 905B Revision Only */
+ regVlanMask_7_w = 0x00, /* 905B Revision Only */
+};
+
+enum Registers6 {
+ regBytesXmittedOk_6_w = 0x0c, /* Universal */
+ regBytesRcvdOk_6_w = 0x0a, /* Universal */
+ regUpperFramesOk_6_b = 0x09, /* Universal */
+ regFramesDeferred_6_b = 0x08, /* Universal */
+ regFramesRecdOk_6_b = 0x07, /* Universal with Exceptions, pg 142 */
+ regFramesXmittedOk_6_b = 0x06, /* Universal */
+ regRxOverruns_6_b = 0x05, /* Universal */
+ regLateCollisions_6_b = 0x04, /* Universal */
+ regSingleCollisions_6_b = 0x03, /* Universal */
+ regMultipleCollisions_6_b = 0x02, /* Universal */
+ regSqeErrors_6_b = 0x01, /* Universal */
+ regCarrierLost_6_b = 0x00, /* Universal */
+};
+
+enum Registers5 {
+ regIndicationEnable_5_w = 0x0c, /* Universal */
+ regInterruptEnable_5_w = 0x0a, /* Universal */
+ regTxReclaimThresh_5_b = 0x09, /* 905B Revision Only */
+ regRxFilter_5_b = 0x08, /* Universal */
+ regRxEarlyThresh_5_w = 0x06, /* Universal */
+ regTxStartThresh_5_w = 0x00, /* Universal */
+};
+
+enum Registers4 {
+ regUpperBytesOk_4_b = 0x0d, /* Universal */
+ regBadSSD_4_b = 0x0c, /* Universal */
+ regMediaStatus_4_w = 0x0a, /* Universal with Exceptions, pg 201 */
+ regPhysicalMgmt_4_w = 0x08, /* Universal */
+ regNetworkDiagnostic_4_w = 0x06, /* Universal with Exceptions, pg 203 */
+ regFifoDiagnostic_4_w = 0x04, /* Universal with Exceptions, pg 196 */
+ regVcoDiagnostic_4_w = 0x02, /* Undocumented? */
+};
+
+enum Registers3 {
+ regTxFree_3_w = 0x0c, /* Universal */
+ regRxFree_3_w = 0x0a, /* Universal with Exceptions, pg 125 */
+ regResetMediaOptions_3_w = 0x08, /* Media Options on B Revision, */
+ /* Reset Options on Non-B Revision */
+ regMacControl_3_w = 0x06, /* Universal with Exceptions, pg 199 */
+ regMaxPktSize_3_w = 0x04, /* 905B Revision Only */
+ regInternalConfig_3_l = 0x00, /* Universal, different bit */
+ /* definitions, pg 59 */
+};
+
+enum Registers2 {
+ regResetOptions_2_w = 0x0c, /* 905B Revision Only */
+ regStationMask_2_3w = 0x06, /* Universal with Exceptions, pg 127 */
+ regStationAddress_2_3w = 0x00, /* Universal with Exceptions, pg 127 */
+};
+
+enum Registers1 {
+ regRxStatus_1_w = 0x0a, /* 90X Revision Only, Pg 126 */
+};
+
+enum Registers0 {
+ regEepromData_0_w = 0x0c, /* Universal */
+ regEepromCommand_0_w = 0x0a, /* Universal */
+ regBiosRomData_0_b = 0x08, /* 905B Revision Only */
+ regBiosRomAddr_0_l = 0x04, /* 905B Revision Only */
+};
+
+
+/* The names for the eight register windows */
+enum Windows {
+ winNone = 0xff,
+ winPowerVlan7 = 0x07,
+ winStatistics6 = 0x06,
+ winTxRxControl5 = 0x05,
+ winDiagnostics4 = 0x04,
+ winTxRxOptions3 = 0x03,
+ winAddressing2 = 0x02,
+ winUnused1 = 0x01,
+ winEepromBios0 = 0x00,
+};
+
+
+/* Command definitions for the 3c90X */
+enum Commands {
+ cmdGlobalReset = 0x00, /* Universal with Exceptions, pg 151 */
+ cmdSelectRegisterWindow = 0x01, /* Universal */
+ cmdEnableDcConverter = 0x02, /* */
+ cmdRxDisable = 0x03, /* */
+ cmdRxEnable = 0x04, /* Universal */
+ cmdRxReset = 0x05, /* Universal */
+ cmdStallCtl = 0x06, /* Universal */
+ cmdTxEnable = 0x09, /* Universal */
+ cmdTxDisable = 0x0A, /* */
+ cmdTxReset = 0x0B, /* Universal */
+ cmdRequestInterrupt = 0x0C, /* */
+ cmdAcknowledgeInterrupt = 0x0D, /* Universal */
+ cmdSetInterruptEnable = 0x0E, /* Universal */
+ cmdSetIndicationEnable = 0x0F, /* Universal */
+ cmdSetRxFilter = 0x10, /* Universal */
+ cmdSetRxEarlyThresh = 0x11, /* */
+ cmdSetTxStartThresh = 0x13, /* */
+ cmdStatisticsEnable = 0x15, /* */
+ cmdStatisticsDisable = 0x16, /* */
+ cmdDisableDcConverter = 0x17, /* */
+ cmdSetTxReclaimThresh = 0x18, /* */
+ cmdSetHashFilterBit = 0x19, /* */
+};
+
+enum GlobalResetParams {
+ globalResetAll = 0,
+ globalResetMaskNetwork = (1<<2),
+ globalResetMaskAll = 0x1ff,
+};
+
+enum FrameStartHeader {
+ fshTxIndicate = 0x8000,
+ fshDnComplete = 0x10000,
+};
+
+enum UpDownDesc {
+ upLastFrag = (1 << 31),
+ downLastFrag = (1 << 31),
+};
+
+enum UpPktStatus {
+ upComplete = (1 << 15),
+ upError = (1 << 14),
+};
+
+enum Stalls {
+ upStall = 0x00,
+ upUnStall = 0x01,
+
+ dnStall = 0x02,
+ dnUnStall = 0x03,
+};
+
+enum Resources {
+ resRxRing = 0x00,
+ resTxRing = 0x02,
+ resRxIOBuf = 0x04
+};
+
+enum eeprom {
+ eepromBusy = (1 << 15),
+ eepromRead = ((0x02) << 6),
+ eepromRead_556 = 0x230,
+ eepromHwAddrOffset = 0x0a,
+};
+
+/* Bit 4 is only used in revison B and upwards */
+enum linktype {
+ link10BaseT = 0x00,
+ linkAUI = 0x01,
+ link10Base2 = 0x03,
+ link100BaseFX = 0x05,
+ linkMII = 0x06,
+ linkAutoneg = 0x08,
+ linkExternalMII = 0x09,
+};
+
+/* Values for int status register bitmask */
+#define INT_INTERRUPTLATCH (1<<0)
+#define INT_HOSTERROR (1<<1)
+#define INT_TXCOMPLETE (1<<2)
+#define INT_RXCOMPLETE (1<<4)
+#define INT_RXEARLY (1<<5)
+#define INT_INTREQUESTED (1<<6)
+#define INT_UPDATESTATS (1<<7)
+#define INT_LINKEVENT (1<<8)
+#define INT_DNCOMPLETE (1<<9)
+#define INT_UPCOMPLETE (1<<10)
+#define INT_CMDINPROGRESS (1<<12)
+#define INT_WINDOWNUMBER (7<<13)
+
+/* Buffer sizes */
+#define TX_RING_SIZE 8
+#define RX_RING_SIZE 8
+#define TX_RING_ALIGN 16
+#define RX_RING_ALIGN 16
+#define RX_BUF_SIZE 1536
+
+/* Timeouts for eeprom and command completion */
+/* Timeout 1 second, to be save */
+#define EEPROM_TIMEOUT 1 * 1000 * 1000
+
+/* TX descriptor */
+struct TXD {
+ volatile unsigned int DnNextPtr;
+ volatile unsigned int FrameStartHeader;
+ volatile unsigned int DataAddr;
+ volatile unsigned int DataLength;
+} __attribute__ ((aligned(8))); /* 64-bit aligned for bus mastering */
+
+/* RX descriptor */
+struct RXD {
+ volatile unsigned int UpNextPtr;
+ volatile unsigned int UpPktStatus;
+ volatile unsigned int DataAddr;
+ volatile unsigned int DataLength;
+} __attribute__ ((aligned(8))); /* 64-bit aligned for bus mastering */
+
+/* Private NIC dats */
+struct INF_3C90X {
+ unsigned int is3c556;
+ unsigned char isBrev;
+ unsigned char CurrentWindow;
+ unsigned int IOAddr;
+ unsigned short eeprom[0x21];
+ unsigned int tx_cur; /* current entry in tx_ring */
+ unsigned int tx_cnt; /* current number of used tx descriptors */
+ unsigned int tx_tail; /* entry of last finished packet */
+ unsigned int rx_cur;
+ struct TXD *tx_ring;
+ struct RXD *rx_ring;
+ struct io_buffer *tx_iobuf[TX_RING_SIZE];
+ struct io_buffer *rx_iobuf[RX_RING_SIZE];
+ struct nvs_device nvs;
+};
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/amd8111e.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/amd8111e.c
new file mode 100644
index 00000000..952e0278
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/amd8111e.c
@@ -0,0 +1,702 @@
+/* Advanced Micro Devices Inc. AMD8111E Linux Network Driver
+ * Copyright (C) 2004 Advanced Micro Devices
+ * Copyright (C) 2005 Liu Tao <liutao1980@gmail.com> [etherboot port]
+ *
+ * Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com> [ 8139cp.c,tg3.c ]
+ * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com)[ tg3.c]
+ * Copyright 1996-1999 Thomas Bogendoerfer [ pcnet32.c ]
+ * Derived from the lance driver written 1993,1994,1995 by Donald Becker.
+ * Copyright 1993 United States Government as represented by the
+ * Director, National Security Agency.[ pcnet32.c ]
+ * Carsten Langgaard, carstenl@mips.com [ pcnet32.c ]
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "etherboot.h"
+#include "nic.h"
+#include "mii.h"
+#include <ipxe/pci.h>
+#include <ipxe/ethernet.h>
+#include "string.h"
+#include "stdint.h"
+#include "amd8111e.h"
+
+
+/* driver definitions */
+#define NUM_TX_SLOTS 2
+#define NUM_RX_SLOTS 4
+#define TX_SLOTS_MASK 1
+#define RX_SLOTS_MASK 3
+
+#define TX_BUF_LEN 1536
+#define RX_BUF_LEN 1536
+
+#define TX_PKT_LEN_MAX (ETH_FRAME_LEN - ETH_HLEN)
+#define RX_PKT_LEN_MIN 60
+#define RX_PKT_LEN_MAX ETH_FRAME_LEN
+
+#define TX_TIMEOUT 3000
+#define TX_PROCESS_TIME 10
+#define TX_RETRY (TX_TIMEOUT / TX_PROCESS_TIME)
+
+#define PHY_RW_RETRY 10
+
+
+struct amd8111e_tx_desc {
+ u16 buf_len;
+ u16 tx_flags;
+ u16 tag_ctrl_info;
+ u16 tag_ctrl_cmd;
+ u32 buf_phy_addr;
+ u32 reserved;
+};
+
+struct amd8111e_rx_desc {
+ u32 reserved;
+ u16 msg_len;
+ u16 tag_ctrl_info;
+ u16 buf_len;
+ u16 rx_flags;
+ u32 buf_phy_addr;
+};
+
+struct eth_frame {
+ u8 dst_addr[ETH_ALEN];
+ u8 src_addr[ETH_ALEN];
+ u16 type;
+ u8 data[ETH_FRAME_LEN - ETH_HLEN];
+} __attribute__((packed));
+
+struct amd8111e_priv {
+ struct amd8111e_tx_desc tx_ring[NUM_TX_SLOTS];
+ struct amd8111e_rx_desc rx_ring[NUM_RX_SLOTS];
+ unsigned char tx_buf[NUM_TX_SLOTS][TX_BUF_LEN];
+ unsigned char rx_buf[NUM_RX_SLOTS][RX_BUF_LEN];
+ unsigned long tx_idx, rx_idx;
+ int tx_consistent;
+
+ char opened;
+ char link;
+ char speed;
+ char duplex;
+ int ext_phy_addr;
+ u32 ext_phy_id;
+
+ struct pci_device *pdev;
+ struct nic *nic;
+ void *mmio;
+};
+
+static struct amd8111e_priv amd8111e;
+
+
+/********************************************************
+ * locale functions *
+ ********************************************************/
+static void amd8111e_init_hw_default(struct amd8111e_priv *lp);
+static int amd8111e_start(struct amd8111e_priv *lp);
+static int amd8111e_read_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 *val);
+#if 0
+static int amd8111e_write_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 val);
+#endif
+static void amd8111e_probe_ext_phy(struct amd8111e_priv *lp);
+static void amd8111e_disable_interrupt(struct amd8111e_priv *lp);
+static void amd8111e_enable_interrupt(struct amd8111e_priv *lp);
+static void amd8111e_force_interrupt(struct amd8111e_priv *lp);
+static int amd8111e_get_mac_address(struct amd8111e_priv *lp);
+static int amd8111e_init_rx_ring(struct amd8111e_priv *lp);
+static int amd8111e_init_tx_ring(struct amd8111e_priv *lp);
+static int amd8111e_wait_tx_ring(struct amd8111e_priv *lp, unsigned int index);
+static void amd8111e_wait_link(struct amd8111e_priv *lp);
+static void amd8111e_poll_link(struct amd8111e_priv *lp);
+static void amd8111e_restart(struct amd8111e_priv *lp);
+
+
+/*
+ * This function clears necessary the device registers.
+ */
+static void amd8111e_init_hw_default(struct amd8111e_priv *lp)
+{
+ unsigned int reg_val;
+ void *mmio = lp->mmio;
+
+ /* stop the chip */
+ writel(RUN, mmio + CMD0);
+
+ /* Clear RCV_RING_BASE_ADDR */
+ writel(0, mmio + RCV_RING_BASE_ADDR0);
+
+ /* Clear XMT_RING_BASE_ADDR */
+ writel(0, mmio + XMT_RING_BASE_ADDR0);
+ writel(0, mmio + XMT_RING_BASE_ADDR1);
+ writel(0, mmio + XMT_RING_BASE_ADDR2);
+ writel(0, mmio + XMT_RING_BASE_ADDR3);
+
+ /* Clear CMD0 */
+ writel(CMD0_CLEAR, mmio + CMD0);
+
+ /* Clear CMD2 */
+ writel(CMD2_CLEAR, mmio + CMD2);
+
+ /* Clear CMD7 */
+ writel(CMD7_CLEAR, mmio + CMD7);
+
+ /* Clear DLY_INT_A and DLY_INT_B */
+ writel(0x0, mmio + DLY_INT_A);
+ writel(0x0, mmio + DLY_INT_B);
+
+ /* Clear FLOW_CONTROL */
+ writel(0x0, mmio + FLOW_CONTROL);
+
+ /* Clear INT0 write 1 to clear register */
+ reg_val = readl(mmio + INT0);
+ writel(reg_val, mmio + INT0);
+
+ /* Clear STVAL */
+ writel(0x0, mmio + STVAL);
+
+ /* Clear INTEN0 */
+ writel(INTEN0_CLEAR, mmio + INTEN0);
+
+ /* Clear LADRF */
+ writel(0x0, mmio + LADRF);
+
+ /* Set SRAM_SIZE & SRAM_BOUNDARY registers */
+ writel(0x80010, mmio + SRAM_SIZE);
+
+ /* Clear RCV_RING0_LEN */
+ writel(0x0, mmio + RCV_RING_LEN0);
+
+ /* Clear XMT_RING0/1/2/3_LEN */
+ writel(0x0, mmio + XMT_RING_LEN0);
+ writel(0x0, mmio + XMT_RING_LEN1);
+ writel(0x0, mmio + XMT_RING_LEN2);
+ writel(0x0, mmio + XMT_RING_LEN3);
+
+ /* Clear XMT_RING_LIMIT */
+ writel(0x0, mmio + XMT_RING_LIMIT);
+
+ /* Clear MIB */
+ writew(MIB_CLEAR, mmio + MIB_ADDR);
+
+ /* Clear LARF */
+ writel( 0, mmio + LADRF);
+ writel( 0, mmio + LADRF + 4);
+
+ /* SRAM_SIZE register */
+ reg_val = readl(mmio + SRAM_SIZE);
+
+ /* Set default value to CTRL1 Register */
+ writel(CTRL1_DEFAULT, mmio + CTRL1);
+
+ /* To avoid PCI posting bug */
+ readl(mmio + CMD2);
+}
+
+/*
+ * This function initializes the device registers and starts the device.
+ */
+static int amd8111e_start(struct amd8111e_priv *lp)
+{
+ struct nic *nic = lp->nic;
+ void *mmio = lp->mmio;
+ int i, reg_val;
+
+ /* stop the chip */
+ writel(RUN, mmio + CMD0);
+
+ /* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */
+ writew(0x8100 | lp->ext_phy_addr, mmio + AUTOPOLL0);
+
+ /* enable the port manager and set auto negotiation always */
+ writel(VAL1 | EN_PMGR, mmio + CMD3 );
+ writel(XPHYANE | XPHYRST, mmio + CTRL2);
+
+ /* set control registers */
+ reg_val = readl(mmio + CTRL1);
+ reg_val &= ~XMTSP_MASK;
+ writel(reg_val | XMTSP_128 | CACHE_ALIGN, mmio + CTRL1);
+
+ /* initialize tx and rx ring base addresses */
+ amd8111e_init_tx_ring(lp);
+ amd8111e_init_rx_ring(lp);
+ writel(virt_to_bus(lp->tx_ring), mmio + XMT_RING_BASE_ADDR0);
+ writel(virt_to_bus(lp->rx_ring), mmio + RCV_RING_BASE_ADDR0);
+ writew(NUM_TX_SLOTS, mmio + XMT_RING_LEN0);
+ writew(NUM_RX_SLOTS, mmio + RCV_RING_LEN0);
+
+ /* set default IPG to 96 */
+ writew(DEFAULT_IPG, mmio + IPG);
+ writew(DEFAULT_IPG - IFS1_DELTA, mmio + IFS1);
+
+ /* AutoPAD transmit, Retransmit on Underflow */
+ writel(VAL0 | APAD_XMT | REX_RTRY | REX_UFLO, mmio + CMD2);
+
+ /* JUMBO disabled */
+ writel(JUMBO, mmio + CMD3);
+
+ /* Setting the MAC address to the device */
+ for(i = 0; i < ETH_ALEN; i++)
+ writeb(nic->node_addr[i], mmio + PADR + i);
+
+ /* set RUN bit to start the chip, interrupt not enabled */
+ writel(VAL2 | RDMD0 | VAL0 | RUN, mmio + CMD0);
+
+ /* To avoid PCI posting bug */
+ readl(mmio + CMD0);
+ return 0;
+}
+
+/*
+This function will read the PHY registers.
+*/
+static int amd8111e_read_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 *val)
+{
+ void *mmio = lp->mmio;
+ unsigned int reg_val;
+ unsigned int retry = PHY_RW_RETRY;
+
+ reg_val = readl(mmio + PHY_ACCESS);
+ while (reg_val & PHY_CMD_ACTIVE)
+ reg_val = readl(mmio + PHY_ACCESS);
+
+ writel(PHY_RD_CMD | ((phy_addr & 0x1f) << 21) | ((reg & 0x1f) << 16),
+ mmio + PHY_ACCESS);
+ do {
+ reg_val = readl(mmio + PHY_ACCESS);
+ udelay(30); /* It takes 30 us to read/write data */
+ } while (--retry && (reg_val & PHY_CMD_ACTIVE));
+
+ if (reg_val & PHY_RD_ERR) {
+ *val = 0;
+ return -1;
+ }
+
+ *val = reg_val & 0xffff;
+ return 0;
+}
+
+/*
+This function will write into PHY registers.
+*/
+#if 0
+static int amd8111e_write_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 val)
+{
+ void *mmio = lp->mmio;
+ unsigned int reg_val;
+ unsigned int retry = PHY_RW_RETRY;
+
+ reg_val = readl(mmio + PHY_ACCESS);
+ while (reg_val & PHY_CMD_ACTIVE)
+ reg_val = readl(mmio + PHY_ACCESS);
+
+ writel(PHY_WR_CMD | ((phy_addr & 0x1f) << 21) | ((reg & 0x1f) << 16) | val,
+ mmio + PHY_ACCESS);
+ do {
+ reg_val = readl(mmio + PHY_ACCESS);
+ udelay(30); /* It takes 30 us to read/write the data */
+ } while (--retry && (reg_val & PHY_CMD_ACTIVE));
+
+ if(reg_val & PHY_RD_ERR)
+ return -1;
+
+ return 0;
+}
+#endif
+
+static void amd8111e_probe_ext_phy(struct amd8111e_priv *lp)
+{
+ int i;
+
+ lp->ext_phy_id = 0;
+ lp->ext_phy_addr = 1;
+
+ for (i = 0x1e; i >= 0; i--) {
+ u32 id1, id2;
+
+ if (amd8111e_read_phy(lp, i, MII_PHYSID1, &id1))
+ continue;
+ if (amd8111e_read_phy(lp, i, MII_PHYSID2, &id2))
+ continue;
+ lp->ext_phy_id = (id1 << 16) | id2;
+ lp->ext_phy_addr = i;
+ break;
+ }
+
+ if (lp->ext_phy_id)
+ printf("Found MII PHY ID 0x%08x at address 0x%02x\n",
+ (unsigned int) lp->ext_phy_id, lp->ext_phy_addr);
+ else
+ printf("Couldn't detect MII PHY, assuming address 0x01\n");
+}
+
+static void amd8111e_disable_interrupt(struct amd8111e_priv *lp)
+{
+ void *mmio = lp->mmio;
+ unsigned int int0;
+
+ writel(INTREN, mmio + CMD0);
+ writel(INTEN0_CLEAR, mmio + INTEN0);
+ int0 = readl(mmio + INT0);
+ writel(int0, mmio + INT0);
+ readl(mmio + INT0);
+}
+
+static void amd8111e_enable_interrupt(struct amd8111e_priv *lp)
+{
+ void *mmio = lp->mmio;
+
+ writel(VAL3 | LCINTEN | VAL1 | TINTEN0 | VAL0 | RINTEN0, mmio + INTEN0);
+ writel(VAL0 | INTREN, mmio + CMD0);
+ readl(mmio + CMD0);
+}
+
+static void amd8111e_force_interrupt(struct amd8111e_priv *lp)
+{
+ void *mmio = lp->mmio;
+
+ writel(VAL0 | UINTCMD, mmio + CMD0);
+ readl(mmio + CMD0);
+}
+
+static int amd8111e_get_mac_address(struct amd8111e_priv *lp)
+{
+ struct nic *nic = lp->nic;
+ void *mmio = lp->mmio;
+ int i;
+
+ /* BIOS should have set mac address to PADR register,
+ * so we read PADR to get it.
+ */
+ for (i = 0; i < ETH_ALEN; i++)
+ nic->node_addr[i] = readb(mmio + PADR + i);
+
+ DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) );
+
+ return 0;
+}
+
+static int amd8111e_init_rx_ring(struct amd8111e_priv *lp)
+{
+ int i;
+
+ lp->rx_idx = 0;
+
+ /* Initilaizing receive descriptors */
+ for (i = 0; i < NUM_RX_SLOTS; i++) {
+ lp->rx_ring[i].buf_phy_addr = cpu_to_le32(virt_to_bus(lp->rx_buf[i]));
+ lp->rx_ring[i].buf_len = cpu_to_le16(RX_BUF_LEN);
+ wmb();
+ lp->rx_ring[i].rx_flags = cpu_to_le16(OWN_BIT);
+ }
+
+ return 0;
+}
+
+static int amd8111e_init_tx_ring(struct amd8111e_priv *lp)
+{
+ int i;
+
+ lp->tx_idx = 0;
+ lp->tx_consistent = 1;
+
+ /* Initializing transmit descriptors */
+ for (i = 0; i < NUM_TX_SLOTS; i++) {
+ lp->tx_ring[i].tx_flags = 0;
+ lp->tx_ring[i].buf_phy_addr = 0;
+ lp->tx_ring[i].buf_len = 0;
+ }
+
+ return 0;
+}
+
+static int amd8111e_wait_tx_ring(struct amd8111e_priv *lp, unsigned int index)
+{
+ volatile u16 status;
+ int retry = TX_RETRY;
+
+ status = le16_to_cpu(lp->tx_ring[index].tx_flags);
+ while (--retry && (status & OWN_BIT)) {
+ mdelay(TX_PROCESS_TIME);
+ status = le16_to_cpu(lp->tx_ring[index].tx_flags);
+ }
+ if (status & OWN_BIT) {
+ printf("Error: tx slot %d timeout, stat = 0x%x\n", index, status);
+ amd8111e_restart(lp);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void amd8111e_wait_link(struct amd8111e_priv *lp)
+{
+ unsigned int status;
+ u32 reg_val;
+
+ do {
+ /* read phy to update STAT0 register */
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMCR, &reg_val);
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMSR, &reg_val);
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_ADVERTISE, &reg_val);
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_LPA, &reg_val);
+ status = readl(lp->mmio + STAT0);
+ } while (!(status & AUTONEG_COMPLETE) || !(status & LINK_STATS));
+}
+
+static void amd8111e_poll_link(struct amd8111e_priv *lp)
+{
+ unsigned int status, speed;
+ u32 reg_val;
+
+ if (!lp->link) {
+ /* read phy to update STAT0 register */
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMCR, &reg_val);
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMSR, &reg_val);
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_ADVERTISE, &reg_val);
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_LPA, &reg_val);
+ status = readl(lp->mmio + STAT0);
+
+ if (status & LINK_STATS) {
+ lp->link = 1;
+ speed = (status & SPEED_MASK) >> 7;
+ if (speed == PHY_SPEED_100)
+ lp->speed = 1;
+ else
+ lp->speed = 0;
+ if (status & FULL_DPLX)
+ lp->duplex = 1;
+ else
+ lp->duplex = 0;
+
+ printf("Link is up: %s Mbps %s duplex\n",
+ lp->speed ? "100" : "10", lp->duplex ? "full" : "half");
+ }
+ } else {
+ status = readl(lp->mmio + STAT0);
+ if (!(status & LINK_STATS)) {
+ lp->link = 0;
+ printf("Link is down\n");
+ }
+ }
+}
+
+static void amd8111e_restart(struct amd8111e_priv *lp)
+{
+ printf("\nStarting nic...\n");
+ amd8111e_disable_interrupt(lp);
+ amd8111e_init_hw_default(lp);
+ amd8111e_probe_ext_phy(lp);
+ amd8111e_get_mac_address(lp);
+ amd8111e_start(lp);
+
+ printf("Waiting link up...\n");
+ lp->link = 0;
+ amd8111e_wait_link(lp);
+ amd8111e_poll_link(lp);
+}
+
+
+/********************************************************
+ * Interface Functions *
+ ********************************************************/
+
+static void amd8111e_transmit(struct nic *nic, const char *dst_addr,
+ unsigned int type, unsigned int size, const char *packet)
+{
+ struct amd8111e_priv *lp = nic->priv_data;
+ struct eth_frame *frame;
+ unsigned int index;
+
+ /* check packet size */
+ if (size > TX_PKT_LEN_MAX) {
+ printf("amd8111e_transmit(): too large packet, drop\n");
+ return;
+ }
+
+ /* get tx slot */
+ index = lp->tx_idx;
+ if (amd8111e_wait_tx_ring(lp, index))
+ return;
+
+ /* fill frame */
+ frame = (struct eth_frame *)lp->tx_buf[index];
+ memset(frame->data, 0, TX_PKT_LEN_MAX);
+ memcpy(frame->dst_addr, dst_addr, ETH_ALEN);
+ memcpy(frame->src_addr, nic->node_addr, ETH_ALEN);
+ frame->type = htons(type);
+ memcpy(frame->data, packet, size);
+
+ /* start xmit */
+ lp->tx_ring[index].buf_len = cpu_to_le16(ETH_HLEN + size);
+ lp->tx_ring[index].buf_phy_addr = cpu_to_le32(virt_to_bus(frame));
+ wmb();
+ lp->tx_ring[index].tx_flags =
+ cpu_to_le16(OWN_BIT | STP_BIT | ENP_BIT | ADD_FCS_BIT | LTINT_BIT);
+ writel(VAL1 | TDMD0, lp->mmio + CMD0);
+ readl(lp->mmio + CMD0);
+
+ /* update slot pointer */
+ lp->tx_idx = (lp->tx_idx + 1) & TX_SLOTS_MASK;
+}
+
+static int amd8111e_poll(struct nic *nic, int retrieve)
+{
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+
+ struct amd8111e_priv *lp = nic->priv_data;
+ u16 status, pkt_len;
+ unsigned int index, pkt_ok;
+
+ amd8111e_poll_link(lp);
+
+ index = lp->rx_idx;
+ status = le16_to_cpu(lp->rx_ring[index].rx_flags);
+ pkt_len = le16_to_cpu(lp->rx_ring[index].msg_len) - 4; /* remove 4bytes FCS */
+
+ if (status & OWN_BIT)
+ return 0;
+
+ if (status & ERR_BIT)
+ pkt_ok = 0;
+ else if (!(status & STP_BIT))
+ pkt_ok = 0;
+ else if (!(status & ENP_BIT))
+ pkt_ok = 0;
+ else if (pkt_len < RX_PKT_LEN_MIN)
+ pkt_ok = 0;
+ else if (pkt_len > RX_PKT_LEN_MAX)
+ pkt_ok = 0;
+ else
+ pkt_ok = 1;
+
+ if (pkt_ok) {
+ if (!retrieve)
+ return 1;
+ nic->packetlen = pkt_len;
+ memcpy(nic->packet, lp->rx_buf[index], nic->packetlen);
+ }
+
+ lp->rx_ring[index].buf_phy_addr = cpu_to_le32(virt_to_bus(lp->rx_buf[index]));
+ lp->rx_ring[index].buf_len = cpu_to_le16(RX_BUF_LEN);
+ wmb();
+ lp->rx_ring[index].rx_flags = cpu_to_le16(OWN_BIT);
+ writel(VAL2 | RDMD0, lp->mmio + CMD0);
+ readl(lp->mmio + CMD0);
+
+ lp->rx_idx = (lp->rx_idx + 1) & RX_SLOTS_MASK;
+ return pkt_ok;
+}
+
+static void amd8111e_disable(struct nic *nic)
+{
+ struct amd8111e_priv *lp = nic->priv_data;
+
+ /* disable interrupt */
+ amd8111e_disable_interrupt(lp);
+
+ /* stop chip */
+ amd8111e_init_hw_default(lp);
+
+ /* unmap mmio */
+ iounmap(lp->mmio);
+
+ /* update status */
+ lp->opened = 0;
+}
+
+static void amd8111e_irq(struct nic *nic, irq_action_t action)
+{
+ struct amd8111e_priv *lp = nic->priv_data;
+
+ switch (action) {
+ case DISABLE:
+ amd8111e_disable_interrupt(lp);
+ break;
+ case ENABLE:
+ amd8111e_enable_interrupt(lp);
+ break;
+ case FORCE:
+ amd8111e_force_interrupt(lp);
+ break;
+ }
+}
+
+static struct nic_operations amd8111e_operations = {
+ .connect = dummy_connect,
+ .poll = amd8111e_poll,
+ .transmit = amd8111e_transmit,
+ .irq = amd8111e_irq,
+};
+
+static int amd8111e_probe(struct nic *nic, struct pci_device *pdev)
+{
+ struct amd8111e_priv *lp = &amd8111e;
+ unsigned long mmio_start, mmio_len;
+
+ nic->ioaddr = pdev->ioaddr;
+ nic->irqno = pdev->irq;
+
+ mmio_start = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
+ mmio_len = pci_bar_size(pdev, PCI_BASE_ADDRESS_0);
+
+ memset(lp, 0, sizeof(*lp));
+ lp->pdev = pdev;
+ lp->nic = nic;
+ lp->mmio = ioremap(mmio_start, mmio_len);
+ lp->opened = 1;
+ adjust_pci_device(pdev);
+
+ nic->priv_data = lp;
+
+ amd8111e_restart(lp);
+
+ nic->nic_op = &amd8111e_operations;
+ return 1;
+}
+
+static struct pci_device_id amd8111e_nics[] = {
+ PCI_ROM(0x1022, 0x7462, "amd8111e", "AMD8111E", 0),
+};
+
+PCI_DRIVER ( amd8111e_driver, amd8111e_nics, PCI_NO_CLASS );
+
+DRIVER ( "AMD8111E", nic_driver, pci_driver, amd8111e_driver,
+ amd8111e_probe, amd8111e_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/amd8111e.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/amd8111e.h
new file mode 100644
index 00000000..da3b1d70
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/amd8111e.h
@@ -0,0 +1,640 @@
+/*
+ * Advanced Micro Devices Inc. AMD8111E Linux Network Driver
+ * Copyright (C) 2003 Advanced Micro Devices
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+
+Module Name:
+
+ amd8111e.h
+
+Abstract:
+
+ AMD8111 based 10/100 Ethernet Controller driver definitions.
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+ 3.0.0
+ Initial Revision.
+ 3.0.1
+*/
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef _AMD811E_H
+#define _AMD811E_H
+
+/* Command style register access
+
+Registers CMD0, CMD2, CMD3,CMD7 and INTEN0 uses a write access technique called command style access. It allows the write to selected bits of this register without altering the bits that are not selected. Command style registers are divided into 4 bytes that can be written independently. Higher order bit of each byte is the value bit that specifies the value that will be written into the selected bits of register.
+
+eg., if the value 10011010b is written into the least significant byte of a command style register, bits 1,3 and 4 of the register will be set to 1, and the other bits will not be altered. If the value 00011010b is written into the same byte, bits 1,3 and 4 will be cleared to 0 and the other bits will not be altered.
+
+*/
+
+/* Offset for Memory Mapped Registers. */
+/* 32 bit registers */
+
+#define ASF_STAT 0x00 /* ASF status register */
+#define CHIPID 0x04 /* Chip ID regsiter */
+#define MIB_DATA 0x10 /* MIB data register */
+#define MIB_ADDR 0x14 /* MIB address register */
+#define STAT0 0x30 /* Status0 register */
+#define INT0 0x38 /* Interrupt0 register */
+#define INTEN0 0x40 /* Interrupt0 enable register*/
+#define CMD0 0x48 /* Command0 register */
+#define CMD2 0x50 /* Command2 register */
+#define CMD3 0x54 /* Command3 resiter */
+#define CMD7 0x64 /* Command7 register */
+
+#define CTRL1 0x6C /* Control1 register */
+#define CTRL2 0x70 /* Control2 register */
+
+#define XMT_RING_LIMIT 0x7C /* Transmit ring limit register */
+
+#define AUTOPOLL0 0x88 /* Auto-poll0 register */
+#define AUTOPOLL1 0x8A /* Auto-poll1 register */
+#define AUTOPOLL2 0x8C /* Auto-poll2 register */
+#define AUTOPOLL3 0x8E /* Auto-poll3 register */
+#define AUTOPOLL4 0x90 /* Auto-poll4 register */
+#define AUTOPOLL5 0x92 /* Auto-poll5 register */
+
+#define AP_VALUE 0x98 /* Auto-poll value register */
+#define DLY_INT_A 0xA8 /* Group A delayed interrupt register */
+#define DLY_INT_B 0xAC /* Group B delayed interrupt register */
+
+#define FLOW_CONTROL 0xC8 /* Flow control register */
+#define PHY_ACCESS 0xD0 /* PHY access register */
+
+#define STVAL 0xD8 /* Software timer value register */
+
+#define XMT_RING_BASE_ADDR0 0x100 /* Transmit ring0 base addr register */
+#define XMT_RING_BASE_ADDR1 0x108 /* Transmit ring1 base addr register */
+#define XMT_RING_BASE_ADDR2 0x110 /* Transmit ring2 base addr register */
+#define XMT_RING_BASE_ADDR3 0x118 /* Transmit ring2 base addr register */
+
+#define RCV_RING_BASE_ADDR0 0x120 /* Transmit ring0 base addr register */
+
+#define PMAT0 0x190 /* OnNow pattern register0 */
+#define PMAT1 0x194 /* OnNow pattern register1 */
+
+/* 16bit registers */
+
+#define XMT_RING_LEN0 0x140 /* Transmit Ring0 length register */
+#define XMT_RING_LEN1 0x144 /* Transmit Ring1 length register */
+#define XMT_RING_LEN2 0x148 /* Transmit Ring2 length register */
+#define XMT_RING_LEN3 0x14C /* Transmit Ring3 length register */
+
+#define RCV_RING_LEN0 0x150 /* Receive Ring0 length register */
+
+#define SRAM_SIZE 0x178 /* SRAM size register */
+#define SRAM_BOUNDARY 0x17A /* SRAM boundary register */
+
+/* 48bit register */
+
+#define PADR 0x160 /* Physical address register */
+
+#define IFS1 0x18C /* Inter-frame spacing Part1 register */
+#define IFS 0x18D /* Inter-frame spacing register */
+#define IPG 0x18E /* Inter-frame gap register */
+/* 64bit register */
+
+#define LADRF 0x168 /* Logical address filter register */
+
+
+/* Register Bit Definitions */
+typedef enum {
+
+ ASF_INIT_DONE = (1 << 1),
+ ASF_INIT_PRESENT = (1 << 0),
+
+}STAT_ASF_BITS;
+
+typedef enum {
+
+ MIB_CMD_ACTIVE = (1 << 15 ),
+ MIB_RD_CMD = (1 << 13 ),
+ MIB_CLEAR = (1 << 12 ),
+ MIB_ADDRESS = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)|
+ (1 << 4) | (1 << 5),
+}MIB_ADDR_BITS;
+
+
+typedef enum {
+
+ PMAT_DET = (1 << 12),
+ MP_DET = (1 << 11),
+ LC_DET = (1 << 10),
+ SPEED_MASK = (1 << 9)|(1 << 8)|(1 << 7),
+ FULL_DPLX = (1 << 6),
+ LINK_STATS = (1 << 5),
+ AUTONEG_COMPLETE = (1 << 4),
+ MIIPD = (1 << 3),
+ RX_SUSPENDED = (1 << 2),
+ TX_SUSPENDED = (1 << 1),
+ RUNNING = (1 << 0),
+
+}STAT0_BITS;
+
+#define PHY_SPEED_10 0x2
+#define PHY_SPEED_100 0x3
+
+/* INT0 0x38, 32bit register */
+typedef enum {
+
+ INTR = (1 << 31),
+ PCSINT = (1 << 28),
+ LCINT = (1 << 27),
+ APINT5 = (1 << 26),
+ APINT4 = (1 << 25),
+ APINT3 = (1 << 24),
+ TINT_SUM = (1 << 23),
+ APINT2 = (1 << 22),
+ APINT1 = (1 << 21),
+ APINT0 = (1 << 20),
+ MIIPDTINT = (1 << 19),
+ MCCINT = (1 << 17),
+ MREINT = (1 << 16),
+ RINT_SUM = (1 << 15),
+ SPNDINT = (1 << 14),
+ MPINT = (1 << 13),
+ SINT = (1 << 12),
+ TINT3 = (1 << 11),
+ TINT2 = (1 << 10),
+ TINT1 = (1 << 9),
+ TINT0 = (1 << 8),
+ UINT = (1 << 7),
+ STINT = (1 << 4),
+ RINT0 = (1 << 0),
+
+}INT0_BITS;
+
+typedef enum {
+
+ VAL3 = (1 << 31), /* VAL bit for byte 3 */
+ VAL2 = (1 << 23), /* VAL bit for byte 2 */
+ VAL1 = (1 << 15), /* VAL bit for byte 1 */
+ VAL0 = (1 << 7), /* VAL bit for byte 0 */
+
+}VAL_BITS;
+
+typedef enum {
+
+ /* VAL3 */
+ LCINTEN = (1 << 27),
+ APINT5EN = (1 << 26),
+ APINT4EN = (1 << 25),
+ APINT3EN = (1 << 24),
+ /* VAL2 */
+ APINT2EN = (1 << 22),
+ APINT1EN = (1 << 21),
+ APINT0EN = (1 << 20),
+ MIIPDTINTEN = (1 << 19),
+ MCCIINTEN = (1 << 18),
+ MCCINTEN = (1 << 17),
+ MREINTEN = (1 << 16),
+ /* VAL1 */
+ SPNDINTEN = (1 << 14),
+ MPINTEN = (1 << 13),
+ TINTEN3 = (1 << 11),
+ SINTEN = (1 << 12),
+ TINTEN2 = (1 << 10),
+ TINTEN1 = (1 << 9),
+ TINTEN0 = (1 << 8),
+ /* VAL0 */
+ STINTEN = (1 << 4),
+ RINTEN0 = (1 << 0),
+
+ INTEN0_CLEAR = 0x1F7F7F1F, /* Command style register */
+
+}INTEN0_BITS;
+
+typedef enum {
+ /* VAL2 */
+ RDMD0 = (1 << 16),
+ /* VAL1 */
+ TDMD3 = (1 << 11),
+ TDMD2 = (1 << 10),
+ TDMD1 = (1 << 9),
+ TDMD0 = (1 << 8),
+ /* VAL0 */
+ UINTCMD = (1 << 6),
+ RX_FAST_SPND = (1 << 5),
+ TX_FAST_SPND = (1 << 4),
+ RX_SPND = (1 << 3),
+ TX_SPND = (1 << 2),
+ INTREN = (1 << 1),
+ RUN = (1 << 0),
+
+ CMD0_CLEAR = 0x000F0F7F, /* Command style register */
+
+}CMD0_BITS;
+
+typedef enum {
+
+ /* VAL3 */
+ CONDUIT_MODE = (1 << 29),
+ /* VAL2 */
+ RPA = (1 << 19),
+ DRCVPA = (1 << 18),
+ DRCVBC = (1 << 17),
+ PROM = (1 << 16),
+ /* VAL1 */
+ ASTRP_RCV = (1 << 13),
+ RCV_DROP0 = (1 << 12),
+ EMBA = (1 << 11),
+ DXMT2PD = (1 << 10),
+ LTINTEN = (1 << 9),
+ DXMTFCS = (1 << 8),
+ /* VAL0 */
+ APAD_XMT = (1 << 6),
+ DRTY = (1 << 5),
+ INLOOP = (1 << 4),
+ EXLOOP = (1 << 3),
+ REX_RTRY = (1 << 2),
+ REX_UFLO = (1 << 1),
+ REX_LCOL = (1 << 0),
+
+ CMD2_CLEAR = 0x3F7F3F7F, /* Command style register */
+
+}CMD2_BITS;
+
+typedef enum {
+
+ /* VAL3 */
+ ASF_INIT_DONE_ALIAS = (1 << 29),
+ /* VAL2 */
+ JUMBO = (1 << 21),
+ VSIZE = (1 << 20),
+ VLONLY = (1 << 19),
+ VL_TAG_DEL = (1 << 18),
+ /* VAL1 */
+ EN_PMGR = (1 << 14),
+ INTLEVEL = (1 << 13),
+ FORCE_FULL_DUPLEX = (1 << 12),
+ FORCE_LINK_STATUS = (1 << 11),
+ APEP = (1 << 10),
+ MPPLBA = (1 << 9),
+ /* VAL0 */
+ RESET_PHY_PULSE = (1 << 2),
+ RESET_PHY = (1 << 1),
+ PHY_RST_POL = (1 << 0),
+
+}CMD3_BITS;
+
+
+typedef enum {
+
+ /* VAL0 */
+ PMAT_SAVE_MATCH = (1 << 4),
+ PMAT_MODE = (1 << 3),
+ MPEN_SW = (1 << 1),
+ LCMODE_SW = (1 << 0),
+
+ CMD7_CLEAR = 0x0000001B /* Command style register */
+
+}CMD7_BITS;
+
+
+typedef enum {
+
+ RESET_PHY_WIDTH = (0xF << 16) | (0xF<< 20), /* 0x00FF0000 */
+ XMTSP_MASK = (1 << 9) | (1 << 8), /* 9:8 */
+ XMTSP_128 = (1 << 9), /* 9 */
+ XMTSP_64 = (1 << 8),
+ CACHE_ALIGN = (1 << 4),
+ BURST_LIMIT_MASK = (0xF << 0 ),
+ CTRL1_DEFAULT = 0x00010111,
+
+}CTRL1_BITS;
+
+typedef enum {
+
+ FMDC_MASK = (1 << 9)|(1 << 8), /* 9:8 */
+ XPHYRST = (1 << 7),
+ XPHYANE = (1 << 6),
+ XPHYFD = (1 << 5),
+ XPHYSP = (1 << 4) | (1 << 3), /* 4:3 */
+ APDW_MASK = (1 << 2) | (1 << 1) | (1 << 0), /* 2:0 */
+
+}CTRL2_BITS;
+
+/* XMT_RING_LIMIT 0x7C, 32bit register */
+typedef enum {
+
+ XMT_RING2_LIMIT = (0xFF << 16), /* 23:16 */
+ XMT_RING1_LIMIT = (0xFF << 8), /* 15:8 */
+ XMT_RING0_LIMIT = (0xFF << 0), /* 7:0 */
+
+}XMT_RING_LIMIT_BITS;
+
+typedef enum {
+
+ AP_REG0_EN = (1 << 15),
+ AP_REG0_ADDR_MASK = (0xF << 8) |(1 << 12),/* 12:8 */
+ AP_PHY0_ADDR_MASK = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL0_BITS;
+
+/* AUTOPOLL1 0x8A, 16bit register */
+typedef enum {
+
+ AP_REG1_EN = (1 << 15),
+ AP_REG1_ADDR_MASK = (0xF << 8) |(1 << 12),/* 12:8 */
+ AP_PRE_SUP1 = (1 << 6),
+ AP_PHY1_DFLT = (1 << 5),
+ AP_PHY1_ADDR_MASK = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL1_BITS;
+
+
+typedef enum {
+
+ AP_REG2_EN = (1 << 15),
+ AP_REG2_ADDR_MASK = (0xF << 8) |(1 << 12),/* 12:8 */
+ AP_PRE_SUP2 = (1 << 6),
+ AP_PHY2_DFLT = (1 << 5),
+ AP_PHY2_ADDR_MASK = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL2_BITS;
+
+typedef enum {
+
+ AP_REG3_EN = (1 << 15),
+ AP_REG3_ADDR_MASK = (0xF << 8) |(1 << 12),/* 12:8 */
+ AP_PRE_SUP3 = (1 << 6),
+ AP_PHY3_DFLT = (1 << 5),
+ AP_PHY3_ADDR_MASK = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL3_BITS;
+
+
+typedef enum {
+
+ AP_REG4_EN = (1 << 15),
+ AP_REG4_ADDR_MASK = (0xF << 8) |(1 << 12),/* 12:8 */
+ AP_PRE_SUP4 = (1 << 6),
+ AP_PHY4_DFLT = (1 << 5),
+ AP_PHY4_ADDR_MASK = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL4_BITS;
+
+
+typedef enum {
+
+ AP_REG5_EN = (1 << 15),
+ AP_REG5_ADDR_MASK = (0xF << 8) |(1 << 12),/* 12:8 */
+ AP_PRE_SUP5 = (1 << 6),
+ AP_PHY5_DFLT = (1 << 5),
+ AP_PHY5_ADDR_MASK = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL5_BITS;
+
+
+
+
+/* AP_VALUE 0x98, 32bit ragister */
+typedef enum {
+
+ AP_VAL_ACTIVE = (1 << 31),
+ AP_VAL_RD_CMD = ( 1 << 29),
+ AP_ADDR = (1 << 18)|(1 << 17)|(1 << 16), /* 18:16 */
+ AP_VAL = (0xF << 0) | (0xF << 4) |( 0xF << 8) |
+ (0xF << 12), /* 15:0 */
+
+}AP_VALUE_BITS;
+
+typedef enum {
+
+ DLY_INT_A_R3 = (1 << 31),
+ DLY_INT_A_R2 = (1 << 30),
+ DLY_INT_A_R1 = (1 << 29),
+ DLY_INT_A_R0 = (1 << 28),
+ DLY_INT_A_T3 = (1 << 27),
+ DLY_INT_A_T2 = (1 << 26),
+ DLY_INT_A_T1 = (1 << 25),
+ DLY_INT_A_T0 = ( 1 << 24),
+ EVENT_COUNT_A = (0xF << 16) | (0x1 << 20),/* 20:16 */
+ MAX_DELAY_TIME_A = (0xF << 0) | (0xF << 4) | (1 << 8)|
+ (1 << 9) | (1 << 10), /* 10:0 */
+
+}DLY_INT_A_BITS;
+
+typedef enum {
+
+ DLY_INT_B_R3 = (1 << 31),
+ DLY_INT_B_R2 = (1 << 30),
+ DLY_INT_B_R1 = (1 << 29),
+ DLY_INT_B_R0 = (1 << 28),
+ DLY_INT_B_T3 = (1 << 27),
+ DLY_INT_B_T2 = (1 << 26),
+ DLY_INT_B_T1 = (1 << 25),
+ DLY_INT_B_T0 = ( 1 << 24),
+ EVENT_COUNT_B = (0xF << 16) | (0x1 << 20),/* 20:16 */
+ MAX_DELAY_TIME_B = (0xF << 0) | (0xF << 4) | (1 << 8)|
+ (1 << 9) | (1 << 10), /* 10:0 */
+}DLY_INT_B_BITS;
+
+
+/* FLOW_CONTROL 0xC8, 32bit register */
+typedef enum {
+
+ PAUSE_LEN_CHG = (1 << 30),
+ FTPE = (1 << 22),
+ FRPE = (1 << 21),
+ NAPA = (1 << 20),
+ NPA = (1 << 19),
+ FIXP = ( 1 << 18),
+ FCCMD = ( 1 << 16),
+ PAUSE_LEN = (0xF << 0) | (0xF << 4) |( 0xF << 8) | (0xF << 12), /* 15:0 */
+
+}FLOW_CONTROL_BITS;
+
+/* PHY_ ACCESS 0xD0, 32bit register */
+typedef enum {
+
+ PHY_CMD_ACTIVE = (1 << 31),
+ PHY_WR_CMD = (1 << 30),
+ PHY_RD_CMD = (1 << 29),
+ PHY_RD_ERR = (1 << 28),
+ PHY_PRE_SUP = (1 << 27),
+ PHY_ADDR = (1 << 21) | (1 << 22) | (1 << 23)|
+ (1 << 24) |(1 << 25),/* 25:21 */
+ PHY_REG_ADDR = (1 << 16) | (1 << 17) | (1 << 18)| (1 << 19) | (1 << 20),/* 20:16 */
+ PHY_DATA = (0xF << 0)|(0xF << 4) |(0xF << 8)|
+ (0xF << 12),/* 15:0 */
+
+}PHY_ACCESS_BITS;
+
+
+/* PMAT0 0x190, 32bit register */
+typedef enum {
+ PMR_ACTIVE = (1 << 31),
+ PMR_WR_CMD = (1 << 30),
+ PMR_RD_CMD = (1 << 29),
+ PMR_BANK = (1 <<28),
+ PMR_ADDR = (0xF << 16)|(1 << 20)|(1 << 21)|
+ (1 << 22),/* 22:16 */
+ PMR_B4 = (0xF << 0) | (0xF << 4),/* 15:0 */
+}PMAT0_BITS;
+
+
+/* PMAT1 0x194, 32bit register */
+typedef enum {
+ PMR_B3 = (0xF << 24) | (0xF <<28),/* 31:24 */
+ PMR_B2 = (0xF << 16) |(0xF << 20),/* 23:16 */
+ PMR_B1 = (0xF << 8) | (0xF <<12), /* 15:8 */
+ PMR_B0 = (0xF << 0)|(0xF << 4),/* 7:0 */
+}PMAT1_BITS;
+
+/************************************************************************/
+/* */
+/* MIB counter definitions */
+/* */
+/************************************************************************/
+
+#define rcv_miss_pkts 0x00
+#define rcv_octets 0x01
+#define rcv_broadcast_pkts 0x02
+#define rcv_multicast_pkts 0x03
+#define rcv_undersize_pkts 0x04
+#define rcv_oversize_pkts 0x05
+#define rcv_fragments 0x06
+#define rcv_jabbers 0x07
+#define rcv_unicast_pkts 0x08
+#define rcv_alignment_errors 0x09
+#define rcv_fcs_errors 0x0A
+#define rcv_good_octets 0x0B
+#define rcv_mac_ctrl 0x0C
+#define rcv_flow_ctrl 0x0D
+#define rcv_pkts_64_octets 0x0E
+#define rcv_pkts_65to127_octets 0x0F
+#define rcv_pkts_128to255_octets 0x10
+#define rcv_pkts_256to511_octets 0x11
+#define rcv_pkts_512to1023_octets 0x12
+#define rcv_pkts_1024to1518_octets 0x13
+#define rcv_unsupported_opcode 0x14
+#define rcv_symbol_errors 0x15
+#define rcv_drop_pkts_ring1 0x16
+#define rcv_drop_pkts_ring2 0x17
+#define rcv_drop_pkts_ring3 0x18
+#define rcv_drop_pkts_ring4 0x19
+#define rcv_jumbo_pkts 0x1A
+
+#define xmt_underrun_pkts 0x20
+#define xmt_octets 0x21
+#define xmt_packets 0x22
+#define xmt_broadcast_pkts 0x23
+#define xmt_multicast_pkts 0x24
+#define xmt_collisions 0x25
+#define xmt_unicast_pkts 0x26
+#define xmt_one_collision 0x27
+#define xmt_multiple_collision 0x28
+#define xmt_deferred_transmit 0x29
+#define xmt_late_collision 0x2A
+#define xmt_excessive_defer 0x2B
+#define xmt_loss_carrier 0x2C
+#define xmt_excessive_collision 0x2D
+#define xmt_back_pressure 0x2E
+#define xmt_flow_ctrl 0x2F
+#define xmt_pkts_64_octets 0x30
+#define xmt_pkts_65to127_octets 0x31
+#define xmt_pkts_128to255_octets 0x32
+#define xmt_pkts_256to511_octets 0x33
+#define xmt_pkts_512to1023_octets 0x34
+#define xmt_pkts_1024to1518_octet 0x35
+#define xmt_oversize_pkts 0x36
+#define xmt_jumbo_pkts 0x37
+
+/* ipg parameters */
+#define DEFAULT_IPG 0x60
+#define IFS1_DELTA 36
+#define IPG_CONVERGE_JIFFIES (HZ/2)
+#define IPG_STABLE_TIME 5
+#define MIN_IPG 96
+#define MAX_IPG 255
+#define IPG_STEP 16
+#define CSTATE 1
+#define SSTATE 2
+
+/* amd8111e decriptor flag definitions */
+typedef enum {
+
+ OWN_BIT = (1 << 15),
+ ADD_FCS_BIT = (1 << 13),
+ LTINT_BIT = (1 << 12),
+ STP_BIT = (1 << 9),
+ ENP_BIT = (1 << 8),
+ KILL_BIT = (1 << 6),
+ TCC_VLAN_INSERT = (1 << 1),
+ TCC_VLAN_REPLACE = (1 << 1) |( 1<< 0),
+
+}TX_FLAG_BITS;
+
+typedef enum {
+ ERR_BIT = (1 << 14),
+ FRAM_BIT = (1 << 13),
+ OFLO_BIT = (1 << 12),
+ CRC_BIT = (1 << 11),
+ PAM_BIT = (1 << 6),
+ LAFM_BIT = (1 << 5),
+ BAM_BIT = (1 << 4),
+ TT_VLAN_TAGGED = (1 << 3) |(1 << 2),/* 0x000 */
+ TT_PRTY_TAGGED = (1 << 3),/* 0x0008 */
+
+}RX_FLAG_BITS;
+
+#define RESET_RX_FLAGS 0x0000
+#define TT_MASK 0x000c
+#define TCC_MASK 0x0003
+
+/* driver ioctl parameters */
+#define AMD8111E_REG_DUMP_LEN 13*sizeof(u32)
+
+/* crc generator constants */
+#define CRC32 0xedb88320
+#define INITCRC 0xFFFFFFFF
+
+/* kernel provided writeq does not write 64 bits into the amd8111e device register instead writes only higher 32bits data into lower 32bits of the register.
+BUG? */
+#define amd8111e_writeq(_UlData,_memMap) \
+ writel(*(u32*)(&_UlData), _memMap); \
+ writel(*(u32*)((u8*)(&_UlData)+4), _memMap+4)
+
+/* maps the external speed options to internal value */
+typedef enum {
+ SPEED_AUTONEG,
+ SPEED10_HALF,
+ SPEED10_FULL,
+ SPEED100_HALF,
+ SPEED100_FULL,
+}EXT_PHY_OPTION;
+
+
+#endif /* _AMD8111E_H */
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath.h
new file mode 100644
index 00000000..5a19a19c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath.h
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ATH_H
+#define ATH_H
+
+#include <unistd.h>
+#include <ipxe/net80211.h>
+
+/* This block of functions are from kernel.h v3.0.1 */
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+#define BITS_PER_BYTE 8
+#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+#define BIT(nr) (1UL << (nr))
+
+#define min(x, y) ({ \
+ typeof(x) _min1 = (x); \
+ typeof(y) _min2 = (y); \
+ (void) (&_min1 == &_min2); \
+ _min1 < _min2 ? _min1 : _min2; })
+#define max(x, y) ({ \
+ typeof(x) _max1 = (x); \
+ typeof(y) _max2 = (y); \
+ (void) (&_max1 == &_max2); \
+ _max1 > _max2 ? _max1 : _max2; })
+#define abs(x) ({ \
+ long ret; \
+ if (sizeof(x) == sizeof(long)) { \
+ long __x = (x); \
+ ret = (__x < 0) ? -__x : __x; \
+ } else { \
+ int __x = (x); \
+ ret = (__x < 0) ? -__x : __x; \
+ } \
+ ret; \
+ })
+
+#define ___constant_swab16(x) ((uint16_t)( \
+ (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
+ (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
+#define ___constant_swab32(x) ((uint32_t)( \
+ (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
+ (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
+ (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
+ (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
+#define __swab16(x) ___constant_swab16(x)
+#define __swab32(x) ___constant_swab32(x)
+#define swab16 __swab16
+#define swab32 __swab32
+
+static inline int32_t sign_extend32(uint32_t value, int index)
+{
+ uint8_t shift = 31 - index;
+ return (int32_t)(value << shift) >> shift;
+}
+
+static inline u16 __get_unaligned_le16(const u8 *p)
+{
+ return p[0] | p[1] << 8;
+}
+static inline u32 __get_unaligned_le32(const u8 *p)
+{
+ return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
+}
+static inline u16 get_unaligned_le16(const void *p)
+{
+ return __get_unaligned_le16((const u8 *)p);
+}
+static inline u32 get_unaligned_le32(const void *p)
+{
+ return __get_unaligned_le32((const u8 *)p);
+}
+/* End Kernel Block */
+
+/*
+ * The key cache is used for h/w cipher state and also for
+ * tracking station state such as the current tx antenna.
+ * We also setup a mapping table between key cache slot indices
+ * and station state to short-circuit node lookups on rx.
+ * Different parts have different size key caches. We handle
+ * up to ATH_KEYMAX entries (could dynamically allocate state).
+ */
+#define ATH_KEYMAX 128 /* max key cache size we handle */
+
+static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+struct ath_ani {
+ int caldone;
+ unsigned int longcal_timer;
+ unsigned int shortcal_timer;
+ unsigned int resetcal_timer;
+ unsigned int checkani_timer;
+ int timer;
+};
+
+struct ath_cycle_counters {
+ u32 cycles;
+ u32 rx_busy;
+ u32 rx_frame;
+ u32 tx_frame;
+};
+
+enum ath_device_state {
+ ATH_HW_UNAVAILABLE,
+ ATH_HW_INITIALIZED,
+};
+
+enum ath_bus_type {
+ ATH_PCI,
+ ATH_AHB,
+ ATH_USB,
+};
+
+struct reg_dmn_pair_mapping {
+ u16 regDmnEnum;
+ u16 reg_5ghz_ctl;
+ u16 reg_2ghz_ctl;
+};
+
+struct ath_regulatory {
+ char alpha2[2];
+ u16 country_code;
+ u16 max_power_level;
+ u32 tp_scale;
+ u16 current_rd;
+ u16 current_rd_ext;
+ int16_t power_limit;
+ struct reg_dmn_pair_mapping *regpair;
+};
+
+enum ath_crypt_caps {
+ ATH_CRYPT_CAP_CIPHER_AESCCM = BIT(0),
+ ATH_CRYPT_CAP_MIC_COMBINED = BIT(1),
+};
+
+struct ath_keyval {
+ u8 kv_type;
+ u8 kv_pad;
+ u16 kv_len;
+ u8 kv_val[16]; /* TK */
+ u8 kv_mic[8]; /* Michael MIC key */
+ u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware
+ * supports both MIC keys in the same key cache entry;
+ * in that case, kv_mic is the RX key) */
+};
+
+enum ath_cipher {
+ ATH_CIPHER_WEP = 0,
+ ATH_CIPHER_AES_OCB = 1,
+ ATH_CIPHER_AES_CCM = 2,
+ ATH_CIPHER_CKIP = 3,
+ ATH_CIPHER_TKIP = 4,
+ ATH_CIPHER_CLR = 5,
+ ATH_CIPHER_MIC = 127
+};
+
+/**
+ * struct ath_ops - Register read/write operations
+ *
+ * @read: Register read
+ * @multi_read: Multiple register read
+ * @write: Register write
+ * @enable_write_buffer: Enable multiple register writes
+ * @write_flush: flush buffered register writes and disable buffering
+ */
+struct ath_ops {
+ unsigned int (*read)(void *, u32 reg_offset);
+ void (*multi_read)(void *, u32 *addr, u32 *val, u16 count);
+ void (*write)(void *, u32 val, u32 reg_offset);
+ void (*enable_write_buffer)(void *);
+ void (*write_flush) (void *);
+ u32 (*rmw)(void *, u32 reg_offset, u32 set, u32 clr);
+};
+
+struct ath_common;
+struct ath_bus_ops;
+
+struct ath_common {
+ void *ah;
+ void *priv;
+ struct net80211_device *dev;
+ int debug_mask;
+ enum ath_device_state state;
+
+ struct ath_ani ani;
+
+ u16 cachelsz;
+ u16 curaid;
+ u8 macaddr[ETH_ALEN];
+ u8 curbssid[ETH_ALEN];
+ u8 bssidmask[ETH_ALEN];
+
+ u8 tx_chainmask;
+ u8 rx_chainmask;
+
+ u32 rx_bufsize;
+
+ u32 keymax;
+ enum ath_crypt_caps crypt_caps;
+
+ unsigned int clockrate;
+
+ struct ath_cycle_counters cc_ani;
+ struct ath_cycle_counters cc_survey;
+
+ struct ath_regulatory regulatory;
+ const struct ath_ops *ops;
+ const struct ath_bus_ops *bus_ops;
+
+ int btcoex_enabled;
+};
+
+struct io_buffer *ath_rxbuf_alloc(struct ath_common *common,
+ u32 len,
+ u32 *iob_addr);
+
+void ath_hw_setbssidmask(struct ath_common *common);
+int ath_hw_keyreset(struct ath_common *common, u16 entry);
+void ath_hw_cycle_counters_update(struct ath_common *common);
+int32_t ath_hw_get_listen_time(struct ath_common *common);
+
+#endif /* ATH_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k.c
new file mode 100644
index 00000000..92c4ffdf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k.c
@@ -0,0 +1,1698 @@
+/*
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004-2005 Atheros Communications, Inc.
+ * Copyright (c) 2006 Devicescape Software, Inc.
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ *
+ * Modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>
+ * Original from Linux kernel 2.6.30.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+FILE_LICENCE ( BSD3 );
+
+#include <stdlib.h>
+#include <ipxe/malloc.h>
+#include <ipxe/timer.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/pci.h>
+#include <ipxe/pci_io.h>
+
+#include "base.h"
+#include "reg.h"
+
+#define ATH5K_CALIB_INTERVAL 10 /* Calibrate PHY every 10 seconds */
+#define ATH5K_RETRIES 4 /* Number of times to retry packet sends */
+#define ATH5K_DESC_ALIGN 16 /* Alignment for TX/RX descriptors */
+
+/******************\
+* Internal defines *
+\******************/
+
+/* Known PCI ids */
+static struct pci_device_id ath5k_nics[] = {
+ PCI_ROM(0x168c, 0x0207, "ath5210e", "Atheros 5210 early", AR5K_AR5210),
+ PCI_ROM(0x168c, 0x0007, "ath5210", "Atheros 5210", AR5K_AR5210),
+ PCI_ROM(0x168c, 0x0011, "ath5311", "Atheros 5311 (AHB)", AR5K_AR5211),
+ PCI_ROM(0x168c, 0x0012, "ath5211", "Atheros 5211", AR5K_AR5211),
+ PCI_ROM(0x168c, 0x0013, "ath5212", "Atheros 5212", AR5K_AR5212),
+ PCI_ROM(0xa727, 0x0013, "ath5212c","3com Ath 5212", AR5K_AR5212),
+ PCI_ROM(0x10b7, 0x0013, "rdag675", "3com 3CRDAG675", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x1014, "ath5212m", "Ath 5212 miniPCI", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x0014, "ath5212x14", "Atheros 5212 x14", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x0015, "ath5212x15", "Atheros 5212 x15", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x0016, "ath5212x16", "Atheros 5212 x16", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x0017, "ath5212x17", "Atheros 5212 x17", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x0018, "ath5212x18", "Atheros 5212 x18", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x0019, "ath5212x19", "Atheros 5212 x19", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x001a, "ath2413", "Atheros 2413 Griffin", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x001b, "ath5413", "Atheros 5413 Eagle", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x001c, "ath5212e", "Atheros 5212 PCI-E", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x001d, "ath2417", "Atheros 2417 Nala", AR5K_AR5212),
+};
+
+/* Known SREVs */
+static const struct ath5k_srev_name srev_names[] = {
+ { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 },
+ { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 },
+ { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A },
+ { "5311B", AR5K_VERSION_MAC, AR5K_SREV_AR5311B },
+ { "5211", AR5K_VERSION_MAC, AR5K_SREV_AR5211 },
+ { "5212", AR5K_VERSION_MAC, AR5K_SREV_AR5212 },
+ { "5213", AR5K_VERSION_MAC, AR5K_SREV_AR5213 },
+ { "5213A", AR5K_VERSION_MAC, AR5K_SREV_AR5213A },
+ { "2413", AR5K_VERSION_MAC, AR5K_SREV_AR2413 },
+ { "2414", AR5K_VERSION_MAC, AR5K_SREV_AR2414 },
+ { "5424", AR5K_VERSION_MAC, AR5K_SREV_AR5424 },
+ { "5413", AR5K_VERSION_MAC, AR5K_SREV_AR5413 },
+ { "5414", AR5K_VERSION_MAC, AR5K_SREV_AR5414 },
+ { "2415", AR5K_VERSION_MAC, AR5K_SREV_AR2415 },
+ { "5416", AR5K_VERSION_MAC, AR5K_SREV_AR5416 },
+ { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 },
+ { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 },
+ { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 },
+ { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN },
+ { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
+ { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
+ { "5111A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111A },
+ { "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 },
+ { "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 },
+ { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A },
+ { "5112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112B },
+ { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 },
+ { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A },
+ { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B },
+ { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 },
+ { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 },
+ { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 },
+ { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 },
+ { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 },
+ { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
+ { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN },
+};
+
+#define ATH5K_SPMBL_NO 1
+#define ATH5K_SPMBL_YES 2
+#define ATH5K_SPMBL_BOTH 3
+
+static const struct {
+ u16 bitrate;
+ u8 short_pmbl;
+ u8 hw_code;
+} ath5k_rates[] = {
+ { 10, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_1M },
+ { 20, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_2M },
+ { 55, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_5_5M },
+ { 110, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_11M },
+ { 60, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_6M },
+ { 90, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_9M },
+ { 120, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_12M },
+ { 180, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_18M },
+ { 240, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_24M },
+ { 360, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_36M },
+ { 480, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_48M },
+ { 540, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_54M },
+ { 20, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_2M | AR5K_SET_SHORT_PREAMBLE },
+ { 55, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_5_5M | AR5K_SET_SHORT_PREAMBLE },
+ { 110, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_11M | AR5K_SET_SHORT_PREAMBLE },
+ { 0, 0, 0 },
+};
+
+#define ATH5K_NR_RATES 15
+
+/*
+ * Prototypes - PCI stack related functions
+ */
+static int ath5k_probe(struct pci_device *pdev);
+static void ath5k_remove(struct pci_device *pdev);
+
+struct pci_driver ath5k_pci_driver __pci_driver = {
+ .ids = ath5k_nics,
+ .id_count = sizeof(ath5k_nics) / sizeof(ath5k_nics[0]),
+ .probe = ath5k_probe,
+ .remove = ath5k_remove,
+};
+
+
+
+/*
+ * Prototypes - MAC 802.11 stack related functions
+ */
+static int ath5k_tx(struct net80211_device *dev, struct io_buffer *skb);
+static int ath5k_reset(struct ath5k_softc *sc, struct net80211_channel *chan);
+static int ath5k_reset_wake(struct ath5k_softc *sc);
+static int ath5k_start(struct net80211_device *dev);
+static void ath5k_stop(struct net80211_device *dev);
+static int ath5k_config(struct net80211_device *dev, int changed);
+static void ath5k_poll(struct net80211_device *dev);
+static void ath5k_irq(struct net80211_device *dev, int enable);
+
+static struct net80211_device_operations ath5k_ops = {
+ .open = ath5k_start,
+ .close = ath5k_stop,
+ .transmit = ath5k_tx,
+ .poll = ath5k_poll,
+ .irq = ath5k_irq,
+ .config = ath5k_config,
+};
+
+/*
+ * Prototypes - Internal functions
+ */
+/* Attach detach */
+static int ath5k_attach(struct net80211_device *dev);
+static void ath5k_detach(struct net80211_device *dev);
+/* Channel/mode setup */
+static unsigned int ath5k_copy_channels(struct ath5k_hw *ah,
+ struct net80211_channel *channels,
+ unsigned int mode,
+ unsigned int max);
+static int ath5k_setup_bands(struct net80211_device *dev);
+static int ath5k_chan_set(struct ath5k_softc *sc,
+ struct net80211_channel *chan);
+static void ath5k_setcurmode(struct ath5k_softc *sc,
+ unsigned int mode);
+static void ath5k_mode_setup(struct ath5k_softc *sc);
+
+/* Descriptor setup */
+static int ath5k_desc_alloc(struct ath5k_softc *sc);
+static void ath5k_desc_free(struct ath5k_softc *sc);
+/* Buffers setup */
+static int ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf);
+static int ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf);
+
+static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
+ struct ath5k_buf *bf)
+{
+ if (!bf->iob)
+ return;
+
+ net80211_tx_complete(sc->dev, bf->iob, 0, ECANCELED);
+ bf->iob = NULL;
+}
+
+static inline void ath5k_rxbuf_free(struct ath5k_softc *sc __unused,
+ struct ath5k_buf *bf)
+{
+ free_iob(bf->iob);
+ bf->iob = NULL;
+}
+
+/* Queues setup */
+static int ath5k_txq_setup(struct ath5k_softc *sc,
+ int qtype, int subtype);
+static void ath5k_txq_drainq(struct ath5k_softc *sc,
+ struct ath5k_txq *txq);
+static void ath5k_txq_cleanup(struct ath5k_softc *sc);
+static void ath5k_txq_release(struct ath5k_softc *sc);
+/* Rx handling */
+static int ath5k_rx_start(struct ath5k_softc *sc);
+static void ath5k_rx_stop(struct ath5k_softc *sc);
+/* Tx handling */
+static void ath5k_tx_processq(struct ath5k_softc *sc,
+ struct ath5k_txq *txq);
+
+/* Interrupt handling */
+static int ath5k_init(struct ath5k_softc *sc);
+static int ath5k_stop_hw(struct ath5k_softc *sc);
+
+static void ath5k_calibrate(struct ath5k_softc *sc);
+
+/* Filter */
+static void ath5k_configure_filter(struct ath5k_softc *sc);
+
+/********************\
+* PCI Initialization *
+\********************/
+
+#if DBGLVL_MAX
+static const char *
+ath5k_chip_name(enum ath5k_srev_type type, u16 val)
+{
+ const char *name = "xxxxx";
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(srev_names); i++) {
+ if (srev_names[i].sr_type != type)
+ continue;
+
+ if ((val & 0xf0) == srev_names[i].sr_val)
+ name = srev_names[i].sr_name;
+
+ if ((val & 0xff) == srev_names[i].sr_val) {
+ name = srev_names[i].sr_name;
+ break;
+ }
+ }
+
+ return name;
+}
+#endif
+
+static int ath5k_probe(struct pci_device *pdev)
+{
+ void *mem;
+ struct ath5k_softc *sc;
+ struct net80211_device *dev;
+ int ret;
+ u8 csz;
+
+ adjust_pci_device(pdev);
+
+ /*
+ * Cache line size is used to size and align various
+ * structures used to communicate with the hardware.
+ */
+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
+ if (csz == 0) {
+ /*
+ * We must have this setup properly for rx buffer
+ * DMA to work so force a reasonable value here if it
+ * comes up zero.
+ */
+ csz = 16;
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
+ }
+ /*
+ * The default setting of latency timer yields poor results,
+ * set it to the value used by other systems. It may be worth
+ * tweaking this setting more.
+ */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
+
+ /*
+ * Disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state.
+ */
+ pci_write_config_byte(pdev, 0x41, 0);
+
+ mem = ioremap(pdev->membase, 0x10000);
+ if (!mem) {
+ DBG("ath5k: cannot remap PCI memory region\n");
+ ret = -EIO;
+ goto err;
+ }
+
+ /*
+ * Allocate dev (net80211 main struct)
+ * and dev->priv (driver private data)
+ */
+ dev = net80211_alloc(sizeof(*sc));
+ if (!dev) {
+ DBG("ath5k: cannot allocate 802.11 device\n");
+ ret = -ENOMEM;
+ goto err_map;
+ }
+
+ /* Initialize driver private data */
+ sc = dev->priv;
+ sc->dev = dev;
+ sc->pdev = pdev;
+
+ sc->hwinfo = zalloc(sizeof(*sc->hwinfo));
+ if (!sc->hwinfo) {
+ DBG("ath5k: cannot allocate 802.11 hardware info structure\n");
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ sc->hwinfo->flags = NET80211_HW_RX_HAS_FCS;
+ sc->hwinfo->signal_type = NET80211_SIGNAL_DB;
+ sc->hwinfo->signal_max = 40; /* 35dB should give perfect 54Mbps */
+ sc->hwinfo->channel_change_time = 5000;
+
+ /* Avoid working with the device until setup is complete */
+ sc->status |= ATH_STAT_INVALID;
+
+ sc->iobase = mem;
+ sc->cachelsz = csz * 4; /* convert to bytes */
+
+ DBG("ath5k: register base at %p (%08lx)\n", sc->iobase, pdev->membase);
+ DBG("ath5k: cache line size %d\n", sc->cachelsz);
+
+ /* Set private data */
+ pci_set_drvdata(pdev, dev);
+ dev->netdev->dev = (struct device *)pdev;
+
+ /* Initialize device */
+ ret = ath5k_hw_attach(sc, pdev->id->driver_data, &sc->ah);
+ if (ret)
+ goto err_free_hwinfo;
+
+ /* Finish private driver data initialization */
+ ret = ath5k_attach(dev);
+ if (ret)
+ goto err_ah;
+
+#if DBGLVL_MAX
+ DBG("Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
+ sc->ah->ah_mac_srev, sc->ah->ah_phy_revision);
+
+ if (!sc->ah->ah_single_chip) {
+ /* Single chip radio (!RF5111) */
+ if (sc->ah->ah_radio_5ghz_revision &&
+ !sc->ah->ah_radio_2ghz_revision) {
+ /* No 5GHz support -> report 2GHz radio */
+ if (!(sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11A)) {
+ DBG("RF%s 2GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ /* No 2GHz support (5110 and some
+ * 5Ghz only cards) -> report 5Ghz radio */
+ } else if (!(sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11B)) {
+ DBG("RF%s 5GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ /* Multiband radio */
+ } else {
+ DBG("RF%s multiband radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ }
+ }
+ /* Multi chip radio (RF5111 - RF2111) ->
+ * report both 2GHz/5GHz radios */
+ else if (sc->ah->ah_radio_5ghz_revision &&
+ sc->ah->ah_radio_2ghz_revision) {
+ DBG("RF%s 5GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ DBG("RF%s 2GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_2ghz_revision),
+ sc->ah->ah_radio_2ghz_revision);
+ }
+ }
+#endif
+
+ /* Ready to go */
+ sc->status &= ~ATH_STAT_INVALID;
+
+ return 0;
+err_ah:
+ ath5k_hw_detach(sc->ah);
+err_free_hwinfo:
+ free(sc->hwinfo);
+err_free:
+ net80211_free(dev);
+err_map:
+ iounmap(mem);
+err:
+ return ret;
+}
+
+static void ath5k_remove(struct pci_device *pdev)
+{
+ struct net80211_device *dev = pci_get_drvdata(pdev);
+ struct ath5k_softc *sc = dev->priv;
+
+ ath5k_detach(dev);
+ ath5k_hw_detach(sc->ah);
+ iounmap(sc->iobase);
+ free(sc->hwinfo);
+ net80211_free(dev);
+}
+
+
+/***********************\
+* Driver Initialization *
+\***********************/
+
+static int
+ath5k_attach(struct net80211_device *dev)
+{
+ struct ath5k_softc *sc = dev->priv;
+ struct ath5k_hw *ah = sc->ah;
+ int ret;
+
+ /*
+ * Collect the channel list. The 802.11 layer
+ * is resposible for filtering this list based
+ * on settings like the phy mode and regulatory
+ * domain restrictions.
+ */
+ ret = ath5k_setup_bands(dev);
+ if (ret) {
+ DBG("ath5k: can't get channels\n");
+ goto err;
+ }
+
+ /* NB: setup here so ath5k_rate_update is happy */
+ if (ah->ah_modes & AR5K_MODE_BIT_11A)
+ ath5k_setcurmode(sc, AR5K_MODE_11A);
+ else
+ ath5k_setcurmode(sc, AR5K_MODE_11B);
+
+ /*
+ * Allocate tx+rx descriptors and populate the lists.
+ */
+ ret = ath5k_desc_alloc(sc);
+ if (ret) {
+ DBG("ath5k: can't allocate descriptors\n");
+ goto err;
+ }
+
+ /*
+ * Allocate hardware transmit queues. Note that hw functions
+ * handle reseting these queues at the needed time.
+ */
+ ret = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
+ if (ret) {
+ DBG("ath5k: can't setup xmit queue\n");
+ goto err_desc;
+ }
+
+ sc->last_calib_ticks = currticks();
+
+ ret = ath5k_eeprom_read_mac(ah, sc->hwinfo->hwaddr);
+ if (ret) {
+ DBG("ath5k: unable to read address from EEPROM: 0x%04x\n",
+ sc->pdev->device);
+ goto err_queues;
+ }
+
+ memset(sc->bssidmask, 0xff, ETH_ALEN);
+ ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
+
+ ret = net80211_register(sc->dev, &ath5k_ops, sc->hwinfo);
+ if (ret) {
+ DBG("ath5k: can't register ieee80211 hw\n");
+ goto err_queues;
+ }
+
+ return 0;
+err_queues:
+ ath5k_txq_release(sc);
+err_desc:
+ ath5k_desc_free(sc);
+err:
+ return ret;
+}
+
+static void
+ath5k_detach(struct net80211_device *dev)
+{
+ struct ath5k_softc *sc = dev->priv;
+
+ net80211_unregister(dev);
+ ath5k_desc_free(sc);
+ ath5k_txq_release(sc);
+}
+
+
+
+
+/********************\
+* Channel/mode setup *
+\********************/
+
+/*
+ * Convert IEEE channel number to MHz frequency.
+ */
+static inline short
+ath5k_ieee2mhz(short chan)
+{
+ if (chan < 14)
+ return 2407 + 5 * chan;
+ if (chan == 14)
+ return 2484;
+ if (chan < 27)
+ return 2212 + 20 * chan;
+ return 5000 + 5 * chan;
+}
+
+static unsigned int
+ath5k_copy_channels(struct ath5k_hw *ah,
+ struct net80211_channel *channels,
+ unsigned int mode, unsigned int max)
+{
+ unsigned int i, count, size, chfreq, freq, ch;
+
+ if (!(ah->ah_modes & (1 << mode)))
+ return 0;
+
+ switch (mode) {
+ case AR5K_MODE_11A:
+ case AR5K_MODE_11A_TURBO:
+ /* 1..220, but 2GHz frequencies are filtered by check_channel */
+ size = 220;
+ chfreq = CHANNEL_5GHZ;
+ break;
+ case AR5K_MODE_11B:
+ case AR5K_MODE_11G:
+ case AR5K_MODE_11G_TURBO:
+ size = 26;
+ chfreq = CHANNEL_2GHZ;
+ break;
+ default:
+ return 0;
+ }
+
+ for (i = 0, count = 0; i < size && max > 0; i++) {
+ ch = i + 1 ;
+ freq = ath5k_ieee2mhz(ch);
+
+ /* Check if channel is supported by the chipset */
+ if (!ath5k_channel_ok(ah, freq, chfreq))
+ continue;
+
+ /* Write channel info and increment counter */
+ channels[count].center_freq = freq;
+ channels[count].maxpower = 0; /* use regulatory */
+ channels[count].band = (chfreq == CHANNEL_2GHZ) ?
+ NET80211_BAND_2GHZ : NET80211_BAND_5GHZ;
+ switch (mode) {
+ case AR5K_MODE_11A:
+ case AR5K_MODE_11G:
+ channels[count].hw_value = chfreq | CHANNEL_OFDM;
+ break;
+ case AR5K_MODE_11A_TURBO:
+ case AR5K_MODE_11G_TURBO:
+ channels[count].hw_value = chfreq |
+ CHANNEL_OFDM | CHANNEL_TURBO;
+ break;
+ case AR5K_MODE_11B:
+ channels[count].hw_value = CHANNEL_B;
+ }
+
+ count++;
+ max--;
+ }
+
+ return count;
+}
+
+static int
+ath5k_setup_bands(struct net80211_device *dev)
+{
+ struct ath5k_softc *sc = dev->priv;
+ struct ath5k_hw *ah = sc->ah;
+ int max_c, count_c = 0;
+ int i;
+ int band;
+
+ max_c = sizeof(sc->hwinfo->channels) / sizeof(sc->hwinfo->channels[0]);
+
+ /* 2GHz band */
+ if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11G) {
+ /* G mode */
+ band = NET80211_BAND_2GHZ;
+ sc->hwinfo->bands = NET80211_BAND_BIT_2GHZ;
+ sc->hwinfo->modes = (NET80211_MODE_G | NET80211_MODE_B);
+
+ for (i = 0; i < 12; i++)
+ sc->hwinfo->rates[band][i] = ath5k_rates[i].bitrate;
+ sc->hwinfo->nr_rates[band] = 12;
+
+ sc->hwinfo->nr_channels =
+ ath5k_copy_channels(ah, sc->hwinfo->channels,
+ AR5K_MODE_11G, max_c);
+ count_c = sc->hwinfo->nr_channels;
+ max_c -= count_c;
+ } else if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11B) {
+ /* B mode */
+ band = NET80211_BAND_2GHZ;
+ sc->hwinfo->bands = NET80211_BAND_BIT_2GHZ;
+ sc->hwinfo->modes = NET80211_MODE_B;
+
+ for (i = 0; i < 4; i++)
+ sc->hwinfo->rates[band][i] = ath5k_rates[i].bitrate;
+ sc->hwinfo->nr_rates[band] = 4;
+
+ sc->hwinfo->nr_channels =
+ ath5k_copy_channels(ah, sc->hwinfo->channels,
+ AR5K_MODE_11B, max_c);
+ count_c = sc->hwinfo->nr_channels;
+ max_c -= count_c;
+ }
+
+ /* 5GHz band, A mode */
+ if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11A) {
+ band = NET80211_BAND_5GHZ;
+ sc->hwinfo->bands |= NET80211_BAND_BIT_5GHZ;
+ sc->hwinfo->modes |= NET80211_MODE_A;
+
+ for (i = 0; i < 8; i++)
+ sc->hwinfo->rates[band][i] = ath5k_rates[i+4].bitrate;
+ sc->hwinfo->nr_rates[band] = 8;
+
+ sc->hwinfo->nr_channels =
+ ath5k_copy_channels(ah, sc->hwinfo->channels,
+ AR5K_MODE_11B, max_c);
+ count_c = sc->hwinfo->nr_channels;
+ max_c -= count_c;
+ }
+
+ return 0;
+}
+
+/*
+ * Set/change channels. If the channel is really being changed,
+ * it's done by reseting the chip. To accomplish this we must
+ * first cleanup any pending DMA, then restart stuff after a la
+ * ath5k_init.
+ */
+static int
+ath5k_chan_set(struct ath5k_softc *sc, struct net80211_channel *chan)
+{
+ if (chan->center_freq != sc->curchan->center_freq ||
+ chan->hw_value != sc->curchan->hw_value) {
+ /*
+ * To switch channels clear any pending DMA operations;
+ * wait long enough for the RX fifo to drain, reset the
+ * hardware at the new frequency, and then re-enable
+ * the relevant bits of the h/w.
+ */
+ DBG2("ath5k: resetting for channel change (%d -> %d MHz)\n",
+ sc->curchan->center_freq, chan->center_freq);
+ return ath5k_reset(sc, chan);
+ }
+
+ return 0;
+}
+
+static void
+ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
+{
+ sc->curmode = mode;
+
+ if (mode == AR5K_MODE_11A) {
+ sc->curband = NET80211_BAND_5GHZ;
+ } else {
+ sc->curband = NET80211_BAND_2GHZ;
+ }
+}
+
+static void
+ath5k_mode_setup(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+ u32 rfilt;
+
+ /* configure rx filter */
+ rfilt = sc->filter_flags;
+ ath5k_hw_set_rx_filter(ah, rfilt);
+
+ if (ath5k_hw_hasbssidmask(ah))
+ ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
+
+ /* configure operational mode */
+ ath5k_hw_set_opmode(ah);
+
+ ath5k_hw_set_mcast_filter(ah, 0, 0);
+}
+
+static inline int
+ath5k_hw_rix_to_bitrate(int hw_rix)
+{
+ int i;
+
+ for (i = 0; i < ATH5K_NR_RATES; i++) {
+ if (ath5k_rates[i].hw_code == hw_rix)
+ return ath5k_rates[i].bitrate;
+ }
+
+ DBG("ath5k: invalid rix %02x\n", hw_rix);
+ return 10; /* use lowest rate */
+}
+
+int ath5k_bitrate_to_hw_rix(int bitrate)
+{
+ int i;
+
+ for (i = 0; i < ATH5K_NR_RATES; i++) {
+ if (ath5k_rates[i].bitrate == bitrate)
+ return ath5k_rates[i].hw_code;
+ }
+
+ DBG("ath5k: invalid bitrate %d\n", bitrate);
+ return ATH5K_RATE_CODE_1M; /* use lowest rate */
+}
+
+/***************\
+* Buffers setup *
+\***************/
+
+static struct io_buffer *
+ath5k_rx_iob_alloc(struct ath5k_softc *sc, u32 *iob_addr)
+{
+ struct io_buffer *iob;
+ unsigned int off;
+
+ /*
+ * Allocate buffer with headroom_needed space for the
+ * fake physical layer header at the start.
+ */
+ iob = alloc_iob(sc->rxbufsize + sc->cachelsz - 1);
+
+ if (!iob) {
+ DBG("ath5k: can't alloc iobuf of size %d\n",
+ sc->rxbufsize + sc->cachelsz - 1);
+ return NULL;
+ }
+
+ *iob_addr = virt_to_bus(iob->data);
+
+ /*
+ * Cache-line-align. This is important (for the
+ * 5210 at least) as not doing so causes bogus data
+ * in rx'd frames.
+ */
+ off = *iob_addr % sc->cachelsz;
+ if (off != 0) {
+ iob_reserve(iob, sc->cachelsz - off);
+ *iob_addr += sc->cachelsz - off;
+ }
+
+ return iob;
+}
+
+static int
+ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+{
+ struct ath5k_hw *ah = sc->ah;
+ struct io_buffer *iob = bf->iob;
+ struct ath5k_desc *ds;
+
+ if (!iob) {
+ iob = ath5k_rx_iob_alloc(sc, &bf->iobaddr);
+ if (!iob)
+ return -ENOMEM;
+ bf->iob = iob;
+ }
+
+ /*
+ * Setup descriptors. For receive we always terminate
+ * the descriptor list with a self-linked entry so we'll
+ * not get overrun under high load (as can happen with a
+ * 5212 when ANI processing enables PHY error frames).
+ *
+ * To insure the last descriptor is self-linked we create
+ * each descriptor as self-linked and add it to the end. As
+ * each additional descriptor is added the previous self-linked
+ * entry is ``fixed'' naturally. This should be safe even
+ * if DMA is happening. When processing RX interrupts we
+ * never remove/process the last, self-linked, entry on the
+ * descriptor list. This insures the hardware always has
+ * someplace to write a new frame.
+ */
+ ds = bf->desc;
+ ds->ds_link = bf->daddr; /* link to self */
+ ds->ds_data = bf->iobaddr;
+ if (ah->ah_setup_rx_desc(ah, ds,
+ iob_tailroom(iob), /* buffer size */
+ 0) != 0) {
+ DBG("ath5k: error setting up RX descriptor for %zd bytes\n", iob_tailroom(iob));
+ return -EINVAL;
+ }
+
+ if (sc->rxlink != NULL)
+ *sc->rxlink = bf->daddr;
+ sc->rxlink = &ds->ds_link;
+ return 0;
+}
+
+static int
+ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+{
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_txq *txq = &sc->txq;
+ struct ath5k_desc *ds = bf->desc;
+ struct io_buffer *iob = bf->iob;
+ unsigned int pktlen, flags;
+ int ret;
+ u16 duration = 0;
+ u16 cts_rate = 0;
+
+ flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
+ bf->iobaddr = virt_to_bus(iob->data);
+ pktlen = iob_len(iob);
+
+ /* FIXME: If we are in g mode and rate is a CCK rate
+ * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta
+ * from tx power (value is in dB units already) */
+ if (sc->dev->phy_flags & NET80211_PHY_USE_PROTECTION) {
+ struct net80211_device *dev = sc->dev;
+
+ flags |= AR5K_TXDESC_CTSENA;
+ cts_rate = sc->hw_rtscts_rate;
+ duration = net80211_cts_duration(dev, pktlen);
+ }
+ ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
+ IEEE80211_TYP_FRAME_HEADER_LEN,
+ AR5K_PKT_TYPE_NORMAL, sc->power_level * 2,
+ sc->hw_rate, ATH5K_RETRIES,
+ AR5K_TXKEYIX_INVALID, 0, flags,
+ cts_rate, duration);
+ if (ret)
+ return ret;
+
+ ds->ds_link = 0;
+ ds->ds_data = bf->iobaddr;
+
+ list_add_tail(&bf->list, &txq->q);
+ if (txq->link == NULL) /* is this first packet? */
+ ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr);
+ else /* no, so only link it */
+ *txq->link = bf->daddr;
+
+ txq->link = &ds->ds_link;
+ ath5k_hw_start_tx_dma(ah, txq->qnum);
+ mb();
+
+ return 0;
+}
+
+/*******************\
+* Descriptors setup *
+\*******************/
+
+static int
+ath5k_desc_alloc(struct ath5k_softc *sc)
+{
+ struct ath5k_desc *ds;
+ struct ath5k_buf *bf;
+ u32 da;
+ unsigned int i;
+ int ret;
+
+ /* allocate descriptors */
+ sc->desc_len = sizeof(struct ath5k_desc) * (ATH_TXBUF + ATH_RXBUF + 1);
+ sc->desc = malloc_dma(sc->desc_len, ATH5K_DESC_ALIGN);
+ if (sc->desc == NULL) {
+ DBG("ath5k: can't allocate descriptors\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ memset(sc->desc, 0, sc->desc_len);
+ sc->desc_daddr = virt_to_bus(sc->desc);
+
+ ds = sc->desc;
+ da = sc->desc_daddr;
+
+ bf = calloc(ATH_TXBUF + ATH_RXBUF + 1, sizeof(struct ath5k_buf));
+ if (bf == NULL) {
+ DBG("ath5k: can't allocate buffer pointers\n");
+ ret = -ENOMEM;
+ goto err_free;
+ }
+ sc->bufptr = bf;
+
+ INIT_LIST_HEAD(&sc->rxbuf);
+ for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
+ bf->desc = ds;
+ bf->daddr = da;
+ list_add_tail(&bf->list, &sc->rxbuf);
+ }
+
+ INIT_LIST_HEAD(&sc->txbuf);
+ sc->txbuf_len = ATH_TXBUF;
+ for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
+ bf->desc = ds;
+ bf->daddr = da;
+ list_add_tail(&bf->list, &sc->txbuf);
+ }
+
+ return 0;
+
+err_free:
+ free_dma(sc->desc, sc->desc_len);
+err:
+ sc->desc = NULL;
+ return ret;
+}
+
+static void
+ath5k_desc_free(struct ath5k_softc *sc)
+{
+ struct ath5k_buf *bf;
+
+ list_for_each_entry(bf, &sc->txbuf, list)
+ ath5k_txbuf_free(sc, bf);
+ list_for_each_entry(bf, &sc->rxbuf, list)
+ ath5k_rxbuf_free(sc, bf);
+
+ /* Free memory associated with all descriptors */
+ free_dma(sc->desc, sc->desc_len);
+
+ free(sc->bufptr);
+ sc->bufptr = NULL;
+}
+
+
+
+
+
+/**************\
+* Queues setup *
+\**************/
+
+static int
+ath5k_txq_setup(struct ath5k_softc *sc, int qtype, int subtype)
+{
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_txq *txq;
+ struct ath5k_txq_info qi = {
+ .tqi_subtype = subtype,
+ .tqi_aifs = AR5K_TXQ_USEDEFAULT,
+ .tqi_cw_min = AR5K_TXQ_USEDEFAULT,
+ .tqi_cw_max = AR5K_TXQ_USEDEFAULT
+ };
+ int qnum;
+
+ /*
+ * Enable interrupts only for EOL and DESC conditions.
+ * We mark tx descriptors to receive a DESC interrupt
+ * when a tx queue gets deep; otherwise waiting for the
+ * EOL to reap descriptors. Note that this is done to
+ * reduce interrupt load and this only defers reaping
+ * descriptors, never transmitting frames. Aside from
+ * reducing interrupts this also permits more concurrency.
+ * The only potential downside is if the tx queue backs
+ * up in which case the top half of the kernel may backup
+ * due to a lack of tx descriptors.
+ */
+ qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE |
+ AR5K_TXQ_FLAG_TXDESCINT_ENABLE;
+ qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi);
+ if (qnum < 0) {
+ DBG("ath5k: can't set up a TX queue\n");
+ return -EIO;
+ }
+
+ txq = &sc->txq;
+ if (!txq->setup) {
+ txq->qnum = qnum;
+ txq->link = NULL;
+ INIT_LIST_HEAD(&txq->q);
+ txq->setup = 1;
+ }
+ return 0;
+}
+
+static void
+ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+{
+ struct ath5k_buf *bf, *bf0;
+
+ list_for_each_entry_safe(bf, bf0, &txq->q, list) {
+ ath5k_txbuf_free(sc, bf);
+
+ list_del(&bf->list);
+ list_add_tail(&bf->list, &sc->txbuf);
+ sc->txbuf_len++;
+ }
+ txq->link = NULL;
+}
+
+/*
+ * Drain the transmit queues and reclaim resources.
+ */
+static void
+ath5k_txq_cleanup(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+
+ if (!(sc->status & ATH_STAT_INVALID)) {
+ /* don't touch the hardware if marked invalid */
+ if (sc->txq.setup) {
+ ath5k_hw_stop_tx_dma(ah, sc->txq.qnum);
+ DBG("ath5k: txq [%d] %x, link %p\n",
+ sc->txq.qnum,
+ ath5k_hw_get_txdp(ah, sc->txq.qnum),
+ sc->txq.link);
+ }
+ }
+
+ if (sc->txq.setup)
+ ath5k_txq_drainq(sc, &sc->txq);
+}
+
+static void
+ath5k_txq_release(struct ath5k_softc *sc)
+{
+ if (sc->txq.setup) {
+ ath5k_hw_release_tx_queue(sc->ah);
+ sc->txq.setup = 0;
+ }
+}
+
+
+
+
+/*************\
+* RX Handling *
+\*************/
+
+/*
+ * Enable the receive h/w following a reset.
+ */
+static int
+ath5k_rx_start(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_buf *bf;
+ int ret;
+
+ sc->rxbufsize = IEEE80211_MAX_LEN;
+ if (sc->rxbufsize % sc->cachelsz != 0)
+ sc->rxbufsize += sc->cachelsz - (sc->rxbufsize % sc->cachelsz);
+
+ sc->rxlink = NULL;
+
+ list_for_each_entry(bf, &sc->rxbuf, list) {
+ ret = ath5k_rxbuf_setup(sc, bf);
+ if (ret != 0)
+ return ret;
+ }
+
+ bf = list_entry(sc->rxbuf.next, struct ath5k_buf, list);
+
+ ath5k_hw_set_rxdp(ah, bf->daddr);
+ ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */
+ ath5k_mode_setup(sc); /* set filters, etc. */
+ ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */
+
+ return 0;
+}
+
+/*
+ * Disable the receive h/w in preparation for a reset.
+ */
+static void
+ath5k_rx_stop(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+
+ ath5k_hw_stop_rx_pcu(ah); /* disable PCU */
+ ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */
+ ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */
+
+ sc->rxlink = NULL; /* just in case */
+}
+
+static void
+ath5k_handle_rx(struct ath5k_softc *sc)
+{
+ struct ath5k_rx_status rs;
+ struct io_buffer *iob, *next_iob;
+ u32 next_iob_addr;
+ struct ath5k_buf *bf, *bf_last;
+ struct ath5k_desc *ds;
+ int ret;
+
+ memset(&rs, 0, sizeof(rs));
+
+ if (list_empty(&sc->rxbuf)) {
+ DBG("ath5k: empty rx buf pool\n");
+ return;
+ }
+
+ bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list);
+
+ do {
+ bf = list_entry(sc->rxbuf.next, struct ath5k_buf, list);
+ assert(bf->iob != NULL);
+ iob = bf->iob;
+ ds = bf->desc;
+
+ /*
+ * last buffer must not be freed to ensure proper hardware
+ * function. When the hardware finishes also a packet next to
+ * it, we are sure, it doesn't use it anymore and we can go on.
+ */
+ if (bf_last == bf)
+ bf->flags |= 1;
+ if (bf->flags) {
+ struct ath5k_buf *bf_next = list_entry(bf->list.next,
+ struct ath5k_buf, list);
+ ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc,
+ &rs);
+ if (ret)
+ break;
+ bf->flags &= ~1;
+ /* skip the overwritten one (even status is martian) */
+ goto next;
+ }
+
+ ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
+ if (ret) {
+ if (ret != -EINPROGRESS) {
+ DBG("ath5k: error in processing rx desc: %s\n",
+ strerror(ret));
+ net80211_rx_err(sc->dev, NULL, -ret);
+ } else {
+ /* normal return, reached end of
+ available descriptors */
+ }
+ return;
+ }
+
+ if (rs.rs_more) {
+ DBG("ath5k: unsupported fragmented rx\n");
+ goto next;
+ }
+
+ if (rs.rs_status) {
+ if (rs.rs_status & AR5K_RXERR_PHY) {
+ /* These are uncommon, and may indicate a real problem. */
+ net80211_rx_err(sc->dev, NULL, EIO);
+ goto next;
+ }
+ if (rs.rs_status & AR5K_RXERR_CRC) {
+ /* These occur *all the time*. */
+ goto next;
+ }
+ if (rs.rs_status & AR5K_RXERR_DECRYPT) {
+ /*
+ * Decrypt error. If the error occurred
+ * because there was no hardware key, then
+ * let the frame through so the upper layers
+ * can process it. This is necessary for 5210
+ * parts which have no way to setup a ``clear''
+ * key cache entry.
+ *
+ * XXX do key cache faulting
+ */
+ if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
+ !(rs.rs_status & AR5K_RXERR_CRC))
+ goto accept;
+ }
+
+ /* any other error, unhandled */
+ DBG("ath5k: packet rx status %x\n", rs.rs_status);
+ goto next;
+ }
+accept:
+ next_iob = ath5k_rx_iob_alloc(sc, &next_iob_addr);
+
+ /*
+ * If we can't replace bf->iob with a new iob under memory
+ * pressure, just skip this packet
+ */
+ if (!next_iob) {
+ DBG("ath5k: dropping packet under memory pressure\n");
+ goto next;
+ }
+
+ iob_put(iob, rs.rs_datalen);
+
+ /* The MAC header is padded to have 32-bit boundary if the
+ * packet payload is non-zero. However, iPXE only
+ * supports standard 802.11 packets with 24-byte
+ * header, so no padding correction should be needed.
+ */
+
+ DBG2("ath5k: rx %d bytes, signal %d\n", rs.rs_datalen,
+ rs.rs_rssi);
+
+ net80211_rx(sc->dev, iob, rs.rs_rssi,
+ ath5k_hw_rix_to_bitrate(rs.rs_rate));
+
+ bf->iob = next_iob;
+ bf->iobaddr = next_iob_addr;
+next:
+ list_del(&bf->list);
+ list_add_tail(&bf->list, &sc->rxbuf);
+ } while (ath5k_rxbuf_setup(sc, bf) == 0);
+}
+
+
+
+
+/*************\
+* TX Handling *
+\*************/
+
+static void
+ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+{
+ struct ath5k_tx_status ts;
+ struct ath5k_buf *bf, *bf0;
+ struct ath5k_desc *ds;
+ struct io_buffer *iob;
+ int ret;
+
+ memset(&ts, 0, sizeof(ts));
+
+ list_for_each_entry_safe(bf, bf0, &txq->q, list) {
+ ds = bf->desc;
+
+ ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
+ if (ret) {
+ if (ret != -EINPROGRESS) {
+ DBG("ath5k: error in processing tx desc: %s\n",
+ strerror(ret));
+ } else {
+ /* normal return, reached end of tx completions */
+ }
+ break;
+ }
+
+ iob = bf->iob;
+ bf->iob = NULL;
+
+ DBG2("ath5k: tx %zd bytes complete, %d retries\n",
+ iob_len(iob), ts.ts_retry[0]);
+
+ net80211_tx_complete(sc->dev, iob, ts.ts_retry[0],
+ ts.ts_status ? EIO : 0);
+
+ list_del(&bf->list);
+ list_add_tail(&bf->list, &sc->txbuf);
+ sc->txbuf_len++;
+ }
+
+ if (list_empty(&txq->q))
+ txq->link = NULL;
+}
+
+static void
+ath5k_handle_tx(struct ath5k_softc *sc)
+{
+ ath5k_tx_processq(sc, &sc->txq);
+}
+
+
+/********************\
+* Interrupt handling *
+\********************/
+
+static void
+ath5k_irq(struct net80211_device *dev, int enable)
+{
+ struct ath5k_softc *sc = dev->priv;
+ struct ath5k_hw *ah = sc->ah;
+
+ sc->irq_ena = enable;
+ ah->ah_ier = enable ? AR5K_IER_ENABLE : AR5K_IER_DISABLE;
+
+ ath5k_hw_reg_write(ah, ah->ah_ier, AR5K_IER);
+ ath5k_hw_set_imr(ah, sc->imask);
+}
+
+static int
+ath5k_init(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+ int ret, i;
+
+ /*
+ * Stop anything previously setup. This is safe
+ * no matter this is the first time through or not.
+ */
+ ath5k_stop_hw(sc);
+
+ /*
+ * The basic interface to setting the hardware in a good
+ * state is ``reset''. On return the hardware is known to
+ * be powered up and with interrupts disabled. This must
+ * be followed by initialization of the appropriate bits
+ * and then setup of the interrupt mask.
+ */
+ sc->curchan = sc->dev->channels + sc->dev->channel;
+ sc->curband = sc->curchan->band;
+ sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
+ AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
+ AR5K_INT_FATAL | AR5K_INT_GLOBAL;
+ ret = ath5k_reset(sc, NULL);
+ if (ret)
+ goto done;
+
+ ath5k_rfkill_hw_start(ah);
+
+ /*
+ * Reset the key cache since some parts do not reset the
+ * contents on initial power up or resume from suspend.
+ */
+ for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
+ ath5k_hw_reset_key(ah, i);
+
+ /* Set ack to be sent at low bit-rates */
+ ath5k_hw_set_ack_bitrate_high(ah, 0);
+
+ ret = 0;
+done:
+ mb();
+ return ret;
+}
+
+static int
+ath5k_stop_hw(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+
+ /*
+ * Shutdown the hardware and driver:
+ * stop output from above
+ * disable interrupts
+ * turn off timers
+ * turn off the radio
+ * clear transmit machinery
+ * clear receive machinery
+ * drain and release tx queues
+ * reclaim beacon resources
+ * power down hardware
+ *
+ * Note that some of this work is not possible if the
+ * hardware is gone (invalid).
+ */
+
+ if (!(sc->status & ATH_STAT_INVALID)) {
+ ath5k_hw_set_imr(ah, 0);
+ }
+ ath5k_txq_cleanup(sc);
+ if (!(sc->status & ATH_STAT_INVALID)) {
+ ath5k_rx_stop(sc);
+ ath5k_hw_phy_disable(ah);
+ } else
+ sc->rxlink = NULL;
+
+ ath5k_rfkill_hw_stop(sc->ah);
+
+ return 0;
+}
+
+static void
+ath5k_poll(struct net80211_device *dev)
+{
+ struct ath5k_softc *sc = dev->priv;
+ struct ath5k_hw *ah = sc->ah;
+ enum ath5k_int status;
+ unsigned int counter = 1000;
+
+ if (currticks() - sc->last_calib_ticks >
+ ATH5K_CALIB_INTERVAL * ticks_per_sec()) {
+ ath5k_calibrate(sc);
+ sc->last_calib_ticks = currticks();
+ }
+
+ if ((sc->status & ATH_STAT_INVALID) ||
+ (sc->irq_ena && !ath5k_hw_is_intr_pending(ah)))
+ return;
+
+ do {
+ ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */
+ DBGP("ath5k: status %#x/%#x\n", status, sc->imask);
+ if (status & AR5K_INT_FATAL) {
+ /*
+ * Fatal errors are unrecoverable.
+ * Typically these are caused by DMA errors.
+ */
+ DBG("ath5k: fatal error, resetting\n");
+ ath5k_reset_wake(sc);
+ } else if (status & AR5K_INT_RXORN) {
+ DBG("ath5k: rx overrun, resetting\n");
+ ath5k_reset_wake(sc);
+ } else {
+ if (status & AR5K_INT_RXEOL) {
+ /*
+ * NB: the hardware should re-read the link when
+ * RXE bit is written, but it doesn't work at
+ * least on older hardware revs.
+ */
+ DBG("ath5k: rx EOL\n");
+ sc->rxlink = NULL;
+ }
+ if (status & AR5K_INT_TXURN) {
+ /* bump tx trigger level */
+ DBG("ath5k: tx underrun\n");
+ ath5k_hw_update_tx_triglevel(ah, 1);
+ }
+ if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
+ ath5k_handle_rx(sc);
+ if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
+ | AR5K_INT_TXERR | AR5K_INT_TXEOL))
+ ath5k_handle_tx(sc);
+ }
+ } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0);
+
+ if (!counter)
+ DBG("ath5k: too many interrupts, giving up for now\n");
+}
+
+/*
+ * Periodically recalibrate the PHY to account
+ * for temperature/environment changes.
+ */
+static void
+ath5k_calibrate(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+
+ if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) {
+ /*
+ * Rfgain is out of bounds, reset the chip
+ * to load new gain values.
+ */
+ DBG("ath5k: resetting for calibration\n");
+ ath5k_reset_wake(sc);
+ }
+ if (ath5k_hw_phy_calibrate(ah, sc->curchan))
+ DBG("ath5k: calibration of channel %d failed\n",
+ sc->curchan->channel_nr);
+}
+
+
+/********************\
+* Net80211 functions *
+\********************/
+
+static int
+ath5k_tx(struct net80211_device *dev, struct io_buffer *iob)
+{
+ struct ath5k_softc *sc = dev->priv;
+ struct ath5k_buf *bf;
+ int rc;
+
+ /*
+ * The hardware expects the header padded to 4 byte boundaries.
+ * iPXE only ever sends 24-byte headers, so no action necessary.
+ */
+
+ if (list_empty(&sc->txbuf)) {
+ DBG("ath5k: dropping packet because no tx bufs available\n");
+ return -ENOBUFS;
+ }
+
+ bf = list_entry(sc->txbuf.next, struct ath5k_buf, list);
+ list_del(&bf->list);
+ sc->txbuf_len--;
+
+ bf->iob = iob;
+
+ if ((rc = ath5k_txbuf_setup(sc, bf)) != 0) {
+ bf->iob = NULL;
+ list_add_tail(&bf->list, &sc->txbuf);
+ sc->txbuf_len++;
+ return rc;
+ }
+ return 0;
+}
+
+/*
+ * Reset the hardware. If chan is not NULL, then also pause rx/tx
+ * and change to the given channel.
+ */
+static int
+ath5k_reset(struct ath5k_softc *sc, struct net80211_channel *chan)
+{
+ struct ath5k_hw *ah = sc->ah;
+ int ret;
+
+ if (chan) {
+ ath5k_hw_set_imr(ah, 0);
+ ath5k_txq_cleanup(sc);
+ ath5k_rx_stop(sc);
+
+ sc->curchan = chan;
+ sc->curband = chan->band;
+ }
+
+ ret = ath5k_hw_reset(ah, sc->curchan, 1);
+ if (ret) {
+ DBG("ath5k: can't reset hardware: %s\n", strerror(ret));
+ return ret;
+ }
+
+ ret = ath5k_rx_start(sc);
+ if (ret) {
+ DBG("ath5k: can't start rx logic: %s\n", strerror(ret));
+ return ret;
+ }
+
+ /*
+ * Change channels and update the h/w rate map if we're switching;
+ * e.g. 11a to 11b/g.
+ *
+ * We may be doing a reset in response to an ioctl that changes the
+ * channel so update any state that might change as a result.
+ *
+ * XXX needed?
+ */
+/* ath5k_chan_change(sc, c); */
+
+ /* Reenable interrupts if necessary */
+ ath5k_irq(sc->dev, sc->irq_ena);
+
+ return 0;
+}
+
+static int ath5k_reset_wake(struct ath5k_softc *sc)
+{
+ return ath5k_reset(sc, sc->curchan);
+}
+
+static int ath5k_start(struct net80211_device *dev)
+{
+ struct ath5k_softc *sc = dev->priv;
+ int ret;
+
+ if ((ret = ath5k_init(sc)) != 0)
+ return ret;
+
+ sc->assoc = 0;
+ ath5k_configure_filter(sc);
+ ath5k_hw_set_lladdr(sc->ah, dev->netdev->ll_addr);
+
+ return 0;
+}
+
+static void ath5k_stop(struct net80211_device *dev)
+{
+ struct ath5k_softc *sc = dev->priv;
+ u8 mac[ETH_ALEN] = {};
+
+ ath5k_hw_set_lladdr(sc->ah, mac);
+
+ ath5k_stop_hw(sc);
+}
+
+static int
+ath5k_config(struct net80211_device *dev, int changed)
+{
+ struct ath5k_softc *sc = dev->priv;
+ struct ath5k_hw *ah = sc->ah;
+ struct net80211_channel *chan = &dev->channels[dev->channel];
+ int ret;
+
+ if (changed & NET80211_CFG_CHANNEL) {
+ sc->power_level = chan->maxpower;
+ if ((ret = ath5k_chan_set(sc, chan)) != 0)
+ return ret;
+ }
+
+ if ((changed & NET80211_CFG_RATE) ||
+ (changed & NET80211_CFG_PHY_PARAMS)) {
+ int spmbl = ATH5K_SPMBL_NO;
+ u16 rate = dev->rates[dev->rate];
+ u16 slowrate = dev->rates[dev->rtscts_rate];
+ int i;
+
+ if (dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE)
+ spmbl = ATH5K_SPMBL_YES;
+
+ for (i = 0; i < ATH5K_NR_RATES; i++) {
+ if (ath5k_rates[i].bitrate == rate &&
+ (ath5k_rates[i].short_pmbl & spmbl))
+ sc->hw_rate = ath5k_rates[i].hw_code;
+
+ if (ath5k_rates[i].bitrate == slowrate &&
+ (ath5k_rates[i].short_pmbl & spmbl))
+ sc->hw_rtscts_rate = ath5k_rates[i].hw_code;
+ }
+ }
+
+ if (changed & NET80211_CFG_ASSOC) {
+ sc->assoc = !!(dev->state & NET80211_ASSOCIATED);
+ if (sc->assoc) {
+ memcpy(ah->ah_bssid, dev->bssid, ETH_ALEN);
+ } else {
+ memset(ah->ah_bssid, 0xff, ETH_ALEN);
+ }
+ ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+ }
+
+ return 0;
+}
+
+/*
+ * o always accept unicast, broadcast, and multicast traffic
+ * o multicast traffic for all BSSIDs will be enabled if mac80211
+ * says it should be
+ * o maintain current state of phy ofdm or phy cck error reception.
+ * If the hardware detects any of these type of errors then
+ * ath5k_hw_get_rx_filter() will pass to us the respective
+ * hardware filters to be able to receive these type of frames.
+ * o probe request frames are accepted only when operating in
+ * hostap, adhoc, or monitor modes
+ * o enable promiscuous mode according to the interface state
+ * o accept beacons:
+ * - when operating in adhoc mode so the 802.11 layer creates
+ * node table entries for peers,
+ * - when operating in station mode for collecting rssi data when
+ * the station is otherwise quiet, or
+ * - when scanning
+ */
+static void ath5k_configure_filter(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+ u32 mfilt[2], rfilt;
+
+ /* Enable all multicast */
+ mfilt[0] = ~0;
+ mfilt[1] = ~0;
+
+ /* Enable data frames and beacons */
+ rfilt = (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
+ AR5K_RX_FILTER_MCAST | AR5K_RX_FILTER_BEACON);
+
+ /* Set filters */
+ ath5k_hw_set_rx_filter(ah, rfilt);
+
+ /* Set multicast bits */
+ ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
+
+ /* Set the cached hw filter flags, this will alter actually
+ * be set in HW */
+ sc->filter_flags = rfilt;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k.h
new file mode 100644
index 00000000..30e2024c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k.h
@@ -0,0 +1,1279 @@
+/*
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>
+ * Original from Linux kernel 2.6.30.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _ATH5K_H
+#define _ATH5K_H
+
+FILE_LICENCE ( MIT );
+
+#include <stddef.h>
+#include <byteswap.h>
+#include <ipxe/io.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/net80211.h>
+#include <errno.h>
+
+/* Keep all ath5k files under one errfile ID */
+#undef ERRFILE
+#define ERRFILE ERRFILE_ath5k
+
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
+
+/* RX/TX descriptor hw structs */
+#include "desc.h"
+
+/* EEPROM structs/offsets */
+#include "eeprom.h"
+
+/* PCI IDs */
+#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
+#define PCI_DEVICE_ID_ATHEROS_AR5311 0x0011 /* AR5311 */
+#define PCI_DEVICE_ID_ATHEROS_AR5211 0x0012 /* AR5211 */
+#define PCI_DEVICE_ID_ATHEROS_AR5212 0x0013 /* AR5212 */
+#define PCI_DEVICE_ID_3COM_3CRDAG675 0x0013 /* 3CRDAG675 (Atheros AR5212) */
+#define PCI_DEVICE_ID_3COM_2_3CRPAG175 0x0013 /* 3CRPAG175 (Atheros AR5212) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 0x0207 /* AR5210 (Early) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_IBM 0x1014 /* AR5212 (IBM MiniPCI) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 0x1107 /* AR5210 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 0x1113 /* AR5212 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 0x1112 /* AR5211 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 0xf013 /* AR5212 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 0xff12 /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 0xf11b /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 0x0058 /* AR5312 WMAC (AP43-030) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 0x0014 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 0x0015 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 0x0016 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 0x0017 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 0x0018 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 0x0019 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR2413 0x001a /* AR2413 (Griffin-lite) */
+#define PCI_DEVICE_ID_ATHEROS_AR5413 0x001b /* AR5413 (Eagle) */
+#define PCI_DEVICE_ID_ATHEROS_AR5424 0x001c /* AR5424 (Condor PCI-E) */
+#define PCI_DEVICE_ID_ATHEROS_AR5416 0x0023 /* AR5416 */
+#define PCI_DEVICE_ID_ATHEROS_AR5418 0x0024 /* AR5418 */
+
+/****************************\
+ GENERIC DRIVER DEFINITIONS
+\****************************/
+
+/*
+ * AR5K REGISTER ACCESS
+ */
+
+/* Some macros to read/write fields */
+
+/* First shift, then mask */
+#define AR5K_REG_SM(_val, _flags) \
+ (((_val) << _flags##_S) & (_flags))
+
+/* First mask, then shift */
+#define AR5K_REG_MS(_val, _flags) \
+ (((_val) & (_flags)) >> _flags##_S)
+
+/* Some registers can hold multiple values of interest. For this
+ * reason when we want to write to these registers we must first
+ * retrieve the values which we do not want to clear (lets call this
+ * old_data) and then set the register with this and our new_value:
+ * ( old_data | new_value) */
+#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val) \
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \
+ (((_val) << _flags##_S) & (_flags)), _reg)
+
+#define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask) \
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & \
+ (_mask)) | (_flags), _reg)
+
+#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags) \
+ ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg)
+
+#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \
+ ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg)
+
+/* Access to PHY registers */
+#define AR5K_PHY_READ(ah, _reg) \
+ ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2))
+
+#define AR5K_PHY_WRITE(ah, _reg, _val) \
+ ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2))
+
+/* Access QCU registers per queue */
+#define AR5K_REG_READ_Q(ah, _reg, _queue) \
+ (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \
+
+#define AR5K_REG_WRITE_Q(ah, _reg, _queue) \
+ ath5k_hw_reg_write(ah, (1 << _queue), _reg)
+
+#define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \
+ _reg |= 1 << _queue; \
+} while (0)
+
+#define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \
+ _reg &= ~(1 << _queue); \
+} while (0)
+
+/* Used while writing initvals */
+#define AR5K_REG_WAIT(_i) do { \
+ if (_i % 64) \
+ udelay(1); \
+} while (0)
+
+/* Register dumps are done per operation mode */
+#define AR5K_INI_RFGAIN_5GHZ 0
+#define AR5K_INI_RFGAIN_2GHZ 1
+
+/* TODO: Clean this up */
+#define AR5K_INI_VAL_11A 0
+#define AR5K_INI_VAL_11A_TURBO 1
+#define AR5K_INI_VAL_11B 2
+#define AR5K_INI_VAL_11G 3
+#define AR5K_INI_VAL_11G_TURBO 4
+#define AR5K_INI_VAL_XR 0
+#define AR5K_INI_VAL_MAX 5
+
+/* Used for BSSID etc manipulation */
+#define AR5K_LOW_ID(_a)( \
+(_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \
+)
+
+#define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8)
+
+#define IEEE80211_MAX_LEN 2352
+
+/*
+ * Some tuneable values (these should be changeable by the user)
+ */
+#define AR5K_TUNE_DMA_BEACON_RESP 2
+#define AR5K_TUNE_SW_BEACON_RESP 10
+#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0
+#define AR5K_TUNE_RADAR_ALERT 0
+#define AR5K_TUNE_MIN_TX_FIFO_THRES 1
+#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1)
+#define AR5K_TUNE_REGISTER_TIMEOUT 20000
+/* Register for RSSI threshold has a mask of 0xff, so 255 seems to
+ * be the max value. */
+#define AR5K_TUNE_RSSI_THRES 129
+/* This must be set when setting the RSSI threshold otherwise it can
+ * prevent a reset. If AR5K_RSSI_THR is read after writing to it
+ * the BMISS_THRES will be seen as 0, seems harware doesn't keep
+ * track of it. Max value depends on harware. For AR5210 this is just 7.
+ * For AR5211+ this seems to be up to 255. */
+#define AR5K_TUNE_BMISS_THRES 7
+#define AR5K_TUNE_REGISTER_DWELL_TIME 20000
+#define AR5K_TUNE_BEACON_INTERVAL 100
+#define AR5K_TUNE_AIFS 2
+#define AR5K_TUNE_AIFS_11B 2
+#define AR5K_TUNE_AIFS_XR 0
+#define AR5K_TUNE_CWMIN 15
+#define AR5K_TUNE_CWMIN_11B 31
+#define AR5K_TUNE_CWMIN_XR 3
+#define AR5K_TUNE_CWMAX 1023
+#define AR5K_TUNE_CWMAX_11B 1023
+#define AR5K_TUNE_CWMAX_XR 7
+#define AR5K_TUNE_NOISE_FLOOR -72
+#define AR5K_TUNE_MAX_TXPOWER 63
+#define AR5K_TUNE_DEFAULT_TXPOWER 25
+#define AR5K_TUNE_TPC_TXPOWER 0
+#define AR5K_TUNE_ANT_DIVERSITY 1
+#define AR5K_TUNE_HWTXTRIES 4
+
+#define AR5K_INIT_CARR_SENSE_EN 1
+
+/*Swap RX/TX Descriptor for big endian archs*/
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define AR5K_INIT_CFG ( \
+ AR5K_CFG_SWTD | AR5K_CFG_SWRD \
+)
+#else
+#define AR5K_INIT_CFG 0x00000000
+#endif
+
+/* Initial values */
+#define AR5K_INIT_CYCRSSI_THR1 2
+#define AR5K_INIT_TX_LATENCY 502
+#define AR5K_INIT_USEC 39
+#define AR5K_INIT_USEC_TURBO 79
+#define AR5K_INIT_USEC_32 31
+#define AR5K_INIT_SLOT_TIME 396
+#define AR5K_INIT_SLOT_TIME_TURBO 480
+#define AR5K_INIT_ACK_CTS_TIMEOUT 1024
+#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800
+#define AR5K_INIT_PROG_IFS 920
+#define AR5K_INIT_PROG_IFS_TURBO 960
+#define AR5K_INIT_EIFS 3440
+#define AR5K_INIT_EIFS_TURBO 6880
+#define AR5K_INIT_SIFS 560
+#define AR5K_INIT_SIFS_TURBO 480
+#define AR5K_INIT_SH_RETRY 10
+#define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY
+#define AR5K_INIT_SSH_RETRY 32
+#define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY
+#define AR5K_INIT_TX_RETRY 10
+
+#define AR5K_INIT_TRANSMIT_LATENCY ( \
+ (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
+ (AR5K_INIT_USEC) \
+)
+#define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \
+ (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
+ (AR5K_INIT_USEC_TURBO) \
+)
+#define AR5K_INIT_PROTO_TIME_CNTRL ( \
+ (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \
+ (AR5K_INIT_PROG_IFS) \
+)
+#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \
+ (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \
+ (AR5K_INIT_PROG_IFS_TURBO) \
+)
+
+/* token to use for aifs, cwmin, cwmax in MadWiFi */
+#define AR5K_TXQ_USEDEFAULT ((u32) -1)
+
+/* GENERIC CHIPSET DEFINITIONS */
+
+/* MAC Chips */
+enum ath5k_version {
+ AR5K_AR5210 = 0,
+ AR5K_AR5211 = 1,
+ AR5K_AR5212 = 2,
+};
+
+/* PHY Chips */
+enum ath5k_radio {
+ AR5K_RF5110 = 0,
+ AR5K_RF5111 = 1,
+ AR5K_RF5112 = 2,
+ AR5K_RF2413 = 3,
+ AR5K_RF5413 = 4,
+ AR5K_RF2316 = 5,
+ AR5K_RF2317 = 6,
+ AR5K_RF2425 = 7,
+};
+
+/*
+ * Common silicon revision/version values
+ */
+
+enum ath5k_srev_type {
+ AR5K_VERSION_MAC,
+ AR5K_VERSION_RAD,
+};
+
+struct ath5k_srev_name {
+ const char *sr_name;
+ enum ath5k_srev_type sr_type;
+ unsigned sr_val;
+};
+
+#define AR5K_SREV_UNKNOWN 0xffff
+
+#define AR5K_SREV_AR5210 0x00 /* Crete */
+#define AR5K_SREV_AR5311 0x10 /* Maui 1 */
+#define AR5K_SREV_AR5311A 0x20 /* Maui 2 */
+#define AR5K_SREV_AR5311B 0x30 /* Spirit */
+#define AR5K_SREV_AR5211 0x40 /* Oahu */
+#define AR5K_SREV_AR5212 0x50 /* Venice */
+#define AR5K_SREV_AR5213 0x55 /* ??? */
+#define AR5K_SREV_AR5213A 0x59 /* Hainan */
+#define AR5K_SREV_AR2413 0x78 /* Griffin lite */
+#define AR5K_SREV_AR2414 0x70 /* Griffin */
+#define AR5K_SREV_AR5424 0x90 /* Condor */
+#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */
+#define AR5K_SREV_AR5414 0xa0 /* Eagle */
+#define AR5K_SREV_AR2415 0xb0 /* Talon */
+#define AR5K_SREV_AR5416 0xc0 /* PCI-E */
+#define AR5K_SREV_AR5418 0xca /* PCI-E */
+#define AR5K_SREV_AR2425 0xe0 /* Swan */
+#define AR5K_SREV_AR2417 0xf0 /* Nala */
+
+#define AR5K_SREV_RAD_5110 0x00
+#define AR5K_SREV_RAD_5111 0x10
+#define AR5K_SREV_RAD_5111A 0x15
+#define AR5K_SREV_RAD_2111 0x20
+#define AR5K_SREV_RAD_5112 0x30
+#define AR5K_SREV_RAD_5112A 0x35
+#define AR5K_SREV_RAD_5112B 0x36
+#define AR5K_SREV_RAD_2112 0x40
+#define AR5K_SREV_RAD_2112A 0x45
+#define AR5K_SREV_RAD_2112B 0x46
+#define AR5K_SREV_RAD_2413 0x50
+#define AR5K_SREV_RAD_5413 0x60
+#define AR5K_SREV_RAD_2316 0x70 /* Cobra SoC */
+#define AR5K_SREV_RAD_2317 0x80
+#define AR5K_SREV_RAD_5424 0xa0 /* Mostly same as 5413 */
+#define AR5K_SREV_RAD_2425 0xa2
+#define AR5K_SREV_RAD_5133 0xc0
+
+#define AR5K_SREV_PHY_5211 0x30
+#define AR5K_SREV_PHY_5212 0x41
+#define AR5K_SREV_PHY_5212A 0x42
+#define AR5K_SREV_PHY_5212B 0x43
+#define AR5K_SREV_PHY_2413 0x45
+#define AR5K_SREV_PHY_5413 0x61
+#define AR5K_SREV_PHY_2425 0x70
+
+/*
+ * Some of this information is based on Documentation from:
+ *
+ * http://madwifi.org/wiki/ChipsetFeatures/SuperAG
+ *
+ * Modulation for Atheros' eXtended Range - range enhancing extension that is
+ * supposed to double the distance an Atheros client device can keep a
+ * connection with an Atheros access point. This is achieved by increasing
+ * the receiver sensitivity up to, -105dBm, which is about 20dB above what
+ * the 802.11 specifications demand. In addition, new (proprietary) data rates
+ * are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s.
+ *
+ * Please note that can you either use XR or TURBO but you cannot use both,
+ * they are exclusive.
+ *
+ */
+#define MODULATION_XR 0x00000200
+
+/*
+ * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a
+ * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s
+ * signaling rate achieved through the bonding of two 54Mbit/s 802.11g
+ * channels. To use this feature your Access Point must also suport it.
+ * There is also a distinction between "static" and "dynamic" turbo modes:
+ *
+ * - Static: is the dumb version: devices set to this mode stick to it until
+ * the mode is turned off.
+ * - Dynamic: is the intelligent version, the network decides itself if it
+ * is ok to use turbo. As soon as traffic is detected on adjacent channels
+ * (which would get used in turbo mode), or when a non-turbo station joins
+ * the network, turbo mode won't be used until the situation changes again.
+ * Dynamic mode is achieved by Atheros' Adaptive Radio (AR) feature which
+ * monitors the used radio band in order to decide whether turbo mode may
+ * be used or not.
+ *
+ * This article claims Super G sticks to bonding of channels 5 and 6 for
+ * USA:
+ *
+ * http://www.pcworld.com/article/id,113428-page,1/article.html
+ *
+ * The channel bonding seems to be driver specific though. In addition to
+ * deciding what channels will be used, these "Turbo" modes are accomplished
+ * by also enabling the following features:
+ *
+ * - Bursting: allows multiple frames to be sent at once, rather than pausing
+ * after each frame. Bursting is a standards-compliant feature that can be
+ * used with any Access Point.
+ * - Fast frames: increases the amount of information that can be sent per
+ * frame, also resulting in a reduction of transmission overhead. It is a
+ * proprietary feature that needs to be supported by the Access Point.
+ * - Compression: data frames are compressed in real time using a Lempel Ziv
+ * algorithm. This is done transparently. Once this feature is enabled,
+ * compression and decompression takes place inside the chipset, without
+ * putting additional load on the host CPU.
+ *
+ */
+#define MODULATION_TURBO 0x00000080
+
+enum ath5k_driver_mode {
+ AR5K_MODE_11A = 0,
+ AR5K_MODE_11A_TURBO = 1,
+ AR5K_MODE_11B = 2,
+ AR5K_MODE_11G = 3,
+ AR5K_MODE_11G_TURBO = 4,
+ AR5K_MODE_XR = 5,
+};
+
+enum {
+ AR5K_MODE_BIT_11A = (1 << AR5K_MODE_11A),
+ AR5K_MODE_BIT_11A_TURBO = (1 << AR5K_MODE_11A_TURBO),
+ AR5K_MODE_BIT_11B = (1 << AR5K_MODE_11B),
+ AR5K_MODE_BIT_11G = (1 << AR5K_MODE_11G),
+ AR5K_MODE_BIT_11G_TURBO = (1 << AR5K_MODE_11G_TURBO),
+ AR5K_MODE_BIT_XR = (1 << AR5K_MODE_XR),
+};
+
+/****************\
+ TX DEFINITIONS
+\****************/
+
+/*
+ * TX Status descriptor
+ */
+struct ath5k_tx_status {
+ u16 ts_seqnum;
+ u16 ts_tstamp;
+ u8 ts_status;
+ u8 ts_rate[4];
+ u8 ts_retry[4];
+ u8 ts_final_idx;
+ s8 ts_rssi;
+ u8 ts_shortretry;
+ u8 ts_longretry;
+ u8 ts_virtcol;
+ u8 ts_antenna;
+} __attribute__ ((packed));
+
+#define AR5K_TXSTAT_ALTRATE 0x80
+#define AR5K_TXERR_XRETRY 0x01
+#define AR5K_TXERR_FILT 0x02
+#define AR5K_TXERR_FIFO 0x04
+
+/**
+ * enum ath5k_tx_queue - Queue types used to classify tx queues.
+ * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue
+ * @AR5K_TX_QUEUE_DATA: A normal data queue
+ * @AR5K_TX_QUEUE_XR_DATA: An XR-data queue
+ * @AR5K_TX_QUEUE_BEACON: The beacon queue
+ * @AR5K_TX_QUEUE_CAB: The after-beacon queue
+ * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue
+ */
+enum ath5k_tx_queue {
+ AR5K_TX_QUEUE_INACTIVE = 0,
+ AR5K_TX_QUEUE_DATA,
+ AR5K_TX_QUEUE_XR_DATA,
+ AR5K_TX_QUEUE_BEACON,
+ AR5K_TX_QUEUE_CAB,
+ AR5K_TX_QUEUE_UAPSD,
+};
+
+/*
+ * Queue syb-types to classify normal data queues.
+ * These are the 4 Access Categories as defined in
+ * WME spec. 0 is the lowest priority and 4 is the
+ * highest. Normal data that hasn't been classified
+ * goes to the Best Effort AC.
+ */
+enum ath5k_tx_queue_subtype {
+ AR5K_WME_AC_BK = 0, /*Background traffic*/
+ AR5K_WME_AC_BE, /*Best-effort (normal) traffic)*/
+ AR5K_WME_AC_VI, /*Video traffic*/
+ AR5K_WME_AC_VO, /*Voice traffic*/
+};
+
+/*
+ * Queue ID numbers as returned by the hw functions, each number
+ * represents a hw queue. If hw does not support hw queues
+ * (eg 5210) all data goes in one queue. These match
+ * d80211 definitions (net80211/MadWiFi don't use them).
+ */
+enum ath5k_tx_queue_id {
+ AR5K_TX_QUEUE_ID_NOQCU_DATA = 0,
+ AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1,
+ AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/
+ AR5K_TX_QUEUE_ID_DATA_MAX = 4, /*IEEE80211_TX_QUEUE_DATA4*/
+ AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/
+ AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/
+ AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/
+ AR5K_TX_QUEUE_ID_UAPSD = 8,
+ AR5K_TX_QUEUE_ID_XR_DATA = 9,
+};
+
+/*
+ * Flags to set hw queue's parameters...
+ */
+#define AR5K_TXQ_FLAG_TXOKINT_ENABLE 0x0001 /* Enable TXOK interrupt */
+#define AR5K_TXQ_FLAG_TXERRINT_ENABLE 0x0002 /* Enable TXERR interrupt */
+#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE 0x0004 /* Enable TXEOL interrupt -not used- */
+#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE 0x0008 /* Enable TXDESC interrupt -not used- */
+#define AR5K_TXQ_FLAG_TXURNINT_ENABLE 0x0010 /* Enable TXURN interrupt */
+#define AR5K_TXQ_FLAG_CBRORNINT_ENABLE 0x0020 /* Enable CBRORN interrupt */
+#define AR5K_TXQ_FLAG_CBRURNINT_ENABLE 0x0040 /* Enable CBRURN interrupt */
+#define AR5K_TXQ_FLAG_QTRIGINT_ENABLE 0x0080 /* Enable QTRIG interrupt */
+#define AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE 0x0100 /* Enable TXNOFRM interrupt */
+#define AR5K_TXQ_FLAG_BACKOFF_DISABLE 0x0200 /* Disable random post-backoff */
+#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0300 /* Enable ready time expiry policy (?)*/
+#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0800 /* Enable backoff while bursting */
+#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x1000 /* Disable backoff while bursting */
+#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/
+
+/*
+ * A struct to hold tx queue's parameters
+ */
+struct ath5k_txq_info {
+ enum ath5k_tx_queue tqi_type;
+ enum ath5k_tx_queue_subtype tqi_subtype;
+ u16 tqi_flags; /* Tx queue flags (see above) */
+ u32 tqi_aifs; /* Arbitrated Interframe Space */
+ s32 tqi_cw_min; /* Minimum Contention Window */
+ s32 tqi_cw_max; /* Maximum Contention Window */
+ u32 tqi_cbr_period; /* Constant bit rate period */
+ u32 tqi_cbr_overflow_limit;
+ u32 tqi_burst_time;
+ u32 tqi_ready_time; /* Not used */
+};
+
+/*
+ * Transmit packet types.
+ * used on tx control descriptor
+ * TODO: Use them inside base.c corectly
+ */
+enum ath5k_pkt_type {
+ AR5K_PKT_TYPE_NORMAL = 0,
+ AR5K_PKT_TYPE_ATIM = 1,
+ AR5K_PKT_TYPE_PSPOLL = 2,
+ AR5K_PKT_TYPE_BEACON = 3,
+ AR5K_PKT_TYPE_PROBE_RESP = 4,
+ AR5K_PKT_TYPE_PIFS = 5,
+};
+
+/*
+ * TX power and TPC settings
+ */
+#define AR5K_TXPOWER_OFDM(_r, _v) ( \
+ ((0 & 1) << ((_v) + 6)) | \
+ (((ah->ah_txpower.txp_rates_power_table[(_r)]) & 0x3f) << (_v)) \
+)
+
+#define AR5K_TXPOWER_CCK(_r, _v) ( \
+ (ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v) \
+)
+
+/*
+ * DMA size definitions (2^n+2)
+ */
+enum ath5k_dmasize {
+ AR5K_DMASIZE_4B = 0,
+ AR5K_DMASIZE_8B,
+ AR5K_DMASIZE_16B,
+ AR5K_DMASIZE_32B,
+ AR5K_DMASIZE_64B,
+ AR5K_DMASIZE_128B,
+ AR5K_DMASIZE_256B,
+ AR5K_DMASIZE_512B
+};
+
+
+/****************\
+ RX DEFINITIONS
+\****************/
+
+/*
+ * RX Status descriptor
+ */
+struct ath5k_rx_status {
+ u16 rs_datalen;
+ u16 rs_tstamp;
+ u8 rs_status;
+ u8 rs_phyerr;
+ s8 rs_rssi;
+ u8 rs_keyix;
+ u8 rs_rate;
+ u8 rs_antenna;
+ u8 rs_more;
+};
+
+#define AR5K_RXERR_CRC 0x01
+#define AR5K_RXERR_PHY 0x02
+#define AR5K_RXERR_FIFO 0x04
+#define AR5K_RXERR_DECRYPT 0x08
+#define AR5K_RXERR_MIC 0x10
+#define AR5K_RXKEYIX_INVALID ((u8) - 1)
+#define AR5K_TXKEYIX_INVALID ((u32) - 1)
+
+
+/*
+ * TSF to TU conversion:
+ *
+ * TSF is a 64bit value in usec (microseconds).
+ * TU is a 32bit value and defined by IEEE802.11 (page 6) as "A measurement of
+ * time equal to 1024 usec", so it's roughly milliseconds (usec / 1024).
+ */
+#define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
+
+
+/*******************************\
+ GAIN OPTIMIZATION DEFINITIONS
+\*******************************/
+
+enum ath5k_rfgain {
+ AR5K_RFGAIN_INACTIVE = 0,
+ AR5K_RFGAIN_ACTIVE,
+ AR5K_RFGAIN_READ_REQUESTED,
+ AR5K_RFGAIN_NEED_CHANGE,
+};
+
+struct ath5k_gain {
+ u8 g_step_idx;
+ u8 g_current;
+ u8 g_target;
+ u8 g_low;
+ u8 g_high;
+ u8 g_f_corr;
+ u8 g_state;
+};
+
+/********************\
+ COMMON DEFINITIONS
+\********************/
+
+#define AR5K_SLOT_TIME_9 396
+#define AR5K_SLOT_TIME_20 880
+#define AR5K_SLOT_TIME_MAX 0xffff
+
+/* channel_flags */
+#define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */
+#define CHANNEL_TURBO 0x0010 /* Turbo Channel */
+#define CHANNEL_CCK 0x0020 /* CCK channel */
+#define CHANNEL_OFDM 0x0040 /* OFDM channel */
+#define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */
+#define CHANNEL_5GHZ 0x0100 /* 5GHz channel */
+#define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed */
+#define CHANNEL_DYN 0x0400 /* Dynamic CCK-OFDM channel (for g operation) */
+#define CHANNEL_XR 0x0800 /* XR channel */
+
+#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM)
+#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK)
+#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM)
+#define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
+#define CHANNEL_TG (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
+#define CHANNEL_108A CHANNEL_T
+#define CHANNEL_108G CHANNEL_TG
+#define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR)
+
+#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \
+ CHANNEL_TURBO)
+
+#define CHANNEL_ALL_NOTURBO (CHANNEL_ALL & ~CHANNEL_TURBO)
+#define CHANNEL_MODES CHANNEL_ALL
+
+/*
+ * Used internaly for reset_tx_queue).
+ * Also see struct struct net80211_channel.
+ */
+#define IS_CHAN_XR(_c) ((_c->hw_value & CHANNEL_XR) != 0)
+#define IS_CHAN_B(_c) ((_c->hw_value & CHANNEL_B) != 0)
+
+/*
+ * The following structure is used to map 2GHz channels to
+ * 5GHz Atheros channels.
+ * TODO: Clean up
+ */
+struct ath5k_athchan_2ghz {
+ u32 a2_flags;
+ u16 a2_athchan;
+};
+
+
+/******************\
+ RATE DEFINITIONS
+\******************/
+
+/**
+ * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32.
+ *
+ * The rate code is used to get the RX rate or set the TX rate on the
+ * hardware descriptors. It is also used for internal modulation control
+ * and settings.
+ *
+ * This is the hardware rate map we are aware of:
+ *
+ * rate_code 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08
+ * rate_kbps 3000 1000 ? ? ? 2000 500 48000
+ *
+ * rate_code 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10
+ * rate_kbps 24000 12000 6000 54000 36000 18000 9000 ?
+ *
+ * rate_code 17 18 19 20 21 22 23 24
+ * rate_kbps ? ? ? ? ? ? ? 11000
+ *
+ * rate_code 25 26 27 28 29 30 31 32
+ * rate_kbps 5500 2000 1000 11000S 5500S 2000S ? ?
+ *
+ * "S" indicates CCK rates with short preamble.
+ *
+ * AR5211 has different rate codes for CCK (802.11B) rates. It only uses the
+ * lowest 4 bits, so they are the same as below with a 0xF mask.
+ * (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M).
+ * We handle this in ath5k_setup_bands().
+ */
+#define AR5K_MAX_RATES 32
+
+/* B */
+#define ATH5K_RATE_CODE_1M 0x1B
+#define ATH5K_RATE_CODE_2M 0x1A
+#define ATH5K_RATE_CODE_5_5M 0x19
+#define ATH5K_RATE_CODE_11M 0x18
+/* A and G */
+#define ATH5K_RATE_CODE_6M 0x0B
+#define ATH5K_RATE_CODE_9M 0x0F
+#define ATH5K_RATE_CODE_12M 0x0A
+#define ATH5K_RATE_CODE_18M 0x0E
+#define ATH5K_RATE_CODE_24M 0x09
+#define ATH5K_RATE_CODE_36M 0x0D
+#define ATH5K_RATE_CODE_48M 0x08
+#define ATH5K_RATE_CODE_54M 0x0C
+/* XR */
+#define ATH5K_RATE_CODE_XR_500K 0x07
+#define ATH5K_RATE_CODE_XR_1M 0x02
+#define ATH5K_RATE_CODE_XR_2M 0x06
+#define ATH5K_RATE_CODE_XR_3M 0x01
+
+/* adding this flag to rate_code enables short preamble */
+#define AR5K_SET_SHORT_PREAMBLE 0x04
+
+/*
+ * Crypto definitions
+ */
+
+#define AR5K_KEYCACHE_SIZE 8
+
+/***********************\
+ HW RELATED DEFINITIONS
+\***********************/
+
+/*
+ * Misc definitions
+ */
+#define AR5K_RSSI_EP_MULTIPLIER (1<<7)
+
+#define AR5K_ASSERT_ENTRY(_e, _s) do { \
+ if (_e >= _s) \
+ return 0; \
+} while (0)
+
+/*
+ * Hardware interrupt abstraction
+ */
+
+/**
+ * enum ath5k_int - Hardware interrupt masks helpers
+ *
+ * @AR5K_INT_RX: mask to identify received frame interrupts, of type
+ * AR5K_ISR_RXOK or AR5K_ISR_RXERR
+ * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?)
+ * @AR5K_INT_RXNOFRM: No frame received (?)
+ * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The
+ * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
+ * LinkPtr is NULL. For more details, refer to:
+ * http://www.freepatentsonline.com/20030225739.html
+ * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors).
+ * Note that Rx overrun is not always fatal, on some chips we can continue
+ * operation without reseting the card, that's why int_fatal is not
+ * common for all chips.
+ * @AR5K_INT_TX: mask to identify received frame interrupts, of type
+ * AR5K_ISR_TXOK or AR5K_ISR_TXERR
+ * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?)
+ * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold
+ * We currently do increments on interrupt by
+ * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
+ * @AR5K_INT_MIB: Indicates the Management Information Base counters should be
+ * checked. We should do this with ath5k_hw_update_mib_counters() but
+ * it seems we should also then do some noise immunity work.
+ * @AR5K_INT_RXPHY: RX PHY Error
+ * @AR5K_INT_RXKCM: RX Key cache miss
+ * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
+ * beacon that must be handled in software. The alternative is if you
+ * have VEOL support, in that case you let the hardware deal with things.
+ * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing
+ * beacons from the AP have associated with, we should probably try to
+ * reassociate. When in IBSS mode this might mean we have not received
+ * any beacons from any local stations. Note that every station in an
+ * IBSS schedules to send beacons at the Target Beacon Transmission Time
+ * (TBTT) with a random backoff.
+ * @AR5K_INT_BNR: Beacon Not Ready interrupt - ??
+ * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now
+ * until properly handled
+ * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA
+ * errors. These types of errors we can enable seem to be of type
+ * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
+ * @AR5K_INT_GLOBAL: Used to clear and set the IER
+ * @AR5K_INT_NOCARD: signals the card has been removed
+ * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same
+ * bit value
+ *
+ * These are mapped to take advantage of some common bits
+ * between the MACs, to be able to set intr properties
+ * easier. Some of them are not used yet inside hw.c. Most map
+ * to the respective hw interrupt value as they are common amogst different
+ * MACs.
+ */
+enum ath5k_int {
+ AR5K_INT_RXOK = 0x00000001,
+ AR5K_INT_RXDESC = 0x00000002,
+ AR5K_INT_RXERR = 0x00000004,
+ AR5K_INT_RXNOFRM = 0x00000008,
+ AR5K_INT_RXEOL = 0x00000010,
+ AR5K_INT_RXORN = 0x00000020,
+ AR5K_INT_TXOK = 0x00000040,
+ AR5K_INT_TXDESC = 0x00000080,
+ AR5K_INT_TXERR = 0x00000100,
+ AR5K_INT_TXNOFRM = 0x00000200,
+ AR5K_INT_TXEOL = 0x00000400,
+ AR5K_INT_TXURN = 0x00000800,
+ AR5K_INT_MIB = 0x00001000,
+ AR5K_INT_SWI = 0x00002000,
+ AR5K_INT_RXPHY = 0x00004000,
+ AR5K_INT_RXKCM = 0x00008000,
+ AR5K_INT_SWBA = 0x00010000,
+ AR5K_INT_BRSSI = 0x00020000,
+ AR5K_INT_BMISS = 0x00040000,
+ AR5K_INT_FATAL = 0x00080000, /* Non common */
+ AR5K_INT_BNR = 0x00100000, /* Non common */
+ AR5K_INT_TIM = 0x00200000, /* Non common */
+ AR5K_INT_DTIM = 0x00400000, /* Non common */
+ AR5K_INT_DTIM_SYNC = 0x00800000, /* Non common */
+ AR5K_INT_GPIO = 0x01000000,
+ AR5K_INT_BCN_TIMEOUT = 0x02000000, /* Non common */
+ AR5K_INT_CAB_TIMEOUT = 0x04000000, /* Non common */
+ AR5K_INT_RX_DOPPLER = 0x08000000, /* Non common */
+ AR5K_INT_QCBRORN = 0x10000000, /* Non common */
+ AR5K_INT_QCBRURN = 0x20000000, /* Non common */
+ AR5K_INT_QTRIG = 0x40000000, /* Non common */
+ AR5K_INT_GLOBAL = 0x80000000,
+
+ AR5K_INT_COMMON = AR5K_INT_RXOK
+ | AR5K_INT_RXDESC
+ | AR5K_INT_RXERR
+ | AR5K_INT_RXNOFRM
+ | AR5K_INT_RXEOL
+ | AR5K_INT_RXORN
+ | AR5K_INT_TXOK
+ | AR5K_INT_TXDESC
+ | AR5K_INT_TXERR
+ | AR5K_INT_TXNOFRM
+ | AR5K_INT_TXEOL
+ | AR5K_INT_TXURN
+ | AR5K_INT_MIB
+ | AR5K_INT_SWI
+ | AR5K_INT_RXPHY
+ | AR5K_INT_RXKCM
+ | AR5K_INT_SWBA
+ | AR5K_INT_BRSSI
+ | AR5K_INT_BMISS
+ | AR5K_INT_GPIO
+ | AR5K_INT_GLOBAL,
+
+ AR5K_INT_NOCARD = 0xffffffff
+};
+
+/*
+ * Power management
+ */
+enum ath5k_power_mode {
+ AR5K_PM_UNDEFINED = 0,
+ AR5K_PM_AUTO,
+ AR5K_PM_AWAKE,
+ AR5K_PM_FULL_SLEEP,
+ AR5K_PM_NETWORK_SLEEP,
+};
+
+/* GPIO-controlled software LED */
+#define AR5K_SOFTLED_PIN 0
+#define AR5K_SOFTLED_ON 0
+#define AR5K_SOFTLED_OFF 1
+
+/*
+ * Chipset capabilities -see ath5k_hw_get_capability-
+ * get_capability function is not yet fully implemented
+ * in ath5k so most of these don't work yet...
+ * TODO: Implement these & merge with _TUNE_ stuff above
+ */
+enum ath5k_capability_type {
+ AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */
+ AR5K_CAP_TKIP_MIC = 2, /* Can handle TKIP MIC in hardware */
+ AR5K_CAP_TKIP_SPLIT = 3, /* TKIP uses split keys */
+ AR5K_CAP_PHYCOUNTERS = 4, /* PHY error counters */
+ AR5K_CAP_DIVERSITY = 5, /* Supports fast diversity */
+ AR5K_CAP_NUM_TXQUEUES = 6, /* Used to get max number of hw txqueues */
+ AR5K_CAP_VEOL = 7, /* Supports virtual EOL */
+ AR5K_CAP_COMPRESSION = 8, /* Supports compression */
+ AR5K_CAP_BURST = 9, /* Supports packet bursting */
+ AR5K_CAP_FASTFRAME = 10, /* Supports fast frames */
+ AR5K_CAP_TXPOW = 11, /* Used to get global tx power limit */
+ AR5K_CAP_TPC = 12, /* Can do per-packet tx power control (needed for 802.11a) */
+ AR5K_CAP_BSSIDMASK = 13, /* Supports bssid mask */
+ AR5K_CAP_MCAST_KEYSRCH = 14, /* Supports multicast key search */
+ AR5K_CAP_TSF_ADJUST = 15, /* Supports beacon tsf adjust */
+ AR5K_CAP_XR = 16, /* Supports XR mode */
+ AR5K_CAP_WME_TKIPMIC = 17, /* Supports TKIP MIC when using WMM */
+ AR5K_CAP_CHAN_HALFRATE = 18, /* Supports half rate channels */
+ AR5K_CAP_CHAN_QUARTERRATE = 19, /* Supports quarter rate channels */
+ AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */
+};
+
+
+/* XXX: we *may* move cap_range stuff to struct wiphy */
+struct ath5k_capabilities {
+ /*
+ * Supported PHY modes
+ * (ie. CHANNEL_A, CHANNEL_B, ...)
+ */
+ u16 cap_mode;
+
+ /*
+ * Frequency range (without regulation restrictions)
+ */
+ struct {
+ u16 range_2ghz_min;
+ u16 range_2ghz_max;
+ u16 range_5ghz_min;
+ u16 range_5ghz_max;
+ } cap_range;
+
+ /*
+ * Values stored in the EEPROM (some of them...)
+ */
+ struct ath5k_eeprom_info cap_eeprom;
+
+ /*
+ * Queue information
+ */
+ struct {
+ u8 q_tx_num;
+ } cap_queues;
+};
+
+
+/***************************************\
+ HARDWARE ABSTRACTION LAYER STRUCTURE
+\***************************************/
+
+/*
+ * Misc defines
+ */
+
+#define AR5K_MAX_GPIO 10
+#define AR5K_MAX_RF_BANKS 8
+
+/* TODO: Clean up and merge with ath5k_softc */
+struct ath5k_hw {
+ struct ath5k_softc *ah_sc;
+ void *ah_iobase;
+
+ enum ath5k_int ah_imr;
+ int ah_ier;
+
+ struct net80211_channel *ah_current_channel;
+ int ah_turbo;
+ int ah_calibration;
+ int ah_running;
+ int ah_single_chip;
+ int ah_combined_mic;
+
+ u32 ah_mac_srev;
+ u16 ah_mac_version;
+ u16 ah_mac_revision;
+ u16 ah_phy_revision;
+ u16 ah_radio_5ghz_revision;
+ u16 ah_radio_2ghz_revision;
+
+ enum ath5k_version ah_version;
+ enum ath5k_radio ah_radio;
+ u32 ah_phy;
+
+ int ah_5ghz;
+ int ah_2ghz;
+
+#define ah_regdomain ah_capabilities.cap_regdomain.reg_current
+#define ah_regdomain_hw ah_capabilities.cap_regdomain.reg_hw
+#define ah_modes ah_capabilities.cap_mode
+#define ah_ee_version ah_capabilities.cap_eeprom.ee_version
+
+ u32 ah_atim_window;
+ u32 ah_aifs;
+ u32 ah_cw_min;
+ u32 ah_cw_max;
+ int ah_software_retry;
+ u32 ah_limit_tx_retries;
+
+ u32 ah_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
+ int ah_ant_diversity;
+
+ u8 ah_sta_id[ETH_ALEN];
+
+ /* Current BSSID we are trying to assoc to / create.
+ * This is passed by mac80211 on config_interface() and cached here for
+ * use in resets */
+ u8 ah_bssid[ETH_ALEN];
+ u8 ah_bssid_mask[ETH_ALEN];
+
+ u32 ah_gpio[AR5K_MAX_GPIO];
+ int ah_gpio_npins;
+
+ struct ath5k_capabilities ah_capabilities;
+
+ struct ath5k_txq_info ah_txq;
+ u32 ah_txq_status;
+ u32 ah_txq_imr_txok;
+ u32 ah_txq_imr_txerr;
+ u32 ah_txq_imr_txurn;
+ u32 ah_txq_imr_txdesc;
+ u32 ah_txq_imr_txeol;
+ u32 ah_txq_imr_cbrorn;
+ u32 ah_txq_imr_cbrurn;
+ u32 ah_txq_imr_qtrig;
+ u32 ah_txq_imr_nofrm;
+ u32 ah_txq_isr;
+ u32 *ah_rf_banks;
+ size_t ah_rf_banks_size;
+ size_t ah_rf_regs_count;
+ struct ath5k_gain ah_gain;
+ u8 ah_offset[AR5K_MAX_RF_BANKS];
+
+
+ struct {
+ /* Temporary tables used for interpolation */
+ u8 tmpL[AR5K_EEPROM_N_PD_GAINS]
+ [AR5K_EEPROM_POWER_TABLE_SIZE];
+ u8 tmpR[AR5K_EEPROM_N_PD_GAINS]
+ [AR5K_EEPROM_POWER_TABLE_SIZE];
+ u8 txp_pd_table[AR5K_EEPROM_POWER_TABLE_SIZE * 2];
+ u16 txp_rates_power_table[AR5K_MAX_RATES];
+ u8 txp_min_idx;
+ int txp_tpc;
+ /* Values in 0.25dB units */
+ s16 txp_min_pwr;
+ s16 txp_max_pwr;
+ s16 txp_offset;
+ s16 txp_ofdm;
+ /* Values in dB units */
+ s16 txp_cck_ofdm_pwr_delta;
+ s16 txp_cck_ofdm_gainf_delta;
+ } ah_txpower;
+
+ /* noise floor from last periodic calibration */
+ s32 ah_noise_floor;
+
+ /*
+ * Function pointers
+ */
+ int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ u32 size, unsigned int flags);
+ int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+ unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
+ unsigned int, unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int, unsigned int);
+ int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+ struct ath5k_tx_status *);
+ int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+ struct ath5k_rx_status *);
+};
+
+/*
+ * Prototypes
+ */
+
+extern int ath5k_bitrate_to_hw_rix(int bitrate);
+
+/* Attach/Detach Functions */
+extern int ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version, struct ath5k_hw **ah);
+extern void ath5k_hw_detach(struct ath5k_hw *ah);
+
+/* LED functions */
+extern int ath5k_init_leds(struct ath5k_softc *sc);
+extern void ath5k_led_enable(struct ath5k_softc *sc);
+extern void ath5k_led_off(struct ath5k_softc *sc);
+extern void ath5k_unregister_leds(struct ath5k_softc *sc);
+
+/* Reset Functions */
+extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, int initial);
+extern int ath5k_hw_reset(struct ath5k_hw *ah, struct net80211_channel *channel, int change_channel);
+/* Power management functions */
+extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, int set_chip, u16 sleep_duration);
+
+/* DMA Related Functions */
+extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah);
+extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah);
+extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah);
+extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr);
+extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue);
+extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue);
+extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue);
+extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue,
+ u32 phys_addr);
+extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, int increase);
+/* Interrupt handling */
+extern int ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
+extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
+extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask);
+
+/* EEPROM access functions */
+extern int ath5k_eeprom_init(struct ath5k_hw *ah);
+extern void ath5k_eeprom_detach(struct ath5k_hw *ah);
+extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
+extern int ath5k_eeprom_is_hb63(struct ath5k_hw *ah);
+
+/* Protocol Control Unit Functions */
+extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
+/* BSSID Functions */
+extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac);
+extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
+extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id);
+extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
+/* Receive start/stop functions */
+extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
+extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
+/* RX Filter functions */
+extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1);
+extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah);
+extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
+/* ACK bit rate */
+void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, int high);
+/* ACK/CTS Timeouts */
+extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout);
+extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah);
+extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout);
+extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah);
+/* Key table (WEP) functions */
+extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
+
+/* Queue Control Unit, DFS Control Unit Functions */
+extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, const struct ath5k_txq_info *queue_info);
+extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah,
+ enum ath5k_tx_queue queue_type,
+ struct ath5k_txq_info *queue_info);
+extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah);
+extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah);
+extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah);
+extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
+
+/* Hardware Descriptor Functions */
+extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah);
+
+/* GPIO Functions */
+extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
+extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio);
+extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
+extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
+extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
+
+/* rfkill Functions */
+extern void ath5k_rfkill_hw_start(struct ath5k_hw *ah);
+extern void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
+
+/* Misc functions */
+int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
+extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
+extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id);
+extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah);
+
+/* Initial register settings functions */
+extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, int change_channel);
+
+/* Initialize RF */
+extern int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
+ struct net80211_channel *channel,
+ unsigned int mode);
+extern int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq);
+extern enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah);
+extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
+/* PHY/RF channel functions */
+extern int ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
+extern int ath5k_hw_channel(struct ath5k_hw *ah, struct net80211_channel *channel);
+/* PHY calibration */
+extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct net80211_channel *channel);
+extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
+/* Misc PHY functions */
+extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
+extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant);
+extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah);
+extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
+/* TX power setup */
+extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct net80211_channel *channel, u8 ee_mode, u8 txpower);
+extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 ee_mode, u8 txpower);
+
+/*
+ * Functions used internaly
+ */
+
+/*
+ * Translate usec to hw clock units
+ * TODO: Half/quarter rate
+ */
+static inline unsigned int ath5k_hw_htoclock(unsigned int usec, int turbo)
+{
+ return turbo ? (usec * 80) : (usec * 40);
+}
+
+/*
+ * Translate hw clock units to usec
+ * TODO: Half/quarter rate
+ */
+static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, int turbo)
+{
+ return turbo ? (clock / 80) : (clock / 40);
+}
+
+/*
+ * Read from a register
+ */
+static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
+{
+ return readl(ah->ah_iobase + reg);
+}
+
+/*
+ * Write to a register
+ */
+static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
+{
+ writel(val, ah->ah_iobase + reg);
+}
+
+#if defined(_ATH5K_RESET) || defined(_ATH5K_PHY)
+/*
+ * Check if a register write has been completed
+ */
+static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag,
+ u32 val, int is_set)
+{
+ int i;
+ u32 data;
+
+ for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
+ data = ath5k_hw_reg_read(ah, reg);
+ if (is_set && (data & flag))
+ break;
+ else if ((data & flag) == val)
+ break;
+ udelay(15);
+ }
+
+ return (i <= 0) ? -EAGAIN : 0;
+}
+
+/*
+ * Convert channel frequency to channel number
+ */
+static inline int ath5k_freq_to_channel(int freq)
+{
+ if (freq == 2484)
+ return 14;
+
+ if (freq < 2484)
+ return (freq - 2407) / 5;
+
+ return freq/5 - 1000;
+}
+
+#endif
+
+static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
+{
+ u32 retval = 0, bit, i;
+
+ for (i = 0; i < bits; i++) {
+ bit = (val >> i) & 1;
+ retval = (retval << 1) | bit;
+ }
+
+ return retval;
+}
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_attach.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_attach.c
new file mode 100644
index 00000000..302536db
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_attach.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>
+ * Original from Linux kernel 2.6.30.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/*************************************\
+* Attach/Detach Functions and helpers *
+\*************************************/
+
+#include <ipxe/pci.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/**
+ * ath5k_hw_post - Power On Self Test helper function
+ *
+ * @ah: The &struct ath5k_hw
+ */
+static int ath5k_hw_post(struct ath5k_hw *ah)
+{
+
+ static const u32 static_pattern[4] = {
+ 0x55555555, 0xaaaaaaaa,
+ 0x66666666, 0x99999999
+ };
+ static const u16 regs[2] = { AR5K_STA_ID0, AR5K_PHY(8) };
+ int i, c;
+ u16 cur_reg;
+ u32 var_pattern;
+ u32 init_val;
+ u32 cur_val;
+
+ for (c = 0; c < 2; c++) {
+
+ cur_reg = regs[c];
+
+ /* Save previous value */
+ init_val = ath5k_hw_reg_read(ah, cur_reg);
+
+ for (i = 0; i < 256; i++) {
+ var_pattern = i << 16 | i;
+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+ cur_val = ath5k_hw_reg_read(ah, cur_reg);
+
+ if (cur_val != var_pattern) {
+ DBG("ath5k: POST failed!\n");
+ return -EAGAIN;
+ }
+
+ /* Found on ndiswrapper dumps */
+ var_pattern = 0x0039080f;
+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+ }
+
+ for (i = 0; i < 4; i++) {
+ var_pattern = static_pattern[i];
+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+ cur_val = ath5k_hw_reg_read(ah, cur_reg);
+
+ if (cur_val != var_pattern) {
+ DBG("ath5k: POST failed!\n");
+ return -EAGAIN;
+ }
+
+ /* Found on ndiswrapper dumps */
+ var_pattern = 0x003b080f;
+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+ }
+
+ /* Restore previous value */
+ ath5k_hw_reg_write(ah, init_val, cur_reg);
+
+ }
+
+ return 0;
+
+}
+
+/**
+ * ath5k_hw_attach - Check if hw is supported and init the needed structs
+ *
+ * @sc: The &struct ath5k_softc we got from the driver's attach function
+ * @mac_version: The mac version id (check out ath5k.h) based on pci id
+ * @hw: Returned newly allocated hardware structure, on success
+ *
+ * Check if the device is supported, perform a POST and initialize the needed
+ * structs. Returns -ENOMEM if we don't have memory for the needed structs,
+ * -ENODEV if the device is not supported or prints an error msg if something
+ * else went wrong.
+ */
+int ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version,
+ struct ath5k_hw **hw)
+{
+ struct ath5k_hw *ah;
+ struct pci_device *pdev = sc->pdev;
+ int ret;
+ u32 srev;
+
+ ah = zalloc(sizeof(struct ath5k_hw));
+ if (ah == NULL) {
+ ret = -ENOMEM;
+ DBG("ath5k: out of memory\n");
+ goto err;
+ }
+
+ ah->ah_sc = sc;
+ ah->ah_iobase = sc->iobase;
+
+ /*
+ * HW information
+ */
+ ah->ah_turbo = 0;
+ ah->ah_txpower.txp_tpc = 0;
+ ah->ah_imr = 0;
+ ah->ah_atim_window = 0;
+ ah->ah_aifs = AR5K_TUNE_AIFS;
+ ah->ah_cw_min = AR5K_TUNE_CWMIN;
+ ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
+ ah->ah_software_retry = 0;
+ ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
+
+ /*
+ * Set the mac version based on the pci id
+ */
+ ah->ah_version = mac_version;
+
+ /*Fill the ath5k_hw struct with the needed functions*/
+ ret = ath5k_hw_init_desc_functions(ah);
+ if (ret)
+ goto err_free;
+
+ /* Bring device out of sleep and reset it's units */
+ ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, 1);
+ if (ret)
+ goto err_free;
+
+ /* Get MAC, PHY and RADIO revisions */
+ srev = ath5k_hw_reg_read(ah, AR5K_SREV);
+ ah->ah_mac_srev = srev;
+ ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
+ ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
+ ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID);
+ ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, CHANNEL_5GHZ);
+ ah->ah_phy = AR5K_PHY(0);
+
+ /* Try to identify radio chip based on it's srev */
+ switch (ah->ah_radio_5ghz_revision & 0xf0) {
+ case AR5K_SREV_RAD_5111:
+ ah->ah_radio = AR5K_RF5111;
+ ah->ah_single_chip = 0;
+ ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
+ CHANNEL_2GHZ);
+ break;
+ case AR5K_SREV_RAD_5112:
+ case AR5K_SREV_RAD_2112:
+ ah->ah_radio = AR5K_RF5112;
+ ah->ah_single_chip = 0;
+ ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
+ CHANNEL_2GHZ);
+ break;
+ case AR5K_SREV_RAD_2413:
+ ah->ah_radio = AR5K_RF2413;
+ ah->ah_single_chip = 1;
+ break;
+ case AR5K_SREV_RAD_5413:
+ ah->ah_radio = AR5K_RF5413;
+ ah->ah_single_chip = 1;
+ break;
+ case AR5K_SREV_RAD_2316:
+ ah->ah_radio = AR5K_RF2316;
+ ah->ah_single_chip = 1;
+ break;
+ case AR5K_SREV_RAD_2317:
+ ah->ah_radio = AR5K_RF2317;
+ ah->ah_single_chip = 1;
+ break;
+ case AR5K_SREV_RAD_5424:
+ if (ah->ah_mac_version == AR5K_SREV_AR2425 ||
+ ah->ah_mac_version == AR5K_SREV_AR2417) {
+ ah->ah_radio = AR5K_RF2425;
+ } else {
+ ah->ah_radio = AR5K_RF5413;
+ }
+ ah->ah_single_chip = 1;
+ break;
+ default:
+ /* Identify radio based on mac/phy srev */
+ if (ah->ah_version == AR5K_AR5210) {
+ ah->ah_radio = AR5K_RF5110;
+ ah->ah_single_chip = 0;
+ } else if (ah->ah_version == AR5K_AR5211) {
+ ah->ah_radio = AR5K_RF5111;
+ ah->ah_single_chip = 0;
+ ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
+ CHANNEL_2GHZ);
+ } else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) ||
+ ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
+ ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
+ ah->ah_radio = AR5K_RF2425;
+ ah->ah_single_chip = 1;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;
+ } else if (srev == AR5K_SREV_AR5213A &&
+ ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
+ ah->ah_radio = AR5K_RF5112;
+ ah->ah_single_chip = 0;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B;
+ } else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) {
+ ah->ah_radio = AR5K_RF2316;
+ ah->ah_single_chip = 1;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
+ } else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) ||
+ ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
+ ah->ah_radio = AR5K_RF5413;
+ ah->ah_single_chip = 1;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
+ } else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) ||
+ ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
+ ah->ah_radio = AR5K_RF2413;
+ ah->ah_single_chip = 1;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413;
+ } else {
+ DBG("ath5k: Couldn't identify radio revision.\n");
+ ret = -ENOTSUP;
+ goto err_free;
+ }
+ }
+
+ /* Return on unsuported chips (unsupported eeprom etc) */
+ if ((srev >= AR5K_SREV_AR5416) &&
+ (srev < AR5K_SREV_AR2425)) {
+ DBG("ath5k: Device not yet supported.\n");
+ ret = -ENOTSUP;
+ goto err_free;
+ }
+
+ /*
+ * Write PCI-E power save settings
+ */
+ if ((ah->ah_version == AR5K_AR5212) &&
+ pci_find_capability(pdev, PCI_CAP_ID_EXP)) {
+ ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
+ /* Shut off RX when elecidle is asserted */
+ ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
+ /* TODO: EEPROM work */
+ ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES);
+ /* Shut off PLL and CLKREQ active in L1 */
+ ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES);
+ /* Preserce other settings */
+ ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES);
+ /* Reset SERDES to load new settings */
+ ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET);
+ mdelay(1);
+ }
+
+ /*
+ * POST
+ */
+ ret = ath5k_hw_post(ah);
+ if (ret)
+ goto err_free;
+
+ /* Enable pci core retry fix on Hainan (5213A) and later chips */
+ if (srev >= AR5K_SREV_AR5213A)
+ ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG);
+
+ /*
+ * Get card capabilities, calibration values etc
+ * TODO: EEPROM work
+ */
+ ret = ath5k_eeprom_init(ah);
+ if (ret) {
+ DBG("ath5k: unable to init EEPROM\n");
+ goto err_free;
+ }
+
+ /* Get misc capabilities */
+ ret = ath5k_hw_set_capabilities(ah);
+ if (ret) {
+ DBG("ath5k: unable to get device capabilities: 0x%04x\n",
+ sc->pdev->device);
+ goto err_free;
+ }
+
+ if (srev >= AR5K_SREV_AR2414) {
+ ah->ah_combined_mic = 1;
+ AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE,
+ AR5K_MISC_MODE_COMBINED_MIC);
+ }
+
+ /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
+ memset(ah->ah_bssid, 0xff, ETH_ALEN);
+ ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+ ath5k_hw_set_opmode(ah);
+
+ ath5k_hw_rfgain_opt_init(ah);
+
+ *hw = ah;
+ return 0;
+err_free:
+ free(ah);
+err:
+ return ret;
+}
+
+/**
+ * ath5k_hw_detach - Free the ath5k_hw struct
+ *
+ * @ah: The &struct ath5k_hw
+ */
+void ath5k_hw_detach(struct ath5k_hw *ah)
+{
+ free(ah->ah_rf_banks);
+ ath5k_eeprom_detach(ah);
+ free(ah);
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_caps.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_caps.c
new file mode 100644
index 00000000..9c00d15d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_caps.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Lightly modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/**************\
+* Capabilities *
+\**************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*
+ * Fill the capabilities struct
+ * TODO: Merge this with EEPROM code when we are done with it
+ */
+int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
+{
+ u16 ee_header;
+
+ /* Capabilities stored in the EEPROM */
+ ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ /*
+ * Set radio capabilities
+ * (The AR5110 only supports the middle 5GHz band)
+ */
+ ah->ah_capabilities.cap_range.range_5ghz_min = 5120;
+ ah->ah_capabilities.cap_range.range_5ghz_max = 5430;
+ ah->ah_capabilities.cap_range.range_2ghz_min = 0;
+ ah->ah_capabilities.cap_range.range_2ghz_max = 0;
+
+ /* Set supported modes */
+ ah->ah_capabilities.cap_mode |= AR5K_MODE_BIT_11A;
+ ah->ah_capabilities.cap_mode |= AR5K_MODE_BIT_11A_TURBO;
+ } else {
+ /*
+ * XXX The tranceiver supports frequencies from 4920 to 6100GHz
+ * XXX and from 2312 to 2732GHz. There are problems with the
+ * XXX current ieee80211 implementation because the IEEE
+ * XXX channel mapping does not support negative channel
+ * XXX numbers (2312MHz is channel -19). Of course, this
+ * XXX doesn't matter because these channels are out of range
+ * XXX but some regulation domains like MKK (Japan) will
+ * XXX support frequencies somewhere around 4.8GHz.
+ */
+
+ /*
+ * Set radio capabilities
+ */
+
+ if (AR5K_EEPROM_HDR_11A(ee_header)) {
+ /* 4920 */
+ ah->ah_capabilities.cap_range.range_5ghz_min = 5005;
+ ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
+
+ /* Set supported modes */
+ ah->ah_capabilities.cap_mode |= AR5K_MODE_BIT_11A;
+ ah->ah_capabilities.cap_mode |= AR5K_MODE_BIT_11A_TURBO;
+ if (ah->ah_version == AR5K_AR5212)
+ ah->ah_capabilities.cap_mode |=
+ AR5K_MODE_BIT_11G_TURBO;
+ }
+
+ /* Enable 802.11b if a 2GHz capable radio (2111/5112) is
+ * connected */
+ if (AR5K_EEPROM_HDR_11B(ee_header) ||
+ (AR5K_EEPROM_HDR_11G(ee_header) &&
+ ah->ah_version != AR5K_AR5211)) {
+ /* 2312 */
+ ah->ah_capabilities.cap_range.range_2ghz_min = 2412;
+ ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
+
+ if (AR5K_EEPROM_HDR_11B(ee_header))
+ ah->ah_capabilities.cap_mode |=
+ AR5K_MODE_BIT_11B;
+
+ if (AR5K_EEPROM_HDR_11G(ee_header) &&
+ ah->ah_version != AR5K_AR5211)
+ ah->ah_capabilities.cap_mode |=
+ AR5K_MODE_BIT_11G;
+ }
+ }
+
+ /* GPIO */
+ ah->ah_gpio_npins = AR5K_NUM_GPIO;
+
+ /* Set number of supported TX queues */
+ ah->ah_capabilities.cap_queues.q_tx_num = 1;
+
+ return 0;
+}
+
+/* Main function used by the driver part to check caps */
+int ath5k_hw_get_capability(struct ath5k_hw *ah,
+ enum ath5k_capability_type cap_type,
+ u32 capability __unused, u32 *result)
+{
+ switch (cap_type) {
+ case AR5K_CAP_NUM_TXQUEUES:
+ if (result) {
+ *result = 1;
+ goto yes;
+ }
+ case AR5K_CAP_VEOL:
+ goto yes;
+ case AR5K_CAP_COMPRESSION:
+ if (ah->ah_version == AR5K_AR5212)
+ goto yes;
+ else
+ goto no;
+ case AR5K_CAP_BURST:
+ goto yes;
+ case AR5K_CAP_TPC:
+ goto yes;
+ case AR5K_CAP_BSSIDMASK:
+ if (ah->ah_version == AR5K_AR5212)
+ goto yes;
+ else
+ goto no;
+ case AR5K_CAP_XR:
+ if (ah->ah_version == AR5K_AR5212)
+ goto yes;
+ else
+ goto no;
+ default:
+ goto no;
+ }
+
+no:
+ return -EINVAL;
+yes:
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_desc.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_desc.c
new file mode 100644
index 00000000..30fe1c77
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_desc.c
@@ -0,0 +1,544 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
+ *
+ * Lightly modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/******************************\
+ Hardware Descriptor Functions
+\******************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*
+ * TX Descriptors
+ */
+
+#define FCS_LEN 4
+
+/*
+ * Initialize the 2-word tx control descriptor on 5210/5211
+ */
+static int
+ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
+ unsigned int tx_power __unused, unsigned int tx_rate0, unsigned int tx_tries0,
+ unsigned int key_index __unused, unsigned int antenna_mode, unsigned int flags,
+ unsigned int rtscts_rate __unused, unsigned int rtscts_duration)
+{
+ u32 frame_type;
+ struct ath5k_hw_2w_tx_ctl *tx_ctl;
+ unsigned int frame_len;
+
+ tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
+
+ /*
+ * Validate input
+ * - Zero retries don't make sense.
+ * - A zero rate will put the HW into a mode where it continously sends
+ * noise on the channel, so it is important to avoid this.
+ */
+ if (tx_tries0 == 0) {
+ DBG("ath5k: zero retries\n");
+ return -EINVAL;
+ }
+ if (tx_rate0 == 0) {
+ DBG("ath5k: zero rate\n");
+ return -EINVAL;
+ }
+
+ /* Clear descriptor */
+ memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
+
+ /* Setup control descriptor */
+
+ /* Verify and set frame length */
+
+ frame_len = pkt_len + FCS_LEN;
+
+ if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
+ return -EINVAL;
+
+ tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
+
+ /* Verify and set buffer length */
+
+ if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
+ return -EINVAL;
+
+ tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
+
+ /*
+ * Verify and set header length
+ * XXX: I only found that on 5210 code, does it work on 5211 ?
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
+ return -EINVAL;
+ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
+ }
+
+ /*Diferences between 5210-5211*/
+ if (ah->ah_version == AR5K_AR5210) {
+ switch (type) {
+ case AR5K_PKT_TYPE_BEACON:
+ case AR5K_PKT_TYPE_PROBE_RESP:
+ frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
+ case AR5K_PKT_TYPE_PIFS:
+ frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
+ default:
+ frame_type = type /*<< 2 ?*/;
+ }
+
+ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
+ AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+
+ } else {
+ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
+ AR5K_REG_SM(antenna_mode,
+ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
+ tx_ctl->tx_control_1 |=
+ AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
+ }
+#define _TX_FLAGS(_c, _flag) \
+ if (flags & AR5K_TXDESC_##_flag) { \
+ tx_ctl->tx_control_##_c |= \
+ AR5K_2W_TX_DESC_CTL##_c##_##_flag; \
+ }
+
+ _TX_FLAGS(0, CLRDMASK);
+ _TX_FLAGS(0, VEOL);
+ _TX_FLAGS(0, INTREQ);
+ _TX_FLAGS(0, RTSENA);
+ _TX_FLAGS(1, NOACK);
+
+#undef _TX_FLAGS
+
+ /*
+ * RTS/CTS Duration [5210 ?]
+ */
+ if ((ah->ah_version == AR5K_AR5210) &&
+ (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
+ tx_ctl->tx_control_1 |= rtscts_duration &
+ AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
+
+ return 0;
+}
+
+/*
+ * Initialize the 4-word tx control descriptor on 5212
+ */
+static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len __unused,
+ enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
+ unsigned int tx_tries0, unsigned int key_index __unused,
+ unsigned int antenna_mode, unsigned int flags,
+ unsigned int rtscts_rate,
+ unsigned int rtscts_duration)
+{
+ struct ath5k_hw_4w_tx_ctl *tx_ctl;
+ unsigned int frame_len;
+
+ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+
+ /*
+ * Validate input
+ * - Zero retries don't make sense.
+ * - A zero rate will put the HW into a mode where it continously sends
+ * noise on the channel, so it is important to avoid this.
+ */
+ if (tx_tries0 == 0) {
+ DBG("ath5k: zero retries\n");
+ return -EINVAL;
+ }
+ if (tx_rate0 == 0) {
+ DBG("ath5k: zero rate\n");
+ return -EINVAL;
+ }
+
+ tx_power += ah->ah_txpower.txp_offset;
+ if (tx_power > AR5K_TUNE_MAX_TXPOWER)
+ tx_power = AR5K_TUNE_MAX_TXPOWER;
+
+ /* Clear descriptor */
+ memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
+
+ /* Setup control descriptor */
+
+ /* Verify and set frame length */
+
+ frame_len = pkt_len + FCS_LEN;
+
+ if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
+ return -EINVAL;
+
+ tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
+
+ /* Verify and set buffer length */
+
+ if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
+ return -EINVAL;
+
+ tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
+
+ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
+ AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
+ tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
+ AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
+ tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
+ tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+
+#define _TX_FLAGS(_c, _flag) \
+ if (flags & AR5K_TXDESC_##_flag) { \
+ tx_ctl->tx_control_##_c |= \
+ AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
+ }
+
+ _TX_FLAGS(0, CLRDMASK);
+ _TX_FLAGS(0, VEOL);
+ _TX_FLAGS(0, INTREQ);
+ _TX_FLAGS(0, RTSENA);
+ _TX_FLAGS(0, CTSENA);
+ _TX_FLAGS(1, NOACK);
+
+#undef _TX_FLAGS
+
+ /*
+ * RTS/CTS
+ */
+ if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
+ if ((flags & AR5K_TXDESC_RTSENA) &&
+ (flags & AR5K_TXDESC_CTSENA))
+ return -EINVAL;
+ tx_ctl->tx_control_2 |= rtscts_duration &
+ AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
+ tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
+ AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
+ }
+
+ return 0;
+}
+
+/*
+ * Proccess the tx status descriptor on 5210/5211
+ */
+static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah __unused,
+ struct ath5k_desc *desc, struct ath5k_tx_status *ts)
+{
+ struct ath5k_hw_2w_tx_ctl *tx_ctl;
+ struct ath5k_hw_tx_status *tx_status;
+
+ tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
+ tx_status = &desc->ud.ds_tx5210.tx_stat;
+
+ /* No frame has been send or error */
+ if ((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)
+ return -EINPROGRESS;
+
+ /*
+ * Get descriptor status
+ */
+ ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+ ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+ ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+ /*TODO: ts->ts_virtcol + test*/
+ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_SEQ_NUM);
+ ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+ ts->ts_antenna = 1;
+ ts->ts_status = 0;
+ ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
+ AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+ ts->ts_retry[0] = ts->ts_longretry;
+ ts->ts_final_idx = 0;
+
+ if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
+ if (tx_status->tx_status_0 &
+ AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+ ts->ts_status |= AR5K_TXERR_XRETRY;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+ ts->ts_status |= AR5K_TXERR_FIFO;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+ ts->ts_status |= AR5K_TXERR_FILT;
+ }
+
+ return 0;
+}
+
+/*
+ * Proccess a tx status descriptor on 5212
+ */
+static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah __unused,
+ struct ath5k_desc *desc, struct ath5k_tx_status *ts)
+{
+ struct ath5k_hw_4w_tx_ctl *tx_ctl;
+ struct ath5k_hw_tx_status *tx_status;
+
+ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+ tx_status = &desc->ud.ds_tx5212.tx_stat;
+
+ /* No frame has been send or error */
+ if (!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))
+ return -EINPROGRESS;
+
+ /*
+ * Get descriptor status
+ */
+ ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+ ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+ ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_SEQ_NUM);
+ ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+ ts->ts_antenna = (tx_status->tx_status_1 &
+ AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
+ ts->ts_status = 0;
+
+ ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX);
+
+ ts->ts_retry[0] = ts->ts_longretry;
+ ts->ts_rate[0] = tx_ctl->tx_control_3 &
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+
+ /* TX error */
+ if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
+ if (tx_status->tx_status_0 &
+ AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+ ts->ts_status |= AR5K_TXERR_XRETRY;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+ ts->ts_status |= AR5K_TXERR_FIFO;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+ ts->ts_status |= AR5K_TXERR_FILT;
+ }
+
+ return 0;
+}
+
+/*
+ * RX Descriptors
+ */
+
+/*
+ * Initialize an rx control descriptor
+ */
+static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah __unused,
+ struct ath5k_desc *desc,
+ u32 size, unsigned int flags)
+{
+ struct ath5k_hw_rx_ctl *rx_ctl;
+
+ rx_ctl = &desc->ud.ds_rx.rx_ctl;
+
+ /*
+ * Clear the descriptor
+ * If we don't clean the status descriptor,
+ * while scanning we get too many results,
+ * most of them virtual, after some secs
+ * of scanning system hangs. M.F.
+ */
+ memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
+
+ /* Setup descriptor */
+ rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
+ if (rx_ctl->rx_control_1 != size)
+ return -EINVAL;
+
+ if (flags & AR5K_RXDESC_INTREQ)
+ rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
+
+ return 0;
+}
+
+/*
+ * Proccess the rx status descriptor on 5210/5211
+ */
+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah __unused,
+ struct ath5k_desc *desc, struct ath5k_rx_status *rs)
+{
+ struct ath5k_hw_rx_status *rx_status;
+
+ rx_status = &desc->ud.ds_rx.u.rx_stat;
+
+ /* No frame received / not ready */
+ if (!(rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE))
+ return -EINPROGRESS;
+
+ /*
+ * Frame receive status
+ */
+ rs->rs_datalen = rx_status->rx_status_0 &
+ AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
+ rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+ rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
+ rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA);
+ rs->rs_more = !!(rx_status->rx_status_0 &
+ AR5K_5210_RX_DESC_STATUS0_MORE);
+ /* TODO: this timestamp is 13 bit, later on we assume 15 bit */
+ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+ rs->rs_status = 0;
+ rs->rs_phyerr = 0;
+ rs->rs_keyix = AR5K_RXKEYIX_INVALID;
+
+ /*
+ * Receive/descriptor errors
+ */
+ if (!(rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
+ if (rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_CRC;
+
+ if (rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
+ rs->rs_status |= AR5K_RXERR_FIFO;
+
+ if (rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
+ rs->rs_status |= AR5K_RXERR_PHY;
+ rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
+ }
+
+ if (rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_DECRYPT;
+ }
+
+ return 0;
+}
+
+/*
+ * Proccess the rx status descriptor on 5212
+ */
+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah __unused,
+ struct ath5k_desc *desc, struct ath5k_rx_status *rs)
+{
+ struct ath5k_hw_rx_status *rx_status;
+ struct ath5k_hw_rx_error *rx_err;
+
+ rx_status = &desc->ud.ds_rx.u.rx_stat;
+
+ /* Overlay on error */
+ rx_err = &desc->ud.ds_rx.u.rx_err;
+
+ /* No frame received / not ready */
+ if (!(rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE))
+ return -EINPROGRESS;
+
+ /*
+ * Frame receive status
+ */
+ rs->rs_datalen = rx_status->rx_status_0 &
+ AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
+ rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+ rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
+ rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
+ rs->rs_more = !!(rx_status->rx_status_0 &
+ AR5K_5212_RX_DESC_STATUS0_MORE);
+ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+ rs->rs_status = 0;
+ rs->rs_phyerr = 0;
+ rs->rs_keyix = AR5K_RXKEYIX_INVALID;
+
+ /*
+ * Receive/descriptor errors
+ */
+ if (!(rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_CRC;
+
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
+ rs->rs_status |= AR5K_RXERR_PHY;
+ rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
+ AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
+ }
+
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_DECRYPT;
+
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
+ rs->rs_status |= AR5K_RXERR_MIC;
+ }
+
+ return 0;
+}
+
+/*
+ * Init function pointers inside ath5k_hw struct
+ */
+int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
+{
+
+ if (ah->ah_version != AR5K_AR5210 &&
+ ah->ah_version != AR5K_AR5211 &&
+ ah->ah_version != AR5K_AR5212)
+ return -ENOTSUP;
+
+ if (ah->ah_version == AR5K_AR5212) {
+ ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
+ ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
+ ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
+ } else {
+ ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
+ ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
+ ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
+ }
+
+ if (ah->ah_version == AR5K_AR5212)
+ ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
+ else if (ah->ah_version <= AR5K_AR5211)
+ ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
+
+ return 0;
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_dma.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_dma.c
new file mode 100644
index 00000000..fa1e0d01
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_dma.c
@@ -0,0 +1,631 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Lightly modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/*************************************\
+* DMA and interrupt masking functions *
+\*************************************/
+
+/*
+ * dma.c - DMA and interrupt masking functions
+ *
+ * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and
+ * handle queue setup for 5210 chipset (rest are handled on qcu.c).
+ * Also we setup interrupt mask register (IMR) and read the various iterrupt
+ * status registers (ISR).
+ *
+ * TODO: Handle SISR on 5211+ and introduce a function to return the queue
+ * number that resulted the interrupt.
+ */
+
+#include <unistd.h>
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*********\
+* Receive *
+\*********/
+
+/**
+ * ath5k_hw_start_rx_dma - Start DMA receive
+ *
+ * @ah: The &struct ath5k_hw
+ */
+void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
+{
+ ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
+ ath5k_hw_reg_read(ah, AR5K_CR);
+}
+
+/**
+ * ath5k_hw_stop_rx_dma - Stop DMA receive
+ *
+ * @ah: The &struct ath5k_hw
+ */
+int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
+{
+ unsigned int i;
+
+ ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
+
+ /*
+ * It may take some time to disable the DMA receive unit
+ */
+ for (i = 1000; i > 0 &&
+ (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
+ i--)
+ udelay(10);
+
+ return i ? 0 : -EBUSY;
+}
+
+/**
+ * ath5k_hw_get_rxdp - Get RX Descriptor's address
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * XXX: Is RXDP read and clear ?
+ */
+u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
+{
+ return ath5k_hw_reg_read(ah, AR5K_RXDP);
+}
+
+/**
+ * ath5k_hw_set_rxdp - Set RX Descriptor's address
+ *
+ * @ah: The &struct ath5k_hw
+ * @phys_addr: RX descriptor address
+ *
+ * XXX: Should we check if rx is enabled before setting rxdp ?
+ */
+void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
+{
+ ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
+}
+
+
+/**********\
+* Transmit *
+\**********/
+
+/**
+ * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Start DMA transmit for a specific queue and since 5210 doesn't have
+ * QCU/DCU, set up queue parameters for 5210 here based on queue type (one
+ * queue for normal data and one queue for beacons). For queue setup
+ * on newer chips check out qcu.c. Returns -EINVAL if queue number is out
+ * of range or if queue is already disabled.
+ *
+ * NOTE: Must be called after setting up tx control descriptor for that
+ * queue (see below).
+ */
+int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
+{
+ u32 tx_queue;
+
+ /* Return if queue is declared inactive */
+ if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return -EIO;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
+
+ /* Assume always a data queue */
+ tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0;
+
+ /* Start queue */
+ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
+ ath5k_hw_reg_read(ah, AR5K_CR);
+ } else {
+ /* Return if queue is disabled */
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
+ return -EIO;
+
+ /* Start queue */
+ AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue);
+ }
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Stop DMA transmit on a specific hw queue and drain queue so we don't
+ * have any pending frames. Returns -EBUSY if we still have pending frames,
+ * -EINVAL if queue number is out of range.
+ *
+ */
+int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
+{
+ unsigned int i = 40;
+ u32 tx_queue, pending;
+
+ /* Return if queue is declared inactive */
+ if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return -EIO;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
+
+ /* Assume a data queue */
+ tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0;
+
+ /* Stop queue */
+ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
+ ath5k_hw_reg_read(ah, AR5K_CR);
+ } else {
+ /*
+ * Schedule TX disable and wait until queue is empty
+ */
+ AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
+
+ /*Check for pending frames*/
+ do {
+ pending = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_STATUS(queue)) &
+ AR5K_QCU_STS_FRMPENDCNT;
+ udelay(100);
+ } while (--i && pending);
+
+ /* For 2413+ order PCU to drop packets using
+ * QUIET mechanism */
+ if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) && pending) {
+ /* Set periodicity and duration */
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)|
+ AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR),
+ AR5K_QUIET_CTL2);
+
+ /* Enable quiet period for current TSF */
+ ath5k_hw_reg_write(ah,
+ AR5K_QUIET_CTL1_QT_EN |
+ AR5K_REG_SM(ath5k_hw_reg_read(ah,
+ AR5K_TSF_L32_5211) >> 10,
+ AR5K_QUIET_CTL1_NEXT_QT_TSF),
+ AR5K_QUIET_CTL1);
+
+ /* Force channel idle high */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
+ AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
+
+ /* Wait a while and disable mechanism */
+ udelay(200);
+ AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1,
+ AR5K_QUIET_CTL1_QT_EN);
+
+ /* Re-check for pending frames */
+ i = 40;
+ do {
+ pending = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_STATUS(queue)) &
+ AR5K_QCU_STS_FRMPENDCNT;
+ udelay(100);
+ } while (--i && pending);
+
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
+ AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
+ }
+
+ /* Clear register */
+ ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
+ if (pending)
+ return -EBUSY;
+ }
+
+ /* TODO: Check for success on 5210 else return error */
+ return 0;
+}
+
+/**
+ * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Get TX descriptor's address for a specific queue. For 5210 we ignore
+ * the queue number and use tx queue type since we only have 2 queues.
+ * We use TXDP0 for normal data queue and TXDP1 for beacon queue.
+ * For newer chips with QCU/DCU we just read the corresponding TXDP register.
+ *
+ * XXX: Is TXDP read and clear ?
+ */
+u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
+{
+ u16 tx_reg;
+
+ /*
+ * Get the transmit queue descriptor pointer from the selected queue
+ */
+ /*5210 doesn't have QCU*/
+ if (ah->ah_version == AR5K_AR5210) {
+ /* Assume a data queue */
+ tx_reg = AR5K_NOQCU_TXDP0;
+ } else {
+ tx_reg = AR5K_QUEUE_TXDP(queue);
+ }
+
+ return ath5k_hw_reg_read(ah, tx_reg);
+}
+
+/**
+ * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Set TX descriptor's address for a specific queue. For 5210 we ignore
+ * the queue number and we use tx queue type since we only have 2 queues
+ * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue.
+ * For newer chips with QCU/DCU we just set the corresponding TXDP register.
+ * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still
+ * active.
+ */
+int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
+{
+ u16 tx_reg;
+
+ /*
+ * Set the transmit queue descriptor pointer register by type
+ * on 5210
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ /* Assume a data queue */
+ tx_reg = AR5K_NOQCU_TXDP0;
+ } else {
+ /*
+ * Set the transmit queue descriptor pointer for
+ * the selected queue on QCU for 5211+
+ * (this won't work if the queue is still active)
+ */
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
+ return -EIO;
+
+ tx_reg = AR5K_QUEUE_TXDP(queue);
+ }
+
+ /* Set descriptor pointer */
+ ath5k_hw_reg_write(ah, phys_addr, tx_reg);
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_update_tx_triglevel - Update tx trigger level
+ *
+ * @ah: The &struct ath5k_hw
+ * @increase: Flag to force increase of trigger level
+ *
+ * This function increases/decreases the tx trigger level for the tx fifo
+ * buffer (aka FIFO threshold) that is used to indicate when PCU flushes
+ * the buffer and transmits it's data. Lowering this results sending small
+ * frames more quickly but can lead to tx underruns, raising it a lot can
+ * result other problems (i think bmiss is related). Right now we start with
+ * the lowest possible (64Bytes) and if we get tx underrun we increase it using
+ * the increase flag. Returns -EIO if we have have reached maximum/minimum.
+ *
+ * XXX: Link this with tx DMA size ?
+ * XXX: Use it to save interrupts ?
+ * TODO: Needs testing, i think it's related to bmiss...
+ */
+int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, int increase)
+{
+ u32 trigger_level, imr;
+ int ret = -EIO;
+
+ /*
+ * Disable interrupts by setting the mask
+ */
+ imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL);
+
+ trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
+ AR5K_TXCFG_TXFULL);
+
+ if (!increase) {
+ if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
+ goto done;
+ } else
+ trigger_level +=
+ ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
+
+ /*
+ * Update trigger level on success
+ */
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL);
+ else
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_TXFULL, trigger_level);
+
+ ret = 0;
+
+done:
+ /*
+ * Restore interrupt mask
+ */
+ ath5k_hw_set_imr(ah, imr);
+
+ return ret;
+}
+
+/*******************\
+* Interrupt masking *
+\*******************/
+
+/**
+ * ath5k_hw_is_intr_pending - Check if we have pending interrupts
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Check if we have pending interrupts to process. Returns 1 if we
+ * have pending interrupts and 0 if we haven't.
+ */
+int ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
+{
+ return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0;
+}
+
+/**
+ * ath5k_hw_get_isr - Get interrupt status
+ *
+ * @ah: The @struct ath5k_hw
+ * @interrupt_mask: Driver's interrupt mask used to filter out
+ * interrupts in sw.
+ *
+ * This function is used inside our interrupt handler to determine the reason
+ * for the interrupt by reading Primary Interrupt Status Register. Returns an
+ * abstract interrupt status mask which is mostly ISR with some uncommon bits
+ * being mapped on some standard non hw-specific positions
+ * (check out &ath5k_int).
+ *
+ * NOTE: We use read-and-clear register, so after this function is called ISR
+ * is zeroed.
+ */
+int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
+{
+ u32 data;
+
+ /*
+ * Read interrupt status from the Interrupt Status register
+ * on 5210
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ data = ath5k_hw_reg_read(ah, AR5K_ISR);
+ if (data == AR5K_INT_NOCARD) {
+ *interrupt_mask = data;
+ return -ENODEV;
+ }
+ } else {
+ /*
+ * Read interrupt status from Interrupt
+ * Status Register shadow copy (Read And Clear)
+ *
+ * Note: PISR/SISR Not available on 5210
+ */
+ data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
+ if (data == AR5K_INT_NOCARD) {
+ *interrupt_mask = data;
+ return -ENODEV;
+ }
+ }
+
+ /*
+ * Get abstract interrupt mask (driver-compatible)
+ */
+ *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
+
+ if (ah->ah_version != AR5K_AR5210) {
+ u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2);
+
+ /*HIU = Host Interface Unit (PCI etc)*/
+ if (data & (AR5K_ISR_HIUERR))
+ *interrupt_mask |= AR5K_INT_FATAL;
+
+ /*Beacon Not Ready*/
+ if (data & (AR5K_ISR_BNR))
+ *interrupt_mask |= AR5K_INT_BNR;
+
+ if (sisr2 & (AR5K_SISR2_SSERR | AR5K_SISR2_DPERR |
+ AR5K_SISR2_MCABT))
+ *interrupt_mask |= AR5K_INT_FATAL;
+
+ if (data & AR5K_ISR_TIM)
+ *interrupt_mask |= AR5K_INT_TIM;
+
+ if (data & AR5K_ISR_BCNMISC) {
+ if (sisr2 & AR5K_SISR2_TIM)
+ *interrupt_mask |= AR5K_INT_TIM;
+ if (sisr2 & AR5K_SISR2_DTIM)
+ *interrupt_mask |= AR5K_INT_DTIM;
+ if (sisr2 & AR5K_SISR2_DTIM_SYNC)
+ *interrupt_mask |= AR5K_INT_DTIM_SYNC;
+ if (sisr2 & AR5K_SISR2_BCN_TIMEOUT)
+ *interrupt_mask |= AR5K_INT_BCN_TIMEOUT;
+ if (sisr2 & AR5K_SISR2_CAB_TIMEOUT)
+ *interrupt_mask |= AR5K_INT_CAB_TIMEOUT;
+ }
+
+ if (data & AR5K_ISR_RXDOPPLER)
+ *interrupt_mask |= AR5K_INT_RX_DOPPLER;
+ if (data & AR5K_ISR_QCBRORN) {
+ *interrupt_mask |= AR5K_INT_QCBRORN;
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
+ AR5K_SISR3_QCBRORN);
+ }
+ if (data & AR5K_ISR_QCBRURN) {
+ *interrupt_mask |= AR5K_INT_QCBRURN;
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
+ AR5K_SISR3_QCBRURN);
+ }
+ if (data & AR5K_ISR_QTRIG) {
+ *interrupt_mask |= AR5K_INT_QTRIG;
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR4),
+ AR5K_SISR4_QTRIG);
+ }
+
+ if (data & AR5K_ISR_TXOK)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
+ AR5K_SISR0_QCU_TXOK);
+
+ if (data & AR5K_ISR_TXDESC)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
+ AR5K_SISR0_QCU_TXDESC);
+
+ if (data & AR5K_ISR_TXERR)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
+ AR5K_SISR1_QCU_TXERR);
+
+ if (data & AR5K_ISR_TXEOL)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
+ AR5K_SISR1_QCU_TXEOL);
+
+ if (data & AR5K_ISR_TXURN)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR2),
+ AR5K_SISR2_QCU_TXURN);
+ } else {
+ if (data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT |
+ AR5K_ISR_HIUERR | AR5K_ISR_DPERR))
+ *interrupt_mask |= AR5K_INT_FATAL;
+
+ /*
+ * XXX: BMISS interrupts may occur after association.
+ * I found this on 5210 code but it needs testing. If this is
+ * true we should disable them before assoc and re-enable them
+ * after a successful assoc + some jiffies.
+ interrupt_mask &= ~AR5K_INT_BMISS;
+ */
+ }
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_set_imr - Set interrupt mask
+ *
+ * @ah: The &struct ath5k_hw
+ * @new_mask: The new interrupt mask to be set
+ *
+ * Set the interrupt mask in hw to save interrupts. We do that by mapping
+ * ath5k_int bits to hw-specific bits to remove abstraction and writing
+ * Interrupt Mask Register.
+ */
+enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
+{
+ enum ath5k_int old_mask, int_mask;
+
+ old_mask = ah->ah_imr;
+
+ /*
+ * Disable card interrupts to prevent any race conditions
+ * (they will be re-enabled afterwards if AR5K_INT GLOBAL
+ * is set again on the new mask).
+ */
+ if (old_mask & AR5K_INT_GLOBAL) {
+ ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
+ ath5k_hw_reg_read(ah, AR5K_IER);
+ }
+
+ /*
+ * Add additional, chipset-dependent interrupt mask flags
+ * and write them to the IMR (interrupt mask register).
+ */
+ int_mask = new_mask & AR5K_INT_COMMON;
+
+ if (ah->ah_version != AR5K_AR5210) {
+ /* Preserve per queue TXURN interrupt mask */
+ u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2)
+ & AR5K_SIMR2_QCU_TXURN;
+
+ if (new_mask & AR5K_INT_FATAL) {
+ int_mask |= AR5K_IMR_HIUERR;
+ simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR
+ | AR5K_SIMR2_DPERR);
+ }
+
+ /*Beacon Not Ready*/
+ if (new_mask & AR5K_INT_BNR)
+ int_mask |= AR5K_INT_BNR;
+
+ if (new_mask & AR5K_INT_TIM)
+ int_mask |= AR5K_IMR_TIM;
+
+ if (new_mask & AR5K_INT_TIM)
+ simr2 |= AR5K_SISR2_TIM;
+ if (new_mask & AR5K_INT_DTIM)
+ simr2 |= AR5K_SISR2_DTIM;
+ if (new_mask & AR5K_INT_DTIM_SYNC)
+ simr2 |= AR5K_SISR2_DTIM_SYNC;
+ if (new_mask & AR5K_INT_BCN_TIMEOUT)
+ simr2 |= AR5K_SISR2_BCN_TIMEOUT;
+ if (new_mask & AR5K_INT_CAB_TIMEOUT)
+ simr2 |= AR5K_SISR2_CAB_TIMEOUT;
+
+ if (new_mask & AR5K_INT_RX_DOPPLER)
+ int_mask |= AR5K_IMR_RXDOPPLER;
+
+ /* Note: Per queue interrupt masks
+ * are set via reset_tx_queue (qcu.c) */
+ ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
+ ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
+
+ } else {
+ if (new_mask & AR5K_INT_FATAL)
+ int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT
+ | AR5K_IMR_HIUERR | AR5K_IMR_DPERR);
+
+ ath5k_hw_reg_write(ah, int_mask, AR5K_IMR);
+ }
+
+ /* If RXNOFRM interrupt is masked disable it
+ * by setting AR5K_RXNOFRM to zero */
+ if (!(new_mask & AR5K_INT_RXNOFRM))
+ ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM);
+
+ /* Store new interrupt mask */
+ ah->ah_imr = new_mask;
+
+ /* ..re-enable interrupts if AR5K_INT_GLOBAL is set */
+ if (new_mask & AR5K_INT_GLOBAL) {
+ ath5k_hw_reg_write(ah, ah->ah_ier, AR5K_IER);
+ ath5k_hw_reg_read(ah, AR5K_IER);
+ }
+
+ return old_mask;
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_eeprom.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_eeprom.c
new file mode 100644
index 00000000..983d206b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_eeprom.c
@@ -0,0 +1,1760 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2008-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * Lightly modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/*************************************\
+* EEPROM access functions and helpers *
+\*************************************/
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*
+ * Read from eeprom
+ */
+static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
+{
+ u32 status, timeout;
+
+ /*
+ * Initialize EEPROM access
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
+ (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
+ } else {
+ ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
+ AR5K_EEPROM_CMD_READ);
+ }
+
+ for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
+ status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
+ if (status & AR5K_EEPROM_STAT_RDDONE) {
+ if (status & AR5K_EEPROM_STAT_RDERR)
+ return -EIO;
+ *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
+ 0xffff);
+ return 0;
+ }
+ udelay(15);
+ }
+
+ return -ETIMEDOUT;
+}
+
+/*
+ * Translate binary channel representation in EEPROM to frequency
+ */
+static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin,
+ unsigned int mode)
+{
+ u16 val;
+
+ if (bin == AR5K_EEPROM_CHANNEL_DIS)
+ return bin;
+
+ if (mode == AR5K_EEPROM_MODE_11A) {
+ if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
+ val = (5 * bin) + 4800;
+ else
+ val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
+ (bin * 10) + 5100;
+ } else {
+ if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
+ val = bin + 2300;
+ else
+ val = bin + 2400;
+ }
+
+ return val;
+}
+
+/*
+ * Initialize eeprom & capabilities structs
+ */
+static int
+ath5k_eeprom_init_header(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ int ret;
+ u16 val;
+
+ /*
+ * Read values from EEPROM and store them in the capability structure
+ */
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
+
+ /* Return if we have an old EEPROM */
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
+ return 0;
+
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
+ ee_ant_gain);
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
+
+ /* XXX: Don't know which versions include these two */
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2);
+
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3)
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3);
+
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) {
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6);
+ }
+ }
+
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
+ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
+ ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
+ ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
+
+ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
+ ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
+ ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
+ }
+
+ AR5K_EEPROM_READ(AR5K_EEPROM_IS_HB63, val);
+
+ if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && val)
+ ee->ee_is_hb63 = 1;
+ else
+ ee->ee_is_hb63 = 0;
+
+ AR5K_EEPROM_READ(AR5K_EEPROM_RFKILL, val);
+ ee->ee_rfkill_pin = (u8) AR5K_REG_MS(val, AR5K_EEPROM_RFKILL_GPIO_SEL);
+ ee->ee_rfkill_pol = val & AR5K_EEPROM_RFKILL_POLARITY ? 1 : 0;
+
+ return 0;
+}
+
+
+/*
+ * Read antenna infos from eeprom
+ */
+static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
+ unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 o = *offset;
+ u16 val;
+ int ret, i = 0;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
+ ee->ee_atn_tx_rx[mode] = (val >> 2) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
+ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
+ ee->ee_ant_control[mode][i++] = val & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f;
+ ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 2) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3;
+ ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f;
+ ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
+ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
+ ee->ee_ant_control[mode][i++] = val & 0x3f;
+
+ /* Get antenna modes */
+ ah->ah_antenna[mode][0] =
+ (ee->ee_ant_control[mode][0] << 4);
+ ah->ah_antenna[mode][AR5K_ANT_FIXED_A] =
+ ee->ee_ant_control[mode][1] |
+ (ee->ee_ant_control[mode][2] << 6) |
+ (ee->ee_ant_control[mode][3] << 12) |
+ (ee->ee_ant_control[mode][4] << 18) |
+ (ee->ee_ant_control[mode][5] << 24);
+ ah->ah_antenna[mode][AR5K_ANT_FIXED_B] =
+ ee->ee_ant_control[mode][6] |
+ (ee->ee_ant_control[mode][7] << 6) |
+ (ee->ee_ant_control[mode][8] << 12) |
+ (ee->ee_ant_control[mode][9] << 18) |
+ (ee->ee_ant_control[mode][10] << 24);
+
+ /* return new offset */
+ *offset = o;
+
+ return 0;
+}
+
+/*
+ * Read supported modes and some mode-specific calibration data
+ * from eeprom
+ */
+static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
+ unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 o = *offset;
+ u16 val;
+ int ret;
+
+ ee->ee_n_piers[mode] = 0;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11A:
+ ee->ee_ob[mode][3] = (val >> 5) & 0x7;
+ ee->ee_db[mode][3] = (val >> 2) & 0x7;
+ ee->ee_ob[mode][2] = (val << 1) & 0x7;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
+ ee->ee_db[mode][2] = (val >> 12) & 0x7;
+ ee->ee_ob[mode][1] = (val >> 9) & 0x7;
+ ee->ee_db[mode][1] = (val >> 6) & 0x7;
+ ee->ee_ob[mode][0] = (val >> 3) & 0x7;
+ ee->ee_db[mode][0] = val & 0x7;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ case AR5K_EEPROM_MODE_11B:
+ ee->ee_ob[mode][1] = (val >> 4) & 0x7;
+ ee->ee_db[mode][1] = val & 0x7;
+ break;
+ }
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
+ ee->ee_thr_62[mode] = val & 0xff;
+
+ if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
+ ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
+ ee->ee_tx_frm2xpa_enable[mode] = val & 0xff;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff;
+
+ if ((val & 0xff) & 0x80)
+ ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
+ else
+ ee->ee_noise_floor_thr[mode] = val & 0xff;
+
+ if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
+ ee->ee_noise_floor_thr[mode] =
+ mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_xlna_gain[mode] = (val >> 5) & 0xff;
+ ee->ee_x_gain[mode] = (val >> 1) & 0xf;
+ ee->ee_xpd[mode] = val & 0x1;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
+ ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
+
+ if (mode == AR5K_EEPROM_MODE_11A)
+ ee->ee_xr_power[mode] = val & 0x3f;
+ else {
+ ee->ee_ob[mode][0] = val & 0x7;
+ ee->ee_db[mode][0] = (val >> 3) & 0x7;
+ }
+ }
+
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
+ ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
+ ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
+ } else {
+ ee->ee_i_gain[mode] = (val >> 13) & 0x7;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_i_gain[mode] |= (val << 3) & 0x38;
+
+ if (mode == AR5K_EEPROM_MODE_11G) {
+ ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6)
+ ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
+ }
+ }
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
+ mode == AR5K_EEPROM_MODE_11A) {
+ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
+ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+ }
+
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0)
+ goto done;
+
+ /* Note: >= v5 have bg freq piers on another location
+ * so these freq piers are ignored for >= v5 (should be 0xff
+ * anyway) */
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11A:
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)
+ break;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_margin_tx_rx[mode] = val & 0x3f;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ AR5K_EEPROM_READ(o++, val);
+
+ ee->ee_pwr_cal_b[0].freq =
+ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+ if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ ee->ee_pwr_cal_b[1].freq =
+ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
+ if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_pwr_cal_b[2].freq =
+ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+ if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ AR5K_EEPROM_READ(o++, val);
+
+ ee->ee_pwr_cal_g[0].freq =
+ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+ if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ ee->ee_pwr_cal_g[1].freq =
+ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
+ if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_turbo_max_power[mode] = val & 0x7f;
+ ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_pwr_cal_g[2].freq =
+ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+ if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
+ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_cck_ofdm_gain_delta = val & 0xff;
+ }
+ break;
+ }
+
+done:
+ /* return new offset */
+ *offset = o;
+
+ return 0;
+}
+
+/*
+ * Read turbo mode information on newer EEPROM versions
+ */
+static int
+ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah,
+ u32 *offset, unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 o = *offset;
+ u16 val;
+ int ret;
+
+ if (ee->ee_version < AR5K_EEPROM_VERSION_5_0)
+ return 0;
+
+ switch (mode){
+ case AR5K_EEPROM_MODE_11A:
+ ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f;
+
+ ee->ee_atn_tx_rx_turbo[mode] = (val >> 13) & 0x7;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x7) << 3;
+ ee->ee_margin_tx_rx_turbo[mode] = (val >> 3) & 0x3f;
+
+ ee->ee_adc_desired_size_turbo[mode] = (val >> 9) & 0x7f;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7;
+ ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff;
+
+ if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2)
+ ee->ee_pd_gain_overlap = (val >> 9) & 0xf;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ ee->ee_switch_settling_turbo[mode] = (val >> 8) & 0x7f;
+
+ ee->ee_atn_tx_rx_turbo[mode] = (val >> 15) & 0x7;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x1f) << 1;
+ ee->ee_margin_tx_rx_turbo[mode] = (val >> 5) & 0x3f;
+
+ ee->ee_adc_desired_size_turbo[mode] = (val >> 11) & 0x7f;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_adc_desired_size_turbo[mode] |= (val & 0x7) << 5;
+ ee->ee_pga_desired_size_turbo[mode] = (val >> 3) & 0xff;
+ break;
+ }
+
+ /* return new offset */
+ *offset = o;
+
+ return 0;
+}
+
+/* Read mode-specific data (except power calibration data) */
+static int
+ath5k_eeprom_init_modes(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 mode_offset[3];
+ unsigned int mode;
+ u32 offset;
+ int ret;
+
+ /*
+ * Get values for all modes
+ */
+ mode_offset[AR5K_EEPROM_MODE_11A] = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
+ mode_offset[AR5K_EEPROM_MODE_11B] = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
+ mode_offset[AR5K_EEPROM_MODE_11G] = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
+
+ ee->ee_turbo_max_power[AR5K_EEPROM_MODE_11A] =
+ AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
+
+ for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) {
+ offset = mode_offset[mode];
+
+ ret = ath5k_eeprom_read_ants(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ ret = ath5k_eeprom_read_modes(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode);
+ if (ret)
+ return ret;
+ }
+
+ /* override for older eeprom versions for better performance */
+ if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) {
+ ee->ee_thr_62[AR5K_EEPROM_MODE_11A] = 15;
+ ee->ee_thr_62[AR5K_EEPROM_MODE_11B] = 28;
+ ee->ee_thr_62[AR5K_EEPROM_MODE_11G] = 28;
+ }
+
+ return 0;
+}
+
+/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff
+ * frequency mask) */
+static inline int
+ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
+ struct ath5k_chan_pcal_info *pc, unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ int o = *offset;
+ int i = 0;
+ u8 freq1, freq2;
+ int ret;
+ u16 val;
+
+ ee->ee_n_piers[mode] = 0;
+ while(i < max) {
+ AR5K_EEPROM_READ(o++, val);
+
+ freq1 = val & 0xff;
+ if (!freq1)
+ break;
+
+ pc[i++].freq = ath5k_eeprom_bin2freq(ee,
+ freq1, mode);
+ ee->ee_n_piers[mode]++;
+
+ freq2 = (val >> 8) & 0xff;
+ if (!freq2)
+ break;
+
+ pc[i++].freq = ath5k_eeprom_bin2freq(ee,
+ freq2, mode);
+ ee->ee_n_piers[mode]++;
+ }
+
+ /* return new offset */
+ *offset = o;
+
+ return 0;
+}
+
+/* Read frequency piers for 802.11a */
+static int
+ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a;
+ int i, ret;
+ u16 val;
+ u8 mask;
+
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
+ ath5k_eeprom_read_freq_list(ah, &offset,
+ AR5K_EEPROM_N_5GHZ_CHAN, pcal,
+ AR5K_EEPROM_MODE_11A);
+ } else {
+ mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version);
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[0].freq = (val >> 9) & mask;
+ pcal[1].freq = (val >> 2) & mask;
+ pcal[2].freq = (val << 5) & mask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[2].freq |= (val >> 11) & 0x1f;
+ pcal[3].freq = (val >> 4) & mask;
+ pcal[4].freq = (val << 3) & mask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[4].freq |= (val >> 13) & 0x7;
+ pcal[5].freq = (val >> 6) & mask;
+ pcal[6].freq = (val << 1) & mask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[6].freq |= (val >> 15) & 0x1;
+ pcal[7].freq = (val >> 8) & mask;
+ pcal[8].freq = (val >> 1) & mask;
+ pcal[9].freq = (val << 6) & mask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[9].freq |= (val >> 10) & 0x3f;
+
+ /* Fixed number of piers */
+ ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10;
+
+ for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) {
+ pcal[i].freq = ath5k_eeprom_bin2freq(ee,
+ pcal[i].freq, AR5K_EEPROM_MODE_11A);
+ }
+ }
+
+ return 0;
+}
+
+/* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */
+static inline int
+ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *pcal;
+
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11B:
+ pcal = ee->ee_pwr_cal_b;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ pcal = ee->ee_pwr_cal_g;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ath5k_eeprom_read_freq_list(ah, &offset,
+ AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal,
+ mode);
+
+ return 0;
+}
+
+/*
+ * Read power calibration for RF5111 chips
+ *
+ * For RF5111 we have an XPD -eXternal Power Detector- curve
+ * for each calibrated channel. Each curve has 0,5dB Power steps
+ * on x axis and PCDAC steps (offsets) on y axis and looks like an
+ * exponential function. To recreate the curve we read 11 points
+ * here and interpolate later.
+ */
+
+/* Used to match PCDAC steps with power values on RF5111 chips
+ * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC
+ * steps that match with the power values we read from eeprom. On
+ * older eeprom versions (< 3.2) these steps are equaly spaced at
+ * 10% of the pcdac curve -until the curve reaches it's maximum-
+ * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
+ * these 11 steps are spaced in a different way. This function returns
+ * the pcdac steps based on eeprom version and curve min/max so that we
+ * can have pcdac/pwr points.
+ */
+static inline void
+ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
+{
+ static const u16 intercepts3[] =
+ { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
+ static const u16 intercepts3_2[] =
+ { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
+ const u16 *ip;
+ unsigned i;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2)
+ ip = intercepts3_2;
+ else
+ ip = intercepts3;
+
+ for (i = 0; i < ARRAY_SIZE(intercepts3); i++)
+ vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;
+}
+
+/* Convert RF5111 specific data to generic raw data
+ * used by interpolation code */
+static int
+ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
+ struct ath5k_chan_pcal_info *chinfo)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info_rf5111 *pcinfo;
+ struct ath5k_pdgain_info *pd;
+ u8 pier, point, idx;
+ u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+
+ /* Fill raw data for each calibration pier */
+ for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
+
+ pcinfo = &chinfo[pier].rf5111_info;
+
+ /* Allocate pd_curves for this cal pier */
+ chinfo[pier].pd_curves =
+ calloc(AR5K_EEPROM_N_PD_CURVES,
+ sizeof(struct ath5k_pdgain_info));
+
+ if (!chinfo[pier].pd_curves)
+ return -ENOMEM;
+
+ /* Only one curve for RF5111
+ * find out which one and place
+ * in in pd_curves.
+ * Note: ee_x_gain is reversed here */
+ for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) {
+
+ if (!((ee->ee_x_gain[mode] >> idx) & 0x1)) {
+ pdgain_idx[0] = idx;
+ break;
+ }
+ }
+
+ ee->ee_pd_gains[mode] = 1;
+
+ pd = &chinfo[pier].pd_curves[idx];
+
+ pd->pd_points = AR5K_EEPROM_N_PWR_POINTS_5111;
+
+ /* Allocate pd points for this curve */
+ pd->pd_step = calloc(AR5K_EEPROM_N_PWR_POINTS_5111, sizeof(u8));
+ if (!pd->pd_step)
+ return -ENOMEM;
+
+ pd->pd_pwr = calloc(AR5K_EEPROM_N_PWR_POINTS_5111, sizeof(s16));
+ if (!pd->pd_pwr)
+ return -ENOMEM;
+
+ /* Fill raw dataset
+ * (convert power to 0.25dB units
+ * for RF5112 combatibility) */
+ for (point = 0; point < pd->pd_points; point++) {
+
+ /* Absolute values */
+ pd->pd_pwr[point] = 2 * pcinfo->pwr[point];
+
+ /* Already sorted */
+ pd->pd_step[point] = pcinfo->pcdac[point];
+ }
+
+ /* Set min/max pwr */
+ chinfo[pier].min_pwr = pd->pd_pwr[0];
+ chinfo[pier].max_pwr = pd->pd_pwr[10];
+
+ }
+
+ return 0;
+}
+
+/* Parse EEPROM data */
+static int
+ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *pcal;
+ int offset, ret;
+ int i;
+ u16 val;
+
+ offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11A:
+ if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
+ return 0;
+
+ ret = ath5k_eeprom_init_11a_pcal_freq(ah,
+ offset + AR5K_EEPROM_GROUP1_OFFSET);
+ if (ret < 0)
+ return ret;
+
+ offset += AR5K_EEPROM_GROUP2_OFFSET;
+ pcal = ee->ee_pwr_cal_a;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ if (!AR5K_EEPROM_HDR_11B(ee->ee_header) &&
+ !AR5K_EEPROM_HDR_11G(ee->ee_header))
+ return 0;
+
+ pcal = ee->ee_pwr_cal_b;
+ offset += AR5K_EEPROM_GROUP3_OFFSET;
+
+ /* fixed piers */
+ pcal[0].freq = 2412;
+ pcal[1].freq = 2447;
+ pcal[2].freq = 2484;
+ ee->ee_n_piers[mode] = 3;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
+ return 0;
+
+ pcal = ee->ee_pwr_cal_g;
+ offset += AR5K_EEPROM_GROUP4_OFFSET;
+
+ /* fixed piers */
+ pcal[0].freq = 2312;
+ pcal[1].freq = 2412;
+ pcal[2].freq = 2484;
+ ee->ee_n_piers[mode] = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ee->ee_n_piers[mode]; i++) {
+ struct ath5k_chan_pcal_info_rf5111 *cdata =
+ &pcal[i].rf5111_info;
+
+ AR5K_EEPROM_READ(offset++, val);
+ cdata->pcdac_max = ((val >> 10) & AR5K_EEPROM_PCDAC_M);
+ cdata->pcdac_min = ((val >> 4) & AR5K_EEPROM_PCDAC_M);
+ cdata->pwr[0] = ((val << 2) & AR5K_EEPROM_POWER_M);
+
+ AR5K_EEPROM_READ(offset++, val);
+ cdata->pwr[0] |= ((val >> 14) & 0x3);
+ cdata->pwr[1] = ((val >> 8) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[2] = ((val >> 2) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[3] = ((val << 4) & AR5K_EEPROM_POWER_M);
+
+ AR5K_EEPROM_READ(offset++, val);
+ cdata->pwr[3] |= ((val >> 12) & 0xf);
+ cdata->pwr[4] = ((val >> 6) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[5] = (val & AR5K_EEPROM_POWER_M);
+
+ AR5K_EEPROM_READ(offset++, val);
+ cdata->pwr[6] = ((val >> 10) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[7] = ((val >> 4) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[8] = ((val << 2) & AR5K_EEPROM_POWER_M);
+
+ AR5K_EEPROM_READ(offset++, val);
+ cdata->pwr[8] |= ((val >> 14) & 0x3);
+ cdata->pwr[9] = ((val >> 8) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[10] = ((val >> 2) & AR5K_EEPROM_POWER_M);
+
+ ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min,
+ cdata->pcdac_max, cdata->pcdac);
+ }
+
+ return ath5k_eeprom_convert_pcal_info_5111(ah, mode, pcal);
+}
+
+
+/*
+ * Read power calibration for RF5112 chips
+ *
+ * For RF5112 we have 4 XPD -eXternal Power Detector- curves
+ * for each calibrated channel on 0, -6, -12 and -18dbm but we only
+ * use the higher (3) and the lower (0) curves. Each curve has 0.5dB
+ * power steps on x axis and PCDAC steps on y axis and looks like a
+ * linear function. To recreate the curve and pass the power values
+ * on hw, we read 4 points for xpd 0 (lower gain -> max power)
+ * and 3 points for xpd 3 (higher gain -> lower power) here and
+ * interpolate later.
+ *
+ * Note: Many vendors just use xpd 0 so xpd 3 is zeroed.
+ */
+
+/* Convert RF5112 specific data to generic raw data
+ * used by interpolation code */
+static int
+ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
+ struct ath5k_chan_pcal_info *chinfo)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info_rf5112 *pcinfo;
+ u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+ unsigned int pier, pdg, point;
+
+ /* Fill raw data for each calibration pier */
+ for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
+
+ pcinfo = &chinfo[pier].rf5112_info;
+
+ /* Allocate pd_curves for this cal pier */
+ chinfo[pier].pd_curves =
+ calloc(AR5K_EEPROM_N_PD_CURVES,
+ sizeof(struct ath5k_pdgain_info));
+
+ if (!chinfo[pier].pd_curves)
+ return -ENOMEM;
+
+ /* Fill pd_curves */
+ for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
+
+ u8 idx = pdgain_idx[pdg];
+ struct ath5k_pdgain_info *pd =
+ &chinfo[pier].pd_curves[idx];
+
+ /* Lowest gain curve (max power) */
+ if (pdg == 0) {
+ /* One more point for better accuracy */
+ pd->pd_points = AR5K_EEPROM_N_XPD0_POINTS;
+
+ /* Allocate pd points for this curve */
+ pd->pd_step = calloc(pd->pd_points, sizeof(u8));
+
+ if (!pd->pd_step)
+ return -ENOMEM;
+
+ pd->pd_pwr = calloc(pd->pd_points, sizeof(s16));
+
+ if (!pd->pd_pwr)
+ return -ENOMEM;
+
+
+ /* Fill raw dataset
+ * (all power levels are in 0.25dB units) */
+ pd->pd_step[0] = pcinfo->pcdac_x0[0];
+ pd->pd_pwr[0] = pcinfo->pwr_x0[0];
+
+ for (point = 1; point < pd->pd_points;
+ point++) {
+ /* Absolute values */
+ pd->pd_pwr[point] =
+ pcinfo->pwr_x0[point];
+
+ /* Deltas */
+ pd->pd_step[point] =
+ pd->pd_step[point - 1] +
+ pcinfo->pcdac_x0[point];
+ }
+
+ /* Set min power for this frequency */
+ chinfo[pier].min_pwr = pd->pd_pwr[0];
+
+ /* Highest gain curve (min power) */
+ } else if (pdg == 1) {
+
+ pd->pd_points = AR5K_EEPROM_N_XPD3_POINTS;
+
+ /* Allocate pd points for this curve */
+ pd->pd_step = calloc(pd->pd_points, sizeof(u8));
+
+ if (!pd->pd_step)
+ return -ENOMEM;
+
+ pd->pd_pwr = calloc(pd->pd_points, sizeof(s16));
+
+ if (!pd->pd_pwr)
+ return -ENOMEM;
+
+ /* Fill raw dataset
+ * (all power levels are in 0.25dB units) */
+ for (point = 0; point < pd->pd_points;
+ point++) {
+ /* Absolute values */
+ pd->pd_pwr[point] =
+ pcinfo->pwr_x3[point];
+
+ /* Fixed points */
+ pd->pd_step[point] =
+ pcinfo->pcdac_x3[point];
+ }
+
+ /* Since we have a higher gain curve
+ * override min power */
+ chinfo[pier].min_pwr = pd->pd_pwr[0];
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Parse EEPROM data */
+static int
+ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info;
+ struct ath5k_chan_pcal_info *gen_chan_info;
+ u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+ u32 offset;
+ u8 i, c;
+ u16 val;
+ int ret;
+ u8 pd_gains = 0;
+
+ /* Count how many curves we have and
+ * identify them (which one of the 4
+ * available curves we have on each count).
+ * Curves are stored from lower (x0) to
+ * higher (x3) gain */
+ for (i = 0; i < AR5K_EEPROM_N_PD_CURVES; i++) {
+ /* ee_x_gain[mode] is x gain mask */
+ if ((ee->ee_x_gain[mode] >> i) & 0x1)
+ pdgain_idx[pd_gains++] = i;
+ }
+ ee->ee_pd_gains[mode] = pd_gains;
+
+ if (pd_gains == 0 || pd_gains > 2)
+ return -EINVAL;
+
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ /*
+ * Read 5GHz EEPROM channels
+ */
+ offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+ ath5k_eeprom_init_11a_pcal_freq(ah, offset);
+
+ offset += AR5K_EEPROM_GROUP2_OFFSET;
+ gen_chan_info = ee->ee_pwr_cal_a;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+ if (AR5K_EEPROM_HDR_11A(ee->ee_header))
+ offset += AR5K_EEPROM_GROUP3_OFFSET;
+
+ /* NB: frequency piers parsed during mode init */
+ gen_chan_info = ee->ee_pwr_cal_b;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+ if (AR5K_EEPROM_HDR_11A(ee->ee_header))
+ offset += AR5K_EEPROM_GROUP4_OFFSET;
+ else if (AR5K_EEPROM_HDR_11B(ee->ee_header))
+ offset += AR5K_EEPROM_GROUP2_OFFSET;
+
+ /* NB: frequency piers parsed during mode init */
+ gen_chan_info = ee->ee_pwr_cal_g;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ee->ee_n_piers[mode]; i++) {
+ chan_pcal_info = &gen_chan_info[i].rf5112_info;
+
+ /* Power values in quarter dB
+ * for the lower xpd gain curve
+ * (0 dBm -> higher output power) */
+ for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pwr_x0[c] = (s8) (val & 0xff);
+ chan_pcal_info->pwr_x0[++c] = (s8) ((val >> 8) & 0xff);
+ }
+
+ /* PCDAC steps
+ * corresponding to the above power
+ * measurements */
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pcdac_x0[1] = (val & 0x1f);
+ chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f);
+ chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f);
+
+ /* Power values in quarter dB
+ * for the higher xpd gain curve
+ * (18 dBm -> lower output power) */
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pwr_x3[0] = (s8) (val & 0xff);
+ chan_pcal_info->pwr_x3[1] = (s8) ((val >> 8) & 0xff);
+
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pwr_x3[2] = (val & 0xff);
+
+ /* PCDAC steps
+ * corresponding to the above power
+ * measurements (fixed) */
+ chan_pcal_info->pcdac_x3[0] = 20;
+ chan_pcal_info->pcdac_x3[1] = 35;
+ chan_pcal_info->pcdac_x3[2] = 63;
+
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) {
+ chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0x3f);
+
+ /* Last xpd0 power level is also channel maximum */
+ gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3];
+ } else {
+ chan_pcal_info->pcdac_x0[0] = 1;
+ gen_chan_info[i].max_pwr = (s8) ((val >> 8) & 0xff);
+ }
+
+ }
+
+ return ath5k_eeprom_convert_pcal_info_5112(ah, mode, gen_chan_info);
+}
+
+
+/*
+ * Read power calibration for RF2413 chips
+ *
+ * For RF2413 we have a Power to PDDAC table (Power Detector)
+ * instead of a PCDAC and 4 pd gain curves for each calibrated channel.
+ * Each curve has power on x axis in 0.5 db steps and PDDADC steps on y
+ * axis and looks like an exponential function like the RF5111 curve.
+ *
+ * To recreate the curves we read here the points and interpolate
+ * later. Note that in most cases only 2 (higher and lower) curves are
+ * used (like RF5112) but vendors have the oportunity to include all
+ * 4 curves on eeprom. The final curve (higher power) has an extra
+ * point for better accuracy like RF5112.
+ */
+
+/* For RF2413 power calibration data doesn't start on a fixed location and
+ * if a mode is not supported, it's section is missing -not zeroed-.
+ * So we need to calculate the starting offset for each section by using
+ * these two functions */
+
+/* Return the size of each section based on the mode and the number of pd
+ * gains available (maximum 4). */
+static inline unsigned int
+ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode)
+{
+ static const unsigned int pdgains_size[] = { 4, 6, 9, 12 };
+ unsigned int sz;
+
+ sz = pdgains_size[ee->ee_pd_gains[mode] - 1];
+ sz *= ee->ee_n_piers[mode];
+
+ return sz;
+}
+
+/* Return the starting offset for a section based on the modes supported
+ * and each section's size. */
+static unsigned int
+ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
+{
+ u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4);
+
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11G:
+ if (AR5K_EEPROM_HDR_11B(ee->ee_header))
+ offset += ath5k_pdgains_size_2413(ee,
+ AR5K_EEPROM_MODE_11B) +
+ AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
+ /* fall through */
+ case AR5K_EEPROM_MODE_11B:
+ if (AR5K_EEPROM_HDR_11A(ee->ee_header))
+ offset += ath5k_pdgains_size_2413(ee,
+ AR5K_EEPROM_MODE_11A) +
+ AR5K_EEPROM_N_5GHZ_CHAN / 2;
+ /* fall through */
+ case AR5K_EEPROM_MODE_11A:
+ break;
+ default:
+ break;
+ }
+
+ return offset;
+}
+
+/* Convert RF2413 specific data to generic raw data
+ * used by interpolation code */
+static int
+ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
+ struct ath5k_chan_pcal_info *chinfo)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info_rf2413 *pcinfo;
+ u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+ unsigned int pier, point;
+ int pdg;
+
+ /* Fill raw data for each calibration pier */
+ for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
+
+ pcinfo = &chinfo[pier].rf2413_info;
+
+ /* Allocate pd_curves for this cal pier */
+ chinfo[pier].pd_curves =
+ calloc(AR5K_EEPROM_N_PD_CURVES,
+ sizeof(struct ath5k_pdgain_info));
+
+ if (!chinfo[pier].pd_curves)
+ return -ENOMEM;
+
+ /* Fill pd_curves */
+ for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
+
+ u8 idx = pdgain_idx[pdg];
+ struct ath5k_pdgain_info *pd =
+ &chinfo[pier].pd_curves[idx];
+
+ /* One more point for the highest power
+ * curve (lowest gain) */
+ if (pdg == ee->ee_pd_gains[mode] - 1)
+ pd->pd_points = AR5K_EEPROM_N_PD_POINTS;
+ else
+ pd->pd_points = AR5K_EEPROM_N_PD_POINTS - 1;
+
+ /* Allocate pd points for this curve */
+ pd->pd_step = calloc(pd->pd_points, sizeof(u8));
+
+ if (!pd->pd_step)
+ return -ENOMEM;
+
+ pd->pd_pwr = calloc(pd->pd_points, sizeof(s16));
+
+ if (!pd->pd_pwr)
+ return -ENOMEM;
+
+ /* Fill raw dataset
+ * convert all pwr levels to
+ * quarter dB for RF5112 combatibility */
+ pd->pd_step[0] = pcinfo->pddac_i[pdg];
+ pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg];
+
+ for (point = 1; point < pd->pd_points; point++) {
+
+ pd->pd_pwr[point] = pd->pd_pwr[point - 1] +
+ 2 * pcinfo->pwr[pdg][point - 1];
+
+ pd->pd_step[point] = pd->pd_step[point - 1] +
+ pcinfo->pddac[pdg][point - 1];
+
+ }
+
+ /* Highest gain curve -> min power */
+ if (pdg == 0)
+ chinfo[pier].min_pwr = pd->pd_pwr[0];
+
+ /* Lowest gain curve -> max power */
+ if (pdg == ee->ee_pd_gains[mode] - 1)
+ chinfo[pier].max_pwr =
+ pd->pd_pwr[pd->pd_points - 1];
+ }
+ }
+
+ return 0;
+}
+
+/* Parse EEPROM data */
+static int
+ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info_rf2413 *pcinfo;
+ struct ath5k_chan_pcal_info *chinfo;
+ u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+ u32 offset;
+ int idx, i, ret;
+ u16 val;
+ u8 pd_gains = 0;
+
+ /* Count how many curves we have and
+ * identify them (which one of the 4
+ * available curves we have on each count).
+ * Curves are stored from higher to
+ * lower gain so we go backwards */
+ for (idx = AR5K_EEPROM_N_PD_CURVES - 1; idx >= 0; idx--) {
+ /* ee_x_gain[mode] is x gain mask */
+ if ((ee->ee_x_gain[mode] >> idx) & 0x1)
+ pdgain_idx[pd_gains++] = idx;
+
+ }
+ ee->ee_pd_gains[mode] = pd_gains;
+
+ if (pd_gains == 0)
+ return -EINVAL;
+
+ offset = ath5k_cal_data_offset_2413(ee, mode);
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
+ return 0;
+
+ ath5k_eeprom_init_11a_pcal_freq(ah, offset);
+ offset += AR5K_EEPROM_N_5GHZ_CHAN / 2;
+ chinfo = ee->ee_pwr_cal_a;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
+ return 0;
+
+ ath5k_eeprom_init_11bg_2413(ah, mode, offset);
+ offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
+ chinfo = ee->ee_pwr_cal_b;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
+ return 0;
+
+ ath5k_eeprom_init_11bg_2413(ah, mode, offset);
+ offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
+ chinfo = ee->ee_pwr_cal_g;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ee->ee_n_piers[mode]; i++) {
+ pcinfo = &chinfo[i].rf2413_info;
+
+ /*
+ * Read pwr_i, pddac_i and the first
+ * 2 pd points (pwr, pddac)
+ */
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr_i[0] = val & 0x1f;
+ pcinfo->pddac_i[0] = (val >> 5) & 0x7f;
+ pcinfo->pwr[0][0] = (val >> 12) & 0xf;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac[0][0] = val & 0x3f;
+ pcinfo->pwr[0][1] = (val >> 6) & 0xf;
+ pcinfo->pddac[0][1] = (val >> 10) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr[0][2] = val & 0xf;
+ pcinfo->pddac[0][2] = (val >> 4) & 0x3f;
+
+ pcinfo->pwr[0][3] = 0;
+ pcinfo->pddac[0][3] = 0;
+
+ if (pd_gains > 1) {
+ /*
+ * Pd gain 0 is not the last pd gain
+ * so it only has 2 pd points.
+ * Continue wih pd gain 1.
+ */
+ pcinfo->pwr_i[1] = (val >> 10) & 0x1f;
+
+ pcinfo->pddac_i[1] = (val >> 15) & 0x1;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac_i[1] |= (val & 0x3F) << 1;
+
+ pcinfo->pwr[1][0] = (val >> 6) & 0xf;
+ pcinfo->pddac[1][0] = (val >> 10) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr[1][1] = val & 0xf;
+ pcinfo->pddac[1][1] = (val >> 4) & 0x3f;
+ pcinfo->pwr[1][2] = (val >> 10) & 0xf;
+
+ pcinfo->pddac[1][2] = (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac[1][2] |= (val & 0xF) << 2;
+
+ pcinfo->pwr[1][3] = 0;
+ pcinfo->pddac[1][3] = 0;
+ } else if (pd_gains == 1) {
+ /*
+ * Pd gain 0 is the last one so
+ * read the extra point.
+ */
+ pcinfo->pwr[0][3] = (val >> 10) & 0xf;
+
+ pcinfo->pddac[0][3] = (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac[0][3] |= (val & 0xF) << 2;
+ }
+
+ /*
+ * Proceed with the other pd_gains
+ * as above.
+ */
+ if (pd_gains > 2) {
+ pcinfo->pwr_i[2] = (val >> 4) & 0x1f;
+ pcinfo->pddac_i[2] = (val >> 9) & 0x7f;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr[2][0] = (val >> 0) & 0xf;
+ pcinfo->pddac[2][0] = (val >> 4) & 0x3f;
+ pcinfo->pwr[2][1] = (val >> 10) & 0xf;
+
+ pcinfo->pddac[2][1] = (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac[2][1] |= (val & 0xF) << 2;
+
+ pcinfo->pwr[2][2] = (val >> 4) & 0xf;
+ pcinfo->pddac[2][2] = (val >> 8) & 0x3f;
+
+ pcinfo->pwr[2][3] = 0;
+ pcinfo->pddac[2][3] = 0;
+ } else if (pd_gains == 2) {
+ pcinfo->pwr[1][3] = (val >> 4) & 0xf;
+ pcinfo->pddac[1][3] = (val >> 8) & 0x3f;
+ }
+
+ if (pd_gains > 3) {
+ pcinfo->pwr_i[3] = (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr_i[3] |= ((val >> 0) & 0x7) << 2;
+
+ pcinfo->pddac_i[3] = (val >> 3) & 0x7f;
+ pcinfo->pwr[3][0] = (val >> 10) & 0xf;
+ pcinfo->pddac[3][0] = (val >> 14) & 0x3;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac[3][0] |= (val & 0xF) << 2;
+ pcinfo->pwr[3][1] = (val >> 4) & 0xf;
+ pcinfo->pddac[3][1] = (val >> 8) & 0x3f;
+
+ pcinfo->pwr[3][2] = (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr[3][2] |= ((val >> 0) & 0x3) << 2;
+
+ pcinfo->pddac[3][2] = (val >> 2) & 0x3f;
+ pcinfo->pwr[3][3] = (val >> 8) & 0xf;
+
+ pcinfo->pddac[3][3] = (val >> 12) & 0xF;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac[3][3] |= ((val >> 0) & 0x3) << 4;
+ } else if (pd_gains == 3) {
+ pcinfo->pwr[2][3] = (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr[2][3] |= ((val >> 0) & 0x3) << 2;
+
+ pcinfo->pddac[2][3] = (val >> 2) & 0x3f;
+ }
+ }
+
+ return ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo);
+}
+
+
+/*
+ * Read per rate target power (this is the maximum tx power
+ * supported by the card). This info is used when setting
+ * tx power, no matter the channel.
+ *
+ * This also works for v5 EEPROMs.
+ */
+static int
+ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_rate_pcal_info *rate_pcal_info;
+ u8 *rate_target_pwr_num;
+ u32 offset;
+ u16 val;
+ int ret, i;
+
+ offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1);
+ rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode];
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version);
+ rate_pcal_info = ee->ee_rate_tpwr_a;
+ ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version);
+ rate_pcal_info = ee->ee_rate_tpwr_b;
+ ee->ee_rate_target_pwr_num[mode] = 2; /* 3rd is g mode's 1st */
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ offset += AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version);
+ rate_pcal_info = ee->ee_rate_tpwr_g;
+ ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_2GHZ_CHAN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Different freq mask for older eeproms (<= v3.2) */
+ if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) {
+ for (i = 0; i < (*rate_target_pwr_num); i++) {
+ AR5K_EEPROM_READ(offset++, val);
+ rate_pcal_info[i].freq =
+ ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode);
+
+ rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f);
+ rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+
+ if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
+ val == 0) {
+ (*rate_target_pwr_num) = i;
+ break;
+ }
+
+ rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7);
+ rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f);
+ rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f);
+ }
+ } else {
+ for (i = 0; i < (*rate_target_pwr_num); i++) {
+ AR5K_EEPROM_READ(offset++, val);
+ rate_pcal_info[i].freq =
+ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
+
+ rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f);
+ rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+
+ if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
+ val == 0) {
+ (*rate_target_pwr_num) = i;
+ break;
+ }
+
+ rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf;
+ rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f);
+ rate_pcal_info[i].target_power_54 = (val & 0x3f);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Read per channel calibration info from EEPROM
+ *
+ * This info is used to calibrate the baseband power table. Imagine
+ * that for each channel there is a power curve that's hw specific
+ * (depends on amplifier etc) and we try to "correct" this curve using
+ * offests we pass on to phy chip (baseband -> before amplifier) so that
+ * it can use accurate power values when setting tx power (takes amplifier's
+ * performance on each channel into account).
+ *
+ * EEPROM provides us with the offsets for some pre-calibrated channels
+ * and we have to interpolate to create the full table for these channels and
+ * also the table for any channel.
+ */
+static int
+ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ int (*read_pcal)(struct ath5k_hw *hw, int mode);
+ int mode;
+ int err;
+
+ if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) &&
+ (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 1))
+ read_pcal = ath5k_eeprom_read_pcal_info_5112;
+ else if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0) &&
+ (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 2))
+ read_pcal = ath5k_eeprom_read_pcal_info_2413;
+ else
+ read_pcal = ath5k_eeprom_read_pcal_info_5111;
+
+
+ for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G;
+ mode++) {
+ err = read_pcal(ah, mode);
+ if (err)
+ return err;
+
+ err = ath5k_eeprom_read_target_rate_pwr_info(ah, mode);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int
+ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *chinfo;
+ u8 pier, pdg;
+
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
+ return 0;
+ chinfo = ee->ee_pwr_cal_a;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
+ return 0;
+ chinfo = ee->ee_pwr_cal_b;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
+ return 0;
+ chinfo = ee->ee_pwr_cal_g;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
+ if (!chinfo[pier].pd_curves)
+ continue;
+
+ for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
+ struct ath5k_pdgain_info *pd =
+ &chinfo[pier].pd_curves[pdg];
+
+ if (pd != NULL) {
+ free(pd->pd_step);
+ free(pd->pd_pwr);
+ }
+ }
+
+ free(chinfo[pier].pd_curves);
+ }
+
+ return 0;
+}
+
+void
+ath5k_eeprom_detach(struct ath5k_hw *ah)
+{
+ u8 mode;
+
+ for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
+ ath5k_eeprom_free_pcal_info(ah, mode);
+}
+
+/* Read conformance test limits used for regulatory control */
+static int
+ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_edge_power *rep;
+ unsigned int fmask, pmask;
+ unsigned int ctl_mode;
+ int ret, i, j;
+ u32 offset;
+ u16 val;
+
+ pmask = AR5K_EEPROM_POWER_M;
+ fmask = AR5K_EEPROM_FREQ_M(ee->ee_version);
+ offset = AR5K_EEPROM_CTL(ee->ee_version);
+ ee->ee_ctls = AR5K_EEPROM_N_CTLS(ee->ee_version);
+ for (i = 0; i < ee->ee_ctls; i += 2) {
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_ctl[i] = (val >> 8) & 0xff;
+ ee->ee_ctl[i + 1] = val & 0xff;
+ }
+
+ offset = AR5K_EEPROM_GROUP8_OFFSET;
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0)
+ offset += AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) -
+ AR5K_EEPROM_GROUP5_OFFSET;
+ else
+ offset += AR5K_EEPROM_GROUPS_START(ee->ee_version);
+
+ rep = ee->ee_ctl_pwr;
+ for(i = 0; i < ee->ee_ctls; i++) {
+ switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) {
+ case AR5K_CTL_11A:
+ case AR5K_CTL_TURBO:
+ ctl_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ default:
+ ctl_mode = AR5K_EEPROM_MODE_11G;
+ break;
+ }
+ if (ee->ee_ctl[i] == 0) {
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3)
+ offset += 8;
+ else
+ offset += 7;
+ rep += AR5K_EEPROM_N_EDGES;
+ continue;
+ }
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
+ for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
+ AR5K_EEPROM_READ(offset++, val);
+ rep[j].freq = (val >> 8) & fmask;
+ rep[j + 1].freq = val & fmask;
+ }
+ for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
+ AR5K_EEPROM_READ(offset++, val);
+ rep[j].edge = (val >> 8) & pmask;
+ rep[j].flag = (val >> 14) & 1;
+ rep[j + 1].edge = val & pmask;
+ rep[j + 1].flag = (val >> 6) & 1;
+ }
+ } else {
+ AR5K_EEPROM_READ(offset++, val);
+ rep[0].freq = (val >> 9) & fmask;
+ rep[1].freq = (val >> 2) & fmask;
+ rep[2].freq = (val << 5) & fmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[2].freq |= (val >> 11) & 0x1f;
+ rep[3].freq = (val >> 4) & fmask;
+ rep[4].freq = (val << 3) & fmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[4].freq |= (val >> 13) & 0x7;
+ rep[5].freq = (val >> 6) & fmask;
+ rep[6].freq = (val << 1) & fmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[6].freq |= (val >> 15) & 0x1;
+ rep[7].freq = (val >> 8) & fmask;
+
+ rep[0].edge = (val >> 2) & pmask;
+ rep[1].edge = (val << 4) & pmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[1].edge |= (val >> 12) & 0xf;
+ rep[2].edge = (val >> 6) & pmask;
+ rep[3].edge = val & pmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[4].edge = (val >> 10) & pmask;
+ rep[5].edge = (val >> 4) & pmask;
+ rep[6].edge = (val << 2) & pmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[6].edge |= (val >> 14) & 0x3;
+ rep[7].edge = (val >> 8) & pmask;
+ }
+ for (j = 0; j < AR5K_EEPROM_N_EDGES; j++) {
+ rep[j].freq = ath5k_eeprom_bin2freq(ee,
+ rep[j].freq, ctl_mode);
+ }
+ rep += AR5K_EEPROM_N_EDGES;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Initialize eeprom power tables
+ */
+int
+ath5k_eeprom_init(struct ath5k_hw *ah)
+{
+ int err;
+
+ err = ath5k_eeprom_init_header(ah);
+ if (err < 0)
+ return err;
+
+ err = ath5k_eeprom_init_modes(ah);
+ if (err < 0)
+ return err;
+
+ err = ath5k_eeprom_read_pcal_info(ah);
+ if (err < 0)
+ return err;
+
+ err = ath5k_eeprom_read_ctl_info(ah);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+/*
+ * Read the MAC address from eeprom
+ */
+int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+{
+ u8 mac_d[ETH_ALEN] = {};
+ u32 total, offset;
+ u16 data;
+ int octet, ret;
+
+ ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
+ if (ret)
+ return ret;
+
+ for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
+ ret = ath5k_hw_eeprom_read(ah, offset, &data);
+ if (ret)
+ return ret;
+
+ total += data;
+ mac_d[octet + 1] = data & 0xff;
+ mac_d[octet] = data >> 8;
+ octet += 2;
+ }
+
+ if (!total || total == 3 * 0xffff)
+ return -EINVAL;
+
+ memcpy(mac, mac_d, ETH_ALEN);
+
+ return 0;
+}
+
+int ath5k_eeprom_is_hb63(struct ath5k_hw *ah)
+{
+ u16 data;
+
+ ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data);
+
+ if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && data)
+ return 1;
+ else
+ return 0;
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_gpio.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_gpio.c
new file mode 100644
index 00000000..2301ec70
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_gpio.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Lightly modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/****************\
+ GPIO Functions
+\****************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*
+ * Set GPIO inputs
+ */
+int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
+{
+ if (gpio >= AR5K_NUM_GPIO)
+ return -EINVAL;
+
+ ath5k_hw_reg_write(ah,
+ (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
+ | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR);
+
+ return 0;
+}
+
+/*
+ * Set GPIO outputs
+ */
+int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
+{
+ if (gpio >= AR5K_NUM_GPIO)
+ return -EINVAL;
+
+ ath5k_hw_reg_write(ah,
+ (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
+ | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR);
+
+ return 0;
+}
+
+/*
+ * Get GPIO state
+ */
+u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
+{
+ if (gpio >= AR5K_NUM_GPIO)
+ return 0xffffffff;
+
+ /* GPIO input magic */
+ return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) &
+ 0x1;
+}
+
+/*
+ * Set GPIO state
+ */
+int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
+{
+ u32 data;
+
+ if (gpio >= AR5K_NUM_GPIO)
+ return -EINVAL;
+
+ /* GPIO output magic */
+ data = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+
+ data &= ~(1 << gpio);
+ data |= (val & 1) << gpio;
+
+ ath5k_hw_reg_write(ah, data, AR5K_GPIODO);
+
+ return 0;
+}
+
+/*
+ * Initialize the GPIO interrupt (RFKill switch)
+ */
+void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
+ u32 interrupt_level)
+{
+ u32 data;
+
+ if (gpio >= AR5K_NUM_GPIO)
+ return;
+
+ /*
+ * Set the GPIO interrupt
+ */
+ data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &
+ ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH |
+ AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) |
+ (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA);
+
+ ath5k_hw_reg_write(ah, interrupt_level ? data :
+ (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR);
+
+ ah->ah_imr |= AR5K_IMR_GPIO;
+
+ /* Enable GPIO interrupts */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO);
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_initvals.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_initvals.c
new file mode 100644
index 00000000..8f3bd203
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_initvals.c
@@ -0,0 +1,1560 @@
+/*
+ * Initial register settings functions
+ *
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Lightly modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+#include <unistd.h>
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*
+ * Mode-independent initial register writes
+ */
+
+struct ath5k_ini {
+ u16 ini_register;
+ u32 ini_value;
+
+ enum {
+ AR5K_INI_WRITE = 0, /* Default */
+ AR5K_INI_READ = 1, /* Cleared on read */
+ } ini_mode;
+};
+
+/*
+ * Mode specific initial register values
+ */
+
+struct ath5k_ini_mode {
+ u16 mode_register;
+ u32 mode_value[5];
+};
+
+/* Initial register settings for AR5210 */
+static const struct ath5k_ini ar5210_ini[] = {
+ /* PCU and MAC registers */
+ { AR5K_NOQCU_TXDP0, 0, AR5K_INI_WRITE },
+ { AR5K_NOQCU_TXDP1, 0, AR5K_INI_WRITE },
+ { AR5K_RXDP, 0, AR5K_INI_WRITE },
+ { AR5K_CR, 0, AR5K_INI_WRITE },
+ { AR5K_ISR, 0, AR5K_INI_READ },
+ { AR5K_IMR, 0, AR5K_INI_WRITE },
+ { AR5K_IER, AR5K_IER_DISABLE, AR5K_INI_WRITE },
+ { AR5K_BSR, 0, AR5K_INI_READ },
+ { AR5K_TXCFG, AR5K_DMASIZE_128B, AR5K_INI_WRITE },
+ { AR5K_RXCFG, AR5K_DMASIZE_128B, AR5K_INI_WRITE },
+ { AR5K_CFG, AR5K_INIT_CFG, AR5K_INI_WRITE },
+ { AR5K_TOPS, 8, AR5K_INI_WRITE },
+ { AR5K_RXNOFRM, 8, AR5K_INI_WRITE },
+ { AR5K_RPGTO, 0, AR5K_INI_WRITE },
+ { AR5K_TXNOFRM, 0, AR5K_INI_WRITE },
+ { AR5K_SFR, 0, AR5K_INI_WRITE },
+ { AR5K_MIBC, 0, AR5K_INI_WRITE },
+ { AR5K_MISC, 0, AR5K_INI_WRITE },
+ { AR5K_RX_FILTER_5210, 0, AR5K_INI_WRITE },
+ { AR5K_MCAST_FILTER0_5210, 0, AR5K_INI_WRITE },
+ { AR5K_MCAST_FILTER1_5210, 0, AR5K_INI_WRITE },
+ { AR5K_TX_MASK0, 0, AR5K_INI_WRITE },
+ { AR5K_TX_MASK1, 0, AR5K_INI_WRITE },
+ { AR5K_CLR_TMASK, 0, AR5K_INI_WRITE },
+ { AR5K_TRIG_LVL, AR5K_TUNE_MIN_TX_FIFO_THRES, AR5K_INI_WRITE },
+ { AR5K_DIAG_SW_5210, 0, AR5K_INI_WRITE },
+ { AR5K_RSSI_THR, AR5K_TUNE_RSSI_THRES, AR5K_INI_WRITE },
+ { AR5K_TSF_L32_5210, 0, AR5K_INI_WRITE },
+ { AR5K_TIMER0_5210, 0, AR5K_INI_WRITE },
+ { AR5K_TIMER1_5210, 0xffffffff, AR5K_INI_WRITE },
+ { AR5K_TIMER2_5210, 0xffffffff, AR5K_INI_WRITE },
+ { AR5K_TIMER3_5210, 1, AR5K_INI_WRITE },
+ { AR5K_CFP_DUR_5210, 0, AR5K_INI_WRITE },
+ { AR5K_CFP_PERIOD_5210, 0, AR5K_INI_WRITE },
+ /* PHY registers */
+ { AR5K_PHY(0), 0x00000047, AR5K_INI_WRITE },
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(3), 0x09848ea6, AR5K_INI_WRITE },
+ { AR5K_PHY(4), 0x3d32e000, AR5K_INI_WRITE },
+ { AR5K_PHY(5), 0x0000076b, AR5K_INI_WRITE },
+ { AR5K_PHY_ACT, AR5K_PHY_ACT_DISABLE, AR5K_INI_WRITE },
+ { AR5K_PHY(8), 0x02020200, AR5K_INI_WRITE },
+ { AR5K_PHY(9), 0x00000e0e, AR5K_INI_WRITE },
+ { AR5K_PHY(10), 0x0a020201, AR5K_INI_WRITE },
+ { AR5K_PHY(11), 0x00036ffc, AR5K_INI_WRITE },
+ { AR5K_PHY(12), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(13), 0x00000e0e, AR5K_INI_WRITE },
+ { AR5K_PHY(14), 0x00000007, AR5K_INI_WRITE },
+ { AR5K_PHY(15), 0x00020100, AR5K_INI_WRITE },
+ { AR5K_PHY(16), 0x89630000, AR5K_INI_WRITE },
+ { AR5K_PHY(17), 0x1372169c, AR5K_INI_WRITE },
+ { AR5K_PHY(18), 0x0018b633, AR5K_INI_WRITE },
+ { AR5K_PHY(19), 0x1284613c, AR5K_INI_WRITE },
+ { AR5K_PHY(20), 0x0de8b8e0, AR5K_INI_WRITE },
+ { AR5K_PHY(21), 0x00074859, AR5K_INI_WRITE },
+ { AR5K_PHY(22), 0x7e80beba, AR5K_INI_WRITE },
+ { AR5K_PHY(23), 0x313a665e, AR5K_INI_WRITE },
+ { AR5K_PHY_AGCCTL, 0x00001d08, AR5K_INI_WRITE },
+ { AR5K_PHY(25), 0x0001ce00, AR5K_INI_WRITE },
+ { AR5K_PHY(26), 0x409a4190, AR5K_INI_WRITE },
+ { AR5K_PHY(28), 0x0000000f, AR5K_INI_WRITE },
+ { AR5K_PHY(29), 0x00000080, AR5K_INI_WRITE },
+ { AR5K_PHY(30), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_PHY(31), 0x00000018, AR5K_INI_WRITE }, /* 0x987c */
+ { AR5K_PHY(64), 0x00000000, AR5K_INI_WRITE }, /* 0x9900 */
+ { AR5K_PHY(65), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(66), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(67), 0x00800000, AR5K_INI_WRITE },
+ { AR5K_PHY(68), 0x00000003, AR5K_INI_WRITE },
+ /* BB gain table (64bytes) */
+ { AR5K_BB_GAIN(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(1), 0x00000020, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(2), 0x00000010, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(3), 0x00000030, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(4), 0x00000008, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(5), 0x00000028, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(6), 0x00000028, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(7), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(8), 0x00000024, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(9), 0x00000014, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(10), 0x00000034, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(11), 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(12), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(13), 0x00000002, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(14), 0x00000022, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(15), 0x00000012, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(16), 0x00000032, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(17), 0x0000000a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(18), 0x0000002a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(19), 0x00000001, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(20), 0x00000021, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(21), 0x00000011, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(22), 0x00000031, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(23), 0x00000009, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(24), 0x00000029, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(25), 0x00000005, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(26), 0x00000025, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(27), 0x00000015, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(28), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(29), 0x0000000d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(30), 0x0000002d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(31), 0x00000003, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(32), 0x00000023, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(33), 0x00000013, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(34), 0x00000033, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(35), 0x0000000b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(36), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(37), 0x00000007, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(38), 0x00000027, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(39), 0x00000017, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(40), 0x00000037, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(41), 0x0000000f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(42), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(43), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(44), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(45), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(46), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(47), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(48), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(49), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(50), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(51), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(52), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(53), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(54), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(55), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(56), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(57), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(58), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(59), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(60), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(61), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(62), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(63), 0x0000002f, AR5K_INI_WRITE },
+ /* 5110 RF gain table (64btes) */
+ { AR5K_RF_GAIN(0), 0x0000001d, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(1), 0x0000005d, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(2), 0x0000009d, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(3), 0x000000dd, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(4), 0x0000011d, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(5), 0x00000021, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(6), 0x00000061, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(7), 0x000000a1, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(8), 0x000000e1, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(9), 0x00000031, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(10), 0x00000071, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(11), 0x000000b1, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(12), 0x0000001c, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(13), 0x0000005c, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(14), 0x00000029, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(15), 0x00000069, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(16), 0x000000a9, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(17), 0x00000020, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(18), 0x00000019, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(19), 0x00000059, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(20), 0x00000099, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(21), 0x00000030, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(22), 0x00000005, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(23), 0x00000025, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(24), 0x00000065, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(25), 0x000000a5, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(26), 0x00000028, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(27), 0x00000068, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(28), 0x0000001f, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(29), 0x0000001e, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(30), 0x00000018, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(31), 0x00000058, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(32), 0x00000098, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(33), 0x00000003, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(34), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(35), 0x00000044, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(36), 0x00000084, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(37), 0x00000013, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(38), 0x00000012, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(39), 0x00000052, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(40), 0x00000092, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(41), 0x000000d2, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(42), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(43), 0x0000002a, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(44), 0x0000006a, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(45), 0x000000aa, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(46), 0x0000001b, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(47), 0x0000001a, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(48), 0x0000005a, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(49), 0x0000009a, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(50), 0x000000da, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(51), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(52), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(53), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(54), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(55), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(56), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(57), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(58), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(59), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(60), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(61), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(62), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(63), 0x00000006, AR5K_INI_WRITE },
+ /* PHY activation */
+ { AR5K_PHY(53), 0x00000020, AR5K_INI_WRITE },
+ { AR5K_PHY(51), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_PHY(50), 0x00060106, AR5K_INI_WRITE },
+ { AR5K_PHY(39), 0x0000006d, AR5K_INI_WRITE },
+ { AR5K_PHY(48), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(52), 0x00000014, AR5K_INI_WRITE },
+ { AR5K_PHY_ACT, AR5K_PHY_ACT_ENABLE, AR5K_INI_WRITE },
+};
+
+/* Initial register settings for AR5211 */
+static const struct ath5k_ini ar5211_ini[] = {
+ { AR5K_RXDP, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RTSD0, 0x84849c9c, AR5K_INI_WRITE },
+ { AR5K_RTSD1, 0x7c7c7c7c, AR5K_INI_WRITE },
+ { AR5K_RXCFG, 0x00000005, AR5K_INI_WRITE },
+ { AR5K_MIBC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TOPS, 0x00000008, AR5K_INI_WRITE },
+ { AR5K_RXNOFRM, 0x00000008, AR5K_INI_WRITE },
+ { AR5K_TXNOFRM, 0x00000010, AR5K_INI_WRITE },
+ { AR5K_RPGTO, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RFCNT, 0x0000001f, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(1), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(2), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(3), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(4), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(5), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(6), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(7), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(8), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(9), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_FP, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_STA_ID1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BSS_ID0, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BSS_ID1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RSSI_THR, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_CFP_PERIOD_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TIMER0_5211, 0x00000030, AR5K_INI_WRITE },
+ { AR5K_TIMER1_5211, 0x0007ffff, AR5K_INI_WRITE },
+ { AR5K_TIMER2_5211, 0x01ffffff, AR5K_INI_WRITE },
+ { AR5K_TIMER3_5211, 0x00000031, AR5K_INI_WRITE },
+ { AR5K_CFP_DUR_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RX_FILTER_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MCAST_FILTER0_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MCAST_FILTER1_5211, 0x00000002, AR5K_INI_WRITE },
+ { AR5K_DIAG_SW_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_ADDAC_TEST, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DEFAULT_ANTENNA, 0x00000000, AR5K_INI_WRITE },
+ /* PHY registers */
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(3), 0x2d849093, AR5K_INI_WRITE },
+ { AR5K_PHY(4), 0x7d32e000, AR5K_INI_WRITE },
+ { AR5K_PHY(5), 0x00000f6b, AR5K_INI_WRITE },
+ { AR5K_PHY_ACT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(11), 0x00026ffe, AR5K_INI_WRITE },
+ { AR5K_PHY(12), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(15), 0x00020100, AR5K_INI_WRITE },
+ { AR5K_PHY(16), 0x206a017a, AR5K_INI_WRITE },
+ { AR5K_PHY(19), 0x1284613c, AR5K_INI_WRITE },
+ { AR5K_PHY(21), 0x00000859, AR5K_INI_WRITE },
+ { AR5K_PHY(26), 0x409a4190, AR5K_INI_WRITE }, /* 0x9868 */
+ { AR5K_PHY(27), 0x050cb081, AR5K_INI_WRITE },
+ { AR5K_PHY(28), 0x0000000f, AR5K_INI_WRITE },
+ { AR5K_PHY(29), 0x00000080, AR5K_INI_WRITE },
+ { AR5K_PHY(30), 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_PHY(64), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(65), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(66), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(67), 0x00800000, AR5K_INI_WRITE },
+ { AR5K_PHY(68), 0x00000001, AR5K_INI_WRITE },
+ { AR5K_PHY(71), 0x0000092a, AR5K_INI_WRITE },
+ { AR5K_PHY_IQ, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(73), 0x00058a05, AR5K_INI_WRITE },
+ { AR5K_PHY(74), 0x00000001, AR5K_INI_WRITE },
+ { AR5K_PHY(75), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_PAPD_PROBE, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(77), 0x00000000, AR5K_INI_WRITE }, /* 0x9934 */
+ { AR5K_PHY(78), 0x00000000, AR5K_INI_WRITE }, /* 0x9938 */
+ { AR5K_PHY(79), 0x0000003f, AR5K_INI_WRITE }, /* 0x993c */
+ { AR5K_PHY(80), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_PHY(82), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(83), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(84), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_RADAR, 0x5d50f14c, AR5K_INI_WRITE },
+ { AR5K_PHY(86), 0x00000018, AR5K_INI_WRITE },
+ { AR5K_PHY(87), 0x004b6a8e, AR5K_INI_WRITE },
+ /* Initial Power table (32bytes)
+ * common on all cards/modes.
+ * Note: Table is rewritten during
+ * txpower setup later using calibration
+ * data etc. so next write is non-common */
+ { AR5K_PHY_PCDAC_TXPOWER(1), 0x06ff05ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(2), 0x07ff07ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(3), 0x08ff08ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(4), 0x09ff09ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(5), 0x0aff0aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(6), 0x0bff0bff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(7), 0x0cff0cff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(8), 0x0dff0dff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(9), 0x0fff0eff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(10), 0x12ff12ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(11), 0x14ff13ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(12), 0x16ff15ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(13), 0x19ff17ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(14), 0x1bff1aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(15), 0x1eff1dff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(16), 0x23ff20ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(17), 0x27ff25ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(18), 0x2cff29ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(19), 0x31ff2fff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(20), 0x37ff34ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(21), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(22), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(23), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(24), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(25), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(26), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(27), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(28), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(29), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(30), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(31), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_CCKTXCTL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(642), 0x503e4646, AR5K_INI_WRITE },
+ { AR5K_PHY_GAIN_2GHZ, 0x6480416c, AR5K_INI_WRITE },
+ { AR5K_PHY(644), 0x0199a003, AR5K_INI_WRITE },
+ { AR5K_PHY(645), 0x044cd610, AR5K_INI_WRITE },
+ { AR5K_PHY(646), 0x13800040, AR5K_INI_WRITE },
+ { AR5K_PHY(647), 0x1be00060, AR5K_INI_WRITE },
+ { AR5K_PHY(648), 0x0c53800a, AR5K_INI_WRITE },
+ { AR5K_PHY(649), 0x0014df3b, AR5K_INI_WRITE },
+ { AR5K_PHY(650), 0x000001b5, AR5K_INI_WRITE },
+ { AR5K_PHY(651), 0x00000020, AR5K_INI_WRITE },
+};
+
+/* Initial mode-specific settings for AR5211
+ * 5211 supports OFDM-only g (draft g) but we
+ * need to test it !
+ */
+static const struct ath5k_ini_mode ar5211_ini_mode[] = {
+ { AR5K_TXCFG,
+ /* a aTurbo b g (OFDM) */
+ { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(0),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(1),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(2),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(3),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(4),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(5),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(6),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(7),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(8),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(9),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_DCU_GBL_IFS_SLOT,
+ { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } },
+ { AR5K_DCU_GBL_IFS_SIFS,
+ { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } },
+ { AR5K_DCU_GBL_IFS_EIFS,
+ { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } },
+ { AR5K_DCU_GBL_IFS_MISC,
+ { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } },
+ { AR5K_TIME_OUT,
+ { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } },
+ { AR5K_USEC_5211,
+ { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } },
+ { AR5K_PHY_TURBO,
+ { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } },
+ { AR5K_PHY(8),
+ { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } },
+ { AR5K_PHY(9),
+ { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } },
+ { AR5K_PHY(10),
+ { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } },
+ { AR5K_PHY(13),
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY(14),
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY(17),
+ { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } },
+ { AR5K_PHY(18),
+ { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } },
+ { AR5K_PHY(20),
+ { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } },
+ { AR5K_PHY_SIG,
+ { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } },
+ { AR5K_PHY_AGCCTL,
+ { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } },
+ { AR5K_PHY_NF,
+ { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } },
+ { AR5K_PHY(70),
+ { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } },
+ { AR5K_PHY_PCDAC_TXPOWER_BASE,
+ { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } },
+ { AR5K_RF_BUFFER_CONTROL_4,
+ { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } },
+};
+
+/* Initial register settings for AR5212 */
+static const struct ath5k_ini ar5212_ini_common_start[] = {
+ { AR5K_RXDP, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RXCFG, 0x00000005, AR5K_INI_WRITE },
+ { AR5K_MIBC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TOPS, 0x00000008, AR5K_INI_WRITE },
+ { AR5K_RXNOFRM, 0x00000008, AR5K_INI_WRITE },
+ { AR5K_TXNOFRM, 0x00000010, AR5K_INI_WRITE },
+ { AR5K_RPGTO, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RFCNT, 0x0000001f, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(1), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(2), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(3), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(4), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(5), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(6), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(7), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(8), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(9), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_FP, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TXP, 0x00000000, AR5K_INI_WRITE },
+ /* Tx filter table 0 (32 entries) */
+ { AR5K_DCU_TX_FILTER_0(0), 0x00000000, AR5K_INI_WRITE }, /* DCU 0 */
+ { AR5K_DCU_TX_FILTER_0(1), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(2), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(3), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(4), 0x00000000, AR5K_INI_WRITE }, /* DCU 1 */
+ { AR5K_DCU_TX_FILTER_0(5), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(6), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(7), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(8), 0x00000000, AR5K_INI_WRITE }, /* DCU 2 */
+ { AR5K_DCU_TX_FILTER_0(9), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(10), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(11), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(12), 0x00000000, AR5K_INI_WRITE }, /* DCU 3 */
+ { AR5K_DCU_TX_FILTER_0(13), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(14), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(15), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(16), 0x00000000, AR5K_INI_WRITE }, /* DCU 4 */
+ { AR5K_DCU_TX_FILTER_0(17), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(18), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(19), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(20), 0x00000000, AR5K_INI_WRITE }, /* DCU 5 */
+ { AR5K_DCU_TX_FILTER_0(21), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(22), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(23), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(24), 0x00000000, AR5K_INI_WRITE }, /* DCU 6 */
+ { AR5K_DCU_TX_FILTER_0(25), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(26), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(27), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(28), 0x00000000, AR5K_INI_WRITE }, /* DCU 7 */
+ { AR5K_DCU_TX_FILTER_0(29), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(30), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(31), 0x00000000, AR5K_INI_WRITE },
+ /* Tx filter table 1 (16 entries) */
+ { AR5K_DCU_TX_FILTER_1(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(1), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(2), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(3), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(4), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(5), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(6), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(7), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(8), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(9), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(10), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(11), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(12), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(13), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(14), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(15), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_CLR, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_SET, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_CLR, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_SET, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_STA_ID1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BSS_ID0, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BSS_ID1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BEACON_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_CFP_PERIOD_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TIMER0_5211, 0x00000030, AR5K_INI_WRITE },
+ { AR5K_TIMER1_5211, 0x0007ffff, AR5K_INI_WRITE },
+ { AR5K_TIMER2_5211, 0x01ffffff, AR5K_INI_WRITE },
+ { AR5K_TIMER3_5211, 0x00000031, AR5K_INI_WRITE },
+ { AR5K_CFP_DUR_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RX_FILTER_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DIAG_SW_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_ADDAC_TEST, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DEFAULT_ANTENNA, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_FRAME_CTL_QOSM, 0x000fc78f, AR5K_INI_WRITE },
+ { AR5K_XRMODE, 0x2a82301a, AR5K_INI_WRITE },
+ { AR5K_XRDELAY, 0x05dc01e0, AR5K_INI_WRITE },
+ { AR5K_XRTIMEOUT, 0x1f402710, AR5K_INI_WRITE },
+ { AR5K_XRCHIRP, 0x01f40000, AR5K_INI_WRITE },
+ { AR5K_XRSTOMP, 0x00001e1c, AR5K_INI_WRITE },
+ { AR5K_SLEEP0, 0x0002aaaa, AR5K_INI_WRITE },
+ { AR5K_SLEEP1, 0x02005555, AR5K_INI_WRITE },
+ { AR5K_SLEEP2, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BSS_IDM0, 0xffffffff, AR5K_INI_WRITE },
+ { AR5K_BSS_IDM1, 0x0000ffff, AR5K_INI_WRITE },
+ { AR5K_TXPC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PROFCNT_TX, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PROFCNT_RX, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PROFCNT_RXCLR, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PROFCNT_CYCLE, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUIET_CTL1, 0x00000088, AR5K_INI_WRITE },
+ /* Initial rate duration table (32 entries )*/
+ { AR5K_RATE_DUR(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(1), 0x0000008c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(2), 0x000000e4, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(3), 0x000002d5, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(4), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(5), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(6), 0x000000a0, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(7), 0x000001c9, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(8), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(9), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(10), 0x00000030, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(11), 0x0000003c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(12), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(13), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(14), 0x00000030, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(15), 0x0000003c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(16), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(17), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(18), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(19), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(20), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(21), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(22), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(23), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(24), 0x000000d5, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(25), 0x000000df, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(26), 0x00000102, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(27), 0x0000013a, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(28), 0x00000075, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(29), 0x0000007f, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(30), 0x000000a2, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(31), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUIET_CTL2, 0x00010002, AR5K_INI_WRITE },
+ { AR5K_TSF_PARM, 0x00000001, AR5K_INI_WRITE },
+ { AR5K_QOS_NOACK, 0x000000c0, AR5K_INI_WRITE },
+ { AR5K_PHY_ERR_FIL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_XRLAT_TX, 0x00000168, AR5K_INI_WRITE },
+ { AR5K_ACKSIFS, 0x00000000, AR5K_INI_WRITE },
+ /* Rate -> db table
+ * notice ...03<-02<-01<-00 ! */
+ { AR5K_RATE2DB(0), 0x03020100, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(1), 0x07060504, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(2), 0x0b0a0908, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(3), 0x0f0e0d0c, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(4), 0x13121110, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(5), 0x17161514, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(6), 0x1b1a1918, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(7), 0x1f1e1d1c, AR5K_INI_WRITE },
+ /* Db -> Rate table */
+ { AR5K_DB2RATE(0), 0x03020100, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(1), 0x07060504, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(2), 0x0b0a0908, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(3), 0x0f0e0d0c, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(4), 0x13121110, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(5), 0x17161514, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(6), 0x1b1a1918, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(7), 0x1f1e1d1c, AR5K_INI_WRITE },
+ /* PHY registers (Common settings
+ * for all chips/modes) */
+ { AR5K_PHY(3), 0xad848e19, AR5K_INI_WRITE },
+ { AR5K_PHY(4), 0x7d28e000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_3, 0x9c0a9f6b, AR5K_INI_WRITE },
+ { AR5K_PHY_ACT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(16), 0x206a017a, AR5K_INI_WRITE },
+ { AR5K_PHY(21), 0x00000859, AR5K_INI_WRITE },
+ { AR5K_PHY_BIN_MASK_1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_BIN_MASK_2, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_BIN_MASK_3, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_BIN_MASK_CTL, 0x00800000, AR5K_INI_WRITE },
+ { AR5K_PHY_ANT_CTL, 0x00000001, AR5K_INI_WRITE },
+ /*{ AR5K_PHY(71), 0x0000092a, AR5K_INI_WRITE },*/ /* Old value */
+ { AR5K_PHY_MAX_RX_LEN, 0x00000c80, AR5K_INI_WRITE },
+ { AR5K_PHY_IQ, 0x05100000, AR5K_INI_WRITE },
+ { AR5K_PHY_WARM_RESET, 0x00000001, AR5K_INI_WRITE },
+ { AR5K_PHY_CTL, 0x00000004, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE1, 0x1e1f2022, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE2, 0x0a0b0c0d, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE_MAX, 0x0000003f, AR5K_INI_WRITE },
+ { AR5K_PHY(82), 0x9280b212, AR5K_INI_WRITE },
+ { AR5K_PHY_RADAR, 0x5d50e188, AR5K_INI_WRITE },
+ /*{ AR5K_PHY(86), 0x000000ff, AR5K_INI_WRITE },*/
+ { AR5K_PHY(87), 0x004b6a8e, AR5K_INI_WRITE },
+ { AR5K_PHY_NFTHRES, 0x000003ce, AR5K_INI_WRITE },
+ { AR5K_PHY_RESTART, 0x192fb515, AR5K_INI_WRITE },
+ { AR5K_PHY(94), 0x00000001, AR5K_INI_WRITE },
+ { AR5K_PHY_RFBUS_REQ, 0x00000000, AR5K_INI_WRITE },
+ /*{ AR5K_PHY(644), 0x0080a333, AR5K_INI_WRITE },*/ /* Old value */
+ /*{ AR5K_PHY(645), 0x00206c10, AR5K_INI_WRITE },*/ /* Old value */
+ { AR5K_PHY(644), 0x00806333, AR5K_INI_WRITE },
+ { AR5K_PHY(645), 0x00106c10, AR5K_INI_WRITE },
+ { AR5K_PHY(646), 0x009c4060, AR5K_INI_WRITE },
+ /* { AR5K_PHY(647), 0x1483800a, AR5K_INI_WRITE }, */
+ /* { AR5K_PHY(648), 0x01831061, AR5K_INI_WRITE }, */ /* Old value */
+ { AR5K_PHY(648), 0x018830c6, AR5K_INI_WRITE },
+ { AR5K_PHY(649), 0x00000400, AR5K_INI_WRITE },
+ /*{ AR5K_PHY(650), 0x000001b5, AR5K_INI_WRITE },*/
+ { AR5K_PHY(651), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE3, 0x20202020, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE2, 0x20202020, AR5K_INI_WRITE },
+ /*{ AR5K_PHY(655), 0x13c889af, AR5K_INI_WRITE },*/
+ { AR5K_PHY(656), 0x38490a20, AR5K_INI_WRITE },
+ { AR5K_PHY(657), 0x00007bb6, AR5K_INI_WRITE },
+ { AR5K_PHY(658), 0x0fff3ffc, AR5K_INI_WRITE },
+};
+
+/* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */
+static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
+ { AR5K_QUEUE_DFS_LOCAL_IFS(0),
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(1),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(2),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(3),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(4),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(5),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(6),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(7),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(8),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(9),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_DCU_GBL_IFS_SIFS,
+ { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } },
+ { AR5K_DCU_GBL_IFS_SLOT,
+ { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } },
+ { AR5K_DCU_GBL_IFS_EIFS,
+ { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } },
+ { AR5K_DCU_GBL_IFS_MISC,
+ { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } },
+ { AR5K_TIME_OUT,
+ { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } },
+ { AR5K_PHY_TURBO,
+ { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } },
+ { AR5K_PHY(8),
+ { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } },
+ { AR5K_PHY_RF_CTL2,
+ { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY_SETTLING,
+ { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } },
+ { AR5K_PHY_AGCCTL,
+ { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } },
+ { AR5K_PHY_NF,
+ { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
+ { AR5K_PHY_WEAK_OFDM_HIGH_THR,
+ { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } },
+ { AR5K_PHY(70),
+ { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } },
+ { AR5K_PHY_OFDM_SELFCORR,
+ { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } },
+ { 0xa230,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } },
+};
+
+/* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */
+static const struct ath5k_ini_mode rf5111_ini_mode_end[] = {
+ { AR5K_TXCFG,
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
+ { AR5K_USEC_5211,
+ { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } },
+ { AR5K_PHY_RF_CTL3,
+ { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } },
+ { AR5K_PHY_RF_CTL4,
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY_PA_CTL,
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY_GAIN,
+ { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } },
+ { AR5K_PHY_DESIRED_SIZE,
+ { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
+ { AR5K_PHY_SIG,
+ { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } },
+ { AR5K_PHY_WEAK_OFDM_LOW_THR,
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } },
+ { AR5K_PHY_GAIN_2GHZ,
+ { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } },
+ { AR5K_PHY_CCK_RX_CTL_4,
+ { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
+};
+
+static const struct ath5k_ini rf5111_ini_common_end[] = {
+ { AR5K_DCU_FP, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_ADC_CTL, 0x00022ffe, AR5K_INI_WRITE },
+ { 0x983c, 0x00020100, AR5K_INI_WRITE },
+ { AR5K_PHY_GAIN_OFFSET, 0x1284613c, AR5K_INI_WRITE },
+ { AR5K_PHY_PAPD_PROBE, 0x00004883, AR5K_INI_WRITE },
+ { 0x9940, 0x00000004, AR5K_INI_WRITE },
+ { 0x9958, 0x000000ff, AR5K_INI_WRITE },
+ { 0x9974, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_SPENDING, 0x00000018, AR5K_INI_WRITE },
+ { AR5K_PHY_CCKTXCTL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_CCK_CROSSCORR, 0xd03e6788, AR5K_INI_WRITE },
+ { AR5K_PHY_DAG_CCK_CTL, 0x000001b5, AR5K_INI_WRITE },
+ { 0xa23c, 0x13c889af, AR5K_INI_WRITE },
+};
+
+/* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */
+static const struct ath5k_ini_mode rf5112_ini_mode_end[] = {
+ { AR5K_TXCFG,
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
+ { AR5K_USEC_5211,
+ { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+ { AR5K_PHY_RF_CTL3,
+ { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+ { AR5K_PHY_RF_CTL4,
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY_PA_CTL,
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY_GAIN,
+ { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } },
+ { AR5K_PHY_DESIRED_SIZE,
+ { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
+ { AR5K_PHY_SIG,
+ { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } },
+ { AR5K_PHY_WEAK_OFDM_LOW_THR,
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } },
+ { AR5K_PHY_CCKTXCTL,
+ { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } },
+ { AR5K_PHY_CCK_CROSSCORR,
+ { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { AR5K_PHY_GAIN_2GHZ,
+ { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } },
+ { AR5K_PHY_CCK_RX_CTL_4,
+ { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
+};
+
+static const struct ath5k_ini rf5112_ini_common_end[] = {
+ { AR5K_DCU_FP, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_ADC_CTL, 0x00022ffe, AR5K_INI_WRITE },
+ { 0x983c, 0x00020100, AR5K_INI_WRITE },
+ { AR5K_PHY_GAIN_OFFSET, 0x1284613c, AR5K_INI_WRITE },
+ { AR5K_PHY_PAPD_PROBE, 0x00004882, AR5K_INI_WRITE },
+ { 0x9940, 0x00000004, AR5K_INI_WRITE },
+ { 0x9958, 0x000000ff, AR5K_INI_WRITE },
+ { 0x9974, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_DAG_CCK_CTL, 0x000001b5, AR5K_INI_WRITE },
+ { 0xa23c, 0x13c889af, AR5K_INI_WRITE },
+};
+
+/* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */
+static const struct ath5k_ini_mode rf5413_ini_mode_end[] = {
+ { AR5K_TXCFG,
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+ { AR5K_USEC_5211,
+ { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+ { AR5K_PHY_RF_CTL3,
+ { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+ { AR5K_PHY_RF_CTL4,
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY_PA_CTL,
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY_GAIN,
+ { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } },
+ { AR5K_PHY_DESIRED_SIZE,
+ { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
+ { AR5K_PHY_SIG,
+ { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
+ { AR5K_PHY_WEAK_OFDM_LOW_THR,
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+ { AR5K_PHY_CCKTXCTL,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY_CCK_CROSSCORR,
+ { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { AR5K_PHY_GAIN_2GHZ,
+ { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } },
+ { AR5K_PHY_CCK_RX_CTL_4,
+ { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+ { 0xa300,
+ { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } },
+ { 0xa304,
+ { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } },
+ { 0xa308,
+ { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } },
+ { 0xa30c,
+ { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
+ { 0xa310,
+ { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } },
+ { 0xa314,
+ { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
+ { 0xa318,
+ { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
+ { 0xa31c,
+ { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } },
+ { 0xa320,
+ { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } },
+ { 0xa324,
+ { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } },
+ { 0xa328,
+ { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } },
+ { 0xa32c,
+ { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } },
+ { 0xa330,
+ { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } },
+ { 0xa334,
+ { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } },
+};
+
+static const struct ath5k_ini rf5413_ini_common_end[] = {
+ { AR5K_DCU_FP, 0x000003e0, AR5K_INI_WRITE },
+ { AR5K_5414_CBCFG, 0x00000010, AR5K_INI_WRITE },
+ { AR5K_SEQ_MASK, 0x0000000f, AR5K_INI_WRITE },
+ { 0x809c, 0x00000000, AR5K_INI_WRITE },
+ { 0x80a0, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MIC_QOS_CTL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MIC_QOS_SEL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MISC_MODE, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_OFDM_FIL_CNT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_CCK_FIL_CNT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT1_MASK, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT2, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT2_MASK, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TSF_THRES, 0x00000000, AR5K_INI_WRITE },
+ { 0x8140, 0x800003f9, AR5K_INI_WRITE },
+ { 0x8144, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_ADC_CTL, 0x0000a000, AR5K_INI_WRITE },
+ { 0x983c, 0x00200400, AR5K_INI_WRITE },
+ { AR5K_PHY_GAIN_OFFSET, 0x1284233c, AR5K_INI_WRITE },
+ { AR5K_PHY_SCR, 0x0000001f, AR5K_INI_WRITE },
+ { AR5K_PHY_SLMT, 0x00000080, AR5K_INI_WRITE },
+ { AR5K_PHY_SCAL, 0x0000000e, AR5K_INI_WRITE },
+ { 0x9958, 0x00081fff, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_7, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_8, 0x02800000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_11, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000, AR5K_INI_WRITE },
+ { 0x99e4, 0xaaaaaaaa, AR5K_INI_WRITE },
+ { 0x99e8, 0x3c466478, AR5K_INI_WRITE },
+ { 0x99ec, 0x000000aa, AR5K_INI_WRITE },
+ { AR5K_PHY_SCLOCK, 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_PHY_SDELAY, 0x000000ff, AR5K_INI_WRITE },
+ { AR5K_PHY_SPENDING, 0x00000014, AR5K_INI_WRITE },
+ { AR5K_PHY_DAG_CCK_CTL, 0x000009b5, AR5K_INI_WRITE },
+ { 0xa23c, 0x93c889af, AR5K_INI_WRITE },
+ { AR5K_PHY_FAST_ADC, 0x00000001, AR5K_INI_WRITE },
+ { 0xa250, 0x0000a000, AR5K_INI_WRITE },
+ { AR5K_PHY_BLUETOOTH, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TPC_RG1, 0x0cc75380, AR5K_INI_WRITE },
+ { 0xa25c, 0x0f0f0f01, AR5K_INI_WRITE },
+ { 0xa260, 0x5f690f01, AR5K_INI_WRITE },
+ { 0xa264, 0x00418a11, AR5K_INI_WRITE },
+ { 0xa268, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TPC_RG5, 0x0c30c16a, AR5K_INI_WRITE },
+ { 0xa270, 0x00820820, AR5K_INI_WRITE },
+ { 0xa274, 0x081b7caa, AR5K_INI_WRITE },
+ { 0xa278, 0x1ce739ce, AR5K_INI_WRITE },
+ { 0xa27c, 0x051701ce, AR5K_INI_WRITE },
+ { 0xa338, 0x00000000, AR5K_INI_WRITE },
+ { 0xa33c, 0x00000000, AR5K_INI_WRITE },
+ { 0xa340, 0x00000000, AR5K_INI_WRITE },
+ { 0xa344, 0x00000000, AR5K_INI_WRITE },
+ { 0xa348, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa34c, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa350, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa354, 0x0003ffff, AR5K_INI_WRITE },
+ { 0xa358, 0x79a8aa1f, AR5K_INI_WRITE },
+ { 0xa35c, 0x066c420f, AR5K_INI_WRITE },
+ { 0xa360, 0x0f282207, AR5K_INI_WRITE },
+ { 0xa364, 0x17601685, AR5K_INI_WRITE },
+ { 0xa368, 0x1f801104, AR5K_INI_WRITE },
+ { 0xa36c, 0x37a00c03, AR5K_INI_WRITE },
+ { 0xa370, 0x3fc40883, AR5K_INI_WRITE },
+ { 0xa374, 0x57c00803, AR5K_INI_WRITE },
+ { 0xa378, 0x5fd80682, AR5K_INI_WRITE },
+ { 0xa37c, 0x7fe00482, AR5K_INI_WRITE },
+ { 0xa380, 0x7f3c7bba, AR5K_INI_WRITE },
+ { 0xa384, 0xf3307ff0, AR5K_INI_WRITE },
+};
+
+/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */
+/* XXX: a mode ? */
+static const struct ath5k_ini_mode rf2413_ini_mode_end[] = {
+ { AR5K_TXCFG,
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+ { AR5K_USEC_5211,
+ { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+ { AR5K_PHY_RF_CTL3,
+ { 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 } },
+ { AR5K_PHY_RF_CTL4,
+ { 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 } },
+ { AR5K_PHY_PA_CTL,
+ { 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a } },
+ { AR5K_PHY_GAIN,
+ { 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 } },
+ { AR5K_PHY_DESIRED_SIZE,
+ { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da } },
+ { AR5K_PHY_SIG,
+ { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e } },
+ { AR5K_PHY_WEAK_OFDM_LOW_THR,
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+ { AR5K_PHY_CCKTXCTL,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY_CCK_CROSSCORR,
+ { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { AR5K_PHY_GAIN_2GHZ,
+ { 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 } },
+ { AR5K_PHY_CCK_RX_CTL_4,
+ { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+};
+
+static const struct ath5k_ini rf2413_ini_common_end[] = {
+ { AR5K_DCU_FP, 0x000003e0, AR5K_INI_WRITE },
+ { AR5K_SEQ_MASK, 0x0000000f, AR5K_INI_WRITE },
+ { AR5K_MIC_QOS_CTL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MIC_QOS_SEL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MISC_MODE, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_OFDM_FIL_CNT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_CCK_FIL_CNT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT1_MASK, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT2, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT2_MASK, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TSF_THRES, 0x00000000, AR5K_INI_WRITE },
+ { 0x8140, 0x800000a8, AR5K_INI_WRITE },
+ { 0x8144, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_ADC_CTL, 0x0000a000, AR5K_INI_WRITE },
+ { 0x983c, 0x00200400, AR5K_INI_WRITE },
+ { AR5K_PHY_GAIN_OFFSET, 0x1284233c, AR5K_INI_WRITE },
+ { AR5K_PHY_SCR, 0x0000001f, AR5K_INI_WRITE },
+ { AR5K_PHY_SLMT, 0x00000080, AR5K_INI_WRITE },
+ { AR5K_PHY_SCAL, 0x0000000e, AR5K_INI_WRITE },
+ { 0x9958, 0x000000ff, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_7, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_8, 0x02800000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_11, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000, AR5K_INI_WRITE },
+ { 0x99e4, 0xaaaaaaaa, AR5K_INI_WRITE },
+ { 0x99e8, 0x3c466478, AR5K_INI_WRITE },
+ { 0x99ec, 0x000000aa, AR5K_INI_WRITE },
+ { AR5K_PHY_SCLOCK, 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_PHY_SDELAY, 0x000000ff, AR5K_INI_WRITE },
+ { AR5K_PHY_SPENDING, 0x00000014, AR5K_INI_WRITE },
+ { AR5K_PHY_DAG_CCK_CTL, 0x000009b5, AR5K_INI_WRITE },
+ { 0xa23c, 0x93c889af, AR5K_INI_WRITE },
+ { AR5K_PHY_FAST_ADC, 0x00000001, AR5K_INI_WRITE },
+ { 0xa250, 0x0000a000, AR5K_INI_WRITE },
+ { AR5K_PHY_BLUETOOTH, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TPC_RG1, 0x0cc75380, AR5K_INI_WRITE },
+ { 0xa25c, 0x0f0f0f01, AR5K_INI_WRITE },
+ { 0xa260, 0x5f690f01, AR5K_INI_WRITE },
+ { 0xa264, 0x00418a11, AR5K_INI_WRITE },
+ { 0xa268, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TPC_RG5, 0x0c30c16a, AR5K_INI_WRITE },
+ { 0xa270, 0x00820820, AR5K_INI_WRITE },
+ { 0xa274, 0x001b7caa, AR5K_INI_WRITE },
+ { 0xa278, 0x1ce739ce, AR5K_INI_WRITE },
+ { 0xa27c, 0x051701ce, AR5K_INI_WRITE },
+ { 0xa300, 0x18010000, AR5K_INI_WRITE },
+ { 0xa304, 0x30032602, AR5K_INI_WRITE },
+ { 0xa308, 0x48073e06, AR5K_INI_WRITE },
+ { 0xa30c, 0x560b4c0a, AR5K_INI_WRITE },
+ { 0xa310, 0x641a600f, AR5K_INI_WRITE },
+ { 0xa314, 0x784f6e1b, AR5K_INI_WRITE },
+ { 0xa318, 0x868f7c5a, AR5K_INI_WRITE },
+ { 0xa31c, 0x8ecf865b, AR5K_INI_WRITE },
+ { 0xa320, 0x9d4f970f, AR5K_INI_WRITE },
+ { 0xa324, 0xa5cfa18f, AR5K_INI_WRITE },
+ { 0xa328, 0xb55faf1f, AR5K_INI_WRITE },
+ { 0xa32c, 0xbddfb99f, AR5K_INI_WRITE },
+ { 0xa330, 0xcd7fc73f, AR5K_INI_WRITE },
+ { 0xa334, 0xd5ffd1bf, AR5K_INI_WRITE },
+ { 0xa338, 0x00000000, AR5K_INI_WRITE },
+ { 0xa33c, 0x00000000, AR5K_INI_WRITE },
+ { 0xa340, 0x00000000, AR5K_INI_WRITE },
+ { 0xa344, 0x00000000, AR5K_INI_WRITE },
+ { 0xa348, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa34c, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa350, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa354, 0x0003ffff, AR5K_INI_WRITE },
+ { 0xa358, 0x79a8aa1f, AR5K_INI_WRITE },
+ { 0xa35c, 0x066c420f, AR5K_INI_WRITE },
+ { 0xa360, 0x0f282207, AR5K_INI_WRITE },
+ { 0xa364, 0x17601685, AR5K_INI_WRITE },
+ { 0xa368, 0x1f801104, AR5K_INI_WRITE },
+ { 0xa36c, 0x37a00c03, AR5K_INI_WRITE },
+ { 0xa370, 0x3fc40883, AR5K_INI_WRITE },
+ { 0xa374, 0x57c00803, AR5K_INI_WRITE },
+ { 0xa378, 0x5fd80682, AR5K_INI_WRITE },
+ { 0xa37c, 0x7fe00482, AR5K_INI_WRITE },
+ { 0xa380, 0x7f3c7bba, AR5K_INI_WRITE },
+ { 0xa384, 0xf3307ff0, AR5K_INI_WRITE },
+};
+
+/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */
+/* XXX: a mode ? */
+static const struct ath5k_ini_mode rf2425_ini_mode_end[] = {
+ { AR5K_TXCFG,
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+ { AR5K_USEC_5211,
+ { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+ { AR5K_PHY_TURBO,
+ { 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 } },
+ { AR5K_PHY_RF_CTL3,
+ { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+ { AR5K_PHY_RF_CTL4,
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY_PA_CTL,
+ { 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY_SETTLING,
+ { 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 } },
+ { AR5K_PHY_GAIN,
+ { 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 } },
+ { AR5K_PHY_DESIRED_SIZE,
+ { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
+ { AR5K_PHY_SIG,
+ { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
+ { AR5K_PHY_WEAK_OFDM_LOW_THR,
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+ { AR5K_PHY_CCKTXCTL,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY_CCK_CROSSCORR,
+ { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { AR5K_PHY_GAIN_2GHZ,
+ { 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 } },
+ { AR5K_PHY_CCK_RX_CTL_4,
+ { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+ { 0xa324,
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+ { 0xa328,
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+ { 0xa32c,
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+ { 0xa330,
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+ { 0xa334,
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+};
+
+static const struct ath5k_ini rf2425_ini_common_end[] = {
+ { AR5K_DCU_FP, 0x000003e0, AR5K_INI_WRITE },
+ { AR5K_SEQ_MASK, 0x0000000f, AR5K_INI_WRITE },
+ { 0x809c, 0x00000000, AR5K_INI_WRITE },
+ { 0x80a0, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MIC_QOS_CTL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MIC_QOS_SEL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MISC_MODE, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_OFDM_FIL_CNT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_CCK_FIL_CNT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT1_MASK, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT2, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT2_MASK, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TSF_THRES, 0x00000000, AR5K_INI_WRITE },
+ { 0x8140, 0x800003f9, AR5K_INI_WRITE },
+ { 0x8144, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_ADC_CTL, 0x0000a000, AR5K_INI_WRITE },
+ { 0x983c, 0x00200400, AR5K_INI_WRITE },
+ { AR5K_PHY_GAIN_OFFSET, 0x1284233c, AR5K_INI_WRITE },
+ { AR5K_PHY_SCR, 0x0000001f, AR5K_INI_WRITE },
+ { AR5K_PHY_SLMT, 0x00000080, AR5K_INI_WRITE },
+ { AR5K_PHY_SCAL, 0x0000000e, AR5K_INI_WRITE },
+ { 0x9958, 0x00081fff, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_7, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_8, 0x02800000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_11, 0x00000000, AR5K_INI_WRITE },
+ { 0x99dc, 0xfebadbe8, AR5K_INI_WRITE },
+ { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000, AR5K_INI_WRITE },
+ { 0x99e4, 0xaaaaaaaa, AR5K_INI_WRITE },
+ { 0x99e8, 0x3c466478, AR5K_INI_WRITE },
+ { 0x99ec, 0x000000aa, AR5K_INI_WRITE },
+ { AR5K_PHY_SCLOCK, 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_PHY_SDELAY, 0x000000ff, AR5K_INI_WRITE },
+ { AR5K_PHY_SPENDING, 0x00000014, AR5K_INI_WRITE },
+ { AR5K_PHY_DAG_CCK_CTL, 0x000009b5, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE3, 0x20202020, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE4, 0x20202020, AR5K_INI_WRITE },
+ { 0xa23c, 0x93c889af, AR5K_INI_WRITE },
+ { AR5K_PHY_FAST_ADC, 0x00000001, AR5K_INI_WRITE },
+ { 0xa250, 0x0000a000, AR5K_INI_WRITE },
+ { AR5K_PHY_BLUETOOTH, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TPC_RG1, 0x0cc75380, AR5K_INI_WRITE },
+ { 0xa25c, 0x0f0f0f01, AR5K_INI_WRITE },
+ { 0xa260, 0x5f690f01, AR5K_INI_WRITE },
+ { 0xa264, 0x00418a11, AR5K_INI_WRITE },
+ { 0xa268, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TPC_RG5, 0x0c30c166, AR5K_INI_WRITE },
+ { 0xa270, 0x00820820, AR5K_INI_WRITE },
+ { 0xa274, 0x081a3caa, AR5K_INI_WRITE },
+ { 0xa278, 0x1ce739ce, AR5K_INI_WRITE },
+ { 0xa27c, 0x051701ce, AR5K_INI_WRITE },
+ { 0xa300, 0x16010000, AR5K_INI_WRITE },
+ { 0xa304, 0x2c032402, AR5K_INI_WRITE },
+ { 0xa308, 0x48433e42, AR5K_INI_WRITE },
+ { 0xa30c, 0x5a0f500b, AR5K_INI_WRITE },
+ { 0xa310, 0x6c4b624a, AR5K_INI_WRITE },
+ { 0xa314, 0x7e8b748a, AR5K_INI_WRITE },
+ { 0xa318, 0x96cf8ccb, AR5K_INI_WRITE },
+ { 0xa31c, 0xa34f9d0f, AR5K_INI_WRITE },
+ { 0xa320, 0xa7cfa58f, AR5K_INI_WRITE },
+ { 0xa348, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa34c, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa350, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa354, 0x0003ffff, AR5K_INI_WRITE },
+ { 0xa358, 0x79a8aa1f, AR5K_INI_WRITE },
+ { 0xa35c, 0x066c420f, AR5K_INI_WRITE },
+ { 0xa360, 0x0f282207, AR5K_INI_WRITE },
+ { 0xa364, 0x17601685, AR5K_INI_WRITE },
+ { 0xa368, 0x1f801104, AR5K_INI_WRITE },
+ { 0xa36c, 0x37a00c03, AR5K_INI_WRITE },
+ { 0xa370, 0x3fc40883, AR5K_INI_WRITE },
+ { 0xa374, 0x57c00803, AR5K_INI_WRITE },
+ { 0xa378, 0x5fd80682, AR5K_INI_WRITE },
+ { 0xa37c, 0x7fe00482, AR5K_INI_WRITE },
+ { 0xa380, 0x7f3c7bba, AR5K_INI_WRITE },
+ { 0xa384, 0xf3307ff0, AR5K_INI_WRITE },
+};
+
+/*
+ * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with
+ * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI)
+ */
+
+/* RF5111 Initial BaseBand Gain settings */
+static const struct ath5k_ini rf5111_ini_bbgain[] = {
+ { AR5K_BB_GAIN(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(1), 0x00000020, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(2), 0x00000010, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(3), 0x00000030, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(4), 0x00000008, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(5), 0x00000028, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(6), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(7), 0x00000024, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(8), 0x00000014, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(9), 0x00000034, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(10), 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(11), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(12), 0x00000002, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(13), 0x00000022, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(14), 0x00000012, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(15), 0x00000032, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(16), 0x0000000a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(17), 0x0000002a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(18), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(19), 0x00000026, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(20), 0x00000016, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(21), 0x00000036, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(22), 0x0000000e, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(23), 0x0000002e, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(24), 0x00000001, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(25), 0x00000021, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(26), 0x00000011, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(27), 0x00000031, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(28), 0x00000009, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(29), 0x00000029, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(30), 0x00000005, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(31), 0x00000025, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(32), 0x00000015, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(33), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(34), 0x0000000d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(35), 0x0000002d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(36), 0x00000003, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(37), 0x00000023, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(38), 0x00000013, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(39), 0x00000033, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(40), 0x0000000b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(41), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(42), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(43), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(44), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(45), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(46), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(47), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(48), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(49), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(50), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(51), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(52), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(53), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(54), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(55), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(56), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(57), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(58), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(59), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(60), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(61), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(62), 0x00000002, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(63), 0x00000016, AR5K_INI_WRITE },
+};
+
+/* RF5112 Initial BaseBand Gain settings (Same for RF5413/5414+) */
+static const struct ath5k_ini rf5112_ini_bbgain[] = {
+ { AR5K_BB_GAIN(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(1), 0x00000001, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(2), 0x00000002, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(3), 0x00000003, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(4), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(5), 0x00000005, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(6), 0x00000008, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(7), 0x00000009, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(8), 0x0000000a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(9), 0x0000000b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(10), 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(11), 0x0000000d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(12), 0x00000010, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(13), 0x00000011, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(14), 0x00000012, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(15), 0x00000013, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(16), 0x00000014, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(17), 0x00000015, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(18), 0x00000018, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(19), 0x00000019, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(20), 0x0000001a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(21), 0x0000001b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(22), 0x0000001c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(23), 0x0000001d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(24), 0x00000020, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(25), 0x00000021, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(26), 0x00000022, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(27), 0x00000023, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(28), 0x00000024, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(29), 0x00000025, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(30), 0x00000028, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(31), 0x00000029, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(32), 0x0000002a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(33), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(34), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(35), 0x0000002d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(36), 0x00000030, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(37), 0x00000031, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(38), 0x00000032, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(39), 0x00000033, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(40), 0x00000034, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(41), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(42), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(43), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(44), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(45), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(46), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(47), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(48), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(49), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(50), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(51), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(52), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(53), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(54), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(55), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(56), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(57), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(58), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(59), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(60), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(61), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(62), 0x00000010, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(63), 0x0000001a, AR5K_INI_WRITE },
+};
+
+
+/*
+ * Write initial register dump
+ */
+static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size,
+ const struct ath5k_ini *ini_regs, int change_channel)
+{
+ unsigned int i;
+
+ /* Write initial registers */
+ for (i = 0; i < size; i++) {
+ /* On channel change there is
+ * no need to mess with PCU */
+ if (change_channel &&
+ ini_regs[i].ini_register >= AR5K_PCU_MIN &&
+ ini_regs[i].ini_register <= AR5K_PCU_MAX)
+ continue;
+
+ switch (ini_regs[i].ini_mode) {
+ case AR5K_INI_READ:
+ /* Cleared on read */
+ ath5k_hw_reg_read(ah, ini_regs[i].ini_register);
+ break;
+ case AR5K_INI_WRITE:
+ default:
+ AR5K_REG_WAIT(i);
+ ath5k_hw_reg_write(ah, ini_regs[i].ini_value,
+ ini_regs[i].ini_register);
+ }
+ }
+}
+
+static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah,
+ unsigned int size, const struct ath5k_ini_mode *ini_mode,
+ u8 mode)
+{
+ unsigned int i;
+
+ for (i = 0; i < size; i++) {
+ AR5K_REG_WAIT(i);
+ ath5k_hw_reg_write(ah, ini_mode[i].mode_value[mode],
+ (u32)ini_mode[i].mode_register);
+ }
+}
+
+int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, int change_channel)
+{
+ /*
+ * Write initial register settings
+ */
+
+ /* For AR5212 and combatible */
+ if (ah->ah_version == AR5K_AR5212) {
+
+ /* First set of mode-specific settings */
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(ar5212_ini_mode_start),
+ ar5212_ini_mode_start, mode);
+
+ /*
+ * Write initial settings common for all modes
+ */
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start),
+ ar5212_ini_common_start, change_channel);
+
+ /* Second set of mode-specific settings */
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(rf5111_ini_mode_end),
+ rf5111_ini_mode_end, mode);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5111_ini_common_end),
+ rf5111_ini_common_end, change_channel);
+
+ /* Baseband gain table */
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5111_ini_bbgain),
+ rf5111_ini_bbgain, change_channel);
+
+ break;
+ case AR5K_RF5112:
+
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(rf5112_ini_mode_end),
+ rf5112_ini_mode_end, mode);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_common_end),
+ rf5112_ini_common_end, change_channel);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_bbgain),
+ rf5112_ini_bbgain, change_channel);
+
+ break;
+ case AR5K_RF5413:
+
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(rf5413_ini_mode_end),
+ rf5413_ini_mode_end, mode);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5413_ini_common_end),
+ rf5413_ini_common_end, change_channel);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_bbgain),
+ rf5112_ini_bbgain, change_channel);
+
+ break;
+ case AR5K_RF2316:
+ case AR5K_RF2413:
+
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(rf2413_ini_mode_end),
+ rf2413_ini_mode_end, mode);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf2413_ini_common_end),
+ rf2413_ini_common_end, change_channel);
+
+ /* Override settings from rf2413_ini_common_end */
+ if (ah->ah_radio == AR5K_RF2316) {
+ ath5k_hw_reg_write(ah, 0x00004000,
+ AR5K_PHY_AGC);
+ ath5k_hw_reg_write(ah, 0x081b7caa,
+ 0xa274);
+ }
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_bbgain),
+ rf5112_ini_bbgain, change_channel);
+ break;
+ case AR5K_RF2317:
+ case AR5K_RF2425:
+
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(rf2425_ini_mode_end),
+ rf2425_ini_mode_end, mode);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf2425_ini_common_end),
+ rf2425_ini_common_end, change_channel);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_bbgain),
+ rf5112_ini_bbgain, change_channel);
+ break;
+ default:
+ return -EINVAL;
+
+ }
+
+ /* For AR5211 */
+ } else if (ah->ah_version == AR5K_AR5211) {
+
+ /* AR5K_MODE_11B */
+ if (mode > 2) {
+ DBG("ath5k: unsupported channel mode %d\n", mode);
+ return -EINVAL;
+ }
+
+ /* Mode-specific settings */
+ ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(ar5211_ini_mode),
+ ar5211_ini_mode, mode);
+
+ /*
+ * Write initial settings common for all modes
+ */
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini),
+ ar5211_ini, change_channel);
+
+ /* AR5211 only comes with 5111 */
+
+ /* Baseband gain table */
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain),
+ rf5111_ini_bbgain, change_channel);
+ /* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */
+ } else if (ah->ah_version == AR5K_AR5210) {
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini),
+ ar5210_ini, change_channel);
+ }
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_pcu.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_pcu.c
new file mode 100644
index 00000000..c8165da7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_pcu.c
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Matthew W. S. Bell <mentor@madwifi.org>
+ * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Lightly modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/*********************************\
+* Protocol Control Unit Functions *
+\*********************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*******************\
+* Generic functions *
+\*******************/
+
+/**
+ * ath5k_hw_set_opmode - Set PCU operating mode
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Initialize PCU for the various operating modes (AP/STA etc)
+ *
+ * For iPXE we always assume STA mode.
+ */
+int ath5k_hw_set_opmode(struct ath5k_hw *ah)
+{
+ u32 pcu_reg, beacon_reg, low_id, high_id;
+
+
+ /* Preserve rest settings */
+ pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
+ pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
+ | AR5K_STA_ID1_KEYSRCH_MODE
+ | (ah->ah_version == AR5K_AR5210 ?
+ (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
+
+ beacon_reg = 0;
+
+ pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
+ | (ah->ah_version == AR5K_AR5210 ?
+ AR5K_STA_ID1_PWR_SV : 0);
+
+ /*
+ * Set PCU registers
+ */
+ low_id = AR5K_LOW_ID(ah->ah_sta_id);
+ high_id = AR5K_HIGH_ID(ah->ah_sta_id);
+ ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
+ ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
+
+ /*
+ * Set Beacon Control Register on 5210
+ */
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_set_ack_bitrate - set bitrate for ACKs
+ *
+ * @ah: The &struct ath5k_hw
+ * @high: Flag to determine if we want to use high transmition rate
+ * for ACKs or not
+ *
+ * If high flag is set, we tell hw to use a set of control rates based on
+ * the current transmition rate (check out control_rates array inside reset.c).
+ * If not hw just uses the lowest rate available for the current modulation
+ * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
+ */
+void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, int high)
+{
+ if (ah->ah_version != AR5K_AR5212)
+ return;
+ else {
+ u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
+ if (high)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
+ }
+}
+
+
+/******************\
+* ACK/CTS Timeouts *
+\******************/
+
+/**
+ * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec
+ *
+ * @ah: The &struct ath5k_hw
+ */
+unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
+{
+ return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
+ AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
+}
+
+/**
+ * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
+ *
+ * @ah: The &struct ath5k_hw
+ * @timeout: Timeout in usec
+ */
+int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
+{
+ if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
+ ah->ah_turbo) <= timeout)
+ return -EINVAL;
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
+ ath5k_hw_htoclock(timeout, ah->ah_turbo));
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec
+ *
+ * @ah: The &struct ath5k_hw
+ */
+unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
+{
+ return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
+ AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
+}
+
+/**
+ * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU
+ *
+ * @ah: The &struct ath5k_hw
+ * @timeout: Timeout in usec
+ */
+int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
+{
+ if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
+ ah->ah_turbo) <= timeout)
+ return -EINVAL;
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
+ ath5k_hw_htoclock(timeout, ah->ah_turbo));
+
+ return 0;
+}
+
+
+/****************\
+* BSSID handling *
+\****************/
+
+/**
+ * ath5k_hw_get_lladdr - Get station id
+ *
+ * @ah: The &struct ath5k_hw
+ * @mac: The card's mac address
+ *
+ * Initialize ah->ah_sta_id using the mac address provided
+ * (just a memcpy).
+ *
+ * TODO: Remove it once we merge ath5k_softc and ath5k_hw
+ */
+void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
+{
+ memcpy(mac, ah->ah_sta_id, ETH_ALEN);
+}
+
+/**
+ * ath5k_hw_set_lladdr - Set station id
+ *
+ * @ah: The &struct ath5k_hw
+ * @mac: The card's mac address
+ *
+ * Set station id on hw using the provided mac address
+ */
+int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
+{
+ u32 low_id, high_id;
+ u32 pcu_reg;
+
+ /* Set new station ID */
+ memcpy(ah->ah_sta_id, mac, ETH_ALEN);
+
+ pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
+
+ low_id = AR5K_LOW_ID(mac);
+ high_id = AR5K_HIGH_ID(mac);
+
+ ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
+ ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_set_associd - Set BSSID for association
+ *
+ * @ah: The &struct ath5k_hw
+ * @bssid: BSSID
+ * @assoc_id: Assoc id
+ *
+ * Sets the BSSID which trigers the "SME Join" operation
+ */
+void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
+{
+ u32 low_id, high_id;
+
+ /*
+ * Set simple BSSID mask on 5212
+ */
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
+ AR5K_BSS_IDM0);
+ ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
+ AR5K_BSS_IDM1);
+ }
+
+ /*
+ * Set BSSID which triggers the "SME Join" operation
+ */
+ low_id = AR5K_LOW_ID(bssid);
+ high_id = AR5K_HIGH_ID(bssid);
+ ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
+ ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
+ AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
+}
+
+/**
+ * ath5k_hw_set_bssid_mask - filter out bssids we listen
+ *
+ * @ah: the &struct ath5k_hw
+ * @mask: the bssid_mask, a u8 array of size ETH_ALEN
+ *
+ * BSSID masking is a method used by AR5212 and newer hardware to inform PCU
+ * which bits of the interface's MAC address should be looked at when trying
+ * to decide which packets to ACK. In station mode and AP mode with a single
+ * BSS every bit matters since we lock to only one BSS. In AP mode with
+ * multiple BSSes (virtual interfaces) not every bit matters because hw must
+ * accept frames for all BSSes and so we tweak some bits of our mac address
+ * in order to have multiple BSSes.
+ *
+ * NOTE: This is a simple filter and does *not* filter out all
+ * relevant frames. Some frames that are not for us might get ACKed from us
+ * by PCU because they just match the mask.
+ *
+ * When handling multiple BSSes you can get the BSSID mask by computing the
+ * set of ~ ( MAC XOR BSSID ) for all bssids we handle.
+ *
+ * When you do this you are essentially computing the common bits of all your
+ * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with
+ * the MAC address to obtain the relevant bits and compare the result with
+ * (frame's BSSID & mask) to see if they match.
+ */
+/*
+ * Simple example: on your card you have have two BSSes you have created with
+ * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
+ * There is another BSSID-03 but you are not part of it. For simplicity's sake,
+ * assuming only 4 bits for a mac address and for BSSIDs you can then have:
+ *
+ * \
+ * MAC: 0001 |
+ * BSSID-01: 0100 | --> Belongs to us
+ * BSSID-02: 1001 |
+ * /
+ * -------------------
+ * BSSID-03: 0110 | --> External
+ * -------------------
+ *
+ * Our bssid_mask would then be:
+ *
+ * On loop iteration for BSSID-01:
+ * ~(0001 ^ 0100) -> ~(0101)
+ * -> 1010
+ * bssid_mask = 1010
+ *
+ * On loop iteration for BSSID-02:
+ * bssid_mask &= ~(0001 ^ 1001)
+ * bssid_mask = (1010) & ~(0001 ^ 1001)
+ * bssid_mask = (1010) & ~(1001)
+ * bssid_mask = (1010) & (0110)
+ * bssid_mask = 0010
+ *
+ * A bssid_mask of 0010 means "only pay attention to the second least
+ * significant bit". This is because its the only bit common
+ * amongst the MAC and all BSSIDs we support. To findout what the real
+ * common bit is we can simply "&" the bssid_mask now with any BSSID we have
+ * or our MAC address (we assume the hardware uses the MAC address).
+ *
+ * Now, suppose there's an incoming frame for BSSID-03:
+ *
+ * IFRAME-01: 0110
+ *
+ * An easy eye-inspeciton of this already should tell you that this frame
+ * will not pass our check. This is beacuse the bssid_mask tells the
+ * hardware to only look at the second least significant bit and the
+ * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
+ * as 1, which does not match 0.
+ *
+ * So with IFRAME-01 we *assume* the hardware will do:
+ *
+ * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
+ * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
+ * --> allow = (0010) == 0000 ? 1 : 0;
+ * --> allow = 0
+ *
+ * Lets now test a frame that should work:
+ *
+ * IFRAME-02: 0001 (we should allow)
+ *
+ * allow = (0001 & 1010) == 1010
+ *
+ * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
+ * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0;
+ * --> allow = (0010) == (0010)
+ * --> allow = 1
+ *
+ * Other examples:
+ *
+ * IFRAME-03: 0100 --> allowed
+ * IFRAME-04: 1001 --> allowed
+ * IFRAME-05: 1101 --> allowed but its not for us!!!
+ *
+ */
+int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
+{
+ u32 low_id, high_id;
+
+ /* Cache bssid mask so that we can restore it
+ * on reset */
+ memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
+ if (ah->ah_version == AR5K_AR5212) {
+ low_id = AR5K_LOW_ID(mask);
+ high_id = AR5K_HIGH_ID(mask);
+
+ ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
+ ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
+
+ return 0;
+ }
+
+ return -EIO;
+}
+
+
+/************\
+* RX Control *
+\************/
+
+/**
+ * ath5k_hw_start_rx_pcu - Start RX engine
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Starts RX engine on PCU so that hw can process RXed frames
+ * (ACK etc).
+ *
+ * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
+ * TODO: Init ANI here
+ */
+void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
+{
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/**
+ * at5k_hw_stop_rx_pcu - Stop RX engine
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Stops RX engine on PCU
+ *
+ * TODO: Detach ANI here
+ */
+void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
+{
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/*
+ * Set multicast filter
+ */
+void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
+{
+ /* Set the multicat filter */
+ ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
+ ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
+}
+
+/**
+ * ath5k_hw_get_rx_filter - Get current rx filter
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Returns the RX filter by reading rx filter and
+ * phy error filter registers. RX filter is used
+ * to set the allowed frame types that PCU will accept
+ * and pass to the driver. For a list of frame types
+ * check out reg.h.
+ */
+u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
+{
+ u32 data, filter = 0;
+
+ filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
+
+ /*Radar detection for 5212*/
+ if (ah->ah_version == AR5K_AR5212) {
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
+
+ if (data & AR5K_PHY_ERR_FIL_RADAR)
+ filter |= AR5K_RX_FILTER_RADARERR;
+ if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
+ filter |= AR5K_RX_FILTER_PHYERR;
+ }
+
+ return filter;
+}
+
+/**
+ * ath5k_hw_set_rx_filter - Set rx filter
+ *
+ * @ah: The &struct ath5k_hw
+ * @filter: RX filter mask (see reg.h)
+ *
+ * Sets RX filter register and also handles PHY error filter
+ * register on 5212 and newer chips so that we have proper PHY
+ * error reporting.
+ */
+void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
+{
+ u32 data = 0;
+
+ /* Set PHY error filter register on 5212*/
+ if (ah->ah_version == AR5K_AR5212) {
+ if (filter & AR5K_RX_FILTER_RADARERR)
+ data |= AR5K_PHY_ERR_FIL_RADAR;
+ if (filter & AR5K_RX_FILTER_PHYERR)
+ data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
+ }
+
+ /*
+ * The AR5210 uses promiscous mode to detect radar activity
+ */
+ if (ah->ah_version == AR5K_AR5210 &&
+ (filter & AR5K_RX_FILTER_RADARERR)) {
+ filter &= ~AR5K_RX_FILTER_RADARERR;
+ filter |= AR5K_RX_FILTER_PROM;
+ }
+
+ /*Zero length DMA (phy error reporting) */
+ if (data)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
+
+ /*Write RX Filter register*/
+ ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
+
+ /*Write PHY error filter register on 5212*/
+ if (ah->ah_version == AR5K_AR5212)
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
+
+}
+
+/*********************\
+* Key table functions *
+\*********************/
+
+/*
+ * Reset a key entry on the table
+ */
+int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
+{
+ unsigned int i, type;
+ u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
+
+ type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
+
+ for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
+ ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
+
+ /* Reset associated MIC entry if TKIP
+ * is enabled located at offset (entry + 64) */
+ if (type == AR5K_KEYTABLE_TYPE_TKIP) {
+ for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++)
+ ath5k_hw_reg_write(ah, 0,
+ AR5K_KEYTABLE_OFF(micentry, i));
+ }
+
+ /*
+ * Set NULL encryption on AR5212+
+ *
+ * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
+ * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
+ *
+ * Note2: Windows driver (ndiswrapper) sets this to
+ * 0x00000714 instead of 0x00000007
+ */
+ if (ah->ah_version >= AR5K_AR5211) {
+ ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+ AR5K_KEYTABLE_TYPE(entry));
+
+ if (type == AR5K_KEYTABLE_TYPE_TKIP) {
+ ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+ AR5K_KEYTABLE_TYPE(micentry));
+ }
+ }
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_phy.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_phy.c
new file mode 100644
index 00000000..7891d39e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_phy.c
@@ -0,0 +1,2581 @@
+/*
+ * PHY functions
+ *
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2008-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * Lightly modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+#define _ATH5K_PHY
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+#include "rfbuffer.h"
+#include "rfgain.h"
+
+static inline int min(int x, int y)
+{
+ return (x < y) ? x : y;
+}
+
+static inline int max(int x, int y)
+{
+ return (x > y) ? x : y;
+}
+
+/*
+ * Used to modify RF Banks before writing them to AR5K_RF_BUFFER
+ */
+static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah,
+ const struct ath5k_rf_reg *rf_regs,
+ u32 val, u8 reg_id, int set)
+{
+ const struct ath5k_rf_reg *rfreg = NULL;
+ u8 offset, bank, num_bits, col, position;
+ u16 entry;
+ u32 mask, data, last_bit, bits_shifted, first_bit;
+ u32 *rfb;
+ s32 bits_left;
+ unsigned i;
+
+ data = 0;
+ rfb = ah->ah_rf_banks;
+
+ for (i = 0; i < ah->ah_rf_regs_count; i++) {
+ if (rf_regs[i].index == reg_id) {
+ rfreg = &rf_regs[i];
+ break;
+ }
+ }
+
+ if (rfb == NULL || rfreg == NULL) {
+ DBG("ath5k: RF register not found!\n");
+ /* should not happen */
+ return 0;
+ }
+
+ bank = rfreg->bank;
+ num_bits = rfreg->field.len;
+ first_bit = rfreg->field.pos;
+ col = rfreg->field.col;
+
+ /* first_bit is an offset from bank's
+ * start. Since we have all banks on
+ * the same array, we use this offset
+ * to mark each bank's start */
+ offset = ah->ah_offset[bank];
+
+ /* Boundary check */
+ if (!(col <= 3 && num_bits <= 32 && first_bit + num_bits <= 319)) {
+ DBG("ath5k: RF invalid values at offset %d\n", offset);
+ return 0;
+ }
+
+ entry = ((first_bit - 1) / 8) + offset;
+ position = (first_bit - 1) % 8;
+
+ if (set)
+ data = ath5k_hw_bitswap(val, num_bits);
+
+ for (bits_shifted = 0, bits_left = num_bits; bits_left > 0;
+ position = 0, entry++) {
+
+ last_bit = (position + bits_left > 8) ? 8 :
+ position + bits_left;
+
+ mask = (((1 << last_bit) - 1) ^ ((1 << position) - 1)) <<
+ (col * 8);
+
+ if (set) {
+ rfb[entry] &= ~mask;
+ rfb[entry] |= ((data << position) << (col * 8)) & mask;
+ data >>= (8 - position);
+ } else {
+ data |= (((rfb[entry] & mask) >> (col * 8)) >> position)
+ << bits_shifted;
+ bits_shifted += last_bit - position;
+ }
+
+ bits_left -= 8 - position;
+ }
+
+ data = set ? 1 : ath5k_hw_bitswap(data, num_bits);
+
+ return data;
+}
+
+/**********************\
+* RF Gain optimization *
+\**********************/
+
+/*
+ * This code is used to optimize rf gain on different environments
+ * (temprature mostly) based on feedback from a power detector.
+ *
+ * It's only used on RF5111 and RF5112, later RF chips seem to have
+ * auto adjustment on hw -notice they have a much smaller BANK 7 and
+ * no gain optimization ladder-.
+ *
+ * For more infos check out this patent doc
+ * http://www.freepatentsonline.com/7400691.html
+ *
+ * This paper describes power drops as seen on the receiver due to
+ * probe packets
+ * http://www.cnri.dit.ie/publications/ICT08%20-%20Practical%20Issues
+ * %20of%20Power%20Control.pdf
+ *
+ * And this is the MadWiFi bug entry related to the above
+ * http://madwifi-project.org/ticket/1659
+ * with various measurements and diagrams
+ *
+ * TODO: Deal with power drops due to probes by setting an apropriate
+ * tx power on the probe packets ! Make this part of the calibration process.
+ */
+
+/* Initialize ah_gain durring attach */
+int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah)
+{
+ /* Initialize the gain optimization values */
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default;
+ ah->ah_gain.g_low = 20;
+ ah->ah_gain.g_high = 35;
+ ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+ break;
+ case AR5K_RF5112:
+ ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
+ ah->ah_gain.g_low = 20;
+ ah->ah_gain.g_high = 85;
+ ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Schedule a gain probe check on the next transmited packet.
+ * That means our next packet is going to be sent with lower
+ * tx power and a Peak to Average Power Detector (PAPD) will try
+ * to measure the gain.
+ *
+ * TODO: Use propper tx power setting for the probe packet so
+ * that we don't observe a serious power drop on the receiver
+ *
+ * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc)
+ * just after we enable the probe so that we don't mess with
+ * standard traffic ? Maybe it's time to use sw interrupts and
+ * a probe tasklet !!!
+ */
+static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah)
+{
+
+ /* Skip if gain calibration is inactive or
+ * we already handle a probe request */
+ if (ah->ah_gain.g_state != AR5K_RFGAIN_ACTIVE)
+ return;
+
+ /* Send the packet with 2dB below max power as
+ * patent doc suggest */
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max_pwr - 4,
+ AR5K_PHY_PAPD_PROBE_TXPOWER) |
+ AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);
+
+ ah->ah_gain.g_state = AR5K_RFGAIN_READ_REQUESTED;
+
+}
+
+/* Calculate gain_F measurement correction
+ * based on the current step for RF5112 rev. 2 */
+static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah)
+{
+ u32 mix, step;
+ const struct ath5k_gain_opt *go;
+ const struct ath5k_gain_opt_step *g_step;
+ const struct ath5k_rf_reg *rf_regs;
+
+ /* Only RF5112 Rev. 2 supports it */
+ if ((ah->ah_radio != AR5K_RF5112) ||
+ (ah->ah_radio_5ghz_revision <= AR5K_SREV_RAD_5112A))
+ return 0;
+
+ go = &rfgain_opt_5112;
+ rf_regs = rf_regs_5112a;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
+
+ g_step = &go->go_step[ah->ah_gain.g_step_idx];
+
+ if (ah->ah_rf_banks == NULL)
+ return 0;
+
+ ah->ah_gain.g_f_corr = 0;
+
+ /* No VGA (Variable Gain Amplifier) override, skip */
+ if (ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, 0) != 1)
+ return 0;
+
+ /* Mix gain stepping */
+ step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXGAIN_STEP, 0);
+
+ /* Mix gain override */
+ mix = g_step->gos_param[0];
+
+ switch (mix) {
+ case 3:
+ ah->ah_gain.g_f_corr = step * 2;
+ break;
+ case 2:
+ ah->ah_gain.g_f_corr = (step - 5) * 2;
+ break;
+ case 1:
+ ah->ah_gain.g_f_corr = step;
+ break;
+ default:
+ ah->ah_gain.g_f_corr = 0;
+ break;
+ }
+
+ return ah->ah_gain.g_f_corr;
+}
+
+/* Check if current gain_F measurement is in the range of our
+ * power detector windows. If we get a measurement outside range
+ * we know it's not accurate (detectors can't measure anything outside
+ * their detection window) so we must ignore it */
+static int ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)
+{
+ const struct ath5k_rf_reg *rf_regs;
+ u32 step, mix_ovr, level[4];
+
+ if (ah->ah_rf_banks == NULL)
+ return 0;
+
+ if (ah->ah_radio == AR5K_RF5111) {
+
+ rf_regs = rf_regs_5111;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
+
+ step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_RFGAIN_STEP,
+ 0);
+
+ level[0] = 0;
+ level[1] = (step == 63) ? 50 : step + 4;
+ level[2] = (step != 63) ? 64 : level[0];
+ level[3] = level[2] + 50 ;
+
+ ah->ah_gain.g_high = level[3] -
+ (step == 63 ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
+ ah->ah_gain.g_low = level[0] +
+ (step == 63 ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0);
+ } else {
+
+ rf_regs = rf_regs_5112;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
+
+ mix_ovr = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR,
+ 0);
+
+ level[0] = level[2] = 0;
+
+ if (mix_ovr == 1) {
+ level[1] = level[3] = 83;
+ } else {
+ level[1] = level[3] = 107;
+ ah->ah_gain.g_high = 55;
+ }
+ }
+
+ return (ah->ah_gain.g_current >= level[0] &&
+ ah->ah_gain.g_current <= level[1]) ||
+ (ah->ah_gain.g_current >= level[2] &&
+ ah->ah_gain.g_current <= level[3]);
+}
+
+/* Perform gain_F adjustment by choosing the right set
+ * of parameters from rf gain optimization ladder */
+static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
+{
+ const struct ath5k_gain_opt *go;
+ const struct ath5k_gain_opt_step *g_step;
+ int ret = 0;
+
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ go = &rfgain_opt_5111;
+ break;
+ case AR5K_RF5112:
+ go = &rfgain_opt_5112;
+ break;
+ default:
+ return 0;
+ }
+
+ g_step = &go->go_step[ah->ah_gain.g_step_idx];
+
+ if (ah->ah_gain.g_current >= ah->ah_gain.g_high) {
+
+ /* Reached maximum */
+ if (ah->ah_gain.g_step_idx == 0)
+ return -1;
+
+ for (ah->ah_gain.g_target = ah->ah_gain.g_current;
+ ah->ah_gain.g_target >= ah->ah_gain.g_high &&
+ ah->ah_gain.g_step_idx > 0;
+ g_step = &go->go_step[ah->ah_gain.g_step_idx])
+ ah->ah_gain.g_target -= 2 *
+ (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain -
+ g_step->gos_gain);
+
+ ret = 1;
+ goto done;
+ }
+
+ if (ah->ah_gain.g_current <= ah->ah_gain.g_low) {
+
+ /* Reached minimum */
+ if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1))
+ return -2;
+
+ for (ah->ah_gain.g_target = ah->ah_gain.g_current;
+ ah->ah_gain.g_target <= ah->ah_gain.g_low &&
+ ah->ah_gain.g_step_idx < go->go_steps_count-1;
+ g_step = &go->go_step[ah->ah_gain.g_step_idx])
+ ah->ah_gain.g_target -= 2 *
+ (go->go_step[++ah->ah_gain.g_step_idx].gos_gain -
+ g_step->gos_gain);
+
+ ret = 2;
+ goto done;
+ }
+
+done:
+ DBG2("ath5k RF adjust: ret %d, gain step %d, current gain %d, "
+ "target gain %d\n", ret, ah->ah_gain.g_step_idx,
+ ah->ah_gain.g_current, ah->ah_gain.g_target);
+
+ return ret;
+}
+
+/* Main callback for thermal rf gain calibration engine
+ * Check for a new gain reading and schedule an adjustment
+ * if needed.
+ *
+ * TODO: Use sw interrupt to schedule reset if gain_F needs
+ * adjustment */
+enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah)
+{
+ u32 data, type;
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+
+ if (ah->ah_rf_banks == NULL ||
+ ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE)
+ return AR5K_RFGAIN_INACTIVE;
+
+ /* No check requested, either engine is inactive
+ * or an adjustment is already requested */
+ if (ah->ah_gain.g_state != AR5K_RFGAIN_READ_REQUESTED)
+ goto done;
+
+ /* Read the PAPD (Peak to Average Power Detector)
+ * register */
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_PAPD_PROBE);
+
+ /* No probe is scheduled, read gain_F measurement */
+ if (!(data & AR5K_PHY_PAPD_PROBE_TX_NEXT)) {
+ ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S;
+ type = AR5K_REG_MS(data, AR5K_PHY_PAPD_PROBE_TYPE);
+
+ /* If tx packet is CCK correct the gain_F measurement
+ * by cck ofdm gain delta */
+ if (type == AR5K_PHY_PAPD_PROBE_TYPE_CCK) {
+ if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A)
+ ah->ah_gain.g_current +=
+ ee->ee_cck_ofdm_gain_delta;
+ else
+ ah->ah_gain.g_current +=
+ AR5K_GAIN_CCK_PROBE_CORR;
+ }
+
+ /* Further correct gain_F measurement for
+ * RF5112A radios */
+ if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
+ ath5k_hw_rf_gainf_corr(ah);
+ ah->ah_gain.g_current =
+ ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ?
+ (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
+ 0;
+ }
+
+ /* Check if measurement is ok and if we need
+ * to adjust gain, schedule a gain adjustment,
+ * else switch back to the acive state */
+ if (ath5k_hw_rf_check_gainf_readback(ah) &&
+ AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&
+ ath5k_hw_rf_gainf_adjust(ah)) {
+ ah->ah_gain.g_state = AR5K_RFGAIN_NEED_CHANGE;
+ } else {
+ ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+ }
+ }
+
+done:
+ return ah->ah_gain.g_state;
+}
+
+/* Write initial rf gain table to set the RF sensitivity
+ * this one works on all RF chips and has nothing to do
+ * with gain_F calibration */
+int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
+{
+ const struct ath5k_ini_rfgain *ath5k_rfg;
+ unsigned int i, size;
+
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ ath5k_rfg = rfgain_5111;
+ size = ARRAY_SIZE(rfgain_5111);
+ break;
+ case AR5K_RF5112:
+ ath5k_rfg = rfgain_5112;
+ size = ARRAY_SIZE(rfgain_5112);
+ break;
+ case AR5K_RF2413:
+ ath5k_rfg = rfgain_2413;
+ size = ARRAY_SIZE(rfgain_2413);
+ break;
+ case AR5K_RF2316:
+ ath5k_rfg = rfgain_2316;
+ size = ARRAY_SIZE(rfgain_2316);
+ break;
+ case AR5K_RF5413:
+ ath5k_rfg = rfgain_5413;
+ size = ARRAY_SIZE(rfgain_5413);
+ break;
+ case AR5K_RF2317:
+ case AR5K_RF2425:
+ ath5k_rfg = rfgain_2425;
+ size = ARRAY_SIZE(rfgain_2425);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (freq) {
+ case AR5K_INI_RFGAIN_2GHZ:
+ case AR5K_INI_RFGAIN_5GHZ:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < size; i++) {
+ AR5K_REG_WAIT(i);
+ ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq],
+ (u32)ath5k_rfg[i].rfg_register);
+ }
+
+ return 0;
+}
+
+
+
+/********************\
+* RF Registers setup *
+\********************/
+
+
+/*
+ * Setup RF registers by writing rf buffer on hw
+ */
+int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct net80211_channel *channel,
+ unsigned int mode)
+{
+ const struct ath5k_rf_reg *rf_regs;
+ const struct ath5k_ini_rfbuffer *ini_rfb;
+ const struct ath5k_gain_opt *go = NULL;
+ const struct ath5k_gain_opt_step *g_step;
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u8 ee_mode = 0;
+ u32 *rfb;
+ int obdb = -1, bank = -1;
+ unsigned i;
+
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ rf_regs = rf_regs_5111;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
+ ini_rfb = rfb_5111;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5111);
+ go = &rfgain_opt_5111;
+ break;
+ case AR5K_RF5112:
+ if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
+ rf_regs = rf_regs_5112a;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
+ ini_rfb = rfb_5112a;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112a);
+ } else {
+ rf_regs = rf_regs_5112;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
+ ini_rfb = rfb_5112;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112);
+ }
+ go = &rfgain_opt_5112;
+ break;
+ case AR5K_RF2413:
+ rf_regs = rf_regs_2413;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2413);
+ ini_rfb = rfb_2413;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2413);
+ break;
+ case AR5K_RF2316:
+ rf_regs = rf_regs_2316;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2316);
+ ini_rfb = rfb_2316;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2316);
+ break;
+ case AR5K_RF5413:
+ rf_regs = rf_regs_5413;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5413);
+ ini_rfb = rfb_5413;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5413);
+ break;
+ case AR5K_RF2317:
+ rf_regs = rf_regs_2425;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
+ ini_rfb = rfb_2317;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2317);
+ break;
+ case AR5K_RF2425:
+ rf_regs = rf_regs_2425;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
+ if (ah->ah_mac_srev < AR5K_SREV_AR2417) {
+ ini_rfb = rfb_2425;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2425);
+ } else {
+ ini_rfb = rfb_2417;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2417);
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* If it's the first time we set rf buffer, allocate
+ * ah->ah_rf_banks based on ah->ah_rf_banks_size
+ * we set above */
+ if (ah->ah_rf_banks == NULL) {
+ ah->ah_rf_banks = malloc(sizeof(u32) * ah->ah_rf_banks_size);
+ if (ah->ah_rf_banks == NULL) {
+ return -ENOMEM;
+ }
+ }
+
+ /* Copy values to modify them */
+ rfb = ah->ah_rf_banks;
+
+ for (i = 0; i < ah->ah_rf_banks_size; i++) {
+ if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) {
+ DBG("ath5k: invalid RF register bank\n");
+ return -EINVAL;
+ }
+
+ /* Bank changed, write down the offset */
+ if (bank != ini_rfb[i].rfb_bank) {
+ bank = ini_rfb[i].rfb_bank;
+ ah->ah_offset[bank] = i;
+ }
+
+ rfb[i] = ini_rfb[i].rfb_mode_data[mode];
+ }
+
+ /* Set Output and Driver bias current (OB/DB) */
+ if (channel->hw_value & CHANNEL_2GHZ) {
+
+ if (channel->hw_value & CHANNEL_CCK)
+ ee_mode = AR5K_EEPROM_MODE_11B;
+ else
+ ee_mode = AR5K_EEPROM_MODE_11G;
+
+ /* For RF511X/RF211X combination we
+ * use b_OB and b_DB parameters stored
+ * in eeprom on ee->ee_ob[ee_mode][0]
+ *
+ * For all other chips we use OB/DB for 2Ghz
+ * stored in the b/g modal section just like
+ * 802.11a on ee->ee_ob[ee_mode][1] */
+ if ((ah->ah_radio == AR5K_RF5111) ||
+ (ah->ah_radio == AR5K_RF5112))
+ obdb = 0;
+ else
+ obdb = 1;
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
+ AR5K_RF_OB_2GHZ, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
+ AR5K_RF_DB_2GHZ, 1);
+
+ /* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */
+ } else if ((channel->hw_value & CHANNEL_5GHZ) ||
+ (ah->ah_radio == AR5K_RF5111)) {
+
+ /* For 11a, Turbo and XR we need to choose
+ * OB/DB based on frequency range */
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ obdb = channel->center_freq >= 5725 ? 3 :
+ (channel->center_freq >= 5500 ? 2 :
+ (channel->center_freq >= 5260 ? 1 :
+ (channel->center_freq > 4000 ? 0 : -1)));
+
+ if (obdb < 0)
+ return -EINVAL;
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
+ AR5K_RF_OB_5GHZ, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
+ AR5K_RF_DB_5GHZ, 1);
+ }
+
+ g_step = &go->go_step[ah->ah_gain.g_step_idx];
+
+ /* Bank Modifications (chip-specific) */
+ if (ah->ah_radio == AR5K_RF5111) {
+
+ /* Set gain_F settings according to current step */
+ if (channel->hw_value & CHANNEL_OFDM) {
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
+ AR5K_PHY_FRAME_CTL_TX_CLIP,
+ g_step->gos_param[0]);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
+ AR5K_RF_PWD_90, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
+ AR5K_RF_PWD_84, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
+ AR5K_RF_RFGAIN_SEL, 1);
+
+ /* We programmed gain_F parameters, switch back
+ * to active state */
+ ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+
+ }
+
+ /* Bank 6/7 setup */
+
+ ath5k_hw_rfb_op(ah, rf_regs, !ee->ee_xpd[ee_mode],
+ AR5K_RF_PWD_XPD, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_x_gain[ee_mode],
+ AR5K_RF_XPD_GAIN, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
+ AR5K_RF_GAIN_I, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
+ AR5K_RF_PLO_SEL, 1);
+
+ /* TODO: Half/quarter channel support */
+ }
+
+ if (ah->ah_radio == AR5K_RF5112) {
+
+ /* Set gain_F settings according to current step */
+ if (channel->hw_value & CHANNEL_OFDM) {
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0],
+ AR5K_RF_MIXGAIN_OVR, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
+ AR5K_RF_PWD_138, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
+ AR5K_RF_PWD_137, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
+ AR5K_RF_PWD_136, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[4],
+ AR5K_RF_PWD_132, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[5],
+ AR5K_RF_PWD_131, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[6],
+ AR5K_RF_PWD_130, 1);
+
+ /* We programmed gain_F parameters, switch back
+ * to active state */
+ ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+ }
+
+ /* Bank 6/7 setup */
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
+ AR5K_RF_XPD_SEL, 1);
+
+ if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
+ /* Rev. 1 supports only one xpd */
+ ath5k_hw_rfb_op(ah, rf_regs,
+ ee->ee_x_gain[ee_mode],
+ AR5K_RF_XPD_GAIN, 1);
+
+ } else {
+ /* TODO: Set high and low gain bits */
+ ath5k_hw_rfb_op(ah, rf_regs,
+ ee->ee_x_gain[ee_mode],
+ AR5K_RF_PD_GAIN_LO, 1);
+ ath5k_hw_rfb_op(ah, rf_regs,
+ ee->ee_x_gain[ee_mode],
+ AR5K_RF_PD_GAIN_HI, 1);
+
+ /* Lower synth voltage on Rev 2 */
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_HIGH_VC_CP, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_MID_VC_CP, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_LOW_VC_CP, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_PUSH_UP, 1);
+
+ /* Decrease power consumption on 5213+ BaseBand */
+ if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
+ ath5k_hw_rfb_op(ah, rf_regs, 1,
+ AR5K_RF_PAD2GND, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 1,
+ AR5K_RF_XB2_LVL, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 1,
+ AR5K_RF_XB5_LVL, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 1,
+ AR5K_RF_PWD_167, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 1,
+ AR5K_RF_PWD_166, 1);
+ }
+ }
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
+ AR5K_RF_GAIN_I, 1);
+
+ /* TODO: Half/quarter channel support */
+
+ }
+
+ if (ah->ah_radio == AR5K_RF5413 &&
+ channel->hw_value & CHANNEL_2GHZ) {
+
+ ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE,
+ 1);
+
+ /* Set optimum value for early revisions (on pci-e chips) */
+ if (ah->ah_mac_srev >= AR5K_SREV_AR5424 &&
+ ah->ah_mac_srev < AR5K_SREV_AR5413)
+ ath5k_hw_rfb_op(ah, rf_regs, ath5k_hw_bitswap(6, 3),
+ AR5K_RF_PWD_ICLOBUF_2G, 1);
+
+ }
+
+ /* Write RF banks on hw */
+ for (i = 0; i < ah->ah_rf_banks_size; i++) {
+ AR5K_REG_WAIT(i);
+ ath5k_hw_reg_write(ah, rfb[i], ini_rfb[i].rfb_ctrl_register);
+ }
+
+ return 0;
+}
+
+
+/**************************\
+ PHY/RF channel functions
+\**************************/
+
+/*
+ * Check if a channel is supported
+ */
+int ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
+{
+ /* Check if the channel is in our supported range */
+ if (flags & CHANNEL_2GHZ) {
+ if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
+ (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
+ return 1;
+ } else if (flags & CHANNEL_5GHZ)
+ if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
+ (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Convertion needed for RF5110
+ */
+static u32 ath5k_hw_rf5110_chan2athchan(struct net80211_channel *channel)
+{
+ u32 athchan;
+
+ /*
+ * Convert IEEE channel/MHz to an internal channel value used
+ * by the AR5210 chipset. This has not been verified with
+ * newer chipsets like the AR5212A who have a completely
+ * different RF/PHY part.
+ */
+ athchan = (ath5k_hw_bitswap((ath5k_freq_to_channel(channel->center_freq)
+ - 24) / 2, 5) << 1)
+ | (1 << 6) | 0x1;
+ return athchan;
+}
+
+/*
+ * Set channel on RF5110
+ */
+static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ u32 data;
+
+ /*
+ * Set the channel and wait
+ */
+ data = ath5k_hw_rf5110_chan2athchan(channel);
+ ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER);
+ ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0);
+ mdelay(1);
+
+ return 0;
+}
+
+/*
+ * Convertion needed for 5111
+ */
+static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee,
+ struct ath5k_athchan_2ghz *athchan)
+{
+ int channel;
+
+ /* Cast this value to catch negative channel numbers (>= -19) */
+ channel = (int)ieee;
+
+ /*
+ * Map 2GHz IEEE channel to 5GHz Atheros channel
+ */
+ if (channel <= 13) {
+ athchan->a2_athchan = 115 + channel;
+ athchan->a2_flags = 0x46;
+ } else if (channel == 14) {
+ athchan->a2_athchan = 124;
+ athchan->a2_flags = 0x44;
+ } else if (channel >= 15 && channel <= 26) {
+ athchan->a2_athchan = ((channel - 14) * 4) + 132;
+ athchan->a2_flags = 0x46;
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+/*
+ * Set channel on 5111
+ */
+static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ struct ath5k_athchan_2ghz ath5k_channel_2ghz;
+ unsigned int ath5k_channel = ath5k_freq_to_channel(channel->center_freq);
+ u32 data0, data1, clock;
+ int ret;
+
+ /*
+ * Set the channel on the RF5111 radio
+ */
+ data0 = data1 = 0;
+
+ if (channel->hw_value & CHANNEL_2GHZ) {
+ /* Map 2GHz channel to 5GHz Atheros channel ID */
+ ret = ath5k_hw_rf5111_chan2athchan(ath5k_channel,
+ &ath5k_channel_2ghz);
+ if (ret)
+ return ret;
+
+ ath5k_channel = ath5k_channel_2ghz.a2_athchan;
+ data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff)
+ << 5) | (1 << 4);
+ }
+
+ if (ath5k_channel < 145 || !(ath5k_channel & 1)) {
+ clock = 1;
+ data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) |
+ (clock << 1) | (1 << 10) | 1;
+ } else {
+ clock = 0;
+ data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff)
+ << 2) | (clock << 1) | (1 << 10) | 1;
+ }
+
+ ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8),
+ AR5K_RF_BUFFER);
+ ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00),
+ AR5K_RF_BUFFER_CONTROL_3);
+
+ return 0;
+}
+
+/*
+ * Set channel on 5112 and newer
+ */
+static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ u32 data, data0, data1, data2;
+ u16 c;
+
+ data = data0 = data1 = data2 = 0;
+ c = channel->center_freq;
+
+ if (c < 4800) {
+ if (!((c - 2224) % 5)) {
+ data0 = ((2 * (c - 704)) - 3040) / 10;
+ data1 = 1;
+ } else if (!((c - 2192) % 5)) {
+ data0 = ((2 * (c - 672)) - 3040) / 10;
+ data1 = 0;
+ } else
+ return -EINVAL;
+
+ data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
+ } else if ((c - (c % 5)) != 2 || c > 5435) {
+ if (!(c % 20) && c >= 5120) {
+ data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
+ data2 = ath5k_hw_bitswap(3, 2);
+ } else if (!(c % 10)) {
+ data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
+ data2 = ath5k_hw_bitswap(2, 2);
+ } else if (!(c % 5)) {
+ data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
+ data2 = ath5k_hw_bitswap(1, 2);
+ } else
+ return -EINVAL;
+ } else {
+ data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
+ data2 = ath5k_hw_bitswap(0, 2);
+ }
+
+ data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
+
+ ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
+ ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
+
+ return 0;
+}
+
+/*
+ * Set the channel on the RF2425
+ */
+static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ u32 data, data0, data2;
+ u16 c;
+
+ data = data0 = data2 = 0;
+ c = channel->center_freq;
+
+ if (c < 4800) {
+ data0 = ath5k_hw_bitswap((c - 2272), 8);
+ data2 = 0;
+ /* ? 5GHz ? */
+ } else if ((c - (c % 5)) != 2 || c > 5435) {
+ if (!(c % 20) && c < 5120)
+ data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
+ else if (!(c % 10))
+ data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
+ else if (!(c % 5))
+ data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
+ else
+ return -EINVAL;
+ data2 = ath5k_hw_bitswap(1, 2);
+ } else {
+ data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
+ data2 = ath5k_hw_bitswap(0, 2);
+ }
+
+ data = (data0 << 4) | data2 << 2 | 0x1001;
+
+ ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
+ ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
+
+ return 0;
+}
+
+/*
+ * Set a channel on the radio chip
+ */
+int ath5k_hw_channel(struct ath5k_hw *ah, struct net80211_channel *channel)
+{
+ int ret;
+ /*
+ * Check bounds supported by the PHY (we don't care about regultory
+ * restrictions at this point). Note: hw_value already has the band
+ * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
+ * of the band by that */
+ if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
+ DBG("ath5k: channel frequency (%d MHz) out of supported "
+ "range\n", channel->center_freq);
+ return -EINVAL;
+ }
+
+ /*
+ * Set the channel and wait
+ */
+ switch (ah->ah_radio) {
+ case AR5K_RF5110:
+ ret = ath5k_hw_rf5110_channel(ah, channel);
+ break;
+ case AR5K_RF5111:
+ ret = ath5k_hw_rf5111_channel(ah, channel);
+ break;
+ case AR5K_RF2425:
+ ret = ath5k_hw_rf2425_channel(ah, channel);
+ break;
+ default:
+ ret = ath5k_hw_rf5112_channel(ah, channel);
+ break;
+ }
+
+ if (ret) {
+ DBG("ath5k: setting channel failed: %s\n", strerror(ret));
+ return ret;
+ }
+
+ /* Set JAPAN setting for channel 14 */
+ if (channel->center_freq == 2484) {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
+ AR5K_PHY_CCKTXCTL_JAPAN);
+ } else {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
+ AR5K_PHY_CCKTXCTL_WORLD);
+ }
+
+ ah->ah_current_channel = channel;
+ ah->ah_turbo = (channel->hw_value == CHANNEL_T ? 1 : 0);
+
+ return 0;
+}
+
+/*****************\
+ PHY calibration
+\*****************/
+
+/**
+ * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
+ *
+ * @ah: struct ath5k_hw pointer we are operating on
+ * @freq: the channel frequency, just used for error logging
+ *
+ * This function performs a noise floor calibration of the PHY and waits for
+ * it to complete. Then the noise floor value is compared to some maximum
+ * noise floor we consider valid.
+ *
+ * Note that this is different from what the madwifi HAL does: it reads the
+ * noise floor and afterwards initiates the calibration. Since the noise floor
+ * calibration can take some time to finish, depending on the current channel
+ * use, that avoids the occasional timeout warnings we are seeing now.
+ *
+ * See the following link for an Atheros patent on noise floor calibration:
+ * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \
+ * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7
+ *
+ * XXX: Since during noise floor calibration antennas are detached according to
+ * the patent, we should stop tx queues here.
+ */
+int
+ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
+{
+ int ret;
+ unsigned int i;
+ s32 noise_floor;
+
+ /*
+ * Enable noise floor calibration
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_NF);
+
+ ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_NF, 0, 0);
+
+ if (ret) {
+ DBG("ath5k: noise floor calibration timeout (%d MHz)\n", freq);
+ return -EAGAIN;
+ }
+
+ /* Wait until the noise floor is calibrated and read the value */
+ for (i = 20; i > 0; i--) {
+ mdelay(1);
+ noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
+ noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
+ if (noise_floor & AR5K_PHY_NF_ACTIVE) {
+ noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
+
+ if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
+ break;
+ }
+ }
+
+ DBG2("ath5k: noise floor %d\n", noise_floor);
+
+ if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
+ DBG("ath5k: noise floor calibration failed (%d MHz)\n", freq);
+ return -EAGAIN;
+ }
+
+ ah->ah_noise_floor = noise_floor;
+
+ return 0;
+}
+
+/*
+ * Perform a PHY calibration on RF5110
+ * -Fix BPSK/QAM Constellation (I/Q correction)
+ * -Calculate Noise Floor
+ */
+static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ u32 phy_sig, phy_agc, phy_sat, beacon;
+ int ret;
+
+ /*
+ * Disable beacons and RX/TX queues, wait
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210,
+ AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+ beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
+ ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
+
+ mdelay(2);
+
+ /*
+ * Set the channel (with AGC turned off)
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+ udelay(10);
+ ret = ath5k_hw_channel(ah, channel);
+
+ /*
+ * Activate PHY and wait
+ */
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
+ mdelay(1);
+
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+
+ if (ret)
+ return ret;
+
+ /*
+ * Calibrate the radio chip
+ */
+
+ /* Remember normal state */
+ phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG);
+ phy_agc = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCOARSE);
+ phy_sat = ath5k_hw_reg_read(ah, AR5K_PHY_ADCSAT);
+
+ /* Update radio registers */
+ ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) |
+ AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG);
+
+ ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI |
+ AR5K_PHY_AGCCOARSE_LO)) |
+ AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) |
+ AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE);
+
+ ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT |
+ AR5K_PHY_ADCSAT_THR)) |
+ AR5K_REG_SM(2, AR5K_PHY_ADCSAT_ICNT) |
+ AR5K_REG_SM(12, AR5K_PHY_ADCSAT_THR), AR5K_PHY_ADCSAT);
+
+ udelay(20);
+
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+ udelay(10);
+ ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG);
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+
+ mdelay(1);
+
+ /*
+ * Enable calibration and wait until completion
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL);
+
+ ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL, 0, 0);
+
+ /* Reset to normal state */
+ ath5k_hw_reg_write(ah, phy_sig, AR5K_PHY_SIG);
+ ath5k_hw_reg_write(ah, phy_agc, AR5K_PHY_AGCCOARSE);
+ ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT);
+
+ if (ret) {
+ DBG("ath5k: calibration timeout (%d MHz)\n",
+ channel->center_freq);
+ return ret;
+ }
+
+ ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+
+ /*
+ * Re-enable RX/TX and beacons
+ */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210,
+ AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+ ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
+
+ return 0;
+}
+
+/*
+ * Perform a PHY calibration on RF5111/5112 and newer chips
+ */
+static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ u32 i_pwr, q_pwr;
+ s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
+ int i;
+
+ if (!ah->ah_calibration ||
+ ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
+ goto done;
+
+ /* Calibration has finished, get the results and re-run */
+ for (i = 0; i <= 10; i++) {
+ iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
+ i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
+ q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
+ }
+
+ i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7;
+ q_coffd = q_pwr >> 7;
+
+ /* No correction */
+ if (i_coffd == 0 || q_coffd == 0)
+ goto done;
+
+ i_coff = ((-iq_corr) / i_coffd) & 0x3f;
+
+ /* Boundary check */
+ if (i_coff > 31)
+ i_coff = 31;
+ if (i_coff < -32)
+ i_coff = -32;
+
+ q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f;
+
+ /* Boundary check */
+ if (q_coff > 15)
+ q_coff = 15;
+ if (q_coff < -16)
+ q_coff = -16;
+
+ /* Commit new I/Q value */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE |
+ ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
+
+ /* Re-enable calibration -if we don't we'll commit
+ * the same values again and again */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN);
+
+done:
+
+ /* TODO: Separate noise floor calibration from I/Q calibration
+ * since noise floor calibration interrupts rx path while I/Q
+ * calibration doesn't. We don't need to run noise floor calibration
+ * as often as I/Q calibration.*/
+ ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+
+ /* Initiate a gain_F calibration */
+ ath5k_hw_request_rfgain_probe(ah);
+
+ return 0;
+}
+
+/*
+ * Perform a PHY calibration
+ */
+int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ int ret;
+
+ if (ah->ah_radio == AR5K_RF5110)
+ ret = ath5k_hw_rf5110_calibrate(ah, channel);
+ else
+ ret = ath5k_hw_rf511x_calibrate(ah, channel);
+
+ return ret;
+}
+
+int ath5k_hw_phy_disable(struct ath5k_hw *ah)
+{
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
+
+ return 0;
+}
+
+/********************\
+ Misc PHY functions
+\********************/
+
+/*
+ * Get the PHY Chip revision
+ */
+u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
+{
+ unsigned int i;
+ u32 srev;
+ u16 ret;
+
+ /*
+ * Set the radio chip access register
+ */
+ switch (chan) {
+ case CHANNEL_2GHZ:
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
+ break;
+ case CHANNEL_5GHZ:
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+ break;
+ default:
+ return 0;
+ }
+
+ mdelay(2);
+
+ /* ...wait until PHY is ready and read the selected radio revision */
+ ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
+
+ for (i = 0; i < 8; i++)
+ ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
+
+ if (ah->ah_version == AR5K_AR5210) {
+ srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
+ ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
+ } else {
+ srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
+ ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
+ ((srev & 0x0f) << 4), 8);
+ }
+
+ /* Reset to the 5GHz mode */
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+
+ return ret;
+}
+
+void /*TODO:Boundary check*/
+ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant)
+{
+ if (ah->ah_version != AR5K_AR5210)
+ ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA);
+}
+
+unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah)
+{
+ if (ah->ah_version != AR5K_AR5210)
+ return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
+
+ return 0; /*XXX: What do we return for 5210 ?*/
+}
+
+
+/****************\
+* TX power setup *
+\****************/
+
+/*
+ * Helper functions
+ */
+
+/*
+ * Do linear interpolation between two given (x, y) points
+ */
+static s16
+ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right,
+ s16 y_left, s16 y_right)
+{
+ s16 ratio, result;
+
+ /* Avoid divide by zero and skip interpolation
+ * if we have the same point */
+ if ((x_left == x_right) || (y_left == y_right))
+ return y_left;
+
+ /*
+ * Since we use ints and not fps, we need to scale up in
+ * order to get a sane ratio value (or else we 'll eg. get
+ * always 1 instead of 1.25, 1.75 etc). We scale up by 100
+ * to have some accuracy both for 0.5 and 0.25 steps.
+ */
+ ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left));
+
+ /* Now scale down to be in range */
+ result = y_left + (ratio * (target - x_left) / 100);
+
+ return result;
+}
+
+/*
+ * Find vertical boundary (min pwr) for the linear PCDAC curve.
+ *
+ * Since we have the top of the curve and we draw the line below
+ * until we reach 1 (1 pcdac step) we need to know which point
+ * (x value) that is so that we don't go below y axis and have negative
+ * pcdac values when creating the curve, or fill the table with zeroes.
+ */
+static s16
+ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR,
+ const s16 *pwrL, const s16 *pwrR)
+{
+ s8 tmp;
+ s16 min_pwrL, min_pwrR;
+ s16 pwr_i;
+
+ if (pwrL[0] == pwrL[1])
+ min_pwrL = pwrL[0];
+ else {
+ pwr_i = pwrL[0];
+ do {
+ pwr_i--;
+ tmp = (s8) ath5k_get_interpolated_value(pwr_i,
+ pwrL[0], pwrL[1],
+ stepL[0], stepL[1]);
+ } while (tmp > 1);
+
+ min_pwrL = pwr_i;
+ }
+
+ if (pwrR[0] == pwrR[1])
+ min_pwrR = pwrR[0];
+ else {
+ pwr_i = pwrR[0];
+ do {
+ pwr_i--;
+ tmp = (s8) ath5k_get_interpolated_value(pwr_i,
+ pwrR[0], pwrR[1],
+ stepR[0], stepR[1]);
+ } while (tmp > 1);
+
+ min_pwrR = pwr_i;
+ }
+
+ /* Keep the right boundary so that it works for both curves */
+ return max(min_pwrL, min_pwrR);
+}
+
+/*
+ * Interpolate (pwr,vpd) points to create a Power to PDADC or a
+ * Power to PCDAC curve.
+ *
+ * Each curve has power on x axis (in 0.5dB units) and PCDAC/PDADC
+ * steps (offsets) on y axis. Power can go up to 31.5dB and max
+ * PCDAC/PDADC step for each curve is 64 but we can write more than
+ * one curves on hw so we can go up to 128 (which is the max step we
+ * can write on the final table).
+ *
+ * We write y values (PCDAC/PDADC steps) on hw.
+ */
+static void
+ath5k_create_power_curve(s16 pmin, s16 pmax,
+ const s16 *pwr, const u8 *vpd,
+ u8 num_points,
+ u8 *vpd_table, u8 type)
+{
+ u8 idx[2] = { 0, 1 };
+ s16 pwr_i = 2*pmin;
+ int i;
+
+ if (num_points < 2)
+ return;
+
+ /* We want the whole line, so adjust boundaries
+ * to cover the entire power range. Note that
+ * power values are already 0.25dB so no need
+ * to multiply pwr_i by 2 */
+ if (type == AR5K_PWRTABLE_LINEAR_PCDAC) {
+ pwr_i = pmin;
+ pmin = 0;
+ pmax = 63;
+ }
+
+ /* Find surrounding turning points (TPs)
+ * and interpolate between them */
+ for (i = 0; (i <= (u16) (pmax - pmin)) &&
+ (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
+
+ /* We passed the right TP, move to the next set of TPs
+ * if we pass the last TP, extrapolate above using the last
+ * two TPs for ratio */
+ if ((pwr_i > pwr[idx[1]]) && (idx[1] < num_points - 1)) {
+ idx[0]++;
+ idx[1]++;
+ }
+
+ vpd_table[i] = (u8) ath5k_get_interpolated_value(pwr_i,
+ pwr[idx[0]], pwr[idx[1]],
+ vpd[idx[0]], vpd[idx[1]]);
+
+ /* Increase by 0.5dB
+ * (0.25 dB units) */
+ pwr_i += 2;
+ }
+}
+
+/*
+ * Get the surrounding per-channel power calibration piers
+ * for a given frequency so that we can interpolate between
+ * them and come up with an apropriate dataset for our current
+ * channel.
+ */
+static void
+ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah,
+ struct net80211_channel *channel,
+ struct ath5k_chan_pcal_info **pcinfo_l,
+ struct ath5k_chan_pcal_info **pcinfo_r)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *pcinfo;
+ u8 idx_l, idx_r;
+ u8 mode, max, i;
+ u32 target = channel->center_freq;
+
+ idx_l = 0;
+ idx_r = 0;
+
+ if (!(channel->hw_value & CHANNEL_OFDM)) {
+ pcinfo = ee->ee_pwr_cal_b;
+ mode = AR5K_EEPROM_MODE_11B;
+ } else if (channel->hw_value & CHANNEL_2GHZ) {
+ pcinfo = ee->ee_pwr_cal_g;
+ mode = AR5K_EEPROM_MODE_11G;
+ } else {
+ pcinfo = ee->ee_pwr_cal_a;
+ mode = AR5K_EEPROM_MODE_11A;
+ }
+ max = ee->ee_n_piers[mode] - 1;
+
+ /* Frequency is below our calibrated
+ * range. Use the lowest power curve
+ * we have */
+ if (target < pcinfo[0].freq) {
+ idx_l = idx_r = 0;
+ goto done;
+ }
+
+ /* Frequency is above our calibrated
+ * range. Use the highest power curve
+ * we have */
+ if (target > pcinfo[max].freq) {
+ idx_l = idx_r = max;
+ goto done;
+ }
+
+ /* Frequency is inside our calibrated
+ * channel range. Pick the surrounding
+ * calibration piers so that we can
+ * interpolate */
+ for (i = 0; i <= max; i++) {
+
+ /* Frequency matches one of our calibration
+ * piers, no need to interpolate, just use
+ * that calibration pier */
+ if (pcinfo[i].freq == target) {
+ idx_l = idx_r = i;
+ goto done;
+ }
+
+ /* We found a calibration pier that's above
+ * frequency, use this pier and the previous
+ * one to interpolate */
+ if (target < pcinfo[i].freq) {
+ idx_r = i;
+ idx_l = idx_r - 1;
+ goto done;
+ }
+ }
+
+done:
+ *pcinfo_l = &pcinfo[idx_l];
+ *pcinfo_r = &pcinfo[idx_r];
+
+ return;
+}
+
+/*
+ * Get the surrounding per-rate power calibration data
+ * for a given frequency and interpolate between power
+ * values to set max target power supported by hw for
+ * each rate.
+ */
+static void
+ath5k_get_rate_pcal_data(struct ath5k_hw *ah,
+ struct net80211_channel *channel,
+ struct ath5k_rate_pcal_info *rates)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_rate_pcal_info *rpinfo;
+ u8 idx_l, idx_r;
+ u8 mode, max, i;
+ u32 target = channel->center_freq;
+
+ idx_l = 0;
+ idx_r = 0;
+
+ if (!(channel->hw_value & CHANNEL_OFDM)) {
+ rpinfo = ee->ee_rate_tpwr_b;
+ mode = AR5K_EEPROM_MODE_11B;
+ } else if (channel->hw_value & CHANNEL_2GHZ) {
+ rpinfo = ee->ee_rate_tpwr_g;
+ mode = AR5K_EEPROM_MODE_11G;
+ } else {
+ rpinfo = ee->ee_rate_tpwr_a;
+ mode = AR5K_EEPROM_MODE_11A;
+ }
+ max = ee->ee_rate_target_pwr_num[mode] - 1;
+
+ /* Get the surrounding calibration
+ * piers - same as above */
+ if (target < rpinfo[0].freq) {
+ idx_l = idx_r = 0;
+ goto done;
+ }
+
+ if (target > rpinfo[max].freq) {
+ idx_l = idx_r = max;
+ goto done;
+ }
+
+ for (i = 0; i <= max; i++) {
+
+ if (rpinfo[i].freq == target) {
+ idx_l = idx_r = i;
+ goto done;
+ }
+
+ if (target < rpinfo[i].freq) {
+ idx_r = i;
+ idx_l = idx_r - 1;
+ goto done;
+ }
+ }
+
+done:
+ /* Now interpolate power value, based on the frequency */
+ rates->freq = target;
+
+ rates->target_power_6to24 =
+ ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
+ rpinfo[idx_r].freq,
+ rpinfo[idx_l].target_power_6to24,
+ rpinfo[idx_r].target_power_6to24);
+
+ rates->target_power_36 =
+ ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
+ rpinfo[idx_r].freq,
+ rpinfo[idx_l].target_power_36,
+ rpinfo[idx_r].target_power_36);
+
+ rates->target_power_48 =
+ ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
+ rpinfo[idx_r].freq,
+ rpinfo[idx_l].target_power_48,
+ rpinfo[idx_r].target_power_48);
+
+ rates->target_power_54 =
+ ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
+ rpinfo[idx_r].freq,
+ rpinfo[idx_l].target_power_54,
+ rpinfo[idx_r].target_power_54);
+}
+
+/*
+ * Get the max edge power for this channel if
+ * we have such data from EEPROM's Conformance Test
+ * Limits (CTL), and limit max power if needed.
+ *
+ * FIXME: Only works for world regulatory domains
+ */
+static void
+ath5k_get_max_ctl_power(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_edge_power *rep = ee->ee_ctl_pwr;
+ u8 *ctl_val = ee->ee_ctl;
+ s16 max_chan_pwr = ah->ah_txpower.txp_max_pwr / 4;
+ s16 edge_pwr = 0;
+ u8 rep_idx;
+ u8 i, ctl_mode;
+ u8 ctl_idx = 0xFF;
+ u32 target = channel->center_freq;
+
+ /* Find out a CTL for our mode that's not mapped
+ * on a specific reg domain.
+ *
+ * TODO: Map our current reg domain to one of the 3 available
+ * reg domain ids so that we can support more CTLs. */
+ switch (channel->hw_value & CHANNEL_MODES) {
+ case CHANNEL_A:
+ ctl_mode = AR5K_CTL_11A | AR5K_CTL_NO_REGDOMAIN;
+ break;
+ case CHANNEL_G:
+ ctl_mode = AR5K_CTL_11G | AR5K_CTL_NO_REGDOMAIN;
+ break;
+ case CHANNEL_B:
+ ctl_mode = AR5K_CTL_11B | AR5K_CTL_NO_REGDOMAIN;
+ break;
+ case CHANNEL_T:
+ ctl_mode = AR5K_CTL_TURBO | AR5K_CTL_NO_REGDOMAIN;
+ break;
+ case CHANNEL_TG:
+ ctl_mode = AR5K_CTL_TURBOG | AR5K_CTL_NO_REGDOMAIN;
+ break;
+ case CHANNEL_XR:
+ /* Fall through */
+ default:
+ return;
+ }
+
+ for (i = 0; i < ee->ee_ctls; i++) {
+ if (ctl_val[i] == ctl_mode) {
+ ctl_idx = i;
+ break;
+ }
+ }
+
+ /* If we have a CTL dataset available grab it and find the
+ * edge power for our frequency */
+ if (ctl_idx == 0xFF)
+ return;
+
+ /* Edge powers are sorted by frequency from lower
+ * to higher. Each CTL corresponds to 8 edge power
+ * measurements. */
+ rep_idx = ctl_idx * AR5K_EEPROM_N_EDGES;
+
+ /* Don't do boundaries check because we
+ * might have more that one bands defined
+ * for this mode */
+
+ /* Get the edge power that's closer to our
+ * frequency */
+ for (i = 0; i < AR5K_EEPROM_N_EDGES; i++) {
+ rep_idx += i;
+ if (target <= rep[rep_idx].freq)
+ edge_pwr = (s16) rep[rep_idx].edge;
+ }
+
+ if (edge_pwr) {
+ ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr);
+ }
+}
+
+
+/*
+ * Power to PCDAC table functions
+ */
+
+/*
+ * Fill Power to PCDAC table on RF5111
+ *
+ * No further processing is needed for RF5111, the only thing we have to
+ * do is fill the values below and above calibration range since eeprom data
+ * may not cover the entire PCDAC table.
+ */
+static void
+ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,
+ s16 *table_max)
+{
+ u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
+ u8 *pcdac_tmp = ah->ah_txpower.tmpL[0];
+ u8 pcdac_0, pcdac_n, pcdac_i, pwr_idx, i;
+ s16 min_pwr, max_pwr;
+
+ /* Get table boundaries */
+ min_pwr = table_min[0];
+ pcdac_0 = pcdac_tmp[0];
+
+ max_pwr = table_max[0];
+ pcdac_n = pcdac_tmp[table_max[0] - table_min[0]];
+
+ /* Extrapolate below minimum using pcdac_0 */
+ pcdac_i = 0;
+ for (i = 0; i < min_pwr; i++)
+ pcdac_out[pcdac_i++] = pcdac_0;
+
+ /* Copy values from pcdac_tmp */
+ pwr_idx = min_pwr;
+ for (i = 0 ; pwr_idx <= max_pwr &&
+ pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {
+ pcdac_out[pcdac_i++] = pcdac_tmp[i];
+ pwr_idx++;
+ }
+
+ /* Extrapolate above maximum */
+ while (pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE)
+ pcdac_out[pcdac_i++] = pcdac_n;
+
+}
+
+/*
+ * Combine available XPD Curves and fill Linear Power to PCDAC table
+ * on RF5112
+ *
+ * RFX112 can have up to 2 curves (one for low txpower range and one for
+ * higher txpower range). We need to put them both on pcdac_out and place
+ * them in the correct location. In case we only have one curve available
+ * just fit it on pcdac_out (it's supposed to cover the entire range of
+ * available pwr levels since it's always the higher power curve). Extrapolate
+ * below and above final table if needed.
+ */
+static void
+ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
+ s16 *table_max, u8 pdcurves)
+{
+ u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
+ u8 *pcdac_low_pwr;
+ u8 *pcdac_high_pwr;
+ u8 *pcdac_tmp;
+ u8 pwr;
+ s16 max_pwr_idx;
+ s16 min_pwr_idx;
+ s16 mid_pwr_idx = 0;
+ /* Edge flag turs on the 7nth bit on the PCDAC
+ * to delcare the higher power curve (force values
+ * to be greater than 64). If we only have one curve
+ * we don't need to set this, if we have 2 curves and
+ * fill the table backwards this can also be used to
+ * switch from higher power curve to lower power curve */
+ u8 edge_flag;
+ int i;
+
+ /* When we have only one curve available
+ * that's the higher power curve. If we have
+ * two curves the first is the high power curve
+ * and the next is the low power curve. */
+ if (pdcurves > 1) {
+ pcdac_low_pwr = ah->ah_txpower.tmpL[1];
+ pcdac_high_pwr = ah->ah_txpower.tmpL[0];
+ mid_pwr_idx = table_max[1] - table_min[1] - 1;
+ max_pwr_idx = (table_max[0] - table_min[0]) / 2;
+
+ /* If table size goes beyond 31.5dB, keep the
+ * upper 31.5dB range when setting tx power.
+ * Note: 126 = 31.5 dB in quarter dB steps */
+ if (table_max[0] - table_min[1] > 126)
+ min_pwr_idx = table_max[0] - 126;
+ else
+ min_pwr_idx = table_min[1];
+
+ /* Since we fill table backwards
+ * start from high power curve */
+ pcdac_tmp = pcdac_high_pwr;
+
+ edge_flag = 0x40;
+ } else {
+ pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */
+ pcdac_high_pwr = ah->ah_txpower.tmpL[0];
+ min_pwr_idx = table_min[0];
+ max_pwr_idx = (table_max[0] - table_min[0]) / 2;
+ pcdac_tmp = pcdac_high_pwr;
+ edge_flag = 0;
+ }
+
+ /* This is used when setting tx power*/
+ ah->ah_txpower.txp_min_idx = min_pwr_idx/2;
+
+ /* Fill Power to PCDAC table backwards */
+ pwr = max_pwr_idx;
+ for (i = 63; i >= 0; i--) {
+ /* Entering lower power range, reset
+ * edge flag and set pcdac_tmp to lower
+ * power curve.*/
+ if (edge_flag == 0x40 &&
+ (2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {
+ edge_flag = 0x00;
+ pcdac_tmp = pcdac_low_pwr;
+ pwr = mid_pwr_idx/2;
+ }
+
+ /* Don't go below 1, extrapolate below if we have
+ * already swithced to the lower power curve -or
+ * we only have one curve and edge_flag is zero
+ * anyway */
+ if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) {
+ while (i >= 0) {
+ pcdac_out[i] = pcdac_out[i + 1];
+ i--;
+ }
+ break;
+ }
+
+ pcdac_out[i] = pcdac_tmp[pwr] | edge_flag;
+
+ /* Extrapolate above if pcdac is greater than
+ * 126 -this can happen because we OR pcdac_out
+ * value with edge_flag on high power curve */
+ if (pcdac_out[i] > 126)
+ pcdac_out[i] = 126;
+
+ /* Decrease by a 0.5dB step */
+ pwr--;
+ }
+}
+
+/* Write PCDAC values on hw */
+static void
+ath5k_setup_pcdac_table(struct ath5k_hw *ah)
+{
+ u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
+ int i;
+
+ /*
+ * Write TX power values
+ */
+ for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
+ ath5k_hw_reg_write(ah,
+ (((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) |
+ (((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16),
+ AR5K_PHY_PCDAC_TXPOWER(i));
+ }
+}
+
+
+/*
+ * Power to PDADC table functions
+ */
+
+/*
+ * Set the gain boundaries and create final Power to PDADC table
+ *
+ * We can have up to 4 pd curves, we need to do a simmilar process
+ * as we do for RF5112. This time we don't have an edge_flag but we
+ * set the gain boundaries on a separate register.
+ */
+static void
+ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah,
+ s16 *pwr_min, s16 *pwr_max, u8 pdcurves)
+{
+ u8 gain_boundaries[AR5K_EEPROM_N_PD_GAINS];
+ u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
+ u8 *pdadc_tmp;
+ s16 pdadc_0;
+ u8 pdadc_i, pdadc_n, pwr_step, pdg, max_idx, table_size;
+ u8 pd_gain_overlap;
+
+ /* Note: Register value is initialized on initvals
+ * there is no feedback from hw.
+ * XXX: What about pd_gain_overlap from EEPROM ? */
+ pd_gain_overlap = (u8) ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG5) &
+ AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP;
+
+ /* Create final PDADC table */
+ for (pdg = 0, pdadc_i = 0; pdg < pdcurves; pdg++) {
+ pdadc_tmp = ah->ah_txpower.tmpL[pdg];
+
+ if (pdg == pdcurves - 1)
+ /* 2 dB boundary stretch for last
+ * (higher power) curve */
+ gain_boundaries[pdg] = pwr_max[pdg] + 4;
+ else
+ /* Set gain boundary in the middle
+ * between this curve and the next one */
+ gain_boundaries[pdg] =
+ (pwr_max[pdg] + pwr_min[pdg + 1]) / 2;
+
+ /* Sanity check in case our 2 db stretch got out of
+ * range. */
+ if (gain_boundaries[pdg] > AR5K_TUNE_MAX_TXPOWER)
+ gain_boundaries[pdg] = AR5K_TUNE_MAX_TXPOWER;
+
+ /* For the first curve (lower power)
+ * start from 0 dB */
+ if (pdg == 0)
+ pdadc_0 = 0;
+ else
+ /* For the other curves use the gain overlap */
+ pdadc_0 = (gain_boundaries[pdg - 1] - pwr_min[pdg]) -
+ pd_gain_overlap;
+
+ /* Force each power step to be at least 0.5 dB */
+ if ((pdadc_tmp[1] - pdadc_tmp[0]) > 1)
+ pwr_step = pdadc_tmp[1] - pdadc_tmp[0];
+ else
+ pwr_step = 1;
+
+ /* If pdadc_0 is negative, we need to extrapolate
+ * below this pdgain by a number of pwr_steps */
+ while ((pdadc_0 < 0) && (pdadc_i < 128)) {
+ s16 tmp = pdadc_tmp[0] + pdadc_0 * pwr_step;
+ pdadc_out[pdadc_i++] = (tmp < 0) ? 0 : (u8) tmp;
+ pdadc_0++;
+ }
+
+ /* Set last pwr level, using gain boundaries */
+ pdadc_n = gain_boundaries[pdg] + pd_gain_overlap - pwr_min[pdg];
+ /* Limit it to be inside pwr range */
+ table_size = pwr_max[pdg] - pwr_min[pdg];
+ max_idx = (pdadc_n < table_size) ? pdadc_n : table_size;
+
+ /* Fill pdadc_out table */
+ while (pdadc_0 < max_idx)
+ pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++];
+
+ /* Need to extrapolate above this pdgain? */
+ if (pdadc_n <= max_idx)
+ continue;
+
+ /* Force each power step to be at least 0.5 dB */
+ if ((pdadc_tmp[table_size - 1] - pdadc_tmp[table_size - 2]) > 1)
+ pwr_step = pdadc_tmp[table_size - 1] -
+ pdadc_tmp[table_size - 2];
+ else
+ pwr_step = 1;
+
+ /* Extrapolate above */
+ while ((pdadc_0 < (s16) pdadc_n) &&
+ (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2)) {
+ s16 tmp = pdadc_tmp[table_size - 1] +
+ (pdadc_0 - max_idx) * pwr_step;
+ pdadc_out[pdadc_i++] = (tmp > 127) ? 127 : (u8) tmp;
+ pdadc_0++;
+ }
+ }
+
+ while (pdg < AR5K_EEPROM_N_PD_GAINS) {
+ gain_boundaries[pdg] = gain_boundaries[pdg - 1];
+ pdg++;
+ }
+
+ while (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2) {
+ pdadc_out[pdadc_i] = pdadc_out[pdadc_i - 1];
+ pdadc_i++;
+ }
+
+ /* Set gain boundaries */
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(pd_gain_overlap,
+ AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP) |
+ AR5K_REG_SM(gain_boundaries[0],
+ AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1) |
+ AR5K_REG_SM(gain_boundaries[1],
+ AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2) |
+ AR5K_REG_SM(gain_boundaries[2],
+ AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3) |
+ AR5K_REG_SM(gain_boundaries[3],
+ AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4),
+ AR5K_PHY_TPC_RG5);
+
+ /* Used for setting rate power table */
+ ah->ah_txpower.txp_min_idx = pwr_min[0];
+
+}
+
+/* Write PDADC values on hw */
+static void
+ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah,
+ u8 pdcurves, u8 *pdg_to_idx)
+{
+ u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
+ u32 reg;
+ u8 i;
+
+ /* Select the right pdgain curves */
+
+ /* Clear current settings */
+ reg = ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG1);
+ reg &= ~(AR5K_PHY_TPC_RG1_PDGAIN_1 |
+ AR5K_PHY_TPC_RG1_PDGAIN_2 |
+ AR5K_PHY_TPC_RG1_PDGAIN_3 |
+ AR5K_PHY_TPC_RG1_NUM_PD_GAIN);
+
+ /*
+ * Use pd_gains curve from eeprom
+ *
+ * This overrides the default setting from initvals
+ * in case some vendors (e.g. Zcomax) don't use the default
+ * curves. If we don't honor their settings we 'll get a
+ * 5dB (1 * gain overlap ?) drop.
+ */
+ reg |= AR5K_REG_SM(pdcurves, AR5K_PHY_TPC_RG1_NUM_PD_GAIN);
+
+ switch (pdcurves) {
+ case 3:
+ reg |= AR5K_REG_SM(pdg_to_idx[2], AR5K_PHY_TPC_RG1_PDGAIN_3);
+ /* Fall through */
+ case 2:
+ reg |= AR5K_REG_SM(pdg_to_idx[1], AR5K_PHY_TPC_RG1_PDGAIN_2);
+ /* Fall through */
+ case 1:
+ reg |= AR5K_REG_SM(pdg_to_idx[0], AR5K_PHY_TPC_RG1_PDGAIN_1);
+ break;
+ }
+ ath5k_hw_reg_write(ah, reg, AR5K_PHY_TPC_RG1);
+
+ /*
+ * Write TX power values
+ */
+ for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
+ ath5k_hw_reg_write(ah,
+ ((pdadc_out[4*i + 0] & 0xff) << 0) |
+ ((pdadc_out[4*i + 1] & 0xff) << 8) |
+ ((pdadc_out[4*i + 2] & 0xff) << 16) |
+ ((pdadc_out[4*i + 3] & 0xff) << 24),
+ AR5K_PHY_PDADC_TXPOWER(i));
+ }
+}
+
+
+/*
+ * Common code for PCDAC/PDADC tables
+ */
+
+/*
+ * This is the main function that uses all of the above
+ * to set PCDAC/PDADC table on hw for the current channel.
+ * This table is used for tx power calibration on the basband,
+ * without it we get weird tx power levels and in some cases
+ * distorted spectral mask
+ */
+static int
+ath5k_setup_channel_powertable(struct ath5k_hw *ah,
+ struct net80211_channel *channel,
+ u8 ee_mode, u8 type)
+{
+ struct ath5k_pdgain_info *pdg_L, *pdg_R;
+ struct ath5k_chan_pcal_info *pcinfo_L;
+ struct ath5k_chan_pcal_info *pcinfo_R;
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode];
+ s16 table_min[AR5K_EEPROM_N_PD_GAINS];
+ s16 table_max[AR5K_EEPROM_N_PD_GAINS];
+ u8 *tmpL;
+ u8 *tmpR;
+ u32 target = channel->center_freq;
+ int pdg, i;
+
+ /* Get surounding freq piers for this channel */
+ ath5k_get_chan_pcal_surrounding_piers(ah, channel,
+ &pcinfo_L,
+ &pcinfo_R);
+
+ /* Loop over pd gain curves on
+ * surounding freq piers by index */
+ for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) {
+
+ /* Fill curves in reverse order
+ * from lower power (max gain)
+ * to higher power. Use curve -> idx
+ * backmaping we did on eeprom init */
+ u8 idx = pdg_curve_to_idx[pdg];
+
+ /* Grab the needed curves by index */
+ pdg_L = &pcinfo_L->pd_curves[idx];
+ pdg_R = &pcinfo_R->pd_curves[idx];
+
+ /* Initialize the temp tables */
+ tmpL = ah->ah_txpower.tmpL[pdg];
+ tmpR = ah->ah_txpower.tmpR[pdg];
+
+ /* Set curve's x boundaries and create
+ * curves so that they cover the same
+ * range (if we don't do that one table
+ * will have values on some range and the
+ * other one won't have any so interpolation
+ * will fail) */
+ table_min[pdg] = min(pdg_L->pd_pwr[0],
+ pdg_R->pd_pwr[0]) / 2;
+
+ table_max[pdg] = max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
+ pdg_R->pd_pwr[pdg_R->pd_points - 1]) / 2;
+
+ /* Now create the curves on surrounding channels
+ * and interpolate if needed to get the final
+ * curve for this gain on this channel */
+ switch (type) {
+ case AR5K_PWRTABLE_LINEAR_PCDAC:
+ /* Override min/max so that we don't loose
+ * accuracy (don't divide by 2) */
+ table_min[pdg] = min(pdg_L->pd_pwr[0],
+ pdg_R->pd_pwr[0]);
+
+ table_max[pdg] =
+ max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
+ pdg_R->pd_pwr[pdg_R->pd_points - 1]);
+
+ /* Override minimum so that we don't get
+ * out of bounds while extrapolating
+ * below. Don't do this when we have 2
+ * curves and we are on the high power curve
+ * because table_min is ok in this case */
+ if (!(ee->ee_pd_gains[ee_mode] > 1 && pdg == 0)) {
+
+ table_min[pdg] =
+ ath5k_get_linear_pcdac_min(pdg_L->pd_step,
+ pdg_R->pd_step,
+ pdg_L->pd_pwr,
+ pdg_R->pd_pwr);
+
+ /* Don't go too low because we will
+ * miss the upper part of the curve.
+ * Note: 126 = 31.5dB (max power supported)
+ * in 0.25dB units */
+ if (table_max[pdg] - table_min[pdg] > 126)
+ table_min[pdg] = table_max[pdg] - 126;
+ }
+
+ /* Fall through */
+ case AR5K_PWRTABLE_PWR_TO_PCDAC:
+ case AR5K_PWRTABLE_PWR_TO_PDADC:
+
+ ath5k_create_power_curve(table_min[pdg],
+ table_max[pdg],
+ pdg_L->pd_pwr,
+ pdg_L->pd_step,
+ pdg_L->pd_points, tmpL, type);
+
+ /* We are in a calibration
+ * pier, no need to interpolate
+ * between freq piers */
+ if (pcinfo_L == pcinfo_R)
+ continue;
+
+ ath5k_create_power_curve(table_min[pdg],
+ table_max[pdg],
+ pdg_R->pd_pwr,
+ pdg_R->pd_step,
+ pdg_R->pd_points, tmpR, type);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Interpolate between curves
+ * of surounding freq piers to
+ * get the final curve for this
+ * pd gain. Re-use tmpL for interpolation
+ * output */
+ for (i = 0; (i < (u16) (table_max[pdg] - table_min[pdg])) &&
+ (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
+ tmpL[i] = (u8) ath5k_get_interpolated_value(target,
+ (s16) pcinfo_L->freq,
+ (s16) pcinfo_R->freq,
+ (s16) tmpL[i],
+ (s16) tmpR[i]);
+ }
+ }
+
+ /* Now we have a set of curves for this
+ * channel on tmpL (x range is table_max - table_min
+ * and y values are tmpL[pdg][]) sorted in the same
+ * order as EEPROM (because we've used the backmaping).
+ * So for RF5112 it's from higher power to lower power
+ * and for RF2413 it's from lower power to higher power.
+ * For RF5111 we only have one curve. */
+
+ /* Fill min and max power levels for this
+ * channel by interpolating the values on
+ * surounding channels to complete the dataset */
+ ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target,
+ (s16) pcinfo_L->freq,
+ (s16) pcinfo_R->freq,
+ pcinfo_L->min_pwr, pcinfo_R->min_pwr);
+
+ ah->ah_txpower.txp_max_pwr = ath5k_get_interpolated_value(target,
+ (s16) pcinfo_L->freq,
+ (s16) pcinfo_R->freq,
+ pcinfo_L->max_pwr, pcinfo_R->max_pwr);
+
+ /* We are ready to go, fill PCDAC/PDADC
+ * table and write settings on hardware */
+ switch (type) {
+ case AR5K_PWRTABLE_LINEAR_PCDAC:
+ /* For RF5112 we can have one or two curves
+ * and each curve covers a certain power lvl
+ * range so we need to do some more processing */
+ ath5k_combine_linear_pcdac_curves(ah, table_min, table_max,
+ ee->ee_pd_gains[ee_mode]);
+
+ /* Set txp.offset so that we can
+ * match max power value with max
+ * table index */
+ ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2);
+
+ /* Write settings on hw */
+ ath5k_setup_pcdac_table(ah);
+ break;
+ case AR5K_PWRTABLE_PWR_TO_PCDAC:
+ /* We are done for RF5111 since it has only
+ * one curve, just fit the curve on the table */
+ ath5k_fill_pwr_to_pcdac_table(ah, table_min, table_max);
+
+ /* No rate powertable adjustment for RF5111 */
+ ah->ah_txpower.txp_min_idx = 0;
+ ah->ah_txpower.txp_offset = 0;
+
+ /* Write settings on hw */
+ ath5k_setup_pcdac_table(ah);
+ break;
+ case AR5K_PWRTABLE_PWR_TO_PDADC:
+ /* Set PDADC boundaries and fill
+ * final PDADC table */
+ ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max,
+ ee->ee_pd_gains[ee_mode]);
+
+ /* Write settings on hw */
+ ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx);
+
+ /* Set txp.offset, note that table_min
+ * can be negative */
+ ah->ah_txpower.txp_offset = table_min[0];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Per-rate tx power setting
+ *
+ * This is the code that sets the desired tx power (below
+ * maximum) on hw for each rate (we also have TPC that sets
+ * power per packet). We do that by providing an index on the
+ * PCDAC/PDADC table we set up.
+ */
+
+/*
+ * Set rate power table
+ *
+ * For now we only limit txpower based on maximum tx power
+ * supported by hw (what's inside rate_info). We need to limit
+ * this even more, based on regulatory domain etc.
+ *
+ * Rate power table contains indices to PCDAC/PDADC table (0.5dB steps)
+ * and is indexed as follows:
+ * rates[0] - rates[7] -> OFDM rates
+ * rates[8] - rates[14] -> CCK rates
+ * rates[15] -> XR rates (they all have the same power)
+ */
+static void
+ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
+ struct ath5k_rate_pcal_info *rate_info,
+ u8 ee_mode)
+{
+ unsigned int i;
+ u16 *rates;
+
+ /* max_pwr is power level we got from driver/user in 0.5dB
+ * units, switch to 0.25dB units so we can compare */
+ max_pwr *= 2;
+ max_pwr = min(max_pwr, (u16) ah->ah_txpower.txp_max_pwr) / 2;
+
+ /* apply rate limits */
+ rates = ah->ah_txpower.txp_rates_power_table;
+
+ /* OFDM rates 6 to 24Mb/s */
+ for (i = 0; i < 5; i++)
+ rates[i] = min(max_pwr, rate_info->target_power_6to24);
+
+ /* Rest OFDM rates */
+ rates[5] = min(rates[0], rate_info->target_power_36);
+ rates[6] = min(rates[0], rate_info->target_power_48);
+ rates[7] = min(rates[0], rate_info->target_power_54);
+
+ /* CCK rates */
+ /* 1L */
+ rates[8] = min(rates[0], rate_info->target_power_6to24);
+ /* 2L */
+ rates[9] = min(rates[0], rate_info->target_power_36);
+ /* 2S */
+ rates[10] = min(rates[0], rate_info->target_power_36);
+ /* 5L */
+ rates[11] = min(rates[0], rate_info->target_power_48);
+ /* 5S */
+ rates[12] = min(rates[0], rate_info->target_power_48);
+ /* 11L */
+ rates[13] = min(rates[0], rate_info->target_power_54);
+ /* 11S */
+ rates[14] = min(rates[0], rate_info->target_power_54);
+
+ /* XR rates */
+ rates[15] = min(rates[0], rate_info->target_power_6to24);
+
+ /* CCK rates have different peak to average ratio
+ * so we have to tweak their power so that gainf
+ * correction works ok. For this we use OFDM to
+ * CCK delta from eeprom */
+ if ((ee_mode == AR5K_EEPROM_MODE_11G) &&
+ (ah->ah_phy_revision < AR5K_SREV_PHY_5212A))
+ for (i = 8; i <= 15; i++)
+ rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta;
+
+ ah->ah_txpower.txp_min_pwr = rates[7];
+ ah->ah_txpower.txp_max_pwr = rates[0];
+ ah->ah_txpower.txp_ofdm = rates[7];
+}
+
+
+/*
+ * Set transmition power
+ */
+int
+ath5k_hw_txpower(struct ath5k_hw *ah, struct net80211_channel *channel,
+ u8 ee_mode, u8 txpower)
+{
+ struct ath5k_rate_pcal_info rate_info;
+ u8 type;
+ int ret;
+
+ if (txpower > AR5K_TUNE_MAX_TXPOWER) {
+ DBG("ath5k: invalid tx power %d\n", txpower);
+ return -EINVAL;
+ }
+ if (txpower == 0)
+ txpower = AR5K_TUNE_DEFAULT_TXPOWER;
+
+ /* Reset TX power values */
+ memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
+ ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
+ ah->ah_txpower.txp_min_pwr = 0;
+ ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER;
+
+ /* Initialize TX power table */
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ type = AR5K_PWRTABLE_PWR_TO_PCDAC;
+ break;
+ case AR5K_RF5112:
+ type = AR5K_PWRTABLE_LINEAR_PCDAC;
+ break;
+ case AR5K_RF2413:
+ case AR5K_RF5413:
+ case AR5K_RF2316:
+ case AR5K_RF2317:
+ case AR5K_RF2425:
+ type = AR5K_PWRTABLE_PWR_TO_PDADC;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* FIXME: Only on channel/mode change */
+ ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type);
+ if (ret)
+ return ret;
+
+ /* Limit max power if we have a CTL available */
+ ath5k_get_max_ctl_power(ah, channel);
+
+ /* FIXME: Tx power limit for this regdomain
+ * XXX: Mac80211/CRDA will do that anyway ? */
+
+ /* FIXME: Antenna reduction stuff */
+
+ /* FIXME: Limit power on turbo modes */
+
+ /* FIXME: TPC scale reduction */
+
+ /* Get surounding channels for per-rate power table
+ * calibration */
+ ath5k_get_rate_pcal_data(ah, channel, &rate_info);
+
+ /* Setup rate power table */
+ ath5k_setup_rate_powertable(ah, txpower, &rate_info, ee_mode);
+
+ /* Write rate power table on hw */
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) |
+ AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) |
+ AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1);
+
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(7, 24) |
+ AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) |
+ AR5K_TXPOWER_OFDM(4, 0), AR5K_PHY_TXPOWER_RATE2);
+
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(10, 24) |
+ AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) |
+ AR5K_TXPOWER_CCK(8, 0), AR5K_PHY_TXPOWER_RATE3);
+
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(14, 24) |
+ AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) |
+ AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4);
+
+ /* FIXME: TPC support */
+ if (ah->ah_txpower.txp_tpc) {
+ ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE |
+ AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
+
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_ACK) |
+ AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CTS) |
+ AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CHIRP),
+ AR5K_TPC);
+ } else {
+ ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX |
+ AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
+ }
+
+ return 0;
+}
+
+int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 mode, u8 txpower)
+{
+ struct net80211_channel *channel = ah->ah_current_channel;
+
+ DBG2("ath5k: changing txpower to %d\n", txpower);
+
+ return ath5k_hw_txpower(ah, channel, mode, txpower);
+}
+
+#undef _ATH5K_PHY
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_qcu.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_qcu.c
new file mode 100644
index 00000000..e38dba9e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_qcu.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Lightly modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/********************************************\
+Queue Control Unit, DFS Control Unit Functions
+\********************************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*
+ * Set properties for a transmit queue
+ */
+int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah,
+ const struct ath5k_txq_info *queue_info)
+{
+ if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return -EIO;
+
+ memcpy(&ah->ah_txq, queue_info, sizeof(struct ath5k_txq_info));
+
+ /*XXX: Is this supported on 5210 ?*/
+ if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
+ ((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
+ (queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
+ queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
+ ah->ah_txq.tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
+
+ return 0;
+}
+
+/*
+ * Initialize a transmit queue
+ */
+int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
+ struct ath5k_txq_info *queue_info)
+{
+ int ret;
+
+ /*
+ * Setup internal queue structure
+ */
+ memset(&ah->ah_txq, 0, sizeof(struct ath5k_txq_info));
+ ah->ah_txq.tqi_type = queue_type;
+
+ if (queue_info != NULL) {
+ queue_info->tqi_type = queue_type;
+ ret = ath5k_hw_set_tx_queueprops(ah, queue_info);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * We use ah_txq_status to hold a temp value for
+ * the Secondary interrupt mask registers on 5211+
+ * check out ath5k_hw_reset_tx_queue
+ */
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_status, 0);
+
+ return 0;
+}
+
+/*
+ * Set a transmit queue inactive
+ */
+void ath5k_hw_release_tx_queue(struct ath5k_hw *ah)
+{
+ /* This queue will be skipped in further operations */
+ ah->ah_txq.tqi_type = AR5K_TX_QUEUE_INACTIVE;
+ /*For SIMR setup*/
+ AR5K_Q_DISABLE_BITS(ah->ah_txq_status, 0);
+}
+
+/*
+ * Set DFS properties for a transmit queue on DCU
+ */
+int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah)
+{
+ u32 cw_min, cw_max, retry_lg, retry_sh;
+ struct ath5k_txq_info *tq = &ah->ah_txq;
+ const int queue = 0;
+
+ tq = &ah->ah_txq;
+
+ if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return 0;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ /* Only handle data queues, others will be ignored */
+ if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
+ return 0;
+
+ /* Set Slot time */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
+ AR5K_SLOT_TIME);
+ /* Set ACK_CTS timeout */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
+ AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
+ /* Set Transmit Latency */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_TRANSMIT_LATENCY_TURBO :
+ AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
+
+ /* Set IFS0 */
+ if (ah->ah_turbo) {
+ ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
+ (ah->ah_aifs + tq->tqi_aifs) *
+ AR5K_INIT_SLOT_TIME_TURBO) <<
+ AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
+ AR5K_IFS0);
+ } else {
+ ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
+ (ah->ah_aifs + tq->tqi_aifs) *
+ AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
+ AR5K_INIT_SIFS, AR5K_IFS0);
+ }
+
+ /* Set IFS1 */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
+ AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
+ /* Set AR5K_PHY_SETTLING */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
+ | 0x38 :
+ (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
+ | 0x1C,
+ AR5K_PHY_SETTLING);
+ /* Set Frame Control Register */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
+ AR5K_PHY_TURBO_SHORT | 0x2020) :
+ (AR5K_PHY_FRAME_CTL_INI | 0x1020),
+ AR5K_PHY_FRAME_CTL_5210);
+ }
+
+ /*
+ * Calculate cwmin/max by channel mode
+ */
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
+ ah->ah_aifs = AR5K_TUNE_AIFS;
+ /*XR is only supported on 5212*/
+ if (IS_CHAN_XR(ah->ah_current_channel) &&
+ ah->ah_version == AR5K_AR5212) {
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
+ ah->ah_aifs = AR5K_TUNE_AIFS_XR;
+ /*B mode is not supported on 5210*/
+ } else if (IS_CHAN_B(ah->ah_current_channel) &&
+ ah->ah_version != AR5K_AR5210) {
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
+ ah->ah_aifs = AR5K_TUNE_AIFS_11B;
+ }
+
+ cw_min = 1;
+ while (cw_min < ah->ah_cw_min)
+ cw_min = (cw_min << 1) | 1;
+
+ cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
+ ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
+ cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
+ ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
+
+ /*
+ * Calculate and set retry limits
+ */
+ if (ah->ah_software_retry) {
+ /* XXX Need to test this */
+ retry_lg = ah->ah_limit_tx_retries;
+ retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
+ AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg;
+ } else {
+ retry_lg = AR5K_INIT_LG_RETRY;
+ retry_sh = AR5K_INIT_SH_RETRY;
+ }
+
+ /*No QCU/DCU [5210]*/
+ if (ah->ah_version == AR5K_AR5210) {
+ ath5k_hw_reg_write(ah,
+ (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
+ | AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
+ AR5K_NODCU_RETRY_LMT_SLG_RETRY)
+ | AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
+ AR5K_NODCU_RETRY_LMT_SSH_RETRY)
+ | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
+ | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
+ AR5K_NODCU_RETRY_LMT);
+ } else {
+ /*QCU/DCU [5211+]*/
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
+ AR5K_DCU_RETRY_LMT_SLG_RETRY) |
+ AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
+ AR5K_DCU_RETRY_LMT_SSH_RETRY) |
+ AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
+ AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
+ AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
+
+ /*===Rest is also for QCU/DCU only [5211+]===*/
+
+ /*
+ * Set initial content window (cw_min/cw_max)
+ * and arbitrated interframe space (aifs)...
+ */
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
+ AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
+ AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
+ AR5K_DCU_LCL_IFS_AIFS),
+ AR5K_QUEUE_DFS_LOCAL_IFS(queue));
+
+ /*
+ * Set misc registers
+ */
+ /* Enable DCU early termination for this queue */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_DCU_EARLY);
+
+ /* Enable DCU to wait for next fragment from QCU */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ AR5K_DCU_MISC_FRAG_WAIT);
+
+ /* On Maui and Spirit use the global seqnum on DCU */
+ if (ah->ah_mac_version < AR5K_SREV_AR5211)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ AR5K_DCU_MISC_SEQNUM_CTL);
+
+ if (tq->tqi_cbr_period) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
+ AR5K_QCU_CBRCFG_INTVAL) |
+ AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
+ AR5K_QCU_CBRCFG_ORN_THRES),
+ AR5K_QUEUE_CBRCFG(queue));
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_FRSHED_CBR);
+ if (tq->tqi_cbr_overflow_limit)
+ AR5K_REG_ENABLE_BITS(ah,
+ AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_CBR_THRES_ENABLE);
+ }
+
+ if (tq->tqi_ready_time &&
+ (tq->tqi_type != AR5K_TX_QUEUE_CAB))
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
+ AR5K_QCU_RDYTIMECFG_INTVAL) |
+ AR5K_QCU_RDYTIMECFG_ENABLE,
+ AR5K_QUEUE_RDYTIMECFG(queue));
+
+ if (tq->tqi_burst_time) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
+ AR5K_DCU_CHAN_TIME_DUR) |
+ AR5K_DCU_CHAN_TIME_ENABLE,
+ AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
+
+ if (tq->tqi_flags
+ & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
+ AR5K_REG_ENABLE_BITS(ah,
+ AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_RDY_VEOL_POLICY);
+ }
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
+ AR5K_QUEUE_DFS_MISC(queue));
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
+ AR5K_QUEUE_DFS_MISC(queue));
+
+ /* TODO: Handle frame compression */
+
+ /*
+ * Enable interrupts for this tx queue
+ * in the secondary interrupt mask registers
+ */
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
+
+ /* Update secondary interrupt mask registers */
+
+ /* Filter out inactive queues */
+ ah->ah_txq_imr_txok &= ah->ah_txq_status;
+ ah->ah_txq_imr_txerr &= ah->ah_txq_status;
+ ah->ah_txq_imr_txurn &= ah->ah_txq_status;
+ ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
+ ah->ah_txq_imr_txeol &= ah->ah_txq_status;
+ ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
+ ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
+ ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
+ ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
+ AR5K_SIMR0_QCU_TXOK) |
+ AR5K_REG_SM(ah->ah_txq_imr_txdesc,
+ AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
+ AR5K_SIMR1_QCU_TXERR) |
+ AR5K_REG_SM(ah->ah_txq_imr_txeol,
+ AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
+ /* Update simr2 but don't overwrite rest simr2 settings */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
+ AR5K_REG_SM(ah->ah_txq_imr_txurn,
+ AR5K_SIMR2_QCU_TXURN));
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
+ AR5K_SIMR3_QCBRORN) |
+ AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
+ AR5K_SIMR3_QCBRURN), AR5K_SIMR3);
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
+ AR5K_SIMR4_QTRIG), AR5K_SIMR4);
+ /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
+ AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
+ /* No queue has TXNOFRM enabled, disable the interrupt
+ * by setting AR5K_TXNOFRM to zero */
+ if (ah->ah_txq_imr_nofrm == 0)
+ ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
+
+ /* Set QCU mask for this DCU to save power */
+ AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
+ }
+
+ return 0;
+}
+
+/*
+ * Set slot time on DCU
+ */
+int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
+{
+ if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX)
+ return -EINVAL;
+
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time,
+ ah->ah_turbo), AR5K_SLOT_TIME);
+ else
+ ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT);
+
+ return 0;
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_reset.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_reset.c
new file mode 100644
index 00000000..2f36a4e9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_reset.c
@@ -0,0 +1,1174 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Lightly modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+#define _ATH5K_RESET
+
+/*****************************\
+ Reset functions and helpers
+\*****************************/
+
+#include <ipxe/pci.h> /* To determine if a card is pci-e */
+#include <unistd.h>
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/* Find last set bit; fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32 */
+static int fls(int x)
+{
+ int r = 32;
+
+ if (!x)
+ return 0;
+ if (!(x & 0xffff0000u)) {
+ x <<= 16;
+ r -= 16;
+ }
+ if (!(x & 0xff000000u)) {
+ x <<= 8;
+ r -= 8;
+ }
+ if (!(x & 0xf0000000u)) {
+ x <<= 4;
+ r -= 4;
+ }
+ if (!(x & 0xc0000000u)) {
+ x <<= 2;
+ r -= 2;
+ }
+ if (!(x & 0x80000000u)) {
+ x <<= 1;
+ r -= 1;
+ }
+ return r;
+}
+
+
+/**
+ * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
+ *
+ * @ah: the &struct ath5k_hw
+ * @channel: the currently set channel upon reset
+ *
+ * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
+ * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset().
+ *
+ * Since delta slope is floating point we split it on its exponent and
+ * mantissa and provide these values on hw.
+ *
+ * For more infos i think this patent is related
+ * http://www.freepatentsonline.com/7184495.html
+ */
+static int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ /* Get exponent and mantissa and set it */
+ u32 coef_scaled, coef_exp, coef_man,
+ ds_coef_exp, ds_coef_man, clock;
+
+ if (!(ah->ah_version == AR5K_AR5212) ||
+ !(channel->hw_value & CHANNEL_OFDM)) {
+ DBG("ath5k: attempt to set OFDM timings on non-OFDM channel\n");
+ return -EFAULT;
+ }
+
+ /* Get coefficient
+ * ALGO: coef = (5 * clock * carrier_freq) / 2)
+ * we scale coef by shifting clock value by 24 for
+ * better precision since we use integers */
+ /* TODO: Half/quarter rate */
+ clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO);
+
+ coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;
+
+ /* Get exponent
+ * ALGO: coef_exp = 14 - highest set bit position */
+ coef_exp = fls(coef_scaled) - 1;
+
+ /* Doesn't make sense if it's zero*/
+ if (!coef_scaled || !coef_exp)
+ return -EINVAL;
+
+ /* Note: we've shifted coef_scaled by 24 */
+ coef_exp = 14 - (coef_exp - 24);
+
+
+ /* Get mantissa (significant digits)
+ * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */
+ coef_man = coef_scaled +
+ (1 << (24 - coef_exp - 1));
+
+ /* Calculate delta slope coefficient exponent
+ * and mantissa (remove scaling) and set them on hw */
+ ds_coef_man = coef_man >> (24 - coef_exp);
+ ds_coef_exp = coef_exp - 16;
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+ AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+ AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
+
+ return 0;
+}
+
+
+/*
+ * index into rates for control rates, we can set it up like this because
+ * this is only used for AR5212 and we know it supports G mode
+ */
+static const unsigned int control_rates[] =
+ { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 };
+
+/**
+ * ath5k_hw_write_rate_duration - fill rate code to duration table
+ *
+ * @ah: the &struct ath5k_hw
+ * @mode: one of enum ath5k_driver_mode
+ *
+ * Write the rate code to duration table upon hw reset. This is a helper for
+ * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on
+ * the hardware, based on current mode, for each rate. The rates which are
+ * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
+ * different rate code so we write their value twice (one for long preample
+ * and one for short).
+ *
+ * Note: Band doesn't matter here, if we set the values for OFDM it works
+ * on both a and g modes. So all we have to do is set values for all g rates
+ * that include all OFDM and CCK rates. If we operate in turbo or xr/half/
+ * quarter rate mode, we need to use another set of bitrates (that's why we
+ * need the mode parameter) but we don't handle these proprietary modes yet.
+ */
+static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
+ unsigned int mode __unused)
+{
+ struct ath5k_softc *sc = ah->ah_sc;
+ u16 rate;
+ int i;
+
+ /* Write rate duration table */
+ for (i = 0; i < sc->hwinfo->nr_rates[NET80211_BAND_2GHZ]; i++) {
+ u32 reg;
+ u16 tx_time;
+
+ rate = sc->hwinfo->rates[NET80211_BAND_2GHZ][i];
+
+ /* Set ACK timeout */
+ reg = AR5K_RATE_DUR(ath5k_bitrate_to_hw_rix(rate));
+
+ /* An ACK frame consists of 10 bytes. If you add the FCS,
+ * it's 14 bytes. Note we use the control rate and not the
+ * actual rate for this rate. See mac80211 tx.c
+ * ieee80211_duration() for a brief description of
+ * what rate we should choose to TX ACKs. */
+ tx_time = net80211_duration(sc->dev, 14, rate);
+
+ ath5k_hw_reg_write(ah, tx_time, reg);
+
+ if (rate != 20 && rate != 55 && rate != 110)
+ continue;
+
+ /*
+ * We're not distinguishing short preamble here,
+ * This is true, all we'll get is a longer value here
+ * which is not necessarilly bad.
+ */
+ ath5k_hw_reg_write(ah, tx_time,
+ reg + (AR5K_SET_SHORT_PREAMBLE << 2));
+ }
+}
+
+/*
+ * Reset chipset
+ */
+static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
+{
+ int ret;
+ u32 mask = val ? val : ~0U;
+
+ /* Read-and-clear RX Descriptor Pointer*/
+ ath5k_hw_reg_read(ah, AR5K_RXDP);
+
+ /*
+ * Reset the device and wait until success
+ */
+ ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL);
+
+ /* Wait at least 128 PCI clocks */
+ udelay(15);
+
+ if (ah->ah_version == AR5K_AR5210) {
+ val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
+ | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
+ mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
+ | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
+ } else {
+ val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
+ mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
+ }
+
+ ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, 0);
+
+ /*
+ * Reset configuration register (for hw byte-swap). Note that this
+ * is only set for big endian. We do the necessary magic in
+ * AR5K_INIT_CFG.
+ */
+ if ((val & AR5K_RESET_CTL_PCU) == 0)
+ ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
+
+ return ret;
+}
+
+/*
+ * Sleep control
+ */
+int ath5k_hw_wake(struct ath5k_hw *ah)
+{
+ unsigned int i;
+ u32 staid, data;
+
+ staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
+ staid &= ~AR5K_STA_ID1_PWR_SV;
+
+ /* Preserve sleep duration */
+ data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
+ if (data & 0xffc00000)
+ data = 0;
+ else
+ data = data & 0xfffcffff;
+
+ ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+ udelay(15);
+
+ for (i = 50; i > 0; i--) {
+ /* Check if the chip did wake up */
+ if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
+ AR5K_PCICFG_SPWR_DN) == 0)
+ break;
+
+ /* Wait a bit and retry */
+ udelay(200);
+ ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+ }
+
+ /* Fail if the chip didn't wake up */
+ if (i <= 0)
+ return -EIO;
+
+ ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1);
+
+ return 0;
+}
+
+/*
+ * Bring up MAC + PHY Chips and program PLL
+ * TODO: Half/Quarter rate support
+ */
+int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, int initial __unused)
+{
+ struct pci_device *pdev = ah->ah_sc->pdev;
+ u32 turbo, mode, clock, bus_flags;
+ int ret;
+
+ turbo = 0;
+ mode = 0;
+ clock = 0;
+
+ /* Wakeup the device */
+ ret = ath5k_hw_wake(ah);
+ if (ret) {
+ DBG("ath5k: failed to wake up the MAC chip\n");
+ return ret;
+ }
+
+ if (ah->ah_version != AR5K_AR5210) {
+ /*
+ * Get channel mode flags
+ */
+
+ if (ah->ah_radio >= AR5K_RF5112) {
+ mode = AR5K_PHY_MODE_RAD_RF5112;
+ clock = AR5K_PHY_PLL_RF5112;
+ } else {
+ mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/
+ clock = AR5K_PHY_PLL_RF5111; /*Zero*/
+ }
+
+ if (flags & CHANNEL_2GHZ) {
+ mode |= AR5K_PHY_MODE_FREQ_2GHZ;
+ clock |= AR5K_PHY_PLL_44MHZ;
+
+ if (flags & CHANNEL_CCK) {
+ mode |= AR5K_PHY_MODE_MOD_CCK;
+ } else if (flags & CHANNEL_OFDM) {
+ /* XXX Dynamic OFDM/CCK is not supported by the
+ * AR5211 so we set MOD_OFDM for plain g (no
+ * CCK headers) operation. We need to test
+ * this, 5211 might support ofdm-only g after
+ * all, there are also initial register values
+ * in the code for g mode (see initvals.c). */
+ if (ah->ah_version == AR5K_AR5211)
+ mode |= AR5K_PHY_MODE_MOD_OFDM;
+ else
+ mode |= AR5K_PHY_MODE_MOD_DYN;
+ } else {
+ DBG("ath5k: invalid radio modulation mode\n");
+ return -EINVAL;
+ }
+ } else if (flags & CHANNEL_5GHZ) {
+ mode |= AR5K_PHY_MODE_FREQ_5GHZ;
+
+ if (ah->ah_radio == AR5K_RF5413)
+ clock = AR5K_PHY_PLL_40MHZ_5413;
+ else
+ clock |= AR5K_PHY_PLL_40MHZ;
+
+ if (flags & CHANNEL_OFDM)
+ mode |= AR5K_PHY_MODE_MOD_OFDM;
+ else {
+ DBG("ath5k: invalid radio modulation mode\n");
+ return -EINVAL;
+ }
+ } else {
+ DBG("ath5k: invalid radio frequency mode\n");
+ return -EINVAL;
+ }
+
+ if (flags & CHANNEL_TURBO)
+ turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT;
+ } else { /* Reset the device */
+
+ /* ...enable Atheros turbo mode if requested */
+ if (flags & CHANNEL_TURBO)
+ ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
+ AR5K_PHY_TURBO);
+ }
+
+ /* reseting PCI on PCI-E cards results card to hang
+ * and always return 0xffff... so we ingore that flag
+ * for PCI-E cards */
+ if (pci_find_capability(pdev, PCI_CAP_ID_EXP))
+ bus_flags = 0;
+ else
+ bus_flags = AR5K_RESET_CTL_PCI;
+
+ /* Reset chipset */
+ if (ah->ah_version == AR5K_AR5210) {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
+ AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
+ mdelay(2);
+ } else {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_BASEBAND | bus_flags);
+ }
+ if (ret) {
+ DBG("ath5k: failed to reset the MAC chip\n");
+ return -EIO;
+ }
+
+ /* ...wakeup again!*/
+ ret = ath5k_hw_wake(ah);
+ if (ret) {
+ DBG("ath5k: failed to resume the MAC chip\n");
+ return ret;
+ }
+
+ /* ...final warm reset */
+ if (ath5k_hw_nic_reset(ah, 0)) {
+ DBG("ath5k: failed to warm reset the MAC chip\n");
+ return -EIO;
+ }
+
+ if (ah->ah_version != AR5K_AR5210) {
+
+ /* ...update PLL if needed */
+ if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) {
+ ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
+ udelay(300);
+ }
+
+ /* ...set the PHY operating mode */
+ ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
+ ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
+ }
+
+ return 0;
+}
+
+static int ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ u8 refclk_freq;
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+ refclk_freq = 40;
+ else
+ refclk_freq = 32;
+
+ if ((channel->center_freq % refclk_freq != 0) &&
+ ((channel->center_freq % refclk_freq < 10) ||
+ (channel->center_freq % refclk_freq > 22)))
+ return 1;
+ else
+ return 0;
+}
+
+/* TODO: Half/Quarter rate */
+static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ if (ah->ah_version == AR5K_AR5212 &&
+ ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
+
+ /* Setup ADC control */
+ ath5k_hw_reg_write(ah,
+ (AR5K_REG_SM(2,
+ AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) |
+ AR5K_REG_SM(2,
+ AR5K_PHY_ADC_CTL_INBUFGAIN_ON) |
+ AR5K_PHY_ADC_CTL_PWD_DAC_OFF |
+ AR5K_PHY_ADC_CTL_PWD_ADC_OFF),
+ AR5K_PHY_ADC_CTL);
+
+
+
+ /* Disable barker RSSI threshold */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
+ AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
+ AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2);
+
+ /* Set the mute mask */
+ ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
+ }
+
+ /* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */
+ if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B)
+ ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH);
+
+ /* Enable DCU double buffering */
+ if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B)
+ AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_DCU_DBL_BUF_DIS);
+
+ /* Set DAC/ADC delays */
+ if (ah->ah_version == AR5K_AR5212) {
+ u32 scal;
+ if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
+ scal = AR5K_PHY_SCAL_32MHZ_2417;
+ else if (ath5k_eeprom_is_hb63(ah))
+ scal = AR5K_PHY_SCAL_32MHZ_HB63;
+ else
+ scal = AR5K_PHY_SCAL_32MHZ;
+ ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
+ }
+
+ /* Set fast ADC */
+ if ((ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
+ u32 fast_adc = 1;
+
+ if (channel->center_freq == 2462 ||
+ channel->center_freq == 2467)
+ fast_adc = 0;
+
+ /* Only update if needed */
+ if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc)
+ ath5k_hw_reg_write(ah, fast_adc,
+ AR5K_PHY_FAST_ADC);
+ }
+
+ /* Fix for first revision of the RF5112 RF chipset */
+ if (ah->ah_radio == AR5K_RF5112 &&
+ ah->ah_radio_5ghz_revision <
+ AR5K_SREV_RAD_5112A) {
+ u32 data;
+ ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
+ AR5K_PHY_CCKTXCTL);
+ if (channel->hw_value & CHANNEL_5GHZ)
+ data = 0xffb81020;
+ else
+ data = 0xffb80d20;
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
+ }
+
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+ u32 usec_reg;
+ /* 5311 has different tx/rx latency masks
+ * from 5211, since we deal 5311 the same
+ * as 5211 when setting initvals, shift
+ * values here to their proper locations */
+ usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
+ ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 |
+ AR5K_USEC_32 |
+ AR5K_USEC_TX_LATENCY_5211 |
+ AR5K_REG_SM(29,
+ AR5K_USEC_RX_LATENCY_5210)),
+ AR5K_USEC_5211);
+ /* Clear QCU/DCU clock gating register */
+ ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT);
+ /* Set DAC/ADC delays */
+ ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL);
+ /* Enable PCU FIFO corruption ECO */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
+ AR5K_DIAG_SW_ECO_ENABLE);
+ }
+}
+
+static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
+ struct net80211_channel *channel, u8 *ant, u8 ee_mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ s16 cck_ofdm_pwr_delta;
+
+ /* Adjust power delta for channel 14 */
+ if (channel->center_freq == 2484)
+ cck_ofdm_pwr_delta =
+ ((ee->ee_cck_ofdm_power_delta -
+ ee->ee_scaled_cck_delta) * 2) / 10;
+ else
+ cck_ofdm_pwr_delta =
+ (ee->ee_cck_ofdm_power_delta * 2) / 10;
+
+ /* Set CCK to OFDM power delta on tx power
+ * adjustment register */
+ if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
+ if (channel->hw_value == CHANNEL_G)
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1),
+ AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
+ AR5K_REG_SM((cck_ofdm_pwr_delta * -1),
+ AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX),
+ AR5K_PHY_TX_PWR_ADJ);
+ else
+ ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ);
+ } else {
+ /* For older revs we scale power on sw during tx power
+ * setup */
+ ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta;
+ ah->ah_txpower.txp_cck_ofdm_gainf_delta =
+ ee->ee_cck_ofdm_gain_delta;
+ }
+
+ /* Set antenna idle switch table */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL,
+ AR5K_PHY_ANT_CTL_SWTABLE_IDLE,
+ (ah->ah_antenna[ee_mode][0] |
+ AR5K_PHY_ANT_CTL_TXRX_EN));
+
+ /* Set antenna switch table */
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]],
+ AR5K_PHY_ANT_SWITCH_TABLE_0);
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]],
+ AR5K_PHY_ANT_SWITCH_TABLE_1);
+
+ /* Noise floor threshold */
+ ath5k_hw_reg_write(ah,
+ AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
+ AR5K_PHY_NFTHRES);
+
+ if ((channel->hw_value & CHANNEL_TURBO) &&
+ (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) {
+ /* Switch settling time (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+ AR5K_PHY_SETTLING_SWITCH,
+ ee->ee_switch_settling_turbo[ee_mode]);
+
+ /* Tx/Rx attenuation (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
+ AR5K_PHY_GAIN_TXRX_ATTEN,
+ ee->ee_atn_tx_rx_turbo[ee_mode]);
+
+ /* ADC/PGA desired size (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_ADC,
+ ee->ee_adc_desired_size_turbo[ee_mode]);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_PGA,
+ ee->ee_pga_desired_size_turbo[ee_mode]);
+
+ /* Tx/Rx margin (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
+ AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
+ ee->ee_margin_tx_rx_turbo[ee_mode]);
+
+ } else {
+ /* Switch settling time */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+ AR5K_PHY_SETTLING_SWITCH,
+ ee->ee_switch_settling[ee_mode]);
+
+ /* Tx/Rx attenuation */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
+ AR5K_PHY_GAIN_TXRX_ATTEN,
+ ee->ee_atn_tx_rx[ee_mode]);
+
+ /* ADC/PGA desired size */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_ADC,
+ ee->ee_adc_desired_size[ee_mode]);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_PGA,
+ ee->ee_pga_desired_size[ee_mode]);
+
+ /* Tx/Rx margin */
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
+ AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
+ ee->ee_margin_tx_rx[ee_mode]);
+ }
+
+ /* XPA delays */
+ ath5k_hw_reg_write(ah,
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
+ (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
+ (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
+
+ /* XLNA delay */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3,
+ AR5K_PHY_RF_CTL3_TXE2XLNA_ON,
+ ee->ee_tx_end2xlna_enable[ee_mode]);
+
+ /* Thresh64 (ANI) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF,
+ AR5K_PHY_NF_THRESH62,
+ ee->ee_thr_62[ee_mode]);
+
+
+ /* False detect backoff for channels
+ * that have spur noise. Write the new
+ * cyclic power RSSI threshold. */
+ if (ath5k_hw_chan_has_spur_noise(ah, channel))
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
+ AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
+ AR5K_INIT_CYCRSSI_THR1 +
+ ee->ee_false_detect[ee_mode]);
+ else
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
+ AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
+ AR5K_INIT_CYCRSSI_THR1);
+
+ /* I/Q correction
+ * TODO: Per channel i/q infos ? */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CORR_ENABLE |
+ (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
+ ee->ee_q_cal[ee_mode]);
+
+ /* Heavy clipping -disable for now */
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1)
+ ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE);
+
+ return;
+}
+
+/*
+ * Main reset function
+ */
+int ath5k_hw_reset(struct ath5k_hw *ah,
+ struct net80211_channel *channel, int change_channel)
+{
+ u32 s_seq[10], s_ant, s_led[3], staid1_flags;
+ u32 phy_tst1;
+ u8 mode, freq, ee_mode, ant[2];
+ int i, ret;
+
+ s_ant = 0;
+ ee_mode = 0;
+ staid1_flags = 0;
+ freq = 0;
+ mode = 0;
+
+ /*
+ * Save some registers before a reset
+ */
+ /*DCU/Antenna selection not available on 5210*/
+ if (ah->ah_version != AR5K_AR5210) {
+
+ switch (channel->hw_value & CHANNEL_MODES) {
+ case CHANNEL_A:
+ mode = AR5K_MODE_11A;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ case CHANNEL_G:
+ mode = AR5K_MODE_11G;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11G;
+ break;
+ case CHANNEL_B:
+ mode = AR5K_MODE_11B;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11B;
+ break;
+ case CHANNEL_T:
+ mode = AR5K_MODE_11A_TURBO;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ case CHANNEL_TG:
+ if (ah->ah_version == AR5K_AR5211) {
+ DBG("ath5k: TurboG not available on 5211\n");
+ return -EINVAL;
+ }
+ mode = AR5K_MODE_11G_TURBO;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11G;
+ break;
+ case CHANNEL_XR:
+ if (ah->ah_version == AR5K_AR5211) {
+ DBG("ath5k: XR mode not available on 5211\n");
+ return -EINVAL;
+ }
+ mode = AR5K_MODE_XR;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ default:
+ DBG("ath5k: invalid channel (%d MHz)\n",
+ channel->center_freq);
+ return -EINVAL;
+ }
+
+ if (change_channel) {
+ /*
+ * Save frame sequence count
+ * For revs. after Oahu, only save
+ * seq num for DCU 0 (Global seq num)
+ */
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+
+ for (i = 0; i < 10; i++)
+ s_seq[i] = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_DCU_SEQNUM(i));
+
+ } else {
+ s_seq[0] = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_DCU_SEQNUM(0));
+ }
+ }
+
+ /* Save default antenna */
+ s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
+
+ if (ah->ah_version == AR5K_AR5212) {
+ /* Since we are going to write rf buffer
+ * check if we have any pending gain_F
+ * optimization settings */
+ if (change_channel && ah->ah_rf_banks != NULL)
+ ath5k_hw_gainf_calibrate(ah);
+ }
+ }
+
+ /*GPIOs*/
+ s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) &
+ AR5K_PCICFG_LEDSTATE;
+ s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
+ s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+
+ /* AR5K_STA_ID1 flags, only preserve antenna
+ * settings and ack/cts rate mode */
+ staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) &
+ (AR5K_STA_ID1_DEFAULT_ANTENNA |
+ AR5K_STA_ID1_DESC_ANTENNA |
+ AR5K_STA_ID1_RTS_DEF_ANTENNA |
+ AR5K_STA_ID1_ACKCTS_6MB |
+ AR5K_STA_ID1_BASE_RATE_11B |
+ AR5K_STA_ID1_SELFGEN_DEF_ANT);
+
+ /* Wakeup the device */
+ ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, 0);
+ if (ret)
+ return ret;
+
+ /* PHY access enable */
+ if (ah->ah_mac_srev >= AR5K_SREV_AR5211)
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+ else
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40,
+ AR5K_PHY(0));
+
+ /* Write initial settings */
+ ret = ath5k_hw_write_initvals(ah, mode, change_channel);
+ if (ret)
+ return ret;
+
+ /*
+ * 5211/5212 Specific
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+
+ /*
+ * Write initial RF gain settings
+ * This should work for both 5111/5112
+ */
+ ret = ath5k_hw_rfgain_init(ah, freq);
+ if (ret)
+ return ret;
+
+ mdelay(1);
+
+ /*
+ * Tweak initval settings for revised
+ * chipsets and add some more config
+ * bits
+ */
+ ath5k_hw_tweak_initval_settings(ah, channel);
+
+ /*
+ * Set TX power (FIXME)
+ */
+ ret = ath5k_hw_txpower(ah, channel, ee_mode,
+ AR5K_TUNE_DEFAULT_TXPOWER);
+ if (ret)
+ return ret;
+
+ /* Write rate duration table only on AR5212 */
+ if (ah->ah_version == AR5K_AR5212)
+ ath5k_hw_write_rate_duration(ah, mode);
+
+ /*
+ * Write RF buffer
+ */
+ ret = ath5k_hw_rfregs_init(ah, channel, mode);
+ if (ret)
+ return ret;
+
+
+ /* Write OFDM timings on 5212*/
+ if (ah->ah_version == AR5K_AR5212 &&
+ channel->hw_value & CHANNEL_OFDM) {
+ ret = ath5k_hw_write_ofdm_timings(ah, channel);
+ if (ret)
+ return ret;
+ }
+
+ /*Enable/disable 802.11b mode on 5111
+ (enable 2111 frequency converter + CCK)*/
+ if (ah->ah_radio == AR5K_RF5111) {
+ if (mode == AR5K_MODE_11B)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_B_MODE);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_B_MODE);
+ }
+
+ /*
+ * In case a fixed antenna was set as default
+ * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE
+ * registers.
+ */
+ if (s_ant != 0) {
+ if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */
+ ant[0] = ant[1] = AR5K_ANT_FIXED_A;
+ else /* 2 - Aux */
+ ant[0] = ant[1] = AR5K_ANT_FIXED_B;
+ } else {
+ ant[0] = AR5K_ANT_FIXED_A;
+ ant[1] = AR5K_ANT_FIXED_B;
+ }
+
+ /* Commit values from EEPROM */
+ ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode);
+
+ } else {
+ /*
+ * For 5210 we do all initialization using
+ * initvals, so we don't have to modify
+ * any settings (5210 also only supports
+ * a/aturbo modes)
+ */
+ mdelay(1);
+ /* Disable phy and wait */
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
+ mdelay(1);
+ }
+
+ /*
+ * Restore saved values
+ */
+
+ /*DCU/Antenna selection not available on 5210*/
+ if (ah->ah_version != AR5K_AR5210) {
+
+ if (change_channel) {
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+ for (i = 0; i < 10; i++)
+ ath5k_hw_reg_write(ah, s_seq[i],
+ AR5K_QUEUE_DCU_SEQNUM(i));
+ } else {
+ ath5k_hw_reg_write(ah, s_seq[0],
+ AR5K_QUEUE_DCU_SEQNUM(0));
+ }
+ }
+
+ ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA);
+ }
+
+ /* Ledstate */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
+
+ /* Gpio settings */
+ ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
+ ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
+
+ /* Restore sta_id flags and preserve our mac address*/
+ ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id),
+ AR5K_STA_ID0);
+ ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id),
+ AR5K_STA_ID1);
+
+
+ /*
+ * Configure PCU
+ */
+
+ /* Restore bssid and bssid mask */
+ /* XXX: add ah->aid once mac80211 gives this to us */
+ ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+
+ /* Set PCU config */
+ ath5k_hw_set_opmode(ah);
+
+ /* Clear any pending interrupts
+ * PISR/SISR Not available on 5210 */
+ if (ah->ah_version != AR5K_AR5210)
+ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
+
+ /* Set RSSI/BRSSI thresholds
+ *
+ * Note: If we decide to set this value
+ * dynamicaly, have in mind that when AR5K_RSSI_THR
+ * register is read it might return 0x40 if we haven't
+ * wrote anything to it plus BMISS RSSI threshold is zeroed.
+ * So doing a save/restore procedure here isn't the right
+ * choice. Instead store it on ath5k_hw */
+ ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES |
+ AR5K_TUNE_BMISS_THRES <<
+ AR5K_RSSI_THR_BMISS_S),
+ AR5K_RSSI_THR);
+
+ /* MIC QoS support */
+ if (ah->ah_mac_srev >= AR5K_SREV_AR2413) {
+ ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL);
+ ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL);
+ }
+
+ /* QoS NOACK Policy */
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
+ AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) |
+ AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),
+ AR5K_QOS_NOACK);
+ }
+
+
+ /*
+ * Configure PHY
+ */
+
+ /* Set channel on PHY */
+ ret = ath5k_hw_channel(ah, channel);
+ if (ret)
+ return ret;
+
+ /*
+ * Enable the PHY and wait until completion
+ * This includes BaseBand and Synthesizer
+ * activation.
+ */
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
+
+ /*
+ * On 5211+ read activation -> rx delay
+ * and use it.
+ *
+ * TODO: Half/quarter rate support
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ u32 delay;
+ delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
+ AR5K_PHY_RX_DELAY_M;
+ delay = (channel->hw_value & CHANNEL_CCK) ?
+ ((delay << 2) / 22) : (delay / 10);
+
+ udelay(100 + (2 * delay));
+ } else {
+ mdelay(1);
+ }
+
+ /*
+ * Perform ADC test to see if baseband is ready
+ * Set tx hold and check adc test register
+ */
+ phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
+ ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
+ for (i = 0; i <= 20; i++) {
+ if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
+ break;
+ udelay(200);
+ }
+ ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
+
+ /*
+ * Start automatic gain control calibration
+ *
+ * During AGC calibration RX path is re-routed to
+ * a power detector so we don't receive anything.
+ *
+ * This method is used to calibrate some static offsets
+ * used together with on-the fly I/Q calibration (the
+ * one performed via ath5k_hw_phy_calibrate), that doesn't
+ * interrupt rx path.
+ *
+ * While rx path is re-routed to the power detector we also
+ * start a noise floor calibration, to measure the
+ * card's noise floor (the noise we measure when we are not
+ * transmiting or receiving anything).
+ *
+ * If we are in a noisy environment AGC calibration may time
+ * out and/or noise floor calibration might timeout.
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL);
+
+ /* At the same time start I/Q calibration for QAM constellation
+ * -no need for CCK- */
+ ah->ah_calibration = 0;
+ if (!(mode == AR5K_MODE_11B)) {
+ ah->ah_calibration = 1;
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_RUN);
+ }
+
+ /* Wait for gain calibration to finish (we check for I/Q calibration
+ * during ath5k_phy_calibrate) */
+ if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL, 0, 0)) {
+ DBG("ath5k: gain calibration timeout (%d MHz)\n",
+ channel->center_freq);
+ }
+
+ /*
+ * If we run NF calibration before AGC, it always times out.
+ * Binary HAL starts NF and AGC calibration at the same time
+ * and only waits for AGC to finish. Also if AGC or NF cal.
+ * times out, reset doesn't fail on binary HAL. I believe
+ * that's wrong because since rx path is routed to a detector,
+ * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211
+ * enables noise floor calibration after offset calibration and if noise
+ * floor calibration fails, reset fails. I believe that's
+ * a better approach, we just need to find a polling interval
+ * that suits best, even if reset continues we need to make
+ * sure that rx path is ready.
+ */
+ ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+
+
+ /*
+ * Configure QCUs/DCUs
+ */
+
+ /* TODO: HW Compression support for data queues */
+ /* TODO: Burst prefetch for data queues */
+
+ /*
+ * Reset queues and start beacon timers at the end of the reset routine
+ * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
+ * Note: If we want we can assign multiple qcus on one dcu.
+ */
+ ret = ath5k_hw_reset_tx_queue(ah);
+ if (ret) {
+ DBG("ath5k: failed to reset TX queue\n");
+ return ret;
+ }
+
+ /*
+ * Configure DMA/Interrupts
+ */
+
+ /*
+ * Set Rx/Tx DMA Configuration
+ *
+ * Set standard DMA size (128). Note that
+ * a DMA size of 512 causes rx overruns and tx errors
+ * on pci-e cards (tested on 5424 but since rx overruns
+ * also occur on 5416/5418 with madwifi we set 128
+ * for all PCI-E cards to be safe).
+ *
+ * XXX: need to check 5210 for this
+ * TODO: Check out tx triger level, it's always 64 on dumps but I
+ * guess we can tweak it and see how it goes ;-)
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
+ }
+
+ /* Pre-enable interrupts on 5211/5212*/
+ if (ah->ah_version != AR5K_AR5210)
+ ath5k_hw_set_imr(ah, ah->ah_imr);
+
+ /*
+ * Setup RFKill interrupt if rfkill flag is set on eeprom.
+ * TODO: Use gpio pin and polarity infos from eeprom
+ * TODO: Handle this in ath5k_intr because it'll result
+ * a nasty interrupt storm.
+ */
+#if 0
+ if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
+ ath5k_hw_set_gpio_input(ah, 0);
+ ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0);
+ if (ah->ah_gpio[0] == 0)
+ ath5k_hw_set_gpio_intr(ah, 0, 1);
+ else
+ ath5k_hw_set_gpio_intr(ah, 0, 0);
+ }
+#endif
+
+ /*
+ * Disable beacons and reset the register
+ */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE |
+ AR5K_BEACON_RESET_TSF);
+
+ return 0;
+}
+
+#undef _ATH5K_RESET
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_rfkill.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_rfkill.c
new file mode 100644
index 00000000..752ef70b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/ath5k_rfkill.c
@@ -0,0 +1,107 @@
+/*
+ * RFKILL support for ath5k
+ *
+ * Copyright (c) 2009 Tobias Doerffel <tobias.doerffel@gmail.com>
+ * Lightly modified for iPXE, Sep 2008 by Joshua Oreman <oremanj@rwcr.net>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+FILE_LICENCE ( MIT );
+
+#include "base.h"
+
+
+static inline void ath5k_rfkill_disable(struct ath5k_softc *sc)
+{
+ DBG("ath5k: rfkill disable (gpio:%d polarity:%d)\n",
+ sc->rf_kill.gpio, sc->rf_kill.polarity);
+ ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
+ ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, !sc->rf_kill.polarity);
+}
+
+
+static inline void ath5k_rfkill_enable(struct ath5k_softc *sc)
+{
+ DBG("ath5k: rfkill enable (gpio:%d polarity:%d)\n",
+ sc->rf_kill.gpio, sc->rf_kill.polarity);
+ ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
+ ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, sc->rf_kill.polarity);
+}
+
+static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, int enable)
+{
+ struct ath5k_hw *ah = sc->ah;
+ u32 curval;
+
+ ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio);
+ curval = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio);
+ ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ?
+ !!curval : !curval);
+}
+
+static int __unused
+ath5k_is_rfkill_set(struct ath5k_softc *sc)
+{
+ /* configuring GPIO for input for some reason disables rfkill */
+ /*ath5k_hw_set_gpio_input(sc->ah, sc->rf_kill.gpio);*/
+ return (ath5k_hw_get_gpio(sc->ah, sc->rf_kill.gpio) ==
+ sc->rf_kill.polarity);
+}
+
+void
+ath5k_rfkill_hw_start(struct ath5k_hw *ah)
+{
+ struct ath5k_softc *sc = ah->ah_sc;
+
+ /* read rfkill GPIO configuration from EEPROM header */
+ sc->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;
+ sc->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;
+
+ ath5k_rfkill_disable(sc);
+
+ /* enable interrupt for rfkill switch */
+ if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
+ ath5k_rfkill_set_intr(sc, 1);
+}
+
+
+void
+ath5k_rfkill_hw_stop(struct ath5k_hw *ah)
+{
+ struct ath5k_softc *sc = ah->ah_sc;
+
+ /* disable interrupt for rfkill switch */
+ if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
+ ath5k_rfkill_set_intr(sc, 0);
+
+ /* enable RFKILL when stopping HW so Wifi LED is turned off */
+ ath5k_rfkill_enable(sc);
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/base.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/base.h
new file mode 100644
index 00000000..976a3f30
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/base.h
@@ -0,0 +1,145 @@
+/*-
+ * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>
+ * Original from Linux kernel 2.6.30.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+/*
+ * Defintions for the Atheros Wireless LAN controller driver.
+ */
+#ifndef _DEV_ATH_ATHVAR_H
+#define _DEV_ATH_ATHVAR_H
+
+FILE_LICENCE ( BSD3 );
+
+#include "ath5k.h"
+#include <ipxe/iobuf.h>
+
+#define ATH_RXBUF 16 /* number of RX buffers */
+#define ATH_TXBUF 16 /* number of TX buffers */
+
+struct ath5k_buf {
+ struct list_head list;
+ unsigned int flags; /* rx descriptor flags */
+ struct ath5k_desc *desc; /* virtual addr of desc */
+ u32 daddr; /* physical addr of desc */
+ struct io_buffer *iob; /* I/O buffer for buf */
+ u32 iobaddr;/* physical addr of iob data */
+};
+
+/*
+ * Data transmit queue state. One of these exists for each
+ * hardware transmit queue. Packets sent to us from above
+ * are assigned to queues based on their priority. Not all
+ * devices support a complete set of hardware transmit queues.
+ * For those devices the array sc_ac2q will map multiple
+ * priorities to fewer hardware queues (typically all to one
+ * hardware queue).
+ */
+struct ath5k_txq {
+ unsigned int qnum; /* hardware q number */
+ u32 *link; /* link ptr in last TX desc */
+ struct list_head q; /* transmit queue */
+ int setup;
+};
+
+#if CHAN_DEBUG
+#define ATH_CHAN_MAX (26+26+26+200+200)
+#else
+#define ATH_CHAN_MAX (14+14+14+252+20)
+#endif
+
+/* Software Carrier, keeps track of the driver state
+ * associated with an instance of a device */
+struct ath5k_softc {
+ struct pci_device *pdev; /* for dma mapping */
+ void *iobase; /* address of the device */
+ struct net80211_device *dev; /* IEEE 802.11 common */
+ struct ath5k_hw *ah; /* Atheros HW */
+ struct net80211_hw_info *hwinfo;
+ int curband;
+ int irq_ena; /* interrupts enabled */
+
+ struct ath5k_buf *bufptr; /* allocated buffer ptr */
+ struct ath5k_desc *desc; /* TX/RX descriptors */
+ u32 desc_daddr; /* DMA (physical) address */
+ size_t desc_len; /* size of TX/RX descriptors */
+ u16 cachelsz; /* cache line size */
+
+ int status;
+#define ATH_STAT_INVALID 0x01 /* disable hardware accesses */
+#define ATH_STAT_MRRETRY 0x02 /* multi-rate retry support */
+#define ATH_STAT_PROMISC 0x04
+#define ATH_STAT_LEDSOFT 0x08 /* enable LED gpio status */
+#define ATH_STAT_STARTED 0x10 /* opened & irqs enabled */
+
+ unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
+ unsigned int curmode; /* current phy mode */
+ struct net80211_channel *curchan; /* current h/w channel */
+
+ enum ath5k_int imask; /* interrupt mask copy */
+
+ u8 bssidmask[ETH_ALEN];
+
+ unsigned int rxbufsize; /* rx size based on mtu */
+ struct list_head rxbuf; /* receive buffer */
+ u32 *rxlink; /* link ptr in last RX desc */
+
+ struct list_head txbuf; /* transmit buffer */
+ unsigned int txbuf_len; /* buf count in txbuf list */
+ struct ath5k_txq txq; /* tx queue */
+
+ struct {
+ u16 gpio;
+ unsigned polarity;
+ } rf_kill;
+
+ int last_calib_ticks;
+
+ int power_level; /* Requested tx power in dbm */
+ int assoc; /* assocate state */
+
+ int hw_rate; /* Hardware tx rate code */
+ int hw_rtscts_rate; /* Hardware rts/cts rate code */
+};
+
+#define ath5k_hw_hasbssidmask(_ah) \
+ (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0)
+#define ath5k_hw_hasveol(_ah) \
+ (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/desc.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/desc.h
new file mode 100644
index 00000000..6e11b0d4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/desc.h
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Internal RX/TX descriptor structures
+ * (rX: reserved fields possibily used by future versions of the ar5k chipset)
+ */
+
+/*
+ * common hardware RX control descriptor
+ */
+struct ath5k_hw_rx_ctl {
+ u32 rx_control_0; /* RX control word 0 */
+ u32 rx_control_1; /* RX control word 1 */
+} __attribute__ ((packed));
+
+/* RX control word 0 field/sflags */
+#define AR5K_DESC_RX_CTL0 0x00000000
+
+/* RX control word 1 fields/flags */
+#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff
+#define AR5K_DESC_RX_CTL1_INTREQ 0x00002000
+
+/*
+ * common hardware RX status descriptor
+ * 5210/11 and 5212 differ only in the flags defined below
+ */
+struct ath5k_hw_rx_status {
+ u32 rx_status_0; /* RX status word 0 */
+ u32 rx_status_1; /* RX status word 1 */
+} __attribute__ ((packed));
+
+/* 5210/5211 */
+/* RX status word 0 fields/flags */
+#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff
+#define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27
+
+/* RX status word 1 fields/flags */
+#define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001
+#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
+#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004
+#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008
+#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010
+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0
+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9
+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000
+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15
+#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000
+
+/* 5212 */
+/* RX status word 0 fields/flags */
+#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff
+#define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000
+#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28
+
+/* RX status word 1 fields/flags */
+#define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001
+#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
+#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004
+#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008
+#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010
+#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9
+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000
+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16
+#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000
+
+/*
+ * common hardware RX error descriptor
+ */
+struct ath5k_hw_rx_error {
+ u32 rx_error_0; /* RX status word 0 */
+ u32 rx_error_1; /* RX status word 1 */
+} __attribute__ ((packed));
+
+/* RX error word 0 fields/flags */
+#define AR5K_RX_DESC_ERROR0 0x00000000
+
+/* RX error word 1 fields/flags */
+#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00
+#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8
+
+/* PHY Error codes */
+#define AR5K_DESC_RX_PHY_ERROR_NONE 0x00
+#define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20
+#define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40
+#define AR5K_DESC_RX_PHY_ERROR_RATE 0x60
+#define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80
+#define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0
+#define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0
+#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0
+
+/*
+ * 5210/5211 hardware 2-word TX control descriptor
+ */
+struct ath5k_hw_2w_tx_ctl {
+ u32 tx_control_0; /* TX control word 0 */
+ u32 tx_control_1; /* TX control word 1 */
+} __attribute__ ((packed));
+
+/* TX control word 0 fields/flags */
+#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
+#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/
+#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12
+#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000
+#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18
+#define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000
+#define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000
+#define AR5K_2W_TX_DESC_CTL0_LONG_PACKET 0x00800000 /*[5210]*/
+#define AR5K_2W_TX_DESC_CTL0_VEOL 0x00800000 /*[5211]*/
+#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE 0x1c000000 /*[5210]*/
+#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000
+
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT \
+ (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \
+ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211)
+
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25
+#define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000
+#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000
+
+/* TX control word 1 fields/flags */
+#define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff
+#define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000
+
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX \
+ (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211)
+
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13
+#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/
+#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20
+#define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/
+#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/
+
+/* Frame types */
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10
+
+/*
+ * 5212 hardware 4-word TX control descriptor
+ */
+struct ath5k_hw_4w_tx_ctl {
+ u32 tx_control_0; /* TX control word 0 */
+
+#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
+#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000
+#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16
+#define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000
+#define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000
+#define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000
+#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000
+#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25
+#define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000
+#define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000
+#define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000
+
+ u32 tx_control_1; /* TX control word 1 */
+
+#define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff
+#define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000
+#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX 0x000fe000
+#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13
+#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000
+#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20
+#define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25
+#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27
+#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29
+
+ u32 tx_control_2; /* TX control word 2 */
+
+#define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff
+#define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE 0x00008000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28
+
+ u32 tx_control_3; /* TX control word 3 */
+
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15
+#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000
+#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20
+} __attribute__ ((packed));
+
+/*
+ * Common TX status descriptor
+ */
+struct ath5k_hw_tx_status {
+ u32 tx_status_0; /* TX status word 0 */
+ u32 tx_status_1; /* TX status word 1 */
+} __attribute__ ((packed));
+
+/* TX status word 0 fields/flags */
+#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001
+#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002
+#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004
+#define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008
+/*???
+#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT 0x000000f0
+#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S 4
+*/
+#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0
+#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4
+/*???
+#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT 0x00000f00
+#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S 8
+*/
+#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00
+#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8
+#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT 0x0000f000
+#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S 12
+#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000
+#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16
+
+/* TX status word 1 fields/flags */
+#define AR5K_DESC_TX_STATUS1_DONE 0x00000001
+#define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe
+#define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1
+#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000
+#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13
+#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX 0x00600000
+#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21
+#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000
+#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000
+
+/*
+ * 5210/5211 hardware TX descriptor
+ */
+struct ath5k_hw_5210_tx_desc {
+ struct ath5k_hw_2w_tx_ctl tx_ctl;
+ struct ath5k_hw_tx_status tx_stat;
+} __attribute__ ((packed));
+
+/*
+ * 5212 hardware TX descriptor
+ */
+struct ath5k_hw_5212_tx_desc {
+ struct ath5k_hw_4w_tx_ctl tx_ctl;
+ struct ath5k_hw_tx_status tx_stat;
+} __attribute__ ((packed));
+
+/*
+ * common hardware RX descriptor
+ */
+struct ath5k_hw_all_rx_desc {
+ struct ath5k_hw_rx_ctl rx_ctl;
+ union {
+ struct ath5k_hw_rx_status rx_stat;
+ struct ath5k_hw_rx_error rx_err;
+ } u;
+} __attribute__ ((packed));
+
+/*
+ * Atheros hardware descriptor
+ * This is read and written to by the hardware
+ */
+struct ath5k_desc {
+ u32 ds_link; /* physical address of the next descriptor */
+ u32 ds_data; /* physical address of data buffer (skb) */
+
+ union {
+ struct ath5k_hw_5210_tx_desc ds_tx5210;
+ struct ath5k_hw_5212_tx_desc ds_tx5212;
+ struct ath5k_hw_all_rx_desc ds_rx;
+ } ud;
+} __attribute__ ((packed));
+
+#define AR5K_RXDESC_INTREQ 0x0020
+
+#define AR5K_TXDESC_CLRDMASK 0x0001
+#define AR5K_TXDESC_NOACK 0x0002 /*[5211+]*/
+#define AR5K_TXDESC_RTSENA 0x0004
+#define AR5K_TXDESC_CTSENA 0x0008
+#define AR5K_TXDESC_INTREQ 0x0010
+#define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/eeprom.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/eeprom.h
new file mode 100644
index 00000000..da454339
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/eeprom.h
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
+ */
+#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */
+#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */
+#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */
+#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
+#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */
+
+#define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */
+
+#define AR5K_EEPROM_RFKILL 0x0f
+#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
+#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
+#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
+#define AR5K_EEPROM_RFKILL_POLARITY_S 1
+
+#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
+#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
+#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
+#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
+#define AR5K_EEPROM_INFO_CKSUM 0xffff
+#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n))
+
+#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */
+#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */
+#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */
+#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */
+#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
+#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */
+#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_3 0x4003 /* power calibration changes */
+#define AR5K_EEPROM_VERSION_4_4 0x4004
+#define AR5K_EEPROM_VERSION_4_5 0x4005
+#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */
+#define AR5K_EEPROM_VERSION_4_7 0x3007 /* 4007 ? */
+#define AR5K_EEPROM_VERSION_4_9 0x4009 /* EAR futureproofing */
+#define AR5K_EEPROM_VERSION_5_0 0x5000 /* Has 2413 PDADC calibration etc */
+#define AR5K_EEPROM_VERSION_5_1 0x5001 /* Has capability values */
+#define AR5K_EEPROM_VERSION_5_3 0x5003 /* Has spur mitigation tables */
+
+#define AR5K_EEPROM_MODE_11A 0
+#define AR5K_EEPROM_MODE_11B 1
+#define AR5K_EEPROM_MODE_11G 2
+
+#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */
+#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
+#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
+#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
+#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */
+#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */
+#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
+#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
+#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */
+
+#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
+#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
+#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
+#define AR5K_EEPROM_RFKILL_POLARITY_S 1
+
+/* Newer EEPROMs are using a different offset */
+#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
+ (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
+
+#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
+#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((s8)(((_v) >> 8) & 0xff))
+#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((s8)((_v) & 0xff))
+
+/* Misc values available since EEPROM 4.0 */
+#define AR5K_EEPROM_MISC0 AR5K_EEPROM_INFO(4)
+#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
+#define AR5K_EEPROM_HDR_XR2_DIS(_v) (((_v) >> 12) & 0x1)
+#define AR5K_EEPROM_HDR_XR5_DIS(_v) (((_v) >> 13) & 0x1)
+#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
+
+#define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5)
+#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
+#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
+#define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1)
+
+#define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6)
+#define AR5K_EEPROM_EEP_FILE_VERSION(_v) (((_v) >> 8) & 0xff)
+#define AR5K_EEPROM_EAR_FILE_VERSION(_v) ((_v) & 0xff)
+
+#define AR5K_EEPROM_MISC3 AR5K_EEPROM_INFO(7)
+#define AR5K_EEPROM_ART_BUILD_NUM(_v) (((_v) >> 10) & 0x3f)
+#define AR5K_EEPROM_EAR_FILE_ID(_v) ((_v) & 0xff)
+
+#define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8)
+#define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff)
+#define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3)
+#define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3)
+
+#define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9)
+#define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1)
+#define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1)
+#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1)
+#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1)
+#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf)
+#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1)
+#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf)
+
+#define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10)
+#define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x8)
+#define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x8)
+#define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1)
+#define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1)
+#define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1)
+#define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 9) & 0x1)
+#define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 10) & 0x1)
+
+/* calibration settings */
+#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
+#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
+#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
+#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */
+#define AR5K_EEPROM_GROUPS_START(_v) AR5K_EEPROM_OFF(_v, 0x0100, 0x0150) /* Start of Groups */
+#define AR5K_EEPROM_GROUP1_OFFSET 0x0
+#define AR5K_EEPROM_GROUP2_OFFSET 0x5
+#define AR5K_EEPROM_GROUP3_OFFSET 0x37
+#define AR5K_EEPROM_GROUP4_OFFSET 0x46
+#define AR5K_EEPROM_GROUP5_OFFSET 0x55
+#define AR5K_EEPROM_GROUP6_OFFSET 0x65
+#define AR5K_EEPROM_GROUP7_OFFSET 0x69
+#define AR5K_EEPROM_GROUP8_OFFSET 0x6f
+
+#define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
+ AR5K_EEPROM_GROUP5_OFFSET, 0x0000)
+#define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
+ AR5K_EEPROM_GROUP6_OFFSET, 0x0010)
+#define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
+ AR5K_EEPROM_GROUP7_OFFSET, 0x0014)
+
+/* [3.1 - 3.3] */
+#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec
+#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed
+
+#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */
+#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */
+#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */
+#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */
+#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008
+#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */
+#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020
+#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */
+#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080
+#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */
+#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200
+#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */
+#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800
+#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */
+#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000
+#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */
+#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000
+
+/* Some EEPROM defines */
+#define AR5K_EEPROM_EEP_SCALE 100
+#define AR5K_EEPROM_EEP_DELTA 10
+#define AR5K_EEPROM_N_MODES 3
+#define AR5K_EEPROM_N_5GHZ_CHAN 10
+#define AR5K_EEPROM_N_2GHZ_CHAN 3
+#define AR5K_EEPROM_N_2GHZ_CHAN_2413 4
+#define AR5K_EEPROM_N_2GHZ_CHAN_MAX 4
+#define AR5K_EEPROM_MAX_CHAN 10
+#define AR5K_EEPROM_N_PWR_POINTS_5111 11
+#define AR5K_EEPROM_N_PCDAC 11
+#define AR5K_EEPROM_N_PHASE_CAL 5
+#define AR5K_EEPROM_N_TEST_FREQ 8
+#define AR5K_EEPROM_N_EDGES 8
+#define AR5K_EEPROM_N_INTERCEPTS 11
+#define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff)
+#define AR5K_EEPROM_PCDAC_M 0x3f
+#define AR5K_EEPROM_PCDAC_START 1
+#define AR5K_EEPROM_PCDAC_STOP 63
+#define AR5K_EEPROM_PCDAC_STEP 1
+#define AR5K_EEPROM_NON_EDGE_M 0x40
+#define AR5K_EEPROM_CHANNEL_POWER 8
+#define AR5K_EEPROM_N_OBDB 4
+#define AR5K_EEPROM_OBDB_DIS 0xffff
+#define AR5K_EEPROM_CHANNEL_DIS 0xff
+#define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10)
+#define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32)
+#define AR5K_EEPROM_MAX_CTLS 32
+#define AR5K_EEPROM_N_PD_CURVES 4
+#define AR5K_EEPROM_N_XPD0_POINTS 4
+#define AR5K_EEPROM_N_XPD3_POINTS 3
+#define AR5K_EEPROM_N_PD_GAINS 4
+#define AR5K_EEPROM_N_PD_POINTS 5
+#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35
+#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55
+#define AR5K_EEPROM_POWER_M 0x3f
+#define AR5K_EEPROM_POWER_MIN 0
+#define AR5K_EEPROM_POWER_MAX 3150
+#define AR5K_EEPROM_POWER_STEP 50
+#define AR5K_EEPROM_POWER_TABLE_SIZE 64
+#define AR5K_EEPROM_N_POWER_LOC_11B 4
+#define AR5K_EEPROM_N_POWER_LOC_11G 6
+#define AR5K_EEPROM_I_GAIN 10
+#define AR5K_EEPROM_CCK_OFDM_DELTA 15
+#define AR5K_EEPROM_N_IQ_CAL 2
+
+#define AR5K_EEPROM_READ(_o, _v) do { \
+ ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \
+ if (ret) \
+ return ret; \
+} while (0)
+
+#define AR5K_EEPROM_READ_HDR(_o, _v) \
+ AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \
+
+enum ath5k_ant_setting {
+ AR5K_ANT_VARIABLE = 0, /* variable by programming */
+ AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */
+ AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */
+ AR5K_ANT_MAX = 3,
+};
+
+enum ath5k_ctl_mode {
+ AR5K_CTL_11A = 0,
+ AR5K_CTL_11B = 1,
+ AR5K_CTL_11G = 2,
+ AR5K_CTL_TURBO = 3,
+ AR5K_CTL_TURBOG = 4,
+ AR5K_CTL_2GHT20 = 5,
+ AR5K_CTL_5GHT20 = 6,
+ AR5K_CTL_2GHT40 = 7,
+ AR5K_CTL_5GHT40 = 8,
+ AR5K_CTL_MODE_M = 15,
+};
+
+/* Default CTL ids for the 3 main reg domains.
+ * Atheros only uses these by default but vendors
+ * can have up to 32 different CTLs for different
+ * scenarios. Note that theese values are ORed with
+ * the mode id (above) so we can have up to 24 CTL
+ * datasets out of these 3 main regdomains. That leaves
+ * 8 ids that can be used by vendors and since 0x20 is
+ * missing from HAL sources i guess this is the set of
+ * custom CTLs vendors can use. */
+#define AR5K_CTL_FCC 0x10
+#define AR5K_CTL_CUSTOM 0x20
+#define AR5K_CTL_ETSI 0x30
+#define AR5K_CTL_MKK 0x40
+
+/* Indicates a CTL with only mode set and
+ * no reg domain mapping, such CTLs are used
+ * for world roaming domains or simply when
+ * a reg domain is not set */
+#define AR5K_CTL_NO_REGDOMAIN 0xf0
+
+/* Indicates an empty (invalid) CTL */
+#define AR5K_CTL_NO_CTL 0xff
+
+/* Per channel calibration data, used for power table setup */
+struct ath5k_chan_pcal_info_rf5111 {
+ /* Power levels in half dbm units
+ * for one power curve. */
+ u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111];
+ /* PCDAC table steps
+ * for the above values */
+ u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111];
+ /* Starting PCDAC step */
+ u8 pcdac_min;
+ /* Final PCDAC step */
+ u8 pcdac_max;
+};
+
+struct ath5k_chan_pcal_info_rf5112 {
+ /* Power levels in quarter dBm units
+ * for lower (0) and higher (3)
+ * level curves in 0.25dB units */
+ s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS];
+ s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS];
+ /* PCDAC table steps
+ * for the above values */
+ u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS];
+ u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS];
+};
+
+struct ath5k_chan_pcal_info_rf2413 {
+ /* Starting pwr/pddac values */
+ s8 pwr_i[AR5K_EEPROM_N_PD_GAINS];
+ u8 pddac_i[AR5K_EEPROM_N_PD_GAINS];
+ /* (pwr,pddac) points
+ * power levels in 0.5dB units */
+ s8 pwr[AR5K_EEPROM_N_PD_GAINS]
+ [AR5K_EEPROM_N_PD_POINTS];
+ u8 pddac[AR5K_EEPROM_N_PD_GAINS]
+ [AR5K_EEPROM_N_PD_POINTS];
+};
+
+enum ath5k_powertable_type {
+ AR5K_PWRTABLE_PWR_TO_PCDAC = 0,
+ AR5K_PWRTABLE_LINEAR_PCDAC = 1,
+ AR5K_PWRTABLE_PWR_TO_PDADC = 2,
+};
+
+struct ath5k_pdgain_info {
+ u8 pd_points;
+ u8 *pd_step;
+ /* Power values are in
+ * 0.25dB units */
+ s16 *pd_pwr;
+};
+
+struct ath5k_chan_pcal_info {
+ /* Frequency */
+ u16 freq;
+ /* Tx power boundaries */
+ s16 max_pwr;
+ s16 min_pwr;
+ union {
+ struct ath5k_chan_pcal_info_rf5111 rf5111_info;
+ struct ath5k_chan_pcal_info_rf5112 rf5112_info;
+ struct ath5k_chan_pcal_info_rf2413 rf2413_info;
+ };
+ /* Raw values used by phy code
+ * Curves are stored in order from lower
+ * gain to higher gain (max txpower -> min txpower) */
+ struct ath5k_pdgain_info *pd_curves;
+};
+
+/* Per rate calibration data for each mode,
+ * used for rate power table setup.
+ * Note: Values in 0.5dB units */
+struct ath5k_rate_pcal_info {
+ u16 freq; /* Frequency */
+ /* Power level for 6-24Mbit/s rates or
+ * 1Mb rate */
+ u16 target_power_6to24;
+ /* Power level for 36Mbit rate or
+ * 2Mb rate */
+ u16 target_power_36;
+ /* Power level for 48Mbit rate or
+ * 5.5Mbit rate */
+ u16 target_power_48;
+ /* Power level for 54Mbit rate or
+ * 11Mbit rate */
+ u16 target_power_54;
+};
+
+/* Power edges for conformance test limits */
+struct ath5k_edge_power {
+ u16 freq;
+ u16 edge; /* in half dBm */
+ int flag;
+};
+
+/* EEPROM calibration data */
+struct ath5k_eeprom_info {
+
+ /* Header information */
+ u16 ee_magic;
+ u16 ee_protect;
+ u16 ee_regdomain;
+ u16 ee_version;
+ u16 ee_header;
+ u16 ee_ant_gain;
+ u8 ee_rfkill_pin;
+ int ee_rfkill_pol;
+ int ee_is_hb63;
+ u16 ee_misc0;
+ u16 ee_misc1;
+ u16 ee_misc2;
+ u16 ee_misc3;
+ u16 ee_misc4;
+ u16 ee_misc5;
+ u16 ee_misc6;
+ u16 ee_cck_ofdm_gain_delta;
+ u16 ee_cck_ofdm_power_delta;
+ u16 ee_scaled_cck_delta;
+
+ /* RF Calibration settings (reset, rfregs) */
+ u16 ee_i_cal[AR5K_EEPROM_N_MODES];
+ u16 ee_q_cal[AR5K_EEPROM_N_MODES];
+ u16 ee_fixed_bias[AR5K_EEPROM_N_MODES];
+ u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES];
+ u16 ee_xr_power[AR5K_EEPROM_N_MODES];
+ u16 ee_switch_settling[AR5K_EEPROM_N_MODES];
+ u16 ee_atn_tx_rx[AR5K_EEPROM_N_MODES];
+ u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
+ u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
+ u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
+ u16 ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES];
+ u16 ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES];
+ u16 ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES];
+ u16 ee_thr_62[AR5K_EEPROM_N_MODES];
+ u16 ee_xlna_gain[AR5K_EEPROM_N_MODES];
+ u16 ee_xpd[AR5K_EEPROM_N_MODES];
+ u16 ee_x_gain[AR5K_EEPROM_N_MODES];
+ u16 ee_i_gain[AR5K_EEPROM_N_MODES];
+ u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
+ u16 ee_switch_settling_turbo[AR5K_EEPROM_N_MODES];
+ u16 ee_margin_tx_rx_turbo[AR5K_EEPROM_N_MODES];
+ u16 ee_atn_tx_rx_turbo[AR5K_EEPROM_N_MODES];
+
+ /* Power calibration data */
+ u16 ee_false_detect[AR5K_EEPROM_N_MODES];
+
+ /* Number of pd gain curves per mode */
+ u8 ee_pd_gains[AR5K_EEPROM_N_MODES];
+ /* Back mapping pdcurve number -> pdcurve index in pd->pd_curves */
+ u8 ee_pdc_to_idx[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PD_GAINS];
+
+ u8 ee_n_piers[AR5K_EEPROM_N_MODES];
+ struct ath5k_chan_pcal_info ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN];
+ struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
+ struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
+
+ /* Per rate target power levels */
+ u8 ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES];
+ struct ath5k_rate_pcal_info ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN];
+ struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
+ struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
+
+ /* Conformance test limits (Unused) */
+ u8 ee_ctls;
+ u8 ee_ctl[AR5K_EEPROM_MAX_CTLS];
+ struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES * AR5K_EEPROM_MAX_CTLS];
+
+ /* Noise Floor Calibration settings */
+ s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
+ s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES];
+ s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES];
+ s8 ee_adc_desired_size_turbo[AR5K_EEPROM_N_MODES];
+ s8 ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES];
+ s8 ee_pd_gain_overlap;
+
+ u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
+};
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/reg.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/reg.h
new file mode 100644
index 00000000..7070d154
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/reg.h
@@ -0,0 +1,2589 @@
+/*
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2007-2008 Michael Taylor <mike.taylor@apprion.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Register values for Atheros 5210/5211/5212 cards from OpenBSD's ar5k
+ * maintained by Reyk Floeter
+ *
+ * I tried to document those registers by looking at ar5k code, some
+ * 802.11 (802.11e mostly) papers and by reading various public available
+ * Atheros presentations and papers like these:
+ *
+ * 5210 - http://nova.stanford.edu/~bbaas/ps/isscc2002_slides.pdf
+ * http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf
+ *
+ * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf
+ *
+ * This file also contains register values found on a memory dump of
+ * Atheros's ART program (Atheros Radio Test), on ath9k, on legacy-hal
+ * released by Atheros and on various debug messages found on the net.
+ */
+
+
+
+/*====MAC DMA REGISTERS====*/
+
+/*
+ * AR5210-Specific TXDP registers
+ * 5210 has only 2 transmit queues so no DCU/QCU, just
+ * 2 transmit descriptor pointers...
+ */
+#define AR5K_NOQCU_TXDP0 0x0000 /* Queue 0 - data */
+#define AR5K_NOQCU_TXDP1 0x0004 /* Queue 1 - beacons */
+
+/*
+ * Mac Control Register
+ */
+#define AR5K_CR 0x0008 /* Register Address */
+#define AR5K_CR_TXE0 0x00000001 /* TX Enable for queue 0 on 5210 */
+#define AR5K_CR_TXE1 0x00000002 /* TX Enable for queue 1 on 5210 */
+#define AR5K_CR_RXE 0x00000004 /* RX Enable */
+#define AR5K_CR_TXD0 0x00000008 /* TX Disable for queue 0 on 5210 */
+#define AR5K_CR_TXD1 0x00000010 /* TX Disable for queue 1 on 5210 */
+#define AR5K_CR_RXD 0x00000020 /* RX Disable */
+#define AR5K_CR_SWI 0x00000040 /* Software Interrupt */
+
+/*
+ * RX Descriptor Pointer register
+ */
+#define AR5K_RXDP 0x000c
+
+/*
+ * Configuration and status register
+ */
+#define AR5K_CFG 0x0014 /* Register Address */
+#define AR5K_CFG_SWTD 0x00000001 /* Byte-swap TX descriptor (for big endian archs) */
+#define AR5K_CFG_SWTB 0x00000002 /* Byte-swap TX buffer */
+#define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */
+#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer */
+#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register access */
+#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */
+#define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */
+#define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */
+#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (Disable dynamic clock) */
+#define AR5K_CFG_TXCNT 0x00007800 /* Tx frame count (?) [5210] */
+#define AR5K_CFG_TXCNT_S 11
+#define AR5K_CFG_TXFSTAT 0x00008000 /* Tx frame status (?) [5210] */
+#define AR5K_CFG_TXFSTRT 0x00010000 /* [5210] */
+#define AR5K_CFG_PCI_THRES 0x00060000 /* PCI Master req q threshold [5211+] */
+#define AR5K_CFG_PCI_THRES_S 17
+
+/*
+ * Interrupt enable register
+ */
+#define AR5K_IER 0x0024 /* Register Address */
+#define AR5K_IER_DISABLE 0x00000000 /* Disable card interrupts */
+#define AR5K_IER_ENABLE 0x00000001 /* Enable card interrupts */
+
+
+/*
+ * 0x0028 is Beacon Control Register on 5210
+ * and first RTS duration register on 5211
+ */
+
+/*
+ * Beacon control register [5210]
+ */
+#define AR5K_BCR 0x0028 /* Register Address */
+#define AR5K_BCR_AP 0x00000000 /* AP mode */
+#define AR5K_BCR_ADHOC 0x00000001 /* Ad-Hoc mode */
+#define AR5K_BCR_BDMAE 0x00000002 /* DMA enable */
+#define AR5K_BCR_TQ1FV 0x00000004 /* Use Queue1 for CAB traffic */
+#define AR5K_BCR_TQ1V 0x00000008 /* Use Queue1 for Beacon traffic */
+#define AR5K_BCR_BCGET 0x00000010
+
+/*
+ * First RTS duration register [5211]
+ */
+#define AR5K_RTSD0 0x0028 /* Register Address */
+#define AR5K_RTSD0_6 0x000000ff /* 6Mb RTS duration mask (?) */
+#define AR5K_RTSD0_6_S 0 /* 6Mb RTS duration shift (?) */
+#define AR5K_RTSD0_9 0x0000ff00 /* 9Mb*/
+#define AR5K_RTSD0_9_S 8
+#define AR5K_RTSD0_12 0x00ff0000 /* 12Mb*/
+#define AR5K_RTSD0_12_S 16
+#define AR5K_RTSD0_18 0xff000000 /* 16Mb*/
+#define AR5K_RTSD0_18_S 24
+
+
+/*
+ * 0x002c is Beacon Status Register on 5210
+ * and second RTS duration register on 5211
+ */
+
+/*
+ * Beacon status register [5210]
+ *
+ * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR
+ * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning
+ * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR).
+ * So SNAPPEDBCRVALID sould also stand for "snapped BCR -values- valid", so i
+ * renamed it to SNAPSHOTSVALID to make more sense. I realy have no idea what
+ * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR.
+ */
+#define AR5K_BSR 0x002c /* Register Address */
+#define AR5K_BSR_BDLYSW 0x00000001 /* SW Beacon delay (?) */
+#define AR5K_BSR_BDLYDMA 0x00000002 /* DMA Beacon delay (?) */
+#define AR5K_BSR_TXQ1F 0x00000004 /* Beacon queue (1) finished */
+#define AR5K_BSR_ATIMDLY 0x00000008 /* ATIM delay (?) */
+#define AR5K_BSR_SNPADHOC 0x00000100 /* Ad-hoc mode set (?) */
+#define AR5K_BSR_SNPBDMAE 0x00000200 /* Beacon DMA enabled (?) */
+#define AR5K_BSR_SNPTQ1FV 0x00000400 /* Queue1 is used for CAB traffic (?) */
+#define AR5K_BSR_SNPTQ1V 0x00000800 /* Queue1 is used for Beacon traffic (?) */
+#define AR5K_BSR_SNAPSHOTSVALID 0x00001000 /* BCR snapshots are valid (?) */
+#define AR5K_BSR_SWBA_CNT 0x00ff0000
+
+/*
+ * Second RTS duration register [5211]
+ */
+#define AR5K_RTSD1 0x002c /* Register Address */
+#define AR5K_RTSD1_24 0x000000ff /* 24Mb */
+#define AR5K_RTSD1_24_S 0
+#define AR5K_RTSD1_36 0x0000ff00 /* 36Mb */
+#define AR5K_RTSD1_36_S 8
+#define AR5K_RTSD1_48 0x00ff0000 /* 48Mb */
+#define AR5K_RTSD1_48_S 16
+#define AR5K_RTSD1_54 0xff000000 /* 54Mb */
+#define AR5K_RTSD1_54_S 24
+
+
+/*
+ * Transmit configuration register
+ */
+#define AR5K_TXCFG 0x0030 /* Register Address */
+#define AR5K_TXCFG_SDMAMR 0x00000007 /* DMA size (read) */
+#define AR5K_TXCFG_SDMAMR_S 0
+#define AR5K_TXCFG_B_MODE 0x00000008 /* Set b mode for 5111 (enable 2111) */
+#define AR5K_TXCFG_TXFSTP 0x00000008 /* TX DMA full Stop [5210] */
+#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Triger level mask */
+#define AR5K_TXCFG_TXFULL_S 4
+#define AR5K_TXCFG_TXFULL_0B 0x00000000
+#define AR5K_TXCFG_TXFULL_64B 0x00000010
+#define AR5K_TXCFG_TXFULL_128B 0x00000020
+#define AR5K_TXCFG_TXFULL_192B 0x00000030
+#define AR5K_TXCFG_TXFULL_256B 0x00000040
+#define AR5K_TXCFG_TXCONT_EN 0x00000080
+#define AR5K_TXCFG_DMASIZE 0x00000100 /* Flag for passing DMA size [5210] */
+#define AR5K_TXCFG_JUMBO_DESC_EN 0x00000400 /* Enable jumbo tx descriptors [5211+] */
+#define AR5K_TXCFG_ADHOC_BCN_ATIM 0x00000800 /* Adhoc Beacon ATIM Policy */
+#define AR5K_TXCFG_ATIM_WINDOW_DEF_DIS 0x00001000 /* Disable ATIM window defer [5211+] */
+#define AR5K_TXCFG_RTSRND 0x00001000 /* [5211+] */
+#define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */
+#define AR5K_TXCFG_RDY_CBR_DIS 0x00004000 /* Ready time CBR disable [5211+] */
+#define AR5K_TXCFG_JUMBO_FRM_MODE 0x00008000 /* Jumbo frame mode [5211+] */
+#define AR5K_TXCFG_DCU_DBL_BUF_DIS 0x00008000 /* Disable double buffering on DCU */
+#define AR5K_TXCFG_DCU_CACHING_DIS 0x00010000 /* Disable DCU caching */
+
+/*
+ * Receive configuration register
+ */
+#define AR5K_RXCFG 0x0034 /* Register Address */
+#define AR5K_RXCFG_SDMAMW 0x00000007 /* DMA size (write) */
+#define AR5K_RXCFG_SDMAMW_S 0
+#define AR5K_RXCFG_ZLFDMA 0x00000008 /* Enable Zero-length frame DMA */
+#define AR5K_RXCFG_DEF_ANTENNA 0x00000010 /* Default antenna (?) */
+#define AR5K_RXCFG_JUMBO_RXE 0x00000020 /* Enable jumbo rx descriptors [5211+] */
+#define AR5K_RXCFG_JUMBO_WRAP 0x00000040 /* Wrap jumbo frames [5211+] */
+#define AR5K_RXCFG_SLE_ENTRY 0x00000080 /* Sleep entry policy */
+
+/*
+ * Receive jumbo descriptor last address register
+ * Only found in 5211 (?)
+ */
+#define AR5K_RXJLA 0x0038
+
+/*
+ * MIB control register
+ */
+#define AR5K_MIBC 0x0040 /* Register Address */
+#define AR5K_MIBC_COW 0x00000001 /* Warn test indicator */
+#define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */
+#define AR5K_MIBC_CMC 0x00000004 /* Clean MIB Counters */
+#define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe */
+
+/*
+ * Timeout prescale register
+ */
+#define AR5K_TOPS 0x0044
+#define AR5K_TOPS_M 0x0000ffff
+
+/*
+ * Receive timeout register (no frame received)
+ */
+#define AR5K_RXNOFRM 0x0048
+#define AR5K_RXNOFRM_M 0x000003ff
+
+/*
+ * Transmit timeout register (no frame sent)
+ */
+#define AR5K_TXNOFRM 0x004c
+#define AR5K_TXNOFRM_M 0x000003ff
+#define AR5K_TXNOFRM_QCU 0x000ffc00
+#define AR5K_TXNOFRM_QCU_S 10
+
+/*
+ * Receive frame gap timeout register
+ */
+#define AR5K_RPGTO 0x0050
+#define AR5K_RPGTO_M 0x000003ff
+
+/*
+ * Receive frame count limit register
+ */
+#define AR5K_RFCNT 0x0054
+#define AR5K_RFCNT_M 0x0000001f /* [5211+] (?) */
+#define AR5K_RFCNT_RFCL 0x0000000f /* [5210] */
+
+/*
+ * Misc settings register
+ * (reserved0-3)
+ */
+#define AR5K_MISC 0x0058 /* Register Address */
+#define AR5K_MISC_DMA_OBS_M 0x000001e0
+#define AR5K_MISC_DMA_OBS_S 5
+#define AR5K_MISC_MISC_OBS_M 0x00000e00
+#define AR5K_MISC_MISC_OBS_S 9
+#define AR5K_MISC_MAC_OBS_LSB_M 0x00007000
+#define AR5K_MISC_MAC_OBS_LSB_S 12
+#define AR5K_MISC_MAC_OBS_MSB_M 0x00038000
+#define AR5K_MISC_MAC_OBS_MSB_S 15
+#define AR5K_MISC_LED_DECAY 0x001c0000 /* [5210] */
+#define AR5K_MISC_LED_BLINK 0x00e00000 /* [5210] */
+
+/*
+ * QCU/DCU clock gating register (5311)
+ * (reserved4-5)
+ */
+#define AR5K_QCUDCU_CLKGT 0x005c /* Register Address (?) */
+#define AR5K_QCUDCU_CLKGT_QCU 0x0000ffff /* Mask for QCU clock */
+#define AR5K_QCUDCU_CLKGT_DCU 0x07ff0000 /* Mask for DCU clock */
+
+/*
+ * Interrupt Status Registers
+ *
+ * For 5210 there is only one status register but for
+ * 5211/5212 we have one primary and 4 secondary registers.
+ * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212.
+ * Most of these bits are common for all chipsets.
+ */
+#define AR5K_ISR 0x001c /* Register Address [5210] */
+#define AR5K_PISR 0x0080 /* Register Address [5211+] */
+#define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly recieved */
+#define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */
+#define AR5K_ISR_RXERR 0x00000004 /* Receive error */
+#define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */
+#define AR5K_ISR_RXEOL 0x00000010 /* Empty RX descriptor */
+#define AR5K_ISR_RXORN 0x00000020 /* Receive FIFO overrun */
+#define AR5K_ISR_TXOK 0x00000040 /* Frame successfuly transmited */
+#define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */
+#define AR5K_ISR_TXERR 0x00000100 /* Transmit error */
+#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout) */
+#define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */
+#define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */
+#define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */
+#define AR5K_ISR_SWI 0x00002000 /* Software interrupt */
+#define AR5K_ISR_RXPHY 0x00004000 /* PHY error */
+#define AR5K_ISR_RXKCM 0x00008000 /* RX Key cache miss */
+#define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */
+#define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */
+#define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */
+#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
+#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */
+#define AR5K_ISR_MCABT 0x00100000 /* Master Cycle Abort [5210] */
+#define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */
+#define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */
+#define AR5K_ISR_DPERR 0x00400000 /* Det par Error (?) [5210] */
+#define AR5K_ISR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */
+#define AR5K_ISR_TIM 0x00800000 /* [5211+] */
+#define AR5K_ISR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
+ CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
+#define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill) */
+#define AR5K_ISR_QCBRORN 0x02000000 /* QCU CBR overrun [5211+] */
+#define AR5K_ISR_QCBRURN 0x04000000 /* QCU CBR underrun [5211+] */
+#define AR5K_ISR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */
+
+/*
+ * Secondary status registers [5211+] (0 - 4)
+ *
+ * These give the status for each QCU, only QCUs 0-9 are
+ * represented.
+ */
+#define AR5K_SISR0 0x0084 /* Register Address [5211+] */
+#define AR5K_SISR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */
+#define AR5K_SISR0_QCU_TXOK_S 0
+#define AR5K_SISR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */
+#define AR5K_SISR0_QCU_TXDESC_S 16
+
+#define AR5K_SISR1 0x0088 /* Register Address [5211+] */
+#define AR5K_SISR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */
+#define AR5K_SISR1_QCU_TXERR_S 0
+#define AR5K_SISR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */
+#define AR5K_SISR1_QCU_TXEOL_S 16
+
+#define AR5K_SISR2 0x008c /* Register Address [5211+] */
+#define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */
+#define AR5K_SISR2_QCU_TXURN_S 0
+#define AR5K_SISR2_MCABT 0x00100000 /* Master Cycle Abort */
+#define AR5K_SISR2_SSERR 0x00200000 /* Signaled System Error */
+#define AR5K_SISR2_DPERR 0x00400000 /* Bus parity error */
+#define AR5K_SISR2_TIM 0x01000000 /* [5212+] */
+#define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */
+#define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */
+#define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */
+#define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */
+#define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */
+#define AR5K_SISR2_TSFOOR 0x80000000 /* TSF OOR (?) */
+
+#define AR5K_SISR3 0x0090 /* Register Address [5211+] */
+#define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
+#define AR5K_SISR3_QCBRORN_S 0
+#define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */
+#define AR5K_SISR3_QCBRURN_S 16
+
+#define AR5K_SISR4 0x0094 /* Register Address [5211+] */
+#define AR5K_SISR4_QTRIG 0x000003ff /* Mask for QTRIG */
+#define AR5K_SISR4_QTRIG_S 0
+
+/*
+ * Shadow read-and-clear interrupt status registers [5211+]
+ */
+#define AR5K_RAC_PISR 0x00c0 /* Read and clear PISR */
+#define AR5K_RAC_SISR0 0x00c4 /* Read and clear SISR0 */
+#define AR5K_RAC_SISR1 0x00c8 /* Read and clear SISR1 */
+#define AR5K_RAC_SISR2 0x00cc /* Read and clear SISR2 */
+#define AR5K_RAC_SISR3 0x00d0 /* Read and clear SISR3 */
+#define AR5K_RAC_SISR4 0x00d4 /* Read and clear SISR4 */
+
+/*
+ * Interrupt Mask Registers
+ *
+ * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary
+ * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match.
+ */
+#define AR5K_IMR 0x0020 /* Register Address [5210] */
+#define AR5K_PIMR 0x00a0 /* Register Address [5211+] */
+#define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly recieved*/
+#define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/
+#define AR5K_IMR_RXERR 0x00000004 /* Receive error*/
+#define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/
+#define AR5K_IMR_RXEOL 0x00000010 /* Empty RX descriptor*/
+#define AR5K_IMR_RXORN 0x00000020 /* Receive FIFO overrun*/
+#define AR5K_IMR_TXOK 0x00000040 /* Frame successfuly transmited*/
+#define AR5K_IMR_TXDESC 0x00000080 /* TX descriptor request*/
+#define AR5K_IMR_TXERR 0x00000100 /* Transmit error*/
+#define AR5K_IMR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout)*/
+#define AR5K_IMR_TXEOL 0x00000400 /* Empty TX descriptor*/
+#define AR5K_IMR_TXURN 0x00000800 /* Transmit FIFO underrun*/
+#define AR5K_IMR_MIB 0x00001000 /* Update MIB counters*/
+#define AR5K_IMR_SWI 0x00002000 /* Software interrupt */
+#define AR5K_IMR_RXPHY 0x00004000 /* PHY error*/
+#define AR5K_IMR_RXKCM 0x00008000 /* RX Key cache miss */
+#define AR5K_IMR_SWBA 0x00010000 /* Software beacon alert*/
+#define AR5K_IMR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */
+#define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/
+#define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
+#define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */
+#define AR5K_IMR_MCABT 0x00100000 /* Master Cycle Abort [5210] */
+#define AR5K_IMR_RXCHIRP 0x00200000 /* CHIRP Received [5212+]*/
+#define AR5K_IMR_SSERR 0x00200000 /* Signaled System Error [5210] */
+#define AR5K_IMR_DPERR 0x00400000 /* Det par Error (?) [5210] */
+#define AR5K_IMR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */
+#define AR5K_IMR_TIM 0x00800000 /* [5211+] */
+#define AR5K_IMR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
+ CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
+#define AR5K_IMR_GPIO 0x01000000 /* GPIO (rf kill)*/
+#define AR5K_IMR_QCBRORN 0x02000000 /* QCU CBR overrun (?) [5211+] */
+#define AR5K_IMR_QCBRURN 0x04000000 /* QCU CBR underrun (?) [5211+] */
+#define AR5K_IMR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */
+
+/*
+ * Secondary interrupt mask registers [5211+] (0 - 4)
+ */
+#define AR5K_SIMR0 0x00a4 /* Register Address [5211+] */
+#define AR5K_SIMR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */
+#define AR5K_SIMR0_QCU_TXOK_S 0
+#define AR5K_SIMR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */
+#define AR5K_SIMR0_QCU_TXDESC_S 16
+
+#define AR5K_SIMR1 0x00a8 /* Register Address [5211+] */
+#define AR5K_SIMR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */
+#define AR5K_SIMR1_QCU_TXERR_S 0
+#define AR5K_SIMR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */
+#define AR5K_SIMR1_QCU_TXEOL_S 16
+
+#define AR5K_SIMR2 0x00ac /* Register Address [5211+] */
+#define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */
+#define AR5K_SIMR2_QCU_TXURN_S 0
+#define AR5K_SIMR2_MCABT 0x00100000 /* Master Cycle Abort */
+#define AR5K_SIMR2_SSERR 0x00200000 /* Signaled System Error */
+#define AR5K_SIMR2_DPERR 0x00400000 /* Bus parity error */
+#define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */
+#define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */
+#define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */
+#define AR5K_SIMR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */
+#define AR5K_SIMR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */
+#define AR5K_SIMR2_DTIM 0x20000000 /* [5212+] */
+#define AR5K_SIMR2_TSFOOR 0x80000000 /* TSF OOR (?) */
+
+#define AR5K_SIMR3 0x00b0 /* Register Address [5211+] */
+#define AR5K_SIMR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
+#define AR5K_SIMR3_QCBRORN_S 0
+#define AR5K_SIMR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */
+#define AR5K_SIMR3_QCBRURN_S 16
+
+#define AR5K_SIMR4 0x00b4 /* Register Address [5211+] */
+#define AR5K_SIMR4_QTRIG 0x000003ff /* Mask for QTRIG */
+#define AR5K_SIMR4_QTRIG_S 0
+
+/*
+ * DMA Debug registers 0-7
+ * 0xe0 - 0xfc
+ */
+
+/*
+ * Decompression mask registers [5212+]
+ */
+#define AR5K_DCM_ADDR 0x0400 /*Decompression mask address (index) */
+#define AR5K_DCM_DATA 0x0404 /*Decompression mask data */
+
+/*
+ * Wake On Wireless pattern control register [5212+]
+ */
+#define AR5K_WOW_PCFG 0x0410 /* Register Address */
+#define AR5K_WOW_PCFG_PAT_MATCH_EN 0x00000001 /* Pattern match enable */
+#define AR5K_WOW_PCFG_LONG_FRAME_POL 0x00000002 /* Long frame policy */
+#define AR5K_WOW_PCFG_WOBMISS 0x00000004 /* Wake on bea(con) miss (?) */
+#define AR5K_WOW_PCFG_PAT_0_EN 0x00000100 /* Enable pattern 0 */
+#define AR5K_WOW_PCFG_PAT_1_EN 0x00000200 /* Enable pattern 1 */
+#define AR5K_WOW_PCFG_PAT_2_EN 0x00000400 /* Enable pattern 2 */
+#define AR5K_WOW_PCFG_PAT_3_EN 0x00000800 /* Enable pattern 3 */
+#define AR5K_WOW_PCFG_PAT_4_EN 0x00001000 /* Enable pattern 4 */
+#define AR5K_WOW_PCFG_PAT_5_EN 0x00002000 /* Enable pattern 5 */
+
+/*
+ * Wake On Wireless pattern index register (?) [5212+]
+ */
+#define AR5K_WOW_PAT_IDX 0x0414
+
+/*
+ * Wake On Wireless pattern data register [5212+]
+ */
+#define AR5K_WOW_PAT_DATA 0x0418 /* Register Address */
+#define AR5K_WOW_PAT_DATA_0_3_V 0x00000001 /* Pattern 0, 3 value */
+#define AR5K_WOW_PAT_DATA_1_4_V 0x00000100 /* Pattern 1, 4 value */
+#define AR5K_WOW_PAT_DATA_2_5_V 0x00010000 /* Pattern 2, 5 value */
+#define AR5K_WOW_PAT_DATA_0_3_M 0x01000000 /* Pattern 0, 3 mask */
+#define AR5K_WOW_PAT_DATA_1_4_M 0x04000000 /* Pattern 1, 4 mask */
+#define AR5K_WOW_PAT_DATA_2_5_M 0x10000000 /* Pattern 2, 5 mask */
+
+/*
+ * Decompression configuration registers [5212+]
+ */
+#define AR5K_DCCFG 0x0420 /* Register Address */
+#define AR5K_DCCFG_GLOBAL_EN 0x00000001 /* Enable decompression on all queues */
+#define AR5K_DCCFG_BYPASS_EN 0x00000002 /* Bypass decompression */
+#define AR5K_DCCFG_BCAST_EN 0x00000004 /* Enable decompression for bcast frames */
+#define AR5K_DCCFG_MCAST_EN 0x00000008 /* Enable decompression for mcast frames */
+
+/*
+ * Compression configuration registers [5212+]
+ */
+#define AR5K_CCFG 0x0600 /* Register Address */
+#define AR5K_CCFG_WINDOW_SIZE 0x00000007 /* Compression window size */
+#define AR5K_CCFG_CPC_EN 0x00000008 /* Enable performance counters */
+
+#define AR5K_CCFG_CCU 0x0604 /* Register Address */
+#define AR5K_CCFG_CCU_CUP_EN 0x00000001 /* CCU Catchup enable */
+#define AR5K_CCFG_CCU_CREDIT 0x00000002 /* CCU Credit (field) */
+#define AR5K_CCFG_CCU_CD_THRES 0x00000080 /* CCU Cyc(lic?) debt threshold (field) */
+#define AR5K_CCFG_CCU_CUP_LCNT 0x00010000 /* CCU Catchup lit(?) count */
+#define AR5K_CCFG_CCU_INIT 0x00100200 /* Initial value during reset */
+
+/*
+ * Compression performance counter registers [5212+]
+ */
+#define AR5K_CPC0 0x0610 /* Compression performance counter 0 */
+#define AR5K_CPC1 0x0614 /* Compression performance counter 1*/
+#define AR5K_CPC2 0x0618 /* Compression performance counter 2 */
+#define AR5K_CPC3 0x061c /* Compression performance counter 3 */
+#define AR5K_CPCOVF 0x0620 /* Compression performance overflow */
+
+
+/*
+ * Queue control unit (QCU) registers [5211+]
+ *
+ * Card has 12 TX Queues but i see that only 0-9 are used (?)
+ * both in binary HAL (see ah.h) and ar5k. Each queue has it's own
+ * TXDP at addresses 0x0800 - 0x082c, a CBR (Constant Bit Rate)
+ * configuration register (0x08c0 - 0x08ec), a ready time configuration
+ * register (0x0900 - 0x092c), a misc configuration register (0x09c0 -
+ * 0x09ec) and a status register (0x0a00 - 0x0a2c). We also have some
+ * global registers, QCU transmit enable/disable and "one shot arm (?)"
+ * set/clear, which contain status for all queues (we shift by 1 for each
+ * queue). To access these registers easily we define some macros here
+ * that are used inside HAL. For more infos check out *_tx_queue functs.
+ */
+
+/*
+ * Generic QCU Register access macros
+ */
+#define AR5K_QUEUE_REG(_r, _q) (((_q) << 2) + _r)
+#define AR5K_QCU_GLOBAL_READ(_r, _q) (AR5K_REG_READ(_r) & (1 << _q))
+#define AR5K_QCU_GLOBAL_WRITE(_r, _q) AR5K_REG_WRITE(_r, (1 << _q))
+
+/*
+ * QCU Transmit descriptor pointer registers
+ */
+#define AR5K_QCU_TXDP_BASE 0x0800 /* Register Address - Queue0 TXDP */
+#define AR5K_QUEUE_TXDP(_q) AR5K_QUEUE_REG(AR5K_QCU_TXDP_BASE, _q)
+
+/*
+ * QCU Transmit enable register
+ */
+#define AR5K_QCU_TXE 0x0840
+#define AR5K_ENABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXE, _q)
+#define AR5K_QUEUE_ENABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXE, _q)
+
+/*
+ * QCU Transmit disable register
+ */
+#define AR5K_QCU_TXD 0x0880
+#define AR5K_DISABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXD, _q)
+#define AR5K_QUEUE_DISABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXD, _q)
+
+/*
+ * QCU Constant Bit Rate configuration registers
+ */
+#define AR5K_QCU_CBRCFG_BASE 0x08c0 /* Register Address - Queue0 CBRCFG */
+#define AR5K_QCU_CBRCFG_INTVAL 0x00ffffff /* CBR Interval mask */
+#define AR5K_QCU_CBRCFG_INTVAL_S 0
+#define AR5K_QCU_CBRCFG_ORN_THRES 0xff000000 /* CBR overrun threshold mask */
+#define AR5K_QCU_CBRCFG_ORN_THRES_S 24
+#define AR5K_QUEUE_CBRCFG(_q) AR5K_QUEUE_REG(AR5K_QCU_CBRCFG_BASE, _q)
+
+/*
+ * QCU Ready time configuration registers
+ */
+#define AR5K_QCU_RDYTIMECFG_BASE 0x0900 /* Register Address - Queue0 RDYTIMECFG */
+#define AR5K_QCU_RDYTIMECFG_INTVAL 0x00ffffff /* Ready time interval mask */
+#define AR5K_QCU_RDYTIMECFG_INTVAL_S 0
+#define AR5K_QCU_RDYTIMECFG_ENABLE 0x01000000 /* Ready time enable mask */
+#define AR5K_QUEUE_RDYTIMECFG(_q) AR5K_QUEUE_REG(AR5K_QCU_RDYTIMECFG_BASE, _q)
+
+/*
+ * QCU one shot arm set registers
+ */
+#define AR5K_QCU_ONESHOTARM_SET 0x0940 /* Register Address -QCU "one shot arm set (?)" */
+#define AR5K_QCU_ONESHOTARM_SET_M 0x0000ffff
+
+/*
+ * QCU one shot arm clear registers
+ */
+#define AR5K_QCU_ONESHOTARM_CLEAR 0x0980 /* Register Address -QCU "one shot arm clear (?)" */
+#define AR5K_QCU_ONESHOTARM_CLEAR_M 0x0000ffff
+
+/*
+ * QCU misc registers
+ */
+#define AR5K_QCU_MISC_BASE 0x09c0 /* Register Address -Queue0 MISC */
+#define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */
+#define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */
+#define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */
+#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated */
+#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* TIMT gated */
+#define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated */
+#define AR5K_QCU_MISC_ONESHOT_ENABLE 0x00000010 /* Oneshot enable */
+#define AR5K_QCU_MISC_CBREXP_DIS 0x00000020 /* Disable CBR expired counter (normal queue) */
+#define AR5K_QCU_MISC_CBREXP_BCN_DIS 0x00000040 /* Disable CBR expired counter (beacon queue) */
+#define AR5K_QCU_MISC_BCN_ENABLE 0x00000080 /* Enable Beacon use */
+#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR expired threshold enabled */
+#define AR5K_QCU_MISC_RDY_VEOL_POLICY 0x00000200 /* TXE reset when RDYTIME expired or VEOL */
+#define AR5K_QCU_MISC_CBR_RESET_CNT 0x00000400 /* CBR threshold (counter) reset */
+#define AR5K_QCU_MISC_DCU_EARLY 0x00000800 /* DCU early termination */
+#define AR5K_QCU_MISC_DCU_CMP_EN 0x00001000 /* Enable frame compression */
+#define AR5K_QUEUE_MISC(_q) AR5K_QUEUE_REG(AR5K_QCU_MISC_BASE, _q)
+
+
+/*
+ * QCU status registers
+ */
+#define AR5K_QCU_STS_BASE 0x0a00 /* Register Address - Queue0 STS */
+#define AR5K_QCU_STS_FRMPENDCNT 0x00000003 /* Frames pending counter */
+#define AR5K_QCU_STS_CBREXPCNT 0x0000ff00 /* CBR expired counter */
+#define AR5K_QUEUE_STATUS(_q) AR5K_QUEUE_REG(AR5K_QCU_STS_BASE, _q)
+
+/*
+ * QCU ready time shutdown register
+ */
+#define AR5K_QCU_RDYTIMESHDN 0x0a40
+#define AR5K_QCU_RDYTIMESHDN_M 0x000003ff
+
+/*
+ * QCU compression buffer base registers [5212+]
+ */
+#define AR5K_QCU_CBB_SELECT 0x0b00
+#define AR5K_QCU_CBB_ADDR 0x0b04
+#define AR5K_QCU_CBB_ADDR_S 9
+
+/*
+ * QCU compression buffer configuration register [5212+]
+ * (buffer size)
+ */
+#define AR5K_QCU_CBCFG 0x0b08
+
+
+
+/*
+ * Distributed Coordination Function (DCF) control unit (DCU)
+ * registers [5211+]
+ *
+ * These registers control the various characteristics of each queue
+ * for 802.11e (WME) combatibility so they go together with
+ * QCU registers in pairs. For each queue we have a QCU mask register,
+ * (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c),
+ * a retry limit register (0x1080 - 0x10ac), a channel time register
+ * (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and
+ * a sequence number register (0x1140 - 0x116c). It seems that "global"
+ * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).
+ * We use the same macros here for easier register access.
+ *
+ */
+
+/*
+ * DCU QCU mask registers
+ */
+#define AR5K_DCU_QCUMASK_BASE 0x1000 /* Register Address -Queue0 DCU_QCUMASK */
+#define AR5K_DCU_QCUMASK_M 0x000003ff
+#define AR5K_QUEUE_QCUMASK(_q) AR5K_QUEUE_REG(AR5K_DCU_QCUMASK_BASE, _q)
+
+/*
+ * DCU local Inter Frame Space settings register
+ */
+#define AR5K_DCU_LCL_IFS_BASE 0x1040 /* Register Address -Queue0 DCU_LCL_IFS */
+#define AR5K_DCU_LCL_IFS_CW_MIN 0x000003ff /* Minimum Contention Window */
+#define AR5K_DCU_LCL_IFS_CW_MIN_S 0
+#define AR5K_DCU_LCL_IFS_CW_MAX 0x000ffc00 /* Maximum Contention Window */
+#define AR5K_DCU_LCL_IFS_CW_MAX_S 10
+#define AR5K_DCU_LCL_IFS_AIFS 0x0ff00000 /* Arbitrated Interframe Space */
+#define AR5K_DCU_LCL_IFS_AIFS_S 20
+#define AR5K_DCU_LCL_IFS_AIFS_MAX 0xfc /* Anything above that can cause DCU to hang */
+#define AR5K_QUEUE_DFS_LOCAL_IFS(_q) AR5K_QUEUE_REG(AR5K_DCU_LCL_IFS_BASE, _q)
+
+/*
+ * DCU retry limit registers
+ */
+#define AR5K_DCU_RETRY_LMT_BASE 0x1080 /* Register Address -Queue0 DCU_RETRY_LMT */
+#define AR5K_DCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */
+#define AR5K_DCU_RETRY_LMT_SH_RETRY_S 0
+#define AR5K_DCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry limit mask */
+#define AR5K_DCU_RETRY_LMT_LG_RETRY_S 4
+#define AR5K_DCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask (?) */
+#define AR5K_DCU_RETRY_LMT_SSH_RETRY_S 8
+#define AR5K_DCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask (?) */
+#define AR5K_DCU_RETRY_LMT_SLG_RETRY_S 14
+#define AR5K_QUEUE_DFS_RETRY_LIMIT(_q) AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q)
+
+/*
+ * DCU channel time registers
+ */
+#define AR5K_DCU_CHAN_TIME_BASE 0x10c0 /* Register Address -Queue0 DCU_CHAN_TIME */
+#define AR5K_DCU_CHAN_TIME_DUR 0x000fffff /* Channel time duration */
+#define AR5K_DCU_CHAN_TIME_DUR_S 0
+#define AR5K_DCU_CHAN_TIME_ENABLE 0x00100000 /* Enable channel time */
+#define AR5K_QUEUE_DFS_CHANNEL_TIME(_q) AR5K_QUEUE_REG(AR5K_DCU_CHAN_TIME_BASE, _q)
+
+/*
+ * DCU misc registers [5211+]
+ *
+ * Note: Arbiter lockout control controls the
+ * behaviour on low priority queues when we have multiple queues
+ * with pending frames. Intra-frame lockout means we wait until
+ * the queue's current frame transmits (with post frame backoff and bursting)
+ * before we transmit anything else and global lockout means we
+ * wait for the whole queue to finish before higher priority queues
+ * can transmit (this is used on beacon and CAB queues).
+ * No lockout means there is no special handling.
+ */
+#define AR5K_DCU_MISC_BASE 0x1100 /* Register Address -Queue0 DCU_MISC */
+#define AR5K_DCU_MISC_BACKOFF 0x0000003f /* Mask for backoff threshold */
+#define AR5K_DCU_MISC_ETS_RTS_POL 0x00000040 /* End of transmission series
+ station RTS/data failure count
+ reset policy (?) */
+#define AR5K_DCU_MISC_ETS_CW_POL 0x00000080 /* End of transmission series
+ CW reset policy */
+#define AR5K_DCU_MISC_FRAG_WAIT 0x00000100 /* Wait for next fragment */
+#define AR5K_DCU_MISC_BACKOFF_FRAG 0x00000200 /* Enable backoff while bursting */
+#define AR5K_DCU_MISC_HCFPOLL_ENABLE 0x00000800 /* CF - Poll enable */
+#define AR5K_DCU_MISC_BACKOFF_PERSIST 0x00001000 /* Persistent backoff */
+#define AR5K_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 /* Enable frame pre-fetch */
+#define AR5K_DCU_MISC_VIRTCOL 0x0000c000 /* Mask for Virtual Collision (?) */
+#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0
+#define AR5K_DCU_MISC_VIRTCOL_IGNORE 1
+#define AR5K_DCU_MISC_BCN_ENABLE 0x00010000 /* Enable Beacon use */
+#define AR5K_DCU_MISC_ARBLOCK_CTL 0x00060000 /* Arbiter lockout control mask */
+#define AR5K_DCU_MISC_ARBLOCK_CTL_S 17
+#define AR5K_DCU_MISC_ARBLOCK_CTL_NONE 0 /* No arbiter lockout */
+#define AR5K_DCU_MISC_ARBLOCK_CTL_INTFRM 1 /* Intra-frame lockout */
+#define AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL 2 /* Global lockout */
+#define AR5K_DCU_MISC_ARBLOCK_IGNORE 0x00080000 /* Ignore Arbiter lockout */
+#define AR5K_DCU_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Disable sequence number increment */
+#define AR5K_DCU_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Disable post-frame backoff */
+#define AR5K_DCU_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual Collision cw policy */
+#define AR5K_DCU_MISC_BLOWN_IFS_POLICY 0x00800000 /* Blown IFS policy (?) */
+#define AR5K_DCU_MISC_SEQNUM_CTL 0x01000000 /* Sequence number control (?) */
+#define AR5K_QUEUE_DFS_MISC(_q) AR5K_QUEUE_REG(AR5K_DCU_MISC_BASE, _q)
+
+/*
+ * DCU frame sequence number registers
+ */
+#define AR5K_DCU_SEQNUM_BASE 0x1140
+#define AR5K_DCU_SEQNUM_M 0x00000fff
+#define AR5K_QUEUE_DCU_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q)
+
+/*
+ * DCU global IFS SIFS register
+ */
+#define AR5K_DCU_GBL_IFS_SIFS 0x1030
+#define AR5K_DCU_GBL_IFS_SIFS_M 0x0000ffff
+
+/*
+ * DCU global IFS slot interval register
+ */
+#define AR5K_DCU_GBL_IFS_SLOT 0x1070
+#define AR5K_DCU_GBL_IFS_SLOT_M 0x0000ffff
+
+/*
+ * DCU global IFS EIFS register
+ */
+#define AR5K_DCU_GBL_IFS_EIFS 0x10b0
+#define AR5K_DCU_GBL_IFS_EIFS_M 0x0000ffff
+
+/*
+ * DCU global IFS misc register
+ *
+ * LFSR stands for Linear Feedback Shift Register
+ * and it's used for generating pseudo-random
+ * number sequences.
+ *
+ * (If i understand corectly, random numbers are
+ * used for idle sensing -multiplied with cwmin/max etc-)
+ */
+#define AR5K_DCU_GBL_IFS_MISC 0x10f0 /* Register Address */
+#define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 /* LFSR Slice Select */
+#define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */
+#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */
+#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */
+#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10
+#define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */
+#define AR5K_DCU_GBL_IFS_MISC_SIFS_CNT_RST 0x00400000 /* SIFS cnt reset policy (?) */
+#define AR5K_DCU_GBL_IFS_MISC_AIFS_CNT_RST 0x00800000 /* AIFS cnt reset policy (?) */
+#define AR5K_DCU_GBL_IFS_MISC_RND_LFSR_SL_DIS 0x01000000 /* Disable random LFSR slice */
+
+/*
+ * DCU frame prefetch control register
+ */
+#define AR5K_DCU_FP 0x1230 /* Register Address */
+#define AR5K_DCU_FP_NOBURST_DCU_EN 0x00000001 /* Enable non-burst prefetch on DCU (?) */
+#define AR5K_DCU_FP_NOBURST_EN 0x00000010 /* Enable non-burst prefetch (?) */
+#define AR5K_DCU_FP_BURST_DCU_EN 0x00000020 /* Enable burst prefetch on DCU (?) */
+
+/*
+ * DCU transmit pause control/status register
+ */
+#define AR5K_DCU_TXP 0x1270 /* Register Address */
+#define AR5K_DCU_TXP_M 0x000003ff /* Tx pause mask */
+#define AR5K_DCU_TXP_STATUS 0x00010000 /* Tx pause status */
+
+/*
+ * DCU transmit filter table 0 (32 entries)
+ * each entry contains a 32bit slice of the
+ * 128bit tx filter for each DCU (4 slices per DCU)
+ */
+#define AR5K_DCU_TX_FILTER_0_BASE 0x1038
+#define AR5K_DCU_TX_FILTER_0(_n) (AR5K_DCU_TX_FILTER_0_BASE + (_n * 64))
+
+/*
+ * DCU transmit filter table 1 (16 entries)
+ */
+#define AR5K_DCU_TX_FILTER_1_BASE 0x103c
+#define AR5K_DCU_TX_FILTER_1(_n) (AR5K_DCU_TX_FILTER_1_BASE + (_n * 64))
+
+/*
+ * DCU clear transmit filter register
+ */
+#define AR5K_DCU_TX_FILTER_CLR 0x143c
+
+/*
+ * DCU set transmit filter register
+ */
+#define AR5K_DCU_TX_FILTER_SET 0x147c
+
+/*
+ * Reset control register
+ */
+#define AR5K_RESET_CTL 0x4000 /* Register Address */
+#define AR5K_RESET_CTL_PCU 0x00000001 /* Protocol Control Unit reset */
+#define AR5K_RESET_CTL_DMA 0x00000002 /* DMA (Rx/Tx) reset [5210] */
+#define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset [5211+] */
+#define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */
+#define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */
+#define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */
+
+/*
+ * Sleep control register
+ */
+#define AR5K_SLEEP_CTL 0x4004 /* Register Address */
+#define AR5K_SLEEP_CTL_SLDUR 0x0000ffff /* Sleep duration mask */
+#define AR5K_SLEEP_CTL_SLDUR_S 0
+#define AR5K_SLEEP_CTL_SLE 0x00030000 /* Sleep enable mask */
+#define AR5K_SLEEP_CTL_SLE_S 16
+#define AR5K_SLEEP_CTL_SLE_WAKE 0x00000000 /* Force chip awake */
+#define AR5K_SLEEP_CTL_SLE_SLP 0x00010000 /* Force chip sleep */
+#define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000 /* Normal sleep policy */
+#define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* [5211+] */
+#define AR5K_SLEEP_CTL_DUR_TIM_POL 0x00040000 /* Sleep duration timing policy */
+#define AR5K_SLEEP_CTL_DUR_WRITE_POL 0x00080000 /* Sleep duration write policy */
+#define AR5K_SLEEP_CTL_SLE_POL 0x00100000 /* Sleep policy mode */
+
+/*
+ * Interrupt pending register
+ */
+#define AR5K_INTPEND 0x4008
+#define AR5K_INTPEND_M 0x00000001
+
+/*
+ * Sleep force register
+ */
+#define AR5K_SFR 0x400c
+#define AR5K_SFR_EN 0x00000001
+
+/*
+ * PCI configuration register
+ * TODO: Fix LED stuff
+ */
+#define AR5K_PCICFG 0x4010 /* Register Address */
+#define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */
+#define AR5K_PCICFG_SLEEP_CLOCK_EN 0x00000002 /* Enable sleep clock */
+#define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */
+#define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */
+#define AR5K_PCICFG_EESIZE_S 3
+#define AR5K_PCICFG_EESIZE_4K 0 /* 4K */
+#define AR5K_PCICFG_EESIZE_8K 1 /* 8K */
+#define AR5K_PCICFG_EESIZE_16K 2 /* 16K */
+#define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size [5211+] */
+#define AR5K_PCICFG_LED 0x00000060 /* Led status [5211+] */
+#define AR5K_PCICFG_LED_NONE 0x00000000 /* Default [5211+] */
+#define AR5K_PCICFG_LED_PEND 0x00000020 /* Scan / Auth pending */
+#define AR5K_PCICFG_LED_ASSOC 0x00000040 /* Associated */
+#define AR5K_PCICFG_BUS_SEL 0x00000380 /* Mask for "bus select" [5211+] (?) */
+#define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix */
+#define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep */
+#define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */
+#define AR5K_PCICFG_RETRY_FIX 0x00001000 /* Enable pci core retry fix */
+#define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even whith pending interrupts*/
+#define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */
+#define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */
+#define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */
+#define AR5K_PCICFG_LEDMODE_PROM 0x00020000 /* Default mode (blink on any traffic) [5211+] */
+#define AR5K_PCICFG_LEDMODE_PWR 0x00040000 /* Some other blinking mode (?) [5211+] */
+#define AR5K_PCICFG_LEDMODE_RAND 0x00060000 /* Random blinking (?) [5211+] */
+#define AR5K_PCICFG_LEDBLINK 0x00700000 /* Led blink rate */
+#define AR5K_PCICFG_LEDBLINK_S 20
+#define AR5K_PCICFG_LEDSLOW 0x00800000 /* Slowest led blink rate [5211+] */
+#define AR5K_PCICFG_LEDSTATE \
+ (AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE | \
+ AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW)
+#define AR5K_PCICFG_SLEEP_CLOCK_RATE 0x03000000 /* Sleep clock rate */
+#define AR5K_PCICFG_SLEEP_CLOCK_RATE_S 24
+
+/*
+ * "General Purpose Input/Output" (GPIO) control register
+ *
+ * I'm not sure about this but after looking at the code
+ * for all chipsets here is what i got.
+ *
+ * We have 6 GPIOs (pins), each GPIO has 4 modes (2 bits)
+ * Mode 0 -> always input
+ * Mode 1 -> output when GPIODO for this GPIO is set to 0
+ * Mode 2 -> output when GPIODO for this GPIO is set to 1
+ * Mode 3 -> always output
+ *
+ * For more infos check out get_gpio/set_gpio and
+ * set_gpio_input/set_gpio_output functs.
+ * For more infos on gpio interrupt check out set_gpio_intr.
+ */
+#define AR5K_NUM_GPIO 6
+
+#define AR5K_GPIOCR 0x4014 /* Register Address */
+#define AR5K_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */
+#define AR5K_GPIOCR_INT_SELL 0x00000000 /* Generate interrupt when pin is low */
+#define AR5K_GPIOCR_INT_SELH 0x00010000 /* Generate interrupt when pin is high */
+#define AR5K_GPIOCR_IN(n) (0 << ((n) * 2)) /* Mode 0 for pin n */
+#define AR5K_GPIOCR_OUT0(n) (1 << ((n) * 2)) /* Mode 1 for pin n */
+#define AR5K_GPIOCR_OUT1(n) (2 << ((n) * 2)) /* Mode 2 for pin n */
+#define AR5K_GPIOCR_OUT(n) (3 << ((n) * 2)) /* Mode 3 for pin n */
+#define AR5K_GPIOCR_INT_SEL(n) ((n) << 12) /* Interrupt for GPIO pin n */
+
+/*
+ * "General Purpose Input/Output" (GPIO) data output register
+ */
+#define AR5K_GPIODO 0x4018
+
+/*
+ * "General Purpose Input/Output" (GPIO) data input register
+ */
+#define AR5K_GPIODI 0x401c
+#define AR5K_GPIODI_M 0x0000002f
+
+/*
+ * Silicon revision register
+ */
+#define AR5K_SREV 0x4020 /* Register Address */
+#define AR5K_SREV_REV 0x0000000f /* Mask for revision */
+#define AR5K_SREV_REV_S 0
+#define AR5K_SREV_VER 0x000000ff /* Mask for version */
+#define AR5K_SREV_VER_S 4
+
+/*
+ * TXE write posting register
+ */
+#define AR5K_TXEPOST 0x4028
+
+/*
+ * QCU sleep mask
+ */
+#define AR5K_QCU_SLEEP_MASK 0x402c
+
+/* 0x4068 is compression buffer configuration
+ * register on 5414 and pm configuration register
+ * on 5424 and newer pci-e chips. */
+
+/*
+ * Compression buffer configuration
+ * register (enable/disable) [5414]
+ */
+#define AR5K_5414_CBCFG 0x4068
+#define AR5K_5414_CBCFG_BUF_DIS 0x10 /* Disable buffer */
+
+/*
+ * PCI-E Power managment configuration
+ * and status register [5424+]
+ */
+#define AR5K_PCIE_PM_CTL 0x4068 /* Register address */
+/* Only 5424 */
+#define AR5K_PCIE_PM_CTL_L1_WHEN_D2 0x00000001 /* enable PCIe core enter L1
+ when d2_sleep_en is asserted */
+#define AR5K_PCIE_PM_CTL_L0_L0S_CLEAR 0x00000002 /* Clear L0 and L0S counters */
+#define AR5K_PCIE_PM_CTL_L0_L0S_EN 0x00000004 /* Start L0 nd L0S counters */
+#define AR5K_PCIE_PM_CTL_LDRESET_EN 0x00000008 /* Enable reset when link goes
+ down */
+/* Wake On Wireless */
+#define AR5K_PCIE_PM_CTL_PME_EN 0x00000010 /* PME Enable */
+#define AR5K_PCIE_PM_CTL_AUX_PWR_DET 0x00000020 /* Aux power detect */
+#define AR5K_PCIE_PM_CTL_PME_CLEAR 0x00000040 /* Clear PME */
+#define AR5K_PCIE_PM_CTL_PSM_D0 0x00000080
+#define AR5K_PCIE_PM_CTL_PSM_D1 0x00000100
+#define AR5K_PCIE_PM_CTL_PSM_D2 0x00000200
+#define AR5K_PCIE_PM_CTL_PSM_D3 0x00000400
+
+/*
+ * PCI-E Workaround enable register
+ */
+#define AR5K_PCIE_WAEN 0x407c
+
+/*
+ * PCI-E Serializer/Desirializer
+ * registers
+ */
+#define AR5K_PCIE_SERDES 0x4080
+#define AR5K_PCIE_SERDES_RESET 0x4084
+
+/*====EEPROM REGISTERS====*/
+
+/*
+ * EEPROM access registers
+ *
+ * Here we got a difference between 5210/5211-12
+ * read data register for 5210 is at 0x6800 and
+ * status register is at 0x6c00. There is also
+ * no eeprom command register on 5210 and the
+ * offsets are different.
+ *
+ * To read eeprom data for a specific offset:
+ * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
+ * read AR5K_EEPROM_BASE +(4 * offset)
+ * check the eeprom status register
+ * and read eeprom data register.
+ *
+ * 5211 - write offset to AR5K_EEPROM_BASE
+ * 5212 write AR5K_EEPROM_CMD_READ on AR5K_EEPROM_CMD
+ * check the eeprom status register
+ * and read eeprom data register.
+ *
+ * To write eeprom data for a specific offset:
+ * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
+ * write data to AR5K_EEPROM_BASE +(4 * offset)
+ * check the eeprom status register
+ * 5211 - write AR5K_EEPROM_CMD_RESET on AR5K_EEPROM_CMD
+ * 5212 write offset to AR5K_EEPROM_BASE
+ * write data to data register
+ * write AR5K_EEPROM_CMD_WRITE on AR5K_EEPROM_CMD
+ * check the eeprom status register
+ *
+ * For more infos check eeprom_* functs and the ar5k.c
+ * file posted in madwifi-devel mailing list.
+ * http://sourceforge.net/mailarchive/message.php?msg_id=8966525
+ *
+ */
+#define AR5K_EEPROM_BASE 0x6000
+
+/*
+ * EEPROM data register
+ */
+#define AR5K_EEPROM_DATA_5211 0x6004
+#define AR5K_EEPROM_DATA_5210 0x6800
+#define AR5K_EEPROM_DATA (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211)
+
+/*
+ * EEPROM command register
+ */
+#define AR5K_EEPROM_CMD 0x6008 /* Register Addres */
+#define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */
+#define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */
+#define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */
+
+/*
+ * EEPROM status register
+ */
+#define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */
+#define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */
+#define AR5K_EEPROM_STATUS (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211)
+#define AR5K_EEPROM_STAT_RDERR 0x00000001 /* EEPROM read failed */
+#define AR5K_EEPROM_STAT_RDDONE 0x00000002 /* EEPROM read successful */
+#define AR5K_EEPROM_STAT_WRERR 0x00000004 /* EEPROM write failed */
+#define AR5K_EEPROM_STAT_WRDONE 0x00000008 /* EEPROM write successful */
+
+/*
+ * EEPROM config register
+ */
+#define AR5K_EEPROM_CFG 0x6010 /* Register Addres */
+#define AR5K_EEPROM_CFG_SIZE 0x00000003 /* Size determination override */
+#define AR5K_EEPROM_CFG_SIZE_AUTO 0
+#define AR5K_EEPROM_CFG_SIZE_4KBIT 1
+#define AR5K_EEPROM_CFG_SIZE_8KBIT 2
+#define AR5K_EEPROM_CFG_SIZE_16KBIT 3
+#define AR5K_EEPROM_CFG_WR_WAIT_DIS 0x00000004 /* Disable write wait */
+#define AR5K_EEPROM_CFG_CLK_RATE 0x00000018 /* Clock rate */
+#define AR5K_EEPROM_CFG_CLK_RATE_S 3
+#define AR5K_EEPROM_CFG_CLK_RATE_156KHZ 0
+#define AR5K_EEPROM_CFG_CLK_RATE_312KHZ 1
+#define AR5K_EEPROM_CFG_CLK_RATE_625KHZ 2
+#define AR5K_EEPROM_CFG_PROT_KEY 0x00ffff00 /* Protection key */
+#define AR5K_EEPROM_CFG_PROT_KEY_S 8
+#define AR5K_EEPROM_CFG_LIND_EN 0x01000000 /* Enable length indicator (?) */
+
+
+/*
+ * TODO: Wake On Wireless registers
+ * Range 0x7000 - 0x7ce0
+ */
+
+/*
+ * Protocol Control Unit (PCU) registers
+ */
+/*
+ * Used for checking initial register writes
+ * during channel reset (see reset func)
+ */
+#define AR5K_PCU_MIN 0x8000
+#define AR5K_PCU_MAX 0x8fff
+
+/*
+ * First station id register (Lower 32 bits of MAC address)
+ */
+#define AR5K_STA_ID0 0x8000
+#define AR5K_STA_ID0_ARRD_L32 0xffffffff
+
+/*
+ * Second station id register (Upper 16 bits of MAC address + PCU settings)
+ */
+#define AR5K_STA_ID1 0x8004 /* Register Address */
+#define AR5K_STA_ID1_ADDR_U16 0x0000ffff /* Upper 16 bits of MAC addres */
+#define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */
+#define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */
+#define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */
+#define AR5K_STA_ID1_NO_KEYSRCH 0x00080000 /* No key search */
+#define AR5K_STA_ID1_NO_PSPOLL 0x00100000 /* No power save polling [5210] */
+#define AR5K_STA_ID1_PCF_5211 0x00100000 /* Enable PCF on [5211+] */
+#define AR5K_STA_ID1_PCF_5210 0x00200000 /* Enable PCF on [5210]*/
+#define AR5K_STA_ID1_PCF (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_STA_ID1_PCF_5210 : AR5K_STA_ID1_PCF_5211)
+#define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */
+#define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */
+#define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS */
+#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS */
+#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate for ACK/CTS [5211+] */
+#define AR5K_STA_ID1_SELFGEN_DEF_ANT 0x04000000 /* Use def. antenna for self generated frames */
+#define AR5K_STA_ID1_CRYPT_MIC_EN 0x08000000 /* Enable MIC */
+#define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Look up key when key id != 0 */
+#define AR5K_STA_ID1_PRESERVE_SEQ_NUM 0x20000000 /* Preserve sequence number */
+#define AR5K_STA_ID1_CBCIV_ENDIAN 0x40000000 /* ??? */
+#define AR5K_STA_ID1_KEYSRCH_MCAST 0x80000000 /* Do key cache search for mcast frames */
+
+/*
+ * First BSSID register (MAC address, lower 32bits)
+ */
+#define AR5K_BSS_ID0 0x8008
+
+/*
+ * Second BSSID register (MAC address in upper 16 bits)
+ *
+ * AID: Association ID
+ */
+#define AR5K_BSS_ID1 0x800c
+#define AR5K_BSS_ID1_AID 0xffff0000
+#define AR5K_BSS_ID1_AID_S 16
+
+/*
+ * Backoff slot time register
+ */
+#define AR5K_SLOT_TIME 0x8010
+
+/*
+ * ACK/CTS timeout register
+ */
+#define AR5K_TIME_OUT 0x8014 /* Register Address */
+#define AR5K_TIME_OUT_ACK 0x00001fff /* ACK timeout mask */
+#define AR5K_TIME_OUT_ACK_S 0
+#define AR5K_TIME_OUT_CTS 0x1fff0000 /* CTS timeout mask */
+#define AR5K_TIME_OUT_CTS_S 16
+
+/*
+ * RSSI threshold register
+ */
+#define AR5K_RSSI_THR 0x8018 /* Register Address */
+#define AR5K_RSSI_THR_M 0x000000ff /* Mask for RSSI threshold [5211+] */
+#define AR5K_RSSI_THR_BMISS_5210 0x00000700 /* Mask for Beacon Missed threshold [5210] */
+#define AR5K_RSSI_THR_BMISS_5210_S 8
+#define AR5K_RSSI_THR_BMISS_5211 0x0000ff00 /* Mask for Beacon Missed threshold [5211+] */
+#define AR5K_RSSI_THR_BMISS_5211_S 8
+#define AR5K_RSSI_THR_BMISS (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_RSSI_THR_BMISS_5210 : AR5K_RSSI_THR_BMISS_5211)
+#define AR5K_RSSI_THR_BMISS_S 8
+
+/*
+ * 5210 has more PCU registers because there is no QCU/DCU
+ * so queue parameters are set here, this way a lot common
+ * registers have different address for 5210. To make things
+ * easier we define a macro based on ah->ah_version for common
+ * registers with different addresses and common flags.
+ */
+
+/*
+ * Retry limit register
+ *
+ * Retry limit register for 5210 (no QCU/DCU so it's done in PCU)
+ */
+#define AR5K_NODCU_RETRY_LMT 0x801c /* Register Address */
+#define AR5K_NODCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */
+#define AR5K_NODCU_RETRY_LMT_SH_RETRY_S 0
+#define AR5K_NODCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry mask */
+#define AR5K_NODCU_RETRY_LMT_LG_RETRY_S 4
+#define AR5K_NODCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask */
+#define AR5K_NODCU_RETRY_LMT_SSH_RETRY_S 8
+#define AR5K_NODCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask */
+#define AR5K_NODCU_RETRY_LMT_SLG_RETRY_S 14
+#define AR5K_NODCU_RETRY_LMT_CW_MIN 0x3ff00000 /* Minimum contention window mask */
+#define AR5K_NODCU_RETRY_LMT_CW_MIN_S 20
+
+/*
+ * Transmit latency register
+ */
+#define AR5K_USEC_5210 0x8020 /* Register Address [5210] */
+#define AR5K_USEC_5211 0x801c /* Register Address [5211+] */
+#define AR5K_USEC (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_USEC_5210 : AR5K_USEC_5211)
+#define AR5K_USEC_1 0x0000007f /* clock cycles for 1us */
+#define AR5K_USEC_1_S 0
+#define AR5K_USEC_32 0x00003f80 /* clock cycles for 1us while on 32Mhz clock */
+#define AR5K_USEC_32_S 7
+#define AR5K_USEC_TX_LATENCY_5211 0x007fc000
+#define AR5K_USEC_TX_LATENCY_5211_S 14
+#define AR5K_USEC_RX_LATENCY_5211 0x1f800000
+#define AR5K_USEC_RX_LATENCY_5211_S 23
+#define AR5K_USEC_TX_LATENCY_5210 0x000fc000 /* also for 5311 */
+#define AR5K_USEC_TX_LATENCY_5210_S 14
+#define AR5K_USEC_RX_LATENCY_5210 0x03f00000 /* also for 5311 */
+#define AR5K_USEC_RX_LATENCY_5210_S 20
+
+/*
+ * PCU beacon control register
+ */
+#define AR5K_BEACON_5210 0x8024 /*Register Address [5210] */
+#define AR5K_BEACON_5211 0x8020 /*Register Address [5211+] */
+#define AR5K_BEACON (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_BEACON_5210 : AR5K_BEACON_5211)
+#define AR5K_BEACON_PERIOD 0x0000ffff /* Mask for beacon period */
+#define AR5K_BEACON_PERIOD_S 0
+#define AR5K_BEACON_TIM 0x007f0000 /* Mask for TIM offset */
+#define AR5K_BEACON_TIM_S 16
+#define AR5K_BEACON_ENABLE 0x00800000 /* Enable beacons */
+#define AR5K_BEACON_RESET_TSF 0x01000000 /* Force TSF reset */
+
+/*
+ * CFP period register
+ */
+#define AR5K_CFP_PERIOD_5210 0x8028
+#define AR5K_CFP_PERIOD_5211 0x8024
+#define AR5K_CFP_PERIOD (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_CFP_PERIOD_5210 : AR5K_CFP_PERIOD_5211)
+
+/*
+ * Next beacon time register
+ */
+#define AR5K_TIMER0_5210 0x802c
+#define AR5K_TIMER0_5211 0x8028
+#define AR5K_TIMER0 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TIMER0_5210 : AR5K_TIMER0_5211)
+
+/*
+ * Next DMA beacon alert register
+ */
+#define AR5K_TIMER1_5210 0x8030
+#define AR5K_TIMER1_5211 0x802c
+#define AR5K_TIMER1 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TIMER1_5210 : AR5K_TIMER1_5211)
+
+/*
+ * Next software beacon alert register
+ */
+#define AR5K_TIMER2_5210 0x8034
+#define AR5K_TIMER2_5211 0x8030
+#define AR5K_TIMER2 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TIMER2_5210 : AR5K_TIMER2_5211)
+
+/*
+ * Next ATIM window time register
+ */
+#define AR5K_TIMER3_5210 0x8038
+#define AR5K_TIMER3_5211 0x8034
+#define AR5K_TIMER3 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TIMER3_5210 : AR5K_TIMER3_5211)
+
+
+/*
+ * 5210 First inter frame spacing register (IFS)
+ */
+#define AR5K_IFS0 0x8040
+#define AR5K_IFS0_SIFS 0x000007ff
+#define AR5K_IFS0_SIFS_S 0
+#define AR5K_IFS0_DIFS 0x007ff800
+#define AR5K_IFS0_DIFS_S 11
+
+/*
+ * 5210 Second inter frame spacing register (IFS)
+ */
+#define AR5K_IFS1 0x8044
+#define AR5K_IFS1_PIFS 0x00000fff
+#define AR5K_IFS1_PIFS_S 0
+#define AR5K_IFS1_EIFS 0x03fff000
+#define AR5K_IFS1_EIFS_S 12
+#define AR5K_IFS1_CS_EN 0x04000000
+
+
+/*
+ * CFP duration register
+ */
+#define AR5K_CFP_DUR_5210 0x8048
+#define AR5K_CFP_DUR_5211 0x8038
+#define AR5K_CFP_DUR (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_CFP_DUR_5210 : AR5K_CFP_DUR_5211)
+
+/*
+ * Receive filter register
+ */
+#define AR5K_RX_FILTER_5210 0x804c /* Register Address [5210] */
+#define AR5K_RX_FILTER_5211 0x803c /* Register Address [5211+] */
+#define AR5K_RX_FILTER (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211)
+#define AR5K_RX_FILTER_UCAST 0x00000001 /* Don't filter unicast frames */
+#define AR5K_RX_FILTER_MCAST 0x00000002 /* Don't filter multicast frames */
+#define AR5K_RX_FILTER_BCAST 0x00000004 /* Don't filter broadcast frames */
+#define AR5K_RX_FILTER_CONTROL 0x00000008 /* Don't filter control frames */
+#define AR5K_RX_FILTER_BEACON 0x00000010 /* Don't filter beacon frames */
+#define AR5K_RX_FILTER_PROM 0x00000020 /* Set promiscuous mode */
+#define AR5K_RX_FILTER_XRPOLL 0x00000040 /* Don't filter XR poll frame [5212+] */
+#define AR5K_RX_FILTER_PROBEREQ 0x00000080 /* Don't filter probe requests [5212+] */
+#define AR5K_RX_FILTER_PHYERR_5212 0x00000100 /* Don't filter phy errors [5212+] */
+#define AR5K_RX_FILTER_RADARERR_5212 0x00000200 /* Don't filter phy radar errors [5212+] */
+#define AR5K_RX_FILTER_PHYERR_5211 0x00000040 /* [5211] */
+#define AR5K_RX_FILTER_RADARERR_5211 0x00000080 /* [5211] */
+#define AR5K_RX_FILTER_PHYERR \
+ ((ah->ah_version == AR5K_AR5211 ? \
+ AR5K_RX_FILTER_PHYERR_5211 : AR5K_RX_FILTER_PHYERR_5212))
+#define AR5K_RX_FILTER_RADARERR \
+ ((ah->ah_version == AR5K_AR5211 ? \
+ AR5K_RX_FILTER_RADARERR_5211 : AR5K_RX_FILTER_RADARERR_5212))
+
+/*
+ * Multicast filter register (lower 32 bits)
+ */
+#define AR5K_MCAST_FILTER0_5210 0x8050
+#define AR5K_MCAST_FILTER0_5211 0x8040
+#define AR5K_MCAST_FILTER0 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_MCAST_FILTER0_5210 : AR5K_MCAST_FILTER0_5211)
+
+/*
+ * Multicast filter register (higher 16 bits)
+ */
+#define AR5K_MCAST_FILTER1_5210 0x8054
+#define AR5K_MCAST_FILTER1_5211 0x8044
+#define AR5K_MCAST_FILTER1 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_MCAST_FILTER1_5210 : AR5K_MCAST_FILTER1_5211)
+
+
+/*
+ * Transmit mask register (lower 32 bits) [5210]
+ */
+#define AR5K_TX_MASK0 0x8058
+
+/*
+ * Transmit mask register (higher 16 bits) [5210]
+ */
+#define AR5K_TX_MASK1 0x805c
+
+/*
+ * Clear transmit mask [5210]
+ */
+#define AR5K_CLR_TMASK 0x8060
+
+/*
+ * Trigger level register (before transmission) [5210]
+ */
+#define AR5K_TRIG_LVL 0x8064
+
+
+/*
+ * PCU control register
+ *
+ * Only DIS_RX is used in the code, the rest i guess are
+ * for tweaking/diagnostics.
+ */
+#define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */
+#define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */
+#define AR5K_DIAG_SW (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_5210 : AR5K_DIAG_SW_5211)
+#define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 /* Disable ACKs if WEP key is invalid */
+#define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */
+#define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */
+#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption */
+#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption */
+#define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */
+#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */
+#define AR5K_DIAG_SW_DIS_RX_5211 0x00000020
+#define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211)
+#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* Loopback (i guess it goes with DIS_TX) [5210] */
+#define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040
+#define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211)
+#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Corrupted FCS */
+#define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080
+#define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211)
+#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Dump channel info */
+#define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100
+#define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211)
+#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400 /* Enable fixed scrambler seed */
+#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200
+#define AR5K_DIAG_SW_EN_SCRAM_SEED (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211)
+#define AR5K_DIAG_SW_ECO_ENABLE 0x00000400 /* [5211+] */
+#define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */
+#define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */
+#define AR5K_DIAG_SW_SCRAM_SEED_S 10
+#define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */
+#define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000
+#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */
+#define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211)
+#define AR5K_DIAG_SW_OBSPT_M 0x000c0000 /* Observation point select (?) */
+#define AR5K_DIAG_SW_OBSPT_S 18
+#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */
+#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */
+#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */
+#define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */
+
+/*
+ * TSF (clock) register (lower 32 bits)
+ */
+#define AR5K_TSF_L32_5210 0x806c
+#define AR5K_TSF_L32_5211 0x804c
+#define AR5K_TSF_L32 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211)
+
+/*
+ * TSF (clock) register (higher 32 bits)
+ */
+#define AR5K_TSF_U32_5210 0x8070
+#define AR5K_TSF_U32_5211 0x8050
+#define AR5K_TSF_U32 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211)
+
+/*
+ * Last beacon timestamp register (Read Only)
+ */
+#define AR5K_LAST_TSTP 0x8080
+
+/*
+ * ADDAC test register [5211+]
+ */
+#define AR5K_ADDAC_TEST 0x8054 /* Register Address */
+#define AR5K_ADDAC_TEST_TXCONT 0x00000001 /* Test continuous tx */
+#define AR5K_ADDAC_TEST_TST_MODE 0x00000002 /* Test mode */
+#define AR5K_ADDAC_TEST_LOOP_EN 0x00000004 /* Enable loop */
+#define AR5K_ADDAC_TEST_LOOP_LEN 0x00000008 /* Loop length (field) */
+#define AR5K_ADDAC_TEST_USE_U8 0x00004000 /* Use upper 8 bits */
+#define AR5K_ADDAC_TEST_MSB 0x00008000 /* State of MSB */
+#define AR5K_ADDAC_TEST_TRIG_SEL 0x00010000 /* Trigger select */
+#define AR5K_ADDAC_TEST_TRIG_PTY 0x00020000 /* Trigger polarity */
+#define AR5K_ADDAC_TEST_RXCONT 0x00040000 /* Continuous capture */
+#define AR5K_ADDAC_TEST_CAPTURE 0x00080000 /* Begin capture */
+#define AR5K_ADDAC_TEST_TST_ARM 0x00100000 /* ARM rx buffer for capture */
+
+/*
+ * Default antenna register [5211+]
+ */
+#define AR5K_DEFAULT_ANTENNA 0x8058
+
+/*
+ * Frame control QoS mask register (?) [5211+]
+ * (FC_QOS_MASK)
+ */
+#define AR5K_FRAME_CTL_QOSM 0x805c
+
+/*
+ * Seq mask register (?) [5211+]
+ */
+#define AR5K_SEQ_MASK 0x8060
+
+/*
+ * Retry count register [5210]
+ */
+#define AR5K_RETRY_CNT 0x8084 /* Register Address [5210] */
+#define AR5K_RETRY_CNT_SSH 0x0000003f /* Station short retry count (?) */
+#define AR5K_RETRY_CNT_SLG 0x00000fc0 /* Station long retry count (?) */
+
+/*
+ * Back-off status register [5210]
+ */
+#define AR5K_BACKOFF 0x8088 /* Register Address [5210] */
+#define AR5K_BACKOFF_CW 0x000003ff /* Backoff Contention Window (?) */
+#define AR5K_BACKOFF_CNT 0x03ff0000 /* Backoff count (?) */
+
+
+
+/*
+ * NAV register (current)
+ */
+#define AR5K_NAV_5210 0x808c
+#define AR5K_NAV_5211 0x8084
+#define AR5K_NAV (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_NAV_5210 : AR5K_NAV_5211)
+
+/*
+ * RTS success register
+ */
+#define AR5K_RTS_OK_5210 0x8090
+#define AR5K_RTS_OK_5211 0x8088
+#define AR5K_RTS_OK (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211)
+
+/*
+ * RTS failure register
+ */
+#define AR5K_RTS_FAIL_5210 0x8094
+#define AR5K_RTS_FAIL_5211 0x808c
+#define AR5K_RTS_FAIL (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211)
+
+/*
+ * ACK failure register
+ */
+#define AR5K_ACK_FAIL_5210 0x8098
+#define AR5K_ACK_FAIL_5211 0x8090
+#define AR5K_ACK_FAIL (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211)
+
+/*
+ * FCS failure register
+ */
+#define AR5K_FCS_FAIL_5210 0x809c
+#define AR5K_FCS_FAIL_5211 0x8094
+#define AR5K_FCS_FAIL (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_FCS_FAIL_5210 : AR5K_FCS_FAIL_5211)
+
+/*
+ * Beacon count register
+ */
+#define AR5K_BEACON_CNT_5210 0x80a0
+#define AR5K_BEACON_CNT_5211 0x8098
+#define AR5K_BEACON_CNT (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_BEACON_CNT_5210 : AR5K_BEACON_CNT_5211)
+
+
+/*===5212 Specific PCU registers===*/
+
+/*
+ * Transmit power control register
+ */
+#define AR5K_TPC 0x80e8
+#define AR5K_TPC_ACK 0x0000003f /* ack frames */
+#define AR5K_TPC_ACK_S 0
+#define AR5K_TPC_CTS 0x00003f00 /* cts frames */
+#define AR5K_TPC_CTS_S 8
+#define AR5K_TPC_CHIRP 0x003f0000 /* chirp frames */
+#define AR5K_TPC_CHIRP_S 16
+#define AR5K_TPC_DOPPLER 0x0f000000 /* doppler chirp span */
+#define AR5K_TPC_DOPPLER_S 24
+
+/*
+ * XR (eXtended Range) mode register
+ */
+#define AR5K_XRMODE 0x80c0 /* Register Address */
+#define AR5K_XRMODE_POLL_TYPE_M 0x0000003f /* Mask for Poll type (?) */
+#define AR5K_XRMODE_POLL_TYPE_S 0
+#define AR5K_XRMODE_POLL_SUBTYPE_M 0x0000003c /* Mask for Poll subtype (?) */
+#define AR5K_XRMODE_POLL_SUBTYPE_S 2
+#define AR5K_XRMODE_POLL_WAIT_ALL 0x00000080 /* Wait for poll */
+#define AR5K_XRMODE_SIFS_DELAY 0x000fff00 /* Mask for SIFS delay */
+#define AR5K_XRMODE_FRAME_HOLD_M 0xfff00000 /* Mask for frame hold (?) */
+#define AR5K_XRMODE_FRAME_HOLD_S 20
+
+/*
+ * XR delay register
+ */
+#define AR5K_XRDELAY 0x80c4 /* Register Address */
+#define AR5K_XRDELAY_SLOT_DELAY_M 0x0000ffff /* Mask for slot delay */
+#define AR5K_XRDELAY_SLOT_DELAY_S 0
+#define AR5K_XRDELAY_CHIRP_DELAY_M 0xffff0000 /* Mask for CHIRP data delay */
+#define AR5K_XRDELAY_CHIRP_DELAY_S 16
+
+/*
+ * XR timeout register
+ */
+#define AR5K_XRTIMEOUT 0x80c8 /* Register Address */
+#define AR5K_XRTIMEOUT_CHIRP_M 0x0000ffff /* Mask for CHIRP timeout */
+#define AR5K_XRTIMEOUT_CHIRP_S 0
+#define AR5K_XRTIMEOUT_POLL_M 0xffff0000 /* Mask for Poll timeout */
+#define AR5K_XRTIMEOUT_POLL_S 16
+
+/*
+ * XR chirp register
+ */
+#define AR5K_XRCHIRP 0x80cc /* Register Address */
+#define AR5K_XRCHIRP_SEND 0x00000001 /* Send CHIRP */
+#define AR5K_XRCHIRP_GAP 0xffff0000 /* Mask for CHIRP gap (?) */
+
+/*
+ * XR stomp register
+ */
+#define AR5K_XRSTOMP 0x80d0 /* Register Address */
+#define AR5K_XRSTOMP_TX 0x00000001 /* Stomp Tx (?) */
+#define AR5K_XRSTOMP_RX 0x00000002 /* Stomp Rx (?) */
+#define AR5K_XRSTOMP_TX_RSSI 0x00000004 /* Stomp Tx RSSI (?) */
+#define AR5K_XRSTOMP_TX_BSSID 0x00000008 /* Stomp Tx BSSID (?) */
+#define AR5K_XRSTOMP_DATA 0x00000010 /* Stomp data (?)*/
+#define AR5K_XRSTOMP_RSSI_THRES 0x0000ff00 /* Mask for XR RSSI threshold */
+
+/*
+ * First enhanced sleep register
+ */
+#define AR5K_SLEEP0 0x80d4 /* Register Address */
+#define AR5K_SLEEP0_NEXT_DTIM 0x0007ffff /* Mask for next DTIM (?) */
+#define AR5K_SLEEP0_NEXT_DTIM_S 0
+#define AR5K_SLEEP0_ASSUME_DTIM 0x00080000 /* Assume DTIM */
+#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000 /* Enable enchanced sleep control */
+#define AR5K_SLEEP0_CABTO 0xff000000 /* Mask for CAB Time Out */
+#define AR5K_SLEEP0_CABTO_S 24
+
+/*
+ * Second enhanced sleep register
+ */
+#define AR5K_SLEEP1 0x80d8 /* Register Address */
+#define AR5K_SLEEP1_NEXT_TIM 0x0007ffff /* Mask for next TIM (?) */
+#define AR5K_SLEEP1_NEXT_TIM_S 0
+#define AR5K_SLEEP1_BEACON_TO 0xff000000 /* Mask for Beacon Time Out */
+#define AR5K_SLEEP1_BEACON_TO_S 24
+
+/*
+ * Third enhanced sleep register
+ */
+#define AR5K_SLEEP2 0x80dc /* Register Address */
+#define AR5K_SLEEP2_TIM_PER 0x0000ffff /* Mask for TIM period (?) */
+#define AR5K_SLEEP2_TIM_PER_S 0
+#define AR5K_SLEEP2_DTIM_PER 0xffff0000 /* Mask for DTIM period (?) */
+#define AR5K_SLEEP2_DTIM_PER_S 16
+
+/*
+ * BSSID mask registers
+ */
+#define AR5K_BSS_IDM0 0x80e0 /* Upper bits */
+#define AR5K_BSS_IDM1 0x80e4 /* Lower bits */
+
+/*
+ * TX power control (TPC) register
+ *
+ * XXX: PCDAC steps (0.5dbm) or DBM ?
+ *
+ */
+#define AR5K_TXPC 0x80e8 /* Register Address */
+#define AR5K_TXPC_ACK_M 0x0000003f /* ACK tx power */
+#define AR5K_TXPC_ACK_S 0
+#define AR5K_TXPC_CTS_M 0x00003f00 /* CTS tx power */
+#define AR5K_TXPC_CTS_S 8
+#define AR5K_TXPC_CHIRP_M 0x003f0000 /* CHIRP tx power */
+#define AR5K_TXPC_CHIRP_S 16
+#define AR5K_TXPC_DOPPLER 0x0f000000 /* Doppler chirp span (?) */
+#define AR5K_TXPC_DOPPLER_S 24
+
+/*
+ * Profile count registers
+ */
+#define AR5K_PROFCNT_TX 0x80ec /* Tx count */
+#define AR5K_PROFCNT_RX 0x80f0 /* Rx count */
+#define AR5K_PROFCNT_RXCLR 0x80f4 /* Clear Rx count */
+#define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */
+
+/*
+ * Quiet period control registers
+ */
+#define AR5K_QUIET_CTL1 0x80fc /* Register Address */
+#define AR5K_QUIET_CTL1_NEXT_QT_TSF 0x0000ffff /* Next quiet period TSF (TU) */
+#define AR5K_QUIET_CTL1_NEXT_QT_TSF_S 0
+#define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet period */
+#define AR5K_QUIET_CTL1_ACK_CTS_EN 0x00020000 /* Send ACK/CTS during quiet period */
+
+#define AR5K_QUIET_CTL2 0x8100 /* Register Address */
+#define AR5K_QUIET_CTL2_QT_PER 0x0000ffff /* Mask for quiet period periodicity */
+#define AR5K_QUIET_CTL2_QT_PER_S 0
+#define AR5K_QUIET_CTL2_QT_DUR 0xffff0000 /* Mask for quiet period duration */
+#define AR5K_QUIET_CTL2_QT_DUR_S 16
+
+/*
+ * TSF parameter register
+ */
+#define AR5K_TSF_PARM 0x8104 /* Register Address */
+#define AR5K_TSF_PARM_INC 0x000000ff /* Mask for TSF increment */
+#define AR5K_TSF_PARM_INC_S 0
+
+/*
+ * QoS NOACK policy
+ */
+#define AR5K_QOS_NOACK 0x8108 /* Register Address */
+#define AR5K_QOS_NOACK_2BIT_VALUES 0x0000000f /* ??? */
+#define AR5K_QOS_NOACK_2BIT_VALUES_S 0
+#define AR5K_QOS_NOACK_BIT_OFFSET 0x00000070 /* ??? */
+#define AR5K_QOS_NOACK_BIT_OFFSET_S 4
+#define AR5K_QOS_NOACK_BYTE_OFFSET 0x00000180 /* ??? */
+#define AR5K_QOS_NOACK_BYTE_OFFSET_S 7
+
+/*
+ * PHY error filter register
+ */
+#define AR5K_PHY_ERR_FIL 0x810c
+#define AR5K_PHY_ERR_FIL_RADAR 0x00000020 /* Radar signal */
+#define AR5K_PHY_ERR_FIL_OFDM 0x00020000 /* OFDM false detect (ANI) */
+#define AR5K_PHY_ERR_FIL_CCK 0x02000000 /* CCK false detect (ANI) */
+
+/*
+ * XR latency register
+ */
+#define AR5K_XRLAT_TX 0x8110
+
+/*
+ * ACK SIFS register
+ */
+#define AR5K_ACKSIFS 0x8114 /* Register Address */
+#define AR5K_ACKSIFS_INC 0x00000000 /* ACK SIFS Increment (field) */
+
+/*
+ * MIC QoS control register (?)
+ */
+#define AR5K_MIC_QOS_CTL 0x8118 /* Register Address */
+#define AR5K_MIC_QOS_CTL_OFF(_n) (1 << (_n * 2))
+#define AR5K_MIC_QOS_CTL_MQ_EN 0x00010000 /* Enable MIC QoS */
+
+/*
+ * MIC QoS select register (?)
+ */
+#define AR5K_MIC_QOS_SEL 0x811c
+#define AR5K_MIC_QOS_SEL_OFF(_n) (1 << (_n * 4))
+
+/*
+ * Misc mode control register (?)
+ */
+#define AR5K_MISC_MODE 0x8120 /* Register Address */
+#define AR5K_MISC_MODE_FBSSID_MATCH 0x00000001 /* Force BSSID match */
+#define AR5K_MISC_MODE_ACKSIFS_MEM 0x00000002 /* ACK SIFS memory (?) */
+#define AR5K_MISC_MODE_COMBINED_MIC 0x00000004 /* use rx/tx MIC key */
+/* more bits */
+
+/*
+ * OFDM Filter counter
+ */
+#define AR5K_OFDM_FIL_CNT 0x8124
+
+/*
+ * CCK Filter counter
+ */
+#define AR5K_CCK_FIL_CNT 0x8128
+
+/*
+ * PHY Error Counters (?)
+ */
+#define AR5K_PHYERR_CNT1 0x812c
+#define AR5K_PHYERR_CNT1_MASK 0x8130
+
+#define AR5K_PHYERR_CNT2 0x8134
+#define AR5K_PHYERR_CNT2_MASK 0x8138
+
+/*
+ * TSF Threshold register (?)
+ */
+#define AR5K_TSF_THRES 0x813c
+
+/*
+ * TODO: Wake On Wireless registers
+ * Range: 0x8147 - 0x818c
+ */
+
+/*
+ * Rate -> ACK SIFS mapping table (32 entries)
+ */
+#define AR5K_RATE_ACKSIFS_BASE 0x8680 /* Register Address */
+#define AR5K_RATE_ACKSIFS(_n) (AR5K_RATE_ACKSIFS_BSE + ((_n) << 2))
+#define AR5K_RATE_ACKSIFS_NORMAL 0x00000001 /* Normal SIFS (field) */
+#define AR5K_RATE_ACKSIFS_TURBO 0x00000400 /* Turbo SIFS (field) */
+
+/*
+ * Rate -> duration mapping table (32 entries)
+ */
+#define AR5K_RATE_DUR_BASE 0x8700
+#define AR5K_RATE_DUR(_n) (AR5K_RATE_DUR_BASE + ((_n) << 2))
+
+/*
+ * Rate -> db mapping table
+ * (8 entries, each one has 4 8bit fields)
+ */
+#define AR5K_RATE2DB_BASE 0x87c0
+#define AR5K_RATE2DB(_n) (AR5K_RATE2DB_BASE + ((_n) << 2))
+
+/*
+ * db -> Rate mapping table
+ * (8 entries, each one has 4 8bit fields)
+ */
+#define AR5K_DB2RATE_BASE 0x87e0
+#define AR5K_DB2RATE(_n) (AR5K_DB2RATE_BASE + ((_n) << 2))
+
+/*===5212 end===*/
+
+/*
+ * Key table (WEP) register
+ */
+#define AR5K_KEYTABLE_0_5210 0x9000
+#define AR5K_KEYTABLE_0_5211 0x8800
+#define AR5K_KEYTABLE_5210(_n) (AR5K_KEYTABLE_0_5210 + ((_n) << 5))
+#define AR5K_KEYTABLE_5211(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5))
+#define AR5K_KEYTABLE(_n) (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n))
+#define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + (x << 2))
+#define AR5K_KEYTABLE_TYPE(_n) AR5K_KEYTABLE_OFF(_n, 5)
+#define AR5K_KEYTABLE_TYPE_40 0x00000000
+#define AR5K_KEYTABLE_TYPE_104 0x00000001
+#define AR5K_KEYTABLE_TYPE_128 0x00000003
+#define AR5K_KEYTABLE_TYPE_TKIP 0x00000004 /* [5212+] */
+#define AR5K_KEYTABLE_TYPE_AES 0x00000005 /* [5211+] */
+#define AR5K_KEYTABLE_TYPE_CCM 0x00000006 /* [5212+] */
+#define AR5K_KEYTABLE_TYPE_NULL 0x00000007 /* [5211+] */
+#define AR5K_KEYTABLE_ANTENNA 0x00000008 /* [5212+] */
+#define AR5K_KEYTABLE_MAC0(_n) AR5K_KEYTABLE_OFF(_n, 6)
+#define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7)
+#define AR5K_KEYTABLE_VALID 0x00008000
+
+/* If key type is TKIP and MIC is enabled
+ * MIC key goes in offset entry + 64 */
+#define AR5K_KEYTABLE_MIC_OFFSET 64
+
+/* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit
+ * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit
+ * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit
+ *
+ * Some vendors have introduced bigger WEP keys to address
+ * security vulnerabilities in WEP. This includes:
+ *
+ * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit
+ *
+ * We can expand this if we find ar5k Atheros cards with a larger
+ * key table size.
+ */
+#define AR5K_KEYTABLE_SIZE_5210 64
+#define AR5K_KEYTABLE_SIZE_5211 128
+#define AR5K_KEYTABLE_SIZE (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211)
+
+
+/*===PHY REGISTERS===*/
+
+/*
+ * PHY registers start
+ */
+#define AR5K_PHY_BASE 0x9800
+#define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2))
+
+/*
+ * TST_2 (Misc config parameters)
+ */
+#define AR5K_PHY_TST2 0x9800 /* Register Address */
+#define AR5K_PHY_TST2_TRIG_SEL 0x00000007 /* Trigger select (?)*/
+#define AR5K_PHY_TST2_TRIG 0x00000010 /* Trigger (?) */
+#define AR5K_PHY_TST2_CBUS_MODE 0x00000060 /* Cardbus mode (?) */
+#define AR5K_PHY_TST2_CLK32 0x00000400 /* CLK_OUT is CLK32 (32Khz external) */
+#define AR5K_PHY_TST2_CHANCOR_DUMP_EN 0x00000800 /* Enable Chancor dump (?) */
+#define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP 0x00001000 /* Even Chancor dump (?) */
+#define AR5K_PHY_TST2_RFSILENT_EN 0x00002000 /* Enable RFSILENT */
+#define AR5K_PHY_TST2_ALT_RFDATA 0x00004000 /* Alternate RFDATA (5-2GHz switch ?) */
+#define AR5K_PHY_TST2_MINI_OBS_EN 0x00008000 /* Enable mini OBS (?) */
+#define AR5K_PHY_TST2_RX2_IS_RX5_INV 0x00010000 /* 2GHz rx path is the 5GHz path inverted (?) */
+#define AR5K_PHY_TST2_SLOW_CLK160 0x00020000 /* Slow CLK160 (?) */
+#define AR5K_PHY_TST2_AGC_OBS_SEL_3 0x00040000 /* AGC OBS Select 3 (?) */
+#define AR5K_PHY_TST2_BBB_OBS_SEL 0x00080000 /* BB OBS Select (field ?) */
+#define AR5K_PHY_TST2_ADC_OBS_SEL 0x00800000 /* ADC OBS Select (field ?) */
+#define AR5K_PHY_TST2_RX_CLR_SEL 0x08000000 /* RX Clear Select (?) */
+#define AR5K_PHY_TST2_FORCE_AGC_CLR 0x10000000 /* Force AGC clear (?) */
+#define AR5K_PHY_SHIFT_2GHZ 0x00004007 /* Used to access 2GHz radios */
+#define AR5K_PHY_SHIFT_5GHZ 0x00000007 /* Used to access 5GHz radios (default) */
+
+/*
+ * PHY frame control register [5110] /turbo mode register [5111+]
+ *
+ * There is another frame control register for [5111+]
+ * at address 0x9944 (see below) but the 2 first flags
+ * are common here between 5110 frame control register
+ * and [5111+] turbo mode register, so this also works as
+ * a "turbo mode register" for 5110. We treat this one as
+ * a frame control register for 5110 below.
+ */
+#define AR5K_PHY_TURBO 0x9804 /* Register Address */
+#define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */
+#define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */
+#define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo mimo */
+
+/*
+ * PHY agility command register
+ * (aka TST_1)
+ */
+#define AR5K_PHY_AGC 0x9808 /* Register Address */
+#define AR5K_PHY_TST1 0x9808
+#define AR5K_PHY_AGC_DISABLE 0x08000000 /* Disable AGC to A2 (?)*/
+#define AR5K_PHY_TST1_TXHOLD 0x00003800 /* Set tx hold (?) */
+#define AR5K_PHY_TST1_TXSRC_SRC 0x00000002 /* Used with bit 7 (?) */
+#define AR5K_PHY_TST1_TXSRC_SRC_S 1
+#define AR5K_PHY_TST1_TXSRC_ALT 0x00000080 /* Set input to tsdac (?) */
+#define AR5K_PHY_TST1_TXSRC_ALT_S 7
+
+
+/*
+ * PHY timing register 3 [5112+]
+ */
+#define AR5K_PHY_TIMING_3 0x9814
+#define AR5K_PHY_TIMING_3_DSC_MAN 0xfffe0000
+#define AR5K_PHY_TIMING_3_DSC_MAN_S 17
+#define AR5K_PHY_TIMING_3_DSC_EXP 0x0001e000
+#define AR5K_PHY_TIMING_3_DSC_EXP_S 13
+
+/*
+ * PHY chip revision register
+ */
+#define AR5K_PHY_CHIP_ID 0x9818
+
+/*
+ * PHY activation register
+ */
+#define AR5K_PHY_ACT 0x981c /* Register Address */
+#define AR5K_PHY_ACT_ENABLE 0x00000001 /* Activate PHY */
+#define AR5K_PHY_ACT_DISABLE 0x00000002 /* Deactivate PHY */
+
+/*
+ * PHY RF control registers
+ */
+#define AR5K_PHY_RF_CTL2 0x9824 /* Register Address */
+#define AR5K_PHY_RF_CTL2_TXF2TXD_START 0x0000000f /* TX frame to TX data start */
+#define AR5K_PHY_RF_CTL2_TXF2TXD_START_S 0
+
+#define AR5K_PHY_RF_CTL3 0x9828 /* Register Address */
+#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000ff00 /* TX end to XLNA on */
+#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 8
+
+#define AR5K_PHY_ADC_CTL 0x982c
+#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF 0x00000003
+#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF_S 0
+#define AR5K_PHY_ADC_CTL_PWD_DAC_OFF 0x00002000
+#define AR5K_PHY_ADC_CTL_PWD_BAND_GAP_OFF 0x00004000
+#define AR5K_PHY_ADC_CTL_PWD_ADC_OFF 0x00008000
+#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON 0x00030000
+#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON_S 16
+
+#define AR5K_PHY_RF_CTL4 0x9834 /* Register Address */
+#define AR5K_PHY_RF_CTL4_TXF2XPA_A_ON 0x00000001 /* TX frame to XPA A on (field) */
+#define AR5K_PHY_RF_CTL4_TXF2XPA_B_ON 0x00000100 /* TX frame to XPA B on (field) */
+#define AR5K_PHY_RF_CTL4_TXE2XPA_A_OFF 0x00010000 /* TX end to XPA A off (field) */
+#define AR5K_PHY_RF_CTL4_TXE2XPA_B_OFF 0x01000000 /* TX end to XPA B off (field) */
+
+/*
+ * Pre-Amplifier control register
+ * (XPA -> external pre-amplifier)
+ */
+#define AR5K_PHY_PA_CTL 0x9838 /* Register Address */
+#define AR5K_PHY_PA_CTL_XPA_A_HI 0x00000001 /* XPA A high (?) */
+#define AR5K_PHY_PA_CTL_XPA_B_HI 0x00000002 /* XPA B high (?) */
+#define AR5K_PHY_PA_CTL_XPA_A_EN 0x00000004 /* Enable XPA A */
+#define AR5K_PHY_PA_CTL_XPA_B_EN 0x00000008 /* Enable XPA B */
+
+/*
+ * PHY settling register
+ */
+#define AR5K_PHY_SETTLING 0x9844 /* Register Address */
+#define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */
+#define AR5K_PHY_SETTLING_AGC_S 0
+#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */
+#define AR5K_PHY_SETTLING_SWITCH_S 7
+
+/*
+ * PHY Gain registers
+ */
+#define AR5K_PHY_GAIN 0x9848 /* Register Address */
+#define AR5K_PHY_GAIN_TXRX_ATTEN 0x0003f000 /* TX-RX Attenuation */
+#define AR5K_PHY_GAIN_TXRX_ATTEN_S 12
+#define AR5K_PHY_GAIN_TXRX_RF_MAX 0x007c0000
+#define AR5K_PHY_GAIN_TXRX_RF_MAX_S 18
+
+#define AR5K_PHY_GAIN_OFFSET 0x984c /* Register Address */
+#define AR5K_PHY_GAIN_OFFSET_RXTX_FLAG 0x00020000 /* RX-TX flag (?) */
+
+/*
+ * Desired ADC/PGA size register
+ * (for more infos read ANI patent)
+ */
+#define AR5K_PHY_DESIRED_SIZE 0x9850 /* Register Address */
+#define AR5K_PHY_DESIRED_SIZE_ADC 0x000000ff /* ADC desired size */
+#define AR5K_PHY_DESIRED_SIZE_ADC_S 0
+#define AR5K_PHY_DESIRED_SIZE_PGA 0x0000ff00 /* PGA desired size */
+#define AR5K_PHY_DESIRED_SIZE_PGA_S 8
+#define AR5K_PHY_DESIRED_SIZE_TOT 0x0ff00000 /* Total desired size */
+#define AR5K_PHY_DESIRED_SIZE_TOT_S 20
+
+/*
+ * PHY signal register
+ * (for more infos read ANI patent)
+ */
+#define AR5K_PHY_SIG 0x9858 /* Register Address */
+#define AR5K_PHY_SIG_FIRSTEP 0x0003f000 /* FIRSTEP */
+#define AR5K_PHY_SIG_FIRSTEP_S 12
+#define AR5K_PHY_SIG_FIRPWR 0x03fc0000 /* FIPWR */
+#define AR5K_PHY_SIG_FIRPWR_S 18
+
+/*
+ * PHY coarse agility control register
+ * (for more infos read ANI patent)
+ */
+#define AR5K_PHY_AGCCOARSE 0x985c /* Register Address */
+#define AR5K_PHY_AGCCOARSE_LO 0x00007f80 /* AGC Coarse low */
+#define AR5K_PHY_AGCCOARSE_LO_S 7
+#define AR5K_PHY_AGCCOARSE_HI 0x003f8000 /* AGC Coarse high */
+#define AR5K_PHY_AGCCOARSE_HI_S 15
+
+/*
+ * PHY agility control register
+ */
+#define AR5K_PHY_AGCCTL 0x9860 /* Register address */
+#define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */
+#define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */
+#define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */
+#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */
+
+/*
+ * PHY noise floor status register
+ */
+#define AR5K_PHY_NF 0x9864 /* Register address */
+#define AR5K_PHY_NF_M 0x000001ff /* Noise floor mask */
+#define AR5K_PHY_NF_ACTIVE 0x00000100 /* Noise floor calibration still active */
+#define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M)
+#define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1)
+#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9))
+#define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */
+#define AR5K_PHY_NF_THRESH62_S 12
+#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* ??? */
+#define AR5K_PHY_NF_MINCCA_PWR_S 19
+
+/*
+ * PHY ADC saturation register [5110]
+ */
+#define AR5K_PHY_ADCSAT 0x9868
+#define AR5K_PHY_ADCSAT_ICNT 0x0001f800
+#define AR5K_PHY_ADCSAT_ICNT_S 11
+#define AR5K_PHY_ADCSAT_THR 0x000007e0
+#define AR5K_PHY_ADCSAT_THR_S 5
+
+/*
+ * PHY Weak ofdm signal detection threshold registers (ANI) [5212+]
+ */
+
+/* High thresholds */
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR 0x9868
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT 0x0000001f
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT_S 0
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1 0x00fe0000
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1_S 17
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2 0x7f000000
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_S 24
+
+/* Low thresholds */
+#define AR5K_PHY_WEAK_OFDM_LOW_THR 0x986c
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN 0x00000001
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT 0x00003f00
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT_S 8
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1 0x001fc000
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1_S 14
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2 0x0fe00000
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_S 21
+
+
+/*
+ * PHY sleep registers [5112+]
+ */
+#define AR5K_PHY_SCR 0x9870
+
+#define AR5K_PHY_SLMT 0x9874
+#define AR5K_PHY_SLMT_32MHZ 0x0000007f
+
+#define AR5K_PHY_SCAL 0x9878
+#define AR5K_PHY_SCAL_32MHZ 0x0000000e
+#define AR5K_PHY_SCAL_32MHZ_2417 0x0000000a
+#define AR5K_PHY_SCAL_32MHZ_HB63 0x00000032
+
+/*
+ * PHY PLL (Phase Locked Loop) control register
+ */
+#define AR5K_PHY_PLL 0x987c
+#define AR5K_PHY_PLL_20MHZ 0x00000013 /* For half rate (?) */
+/* 40MHz -> 5GHz band */
+#define AR5K_PHY_PLL_40MHZ_5211 0x00000018
+#define AR5K_PHY_PLL_40MHZ_5212 0x000000aa
+#define AR5K_PHY_PLL_40MHZ_5413 0x00000004
+#define AR5K_PHY_PLL_40MHZ (ah->ah_version == AR5K_AR5211 ? \
+ AR5K_PHY_PLL_40MHZ_5211 : AR5K_PHY_PLL_40MHZ_5212)
+/* 44MHz -> 2.4GHz band */
+#define AR5K_PHY_PLL_44MHZ_5211 0x00000019
+#define AR5K_PHY_PLL_44MHZ_5212 0x000000ab
+#define AR5K_PHY_PLL_44MHZ (ah->ah_version == AR5K_AR5211 ? \
+ AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212)
+
+#define AR5K_PHY_PLL_RF5111 0x00000000
+#define AR5K_PHY_PLL_RF5112 0x00000040
+#define AR5K_PHY_PLL_HALF_RATE 0x00000100
+#define AR5K_PHY_PLL_QUARTER_RATE 0x00000200
+
+/*
+ * RF Buffer register
+ *
+ * It's obvious from the code that 0x989c is the buffer register but
+ * for the other special registers that we write to after sending each
+ * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers
+ * for now. It's interesting that they are also used for some other operations.
+ */
+
+#define AR5K_RF_BUFFER 0x989c
+#define AR5K_RF_BUFFER_CONTROL_0 0x98c0 /* Channel on 5110 */
+#define AR5K_RF_BUFFER_CONTROL_1 0x98c4 /* Bank 7 on 5112 */
+#define AR5K_RF_BUFFER_CONTROL_2 0x98cc /* Bank 7 on 5111 */
+
+#define AR5K_RF_BUFFER_CONTROL_3 0x98d0 /* Bank 2 on 5112 */
+ /* Channel set on 5111 */
+ /* Used to read radio revision*/
+
+#define AR5K_RF_BUFFER_CONTROL_4 0x98d4 /* RF Stage register on 5110 */
+ /* Bank 0,1,2,6 on 5111 */
+ /* Bank 1 on 5112 */
+ /* Used during activation on 5111 */
+
+#define AR5K_RF_BUFFER_CONTROL_5 0x98d8 /* Bank 3 on 5111 */
+ /* Used during activation on 5111 */
+ /* Channel on 5112 */
+ /* Bank 6 on 5112 */
+
+#define AR5K_RF_BUFFER_CONTROL_6 0x98dc /* Bank 3 on 5112 */
+
+/*
+ * PHY RF stage register [5210]
+ */
+#define AR5K_PHY_RFSTG 0x98d4
+#define AR5K_PHY_RFSTG_DISABLE 0x00000021
+
+/*
+ * BIN masks (?)
+ */
+#define AR5K_PHY_BIN_MASK_1 0x9900
+#define AR5K_PHY_BIN_MASK_2 0x9904
+#define AR5K_PHY_BIN_MASK_3 0x9908
+
+#define AR5K_PHY_BIN_MASK_CTL 0x990c
+#define AR5K_PHY_BIN_MASK_CTL_MASK_4 0x00003fff
+#define AR5K_PHY_BIN_MASK_CTL_MASK_4_S 0
+#define AR5K_PHY_BIN_MASK_CTL_RATE 0xff000000
+#define AR5K_PHY_BIN_MASK_CTL_RATE_S 24
+
+/*
+ * PHY Antenna control register
+ */
+#define AR5K_PHY_ANT_CTL 0x9910 /* Register Address */
+#define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */
+#define AR5K_PHY_ANT_CTL_SECTORED_ANT 0x00000004 /* Sectored Antenna */
+#define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */
+#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x000003f0 /* Switch table idle (?) */
+#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S 4
+
+/*
+ * PHY receiver delay register [5111+]
+ */
+#define AR5K_PHY_RX_DELAY 0x9914 /* Register Address */
+#define AR5K_PHY_RX_DELAY_M 0x00003fff /* Mask for RX activate to receive delay (/100ns) */
+
+/*
+ * PHY max rx length register (?) [5111]
+ */
+#define AR5K_PHY_MAX_RX_LEN 0x991c
+
+/*
+ * PHY timing register 4
+ * I(nphase)/Q(adrature) calibration register [5111+]
+ */
+#define AR5K_PHY_IQ 0x9920 /* Register Address */
+#define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */
+#define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */
+#define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5
+#define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */
+#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX 0x0000f000 /* Mask for max number of samples in log scale */
+#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX_S 12
+#define AR5K_PHY_IQ_RUN 0x00010000 /* Run i/q calibration */
+#define AR5K_PHY_IQ_USE_PT_DF 0x00020000 /* Use pilot track df (?) */
+#define AR5K_PHY_IQ_EARLY_TRIG_THR 0x00200000 /* Early trigger threshold (?) (field) */
+#define AR5K_PHY_IQ_PILOT_MASK_EN 0x10000000 /* Enable pilot mask (?) */
+#define AR5K_PHY_IQ_CHAN_MASK_EN 0x20000000 /* Enable channel mask (?) */
+#define AR5K_PHY_IQ_SPUR_FILT_EN 0x40000000 /* Enable spur filter */
+#define AR5K_PHY_IQ_SPUR_RSSI_EN 0x80000000 /* Enable spur rssi */
+
+/*
+ * PHY timing register 5
+ * OFDM Self-correlator Cyclic RSSI threshold params
+ * (Check out bb_cycpwr_thr1 on ANI patent)
+ */
+#define AR5K_PHY_OFDM_SELFCORR 0x9924 /* Register Address */
+#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_EN 0x00000001 /* Enable cyclic RSSI thr 1 */
+#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1 0x000000fe /* Mask for Cyclic RSSI threshold 1 */
+#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 1
+#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR3 0x00000100 /* Cyclic RSSI threshold 3 (field) (?) */
+#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR_EN 0x00008000 /* Enable 1A RSSI threshold (?) */
+#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR 0x00010000 /* 1A RSSI threshold (field) (?) */
+#define AR5K_PHY_OFDM_SELFCORR_LSCTHR_HIRSSI 0x00800000 /* Long sc threshold hi rssi (?) */
+
+/*
+ * PHY-only warm reset register
+ */
+#define AR5K_PHY_WARM_RESET 0x9928
+
+/*
+ * PHY-only control register
+ */
+#define AR5K_PHY_CTL 0x992c /* Register Address */
+#define AR5K_PHY_CTL_RX_DRAIN_RATE 0x00000001 /* RX drain rate (?) */
+#define AR5K_PHY_CTL_LATE_TX_SIG_SYM 0x00000002 /* Late tx signal symbol (?) */
+#define AR5K_PHY_CTL_GEN_SCRAMBLER 0x00000004 /* Generate scrambler */
+#define AR5K_PHY_CTL_TX_ANT_SEL 0x00000008 /* TX antenna select */
+#define AR5K_PHY_CTL_TX_ANT_STATIC 0x00000010 /* Static TX antenna */
+#define AR5K_PHY_CTL_RX_ANT_SEL 0x00000020 /* RX antenna select */
+#define AR5K_PHY_CTL_RX_ANT_STATIC 0x00000040 /* Static RX antenna */
+#define AR5K_PHY_CTL_LOW_FREQ_SLE_EN 0x00000080 /* Enable low freq sleep */
+
+/*
+ * PHY PAPD probe register [5111+]
+ */
+#define AR5K_PHY_PAPD_PROBE 0x9930
+#define AR5K_PHY_PAPD_PROBE_SH_HI_PAR 0x00000001
+#define AR5K_PHY_PAPD_PROBE_PCDAC_BIAS 0x00000002
+#define AR5K_PHY_PAPD_PROBE_COMP_GAIN 0x00000040
+#define AR5K_PHY_PAPD_PROBE_TXPOWER 0x00007e00
+#define AR5K_PHY_PAPD_PROBE_TXPOWER_S 9
+#define AR5K_PHY_PAPD_PROBE_TX_NEXT 0x00008000
+#define AR5K_PHY_PAPD_PROBE_PREDIST_EN 0x00010000
+#define AR5K_PHY_PAPD_PROBE_TYPE 0x01800000 /* [5112+] */
+#define AR5K_PHY_PAPD_PROBE_TYPE_S 23
+#define AR5K_PHY_PAPD_PROBE_TYPE_OFDM 0
+#define AR5K_PHY_PAPD_PROBE_TYPE_XR 1
+#define AR5K_PHY_PAPD_PROBE_TYPE_CCK 2
+#define AR5K_PHY_PAPD_PROBE_GAINF 0xfe000000
+#define AR5K_PHY_PAPD_PROBE_GAINF_S 25
+#define AR5K_PHY_PAPD_PROBE_INI_5111 0x00004883 /* [5212+] */
+#define AR5K_PHY_PAPD_PROBE_INI_5112 0x00004882 /* [5212+] */
+
+/*
+ * PHY TX rate power registers [5112+]
+ */
+#define AR5K_PHY_TXPOWER_RATE1 0x9934
+#define AR5K_PHY_TXPOWER_RATE2 0x9938
+#define AR5K_PHY_TXPOWER_RATE_MAX 0x993c
+#define AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE 0x00000040
+#define AR5K_PHY_TXPOWER_RATE3 0xa234
+#define AR5K_PHY_TXPOWER_RATE4 0xa238
+
+/*
+ * PHY frame control register [5111+]
+ */
+#define AR5K_PHY_FRAME_CTL_5210 0x9804
+#define AR5K_PHY_FRAME_CTL_5211 0x9944
+#define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211)
+/*---[5111+]---*/
+#define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */
+#define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3
+#define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */
+#define AR5K_PHY_FRAME_CTL_EMU 0x80000000
+#define AR5K_PHY_FRAME_CTL_EMU_S 31
+/*---[5110/5111]---*/
+#define AR5K_PHY_FRAME_CTL_TIMING_ERR 0x01000000 /* PHY timing error */
+#define AR5K_PHY_FRAME_CTL_PARITY_ERR 0x02000000 /* Parity error */
+#define AR5K_PHY_FRAME_CTL_ILLRATE_ERR 0x04000000 /* Illegal rate */
+#define AR5K_PHY_FRAME_CTL_ILLLEN_ERR 0x08000000 /* Illegal length */
+#define AR5K_PHY_FRAME_CTL_SERVICE_ERR 0x20000000
+#define AR5K_PHY_FRAME_CTL_TXURN_ERR 0x40000000 /* TX underrun */
+#define AR5K_PHY_FRAME_CTL_INI AR5K_PHY_FRAME_CTL_SERVICE_ERR | \
+ AR5K_PHY_FRAME_CTL_TXURN_ERR | \
+ AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \
+ AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \
+ AR5K_PHY_FRAME_CTL_PARITY_ERR | \
+ AR5K_PHY_FRAME_CTL_TIMING_ERR
+
+/*
+ * PHY Tx Power adjustment register [5212A+]
+ */
+#define AR5K_PHY_TX_PWR_ADJ 0x994c
+#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA 0x00000fc0
+#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA_S 6
+#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX 0x00fc0000
+#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX_S 18
+
+/*
+ * PHY radar detection register [5111+]
+ */
+#define AR5K_PHY_RADAR 0x9954
+#define AR5K_PHY_RADAR_ENABLE 0x00000001
+#define AR5K_PHY_RADAR_DISABLE 0x00000000
+#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e /* Inband threshold
+ 5-bits, units unknown {0..31}
+ (? MHz ?) */
+#define AR5K_PHY_RADAR_INBANDTHR_S 1
+
+#define AR5K_PHY_RADAR_PRSSI_THR 0x00000fc0 /* Pulse RSSI/SNR threshold
+ 6-bits, dBm range {0..63}
+ in dBm units. */
+#define AR5K_PHY_RADAR_PRSSI_THR_S 6
+
+#define AR5K_PHY_RADAR_PHEIGHT_THR 0x0003f000 /* Pulse height threshold
+ 6-bits, dBm range {0..63}
+ in dBm units. */
+#define AR5K_PHY_RADAR_PHEIGHT_THR_S 12
+
+#define AR5K_PHY_RADAR_RSSI_THR 0x00fc0000 /* Radar RSSI/SNR threshold.
+ 6-bits, dBm range {0..63}
+ in dBm units. */
+#define AR5K_PHY_RADAR_RSSI_THR_S 18
+
+#define AR5K_PHY_RADAR_FIRPWR_THR 0x7f000000 /* Finite Impulse Response
+ filter power out threshold.
+ 7-bits, standard power range
+ {0..127} in 1/2 dBm units. */
+#define AR5K_PHY_RADAR_FIRPWR_THRS 24
+
+/*
+ * PHY antenna switch table registers
+ */
+#define AR5K_PHY_ANT_SWITCH_TABLE_0 0x9960
+#define AR5K_PHY_ANT_SWITCH_TABLE_1 0x9964
+
+/*
+ * PHY Noise floor threshold
+ */
+#define AR5K_PHY_NFTHRES 0x9968
+
+/*
+ * Sigma Delta register (?) [5213]
+ */
+#define AR5K_PHY_SIGMA_DELTA 0x996C
+#define AR5K_PHY_SIGMA_DELTA_ADC_SEL 0x00000003
+#define AR5K_PHY_SIGMA_DELTA_ADC_SEL_S 0
+#define AR5K_PHY_SIGMA_DELTA_FILT2 0x000000f8
+#define AR5K_PHY_SIGMA_DELTA_FILT2_S 3
+#define AR5K_PHY_SIGMA_DELTA_FILT1 0x00001f00
+#define AR5K_PHY_SIGMA_DELTA_FILT1_S 8
+#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ffe000
+#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP_S 13
+
+/*
+ * RF restart register [5112+] (?)
+ */
+#define AR5K_PHY_RESTART 0x9970 /* restart */
+#define AR5K_PHY_RESTART_DIV_GC 0x001c0000 /* Fast diversity gc_limit (?) */
+#define AR5K_PHY_RESTART_DIV_GC_S 18
+
+/*
+ * RF Bus access request register (for synth-oly channel switching)
+ */
+#define AR5K_PHY_RFBUS_REQ 0x997C
+#define AR5K_PHY_RFBUS_REQ_REQUEST 0x00000001
+
+/*
+ * Spur mitigation masks (?)
+ */
+#define AR5K_PHY_TIMING_7 0x9980
+#define AR5K_PHY_TIMING_8 0x9984
+#define AR5K_PHY_TIMING_8_PILOT_MASK_2 0x000fffff
+#define AR5K_PHY_TIMING_8_PILOT_MASK_2_S 0
+
+#define AR5K_PHY_BIN_MASK2_1 0x9988
+#define AR5K_PHY_BIN_MASK2_2 0x998c
+#define AR5K_PHY_BIN_MASK2_3 0x9990
+
+#define AR5K_PHY_BIN_MASK2_4 0x9994
+#define AR5K_PHY_BIN_MASK2_4_MASK_4 0x00003fff
+#define AR5K_PHY_BIN_MASK2_4_MASK_4_S 0
+
+#define AR5K_PHY_TIMING_9 0x9998
+#define AR5K_PHY_TIMING_10 0x999c
+#define AR5K_PHY_TIMING_10_PILOT_MASK_2 0x000fffff
+#define AR5K_PHY_TIMING_10_PILOT_MASK_2_S 0
+
+/*
+ * Spur mitigation control
+ */
+#define AR5K_PHY_TIMING_11 0x99a0 /* Register address */
+#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE 0x000fffff /* Spur delta phase */
+#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE_S 0
+#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD 0x3ff00000 /* Freq sigma delta */
+#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD_S 20
+#define AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC 0x40000000 /* Spur filter in AGC detector */
+#define AR5K_PHY_TIMING_11_USE_SPUR_IN_SELFCOR 0x80000000 /* Spur filter in OFDM self correlator */
+
+/*
+ * Gain tables
+ */
+#define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */
+#define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2))
+#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplrifier Gain table base address */
+#define AR5K_RF_GAIN(_n) (AR5K_RF_GAIN_BASE + ((_n) << 2))
+
+/*
+ * PHY timing IQ calibration result register [5111+]
+ */
+#define AR5K_PHY_IQRES_CAL_PWR_I 0x9c10 /* I (Inphase) power value */
+#define AR5K_PHY_IQRES_CAL_PWR_Q 0x9c14 /* Q (Quadrature) power value */
+#define AR5K_PHY_IQRES_CAL_CORR 0x9c18 /* I/Q Correlation */
+
+/*
+ * PHY current RSSI register [5111+]
+ */
+#define AR5K_PHY_CURRENT_RSSI 0x9c1c
+
+/*
+ * PHY RF Bus grant register
+ */
+#define AR5K_PHY_RFBUS_GRANT 0x9c20
+#define AR5K_PHY_RFBUS_GRANT_OK 0x00000001
+
+/*
+ * PHY ADC test register
+ */
+#define AR5K_PHY_ADC_TEST 0x9c24
+#define AR5K_PHY_ADC_TEST_I 0x00000001
+#define AR5K_PHY_ADC_TEST_Q 0x00000200
+
+/*
+ * PHY DAC test register
+ */
+#define AR5K_PHY_DAC_TEST 0x9c28
+#define AR5K_PHY_DAC_TEST_I 0x00000001
+#define AR5K_PHY_DAC_TEST_Q 0x00000200
+
+/*
+ * PHY PTAT register (?)
+ */
+#define AR5K_PHY_PTAT 0x9c2c
+
+/*
+ * PHY Illegal TX rate register [5112+]
+ */
+#define AR5K_PHY_BAD_TX_RATE 0x9c30
+
+/*
+ * PHY SPUR Power register [5112+]
+ */
+#define AR5K_PHY_SPUR_PWR 0x9c34 /* Register Address */
+#define AR5K_PHY_SPUR_PWR_I 0x00000001 /* SPUR Power estimate for I (field) */
+#define AR5K_PHY_SPUR_PWR_Q 0x00000100 /* SPUR Power estimate for Q (field) */
+#define AR5K_PHY_SPUR_PWR_FILT 0x00010000 /* Power with SPUR removed (field) */
+
+/*
+ * PHY Channel status register [5112+] (?)
+ */
+#define AR5K_PHY_CHAN_STATUS 0x9c38
+#define AR5K_PHY_CHAN_STATUS_BT_ACT 0x00000001
+#define AR5K_PHY_CHAN_STATUS_RX_CLR_RAW 0x00000002
+#define AR5K_PHY_CHAN_STATUS_RX_CLR_MAC 0x00000004
+#define AR5K_PHY_CHAN_STATUS_RX_CLR_PAP 0x00000008
+
+/*
+ * Heavy clip enable register
+ */
+#define AR5K_PHY_HEAVY_CLIP_ENABLE 0x99e0
+
+/*
+ * PHY clock sleep registers [5112+]
+ */
+#define AR5K_PHY_SCLOCK 0x99f0
+#define AR5K_PHY_SCLOCK_32MHZ 0x0000000c
+#define AR5K_PHY_SDELAY 0x99f4
+#define AR5K_PHY_SDELAY_32MHZ 0x000000ff
+#define AR5K_PHY_SPENDING 0x99f8
+
+
+/*
+ * PHY PAPD I (power?) table (?)
+ * (92! entries)
+ */
+#define AR5K_PHY_PAPD_I_BASE 0xa000
+#define AR5K_PHY_PAPD_I(_n) (AR5K_PHY_PAPD_I_BASE + ((_n) << 2))
+
+/*
+ * PHY PCDAC TX power table
+ */
+#define AR5K_PHY_PCDAC_TXPOWER_BASE 0xa180
+#define AR5K_PHY_PCDAC_TXPOWER(_n) (AR5K_PHY_PCDAC_TXPOWER_BASE + ((_n) << 2))
+
+/*
+ * PHY mode register [5111+]
+ */
+#define AR5K_PHY_MODE 0x0a200 /* Register Address */
+#define AR5K_PHY_MODE_MOD 0x00000001 /* PHY Modulation bit */
+#define AR5K_PHY_MODE_MOD_OFDM 0
+#define AR5K_PHY_MODE_MOD_CCK 1
+#define AR5K_PHY_MODE_FREQ 0x00000002 /* Freq mode bit */
+#define AR5K_PHY_MODE_FREQ_5GHZ 0
+#define AR5K_PHY_MODE_FREQ_2GHZ 2
+#define AR5K_PHY_MODE_MOD_DYN 0x00000004 /* Enable Dynamic OFDM/CCK mode [5112+] */
+#define AR5K_PHY_MODE_RAD 0x00000008 /* [5212+] */
+#define AR5K_PHY_MODE_RAD_RF5111 0
+#define AR5K_PHY_MODE_RAD_RF5112 8
+#define AR5K_PHY_MODE_XR 0x00000010 /* Enable XR mode [5112+] */
+#define AR5K_PHY_MODE_HALF_RATE 0x00000020 /* Enable Half rate (test) */
+#define AR5K_PHY_MODE_QUARTER_RATE 0x00000040 /* Enable Quarter rat (test) */
+
+/*
+ * PHY CCK transmit control register [5111+ (?)]
+ */
+#define AR5K_PHY_CCKTXCTL 0xa204
+#define AR5K_PHY_CCKTXCTL_WORLD 0x00000000
+#define AR5K_PHY_CCKTXCTL_JAPAN 0x00000010
+#define AR5K_PHY_CCKTXCTL_SCRAMBLER_DIS 0x00000001
+#define AR5K_PHY_CCKTXCTK_DAC_SCALE 0x00000004
+
+/*
+ * PHY CCK Cross-correlator Barker RSSI threshold register [5212+]
+ */
+#define AR5K_PHY_CCK_CROSSCORR 0xa208
+#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000000f
+#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S 0
+
+/* Same address is used for antenna diversity activation */
+#define AR5K_PHY_FAST_ANT_DIV 0xa208
+#define AR5K_PHY_FAST_ANT_DIV_EN 0x00002000
+
+/*
+ * PHY 2GHz gain register [5111+]
+ */
+#define AR5K_PHY_GAIN_2GHZ 0xa20c
+#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000
+#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX_S 18
+#define AR5K_PHY_GAIN_2GHZ_INI_5111 0x6480416c
+
+#define AR5K_PHY_CCK_RX_CTL_4 0xa21c
+#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT 0x01f80000
+#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT_S 19
+
+#define AR5K_PHY_DAG_CCK_CTL 0xa228
+#define AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR 0x00000200
+#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR 0x0001fc00
+#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR_S 10
+
+#define AR5K_PHY_FAST_ADC 0xa24c
+
+#define AR5K_PHY_BLUETOOTH 0xa254
+
+/*
+ * Transmit Power Control register
+ * [2413+]
+ */
+#define AR5K_PHY_TPC_RG1 0xa258
+#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN 0x0000c000
+#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN_S 14
+#define AR5K_PHY_TPC_RG1_PDGAIN_1 0x00030000
+#define AR5K_PHY_TPC_RG1_PDGAIN_1_S 16
+#define AR5K_PHY_TPC_RG1_PDGAIN_2 0x000c0000
+#define AR5K_PHY_TPC_RG1_PDGAIN_2_S 18
+#define AR5K_PHY_TPC_RG1_PDGAIN_3 0x00300000
+#define AR5K_PHY_TPC_RG1_PDGAIN_3_S 20
+
+#define AR5K_PHY_TPC_RG5 0xa26C
+#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP 0x0000000F
+#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP_S 0
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1 0x000003F0
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1_S 4
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2 0x0000FC00
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2_S 10
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3 0x003F0000
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3_S 16
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4 0x0FC00000
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4_S 22
+
+/*
+ * PHY PDADC Tx power table
+ */
+#define AR5K_PHY_PDADC_TXPOWER_BASE 0xa280
+#define AR5K_PHY_PDADC_TXPOWER(_n) (AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2))
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/rfbuffer.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/rfbuffer.h
new file mode 100644
index 00000000..e50baff6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/rfbuffer.h
@@ -0,0 +1,1181 @@
+/*
+ * RF Buffer handling functions
+ *
+ * Copyright (c) 2009 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+
+/*
+ * There are some special registers on the RF chip
+ * that control various operation settings related mostly to
+ * the analog parts (channel, gain adjustment etc).
+ *
+ * We don't write on those registers directly but
+ * we send a data packet on the chip, using a special register,
+ * that holds all the settings we need. After we 've sent the
+ * data packet, we write on another special register to notify hw
+ * to apply the settings. This is done so that control registers
+ * can be dynamicaly programmed during operation and the settings
+ * are applied faster on the hw.
+ *
+ * We call each data packet an "RF Bank" and all the data we write
+ * (all RF Banks) "RF Buffer". This file holds initial RF Buffer
+ * data for the different RF chips, and various info to match RF
+ * Buffer offsets with specific RF registers so that we can access
+ * them. We tweak these settings on rfregs_init function.
+ *
+ * Also check out reg.h and U.S. Patent 6677779 B1 (about buffer
+ * registers and control registers):
+ *
+ * http://www.google.com/patents?id=qNURAAAAEBAJ
+ */
+
+
+/*
+ * Struct to hold default mode specific RF
+ * register values (RF Banks)
+ */
+struct ath5k_ini_rfbuffer {
+ u8 rfb_bank; /* RF Bank number */
+ u16 rfb_ctrl_register; /* RF Buffer control register */
+ u32 rfb_mode_data[5]; /* RF Buffer data for each mode */
+};
+
+/*
+ * Struct to hold RF Buffer field
+ * infos used to access certain RF
+ * analog registers
+ */
+struct ath5k_rfb_field {
+ u8 len; /* Field length */
+ u16 pos; /* Offset on the raw packet */
+ u8 col; /* Column -used for shifting */
+};
+
+/*
+ * RF analog register definition
+ */
+struct ath5k_rf_reg {
+ u8 bank; /* RF Buffer Bank number */
+ u8 index; /* Register's index on rf_regs_idx */
+ struct ath5k_rfb_field field; /* RF Buffer field for this register */
+};
+
+/* Map RF registers to indexes
+ * We do this to handle common bits and make our
+ * life easier by using an index for each register
+ * instead of a full rfb_field */
+enum ath5k_rf_regs_idx {
+ /* BANK 6 */
+ AR5K_RF_OB_2GHZ = 0,
+ AR5K_RF_OB_5GHZ,
+ AR5K_RF_DB_2GHZ,
+ AR5K_RF_DB_5GHZ,
+ AR5K_RF_FIXED_BIAS_A,
+ AR5K_RF_FIXED_BIAS_B,
+ AR5K_RF_PWD_XPD,
+ AR5K_RF_XPD_SEL,
+ AR5K_RF_XPD_GAIN,
+ AR5K_RF_PD_GAIN_LO,
+ AR5K_RF_PD_GAIN_HI,
+ AR5K_RF_HIGH_VC_CP,
+ AR5K_RF_MID_VC_CP,
+ AR5K_RF_LOW_VC_CP,
+ AR5K_RF_PUSH_UP,
+ AR5K_RF_PAD2GND,
+ AR5K_RF_XB2_LVL,
+ AR5K_RF_XB5_LVL,
+ AR5K_RF_PWD_ICLOBUF_2G,
+ AR5K_RF_PWD_84,
+ AR5K_RF_PWD_90,
+ AR5K_RF_PWD_130,
+ AR5K_RF_PWD_131,
+ AR5K_RF_PWD_132,
+ AR5K_RF_PWD_136,
+ AR5K_RF_PWD_137,
+ AR5K_RF_PWD_138,
+ AR5K_RF_PWD_166,
+ AR5K_RF_PWD_167,
+ AR5K_RF_DERBY_CHAN_SEL_MODE,
+ /* BANK 7 */
+ AR5K_RF_GAIN_I,
+ AR5K_RF_PLO_SEL,
+ AR5K_RF_RFGAIN_SEL,
+ AR5K_RF_RFGAIN_STEP,
+ AR5K_RF_WAIT_S,
+ AR5K_RF_WAIT_I,
+ AR5K_RF_MAX_TIME,
+ AR5K_RF_MIXVGA_OVR,
+ AR5K_RF_MIXGAIN_OVR,
+ AR5K_RF_MIXGAIN_STEP,
+ AR5K_RF_PD_DELAY_A,
+ AR5K_RF_PD_DELAY_B,
+ AR5K_RF_PD_DELAY_XR,
+ AR5K_RF_PD_PERIOD_A,
+ AR5K_RF_PD_PERIOD_B,
+ AR5K_RF_PD_PERIOD_XR,
+};
+
+
+/*******************\
+* RF5111 (Sombrero) *
+\*******************/
+
+/* BANK 6 len pos col */
+#define AR5K_RF5111_OB_2GHZ { 3, 119, 0 }
+#define AR5K_RF5111_DB_2GHZ { 3, 122, 0 }
+
+#define AR5K_RF5111_OB_5GHZ { 3, 104, 0 }
+#define AR5K_RF5111_DB_5GHZ { 3, 107, 0 }
+
+#define AR5K_RF5111_PWD_XPD { 1, 95, 0 }
+#define AR5K_RF5111_XPD_GAIN { 4, 96, 0 }
+
+/* Access to PWD registers */
+#define AR5K_RF5111_PWD(_n) { 1, (135 - _n), 3 }
+
+/* BANK 7 len pos col */
+#define AR5K_RF5111_GAIN_I { 6, 29, 0 }
+#define AR5K_RF5111_PLO_SEL { 1, 4, 0 }
+#define AR5K_RF5111_RFGAIN_SEL { 1, 36, 0 }
+#define AR5K_RF5111_RFGAIN_STEP { 6, 37, 0 }
+/* Only on AR5212 BaseBand and up */
+#define AR5K_RF5111_WAIT_S { 5, 19, 0 }
+#define AR5K_RF5111_WAIT_I { 5, 24, 0 }
+#define AR5K_RF5111_MAX_TIME { 2, 49, 0 }
+
+static const struct ath5k_rf_reg rf_regs_5111[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF5111_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF5111_DB_2GHZ},
+ {6, AR5K_RF_OB_5GHZ, AR5K_RF5111_OB_5GHZ},
+ {6, AR5K_RF_DB_5GHZ, AR5K_RF5111_DB_5GHZ},
+ {6, AR5K_RF_PWD_XPD, AR5K_RF5111_PWD_XPD},
+ {6, AR5K_RF_XPD_GAIN, AR5K_RF5111_XPD_GAIN},
+ {6, AR5K_RF_PWD_84, AR5K_RF5111_PWD(84)},
+ {6, AR5K_RF_PWD_90, AR5K_RF5111_PWD(90)},
+ {7, AR5K_RF_GAIN_I, AR5K_RF5111_GAIN_I},
+ {7, AR5K_RF_PLO_SEL, AR5K_RF5111_PLO_SEL},
+ {7, AR5K_RF_RFGAIN_SEL, AR5K_RF5111_RFGAIN_SEL},
+ {7, AR5K_RF_RFGAIN_STEP, AR5K_RF5111_RFGAIN_STEP},
+ {7, AR5K_RF_WAIT_S, AR5K_RF5111_WAIT_S},
+ {7, AR5K_RF_WAIT_I, AR5K_RF5111_WAIT_I},
+ {7, AR5K_RF_MAX_TIME, AR5K_RF5111_MAX_TIME}
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_5111[] = {
+ { 0, 0x989c,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } },
+ { 0, 0x989c,
+ { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } },
+ { 0, 0x98d4,
+ { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } },
+ { 1, 0x98d4,
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d4,
+ { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } },
+ { 3, 0x98d8,
+ { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
+ { 6, 0x989c,
+ { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } },
+ { 6, 0x989c,
+ { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } },
+ { 6, 0x989c,
+ { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } },
+ { 6, 0x989c,
+ { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } },
+ { 6, 0x989c,
+ { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } },
+ { 6, 0x98d4,
+ { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } },
+ { 7, 0x989c,
+ { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } },
+ { 7, 0x989c,
+ { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } },
+ { 7, 0x989c,
+ { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
+ { 7, 0x989c,
+ { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } },
+ { 7, 0x989c,
+ { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } },
+ { 7, 0x989c,
+ { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } },
+ { 7, 0x989c,
+ { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } },
+};
+
+
+
+/***********************\
+* RF5112/RF2112 (Derby) *
+\***********************/
+
+/* BANK 7 (Common) len pos col */
+#define AR5K_RF5112X_GAIN_I { 6, 14, 0 }
+#define AR5K_RF5112X_MIXVGA_OVR { 1, 36, 0 }
+#define AR5K_RF5112X_MIXGAIN_OVR { 2, 37, 0 }
+#define AR5K_RF5112X_MIXGAIN_STEP { 4, 32, 0 }
+#define AR5K_RF5112X_PD_DELAY_A { 4, 58, 0 }
+#define AR5K_RF5112X_PD_DELAY_B { 4, 62, 0 }
+#define AR5K_RF5112X_PD_DELAY_XR { 4, 66, 0 }
+#define AR5K_RF5112X_PD_PERIOD_A { 4, 70, 0 }
+#define AR5K_RF5112X_PD_PERIOD_B { 4, 74, 0 }
+#define AR5K_RF5112X_PD_PERIOD_XR { 4, 78, 0 }
+
+/* RFX112 (Derby 1) */
+
+/* BANK 6 len pos col */
+#define AR5K_RF5112_OB_2GHZ { 3, 269, 0 }
+#define AR5K_RF5112_DB_2GHZ { 3, 272, 0 }
+
+#define AR5K_RF5112_OB_5GHZ { 3, 261, 0 }
+#define AR5K_RF5112_DB_5GHZ { 3, 264, 0 }
+
+#define AR5K_RF5112_FIXED_BIAS_A { 1, 260, 0 }
+#define AR5K_RF5112_FIXED_BIAS_B { 1, 259, 0 }
+
+#define AR5K_RF5112_XPD_SEL { 1, 284, 0 }
+#define AR5K_RF5112_XPD_GAIN { 2, 252, 0 }
+
+/* Access to PWD registers */
+#define AR5K_RF5112_PWD(_n) { 1, (302 - _n), 3 }
+
+static const struct ath5k_rf_reg rf_regs_5112[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF5112_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF5112_DB_2GHZ},
+ {6, AR5K_RF_OB_5GHZ, AR5K_RF5112_OB_5GHZ},
+ {6, AR5K_RF_DB_5GHZ, AR5K_RF5112_DB_5GHZ},
+ {6, AR5K_RF_FIXED_BIAS_A, AR5K_RF5112_FIXED_BIAS_A},
+ {6, AR5K_RF_FIXED_BIAS_B, AR5K_RF5112_FIXED_BIAS_B},
+ {6, AR5K_RF_XPD_SEL, AR5K_RF5112_XPD_SEL},
+ {6, AR5K_RF_XPD_GAIN, AR5K_RF5112_XPD_GAIN},
+ {6, AR5K_RF_PWD_130, AR5K_RF5112_PWD(130)},
+ {6, AR5K_RF_PWD_131, AR5K_RF5112_PWD(131)},
+ {6, AR5K_RF_PWD_132, AR5K_RF5112_PWD(132)},
+ {6, AR5K_RF_PWD_136, AR5K_RF5112_PWD(136)},
+ {6, AR5K_RF_PWD_137, AR5K_RF5112_PWD(137)},
+ {6, AR5K_RF_PWD_138, AR5K_RF5112_PWD(138)},
+ {7, AR5K_RF_GAIN_I, AR5K_RF5112X_GAIN_I},
+ {7, AR5K_RF_MIXVGA_OVR, AR5K_RF5112X_MIXVGA_OVR},
+ {7, AR5K_RF_MIXGAIN_OVR, AR5K_RF5112X_MIXGAIN_OVR},
+ {7, AR5K_RF_MIXGAIN_STEP, AR5K_RF5112X_MIXGAIN_STEP},
+ {7, AR5K_RF_PD_DELAY_A, AR5K_RF5112X_PD_DELAY_A},
+ {7, AR5K_RF_PD_DELAY_B, AR5K_RF5112X_PD_DELAY_B},
+ {7, AR5K_RF_PD_DELAY_XR, AR5K_RF5112X_PD_DELAY_XR},
+ {7, AR5K_RF_PD_PERIOD_A, AR5K_RF5112X_PD_PERIOD_A},
+ {7, AR5K_RF_PD_PERIOD_B, AR5K_RF5112X_PD_PERIOD_B},
+ {7, AR5K_RF_PD_PERIOD_XR, AR5K_RF5112X_PD_PERIOD_XR},
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_5112[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
+ { 3, 0x98dc,
+ { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } },
+ { 6, 0x989c,
+ { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } },
+ { 6, 0x989c,
+ { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } },
+ { 6, 0x989c,
+ { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } },
+ { 6, 0x989c,
+ { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } },
+ { 6, 0x989c,
+ { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
+ { 6, 0x989c,
+ { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
+ { 6, 0x989c,
+ { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } },
+ { 6, 0x989c,
+ { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } },
+ { 6, 0x989c,
+ { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
+ { 6, 0x989c,
+ { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
+ { 6, 0x989c,
+ { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } },
+ { 6, 0x989c,
+ { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } },
+ { 6, 0x989c,
+ { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
+ { 6, 0x989c,
+ { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } },
+ { 6, 0x989c,
+ { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
+ { 6, 0x989c,
+ { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
+ { 6, 0x989c,
+ { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } },
+ { 6, 0x989c,
+ { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } },
+ { 6, 0x989c,
+ { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
+ { 6, 0x989c,
+ { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } },
+ { 6, 0x989c,
+ { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } },
+ { 6, 0x989c,
+ { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } },
+ { 6, 0x989c,
+ { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } },
+ { 6, 0x989c,
+ { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } },
+ { 6, 0x989c,
+ { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } },
+ { 6, 0x989c,
+ { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } },
+ { 6, 0x989c,
+ { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } },
+ { 6, 0x989c,
+ { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } },
+ { 6, 0x989c,
+ { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } },
+ { 6, 0x98d0,
+ { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } },
+ { 7, 0x989c,
+ { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
+ { 7, 0x989c,
+ { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
+ { 7, 0x989c,
+ { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } },
+ { 7, 0x989c,
+ { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
+ { 7, 0x989c,
+ { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } },
+ { 7, 0x989c,
+ { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
+ { 7, 0x989c,
+ { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
+ { 7, 0x989c,
+ { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } },
+ { 7, 0x989c,
+ { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } },
+ { 7, 0x989c,
+ { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
+ { 7, 0x989c,
+ { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
+ { 7, 0x989c,
+ { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
+ { 7, 0x98c4,
+ { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+};
+
+/* RFX112A (Derby 2) */
+
+/* BANK 6 len pos col */
+#define AR5K_RF5112A_OB_2GHZ { 3, 287, 0 }
+#define AR5K_RF5112A_DB_2GHZ { 3, 290, 0 }
+
+#define AR5K_RF5112A_OB_5GHZ { 3, 279, 0 }
+#define AR5K_RF5112A_DB_5GHZ { 3, 282, 0 }
+
+#define AR5K_RF5112A_FIXED_BIAS_A { 1, 278, 0 }
+#define AR5K_RF5112A_FIXED_BIAS_B { 1, 277, 0 }
+
+#define AR5K_RF5112A_XPD_SEL { 1, 302, 0 }
+#define AR5K_RF5112A_PDGAINLO { 2, 270, 0 }
+#define AR5K_RF5112A_PDGAINHI { 2, 257, 0 }
+
+/* Access to PWD registers */
+#define AR5K_RF5112A_PWD(_n) { 1, (306 - _n), 3 }
+
+/* Voltage regulators */
+#define AR5K_RF5112A_HIGH_VC_CP { 2, 90, 2 }
+#define AR5K_RF5112A_MID_VC_CP { 2, 92, 2 }
+#define AR5K_RF5112A_LOW_VC_CP { 2, 94, 2 }
+#define AR5K_RF5112A_PUSH_UP { 1, 254, 2 }
+
+/* Power consumption */
+#define AR5K_RF5112A_PAD2GND { 1, 281, 1 }
+#define AR5K_RF5112A_XB2_LVL { 2, 1, 3 }
+#define AR5K_RF5112A_XB5_LVL { 2, 3, 3 }
+
+static const struct ath5k_rf_reg rf_regs_5112a[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF5112A_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF5112A_DB_2GHZ},
+ {6, AR5K_RF_OB_5GHZ, AR5K_RF5112A_OB_5GHZ},
+ {6, AR5K_RF_DB_5GHZ, AR5K_RF5112A_DB_5GHZ},
+ {6, AR5K_RF_FIXED_BIAS_A, AR5K_RF5112A_FIXED_BIAS_A},
+ {6, AR5K_RF_FIXED_BIAS_B, AR5K_RF5112A_FIXED_BIAS_B},
+ {6, AR5K_RF_XPD_SEL, AR5K_RF5112A_XPD_SEL},
+ {6, AR5K_RF_PD_GAIN_LO, AR5K_RF5112A_PDGAINLO},
+ {6, AR5K_RF_PD_GAIN_HI, AR5K_RF5112A_PDGAINHI},
+ {6, AR5K_RF_PWD_130, AR5K_RF5112A_PWD(130)},
+ {6, AR5K_RF_PWD_131, AR5K_RF5112A_PWD(131)},
+ {6, AR5K_RF_PWD_132, AR5K_RF5112A_PWD(132)},
+ {6, AR5K_RF_PWD_136, AR5K_RF5112A_PWD(136)},
+ {6, AR5K_RF_PWD_137, AR5K_RF5112A_PWD(137)},
+ {6, AR5K_RF_PWD_138, AR5K_RF5112A_PWD(138)},
+ {6, AR5K_RF_PWD_166, AR5K_RF5112A_PWD(166)},
+ {6, AR5K_RF_PWD_167, AR5K_RF5112A_PWD(167)},
+ {6, AR5K_RF_HIGH_VC_CP, AR5K_RF5112A_HIGH_VC_CP},
+ {6, AR5K_RF_MID_VC_CP, AR5K_RF5112A_MID_VC_CP},
+ {6, AR5K_RF_LOW_VC_CP, AR5K_RF5112A_LOW_VC_CP},
+ {6, AR5K_RF_PUSH_UP, AR5K_RF5112A_PUSH_UP},
+ {6, AR5K_RF_PAD2GND, AR5K_RF5112A_PAD2GND},
+ {6, AR5K_RF_XB2_LVL, AR5K_RF5112A_XB2_LVL},
+ {6, AR5K_RF_XB5_LVL, AR5K_RF5112A_XB5_LVL},
+ {7, AR5K_RF_GAIN_I, AR5K_RF5112X_GAIN_I},
+ {7, AR5K_RF_MIXVGA_OVR, AR5K_RF5112X_MIXVGA_OVR},
+ {7, AR5K_RF_MIXGAIN_OVR, AR5K_RF5112X_MIXGAIN_OVR},
+ {7, AR5K_RF_MIXGAIN_STEP, AR5K_RF5112X_MIXGAIN_STEP},
+ {7, AR5K_RF_PD_DELAY_A, AR5K_RF5112X_PD_DELAY_A},
+ {7, AR5K_RF_PD_DELAY_B, AR5K_RF5112X_PD_DELAY_B},
+ {7, AR5K_RF_PD_DELAY_XR, AR5K_RF5112X_PD_DELAY_XR},
+ {7, AR5K_RF_PD_PERIOD_A, AR5K_RF5112X_PD_PERIOD_A},
+ {7, AR5K_RF_PD_PERIOD_B, AR5K_RF5112X_PD_PERIOD_B},
+ {7, AR5K_RF_PD_PERIOD_XR, AR5K_RF5112X_PD_PERIOD_XR},
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_5112a[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
+ { 3, 0x98dc,
+ { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c,
+ { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } },
+ { 6, 0x989c,
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c,
+ { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } },
+ { 6, 0x989c,
+ { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } },
+ { 6, 0x989c,
+ { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } },
+ { 6, 0x989c,
+ { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } },
+ { 6, 0x989c,
+ { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } },
+ { 6, 0x989c,
+ { 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 } },
+ { 6, 0x989c,
+ { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } },
+ { 6, 0x989c,
+ { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
+ { 6, 0x989c,
+ { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } },
+ { 6, 0x989c,
+ { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
+ { 6, 0x989c,
+ { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } },
+ { 6, 0x989c,
+ { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } },
+ { 6, 0x989c,
+ { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } },
+ { 6, 0x989c,
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c,
+ { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
+ { 6, 0x989c,
+ { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } },
+ { 6, 0x989c,
+ { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } },
+ { 6, 0x989c,
+ { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
+ { 6, 0x989c,
+ { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } },
+ { 6, 0x989c,
+ { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } },
+ { 6, 0x989c,
+ { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } },
+ { 6, 0x989c,
+ { 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 } },
+ { 6, 0x989c,
+ { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } },
+ { 6, 0x989c,
+ { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } },
+ { 6, 0x989c,
+ { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } },
+ { 6, 0x989c,
+ { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } },
+ { 6, 0x989c,
+ { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } },
+ { 6, 0x98d8,
+ { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } },
+ { 7, 0x989c,
+ { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
+ { 7, 0x989c,
+ { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
+ { 7, 0x989c,
+ { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } },
+ { 7, 0x989c,
+ { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
+ { 7, 0x989c,
+ { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } },
+ { 7, 0x989c,
+ { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
+ { 7, 0x989c,
+ { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
+ { 7, 0x989c,
+ { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } },
+ { 7, 0x989c,
+ { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } },
+ { 7, 0x989c,
+ { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
+ { 7, 0x989c,
+ { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
+ { 7, 0x989c,
+ { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
+ { 7, 0x98c4,
+ { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+};
+
+
+
+/******************\
+* RF2413 (Griffin) *
+\******************/
+
+/* BANK 6 len pos col */
+#define AR5K_RF2413_OB_2GHZ { 3, 168, 0 }
+#define AR5K_RF2413_DB_2GHZ { 3, 165, 0 }
+
+static const struct ath5k_rf_reg rf_regs_2413[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF2413_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF2413_DB_2GHZ},
+};
+
+/* Default mode specific settings
+ * XXX: a/aTurbo ???
+ */
+static const struct ath5k_ini_rfbuffer rfb_2413[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
+ { 3, 0x98dc,
+ { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c,
+ { 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 } },
+ { 6, 0x989c,
+ { 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 } },
+ { 6, 0x989c,
+ { 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 } },
+ { 6, 0x989c,
+ { 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 } },
+ { 6, 0x989c,
+ { 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 } },
+ { 6, 0x989c,
+ { 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 } },
+ { 6, 0x989c,
+ { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } },
+ { 6, 0x989c,
+ { 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 } },
+ { 6, 0x989c,
+ { 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 } },
+ { 6, 0x989c,
+ { 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 } },
+ { 6, 0x989c,
+ { 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 } },
+ { 6, 0x989c,
+ { 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f } },
+ { 6, 0x989c,
+ { 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 } },
+ { 6, 0x98d8,
+ { 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 } },
+ { 7, 0x989c,
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c,
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+
+
+/***************************\
+* RF2315/RF2316 (Cobra SoC) *
+\***************************/
+
+/* BANK 6 len pos col */
+#define AR5K_RF2316_OB_2GHZ { 3, 178, 0 }
+#define AR5K_RF2316_DB_2GHZ { 3, 175, 0 }
+
+static const struct ath5k_rf_reg rf_regs_2316[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF2316_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF2316_DB_2GHZ},
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_2316[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
+ { 3, 0x98dc,
+ { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 } },
+ { 6, 0x989c,
+ { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
+ { 6, 0x989c,
+ { 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 } },
+ { 6, 0x989c,
+ { 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 } },
+ { 6, 0x989c,
+ { 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 } },
+ { 6, 0x989c,
+ { 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 } },
+ { 6, 0x989c,
+ { 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 } },
+ { 6, 0x989c,
+ { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
+ { 6, 0x989c,
+ { 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 } },
+ { 6, 0x989c,
+ { 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 } },
+ { 6, 0x989c,
+ { 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 } },
+ { 6, 0x989c,
+ { 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 } },
+ { 6, 0x989c,
+ { 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d } },
+ { 6, 0x989c,
+ { 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 } },
+ { 6, 0x989c,
+ { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
+ { 6, 0x989c,
+ { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
+ { 6, 0x989c,
+ { 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 } },
+ { 6, 0x989c,
+ { 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 } },
+ { 6, 0x98c0,
+ { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
+ { 7, 0x989c,
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c,
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+
+
+/******************************\
+* RF5413/RF5424 (Eagle/Condor) *
+\******************************/
+
+/* BANK 6 len pos col */
+#define AR5K_RF5413_OB_2GHZ { 3, 241, 0 }
+#define AR5K_RF5413_DB_2GHZ { 3, 238, 0 }
+
+#define AR5K_RF5413_OB_5GHZ { 3, 247, 0 }
+#define AR5K_RF5413_DB_5GHZ { 3, 244, 0 }
+
+#define AR5K_RF5413_PWD_ICLOBUF2G { 3, 131, 3 }
+#define AR5K_RF5413_DERBY_CHAN_SEL_MODE { 1, 291, 2 }
+
+static const struct ath5k_rf_reg rf_regs_5413[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF5413_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF5413_DB_2GHZ},
+ {6, AR5K_RF_OB_5GHZ, AR5K_RF5413_OB_5GHZ},
+ {6, AR5K_RF_DB_5GHZ, AR5K_RF5413_DB_5GHZ},
+ {6, AR5K_RF_PWD_ICLOBUF_2G, AR5K_RF5413_PWD_ICLOBUF2G},
+ {6, AR5K_RF_DERBY_CHAN_SEL_MODE, AR5K_RF5413_DERBY_CHAN_SEL_MODE},
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_5413[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
+ { 3, 0x98dc,
+ { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } },
+ { 6, 0x989c,
+ { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } },
+ { 6, 0x989c,
+ { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } },
+ { 6, 0x989c,
+ { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } },
+ { 6, 0x989c,
+ { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
+ { 6, 0x989c,
+ { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
+ { 6, 0x989c,
+ { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } },
+ { 6, 0x989c,
+ { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } },
+ { 6, 0x989c,
+ { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } },
+ { 6, 0x989c,
+ { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } },
+ { 6, 0x989c,
+ { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } },
+ { 6, 0x989c,
+ { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } },
+ { 6, 0x989c,
+ { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
+ { 6, 0x989c,
+ { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } },
+ { 6, 0x989c,
+ { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
+ { 6, 0x989c,
+ { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } },
+ { 6, 0x989c,
+ { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } },
+ { 6, 0x989c,
+ { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } },
+ { 6, 0x989c,
+ { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } },
+ { 6, 0x989c,
+ { 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 } },
+ { 6, 0x989c,
+ { 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } },
+ { 6, 0x989c,
+ { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 } },
+ { 6, 0x98c8,
+ { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } },
+ { 7, 0x989c,
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c,
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+
+
+/***************************\
+* RF2425/RF2417 (Swan/Nala) *
+* AR2317 (Spider SoC) *
+\***************************/
+
+/* BANK 6 len pos col */
+#define AR5K_RF2425_OB_2GHZ { 3, 193, 0 }
+#define AR5K_RF2425_DB_2GHZ { 3, 190, 0 }
+
+static const struct ath5k_rf_reg rf_regs_2425[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF2425_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF2425_DB_2GHZ},
+};
+
+/* Default mode specific settings
+ * XXX: a/aTurbo ?
+ */
+static const struct ath5k_ini_rfbuffer rfb_2425[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
+ { 3, 0x98dc,
+ { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c,
+ { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
+ { 6, 0x989c,
+ { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
+ { 6, 0x989c,
+ { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
+ { 6, 0x989c,
+ { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
+ { 6, 0x989c,
+ { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
+ { 6, 0x989c,
+ { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
+ { 6, 0x989c,
+ { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
+ { 6, 0x989c,
+ { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
+ { 6, 0x989c,
+ { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
+ { 6, 0x989c,
+ { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
+ { 6, 0x989c,
+ { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
+ { 6, 0x989c,
+ { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
+ { 6, 0x98c4,
+ { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
+ { 7, 0x989c,
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c,
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+/*
+ * TODO: Handle the few differences with swan during
+ * bank modification and get rid of this
+ */
+static const struct ath5k_ini_rfbuffer rfb_2317[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
+ { 3, 0x98dc,
+ { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c,
+ { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
+ { 6, 0x989c,
+ { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
+ { 6, 0x989c,
+ { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
+ { 6, 0x989c,
+ { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
+ { 6, 0x989c,
+ { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
+ { 6, 0x989c,
+ { 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 } },
+ { 6, 0x989c,
+ { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
+ { 6, 0x989c,
+ { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
+ { 6, 0x989c,
+ { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
+ { 6, 0x989c,
+ { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
+ { 6, 0x989c,
+ { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
+ { 6, 0x989c,
+ { 0x00009688, 0x00009688, 0x00009688, 0x00009688, 0x00009688 } },
+ { 6, 0x98c4,
+ { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
+ { 7, 0x989c,
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c,
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+/*
+ * TODO: Handle the few differences with swan during
+ * bank modification and get rid of this
+ * XXX: a/aTurbo ?
+ */
+static const struct ath5k_ini_rfbuffer rfb_2417[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
+ { 3, 0x98dc,
+ { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c,
+ { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
+ { 6, 0x989c,
+ { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
+ { 6, 0x989c,
+ { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
+ { 6, 0x989c,
+ { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
+ { 6, 0x989c,
+ { 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 } },
+ { 6, 0x989c,
+ { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
+ { 6, 0x989c,
+ { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
+ { 6, 0x989c,
+ { 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a } },
+ { 6, 0x989c,
+ { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
+ { 6, 0x989c,
+ { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
+ { 6, 0x989c,
+ { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
+ { 6, 0x989c,
+ { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
+ { 6, 0x98c4,
+ { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
+ { 7, 0x989c,
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c,
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/rfgain.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/rfgain.h
new file mode 100644
index 00000000..1354d8c3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath5k/rfgain.h
@@ -0,0 +1,516 @@
+/*
+ * RF Gain optimization
+ *
+ * Copyright (c) 2004-2009 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Mode-specific RF Gain table (64bytes) for RF5111/5112
+ * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial
+ * RF Gain values are included in AR5K_AR5210_INI)
+ */
+struct ath5k_ini_rfgain {
+ u16 rfg_register; /* RF Gain register address */
+ u32 rfg_value[2]; /* [freq (see below)] */
+};
+
+/* Initial RF Gain settings for RF5111 */
+static const struct ath5k_ini_rfgain rfgain_5111[] = {
+ /* 5Ghz 2Ghz */
+ { AR5K_RF_GAIN(0), { 0x000001a9, 0x00000000 } },
+ { AR5K_RF_GAIN(1), { 0x000001e9, 0x00000040 } },
+ { AR5K_RF_GAIN(2), { 0x00000029, 0x00000080 } },
+ { AR5K_RF_GAIN(3), { 0x00000069, 0x00000150 } },
+ { AR5K_RF_GAIN(4), { 0x00000199, 0x00000190 } },
+ { AR5K_RF_GAIN(5), { 0x000001d9, 0x000001d0 } },
+ { AR5K_RF_GAIN(6), { 0x00000019, 0x00000010 } },
+ { AR5K_RF_GAIN(7), { 0x00000059, 0x00000044 } },
+ { AR5K_RF_GAIN(8), { 0x00000099, 0x00000084 } },
+ { AR5K_RF_GAIN(9), { 0x000001a5, 0x00000148 } },
+ { AR5K_RF_GAIN(10), { 0x000001e5, 0x00000188 } },
+ { AR5K_RF_GAIN(11), { 0x00000025, 0x000001c8 } },
+ { AR5K_RF_GAIN(12), { 0x000001c8, 0x00000014 } },
+ { AR5K_RF_GAIN(13), { 0x00000008, 0x00000042 } },
+ { AR5K_RF_GAIN(14), { 0x00000048, 0x00000082 } },
+ { AR5K_RF_GAIN(15), { 0x00000088, 0x00000178 } },
+ { AR5K_RF_GAIN(16), { 0x00000198, 0x000001b8 } },
+ { AR5K_RF_GAIN(17), { 0x000001d8, 0x000001f8 } },
+ { AR5K_RF_GAIN(18), { 0x00000018, 0x00000012 } },
+ { AR5K_RF_GAIN(19), { 0x00000058, 0x00000052 } },
+ { AR5K_RF_GAIN(20), { 0x00000098, 0x00000092 } },
+ { AR5K_RF_GAIN(21), { 0x000001a4, 0x0000017c } },
+ { AR5K_RF_GAIN(22), { 0x000001e4, 0x000001bc } },
+ { AR5K_RF_GAIN(23), { 0x00000024, 0x000001fc } },
+ { AR5K_RF_GAIN(24), { 0x00000064, 0x0000000a } },
+ { AR5K_RF_GAIN(25), { 0x000000a4, 0x0000004a } },
+ { AR5K_RF_GAIN(26), { 0x000000e4, 0x0000008a } },
+ { AR5K_RF_GAIN(27), { 0x0000010a, 0x0000015a } },
+ { AR5K_RF_GAIN(28), { 0x0000014a, 0x0000019a } },
+ { AR5K_RF_GAIN(29), { 0x0000018a, 0x000001da } },
+ { AR5K_RF_GAIN(30), { 0x000001ca, 0x0000000e } },
+ { AR5K_RF_GAIN(31), { 0x0000000a, 0x0000004e } },
+ { AR5K_RF_GAIN(32), { 0x0000004a, 0x0000008e } },
+ { AR5K_RF_GAIN(33), { 0x0000008a, 0x0000015e } },
+ { AR5K_RF_GAIN(34), { 0x000001ba, 0x0000019e } },
+ { AR5K_RF_GAIN(35), { 0x000001fa, 0x000001de } },
+ { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000009 } },
+ { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000049 } },
+ { AR5K_RF_GAIN(38), { 0x00000186, 0x00000089 } },
+ { AR5K_RF_GAIN(39), { 0x000001c6, 0x00000179 } },
+ { AR5K_RF_GAIN(40), { 0x00000006, 0x000001b9 } },
+ { AR5K_RF_GAIN(41), { 0x00000046, 0x000001f9 } },
+ { AR5K_RF_GAIN(42), { 0x00000086, 0x00000039 } },
+ { AR5K_RF_GAIN(43), { 0x000000c6, 0x00000079 } },
+ { AR5K_RF_GAIN(44), { 0x000000c6, 0x000000b9 } },
+ { AR5K_RF_GAIN(45), { 0x000000c6, 0x000001bd } },
+ { AR5K_RF_GAIN(46), { 0x000000c6, 0x000001fd } },
+ { AR5K_RF_GAIN(47), { 0x000000c6, 0x0000003d } },
+ { AR5K_RF_GAIN(48), { 0x000000c6, 0x0000007d } },
+ { AR5K_RF_GAIN(49), { 0x000000c6, 0x000000bd } },
+ { AR5K_RF_GAIN(50), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(51), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(52), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(53), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(54), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(55), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(56), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(57), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(58), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(59), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(60), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(61), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(62), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(63), { 0x000000c6, 0x000000fd } },
+};
+
+/* Initial RF Gain settings for RF5112 */
+static const struct ath5k_ini_rfgain rfgain_5112[] = {
+ /* 5Ghz 2Ghz */
+ { AR5K_RF_GAIN(0), { 0x00000007, 0x00000007 } },
+ { AR5K_RF_GAIN(1), { 0x00000047, 0x00000047 } },
+ { AR5K_RF_GAIN(2), { 0x00000087, 0x00000087 } },
+ { AR5K_RF_GAIN(3), { 0x000001a0, 0x000001a0 } },
+ { AR5K_RF_GAIN(4), { 0x000001e0, 0x000001e0 } },
+ { AR5K_RF_GAIN(5), { 0x00000020, 0x00000020 } },
+ { AR5K_RF_GAIN(6), { 0x00000060, 0x00000060 } },
+ { AR5K_RF_GAIN(7), { 0x000001a1, 0x000001a1 } },
+ { AR5K_RF_GAIN(8), { 0x000001e1, 0x000001e1 } },
+ { AR5K_RF_GAIN(9), { 0x00000021, 0x00000021 } },
+ { AR5K_RF_GAIN(10), { 0x00000061, 0x00000061 } },
+ { AR5K_RF_GAIN(11), { 0x00000162, 0x00000162 } },
+ { AR5K_RF_GAIN(12), { 0x000001a2, 0x000001a2 } },
+ { AR5K_RF_GAIN(13), { 0x000001e2, 0x000001e2 } },
+ { AR5K_RF_GAIN(14), { 0x00000022, 0x00000022 } },
+ { AR5K_RF_GAIN(15), { 0x00000062, 0x00000062 } },
+ { AR5K_RF_GAIN(16), { 0x00000163, 0x00000163 } },
+ { AR5K_RF_GAIN(17), { 0x000001a3, 0x000001a3 } },
+ { AR5K_RF_GAIN(18), { 0x000001e3, 0x000001e3 } },
+ { AR5K_RF_GAIN(19), { 0x00000023, 0x00000023 } },
+ { AR5K_RF_GAIN(20), { 0x00000063, 0x00000063 } },
+ { AR5K_RF_GAIN(21), { 0x00000184, 0x00000184 } },
+ { AR5K_RF_GAIN(22), { 0x000001c4, 0x000001c4 } },
+ { AR5K_RF_GAIN(23), { 0x00000004, 0x00000004 } },
+ { AR5K_RF_GAIN(24), { 0x000001ea, 0x0000000b } },
+ { AR5K_RF_GAIN(25), { 0x0000002a, 0x0000004b } },
+ { AR5K_RF_GAIN(26), { 0x0000006a, 0x0000008b } },
+ { AR5K_RF_GAIN(27), { 0x000000aa, 0x000001ac } },
+ { AR5K_RF_GAIN(28), { 0x000001ab, 0x000001ec } },
+ { AR5K_RF_GAIN(29), { 0x000001eb, 0x0000002c } },
+ { AR5K_RF_GAIN(30), { 0x0000002b, 0x00000012 } },
+ { AR5K_RF_GAIN(31), { 0x0000006b, 0x00000052 } },
+ { AR5K_RF_GAIN(32), { 0x000000ab, 0x00000092 } },
+ { AR5K_RF_GAIN(33), { 0x000001ac, 0x00000193 } },
+ { AR5K_RF_GAIN(34), { 0x000001ec, 0x000001d3 } },
+ { AR5K_RF_GAIN(35), { 0x0000002c, 0x00000013 } },
+ { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000053 } },
+ { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000093 } },
+ { AR5K_RF_GAIN(38), { 0x000000ba, 0x00000194 } },
+ { AR5K_RF_GAIN(39), { 0x000001bb, 0x000001d4 } },
+ { AR5K_RF_GAIN(40), { 0x000001fb, 0x00000014 } },
+ { AR5K_RF_GAIN(41), { 0x0000003b, 0x0000003a } },
+ { AR5K_RF_GAIN(42), { 0x0000007b, 0x0000007a } },
+ { AR5K_RF_GAIN(43), { 0x000000bb, 0x000000ba } },
+ { AR5K_RF_GAIN(44), { 0x000001bc, 0x000001bb } },
+ { AR5K_RF_GAIN(45), { 0x000001fc, 0x000001fb } },
+ { AR5K_RF_GAIN(46), { 0x0000003c, 0x0000003b } },
+ { AR5K_RF_GAIN(47), { 0x0000007c, 0x0000007b } },
+ { AR5K_RF_GAIN(48), { 0x000000bc, 0x000000bb } },
+ { AR5K_RF_GAIN(49), { 0x000000fc, 0x000001bc } },
+ { AR5K_RF_GAIN(50), { 0x000000fc, 0x000001fc } },
+ { AR5K_RF_GAIN(51), { 0x000000fc, 0x0000003c } },
+ { AR5K_RF_GAIN(52), { 0x000000fc, 0x0000007c } },
+ { AR5K_RF_GAIN(53), { 0x000000fc, 0x000000bc } },
+ { AR5K_RF_GAIN(54), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(55), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(56), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(57), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(58), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(59), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(60), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(61), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(62), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(63), { 0x000000fc, 0x000000fc } },
+};
+
+/* Initial RF Gain settings for RF2413 */
+static const struct ath5k_ini_rfgain rfgain_2413[] = {
+ { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
+ { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } },
+ { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } },
+ { AR5K_RF_GAIN(3), { 0x00000000, 0x00000181 } },
+ { AR5K_RF_GAIN(4), { 0x00000000, 0x000001c1 } },
+ { AR5K_RF_GAIN(5), { 0x00000000, 0x00000001 } },
+ { AR5K_RF_GAIN(6), { 0x00000000, 0x00000041 } },
+ { AR5K_RF_GAIN(7), { 0x00000000, 0x00000081 } },
+ { AR5K_RF_GAIN(8), { 0x00000000, 0x00000168 } },
+ { AR5K_RF_GAIN(9), { 0x00000000, 0x000001a8 } },
+ { AR5K_RF_GAIN(10), { 0x00000000, 0x000001e8 } },
+ { AR5K_RF_GAIN(11), { 0x00000000, 0x00000028 } },
+ { AR5K_RF_GAIN(12), { 0x00000000, 0x00000068 } },
+ { AR5K_RF_GAIN(13), { 0x00000000, 0x00000189 } },
+ { AR5K_RF_GAIN(14), { 0x00000000, 0x000001c9 } },
+ { AR5K_RF_GAIN(15), { 0x00000000, 0x00000009 } },
+ { AR5K_RF_GAIN(16), { 0x00000000, 0x00000049 } },
+ { AR5K_RF_GAIN(17), { 0x00000000, 0x00000089 } },
+ { AR5K_RF_GAIN(18), { 0x00000000, 0x00000190 } },
+ { AR5K_RF_GAIN(19), { 0x00000000, 0x000001d0 } },
+ { AR5K_RF_GAIN(20), { 0x00000000, 0x00000010 } },
+ { AR5K_RF_GAIN(21), { 0x00000000, 0x00000050 } },
+ { AR5K_RF_GAIN(22), { 0x00000000, 0x00000090 } },
+ { AR5K_RF_GAIN(23), { 0x00000000, 0x00000191 } },
+ { AR5K_RF_GAIN(24), { 0x00000000, 0x000001d1 } },
+ { AR5K_RF_GAIN(25), { 0x00000000, 0x00000011 } },
+ { AR5K_RF_GAIN(26), { 0x00000000, 0x00000051 } },
+ { AR5K_RF_GAIN(27), { 0x00000000, 0x00000091 } },
+ { AR5K_RF_GAIN(28), { 0x00000000, 0x00000178 } },
+ { AR5K_RF_GAIN(29), { 0x00000000, 0x000001b8 } },
+ { AR5K_RF_GAIN(30), { 0x00000000, 0x000001f8 } },
+ { AR5K_RF_GAIN(31), { 0x00000000, 0x00000038 } },
+ { AR5K_RF_GAIN(32), { 0x00000000, 0x00000078 } },
+ { AR5K_RF_GAIN(33), { 0x00000000, 0x00000199 } },
+ { AR5K_RF_GAIN(34), { 0x00000000, 0x000001d9 } },
+ { AR5K_RF_GAIN(35), { 0x00000000, 0x00000019 } },
+ { AR5K_RF_GAIN(36), { 0x00000000, 0x00000059 } },
+ { AR5K_RF_GAIN(37), { 0x00000000, 0x00000099 } },
+ { AR5K_RF_GAIN(38), { 0x00000000, 0x000000d9 } },
+ { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f9 } },
+};
+
+/* Initial RF Gain settings for AR2316 */
+static const struct ath5k_ini_rfgain rfgain_2316[] = {
+ { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
+ { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } },
+ { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } },
+ { AR5K_RF_GAIN(3), { 0x00000000, 0x000000c0 } },
+ { AR5K_RF_GAIN(4), { 0x00000000, 0x000000e0 } },
+ { AR5K_RF_GAIN(5), { 0x00000000, 0x000000e0 } },
+ { AR5K_RF_GAIN(6), { 0x00000000, 0x00000128 } },
+ { AR5K_RF_GAIN(7), { 0x00000000, 0x00000128 } },
+ { AR5K_RF_GAIN(8), { 0x00000000, 0x00000128 } },
+ { AR5K_RF_GAIN(9), { 0x00000000, 0x00000168 } },
+ { AR5K_RF_GAIN(10), { 0x00000000, 0x000001a8 } },
+ { AR5K_RF_GAIN(11), { 0x00000000, 0x000001e8 } },
+ { AR5K_RF_GAIN(12), { 0x00000000, 0x00000028 } },
+ { AR5K_RF_GAIN(13), { 0x00000000, 0x00000068 } },
+ { AR5K_RF_GAIN(14), { 0x00000000, 0x000000a8 } },
+ { AR5K_RF_GAIN(15), { 0x00000000, 0x000000e8 } },
+ { AR5K_RF_GAIN(16), { 0x00000000, 0x000000e8 } },
+ { AR5K_RF_GAIN(17), { 0x00000000, 0x00000130 } },
+ { AR5K_RF_GAIN(18), { 0x00000000, 0x00000130 } },
+ { AR5K_RF_GAIN(19), { 0x00000000, 0x00000170 } },
+ { AR5K_RF_GAIN(20), { 0x00000000, 0x000001b0 } },
+ { AR5K_RF_GAIN(21), { 0x00000000, 0x000001f0 } },
+ { AR5K_RF_GAIN(22), { 0x00000000, 0x00000030 } },
+ { AR5K_RF_GAIN(23), { 0x00000000, 0x00000070 } },
+ { AR5K_RF_GAIN(24), { 0x00000000, 0x000000b0 } },
+ { AR5K_RF_GAIN(25), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(26), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(27), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(28), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(29), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(30), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(31), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(32), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(33), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(34), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(35), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(36), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(37), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(38), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f0 } },
+};
+
+
+/* Initial RF Gain settings for RF5413 */
+static const struct ath5k_ini_rfgain rfgain_5413[] = {
+ /* 5Ghz 2Ghz */
+ { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
+ { AR5K_RF_GAIN(1), { 0x00000040, 0x00000040 } },
+ { AR5K_RF_GAIN(2), { 0x00000080, 0x00000080 } },
+ { AR5K_RF_GAIN(3), { 0x000001a1, 0x00000161 } },
+ { AR5K_RF_GAIN(4), { 0x000001e1, 0x000001a1 } },
+ { AR5K_RF_GAIN(5), { 0x00000021, 0x000001e1 } },
+ { AR5K_RF_GAIN(6), { 0x00000061, 0x00000021 } },
+ { AR5K_RF_GAIN(7), { 0x00000188, 0x00000061 } },
+ { AR5K_RF_GAIN(8), { 0x000001c8, 0x00000188 } },
+ { AR5K_RF_GAIN(9), { 0x00000008, 0x000001c8 } },
+ { AR5K_RF_GAIN(10), { 0x00000048, 0x00000008 } },
+ { AR5K_RF_GAIN(11), { 0x00000088, 0x00000048 } },
+ { AR5K_RF_GAIN(12), { 0x000001a9, 0x00000088 } },
+ { AR5K_RF_GAIN(13), { 0x000001e9, 0x00000169 } },
+ { AR5K_RF_GAIN(14), { 0x00000029, 0x000001a9 } },
+ { AR5K_RF_GAIN(15), { 0x00000069, 0x000001e9 } },
+ { AR5K_RF_GAIN(16), { 0x000001d0, 0x00000029 } },
+ { AR5K_RF_GAIN(17), { 0x00000010, 0x00000069 } },
+ { AR5K_RF_GAIN(18), { 0x00000050, 0x00000190 } },
+ { AR5K_RF_GAIN(19), { 0x00000090, 0x000001d0 } },
+ { AR5K_RF_GAIN(20), { 0x000001b1, 0x00000010 } },
+ { AR5K_RF_GAIN(21), { 0x000001f1, 0x00000050 } },
+ { AR5K_RF_GAIN(22), { 0x00000031, 0x00000090 } },
+ { AR5K_RF_GAIN(23), { 0x00000071, 0x00000171 } },
+ { AR5K_RF_GAIN(24), { 0x000001b8, 0x000001b1 } },
+ { AR5K_RF_GAIN(25), { 0x000001f8, 0x000001f1 } },
+ { AR5K_RF_GAIN(26), { 0x00000038, 0x00000031 } },
+ { AR5K_RF_GAIN(27), { 0x00000078, 0x00000071 } },
+ { AR5K_RF_GAIN(28), { 0x00000199, 0x00000198 } },
+ { AR5K_RF_GAIN(29), { 0x000001d9, 0x000001d8 } },
+ { AR5K_RF_GAIN(30), { 0x00000019, 0x00000018 } },
+ { AR5K_RF_GAIN(31), { 0x00000059, 0x00000058 } },
+ { AR5K_RF_GAIN(32), { 0x00000099, 0x00000098 } },
+ { AR5K_RF_GAIN(33), { 0x000000d9, 0x00000179 } },
+ { AR5K_RF_GAIN(34), { 0x000000f9, 0x000001b9 } },
+ { AR5K_RF_GAIN(35), { 0x000000f9, 0x000001f9 } },
+ { AR5K_RF_GAIN(36), { 0x000000f9, 0x00000039 } },
+ { AR5K_RF_GAIN(37), { 0x000000f9, 0x00000079 } },
+ { AR5K_RF_GAIN(38), { 0x000000f9, 0x000000b9 } },
+ { AR5K_RF_GAIN(39), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(40), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(41), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(42), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(43), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(44), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(45), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(46), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(47), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(48), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(49), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(50), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(51), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(52), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(53), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(54), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(55), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(56), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(57), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(58), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(59), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(60), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(61), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(62), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } },
+};
+
+
+/* Initial RF Gain settings for RF2425 */
+static const struct ath5k_ini_rfgain rfgain_2425[] = {
+ { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
+ { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } },
+ { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } },
+ { AR5K_RF_GAIN(3), { 0x00000000, 0x00000181 } },
+ { AR5K_RF_GAIN(4), { 0x00000000, 0x000001c1 } },
+ { AR5K_RF_GAIN(5), { 0x00000000, 0x00000001 } },
+ { AR5K_RF_GAIN(6), { 0x00000000, 0x00000041 } },
+ { AR5K_RF_GAIN(7), { 0x00000000, 0x00000081 } },
+ { AR5K_RF_GAIN(8), { 0x00000000, 0x00000188 } },
+ { AR5K_RF_GAIN(9), { 0x00000000, 0x000001c8 } },
+ { AR5K_RF_GAIN(10), { 0x00000000, 0x00000008 } },
+ { AR5K_RF_GAIN(11), { 0x00000000, 0x00000048 } },
+ { AR5K_RF_GAIN(12), { 0x00000000, 0x00000088 } },
+ { AR5K_RF_GAIN(13), { 0x00000000, 0x00000189 } },
+ { AR5K_RF_GAIN(14), { 0x00000000, 0x000001c9 } },
+ { AR5K_RF_GAIN(15), { 0x00000000, 0x00000009 } },
+ { AR5K_RF_GAIN(16), { 0x00000000, 0x00000049 } },
+ { AR5K_RF_GAIN(17), { 0x00000000, 0x00000089 } },
+ { AR5K_RF_GAIN(18), { 0x00000000, 0x000001b0 } },
+ { AR5K_RF_GAIN(19), { 0x00000000, 0x000001f0 } },
+ { AR5K_RF_GAIN(20), { 0x00000000, 0x00000030 } },
+ { AR5K_RF_GAIN(21), { 0x00000000, 0x00000070 } },
+ { AR5K_RF_GAIN(22), { 0x00000000, 0x00000171 } },
+ { AR5K_RF_GAIN(23), { 0x00000000, 0x000001b1 } },
+ { AR5K_RF_GAIN(24), { 0x00000000, 0x000001f1 } },
+ { AR5K_RF_GAIN(25), { 0x00000000, 0x00000031 } },
+ { AR5K_RF_GAIN(26), { 0x00000000, 0x00000071 } },
+ { AR5K_RF_GAIN(27), { 0x00000000, 0x000001b8 } },
+ { AR5K_RF_GAIN(28), { 0x00000000, 0x000001f8 } },
+ { AR5K_RF_GAIN(29), { 0x00000000, 0x00000038 } },
+ { AR5K_RF_GAIN(30), { 0x00000000, 0x00000078 } },
+ { AR5K_RF_GAIN(31), { 0x00000000, 0x000000b8 } },
+ { AR5K_RF_GAIN(32), { 0x00000000, 0x000001b9 } },
+ { AR5K_RF_GAIN(33), { 0x00000000, 0x000001f9 } },
+ { AR5K_RF_GAIN(34), { 0x00000000, 0x00000039 } },
+ { AR5K_RF_GAIN(35), { 0x00000000, 0x00000079 } },
+ { AR5K_RF_GAIN(36), { 0x00000000, 0x000000b9 } },
+ { AR5K_RF_GAIN(37), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(38), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f9 } },
+};
+
+#define AR5K_GAIN_CRN_FIX_BITS_5111 4
+#define AR5K_GAIN_CRN_FIX_BITS_5112 7
+#define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112
+#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15
+#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20
+#define AR5K_GAIN_CCK_PROBE_CORR 5
+#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15
+#define AR5K_GAIN_STEP_COUNT 10
+
+/* Check if our current measurement is inside our
+ * current variable attenuation window */
+#define AR5K_GAIN_CHECK_ADJUST(_g) \
+ ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
+
+struct ath5k_gain_opt_step {
+ s8 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS];
+ s8 gos_gain;
+};
+
+struct ath5k_gain_opt {
+ u8 go_default;
+ u8 go_steps_count;
+ const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT];
+};
+
+/*
+ * Parameters on gos_param:
+ * 1) Tx clip PHY register
+ * 2) PWD 90 RF register
+ * 3) PWD 84 RF register
+ * 4) RFGainSel RF register
+ */
+static const struct ath5k_gain_opt rfgain_opt_5111 = {
+ 4,
+ 9,
+ {
+ { { 4, 1, 1, 1 }, 6 },
+ { { 4, 0, 1, 1 }, 4 },
+ { { 3, 1, 1, 1 }, 3 },
+ { { 4, 0, 0, 1 }, 1 },
+ { { 4, 1, 1, 0 }, 0 },
+ { { 4, 0, 1, 0 }, -2 },
+ { { 3, 1, 1, 0 }, -3 },
+ { { 4, 0, 0, 0 }, -4 },
+ { { 2, 1, 1, 0 }, -6 }
+ }
+};
+
+/*
+ * Parameters on gos_param:
+ * 1) Mixgain ovr RF register
+ * 2) PWD 138 RF register
+ * 3) PWD 137 RF register
+ * 4) PWD 136 RF register
+ * 5) PWD 132 RF register
+ * 6) PWD 131 RF register
+ * 7) PWD 130 RF register
+ */
+static const struct ath5k_gain_opt rfgain_opt_5112 = {
+ 1,
+ 8,
+ {
+ { { 3, 0, 0, 0, 0, 0, 0 }, 6 },
+ { { 2, 0, 0, 0, 0, 0, 0 }, 0 },
+ { { 1, 0, 0, 0, 0, 0, 0 }, -3 },
+ { { 0, 0, 0, 0, 0, 0, 0 }, -6 },
+ { { 0, 1, 1, 0, 0, 0, 0 }, -8 },
+ { { 0, 1, 1, 0, 1, 1, 0 }, -10 },
+ { { 0, 1, 0, 1, 1, 1, 0 }, -13 },
+ { { 0, 1, 0, 1, 1, 0, 1 }, -16 },
+ }
+};
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ani.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ani.h
new file mode 100644
index 00000000..9a333b5f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ani.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ANI_H
+#define ANI_H
+
+#define HAL_PROCESS_ANI 0x00000001
+
+#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI) && ah->curchan)
+
+#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi)
+
+/* units are errors per second */
+#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500
+#define ATH9K_ANI_OFDM_TRIG_HIGH_NEW 1000
+
+/* units are errors per second */
+#define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200
+#define ATH9K_ANI_OFDM_TRIG_LOW_NEW 400
+
+/* units are errors per second */
+#define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200
+#define ATH9K_ANI_CCK_TRIG_HIGH_NEW 600
+
+/* units are errors per second */
+#define ATH9K_ANI_CCK_TRIG_LOW_OLD 100
+#define ATH9K_ANI_CCK_TRIG_LOW_NEW 300
+
+#define ATH9K_ANI_NOISE_IMMUNE_LVL 4
+#define ATH9K_ANI_USE_OFDM_WEAK_SIG 1
+#define ATH9K_ANI_CCK_WEAK_SIG_THR 0
+
+#define ATH9K_ANI_SPUR_IMMUNE_LVL_OLD 7
+#define ATH9K_ANI_SPUR_IMMUNE_LVL_NEW 3
+
+#define ATH9K_ANI_FIRSTEP_LVL_OLD 0
+#define ATH9K_ANI_FIRSTEP_LVL_NEW 2
+
+#define ATH9K_ANI_RSSI_THR_HIGH 40
+#define ATH9K_ANI_RSSI_THR_LOW 7
+
+#define ATH9K_ANI_PERIOD_OLD 100
+#define ATH9K_ANI_PERIOD_NEW 1000
+
+/* in ms */
+#define ATH9K_ANI_POLLINTERVAL_OLD 100
+#define ATH9K_ANI_POLLINTERVAL_NEW 1000
+
+#define HAL_NOISE_IMMUNE_MAX 4
+#define HAL_SPUR_IMMUNE_MAX 7
+#define HAL_FIRST_STEP_MAX 2
+
+#define ATH9K_SIG_FIRSTEP_SETTING_MIN 0
+#define ATH9K_SIG_FIRSTEP_SETTING_MAX 20
+#define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0
+#define ATH9K_SIG_SPUR_IMM_SETTING_MAX 22
+
+#define ATH9K_ANI_ENABLE_MRC_CCK 1
+
+/* values here are relative to the INI */
+
+enum ath9k_ani_cmd {
+ ATH9K_ANI_PRESENT = 0x1,
+ ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x4,
+ ATH9K_ANI_CCK_WEAK_SIGNAL_THR = 0x8,
+ ATH9K_ANI_FIRSTEP_LEVEL = 0x10,
+ ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20,
+ ATH9K_ANI_MODE = 0x40,
+ ATH9K_ANI_PHYERR_RESET = 0x80,
+ ATH9K_ANI_MRC_CCK = 0x100,
+ ATH9K_ANI_ALL = 0xfff
+};
+
+struct ath9k_mib_stats {
+ u32 ackrcv_bad;
+ u32 rts_bad;
+ u32 rts_good;
+ u32 fcs_bad;
+ u32 beacons;
+};
+
+/* INI default values for ANI registers */
+struct ath9k_ani_default {
+ u16 m1ThreshLow;
+ u16 m2ThreshLow;
+ u16 m1Thresh;
+ u16 m2Thresh;
+ u16 m2CountThr;
+ u16 m2CountThrLow;
+ u16 m1ThreshLowExt;
+ u16 m2ThreshLowExt;
+ u16 m1ThreshExt;
+ u16 m2ThreshExt;
+ u16 firstep;
+ u16 firstepLow;
+ u16 cycpwrThr1;
+ u16 cycpwrThr1Ext;
+};
+
+struct ar5416AniState {
+ struct ath9k_channel *c;
+ u8 noiseImmunityLevel;
+ u8 ofdmNoiseImmunityLevel;
+ u8 cckNoiseImmunityLevel;
+ int ofdmsTurn;
+ u8 mrcCCKOff;
+ u8 spurImmunityLevel;
+ u8 firstepLevel;
+ u8 ofdmWeakSigDetectOff;
+ u8 cckWeakSigThreshold;
+ u32 listenTime;
+ int32_t rssiThrLow;
+ int32_t rssiThrHigh;
+ u32 noiseFloor;
+ u32 ofdmPhyErrCount;
+ u32 cckPhyErrCount;
+ int16_t pktRssi[2];
+ int16_t ofdmErrRssi[2];
+ int16_t cckErrRssi[2];
+ struct ath9k_ani_default iniDef;
+};
+
+struct ar5416Stats {
+ u32 ast_ani_niup;
+ u32 ast_ani_nidown;
+ u32 ast_ani_spurup;
+ u32 ast_ani_spurdown;
+ u32 ast_ani_ofdmon;
+ u32 ast_ani_ofdmoff;
+ u32 ast_ani_cckhigh;
+ u32 ast_ani_ccklow;
+ u32 ast_ani_stepup;
+ u32 ast_ani_stepdown;
+ u32 ast_ani_ofdmerrs;
+ u32 ast_ani_cckerrs;
+ u32 ast_ani_reset;
+ u32 ast_ani_lzero;
+ u32 ast_ani_lneg;
+ u32 avgbrssi;
+ struct ath9k_mib_stats ast_mibstats;
+};
+#define ah_mibStats stats.ast_mibstats
+
+void ath9k_enable_mib_counters(struct ath_hw *ah);
+void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
+void ath9k_hw_ani_setup(struct ath_hw *ah);
+void ath9k_hw_ani_init(struct ath_hw *ah);
+int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
+ struct ath9k_channel *chan);
+
+#endif /* ANI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar5008_initvals.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar5008_initvals.h
new file mode 100644
index 00000000..479aed54
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar5008_initvals.h
@@ -0,0 +1,672 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+static const u32 ar5416Modes[][6] = {
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
+ {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
+ {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0},
+ {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+ {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+ {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+ {0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de},
+ {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+ {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
+ {0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18},
+ {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190},
+ {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
+ {0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134},
+ {0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b},
+ {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
+ {0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
+ {0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
+ {0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
+ {0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120},
+ {0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00},
+ {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+ {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
+ {0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
+ {0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
+ {0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
+ {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
+ {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+ {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
+ {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
+ {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
+ {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
+ {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
+ {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
+ {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
+ {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
+ {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
+ {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar5416Common[][2] = {
+ /* Addr allmodes */
+ {0x0000000c, 0x00000000},
+ {0x00000030, 0x00020015},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000008},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00000054, 0x0000001f},
+ {0x00000800, 0x00000000},
+ {0x00000804, 0x00000000},
+ {0x00000808, 0x00000000},
+ {0x0000080c, 0x00000000},
+ {0x00000810, 0x00000000},
+ {0x00000814, 0x00000000},
+ {0x00000818, 0x00000000},
+ {0x0000081c, 0x00000000},
+ {0x00000820, 0x00000000},
+ {0x00000824, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x00001230, 0x00000000},
+ {0x00001270, 0x00000000},
+ {0x00001038, 0x00000000},
+ {0x00001078, 0x00000000},
+ {0x000010b8, 0x00000000},
+ {0x000010f8, 0x00000000},
+ {0x00001138, 0x00000000},
+ {0x00001178, 0x00000000},
+ {0x000011b8, 0x00000000},
+ {0x000011f8, 0x00000000},
+ {0x00001238, 0x00000000},
+ {0x00001278, 0x00000000},
+ {0x000012b8, 0x00000000},
+ {0x000012f8, 0x00000000},
+ {0x00001338, 0x00000000},
+ {0x00001378, 0x00000000},
+ {0x000013b8, 0x00000000},
+ {0x000013f8, 0x00000000},
+ {0x00001438, 0x00000000},
+ {0x00001478, 0x00000000},
+ {0x000014b8, 0x00000000},
+ {0x000014f8, 0x00000000},
+ {0x00001538, 0x00000000},
+ {0x00001578, 0x00000000},
+ {0x000015b8, 0x00000000},
+ {0x000015f8, 0x00000000},
+ {0x00001638, 0x00000000},
+ {0x00001678, 0x00000000},
+ {0x000016b8, 0x00000000},
+ {0x000016f8, 0x00000000},
+ {0x00001738, 0x00000000},
+ {0x00001778, 0x00000000},
+ {0x000017b8, 0x00000000},
+ {0x000017f8, 0x00000000},
+ {0x0000103c, 0x00000000},
+ {0x0000107c, 0x00000000},
+ {0x000010bc, 0x00000000},
+ {0x000010fc, 0x00000000},
+ {0x0000113c, 0x00000000},
+ {0x0000117c, 0x00000000},
+ {0x000011bc, 0x00000000},
+ {0x000011fc, 0x00000000},
+ {0x0000123c, 0x00000000},
+ {0x0000127c, 0x00000000},
+ {0x000012bc, 0x00000000},
+ {0x000012fc, 0x00000000},
+ {0x0000133c, 0x00000000},
+ {0x0000137c, 0x00000000},
+ {0x000013bc, 0x00000000},
+ {0x000013fc, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00004030, 0x00000002},
+ {0x0000403c, 0x00000002},
+ {0x00007010, 0x00000000},
+ {0x00007038, 0x000004c2},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000700},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00000000},
+ {0x00008048, 0x40000000},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x000080c0, 0x2a82301a},
+ {0x000080c4, 0x05dc01e0},
+ {0x000080c8, 0x1f402710},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00001e00},
+ {0x000080d4, 0x00000000},
+ {0x000080d8, 0x00400000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x003f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080f8, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00020000},
+ {0x00008104, 0x00000001},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000168},
+ {0x00008118, 0x000100aa},
+ {0x0000811c, 0x00003210},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x00000000},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x32143320},
+ {0x00008174, 0xfaa4fa50},
+ {0x00008178, 0x00000100},
+ {0x0000817c, 0x00000000},
+ {0x000081c4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008200, 0x00000000},
+ {0x00008204, 0x00000000},
+ {0x00008208, 0x00000000},
+ {0x0000820c, 0x00000000},
+ {0x00008210, 0x00000000},
+ {0x00008214, 0x00000000},
+ {0x00008218, 0x00000000},
+ {0x0000821c, 0x00000000},
+ {0x00008220, 0x00000000},
+ {0x00008224, 0x00000000},
+ {0x00008228, 0x00000000},
+ {0x0000822c, 0x00000000},
+ {0x00008230, 0x00000000},
+ {0x00008234, 0x00000000},
+ {0x00008238, 0x00000000},
+ {0x0000823c, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f400},
+ {0x00008248, 0x00000100},
+ {0x0000824c, 0x0001e800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x400000ff},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x88000010},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000000},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x00000000},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x00008300, 0x00000000},
+ {0x00008304, 0x00000000},
+ {0x00008308, 0x00000000},
+ {0x0000830c, 0x00000000},
+ {0x00008310, 0x00000000},
+ {0x00008314, 0x00000000},
+ {0x00008318, 0x00000000},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000007},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000e00},
+ {0x00008338, 0x00070000},
+ {0x0000833c, 0x00000000},
+ {0x00008340, 0x000107ff},
+ {0x00009808, 0x00000000},
+ {0x0000980c, 0xad848e19},
+ {0x00009810, 0x7d14e000},
+ {0x00009814, 0x9c0a9f6b},
+ {0x0000981c, 0x00000000},
+ {0x0000982c, 0x0000a000},
+ {0x00009830, 0x00000000},
+ {0x0000983c, 0x00200400},
+ {0x00009840, 0x206a002e},
+ {0x0000984c, 0x1284233c},
+ {0x00009854, 0x00000859},
+ {0x00009900, 0x00000000},
+ {0x00009904, 0x00000000},
+ {0x00009908, 0x00000000},
+ {0x0000990c, 0x00000000},
+ {0x0000991c, 0x10000fff},
+ {0x00009920, 0x05100000},
+ {0x0000a920, 0x05100000},
+ {0x0000b920, 0x05100000},
+ {0x00009928, 0x00000001},
+ {0x0000992c, 0x00000004},
+ {0x00009934, 0x1e1f2022},
+ {0x00009938, 0x0a0b0c0d},
+ {0x0000993c, 0x00000000},
+ {0x00009948, 0x9280b212},
+ {0x0000994c, 0x00020028},
+ {0x00009954, 0x5d50e188},
+ {0x00009958, 0x00081fff},
+ {0x0000c95c, 0x004b6a8e},
+ {0x0000c968, 0x000003ce},
+ {0x00009970, 0x190fb515},
+ {0x00009974, 0x00000000},
+ {0x00009978, 0x00000001},
+ {0x0000997c, 0x00000000},
+ {0x00009980, 0x00000000},
+ {0x00009984, 0x00000000},
+ {0x00009988, 0x00000000},
+ {0x0000998c, 0x00000000},
+ {0x00009990, 0x00000000},
+ {0x00009994, 0x00000000},
+ {0x00009998, 0x00000000},
+ {0x0000999c, 0x00000000},
+ {0x000099a0, 0x00000000},
+ {0x000099a4, 0x00000001},
+ {0x000099a8, 0x001fff00},
+ {0x000099ac, 0x00000000},
+ {0x000099b0, 0x03051000},
+ {0x000099dc, 0x00000000},
+ {0x000099e0, 0x00000200},
+ {0x000099e4, 0xaaaaaaaa},
+ {0x000099e8, 0x3c466478},
+ {0x000099ec, 0x000000aa},
+ {0x000099fc, 0x00001042},
+ {0x00009b00, 0x00000000},
+ {0x00009b04, 0x00000001},
+ {0x00009b08, 0x00000002},
+ {0x00009b0c, 0x00000003},
+ {0x00009b10, 0x00000004},
+ {0x00009b14, 0x00000005},
+ {0x00009b18, 0x00000008},
+ {0x00009b1c, 0x00000009},
+ {0x00009b20, 0x0000000a},
+ {0x00009b24, 0x0000000b},
+ {0x00009b28, 0x0000000c},
+ {0x00009b2c, 0x0000000d},
+ {0x00009b30, 0x00000010},
+ {0x00009b34, 0x00000011},
+ {0x00009b38, 0x00000012},
+ {0x00009b3c, 0x00000013},
+ {0x00009b40, 0x00000014},
+ {0x00009b44, 0x00000015},
+ {0x00009b48, 0x00000018},
+ {0x00009b4c, 0x00000019},
+ {0x00009b50, 0x0000001a},
+ {0x00009b54, 0x0000001b},
+ {0x00009b58, 0x0000001c},
+ {0x00009b5c, 0x0000001d},
+ {0x00009b60, 0x00000020},
+ {0x00009b64, 0x00000021},
+ {0x00009b68, 0x00000022},
+ {0x00009b6c, 0x00000023},
+ {0x00009b70, 0x00000024},
+ {0x00009b74, 0x00000025},
+ {0x00009b78, 0x00000028},
+ {0x00009b7c, 0x00000029},
+ {0x00009b80, 0x0000002a},
+ {0x00009b84, 0x0000002b},
+ {0x00009b88, 0x0000002c},
+ {0x00009b8c, 0x0000002d},
+ {0x00009b90, 0x00000030},
+ {0x00009b94, 0x00000031},
+ {0x00009b98, 0x00000032},
+ {0x00009b9c, 0x00000033},
+ {0x00009ba0, 0x00000034},
+ {0x00009ba4, 0x00000035},
+ {0x00009ba8, 0x00000035},
+ {0x00009bac, 0x00000035},
+ {0x00009bb0, 0x00000035},
+ {0x00009bb4, 0x00000035},
+ {0x00009bb8, 0x00000035},
+ {0x00009bbc, 0x00000035},
+ {0x00009bc0, 0x00000035},
+ {0x00009bc4, 0x00000035},
+ {0x00009bc8, 0x00000035},
+ {0x00009bcc, 0x00000035},
+ {0x00009bd0, 0x00000035},
+ {0x00009bd4, 0x00000035},
+ {0x00009bd8, 0x00000035},
+ {0x00009bdc, 0x00000035},
+ {0x00009be0, 0x00000035},
+ {0x00009be4, 0x00000035},
+ {0x00009be8, 0x00000035},
+ {0x00009bec, 0x00000035},
+ {0x00009bf0, 0x00000035},
+ {0x00009bf4, 0x00000035},
+ {0x00009bf8, 0x00000010},
+ {0x00009bfc, 0x0000001a},
+ {0x0000a210, 0x40806333},
+ {0x0000a214, 0x00106c10},
+ {0x0000a218, 0x009c4060},
+ {0x0000a220, 0x018830c6},
+ {0x0000a224, 0x00000400},
+ {0x0000a228, 0x00000bb5},
+ {0x0000a22c, 0x00000011},
+ {0x0000a234, 0x20202020},
+ {0x0000a238, 0x20202020},
+ {0x0000a23c, 0x13c889af},
+ {0x0000a240, 0x38490a20},
+ {0x0000a244, 0x00007bb6},
+ {0x0000a248, 0x0fff3ffc},
+ {0x0000a24c, 0x00000001},
+ {0x0000a250, 0x0000a000},
+ {0x0000a254, 0x00000000},
+ {0x0000a258, 0x0cc75380},
+ {0x0000a25c, 0x0f0f0f01},
+ {0x0000a260, 0xdfa91f01},
+ {0x0000a268, 0x00000000},
+ {0x0000a26c, 0x0e79e5c6},
+ {0x0000b26c, 0x0e79e5c6},
+ {0x0000c26c, 0x0e79e5c6},
+ {0x0000d270, 0x00820820},
+ {0x0000a278, 0x1ce739ce},
+ {0x0000a27c, 0x051701ce},
+ {0x0000a338, 0x00000000},
+ {0x0000a33c, 0x00000000},
+ {0x0000a340, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a348, 0x3fffffff},
+ {0x0000a34c, 0x3fffffff},
+ {0x0000a350, 0x3fffffff},
+ {0x0000a354, 0x0003ffff},
+ {0x0000a358, 0x79a8aa1f},
+ {0x0000d35c, 0x07ffffef},
+ {0x0000d360, 0x0fffffe7},
+ {0x0000d364, 0x17ffffe5},
+ {0x0000d368, 0x1fffffe4},
+ {0x0000d36c, 0x37ffffe3},
+ {0x0000d370, 0x3fffffe3},
+ {0x0000d374, 0x57ffffe3},
+ {0x0000d378, 0x5fffffe2},
+ {0x0000d37c, 0x7fffffe2},
+ {0x0000d380, 0x7f3c7bba},
+ {0x0000d384, 0xf3307ff0},
+ {0x0000a388, 0x08000000},
+ {0x0000a38c, 0x20202020},
+ {0x0000a390, 0x20202020},
+ {0x0000a394, 0x1ce739ce},
+ {0x0000a398, 0x000001ce},
+ {0x0000a39c, 0x00000001},
+ {0x0000a3a0, 0x00000000},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0x00000000},
+ {0x0000a3ac, 0x00000000},
+ {0x0000a3b0, 0x00000000},
+ {0x0000a3b4, 0x00000000},
+ {0x0000a3b8, 0x00000000},
+ {0x0000a3bc, 0x00000000},
+ {0x0000a3c0, 0x00000000},
+ {0x0000a3c4, 0x00000000},
+ {0x0000a3c8, 0x00000246},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3dc, 0x1ce739ce},
+ {0x0000a3e0, 0x000001ce},
+};
+
+static const u32 ar5416Bank0[][2] = {
+ /* Addr allmodes */
+ {0x000098b0, 0x1e5795e5},
+ {0x000098e0, 0x02008020},
+};
+
+static const u32 ar5416BB_RfGain[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x00009a00, 0x00000000, 0x00000000},
+ {0x00009a04, 0x00000040, 0x00000040},
+ {0x00009a08, 0x00000080, 0x00000080},
+ {0x00009a0c, 0x000001a1, 0x00000141},
+ {0x00009a10, 0x000001e1, 0x00000181},
+ {0x00009a14, 0x00000021, 0x000001c1},
+ {0x00009a18, 0x00000061, 0x00000001},
+ {0x00009a1c, 0x00000168, 0x00000041},
+ {0x00009a20, 0x000001a8, 0x000001a8},
+ {0x00009a24, 0x000001e8, 0x000001e8},
+ {0x00009a28, 0x00000028, 0x00000028},
+ {0x00009a2c, 0x00000068, 0x00000068},
+ {0x00009a30, 0x00000189, 0x000000a8},
+ {0x00009a34, 0x000001c9, 0x00000169},
+ {0x00009a38, 0x00000009, 0x000001a9},
+ {0x00009a3c, 0x00000049, 0x000001e9},
+ {0x00009a40, 0x00000089, 0x00000029},
+ {0x00009a44, 0x00000170, 0x00000069},
+ {0x00009a48, 0x000001b0, 0x00000190},
+ {0x00009a4c, 0x000001f0, 0x000001d0},
+ {0x00009a50, 0x00000030, 0x00000010},
+ {0x00009a54, 0x00000070, 0x00000050},
+ {0x00009a58, 0x00000191, 0x00000090},
+ {0x00009a5c, 0x000001d1, 0x00000151},
+ {0x00009a60, 0x00000011, 0x00000191},
+ {0x00009a64, 0x00000051, 0x000001d1},
+ {0x00009a68, 0x00000091, 0x00000011},
+ {0x00009a6c, 0x000001b8, 0x00000051},
+ {0x00009a70, 0x000001f8, 0x00000198},
+ {0x00009a74, 0x00000038, 0x000001d8},
+ {0x00009a78, 0x00000078, 0x00000018},
+ {0x00009a7c, 0x00000199, 0x00000058},
+ {0x00009a80, 0x000001d9, 0x00000098},
+ {0x00009a84, 0x00000019, 0x00000159},
+ {0x00009a88, 0x00000059, 0x00000199},
+ {0x00009a8c, 0x00000099, 0x000001d9},
+ {0x00009a90, 0x000000d9, 0x00000019},
+ {0x00009a94, 0x000000f9, 0x00000059},
+ {0x00009a98, 0x000000f9, 0x00000099},
+ {0x00009a9c, 0x000000f9, 0x000000d9},
+ {0x00009aa0, 0x000000f9, 0x000000f9},
+ {0x00009aa4, 0x000000f9, 0x000000f9},
+ {0x00009aa8, 0x000000f9, 0x000000f9},
+ {0x00009aac, 0x000000f9, 0x000000f9},
+ {0x00009ab0, 0x000000f9, 0x000000f9},
+ {0x00009ab4, 0x000000f9, 0x000000f9},
+ {0x00009ab8, 0x000000f9, 0x000000f9},
+ {0x00009abc, 0x000000f9, 0x000000f9},
+ {0x00009ac0, 0x000000f9, 0x000000f9},
+ {0x00009ac4, 0x000000f9, 0x000000f9},
+ {0x00009ac8, 0x000000f9, 0x000000f9},
+ {0x00009acc, 0x000000f9, 0x000000f9},
+ {0x00009ad0, 0x000000f9, 0x000000f9},
+ {0x00009ad4, 0x000000f9, 0x000000f9},
+ {0x00009ad8, 0x000000f9, 0x000000f9},
+ {0x00009adc, 0x000000f9, 0x000000f9},
+ {0x00009ae0, 0x000000f9, 0x000000f9},
+ {0x00009ae4, 0x000000f9, 0x000000f9},
+ {0x00009ae8, 0x000000f9, 0x000000f9},
+ {0x00009aec, 0x000000f9, 0x000000f9},
+ {0x00009af0, 0x000000f9, 0x000000f9},
+ {0x00009af4, 0x000000f9, 0x000000f9},
+ {0x00009af8, 0x000000f9, 0x000000f9},
+ {0x00009afc, 0x000000f9, 0x000000f9},
+};
+
+static const u32 ar5416Bank1[][2] = {
+ /* Addr allmodes */
+ {0x000098b0, 0x02108421},
+ {0x000098ec, 0x00000008},
+};
+
+static const u32 ar5416Bank2[][2] = {
+ /* Addr allmodes */
+ {0x000098b0, 0x0e73ff17},
+ {0x000098e0, 0x00000420},
+};
+
+static const u32 ar5416Bank3[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x000098f0, 0x01400018, 0x01c00018},
+};
+
+static const u32 ar5416Bank6[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00e00000, 0x00e00000},
+ {0x0000989c, 0x005e0000, 0x005e0000},
+ {0x0000989c, 0x00120000, 0x00120000},
+ {0x0000989c, 0x00620000, 0x00620000},
+ {0x0000989c, 0x00020000, 0x00020000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x40ff0000, 0x40ff0000},
+ {0x0000989c, 0x005f0000, 0x005f0000},
+ {0x0000989c, 0x00870000, 0x00870000},
+ {0x0000989c, 0x00f90000, 0x00f90000},
+ {0x0000989c, 0x007b0000, 0x007b0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00f50000, 0x00f50000},
+ {0x0000989c, 0x00dc0000, 0x00dc0000},
+ {0x0000989c, 0x00110000, 0x00110000},
+ {0x0000989c, 0x006100a8, 0x006100a8},
+ {0x0000989c, 0x004210a2, 0x004210a2},
+ {0x0000989c, 0x0014008f, 0x0014008f},
+ {0x0000989c, 0x00c40003, 0x00c40003},
+ {0x0000989c, 0x003000f2, 0x003000f2},
+ {0x0000989c, 0x00440016, 0x00440016},
+ {0x0000989c, 0x00410040, 0x00410040},
+ {0x0000989c, 0x0001805e, 0x0001805e},
+ {0x0000989c, 0x0000c0ab, 0x0000c0ab},
+ {0x0000989c, 0x000000f1, 0x000000f1},
+ {0x0000989c, 0x00002081, 0x00002081},
+ {0x0000989c, 0x000000d4, 0x000000d4},
+ {0x000098d0, 0x0000000f, 0x0010000f},
+};
+
+static const u32 ar5416Bank6TPC[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00e00000, 0x00e00000},
+ {0x0000989c, 0x005e0000, 0x005e0000},
+ {0x0000989c, 0x00120000, 0x00120000},
+ {0x0000989c, 0x00620000, 0x00620000},
+ {0x0000989c, 0x00020000, 0x00020000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x40ff0000, 0x40ff0000},
+ {0x0000989c, 0x005f0000, 0x005f0000},
+ {0x0000989c, 0x00870000, 0x00870000},
+ {0x0000989c, 0x00f90000, 0x00f90000},
+ {0x0000989c, 0x007b0000, 0x007b0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00f50000, 0x00f50000},
+ {0x0000989c, 0x00dc0000, 0x00dc0000},
+ {0x0000989c, 0x00110000, 0x00110000},
+ {0x0000989c, 0x006100a8, 0x006100a8},
+ {0x0000989c, 0x00423022, 0x00423022},
+ {0x0000989c, 0x201400df, 0x201400df},
+ {0x0000989c, 0x00c40002, 0x00c40002},
+ {0x0000989c, 0x003000f2, 0x003000f2},
+ {0x0000989c, 0x00440016, 0x00440016},
+ {0x0000989c, 0x00410040, 0x00410040},
+ {0x0000989c, 0x0001805e, 0x0001805e},
+ {0x0000989c, 0x0000c0ab, 0x0000c0ab},
+ {0x0000989c, 0x000000e1, 0x000000e1},
+ {0x0000989c, 0x00007081, 0x00007081},
+ {0x0000989c, 0x000000d4, 0x000000d4},
+ {0x000098d0, 0x0000000f, 0x0010000f},
+};
+
+static const u32 ar5416Bank7[][2] = {
+ /* Addr allmodes */
+ {0x0000989c, 0x00000500},
+ {0x0000989c, 0x00000800},
+ {0x000098cc, 0x0000000e},
+};
+
+static const u32 ar5416Addac[][2] = {
+ /* Addr allmodes */
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000003},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x0000000c},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000030},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000060},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000058},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x000098cc, 0x00000000},
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9001_initvals.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9001_initvals.h
new file mode 100644
index 00000000..7dca4744
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9001_initvals.h
@@ -0,0 +1,1356 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+static const u32 ar5416Modes_9100[][6] = {
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
+ {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
+ {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
+ {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+ {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+ {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+ {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2},
+ {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+ {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
+ {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
+ {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
+ {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
+ {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
+ {0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204},
+ {0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020},
+ {0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e},
+ {0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff},
+ {0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+ {0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+ {0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+ {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
+ {0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00},
+ {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+ {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
+ {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
+ {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
+ {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
+ {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
+ {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+ {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
+ {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
+ {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
+ {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
+ {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
+ {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
+ {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
+ {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
+ {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
+ {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar5416Common_9100[][2] = {
+ /* Addr allmodes */
+ {0x0000000c, 0x00000000},
+ {0x00000030, 0x00020015},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000008},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00000054, 0x0000001f},
+ {0x00000800, 0x00000000},
+ {0x00000804, 0x00000000},
+ {0x00000808, 0x00000000},
+ {0x0000080c, 0x00000000},
+ {0x00000810, 0x00000000},
+ {0x00000814, 0x00000000},
+ {0x00000818, 0x00000000},
+ {0x0000081c, 0x00000000},
+ {0x00000820, 0x00000000},
+ {0x00000824, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x00001230, 0x00000000},
+ {0x00001270, 0x00000000},
+ {0x00001038, 0x00000000},
+ {0x00001078, 0x00000000},
+ {0x000010b8, 0x00000000},
+ {0x000010f8, 0x00000000},
+ {0x00001138, 0x00000000},
+ {0x00001178, 0x00000000},
+ {0x000011b8, 0x00000000},
+ {0x000011f8, 0x00000000},
+ {0x00001238, 0x00000000},
+ {0x00001278, 0x00000000},
+ {0x000012b8, 0x00000000},
+ {0x000012f8, 0x00000000},
+ {0x00001338, 0x00000000},
+ {0x00001378, 0x00000000},
+ {0x000013b8, 0x00000000},
+ {0x000013f8, 0x00000000},
+ {0x00001438, 0x00000000},
+ {0x00001478, 0x00000000},
+ {0x000014b8, 0x00000000},
+ {0x000014f8, 0x00000000},
+ {0x00001538, 0x00000000},
+ {0x00001578, 0x00000000},
+ {0x000015b8, 0x00000000},
+ {0x000015f8, 0x00000000},
+ {0x00001638, 0x00000000},
+ {0x00001678, 0x00000000},
+ {0x000016b8, 0x00000000},
+ {0x000016f8, 0x00000000},
+ {0x00001738, 0x00000000},
+ {0x00001778, 0x00000000},
+ {0x000017b8, 0x00000000},
+ {0x000017f8, 0x00000000},
+ {0x0000103c, 0x00000000},
+ {0x0000107c, 0x00000000},
+ {0x000010bc, 0x00000000},
+ {0x000010fc, 0x00000000},
+ {0x0000113c, 0x00000000},
+ {0x0000117c, 0x00000000},
+ {0x000011bc, 0x00000000},
+ {0x000011fc, 0x00000000},
+ {0x0000123c, 0x00000000},
+ {0x0000127c, 0x00000000},
+ {0x000012bc, 0x00000000},
+ {0x000012fc, 0x00000000},
+ {0x0000133c, 0x00000000},
+ {0x0000137c, 0x00000000},
+ {0x000013bc, 0x00000000},
+ {0x000013fc, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00020010, 0x00000003},
+ {0x00020038, 0x000004c2},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000700},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00000000},
+ {0x00008048, 0x40000000},
+ {0x00008054, 0x00004000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x000080c0, 0x2a82301a},
+ {0x000080c4, 0x05dc01e0},
+ {0x000080c8, 0x1f402710},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00001e00},
+ {0x000080d4, 0x00000000},
+ {0x000080d8, 0x00400000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x003f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080f8, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00020000},
+ {0x00008104, 0x00000001},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000168},
+ {0x00008118, 0x000100aa},
+ {0x0000811c, 0x00003210},
+ {0x00008120, 0x08f04800},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x00000000},
+ {0x00008144, 0x00000000},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x32143320},
+ {0x00008174, 0xfaa4fa50},
+ {0x00008178, 0x00000100},
+ {0x0000817c, 0x00000000},
+ {0x000081c4, 0x00000000},
+ {0x000081d0, 0x00003210},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008200, 0x00000000},
+ {0x00008204, 0x00000000},
+ {0x00008208, 0x00000000},
+ {0x0000820c, 0x00000000},
+ {0x00008210, 0x00000000},
+ {0x00008214, 0x00000000},
+ {0x00008218, 0x00000000},
+ {0x0000821c, 0x00000000},
+ {0x00008220, 0x00000000},
+ {0x00008224, 0x00000000},
+ {0x00008228, 0x00000000},
+ {0x0000822c, 0x00000000},
+ {0x00008230, 0x00000000},
+ {0x00008234, 0x00000000},
+ {0x00008238, 0x00000000},
+ {0x0000823c, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f400},
+ {0x00008248, 0x00000100},
+ {0x0000824c, 0x0001e800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x400000ff},
+ {0x00008260, 0x00080922},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000000},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x00000000},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x00008300, 0x00000000},
+ {0x00008304, 0x00000000},
+ {0x00008308, 0x00000000},
+ {0x0000830c, 0x00000000},
+ {0x00008310, 0x00000000},
+ {0x00008314, 0x00000000},
+ {0x00008318, 0x00000000},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000007},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000e00},
+ {0x00008338, 0x00000000},
+ {0x0000833c, 0x00000000},
+ {0x00008340, 0x000107ff},
+ {0x00009808, 0x00000000},
+ {0x0000980c, 0xad848e19},
+ {0x00009810, 0x7d14e000},
+ {0x00009814, 0x9c0a9f6b},
+ {0x0000981c, 0x00000000},
+ {0x0000982c, 0x0000a000},
+ {0x00009830, 0x00000000},
+ {0x0000983c, 0x00200400},
+ {0x00009840, 0x206a01ae},
+ {0x0000984c, 0x1284233c},
+ {0x00009854, 0x00000859},
+ {0x00009900, 0x00000000},
+ {0x00009904, 0x00000000},
+ {0x00009908, 0x00000000},
+ {0x0000990c, 0x00000000},
+ {0x0000991c, 0x10000fff},
+ {0x00009920, 0x05100000},
+ {0x0000a920, 0x05100000},
+ {0x0000b920, 0x05100000},
+ {0x00009928, 0x00000001},
+ {0x0000992c, 0x00000004},
+ {0x00009934, 0x1e1f2022},
+ {0x00009938, 0x0a0b0c0d},
+ {0x0000993c, 0x00000000},
+ {0x00009948, 0x9280b212},
+ {0x0000994c, 0x00020028},
+ {0x0000c95c, 0x004b6a8e},
+ {0x0000c968, 0x000003ce},
+ {0x00009970, 0x190fb515},
+ {0x00009974, 0x00000000},
+ {0x00009978, 0x00000001},
+ {0x0000997c, 0x00000000},
+ {0x00009980, 0x00000000},
+ {0x00009984, 0x00000000},
+ {0x00009988, 0x00000000},
+ {0x0000998c, 0x00000000},
+ {0x00009990, 0x00000000},
+ {0x00009994, 0x00000000},
+ {0x00009998, 0x00000000},
+ {0x0000999c, 0x00000000},
+ {0x000099a0, 0x00000000},
+ {0x000099a4, 0x00000001},
+ {0x000099a8, 0x201fff00},
+ {0x000099ac, 0x006f0000},
+ {0x000099b0, 0x03051000},
+ {0x000099dc, 0x00000000},
+ {0x000099e0, 0x00000200},
+ {0x000099e4, 0xaaaaaaaa},
+ {0x000099e8, 0x3c466478},
+ {0x000099ec, 0x0cc80caa},
+ {0x000099fc, 0x00001042},
+ {0x00009b00, 0x00000000},
+ {0x00009b04, 0x00000001},
+ {0x00009b08, 0x00000002},
+ {0x00009b0c, 0x00000003},
+ {0x00009b10, 0x00000004},
+ {0x00009b14, 0x00000005},
+ {0x00009b18, 0x00000008},
+ {0x00009b1c, 0x00000009},
+ {0x00009b20, 0x0000000a},
+ {0x00009b24, 0x0000000b},
+ {0x00009b28, 0x0000000c},
+ {0x00009b2c, 0x0000000d},
+ {0x00009b30, 0x00000010},
+ {0x00009b34, 0x00000011},
+ {0x00009b38, 0x00000012},
+ {0x00009b3c, 0x00000013},
+ {0x00009b40, 0x00000014},
+ {0x00009b44, 0x00000015},
+ {0x00009b48, 0x00000018},
+ {0x00009b4c, 0x00000019},
+ {0x00009b50, 0x0000001a},
+ {0x00009b54, 0x0000001b},
+ {0x00009b58, 0x0000001c},
+ {0x00009b5c, 0x0000001d},
+ {0x00009b60, 0x00000020},
+ {0x00009b64, 0x00000021},
+ {0x00009b68, 0x00000022},
+ {0x00009b6c, 0x00000023},
+ {0x00009b70, 0x00000024},
+ {0x00009b74, 0x00000025},
+ {0x00009b78, 0x00000028},
+ {0x00009b7c, 0x00000029},
+ {0x00009b80, 0x0000002a},
+ {0x00009b84, 0x0000002b},
+ {0x00009b88, 0x0000002c},
+ {0x00009b8c, 0x0000002d},
+ {0x00009b90, 0x00000030},
+ {0x00009b94, 0x00000031},
+ {0x00009b98, 0x00000032},
+ {0x00009b9c, 0x00000033},
+ {0x00009ba0, 0x00000034},
+ {0x00009ba4, 0x00000035},
+ {0x00009ba8, 0x00000035},
+ {0x00009bac, 0x00000035},
+ {0x00009bb0, 0x00000035},
+ {0x00009bb4, 0x00000035},
+ {0x00009bb8, 0x00000035},
+ {0x00009bbc, 0x00000035},
+ {0x00009bc0, 0x00000035},
+ {0x00009bc4, 0x00000035},
+ {0x00009bc8, 0x00000035},
+ {0x00009bcc, 0x00000035},
+ {0x00009bd0, 0x00000035},
+ {0x00009bd4, 0x00000035},
+ {0x00009bd8, 0x00000035},
+ {0x00009bdc, 0x00000035},
+ {0x00009be0, 0x00000035},
+ {0x00009be4, 0x00000035},
+ {0x00009be8, 0x00000035},
+ {0x00009bec, 0x00000035},
+ {0x00009bf0, 0x00000035},
+ {0x00009bf4, 0x00000035},
+ {0x00009bf8, 0x00000010},
+ {0x00009bfc, 0x0000001a},
+ {0x0000a210, 0x40806333},
+ {0x0000a214, 0x00106c10},
+ {0x0000a218, 0x009c4060},
+ {0x0000a220, 0x018830c6},
+ {0x0000a224, 0x00000400},
+ {0x0000a228, 0x001a0bb5},
+ {0x0000a22c, 0x00000000},
+ {0x0000a234, 0x20202020},
+ {0x0000a238, 0x20202020},
+ {0x0000a23c, 0x13c889af},
+ {0x0000a240, 0x38490a20},
+ {0x0000a244, 0x00007bb6},
+ {0x0000a248, 0x0fff3ffc},
+ {0x0000a24c, 0x00000001},
+ {0x0000a250, 0x0000e000},
+ {0x0000a254, 0x00000000},
+ {0x0000a258, 0x0cc75380},
+ {0x0000a25c, 0x0f0f0f01},
+ {0x0000a260, 0xdfa91f01},
+ {0x0000a268, 0x00000001},
+ {0x0000a26c, 0x0ebae9c6},
+ {0x0000b26c, 0x0ebae9c6},
+ {0x0000c26c, 0x0ebae9c6},
+ {0x0000d270, 0x00820820},
+ {0x0000a278, 0x1ce739ce},
+ {0x0000a27c, 0x050701ce},
+ {0x0000a338, 0x00000000},
+ {0x0000a33c, 0x00000000},
+ {0x0000a340, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a348, 0x3fffffff},
+ {0x0000a34c, 0x3fffffff},
+ {0x0000a350, 0x3fffffff},
+ {0x0000a354, 0x0003ffff},
+ {0x0000a358, 0x79a8aa33},
+ {0x0000d35c, 0x07ffffef},
+ {0x0000d360, 0x0fffffe7},
+ {0x0000d364, 0x17ffffe5},
+ {0x0000d368, 0x1fffffe4},
+ {0x0000d36c, 0x37ffffe3},
+ {0x0000d370, 0x3fffffe3},
+ {0x0000d374, 0x57ffffe3},
+ {0x0000d378, 0x5fffffe2},
+ {0x0000d37c, 0x7fffffe2},
+ {0x0000d380, 0x7f3c7bba},
+ {0x0000d384, 0xf3307ff0},
+ {0x0000a388, 0x0c000000},
+ {0x0000a38c, 0x20202020},
+ {0x0000a390, 0x20202020},
+ {0x0000a394, 0x1ce739ce},
+ {0x0000a398, 0x000001ce},
+ {0x0000a39c, 0x00000001},
+ {0x0000a3a0, 0x00000000},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0x00000000},
+ {0x0000a3ac, 0x00000000},
+ {0x0000a3b0, 0x00000000},
+ {0x0000a3b4, 0x00000000},
+ {0x0000a3b8, 0x00000000},
+ {0x0000a3bc, 0x00000000},
+ {0x0000a3c0, 0x00000000},
+ {0x0000a3c4, 0x00000000},
+ {0x0000a3c8, 0x00000246},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3dc, 0x1ce739ce},
+ {0x0000a3e0, 0x000001ce},
+};
+
+static const u32 ar5416Bank0_9100[][2] = {
+ /* Addr allmodes */
+ {0x000098b0, 0x1e5795e5},
+ {0x000098e0, 0x02008020},
+};
+
+static const u32 ar5416BB_RfGain_9100[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x00009a00, 0x00000000, 0x00000000},
+ {0x00009a04, 0x00000040, 0x00000040},
+ {0x00009a08, 0x00000080, 0x00000080},
+ {0x00009a0c, 0x000001a1, 0x00000141},
+ {0x00009a10, 0x000001e1, 0x00000181},
+ {0x00009a14, 0x00000021, 0x000001c1},
+ {0x00009a18, 0x00000061, 0x00000001},
+ {0x00009a1c, 0x00000168, 0x00000041},
+ {0x00009a20, 0x000001a8, 0x000001a8},
+ {0x00009a24, 0x000001e8, 0x000001e8},
+ {0x00009a28, 0x00000028, 0x00000028},
+ {0x00009a2c, 0x00000068, 0x00000068},
+ {0x00009a30, 0x00000189, 0x000000a8},
+ {0x00009a34, 0x000001c9, 0x00000169},
+ {0x00009a38, 0x00000009, 0x000001a9},
+ {0x00009a3c, 0x00000049, 0x000001e9},
+ {0x00009a40, 0x00000089, 0x00000029},
+ {0x00009a44, 0x00000170, 0x00000069},
+ {0x00009a48, 0x000001b0, 0x00000190},
+ {0x00009a4c, 0x000001f0, 0x000001d0},
+ {0x00009a50, 0x00000030, 0x00000010},
+ {0x00009a54, 0x00000070, 0x00000050},
+ {0x00009a58, 0x00000191, 0x00000090},
+ {0x00009a5c, 0x000001d1, 0x00000151},
+ {0x00009a60, 0x00000011, 0x00000191},
+ {0x00009a64, 0x00000051, 0x000001d1},
+ {0x00009a68, 0x00000091, 0x00000011},
+ {0x00009a6c, 0x000001b8, 0x00000051},
+ {0x00009a70, 0x000001f8, 0x00000198},
+ {0x00009a74, 0x00000038, 0x000001d8},
+ {0x00009a78, 0x00000078, 0x00000018},
+ {0x00009a7c, 0x00000199, 0x00000058},
+ {0x00009a80, 0x000001d9, 0x00000098},
+ {0x00009a84, 0x00000019, 0x00000159},
+ {0x00009a88, 0x00000059, 0x00000199},
+ {0x00009a8c, 0x00000099, 0x000001d9},
+ {0x00009a90, 0x000000d9, 0x00000019},
+ {0x00009a94, 0x000000f9, 0x00000059},
+ {0x00009a98, 0x000000f9, 0x00000099},
+ {0x00009a9c, 0x000000f9, 0x000000d9},
+ {0x00009aa0, 0x000000f9, 0x000000f9},
+ {0x00009aa4, 0x000000f9, 0x000000f9},
+ {0x00009aa8, 0x000000f9, 0x000000f9},
+ {0x00009aac, 0x000000f9, 0x000000f9},
+ {0x00009ab0, 0x000000f9, 0x000000f9},
+ {0x00009ab4, 0x000000f9, 0x000000f9},
+ {0x00009ab8, 0x000000f9, 0x000000f9},
+ {0x00009abc, 0x000000f9, 0x000000f9},
+ {0x00009ac0, 0x000000f9, 0x000000f9},
+ {0x00009ac4, 0x000000f9, 0x000000f9},
+ {0x00009ac8, 0x000000f9, 0x000000f9},
+ {0x00009acc, 0x000000f9, 0x000000f9},
+ {0x00009ad0, 0x000000f9, 0x000000f9},
+ {0x00009ad4, 0x000000f9, 0x000000f9},
+ {0x00009ad8, 0x000000f9, 0x000000f9},
+ {0x00009adc, 0x000000f9, 0x000000f9},
+ {0x00009ae0, 0x000000f9, 0x000000f9},
+ {0x00009ae4, 0x000000f9, 0x000000f9},
+ {0x00009ae8, 0x000000f9, 0x000000f9},
+ {0x00009aec, 0x000000f9, 0x000000f9},
+ {0x00009af0, 0x000000f9, 0x000000f9},
+ {0x00009af4, 0x000000f9, 0x000000f9},
+ {0x00009af8, 0x000000f9, 0x000000f9},
+ {0x00009afc, 0x000000f9, 0x000000f9},
+};
+
+static const u32 ar5416Bank1_9100[][2] = {
+ /* Addr allmodes */
+ {0x000098b0, 0x02108421},
+ {0x000098ec, 0x00000008},
+};
+
+static const u32 ar5416Bank2_9100[][2] = {
+ /* Addr allmodes */
+ {0x000098b0, 0x0e73ff17},
+ {0x000098e0, 0x00000420},
+};
+
+static const u32 ar5416Bank3_9100[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x000098f0, 0x01400018, 0x01c00018},
+};
+
+static const u32 ar5416Bank6_9100[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00e00000, 0x00e00000},
+ {0x0000989c, 0x005e0000, 0x005e0000},
+ {0x0000989c, 0x00120000, 0x00120000},
+ {0x0000989c, 0x00620000, 0x00620000},
+ {0x0000989c, 0x00020000, 0x00020000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x005f0000, 0x005f0000},
+ {0x0000989c, 0x00870000, 0x00870000},
+ {0x0000989c, 0x00f90000, 0x00f90000},
+ {0x0000989c, 0x007b0000, 0x007b0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00f50000, 0x00f50000},
+ {0x0000989c, 0x00dc0000, 0x00dc0000},
+ {0x0000989c, 0x00110000, 0x00110000},
+ {0x0000989c, 0x006100a8, 0x006100a8},
+ {0x0000989c, 0x004210a2, 0x004210a2},
+ {0x0000989c, 0x0014000f, 0x0014000f},
+ {0x0000989c, 0x00c40002, 0x00c40002},
+ {0x0000989c, 0x003000f2, 0x003000f2},
+ {0x0000989c, 0x00440016, 0x00440016},
+ {0x0000989c, 0x00410040, 0x00410040},
+ {0x0000989c, 0x000180d6, 0x000180d6},
+ {0x0000989c, 0x0000c0aa, 0x0000c0aa},
+ {0x0000989c, 0x000000b1, 0x000000b1},
+ {0x0000989c, 0x00002000, 0x00002000},
+ {0x0000989c, 0x000000d4, 0x000000d4},
+ {0x000098d0, 0x0000000f, 0x0010000f},
+};
+
+static const u32 ar5416Bank6TPC_9100[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00e00000, 0x00e00000},
+ {0x0000989c, 0x005e0000, 0x005e0000},
+ {0x0000989c, 0x00120000, 0x00120000},
+ {0x0000989c, 0x00620000, 0x00620000},
+ {0x0000989c, 0x00020000, 0x00020000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x40ff0000, 0x40ff0000},
+ {0x0000989c, 0x005f0000, 0x005f0000},
+ {0x0000989c, 0x00870000, 0x00870000},
+ {0x0000989c, 0x00f90000, 0x00f90000},
+ {0x0000989c, 0x007b0000, 0x007b0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00f50000, 0x00f50000},
+ {0x0000989c, 0x00dc0000, 0x00dc0000},
+ {0x0000989c, 0x00110000, 0x00110000},
+ {0x0000989c, 0x006100a8, 0x006100a8},
+ {0x0000989c, 0x00423022, 0x00423022},
+ {0x0000989c, 0x2014008f, 0x2014008f},
+ {0x0000989c, 0x00c40002, 0x00c40002},
+ {0x0000989c, 0x003000f2, 0x003000f2},
+ {0x0000989c, 0x00440016, 0x00440016},
+ {0x0000989c, 0x00410040, 0x00410040},
+ {0x0000989c, 0x0001805e, 0x0001805e},
+ {0x0000989c, 0x0000c0ab, 0x0000c0ab},
+ {0x0000989c, 0x000000e1, 0x000000e1},
+ {0x0000989c, 0x00007080, 0x00007080},
+ {0x0000989c, 0x000000d4, 0x000000d4},
+ {0x000098d0, 0x0000000f, 0x0010000f},
+};
+
+static const u32 ar5416Bank7_9100[][2] = {
+ /* Addr allmodes */
+ {0x0000989c, 0x00000500},
+ {0x0000989c, 0x00000800},
+ {0x000098cc, 0x0000000e},
+};
+
+static const u32 ar5416Addac_9100[][2] = {
+ /* Addr allmodes */
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000010},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x000000c0},
+ {0x0000989c, 0x00000015},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x000098cc, 0x00000000},
+};
+
+static const u32 ar5416Modes_9160[][6] = {
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
+ {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
+ {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
+ {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+ {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+ {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+ {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2},
+ {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+ {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
+ {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
+ {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
+ {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
+ {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
+ {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
+ {0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+ {0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+ {0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+ {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
+ {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce},
+ {0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00},
+ {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+ {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
+ {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
+ {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
+ {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
+ {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
+ {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+ {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
+ {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
+ {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
+ {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
+ {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
+ {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
+ {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
+ {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
+ {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
+ {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar5416Common_9160[][2] = {
+ /* Addr allmodes */
+ {0x0000000c, 0x00000000},
+ {0x00000030, 0x00020015},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000008},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00000054, 0x0000001f},
+ {0x00000800, 0x00000000},
+ {0x00000804, 0x00000000},
+ {0x00000808, 0x00000000},
+ {0x0000080c, 0x00000000},
+ {0x00000810, 0x00000000},
+ {0x00000814, 0x00000000},
+ {0x00000818, 0x00000000},
+ {0x0000081c, 0x00000000},
+ {0x00000820, 0x00000000},
+ {0x00000824, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x00001230, 0x00000000},
+ {0x00001270, 0x00000000},
+ {0x00001038, 0x00000000},
+ {0x00001078, 0x00000000},
+ {0x000010b8, 0x00000000},
+ {0x000010f8, 0x00000000},
+ {0x00001138, 0x00000000},
+ {0x00001178, 0x00000000},
+ {0x000011b8, 0x00000000},
+ {0x000011f8, 0x00000000},
+ {0x00001238, 0x00000000},
+ {0x00001278, 0x00000000},
+ {0x000012b8, 0x00000000},
+ {0x000012f8, 0x00000000},
+ {0x00001338, 0x00000000},
+ {0x00001378, 0x00000000},
+ {0x000013b8, 0x00000000},
+ {0x000013f8, 0x00000000},
+ {0x00001438, 0x00000000},
+ {0x00001478, 0x00000000},
+ {0x000014b8, 0x00000000},
+ {0x000014f8, 0x00000000},
+ {0x00001538, 0x00000000},
+ {0x00001578, 0x00000000},
+ {0x000015b8, 0x00000000},
+ {0x000015f8, 0x00000000},
+ {0x00001638, 0x00000000},
+ {0x00001678, 0x00000000},
+ {0x000016b8, 0x00000000},
+ {0x000016f8, 0x00000000},
+ {0x00001738, 0x00000000},
+ {0x00001778, 0x00000000},
+ {0x000017b8, 0x00000000},
+ {0x000017f8, 0x00000000},
+ {0x0000103c, 0x00000000},
+ {0x0000107c, 0x00000000},
+ {0x000010bc, 0x00000000},
+ {0x000010fc, 0x00000000},
+ {0x0000113c, 0x00000000},
+ {0x0000117c, 0x00000000},
+ {0x000011bc, 0x00000000},
+ {0x000011fc, 0x00000000},
+ {0x0000123c, 0x00000000},
+ {0x0000127c, 0x00000000},
+ {0x000012bc, 0x00000000},
+ {0x000012fc, 0x00000000},
+ {0x0000133c, 0x00000000},
+ {0x0000137c, 0x00000000},
+ {0x000013bc, 0x00000000},
+ {0x000013fc, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00004030, 0x00000002},
+ {0x0000403c, 0x00000002},
+ {0x00007010, 0x00000020},
+ {0x00007038, 0x000004c2},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000700},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00000000},
+ {0x00008048, 0x40000000},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x000080c0, 0x2a82301a},
+ {0x000080c4, 0x05dc01e0},
+ {0x000080c8, 0x1f402710},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00001e00},
+ {0x000080d4, 0x00000000},
+ {0x000080d8, 0x00400000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x003f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080f8, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00020000},
+ {0x00008104, 0x00000001},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000168},
+ {0x00008118, 0x000100aa},
+ {0x0000811c, 0x00003210},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x00000000},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x32143320},
+ {0x00008174, 0xfaa4fa50},
+ {0x00008178, 0x00000100},
+ {0x0000817c, 0x00000000},
+ {0x000081c4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008200, 0x00000000},
+ {0x00008204, 0x00000000},
+ {0x00008208, 0x00000000},
+ {0x0000820c, 0x00000000},
+ {0x00008210, 0x00000000},
+ {0x00008214, 0x00000000},
+ {0x00008218, 0x00000000},
+ {0x0000821c, 0x00000000},
+ {0x00008220, 0x00000000},
+ {0x00008224, 0x00000000},
+ {0x00008228, 0x00000000},
+ {0x0000822c, 0x00000000},
+ {0x00008230, 0x00000000},
+ {0x00008234, 0x00000000},
+ {0x00008238, 0x00000000},
+ {0x0000823c, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f400},
+ {0x00008248, 0x00000100},
+ {0x0000824c, 0x0001e800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x400000ff},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x88a00010},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000000},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x00000000},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x00008300, 0x00000000},
+ {0x00008304, 0x00000000},
+ {0x00008308, 0x00000000},
+ {0x0000830c, 0x00000000},
+ {0x00008310, 0x00000000},
+ {0x00008314, 0x00000000},
+ {0x00008318, 0x00000000},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000007},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000e00},
+ {0x00008338, 0x00ff0000},
+ {0x0000833c, 0x00000000},
+ {0x00008340, 0x000107ff},
+ {0x00009808, 0x00000000},
+ {0x0000980c, 0xad848e19},
+ {0x00009810, 0x7d14e000},
+ {0x00009814, 0x9c0a9f6b},
+ {0x0000981c, 0x00000000},
+ {0x0000982c, 0x0000a000},
+ {0x00009830, 0x00000000},
+ {0x0000983c, 0x00200400},
+ {0x00009840, 0x206a01ae},
+ {0x0000984c, 0x1284233c},
+ {0x00009854, 0x00000859},
+ {0x00009900, 0x00000000},
+ {0x00009904, 0x00000000},
+ {0x00009908, 0x00000000},
+ {0x0000990c, 0x00000000},
+ {0x0000991c, 0x10000fff},
+ {0x00009920, 0x05100000},
+ {0x0000a920, 0x05100000},
+ {0x0000b920, 0x05100000},
+ {0x00009928, 0x00000001},
+ {0x0000992c, 0x00000004},
+ {0x00009934, 0x1e1f2022},
+ {0x00009938, 0x0a0b0c0d},
+ {0x0000993c, 0x00000000},
+ {0x00009948, 0x9280b212},
+ {0x0000994c, 0x00020028},
+ {0x00009954, 0x5f3ca3de},
+ {0x00009958, 0x2108ecff},
+ {0x00009940, 0x00750604},
+ {0x0000c95c, 0x004b6a8e},
+ {0x00009970, 0x190fb515},
+ {0x00009974, 0x00000000},
+ {0x00009978, 0x00000001},
+ {0x0000997c, 0x00000000},
+ {0x00009980, 0x00000000},
+ {0x00009984, 0x00000000},
+ {0x00009988, 0x00000000},
+ {0x0000998c, 0x00000000},
+ {0x00009990, 0x00000000},
+ {0x00009994, 0x00000000},
+ {0x00009998, 0x00000000},
+ {0x0000999c, 0x00000000},
+ {0x000099a0, 0x00000000},
+ {0x000099a4, 0x00000001},
+ {0x000099a8, 0x201fff00},
+ {0x000099ac, 0x006f0000},
+ {0x000099b0, 0x03051000},
+ {0x000099dc, 0x00000000},
+ {0x000099e0, 0x00000200},
+ {0x000099e4, 0xaaaaaaaa},
+ {0x000099e8, 0x3c466478},
+ {0x000099ec, 0x0cc80caa},
+ {0x000099fc, 0x00001042},
+ {0x00009b00, 0x00000000},
+ {0x00009b04, 0x00000001},
+ {0x00009b08, 0x00000002},
+ {0x00009b0c, 0x00000003},
+ {0x00009b10, 0x00000004},
+ {0x00009b14, 0x00000005},
+ {0x00009b18, 0x00000008},
+ {0x00009b1c, 0x00000009},
+ {0x00009b20, 0x0000000a},
+ {0x00009b24, 0x0000000b},
+ {0x00009b28, 0x0000000c},
+ {0x00009b2c, 0x0000000d},
+ {0x00009b30, 0x00000010},
+ {0x00009b34, 0x00000011},
+ {0x00009b38, 0x00000012},
+ {0x00009b3c, 0x00000013},
+ {0x00009b40, 0x00000014},
+ {0x00009b44, 0x00000015},
+ {0x00009b48, 0x00000018},
+ {0x00009b4c, 0x00000019},
+ {0x00009b50, 0x0000001a},
+ {0x00009b54, 0x0000001b},
+ {0x00009b58, 0x0000001c},
+ {0x00009b5c, 0x0000001d},
+ {0x00009b60, 0x00000020},
+ {0x00009b64, 0x00000021},
+ {0x00009b68, 0x00000022},
+ {0x00009b6c, 0x00000023},
+ {0x00009b70, 0x00000024},
+ {0x00009b74, 0x00000025},
+ {0x00009b78, 0x00000028},
+ {0x00009b7c, 0x00000029},
+ {0x00009b80, 0x0000002a},
+ {0x00009b84, 0x0000002b},
+ {0x00009b88, 0x0000002c},
+ {0x00009b8c, 0x0000002d},
+ {0x00009b90, 0x00000030},
+ {0x00009b94, 0x00000031},
+ {0x00009b98, 0x00000032},
+ {0x00009b9c, 0x00000033},
+ {0x00009ba0, 0x00000034},
+ {0x00009ba4, 0x00000035},
+ {0x00009ba8, 0x00000035},
+ {0x00009bac, 0x00000035},
+ {0x00009bb0, 0x00000035},
+ {0x00009bb4, 0x00000035},
+ {0x00009bb8, 0x00000035},
+ {0x00009bbc, 0x00000035},
+ {0x00009bc0, 0x00000035},
+ {0x00009bc4, 0x00000035},
+ {0x00009bc8, 0x00000035},
+ {0x00009bcc, 0x00000035},
+ {0x00009bd0, 0x00000035},
+ {0x00009bd4, 0x00000035},
+ {0x00009bd8, 0x00000035},
+ {0x00009bdc, 0x00000035},
+ {0x00009be0, 0x00000035},
+ {0x00009be4, 0x00000035},
+ {0x00009be8, 0x00000035},
+ {0x00009bec, 0x00000035},
+ {0x00009bf0, 0x00000035},
+ {0x00009bf4, 0x00000035},
+ {0x00009bf8, 0x00000010},
+ {0x00009bfc, 0x0000001a},
+ {0x0000a210, 0x40806333},
+ {0x0000a214, 0x00106c10},
+ {0x0000a218, 0x009c4060},
+ {0x0000a220, 0x018830c6},
+ {0x0000a224, 0x00000400},
+ {0x0000a228, 0x001a0bb5},
+ {0x0000a22c, 0x00000000},
+ {0x0000a234, 0x20202020},
+ {0x0000a238, 0x20202020},
+ {0x0000a23c, 0x13c889af},
+ {0x0000a240, 0x38490a20},
+ {0x0000a244, 0x00007bb6},
+ {0x0000a248, 0x0fff3ffc},
+ {0x0000a24c, 0x00000001},
+ {0x0000a250, 0x0000e000},
+ {0x0000a254, 0x00000000},
+ {0x0000a258, 0x0cc75380},
+ {0x0000a25c, 0x0f0f0f01},
+ {0x0000a260, 0xdfa91f01},
+ {0x0000a268, 0x00000001},
+ {0x0000a26c, 0x0e79e5c6},
+ {0x0000b26c, 0x0e79e5c6},
+ {0x0000c26c, 0x0e79e5c6},
+ {0x0000d270, 0x00820820},
+ {0x0000a278, 0x1ce739ce},
+ {0x0000a27c, 0x050701ce},
+ {0x0000a338, 0x00000000},
+ {0x0000a33c, 0x00000000},
+ {0x0000a340, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a348, 0x3fffffff},
+ {0x0000a34c, 0x3fffffff},
+ {0x0000a350, 0x3fffffff},
+ {0x0000a354, 0x0003ffff},
+ {0x0000a358, 0x79bfaa03},
+ {0x0000d35c, 0x07ffffef},
+ {0x0000d360, 0x0fffffe7},
+ {0x0000d364, 0x17ffffe5},
+ {0x0000d368, 0x1fffffe4},
+ {0x0000d36c, 0x37ffffe3},
+ {0x0000d370, 0x3fffffe3},
+ {0x0000d374, 0x57ffffe3},
+ {0x0000d378, 0x5fffffe2},
+ {0x0000d37c, 0x7fffffe2},
+ {0x0000d380, 0x7f3c7bba},
+ {0x0000d384, 0xf3307ff0},
+ {0x0000a388, 0x0c000000},
+ {0x0000a38c, 0x20202020},
+ {0x0000a390, 0x20202020},
+ {0x0000a394, 0x1ce739ce},
+ {0x0000a398, 0x000001ce},
+ {0x0000a39c, 0x00000001},
+ {0x0000a3a0, 0x00000000},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0x00000000},
+ {0x0000a3ac, 0x00000000},
+ {0x0000a3b0, 0x00000000},
+ {0x0000a3b4, 0x00000000},
+ {0x0000a3b8, 0x00000000},
+ {0x0000a3bc, 0x00000000},
+ {0x0000a3c0, 0x00000000},
+ {0x0000a3c4, 0x00000000},
+ {0x0000a3c8, 0x00000246},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3dc, 0x1ce739ce},
+ {0x0000a3e0, 0x000001ce},
+};
+
+static const u32 ar5416Bank0_9160[][2] = {
+ /* Addr allmodes */
+ {0x000098b0, 0x1e5795e5},
+ {0x000098e0, 0x02008020},
+};
+
+static const u32 ar5416BB_RfGain_9160[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x00009a00, 0x00000000, 0x00000000},
+ {0x00009a04, 0x00000040, 0x00000040},
+ {0x00009a08, 0x00000080, 0x00000080},
+ {0x00009a0c, 0x000001a1, 0x00000141},
+ {0x00009a10, 0x000001e1, 0x00000181},
+ {0x00009a14, 0x00000021, 0x000001c1},
+ {0x00009a18, 0x00000061, 0x00000001},
+ {0x00009a1c, 0x00000168, 0x00000041},
+ {0x00009a20, 0x000001a8, 0x000001a8},
+ {0x00009a24, 0x000001e8, 0x000001e8},
+ {0x00009a28, 0x00000028, 0x00000028},
+ {0x00009a2c, 0x00000068, 0x00000068},
+ {0x00009a30, 0x00000189, 0x000000a8},
+ {0x00009a34, 0x000001c9, 0x00000169},
+ {0x00009a38, 0x00000009, 0x000001a9},
+ {0x00009a3c, 0x00000049, 0x000001e9},
+ {0x00009a40, 0x00000089, 0x00000029},
+ {0x00009a44, 0x00000170, 0x00000069},
+ {0x00009a48, 0x000001b0, 0x00000190},
+ {0x00009a4c, 0x000001f0, 0x000001d0},
+ {0x00009a50, 0x00000030, 0x00000010},
+ {0x00009a54, 0x00000070, 0x00000050},
+ {0x00009a58, 0x00000191, 0x00000090},
+ {0x00009a5c, 0x000001d1, 0x00000151},
+ {0x00009a60, 0x00000011, 0x00000191},
+ {0x00009a64, 0x00000051, 0x000001d1},
+ {0x00009a68, 0x00000091, 0x00000011},
+ {0x00009a6c, 0x000001b8, 0x00000051},
+ {0x00009a70, 0x000001f8, 0x00000198},
+ {0x00009a74, 0x00000038, 0x000001d8},
+ {0x00009a78, 0x00000078, 0x00000018},
+ {0x00009a7c, 0x00000199, 0x00000058},
+ {0x00009a80, 0x000001d9, 0x00000098},
+ {0x00009a84, 0x00000019, 0x00000159},
+ {0x00009a88, 0x00000059, 0x00000199},
+ {0x00009a8c, 0x00000099, 0x000001d9},
+ {0x00009a90, 0x000000d9, 0x00000019},
+ {0x00009a94, 0x000000f9, 0x00000059},
+ {0x00009a98, 0x000000f9, 0x00000099},
+ {0x00009a9c, 0x000000f9, 0x000000d9},
+ {0x00009aa0, 0x000000f9, 0x000000f9},
+ {0x00009aa4, 0x000000f9, 0x000000f9},
+ {0x00009aa8, 0x000000f9, 0x000000f9},
+ {0x00009aac, 0x000000f9, 0x000000f9},
+ {0x00009ab0, 0x000000f9, 0x000000f9},
+ {0x00009ab4, 0x000000f9, 0x000000f9},
+ {0x00009ab8, 0x000000f9, 0x000000f9},
+ {0x00009abc, 0x000000f9, 0x000000f9},
+ {0x00009ac0, 0x000000f9, 0x000000f9},
+ {0x00009ac4, 0x000000f9, 0x000000f9},
+ {0x00009ac8, 0x000000f9, 0x000000f9},
+ {0x00009acc, 0x000000f9, 0x000000f9},
+ {0x00009ad0, 0x000000f9, 0x000000f9},
+ {0x00009ad4, 0x000000f9, 0x000000f9},
+ {0x00009ad8, 0x000000f9, 0x000000f9},
+ {0x00009adc, 0x000000f9, 0x000000f9},
+ {0x00009ae0, 0x000000f9, 0x000000f9},
+ {0x00009ae4, 0x000000f9, 0x000000f9},
+ {0x00009ae8, 0x000000f9, 0x000000f9},
+ {0x00009aec, 0x000000f9, 0x000000f9},
+ {0x00009af0, 0x000000f9, 0x000000f9},
+ {0x00009af4, 0x000000f9, 0x000000f9},
+ {0x00009af8, 0x000000f9, 0x000000f9},
+ {0x00009afc, 0x000000f9, 0x000000f9},
+};
+
+static const u32 ar5416Bank1_9160[][2] = {
+ /* Addr allmodes */
+ {0x000098b0, 0x02108421},
+ {0x000098ec, 0x00000008},
+};
+
+static const u32 ar5416Bank2_9160[][2] = {
+ /* Addr allmodes */
+ {0x000098b0, 0x0e73ff17},
+ {0x000098e0, 0x00000420},
+};
+
+static const u32 ar5416Bank3_9160[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x000098f0, 0x01400018, 0x01c00018},
+};
+
+static const u32 ar5416Bank6_9160[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00e00000, 0x00e00000},
+ {0x0000989c, 0x005e0000, 0x005e0000},
+ {0x0000989c, 0x00120000, 0x00120000},
+ {0x0000989c, 0x00620000, 0x00620000},
+ {0x0000989c, 0x00020000, 0x00020000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x40ff0000, 0x40ff0000},
+ {0x0000989c, 0x005f0000, 0x005f0000},
+ {0x0000989c, 0x00870000, 0x00870000},
+ {0x0000989c, 0x00f90000, 0x00f90000},
+ {0x0000989c, 0x007b0000, 0x007b0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00f50000, 0x00f50000},
+ {0x0000989c, 0x00dc0000, 0x00dc0000},
+ {0x0000989c, 0x00110000, 0x00110000},
+ {0x0000989c, 0x006100a8, 0x006100a8},
+ {0x0000989c, 0x004210a2, 0x004210a2},
+ {0x0000989c, 0x0014008f, 0x0014008f},
+ {0x0000989c, 0x00c40003, 0x00c40003},
+ {0x0000989c, 0x003000f2, 0x003000f2},
+ {0x0000989c, 0x00440016, 0x00440016},
+ {0x0000989c, 0x00410040, 0x00410040},
+ {0x0000989c, 0x0001805e, 0x0001805e},
+ {0x0000989c, 0x0000c0ab, 0x0000c0ab},
+ {0x0000989c, 0x000000f1, 0x000000f1},
+ {0x0000989c, 0x00002081, 0x00002081},
+ {0x0000989c, 0x000000d4, 0x000000d4},
+ {0x000098d0, 0x0000000f, 0x0010000f},
+};
+
+static const u32 ar5416Bank6TPC_9160[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00000000, 0x00000000},
+ {0x0000989c, 0x00e00000, 0x00e00000},
+ {0x0000989c, 0x005e0000, 0x005e0000},
+ {0x0000989c, 0x00120000, 0x00120000},
+ {0x0000989c, 0x00620000, 0x00620000},
+ {0x0000989c, 0x00020000, 0x00020000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x40ff0000, 0x40ff0000},
+ {0x0000989c, 0x005f0000, 0x005f0000},
+ {0x0000989c, 0x00870000, 0x00870000},
+ {0x0000989c, 0x00f90000, 0x00f90000},
+ {0x0000989c, 0x007b0000, 0x007b0000},
+ {0x0000989c, 0x00ff0000, 0x00ff0000},
+ {0x0000989c, 0x00f50000, 0x00f50000},
+ {0x0000989c, 0x00dc0000, 0x00dc0000},
+ {0x0000989c, 0x00110000, 0x00110000},
+ {0x0000989c, 0x006100a8, 0x006100a8},
+ {0x0000989c, 0x00423022, 0x00423022},
+ {0x0000989c, 0x2014008f, 0x2014008f},
+ {0x0000989c, 0x00c40002, 0x00c40002},
+ {0x0000989c, 0x003000f2, 0x003000f2},
+ {0x0000989c, 0x00440016, 0x00440016},
+ {0x0000989c, 0x00410040, 0x00410040},
+ {0x0000989c, 0x0001805e, 0x0001805e},
+ {0x0000989c, 0x0000c0ab, 0x0000c0ab},
+ {0x0000989c, 0x000000e1, 0x000000e1},
+ {0x0000989c, 0x00007080, 0x00007080},
+ {0x0000989c, 0x000000d4, 0x000000d4},
+ {0x000098d0, 0x0000000f, 0x0010000f},
+};
+
+static const u32 ar5416Bank7_9160[][2] = {
+ /* Addr allmodes */
+ {0x0000989c, 0x00000500},
+ {0x0000989c, 0x00000800},
+ {0x000098cc, 0x0000000e},
+};
+
+static const u32 ar5416Addac_9160[][2] = {
+ /* Addr allmodes */
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x000000c0},
+ {0x0000989c, 0x00000018},
+ {0x0000989c, 0x00000004},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x000000c0},
+ {0x0000989c, 0x00000019},
+ {0x0000989c, 0x00000004},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000004},
+ {0x0000989c, 0x00000003},
+ {0x0000989c, 0x00000008},
+ {0x0000989c, 0x00000000},
+ {0x000098cc, 0x00000000},
+};
+
+static const u32 ar5416Addac_9160_1_1[][2] = {
+ /* Addr allmodes */
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x000000c0},
+ {0x0000989c, 0x00000018},
+ {0x0000989c, 0x00000004},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x000000c0},
+ {0x0000989c, 0x00000019},
+ {0x0000989c, 0x00000004},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x0000989c, 0x00000000},
+ {0x000098cc, 0x00000000},
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9002_initvals.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9002_initvals.h
new file mode 100644
index 00000000..dd121513
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9002_initvals.h
@@ -0,0 +1,3264 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+static const u32 ar9280Modes_9280_2[][6] = {
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
+ {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
+ {0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2},
+ {0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
+ {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
+ {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b, 0x00000016},
+ {0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
+ {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010},
+ {0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
+ {0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
+ {0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210},
+ {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce},
+ {0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c},
+ {0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00},
+ {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444},
+ {0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019},
+ {0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
+ {0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000, 0x13c88000},
+ {0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000},
+ {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
+ {0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000, 0x0c000000},
+ {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000},
+};
+
+static const u32 ar9280Common_9280_2[][2] = {
+ /* Addr allmodes */
+ {0x0000000c, 0x00000000},
+ {0x00000030, 0x00020015},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000008},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00000054, 0x0000001f},
+ {0x00000800, 0x00000000},
+ {0x00000804, 0x00000000},
+ {0x00000808, 0x00000000},
+ {0x0000080c, 0x00000000},
+ {0x00000810, 0x00000000},
+ {0x00000814, 0x00000000},
+ {0x00000818, 0x00000000},
+ {0x0000081c, 0x00000000},
+ {0x00000820, 0x00000000},
+ {0x00000824, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x00001230, 0x00000000},
+ {0x00001270, 0x00000000},
+ {0x00001038, 0x00000000},
+ {0x00001078, 0x00000000},
+ {0x000010b8, 0x00000000},
+ {0x000010f8, 0x00000000},
+ {0x00001138, 0x00000000},
+ {0x00001178, 0x00000000},
+ {0x000011b8, 0x00000000},
+ {0x000011f8, 0x00000000},
+ {0x00001238, 0x00000000},
+ {0x00001278, 0x00000000},
+ {0x000012b8, 0x00000000},
+ {0x000012f8, 0x00000000},
+ {0x00001338, 0x00000000},
+ {0x00001378, 0x00000000},
+ {0x000013b8, 0x00000000},
+ {0x000013f8, 0x00000000},
+ {0x00001438, 0x00000000},
+ {0x00001478, 0x00000000},
+ {0x000014b8, 0x00000000},
+ {0x000014f8, 0x00000000},
+ {0x00001538, 0x00000000},
+ {0x00001578, 0x00000000},
+ {0x000015b8, 0x00000000},
+ {0x000015f8, 0x00000000},
+ {0x00001638, 0x00000000},
+ {0x00001678, 0x00000000},
+ {0x000016b8, 0x00000000},
+ {0x000016f8, 0x00000000},
+ {0x00001738, 0x00000000},
+ {0x00001778, 0x00000000},
+ {0x000017b8, 0x00000000},
+ {0x000017f8, 0x00000000},
+ {0x0000103c, 0x00000000},
+ {0x0000107c, 0x00000000},
+ {0x000010bc, 0x00000000},
+ {0x000010fc, 0x00000000},
+ {0x0000113c, 0x00000000},
+ {0x0000117c, 0x00000000},
+ {0x000011bc, 0x00000000},
+ {0x000011fc, 0x00000000},
+ {0x0000123c, 0x00000000},
+ {0x0000127c, 0x00000000},
+ {0x000012bc, 0x00000000},
+ {0x000012fc, 0x00000000},
+ {0x0000133c, 0x00000000},
+ {0x0000137c, 0x00000000},
+ {0x000013bc, 0x00000000},
+ {0x000013fc, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00004030, 0x00000002},
+ {0x0000403c, 0x00000002},
+ {0x00004024, 0x0000001f},
+ {0x00004060, 0x00000000},
+ {0x00004064, 0x00000000},
+ {0x00007010, 0x00000033},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000700},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00000000},
+ {0x00008048, 0x40000000},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x00008070, 0x00000000},
+ {0x000080c0, 0x2a80001a},
+ {0x000080c4, 0x05dc01e0},
+ {0x000080c8, 0x1f402710},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00001e00},
+ {0x000080d4, 0x00000000},
+ {0x000080d8, 0x00400000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x003f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080f8, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00020000},
+ {0x00008104, 0x00000001},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000168},
+ {0x00008118, 0x000100aa},
+ {0x0000811c, 0x00003210},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x00000000},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x32143320},
+ {0x00008174, 0xfaa4fa50},
+ {0x00008178, 0x00000100},
+ {0x0000817c, 0x00000000},
+ {0x000081c0, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008200, 0x00000000},
+ {0x00008204, 0x00000000},
+ {0x00008208, 0x00000000},
+ {0x0000820c, 0x00000000},
+ {0x00008210, 0x00000000},
+ {0x00008214, 0x00000000},
+ {0x00008218, 0x00000000},
+ {0x0000821c, 0x00000000},
+ {0x00008220, 0x00000000},
+ {0x00008224, 0x00000000},
+ {0x00008228, 0x00000000},
+ {0x0000822c, 0x00000000},
+ {0x00008230, 0x00000000},
+ {0x00008234, 0x00000000},
+ {0x00008238, 0x00000000},
+ {0x0000823c, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f400},
+ {0x00008248, 0x00000100},
+ {0x0000824c, 0x0001e800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x400000ff},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x88a00010},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000000},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x00000000},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x0000829c, 0x00000000},
+ {0x00008300, 0x00000040},
+ {0x00008314, 0x00000000},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000007},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000e00},
+ {0x00008338, 0x00ff0000},
+ {0x0000833c, 0x00000000},
+ {0x00008340, 0x000107ff},
+ {0x00008344, 0x00481043},
+ {0x00009808, 0x00000000},
+ {0x0000980c, 0xafa68e30},
+ {0x00009810, 0xfd14e000},
+ {0x00009814, 0x9c0a9f6b},
+ {0x0000981c, 0x00000000},
+ {0x0000982c, 0x0000a000},
+ {0x00009830, 0x00000000},
+ {0x0000983c, 0x00200400},
+ {0x0000984c, 0x0040233c},
+ {0x0000a84c, 0x0040233c},
+ {0x00009854, 0x00000044},
+ {0x00009900, 0x00000000},
+ {0x00009904, 0x00000000},
+ {0x00009908, 0x00000000},
+ {0x0000990c, 0x00000000},
+ {0x00009910, 0x01002310},
+ {0x0000991c, 0x10000fff},
+ {0x00009920, 0x04900000},
+ {0x0000a920, 0x04900000},
+ {0x00009928, 0x00000001},
+ {0x0000992c, 0x00000004},
+ {0x00009934, 0x1e1f2022},
+ {0x00009938, 0x0a0b0c0d},
+ {0x0000993c, 0x00000000},
+ {0x00009948, 0x9280c00a},
+ {0x0000994c, 0x00020028},
+ {0x00009954, 0x5f3ca3de},
+ {0x00009958, 0x2108ecff},
+ {0x00009940, 0x14750604},
+ {0x0000c95c, 0x004b6a8e},
+ {0x00009970, 0x190fb514},
+ {0x00009974, 0x00000000},
+ {0x00009978, 0x00000001},
+ {0x0000997c, 0x00000000},
+ {0x00009980, 0x00000000},
+ {0x00009984, 0x00000000},
+ {0x00009988, 0x00000000},
+ {0x0000998c, 0x00000000},
+ {0x00009990, 0x00000000},
+ {0x00009994, 0x00000000},
+ {0x00009998, 0x00000000},
+ {0x0000999c, 0x00000000},
+ {0x000099a0, 0x00000000},
+ {0x000099a4, 0x00000001},
+ {0x000099a8, 0x201fff00},
+ {0x000099ac, 0x006f0000},
+ {0x000099b0, 0x03051000},
+ {0x000099b4, 0x00000820},
+ {0x000099c4, 0x06336f77},
+ {0x000099c8, 0x6af6532f},
+ {0x000099cc, 0x08f186c8},
+ {0x000099d0, 0x00046384},
+ {0x000099d4, 0x00000000},
+ {0x000099d8, 0x00000000},
+ {0x000099dc, 0x00000000},
+ {0x000099e0, 0x00000000},
+ {0x000099e4, 0xaaaaaaaa},
+ {0x000099e8, 0x3c466478},
+ {0x000099ec, 0x0cc80caa},
+ {0x000099f0, 0x00000000},
+ {0x000099fc, 0x00001042},
+ {0x0000a208, 0x803e4788},
+ {0x0000a210, 0x4080a333},
+ {0x0000a214, 0x40206c10},
+ {0x0000a218, 0x009c4060},
+ {0x0000a220, 0x01834061},
+ {0x0000a224, 0x00000400},
+ {0x0000a228, 0x000003b5},
+ {0x0000a22c, 0x233f7180},
+ {0x0000a234, 0x20202020},
+ {0x0000a238, 0x20202020},
+ {0x0000a240, 0x38490a20},
+ {0x0000a244, 0x00007bb6},
+ {0x0000a248, 0x0fff3ffc},
+ {0x0000a24c, 0x00000000},
+ {0x0000a254, 0x00000000},
+ {0x0000a258, 0x0cdbd380},
+ {0x0000a25c, 0x0f0f0f01},
+ {0x0000a260, 0xdfa91f01},
+ {0x0000a268, 0x00000000},
+ {0x0000a26c, 0x0e79e5c6},
+ {0x0000b26c, 0x0e79e5c6},
+ {0x0000d270, 0x00820820},
+ {0x0000a278, 0x1ce739ce},
+ {0x0000d35c, 0x07ffffef},
+ {0x0000d360, 0x0fffffe7},
+ {0x0000d364, 0x17ffffe5},
+ {0x0000d368, 0x1fffffe4},
+ {0x0000d36c, 0x37ffffe3},
+ {0x0000d370, 0x3fffffe3},
+ {0x0000d374, 0x57ffffe3},
+ {0x0000d378, 0x5fffffe2},
+ {0x0000d37c, 0x7fffffe2},
+ {0x0000d380, 0x7f3c7bba},
+ {0x0000d384, 0xf3307ff0},
+ {0x0000a38c, 0x20202020},
+ {0x0000a390, 0x20202020},
+ {0x0000a394, 0x1ce739ce},
+ {0x0000a398, 0x000001ce},
+ {0x0000a39c, 0x00000001},
+ {0x0000a3a0, 0x00000000},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0x00000000},
+ {0x0000a3ac, 0x00000000},
+ {0x0000a3b0, 0x00000000},
+ {0x0000a3b4, 0x00000000},
+ {0x0000a3b8, 0x00000000},
+ {0x0000a3bc, 0x00000000},
+ {0x0000a3c0, 0x00000000},
+ {0x0000a3c4, 0x00000000},
+ {0x0000a3c8, 0x00000246},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3dc, 0x1ce739ce},
+ {0x0000a3e0, 0x000001ce},
+ {0x0000a3e4, 0x00000000},
+ {0x0000a3e8, 0x18c43433},
+ {0x00007800, 0x00040000},
+ {0x00007804, 0xdb005012},
+ {0x00007808, 0x04924914},
+ {0x0000780c, 0x21084210},
+ {0x00007810, 0x6d801300},
+ {0x00007818, 0x07e41000},
+ {0x00007824, 0x00040000},
+ {0x00007828, 0xdb005012},
+ {0x0000782c, 0x04924914},
+ {0x00007830, 0x21084210},
+ {0x00007834, 0x6d801300},
+ {0x0000783c, 0x07e40000},
+ {0x00007848, 0x00100000},
+ {0x0000784c, 0x773f0567},
+ {0x00007850, 0x54214514},
+ {0x00007854, 0x12035828},
+ {0x00007858, 0x9259269a},
+ {0x00007860, 0x52802000},
+ {0x00007864, 0x0a8e370e},
+ {0x00007868, 0xc0102850},
+ {0x0000786c, 0x812d4000},
+ {0x00007870, 0x807ec400},
+ {0x00007874, 0x001b6db0},
+ {0x00007878, 0x00376b63},
+ {0x0000787c, 0x06db6db6},
+ {0x00007880, 0x006d8000},
+ {0x00007884, 0xffeffffe},
+ {0x00007888, 0xffeffffe},
+ {0x0000788c, 0x00010000},
+ {0x00007890, 0x02060aeb},
+ {0x00007898, 0x2a850160},
+};
+
+static const u32 ar9280Modes_fast_clock_9280_2[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x00001030, 0x00000268, 0x000004d0},
+ {0x00001070, 0x0000018c, 0x00000318},
+ {0x000010b0, 0x00000fd0, 0x00001fa0},
+ {0x00008014, 0x044c044c, 0x08980898},
+ {0x0000801c, 0x148ec02b, 0x148ec057},
+ {0x00008318, 0x000044c0, 0x00008980},
+ {0x00009820, 0x02020200, 0x02020200},
+ {0x00009824, 0x01000f0f, 0x01000f0f},
+ {0x00009828, 0x0b020001, 0x0b020001},
+ {0x00009834, 0x00000f0f, 0x00000f0f},
+ {0x00009844, 0x03721821, 0x03721821},
+ {0x00009914, 0x00000898, 0x00001130},
+ {0x00009918, 0x0000000b, 0x00000016},
+};
+
+static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = {
+ {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290},
+ {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300},
+ {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304},
+ {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308},
+ {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c},
+ {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000},
+ {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004},
+ {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008},
+ {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c},
+ {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080},
+ {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084},
+ {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088},
+ {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c},
+ {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100},
+ {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104},
+ {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108},
+ {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c},
+ {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110},
+ {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114},
+ {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180},
+ {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184},
+ {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188},
+ {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c},
+ {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190},
+ {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194},
+ {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0},
+ {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c},
+ {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8},
+ {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284},
+ {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288},
+ {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224},
+ {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290},
+ {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300},
+ {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304},
+ {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308},
+ {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c},
+ {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380},
+ {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384},
+ {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700},
+ {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704},
+ {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708},
+ {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c},
+ {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780},
+ {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784},
+ {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00},
+ {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04},
+ {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08},
+ {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c},
+ {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10},
+ {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b80, 0x00008b80, 0x00008b80},
+ {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b84, 0x00008b84, 0x00008b84},
+ {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b88, 0x00008b88, 0x00008b88},
+ {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b8c, 0x00008b8c, 0x00008b8c},
+ {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b90, 0x00008b90, 0x00008b90},
+ {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b94, 0x00008b94, 0x00008b94},
+ {0x00009adc, 0x0000b390, 0x0000b390, 0x00008b98, 0x00008b98, 0x00008b98},
+ {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008ba4, 0x00008ba4, 0x00008ba4},
+ {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008ba8, 0x00008ba8, 0x00008ba8},
+ {0x00009ae8, 0x0000b780, 0x0000b780, 0x00008bac, 0x00008bac, 0x00008bac},
+ {0x00009aec, 0x0000b784, 0x0000b784, 0x00008bb0, 0x00008bb0, 0x00008bb0},
+ {0x00009af0, 0x0000b788, 0x0000b788, 0x00008bb4, 0x00008bb4, 0x00008bb4},
+ {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008ba1, 0x00008ba1, 0x00008ba1},
+ {0x00009af8, 0x0000b790, 0x0000b790, 0x00008ba5, 0x00008ba5, 0x00008ba5},
+ {0x00009afc, 0x0000b794, 0x0000b794, 0x00008ba9, 0x00008ba9, 0x00008ba9},
+ {0x00009b00, 0x0000b798, 0x0000b798, 0x00008bad, 0x00008bad, 0x00008bad},
+ {0x00009b04, 0x0000d784, 0x0000d784, 0x00008bb1, 0x00008bb1, 0x00008bb1},
+ {0x00009b08, 0x0000d788, 0x0000d788, 0x00008bb5, 0x00008bb5, 0x00008bb5},
+ {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008ba2, 0x00008ba2, 0x00008ba2},
+ {0x00009b10, 0x0000d790, 0x0000d790, 0x00008ba6, 0x00008ba6, 0x00008ba6},
+ {0x00009b14, 0x0000f780, 0x0000f780, 0x00008baa, 0x00008baa, 0x00008baa},
+ {0x00009b18, 0x0000f784, 0x0000f784, 0x00008bae, 0x00008bae, 0x00008bae},
+ {0x00009b1c, 0x0000f788, 0x0000f788, 0x00008bb2, 0x00008bb2, 0x00008bb2},
+ {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008bb6, 0x00008bb6, 0x00008bb6},
+ {0x00009b24, 0x0000f790, 0x0000f790, 0x00008ba3, 0x00008ba3, 0x00008ba3},
+ {0x00009b28, 0x0000f794, 0x0000f794, 0x00008ba7, 0x00008ba7, 0x00008ba7},
+ {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008bab, 0x00008bab, 0x00008bab},
+ {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008baf, 0x00008baf, 0x00008baf},
+ {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008bb3, 0x00008bb3, 0x00008bb3},
+ {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008bb7, 0x00008bb7, 0x00008bb7},
+ {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008bc3, 0x00008bc3, 0x00008bc3},
+ {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008bc7, 0x00008bc7, 0x00008bc7},
+ {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008bcb, 0x00008bcb, 0x00008bcb},
+ {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008bcf, 0x00008bcf, 0x00008bcf},
+ {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008bd3, 0x00008bd3, 0x00008bd3},
+ {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008bd7, 0x00008bd7, 0x00008bd7},
+ {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
+ {0x00009848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055},
+ {0x0000a848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055},
+};
+
+static const u32 ar9280Modes_original_rxgain_9280_2[][6] = {
+ {0x00009a00, 0x00008184, 0x00008184, 0x00008000, 0x00008000, 0x00008000},
+ {0x00009a04, 0x00008188, 0x00008188, 0x00008000, 0x00008000, 0x00008000},
+ {0x00009a08, 0x0000818c, 0x0000818c, 0x00008000, 0x00008000, 0x00008000},
+ {0x00009a0c, 0x00008190, 0x00008190, 0x00008000, 0x00008000, 0x00008000},
+ {0x00009a10, 0x00008194, 0x00008194, 0x00008000, 0x00008000, 0x00008000},
+ {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000},
+ {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004},
+ {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008},
+ {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c},
+ {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080},
+ {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084},
+ {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088},
+ {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c},
+ {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100},
+ {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104},
+ {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108},
+ {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c},
+ {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110},
+ {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114},
+ {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180},
+ {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184},
+ {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188},
+ {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c},
+ {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190},
+ {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194},
+ {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0},
+ {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c},
+ {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8},
+ {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284},
+ {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288},
+ {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224},
+ {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290},
+ {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300},
+ {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304},
+ {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308},
+ {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c},
+ {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380},
+ {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384},
+ {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700},
+ {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704},
+ {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708},
+ {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c},
+ {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780},
+ {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784},
+ {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00},
+ {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04},
+ {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08},
+ {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c},
+ {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80},
+ {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84},
+ {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88},
+ {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c},
+ {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90},
+ {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80},
+ {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84},
+ {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88},
+ {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c},
+ {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90},
+ {0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c},
+ {0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310},
+ {0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384},
+ {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388},
+ {0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324},
+ {0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704},
+ {0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4},
+ {0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8},
+ {0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710},
+ {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714},
+ {0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720},
+ {0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724},
+ {0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728},
+ {0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c},
+ {0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0},
+ {0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4},
+ {0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8},
+ {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0},
+ {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4},
+ {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8},
+ {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5},
+ {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9},
+ {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad},
+ {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1},
+ {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5},
+ {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9},
+ {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5},
+ {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9},
+ {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1},
+ {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5},
+ {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9},
+ {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6},
+ {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca},
+ {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce},
+ {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2},
+ {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6},
+ {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3},
+ {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7},
+ {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb},
+ {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf},
+ {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7},
+ {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
+ {0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063},
+ {0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063},
+};
+
+static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = {
+ {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290},
+ {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300},
+ {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304},
+ {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308},
+ {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c},
+ {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000},
+ {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004},
+ {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008},
+ {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c},
+ {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080},
+ {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084},
+ {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088},
+ {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c},
+ {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100},
+ {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104},
+ {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108},
+ {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c},
+ {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110},
+ {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114},
+ {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180},
+ {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184},
+ {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188},
+ {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c},
+ {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190},
+ {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194},
+ {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0},
+ {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c},
+ {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8},
+ {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284},
+ {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288},
+ {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224},
+ {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290},
+ {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300},
+ {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304},
+ {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308},
+ {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c},
+ {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380},
+ {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384},
+ {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700},
+ {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704},
+ {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708},
+ {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c},
+ {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780},
+ {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784},
+ {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00},
+ {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04},
+ {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08},
+ {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c},
+ {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80},
+ {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84},
+ {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88},
+ {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c},
+ {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90},
+ {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80},
+ {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84},
+ {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88},
+ {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c},
+ {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90},
+ {0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310},
+ {0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314},
+ {0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320},
+ {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324},
+ {0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328},
+ {0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c},
+ {0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330},
+ {0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334},
+ {0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321},
+ {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325},
+ {0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329},
+ {0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d},
+ {0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331},
+ {0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335},
+ {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322},
+ {0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326},
+ {0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a},
+ {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e},
+ {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332},
+ {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336},
+ {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323},
+ {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327},
+ {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b},
+ {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f},
+ {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333},
+ {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337},
+ {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343},
+ {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347},
+ {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b},
+ {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f},
+ {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353},
+ {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357},
+ {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
+ {0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a},
+ {0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a},
+};
+
+static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = {
+ {0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652},
+ {0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce},
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002},
+ {0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008},
+ {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010},
+ {0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012},
+ {0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014},
+ {0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a},
+ {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211},
+ {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213},
+ {0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411},
+ {0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413},
+ {0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811},
+ {0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813},
+ {0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14},
+ {0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50},
+ {0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c},
+ {0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a},
+ {0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92},
+ {0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2},
+ {0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5},
+ {0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54},
+ {0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5},
+ {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
+ {0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
+ {0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
+ {0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
+ {0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
+ {0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
+ {0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
+};
+
+static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = {
+ {0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652},
+ {0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce},
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002},
+ {0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009},
+ {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b},
+ {0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012},
+ {0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048},
+ {0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a},
+ {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211},
+ {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213},
+ {0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b},
+ {0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412},
+ {0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414},
+ {0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a},
+ {0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649},
+ {0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b},
+ {0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49},
+ {0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48},
+ {0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a},
+ {0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88},
+ {0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a},
+ {0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9},
+ {0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42},
+ {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
+ {0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
+ {0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
+ {0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
+ {0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
+ {0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
+ {0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
+};
+
+static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x9248fd00},
+ {0x00004040, 0x24924924},
+ {0x00004040, 0xa8000019},
+ {0x00004040, 0x13160820},
+ {0x00004040, 0xe5980560},
+ {0x00004040, 0xc01dcffc},
+ {0x00004040, 0x1aaabe41},
+ {0x00004040, 0xbe105554},
+ {0x00004040, 0x00043007},
+ {0x00004044, 0x00000000},
+};
+
+static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x9248fd00},
+ {0x00004040, 0x24924924},
+ {0x00004040, 0xa8000019},
+ {0x00004040, 0x13160820},
+ {0x00004040, 0xe5980560},
+ {0x00004040, 0xc01dcffd},
+ {0x00004040, 0x1aaabe41},
+ {0x00004040, 0xbe105554},
+ {0x00004040, 0x00043007},
+ {0x00004044, 0x00000000},
+};
+
+static const u32 ar9285PciePhy_clkreq_always_on_L1_9285[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x9248fd00},
+ {0x00004040, 0x24924924},
+ {0x00004040, 0xa8000019},
+ {0x00004040, 0x13160820},
+ {0x00004040, 0xe5980560},
+ {0x00004040, 0xc01dcffd},
+ {0x00004040, 0x1aaabe41},
+ {0x00004040, 0xbe105554},
+ {0x00004040, 0x00043007},
+ {0x00004044, 0x00000000},
+};
+
+static const u32 ar9285PciePhy_clkreq_off_L1_9285[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x9248fd00},
+ {0x00004040, 0x24924924},
+ {0x00004040, 0xa8000019},
+ {0x00004040, 0x13160820},
+ {0x00004040, 0xe5980560},
+ {0x00004040, 0xc01dcffc},
+ {0x00004040, 0x1aaabe41},
+ {0x00004040, 0xbe105554},
+ {0x00004040, 0x00043007},
+ {0x00004044, 0x00000000},
+};
+
+static const u32 ar9285Modes_9285_1_2[][6] = {
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
+ {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0},
+ {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
+ {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
+ {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+ {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e},
+ {0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18},
+ {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
+ {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d},
+ {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010},
+ {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
+ {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00},
+ {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
+ {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
+ {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
+ {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
+ {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
+ {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
+ {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
+ {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
+ {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
+ {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
+ {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
+ {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
+ {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
+ {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
+ {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
+ {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
+ {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
+ {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
+ {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
+ {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
+ {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
+ {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
+ {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
+ {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
+ {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
+ {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
+ {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
+ {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
+ {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
+ {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
+ {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
+ {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
+ {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
+ {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
+ {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
+ {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
+ {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
+ {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
+ {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
+ {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
+ {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
+ {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
+ {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
+ {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
+ {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
+ {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
+ {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
+ {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
+ {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
+ {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
+ {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
+ {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
+ {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
+ {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
+ {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
+ {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
+ {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
+ {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
+ {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
+ {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
+ {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
+ {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
+ {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
+ {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
+ {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
+ {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
+ {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
+ {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
+ {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
+ {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
+ {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
+ {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
+ {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
+ {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
+ {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
+ {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
+ {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
+ {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
+ {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
+ {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
+ {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
+ {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
+ {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
+ {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
+ {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
+ {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
+ {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
+ {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
+ {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
+ {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
+ {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
+ {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
+ {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
+ {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
+ {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
+ {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
+ {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
+ {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
+ {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
+ {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
+ {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
+ {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
+ {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
+ {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
+ {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
+ {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
+ {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
+ {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
+ {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
+ {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
+ {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
+ {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
+ {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
+ {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
+ {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
+ {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
+ {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
+ {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
+ {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
+ {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
+ {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
+ {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
+ {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
+ {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
+ {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
+ {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
+ {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
+ {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
+ {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
+ {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
+ {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
+ {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
+ {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
+ {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
+ {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
+ {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
+ {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
+ {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
+ {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
+ {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
+ {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
+ {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
+ {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
+ {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
+ {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
+ {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
+ {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
+ {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
+ {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
+ {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
+ {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
+ {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
+ {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
+ {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
+ {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
+ {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
+ {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
+ {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
+ {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
+ {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
+ {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
+ {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
+ {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
+ {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
+ {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
+ {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
+ {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
+ {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
+ {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
+ {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
+ {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
+ {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
+ {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
+ {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
+ {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
+ {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
+ {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
+ {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
+ {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
+ {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
+ {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
+ {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000},
+ {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
+};
+
+static const u32 ar9285Common_9285_1_2[][2] = {
+ /* Addr allmodes */
+ {0x0000000c, 0x00000000},
+ {0x00000030, 0x00020045},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000008},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00000054, 0x0000001f},
+ {0x00000800, 0x00000000},
+ {0x00000804, 0x00000000},
+ {0x00000808, 0x00000000},
+ {0x0000080c, 0x00000000},
+ {0x00000810, 0x00000000},
+ {0x00000814, 0x00000000},
+ {0x00000818, 0x00000000},
+ {0x0000081c, 0x00000000},
+ {0x00000820, 0x00000000},
+ {0x00000824, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x00001230, 0x00000000},
+ {0x00001270, 0x00000000},
+ {0x00001038, 0x00000000},
+ {0x00001078, 0x00000000},
+ {0x000010b8, 0x00000000},
+ {0x000010f8, 0x00000000},
+ {0x00001138, 0x00000000},
+ {0x00001178, 0x00000000},
+ {0x000011b8, 0x00000000},
+ {0x000011f8, 0x00000000},
+ {0x00001238, 0x00000000},
+ {0x00001278, 0x00000000},
+ {0x000012b8, 0x00000000},
+ {0x000012f8, 0x00000000},
+ {0x00001338, 0x00000000},
+ {0x00001378, 0x00000000},
+ {0x000013b8, 0x00000000},
+ {0x000013f8, 0x00000000},
+ {0x00001438, 0x00000000},
+ {0x00001478, 0x00000000},
+ {0x000014b8, 0x00000000},
+ {0x000014f8, 0x00000000},
+ {0x00001538, 0x00000000},
+ {0x00001578, 0x00000000},
+ {0x000015b8, 0x00000000},
+ {0x000015f8, 0x00000000},
+ {0x00001638, 0x00000000},
+ {0x00001678, 0x00000000},
+ {0x000016b8, 0x00000000},
+ {0x000016f8, 0x00000000},
+ {0x00001738, 0x00000000},
+ {0x00001778, 0x00000000},
+ {0x000017b8, 0x00000000},
+ {0x000017f8, 0x00000000},
+ {0x0000103c, 0x00000000},
+ {0x0000107c, 0x00000000},
+ {0x000010bc, 0x00000000},
+ {0x000010fc, 0x00000000},
+ {0x0000113c, 0x00000000},
+ {0x0000117c, 0x00000000},
+ {0x000011bc, 0x00000000},
+ {0x000011fc, 0x00000000},
+ {0x0000123c, 0x00000000},
+ {0x0000127c, 0x00000000},
+ {0x000012bc, 0x00000000},
+ {0x000012fc, 0x00000000},
+ {0x0000133c, 0x00000000},
+ {0x0000137c, 0x00000000},
+ {0x000013bc, 0x00000000},
+ {0x000013fc, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00004030, 0x00000002},
+ {0x0000403c, 0x00000002},
+ {0x00004024, 0x0000001f},
+ {0x00004060, 0x00000000},
+ {0x00004064, 0x00000000},
+ {0x00007010, 0x00000031},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000700},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00000000},
+ {0x00008048, 0x00000000},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x00008070, 0x00000000},
+ {0x000080c0, 0x2a80001a},
+ {0x000080c4, 0x05dc01e0},
+ {0x000080c8, 0x1f402710},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00001e00},
+ {0x000080d4, 0x00000000},
+ {0x000080d8, 0x00400000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x003f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080f8, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00020000},
+ {0x00008104, 0x00000001},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000168},
+ {0x00008118, 0x000100aa},
+ {0x0000811c, 0x00003210},
+ {0x00008120, 0x08f04810},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x00000000},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x32143320},
+ {0x00008174, 0xfaa4fa50},
+ {0x00008178, 0x00000100},
+ {0x0000817c, 0x00000000},
+ {0x000081c0, 0x00000000},
+ {0x000081d0, 0x0000320a},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008200, 0x00000000},
+ {0x00008204, 0x00000000},
+ {0x00008208, 0x00000000},
+ {0x0000820c, 0x00000000},
+ {0x00008210, 0x00000000},
+ {0x00008214, 0x00000000},
+ {0x00008218, 0x00000000},
+ {0x0000821c, 0x00000000},
+ {0x00008220, 0x00000000},
+ {0x00008224, 0x00000000},
+ {0x00008228, 0x00000000},
+ {0x0000822c, 0x00000000},
+ {0x00008230, 0x00000000},
+ {0x00008234, 0x00000000},
+ {0x00008238, 0x00000000},
+ {0x0000823c, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f400},
+ {0x00008248, 0x00000100},
+ {0x0000824c, 0x0001e800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x400000ff},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x88a00010},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000000},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x00000000},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x0000829c, 0x00000000},
+ {0x00008300, 0x00000040},
+ {0x00008314, 0x00000000},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000001},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000e00},
+ {0x00008338, 0x00ff0000},
+ {0x0000833c, 0x00000000},
+ {0x00008340, 0x00010380},
+ {0x00008344, 0x00481043},
+ {0x00009808, 0x00000000},
+ {0x0000980c, 0xafe68e30},
+ {0x00009810, 0xfd14e000},
+ {0x00009814, 0x9c0a9f6b},
+ {0x0000981c, 0x00000000},
+ {0x0000982c, 0x0000a000},
+ {0x00009830, 0x00000000},
+ {0x0000983c, 0x00200400},
+ {0x0000984c, 0x0040233c},
+ {0x00009854, 0x00000044},
+ {0x00009900, 0x00000000},
+ {0x00009904, 0x00000000},
+ {0x00009908, 0x00000000},
+ {0x0000990c, 0x00000000},
+ {0x00009910, 0x01002310},
+ {0x0000991c, 0x10000fff},
+ {0x00009920, 0x04900000},
+ {0x00009928, 0x00000001},
+ {0x0000992c, 0x00000004},
+ {0x00009934, 0x1e1f2022},
+ {0x00009938, 0x0a0b0c0d},
+ {0x0000993c, 0x00000000},
+ {0x00009940, 0x14750604},
+ {0x00009948, 0x9280c00a},
+ {0x0000994c, 0x00020028},
+ {0x00009954, 0x5f3ca3de},
+ {0x00009958, 0x2108ecff},
+ {0x00009968, 0x000003ce},
+ {0x00009970, 0x192bb514},
+ {0x00009974, 0x00000000},
+ {0x00009978, 0x00000001},
+ {0x0000997c, 0x00000000},
+ {0x00009980, 0x00000000},
+ {0x00009984, 0x00000000},
+ {0x00009988, 0x00000000},
+ {0x0000998c, 0x00000000},
+ {0x00009990, 0x00000000},
+ {0x00009994, 0x00000000},
+ {0x00009998, 0x00000000},
+ {0x0000999c, 0x00000000},
+ {0x000099a0, 0x00000000},
+ {0x000099a4, 0x00000001},
+ {0x000099a8, 0x201fff00},
+ {0x000099ac, 0x2def0400},
+ {0x000099b0, 0x03051000},
+ {0x000099b4, 0x00000820},
+ {0x000099dc, 0x00000000},
+ {0x000099e0, 0x00000000},
+ {0x000099e4, 0xaaaaaaaa},
+ {0x000099e8, 0x3c466478},
+ {0x000099ec, 0x0cc80caa},
+ {0x000099f0, 0x00000000},
+ {0x0000a208, 0x803e68c8},
+ {0x0000a210, 0x4080a333},
+ {0x0000a214, 0x00206c10},
+ {0x0000a218, 0x009c4060},
+ {0x0000a220, 0x01834061},
+ {0x0000a224, 0x00000400},
+ {0x0000a228, 0x000003b5},
+ {0x0000a22c, 0x00000000},
+ {0x0000a234, 0x20202020},
+ {0x0000a238, 0x20202020},
+ {0x0000a244, 0x00000000},
+ {0x0000a248, 0xfffffffc},
+ {0x0000a24c, 0x00000000},
+ {0x0000a254, 0x00000000},
+ {0x0000a258, 0x0ccb5380},
+ {0x0000a25c, 0x15151501},
+ {0x0000a260, 0xdfa90f01},
+ {0x0000a268, 0x00000000},
+ {0x0000a26c, 0x0ebae9e6},
+ {0x0000d270, 0x0d820820},
+ {0x0000d35c, 0x07ffffef},
+ {0x0000d360, 0x0fffffe7},
+ {0x0000d364, 0x17ffffe5},
+ {0x0000d368, 0x1fffffe4},
+ {0x0000d36c, 0x37ffffe3},
+ {0x0000d370, 0x3fffffe3},
+ {0x0000d374, 0x57ffffe3},
+ {0x0000d378, 0x5fffffe2},
+ {0x0000d37c, 0x7fffffe2},
+ {0x0000d380, 0x7f3c7bba},
+ {0x0000d384, 0xf3307ff0},
+ {0x0000a388, 0x0c000000},
+ {0x0000a38c, 0x20202020},
+ {0x0000a390, 0x20202020},
+ {0x0000a39c, 0x00000001},
+ {0x0000a3a0, 0x00000000},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0x00000000},
+ {0x0000a3ac, 0x00000000},
+ {0x0000a3b0, 0x00000000},
+ {0x0000a3b4, 0x00000000},
+ {0x0000a3b8, 0x00000000},
+ {0x0000a3bc, 0x00000000},
+ {0x0000a3c0, 0x00000000},
+ {0x0000a3c4, 0x00000000},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3e4, 0x00000000},
+ {0x0000a3e8, 0x18c43433},
+ {0x0000a3ec, 0x00f70081},
+ {0x00007800, 0x00140000},
+ {0x00007804, 0x0e4548d8},
+ {0x00007808, 0x54214514},
+ {0x0000780c, 0x02025830},
+ {0x00007810, 0x71c0d388},
+ {0x0000781c, 0x00000000},
+ {0x00007824, 0x00d86fff},
+ {0x0000782c, 0x6e36d97b},
+ {0x00007834, 0x71400087},
+ {0x00007844, 0x000c0db6},
+ {0x00007848, 0x6db6246f},
+ {0x0000784c, 0x6d9b66db},
+ {0x00007850, 0x6d8c6dba},
+ {0x00007854, 0x00040000},
+ {0x00007858, 0xdb003012},
+ {0x0000785c, 0x04924914},
+ {0x00007860, 0x21084210},
+ {0x00007864, 0xf7d7ffde},
+ {0x00007868, 0xc2034080},
+ {0x00007870, 0x10142c00},
+};
+
+static const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][6] = {
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000},
+ {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000},
+ {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000},
+ {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
+ {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
+ {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
+ {0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803},
+ {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
+ {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
+ {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
+ {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+ {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652},
+ {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
+ {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+ {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+};
+
+static const u32 ar9285Modes_original_tx_gain_9285_1_2[][6] = {
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000},
+ {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000},
+ {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000},
+ {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000},
+ {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
+ {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
+ {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
+ {0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801},
+ {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
+ {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
+ {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+ {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+ {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652},
+ {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
+ {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+ {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+};
+
+static const u32 ar9285Modes_XE2_0_normal_power[][6] = {
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000},
+ {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000},
+ {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000},
+ {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000},
+ {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
+ {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b},
+ {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6dbae},
+ {0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441},
+ {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
+ {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
+ {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+ {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+ {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652},
+ {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
+ {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+ {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+};
+
+static const u32 ar9285Modes_XE2_0_high_power[][6] = {
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000},
+ {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000},
+ {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000},
+ {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
+ {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b},
+ {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e},
+ {0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443},
+ {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
+ {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
+ {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
+ {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+ {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652},
+ {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
+ {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+ {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+};
+
+static const u32 ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x9248fd00},
+ {0x00004040, 0x24924924},
+ {0x00004040, 0xa8000019},
+ {0x00004040, 0x13160820},
+ {0x00004040, 0xe5980560},
+ {0x00004040, 0xc01dcffd},
+ {0x00004040, 0x1aaabe41},
+ {0x00004040, 0xbe105554},
+ {0x00004040, 0x00043007},
+ {0x00004044, 0x00000000},
+};
+
+static const u32 ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x9248fd00},
+ {0x00004040, 0x24924924},
+ {0x00004040, 0xa8000019},
+ {0x00004040, 0x13160820},
+ {0x00004040, 0xe5980560},
+ {0x00004040, 0xc01dcffc},
+ {0x00004040, 0x1aaabe41},
+ {0x00004040, 0xbe105554},
+ {0x00004040, 0x00043007},
+ {0x00004044, 0x00000000},
+};
+
+static const u32 ar9287Modes_9287_1_1[][6] = {
+ {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0},
+ {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0},
+ {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180},
+ {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
+ {0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0},
+ {0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880},
+ {0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303},
+ {0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001, 0x3a020001},
+ {0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e},
+ {0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0},
+ {0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2},
+ {0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e},
+ {0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18},
+ {0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881},
+ {0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0},
+ {0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016},
+ {0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
+ {0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010},
+ {0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010},
+ {0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010},
+ {0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210},
+ {0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce},
+ {0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c},
+ {0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00},
+ {0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444},
+ {0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
+ {0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000},
+ {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
+ {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9287Common_9287_1_1[][2] = {
+ /* Addr allmodes */
+ {0x0000000c, 0x00000000},
+ {0x00000030, 0x00020015},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000008},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00000054, 0x0000001f},
+ {0x00000800, 0x00000000},
+ {0x00000804, 0x00000000},
+ {0x00000808, 0x00000000},
+ {0x0000080c, 0x00000000},
+ {0x00000810, 0x00000000},
+ {0x00000814, 0x00000000},
+ {0x00000818, 0x00000000},
+ {0x0000081c, 0x00000000},
+ {0x00000820, 0x00000000},
+ {0x00000824, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x00001230, 0x00000000},
+ {0x00001270, 0x00000000},
+ {0x00001038, 0x00000000},
+ {0x00001078, 0x00000000},
+ {0x000010b8, 0x00000000},
+ {0x000010f8, 0x00000000},
+ {0x00001138, 0x00000000},
+ {0x00001178, 0x00000000},
+ {0x000011b8, 0x00000000},
+ {0x000011f8, 0x00000000},
+ {0x00001238, 0x00000000},
+ {0x00001278, 0x00000000},
+ {0x000012b8, 0x00000000},
+ {0x000012f8, 0x00000000},
+ {0x00001338, 0x00000000},
+ {0x00001378, 0x00000000},
+ {0x000013b8, 0x00000000},
+ {0x000013f8, 0x00000000},
+ {0x00001438, 0x00000000},
+ {0x00001478, 0x00000000},
+ {0x000014b8, 0x00000000},
+ {0x000014f8, 0x00000000},
+ {0x00001538, 0x00000000},
+ {0x00001578, 0x00000000},
+ {0x000015b8, 0x00000000},
+ {0x000015f8, 0x00000000},
+ {0x00001638, 0x00000000},
+ {0x00001678, 0x00000000},
+ {0x000016b8, 0x00000000},
+ {0x000016f8, 0x00000000},
+ {0x00001738, 0x00000000},
+ {0x00001778, 0x00000000},
+ {0x000017b8, 0x00000000},
+ {0x000017f8, 0x00000000},
+ {0x0000103c, 0x00000000},
+ {0x0000107c, 0x00000000},
+ {0x000010bc, 0x00000000},
+ {0x000010fc, 0x00000000},
+ {0x0000113c, 0x00000000},
+ {0x0000117c, 0x00000000},
+ {0x000011bc, 0x00000000},
+ {0x000011fc, 0x00000000},
+ {0x0000123c, 0x00000000},
+ {0x0000127c, 0x00000000},
+ {0x000012bc, 0x00000000},
+ {0x000012fc, 0x00000000},
+ {0x0000133c, 0x00000000},
+ {0x0000137c, 0x00000000},
+ {0x000013bc, 0x00000000},
+ {0x000013fc, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00004030, 0x00000002},
+ {0x0000403c, 0x00000002},
+ {0x00004024, 0x0000001f},
+ {0x00004060, 0x00000000},
+ {0x00004064, 0x00000000},
+ {0x00007010, 0x00000033},
+ {0x00007020, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000700},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00000000},
+ {0x00008048, 0x40000000},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x00008070, 0x00000000},
+ {0x000080c0, 0x2a80001a},
+ {0x000080c4, 0x05dc01e0},
+ {0x000080c8, 0x1f402710},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00001e00},
+ {0x000080d4, 0x00000000},
+ {0x000080d8, 0x00400000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x003f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080f8, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00020000},
+ {0x00008104, 0x00000001},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000168},
+ {0x00008118, 0x000100aa},
+ {0x0000811c, 0x00003210},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x00000000},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x18487320},
+ {0x00008174, 0xfaa4fa50},
+ {0x00008178, 0x00000100},
+ {0x0000817c, 0x00000000},
+ {0x000081c0, 0x00000000},
+ {0x000081c4, 0x00000000},
+ {0x000081d4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008200, 0x00000000},
+ {0x00008204, 0x00000000},
+ {0x00008208, 0x00000000},
+ {0x0000820c, 0x00000000},
+ {0x00008210, 0x00000000},
+ {0x00008214, 0x00000000},
+ {0x00008218, 0x00000000},
+ {0x0000821c, 0x00000000},
+ {0x00008220, 0x00000000},
+ {0x00008224, 0x00000000},
+ {0x00008228, 0x00000000},
+ {0x0000822c, 0x00000000},
+ {0x00008230, 0x00000000},
+ {0x00008234, 0x00000000},
+ {0x00008238, 0x00000000},
+ {0x0000823c, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f400},
+ {0x00008248, 0x00000100},
+ {0x0000824c, 0x0001e800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x400000ff},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x88a00010},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000000},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x000000ff},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x0000829c, 0x00000000},
+ {0x00008300, 0x00000040},
+ {0x00008314, 0x00000000},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000007},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000e00},
+ {0x00008338, 0x00ff0000},
+ {0x0000833c, 0x00000000},
+ {0x00008340, 0x000107ff},
+ {0x00008344, 0x01c81043},
+ {0x00008360, 0xffffffff},
+ {0x00008364, 0xffffffff},
+ {0x00008368, 0x00000000},
+ {0x00008370, 0x00000000},
+ {0x00008374, 0x000000ff},
+ {0x00008378, 0x00000000},
+ {0x0000837c, 0x00000000},
+ {0x00008380, 0xffffffff},
+ {0x00008384, 0xffffffff},
+ {0x00008390, 0x0fffffff},
+ {0x00008394, 0x0fffffff},
+ {0x00008398, 0x00000000},
+ {0x0000839c, 0x00000000},
+ {0x000083a0, 0x00000000},
+ {0x00009808, 0x00000000},
+ {0x0000980c, 0xafe68e30},
+ {0x00009810, 0xfd14e000},
+ {0x00009814, 0x9c0a9f6b},
+ {0x0000981c, 0x00000000},
+ {0x0000982c, 0x0000a000},
+ {0x00009830, 0x00000000},
+ {0x0000983c, 0x00200400},
+ {0x0000984c, 0x0040233c},
+ {0x0000a84c, 0x0040233c},
+ {0x00009854, 0x00000044},
+ {0x00009900, 0x00000000},
+ {0x00009904, 0x00000000},
+ {0x00009908, 0x00000000},
+ {0x0000990c, 0x00000000},
+ {0x00009910, 0x10002310},
+ {0x0000991c, 0x10000fff},
+ {0x00009920, 0x04900000},
+ {0x0000a920, 0x04900000},
+ {0x00009928, 0x00000001},
+ {0x0000992c, 0x00000004},
+ {0x00009930, 0x00000000},
+ {0x0000a930, 0x00000000},
+ {0x00009934, 0x1e1f2022},
+ {0x00009938, 0x0a0b0c0d},
+ {0x0000993c, 0x00000000},
+ {0x00009948, 0x9280c00a},
+ {0x0000994c, 0x00020028},
+ {0x00009954, 0x5f3ca3de},
+ {0x00009958, 0x0108ecff},
+ {0x00009940, 0x14750604},
+ {0x0000c95c, 0x004b6a8e},
+ {0x00009970, 0x990bb514},
+ {0x00009974, 0x00000000},
+ {0x00009978, 0x00000001},
+ {0x0000997c, 0x00000000},
+ {0x000099a0, 0x00000000},
+ {0x000099a4, 0x00000001},
+ {0x000099a8, 0x201fff00},
+ {0x000099ac, 0x0c6f0000},
+ {0x000099b0, 0x03051000},
+ {0x000099b4, 0x00000820},
+ {0x000099c4, 0x06336f77},
+ {0x000099c8, 0x6af6532f},
+ {0x000099cc, 0x08f186c8},
+ {0x000099d0, 0x00046384},
+ {0x000099dc, 0x00000000},
+ {0x000099e0, 0x00000000},
+ {0x000099e4, 0xaaaaaaaa},
+ {0x000099e8, 0x3c466478},
+ {0x000099ec, 0x0cc80caa},
+ {0x000099f0, 0x00000000},
+ {0x000099fc, 0x00001042},
+ {0x0000a208, 0x803e4788},
+ {0x0000a210, 0x4080a333},
+ {0x0000a214, 0x40206c10},
+ {0x0000a218, 0x009c4060},
+ {0x0000a220, 0x01834061},
+ {0x0000a224, 0x00000400},
+ {0x0000a228, 0x000003b5},
+ {0x0000a22c, 0x233f7180},
+ {0x0000a234, 0x20202020},
+ {0x0000a238, 0x20202020},
+ {0x0000a23c, 0x13c889af},
+ {0x0000a240, 0x38490a20},
+ {0x0000a244, 0x00000000},
+ {0x0000a248, 0xfffffffc},
+ {0x0000a24c, 0x00000000},
+ {0x0000a254, 0x00000000},
+ {0x0000a258, 0x0cdbd380},
+ {0x0000a25c, 0x0f0f0f01},
+ {0x0000a260, 0xdfa91f01},
+ {0x0000a264, 0x00418a11},
+ {0x0000b264, 0x00418a11},
+ {0x0000a268, 0x00000000},
+ {0x0000a26c, 0x0e79e5c6},
+ {0x0000b26c, 0x0e79e5c6},
+ {0x0000d270, 0x00820820},
+ {0x0000a278, 0x1ce739ce},
+ {0x0000a27c, 0x050701ce},
+ {0x0000d35c, 0x07ffffef},
+ {0x0000d360, 0x0fffffe7},
+ {0x0000d364, 0x17ffffe5},
+ {0x0000d368, 0x1fffffe4},
+ {0x0000d36c, 0x37ffffe3},
+ {0x0000d370, 0x3fffffe3},
+ {0x0000d374, 0x57ffffe3},
+ {0x0000d378, 0x5fffffe2},
+ {0x0000d37c, 0x7fffffe2},
+ {0x0000d380, 0x7f3c7bba},
+ {0x0000d384, 0xf3307ff0},
+ {0x0000a388, 0x0c000000},
+ {0x0000a38c, 0x20202020},
+ {0x0000a390, 0x20202020},
+ {0x0000a394, 0x1ce739ce},
+ {0x0000a398, 0x000001ce},
+ {0x0000b398, 0x000001ce},
+ {0x0000a39c, 0x00000001},
+ {0x0000a3c8, 0x00000246},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3dc, 0x1ce739ce},
+ {0x0000a3e0, 0x000001ce},
+ {0x0000a3e4, 0x00000000},
+ {0x0000a3e8, 0x18c43433},
+ {0x0000a3ec, 0x00f70081},
+ {0x0000a3f0, 0x01036a1e},
+ {0x0000a3f4, 0x00000000},
+ {0x0000b3f4, 0x00000000},
+ {0x0000a7d8, 0x000003f1},
+ {0x00007800, 0x00000800},
+ {0x00007804, 0x6c35ffd2},
+ {0x00007808, 0x6db6c000},
+ {0x0000780c, 0x6db6cb30},
+ {0x00007810, 0x6db6cb6c},
+ {0x00007814, 0x0501e200},
+ {0x00007818, 0x0094128d},
+ {0x0000781c, 0x976ee392},
+ {0x00007820, 0xf75ff6fc},
+ {0x00007824, 0x00040000},
+ {0x00007828, 0xdb003012},
+ {0x0000782c, 0x04924914},
+ {0x00007830, 0x21084210},
+ {0x00007834, 0x00140000},
+ {0x00007838, 0x0e4548d8},
+ {0x0000783c, 0x54214514},
+ {0x00007840, 0x02025830},
+ {0x00007844, 0x71c0d388},
+ {0x00007848, 0x934934a8},
+ {0x00007850, 0x00000000},
+ {0x00007854, 0x00000800},
+ {0x00007858, 0x6c35ffd2},
+ {0x0000785c, 0x6db6c000},
+ {0x00007860, 0x6db6cb30},
+ {0x00007864, 0x6db6cb6c},
+ {0x00007868, 0x0501e200},
+ {0x0000786c, 0x0094128d},
+ {0x00007870, 0x976ee392},
+ {0x00007874, 0xf75ff6fc},
+ {0x00007878, 0x00040000},
+ {0x0000787c, 0xdb003012},
+ {0x00007880, 0x04924914},
+ {0x00007884, 0x21084210},
+ {0x00007888, 0x001b6db0},
+ {0x0000788c, 0x00376b63},
+ {0x00007890, 0x06db6db6},
+ {0x00007894, 0x006d8000},
+ {0x00007898, 0x48100000},
+ {0x0000789c, 0x00000000},
+ {0x000078a0, 0x08000000},
+ {0x000078a4, 0x0007ffd8},
+ {0x000078a8, 0x0007ffd8},
+ {0x000078ac, 0x001c0020},
+ {0x000078b0, 0x00060aeb},
+ {0x000078b4, 0x40008080},
+ {0x000078b8, 0x2a850160},
+};
+
+static const u32 ar9287Common_normal_cck_fir_coeff_9287_1_1[][2] = {
+ /* Addr allmodes */
+ {0x0000a1f4, 0x00fffeff},
+ {0x0000a1f8, 0x00f5f9ff},
+ {0x0000a1fc, 0xb79f6427},
+};
+
+static const u32 ar9287Common_japan_2484_cck_fir_coeff_9287_1_1[][2] = {
+ /* Addr allmodes */
+ {0x0000a1f4, 0x00000000},
+ {0x0000a1f8, 0xefff0301},
+ {0x0000a1fc, 0xca9228ee},
+};
+
+static const u32 ar9287Modes_tx_gain_9287_1_1[][6] = {
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b},
+ {0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a},
+ {0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a},
+ {0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a},
+ {0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a},
+ {0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c},
+ {0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc},
+ {0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4},
+ {0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc},
+ {0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede},
+ {0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e},
+ {0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e},
+ {0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e},
+ {0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062, 0x00000062},
+ {0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064, 0x00004064},
+ {0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4, 0x000080a4},
+ {0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa, 0x0000c0aa},
+ {0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac, 0x000100ac},
+ {0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4, 0x000140b4},
+ {0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4, 0x000180f4},
+ {0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134, 0x0001c134},
+ {0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174, 0x00020174},
+ {0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c, 0x0002417c},
+ {0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e, 0x0002817e},
+ {0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be, 0x0002c1be},
+ {0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
+ {0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
+ {0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
+ {0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
+ {0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
+ {0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
+ {0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
+ {0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
+ {0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
+ {0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
+ {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000},
+};
+
+static const u32 ar9287Modes_rx_gain_9287_1_1[][6] = {
+ {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120},
+ {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124},
+ {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128},
+ {0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c},
+ {0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130},
+ {0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194},
+ {0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198},
+ {0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c},
+ {0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210},
+ {0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284},
+ {0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288},
+ {0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c},
+ {0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290},
+ {0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294},
+ {0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0},
+ {0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4},
+ {0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8},
+ {0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac},
+ {0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0},
+ {0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4},
+ {0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8},
+ {0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4},
+ {0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708},
+ {0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c},
+ {0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710},
+ {0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04},
+ {0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08},
+ {0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c},
+ {0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10},
+ {0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14},
+ {0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18},
+ {0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c},
+ {0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90},
+ {0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94},
+ {0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98},
+ {0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4},
+ {0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8},
+ {0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04},
+ {0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08},
+ {0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c},
+ {0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10},
+ {0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14},
+ {0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18},
+ {0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c},
+ {0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90},
+ {0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18},
+ {0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24},
+ {0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28},
+ {0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314},
+ {0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318},
+ {0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c},
+ {0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390},
+ {0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394},
+ {0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398},
+ {0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4},
+ {0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8},
+ {0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac},
+ {0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0},
+ {0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380},
+ {0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384},
+ {0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388},
+ {0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710},
+ {0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714},
+ {0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718},
+ {0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10},
+ {0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14},
+ {0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18},
+ {0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c},
+ {0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90},
+ {0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94},
+ {0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c},
+ {0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90},
+ {0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94},
+ {0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0},
+ {0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4},
+ {0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8},
+ {0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac},
+ {0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0},
+ {0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4},
+ {0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1},
+ {0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5},
+ {0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9},
+ {0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad},
+ {0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1},
+ {0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5},
+ {0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9},
+ {0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5},
+ {0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9},
+ {0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd},
+ {0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1},
+ {0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5},
+ {0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2},
+ {0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6},
+ {0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca},
+ {0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce},
+ {0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2},
+ {0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6},
+ {0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda},
+ {0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7},
+ {0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb},
+ {0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf},
+ {0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3},
+ {0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7},
+ {0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120},
+ {0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124},
+ {0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128},
+ {0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c},
+ {0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130},
+ {0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194},
+ {0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198},
+ {0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c},
+ {0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210},
+ {0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284},
+ {0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288},
+ {0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c},
+ {0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290},
+ {0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294},
+ {0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0},
+ {0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4},
+ {0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8},
+ {0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac},
+ {0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0},
+ {0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4},
+ {0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8},
+ {0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4},
+ {0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708},
+ {0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c},
+ {0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710},
+ {0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04},
+ {0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08},
+ {0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c},
+ {0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10},
+ {0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14},
+ {0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18},
+ {0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c},
+ {0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90},
+ {0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94},
+ {0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98},
+ {0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4},
+ {0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8},
+ {0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04},
+ {0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08},
+ {0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c},
+ {0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10},
+ {0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14},
+ {0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18},
+ {0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c},
+ {0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90},
+ {0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18},
+ {0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24},
+ {0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28},
+ {0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314},
+ {0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318},
+ {0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c},
+ {0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390},
+ {0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394},
+ {0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398},
+ {0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4},
+ {0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8},
+ {0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac},
+ {0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0},
+ {0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380},
+ {0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384},
+ {0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388},
+ {0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710},
+ {0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714},
+ {0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718},
+ {0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10},
+ {0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14},
+ {0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18},
+ {0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c},
+ {0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90},
+ {0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94},
+ {0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c},
+ {0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90},
+ {0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94},
+ {0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0},
+ {0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4},
+ {0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8},
+ {0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac},
+ {0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0},
+ {0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4},
+ {0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1},
+ {0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5},
+ {0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9},
+ {0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad},
+ {0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1},
+ {0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5},
+ {0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9},
+ {0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5},
+ {0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9},
+ {0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd},
+ {0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1},
+ {0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5},
+ {0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2},
+ {0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6},
+ {0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca},
+ {0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce},
+ {0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2},
+ {0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6},
+ {0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda},
+ {0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7},
+ {0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb},
+ {0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf},
+ {0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3},
+ {0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7},
+ {0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
+ {0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067},
+ {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067},
+};
+
+static const u32 ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x9248fd00},
+ {0x00004040, 0x24924924},
+ {0x00004040, 0xa8000019},
+ {0x00004040, 0x13160820},
+ {0x00004040, 0xe5980560},
+ {0x00004040, 0xc01dcffd},
+ {0x00004040, 0x1aaabe41},
+ {0x00004040, 0xbe105554},
+ {0x00004040, 0x00043007},
+ {0x00004044, 0x00000000},
+};
+
+static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x9248fd00},
+ {0x00004040, 0x24924924},
+ {0x00004040, 0xa8000019},
+ {0x00004040, 0x13160820},
+ {0x00004040, 0xe5980560},
+ {0x00004040, 0xc01dcffc},
+ {0x00004040, 0x1aaabe41},
+ {0x00004040, 0xbe105554},
+ {0x00004040, 0x00043007},
+ {0x00004044, 0x00000000},
+};
+
+static const u32 ar9271Modes_9271[][6] = {
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
+ {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0},
+ {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
+ {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
+ {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+ {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e},
+ {0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
+ {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881},
+ {0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310, 0x30002310},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
+ {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d},
+ {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010},
+ {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
+ {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00},
+ {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
+ {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
+ {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
+ {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
+ {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
+ {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
+ {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
+ {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
+ {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
+ {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
+ {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
+ {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
+ {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
+ {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
+ {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
+ {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
+ {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
+ {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
+ {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
+ {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
+ {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
+ {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
+ {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
+ {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
+ {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
+ {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
+ {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
+ {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
+ {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
+ {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
+ {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
+ {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
+ {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
+ {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
+ {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
+ {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
+ {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
+ {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
+ {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
+ {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
+ {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
+ {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
+ {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
+ {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
+ {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
+ {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
+ {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
+ {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
+ {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
+ {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
+ {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
+ {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
+ {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
+ {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
+ {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
+ {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
+ {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
+ {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
+ {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
+ {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
+ {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
+ {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
+ {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
+ {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
+ {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
+ {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
+ {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
+ {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
+ {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
+ {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
+ {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
+ {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
+ {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
+ {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
+ {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
+ {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
+ {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
+ {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
+ {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
+ {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
+ {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
+ {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
+ {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
+ {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
+ {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
+ {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
+ {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
+ {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
+ {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
+ {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
+ {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
+ {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
+ {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
+ {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
+ {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
+ {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
+ {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
+ {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
+ {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
+ {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
+ {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
+ {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
+ {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
+ {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
+ {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
+ {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
+ {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
+ {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
+ {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
+ {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
+ {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
+ {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
+ {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
+ {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
+ {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
+ {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
+ {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
+ {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
+ {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
+ {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
+ {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
+ {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
+ {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
+ {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
+ {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
+ {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
+ {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
+ {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
+ {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
+ {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
+ {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
+ {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
+ {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
+ {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
+ {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
+ {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
+ {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
+ {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
+ {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
+ {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
+ {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
+ {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
+ {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
+ {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
+ {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
+ {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
+ {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
+ {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
+ {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
+ {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
+ {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
+ {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
+ {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
+ {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
+ {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
+ {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
+ {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
+ {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
+ {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
+ {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
+ {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
+ {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
+ {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
+ {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
+ {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
+ {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
+ {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
+ {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
+ {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
+ {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
+ {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
+ {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
+ {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
+ {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
+ {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
+ {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
+ {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
+ {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
+ {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
+ {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
+ {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
+ {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
+ {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000},
+ {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
+};
+
+static const u32 ar9271Common_9271[][2] = {
+ /* Addr allmodes */
+ {0x0000000c, 0x00000000},
+ {0x00000030, 0x00020045},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000008},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00000054, 0x0000001f},
+ {0x00000800, 0x00000000},
+ {0x00000804, 0x00000000},
+ {0x00000808, 0x00000000},
+ {0x0000080c, 0x00000000},
+ {0x00000810, 0x00000000},
+ {0x00000814, 0x00000000},
+ {0x00000818, 0x00000000},
+ {0x0000081c, 0x00000000},
+ {0x00000820, 0x00000000},
+ {0x00000824, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x00001230, 0x00000000},
+ {0x00001270, 0x00000000},
+ {0x00001038, 0x00000000},
+ {0x00001078, 0x00000000},
+ {0x000010b8, 0x00000000},
+ {0x000010f8, 0x00000000},
+ {0x00001138, 0x00000000},
+ {0x00001178, 0x00000000},
+ {0x000011b8, 0x00000000},
+ {0x000011f8, 0x00000000},
+ {0x00001238, 0x00000000},
+ {0x00001278, 0x00000000},
+ {0x000012b8, 0x00000000},
+ {0x000012f8, 0x00000000},
+ {0x00001338, 0x00000000},
+ {0x00001378, 0x00000000},
+ {0x000013b8, 0x00000000},
+ {0x000013f8, 0x00000000},
+ {0x00001438, 0x00000000},
+ {0x00001478, 0x00000000},
+ {0x000014b8, 0x00000000},
+ {0x000014f8, 0x00000000},
+ {0x00001538, 0x00000000},
+ {0x00001578, 0x00000000},
+ {0x000015b8, 0x00000000},
+ {0x000015f8, 0x00000000},
+ {0x00001638, 0x00000000},
+ {0x00001678, 0x00000000},
+ {0x000016b8, 0x00000000},
+ {0x000016f8, 0x00000000},
+ {0x00001738, 0x00000000},
+ {0x00001778, 0x00000000},
+ {0x000017b8, 0x00000000},
+ {0x000017f8, 0x00000000},
+ {0x0000103c, 0x00000000},
+ {0x0000107c, 0x00000000},
+ {0x000010bc, 0x00000000},
+ {0x000010fc, 0x00000000},
+ {0x0000113c, 0x00000000},
+ {0x0000117c, 0x00000000},
+ {0x000011bc, 0x00000000},
+ {0x000011fc, 0x00000000},
+ {0x0000123c, 0x00000000},
+ {0x0000127c, 0x00000000},
+ {0x000012bc, 0x00000000},
+ {0x000012fc, 0x00000000},
+ {0x0000133c, 0x00000000},
+ {0x0000137c, 0x00000000},
+ {0x000013bc, 0x00000000},
+ {0x000013fc, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00004030, 0x00000002},
+ {0x0000403c, 0x00000002},
+ {0x00004024, 0x0000001f},
+ {0x00004060, 0x00000000},
+ {0x00004064, 0x00000000},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000700},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00000000},
+ {0x00008048, 0x00000000},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x00008070, 0x00000000},
+ {0x000080b0, 0x00000000},
+ {0x000080b4, 0x00000000},
+ {0x000080b8, 0x00000000},
+ {0x000080bc, 0x00000000},
+ {0x000080c0, 0x2a80001a},
+ {0x000080c4, 0x05dc01e0},
+ {0x000080c8, 0x1f402710},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00001e00},
+ {0x000080d4, 0x00000000},
+ {0x000080d8, 0x00400000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x003f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080f8, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00020000},
+ {0x00008104, 0x00000001},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000168},
+ {0x00008118, 0x000100aa},
+ {0x0000811c, 0x00003210},
+ {0x00008120, 0x08f04810},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x00000000},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x32143320},
+ {0x00008174, 0xfaa4fa50},
+ {0x00008178, 0x00000100},
+ {0x0000817c, 0x00000000},
+ {0x000081c0, 0x00000000},
+ {0x000081d0, 0x0000320a},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008200, 0x00000000},
+ {0x00008204, 0x00000000},
+ {0x00008208, 0x00000000},
+ {0x0000820c, 0x00000000},
+ {0x00008210, 0x00000000},
+ {0x00008214, 0x00000000},
+ {0x00008218, 0x00000000},
+ {0x0000821c, 0x00000000},
+ {0x00008220, 0x00000000},
+ {0x00008224, 0x00000000},
+ {0x00008228, 0x00000000},
+ {0x0000822c, 0x00000000},
+ {0x00008230, 0x00000000},
+ {0x00008234, 0x00000000},
+ {0x00008238, 0x00000000},
+ {0x0000823c, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f400},
+ {0x00008248, 0x00000100},
+ {0x0000824c, 0x0001e800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x400000ff},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x88a00010},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000000},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x00000000},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x0000829c, 0x00000000},
+ {0x00008300, 0x00000040},
+ {0x00008314, 0x00000000},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000001},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000e00},
+ {0x00008338, 0x00ff0000},
+ {0x0000833c, 0x00000000},
+ {0x00008340, 0x00010380},
+ {0x00008344, 0x00581043},
+ {0x00007010, 0x00000030},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+ {0x00007800, 0x00140000},
+ {0x00007804, 0x0e4548d8},
+ {0x00007808, 0x54214514},
+ {0x0000780c, 0x02025820},
+ {0x00007810, 0x71c0d388},
+ {0x00007814, 0x924934a8},
+ {0x0000781c, 0x00000000},
+ {0x00007828, 0x66964300},
+ {0x0000782c, 0x8db6d961},
+ {0x00007830, 0x8db6d96c},
+ {0x00007834, 0x6140008b},
+ {0x0000783c, 0x72ee0a72},
+ {0x00007840, 0xbbfffffc},
+ {0x00007844, 0x000c0db6},
+ {0x00007848, 0x6db6246f},
+ {0x0000784c, 0x6d9b66db},
+ {0x00007850, 0x6d8c6dba},
+ {0x00007854, 0x00040000},
+ {0x00007858, 0xdb003012},
+ {0x0000785c, 0x04924914},
+ {0x00007860, 0x21084210},
+ {0x00007864, 0xf7d7ffde},
+ {0x00007868, 0xc2034080},
+ {0x00007870, 0x10142c00},
+ {0x00009808, 0x00000000},
+ {0x0000980c, 0xafe68e30},
+ {0x00009810, 0xfd14e000},
+ {0x00009814, 0x9c0a9f6b},
+ {0x0000981c, 0x00000000},
+ {0x0000982c, 0x0000a000},
+ {0x00009830, 0x00000000},
+ {0x0000983c, 0x00200400},
+ {0x0000984c, 0x0040233c},
+ {0x00009854, 0x00000044},
+ {0x00009900, 0x00000000},
+ {0x00009904, 0x00000000},
+ {0x00009908, 0x00000000},
+ {0x0000990c, 0x00000000},
+ {0x0000991c, 0x10000fff},
+ {0x00009920, 0x04900000},
+ {0x00009928, 0x00000001},
+ {0x0000992c, 0x00000004},
+ {0x00009934, 0x1e1f2022},
+ {0x00009938, 0x0a0b0c0d},
+ {0x0000993c, 0x00000000},
+ {0x00009940, 0x14750604},
+ {0x00009948, 0x9280c00a},
+ {0x0000994c, 0x00020028},
+ {0x00009954, 0x5f3ca3de},
+ {0x00009958, 0x0108ecff},
+ {0x00009968, 0x000003ce},
+ {0x00009970, 0x192bb514},
+ {0x00009974, 0x00000000},
+ {0x00009978, 0x00000001},
+ {0x0000997c, 0x00000000},
+ {0x00009980, 0x00000000},
+ {0x00009984, 0x00000000},
+ {0x00009988, 0x00000000},
+ {0x0000998c, 0x00000000},
+ {0x00009990, 0x00000000},
+ {0x00009994, 0x00000000},
+ {0x00009998, 0x00000000},
+ {0x0000999c, 0x00000000},
+ {0x000099a0, 0x00000000},
+ {0x000099a4, 0x00000001},
+ {0x000099a8, 0x201fff00},
+ {0x000099ac, 0x2def0400},
+ {0x000099b0, 0x03051000},
+ {0x000099b4, 0x00000820},
+ {0x000099dc, 0x00000000},
+ {0x000099e0, 0x00000000},
+ {0x000099e4, 0xaaaaaaaa},
+ {0x000099e8, 0x3c466478},
+ {0x000099ec, 0x0cc80caa},
+ {0x000099f0, 0x00000000},
+ {0x0000a208, 0x803e68c8},
+ {0x0000a210, 0x4080a333},
+ {0x0000a214, 0x00206c10},
+ {0x0000a218, 0x009c4060},
+ {0x0000a220, 0x01834061},
+ {0x0000a224, 0x00000400},
+ {0x0000a228, 0x000003b5},
+ {0x0000a22c, 0x00000000},
+ {0x0000a234, 0x20202020},
+ {0x0000a238, 0x20202020},
+ {0x0000a244, 0x00000000},
+ {0x0000a248, 0xfffffffc},
+ {0x0000a24c, 0x00000000},
+ {0x0000a254, 0x00000000},
+ {0x0000a258, 0x0ccb5380},
+ {0x0000a25c, 0x15151501},
+ {0x0000a260, 0xdfa90f01},
+ {0x0000a268, 0x00000000},
+ {0x0000a26c, 0x0ebae9e6},
+ {0x0000a388, 0x0c000000},
+ {0x0000a38c, 0x20202020},
+ {0x0000a390, 0x20202020},
+ {0x0000a39c, 0x00000001},
+ {0x0000a3a0, 0x00000000},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0x00000000},
+ {0x0000a3ac, 0x00000000},
+ {0x0000a3b0, 0x00000000},
+ {0x0000a3b4, 0x00000000},
+ {0x0000a3b8, 0x00000000},
+ {0x0000a3bc, 0x00000000},
+ {0x0000a3c0, 0x00000000},
+ {0x0000a3c4, 0x00000000},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3e4, 0x00000000},
+ {0x0000a3e8, 0x18c43433},
+ {0x0000a3ec, 0x00f70081},
+ {0x0000a3f0, 0x01036a2f},
+ {0x0000a3f4, 0x00000000},
+ {0x0000d270, 0x0d820820},
+ {0x0000d35c, 0x07ffffef},
+ {0x0000d360, 0x0fffffe7},
+ {0x0000d364, 0x17ffffe5},
+ {0x0000d368, 0x1fffffe4},
+ {0x0000d36c, 0x37ffffe3},
+ {0x0000d370, 0x3fffffe3},
+ {0x0000d374, 0x57ffffe3},
+ {0x0000d378, 0x5fffffe2},
+ {0x0000d37c, 0x7fffffe2},
+ {0x0000d380, 0x7f3c7bba},
+ {0x0000d384, 0xf3307ff0},
+};
+
+static const u32 ar9271Common_normal_cck_fir_coeff_9271[][2] = {
+ /* Addr allmodes */
+ {0x0000a1f4, 0x00fffeff},
+ {0x0000a1f8, 0x00f5f9ff},
+ {0x0000a1fc, 0xb79f6427},
+};
+
+static const u32 ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = {
+ /* Addr allmodes */
+ {0x0000a1f4, 0x00000000},
+ {0x0000a1f8, 0xefff0301},
+ {0x0000a1fc, 0xca9228ee},
+};
+
+static const u32 ar9271Modes_9271_1_0_only[][6] = {
+ {0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+};
+
+static const u32 ar9271Modes_9271_ANI_reg[][6] = {
+ {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+ {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e},
+ {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881, 0x06903881},
+ {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8},
+ {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d},
+ {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+};
+
+static const u32 ar9271Modes_normal_power_tx_gain_9271[][6] = {
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000},
+ {0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000},
+ {0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000},
+ {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029, 0x00000029},
+ {0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff},
+ {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+ {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+ {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652},
+ {0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+ {0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd},
+ {0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+ {0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
+ {0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+ {0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
+};
+
+static const u32 ar9271Modes_high_power_tx_gain_9271[][6] = {
+ {0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200, 0x00000000},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201, 0x00000000},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240, 0x00000000},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241, 0x00000000},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600, 0x00000000},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800, 0x00000000},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802, 0x00000000},
+ {0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805, 0x00000000},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41, 0x00000000},
+ {0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80, 0x00000000},
+ {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
+ {0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b},
+ {0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff},
+ {0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba, 0x08609eb6},
+ {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+ {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a214652, 0x0a214652, 0x0a22a652},
+ {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063, 0x05018063},
+ {0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
+ {0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
+ {0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
+ {0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9002_phy.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9002_phy.h
new file mode 100644
index 00000000..453af6dc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9002_phy.h
@@ -0,0 +1,613 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef AR9002_PHY_H
+#define AR9002_PHY_H
+
+#define AR_PHY_TEST 0x9800
+#define PHY_AGC_CLR 0x10000000
+#define RFSILENT_BB 0x00002000
+
+#define AR_PHY_TURBO 0x9804
+#define AR_PHY_FC_TURBO_MODE 0x00000001
+#define AR_PHY_FC_TURBO_SHORT 0x00000002
+#define AR_PHY_FC_DYN2040_EN 0x00000004
+#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008
+#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010
+/* For 25 MHz channel spacing -- not used but supported by hw */
+#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020
+#define AR_PHY_FC_HT_EN 0x00000040
+#define AR_PHY_FC_SHORT_GI_40 0x00000080
+#define AR_PHY_FC_WALSH 0x00000100
+#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200
+#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800
+
+#define AR_PHY_TEST2 0x9808
+
+#define AR_PHY_TIMING2 0x9810
+#define AR_PHY_TIMING3 0x9814
+#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000
+#define AR_PHY_TIMING3_DSC_MAN_S 17
+#define AR_PHY_TIMING3_DSC_EXP 0x0001E000
+#define AR_PHY_TIMING3_DSC_EXP_S 13
+
+#define AR_PHY_CHIP_ID_REV_0 0x80
+#define AR_PHY_CHIP_ID_REV_1 0x81
+#define AR_PHY_CHIP_ID_9160_REV_0 0xb0
+
+#define AR_PHY_ACTIVE 0x981C
+#define AR_PHY_ACTIVE_EN 0x00000001
+#define AR_PHY_ACTIVE_DIS 0x00000000
+
+#define AR_PHY_RF_CTL2 0x9824
+#define AR_PHY_TX_END_DATA_START 0x000000FF
+#define AR_PHY_TX_END_DATA_START_S 0
+#define AR_PHY_TX_END_PA_ON 0x0000FF00
+#define AR_PHY_TX_END_PA_ON_S 8
+
+#define AR_PHY_RF_CTL3 0x9828
+#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000
+#define AR_PHY_TX_END_TO_A2_RX_ON_S 16
+
+#define AR_PHY_ADC_CTL 0x982C
+#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003
+#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0
+#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000
+#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000
+#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000
+#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000
+#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16
+
+#define AR_PHY_ADC_SERIAL_CTL 0x9830
+#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000
+#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001
+
+#define AR_PHY_RF_CTL4 0x9834
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0
+
+#define AR_PHY_TSTDAC_CONST 0x983c
+
+#define AR_PHY_SETTLING 0x9844
+#define AR_PHY_SETTLING_SWITCH 0x00003F80
+#define AR_PHY_SETTLING_SWITCH_S 7
+
+#define AR_PHY_RXGAIN 0x9848
+#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000
+#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12
+#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000
+#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14
+
+#define AR_PHY_DESIRED_SZ 0x9850
+#define AR_PHY_DESIRED_SZ_ADC 0x000000FF
+#define AR_PHY_DESIRED_SZ_ADC_S 0
+#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00
+#define AR_PHY_DESIRED_SZ_PGA_S 8
+#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000
+#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
+
+#define AR_PHY_FIND_SIG 0x9858
+#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000
+#define AR_PHY_FIND_SIG_FIRSTEP_S 12
+#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000
+#define AR_PHY_FIND_SIG_FIRPWR_S 18
+
+#define AR_PHY_FIND_SIG_LOW 0x9840
+#define AR_PHY_FIND_SIG_FIRSTEP_LOW 0x00000FC0L
+#define AR_PHY_FIND_SIG_FIRSTEP_LOW_S 6
+
+#define AR_PHY_AGC_CTL1 0x985C
+#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80
+#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7
+#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000
+#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15
+
+#define AR_PHY_CCA 0x9864
+#define AR_PHY_MINCCA_PWR 0x0FF80000
+#define AR_PHY_MINCCA_PWR_S 19
+#define AR_PHY_CCA_THRESH62 0x0007F000
+#define AR_PHY_CCA_THRESH62_S 12
+#define AR9280_PHY_MINCCA_PWR 0x1FF00000
+#define AR9280_PHY_MINCCA_PWR_S 20
+#define AR9280_PHY_CCA_THRESH62 0x000FF000
+#define AR9280_PHY_CCA_THRESH62_S 12
+
+#define AR_PHY_SFCORR_LOW 0x986C
+#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21
+
+#define AR_PHY_SFCORR 0x9868
+#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F
+#define AR_PHY_SFCORR_M2COUNT_THR_S 0
+#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000
+#define AR_PHY_SFCORR_M1_THRESH_S 17
+#define AR_PHY_SFCORR_M2_THRESH 0x7F000000
+#define AR_PHY_SFCORR_M2_THRESH_S 24
+
+#define AR_PHY_SLEEP_CTR_CONTROL 0x9870
+#define AR_PHY_SLEEP_CTR_LIMIT 0x9874
+#define AR_PHY_SYNTH_CONTROL 0x9874
+#define AR_PHY_SLEEP_SCAL 0x9878
+
+#define AR_PHY_PLL_CTL 0x987c
+#define AR_PHY_PLL_CTL_40 0xaa
+#define AR_PHY_PLL_CTL_40_5413 0x04
+#define AR_PHY_PLL_CTL_44 0xab
+#define AR_PHY_PLL_CTL_44_2133 0xeb
+#define AR_PHY_PLL_CTL_40_2133 0xea
+
+#define AR_PHY_SPECTRAL_SCAN 0x9910 /* AR9280 spectral scan configuration register */
+#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1
+#define AR_PHY_SPECTRAL_SCAN_ENA 0x00000001 /* Enable spectral scan, reg 68, bit 0 */
+#define AR_PHY_SPECTRAL_SCAN_ENA_S 0 /* Enable spectral scan, reg 68, bit 0 */
+#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 /* Activate spectral scan reg 68, bit 1*/
+#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 /* Activate spectral scan reg 68, bit 1*/
+#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 /* Interval for FFT reports, reg 68, bits 4-7*/
+#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4
+#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 /* Interval for FFT reports, reg 68, bits 8-15*/
+#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8
+#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 /* Number of reports, reg 68, bits 16-23*/
+#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16
+#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 /* Short repeat, reg 68, bit 24*/
+#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 /* Short repeat, reg 68, bit 24*/
+
+#define AR_PHY_RX_DELAY 0x9914
+#define AR_PHY_SEARCH_START_DELAY 0x9918
+#define AR_PHY_RX_DELAY_DELAY 0x00003FFF
+
+#define AR_PHY_TIMING_CTRL4(_i) (0x9920 + ((_i) << 12))
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5
+#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12
+#define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000
+
+#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000
+#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000
+#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000
+#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000
+
+#define AR_PHY_TIMING5 0x9924
+#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE
+#define AR_PHY_TIMING5_CYCPWR_THR1_S 1
+
+#define AR_PHY_POWER_TX_RATE1 0x9934
+#define AR_PHY_POWER_TX_RATE2 0x9938
+#define AR_PHY_POWER_TX_RATE_MAX 0x993c
+#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
+
+#define AR_PHY_FRAME_CTL 0x9944
+#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038
+#define AR_PHY_FRAME_CTL_TX_CLIP_S 3
+
+#define AR_PHY_TXPWRADJ 0x994C
+#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0
+#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6
+#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000
+#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18
+
+#define AR_PHY_RADAR_EXT 0x9940
+#define AR_PHY_RADAR_EXT_ENA 0x00004000
+
+#define AR_PHY_RADAR_0 0x9954
+#define AR_PHY_RADAR_0_ENA 0x00000001
+#define AR_PHY_RADAR_0_FFT_ENA 0x80000000
+#define AR_PHY_RADAR_0_INBAND 0x0000003e
+#define AR_PHY_RADAR_0_INBAND_S 1
+#define AR_PHY_RADAR_0_PRSSI 0x00000FC0
+#define AR_PHY_RADAR_0_PRSSI_S 6
+#define AR_PHY_RADAR_0_HEIGHT 0x0003F000
+#define AR_PHY_RADAR_0_HEIGHT_S 12
+#define AR_PHY_RADAR_0_RRSSI 0x00FC0000
+#define AR_PHY_RADAR_0_RRSSI_S 18
+#define AR_PHY_RADAR_0_FIRPWR 0x7F000000
+#define AR_PHY_RADAR_0_FIRPWR_S 24
+
+#define AR_PHY_RADAR_1 0x9958
+#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000
+#define AR_PHY_RADAR_1_USE_FIR128 0x00400000
+#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000
+#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16
+#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000
+#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000
+#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000
+#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00
+#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
+#define AR_PHY_RADAR_1_MAXLEN 0x000000FF
+#define AR_PHY_RADAR_1_MAXLEN_S 0
+
+#define AR_PHY_SWITCH_CHAIN_0 0x9960
+#define AR_PHY_SWITCH_COM 0x9964
+
+#define AR_PHY_SIGMA_DELTA 0x996C
+#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003
+#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0
+#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8
+#define AR_PHY_SIGMA_DELTA_FILT2_S 3
+#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00
+#define AR_PHY_SIGMA_DELTA_FILT1_S 8
+#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000
+#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13
+
+#define AR_PHY_RESTART 0x9970
+#define AR_PHY_RESTART_DIV_GC 0x001C0000
+#define AR_PHY_RESTART_DIV_GC_S 18
+
+#define AR_PHY_RFBUS_REQ 0x997C
+#define AR_PHY_RFBUS_REQ_EN 0x00000001
+
+#define AR_PHY_TIMING7 0x9980
+#define AR_PHY_TIMING8 0x9984
+#define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF
+#define AR_PHY_TIMING8_PILOT_MASK_2_S 0
+
+#define AR_PHY_BIN_MASK2_1 0x9988
+#define AR_PHY_BIN_MASK2_2 0x998c
+#define AR_PHY_BIN_MASK2_3 0x9990
+#define AR_PHY_BIN_MASK2_4 0x9994
+
+#define AR_PHY_BIN_MASK_1 0x9900
+#define AR_PHY_BIN_MASK_2 0x9904
+#define AR_PHY_BIN_MASK_3 0x9908
+
+#define AR_PHY_MASK_CTL 0x990c
+
+#define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF
+#define AR_PHY_BIN_MASK2_4_MASK_4_S 0
+
+#define AR_PHY_TIMING9 0x9998
+#define AR_PHY_TIMING10 0x999c
+#define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF
+#define AR_PHY_TIMING10_PILOT_MASK_2_S 0
+
+#define AR_PHY_TIMING11 0x99a0
+#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF
+#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0
+#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000
+#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000
+
+#define AR_PHY_RX_CHAINMASK 0x99a4
+#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12))
+#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
+#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
+
+#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac
+#define AR_PHY_9285_FAST_DIV_BIAS 0x00007E00
+#define AR_PHY_9285_FAST_DIV_BIAS_S 9
+#define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000
+#define AR_PHY_9285_ANT_DIV_CTL 0x01000000
+#define AR_PHY_9285_ANT_DIV_CTL_S 24
+#define AR_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000
+#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S 25
+#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000
+#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27
+#define AR_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000
+#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29
+#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000
+#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30
+#define AR_PHY_9285_ANT_DIV_LNA1 2
+#define AR_PHY_9285_ANT_DIV_LNA2 1
+#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3
+#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0
+#define AR_PHY_9285_ANT_DIV_GAINTB_0 0
+#define AR_PHY_9285_ANT_DIV_GAINTB_1 1
+
+#define AR_PHY_EXT_CCA0 0x99b8
+#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF
+#define AR_PHY_EXT_CCA0_THRESH62_S 0
+
+#define AR_PHY_EXT_CCA 0x99bc
+#define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00
+#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9
+#define AR_PHY_EXT_CCA_THRESH62 0x007F0000
+#define AR_PHY_EXT_CCA_THRESH62_S 16
+#define AR_PHY_EXT_TIMING5_CYCPWR_THR1 0x0000FE00L
+#define AR_PHY_EXT_TIMING5_CYCPWR_THR1_S 9
+
+#define AR_PHY_EXT_MINCCA_PWR 0xFF800000
+#define AR_PHY_EXT_MINCCA_PWR_S 23
+#define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000
+#define AR9280_PHY_EXT_MINCCA_PWR_S 16
+
+#define AR_PHY_SFCORR_EXT 0x99c0
+#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F
+#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0
+#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80
+#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
+#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28
+
+#define AR_PHY_HALFGI 0x99D0
+#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0
+#define AR_PHY_HALFGI_DSC_MAN_S 4
+#define AR_PHY_HALFGI_DSC_EXP 0x0000000F
+#define AR_PHY_HALFGI_DSC_EXP_S 0
+
+#define AR_PHY_CHAN_INFO_MEMORY 0x99DC
+#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001
+
+#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0
+
+#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS 0x99EC
+#define AR_PHY_RIFS_INIT_DELAY 0x03ff0000
+
+#define AR_PHY_M_SLEEP 0x99f0
+#define AR_PHY_REFCLKDLY 0x99f4
+#define AR_PHY_REFCLKPD 0x99f8
+
+#define AR_PHY_CALMODE 0x99f0
+
+#define AR_PHY_CALMODE_IQ 0x00000000
+#define AR_PHY_CALMODE_ADC_GAIN 0x00000001
+#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002
+#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003
+
+#define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12))
+#define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12))
+#define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12))
+#define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12))
+
+#define AR_PHY_CURRENT_RSSI 0x9c1c
+#define AR9280_PHY_CURRENT_RSSI 0x9c3c
+
+#define AR_PHY_RFBUS_GRANT 0x9C20
+#define AR_PHY_RFBUS_GRANT_EN 0x00000001
+
+#define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4
+#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
+
+#define AR_PHY_CHAN_INFO_GAIN 0x9CFC
+
+#define AR_PHY_MODE 0xA200
+#define AR_PHY_MODE_ASYNCFIFO 0x80
+#define AR_PHY_MODE_AR2133 0x08
+#define AR_PHY_MODE_AR5111 0x00
+#define AR_PHY_MODE_AR5112 0x08
+#define AR_PHY_MODE_DYNAMIC 0x04
+#define AR_PHY_MODE_RF2GHZ 0x02
+#define AR_PHY_MODE_RF5GHZ 0x00
+#define AR_PHY_MODE_CCK 0x01
+#define AR_PHY_MODE_OFDM 0x00
+#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100
+
+#define AR_PHY_CCK_TX_CTRL 0xA204
+#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
+#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C
+#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2
+
+#define AR_PHY_CCK_DETECT 0xA208
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0
+/* [12:6] settling time for antenna switch */
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
+#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
+#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13
+
+#define AR_PHY_GAIN_2GHZ 0xA20C
+#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000
+#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0
+
+#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003E0000
+#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17
+#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001F000
+#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12
+#define AR_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000FC0
+#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6
+#define AR_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003F
+#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0
+
+#define AR_PHY_CCK_RXCTRL4 0xA21C
+#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000
+#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19
+
+#define AR_PHY_DAG_CTRLCCK 0xA228
+#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10
+
+#define AR_PHY_FORCE_CLKEN_CCK 0xA22C
+#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040
+
+#define AR_PHY_POWER_TX_RATE3 0xA234
+#define AR_PHY_POWER_TX_RATE4 0xA238
+
+#define AR_PHY_SCRM_SEQ_XR 0xA23C
+#define AR_PHY_HEADER_DETECT_XR 0xA240
+#define AR_PHY_CHIRP_DETECTED_XR 0xA244
+#define AR_PHY_BLUETOOTH 0xA254
+
+#define AR_PHY_TPCRG1 0xA258
+#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000
+#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
+
+#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000
+#define AR_PHY_TPCRG1_PD_GAIN_1_S 16
+#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000
+#define AR_PHY_TPCRG1_PD_GAIN_2_S 18
+#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000
+#define AR_PHY_TPCRG1_PD_GAIN_3_S 20
+
+#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000
+#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22
+
+#define AR_PHY_TX_PWRCTRL4 0xa264
+#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001
+#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0
+#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE
+#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1
+
+#define AR_PHY_TX_PWRCTRL6_0 0xa270
+#define AR_PHY_TX_PWRCTRL6_1 0xb270
+#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000
+#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24
+
+#define AR_PHY_TX_PWRCTRL7 0xa274
+#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000
+#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19
+
+#define AR_PHY_TX_PWRCTRL8 0xa278
+
+#define AR_PHY_TX_PWRCTRL9 0xa27C
+
+#define AR_PHY_TX_PWRCTRL10 0xa394
+#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00
+#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10
+#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000
+#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31
+
+#define AR_PHY_TX_GAIN_TBL1 0xa300
+#define AR_PHY_TX_GAIN 0x0007F000
+#define AR_PHY_TX_GAIN_S 12
+
+#define AR_PHY_CH0_TX_PWRCTRL11 0xa398
+#define AR_PHY_CH1_TX_PWRCTRL11 0xb398
+#define AR_PHY_CH0_TX_PWRCTRL12 0xa3dc
+#define AR_PHY_CH0_TX_PWRCTRL13 0xa3e0
+#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00
+#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10
+
+#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
+#define AR_PHY_MASK2_M_31_45 0xa3a4
+#define AR_PHY_MASK2_M_16_30 0xa3a8
+#define AR_PHY_MASK2_M_00_15 0xa3ac
+#define AR_PHY_MASK2_P_15_01 0xa3b8
+#define AR_PHY_MASK2_P_30_16 0xa3bc
+#define AR_PHY_MASK2_P_45_31 0xa3c0
+#define AR_PHY_MASK2_P_61_45 0xa3c4
+#define AR_PHY_SPUR_REG 0x994c
+
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18)
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18
+
+#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000
+#define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9)
+#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9
+#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0
+
+#define AR_PHY_PILOT_MASK_01_30 0xa3b0
+#define AR_PHY_PILOT_MASK_31_60 0xa3b4
+
+#define AR_PHY_CHANNEL_MASK_01_30 0x99d4
+#define AR_PHY_CHANNEL_MASK_31_60 0x99d8
+
+#define AR_PHY_ANALOG_SWAP 0xa268
+#define AR_PHY_SWAP_ALT_CHAIN 0x00000040
+
+#define AR_PHY_TPCRG5 0xA26C
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22
+
+/* Carrier leak calibration control, do it after AGC calibration */
+#define AR_PHY_CL_CAL_CTL 0xA358
+#define AR_PHY_CL_CAL_ENABLE 0x00000002
+#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001
+
+#define AR_PHY_POWER_TX_RATE5 0xA38C
+#define AR_PHY_POWER_TX_RATE6 0xA390
+
+#define AR_PHY_CAL_CHAINMASK 0xA39C
+
+#define AR_PHY_POWER_TX_SUB 0xA3C8
+#define AR_PHY_POWER_TX_RATE7 0xA3CC
+#define AR_PHY_POWER_TX_RATE8 0xA3D0
+#define AR_PHY_POWER_TX_RATE9 0xA3D4
+
+#define AR_PHY_XPA_CFG 0xA3D8
+#define AR_PHY_FORCE_XPA_CFG 0x000000001
+#define AR_PHY_FORCE_XPA_CFG_S 0
+
+#define AR_PHY_CH1_CCA 0xa864
+#define AR_PHY_CH1_MINCCA_PWR 0x0FF80000
+#define AR_PHY_CH1_MINCCA_PWR_S 19
+#define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000
+#define AR9280_PHY_CH1_MINCCA_PWR_S 20
+
+#define AR_PHY_CH2_CCA 0xb864
+#define AR_PHY_CH2_MINCCA_PWR 0x0FF80000
+#define AR_PHY_CH2_MINCCA_PWR_S 19
+
+#define AR_PHY_CH1_EXT_CCA 0xa9bc
+#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000
+#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23
+#define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000
+#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16
+
+#define AR_PHY_CH2_EXT_CCA 0xb9bc
+#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000
+#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23
+
+#define AR_PHY_CCA_NOM_VAL_5416_2GHZ -90
+#define AR_PHY_CCA_NOM_VAL_5416_5GHZ -100
+#define AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ -100
+#define AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ -110
+#define AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ -80
+#define AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ -90
+
+#define AR_PHY_CCA_NOM_VAL_9280_2GHZ -112
+#define AR_PHY_CCA_NOM_VAL_9280_5GHZ -112
+#define AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ -127
+#define AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ -122
+#define AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ -97
+#define AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ -102
+
+#define AR_PHY_CCA_NOM_VAL_9285_2GHZ -118
+#define AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ -127
+#define AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ -108
+
+#define AR_PHY_CCA_NOM_VAL_9271_2GHZ -118
+#define AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ -127
+#define AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ -116
+
+#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -120
+#define AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ -127
+#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -110
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_2p2_initvals.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_2p2_initvals.h
new file mode 100644
index 00000000..e8ac70da
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_2p2_initvals.h
@@ -0,0 +1,1864 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9003_2P2_H
+#define INITVALS_9003_2P2_H
+
+/* AR9003 2.2 */
+
+static const u32 ar9300_2p2_radio_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31},
+ {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800},
+ {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20},
+ {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+ {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+ {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+};
+
+static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+ {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
+ {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+ {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+ {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+ {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+ {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+ {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+ {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+ {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+ {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+ {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+ {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
+ {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
+ {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
+ {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
+ {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
+ {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
+ {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
+ {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+ {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+ {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+ {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
+ {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+ {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+ {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+ {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+ {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+ {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+ {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+ {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+ {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+ {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
+ {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
+ {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
+ {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
+ {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
+ {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
+ {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
+ {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
+ {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
+ {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+ {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+ {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+ {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+ {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+ {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+static const u32 ar9300Modes_fast_clock_2p2[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x00001030, 0x00000268, 0x000004d0},
+ {0x00001070, 0x0000018c, 0x00000318},
+ {0x000010b0, 0x00000fd0, 0x00001fa0},
+ {0x00008014, 0x044c044c, 0x08980898},
+ {0x0000801c, 0x148ec02b, 0x148ec057},
+ {0x00008318, 0x000044c0, 0x00008980},
+ {0x00009e00, 0x0372131c, 0x0372131c},
+ {0x0000a230, 0x0000000b, 0x00000016},
+ {0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9300_2p2_radio_core[][2] = {
+ /* Addr allmodes */
+ {0x00016000, 0x36db6db6},
+ {0x00016004, 0x6db6db40},
+ {0x00016008, 0x73f00000},
+ {0x0001600c, 0x00000000},
+ {0x00016040, 0x7f80fff8},
+ {0x0001604c, 0x76d005b5},
+ {0x00016050, 0x556cf031},
+ {0x00016054, 0x13449440},
+ {0x00016058, 0x0c51c92c},
+ {0x0001605c, 0x3db7fffc},
+ {0x00016060, 0xfffffffc},
+ {0x00016064, 0x000f0278},
+ {0x0001606c, 0x6db60000},
+ {0x00016080, 0x00000000},
+ {0x00016084, 0x0e48048c},
+ {0x00016088, 0x54214514},
+ {0x0001608c, 0x119f481e},
+ {0x00016090, 0x24926490},
+ {0x00016098, 0xd2888888},
+ {0x000160a0, 0x0a108ffe},
+ {0x000160a4, 0x812fc370},
+ {0x000160a8, 0x423c8000},
+ {0x000160b4, 0x92480080},
+ {0x000160c0, 0x00adb6d0},
+ {0x000160c4, 0x6db6db60},
+ {0x000160c8, 0x6db6db6c},
+ {0x000160cc, 0x01e6c000},
+ {0x00016100, 0x3fffbe01},
+ {0x00016104, 0xfff80000},
+ {0x00016108, 0x00080010},
+ {0x00016144, 0x02084080},
+ {0x00016148, 0x00000000},
+ {0x00016280, 0x058a0001},
+ {0x00016284, 0x3d840208},
+ {0x00016288, 0x05a20408},
+ {0x0001628c, 0x00038c07},
+ {0x00016290, 0x00000004},
+ {0x00016294, 0x458aa14f},
+ {0x00016380, 0x00000000},
+ {0x00016384, 0x00000000},
+ {0x00016388, 0x00800700},
+ {0x0001638c, 0x00800700},
+ {0x00016390, 0x00800700},
+ {0x00016394, 0x00000000},
+ {0x00016398, 0x00000000},
+ {0x0001639c, 0x00000000},
+ {0x000163a0, 0x00000001},
+ {0x000163a4, 0x00000001},
+ {0x000163a8, 0x00000000},
+ {0x000163ac, 0x00000000},
+ {0x000163b0, 0x00000000},
+ {0x000163b4, 0x00000000},
+ {0x000163b8, 0x00000000},
+ {0x000163bc, 0x00000000},
+ {0x000163c0, 0x000000a0},
+ {0x000163c4, 0x000c0000},
+ {0x000163c8, 0x14021402},
+ {0x000163cc, 0x00001402},
+ {0x000163d0, 0x00000000},
+ {0x000163d4, 0x00000000},
+ {0x00016400, 0x36db6db6},
+ {0x00016404, 0x6db6db40},
+ {0x00016408, 0x73f00000},
+ {0x0001640c, 0x00000000},
+ {0x00016440, 0x7f80fff8},
+ {0x0001644c, 0x76d005b5},
+ {0x00016450, 0x556cf031},
+ {0x00016454, 0x13449440},
+ {0x00016458, 0x0c51c92c},
+ {0x0001645c, 0x3db7fffc},
+ {0x00016460, 0xfffffffc},
+ {0x00016464, 0x000f0278},
+ {0x0001646c, 0x6db60000},
+ {0x00016500, 0x3fffbe01},
+ {0x00016504, 0xfff80000},
+ {0x00016508, 0x00080010},
+ {0x00016544, 0x02084080},
+ {0x00016548, 0x00000000},
+ {0x00016780, 0x00000000},
+ {0x00016784, 0x00000000},
+ {0x00016788, 0x00800700},
+ {0x0001678c, 0x00800700},
+ {0x00016790, 0x00800700},
+ {0x00016794, 0x00000000},
+ {0x00016798, 0x00000000},
+ {0x0001679c, 0x00000000},
+ {0x000167a0, 0x00000001},
+ {0x000167a4, 0x00000001},
+ {0x000167a8, 0x00000000},
+ {0x000167ac, 0x00000000},
+ {0x000167b0, 0x00000000},
+ {0x000167b4, 0x00000000},
+ {0x000167b8, 0x00000000},
+ {0x000167bc, 0x00000000},
+ {0x000167c0, 0x000000a0},
+ {0x000167c4, 0x000c0000},
+ {0x000167c8, 0x14021402},
+ {0x000167cc, 0x00001402},
+ {0x000167d0, 0x00000000},
+ {0x000167d4, 0x00000000},
+ {0x00016800, 0x36db6db6},
+ {0x00016804, 0x6db6db40},
+ {0x00016808, 0x73f00000},
+ {0x0001680c, 0x00000000},
+ {0x00016840, 0x7f80fff8},
+ {0x0001684c, 0x76d005b5},
+ {0x00016850, 0x556cf031},
+ {0x00016854, 0x13449440},
+ {0x00016858, 0x0c51c92c},
+ {0x0001685c, 0x3db7fffc},
+ {0x00016860, 0xfffffffc},
+ {0x00016864, 0x000f0278},
+ {0x0001686c, 0x6db60000},
+ {0x00016900, 0x3fffbe01},
+ {0x00016904, 0xfff80000},
+ {0x00016908, 0x00080010},
+ {0x00016944, 0x02084080},
+ {0x00016948, 0x00000000},
+ {0x00016b80, 0x00000000},
+ {0x00016b84, 0x00000000},
+ {0x00016b88, 0x00800700},
+ {0x00016b8c, 0x00800700},
+ {0x00016b90, 0x00800700},
+ {0x00016b94, 0x00000000},
+ {0x00016b98, 0x00000000},
+ {0x00016b9c, 0x00000000},
+ {0x00016ba0, 0x00000001},
+ {0x00016ba4, 0x00000001},
+ {0x00016ba8, 0x00000000},
+ {0x00016bac, 0x00000000},
+ {0x00016bb0, 0x00000000},
+ {0x00016bb4, 0x00000000},
+ {0x00016bb8, 0x00000000},
+ {0x00016bbc, 0x00000000},
+ {0x00016bc0, 0x000000a0},
+ {0x00016bc4, 0x000c0000},
+ {0x00016bc8, 0x14021402},
+ {0x00016bcc, 0x00001402},
+ {0x00016bd0, 0x00000000},
+ {0x00016bd4, 0x00000000},
+};
+
+static const u32 ar9300Common_rx_gain_table_merlin_2p2[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x02000101},
+ {0x0000a004, 0x02000102},
+ {0x0000a008, 0x02000103},
+ {0x0000a00c, 0x02000104},
+ {0x0000a010, 0x02000200},
+ {0x0000a014, 0x02000201},
+ {0x0000a018, 0x02000202},
+ {0x0000a01c, 0x02000203},
+ {0x0000a020, 0x02000204},
+ {0x0000a024, 0x02000205},
+ {0x0000a028, 0x02000208},
+ {0x0000a02c, 0x02000302},
+ {0x0000a030, 0x02000303},
+ {0x0000a034, 0x02000304},
+ {0x0000a038, 0x02000400},
+ {0x0000a03c, 0x02010300},
+ {0x0000a040, 0x02010301},
+ {0x0000a044, 0x02010302},
+ {0x0000a048, 0x02000500},
+ {0x0000a04c, 0x02010400},
+ {0x0000a050, 0x02020300},
+ {0x0000a054, 0x02020301},
+ {0x0000a058, 0x02020302},
+ {0x0000a05c, 0x02020303},
+ {0x0000a060, 0x02020400},
+ {0x0000a064, 0x02030300},
+ {0x0000a068, 0x02030301},
+ {0x0000a06c, 0x02030302},
+ {0x0000a070, 0x02030303},
+ {0x0000a074, 0x02030400},
+ {0x0000a078, 0x02040300},
+ {0x0000a07c, 0x02040301},
+ {0x0000a080, 0x02040302},
+ {0x0000a084, 0x02040303},
+ {0x0000a088, 0x02030500},
+ {0x0000a08c, 0x02040400},
+ {0x0000a090, 0x02050203},
+ {0x0000a094, 0x02050204},
+ {0x0000a098, 0x02050205},
+ {0x0000a09c, 0x02040500},
+ {0x0000a0a0, 0x02050301},
+ {0x0000a0a4, 0x02050302},
+ {0x0000a0a8, 0x02050303},
+ {0x0000a0ac, 0x02050400},
+ {0x0000a0b0, 0x02050401},
+ {0x0000a0b4, 0x02050402},
+ {0x0000a0b8, 0x02050403},
+ {0x0000a0bc, 0x02050500},
+ {0x0000a0c0, 0x02050501},
+ {0x0000a0c4, 0x02050502},
+ {0x0000a0c8, 0x02050503},
+ {0x0000a0cc, 0x02050504},
+ {0x0000a0d0, 0x02050600},
+ {0x0000a0d4, 0x02050601},
+ {0x0000a0d8, 0x02050602},
+ {0x0000a0dc, 0x02050603},
+ {0x0000a0e0, 0x02050604},
+ {0x0000a0e4, 0x02050700},
+ {0x0000a0e8, 0x02050701},
+ {0x0000a0ec, 0x02050702},
+ {0x0000a0f0, 0x02050703},
+ {0x0000a0f4, 0x02050704},
+ {0x0000a0f8, 0x02050705},
+ {0x0000a0fc, 0x02050708},
+ {0x0000a100, 0x02050709},
+ {0x0000a104, 0x0205070a},
+ {0x0000a108, 0x0205070b},
+ {0x0000a10c, 0x0205070c},
+ {0x0000a110, 0x0205070d},
+ {0x0000a114, 0x02050710},
+ {0x0000a118, 0x02050711},
+ {0x0000a11c, 0x02050712},
+ {0x0000a120, 0x02050713},
+ {0x0000a124, 0x02050714},
+ {0x0000a128, 0x02050715},
+ {0x0000a12c, 0x02050730},
+ {0x0000a130, 0x02050731},
+ {0x0000a134, 0x02050732},
+ {0x0000a138, 0x02050733},
+ {0x0000a13c, 0x02050734},
+ {0x0000a140, 0x02050735},
+ {0x0000a144, 0x02050750},
+ {0x0000a148, 0x02050751},
+ {0x0000a14c, 0x02050752},
+ {0x0000a150, 0x02050753},
+ {0x0000a154, 0x02050754},
+ {0x0000a158, 0x02050755},
+ {0x0000a15c, 0x02050770},
+ {0x0000a160, 0x02050771},
+ {0x0000a164, 0x02050772},
+ {0x0000a168, 0x02050773},
+ {0x0000a16c, 0x02050774},
+ {0x0000a170, 0x02050775},
+ {0x0000a174, 0x00000776},
+ {0x0000a178, 0x00000776},
+ {0x0000a17c, 0x00000776},
+ {0x0000a180, 0x00000776},
+ {0x0000a184, 0x00000776},
+ {0x0000a188, 0x00000776},
+ {0x0000a18c, 0x00000776},
+ {0x0000a190, 0x00000776},
+ {0x0000a194, 0x00000776},
+ {0x0000a198, 0x00000776},
+ {0x0000a19c, 0x00000776},
+ {0x0000a1a0, 0x00000776},
+ {0x0000a1a4, 0x00000776},
+ {0x0000a1a8, 0x00000776},
+ {0x0000a1ac, 0x00000776},
+ {0x0000a1b0, 0x00000776},
+ {0x0000a1b4, 0x00000776},
+ {0x0000a1b8, 0x00000776},
+ {0x0000a1bc, 0x00000776},
+ {0x0000a1c0, 0x00000776},
+ {0x0000a1c4, 0x00000776},
+ {0x0000a1c8, 0x00000776},
+ {0x0000a1cc, 0x00000776},
+ {0x0000a1d0, 0x00000776},
+ {0x0000a1d4, 0x00000776},
+ {0x0000a1d8, 0x00000776},
+ {0x0000a1dc, 0x00000776},
+ {0x0000a1e0, 0x00000776},
+ {0x0000a1e4, 0x00000776},
+ {0x0000a1e8, 0x00000776},
+ {0x0000a1ec, 0x00000776},
+ {0x0000a1f0, 0x00000776},
+ {0x0000a1f4, 0x00000776},
+ {0x0000a1f8, 0x00000776},
+ {0x0000a1fc, 0x00000776},
+ {0x0000b000, 0x02000101},
+ {0x0000b004, 0x02000102},
+ {0x0000b008, 0x02000103},
+ {0x0000b00c, 0x02000104},
+ {0x0000b010, 0x02000200},
+ {0x0000b014, 0x02000201},
+ {0x0000b018, 0x02000202},
+ {0x0000b01c, 0x02000203},
+ {0x0000b020, 0x02000204},
+ {0x0000b024, 0x02000205},
+ {0x0000b028, 0x02000208},
+ {0x0000b02c, 0x02000302},
+ {0x0000b030, 0x02000303},
+ {0x0000b034, 0x02000304},
+ {0x0000b038, 0x02000400},
+ {0x0000b03c, 0x02010300},
+ {0x0000b040, 0x02010301},
+ {0x0000b044, 0x02010302},
+ {0x0000b048, 0x02000500},
+ {0x0000b04c, 0x02010400},
+ {0x0000b050, 0x02020300},
+ {0x0000b054, 0x02020301},
+ {0x0000b058, 0x02020302},
+ {0x0000b05c, 0x02020303},
+ {0x0000b060, 0x02020400},
+ {0x0000b064, 0x02030300},
+ {0x0000b068, 0x02030301},
+ {0x0000b06c, 0x02030302},
+ {0x0000b070, 0x02030303},
+ {0x0000b074, 0x02030400},
+ {0x0000b078, 0x02040300},
+ {0x0000b07c, 0x02040301},
+ {0x0000b080, 0x02040302},
+ {0x0000b084, 0x02040303},
+ {0x0000b088, 0x02030500},
+ {0x0000b08c, 0x02040400},
+ {0x0000b090, 0x02050203},
+ {0x0000b094, 0x02050204},
+ {0x0000b098, 0x02050205},
+ {0x0000b09c, 0x02040500},
+ {0x0000b0a0, 0x02050301},
+ {0x0000b0a4, 0x02050302},
+ {0x0000b0a8, 0x02050303},
+ {0x0000b0ac, 0x02050400},
+ {0x0000b0b0, 0x02050401},
+ {0x0000b0b4, 0x02050402},
+ {0x0000b0b8, 0x02050403},
+ {0x0000b0bc, 0x02050500},
+ {0x0000b0c0, 0x02050501},
+ {0x0000b0c4, 0x02050502},
+ {0x0000b0c8, 0x02050503},
+ {0x0000b0cc, 0x02050504},
+ {0x0000b0d0, 0x02050600},
+ {0x0000b0d4, 0x02050601},
+ {0x0000b0d8, 0x02050602},
+ {0x0000b0dc, 0x02050603},
+ {0x0000b0e0, 0x02050604},
+ {0x0000b0e4, 0x02050700},
+ {0x0000b0e8, 0x02050701},
+ {0x0000b0ec, 0x02050702},
+ {0x0000b0f0, 0x02050703},
+ {0x0000b0f4, 0x02050704},
+ {0x0000b0f8, 0x02050705},
+ {0x0000b0fc, 0x02050708},
+ {0x0000b100, 0x02050709},
+ {0x0000b104, 0x0205070a},
+ {0x0000b108, 0x0205070b},
+ {0x0000b10c, 0x0205070c},
+ {0x0000b110, 0x0205070d},
+ {0x0000b114, 0x02050710},
+ {0x0000b118, 0x02050711},
+ {0x0000b11c, 0x02050712},
+ {0x0000b120, 0x02050713},
+ {0x0000b124, 0x02050714},
+ {0x0000b128, 0x02050715},
+ {0x0000b12c, 0x02050730},
+ {0x0000b130, 0x02050731},
+ {0x0000b134, 0x02050732},
+ {0x0000b138, 0x02050733},
+ {0x0000b13c, 0x02050734},
+ {0x0000b140, 0x02050735},
+ {0x0000b144, 0x02050750},
+ {0x0000b148, 0x02050751},
+ {0x0000b14c, 0x02050752},
+ {0x0000b150, 0x02050753},
+ {0x0000b154, 0x02050754},
+ {0x0000b158, 0x02050755},
+ {0x0000b15c, 0x02050770},
+ {0x0000b160, 0x02050771},
+ {0x0000b164, 0x02050772},
+ {0x0000b168, 0x02050773},
+ {0x0000b16c, 0x02050774},
+ {0x0000b170, 0x02050775},
+ {0x0000b174, 0x00000776},
+ {0x0000b178, 0x00000776},
+ {0x0000b17c, 0x00000776},
+ {0x0000b180, 0x00000776},
+ {0x0000b184, 0x00000776},
+ {0x0000b188, 0x00000776},
+ {0x0000b18c, 0x00000776},
+ {0x0000b190, 0x00000776},
+ {0x0000b194, 0x00000776},
+ {0x0000b198, 0x00000776},
+ {0x0000b19c, 0x00000776},
+ {0x0000b1a0, 0x00000776},
+ {0x0000b1a4, 0x00000776},
+ {0x0000b1a8, 0x00000776},
+ {0x0000b1ac, 0x00000776},
+ {0x0000b1b0, 0x00000776},
+ {0x0000b1b4, 0x00000776},
+ {0x0000b1b8, 0x00000776},
+ {0x0000b1bc, 0x00000776},
+ {0x0000b1c0, 0x00000776},
+ {0x0000b1c4, 0x00000776},
+ {0x0000b1c8, 0x00000776},
+ {0x0000b1cc, 0x00000776},
+ {0x0000b1d0, 0x00000776},
+ {0x0000b1d4, 0x00000776},
+ {0x0000b1d8, 0x00000776},
+ {0x0000b1dc, 0x00000776},
+ {0x0000b1e0, 0x00000776},
+ {0x0000b1e4, 0x00000776},
+ {0x0000b1e8, 0x00000776},
+ {0x0000b1ec, 0x00000776},
+ {0x0000b1f0, 0x00000776},
+ {0x0000b1f4, 0x00000776},
+ {0x0000b1f8, 0x00000776},
+ {0x0000b1fc, 0x00000776},
+};
+
+static const u32 ar9300_2p2_mac_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9300_2p2_soc_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
+};
+
+static const u32 ar9200_merlin_2p2_radio_core[][2] = {
+ /* Addr allmodes */
+ {0x00007800, 0x00040000},
+ {0x00007804, 0xdb005012},
+ {0x00007808, 0x04924914},
+ {0x0000780c, 0x21084210},
+ {0x00007810, 0x6d801300},
+ {0x00007814, 0x0019beff},
+ {0x00007818, 0x07e41000},
+ {0x0000781c, 0x00392000},
+ {0x00007820, 0x92592480},
+ {0x00007824, 0x00040000},
+ {0x00007828, 0xdb005012},
+ {0x0000782c, 0x04924914},
+ {0x00007830, 0x21084210},
+ {0x00007834, 0x6d801300},
+ {0x00007838, 0x0019beff},
+ {0x0000783c, 0x07e40000},
+ {0x00007840, 0x00392000},
+ {0x00007844, 0x92592480},
+ {0x00007848, 0x00100000},
+ {0x0000784c, 0x773f0567},
+ {0x00007850, 0x54214514},
+ {0x00007854, 0x12035828},
+ {0x00007858, 0x92592692},
+ {0x0000785c, 0x00000000},
+ {0x00007860, 0x56400000},
+ {0x00007864, 0x0a8e370e},
+ {0x00007868, 0xc0102850},
+ {0x0000786c, 0x812d4000},
+ {0x00007870, 0x807ec400},
+ {0x00007874, 0x001b6db0},
+ {0x00007878, 0x00376b63},
+ {0x0000787c, 0x06db6db6},
+ {0x00007880, 0x006d8000},
+ {0x00007884, 0xffeffffe},
+ {0x00007888, 0xffeffffe},
+ {0x0000788c, 0x00010000},
+ {0x00007890, 0x02060aeb},
+ {0x00007894, 0x5a108000},
+};
+
+static const u32 ar9300_2p2_baseband_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+ {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+ {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+ {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+ {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+ {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+ {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+ {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0},
+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a22c, 0x01026a2f, 0x01026a2f, 0x01026a2f, 0x01026a2f},
+ {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+ {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+ {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+ {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
+ {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982},
+ {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+ {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+ {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+ {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+ {0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+};
+
+static const u32 ar9300_2p2_baseband_core[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafe68e30},
+ {0x00009804, 0xfd14e000},
+ {0x00009808, 0x9c0a9f6b},
+ {0x0000980c, 0x04900000},
+ {0x00009814, 0x9280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+ {0x00009834, 0x6400a290},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x0d000600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+ {0x000098b0, 0x32840bbe},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+ {0x000098f0, 0x00000000},
+ {0x000098f4, 0x00000000},
+ {0x00009c04, 0xff55ff55},
+ {0x00009c08, 0x0320ff55},
+ {0x00009c0c, 0x00000000},
+ {0x00009c10, 0x00000000},
+ {0x00009c14, 0x00046384},
+ {0x00009c18, 0x05b6b440},
+ {0x00009c1c, 0x00b6b440},
+ {0x00009d00, 0xc080a333},
+ {0x00009d04, 0x40206c10},
+ {0x00009d08, 0x009c4060},
+ {0x00009d0c, 0x9883800a},
+ {0x00009d10, 0x01834061},
+ {0x00009d14, 0x00c0040b},
+ {0x00009d18, 0x00000000},
+ {0x00009e08, 0x0038230c},
+ {0x00009e24, 0x990bb515},
+ {0x00009e28, 0x0c6f0000},
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+ {0x00009e54, 0x00000000},
+ {0x00009fc0, 0x803e4788},
+ {0x00009fc4, 0x0001efb5},
+ {0x00009fcc, 0x40000014},
+ {0x00009fd0, 0x01193b93},
+ {0x0000a20c, 0x00000000},
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a2a0, 0x00000001},
+ {0x0000a2c0, 0x00000001},
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2cc, 0x18c43433},
+ {0x0000a2d4, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+ {0x0000a2f8, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a34c, 0x00000000},
+ {0x0000a350, 0x0000a000},
+ {0x0000a364, 0x00000000},
+ {0x0000a370, 0x00000000},
+ {0x0000a390, 0x00000001},
+ {0x0000a394, 0x00000444},
+ {0x0000a398, 0x001f0e0f},
+ {0x0000a39c, 0x0075393f},
+ {0x0000a3a0, 0xb79f6427},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0xaaaaaaaa},
+ {0x0000a3ac, 0x3c466478},
+ {0x0000a3c0, 0x20202020},
+ {0x0000a3c4, 0x22222220},
+ {0x0000a3c8, 0x20200020},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3d8, 0x20202020},
+ {0x0000a3dc, 0x20202020},
+ {0x0000a3e0, 0x20202020},
+ {0x0000a3e4, 0x20202020},
+ {0x0000a3e8, 0x20202020},
+ {0x0000a3ec, 0x20202020},
+ {0x0000a3f0, 0x00000000},
+ {0x0000a3f4, 0x00000246},
+ {0x0000a3f8, 0x0cdbd380},
+ {0x0000a3fc, 0x000f0f01},
+ {0x0000a400, 0x8fa91f01},
+ {0x0000a404, 0x00000000},
+ {0x0000a408, 0x0e79e5c6},
+ {0x0000a40c, 0x00820820},
+ {0x0000a414, 0x1ce739ce},
+ {0x0000a418, 0x2d001dce},
+ {0x0000a41c, 0x1ce739ce},
+ {0x0000a420, 0x000001ce},
+ {0x0000a424, 0x1ce739ce},
+ {0x0000a428, 0x000001ce},
+ {0x0000a42c, 0x1ce739ce},
+ {0x0000a430, 0x1ce739ce},
+ {0x0000a434, 0x00000000},
+ {0x0000a438, 0x00001801},
+ {0x0000a43c, 0x00100000},
+ {0x0000a440, 0x00000000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x06000080},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a458, 0x00000000},
+ {0x0000a640, 0x00000000},
+ {0x0000a644, 0x3fad9d74},
+ {0x0000a648, 0x0048060a},
+ {0x0000a64c, 0x00003c37},
+ {0x0000a670, 0x03020100},
+ {0x0000a674, 0x09080504},
+ {0x0000a678, 0x0d0c0b0a},
+ {0x0000a67c, 0x13121110},
+ {0x0000a680, 0x31301514},
+ {0x0000a684, 0x35343332},
+ {0x0000a688, 0x00000036},
+ {0x0000a690, 0x00000838},
+ {0x0000a7c0, 0x00000000},
+ {0x0000a7c4, 0xfffffffc},
+ {0x0000a7c8, 0x00000000},
+ {0x0000a7cc, 0x00000000},
+ {0x0000a7d0, 0x00000000},
+ {0x0000a7d4, 0x00000004},
+ {0x0000a7dc, 0x00000001},
+ {0x0000a8d0, 0x004b6a8e},
+ {0x0000a8d4, 0x00000820},
+ {0x0000a8dc, 0x00000000},
+ {0x0000a8f0, 0x00000000},
+ {0x0000a8f4, 0x00000000},
+ {0x0000b2d0, 0x00000080},
+ {0x0000b2d4, 0x00000000},
+ {0x0000b2ec, 0x00000000},
+ {0x0000b2f0, 0x00000000},
+ {0x0000b2f4, 0x00000000},
+ {0x0000b2f8, 0x00000000},
+ {0x0000b408, 0x0e79e5c0},
+ {0x0000b40c, 0x00820820},
+ {0x0000b420, 0x00000000},
+ {0x0000b8d0, 0x004b6a8e},
+ {0x0000b8d4, 0x00000820},
+ {0x0000b8dc, 0x00000000},
+ {0x0000b8f0, 0x00000000},
+ {0x0000b8f4, 0x00000000},
+ {0x0000c2d0, 0x00000080},
+ {0x0000c2d4, 0x00000000},
+ {0x0000c2ec, 0x00000000},
+ {0x0000c2f0, 0x00000000},
+ {0x0000c2f4, 0x00000000},
+ {0x0000c2f8, 0x00000000},
+ {0x0000c408, 0x0e79e5c0},
+ {0x0000c40c, 0x00820820},
+ {0x0000c420, 0x00000000},
+};
+
+static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+ {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
+ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
+ {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
+ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
+ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
+ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
+ {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
+ {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
+ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
+ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
+ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
+ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
+ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
+ {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
+ {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
+ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
+ {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
+ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
+ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
+ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
+ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
+ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
+ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
+ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
+ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
+ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
+ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
+ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
+ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
+ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
+ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
+ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
+ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
+ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
+ {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
+ {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
+ {0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
+ {0x00016448, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
+ {0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
+ {0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
+ {0x00016848, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
+ {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
+};
+
+static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+ {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
+ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
+ {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
+ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
+ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
+ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
+ {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
+ {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
+ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
+ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
+ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
+ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
+ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
+ {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
+ {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
+ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
+ {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
+ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
+ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
+ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
+ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
+ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
+ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
+ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
+ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
+ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
+ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
+ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
+ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
+ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
+ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
+ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
+ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
+ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
+ {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
+ {0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
+ {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
+ {0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
+ {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+static const u32 ar9300Common_rx_gain_table_2p2[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x01910190},
+ {0x0000a030, 0x01930192},
+ {0x0000a034, 0x01950194},
+ {0x0000a038, 0x038a0196},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x22222229},
+ {0x0000a084, 0x1d1d1d1d},
+ {0x0000a088, 0x1d1d1d1d},
+ {0x0000a08c, 0x1d1d1d1d},
+ {0x0000a090, 0x171d1d1d},
+ {0x0000a094, 0x11111717},
+ {0x0000a098, 0x00030311},
+ {0x0000a09c, 0x00000000},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x2a2d2f32},
+ {0x0000b084, 0x21232328},
+ {0x0000b088, 0x19191c1e},
+ {0x0000b08c, 0x12141417},
+ {0x0000b090, 0x07070e0e},
+ {0x0000b094, 0x03030305},
+ {0x0000b098, 0x00000003},
+ {0x0000b09c, 0x00000000},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+ {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
+ {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+ {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+ {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+ {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+ {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+ {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+ {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+ {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+ {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+ {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+ {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
+ {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
+ {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
+ {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
+ {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
+ {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
+ {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
+ {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+ {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+ {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+ {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
+ {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+ {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+ {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+ {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+ {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+ {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+ {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+ {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+ {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+ {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
+ {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
+ {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
+ {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
+ {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
+ {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
+ {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
+ {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
+ {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
+ {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+ {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+ {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+ {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+static const u32 ar9300_2p2_mac_core[][2] = {
+ /* Addr allmodes */
+ {0x00000008, 0x00000000},
+ {0x00000030, 0x00020085},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000000},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x000010f0, 0x00000100},
+ {0x00001270, 0x00000000},
+ {0x000012b0, 0x00000000},
+ {0x000012f0, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00008000, 0x00000000},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000000},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00000000},
+ {0x00008040, 0x00000000},
+ {0x00008044, 0x00000000},
+ {0x00008048, 0x00000000},
+ {0x0000804c, 0xffffffff},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x00008070, 0x00000310},
+ {0x00008074, 0x00000020},
+ {0x00008078, 0x00000000},
+ {0x0000809c, 0x0000000f},
+ {0x000080a0, 0x00000000},
+ {0x000080a4, 0x02ff0000},
+ {0x000080a8, 0x0e070605},
+ {0x000080ac, 0x0000000d},
+ {0x000080b0, 0x00000000},
+ {0x000080b4, 0x00000000},
+ {0x000080b8, 0x00000000},
+ {0x000080bc, 0x00000000},
+ {0x000080c0, 0x2a800000},
+ {0x000080c4, 0x06900168},
+ {0x000080c8, 0x13881c20},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00252500},
+ {0x000080d4, 0x00a00000},
+ {0x000080d8, 0x00400000},
+ {0x000080dc, 0x00000000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x3f3f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00000000},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000000},
+ {0x00008114, 0x000007ff},
+ {0x00008118, 0x000000aa},
+ {0x0000811c, 0x00003210},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x0000ffff},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x000081c0, 0x00000000},
+ {0x000081c4, 0x33332210},
+ {0x000081c8, 0x00000000},
+ {0x000081cc, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f424},
+ {0x00008248, 0x00000800},
+ {0x0000824c, 0x0001e848},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x40000000},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x9bc00010},
+ {0x00008268, 0xffffffff},
+ {0x0000826c, 0x0000ffff},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000004},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x000000ff},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x0000829c, 0x00000000},
+ {0x00008300, 0x00000140},
+ {0x00008314, 0x00000000},
+ {0x0000831c, 0x0000010d},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000007},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000700},
+ {0x00008338, 0x00ff0000},
+ {0x0000833c, 0x02400000},
+ {0x00008340, 0x000107ff},
+ {0x00008344, 0xaa48105b},
+ {0x00008348, 0x008f0000},
+ {0x0000835c, 0x00000000},
+ {0x00008360, 0xffffffff},
+ {0x00008364, 0xffffffff},
+ {0x00008368, 0x00000000},
+ {0x00008370, 0x00000000},
+ {0x00008374, 0x000000ff},
+ {0x00008378, 0x00000000},
+ {0x0000837c, 0x00000000},
+ {0x00008380, 0xffffffff},
+ {0x00008384, 0xffffffff},
+ {0x00008390, 0xffffffff},
+ {0x00008394, 0xffffffff},
+ {0x00008398, 0x00000000},
+ {0x0000839c, 0x00000000},
+ {0x000083a0, 0x00000000},
+ {0x000083a4, 0x0000fa14},
+ {0x000083a8, 0x000f0c00},
+ {0x000083ac, 0x33332210},
+ {0x000083b0, 0x33332210},
+ {0x000083b4, 0x33332210},
+ {0x000083b8, 0x33332210},
+ {0x000083bc, 0x00000000},
+ {0x000083c0, 0x00000000},
+ {0x000083c4, 0x00000000},
+ {0x000083c8, 0x00000000},
+ {0x000083cc, 0x00000200},
+ {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9300Common_wo_xlna_rx_gain_table_2p2[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x03820190},
+ {0x0000a030, 0x03840383},
+ {0x0000a034, 0x03880385},
+ {0x0000a038, 0x038a0389},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x29292929},
+ {0x0000a084, 0x29292929},
+ {0x0000a088, 0x29292929},
+ {0x0000a08c, 0x29292929},
+ {0x0000a090, 0x22292929},
+ {0x0000a094, 0x1d1d2222},
+ {0x0000a098, 0x0c111117},
+ {0x0000a09c, 0x00030303},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x32323232},
+ {0x0000b084, 0x2f2f3232},
+ {0x0000b088, 0x23282a2d},
+ {0x0000b08c, 0x1c1e2123},
+ {0x0000b090, 0x14171919},
+ {0x0000b094, 0x0e0e1214},
+ {0x0000b098, 0x03050707},
+ {0x0000b09c, 0x00030303},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9300_2p2_soc_preamble[][2] = {
+ /* Addr allmodes */
+ {0x000040a4, 0x00a0c1c9},
+ {0x00007008, 0x00000000},
+ {0x00007020, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+ {0x00007048, 0x00000008},
+};
+
+static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x0821265e},
+ {0x00004040, 0x0008003b},
+ {0x00004044, 0x00000000},
+};
+
+static const u32 ar9300PciePhy_clkreq_enable_L1_2p2[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x08253e5e},
+ {0x00004040, 0x0008003b},
+ {0x00004044, 0x00000000},
+};
+
+static const u32 ar9300PciePhy_clkreq_disable_L1_2p2[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x08213e5e},
+ {0x00004040, 0x0008003b},
+ {0x00004044, 0x00000000},
+};
+
+#endif /* INITVALS_9003_2P2_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_eeprom.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_eeprom.h
new file mode 100644
index 00000000..393f2de5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_eeprom.h
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef AR9003_EEPROM_H
+#define AR9003_EEPROM_H
+
+#define AR9300_EEP_VER 0xD000
+#define AR9300_EEP_VER_MINOR_MASK 0xFFF
+#define AR9300_EEP_MINOR_VER_1 0x1
+#define AR9300_EEP_MINOR_VER AR9300_EEP_MINOR_VER_1
+
+/* 16-bit offset location start of calibration struct */
+#define AR9300_EEP_START_LOC 256
+#define AR9300_NUM_5G_CAL_PIERS 8
+#define AR9300_NUM_2G_CAL_PIERS 3
+#define AR9300_NUM_5G_20_TARGET_POWERS 8
+#define AR9300_NUM_5G_40_TARGET_POWERS 8
+#define AR9300_NUM_2G_CCK_TARGET_POWERS 2
+#define AR9300_NUM_2G_20_TARGET_POWERS 3
+#define AR9300_NUM_2G_40_TARGET_POWERS 3
+/* #define AR9300_NUM_CTLS 21 */
+#define AR9300_NUM_CTLS_5G 9
+#define AR9300_NUM_CTLS_2G 12
+#define AR9300_NUM_BAND_EDGES_5G 8
+#define AR9300_NUM_BAND_EDGES_2G 4
+#define AR9300_EEPMISC_BIG_ENDIAN 0x01
+#define AR9300_EEPMISC_WOW 0x02
+#define AR9300_CUSTOMER_DATA_SIZE 20
+
+#define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x))
+#define AR9300_MAX_CHAINS 3
+#define AR9300_ANT_16S 25
+#define AR9300_FUTURE_MODAL_SZ 6
+
+#define AR9300_PAPRD_RATE_MASK 0x01ffffff
+#define AR9300_PAPRD_SCALE_1 0x0e000000
+#define AR9300_PAPRD_SCALE_1_S 25
+#define AR9300_PAPRD_SCALE_2 0x70000000
+#define AR9300_PAPRD_SCALE_2_S 28
+
+/* Delta from which to start power to pdadc table */
+/* This offset is used in both open loop and closed loop power control
+ * schemes. In open loop power control, it is not really needed, but for
+ * the "sake of consistency" it was kept. For certain AP designs, this
+ * value is overwritten by the value in the flag "pwrTableOffset" just
+ * before writing the pdadc vs pwr into the chip registers.
+ */
+#define AR9300_PWR_TABLE_OFFSET 0
+
+/* byte addressable */
+#define AR9300_EEPROM_SIZE (16*1024)
+
+#define AR9300_BASE_ADDR_4K 0xfff
+#define AR9300_BASE_ADDR 0x3ff
+#define AR9300_BASE_ADDR_512 0x1ff
+
+#define AR9300_OTP_BASE 0x14000
+#define AR9300_OTP_STATUS 0x15f18
+#define AR9300_OTP_STATUS_TYPE 0x7
+#define AR9300_OTP_STATUS_VALID 0x4
+#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2
+#define AR9300_OTP_STATUS_SM_BUSY 0x1
+#define AR9300_OTP_READ_DATA 0x15f1c
+
+enum targetPowerHTRates {
+ HT_TARGET_RATE_0_8_16,
+ HT_TARGET_RATE_1_3_9_11_17_19,
+ HT_TARGET_RATE_4,
+ HT_TARGET_RATE_5,
+ HT_TARGET_RATE_6,
+ HT_TARGET_RATE_7,
+ HT_TARGET_RATE_12,
+ HT_TARGET_RATE_13,
+ HT_TARGET_RATE_14,
+ HT_TARGET_RATE_15,
+ HT_TARGET_RATE_20,
+ HT_TARGET_RATE_21,
+ HT_TARGET_RATE_22,
+ HT_TARGET_RATE_23
+};
+
+enum targetPowerLegacyRates {
+ LEGACY_TARGET_RATE_6_24,
+ LEGACY_TARGET_RATE_36,
+ LEGACY_TARGET_RATE_48,
+ LEGACY_TARGET_RATE_54
+};
+
+enum targetPowerCckRates {
+ LEGACY_TARGET_RATE_1L_5L,
+ LEGACY_TARGET_RATE_5S,
+ LEGACY_TARGET_RATE_11L,
+ LEGACY_TARGET_RATE_11S
+};
+
+enum ar9300_Rates {
+ ALL_TARGET_LEGACY_6_24,
+ ALL_TARGET_LEGACY_36,
+ ALL_TARGET_LEGACY_48,
+ ALL_TARGET_LEGACY_54,
+ ALL_TARGET_LEGACY_1L_5L,
+ ALL_TARGET_LEGACY_5S,
+ ALL_TARGET_LEGACY_11L,
+ ALL_TARGET_LEGACY_11S,
+ ALL_TARGET_HT20_0_8_16,
+ ALL_TARGET_HT20_1_3_9_11_17_19,
+ ALL_TARGET_HT20_4,
+ ALL_TARGET_HT20_5,
+ ALL_TARGET_HT20_6,
+ ALL_TARGET_HT20_7,
+ ALL_TARGET_HT20_12,
+ ALL_TARGET_HT20_13,
+ ALL_TARGET_HT20_14,
+ ALL_TARGET_HT20_15,
+ ALL_TARGET_HT20_20,
+ ALL_TARGET_HT20_21,
+ ALL_TARGET_HT20_22,
+ ALL_TARGET_HT20_23,
+ ALL_TARGET_HT40_0_8_16,
+ ALL_TARGET_HT40_1_3_9_11_17_19,
+ ALL_TARGET_HT40_4,
+ ALL_TARGET_HT40_5,
+ ALL_TARGET_HT40_6,
+ ALL_TARGET_HT40_7,
+ ALL_TARGET_HT40_12,
+ ALL_TARGET_HT40_13,
+ ALL_TARGET_HT40_14,
+ ALL_TARGET_HT40_15,
+ ALL_TARGET_HT40_20,
+ ALL_TARGET_HT40_21,
+ ALL_TARGET_HT40_22,
+ ALL_TARGET_HT40_23,
+ ar9300RateSize,
+};
+
+
+struct eepFlags {
+ u8 opFlags;
+ u8 eepMisc;
+} __attribute__((packed));
+
+enum CompressAlgorithm {
+ _CompressNone = 0,
+ _CompressLzma,
+ _CompressPairs,
+ _CompressBlock,
+ _Compress4,
+ _Compress5,
+ _Compress6,
+ _Compress7,
+};
+
+struct ar9300_base_eep_hdr {
+ uint16_t regDmn[2];
+ /* 4 bits tx and 4 bits rx */
+ u8 txrxMask;
+ struct eepFlags opCapFlags;
+ u8 rfSilent;
+ u8 blueToothOptions;
+ u8 deviceCap;
+ /* takes lower byte in eeprom location */
+ u8 deviceType;
+ /* offset in dB to be added to beginning
+ * of pdadc table in calibration
+ */
+ int8_t pwrTableOffset;
+ u8 params_for_tuning_caps[2];
+ /*
+ * bit0 - enable tx temp comp
+ * bit1 - enable tx volt comp
+ * bit2 - enable fastClock - default to 1
+ * bit3 - enable doubling - default to 1
+ * bit4 - enable internal regulator - default to 1
+ */
+ u8 featureEnable;
+ /* misc flags: bit0 - turn down drivestrength */
+ u8 miscConfiguration;
+ u8 eepromWriteEnableGpio;
+ u8 wlanDisableGpio;
+ u8 wlanLedGpio;
+ u8 rxBandSelectGpio;
+ u8 txrxgain;
+ /* SW controlled internal regulator fields */
+ uint32_t swreg;
+} __attribute__((packed));
+
+struct ar9300_modal_eep_header {
+ /* 4 idle, t1, t2, b (4 bits per setting) */
+ uint32_t antCtrlCommon;
+ /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+ uint32_t antCtrlCommon2;
+ /* 6 idle, t, r, rx1, rx12, b (2 bits each) */
+ uint16_t antCtrlChain[AR9300_MAX_CHAINS];
+ /* 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+ u8 xatten1DB[AR9300_MAX_CHAINS];
+ /* 3 xatten1_margin for merlin (0xa20c/b20c 16:12 */
+ u8 xatten1Margin[AR9300_MAX_CHAINS];
+ int8_t tempSlope;
+ int8_t voltSlope;
+ /* spur channels in usual fbin coding format */
+ u8 spurChans[AR_EEPROM_MODAL_SPURS];
+ /* 3 Check if the register is per chain */
+ int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS];
+ u8 ob[AR9300_MAX_CHAINS];
+ u8 db_stage2[AR9300_MAX_CHAINS];
+ u8 db_stage3[AR9300_MAX_CHAINS];
+ u8 db_stage4[AR9300_MAX_CHAINS];
+ u8 xpaBiasLvl;
+ u8 txFrameToDataStart;
+ u8 txFrameToPaOn;
+ u8 txClip;
+ int8_t antennaGain;
+ u8 switchSettling;
+ int8_t adcDesiredSize;
+ u8 txEndToXpaOff;
+ u8 txEndToRxOn;
+ u8 txFrameToXpaOn;
+ u8 thresh62;
+ uint32_t papdRateMaskHt20;
+ uint32_t papdRateMaskHt40;
+ u8 futureModal[10];
+} __attribute__((packed));
+
+struct ar9300_cal_data_per_freq_op_loop {
+ int8_t refPower;
+ /* pdadc voltage at power measurement */
+ u8 voltMeas;
+ /* pcdac used for power measurement */
+ u8 tempMeas;
+ /* range is -60 to -127 create a mapping equation 1db resolution */
+ int8_t rxNoisefloorCal;
+ /*range is same as noisefloor */
+ int8_t rxNoisefloorPower;
+ /* temp measured when noisefloor cal was performed */
+ u8 rxTempMeas;
+} __attribute__((packed));
+
+struct cal_tgt_pow_legacy {
+ u8 tPow2x[4];
+} __attribute__((packed));
+
+struct cal_tgt_pow_ht {
+ u8 tPow2x[14];
+} __attribute__((packed));
+
+struct cal_ctl_data_2g {
+ u8 ctlEdges[AR9300_NUM_BAND_EDGES_2G];
+} __attribute__((packed));
+
+struct cal_ctl_data_5g {
+ u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G];
+} __attribute__((packed));
+
+struct ar9300_BaseExtension_1 {
+ u8 ant_div_control;
+ u8 future[13];
+} __attribute__((packed));
+
+struct ar9300_BaseExtension_2 {
+ int8_t tempSlopeLow;
+ int8_t tempSlopeHigh;
+ u8 xatten1DBLow[AR9300_MAX_CHAINS];
+ u8 xatten1MarginLow[AR9300_MAX_CHAINS];
+ u8 xatten1DBHigh[AR9300_MAX_CHAINS];
+ u8 xatten1MarginHigh[AR9300_MAX_CHAINS];
+} __attribute__((packed));
+
+struct ar9300_eeprom {
+ u8 eepromVersion;
+ u8 templateVersion;
+ u8 macAddr[6];
+ u8 custData[AR9300_CUSTOMER_DATA_SIZE];
+
+ struct ar9300_base_eep_hdr baseEepHeader;
+
+ struct ar9300_modal_eep_header modalHeader2G;
+ struct ar9300_BaseExtension_1 base_ext1;
+ u8 calFreqPier2G[AR9300_NUM_2G_CAL_PIERS];
+ struct ar9300_cal_data_per_freq_op_loop
+ calPierData2G[AR9300_MAX_CHAINS][AR9300_NUM_2G_CAL_PIERS];
+ u8 calTarget_freqbin_Cck[AR9300_NUM_2G_CCK_TARGET_POWERS];
+ u8 calTarget_freqbin_2G[AR9300_NUM_2G_20_TARGET_POWERS];
+ u8 calTarget_freqbin_2GHT20[AR9300_NUM_2G_20_TARGET_POWERS];
+ u8 calTarget_freqbin_2GHT40[AR9300_NUM_2G_40_TARGET_POWERS];
+ struct cal_tgt_pow_legacy
+ calTargetPowerCck[AR9300_NUM_2G_CCK_TARGET_POWERS];
+ struct cal_tgt_pow_legacy
+ calTargetPower2G[AR9300_NUM_2G_20_TARGET_POWERS];
+ struct cal_tgt_pow_ht
+ calTargetPower2GHT20[AR9300_NUM_2G_20_TARGET_POWERS];
+ struct cal_tgt_pow_ht
+ calTargetPower2GHT40[AR9300_NUM_2G_40_TARGET_POWERS];
+ u8 ctlIndex_2G[AR9300_NUM_CTLS_2G];
+ u8 ctl_freqbin_2G[AR9300_NUM_CTLS_2G][AR9300_NUM_BAND_EDGES_2G];
+ struct cal_ctl_data_2g ctlPowerData_2G[AR9300_NUM_CTLS_2G];
+ struct ar9300_modal_eep_header modalHeader5G;
+ struct ar9300_BaseExtension_2 base_ext2;
+ u8 calFreqPier5G[AR9300_NUM_5G_CAL_PIERS];
+ struct ar9300_cal_data_per_freq_op_loop
+ calPierData5G[AR9300_MAX_CHAINS][AR9300_NUM_5G_CAL_PIERS];
+ u8 calTarget_freqbin_5G[AR9300_NUM_5G_20_TARGET_POWERS];
+ u8 calTarget_freqbin_5GHT20[AR9300_NUM_5G_20_TARGET_POWERS];
+ u8 calTarget_freqbin_5GHT40[AR9300_NUM_5G_40_TARGET_POWERS];
+ struct cal_tgt_pow_legacy
+ calTargetPower5G[AR9300_NUM_5G_20_TARGET_POWERS];
+ struct cal_tgt_pow_ht
+ calTargetPower5GHT20[AR9300_NUM_5G_20_TARGET_POWERS];
+ struct cal_tgt_pow_ht
+ calTargetPower5GHT40[AR9300_NUM_5G_40_TARGET_POWERS];
+ u8 ctlIndex_5G[AR9300_NUM_CTLS_5G];
+ u8 ctl_freqbin_5G[AR9300_NUM_CTLS_5G][AR9300_NUM_BAND_EDGES_5G];
+ struct cal_ctl_data_5g ctlPowerData_5G[AR9300_NUM_CTLS_5G];
+} __attribute__((packed));
+
+s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah);
+s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah);
+
+u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, int is_2ghz);
+
+unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah,
+ struct ath9k_channel *chan);
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_mac.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_mac.h
new file mode 100644
index 00000000..6442bb77
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_mac.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef AR9003_MAC_H
+#define AR9003_MAC_H
+
+#define AR_DescId 0xffff0000
+#define AR_DescId_S 16
+#define AR_CtrlStat 0x00004000
+#define AR_CtrlStat_S 14
+#define AR_TxRxDesc 0x00008000
+#define AR_TxRxDesc_S 15
+#define AR_TxQcuNum 0x00000f00
+#define AR_TxQcuNum_S 8
+
+#define AR_BufLen 0x0fff0000
+#define AR_BufLen_S 16
+
+#define AR_TxDescId 0xffff0000
+#define AR_TxDescId_S 16
+#define AR_TxPtrChkSum 0x0000ffff
+
+#define AR_LowRxChain 0x00004000
+
+#define AR_Not_Sounding 0x20000000
+
+/* ctl 12 */
+#define AR_PAPRDChainMask 0x00000e00
+#define AR_PAPRDChainMask_S 9
+
+#define MAP_ISR_S2_CST 6
+#define MAP_ISR_S2_GTT 6
+#define MAP_ISR_S2_TIM 3
+#define MAP_ISR_S2_CABEND 0
+#define MAP_ISR_S2_DTIMSYNC 7
+#define MAP_ISR_S2_DTIM 7
+#define MAP_ISR_S2_TSFOOR 4
+#define MAP_ISR_S2_BB_WATCHDOG 6
+
+#define AR9003TXC_CONST(_ds) ((const struct ar9003_txc *) _ds)
+
+struct ar9003_rxs {
+ u32 ds_info;
+ u32 status1;
+ u32 status2;
+ u32 status3;
+ u32 status4;
+ u32 status5;
+ u32 status6;
+ u32 status7;
+ u32 status8;
+ u32 status9;
+ u32 status10;
+ u32 status11;
+} __attribute__((packed, aligned(4)));
+
+/* Transmit Control Descriptor */
+struct ar9003_txc {
+ u32 info; /* descriptor information */
+ u32 link; /* link pointer */
+ u32 data0; /* data pointer to 1st buffer */
+ u32 ctl3; /* DMA control 3 */
+ u32 data1; /* data pointer to 2nd buffer */
+ u32 ctl5; /* DMA control 5 */
+ u32 data2; /* data pointer to 3rd buffer */
+ u32 ctl7; /* DMA control 7 */
+ u32 data3; /* data pointer to 4th buffer */
+ u32 ctl9; /* DMA control 9 */
+ u32 ctl10; /* DMA control 10 */
+ u32 ctl11; /* DMA control 11 */
+ u32 ctl12; /* DMA control 12 */
+ u32 ctl13; /* DMA control 13 */
+ u32 ctl14; /* DMA control 14 */
+ u32 ctl15; /* DMA control 15 */
+ u32 ctl16; /* DMA control 16 */
+ u32 ctl17; /* DMA control 17 */
+ u32 ctl18; /* DMA control 18 */
+ u32 ctl19; /* DMA control 19 */
+ u32 ctl20; /* DMA control 20 */
+ u32 ctl21; /* DMA control 21 */
+ u32 ctl22; /* DMA control 22 */
+ u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */
+} __attribute__((packed, aligned(4)));
+
+struct ar9003_txs {
+ u32 ds_info;
+ u32 status1;
+ u32 status2;
+ u32 status3;
+ u32 status4;
+ u32 status5;
+ u32 status6;
+ u32 status7;
+ u32 status8;
+} __attribute__((packed, aligned(4)));
+
+void ar9003_hw_attach_mac_ops(struct ath_hw *hw);
+void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size);
+void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp,
+ enum ath9k_rx_qtype qtype);
+
+int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah,
+ struct ath_rx_status *rxs,
+ void *buf_addr);
+void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah);
+void ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start,
+ u32 ts_paddr_start,
+ u8 size);
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_phy.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_phy.h
new file mode 100644
index 00000000..443090d2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9003_phy.h
@@ -0,0 +1,1124 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef AR9003_PHY_H
+#define AR9003_PHY_H
+
+/*
+ * Channel Register Map
+ */
+#define AR_CHAN_BASE 0x9800
+
+#define AR_PHY_TIMING1 (AR_CHAN_BASE + 0x0)
+#define AR_PHY_TIMING2 (AR_CHAN_BASE + 0x4)
+#define AR_PHY_TIMING3 (AR_CHAN_BASE + 0x8)
+#define AR_PHY_TIMING4 (AR_CHAN_BASE + 0xc)
+#define AR_PHY_TIMING5 (AR_CHAN_BASE + 0x10)
+#define AR_PHY_TIMING6 (AR_CHAN_BASE + 0x14)
+#define AR_PHY_TIMING11 (AR_CHAN_BASE + 0x18)
+#define AR_PHY_SPUR_REG (AR_CHAN_BASE + 0x1c)
+#define AR_PHY_RX_IQCAL_CORR_B0 (AR_CHAN_BASE + 0xdc)
+#define AR_PHY_TX_IQCAL_CONTROL_3 (AR_CHAN_BASE + 0xb0)
+
+#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000
+#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20
+
+#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF
+#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0
+
+#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC 0x40000000
+#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC_S 30
+
+#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR 0x80000000
+#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR_S 31
+
+#define AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT 0x4000000
+#define AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT_S 26
+
+#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000 /* bins move with freq offset */
+#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM_S 17
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x000000FF
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0
+#define AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI 0x00000100
+#define AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI_S 8
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL 0x03FC0000
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18
+
+#define AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN 0x20000000
+#define AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN_S 29
+
+#define AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN 0x80000000
+#define AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN_S 31
+
+#define AR_PHY_FIND_SIG_LOW (AR_CHAN_BASE + 0x20)
+
+#define AR_PHY_SFCORR (AR_CHAN_BASE + 0x24)
+#define AR_PHY_SFCORR_LOW (AR_CHAN_BASE + 0x28)
+#define AR_PHY_SFCORR_EXT (AR_CHAN_BASE + 0x2c)
+
+#define AR_PHY_EXT_CCA (AR_CHAN_BASE + 0x30)
+#define AR_PHY_RADAR_0 (AR_CHAN_BASE + 0x34)
+#define AR_PHY_RADAR_1 (AR_CHAN_BASE + 0x38)
+#define AR_PHY_RADAR_EXT (AR_CHAN_BASE + 0x3c)
+#define AR_PHY_MULTICHAIN_CTRL (AR_CHAN_BASE + 0x80)
+#define AR_PHY_PERCHAIN_CSD (AR_CHAN_BASE + 0x84)
+
+#define AR_PHY_TX_PHASE_RAMP_0 (AR_CHAN_BASE + 0xd0)
+#define AR_PHY_ADC_GAIN_DC_CORR_0 (AR_CHAN_BASE + 0xd4)
+#define AR_PHY_IQ_ADC_MEAS_0_B0 (AR_CHAN_BASE + 0xc0)
+#define AR_PHY_IQ_ADC_MEAS_1_B0 (AR_CHAN_BASE + 0xc4)
+#define AR_PHY_IQ_ADC_MEAS_2_B0 (AR_CHAN_BASE + 0xc8)
+#define AR_PHY_IQ_ADC_MEAS_3_B0 (AR_CHAN_BASE + 0xcc)
+
+/* The following registers changed position from AR9300 1.0 to AR9300 2.0 */
+#define AR_PHY_TX_PHASE_RAMP_0_9300_10 (AR_CHAN_BASE + 0xd0 - 0x10)
+#define AR_PHY_ADC_GAIN_DC_CORR_0_9300_10 (AR_CHAN_BASE + 0xd4 - 0x10)
+#define AR_PHY_IQ_ADC_MEAS_0_B0_9300_10 (AR_CHAN_BASE + 0xc0 + 0x8)
+#define AR_PHY_IQ_ADC_MEAS_1_B0_9300_10 (AR_CHAN_BASE + 0xc4 + 0x8)
+#define AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 (AR_CHAN_BASE + 0xc8 + 0x8)
+#define AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 (AR_CHAN_BASE + 0xcc + 0x8)
+
+#define AR_PHY_TX_CRC (AR_CHAN_BASE + 0xa0)
+#define AR_PHY_TST_DAC_CONST (AR_CHAN_BASE + 0xa4)
+#define AR_PHY_SPUR_REPORT_0 (AR_CHAN_BASE + 0xa8)
+#define AR_PHY_CHAN_INFO_TAB_0 (AR_CHAN_BASE + 0x300)
+
+/*
+ * Channel Field Definitions
+ */
+#define AR_PHY_TIMING2_USE_FORCE_PPM 0x00001000
+#define AR_PHY_TIMING2_FORCE_PPM_VAL 0x00000fff
+#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000
+#define AR_PHY_TIMING3_DSC_MAN_S 17
+#define AR_PHY_TIMING3_DSC_EXP 0x0001E000
+#define AR_PHY_TIMING3_DSC_EXP_S 13
+#define AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX 0xF000
+#define AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX_S 12
+#define AR_PHY_TIMING4_DO_CAL 0x10000
+
+#define AR_PHY_TIMING4_ENABLE_PILOT_MASK 0x10000000
+#define AR_PHY_TIMING4_ENABLE_PILOT_MASK_S 28
+#define AR_PHY_TIMING4_ENABLE_CHAN_MASK 0x20000000
+#define AR_PHY_TIMING4_ENABLE_CHAN_MASK_S 29
+
+#define AR_PHY_TIMING4_ENABLE_SPUR_FILTER 0x40000000
+#define AR_PHY_TIMING4_ENABLE_SPUR_FILTER_S 30
+#define AR_PHY_TIMING4_ENABLE_SPUR_RSSI 0x80000000
+#define AR_PHY_TIMING4_ENABLE_SPUR_RSSI_S 31
+
+#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
+#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
+#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21
+#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F
+#define AR_PHY_SFCORR_M2COUNT_THR_S 0
+#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000
+#define AR_PHY_SFCORR_M1_THRESH_S 17
+#define AR_PHY_SFCORR_M2_THRESH 0x7F000000
+#define AR_PHY_SFCORR_M2_THRESH_S 24
+#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F
+#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0
+#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80
+#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
+#define AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD 0x10000000
+#define AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD_S 28
+#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28
+#define AR_PHY_EXT_CCA_THRESH62 0x007F0000
+#define AR_PHY_EXT_CCA_THRESH62_S 16
+#define AR_PHY_EXT_MINCCA_PWR 0x01FF0000
+#define AR_PHY_EXT_MINCCA_PWR_S 16
+#define AR_PHY_EXT_CYCPWR_THR1 0x0000FE00L
+#define AR_PHY_EXT_CYCPWR_THR1_S 9
+#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE
+#define AR_PHY_TIMING5_CYCPWR_THR1_S 1
+#define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE 0x00000001
+#define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE_S 0
+#define AR_PHY_TIMING5_CYCPWR_THR1A 0x007F0000
+#define AR_PHY_TIMING5_CYCPWR_THR1A_S 16
+#define AR_PHY_TIMING5_RSSI_THR1A (0x7F << 16)
+#define AR_PHY_TIMING5_RSSI_THR1A_S 16
+#define AR_PHY_TIMING5_RSSI_THR1A_ENA (0x1 << 15)
+#define AR_PHY_RADAR_0_ENA 0x00000001
+#define AR_PHY_RADAR_0_FFT_ENA 0x80000000
+#define AR_PHY_RADAR_0_INBAND 0x0000003e
+#define AR_PHY_RADAR_0_INBAND_S 1
+#define AR_PHY_RADAR_0_PRSSI 0x00000FC0
+#define AR_PHY_RADAR_0_PRSSI_S 6
+#define AR_PHY_RADAR_0_HEIGHT 0x0003F000
+#define AR_PHY_RADAR_0_HEIGHT_S 12
+#define AR_PHY_RADAR_0_RRSSI 0x00FC0000
+#define AR_PHY_RADAR_0_RRSSI_S 18
+#define AR_PHY_RADAR_0_FIRPWR 0x7F000000
+#define AR_PHY_RADAR_0_FIRPWR_S 24
+#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000
+#define AR_PHY_RADAR_1_USE_FIR128 0x00400000
+#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000
+#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16
+#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000
+#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000
+#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000
+#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00
+#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
+#define AR_PHY_RADAR_1_MAXLEN 0x000000FF
+#define AR_PHY_RADAR_1_MAXLEN_S 0
+#define AR_PHY_RADAR_EXT_ENA 0x00004000
+#define AR_PHY_RADAR_DC_PWR_THRESH 0x007f8000
+#define AR_PHY_RADAR_DC_PWR_THRESH_S 15
+#define AR_PHY_RADAR_LB_DC_CAP 0x7f800000
+#define AR_PHY_RADAR_LB_DC_CAP_S 23
+#define AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW (0x3f << 6)
+#define AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW_S 6
+#define AR_PHY_FIND_SIG_LOW_FIRPWR (0x7f << 12)
+#define AR_PHY_FIND_SIG_LOW_FIRPWR_S 12
+#define AR_PHY_FIND_SIG_LOW_FIRPWR_SIGN_BIT 19
+#define AR_PHY_FIND_SIG_LOW_RELSTEP 0x1f
+#define AR_PHY_FIND_SIG_LOW_RELSTEP_S 0
+#define AR_PHY_FIND_SIG_LOW_RELSTEP_SIGN_BIT 5
+#define AR_PHY_CHAN_INFO_TAB_S2_READ 0x00000008
+#define AR_PHY_CHAN_INFO_TAB_S2_READ_S 3
+#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF 0x0000007F
+#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF_S 0
+#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF 0x00003F80
+#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF_S 7
+#define AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE 0x00004000
+#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF 0x003f8000
+#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF_S 15
+#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF 0x1fc00000
+#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF_S 22
+
+/*
+ * MRC Register Map
+ */
+#define AR_MRC_BASE 0x9c00
+
+#define AR_PHY_TIMING_3A (AR_MRC_BASE + 0x0)
+#define AR_PHY_LDPC_CNTL1 (AR_MRC_BASE + 0x4)
+#define AR_PHY_LDPC_CNTL2 (AR_MRC_BASE + 0x8)
+#define AR_PHY_PILOT_SPUR_MASK (AR_MRC_BASE + 0xc)
+#define AR_PHY_CHAN_SPUR_MASK (AR_MRC_BASE + 0x10)
+#define AR_PHY_SGI_DELTA (AR_MRC_BASE + 0x14)
+#define AR_PHY_ML_CNTL_1 (AR_MRC_BASE + 0x18)
+#define AR_PHY_ML_CNTL_2 (AR_MRC_BASE + 0x1c)
+#define AR_PHY_TST_ADC (AR_MRC_BASE + 0x20)
+
+#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A 0x00000FE0
+#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A_S 5
+#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A 0x1F
+#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A_S 0
+
+#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A 0x00000FE0
+#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A_S 5
+#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A 0x1F
+#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A_S 0
+
+/*
+ * MRC Feild Definitions
+ */
+#define AR_PHY_SGI_DSC_MAN 0x0007FFF0
+#define AR_PHY_SGI_DSC_MAN_S 4
+#define AR_PHY_SGI_DSC_EXP 0x0000000F
+#define AR_PHY_SGI_DSC_EXP_S 0
+/*
+ * BBB Register Map
+ */
+#define AR_BBB_BASE 0x9d00
+
+/*
+ * AGC Register Map
+ */
+#define AR_AGC_BASE 0x9e00
+
+#define AR_PHY_SETTLING (AR_AGC_BASE + 0x0)
+#define AR_PHY_FORCEMAX_GAINS_0 (AR_AGC_BASE + 0x4)
+#define AR_PHY_GAINS_MINOFF0 (AR_AGC_BASE + 0x8)
+#define AR_PHY_DESIRED_SZ (AR_AGC_BASE + 0xc)
+#define AR_PHY_FIND_SIG (AR_AGC_BASE + 0x10)
+#define AR_PHY_AGC (AR_AGC_BASE + 0x14)
+#define AR_PHY_EXT_ATTEN_CTL_0 (AR_AGC_BASE + 0x18)
+#define AR_PHY_CCA_0 (AR_AGC_BASE + 0x1c)
+#define AR_PHY_EXT_CCA0 (AR_AGC_BASE + 0x20)
+#define AR_PHY_RESTART (AR_AGC_BASE + 0x24)
+
+/*
+ * Antenna Diversity settings
+ */
+#define AR_PHY_MC_GAIN_CTRL (AR_AGC_BASE + 0x28)
+#define AR_ANT_DIV_CTRL_ALL 0x7e000000
+#define AR_ANT_DIV_CTRL_ALL_S 25
+#define AR_ANT_DIV_ENABLE 0x1000000
+#define AR_ANT_DIV_ENABLE_S 24
+
+
+#define AR_PHY_9485_ANT_FAST_DIV_BIAS 0x00007e00
+#define AR_PHY_9485_ANT_FAST_DIV_BIAS_S 9
+#define AR_PHY_9485_ANT_DIV_LNADIV 0x01000000
+#define AR_PHY_9485_ANT_DIV_LNADIV_S 24
+#define AR_PHY_9485_ANT_DIV_ALT_LNACONF 0x06000000
+#define AR_PHY_9485_ANT_DIV_ALT_LNACONF_S 25
+#define AR_PHY_9485_ANT_DIV_MAIN_LNACONF 0x18000000
+#define AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S 27
+#define AR_PHY_9485_ANT_DIV_ALT_GAINTB 0x20000000
+#define AR_PHY_9485_ANT_DIV_ALT_GAINTB_S 29
+#define AR_PHY_9485_ANT_DIV_MAIN_GAINTB 0x40000000
+#define AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S 30
+
+#define AR_PHY_9485_ANT_DIV_LNA1_MINUS_LNA2 0x0
+#define AR_PHY_9485_ANT_DIV_LNA2 0x1
+#define AR_PHY_9485_ANT_DIV_LNA1 0x2
+#define AR_PHY_9485_ANT_DIV_LNA1_PLUS_LNA2 0x3
+
+#define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c)
+#define AR_PHY_EXT_CHN_WIN (AR_AGC_BASE + 0x30)
+#define AR_PHY_20_40_DET_THR (AR_AGC_BASE + 0x34)
+#define AR_PHY_RIFS_SRCH (AR_AGC_BASE + 0x38)
+#define AR_PHY_PEAK_DET_CTRL_1 (AR_AGC_BASE + 0x3c)
+#define AR_PHY_PEAK_DET_CTRL_2 (AR_AGC_BASE + 0x40)
+#define AR_PHY_RX_GAIN_BOUNDS_1 (AR_AGC_BASE + 0x44)
+#define AR_PHY_RX_GAIN_BOUNDS_2 (AR_AGC_BASE + 0x48)
+#define AR_PHY_RSSI_0 (AR_AGC_BASE + 0x180)
+#define AR_PHY_SPUR_CCK_REP0 (AR_AGC_BASE + 0x184)
+
+#define AR_PHY_CCK_DETECT (AR_AGC_BASE + 0x1c0)
+#define AR_FAST_DIV_ENABLE 0x2000
+#define AR_FAST_DIV_ENABLE_S 13
+
+#define AR_PHY_DAG_CTRLCCK (AR_AGC_BASE + 0x1c4)
+#define AR_PHY_IQCORR_CTRL_CCK (AR_AGC_BASE + 0x1c8)
+
+#define AR_PHY_CCK_SPUR_MIT (AR_AGC_BASE + 0x1cc)
+#define AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR 0x000001fe
+#define AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR_S 1
+#define AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE 0x60000000
+#define AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE_S 29
+#define AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT 0x00000001
+#define AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT_S 0
+#define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ 0x1ffffe00
+#define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ_S 9
+
+#define AR_PHY_MRC_CCK_CTRL (AR_AGC_BASE + 0x1d0)
+#define AR_PHY_MRC_CCK_ENABLE 0x00000001
+#define AR_PHY_MRC_CCK_ENABLE_S 0
+#define AR_PHY_MRC_CCK_MUX_REG 0x00000002
+#define AR_PHY_MRC_CCK_MUX_REG_S 1
+
+#define AR_PHY_RX_OCGAIN (AR_AGC_BASE + 0x200)
+
+#define AR_PHY_CCA_NOM_VAL_9300_2GHZ -110
+#define AR_PHY_CCA_NOM_VAL_9300_5GHZ -115
+#define AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ -125
+#define AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ -125
+#define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ -95
+#define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ -100
+
+/*
+ * AGC Field Definitions
+ */
+#define AR_PHY_EXT_ATTEN_CTL_RXTX_MARGIN 0x00FC0000
+#define AR_PHY_EXT_ATTEN_CTL_RXTX_MARGIN_S 18
+#define AR_PHY_EXT_ATTEN_CTL_BSW_MARGIN 0x00003C00
+#define AR_PHY_EXT_ATTEN_CTL_BSW_MARGIN_S 10
+#define AR_PHY_EXT_ATTEN_CTL_BSW_ATTEN 0x0000001F
+#define AR_PHY_EXT_ATTEN_CTL_BSW_ATTEN_S 0
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_MARGIN 0x003E0000
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_MARGIN_S 17
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN 0x0001F000
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN_S 12
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_DB 0x00000FC0
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_DB_S 6
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB 0x0000003F
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB_S 0
+#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000
+#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12
+#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000
+#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14
+#define AR_PHY_SETTLING_SWITCH 0x00003F80
+#define AR_PHY_SETTLING_SWITCH_S 7
+#define AR_PHY_DESIRED_SZ_ADC 0x000000FF
+#define AR_PHY_DESIRED_SZ_ADC_S 0
+#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00
+#define AR_PHY_DESIRED_SZ_PGA_S 8
+#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000
+#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
+#define AR_PHY_MINCCA_PWR 0x1FF00000
+#define AR_PHY_MINCCA_PWR_S 20
+#define AR_PHY_CCA_THRESH62 0x0007F000
+#define AR_PHY_CCA_THRESH62_S 12
+#define AR9280_PHY_MINCCA_PWR 0x1FF00000
+#define AR9280_PHY_MINCCA_PWR_S 20
+#define AR9280_PHY_CCA_THRESH62 0x000FF000
+#define AR9280_PHY_CCA_THRESH62_S 12
+#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF
+#define AR_PHY_EXT_CCA0_THRESH62_S 0
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
+#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
+
+#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200
+#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR_S 9
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10
+
+#define AR_PHY_RIFS_INIT_DELAY 0x3ff0000
+#define AR_PHY_AGC_COARSE_LOW 0x00007F80
+#define AR_PHY_AGC_COARSE_LOW_S 7
+#define AR_PHY_AGC_COARSE_HIGH 0x003F8000
+#define AR_PHY_AGC_COARSE_HIGH_S 15
+#define AR_PHY_AGC_COARSE_PWR_CONST 0x0000007F
+#define AR_PHY_AGC_COARSE_PWR_CONST_S 0
+#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000
+#define AR_PHY_FIND_SIG_FIRSTEP_S 12
+#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000
+#define AR_PHY_FIND_SIG_FIRPWR_S 18
+#define AR_PHY_FIND_SIG_FIRPWR_SIGN_BIT 25
+#define AR_PHY_FIND_SIG_RELPWR (0x1f << 6)
+#define AR_PHY_FIND_SIG_RELPWR_S 6
+#define AR_PHY_FIND_SIG_RELPWR_SIGN_BIT 11
+#define AR_PHY_FIND_SIG_RELSTEP 0x1f
+#define AR_PHY_FIND_SIG_RELSTEP_S 0
+#define AR_PHY_FIND_SIG_RELSTEP_SIGN_BIT 5
+#define AR_PHY_RESTART_DIV_GC 0x001C0000
+#define AR_PHY_RESTART_DIV_GC_S 18
+#define AR_PHY_RESTART_ENA 0x01
+#define AR_PHY_DC_RESTART_DIS 0x40000000
+
+#define AR_PHY_TPC_OLPC_GAIN_DELTA_PAL_ON 0xFF000000
+#define AR_PHY_TPC_OLPC_GAIN_DELTA_PAL_ON_S 24
+#define AR_PHY_TPC_OLPC_GAIN_DELTA 0x00FF0000
+#define AR_PHY_TPC_OLPC_GAIN_DELTA_S 16
+
+#define AR_PHY_TPC_6_ERROR_EST_MODE 0x03000000
+#define AR_PHY_TPC_6_ERROR_EST_MODE_S 24
+
+/*
+ * SM Register Map
+ */
+#define AR_SM_BASE 0xa200
+
+#define AR_PHY_D2_CHIP_ID (AR_SM_BASE + 0x0)
+#define AR_PHY_GEN_CTRL (AR_SM_BASE + 0x4)
+#define AR_PHY_MODE (AR_SM_BASE + 0x8)
+#define AR_PHY_ACTIVE (AR_SM_BASE + 0xc)
+#define AR_PHY_SPUR_MASK_A (AR_SM_BASE + 0x20)
+#define AR_PHY_SPUR_MASK_B (AR_SM_BASE + 0x24)
+#define AR_PHY_SPECTRAL_SCAN (AR_SM_BASE + 0x28)
+#define AR_PHY_RADAR_BW_FILTER (AR_SM_BASE + 0x2c)
+#define AR_PHY_SEARCH_START_DELAY (AR_SM_BASE + 0x30)
+#define AR_PHY_MAX_RX_LEN (AR_SM_BASE + 0x34)
+#define AR_PHY_FRAME_CTL (AR_SM_BASE + 0x38)
+#define AR_PHY_RFBUS_REQ (AR_SM_BASE + 0x3c)
+#define AR_PHY_RFBUS_GRANT (AR_SM_BASE + 0x40)
+#define AR_PHY_RIFS (AR_SM_BASE + 0x44)
+#define AR_PHY_RX_CLR_DELAY (AR_SM_BASE + 0x50)
+#define AR_PHY_RX_DELAY (AR_SM_BASE + 0x54)
+
+#define AR_PHY_XPA_TIMING_CTL (AR_SM_BASE + 0x64)
+#define AR_PHY_MISC_PA_CTL (AR_SM_BASE + 0x80)
+#define AR_PHY_SWITCH_CHAIN_0 (AR_SM_BASE + 0x84)
+#define AR_PHY_SWITCH_COM (AR_SM_BASE + 0x88)
+#define AR_PHY_SWITCH_COM_2 (AR_SM_BASE + 0x8c)
+#define AR_PHY_RX_CHAINMASK (AR_SM_BASE + 0xa0)
+#define AR_PHY_CAL_CHAINMASK (AR_SM_BASE + 0xc0)
+#define AR_PHY_CALMODE (AR_SM_BASE + 0xc8)
+#define AR_PHY_FCAL_1 (AR_SM_BASE + 0xcc)
+#define AR_PHY_FCAL_2_0 (AR_SM_BASE + 0xd0)
+#define AR_PHY_DFT_TONE_CTL_0 (AR_SM_BASE + 0xd4)
+#define AR_PHY_CL_CAL_CTL (AR_SM_BASE + 0xd8)
+#define AR_PHY_CL_TAB_0 (AR_SM_BASE + 0x100)
+#define AR_PHY_SYNTH_CONTROL (AR_SM_BASE + 0x140)
+#define AR_PHY_ADDAC_CLK_SEL (AR_SM_BASE + 0x144)
+#define AR_PHY_PLL_CTL (AR_SM_BASE + 0x148)
+#define AR_PHY_ANALOG_SWAP (AR_SM_BASE + 0x14c)
+#define AR_PHY_ADDAC_PARA_CTL (AR_SM_BASE + 0x150)
+#define AR_PHY_XPA_CFG (AR_SM_BASE + 0x158)
+
+#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A 0x0001FC00
+#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A_S 10
+#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A 0x3FF
+#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A_S 0
+
+#define AR_PHY_TEST (AR_SM_BASE + 0x160)
+
+#define AR_PHY_TEST_BBB_OBS_SEL 0x780000
+#define AR_PHY_TEST_BBB_OBS_SEL_S 19
+
+#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23
+#define AR_PHY_TEST_RX_OBS_SEL_BIT5 (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S)
+
+#define AR_PHY_TEST_CHAIN_SEL 0xC0000000
+#define AR_PHY_TEST_CHAIN_SEL_S 30
+
+#define AR_PHY_TEST_CTL_STATUS (AR_SM_BASE + 0x164)
+#define AR_PHY_TEST_CTL_TSTDAC_EN 0x1
+#define AR_PHY_TEST_CTL_TSTDAC_EN_S 0
+#define AR_PHY_TEST_CTL_TX_OBS_SEL 0x1C
+#define AR_PHY_TEST_CTL_TX_OBS_SEL_S 2
+#define AR_PHY_TEST_CTL_TX_OBS_MUX_SEL 0x60
+#define AR_PHY_TEST_CTL_TX_OBS_MUX_SEL_S 5
+#define AR_PHY_TEST_CTL_TSTADC_EN 0x100
+#define AR_PHY_TEST_CTL_TSTADC_EN_S 8
+#define AR_PHY_TEST_CTL_RX_OBS_SEL 0x3C00
+#define AR_PHY_TEST_CTL_RX_OBS_SEL_S 10
+
+
+#define AR_PHY_TSTDAC (AR_SM_BASE + 0x168)
+
+#define AR_PHY_CHAN_STATUS (AR_SM_BASE + 0x16c)
+
+#define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + 0x170)
+#define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ 0x00000008
+#define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ_S 3
+
+#define AR_PHY_CHNINFO_NOISEPWR (AR_SM_BASE + 0x174)
+#define AR_PHY_CHNINFO_GAINDIFF (AR_SM_BASE + 0x178)
+#define AR_PHY_CHNINFO_FINETIM (AR_SM_BASE + 0x17c)
+#define AR_PHY_CHAN_INFO_GAIN_0 (AR_SM_BASE + 0x180)
+#define AR_PHY_SCRAMBLER_SEED (AR_SM_BASE + 0x190)
+#define AR_PHY_CCK_TX_CTRL (AR_SM_BASE + 0x194)
+
+#define AR_PHY_HEAVYCLIP_CTL (AR_SM_BASE + 0x1a4)
+#define AR_PHY_HEAVYCLIP_20 (AR_SM_BASE + 0x1a8)
+#define AR_PHY_HEAVYCLIP_40 (AR_SM_BASE + 0x1ac)
+#define AR_PHY_ILLEGAL_TXRATE (AR_SM_BASE + 0x1b0)
+
+#define AR_PHY_POWER_TX_RATE(_d) (AR_SM_BASE + 0x1c0 + ((_d) << 2))
+
+#define AR_PHY_PWRTX_MAX (AR_SM_BASE + 0x1f0)
+#define AR_PHY_POWER_TX_SUB (AR_SM_BASE + 0x1f4)
+
+#define AR_PHY_TPC_1 (AR_SM_BASE + 0x1f8)
+#define AR_PHY_TPC_1_FORCED_DAC_GAIN 0x0000003e
+#define AR_PHY_TPC_1_FORCED_DAC_GAIN_S 1
+#define AR_PHY_TPC_1_FORCE_DAC_GAIN 0x00000001
+#define AR_PHY_TPC_1_FORCE_DAC_GAIN_S 0
+
+#define AR_PHY_TPC_4_B0 (AR_SM_BASE + 0x204)
+#define AR_PHY_TPC_5_B0 (AR_SM_BASE + 0x208)
+#define AR_PHY_TPC_6_B0 (AR_SM_BASE + 0x20c)
+
+#define AR_PHY_TPC_11_B0 (AR_SM_BASE + 0x220)
+#define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220)
+#define AR_PHY_TPC_11_B2 (AR_SM2_BASE + 0x220)
+#define AR_PHY_TPC_11_OLPC_GAIN_DELTA 0x00ff0000
+#define AR_PHY_TPC_11_OLPC_GAIN_DELTA_S 16
+
+#define AR_PHY_TPC_12 (AR_SM_BASE + 0x224)
+#define AR_PHY_TPC_12_DESIRED_SCALE_HT40_5 0x3e000000
+#define AR_PHY_TPC_12_DESIRED_SCALE_HT40_5_S 25
+
+#define AR_PHY_TPC_18 (AR_SM_BASE + 0x23c)
+#define AR_PHY_TPC_18_THERM_CAL_VALUE 0x000000ff
+#define AR_PHY_TPC_18_THERM_CAL_VALUE_S 0
+#define AR_PHY_TPC_18_VOLT_CAL_VALUE 0x0000ff00
+#define AR_PHY_TPC_18_VOLT_CAL_VALUE_S 8
+
+#define AR_PHY_TPC_19 (AR_SM_BASE + 0x240)
+#define AR_PHY_TPC_19_ALPHA_VOLT 0x001f0000
+#define AR_PHY_TPC_19_ALPHA_VOLT_S 16
+#define AR_PHY_TPC_19_ALPHA_THERM 0xff
+#define AR_PHY_TPC_19_ALPHA_THERM_S 0
+
+#define AR_PHY_TX_FORCED_GAIN (AR_SM_BASE + 0x258)
+#define AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN 0x00000001
+#define AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN_S 0
+#define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN 0x0000000e
+#define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN_S 1
+#define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN 0x00000030
+#define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN_S 4
+#define AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN 0x000003c0
+#define AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN_S 6
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA 0x00003c00
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA_S 10
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB 0x0003c000
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB_S 14
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC 0x003c0000
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC_S 18
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND 0x00c00000
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND_S 22
+#define AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL 0x01000000
+#define AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL_S 24
+
+
+#define AR_PHY_PDADC_TAB_0 (AR_SM_BASE + 0x280)
+
+#define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300)
+
+#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + AR_SREV_9485(ah) ? \
+ 0x3c8 : 0x448)
+#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + AR_SREV_9485(ah) ? \
+ 0x3c4 : 0x440)
+#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + AR_SREV_9485(ah) ? \
+ 0x3f0 : 0x48c)
+#define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \
+ (AR_SREV_9485(ah) ? \
+ 0x3d0 : 0x450) + ((_i) << 2))
+
+#define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0)
+#define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4)
+#define AR_PHY_WATCHDOG_CTL_2 (AR_SM_BASE + 0x5c8)
+#define AR_PHY_WATCHDOG_CTL (AR_SM_BASE + 0x5cc)
+#define AR_PHY_ONLY_WARMRESET (AR_SM_BASE + 0x5d0)
+#define AR_PHY_ONLY_CTL (AR_SM_BASE + 0x5d4)
+#define AR_PHY_ECO_CTRL (AR_SM_BASE + 0x5dc)
+
+#define AR_PHY_BB_THERM_ADC_1 (AR_SM_BASE + 0x248)
+#define AR_PHY_BB_THERM_ADC_1_INIT_THERM 0x000000ff
+#define AR_PHY_BB_THERM_ADC_1_INIT_THERM_S 0
+
+#define AR_PHY_BB_THERM_ADC_4 (AR_SM_BASE + 0x254)
+#define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE 0x000000ff
+#define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE_S 0
+#define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE 0x0000ff00
+#define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE_S 8
+
+
+#define AR_PHY_65NM_CH0_SYNTH4 0x1608c
+#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT 0x00000002
+#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S 1
+#define AR_PHY_65NM_CH0_SYNTH7 0x16098
+#define AR_PHY_65NM_CH0_BIAS1 0x160c0
+#define AR_PHY_65NM_CH0_BIAS2 0x160c4
+#define AR_PHY_65NM_CH0_BIAS4 0x160cc
+#define AR_PHY_65NM_CH0_RXTX4 0x1610c
+#define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : 0x1628c)
+
+#define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000
+#define AR_PHY_65NM_CH0_THERM_LOCAL_S 31
+#define AR_PHY_65NM_CH0_THERM_START 0x20000000
+#define AR_PHY_65NM_CH0_THERM_START_S 29
+#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT 0x0000ff00
+#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT_S 8
+
+#define AR_PHY_65NM_CH0_RXTX1 0x16100
+#define AR_PHY_65NM_CH0_RXTX2 0x16104
+#define AR_PHY_65NM_CH1_RXTX1 0x16500
+#define AR_PHY_65NM_CH1_RXTX2 0x16504
+#define AR_PHY_65NM_CH2_RXTX1 0x16900
+#define AR_PHY_65NM_CH2_RXTX2 0x16904
+
+#define AR_CH0_TOP2 (AR_SREV_9485(ah) ? 0x00016284 : 0x0001628c)
+#define AR_CH0_TOP2_XPABIASLVL 0xf000
+#define AR_CH0_TOP2_XPABIASLVL_S 12
+
+#define AR_CH0_XTAL (AR_SREV_9485(ah) ? 0x16290 : 0x16294)
+#define AR_CH0_XTAL_CAPINDAC 0x7f000000
+#define AR_CH0_XTAL_CAPINDAC_S 24
+#define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000
+#define AR_CH0_XTAL_CAPOUTDAC_S 17
+
+#define AR_PHY_PMU1 0x16c40
+#define AR_PHY_PMU1_PWD 0x1
+#define AR_PHY_PMU1_PWD_S 0
+
+#define AR_PHY_PMU2 0x16c44
+#define AR_PHY_PMU2_PGM 0x00200000
+#define AR_PHY_PMU2_PGM_S 21
+
+#define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT 0x00380000
+#define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT_S 19
+#define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT 0x00c00000
+#define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT_S 22
+#define AR_PHY_LNAGAIN_LONG_SHIFT 0xe0000000
+#define AR_PHY_LNAGAIN_LONG_SHIFT_S 29
+#define AR_PHY_MXRGAIN_LONG_SHIFT 0x03000000
+#define AR_PHY_MXRGAIN_LONG_SHIFT_S 24
+#define AR_PHY_VGAGAIN_LONG_SHIFT 0x1c000000
+#define AR_PHY_VGAGAIN_LONG_SHIFT_S 26
+#define AR_PHY_SCFIR_GAIN_LONG_SHIFT 0x00000001
+#define AR_PHY_SCFIR_GAIN_LONG_SHIFT_S 0
+#define AR_PHY_MANRXGAIN_LONG_SHIFT 0x00000002
+#define AR_PHY_MANRXGAIN_LONG_SHIFT_S 1
+
+/*
+ * SM Field Definitions
+ */
+#define AR_PHY_CL_CAL_ENABLE 0x00000002
+#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001
+#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000
+#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22
+
+#define AR_PHY_ADDAC_PARACTL_OFF_PWDADC 0x00008000
+
+#define AR_PHY_FCAL20_CAP_STATUS_0 0x01f00000
+#define AR_PHY_FCAL20_CAP_STATUS_0_S 20
+
+#define AR_PHY_RFBUS_REQ_EN 0x00000001 /* request for RF bus */
+#define AR_PHY_RFBUS_GRANT_EN 0x00000001 /* RF bus granted */
+#define AR_PHY_GC_TURBO_MODE 0x00000001 /* set turbo mode bits */
+#define AR_PHY_GC_TURBO_SHORT 0x00000002 /* set short symbols to turbo mode setting */
+#define AR_PHY_GC_DYN2040_EN 0x00000004 /* enable dyn 20/40 mode */
+#define AR_PHY_GC_DYN2040_PRI_ONLY 0x00000008 /* dyn 20/40 - primary only */
+#define AR_PHY_GC_DYN2040_PRI_CH 0x00000010 /* dyn 20/40 - primary ch offset (0=+10MHz, 1=-10MHz)*/
+#define AR_PHY_GC_DYN2040_PRI_CH_S 4
+#define AR_PHY_GC_DYN2040_EXT_CH 0x00000020 /* dyn 20/40 - ext ch spacing (0=20MHz/ 1=25MHz) */
+#define AR_PHY_GC_HT_EN 0x00000040 /* ht enable */
+#define AR_PHY_GC_SHORT_GI_40 0x00000080 /* allow short GI for HT 40 */
+#define AR_PHY_GC_WALSH 0x00000100 /* walsh spatial spreading for 2 chains,2 streams TX */
+#define AR_PHY_GC_SINGLE_HT_LTF1 0x00000200 /* single length (4us) 1st HT long training symbol */
+#define AR_PHY_GC_GF_DETECT_EN 0x00000400 /* enable Green Field detection. Only affects rx, not tx */
+#define AR_PHY_GC_ENABLE_DAC_FIFO 0x00000800 /* fifo between bb and dac */
+#define AR_PHY_RX_DELAY_DELAY 0x00003FFF /* delay from wakeup to rx ena */
+
+#define AR_PHY_CALMODE_IQ 0x00000000
+#define AR_PHY_CALMODE_ADC_GAIN 0x00000001
+#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002
+#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003
+#define AR_PHY_SWAP_ALT_CHAIN 0x00000040
+#define AR_PHY_MODE_OFDM 0x00000000
+#define AR_PHY_MODE_CCK 0x00000001
+#define AR_PHY_MODE_DYNAMIC 0x00000004
+#define AR_PHY_MODE_DYNAMIC_S 2
+#define AR_PHY_MODE_HALF 0x00000020
+#define AR_PHY_MODE_QUARTER 0x00000040
+#define AR_PHY_MAC_CLK_MODE 0x00000080
+#define AR_PHY_MODE_DYN_CCK_DISABLE 0x00000100
+#define AR_PHY_MODE_SVD_HALF 0x00000200
+#define AR_PHY_ACTIVE_EN 0x00000001
+#define AR_PHY_ACTIVE_DIS 0x00000000
+#define AR_PHY_FORCE_XPA_CFG 0x000000001
+#define AR_PHY_FORCE_XPA_CFG_S 0
+#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF 0xFF000000
+#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF_S 24
+#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF 0x00FF0000
+#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF_S 16
+#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON 0x0000FF00
+#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON_S 8
+#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON 0x000000FF
+#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON_S 0
+#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000
+#define AR_PHY_TX_END_TO_A2_RX_ON_S 16
+#define AR_PHY_TX_END_DATA_START 0x000000FF
+#define AR_PHY_TX_END_DATA_START_S 0
+#define AR_PHY_TX_END_PA_ON 0x0000FF00
+#define AR_PHY_TX_END_PA_ON_S 8
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22
+#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000
+#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
+#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000
+#define AR_PHY_TPCRG1_PD_GAIN_1_S 16
+#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000
+#define AR_PHY_TPCRG1_PD_GAIN_2_S 18
+#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000
+#define AR_PHY_TPCRG1_PD_GAIN_3_S 20
+#define AR_PHY_TPCGR1_FORCED_DAC_GAIN 0x0000003e
+#define AR_PHY_TPCGR1_FORCED_DAC_GAIN_S 1
+#define AR_PHY_TPCGR1_FORCE_DAC_GAIN 0x00000001
+#define AR_PHY_TXGAIN_FORCE 0x00000001
+#define AR_PHY_TXGAIN_FORCE_S 0
+#define AR_PHY_TXGAIN_FORCED_PADVGNRA 0x00003c00
+#define AR_PHY_TXGAIN_FORCED_PADVGNRA_S 10
+#define AR_PHY_TXGAIN_FORCED_PADVGNRB 0x0003c000
+#define AR_PHY_TXGAIN_FORCED_PADVGNRB_S 14
+#define AR_PHY_TXGAIN_FORCED_PADVGNRD 0x00c00000
+#define AR_PHY_TXGAIN_FORCED_PADVGNRD_S 22
+#define AR_PHY_TXGAIN_FORCED_TXMXRGAIN 0x000003c0
+#define AR_PHY_TXGAIN_FORCED_TXMXRGAIN_S 6
+#define AR_PHY_TXGAIN_FORCED_TXBB1DBGAIN 0x0000000e
+#define AR_PHY_TXGAIN_FORCED_TXBB1DBGAIN_S 1
+
+#define AR_PHY_POWER_TX_RATE1 0x9934
+#define AR_PHY_POWER_TX_RATE2 0x9938
+#define AR_PHY_POWER_TX_RATE_MAX 0x993c
+#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
+#define PHY_AGC_CLR 0x10000000
+#define RFSILENT_BB 0x00002000
+#define AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_MASK 0xFFF
+#define AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_SIGNED_BIT 0x800
+#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
+#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001
+#define AR_PHY_RX_DELAY_DELAY 0x00003FFF
+#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
+#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x00000001
+#define AR_PHY_SPECTRAL_SCAN_ENABLE_S 0
+#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002
+#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1
+#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0
+#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4
+#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00
+#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8
+#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000
+#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16
+#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000
+#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24
+#define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004
+#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000
+#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18
+#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001
+#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0
+
+#define AR_PHY_TX_IQCAL_STATUS_FAILED 0x00000001
+#define AR_PHY_CALIBRATED_GAINS_0 0x3e
+#define AR_PHY_CALIBRATED_GAINS_0_S 1
+
+#define AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE 0x00003fff
+#define AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE_S 0
+#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE 0x0fffc000
+#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S 14
+
+#define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000
+#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28
+
+/*
+ * Channel 1 Register Map
+ */
+#define AR_CHAN1_BASE 0xa800
+
+#define AR_PHY_EXT_CCA_1 (AR_CHAN1_BASE + 0x30)
+#define AR_PHY_TX_PHASE_RAMP_1 (AR_CHAN1_BASE + 0xd0)
+#define AR_PHY_ADC_GAIN_DC_CORR_1 (AR_CHAN1_BASE + 0xd4)
+
+#define AR_PHY_SPUR_REPORT_1 (AR_CHAN1_BASE + 0xa8)
+#define AR_PHY_CHAN_INFO_TAB_1 (AR_CHAN1_BASE + 0x300)
+#define AR_PHY_RX_IQCAL_CORR_B1 (AR_CHAN1_BASE + 0xdc)
+
+/*
+ * Channel 1 Field Definitions
+ */
+#define AR_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000
+#define AR_PHY_CH1_EXT_MINCCA_PWR_S 16
+
+/*
+ * AGC 1 Register Map
+ */
+#define AR_AGC1_BASE 0xae00
+
+#define AR_PHY_FORCEMAX_GAINS_1 (AR_AGC1_BASE + 0x4)
+#define AR_PHY_EXT_ATTEN_CTL_1 (AR_AGC1_BASE + 0x18)
+#define AR_PHY_CCA_1 (AR_AGC1_BASE + 0x1c)
+#define AR_PHY_CCA_CTRL_1 (AR_AGC1_BASE + 0x20)
+#define AR_PHY_RSSI_1 (AR_AGC1_BASE + 0x180)
+#define AR_PHY_SPUR_CCK_REP_1 (AR_AGC1_BASE + 0x184)
+#define AR_PHY_RX_OCGAIN_2 (AR_AGC1_BASE + 0x200)
+
+/*
+ * AGC 1 Field Definitions
+ */
+#define AR_PHY_CH1_MINCCA_PWR 0x1FF00000
+#define AR_PHY_CH1_MINCCA_PWR_S 20
+
+/*
+ * SM 1 Register Map
+ */
+#define AR_SM1_BASE 0xb200
+
+#define AR_PHY_SWITCH_CHAIN_1 (AR_SM1_BASE + 0x84)
+#define AR_PHY_FCAL_2_1 (AR_SM1_BASE + 0xd0)
+#define AR_PHY_DFT_TONE_CTL_1 (AR_SM1_BASE + 0xd4)
+#define AR_PHY_CL_TAB_1 (AR_SM1_BASE + 0x100)
+#define AR_PHY_CHAN_INFO_GAIN_1 (AR_SM1_BASE + 0x180)
+#define AR_PHY_TPC_4_B1 (AR_SM1_BASE + 0x204)
+#define AR_PHY_TPC_5_B1 (AR_SM1_BASE + 0x208)
+#define AR_PHY_TPC_6_B1 (AR_SM1_BASE + 0x20c)
+#define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220)
+#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + 0x240)
+#define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c)
+#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i) (AR_SM_BASE + 0x450 + ((_i) << 2))
+
+/*
+ * Channel 2 Register Map
+ */
+#define AR_CHAN2_BASE 0xb800
+
+#define AR_PHY_EXT_CCA_2 (AR_CHAN2_BASE + 0x30)
+#define AR_PHY_TX_PHASE_RAMP_2 (AR_CHAN2_BASE + 0xd0)
+#define AR_PHY_ADC_GAIN_DC_CORR_2 (AR_CHAN2_BASE + 0xd4)
+
+#define AR_PHY_SPUR_REPORT_2 (AR_CHAN2_BASE + 0xa8)
+#define AR_PHY_CHAN_INFO_TAB_2 (AR_CHAN2_BASE + 0x300)
+#define AR_PHY_RX_IQCAL_CORR_B2 (AR_CHAN2_BASE + 0xdc)
+
+/*
+ * Channel 2 Field Definitions
+ */
+#define AR_PHY_CH2_EXT_MINCCA_PWR 0x01FF0000
+#define AR_PHY_CH2_EXT_MINCCA_PWR_S 16
+/*
+ * AGC 2 Register Map
+ */
+#define AR_AGC2_BASE 0xbe00
+
+#define AR_PHY_FORCEMAX_GAINS_2 (AR_AGC2_BASE + 0x4)
+#define AR_PHY_EXT_ATTEN_CTL_2 (AR_AGC2_BASE + 0x18)
+#define AR_PHY_CCA_2 (AR_AGC2_BASE + 0x1c)
+#define AR_PHY_CCA_CTRL_2 (AR_AGC2_BASE + 0x20)
+#define AR_PHY_RSSI_2 (AR_AGC2_BASE + 0x180)
+
+/*
+ * AGC 2 Field Definitions
+ */
+#define AR_PHY_CH2_MINCCA_PWR 0x1FF00000
+#define AR_PHY_CH2_MINCCA_PWR_S 20
+
+/*
+ * SM 2 Register Map
+ */
+#define AR_SM2_BASE 0xc200
+
+#define AR_PHY_SWITCH_CHAIN_2 (AR_SM2_BASE + 0x84)
+#define AR_PHY_FCAL_2_2 (AR_SM2_BASE + 0xd0)
+#define AR_PHY_DFT_TONE_CTL_2 (AR_SM2_BASE + 0xd4)
+#define AR_PHY_CL_TAB_2 (AR_SM2_BASE + 0x100)
+#define AR_PHY_CHAN_INFO_GAIN_2 (AR_SM2_BASE + 0x180)
+#define AR_PHY_TPC_4_B2 (AR_SM2_BASE + 0x204)
+#define AR_PHY_TPC_5_B2 (AR_SM2_BASE + 0x208)
+#define AR_PHY_TPC_6_B2 (AR_SM2_BASE + 0x20c)
+#define AR_PHY_TPC_11_B2 (AR_SM2_BASE + 0x220)
+#define AR_PHY_PDADC_TAB_2 (AR_SM2_BASE + 0x240)
+#define AR_PHY_TX_IQCAL_STATUS_B2 (AR_SM2_BASE + 0x48c)
+#define AR_PHY_TX_IQCAL_CORR_COEFF_B2(_i) (AR_SM2_BASE + 0x450 + ((_i) << 2))
+
+#define AR_PHY_TX_IQCAL_STATUS_B2_FAILED 0x00000001
+
+/*
+ * AGC 3 Register Map
+ */
+#define AR_AGC3_BASE 0xce00
+
+#define AR_PHY_RSSI_3 (AR_AGC3_BASE + 0x180)
+
+/*
+ * Misc helper defines
+ */
+#define AR_PHY_CHAIN_OFFSET (AR_CHAN1_BASE - AR_CHAN_BASE)
+
+#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (AR_PHY_ADC_GAIN_DC_CORR_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_NEW_ADC_DC_GAIN_CORR_9300_10(_i) (AR_PHY_ADC_GAIN_DC_CORR_0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_SWITCH_CHAIN(_i) (AR_PHY_SWITCH_CHAIN_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_EXT_ATTEN_CTL(_i) (AR_PHY_EXT_ATTEN_CTL_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+
+#define AR_PHY_RXGAIN(_i) (AR_PHY_FORCEMAX_GAINS_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_TPCRG5(_i) (AR_PHY_TPC_5_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_PDADC_TAB(_i) (AR_PHY_PDADC_TAB_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+
+#define AR_PHY_CAL_MEAS_0(_i) (AR_PHY_IQ_ADC_MEAS_0_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_1(_i) (AR_PHY_IQ_ADC_MEAS_1_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_2(_i) (AR_PHY_IQ_ADC_MEAS_2_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_3(_i) (AR_PHY_IQ_ADC_MEAS_3_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_0_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_0_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_1_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_1_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_2_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_3_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
+
+#define AR_PHY_WATCHDOG_NON_IDLE_ENABLE 0x00000001
+#define AR_PHY_WATCHDOG_IDLE_ENABLE 0x00000002
+#define AR_PHY_WATCHDOG_IDLE_MASK 0xFFFF0000
+#define AR_PHY_WATCHDOG_NON_IDLE_MASK 0x0000FFFC
+
+#define AR_PHY_WATCHDOG_RST_ENABLE 0x00000002
+#define AR_PHY_WATCHDOG_IRQ_ENABLE 0x00000004
+#define AR_PHY_WATCHDOG_CNTL2_MASK 0xFFFFFFF9
+
+#define AR_PHY_WATCHDOG_INFO 0x00000007
+#define AR_PHY_WATCHDOG_INFO_S 0
+#define AR_PHY_WATCHDOG_DET_HANG 0x00000008
+#define AR_PHY_WATCHDOG_DET_HANG_S 3
+#define AR_PHY_WATCHDOG_RADAR_SM 0x000000F0
+#define AR_PHY_WATCHDOG_RADAR_SM_S 4
+#define AR_PHY_WATCHDOG_RX_OFDM_SM 0x00000F00
+#define AR_PHY_WATCHDOG_RX_OFDM_SM_S 8
+#define AR_PHY_WATCHDOG_RX_CCK_SM 0x0000F000
+#define AR_PHY_WATCHDOG_RX_CCK_SM_S 12
+#define AR_PHY_WATCHDOG_TX_OFDM_SM 0x000F0000
+#define AR_PHY_WATCHDOG_TX_OFDM_SM_S 16
+#define AR_PHY_WATCHDOG_TX_CCK_SM 0x00F00000
+#define AR_PHY_WATCHDOG_TX_CCK_SM_S 20
+#define AR_PHY_WATCHDOG_AGC_SM 0x0F000000
+#define AR_PHY_WATCHDOG_AGC_SM_S 24
+#define AR_PHY_WATCHDOG_SRCH_SM 0xF0000000
+#define AR_PHY_WATCHDOG_SRCH_SM_S 28
+
+#define AR_PHY_WATCHDOG_STATUS_CLR 0x00000008
+
+/*
+ * PAPRD registers
+ */
+#define AR_PHY_XPA_TIMING_CTL (AR_SM_BASE + 0x64)
+
+#define AR_PHY_PAPRD_AM2AM (AR_CHAN_BASE + 0xe4)
+#define AR_PHY_PAPRD_AM2AM_MASK 0x01ffffff
+#define AR_PHY_PAPRD_AM2AM_MASK_S 0
+
+#define AR_PHY_PAPRD_AM2PM (AR_CHAN_BASE + 0xe8)
+#define AR_PHY_PAPRD_AM2PM_MASK 0x01ffffff
+#define AR_PHY_PAPRD_AM2PM_MASK_S 0
+
+#define AR_PHY_PAPRD_HT40 (AR_CHAN_BASE + 0xec)
+#define AR_PHY_PAPRD_HT40_MASK 0x01ffffff
+#define AR_PHY_PAPRD_HT40_MASK_S 0
+
+#define AR_PHY_PAPRD_CTRL0_B0 (AR_CHAN_BASE + 0xf0)
+#define AR_PHY_PAPRD_CTRL0_B1 (AR_CHAN1_BASE + 0xf0)
+#define AR_PHY_PAPRD_CTRL0_B2 (AR_CHAN2_BASE + 0xf0)
+#define AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE 0x00000001
+#define AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE_S 0
+#define AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK 0x00000002
+#define AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK_S 1
+#define AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH 0xf8000000
+#define AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH_S 27
+
+#define AR_PHY_PAPRD_CTRL1_B0 (AR_CHAN_BASE + 0xf4)
+#define AR_PHY_PAPRD_CTRL1_B1 (AR_CHAN1_BASE + 0xf4)
+#define AR_PHY_PAPRD_CTRL1_B2 (AR_CHAN2_BASE + 0xf4)
+#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA 0x00000001
+#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA_S 0
+#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE 0x00000002
+#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE_S 1
+#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE 0x00000004
+#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE_S 2
+#define AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL 0x000001f8
+#define AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL_S 3
+#define AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK 0x0001fe00
+#define AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK_S 9
+#define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT 0x0ffe0000
+#define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT_S 17
+
+#define AR_PHY_PAPRD_TRAINER_CNTL1 (AR_SM_BASE + \
+ (AR_SREV_9485(ah) ? \
+ 0x580 : 0x490))
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE 0x00000001
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE_S 0
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING 0x0000007e
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING_S 1
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE 0x00000100
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE_S 8
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE 0x00000200
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE_S 9
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE 0x00000400
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE_S 10
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE 0x00000800
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE_S 11
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP 0x0003f000
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP_S 12
+
+#define AR_PHY_PAPRD_TRAINER_CNTL2 (AR_SM_BASE + \
+ (AR_SREV_9485(ah) ? \
+ 0x584 : 0x494))
+#define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN 0xFFFFFFFF
+#define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN_S 0
+
+#define AR_PHY_PAPRD_TRAINER_CNTL3 (AR_SM_BASE + \
+ (AR_SREV_9485(ah) ? \
+ 0x588 : 0x498))
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE 0x0000003f
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE_S 0
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP 0x00000fc0
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP_S 6
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL 0x0001f000
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL_S 12
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES 0x000e0000
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES_S 17
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN 0x00f00000
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN_S 20
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN 0x0f000000
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN_S 24
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE 0x20000000
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE_S 29
+
+#define AR_PHY_PAPRD_TRAINER_CNTL4 (AR_SM_BASE + \
+ (AR_SREV_9485(ah) ? \
+ 0x58c : 0x49c))
+#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES 0x03ff0000
+#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES_S 16
+#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA 0x0000f000
+#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA_S 12
+#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR 0x00000fff
+#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR_S 0
+
+#define AR_PHY_PAPRD_PRE_POST_SCALE_0_B0 (AR_CHAN_BASE + 0x100)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_1_B0 (AR_CHAN_BASE + 0x104)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_2_B0 (AR_CHAN_BASE + 0x108)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_3_B0 (AR_CHAN_BASE + 0x10c)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_4_B0 (AR_CHAN_BASE + 0x110)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_5_B0 (AR_CHAN_BASE + 0x114)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_6_B0 (AR_CHAN_BASE + 0x118)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_7_B0 (AR_CHAN_BASE + 0x11c)
+#define AR_PHY_PAPRD_PRE_POST_SCALING 0x3FFFF
+#define AR_PHY_PAPRD_PRE_POST_SCALING_S 0
+
+#define AR_PHY_PAPRD_TRAINER_STAT1 (AR_SM_BASE + 0x4a0)
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE 0x00000001
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE_S 0
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_INCOMPLETE 0x00000002
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_INCOMPLETE_S 1
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_CORR_ERR 0x00000004
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_CORR_ERR_S 2
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_ACTIVE 0x00000008
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_ACTIVE_S 3
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_RX_GAIN_IDX 0x000001f0
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_RX_GAIN_IDX_S 4
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR 0x0001fe00
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR_S 9
+
+#define AR_PHY_PAPRD_TRAINER_STAT2 (AR_SM_BASE + 0x4a4)
+#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL 0x0000ffff
+#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL_S 0
+#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_COARSE_IDX 0x001f0000
+#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_COARSE_IDX_S 16
+#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX 0x00600000
+#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX_S 21
+
+#define AR_PHY_PAPRD_TRAINER_STAT3 (AR_SM_BASE + 0x4a8)
+#define AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT 0x000fffff
+#define AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT_S 0
+
+#define AR_PHY_PAPRD_MEM_TAB_B0 (AR_CHAN_BASE + 0x120)
+#define AR_PHY_PAPRD_MEM_TAB_B1 (AR_CHAN1_BASE + 0x120)
+#define AR_PHY_PAPRD_MEM_TAB_B2 (AR_CHAN2_BASE + 0x120)
+
+#define AR_PHY_PA_GAIN123_B0 (AR_CHAN_BASE + 0xf8)
+#define AR_PHY_PA_GAIN123_B1 (AR_CHAN1_BASE + 0xf8)
+#define AR_PHY_PA_GAIN123_B2 (AR_CHAN2_BASE + 0xf8)
+#define AR_PHY_PA_GAIN123_PA_GAIN1 0x3FF
+#define AR_PHY_PA_GAIN123_PA_GAIN1_S 0
+
+#define AR_PHY_POWERTX_RATE5 (AR_SM_BASE + 0x1d0)
+#define AR_PHY_POWERTX_RATE5_POWERTXHT20_0 0x3F
+#define AR_PHY_POWERTX_RATE5_POWERTXHT20_0_S 0
+
+#define AR_PHY_POWERTX_RATE6 (AR_SM_BASE + 0x1d4)
+#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5 0x3F00
+#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5_S 8
+
+#define AR_PHY_POWERTX_RATE8 (AR_SM_BASE + 0x1dc)
+#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5 0x3F00
+#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S 8
+
+void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
+
+#endif /* AR9003_PHY_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9340_initvals.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9340_initvals.h
new file mode 100644
index 00000000..815a8af1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9340_initvals.h
@@ -0,0 +1,1525 @@
+/*
+ * Copyright (c) 2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9340_H
+#define INITVALS_9340_H
+
+static const u32 ar9340_1p0_radio_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800},
+ {0x0001610c, 0x08000000, 0x08000000, 0x00000000, 0x00000000},
+ {0x00016140, 0x10804000, 0x10804000, 0x50804000, 0x50804000},
+ {0x0001650c, 0x08000000, 0x08000000, 0x00000000, 0x00000000},
+ {0x00016540, 0x10804000, 0x10804000, 0x50804000, 0x50804000},
+};
+
+static const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+ {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
+ {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
+ {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+ {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+ {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+ {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+ {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+ {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+ {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+ {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+ {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+ {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+ {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+ {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
+ {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
+ {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
+ {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
+ {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
+ {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+ {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+ {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+ {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402},
+ {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+ {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+ {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+ {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+ {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+ {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+ {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+ {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+ {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+ {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
+ {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
+ {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83},
+ {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84},
+ {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3},
+ {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5},
+ {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9},
+ {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb},
+ {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
+ {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
+ {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
+ {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
+};
+
+static const u32 ar9340Modes_fast_clock_1p0[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x00001030, 0x00000268, 0x000004d0},
+ {0x00001070, 0x0000018c, 0x00000318},
+ {0x000010b0, 0x00000fd0, 0x00001fa0},
+ {0x00008014, 0x044c044c, 0x08980898},
+ {0x0000801c, 0x148ec02b, 0x148ec057},
+ {0x00008318, 0x000044c0, 0x00008980},
+ {0x00009e00, 0x03721821, 0x03721821},
+ {0x0000a230, 0x0000000b, 0x00000016},
+ {0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9340_1p0_radio_core[][2] = {
+ /* Addr allmodes */
+ {0x00016000, 0x36db6db6},
+ {0x00016004, 0x6db6db40},
+ {0x00016008, 0x73f00000},
+ {0x0001600c, 0x00000000},
+ {0x00016040, 0x7f80fff8},
+ {0x00016044, 0x03b6d2db},
+ {0x00016048, 0x24925266},
+ {0x0001604c, 0x000f0278},
+ {0x00016050, 0x6db6db6c},
+ {0x00016054, 0x6db60000},
+ {0x00016080, 0x00080000},
+ {0x00016084, 0x0e48048c},
+ {0x00016088, 0x14214514},
+ {0x0001608c, 0x119f081c},
+ {0x00016090, 0x24926490},
+ {0x00016094, 0x00000000},
+ {0x00016098, 0xd411eb84},
+ {0x0001609c, 0x03e47f32},
+ {0x000160a0, 0xc2108ffe},
+ {0x000160a4, 0x812fc370},
+ {0x000160a8, 0x423c8000},
+ {0x000160ac, 0xa4646800},
+ {0x000160b0, 0x00fe7f46},
+ {0x000160b4, 0x92480000},
+ {0x000160c0, 0x006db6db},
+ {0x000160c4, 0x6db6db60},
+ {0x000160c8, 0x6db6db6c},
+ {0x000160cc, 0x6de6db6c},
+ {0x000160d0, 0xb6da4924},
+ {0x00016100, 0x04cb0001},
+ {0x00016104, 0xfff80000},
+ {0x00016108, 0x00080010},
+ {0x0001610c, 0x00000000},
+ {0x00016140, 0x50804008},
+ {0x00016144, 0x01884080},
+ {0x00016148, 0x000080c0},
+ {0x00016280, 0x01000015},
+ {0x00016284, 0x05530000},
+ {0x00016288, 0x00318000},
+ {0x0001628c, 0x50000000},
+ {0x00016290, 0x4080294f},
+ {0x00016380, 0x00000000},
+ {0x00016384, 0x00000000},
+ {0x00016388, 0x00800700},
+ {0x0001638c, 0x00800700},
+ {0x00016390, 0x00800700},
+ {0x00016394, 0x00000000},
+ {0x00016398, 0x00000000},
+ {0x0001639c, 0x00000000},
+ {0x000163a0, 0x00000001},
+ {0x000163a4, 0x00000001},
+ {0x000163a8, 0x00000000},
+ {0x000163ac, 0x00000000},
+ {0x000163b0, 0x00000000},
+ {0x000163b4, 0x00000000},
+ {0x000163b8, 0x00000000},
+ {0x000163bc, 0x00000000},
+ {0x000163c0, 0x000000a0},
+ {0x000163c4, 0x000c0000},
+ {0x000163c8, 0x14021402},
+ {0x000163cc, 0x00001402},
+ {0x000163d0, 0x00000000},
+ {0x000163d4, 0x00000000},
+ {0x00016400, 0x36db6db6},
+ {0x00016404, 0x6db6db40},
+ {0x00016408, 0x73f00000},
+ {0x0001640c, 0x00000000},
+ {0x00016440, 0x7f80fff8},
+ {0x00016444, 0x03b6d2db},
+ {0x00016448, 0x24927266},
+ {0x0001644c, 0x000f0278},
+ {0x00016450, 0x6db6db6c},
+ {0x00016454, 0x6db60000},
+ {0x00016500, 0x04cb0001},
+ {0x00016504, 0xfff80000},
+ {0x00016508, 0x00080010},
+ {0x0001650c, 0x00000000},
+ {0x00016540, 0x50804008},
+ {0x00016544, 0x01884080},
+ {0x00016548, 0x000080c0},
+ {0x00016780, 0x00000000},
+ {0x00016784, 0x00000000},
+ {0x00016788, 0x00800700},
+ {0x0001678c, 0x00800700},
+ {0x00016790, 0x00800700},
+ {0x00016794, 0x00000000},
+ {0x00016798, 0x00000000},
+ {0x0001679c, 0x00000000},
+ {0x000167a0, 0x00000001},
+ {0x000167a4, 0x00000001},
+ {0x000167a8, 0x00000000},
+ {0x000167ac, 0x00000000},
+ {0x000167b0, 0x00000000},
+ {0x000167b4, 0x00000000},
+ {0x000167b8, 0x00000000},
+ {0x000167bc, 0x00000000},
+ {0x000167c0, 0x000000a0},
+ {0x000167c4, 0x000c0000},
+ {0x000167c8, 0x14021402},
+ {0x000167cc, 0x00001402},
+ {0x000167d0, 0x00000000},
+ {0x000167d4, 0x00000000},
+};
+
+static const u32 ar9340_1p0_radio_core_40M[][2] = {
+ {0x0001609c, 0x02566f3a},
+ {0x000160ac, 0xa4647c00},
+ {0x000160b0, 0x01885f5a},
+};
+
+static const u32 ar9340_1p0_mac_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9340_1p0_soc_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
+};
+
+static const u32 ar9340_1p0_baseband_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+ {0x00009820, 0x206a022e, 0x206a022e, 0x206a022e, 0x206a022e},
+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+ {0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044},
+ {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+ {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e},
+ {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+ {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+ {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+ {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+ {0x0000a288, 0x00000220, 0x00000220, 0x00000110, 0x00000110},
+ {0x0000a28c, 0x00011111, 0x00011111, 0x00022222, 0x00022222},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982},
+ {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae04, 0x00180000, 0x00180000, 0x00180000, 0x00180000},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+ {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+};
+
+static const u32 ar9340_1p0_baseband_core[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafe68e30},
+ {0x00009804, 0xfd14e000},
+ {0x00009808, 0x9c0a9f6b},
+ {0x0000980c, 0x04900000},
+ {0x00009814, 0xb280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+ {0x00009834, 0x5f3ca3de},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x14750600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+ {0x000098b0, 0x52440bbe},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+ {0x000098f0, 0x00000000},
+ {0x000098f4, 0x00000000},
+ {0x00009c04, 0xff55ff55},
+ {0x00009c08, 0x0320ff55},
+ {0x00009c0c, 0x00000000},
+ {0x00009c10, 0x00000000},
+ {0x00009c14, 0x00046384},
+ {0x00009c18, 0x05b6b440},
+ {0x00009c1c, 0x00b6b440},
+ {0x00009d00, 0xc080a333},
+ {0x00009d04, 0x40206c10},
+ {0x00009d08, 0x009c4060},
+ {0x00009d0c, 0x9883800a},
+ {0x00009d10, 0x01834061},
+ {0x00009d14, 0x00c0040b},
+ {0x00009d18, 0x00000000},
+ {0x00009e08, 0x0038230c},
+ {0x00009e24, 0x990bb515},
+ {0x00009e28, 0x0c6f0000},
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+ {0x00009e3c, 0xcf946222},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+ {0x00009e54, 0x00000000},
+ {0x00009fc0, 0x803e4788},
+ {0x00009fc4, 0x0001efb5},
+ {0x00009fcc, 0x40000014},
+ {0x00009fd0, 0x01193b93},
+ {0x0000a20c, 0x00000000},
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+ {0x0000a22c, 0x01036a1e},
+ {0x0000a234, 0x10000fff},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a2a0, 0x00000001},
+ {0x0000a2c0, 0x00000001},
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2cc, 0x18c43433},
+ {0x0000a2d4, 0x00000000},
+ {0x0000a2dc, 0x00000000},
+ {0x0000a2e0, 0x00000000},
+ {0x0000a2e4, 0x00000000},
+ {0x0000a2e8, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+ {0x0000a2f8, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a34c, 0x00000000},
+ {0x0000a350, 0x0000a000},
+ {0x0000a364, 0x00000000},
+ {0x0000a370, 0x00000000},
+ {0x0000a390, 0x00000001},
+ {0x0000a394, 0x00000444},
+ {0x0000a398, 0x001f0e0f},
+ {0x0000a39c, 0x0075393f},
+ {0x0000a3a0, 0xb79f6427},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0xaaaaaaaa},
+ {0x0000a3ac, 0x3c466478},
+ {0x0000a3c0, 0x20202020},
+ {0x0000a3c4, 0x22222220},
+ {0x0000a3c8, 0x20200020},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3d8, 0x20202020},
+ {0x0000a3dc, 0x20202020},
+ {0x0000a3e0, 0x20202020},
+ {0x0000a3e4, 0x20202020},
+ {0x0000a3e8, 0x20202020},
+ {0x0000a3ec, 0x20202020},
+ {0x0000a3f0, 0x00000000},
+ {0x0000a3f4, 0x00000246},
+ {0x0000a3f8, 0x0cdbd380},
+ {0x0000a3fc, 0x000f0f01},
+ {0x0000a400, 0x8fa91f01},
+ {0x0000a404, 0x00000000},
+ {0x0000a408, 0x0e79e5c6},
+ {0x0000a40c, 0x00820820},
+ {0x0000a414, 0x1ce739ce},
+ {0x0000a418, 0x2d001dce},
+ {0x0000a41c, 0x1ce739ce},
+ {0x0000a420, 0x000001ce},
+ {0x0000a424, 0x1ce739ce},
+ {0x0000a428, 0x000001ce},
+ {0x0000a42c, 0x1ce739ce},
+ {0x0000a430, 0x1ce739ce},
+ {0x0000a434, 0x00000000},
+ {0x0000a438, 0x00001801},
+ {0x0000a43c, 0x00000000},
+ {0x0000a440, 0x00000000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x04000080},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a458, 0x00000000},
+ {0x0000a600, 0x00000000},
+ {0x0000a604, 0x00000000},
+ {0x0000a608, 0x00000000},
+ {0x0000a60c, 0x00000000},
+ {0x0000a610, 0x00000000},
+ {0x0000a614, 0x00000000},
+ {0x0000a618, 0x00000000},
+ {0x0000a61c, 0x00000000},
+ {0x0000a620, 0x00000000},
+ {0x0000a624, 0x00000000},
+ {0x0000a628, 0x00000000},
+ {0x0000a62c, 0x00000000},
+ {0x0000a630, 0x00000000},
+ {0x0000a634, 0x00000000},
+ {0x0000a638, 0x00000000},
+ {0x0000a63c, 0x00000000},
+ {0x0000a640, 0x00000000},
+ {0x0000a644, 0x3fad9d74},
+ {0x0000a648, 0x0048060a},
+ {0x0000a64c, 0x00000637},
+ {0x0000a670, 0x03020100},
+ {0x0000a674, 0x09080504},
+ {0x0000a678, 0x0d0c0b0a},
+ {0x0000a67c, 0x13121110},
+ {0x0000a680, 0x31301514},
+ {0x0000a684, 0x35343332},
+ {0x0000a688, 0x00000036},
+ {0x0000a690, 0x00000838},
+ {0x0000a7c0, 0x00000000},
+ {0x0000a7c4, 0xfffffffc},
+ {0x0000a7c8, 0x00000000},
+ {0x0000a7cc, 0x00000000},
+ {0x0000a7d0, 0x00000000},
+ {0x0000a7d4, 0x00000004},
+ {0x0000a7dc, 0x00000000},
+ {0x0000a8d0, 0x004b6a8e},
+ {0x0000a8d4, 0x00000820},
+ {0x0000a8dc, 0x00000000},
+ {0x0000a8f0, 0x00000000},
+ {0x0000a8f4, 0x00000000},
+ {0x0000b2d0, 0x00000080},
+ {0x0000b2d4, 0x00000000},
+ {0x0000b2dc, 0x00000000},
+ {0x0000b2e0, 0x00000000},
+ {0x0000b2e4, 0x00000000},
+ {0x0000b2e8, 0x00000000},
+ {0x0000b2ec, 0x00000000},
+ {0x0000b2f0, 0x00000000},
+ {0x0000b2f4, 0x00000000},
+ {0x0000b2f8, 0x00000000},
+ {0x0000b408, 0x0e79e5c0},
+ {0x0000b40c, 0x00820820},
+ {0x0000b420, 0x00000000},
+};
+
+static const u32 ar9340Modes_high_power_tx_gain_table_1p0[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+ {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
+ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
+ {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
+ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
+ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
+ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
+ {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
+ {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
+ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
+ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
+ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+ {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
+ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
+ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
+ {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
+ {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
+ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
+ {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
+ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
+ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
+ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
+ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
+ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
+ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
+ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
+ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
+ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
+ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
+ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
+ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
+ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
+ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
+ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
+ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
+ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
+ {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
+ {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
+ {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
+};
+
+static const u32 ar9340Modes_high_ob_db_tx_gain_table_1p0[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+ {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
+ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
+ {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
+ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
+ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
+ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
+ {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
+ {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
+ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
+ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
+ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+ {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
+ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
+ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
+ {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
+ {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
+ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
+ {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
+ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
+ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
+ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
+ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
+ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
+ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
+ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
+ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
+ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
+ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
+ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
+ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
+ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
+ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
+ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
+ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
+ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x00016044, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4},
+ {0x00016048, 0x8e481266, 0x8e481266, 0x8e481266, 0x8e481266},
+ {0x00016444, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4},
+ {0x00016448, 0x8e481266, 0x8e481266, 0x8e481266, 0x8e481266},
+};
+static const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+ {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
+ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
+ {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
+ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
+ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
+ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
+ {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
+ {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
+ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
+ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
+ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+ {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
+ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
+ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
+ {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
+ {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
+ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
+ {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
+ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
+ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
+ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
+ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
+ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
+ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
+ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
+ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
+ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
+ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
+ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
+ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
+ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
+ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
+ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
+ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
+ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x00016044, 0x036db2db, 0x036db2db, 0x036db2db, 0x036db2db},
+ {0x00016048, 0x69b65266, 0x69b65266, 0x69b65266, 0x69b65266},
+ {0x00016444, 0x036db2db, 0x036db2db, 0x036db2db, 0x036db2db},
+ {0x00016448, 0x69b65266, 0x69b65266, 0x69b65266, 0x69b65266},
+};
+
+
+static const u32 ar9340Common_rx_gain_table_1p0[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x01910190},
+ {0x0000a030, 0x01930192},
+ {0x0000a034, 0x01950194},
+ {0x0000a038, 0x038a0196},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x22222229},
+ {0x0000a084, 0x1d1d1d1d},
+ {0x0000a088, 0x1d1d1d1d},
+ {0x0000a08c, 0x1d1d1d1d},
+ {0x0000a090, 0x171d1d1d},
+ {0x0000a094, 0x11111717},
+ {0x0000a098, 0x00030311},
+ {0x0000a09c, 0x00000000},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x32323232},
+ {0x0000b084, 0x2f2f3232},
+ {0x0000b088, 0x23282a2d},
+ {0x0000b08c, 0x1c1e2123},
+ {0x0000b090, 0x14171919},
+ {0x0000b094, 0x0e0e1214},
+ {0x0000b098, 0x03050707},
+ {0x0000b09c, 0x00030303},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+ {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
+ {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
+ {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+ {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+ {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+ {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+ {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+ {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+ {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+ {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+ {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+ {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+ {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+ {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
+ {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
+ {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
+ {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
+ {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
+ {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+ {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+ {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+ {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402},
+ {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+ {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+ {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+ {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+ {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+ {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+ {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+ {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+ {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+ {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
+ {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
+ {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83},
+ {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84},
+ {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3},
+ {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5},
+ {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9},
+ {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb},
+ {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
+ {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
+ {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
+ {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
+};
+
+static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400},
+ {0x0000a518, 0x21020220, 0x21020220, 0x15000402, 0x15000402},
+ {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
+ {0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603},
+ {0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02},
+ {0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04},
+ {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x26000a20, 0x26000a20},
+ {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2a000e20, 0x2a000e20},
+ {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22},
+ {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24},
+ {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640},
+ {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660},
+ {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81},
+ {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x61042a6c, 0x61042a6c, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x66062a6c, 0x66062a6c, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a55c, 0x7006308c, 0x7006308c, 0x50001ce9, 0x50001ce9},
+ {0x0000a560, 0x730a308a, 0x730a308a, 0x54001ceb, 0x54001ceb},
+ {0x0000a564, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
+ {0x0000a568, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
+ {0x0000a56c, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
+ {0x0000a570, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
+ {0x0000a574, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
+ {0x0000a578, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
+ {0x0000a57c, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
+ {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+ {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+ {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400},
+ {0x0000a598, 0x21820220, 0x21820220, 0x15800402, 0x15800402},
+ {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603},
+ {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02},
+ {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04},
+ {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20},
+ {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20},
+ {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22},
+ {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24},
+ {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640},
+ {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660},
+ {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861},
+ {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81},
+ {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x42801a83, 0x42801a83},
+ {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x44801c84, 0x44801c84},
+ {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x48801ce3, 0x48801ce3},
+ {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x4c801ce5, 0x4c801ce5},
+ {0x0000a5dc, 0x7086308c, 0x7086308c, 0x50801ce9, 0x50801ce9},
+ {0x0000a5e0, 0x738a308a, 0x738a308a, 0x54801ceb, 0x54801ceb},
+ {0x0000a5e4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+ {0x0000a5e8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+ {0x0000a5ec, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+ {0x0000a5f0, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+ {0x0000a5f4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+ {0x0000a5f8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+ {0x0000a5fc, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+ {0x00016044, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4},
+ {0x00016048, 0x24927266, 0x24927266, 0x8e483266, 0x8e483266},
+ {0x00016444, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4},
+ {0x00016448, 0x24927266, 0x24927266, 0x8e482266, 0x8e482266},
+};
+
+static const u32 ar9340_1p0_mac_core[][2] = {
+ /* Addr allmodes */
+ {0x00000008, 0x00000000},
+ {0x00000030, 0x00020085},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000000},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x000010f0, 0x00000100},
+ {0x00001270, 0x00000000},
+ {0x000012b0, 0x00000000},
+ {0x000012f0, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00008000, 0x00000000},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000000},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00000000},
+ {0x00008040, 0x00000000},
+ {0x00008044, 0x00000000},
+ {0x00008048, 0x00000000},
+ {0x0000804c, 0xffffffff},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x00008070, 0x00000310},
+ {0x00008074, 0x00000020},
+ {0x00008078, 0x00000000},
+ {0x0000809c, 0x0000000f},
+ {0x000080a0, 0x00000000},
+ {0x000080a4, 0x02ff0000},
+ {0x000080a8, 0x0e070605},
+ {0x000080ac, 0x0000000d},
+ {0x000080b0, 0x00000000},
+ {0x000080b4, 0x00000000},
+ {0x000080b8, 0x00000000},
+ {0x000080bc, 0x00000000},
+ {0x000080c0, 0x2a800000},
+ {0x000080c4, 0x06900168},
+ {0x000080c8, 0x13881c20},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00252500},
+ {0x000080d4, 0x00a00000},
+ {0x000080d8, 0x00400000},
+ {0x000080dc, 0x00000000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x3f3f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00000000},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000000},
+ {0x00008114, 0x000007ff},
+ {0x00008118, 0x000000aa},
+ {0x0000811c, 0x00003210},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x0000ffff},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x18486200},
+ {0x00008174, 0x33332210},
+ {0x00008178, 0x00000000},
+ {0x0000817c, 0x00020000},
+ {0x000081c0, 0x00000000},
+ {0x000081c4, 0x33332210},
+ {0x000081c8, 0x00000000},
+ {0x000081cc, 0x00000000},
+ {0x000081d4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f424},
+ {0x00008248, 0x00000800},
+ {0x0000824c, 0x0001e848},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x40000000},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x9d400010},
+ {0x00008268, 0xffffffff},
+ {0x0000826c, 0x0000ffff},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000004},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x000000ff},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x0000829c, 0x00000000},
+ {0x00008300, 0x00000140},
+ {0x00008314, 0x00000000},
+ {0x0000831c, 0x0000010d},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000007},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000700},
+ {0x00008338, 0x00ff0000},
+ {0x0000833c, 0x02400000},
+ {0x00008340, 0x000107ff},
+ {0x00008344, 0xaa48105b},
+ {0x00008348, 0x008f0000},
+ {0x0000835c, 0x00000000},
+ {0x00008360, 0xffffffff},
+ {0x00008364, 0xffffffff},
+ {0x00008368, 0x00000000},
+ {0x00008370, 0x00000000},
+ {0x00008374, 0x000000ff},
+ {0x00008378, 0x00000000},
+ {0x0000837c, 0x00000000},
+ {0x00008380, 0xffffffff},
+ {0x00008384, 0xffffffff},
+ {0x00008390, 0xffffffff},
+ {0x00008394, 0xffffffff},
+ {0x00008398, 0x00000000},
+ {0x0000839c, 0x00000000},
+ {0x000083a0, 0x00000000},
+ {0x000083a4, 0x0000fa14},
+ {0x000083a8, 0x000f0c00},
+ {0x000083ac, 0x33332210},
+ {0x000083b0, 0x33332210},
+ {0x000083b4, 0x33332210},
+ {0x000083b8, 0x33332210},
+ {0x000083bc, 0x00000000},
+ {0x000083c0, 0x00000000},
+ {0x000083c4, 0x00000000},
+ {0x000083c8, 0x00000000},
+ {0x000083cc, 0x00000200},
+ {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9340Common_wo_xlna_rx_gain_table_1p0[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x03820190},
+ {0x0000a030, 0x03840383},
+ {0x0000a034, 0x03880385},
+ {0x0000a038, 0x038a0389},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x29292929},
+ {0x0000a084, 0x29292929},
+ {0x0000a088, 0x29292929},
+ {0x0000a08c, 0x29292929},
+ {0x0000a090, 0x22292929},
+ {0x0000a094, 0x1d1d2222},
+ {0x0000a098, 0x0c111117},
+ {0x0000a09c, 0x00030303},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x32323232},
+ {0x0000b084, 0x2f2f3232},
+ {0x0000b088, 0x23282a2d},
+ {0x0000b08c, 0x1c1e2123},
+ {0x0000b090, 0x14171919},
+ {0x0000b094, 0x0e0e1214},
+ {0x0000b098, 0x03050707},
+ {0x0000b09c, 0x00030303},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9340_1p0_soc_preamble[][2] = {
+ /* Addr allmodes */
+ {0x000040a4, 0x00a0c1c9},
+ {0x00007008, 0x00000000},
+ {0x00007020, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+};
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9485_initvals.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9485_initvals.h
new file mode 100644
index 00000000..611ea6ce
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ar9485_initvals.h
@@ -0,0 +1,1161 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9485_H
+#define INITVALS_9485_H
+
+static const u32 ar9485_1_1_mac_core[][2] = {
+ /* Addr allmodes */
+ {0x00000008, 0x00000000},
+ {0x00000030, 0x00020085},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000000},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x000010f0, 0x00000100},
+ {0x00001270, 0x00000000},
+ {0x000012b0, 0x00000000},
+ {0x000012f0, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00008000, 0x00000000},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000000},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00000000},
+ {0x00008040, 0x00000000},
+ {0x00008044, 0x00000000},
+ {0x00008048, 0x00000000},
+ {0x0000804c, 0xffffffff},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x00008070, 0x00000310},
+ {0x00008074, 0x00000020},
+ {0x00008078, 0x00000000},
+ {0x0000809c, 0x0000000f},
+ {0x000080a0, 0x00000000},
+ {0x000080a4, 0x02ff0000},
+ {0x000080a8, 0x0e070605},
+ {0x000080ac, 0x0000000d},
+ {0x000080b0, 0x00000000},
+ {0x000080b4, 0x00000000},
+ {0x000080b8, 0x00000000},
+ {0x000080bc, 0x00000000},
+ {0x000080c0, 0x2a800000},
+ {0x000080c4, 0x06900168},
+ {0x000080c8, 0x13881c22},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00252500},
+ {0x000080d4, 0x00a00000},
+ {0x000080d8, 0x00400000},
+ {0x000080dc, 0x00000000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x3f3f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00000000},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000000},
+ {0x00008114, 0x000007ff},
+ {0x00008118, 0x000000aa},
+ {0x0000811c, 0x00003210},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x0000ffff},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x18486200},
+ {0x00008174, 0x33332210},
+ {0x00008178, 0x00000000},
+ {0x0000817c, 0x00020000},
+ {0x000081c0, 0x00000000},
+ {0x000081c4, 0x33332210},
+ {0x000081d4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f400},
+ {0x00008248, 0x00000800},
+ {0x0000824c, 0x0001e800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x40000000},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x9ca00010},
+ {0x00008268, 0xffffffff},
+ {0x0000826c, 0x0000ffff},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000004},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x000000ff},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x0000829c, 0x00000000},
+ {0x00008300, 0x00000140},
+ {0x00008314, 0x00000000},
+ {0x0000831c, 0x0000010d},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000007},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000700},
+ {0x00008338, 0x00ff0000},
+ {0x0000833c, 0x02400000},
+ {0x00008340, 0x000107ff},
+ {0x00008344, 0xa248105b},
+ {0x00008348, 0x008f0000},
+ {0x0000835c, 0x00000000},
+ {0x00008360, 0xffffffff},
+ {0x00008364, 0xffffffff},
+ {0x00008368, 0x00000000},
+ {0x00008370, 0x00000000},
+ {0x00008374, 0x000000ff},
+ {0x00008378, 0x00000000},
+ {0x0000837c, 0x00000000},
+ {0x00008380, 0xffffffff},
+ {0x00008384, 0xffffffff},
+ {0x00008390, 0xffffffff},
+ {0x00008394, 0xffffffff},
+ {0x00008398, 0x00000000},
+ {0x0000839c, 0x00000000},
+ {0x000083a0, 0x00000000},
+ {0x000083a4, 0x0000fa14},
+ {0x000083a8, 0x000f0c00},
+ {0x000083ac, 0x33332210},
+ {0x000083b0, 0x33332210},
+ {0x000083b4, 0x33332210},
+ {0x000083b8, 0x33332210},
+ {0x000083bc, 0x00000000},
+ {0x000083c0, 0x00000000},
+ {0x000083c4, 0x00000000},
+ {0x000083c8, 0x00000000},
+ {0x000083cc, 0x00000200},
+ {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9485_1_1_baseband_core[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafe68e30},
+ {0x00009804, 0xfd14e000},
+ {0x00009808, 0x9c0a8f6b},
+ {0x0000980c, 0x04800000},
+ {0x00009814, 0x9280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+ {0x00009834, 0x5f3ca3de},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x14750600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+ {0x000098b0, 0x52440bbe},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+ {0x000098f0, 0x00000000},
+ {0x000098f4, 0x00000000},
+ {0x00009c04, 0x00000000},
+ {0x00009c08, 0x03200000},
+ {0x00009c0c, 0x00000000},
+ {0x00009c10, 0x00000000},
+ {0x00009c14, 0x00046384},
+ {0x00009c18, 0x05b6b440},
+ {0x00009c1c, 0x00b6b440},
+ {0x00009d00, 0xc080a333},
+ {0x00009d04, 0x40206c10},
+ {0x00009d08, 0x009c4060},
+ {0x00009d0c, 0x1883800a},
+ {0x00009d10, 0x01834061},
+ {0x00009d14, 0x00c00400},
+ {0x00009d18, 0x00000000},
+ {0x00009d1c, 0x00000000},
+ {0x00009e08, 0x0038233c},
+ {0x00009e24, 0x9927b515},
+ {0x00009e28, 0x12ef0200},
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+ {0x00009fc0, 0x80be4788},
+ {0x00009fc4, 0x0001efb5},
+ {0x00009fcc, 0x40000014},
+ {0x0000a20c, 0x00000000},
+ {0x0000a210, 0x00000000},
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a2a0, 0x00000001},
+ {0x0000a2c0, 0x00000001},
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2cc, 0x18c43433},
+ {0x0000a2d4, 0x00000000},
+ {0x0000a2dc, 0x00000000},
+ {0x0000a2e0, 0x00000000},
+ {0x0000a2e4, 0x00000000},
+ {0x0000a2e8, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+ {0x0000a2f8, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a34c, 0x00000000},
+ {0x0000a350, 0x0000a000},
+ {0x0000a364, 0x00000000},
+ {0x0000a370, 0x00000000},
+ {0x0000a390, 0x00000001},
+ {0x0000a394, 0x00000444},
+ {0x0000a398, 0x001f0e0f},
+ {0x0000a39c, 0x0075393f},
+ {0x0000a3a0, 0xb79f6427},
+ {0x0000a3a4, 0x000000ff},
+ {0x0000a3a8, 0x3b3b3b3b},
+ {0x0000a3ac, 0x2f2f2f2f},
+ {0x0000a3c0, 0x20202020},
+ {0x0000a3c4, 0x22222220},
+ {0x0000a3c8, 0x20200020},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3d8, 0x20202020},
+ {0x0000a3dc, 0x20202020},
+ {0x0000a3e0, 0x20202020},
+ {0x0000a3e4, 0x20202020},
+ {0x0000a3e8, 0x20202020},
+ {0x0000a3ec, 0x20202020},
+ {0x0000a3f0, 0x00000000},
+ {0x0000a3f4, 0x00000006},
+ {0x0000a3f8, 0x0cdbd380},
+ {0x0000a3fc, 0x000f0f01},
+ {0x0000a400, 0x8fa91f01},
+ {0x0000a404, 0x00000000},
+ {0x0000a408, 0x0e79e5c6},
+ {0x0000a40c, 0x00820820},
+ {0x0000a414, 0x1ce739cf},
+ {0x0000a418, 0x2d0019ce},
+ {0x0000a41c, 0x1ce739ce},
+ {0x0000a420, 0x000001ce},
+ {0x0000a424, 0x1ce739ce},
+ {0x0000a428, 0x000001ce},
+ {0x0000a42c, 0x1ce739ce},
+ {0x0000a430, 0x1ce739ce},
+ {0x0000a434, 0x00000000},
+ {0x0000a438, 0x00001801},
+ {0x0000a43c, 0x00000000},
+ {0x0000a440, 0x00000000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x04000000},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a5c4, 0xbfad9d74},
+ {0x0000a5c8, 0x0048060a},
+ {0x0000a5cc, 0x00000637},
+ {0x0000a760, 0x03020100},
+ {0x0000a764, 0x09080504},
+ {0x0000a768, 0x0d0c0b0a},
+ {0x0000a76c, 0x13121110},
+ {0x0000a770, 0x31301514},
+ {0x0000a774, 0x35343332},
+ {0x0000a778, 0x00000036},
+ {0x0000a780, 0x00000838},
+ {0x0000a7c0, 0x00000000},
+ {0x0000a7c4, 0xfffffffc},
+ {0x0000a7c8, 0x00000000},
+ {0x0000a7cc, 0x00000000},
+ {0x0000a7d0, 0x00000000},
+ {0x0000a7d4, 0x00000004},
+ {0x0000a7dc, 0x00000000},
+};
+
+static const u32 ar9485Common_1_1[][2] = {
+ /* Addr allmodes */
+ {0x00007010, 0x00000022},
+ {0x00007020, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+};
+
+static const u32 ar9485_1_1_baseband_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+ {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+ {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+ {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+ {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e},
+ {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+ {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+ {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+ {0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0},
+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
+ {0x0000a234, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff},
+ {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+ {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0},
+ {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982},
+ {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000be04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+ {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+ {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+ {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+ {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+ {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_1_1_radio_postamble[][2] = {
+ /* Addr allmodes */
+ {0x0001609c, 0x0b283f31},
+ {0x000160ac, 0x24611800},
+ {0x000160b0, 0x03284f3e},
+ {0x0001610c, 0x00170000},
+ {0x00016140, 0x10804008},
+};
+
+static const u32 ar9485_1_1_mac_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9485_1_1_radio_core[][2] = {
+ /* Addr allmodes */
+ {0x00016000, 0x36db6db6},
+ {0x00016004, 0x6db6db40},
+ {0x00016008, 0x73800000},
+ {0x0001600c, 0x00000000},
+ {0x00016040, 0x7f80fff8},
+ {0x0001604c, 0x000f0278},
+ {0x00016050, 0x4db6db8c},
+ {0x00016054, 0x6db60000},
+ {0x00016080, 0x00080000},
+ {0x00016084, 0x0e48048c},
+ {0x00016088, 0x14214514},
+ {0x0001608c, 0x119f081e},
+ {0x00016090, 0x24926490},
+ {0x00016098, 0xd28b3330},
+ {0x000160a0, 0xc2108ffe},
+ {0x000160a4, 0x812fc370},
+ {0x000160a8, 0x423c8000},
+ {0x000160b4, 0x92480040},
+ {0x000160c0, 0x006db6db},
+ {0x000160c4, 0x0186db60},
+ {0x000160c8, 0x6db6db6c},
+ {0x000160cc, 0x6de6fbe0},
+ {0x000160d0, 0xf7dfcf3c},
+ {0x00016100, 0x04cb0001},
+ {0x00016104, 0xfff80015},
+ {0x00016108, 0x00080010},
+ {0x00016144, 0x01884080},
+ {0x00016148, 0x00008040},
+ {0x00016240, 0x08400000},
+ {0x00016244, 0x1bf90f00},
+ {0x00016248, 0x00000000},
+ {0x0001624c, 0x00000000},
+ {0x00016280, 0x01000015},
+ {0x00016284, 0x00d30000},
+ {0x00016288, 0x00318000},
+ {0x0001628c, 0x50000000},
+ {0x00016290, 0x4b96210f},
+ {0x00016380, 0x00000000},
+ {0x00016384, 0x00000000},
+ {0x00016388, 0x00800700},
+ {0x0001638c, 0x00800700},
+ {0x00016390, 0x00800700},
+ {0x00016394, 0x00000000},
+ {0x00016398, 0x00000000},
+ {0x0001639c, 0x00000000},
+ {0x000163a0, 0x00000001},
+ {0x000163a4, 0x00000001},
+ {0x000163a8, 0x00000000},
+ {0x000163ac, 0x00000000},
+ {0x000163b0, 0x00000000},
+ {0x000163b4, 0x00000000},
+ {0x000163b8, 0x00000000},
+ {0x000163bc, 0x00000000},
+ {0x000163c0, 0x000000a0},
+ {0x000163c4, 0x000c0000},
+ {0x000163c8, 0x14021402},
+ {0x000163cc, 0x00001402},
+ {0x000163d0, 0x00000000},
+ {0x000163d4, 0x00000000},
+ {0x00016c40, 0x13188278},
+ {0x00016c44, 0x12000000},
+};
+
+static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_enable_L1[][2] = {
+ /* Addr allmodes */
+ {0x00018c00, 0x10052e5e},
+ {0x00018c04, 0x000801d8},
+ {0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+ {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+ {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_1_1[][2] = {
+ /* Addr allmodes */
+ {0x0000a580, 0x00000000},
+ {0x0000a584, 0x00000000},
+ {0x0000a588, 0x00000000},
+ {0x0000a58c, 0x00000000},
+ {0x0000a590, 0x00000000},
+ {0x0000a594, 0x00000000},
+ {0x0000a598, 0x00000000},
+ {0x0000a59c, 0x00000000},
+ {0x0000a5a0, 0x00000000},
+ {0x0000a5a4, 0x00000000},
+ {0x0000a5a8, 0x00000000},
+ {0x0000a5ac, 0x00000000},
+ {0x0000a5b0, 0x00000000},
+ {0x0000a5b4, 0x00000000},
+ {0x0000a5b8, 0x00000000},
+ {0x0000a5bc, 0x00000000},
+};
+
+static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+ {0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006},
+ {0x0000a504, 0x05062002, 0x05062002, 0x03000201, 0x03000201},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x06000203, 0x06000203},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0a000401, 0x0a000401},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x0e000403, 0x0e000403},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x12000405, 0x12000405},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x15000604, 0x15000604},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x18000605, 0x18000605},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x1c000a04, 0x1c000a04},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x21000a06, 0x21000a06},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x29000a24, 0x29000a24},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x2f000e21, 0x2f000e21},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000e20, 0x31000e20},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x33000e20, 0x33000e20},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+ {0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+ {0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+ {0x0000b50c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+ {0x0000b510, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+ {0x0000b514, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+ {0x0000b518, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+ {0x0000b51c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+ {0x0000b520, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+ {0x0000b524, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+ {0x0000b528, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+ {0x0000b52c, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a},
+ {0x0000b530, 0x0000003a, 0x0000003a, 0x0000003a, 0x0000003a},
+ {0x0000b534, 0x0000004a, 0x0000004a, 0x0000004a, 0x0000004a},
+ {0x0000b538, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b53c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b540, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b544, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b548, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b54c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b550, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b554, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b558, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b55c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b560, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b564, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b568, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b56c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b570, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b574, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b578, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x0000b57c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+ {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+ {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = {
+ /* Addr allmodes */
+ {0x00018c00, 0x10013e5e},
+ {0x00018c04, 0x000801d8},
+ {0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485_1_1_soc_preamble[][2] = {
+ /* Addr allmodes */
+ {0x00004014, 0xba280400},
+ {0x00004090, 0x00aa10aa},
+ {0x000040a4, 0x00a0c9c9},
+ {0x00007010, 0x00000022},
+ {0x00007020, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+ {0x00007048, 0x00000002},
+};
+
+static const u32 ar9485_1_1_baseband_core_txfir_coeff_japan_2484[][2] = {
+ /* Addr allmodes */
+ {0x0000a398, 0x00000000},
+ {0x0000a39c, 0x6f7f0301},
+ {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+ {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+ {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_fast_clock_1_1_baseband_postamble[][3] = {
+ /* Addr 5G_HT2 5G_HT40 */
+ {0x00009e00, 0x03721821, 0x03721821},
+ {0x0000a230, 0x0000400b, 0x00004016},
+ {0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = {
+ /* Addr allmodes */
+ {0x00018c00, 0x10012e5e},
+ {0x00018c04, 0x000801d8},
+ {0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485_common_rx_gain_1_1[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x01800082},
+ {0x0000a014, 0x01820181},
+ {0x0000a018, 0x01840183},
+ {0x0000a01c, 0x01880185},
+ {0x0000a020, 0x018a0189},
+ {0x0000a024, 0x02850284},
+ {0x0000a028, 0x02890288},
+ {0x0000a02c, 0x03850384},
+ {0x0000a030, 0x03890388},
+ {0x0000a034, 0x038b038a},
+ {0x0000a038, 0x038d038c},
+ {0x0000a03c, 0x03910390},
+ {0x0000a040, 0x03930392},
+ {0x0000a044, 0x03950394},
+ {0x0000a048, 0x00000396},
+ {0x0000a04c, 0x00000000},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x28282828},
+ {0x0000a084, 0x28282828},
+ {0x0000a088, 0x28282828},
+ {0x0000a08c, 0x28282828},
+ {0x0000a090, 0x28282828},
+ {0x0000a094, 0x21212128},
+ {0x0000a098, 0x171c1c1c},
+ {0x0000a09c, 0x02020212},
+ {0x0000a0a0, 0x00000202},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x111f1100},
+ {0x0000a0c8, 0x111d111e},
+ {0x0000a0cc, 0x111b111c},
+ {0x0000a0d0, 0x22032204},
+ {0x0000a0d4, 0x22012202},
+ {0x0000a0d8, 0x221f2200},
+ {0x0000a0dc, 0x221d221e},
+ {0x0000a0e0, 0x33013302},
+ {0x0000a0e4, 0x331f3300},
+ {0x0000a0e8, 0x4402331e},
+ {0x0000a0ec, 0x44004401},
+ {0x0000a0f0, 0x441e441f},
+ {0x0000a0f4, 0x55015502},
+ {0x0000a0f8, 0x551f5500},
+ {0x0000a0fc, 0x6602551e},
+ {0x0000a100, 0x66006601},
+ {0x0000a104, 0x661e661f},
+ {0x0000a108, 0x7703661d},
+ {0x0000a10c, 0x77017702},
+ {0x0000a110, 0x00007700},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x111f1100},
+ {0x0000a148, 0x111d111e},
+ {0x0000a14c, 0x111b111c},
+ {0x0000a150, 0x22032204},
+ {0x0000a154, 0x22012202},
+ {0x0000a158, 0x221f2200},
+ {0x0000a15c, 0x221d221e},
+ {0x0000a160, 0x33013302},
+ {0x0000a164, 0x331f3300},
+ {0x0000a168, 0x4402331e},
+ {0x0000a16c, 0x44004401},
+ {0x0000a170, 0x441e441f},
+ {0x0000a174, 0x55015502},
+ {0x0000a178, 0x551f5500},
+ {0x0000a17c, 0x6602551e},
+ {0x0000a180, 0x66006601},
+ {0x0000a184, 0x661e661f},
+ {0x0000a188, 0x7703661d},
+ {0x0000a18c, 0x77017702},
+ {0x0000a190, 0x00007700},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9485_1_1_pcie_phy_clkreq_enable_L1[][2] = {
+ /* Addr allmodes */
+ {0x00018c00, 0x10053e5e},
+ {0x00018c04, 0x000801d8},
+ {0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00060005},
+ {0x0000a004, 0x00810080},
+ {0x0000a008, 0x00830082},
+ {0x0000a00c, 0x00850084},
+ {0x0000a010, 0x01820181},
+ {0x0000a014, 0x01840183},
+ {0x0000a018, 0x01880185},
+ {0x0000a01c, 0x018a0189},
+ {0x0000a020, 0x02850284},
+ {0x0000a024, 0x02890288},
+ {0x0000a028, 0x028b028a},
+ {0x0000a02c, 0x03850384},
+ {0x0000a030, 0x03890388},
+ {0x0000a034, 0x038b038a},
+ {0x0000a038, 0x038d038c},
+ {0x0000a03c, 0x03910390},
+ {0x0000a040, 0x03930392},
+ {0x0000a044, 0x03950394},
+ {0x0000a048, 0x00000396},
+ {0x0000a04c, 0x00000000},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x28282828},
+ {0x0000a084, 0x28282828},
+ {0x0000a088, 0x28282828},
+ {0x0000a08c, 0x28282828},
+ {0x0000a090, 0x28282828},
+ {0x0000a094, 0x24242428},
+ {0x0000a098, 0x171e1e1e},
+ {0x0000a09c, 0x02020b0b},
+ {0x0000a0a0, 0x02020202},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x22072208},
+ {0x0000a0c4, 0x22052206},
+ {0x0000a0c8, 0x22032204},
+ {0x0000a0cc, 0x22012202},
+ {0x0000a0d0, 0x221f2200},
+ {0x0000a0d4, 0x221d221e},
+ {0x0000a0d8, 0x33023303},
+ {0x0000a0dc, 0x33003301},
+ {0x0000a0e0, 0x331e331f},
+ {0x0000a0e4, 0x4402331d},
+ {0x0000a0e8, 0x44004401},
+ {0x0000a0ec, 0x441e441f},
+ {0x0000a0f0, 0x55025503},
+ {0x0000a0f4, 0x55005501},
+ {0x0000a0f8, 0x551e551f},
+ {0x0000a0fc, 0x6602551d},
+ {0x0000a100, 0x66006601},
+ {0x0000a104, 0x661e661f},
+ {0x0000a108, 0x7703661d},
+ {0x0000a10c, 0x77017702},
+ {0x0000a110, 0x00007700},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x111f1100},
+ {0x0000a148, 0x111d111e},
+ {0x0000a14c, 0x111b111c},
+ {0x0000a150, 0x22032204},
+ {0x0000a154, 0x22012202},
+ {0x0000a158, 0x221f2200},
+ {0x0000a15c, 0x221d221e},
+ {0x0000a160, 0x33013302},
+ {0x0000a164, 0x331f3300},
+ {0x0000a168, 0x4402331e},
+ {0x0000a16c, 0x44004401},
+ {0x0000a170, 0x441e441f},
+ {0x0000a174, 0x55015502},
+ {0x0000a178, 0x551f5500},
+ {0x0000a17c, 0x6602551e},
+ {0x0000a180, 0x66006601},
+ {0x0000a184, 0x661e661f},
+ {0x0000a188, 0x7703661d},
+ {0x0000a18c, 0x77017702},
+ {0x0000a190, 0x00007700},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000296},
+};
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k.c
new file mode 100644
index 00000000..183aa65f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/pci.h>
+
+#include "ath9k.h"
+
+static struct pci_device_id ath_pci_id_table[] = {
+ PCI_ROM(0x168c, 0x0023, "ar5416", "Atheros 5416 PCI", 0), /* PCI */
+ PCI_ROM(0x168c, 0x0024, "ar5416", "Atheros 5416 PCI-E", 0), /* PCI-E */
+ PCI_ROM(0x168c, 0x0027, "ar9160", "Atheros 9160 PCI", 0), /* PCI */
+ PCI_ROM(0x168c, 0x0029, "ar9280", "Atheros 9280 PCI", 0), /* PCI */
+ PCI_ROM(0x168c, 0x002A, "ar9280", "Atheros 9280 PCI-E", 0), /* PCI-E */
+ PCI_ROM(0x168c, 0x002B, "ar9285", "Atheros 9285 PCI-E", 0), /* PCI-E */
+ PCI_ROM(0x168c, 0x002C, "ar2427", "Atheros 2427 PCI-E", 0), /* PCI-E 802.11n bonded out */
+ PCI_ROM(0x168c, 0x002D, "ar9287", "Atheros 9287 PCI", 0), /* PCI */
+ PCI_ROM(0x168c, 0x002E, "ar9287", "Atheros 9287 PCI-E", 0), /* PCI-E */
+ PCI_ROM(0x168c, 0x0030, "ar9300", "Atheros 9300 PCI-E", 0), /* PCI-E AR9300 */
+ PCI_ROM(0x168c, 0x0032, "ar9485", "Atheros 9485 PCI-E", 0), /* PCI-E AR9485 */
+};
+
+
+/* return bus cachesize in 4B word units */
+static void ath_pci_read_cachesize(struct ath_common *common, int *csz)
+{
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+ u8 u8tmp;
+
+ pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, &u8tmp);
+ *csz = (int)u8tmp;
+
+ /*
+ * This check was put in to avoid "unpleasant" consequences if
+ * the bootrom has not fully initialized all PCI devices.
+ * Sometimes the cache line size register is not set
+ */
+
+ if (*csz == 0)
+ *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */
+}
+
+static int ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
+{
+ struct ath_hw *ah = (struct ath_hw *) common->ah;
+
+ common->ops->read(ah, AR5416_EEPROM_OFFSET +
+ (off << AR5416_EEPROM_S));
+
+ if (!ath9k_hw_wait(ah,
+ AR_EEPROM_STATUS_DATA,
+ AR_EEPROM_STATUS_DATA_BUSY |
+ AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
+ AH_WAIT_TIMEOUT)) {
+ return 0;
+ }
+
+ *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA),
+ AR_EEPROM_STATUS_DATA_VAL);
+
+ return 1;
+}
+
+static void ath_pci_extn_synch_enable(struct ath_common *common)
+{
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+ struct pci_device *pdev = sc->pdev;
+ u8 lnkctl;
+
+ pci_read_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, &lnkctl);
+ lnkctl |= 0x0080;
+ pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);
+}
+
+static const struct ath_bus_ops ath_pci_bus_ops = {
+ .ath_bus_type = ATH_PCI,
+ .read_cachesize = ath_pci_read_cachesize,
+ .eeprom_read = ath_pci_eeprom_read,
+ .extn_synch_en = ath_pci_extn_synch_enable,
+};
+
+static int ath_pci_probe(struct pci_device *pdev)
+{
+ void *mem;
+ struct ath_softc *sc;
+ struct net80211_device *dev;
+ u8 csz;
+ u16 subsysid;
+ u32 val;
+ int ret = 0;
+ char hw_name[64];
+
+ adjust_pci_device(pdev);
+
+ /*
+ * Cache line size is used to size and align various
+ * structures used to communicate with the hardware.
+ */
+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
+ if (csz == 0) {
+ /*
+ * Linux 2.4.18 (at least) writes the cache line size
+ * register as a 16-bit wide register which is wrong.
+ * We must have this setup properly for rx buffer
+ * DMA to work so force a reasonable value here if it
+ * comes up zero.
+ */
+ csz =16;
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
+ }
+ /*
+ * The default setting of latency timer yields poor results,
+ * set it to the value used by other systems. It may be worth
+ * tweaking this setting more.
+ */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
+
+ /*
+ * Disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state.
+ */
+ pci_read_config_dword(pdev, 0x40, &val);
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+ mem = ioremap(pdev->membase, 0x10000);
+ if (!mem) {
+ DBG("ath9K: PCI memory map error\n") ;
+ ret = -EIO;
+ goto err_iomap;
+ }
+
+ dev = net80211_alloc(sizeof(struct ath_softc));
+ if (!dev) {
+ DBG("ath9k: No memory for net80211_device\n");
+ ret = -ENOMEM;
+ goto err_alloc_hw;
+ }
+
+ pci_set_drvdata(pdev, dev);
+ dev->netdev->dev = (struct device *)pdev;
+
+ sc = dev->priv;
+ sc->dev = dev;
+ sc->pdev = pdev;
+ sc->mem = mem;
+
+ /* Will be cleared in ath9k_start() */
+ sc->sc_flags |= SC_OP_INVALID;
+
+ sc->irq = pdev->irq;
+
+ pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid);
+ ret = ath9k_init_device(pdev->device, sc, subsysid, &ath_pci_bus_ops);
+ if (ret) {
+ DBG("ath9k: Failed to initialize device\n");
+ goto err_init;
+ }
+
+ ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
+ DBG("ath9k: %s mem=0x%lx, irq=%d\n",
+ hw_name, (unsigned long)mem, pdev->irq);
+
+ return 0;
+
+err_init:
+ net80211_free(dev);
+err_alloc_hw:
+ iounmap(mem);
+err_iomap:
+ return ret;
+}
+
+static void ath_pci_remove(struct pci_device *pdev)
+{
+ struct net80211_device *dev = pci_get_drvdata(pdev);
+ struct ath_softc *sc = dev->priv;
+ void *mem = sc->mem;
+
+ if (!is_ath9k_unloaded)
+ sc->sc_ah->ah_flags |= AH_UNPLUGGED;
+ ath9k_deinit_device(sc);
+ net80211_free(sc->dev);
+
+ iounmap(mem);
+}
+
+struct pci_driver ath_pci_driver __pci_driver = {
+ .id_count = ARRAY_SIZE(ath_pci_id_table),
+ .ids = ath_pci_id_table,
+ .probe = ath_pci_probe,
+ .remove = ath_pci_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k.h
new file mode 100644
index 00000000..d2dce9b7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k.h
@@ -0,0 +1,521 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ATH9K_H
+#define ATH9K_H
+
+#include "common.h"
+
+/*
+ * Header for the ath9k.ko driver core *only* -- hw code nor any other driver
+ * should rely on this file or its contents.
+ */
+
+struct ath_node;
+struct ath_softc;
+
+/* Macro to expand scalars to 64-bit objects */
+
+#define ito64(x) (sizeof(x) == 1) ? \
+ (((unsigned long long int)(x)) & (0xff)) : \
+ (sizeof(x) == 2) ? \
+ (((unsigned long long int)(x)) & 0xffff) : \
+ ((sizeof(x) == 4) ? \
+ (((unsigned long long int)(x)) & 0xffffffff) : \
+ (unsigned long long int)(x))
+
+/* increment with wrap-around */
+#define INCR(_l, _sz) do { \
+ (_l)++; \
+ (_l) &= ((_sz) - 1); \
+ } while (0)
+
+/* decrement with wrap-around */
+#define DECR(_l, _sz) do { \
+ (_l)--; \
+ (_l) &= ((_sz) - 1); \
+ } while (0)
+
+#define A_MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#define TSF_TO_TU(_h,_l) \
+ ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
+
+#define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i))
+
+struct ath_config {
+ u16 txpowlimit;
+ u8 cabqReadytime;
+};
+
+/*************************/
+/* Descriptor Management */
+/*************************/
+
+#define ATH_TXBUF_RESET(_bf) do { \
+ (_bf)->bf_stale = 0; \
+ (_bf)->bf_lastbf = NULL; \
+ (_bf)->bf_next = NULL; \
+ memset(&((_bf)->bf_state), 0, \
+ sizeof(struct ath_buf_state)); \
+ } while (0)
+
+#define ATH_RXBUF_RESET(_bf) do { \
+ (_bf)->bf_stale = 0; \
+ } while (0)
+
+/**
+ * enum buffer_type - Buffer type flags
+ *
+ * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
+ * @BUF_AGGR: Indicates whether the buffer can be aggregated
+ * (used in aggregation scheduling)
+ * @BUF_XRETRY: To denote excessive retries of the buffer
+ */
+enum buffer_type {
+ BUF_AMPDU = BIT(0),
+ BUF_AGGR = BIT(1),
+ BUF_XRETRY = BIT(2),
+};
+
+#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
+#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
+#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY)
+
+#define ATH_TXSTATUS_RING_SIZE 64
+
+struct ath_descdma {
+ void *dd_desc;
+ u32 dd_desc_paddr;
+ u32 dd_desc_len;
+ struct ath_buf *dd_bufptr;
+};
+
+int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
+ struct list_head *head, const char *name,
+ int nbuf, int ndesc, int is_tx);
+void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
+ struct list_head *head);
+
+/***********/
+/* RX / TX */
+/***********/
+
+#define ATH_RXBUF 16
+#define ATH_TXBUF 16
+#define ATH_TXBUF_RESERVE 5
+#define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
+#define ATH_TXMAXTRY 13
+
+#define TID_TO_WME_AC(_tid) \
+ ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
+ (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
+ (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
+ WME_AC_VO)
+
+#define ATH_AGGR_DELIM_SZ 4
+#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
+/* number of delimiters for encryption padding */
+#define ATH_AGGR_ENCRYPTDELIM 10
+/* minimum h/w qdepth to be sustained to maximize aggregation */
+#define ATH_AGGR_MIN_QDEPTH 2
+#define ATH_AMPDU_SUBFRAME_DEFAULT 32
+
+#define FCS_LEN 4
+#define IEEE80211_SEQ_SEQ_SHIFT 4
+#define IEEE80211_SEQ_MAX 4096
+#define IEEE80211_WEP_IVLEN 3
+#define IEEE80211_WEP_KIDLEN 1
+#define IEEE80211_WEP_CRCLEN 4
+#define IEEE80211_MAX_MPDU_LEN (3840 + FCS_LEN + \
+ (IEEE80211_WEP_IVLEN + \
+ IEEE80211_WEP_KIDLEN + \
+ IEEE80211_WEP_CRCLEN))
+
+/* return whether a bit at index _n in bitmap _bm is set
+ * _sz is the size of the bitmap */
+#define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \
+ ((_bm)[(_n) >> 5] & (1 << ((_n) & 31))))
+
+/* return block-ack bitmap index given sequence and starting sequence */
+#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
+
+/* returns delimiter padding required given the packet length */
+#define ATH_AGGR_GET_NDELIM(_len) \
+ (((_len) >= ATH_AGGR_MINPLEN) ? 0 : \
+ DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ))
+
+#define BAW_WITHIN(_start, _bawsz, _seqno) \
+ ((((_seqno) - (_start)) & 4095) < (_bawsz))
+
+#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)])
+
+#define ATH_TX_COMPLETE_POLL_INT 1000
+
+enum ATH_AGGR_STATUS {
+ ATH_AGGR_DONE,
+ ATH_AGGR_BAW_CLOSED,
+ ATH_AGGR_LIMITED,
+};
+
+#define ATH_TXFIFO_DEPTH 8
+struct ath_txq {
+ int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
+ u32 axq_qnum; /* ath9k hardware queue number */
+ u32 *axq_link;
+ struct list_head axq_q;
+ u32 axq_depth;
+ u32 axq_ampdu_depth;
+ int stopped;
+ int axq_tx_inprogress;
+ struct list_head axq_acq;
+ struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
+ struct list_head txq_fifo_pending;
+ u8 txq_headidx;
+ u8 txq_tailidx;
+ int pending_frames;
+};
+
+struct ath_atx_ac {
+ struct ath_txq *txq;
+ int sched;
+ struct list_head list;
+ struct list_head tid_q;
+ int clear_ps_filter;
+};
+
+struct ath_frame_info {
+ int framelen;
+ u32 keyix;
+ enum ath9k_key_type keytype;
+ u8 retries;
+ u16 seqno;
+};
+
+struct ath_buf_state {
+ u8 bf_type;
+ u8 bfs_paprd;
+ unsigned long bfs_paprd_timestamp;
+};
+
+struct ath_buf {
+ struct list_head list;
+ struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or
+ an aggregate) */
+ struct ath_buf *bf_next; /* next subframe in the aggregate */
+ struct io_buffer *bf_mpdu; /* enclosing frame structure */
+ void *bf_desc; /* virtual addr of desc */
+ u32 bf_daddr; /* physical addr of desc */
+ u32 bf_buf_addr; /* physical addr of data buffer, for DMA */
+ int bf_stale;
+ u16 bf_flags;
+ struct ath_buf_state bf_state;
+};
+
+struct ath_atx_tid {
+ struct list_head list;
+ struct list_head buf_q;
+ struct ath_node *an;
+ struct ath_atx_ac *ac;
+ unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
+ u16 seq_start;
+ u16 seq_next;
+ u16 baw_size;
+ int tidno;
+ int baw_head; /* first un-acked tx buffer */
+ int baw_tail; /* next unused tx buffer slot */
+ int sched;
+ int paused;
+ u8 state;
+};
+
+struct ath_node {
+ struct ath_atx_tid tid[WME_NUM_TID];
+ struct ath_atx_ac ac[WME_NUM_AC];
+ int ps_key;
+
+ u16 maxampdu;
+ u8 mpdudensity;
+
+ int sleeping;
+};
+
+#define AGGR_CLEANUP BIT(1)
+#define AGGR_ADDBA_COMPLETE BIT(2)
+#define AGGR_ADDBA_PROGRESS BIT(3)
+
+struct ath_tx_control {
+ struct ath_txq *txq;
+ struct ath_node *an;
+ int if_id;
+ u8 paprd;
+};
+
+#define ATH_TX_ERROR 0x01
+#define ATH_TX_XRETRY 0x02
+#define ATH_TX_BAR 0x04
+
+/**
+ * @txq_map: Index is mac80211 queue number. This is
+ * not necessarily the same as the hardware queue number
+ * (axq_qnum).
+ */
+struct ath_tx {
+ u16 seq_no;
+ u32 txqsetup;
+ struct list_head txbuf;
+ struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
+ struct ath_descdma txdma;
+ struct ath_txq *txq_map[WME_NUM_AC];
+};
+
+struct ath_rx_edma {
+ struct list_head rx_fifo;
+ struct list_head rx_buffers;
+ u32 rx_fifo_hwsize;
+};
+
+struct ath_rx {
+ u8 defant;
+ u8 rxotherant;
+ u32 *rxlink;
+ unsigned int rxfilter;
+ struct list_head rxbuf;
+ struct ath_descdma rxdma;
+ struct ath_buf *rx_bufptr;
+ struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
+
+ struct io_buffer *frag;
+};
+
+int ath_startrecv(struct ath_softc *sc);
+int ath_stoprecv(struct ath_softc *sc);
+void ath_flushrecv(struct ath_softc *sc);
+u32 ath_calcrxfilter(struct ath_softc *sc);
+int ath_rx_init(struct ath_softc *sc, int nbufs);
+void ath_rx_cleanup(struct ath_softc *sc);
+int ath_rx_tasklet(struct ath_softc *sc, int flush, int hp);
+struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
+void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
+int ath_drain_all_txq(struct ath_softc *sc, int retry_tx);
+void ath_draintxq(struct ath_softc *sc,
+ struct ath_txq *txq, int retry_tx);
+void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
+int ath_tx_init(struct ath_softc *sc, int nbufs);
+void ath_tx_cleanup(struct ath_softc *sc);
+int ath_txq_update(struct ath_softc *sc, int qnum,
+ struct ath9k_tx_queue_info *q);
+int ath_tx_start(struct net80211_device *dev, struct io_buffer *iob,
+ struct ath_tx_control *txctl);
+void ath_tx_tasklet(struct ath_softc *sc);
+
+/*******/
+/* ANI */
+/*******/
+
+#define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */
+#define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */
+#define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */
+#define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */
+#define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */
+#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
+#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
+
+void ath_hw_pll_work(struct ath_softc *sc);
+void ath_ani_calibrate(struct ath_softc *sc);
+
+/********************/
+/* Main driver core */
+/********************/
+
+/*
+ * Default cache line size, in bytes.
+ * Used when PCI device not fully initialized by bootrom/BIOS
+*/
+#define DEFAULT_CACHELINE 32
+#define ATH_REGCLASSIDS_MAX 10
+#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
+#define ATH_MAX_SW_RETRIES 10
+#define ATH_CHAN_MAX 255
+
+#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
+#define ATH_RATE_DUMMY_MARKER 0
+
+#define SC_OP_INVALID BIT(0)
+#define SC_OP_BEACONS BIT(1)
+#define SC_OP_RXAGGR BIT(2)
+#define SC_OP_TXAGGR BIT(3)
+#define SC_OP_OFFCHANNEL BIT(4)
+#define SC_OP_PREAMBLE_SHORT BIT(5)
+#define SC_OP_PROTECT_ENABLE BIT(6)
+#define SC_OP_RXFLUSH BIT(7)
+#define SC_OP_LED_ASSOCIATED BIT(8)
+#define SC_OP_LED_ON BIT(9)
+#define SC_OP_TSF_RESET BIT(11)
+#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
+#define SC_OP_BT_SCAN BIT(13)
+#define SC_OP_ANI_RUN BIT(14)
+#define SC_OP_ENABLE_APM BIT(15)
+#define SC_OP_PRIM_STA_VIF BIT(16)
+
+/* Powersave flags */
+#define PS_WAIT_FOR_BEACON BIT(0)
+#define PS_WAIT_FOR_CAB BIT(1)
+#define PS_WAIT_FOR_PSPOLL_DATA BIT(2)
+#define PS_WAIT_FOR_TX_ACK BIT(3)
+#define PS_BEACON_SYNC BIT(4)
+#define PS_TSFOOR_SYNC BIT(5)
+
+struct ath_rate_table;
+
+struct ath9k_legacy_rate {
+ u16 bitrate;
+ u32 flags;
+ u16 hw_value;
+ u16 hw_value_short;
+};
+
+enum ath9k_rate_control_flags {
+ IEEE80211_TX_RC_USE_RTS_CTS = BIT(0),
+ IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1),
+ IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2),
+
+ /* rate index is an MCS rate number instead of an index */
+ IEEE80211_TX_RC_MCS = BIT(3),
+ IEEE80211_TX_RC_GREEN_FIELD = BIT(4),
+ IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5),
+ IEEE80211_TX_RC_DUP_DATA = BIT(6),
+ IEEE80211_TX_RC_SHORT_GI = BIT(7),
+};
+
+struct survey_info {
+ struct net80211_channel *channel;
+ u64 channel_time;
+ u64 channel_time_busy;
+ u64 channel_time_ext_busy;
+ u64 channel_time_rx;
+ u64 channel_time_tx;
+ u32 filled;
+ s8 noise;
+};
+
+enum survey_info_flags {
+ SURVEY_INFO_NOISE_DBM = 1<<0,
+ SURVEY_INFO_IN_USE = 1<<1,
+ SURVEY_INFO_CHANNEL_TIME = 1<<2,
+ SURVEY_INFO_CHANNEL_TIME_BUSY = 1<<3,
+ SURVEY_INFO_CHANNEL_TIME_EXT_BUSY = 1<<4,
+ SURVEY_INFO_CHANNEL_TIME_RX = 1<<5,
+ SURVEY_INFO_CHANNEL_TIME_TX = 1<<6,
+};
+
+struct ath9k_vif_iter_data {
+ const u8 *hw_macaddr; /* phy's hardware address, set
+ * before starting iteration for
+ * valid bssid mask.
+ */
+ u8 mask[ETH_ALEN]; /* bssid mask */
+ int naps; /* number of AP vifs */
+ int nmeshes; /* number of mesh vifs */
+ int nstations; /* number of station vifs */
+ int nwds; /* number of nwd vifs */
+ int nadhocs; /* number of adhoc vifs */
+ int nothers; /* number of vifs not specified above. */
+};
+
+struct ath_softc {
+ struct net80211_device *dev;
+ struct pci_device *pdev;
+
+ int chan_idx;
+ int chan_is_ht;
+ struct survey_info *cur_survey;
+ struct survey_info survey[ATH9K_NUM_CHANNELS];
+
+ void (*intr_tq)(struct ath_softc *sc);
+ struct ath_hw *sc_ah;
+ void *mem;
+ int irq;
+
+ void (*paprd_work)(struct ath_softc *sc);
+ void (*hw_check_work)(struct ath_softc *sc);
+ void (*paprd_complete)(struct ath_softc *sc);
+
+ unsigned int hw_busy_count;
+
+ u32 intrstatus;
+ u32 sc_flags; /* SC_OP_* */
+ u16 ps_flags; /* PS_* */
+ u16 curtxpow;
+ int ps_enabled;
+ int ps_idle;
+ short nbcnvifs;
+ short nvifs;
+ unsigned long ps_usecount;
+
+ struct ath_config config;
+ struct ath_rx rx;
+ struct ath_tx tx;
+ struct net80211_hw_info *hwinfo;
+ struct ath9k_legacy_rate rates[NET80211_MAX_RATES];
+ int hw_rix;
+
+ struct ath9k_hw_cal_data caldata;
+ int last_rssi;
+
+ void (*tx_complete_work)(struct ath_softc *sc);
+ unsigned long tx_complete_work_timer;
+ void (*hw_pll_work)(struct ath_softc *sc);
+ unsigned long hw_pll_work_timer;
+
+ struct ath_descdma txsdma;
+};
+
+void ath9k_tasklet(struct ath_softc *sc);
+int ath_reset(struct ath_softc *sc, int retry_tx);
+
+static inline void ath_read_cachesize(struct ath_common *common, int *csz)
+{
+ common->bus_ops->read_cachesize(common, csz);
+}
+
+extern struct net80211_device_operations ath9k_ops;
+extern int ath9k_modparam_nohwcrypt;
+extern int is_ath9k_unloaded;
+
+void ath_isr(struct net80211_device *dev);
+void ath9k_init_crypto(struct ath_softc *sc);
+int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
+ const struct ath_bus_ops *bus_ops);
+void ath9k_deinit_device(struct ath_softc *sc);
+void ath9k_set_hw_capab(struct ath_softc *sc, struct net80211_device *dev);
+int ath_set_channel(struct ath_softc *sc, struct net80211_device *dev,
+ struct ath9k_channel *hchan);
+
+void ath_radio_enable(struct ath_softc *sc, struct net80211_device *dev);
+void ath_radio_disable(struct ath_softc *sc, struct net80211_device *dev);
+int ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
+int ath9k_uses_beacons(int type);
+
+u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
+
+void ath_start_rfkill_poll(struct ath_softc *sc);
+extern void ath9k_rfkill_poll_state(struct net80211_device *dev);
+
+#endif /* ATH9K_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ani.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ani.c
new file mode 100644
index 00000000..ff7df497
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ani.c
@@ -0,0 +1,733 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "hw-ops.h"
+
+struct ani_ofdm_level_entry {
+ int spur_immunity_level;
+ int fir_step_level;
+ int ofdm_weak_signal_on;
+};
+
+/* values here are relative to the INI */
+
+/*
+ * Legend:
+ *
+ * SI: Spur immunity
+ * FS: FIR Step
+ * WS: OFDM / CCK Weak Signal detection
+ * MRC-CCK: Maximal Ratio Combining for CCK
+ */
+
+static const struct ani_ofdm_level_entry ofdm_level_table[] = {
+ /* SI FS WS */
+ { 0, 0, 1 }, /* lvl 0 */
+ { 1, 1, 1 }, /* lvl 1 */
+ { 2, 2, 1 }, /* lvl 2 */
+ { 3, 2, 1 }, /* lvl 3 (default) */
+ { 4, 3, 1 }, /* lvl 4 */
+ { 5, 4, 1 }, /* lvl 5 */
+ { 6, 5, 1 }, /* lvl 6 */
+ { 7, 6, 1 }, /* lvl 7 */
+ { 7, 7, 1 }, /* lvl 8 */
+ { 7, 8, 0 } /* lvl 9 */
+};
+#define ATH9K_ANI_OFDM_NUM_LEVEL \
+ ARRAY_SIZE(ofdm_level_table)
+#define ATH9K_ANI_OFDM_MAX_LEVEL \
+ (ATH9K_ANI_OFDM_NUM_LEVEL-1)
+#define ATH9K_ANI_OFDM_DEF_LEVEL \
+ 3 /* default level - matches the INI settings */
+
+/*
+ * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm.
+ * With OFDM for single stream you just add up all antenna inputs, you're
+ * only interested in what you get after FFT. Signal aligment is also not
+ * required for OFDM because any phase difference adds up in the frequency
+ * domain.
+ *
+ * MRC requires extra work for use with CCK. You need to align the antenna
+ * signals from the different antenna before you can add the signals together.
+ * You need aligment of signals as CCK is in time domain, so addition can cancel
+ * your signal completely if phase is 180 degrees (think of adding sine waves).
+ * You also need to remove noise before the addition and this is where ANI
+ * MRC CCK comes into play. One of the antenna inputs may be stronger but
+ * lower SNR, so just adding after alignment can be dangerous.
+ *
+ * Regardless of alignment in time, the antenna signals add constructively after
+ * FFT and improve your reception. For more information:
+ *
+ * http://en.wikipedia.org/wiki/Maximal-ratio_combining
+ */
+
+struct ani_cck_level_entry {
+ int fir_step_level;
+ int mrc_cck_on;
+};
+
+static const struct ani_cck_level_entry cck_level_table[] = {
+ /* FS MRC-CCK */
+ { 0, 1 }, /* lvl 0 */
+ { 1, 1 }, /* lvl 1 */
+ { 2, 1 }, /* lvl 2 (default) */
+ { 3, 1 }, /* lvl 3 */
+ { 4, 0 }, /* lvl 4 */
+ { 5, 0 }, /* lvl 5 */
+ { 6, 0 }, /* lvl 6 */
+ { 7, 0 }, /* lvl 7 (only for high rssi) */
+ { 8, 0 } /* lvl 8 (only for high rssi) */
+};
+
+#define ATH9K_ANI_CCK_NUM_LEVEL \
+ ARRAY_SIZE(cck_level_table)
+#define ATH9K_ANI_CCK_MAX_LEVEL \
+ (ATH9K_ANI_CCK_NUM_LEVEL-1)
+#define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \
+ (ATH9K_ANI_CCK_NUM_LEVEL-3)
+#define ATH9K_ANI_CCK_DEF_LEVEL \
+ 2 /* default level - matches the INI settings */
+
+static int use_new_ani(struct ath_hw *ah)
+{
+ return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani;
+}
+
+static void ath9k_hw_update_mibstats(struct ath_hw *ah,
+ struct ath9k_mib_stats *stats)
+{
+ stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
+ stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
+ stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
+ stats->rts_good += REG_READ(ah, AR_RTS_OK);
+ stats->beacons += REG_READ(ah, AR_BEACON_CNT);
+}
+
+static void ath9k_ani_restart(struct ath_hw *ah)
+{
+ struct ar5416AniState *aniState;
+ u32 ofdm_base = 0, cck_base = 0;
+
+ if (!DO_ANI(ah))
+ return;
+
+ aniState = &ah->curchan->ani;
+ aniState->listenTime = 0;
+
+ if (!use_new_ani(ah)) {
+ ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
+ cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
+ }
+
+ DBG2("ath9k: "
+ "Writing ofdmbase=%d cckbase=%d\n", ofdm_base, cck_base);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
+ REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+
+ aniState->ofdmPhyErrCount = 0;
+ aniState->cckPhyErrCount = 0;
+}
+
+static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
+{
+ struct ar5416AniState *aniState;
+ int32_t rssi;
+
+ aniState = &ah->curchan->ani;
+
+ if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+ aniState->noiseImmunityLevel + 1)) {
+ return;
+ }
+ }
+
+ if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+ aniState->spurImmunityLevel + 1)) {
+ return;
+ }
+ }
+
+ rssi = BEACON_RSSI(ah);
+ if (rssi > aniState->rssiThrHigh) {
+ if (!aniState->ofdmWeakSigDetectOff) {
+ if (ath9k_hw_ani_control(ah,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ 0)) {
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
+ return;
+ }
+ }
+ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
+ ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel + 1);
+ return;
+ }
+ } else if (rssi > aniState->rssiThrLow) {
+ if (aniState->ofdmWeakSigDetectOff)
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ 1);
+ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel + 1);
+ return;
+ } else {
+ if ((ah->dev->channels + ah->dev->channel)->band == NET80211_BAND_2GHZ) {
+ if (!aniState->ofdmWeakSigDetectOff)
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ 0);
+ if (aniState->firstepLevel > 0)
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL, 0);
+ return;
+ }
+ }
+}
+
+static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
+{
+ struct ar5416AniState *aniState;
+ int32_t rssi;
+
+ aniState = &ah->curchan->ani;
+ if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+ aniState->noiseImmunityLevel + 1)) {
+ return;
+ }
+ }
+ rssi = BEACON_RSSI(ah);
+ if (rssi > aniState->rssiThrLow) {
+ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel + 1);
+ } else {
+ if ((ah->dev->channels + ah->dev->channel)->band == NET80211_BAND_2GHZ) {
+ if (aniState->firstepLevel > 0)
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL, 0);
+ }
+ }
+}
+
+/* Adjust the OFDM Noise Immunity Level */
+static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
+{
+ struct ar5416AniState *aniState = &ah->curchan->ani;
+ const struct ani_ofdm_level_entry *entry_ofdm;
+ const struct ani_cck_level_entry *entry_cck;
+
+ aniState->noiseFloor = BEACON_RSSI(ah);
+
+ DBG2("ath9k: "
+ "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
+ aniState->ofdmNoiseImmunityLevel,
+ immunityLevel, aniState->noiseFloor,
+ aniState->rssiThrLow, aniState->rssiThrHigh);
+
+ aniState->ofdmNoiseImmunityLevel = immunityLevel;
+
+ entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
+ entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
+
+ if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level)
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+ entry_ofdm->spur_immunity_level);
+
+ if (aniState->firstepLevel != entry_ofdm->fir_step_level &&
+ entry_ofdm->fir_step_level >= entry_cck->fir_step_level)
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL,
+ entry_ofdm->fir_step_level);
+}
+
+static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
+{
+ struct ar5416AniState *aniState;
+
+ if (!DO_ANI(ah))
+ return;
+
+ if (!use_new_ani(ah)) {
+ ath9k_hw_ani_ofdm_err_trigger_old(ah);
+ return;
+ }
+
+ aniState = &ah->curchan->ani;
+
+ if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
+ ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
+}
+
+/*
+ * Set the ANI settings to match an CCK level.
+ */
+static void ath9k_hw_set_cck_nil(struct ath_hw *ah, uint8_t immunityLevel)
+{
+ struct ar5416AniState *aniState = &ah->curchan->ani;
+ const struct ani_ofdm_level_entry *entry_ofdm;
+ const struct ani_cck_level_entry *entry_cck;
+
+ aniState->noiseFloor = BEACON_RSSI(ah);
+ DBG2("ath9k: "
+ "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
+ aniState->cckNoiseImmunityLevel, immunityLevel,
+ aniState->noiseFloor, aniState->rssiThrLow,
+ aniState->rssiThrHigh);
+
+ if (aniState->noiseFloor <= (unsigned int)aniState->rssiThrLow &&
+ immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
+ immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
+
+ aniState->cckNoiseImmunityLevel = immunityLevel;
+
+ entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
+ entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
+
+ if (aniState->firstepLevel != entry_cck->fir_step_level &&
+ entry_cck->fir_step_level >= entry_ofdm->fir_step_level)
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL,
+ entry_cck->fir_step_level);
+
+ /* Skip MRC CCK for pre AR9003 families */
+ if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah))
+ return;
+
+ if (aniState->mrcCCKOff == entry_cck->mrc_cck_on)
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_MRC_CCK,
+ entry_cck->mrc_cck_on);
+}
+
+static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
+{
+ struct ar5416AniState *aniState;
+
+ if (!DO_ANI(ah))
+ return;
+
+ if (!use_new_ani(ah)) {
+ ath9k_hw_ani_cck_err_trigger_old(ah);
+ return;
+ }
+
+ aniState = &ah->curchan->ani;
+
+ if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
+ ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
+}
+
+static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
+{
+ struct ar5416AniState *aniState;
+ int32_t rssi;
+
+ aniState = &ah->curchan->ani;
+
+ rssi = BEACON_RSSI(ah);
+ if (rssi > aniState->rssiThrHigh) {
+ /* XXX: Handle me */
+ } else if (rssi > aniState->rssiThrLow) {
+ if (aniState->ofdmWeakSigDetectOff) {
+ if (ath9k_hw_ani_control(ah,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ 1) == 1)
+ return;
+ }
+ if (aniState->firstepLevel > 0) {
+ if (ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel - 1) == 1)
+ return;
+ }
+ } else {
+ if (aniState->firstepLevel > 0) {
+ if (ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel - 1) == 1)
+ return;
+ }
+ }
+
+ if (aniState->spurImmunityLevel > 0) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+ aniState->spurImmunityLevel - 1))
+ return;
+ }
+
+ if (aniState->noiseImmunityLevel > 0) {
+ ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+ aniState->noiseImmunityLevel - 1);
+ return;
+ }
+}
+
+/*
+ * only lower either OFDM or CCK errors per turn
+ * we lower the other one next time
+ */
+static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
+{
+ struct ar5416AniState *aniState;
+
+ aniState = &ah->curchan->ani;
+
+ if (!use_new_ani(ah)) {
+ ath9k_hw_ani_lower_immunity_old(ah);
+ return;
+ }
+
+ /* lower OFDM noise immunity */
+ if (aniState->ofdmNoiseImmunityLevel > 0 &&
+ (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
+ ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1);
+ return;
+ }
+
+ /* lower CCK noise immunity */
+ if (aniState->cckNoiseImmunityLevel > 0)
+ ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
+}
+
+static void ath9k_ani_reset_old(struct ath_hw *ah)
+{
+ struct ar5416AniState *aniState;
+
+ if (!DO_ANI(ah))
+ return;
+
+ aniState = &ah->curchan->ani;
+
+ if (aniState->noiseImmunityLevel != 0)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+ aniState->noiseImmunityLevel);
+ if (aniState->spurImmunityLevel != 0)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+ aniState->spurImmunityLevel);
+ if (aniState->ofdmWeakSigDetectOff)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ !aniState->ofdmWeakSigDetectOff);
+ if (aniState->cckWeakSigThreshold)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
+ aniState->cckWeakSigThreshold);
+ if (aniState->firstepLevel != 0)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel);
+
+ ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
+ ~ATH9K_RX_FILTER_PHYERR);
+ ath9k_ani_restart(ah);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+}
+
+/*
+ * Restore the ANI parameters in the HAL and reset the statistics.
+ * This routine should be called for every hardware reset and for
+ * every channel change.
+ */
+void ath9k_ani_reset(struct ath_hw *ah, int is_scanning)
+{
+ struct ar5416AniState *aniState = &ah->curchan->ani;
+ struct ath9k_channel *chan = ah->curchan;
+
+ if (!DO_ANI(ah))
+ return;
+
+ if (!use_new_ani(ah))
+ return ath9k_ani_reset_old(ah);
+
+ ah->stats.ast_ani_reset++;
+
+ /* always allow mode (on/off) to be controlled */
+ ah->ani_function |= ATH9K_ANI_MODE;
+
+ if (is_scanning) {
+ /*
+ * If we're scanning or in AP mode, the defaults (ini)
+ * should be in place. For an AP we assume the historical
+ * levels for this channel are probably outdated so start
+ * from defaults instead.
+ */
+ if (aniState->ofdmNoiseImmunityLevel !=
+ ATH9K_ANI_OFDM_DEF_LEVEL ||
+ aniState->cckNoiseImmunityLevel !=
+ ATH9K_ANI_CCK_DEF_LEVEL) {
+ DBG("ath9k: "
+ "Restore defaults: chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
+ chan->channel,
+ chan->channelFlags,
+ is_scanning,
+ aniState->ofdmNoiseImmunityLevel,
+ aniState->cckNoiseImmunityLevel);
+
+ ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
+ ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
+ }
+ } else {
+ /*
+ * restore historical levels for this channel
+ */
+ DBG2("ath9k: "
+ "Restore history: chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
+ chan->channel,
+ chan->channelFlags,
+ is_scanning,
+ aniState->ofdmNoiseImmunityLevel,
+ aniState->cckNoiseImmunityLevel);
+
+ ath9k_hw_set_ofdm_nil(ah,
+ aniState->ofdmNoiseImmunityLevel);
+ ath9k_hw_set_cck_nil(ah,
+ aniState->cckNoiseImmunityLevel);
+ }
+
+ /*
+ * enable phy counters if hw supports or if not, enable phy
+ * interrupts (so we can count each one)
+ */
+ ath9k_ani_restart(ah);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+}
+
+static int ath9k_hw_ani_read_counters(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ar5416AniState *aniState = &ah->curchan->ani;
+ u32 ofdm_base = 0;
+ u32 cck_base = 0;
+ u32 ofdmPhyErrCnt, cckPhyErrCnt;
+ u32 phyCnt1, phyCnt2;
+ int32_t listenTime;
+
+ ath_hw_cycle_counters_update(common);
+ listenTime = ath_hw_get_listen_time(common);
+
+ if (listenTime <= 0) {
+ ah->stats.ast_ani_lneg++;
+ ath9k_ani_restart(ah);
+ return 0;
+ }
+
+ if (!use_new_ani(ah)) {
+ ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
+ cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
+ }
+
+ aniState->listenTime += listenTime;
+
+ phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
+ phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
+
+ if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
+ if (phyCnt1 < ofdm_base) {
+ DBG2("ath9k: "
+ "phyCnt1 0x%x, resetting counter value to 0x%x\n",
+ phyCnt1, ofdm_base);
+ REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1,
+ AR_PHY_ERR_OFDM_TIMING);
+ }
+ if (phyCnt2 < cck_base) {
+ DBG2("ath9k: "
+ "phyCnt2 0x%x, resetting counter value to 0x%x\n",
+ phyCnt2, cck_base);
+ REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2,
+ AR_PHY_ERR_CCK_TIMING);
+ }
+ return 0;
+ }
+
+ ofdmPhyErrCnt = phyCnt1 - ofdm_base;
+ ah->stats.ast_ani_ofdmerrs +=
+ ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+ aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+ cckPhyErrCnt = phyCnt2 - cck_base;
+ ah->stats.ast_ani_cckerrs +=
+ cckPhyErrCnt - aniState->cckPhyErrCount;
+ aniState->cckPhyErrCount = cckPhyErrCnt;
+ return 1;
+}
+
+void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan __unused)
+{
+ struct ar5416AniState *aniState;
+ u32 ofdmPhyErrRate, cckPhyErrRate;
+
+ if (!DO_ANI(ah))
+ return;
+
+ aniState = &ah->curchan->ani;
+ if (!aniState)
+ return;
+
+ if (!ath9k_hw_ani_read_counters(ah))
+ return;
+
+ ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
+ aniState->listenTime;
+ cckPhyErrRate = aniState->cckPhyErrCount * 1000 /
+ aniState->listenTime;
+
+ DBG2("ath9k: "
+ "listenTime=%d OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n",
+ aniState->listenTime,
+ aniState->ofdmNoiseImmunityLevel,
+ ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
+ cckPhyErrRate, aniState->ofdmsTurn);
+
+ if (aniState->listenTime > 5 * ah->aniperiod) {
+ if (ofdmPhyErrRate <= ah->config.ofdm_trig_low &&
+ cckPhyErrRate <= ah->config.cck_trig_low) {
+ ath9k_hw_ani_lower_immunity(ah);
+ aniState->ofdmsTurn = !aniState->ofdmsTurn;
+ }
+ ath9k_ani_restart(ah);
+ } else if (aniState->listenTime > ah->aniperiod) {
+ /* check to see if need to raise immunity */
+ if (ofdmPhyErrRate > ah->config.ofdm_trig_high &&
+ (cckPhyErrRate <= ah->config.cck_trig_high ||
+ aniState->ofdmsTurn)) {
+ ath9k_hw_ani_ofdm_err_trigger(ah);
+ ath9k_ani_restart(ah);
+ aniState->ofdmsTurn = 0;
+ } else if (cckPhyErrRate > ah->config.cck_trig_high) {
+ ath9k_hw_ani_cck_err_trigger(ah);
+ ath9k_ani_restart(ah);
+ aniState->ofdmsTurn = 1;
+ }
+ }
+}
+
+void ath9k_hw_ani_setup(struct ath_hw *ah)
+{
+ int i;
+
+ static const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
+ static const int coarseHigh[] = { -14, -14, -14, -14, -12 };
+ static const int coarseLow[] = { -64, -64, -64, -64, -70 };
+ static const int firpwr[] = { -78, -78, -78, -78, -80 };
+
+ for (i = 0; i < 5; i++) {
+ ah->totalSizeDesired[i] = totalSizeDesired[i];
+ ah->coarse_high[i] = coarseHigh[i];
+ ah->coarse_low[i] = coarseLow[i];
+ ah->firpwr[i] = firpwr[i];
+ }
+}
+
+void ath9k_hw_ani_init(struct ath_hw *ah)
+{
+ unsigned int i;
+
+ DBG2("ath9k: Initialize ANI\n");
+
+ if (use_new_ani(ah)) {
+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
+
+ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
+ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW;
+ } else {
+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
+
+ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
+ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(ah->channels); i++) {
+ struct ath9k_channel *chan = &ah->channels[i];
+ struct ar5416AniState *ani = &chan->ani;
+
+ if (use_new_ani(ah)) {
+ ani->spurImmunityLevel =
+ ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
+
+ ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
+
+ if (AR_SREV_9300_20_OR_LATER(ah))
+ ani->mrcCCKOff =
+ !ATH9K_ANI_ENABLE_MRC_CCK;
+ else
+ ani->mrcCCKOff = 1;
+
+ ani->ofdmsTurn = 1;
+ } else {
+ ani->spurImmunityLevel =
+ ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
+ ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
+
+ ani->cckWeakSigThreshold =
+ ATH9K_ANI_CCK_WEAK_SIG_THR;
+ }
+
+ ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
+ ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
+ ani->ofdmWeakSigDetectOff =
+ !ATH9K_ANI_USE_OFDM_WEAK_SIG;
+ ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
+ }
+
+ /*
+ * since we expect some ongoing maintenance on the tables, let's sanity
+ * check here default level should not modify INI setting.
+ */
+ if (use_new_ani(ah)) {
+ ah->aniperiod = ATH9K_ANI_PERIOD_NEW;
+ ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW;
+ } else {
+ ah->aniperiod = ATH9K_ANI_PERIOD_OLD;
+ ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
+ }
+
+ if (ah->config.enable_ani)
+ ah->proc_phyerr |= HAL_PROCESS_ANI;
+
+ ath9k_ani_restart(ah);
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar5008_phy.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar5008_phy.c
new file mode 100644
index 00000000..60e87e9e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar5008_phy.c
@@ -0,0 +1,1663 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/malloc.h>
+#include <ipxe/io.h>
+
+#include "hw.h"
+#include "hw-ops.h"
+#include "../regd.h"
+#include "ar9002_phy.h"
+
+/* All code below is for AR5008, AR9001, AR9002 */
+
+static const int firstep_table[] =
+/* level: 0 1 2 3 4 5 6 7 8 */
+ { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */
+
+static const int cycpwrThr1_table[] =
+/* level: 0 1 2 3 4 5 6 7 8 */
+ { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */
+
+/*
+ * register values to turn OFDM weak signal detection OFF
+ */
+static const int m1ThreshLow_off = 127;
+static const int m2ThreshLow_off = 127;
+static const int m1Thresh_off = 127;
+static const int m2Thresh_off = 127;
+static const int m2CountThr_off = 31;
+static const int m2CountThrLow_off = 63;
+static const int m1ThreshLowExt_off = 127;
+static const int m2ThreshLowExt_off = 127;
+static const int m1ThreshExt_off = 127;
+static const int m2ThreshExt_off = 127;
+
+
+static void ar5008_rf_bank_setup(u32 *bank, struct ar5416IniArray *array,
+ int col)
+{
+ unsigned int i;
+
+ for (i = 0; i < array->ia_rows; i++)
+ bank[i] = INI_RA(array, i, col);
+}
+
+
+#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) \
+ ar5008_write_rf_array(ah, iniarray, regData, &(regWr))
+
+static void ar5008_write_rf_array(struct ath_hw *ah, struct ar5416IniArray *array,
+ u32 *data, unsigned int *writecnt)
+{
+ unsigned int r;
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ for (r = 0; r < array->ia_rows; r++) {
+ REG_WRITE(ah, INI_RA(array, r, 0), data[r]);
+ DO_DELAY(*writecnt);
+ }
+
+ REGWRITE_BUFFER_FLUSH(ah);
+}
+
+/**
+ * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters
+ * @rfbuf:
+ * @reg32:
+ * @numBits:
+ * @firstBit:
+ * @column:
+ *
+ * Performs analog "swizzling" of parameters into their location.
+ * Used on external AR2133/AR5133 radios.
+ */
+static void ar5008_hw_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32,
+ u32 numBits, u32 firstBit,
+ u32 column)
+{
+ u32 tmp32, mask, arrayEntry, lastBit;
+ int32_t bitPosition, bitsLeft;
+
+ tmp32 = ath9k_hw_reverse_bits(reg32, numBits);
+ arrayEntry = (firstBit - 1) / 8;
+ bitPosition = (firstBit - 1) % 8;
+ bitsLeft = numBits;
+ while (bitsLeft > 0) {
+ lastBit = (bitPosition + bitsLeft > 8) ?
+ 8 : bitPosition + bitsLeft;
+ mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<
+ (column * 8);
+ rfBuf[arrayEntry] &= ~mask;
+ rfBuf[arrayEntry] |= ((tmp32 << bitPosition) <<
+ (column * 8)) & mask;
+ bitsLeft -= 8 - bitPosition;
+ tmp32 = tmp32 >> (8 - bitPosition);
+ bitPosition = 0;
+ arrayEntry++;
+ }
+}
+
+/*
+ * Fix on 2.4 GHz band for orientation sensitivity issue by increasing
+ * rf_pwd_icsyndiv.
+ *
+ * Theoretical Rules:
+ * if 2 GHz band
+ * if forceBiasAuto
+ * if synth_freq < 2412
+ * bias = 0
+ * else if 2412 <= synth_freq <= 2422
+ * bias = 1
+ * else // synth_freq > 2422
+ * bias = 2
+ * else if forceBias > 0
+ * bias = forceBias & 7
+ * else
+ * no change, use value from ini file
+ * else
+ * no change, invalid band
+ *
+ * 1st Mod:
+ * 2422 also uses value of 2
+ * <approved>
+ *
+ * 2nd Mod:
+ * Less than 2412 uses value of 0, 2412 and above uses value of 2
+ */
+static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq)
+{
+ u32 tmp_reg;
+ unsigned int reg_writes = 0;
+ u32 new_bias = 0;
+
+ if (!AR_SREV_5416(ah) || synth_freq >= 3000)
+ return;
+
+ if (synth_freq < 2412)
+ new_bias = 0;
+ else if (synth_freq < 2422)
+ new_bias = 1;
+ else
+ new_bias = 2;
+
+ /* pre-reverse this field */
+ tmp_reg = ath9k_hw_reverse_bits(new_bias, 3);
+
+ DBG("ath9k: Force rf_pwd_icsyndiv to %1d on %4d\n",
+ new_bias, synth_freq);
+
+ /* swizzle rf_pwd_icsyndiv */
+ ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3);
+
+ /* write Bank 6 with new params */
+ REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes);
+}
+
+/**
+ * ar5008_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * For the external AR2133/AR5133 radios, takes the MHz channel value and set
+ * the channel value. Assumes writes enabled to analog bus and bank6 register
+ * cache in ah->analogBank6Data.
+ */
+static int ar5008_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ u32 channelSel = 0;
+ u32 bModeSynth = 0;
+ u32 aModeRefSel = 0;
+ u32 reg32 = 0;
+ u16 freq;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ freq = centers.synth_center;
+
+ if (freq < 4800) {
+ u32 txctl;
+
+ if (((freq - 2192) % 5) == 0) {
+ channelSel = ((freq - 672) * 2 - 3040) / 10;
+ bModeSynth = 0;
+ } else if (((freq - 2224) % 5) == 0) {
+ channelSel = ((freq - 704) * 2 - 3040) / 10;
+ bModeSynth = 1;
+ } else {
+ DBG("ath9k: Invalid channel %d MHz\n", freq);
+ return -EINVAL;
+ }
+
+ channelSel = (channelSel << 2) & 0xff;
+ channelSel = ath9k_hw_reverse_bits(channelSel, 8);
+
+ txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+ if (freq == 2484) {
+
+ REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+ txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+ } else {
+ REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+ txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
+ }
+
+ } else if ((freq % 20) == 0 && freq >= 5120) {
+ channelSel =
+ ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8);
+ aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+ } else if ((freq % 10) == 0) {
+ channelSel =
+ ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8);
+ if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
+ aModeRefSel = ath9k_hw_reverse_bits(2, 2);
+ else
+ aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+ } else if ((freq % 5) == 0) {
+ channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
+ aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+ } else {
+ DBG("ath9k: Invalid channel %d MHz\n", freq);
+ return -EINVAL;
+ }
+
+ ar5008_hw_force_bias(ah, freq);
+
+ reg32 =
+ (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
+ (1 << 5) | 0x1;
+
+ REG_WRITE(ah, AR_PHY(0x37), reg32);
+
+ ah->curchan = chan;
+ ah->curchan_rad_index = -1;
+
+ return 0;
+}
+
+/**
+ * ar5008_hw_spur_mitigate - convert baseband spur frequency for external radios
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * For non single-chip solutions. Converts to baseband spur frequency given the
+ * input channel frequency and compute register settings below.
+ */
+static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ int bb_spur = AR_NO_SPUR;
+ int bin, cur_bin;
+ int spur_freq_sd;
+ int spur_delta_phase;
+ int denominator;
+ int upper, lower, cur_vit_mask;
+ int tmp, new;
+ int i;
+ static int pilot_mask_reg[4] = {
+ AR_PHY_TIMING7, AR_PHY_TIMING8,
+ AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
+ };
+ static int chan_mask_reg[4] = {
+ AR_PHY_TIMING9, AR_PHY_TIMING10,
+ AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
+ };
+ static int inc[4] = { 0, 100, 0, 0 };
+
+ int8_t mask_m[123];
+ int8_t mask_p[123];
+ int8_t mask_amt;
+ int tmp_mask;
+ int cur_bb_spur;
+ int is2GHz = IS_CHAN_2GHZ(chan);
+
+ memset(&mask_m, 0, sizeof(int8_t) * 123);
+ memset(&mask_p, 0, sizeof(int8_t) * 123);
+
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
+ if (AR_NO_SPUR == cur_bb_spur)
+ break;
+ cur_bb_spur = cur_bb_spur - (chan->channel * 10);
+ if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
+ bb_spur = cur_bb_spur;
+ break;
+ }
+ }
+
+ if (AR_NO_SPUR == bb_spur)
+ return;
+
+ bin = bb_spur * 32;
+
+ tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
+ new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+ AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+ AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+ AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new);
+
+ new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+ AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+ AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+ AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+ SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+ REG_WRITE(ah, AR_PHY_SPUR_REG, new);
+
+ spur_delta_phase = ((bb_spur * 524288) / 100) &
+ AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+
+ denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
+ spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
+
+ new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+ SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+ SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+ REG_WRITE(ah, AR_PHY_TIMING11, new);
+
+ cur_bin = -6000;
+ upper = bin + 100;
+ lower = bin - 100;
+
+ for (i = 0; i < 4; i++) {
+ int pilot_mask = 0;
+ int chan_mask = 0;
+ int bp = 0;
+ for (bp = 0; bp < 30; bp++) {
+ if ((cur_bin > lower) && (cur_bin < upper)) {
+ pilot_mask = pilot_mask | 0x1 << bp;
+ chan_mask = chan_mask | 0x1 << bp;
+ }
+ cur_bin += 100;
+ }
+ cur_bin += inc[i];
+ REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+ REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+ }
+
+ cur_vit_mask = 6100;
+ upper = bin + 120;
+ lower = bin - 120;
+
+ for (i = 0; i < 123; i++) {
+ if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+
+ /* workaround for gcc bug #37014 */
+ volatile int tmp_v = abs(cur_vit_mask - bin);
+
+ if (tmp_v < 75)
+ mask_amt = 1;
+ else
+ mask_amt = 0;
+ if (cur_vit_mask < 0)
+ mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+ else
+ mask_p[cur_vit_mask / 100] = mask_amt;
+ }
+ cur_vit_mask -= 100;
+ }
+
+ tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
+ | (mask_m[48] << 26) | (mask_m[49] << 24)
+ | (mask_m[50] << 22) | (mask_m[51] << 20)
+ | (mask_m[52] << 18) | (mask_m[53] << 16)
+ | (mask_m[54] << 14) | (mask_m[55] << 12)
+ | (mask_m[56] << 10) | (mask_m[57] << 8)
+ | (mask_m[58] << 6) | (mask_m[59] << 4)
+ | (mask_m[60] << 2) | (mask_m[61] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+ REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+ tmp_mask = (mask_m[31] << 28)
+ | (mask_m[32] << 26) | (mask_m[33] << 24)
+ | (mask_m[34] << 22) | (mask_m[35] << 20)
+ | (mask_m[36] << 18) | (mask_m[37] << 16)
+ | (mask_m[48] << 14) | (mask_m[39] << 12)
+ | (mask_m[40] << 10) | (mask_m[41] << 8)
+ | (mask_m[42] << 6) | (mask_m[43] << 4)
+ | (mask_m[44] << 2) | (mask_m[45] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+ tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
+ | (mask_m[18] << 26) | (mask_m[18] << 24)
+ | (mask_m[20] << 22) | (mask_m[20] << 20)
+ | (mask_m[22] << 18) | (mask_m[22] << 16)
+ | (mask_m[24] << 14) | (mask_m[24] << 12)
+ | (mask_m[25] << 10) | (mask_m[26] << 8)
+ | (mask_m[27] << 6) | (mask_m[28] << 4)
+ | (mask_m[29] << 2) | (mask_m[30] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+ tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
+ | (mask_m[2] << 26) | (mask_m[3] << 24)
+ | (mask_m[4] << 22) | (mask_m[5] << 20)
+ | (mask_m[6] << 18) | (mask_m[7] << 16)
+ | (mask_m[8] << 14) | (mask_m[9] << 12)
+ | (mask_m[10] << 10) | (mask_m[11] << 8)
+ | (mask_m[12] << 6) | (mask_m[13] << 4)
+ | (mask_m[14] << 2) | (mask_m[15] << 0);
+ REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+ tmp_mask = (mask_p[15] << 28)
+ | (mask_p[14] << 26) | (mask_p[13] << 24)
+ | (mask_p[12] << 22) | (mask_p[11] << 20)
+ | (mask_p[10] << 18) | (mask_p[9] << 16)
+ | (mask_p[8] << 14) | (mask_p[7] << 12)
+ | (mask_p[6] << 10) | (mask_p[5] << 8)
+ | (mask_p[4] << 6) | (mask_p[3] << 4)
+ | (mask_p[2] << 2) | (mask_p[1] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+ tmp_mask = (mask_p[30] << 28)
+ | (mask_p[29] << 26) | (mask_p[28] << 24)
+ | (mask_p[27] << 22) | (mask_p[26] << 20)
+ | (mask_p[25] << 18) | (mask_p[24] << 16)
+ | (mask_p[23] << 14) | (mask_p[22] << 12)
+ | (mask_p[21] << 10) | (mask_p[20] << 8)
+ | (mask_p[19] << 6) | (mask_p[18] << 4)
+ | (mask_p[17] << 2) | (mask_p[16] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+ tmp_mask = (mask_p[45] << 28)
+ | (mask_p[44] << 26) | (mask_p[43] << 24)
+ | (mask_p[42] << 22) | (mask_p[41] << 20)
+ | (mask_p[40] << 18) | (mask_p[39] << 16)
+ | (mask_p[38] << 14) | (mask_p[37] << 12)
+ | (mask_p[36] << 10) | (mask_p[35] << 8)
+ | (mask_p[34] << 6) | (mask_p[33] << 4)
+ | (mask_p[32] << 2) | (mask_p[31] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+ tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
+ | (mask_p[59] << 26) | (mask_p[58] << 24)
+ | (mask_p[57] << 22) | (mask_p[56] << 20)
+ | (mask_p[55] << 18) | (mask_p[54] << 16)
+ | (mask_p[53] << 14) | (mask_p[52] << 12)
+ | (mask_p[51] << 10) | (mask_p[50] << 8)
+ | (mask_p[49] << 6) | (mask_p[48] << 4)
+ | (mask_p[47] << 2) | (mask_p[46] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+}
+
+/**
+ * ar5008_hw_rf_alloc_ext_banks - allocates banks for external radio programming
+ * @ah: atheros hardware structure
+ *
+ * Only required for older devices with external AR2133/AR5133 radios.
+ */
+static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)
+{
+#define ATH_ALLOC_BANK(bank, size) do { \
+ bank = zalloc((sizeof(u32) * size)); \
+ if (!bank) { \
+ DBG("ath9k: Cannot allocate RF banks\n"); \
+ return -ENOMEM; \
+ } \
+ } while (0);
+
+ ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows);
+ ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows);
+ ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows);
+ ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows);
+ ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows);
+ ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows);
+ ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows);
+ ATH_ALLOC_BANK(ah->addac5416_21,
+ ah->iniAddac.ia_rows * ah->iniAddac.ia_columns);
+ ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows);
+
+ return 0;
+#undef ATH_ALLOC_BANK
+}
+
+
+/**
+ * ar5008_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers
+ * @ah: atheros hardware struture
+ * For the external AR2133/AR5133 radios banks.
+ */
+static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah)
+{
+#define ATH_FREE_BANK(bank) do { \
+ free(bank); \
+ bank = NULL; \
+ } while (0);
+
+ ATH_FREE_BANK(ah->analogBank0Data);
+ ATH_FREE_BANK(ah->analogBank1Data);
+ ATH_FREE_BANK(ah->analogBank2Data);
+ ATH_FREE_BANK(ah->analogBank3Data);
+ ATH_FREE_BANK(ah->analogBank6Data);
+ ATH_FREE_BANK(ah->analogBank6TPCData);
+ ATH_FREE_BANK(ah->analogBank7Data);
+ ATH_FREE_BANK(ah->addac5416_21);
+ ATH_FREE_BANK(ah->bank6Temp);
+
+#undef ATH_FREE_BANK
+}
+
+/* *
+ * ar5008_hw_set_rf_regs - programs rf registers based on EEPROM
+ * @ah: atheros hardware structure
+ * @chan:
+ * @modesIndex:
+ *
+ * Used for the external AR2133/AR5133 radios.
+ *
+ * Reads the EEPROM header info from the device structure and programs
+ * all rf registers. This routine requires access to the analog
+ * rf device. This is not required for single-chip devices.
+ */
+static int ar5008_hw_set_rf_regs(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u16 modesIndex)
+{
+ u32 eepMinorRev;
+ u32 ob5GHz = 0, db5GHz = 0;
+ u32 ob2GHz = 0, db2GHz = 0;
+ unsigned int regWrites = 0;
+
+ /*
+ * Software does not need to program bank data
+ * for single chip devices, that is AR9280 or anything
+ * after that.
+ */
+ if (AR_SREV_9280_20_OR_LATER(ah))
+ return 1;
+
+ /* Setup rf parameters */
+ eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV);
+
+ /* Setup Bank 0 Write */
+ ar5008_rf_bank_setup(ah->analogBank0Data, &ah->iniBank0, 1);
+
+ /* Setup Bank 1 Write */
+ ar5008_rf_bank_setup(ah->analogBank1Data, &ah->iniBank1, 1);
+
+ /* Setup Bank 2 Write */
+ ar5008_rf_bank_setup(ah->analogBank2Data, &ah->iniBank2, 1);
+
+ /* Setup Bank 6 Write */
+ ar5008_rf_bank_setup(ah->analogBank3Data, &ah->iniBank3,
+ modesIndex);
+ {
+ unsigned int i;
+ for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) {
+ ah->analogBank6Data[i] =
+ INI_RA(&ah->iniBank6TPC, i, modesIndex);
+ }
+ }
+
+ /* Only the 5 or 2 GHz OB/DB need to be set for a mode */
+ if (eepMinorRev >= 2) {
+ if (IS_CHAN_2GHZ(chan)) {
+ ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2);
+ db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2);
+ ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data,
+ ob2GHz, 3, 197, 0);
+ ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data,
+ db2GHz, 3, 194, 0);
+ } else {
+ ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5);
+ db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5);
+ ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data,
+ ob5GHz, 3, 203, 0);
+ ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data,
+ db5GHz, 3, 200, 0);
+ }
+ }
+
+ /* Setup Bank 7 Setup */
+ ar5008_rf_bank_setup(ah->analogBank7Data, &ah->iniBank7, 1);
+
+ /* Write Analog registers */
+ REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data,
+ regWrites);
+ REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data,
+ regWrites);
+ REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data,
+ regWrites);
+ REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data,
+ regWrites);
+ REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data,
+ regWrites);
+ REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data,
+ regWrites);
+
+ return 1;
+}
+
+static void ar5008_hw_init_bb(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ u32 synthDelay;
+
+ synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+ if (IS_CHAN_B(chan))
+ synthDelay = (4 * synthDelay) / 22;
+ else
+ synthDelay /= 10;
+
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+ udelay(synthDelay + BASE_ACTIVATE_DELAY);
+}
+
+static void ar5008_hw_init_chain_masks(struct ath_hw *ah)
+{
+ int rx_chainmask, tx_chainmask;
+
+ rx_chainmask = ah->rxchainmask;
+ tx_chainmask = ah->txchainmask;
+
+
+ switch (rx_chainmask) {
+ case 0x5:
+ REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+ AR_PHY_SWAP_ALT_CHAIN);
+ case 0x3:
+ if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) {
+ REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
+ REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
+ break;
+ }
+ case 0x1:
+ case 0x2:
+ case 0x7:
+ ENABLE_REGWRITE_BUFFER(ah);
+ REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
+ REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
+ break;
+ default:
+ ENABLE_REGWRITE_BUFFER(ah);
+ break;
+ }
+
+ REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ if (tx_chainmask == 0x5) {
+ REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+ AR_PHY_SWAP_ALT_CHAIN);
+ }
+ if (AR_SREV_9100(ah))
+ REG_WRITE(ah, AR_PHY_ANALOG_SWAP,
+ REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);
+}
+
+static void ar5008_hw_override_ini(struct ath_hw *ah,
+ struct ath9k_channel *chan __unused)
+{
+ u32 val;
+
+ /*
+ * Set the RX_ABORT and RX_DIS and clear if off only after
+ * RXE is set for MAC. This prevents frames with corrupted
+ * descriptor status.
+ */
+ REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ val = REG_READ(ah, AR_PCU_MISC_MODE2);
+
+ if (!AR_SREV_9271(ah))
+ val &= ~AR_PCU_MISC_MODE2_HWWAR1;
+
+ if (AR_SREV_9287_11_OR_LATER(ah))
+ val = val & (~AR_PCU_MISC_MODE2_HWWAR2);
+
+ REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
+ }
+
+ if (!AR_SREV_5416_20_OR_LATER(ah) ||
+ AR_SREV_9280_20_OR_LATER(ah))
+ return;
+ /*
+ * Disable BB clock gating
+ * Necessary to avoid issues on AR5416 2.0
+ */
+ REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
+
+ /*
+ * Disable RIFS search on some chips to avoid baseband
+ * hang issues.
+ */
+ if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) {
+ val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS);
+ val &= ~AR_PHY_RIFS_INIT_DELAY;
+ REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val);
+ }
+}
+
+static void ar5008_hw_set_channel_regs(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ u32 phymode;
+ u32 enableDacFifo = 0;
+
+ if (AR_SREV_9285_12_OR_LATER(ah))
+ enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
+ AR_PHY_FC_ENABLE_DAC_FIFO);
+
+ phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
+ | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo;
+
+ if (IS_CHAN_HT40(chan)) {
+ phymode |= AR_PHY_FC_DYN2040_EN;
+
+ if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+ (chan->chanmode == CHANNEL_G_HT40PLUS))
+ phymode |= AR_PHY_FC_DYN2040_PRI_CH;
+
+ }
+ REG_WRITE(ah, AR_PHY_TURBO, phymode);
+
+ ath9k_hw_set11nmac2040(ah);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
+ REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+}
+
+
+static int ar5008_hw_process_ini(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ath_common *common = ath9k_hw_common(ah);
+ unsigned int i, regWrites = 0;
+ struct net80211_channel *channel = chan->chan;
+ u32 modesIndex, freqIndex;
+
+ switch (chan->chanmode) {
+ case CHANNEL_A:
+ case CHANNEL_A_HT20:
+ modesIndex = 1;
+ freqIndex = 1;
+ break;
+ case CHANNEL_A_HT40PLUS:
+ case CHANNEL_A_HT40MINUS:
+ modesIndex = 2;
+ freqIndex = 1;
+ break;
+ case CHANNEL_G:
+ case CHANNEL_G_HT20:
+ case CHANNEL_B:
+ modesIndex = 4;
+ freqIndex = 2;
+ break;
+ case CHANNEL_G_HT40PLUS:
+ case CHANNEL_G_HT40MINUS:
+ modesIndex = 3;
+ freqIndex = 2;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /*
+ * Set correct baseband to analog shift setting to
+ * access analog chips.
+ */
+ REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+ /* Write ADDAC shifts */
+ REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
+ ah->eep_ops->set_addac(ah, chan);
+
+ if (AR_SREV_5416_22_OR_LATER(ah)) {
+ REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
+ } else {
+ struct ar5416IniArray temp;
+ u32 addacSize =
+ sizeof(u32) * ah->iniAddac.ia_rows *
+ ah->iniAddac.ia_columns;
+
+ /* For AR5416 2.0/2.1 */
+ memcpy(ah->addac5416_21,
+ ah->iniAddac.ia_array, addacSize);
+
+ /* override CLKDRV value at [row, column] = [31, 1] */
+ (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0;
+
+ temp.ia_array = ah->addac5416_21;
+ temp.ia_columns = ah->iniAddac.ia_columns;
+ temp.ia_rows = ah->iniAddac.ia_rows;
+ REG_WRITE_ARRAY(&temp, 1, regWrites);
+ }
+
+ REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ for (i = 0; i < ah->iniModes.ia_rows; i++) {
+ u32 reg = INI_RA(&ah->iniModes, i, 0);
+ u32 val = INI_RA(&ah->iniModes, i, modesIndex);
+
+ if (reg == AR_AN_TOP2 && ah->need_an_top2_fixup)
+ val &= ~AR_AN_TOP2_PWDCLKIND;
+
+ REG_WRITE(ah, reg, val);
+
+ if (reg >= 0x7800 && reg < 0x78a0
+ && ah->config.analog_shiftreg
+ && (common->bus_ops->ath_bus_type != ATH_USB)) {
+ udelay(100);
+ }
+
+ DO_DELAY(regWrites);
+ }
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ if (AR_SREV_9280(ah) || AR_SREV_9287_11_OR_LATER(ah))
+ REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
+
+ if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) ||
+ AR_SREV_9287_11_OR_LATER(ah))
+ REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+
+ if (AR_SREV_9271_10(ah))
+ REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only,
+ modesIndex, regWrites);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ /* Write common array parameters */
+ for (i = 0; i < ah->iniCommon.ia_rows; i++) {
+ u32 reg = INI_RA(&ah->iniCommon, i, 0);
+ u32 val = INI_RA(&ah->iniCommon, i, 1);
+
+ REG_WRITE(ah, reg, val);
+
+ if (reg >= 0x7800 && reg < 0x78a0
+ && ah->config.analog_shiftreg
+ && (common->bus_ops->ath_bus_type != ATH_USB)) {
+ udelay(100);
+ }
+
+ DO_DELAY(regWrites);
+ }
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ if (AR_SREV_9271(ah)) {
+ if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1)
+ REG_WRITE_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
+ modesIndex, regWrites);
+ else
+ REG_WRITE_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
+ modesIndex, regWrites);
+ }
+
+ REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);
+
+ if (IS_CHAN_A_FAST_CLOCK(ah, chan)) {
+ REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex,
+ regWrites);
+ }
+
+ ar5008_hw_override_ini(ah, chan);
+ ar5008_hw_set_channel_regs(ah, chan);
+ ar5008_hw_init_chain_masks(ah);
+ ath9k_olc_init(ah);
+
+ /* Set TX power */
+ ah->eep_ops->set_txpower(ah, chan,
+ ath9k_regd_get_ctl(regulatory, chan),
+ 0,
+ channel->maxpower * 2,
+ min((u32) MAX_RATE_POWER,
+ (u32) regulatory->power_limit), 0);
+
+ /* Write analog registers */
+ if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
+ DBG("ath9k: ar5416SetRfRegs failed\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ u32 rfMode = 0;
+
+ if (chan == NULL)
+ return;
+
+ rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
+ ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
+
+ if (!AR_SREV_9280_20_OR_LATER(ah))
+ rfMode |= (IS_CHAN_5GHZ(chan)) ?
+ AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
+
+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+ rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
+
+ REG_WRITE(ah, AR_PHY_MODE, rfMode);
+}
+
+static void ar5008_hw_mark_phy_inactive(struct ath_hw *ah)
+{
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+}
+
+static void ar5008_hw_set_delta_slope(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ u32 coef_scaled, ds_coef_exp, ds_coef_man;
+ u32 clockMhzScaled = 0x64000000;
+ struct chan_centers centers;
+
+ if (IS_CHAN_HALF_RATE(chan))
+ clockMhzScaled = clockMhzScaled >> 1;
+ else if (IS_CHAN_QUARTER_RATE(chan))
+ clockMhzScaled = clockMhzScaled >> 2;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ coef_scaled = clockMhzScaled / centers.synth_center;
+
+ ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
+ &ds_coef_exp);
+
+ REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+ AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+ AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
+
+ coef_scaled = (9 * coef_scaled) / 10;
+
+ ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
+ &ds_coef_exp);
+
+ REG_RMW_FIELD(ah, AR_PHY_HALFGI,
+ AR_PHY_HALFGI_DSC_MAN, ds_coef_man);
+ REG_RMW_FIELD(ah, AR_PHY_HALFGI,
+ AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
+}
+
+static int ar5008_hw_rfbus_req(struct ath_hw *ah)
+{
+ REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
+ return ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
+ AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT);
+}
+
+static void ar5008_hw_rfbus_done(struct ath_hw *ah)
+{
+ u32 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+ if (IS_CHAN_B(ah->curchan))
+ synthDelay = (4 * synthDelay) / 22;
+ else
+ synthDelay /= 10;
+
+ udelay(synthDelay + BASE_ACTIVATE_DELAY);
+
+ REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+}
+
+static void ar5008_restore_chainmask(struct ath_hw *ah)
+{
+ int rx_chainmask = ah->rxchainmask;
+
+ if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {
+ REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
+ REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
+ }
+}
+
+static void ar5008_set_diversity(struct ath_hw *ah, int value)
+{
+ u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
+ if (value)
+ v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+ else
+ v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+ REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
+}
+
+static u32 ar9100_hw_compute_pll_control(struct ath_hw *ah __unused,
+ struct ath9k_channel *chan)
+{
+ if (chan && IS_CHAN_5GHZ(chan))
+ return 0x1450;
+ return 0x1458;
+}
+
+static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah __unused,
+ struct ath9k_channel *chan)
+{
+ u32 pll;
+
+ pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
+
+ if (chan && IS_CHAN_HALF_RATE(chan))
+ pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
+ else if (chan && IS_CHAN_QUARTER_RATE(chan))
+ pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
+
+ if (chan && IS_CHAN_5GHZ(chan))
+ pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
+ else
+ pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
+
+ return pll;
+}
+
+static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah __unused,
+ struct ath9k_channel *chan)
+{
+ u32 pll;
+
+ pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
+
+ if (chan && IS_CHAN_HALF_RATE(chan))
+ pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
+ else if (chan && IS_CHAN_QUARTER_RATE(chan))
+ pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
+
+ if (chan && IS_CHAN_5GHZ(chan))
+ pll |= SM(0xa, AR_RTC_PLL_DIV);
+ else
+ pll |= SM(0xb, AR_RTC_PLL_DIV);
+
+ return pll;
+}
+
+static int ar5008_hw_ani_control_old(struct ath_hw *ah,
+ enum ath9k_ani_cmd cmd,
+ int param)
+{
+ struct ar5416AniState *aniState = &ah->curchan->ani;
+
+ switch (cmd & ah->ani_function) {
+ case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
+ u32 level = param;
+
+ if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
+ DBG("ath9k: "
+ "level out of range (%d > %zd)\n",
+ level, ARRAY_SIZE(ah->totalSizeDesired));
+ return 0;
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+ AR_PHY_DESIRED_SZ_TOT_DES,
+ ah->totalSizeDesired[level]);
+ REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+ AR_PHY_AGC_CTL1_COARSE_LOW,
+ ah->coarse_low[level]);
+ REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+ AR_PHY_AGC_CTL1_COARSE_HIGH,
+ ah->coarse_high[level]);
+ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+ AR_PHY_FIND_SIG_FIRPWR,
+ ah->firpwr[level]);
+
+ if (level > aniState->noiseImmunityLevel)
+ ah->stats.ast_ani_niup++;
+ else if (level < aniState->noiseImmunityLevel)
+ ah->stats.ast_ani_nidown++;
+ aniState->noiseImmunityLevel = level;
+ break;
+ }
+ case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
+ static const int m1ThreshLow[] = { 127, 50 };
+ static const int m2ThreshLow[] = { 127, 40 };
+ static const int m1Thresh[] = { 127, 0x4d };
+ static const int m2Thresh[] = { 127, 0x40 };
+ static const int m2CountThr[] = { 31, 16 };
+ static const int m2CountThrLow[] = { 63, 48 };
+ u32 on = param ? 1 : 0;
+
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+ m1ThreshLow[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+ m2ThreshLow[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M1_THRESH,
+ m1Thresh[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M2_THRESH,
+ m2Thresh[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M2COUNT_THR,
+ m2CountThr[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+ m2CountThrLow[on]);
+
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
+ m1ThreshLow[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
+ m2ThreshLow[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M1_THRESH,
+ m1Thresh[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M2_THRESH,
+ m2Thresh[on]);
+
+ if (on)
+ REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+ else
+ REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+
+ if (!on != aniState->ofdmWeakSigDetectOff) {
+ if (on)
+ ah->stats.ast_ani_ofdmon++;
+ else
+ ah->stats.ast_ani_ofdmoff++;
+ aniState->ofdmWeakSigDetectOff = !on;
+ }
+ break;
+ }
+ case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
+ static const int weakSigThrCck[] = { 8, 6 };
+ u32 high = param ? 1 : 0;
+
+ REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
+ AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
+ weakSigThrCck[high]);
+ if (high != aniState->cckWeakSigThreshold) {
+ if (high)
+ ah->stats.ast_ani_cckhigh++;
+ else
+ ah->stats.ast_ani_ccklow++;
+ aniState->cckWeakSigThreshold = high;
+ }
+ break;
+ }
+ case ATH9K_ANI_FIRSTEP_LEVEL:{
+ static const int firstep[] = { 0, 4, 8 };
+ u32 level = param;
+
+ if (level >= ARRAY_SIZE(firstep)) {
+ DBG("ath9k: "
+ "level out of range (%d > %zd)\n",
+ level, ARRAY_SIZE(firstep));
+ return 0;
+ }
+ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+ AR_PHY_FIND_SIG_FIRSTEP,
+ firstep[level]);
+ if (level > aniState->firstepLevel)
+ ah->stats.ast_ani_stepup++;
+ else if (level < aniState->firstepLevel)
+ ah->stats.ast_ani_stepdown++;
+ aniState->firstepLevel = level;
+ break;
+ }
+ case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
+ static const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
+ u32 level = param;
+
+ if (level >= ARRAY_SIZE(cycpwrThr1)) {
+ DBG("ath9k: "
+ "level out of range (%d > %zd)\n",
+ level, ARRAY_SIZE(cycpwrThr1));
+ return 0;
+ }
+ REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+ AR_PHY_TIMING5_CYCPWR_THR1,
+ cycpwrThr1[level]);
+ if (level > aniState->spurImmunityLevel)
+ ah->stats.ast_ani_spurup++;
+ else if (level < aniState->spurImmunityLevel)
+ ah->stats.ast_ani_spurdown++;
+ aniState->spurImmunityLevel = level;
+ break;
+ }
+ case ATH9K_ANI_PRESENT:
+ break;
+ default:
+ DBG("ath9k: invalid cmd %d\n", cmd);
+ return 0;
+ }
+
+ DBG2("ath9k: ANI parameters:\n");
+ DBG2(
+ "noiseImmunityLevel=%d, spurImmunityLevel=%d, ofdmWeakSigDetectOff=%d\n",
+ aniState->noiseImmunityLevel,
+ aniState->spurImmunityLevel,
+ !aniState->ofdmWeakSigDetectOff);
+ DBG2(
+ "cckWeakSigThreshold=%d, firstepLevel=%d, listenTime=%d\n",
+ aniState->cckWeakSigThreshold,
+ aniState->firstepLevel,
+ aniState->listenTime);
+ DBG2(
+ "ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
+ aniState->ofdmPhyErrCount,
+ aniState->cckPhyErrCount);
+
+ return 1;
+}
+
+static int ar5008_hw_ani_control_new(struct ath_hw *ah,
+ enum ath9k_ani_cmd cmd,
+ int param)
+{
+ struct ath9k_channel *chan = ah->curchan;
+ struct ar5416AniState *aniState = &chan->ani;
+ s32 value, value2;
+
+ switch (cmd & ah->ani_function) {
+ case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
+ /*
+ * on == 1 means ofdm weak signal detection is ON
+ * on == 1 is the default, for less noise immunity
+ *
+ * on == 0 means ofdm weak signal detection is OFF
+ * on == 0 means more noise imm
+ */
+ u32 on = param ? 1 : 0;
+ /*
+ * make register setting for default
+ * (weak sig detect ON) come from INI file
+ */
+ int m1ThreshLow = on ?
+ aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
+ int m2ThreshLow = on ?
+ aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
+ int m1Thresh = on ?
+ aniState->iniDef.m1Thresh : m1Thresh_off;
+ int m2Thresh = on ?
+ aniState->iniDef.m2Thresh : m2Thresh_off;
+ int m2CountThr = on ?
+ aniState->iniDef.m2CountThr : m2CountThr_off;
+ int m2CountThrLow = on ?
+ aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
+ int m1ThreshLowExt = on ?
+ aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
+ int m2ThreshLowExt = on ?
+ aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
+ int m1ThreshExt = on ?
+ aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
+ int m2ThreshExt = on ?
+ aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
+
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+ m1ThreshLow);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+ m2ThreshLow);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M1_THRESH, m1Thresh);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M2_THRESH, m2Thresh);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M2COUNT_THR, m2CountThr);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+ m2CountThrLow);
+
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt);
+
+ if (on)
+ REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+ else
+ REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+
+ if (!on != aniState->ofdmWeakSigDetectOff) {
+ DBG2("ath9k: "
+ "** ch %d: ofdm weak signal: %s=>%s\n",
+ chan->channel,
+ !aniState->ofdmWeakSigDetectOff ?
+ "on" : "off",
+ on ? "on" : "off");
+ if (on)
+ ah->stats.ast_ani_ofdmon++;
+ else
+ ah->stats.ast_ani_ofdmoff++;
+ aniState->ofdmWeakSigDetectOff = !on;
+ }
+ break;
+ }
+ case ATH9K_ANI_FIRSTEP_LEVEL:{
+ u32 level = param;
+
+ if (level >= ARRAY_SIZE(firstep_table)) {
+ DBG("ath9k: "
+ "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%d > %zd)\n",
+ level, ARRAY_SIZE(firstep_table));
+ return 0;
+ }
+
+ /*
+ * make register setting relative to default
+ * from INI file & cap value
+ */
+ value = firstep_table[level] -
+ firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
+ aniState->iniDef.firstep;
+ if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
+ value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
+ if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX)
+ value = ATH9K_SIG_FIRSTEP_SETTING_MAX;
+ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+ AR_PHY_FIND_SIG_FIRSTEP,
+ value);
+ /*
+ * we need to set first step low register too
+ * make register setting relative to default
+ * from INI file & cap value
+ */
+ value2 = firstep_table[level] -
+ firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
+ aniState->iniDef.firstepLow;
+ if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
+ value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
+ if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX)
+ value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX;
+
+ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
+ AR_PHY_FIND_SIG_FIRSTEP_LOW, value2);
+
+ if (level != aniState->firstepLevel) {
+ DBG2("ath9k: "
+ "** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n",
+ chan->channel,
+ aniState->firstepLevel,
+ level,
+ ATH9K_ANI_FIRSTEP_LVL_NEW,
+ value,
+ aniState->iniDef.firstep);
+ DBG2("ath9k: "
+ "** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n",
+ chan->channel,
+ aniState->firstepLevel,
+ level,
+ ATH9K_ANI_FIRSTEP_LVL_NEW,
+ value2,
+ aniState->iniDef.firstepLow);
+ if (level > aniState->firstepLevel)
+ ah->stats.ast_ani_stepup++;
+ else if (level < aniState->firstepLevel)
+ ah->stats.ast_ani_stepdown++;
+ aniState->firstepLevel = level;
+ }
+ break;
+ }
+ case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
+ u32 level = param;
+
+ if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
+ DBG("ath9k: "
+ "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%d > %zd)\n",
+ level, ARRAY_SIZE(cycpwrThr1_table));
+ return 0;
+ }
+ /*
+ * make register setting relative to default
+ * from INI file & cap value
+ */
+ value = cycpwrThr1_table[level] -
+ cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
+ aniState->iniDef.cycpwrThr1;
+ if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
+ value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
+ if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
+ value = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
+ REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+ AR_PHY_TIMING5_CYCPWR_THR1,
+ value);
+
+ /*
+ * set AR_PHY_EXT_CCA for extension channel
+ * make register setting relative to default
+ * from INI file & cap value
+ */
+ value2 = cycpwrThr1_table[level] -
+ cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
+ aniState->iniDef.cycpwrThr1Ext;
+ if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
+ value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
+ if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
+ value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+ AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2);
+
+ if (level != aniState->spurImmunityLevel) {
+ DBG2("ath9k: "
+ "** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n",
+ chan->channel,
+ aniState->spurImmunityLevel,
+ level,
+ ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
+ value,
+ aniState->iniDef.cycpwrThr1);
+ DBG2("ath9k: "
+ "** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n",
+ chan->channel,
+ aniState->spurImmunityLevel,
+ level,
+ ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
+ value2,
+ aniState->iniDef.cycpwrThr1Ext);
+ if (level > aniState->spurImmunityLevel)
+ ah->stats.ast_ani_spurup++;
+ else if (level < aniState->spurImmunityLevel)
+ ah->stats.ast_ani_spurdown++;
+ aniState->spurImmunityLevel = level;
+ }
+ break;
+ }
+ case ATH9K_ANI_MRC_CCK:
+ /*
+ * You should not see this as AR5008, AR9001, AR9002
+ * does not have hardware support for MRC CCK.
+ */
+ break;
+ case ATH9K_ANI_PRESENT:
+ break;
+ default:
+ DBG("ath9k: invalid cmd %d\n", cmd);
+ return 0;
+ }
+
+ DBG2("ath9k: "
+ "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
+ aniState->spurImmunityLevel,
+ !aniState->ofdmWeakSigDetectOff ? "on" : "off",
+ aniState->firstepLevel,
+ !aniState->mrcCCKOff ? "on" : "off",
+ aniState->listenTime,
+ aniState->ofdmPhyErrCount,
+ aniState->cckPhyErrCount);
+ return 1;
+}
+
+static void ar5008_hw_do_getnf(struct ath_hw *ah,
+ int16_t nfarray[NUM_NF_READINGS])
+{
+ int16_t nf;
+
+ nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
+ nfarray[0] = sign_extend32(nf, 8);
+
+ nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR);
+ nfarray[1] = sign_extend32(nf, 8);
+
+ nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR);
+ nfarray[2] = sign_extend32(nf, 8);
+
+ if (!IS_CHAN_HT40(ah->curchan))
+ return;
+
+ nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
+ nfarray[3] = sign_extend32(nf, 8);
+
+ nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR);
+ nfarray[4] = sign_extend32(nf, 8);
+
+ nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR);
+ nfarray[5] = sign_extend32(nf, 8);
+}
+
+/*
+ * Initialize the ANI register values with default (ini) values.
+ * This routine is called during a (full) hardware reset after
+ * all the registers are initialised from the INI.
+ */
+static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
+{
+ struct ath9k_channel *chan = ah->curchan;
+ struct ar5416AniState *aniState = &chan->ani;
+ struct ath9k_ani_default *iniDef;
+ u32 val;
+
+ iniDef = &aniState->iniDef;
+
+ DBG2("ath9k: ver %d.%d chan %d Mhz/0x%x\n",
+ ah->hw_version.macVersion,
+ ah->hw_version.macRev,
+ chan->channel,
+ chan->channelFlags);
+
+ val = REG_READ(ah, AR_PHY_SFCORR);
+ iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH);
+ iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH);
+ iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR);
+
+ val = REG_READ(ah, AR_PHY_SFCORR_LOW);
+ iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW);
+ iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW);
+ iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW);
+
+ val = REG_READ(ah, AR_PHY_SFCORR_EXT);
+ iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH);
+ iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH);
+ iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW);
+ iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW);
+ iniDef->firstep = REG_READ_FIELD(ah,
+ AR_PHY_FIND_SIG,
+ AR_PHY_FIND_SIG_FIRSTEP);
+ iniDef->firstepLow = REG_READ_FIELD(ah,
+ AR_PHY_FIND_SIG_LOW,
+ AR_PHY_FIND_SIG_FIRSTEP_LOW);
+ iniDef->cycpwrThr1 = REG_READ_FIELD(ah,
+ AR_PHY_TIMING5,
+ AR_PHY_TIMING5_CYCPWR_THR1);
+ iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah,
+ AR_PHY_EXT_CCA,
+ AR_PHY_EXT_TIMING5_CYCPWR_THR1);
+
+ /* these levels just got reset to defaults by the INI */
+ aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
+ aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
+ aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
+ aniState->mrcCCKOff = 1; /* not available on pre AR9003 */
+}
+
+static void ar5008_hw_set_nf_limits(struct ath_hw *ah)
+{
+ ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ;
+ ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ;
+ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ;
+ ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ;
+ ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ;
+ ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ;
+}
+
+static void ar5008_hw_set_radar_params(struct ath_hw *ah,
+ struct ath_hw_radar_conf *conf)
+{
+ u32 radar_0 = 0, radar_1 = 0;
+
+ if (!conf) {
+ REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
+ return;
+ }
+
+ radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA;
+ radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR);
+ radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI);
+ radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT);
+ radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);
+ radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);
+
+ radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;
+ radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;
+ radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);
+ radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH);
+ radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH);
+
+ REG_WRITE(ah, AR_PHY_RADAR_0, radar_0);
+ REG_WRITE(ah, AR_PHY_RADAR_1, radar_1);
+ if (conf->ext_channel)
+ REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+ else
+ REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+}
+
+static void ar5008_hw_set_radar_conf(struct ath_hw *ah)
+{
+ struct ath_hw_radar_conf *conf = &ah->radar_conf;
+
+ conf->fir_power = -33;
+ conf->radar_rssi = 20;
+ conf->pulse_height = 10;
+ conf->pulse_rssi = 24;
+ conf->pulse_inband = 15;
+ conf->pulse_maxlen = 255;
+ conf->pulse_inband_step = 12;
+ conf->radar_inband = 8;
+}
+
+void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
+{
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+ static const u32 ar5416_cca_regs[6] = {
+ AR_PHY_CCA,
+ AR_PHY_CH1_CCA,
+ AR_PHY_CH2_CCA,
+ AR_PHY_EXT_CCA,
+ AR_PHY_CH1_EXT_CCA,
+ AR_PHY_CH2_EXT_CCA
+ };
+
+ priv_ops->rf_set_freq = ar5008_hw_set_channel;
+ priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate;
+
+ priv_ops->rf_alloc_ext_banks = ar5008_hw_rf_alloc_ext_banks;
+ priv_ops->rf_free_ext_banks = ar5008_hw_rf_free_ext_banks;
+ priv_ops->set_rf_regs = ar5008_hw_set_rf_regs;
+ priv_ops->set_channel_regs = ar5008_hw_set_channel_regs;
+ priv_ops->init_bb = ar5008_hw_init_bb;
+ priv_ops->process_ini = ar5008_hw_process_ini;
+ priv_ops->set_rfmode = ar5008_hw_set_rfmode;
+ priv_ops->mark_phy_inactive = ar5008_hw_mark_phy_inactive;
+ priv_ops->set_delta_slope = ar5008_hw_set_delta_slope;
+ priv_ops->rfbus_req = ar5008_hw_rfbus_req;
+ priv_ops->rfbus_done = ar5008_hw_rfbus_done;
+ priv_ops->restore_chainmask = ar5008_restore_chainmask;
+ priv_ops->set_diversity = ar5008_set_diversity;
+ priv_ops->do_getnf = ar5008_hw_do_getnf;
+ priv_ops->set_radar_params = ar5008_hw_set_radar_params;
+
+ if (modparam_force_new_ani) {
+ priv_ops->ani_control = ar5008_hw_ani_control_new;
+ priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs;
+ } else
+ priv_ops->ani_control = ar5008_hw_ani_control_old;
+
+ if (AR_SREV_9100(ah))
+ priv_ops->compute_pll_control = ar9100_hw_compute_pll_control;
+ else if (AR_SREV_9160_10_OR_LATER(ah))
+ priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;
+ else
+ priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;
+
+ ar5008_hw_set_nf_limits(ah);
+ ar5008_hw_set_radar_conf(ah);
+ memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs));
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_calib.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_calib.c
new file mode 100644
index 00000000..f8978a55
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_calib.c
@@ -0,0 +1,997 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "hw-ops.h"
+#include "ar9002_phy.h"
+
+#define AR9285_CLCAL_REDO_THRESH 1
+
+enum ar9002_cal_types {
+ ADC_GAIN_CAL = BIT(0),
+ ADC_DC_CAL = BIT(1),
+ IQ_MISMATCH_CAL = BIT(2),
+};
+
+static int ar9002_hw_is_cal_supported(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ enum ar9002_cal_types cal_type)
+{
+ int supported = 0;
+ switch (ah->supp_cals & cal_type) {
+ case IQ_MISMATCH_CAL:
+ /* Run IQ Mismatch for non-CCK only */
+ if (!IS_CHAN_B(chan))
+ supported = 1;
+ break;
+ case ADC_GAIN_CAL:
+ case ADC_DC_CAL:
+ /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
+ if (!IS_CHAN_B(chan) &&
+ !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
+ supported = 1;
+ break;
+ }
+ return supported;
+}
+
+static void ar9002_hw_setup_calibration(struct ath_hw *ah,
+ struct ath9k_cal_list *currCal)
+{
+ REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
+ AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
+ currCal->calData->calCountMax);
+
+ switch (currCal->calData->calType) {
+ case IQ_MISMATCH_CAL:
+ REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
+ DBG2("ath9k: "
+ "starting IQ Mismatch Calibration\n");
+ break;
+ case ADC_GAIN_CAL:
+ REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
+ DBG2("ath9k: "
+ "starting ADC Gain Calibration\n");
+ break;
+ case ADC_DC_CAL:
+ REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
+ DBG2("ath9k: "
+ "starting ADC DC Calibration\n");
+ break;
+ }
+
+ REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
+ AR_PHY_TIMING_CTRL4_DO_CAL);
+}
+
+static int ar9002_hw_per_calibration(struct ath_hw *ah,
+ struct ath9k_channel *ichan __unused,
+ u8 rxchainmask,
+ struct ath9k_cal_list *currCal)
+{
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
+ int iscaldone = 0;
+
+ if (currCal->calState == CAL_RUNNING) {
+ if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
+ AR_PHY_TIMING_CTRL4_DO_CAL)) {
+
+ currCal->calData->calCollect(ah);
+ ah->cal_samples++;
+
+ if (ah->cal_samples >=
+ currCal->calData->calNumSamples) {
+ int i, numChains = 0;
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (rxchainmask & (1 << i))
+ numChains++;
+ }
+
+ currCal->calData->calPostProc(ah, numChains);
+ caldata->CalValid |= currCal->calData->calType;
+ currCal->calState = CAL_DONE;
+ iscaldone = 1;
+ } else {
+ ar9002_hw_setup_calibration(ah, currCal);
+ }
+ }
+ } else if (!(caldata->CalValid & currCal->calData->calType)) {
+ ath9k_hw_reset_calibration(ah, currCal);
+ }
+
+ return iscaldone;
+}
+
+static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
+{
+ int i;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ ah->totalPowerMeasI[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+ ah->totalPowerMeasQ[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+ ah->totalIqCorrMeas[i] +=
+ (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+ DBG2("ath9k: "
+ "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
+ ah->cal_samples, i, ah->totalPowerMeasI[i],
+ ah->totalPowerMeasQ[i],
+ ah->totalIqCorrMeas[i]);
+ }
+}
+
+static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah)
+{
+ int i;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ ah->totalAdcIOddPhase[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+ ah->totalAdcIEvenPhase[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+ ah->totalAdcQOddPhase[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+ ah->totalAdcQEvenPhase[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+ DBG2("ath9k: "
+ "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
+ ah->cal_samples, i,
+ ah->totalAdcIOddPhase[i],
+ ah->totalAdcIEvenPhase[i],
+ ah->totalAdcQOddPhase[i],
+ ah->totalAdcQEvenPhase[i]);
+ }
+}
+
+static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
+{
+ int i;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ ah->totalAdcDcOffsetIOddPhase[i] +=
+ (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+ ah->totalAdcDcOffsetIEvenPhase[i] +=
+ (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+ ah->totalAdcDcOffsetQOddPhase[i] +=
+ (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+ ah->totalAdcDcOffsetQEvenPhase[i] +=
+ (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+ DBG2("ath9k: "
+ "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
+ ah->cal_samples, i,
+ ah->totalAdcDcOffsetIOddPhase[i],
+ ah->totalAdcDcOffsetIEvenPhase[i],
+ ah->totalAdcDcOffsetQOddPhase[i],
+ ah->totalAdcDcOffsetQEvenPhase[i]);
+ }
+}
+
+static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
+{
+ u32 powerMeasQ, powerMeasI, iqCorrMeas;
+ u32 qCoffDenom, iCoffDenom;
+ int32_t qCoff, iCoff;
+ int iqCorrNeg, i;
+
+ for (i = 0; i < numChains; i++) {
+ powerMeasI = ah->totalPowerMeasI[i];
+ powerMeasQ = ah->totalPowerMeasQ[i];
+ iqCorrMeas = ah->totalIqCorrMeas[i];
+
+ DBG2("ath9k: "
+ "Starting IQ Cal and Correction for Chain %d\n",
+ i);
+
+ DBG2("ath9k: "
+ "Orignal: Chn %diq_corr_meas = 0x%08x\n",
+ i, ah->totalIqCorrMeas[i]);
+
+ iqCorrNeg = 0;
+
+ if (iqCorrMeas > 0x80000000) {
+ iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
+ iqCorrNeg = 1;
+ }
+
+ DBG2("ath9k: "
+ "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
+ DBG2("ath9k: "
+ "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
+ DBG2("ath9k: iqCorrNeg is 0x%08x\n",
+ iqCorrNeg);
+
+ iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
+ qCoffDenom = powerMeasQ / 64;
+
+ if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
+ (qCoffDenom != 0)) {
+ iCoff = iqCorrMeas / iCoffDenom;
+ qCoff = powerMeasI / qCoffDenom - 64;
+ DBG2("ath9k: "
+ "Chn %d iCoff = 0x%08x\n", i, iCoff);
+ DBG2("ath9k: "
+ "Chn %d qCoff = 0x%08x\n", i, qCoff);
+
+ iCoff = iCoff & 0x3f;
+ DBG2("ath9k: "
+ "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
+ if (iqCorrNeg == 0x0)
+ iCoff = 0x40 - iCoff;
+
+ if (qCoff > 15)
+ qCoff = 15;
+ else if (qCoff <= -16)
+ qCoff = -16;
+
+ DBG2("ath9k: "
+ "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
+ i, iCoff, qCoff);
+
+ REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
+ iCoff);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
+ qCoff);
+ DBG2("ath9k: "
+ "IQ Cal and Correction done for Chain %d\n",
+ i);
+ }
+ }
+
+ REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
+ AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
+}
+
+static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
+{
+ u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
+ u32 qGainMismatch, iGainMismatch, val, i;
+
+ for (i = 0; i < numChains; i++) {
+ iOddMeasOffset = ah->totalAdcIOddPhase[i];
+ iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
+ qOddMeasOffset = ah->totalAdcQOddPhase[i];
+ qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
+
+ DBG2("ath9k: "
+ "Starting ADC Gain Cal for Chain %d\n", i);
+
+ DBG2("ath9k: "
+ "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
+ iOddMeasOffset);
+ DBG2("ath9k: "
+ "Chn %d pwr_meas_even_i = 0x%08x\n", i,
+ iEvenMeasOffset);
+ DBG2("ath9k: "
+ "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
+ qOddMeasOffset);
+ DBG2("ath9k: "
+ "Chn %d pwr_meas_even_q = 0x%08x\n", i,
+ qEvenMeasOffset);
+
+ if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
+ iGainMismatch =
+ ((iEvenMeasOffset * 32) /
+ iOddMeasOffset) & 0x3f;
+ qGainMismatch =
+ ((qOddMeasOffset * 32) /
+ qEvenMeasOffset) & 0x3f;
+
+ DBG2("ath9k: "
+ "Chn %d gain_mismatch_i = 0x%08x\n", i,
+ iGainMismatch);
+ DBG2("ath9k: "
+ "Chn %d gain_mismatch_q = 0x%08x\n", i,
+ qGainMismatch);
+
+ val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+ val &= 0xfffff000;
+ val |= (qGainMismatch) | (iGainMismatch << 6);
+ REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+ DBG2("ath9k: "
+ "ADC Gain Cal done for Chain %d\n", i);
+ }
+ }
+
+ REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+ REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
+ AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
+}
+
+static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
+{
+ u32 iOddMeasOffset, iEvenMeasOffset, val, i;
+ int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
+ const struct ath9k_percal_data *calData =
+ ah->cal_list_curr->calData;
+ u32 numSamples =
+ (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
+
+ for (i = 0; i < numChains; i++) {
+ iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
+ iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
+ qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
+ qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
+
+ DBG2("ath9k: "
+ "Starting ADC DC Offset Cal for Chain %d\n", i);
+
+ DBG2("ath9k: "
+ "Chn %d pwr_meas_odd_i = %d\n", i,
+ iOddMeasOffset);
+ DBG2("ath9k: "
+ "Chn %d pwr_meas_even_i = %d\n", i,
+ iEvenMeasOffset);
+ DBG2("ath9k: "
+ "Chn %d pwr_meas_odd_q = %d\n", i,
+ qOddMeasOffset);
+ DBG2("ath9k: "
+ "Chn %d pwr_meas_even_q = %d\n", i,
+ qEvenMeasOffset);
+
+ iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
+ numSamples) & 0x1ff;
+ qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
+ numSamples) & 0x1ff;
+
+ DBG2("ath9k: "
+ "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
+ iDcMismatch);
+ DBG2("ath9k: "
+ "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
+ qDcMismatch);
+
+ val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+ val &= 0xc0000fff;
+ val |= (qDcMismatch << 12) | (iDcMismatch << 21);
+ REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+ DBG2("ath9k: "
+ "ADC DC Offset Cal done for Chain %d\n", i);
+ }
+
+ REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+ REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
+ AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
+}
+
+static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah)
+{
+ u32 rddata;
+ int32_t delta, currPDADC, slope;
+
+ rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
+ currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
+
+ if (ah->initPDADC == 0 || currPDADC == 0) {
+ /*
+ * Zero value indicates that no frames have been transmitted
+ * yet, can't do temperature compensation until frames are
+ * transmitted.
+ */
+ return;
+ } else {
+ slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
+
+ if (slope == 0) { /* to avoid divide by zero case */
+ delta = 0;
+ } else {
+ delta = ((currPDADC - ah->initPDADC)*4) / slope;
+ }
+ REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
+ AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
+ REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
+ AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
+ }
+}
+
+static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
+{
+ u32 rddata, i;
+ int delta, currPDADC, regval;
+
+ rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
+ currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
+
+ if (ah->initPDADC == 0 || currPDADC == 0)
+ return;
+
+ if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
+ delta = (currPDADC - ah->initPDADC + 4) / 8;
+ else
+ delta = (currPDADC - ah->initPDADC + 5) / 10;
+
+ if (delta != ah->PDADCdelta) {
+ ah->PDADCdelta = delta;
+ for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
+ regval = ah->originalGain[i] - delta;
+ if (regval < 0)
+ regval = 0;
+
+ REG_RMW_FIELD(ah,
+ AR_PHY_TX_GAIN_TBL1 + i * 4,
+ AR_PHY_TX_GAIN, regval);
+ }
+ }
+}
+
+static void ar9271_hw_pa_cal(struct ath_hw *ah, int is_reset)
+{
+ u32 regVal;
+ unsigned int i;
+ u32 regList[][2] = {
+ { 0x786c, 0 },
+ { 0x7854, 0 },
+ { 0x7820, 0 },
+ { 0x7824, 0 },
+ { 0x7868, 0 },
+ { 0x783c, 0 },
+ { 0x7838, 0 } ,
+ { 0x7828, 0 } ,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(regList); i++)
+ regList[i][1] = REG_READ(ah, regList[i][0]);
+
+ regVal = REG_READ(ah, 0x7834);
+ regVal &= (~(0x1));
+ REG_WRITE(ah, 0x7834, regVal);
+ regVal = REG_READ(ah, 0x9808);
+ regVal |= (0x1 << 27);
+ REG_WRITE(ah, 0x9808, regVal);
+
+ /* 786c,b23,1, pwddac=1 */
+ REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
+ /* 7854, b5,1, pdrxtxbb=1 */
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
+ /* 7854, b7,1, pdv2i=1 */
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
+ /* 7854, b8,1, pddacinterface=1 */
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
+ /* 7824,b12,0, offcal=0 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
+ /* 7838, b1,0, pwddb=0 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
+ /* 7820,b11,0, enpacal=0 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
+ /* 7820,b25,1, pdpadrv1=0 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
+ /* 7820,b24,0, pdpadrv2=0 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
+ /* 7820,b23,0, pdpaout=0 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
+ /* 783c,b14-16,7, padrvgn2tab_0=7 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
+ /*
+ * 7838,b29-31,0, padrvgn1tab_0=0
+ * does not matter since we turn it off
+ */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
+
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
+
+ /* Set:
+ * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
+ * txon=1,paon=1,oscon=1,synthon_force=1
+ */
+ REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
+ udelay(30);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
+
+ /* find off_6_1; */
+ for (i = 6; i > 0; i--) {
+ regVal = REG_READ(ah, 0x7834);
+ regVal |= (1 << (20 + i));
+ REG_WRITE(ah, 0x7834, regVal);
+ udelay(1);
+ /* regVal = REG_READ(ah, 0x7834); */
+ regVal &= (~(0x1 << (20 + i)));
+ regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
+ << (20 + i));
+ REG_WRITE(ah, 0x7834, regVal);
+ }
+
+ regVal = (regVal >> 20) & 0x7f;
+
+ /* Update PA cal info */
+ if ((!is_reset) && ((unsigned int)ah->pacal_info.prev_offset == regVal)) {
+ if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
+ ah->pacal_info.max_skipcount =
+ 2 * ah->pacal_info.max_skipcount;
+ ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
+ } else {
+ ah->pacal_info.max_skipcount = 1;
+ ah->pacal_info.skipcount = 0;
+ ah->pacal_info.prev_offset = regVal;
+ }
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ regVal = REG_READ(ah, 0x7834);
+ regVal |= 0x1;
+ REG_WRITE(ah, 0x7834, regVal);
+ regVal = REG_READ(ah, 0x9808);
+ regVal &= (~(0x1 << 27));
+ REG_WRITE(ah, 0x9808, regVal);
+
+ for (i = 0; i < ARRAY_SIZE(regList); i++)
+ REG_WRITE(ah, regList[i][0], regList[i][1]);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+}
+
+static inline void ar9285_hw_pa_cal(struct ath_hw *ah, int is_reset)
+{
+ u32 regVal;
+ unsigned int i;
+ int offset, offs_6_1, offs_0;
+ u32 ccomp_org, reg_field;
+ u32 regList[][2] = {
+ { 0x786c, 0 },
+ { 0x7854, 0 },
+ { 0x7820, 0 },
+ { 0x7824, 0 },
+ { 0x7868, 0 },
+ { 0x783c, 0 },
+ { 0x7838, 0 },
+ };
+
+ DBG2("ath9k: Running PA Calibration\n");
+
+ /* PA CAL is not needed for high power solution */
+ if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
+ AR5416_EEP_TXGAIN_HIGH_POWER)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(regList); i++)
+ regList[i][1] = REG_READ(ah, regList[i][0]);
+
+ regVal = REG_READ(ah, 0x7834);
+ regVal &= (~(0x1));
+ REG_WRITE(ah, 0x7834, regVal);
+ regVal = REG_READ(ah, 0x9808);
+ regVal |= (0x1 << 27);
+ REG_WRITE(ah, 0x9808, regVal);
+
+ REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
+ ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
+
+ REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
+ udelay(30);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
+
+ for (i = 6; i > 0; i--) {
+ regVal = REG_READ(ah, 0x7834);
+ regVal |= (1 << (19 + i));
+ REG_WRITE(ah, 0x7834, regVal);
+ udelay(1);
+ regVal = REG_READ(ah, 0x7834);
+ regVal &= (~(0x1 << (19 + i)));
+ reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
+ regVal |= (reg_field << (19 + i));
+ REG_WRITE(ah, 0x7834, regVal);
+ }
+
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
+ udelay(1);
+ reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
+ offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
+ offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
+
+ offset = (offs_6_1<<1) | offs_0;
+ offset = offset - 0;
+ offs_6_1 = offset>>1;
+ offs_0 = offset & 1;
+
+ if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
+ if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
+ ah->pacal_info.max_skipcount =
+ 2 * ah->pacal_info.max_skipcount;
+ ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
+ } else {
+ ah->pacal_info.max_skipcount = 1;
+ ah->pacal_info.skipcount = 0;
+ ah->pacal_info.prev_offset = offset;
+ }
+
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
+
+ regVal = REG_READ(ah, 0x7834);
+ regVal |= 0x1;
+ REG_WRITE(ah, 0x7834, regVal);
+ regVal = REG_READ(ah, 0x9808);
+ regVal &= (~(0x1 << 27));
+ REG_WRITE(ah, 0x9808, regVal);
+
+ for (i = 0; i < ARRAY_SIZE(regList); i++)
+ REG_WRITE(ah, regList[i][0], regList[i][1]);
+
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
+}
+
+static void ar9002_hw_pa_cal(struct ath_hw *ah, int is_reset)
+{
+ if (AR_SREV_9271(ah)) {
+ if (is_reset || !ah->pacal_info.skipcount)
+ ar9271_hw_pa_cal(ah, is_reset);
+ else
+ ah->pacal_info.skipcount--;
+ } else if (AR_SREV_9285_12_OR_LATER(ah)) {
+ if (is_reset || !ah->pacal_info.skipcount)
+ ar9285_hw_pa_cal(ah, is_reset);
+ else
+ ah->pacal_info.skipcount--;
+ }
+}
+
+static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
+{
+ if (OLC_FOR_AR9287_10_LATER)
+ ar9287_hw_olc_temp_compensation(ah);
+ else if (OLC_FOR_AR9280_20_LATER)
+ ar9280_hw_olc_temp_compensation(ah);
+}
+
+static int ar9002_hw_calibrate(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 rxchainmask,
+ int longcal)
+{
+ int iscaldone = 1;
+ struct ath9k_cal_list *currCal = ah->cal_list_curr;
+ int nfcal, nfcal_pending = 0;
+
+ nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
+ if (ah->caldata)
+ nfcal_pending = ah->caldata->nfcal_pending;
+
+ if (currCal && !nfcal &&
+ (currCal->calState == CAL_RUNNING ||
+ currCal->calState == CAL_WAITING)) {
+ iscaldone = ar9002_hw_per_calibration(ah, chan,
+ rxchainmask, currCal);
+ if (iscaldone) {
+ ah->cal_list_curr = currCal = currCal->calNext;
+
+ if (currCal->calState == CAL_WAITING) {
+ iscaldone = 0;
+ ath9k_hw_reset_calibration(ah, currCal);
+ }
+ }
+ }
+
+ /* Do NF cal only at longer intervals */
+ if (longcal || nfcal_pending) {
+ /*
+ * Get the value from the previous NF cal and update
+ * history buffer.
+ */
+ if (ath9k_hw_getnf(ah, chan)) {
+ /*
+ * Load the NF from history buffer of the current
+ * channel.
+ * NF is slow time-variant, so it is OK to use a
+ * historical value.
+ */
+ ath9k_hw_loadnf(ah, ah->curchan);
+ }
+
+ if (longcal) {
+ ath9k_hw_start_nfcal(ah, 0);
+ /* Do periodic PAOffset Cal */
+ ar9002_hw_pa_cal(ah, 0);
+ ar9002_hw_olc_temp_compensation(ah);
+ }
+ }
+
+ return iscaldone;
+}
+
+/* Carrier leakage Calibration fix */
+static int ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+ if (IS_CHAN_HT20(chan)) {
+ REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
+ REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_FLTR_CAL);
+ REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
+ if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
+ DBG("ath9k: "
+ "offset calibration failed to complete in 1ms; noisy environment?\n");
+ return 0;
+ }
+ REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
+ REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
+ REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+ }
+ REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+ REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
+ if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
+ 0, AH_WAIT_TIMEOUT)) {
+ DBG("ath9k: "
+ "offset calibration failed to complete in 1ms; noisy environment?\n");
+ return 0;
+ }
+
+ REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+ REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+
+ return 1;
+}
+
+static int ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ unsigned int i;
+ uint32_t txgain_max;
+ uint32_t clc_gain, gain_mask = 0, clc_num = 0;
+ uint32_t reg_clc_I0, reg_clc_Q0;
+ uint32_t i0_num = 0;
+ uint32_t q0_num = 0;
+ uint32_t total_num = 0;
+ uint32_t reg_rf2g5_org;
+ int retv = 1;
+
+ if (!(ar9285_hw_cl_cal(ah, chan)))
+ return 0;
+
+ txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7),
+ AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX);
+
+ for (i = 0; i < (txgain_max+1); i++) {
+ clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) &
+ AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S;
+ if (!(gain_mask & (1 << clc_gain))) {
+ gain_mask |= (1 << clc_gain);
+ clc_num++;
+ }
+ }
+
+ for (i = 0; i < clc_num; i++) {
+ reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
+ & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S;
+ reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
+ & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S;
+ if (reg_clc_I0 == 0)
+ i0_num++;
+
+ if (reg_clc_Q0 == 0)
+ q0_num++;
+ }
+ total_num = i0_num + q0_num;
+ if (total_num > AR9285_CLCAL_REDO_THRESH) {
+ reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5);
+ if (AR_SREV_9285E_20(ah)) {
+ REG_WRITE(ah, AR9285_RF2G5,
+ (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
+ AR9285_RF2G5_IC50TX_XE_SET);
+ } else {
+ REG_WRITE(ah, AR9285_RF2G5,
+ (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
+ AR9285_RF2G5_IC50TX_SET);
+ }
+ retv = ar9285_hw_cl_cal(ah, chan);
+ REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org);
+ }
+ return retv;
+}
+
+static int ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ if (AR_SREV_9271(ah)) {
+ if (!ar9285_hw_cl_cal(ah, chan))
+ return 0;
+ } else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
+ if (!ar9285_hw_clc(ah, chan))
+ return 0;
+ } else {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ if (!AR_SREV_9287_11_OR_LATER(ah))
+ REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
+ AR_PHY_ADC_CTL_OFF_PWDADC);
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_FLTR_CAL);
+ }
+
+ /* Calibrate the AGC */
+ REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+ REG_READ(ah, AR_PHY_AGC_CONTROL) |
+ AR_PHY_AGC_CONTROL_CAL);
+
+ /* Poll for offset calibration complete */
+ if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_CAL,
+ 0, AH_WAIT_TIMEOUT)) {
+ DBG("ath9k: "
+ "offset calibration failed to complete in 1ms; noisy environment?\n");
+ return 0;
+ }
+
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ if (!AR_SREV_9287_11_OR_LATER(ah))
+ REG_SET_BIT(ah, AR_PHY_ADC_CTL,
+ AR_PHY_ADC_CTL_OFF_PWDADC);
+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_FLTR_CAL);
+ }
+ }
+
+ /* Do PA Calibration */
+ ar9002_hw_pa_cal(ah, 1);
+
+ /* Do NF Calibration after DC offset and other calibrations */
+ ath9k_hw_start_nfcal(ah, 1);
+
+ if (ah->caldata)
+ ah->caldata->nfcal_pending = 1;
+
+ ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
+
+ /* Enable IQ, ADC Gain and ADC DC offset CALs */
+ if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
+ ah->supp_cals = IQ_MISMATCH_CAL;
+
+ if (AR_SREV_9160_10_OR_LATER(ah))
+ ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL;
+
+ if (AR_SREV_9287(ah))
+ ah->supp_cals &= ~ADC_GAIN_CAL;
+
+ if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) {
+ INIT_CAL(&ah->adcgain_caldata);
+ INSERT_CAL(ah, &ah->adcgain_caldata);
+ DBG2("ath9k: "
+ "enabling ADC Gain Calibration.\n");
+ }
+
+ if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) {
+ INIT_CAL(&ah->adcdc_caldata);
+ INSERT_CAL(ah, &ah->adcdc_caldata);
+ DBG2("ath9k: "
+ "enabling ADC DC Calibration.\n");
+ }
+
+ if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) {
+ INIT_CAL(&ah->iq_caldata);
+ INSERT_CAL(ah, &ah->iq_caldata);
+ DBG2("ath9k: "
+ "enabling IQ Calibration.\n");
+ }
+
+ ah->cal_list_curr = ah->cal_list;
+
+ if (ah->cal_list_curr)
+ ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
+ }
+
+ if (ah->caldata)
+ ah->caldata->CalValid = 0;
+
+ return 1;
+}
+
+static const struct ath9k_percal_data iq_cal_multi_sample = {
+ IQ_MISMATCH_CAL,
+ MAX_CAL_SAMPLES,
+ PER_MIN_LOG_COUNT,
+ ar9002_hw_iqcal_collect,
+ ar9002_hw_iqcalibrate
+};
+static const struct ath9k_percal_data iq_cal_single_sample = {
+ IQ_MISMATCH_CAL,
+ MIN_CAL_SAMPLES,
+ PER_MAX_LOG_COUNT,
+ ar9002_hw_iqcal_collect,
+ ar9002_hw_iqcalibrate
+};
+static const struct ath9k_percal_data adc_gain_cal_multi_sample = {
+ ADC_GAIN_CAL,
+ MAX_CAL_SAMPLES,
+ PER_MIN_LOG_COUNT,
+ ar9002_hw_adc_gaincal_collect,
+ ar9002_hw_adc_gaincal_calibrate
+};
+static const struct ath9k_percal_data adc_gain_cal_single_sample = {
+ ADC_GAIN_CAL,
+ MIN_CAL_SAMPLES,
+ PER_MAX_LOG_COUNT,
+ ar9002_hw_adc_gaincal_collect,
+ ar9002_hw_adc_gaincal_calibrate
+};
+static const struct ath9k_percal_data adc_dc_cal_multi_sample = {
+ ADC_DC_CAL,
+ MAX_CAL_SAMPLES,
+ PER_MIN_LOG_COUNT,
+ ar9002_hw_adc_dccal_collect,
+ ar9002_hw_adc_dccal_calibrate
+};
+static const struct ath9k_percal_data adc_dc_cal_single_sample = {
+ ADC_DC_CAL,
+ MIN_CAL_SAMPLES,
+ PER_MAX_LOG_COUNT,
+ ar9002_hw_adc_dccal_collect,
+ ar9002_hw_adc_dccal_calibrate
+};
+
+static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
+{
+ if (AR_SREV_9100(ah)) {
+ ah->iq_caldata.calData = &iq_cal_multi_sample;
+ ah->supp_cals = IQ_MISMATCH_CAL;
+ return;
+ }
+
+ if (AR_SREV_9160_10_OR_LATER(ah)) {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ ah->iq_caldata.calData = &iq_cal_single_sample;
+ ah->adcgain_caldata.calData =
+ &adc_gain_cal_single_sample;
+ ah->adcdc_caldata.calData =
+ &adc_dc_cal_single_sample;
+ } else {
+ ah->iq_caldata.calData = &iq_cal_multi_sample;
+ ah->adcgain_caldata.calData =
+ &adc_gain_cal_multi_sample;
+ ah->adcdc_caldata.calData =
+ &adc_dc_cal_multi_sample;
+ }
+ ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
+
+ if (AR_SREV_9287(ah))
+ ah->supp_cals &= ~ADC_GAIN_CAL;
+ }
+}
+
+void ar9002_hw_attach_calib_ops(struct ath_hw *ah)
+{
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+ struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+
+ priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
+ priv_ops->init_cal = ar9002_hw_init_cal;
+ priv_ops->setup_calibration = ar9002_hw_setup_calibration;
+
+ ops->calibrate = ar9002_hw_calibrate;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_hw.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_hw.c
new file mode 100644
index 00000000..cc4edece
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_hw.c
@@ -0,0 +1,607 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "ar5008_initvals.h"
+#include "ar9001_initvals.h"
+#include "ar9002_initvals.h"
+#include "ar9002_phy.h"
+
+int modparam_force_new_ani;
+
+/* General hardware code for the A5008/AR9001/AR9002 hadware families */
+
+static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
+{
+ if (AR_SREV_9271(ah)) {
+ INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271,
+ ARRAY_SIZE(ar9271Modes_9271), 6);
+ INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
+ ARRAY_SIZE(ar9271Common_9271), 2);
+ INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271,
+ ar9271Common_normal_cck_fir_coeff_9271,
+ ARRAY_SIZE(ar9271Common_normal_cck_fir_coeff_9271), 2);
+ INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271,
+ ar9271Common_japan_2484_cck_fir_coeff_9271,
+ ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2);
+ INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
+ ar9271Modes_9271_1_0_only,
+ ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6);
+ INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
+ ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6);
+ INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
+ ar9271Modes_high_power_tx_gain_9271,
+ ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6);
+ INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
+ ar9271Modes_normal_power_tx_gain_9271,
+ ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6);
+ return;
+ }
+
+ if (AR_SREV_9287_11_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
+ ARRAY_SIZE(ar9287Modes_9287_1_1), 6);
+ INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
+ ARRAY_SIZE(ar9287Common_9287_1_1), 2);
+ if (ah->config.pcie_clock_req)
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9287PciePhy_clkreq_off_L1_9287_1_1,
+ ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2);
+ else
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9287PciePhy_clkreq_always_on_L1_9287_1_1,
+ ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1),
+ 2);
+ } else if (AR_SREV_9285_12_OR_LATER(ah)) {
+
+
+ INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
+ ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
+ INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
+ ARRAY_SIZE(ar9285Common_9285_1_2), 2);
+
+ if (ah->config.pcie_clock_req) {
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9285PciePhy_clkreq_off_L1_9285_1_2,
+ ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2);
+ } else {
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9285PciePhy_clkreq_always_on_L1_9285_1_2,
+ ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2),
+ 2);
+ }
+ } else if (AR_SREV_9280_20_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
+ ARRAY_SIZE(ar9280Modes_9280_2), 6);
+ INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
+ ARRAY_SIZE(ar9280Common_9280_2), 2);
+
+ if (ah->config.pcie_clock_req) {
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9280PciePhy_clkreq_off_L1_9280,
+ ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280), 2);
+ } else {
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9280PciePhy_clkreq_always_on_L1_9280,
+ ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
+ }
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9280Modes_fast_clock_9280_2,
+ ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
+ } else if (AR_SREV_9160_10_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
+ ARRAY_SIZE(ar5416Modes_9160), 6);
+ INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
+ ARRAY_SIZE(ar5416Common_9160), 2);
+ INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160,
+ ARRAY_SIZE(ar5416Bank0_9160), 2);
+ INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160,
+ ARRAY_SIZE(ar5416BB_RfGain_9160), 3);
+ INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160,
+ ARRAY_SIZE(ar5416Bank1_9160), 2);
+ INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160,
+ ARRAY_SIZE(ar5416Bank2_9160), 2);
+ INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160,
+ ARRAY_SIZE(ar5416Bank3_9160), 3);
+ INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160,
+ ARRAY_SIZE(ar5416Bank6_9160), 3);
+ INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160,
+ ARRAY_SIZE(ar5416Bank6TPC_9160), 3);
+ INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160,
+ ARRAY_SIZE(ar5416Bank7_9160), 2);
+ if (AR_SREV_9160_11(ah)) {
+ INIT_INI_ARRAY(&ah->iniAddac,
+ ar5416Addac_9160_1_1,
+ ARRAY_SIZE(ar5416Addac_9160_1_1), 2);
+ } else {
+ INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160,
+ ARRAY_SIZE(ar5416Addac_9160), 2);
+ }
+ } else if (AR_SREV_9100_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
+ ARRAY_SIZE(ar5416Modes_9100), 6);
+ INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
+ ARRAY_SIZE(ar5416Common_9100), 2);
+ INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100,
+ ARRAY_SIZE(ar5416Bank0_9100), 2);
+ INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100,
+ ARRAY_SIZE(ar5416BB_RfGain_9100), 3);
+ INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100,
+ ARRAY_SIZE(ar5416Bank1_9100), 2);
+ INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100,
+ ARRAY_SIZE(ar5416Bank2_9100), 2);
+ INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100,
+ ARRAY_SIZE(ar5416Bank3_9100), 3);
+ INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100,
+ ARRAY_SIZE(ar5416Bank6_9100), 3);
+ INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100,
+ ARRAY_SIZE(ar5416Bank6TPC_9100), 3);
+ INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100,
+ ARRAY_SIZE(ar5416Bank7_9100), 2);
+ INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100,
+ ARRAY_SIZE(ar5416Addac_9100), 2);
+ } else {
+ INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
+ ARRAY_SIZE(ar5416Modes), 6);
+ INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
+ ARRAY_SIZE(ar5416Common), 2);
+ INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
+ ARRAY_SIZE(ar5416Bank0), 2);
+ INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain,
+ ARRAY_SIZE(ar5416BB_RfGain), 3);
+ INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1,
+ ARRAY_SIZE(ar5416Bank1), 2);
+ INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2,
+ ARRAY_SIZE(ar5416Bank2), 2);
+ INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3,
+ ARRAY_SIZE(ar5416Bank3), 3);
+ INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6,
+ ARRAY_SIZE(ar5416Bank6), 3);
+ INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC,
+ ARRAY_SIZE(ar5416Bank6TPC), 3);
+ INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7,
+ ARRAY_SIZE(ar5416Bank7), 2);
+ INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
+ ARRAY_SIZE(ar5416Addac), 2);
+ }
+}
+
+/* Support for Japan ch.14 (2484) spread */
+void ar9002_hw_cck_chan14_spread(struct ath_hw *ah)
+{
+ if (AR_SREV_9287_11_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ah->iniCckfirNormal,
+ ar9287Common_normal_cck_fir_coeff_9287_1_1,
+ ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_9287_1_1),
+ 2);
+ INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+ ar9287Common_japan_2484_cck_fir_coeff_9287_1_1,
+ ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_9287_1_1),
+ 2);
+ }
+}
+
+static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
+{
+ u32 rxgain_type;
+
+ if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
+ AR5416_EEP_MINOR_VER_17) {
+ rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
+
+ if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9280Modes_backoff_13db_rxgain_9280_2,
+ ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
+ else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9280Modes_backoff_23db_rxgain_9280_2,
+ ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
+ else
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9280Modes_original_rxgain_9280_2,
+ ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
+ } else {
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9280Modes_original_rxgain_9280_2,
+ ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
+ }
+}
+
+static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah)
+{
+ u32 txgain_type;
+
+ if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
+ AR5416_EEP_MINOR_VER_19) {
+ txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
+
+ if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9280Modes_high_power_tx_gain_9280_2,
+ ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
+ else
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9280Modes_original_tx_gain_9280_2,
+ ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
+ } else {
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9280Modes_original_tx_gain_9280_2,
+ ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
+ }
+}
+
+static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
+{
+ if (AR_SREV_9287_11_OR_LATER(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9287Modes_rx_gain_9287_1_1,
+ ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
+ else if (AR_SREV_9280_20(ah))
+ ar9280_20_hw_init_rxgain_ini(ah);
+
+ if (AR_SREV_9287_11_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9287Modes_tx_gain_9287_1_1,
+ ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
+ } else if (AR_SREV_9280_20(ah)) {
+ ar9280_20_hw_init_txgain_ini(ah);
+ } else if (AR_SREV_9285_12_OR_LATER(ah)) {
+ u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
+
+ /* txgain table */
+ if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
+ if (AR_SREV_9285E_20(ah)) {
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9285Modes_XE2_0_high_power,
+ ARRAY_SIZE(
+ ar9285Modes_XE2_0_high_power), 6);
+ } else {
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9285Modes_high_power_tx_gain_9285_1_2,
+ ARRAY_SIZE(
+ ar9285Modes_high_power_tx_gain_9285_1_2), 6);
+ }
+ } else {
+ if (AR_SREV_9285E_20(ah)) {
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9285Modes_XE2_0_normal_power,
+ ARRAY_SIZE(
+ ar9285Modes_XE2_0_normal_power), 6);
+ } else {
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9285Modes_original_tx_gain_9285_1_2,
+ ARRAY_SIZE(
+ ar9285Modes_original_tx_gain_9285_1_2), 6);
+ }
+ }
+ }
+}
+
+/*
+ * Helper for ASPM support.
+ *
+ * Disable PLL when in L0s as well as receiver clock when in L1.
+ * This power saving option must be enabled through the SerDes.
+ *
+ * Programming the SerDes must go through the same 288 bit serial shift
+ * register as the other analog registers. Hence the 9 writes.
+ */
+static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
+ int restore,
+ int power_off)
+{
+ u8 i;
+ u32 val;
+
+ if (ah->is_pciexpress != 1)
+ return;
+
+ /* Do not touch SerDes registers */
+ if (ah->config.pcie_powersave_enable == 2)
+ return;
+
+ /* Nothing to do on restore for 11N */
+ if (!restore) {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ /*
+ * AR9280 2.0 or later chips use SerDes values from the
+ * initvals.h initialized depending on chipset during
+ * __ath9k_hw_init()
+ */
+ for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
+ REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
+ INI_RA(&ah->iniPcieSerdes, i, 1));
+ }
+ } else {
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+
+ /* RX shut off when elecidle is asserted */
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
+
+ /*
+ * Ignore ah->ah_config.pcie_clock_req setting for
+ * pre-AR9280 11n
+ */
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
+
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
+
+ /* Load the new settings */
+ REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+ }
+
+ udelay(1000);
+ }
+
+ if (power_off) {
+ /* clear bit 19 to disable L1 */
+ REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+
+ val = REG_READ(ah, AR_WA);
+
+ /*
+ * Set PCIe workaround bits
+ * In AR9280 and AR9285, bit 14 in WA register (disable L1)
+ * should only be set when device enters D3 and be
+ * cleared when device comes back to D0.
+ */
+ if (ah->config.pcie_waen) {
+ if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
+ val |= AR_WA_D3_L1_DISABLE;
+ } else {
+ if (((AR_SREV_9285(ah) ||
+ AR_SREV_9271(ah) ||
+ AR_SREV_9287(ah)) &&
+ (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
+ (AR_SREV_9280(ah) &&
+ (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
+ val |= AR_WA_D3_L1_DISABLE;
+ }
+ }
+
+ if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
+ /*
+ * Disable bit 6 and 7 before entering D3 to
+ * prevent system hang.
+ */
+ val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
+ }
+
+ if (AR_SREV_9280(ah))
+ val |= AR_WA_BIT22;
+
+ if (AR_SREV_9285E_20(ah))
+ val |= AR_WA_BIT23;
+
+ REG_WRITE(ah, AR_WA, val);
+ } else {
+ if (ah->config.pcie_waen) {
+ val = ah->config.pcie_waen;
+ if (!power_off)
+ val &= (~AR_WA_D3_L1_DISABLE);
+ } else {
+ if (AR_SREV_9285(ah) ||
+ AR_SREV_9271(ah) ||
+ AR_SREV_9287(ah)) {
+ val = AR9285_WA_DEFAULT;
+ if (!power_off)
+ val &= (~AR_WA_D3_L1_DISABLE);
+ }
+ else if (AR_SREV_9280(ah)) {
+ /*
+ * For AR9280 chips, bit 22 of 0x4004
+ * needs to be set.
+ */
+ val = AR9280_WA_DEFAULT;
+ if (!power_off)
+ val &= (~AR_WA_D3_L1_DISABLE);
+ } else {
+ val = AR_WA_DEFAULT;
+ }
+ }
+
+ /* WAR for ASPM system hang */
+ if (AR_SREV_9285(ah) || AR_SREV_9287(ah))
+ val |= (AR_WA_BIT6 | AR_WA_BIT7);
+
+ if (AR_SREV_9285E_20(ah))
+ val |= AR_WA_BIT23;
+
+ REG_WRITE(ah, AR_WA, val);
+
+ /* set bit 19 to allow forcing of pcie core into L1 state */
+ REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+ }
+}
+
+static int ar9002_hw_get_radiorev(struct ath_hw *ah)
+{
+ u32 val;
+ int i;
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
+ for (i = 0; i < 8; i++)
+ REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
+ val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
+
+ return ath9k_hw_reverse_bits(val, 8);
+}
+
+int ar9002_hw_rf_claim(struct ath_hw *ah)
+{
+ u32 val;
+
+ REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+ val = ar9002_hw_get_radiorev(ah);
+ switch (val & AR_RADIO_SREV_MAJOR) {
+ case 0:
+ val = AR_RAD5133_SREV_MAJOR;
+ break;
+ case AR_RAD5133_SREV_MAJOR:
+ case AR_RAD5122_SREV_MAJOR:
+ case AR_RAD2133_SREV_MAJOR:
+ case AR_RAD2122_SREV_MAJOR:
+ break;
+ default:
+ DBG("ath9k: "
+ "Radio Chip Rev 0x%02X not supported\n",
+ val & AR_RADIO_SREV_MAJOR);
+ return -EOPNOTSUPP;
+ }
+
+ ah->hw_version.analog5GhzRev = val;
+
+ return 0;
+}
+
+void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
+{
+ if (AR_SREV_9287_13_OR_LATER(ah)) {
+ REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
+ AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
+ REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
+ REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
+ AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
+ REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
+ AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
+ }
+}
+
+/*
+ * If Async FIFO is enabled, the following counters change as MAC now runs
+ * at 117 Mhz instead of 88/44MHz when async FIFO is disabled.
+ *
+ * The values below tested for ht40 2 chain.
+ * Overwrite the delay/timeouts initialized in process ini.
+ */
+void ar9002_hw_update_async_fifo(struct ath_hw *ah)
+{
+ if (AR_SREV_9287_13_OR_LATER(ah)) {
+ REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
+ AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
+ REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
+ AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
+ REG_WRITE(ah, AR_D_GBL_IFS_EIFS,
+ AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
+
+ REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
+ REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
+
+ REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
+ AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
+ REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
+ AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
+ }
+}
+
+/*
+ * We don't enable WEP aggregation on mac80211 but we keep this
+ * around for HAL unification purposes.
+ */
+void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah)
+{
+ if (AR_SREV_9287_13_OR_LATER(ah)) {
+ REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
+ AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
+ }
+}
+
+/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
+void ar9002_hw_attach_ops(struct ath_hw *ah)
+{
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+ struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+
+ priv_ops->init_mode_regs = ar9002_hw_init_mode_regs;
+ priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
+
+ ops->config_pci_powersave = ar9002_hw_configpcipowersave;
+
+ ar5008_hw_attach_phy_ops(ah);
+ if (AR_SREV_9280_20_OR_LATER(ah))
+ ar9002_hw_attach_phy_ops(ah);
+
+ ar9002_hw_attach_calib_ops(ah);
+ ar9002_hw_attach_mac_ops(ah);
+}
+
+void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ u32 modesIndex;
+ unsigned int i;
+
+ switch (chan->chanmode) {
+ case CHANNEL_A:
+ case CHANNEL_A_HT20:
+ modesIndex = 1;
+ break;
+ case CHANNEL_A_HT40PLUS:
+ case CHANNEL_A_HT40MINUS:
+ modesIndex = 2;
+ break;
+ case CHANNEL_G:
+ case CHANNEL_G_HT20:
+ case CHANNEL_B:
+ modesIndex = 4;
+ break;
+ case CHANNEL_G_HT40PLUS:
+ case CHANNEL_G_HT40MINUS:
+ modesIndex = 3;
+ break;
+
+ default:
+ return;
+ }
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) {
+ u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0);
+ u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex);
+ u32 val_orig;
+
+ if (reg == AR_PHY_CCK_DETECT) {
+ val_orig = REG_READ(ah, reg);
+ val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
+ val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
+
+ REG_WRITE(ah, reg, val|val_orig);
+ } else
+ REG_WRITE(ah, reg, val);
+ }
+
+ REGWRITE_BUFFER_FLUSH(ah);
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_mac.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_mac.c
new file mode 100644
index 00000000..057756b2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_mac.c
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+
+#include "hw.h"
+
+#define AR_BufLen 0x00000fff
+
+static void ar9002_hw_rx_enable(struct ath_hw *ah)
+{
+ REG_WRITE(ah, AR_CR, AR_CR_RXE);
+}
+
+static void ar9002_hw_set_desc_link(void *ds, u32 ds_link)
+{
+ ((struct ath_desc*) ds)->ds_link = ds_link;
+}
+
+static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link)
+{
+ *ds_link = &((struct ath_desc *)ds)->ds_link;
+}
+
+static int ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
+{
+ u32 isr = 0;
+ u32 mask2 = 0;
+ struct ath9k_hw_capabilities *pCap = &ah->caps;
+ u32 sync_cause = 0;
+ int fatal_int = 0;
+
+ if (!AR_SREV_9100(ah) && (ah->ah_ier & AR_IER_ENABLE)) {
+ if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
+ if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
+ == AR_RTC_STATUS_ON) {
+ isr = REG_READ(ah, AR_ISR);
+ }
+ }
+
+ sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) &
+ AR_INTR_SYNC_DEFAULT;
+
+ *masked = 0;
+
+ if (!isr && !sync_cause)
+ return 0;
+ } else {
+ *masked = 0;
+ isr = REG_READ(ah, AR_ISR);
+ }
+
+ if (isr) {
+ if (isr & AR_ISR_BCNMISC) {
+ u32 isr2;
+ isr2 = REG_READ(ah, AR_ISR_S2);
+ if (isr2 & AR_ISR_S2_TIM)
+ mask2 |= ATH9K_INT_TIM;
+ if (isr2 & AR_ISR_S2_DTIM)
+ mask2 |= ATH9K_INT_DTIM;
+ if (isr2 & AR_ISR_S2_DTIMSYNC)
+ mask2 |= ATH9K_INT_DTIMSYNC;
+ if (isr2 & (AR_ISR_S2_CABEND))
+ mask2 |= ATH9K_INT_CABEND;
+ if (isr2 & AR_ISR_S2_GTT)
+ mask2 |= ATH9K_INT_GTT;
+ if (isr2 & AR_ISR_S2_CST)
+ mask2 |= ATH9K_INT_CST;
+ if (isr2 & AR_ISR_S2_TSFOOR)
+ mask2 |= ATH9K_INT_TSFOOR;
+ }
+
+ isr = REG_READ(ah, AR_ISR_RAC);
+ if (isr == 0xffffffff) {
+ *masked = 0;
+ return 0;
+ }
+
+ *masked = isr & ATH9K_INT_COMMON;
+
+ if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM |
+ AR_ISR_RXOK | AR_ISR_RXERR))
+ *masked |= ATH9K_INT_RX;
+
+ if (isr &
+ (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
+ AR_ISR_TXEOL)) {
+ u32 s0_s, s1_s;
+
+ *masked |= ATH9K_INT_TX;
+
+ s0_s = REG_READ(ah, AR_ISR_S0_S);
+ ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
+ ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
+
+ s1_s = REG_READ(ah, AR_ISR_S1_S);
+ ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
+ ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
+ }
+
+ if (isr & AR_ISR_RXORN) {
+ DBG("ath9k: "
+ "receive FIFO overrun interrupt\n");
+ }
+
+ *masked |= mask2;
+ }
+
+ if (AR_SREV_9100(ah))
+ return 1;
+
+ if (isr & AR_ISR_GENTMR) {
+ u32 s5_s;
+
+ s5_s = REG_READ(ah, AR_ISR_S5_S);
+ ah->intr_gen_timer_trigger =
+ MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
+
+ ah->intr_gen_timer_thresh =
+ MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
+
+ if (ah->intr_gen_timer_trigger)
+ *masked |= ATH9K_INT_GENTIMER;
+
+ if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
+ !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+ *masked |= ATH9K_INT_TIM_TIMER;
+ }
+
+ if (sync_cause) {
+ fatal_int =
+ (sync_cause &
+ (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
+ ? 1 : 0;
+
+ if (fatal_int) {
+ if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
+ DBG("ath9k: "
+ "received PCI FATAL interrupt\n");
+ }
+ if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
+ DBG("ath9k: "
+ "received PCI PERR interrupt\n");
+ }
+ *masked |= ATH9K_INT_FATAL;
+ }
+ if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
+ DBG("ath9k: "
+ "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
+ REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
+ REG_WRITE(ah, AR_RC, 0);
+ *masked |= ATH9K_INT_FATAL;
+ }
+ if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
+ DBG("ath9k: "
+ "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
+ }
+
+ REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
+ (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
+ }
+
+ return 1;
+}
+
+static void ar9002_hw_fill_txdesc(struct ath_hw *ah __unused, void *ds, u32 seglen,
+ int is_firstseg, int is_lastseg,
+ const void *ds0, u32 buf_addr,
+ unsigned int qcu __unused)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_data = buf_addr;
+
+ if (is_firstseg) {
+ ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore);
+ } else if (is_lastseg) {
+ ads->ds_ctl0 = 0;
+ ads->ds_ctl1 = seglen;
+ ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
+ ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
+ } else {
+ ads->ds_ctl0 = 0;
+ ads->ds_ctl1 = seglen | AR_TxMore;
+ ads->ds_ctl2 = 0;
+ ads->ds_ctl3 = 0;
+ }
+ ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
+ ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
+ ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
+ ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
+ ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+}
+
+static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
+ struct ath_tx_status *ts)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+ u32 status;
+
+ status = *(volatile typeof(ads->ds_txstatus9) *)&(ads->ds_txstatus9);
+ if ((status & AR_TxDone) == 0)
+ return -EINPROGRESS;
+
+ ts->ts_tstamp = ads->AR_SendTimestamp;
+ ts->ts_status = 0;
+ ts->ts_flags = 0;
+
+ if (status & AR_TxOpExceeded)
+ ts->ts_status |= ATH9K_TXERR_XTXOP;
+ ts->tid = MS(status, AR_TxTid);
+ ts->ts_rateindex = MS(status, AR_FinalTxIdx);
+ ts->ts_seqnum = MS(status, AR_SeqNum);
+
+ status = *(volatile typeof(ads->ds_txstatus0) *)&(ads->ds_txstatus0);
+ ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
+ ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
+ ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
+ if (status & AR_TxBaStatus) {
+ ts->ts_flags |= ATH9K_TX_BA;
+ ts->ba_low = ads->AR_BaBitmapLow;
+ ts->ba_high = ads->AR_BaBitmapHigh;
+ }
+
+ status = *(volatile typeof(ads->ds_txstatus1) *)&(ads->ds_txstatus1);
+ if (status & AR_FrmXmitOK)
+ ts->ts_status |= ATH9K_TX_ACKED;
+ else {
+ if (status & AR_ExcessiveRetries)
+ ts->ts_status |= ATH9K_TXERR_XRETRY;
+ if (status & AR_Filtered)
+ ts->ts_status |= ATH9K_TXERR_FILT;
+ if (status & AR_FIFOUnderrun) {
+ ts->ts_status |= ATH9K_TXERR_FIFO;
+ ath9k_hw_updatetxtriglevel(ah, 1);
+ }
+ }
+ if (status & AR_TxTimerExpired)
+ ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
+ if (status & AR_DescCfgErr)
+ ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
+ if (status & AR_TxDataUnderrun) {
+ ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
+ ath9k_hw_updatetxtriglevel(ah, 1);
+ }
+ if (status & AR_TxDelimUnderrun) {
+ ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
+ ath9k_hw_updatetxtriglevel(ah, 1);
+ }
+ ts->ts_shortretry = MS(status, AR_RTSFailCnt);
+ ts->ts_longretry = MS(status, AR_DataFailCnt);
+ ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
+
+ status = *(volatile typeof(ads->ds_txstatus5) *)&(ads->ds_txstatus5);
+ ts->ts_rssi = MS(status, AR_TxRSSICombined);
+ ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
+ ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
+ ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
+
+ ts->evm0 = ads->AR_TxEVM0;
+ ts->evm1 = ads->AR_TxEVM1;
+ ts->evm2 = ads->AR_TxEVM2;
+
+ return 0;
+}
+
+static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
+ u32 pktLen, enum ath9k_pkt_type type,
+ u32 txPower, u32 keyIx,
+ enum ath9k_key_type keyType, u32 flags)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ if (txPower > 63)
+ txPower = 63;
+
+ ads->ds_ctl0 = (pktLen & AR_FrameLen)
+ | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+ | SM(txPower, AR_XmitPower)
+ | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+ | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
+ | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
+
+ ads->ds_ctl1 =
+ (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
+ | SM(type, AR_FrameType)
+ | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+ | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+ | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+ ads->ds_ctl6 = SM(keyType, AR_EncrType);
+
+ if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
+ ads->ds_ctl8 = 0;
+ ads->ds_ctl9 = 0;
+ ads->ds_ctl10 = 0;
+ ads->ds_ctl11 = 0;
+ }
+}
+
+static void ar9002_hw_set_clrdmask(struct ath_hw *ah __unused, void *ds, int val)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ if (val)
+ ads->ds_ctl0 |= AR_ClrDestMask;
+ else
+ ads->ds_ctl0 &= ~AR_ClrDestMask;
+}
+
+static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah __unused, void *ds,
+ void *lastds,
+ u32 durUpdateEn, u32 rtsctsRate,
+ u32 rtsctsDuration __unused,
+ struct ath9k_11n_rate_series series[],
+ u32 nseries __unused, u32 flags)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+ struct ar5416_desc *last_ads = AR5416DESC(lastds);
+ u32 ds_ctl0;
+
+ if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
+ ds_ctl0 = ads->ds_ctl0;
+
+ if (flags & ATH9K_TXDESC_RTSENA) {
+ ds_ctl0 &= ~AR_CTSEnable;
+ ds_ctl0 |= AR_RTSEnable;
+ } else {
+ ds_ctl0 &= ~AR_RTSEnable;
+ ds_ctl0 |= AR_CTSEnable;
+ }
+
+ ads->ds_ctl0 = ds_ctl0;
+ } else {
+ ads->ds_ctl0 =
+ (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
+ }
+
+ ads->ds_ctl2 = set11nTries(series, 0)
+ | set11nTries(series, 1)
+ | set11nTries(series, 2)
+ | set11nTries(series, 3)
+ | (durUpdateEn ? AR_DurUpdateEna : 0)
+ | SM(0, AR_BurstDur);
+
+ ads->ds_ctl3 = set11nRate(series, 0)
+ | set11nRate(series, 1)
+ | set11nRate(series, 2)
+ | set11nRate(series, 3);
+
+ ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
+ | set11nPktDurRTSCTS(series, 1);
+
+ ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
+ | set11nPktDurRTSCTS(series, 3);
+
+ ads->ds_ctl7 = set11nRateFlags(series, 0)
+ | set11nRateFlags(series, 1)
+ | set11nRateFlags(series, 2)
+ | set11nRateFlags(series, 3)
+ | SM(rtsctsRate, AR_RTSCTSRate);
+ last_ads->ds_ctl2 = ads->ds_ctl2;
+ last_ads->ds_ctl3 = ads->ds_ctl3;
+}
+
+static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah __unused, void *ds,
+ u32 aggrLen)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+ ads->ds_ctl6 &= ~AR_AggrLen;
+ ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
+}
+
+static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah __unused, void *ds,
+ u32 numDelims)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+ unsigned int ctl6;
+
+ ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+
+ ctl6 = ads->ds_ctl6;
+ ctl6 &= ~AR_PadDelim;
+ ctl6 |= SM(numDelims, AR_PadDelim);
+ ads->ds_ctl6 = ctl6;
+}
+
+static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah __unused, void *ds)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_ctl1 |= AR_IsAggr;
+ ads->ds_ctl1 &= ~AR_MoreAggr;
+ ads->ds_ctl6 &= ~AR_PadDelim;
+}
+
+static void ar9002_hw_clr11n_aggr(struct ath_hw *ah __unused, void *ds)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
+}
+
+void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
+ u32 size, u32 flags)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+ struct ath9k_hw_capabilities *pCap = &ah->caps;
+
+ ads->ds_ctl1 = size & AR_BufLen;
+ if (flags & ATH9K_RXDESC_INTREQ)
+ ads->ds_ctl1 |= AR_RxIntrReq;
+
+ ads->ds_rxstatus8 &= ~AR_RxDone;
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+ memset(&(ads->u), 0, sizeof(ads->u));
+}
+
+void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
+{
+ struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+
+ ops->rx_enable = ar9002_hw_rx_enable;
+ ops->set_desc_link = ar9002_hw_set_desc_link;
+ ops->get_desc_link = ar9002_hw_get_desc_link;
+ ops->get_isr = ar9002_hw_get_isr;
+ ops->fill_txdesc = ar9002_hw_fill_txdesc;
+ ops->proc_txdesc = ar9002_hw_proc_txdesc;
+ ops->set11n_txdesc = ar9002_hw_set11n_txdesc;
+ ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario;
+ ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first;
+ ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle;
+ ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
+ ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
+ ops->set_clrdmask = ar9002_hw_set_clrdmask;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_phy.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_phy.c
new file mode 100644
index 00000000..72203ba4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_phy.c
@@ -0,0 +1,578 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Programming Atheros 802.11n analog front end radios
+ *
+ * AR5416 MAC based PCI devices and AR518 MAC based PCI-Express
+ * devices have either an external AR2133 analog front end radio for single
+ * band 2.4 GHz communication or an AR5133 analog front end radio for dual
+ * band 2.4 GHz / 5 GHz communication.
+ *
+ * All devices after the AR5416 and AR5418 family starting with the AR9280
+ * have their analog front radios, MAC/BB and host PCIe/USB interface embedded
+ * into a single-chip and require less programming.
+ *
+ * The following single-chips exist with a respective embedded radio:
+ *
+ * AR9280 - 11n dual-band 2x2 MIMO for PCIe
+ * AR9281 - 11n single-band 1x2 MIMO for PCIe
+ * AR9285 - 11n single-band 1x1 for PCIe
+ * AR9287 - 11n single-band 2x2 MIMO for PCIe
+ *
+ * AR9220 - 11n dual-band 2x2 MIMO for PCI
+ * AR9223 - 11n single-band 2x2 MIMO for PCI
+ *
+ * AR9287 - 11n single-band 1x1 MIMO for USB
+ */
+
+#include <ipxe/io.h>
+
+#include "hw.h"
+#include "ar9002_phy.h"
+
+/**
+ * ar9002_hw_set_channel - set channel on single-chip device
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * This is the function to change channel on single-chip devices, that is
+ * all devices after ar9280.
+ *
+ * This function takes the channel value in MHz and sets
+ * hardware channel value. Assumes writes have been enabled to analog bus.
+ *
+ * Actual Expression,
+ *
+ * For 2GHz channel,
+ * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
+ * (freq_ref = 40MHz)
+ *
+ * For 5GHz channel,
+ * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
+ * (freq_ref = 40MHz/(24>>amodeRefSel))
+ */
+static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ u16 bMode, fracMode, aModeRefSel = 0;
+ u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
+ struct chan_centers centers;
+ u32 refDivA = 24;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ freq = centers.synth_center;
+
+ reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL);
+ reg32 &= 0xc0000000;
+
+ if (freq < 4800) { /* 2 GHz, fractional mode */
+ u32 txctl;
+ unsigned int regWrites = 0;
+
+ bMode = 1;
+ fracMode = 1;
+ aModeRefSel = 0;
+ channelSel = CHANSEL_2G(freq);
+
+ if (AR_SREV_9287_11_OR_LATER(ah)) {
+ if (freq == 2484) {
+ /* Enable channel spreading for channel 14 */
+ REG_WRITE_ARRAY(&ah->iniCckfirJapan2484,
+ 1, regWrites);
+ } else {
+ REG_WRITE_ARRAY(&ah->iniCckfirNormal,
+ 1, regWrites);
+ }
+ } else {
+ txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+ if (freq == 2484) {
+ /* Enable channel spreading for channel 14 */
+ REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+ txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+ } else {
+ REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+ txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
+ }
+ }
+ } else {
+ bMode = 0;
+ fracMode = 0;
+
+ switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
+ case 0:
+ if ((freq % 20) == 0)
+ aModeRefSel = 3;
+ else if ((freq % 10) == 0)
+ aModeRefSel = 2;
+ if (aModeRefSel)
+ break;
+ case 1:
+ default:
+ aModeRefSel = 0;
+ /*
+ * Enable 2G (fractional) mode for channels
+ * which are 5MHz spaced.
+ */
+ fracMode = 1;
+ refDivA = 1;
+ channelSel = CHANSEL_5G(freq);
+
+ /* RefDivA setting */
+ REG_RMW_FIELD(ah, AR_AN_SYNTH9,
+ AR_AN_SYNTH9_REFDIVA, refDivA);
+
+ }
+
+ if (!fracMode) {
+ ndiv = (freq * (refDivA >> aModeRefSel)) / 60;
+ channelSel = ndiv & 0x1ff;
+ channelFrac = (ndiv & 0xfffffe00) * 2;
+ channelSel = (channelSel << 17) | channelFrac;
+ }
+ }
+
+ reg32 = reg32 |
+ (bMode << 29) |
+ (fracMode << 28) | (aModeRefSel << 26) | (channelSel);
+
+ REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
+
+ ah->curchan = chan;
+ ah->curchan_rad_index = -1;
+
+ return 0;
+}
+
+/**
+ * ar9002_hw_spur_mitigate - convert baseband spur frequency
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * For single-chip solutions. Converts to baseband spur frequency given the
+ * input channel frequency and compute register settings below.
+ */
+static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ int bb_spur = AR_NO_SPUR;
+ int freq;
+ int bin, cur_bin;
+ int bb_spur_off, spur_subchannel_sd;
+ int spur_freq_sd;
+ int spur_delta_phase;
+ int denominator;
+ int upper, lower, cur_vit_mask;
+ int tmp, newVal;
+ int i;
+ static const int pilot_mask_reg[4] = {
+ AR_PHY_TIMING7, AR_PHY_TIMING8,
+ AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
+ };
+ static const int chan_mask_reg[4] = {
+ AR_PHY_TIMING9, AR_PHY_TIMING10,
+ AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
+ };
+ static const int inc[4] = { 0, 100, 0, 0 };
+ struct chan_centers centers;
+
+ int8_t mask_m[123];
+ int8_t mask_p[123];
+ int8_t mask_amt;
+ int tmp_mask;
+ int cur_bb_spur;
+ int is2GHz = IS_CHAN_2GHZ(chan);
+
+ memset(&mask_m, 0, sizeof(int8_t) * 123);
+ memset(&mask_p, 0, sizeof(int8_t) * 123);
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ freq = centers.synth_center;
+
+ ah->config.spurmode = SPUR_ENABLE_EEPROM;
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
+
+ if (AR_NO_SPUR == cur_bb_spur)
+ break;
+
+ if (is2GHz)
+ cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
+ else
+ cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
+
+ cur_bb_spur = cur_bb_spur - freq;
+
+ if (IS_CHAN_HT40(chan)) {
+ if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
+ (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
+ bb_spur = cur_bb_spur;
+ break;
+ }
+ } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
+ (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
+ bb_spur = cur_bb_spur;
+ break;
+ }
+ }
+
+ if (AR_NO_SPUR == bb_spur) {
+ REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
+ AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+ return;
+ } else {
+ REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
+ AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+ }
+
+ bin = bb_spur * 320;
+
+ tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+ AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+ AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+ AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal);
+
+ newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+ AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+ AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+ AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+ SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+ REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
+
+ if (IS_CHAN_HT40(chan)) {
+ if (bb_spur < 0) {
+ spur_subchannel_sd = 1;
+ bb_spur_off = bb_spur + 10;
+ } else {
+ spur_subchannel_sd = 0;
+ bb_spur_off = bb_spur - 10;
+ }
+ } else {
+ spur_subchannel_sd = 0;
+ bb_spur_off = bb_spur;
+ }
+
+ if (IS_CHAN_HT40(chan))
+ spur_delta_phase =
+ ((bb_spur * 262144) /
+ 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+ else
+ spur_delta_phase =
+ ((bb_spur * 524288) /
+ 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+
+ denominator = IS_CHAN_2GHZ(chan) ? 44 : 40;
+ spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
+
+ newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+ SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+ SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+ REG_WRITE(ah, AR_PHY_TIMING11, newVal);
+
+ newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
+ REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
+
+ cur_bin = -6000;
+ upper = bin + 100;
+ lower = bin - 100;
+
+ for (i = 0; i < 4; i++) {
+ int pilot_mask = 0;
+ int chan_mask = 0;
+ int bp = 0;
+ for (bp = 0; bp < 30; bp++) {
+ if ((cur_bin > lower) && (cur_bin < upper)) {
+ pilot_mask = pilot_mask | 0x1 << bp;
+ chan_mask = chan_mask | 0x1 << bp;
+ }
+ cur_bin += 100;
+ }
+ cur_bin += inc[i];
+ REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+ REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+ }
+
+ cur_vit_mask = 6100;
+ upper = bin + 120;
+ lower = bin - 120;
+
+ for (i = 0; i < 123; i++) {
+ if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+
+ /* workaround for gcc bug #37014 */
+ volatile int tmp_v = abs(cur_vit_mask - bin);
+
+ if (tmp_v < 75)
+ mask_amt = 1;
+ else
+ mask_amt = 0;
+ if (cur_vit_mask < 0)
+ mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+ else
+ mask_p[cur_vit_mask / 100] = mask_amt;
+ }
+ cur_vit_mask -= 100;
+ }
+
+ tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
+ | (mask_m[48] << 26) | (mask_m[49] << 24)
+ | (mask_m[50] << 22) | (mask_m[51] << 20)
+ | (mask_m[52] << 18) | (mask_m[53] << 16)
+ | (mask_m[54] << 14) | (mask_m[55] << 12)
+ | (mask_m[56] << 10) | (mask_m[57] << 8)
+ | (mask_m[58] << 6) | (mask_m[59] << 4)
+ | (mask_m[60] << 2) | (mask_m[61] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+ REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+ tmp_mask = (mask_m[31] << 28)
+ | (mask_m[32] << 26) | (mask_m[33] << 24)
+ | (mask_m[34] << 22) | (mask_m[35] << 20)
+ | (mask_m[36] << 18) | (mask_m[37] << 16)
+ | (mask_m[48] << 14) | (mask_m[39] << 12)
+ | (mask_m[40] << 10) | (mask_m[41] << 8)
+ | (mask_m[42] << 6) | (mask_m[43] << 4)
+ | (mask_m[44] << 2) | (mask_m[45] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+ tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
+ | (mask_m[18] << 26) | (mask_m[18] << 24)
+ | (mask_m[20] << 22) | (mask_m[20] << 20)
+ | (mask_m[22] << 18) | (mask_m[22] << 16)
+ | (mask_m[24] << 14) | (mask_m[24] << 12)
+ | (mask_m[25] << 10) | (mask_m[26] << 8)
+ | (mask_m[27] << 6) | (mask_m[28] << 4)
+ | (mask_m[29] << 2) | (mask_m[30] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+ tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
+ | (mask_m[2] << 26) | (mask_m[3] << 24)
+ | (mask_m[4] << 22) | (mask_m[5] << 20)
+ | (mask_m[6] << 18) | (mask_m[7] << 16)
+ | (mask_m[8] << 14) | (mask_m[9] << 12)
+ | (mask_m[10] << 10) | (mask_m[11] << 8)
+ | (mask_m[12] << 6) | (mask_m[13] << 4)
+ | (mask_m[14] << 2) | (mask_m[15] << 0);
+ REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+ tmp_mask = (mask_p[15] << 28)
+ | (mask_p[14] << 26) | (mask_p[13] << 24)
+ | (mask_p[12] << 22) | (mask_p[11] << 20)
+ | (mask_p[10] << 18) | (mask_p[9] << 16)
+ | (mask_p[8] << 14) | (mask_p[7] << 12)
+ | (mask_p[6] << 10) | (mask_p[5] << 8)
+ | (mask_p[4] << 6) | (mask_p[3] << 4)
+ | (mask_p[2] << 2) | (mask_p[1] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+ tmp_mask = (mask_p[30] << 28)
+ | (mask_p[29] << 26) | (mask_p[28] << 24)
+ | (mask_p[27] << 22) | (mask_p[26] << 20)
+ | (mask_p[25] << 18) | (mask_p[24] << 16)
+ | (mask_p[23] << 14) | (mask_p[22] << 12)
+ | (mask_p[21] << 10) | (mask_p[20] << 8)
+ | (mask_p[19] << 6) | (mask_p[18] << 4)
+ | (mask_p[17] << 2) | (mask_p[16] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+ tmp_mask = (mask_p[45] << 28)
+ | (mask_p[44] << 26) | (mask_p[43] << 24)
+ | (mask_p[42] << 22) | (mask_p[41] << 20)
+ | (mask_p[40] << 18) | (mask_p[39] << 16)
+ | (mask_p[38] << 14) | (mask_p[37] << 12)
+ | (mask_p[36] << 10) | (mask_p[35] << 8)
+ | (mask_p[34] << 6) | (mask_p[33] << 4)
+ | (mask_p[32] << 2) | (mask_p[31] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+ tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
+ | (mask_p[59] << 26) | (mask_p[58] << 24)
+ | (mask_p[57] << 22) | (mask_p[56] << 20)
+ | (mask_p[55] << 18) | (mask_p[54] << 16)
+ | (mask_p[53] << 14) | (mask_p[52] << 12)
+ | (mask_p[51] << 10) | (mask_p[50] << 8)
+ | (mask_p[49] << 6) | (mask_p[48] << 4)
+ | (mask_p[47] << 2) | (mask_p[46] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+}
+
+static void ar9002_olc_init(struct ath_hw *ah)
+{
+ u32 i;
+
+ if (!OLC_FOR_AR9280_20_LATER)
+ return;
+
+ if (OLC_FOR_AR9287_10_LATER) {
+ REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9,
+ AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL);
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0,
+ AR9287_AN_TXPC0_TXPCMODE,
+ AR9287_AN_TXPC0_TXPCMODE_S,
+ AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE);
+ udelay(100);
+ } else {
+ for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
+ ah->originalGain[i] =
+ MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
+ AR_PHY_TX_GAIN);
+ ah->PDADCdelta = 0;
+ }
+}
+
+static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ u32 pll;
+
+ pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
+
+ if (chan && IS_CHAN_HALF_RATE(chan))
+ pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
+ else if (chan && IS_CHAN_QUARTER_RATE(chan))
+ pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
+
+ if (chan && IS_CHAN_5GHZ(chan)) {
+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+ pll = 0x142c;
+ else if (AR_SREV_9280_20(ah))
+ pll = 0x2850;
+ else
+ pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
+ } else {
+ pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
+ }
+
+ return pll;
+}
+
+static void ar9002_hw_do_getnf(struct ath_hw *ah,
+ int16_t nfarray[NUM_NF_READINGS])
+{
+ int16_t nf;
+
+ nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
+ nfarray[0] = sign_extend32(nf, 8);
+
+ nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
+ if (IS_CHAN_HT40(ah->curchan))
+ nfarray[3] = sign_extend32(nf, 8);
+
+ if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+ return;
+
+ nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR);
+ nfarray[1] = sign_extend32(nf, 8);
+
+ nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR);
+ if (IS_CHAN_HT40(ah->curchan))
+ nfarray[4] = sign_extend32(nf, 8);
+}
+
+static void ar9002_hw_set_nf_limits(struct ath_hw *ah)
+{
+ if (AR_SREV_9285(ah)) {
+ ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ;
+ ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ;
+ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ;
+ } else if (AR_SREV_9287(ah)) {
+ ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ;
+ ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ;
+ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9287_2GHZ;
+ } else if (AR_SREV_9271(ah)) {
+ ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ;
+ ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ;
+ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9271_2GHZ;
+ } else {
+ ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ;
+ ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ;
+ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9280_2GHZ;
+ ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ;
+ ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ;
+ ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9280_5GHZ;
+ }
+}
+
+static void ar9002_hw_antdiv_comb_conf_get(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf)
+{
+ u32 regval;
+
+ regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+ antconf->main_lna_conf = (regval & AR_PHY_9285_ANT_DIV_MAIN_LNACONF) >>
+ AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S;
+ antconf->alt_lna_conf = (regval & AR_PHY_9285_ANT_DIV_ALT_LNACONF) >>
+ AR_PHY_9285_ANT_DIV_ALT_LNACONF_S;
+ antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >>
+ AR_PHY_9285_FAST_DIV_BIAS_S;
+ antconf->lna1_lna2_delta = -3;
+ antconf->div_group = 0;
+}
+
+static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf)
+{
+ u32 regval;
+
+ regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+ regval &= ~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF |
+ AR_PHY_9285_ANT_DIV_ALT_LNACONF |
+ AR_PHY_9285_FAST_DIV_BIAS);
+ regval |= ((antconf->main_lna_conf << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S)
+ & AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
+ regval |= ((antconf->alt_lna_conf << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S)
+ & AR_PHY_9285_ANT_DIV_ALT_LNACONF);
+ regval |= ((antconf->fast_div_bias << AR_PHY_9285_FAST_DIV_BIAS_S)
+ & AR_PHY_9285_FAST_DIV_BIAS);
+
+ REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval);
+}
+
+void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
+{
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+ struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+
+ priv_ops->set_rf_regs = NULL;
+ priv_ops->rf_alloc_ext_banks = NULL;
+ priv_ops->rf_free_ext_banks = NULL;
+ priv_ops->rf_set_freq = ar9002_hw_set_channel;
+ priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate;
+ priv_ops->olc_init = ar9002_olc_init;
+ priv_ops->compute_pll_control = ar9002_hw_compute_pll_control;
+ priv_ops->do_getnf = ar9002_hw_do_getnf;
+
+ ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get;
+ ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set;
+
+ ar9002_hw_set_nf_limits(ah);
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_calib.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_calib.c
new file mode 100644
index 00000000..c37168bd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_calib.c
@@ -0,0 +1,932 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+
+#include "hw.h"
+#include "hw-ops.h"
+#include "ar9003_phy.h"
+
+#define MAX_MEASUREMENT 8
+#define MAX_MAG_DELTA 11
+#define MAX_PHS_DELTA 10
+
+struct coeff {
+ int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
+ int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
+ int iqc_coeff[2];
+};
+
+enum ar9003_cal_types {
+ IQ_MISMATCH_CAL = BIT(0),
+ TEMP_COMP_CAL = BIT(1),
+};
+
+static void ar9003_hw_setup_calibration(struct ath_hw *ah,
+ struct ath9k_cal_list *currCal)
+{
+ /* Select calibration to run */
+ switch (currCal->calData->calType) {
+ case IQ_MISMATCH_CAL:
+ /*
+ * Start calibration with
+ * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
+ */
+ REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+ AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
+ currCal->calData->calCountMax);
+ REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
+
+ DBG2("ath9k: "
+ "starting IQ Mismatch Calibration\n");
+
+ /* Kick-off cal */
+ REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
+ break;
+ case TEMP_COMP_CAL:
+ REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
+ AR_PHY_65NM_CH0_THERM_LOCAL, 1);
+ REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
+ AR_PHY_65NM_CH0_THERM_START, 1);
+
+ DBG2("ath9k: "
+ "starting Temperature Compensation Calibration\n");
+ break;
+ }
+}
+
+/*
+ * Generic calibration routine.
+ * Recalibrate the lower PHY chips to account for temperature/environment
+ * changes.
+ */
+static int ar9003_hw_per_calibration(struct ath_hw *ah,
+ struct ath9k_channel *ichan __unused,
+ u8 rxchainmask,
+ struct ath9k_cal_list *currCal)
+{
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
+ /* Cal is assumed not done until explicitly set below */
+ int iscaldone = 0;
+
+ /* Calibration in progress. */
+ if (currCal->calState == CAL_RUNNING) {
+ /* Check to see if it has finished. */
+ if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) {
+ /*
+ * Accumulate cal measures for active chains
+ */
+ currCal->calData->calCollect(ah);
+ ah->cal_samples++;
+
+ if (ah->cal_samples >=
+ currCal->calData->calNumSamples) {
+ unsigned int i, numChains = 0;
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (rxchainmask & (1 << i))
+ numChains++;
+ }
+
+ /*
+ * Process accumulated data
+ */
+ currCal->calData->calPostProc(ah, numChains);
+
+ /* Calibration has finished. */
+ caldata->CalValid |= currCal->calData->calType;
+ currCal->calState = CAL_DONE;
+ iscaldone = 1;
+ } else {
+ /*
+ * Set-up collection of another sub-sample until we
+ * get desired number
+ */
+ ar9003_hw_setup_calibration(ah, currCal);
+ }
+ }
+ } else if (!(caldata->CalValid & currCal->calData->calType)) {
+ /* If current cal is marked invalid in channel, kick it off */
+ ath9k_hw_reset_calibration(ah, currCal);
+ }
+
+ return iscaldone;
+}
+
+static int ar9003_hw_calibrate(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 rxchainmask,
+ int longcal)
+{
+ int iscaldone = 1;
+ struct ath9k_cal_list *currCal = ah->cal_list_curr;
+
+ /*
+ * For given calibration:
+ * 1. Call generic cal routine
+ * 2. When this cal is done (isCalDone) if we have more cals waiting
+ * (eg after reset), mask this to upper layers by not propagating
+ * isCalDone if it is set to TRUE.
+ * Instead, change isCalDone to FALSE and setup the waiting cal(s)
+ * to be run.
+ */
+ if (currCal &&
+ (currCal->calState == CAL_RUNNING ||
+ currCal->calState == CAL_WAITING)) {
+ iscaldone = ar9003_hw_per_calibration(ah, chan,
+ rxchainmask, currCal);
+ if (iscaldone) {
+ ah->cal_list_curr = currCal = currCal->calNext;
+
+ if (currCal->calState == CAL_WAITING) {
+ iscaldone = 0;
+ ath9k_hw_reset_calibration(ah, currCal);
+ }
+ }
+ }
+
+ /* Do NF cal only at longer intervals */
+ if (longcal) {
+ /*
+ * Get the value from the previous NF cal and update
+ * history buffer.
+ */
+ ath9k_hw_getnf(ah, chan);
+
+ /*
+ * Load the NF from history buffer of the current channel.
+ * NF is slow time-variant, so it is OK to use a historical
+ * value.
+ */
+ ath9k_hw_loadnf(ah, ah->curchan);
+
+ /* start NF calibration, without updating BB NF register */
+ ath9k_hw_start_nfcal(ah, 0);
+ }
+
+ return iscaldone;
+}
+
+static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
+{
+ int i;
+
+ /* Accumulate IQ cal measures for active chains */
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (ah->txchainmask & BIT(i)) {
+ ah->totalPowerMeasI[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+ ah->totalPowerMeasQ[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+ ah->totalIqCorrMeas[i] +=
+ (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+ DBG2("ath9k: "
+ "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
+ ah->cal_samples, i, ah->totalPowerMeasI[i],
+ ah->totalPowerMeasQ[i],
+ ah->totalIqCorrMeas[i]);
+ }
+ }
+}
+
+static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
+{
+ u32 powerMeasQ, powerMeasI, iqCorrMeas;
+ u32 qCoffDenom, iCoffDenom;
+ int32_t qCoff, iCoff;
+ int iqCorrNeg, i;
+ static const uint32_t offset_array[3] = {
+ AR_PHY_RX_IQCAL_CORR_B0,
+ AR_PHY_RX_IQCAL_CORR_B1,
+ AR_PHY_RX_IQCAL_CORR_B2,
+ };
+
+ for (i = 0; i < numChains; i++) {
+ powerMeasI = ah->totalPowerMeasI[i];
+ powerMeasQ = ah->totalPowerMeasQ[i];
+ iqCorrMeas = ah->totalIqCorrMeas[i];
+
+ DBG2("ath9k: "
+ "Starting IQ Cal and Correction for Chain %d\n",
+ i);
+
+ DBG2("ath9k: "
+ "Orignal: Chn %diq_corr_meas = 0x%08x\n",
+ i, ah->totalIqCorrMeas[i]);
+
+ iqCorrNeg = 0;
+
+ if (iqCorrMeas > 0x80000000) {
+ iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
+ iqCorrNeg = 1;
+ }
+
+ DBG2("ath9k: "
+ "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
+ DBG2("ath9k: "
+ "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
+ DBG2("ath9k: iqCorrNeg is 0x%08x\n",
+ iqCorrNeg);
+
+ iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
+ qCoffDenom = powerMeasQ / 64;
+
+ if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
+ iCoff = iqCorrMeas / iCoffDenom;
+ qCoff = powerMeasI / qCoffDenom - 64;
+ DBG2("ath9k: "
+ "Chn %d iCoff = 0x%08x\n", i, iCoff);
+ DBG2("ath9k: "
+ "Chn %d qCoff = 0x%08x\n", i, qCoff);
+
+ /* Force bounds on iCoff */
+ if (iCoff >= 63)
+ iCoff = 63;
+ else if (iCoff <= -63)
+ iCoff = -63;
+
+ /* Negate iCoff if iqCorrNeg == 0 */
+ if (iqCorrNeg == 0x0)
+ iCoff = -iCoff;
+
+ /* Force bounds on qCoff */
+ if (qCoff >= 63)
+ qCoff = 63;
+ else if (qCoff <= -63)
+ qCoff = -63;
+
+ iCoff = iCoff & 0x7f;
+ qCoff = qCoff & 0x7f;
+
+ DBG2("ath9k: "
+ "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
+ i, iCoff, qCoff);
+ DBG2("ath9k: "
+ "Register offset (0x%04x) before update = 0x%x\n",
+ offset_array[i],
+ REG_READ(ah, offset_array[i]));
+
+ REG_RMW_FIELD(ah, offset_array[i],
+ AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
+ iCoff);
+ REG_RMW_FIELD(ah, offset_array[i],
+ AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
+ qCoff);
+ DBG2("ath9k: "
+ "Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n",
+ offset_array[i],
+ AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
+ REG_READ(ah, offset_array[i]));
+ DBG2("ath9k: "
+ "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n",
+ offset_array[i],
+ AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
+ REG_READ(ah, offset_array[i]));
+
+ DBG2("ath9k: "
+ "IQ Cal and Correction done for Chain %d\n", i);
+ }
+ }
+
+ REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
+ AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
+ DBG2("ath9k: "
+ "IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n",
+ (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
+ AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
+ REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
+}
+
+static const struct ath9k_percal_data iq_cal_single_sample = {
+ IQ_MISMATCH_CAL,
+ MIN_CAL_SAMPLES,
+ PER_MAX_LOG_COUNT,
+ ar9003_hw_iqcal_collect,
+ ar9003_hw_iqcalibrate
+};
+
+static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
+{
+ ah->iq_caldata.calData = &iq_cal_single_sample;
+}
+
+/*
+ * solve 4x4 linear equation used in loopback iq cal.
+ */
+static int ar9003_hw_solve_iq_cal(struct ath_hw *ah __unused,
+ s32 sin_2phi_1,
+ s32 cos_2phi_1,
+ s32 sin_2phi_2,
+ s32 cos_2phi_2,
+ s32 mag_a0_d0,
+ s32 phs_a0_d0,
+ s32 mag_a1_d0,
+ s32 phs_a1_d0,
+ s32 solved_eq[])
+{
+ s32 f1 = cos_2phi_1 - cos_2phi_2,
+ f3 = sin_2phi_1 - sin_2phi_2,
+ f2;
+ s32 mag_tx, phs_tx, mag_rx, phs_rx;
+ const s32 result_shift = 1 << 15;
+
+ f2 = (f1 * f1 + f3 * f3) / result_shift;
+
+ if (!f2) {
+ DBG("ath9k: Divide by 0\n");
+ return 0;
+ }
+
+ /* mag mismatch, tx */
+ mag_tx = f1 * (mag_a0_d0 - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0);
+ /* phs mismatch, tx */
+ phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0);
+
+ mag_tx = (mag_tx / f2);
+ phs_tx = (phs_tx / f2);
+
+ /* mag mismatch, rx */
+ mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) /
+ result_shift;
+ /* phs mismatch, rx */
+ phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) /
+ result_shift;
+
+ solved_eq[0] = mag_tx;
+ solved_eq[1] = phs_tx;
+ solved_eq[2] = mag_rx;
+ solved_eq[3] = phs_rx;
+
+ return 1;
+}
+
+static s32 ar9003_hw_find_mag_approx(struct ath_hw *ah __unused, s32 in_re, s32 in_im)
+{
+ s32 abs_i = abs(in_re),
+ abs_q = abs(in_im),
+ max_abs, min_abs;
+
+ if (abs_i > abs_q) {
+ max_abs = abs_i;
+ min_abs = abs_q;
+ } else {
+ max_abs = abs_q;
+ min_abs = abs_i;
+ }
+
+ return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4);
+}
+
+#define DELPT 32
+
+static int ar9003_hw_calc_iq_corr(struct ath_hw *ah,
+ s32 chain_idx,
+ const s32 iq_res[],
+ s32 iqc_coeff[])
+{
+ s32 i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0,
+ i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1,
+ i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0,
+ i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1;
+ s32 mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1,
+ phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1,
+ sin_2phi_1, cos_2phi_1,
+ sin_2phi_2, cos_2phi_2;
+ s32 mag_tx, phs_tx, mag_rx, phs_rx;
+ s32 solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx,
+ q_q_coff, q_i_coff;
+ const s32 res_scale = 1 << 15;
+ const s32 delpt_shift = 1 << 8;
+ s32 mag1, mag2;
+
+ i2_m_q2_a0_d0 = iq_res[0] & 0xfff;
+ i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff;
+ iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8);
+
+ if (i2_m_q2_a0_d0 > 0x800)
+ i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1);
+
+ if (i2_p_q2_a0_d0 > 0x800)
+ i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1);
+
+ if (iq_corr_a0_d0 > 0x800)
+ iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1);
+
+ i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff;
+ i2_p_q2_a0_d1 = (iq_res[2] & 0xfff);
+ iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff;
+
+ if (i2_m_q2_a0_d1 > 0x800)
+ i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
+
+ if (i2_p_q2_a0_d1 > 0x800)
+ i2_p_q2_a0_d1 = -((0xfff - i2_p_q2_a0_d1) + 1);
+
+ if (iq_corr_a0_d1 > 0x800)
+ iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
+
+ i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8);
+ i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff;
+ iq_corr_a1_d0 = iq_res[4] & 0xfff;
+
+ if (i2_m_q2_a1_d0 > 0x800)
+ i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1);
+
+ if (i2_p_q2_a1_d0 > 0x800)
+ i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1);
+
+ if (iq_corr_a1_d0 > 0x800)
+ iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1);
+
+ i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff;
+ i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8);
+ iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff;
+
+ if (i2_m_q2_a1_d1 > 0x800)
+ i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1);
+
+ if (i2_p_q2_a1_d1 > 0x800)
+ i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1);
+
+ if (iq_corr_a1_d1 > 0x800)
+ iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1);
+
+ if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
+ (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
+ DBG("ath9k: "
+ "Divide by 0:\n"
+ "a0_d0=%d\n"
+ "a0_d1=%d\n"
+ "a2_d0=%d\n"
+ "a1_d1=%d\n",
+ i2_p_q2_a0_d0, i2_p_q2_a0_d1,
+ i2_p_q2_a1_d0, i2_p_q2_a1_d1);
+ return 0;
+ }
+
+ mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0;
+ phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0;
+
+ mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1;
+ phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1;
+
+ mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0;
+ phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0;
+
+ mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1;
+ phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1;
+
+ /* w/o analog phase shift */
+ sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT);
+ /* w/o analog phase shift */
+ cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT);
+ /* w/ analog phase shift */
+ sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT);
+ /* w/ analog phase shift */
+ cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT);
+
+ /*
+ * force sin^2 + cos^2 = 1;
+ * find magnitude by approximation
+ */
+ mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1);
+ mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
+
+ if ((mag1 == 0) || (mag2 == 0)) {
+ DBG("ath9k: "
+ "Divide by 0: mag1=%d, mag2=%d\n",
+ mag1, mag2);
+ return 0;
+ }
+
+ /* normalization sin and cos by mag */
+ sin_2phi_1 = (sin_2phi_1 * res_scale / mag1);
+ cos_2phi_1 = (cos_2phi_1 * res_scale / mag1);
+ sin_2phi_2 = (sin_2phi_2 * res_scale / mag2);
+ cos_2phi_2 = (cos_2phi_2 * res_scale / mag2);
+
+ /* calculate IQ mismatch */
+ if (!ar9003_hw_solve_iq_cal(ah,
+ sin_2phi_1, cos_2phi_1,
+ sin_2phi_2, cos_2phi_2,
+ mag_a0_d0, phs_a0_d0,
+ mag_a1_d0,
+ phs_a1_d0, solved_eq)) {
+ DBG("ath9k: "
+ "Call to ar9003_hw_solve_iq_cal() failed.\n");
+ return 0;
+ }
+
+ mag_tx = solved_eq[0];
+ phs_tx = solved_eq[1];
+ mag_rx = solved_eq[2];
+ phs_rx = solved_eq[3];
+
+ DBG2("ath9k: "
+ "chain %d: mag mismatch=%d phase mismatch=%d\n",
+ chain_idx, mag_tx/res_scale, phs_tx/res_scale);
+
+ if (res_scale == mag_tx) {
+ DBG("ath9k: "
+ "Divide by 0: mag_tx=%d, res_scale=%d\n",
+ mag_tx, res_scale);
+ return 0;
+ }
+
+ /* calculate and quantize Tx IQ correction factor */
+ mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx);
+ phs_corr_tx = -phs_tx;
+
+ q_q_coff = (mag_corr_tx * 128 / res_scale);
+ q_i_coff = (phs_corr_tx * 256 / res_scale);
+
+ DBG2("ath9k: "
+ "tx chain %d: mag corr=%d phase corr=%d\n",
+ chain_idx, q_q_coff, q_i_coff);
+
+ if (q_i_coff < -63)
+ q_i_coff = -63;
+ if (q_i_coff > 63)
+ q_i_coff = 63;
+ if (q_q_coff < -63)
+ q_q_coff = -63;
+ if (q_q_coff > 63)
+ q_q_coff = 63;
+
+ iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
+
+ DBG2("ath9k: "
+ "tx chain %d: iq corr coeff=%x\n",
+ chain_idx, iqc_coeff[0]);
+
+ if (-mag_rx == res_scale) {
+ DBG("ath9k: "
+ "Divide by 0: mag_rx=%d, res_scale=%d\n",
+ mag_rx, res_scale);
+ return 0;
+ }
+
+ /* calculate and quantize Rx IQ correction factors */
+ mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx);
+ phs_corr_rx = -phs_rx;
+
+ q_q_coff = (mag_corr_rx * 128 / res_scale);
+ q_i_coff = (phs_corr_rx * 256 / res_scale);
+
+ DBG("ath9k: "
+ "rx chain %d: mag corr=%d phase corr=%d\n",
+ chain_idx, q_q_coff, q_i_coff);
+
+ if (q_i_coff < -63)
+ q_i_coff = -63;
+ if (q_i_coff > 63)
+ q_i_coff = 63;
+ if (q_q_coff < -63)
+ q_q_coff = -63;
+ if (q_q_coff > 63)
+ q_q_coff = 63;
+
+ iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
+
+ DBG2("ath9k: "
+ "rx chain %d: iq corr coeff=%x\n",
+ chain_idx, iqc_coeff[1]);
+
+ return 1;
+}
+
+static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
+ int max_delta)
+{
+ int mp_max = -64, max_idx = 0;
+ int mp_min = 63, min_idx = 0;
+ int mp_avg = 0, i, outlier_idx = 0;
+
+ /* find min/max mismatch across all calibrated gains */
+ for (i = 0; i < nmeasurement; i++) {
+ mp_avg += mp_coeff[i];
+ if (mp_coeff[i] > mp_max) {
+ mp_max = mp_coeff[i];
+ max_idx = i;
+ } else if (mp_coeff[i] < mp_min) {
+ mp_min = mp_coeff[i];
+ min_idx = i;
+ }
+ }
+
+ /* find average (exclude max abs value) */
+ for (i = 0; i < nmeasurement; i++) {
+ if ((abs(mp_coeff[i]) < abs(mp_max)) ||
+ (abs(mp_coeff[i]) < abs(mp_min)))
+ mp_avg += mp_coeff[i];
+ }
+ mp_avg /= (nmeasurement - 1);
+
+ /* detect outlier */
+ if (abs(mp_max - mp_min) > max_delta) {
+ if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg))
+ outlier_idx = max_idx;
+ else
+ outlier_idx = min_idx;
+ }
+ mp_coeff[outlier_idx] = mp_avg;
+}
+
+static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
+ u8 num_chains,
+ struct coeff *coeff)
+{
+ int i, im, nmeasurement;
+ u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
+
+ memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
+ for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
+ tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
+ AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
+ if (!AR_SREV_9485(ah)) {
+ tx_corr_coeff[i * 2][1] =
+ tx_corr_coeff[(i * 2) + 1][1] =
+ AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
+
+ tx_corr_coeff[i * 2][2] =
+ tx_corr_coeff[(i * 2) + 1][2] =
+ AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
+ }
+ }
+
+ /* Load the average of 2 passes */
+ for (i = 0; i < num_chains; i++) {
+ nmeasurement = REG_READ_FIELD(ah,
+ AR_PHY_TX_IQCAL_STATUS_B0,
+ AR_PHY_CALIBRATED_GAINS_0);
+
+ if (nmeasurement > MAX_MEASUREMENT)
+ nmeasurement = MAX_MEASUREMENT;
+
+ /* detect outlier only if nmeasurement > 1 */
+ if (nmeasurement > 1) {
+ /* Detect magnitude outlier */
+ ar9003_hw_detect_outlier(coeff->mag_coeff[i],
+ nmeasurement, MAX_MAG_DELTA);
+
+ /* Detect phase outlier */
+ ar9003_hw_detect_outlier(coeff->phs_coeff[i],
+ nmeasurement, MAX_PHS_DELTA);
+ }
+
+ for (im = 0; im < nmeasurement; im++) {
+
+ coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
+ ((coeff->phs_coeff[i][im] & 0x7f) << 7);
+
+ if ((im % 2) == 0)
+ REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+ AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
+ coeff->iqc_coeff[0]);
+ else
+ REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+ AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
+ coeff->iqc_coeff[0]);
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
+ AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
+ AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
+
+ return;
+
+}
+
+static int ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
+{
+ u8 tx_gain_forced;
+
+ tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+ AR_PHY_TXGAIN_FORCE);
+ if (tx_gain_forced)
+ REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+ AR_PHY_TXGAIN_FORCE, 0);
+
+ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
+ AR_PHY_TX_IQCAL_START_DO_CAL, 1);
+
+ if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
+ AR_PHY_TX_IQCAL_START_DO_CAL, 0,
+ AH_WAIT_TIMEOUT)) {
+ DBG2("ath9k: "
+ "Tx IQ Cal is not completed.\n");
+ return 0;
+ }
+ return 1;
+}
+
+static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
+{
+ const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
+ AR_PHY_TX_IQCAL_STATUS_B0,
+ AR_PHY_TX_IQCAL_STATUS_B1,
+ AR_PHY_TX_IQCAL_STATUS_B2,
+ };
+ const uint32_t chan_info_tab[] = {
+ AR_PHY_CHAN_INFO_TAB_0,
+ AR_PHY_CHAN_INFO_TAB_1,
+ AR_PHY_CHAN_INFO_TAB_2,
+ };
+ struct coeff coeff;
+ s32 iq_res[6];
+ u8 num_chains = 0;
+ int i, im, j;
+ int nmeasurement;
+
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (ah->txchainmask & (1 << i))
+ num_chains++;
+ }
+
+ for (i = 0; i < num_chains; i++) {
+ nmeasurement = REG_READ_FIELD(ah,
+ AR_PHY_TX_IQCAL_STATUS_B0,
+ AR_PHY_CALIBRATED_GAINS_0);
+ if (nmeasurement > MAX_MEASUREMENT)
+ nmeasurement = MAX_MEASUREMENT;
+
+ for (im = 0; im < nmeasurement; im++) {
+ DBG2("ath9k: "
+ "Doing Tx IQ Cal for chain %d.\n", i);
+
+ if (REG_READ(ah, txiqcal_status[i]) &
+ AR_PHY_TX_IQCAL_STATUS_FAILED) {
+ DBG("ath9k: "
+ "Tx IQ Cal failed for chain %d.\n", i);
+ goto tx_iqcal_fail;
+ }
+
+ for (j = 0; j < 3; j++) {
+ u32 idx = 2 * j, offset = 4 * (3 * im + j);
+
+ REG_RMW_FIELD(ah,
+ AR_PHY_CHAN_INFO_MEMORY,
+ AR_PHY_CHAN_INFO_TAB_S2_READ,
+ 0);
+
+ /* 32 bits */
+ iq_res[idx] = REG_READ(ah,
+ chan_info_tab[i] +
+ offset);
+
+ REG_RMW_FIELD(ah,
+ AR_PHY_CHAN_INFO_MEMORY,
+ AR_PHY_CHAN_INFO_TAB_S2_READ,
+ 1);
+
+ /* 16 bits */
+ iq_res[idx + 1] = 0xffff & REG_READ(ah,
+ chan_info_tab[i] + offset);
+
+ DBG2("ath9k: "
+ "IQ RES[%d]=0x%x"
+ "IQ_RES[%d]=0x%x\n",
+ idx, iq_res[idx], idx + 1,
+ iq_res[idx + 1]);
+ }
+
+ if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
+ coeff.iqc_coeff)) {
+ DBG("ath9k: "
+ "Failed in calculation of \
+ IQ correction.\n");
+ goto tx_iqcal_fail;
+ }
+
+ coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
+ coeff.phs_coeff[i][im] =
+ (coeff.iqc_coeff[0] >> 7) & 0x7f;
+
+ if (coeff.mag_coeff[i][im] > 63)
+ coeff.mag_coeff[i][im] -= 128;
+ if (coeff.phs_coeff[i][im] > 63)
+ coeff.phs_coeff[i][im] -= 128;
+ }
+ }
+ ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff);
+
+ return;
+
+tx_iqcal_fail:
+ DBG("ath9k: Tx IQ Cal failed\n");
+ return;
+}
+static int ar9003_hw_init_cal(struct ath_hw *ah,
+ struct ath9k_channel *chan __unused)
+{
+ struct ath9k_hw_capabilities *pCap = &ah->caps;
+ int val;
+ int txiqcal_done = 0;
+
+ val = REG_READ(ah, AR_ENT_OTP);
+ DBG2("ath9k: ath9k: AR_ENT_OTP 0x%x\n", val);
+
+ /* Configure rx/tx chains before running AGC/TxiQ cals */
+ if (val & AR_ENT_OTP_CHAIN2_DISABLE)
+ ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
+ else
+ ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask,
+ pCap->tx_chainmask);
+
+ /* Do Tx IQ Calibration */
+ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
+ AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
+ DELPT);
+
+ /*
+ * For AR9485 or later chips, TxIQ cal runs as part of
+ * AGC calibration
+ */
+ if (AR_SREV_9485_OR_LATER(ah))
+ txiqcal_done = 1;
+ else {
+ txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+ udelay(5);
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+ }
+
+ /* Calibrate the AGC */
+ REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+ REG_READ(ah, AR_PHY_AGC_CONTROL) |
+ AR_PHY_AGC_CONTROL_CAL);
+
+ /* Poll for offset calibration complete */
+ if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
+ 0, AH_WAIT_TIMEOUT)) {
+ DBG("ath9k: "
+ "offset calibration failed to complete in 1ms; noisy environment?\n");
+ return 0;
+ }
+
+ if (txiqcal_done)
+ ar9003_hw_tx_iq_cal_post_proc(ah);
+
+ /* Revert chainmasks to their original values before NF cal */
+ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+
+ ath9k_hw_start_nfcal(ah, 1);
+
+ /* Initialize list pointers */
+ ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
+ ah->supp_cals = IQ_MISMATCH_CAL;
+
+ if (ah->supp_cals & IQ_MISMATCH_CAL) {
+ INIT_CAL(&ah->iq_caldata);
+ INSERT_CAL(ah, &ah->iq_caldata);
+ DBG2("ath9k: "
+ "enabling IQ Calibration.\n");
+ }
+
+ if (ah->supp_cals & TEMP_COMP_CAL) {
+ INIT_CAL(&ah->tempCompCalData);
+ INSERT_CAL(ah, &ah->tempCompCalData);
+ DBG2("ath9k: "
+ "enabling Temperature Compensation Calibration.\n");
+ }
+
+ /* Initialize current pointer to first element in list */
+ ah->cal_list_curr = ah->cal_list;
+
+ if (ah->cal_list_curr)
+ ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
+
+ if (ah->caldata)
+ ah->caldata->CalValid = 0;
+
+ return 1;
+}
+
+void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
+{
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+ struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+
+ priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
+ priv_ops->init_cal = ar9003_hw_init_cal;
+ priv_ops->setup_calibration = ar9003_hw_setup_calibration;
+
+ ops->calibrate = ar9003_hw_calibrate;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_eeprom.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_eeprom.c
new file mode 100644
index 00000000..95e54b9b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_eeprom.c
@@ -0,0 +1,5005 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+#include <ipxe/malloc.h>
+
+#include "hw.h"
+#include "ar9003_phy.h"
+#include "ar9003_eeprom.h"
+
+#define COMP_HDR_LEN 4
+#define COMP_CKSUM_LEN 2
+
+#define AR_CH0_TOP (0x00016288)
+#define AR_CH0_TOP_XPABIASLVL (0x300)
+#define AR_CH0_TOP_XPABIASLVL_S (8)
+
+#define AR_CH0_THERM (0x00016290)
+#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
+#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
+#define AR_CH0_THERM_XPASHORT2GND 0x4
+#define AR_CH0_THERM_XPASHORT2GND_S 2
+
+#define AR_SWITCH_TABLE_COM_ALL (0xffff)
+#define AR_SWITCH_TABLE_COM_ALL_S (0)
+
+#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM2_ALL_S (0)
+
+#define AR_SWITCH_TABLE_ALL (0xfff)
+#define AR_SWITCH_TABLE_ALL_S (0)
+
+#define LE16(x) (uint16_t)(x)
+#define LE32(x) (uint32_t)(x)
+
+/* Local defines to distinguish between extension and control CTL's */
+#define EXT_ADDITIVE (0x8000)
+#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
+#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
+#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
+#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
+#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */
+#define PWRINCR_3_TO_1_CHAIN 9 /* 10*log(3)*2 */
+#define PWRINCR_3_TO_2_CHAIN 3 /* floor(10*log(3/2)*2) */
+#define PWRINCR_2_TO_1_CHAIN 6 /* 10*log(2)*2 */
+
+#define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */
+#define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */
+
+#define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6))
+
+#define EEPROM_DATA_LEN_9485 1088
+
+static int ar9003_hw_power_interpolate(int32_t x,
+ int32_t *px, int32_t *py, uint16_t np);
+
+
+static const struct ar9300_eeprom ar9300_default = {
+ .eepromVersion = 2,
+ .templateVersion = 2,
+ .macAddr = {1, 2, 3, 4, 5, 6},
+ .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ .baseEepHeader = {
+ .regDmn = { LE16(0), LE16(0x1f) },
+ .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
+ .opCapFlags = {
+ .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
+ .eepMisc = 0,
+ },
+ .rfSilent = 0,
+ .blueToothOptions = 0,
+ .deviceCap = 0,
+ .deviceType = 5, /* takes lower byte in eeprom location */
+ .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+ .params_for_tuning_caps = {0, 0},
+ .featureEnable = 0x0c,
+ /*
+ * bit0 - enable tx temp comp - disabled
+ * bit1 - enable tx volt comp - disabled
+ * bit2 - enable fastClock - enabled
+ * bit3 - enable doubling - enabled
+ * bit4 - enable internal regulator - disabled
+ * bit5 - enable pa predistortion - disabled
+ */
+ .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+ .eepromWriteEnableGpio = 3,
+ .wlanDisableGpio = 0,
+ .wlanLedGpio = 8,
+ .rxBandSelectGpio = 0xff,
+ .txrxgain = 0,
+ .swreg = 0,
+ },
+ .modalHeader2G = {
+ /* ar9300_modal_eep_header 2g */
+ /* 4 idle,t1,t2,b(4 bits per setting) */
+ .antCtrlCommon = LE32(0x110),
+ /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+ .antCtrlCommon2 = LE32(0x22222),
+
+ /*
+ * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+ * rx1, rx12, b (2 bits each)
+ */
+ .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
+
+ /*
+ * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
+ * for ar9280 (0xa20c/b20c 5:0)
+ */
+ .xatten1DB = {0, 0, 0},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for ar9280 (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0, 0, 0},
+ .tempSlope = 36,
+ .voltSlope = 0,
+
+ /*
+ * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+ * channels in usual fbin coding format
+ */
+ .spurChans = {0, 0, 0, 0, 0},
+
+ /*
+ * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+ * if the register is per chain
+ */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {1, 1, 1},/* 3 chain */
+ .db_stage2 = {1, 1, 1}, /* 3 chain */
+ .db_stage3 = {0, 0, 0},
+ .db_stage4 = {0, 0, 0},
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2c,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+ .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext1 = {
+ .ant_div_control = 0,
+ .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ },
+ .calFreqPier2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ /* ar9300_cal_data_per_freq_op_loop 2g */
+ .calPierData2G = {
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ },
+ .calTarget_freqbin_Cck = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2484, 1),
+ },
+ .calTarget_freqbin_2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT20 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT40 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTargetPowerCck = {
+ /* 1L-5L,5S,11L,11S */
+ { {36, 36, 36, 36} },
+ { {36, 36, 36, 36} },
+ },
+ .calTargetPower2G = {
+ /* 6-24,36,48,54 */
+ { {32, 32, 28, 24} },
+ { {32, 32, 28, 24} },
+ { {32, 32, 28, 24} },
+ },
+ .calTargetPower2GHT20 = {
+ { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
+ { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
+ { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
+ },
+ .calTargetPower2GHT40 = {
+ { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
+ { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
+ { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
+ },
+ .ctlIndex_2G = {
+ 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+ 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+ },
+ .ctl_freqbin_2G = {
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2457, 1),
+ FREQ2FBIN(2462, 1)
+ },
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+ {
+ FREQ2FBIN(2422, 1),
+ FREQ2FBIN(2427, 1),
+ FREQ2FBIN(2447, 1),
+ FREQ2FBIN(2452, 1)
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ },
+
+ {
+ /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ }
+ },
+ .ctlPowerData_2G = {
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+ { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ },
+ .modalHeader5G = {
+ /* 4 idle,t1,t2,b (4 bits per setting) */
+ .antCtrlCommon = LE32(0x110),
+ /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+ .antCtrlCommon2 = LE32(0x22222),
+ /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+ .antCtrlChain = {
+ LE16(0x000), LE16(0x000), LE16(0x000),
+ },
+ /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+ .xatten1DB = {0, 0, 0},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for merlin (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0, 0, 0},
+ .tempSlope = 68,
+ .voltSlope = 0,
+ /* spurChans spur channels in usual fbin coding format */
+ .spurChans = {0, 0, 0, 0, 0},
+ /* noiseFloorThreshCh Check if the register is per chain */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {3, 3, 3}, /* 3 chain */
+ .db_stage2 = {3, 3, 3}, /* 3 chain */
+ .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+ .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2d,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0c80c080),
+ .papdRateMaskHt40 = LE32(0x0080c080),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext2 = {
+ .tempSlopeLow = 0,
+ .tempSlopeHigh = 0,
+ .xatten1DBLow = {0, 0, 0},
+ .xatten1MarginLow = {0, 0, 0},
+ .xatten1DBHigh = {0, 0, 0},
+ .xatten1MarginHigh = {0, 0, 0}
+ },
+ .calFreqPier5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5725, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calPierData5G = {
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+
+ },
+ .calTarget_freqbin_5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5725, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT20 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5725, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT40 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5725, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTargetPower5G = {
+ /* 6-24,36,48,54 */
+ { {20, 20, 20, 10} },
+ { {20, 20, 20, 10} },
+ { {20, 20, 20, 10} },
+ { {20, 20, 20, 10} },
+ { {20, 20, 20, 10} },
+ { {20, 20, 20, 10} },
+ { {20, 20, 20, 10} },
+ { {20, 20, 20, 10} },
+ },
+ .calTargetPower5GHT20 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ },
+ .calTargetPower5GHT40 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+ },
+ .ctlIndex_5G = {
+ 0x10, 0x16, 0x18, 0x40, 0x46,
+ 0x48, 0x30, 0x36, 0x38
+ },
+ .ctl_freqbin_5G = {
+ {
+ /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+ {
+ /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+ /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+ },
+
+ {
+ /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[3].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[3].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[4].ctlEdges[4].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[5].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+ /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[5].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[5].ctlEdges[7].bChannel */ 0xFF
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+ /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+ /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+ /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+ }
+ },
+ .ctlPowerData_5G = {
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ }
+ },
+ }
+};
+
+static const struct ar9300_eeprom ar9300_x113 = {
+ .eepromVersion = 2,
+ .templateVersion = 6,
+ .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+ .custData = {"x113-023-f0000"},
+ .baseEepHeader = {
+ .regDmn = { LE16(0), LE16(0x1f) },
+ .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
+ .opCapFlags = {
+ .opFlags = AR5416_OPFLAGS_11A,
+ .eepMisc = 0,
+ },
+ .rfSilent = 0,
+ .blueToothOptions = 0,
+ .deviceCap = 0,
+ .deviceType = 5, /* takes lower byte in eeprom location */
+ .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+ .params_for_tuning_caps = {0, 0},
+ .featureEnable = 0x0d,
+ /*
+ * bit0 - enable tx temp comp - disabled
+ * bit1 - enable tx volt comp - disabled
+ * bit2 - enable fastClock - enabled
+ * bit3 - enable doubling - enabled
+ * bit4 - enable internal regulator - disabled
+ * bit5 - enable pa predistortion - disabled
+ */
+ .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+ .eepromWriteEnableGpio = 6,
+ .wlanDisableGpio = 0,
+ .wlanLedGpio = 8,
+ .rxBandSelectGpio = 0xff,
+ .txrxgain = 0x21,
+ .swreg = 0,
+ },
+ .modalHeader2G = {
+ /* ar9300_modal_eep_header 2g */
+ /* 4 idle,t1,t2,b(4 bits per setting) */
+ .antCtrlCommon = LE32(0x110),
+ /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+ .antCtrlCommon2 = LE32(0x44444),
+
+ /*
+ * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+ * rx1, rx12, b (2 bits each)
+ */
+ .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
+
+ /*
+ * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
+ * for ar9280 (0xa20c/b20c 5:0)
+ */
+ .xatten1DB = {0, 0, 0},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for ar9280 (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0, 0, 0},
+ .tempSlope = 25,
+ .voltSlope = 0,
+
+ /*
+ * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+ * channels in usual fbin coding format
+ */
+ .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+ /*
+ * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+ * if the register is per chain
+ */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {1, 1, 1},/* 3 chain */
+ .db_stage2 = {1, 1, 1}, /* 3 chain */
+ .db_stage3 = {0, 0, 0},
+ .db_stage4 = {0, 0, 0},
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2c,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0c80c080),
+ .papdRateMaskHt40 = LE32(0x0080c080),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext1 = {
+ .ant_div_control = 0,
+ .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ },
+ .calFreqPier2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ /* ar9300_cal_data_per_freq_op_loop 2g */
+ .calPierData2G = {
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ },
+ .calTarget_freqbin_Cck = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ .calTarget_freqbin_2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT20 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT40 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTargetPowerCck = {
+ /* 1L-5L,5S,11L,11S */
+ { {34, 34, 34, 34} },
+ { {34, 34, 34, 34} },
+ },
+ .calTargetPower2G = {
+ /* 6-24,36,48,54 */
+ { {34, 34, 32, 32} },
+ { {34, 34, 32, 32} },
+ { {34, 34, 32, 32} },
+ },
+ .calTargetPower2GHT20 = {
+ { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} },
+ { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} },
+ { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} },
+ },
+ .calTargetPower2GHT40 = {
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+ },
+ .ctlIndex_2G = {
+ 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+ 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+ },
+ .ctl_freqbin_2G = {
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2457, 1),
+ FREQ2FBIN(2462, 1)
+ },
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+ {
+ FREQ2FBIN(2422, 1),
+ FREQ2FBIN(2427, 1),
+ FREQ2FBIN(2447, 1),
+ FREQ2FBIN(2452, 1)
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ },
+
+ {
+ /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ }
+ },
+ .ctlPowerData_2G = {
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+ { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ },
+ .modalHeader5G = {
+ /* 4 idle,t1,t2,b (4 bits per setting) */
+ .antCtrlCommon = LE32(0x220),
+ /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+ .antCtrlCommon2 = LE32(0x11111),
+ /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+ .antCtrlChain = {
+ LE16(0x150), LE16(0x150), LE16(0x150),
+ },
+ /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+ .xatten1DB = {0, 0, 0},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for merlin (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0, 0, 0},
+ .tempSlope = 68,
+ .voltSlope = 0,
+ /* spurChans spur channels in usual fbin coding format */
+ .spurChans = {FREQ2FBIN(5500, 0), 0, 0, 0, 0},
+ /* noiseFloorThreshCh Check if the register is per chain */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {3, 3, 3}, /* 3 chain */
+ .db_stage2 = {3, 3, 3}, /* 3 chain */
+ .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+ .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
+ .xpaBiasLvl = 0xf,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2d,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+ .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext2 = {
+ .tempSlopeLow = 72,
+ .tempSlopeHigh = 105,
+ .xatten1DBLow = {0, 0, 0},
+ .xatten1MarginLow = {0, 0, 0},
+ .xatten1DBHigh = {0, 0, 0},
+ .xatten1MarginHigh = {0, 0, 0}
+ },
+ .calFreqPier5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5785, 0)
+ },
+ .calPierData5G = {
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+
+ },
+ .calTarget_freqbin_5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5785, 0)
+ },
+ .calTarget_freqbin_5GHT20 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT40 = {
+ FREQ2FBIN(5190, 0),
+ FREQ2FBIN(5230, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5410, 0),
+ FREQ2FBIN(5510, 0),
+ FREQ2FBIN(5670, 0),
+ FREQ2FBIN(5755, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTargetPower5G = {
+ /* 6-24,36,48,54 */
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ },
+ .calTargetPower5GHT20 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+ { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+ { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+ { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+ { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+ { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+ { {38, 38, 38, 38, 32, 28, 38, 38, 32, 28, 38, 38, 32, 26} },
+ { {36, 36, 36, 36, 32, 28, 36, 36, 32, 28, 36, 36, 32, 26} },
+ },
+ .calTargetPower5GHT40 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+ { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+ { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+ { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+ { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+ { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+ { {36, 36, 36, 36, 30, 26, 36, 36, 30, 26, 36, 36, 30, 24} },
+ { {34, 34, 34, 34, 30, 26, 34, 34, 30, 26, 34, 34, 30, 24} },
+ },
+ .ctlIndex_5G = {
+ 0x10, 0x16, 0x18, 0x40, 0x46,
+ 0x48, 0x30, 0x36, 0x38
+ },
+ .ctl_freqbin_5G = {
+ {
+ /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+ {
+ /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+ /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+ },
+
+ {
+ /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[3].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[3].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[4].ctlEdges[4].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[5].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+ /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[5].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[5].ctlEdges[7].bChannel */ 0xFF
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+ /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+ /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+ /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+ }
+ },
+ .ctlPowerData_5G = {
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ }
+ },
+ }
+};
+
+
+static const struct ar9300_eeprom ar9300_h112 = {
+ .eepromVersion = 2,
+ .templateVersion = 3,
+ .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+ .custData = {"h112-241-f0000"},
+ .baseEepHeader = {
+ .regDmn = { LE16(0), LE16(0x1f) },
+ .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
+ .opCapFlags = {
+ .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
+ .eepMisc = 0,
+ },
+ .rfSilent = 0,
+ .blueToothOptions = 0,
+ .deviceCap = 0,
+ .deviceType = 5, /* takes lower byte in eeprom location */
+ .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+ .params_for_tuning_caps = {0, 0},
+ .featureEnable = 0x0d,
+ /*
+ * bit0 - enable tx temp comp - disabled
+ * bit1 - enable tx volt comp - disabled
+ * bit2 - enable fastClock - enabled
+ * bit3 - enable doubling - enabled
+ * bit4 - enable internal regulator - disabled
+ * bit5 - enable pa predistortion - disabled
+ */
+ .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+ .eepromWriteEnableGpio = 6,
+ .wlanDisableGpio = 0,
+ .wlanLedGpio = 8,
+ .rxBandSelectGpio = 0xff,
+ .txrxgain = 0x10,
+ .swreg = 0,
+ },
+ .modalHeader2G = {
+ /* ar9300_modal_eep_header 2g */
+ /* 4 idle,t1,t2,b(4 bits per setting) */
+ .antCtrlCommon = LE32(0x110),
+ /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+ .antCtrlCommon2 = LE32(0x44444),
+
+ /*
+ * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+ * rx1, rx12, b (2 bits each)
+ */
+ .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
+
+ /*
+ * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
+ * for ar9280 (0xa20c/b20c 5:0)
+ */
+ .xatten1DB = {0, 0, 0},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for ar9280 (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0, 0, 0},
+ .tempSlope = 25,
+ .voltSlope = 0,
+
+ /*
+ * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+ * channels in usual fbin coding format
+ */
+ .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+ /*
+ * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+ * if the register is per chain
+ */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {1, 1, 1},/* 3 chain */
+ .db_stage2 = {1, 1, 1}, /* 3 chain */
+ .db_stage3 = {0, 0, 0},
+ .db_stage4 = {0, 0, 0},
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2c,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x80c080),
+ .papdRateMaskHt40 = LE32(0x80c080),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext1 = {
+ .ant_div_control = 0,
+ .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ },
+ .calFreqPier2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ /* ar9300_cal_data_per_freq_op_loop 2g */
+ .calPierData2G = {
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ },
+ .calTarget_freqbin_Cck = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2484, 1),
+ },
+ .calTarget_freqbin_2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT20 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT40 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTargetPowerCck = {
+ /* 1L-5L,5S,11L,11S */
+ { {34, 34, 34, 34} },
+ { {34, 34, 34, 34} },
+ },
+ .calTargetPower2G = {
+ /* 6-24,36,48,54 */
+ { {34, 34, 32, 32} },
+ { {34, 34, 32, 32} },
+ { {34, 34, 32, 32} },
+ },
+ .calTargetPower2GHT20 = {
+ { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} },
+ { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} },
+ { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} },
+ },
+ .calTargetPower2GHT40 = {
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} },
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} },
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} },
+ },
+ .ctlIndex_2G = {
+ 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+ 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+ },
+ .ctl_freqbin_2G = {
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2457, 1),
+ FREQ2FBIN(2462, 1)
+ },
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+ {
+ FREQ2FBIN(2422, 1),
+ FREQ2FBIN(2427, 1),
+ FREQ2FBIN(2447, 1),
+ FREQ2FBIN(2452, 1)
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ },
+
+ {
+ /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ }
+ },
+ .ctlPowerData_2G = {
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+ { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ },
+ .modalHeader5G = {
+ /* 4 idle,t1,t2,b (4 bits per setting) */
+ .antCtrlCommon = LE32(0x220),
+ /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+ .antCtrlCommon2 = LE32(0x44444),
+ /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+ .antCtrlChain = {
+ LE16(0x150), LE16(0x150), LE16(0x150),
+ },
+ /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+ .xatten1DB = {0, 0, 0},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for merlin (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0, 0, 0},
+ .tempSlope = 45,
+ .voltSlope = 0,
+ /* spurChans spur channels in usual fbin coding format */
+ .spurChans = {0, 0, 0, 0, 0},
+ /* noiseFloorThreshCh Check if the register is per chain */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {3, 3, 3}, /* 3 chain */
+ .db_stage2 = {3, 3, 3}, /* 3 chain */
+ .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+ .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2d,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+ .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext2 = {
+ .tempSlopeLow = 40,
+ .tempSlopeHigh = 50,
+ .xatten1DBLow = {0, 0, 0},
+ .xatten1MarginLow = {0, 0, 0},
+ .xatten1DBHigh = {0, 0, 0},
+ .xatten1MarginHigh = {0, 0, 0}
+ },
+ .calFreqPier5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calPierData5G = {
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+
+ },
+ .calTarget_freqbin_5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT20 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT40 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTargetPower5G = {
+ /* 6-24,36,48,54 */
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ },
+ .calTargetPower5GHT20 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} },
+ { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} },
+ { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} },
+ { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} },
+ { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} },
+ { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} },
+ { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} },
+ { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} },
+ },
+ .calTargetPower5GHT40 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} },
+ { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} },
+ { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} },
+ { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} },
+ { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} },
+ { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} },
+ { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} },
+ { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} },
+ },
+ .ctlIndex_5G = {
+ 0x10, 0x16, 0x18, 0x40, 0x46,
+ 0x48, 0x30, 0x36, 0x38
+ },
+ .ctl_freqbin_5G = {
+ {
+ /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+ {
+ /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+ /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+ },
+
+ {
+ /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[3].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[3].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[4].ctlEdges[4].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[5].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+ /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[5].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[5].ctlEdges[7].bChannel */ 0xFF
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+ /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+ /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+ /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+ }
+ },
+ .ctlPowerData_5G = {
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ }
+ },
+ }
+};
+
+
+static const struct ar9300_eeprom ar9300_x112 = {
+ .eepromVersion = 2,
+ .templateVersion = 5,
+ .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+ .custData = {"x112-041-f0000"},
+ .baseEepHeader = {
+ .regDmn = { LE16(0), LE16(0x1f) },
+ .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
+ .opCapFlags = {
+ .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
+ .eepMisc = 0,
+ },
+ .rfSilent = 0,
+ .blueToothOptions = 0,
+ .deviceCap = 0,
+ .deviceType = 5, /* takes lower byte in eeprom location */
+ .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+ .params_for_tuning_caps = {0, 0},
+ .featureEnable = 0x0d,
+ /*
+ * bit0 - enable tx temp comp - disabled
+ * bit1 - enable tx volt comp - disabled
+ * bit2 - enable fastclock - enabled
+ * bit3 - enable doubling - enabled
+ * bit4 - enable internal regulator - disabled
+ * bit5 - enable pa predistortion - disabled
+ */
+ .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+ .eepromWriteEnableGpio = 6,
+ .wlanDisableGpio = 0,
+ .wlanLedGpio = 8,
+ .rxBandSelectGpio = 0xff,
+ .txrxgain = 0x0,
+ .swreg = 0,
+ },
+ .modalHeader2G = {
+ /* ar9300_modal_eep_header 2g */
+ /* 4 idle,t1,t2,b(4 bits per setting) */
+ .antCtrlCommon = LE32(0x110),
+ /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+ .antCtrlCommon2 = LE32(0x22222),
+
+ /*
+ * antCtrlChain[ar9300_max_chains]; 6 idle, t, r,
+ * rx1, rx12, b (2 bits each)
+ */
+ .antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) },
+
+ /*
+ * xatten1DB[AR9300_max_chains]; 3 xatten1_db
+ * for ar9280 (0xa20c/b20c 5:0)
+ */
+ .xatten1DB = {0x1b, 0x1b, 0x1b},
+
+ /*
+ * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin
+ * for ar9280 (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0x15, 0x15, 0x15},
+ .tempSlope = 50,
+ .voltSlope = 0,
+
+ /*
+ * spurChans[OSPrey_eeprom_modal_sPURS]; spur
+ * channels in usual fbin coding format
+ */
+ .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+ /*
+ * noiseFloorThreshch[ar9300_max_cHAINS]; 3 Check
+ * if the register is per chain
+ */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {1, 1, 1},/* 3 chain */
+ .db_stage2 = {1, 1, 1}, /* 3 chain */
+ .db_stage3 = {0, 0, 0},
+ .db_stage4 = {0, 0, 0},
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2c,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0c80c080),
+ .papdRateMaskHt40 = LE32(0x0080c080),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext1 = {
+ .ant_div_control = 0,
+ .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ },
+ .calFreqPier2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ /* ar9300_cal_data_per_freq_op_loop 2g */
+ .calPierData2G = {
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ },
+ .calTarget_freqbin_Cck = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ .calTarget_freqbin_2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT20 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT40 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTargetPowerCck = {
+ /* 1L-5L,5S,11L,11s */
+ { {38, 38, 38, 38} },
+ { {38, 38, 38, 38} },
+ },
+ .calTargetPower2G = {
+ /* 6-24,36,48,54 */
+ { {38, 38, 36, 34} },
+ { {38, 38, 36, 34} },
+ { {38, 38, 34, 32} },
+ },
+ .calTargetPower2GHT20 = {
+ { {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} },
+ { {36, 36, 36, 36, 36, 34, 36, 34, 32, 30, 30, 30, 28, 26} },
+ { {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} },
+ },
+ .calTargetPower2GHT40 = {
+ { {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} },
+ { {36, 36, 36, 36, 34, 32, 34, 32, 30, 28, 28, 28, 28, 24} },
+ { {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} },
+ },
+ .ctlIndex_2G = {
+ 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+ 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+ },
+ .ctl_freqbin_2G = {
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2457, 1),
+ FREQ2FBIN(2462, 1)
+ },
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+ {
+ FREQ2FBIN(2422, 1),
+ FREQ2FBIN(2427, 1),
+ FREQ2FBIN(2447, 1),
+ FREQ2FBIN(2452, 1)
+ },
+
+ {
+ /* Data[4].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+ /* Data[4].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+ /* Data[4].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+ /* Data[4].ctledges[3].bchannel */ FREQ2FBIN(2484, 1),
+ },
+
+ {
+ /* Data[5].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+ /* Data[5].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+ /* Data[5].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[6].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+ /* Data[6].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[7].ctledges[0].bchannel */ FREQ2FBIN(2422, 1),
+ /* Data[7].ctledges[1].bchannel */ FREQ2FBIN(2427, 1),
+ /* Data[7].ctledges[2].bchannel */ FREQ2FBIN(2447, 1),
+ /* Data[7].ctledges[3].bchannel */ FREQ2FBIN(2462, 1),
+ },
+
+ {
+ /* Data[8].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+ /* Data[8].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+ /* Data[8].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+ },
+
+ {
+ /* Data[9].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+ /* Data[9].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+ /* Data[9].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[10].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+ /* Data[10].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+ /* Data[10].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[11].ctledges[0].bchannel */ FREQ2FBIN(2422, 1),
+ /* Data[11].ctledges[1].bchannel */ FREQ2FBIN(2427, 1),
+ /* Data[11].ctledges[2].bchannel */ FREQ2FBIN(2447, 1),
+ /* Data[11].ctledges[3].bchannel */ FREQ2FBIN(2462, 1),
+ }
+ },
+ .ctlPowerData_2G = {
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+ { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ },
+ .modalHeader5G = {
+ /* 4 idle,t1,t2,b (4 bits per setting) */
+ .antCtrlCommon = LE32(0x110),
+ /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+ .antCtrlCommon2 = LE32(0x22222),
+ /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+ .antCtrlChain = {
+ LE16(0x0), LE16(0x0), LE16(0x0),
+ },
+ /* xatten1DB 3 xatten1_db for ar9280 (0xa20c/b20c 5:0) */
+ .xatten1DB = {0x13, 0x19, 0x17},
+
+ /*
+ * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin
+ * for merlin (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0x19, 0x19, 0x19},
+ .tempSlope = 70,
+ .voltSlope = 15,
+ /* spurChans spur channels in usual fbin coding format */
+ .spurChans = {0, 0, 0, 0, 0},
+ /* noiseFloorThreshch check if the register is per chain */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {3, 3, 3}, /* 3 chain */
+ .db_stage2 = {3, 3, 3}, /* 3 chain */
+ .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+ .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2d,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+ .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext2 = {
+ .tempSlopeLow = 72,
+ .tempSlopeHigh = 105,
+ .xatten1DBLow = {0x10, 0x14, 0x10},
+ .xatten1MarginLow = {0x19, 0x19 , 0x19},
+ .xatten1DBHigh = {0x1d, 0x20, 0x24},
+ .xatten1MarginHigh = {0x10, 0x10, 0x10}
+ },
+ .calFreqPier5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5785, 0)
+ },
+ .calPierData5G = {
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+
+ },
+ .calTarget_freqbin_5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5725, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT20 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5725, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT40 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5725, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTargetPower5G = {
+ /* 6-24,36,48,54 */
+ { {32, 32, 28, 26} },
+ { {32, 32, 28, 26} },
+ { {32, 32, 28, 26} },
+ { {32, 32, 26, 24} },
+ { {32, 32, 26, 24} },
+ { {32, 32, 24, 22} },
+ { {30, 30, 24, 22} },
+ { {30, 30, 24, 22} },
+ },
+ .calTargetPower5GHT20 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} },
+ { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} },
+ { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} },
+ { {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 22, 22, 20, 20} },
+ { {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 20, 18, 16, 16} },
+ { {32, 32, 32, 32, 28, 26, 32, 24, 20, 16, 18, 16, 14, 14} },
+ { {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} },
+ { {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} },
+ },
+ .calTargetPower5GHT40 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} },
+ { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} },
+ { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} },
+ { {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 22, 22, 20, 20} },
+ { {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 20, 18, 16, 16} },
+ { {32, 32, 32, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} },
+ { {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} },
+ { {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} },
+ },
+ .ctlIndex_5G = {
+ 0x10, 0x16, 0x18, 0x40, 0x46,
+ 0x48, 0x30, 0x36, 0x38
+ },
+ .ctl_freqbin_5G = {
+ {
+ /* Data[0].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+ /* Data[0].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+ /* Data[0].ctledges[2].bchannel */ FREQ2FBIN(5280, 0),
+ /* Data[0].ctledges[3].bchannel */ FREQ2FBIN(5500, 0),
+ /* Data[0].ctledges[4].bchannel */ FREQ2FBIN(5600, 0),
+ /* Data[0].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+ /* Data[0].ctledges[6].bchannel */ FREQ2FBIN(5745, 0),
+ /* Data[0].ctledges[7].bchannel */ FREQ2FBIN(5825, 0)
+ },
+ {
+ /* Data[1].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+ /* Data[1].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+ /* Data[1].ctledges[2].bchannel */ FREQ2FBIN(5280, 0),
+ /* Data[1].ctledges[3].bchannel */ FREQ2FBIN(5500, 0),
+ /* Data[1].ctledges[4].bchannel */ FREQ2FBIN(5520, 0),
+ /* Data[1].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+ /* Data[1].ctledges[6].bchannel */ FREQ2FBIN(5745, 0),
+ /* Data[1].ctledges[7].bchannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[2].ctledges[0].bchannel */ FREQ2FBIN(5190, 0),
+ /* Data[2].ctledges[1].bchannel */ FREQ2FBIN(5230, 0),
+ /* Data[2].ctledges[2].bchannel */ FREQ2FBIN(5270, 0),
+ /* Data[2].ctledges[3].bchannel */ FREQ2FBIN(5310, 0),
+ /* Data[2].ctledges[4].bchannel */ FREQ2FBIN(5510, 0),
+ /* Data[2].ctledges[5].bchannel */ FREQ2FBIN(5550, 0),
+ /* Data[2].ctledges[6].bchannel */ FREQ2FBIN(5670, 0),
+ /* Data[2].ctledges[7].bchannel */ FREQ2FBIN(5755, 0)
+ },
+
+ {
+ /* Data[3].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+ /* Data[3].ctledges[1].bchannel */ FREQ2FBIN(5200, 0),
+ /* Data[3].ctledges[2].bchannel */ FREQ2FBIN(5260, 0),
+ /* Data[3].ctledges[3].bchannel */ FREQ2FBIN(5320, 0),
+ /* Data[3].ctledges[4].bchannel */ FREQ2FBIN(5500, 0),
+ /* Data[3].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+ /* Data[3].ctledges[6].bchannel */ 0xFF,
+ /* Data[3].ctledges[7].bchannel */ 0xFF,
+ },
+
+ {
+ /* Data[4].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+ /* Data[4].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+ /* Data[4].ctledges[2].bchannel */ FREQ2FBIN(5500, 0),
+ /* Data[4].ctledges[3].bchannel */ FREQ2FBIN(5700, 0),
+ /* Data[4].ctledges[4].bchannel */ 0xFF,
+ /* Data[4].ctledges[5].bchannel */ 0xFF,
+ /* Data[4].ctledges[6].bchannel */ 0xFF,
+ /* Data[4].ctledges[7].bchannel */ 0xFF,
+ },
+
+ {
+ /* Data[5].ctledges[0].bchannel */ FREQ2FBIN(5190, 0),
+ /* Data[5].ctledges[1].bchannel */ FREQ2FBIN(5270, 0),
+ /* Data[5].ctledges[2].bchannel */ FREQ2FBIN(5310, 0),
+ /* Data[5].ctledges[3].bchannel */ FREQ2FBIN(5510, 0),
+ /* Data[5].ctledges[4].bchannel */ FREQ2FBIN(5590, 0),
+ /* Data[5].ctledges[5].bchannel */ FREQ2FBIN(5670, 0),
+ /* Data[5].ctledges[6].bchannel */ 0xFF,
+ /* Data[5].ctledges[7].bchannel */ 0xFF
+ },
+
+ {
+ /* Data[6].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+ /* Data[6].ctledges[1].bchannel */ FREQ2FBIN(5200, 0),
+ /* Data[6].ctledges[2].bchannel */ FREQ2FBIN(5220, 0),
+ /* Data[6].ctledges[3].bchannel */ FREQ2FBIN(5260, 0),
+ /* Data[6].ctledges[4].bchannel */ FREQ2FBIN(5500, 0),
+ /* Data[6].ctledges[5].bchannel */ FREQ2FBIN(5600, 0),
+ /* Data[6].ctledges[6].bchannel */ FREQ2FBIN(5700, 0),
+ /* Data[6].ctledges[7].bchannel */ FREQ2FBIN(5745, 0)
+ },
+
+ {
+ /* Data[7].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+ /* Data[7].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+ /* Data[7].ctledges[2].bchannel */ FREQ2FBIN(5320, 0),
+ /* Data[7].ctledges[3].bchannel */ FREQ2FBIN(5500, 0),
+ /* Data[7].ctledges[4].bchannel */ FREQ2FBIN(5560, 0),
+ /* Data[7].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+ /* Data[7].ctledges[6].bchannel */ FREQ2FBIN(5745, 0),
+ /* Data[7].ctledges[7].bchannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[8].ctledges[0].bchannel */ FREQ2FBIN(5190, 0),
+ /* Data[8].ctledges[1].bchannel */ FREQ2FBIN(5230, 0),
+ /* Data[8].ctledges[2].bchannel */ FREQ2FBIN(5270, 0),
+ /* Data[8].ctledges[3].bchannel */ FREQ2FBIN(5510, 0),
+ /* Data[8].ctledges[4].bchannel */ FREQ2FBIN(5550, 0),
+ /* Data[8].ctledges[5].bchannel */ FREQ2FBIN(5670, 0),
+ /* Data[8].ctledges[6].bchannel */ FREQ2FBIN(5755, 0),
+ /* Data[8].ctledges[7].bchannel */ FREQ2FBIN(5795, 0)
+ }
+ },
+ .ctlPowerData_5G = {
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ }
+ },
+ }
+};
+
+static const struct ar9300_eeprom ar9300_h116 = {
+ .eepromVersion = 2,
+ .templateVersion = 4,
+ .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+ .custData = {"h116-041-f0000"},
+ .baseEepHeader = {
+ .regDmn = { LE16(0), LE16(0x1f) },
+ .txrxMask = 0x33, /* 4 bits tx and 4 bits rx */
+ .opCapFlags = {
+ .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
+ .eepMisc = 0,
+ },
+ .rfSilent = 0,
+ .blueToothOptions = 0,
+ .deviceCap = 0,
+ .deviceType = 5, /* takes lower byte in eeprom location */
+ .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+ .params_for_tuning_caps = {0, 0},
+ .featureEnable = 0x0d,
+ /*
+ * bit0 - enable tx temp comp - disabled
+ * bit1 - enable tx volt comp - disabled
+ * bit2 - enable fastClock - enabled
+ * bit3 - enable doubling - enabled
+ * bit4 - enable internal regulator - disabled
+ * bit5 - enable pa predistortion - disabled
+ */
+ .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+ .eepromWriteEnableGpio = 6,
+ .wlanDisableGpio = 0,
+ .wlanLedGpio = 8,
+ .rxBandSelectGpio = 0xff,
+ .txrxgain = 0x10,
+ .swreg = 0,
+ },
+ .modalHeader2G = {
+ /* ar9300_modal_eep_header 2g */
+ /* 4 idle,t1,t2,b(4 bits per setting) */
+ .antCtrlCommon = LE32(0x110),
+ /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+ .antCtrlCommon2 = LE32(0x44444),
+
+ /*
+ * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+ * rx1, rx12, b (2 bits each)
+ */
+ .antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) },
+
+ /*
+ * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
+ * for ar9280 (0xa20c/b20c 5:0)
+ */
+ .xatten1DB = {0x1f, 0x1f, 0x1f},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for ar9280 (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0x12, 0x12, 0x12},
+ .tempSlope = 25,
+ .voltSlope = 0,
+
+ /*
+ * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+ * channels in usual fbin coding format
+ */
+ .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+ /*
+ * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+ * if the register is per chain
+ */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {1, 1, 1},/* 3 chain */
+ .db_stage2 = {1, 1, 1}, /* 3 chain */
+ .db_stage3 = {0, 0, 0},
+ .db_stage4 = {0, 0, 0},
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2c,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0c80C080),
+ .papdRateMaskHt40 = LE32(0x0080C080),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext1 = {
+ .ant_div_control = 0,
+ .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ },
+ .calFreqPier2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ /* ar9300_cal_data_per_freq_op_loop 2g */
+ .calPierData2G = {
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ },
+ .calTarget_freqbin_Cck = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ .calTarget_freqbin_2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT20 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT40 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTargetPowerCck = {
+ /* 1L-5L,5S,11L,11S */
+ { {34, 34, 34, 34} },
+ { {34, 34, 34, 34} },
+ },
+ .calTargetPower2G = {
+ /* 6-24,36,48,54 */
+ { {34, 34, 32, 32} },
+ { {34, 34, 32, 32} },
+ { {34, 34, 32, 32} },
+ },
+ .calTargetPower2GHT20 = {
+ { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} },
+ { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} },
+ { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} },
+ },
+ .calTargetPower2GHT40 = {
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+ },
+ .ctlIndex_2G = {
+ 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+ 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+ },
+ .ctl_freqbin_2G = {
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2457, 1),
+ FREQ2FBIN(2462, 1)
+ },
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+ {
+ FREQ2FBIN(2422, 1),
+ FREQ2FBIN(2427, 1),
+ FREQ2FBIN(2447, 1),
+ FREQ2FBIN(2452, 1)
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ },
+
+ {
+ /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ }
+ },
+ .ctlPowerData_2G = {
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+ { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ },
+ .modalHeader5G = {
+ /* 4 idle,t1,t2,b (4 bits per setting) */
+ .antCtrlCommon = LE32(0x220),
+ /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+ .antCtrlCommon2 = LE32(0x44444),
+ /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+ .antCtrlChain = {
+ LE16(0x150), LE16(0x150), LE16(0x150),
+ },
+ /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+ .xatten1DB = {0x19, 0x19, 0x19},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for merlin (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0x14, 0x14, 0x14},
+ .tempSlope = 70,
+ .voltSlope = 0,
+ /* spurChans spur channels in usual fbin coding format */
+ .spurChans = {0, 0, 0, 0, 0},
+ /* noiseFloorThreshCh Check if the register is per chain */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {3, 3, 3}, /* 3 chain */
+ .db_stage2 = {3, 3, 3}, /* 3 chain */
+ .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+ .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2d,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+ .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext2 = {
+ .tempSlopeLow = 35,
+ .tempSlopeHigh = 50,
+ .xatten1DBLow = {0, 0, 0},
+ .xatten1MarginLow = {0, 0, 0},
+ .xatten1DBHigh = {0, 0, 0},
+ .xatten1MarginHigh = {0, 0, 0}
+ },
+ .calFreqPier5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5785, 0)
+ },
+ .calPierData5G = {
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ },
+
+ },
+ .calTarget_freqbin_5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT20 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT40 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTargetPower5G = {
+ /* 6-24,36,48,54 */
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ },
+ .calTargetPower5GHT20 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} },
+ { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} },
+ { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} },
+ { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} },
+ { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} },
+ { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} },
+ { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} },
+ { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} },
+ },
+ .calTargetPower5GHT40 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} },
+ { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} },
+ { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} },
+ { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} },
+ { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} },
+ { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} },
+ { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} },
+ { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} },
+ },
+ .ctlIndex_5G = {
+ 0x10, 0x16, 0x18, 0x40, 0x46,
+ 0x48, 0x30, 0x36, 0x38
+ },
+ .ctl_freqbin_5G = {
+ {
+ /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+ {
+ /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+ /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+ },
+
+ {
+ /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[3].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[3].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[4].ctlEdges[4].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[5].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+ /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[5].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[5].ctlEdges[7].bChannel */ 0xFF
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+ /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+ /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+ /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+ }
+ },
+ .ctlPowerData_5G = {
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ }
+ },
+ }
+};
+
+
+static const struct ar9300_eeprom *ar9300_eep_templates[] = {
+ &ar9300_default,
+ &ar9300_x112,
+ &ar9300_h116,
+ &ar9300_h112,
+ &ar9300_x113,
+};
+
+static const struct ar9300_eeprom *ar9003_eeprom_struct_find_by_id(int id)
+{
+#define N_LOOP (sizeof(ar9300_eep_templates) / sizeof(ar9300_eep_templates[0]))
+ unsigned int it;
+
+ for (it = 0; it < N_LOOP; it++)
+ if (ar9300_eep_templates[it]->templateVersion == id)
+ return ar9300_eep_templates[it];
+ return NULL;
+#undef N_LOOP
+}
+
+
+static u16 ath9k_hw_fbin2freq(u8 fbin, int is2GHz)
+{
+ if (fbin == AR5416_BCHAN_UNUSED)
+ return fbin;
+
+ return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
+}
+
+static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah __unused)
+{
+ return 0;
+}
+
+static int interpolate(int x, int xa, int xb, int ya, int yb)
+{
+ int bf, factor, plus;
+
+ bf = 2 * (yb - ya) * (x - xa) / (xb - xa);
+ factor = bf / 2;
+ plus = bf % 2;
+ return ya + factor + plus;
+}
+
+static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
+ enum eeprom_param param)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader;
+
+ switch (param) {
+ case EEP_MAC_LSW:
+ return eep->macAddr[0] << 8 | eep->macAddr[1];
+ case EEP_MAC_MID:
+ return eep->macAddr[2] << 8 | eep->macAddr[3];
+ case EEP_MAC_MSW:
+ return eep->macAddr[4] << 8 | eep->macAddr[5];
+ case EEP_REG_0:
+ return (uint16_t)(pBase->regDmn[0]);
+ case EEP_REG_1:
+ return (uint16_t)(pBase->regDmn[1]);
+ case EEP_OP_CAP:
+ return pBase->deviceCap;
+ case EEP_OP_MODE:
+ return pBase->opCapFlags.opFlags;
+ case EEP_RF_SILENT:
+ return pBase->rfSilent;
+ case EEP_TX_MASK:
+ return (pBase->txrxMask >> 4) & 0xf;
+ case EEP_RX_MASK:
+ return pBase->txrxMask & 0xf;
+ case EEP_DRIVE_STRENGTH:
+#define AR9300_EEP_BASE_DRIV_STRENGTH 0x1
+ return pBase->miscConfiguration & AR9300_EEP_BASE_DRIV_STRENGTH;
+ case EEP_INTERNAL_REGULATOR:
+ /* Bit 4 is internal regulator flag */
+ return (pBase->featureEnable & 0x10) >> 4;
+ case EEP_SWREG:
+ return (uint32_t)(pBase->swreg);
+ case EEP_PAPRD:
+ return !!(pBase->featureEnable & BIT(5));
+ case EEP_CHAIN_MASK_REDUCE:
+ return (pBase->miscConfiguration >> 0x3) & 0x1;
+ case EEP_ANT_DIV_CTL1:
+ return (uint32_t)(eep->base_ext1.ant_div_control);
+ default:
+ return 0;
+ }
+}
+
+static int ar9300_eeprom_read_byte(struct ath_common *common, int address,
+ u8 *buffer)
+{
+ u16 val;
+
+ if (!ath9k_hw_nvram_read(common, address / 2, &val))
+ return 0;
+
+ *buffer = (val >> (8 * (address % 2))) & 0xff;
+ return 1;
+}
+
+static int ar9300_eeprom_read_word(struct ath_common *common, int address,
+ u8 *buffer)
+{
+ u16 val;
+
+ if (!ath9k_hw_nvram_read(common, address / 2, &val))
+ return 0;
+
+ buffer[0] = val >> 8;
+ buffer[1] = val & 0xff;
+
+ return 1;
+}
+
+static int ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
+ int count)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ int i;
+
+ if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) {
+ DBG("ath9k: "
+ "eeprom address not in range\n");
+ return 0;
+ }
+
+ /*
+ * Since we're reading the bytes in reverse order from a little-endian
+ * word stream, an even address means we only use the lower half of
+ * the 16-bit word at that address
+ */
+ if (address % 2 == 0) {
+ if (!ar9300_eeprom_read_byte(common, address--, buffer++))
+ goto error;
+
+ count--;
+ }
+
+ for (i = 0; i < count / 2; i++) {
+ if (!ar9300_eeprom_read_word(common, address, buffer))
+ goto error;
+
+ address -= 2;
+ buffer += 2;
+ }
+
+ if (count % 2)
+ if (!ar9300_eeprom_read_byte(common, address, buffer))
+ goto error;
+
+ return 1;
+
+error:
+ DBG("ath9k: "
+ "unable to read eeprom region at offset %d\n", address);
+ return 0;
+}
+
+static int ar9300_otp_read_word(struct ath_hw *ah, int addr, u32 *data)
+{
+ REG_READ(ah, AR9300_OTP_BASE + (4 * addr));
+
+ if (!ath9k_hw_wait(ah, AR9300_OTP_STATUS, AR9300_OTP_STATUS_TYPE,
+ AR9300_OTP_STATUS_VALID, 1000))
+ return 0;
+
+ *data = REG_READ(ah, AR9300_OTP_READ_DATA);
+ return 1;
+}
+
+static int ar9300_read_otp(struct ath_hw *ah, int address, u8 *buffer,
+ int count)
+{
+ u32 data;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ int offset = 8 * ((address - i) % 4);
+ if (!ar9300_otp_read_word(ah, (address - i) / 4, &data))
+ return 0;
+
+ buffer[i] = (data >> offset) & 0xff;
+ }
+
+ return 1;
+}
+
+
+static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
+ int *length, int *major, int *minor)
+{
+ unsigned long value[4];
+
+ value[0] = best[0];
+ value[1] = best[1];
+ value[2] = best[2];
+ value[3] = best[3];
+ *code = ((value[0] >> 5) & 0x0007);
+ *reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020);
+ *length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f);
+ *major = (value[2] & 0x000f);
+ *minor = (value[3] & 0x00ff);
+}
+
+static u16 ar9300_comp_cksum(u8 *data, int dsize)
+{
+ int it, checksum = 0;
+
+ for (it = 0; it < dsize; it++) {
+ checksum += data[it];
+ checksum &= 0xffff;
+ }
+
+ return checksum;
+}
+
+static int ar9300_uncompress_block(struct ath_hw *ah __unused,
+ u8 *mptr,
+ int mdataSize,
+ u8 *block,
+ int size)
+{
+ int it;
+ int spot;
+ int offset;
+ int length;
+
+ spot = 0;
+
+ for (it = 0; it < size; it += (length+2)) {
+ offset = block[it];
+ offset &= 0xff;
+ spot += offset;
+ length = block[it+1];
+ length &= 0xff;
+
+ if (length > 0 && spot >= 0 && spot+length <= mdataSize) {
+ DBG2("ath9k: "
+ "Restore at %d: spot=%d offset=%d length=%d\n",
+ it, spot, offset, length);
+ memcpy(&mptr[spot], &block[it+2], length);
+ spot += length;
+ } else if (length > 0) {
+ DBG("ath9k: "
+ "Bad restore at %d: spot=%d offset=%d length=%d\n",
+ it, spot, offset, length);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int ar9300_compress_decision(struct ath_hw *ah,
+ int it,
+ int code,
+ int reference,
+ u8 *mptr,
+ u8 *word, int length, int mdata_size)
+{
+ const struct ar9300_eeprom *eep = NULL;
+
+ switch (code) {
+ case _CompressNone:
+ if (length != mdata_size) {
+ DBG("ath9k: "
+ "EEPROM structure size mismatch memory=%d eeprom=%d\n",
+ mdata_size, length);
+ return -1;
+ }
+ memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length);
+ DBG2("ath9k: "
+ "restored eeprom %d: uncompressed, length %d\n",
+ it, length);
+ break;
+ case _CompressBlock:
+ if (reference == 0) {
+ } else {
+ eep = ar9003_eeprom_struct_find_by_id(reference);
+ if (eep == NULL) {
+ DBG("ath9k: "
+ "can't find reference eeprom struct %d\n",
+ reference);
+ return -1;
+ }
+ memcpy(mptr, eep, mdata_size);
+ }
+ DBG2("ath9k: "
+ "restore eeprom %d: block, reference %d, length %d\n",
+ it, reference, length);
+ ar9300_uncompress_block(ah, mptr, mdata_size,
+ (u8 *) (word + COMP_HDR_LEN), length);
+ break;
+ default:
+ DBG("ath9k: "
+ "unknown compression code %d\n", code);
+ return -1;
+ }
+ return 0;
+}
+
+typedef int (*eeprom_read_op)(struct ath_hw *ah, int address, u8 *buffer,
+ int count);
+
+static int ar9300_check_header(void *data)
+{
+ u32 *word = data;
+ return !(*word == 0 || *word == (unsigned int)~0);
+}
+
+static int ar9300_check_eeprom_header(struct ath_hw *ah, eeprom_read_op read,
+ int base_addr)
+{
+ u8 header[4];
+
+ if (!read(ah, base_addr, header, 4))
+ return 0;
+
+ return ar9300_check_header(header);
+}
+
+static int ar9300_eeprom_restore_flash(struct ath_hw *ah, u8 *mptr,
+ int mdata_size)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ u16 *data = (u16 *) mptr;
+ int i;
+
+ for (i = 0; i < mdata_size / 2; i++, data++)
+ ath9k_hw_nvram_read(common, i, data);
+
+ return 0;
+}
+/*
+ * Read the configuration data from the eeprom.
+ * The data can be put in any specified memory buffer.
+ *
+ * Returns -1 on error.
+ * Returns address of next memory location on success.
+ */
+static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
+ u8 *mptr, int mdata_size)
+{
+#define MDEFAULT 15
+#define MSTATE 100
+ int cptr;
+ u8 *word;
+ int code;
+ int reference, length, major, minor;
+ int osize;
+ int it;
+ u16 checksum, mchecksum;
+ eeprom_read_op read;
+
+ if (ath9k_hw_use_flash(ah))
+ return ar9300_eeprom_restore_flash(ah, mptr, mdata_size);
+
+ word = zalloc(2048);
+ if (!word)
+ return -1;
+
+ memcpy(mptr, &ar9300_default, mdata_size);
+
+ read = ar9300_read_eeprom;
+ if (AR_SREV_9485(ah))
+ cptr = AR9300_BASE_ADDR_4K;
+ else
+ cptr = AR9300_BASE_ADDR;
+ DBG2("ath9k: "
+ "Trying EEPROM access at Address 0x%04x\n", cptr);
+ if (ar9300_check_eeprom_header(ah, read, cptr))
+ goto found;
+
+ cptr = AR9300_BASE_ADDR_512;
+ DBG2("ath9k: "
+ "Trying EEPROM access at Address 0x%04x\n", cptr);
+ if (ar9300_check_eeprom_header(ah, read, cptr))
+ goto found;
+
+ read = ar9300_read_otp;
+ cptr = AR9300_BASE_ADDR;
+ DBG2("ath9k: "
+ "Trying OTP access at Address 0x%04x\n", cptr);
+ if (ar9300_check_eeprom_header(ah, read, cptr))
+ goto found;
+
+ cptr = AR9300_BASE_ADDR_512;
+ DBG2("ath9k: "
+ "Trying OTP access at Address 0x%04x\n", cptr);
+ if (ar9300_check_eeprom_header(ah, read, cptr))
+ goto found;
+
+ goto fail;
+
+found:
+ DBG2("ath9k: Found valid EEPROM data\n");
+
+ for (it = 0; it < MSTATE; it++) {
+ if (!read(ah, cptr, word, COMP_HDR_LEN))
+ goto fail;
+
+ if (!ar9300_check_header(word))
+ break;
+
+ ar9300_comp_hdr_unpack(word, &code, &reference,
+ &length, &major, &minor);
+ DBG2("ath9k: "
+ "Found block at %x: code=%d ref=%d length=%d major=%d minor=%d\n",
+ cptr, code, reference, length, major, minor);
+ if ((!AR_SREV_9485(ah) && length >= 1024) ||
+ (AR_SREV_9485(ah) && length > EEPROM_DATA_LEN_9485)) {
+ DBG2("ath9k: "
+ "Skipping bad header\n");
+ cptr -= COMP_HDR_LEN;
+ continue;
+ }
+
+ osize = length;
+ read(ah, cptr, word, COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
+ checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
+ mchecksum = word[COMP_HDR_LEN + osize] |
+ (word[COMP_HDR_LEN + osize + 1] << 8);
+ DBG2("ath9k: "
+ "checksum %x %x\n", checksum, mchecksum);
+ if (checksum == mchecksum) {
+ ar9300_compress_decision(ah, it, code, reference, mptr,
+ word, length, mdata_size);
+ } else {
+ DBG2("ath9k: "
+ "skipping block with bad checksum\n");
+ }
+ cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
+ }
+
+ free(word);
+ return cptr;
+
+fail:
+ free(word);
+ return -1;
+}
+
+/*
+ * Restore the configuration structure by reading the eeprom.
+ * This function destroys any existing in-memory structure
+ * content.
+ */
+static int ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
+{
+ u8 *mptr = (u8 *) &ah->eeprom.ar9300_eep;
+
+ if (ar9300_eeprom_restore_internal(ah, mptr,
+ sizeof(struct ar9300_eeprom)) < 0)
+ return 0;
+
+ return 1;
+}
+
+/* XXX: review hardware docs */
+static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
+{
+ return ah->eeprom.ar9300_eep.eepromVersion;
+}
+
+/* XXX: could be read from the eepromVersion, not sure yet */
+static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah __unused)
+{
+ return 0;
+}
+
+static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, int is2ghz)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+ if (is2ghz)
+ return eep->modalHeader2G.xpaBiasLvl;
+ else
+ return eep->modalHeader5G.xpaBiasLvl;
+}
+
+static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, int is2ghz)
+{
+ int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
+
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
+ else {
+ REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
+ REG_RMW_FIELD(ah, AR_CH0_THERM,
+ AR_CH0_THERM_XPABIASLVL_MSB,
+ bias >> 2);
+ REG_RMW_FIELD(ah, AR_CH0_THERM,
+ AR_CH0_THERM_XPASHORT2GND, 1);
+ }
+}
+
+static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, int is2ghz)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ uint32_t val;
+
+ if (is2ghz)
+ val = eep->modalHeader2G.antCtrlCommon;
+ else
+ val = eep->modalHeader5G.antCtrlCommon;
+ return (uint32_t)(val);
+}
+
+static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, int is2ghz)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ uint32_t val;
+
+ if (is2ghz)
+ val = eep->modalHeader2G.antCtrlCommon2;
+ else
+ val = eep->modalHeader5G.antCtrlCommon2;
+ return (uint32_t)(val);
+}
+
+static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
+ int chain,
+ int is2ghz)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ uint16_t val = 0;
+
+ if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
+ if (is2ghz)
+ val = eep->modalHeader2G.antCtrlChain[chain];
+ else
+ val = eep->modalHeader5G.antCtrlChain[chain];
+ }
+
+ return (uint16_t)(val);
+}
+
+static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, int is2ghz)
+{
+ int chain;
+ u32 regval;
+ u32 ant_div_ctl1;
+ static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = {
+ AR_PHY_SWITCH_CHAIN_0,
+ AR_PHY_SWITCH_CHAIN_1,
+ AR_PHY_SWITCH_CHAIN_2,
+ };
+
+ u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
+
+ REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value);
+
+ value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
+ REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
+
+ for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+ if ((ah->rxchainmask & BIT(chain)) ||
+ (ah->txchainmask & BIT(chain))) {
+ value = ar9003_hw_ant_ctrl_chain_get(ah, chain,
+ is2ghz);
+ REG_RMW_FIELD(ah, switch_chain_reg[chain],
+ AR_SWITCH_TABLE_ALL, value);
+ }
+ }
+
+ if (AR_SREV_9485(ah)) {
+ value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1);
+ /*
+ * main_lnaconf, alt_lnaconf, main_tb, alt_tb
+ * are the fields present
+ */
+ regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
+ regval &= (~AR_ANT_DIV_CTRL_ALL);
+ regval |= (value & 0x3f) << AR_ANT_DIV_CTRL_ALL_S;
+ /* enable_lnadiv */
+ regval &= (~AR_PHY_9485_ANT_DIV_LNADIV);
+ regval |= ((value >> 6) & 0x1) <<
+ AR_PHY_9485_ANT_DIV_LNADIV_S;
+ REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
+
+ /*enable fast_div */
+ regval = REG_READ(ah, AR_PHY_CCK_DETECT);
+ regval &= (~AR_FAST_DIV_ENABLE);
+ regval |= ((value >> 7) & 0x1) <<
+ AR_FAST_DIV_ENABLE_S;
+ REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
+ ant_div_ctl1 =
+ ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
+ /* check whether antenna diversity is enabled */
+ if ((ant_div_ctl1 >> 0x6) == 0x3) {
+ regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
+ /*
+ * clear bits 25-30 main_lnaconf, alt_lnaconf,
+ * main_tb, alt_tb
+ */
+ regval &= (~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF |
+ AR_PHY_9485_ANT_DIV_ALT_LNACONF |
+ AR_PHY_9485_ANT_DIV_ALT_GAINTB |
+ AR_PHY_9485_ANT_DIV_MAIN_GAINTB));
+ /* by default use LNA1 for the main antenna */
+ regval |= (AR_PHY_9485_ANT_DIV_LNA1 <<
+ AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S);
+ regval |= (AR_PHY_9485_ANT_DIV_LNA2 <<
+ AR_PHY_9485_ANT_DIV_ALT_LNACONF_S);
+ REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
+ }
+
+
+ }
+
+}
+
+static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
+{
+ int drive_strength;
+ unsigned long reg;
+
+ drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH);
+
+ if (!drive_strength)
+ return;
+
+ reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1);
+ reg &= ~0x00ffffc0;
+ reg |= 0x5 << 21;
+ reg |= 0x5 << 18;
+ reg |= 0x5 << 15;
+ reg |= 0x5 << 12;
+ reg |= 0x5 << 9;
+ reg |= 0x5 << 6;
+ REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg);
+
+ reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2);
+ reg &= ~0xffffffe0;
+ reg |= 0x5 << 29;
+ reg |= 0x5 << 26;
+ reg |= 0x5 << 23;
+ reg |= 0x5 << 20;
+ reg |= 0x5 << 17;
+ reg |= 0x5 << 14;
+ reg |= 0x5 << 11;
+ reg |= 0x5 << 8;
+ reg |= 0x5 << 5;
+ REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg);
+
+ reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4);
+ reg &= ~0xff800000;
+ reg |= 0x5 << 29;
+ reg |= 0x5 << 26;
+ reg |= 0x5 << 23;
+ REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
+}
+
+static u16 ar9003_hw_atten_chain_get(struct ath_hw *ah, int chain,
+ struct ath9k_channel *chan)
+{
+ int f[3], t[3];
+ u16 value;
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+ if (chain >= 0 && chain < 3) {
+ if (IS_CHAN_2GHZ(chan))
+ return eep->modalHeader2G.xatten1DB[chain];
+ else if (eep->base_ext2.xatten1DBLow[chain] != 0) {
+ t[0] = eep->base_ext2.xatten1DBLow[chain];
+ f[0] = 5180;
+ t[1] = eep->modalHeader5G.xatten1DB[chain];
+ f[1] = 5500;
+ t[2] = eep->base_ext2.xatten1DBHigh[chain];
+ f[2] = 5785;
+ value = ar9003_hw_power_interpolate((s32) chan->channel,
+ f, t, 3);
+ return value;
+ } else
+ return eep->modalHeader5G.xatten1DB[chain];
+ }
+
+ return 0;
+}
+
+
+static u16 ar9003_hw_atten_chain_get_margin(struct ath_hw *ah, int chain,
+ struct ath9k_channel *chan)
+{
+ int f[3], t[3];
+ u16 value;
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+ if (chain >= 0 && chain < 3) {
+ if (IS_CHAN_2GHZ(chan))
+ return eep->modalHeader2G.xatten1Margin[chain];
+ else if (eep->base_ext2.xatten1MarginLow[chain] != 0) {
+ t[0] = eep->base_ext2.xatten1MarginLow[chain];
+ f[0] = 5180;
+ t[1] = eep->modalHeader5G.xatten1Margin[chain];
+ f[1] = 5500;
+ t[2] = eep->base_ext2.xatten1MarginHigh[chain];
+ f[2] = 5785;
+ value = ar9003_hw_power_interpolate((s32) chan->channel,
+ f, t, 3);
+ return value;
+ } else
+ return eep->modalHeader5G.xatten1Margin[chain];
+ }
+
+ return 0;
+}
+
+static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ int i;
+ u16 value;
+ unsigned long ext_atten_reg[3] = {AR_PHY_EXT_ATTEN_CTL_0,
+ AR_PHY_EXT_ATTEN_CTL_1,
+ AR_PHY_EXT_ATTEN_CTL_2,
+ };
+
+ /* Test value. if 0 then attenuation is unused. Don't load anything. */
+ for (i = 0; i < 3; i++) {
+ if (ah->txchainmask & BIT(i)) {
+ value = ar9003_hw_atten_chain_get(ah, i, chan);
+ REG_RMW_FIELD(ah, ext_atten_reg[i],
+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
+
+ value = ar9003_hw_atten_chain_get_margin(ah, i, chan);
+ REG_RMW_FIELD(ah, ext_atten_reg[i],
+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
+ value);
+ }
+ }
+}
+
+static int is_pmu_set(struct ath_hw *ah, u32 pmu_reg, int pmu_set)
+{
+ int timeout = 100;
+
+ while ((unsigned int)pmu_set != REG_READ(ah, pmu_reg)) {
+ if (timeout-- == 0)
+ return 0;
+ REG_WRITE(ah, pmu_reg, pmu_set);
+ udelay(10);
+ }
+
+ return 1;
+}
+
+static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
+{
+ int internal_regulator =
+ ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
+
+ if (internal_regulator) {
+ if (AR_SREV_9485(ah)) {
+ int reg_pmu_set;
+
+ reg_pmu_set = REG_READ(ah, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM;
+ REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
+ if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
+ return;
+
+ reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) |
+ (2 << 14) | (6 << 17) | (1 << 20) |
+ (3 << 24) | (1 << 28);
+
+ REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set);
+ if (!is_pmu_set(ah, AR_PHY_PMU1, reg_pmu_set))
+ return;
+
+ reg_pmu_set = (REG_READ(ah, AR_PHY_PMU2) & ~0xFFC00000)
+ | (4 << 26);
+ REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
+ if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
+ return;
+
+ reg_pmu_set = (REG_READ(ah, AR_PHY_PMU2) & ~0x00200000)
+ | (1 << 21);
+ REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
+ if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
+ return;
+ } else {
+ /* Internal regulator is ON. Write swreg register. */
+ int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
+ REG_WRITE(ah, AR_RTC_REG_CONTROL1,
+ REG_READ(ah, AR_RTC_REG_CONTROL1) &
+ (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
+ REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
+ /* Set REG_CONTROL1.SWREG_PROGRAM */
+ REG_WRITE(ah, AR_RTC_REG_CONTROL1,
+ REG_READ(ah,
+ AR_RTC_REG_CONTROL1) |
+ AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
+ }
+ } else {
+ if (AR_SREV_9485(ah)) {
+ REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0);
+ while (REG_READ_FIELD(ah, AR_PHY_PMU2,
+ AR_PHY_PMU2_PGM))
+ udelay(10);
+
+ REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
+ while (!REG_READ_FIELD(ah, AR_PHY_PMU1,
+ AR_PHY_PMU1_PWD))
+ udelay(10);
+ REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0x1);
+ while (!REG_READ_FIELD(ah, AR_PHY_PMU2,
+ AR_PHY_PMU2_PGM))
+ udelay(10);
+ } else
+ REG_WRITE(ah, AR_RTC_SLEEP_CLK,
+ (REG_READ(ah,
+ AR_RTC_SLEEP_CLK) |
+ AR_RTC_FORCE_SWREG_PRD));
+ }
+
+}
+
+static void ar9003_hw_apply_tuning_caps(struct ath_hw *ah)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0];
+
+ if (eep->baseEepHeader.featureEnable & 0x40) {
+ tuning_caps_param &= 0x7f;
+ REG_RMW_FIELD(ah, AR_CH0_XTAL, AR_CH0_XTAL_CAPINDAC,
+ tuning_caps_param);
+ REG_RMW_FIELD(ah, AR_CH0_XTAL, AR_CH0_XTAL_CAPOUTDAC,
+ tuning_caps_param);
+ }
+}
+
+static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
+ ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
+ ar9003_hw_drive_strength_apply(ah);
+ ar9003_hw_atten_apply(ah, chan);
+ if (!AR_SREV_9340(ah))
+ ar9003_hw_internal_regulator_apply(ah);
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ ar9003_hw_apply_tuning_caps(ah);
+}
+
+static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah __unused,
+ struct ath9k_channel *chan __unused)
+{
+}
+
+/*
+ * Returns the interpolated y value corresponding to the specified x value
+ * from the np ordered pairs of data (px,py).
+ * The pairs do not have to be in any order.
+ * If the specified x value is less than any of the px,
+ * the returned y value is equal to the py for the lowest px.
+ * If the specified x value is greater than any of the px,
+ * the returned y value is equal to the py for the highest px.
+ */
+static int ar9003_hw_power_interpolate(int32_t x,
+ int32_t *px, int32_t *py, uint16_t np)
+{
+ int ip = 0;
+ int lx = 0, ly = 0, lhave = 0;
+ int hx = 0, hy = 0, hhave = 0;
+ int dx = 0;
+ int y = 0;
+
+ lhave = 0;
+ hhave = 0;
+
+ /* identify best lower and higher x calibration measurement */
+ for (ip = 0; ip < np; ip++) {
+ dx = x - px[ip];
+
+ /* this measurement is higher than our desired x */
+ if (dx <= 0) {
+ if (!hhave || dx > (x - hx)) {
+ /* new best higher x measurement */
+ hx = px[ip];
+ hy = py[ip];
+ hhave = 1;
+ }
+ }
+ /* this measurement is lower than our desired x */
+ if (dx >= 0) {
+ if (!lhave || dx < (x - lx)) {
+ /* new best lower x measurement */
+ lx = px[ip];
+ ly = py[ip];
+ lhave = 1;
+ }
+ }
+ }
+
+ /* the low x is good */
+ if (lhave) {
+ /* so is the high x */
+ if (hhave) {
+ /* they're the same, so just pick one */
+ if (hx == lx)
+ y = ly;
+ else /* interpolate */
+ y = interpolate(x, lx, hx, ly, hy);
+ } else /* only low is good, use it */
+ y = ly;
+ } else if (hhave) /* only high is good, use it */
+ y = hy;
+ else /* nothing is good,this should never happen unless np=0, ???? */
+ y = -(1 << 30);
+ return y;
+}
+
+static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
+ u16 rateIndex, u16 freq, int is2GHz)
+{
+ u16 numPiers, i;
+ s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
+ s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ struct cal_tgt_pow_legacy *pEepromTargetPwr;
+ u8 *pFreqBin;
+
+ if (is2GHz) {
+ numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
+ pEepromTargetPwr = eep->calTargetPower2G;
+ pFreqBin = eep->calTarget_freqbin_2G;
+ } else {
+ numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
+ pEepromTargetPwr = eep->calTargetPower5G;
+ pFreqBin = eep->calTarget_freqbin_5G;
+ }
+
+ /*
+ * create array of channels and targetpower from
+ * targetpower piers stored on eeprom
+ */
+ for (i = 0; i < numPiers; i++) {
+ freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
+ targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
+ }
+
+ /* interpolate to get target power for given frequency */
+ return (u8) ar9003_hw_power_interpolate((s32) freq,
+ freqArray,
+ targetPowerArray, numPiers);
+}
+
+static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
+ u16 rateIndex,
+ u16 freq, int is2GHz)
+{
+ u16 numPiers, i;
+ s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
+ s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ struct cal_tgt_pow_ht *pEepromTargetPwr;
+ u8 *pFreqBin;
+
+ if (is2GHz) {
+ numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
+ pEepromTargetPwr = eep->calTargetPower2GHT20;
+ pFreqBin = eep->calTarget_freqbin_2GHT20;
+ } else {
+ numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
+ pEepromTargetPwr = eep->calTargetPower5GHT20;
+ pFreqBin = eep->calTarget_freqbin_5GHT20;
+ }
+
+ /*
+ * create array of channels and targetpower
+ * from targetpower piers stored on eeprom
+ */
+ for (i = 0; i < numPiers; i++) {
+ freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
+ targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
+ }
+
+ /* interpolate to get target power for given frequency */
+ return (u8) ar9003_hw_power_interpolate((s32) freq,
+ freqArray,
+ targetPowerArray, numPiers);
+}
+
+static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah,
+ u16 rateIndex,
+ u16 freq, int is2GHz)
+{
+ u16 numPiers, i;
+ s32 targetPowerArray[AR9300_NUM_5G_40_TARGET_POWERS];
+ s32 freqArray[AR9300_NUM_5G_40_TARGET_POWERS];
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ struct cal_tgt_pow_ht *pEepromTargetPwr;
+ u8 *pFreqBin;
+
+ if (is2GHz) {
+ numPiers = AR9300_NUM_2G_40_TARGET_POWERS;
+ pEepromTargetPwr = eep->calTargetPower2GHT40;
+ pFreqBin = eep->calTarget_freqbin_2GHT40;
+ } else {
+ numPiers = AR9300_NUM_5G_40_TARGET_POWERS;
+ pEepromTargetPwr = eep->calTargetPower5GHT40;
+ pFreqBin = eep->calTarget_freqbin_5GHT40;
+ }
+
+ /*
+ * create array of channels and targetpower from
+ * targetpower piers stored on eeprom
+ */
+ for (i = 0; i < numPiers; i++) {
+ freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
+ targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
+ }
+
+ /* interpolate to get target power for given frequency */
+ return (u8) ar9003_hw_power_interpolate((s32) freq,
+ freqArray,
+ targetPowerArray, numPiers);
+}
+
+static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah,
+ u16 rateIndex, u16 freq)
+{
+ u16 numPiers = AR9300_NUM_2G_CCK_TARGET_POWERS, i;
+ s32 targetPowerArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
+ s32 freqArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ struct cal_tgt_pow_legacy *pEepromTargetPwr = eep->calTargetPowerCck;
+ u8 *pFreqBin = eep->calTarget_freqbin_Cck;
+
+ /*
+ * create array of channels and targetpower from
+ * targetpower piers stored on eeprom
+ */
+ for (i = 0; i < numPiers; i++) {
+ freqArray[i] = FBIN2FREQ(pFreqBin[i], 1);
+ targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
+ }
+
+ /* interpolate to get target power for given frequency */
+ return (u8) ar9003_hw_power_interpolate((s32) freq,
+ freqArray,
+ targetPowerArray, numPiers);
+}
+
+/* Set tx power registers to array of values passed in */
+static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
+{
+#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
+ /* make sure forced gain is not set */
+ REG_WRITE(ah, AR_PHY_TX_FORCED_GAIN, 0);
+
+ /* Write the OFDM power per rate set */
+
+ /* 6 (LSB), 9, 12, 18 (MSB) */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE(0),
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) |
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
+
+ /* 24 (LSB), 36, 48, 54 (MSB) */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE(1),
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) |
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) |
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) |
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
+
+ /* Write the CCK power per rate set */
+
+ /* 1L (LSB), reserved, 2L, 2S (MSB) */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE(2),
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) |
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
+ /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0));
+
+ /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE(3),
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) |
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) |
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) |
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
+ );
+
+ /* Write the power for duplicated frames - HT40 */
+
+ /* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */
+ REG_WRITE(ah, 0xa3e0,
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
+ );
+
+ /* Write the HT20 power per rate set */
+
+ /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE(4),
+ POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) |
+ POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) |
+ POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) |
+ POW_SM(pPwrArray[ALL_TARGET_HT20_0_8_16], 0)
+ );
+
+ /* 6 (LSB), 7, 12, 13 (MSB) */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE(5),
+ POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) |
+ POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) |
+ POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) |
+ POW_SM(pPwrArray[ALL_TARGET_HT20_6], 0)
+ );
+
+ /* 14 (LSB), 15, 20, 21 */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE(9),
+ POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) |
+ POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) |
+ POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) |
+ POW_SM(pPwrArray[ALL_TARGET_HT20_14], 0)
+ );
+
+ /* Mixed HT20 and HT40 rates */
+
+ /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE(10),
+ POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) |
+ POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) |
+ POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) |
+ POW_SM(pPwrArray[ALL_TARGET_HT20_22], 0)
+ );
+
+ /*
+ * Write the HT40 power per rate set
+ * correct PAR difference between HT40 and HT20/LEGACY
+ * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
+ */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE(6),
+ POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) |
+ POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) |
+ POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) |
+ POW_SM(pPwrArray[ALL_TARGET_HT40_0_8_16], 0)
+ );
+
+ /* 6 (LSB), 7, 12, 13 (MSB) */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE(7),
+ POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) |
+ POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) |
+ POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) |
+ POW_SM(pPwrArray[ALL_TARGET_HT40_6], 0)
+ );
+
+ /* 14 (LSB), 15, 20, 21 */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE(11),
+ POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) |
+ POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) |
+ POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) |
+ POW_SM(pPwrArray[ALL_TARGET_HT40_14], 0)
+ );
+
+ return 0;
+#undef POW_SM
+}
+
+static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq,
+ u8 *targetPowerValT2)
+{
+ /* XXX: hard code for now, need to get from eeprom struct */
+ u8 ht40PowerIncForPdadc = 0;
+ int is2GHz = 0;
+ unsigned int i = 0;
+
+ if (freq < 4000)
+ is2GHz = 1;
+
+ targetPowerValT2[ALL_TARGET_LEGACY_6_24] =
+ ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_LEGACY_36] =
+ ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_LEGACY_48] =
+ ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_LEGACY_54] =
+ ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] =
+ ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L,
+ freq);
+ targetPowerValT2[ALL_TARGET_LEGACY_5S] =
+ ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_5S, freq);
+ targetPowerValT2[ALL_TARGET_LEGACY_11L] =
+ ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11L, freq);
+ targetPowerValT2[ALL_TARGET_LEGACY_11S] =
+ ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11S, freq);
+ targetPowerValT2[ALL_TARGET_HT20_0_8_16] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_HT20_1_3_9_11_17_19] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
+ freq, is2GHz);
+ targetPowerValT2[ALL_TARGET_HT20_4] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_HT20_5] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_HT20_6] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_HT20_7] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_HT20_12] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_HT20_13] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_HT20_14] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_HT20_15] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_HT20_20] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_HT20_21] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_HT20_22] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_HT20_23] =
+ ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
+ is2GHz);
+ targetPowerValT2[ALL_TARGET_HT40_0_8_16] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
+ is2GHz) + ht40PowerIncForPdadc;
+ targetPowerValT2[ALL_TARGET_HT40_1_3_9_11_17_19] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
+ freq,
+ is2GHz) + ht40PowerIncForPdadc;
+ targetPowerValT2[ALL_TARGET_HT40_4] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
+ is2GHz) + ht40PowerIncForPdadc;
+ targetPowerValT2[ALL_TARGET_HT40_5] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
+ is2GHz) + ht40PowerIncForPdadc;
+ targetPowerValT2[ALL_TARGET_HT40_6] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
+ is2GHz) + ht40PowerIncForPdadc;
+ targetPowerValT2[ALL_TARGET_HT40_7] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
+ is2GHz) + ht40PowerIncForPdadc;
+ targetPowerValT2[ALL_TARGET_HT40_12] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
+ is2GHz) + ht40PowerIncForPdadc;
+ targetPowerValT2[ALL_TARGET_HT40_13] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
+ is2GHz) + ht40PowerIncForPdadc;
+ targetPowerValT2[ALL_TARGET_HT40_14] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
+ is2GHz) + ht40PowerIncForPdadc;
+ targetPowerValT2[ALL_TARGET_HT40_15] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
+ is2GHz) + ht40PowerIncForPdadc;
+ targetPowerValT2[ALL_TARGET_HT40_20] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
+ is2GHz) + ht40PowerIncForPdadc;
+ targetPowerValT2[ALL_TARGET_HT40_21] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
+ is2GHz) + ht40PowerIncForPdadc;
+ targetPowerValT2[ALL_TARGET_HT40_22] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
+ is2GHz) + ht40PowerIncForPdadc;
+ targetPowerValT2[ALL_TARGET_HT40_23] =
+ ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
+ is2GHz) + ht40PowerIncForPdadc;
+
+ for (i = 0; i < ar9300RateSize; i++) {
+ DBG2("ath9k: "
+ "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
+ }
+}
+
+static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
+ int mode,
+ int ipier,
+ int ichain,
+ int *pfrequency,
+ int *pcorrection,
+ int *ptemperature, int *pvoltage)
+{
+ u8 *pCalPier;
+ struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct;
+ int is2GHz;
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+ if (ichain >= AR9300_MAX_CHAINS) {
+ DBG("ath9k: "
+ "Invalid chain index, must be less than %d\n",
+ AR9300_MAX_CHAINS);
+ return -1;
+ }
+
+ if (mode) { /* 5GHz */
+ if (ipier >= AR9300_NUM_5G_CAL_PIERS) {
+ DBG("ath9k: "
+ "Invalid 5GHz cal pier index, must be less than %d\n",
+ AR9300_NUM_5G_CAL_PIERS);
+ return -1;
+ }
+ pCalPier = &(eep->calFreqPier5G[ipier]);
+ pCalPierStruct = &(eep->calPierData5G[ichain][ipier]);
+ is2GHz = 0;
+ } else {
+ if (ipier >= AR9300_NUM_2G_CAL_PIERS) {
+ DBG("ath9k: "
+ "Invalid 2GHz cal pier index, must be less than %d\n",
+ AR9300_NUM_2G_CAL_PIERS);
+ return -1;
+ }
+
+ pCalPier = &(eep->calFreqPier2G[ipier]);
+ pCalPierStruct = &(eep->calPierData2G[ichain][ipier]);
+ is2GHz = 1;
+ }
+
+ *pfrequency = FBIN2FREQ(*pCalPier, is2GHz);
+ *pcorrection = pCalPierStruct->refPower;
+ *ptemperature = pCalPierStruct->tempMeas;
+ *pvoltage = pCalPierStruct->voltMeas;
+
+ return 0;
+}
+
+static int ar9003_hw_power_control_override(struct ath_hw *ah,
+ int frequency,
+ int *correction,
+ int *voltage __unused, int *temperature)
+{
+ int tempSlope = 0;
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ int f[3], t[3];
+
+ REG_RMW(ah, AR_PHY_TPC_11_B0,
+ (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
+ AR_PHY_TPC_OLPC_GAIN_DELTA);
+ if (ah->caps.tx_chainmask & BIT(1))
+ REG_RMW(ah, AR_PHY_TPC_11_B1,
+ (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
+ AR_PHY_TPC_OLPC_GAIN_DELTA);
+ if (ah->caps.tx_chainmask & BIT(2))
+ REG_RMW(ah, AR_PHY_TPC_11_B2,
+ (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
+ AR_PHY_TPC_OLPC_GAIN_DELTA);
+
+ /* enable open loop power control on chip */
+ REG_RMW(ah, AR_PHY_TPC_6_B0,
+ (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
+ AR_PHY_TPC_6_ERROR_EST_MODE);
+ if (ah->caps.tx_chainmask & BIT(1))
+ REG_RMW(ah, AR_PHY_TPC_6_B1,
+ (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
+ AR_PHY_TPC_6_ERROR_EST_MODE);
+ if (ah->caps.tx_chainmask & BIT(2))
+ REG_RMW(ah, AR_PHY_TPC_6_B2,
+ (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
+ AR_PHY_TPC_6_ERROR_EST_MODE);
+
+ /*
+ * enable temperature compensation
+ * Need to use register names
+ */
+ if (frequency < 4000)
+ tempSlope = eep->modalHeader2G.tempSlope;
+ else if (eep->base_ext2.tempSlopeLow != 0) {
+ t[0] = eep->base_ext2.tempSlopeLow;
+ f[0] = 5180;
+ t[1] = eep->modalHeader5G.tempSlope;
+ f[1] = 5500;
+ t[2] = eep->base_ext2.tempSlopeHigh;
+ f[2] = 5785;
+ tempSlope = ar9003_hw_power_interpolate((s32) frequency,
+ f, t, 3);
+ } else
+ tempSlope = eep->modalHeader5G.tempSlope;
+
+ REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
+ REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
+ temperature[0]);
+
+ return 0;
+}
+
+/* Apply the recorded correction values. */
+static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
+{
+ int ichain, ipier, npier;
+ int mode;
+ int lfrequency[AR9300_MAX_CHAINS],
+ lcorrection[AR9300_MAX_CHAINS],
+ ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS];
+ int hfrequency[AR9300_MAX_CHAINS],
+ hcorrection[AR9300_MAX_CHAINS],
+ htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS];
+ int fdiff;
+ int correction[AR9300_MAX_CHAINS],
+ voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS];
+ int pfrequency, pcorrection, ptemperature, pvoltage;
+
+ mode = (frequency >= 4000);
+ if (mode)
+ npier = AR9300_NUM_5G_CAL_PIERS;
+ else
+ npier = AR9300_NUM_2G_CAL_PIERS;
+
+ for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
+ lfrequency[ichain] = 0;
+ hfrequency[ichain] = 100000;
+ }
+ /* identify best lower and higher frequency calibration measurement */
+ for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
+ for (ipier = 0; ipier < npier; ipier++) {
+ if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain,
+ &pfrequency, &pcorrection,
+ &ptemperature, &pvoltage)) {
+ fdiff = frequency - pfrequency;
+
+ /*
+ * this measurement is higher than
+ * our desired frequency
+ */
+ if (fdiff <= 0) {
+ if (hfrequency[ichain] <= 0 ||
+ hfrequency[ichain] >= 100000 ||
+ fdiff >
+ (frequency - hfrequency[ichain])) {
+ /*
+ * new best higher
+ * frequency measurement
+ */
+ hfrequency[ichain] = pfrequency;
+ hcorrection[ichain] =
+ pcorrection;
+ htemperature[ichain] =
+ ptemperature;
+ hvoltage[ichain] = pvoltage;
+ }
+ }
+ if (fdiff >= 0) {
+ if (lfrequency[ichain] <= 0
+ || fdiff <
+ (frequency - lfrequency[ichain])) {
+ /*
+ * new best lower
+ * frequency measurement
+ */
+ lfrequency[ichain] = pfrequency;
+ lcorrection[ichain] =
+ pcorrection;
+ ltemperature[ichain] =
+ ptemperature;
+ lvoltage[ichain] = pvoltage;
+ }
+ }
+ }
+ }
+ }
+
+ /* interpolate */
+ for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
+ DBG2("ath9k: "
+ "ch=%d f=%d low=%d %d h=%d %d\n",
+ ichain, frequency, lfrequency[ichain],
+ lcorrection[ichain], hfrequency[ichain],
+ hcorrection[ichain]);
+ /* they're the same, so just pick one */
+ if (hfrequency[ichain] == lfrequency[ichain]) {
+ correction[ichain] = lcorrection[ichain];
+ voltage[ichain] = lvoltage[ichain];
+ temperature[ichain] = ltemperature[ichain];
+ }
+ /* the low frequency is good */
+ else if (frequency - lfrequency[ichain] < 1000) {
+ /* so is the high frequency, interpolate */
+ if (hfrequency[ichain] - frequency < 1000) {
+
+ correction[ichain] = interpolate(frequency,
+ lfrequency[ichain],
+ hfrequency[ichain],
+ lcorrection[ichain],
+ hcorrection[ichain]);
+
+ temperature[ichain] = interpolate(frequency,
+ lfrequency[ichain],
+ hfrequency[ichain],
+ ltemperature[ichain],
+ htemperature[ichain]);
+
+ voltage[ichain] = interpolate(frequency,
+ lfrequency[ichain],
+ hfrequency[ichain],
+ lvoltage[ichain],
+ hvoltage[ichain]);
+ }
+ /* only low is good, use it */
+ else {
+ correction[ichain] = lcorrection[ichain];
+ temperature[ichain] = ltemperature[ichain];
+ voltage[ichain] = lvoltage[ichain];
+ }
+ }
+ /* only high is good, use it */
+ else if (hfrequency[ichain] - frequency < 1000) {
+ correction[ichain] = hcorrection[ichain];
+ temperature[ichain] = htemperature[ichain];
+ voltage[ichain] = hvoltage[ichain];
+ } else { /* nothing is good, presume 0???? */
+ correction[ichain] = 0;
+ temperature[ichain] = 0;
+ voltage[ichain] = 0;
+ }
+ }
+
+ ar9003_hw_power_control_override(ah, frequency, correction, voltage,
+ temperature);
+
+ DBG2("ath9k: "
+ "for frequency=%d, calibration correction = %d %d %d\n",
+ frequency, correction[0], correction[1], correction[2]);
+
+ return 0;
+}
+
+static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep,
+ int idx,
+ int edge,
+ int is2GHz)
+{
+ struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
+ struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
+
+ if (is2GHz)
+ return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge]);
+ else
+ return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge]);
+}
+
+static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
+ int idx,
+ unsigned int edge,
+ u16 freq,
+ int is2GHz)
+{
+ struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
+ struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
+
+ u8 *ctl_freqbin = is2GHz ?
+ &eep->ctl_freqbin_2G[idx][0] :
+ &eep->ctl_freqbin_5G[idx][0];
+
+ if (is2GHz) {
+ if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq &&
+ CTL_EDGE_FLAGS(ctl_2g[idx].ctlEdges[edge - 1]))
+ return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge - 1]);
+ } else {
+ if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq &&
+ CTL_EDGE_FLAGS(ctl_5g[idx].ctlEdges[edge - 1]))
+ return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge - 1]);
+ }
+
+ return MAX_RATE_POWER;
+}
+
+/*
+ * Find the maximum conformance test limit for the given channel and CTL info
+ */
+static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
+ u16 freq, int idx, int is2GHz)
+{
+ u16 twiceMaxEdgePower = MAX_RATE_POWER;
+ u8 *ctl_freqbin = is2GHz ?
+ &eep->ctl_freqbin_2G[idx][0] :
+ &eep->ctl_freqbin_5G[idx][0];
+ u16 num_edges = is2GHz ?
+ AR9300_NUM_BAND_EDGES_2G : AR9300_NUM_BAND_EDGES_5G;
+ unsigned int edge;
+
+ /* Get the edge power */
+ for (edge = 0;
+ (edge < num_edges) && (ctl_freqbin[edge] != AR5416_BCHAN_UNUSED);
+ edge++) {
+ /*
+ * If there's an exact channel match or an inband flag set
+ * on the lower channel use the given rdEdgePower
+ */
+ if (freq == ath9k_hw_fbin2freq(ctl_freqbin[edge], is2GHz)) {
+ twiceMaxEdgePower =
+ ar9003_hw_get_direct_edge_power(eep, idx,
+ edge, is2GHz);
+ break;
+ } else if ((edge > 0) &&
+ (freq < ath9k_hw_fbin2freq(ctl_freqbin[edge],
+ is2GHz))) {
+ twiceMaxEdgePower =
+ ar9003_hw_get_indirect_edge_power(eep, idx,
+ edge, freq,
+ is2GHz);
+ /*
+ * Leave loop - no more affecting edges possible in
+ * this monotonic increasing list
+ */
+ break;
+ }
+ }
+ return twiceMaxEdgePower;
+}
+
+static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 *pPwrArray, u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+ u16 powerLimit)
+{
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
+ u16 twiceMaxEdgePower = MAX_RATE_POWER;
+ static const u16 tpScaleReductionTable[5] = {
+ 0, 3, 6, 9, MAX_RATE_POWER
+ };
+ int i;
+ int16_t twiceLargestAntenna;
+ u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ static const u16 ctlModesFor11a[] = {
+ CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
+ };
+ static const u16 ctlModesFor11g[] = {
+ CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT,
+ CTL_11G_EXT, CTL_2GHT40
+ };
+ u16 numCtlModes;
+ const u16 *pCtlMode;
+ u16 ctlMode, freq;
+ struct chan_centers centers;
+ u8 *ctlIndex;
+ u8 ctlNum;
+ u16 twiceMinEdgePower;
+ int is2ghz = IS_CHAN_2GHZ(chan);
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ /* Compute TxPower reduction due to Antenna Gain */
+ if (is2ghz)
+ twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
+ else
+ twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
+
+ twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
+ twiceLargestAntenna, 0);
+
+ /*
+ * scaledPower is the minimum of the user input power level
+ * and the regulatory allowed power level
+ */
+ maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+
+ if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
+ maxRegAllowedPower -=
+ (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
+ }
+
+ scaledPower = min(powerLimit, maxRegAllowedPower);
+
+ /*
+ * Reduce scaled Power by number of chains active to get
+ * to per chain tx power level
+ */
+ switch (ar5416_get_ntxchains(ah->txchainmask)) {
+ case 1:
+ break;
+ case 2:
+ if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
+ scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+ else
+ scaledPower = 0;
+ break;
+ case 3:
+ if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
+ scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+ else
+ scaledPower = 0;
+ break;
+ }
+
+ scaledPower = max((u16)0, scaledPower);
+
+ /*
+ * Get target powers from EEPROM - our baseline for TX Power
+ */
+ if (is2ghz) {
+ /* Setup for CTL modes */
+ /* CTL_11B, CTL_11G, CTL_2GHT20 */
+ numCtlModes =
+ ARRAY_SIZE(ctlModesFor11g) -
+ SUB_NUM_CTL_MODES_AT_2G_40;
+ pCtlMode = ctlModesFor11g;
+ if (IS_CHAN_HT40(chan))
+ /* All 2G CTL's */
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+ } else {
+ /* Setup for CTL modes */
+ /* CTL_11A, CTL_5GHT20 */
+ numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
+ SUB_NUM_CTL_MODES_AT_5G_40;
+ pCtlMode = ctlModesFor11a;
+ if (IS_CHAN_HT40(chan))
+ /* All 5G CTL's */
+ numCtlModes = ARRAY_SIZE(ctlModesFor11a);
+ }
+
+ /*
+ * For MIMO, need to apply regulatory caps individually across
+ * dynamically running modes: CCK, OFDM, HT20, HT40
+ *
+ * The outer loop walks through each possible applicable runtime mode.
+ * The inner loop walks through each ctlIndex entry in EEPROM.
+ * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
+ */
+ for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+ int isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+ (pCtlMode[ctlMode] == CTL_2GHT40);
+ if (isHt40CtlMode)
+ freq = centers.synth_center;
+ else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+ freq = centers.ext_center;
+ else
+ freq = centers.ctl_center;
+
+ DBG2("ath9k: "
+ "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, EXT_ADDITIVE %d\n",
+ ctlMode, numCtlModes, isHt40CtlMode,
+ (pCtlMode[ctlMode] & EXT_ADDITIVE));
+
+ /* walk through each CTL index stored in EEPROM */
+ if (is2ghz) {
+ ctlIndex = pEepData->ctlIndex_2G;
+ ctlNum = AR9300_NUM_CTLS_2G;
+ } else {
+ ctlIndex = pEepData->ctlIndex_5G;
+ ctlNum = AR9300_NUM_CTLS_5G;
+ }
+
+ for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) {
+ DBG2("ath9k: "
+ "LOOP-Ctlidx %d: cfgCtl 0x%2.2x pCtlMode 0x%2.2x ctlIndex 0x%2.2x chan %d\n",
+ i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
+ chan->channel);
+
+ /*
+ * compare test group from regulatory
+ * channel list with test mode from pCtlMode
+ * list
+ */
+ if ((((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ ctlIndex[i]) ||
+ (((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ ((ctlIndex[i] & CTL_MODE_M) |
+ SD_NO_CTL))) {
+ twiceMinEdgePower =
+ ar9003_hw_get_max_edge_power(pEepData,
+ freq, i,
+ is2ghz);
+
+ if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
+ /*
+ * Find the minimum of all CTL
+ * edge powers that apply to
+ * this channel
+ */
+ twiceMaxEdgePower =
+ min(twiceMaxEdgePower,
+ twiceMinEdgePower);
+ else {
+ /* specific */
+ twiceMaxEdgePower =
+ twiceMinEdgePower;
+ break;
+ }
+ }
+ }
+
+ minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
+
+ DBG2("ath9k: "
+ "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d sP %d minCtlPwr %d\n",
+ ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
+ scaledPower, minCtlPower);
+
+ /* Apply ctl mode to correct target power set */
+ switch (pCtlMode[ctlMode]) {
+ case CTL_11B:
+ for (i = ALL_TARGET_LEGACY_1L_5L;
+ i <= ALL_TARGET_LEGACY_11S; i++)
+ pPwrArray[i] =
+ (u8)min((u16)pPwrArray[i],
+ minCtlPower);
+ break;
+ case CTL_11A:
+ case CTL_11G:
+ for (i = ALL_TARGET_LEGACY_6_24;
+ i <= ALL_TARGET_LEGACY_54; i++)
+ pPwrArray[i] =
+ (u8)min((u16)pPwrArray[i],
+ minCtlPower);
+ break;
+ case CTL_5GHT20:
+ case CTL_2GHT20:
+ for (i = ALL_TARGET_HT20_0_8_16;
+ i <= ALL_TARGET_HT20_21; i++)
+ pPwrArray[i] =
+ (u8)min((u16)pPwrArray[i],
+ minCtlPower);
+ pPwrArray[ALL_TARGET_HT20_22] =
+ (u8)min((u16)pPwrArray[ALL_TARGET_HT20_22],
+ minCtlPower);
+ pPwrArray[ALL_TARGET_HT20_23] =
+ (u8)min((u16)pPwrArray[ALL_TARGET_HT20_23],
+ minCtlPower);
+ break;
+ case CTL_5GHT40:
+ case CTL_2GHT40:
+ for (i = ALL_TARGET_HT40_0_8_16;
+ i <= ALL_TARGET_HT40_23; i++)
+ pPwrArray[i] =
+ (u8)min((u16)pPwrArray[i],
+ minCtlPower);
+ break;
+ default:
+ break;
+ }
+ } /* end ctl mode checking */
+}
+
+static inline u8 mcsidx_to_tgtpwridx(unsigned int mcs_idx, u8 base_pwridx)
+{
+ u8 mod_idx = mcs_idx % 8;
+
+ if (mod_idx <= 3)
+ return mod_idx ? (base_pwridx + 1) : base_pwridx;
+ else
+ return base_pwridx + 4 * (mcs_idx / 8) + mod_idx - 2;
+}
+
+static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
+ struct ath9k_channel *chan, u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+ u8 powerLimit, int test)
+{
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ struct ar9300_modal_eep_header *modal_hdr;
+ u8 targetPowerValT2[ar9300RateSize];
+ u8 target_power_val_t2_eep[ar9300RateSize];
+ unsigned int i = 0, paprd_scale_factor = 0;
+ u8 pwr_idx, min_pwridx = 0;
+
+ ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2);
+
+ if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
+ if (IS_CHAN_2GHZ(chan))
+ modal_hdr = &eep->modalHeader2G;
+ else
+ modal_hdr = &eep->modalHeader5G;
+
+ ah->paprd_ratemask =
+ (uint32_t)(modal_hdr->papdRateMaskHt20) &
+ AR9300_PAPRD_RATE_MASK;
+
+ ah->paprd_ratemask_ht40 =
+ (uint32_t)(modal_hdr->papdRateMaskHt40) &
+ AR9300_PAPRD_RATE_MASK;
+
+ paprd_scale_factor = ar9003_get_paprd_scale_factor(ah, chan);
+ min_pwridx = IS_CHAN_HT40(chan) ? ALL_TARGET_HT40_0_8_16 :
+ ALL_TARGET_HT20_0_8_16;
+
+ if (!ah->paprd_table_write_done) {
+ memcpy(target_power_val_t2_eep, targetPowerValT2,
+ sizeof(targetPowerValT2));
+ for (i = 0; i < 24; i++) {
+ pwr_idx = mcsidx_to_tgtpwridx(i, min_pwridx);
+ if (ah->paprd_ratemask & (1 << i)) {
+ if (targetPowerValT2[pwr_idx] &&
+ targetPowerValT2[pwr_idx] ==
+ target_power_val_t2_eep[pwr_idx])
+ targetPowerValT2[pwr_idx] -=
+ paprd_scale_factor;
+ }
+ }
+ }
+ memcpy(target_power_val_t2_eep, targetPowerValT2,
+ sizeof(targetPowerValT2));
+ }
+
+ ar9003_hw_set_power_per_rate_table(ah, chan,
+ targetPowerValT2, cfgCtl,
+ twiceAntennaReduction,
+ twiceMaxRegulatoryPower,
+ powerLimit);
+
+ if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
+ for (i = 0; i < ar9300RateSize; i++) {
+ if ((ah->paprd_ratemask & (1 << i)) &&
+ ((unsigned int)abs(targetPowerValT2[i] -
+ target_power_val_t2_eep[i]) >
+ paprd_scale_factor)) {
+ ah->paprd_ratemask &= ~(1 << i);
+ DBG2("ath9k: "
+ "paprd disabled for mcs %d\n", i);
+ }
+ }
+ }
+
+ regulatory->max_power_level = 0;
+ for (i = 0; i < ar9300RateSize; i++) {
+ if (targetPowerValT2[i] > regulatory->max_power_level)
+ regulatory->max_power_level = targetPowerValT2[i];
+ }
+
+ if (test)
+ return;
+
+ for (i = 0; i < ar9300RateSize; i++) {
+ DBG2("ath9k: "
+ "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
+ }
+
+ /*
+ * This is the TX power we send back to driver core,
+ * and it can use to pass to userspace to display our
+ * currently configured TX power setting.
+ *
+ * Since power is rate dependent, use one of the indices
+ * from the AR9300_Rates enum to select an entry from
+ * targetPowerValT2[] to report. Currently returns the
+ * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
+ * as CCK power is less interesting (?).
+ */
+ i = ALL_TARGET_LEGACY_6_24; /* legacy */
+ if (IS_CHAN_HT40(chan))
+ i = ALL_TARGET_HT40_0_8_16; /* ht40 */
+ else if (IS_CHAN_HT20(chan))
+ i = ALL_TARGET_HT20_0_8_16; /* ht20 */
+
+ ah->txpower_limit = targetPowerValT2[i];
+ regulatory->max_power_level = targetPowerValT2[i];
+
+ /* Write target power array to registers */
+ ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
+ ar9003_hw_calibration_apply(ah, chan->channel);
+
+ if (IS_CHAN_2GHZ(chan)) {
+ if (IS_CHAN_HT40(chan))
+ i = ALL_TARGET_HT40_0_8_16;
+ else
+ i = ALL_TARGET_HT20_0_8_16;
+ } else {
+ if (IS_CHAN_HT40(chan))
+ i = ALL_TARGET_HT40_7;
+ else
+ i = ALL_TARGET_HT20_7;
+ }
+ ah->paprd_target_power = targetPowerValT2[i];
+}
+
+static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah __unused,
+ u16 i __unused, int is2GHz __unused)
+{
+ return AR_NO_SPUR;
+}
+
+s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+ return (eep->baseEepHeader.txrxgain >> 4) & 0xf; /* bits 7:4 */
+}
+
+s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+ return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */
+}
+
+u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, int is_2ghz)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+ if (is_2ghz)
+ return eep->modalHeader2G.spurChans;
+ else
+ return eep->modalHeader5G.spurChans;
+}
+
+unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+ if (IS_CHAN_2GHZ(chan))
+ return MS((uint32_t)(eep->modalHeader2G.papdRateMaskHt20),
+ AR9300_PAPRD_SCALE_1);
+ else {
+ if (chan->channel >= 5700)
+ return MS((uint32_t)(eep->modalHeader5G.papdRateMaskHt20),
+ AR9300_PAPRD_SCALE_1);
+ else if (chan->channel >= 5400)
+ return MS((uint32_t)(eep->modalHeader5G.papdRateMaskHt40),
+ AR9300_PAPRD_SCALE_2);
+ else
+ return MS((uint32_t)(eep->modalHeader5G.papdRateMaskHt40),
+ AR9300_PAPRD_SCALE_1);
+ }
+}
+
+const struct eeprom_ops eep_ar9300_ops = {
+ .check_eeprom = ath9k_hw_ar9300_check_eeprom,
+ .get_eeprom = ath9k_hw_ar9300_get_eeprom,
+ .fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
+ .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
+ .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
+ .set_board_values = ath9k_hw_ar9300_set_board_values,
+ .set_addac = ath9k_hw_ar9300_set_addac,
+ .set_txpower = ath9k_hw_ar9300_set_txpower,
+ .get_spur_channel = ath9k_hw_ar9300_get_spur_channel
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_hw.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_hw.c
new file mode 100644
index 00000000..f3020fd7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_hw.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "ar9003_mac.h"
+#include "ar9003_2p2_initvals.h"
+#include "ar9485_initvals.h"
+#include "ar9340_initvals.h"
+
+/* General hardware code for the AR9003 hadware family */
+
+/*
+ * The AR9003 family uses a new INI format (pre, core, post
+ * arrays per subsystem). This provides support for the
+ * AR9003 2.2 chipsets.
+ */
+static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
+{
+ if (AR_SREV_9340(ah)) {
+ /* mac */
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+ ar9340_1p0_mac_core,
+ ARRAY_SIZE(ar9340_1p0_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9340_1p0_mac_postamble,
+ ARRAY_SIZE(ar9340_1p0_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9340_1p0_baseband_core,
+ ARRAY_SIZE(ar9340_1p0_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9340_1p0_baseband_postamble,
+ ARRAY_SIZE(ar9340_1p0_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9340_1p0_radio_core,
+ ARRAY_SIZE(ar9340_1p0_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+ ar9340_1p0_radio_postamble,
+ ARRAY_SIZE(ar9340_1p0_radio_postamble), 5);
+
+ /* soc */
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9340_1p0_soc_preamble,
+ ARRAY_SIZE(ar9340_1p0_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9340_1p0_soc_postamble,
+ ARRAY_SIZE(ar9340_1p0_soc_postamble), 5);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9340Common_wo_xlna_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
+ 5);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_high_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Modes_high_ob_db_tx_gain_table_1p0),
+ 5);
+
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9340Modes_fast_clock_1p0,
+ ARRAY_SIZE(ar9340Modes_fast_clock_1p0),
+ 3);
+
+ INIT_INI_ARRAY(&ah->iniModesAdditional_40M,
+ ar9340_1p0_radio_core_40M,
+ ARRAY_SIZE(ar9340_1p0_radio_core_40M),
+ 2);
+ } else if (AR_SREV_9485_11(ah)) {
+ /* mac */
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+ ar9485_1_1_mac_core,
+ ARRAY_SIZE(ar9485_1_1_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9485_1_1_mac_postamble,
+ ARRAY_SIZE(ar9485_1_1_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1,
+ ARRAY_SIZE(ar9485_1_1), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9485_1_1_baseband_core,
+ ARRAY_SIZE(ar9485_1_1_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9485_1_1_baseband_postamble,
+ ARRAY_SIZE(ar9485_1_1_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9485_1_1_radio_core,
+ ARRAY_SIZE(ar9485_1_1_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+ ar9485_1_1_radio_postamble,
+ ARRAY_SIZE(ar9485_1_1_radio_postamble), 2);
+
+ /* soc */
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9485_1_1_soc_preamble,
+ ARRAY_SIZE(ar9485_1_1_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9485Common_wo_xlna_rx_gain_1_1,
+ ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485_modes_lowest_ob_db_tx_gain_1_1,
+ ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
+ 5);
+
+ /* Load PCIE SERDES settings from INI */
+
+ /* Awake Setting */
+
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9485_1_1_pcie_phy_clkreq_disable_L1,
+ ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
+ 2);
+
+ /* Sleep Setting */
+
+ INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+ ar9485_1_1_pcie_phy_clkreq_disable_L1,
+ ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
+ 2);
+ } else {
+ /* mac */
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+ ar9300_2p2_mac_core,
+ ARRAY_SIZE(ar9300_2p2_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9300_2p2_mac_postamble,
+ ARRAY_SIZE(ar9300_2p2_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9300_2p2_baseband_core,
+ ARRAY_SIZE(ar9300_2p2_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9300_2p2_baseband_postamble,
+ ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9300_2p2_radio_core,
+ ARRAY_SIZE(ar9300_2p2_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+ ar9300_2p2_radio_postamble,
+ ARRAY_SIZE(ar9300_2p2_radio_postamble), 5);
+
+ /* soc */
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9300_2p2_soc_preamble,
+ ARRAY_SIZE(ar9300_2p2_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9300_2p2_soc_postamble,
+ ARRAY_SIZE(ar9300_2p2_soc_postamble), 5);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9300Common_rx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
+ 5);
+
+ /* Load PCIE SERDES settings from INI */
+
+ /* Awake Setting */
+
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
+ ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
+ 2);
+
+ /* Sleep Setting */
+
+ INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+ ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
+ ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
+ 2);
+
+ /* Fast clock modal settings */
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9300Modes_fast_clock_2p2,
+ ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
+ 3);
+ }
+}
+
+static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
+{
+ switch (ar9003_hw_get_tx_gain_idx(ah)) {
+ case 0:
+ default:
+ if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485_modes_lowest_ob_db_tx_gain_1_1,
+ ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
+ 5);
+ else
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
+ 5);
+ break;
+ case 1:
+ if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485Modes_high_ob_db_tx_gain_1_1,
+ ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
+ 5);
+ else
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_high_ob_db_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
+ 5);
+ break;
+ case 2:
+ if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485Modes_low_ob_db_tx_gain_1_1,
+ ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
+ 5);
+ else
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_low_ob_db_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
+ 5);
+ break;
+ case 3:
+ if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485Modes_high_power_tx_gain_1_1,
+ ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
+ 5);
+ else
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_high_power_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
+ 5);
+ break;
+ }
+}
+
+static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
+{
+ switch (ar9003_hw_get_rx_gain_idx(ah)) {
+ case 0:
+ default:
+ if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9340Common_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
+ 2);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9485Common_wo_xlna_rx_gain_1_1,
+ ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
+ 2);
+ else
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9300Common_rx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
+ 2);
+ break;
+ case 1:
+ if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9340Common_wo_xlna_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
+ 2);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9485Common_wo_xlna_rx_gain_1_1,
+ ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
+ 2);
+ else
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9300Common_wo_xlna_rx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
+ 2);
+ break;
+ }
+}
+
+/* set gain table pointers according to values read from the eeprom */
+static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
+{
+ ar9003_tx_gain_table_apply(ah);
+ ar9003_rx_gain_table_apply(ah);
+}
+
+/*
+ * Helper for ASPM support.
+ *
+ * Disable PLL when in L0s as well as receiver clock when in L1.
+ * This power saving option must be enabled through the SerDes.
+ *
+ * Programming the SerDes must go through the same 288 bit serial shift
+ * register as the other analog registers. Hence the 9 writes.
+ */
+static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
+ int restore,
+ int power_off)
+{
+ if (ah->is_pciexpress != 1)
+ return;
+
+ /* Do not touch SerDes registers */
+ if (ah->config.pcie_powersave_enable == 2)
+ return;
+
+ /* Nothing to do on restore for 11N */
+ if (!restore) {
+ /* set bit 19 to allow forcing of pcie core into L1 state */
+ REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+
+ /* Several PCIe massages to ensure proper behaviour */
+ if (ah->config.pcie_waen)
+ REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
+ else
+ REG_WRITE(ah, AR_WA, ah->WARegVal);
+ }
+
+ /*
+ * Configire PCIE after Ini init. SERDES values now come from ini file
+ * This enables PCIe low power mode.
+ */
+ if (ah->config.pcieSerDesWrite) {
+ unsigned int i;
+ struct ar5416IniArray *array;
+
+ array = power_off ? &ah->iniPcieSerdes :
+ &ah->iniPcieSerdesLowPower;
+
+ for (i = 0; i < array->ia_rows; i++) {
+ REG_WRITE(ah,
+ INI_RA(array, i, 0),
+ INI_RA(array, i, 1));
+ }
+ }
+}
+
+/* Sets up the AR9003 hardware familiy callbacks */
+void ar9003_hw_attach_ops(struct ath_hw *ah)
+{
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+ struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+
+ priv_ops->init_mode_regs = ar9003_hw_init_mode_regs;
+ priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
+
+ ops->config_pci_powersave = ar9003_hw_configpcipowersave;
+
+ ar9003_hw_attach_phy_ops(ah);
+ ar9003_hw_attach_calib_ops(ah);
+ ar9003_hw_attach_mac_ops(ah);
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_mac.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_mac.c
new file mode 100644
index 00000000..1fa4039c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_mac.c
@@ -0,0 +1,669 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <ipxe/io.h>
+
+#include "hw.h"
+#include "ar9003_mac.h"
+
+static void ar9003_hw_rx_enable(struct ath_hw *hw)
+{
+ REG_WRITE(hw, AR_CR, 0);
+}
+
+static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
+{
+ int checksum;
+
+ checksum = ads->info + ads->link
+ + ads->data0 + ads->ctl3
+ + ads->data1 + ads->ctl5
+ + ads->data2 + ads->ctl7
+ + ads->data3 + ads->ctl9;
+
+ return ((checksum & 0xffff) + (checksum >> 16)) & AR_TxPtrChkSum;
+}
+
+static void ar9003_hw_set_desc_link(void *ds, u32 ds_link)
+{
+ struct ar9003_txc *ads = ds;
+
+ ads->link = ds_link;
+ ads->ctl10 &= ~AR_TxPtrChkSum;
+ ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
+}
+
+static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link)
+{
+ struct ar9003_txc *ads = ds;
+
+ *ds_link = &ads->link;
+}
+
+static int ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
+{
+ u32 isr = 0;
+ u32 mask2 = 0;
+ struct ath9k_hw_capabilities *pCap = &ah->caps;
+ u32 sync_cause = 0;
+
+ if (ah->ah_ier & AR_IER_ENABLE) {
+ if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
+ if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
+ == AR_RTC_STATUS_ON)
+ isr = REG_READ(ah, AR_ISR);
+ }
+
+ sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT;
+
+ *masked = 0;
+
+ if (!isr && !sync_cause)
+ return 0;
+ } else {
+ *masked = 0;
+ isr = REG_READ(ah, AR_ISR);
+ }
+
+ if (isr) {
+ if (isr & AR_ISR_BCNMISC) {
+ u32 isr2;
+ isr2 = REG_READ(ah, AR_ISR_S2);
+
+ mask2 |= ((isr2 & AR_ISR_S2_TIM) >>
+ MAP_ISR_S2_TIM);
+ mask2 |= ((isr2 & AR_ISR_S2_DTIM) >>
+ MAP_ISR_S2_DTIM);
+ mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >>
+ MAP_ISR_S2_DTIMSYNC);
+ mask2 |= ((isr2 & AR_ISR_S2_CABEND) >>
+ MAP_ISR_S2_CABEND);
+ mask2 |= ((isr2 & AR_ISR_S2_GTT) <<
+ MAP_ISR_S2_GTT);
+ mask2 |= ((isr2 & AR_ISR_S2_CST) <<
+ MAP_ISR_S2_CST);
+ mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >>
+ MAP_ISR_S2_TSFOOR);
+ mask2 |= ((isr2 & AR_ISR_S2_BB_WATCHDOG) >>
+ MAP_ISR_S2_BB_WATCHDOG);
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+ REG_WRITE(ah, AR_ISR_S2, isr2);
+ isr &= ~AR_ISR_BCNMISC;
+ }
+ }
+
+ if ((pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED))
+ isr = REG_READ(ah, AR_ISR_RAC);
+
+ if (isr == 0xffffffff) {
+ *masked = 0;
+ return 0;
+ }
+
+ *masked = isr & ATH9K_INT_COMMON;
+
+ if (ah->config.rx_intr_mitigation)
+ if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
+ *masked |= ATH9K_INT_RXLP;
+
+ if (ah->config.tx_intr_mitigation)
+ if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
+ *masked |= ATH9K_INT_TX;
+
+ if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR))
+ *masked |= ATH9K_INT_RXLP;
+
+ if (isr & AR_ISR_HP_RXOK)
+ *masked |= ATH9K_INT_RXHP;
+
+ if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
+ *masked |= ATH9K_INT_TX;
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+ u32 s0, s1;
+ s0 = REG_READ(ah, AR_ISR_S0);
+ REG_WRITE(ah, AR_ISR_S0, s0);
+ s1 = REG_READ(ah, AR_ISR_S1);
+ REG_WRITE(ah, AR_ISR_S1, s1);
+
+ isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR |
+ AR_ISR_TXEOL);
+ }
+ }
+
+ if (isr & AR_ISR_GENTMR) {
+ u32 s5;
+
+ if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
+ s5 = REG_READ(ah, AR_ISR_S5_S);
+ else
+ s5 = REG_READ(ah, AR_ISR_S5);
+
+ ah->intr_gen_timer_trigger =
+ MS(s5, AR_ISR_S5_GENTIMER_TRIG);
+
+ ah->intr_gen_timer_thresh =
+ MS(s5, AR_ISR_S5_GENTIMER_THRESH);
+
+ if (ah->intr_gen_timer_trigger)
+ *masked |= ATH9K_INT_GENTIMER;
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+ REG_WRITE(ah, AR_ISR_S5, s5);
+ isr &= ~AR_ISR_GENTMR;
+ }
+
+ }
+
+ *masked |= mask2;
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+ REG_WRITE(ah, AR_ISR, isr);
+
+ (void) REG_READ(ah, AR_ISR);
+ }
+ }
+
+ if (sync_cause) {
+ if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
+ REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
+ REG_WRITE(ah, AR_RC, 0);
+ *masked |= ATH9K_INT_FATAL;
+ }
+
+ if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
+ DBG("ath9k: "
+ "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
+
+ REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
+ (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
+
+ }
+ return 1;
+}
+
+static void ar9003_hw_fill_txdesc(struct ath_hw *ah __unused, void *ds, u32 seglen,
+ int is_firstseg, int is_lastseg,
+ const void *ds0, u32 buf_addr,
+ unsigned int qcu)
+{
+ struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+ unsigned int descid = 0;
+
+ ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) |
+ (1 << AR_TxRxDesc_S) |
+ (1 << AR_CtrlStat_S) |
+ (qcu << AR_TxQcuNum_S) | 0x17;
+
+ ads->data0 = buf_addr;
+ ads->data1 = 0;
+ ads->data2 = 0;
+ ads->data3 = 0;
+
+ ads->ctl3 = (seglen << AR_BufLen_S);
+ ads->ctl3 &= AR_BufLen;
+
+ /* Fill in pointer checksum and descriptor id */
+ ads->ctl10 = ar9003_calc_ptr_chksum(ads);
+ ads->ctl10 |= (descid << AR_TxDescId_S);
+
+ if (is_firstseg) {
+ ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore);
+ } else if (is_lastseg) {
+ ads->ctl11 = 0;
+ ads->ctl12 = 0;
+ ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13;
+ ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14;
+ } else {
+ /* XXX Intermediate descriptor in a multi-descriptor frame.*/
+ ads->ctl11 = 0;
+ ads->ctl12 = AR_TxMore;
+ ads->ctl13 = 0;
+ ads->ctl14 = 0;
+ }
+}
+
+static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds __unused,
+ struct ath_tx_status *ts)
+{
+ struct ar9003_txs *ads;
+ u32 status;
+
+ ads = &ah->ts_ring[ah->ts_tail];
+
+ status = *(volatile typeof(ads->status8) *)&(ads->status8);
+ if ((status & AR_TxDone) == 0)
+ return -EINPROGRESS;
+
+ ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
+
+ if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
+ (MS(ads->ds_info, AR_TxRxDesc) != 1)) {
+ DBG("ath9k: "
+ "Tx Descriptor error %x\n", ads->ds_info);
+ memset(ads, 0, sizeof(*ads));
+ return -EIO;
+ }
+
+ if (status & AR_TxOpExceeded)
+ ts->ts_status |= ATH9K_TXERR_XTXOP;
+ ts->ts_rateindex = MS(status, AR_FinalTxIdx);
+ ts->ts_seqnum = MS(status, AR_SeqNum);
+ ts->tid = MS(status, AR_TxTid);
+
+ ts->qid = MS(ads->ds_info, AR_TxQcuNum);
+ ts->desc_id = MS(ads->status1, AR_TxDescId);
+ ts->ts_tstamp = ads->status4;
+ ts->ts_status = 0;
+ ts->ts_flags = 0;
+
+ status = *(volatile typeof(ads->status2) *)&(ads->status2);
+ ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
+ ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
+ ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
+ if (status & AR_TxBaStatus) {
+ ts->ts_flags |= ATH9K_TX_BA;
+ ts->ba_low = ads->status5;
+ ts->ba_high = ads->status6;
+ }
+
+ status = *(volatile typeof(ads->status3) *)&(ads->status3);
+ if (status & AR_ExcessiveRetries)
+ ts->ts_status |= ATH9K_TXERR_XRETRY;
+ if (status & AR_Filtered)
+ ts->ts_status |= ATH9K_TXERR_FILT;
+ if (status & AR_FIFOUnderrun) {
+ ts->ts_status |= ATH9K_TXERR_FIFO;
+ ath9k_hw_updatetxtriglevel(ah, 1);
+ }
+ if (status & AR_TxTimerExpired)
+ ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
+ if (status & AR_DescCfgErr)
+ ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
+ if (status & AR_TxDataUnderrun) {
+ ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
+ ath9k_hw_updatetxtriglevel(ah, 1);
+ }
+ if (status & AR_TxDelimUnderrun) {
+ ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
+ ath9k_hw_updatetxtriglevel(ah, 1);
+ }
+ ts->ts_shortretry = MS(status, AR_RTSFailCnt);
+ ts->ts_longretry = MS(status, AR_DataFailCnt);
+ ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
+
+ status = *(volatile typeof(ads->status7) *)&(ads->status7);
+ ts->ts_rssi = MS(status, AR_TxRSSICombined);
+ ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
+ ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
+ ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
+
+ memset(ads, 0, sizeof(*ads));
+
+ return 0;
+}
+
+static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
+ u32 pktlen, enum ath9k_pkt_type type, u32 txpower,
+ u32 keyIx, enum ath9k_key_type keyType, u32 flags)
+{
+ struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+
+ if (txpower > ah->txpower_limit)
+ txpower = ah->txpower_limit;
+
+ if (txpower > 63)
+ txpower = 63;
+
+ ads->ctl11 = (pktlen & AR_FrameLen)
+ | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+ | SM(txpower, AR_XmitPower)
+ | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+ | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
+ | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
+
+ ads->ctl12 =
+ (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
+ | SM(type, AR_FrameType)
+ | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+ | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+ | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+ ads->ctl17 = SM(keyType, AR_EncrType) |
+ (flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
+ ads->ctl18 = 0;
+ ads->ctl19 = AR_Not_Sounding;
+
+ ads->ctl20 = 0;
+ ads->ctl21 = 0;
+ ads->ctl22 = 0;
+}
+
+static void ar9003_hw_set_clrdmask(struct ath_hw *ah __unused, void *ds, int val)
+{
+ struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+
+ if (val)
+ ads->ctl11 |= AR_ClrDestMask;
+ else
+ ads->ctl11 &= ~AR_ClrDestMask;
+}
+
+static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah __unused, void *ds,
+ void *lastds,
+ u32 durUpdateEn, u32 rtsctsRate,
+ u32 rtsctsDuration __unused,
+ struct ath9k_11n_rate_series series[],
+ u32 nseries __unused, u32 flags)
+{
+ struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+ struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds;
+ uint32_t ctl11;
+
+ if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
+ ctl11 = ads->ctl11;
+
+ if (flags & ATH9K_TXDESC_RTSENA) {
+ ctl11 &= ~AR_CTSEnable;
+ ctl11 |= AR_RTSEnable;
+ } else {
+ ctl11 &= ~AR_RTSEnable;
+ ctl11 |= AR_CTSEnable;
+ }
+
+ ads->ctl11 = ctl11;
+ } else {
+ ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable));
+ }
+
+ ads->ctl13 = set11nTries(series, 0)
+ | set11nTries(series, 1)
+ | set11nTries(series, 2)
+ | set11nTries(series, 3)
+ | (durUpdateEn ? AR_DurUpdateEna : 0)
+ | SM(0, AR_BurstDur);
+
+ ads->ctl14 = set11nRate(series, 0)
+ | set11nRate(series, 1)
+ | set11nRate(series, 2)
+ | set11nRate(series, 3);
+
+ ads->ctl15 = set11nPktDurRTSCTS(series, 0)
+ | set11nPktDurRTSCTS(series, 1);
+
+ ads->ctl16 = set11nPktDurRTSCTS(series, 2)
+ | set11nPktDurRTSCTS(series, 3);
+
+ ads->ctl18 = set11nRateFlags(series, 0)
+ | set11nRateFlags(series, 1)
+ | set11nRateFlags(series, 2)
+ | set11nRateFlags(series, 3)
+ | SM(rtsctsRate, AR_RTSCTSRate);
+ ads->ctl19 = AR_Not_Sounding;
+
+ last_ads->ctl13 = ads->ctl13;
+ last_ads->ctl14 = ads->ctl14;
+}
+
+static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
+ u32 aggrLen)
+{
+#define FIRST_DESC_NDELIMS 60
+ struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+
+ ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
+
+ if (ah->ent_mode & AR_ENT_OTP_MPSD) {
+ u32 ctl17, ndelim;
+ /*
+ * Add delimiter when using RTS/CTS with aggregation
+ * and non enterprise AR9003 card
+ */
+ ctl17 = ads->ctl17;
+ ndelim = MS(ctl17, AR_PadDelim);
+
+ if (ndelim < FIRST_DESC_NDELIMS) {
+ aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4;
+ ndelim = FIRST_DESC_NDELIMS;
+ }
+
+ ctl17 &= ~AR_AggrLen;
+ ctl17 |= SM(aggrLen, AR_AggrLen);
+
+ ctl17 &= ~AR_PadDelim;
+ ctl17 |= SM(ndelim, AR_PadDelim);
+
+ ads->ctl17 = ctl17;
+ } else {
+ ads->ctl17 &= ~AR_AggrLen;
+ ads->ctl17 |= SM(aggrLen, AR_AggrLen);
+ }
+}
+
+static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah __unused, void *ds,
+ u32 numDelims)
+{
+ struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+ unsigned int ctl17;
+
+ ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
+
+ /*
+ * We use a stack variable to manipulate ctl6 to reduce uncached
+ * read modify, modfiy, write.
+ */
+ ctl17 = ads->ctl17;
+ ctl17 &= ~AR_PadDelim;
+ ctl17 |= SM(numDelims, AR_PadDelim);
+ ads->ctl17 = ctl17;
+}
+
+static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah __unused, void *ds)
+{
+ struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+
+ ads->ctl12 |= AR_IsAggr;
+ ads->ctl12 &= ~AR_MoreAggr;
+ ads->ctl17 &= ~AR_PadDelim;
+}
+
+static void ar9003_hw_clr11n_aggr(struct ath_hw *ah __unused, void *ds)
+{
+ struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+
+ ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr);
+}
+
+void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah __unused, void *ds, u8 chains)
+{
+ struct ar9003_txc *ads = ds;
+
+ ads->ctl12 |= SM(chains, AR_PAPRDChainMask);
+}
+
+void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
+{
+ struct ath_hw_ops *ops = ath9k_hw_ops(hw);
+
+ ops->rx_enable = ar9003_hw_rx_enable;
+ ops->set_desc_link = ar9003_hw_set_desc_link;
+ ops->get_desc_link = ar9003_hw_get_desc_link;
+ ops->get_isr = ar9003_hw_get_isr;
+ ops->fill_txdesc = ar9003_hw_fill_txdesc;
+ ops->proc_txdesc = ar9003_hw_proc_txdesc;
+ ops->set11n_txdesc = ar9003_hw_set11n_txdesc;
+ ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario;
+ ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first;
+ ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle;
+ ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
+ ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
+ ops->set_clrdmask = ar9003_hw_set_clrdmask;
+}
+
+void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
+{
+ REG_WRITE(ah, AR_DATABUF_SIZE, buf_size & AR_DATABUF_SIZE_MASK);
+}
+
+void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp,
+ enum ath9k_rx_qtype qtype)
+{
+ if (qtype == ATH9K_RX_QUEUE_HP)
+ REG_WRITE(ah, AR_HP_RXDP, rxdp);
+ else
+ REG_WRITE(ah, AR_LP_RXDP, rxdp);
+}
+
+int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah __unused, struct ath_rx_status *rxs,
+ void *buf_addr)
+{
+ struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr;
+ unsigned int phyerr;
+
+ /* TODO: byte swap on big endian for ar9300_10 */
+
+ if ((rxsp->status11 & AR_RxDone) == 0)
+ return -EINPROGRESS;
+
+ if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
+ return -EINVAL;
+
+ if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
+ return -EINPROGRESS;
+
+ if (!rxs)
+ return 0;
+
+ rxs->rs_status = 0;
+ rxs->rs_flags = 0;
+
+ rxs->rs_datalen = rxsp->status2 & AR_DataLen;
+ rxs->rs_tstamp = rxsp->status3;
+
+ /* XXX: Keycache */
+ rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
+ rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
+ rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
+ rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
+ rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
+ rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
+ rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
+
+ if (rxsp->status11 & AR_RxKeyIdxValid)
+ rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
+ else
+ rxs->rs_keyix = ATH9K_RXKEYIX_INVALID;
+
+ rxs->rs_rate = MS(rxsp->status1, AR_RxRate);
+ rxs->rs_more = (rxsp->status2 & AR_RxMore) ? 1 : 0;
+
+ rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0;
+ rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0;
+ rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7);
+ rxs->rs_flags = (rxsp->status4 & AR_GI) ? ATH9K_RX_GI : 0;
+ rxs->rs_flags |= (rxsp->status4 & AR_2040) ? ATH9K_RX_2040 : 0;
+
+ rxs->evm0 = rxsp->status6;
+ rxs->evm1 = rxsp->status7;
+ rxs->evm2 = rxsp->status8;
+ rxs->evm3 = rxsp->status9;
+ rxs->evm4 = (rxsp->status10 & 0xffff);
+
+ if (rxsp->status11 & AR_PreDelimCRCErr)
+ rxs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
+
+ if (rxsp->status11 & AR_PostDelimCRCErr)
+ rxs->rs_flags |= ATH9K_RX_DELIM_CRC_POST;
+
+ if (rxsp->status11 & AR_DecryptBusyErr)
+ rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
+
+ if ((rxsp->status11 & AR_RxFrameOK) == 0) {
+ /*
+ * AR_CRCErr will bet set to true if we're on the last
+ * subframe and the AR_PostDelimCRCErr is caught.
+ * In a way this also gives us a guarantee that when
+ * (!(AR_CRCErr) && (AR_PostDelimCRCErr)) we cannot
+ * possibly be reviewing the last subframe. AR_CRCErr
+ * is the CRC of the actual data.
+ */
+ if (rxsp->status11 & AR_CRCErr)
+ rxs->rs_status |= ATH9K_RXERR_CRC;
+ else if (rxsp->status11 & AR_PHYErr) {
+ phyerr = MS(rxsp->status11, AR_PHYErrCode);
+ /*
+ * If we reach a point here where AR_PostDelimCRCErr is
+ * true it implies we're *not* on the last subframe. In
+ * in that case that we know already that the CRC of
+ * the frame was OK, and MAC would send an ACK for that
+ * subframe, even if we did get a phy error of type
+ * ATH9K_PHYERR_OFDM_RESTART. This is only applicable
+ * to frame that are prior to the last subframe.
+ * The AR_PostDelimCRCErr is the CRC for the MPDU
+ * delimiter, which contains the 4 reserved bits,
+ * the MPDU length (12 bits), and follows the MPDU
+ * delimiter for an A-MPDU subframe (0x4E = 'N' ASCII).
+ */
+ if ((phyerr == ATH9K_PHYERR_OFDM_RESTART) &&
+ (rxsp->status11 & AR_PostDelimCRCErr)) {
+ rxs->rs_phyerr = 0;
+ } else {
+ rxs->rs_status |= ATH9K_RXERR_PHY;
+ rxs->rs_phyerr = phyerr;
+ }
+
+ } else if (rxsp->status11 & AR_DecryptCRCErr)
+ rxs->rs_status |= ATH9K_RXERR_DECRYPT;
+ else if (rxsp->status11 & AR_MichaelErr)
+ rxs->rs_status |= ATH9K_RXERR_MIC;
+ else if (rxsp->status11 & AR_KeyMiss)
+ rxs->rs_status |= ATH9K_RXERR_DECRYPT;
+ }
+
+ return 0;
+}
+
+void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah)
+{
+ ah->ts_tail = 0;
+
+ memset((void *) ah->ts_ring, 0,
+ ah->ts_size * sizeof(struct ar9003_txs));
+
+ DBG2("ath9k: "
+ "TS Start 0x%x End 0x%x Virt %p, Size %d\n",
+ ah->ts_paddr_start, ah->ts_paddr_end,
+ ah->ts_ring, ah->ts_size);
+
+ REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start);
+ REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end);
+}
+
+void ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start,
+ u32 ts_paddr_start,
+ u8 size)
+{
+
+ ah->ts_paddr_start = ts_paddr_start;
+ ah->ts_paddr_end = ts_paddr_start + (size * sizeof(struct ar9003_txs));
+ ah->ts_size = size;
+ ah->ts_ring = (struct ar9003_txs *) ts_start;
+
+ ath9k_hw_reset_txstatus_ring(ah);
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_phy.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_phy.c
new file mode 100644
index 00000000..6103040a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_phy.c
@@ -0,0 +1,1277 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+
+#include "hw.h"
+#include "ar9003_phy.h"
+
+static const int firstep_table[] =
+/* level: 0 1 2 3 4 5 6 7 8 */
+ { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */
+
+static const int cycpwrThr1_table[] =
+/* level: 0 1 2 3 4 5 6 7 8 */
+ { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */
+
+/*
+ * register values to turn OFDM weak signal detection OFF
+ */
+static const int m1ThreshLow_off = 127;
+static const int m2ThreshLow_off = 127;
+static const int m1Thresh_off = 127;
+static const int m2Thresh_off = 127;
+static const int m2CountThr_off = 31;
+static const int m2CountThrLow_off = 63;
+static const int m1ThreshLowExt_off = 127;
+static const int m2ThreshLowExt_off = 127;
+static const int m1ThreshExt_off = 127;
+static const int m2ThreshExt_off = 127;
+
+/**
+ * ar9003_hw_set_channel - set channel on single-chip device
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * This is the function to change channel on single-chip devices, that is
+ * all devices after ar9280.
+ *
+ * This function takes the channel value in MHz and sets
+ * hardware channel value. Assumes writes have been enabled to analog bus.
+ *
+ * Actual Expression,
+ *
+ * For 2GHz channel,
+ * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
+ * (freq_ref = 40MHz)
+ *
+ * For 5GHz channel,
+ * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
+ * (freq_ref = 40MHz/(24>>amodeRefSel))
+ *
+ * For 5GHz channels which are 5MHz spaced,
+ * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
+ * (freq_ref = 40MHz)
+ */
+static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ u16 bMode, fracMode = 0, aModeRefSel = 0;
+ u32 freq, channelSel = 0, reg32 = 0;
+ struct chan_centers centers;
+ int loadSynthChannel;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ freq = centers.synth_center;
+
+ if (freq < 4800) { /* 2 GHz, fractional mode */
+ if (AR_SREV_9485(ah)) {
+ u32 chan_frac;
+
+ /*
+ * freq_ref = 40 / (refdiva >> amoderefsel); where refdiva=1 and amoderefsel=0
+ * ndiv = ((chan_mhz * 4) / 3) / freq_ref;
+ * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000
+ */
+ channelSel = (freq * 4) / 120;
+ chan_frac = (((freq * 4) % 120) * 0x20000) / 120;
+ channelSel = (channelSel << 17) | chan_frac;
+ } else if (AR_SREV_9340(ah)) {
+ if (ah->is_clk_25mhz) {
+ u32 chan_frac;
+
+ channelSel = (freq * 2) / 75;
+ chan_frac = (((freq * 2) % 75) * 0x20000) / 75;
+ channelSel = (channelSel << 17) | chan_frac;
+ } else
+ channelSel = CHANSEL_2G(freq) >> 1;
+ } else
+ channelSel = CHANSEL_2G(freq);
+ /* Set to 2G mode */
+ bMode = 1;
+ } else {
+ if (AR_SREV_9340(ah) && ah->is_clk_25mhz) {
+ u32 chan_frac;
+
+ channelSel = (freq * 2) / 75;
+ chan_frac = ((freq % 75) * 0x20000) / 75;
+ channelSel = (channelSel << 17) | chan_frac;
+ } else {
+ channelSel = CHANSEL_5G(freq);
+ /* Doubler is ON, so, divide channelSel by 2. */
+ channelSel >>= 1;
+ }
+ /* Set to 5G mode */
+ bMode = 0;
+ }
+
+ /* Enable fractional mode for all channels */
+ fracMode = 1;
+ aModeRefSel = 0;
+ loadSynthChannel = 0;
+
+ reg32 = (bMode << 29);
+ REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
+
+ /* Enable Long shift Select for Synthesizer */
+ REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_SYNTH4,
+ AR_PHY_SYNTH4_LONG_SHIFT_SELECT, 1);
+
+ /* Program Synth. setting */
+ reg32 = (channelSel << 2) | (fracMode << 30) |
+ (aModeRefSel << 28) | (loadSynthChannel << 31);
+ REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32);
+
+ /* Toggle Load Synth channel bit */
+ loadSynthChannel = 1;
+ reg32 = (channelSel << 2) | (fracMode << 30) |
+ (aModeRefSel << 28) | (loadSynthChannel << 31);
+ REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32);
+
+ ah->curchan = chan;
+ ah->curchan_rad_index = -1;
+
+ return 0;
+}
+
+/**
+ * ar9003_hw_spur_mitigate_mrc_cck - convert baseband spur frequency
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * For single-chip solutions. Converts to baseband spur frequency given the
+ * input channel frequency and compute register settings below.
+ *
+ * Spur mitigation for MRC CCK
+ */
+static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ static const u32 spur_freq[4] = { 2420, 2440, 2464, 2480 };
+ int cur_bb_spur, negative = 0, cck_spur_freq;
+ int i;
+ int range, max_spur_cnts, synth_freq;
+ u8 *spur_fbin_ptr = NULL;
+
+ /*
+ * Need to verify range +/- 10 MHz in control channel, otherwise spur
+ * is out-of-band and can be ignored.
+ */
+
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) {
+ spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah,
+ IS_CHAN_2GHZ(chan));
+ if (spur_fbin_ptr[0] == 0) /* No spur */
+ return;
+ max_spur_cnts = 5;
+ if (IS_CHAN_HT40(chan)) {
+ range = 19;
+ if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
+ AR_PHY_GC_DYN2040_PRI_CH) == 0)
+ synth_freq = chan->channel + 10;
+ else
+ synth_freq = chan->channel - 10;
+ } else {
+ range = 10;
+ synth_freq = chan->channel;
+ }
+ } else {
+ range = 10;
+ max_spur_cnts = 4;
+ synth_freq = chan->channel;
+ }
+
+ for (i = 0; i < max_spur_cnts; i++) {
+ negative = 0;
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],
+ IS_CHAN_2GHZ(chan)) - synth_freq;
+ else
+ cur_bb_spur = spur_freq[i] - synth_freq;
+
+ if (cur_bb_spur < 0) {
+ negative = 1;
+ cur_bb_spur = -cur_bb_spur;
+ }
+ if (cur_bb_spur < range) {
+ cck_spur_freq = (int)((cur_bb_spur << 19) / 11);
+
+ if (negative == 1)
+ cck_spur_freq = -cck_spur_freq;
+
+ cck_spur_freq = cck_spur_freq & 0xfffff;
+
+ REG_RMW_FIELD(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_YCOK_MAX, 0x7);
+ REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
+ AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR, 0x7f);
+ REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
+ AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE,
+ 0x2);
+ REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
+ AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT,
+ 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
+ AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ,
+ cck_spur_freq);
+
+ return;
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_YCOK_MAX, 0x5);
+ REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
+ AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT, 0x0);
+ REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
+ AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, 0x0);
+}
+
+/* Clean all spur register fields */
+static void ar9003_hw_spur_ofdm_clear(struct ath_hw *ah)
+{
+ REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+ AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+ AR_PHY_TIMING11_SPUR_FREQ_SD, 0);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+ AR_PHY_TIMING11_SPUR_DELTA_PHASE, 0);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, 0);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+ AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+ AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+ AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0);
+ REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+ AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 0);
+ REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+ AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 0);
+
+ REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+ AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+ AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+ AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0);
+ REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
+ AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, 0);
+ REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A,
+ AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, 0);
+ REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
+ AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, 0);
+ REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
+ AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0);
+ REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
+ AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0);
+ REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A,
+ AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0);
+ REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+ AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0);
+}
+
+static void ar9003_hw_spur_ofdm(struct ath_hw *ah,
+ int freq_offset,
+ int spur_freq_sd,
+ int spur_delta_phase,
+ int spur_subchannel_sd)
+{
+ int mask_index = 0;
+
+ /* OFDM Spur mitigation */
+ REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+ AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+ AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+ AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, spur_subchannel_sd);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+ AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+ AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+ AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+ AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, 34);
+ REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+ AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 1);
+
+ if (REG_READ_FIELD(ah, AR_PHY_MODE,
+ AR_PHY_MODE_DYNAMIC) == 0x1)
+ REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+ AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1);
+
+ mask_index = (freq_offset << 4) / 5;
+ if (mask_index < 0)
+ mask_index = mask_index - 1;
+
+ mask_index = mask_index & 0x7f;
+
+ REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+ AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+ AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+ AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
+ AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, mask_index);
+ REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A,
+ AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, mask_index);
+ REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
+ AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, mask_index);
+ REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
+ AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0xc);
+ REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
+ AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0xc);
+ REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A,
+ AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0xa0);
+ REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+ AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0xff);
+}
+
+static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ int freq_offset)
+{
+ int spur_freq_sd = 0;
+ int spur_subchannel_sd = 0;
+ int spur_delta_phase = 0;
+
+ if (IS_CHAN_HT40(chan)) {
+ if (freq_offset < 0) {
+ if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
+ AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
+ spur_subchannel_sd = 1;
+ else
+ spur_subchannel_sd = 0;
+
+ spur_freq_sd = ((freq_offset + 10) << 9) / 11;
+
+ } else {
+ if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
+ AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
+ spur_subchannel_sd = 0;
+ else
+ spur_subchannel_sd = 1;
+
+ spur_freq_sd = ((freq_offset - 10) << 9) / 11;
+
+ }
+
+ spur_delta_phase = (freq_offset << 17) / 5;
+
+ } else {
+ spur_subchannel_sd = 0;
+ spur_freq_sd = (freq_offset << 9) /11;
+ spur_delta_phase = (freq_offset << 18) / 5;
+ }
+
+ spur_freq_sd = spur_freq_sd & 0x3ff;
+ spur_delta_phase = spur_delta_phase & 0xfffff;
+
+ ar9003_hw_spur_ofdm(ah,
+ freq_offset,
+ spur_freq_sd,
+ spur_delta_phase,
+ spur_subchannel_sd);
+}
+
+/* Spur mitigation for OFDM */
+static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ int synth_freq;
+ int range = 10;
+ int freq_offset = 0;
+ int mode;
+ u8* spurChansPtr;
+ unsigned int i;
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+ if (IS_CHAN_5GHZ(chan)) {
+ spurChansPtr = &(eep->modalHeader5G.spurChans[0]);
+ mode = 0;
+ }
+ else {
+ spurChansPtr = &(eep->modalHeader2G.spurChans[0]);
+ mode = 1;
+ }
+
+ if (spurChansPtr[0] == 0)
+ return; /* No spur in the mode */
+
+ if (IS_CHAN_HT40(chan)) {
+ range = 19;
+ if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
+ AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
+ synth_freq = chan->channel - 10;
+ else
+ synth_freq = chan->channel + 10;
+ } else {
+ range = 10;
+ synth_freq = chan->channel;
+ }
+
+ ar9003_hw_spur_ofdm_clear(ah);
+
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) {
+ freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq;
+ if (abs(freq_offset) < range) {
+ ar9003_hw_spur_ofdm_work(ah, chan, freq_offset);
+ break;
+ }
+ }
+}
+
+static void ar9003_hw_spur_mitigate(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ ar9003_hw_spur_mitigate_mrc_cck(ah, chan);
+ ar9003_hw_spur_mitigate_ofdm(ah, chan);
+}
+
+static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah __unused,
+ struct ath9k_channel *chan)
+{
+ u32 pll;
+
+ pll = SM(0x5, AR_RTC_9300_PLL_REFDIV);
+
+ if (chan && IS_CHAN_HALF_RATE(chan))
+ pll |= SM(0x1, AR_RTC_9300_PLL_CLKSEL);
+ else if (chan && IS_CHAN_QUARTER_RATE(chan))
+ pll |= SM(0x2, AR_RTC_9300_PLL_CLKSEL);
+
+ pll |= SM(0x2c, AR_RTC_9300_PLL_DIV);
+
+ return pll;
+}
+
+static void ar9003_hw_set_channel_regs(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ u32 phymode;
+ u32 enableDacFifo = 0;
+
+ enableDacFifo =
+ (REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO);
+
+ /* Enable 11n HT, 20 MHz */
+ phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_WALSH |
+ AR_PHY_GC_SHORT_GI_40 | enableDacFifo;
+
+ /* Configure baseband for dynamic 20/40 operation */
+ if (IS_CHAN_HT40(chan)) {
+ phymode |= AR_PHY_GC_DYN2040_EN;
+ /* Configure control (primary) channel at +-10MHz */
+ if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+ (chan->chanmode == CHANNEL_G_HT40PLUS))
+ phymode |= AR_PHY_GC_DYN2040_PRI_CH;
+
+ }
+
+ /* make sure we preserve INI settings */
+ phymode |= REG_READ(ah, AR_PHY_GEN_CTRL);
+ /* turn off Green Field detection for STA for now */
+ phymode &= ~AR_PHY_GC_GF_DETECT_EN;
+
+ REG_WRITE(ah, AR_PHY_GEN_CTRL, phymode);
+
+ /* Configure MAC for 20/40 operation */
+ ath9k_hw_set11nmac2040(ah);
+
+ /* global transmit timeout (25 TUs default)*/
+ REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
+ /* carrier sense timeout */
+ REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
+}
+
+static void ar9003_hw_init_bb(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ u32 synthDelay;
+
+ /*
+ * Wait for the frequency synth to settle (synth goes on
+ * via AR_PHY_ACTIVE_EN). Read the phy active delay register.
+ * Value is in 100ns increments.
+ */
+ synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+ if (IS_CHAN_B(chan))
+ synthDelay = (4 * synthDelay) / 22;
+ else
+ synthDelay /= 10;
+
+ /* Activate the PHY (includes baseband activate + synthesizer on) */
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+ /*
+ * There is an issue if the AP starts the calibration before
+ * the base band timeout completes. This could result in the
+ * rx_clear false triggering. As a workaround we add delay an
+ * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
+ * does not happen.
+ */
+ udelay(synthDelay + BASE_ACTIVATE_DELAY);
+}
+
+void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
+{
+ switch (rx) {
+ case 0x5:
+ REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+ AR_PHY_SWAP_ALT_CHAIN);
+ case 0x3:
+ case 0x1:
+ case 0x2:
+ case 0x7:
+ REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx);
+ REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx);
+ break;
+ default:
+ break;
+ }
+
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
+ REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
+ else
+ REG_WRITE(ah, AR_SELFGEN_MASK, tx);
+
+ if (tx == 0x5) {
+ REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+ AR_PHY_SWAP_ALT_CHAIN);
+ }
+}
+
+/*
+ * Override INI values with chip specific configuration.
+ */
+static void ar9003_hw_override_ini(struct ath_hw *ah)
+{
+ u32 val;
+
+ /*
+ * Set the RX_ABORT and RX_DIS and clear it only after
+ * RXE is set for MAC. This prevents frames with
+ * corrupted descriptor status.
+ */
+ REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+ /*
+ * For AR9280 and above, there is a new feature that allows
+ * Multicast search based on both MAC Address and Key ID. By default,
+ * this feature is enabled. But since the driver is not using this
+ * feature, we switch it off; otherwise multicast search based on
+ * MAC addr only will fail.
+ */
+ val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE);
+ REG_WRITE(ah, AR_PCU_MISC_MODE2,
+ val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE);
+}
+
+static void ar9003_hw_prog_ini(struct ath_hw *ah,
+ struct ar5416IniArray *iniArr,
+ int column)
+{
+ unsigned int i, regWrites = 0;
+
+ /* New INI format: Array may be undefined (pre, core, post arrays) */
+ if (!iniArr->ia_array)
+ return;
+
+ /*
+ * New INI format: Pre, core, and post arrays for a given subsystem
+ * may be modal (> 2 columns) or non-modal (2 columns). Determine if
+ * the array is non-modal and force the column to 1.
+ */
+ if ((unsigned int)column >= iniArr->ia_columns)
+ column = 1;
+
+ for (i = 0; i < iniArr->ia_rows; i++) {
+ u32 reg = INI_RA(iniArr, i, 0);
+ u32 val = INI_RA(iniArr, i, column);
+
+ REG_WRITE(ah, reg, val);
+
+ DO_DELAY(regWrites);
+ }
+}
+
+static int ar9003_hw_process_ini(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ unsigned int regWrites = 0, i;
+ struct net80211_channel *channel = chan->chan;
+ u32 modesIndex;
+
+ switch (chan->chanmode) {
+ case CHANNEL_A:
+ case CHANNEL_A_HT20:
+ modesIndex = 1;
+ break;
+ case CHANNEL_A_HT40PLUS:
+ case CHANNEL_A_HT40MINUS:
+ modesIndex = 2;
+ break;
+ case CHANNEL_G:
+ case CHANNEL_G_HT20:
+ case CHANNEL_B:
+ modesIndex = 4;
+ break;
+ case CHANNEL_G_HT40PLUS:
+ case CHANNEL_G_HT40MINUS:
+ modesIndex = 3;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ATH_INI_NUM_SPLIT; i++) {
+ ar9003_hw_prog_ini(ah, &ah->iniSOC[i], modesIndex);
+ ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex);
+ ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex);
+ ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex);
+ }
+
+ REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites);
+ REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+
+ /*
+ * For 5GHz channels requiring Fast Clock, apply
+ * different modal values.
+ */
+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+ REG_WRITE_ARRAY(&ah->iniModesAdditional,
+ modesIndex, regWrites);
+
+ if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
+ REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
+
+ ar9003_hw_override_ini(ah);
+ ar9003_hw_set_channel_regs(ah, chan);
+ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+
+ /* Set TX power */
+ ah->eep_ops->set_txpower(ah, chan,
+ ath9k_regd_get_ctl(regulatory, chan),
+ 0,
+ channel->maxpower * 2,
+ min((u32) MAX_RATE_POWER,
+ (u32) regulatory->power_limit), 0);
+
+ return 0;
+}
+
+static void ar9003_hw_set_rfmode(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ u32 rfMode = 0;
+
+ if (chan == NULL)
+ return;
+
+ rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
+ ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
+
+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+ rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
+
+ REG_WRITE(ah, AR_PHY_MODE, rfMode);
+}
+
+static void ar9003_hw_mark_phy_inactive(struct ath_hw *ah)
+{
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+}
+
+static void ar9003_hw_set_delta_slope(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ u32 coef_scaled, ds_coef_exp, ds_coef_man;
+ u32 clockMhzScaled = 0x64000000;
+ struct chan_centers centers;
+
+ /*
+ * half and quarter rate can divide the scaled clock by 2 or 4
+ * scale for selected channel bandwidth
+ */
+ if (IS_CHAN_HALF_RATE(chan))
+ clockMhzScaled = clockMhzScaled >> 1;
+ else if (IS_CHAN_QUARTER_RATE(chan))
+ clockMhzScaled = clockMhzScaled >> 2;
+
+ /*
+ * ALGO -> coef = 1e8/fcarrier*fclock/40;
+ * scaled coef to provide precision for this floating calculation
+ */
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ coef_scaled = clockMhzScaled / centers.synth_center;
+
+ ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
+ &ds_coef_exp);
+
+ REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+ AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+ AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
+
+ /*
+ * For Short GI,
+ * scaled coeff is 9/10 that of normal coeff
+ */
+ coef_scaled = (9 * coef_scaled) / 10;
+
+ ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
+ &ds_coef_exp);
+
+ /* for short gi */
+ REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA,
+ AR_PHY_SGI_DSC_MAN, ds_coef_man);
+ REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA,
+ AR_PHY_SGI_DSC_EXP, ds_coef_exp);
+}
+
+static int ar9003_hw_rfbus_req(struct ath_hw *ah)
+{
+ REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
+ return ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
+ AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT);
+}
+
+/*
+ * Wait for the frequency synth to settle (synth goes on via PHY_ACTIVE_EN).
+ * Read the phy active delay register. Value is in 100ns increments.
+ */
+static void ar9003_hw_rfbus_done(struct ath_hw *ah)
+{
+ u32 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+ if (IS_CHAN_B(ah->curchan))
+ synthDelay = (4 * synthDelay) / 22;
+ else
+ synthDelay /= 10;
+
+ udelay(synthDelay + BASE_ACTIVATE_DELAY);
+
+ REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+}
+
+static void ar9003_hw_set_diversity(struct ath_hw *ah, int value)
+{
+ u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
+ if (value)
+ v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+ else
+ v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+ REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
+}
+
+static int ar9003_hw_ani_control(struct ath_hw *ah,
+ enum ath9k_ani_cmd cmd, int param)
+{
+ struct ath9k_channel *chan = ah->curchan;
+ struct ar5416AniState *aniState = &chan->ani;
+ s32 value, value2;
+
+ switch (cmd & ah->ani_function) {
+ case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
+ /*
+ * on == 1 means ofdm weak signal detection is ON
+ * on == 1 is the default, for less noise immunity
+ *
+ * on == 0 means ofdm weak signal detection is OFF
+ * on == 0 means more noise imm
+ */
+ u32 on = param ? 1 : 0;
+ /*
+ * make register setting for default
+ * (weak sig detect ON) come from INI file
+ */
+ int m1ThreshLow = on ?
+ aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
+ int m2ThreshLow = on ?
+ aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
+ int m1Thresh = on ?
+ aniState->iniDef.m1Thresh : m1Thresh_off;
+ int m2Thresh = on ?
+ aniState->iniDef.m2Thresh : m2Thresh_off;
+ int m2CountThr = on ?
+ aniState->iniDef.m2CountThr : m2CountThr_off;
+ int m2CountThrLow = on ?
+ aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
+ int m1ThreshLowExt = on ?
+ aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
+ int m2ThreshLowExt = on ?
+ aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
+ int m1ThreshExt = on ?
+ aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
+ int m2ThreshExt = on ?
+ aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
+
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+ m1ThreshLow);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+ m2ThreshLow);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M1_THRESH, m1Thresh);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M2_THRESH, m2Thresh);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M2COUNT_THR, m2CountThr);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+ m2CountThrLow);
+
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt);
+
+ if (on)
+ REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+ else
+ REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+
+ if (!on != aniState->ofdmWeakSigDetectOff) {
+ DBG2("ath9k: "
+ "** ch %d: ofdm weak signal: %s=>%s\n",
+ chan->channel,
+ !aniState->ofdmWeakSigDetectOff ?
+ "on" : "off",
+ on ? "on" : "off");
+ if (on)
+ ah->stats.ast_ani_ofdmon++;
+ else
+ ah->stats.ast_ani_ofdmoff++;
+ aniState->ofdmWeakSigDetectOff = !on;
+ }
+ break;
+ }
+ case ATH9K_ANI_FIRSTEP_LEVEL:{
+ u32 level = param;
+
+ if (level >= ARRAY_SIZE(firstep_table)) {
+ DBG("ath9k: "
+ "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%d > %zd)\n",
+ level, ARRAY_SIZE(firstep_table));
+ return 0;
+ }
+
+ /*
+ * make register setting relative to default
+ * from INI file & cap value
+ */
+ value = firstep_table[level] -
+ firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
+ aniState->iniDef.firstep;
+ if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
+ value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
+ if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX)
+ value = ATH9K_SIG_FIRSTEP_SETTING_MAX;
+ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+ AR_PHY_FIND_SIG_FIRSTEP,
+ value);
+ /*
+ * we need to set first step low register too
+ * make register setting relative to default
+ * from INI file & cap value
+ */
+ value2 = firstep_table[level] -
+ firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
+ aniState->iniDef.firstepLow;
+ if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
+ value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
+ if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX)
+ value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX;
+
+ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
+ AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2);
+
+ if (level != aniState->firstepLevel) {
+ DBG2("ath9k: "
+ "** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n",
+ chan->channel,
+ aniState->firstepLevel,
+ level,
+ ATH9K_ANI_FIRSTEP_LVL_NEW,
+ value,
+ aniState->iniDef.firstep);
+ DBG2("ath9k: "
+ "** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n",
+ chan->channel,
+ aniState->firstepLevel,
+ level,
+ ATH9K_ANI_FIRSTEP_LVL_NEW,
+ value2,
+ aniState->iniDef.firstepLow);
+ if (level > aniState->firstepLevel)
+ ah->stats.ast_ani_stepup++;
+ else if (level < aniState->firstepLevel)
+ ah->stats.ast_ani_stepdown++;
+ aniState->firstepLevel = level;
+ }
+ break;
+ }
+ case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
+ u32 level = param;
+
+ if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
+ DBG("ath9k: "
+ "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%d > %zd)\n",
+ level, ARRAY_SIZE(cycpwrThr1_table));
+ return 0;
+ }
+ /*
+ * make register setting relative to default
+ * from INI file & cap value
+ */
+ value = cycpwrThr1_table[level] -
+ cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
+ aniState->iniDef.cycpwrThr1;
+ if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
+ value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
+ if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
+ value = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
+ REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+ AR_PHY_TIMING5_CYCPWR_THR1,
+ value);
+
+ /*
+ * set AR_PHY_EXT_CCA for extension channel
+ * make register setting relative to default
+ * from INI file & cap value
+ */
+ value2 = cycpwrThr1_table[level] -
+ cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
+ aniState->iniDef.cycpwrThr1Ext;
+ if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
+ value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
+ if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
+ value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+ AR_PHY_EXT_CYCPWR_THR1, value2);
+
+ if (level != aniState->spurImmunityLevel) {
+ DBG2("ath9k: "
+ "** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n",
+ chan->channel,
+ aniState->spurImmunityLevel,
+ level,
+ ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
+ value,
+ aniState->iniDef.cycpwrThr1);
+ DBG2("ath9k: "
+ "** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n",
+ chan->channel,
+ aniState->spurImmunityLevel,
+ level,
+ ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
+ value2,
+ aniState->iniDef.cycpwrThr1Ext);
+ if (level > aniState->spurImmunityLevel)
+ ah->stats.ast_ani_spurup++;
+ else if (level < aniState->spurImmunityLevel)
+ ah->stats.ast_ani_spurdown++;
+ aniState->spurImmunityLevel = level;
+ }
+ break;
+ }
+ case ATH9K_ANI_MRC_CCK:{
+ /*
+ * is_on == 1 means MRC CCK ON (default, less noise imm)
+ * is_on == 0 means MRC CCK is OFF (more noise imm)
+ */
+ int is_on = param ? 1 : 0;
+ REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
+ AR_PHY_MRC_CCK_ENABLE, is_on);
+ REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
+ AR_PHY_MRC_CCK_MUX_REG, is_on);
+ if (!is_on != aniState->mrcCCKOff) {
+ DBG2("ath9k: "
+ "** ch %d: MRC CCK: %s=>%s\n",
+ chan->channel,
+ !aniState->mrcCCKOff ? "on" : "off",
+ is_on ? "on" : "off");
+ if (is_on)
+ ah->stats.ast_ani_ccklow++;
+ else
+ ah->stats.ast_ani_cckhigh++;
+ aniState->mrcCCKOff = !is_on;
+ }
+ break;
+ }
+ case ATH9K_ANI_PRESENT:
+ break;
+ default:
+ DBG2("ath9k: invalid cmd %d\n", cmd);
+ return 0;
+ }
+
+ DBG2("ath9k: "
+ "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
+ aniState->spurImmunityLevel,
+ !aniState->ofdmWeakSigDetectOff ? "on" : "off",
+ aniState->firstepLevel,
+ !aniState->mrcCCKOff ? "on" : "off",
+ aniState->listenTime,
+ aniState->ofdmPhyErrCount,
+ aniState->cckPhyErrCount);
+ return 1;
+}
+
+static void ar9003_hw_do_getnf(struct ath_hw *ah,
+ int16_t nfarray[NUM_NF_READINGS])
+{
+#define AR_PHY_CH_MINCCA_PWR 0x1FF00000
+#define AR_PHY_CH_MINCCA_PWR_S 20
+#define AR_PHY_CH_EXT_MINCCA_PWR 0x01FF0000
+#define AR_PHY_CH_EXT_MINCCA_PWR_S 16
+
+ int16_t nf;
+ int i;
+
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (ah->rxchainmask & BIT(i)) {
+ nf = MS(REG_READ(ah, ah->nf_regs[i]),
+ AR_PHY_CH_MINCCA_PWR);
+ nfarray[i] = sign_extend32(nf, 8);
+
+ if (IS_CHAN_HT40(ah->curchan)) {
+ u8 ext_idx = AR9300_MAX_CHAINS + i;
+
+ nf = MS(REG_READ(ah, ah->nf_regs[ext_idx]),
+ AR_PHY_CH_EXT_MINCCA_PWR);
+ nfarray[ext_idx] = sign_extend32(nf, 8);
+ }
+ }
+ }
+}
+
+static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
+{
+ ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ;
+ ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ;
+ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
+ ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ;
+ ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ;
+ ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9300_5GHZ;
+}
+
+/*
+ * Initialize the ANI register values with default (ini) values.
+ * This routine is called during a (full) hardware reset after
+ * all the registers are initialised from the INI.
+ */
+static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
+{
+ struct ar5416AniState *aniState;
+ struct ath9k_channel *chan = ah->curchan;
+ struct ath9k_ani_default *iniDef;
+ u32 val;
+
+ aniState = &ah->curchan->ani;
+ iniDef = &aniState->iniDef;
+
+ DBG2("ath9k: "
+ "ver %d.%d chan %d Mhz/0x%x\n",
+ ah->hw_version.macVersion,
+ ah->hw_version.macRev,
+ chan->channel,
+ chan->channelFlags);
+
+ val = REG_READ(ah, AR_PHY_SFCORR);
+ iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH);
+ iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH);
+ iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR);
+
+ val = REG_READ(ah, AR_PHY_SFCORR_LOW);
+ iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW);
+ iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW);
+ iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW);
+
+ val = REG_READ(ah, AR_PHY_SFCORR_EXT);
+ iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH);
+ iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH);
+ iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW);
+ iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW);
+ iniDef->firstep = REG_READ_FIELD(ah,
+ AR_PHY_FIND_SIG,
+ AR_PHY_FIND_SIG_FIRSTEP);
+ iniDef->firstepLow = REG_READ_FIELD(ah,
+ AR_PHY_FIND_SIG_LOW,
+ AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW);
+ iniDef->cycpwrThr1 = REG_READ_FIELD(ah,
+ AR_PHY_TIMING5,
+ AR_PHY_TIMING5_CYCPWR_THR1);
+ iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah,
+ AR_PHY_EXT_CCA,
+ AR_PHY_EXT_CYCPWR_THR1);
+
+ /* these levels just got reset to defaults by the INI */
+ aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
+ aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
+ aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
+ aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK;
+}
+
+static void ar9003_hw_set_radar_params(struct ath_hw *ah,
+ struct ath_hw_radar_conf *conf)
+{
+ u32 radar_0 = 0, radar_1 = 0;
+
+ if (!conf) {
+ REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
+ return;
+ }
+
+ radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA;
+ radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR);
+ radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI);
+ radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT);
+ radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);
+ radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);
+
+ radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;
+ radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;
+ radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);
+ radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH);
+ radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH);
+
+ REG_WRITE(ah, AR_PHY_RADAR_0, radar_0);
+ REG_WRITE(ah, AR_PHY_RADAR_1, radar_1);
+ if (conf->ext_channel)
+ REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+ else
+ REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+}
+
+static void ar9003_hw_set_radar_conf(struct ath_hw *ah)
+{
+ struct ath_hw_radar_conf *conf = &ah->radar_conf;
+
+ conf->fir_power = -28;
+ conf->radar_rssi = 0;
+ conf->pulse_height = 10;
+ conf->pulse_rssi = 24;
+ conf->pulse_inband = 8;
+ conf->pulse_maxlen = 255;
+ conf->pulse_inband_step = 12;
+ conf->radar_inband = 8;
+}
+
+static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf)
+{
+ u32 regval;
+
+ regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
+ antconf->main_lna_conf = (regval & AR_PHY_9485_ANT_DIV_MAIN_LNACONF) >>
+ AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S;
+ antconf->alt_lna_conf = (regval & AR_PHY_9485_ANT_DIV_ALT_LNACONF) >>
+ AR_PHY_9485_ANT_DIV_ALT_LNACONF_S;
+ antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >>
+ AR_PHY_9485_ANT_FAST_DIV_BIAS_S;
+ antconf->lna1_lna2_delta = -9;
+ antconf->div_group = 2;
+}
+
+static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf)
+{
+ u32 regval;
+
+ regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
+ regval &= ~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF |
+ AR_PHY_9485_ANT_DIV_ALT_LNACONF |
+ AR_PHY_9485_ANT_FAST_DIV_BIAS |
+ AR_PHY_9485_ANT_DIV_MAIN_GAINTB |
+ AR_PHY_9485_ANT_DIV_ALT_GAINTB);
+ regval |= ((antconf->main_lna_conf <<
+ AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S)
+ & AR_PHY_9485_ANT_DIV_MAIN_LNACONF);
+ regval |= ((antconf->alt_lna_conf << AR_PHY_9485_ANT_DIV_ALT_LNACONF_S)
+ & AR_PHY_9485_ANT_DIV_ALT_LNACONF);
+ regval |= ((antconf->fast_div_bias << AR_PHY_9485_ANT_FAST_DIV_BIAS_S)
+ & AR_PHY_9485_ANT_FAST_DIV_BIAS);
+ regval |= ((antconf->main_gaintb << AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S)
+ & AR_PHY_9485_ANT_DIV_MAIN_GAINTB);
+ regval |= ((antconf->alt_gaintb << AR_PHY_9485_ANT_DIV_ALT_GAINTB_S)
+ & AR_PHY_9485_ANT_DIV_ALT_GAINTB);
+
+ REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
+}
+
+void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
+{
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+ struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+ static const u32 ar9300_cca_regs[6] = {
+ AR_PHY_CCA_0,
+ AR_PHY_CCA_1,
+ AR_PHY_CCA_2,
+ AR_PHY_EXT_CCA,
+ AR_PHY_EXT_CCA_1,
+ AR_PHY_EXT_CCA_2,
+ };
+
+ priv_ops->rf_set_freq = ar9003_hw_set_channel;
+ priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate;
+ priv_ops->compute_pll_control = ar9003_hw_compute_pll_control;
+ priv_ops->set_channel_regs = ar9003_hw_set_channel_regs;
+ priv_ops->init_bb = ar9003_hw_init_bb;
+ priv_ops->process_ini = ar9003_hw_process_ini;
+ priv_ops->set_rfmode = ar9003_hw_set_rfmode;
+ priv_ops->mark_phy_inactive = ar9003_hw_mark_phy_inactive;
+ priv_ops->set_delta_slope = ar9003_hw_set_delta_slope;
+ priv_ops->rfbus_req = ar9003_hw_rfbus_req;
+ priv_ops->rfbus_done = ar9003_hw_rfbus_done;
+ priv_ops->set_diversity = ar9003_hw_set_diversity;
+ priv_ops->ani_control = ar9003_hw_ani_control;
+ priv_ops->do_getnf = ar9003_hw_do_getnf;
+ priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
+ priv_ops->set_radar_params = ar9003_hw_set_radar_params;
+
+ ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
+ ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
+
+ ar9003_hw_set_nf_limits(ah);
+ ar9003_hw_set_radar_conf(ah);
+ memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs));
+}
+
+void ar9003_hw_disable_phy_restart(struct ath_hw *ah)
+{
+ u32 val;
+
+ val = REG_READ(ah, AR_PHY_RESTART);
+ val &= ~AR_PHY_RESTART_ENA;
+
+ REG_WRITE(ah, AR_PHY_RESTART, val);
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_calib.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_calib.c
new file mode 100644
index 00000000..6f3e07e6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_calib.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "hw-ops.h"
+
+/* Common calibration code */
+
+#define ATH9K_NF_TOO_HIGH -60
+
+static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
+{
+ int16_t nfval;
+ int16_t sort[ATH9K_NF_CAL_HIST_MAX];
+ int i, j;
+
+ for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
+ sort[i] = nfCalBuffer[i];
+
+ for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
+ for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
+ if (sort[j] > sort[j - 1]) {
+ nfval = sort[j];
+ sort[j] = sort[j - 1];
+ sort[j - 1] = nfval;
+ }
+ }
+ }
+ nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
+
+ return nfval;
+}
+
+static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct ath_nf_limits *limit;
+
+ if (!chan || IS_CHAN_2GHZ(chan))
+ limit = &ah->nf_2g;
+ else
+ limit = &ah->nf_5g;
+
+ return limit;
+}
+
+static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ return ath9k_hw_get_nf_limits(ah, chan)->nominal;
+}
+
+
+static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
+ struct ath9k_hw_cal_data *cal,
+ int16_t *nfarray)
+{
+ struct ath_nf_limits *limit;
+ struct ath9k_nfcal_hist *h;
+ int high_nf_mid = 0;
+ u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+ int i;
+
+ h = cal->nfCalHist;
+ limit = ath9k_hw_get_nf_limits(ah, ah->curchan);
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (!(chainmask & (1 << i)) ||
+ (i >= AR5416_MAX_CHAINS))
+ continue;
+
+ h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
+
+ if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
+ h[i].currIndex = 0;
+
+ if (h[i].invalidNFcount > 0) {
+ h[i].invalidNFcount--;
+ h[i].privNF = nfarray[i];
+ } else {
+ h[i].privNF =
+ ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
+ }
+
+ if (!h[i].privNF)
+ continue;
+
+ if (h[i].privNF > limit->max) {
+ high_nf_mid = 1;
+
+ DBG2("ath9k: "
+ "NFmid[%d] (%d) > MAX (%d), %s\n",
+ i, h[i].privNF, limit->max,
+ (cal->nfcal_interference ?
+ "not corrected (due to interference)" :
+ "correcting to MAX"));
+
+ /*
+ * Normally we limit the average noise floor by the
+ * hardware specific maximum here. However if we have
+ * encountered stuck beacons because of interference,
+ * we bypass this limit here in order to better deal
+ * with our environment.
+ */
+ if (!cal->nfcal_interference)
+ h[i].privNF = limit->max;
+ }
+ }
+
+ /*
+ * If the noise floor seems normal for all chains, assume that
+ * there is no significant interference in the environment anymore.
+ * Re-enable the enforcement of the NF maximum again.
+ */
+ if (!high_nf_mid)
+ cal->nfcal_interference = 0;
+}
+
+static int ath9k_hw_get_nf_thresh(struct ath_hw *ah,
+ int band,
+ int16_t *nft)
+{
+ switch (band) {
+ case NET80211_BAND_5GHZ:
+ *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5);
+ break;
+ case NET80211_BAND_2GHZ:
+ *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2);
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+void ath9k_hw_reset_calibration(struct ath_hw *ah,
+ struct ath9k_cal_list *currCal)
+{
+ int i;
+
+ ath9k_hw_setup_calibration(ah, currCal);
+
+ currCal->calState = CAL_RUNNING;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ ah->meas0.sign[i] = 0;
+ ah->meas1.sign[i] = 0;
+ ah->meas2.sign[i] = 0;
+ ah->meas3.sign[i] = 0;
+ }
+
+ ah->cal_samples = 0;
+}
+
+/* This is done for the currently configured channel */
+int ath9k_hw_reset_calvalid(struct ath_hw *ah)
+{
+ struct ath9k_cal_list *currCal = ah->cal_list_curr;
+
+ if (!ah->caldata)
+ return 1;
+
+ if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
+ return 1;
+
+ if (currCal == NULL)
+ return 1;
+
+ if (currCal->calState != CAL_DONE) {
+ DBG("ath9k: "
+ "Calibration state incorrect, %d\n",
+ currCal->calState);
+ return 1;
+ }
+
+ if (!(ah->supp_cals & currCal->calData->calType))
+ return 1;
+
+ DBG("ath9k: "
+ "Resetting Cal %d state for channel %d\n",
+ currCal->calData->calType, (ah->dev->channels + ah->dev->channel)->center_freq);
+
+ ah->caldata->CalValid &= ~currCal->calData->calType;
+ currCal->calState = CAL_WAITING;
+
+ return 0;
+}
+
+void ath9k_hw_start_nfcal(struct ath_hw *ah, int update)
+{
+ if (ah->caldata)
+ ah->caldata->nfcal_pending = 1;
+
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_ENABLE_NF);
+
+ if (update)
+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+ else
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+}
+
+void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ struct ath9k_nfcal_hist *h = NULL;
+ unsigned i, j;
+ int32_t val;
+ u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+ s16 default_nf = ath9k_hw_get_default_nf(ah, chan);
+
+ if (ah->caldata)
+ h = ah->caldata->nfCalHist;
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (chainmask & (1 << i)) {
+ s16 nfval;
+
+ if (i >= AR5416_MAX_CHAINS)
+ continue;
+
+ if (h)
+ nfval = h[i].privNF;
+ else
+ nfval = default_nf;
+
+ val = REG_READ(ah, ah->nf_regs[i]);
+ val &= 0xFFFFFE00;
+ val |= (((u32) nfval << 1) & 0x1ff);
+ REG_WRITE(ah, ah->nf_regs[i], val);
+ }
+ }
+
+ /*
+ * Load software filtered NF value into baseband internal minCCApwr
+ * variable.
+ */
+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_ENABLE_NF);
+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+ /*
+ * Wait for load to complete, should be fast, a few 10s of us.
+ * The max delay was changed from an original 250us to 10000us
+ * since 250us often results in NF load timeout and causes deaf
+ * condition during stress testing 12/12/2009
+ */
+ for (j = 0; j < 10000; j++) {
+ if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
+ AR_PHY_AGC_CONTROL_NF) == 0)
+ break;
+ udelay(10);
+ }
+
+ /*
+ * We timed out waiting for the noisefloor to load, probably due to an
+ * in-progress rx. Simply return here and allow the load plenty of time
+ * to complete before the next calibration interval. We need to avoid
+ * trying to load -50 (which happens below) while the previous load is
+ * still in progress as this can cause rx deafness. Instead by returning
+ * here, the baseband nf cal will just be capped by our present
+ * noisefloor until the next calibration timer.
+ */
+ if (j == 10000) {
+ DBG("ath9k: "
+ "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
+ REG_READ(ah, AR_PHY_AGC_CONTROL));
+ return;
+ }
+
+ /*
+ * Restore maxCCAPower register parameter again so that we're not capped
+ * by the median we just loaded. This will be initial (and max) value
+ * of next noise floor calibration the baseband does.
+ */
+ ENABLE_REGWRITE_BUFFER(ah);
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (chainmask & (1 << i)) {
+ if (i >= AR5416_MAX_CHAINS)
+ continue;
+
+ val = REG_READ(ah, ah->nf_regs[i]);
+ val &= 0xFFFFFE00;
+ val |= (((u32) (-50) << 1) & 0x1ff);
+ REG_WRITE(ah, ah->nf_regs[i], val);
+ }
+ }
+ REGWRITE_BUFFER_FLUSH(ah);
+}
+
+
+static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
+{
+ struct ath_nf_limits *limit;
+ int i;
+
+ if (IS_CHAN_2GHZ(ah->curchan))
+ limit = &ah->nf_2g;
+ else
+ limit = &ah->nf_5g;
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (!nf[i])
+ continue;
+
+ DBG2("ath9k: "
+ "NF calibrated [%s] [chain %d] is %d\n",
+ (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
+
+ if (nf[i] > ATH9K_NF_TOO_HIGH) {
+ DBG("ath9k: "
+ "NF[%d] (%d) > MAX (%d), correcting to MAX\n",
+ i, nf[i], ATH9K_NF_TOO_HIGH);
+ nf[i] = limit->max;
+ } else if (nf[i] < limit->min) {
+ DBG("ath9k: "
+ "NF[%d] (%d) < MIN (%d), correcting to NOM\n",
+ i, nf[i], limit->min);
+ nf[i] = limit->nominal;
+ }
+ }
+}
+
+int ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ int16_t nf, nfThresh;
+ int16_t nfarray[NUM_NF_READINGS] = { 0 };
+ struct ath9k_nfcal_hist *h;
+ struct net80211_channel *c = chan->chan;
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
+
+ chan->channelFlags &= (~CHANNEL_CW_INT);
+ if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
+ DBG("ath9k: "
+ "NF did not complete in calibration window\n");
+ return 0;
+ }
+
+ ath9k_hw_do_getnf(ah, nfarray);
+ ath9k_hw_nf_sanitize(ah, nfarray);
+ nf = nfarray[0];
+ if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
+ && nf > nfThresh) {
+ DBG2("ath9k: "
+ "noise floor failed detected; detected %d, threshold %d\n",
+ nf, nfThresh);
+ chan->channelFlags |= CHANNEL_CW_INT;
+ }
+
+ if (!caldata) {
+ chan->noisefloor = nf;
+ return 0;
+ }
+
+ h = caldata->nfCalHist;
+ caldata->nfcal_pending = 0;
+ ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
+ chan->noisefloor = h[0].privNF;
+ return 1;
+}
+
+void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct ath9k_nfcal_hist *h;
+ s16 default_nf;
+ int i, j;
+
+ ah->caldata->channel = chan->channel;
+ ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
+ h = ah->caldata->nfCalHist;
+ default_nf = ath9k_hw_get_default_nf(ah, chan);
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ h[i].currIndex = 0;
+ h[i].privNF = default_nf;
+ h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH;
+ for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
+ h[i].nfCalBuffer[j] = default_nf;
+ }
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_common.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_common.c
new file mode 100644
index 00000000..ce33afbd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_common.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2009-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Module for common driver code between ath9k and ath9k_htc
+ */
+
+#include "common.h"
+
+/*
+ * Update internal channel flags.
+ */
+void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
+ struct net80211_channel *chan)
+{
+ ichan->channel = chan->center_freq;
+ ichan->chan = chan;
+
+ if (chan->band == NET80211_BAND_2GHZ) {
+ ichan->chanmode = CHANNEL_G;
+ ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM;
+ } else {
+ ichan->chanmode = CHANNEL_A;
+ ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
+ }
+}
+
+/*
+ * Get the internal channel reference.
+ */
+struct ath9k_channel *ath9k_cmn_get_curchannel(struct net80211_device *dev,
+ struct ath_hw *ah)
+{
+ struct net80211_channel *curchan = dev->channels + dev->channel;
+ struct ath9k_channel *channel;
+ u8 chan_idx;
+
+ chan_idx = curchan->hw_value;
+ channel = &ah->channels[chan_idx];
+ ath9k_cmn_update_ichannel(channel, curchan);
+
+ return channel;
+}
+
+void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
+ u16 new_txpow, u16 *txpower)
+{
+ if (cur_txpow != new_txpow) {
+ ath9k_hw_set_txpowerlimit(ah, new_txpow, 0);
+ /* read back in case value is clamped */
+ *txpower = ath9k_hw_regulatory(ah)->power_limit;
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom.c
new file mode 100644
index 00000000..f552acaa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom.c
@@ -0,0 +1,551 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+
+#include "hw.h"
+
+static inline u16 ath9k_hw_fbin2freq(u8 fbin, int is2GHz)
+{
+ if (fbin == AR5416_BCHAN_UNUSED)
+ return fbin;
+
+ return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
+}
+
+void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val)
+{
+ REG_WRITE(ah, reg, val);
+
+ if (ah->config.analog_shiftreg)
+ udelay(100);
+}
+
+void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
+ u32 shift, u32 val)
+{
+ u32 regVal;
+
+ regVal = REG_READ(ah, reg) & ~mask;
+ regVal |= (val << shift) & mask;
+
+ REG_WRITE(ah, reg, regVal);
+
+ if (ah->config.analog_shiftreg)
+ udelay(100);
+}
+
+int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
+ int16_t targetLeft, int16_t targetRight)
+{
+ int16_t rv;
+
+ if (srcRight == srcLeft) {
+ rv = targetLeft;
+ } else {
+ rv = (int16_t) (((target - srcLeft) * targetRight +
+ (srcRight - target) * targetLeft) /
+ (srcRight - srcLeft));
+ }
+ return rv;
+}
+
+int ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
+ u16 *indexL, u16 *indexR)
+{
+ u16 i;
+
+ if (target <= pList[0]) {
+ *indexL = *indexR = 0;
+ return 1;
+ }
+ if (target >= pList[listSize - 1]) {
+ *indexL = *indexR = (u16) (listSize - 1);
+ return 1;
+ }
+
+ for (i = 0; i < listSize - 1; i++) {
+ if (pList[i] == target) {
+ *indexL = *indexR = i;
+ return 1;
+ }
+ if (target < pList[i + 1]) {
+ *indexL = i;
+ *indexR = (u16) (i + 1);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
+ int eep_start_loc, int size)
+{
+ int i = 0, j, addr;
+ u32 addrdata[8];
+ u32 data[8];
+
+ for (addr = 0; addr < size; addr++) {
+ addrdata[i] = AR5416_EEPROM_OFFSET +
+ ((addr + eep_start_loc) << AR5416_EEPROM_S);
+ i++;
+ if (i == 8) {
+ REG_READ_MULTI(ah, addrdata, data, i);
+
+ for (j = 0; j < i; j++) {
+ *eep_data = data[j];
+ eep_data++;
+ }
+ i = 0;
+ }
+ }
+
+ if (i != 0) {
+ REG_READ_MULTI(ah, addrdata, data, i);
+
+ for (j = 0; j < i; j++) {
+ *eep_data = data[j];
+ eep_data++;
+ }
+ }
+}
+
+int ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data)
+{
+ return common->bus_ops->eeprom_read(common, off, data);
+}
+
+void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
+ u8 *pVpdList, u16 numIntercepts,
+ u8 *pRetVpdList)
+{
+ u16 i, k;
+ u8 currPwr = pwrMin;
+ u16 idxL = 0, idxR = 0;
+
+ for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
+ ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
+ numIntercepts, &(idxL),
+ &(idxR));
+ if (idxR < 1)
+ idxR = 1;
+ if (idxL == numIntercepts - 1)
+ idxL = (u16) (numIntercepts - 2);
+ if (pPwrList[idxL] == pPwrList[idxR])
+ k = pVpdList[idxL];
+ else
+ k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
+ (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
+ (pPwrList[idxR] - pPwrList[idxL]));
+ pRetVpdList[i] = (u8) k;
+ currPwr += 2;
+ }
+}
+
+void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct cal_target_power_leg *powInfo,
+ u16 numChannels,
+ struct cal_target_power_leg *pNewPower,
+ u16 numRates, int isExtTarget)
+{
+ struct chan_centers centers;
+ u16 clo, chi;
+ int i;
+ int matchIndex = -1, lowIndex = -1;
+ u16 freq;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
+
+ if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
+ IS_CHAN_2GHZ(chan))) {
+ matchIndex = 0;
+ } else {
+ for (i = 0; (i < numChannels) &&
+ (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+ if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
+ IS_CHAN_2GHZ(chan))) {
+ matchIndex = i;
+ break;
+ } else if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
+ IS_CHAN_2GHZ(chan)) && i > 0 &&
+ freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
+ IS_CHAN_2GHZ(chan))) {
+ lowIndex = i - 1;
+ break;
+ }
+ }
+ if ((matchIndex == -1) && (lowIndex == -1))
+ matchIndex = i - 1;
+ }
+
+ if (matchIndex != -1) {
+ *pNewPower = powInfo[matchIndex];
+ } else {
+ clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
+ IS_CHAN_2GHZ(chan));
+ chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
+ IS_CHAN_2GHZ(chan));
+
+ for (i = 0; i < numRates; i++) {
+ pNewPower->tPow2x[i] =
+ (u8)ath9k_hw_interpolate(freq, clo, chi,
+ powInfo[lowIndex].tPow2x[i],
+ powInfo[lowIndex + 1].tPow2x[i]);
+ }
+ }
+}
+
+void ath9k_hw_get_target_powers(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct cal_target_power_ht *powInfo,
+ u16 numChannels,
+ struct cal_target_power_ht *pNewPower,
+ u16 numRates, int isHt40Target)
+{
+ struct chan_centers centers;
+ u16 clo, chi;
+ int i;
+ int matchIndex = -1, lowIndex = -1;
+ u16 freq;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ freq = isHt40Target ? centers.synth_center : centers.ctl_center;
+
+ if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
+ matchIndex = 0;
+ } else {
+ for (i = 0; (i < numChannels) &&
+ (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+ if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
+ IS_CHAN_2GHZ(chan))) {
+ matchIndex = i;
+ break;
+ } else
+ if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
+ IS_CHAN_2GHZ(chan)) && i > 0 &&
+ freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
+ IS_CHAN_2GHZ(chan))) {
+ lowIndex = i - 1;
+ break;
+ }
+ }
+ if ((matchIndex == -1) && (lowIndex == -1))
+ matchIndex = i - 1;
+ }
+
+ if (matchIndex != -1) {
+ *pNewPower = powInfo[matchIndex];
+ } else {
+ clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
+ IS_CHAN_2GHZ(chan));
+ chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
+ IS_CHAN_2GHZ(chan));
+
+ for (i = 0; i < numRates; i++) {
+ pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq,
+ clo, chi,
+ powInfo[lowIndex].tPow2x[i],
+ powInfo[lowIndex + 1].tPow2x[i]);
+ }
+ }
+}
+
+u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
+ int is2GHz, int num_band_edges)
+{
+ u16 twiceMaxEdgePower = MAX_RATE_POWER;
+ int i;
+
+ for (i = 0; (i < num_band_edges) &&
+ (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+ if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
+ twiceMaxEdgePower = CTL_EDGE_TPOWER(pRdEdgesPower[i].ctl);
+ break;
+ } else if ((i > 0) &&
+ (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
+ is2GHz))) {
+ if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
+ is2GHz) < freq &&
+ CTL_EDGE_FLAGS(pRdEdgesPower[i - 1].ctl)) {
+ twiceMaxEdgePower =
+ CTL_EDGE_TPOWER(pRdEdgesPower[i - 1].ctl);
+ }
+ break;
+ }
+ }
+
+ return twiceMaxEdgePower;
+}
+
+void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah)
+{
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+
+ switch (ar5416_get_ntxchains(ah->txchainmask)) {
+ case 1:
+ break;
+ case 2:
+ regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
+ break;
+ case 3:
+ regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
+ break;
+ default:
+ DBG2("ath9k: "
+ "Invalid chainmask configuration\n");
+ break;
+ }
+}
+
+void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ void *pRawDataSet,
+ u8 *bChans, u16 availPiers,
+ u16 tPdGainOverlap,
+ u16 *pPdGainBoundaries, u8 *pPDADCValues,
+ u16 numXpdGains)
+{
+ int i, j, k;
+ int16_t ss;
+ u16 idxL = 0, idxR = 0, numPiers;
+ static u8 vpdTableL[AR5416_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static u8 vpdTableR[AR5416_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static u8 vpdTableI[AR5416_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+ u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+ u8 minPwrT4[AR5416_NUM_PD_GAINS];
+ u8 maxPwrT4[AR5416_NUM_PD_GAINS];
+ int16_t vpdStep;
+ int16_t tmpVal;
+ u16 sizeCurrVpdTable, maxIndex, tgtIndex;
+ int match;
+ int16_t minDelta = 0;
+ struct chan_centers centers;
+ int pdgain_boundary_default;
+ struct cal_data_per_freq *data_def = pRawDataSet;
+ struct cal_data_per_freq_4k *data_4k = pRawDataSet;
+ struct cal_data_per_freq_ar9287 *data_9287 = pRawDataSet;
+ int eeprom_4k = AR_SREV_9285(ah) || AR_SREV_9271(ah);
+ int intercepts;
+
+ if (AR_SREV_9287(ah))
+ intercepts = AR9287_PD_GAIN_ICEPTS;
+ else
+ intercepts = AR5416_PD_GAIN_ICEPTS;
+
+ memset(&minPwrT4, 0, AR5416_NUM_PD_GAINS);
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ for (numPiers = 0; numPiers < availPiers; numPiers++) {
+ if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
+ break;
+ }
+
+ match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
+ IS_CHAN_2GHZ(chan)),
+ bChans, numPiers, &idxL, &idxR);
+
+ if (match) {
+ if (AR_SREV_9287(ah)) {
+ /* FIXME: array overrun? */
+ for (i = 0; i < numXpdGains; i++) {
+ minPwrT4[i] = data_9287[idxL].pwrPdg[i][0];
+ maxPwrT4[i] = data_9287[idxL].pwrPdg[i][4];
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ data_9287[idxL].pwrPdg[i],
+ data_9287[idxL].vpdPdg[i],
+ intercepts,
+ vpdTableI[i]);
+ }
+ } else if (eeprom_4k) {
+ for (i = 0; i < numXpdGains; i++) {
+ minPwrT4[i] = data_4k[idxL].pwrPdg[i][0];
+ maxPwrT4[i] = data_4k[idxL].pwrPdg[i][4];
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ data_4k[idxL].pwrPdg[i],
+ data_4k[idxL].vpdPdg[i],
+ intercepts,
+ vpdTableI[i]);
+ }
+ } else {
+ for (i = 0; i < numXpdGains; i++) {
+ minPwrT4[i] = data_def[idxL].pwrPdg[i][0];
+ maxPwrT4[i] = data_def[idxL].pwrPdg[i][4];
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ data_def[idxL].pwrPdg[i],
+ data_def[idxL].vpdPdg[i],
+ intercepts,
+ vpdTableI[i]);
+ }
+ }
+ } else {
+ for (i = 0; i < numXpdGains; i++) {
+ if (AR_SREV_9287(ah)) {
+ pVpdL = data_9287[idxL].vpdPdg[i];
+ pPwrL = data_9287[idxL].pwrPdg[i];
+ pVpdR = data_9287[idxR].vpdPdg[i];
+ pPwrR = data_9287[idxR].pwrPdg[i];
+ } else if (eeprom_4k) {
+ pVpdL = data_4k[idxL].vpdPdg[i];
+ pPwrL = data_4k[idxL].pwrPdg[i];
+ pVpdR = data_4k[idxR].vpdPdg[i];
+ pPwrR = data_4k[idxR].pwrPdg[i];
+ } else {
+ pVpdL = data_def[idxL].vpdPdg[i];
+ pPwrL = data_def[idxL].pwrPdg[i];
+ pVpdR = data_def[idxR].vpdPdg[i];
+ pPwrR = data_def[idxR].pwrPdg[i];
+ }
+
+ minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
+
+ maxPwrT4[i] =
+ min(pPwrL[intercepts - 1],
+ pPwrR[intercepts - 1]);
+
+
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrL, pVpdL,
+ intercepts,
+ vpdTableL[i]);
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrR, pVpdR,
+ intercepts,
+ vpdTableR[i]);
+
+ for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+ vpdTableI[i][j] =
+ (u8)(ath9k_hw_interpolate((u16)
+ FREQ2FBIN(centers.
+ synth_center,
+ IS_CHAN_2GHZ
+ (chan)),
+ bChans[idxL], bChans[idxR],
+ vpdTableL[i][j], vpdTableR[i][j]));
+ }
+ }
+ }
+
+ k = 0;
+
+ for (i = 0; i < numXpdGains; i++) {
+ if (i == (numXpdGains - 1))
+ pPdGainBoundaries[i] =
+ (u16)(maxPwrT4[i] / 2);
+ else
+ pPdGainBoundaries[i] =
+ (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
+
+ pPdGainBoundaries[i] =
+ min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+ if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
+ minDelta = pPdGainBoundaries[0] - 23;
+ pPdGainBoundaries[0] = 23;
+ } else {
+ minDelta = 0;
+ }
+
+ if (i == 0) {
+ if (AR_SREV_9280_20_OR_LATER(ah))
+ ss = (int16_t)(0 - (minPwrT4[i] / 2));
+ else
+ ss = 0;
+ } else {
+ ss = (int16_t)((pPdGainBoundaries[i - 1] -
+ (minPwrT4[i] / 2)) -
+ tPdGainOverlap + 1 + minDelta);
+ }
+ vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+ while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+ pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
+ ss++;
+ }
+
+ sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
+ tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
+ (minPwrT4[i] / 2));
+ maxIndex = (tgtIndex < sizeCurrVpdTable) ?
+ tgtIndex : sizeCurrVpdTable;
+
+ while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ pPDADCValues[k++] = vpdTableI[i][ss++];
+ }
+
+ vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
+ vpdTableI[i][sizeCurrVpdTable - 2]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+ if (tgtIndex >= maxIndex) {
+ while ((ss <= tgtIndex) &&
+ (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
+ (ss - maxIndex + 1) * vpdStep));
+ pPDADCValues[k++] = (u8)((tmpVal > 255) ?
+ 255 : tmpVal);
+ ss++;
+ }
+ }
+ }
+
+ if (eeprom_4k)
+ pdgain_boundary_default = 58;
+ else
+ pdgain_boundary_default = pPdGainBoundaries[i - 1];
+
+ while (i < AR5416_PD_GAINS_IN_MASK) {
+ pPdGainBoundaries[i] = pdgain_boundary_default;
+ i++;
+ }
+
+ while (k < AR5416_NUM_PDADC_VALUES) {
+ pPDADCValues[k] = pPDADCValues[k - 1];
+ k++;
+ }
+}
+
+int ath9k_hw_eeprom_init(struct ath_hw *ah)
+{
+ int status;
+
+ if (AR_SREV_9300_20_OR_LATER(ah))
+ ah->eep_ops = &eep_ar9300_ops;
+ else if (AR_SREV_9287(ah)) {
+ ah->eep_ops = &eep_ar9287_ops;
+ } else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
+ ah->eep_ops = &eep_4k_ops;
+ } else {
+ ah->eep_ops = &eep_def_ops;
+ }
+
+ if (!ah->eep_ops->fill_eeprom(ah))
+ return -EIO;
+
+ status = ah->eep_ops->check_eeprom(ah);
+
+ return status;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_4k.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_4k.c
new file mode 100644
index 00000000..a42ad3d9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_4k.c
@@ -0,0 +1,1078 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+
+#include "hw.h"
+#include "ar9002_phy.h"
+
+static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
+{
+ return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF);
+}
+
+static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
+{
+ return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF);
+}
+
+#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
+
+static int __ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ u16 *eep_data = (u16 *)&ah->eeprom.map4k;
+ unsigned int addr;
+ int eep_start_loc = 64;
+
+ for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
+ if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) {
+ DBG("ath9k: "
+ "Unable to read eeprom region\n");
+ return 0;
+ }
+ eep_data++;
+ }
+
+ return 1;
+}
+
+static int __ath9k_hw_usb_4k_fill_eeprom(struct ath_hw *ah)
+{
+ u16 *eep_data = (u16 *)&ah->eeprom.map4k;
+
+ ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, 64, SIZE_EEPROM_4K);
+
+ return 1;
+}
+
+static int ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!ath9k_hw_use_flash(ah)) {
+ DBG2("ath9k: "
+ "Reading from EEPROM, not flash\n");
+ }
+
+ if (common->bus_ops->ath_bus_type == ATH_USB)
+ return __ath9k_hw_usb_4k_fill_eeprom(ah);
+ else
+ return __ath9k_hw_4k_fill_eeprom(ah);
+}
+
+#undef SIZE_EEPROM_4K
+
+static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
+{
+#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ar5416_eeprom_4k *eep =
+ (struct ar5416_eeprom_4k *) &ah->eeprom.map4k;
+ u16 *eepdata, temp, magic, magic2;
+ u32 sum = 0, el;
+ int need_swap = 0;
+ unsigned int i, addr;
+
+
+ if (!ath9k_hw_use_flash(ah)) {
+ if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
+ &magic)) {
+ DBG("ath9k: Reading Magic # failed\n");
+ return 0;
+ }
+
+ DBG2("ath9k: "
+ "Read Magic = 0x%04X\n", magic);
+
+ if (magic != AR5416_EEPROM_MAGIC) {
+ magic2 = swab16(magic);
+
+ if (magic2 == AR5416_EEPROM_MAGIC) {
+ need_swap = 1;
+ eepdata = (u16 *) (&ah->eeprom);
+
+ for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
+ temp = swab16(*eepdata);
+ *eepdata = temp;
+ eepdata++;
+ }
+ } else {
+ DBG("ath9k: "
+ "Invalid EEPROM Magic. Endianness mismatch.\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ DBG2("ath9k: need_swap = %s.\n",
+ need_swap ? "True" : "False");
+
+ if (need_swap)
+ el = swab16(ah->eeprom.map4k.baseEepHeader.length);
+ else
+ el = ah->eeprom.map4k.baseEepHeader.length;
+
+ if (el > sizeof(struct ar5416_eeprom_4k))
+ el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
+ else
+ el = el / sizeof(u16);
+
+ eepdata = (u16 *)(&ah->eeprom);
+
+ for (i = 0; i < el; i++)
+ sum ^= *eepdata++;
+
+ if (need_swap) {
+ u32 integer;
+ u16 word;
+
+ DBG("ath9k: "
+ "EEPROM Endianness is not native.. Changing\n");
+
+ word = swab16(eep->baseEepHeader.length);
+ eep->baseEepHeader.length = word;
+
+ word = swab16(eep->baseEepHeader.checksum);
+ eep->baseEepHeader.checksum = word;
+
+ word = swab16(eep->baseEepHeader.version);
+ eep->baseEepHeader.version = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[0]);
+ eep->baseEepHeader.regDmn[0] = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[1]);
+ eep->baseEepHeader.regDmn[1] = word;
+
+ word = swab16(eep->baseEepHeader.rfSilent);
+ eep->baseEepHeader.rfSilent = word;
+
+ word = swab16(eep->baseEepHeader.blueToothOptions);
+ eep->baseEepHeader.blueToothOptions = word;
+
+ word = swab16(eep->baseEepHeader.deviceCap);
+ eep->baseEepHeader.deviceCap = word;
+
+ integer = swab32(eep->modalHeader.antCtrlCommon);
+ eep->modalHeader.antCtrlCommon = integer;
+
+ for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
+ integer = swab32(eep->modalHeader.antCtrlChain[i]);
+ eep->modalHeader.antCtrlChain[i] = integer;
+ }
+
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ word = swab16(eep->modalHeader.spurChans[i].spurChan);
+ eep->modalHeader.spurChans[i].spurChan = word;
+ }
+ }
+
+ if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
+ ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
+ DBG("ath9k: Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+ sum, ah->eep_ops->get_eeprom_ver(ah));
+ return -EINVAL;
+ }
+
+ return 0;
+#undef EEPROM_4K_SIZE
+}
+
+static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
+ enum eeprom_param param)
+{
+ struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+ struct modal_eep_4k_header *pModal = &eep->modalHeader;
+ struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+ u16 ver_minor;
+
+ ver_minor = pBase->version & AR5416_EEP_VER_MINOR_MASK;
+
+ switch (param) {
+ case EEP_NFTHRESH_2:
+ return pModal->noiseFloorThreshCh[0];
+ case EEP_MAC_LSW:
+ return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ case EEP_MAC_MID:
+ return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ case EEP_MAC_MSW:
+ return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ case EEP_REG_0:
+ return pBase->regDmn[0];
+ case EEP_REG_1:
+ return pBase->regDmn[1];
+ case EEP_OP_CAP:
+ return pBase->deviceCap;
+ case EEP_OP_MODE:
+ return pBase->opCapFlags;
+ case EEP_RF_SILENT:
+ return pBase->rfSilent;
+ case EEP_OB_2:
+ return pModal->ob_0;
+ case EEP_DB_2:
+ return pModal->db1_1;
+ case EEP_MINOR_REV:
+ return ver_minor;
+ case EEP_TX_MASK:
+ return pBase->txMask;
+ case EEP_RX_MASK:
+ return pBase->rxMask;
+ case EEP_FRAC_N_5G:
+ return 0;
+ case EEP_PWR_TABLE_OFFSET:
+ return AR5416_PWR_TABLE_OFFSET_DB;
+ case EEP_MODAL_VER:
+ return pModal->version;
+ case EEP_ANT_DIV_CTL1:
+ return pModal->antdiv_ctl1;
+ case EEP_TXGAIN_TYPE:
+ if (ver_minor >= AR5416_EEP_MINOR_VER_19)
+ return pBase->txGainType;
+ else
+ return AR5416_EEP_TXGAIN_ORIGINAL;
+ default:
+ return 0;
+ }
+}
+
+static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ int16_t *pTxPowerIndexOffset)
+{
+ struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+ struct cal_data_per_freq_4k *pRawDataset;
+ u8 *pCalBChans = NULL;
+ u16 pdGainOverlap_t2;
+ static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+ u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
+ u16 numPiers, i, j;
+ u16 numXpdGain, xpdMask;
+ u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
+ u32 reg32, regOffset, regChainOffset;
+
+ xpdMask = pEepData->modalHeader.xpdGain;
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ pdGainOverlap_t2 =
+ pEepData->modalHeader.pdGainOverlap;
+ } else {
+ pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+ }
+
+ pCalBChans = pEepData->calFreqPier2G;
+ numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;
+
+ numXpdGain = 0;
+
+ for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+ if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+ if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
+ break;
+ xpdGainValues[numXpdGain] =
+ (u16)(AR5416_PD_GAINS_IN_MASK - i);
+ numXpdGain++;
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+ (numXpdGain - 1) & 0x3);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+ xpdGainValues[0]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+ xpdGainValues[1]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
+
+ for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
+ if (AR_SREV_5416_20_OR_LATER(ah) &&
+ (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
+ (i != 0)) {
+ regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+ } else
+ regChainOffset = i * 0x1000;
+
+ if (pEepData->baseEepHeader.txMask & (1 << i)) {
+ pRawDataset = pEepData->calPierData2G[i];
+
+ ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
+ pRawDataset, pCalBChans,
+ numPiers, pdGainOverlap_t2,
+ gainBoundaries,
+ pdadcValues, numXpdGain);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
+ REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
+ SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
+ | SM(gainBoundaries[0],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+ | SM(gainBoundaries[1],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+ | SM(gainBoundaries[2],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+ | SM(gainBoundaries[3],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+ }
+
+ regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+ for (j = 0; j < 32; j++) {
+ reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
+ ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
+ ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
+ ((pdadcValues[4 * j + 3] & 0xFF) << 24);
+ REG_WRITE(ah, regOffset, reg32);
+
+ DBG2("ath9k: "
+ "PDADC (%d,%4x): %4.4x %8.8x\n",
+ i, regChainOffset, regOffset,
+ reg32);
+ DBG2("ath9k: "
+ "PDADC: Chain %d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d |\n",
+ i, 4 * j, pdadcValues[4 * j],
+ 4 * j + 1, pdadcValues[4 * j + 1],
+ 4 * j + 2, pdadcValues[4 * j + 2],
+ 4 * j + 3, pdadcValues[4 * j + 3]);
+
+ regOffset += 4;
+ }
+
+ REGWRITE_BUFFER_FLUSH(ah);
+ }
+ }
+
+ *pTxPowerIndexOffset = 0;
+}
+
+static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ int16_t *ratesArray,
+ u16 cfgCtl,
+ u16 AntennaReduction,
+ u16 twiceMaxRegulatoryPower,
+ u16 powerLimit)
+{
+#define CMP_TEST_GRP \
+ (((cfgCtl & ~CTL_MODE_M)| (pCtlMode[ctlMode] & CTL_MODE_M)) == \
+ pEepData->ctlIndex[i]) \
+ || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
+ ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
+
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ unsigned int i;
+ int16_t twiceLargestAntenna;
+ u16 twiceMinEdgePower;
+ u16 twiceMaxEdgePower = MAX_RATE_POWER;
+ u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 numCtlModes;
+ const u16 *pCtlMode;
+ u16 ctlMode, freq;
+ struct chan_centers centers;
+ struct cal_ctl_data_4k *rep;
+ struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+ static const u16 tpScaleReductionTable[5] =
+ { 0, 3, 6, 9, MAX_RATE_POWER };
+ struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+ 0, { 0, 0, 0, 0}
+ };
+ struct cal_target_power_leg targetPowerOfdmExt = {
+ 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
+ 0, { 0, 0, 0, 0 }
+ };
+ struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+ 0, {0, 0, 0, 0}
+ };
+ static const u16 ctlModesFor11g[] = {
+ CTL_11B, CTL_11G, CTL_2GHT20,
+ CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+ };
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
+ twiceLargestAntenna = (int16_t)min(AntennaReduction -
+ twiceLargestAntenna, 0);
+
+ maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+ if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
+ maxRegAllowedPower -=
+ (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
+ }
+
+ scaledPower = min(powerLimit, maxRegAllowedPower);
+ scaledPower = max((u16)0, scaledPower);
+
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
+ pCtlMode = ctlModesFor11g;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCck, 4, 0);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, 0);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT20,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, 0);
+
+ if (IS_CHAN_HT40(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT40,
+ AR5416_NUM_2G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, 1);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCckExt, 4, 1);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, 1);
+ }
+
+ for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+ int isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+ (pCtlMode[ctlMode] == CTL_2GHT40);
+
+ if (isHt40CtlMode)
+ freq = centers.synth_center;
+ else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+ freq = centers.ext_center;
+ else
+ freq = centers.ctl_center;
+
+ if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
+ ah->eep_ops->get_eeprom_rev(ah) <= 2)
+ twiceMaxEdgePower = MAX_RATE_POWER;
+
+ for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&
+ pEepData->ctlIndex[i]; i++) {
+
+ if (CMP_TEST_GRP) {
+ rep = &(pEepData->ctlData[i]);
+
+ twiceMinEdgePower = ath9k_hw_get_max_edge_power(
+ freq,
+ rep->ctlEdges[
+ ar5416_get_ntxchains(ah->txchainmask) - 1],
+ IS_CHAN_2GHZ(chan),
+ AR5416_EEP4K_NUM_BAND_EDGES);
+
+ if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+ twiceMaxEdgePower =
+ min(twiceMaxEdgePower,
+ twiceMinEdgePower);
+ } else {
+ twiceMaxEdgePower = twiceMinEdgePower;
+ break;
+ }
+ }
+ }
+
+ minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
+
+ switch (pCtlMode[ctlMode]) {
+ case CTL_11B:
+ for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
+ targetPowerCck.tPow2x[i] =
+ min((u16)targetPowerCck.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11G:
+ for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
+ targetPowerOfdm.tPow2x[i] =
+ min((u16)targetPowerOfdm.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_2GHT20:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
+ targetPowerHt20.tPow2x[i] =
+ min((u16)targetPowerHt20.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11B_EXT:
+ targetPowerCckExt.tPow2x[0] =
+ min((u16)targetPowerCckExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_11G_EXT:
+ targetPowerOfdmExt.tPow2x[0] =
+ min((u16)targetPowerOfdmExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_2GHT40:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ targetPowerHt40.tPow2x[i] =
+ min((u16)targetPowerHt40.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ratesArray[rate6mb] =
+ ratesArray[rate9mb] =
+ ratesArray[rate12mb] =
+ ratesArray[rate18mb] =
+ ratesArray[rate24mb] =
+ targetPowerOfdm.tPow2x[0];
+
+ ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+ ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+ ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+ ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+ ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+ ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+ ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
+ ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
+ ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
+
+ if (IS_CHAN_HT40(chan)) {
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ ratesArray[rateHt40_0 + i] =
+ targetPowerHt40.tPow2x[i];
+ }
+ ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+ ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
+ }
+
+#undef CMP_TEST_GRP
+}
+
+static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+ u8 powerLimit, int test)
+{
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+ struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
+ int16_t ratesArray[Ar5416RateSize];
+ int16_t txPowerIndexOffset = 0;
+ u8 ht40PowerIncForPdadc = 2;
+ unsigned int i;
+
+ memset(ratesArray, 0, sizeof(ratesArray));
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+ }
+
+ ath9k_hw_set_4k_power_per_rate_table(ah, chan,
+ &ratesArray[0], cfgCtl,
+ twiceAntennaReduction,
+ twiceMaxRegulatoryPower,
+ powerLimit);
+
+ ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
+
+ regulatory->max_power_level = 0;
+ for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+ ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+ if (ratesArray[i] > MAX_RATE_POWER)
+ ratesArray[i] = MAX_RATE_POWER;
+
+ if (ratesArray[i] > regulatory->max_power_level)
+ regulatory->max_power_level = ratesArray[i];
+ }
+
+ if (test)
+ return;
+
+ /* Update regulatory */
+ i = rate6mb;
+ if (IS_CHAN_HT40(chan))
+ i = rateHt40_0;
+ else if (IS_CHAN_HT20(chan))
+ i = rateHt20_0;
+
+ regulatory->max_power_level = ratesArray[i];
+
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
+ }
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ /* OFDM power per rate */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+ ATH9K_POW_SM(ratesArray[rate18mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+ ATH9K_POW_SM(ratesArray[rate54mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+ /* CCK power per rate */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+ ATH9K_POW_SM(ratesArray[rate2s], 24)
+ | ATH9K_POW_SM(ratesArray[rate2l], 16)
+ | ATH9K_POW_SM(ratesArray[rateXr], 8)
+ | ATH9K_POW_SM(ratesArray[rate1l], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+ ATH9K_POW_SM(ratesArray[rate11s], 24)
+ | ATH9K_POW_SM(ratesArray[rate11l], 16)
+ | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+ | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+
+ /* HT20 power per rate */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+ ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+ ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+ /* HT40 power per rate */
+ if (IS_CHAN_HT40(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+ ATH9K_POW_SM(ratesArray[rateHt40_3] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+ ht40PowerIncForPdadc, 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+ ATH9K_POW_SM(ratesArray[rateHt40_7] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+ ht40PowerIncForPdadc, 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+ | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+ | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+ | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+ }
+
+ REGWRITE_BUFFER_FLUSH(ah);
+}
+
+static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
+ struct ath9k_channel *chan __unused)
+{
+ struct modal_eep_4k_header *pModal;
+ struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+ u8 biaslevel;
+
+ if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
+ return;
+
+ if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
+ return;
+
+ pModal = &eep->modalHeader;
+
+ if (pModal->xpaBiasLvl != 0xff) {
+ biaslevel = pModal->xpaBiasLvl;
+ INI_RA(&ah->iniAddac, 7, 1) =
+ (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
+ }
+}
+
+static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
+ struct modal_eep_4k_header *pModal,
+ struct ar5416_eeprom_4k *eep,
+ u8 txRxAttenLocal)
+{
+ REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0,
+ pModal->antCtrlChain[0]);
+
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0),
+ (REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
+ ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+ SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+ SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_3) {
+ txRxAttenLocal = pModal->txRxAttenCh[0];
+
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+ AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+ AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+ AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+ pModal->xatten2Margin[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+ AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
+
+ /* Set the block 1 value to block 0 value */
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
+ AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+ pModal->bswMargin[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
+ AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
+ AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+ pModal->xatten2Margin[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
+ AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+ pModal->xatten2Db[0]);
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
+ AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
+ AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
+
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
+ AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
+ AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
+}
+
+/*
+ * Read EEPROM header info and program the device for correct operation
+ * given the channel value.
+ */
+static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct modal_eep_4k_header *pModal;
+ struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+ struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+ u8 txRxAttenLocal;
+ u8 ob[5], db1[5], db2[5];
+ u8 ant_div_control1, ant_div_control2;
+ u32 regVal;
+
+ pModal = &eep->modalHeader;
+ txRxAttenLocal = 23;
+
+ REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
+
+ /* Single chain for 4K EEPROM*/
+ ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal);
+
+ /* Initialize Ant Diversity settings from EEPROM */
+ if (pModal->version >= 3) {
+ ant_div_control1 = pModal->antdiv_ctl1;
+ ant_div_control2 = pModal->antdiv_ctl2;
+
+ regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+ regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL));
+
+ regVal |= SM(ant_div_control1,
+ AR_PHY_9285_ANT_DIV_CTL);
+ regVal |= SM(ant_div_control2,
+ AR_PHY_9285_ANT_DIV_ALT_LNACONF);
+ regVal |= SM((ant_div_control2 >> 2),
+ AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
+ regVal |= SM((ant_div_control1 >> 1),
+ AR_PHY_9285_ANT_DIV_ALT_GAINTB);
+ regVal |= SM((ant_div_control1 >> 2),
+ AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
+
+
+ REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);
+ regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+ regVal = REG_READ(ah, AR_PHY_CCK_DETECT);
+ regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+ regVal |= SM((ant_div_control1 >> 3),
+ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+
+ REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal);
+ regVal = REG_READ(ah, AR_PHY_CCK_DETECT);
+ }
+
+ if (pModal->version >= 2) {
+ ob[0] = pModal->ob_0;
+ ob[1] = pModal->ob_1;
+ ob[2] = pModal->ob_2;
+ ob[3] = pModal->ob_3;
+ ob[4] = pModal->ob_4;
+
+ db1[0] = pModal->db1_0;
+ db1[1] = pModal->db1_1;
+ db1[2] = pModal->db1_2;
+ db1[3] = pModal->db1_3;
+ db1[4] = pModal->db1_4;
+
+ db2[0] = pModal->db2_0;
+ db2[1] = pModal->db2_1;
+ db2[2] = pModal->db2_2;
+ db2[3] = pModal->db2_3;
+ db2[4] = pModal->db2_4;
+ } else if (pModal->version == 1) {
+ ob[0] = pModal->ob_0;
+ ob[1] = ob[2] = ob[3] = ob[4] = pModal->ob_1;
+ db1[0] = pModal->db1_0;
+ db1[1] = db1[2] = db1[3] = db1[4] = pModal->db1_1;
+ db2[0] = pModal->db2_0;
+ db2[1] = db2[2] = db2[3] = db2[4] = pModal->db2_1;
+ } else {
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ ob[i] = pModal->ob_0;
+ db1[i] = pModal->db1_0;
+ db2[i] = pModal->db1_0;
+ }
+ }
+
+ if (AR_SREV_9271(ah)) {
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9271_AN_RF2G3_OB_cck,
+ AR9271_AN_RF2G3_OB_cck_S,
+ ob[0]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9271_AN_RF2G3_OB_psk,
+ AR9271_AN_RF2G3_OB_psk_S,
+ ob[1]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9271_AN_RF2G3_OB_qam,
+ AR9271_AN_RF2G3_OB_qam_S,
+ ob[2]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9271_AN_RF2G3_DB_1,
+ AR9271_AN_RF2G3_DB_1_S,
+ db1[0]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9271_AN_RF2G4_DB_2,
+ AR9271_AN_RF2G4_DB_2_S,
+ db2[0]);
+ } else {
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_0,
+ AR9285_AN_RF2G3_OB_0_S,
+ ob[0]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_1,
+ AR9285_AN_RF2G3_OB_1_S,
+ ob[1]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_2,
+ AR9285_AN_RF2G3_OB_2_S,
+ ob[2]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_3,
+ AR9285_AN_RF2G3_OB_3_S,
+ ob[3]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_4,
+ AR9285_AN_RF2G3_OB_4_S,
+ ob[4]);
+
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_DB1_0,
+ AR9285_AN_RF2G3_DB1_0_S,
+ db1[0]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_DB1_1,
+ AR9285_AN_RF2G3_DB1_1_S,
+ db1[1]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_DB1_2,
+ AR9285_AN_RF2G3_DB1_2_S,
+ db1[2]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB1_3,
+ AR9285_AN_RF2G4_DB1_3_S,
+ db1[3]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB1_4,
+ AR9285_AN_RF2G4_DB1_4_S, db1[4]);
+
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_0,
+ AR9285_AN_RF2G4_DB2_0_S,
+ db2[0]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_1,
+ AR9285_AN_RF2G4_DB2_1_S,
+ db2[1]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_2,
+ AR9285_AN_RF2G4_DB2_2_S,
+ db2[2]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_3,
+ AR9285_AN_RF2G4_DB2_3_S,
+ db2[3]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_4,
+ AR9285_AN_RF2G4_DB2_4_S,
+ db2[4]);
+ }
+
+
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
+ pModal->switchSettling);
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
+ pModal->adcDesiredSize);
+
+ REG_WRITE(ah, AR_PHY_RF_CTL4,
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
+ SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
+ SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+ pModal->txEndToRxOn);
+
+ if (AR_SREV_9271_10(ah))
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+ pModal->txEndToRxOn);
+ REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+ pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
+ pModal->thresh62);
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
+ pModal->txFrameToDataStart);
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+ pModal->txFrameToPaOn);
+ }
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_3) {
+ if (IS_CHAN_HT40(chan))
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH,
+ pModal->swSettleHt40);
+ }
+ if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) {
+ u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna &
+ EEP_4K_BB_DESIRED_SCALE_MASK);
+ if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
+ u32 pwrctrl, mask, clr;
+
+ mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
+ pwrctrl = mask * bb_desired_scale;
+ clr = mask * 0x1f;
+ REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
+ REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
+ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
+
+ mask = BIT(0)|BIT(5)|BIT(15);
+ pwrctrl = mask * bb_desired_scale;
+ clr = mask * 0x1f;
+ REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
+
+ mask = BIT(0)|BIT(5);
+ pwrctrl = mask * bb_desired_scale;
+ clr = mask * 0x1f;
+ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
+ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
+ }
+ }
+}
+
+static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, int is2GHz)
+{
+#define EEP_MAP4K_SPURCHAN \
+ (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
+
+ u16 spur_val = AR_NO_SPUR;
+
+ DBG2("ath9k: "
+ "Getting spur idx:%d is2Ghz:%d val:%x\n",
+ i, is2GHz, ah->config.spurchans[i][is2GHz]);
+
+ switch (ah->config.spurmode) {
+ case SPUR_DISABLE:
+ break;
+ case SPUR_ENABLE_IOCTL:
+ spur_val = ah->config.spurchans[i][is2GHz];
+ DBG2("ath9k: "
+ "Getting spur val from new loc. %d\n", spur_val);
+ break;
+ case SPUR_ENABLE_EEPROM:
+ spur_val = EEP_MAP4K_SPURCHAN;
+ break;
+ }
+
+ return spur_val;
+
+#undef EEP_MAP4K_SPURCHAN
+}
+
+const struct eeprom_ops eep_4k_ops = {
+ .check_eeprom = ath9k_hw_4k_check_eeprom,
+ .get_eeprom = ath9k_hw_4k_get_eeprom,
+ .fill_eeprom = ath9k_hw_4k_fill_eeprom,
+ .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,
+ .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
+ .set_board_values = ath9k_hw_4k_set_board_values,
+ .set_addac = ath9k_hw_4k_set_addac,
+ .set_txpower = ath9k_hw_4k_set_txpower,
+ .get_spur_channel = ath9k_hw_4k_get_spur_channel
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_9287.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_9287.c
new file mode 100644
index 00000000..ee16a6f1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_9287.c
@@ -0,0 +1,1019 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+
+#include "hw.h"
+#include "ar9002_phy.h"
+
+#define SIZE_EEPROM_AR9287 (sizeof(struct ar9287_eeprom) / sizeof(u16))
+
+static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah)
+{
+ return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF;
+}
+
+static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah)
+{
+ return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF;
+}
+
+static int __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
+{
+ struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+ struct ath_common *common = ath9k_hw_common(ah);
+ u16 *eep_data;
+ unsigned int addr;
+ int eep_start_loc = AR9287_EEP_START_LOC;
+ eep_data = (u16 *)eep;
+
+ for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
+ if (!ath9k_hw_nvram_read(common, addr + eep_start_loc,
+ eep_data)) {
+ DBG("ath9k: "
+ "Unable to read eeprom region\n");
+ return 0;
+ }
+ eep_data++;
+ }
+
+ return 1;
+}
+
+static int __ath9k_hw_usb_ar9287_fill_eeprom(struct ath_hw *ah)
+{
+ u16 *eep_data = (u16 *)&ah->eeprom.map9287;
+
+ ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
+ AR9287_HTC_EEP_START_LOC,
+ SIZE_EEPROM_AR9287);
+ return 1;
+}
+
+static int ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!ath9k_hw_use_flash(ah)) {
+ DBG2("ath9k: "
+ "Reading from EEPROM, not flash\n");
+ }
+
+ if (common->bus_ops->ath_bus_type == ATH_USB)
+ return __ath9k_hw_usb_ar9287_fill_eeprom(ah);
+ else
+ return __ath9k_hw_ar9287_fill_eeprom(ah);
+}
+
+static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
+{
+ u32 sum = 0, el, integer;
+ u16 temp, word, magic, magic2, *eepdata;
+ unsigned int i, addr;
+ int need_swap = 0;
+ struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!ath9k_hw_use_flash(ah)) {
+ if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
+ &magic)) {
+ DBG("ath9k: Reading Magic # failed\n");
+ return 0;
+ }
+
+ DBG2("ath9k: "
+ "Read Magic = 0x%04X\n", magic);
+
+ if (magic != AR5416_EEPROM_MAGIC) {
+ magic2 = swab16(magic);
+
+ if (magic2 == AR5416_EEPROM_MAGIC) {
+ need_swap = 1;
+ eepdata = (u16 *)(&ah->eeprom);
+
+ for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
+ temp = swab16(*eepdata);
+ *eepdata = temp;
+ eepdata++;
+ }
+ } else {
+ DBG("ath9k: "
+ "Invalid EEPROM Magic. Endianness mismatch.\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ DBG2("ath9k: need_swap = %s.\n",
+ need_swap ? "True" : "False");
+
+ if (need_swap)
+ el = swab16(ah->eeprom.map9287.baseEepHeader.length);
+ else
+ el = ah->eeprom.map9287.baseEepHeader.length;
+
+ if (el > sizeof(struct ar9287_eeprom))
+ el = sizeof(struct ar9287_eeprom) / sizeof(u16);
+ else
+ el = el / sizeof(u16);
+
+ eepdata = (u16 *)(&ah->eeprom);
+
+ for (i = 0; i < el; i++)
+ sum ^= *eepdata++;
+
+ if (need_swap) {
+ word = swab16(eep->baseEepHeader.length);
+ eep->baseEepHeader.length = word;
+
+ word = swab16(eep->baseEepHeader.checksum);
+ eep->baseEepHeader.checksum = word;
+
+ word = swab16(eep->baseEepHeader.version);
+ eep->baseEepHeader.version = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[0]);
+ eep->baseEepHeader.regDmn[0] = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[1]);
+ eep->baseEepHeader.regDmn[1] = word;
+
+ word = swab16(eep->baseEepHeader.rfSilent);
+ eep->baseEepHeader.rfSilent = word;
+
+ word = swab16(eep->baseEepHeader.blueToothOptions);
+ eep->baseEepHeader.blueToothOptions = word;
+
+ word = swab16(eep->baseEepHeader.deviceCap);
+ eep->baseEepHeader.deviceCap = word;
+
+ integer = swab32(eep->modalHeader.antCtrlCommon);
+ eep->modalHeader.antCtrlCommon = integer;
+
+ for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+ integer = swab32(eep->modalHeader.antCtrlChain[i]);
+ eep->modalHeader.antCtrlChain[i] = integer;
+ }
+
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ word = swab16(eep->modalHeader.spurChans[i].spurChan);
+ eep->modalHeader.spurChans[i].spurChan = word;
+ }
+ }
+
+ if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER
+ || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
+ DBG("ath9k: Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+ sum, ah->eep_ops->get_eeprom_ver(ah));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
+ enum eeprom_param param)
+{
+ struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+ struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
+ struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
+ u16 ver_minor;
+
+ ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK;
+
+ switch (param) {
+ case EEP_NFTHRESH_2:
+ return pModal->noiseFloorThreshCh[0];
+ case EEP_MAC_LSW:
+ return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ case EEP_MAC_MID:
+ return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ case EEP_MAC_MSW:
+ return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ case EEP_REG_0:
+ return pBase->regDmn[0];
+ case EEP_REG_1:
+ return pBase->regDmn[1];
+ case EEP_OP_CAP:
+ return pBase->deviceCap;
+ case EEP_OP_MODE:
+ return pBase->opCapFlags;
+ case EEP_RF_SILENT:
+ return pBase->rfSilent;
+ case EEP_MINOR_REV:
+ return ver_minor;
+ case EEP_TX_MASK:
+ return pBase->txMask;
+ case EEP_RX_MASK:
+ return pBase->rxMask;
+ case EEP_DEV_TYPE:
+ return pBase->deviceType;
+ case EEP_OL_PWRCTRL:
+ return pBase->openLoopPwrCntl;
+ case EEP_TEMPSENSE_SLOPE:
+ if (ver_minor >= AR9287_EEP_MINOR_VER_2)
+ return pBase->tempSensSlope;
+ else
+ return 0;
+ case EEP_TEMPSENSE_SLOPE_PAL_ON:
+ if (ver_minor >= AR9287_EEP_MINOR_VER_3)
+ return pBase->tempSensSlopePalOn;
+ else
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop,
+ u8 *pCalChans, u16 availPiers, int8_t *pPwr)
+{
+ u16 idxL = 0, idxR = 0, numPiers;
+ int match;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ for (numPiers = 0; numPiers < availPiers; numPiers++) {
+ if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED)
+ break;
+ }
+
+ match = ath9k_hw_get_lower_upper_index(
+ (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
+ pCalChans, numPiers, &idxL, &idxR);
+
+ if (match) {
+ *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0];
+ } else {
+ *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] +
+ (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
+ }
+
+}
+
+static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah,
+ int32_t txPower, u16 chain)
+{
+ u32 tmpVal;
+ u32 a;
+
+ /* Enable OLPC for chain 0 */
+
+ tmpVal = REG_READ(ah, 0xa270);
+ tmpVal = tmpVal & 0xFCFFFFFF;
+ tmpVal = tmpVal | (0x3 << 24);
+ REG_WRITE(ah, 0xa270, tmpVal);
+
+ /* Enable OLPC for chain 1 */
+
+ tmpVal = REG_READ(ah, 0xb270);
+ tmpVal = tmpVal & 0xFCFFFFFF;
+ tmpVal = tmpVal | (0x3 << 24);
+ REG_WRITE(ah, 0xb270, tmpVal);
+
+ /* Write the OLPC ref power for chain 0 */
+
+ if (chain == 0) {
+ tmpVal = REG_READ(ah, 0xa398);
+ tmpVal = tmpVal & 0xff00ffff;
+ a = (txPower)&0xff;
+ tmpVal = tmpVal | (a << 16);
+ REG_WRITE(ah, 0xa398, tmpVal);
+ }
+
+ /* Write the OLPC ref power for chain 1 */
+
+ if (chain == 1) {
+ tmpVal = REG_READ(ah, 0xb398);
+ tmpVal = tmpVal & 0xff00ffff;
+ a = (txPower)&0xff;
+ tmpVal = tmpVal | (a << 16);
+ REG_WRITE(ah, 0xb398, tmpVal);
+ }
+}
+
+static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ int16_t *pTxPowerIndexOffset)
+{
+ struct cal_data_per_freq_ar9287 *pRawDataset;
+ struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
+ u8 *pCalBChans = NULL;
+ u16 pdGainOverlap_t2;
+ u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+ u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
+ u16 numPiers = 0, i, j;
+ u16 numXpdGain, xpdMask;
+ u16 xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0};
+ u32 reg32, regOffset, regChainOffset, regval;
+ int16_t diff = 0;
+ struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
+
+ xpdMask = pEepData->modalHeader.xpdGain;
+
+ if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
+ AR9287_EEP_MINOR_VER_2)
+ pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap;
+ else
+ pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+
+ if (IS_CHAN_2GHZ(chan)) {
+ pCalBChans = pEepData->calFreqPier2G;
+ numPiers = AR9287_NUM_2G_CAL_PIERS;
+ if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
+ pRawDatasetOpenLoop =
+ (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[0];
+ ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0];
+ }
+ }
+
+ numXpdGain = 0;
+
+ /* Calculate the value of xpdgains from the xpdGain Mask */
+ for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+ if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+ if (numXpdGain >= AR5416_NUM_PD_GAINS)
+ break;
+ xpdGainValues[numXpdGain] =
+ (u16)(AR5416_PD_GAINS_IN_MASK-i);
+ numXpdGain++;
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+ (numXpdGain - 1) & 0x3);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+ xpdGainValues[0]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+ xpdGainValues[1]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
+ xpdGainValues[2]);
+
+ for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+ regChainOffset = i * 0x1000;
+
+ if (pEepData->baseEepHeader.txMask & (1 << i)) {
+ pRawDatasetOpenLoop =
+ (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[i];
+
+ if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
+ int8_t txPower;
+ ar9287_eeprom_get_tx_gain_index(ah, chan,
+ pRawDatasetOpenLoop,
+ pCalBChans, numPiers,
+ &txPower);
+ ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i);
+ } else {
+ pRawDataset =
+ (struct cal_data_per_freq_ar9287 *)
+ pEepData->calPierData2G[i];
+
+ ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
+ pRawDataset,
+ pCalBChans, numPiers,
+ pdGainOverlap_t2,
+ gainBoundaries,
+ pdadcValues,
+ numXpdGain);
+ }
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ if (i == 0) {
+ if (!ath9k_hw_ar9287_get_eeprom(ah,
+ EEP_OL_PWRCTRL)) {
+
+ regval = SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
+ | SM(gainBoundaries[0],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+ | SM(gainBoundaries[1],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+ | SM(gainBoundaries[2],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+ | SM(gainBoundaries[3],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4);
+
+ REG_WRITE(ah,
+ AR_PHY_TPCRG5 + regChainOffset,
+ regval);
+ }
+ }
+
+ if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB !=
+ pEepData->baseEepHeader.pwrTableOffset) {
+ diff = (u16)(pEepData->baseEepHeader.pwrTableOffset -
+ (int32_t)AR9287_PWR_TABLE_OFFSET_DB);
+ diff *= 2;
+
+ for (j = 0; j < ((u16)AR5416_NUM_PDADC_VALUES-diff); j++)
+ pdadcValues[j] = pdadcValues[j+diff];
+
+ for (j = (u16)(AR5416_NUM_PDADC_VALUES-diff);
+ j < AR5416_NUM_PDADC_VALUES; j++)
+ pdadcValues[j] =
+ pdadcValues[AR5416_NUM_PDADC_VALUES-diff];
+ }
+
+ if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
+ regOffset = AR_PHY_BASE +
+ (672 << 2) + regChainOffset;
+
+ for (j = 0; j < 32; j++) {
+ reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0)
+ | ((pdadcValues[4*j + 1] & 0xFF) << 8)
+ | ((pdadcValues[4*j + 2] & 0xFF) << 16)
+ | ((pdadcValues[4*j + 3] & 0xFF) << 24);
+
+ REG_WRITE(ah, regOffset, reg32);
+ regOffset += 4;
+ }
+ }
+ REGWRITE_BUFFER_FLUSH(ah);
+ }
+ }
+
+ *pTxPowerIndexOffset = 0;
+}
+
+static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ int16_t *ratesArray,
+ u16 cfgCtl,
+ u16 AntennaReduction,
+ u16 twiceMaxRegulatoryPower,
+ u16 powerLimit)
+{
+#define CMP_CTL \
+ (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
+ pEepData->ctlIndex[i])
+
+#define CMP_NO_CTL \
+ (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
+ ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
+
+#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6
+#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
+
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ u16 twiceMaxEdgePower = MAX_RATE_POWER;
+ static const u16 tpScaleReductionTable[5] =
+ { 0, 3, 6, 9, MAX_RATE_POWER };
+ unsigned int i;
+ int16_t twiceLargestAntenna;
+ struct cal_ctl_data_ar9287 *rep;
+ struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
+ targetPowerCck = {0, {0, 0, 0, 0} };
+ struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} },
+ targetPowerCckExt = {0, {0, 0, 0, 0} };
+ struct cal_target_power_ht targetPowerHt20,
+ targetPowerHt40 = {0, {0, 0, 0, 0} };
+ u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ static const u16 ctlModesFor11g[] = {
+ CTL_11B, CTL_11G, CTL_2GHT20,
+ CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+ };
+ u16 numCtlModes = 0;
+ const u16 *pCtlMode = NULL;
+ u16 ctlMode, freq;
+ struct chan_centers centers;
+ int tx_chainmask;
+ u16 twiceMinEdgePower;
+ struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
+ tx_chainmask = ah->txchainmask;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ /* Compute TxPower reduction due to Antenna Gain */
+ twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0],
+ pEepData->modalHeader.antennaGainCh[1]);
+ twiceLargestAntenna = (int16_t)min((AntennaReduction) -
+ twiceLargestAntenna, 0);
+
+ /*
+ * scaledPower is the minimum of the user input power level
+ * and the regulatory allowed power level.
+ */
+ maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+
+ if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX)
+ maxRegAllowedPower -=
+ (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
+
+ scaledPower = min(powerLimit, maxRegAllowedPower);
+
+ /*
+ * Reduce scaled Power by number of chains active
+ * to get the per chain tx power level.
+ */
+ switch (ar5416_get_ntxchains(tx_chainmask)) {
+ case 1:
+ break;
+ case 2:
+ if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
+ scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+ else
+ scaledPower = 0;
+ break;
+ case 3:
+ if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
+ scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+ else
+ scaledPower = 0;
+ break;
+ }
+ scaledPower = max((u16)0, scaledPower);
+
+ /*
+ * Get TX power from EEPROM.
+ */
+ if (IS_CHAN_2GHZ(chan)) {
+ /* CTL_11B, CTL_11G, CTL_2GHT20 */
+ numCtlModes =
+ ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
+
+ pCtlMode = ctlModesFor11g;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR9287_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCck, 4, 0);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR9287_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, 0);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT20,
+ AR9287_NUM_2G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, 0);
+
+ if (IS_CHAN_HT40(chan)) {
+ /* All 2G CTLs */
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT40,
+ AR9287_NUM_2G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, 1);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR9287_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCckExt, 4, 1);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR9287_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, 1);
+ }
+ }
+
+ for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+ int isHt40CtlMode =
+ (pCtlMode[ctlMode] == CTL_2GHT40) ? 1 : 0;
+
+ if (isHt40CtlMode)
+ freq = centers.synth_center;
+ else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+ freq = centers.ext_center;
+ else
+ freq = centers.ctl_center;
+
+ /* Walk through the CTL indices stored in EEPROM */
+ for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
+ struct cal_ctl_edges *pRdEdgesPower;
+
+ /*
+ * Compare test group from regulatory channel list
+ * with test mode from pCtlMode list
+ */
+ if (CMP_CTL || CMP_NO_CTL) {
+ rep = &(pEepData->ctlData[i]);
+ pRdEdgesPower =
+ rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1];
+
+ twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
+ pRdEdgesPower,
+ IS_CHAN_2GHZ(chan),
+ AR5416_NUM_BAND_EDGES);
+
+ if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+ twiceMaxEdgePower = min(twiceMaxEdgePower,
+ twiceMinEdgePower);
+ } else {
+ twiceMaxEdgePower = twiceMinEdgePower;
+ break;
+ }
+ }
+ }
+
+ minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
+
+ /* Apply ctl mode to correct target power set */
+ switch (pCtlMode[ctlMode]) {
+ case CTL_11B:
+ for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
+ targetPowerCck.tPow2x[i] =
+ (u8)min((u16)targetPowerCck.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11A:
+ case CTL_11G:
+ for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
+ targetPowerOfdm.tPow2x[i] =
+ (u8)min((u16)targetPowerOfdm.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_5GHT20:
+ case CTL_2GHT20:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
+ targetPowerHt20.tPow2x[i] =
+ (u8)min((u16)targetPowerHt20.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11B_EXT:
+ targetPowerCckExt.tPow2x[0] =
+ (u8)min((u16)targetPowerCckExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_11A_EXT:
+ case CTL_11G_EXT:
+ targetPowerOfdmExt.tPow2x[0] =
+ (u8)min((u16)targetPowerOfdmExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_5GHT40:
+ case CTL_2GHT40:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ targetPowerHt40.tPow2x[i] =
+ (u8)min((u16)targetPowerHt40.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Now set the rates array */
+
+ ratesArray[rate6mb] =
+ ratesArray[rate9mb] =
+ ratesArray[rate12mb] =
+ ratesArray[rate18mb] =
+ ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0];
+
+ ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+ ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+ ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+ ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+ ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+ if (IS_CHAN_2GHZ(chan)) {
+ ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+ ratesArray[rate2s] =
+ ratesArray[rate2l] = targetPowerCck.tPow2x[1];
+ ratesArray[rate5_5s] =
+ ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
+ ratesArray[rate11s] =
+ ratesArray[rate11l] = targetPowerCck.tPow2x[3];
+ }
+ if (IS_CHAN_HT40(chan)) {
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++)
+ ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i];
+
+ ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+
+ if (IS_CHAN_2GHZ(chan))
+ ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
+ }
+
+#undef CMP_CTL
+#undef CMP_NO_CTL
+#undef REDUCE_SCALED_POWER_BY_TWO_CHAIN
+#undef REDUCE_SCALED_POWER_BY_THREE_CHAIN
+}
+
+static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
+ struct ath9k_channel *chan, u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+ u8 powerLimit, int test)
+{
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
+ struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
+ int16_t ratesArray[Ar5416RateSize];
+ int16_t txPowerIndexOffset = 0;
+ u8 ht40PowerIncForPdadc = 2;
+ unsigned int i;
+
+ memset(ratesArray, 0, sizeof(ratesArray));
+
+ if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
+ AR9287_EEP_MINOR_VER_2)
+ ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+
+ ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
+ &ratesArray[0], cfgCtl,
+ twiceAntennaReduction,
+ twiceMaxRegulatoryPower,
+ powerLimit);
+
+ ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
+
+ regulatory->max_power_level = 0;
+ for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+ ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+ if (ratesArray[i] > MAX_RATE_POWER)
+ ratesArray[i] = MAX_RATE_POWER;
+
+ if (ratesArray[i] > regulatory->max_power_level)
+ regulatory->max_power_level = ratesArray[i];
+ }
+
+ if (test)
+ return;
+
+ if (IS_CHAN_2GHZ(chan))
+ i = rate1l;
+ else
+ i = rate6mb;
+
+ regulatory->max_power_level = ratesArray[i];
+
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
+ }
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ /* OFDM power per rate */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+ ATH9K_POW_SM(ratesArray[rate18mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+ ATH9K_POW_SM(ratesArray[rate54mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+ /* CCK power per rate */
+ if (IS_CHAN_2GHZ(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+ ATH9K_POW_SM(ratesArray[rate2s], 24)
+ | ATH9K_POW_SM(ratesArray[rate2l], 16)
+ | ATH9K_POW_SM(ratesArray[rateXr], 8)
+ | ATH9K_POW_SM(ratesArray[rate1l], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+ ATH9K_POW_SM(ratesArray[rate11s], 24)
+ | ATH9K_POW_SM(ratesArray[rate11l], 16)
+ | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+ | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+ }
+
+ /* HT20 power per rate */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+ ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+ ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+ /* HT40 power per rate */
+ if (IS_CHAN_HT40(chan)) {
+ if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+ ATH9K_POW_SM(ratesArray[rateHt40_3], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_2], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_1], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_0], 0));
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+ ATH9K_POW_SM(ratesArray[rateHt40_7], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_6], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_5], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_4], 0));
+ } else {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+ ATH9K_POW_SM(ratesArray[rateHt40_3] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+ ht40PowerIncForPdadc, 0));
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+ ATH9K_POW_SM(ratesArray[rateHt40_7] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+ ht40PowerIncForPdadc, 0));
+ }
+
+ /* Dup/Ext power per rate */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+ | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+ | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+ | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+ }
+ REGWRITE_BUFFER_FLUSH(ah);
+}
+
+static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah __unused,
+ struct ath9k_channel *chan __unused)
+{
+}
+
+static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+ struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
+ u32 regChainOffset, regval;
+ u8 txRxAttenLocal;
+ int i;
+
+ pModal = &eep->modalHeader;
+
+ REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
+
+ for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+ regChainOffset = i * 0x1000;
+
+ REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
+ pModal->antCtrlChain[i]);
+
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
+ (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset)
+ & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+ SM(pModal->iqCalICh[i],
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+ SM(pModal->iqCalQCh[i],
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+ txRxAttenLocal = pModal->txRxAttenCh[i];
+
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+ pModal->bswMargin[i]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+ pModal->bswAtten[i]);
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_ATTEN,
+ txRxAttenLocal);
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_MARGIN,
+ pModal->rxTxMarginCh[i]);
+ }
+
+
+ if (IS_CHAN_HT40(chan))
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
+ else
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH, pModal->switchSettling);
+
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+ AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize);
+
+ REG_WRITE(ah, AR_PHY_RF_CTL4,
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
+ | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
+ | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)
+ | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL3,
+ AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn);
+
+ REG_RMW_FIELD(ah, AR_PHY_CCA,
+ AR9280_PHY_CCA_THRESH62, pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
+ AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62);
+
+ regval = REG_READ(ah, AR9287_AN_RF2G3_CH0);
+ regval &= ~(AR9287_AN_RF2G3_DB1 |
+ AR9287_AN_RF2G3_DB2 |
+ AR9287_AN_RF2G3_OB_CCK |
+ AR9287_AN_RF2G3_OB_PSK |
+ AR9287_AN_RF2G3_OB_QAM |
+ AR9287_AN_RF2G3_OB_PAL_OFF);
+ regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) |
+ SM(pModal->db2, AR9287_AN_RF2G3_DB2) |
+ SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) |
+ SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) |
+ SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) |
+ SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF));
+
+ ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH0, regval);
+
+ regval = REG_READ(ah, AR9287_AN_RF2G3_CH1);
+ regval &= ~(AR9287_AN_RF2G3_DB1 |
+ AR9287_AN_RF2G3_DB2 |
+ AR9287_AN_RF2G3_OB_CCK |
+ AR9287_AN_RF2G3_OB_PSK |
+ AR9287_AN_RF2G3_OB_QAM |
+ AR9287_AN_RF2G3_OB_PAL_OFF);
+ regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) |
+ SM(pModal->db2, AR9287_AN_RF2G3_DB2) |
+ SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) |
+ SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) |
+ SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) |
+ SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF));
+
+ ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH1, regval);
+
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+ AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart);
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+ AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn);
+
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2,
+ AR9287_AN_TOP2_XPABIAS_LVL,
+ AR9287_AN_TOP2_XPABIAS_LVL_S,
+ pModal->xpaBiasLvl);
+}
+
+static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
+ u16 i, int is2GHz)
+{
+#define EEP_MAP9287_SPURCHAN \
+ (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan)
+
+ u16 spur_val = AR_NO_SPUR;
+
+ DBG2("ath9k: "
+ "Getting spur idx:%d is2Ghz:%d val:%x\n",
+ i, is2GHz, ah->config.spurchans[i][is2GHz]);
+
+ switch (ah->config.spurmode) {
+ case SPUR_DISABLE:
+ break;
+ case SPUR_ENABLE_IOCTL:
+ spur_val = ah->config.spurchans[i][is2GHz];
+ DBG2("ath9k: "
+ "Getting spur val from new loc. %d\n", spur_val);
+ break;
+ case SPUR_ENABLE_EEPROM:
+ spur_val = EEP_MAP9287_SPURCHAN;
+ break;
+ }
+
+ return spur_val;
+
+#undef EEP_MAP9287_SPURCHAN
+}
+
+const struct eeprom_ops eep_ar9287_ops = {
+ .check_eeprom = ath9k_hw_ar9287_check_eeprom,
+ .get_eeprom = ath9k_hw_ar9287_get_eeprom,
+ .fill_eeprom = ath9k_hw_ar9287_fill_eeprom,
+ .get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver,
+ .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev,
+ .set_board_values = ath9k_hw_ar9287_set_board_values,
+ .set_addac = ath9k_hw_ar9287_set_addac,
+ .set_txpower = ath9k_hw_ar9287_set_txpower,
+ .get_spur_channel = ath9k_hw_ar9287_get_spur_channel
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_def.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_def.c
new file mode 100644
index 00000000..9b144d70
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_def.c
@@ -0,0 +1,1351 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+
+#include "hw.h"
+#include "ar9002_phy.h"
+
+static void ath9k_get_txgain_index(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct calDataPerFreqOpLoop *rawDatasetOpLoop,
+ u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx)
+{
+ u8 pcdac, i = 0;
+ u16 idxL = 0, idxR = 0, numPiers;
+ int match;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ for (numPiers = 0; numPiers < availPiers; numPiers++)
+ if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
+ break;
+
+ match = ath9k_hw_get_lower_upper_index(
+ (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
+ calChans, numPiers, &idxL, &idxR);
+ if (match) {
+ pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
+ *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
+ } else {
+ pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
+ *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
+ rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
+ }
+
+ while (pcdac > ah->originalGain[i] &&
+ i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
+ i++;
+
+ *pcdacIdx = i;
+}
+
+static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
+ u32 initTxGain,
+ int txPower,
+ u8 *pPDADCValues)
+{
+ u32 i;
+ u32 offset;
+
+ REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
+ AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
+ REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
+ AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
+
+ REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
+ AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
+
+ offset = txPower;
+ for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
+ if (i < offset)
+ pPDADCValues[i] = 0x0;
+ else
+ pPDADCValues[i] = 0xFF;
+}
+
+static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)
+{
+ return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF);
+}
+
+static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
+{
+ return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF);
+}
+
+#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
+
+static int __ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ u16 *eep_data = (u16 *)&ah->eeprom.def;
+ unsigned int addr;
+ int ar5416_eep_start_loc = 0x100;
+
+ for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
+ if (!ath9k_hw_nvram_read(common, addr + ar5416_eep_start_loc,
+ eep_data)) {
+ DBG("ath9k: "
+ "Unable to read eeprom region\n");
+ return 0;
+ }
+ eep_data++;
+ }
+ return 1;
+}
+
+static int __ath9k_hw_usb_def_fill_eeprom(struct ath_hw *ah)
+{
+ u16 *eep_data = (u16 *)&ah->eeprom.def;
+
+ ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
+ 0x100, SIZE_EEPROM_DEF);
+ return 1;
+}
+
+static int ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!ath9k_hw_use_flash(ah)) {
+ DBG2("ath9k: "
+ "Reading from EEPROM, not flash\n");
+ }
+
+ if (common->bus_ops->ath_bus_type == ATH_USB)
+ return __ath9k_hw_usb_def_fill_eeprom(ah);
+ else
+ return __ath9k_hw_def_fill_eeprom(ah);
+}
+
+#undef SIZE_EEPROM_DEF
+
+static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
+{
+ struct ar5416_eeprom_def *eep =
+ (struct ar5416_eeprom_def *) &ah->eeprom.def;
+ struct ath_common *common = ath9k_hw_common(ah);
+ u16 *eepdata, temp, magic, magic2;
+ u32 sum = 0, el;
+ int need_swap = 0;
+ unsigned int i, addr, size;
+
+ if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
+ DBG("ath9k: Reading Magic # failed\n");
+ return 0;
+ }
+
+ if (!ath9k_hw_use_flash(ah)) {
+ DBG2("ath9k: "
+ "Read Magic = 0x%04X\n", magic);
+
+ if (magic != AR5416_EEPROM_MAGIC) {
+ magic2 = swab16(magic);
+
+ if (magic2 == AR5416_EEPROM_MAGIC) {
+ size = sizeof(struct ar5416_eeprom_def);
+ need_swap = 1;
+ eepdata = (u16 *) (&ah->eeprom);
+
+ for (addr = 0; addr < size / sizeof(u16); addr++) {
+ temp = swab16(*eepdata);
+ *eepdata = temp;
+ eepdata++;
+ }
+ } else {
+ DBG("ath9k: "
+ "Invalid EEPROM Magic. Endianness mismatch.\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ DBG2("ath9k: need_swap = %s.\n",
+ need_swap ? "True" : "False");
+
+ if (need_swap)
+ el = swab16(ah->eeprom.def.baseEepHeader.length);
+ else
+ el = ah->eeprom.def.baseEepHeader.length;
+
+ if (el > sizeof(struct ar5416_eeprom_def))
+ el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
+ else
+ el = el / sizeof(u16);
+
+ eepdata = (u16 *)(&ah->eeprom);
+
+ for (i = 0; i < el; i++)
+ sum ^= *eepdata++;
+
+ if (need_swap) {
+ u32 integer, j;
+ u16 word;
+
+ DBG("ath9k: "
+ "EEPROM Endianness is not native.. Changing.\n");
+
+ word = swab16(eep->baseEepHeader.length);
+ eep->baseEepHeader.length = word;
+
+ word = swab16(eep->baseEepHeader.checksum);
+ eep->baseEepHeader.checksum = word;
+
+ word = swab16(eep->baseEepHeader.version);
+ eep->baseEepHeader.version = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[0]);
+ eep->baseEepHeader.regDmn[0] = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[1]);
+ eep->baseEepHeader.regDmn[1] = word;
+
+ word = swab16(eep->baseEepHeader.rfSilent);
+ eep->baseEepHeader.rfSilent = word;
+
+ word = swab16(eep->baseEepHeader.blueToothOptions);
+ eep->baseEepHeader.blueToothOptions = word;
+
+ word = swab16(eep->baseEepHeader.deviceCap);
+ eep->baseEepHeader.deviceCap = word;
+
+ for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
+ struct modal_eep_header *pModal =
+ &eep->modalHeader[j];
+ integer = swab32(pModal->antCtrlCommon);
+ pModal->antCtrlCommon = integer;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ integer = swab32(pModal->antCtrlChain[i]);
+ pModal->antCtrlChain[i] = integer;
+ }
+ for (i = 0; i < 3; i++) {
+ word = swab16(pModal->xpaBiasLvlFreq[i]);
+ pModal->xpaBiasLvlFreq[i] = word;
+ }
+
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ word = swab16(pModal->spurChans[i].spurChan);
+ pModal->spurChans[i].spurChan = word;
+ }
+ }
+ }
+
+ if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
+ ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
+ DBG("ath9k: Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+ sum, ah->eep_ops->get_eeprom_ver(ah));
+ return -EINVAL;
+ }
+
+ /* Enable fixup for AR_AN_TOP2 if necessary */
+ if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
+ ((eep->baseEepHeader.version & 0xff) > 0x0a) &&
+ (eep->baseEepHeader.pwdclkind == 0))
+ ah->need_an_top2_fixup = 1;
+
+ if ((common->bus_ops->ath_bus_type == ATH_USB) &&
+ (AR_SREV_9280(ah)))
+ eep->modalHeader[0].xpaBiasLvl = 0;
+
+ return 0;
+}
+
+static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
+ enum eeprom_param param)
+{
+ struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+ struct modal_eep_header *pModal = eep->modalHeader;
+ struct base_eep_header *pBase = &eep->baseEepHeader;
+
+ switch (param) {
+ case EEP_NFTHRESH_5:
+ return pModal[0].noiseFloorThreshCh[0];
+ case EEP_NFTHRESH_2:
+ return pModal[1].noiseFloorThreshCh[0];
+ case EEP_MAC_LSW:
+ return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ case EEP_MAC_MID:
+ return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ case EEP_MAC_MSW:
+ return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ case EEP_REG_0:
+ return pBase->regDmn[0];
+ case EEP_REG_1:
+ return pBase->regDmn[1];
+ case EEP_OP_CAP:
+ return pBase->deviceCap;
+ case EEP_OP_MODE:
+ return pBase->opCapFlags;
+ case EEP_RF_SILENT:
+ return pBase->rfSilent;
+ case EEP_OB_5:
+ return pModal[0].ob;
+ case EEP_DB_5:
+ return pModal[0].db;
+ case EEP_OB_2:
+ return pModal[1].ob;
+ case EEP_DB_2:
+ return pModal[1].db;
+ case EEP_MINOR_REV:
+ return AR5416_VER_MASK;
+ case EEP_TX_MASK:
+ return pBase->txMask;
+ case EEP_RX_MASK:
+ return pBase->rxMask;
+ case EEP_FSTCLK_5G:
+ return pBase->fastClk5g;
+ case EEP_RXGAIN_TYPE:
+ return pBase->rxGainType;
+ case EEP_TXGAIN_TYPE:
+ return pBase->txGainType;
+ case EEP_OL_PWRCTRL:
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
+ return pBase->openLoopPwrCntl ? 1 : 0;
+ else
+ return 0;
+ case EEP_RC_CHAIN_MASK:
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
+ return pBase->rcChainMask;
+ else
+ return 0;
+ case EEP_DAC_HPWR_5G:
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
+ return pBase->dacHiPwrMode_5G;
+ else
+ return 0;
+ case EEP_FRAC_N_5G:
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
+ return pBase->frac_n_5g;
+ else
+ return 0;
+ case EEP_PWR_TABLE_OFFSET:
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_21)
+ return pBase->pwr_table_offset;
+ else
+ return AR5416_PWR_TABLE_OFFSET_DB;
+ default:
+ return 0;
+ }
+}
+
+static void ath9k_hw_def_set_gain(struct ath_hw *ah,
+ struct modal_eep_header *pModal,
+ struct ar5416_eeprom_def *eep,
+ u8 txRxAttenLocal, int regChainOffset, int i)
+{
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
+ txRxAttenLocal = pModal->txRxAttenCh[i];
+
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+ pModal->bswMargin[i]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+ pModal->bswAtten[i]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+ pModal->xatten2Margin[i]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+ pModal->xatten2Db[i]);
+ } else {
+ REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+ ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
+ | SM(pModal-> bswMargin[i],
+ AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+ REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+ ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
+ | SM(pModal->bswAtten[i],
+ AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+ }
+ }
+
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ REG_RMW_FIELD(ah,
+ AR_PHY_RXGAIN + regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+ REG_RMW_FIELD(ah,
+ AR_PHY_RXGAIN + regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);
+ } else {
+ REG_WRITE(ah,
+ AR_PHY_RXGAIN + regChainOffset,
+ (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) &
+ ~AR_PHY_RXGAIN_TXRX_ATTEN)
+ | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN));
+ REG_WRITE(ah,
+ AR_PHY_GAIN_2GHZ + regChainOffset,
+ (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+ ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
+ SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
+ }
+}
+
+static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct modal_eep_header *pModal;
+ struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+ int i, regChainOffset;
+ u8 txRxAttenLocal;
+
+ pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+ txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
+
+ REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon & 0xffff);
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (AR_SREV_9280(ah)) {
+ if (i >= 2)
+ break;
+ }
+
+ if (AR_SREV_5416_20_OR_LATER(ah) &&
+ (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
+ regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+ else
+ regChainOffset = i * 0x1000;
+
+ REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
+ pModal->antCtrlChain[i]);
+
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
+ (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
+ ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+ SM(pModal->iqCalICh[i],
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+ SM(pModal->iqCalQCh[i],
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+ if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
+ ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
+ regChainOffset, i);
+ }
+
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ if (IS_CHAN_2GHZ(chan)) {
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+ AR_AN_RF2G1_CH0_OB,
+ AR_AN_RF2G1_CH0_OB_S,
+ pModal->ob);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+ AR_AN_RF2G1_CH0_DB,
+ AR_AN_RF2G1_CH0_DB_S,
+ pModal->db);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+ AR_AN_RF2G1_CH1_OB,
+ AR_AN_RF2G1_CH1_OB_S,
+ pModal->ob_ch1);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+ AR_AN_RF2G1_CH1_DB,
+ AR_AN_RF2G1_CH1_DB_S,
+ pModal->db_ch1);
+ } else {
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+ AR_AN_RF5G1_CH0_OB5,
+ AR_AN_RF5G1_CH0_OB5_S,
+ pModal->ob);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+ AR_AN_RF5G1_CH0_DB5,
+ AR_AN_RF5G1_CH0_DB5_S,
+ pModal->db);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+ AR_AN_RF5G1_CH1_OB5,
+ AR_AN_RF5G1_CH1_OB5_S,
+ pModal->ob_ch1);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+ AR_AN_RF5G1_CH1_DB5,
+ AR_AN_RF5G1_CH1_DB5_S,
+ pModal->db_ch1);
+ }
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+ AR_AN_TOP2_XPABIAS_LVL,
+ AR_AN_TOP2_XPABIAS_LVL_S,
+ pModal->xpaBiasLvl);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+ AR_AN_TOP2_LOCALBIAS,
+ AR_AN_TOP2_LOCALBIAS_S,
+ !!(pModal->lna_ctl &
+ LNA_CTL_LOCAL_BIAS));
+ REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
+ !!(pModal->lna_ctl & LNA_CTL_FORCE_XPA));
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
+ pModal->switchSettling);
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
+ pModal->adcDesiredSize);
+
+ if (!AR_SREV_9280_20_OR_LATER(ah))
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+ AR_PHY_DESIRED_SZ_PGA,
+ pModal->pgaDesiredSize);
+
+ REG_WRITE(ah, AR_PHY_RF_CTL4,
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
+ | SM(pModal->txEndToXpaOff,
+ AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
+ | SM(pModal->txFrameToXpaOn,
+ AR_PHY_RF_CTL4_FRAME_XPAA_ON)
+ | SM(pModal->txFrameToXpaOn,
+ AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+ pModal->txEndToRxOn);
+
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+ pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
+ AR_PHY_EXT_CCA0_THRESH62,
+ pModal->thresh62);
+ } else {
+ REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
+ pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+ AR_PHY_EXT_CCA_THRESH62,
+ pModal->thresh62);
+ }
+
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+ AR_PHY_TX_END_DATA_START,
+ pModal->txFrameToDataStart);
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+ pModal->txFrameToPaOn);
+ }
+
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
+ if (IS_CHAN_HT40(chan))
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH,
+ pModal->swSettleHt40);
+ }
+
+ if (AR_SREV_9280_20_OR_LATER(ah) &&
+ AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
+ REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
+ AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
+ pModal->miscBits);
+
+
+ if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
+ if (IS_CHAN_2GHZ(chan))
+ REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
+ eep->baseEepHeader.dacLpMode);
+ else if (eep->baseEepHeader.dacHiPwrMode_5G)
+ REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
+ else
+ REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
+ eep->baseEepHeader.dacLpMode);
+
+ udelay(100);
+
+ REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
+ pModal->miscBits >> 2);
+
+ REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
+ AR_PHY_TX_DESIRED_SCALE_CCK,
+ eep->baseEepHeader.desiredScaleCCK);
+ }
+}
+
+static void ath9k_hw_def_set_addac(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
+ struct modal_eep_header *pModal;
+ struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+ u8 biaslevel;
+
+ if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
+ return;
+
+ if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
+ return;
+
+ pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+
+ if (pModal->xpaBiasLvl != 0xff) {
+ biaslevel = pModal->xpaBiasLvl;
+ } else {
+ u16 resetFreqBin, freqBin, freqCount = 0;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ resetFreqBin = FREQ2FBIN(centers.synth_center,
+ IS_CHAN_2GHZ(chan));
+ freqBin = XPA_LVL_FREQ(0) & 0xff;
+ biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);
+
+ freqCount++;
+
+ while (freqCount < 3) {
+ if (XPA_LVL_FREQ(freqCount) == 0x0)
+ break;
+
+ freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
+ if (resetFreqBin >= freqBin)
+ biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);
+ else
+ break;
+ freqCount++;
+ }
+ }
+
+ if (IS_CHAN_2GHZ(chan)) {
+ INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac,
+ 7, 1) & (~0x18)) | biaslevel << 3;
+ } else {
+ INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac,
+ 6, 1) & (~0xc0)) | biaslevel << 6;
+ }
+#undef XPA_LVL_FREQ
+}
+
+static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah,
+ u16 *gb,
+ u16 numXpdGain,
+ u16 pdGainOverlap_t2,
+ int8_t pwr_table_offset,
+ int16_t *diff)
+
+{
+ u16 k;
+
+ /* Prior to writing the boundaries or the pdadc vs. power table
+ * into the chip registers the default starting point on the pdadc
+ * vs. power table needs to be checked and the curve boundaries
+ * adjusted accordingly
+ */
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ u16 gb_limit;
+
+ if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) {
+ /* get the difference in dB */
+ *diff = (u16)(pwr_table_offset - AR5416_PWR_TABLE_OFFSET_DB);
+ /* get the number of half dB steps */
+ *diff *= 2;
+ /* change the original gain boundary settings
+ * by the number of half dB steps
+ */
+ for (k = 0; k < numXpdGain; k++)
+ gb[k] = (u16)(gb[k] - *diff);
+ }
+ /* Because of a hardware limitation, ensure the gain boundary
+ * is not larger than (63 - overlap)
+ */
+ gb_limit = (u16)(MAX_RATE_POWER - pdGainOverlap_t2);
+
+ for (k = 0; k < numXpdGain; k++)
+ gb[k] = (u16)min(gb_limit, gb[k]);
+ }
+
+ return *diff;
+}
+
+static void ath9k_adjust_pdadc_values(struct ath_hw *ah,
+ int8_t pwr_table_offset,
+ int16_t diff,
+ u8 *pdadcValues)
+{
+#define NUM_PDADC(diff) (AR5416_NUM_PDADC_VALUES - diff)
+ u16 k;
+
+ /* If this is a board that has a pwrTableOffset that differs from
+ * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the
+ * pdadc vs pwr table needs to be adjusted prior to writing to the
+ * chip.
+ */
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) {
+ /* shift the table to start at the new offset */
+ for (k = 0; k < (u16)NUM_PDADC(diff); k++ ) {
+ pdadcValues[k] = pdadcValues[k + diff];
+ }
+
+ /* fill the back of the table */
+ for (k = (u16)NUM_PDADC(diff); k < NUM_PDADC(0); k++) {
+ pdadcValues[k] = pdadcValues[NUM_PDADC(diff)];
+ }
+ }
+ }
+#undef NUM_PDADC
+}
+
+static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ int16_t *pTxPowerIndexOffset)
+{
+#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
+#define SM_PDGAIN_B(x, y) \
+ SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
+ struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+ struct cal_data_per_freq *pRawDataset;
+ u8 *pCalBChans = NULL;
+ u16 pdGainOverlap_t2;
+ static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+ u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
+ u16 numPiers, i, j;
+ int16_t diff = 0;
+ u16 numXpdGain, xpdMask;
+ u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
+ u32 reg32, regOffset, regChainOffset;
+ int16_t modalIdx;
+ int8_t pwr_table_offset;
+
+ modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
+ xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
+
+ pwr_table_offset = ah->eep_ops->get_eeprom(ah, EEP_PWR_TABLE_OFFSET);
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ pdGainOverlap_t2 =
+ pEepData->modalHeader[modalIdx].pdGainOverlap;
+ } else {
+ pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+ }
+
+ if (IS_CHAN_2GHZ(chan)) {
+ pCalBChans = pEepData->calFreqPier2G;
+ numPiers = AR5416_NUM_2G_CAL_PIERS;
+ } else {
+ pCalBChans = pEepData->calFreqPier5G;
+ numPiers = AR5416_NUM_5G_CAL_PIERS;
+ }
+
+ if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
+ pRawDataset = pEepData->calPierData2G[0];
+ ah->initPDADC = ((struct calDataPerFreqOpLoop *)
+ pRawDataset)->vpdPdg[0][0];
+ }
+
+ numXpdGain = 0;
+
+ for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+ if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+ if (numXpdGain >= AR5416_NUM_PD_GAINS)
+ break;
+ xpdGainValues[numXpdGain] =
+ (u16)(AR5416_PD_GAINS_IN_MASK - i);
+ numXpdGain++;
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+ (numXpdGain - 1) & 0x3);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+ xpdGainValues[0]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+ xpdGainValues[1]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
+ xpdGainValues[2]);
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (AR_SREV_5416_20_OR_LATER(ah) &&
+ (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
+ (i != 0)) {
+ regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+ } else
+ regChainOffset = i * 0x1000;
+
+ if (pEepData->baseEepHeader.txMask & (1 << i)) {
+ if (IS_CHAN_2GHZ(chan))
+ pRawDataset = pEepData->calPierData2G[i];
+ else
+ pRawDataset = pEepData->calPierData5G[i];
+
+
+ if (OLC_FOR_AR9280_20_LATER) {
+ u8 pcdacIdx;
+ u8 txPower;
+
+ ath9k_get_txgain_index(ah, chan,
+ (struct calDataPerFreqOpLoop *)pRawDataset,
+ pCalBChans, numPiers, &txPower, &pcdacIdx);
+ ath9k_olc_get_pdadcs(ah, pcdacIdx,
+ txPower/2, pdadcValues);
+ } else {
+ ath9k_hw_get_gain_boundaries_pdadcs(ah,
+ chan, pRawDataset,
+ pCalBChans, numPiers,
+ pdGainOverlap_t2,
+ gainBoundaries,
+ pdadcValues,
+ numXpdGain);
+ }
+
+ diff = ath9k_change_gain_boundary_setting(ah,
+ gainBoundaries,
+ numXpdGain,
+ pdGainOverlap_t2,
+ pwr_table_offset,
+ &diff);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
+ if (OLC_FOR_AR9280_20_LATER) {
+ REG_WRITE(ah,
+ AR_PHY_TPCRG5 + regChainOffset,
+ SM(0x6,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+ SM_PD_GAIN(1) | SM_PD_GAIN(2) |
+ SM_PD_GAIN(3) | SM_PD_GAIN(4));
+ } else {
+ REG_WRITE(ah,
+ AR_PHY_TPCRG5 + regChainOffset,
+ SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
+ SM_PDGAIN_B(0, 1) |
+ SM_PDGAIN_B(1, 2) |
+ SM_PDGAIN_B(2, 3) |
+ SM_PDGAIN_B(3, 4));
+ }
+ }
+
+
+ ath9k_adjust_pdadc_values(ah, pwr_table_offset,
+ diff, pdadcValues);
+
+ regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+ for (j = 0; j < 32; j++) {
+ reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
+ ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
+ ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
+ ((pdadcValues[4 * j + 3] & 0xFF) << 24);
+ REG_WRITE(ah, regOffset, reg32);
+
+ DBG2("ath9k: "
+ "PDADC (%d,%4x): %4.4x %8.8x\n",
+ i, regChainOffset, regOffset,
+ reg32);
+ DBG2("ath9k: "
+ "PDADC: Chain %d | PDADC %3d "
+ "Value %3d | PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | PDADC %3d "
+ "Value %3d |\n",
+ i, 4 * j, pdadcValues[4 * j],
+ 4 * j + 1, pdadcValues[4 * j + 1],
+ 4 * j + 2, pdadcValues[4 * j + 2],
+ 4 * j + 3, pdadcValues[4 * j + 3]);
+
+ regOffset += 4;
+ }
+ REGWRITE_BUFFER_FLUSH(ah);
+ }
+ }
+
+ *pTxPowerIndexOffset = 0;
+#undef SM_PD_GAIN
+#undef SM_PDGAIN_B
+}
+
+static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ int16_t *ratesArray,
+ u16 cfgCtl,
+ u16 AntennaReduction,
+ u16 twiceMaxRegulatoryPower,
+ u16 powerLimit)
+{
+#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
+#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */
+
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+ u16 twiceMaxEdgePower = MAX_RATE_POWER;
+ static const u16 tpScaleReductionTable[5] =
+ { 0, 3, 6, 9, MAX_RATE_POWER };
+
+ unsigned int i;
+ int16_t twiceLargestAntenna;
+ struct cal_ctl_data *rep;
+ struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+ 0, { 0, 0, 0, 0}
+ };
+ struct cal_target_power_leg targetPowerOfdmExt = {
+ 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
+ 0, { 0, 0, 0, 0 }
+ };
+ struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+ 0, {0, 0, 0, 0}
+ };
+ u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ static const u16 ctlModesFor11a[] = {
+ CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
+ };
+ static const u16 ctlModesFor11g[] = {
+ CTL_11B, CTL_11G, CTL_2GHT20,
+ CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+ };
+ u16 numCtlModes;
+ const u16 *pCtlMode;
+ u16 ctlMode, freq;
+ struct chan_centers centers;
+ int tx_chainmask;
+ u16 twiceMinEdgePower;
+
+ tx_chainmask = ah->txchainmask;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ twiceLargestAntenna = max(
+ pEepData->modalHeader
+ [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
+ pEepData->modalHeader
+ [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
+
+ twiceLargestAntenna = max((u8)twiceLargestAntenna,
+ pEepData->modalHeader
+ [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
+
+ twiceLargestAntenna = (int16_t)min(AntennaReduction -
+ twiceLargestAntenna, 0);
+
+ maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+
+ if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
+ maxRegAllowedPower -=
+ (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
+ }
+
+ scaledPower = min(powerLimit, maxRegAllowedPower);
+
+ switch (ar5416_get_ntxchains(tx_chainmask)) {
+ case 1:
+ break;
+ case 2:
+ if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
+ scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+ else
+ scaledPower = 0;
+ break;
+ case 3:
+ if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
+ scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+ else
+ scaledPower = 0;
+ break;
+ }
+
+ if (IS_CHAN_2GHZ(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
+ SUB_NUM_CTL_MODES_AT_2G_40;
+ pCtlMode = ctlModesFor11g;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCck, 4, 0);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, 0);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT20,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, 0);
+
+ if (IS_CHAN_HT40(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT40,
+ AR5416_NUM_2G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, 1);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCckExt, 4, 1);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, 1);
+ }
+ } else {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
+ SUB_NUM_CTL_MODES_AT_5G_40;
+ pCtlMode = ctlModesFor11a;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower5G,
+ AR5416_NUM_5G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, 0);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower5GHT20,
+ AR5416_NUM_5G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, 0);
+
+ if (IS_CHAN_HT40(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11a);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower5GHT40,
+ AR5416_NUM_5G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, 1);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower5G,
+ AR5416_NUM_5G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, 1);
+ }
+ }
+
+ for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+ int isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+ (pCtlMode[ctlMode] == CTL_2GHT40);
+ if (isHt40CtlMode)
+ freq = centers.synth_center;
+ else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+ freq = centers.ext_center;
+ else
+ freq = centers.ctl_center;
+
+ if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
+ ah->eep_ops->get_eeprom_rev(ah) <= 2)
+ twiceMaxEdgePower = MAX_RATE_POWER;
+
+ for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
+ if ((((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ pEepData->ctlIndex[i]) ||
+ (((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
+ rep = &(pEepData->ctlData[i]);
+
+ twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
+ rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
+ IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
+
+ if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+ twiceMaxEdgePower = min(twiceMaxEdgePower,
+ twiceMinEdgePower);
+ } else {
+ twiceMaxEdgePower = twiceMinEdgePower;
+ break;
+ }
+ }
+ }
+
+ minCtlPower = min(twiceMaxEdgePower, scaledPower);
+
+ switch (pCtlMode[ctlMode]) {
+ case CTL_11B:
+ for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
+ targetPowerCck.tPow2x[i] =
+ min((u16)targetPowerCck.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11A:
+ case CTL_11G:
+ for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
+ targetPowerOfdm.tPow2x[i] =
+ min((u16)targetPowerOfdm.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_5GHT20:
+ case CTL_2GHT20:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
+ targetPowerHt20.tPow2x[i] =
+ min((u16)targetPowerHt20.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11B_EXT:
+ targetPowerCckExt.tPow2x[0] = min((u16)
+ targetPowerCckExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_11A_EXT:
+ case CTL_11G_EXT:
+ targetPowerOfdmExt.tPow2x[0] = min((u16)
+ targetPowerOfdmExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_5GHT40:
+ case CTL_2GHT40:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ targetPowerHt40.tPow2x[i] =
+ min((u16)targetPowerHt40.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
+ ratesArray[rate18mb] = ratesArray[rate24mb] =
+ targetPowerOfdm.tPow2x[0];
+ ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+ ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+ ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+ ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+ ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+ if (IS_CHAN_2GHZ(chan)) {
+ ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+ ratesArray[rate2s] = ratesArray[rate2l] =
+ targetPowerCck.tPow2x[1];
+ ratesArray[rate5_5s] = ratesArray[rate5_5l] =
+ targetPowerCck.tPow2x[2];
+ ratesArray[rate11s] = ratesArray[rate11l] =
+ targetPowerCck.tPow2x[3];
+ }
+ if (IS_CHAN_HT40(chan)) {
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ ratesArray[rateHt40_0 + i] =
+ targetPowerHt40.tPow2x[i];
+ }
+ ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+ if (IS_CHAN_2GHZ(chan)) {
+ ratesArray[rateExtCck] =
+ targetPowerCckExt.tPow2x[0];
+ }
+ }
+}
+
+static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+ u8 powerLimit, int test)
+{
+#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+ struct modal_eep_header *pModal =
+ &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
+ int16_t ratesArray[Ar5416RateSize];
+ int16_t txPowerIndexOffset = 0;
+ u8 ht40PowerIncForPdadc = 2;
+ unsigned int i, cck_ofdm_delta = 0;
+
+ memset(ratesArray, 0, sizeof(ratesArray));
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+ }
+
+ ath9k_hw_set_def_power_per_rate_table(ah, chan,
+ &ratesArray[0], cfgCtl,
+ twiceAntennaReduction,
+ twiceMaxRegulatoryPower,
+ powerLimit);
+
+ ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
+
+ regulatory->max_power_level = 0;
+ for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+ ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+ if (ratesArray[i] > MAX_RATE_POWER)
+ ratesArray[i] = MAX_RATE_POWER;
+ if (ratesArray[i] > regulatory->max_power_level)
+ regulatory->max_power_level = ratesArray[i];
+ }
+
+ if (!test) {
+ i = rate6mb;
+
+ if (IS_CHAN_HT40(chan))
+ i = rateHt40_0;
+ else if (IS_CHAN_HT20(chan))
+ i = rateHt20_0;
+
+ regulatory->max_power_level = ratesArray[i];
+ }
+
+ switch(ar5416_get_ntxchains(ah->txchainmask)) {
+ case 1:
+ break;
+ case 2:
+ regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
+ break;
+ case 3:
+ regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
+ break;
+ default:
+ DBG2("ath9k: "
+ "Invalid chainmask configuration\n");
+ break;
+ }
+
+ if (test)
+ return;
+
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ for (i = 0; i < Ar5416RateSize; i++) {
+ int8_t pwr_table_offset;
+
+ pwr_table_offset = ah->eep_ops->get_eeprom(ah,
+ EEP_PWR_TABLE_OFFSET);
+ ratesArray[i] -= pwr_table_offset * 2;
+ }
+ }
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+ ATH9K_POW_SM(ratesArray[rate18mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+ ATH9K_POW_SM(ratesArray[rate54mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+ if (IS_CHAN_2GHZ(chan)) {
+ if (OLC_FOR_AR9280_20_LATER) {
+ cck_ofdm_delta = 2;
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+ ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
+ | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
+ | ATH9K_POW_SM(ratesArray[rateXr], 8)
+ | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+ ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
+ | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
+ | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
+ | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
+ } else {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+ ATH9K_POW_SM(ratesArray[rate2s], 24)
+ | ATH9K_POW_SM(ratesArray[rate2l], 16)
+ | ATH9K_POW_SM(ratesArray[rateXr], 8)
+ | ATH9K_POW_SM(ratesArray[rate1l], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+ ATH9K_POW_SM(ratesArray[rate11s], 24)
+ | ATH9K_POW_SM(ratesArray[rate11l], 16)
+ | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+ | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+ }
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+ ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+ ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+ if (IS_CHAN_HT40(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+ ATH9K_POW_SM(ratesArray[rateHt40_3] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+ ht40PowerIncForPdadc, 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+ ATH9K_POW_SM(ratesArray[rateHt40_7] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+ ht40PowerIncForPdadc, 0));
+ if (OLC_FOR_AR9280_20_LATER) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+ | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
+ | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+ | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
+ } else {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+ | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+ | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+ | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+ }
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
+ ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
+ | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
+
+ REGWRITE_BUFFER_FLUSH(ah);
+}
+
+static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, int is2GHz)
+{
+#define EEP_DEF_SPURCHAN \
+ (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
+
+ u16 spur_val = AR_NO_SPUR;
+
+ DBG2("ath9k: "
+ "Getting spur idx:%d is2Ghz:%d val:%x\n",
+ i, is2GHz, ah->config.spurchans[i][is2GHz]);
+
+ switch (ah->config.spurmode) {
+ case SPUR_DISABLE:
+ break;
+ case SPUR_ENABLE_IOCTL:
+ spur_val = ah->config.spurchans[i][is2GHz];
+ DBG2("ath9k: "
+ "Getting spur val from new loc. %d\n", spur_val);
+ break;
+ case SPUR_ENABLE_EEPROM:
+ spur_val = EEP_DEF_SPURCHAN;
+ break;
+ }
+
+ return spur_val;
+
+#undef EEP_DEF_SPURCHAN
+}
+
+const struct eeprom_ops eep_def_ops = {
+ .check_eeprom = ath9k_hw_def_check_eeprom,
+ .get_eeprom = ath9k_hw_def_get_eeprom,
+ .fill_eeprom = ath9k_hw_def_fill_eeprom,
+ .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver,
+ .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev,
+ .set_board_values = ath9k_hw_def_set_board_values,
+ .set_addac = ath9k_hw_def_set_addac,
+ .set_txpower = ath9k_hw_def_set_txpower,
+ .get_spur_channel = ath9k_hw_def_get_spur_channel
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_hw.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_hw.c
new file mode 100644
index 00000000..554e9be3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_hw.c
@@ -0,0 +1,2067 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/vsprintf.h>
+#include <ipxe/io.h>
+
+#include "hw.h"
+#include "hw-ops.h"
+#include "ar9003_mac.h"
+
+static int ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
+
+/* Private hardware callbacks */
+
+static void ath9k_hw_init_cal_settings(struct ath_hw *ah)
+{
+ ath9k_hw_private_ops(ah)->init_cal_settings(ah);
+}
+
+static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
+{
+ ath9k_hw_private_ops(ah)->init_mode_regs(ah);
+}
+
+static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ return ath9k_hw_private_ops(ah)->compute_pll_control(ah, chan);
+}
+
+static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
+{
+ if (!ath9k_hw_private_ops(ah)->init_mode_gain_regs)
+ return;
+
+ ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah);
+}
+
+static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah)
+{
+ /* You will not have this callback if using the old ANI */
+ if (!ath9k_hw_private_ops(ah)->ani_cache_ini_regs)
+ return;
+
+ ath9k_hw_private_ops(ah)->ani_cache_ini_regs(ah);
+}
+
+/********************/
+/* Helper Functions */
+/********************/
+
+static void ath9k_hw_set_clockrate(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct net80211_device *dev = common->dev;
+ unsigned int clockrate;
+
+ if (!ah->curchan) /* should really check for CCK instead */
+ clockrate = ATH9K_CLOCK_RATE_CCK;
+ else if ((dev->channels + dev->channel)->band == NET80211_BAND_2GHZ)
+ clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
+ else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
+ clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
+ else
+ clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
+
+ common->clockrate = clockrate;
+}
+
+static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ return usecs * common->clockrate;
+}
+
+int ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
+{
+ unsigned int i;
+
+ for (i = 0; i < (timeout / AH_TIME_QUANTUM); i++) {
+ if ((REG_READ(ah, reg) & mask) == val)
+ return 1;
+
+ udelay(AH_TIME_QUANTUM);
+ }
+
+ DBG("ath9k: "
+ "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
+ timeout, reg, REG_READ(ah, reg), mask, val);
+
+ return 0;
+}
+
+void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array,
+ int column, unsigned int *writecnt)
+{
+ unsigned int r;
+
+ ENABLE_REGWRITE_BUFFER(ah);
+ for (r = 0; r < array->ia_rows; r++) {
+ REG_WRITE(ah, INI_RA(array, r, 0),
+ INI_RA(array, r, column));
+ DO_DELAY(*writecnt);
+ }
+ REGWRITE_BUFFER_FLUSH(ah);
+}
+
+u32 ath9k_hw_reverse_bits(u32 val, u32 n)
+{
+ u32 retval;
+ unsigned int i;
+
+ for (i = 0, retval = 0; i < n; i++) {
+ retval = (retval << 1) | (val & 1);
+ val >>= 1;
+ }
+ return retval;
+}
+
+u16 ath9k_hw_computetxtime(struct ath_hw *ah,
+ u8 phy, int kbps,
+ u32 frameLen, u16 rateix,
+ int shortPreamble)
+{
+ u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
+
+ if (kbps == 0)
+ return 0;
+
+ switch (phy) {
+ case CHANNEL_CCK:
+ phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
+ if (shortPreamble)
+ phyTime >>= 1;
+ numBits = frameLen << 3;
+ txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps);
+ break;
+ case CHANNEL_OFDM:
+ if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) {
+ bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
+ numBits = OFDM_PLCP_BITS + (frameLen << 3);
+ numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+ txTime = OFDM_SIFS_TIME_QUARTER
+ + OFDM_PREAMBLE_TIME_QUARTER
+ + (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
+ } else if (ah->curchan &&
+ IS_CHAN_HALF_RATE(ah->curchan)) {
+ bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
+ numBits = OFDM_PLCP_BITS + (frameLen << 3);
+ numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+ txTime = OFDM_SIFS_TIME_HALF +
+ OFDM_PREAMBLE_TIME_HALF
+ + (numSymbols * OFDM_SYMBOL_TIME_HALF);
+ } else {
+ bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
+ numBits = OFDM_PLCP_BITS + (frameLen << 3);
+ numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+ txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
+ + (numSymbols * OFDM_SYMBOL_TIME);
+ }
+ break;
+ default:
+ DBG("ath9k: "
+ "Unknown phy %d (rate ix %d)\n", phy, rateix);
+ txTime = 0;
+ break;
+ }
+
+ return txTime;
+}
+
+void ath9k_hw_get_channel_centers(struct ath_hw *ah __unused,
+ struct ath9k_channel *chan,
+ struct chan_centers *centers)
+{
+ int8_t extoff;
+
+ if (!IS_CHAN_HT40(chan)) {
+ centers->ctl_center = centers->ext_center =
+ centers->synth_center = chan->channel;
+ return;
+ }
+
+ if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+ (chan->chanmode == CHANNEL_G_HT40PLUS)) {
+ centers->synth_center =
+ chan->channel + HT40_CHANNEL_CENTER_SHIFT;
+ extoff = 1;
+ } else {
+ centers->synth_center =
+ chan->channel - HT40_CHANNEL_CENTER_SHIFT;
+ extoff = -1;
+ }
+
+ centers->ctl_center =
+ centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT);
+ /* 25 MHz spacing is supported by hw but not on upper layers */
+ centers->ext_center =
+ centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
+}
+
+/******************/
+/* Chip Revisions */
+/******************/
+
+static void ath9k_hw_read_revisions(struct ath_hw *ah)
+{
+ u32 val;
+
+ switch (ah->hw_version.devid) {
+ case AR5416_AR9100_DEVID:
+ ah->hw_version.macVersion = AR_SREV_VERSION_9100;
+ break;
+ case AR9300_DEVID_AR9340:
+ ah->hw_version.macVersion = AR_SREV_VERSION_9340;
+ val = REG_READ(ah, AR_SREV);
+ ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
+ return;
+ }
+
+ val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
+
+ if (val == 0xFF) {
+ val = REG_READ(ah, AR_SREV);
+ ah->hw_version.macVersion =
+ (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
+ ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
+ ah->is_pciexpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
+ } else {
+ if (!AR_SREV_9100(ah))
+ ah->hw_version.macVersion = MS(val, AR_SREV_VERSION);
+
+ ah->hw_version.macRev = val & AR_SREV_REVISION;
+
+ if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)
+ ah->is_pciexpress = 1;
+ }
+}
+
+/************************************/
+/* HW Attach, Detach, Init Routines */
+/************************************/
+
+static void ath9k_hw_disablepcie(struct ath_hw *ah)
+{
+ if (!AR_SREV_5416(ah))
+ return;
+
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
+
+ REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+}
+
+/* This should work for all families including legacy */
+static int ath9k_hw_chip_test(struct ath_hw *ah)
+{
+ u32 regAddr[2] = { AR_STA_ID0 };
+ u32 regHold[2];
+ static const u32 patternData[4] = {
+ 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999
+ };
+ int i, j, loop_max;
+
+ if (!AR_SREV_9300_20_OR_LATER(ah)) {
+ loop_max = 2;
+ regAddr[1] = AR_PHY_BASE + (8 << 2);
+ } else
+ loop_max = 1;
+
+ for (i = 0; i < loop_max; i++) {
+ u32 addr = regAddr[i];
+ u32 wrData, rdData;
+
+ regHold[i] = REG_READ(ah, addr);
+ for (j = 0; j < 0x100; j++) {
+ wrData = (j << 16) | j;
+ REG_WRITE(ah, addr, wrData);
+ rdData = REG_READ(ah, addr);
+ if (rdData != wrData) {
+ DBG("ath9k: "
+ "address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+ addr, wrData, rdData);
+ return 0;
+ }
+ }
+ for (j = 0; j < 4; j++) {
+ wrData = patternData[j];
+ REG_WRITE(ah, addr, wrData);
+ rdData = REG_READ(ah, addr);
+ if (wrData != rdData) {
+ DBG("ath9k: "
+ "address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+ addr, wrData, rdData);
+ return 0;
+ }
+ }
+ REG_WRITE(ah, regAddr[i], regHold[i]);
+ }
+ udelay(100);
+
+ return 1;
+}
+
+static void ath9k_hw_init_config(struct ath_hw *ah)
+{
+ int i;
+
+ ah->config.dma_beacon_response_time = 2;
+ ah->config.sw_beacon_response_time = 10;
+ ah->config.additional_swba_backoff = 0;
+ ah->config.ack_6mb = 0x0;
+ ah->config.cwm_ignore_extcca = 0;
+ ah->config.pcie_powersave_enable = 0;
+ ah->config.pcie_clock_req = 0;
+ ah->config.pcie_waen = 0;
+ ah->config.analog_shiftreg = 1;
+ ah->config.enable_ani = 1;
+
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ ah->config.spurchans[i][0] = AR_NO_SPUR;
+ ah->config.spurchans[i][1] = AR_NO_SPUR;
+ }
+
+ /* PAPRD needs some more work to be enabled */
+ ah->config.paprd_disable = 1;
+
+ ah->config.rx_intr_mitigation = 1;
+ ah->config.pcieSerDesWrite = 1;
+}
+
+static void ath9k_hw_init_defaults(struct ath_hw *ah)
+{
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+
+ regulatory->country_code = CTRY_DEFAULT;
+ regulatory->power_limit = MAX_RATE_POWER;
+ regulatory->tp_scale = ATH9K_TP_SCALE_MAX;
+
+ ah->hw_version.magic = AR5416_MAGIC;
+ ah->hw_version.subvendorid = 0;
+
+ ah->atim_window = 0;
+ ah->sta_id1_defaults =
+ AR_STA_ID1_CRPT_MIC_ENABLE |
+ AR_STA_ID1_MCAST_KSRCH;
+ if (AR_SREV_9100(ah))
+ ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX;
+ ah->enable_32kHz_clock = DONT_USE_32KHZ;
+ ah->slottime = 20;
+ ah->globaltxtimeout = (u32) -1;
+ ah->power_mode = ATH9K_PM_UNDEFINED;
+}
+
+static int ath9k_hw_init_macaddr(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ u32 sum;
+ int i;
+ u16 eeval;
+ static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
+
+ sum = 0;
+ for (i = 0; i < 3; i++) {
+ eeval = ah->eep_ops->get_eeprom(ah, EEP_MAC[i]);
+ sum += eeval;
+ common->macaddr[2 * i] = eeval >> 8;
+ common->macaddr[2 * i + 1] = eeval & 0xff;
+ }
+ if (sum == 0 || sum == 0xffff * 3)
+ return -EADDRNOTAVAIL;
+
+ return 0;
+}
+
+static int ath9k_hw_post_init(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ int ecode;
+
+ if (common->bus_ops->ath_bus_type != ATH_USB) {
+ if (!ath9k_hw_chip_test(ah))
+ return -ENODEV;
+ }
+
+ if (!AR_SREV_9300_20_OR_LATER(ah)) {
+ ecode = ar9002_hw_rf_claim(ah);
+ if (ecode != 0)
+ return ecode;
+ }
+
+ ecode = ath9k_hw_eeprom_init(ah);
+ if (ecode != 0)
+ return ecode;
+
+ DBG("ath9k: "
+ "Eeprom VER: %d, REV: %d\n",
+ ah->eep_ops->get_eeprom_ver(ah),
+ ah->eep_ops->get_eeprom_rev(ah));
+
+ ecode = ath9k_hw_rf_alloc_ext_banks(ah);
+ if (ecode) {
+ DBG("ath9k: "
+ "Failed allocating banks for external radio\n");
+ ath9k_hw_rf_free_ext_banks(ah);
+ return ecode;
+ }
+
+ if (!AR_SREV_9100(ah) && !AR_SREV_9340(ah)) {
+ ath9k_hw_ani_setup(ah);
+ ath9k_hw_ani_init(ah);
+ }
+
+ return 0;
+}
+
+static void ath9k_hw_attach_ops(struct ath_hw *ah)
+{
+ if (AR_SREV_9300_20_OR_LATER(ah))
+ ar9003_hw_attach_ops(ah);
+ else
+ ar9002_hw_attach_ops(ah);
+}
+
+/* Called for all hardware families */
+static int __ath9k_hw_init(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ int r = 0;
+
+ ath9k_hw_read_revisions(ah);
+
+ /*
+ * Read back AR_WA into a permanent copy and set bits 14 and 17.
+ * We need to do this to avoid RMW of this register. We cannot
+ * read the reg when chip is asleep.
+ */
+ ah->WARegVal = REG_READ(ah, AR_WA);
+ ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
+ AR_WA_ASPM_TIMER_BASED_DISABLE);
+
+ if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
+ DBG("ath9k: Couldn't reset chip\n");
+ return -EIO;
+ }
+
+ ath9k_hw_init_defaults(ah);
+ ath9k_hw_init_config(ah);
+
+ ath9k_hw_attach_ops(ah);
+
+ if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
+ DBG("ath9k: Couldn't wakeup chip\n");
+ return -EIO;
+ }
+
+ if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
+ if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
+ ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) &&
+ !ah->is_pciexpress)) {
+ ah->config.serialize_regmode =
+ SER_REG_MODE_ON;
+ } else {
+ ah->config.serialize_regmode =
+ SER_REG_MODE_OFF;
+ }
+ }
+
+ DBG2("ath9k: serialize_regmode is %d\n",
+ ah->config.serialize_regmode);
+
+ if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+ ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1;
+ else
+ ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD;
+
+ switch (ah->hw_version.macVersion) {
+ case AR_SREV_VERSION_5416_PCI:
+ case AR_SREV_VERSION_5416_PCIE:
+ case AR_SREV_VERSION_9160:
+ case AR_SREV_VERSION_9100:
+ case AR_SREV_VERSION_9280:
+ case AR_SREV_VERSION_9285:
+ case AR_SREV_VERSION_9287:
+ case AR_SREV_VERSION_9271:
+ case AR_SREV_VERSION_9300:
+ case AR_SREV_VERSION_9485:
+ case AR_SREV_VERSION_9340:
+ break;
+ default:
+ DBG("ath9k: "
+ "Mac Chip Rev 0x%02x.%x is not supported by this driver\n",
+ ah->hw_version.macVersion, ah->hw_version.macRev);
+ return -EOPNOTSUPP;
+ }
+
+ if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah))
+ ah->is_pciexpress = 0;
+
+ ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
+ ath9k_hw_init_cal_settings(ah);
+
+ ah->ani_function = ATH9K_ANI_ALL;
+ if (AR_SREV_9280_20_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah))
+ ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
+ if (!AR_SREV_9300_20_OR_LATER(ah))
+ ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
+
+ ath9k_hw_init_mode_regs(ah);
+
+
+ if (ah->is_pciexpress)
+ ath9k_hw_configpcipowersave(ah, 0, 0);
+ else
+ ath9k_hw_disablepcie(ah);
+
+ if (!AR_SREV_9300_20_OR_LATER(ah))
+ ar9002_hw_cck_chan14_spread(ah);
+
+ r = ath9k_hw_post_init(ah);
+ if (r)
+ return r;
+
+ ath9k_hw_init_mode_gain_regs(ah);
+ r = ath9k_hw_fill_cap_info(ah);
+ if (r)
+ return r;
+
+ r = ath9k_hw_init_macaddr(ah);
+ if (r) {
+ DBG("ath9k: Failed to initialize MAC address\n");
+ return r;
+ }
+
+ if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+ ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S);
+ else
+ ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
+
+ common->state = ATH_HW_INITIALIZED;
+
+ return 0;
+}
+
+int ath9k_hw_init(struct ath_hw *ah)
+{
+ int ret;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ /* These are all the AR5008/AR9001/AR9002 hardware family of chipsets */
+ switch (ah->hw_version.devid) {
+ case AR5416_DEVID_PCI:
+ case AR5416_DEVID_PCIE:
+ case AR5416_AR9100_DEVID:
+ case AR9160_DEVID_PCI:
+ case AR9280_DEVID_PCI:
+ case AR9280_DEVID_PCIE:
+ case AR9285_DEVID_PCIE:
+ case AR9287_DEVID_PCI:
+ case AR9287_DEVID_PCIE:
+ case AR2427_DEVID_PCIE:
+ case AR9300_DEVID_PCIE:
+ case AR9300_DEVID_AR9485_PCIE:
+ case AR9300_DEVID_AR9340:
+ break;
+ default:
+ if (common->bus_ops->ath_bus_type == ATH_USB)
+ break;
+ DBG("ath9k: Hardware device ID 0x%04x not supported\n",
+ ah->hw_version.devid);
+ return -EOPNOTSUPP;
+ }
+
+ ret = __ath9k_hw_init(ah);
+ if (ret) {
+ DBG("ath9k: "
+ "Unable to initialize hardware; initialization status: %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah)
+{
+ REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK);
+ udelay(100);
+ REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK);
+
+ while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0)
+ udelay(100);
+
+ return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3;
+}
+
+static void ath9k_hw_init_pll(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ u32 pll;
+
+ if (AR_SREV_9485(ah)) {
+
+ /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+ AR_CH0_BB_DPLL2_PLL_PWD, 0x1);
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+ AR_CH0_DPLL2_KD, 0x40);
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+ AR_CH0_DPLL2_KI, 0x4);
+
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1,
+ AR_CH0_BB_DPLL1_REFDIV, 0x5);
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1,
+ AR_CH0_BB_DPLL1_NINI, 0x58);
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1,
+ AR_CH0_BB_DPLL1_NFRAC, 0x0);
+
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+ AR_CH0_BB_DPLL2_OUTDIV, 0x1);
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+ AR_CH0_BB_DPLL2_LOCAL_PLL, 0x1);
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+ AR_CH0_BB_DPLL2_EN_NEGTRIG, 0x1);
+
+ /* program BB PLL phase_shift to 0x6 */
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
+ AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x6);
+
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+ AR_CH0_BB_DPLL2_PLL_PWD, 0x0);
+ udelay(1000);
+ } else if (AR_SREV_9340(ah)) {
+ u32 regval, pll2_divint, pll2_divfrac, refdiv;
+
+ REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+ udelay(1000);
+
+ REG_SET_BIT(ah, AR_PHY_PLL_MODE, 0x1 << 16);
+ udelay(100);
+
+ if (ah->is_clk_25mhz) {
+ pll2_divint = 0x54;
+ pll2_divfrac = 0x1eb85;
+ refdiv = 3;
+ } else {
+ pll2_divint = 88;
+ pll2_divfrac = 0;
+ refdiv = 5;
+ }
+
+ regval = REG_READ(ah, AR_PHY_PLL_MODE);
+ regval |= (0x1 << 16);
+ REG_WRITE(ah, AR_PHY_PLL_MODE, regval);
+ udelay(100);
+
+ REG_WRITE(ah, AR_PHY_PLL_CONTROL, (refdiv << 27) |
+ (pll2_divint << 18) | pll2_divfrac);
+ udelay(100);
+
+ regval = REG_READ(ah, AR_PHY_PLL_MODE);
+ regval = (regval & 0x80071fff) | (0x1 << 30) | (0x1 << 13) |
+ (0x4 << 26) | (0x18 << 19);
+ REG_WRITE(ah, AR_PHY_PLL_MODE, regval);
+ REG_WRITE(ah, AR_PHY_PLL_MODE,
+ REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff);
+ udelay(1000);
+ }
+
+ pll = ath9k_hw_compute_pll_control(ah, chan);
+
+ REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
+
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ udelay(1000);
+
+ /* Switch the core clock for ar9271 to 117Mhz */
+ if (AR_SREV_9271(ah)) {
+ udelay(500);
+ REG_WRITE(ah, 0x50040, 0x304);
+ }
+
+ udelay(RTC_PLL_SETTLE_DELAY);
+
+ REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
+
+ if (AR_SREV_9340(ah)) {
+ if (ah->is_clk_25mhz) {
+ REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1);
+ REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
+ REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae);
+ } else {
+ REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1);
+ REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400);
+ REG_WRITE(ah, AR_SLP32_INC, 0x0001e800);
+ }
+ udelay(100);
+ }
+}
+
+static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah)
+{
+ u32 sync_default = AR_INTR_SYNC_DEFAULT;
+ u32 imr_reg = AR_IMR_TXERR |
+ AR_IMR_TXURN |
+ AR_IMR_RXERR |
+ AR_IMR_RXORN;;
+
+ if (AR_SREV_9340(ah))
+ sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
+
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ imr_reg |= AR_IMR_RXOK_HP;
+ if (ah->config.rx_intr_mitigation)
+ imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
+ else
+ imr_reg |= AR_IMR_RXOK_LP;
+
+ } else {
+ if (ah->config.rx_intr_mitigation)
+ imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
+ else
+ imr_reg |= AR_IMR_RXOK;
+ }
+
+ if (ah->config.tx_intr_mitigation)
+ imr_reg |= AR_IMR_TXINTM | AR_IMR_TXMINTR;
+ else
+ imr_reg |= AR_IMR_TXOK;
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_IMR, imr_reg);
+// ah->imrs2_reg |= AR_IMR_S2_GTT;
+ REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
+
+ if (!AR_SREV_9100(ah)) {
+ REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default);
+ REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
+ }
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0);
+ REG_WRITE(ah, AR_INTR_PRIO_ASYNC_MASK, 0);
+ REG_WRITE(ah, AR_INTR_PRIO_SYNC_ENABLE, 0);
+ REG_WRITE(ah, AR_INTR_PRIO_SYNC_MASK, 0);
+ }
+}
+
+static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
+{
+ u32 val = ath9k_hw_mac_to_clks(ah, us);
+ val = min(val, (u32) 0xFFFF);
+ REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val);
+}
+
+static void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
+{
+ u32 val = ath9k_hw_mac_to_clks(ah, us);
+ val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK));
+ REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val);
+}
+
+static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
+{
+ u32 val = ath9k_hw_mac_to_clks(ah, us);
+ val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS));
+ REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, val);
+}
+
+static int ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
+{
+ if (tu > 0xFFFF) {
+ DBG("ath9k: "
+ "bad global tx timeout %d\n", tu);
+ ah->globaltxtimeout = (u32) -1;
+ return 0;
+ } else {
+ REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
+ ah->globaltxtimeout = tu;
+ return 1;
+ }
+}
+
+void ath9k_hw_init_global_settings(struct ath_hw *ah)
+{
+ int acktimeout;
+ int slottime;
+ int sifstime;
+
+ DBG2("ath9k: ah->misc_mode 0x%x\n",
+ ah->misc_mode);
+
+ if (ah->misc_mode != 0)
+ REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
+
+ if ((ah->dev->channels + ah->dev->channel)->band == NET80211_BAND_5GHZ)
+ sifstime = 16;
+ else
+ sifstime = 10;
+
+ /* As defined by IEEE 802.11-2007 17.3.8.6 */
+ slottime = ah->slottime + 3 * ah->coverage_class;
+ acktimeout = slottime + sifstime;
+
+ /*
+ * Workaround for early ACK timeouts, add an offset to match the
+ * initval's 64us ack timeout value.
+ * This was initially only meant to work around an issue with delayed
+ * BA frames in some implementations, but it has been found to fix ACK
+ * timeout issues in other cases as well.
+ */
+ if ((ah->dev->channels + ah->dev->channel)->band == NET80211_BAND_2GHZ)
+ acktimeout += 64 - sifstime - ah->slottime;
+
+ ath9k_hw_setslottime(ah, ah->slottime);
+ ath9k_hw_set_ack_timeout(ah, acktimeout);
+ ath9k_hw_set_cts_timeout(ah, acktimeout);
+ if (ah->globaltxtimeout != (u32) -1)
+ ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
+}
+
+void ath9k_hw_deinit(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (common->state < ATH_HW_INITIALIZED)
+ goto free_hw;
+
+ ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
+
+free_hw:
+ ath9k_hw_rf_free_ext_banks(ah);
+}
+
+/*******/
+/* INI */
+/*******/
+
+u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan)
+{
+ u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band);
+
+ if (IS_CHAN_B(chan))
+ ctl |= CTL_11B;
+ else if (IS_CHAN_G(chan))
+ ctl |= CTL_11G;
+ else
+ ctl |= CTL_11A;
+
+ return ctl;
+}
+
+/****************************************/
+/* Reset and Channel Switching Routines */
+/****************************************/
+
+static inline void ath9k_hw_set_dma(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ /*
+ * set AHB_MODE not to do cacheline prefetches
+ */
+ if (!AR_SREV_9300_20_OR_LATER(ah))
+ REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN);
+
+ /*
+ * let mac dma reads be in 128 byte chunks
+ */
+ REG_RMW(ah, AR_TXCFG, AR_TXCFG_DMASZ_128B, AR_TXCFG_DMASZ_MASK);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ /*
+ * Restore TX Trigger Level to its pre-reset value.
+ * The initial value depends on whether aggregation is enabled, and is
+ * adjusted whenever underruns are detected.
+ */
+ if (!AR_SREV_9300_20_OR_LATER(ah))
+ REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ /*
+ * let mac dma writes be in 128 byte chunks
+ */
+ REG_RMW(ah, AR_RXCFG, AR_RXCFG_DMASZ_128B, AR_RXCFG_DMASZ_MASK);
+
+ /*
+ * Setup receive FIFO threshold to hold off TX activities
+ */
+ REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
+
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_HP, 0x1);
+ REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_LP, 0x1);
+
+ ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize -
+ ah->caps.rx_status_len);
+ }
+
+ /*
+ * reduce the number of usable entries in PCU TXBUF to avoid
+ * wrap around issues.
+ */
+ if (AR_SREV_9285(ah)) {
+ /* For AR9285 the number of Fifos are reduced to half.
+ * So set the usable tx buf size also to half to
+ * avoid data/delimiter underruns
+ */
+ REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
+ AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
+ } else if (!AR_SREV_9271(ah)) {
+ REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
+ AR_PCU_TXBUF_CTRL_USABLE_SIZE);
+ }
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ if (AR_SREV_9300_20_OR_LATER(ah))
+ ath9k_hw_reset_txstatus_ring(ah);
+}
+
+static void ath9k_hw_set_operating_mode(struct ath_hw *ah)
+{
+ u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC;
+ u32 set = AR_STA_ID1_KSRCH_MODE;
+
+ REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+
+ REG_RMW(ah, AR_STA_ID1, set, mask);
+}
+
+void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah __unused, u32 coef_scaled,
+ u32 *coef_mantissa, u32 *coef_exponent)
+{
+ u32 coef_exp, coef_man;
+
+ for (coef_exp = 31; coef_exp > 0; coef_exp--)
+ if ((coef_scaled >> coef_exp) & 0x1)
+ break;
+
+ coef_exp = 14 - (coef_exp - COEF_SCALE_S);
+
+ coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
+
+ *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp);
+ *coef_exponent = coef_exp - 16;
+}
+
+static int ath9k_hw_set_reset(struct ath_hw *ah, int type)
+{
+ u32 rst_flags;
+ u32 tmpReg;
+
+ if (AR_SREV_9100(ah)) {
+ REG_RMW_FIELD(ah, AR_RTC_DERIVED_CLK,
+ AR_RTC_DERIVED_CLK_PERIOD, 1);
+ (void)REG_READ(ah, AR_RTC_DERIVED_CLK);
+ }
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ REG_WRITE(ah, AR_WA, ah->WARegVal);
+ udelay(10);
+ }
+
+ REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
+ AR_RTC_FORCE_WAKE_ON_INT);
+
+ if (AR_SREV_9100(ah)) {
+ rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD |
+ AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
+ } else {
+ tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
+ if (tmpReg &
+ (AR_INTR_SYNC_LOCAL_TIMEOUT |
+ AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
+ u32 val;
+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+
+ val = AR_RC_HOSTIF;
+ if (!AR_SREV_9300_20_OR_LATER(ah))
+ val |= AR_RC_AHB;
+ REG_WRITE(ah, AR_RC, val);
+
+ } else if (!AR_SREV_9300_20_OR_LATER(ah))
+ REG_WRITE(ah, AR_RC, AR_RC_AHB);
+
+ rst_flags = AR_RTC_RC_MAC_WARM;
+ if (type == ATH9K_RESET_COLD)
+ rst_flags |= AR_RTC_RC_MAC_COLD;
+ }
+
+ REG_WRITE(ah, AR_RTC_RC, rst_flags);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ udelay(50);
+
+ REG_WRITE(ah, AR_RTC_RC, 0);
+ if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) {
+ DBG("ath9k: "
+ "RTC stuck in MAC reset\n");
+ return 0;
+ }
+
+ if (!AR_SREV_9100(ah))
+ REG_WRITE(ah, AR_RC, 0);
+
+ if (AR_SREV_9100(ah))
+ udelay(50);
+
+ return 1;
+}
+
+static int ath9k_hw_set_reset_power_on(struct ath_hw *ah)
+{
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ REG_WRITE(ah, AR_WA, ah->WARegVal);
+ udelay(10);
+ }
+
+ REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
+ AR_RTC_FORCE_WAKE_ON_INT);
+
+ if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
+ REG_WRITE(ah, AR_RC, AR_RC_AHB);
+
+ REG_WRITE(ah, AR_RTC_RESET, 0);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ if (!AR_SREV_9300_20_OR_LATER(ah))
+ udelay(2);
+
+ if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
+ REG_WRITE(ah, AR_RC, 0);
+
+ REG_WRITE(ah, AR_RTC_RESET, 1);
+
+ if (!ath9k_hw_wait(ah,
+ AR_RTC_STATUS,
+ AR_RTC_STATUS_M,
+ AR_RTC_STATUS_ON,
+ AH_WAIT_TIMEOUT)) {
+ DBG("ath9k: "
+ "RTC not waking up\n");
+ return 0;
+ }
+
+ return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
+}
+
+static int ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
+{
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ REG_WRITE(ah, AR_WA, ah->WARegVal);
+ udelay(10);
+ }
+
+ REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+ switch (type) {
+ case ATH9K_RESET_POWER_ON:
+ return ath9k_hw_set_reset_power_on(ah);
+ case ATH9K_RESET_WARM:
+ case ATH9K_RESET_COLD:
+ return ath9k_hw_set_reset(ah, type);
+ default:
+ return 0;
+ }
+}
+
+static int ath9k_hw_chip_reset(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) {
+ if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
+ return 0;
+ } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
+ return 0;
+
+ if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+ return 0;
+
+ ah->chip_fullsleep = 0;
+ ath9k_hw_init_pll(ah, chan);
+ ath9k_hw_set_rfmode(ah, chan);
+
+ return 1;
+}
+
+static int ath9k_hw_channel_change(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct net80211_channel *channel = chan->chan;
+ u32 qnum;
+ int r;
+
+ for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
+ if (ath9k_hw_numtxpending(ah, qnum)) {
+ DBG("ath9k: "
+ "Transmit frames pending on queue %d\n", qnum);
+ return 0;
+ }
+ }
+
+ if (!ath9k_hw_rfbus_req(ah)) {
+ DBG("ath9k: Could not kill baseband RX\n");
+ return 0;
+ }
+
+ ath9k_hw_set_channel_regs(ah, chan);
+
+ r = ath9k_hw_rf_set_freq(ah, chan);
+ if (r) {
+ DBG("ath9k: Failed to set channel\n");
+ return 0;
+ }
+ ath9k_hw_set_clockrate(ah);
+
+ ah->eep_ops->set_txpower(ah, chan,
+ ath9k_regd_get_ctl(regulatory, chan),
+ 0,
+ channel->maxpower * 2,
+ min((u32) MAX_RATE_POWER,
+ (u32) regulatory->power_limit), 0);
+
+ ath9k_hw_rfbus_done(ah);
+
+ if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
+ ath9k_hw_set_delta_slope(ah, chan);
+
+ ath9k_hw_spur_mitigate_freq(ah, chan);
+
+ return 1;
+}
+
+static void ath9k_hw_apply_gpio_override(struct ath_hw *ah)
+{
+ u32 gpio_mask = ah->gpio_mask;
+ int i;
+
+ for (i = 0; gpio_mask; i++, gpio_mask >>= 1) {
+ if (!(gpio_mask & 1))
+ continue;
+
+ ath9k_hw_cfg_output(ah, i, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+ ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i)));
+ }
+}
+
+int ath9k_hw_check_alive(struct ath_hw *ah)
+{
+ int count = 50;
+ u32 reg;
+
+ if (AR_SREV_9285_12_OR_LATER(ah))
+ return 1;
+
+ do {
+ reg = REG_READ(ah, AR_OBS_BUS_1);
+
+ if ((reg & 0x7E7FFFEF) == 0x00702400)
+ continue;
+
+ switch (reg & 0x7E000B00) {
+ case 0x1E000000:
+ case 0x52000B00:
+ case 0x18000B00:
+ continue;
+ default:
+ return 1;
+ }
+ } while (count-- > 0);
+
+ return 0;
+}
+
+int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+ struct ath9k_hw_cal_data *caldata, int bChannelChange)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ u32 saveLedState;
+ struct ath9k_channel *curchan = ah->curchan;
+ u32 saveDefAntenna;
+ u32 macStaId1;
+ int i, r;
+
+ ah->txchainmask = common->tx_chainmask;
+ ah->rxchainmask = common->rx_chainmask;
+
+ if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+ return -EIO;
+
+ if (curchan && !ah->chip_fullsleep)
+ ath9k_hw_getnf(ah, curchan);
+
+ ah->caldata = caldata;
+ if (caldata &&
+ (chan->channel != caldata->channel ||
+ (chan->channelFlags & ~CHANNEL_CW_INT) !=
+ (caldata->channelFlags & ~CHANNEL_CW_INT))) {
+ /* Operating channel changed, reset channel calibration data */
+ memset(caldata, 0, sizeof(*caldata));
+ ath9k_init_nfcal_hist_buffer(ah, chan);
+ }
+
+ if (bChannelChange &&
+ (ah->chip_fullsleep != 1) &&
+ (ah->curchan != NULL) &&
+ (chan->channel != ah->curchan->channel) &&
+ ((chan->channelFlags & CHANNEL_ALL) ==
+ (ah->curchan->channelFlags & CHANNEL_ALL)) &&
+ (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) {
+
+ if (ath9k_hw_channel_change(ah, chan)) {
+ ath9k_hw_loadnf(ah, ah->curchan);
+ ath9k_hw_start_nfcal(ah, 1);
+ if (AR_SREV_9271(ah))
+ ar9002_hw_load_ani_reg(ah, chan);
+ return 0;
+ }
+ }
+
+ saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA);
+ if (saveDefAntenna == 0)
+ saveDefAntenna = 1;
+
+ macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
+
+ saveLedState = REG_READ(ah, AR_CFG_LED) &
+ (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
+ AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
+
+ ath9k_hw_mark_phy_inactive(ah);
+
+ ah->paprd_table_write_done = 0;
+
+ /* Only required on the first reset */
+ if (AR_SREV_9271(ah) && ah->htc_reset_init) {
+ REG_WRITE(ah,
+ AR9271_RESET_POWER_DOWN_CONTROL,
+ AR9271_RADIO_RF_RST);
+ udelay(50);
+ }
+
+ if (!ath9k_hw_chip_reset(ah, chan)) {
+ DBG("ath9k: Chip reset failed\n");
+ return -EINVAL;
+ }
+
+ /* Only required on the first reset */
+ if (AR_SREV_9271(ah) && ah->htc_reset_init) {
+ ah->htc_reset_init = 0;
+ REG_WRITE(ah,
+ AR9271_RESET_POWER_DOWN_CONTROL,
+ AR9271_GATE_MAC_CTL);
+ udelay(50);
+ }
+
+ if (AR_SREV_9280_20_OR_LATER(ah))
+ REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
+
+ if (!AR_SREV_9300_20_OR_LATER(ah))
+ ar9002_hw_enable_async_fifo(ah);
+
+ r = ath9k_hw_process_ini(ah, chan);
+ if (r)
+ return r;
+
+ /* Setup MFP options for CCMP */
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
+ * frames when constructing CCMP AAD. */
+ REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT,
+ 0xc7ff);
+ ah->sw_mgmt_crypto = 0;
+ } else if (AR_SREV_9160_10_OR_LATER(ah)) {
+ /* Disable hardware crypto for management frames */
+ REG_CLR_BIT(ah, AR_PCU_MISC_MODE2,
+ AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
+ REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
+ AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
+ ah->sw_mgmt_crypto = 1;
+ } else
+ ah->sw_mgmt_crypto = 1;
+
+ if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
+ ath9k_hw_set_delta_slope(ah, chan);
+
+ ath9k_hw_spur_mitigate_freq(ah, chan);
+ ah->eep_ops->set_board_values(ah, chan);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
+ REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
+ | macStaId1
+ | AR_STA_ID1_RTS_USE_DEF
+ | (ah->config.
+ ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
+ | ah->sta_id1_defaults);
+ ath_hw_setbssidmask(common);
+ REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
+ ath9k_hw_write_associd(ah);
+ REG_WRITE(ah, AR_ISR, ~0);
+ REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ ath9k_hw_set_operating_mode(ah);
+
+ r = ath9k_hw_rf_set_freq(ah, chan);
+ if (r)
+ return r;
+
+ ath9k_hw_set_clockrate(ah);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ for (i = 0; i < AR_NUM_DCU; i++)
+ REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ ah->intr_txqs = 0;
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+ ath9k_hw_resettxqueue(ah, i);
+
+ ath9k_hw_init_interrupt_masks(ah);
+ ath9k_hw_ani_cache_ini_regs(ah);
+
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+ ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
+
+ ath9k_hw_init_global_settings(ah);
+
+ if (!AR_SREV_9300_20_OR_LATER(ah)) {
+ ar9002_hw_update_async_fifo(ah);
+ ar9002_hw_enable_wep_aggregation(ah);
+ }
+
+ REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
+
+ ath9k_hw_set_dma(ah);
+
+ REG_WRITE(ah, AR_OBS, 8);
+
+ if (ah->config.rx_intr_mitigation) {
+ REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
+ REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
+ }
+
+ if (ah->config.tx_intr_mitigation) {
+ REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300);
+ REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750);
+ }
+
+ ath9k_hw_init_bb(ah, chan);
+
+ if (!ath9k_hw_init_cal(ah, chan))
+ return -EIO;
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ ath9k_hw_restore_chainmask(ah);
+ REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ /*
+ * For big endian systems turn on swapping for descriptors
+ */
+ if (AR_SREV_9100(ah)) {
+ u32 mask;
+ mask = REG_READ(ah, AR_CFG);
+ if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
+ DBG2("ath9k: "
+ "CFG Byte Swap Set 0x%x\n", mask);
+ } else {
+ mask =
+ INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
+ REG_WRITE(ah, AR_CFG, mask);
+ DBG2("ath9k: "
+ "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG));
+ }
+ } else {
+ if (common->bus_ops->ath_bus_type == ATH_USB) {
+ /* Configure AR9271 target WLAN */
+ if (AR_SREV_9271(ah))
+ REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB);
+ else
+ REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
+ }
+#if __BYTE_ORDER == __BIG_ENDIAN
+ else if (AR_SREV_9340(ah))
+ REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);
+ else
+ REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
+#endif
+ }
+
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ ar9003_hw_disable_phy_restart(ah);
+ }
+
+ ath9k_hw_apply_gpio_override(ah);
+
+ return 0;
+}
+
+/******************************/
+/* Power Management (Chipset) */
+/******************************/
+
+/*
+ * Notify Power Mgt is disabled in self-generated frames.
+ * If requested, force chip to sleep.
+ */
+static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
+{
+ REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+ if (setChip) {
+ /*
+ * Clear the RTC force wake bit to allow the
+ * mac to go to sleep.
+ */
+ REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN);
+ if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
+ REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
+
+ /* Shutdown chip. Active low */
+ if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah))
+ REG_CLR_BIT(ah, (AR_RTC_RESET),
+ AR_RTC_RESET_EN);
+ }
+
+ /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
+ if (AR_SREV_9300_20_OR_LATER(ah))
+ REG_WRITE(ah, AR_WA,
+ ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
+}
+
+static int ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
+{
+ u32 val;
+ int i;
+
+ /* Set Bits 14 and 17 of AR_WA before powering on the chip. */
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ REG_WRITE(ah, AR_WA, ah->WARegVal);
+ udelay(10);
+ }
+
+ if (setChip) {
+ if ((REG_READ(ah, AR_RTC_STATUS) &
+ AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
+ if (ath9k_hw_set_reset_reg(ah,
+ ATH9K_RESET_POWER_ON) != 1) {
+ return 0;
+ }
+ if (!AR_SREV_9300_20_OR_LATER(ah))
+ ath9k_hw_init_pll(ah, NULL);
+ }
+ if (AR_SREV_9100(ah))
+ REG_SET_BIT(ah, AR_RTC_RESET,
+ AR_RTC_RESET_EN);
+
+ REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN);
+ udelay(50);
+
+ for (i = POWER_UP_TIME / 50; i > 0; i--) {
+ val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
+ if (val == AR_RTC_STATUS_ON)
+ break;
+ udelay(50);
+ REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN);
+ }
+ if (i == 0) {
+ DBG("ath9k: "
+ "Failed to wakeup in %dus\n",
+ POWER_UP_TIME / 20);
+ return 0;
+ }
+ }
+
+ REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+
+ return 1;
+}
+
+int ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
+{
+ int status = 1, setChip = 1;
+ static const char *modes[] = {
+ "AWAKE",
+ "FULL-SLEEP",
+ "NETWORK SLEEP",
+ "UNDEFINED"
+ };
+
+ if (ah->power_mode == mode)
+ return status;
+
+ DBG2("ath9k: %s -> %s\n",
+ modes[ah->power_mode], modes[mode]);
+
+ switch (mode) {
+ case ATH9K_PM_AWAKE:
+ status = ath9k_hw_set_power_awake(ah, setChip);
+ break;
+ case ATH9K_PM_FULL_SLEEP:
+ ath9k_set_power_sleep(ah, setChip);
+ ah->chip_fullsleep = 1;
+ break;
+ default:
+ DBG("ath9k: Unknown power mode %d\n", mode);
+ return 0;
+ }
+ ah->power_mode = mode;
+
+ return status;
+}
+
+/*******************/
+/* HW Capabilities */
+/*******************/
+
+int ath9k_hw_fill_cap_info(struct ath_hw *ah)
+{
+ struct ath9k_hw_capabilities *pCap = &ah->caps;
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ u16 eeval;
+ u8 ant_div_ctl1, tx_chainmask, rx_chainmask;
+
+ eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
+ regulatory->current_rd = eeval;
+
+ eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
+ if (AR_SREV_9285_12_OR_LATER(ah))
+ eeval |= AR9285_RDEXT_DEFAULT;
+ regulatory->current_rd_ext = eeval;
+
+ if (ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
+ if (regulatory->current_rd == 0x64 ||
+ regulatory->current_rd == 0x65)
+ regulatory->current_rd += 5;
+ else if (regulatory->current_rd == 0x41)
+ regulatory->current_rd = 0x43;
+ DBG2("ath9k: "
+ "regdomain mapped to 0x%x\n", regulatory->current_rd);
+ }
+
+ eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
+ if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) {
+ DBG("ath9k: "
+ "no band has been marked as supported in EEPROM\n");
+ return -EINVAL;
+ }
+
+ if (eeval & AR5416_OPFLAGS_11A)
+ pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
+
+ if (eeval & AR5416_OPFLAGS_11G)
+ pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
+
+ pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
+ /*
+ * For AR9271 we will temporarilly uses the rx chainmax as read from
+ * the EEPROM.
+ */
+ if ((ah->hw_version.devid == AR5416_DEVID_PCI) &&
+ !(eeval & AR5416_OPFLAGS_11A) &&
+ !(AR_SREV_9271(ah)))
+ /* CB71: GPIO 0 is pulled down to indicate 3 rx chains */
+ pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7;
+ else if (AR_SREV_9100(ah))
+ pCap->rx_chainmask = 0x7;
+ else
+ /* Use rx_chainmask from EEPROM. */
+ pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
+
+ ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
+
+ /* enable key search for every frame in an aggregate */
+ if (AR_SREV_9300_20_OR_LATER(ah))
+ ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH;
+
+ common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;
+
+ pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
+
+ if (AR_SREV_9271(ah))
+ pCap->num_gpio_pins = AR9271_NUM_GPIO;
+ else if (AR_DEVID_7010(ah))
+ pCap->num_gpio_pins = AR7010_NUM_GPIO;
+ else if (AR_SREV_9285_12_OR_LATER(ah))
+ pCap->num_gpio_pins = AR9285_NUM_GPIO;
+ else if (AR_SREV_9280_20_OR_LATER(ah))
+ pCap->num_gpio_pins = AR928X_NUM_GPIO;
+ else
+ pCap->num_gpio_pins = AR_NUM_GPIO;
+
+ if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
+ pCap->hw_caps |= ATH9K_HW_CAP_CST;
+ pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
+ } else {
+ pCap->rts_aggr_limit = (8 * 1024);
+ }
+
+ ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT);
+ if (ah->rfsilent & EEP_RFSILENT_ENABLED) {
+ ah->rfkill_gpio =
+ MS(ah->rfsilent, EEP_RFSILENT_GPIO_SEL);
+ ah->rfkill_polarity =
+ MS(ah->rfsilent, EEP_RFSILENT_POLARITY);
+
+ pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
+ }
+
+ pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
+
+ if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
+ pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
+ else
+ pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
+
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK;
+ if (!AR_SREV_9485(ah))
+ pCap->hw_caps |= ATH9K_HW_CAP_LDPC;
+
+ pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
+ pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH;
+ pCap->rx_status_len = sizeof(struct ar9003_rxs);
+ pCap->tx_desc_len = sizeof(struct ar9003_txc);
+ pCap->txs_len = sizeof(struct ar9003_txs);
+ if (!ah->config.paprd_disable &&
+ ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
+ pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
+ } else {
+ pCap->tx_desc_len = sizeof(struct ath_desc);
+ if (AR_SREV_9280_20(ah) &&
+ ((ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) <=
+ AR5416_EEP_MINOR_VER_16) ||
+ ah->eep_ops->get_eeprom(ah, EEP_FSTCLK_5G)))
+ pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK;
+ }
+
+ if (AR_SREV_9300_20_OR_LATER(ah))
+ pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
+
+ if (AR_SREV_9300_20_OR_LATER(ah))
+ ah->ent_mode = REG_READ(ah, AR_ENT_OTP);
+
+ if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah))
+ pCap->hw_caps |= ATH9K_HW_CAP_SGI_20;
+
+ if (AR_SREV_9285(ah))
+ if (ah->eep_ops->get_eeprom(ah, EEP_MODAL_VER) >= 3) {
+ ant_div_ctl1 =
+ ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
+ if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1))
+ pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
+ }
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE))
+ pCap->hw_caps |= ATH9K_HW_CAP_APM;
+ }
+
+
+ if (AR_SREV_9485(ah)) {
+ ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
+ /*
+ * enable the diversity-combining algorithm only when
+ * both enable_lna_div and enable_fast_div are set
+ * Table for Diversity
+ * ant_div_alt_lnaconf bit 0-1
+ * ant_div_main_lnaconf bit 2-3
+ * ant_div_alt_gaintb bit 4
+ * ant_div_main_gaintb bit 5
+ * enable_ant_div_lnadiv bit 6
+ * enable_ant_fast_div bit 7
+ */
+ if ((ant_div_ctl1 >> 0x6) == 0x3)
+ pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
+ }
+
+ if (AR_SREV_9485_10(ah)) {
+ pCap->pcie_lcr_extsync_en = 1;
+ pCap->pcie_lcr_offset = 0x80;
+ }
+
+ tx_chainmask = pCap->tx_chainmask;
+ rx_chainmask = pCap->rx_chainmask;
+ while (tx_chainmask || rx_chainmask) {
+ if (tx_chainmask & BIT(0))
+ pCap->max_txchains++;
+ if (rx_chainmask & BIT(0))
+ pCap->max_rxchains++;
+
+ tx_chainmask >>= 1;
+ rx_chainmask >>= 1;
+ }
+
+ return 0;
+}
+
+/****************************/
+/* GPIO / RFKILL / Antennae */
+/****************************/
+
+static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah,
+ u32 gpio, u32 type)
+{
+ int addr;
+ u32 gpio_shift, tmp;
+
+ if (gpio > 11)
+ addr = AR_GPIO_OUTPUT_MUX3;
+ else if (gpio > 5)
+ addr = AR_GPIO_OUTPUT_MUX2;
+ else
+ addr = AR_GPIO_OUTPUT_MUX1;
+
+ gpio_shift = (gpio % 6) * 5;
+
+ if (AR_SREV_9280_20_OR_LATER(ah)
+ || (addr != AR_GPIO_OUTPUT_MUX1)) {
+ REG_RMW(ah, addr, (type << gpio_shift),
+ (0x1f << gpio_shift));
+ } else {
+ tmp = REG_READ(ah, addr);
+ tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
+ tmp &= ~(0x1f << gpio_shift);
+ tmp |= (type << gpio_shift);
+ REG_WRITE(ah, addr, tmp);
+ }
+}
+
+void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio)
+{
+ u32 gpio_shift;
+
+ if (AR_DEVID_7010(ah)) {
+ gpio_shift = gpio;
+ REG_RMW(ah, AR7010_GPIO_OE,
+ (AR7010_GPIO_OE_AS_INPUT << gpio_shift),
+ (AR7010_GPIO_OE_MASK << gpio_shift));
+ return;
+ }
+
+ gpio_shift = gpio << 1;
+ REG_RMW(ah,
+ AR_GPIO_OE_OUT,
+ (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
+ (AR_GPIO_OE_OUT_DRV << gpio_shift));
+}
+
+u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
+{
+#define MS_REG_READ(x, y) \
+ (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & (AR_GPIO_BIT(y)))
+
+ if (gpio >= ah->caps.num_gpio_pins)
+ return 0xffffffff;
+
+ if (AR_DEVID_7010(ah)) {
+ u32 val;
+ val = REG_READ(ah, AR7010_GPIO_IN);
+ return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0;
+ } else if (AR_SREV_9300_20_OR_LATER(ah))
+ return (MS(REG_READ(ah, AR_GPIO_IN), AR9300_GPIO_IN_VAL) &
+ AR_GPIO_BIT(gpio)) != 0;
+ else if (AR_SREV_9271(ah))
+ return MS_REG_READ(AR9271, gpio) != 0;
+ else if (AR_SREV_9287_11_OR_LATER(ah))
+ return MS_REG_READ(AR9287, gpio) != 0;
+ else if (AR_SREV_9285_12_OR_LATER(ah))
+ return MS_REG_READ(AR9285, gpio) != 0;
+ else if (AR_SREV_9280_20_OR_LATER(ah))
+ return MS_REG_READ(AR928X, gpio) != 0;
+ else
+ return MS_REG_READ(AR, gpio) != 0;
+}
+
+void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
+ u32 ah_signal_type)
+{
+ u32 gpio_shift;
+
+ if (AR_DEVID_7010(ah)) {
+ gpio_shift = gpio;
+ REG_RMW(ah, AR7010_GPIO_OE,
+ (AR7010_GPIO_OE_AS_OUTPUT << gpio_shift),
+ (AR7010_GPIO_OE_MASK << gpio_shift));
+ return;
+ }
+
+ ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
+ gpio_shift = 2 * gpio;
+ REG_RMW(ah,
+ AR_GPIO_OE_OUT,
+ (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
+ (AR_GPIO_OE_OUT_DRV << gpio_shift));
+}
+
+void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
+{
+ if (AR_DEVID_7010(ah)) {
+ val = val ? 0 : 1;
+ REG_RMW(ah, AR7010_GPIO_OUT, ((val&1) << gpio),
+ AR_GPIO_BIT(gpio));
+ return;
+ }
+
+ if (AR_SREV_9271(ah))
+ val = ~val;
+
+ REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
+ AR_GPIO_BIT(gpio));
+}
+
+u32 ath9k_hw_getdefantenna(struct ath_hw *ah)
+{
+ return REG_READ(ah, AR_DEF_ANTENNA) & 0x7;
+}
+
+void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna)
+{
+ REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
+}
+
+/*********************/
+/* General Operation */
+/*********************/
+
+u32 ath9k_hw_getrxfilter(struct ath_hw *ah)
+{
+ u32 bits = REG_READ(ah, AR_RX_FILTER);
+ u32 phybits = REG_READ(ah, AR_PHY_ERR);
+
+ if (phybits & AR_PHY_ERR_RADAR)
+ bits |= ATH9K_RX_FILTER_PHYRADAR;
+ if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))
+ bits |= ATH9K_RX_FILTER_PHYERR;
+
+ return bits;
+}
+
+void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
+{
+ u32 phybits;
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_RX_FILTER, bits);
+
+ phybits = 0;
+ if (bits & ATH9K_RX_FILTER_PHYRADAR)
+ phybits |= AR_PHY_ERR_RADAR;
+ if (bits & ATH9K_RX_FILTER_PHYERR)
+ phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
+ REG_WRITE(ah, AR_PHY_ERR, phybits);
+
+ if (phybits)
+ REG_SET_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA);
+ else
+ REG_CLR_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+}
+
+int ath9k_hw_phy_disable(struct ath_hw *ah)
+{
+ if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
+ return 0;
+
+ ath9k_hw_init_pll(ah, NULL);
+ return 1;
+}
+
+int ath9k_hw_disable(struct ath_hw *ah)
+{
+ if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+ return 0;
+
+ if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD))
+ return 0;
+
+ ath9k_hw_init_pll(ah, NULL);
+ return 1;
+}
+
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, int test)
+{
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ath9k_channel *chan = ah->curchan;
+ struct net80211_channel *channel = chan->chan;
+
+ regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER);
+
+ ah->eep_ops->set_txpower(ah, chan,
+ ath9k_regd_get_ctl(regulatory, chan),
+ 0,
+ channel->maxpower * 2,
+ min((u32) MAX_RATE_POWER,
+ (u32) regulatory->power_limit), test);
+}
+
+void ath9k_hw_setopmode(struct ath_hw *ah)
+{
+ ath9k_hw_set_operating_mode(ah);
+}
+
+void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1)
+{
+ REG_WRITE(ah, AR_MCAST_FIL0, filter0);
+ REG_WRITE(ah, AR_MCAST_FIL1, filter1);
+}
+
+void ath9k_hw_write_associd(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(common->curbssid));
+ REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(common->curbssid + 4) |
+ ((common->curaid & 0x3fff) << AR_BSS_ID1_AID_S));
+}
+
+void ath9k_hw_set11nmac2040(struct ath_hw *ah)
+{
+ u32 macmode;
+
+ macmode = 0;
+
+ REG_WRITE(ah, AR_2040_MODE, macmode);
+}
+
+static struct {
+ u32 version;
+ const char * name;
+} ath_mac_bb_names[] = {
+ /* Devices with external radios */
+ { AR_SREV_VERSION_5416_PCI, "5416" },
+ { AR_SREV_VERSION_5416_PCIE, "5418" },
+ { AR_SREV_VERSION_9100, "9100" },
+ { AR_SREV_VERSION_9160, "9160" },
+ /* Single-chip solutions */
+ { AR_SREV_VERSION_9280, "9280" },
+ { AR_SREV_VERSION_9285, "9285" },
+ { AR_SREV_VERSION_9287, "9287" },
+ { AR_SREV_VERSION_9271, "9271" },
+ { AR_SREV_VERSION_9300, "9300" },
+ { AR_SREV_VERSION_9485, "9485" },
+};
+
+/* For devices with external radios */
+static struct {
+ u16 version;
+ const char * name;
+} ath_rf_names[] = {
+ { 0, "5133" },
+ { AR_RAD5133_SREV_MAJOR, "5133" },
+ { AR_RAD5122_SREV_MAJOR, "5122" },
+ { AR_RAD2133_SREV_MAJOR, "2133" },
+ { AR_RAD2122_SREV_MAJOR, "2122" }
+};
+
+/*
+ * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
+ */
+static const char *ath9k_hw_mac_bb_name(u32 mac_bb_version)
+{
+ unsigned int i;
+
+ for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) {
+ if (ath_mac_bb_names[i].version == mac_bb_version) {
+ return ath_mac_bb_names[i].name;
+ }
+ }
+
+ return "????";
+}
+
+/*
+ * Return the RF name. "????" is returned if the RF is unknown.
+ * Used for devices with external radios.
+ */
+static const char *ath9k_hw_rf_name(u16 rf_version)
+{
+ unsigned int i;
+
+ for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) {
+ if (ath_rf_names[i].version == rf_version) {
+ return ath_rf_names[i].name;
+ }
+ }
+
+ return "????";
+}
+
+void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len)
+{
+ int used;
+
+ /* chipsets >= AR9280 are single-chip */
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ used = snprintf(hw_name, len,
+ "Atheros AR%s Rev:%x",
+ ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
+ ah->hw_version.macRev);
+ }
+ else {
+ used = snprintf(hw_name, len,
+ "Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x",
+ ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
+ ah->hw_version.macRev,
+ ath9k_hw_rf_name((ah->hw_version.analog5GhzRev &
+ AR_RADIO_SREV_MAJOR)),
+ ah->hw_version.phyRev);
+ }
+
+ hw_name[used] = '\0';
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_init.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_init.c
new file mode 100644
index 00000000..93fbe773
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_init.c
@@ -0,0 +1,593 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/malloc.h>
+#include <ipxe/pci_io.h>
+#include <ipxe/pci.h>
+
+#include "ath9k.h"
+
+int is_ath9k_unloaded;
+/* We use the hw_value as an index into our private channel structure */
+
+#define CHAN2G(_freq, _idx) { \
+ .band = NET80211_BAND_2GHZ, \
+ .center_freq = (_freq), \
+ .hw_value = (_idx), \
+ .maxpower = 20, \
+}
+
+#define CHAN5G(_freq, _idx) { \
+ .band = NET80211_BAND_5GHZ, \
+ .center_freq = (_freq), \
+ .hw_value = (_idx), \
+ .maxpower = 20, \
+}
+
+/* Some 2 GHz radios are actually tunable on 2312-2732
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+static const struct net80211_channel ath9k_2ghz_chantable[] = {
+ CHAN2G(2412, 0), /* Channel 1 */
+ CHAN2G(2417, 1), /* Channel 2 */
+ CHAN2G(2422, 2), /* Channel 3 */
+ CHAN2G(2427, 3), /* Channel 4 */
+ CHAN2G(2432, 4), /* Channel 5 */
+ CHAN2G(2437, 5), /* Channel 6 */
+ CHAN2G(2442, 6), /* Channel 7 */
+ CHAN2G(2447, 7), /* Channel 8 */
+ CHAN2G(2452, 8), /* Channel 9 */
+ CHAN2G(2457, 9), /* Channel 10 */
+ CHAN2G(2462, 10), /* Channel 11 */
+ CHAN2G(2467, 11), /* Channel 12 */
+ CHAN2G(2472, 12), /* Channel 13 */
+ CHAN2G(2484, 13), /* Channel 14 */
+};
+
+/* Some 5 GHz radios are actually tunable on XXXX-YYYY
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+static const struct net80211_channel ath9k_5ghz_chantable[] = {
+ /* _We_ call this UNII 1 */
+ CHAN5G(5180, 14), /* Channel 36 */
+ CHAN5G(5200, 15), /* Channel 40 */
+ CHAN5G(5220, 16), /* Channel 44 */
+ CHAN5G(5240, 17), /* Channel 48 */
+ /* _We_ call this UNII 2 */
+ CHAN5G(5260, 18), /* Channel 52 */
+ CHAN5G(5280, 19), /* Channel 56 */
+ CHAN5G(5300, 20), /* Channel 60 */
+ CHAN5G(5320, 21), /* Channel 64 */
+ /* _We_ call this "Middle band" */
+ CHAN5G(5500, 22), /* Channel 100 */
+ CHAN5G(5520, 23), /* Channel 104 */
+ CHAN5G(5540, 24), /* Channel 108 */
+ CHAN5G(5560, 25), /* Channel 112 */
+ CHAN5G(5580, 26), /* Channel 116 */
+ CHAN5G(5600, 27), /* Channel 120 */
+ CHAN5G(5620, 28), /* Channel 124 */
+ CHAN5G(5640, 29), /* Channel 128 */
+ CHAN5G(5660, 30), /* Channel 132 */
+ CHAN5G(5680, 31), /* Channel 136 */
+ CHAN5G(5700, 32), /* Channel 140 */
+ /* _We_ call this UNII 3 */
+ CHAN5G(5745, 33), /* Channel 149 */
+ CHAN5G(5765, 34), /* Channel 153 */
+ CHAN5G(5785, 35), /* Channel 157 */
+ CHAN5G(5805, 36), /* Channel 161 */
+ CHAN5G(5825, 37), /* Channel 165 */
+};
+
+/* Atheros hardware rate code addition for short premble */
+#define SHPCHECK(__hw_rate, __flags) \
+ ((__flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0)
+
+#define RATE(_bitrate, _hw_rate, _flags) { \
+ .bitrate = (_bitrate), \
+ .flags = (_flags), \
+ .hw_value = (_hw_rate), \
+ .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \
+}
+
+static struct ath9k_legacy_rate ath9k_legacy_rates[] = {
+ RATE(10, 0x1b, 0),
+ RATE(20, 0x1a, IEEE80211_TX_RC_USE_SHORT_PREAMBLE),
+ RATE(55, 0x19, IEEE80211_TX_RC_USE_SHORT_PREAMBLE),
+ RATE(110, 0x18, IEEE80211_TX_RC_USE_SHORT_PREAMBLE),
+ RATE(60, 0x0b, 0),
+ RATE(90, 0x0f, 0),
+ RATE(120, 0x0a, 0),
+ RATE(180, 0x0e, 0),
+ RATE(240, 0x09, 0),
+ RATE(360, 0x0d, 0),
+ RATE(480, 0x08, 0),
+ RATE(540, 0x0c, 0),
+};
+
+static void ath9k_deinit_softc(struct ath_softc *sc);
+
+/*
+ * Read and write, they both share the same lock. We do this to serialize
+ * reads and writes on Atheros 802.11n PCI devices only. This is required
+ * as the FIFO on these devices can only accept sanely 2 requests.
+ */
+
+static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
+{
+ struct ath_hw *ah = (struct ath_hw *) hw_priv;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+
+ writel(val, sc->mem + reg_offset);
+}
+
+static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
+{
+ struct ath_hw *ah = (struct ath_hw *) hw_priv;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+ u32 val;
+
+ val = readl(sc->mem + reg_offset);
+ return val;
+}
+
+static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
+{
+ struct ath_hw *ah = (struct ath_hw *) hw_priv;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+ u32 val;
+
+ val = readl(sc->mem + reg_offset);
+ val &= ~clr;
+ val |= set;
+ writel(val, sc->mem + reg_offset);
+
+ return val;
+}
+
+/**************************/
+/* Initialization */
+/**************************/
+
+/*
+ * This function will allocate both the DMA descriptor structure, and the
+ * buffers it contains. These are used to contain the descriptors used
+ * by the system.
+*/
+int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
+ struct list_head *head, const char *name,
+ int nbuf, int ndesc, int is_tx)
+{
+#define DS2PHYS(_dd, _ds) \
+ ((_dd)->dd_desc_paddr + ((char *)(_ds) - (char *)(_dd)->dd_desc))
+#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF9F) ? 1 : 0)
+ u8 *ds;
+ struct ath_buf *bf;
+ int i, bsize, error, desc_len;
+
+ DBG2("ath9k: %s DMA: %d buffers %d desc/buf\n",
+ name, nbuf, ndesc);
+
+ INIT_LIST_HEAD(head);
+
+ if (is_tx)
+ desc_len = sc->sc_ah->caps.tx_desc_len;
+ else
+ desc_len = sizeof(struct ath_desc);
+
+ /* ath_desc must be a multiple of DWORDs */
+ if ((desc_len % 4) != 0) {
+ DBG("ath9k: ath_desc not DWORD aligned\n");
+ error = -ENOMEM;
+ goto fail;
+ }
+
+ dd->dd_desc_len = desc_len * nbuf * ndesc;
+
+ /*
+ * Need additional DMA memory because we can't use
+ * descriptors that cross the 4K page boundary.
+ * However, iPXE only utilizes 16 buffers, which
+ * will never make up more than half of one page,
+ * so we will only ever skip 1 descriptor, if that.
+ */
+ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
+ u32 ndesc_skipped = 1;
+ u32 dma_len;
+
+ dma_len = ndesc_skipped * desc_len;
+ dd->dd_desc_len += dma_len;
+ }
+
+ /* allocate descriptors */
+ dd->dd_desc = malloc_dma(dd->dd_desc_len, 16);
+ if (dd->dd_desc == NULL) {
+ error = -ENOMEM;
+ goto fail;
+ }
+ dd->dd_desc_paddr = virt_to_bus(dd->dd_desc);
+ ds = (u8 *) dd->dd_desc;
+ DBG2("ath9k: %s DMA map: %p (%d) -> %llx (%d)\n",
+ name, ds, (u32) dd->dd_desc_len,
+ ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
+
+ /* allocate buffers */
+ bsize = sizeof(struct ath_buf) * nbuf;
+ bf = zalloc(bsize);
+ if (bf == NULL) {
+ error = -ENOMEM;
+ goto fail2;
+ }
+ dd->dd_bufptr = bf;
+
+ for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
+ bf->bf_desc = ds;
+ bf->bf_daddr = DS2PHYS(dd, ds);
+
+ if (!(sc->sc_ah->caps.hw_caps &
+ ATH9K_HW_CAP_4KB_SPLITTRANS)) {
+ /*
+ * Skip descriptor addresses which can cause 4KB
+ * boundary crossing (addr + length) with a 32 dword
+ * descriptor fetch.
+ */
+ while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
+ ds += (desc_len * ndesc);
+ bf->bf_desc = ds;
+ bf->bf_daddr = DS2PHYS(dd, ds);
+ }
+ }
+ list_add_tail(&bf->list, head);
+ }
+ return 0;
+fail2:
+ free_dma(dd->dd_desc, dd->dd_desc_len);
+fail:
+ memset(dd, 0, sizeof(*dd));
+ return error;
+#undef ATH_DESC_4KB_BOUND_CHECK
+#undef DS2PHYS
+}
+
+void ath9k_init_crypto(struct ath_softc *sc)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ unsigned int i = 0;
+
+ /* Get the hardware key cache size. */
+ common->keymax = AR_KEYTABLE_SIZE;
+
+ /*
+ * Reset the key cache since some parts do not
+ * reset the contents on initial power up.
+ */
+ for (i = 0; i < common->keymax; i++)
+ ath_hw_keyreset(common, (u16) i);
+
+ /*
+ * Check whether the separate key cache entries
+ * are required to handle both tx+rx MIC keys.
+ * With split mic keys the number of stations is limited
+ * to 27 otherwise 59.
+ */
+ if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
+ common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
+}
+
+static int ath9k_init_queues(struct ath_softc *sc)
+{
+ int i = 0;
+
+ for (i = 0; i < WME_NUM_AC; i++) {
+ sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
+ sc->tx.txq_map[i]->mac80211_qnum = i;
+ }
+ return 0;
+}
+
+static int ath9k_init_channels_rates(struct ath_softc *sc)
+{
+ unsigned int i;
+
+ memcpy(&sc->rates, ath9k_legacy_rates, sizeof(ath9k_legacy_rates));
+
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
+ memcpy(&sc->hwinfo->channels[sc->hwinfo->nr_channels], ath9k_2ghz_chantable, sizeof(ath9k_2ghz_chantable));
+
+ sc->hwinfo->nr_channels += ARRAY_SIZE(ath9k_2ghz_chantable);
+
+ for (i = 0; i < ARRAY_SIZE(ath9k_legacy_rates); i++)
+ sc->hwinfo->rates[NET80211_BAND_2GHZ][i] = ath9k_legacy_rates[i].bitrate;
+ sc->hwinfo->nr_rates[NET80211_BAND_2GHZ] = ARRAY_SIZE(ath9k_legacy_rates);
+ }
+
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
+ memcpy(&sc->hwinfo->channels[sc->hwinfo->nr_channels], ath9k_5ghz_chantable, sizeof(ath9k_5ghz_chantable));
+
+ sc->hwinfo->nr_channels += ARRAY_SIZE(ath9k_5ghz_chantable);
+
+ for (i = 4; i < ARRAY_SIZE(ath9k_legacy_rates); i++)
+ sc->hwinfo->rates[NET80211_BAND_5GHZ][i - 4] = ath9k_legacy_rates[i].bitrate;
+ sc->hwinfo->nr_rates[NET80211_BAND_5GHZ] = ARRAY_SIZE(ath9k_legacy_rates) - 4;
+ }
+ return 0;
+}
+
+static void ath9k_init_misc(struct ath_softc *sc)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+ common->ani.timer = 0;
+
+ sc->config.txpowlimit = ATH_TXPOWER_MAX;
+
+ common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
+ common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
+
+ ath9k_hw_set_diversity(sc->sc_ah, 1);
+ sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
+
+ memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
+}
+
+static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
+ const struct ath_bus_ops *bus_ops)
+{
+ struct ath_hw *ah = NULL;
+ struct ath_common *common;
+ int ret = 0, i;
+ int csz = 0;
+
+ ah = zalloc(sizeof(struct ath_hw));
+ if (!ah)
+ return -ENOMEM;
+
+ ah->dev = sc->dev;
+ ah->hw_version.devid = devid;
+ ah->hw_version.subsysid = subsysid;
+ ah->reg_ops.read = ath9k_ioread32;
+ ah->reg_ops.write = ath9k_iowrite32;
+ ah->reg_ops.rmw = ath9k_reg_rmw;
+ sc->sc_ah = ah;
+
+ sc->hwinfo = zalloc(sizeof(*sc->hwinfo));
+ if (!sc->hwinfo) {
+ DBG("ath9k: cannot allocate 802.11 hardware info structure\n");
+ return -ENOMEM;
+ }
+
+ ah->ah_flags |= AH_USE_EEPROM;
+ sc->sc_ah->led_pin = -1;
+
+ common = ath9k_hw_common(ah);
+ common->ops = &ah->reg_ops;
+ common->bus_ops = bus_ops;
+ common->ah = ah;
+ common->dev = sc->dev;
+ common->priv = sc;
+
+ sc->intr_tq = ath9k_tasklet;
+
+ /*
+ * Cache line size is used to size and align various
+ * structures used to communicate with the hardware.
+ */
+ ath_read_cachesize(common, &csz);
+ common->cachelsz = csz << 2; /* convert to bytes */
+
+ /* Initializes the hardware for all supported chipsets */
+ ret = ath9k_hw_init(ah);
+ if (ret)
+ goto err_hw;
+
+ memcpy(sc->hwinfo->hwaddr, common->macaddr, ETH_ALEN);
+
+ ret = ath9k_init_queues(sc);
+ if (ret)
+ goto err_queues;
+
+ ret = ath9k_init_channels_rates(sc);
+ if (ret)
+ goto err_btcoex;
+
+ ath9k_init_crypto(sc);
+ ath9k_init_misc(sc);
+
+ return 0;
+
+err_btcoex:
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+ if (ATH_TXQ_SETUP(sc, i))
+ ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+err_queues:
+ ath9k_hw_deinit(ah);
+err_hw:
+ free(sc->hwinfo);
+ sc->hwinfo = NULL;
+
+ free(ah);
+ sc->sc_ah = NULL;
+
+ return ret;
+}
+
+static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
+{
+ struct net80211_channel *chan;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+ int i;
+
+ for (i = 0; i < sc->hwinfo->nr_channels; i++) {
+ chan = &sc->hwinfo->channels[i];
+ if(chan->band != band)
+ continue;
+ ah->curchan = &ah->channels[chan->hw_value];
+ ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, 1);
+ chan->maxpower = reg->max_power_level / 2;
+ }
+}
+
+static void ath9k_init_txpower_limits(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_channel *curchan = ah->curchan;
+
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+ ath9k_init_band_txpower(sc, NET80211_BAND_2GHZ);
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+ ath9k_init_band_txpower(sc, NET80211_BAND_5GHZ);
+
+ ah->curchan = curchan;
+}
+
+void ath9k_set_hw_capab(struct ath_softc *sc, struct net80211_device *dev __unused)
+{
+ sc->hwinfo->flags = NET80211_HW_RX_HAS_FCS;
+ sc->hwinfo->signal_type = NET80211_SIGNAL_DB;
+ sc->hwinfo->signal_max = 40; /* 35dB should give perfect 54Mbps */
+ sc->hwinfo->channel_change_time = 5000;
+
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+ {
+ sc->hwinfo->bands |= NET80211_BAND_BIT_2GHZ;
+ sc->hwinfo->modes |= NET80211_MODE_B | NET80211_MODE_G;
+ }
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+ {
+ sc->hwinfo->bands |= NET80211_BAND_BIT_5GHZ;
+ sc->hwinfo->modes |= NET80211_MODE_A;
+ }
+}
+
+int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
+ const struct ath_bus_ops *bus_ops)
+{
+ struct net80211_device *dev = sc->dev;
+ /*struct ath_common *common;
+ struct ath_hw *ah;*/
+ int error = 0;
+ /*struct ath_regulatory *reg;*/
+
+ /* Bring up device */
+ error = ath9k_init_softc(devid, sc, subsysid, bus_ops);
+ if (error != 0)
+ goto error_init;
+
+ /*ah = sc->sc_ah;
+ common = ath9k_hw_common(ah);*/
+ ath9k_set_hw_capab(sc, dev);
+ /* TODO Cottsay: reg */
+ /* Initialize regulatory */
+ /*error = ath_regd_init(&common->regulatory, sc->dev->wiphy,
+ ath9k_reg_notifier);
+ if (error)
+ goto error_regd;
+
+ reg = &common->regulatory;*/
+
+ /* Setup TX DMA */
+ error = ath_tx_init(sc, ATH_TXBUF);
+ if (error != 0)
+ goto error_tx;
+
+ /* Setup RX DMA */
+ error = ath_rx_init(sc, ATH_RXBUF);
+ if (error != 0)
+ goto error_rx;
+
+ ath9k_init_txpower_limits(sc);
+
+ /* Register with mac80211 */
+ error = net80211_register(dev, &ath9k_ops, sc->hwinfo);
+ if (error)
+ goto error_register;
+
+ /* TODO Cottsay: reg */
+ /* Handle world regulatory */
+ /*if (!ath_is_world_regd(reg)) {
+ error = regulatory_hint(hw->wiphy, reg->alpha2);
+ if (error)
+ goto error_world;
+ }*/
+
+ sc->hw_pll_work = ath_hw_pll_work;
+ sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+
+ /* TODO Cottsay: rfkill */
+ /*ath_start_rfkill_poll(sc);*/
+
+ return 0;
+
+//error_world:
+// net80211_unregister(dev);
+error_register:
+ ath_rx_cleanup(sc);
+error_rx:
+ ath_tx_cleanup(sc);
+error_tx:
+ ath9k_deinit_softc(sc);
+error_init:
+ return error;
+}
+
+/*****************************/
+/* De-Initialization */
+/*****************************/
+
+static void ath9k_deinit_softc(struct ath_softc *sc)
+{
+ int i = 0;
+
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+ if (ATH_TXQ_SETUP(sc, i))
+ ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+
+ ath9k_hw_deinit(sc->sc_ah);
+
+ free(sc->hwinfo);
+ sc->hwinfo = NULL;
+ free(sc->sc_ah);
+ sc->sc_ah = NULL;
+}
+
+void ath9k_deinit_device(struct ath_softc *sc)
+{
+ struct net80211_device *dev = sc->dev;
+
+ net80211_unregister(dev);
+ ath_rx_cleanup(sc);
+ ath_tx_cleanup(sc);
+ ath9k_deinit_softc(sc);
+}
+
+void ath_descdma_cleanup(struct ath_softc *sc __unused,
+ struct ath_descdma *dd,
+ struct list_head *head)
+{
+ free_dma(dd->dd_desc, dd->dd_desc_len);
+
+ INIT_LIST_HEAD(head);
+ free(dd->dd_bufptr);
+ memset(dd, 0, sizeof(*dd));
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_mac.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_mac.c
new file mode 100644
index 00000000..c2f6d630
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_mac.c
@@ -0,0 +1,733 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+
+#include "hw.h"
+#include "hw-ops.h"
+
+static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
+ struct ath9k_tx_queue_info *qi __unused)
+{
+ DBG2("ath9k: "
+ "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
+ ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
+ ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
+ ah->txurn_interrupt_mask);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_IMR_S0,
+ SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
+ | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));
+ REG_WRITE(ah, AR_IMR_S1,
+ SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)
+ | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));
+
+ ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN;
+ ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN);
+ REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+}
+
+void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
+{
+ REG_WRITE(ah, AR_QTXDP(q), txdp);
+}
+
+void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
+{
+ DBG2("ath9k: "
+ "Enable TXE on queue: %d\n", q);
+ REG_WRITE(ah, AR_Q_TXE, 1 << q);
+}
+
+u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
+{
+ u32 npend;
+
+ npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
+ if (npend == 0) {
+
+ if (REG_READ(ah, AR_Q_TXE) & (1 << q))
+ npend = 1;
+ }
+
+ return npend;
+}
+
+/**
+ * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level
+ *
+ * @ah: atheros hardware struct
+ * @bIncTrigLevel: whether or not the frame trigger level should be updated
+ *
+ * The frame trigger level specifies the minimum number of bytes,
+ * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO
+ * before the PCU will initiate sending the frame on the air. This can
+ * mean we initiate transmit before a full frame is on the PCU TX FIFO.
+ * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs
+ * first)
+ *
+ * Caution must be taken to ensure to set the frame trigger level based
+ * on the DMA request size. For example if the DMA request size is set to
+ * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because
+ * there need to be enough space in the tx FIFO for the requested transfer
+ * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set
+ * the threshold to a value beyond 6, then the transmit will hang.
+ *
+ * Current dual stream devices have a PCU TX FIFO size of 8 KB.
+ * Current single stream devices have a PCU TX FIFO size of 4 KB, however,
+ * there is a hardware issue which forces us to use 2 KB instead so the
+ * frame trigger level must not exceed 2 KB for these chipsets.
+ */
+int ath9k_hw_updatetxtriglevel(struct ath_hw *ah, int bIncTrigLevel)
+{
+ u32 txcfg, curLevel, newLevel;
+
+ if (ah->tx_trig_level >= ah->config.max_txtrig_level)
+ return 0;
+
+ ath9k_hw_disable_interrupts(ah);
+
+ txcfg = REG_READ(ah, AR_TXCFG);
+ curLevel = MS(txcfg, AR_FTRIG);
+ newLevel = curLevel;
+ if (bIncTrigLevel) {
+ if (curLevel < ah->config.max_txtrig_level)
+ newLevel++;
+ } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
+ newLevel--;
+ if (newLevel != curLevel)
+ REG_WRITE(ah, AR_TXCFG,
+ (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
+
+ ath9k_hw_enable_interrupts(ah);
+
+ ah->tx_trig_level = newLevel;
+
+ return newLevel != curLevel;
+}
+
+void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
+{
+ int i, q;
+
+ REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
+
+ REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
+ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+ REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
+
+ for (q = 0; q < AR_NUM_QCU; q++) {
+ for (i = 0; i < 1000; i++) {
+ if (i)
+ udelay(5);
+
+ if (!ath9k_hw_numtxpending(ah, q))
+ break;
+ }
+ }
+
+ REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
+ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+ REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
+
+ REG_WRITE(ah, AR_Q_TXD, 0);
+}
+
+void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
+{
+ *txqs &= ah->intr_txqs;
+ ah->intr_txqs &= ~(*txqs);
+}
+
+int ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
+ const struct ath9k_tx_queue_info *qinfo)
+{
+ u32 cw;
+ struct ath9k_tx_queue_info *qi;
+
+ qi = &ah->txq[q];
+ if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ DBG("ath9k: "
+ "Set TXQ properties, inactive queue: %d\n", q);
+ return 0;
+ }
+
+ DBG2("ath9k: Set queue properties for: %d\n", q);
+
+ qi->tqi_ver = qinfo->tqi_ver;
+ qi->tqi_subtype = qinfo->tqi_subtype;
+ qi->tqi_qflags = qinfo->tqi_qflags;
+ qi->tqi_priority = qinfo->tqi_priority;
+ if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
+ qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
+ else
+ qi->tqi_aifs = INIT_AIFS;
+ if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
+ cw = min(qinfo->tqi_cwmin, 1024U);
+ qi->tqi_cwmin = 1;
+ while (qi->tqi_cwmin < cw)
+ qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
+ } else
+ qi->tqi_cwmin = qinfo->tqi_cwmin;
+ if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
+ cw = min(qinfo->tqi_cwmax, 1024U);
+ qi->tqi_cwmax = 1;
+ while (qi->tqi_cwmax < cw)
+ qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
+ } else
+ qi->tqi_cwmax = INIT_CWMAX;
+
+ if (qinfo->tqi_shretry != 0)
+ qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
+ else
+ qi->tqi_shretry = INIT_SH_RETRY;
+ if (qinfo->tqi_lgretry != 0)
+ qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
+ else
+ qi->tqi_lgretry = INIT_LG_RETRY;
+ qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
+ qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
+ qi->tqi_burstTime = qinfo->tqi_burstTime;
+ qi->tqi_readyTime = qinfo->tqi_readyTime;
+
+ return 1;
+}
+
+int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
+ const struct ath9k_tx_queue_info *qinfo)
+{
+ struct ath9k_tx_queue_info *qi;
+ int q;
+
+ for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++)
+ if (ah->txq[q].tqi_type ==
+ ATH9K_TX_QUEUE_INACTIVE)
+ break;
+ if (q == ATH9K_NUM_TX_QUEUES) {
+ DBG("No available TX queue\n");
+ return -1;
+ }
+
+ DBG2("ath9K: Setup TX queue: %d\n", q);
+
+ qi = &ah->txq[q];
+ if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
+ DBG("ath9k: TX queue: %d already active\n", q);
+ return -1;
+ }
+ memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
+ qi->tqi_type = type;
+ if (qinfo == NULL) {
+ qi->tqi_qflags =
+ TXQ_FLAG_TXOKINT_ENABLE
+ | TXQ_FLAG_TXERRINT_ENABLE
+ | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
+ qi->tqi_aifs = INIT_AIFS;
+ qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
+ qi->tqi_cwmax = INIT_CWMAX;
+ qi->tqi_shretry = INIT_SH_RETRY;
+ qi->tqi_lgretry = INIT_LG_RETRY;
+ qi->tqi_physCompBuf = 0;
+ } else {
+ qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
+ (void) ath9k_hw_set_txq_props(ah, q, qinfo);
+ }
+
+ return q;
+}
+
+int ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
+{
+ struct ath9k_tx_queue_info *qi;
+
+ qi = &ah->txq[q];
+ if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ DBG("ath9k: "
+ "Release TXQ, inactive queue: %d\n", q);
+ return 0;
+ }
+
+ DBG2("ath9k: Release TX queue: %d\n", q);
+
+ qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
+ ah->txok_interrupt_mask &= ~(1 << q);
+ ah->txerr_interrupt_mask &= ~(1 << q);
+ ah->txdesc_interrupt_mask &= ~(1 << q);
+ ah->txeol_interrupt_mask &= ~(1 << q);
+ ah->txurn_interrupt_mask &= ~(1 << q);
+ ath9k_hw_set_txq_interrupts(ah, qi);
+
+ return 1;
+}
+
+int ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
+{
+ struct ath9k_channel *chan = ah->curchan;
+ struct ath9k_tx_queue_info *qi;
+ u32 cwMin, chanCwMin, value __unused;
+
+ qi = &ah->txq[q];
+ if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ DBG("ath9k: "
+ "Reset TXQ, inactive queue: %d\n", q);
+ return 1;
+ }
+
+ DBG2("ath9k: Reset TX queue: %d\n", q);
+
+ if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
+ if (chan && IS_CHAN_B(chan))
+ chanCwMin = INIT_CWMIN_11B;
+ else
+ chanCwMin = INIT_CWMIN;
+
+ for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
+ } else
+ cwMin = qi->tqi_cwmin;
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_DLCL_IFS(q),
+ SM(cwMin, AR_D_LCL_IFS_CWMIN) |
+ SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
+ SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
+
+ REG_WRITE(ah, AR_DRETRY_LIMIT(q),
+ SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
+ SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
+ SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
+
+ REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
+
+ if (AR_SREV_9340(ah))
+ REG_WRITE(ah, AR_DMISC(q),
+ AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1);
+ else
+ REG_WRITE(ah, AR_DMISC(q),
+ AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
+
+ if (qi->tqi_cbrPeriod) {
+ REG_WRITE(ah, AR_QCBRCFG(q),
+ SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
+ SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
+ REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_FSP_CBR |
+ (qi->tqi_cbrOverflowLimit ?
+ AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
+ }
+ if (qi->tqi_readyTime) {
+ REG_WRITE(ah, AR_QRDYTIMECFG(q),
+ SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
+ AR_Q_RDYTIMECFG_EN);
+ }
+
+ REG_WRITE(ah, AR_DCHNTIME(q),
+ SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
+ (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
+
+ if (qi->tqi_burstTime
+ && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE))
+ REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_RDYTIME_EXP_POLICY);
+
+ if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE)
+ REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
+ REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_FRAG_BKOFF_EN);
+
+ if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
+ REG_SET_BIT(ah, AR_DMISC(q),
+ SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
+ AR_D_MISC_ARB_LOCKOUT_CNTRL) |
+ AR_D_MISC_POST_FR_BKOFF_DIS);
+ }
+
+ if (AR_SREV_9300_20_OR_LATER(ah))
+ REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN);
+
+ if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
+ ah->txok_interrupt_mask |= 1 << q;
+ else
+ ah->txok_interrupt_mask &= ~(1 << q);
+ if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
+ ah->txerr_interrupt_mask |= 1 << q;
+ else
+ ah->txerr_interrupt_mask &= ~(1 << q);
+ if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
+ ah->txdesc_interrupt_mask |= 1 << q;
+ else
+ ah->txdesc_interrupt_mask &= ~(1 << q);
+ if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
+ ah->txeol_interrupt_mask |= 1 << q;
+ else
+ ah->txeol_interrupt_mask &= ~(1 << q);
+ if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
+ ah->txurn_interrupt_mask |= 1 << q;
+ else
+ ah->txurn_interrupt_mask &= ~(1 << q);
+ ath9k_hw_set_txq_interrupts(ah, qi);
+
+ return 1;
+}
+
+int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
+ struct ath_rx_status *rs, u64 tsf __unused)
+{
+ struct ar5416_desc ads;
+ struct ar5416_desc *adsp = AR5416DESC(ds);
+ u32 phyerr;
+
+ if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
+ return -EINPROGRESS;
+
+ ads.u.rx = adsp->u.rx;
+
+ rs->rs_status = 0;
+ rs->rs_flags = 0;
+
+ rs->rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
+ rs->rs_tstamp = ads.AR_RcvTimestamp;
+
+ if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
+ rs->rs_rssi = ATH9K_RSSI_BAD;
+ rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
+ rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
+ rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
+ rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
+ rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
+ rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
+ } else {
+ rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
+ rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
+ AR_RxRSSIAnt00);
+ rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
+ AR_RxRSSIAnt01);
+ rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
+ AR_RxRSSIAnt02);
+ rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
+ AR_RxRSSIAnt10);
+ rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
+ AR_RxRSSIAnt11);
+ rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
+ AR_RxRSSIAnt12);
+ }
+ if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
+ rs->rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
+ else
+ rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
+
+ rs->rs_rate = RXSTATUS_RATE(ah, (&ads));
+ rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
+
+ rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
+ rs->rs_moreaggr =
+ (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
+ rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
+ rs->rs_flags =
+ (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
+ rs->rs_flags |=
+ (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
+
+ if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
+ rs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
+ if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
+ rs->rs_flags |= ATH9K_RX_DELIM_CRC_POST;
+ if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
+ rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
+
+ if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
+ /*
+ * Treat these errors as mutually exclusive to avoid spurious
+ * extra error reports from the hardware. If a CRC error is
+ * reported, then decryption and MIC errors are irrelevant,
+ * the frame is going to be dropped either way
+ */
+ if (ads.ds_rxstatus8 & AR_CRCErr)
+ rs->rs_status |= ATH9K_RXERR_CRC;
+ else if (ads.ds_rxstatus8 & AR_PHYErr) {
+ rs->rs_status |= ATH9K_RXERR_PHY;
+ phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
+ rs->rs_phyerr = phyerr;
+ } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
+ rs->rs_status |= ATH9K_RXERR_DECRYPT;
+ else if (ads.ds_rxstatus8 & AR_MichaelErr)
+ rs->rs_status |= ATH9K_RXERR_MIC;
+ else if (ads.ds_rxstatus8 & AR_KeyMiss)
+ rs->rs_status |= ATH9K_RXERR_DECRYPT;
+ }
+
+ return 0;
+}
+
+/*
+ * This can stop or re-enables RX.
+ *
+ * If bool is set this will kill any frame which is currently being
+ * transferred between the MAC and baseband and also prevent any new
+ * frames from getting started.
+ */
+int ath9k_hw_setrxabort(struct ath_hw *ah, int set)
+{
+ u32 reg;
+
+ if (set) {
+ REG_SET_BIT(ah, AR_DIAG_SW,
+ (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+ if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE,
+ 0, AH_WAIT_TIMEOUT)) {
+ REG_CLR_BIT(ah, AR_DIAG_SW,
+ (AR_DIAG_RX_DIS |
+ AR_DIAG_RX_ABORT));
+
+ reg = REG_READ(ah, AR_OBS_BUS_1);
+ DBG("ath9k: "
+ "RX failed to go idle in 10 ms RXSM=0x%x\n",
+ reg);
+
+ return 0;
+ }
+ } else {
+ REG_CLR_BIT(ah, AR_DIAG_SW,
+ (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+ }
+
+ return 1;
+}
+
+void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)
+{
+ REG_WRITE(ah, AR_RXDP, rxdp);
+}
+
+void ath9k_hw_startpcureceive(struct ath_hw *ah, int is_scanning)
+{
+ ath9k_ani_reset(ah, is_scanning);
+
+ REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+}
+
+void ath9k_hw_abortpcurecv(struct ath_hw *ah)
+{
+ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
+}
+
+int ath9k_hw_stopdmarecv(struct ath_hw *ah, int *reset)
+{
+#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
+ u32 mac_status, last_mac_status = 0;
+ int i;
+
+ /* Enable access to the DMA observation bus */
+ REG_WRITE(ah, AR_MACMISC,
+ ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+ (AR_MACMISC_MISC_OBS_BUS_1 <<
+ AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
+ REG_WRITE(ah, AR_CR, AR_CR_RXD);
+
+ /* Wait for rx enable bit to go low */
+ for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
+ if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
+ break;
+
+ if (!AR_SREV_9300_20_OR_LATER(ah)) {
+ mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0;
+ if (mac_status == 0x1c0 && mac_status == last_mac_status) {
+ *reset = 1;
+ break;
+ }
+
+ last_mac_status = mac_status;
+ }
+
+ udelay(AH_TIME_QUANTUM);
+ }
+
+ if (i == 0) {
+ DBG("ath9k: "
+ "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",
+ AH_RX_STOP_DMA_TIMEOUT / 1000,
+ REG_READ(ah, AR_CR),
+ REG_READ(ah, AR_DIAG_SW),
+ REG_READ(ah, AR_DMADBG_7));
+ return 0;
+ } else {
+ return 1;
+ }
+
+#undef AH_RX_STOP_DMA_TIMEOUT
+}
+
+int ath9k_hw_intrpend(struct ath_hw *ah)
+{
+ u32 host_isr;
+
+ if (AR_SREV_9100(ah) || !(ah->ah_ier & AR_IER_ENABLE))
+ return 1;
+
+ host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
+ if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS))
+ return 1;
+
+ host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
+ if ((host_isr & AR_INTR_SYNC_DEFAULT)
+ && (host_isr != AR_INTR_SPURIOUS))
+ return 1;
+
+ return 0;
+}
+
+void ath9k_hw_disable_interrupts(struct ath_hw *ah)
+{
+ DBG2("ath9k: disable IER\n");
+ REG_WRITE(ah, AR_IER, ah->ah_ier);
+ (void) REG_READ(ah, AR_IER);
+ if (!AR_SREV_9100(ah)) {
+ REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
+ (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
+
+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+ (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
+ }
+}
+
+void ath9k_hw_enable_interrupts(struct ath_hw *ah)
+{
+ u32 sync_default = AR_INTR_SYNC_DEFAULT;
+
+ if (!(ah->imask & ATH9K_INT_GLOBAL))
+ return;
+
+ if (AR_SREV_9340(ah))
+ sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
+
+ DBG2("ath9k: enable IER\n");
+ REG_WRITE(ah, AR_IER, ah->ah_ier);
+ if (!AR_SREV_9100(ah)) {
+ REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
+ AR_INTR_MAC_IRQ);
+ REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
+
+
+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default);
+ REG_WRITE(ah, AR_INTR_SYNC_MASK, sync_default);
+ }
+ DBG2("ath9k: AR_IMR 0x%x IER 0x%x\n",
+ REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
+}
+
+void ath9k_hw_set_interrupts(struct ath_hw *ah, unsigned int ints)
+{
+ enum ath9k_int omask = ah->imask;
+ u32 mask, mask2;
+ struct ath9k_hw_capabilities *pCap = &ah->caps;
+
+ if (!(ints & ATH9K_INT_GLOBAL))
+ ath9k_hw_disable_interrupts(ah);
+
+ DBG2("ath9k: 0x%x => 0x%x\n", omask, ints);
+
+ /* TODO: global int Ref count */
+ mask = ints & ATH9K_INT_COMMON;
+ mask2 = 0;
+
+ if (ints & ATH9K_INT_TX) {
+ if (ah->config.tx_intr_mitigation)
+ mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
+ else {
+ if (ah->txok_interrupt_mask)
+ mask |= AR_IMR_TXOK;
+ if (ah->txdesc_interrupt_mask)
+ mask |= AR_IMR_TXDESC;
+ }
+ if (ah->txerr_interrupt_mask)
+ mask |= AR_IMR_TXERR;
+ if (ah->txeol_interrupt_mask)
+ mask |= AR_IMR_TXEOL;
+ }
+ if (ints & ATH9K_INT_RX) {
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;
+ if (ah->config.rx_intr_mitigation) {
+ mask &= ~AR_IMR_RXOK_LP;
+ mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
+ } else {
+ mask |= AR_IMR_RXOK_LP;
+ }
+ } else {
+ if (ah->config.rx_intr_mitigation)
+ mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
+ else
+ mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
+ }
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+ mask |= AR_IMR_GENTMR;
+ }
+
+ if (ints & ATH9K_INT_GENTIMER)
+ mask |= AR_IMR_GENTMR;
+
+ if (ints & (ATH9K_INT_BMISC)) {
+ mask |= AR_IMR_BCNMISC;
+ if (ints & ATH9K_INT_TIM)
+ mask2 |= AR_IMR_S2_TIM;
+ if (ints & ATH9K_INT_DTIM)
+ mask2 |= AR_IMR_S2_DTIM;
+ if (ints & ATH9K_INT_DTIMSYNC)
+ mask2 |= AR_IMR_S2_DTIMSYNC;
+ if (ints & ATH9K_INT_CABEND)
+ mask2 |= AR_IMR_S2_CABEND;
+ if (ints & ATH9K_INT_TSFOOR)
+ mask2 |= AR_IMR_S2_TSFOOR;
+ }
+
+ if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
+ mask |= AR_IMR_BCNMISC;
+ if (ints & ATH9K_INT_GTT)
+ mask2 |= AR_IMR_S2_GTT;
+ if (ints & ATH9K_INT_CST)
+ mask2 |= AR_IMR_S2_CST;
+ }
+
+ DBG2("ath9k: new IMR 0x%x\n", mask);
+ REG_WRITE(ah, AR_IMR, mask);
+ ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
+ AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
+ AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
+ ah->imrs2_reg |= mask2;
+ REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+ if (ints & ATH9K_INT_TIM_TIMER)
+ REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
+ else
+ REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
+ }
+
+ if (ints & ATH9K_INT_GLOBAL)
+ ath9k_hw_enable_interrupts(ah);
+
+ return;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_main.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_main.c
new file mode 100644
index 00000000..0a17b9bc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_main.c
@@ -0,0 +1,916 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+
+#include "ath9k.h"
+
+static void ath9k_bss_info_changed(struct net80211_device *dev, u32 changed);
+
+int ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
+{
+ int ret;
+
+ ret = ath9k_hw_setpower(sc->sc_ah, mode);
+
+ return ret;
+}
+
+static void ath_start_ani(struct ath_common *common)
+{
+ struct ath_hw *ah = common->ah;
+ unsigned long timestamp = ( currticks() * 1000 ) / TICKS_PER_SEC;
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+
+ if (!(sc->sc_flags & SC_OP_ANI_RUN))
+ return;
+
+ if (sc->sc_flags & SC_OP_OFFCHANNEL)
+ return;
+
+ common->ani.longcal_timer = timestamp;
+ common->ani.shortcal_timer = timestamp;
+ common->ani.checkani_timer = timestamp;
+
+ common->ani.timer = timestamp + ah->config.ani_poll_interval;
+}
+
+static void ath_update_survey_nf(struct ath_softc *sc, int channel)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_channel *chan = &ah->channels[channel];
+ struct survey_info *survey = &sc->survey[channel];
+
+ if (chan->noisefloor) {
+ survey->filled |= SURVEY_INFO_NOISE_DBM;
+ survey->noise = chan->noisefloor;
+ }
+}
+
+/*
+ * Updates the survey statistics and returns the busy time since last
+ * update in %, if the measurement duration was long enough for the
+ * result to be useful, -1 otherwise.
+ */
+static int ath_update_survey_stats(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ int pos = ah->curchan - &ah->channels[0];
+ struct survey_info *survey = &sc->survey[pos];
+ struct ath_cycle_counters *cc = &common->cc_survey;
+ unsigned int div = common->clockrate * 1000;
+ int ret = 0;
+
+ if (!ah->curchan)
+ return -1;
+
+ if (ah->power_mode == ATH9K_PM_AWAKE)
+ ath_hw_cycle_counters_update(common);
+
+ if (cc->cycles > 0) {
+ survey->filled |= SURVEY_INFO_CHANNEL_TIME |
+ SURVEY_INFO_CHANNEL_TIME_BUSY |
+ SURVEY_INFO_CHANNEL_TIME_RX |
+ SURVEY_INFO_CHANNEL_TIME_TX;
+ survey->channel_time += cc->cycles / div;
+ survey->channel_time_busy += cc->rx_busy / div;
+ survey->channel_time_rx += cc->rx_frame / div;
+ survey->channel_time_tx += cc->tx_frame / div;
+ }
+
+ if (cc->cycles < div)
+ return -1;
+
+ if (cc->cycles > 0)
+ ret = cc->rx_busy * 100 / cc->cycles;
+
+ memset(cc, 0, sizeof(*cc));
+
+ ath_update_survey_nf(sc, pos);
+
+ return ret;
+}
+
+/*
+ * Set/change channels. If the channel is really being changed, it's done
+ * by reseting the chip. To accomplish this we must first cleanup any pending
+ * DMA, then restart stuff.
+*/
+int ath_set_channel(struct ath_softc *sc, struct net80211_device *dev,
+ struct ath9k_channel *hchan)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ int fastcc __unused = 1, stopped __unused;
+ struct net80211_channel *channel = dev->channels + dev->channel;
+ struct ath9k_hw_cal_data *caldata = NULL;
+ int r;
+
+ if (sc->sc_flags & SC_OP_INVALID)
+ return -EIO;
+
+ sc->hw_busy_count = 0;
+
+ common->ani.timer = 0;
+ sc->tx_complete_work_timer = 0;
+ sc->hw_pll_work_timer = 0;
+
+ /*
+ * This is only performed if the channel settings have
+ * actually changed.
+ *
+ * To switch channels clear any pending DMA operations;
+ * wait long enough for the RX fifo to drain, reset the
+ * hardware at the new frequency, and then re-enable
+ * the relevant bits of the h/w.
+ */
+ ath9k_hw_disable_interrupts(ah);
+ stopped = ath_drain_all_txq(sc, 0);
+
+ if (!ath_stoprecv(sc))
+ stopped = 0;
+
+ if (!ath9k_hw_check_alive(ah))
+ stopped = 0;
+
+ /* XXX: do not flush receive queue here. We don't want
+ * to flush data frames already in queue because of
+ * changing channel. */
+
+ if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
+ caldata = &sc->caldata;
+
+ DBG2("ath9k: "
+ "(%d MHz) -> (%d MHz)\n",
+ sc->sc_ah->curchan->channel,
+ channel->center_freq);
+
+ r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
+ if (r) {
+ DBG("ath9k: "
+ "Unable to reset channel (%d MHz), reset status %d\n",
+ channel->center_freq, r);
+ goto ps_restore;
+ }
+
+ if (ath_startrecv(sc) != 0) {
+ DBG("ath9k: Unable to restart recv logic\n");
+ r = -EIO;
+ goto ps_restore;
+ }
+
+ ath9k_cmn_update_txpow(ah, sc->curtxpow,
+ sc->config.txpowlimit, &sc->curtxpow);
+ ath9k_hw_set_interrupts(ah, ah->imask);
+
+ if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
+ sc->tx_complete_work(sc);
+ sc->hw_pll_work_timer = (currticks() * 1000 ) / TICKS_PER_SEC + 500;
+ ath_start_ani(common);
+ }
+
+ ps_restore:
+ return r;
+}
+
+/*
+ * This routine performs the periodic noise floor calibration function
+ * that is used to adjust and optimize the chip performance. This
+ * takes environmental changes (location, temperature) into account.
+ * When the task is complete, it reschedules itself depending on the
+ * appropriate interval that was calculated.
+ */
+void ath_ani_calibrate(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ int longcal = 0;
+ int shortcal = 0;
+ int aniflag = 0;
+ unsigned int timestamp = (currticks() * 1000 ) / TICKS_PER_SEC;
+ u32 cal_interval, short_cal_interval, long_cal_interval;
+
+ if (ah->caldata && ah->caldata->nfcal_interference)
+ long_cal_interval = ATH_LONG_CALINTERVAL_INT;
+ else
+ long_cal_interval = ATH_LONG_CALINTERVAL;
+
+ short_cal_interval = ATH_STA_SHORT_CALINTERVAL;
+
+ /* Only calibrate if awake */
+ if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE)
+ goto set_timer;
+
+ /* Long calibration runs independently of short calibration. */
+ if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) {
+ longcal = 1;
+ DBG2("ath9k: longcal @%d\n", timestamp);
+ common->ani.longcal_timer = timestamp;
+ }
+
+ /* Short calibration applies only while caldone is false */
+ if (!common->ani.caldone) {
+ if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) {
+ shortcal = 1;
+ DBG2("ath9k: "
+ "shortcal @%d\n", timestamp);
+ common->ani.shortcal_timer = timestamp;
+ common->ani.resetcal_timer = timestamp;
+ }
+ } else {
+ if ((timestamp - common->ani.resetcal_timer) >=
+ ATH_RESTART_CALINTERVAL) {
+ common->ani.caldone = ath9k_hw_reset_calvalid(ah);
+ if (common->ani.caldone)
+ common->ani.resetcal_timer = timestamp;
+ }
+ }
+
+ /* Verify whether we must check ANI */
+ if ((timestamp - common->ani.checkani_timer) >=
+ ah->config.ani_poll_interval) {
+ aniflag = 1;
+ common->ani.checkani_timer = timestamp;
+ }
+
+ /* Skip all processing if there's nothing to do. */
+ if (longcal || shortcal || aniflag) {
+ /* Call ANI routine if necessary */
+ if (aniflag) {
+ ath9k_hw_ani_monitor(ah, ah->curchan);
+ ath_update_survey_stats(sc);
+ }
+
+ /* Perform calibration if necessary */
+ if (longcal || shortcal) {
+ common->ani.caldone =
+ ath9k_hw_calibrate(ah,
+ ah->curchan,
+ common->rx_chainmask,
+ longcal);
+ }
+ }
+
+set_timer:
+ /*
+ * Set timer interval based on previous results.
+ * The interval must be the shortest necessary to satisfy ANI,
+ * short calibration and long calibration.
+ */
+ cal_interval = ATH_LONG_CALINTERVAL;
+ if (sc->sc_ah->config.enable_ani)
+ cal_interval = min(cal_interval,
+ (u32)ah->config.ani_poll_interval);
+ if (!common->ani.caldone)
+ cal_interval = min(cal_interval, (u32)short_cal_interval);
+
+ common->ani.timer = timestamp + cal_interval;
+}
+
+void ath_hw_check(struct ath_softc *sc)
+{
+ int busy;
+
+ if (ath9k_hw_check_alive(sc->sc_ah))
+ goto out;
+
+ busy = ath_update_survey_stats(sc);
+
+ DBG("ath9k: Possible baseband hang, "
+ "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
+ if (busy >= 99) {
+ if (++sc->hw_busy_count >= 3)
+ ath_reset(sc, 1);
+ } else if (busy >= 0)
+ sc->hw_busy_count = 0;
+
+out:
+ return;
+}
+
+static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
+{
+ static int count;
+
+ if (pll_sqsum >= 0x40000) {
+ count++;
+ if (count == 3) {
+ /* Rx is hung for more than 500ms. Reset it */
+ DBG("ath9k: "
+ "Possible RX hang, resetting");
+ ath_reset(sc, 1);
+ count = 0;
+ }
+ } else
+ count = 0;
+}
+
+void ath_hw_pll_work(struct ath_softc *sc)
+{
+ u32 pll_sqsum;
+
+ if (AR_SREV_9485(sc->sc_ah)) {
+ pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
+
+ ath_hw_pll_rx_hang_check(sc, pll_sqsum);
+
+ sc->hw_pll_work_timer = (currticks() * 1000 ) / TICKS_PER_SEC + 200;
+ }
+}
+
+
+void ath9k_tasklet(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+
+ u32 status = sc->intrstatus;
+ u32 rxmask;
+
+ if ((status & ATH9K_INT_FATAL) ||
+ (status & ATH9K_INT_BB_WATCHDOG)) {
+ ath_reset(sc, 1);
+ return;
+ }
+
+ rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+
+ if (status & rxmask) {
+ ath_rx_tasklet(sc, 0, 0);
+ }
+
+ if (status & ATH9K_INT_TX) {
+ ath_tx_tasklet(sc);
+ }
+
+ /* re-enable hardware interrupt */
+ ath9k_hw_enable_interrupts(ah);
+}
+
+void ath_isr(struct net80211_device *dev)
+{
+#define SCHED_INTR ( \
+ ATH9K_INT_FATAL | \
+ ATH9K_INT_BB_WATCHDOG | \
+ ATH9K_INT_RXORN | \
+ ATH9K_INT_RXEOL | \
+ ATH9K_INT_RX | \
+ ATH9K_INT_RXLP | \
+ ATH9K_INT_RXHP | \
+ ATH9K_INT_TX | \
+ ATH9K_INT_BMISS | \
+ ATH9K_INT_CST | \
+ ATH9K_INT_TSFOOR | \
+ ATH9K_INT_GENTIMER)
+
+ struct ath_softc *sc = dev->priv;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ enum ath9k_int status;
+ unsigned long timestamp = (currticks() * 1000 ) / TICKS_PER_SEC;
+ int sched = 0;
+
+ /*
+ * The hardware is not ready/present, don't
+ * touch anything. Note this can happen early
+ * on if the IRQ is shared.
+ */
+ if (sc->sc_flags & SC_OP_INVALID)
+ return;
+
+
+ /* Check calibration */
+ if(timestamp >= (unsigned int)common->ani.timer && common->ani.timer)
+ ath_ani_calibrate(sc);
+
+ /* Check tx_complete_work */
+ if(timestamp >= (unsigned int)sc->tx_complete_work_timer && sc->tx_complete_work_timer)
+ sc->tx_complete_work(sc);
+
+ /* Check hw_pll_work */
+ if(timestamp >= (unsigned int)sc->hw_pll_work_timer && sc->hw_pll_work_timer)
+ sc->hw_pll_work(sc);
+
+ /* shared irq, not for us */
+
+ if (!ath9k_hw_intrpend(ah))
+ return;
+
+ /*
+ * Figure out the reason(s) for the interrupt. Note
+ * that the hal returns a pseudo-ISR that may include
+ * bits we haven't explicitly enabled so we mask the
+ * value to insure we only process bits we requested.
+ */
+ ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */
+ status &= ah->imask; /* discard unasked-for bits */
+
+ /*
+ * If there are no status bits set, then this interrupt was not
+ * for me (should have been caught above).
+ */
+ if (!status)
+ return;
+
+ /* Cache the status */
+ sc->intrstatus = status;
+
+ if (status & SCHED_INTR)
+ sched = 1;
+
+ /*
+ * If a FATAL or RXORN interrupt is received, we have to reset the
+ * chip immediately.
+ */
+ if ((status & ATH9K_INT_FATAL) || (status & ATH9K_INT_RXORN))
+ goto chip_reset;
+
+ if (status & ATH9K_INT_TXURN)
+ ath9k_hw_updatetxtriglevel(ah, 1);
+
+ if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+ if (status & ATH9K_INT_TIM_TIMER) {
+ if (sc->ps_idle)
+ goto chip_reset;
+ /* Clear RxAbort bit so that we can
+ * receive frames */
+ ath9k_setpower(sc, ATH9K_PM_AWAKE);
+ ath9k_hw_setrxabort(sc->sc_ah, 0);
+ sc->ps_flags |= PS_WAIT_FOR_BEACON;
+ }
+
+chip_reset:
+
+ if (sched) {
+ /* turn off every interrupt */
+ ath9k_hw_disable_interrupts(ah);
+ sc->intr_tq(sc);
+ }
+
+ return;
+
+#undef SCHED_INTR
+}
+
+void ath_radio_disable(struct ath_softc *sc, struct net80211_device *dev)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct net80211_channel *channel = dev->channels + dev->channel;
+ int r;
+
+ sc->hw_pll_work_timer = 0;
+
+ /*
+ * Keep the LED on when the radio is disabled
+ * during idle unassociated state.
+ */
+ if (!sc->ps_idle) {
+ ath9k_hw_set_gpio(ah, ah->led_pin, 1);
+ ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
+ }
+
+ /* Disable interrupts */
+ ath9k_hw_disable_interrupts(ah);
+
+ ath_drain_all_txq(sc, 0); /* clear pending tx frames */
+
+ ath_stoprecv(sc); /* turn off frame recv */
+ ath_flushrecv(sc); /* flush recv queue */
+
+ if (!ah->curchan)
+ ah->curchan = ath9k_cmn_get_curchannel(dev, ah);
+
+ r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, 0);
+ if (r) {
+ DBG("ath9k: "
+ "Unable to reset channel (%d MHz), reset status %d\n",
+ channel->center_freq, r);
+ }
+
+ ath9k_hw_phy_disable(ah);
+
+ ath9k_hw_configpcipowersave(ah, 1, 1);
+}
+
+int ath_reset(struct ath_softc *sc, int retry_tx)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ int r;
+
+ sc->hw_busy_count = 0;
+
+ /* Stop ANI */
+ common->ani.timer = 0;
+
+ ath9k_hw_disable_interrupts(ah);
+ ath_drain_all_txq(sc, retry_tx);
+
+ ath_stoprecv(sc);
+ ath_flushrecv(sc);
+
+ r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, 0);
+ if (r)
+ DBG("ath9k: "
+ "Unable to reset hardware; reset status %d\n", r);
+
+ if (ath_startrecv(sc) != 0)
+ DBG("ath9k: Unable to start recv logic\n");
+
+ /*
+ * We may be doing a reset in response to a request
+ * that changes the channel so update any state that
+ * might change as a result.
+ */
+ ath9k_cmn_update_txpow(ah, sc->curtxpow,
+ sc->config.txpowlimit, &sc->curtxpow);
+
+ ath9k_hw_set_interrupts(ah, ah->imask);
+
+ if (retry_tx) {
+ int i;
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (ATH_TXQ_SETUP(sc, i)) {
+ ath_txq_schedule(sc, &sc->tx.txq[i]);
+ }
+ }
+ }
+
+ /* Start ANI */
+ ath_start_ani(common);
+
+ return r;
+}
+
+/**********************/
+/* mac80211 callbacks */
+/**********************/
+
+static int ath9k_start(struct net80211_device *dev)
+{
+ struct ath_softc *sc = dev->priv;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct net80211_channel *curchan = dev->channels + dev->channel;
+ struct ath9k_channel *init_channel;
+ int r;
+
+ DBG("ath9k: "
+ "Starting driver with initial channel: %d MHz\n",
+ curchan->center_freq);
+
+ /* setup initial channel */
+ sc->chan_idx = curchan->hw_value;
+
+ init_channel = ath9k_cmn_get_curchannel(dev, ah);
+
+ /* Reset SERDES registers */
+ ath9k_hw_configpcipowersave(ah, 0, 0);
+
+ /*
+ * The basic interface to setting the hardware in a good
+ * state is ``reset''. On return the hardware is known to
+ * be powered up and with interrupts disabled. This must
+ * be followed by initialization of the appropriate bits
+ * and then setup of the interrupt mask.
+ */
+ r = ath9k_hw_reset(ah, init_channel, ah->caldata, 0);
+ if (r) {
+ DBG("ath9k: "
+ "Unable to reset hardware; reset status %d (freq %d MHz)\n",
+ r, curchan->center_freq);
+ goto mutex_unlock;
+ }
+
+ /*
+ * This is needed only to setup initial state
+ * but it's best done after a reset.
+ */
+ ath9k_cmn_update_txpow(ah, sc->curtxpow,
+ sc->config.txpowlimit, &sc->curtxpow);
+
+ /*
+ * Setup the hardware after reset:
+ * The receive engine is set going.
+ * Frame transmit is handled entirely
+ * in the frame output path; there's nothing to do
+ * here except setup the interrupt mask.
+ */
+ if (ath_startrecv(sc) != 0) {
+ DBG("ath9k: Unable to start recv logic\n");
+ r = -EIO;
+ goto mutex_unlock;
+ }
+
+ /* Setup our intr mask. */
+ ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
+ ATH9K_INT_RXORN | ATH9K_INT_FATAL |
+ ATH9K_INT_GLOBAL;
+
+ ah->imask |= ATH9K_INT_RX;
+
+ sc->sc_flags &= ~SC_OP_INVALID;
+ sc->sc_ah->is_monitoring = 0;
+
+ ath9k_hw_set_interrupts(ah, ah->imask);
+
+ sc->tx_complete_work(sc);
+
+ if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
+ common->bus_ops->extn_synch_en(common);
+
+mutex_unlock:
+ return r;
+}
+
+static int ath9k_tx(struct net80211_device *dev, struct io_buffer *iob)
+{
+ struct ath_softc *sc = dev->priv;
+ struct ath_tx_control txctl;
+ int ret = 0;
+
+ memset(&txctl, 0, sizeof(struct ath_tx_control));
+ txctl.txq = sc->tx.txq_map[0];
+
+ DBGIO("ath9k: transmitting packet, iob: %p\n", iob);
+
+ ret = ath_tx_start(dev, iob, &txctl);
+ if (ret) {
+ DBG("ath9k: TX failed\n");
+ goto exit;
+ }
+
+ return ret;
+exit:
+ free_iob(iob);
+ return ret;
+}
+
+static void ath9k_stop(struct net80211_device *dev)
+{
+ struct ath_softc *sc = dev->priv;
+ struct ath_hw *ah = sc->sc_ah;
+
+ sc->tx_complete_work_timer = 0;
+ sc->hw_pll_work_timer = 0;
+
+ if (sc->sc_flags & SC_OP_INVALID) {
+ DBG("ath9k: Device not present\n");
+ return;
+ }
+
+ /* prevent tasklets to enable interrupts once we disable them */
+ ah->imask &= ~ATH9K_INT_GLOBAL;
+
+ /* make sure h/w will not generate any interrupt
+ * before setting the invalid flag. */
+ ath9k_hw_disable_interrupts(ah);
+
+ if (!(sc->sc_flags & SC_OP_INVALID)) {
+ ath_drain_all_txq(sc, 0);
+ ath_stoprecv(sc);
+ ath9k_hw_phy_disable(ah);
+ } else
+ sc->rx.rxlink = NULL;
+
+ if (sc->rx.frag) {
+ free_iob(sc->rx.frag);
+ sc->rx.frag = NULL;
+ }
+
+ /* disable HAL and put h/w to sleep */
+ ath9k_hw_disable(ah);
+ ath9k_hw_configpcipowersave(ah, 1, 1);
+
+ ath_radio_disable(sc, dev);
+
+ sc->sc_flags |= SC_OP_INVALID;
+
+ DBG("ath9k: Driver halt\n");
+}
+
+static int ath9k_config(struct net80211_device *dev, int changed)
+{
+ struct ath_softc *sc = dev->priv;
+ struct ath_hw *ah = sc->sc_ah;
+
+ if ((changed & NET80211_CFG_RATE) ||
+ (changed & NET80211_CFG_PHY_PARAMS)) {
+ int spmbl = (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ? IEEE80211_TX_RC_USE_SHORT_PREAMBLE : 0;
+ u16 rate = dev->rates[dev->rate];
+ u16 slowrate = dev->rates[dev->rtscts_rate];
+ int i;
+
+ for (i = 0; i < NET80211_MAX_RATES; i++) {
+ if (sc->rates[i].bitrate == rate &&
+ (sc->rates[i].flags & spmbl))
+ sc->hw_rix = i;
+
+ if (sc->rates[i].bitrate == slowrate &&
+ (sc->rates[i].flags & spmbl))
+ sc->hw_rix = i;
+ }
+ }
+
+ ath9k_bss_info_changed(dev, changed);
+
+ if (changed & NET80211_CFG_CHANNEL) {
+ struct net80211_channel *curchan = dev->channels + dev->channel;
+ int pos = curchan->hw_value;
+ int old_pos = -1;
+
+ if (ah->curchan)
+ old_pos = ah->curchan - &ah->channels[0];
+
+ sc->sc_flags &= ~SC_OP_OFFCHANNEL;
+
+ DBG2("ath9k: "
+ "Set channel: %d MHz\n",
+ curchan->center_freq);
+
+ ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
+ curchan);
+
+ /* update survey stats for the old channel before switching */
+ ath_update_survey_stats(sc);
+
+ /*
+ * If the operating channel changes, change the survey in-use flags
+ * along with it.
+ * Reset the survey data for the new channel, unless we're switching
+ * back to the operating channel from an off-channel operation.
+ */
+ if (sc->cur_survey != &sc->survey[pos]) {
+
+ if (sc->cur_survey)
+ sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
+
+ sc->cur_survey = &sc->survey[pos];
+
+ memset(sc->cur_survey, 0, sizeof(struct survey_info));
+ sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
+ } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
+ memset(&sc->survey[pos], 0, sizeof(struct survey_info));
+ }
+
+ if (ath_set_channel(sc, dev, &sc->sc_ah->channels[pos]) < 0) {
+ DBG("ath9k: Unable to set channel\n");
+ return -EINVAL;
+ }
+
+ /*
+ * The most recent snapshot of channel->noisefloor for the old
+ * channel is only available after the hardware reset. Copy it to
+ * the survey stats now.
+ */
+ if (old_pos >= 0)
+ ath_update_survey_nf(sc, old_pos);
+ }
+
+ if (changed & NET80211_CFG_CHANNEL) {
+ DBG2("ath9k: "
+ "Set power: %d\n", (dev->channels + dev->channel)->maxpower);
+ sc->config.txpowlimit = 2 * (dev->channels + dev->channel)->maxpower;
+ ath9k_cmn_update_txpow(ah, sc->curtxpow,
+ sc->config.txpowlimit, &sc->curtxpow);
+ }
+
+ return 0;
+}
+
+static void ath9k_bss_iter(struct ath_softc *sc)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+ if (common->dev->state & NET80211_ASSOCIATED) {
+ sc->sc_flags |= SC_OP_PRIM_STA_VIF;
+ memcpy(common->curbssid, common->dev->bssid, ETH_ALEN);
+ common->curaid = common->dev->aid;
+ ath9k_hw_write_associd(sc->sc_ah);
+ DBG("ath9k: "
+ "Bss Info ASSOC %d, bssid: %pM\n",
+ common->dev->aid, common->curbssid);
+
+ /*
+ * Request a re-configuration of Beacon related timers
+ * on the receipt of the first Beacon frame (i.e.,
+ * after time sync with the AP).
+ */
+ sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
+ /* Reset rssi stats */
+ sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+
+ sc->sc_flags |= SC_OP_ANI_RUN;
+ ath_start_ani(common);
+ }
+}
+
+static void ath9k_config_bss(struct ath_softc *sc)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct net80211_device *dev = common->dev;
+
+ /* Reconfigure bss info */
+ if (!(dev->state & NET80211_ASSOCIATED)) {
+ DBG2("ath9k: "
+ "ath9k: Bss Info DISASSOC %d, bssid %pM\n",
+ common->curaid, common->curbssid);
+ sc->sc_flags &= ~(SC_OP_PRIM_STA_VIF | SC_OP_BEACONS);
+ memset(common->curbssid, 0, ETH_ALEN);
+ common->curaid = 0;
+ }
+
+ ath9k_bss_iter(sc);
+
+ /*
+ * None of station vifs are associated.
+ * Clear bssid & aid
+ */
+ if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {
+ ath9k_hw_write_associd(sc->sc_ah);
+ /* Stop ANI */
+ sc->sc_flags &= ~SC_OP_ANI_RUN;
+ common->ani.timer = 0;
+ }
+}
+
+static void ath9k_bss_info_changed(struct net80211_device *dev,
+ u32 changed)
+{
+ struct ath_softc *sc = dev->priv;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ int slottime;
+
+ if (changed & NET80211_CFG_ASSOC) {
+ ath9k_config_bss(sc);
+
+ DBG2("ath9k: BSSID: %pM aid: 0x%x\n",
+ common->curbssid, common->curaid);
+ }
+
+ if (changed & NET80211_CFG_PHY_PARAMS) {
+ if (dev->phy_flags & NET80211_PHY_USE_PROTECTION)
+ slottime = 9;
+ else
+ slottime = 20;
+ ah->slottime = slottime;
+ ath9k_hw_init_global_settings(ah);
+
+ DBG2("ath9k: BSS Changed PREAMBLE %d\n",
+ !!(dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE));
+ if (dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE)
+ sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
+ else
+ sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
+
+ DBG2("ath9k: BSS Changed CTS PROT %d\n",
+ !!(dev->phy_flags & NET80211_PHY_USE_PROTECTION));
+ if ((dev->phy_flags & NET80211_PHY_USE_PROTECTION) &&
+ (dev->channels + dev->channel)->band != NET80211_BAND_5GHZ)
+ sc->sc_flags |= SC_OP_PROTECT_ENABLE;
+ else
+ sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
+ }
+}
+
+static void ath9k_poll(struct net80211_device *dev)
+{
+ ath_isr(dev);
+}
+
+static void ath9k_irq(struct net80211_device *dev, int enable)
+{
+ struct ath_softc *sc = dev->priv;
+ struct ath_hw *ah = sc->sc_ah;
+
+ ah->ah_ier = enable ? AR_IER_ENABLE : AR_IER_DISABLE;
+
+ ath9k_hw_set_interrupts(ah, ah->imask);
+}
+
+struct net80211_device_operations ath9k_ops = {
+ .transmit = ath9k_tx,
+ .open = ath9k_start,
+ .close = ath9k_stop,
+ .config = ath9k_config,
+ .poll = ath9k_poll,
+ .irq = ath9k_irq,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_recv.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_recv.c
new file mode 100644
index 00000000..ba363c67
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_recv.c
@@ -0,0 +1,521 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+
+#include "ath9k.h"
+#include "ar9003_mac.h"
+
+/*
+ * Setup and link descriptors.
+ *
+ * 11N: we can no longer afford to self link the last descriptor.
+ * MAC acknowledges BA status as long as it copies frames to host
+ * buffer (or rx fifo). This can incorrectly acknowledge packets
+ * to a sender if last desc is self-linked.
+ */
+static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath_desc *ds;
+// struct io_buffer *iob;
+
+ ATH_RXBUF_RESET(bf);
+
+ ds = bf->bf_desc;
+ ds->ds_link = 0; /* link to null */
+ ds->ds_data = bf->bf_buf_addr;
+
+// /* virtual addr of the beginning of the buffer. */
+// iob = bf->bf_mpdu;
+// ds->ds_vdata = iob->data;
+
+ /*
+ * setup rx descriptors. The rx_bufsize here tells the hardware
+ * how much data it can DMA to us and that we are prepared
+ * to process
+ */
+ ath9k_hw_setuprxdesc(ah, ds,
+ common->rx_bufsize,
+ 0);
+
+ if (sc->rx.rxlink == NULL)
+ ath9k_hw_putrxbuf(ah, bf->bf_daddr);
+ else
+ *sc->rx.rxlink = bf->bf_daddr;
+
+ sc->rx.rxlink = &ds->ds_link;
+}
+
+static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
+{
+ /* XXX block beacon interrupts */
+ ath9k_hw_setantenna(sc->sc_ah, antenna);
+ sc->rx.defant = antenna;
+ sc->rx.rxotherant = 0;
+}
+
+static void ath_opmode_init(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ u32 rfilt, mfilt[2];
+
+ /* configure rx filter */
+ rfilt = ath_calcrxfilter(sc);
+ ath9k_hw_setrxfilter(ah, rfilt);
+
+ /* configure bssid mask */
+ ath_hw_setbssidmask(common);
+
+ /* configure operational mode */
+ ath9k_hw_setopmode(ah);
+
+ /* calculate and install multicast filter */
+ mfilt[0] = mfilt[1] = ~0;
+ ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
+}
+
+int ath_rx_init(struct ath_softc *sc, int nbufs)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct io_buffer *iob;
+ u32 *iob_addr = NULL;
+ struct ath_buf *bf;
+ int error = 0;
+
+ sc->sc_flags &= ~SC_OP_RXFLUSH;
+
+ common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
+ sc->sc_ah->caps.rx_status_len;
+
+ DBG2("ath9k: cachelsz %d rxbufsize %d\n",
+ common->cachelsz, common->rx_bufsize);
+
+ /* Initialize rx descriptors */
+
+ error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
+ "rx", nbufs, 1, 0);
+ if (error != 0) {
+ DBG("ath9k: "
+ "failed to allocate rx descriptors: %d\n",
+ error);
+ goto err;
+ }
+
+ list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+ iob = ath_rxbuf_alloc(common, common->rx_bufsize,
+ iob_addr);
+ if (iob == NULL) {
+ error = -ENOMEM;
+ goto err;
+ }
+
+ bf->bf_mpdu = iob;
+ bf->bf_buf_addr = *iob_addr;
+ }
+ sc->rx.rxlink = NULL;
+
+err:
+ if (error)
+ ath_rx_cleanup(sc);
+
+ return error;
+}
+
+void ath_rx_cleanup(struct ath_softc *sc)
+{
+ struct io_buffer *iob;
+ struct ath_buf *bf;
+
+ list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+ iob = bf->bf_mpdu;
+ if (iob) {
+ free_iob(iob);
+ bf->bf_buf_addr = 0;
+ bf->bf_mpdu = NULL;
+ }
+ }
+
+ if (sc->rx.rxdma.dd_desc_len != 0)
+ ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf);
+}
+
+/*
+ * Calculate the receive filter according to the
+ * operating mode and state:
+ *
+ * o always accept unicast, broadcast, and multicast traffic
+ * o maintain current state of phy error reception (the hal
+ * may enable phy error frames for noise immunity work)
+ * o probe request frames are accepted only when operating in
+ * hostap, adhoc, or monitor modes
+ * o enable promiscuous mode according to the interface state
+ * o accept beacons:
+ * - when operating in adhoc mode so the 802.11 layer creates
+ * node table entries for peers,
+ * - when operating in station mode for collecting rssi data when
+ * the station is otherwise quiet, or
+ * - when operating as a repeater so we see repeater-sta beacons
+ * - when scanning
+ */
+
+u32 ath_calcrxfilter(struct ath_softc *sc)
+{
+#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
+
+ u32 rfilt;
+
+ rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE)
+ | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
+ | ATH9K_RX_FILTER_MCAST | ATH9K_RX_FILTER_BEACON;
+
+ return rfilt;
+
+#undef RX_FILTER_PRESERVE
+}
+
+int ath_startrecv(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_buf *bf, *tbf;
+
+ if (list_empty(&sc->rx.rxbuf))
+ goto start_recv;
+
+ sc->rx.rxlink = NULL;
+ list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
+ ath_rx_buf_link(sc, bf);
+ }
+
+ /* We could have deleted elements so the list may be empty now */
+ if (list_empty(&sc->rx.rxbuf))
+ goto start_recv;
+
+ bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
+ ath9k_hw_putrxbuf(ah, bf->bf_daddr);
+ ath9k_hw_rxena(ah);
+
+start_recv:
+ ath_opmode_init(sc);
+ ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
+
+ return 0;
+}
+
+int ath_stoprecv(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ int stopped, reset = 0;
+
+ ath9k_hw_abortpcurecv(ah);
+ ath9k_hw_setrxfilter(ah, 0);
+ stopped = ath9k_hw_stopdmarecv(ah, &reset);
+
+ sc->rx.rxlink = NULL;
+
+ if (!(ah->ah_flags & AH_UNPLUGGED) &&
+ !stopped) {
+ DBG("ath9k: "
+ "Could not stop RX, we could be "
+ "confusing the DMA engine when we start RX up\n");
+ }
+ return stopped && !reset;
+}
+
+void ath_flushrecv(struct ath_softc *sc)
+{
+ sc->sc_flags |= SC_OP_RXFLUSH;
+ ath_rx_tasklet(sc, 1, 0);
+ sc->sc_flags &= ~SC_OP_RXFLUSH;
+}
+
+static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
+ struct ath_rx_status *rs)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_desc *ds;
+ struct ath_buf *bf;
+ int ret;
+
+ if (list_empty(&sc->rx.rxbuf)) {
+ sc->rx.rxlink = NULL;
+ return NULL;
+ }
+
+ bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
+ ds = bf->bf_desc;
+
+ /*
+ * Must provide the virtual address of the current
+ * descriptor, the physical address, and the virtual
+ * address of the next descriptor in the h/w chain.
+ * This allows the HAL to look ahead to see if the
+ * hardware is done with a descriptor by checking the
+ * done bit in the following descriptor and the address
+ * of the current descriptor the DMA engine is working
+ * on. All this is necessary because of our use of
+ * a self-linked list to avoid rx overruns.
+ */
+ ret = ath9k_hw_rxprocdesc(ah, ds, rs, 0);
+ if (ret == -EINPROGRESS) {
+ struct ath_rx_status trs;
+ struct ath_buf *tbf;
+ struct ath_desc *tds;
+
+ memset(&trs, 0, sizeof(trs));
+ if ((&bf->list)->next == &sc->rx.rxbuf) {
+ sc->rx.rxlink = NULL;
+ return NULL;
+ }
+
+ tbf = list_entry(bf->list.next, struct ath_buf, list);
+
+ /*
+ * On some hardware the descriptor status words could
+ * get corrupted, including the done bit. Because of
+ * this, check if the next descriptor's done bit is
+ * set or not.
+ *
+ * If the next descriptor's done bit is set, the current
+ * descriptor has been corrupted. Force s/w to discard
+ * this descriptor and continue...
+ */
+
+ tds = tbf->bf_desc;
+ ret = ath9k_hw_rxprocdesc(ah, tds, &trs, 0);
+ if (ret == -EINPROGRESS)
+ return NULL;
+ }
+
+ if (!bf->bf_mpdu)
+ return bf;
+
+ return bf;
+}
+
+/* Assumes you've already done the endian to CPU conversion */
+static int ath9k_rx_accept(struct ath_common *common,
+ struct ath_rx_status *rx_stats,
+ int *decrypt_error)
+{
+ struct ath_hw *ah = common->ah;
+ u8 rx_status_len = ah->caps.rx_status_len;
+
+
+ if (!rx_stats->rs_datalen)
+ return 0;
+ /*
+ * rs_status follows rs_datalen so if rs_datalen is too large
+ * we can take a hint that hardware corrupted it, so ignore
+ * those frames.
+ */
+ if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len))
+ return 0;
+
+ /* Only use error bits from the last fragment */
+ if (rx_stats->rs_more)
+ return 1;
+
+ /*
+ * The rx_stats->rs_status will not be set until the end of the
+ * chained descriptors so it can be ignored if rs_more is set. The
+ * rs_more will be false at the last element of the chained
+ * descriptors.
+ */
+ if (rx_stats->rs_status != 0) {
+ if (rx_stats->rs_status & ATH9K_RXERR_PHY)
+ return 0;
+
+ if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
+ *decrypt_error = 1;
+ }
+ /*
+ * Reject error frames with the exception of
+ * decryption and MIC failures. For monitor mode,
+ * we also ignore the CRC error.
+ */
+ if (ah->is_monitoring) {
+ if (rx_stats->rs_status &
+ ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
+ ATH9K_RXERR_CRC))
+ return 0;
+ } else {
+ if (rx_stats->rs_status &
+ ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+static int ath9k_process_rate(struct ath_common *common __unused,
+ struct net80211_device *dev,
+ struct ath_rx_status *rx_stats,
+ int *rix)
+{
+ struct ath_softc *sc = (struct ath_softc *)dev->priv;
+ int band;
+ int i = 0;
+
+ band = (dev->channels + sc->dev->channel)->band;
+
+ for (i = 0; i < sc->hwinfo->nr_rates[band]; i++) {
+ if (sc->rates[i].hw_value == rx_stats->rs_rate) {
+ *rix = i;
+ return 0;
+ }
+ if (sc->rates[i].hw_value_short == rx_stats->rs_rate) {
+ *rix = i;
+ return 0;
+ }
+ }
+
+ /*
+ * No valid hardware bitrate found -- we should not get here
+ * because hardware has already validated this frame as OK.
+ */
+ DBG("ath9k: "
+ "unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
+ rx_stats->rs_rate);
+
+ return -EINVAL;
+}
+
+/*
+ * For Decrypt or Demic errors, we only mark packet status here and always push
+ * up the frame up to let mac80211 handle the actual error case, be it no
+ * decryption key or real decryption error. This let us keep statistics there.
+ */
+static int ath9k_rx_iob_preprocess(struct ath_common *common,
+ struct net80211_device *dev,
+ struct ath_rx_status *rx_stats,
+ int *rix,
+ int *decrypt_error)
+{
+ /*
+ * everything but the rate is checked here, the rate check is done
+ * separately to avoid doing two lookups for a rate for each frame.
+ */
+ if (!ath9k_rx_accept(common, rx_stats, decrypt_error))
+ return -EINVAL;
+
+ /* Only use status info from the last fragment */
+ if (rx_stats->rs_more)
+ return 0;
+
+ if (ath9k_process_rate(common, dev, rx_stats, rix))
+ return -EINVAL;
+
+ return 0;
+}
+
+int ath_rx_tasklet(struct ath_softc *sc, int flush, int hp __unused)
+{
+ struct ath_buf *bf;
+ struct io_buffer *iob = NULL, *requeue_iob;
+ u32 *requeue_iob_addr = NULL;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ /*
+ * The hw can technically differ from common->hw when using ath9k
+ * virtual wiphy so to account for that we iterate over the active
+ * wiphys and find the appropriate wiphy and therefore hw.
+ */
+ struct net80211_device *dev = sc->dev;
+ int retval;
+ int decrypt_error = 0;
+ struct ath_rx_status rs;
+ int rix = 0;
+
+ do {
+ /* If handling rx interrupt and flush is in progress => exit */
+ if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))
+ break;
+
+ memset(&rs, 0, sizeof(rs));
+ bf = ath_get_next_rx_buf(sc, &rs);
+
+ if (!bf)
+ break;
+
+ iob = bf->bf_mpdu;
+ if (!iob)
+ continue;
+
+ /*
+ * If we're asked to flush receive queue, directly
+ * chain it back at the queue without processing it.
+ */
+ if (flush)
+ goto requeue_drop_frag;
+
+ retval = ath9k_rx_iob_preprocess(common, dev, &rs,
+ &rix, &decrypt_error);
+ if (retval)
+ goto requeue_drop_frag;
+
+ /* Ensure we always have an iob to requeue once we are done
+ * processing the current buffer's iob */
+ requeue_iob = ath_rxbuf_alloc(common, common->rx_bufsize, requeue_iob_addr);
+
+ /* If there is no memory we ignore the current RX'd frame,
+ * tell hardware it can give us a new frame using the old
+ * iob and put it at the tail of the sc->rx.rxbuf list for
+ * processing. */
+ if (!requeue_iob)
+ goto requeue_drop_frag;
+
+ iob_put(iob, rs.rs_datalen + ah->caps.rx_status_len);
+ if (ah->caps.rx_status_len)
+ iob_pull(iob, ah->caps.rx_status_len);
+
+ /* We will now give hardware our shiny new allocated iob */
+ bf->bf_mpdu = requeue_iob;
+ bf->bf_buf_addr = *requeue_iob_addr;
+
+ /*
+ * change the default rx antenna if rx diversity chooses the
+ * other antenna 3 times in a row.
+ */
+ if (sc->rx.defant != rs.rs_antenna) {
+ if (++sc->rx.rxotherant >= 3)
+ ath_setdefantenna(sc, rs.rs_antenna);
+ } else {
+ sc->rx.rxotherant = 0;
+ }
+
+ DBGIO("ath9k: rx %d bytes, signal %d, bitrate %d, hw_value %d\n", rs.rs_datalen,
+ rs.rs_rssi, sc->rates[rix].bitrate, rs.rs_rate);
+
+ net80211_rx(dev, iob, rs.rs_rssi,
+ sc->rates[rix].bitrate);
+
+requeue_drop_frag:
+ list_del(&bf->list);
+ list_add_tail(&bf->list, &sc->rx.rxbuf);
+ ath_rx_buf_link(sc, bf);
+ ath9k_hw_rxena(ah);
+ } while (1);
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_xmit.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_xmit.c
new file mode 100644
index 00000000..7f4f28ab
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/ath9k_xmit.c
@@ -0,0 +1,813 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+
+#include "ath9k.h"
+#include "ar9003_mac.h"
+
+#define BITS_PER_BYTE 8
+#define OFDM_PLCP_BITS 22
+#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
+#define L_STF 8
+#define L_LTF 8
+#define L_SIG 4
+#define HT_SIG 8
+#define HT_STF 4
+#define HT_LTF(_ns) (4 * (_ns))
+#define SYMBOL_TIME(_ns) ((_ns) << 2) /* ns * 4 us */
+#define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5) /* ns * 3.6 us */
+#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2)
+#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18)
+
+
+#define IS_HT_RATE(_rate) ((_rate) & 0x80)
+
+static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_atx_tid *tid,
+ struct list_head *bf_head);
+static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_txq *txq, struct list_head *bf_q,
+ struct ath_tx_status *ts, int txok, int sendbar);
+static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
+ struct list_head *head);
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
+
+enum {
+ MCS_HT20,
+ MCS_HT20_SGI,
+ MCS_HT40,
+ MCS_HT40_SGI,
+};
+
+/*********************/
+/* Aggregation logic */
+/*********************/
+
+static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
+{
+ struct ath_atx_ac *ac = tid->ac;
+
+ if (tid->paused)
+ return;
+
+ if (tid->sched)
+ return;
+
+ tid->sched = 1;
+ list_add_tail(&tid->list, &ac->tid_q);
+
+ if (ac->sched)
+ return;
+
+ ac->sched = 1;
+ list_add_tail(&ac->list, &txq->axq_acq);
+}
+
+static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
+{
+ struct ath_buf *bf = NULL;
+
+ if (list_empty(&sc->tx.txbuf)) {
+ return NULL;
+ }
+
+ bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
+ list_del(&bf->list);
+
+ return bf;
+}
+
+static void ath_tx_return_buffer(struct ath_softc *sc, struct ath_buf *bf)
+{
+ list_add_tail(&bf->list, &sc->tx.txbuf);
+}
+
+/********************/
+/* Queue Management */
+/********************/
+
+struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_tx_queue_info qi;
+ static const int subtype_txq_to_hwq[] = {
+ [WME_AC_BE] = ATH_TXQ_AC_BE,
+ };
+ int axq_qnum, i;
+
+ memset(&qi, 0, sizeof(qi));
+ qi.tqi_subtype = subtype_txq_to_hwq[subtype];
+ qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
+ qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
+ qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
+ qi.tqi_physCompBuf = 0;
+
+ /*
+ * Enable interrupts only for EOL and DESC conditions.
+ * We mark tx descriptors to receive a DESC interrupt
+ * when a tx queue gets deep; otherwise waiting for the
+ * EOL to reap descriptors. Note that this is done to
+ * reduce interrupt load and this only defers reaping
+ * descriptors, never transmitting frames. Aside from
+ * reducing interrupts this also permits more concurrency.
+ * The only potential downside is if the tx queue backs
+ * up in which case the top half of the kernel may backup
+ * due to a lack of tx descriptors.
+ *
+ * The UAPSD queue is an exception, since we take a desc-
+ * based intr on the EOSP frames.
+ */
+ qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
+ TXQ_FLAG_TXDESCINT_ENABLE;
+
+ axq_qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
+ if (axq_qnum == -1) {
+ /*
+ * NB: don't print a message, this happens
+ * normally on parts with too few tx queues
+ */
+ return NULL;
+ }
+ if ((unsigned int)axq_qnum >= ARRAY_SIZE(sc->tx.txq)) {
+ DBG("ath9k: qnum %d out of range, max %zd!\n",
+ axq_qnum, ARRAY_SIZE(sc->tx.txq));
+ ath9k_hw_releasetxqueue(ah, axq_qnum);
+ return NULL;
+ }
+ if (!ATH_TXQ_SETUP(sc, axq_qnum)) {
+ struct ath_txq *txq = &sc->tx.txq[axq_qnum];
+
+ txq->axq_qnum = axq_qnum;
+ txq->mac80211_qnum = -1;
+ txq->axq_link = NULL;
+ INIT_LIST_HEAD(&txq->axq_q);
+ INIT_LIST_HEAD(&txq->axq_acq);
+ txq->axq_depth = 0;
+ txq->axq_ampdu_depth = 0;
+ txq->axq_tx_inprogress = 0;
+ sc->tx.txqsetup |= 1<<axq_qnum;
+
+ txq->txq_headidx = txq->txq_tailidx = 0;
+ for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
+ INIT_LIST_HEAD(&txq->txq_fifo[i]);
+ INIT_LIST_HEAD(&txq->txq_fifo_pending);
+ }
+ return &sc->tx.txq[axq_qnum];
+}
+
+/*
+ * Drain a given TX queue (could be Beacon or Data)
+ *
+ * This assumes output has been stopped and
+ * we do not need to block ath_tx_tasklet.
+ */
+void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, int retry_tx __unused)
+{
+ struct ath_buf *bf, *lastbf __unused;
+ struct list_head bf_head;
+ struct ath_tx_status ts;
+
+ memset(&ts, 0, sizeof(ts));
+ INIT_LIST_HEAD(&bf_head);
+
+ for (;;) {
+ if (list_empty(&txq->axq_q)) {
+ txq->axq_link = NULL;
+ break;
+ }
+ bf = list_first_entry(&txq->axq_q, struct ath_buf,
+ list);
+
+ if (bf->bf_stale) {
+ list_del(&bf->list);
+
+ ath_tx_return_buffer(sc, bf);
+ continue;
+ }
+
+ lastbf = bf->bf_lastbf;
+
+ list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
+
+ txq->axq_depth--;
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
+ }
+
+ txq->axq_tx_inprogress = 0;
+}
+
+int ath_drain_all_txq(struct ath_softc *sc, int retry_tx)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_txq *txq;
+ int i, npend = 0;
+
+ if (sc->sc_flags & SC_OP_INVALID)
+ return 1;
+
+ ath9k_hw_abort_tx_dma(ah);
+
+ /* Check if any queue remains active */
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (!ATH_TXQ_SETUP(sc, i))
+ continue;
+
+ npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
+ }
+
+ if (npend)
+ DBG("ath9k: Failed to stop TX DMA!\n");
+
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (!ATH_TXQ_SETUP(sc, i))
+ continue;
+
+ /*
+ * The caller will resume queues with ieee80211_wake_queues.
+ * Mark the queue as not stopped to prevent ath_tx_complete
+ * from waking the queue too early.
+ */
+ txq = &sc->tx.txq[i];
+ txq->stopped = 0;
+ ath_draintxq(sc, txq, retry_tx);
+ }
+
+ return !npend;
+}
+
+void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
+{
+ ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
+ sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
+}
+
+/* For each axq_acq entry, for each tid, try to schedule packets
+ * for transmit until ampdu_depth has reached min Q depth.
+ */
+void ath_txq_schedule(struct ath_softc *sc __unused, struct ath_txq *txq)
+{
+ struct ath_atx_ac *ac, *ac_tmp, *last_ac;
+ struct ath_atx_tid *tid, *last_tid;
+
+ if (list_empty(&txq->axq_acq) ||
+ txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+ return;
+
+ ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
+ last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list);
+
+ list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
+ last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
+ list_del(&ac->list);
+ ac->sched = 0;
+
+ while (!list_empty(&ac->tid_q)) {
+ tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
+ list);
+ list_del(&tid->list);
+ tid->sched = 0;
+
+ if (tid->paused)
+ continue;
+
+ /*
+ * add tid to round-robin queue if more frames
+ * are pending for the tid
+ */
+ if (!list_empty(&tid->buf_q))
+ ath_tx_queue_tid(txq, tid);
+
+ if (tid == last_tid ||
+ txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+ break;
+ }
+
+ if (!list_empty(&ac->tid_q)) {
+ if (!ac->sched) {
+ ac->sched = 1;
+ list_add_tail(&ac->list, &txq->axq_acq);
+ }
+ }
+
+ if (ac == last_ac ||
+ txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+ return;
+ }
+}
+
+/***********/
+/* TX, DMA */
+/***********/
+
+/*
+ * Insert a chain of ath_buf (descriptors) on a txq and
+ * assume the descriptors are already chained together by caller.
+ */
+static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
+ struct list_head *head)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_buf *bf;
+
+ /*
+ * Insert the frame on the outbound list and
+ * pass it on to the hardware.
+ */
+
+ if (list_empty(head))
+ return;
+
+ bf = list_first_entry(head, struct ath_buf, list);
+
+ DBGIO("ath9k: "
+ "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
+
+ list_splice_tail_init(head, &txq->axq_q);
+
+ if (txq->axq_link == NULL) {
+ ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
+ DBGIO("ath9k: TXDP[%d] = %llx (%p)\n",
+ txq->axq_qnum, ito64(bf->bf_daddr),
+ bf->bf_desc);
+ } else {
+ *txq->axq_link = bf->bf_daddr;
+ DBGIO("ath9k: "
+ "link[%d] (%p)=%llx (%p)\n",
+ txq->axq_qnum, txq->axq_link,
+ ito64(bf->bf_daddr), bf->bf_desc);
+ }
+ ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
+ &txq->axq_link);
+ ath9k_hw_txstart(ah, txq->axq_qnum);
+
+ txq->axq_depth++;
+}
+
+static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_atx_tid *tid,
+ struct list_head *bf_head)
+{
+ struct ath_buf *bf;
+
+ bf = list_first_entry(bf_head, struct ath_buf, list);
+ bf->bf_state.bf_type &= ~BUF_AMPDU;
+
+ /* update starting sequence number for subsequent ADDBA request */
+ if (tid)
+ INCR(tid->seq_start, IEEE80211_SEQ_MAX);
+
+ bf->bf_lastbf = bf;
+ ath_buf_set_rate(sc, bf, iob_len(bf->bf_mpdu) + FCS_LEN);
+ ath_tx_txqaddbuf(sc, txq, bf_head);
+}
+
+static enum ath9k_pkt_type get_hw_packet_type(struct io_buffer *iob)
+{
+ struct ieee80211_frame *hdr;
+ enum ath9k_pkt_type htype;
+ u16 fc;
+
+ hdr = (struct ieee80211_frame *)iob->data;
+ fc = hdr->fc;
+
+ if ((fc & (IEEE80211_FC_TYPE | IEEE80211_FC_SUBTYPE)) == (IEEE80211_TYPE_MGMT | IEEE80211_STYPE_BEACON))
+ htype = ATH9K_PKT_TYPE_BEACON;
+ else if ((fc & (IEEE80211_FC_TYPE | IEEE80211_FC_SUBTYPE)) == (IEEE80211_TYPE_MGMT | IEEE80211_STYPE_PROBE_RESP))
+ htype = ATH9K_PKT_TYPE_PROBE_RESP;
+ else
+ htype = ATH9K_PKT_TYPE_NORMAL;
+
+ return htype;
+}
+
+static int setup_tx_flags(struct io_buffer *iob __unused)
+{
+ int flags = 0;
+
+ flags |= ATH9K_TXDESC_INTREQ;
+
+ return flags;
+}
+
+u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_channel *curchan = ah->curchan;
+ if ((sc->sc_flags & SC_OP_ENABLE_APM) &&
+ (curchan->channelFlags & CHANNEL_5GHZ) &&
+ (chainmask == 0x7) && (rate < 0x90))
+ return 0x3;
+ else
+ return chainmask;
+}
+
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath9k_11n_rate_series series[4];
+ const struct ath9k_legacy_rate *rate;
+ int i, flags = 0;
+ u8 rix = 0, ctsrate = 0;
+ int is_pspoll;
+
+ memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
+
+ is_pspoll = 0;
+
+ /*
+ * We check if Short Preamble is needed for the CTS rate by
+ * checking the BSS's global flag.
+ * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
+ */
+ rate = &sc->rates[sc->hw_rix];
+ ctsrate = rate->hw_value;
+ if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
+ ctsrate |= rate->hw_value_short;
+
+ for (i = 0; i < 4; i++) {
+ int is_40 __unused, is_sgi __unused, is_sp;
+ int phy;
+
+ rix = sc->hw_rix;
+ series[i].Tries = ATH_TXMAXTRY;
+
+ if (sc->sc_flags & SC_OP_PROTECT_ENABLE) {
+ series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+ flags |= ATH9K_TXDESC_CTSENA;
+ }
+
+ is_sp = !!(rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
+
+ /* legacy rates */
+ if ((sc->dev->channels + sc->dev->channel)->band == NET80211_BAND_2GHZ)
+ phy = CHANNEL_CCK;
+ else
+ phy = CHANNEL_OFDM;
+
+ series[i].Rate = rate->hw_value;
+ if (rate->hw_value_short && (sc->sc_flags & SC_OP_PREAMBLE_SHORT)) {
+ if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+ series[i].Rate |= rate->hw_value_short;
+ } else {
+ is_sp = 0;
+ }
+
+ if (bf->bf_state.bfs_paprd)
+ series[i].ChSel = common->tx_chainmask;
+ else
+ series[i].ChSel = ath_txchainmask_reduction(sc,
+ common->tx_chainmask, series[i].Rate);
+
+ series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
+ phy, rate->bitrate * 100, len, rix, is_sp);
+ }
+
+ /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
+ if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
+ flags &= ~ATH9K_TXDESC_RTSENA;
+
+ /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
+ if (flags & ATH9K_TXDESC_RTSENA)
+ flags &= ~ATH9K_TXDESC_CTSENA;
+
+ /* set dur_update_en for l-sig computation except for PS-Poll frames */
+ ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
+ bf->bf_lastbf->bf_desc,
+ !is_pspoll, ctsrate,
+ 0, series, 4, flags);
+
+}
+
+static struct ath_buf *ath_tx_setup_buffer(struct net80211_device *dev,
+ struct ath_txq *txq,
+ struct io_buffer *iob)
+{
+ struct ath_softc *sc = dev->priv;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_buf *bf;
+ struct ath_desc *ds;
+ int frm_type;
+ static const enum ath9k_key_type net80211_keytype_to_ath[] = {
+ [NET80211_CRYPT_NONE] = ATH9K_KEY_TYPE_CLEAR,
+ [NET80211_CRYPT_WEP] = ATH9K_KEY_TYPE_WEP,
+ [NET80211_CRYPT_TKIP] = ATH9K_KEY_TYPE_TKIP,
+ [NET80211_CRYPT_CCMP] = ATH9K_KEY_TYPE_AES,
+ [NET80211_CRYPT_UNKNOWN] = ATH9K_KEY_TYPE_CLEAR,
+ };
+
+ bf = ath_tx_get_buffer(sc);
+ if (!bf) {
+ DBG("ath9k: TX buffers are full\n");
+ return NULL;
+ }
+
+ ATH_TXBUF_RESET(bf);
+
+ bf->bf_flags = setup_tx_flags(iob);
+ bf->bf_mpdu = iob;
+
+ bf->bf_buf_addr = virt_to_bus(iob->data);
+
+ frm_type = get_hw_packet_type(iob);
+
+ ds = bf->bf_desc;
+ ath9k_hw_set_desc_link(ah, ds, 0);
+
+ ath9k_hw_set11n_txdesc(ah, ds, iob_len(iob) + FCS_LEN, frm_type, MAX_RATE_POWER,
+ ATH9K_TXKEYIX_INVALID, net80211_keytype_to_ath[dev->crypto->algorithm], bf->bf_flags);
+
+ ath9k_hw_filltxdesc(ah, ds,
+ iob_len(iob), /* segment length */
+ 1, /* first segment */
+ 1, /* last segment */
+ ds, /* first descriptor */
+ bf->bf_buf_addr,
+ txq->axq_qnum);
+
+
+ return bf;
+}
+
+/* FIXME: tx power */
+static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_tx_control *txctl)
+{
+ struct list_head bf_head;
+ struct ath_atx_tid *tid = NULL;
+
+ INIT_LIST_HEAD(&bf_head);
+ list_add_tail(&bf->list, &bf_head);
+
+ bf->bf_state.bfs_paprd = txctl->paprd;
+
+ if (txctl->paprd)
+ bf->bf_state.bfs_paprd_timestamp = ( currticks() * 1000 ) / TICKS_PER_SEC;
+
+ ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, 1);
+
+ ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
+}
+
+/* Upon failure caller should free iob */
+int ath_tx_start(struct net80211_device *dev, struct io_buffer *iob,
+ struct ath_tx_control *txctl)
+{
+ struct ath_softc *sc = dev->priv;
+ struct ath_txq *txq = txctl->txq;
+ struct ath_buf *bf;
+ int q;
+
+ /*
+ * At this point, the vif, hw_key and sta pointers in the tx control
+ * info are no longer valid (overwritten by the ath_frame_info data.
+ */
+
+ bf = ath_tx_setup_buffer(dev, txctl->txq, iob);
+ if (!bf)
+ return -ENOMEM;
+
+ q = 0;
+ if (txq == sc->tx.txq_map[q] &&
+ ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
+ txq->stopped = 1;
+ }
+
+ ath_tx_start_dma(sc, bf, txctl);
+
+ return 0;
+}
+
+/*****************/
+/* TX Completion */
+/*****************/
+
+static void ath_tx_complete(struct ath_softc *sc, struct io_buffer *iob,
+ int tx_flags __unused, struct ath_tx_status *ts, struct ath_txq *txq)
+{
+ struct net80211_device *dev = sc->dev;
+ int q, padpos __unused, padsize __unused;
+
+ DBGIO("ath9k: TX complete: iob: %p\n", iob);
+
+ q = 0;
+ if (txq == sc->tx.txq_map[q]) {
+ if (--txq->pending_frames < 0)
+ txq->pending_frames = 0;
+
+ if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
+ txq->stopped = 0;
+ }
+ }
+
+ net80211_tx_complete(dev, iob, ts->ts_longretry,
+ (ts->ts_status & ATH9K_TXERR_MASK) ? EIO : 0);
+}
+
+static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_txq *txq, struct list_head *bf_q,
+ struct ath_tx_status *ts, int txok, int sendbar)
+{
+ struct io_buffer *iob = bf->bf_mpdu;
+ int tx_flags = 0;
+
+ if (sendbar)
+ tx_flags = ATH_TX_BAR;
+
+ if (!txok) {
+ tx_flags |= ATH_TX_ERROR;
+
+ if (bf_isxretried(bf))
+ tx_flags |= ATH_TX_XRETRY;
+ }
+
+ bf->bf_buf_addr = 0;
+
+ ath_tx_complete(sc, iob, tx_flags,
+ ts, txq);
+
+ /* At this point, iob (bf->bf_mpdu) is consumed...make sure we don't
+ * accidentally reference it later.
+ */
+ bf->bf_mpdu = NULL;
+
+ /*
+ * Return the list of ath_buf of this mpdu to free queue
+ */
+ list_splice_tail_init(bf_q, &sc->tx.txbuf);
+}
+
+static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_buf *bf, *lastbf, *bf_held = NULL;
+ struct list_head bf_head;
+ struct ath_desc *ds;
+ struct ath_tx_status ts;
+ int txok;
+ int status;
+
+ DBGIO("ath9k: tx queue %d (%x), link %p\n",
+ txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
+ txq->axq_link);
+
+ for (;;) {
+ if (list_empty(&txq->axq_q)) {
+ txq->axq_link = NULL;
+ if (sc->sc_flags & SC_OP_TXAGGR)
+ ath_txq_schedule(sc, txq);
+ break;
+ }
+ bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
+
+ /*
+ * There is a race condition that a BH gets scheduled
+ * after sw writes TxE and before hw re-load the last
+ * descriptor to get the newly chained one.
+ * Software must keep the last DONE descriptor as a
+ * holding descriptor - software does so by marking
+ * it with the STALE flag.
+ */
+ bf_held = NULL;
+ if (bf->bf_stale) {
+ bf_held = bf;
+ if (list_is_last(&bf_held->list, &txq->axq_q)) {
+ break;
+ } else {
+ bf = list_entry(bf_held->list.next,
+ struct ath_buf, list);
+ }
+ }
+
+ lastbf = bf->bf_lastbf;
+ ds = lastbf->bf_desc;
+
+ memset(&ts, 0, sizeof(ts));
+ status = ath9k_hw_txprocdesc(ah, ds, &ts);
+ if (status == -EINPROGRESS) {
+ break;
+ }
+
+ /*
+ * Remove ath_buf's of the same transmit unit from txq,
+ * however leave the last descriptor back as the holding
+ * descriptor for hw.
+ */
+ lastbf->bf_stale = 1;
+ INIT_LIST_HEAD(&bf_head);
+ if (!list_is_singular(&lastbf->list))
+ list_cut_position(&bf_head,
+ &txq->axq_q, lastbf->list.prev);
+
+ txq->axq_depth--;
+ txok = !(ts.ts_status & ATH9K_TXERR_MASK);
+ txq->axq_tx_inprogress = 0;
+ if (bf_held)
+ list_del(&bf_held->list);
+
+ if (bf_held)
+ ath_tx_return_buffer(sc, bf_held);
+
+ /*
+ * This frame is sent out as a single frame.
+ * Use hardware retry status for this frame.
+ */
+ if (ts.ts_status & ATH9K_TXERR_XRETRY)
+ bf->bf_state.bf_type |= BUF_XRETRY;
+
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
+
+ if (sc->sc_flags & SC_OP_TXAGGR)
+ ath_txq_schedule(sc, txq);
+ }
+}
+
+static void ath_tx_complete_poll_work(struct ath_softc *sc)
+{
+ struct ath_txq *txq;
+ int i;
+ int needreset = 0;
+
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+ if (ATH_TXQ_SETUP(sc, i)) {
+ txq = &sc->tx.txq[i];
+ if (txq->axq_depth) {
+ if (txq->axq_tx_inprogress) {
+ needreset = 1;
+ break;
+ } else {
+ txq->axq_tx_inprogress = 1;
+ }
+ }
+ }
+
+ if (needreset) {
+ DBG("ath9k: "
+ "tx hung, resetting the chip\n");
+ ath_reset(sc, 1);
+ }
+
+ sc->tx_complete_work_timer = ( currticks() * 1000 ) / TICKS_PER_SEC + ATH_TX_COMPLETE_POLL_INT;
+}
+
+
+
+void ath_tx_tasklet(struct ath_softc *sc)
+{
+ int i;
+ u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
+
+ ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
+
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
+ ath_tx_processq(sc, &sc->tx.txq[i]);
+ }
+}
+
+/*****************/
+/* Init, Cleanup */
+/*****************/
+
+int ath_tx_init(struct ath_softc *sc, int nbufs)
+{
+ int error = 0;
+
+ error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
+ "tx", nbufs, 1, 1);
+ if (error != 0) {
+ DBG("ath9k: "
+ "Failed to allocate tx descriptors: %d\n", error);
+ goto err;
+ }
+
+ sc->tx_complete_work = ath_tx_complete_poll_work;
+
+err:
+ if (error != 0)
+ ath_tx_cleanup(sc);
+
+ return error;
+}
+
+void ath_tx_cleanup(struct ath_softc *sc)
+{
+ if (sc->tx.txdma.dd_desc_len != 0)
+ ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/calib.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/calib.h
new file mode 100644
index 00000000..5bf50f4a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/calib.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef CALIB_H
+#define CALIB_H
+
+#include "hw.h"
+
+#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3
+#define AR_PHY_CCA_FILTERWINDOW_LENGTH 5
+
+#define NUM_NF_READINGS 6
+#define ATH9K_NF_CAL_HIST_MAX 5
+
+struct ar5416IniArray {
+ u32 *ia_array;
+ u32 ia_rows;
+ u32 ia_columns;
+};
+
+#define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \
+ (iniarray)->ia_array = (u32 *)(array); \
+ (iniarray)->ia_rows = (rows); \
+ (iniarray)->ia_columns = (columns); \
+ } while (0)
+
+#define INI_RA(iniarray, row, column) \
+ (((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)])
+
+#define INIT_CAL(_perCal) do { \
+ (_perCal)->calState = CAL_WAITING; \
+ (_perCal)->calNext = NULL; \
+ } while (0)
+
+#define INSERT_CAL(_ahp, _perCal) \
+ do { \
+ if ((_ahp)->cal_list_last == NULL) { \
+ (_ahp)->cal_list = \
+ (_ahp)->cal_list_last = (_perCal); \
+ ((_ahp)->cal_list_last)->calNext = (_perCal); \
+ } else { \
+ ((_ahp)->cal_list_last)->calNext = (_perCal); \
+ (_ahp)->cal_list_last = (_perCal); \
+ (_perCal)->calNext = (_ahp)->cal_list; \
+ } \
+ } while (0)
+
+enum ath9k_cal_state {
+ CAL_INACTIVE,
+ CAL_WAITING,
+ CAL_RUNNING,
+ CAL_DONE
+};
+
+#define MIN_CAL_SAMPLES 1
+#define MAX_CAL_SAMPLES 64
+#define INIT_LOG_COUNT 5
+#define PER_MIN_LOG_COUNT 2
+#define PER_MAX_LOG_COUNT 10
+
+struct ath9k_percal_data {
+ u32 calType;
+ u32 calNumSamples;
+ u32 calCountMax;
+ void (*calCollect) (struct ath_hw *);
+ void (*calPostProc) (struct ath_hw *, u8);
+};
+
+struct ath9k_cal_list {
+ const struct ath9k_percal_data *calData;
+ enum ath9k_cal_state calState;
+ struct ath9k_cal_list *calNext;
+};
+
+struct ath9k_nfcal_hist {
+ int16_t nfCalBuffer[ATH9K_NF_CAL_HIST_MAX];
+ u8 currIndex;
+ int16_t privNF;
+ u8 invalidNFcount;
+};
+
+#define MAX_PACAL_SKIPCOUNT 8
+struct ath9k_pacal_info{
+ int32_t prev_offset; /* Previous value of PA offset value */
+ int8_t max_skipcount; /* Max No. of times PACAL can be skipped */
+ int8_t skipcount; /* No. of times the PACAL to be skipped */
+};
+
+int ath9k_hw_reset_calvalid(struct ath_hw *ah);
+void ath9k_hw_start_nfcal(struct ath_hw *ah, int update);
+void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
+int ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan);
+void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
+ struct ath9k_channel *chan);
+void ath9k_hw_reset_calibration(struct ath_hw *ah,
+ struct ath9k_cal_list *currCal);
+
+
+#endif /* CALIB_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/common.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/common.h
new file mode 100644
index 00000000..009f8036
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/common.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "../ath.h"
+
+#include "hw.h"
+#include "hw-ops.h"
+
+/* Common header for Atheros 802.11n base driver cores */
+
+#define WME_NUM_TID 16
+#define WME_BA_BMP_SIZE 64
+#define WME_MAX_BA WME_BA_BMP_SIZE
+#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
+
+#define WME_AC_BE 2
+#define WME_NUM_AC 1
+
+#define ATH_RSSI_DUMMY_MARKER 0x127
+#define ATH_RSSI_LPF_LEN 10
+#define RSSI_LPF_THRESHOLD -20
+#define ATH_RSSI_EP_MULTIPLIER (1<<7)
+#define ATH_EP_MUL(x, mul) ((x) * (mul))
+#define ATH_RSSI_IN(x) (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER))
+#define ATH_LPF_RSSI(x, y, len) \
+ ((x != ATH_RSSI_DUMMY_MARKER) ? (((x) * ((len) - 1) + (y)) / (len)) : (y))
+#define ATH_RSSI_LPF(x, y) do { \
+ if ((y) >= RSSI_LPF_THRESHOLD) \
+ x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \
+} while (0)
+#define ATH_EP_RND(x, mul) \
+ ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
+
+
+void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
+ struct net80211_channel *chan);
+struct ath9k_channel *ath9k_cmn_get_curchannel(struct net80211_device *dev,
+ struct ath_hw *ah);
+void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
+ u16 new_txpow, u16 *txpower);
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/eeprom.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/eeprom.h
new file mode 100644
index 00000000..b451ebd7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/eeprom.h
@@ -0,0 +1,714 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef EEPROM_H
+#define EEPROM_H
+
+#define AR_EEPROM_MODAL_SPURS 5
+
+#include "../ath.h"
+#include "ar9003_eeprom.h"
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define AR5416_EEPROM_MAGIC 0x5aa5
+#else
+#define AR5416_EEPROM_MAGIC 0xa55a
+#endif
+
+#define CTRY_DEBUG 0x1ff
+#define CTRY_DEFAULT 0
+
+#define AR_EEPROM_EEPCAP_COMPRESS_DIS 0x0001
+#define AR_EEPROM_EEPCAP_AES_DIS 0x0002
+#define AR_EEPROM_EEPCAP_FASTFRAME_DIS 0x0004
+#define AR_EEPROM_EEPCAP_BURST_DIS 0x0008
+#define AR_EEPROM_EEPCAP_MAXQCU 0x01F0
+#define AR_EEPROM_EEPCAP_MAXQCU_S 4
+#define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN 0x0200
+#define AR_EEPROM_EEPCAP_KC_ENTRIES 0xF000
+#define AR_EEPROM_EEPCAP_KC_ENTRIES_S 12
+
+#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080
+#define AR_EEPROM_EEREGCAP_EN_KK_U2 0x0100
+#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400
+#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800
+
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0 0x4000
+#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000
+
+#define AR5416_EEPROM_MAGIC_OFFSET 0x0
+#define AR5416_EEPROM_S 2
+#define AR5416_EEPROM_OFFSET 0x2000
+#define AR5416_EEPROM_MAX 0xae0
+
+#define AR5416_EEPROM_START_ADDR \
+ (AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200
+
+#define SD_NO_CTL 0xE0
+#define NO_CTL 0xff
+#define CTL_MODE_M 0xf
+#define CTL_11A 0
+#define CTL_11B 1
+#define CTL_11G 2
+#define CTL_2GHT20 5
+#define CTL_5GHT20 6
+#define CTL_2GHT40 7
+#define CTL_5GHT40 8
+
+#define EXT_ADDITIVE (0x8000)
+#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
+#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
+#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
+
+#define SUB_NUM_CTL_MODES_AT_5G_40 2
+#define SUB_NUM_CTL_MODES_AT_2G_40 3
+
+#define INCREASE_MAXPOW_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
+#define INCREASE_MAXPOW_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
+
+/*
+ * For AR9285 and later chipsets, the following bits are not being programmed
+ * in EEPROM and so need to be enabled always.
+ *
+ * Bit 0: en_fcc_mid
+ * Bit 1: en_jap_mid
+ * Bit 2: en_fcc_dfs_ht40
+ * Bit 3: en_jap_ht40
+ * Bit 4: en_jap_dfs_ht40
+ */
+#define AR9285_RDEXT_DEFAULT 0x1F
+
+#define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
+#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
+#define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM))
+
+#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
+#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
+ ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \
+ ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+
+#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c
+#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2
+#define AR_EEPROM_RFSILENT_POLARITY 0x0002
+#define AR_EEPROM_RFSILENT_POLARITY_S 1
+
+#define EEP_RFSILENT_ENABLED 0x0001
+#define EEP_RFSILENT_ENABLED_S 0
+#define EEP_RFSILENT_POLARITY 0x0002
+#define EEP_RFSILENT_POLARITY_S 1
+#define EEP_RFSILENT_GPIO_SEL 0x001c
+#define EEP_RFSILENT_GPIO_SEL_S 2
+
+#define AR5416_OPFLAGS_11A 0x01
+#define AR5416_OPFLAGS_11G 0x02
+#define AR5416_OPFLAGS_N_5G_HT40 0x04
+#define AR5416_OPFLAGS_N_2G_HT40 0x08
+#define AR5416_OPFLAGS_N_5G_HT20 0x10
+#define AR5416_OPFLAGS_N_2G_HT20 0x20
+
+#define AR5416_EEP_NO_BACK_VER 0x1
+#define AR5416_EEP_VER 0xE
+#define AR5416_EEP_VER_MINOR_MASK 0x0FFF
+#define AR5416_EEP_MINOR_VER_2 0x2
+#define AR5416_EEP_MINOR_VER_3 0x3
+#define AR5416_EEP_MINOR_VER_7 0x7
+#define AR5416_EEP_MINOR_VER_9 0x9
+#define AR5416_EEP_MINOR_VER_16 0x10
+#define AR5416_EEP_MINOR_VER_17 0x11
+#define AR5416_EEP_MINOR_VER_19 0x13
+#define AR5416_EEP_MINOR_VER_20 0x14
+#define AR5416_EEP_MINOR_VER_21 0x15
+#define AR5416_EEP_MINOR_VER_22 0x16
+
+#define AR5416_NUM_5G_CAL_PIERS 8
+#define AR5416_NUM_2G_CAL_PIERS 4
+#define AR5416_NUM_5G_20_TARGET_POWERS 8
+#define AR5416_NUM_5G_40_TARGET_POWERS 8
+#define AR5416_NUM_2G_CCK_TARGET_POWERS 3
+#define AR5416_NUM_2G_20_TARGET_POWERS 4
+#define AR5416_NUM_2G_40_TARGET_POWERS 4
+#define AR5416_NUM_CTLS 24
+#define AR5416_NUM_BAND_EDGES 8
+#define AR5416_NUM_PD_GAINS 4
+#define AR5416_PD_GAINS_IN_MASK 4
+#define AR5416_PD_GAIN_ICEPTS 5
+#define AR5416_NUM_PDADC_VALUES 128
+#define AR5416_BCHAN_UNUSED 0xFF
+#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
+#define AR5416_MAX_CHAINS 3
+#define AR9300_MAX_CHAINS 3
+#define AR5416_PWR_TABLE_OFFSET_DB -5
+
+/* Rx gain type values */
+#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0
+#define AR5416_EEP_RXGAIN_13DB_BACKOFF 1
+#define AR5416_EEP_RXGAIN_ORIG 2
+
+/* Tx gain type values */
+#define AR5416_EEP_TXGAIN_ORIGINAL 0
+#define AR5416_EEP_TXGAIN_HIGH_POWER 1
+
+#define AR5416_EEP4K_START_LOC 64
+#define AR5416_EEP4K_NUM_2G_CAL_PIERS 3
+#define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3
+#define AR5416_EEP4K_NUM_2G_20_TARGET_POWERS 3
+#define AR5416_EEP4K_NUM_2G_40_TARGET_POWERS 3
+#define AR5416_EEP4K_NUM_CTLS 12
+#define AR5416_EEP4K_NUM_BAND_EDGES 4
+#define AR5416_EEP4K_NUM_PD_GAINS 2
+#define AR5416_EEP4K_MAX_CHAINS 1
+
+#define AR9280_TX_GAIN_TABLE_SIZE 22
+
+#define AR9287_EEP_VER 0xE
+#define AR9287_EEP_VER_MINOR_MASK 0xFFF
+#define AR9287_EEP_MINOR_VER_1 0x1
+#define AR9287_EEP_MINOR_VER_2 0x2
+#define AR9287_EEP_MINOR_VER_3 0x3
+#define AR9287_EEP_MINOR_VER AR9287_EEP_MINOR_VER_3
+#define AR9287_EEP_MINOR_VER_b AR9287_EEP_MINOR_VER
+#define AR9287_EEP_NO_BACK_VER AR9287_EEP_MINOR_VER_1
+
+#define AR9287_EEP_START_LOC 128
+#define AR9287_HTC_EEP_START_LOC 256
+#define AR9287_NUM_2G_CAL_PIERS 3
+#define AR9287_NUM_2G_CCK_TARGET_POWERS 3
+#define AR9287_NUM_2G_20_TARGET_POWERS 3
+#define AR9287_NUM_2G_40_TARGET_POWERS 3
+#define AR9287_NUM_CTLS 12
+#define AR9287_NUM_BAND_EDGES 4
+#define AR9287_PD_GAIN_ICEPTS 1
+#define AR9287_EEPMISC_BIG_ENDIAN 0x01
+#define AR9287_EEPMISC_WOW 0x02
+#define AR9287_MAX_CHAINS 2
+#define AR9287_ANT_16S 32
+
+#define AR9287_DATA_SZ 32
+
+#define AR9287_PWR_TABLE_OFFSET_DB -5
+
+#define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1)
+
+#define CTL_EDGE_TPOWER(_ctl) ((_ctl) & 0x3f)
+#define CTL_EDGE_FLAGS(_ctl) (((_ctl) >> 6) & 0x03)
+
+#define LNA_CTL_BUF_MODE BIT(0)
+#define LNA_CTL_ISEL_LO BIT(1)
+#define LNA_CTL_ISEL_HI BIT(2)
+#define LNA_CTL_BUF_IN BIT(3)
+#define LNA_CTL_FEM_BAND BIT(4)
+#define LNA_CTL_LOCAL_BIAS BIT(5)
+#define LNA_CTL_FORCE_XPA BIT(6)
+#define LNA_CTL_USE_ANT1 BIT(7)
+
+enum eeprom_param {
+ EEP_NFTHRESH_5,
+ EEP_NFTHRESH_2,
+ EEP_MAC_MSW,
+ EEP_MAC_MID,
+ EEP_MAC_LSW,
+ EEP_REG_0,
+ EEP_REG_1,
+ EEP_OP_CAP,
+ EEP_OP_MODE,
+ EEP_RF_SILENT,
+ EEP_OB_5,
+ EEP_DB_5,
+ EEP_OB_2,
+ EEP_DB_2,
+ EEP_MINOR_REV,
+ EEP_TX_MASK,
+ EEP_RX_MASK,
+ EEP_FSTCLK_5G,
+ EEP_RXGAIN_TYPE,
+ EEP_OL_PWRCTRL,
+ EEP_TXGAIN_TYPE,
+ EEP_RC_CHAIN_MASK,
+ EEP_DAC_HPWR_5G,
+ EEP_FRAC_N_5G,
+ EEP_DEV_TYPE,
+ EEP_TEMPSENSE_SLOPE,
+ EEP_TEMPSENSE_SLOPE_PAL_ON,
+ EEP_PWR_TABLE_OFFSET,
+ EEP_DRIVE_STRENGTH,
+ EEP_INTERNAL_REGULATOR,
+ EEP_SWREG,
+ EEP_PAPRD,
+ EEP_MODAL_VER,
+ EEP_ANT_DIV_CTL1,
+ EEP_CHAIN_MASK_REDUCE
+};
+
+enum ar5416_rates {
+ rate6mb, rate9mb, rate12mb, rate18mb,
+ rate24mb, rate36mb, rate48mb, rate54mb,
+ rate1l, rate2l, rate2s, rate5_5l,
+ rate5_5s, rate11l, rate11s, rateXr,
+ rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3,
+ rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7,
+ rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3,
+ rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7,
+ rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm,
+ Ar5416RateSize
+};
+
+enum ath9k_hal_freq_band {
+ ATH9K_HAL_FREQ_BAND_5GHZ = 0,
+ ATH9K_HAL_FREQ_BAND_2GHZ = 1
+};
+
+struct base_eep_header {
+ u16 length;
+ u16 checksum;
+ u16 version;
+ u8 opCapFlags;
+ u8 eepMisc;
+ u16 regDmn[2];
+ u8 macAddr[6];
+ u8 rxMask;
+ u8 txMask;
+ u16 rfSilent;
+ u16 blueToothOptions;
+ u16 deviceCap;
+ u32 binBuildNumber;
+ u8 deviceType;
+ u8 pwdclkind;
+ u8 fastClk5g;
+ u8 divChain;
+ u8 rxGainType;
+ u8 dacHiPwrMode_5G;
+ u8 openLoopPwrCntl;
+ u8 dacLpMode;
+ u8 txGainType;
+ u8 rcChainMask;
+ u8 desiredScaleCCK;
+ u8 pwr_table_offset;
+ u8 frac_n_5g;
+ u8 futureBase_3[21];
+} __attribute__((packed));
+
+struct base_eep_header_4k {
+ u16 length;
+ u16 checksum;
+ u16 version;
+ u8 opCapFlags;
+ u8 eepMisc;
+ u16 regDmn[2];
+ u8 macAddr[6];
+ u8 rxMask;
+ u8 txMask;
+ u16 rfSilent;
+ u16 blueToothOptions;
+ u16 deviceCap;
+ u32 binBuildNumber;
+ u8 deviceType;
+ u8 txGainType;
+} __attribute__((packed));
+
+
+struct spur_chan {
+ u16 spurChan;
+ u8 spurRangeLow;
+ u8 spurRangeHigh;
+} __attribute__((packed));
+
+struct modal_eep_header {
+ u32 antCtrlChain[AR5416_MAX_CHAINS];
+ u32 antCtrlCommon;
+ u8 antennaGainCh[AR5416_MAX_CHAINS];
+ u8 switchSettling;
+ u8 txRxAttenCh[AR5416_MAX_CHAINS];
+ u8 rxTxMarginCh[AR5416_MAX_CHAINS];
+ u8 adcDesiredSize;
+ u8 pgaDesiredSize;
+ u8 xlnaGainCh[AR5416_MAX_CHAINS];
+ u8 txEndToXpaOff;
+ u8 txEndToRxOn;
+ u8 txFrameToXpaOn;
+ u8 thresh62;
+ u8 noiseFloorThreshCh[AR5416_MAX_CHAINS];
+ u8 xpdGain;
+ u8 xpd;
+ u8 iqCalICh[AR5416_MAX_CHAINS];
+ u8 iqCalQCh[AR5416_MAX_CHAINS];
+ u8 pdGainOverlap;
+ u8 ob;
+ u8 db;
+ u8 xpaBiasLvl;
+ u8 pwrDecreaseFor2Chain;
+ u8 pwrDecreaseFor3Chain;
+ u8 txFrameToDataStart;
+ u8 txFrameToPaOn;
+ u8 ht40PowerIncForPdadc;
+ u8 bswAtten[AR5416_MAX_CHAINS];
+ u8 bswMargin[AR5416_MAX_CHAINS];
+ u8 swSettleHt40;
+ u8 xatten2Db[AR5416_MAX_CHAINS];
+ u8 xatten2Margin[AR5416_MAX_CHAINS];
+ u8 ob_ch1;
+ u8 db_ch1;
+ u8 lna_ctl;
+ u8 miscBits;
+ u16 xpaBiasLvlFreq[3];
+ u8 futureModal[6];
+
+ struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
+} __attribute__((packed));
+
+struct calDataPerFreqOpLoop {
+ u8 pwrPdg[2][5];
+ u8 vpdPdg[2][5];
+ u8 pcdac[2][5];
+ u8 empty[2][5];
+} __attribute__((packed));
+
+struct modal_eep_4k_header {
+ u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
+ u32 antCtrlCommon;
+ u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 switchSettling;
+ u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 adcDesiredSize;
+ u8 pgaDesiredSize;
+ u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 txEndToXpaOff;
+ u8 txEndToRxOn;
+ u8 txFrameToXpaOn;
+ u8 thresh62;
+ u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 xpdGain;
+ u8 xpd;
+ u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS];
+ u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 pdGainOverlap;
+#ifdef __BIG_ENDIAN_BITFIELD
+ u8 ob_1:4, ob_0:4;
+ u8 db1_1:4, db1_0:4;
+#else
+ u8 ob_0:4, ob_1:4;
+ u8 db1_0:4, db1_1:4;
+#endif
+ u8 xpaBiasLvl;
+ u8 txFrameToDataStart;
+ u8 txFrameToPaOn;
+ u8 ht40PowerIncForPdadc;
+ u8 bswAtten[AR5416_EEP4K_MAX_CHAINS];
+ u8 bswMargin[AR5416_EEP4K_MAX_CHAINS];
+ u8 swSettleHt40;
+ u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS];
+ u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS];
+#ifdef __BIG_ENDIAN_BITFIELD
+ u8 db2_1:4, db2_0:4;
+#else
+ u8 db2_0:4, db2_1:4;
+#endif
+ u8 version;
+#ifdef __BIG_ENDIAN_BITFIELD
+ u8 ob_3:4, ob_2:4;
+ u8 antdiv_ctl1:4, ob_4:4;
+ u8 db1_3:4, db1_2:4;
+ u8 antdiv_ctl2:4, db1_4:4;
+ u8 db2_2:4, db2_3:4;
+ u8 reserved:4, db2_4:4;
+#else
+ u8 ob_2:4, ob_3:4;
+ u8 ob_4:4, antdiv_ctl1:4;
+ u8 db1_2:4, db1_3:4;
+ u8 db1_4:4, antdiv_ctl2:4;
+ u8 db2_2:4, db2_3:4;
+ u8 db2_4:4, reserved:4;
+#endif
+ u8 tx_diversity;
+ u8 flc_pwr_thresh;
+ u8 bb_scale_smrt_antenna;
+#define EEP_4K_BB_DESIRED_SCALE_MASK 0x1f
+ u8 futureModal[1];
+ struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
+} __attribute__((packed));
+
+struct base_eep_ar9287_header {
+ u16 length;
+ u16 checksum;
+ u16 version;
+ u8 opCapFlags;
+ u8 eepMisc;
+ u16 regDmn[2];
+ u8 macAddr[6];
+ u8 rxMask;
+ u8 txMask;
+ u16 rfSilent;
+ u16 blueToothOptions;
+ u16 deviceCap;
+ u32 binBuildNumber;
+ u8 deviceType;
+ u8 openLoopPwrCntl;
+ int8_t pwrTableOffset;
+ int8_t tempSensSlope;
+ int8_t tempSensSlopePalOn;
+ u8 futureBase[29];
+} __attribute__((packed));
+
+struct modal_eep_ar9287_header {
+ u32 antCtrlChain[AR9287_MAX_CHAINS];
+ u32 antCtrlCommon;
+ int8_t antennaGainCh[AR9287_MAX_CHAINS];
+ u8 switchSettling;
+ u8 txRxAttenCh[AR9287_MAX_CHAINS];
+ u8 rxTxMarginCh[AR9287_MAX_CHAINS];
+ int8_t adcDesiredSize;
+ u8 txEndToXpaOff;
+ u8 txEndToRxOn;
+ u8 txFrameToXpaOn;
+ u8 thresh62;
+ int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS];
+ u8 xpdGain;
+ u8 xpd;
+ int8_t iqCalICh[AR9287_MAX_CHAINS];
+ int8_t iqCalQCh[AR9287_MAX_CHAINS];
+ u8 pdGainOverlap;
+ u8 xpaBiasLvl;
+ u8 txFrameToDataStart;
+ u8 txFrameToPaOn;
+ u8 ht40PowerIncForPdadc;
+ u8 bswAtten[AR9287_MAX_CHAINS];
+ u8 bswMargin[AR9287_MAX_CHAINS];
+ u8 swSettleHt40;
+ u8 version;
+ u8 db1;
+ u8 db2;
+ u8 ob_cck;
+ u8 ob_psk;
+ u8 ob_qam;
+ u8 ob_pal_off;
+ u8 futureModal[30];
+ struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
+} __attribute__((packed));
+
+struct cal_data_per_freq {
+ u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+ u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+} __attribute__((packed));
+
+struct cal_data_per_freq_4k {
+ u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+ u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+} __attribute__((packed));
+
+struct cal_target_power_leg {
+ u8 bChannel;
+ u8 tPow2x[4];
+} __attribute__((packed));
+
+struct cal_target_power_ht {
+ u8 bChannel;
+ u8 tPow2x[8];
+} __attribute__((packed));
+
+struct cal_ctl_edges {
+ u8 bChannel;
+ u8 ctl;
+} __attribute__((packed));
+
+struct cal_data_op_loop_ar9287 {
+ u8 pwrPdg[2][5];
+ u8 vpdPdg[2][5];
+ u8 pcdac[2][5];
+ u8 empty[2][5];
+} __attribute__((packed));
+
+struct cal_data_per_freq_ar9287 {
+ u8 pwrPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
+ u8 vpdPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
+} __attribute__((packed));
+
+union cal_data_per_freq_ar9287_u {
+ struct cal_data_op_loop_ar9287 calDataOpen;
+ struct cal_data_per_freq_ar9287 calDataClose;
+} __attribute__((packed));
+
+struct cal_ctl_data_ar9287 {
+ struct cal_ctl_edges
+ ctlEdges[AR9287_MAX_CHAINS][AR9287_NUM_BAND_EDGES];
+} __attribute__((packed));
+
+struct cal_ctl_data {
+ struct cal_ctl_edges
+ ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
+} __attribute__((packed));
+
+struct cal_ctl_data_4k {
+ struct cal_ctl_edges
+ ctlEdges[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_BAND_EDGES];
+} __attribute__((packed));
+
+struct ar5416_eeprom_def {
+ struct base_eep_header baseEepHeader;
+ u8 custData[64];
+ struct modal_eep_header modalHeader[2];
+ u8 calFreqPier5G[AR5416_NUM_5G_CAL_PIERS];
+ u8 calFreqPier2G[AR5416_NUM_2G_CAL_PIERS];
+ struct cal_data_per_freq
+ calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS];
+ struct cal_data_per_freq
+ calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
+ struct cal_target_power_leg
+ calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS];
+ struct cal_target_power_leg
+ calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS];
+ struct cal_target_power_leg
+ calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS];
+ u8 ctlIndex[AR5416_NUM_CTLS];
+ struct cal_ctl_data ctlData[AR5416_NUM_CTLS];
+ u8 padding;
+} __attribute__((packed));
+
+struct ar5416_eeprom_4k {
+ struct base_eep_header_4k baseEepHeader;
+ u8 custData[20];
+ struct modal_eep_4k_header modalHeader;
+ u8 calFreqPier2G[AR5416_EEP4K_NUM_2G_CAL_PIERS];
+ struct cal_data_per_freq_4k
+ calPierData2G[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_2G_CAL_PIERS];
+ struct cal_target_power_leg
+ calTargetPowerCck[AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS];
+ struct cal_target_power_leg
+ calTargetPower2G[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT20[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT40[AR5416_EEP4K_NUM_2G_40_TARGET_POWERS];
+ u8 ctlIndex[AR5416_EEP4K_NUM_CTLS];
+ struct cal_ctl_data_4k ctlData[AR5416_EEP4K_NUM_CTLS];
+ u8 padding;
+} __attribute__((packed));
+
+struct ar9287_eeprom {
+ struct base_eep_ar9287_header baseEepHeader;
+ u8 custData[AR9287_DATA_SZ];
+ struct modal_eep_ar9287_header modalHeader;
+ u8 calFreqPier2G[AR9287_NUM_2G_CAL_PIERS];
+ union cal_data_per_freq_ar9287_u
+ calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS];
+ struct cal_target_power_leg
+ calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS];
+ struct cal_target_power_leg
+ calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS];
+ u8 ctlIndex[AR9287_NUM_CTLS];
+ struct cal_ctl_data_ar9287 ctlData[AR9287_NUM_CTLS];
+ u8 padding;
+} __attribute__((packed));
+
+enum reg_ext_bitmap {
+ REG_EXT_FCC_MIDBAND = 0,
+ REG_EXT_JAPAN_MIDBAND = 1,
+ REG_EXT_FCC_DFS_HT40 = 2,
+ REG_EXT_JAPAN_NONDFS_HT40 = 3,
+ REG_EXT_JAPAN_DFS_HT40 = 4
+};
+
+struct ath9k_country_entry {
+ u16 countryCode;
+ u16 regDmnEnum;
+ u16 regDmn5G;
+ u16 regDmn2G;
+ u8 isMultidomain;
+ u8 iso[3];
+};
+
+struct eeprom_ops {
+ int (*check_eeprom)(struct ath_hw *hw);
+ u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param);
+ int (*fill_eeprom)(struct ath_hw *hw);
+ int (*get_eeprom_ver)(struct ath_hw *hw);
+ int (*get_eeprom_rev)(struct ath_hw *hw);
+ void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
+ void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
+ void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
+ u16 cfgCtl, u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower, u8 powerLimit,
+ int test);
+ u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, int is2GHz);
+};
+
+void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val);
+void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
+ u32 shift, u32 val);
+int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
+ int16_t targetLeft,
+ int16_t targetRight);
+int ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
+ u16 *indexL, u16 *indexR);
+int ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data);
+void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
+ int eep_start_loc, int size);
+void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
+ u8 *pVpdList, u16 numIntercepts,
+ u8 *pRetVpdList);
+void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct cal_target_power_leg *powInfo,
+ u16 numChannels,
+ struct cal_target_power_leg *pNewPower,
+ u16 numRates, int isExtTarget);
+void ath9k_hw_get_target_powers(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct cal_target_power_ht *powInfo,
+ u16 numChannels,
+ struct cal_target_power_ht *pNewPower,
+ u16 numRates, int isHt40Target);
+u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
+ int is2GHz, int num_band_edges);
+void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah);
+int ath9k_hw_eeprom_init(struct ath_hw *ah);
+
+void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ void *pRawDataSet,
+ u8 *bChans, u16 availPiers,
+ u16 tPdGainOverlap,
+ u16 *pPdGainBoundaries, u8 *pPDADCValues,
+ u16 numXpdGains);
+
+#define ar5416_get_ntxchains(_txchainmask) \
+ (((_txchainmask >> 2) & 1) + \
+ ((_txchainmask >> 1) & 1) + (_txchainmask & 1))
+
+extern const struct eeprom_ops eep_def_ops;
+extern const struct eeprom_ops eep_4k_ops;
+extern const struct eeprom_ops eep_ar9287_ops;
+extern const struct eeprom_ops eep_ar9287_ops;
+extern const struct eeprom_ops eep_ar9300_ops;
+
+#endif /* EEPROM_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/hw-ops.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/hw-ops.h
new file mode 100644
index 00000000..65cff3b0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/hw-ops.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ATH9K_HW_OPS_H
+#define ATH9K_HW_OPS_H
+
+#include "hw.h"
+
+/* Hardware core and driver accessible callbacks */
+
+static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah,
+ int restore,
+ int power_off)
+{
+ ath9k_hw_ops(ah)->config_pci_powersave(ah, restore, power_off);
+}
+
+static inline void ath9k_hw_rxena(struct ath_hw *ah)
+{
+ ath9k_hw_ops(ah)->rx_enable(ah);
+}
+
+static inline void ath9k_hw_set_desc_link(struct ath_hw *ah, void *ds,
+ u32 link)
+{
+ ath9k_hw_ops(ah)->set_desc_link(ds, link);
+}
+
+static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds,
+ u32 **link)
+{
+ ath9k_hw_ops(ah)->get_desc_link(ds, link);
+}
+static inline int ath9k_hw_calibrate(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 rxchainmask,
+ int longcal)
+{
+ return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal);
+}
+
+static inline int ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
+{
+ return ath9k_hw_ops(ah)->get_isr(ah, masked);
+}
+
+static inline void ath9k_hw_filltxdesc(struct ath_hw *ah, void *ds, u32 seglen,
+ int is_firstseg, int is_lastseg,
+ const void *ds0, u32 buf_addr,
+ unsigned int qcu)
+{
+ ath9k_hw_ops(ah)->fill_txdesc(ah, ds, seglen, is_firstseg, is_lastseg,
+ ds0, buf_addr, qcu);
+}
+
+static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
+ struct ath_tx_status *ts)
+{
+ return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
+}
+
+static inline void ath9k_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
+ u32 pktLen, enum ath9k_pkt_type type,
+ u32 txPower, u32 keyIx,
+ enum ath9k_key_type keyType,
+ u32 flags)
+{
+ ath9k_hw_ops(ah)->set11n_txdesc(ah, ds, pktLen, type, txPower, keyIx,
+ keyType, flags);
+}
+
+static inline void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
+ void *lastds,
+ u32 durUpdateEn, u32 rtsctsRate,
+ u32 rtsctsDuration,
+ struct ath9k_11n_rate_series series[],
+ u32 nseries, u32 flags)
+{
+ ath9k_hw_ops(ah)->set11n_ratescenario(ah, ds, lastds, durUpdateEn,
+ rtsctsRate, rtsctsDuration, series,
+ nseries, flags);
+}
+
+static inline void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
+ u32 aggrLen)
+{
+ ath9k_hw_ops(ah)->set11n_aggr_first(ah, ds, aggrLen);
+}
+
+static inline void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
+ u32 numDelims)
+{
+ ath9k_hw_ops(ah)->set11n_aggr_middle(ah, ds, numDelims);
+}
+
+static inline void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
+{
+ ath9k_hw_ops(ah)->set11n_aggr_last(ah, ds);
+}
+
+static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
+{
+ ath9k_hw_ops(ah)->clr11n_aggr(ah, ds);
+}
+
+static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, int val)
+{
+ ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
+}
+
+static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf)
+{
+ ath9k_hw_ops(ah)->antdiv_comb_conf_get(ah, antconf);
+}
+
+static inline void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf)
+{
+ ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf);
+}
+
+/* Private hardware call ops */
+
+/* PHY ops */
+
+static inline int ath9k_hw_rf_set_freq(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ return ath9k_hw_private_ops(ah)->rf_set_freq(ah, chan);
+}
+
+static inline void ath9k_hw_spur_mitigate_freq(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ ath9k_hw_private_ops(ah)->spur_mitigate_freq(ah, chan);
+}
+
+static inline int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah)
+{
+ if (!ath9k_hw_private_ops(ah)->rf_alloc_ext_banks)
+ return 0;
+
+ return ath9k_hw_private_ops(ah)->rf_alloc_ext_banks(ah);
+}
+
+static inline void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah)
+{
+ if (!ath9k_hw_private_ops(ah)->rf_free_ext_banks)
+ return;
+
+ ath9k_hw_private_ops(ah)->rf_free_ext_banks(ah);
+}
+
+static inline int ath9k_hw_set_rf_regs(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u16 modesIndex)
+{
+ if (!ath9k_hw_private_ops(ah)->set_rf_regs)
+ return 1;
+
+ return ath9k_hw_private_ops(ah)->set_rf_regs(ah, chan, modesIndex);
+}
+
+static inline void ath9k_hw_init_bb(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ return ath9k_hw_private_ops(ah)->init_bb(ah, chan);
+}
+
+static inline void ath9k_hw_set_channel_regs(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ return ath9k_hw_private_ops(ah)->set_channel_regs(ah, chan);
+}
+
+static inline int ath9k_hw_process_ini(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ return ath9k_hw_private_ops(ah)->process_ini(ah, chan);
+}
+
+static inline void ath9k_olc_init(struct ath_hw *ah)
+{
+ if (!ath9k_hw_private_ops(ah)->olc_init)
+ return;
+
+ return ath9k_hw_private_ops(ah)->olc_init(ah);
+}
+
+static inline void ath9k_hw_set_rfmode(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ return ath9k_hw_private_ops(ah)->set_rfmode(ah, chan);
+}
+
+static inline void ath9k_hw_mark_phy_inactive(struct ath_hw *ah)
+{
+ return ath9k_hw_private_ops(ah)->mark_phy_inactive(ah);
+}
+
+static inline void ath9k_hw_set_delta_slope(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ return ath9k_hw_private_ops(ah)->set_delta_slope(ah, chan);
+}
+
+static inline int ath9k_hw_rfbus_req(struct ath_hw *ah)
+{
+ return ath9k_hw_private_ops(ah)->rfbus_req(ah);
+}
+
+static inline void ath9k_hw_rfbus_done(struct ath_hw *ah)
+{
+ return ath9k_hw_private_ops(ah)->rfbus_done(ah);
+}
+
+static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah)
+{
+ if (!ath9k_hw_private_ops(ah)->restore_chainmask)
+ return;
+
+ return ath9k_hw_private_ops(ah)->restore_chainmask(ah);
+}
+
+static inline void ath9k_hw_set_diversity(struct ath_hw *ah, int value)
+{
+ return ath9k_hw_private_ops(ah)->set_diversity(ah, value);
+}
+
+static inline int ath9k_hw_ani_control(struct ath_hw *ah,
+ enum ath9k_ani_cmd cmd, int param)
+{
+ return ath9k_hw_private_ops(ah)->ani_control(ah, cmd, param);
+}
+
+static inline void ath9k_hw_do_getnf(struct ath_hw *ah,
+ int16_t nfarray[NUM_NF_READINGS])
+{
+ ath9k_hw_private_ops(ah)->do_getnf(ah, nfarray);
+}
+
+static inline int ath9k_hw_init_cal(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ return ath9k_hw_private_ops(ah)->init_cal(ah, chan);
+}
+
+static inline void ath9k_hw_setup_calibration(struct ath_hw *ah,
+ struct ath9k_cal_list *currCal)
+{
+ ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal);
+}
+
+#endif /* ATH9K_HW_OPS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/hw.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/hw.h
new file mode 100644
index 00000000..c10df388
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/hw.h
@@ -0,0 +1,995 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HW_H
+#define HW_H
+
+#include <errno.h>
+
+#include "mac.h"
+#include "ani.h"
+#include "eeprom.h"
+#include "calib.h"
+#include "reg.h"
+#include "phy.h"
+
+#include "../regd.h"
+
+/* Keep all ath9k files under one errfile ID */
+#undef ERRFILE
+#define ERRFILE ERRFILE_ath9k
+
+#define ATHEROS_VENDOR_ID 0x168c
+
+#define AR5416_DEVID_PCI 0x0023
+#define AR5416_DEVID_PCIE 0x0024
+#define AR9160_DEVID_PCI 0x0027
+#define AR9280_DEVID_PCI 0x0029
+#define AR9280_DEVID_PCIE 0x002a
+#define AR9285_DEVID_PCIE 0x002b
+#define AR2427_DEVID_PCIE 0x002c
+#define AR9287_DEVID_PCI 0x002d
+#define AR9287_DEVID_PCIE 0x002e
+#define AR9300_DEVID_PCIE 0x0030
+#define AR9300_DEVID_AR9340 0x0031
+#define AR9300_DEVID_AR9485_PCIE 0x0032
+
+#define AR5416_AR9100_DEVID 0x000b
+
+#define AR_SUBVENDOR_ID_NOG 0x0e11
+#define AR_SUBVENDOR_ID_NEW_A 0x7065
+#define AR5416_MAGIC 0x19641014
+
+#define AR9280_COEX2WIRE_SUBSYSID 0x309b
+#define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa
+#define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab
+
+#define AR9300_NUM_BT_WEIGHTS 4
+#define AR9300_NUM_WLAN_WEIGHTS 4
+
+#define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1)
+
+#define ATH_DEFAULT_NOISE_FLOOR -95
+
+#define ATH9K_RSSI_BAD -128
+
+#define ATH9K_NUM_CHANNELS 38
+
+/* Register read/write primitives */
+#define REG_WRITE(_ah, _reg, _val) \
+ (_ah)->reg_ops.write((_ah), (_val), (_reg))
+
+#define REG_READ(_ah, _reg) \
+ (_ah)->reg_ops.read((_ah), (_reg))
+
+#define REG_READ_MULTI(_ah, _addr, _val, _cnt) \
+ (_ah)->reg_ops.multi_read((_ah), (_addr), (_val), (_cnt))
+
+#define REG_RMW(_ah, _reg, _set, _clr) \
+ (_ah)->reg_ops.rmw((_ah), (_reg), (_set), (_clr))
+
+#define ENABLE_REGWRITE_BUFFER(_ah) \
+ do { \
+ if ((_ah)->reg_ops.enable_write_buffer) \
+ (_ah)->reg_ops.enable_write_buffer((_ah)); \
+ } while (0)
+
+#define REGWRITE_BUFFER_FLUSH(_ah) \
+ do { \
+ if ((_ah)->reg_ops.write_flush) \
+ (_ah)->reg_ops.write_flush((_ah)); \
+ } while (0)
+
+#define SM(_v, _f) (((_v) << _f##_S) & _f)
+#define MS(_v, _f) (((_v) & _f) >> _f##_S)
+#define REG_RMW_FIELD(_a, _r, _f, _v) \
+ REG_RMW(_a, _r, (((_v) << _f##_S) & _f), (_f))
+#define REG_READ_FIELD(_a, _r, _f) \
+ (((REG_READ(_a, _r) & _f) >> _f##_S))
+#define REG_SET_BIT(_a, _r, _f) \
+ REG_RMW(_a, _r, (_f), 0)
+#define REG_CLR_BIT(_a, _r, _f) \
+ REG_RMW(_a, _r, 0, (_f))
+
+#define DO_DELAY(x) do { \
+ if (((++(x) % 64) == 0) && \
+ (ath9k_hw_common(ah)->bus_ops->ath_bus_type \
+ != ATH_USB)) \
+ udelay(1); \
+ } while (0)
+
+#define REG_WRITE_ARRAY(iniarray, column, regWr) \
+ ath9k_hw_write_array(ah, iniarray, column, &(regWr))
+
+#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0
+#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
+#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2
+#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3
+#define AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL 4
+#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5
+#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6
+
+#define AR_GPIOD_MASK 0x00001FFF
+#define AR_GPIO_BIT(_gpio) (1 << (_gpio))
+
+#define BASE_ACTIVATE_DELAY 100
+#define RTC_PLL_SETTLE_DELAY (AR_SREV_9340(ah) ? 1000 : 100)
+#define COEF_SCALE_S 24
+#define HT40_CHANNEL_CENTER_SHIFT 10
+
+#define ATH9K_ANTENNA0_CHAINMASK 0x1
+#define ATH9K_ANTENNA1_CHAINMASK 0x2
+
+#define ATH9K_NUM_DMA_DEBUG_REGS 8
+#define ATH9K_NUM_QUEUES 10
+
+#define MAX_RATE_POWER 63
+#define AH_WAIT_TIMEOUT 100000 /* (us) */
+#define AH_TSF_WRITE_TIMEOUT 100 /* (us) */
+#define AH_TIME_QUANTUM 10
+#define AR_KEYTABLE_SIZE 128
+#define POWER_UP_TIME 10000
+#define SPUR_RSSI_THRESH 40
+
+#define CAB_TIMEOUT_VAL 10
+#define BEACON_TIMEOUT_VAL 10
+#define MIN_BEACON_TIMEOUT_VAL 1
+#define SLEEP_SLOP 3
+
+#define INIT_CONFIG_STATUS 0x00000000
+#define INIT_RSSI_THR 0x00000700
+#define INIT_BCON_CNTRL_REG 0x00000000
+
+#define TU_TO_USEC(_tu) ((_tu) << 10)
+
+#define ATH9K_HW_RX_HP_QDEPTH 16
+#define ATH9K_HW_RX_LP_QDEPTH 128
+
+#define PAPRD_GAIN_TABLE_ENTRIES 32
+#define PAPRD_TABLE_SZ 24
+
+enum ath_hw_txq_subtype {
+ ATH_TXQ_AC_BE = 0,
+};
+
+enum ath_ini_subsys {
+ ATH_INI_PRE = 0,
+ ATH_INI_CORE,
+ ATH_INI_POST,
+ ATH_INI_NUM_SPLIT,
+};
+
+enum ath9k_hw_caps {
+ ATH9K_HW_CAP_HT = BIT(0),
+ ATH9K_HW_CAP_RFSILENT = BIT(1),
+ ATH9K_HW_CAP_CST = BIT(2),
+ ATH9K_HW_CAP_AUTOSLEEP = BIT(4),
+ ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(5),
+ ATH9K_HW_CAP_EDMA = BIT(6),
+ ATH9K_HW_CAP_RAC_SUPPORTED = BIT(7),
+ ATH9K_HW_CAP_LDPC = BIT(8),
+ ATH9K_HW_CAP_FASTCLOCK = BIT(9),
+ ATH9K_HW_CAP_SGI_20 = BIT(10),
+ ATH9K_HW_CAP_PAPRD = BIT(11),
+ ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12),
+ ATH9K_HW_CAP_2GHZ = BIT(13),
+ ATH9K_HW_CAP_5GHZ = BIT(14),
+ ATH9K_HW_CAP_APM = BIT(15),
+};
+
+struct ath9k_hw_capabilities {
+ u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
+ u16 rts_aggr_limit;
+ u8 tx_chainmask;
+ u8 rx_chainmask;
+ u8 max_txchains;
+ u8 max_rxchains;
+ u8 num_gpio_pins;
+ u8 rx_hp_qdepth;
+ u8 rx_lp_qdepth;
+ u8 rx_status_len;
+ u8 tx_desc_len;
+ u8 txs_len;
+ u16 pcie_lcr_offset;
+ int pcie_lcr_extsync_en;
+};
+
+struct ath9k_ops_config {
+ int dma_beacon_response_time;
+ int sw_beacon_response_time;
+ int additional_swba_backoff;
+ int ack_6mb;
+ u32 cwm_ignore_extcca;
+ u8 pcie_powersave_enable;
+ int pcieSerDesWrite;
+ u8 pcie_clock_req;
+ u32 pcie_waen;
+ u8 analog_shiftreg;
+ u8 paprd_disable;
+ u32 ofdm_trig_low;
+ u32 ofdm_trig_high;
+ u32 cck_trig_high;
+ u32 cck_trig_low;
+ u32 enable_ani;
+ int serialize_regmode;
+ int rx_intr_mitigation;
+ int tx_intr_mitigation;
+#define SPUR_DISABLE 0
+#define SPUR_ENABLE_IOCTL 1
+#define SPUR_ENABLE_EEPROM 2
+#define AR_SPUR_5413_1 1640
+#define AR_SPUR_5413_2 1200
+#define AR_NO_SPUR 0x8000
+#define AR_BASE_FREQ_2GHZ 2300
+#define AR_BASE_FREQ_5GHZ 4900
+#define AR_SPUR_FEEQ_BOUND_HT40 19
+#define AR_SPUR_FEEQ_BOUND_HT20 10
+ int spurmode;
+ u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
+ u8 max_txtrig_level;
+ u16 ani_poll_interval; /* ANI poll interval in ms */
+};
+
+enum ath9k_int {
+ ATH9K_INT_RX = 0x00000001,
+ ATH9K_INT_RXDESC = 0x00000002,
+ ATH9K_INT_RXHP = 0x00000001,
+ ATH9K_INT_RXLP = 0x00000002,
+ ATH9K_INT_RXNOFRM = 0x00000008,
+ ATH9K_INT_RXEOL = 0x00000010,
+ ATH9K_INT_RXORN = 0x00000020,
+ ATH9K_INT_TX = 0x00000040,
+ ATH9K_INT_TXDESC = 0x00000080,
+ ATH9K_INT_TIM_TIMER = 0x00000100,
+ ATH9K_INT_BB_WATCHDOG = 0x00000400,
+ ATH9K_INT_TXURN = 0x00000800,
+ ATH9K_INT_MIB = 0x00001000,
+ ATH9K_INT_RXPHY = 0x00004000,
+ ATH9K_INT_RXKCM = 0x00008000,
+ ATH9K_INT_SWBA = 0x00010000,
+ ATH9K_INT_BMISS = 0x00040000,
+ ATH9K_INT_BNR = 0x00100000,
+ ATH9K_INT_TIM = 0x00200000,
+ ATH9K_INT_DTIM = 0x00400000,
+ ATH9K_INT_DTIMSYNC = 0x00800000,
+ ATH9K_INT_GPIO = 0x01000000,
+ ATH9K_INT_CABEND = 0x02000000,
+ ATH9K_INT_TSFOOR = 0x04000000,
+ ATH9K_INT_GENTIMER = 0x08000000,
+ ATH9K_INT_CST = 0x10000000,
+ ATH9K_INT_GTT = 0x20000000,
+ ATH9K_INT_FATAL = 0x40000000,
+ ATH9K_INT_GLOBAL = 0x80000000,
+ ATH9K_INT_BMISC = ATH9K_INT_TIM |
+ ATH9K_INT_DTIM |
+ ATH9K_INT_DTIMSYNC |
+ ATH9K_INT_TSFOOR |
+ ATH9K_INT_CABEND,
+ ATH9K_INT_COMMON = ATH9K_INT_RXNOFRM |
+ ATH9K_INT_RXDESC |
+ ATH9K_INT_RXEOL |
+ ATH9K_INT_RXORN |
+ ATH9K_INT_TXURN |
+ ATH9K_INT_TXDESC |
+ ATH9K_INT_MIB |
+ ATH9K_INT_RXPHY |
+ ATH9K_INT_RXKCM |
+ ATH9K_INT_SWBA |
+ ATH9K_INT_BMISS |
+ ATH9K_INT_GPIO,
+ ATH9K_INT_NOCARD = 0xffffffff
+};
+
+#define CHANNEL_CW_INT 0x00002
+#define CHANNEL_CCK 0x00020
+#define CHANNEL_OFDM 0x00040
+#define CHANNEL_2GHZ 0x00080
+#define CHANNEL_5GHZ 0x00100
+#define CHANNEL_PASSIVE 0x00200
+#define CHANNEL_DYN 0x00400
+#define CHANNEL_HALF 0x04000
+#define CHANNEL_QUARTER 0x08000
+#define CHANNEL_HT20 0x10000
+#define CHANNEL_HT40PLUS 0x20000
+#define CHANNEL_HT40MINUS 0x40000
+
+#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM)
+#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK)
+#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM)
+#define CHANNEL_G_HT20 (CHANNEL_2GHZ|CHANNEL_HT20)
+#define CHANNEL_A_HT20 (CHANNEL_5GHZ|CHANNEL_HT20)
+#define CHANNEL_G_HT40PLUS (CHANNEL_2GHZ|CHANNEL_HT40PLUS)
+#define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS)
+#define CHANNEL_A_HT40PLUS (CHANNEL_5GHZ|CHANNEL_HT40PLUS)
+#define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS)
+#define CHANNEL_ALL \
+ (CHANNEL_OFDM| \
+ CHANNEL_CCK| \
+ CHANNEL_2GHZ | \
+ CHANNEL_5GHZ | \
+ CHANNEL_HT20 | \
+ CHANNEL_HT40PLUS | \
+ CHANNEL_HT40MINUS)
+
+struct ath9k_hw_cal_data {
+ u16 channel;
+ u32 channelFlags;
+ int32_t CalValid;
+ int8_t iCoff;
+ int8_t qCoff;
+ int paprd_done;
+ int nfcal_pending;
+ int nfcal_interference;
+ u16 small_signal_gain[AR9300_MAX_CHAINS];
+ u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
+ struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
+};
+
+struct ath9k_channel {
+ struct net80211_channel *chan;
+ struct ar5416AniState ani;
+ u16 channel;
+ u32 channelFlags;
+ u32 chanmode;
+ s16 noisefloor;
+};
+
+#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
+ (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \
+ (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \
+ (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS))
+#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0)
+#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0)
+#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
+#define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0)
+#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
+#define IS_CHAN_A_FAST_CLOCK(_ah, _c) \
+ ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \
+ ((_ah)->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK))
+
+/* These macros check chanmode and not channelFlags */
+#define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B)
+#define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \
+ ((_c)->chanmode == CHANNEL_G_HT20))
+#define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \
+ ((_c)->chanmode == CHANNEL_A_HT40MINUS) || \
+ ((_c)->chanmode == CHANNEL_G_HT40PLUS) || \
+ ((_c)->chanmode == CHANNEL_G_HT40MINUS))
+#define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c)))
+
+enum ath9k_power_mode {
+ ATH9K_PM_AWAKE = 0,
+ ATH9K_PM_FULL_SLEEP,
+ ATH9K_PM_NETWORK_SLEEP,
+ ATH9K_PM_UNDEFINED
+};
+
+enum ath9k_tp_scale {
+ ATH9K_TP_SCALE_MAX = 0,
+ ATH9K_TP_SCALE_50,
+ ATH9K_TP_SCALE_25,
+ ATH9K_TP_SCALE_12,
+ ATH9K_TP_SCALE_MIN
+};
+
+enum ser_reg_mode {
+ SER_REG_MODE_OFF = 0,
+ SER_REG_MODE_ON = 1,
+ SER_REG_MODE_AUTO = 2,
+};
+
+enum ath9k_rx_qtype {
+ ATH9K_RX_QUEUE_HP,
+ ATH9K_RX_QUEUE_LP,
+ ATH9K_RX_QUEUE_MAX,
+};
+
+struct ath9k_beacon_state {
+ u32 bs_nexttbtt;
+ u32 bs_nextdtim;
+ u32 bs_intval;
+#define ATH9K_BEACON_PERIOD 0x0000ffff
+#define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */
+ u32 bs_dtimperiod;
+ u16 bs_cfpperiod;
+ u16 bs_cfpmaxduration;
+ u32 bs_cfpnext;
+ u16 bs_timoffset;
+ u16 bs_bmissthreshold;
+ u32 bs_sleepduration;
+ u32 bs_tsfoor_threshold;
+};
+
+struct chan_centers {
+ u16 synth_center;
+ u16 ctl_center;
+ u16 ext_center;
+};
+
+enum {
+ ATH9K_RESET_POWER_ON,
+ ATH9K_RESET_WARM,
+ ATH9K_RESET_COLD,
+};
+
+struct ath9k_hw_version {
+ u32 magic;
+ u16 devid;
+ u16 subvendorid;
+ u32 macVersion;
+ u16 macRev;
+ u16 phyRev;
+ u16 analog5GhzRev;
+ u16 analog2GhzRev;
+ u16 subsysid;
+ enum ath_usb_dev usbdev;
+};
+
+/* Generic TSF timer definitions */
+
+#define ATH_MAX_GEN_TIMER 16
+
+#define AR_GENTMR_BIT(_index) (1 << (_index))
+
+/*
+ * Using de Bruijin sequence to look up 1's index in a 32 bit number
+ * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001
+ */
+#define debruijn32 0x077CB531U
+
+struct ath_gen_timer_configuration {
+ u32 next_addr;
+ u32 period_addr;
+ u32 mode_addr;
+ u32 mode_mask;
+};
+
+struct ath_gen_timer {
+ void (*trigger)(void *arg);
+ void (*overflow)(void *arg);
+ void *arg;
+ u8 index;
+};
+
+struct ath_gen_timer_table {
+ u32 gen_timer_index[32];
+ struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER];
+ union {
+ unsigned long timer_bits;
+ u16 val;
+ } timer_mask;
+};
+
+struct ath_hw_antcomb_conf {
+ u8 main_lna_conf;
+ u8 alt_lna_conf;
+ u8 fast_div_bias;
+ u8 main_gaintb;
+ u8 alt_gaintb;
+ int lna1_lna2_delta;
+ u8 div_group;
+};
+
+/**
+ * struct ath_hw_radar_conf - radar detection initialization parameters
+ *
+ * @pulse_inband: threshold for checking the ratio of in-band power
+ * to total power for short radar pulses (half dB steps)
+ * @pulse_inband_step: threshold for checking an in-band power to total
+ * power ratio increase for short radar pulses (half dB steps)
+ * @pulse_height: threshold for detecting the beginning of a short
+ * radar pulse (dB step)
+ * @pulse_rssi: threshold for detecting if a short radar pulse is
+ * gone (dB step)
+ * @pulse_maxlen: maximum pulse length (0.8 us steps)
+ *
+ * @radar_rssi: RSSI threshold for starting long radar detection (dB steps)
+ * @radar_inband: threshold for checking the ratio of in-band power
+ * to total power for long radar pulses (half dB steps)
+ * @fir_power: threshold for detecting the end of a long radar pulse (dB)
+ *
+ * @ext_channel: enable extension channel radar detection
+ */
+struct ath_hw_radar_conf {
+ unsigned int pulse_inband;
+ unsigned int pulse_inband_step;
+ unsigned int pulse_height;
+ unsigned int pulse_rssi;
+ unsigned int pulse_maxlen;
+
+ unsigned int radar_rssi;
+ unsigned int radar_inband;
+ int fir_power;
+
+ int ext_channel;
+};
+
+/**
+ * struct ath_hw_private_ops - callbacks used internally by hardware code
+ *
+ * This structure contains private callbacks designed to only be used internally
+ * by the hardware core.
+ *
+ * @init_cal_settings: setup types of calibrations supported
+ * @init_cal: starts actual calibration
+ *
+ * @init_mode_regs: Initializes mode registers
+ * @init_mode_gain_regs: Initialize TX/RX gain registers
+ *
+ * @rf_set_freq: change frequency
+ * @spur_mitigate_freq: spur mitigation
+ * @rf_alloc_ext_banks:
+ * @rf_free_ext_banks:
+ * @set_rf_regs:
+ * @compute_pll_control: compute the PLL control value to use for
+ * AR_RTC_PLL_CONTROL for a given channel
+ * @setup_calibration: set up calibration
+ * @iscal_supported: used to query if a type of calibration is supported
+ *
+ * @ani_cache_ini_regs: cache the values for ANI from the initial
+ * register settings through the register initialization.
+ */
+struct ath_hw_private_ops {
+ /* Calibration ops */
+ void (*init_cal_settings)(struct ath_hw *ah);
+ int (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan);
+
+ void (*init_mode_regs)(struct ath_hw *ah);
+ void (*init_mode_gain_regs)(struct ath_hw *ah);
+ void (*setup_calibration)(struct ath_hw *ah,
+ struct ath9k_cal_list *currCal);
+
+ /* PHY ops */
+ int (*rf_set_freq)(struct ath_hw *ah,
+ struct ath9k_channel *chan);
+ void (*spur_mitigate_freq)(struct ath_hw *ah,
+ struct ath9k_channel *chan);
+ int (*rf_alloc_ext_banks)(struct ath_hw *ah);
+ void (*rf_free_ext_banks)(struct ath_hw *ah);
+ int (*set_rf_regs)(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u16 modesIndex);
+ void (*set_channel_regs)(struct ath_hw *ah, struct ath9k_channel *chan);
+ void (*init_bb)(struct ath_hw *ah,
+ struct ath9k_channel *chan);
+ int (*process_ini)(struct ath_hw *ah, struct ath9k_channel *chan);
+ void (*olc_init)(struct ath_hw *ah);
+ void (*set_rfmode)(struct ath_hw *ah, struct ath9k_channel *chan);
+ void (*mark_phy_inactive)(struct ath_hw *ah);
+ void (*set_delta_slope)(struct ath_hw *ah, struct ath9k_channel *chan);
+ int (*rfbus_req)(struct ath_hw *ah);
+ void (*rfbus_done)(struct ath_hw *ah);
+ void (*restore_chainmask)(struct ath_hw *ah);
+ void (*set_diversity)(struct ath_hw *ah, int value);
+ u32 (*compute_pll_control)(struct ath_hw *ah,
+ struct ath9k_channel *chan);
+ int (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
+ int param);
+ void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
+ void (*set_radar_params)(struct ath_hw *ah,
+ struct ath_hw_radar_conf *conf);
+
+ /* ANI */
+ void (*ani_cache_ini_regs)(struct ath_hw *ah);
+};
+
+/**
+ * struct ath_hw_ops - callbacks used by hardware code and driver code
+ *
+ * This structure contains callbacks designed to to be used internally by
+ * hardware code and also by the lower level driver.
+ *
+ * @config_pci_powersave:
+ * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
+ */
+struct ath_hw_ops {
+ void (*config_pci_powersave)(struct ath_hw *ah,
+ int restore,
+ int power_off);
+ void (*rx_enable)(struct ath_hw *ah);
+ void (*set_desc_link)(void *ds, u32 link);
+ void (*get_desc_link)(void *ds, u32 **link);
+ int (*calibrate)(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 rxchainmask,
+ int longcal);
+ int (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked);
+ void (*fill_txdesc)(struct ath_hw *ah, void *ds, u32 seglen,
+ int is_firstseg, int is_is_lastseg,
+ const void *ds0, u32 buf_addr,
+ unsigned int qcu);
+ int (*proc_txdesc)(struct ath_hw *ah, void *ds,
+ struct ath_tx_status *ts);
+ void (*set11n_txdesc)(struct ath_hw *ah, void *ds,
+ u32 pktLen, enum ath9k_pkt_type type,
+ u32 txPower, u32 keyIx,
+ enum ath9k_key_type keyType,
+ u32 flags);
+ void (*set11n_ratescenario)(struct ath_hw *ah, void *ds,
+ void *lastds,
+ u32 durUpdateEn, u32 rtsctsRate,
+ u32 rtsctsDuration,
+ struct ath9k_11n_rate_series series[],
+ u32 nseries, u32 flags);
+ void (*set11n_aggr_first)(struct ath_hw *ah, void *ds,
+ u32 aggrLen);
+ void (*set11n_aggr_middle)(struct ath_hw *ah, void *ds,
+ u32 numDelims);
+ void (*set11n_aggr_last)(struct ath_hw *ah, void *ds);
+ void (*clr11n_aggr)(struct ath_hw *ah, void *ds);
+ void (*set_clrdmask)(struct ath_hw *ah, void *ds, int val);
+ void (*antdiv_comb_conf_get)(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf);
+ void (*antdiv_comb_conf_set)(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf);
+
+};
+
+struct ath_nf_limits {
+ s16 max;
+ s16 min;
+ s16 nominal;
+};
+
+/* ah_flags */
+#define AH_USE_EEPROM 0x1
+#define AH_UNPLUGGED 0x2 /* The card has been physically removed. */
+
+struct ath_hw {
+ struct ath_ops reg_ops;
+
+ struct net80211_device *dev;
+ struct ath_common common;
+ struct ath9k_hw_version hw_version;
+ struct ath9k_ops_config config;
+ struct ath9k_hw_capabilities caps;
+ struct ath9k_channel channels[ATH9K_NUM_CHANNELS];
+ struct ath9k_channel *curchan;
+
+ union {
+ struct ar5416_eeprom_def def;
+ struct ar5416_eeprom_4k map4k;
+ struct ar9287_eeprom map9287;
+ struct ar9300_eeprom ar9300_eep;
+ } eeprom;
+ const struct eeprom_ops *eep_ops;
+
+ int sw_mgmt_crypto;
+ int is_pciexpress;
+ int is_monitoring;
+ int need_an_top2_fixup;
+ u16 tx_trig_level;
+
+ u32 nf_regs[6];
+ struct ath_nf_limits nf_2g;
+ struct ath_nf_limits nf_5g;
+ u16 rfsilent;
+ u32 rfkill_gpio;
+ u32 rfkill_polarity;
+ u32 ah_flags;
+
+ int htc_reset_init;
+
+ enum ath9k_power_mode power_mode;
+
+ struct ath9k_hw_cal_data *caldata;
+ struct ath9k_pacal_info pacal_info;
+ struct ar5416Stats stats;
+ struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
+
+ int16_t curchan_rad_index;
+ int ah_ier;
+ enum ath9k_int imask;
+ u32 imrs2_reg;
+ u32 txok_interrupt_mask;
+ u32 txerr_interrupt_mask;
+ u32 txdesc_interrupt_mask;
+ u32 txeol_interrupt_mask;
+ u32 txurn_interrupt_mask;
+ int chip_fullsleep;
+ u32 atim_window;
+
+ /* Calibration */
+ u32 supp_cals;
+ struct ath9k_cal_list iq_caldata;
+ struct ath9k_cal_list adcgain_caldata;
+ struct ath9k_cal_list adcdc_caldata;
+ struct ath9k_cal_list tempCompCalData;
+ struct ath9k_cal_list *cal_list;
+ struct ath9k_cal_list *cal_list_last;
+ struct ath9k_cal_list *cal_list_curr;
+#define totalPowerMeasI meas0.unsign
+#define totalPowerMeasQ meas1.unsign
+#define totalIqCorrMeas meas2.sign
+#define totalAdcIOddPhase meas0.unsign
+#define totalAdcIEvenPhase meas1.unsign
+#define totalAdcQOddPhase meas2.unsign
+#define totalAdcQEvenPhase meas3.unsign
+#define totalAdcDcOffsetIOddPhase meas0.sign
+#define totalAdcDcOffsetIEvenPhase meas1.sign
+#define totalAdcDcOffsetQOddPhase meas2.sign
+#define totalAdcDcOffsetQEvenPhase meas3.sign
+ union {
+ u32 unsign[AR5416_MAX_CHAINS];
+ int32_t sign[AR5416_MAX_CHAINS];
+ } meas0;
+ union {
+ u32 unsign[AR5416_MAX_CHAINS];
+ int32_t sign[AR5416_MAX_CHAINS];
+ } meas1;
+ union {
+ u32 unsign[AR5416_MAX_CHAINS];
+ int32_t sign[AR5416_MAX_CHAINS];
+ } meas2;
+ union {
+ u32 unsign[AR5416_MAX_CHAINS];
+ int32_t sign[AR5416_MAX_CHAINS];
+ } meas3;
+ u16 cal_samples;
+
+ u32 sta_id1_defaults;
+ u32 misc_mode;
+ enum {
+ AUTO_32KHZ,
+ USE_32KHZ,
+ DONT_USE_32KHZ,
+ } enable_32kHz_clock;
+
+ /* Private to hardware code */
+ struct ath_hw_private_ops private_ops;
+ /* Accessed by the lower level driver */
+ struct ath_hw_ops ops;
+
+ /* Used to program the radio on non single-chip devices */
+ u32 *analogBank0Data;
+ u32 *analogBank1Data;
+ u32 *analogBank2Data;
+ u32 *analogBank3Data;
+ u32 *analogBank6Data;
+ u32 *analogBank6TPCData;
+ u32 *analogBank7Data;
+ u32 *addac5416_21;
+ u32 *bank6Temp;
+
+ u8 txpower_limit;
+ int coverage_class;
+ u32 slottime;
+ u32 globaltxtimeout;
+
+ /* ANI */
+ u32 proc_phyerr;
+ u32 aniperiod;
+ int totalSizeDesired[5];
+ int coarse_high[5];
+ int coarse_low[5];
+ int firpwr[5];
+ enum ath9k_ani_cmd ani_function;
+
+ u32 intr_txqs;
+ u8 txchainmask;
+ u8 rxchainmask;
+
+ struct ath_hw_radar_conf radar_conf;
+
+ u32 originalGain[22];
+ int initPDADC;
+ int PDADCdelta;
+ int led_pin;
+ u32 gpio_mask;
+ u32 gpio_val;
+
+ struct ar5416IniArray iniModes;
+ struct ar5416IniArray iniCommon;
+ struct ar5416IniArray iniBank0;
+ struct ar5416IniArray iniBB_RfGain;
+ struct ar5416IniArray iniBank1;
+ struct ar5416IniArray iniBank2;
+ struct ar5416IniArray iniBank3;
+ struct ar5416IniArray iniBank6;
+ struct ar5416IniArray iniBank6TPC;
+ struct ar5416IniArray iniBank7;
+ struct ar5416IniArray iniAddac;
+ struct ar5416IniArray iniPcieSerdes;
+ struct ar5416IniArray iniPcieSerdesLowPower;
+ struct ar5416IniArray iniModesAdditional;
+ struct ar5416IniArray iniModesAdditional_40M;
+ struct ar5416IniArray iniModesRxGain;
+ struct ar5416IniArray iniModesTxGain;
+ struct ar5416IniArray iniModes_9271_1_0_only;
+ struct ar5416IniArray iniCckfirNormal;
+ struct ar5416IniArray iniCckfirJapan2484;
+ struct ar5416IniArray iniCommon_normal_cck_fir_coeff_9271;
+ struct ar5416IniArray iniCommon_japan_2484_cck_fir_coeff_9271;
+ struct ar5416IniArray iniModes_9271_ANI_reg;
+ struct ar5416IniArray iniModes_high_power_tx_gain_9271;
+ struct ar5416IniArray iniModes_normal_power_tx_gain_9271;
+
+ struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT];
+ struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT];
+ struct ar5416IniArray iniRadio[ATH_INI_NUM_SPLIT];
+ struct ar5416IniArray iniSOC[ATH_INI_NUM_SPLIT];
+
+ u32 intr_gen_timer_trigger;
+ u32 intr_gen_timer_thresh;
+ struct ath_gen_timer_table hw_gen_timers;
+
+ struct ar9003_txs *ts_ring;
+ void *ts_start;
+ u32 ts_paddr_start;
+ u32 ts_paddr_end;
+ u16 ts_tail;
+ u8 ts_size;
+
+ unsigned int paprd_target_power;
+ unsigned int paprd_training_power;
+ unsigned int paprd_ratemask;
+ unsigned int paprd_ratemask_ht40;
+ int paprd_table_write_done;
+ u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES];
+ u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES];
+ /*
+ * Store the permanent value of Reg 0x4004in WARegVal
+ * so we dont have to R/M/W. We should not be reading
+ * this register when in sleep states.
+ */
+ u32 WARegVal;
+
+ /* Enterprise mode cap */
+ u32 ent_mode;
+
+ int is_clk_25mhz;
+};
+
+struct ath_bus_ops {
+ enum ath_bus_type ath_bus_type;
+ void (*read_cachesize)(struct ath_common *common, int *csz);
+ int (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
+ void (*bt_coex_prep)(struct ath_common *common);
+ void (*extn_synch_en)(struct ath_common *common);
+};
+
+static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
+{
+ return &ah->common;
+}
+
+static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah)
+{
+ return &(ath9k_hw_common(ah)->regulatory);
+}
+
+static inline struct ath_hw_private_ops *ath9k_hw_private_ops(struct ath_hw *ah)
+{
+ return &ah->private_ops;
+}
+
+static inline struct ath_hw_ops *ath9k_hw_ops(struct ath_hw *ah)
+{
+ return &ah->ops;
+}
+
+static inline u8 get_streams(int mask)
+{
+ return !!(mask & BIT(0)) + !!(mask & BIT(1)) + !!(mask & BIT(2));
+}
+
+/* Initialization, Detach, Reset */
+const char *ath9k_hw_probe(u16 vendorid, u16 devid);
+void ath9k_hw_deinit(struct ath_hw *ah);
+int ath9k_hw_init(struct ath_hw *ah);
+int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+ struct ath9k_hw_cal_data *caldata, int bChannelChange);
+int ath9k_hw_fill_cap_info(struct ath_hw *ah);
+u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
+
+/* GPIO / RFKILL / Antennae */
+void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio);
+u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
+void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
+ u32 ah_signal_type);
+void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
+u32 ath9k_hw_getdefantenna(struct ath_hw *ah);
+void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
+
+/* General Operation */
+int ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
+void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array,
+ int column, unsigned int *writecnt);
+u32 ath9k_hw_reverse_bits(u32 val, u32 n);
+u16 ath9k_hw_computetxtime(struct ath_hw *ah,
+ u8 phy, int kbps,
+ u32 frameLen, u16 rateix, int shortPreamble);
+void ath9k_hw_get_channel_centers(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct chan_centers *centers);
+u32 ath9k_hw_getrxfilter(struct ath_hw *ah);
+void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
+int ath9k_hw_phy_disable(struct ath_hw *ah);
+int ath9k_hw_disable(struct ath_hw *ah);
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, int test);
+void ath9k_hw_setopmode(struct ath_hw *ah);
+void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
+void ath9k_hw_setbssidmask(struct ath_hw *ah);
+void ath9k_hw_write_associd(struct ath_hw *ah);
+void ath9k_hw_init_global_settings(struct ath_hw *ah);
+u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah);
+void ath9k_hw_set11nmac2040(struct ath_hw *ah);
+int ath9k_hw_check_alive(struct ath_hw *ah);
+
+int ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
+
+void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
+
+/* HTC */
+void ath9k_hw_htc_resetinit(struct ath_hw *ah);
+
+/* PHY */
+void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
+ u32 *coef_mantissa, u32 *coef_exponent);
+
+/*
+ * Code Specific to AR5008, AR9001 or AR9002,
+ * we stuff these here to avoid callbacks for AR9003.
+ */
+void ar9002_hw_cck_chan14_spread(struct ath_hw *ah);
+int ar9002_hw_rf_claim(struct ath_hw *ah);
+void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
+void ar9002_hw_update_async_fifo(struct ath_hw *ah);
+void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah);
+
+/*
+ * Code specific to AR9003, we stuff these here to avoid callbacks
+ * for older families
+ */
+void ar9003_hw_disable_phy_restart(struct ath_hw *ah);
+
+/* Hardware family op attach helpers */
+void ar5008_hw_attach_phy_ops(struct ath_hw *ah);
+void ar9002_hw_attach_phy_ops(struct ath_hw *ah);
+void ar9003_hw_attach_phy_ops(struct ath_hw *ah);
+
+void ar9002_hw_attach_calib_ops(struct ath_hw *ah);
+void ar9003_hw_attach_calib_ops(struct ath_hw *ah);
+
+void ar9002_hw_attach_ops(struct ath_hw *ah);
+void ar9003_hw_attach_ops(struct ath_hw *ah);
+
+void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan);
+/*
+ * ANI work can be shared between all families but a next
+ * generation implementation of ANI will be used only for AR9003 only
+ * for now as the other families still need to be tested with the same
+ * next generation ANI. Feel free to start testing it though for the
+ * older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani.
+ */
+extern int modparam_force_new_ani;
+void ath9k_ani_reset(struct ath_hw *ah, int is_scanning);
+void ath9k_hw_proc_mib_event(struct ath_hw *ah);
+void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
+
+#define ATH_PCIE_CAP_LINK_CTRL 0x70
+#define ATH_PCIE_CAP_LINK_L0S 1
+#define ATH_PCIE_CAP_LINK_L1 2
+
+#define ATH9K_CLOCK_RATE_CCK 22
+#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40
+#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44
+#define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/mac.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/mac.h
new file mode 100644
index 00000000..5899230e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/mac.h
@@ -0,0 +1,707 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MAC_H
+#define MAC_H
+
+#include <unistd.h>
+
+#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \
+ MS(ads->ds_rxstatus0, AR_RxRate) : \
+ (ads->ds_rxstatus3 >> 2) & 0xFF)
+
+#define set11nTries(_series, _index) \
+ (SM((_series)[_index].Tries, AR_XmitDataTries##_index))
+
+#define set11nRate(_series, _index) \
+ (SM((_series)[_index].Rate, AR_XmitRate##_index))
+
+#define set11nPktDurRTSCTS(_series, _index) \
+ (SM((_series)[_index].PktDuration, AR_PacketDur##_index) | \
+ ((_series)[_index].RateFlags & ATH9K_RATESERIES_RTS_CTS ? \
+ AR_RTSCTSQual##_index : 0))
+
+#define set11nRateFlags(_series, _index) \
+ (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \
+ AR_2040_##_index : 0) \
+ |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \
+ AR_GI##_index : 0) \
+ |((_series)[_index].RateFlags & ATH9K_RATESERIES_STBC ? \
+ AR_STBC##_index : 0) \
+ |SM((_series)[_index].ChSel, AR_ChainSel##_index))
+
+#define CCK_SIFS_TIME 10
+#define CCK_PREAMBLE_BITS 144
+#define CCK_PLCP_BITS 48
+
+#define OFDM_SIFS_TIME 16
+#define OFDM_PREAMBLE_TIME 20
+#define OFDM_PLCP_BITS 22
+#define OFDM_SYMBOL_TIME 4
+
+#define OFDM_SIFS_TIME_HALF 32
+#define OFDM_PREAMBLE_TIME_HALF 40
+#define OFDM_PLCP_BITS_HALF 22
+#define OFDM_SYMBOL_TIME_HALF 8
+
+#define OFDM_SIFS_TIME_QUARTER 64
+#define OFDM_PREAMBLE_TIME_QUARTER 80
+#define OFDM_PLCP_BITS_QUARTER 22
+#define OFDM_SYMBOL_TIME_QUARTER 16
+
+#define INIT_AIFS 2
+#define INIT_CWMIN 15
+#define INIT_CWMIN_11B 31
+#define INIT_CWMAX 1023
+#define INIT_SH_RETRY 10
+#define INIT_LG_RETRY 10
+#define INIT_SSH_RETRY 32
+#define INIT_SLG_RETRY 32
+
+#define ATH9K_SLOT_TIME_6 6
+#define ATH9K_SLOT_TIME_9 9
+#define ATH9K_SLOT_TIME_20 20
+
+#define ATH9K_TXERR_XRETRY 0x01
+#define ATH9K_TXERR_FILT 0x02
+#define ATH9K_TXERR_FIFO 0x04
+#define ATH9K_TXERR_XTXOP 0x08
+#define ATH9K_TXERR_TIMER_EXPIRED 0x10
+#define ATH9K_TX_ACKED 0x20
+#define ATH9K_TXERR_MASK \
+ (ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO | \
+ ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED)
+
+#define ATH9K_TX_BA 0x01
+#define ATH9K_TX_PWRMGMT 0x02
+#define ATH9K_TX_DESC_CFG_ERR 0x04
+#define ATH9K_TX_DATA_UNDERRUN 0x08
+#define ATH9K_TX_DELIM_UNDERRUN 0x10
+#define ATH9K_TX_SW_FILTERED 0x80
+
+/* 64 bytes */
+#define MIN_TX_FIFO_THRESHOLD 0x1
+
+/*
+ * Single stream device AR9285 and AR9271 require 2 KB
+ * to work around a hardware issue, all other devices
+ * have can use the max 4 KB limit.
+ */
+#define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1)
+
+struct ath_tx_status {
+ u32 ts_tstamp;
+ u16 ts_seqnum;
+ u8 ts_status;
+ u8 ts_rateindex;
+ int8_t ts_rssi;
+ u8 ts_shortretry;
+ u8 ts_longretry;
+ u8 ts_virtcol;
+ u8 ts_flags;
+ int8_t ts_rssi_ctl0;
+ int8_t ts_rssi_ctl1;
+ int8_t ts_rssi_ctl2;
+ int8_t ts_rssi_ext0;
+ int8_t ts_rssi_ext1;
+ int8_t ts_rssi_ext2;
+ u8 qid;
+ u16 desc_id;
+ u8 tid;
+ u32 ba_low;
+ u32 ba_high;
+ u32 evm0;
+ u32 evm1;
+ u32 evm2;
+};
+
+struct ath_rx_status {
+ u32 rs_tstamp;
+ u16 rs_datalen;
+ u8 rs_status;
+ u8 rs_phyerr;
+ int8_t rs_rssi;
+ u8 rs_keyix;
+ u8 rs_rate;
+ u8 rs_antenna;
+ u8 rs_more;
+ int8_t rs_rssi_ctl0;
+ int8_t rs_rssi_ctl1;
+ int8_t rs_rssi_ctl2;
+ int8_t rs_rssi_ext0;
+ int8_t rs_rssi_ext1;
+ int8_t rs_rssi_ext2;
+ u8 rs_isaggr;
+ u8 rs_moreaggr;
+ u8 rs_num_delims;
+ u8 rs_flags;
+ u32 evm0;
+ u32 evm1;
+ u32 evm2;
+ u32 evm3;
+ u32 evm4;
+};
+
+struct ath_htc_rx_status {
+ uint64_t rs_tstamp;
+ uint16_t rs_datalen;
+ u8 rs_status;
+ u8 rs_phyerr;
+ int8_t rs_rssi;
+ int8_t rs_rssi_ctl0;
+ int8_t rs_rssi_ctl1;
+ int8_t rs_rssi_ctl2;
+ int8_t rs_rssi_ext0;
+ int8_t rs_rssi_ext1;
+ int8_t rs_rssi_ext2;
+ u8 rs_keyix;
+ u8 rs_rate;
+ u8 rs_antenna;
+ u8 rs_more;
+ u8 rs_isaggr;
+ u8 rs_moreaggr;
+ u8 rs_num_delims;
+ u8 rs_flags;
+ u8 rs_dummy;
+ uint32_t evm0;
+ uint32_t evm1;
+ uint32_t evm2;
+};
+
+#define ATH9K_RXERR_CRC 0x01
+#define ATH9K_RXERR_PHY 0x02
+#define ATH9K_RXERR_FIFO 0x04
+#define ATH9K_RXERR_DECRYPT 0x08
+#define ATH9K_RXERR_MIC 0x10
+
+#define ATH9K_RX_MORE 0x01
+#define ATH9K_RX_MORE_AGGR 0x02
+#define ATH9K_RX_GI 0x04
+#define ATH9K_RX_2040 0x08
+#define ATH9K_RX_DELIM_CRC_PRE 0x10
+#define ATH9K_RX_DELIM_CRC_POST 0x20
+#define ATH9K_RX_DECRYPT_BUSY 0x40
+
+#define ATH9K_RXKEYIX_INVALID ((u8)-1)
+#define ATH9K_TXKEYIX_INVALID ((u32)-1)
+
+enum ath9k_phyerr {
+ ATH9K_PHYERR_UNDERRUN = 0, /* Transmit underrun */
+ ATH9K_PHYERR_TIMING = 1, /* Timing error */
+ ATH9K_PHYERR_PARITY = 2, /* Illegal parity */
+ ATH9K_PHYERR_RATE = 3, /* Illegal rate */
+ ATH9K_PHYERR_LENGTH = 4, /* Illegal length */
+ ATH9K_PHYERR_RADAR = 5, /* Radar detect */
+ ATH9K_PHYERR_SERVICE = 6, /* Illegal service */
+ ATH9K_PHYERR_TOR = 7, /* Transmit override receive */
+
+ ATH9K_PHYERR_OFDM_TIMING = 17,
+ ATH9K_PHYERR_OFDM_SIGNAL_PARITY = 18,
+ ATH9K_PHYERR_OFDM_RATE_ILLEGAL = 19,
+ ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL = 20,
+ ATH9K_PHYERR_OFDM_POWER_DROP = 21,
+ ATH9K_PHYERR_OFDM_SERVICE = 22,
+ ATH9K_PHYERR_OFDM_RESTART = 23,
+ ATH9K_PHYERR_FALSE_RADAR_EXT = 24,
+
+ ATH9K_PHYERR_CCK_TIMING = 25,
+ ATH9K_PHYERR_CCK_HEADER_CRC = 26,
+ ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27,
+ ATH9K_PHYERR_CCK_SERVICE = 30,
+ ATH9K_PHYERR_CCK_RESTART = 31,
+ ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 32,
+ ATH9K_PHYERR_CCK_POWER_DROP = 33,
+
+ ATH9K_PHYERR_HT_CRC_ERROR = 34,
+ ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35,
+ ATH9K_PHYERR_HT_RATE_ILLEGAL = 36,
+
+ ATH9K_PHYERR_MAX = 37,
+};
+
+struct ath_desc {
+ u32 ds_link;
+ u32 ds_data;
+ u32 ds_ctl0;
+ u32 ds_ctl1;
+ u32 ds_hw[20];
+// void *ds_vdata;
+} __attribute__((packed, aligned(4)));
+
+#define ATH9K_TXDESC_NOACK 0x0002
+#define ATH9K_TXDESC_RTSENA 0x0004
+#define ATH9K_TXDESC_CTSENA 0x0008
+/* ATH9K_TXDESC_INTREQ forces a tx interrupt to be generated for
+ * the descriptor its marked on. We take a tx interrupt to reap
+ * descriptors when the h/w hits an EOL condition or
+ * when the descriptor is specifically marked to generate
+ * an interrupt with this flag. Descriptors should be
+ * marked periodically to insure timely replenishing of the
+ * supply needed for sending frames. Defering interrupts
+ * reduces system load and potentially allows more concurrent
+ * work to be done but if done to aggressively can cause
+ * senders to backup. When the hardware queue is left too
+ * large rate control information may also be too out of
+ * date. An Alternative for this is TX interrupt mitigation
+ * but this needs more testing. */
+#define ATH9K_TXDESC_INTREQ 0x0010
+#define ATH9K_TXDESC_VEOL 0x0020
+#define ATH9K_TXDESC_EXT_ONLY 0x0040
+#define ATH9K_TXDESC_EXT_AND_CTL 0x0080
+#define ATH9K_TXDESC_VMF 0x0100
+#define ATH9K_TXDESC_FRAG_IS_ON 0x0200
+#define ATH9K_TXDESC_LOWRXCHAIN 0x0400
+#define ATH9K_TXDESC_LDPC 0x00010000
+
+#define ATH9K_RXDESC_INTREQ 0x0020
+
+struct ar5416_desc {
+ u32 ds_link;
+ u32 ds_data;
+ u32 ds_ctl0;
+ u32 ds_ctl1;
+ union {
+ struct {
+ u32 ctl2;
+ u32 ctl3;
+ u32 ctl4;
+ u32 ctl5;
+ u32 ctl6;
+ u32 ctl7;
+ u32 ctl8;
+ u32 ctl9;
+ u32 ctl10;
+ u32 ctl11;
+ u32 status0;
+ u32 status1;
+ u32 status2;
+ u32 status3;
+ u32 status4;
+ u32 status5;
+ u32 status6;
+ u32 status7;
+ u32 status8;
+ u32 status9;
+ } tx;
+ struct {
+ u32 status0;
+ u32 status1;
+ u32 status2;
+ u32 status3;
+ u32 status4;
+ u32 status5;
+ u32 status6;
+ u32 status7;
+ u32 status8;
+ } rx;
+ } u;
+} __attribute__((packed, aligned(4)));
+
+#define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds))
+#define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds))
+
+#define ds_ctl2 u.tx.ctl2
+#define ds_ctl3 u.tx.ctl3
+#define ds_ctl4 u.tx.ctl4
+#define ds_ctl5 u.tx.ctl5
+#define ds_ctl6 u.tx.ctl6
+#define ds_ctl7 u.tx.ctl7
+#define ds_ctl8 u.tx.ctl8
+#define ds_ctl9 u.tx.ctl9
+#define ds_ctl10 u.tx.ctl10
+#define ds_ctl11 u.tx.ctl11
+
+#define ds_txstatus0 u.tx.status0
+#define ds_txstatus1 u.tx.status1
+#define ds_txstatus2 u.tx.status2
+#define ds_txstatus3 u.tx.status3
+#define ds_txstatus4 u.tx.status4
+#define ds_txstatus5 u.tx.status5
+#define ds_txstatus6 u.tx.status6
+#define ds_txstatus7 u.tx.status7
+#define ds_txstatus8 u.tx.status8
+#define ds_txstatus9 u.tx.status9
+
+#define ds_rxstatus0 u.rx.status0
+#define ds_rxstatus1 u.rx.status1
+#define ds_rxstatus2 u.rx.status2
+#define ds_rxstatus3 u.rx.status3
+#define ds_rxstatus4 u.rx.status4
+#define ds_rxstatus5 u.rx.status5
+#define ds_rxstatus6 u.rx.status6
+#define ds_rxstatus7 u.rx.status7
+#define ds_rxstatus8 u.rx.status8
+
+#define AR_FrameLen 0x00000fff
+#define AR_VirtMoreFrag 0x00001000
+#define AR_TxCtlRsvd00 0x0000e000
+#define AR_XmitPower 0x003f0000
+#define AR_XmitPower_S 16
+#define AR_RTSEnable 0x00400000
+#define AR_VEOL 0x00800000
+#define AR_ClrDestMask 0x01000000
+#define AR_TxCtlRsvd01 0x1e000000
+#define AR_TxIntrReq 0x20000000
+#define AR_DestIdxValid 0x40000000
+#define AR_CTSEnable 0x80000000
+
+#define AR_TxMore 0x00001000
+#define AR_DestIdx 0x000fe000
+#define AR_DestIdx_S 13
+#define AR_FrameType 0x00f00000
+#define AR_FrameType_S 20
+#define AR_NoAck 0x01000000
+#define AR_InsertTS 0x02000000
+#define AR_CorruptFCS 0x04000000
+#define AR_ExtOnly 0x08000000
+#define AR_ExtAndCtl 0x10000000
+#define AR_MoreAggr 0x20000000
+#define AR_IsAggr 0x40000000
+
+#define AR_BurstDur 0x00007fff
+#define AR_BurstDur_S 0
+#define AR_DurUpdateEna 0x00008000
+#define AR_XmitDataTries0 0x000f0000
+#define AR_XmitDataTries0_S 16
+#define AR_XmitDataTries1 0x00f00000
+#define AR_XmitDataTries1_S 20
+#define AR_XmitDataTries2 0x0f000000
+#define AR_XmitDataTries2_S 24
+#define AR_XmitDataTries3 0xf0000000
+#define AR_XmitDataTries3_S 28
+
+#define AR_XmitRate0 0x000000ff
+#define AR_XmitRate0_S 0
+#define AR_XmitRate1 0x0000ff00
+#define AR_XmitRate1_S 8
+#define AR_XmitRate2 0x00ff0000
+#define AR_XmitRate2_S 16
+#define AR_XmitRate3 0xff000000
+#define AR_XmitRate3_S 24
+
+#define AR_PacketDur0 0x00007fff
+#define AR_PacketDur0_S 0
+#define AR_RTSCTSQual0 0x00008000
+#define AR_PacketDur1 0x7fff0000
+#define AR_PacketDur1_S 16
+#define AR_RTSCTSQual1 0x80000000
+
+#define AR_PacketDur2 0x00007fff
+#define AR_PacketDur2_S 0
+#define AR_RTSCTSQual2 0x00008000
+#define AR_PacketDur3 0x7fff0000
+#define AR_PacketDur3_S 16
+#define AR_RTSCTSQual3 0x80000000
+
+#define AR_AggrLen 0x0000ffff
+#define AR_AggrLen_S 0
+#define AR_TxCtlRsvd60 0x00030000
+#define AR_PadDelim 0x03fc0000
+#define AR_PadDelim_S 18
+#define AR_EncrType 0x0c000000
+#define AR_EncrType_S 26
+#define AR_TxCtlRsvd61 0xf0000000
+#define AR_LDPC 0x80000000
+
+#define AR_2040_0 0x00000001
+#define AR_GI0 0x00000002
+#define AR_ChainSel0 0x0000001c
+#define AR_ChainSel0_S 2
+#define AR_2040_1 0x00000020
+#define AR_GI1 0x00000040
+#define AR_ChainSel1 0x00000380
+#define AR_ChainSel1_S 7
+#define AR_2040_2 0x00000400
+#define AR_GI2 0x00000800
+#define AR_ChainSel2 0x00007000
+#define AR_ChainSel2_S 12
+#define AR_2040_3 0x00008000
+#define AR_GI3 0x00010000
+#define AR_ChainSel3 0x000e0000
+#define AR_ChainSel3_S 17
+#define AR_RTSCTSRate 0x0ff00000
+#define AR_RTSCTSRate_S 20
+#define AR_STBC0 0x10000000
+#define AR_STBC1 0x20000000
+#define AR_STBC2 0x40000000
+#define AR_STBC3 0x80000000
+
+#define AR_TxRSSIAnt00 0x000000ff
+#define AR_TxRSSIAnt00_S 0
+#define AR_TxRSSIAnt01 0x0000ff00
+#define AR_TxRSSIAnt01_S 8
+#define AR_TxRSSIAnt02 0x00ff0000
+#define AR_TxRSSIAnt02_S 16
+#define AR_TxStatusRsvd00 0x3f000000
+#define AR_TxBaStatus 0x40000000
+#define AR_TxStatusRsvd01 0x80000000
+
+/*
+ * AR_FrmXmitOK - Frame transmission success flag. If set, the frame was
+ * transmitted successfully. If clear, no ACK or BA was received to indicate
+ * successful transmission when we were expecting an ACK or BA.
+ */
+#define AR_FrmXmitOK 0x00000001
+#define AR_ExcessiveRetries 0x00000002
+#define AR_FIFOUnderrun 0x00000004
+#define AR_Filtered 0x00000008
+#define AR_RTSFailCnt 0x000000f0
+#define AR_RTSFailCnt_S 4
+#define AR_DataFailCnt 0x00000f00
+#define AR_DataFailCnt_S 8
+#define AR_VirtRetryCnt 0x0000f000
+#define AR_VirtRetryCnt_S 12
+#define AR_TxDelimUnderrun 0x00010000
+#define AR_TxDataUnderrun 0x00020000
+#define AR_DescCfgErr 0x00040000
+#define AR_TxTimerExpired 0x00080000
+#define AR_TxStatusRsvd10 0xfff00000
+
+#define AR_SendTimestamp ds_txstatus2
+#define AR_BaBitmapLow ds_txstatus3
+#define AR_BaBitmapHigh ds_txstatus4
+
+#define AR_TxRSSIAnt10 0x000000ff
+#define AR_TxRSSIAnt10_S 0
+#define AR_TxRSSIAnt11 0x0000ff00
+#define AR_TxRSSIAnt11_S 8
+#define AR_TxRSSIAnt12 0x00ff0000
+#define AR_TxRSSIAnt12_S 16
+#define AR_TxRSSICombined 0xff000000
+#define AR_TxRSSICombined_S 24
+
+#define AR_TxTid 0xf0000000
+#define AR_TxTid_S 28
+
+#define AR_TxEVM0 ds_txstatus5
+#define AR_TxEVM1 ds_txstatus6
+#define AR_TxEVM2 ds_txstatus7
+
+#define AR_TxDone 0x00000001
+#define AR_SeqNum 0x00001ffe
+#define AR_SeqNum_S 1
+#define AR_TxStatusRsvd80 0x0001e000
+#define AR_TxOpExceeded 0x00020000
+#define AR_TxStatusRsvd81 0x001c0000
+#define AR_FinalTxIdx 0x00600000
+#define AR_FinalTxIdx_S 21
+#define AR_TxStatusRsvd82 0x01800000
+#define AR_PowerMgmt 0x02000000
+#define AR_TxStatusRsvd83 0xfc000000
+
+#define AR_RxCTLRsvd00 0xffffffff
+
+#define AR_RxCtlRsvd00 0x00001000
+#define AR_RxIntrReq 0x00002000
+#define AR_RxCtlRsvd01 0xffffc000
+
+#define AR_RxRSSIAnt00 0x000000ff
+#define AR_RxRSSIAnt00_S 0
+#define AR_RxRSSIAnt01 0x0000ff00
+#define AR_RxRSSIAnt01_S 8
+#define AR_RxRSSIAnt02 0x00ff0000
+#define AR_RxRSSIAnt02_S 16
+#define AR_RxRate 0xff000000
+#define AR_RxRate_S 24
+#define AR_RxStatusRsvd00 0xff000000
+
+#define AR_DataLen 0x00000fff
+#define AR_RxMore 0x00001000
+#define AR_NumDelim 0x003fc000
+#define AR_NumDelim_S 14
+#define AR_RxStatusRsvd10 0xff800000
+
+#define AR_RcvTimestamp ds_rxstatus2
+
+#define AR_GI 0x00000001
+#define AR_2040 0x00000002
+#define AR_Parallel40 0x00000004
+#define AR_Parallel40_S 2
+#define AR_RxStatusRsvd30 0x000000f8
+#define AR_RxAntenna 0xffffff00
+#define AR_RxAntenna_S 8
+
+#define AR_RxRSSIAnt10 0x000000ff
+#define AR_RxRSSIAnt10_S 0
+#define AR_RxRSSIAnt11 0x0000ff00
+#define AR_RxRSSIAnt11_S 8
+#define AR_RxRSSIAnt12 0x00ff0000
+#define AR_RxRSSIAnt12_S 16
+#define AR_RxRSSICombined 0xff000000
+#define AR_RxRSSICombined_S 24
+
+#define AR_RxEVM0 ds_rxstatus4
+#define AR_RxEVM1 ds_rxstatus5
+#define AR_RxEVM2 ds_rxstatus6
+
+#define AR_RxDone 0x00000001
+#define AR_RxFrameOK 0x00000002
+#define AR_CRCErr 0x00000004
+#define AR_DecryptCRCErr 0x00000008
+#define AR_PHYErr 0x00000010
+#define AR_MichaelErr 0x00000020
+#define AR_PreDelimCRCErr 0x00000040
+#define AR_RxStatusRsvd70 0x00000080
+#define AR_RxKeyIdxValid 0x00000100
+#define AR_KeyIdx 0x0000fe00
+#define AR_KeyIdx_S 9
+#define AR_PHYErrCode 0x0000ff00
+#define AR_PHYErrCode_S 8
+#define AR_RxMoreAggr 0x00010000
+#define AR_RxAggr 0x00020000
+#define AR_PostDelimCRCErr 0x00040000
+#define AR_RxStatusRsvd71 0x3ff80000
+#define AR_DecryptBusyErr 0x40000000
+#define AR_KeyMiss 0x80000000
+
+enum ath9k_tx_queue {
+ ATH9K_TX_QUEUE_INACTIVE = 0,
+ ATH9K_TX_QUEUE_DATA,
+};
+
+#define ATH9K_NUM_TX_QUEUES 1
+
+/* Used as a queue subtype instead of a WMM AC */
+#define ATH9K_WME_UPSD 4
+
+enum ath9k_tx_queue_flags {
+ TXQ_FLAG_TXOKINT_ENABLE = 0x0001,
+ TXQ_FLAG_TXERRINT_ENABLE = 0x0001,
+ TXQ_FLAG_TXDESCINT_ENABLE = 0x0002,
+ TXQ_FLAG_TXEOLINT_ENABLE = 0x0004,
+ TXQ_FLAG_TXURNINT_ENABLE = 0x0008,
+ TXQ_FLAG_BACKOFF_DISABLE = 0x0010,
+ TXQ_FLAG_COMPRESSION_ENABLE = 0x0020,
+ TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE = 0x0040,
+ TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE = 0x0080,
+};
+
+#define ATH9K_TXQ_USEDEFAULT ((u32) -1)
+#define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001
+
+#define ATH9K_DECOMP_MASK_SIZE 128
+#define ATH9K_READY_TIME_LO_BOUND 50
+#define ATH9K_READY_TIME_HI_BOUND 96
+
+enum ath9k_pkt_type {
+ ATH9K_PKT_TYPE_NORMAL = 0,
+ ATH9K_PKT_TYPE_ATIM,
+ ATH9K_PKT_TYPE_PSPOLL,
+ ATH9K_PKT_TYPE_BEACON,
+ ATH9K_PKT_TYPE_PROBE_RESP,
+ ATH9K_PKT_TYPE_CHIRP,
+ ATH9K_PKT_TYPE_GRP_POLL,
+};
+
+struct ath9k_tx_queue_info {
+ u32 tqi_ver;
+ enum ath9k_tx_queue tqi_type;
+ int tqi_subtype;
+ enum ath9k_tx_queue_flags tqi_qflags;
+ u32 tqi_priority;
+ u32 tqi_aifs;
+ u32 tqi_cwmin;
+ u32 tqi_cwmax;
+ u16 tqi_shretry;
+ u16 tqi_lgretry;
+ u32 tqi_cbrPeriod;
+ u32 tqi_cbrOverflowLimit;
+ u32 tqi_burstTime;
+ u32 tqi_readyTime;
+ u32 tqi_physCompBuf;
+ u32 tqi_intFlags;
+};
+
+enum ath9k_rx_filter {
+ ATH9K_RX_FILTER_UCAST = 0x00000001,
+ ATH9K_RX_FILTER_MCAST = 0x00000002,
+ ATH9K_RX_FILTER_BCAST = 0x00000004,
+ ATH9K_RX_FILTER_CONTROL = 0x00000008,
+ ATH9K_RX_FILTER_BEACON = 0x00000010,
+ ATH9K_RX_FILTER_PROM = 0x00000020,
+ ATH9K_RX_FILTER_PROBEREQ = 0x00000080,
+ ATH9K_RX_FILTER_PHYERR = 0x00000100,
+ ATH9K_RX_FILTER_MYBEACON = 0x00000200,
+ ATH9K_RX_FILTER_COMP_BAR = 0x00000400,
+ ATH9K_RX_FILTER_COMP_BA = 0x00000800,
+ ATH9K_RX_FILTER_UNCOMP_BA_BAR = 0x00001000,
+ ATH9K_RX_FILTER_PSPOLL = 0x00004000,
+ ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
+ ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
+};
+
+#define ATH9K_RATESERIES_RTS_CTS 0x0001
+#define ATH9K_RATESERIES_2040 0x0002
+#define ATH9K_RATESERIES_HALFGI 0x0004
+#define ATH9K_RATESERIES_STBC 0x0008
+
+struct ath9k_11n_rate_series {
+ u32 Tries;
+ u32 Rate;
+ u32 PktDuration;
+ u32 ChSel;
+ u32 RateFlags;
+};
+
+enum ath9k_key_type {
+ ATH9K_KEY_TYPE_CLEAR,
+ ATH9K_KEY_TYPE_WEP,
+ ATH9K_KEY_TYPE_AES,
+ ATH9K_KEY_TYPE_TKIP,
+};
+
+struct ath_hw;
+struct ath9k_channel;
+
+u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
+void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
+void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
+void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
+u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
+int ath9k_hw_updatetxtriglevel(struct ath_hw *ah, int bIncTrigLevel);
+int ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
+void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
+void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
+int ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
+ const struct ath9k_tx_queue_info *qinfo);
+int ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
+ struct ath9k_tx_queue_info *qinfo);
+int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
+ const struct ath9k_tx_queue_info *qinfo);
+int ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);
+int ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);
+int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
+ struct ath_rx_status *rs, u64 tsf);
+void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
+ u32 size, u32 flags);
+int ath9k_hw_setrxabort(struct ath_hw *ah, int set);
+void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
+void ath9k_hw_startpcureceive(struct ath_hw *ah, int is_scanning);
+void ath9k_hw_abortpcurecv(struct ath_hw *ah);
+int ath9k_hw_stopdmarecv(struct ath_hw *ah, int *reset);
+
+/* Interrupt Handling */
+int ath9k_hw_intrpend(struct ath_hw *ah);
+void ath9k_hw_set_interrupts(struct ath_hw *ah, unsigned int ints);
+void ath9k_hw_enable_interrupts(struct ath_hw *ah);
+void ath9k_hw_disable_interrupts(struct ath_hw *ah);
+
+void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
+
+#endif /* MAC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/phy.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/phy.h
new file mode 100644
index 00000000..8b380305
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/phy.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef PHY_H
+#define PHY_H
+
+#define CHANSEL_DIV 15
+#define CHANSEL_2G(_freq) (((_freq) * 0x10000) / CHANSEL_DIV)
+#define CHANSEL_5G(_freq) (((_freq) * 0x8000) / CHANSEL_DIV)
+
+#define AR_PHY_BASE 0x9800
+#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2))
+
+#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX 0x0007E000
+#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX_S 13
+#define AR_PHY_TX_GAIN_CLC 0x0000001E
+#define AR_PHY_TX_GAIN_CLC_S 1
+#define AR_PHY_TX_GAIN 0x0007F000
+#define AR_PHY_TX_GAIN_S 12
+
+#define AR_PHY_CLC_TBL1 0xa35c
+#define AR_PHY_CLC_I0 0x07ff0000
+#define AR_PHY_CLC_I0_S 16
+#define AR_PHY_CLC_Q0 0x0000ffd0
+#define AR_PHY_CLC_Q0_S 5
+
+#define ANTSWAP_AB 0x0001
+#define REDUCE_CHAIN_0 0x00000050
+#define REDUCE_CHAIN_1 0x00000051
+#define AR_PHY_CHIP_ID 0x9818
+
+#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000
+#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20
+
+#define AR_PHY_PLL_CONTROL 0x16180
+#define AR_PHY_PLL_MODE 0x16184
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/reg.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/reg.h
new file mode 100644
index 00000000..c18ee992
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath9k/reg.h
@@ -0,0 +1,1919 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef REG_H
+#define REG_H
+
+#include "../reg.h"
+
+#define AR_CR 0x0008
+#define AR_CR_RXE (AR_SREV_9300_20_OR_LATER(ah) ? 0x0000000c : 0x00000004)
+#define AR_CR_RXD 0x00000020
+#define AR_CR_SWI 0x00000040
+
+#define AR_RXDP 0x000C
+
+#define AR_CFG 0x0014
+#define AR_CFG_SWTD 0x00000001
+#define AR_CFG_SWTB 0x00000002
+#define AR_CFG_SWRD 0x00000004
+#define AR_CFG_SWRB 0x00000008
+#define AR_CFG_SWRG 0x00000010
+#define AR_CFG_AP_ADHOC_INDICATION 0x00000020
+#define AR_CFG_PHOK 0x00000100
+#define AR_CFG_CLK_GATE_DIS 0x00000400
+#define AR_CFG_EEBS 0x00000200
+#define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000
+#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17
+
+#define AR_RXBP_THRESH 0x0018
+#define AR_RXBP_THRESH_HP 0x0000000f
+#define AR_RXBP_THRESH_HP_S 0
+#define AR_RXBP_THRESH_LP 0x00003f00
+#define AR_RXBP_THRESH_LP_S 8
+
+#define AR_MIRT 0x0020
+#define AR_MIRT_VAL 0x0000ffff
+#define AR_MIRT_VAL_S 16
+
+#define AR_IER 0x0024
+#define AR_IER_ENABLE 0x00000001
+#define AR_IER_DISABLE 0x00000000
+
+#define AR_TIMT 0x0028
+#define AR_TIMT_LAST 0x0000ffff
+#define AR_TIMT_LAST_S 0
+#define AR_TIMT_FIRST 0xffff0000
+#define AR_TIMT_FIRST_S 16
+
+#define AR_RIMT 0x002C
+#define AR_RIMT_LAST 0x0000ffff
+#define AR_RIMT_LAST_S 0
+#define AR_RIMT_FIRST 0xffff0000
+#define AR_RIMT_FIRST_S 16
+
+#define AR_DMASIZE_4B 0x00000000
+#define AR_DMASIZE_8B 0x00000001
+#define AR_DMASIZE_16B 0x00000002
+#define AR_DMASIZE_32B 0x00000003
+#define AR_DMASIZE_64B 0x00000004
+#define AR_DMASIZE_128B 0x00000005
+#define AR_DMASIZE_256B 0x00000006
+#define AR_DMASIZE_512B 0x00000007
+
+#define AR_TXCFG 0x0030
+#define AR_TXCFG_DMASZ_MASK 0x00000007
+#define AR_TXCFG_DMASZ_4B 0
+#define AR_TXCFG_DMASZ_8B 1
+#define AR_TXCFG_DMASZ_16B 2
+#define AR_TXCFG_DMASZ_32B 3
+#define AR_TXCFG_DMASZ_64B 4
+#define AR_TXCFG_DMASZ_128B 5
+#define AR_TXCFG_DMASZ_256B 6
+#define AR_TXCFG_DMASZ_512B 7
+#define AR_FTRIG 0x000003F0
+#define AR_FTRIG_S 4
+#define AR_FTRIG_IMMED 0x00000000
+#define AR_FTRIG_64B 0x00000010
+#define AR_FTRIG_128B 0x00000020
+#define AR_FTRIG_192B 0x00000030
+#define AR_FTRIG_256B 0x00000040
+#define AR_FTRIG_512B 0x00000080
+#define AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY 0x00000800
+
+#define AR_RXCFG 0x0034
+#define AR_RXCFG_CHIRP 0x00000008
+#define AR_RXCFG_ZLFDMA 0x00000010
+#define AR_RXCFG_DMASZ_MASK 0x00000007
+#define AR_RXCFG_DMASZ_4B 0
+#define AR_RXCFG_DMASZ_8B 1
+#define AR_RXCFG_DMASZ_16B 2
+#define AR_RXCFG_DMASZ_32B 3
+#define AR_RXCFG_DMASZ_64B 4
+#define AR_RXCFG_DMASZ_128B 5
+#define AR_RXCFG_DMASZ_256B 6
+#define AR_RXCFG_DMASZ_512B 7
+
+#define AR_TOPS 0x0044
+#define AR_TOPS_MASK 0x0000FFFF
+
+#define AR_RXNPTO 0x0048
+#define AR_RXNPTO_MASK 0x000003FF
+
+#define AR_TXNPTO 0x004C
+#define AR_TXNPTO_MASK 0x000003FF
+#define AR_TXNPTO_QCU_MASK 0x000FFC00
+
+#define AR_RPGTO 0x0050
+#define AR_RPGTO_MASK 0x000003FF
+
+#define AR_RPCNT 0x0054
+#define AR_RPCNT_MASK 0x0000001F
+
+#define AR_MACMISC 0x0058
+#define AR_MACMISC_PCI_EXT_FORCE 0x00000010
+#define AR_MACMISC_DMA_OBS 0x000001E0
+#define AR_MACMISC_DMA_OBS_S 5
+#define AR_MACMISC_DMA_OBS_LINE_0 0
+#define AR_MACMISC_DMA_OBS_LINE_1 1
+#define AR_MACMISC_DMA_OBS_LINE_2 2
+#define AR_MACMISC_DMA_OBS_LINE_3 3
+#define AR_MACMISC_DMA_OBS_LINE_4 4
+#define AR_MACMISC_DMA_OBS_LINE_5 5
+#define AR_MACMISC_DMA_OBS_LINE_6 6
+#define AR_MACMISC_DMA_OBS_LINE_7 7
+#define AR_MACMISC_DMA_OBS_LINE_8 8
+#define AR_MACMISC_MISC_OBS 0x00000E00
+#define AR_MACMISC_MISC_OBS_S 9
+#define AR_MACMISC_MISC_OBS_BUS_LSB 0x00007000
+#define AR_MACMISC_MISC_OBS_BUS_LSB_S 12
+#define AR_MACMISC_MISC_OBS_BUS_MSB 0x00038000
+#define AR_MACMISC_MISC_OBS_BUS_MSB_S 15
+#define AR_MACMISC_MISC_OBS_BUS_1 1
+
+#define AR_DATABUF_SIZE 0x0060
+#define AR_DATABUF_SIZE_MASK 0x00000FFF
+
+#define AR_GTXTO 0x0064
+#define AR_GTXTO_TIMEOUT_COUNTER 0x0000FFFF
+#define AR_GTXTO_TIMEOUT_LIMIT 0xFFFF0000
+#define AR_GTXTO_TIMEOUT_LIMIT_S 16
+
+#define AR_GTTM 0x0068
+#define AR_GTTM_USEC 0x00000001
+#define AR_GTTM_IGNORE_IDLE 0x00000002
+#define AR_GTTM_RESET_IDLE 0x00000004
+#define AR_GTTM_CST_USEC 0x00000008
+
+#define AR_CST 0x006C
+#define AR_CST_TIMEOUT_COUNTER 0x0000FFFF
+#define AR_CST_TIMEOUT_LIMIT 0xFFFF0000
+#define AR_CST_TIMEOUT_LIMIT_S 16
+
+#define AR_HP_RXDP 0x0074
+#define AR_LP_RXDP 0x0078
+
+#define AR_ISR 0x0080
+#define AR_ISR_RXOK 0x00000001
+#define AR_ISR_RXDESC 0x00000002
+#define AR_ISR_HP_RXOK 0x00000001
+#define AR_ISR_LP_RXOK 0x00000002
+#define AR_ISR_RXERR 0x00000004
+#define AR_ISR_RXNOPKT 0x00000008
+#define AR_ISR_RXEOL 0x00000010
+#define AR_ISR_RXORN 0x00000020
+#define AR_ISR_TXOK 0x00000040
+#define AR_ISR_TXDESC 0x00000080
+#define AR_ISR_TXERR 0x00000100
+#define AR_ISR_TXNOPKT 0x00000200
+#define AR_ISR_TXEOL 0x00000400
+#define AR_ISR_TXURN 0x00000800
+#define AR_ISR_MIB 0x00001000
+#define AR_ISR_SWI 0x00002000
+#define AR_ISR_RXPHY 0x00004000
+#define AR_ISR_RXKCM 0x00008000
+#define AR_ISR_SWBA 0x00010000
+#define AR_ISR_BRSSI 0x00020000
+#define AR_ISR_BMISS 0x00040000
+#define AR_ISR_BNR 0x00100000
+#define AR_ISR_RXCHIRP 0x00200000
+#define AR_ISR_BCNMISC 0x00800000
+#define AR_ISR_TIM 0x00800000
+#define AR_ISR_QCBROVF 0x02000000
+#define AR_ISR_QCBRURN 0x04000000
+#define AR_ISR_QTRIG 0x08000000
+#define AR_ISR_GENTMR 0x10000000
+
+#define AR_ISR_TXMINTR 0x00080000
+#define AR_ISR_RXMINTR 0x01000000
+#define AR_ISR_TXINTM 0x40000000
+#define AR_ISR_RXINTM 0x80000000
+
+#define AR_ISR_S0 0x0084
+#define AR_ISR_S0_QCU_TXOK 0x000003FF
+#define AR_ISR_S0_QCU_TXOK_S 0
+#define AR_ISR_S0_QCU_TXDESC 0x03FF0000
+#define AR_ISR_S0_QCU_TXDESC_S 16
+
+#define AR_ISR_S1 0x0088
+#define AR_ISR_S1_QCU_TXERR 0x000003FF
+#define AR_ISR_S1_QCU_TXERR_S 0
+#define AR_ISR_S1_QCU_TXEOL 0x03FF0000
+#define AR_ISR_S1_QCU_TXEOL_S 16
+
+#define AR_ISR_S2 0x008c
+#define AR_ISR_S2_QCU_TXURN 0x000003FF
+#define AR_ISR_S2_BB_WATCHDOG 0x00010000
+#define AR_ISR_S2_CST 0x00400000
+#define AR_ISR_S2_GTT 0x00800000
+#define AR_ISR_S2_TIM 0x01000000
+#define AR_ISR_S2_CABEND 0x02000000
+#define AR_ISR_S2_DTIMSYNC 0x04000000
+#define AR_ISR_S2_BCNTO 0x08000000
+#define AR_ISR_S2_CABTO 0x10000000
+#define AR_ISR_S2_DTIM 0x20000000
+#define AR_ISR_S2_TSFOOR 0x40000000
+#define AR_ISR_S2_TBTT_TIME 0x80000000
+
+#define AR_ISR_S3 0x0090
+#define AR_ISR_S3_QCU_QCBROVF 0x000003FF
+#define AR_ISR_S3_QCU_QCBRURN 0x03FF0000
+
+#define AR_ISR_S4 0x0094
+#define AR_ISR_S4_QCU_QTRIG 0x000003FF
+#define AR_ISR_S4_RESV0 0xFFFFFC00
+
+#define AR_ISR_S5 0x0098
+#define AR_ISR_S5_TIMER_TRIG 0x000000FF
+#define AR_ISR_S5_TIMER_THRESH 0x0007FE00
+#define AR_ISR_S5_TIM_TIMER 0x00000010
+#define AR_ISR_S5_DTIM_TIMER 0x00000020
+#define AR_IMR_S5 0x00b8
+#define AR_IMR_S5_TIM_TIMER 0x00000010
+#define AR_IMR_S5_DTIM_TIMER 0x00000020
+#define AR_ISR_S5_GENTIMER_TRIG 0x0000FF80
+#define AR_ISR_S5_GENTIMER_TRIG_S 0
+#define AR_ISR_S5_GENTIMER_THRESH 0xFF800000
+#define AR_ISR_S5_GENTIMER_THRESH_S 16
+#define AR_IMR_S5_GENTIMER_TRIG 0x0000FF80
+#define AR_IMR_S5_GENTIMER_TRIG_S 0
+#define AR_IMR_S5_GENTIMER_THRESH 0xFF800000
+#define AR_IMR_S5_GENTIMER_THRESH_S 16
+
+#define AR_IMR 0x00a0
+#define AR_IMR_RXOK 0x00000001
+#define AR_IMR_RXDESC 0x00000002
+#define AR_IMR_RXOK_HP 0x00000001
+#define AR_IMR_RXOK_LP 0x00000002
+#define AR_IMR_RXERR 0x00000004
+#define AR_IMR_RXNOPKT 0x00000008
+#define AR_IMR_RXEOL 0x00000010
+#define AR_IMR_RXORN 0x00000020
+#define AR_IMR_TXOK 0x00000040
+#define AR_IMR_TXDESC 0x00000080
+#define AR_IMR_TXERR 0x00000100
+#define AR_IMR_TXNOPKT 0x00000200
+#define AR_IMR_TXEOL 0x00000400
+#define AR_IMR_TXURN 0x00000800
+#define AR_IMR_MIB 0x00001000
+#define AR_IMR_SWI 0x00002000
+#define AR_IMR_RXPHY 0x00004000
+#define AR_IMR_RXKCM 0x00008000
+#define AR_IMR_SWBA 0x00010000
+#define AR_IMR_BRSSI 0x00020000
+#define AR_IMR_BMISS 0x00040000
+#define AR_IMR_BNR 0x00100000
+#define AR_IMR_RXCHIRP 0x00200000
+#define AR_IMR_BCNMISC 0x00800000
+#define AR_IMR_TIM 0x00800000
+#define AR_IMR_QCBROVF 0x02000000
+#define AR_IMR_QCBRURN 0x04000000
+#define AR_IMR_QTRIG 0x08000000
+#define AR_IMR_GENTMR 0x10000000
+
+#define AR_IMR_TXMINTR 0x00080000
+#define AR_IMR_RXMINTR 0x01000000
+#define AR_IMR_TXINTM 0x40000000
+#define AR_IMR_RXINTM 0x80000000
+
+#define AR_IMR_S0 0x00a4
+#define AR_IMR_S0_QCU_TXOK 0x000003FF
+#define AR_IMR_S0_QCU_TXOK_S 0
+#define AR_IMR_S0_QCU_TXDESC 0x03FF0000
+#define AR_IMR_S0_QCU_TXDESC_S 16
+
+#define AR_IMR_S1 0x00a8
+#define AR_IMR_S1_QCU_TXERR 0x000003FF
+#define AR_IMR_S1_QCU_TXERR_S 0
+#define AR_IMR_S1_QCU_TXEOL 0x03FF0000
+#define AR_IMR_S1_QCU_TXEOL_S 16
+
+#define AR_IMR_S2 0x00ac
+#define AR_IMR_S2_QCU_TXURN 0x000003FF
+#define AR_IMR_S2_QCU_TXURN_S 0
+#define AR_IMR_S2_CST 0x00400000
+#define AR_IMR_S2_GTT 0x00800000
+#define AR_IMR_S2_TIM 0x01000000
+#define AR_IMR_S2_CABEND 0x02000000
+#define AR_IMR_S2_DTIMSYNC 0x04000000
+#define AR_IMR_S2_BCNTO 0x08000000
+#define AR_IMR_S2_CABTO 0x10000000
+#define AR_IMR_S2_DTIM 0x20000000
+#define AR_IMR_S2_TSFOOR 0x40000000
+
+#define AR_IMR_S3 0x00b0
+#define AR_IMR_S3_QCU_QCBROVF 0x000003FF
+#define AR_IMR_S3_QCU_QCBRURN 0x03FF0000
+#define AR_IMR_S3_QCU_QCBRURN_S 16
+
+#define AR_IMR_S4 0x00b4
+#define AR_IMR_S4_QCU_QTRIG 0x000003FF
+#define AR_IMR_S4_RESV0 0xFFFFFC00
+
+#define AR_IMR_S5 0x00b8
+#define AR_IMR_S5_TIMER_TRIG 0x000000FF
+#define AR_IMR_S5_TIMER_THRESH 0x0000FF00
+
+
+#define AR_ISR_RAC 0x00c0
+#define AR_ISR_S0_S 0x00c4
+#define AR_ISR_S0_QCU_TXOK 0x000003FF
+#define AR_ISR_S0_QCU_TXOK_S 0
+#define AR_ISR_S0_QCU_TXDESC 0x03FF0000
+#define AR_ISR_S0_QCU_TXDESC_S 16
+
+#define AR_ISR_S1_S 0x00c8
+#define AR_ISR_S1_QCU_TXERR 0x000003FF
+#define AR_ISR_S1_QCU_TXERR_S 0
+#define AR_ISR_S1_QCU_TXEOL 0x03FF0000
+#define AR_ISR_S1_QCU_TXEOL_S 16
+
+#define AR_ISR_S2_S (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d0 : 0x00cc)
+#define AR_ISR_S3_S (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d4 : 0x00d0)
+#define AR_ISR_S4_S (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d8 : 0x00d4)
+#define AR_ISR_S5_S (AR_SREV_9300_20_OR_LATER(ah) ? 0x00dc : 0x00d8)
+#define AR_DMADBG_0 0x00e0
+#define AR_DMADBG_1 0x00e4
+#define AR_DMADBG_2 0x00e8
+#define AR_DMADBG_3 0x00ec
+#define AR_DMADBG_4 0x00f0
+#define AR_DMADBG_5 0x00f4
+#define AR_DMADBG_6 0x00f8
+#define AR_DMADBG_7 0x00fc
+
+#define AR_NUM_QCU 10
+#define AR_QCU_0 0x0001
+#define AR_QCU_1 0x0002
+#define AR_QCU_2 0x0004
+#define AR_QCU_3 0x0008
+#define AR_QCU_4 0x0010
+#define AR_QCU_5 0x0020
+#define AR_QCU_6 0x0040
+#define AR_QCU_7 0x0080
+#define AR_QCU_8 0x0100
+#define AR_QCU_9 0x0200
+
+#define AR_Q0_TXDP 0x0800
+#define AR_Q1_TXDP 0x0804
+#define AR_Q2_TXDP 0x0808
+#define AR_Q3_TXDP 0x080c
+#define AR_Q4_TXDP 0x0810
+#define AR_Q5_TXDP 0x0814
+#define AR_Q6_TXDP 0x0818
+#define AR_Q7_TXDP 0x081c
+#define AR_Q8_TXDP 0x0820
+#define AR_Q9_TXDP 0x0824
+#define AR_QTXDP(_i) (AR_Q0_TXDP + ((_i)<<2))
+
+#define AR_Q_STATUS_RING_START 0x830
+#define AR_Q_STATUS_RING_END 0x834
+
+#define AR_Q_TXE 0x0840
+#define AR_Q_TXE_M 0x000003FF
+
+#define AR_Q_TXD 0x0880
+#define AR_Q_TXD_M 0x000003FF
+
+#define AR_Q0_CBRCFG 0x08c0
+#define AR_Q1_CBRCFG 0x08c4
+#define AR_Q2_CBRCFG 0x08c8
+#define AR_Q3_CBRCFG 0x08cc
+#define AR_Q4_CBRCFG 0x08d0
+#define AR_Q5_CBRCFG 0x08d4
+#define AR_Q6_CBRCFG 0x08d8
+#define AR_Q7_CBRCFG 0x08dc
+#define AR_Q8_CBRCFG 0x08e0
+#define AR_Q9_CBRCFG 0x08e4
+#define AR_QCBRCFG(_i) (AR_Q0_CBRCFG + ((_i)<<2))
+#define AR_Q_CBRCFG_INTERVAL 0x00FFFFFF
+#define AR_Q_CBRCFG_INTERVAL_S 0
+#define AR_Q_CBRCFG_OVF_THRESH 0xFF000000
+#define AR_Q_CBRCFG_OVF_THRESH_S 24
+
+#define AR_Q0_RDYTIMECFG 0x0900
+#define AR_Q1_RDYTIMECFG 0x0904
+#define AR_Q2_RDYTIMECFG 0x0908
+#define AR_Q3_RDYTIMECFG 0x090c
+#define AR_Q4_RDYTIMECFG 0x0910
+#define AR_Q5_RDYTIMECFG 0x0914
+#define AR_Q6_RDYTIMECFG 0x0918
+#define AR_Q7_RDYTIMECFG 0x091c
+#define AR_Q8_RDYTIMECFG 0x0920
+#define AR_Q9_RDYTIMECFG 0x0924
+#define AR_QRDYTIMECFG(_i) (AR_Q0_RDYTIMECFG + ((_i)<<2))
+#define AR_Q_RDYTIMECFG_DURATION 0x00FFFFFF
+#define AR_Q_RDYTIMECFG_DURATION_S 0
+#define AR_Q_RDYTIMECFG_EN 0x01000000
+
+#define AR_Q_ONESHOTARM_SC 0x0940
+#define AR_Q_ONESHOTARM_SC_M 0x000003FF
+#define AR_Q_ONESHOTARM_SC_RESV0 0xFFFFFC00
+
+#define AR_Q_ONESHOTARM_CC 0x0980
+#define AR_Q_ONESHOTARM_CC_M 0x000003FF
+#define AR_Q_ONESHOTARM_CC_RESV0 0xFFFFFC00
+
+#define AR_Q0_MISC 0x09c0
+#define AR_Q1_MISC 0x09c4
+#define AR_Q2_MISC 0x09c8
+#define AR_Q3_MISC 0x09cc
+#define AR_Q4_MISC 0x09d0
+#define AR_Q5_MISC 0x09d4
+#define AR_Q6_MISC 0x09d8
+#define AR_Q7_MISC 0x09dc
+#define AR_Q8_MISC 0x09e0
+#define AR_Q9_MISC 0x09e4
+#define AR_QMISC(_i) (AR_Q0_MISC + ((_i)<<2))
+#define AR_Q_MISC_FSP 0x0000000F
+#define AR_Q_MISC_FSP_ASAP 0
+#define AR_Q_MISC_FSP_CBR 1
+#define AR_Q_MISC_FSP_DBA_GATED 2
+#define AR_Q_MISC_FSP_TIM_GATED 3
+#define AR_Q_MISC_FSP_BEACON_SENT_GATED 4
+#define AR_Q_MISC_FSP_BEACON_RCVD_GATED 5
+#define AR_Q_MISC_ONE_SHOT_EN 0x00000010
+#define AR_Q_MISC_CBR_INCR_DIS1 0x00000020
+#define AR_Q_MISC_CBR_INCR_DIS0 0x00000040
+#define AR_Q_MISC_BEACON_USE 0x00000080
+#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN 0x00000100
+#define AR_Q_MISC_RDYTIME_EXP_POLICY 0x00000200
+#define AR_Q_MISC_RESET_CBR_EXP_CTR 0x00000400
+#define AR_Q_MISC_DCU_EARLY_TERM_REQ 0x00000800
+#define AR_Q_MISC_RESV0 0xFFFFF000
+
+#define AR_Q0_STS 0x0a00
+#define AR_Q1_STS 0x0a04
+#define AR_Q2_STS 0x0a08
+#define AR_Q3_STS 0x0a0c
+#define AR_Q4_STS 0x0a10
+#define AR_Q5_STS 0x0a14
+#define AR_Q6_STS 0x0a18
+#define AR_Q7_STS 0x0a1c
+#define AR_Q8_STS 0x0a20
+#define AR_Q9_STS 0x0a24
+#define AR_QSTS(_i) (AR_Q0_STS + ((_i)<<2))
+#define AR_Q_STS_PEND_FR_CNT 0x00000003
+#define AR_Q_STS_RESV0 0x000000FC
+#define AR_Q_STS_CBR_EXP_CNT 0x0000FF00
+#define AR_Q_STS_RESV1 0xFFFF0000
+
+#define AR_Q_RDYTIMESHDN 0x0a40
+#define AR_Q_RDYTIMESHDN_M 0x000003FF
+
+/* MAC Descriptor CRC check */
+#define AR_Q_DESC_CRCCHK 0xa44
+/* Enable CRC check on the descriptor fetched from host */
+#define AR_Q_DESC_CRCCHK_EN 1
+
+#define AR_NUM_DCU 10
+#define AR_DCU_0 0x0001
+#define AR_DCU_1 0x0002
+#define AR_DCU_2 0x0004
+#define AR_DCU_3 0x0008
+#define AR_DCU_4 0x0010
+#define AR_DCU_5 0x0020
+#define AR_DCU_6 0x0040
+#define AR_DCU_7 0x0080
+#define AR_DCU_8 0x0100
+#define AR_DCU_9 0x0200
+
+#define AR_D0_QCUMASK 0x1000
+#define AR_D1_QCUMASK 0x1004
+#define AR_D2_QCUMASK 0x1008
+#define AR_D3_QCUMASK 0x100c
+#define AR_D4_QCUMASK 0x1010
+#define AR_D5_QCUMASK 0x1014
+#define AR_D6_QCUMASK 0x1018
+#define AR_D7_QCUMASK 0x101c
+#define AR_D8_QCUMASK 0x1020
+#define AR_D9_QCUMASK 0x1024
+#define AR_DQCUMASK(_i) (AR_D0_QCUMASK + ((_i)<<2))
+#define AR_D_QCUMASK 0x000003FF
+#define AR_D_QCUMASK_RESV0 0xFFFFFC00
+
+#define AR_D_TXBLK_CMD 0x1038
+#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i))
+
+#define AR_D0_LCL_IFS 0x1040
+#define AR_D1_LCL_IFS 0x1044
+#define AR_D2_LCL_IFS 0x1048
+#define AR_D3_LCL_IFS 0x104c
+#define AR_D4_LCL_IFS 0x1050
+#define AR_D5_LCL_IFS 0x1054
+#define AR_D6_LCL_IFS 0x1058
+#define AR_D7_LCL_IFS 0x105c
+#define AR_D8_LCL_IFS 0x1060
+#define AR_D9_LCL_IFS 0x1064
+#define AR_DLCL_IFS(_i) (AR_D0_LCL_IFS + ((_i)<<2))
+#define AR_D_LCL_IFS_CWMIN 0x000003FF
+#define AR_D_LCL_IFS_CWMIN_S 0
+#define AR_D_LCL_IFS_CWMAX 0x000FFC00
+#define AR_D_LCL_IFS_CWMAX_S 10
+#define AR_D_LCL_IFS_AIFS 0x0FF00000
+#define AR_D_LCL_IFS_AIFS_S 20
+
+#define AR_D_LCL_IFS_RESV0 0xF0000000
+
+#define AR_D0_RETRY_LIMIT 0x1080
+#define AR_D1_RETRY_LIMIT 0x1084
+#define AR_D2_RETRY_LIMIT 0x1088
+#define AR_D3_RETRY_LIMIT 0x108c
+#define AR_D4_RETRY_LIMIT 0x1090
+#define AR_D5_RETRY_LIMIT 0x1094
+#define AR_D6_RETRY_LIMIT 0x1098
+#define AR_D7_RETRY_LIMIT 0x109c
+#define AR_D8_RETRY_LIMIT 0x10a0
+#define AR_D9_RETRY_LIMIT 0x10a4
+#define AR_DRETRY_LIMIT(_i) (AR_D0_RETRY_LIMIT + ((_i)<<2))
+#define AR_D_RETRY_LIMIT_FR_SH 0x0000000F
+#define AR_D_RETRY_LIMIT_FR_SH_S 0
+#define AR_D_RETRY_LIMIT_STA_SH 0x00003F00
+#define AR_D_RETRY_LIMIT_STA_SH_S 8
+#define AR_D_RETRY_LIMIT_STA_LG 0x000FC000
+#define AR_D_RETRY_LIMIT_STA_LG_S 14
+#define AR_D_RETRY_LIMIT_RESV0 0xFFF00000
+
+#define AR_D0_CHNTIME 0x10c0
+#define AR_D1_CHNTIME 0x10c4
+#define AR_D2_CHNTIME 0x10c8
+#define AR_D3_CHNTIME 0x10cc
+#define AR_D4_CHNTIME 0x10d0
+#define AR_D5_CHNTIME 0x10d4
+#define AR_D6_CHNTIME 0x10d8
+#define AR_D7_CHNTIME 0x10dc
+#define AR_D8_CHNTIME 0x10e0
+#define AR_D9_CHNTIME 0x10e4
+#define AR_DCHNTIME(_i) (AR_D0_CHNTIME + ((_i)<<2))
+#define AR_D_CHNTIME_DUR 0x000FFFFF
+#define AR_D_CHNTIME_DUR_S 0
+#define AR_D_CHNTIME_EN 0x00100000
+#define AR_D_CHNTIME_RESV0 0xFFE00000
+
+#define AR_D0_MISC 0x1100
+#define AR_D1_MISC 0x1104
+#define AR_D2_MISC 0x1108
+#define AR_D3_MISC 0x110c
+#define AR_D4_MISC 0x1110
+#define AR_D5_MISC 0x1114
+#define AR_D6_MISC 0x1118
+#define AR_D7_MISC 0x111c
+#define AR_D8_MISC 0x1120
+#define AR_D9_MISC 0x1124
+#define AR_DMISC(_i) (AR_D0_MISC + ((_i)<<2))
+#define AR_D_MISC_BKOFF_THRESH 0x0000003F
+#define AR_D_MISC_RETRY_CNT_RESET_EN 0x00000040
+#define AR_D_MISC_CW_RESET_EN 0x00000080
+#define AR_D_MISC_FRAG_WAIT_EN 0x00000100
+#define AR_D_MISC_FRAG_BKOFF_EN 0x00000200
+#define AR_D_MISC_CW_BKOFF_EN 0x00001000
+#define AR_D_MISC_VIR_COL_HANDLING 0x0000C000
+#define AR_D_MISC_VIR_COL_HANDLING_S 14
+#define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0
+#define AR_D_MISC_VIR_COL_HANDLING_IGNORE 1
+#define AR_D_MISC_BEACON_USE 0x00010000
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL 0x00060000
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE 0
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL 2
+#define AR_D_MISC_ARB_LOCKOUT_IGNORE 0x00080000
+#define AR_D_MISC_SEQ_NUM_INCR_DIS 0x00100000
+#define AR_D_MISC_POST_FR_BKOFF_DIS 0x00200000
+#define AR_D_MISC_VIT_COL_CW_BKOFF_EN 0x00400000
+#define AR_D_MISC_BLOWN_IFS_RETRY_EN 0x00800000
+#define AR_D_MISC_RESV0 0xFF000000
+
+#define AR_D_SEQNUM 0x1140
+
+#define AR_D_GBL_IFS_SIFS 0x1030
+#define AR_D_GBL_IFS_SIFS_M 0x0000FFFF
+#define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003AB
+#define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF
+
+#define AR_D_TXBLK_BASE 0x1038
+#define AR_D_TXBLK_WRITE_BITMASK 0x0000FFFF
+#define AR_D_TXBLK_WRITE_BITMASK_S 0
+#define AR_D_TXBLK_WRITE_SLICE 0x000F0000
+#define AR_D_TXBLK_WRITE_SLICE_S 16
+#define AR_D_TXBLK_WRITE_DCU 0x00F00000
+#define AR_D_TXBLK_WRITE_DCU_S 20
+#define AR_D_TXBLK_WRITE_COMMAND 0x0F000000
+#define AR_D_TXBLK_WRITE_COMMAND_S 24
+
+#define AR_D_GBL_IFS_SLOT 0x1070
+#define AR_D_GBL_IFS_SLOT_M 0x0000FFFF
+#define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000
+#define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR 0x00000420
+
+#define AR_D_GBL_IFS_EIFS 0x10b0
+#define AR_D_GBL_IFS_EIFS_M 0x0000FFFF
+#define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000
+#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR 0x0000A5EB
+
+#define AR_D_GBL_IFS_MISC 0x10f0
+#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007
+#define AR_D_GBL_IFS_MISC_TURBO_MODE 0x00000008
+#define AR_D_GBL_IFS_MISC_USEC_DURATION 0x000FFC00
+#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY 0x00300000
+#define AR_D_GBL_IFS_MISC_RANDOM_LFSR_SLICE_DIS 0x01000000
+#define AR_D_GBL_IFS_MISC_SLOT_XMIT_WIND_LEN 0x06000000
+#define AR_D_GBL_IFS_MISC_FORCE_XMIT_SLOT_BOUND 0x08000000
+#define AR_D_GBL_IFS_MISC_IGNORE_BACKOFF 0x10000000
+
+#define AR_D_FPCTL 0x1230
+#define AR_D_FPCTL_DCU 0x0000000F
+#define AR_D_FPCTL_DCU_S 0
+#define AR_D_FPCTL_PREFETCH_EN 0x00000010
+#define AR_D_FPCTL_BURST_PREFETCH 0x00007FE0
+#define AR_D_FPCTL_BURST_PREFETCH_S 5
+
+#define AR_D_TXPSE 0x1270
+#define AR_D_TXPSE_CTRL 0x000003FF
+#define AR_D_TXPSE_RESV0 0x0000FC00
+#define AR_D_TXPSE_STATUS 0x00010000
+#define AR_D_TXPSE_RESV1 0xFFFE0000
+
+#define AR_D_TXSLOTMASK 0x12f0
+#define AR_D_TXSLOTMASK_NUM 0x0000000F
+
+#define AR_CFG_LED 0x1f04
+#define AR_CFG_SCLK_RATE_IND 0x00000003
+#define AR_CFG_SCLK_RATE_IND_S 0
+#define AR_CFG_SCLK_32MHZ 0x00000000
+#define AR_CFG_SCLK_4MHZ 0x00000001
+#define AR_CFG_SCLK_1MHZ 0x00000002
+#define AR_CFG_SCLK_32KHZ 0x00000003
+#define AR_CFG_LED_BLINK_SLOW 0x00000008
+#define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070
+#define AR_CFG_LED_MODE_SEL 0x00000380
+#define AR_CFG_LED_MODE_SEL_S 7
+#define AR_CFG_LED_POWER 0x00000280
+#define AR_CFG_LED_POWER_S 7
+#define AR_CFG_LED_NETWORK 0x00000300
+#define AR_CFG_LED_NETWORK_S 7
+#define AR_CFG_LED_MODE_PROP 0x0
+#define AR_CFG_LED_MODE_RPROP 0x1
+#define AR_CFG_LED_MODE_SPLIT 0x2
+#define AR_CFG_LED_MODE_RAND 0x3
+#define AR_CFG_LED_MODE_POWER_OFF 0x4
+#define AR_CFG_LED_MODE_POWER_ON 0x5
+#define AR_CFG_LED_MODE_NETWORK_OFF 0x4
+#define AR_CFG_LED_MODE_NETWORK_ON 0x6
+#define AR_CFG_LED_ASSOC_CTL 0x00000c00
+#define AR_CFG_LED_ASSOC_CTL_S 10
+#define AR_CFG_LED_ASSOC_NONE 0x0
+#define AR_CFG_LED_ASSOC_ACTIVE 0x1
+#define AR_CFG_LED_ASSOC_PENDING 0x2
+
+#define AR_CFG_LED_BLINK_SLOW 0x00000008
+#define AR_CFG_LED_BLINK_SLOW_S 3
+
+#define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070
+#define AR_CFG_LED_BLINK_THRESH_SEL_S 4
+
+#define AR_MAC_SLEEP 0x1f00
+#define AR_MAC_SLEEP_MAC_AWAKE 0x00000000
+#define AR_MAC_SLEEP_MAC_ASLEEP 0x00000001
+
+#define AR_RC 0x4000
+#define AR_RC_AHB 0x00000001
+#define AR_RC_APB 0x00000002
+#define AR_RC_HOSTIF 0x00000100
+
+#define AR_WA (AR_SREV_9340(ah) ? 0x40c4 : 0x4004)
+#define AR_WA_BIT6 (1 << 6)
+#define AR_WA_BIT7 (1 << 7)
+#define AR_WA_BIT23 (1 << 23)
+#define AR_WA_D3_L1_DISABLE (1 << 14)
+#define AR_WA_D3_TO_L1_DISABLE_REAL (1 << 16)
+#define AR_WA_ASPM_TIMER_BASED_DISABLE (1 << 17)
+#define AR_WA_RESET_EN (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */
+#define AR_WA_ANALOG_SHIFT (1 << 20)
+#define AR_WA_POR_SHORT (1 << 21) /* PCI-E Phy reset control */
+#define AR_WA_BIT22 (1 << 22)
+#define AR9285_WA_DEFAULT 0x004a050b
+#define AR9280_WA_DEFAULT 0x0040073b
+#define AR_WA_DEFAULT 0x0000073f
+
+
+#define AR_PM_STATE 0x4008
+#define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000
+
+#define AR_HOST_TIMEOUT (AR_SREV_9340(ah) ? 0x4008 : 0x4018)
+#define AR_HOST_TIMEOUT_APB_CNTR 0x0000FFFF
+#define AR_HOST_TIMEOUT_APB_CNTR_S 0
+#define AR_HOST_TIMEOUT_LCL_CNTR 0xFFFF0000
+#define AR_HOST_TIMEOUT_LCL_CNTR_S 16
+
+#define AR_EEPROM 0x401c
+#define AR_EEPROM_ABSENT 0x00000100
+#define AR_EEPROM_CORRUPT 0x00000200
+#define AR_EEPROM_PROT_MASK 0x03FFFC00
+#define AR_EEPROM_PROT_MASK_S 10
+
+#define EEPROM_PROTECT_RP_0_31 0x0001
+#define EEPROM_PROTECT_WP_0_31 0x0002
+#define EEPROM_PROTECT_RP_32_63 0x0004
+#define EEPROM_PROTECT_WP_32_63 0x0008
+#define EEPROM_PROTECT_RP_64_127 0x0010
+#define EEPROM_PROTECT_WP_64_127 0x0020
+#define EEPROM_PROTECT_RP_128_191 0x0040
+#define EEPROM_PROTECT_WP_128_191 0x0080
+#define EEPROM_PROTECT_RP_192_255 0x0100
+#define EEPROM_PROTECT_WP_192_255 0x0200
+#define EEPROM_PROTECT_RP_256_511 0x0400
+#define EEPROM_PROTECT_WP_256_511 0x0800
+#define EEPROM_PROTECT_RP_512_1023 0x1000
+#define EEPROM_PROTECT_WP_512_1023 0x2000
+#define EEPROM_PROTECT_RP_1024_2047 0x4000
+#define EEPROM_PROTECT_WP_1024_2047 0x8000
+
+#define AR_SREV \
+ ((AR_SREV_9100(ah)) ? 0x0600 : (AR_SREV_9340(ah) \
+ ? 0x400c : 0x4020))
+
+#define AR_SREV_ID \
+ ((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF)
+#define AR_SREV_VERSION 0x000000F0
+#define AR_SREV_VERSION_S 4
+#define AR_SREV_REVISION 0x00000007
+
+#define AR_SREV_ID2 0xFFFFFFFF
+#define AR_SREV_VERSION2 0xFFFC0000
+#define AR_SREV_VERSION2_S 18
+#define AR_SREV_TYPE2 0x0003F000
+#define AR_SREV_TYPE2_S 12
+#define AR_SREV_TYPE2_CHAIN 0x00001000
+#define AR_SREV_TYPE2_HOST_MODE 0x00002000
+#define AR_SREV_REVISION2 0x00000F00
+#define AR_SREV_REVISION2_S 8
+
+#define AR_SREV_VERSION_5416_PCI 0xD
+#define AR_SREV_VERSION_5416_PCIE 0xC
+#define AR_SREV_REVISION_5416_10 0
+#define AR_SREV_REVISION_5416_20 1
+#define AR_SREV_REVISION_5416_22 2
+#define AR_SREV_VERSION_9100 0x14
+#define AR_SREV_VERSION_9160 0x40
+#define AR_SREV_REVISION_9160_10 0
+#define AR_SREV_REVISION_9160_11 1
+#define AR_SREV_VERSION_9280 0x80
+#define AR_SREV_REVISION_9280_10 0
+#define AR_SREV_REVISION_9280_20 1
+#define AR_SREV_REVISION_9280_21 2
+#define AR_SREV_VERSION_9285 0xC0
+#define AR_SREV_REVISION_9285_10 0
+#define AR_SREV_REVISION_9285_11 1
+#define AR_SREV_REVISION_9285_12 2
+#define AR_SREV_VERSION_9287 0x180
+#define AR_SREV_REVISION_9287_10 0
+#define AR_SREV_REVISION_9287_11 1
+#define AR_SREV_REVISION_9287_12 2
+#define AR_SREV_REVISION_9287_13 3
+#define AR_SREV_VERSION_9271 0x140
+#define AR_SREV_REVISION_9271_10 0
+#define AR_SREV_REVISION_9271_11 1
+#define AR_SREV_VERSION_9300 0x1c0
+#define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */
+#define AR_SREV_VERSION_9485 0x240
+#define AR_SREV_REVISION_9485_10 0
+#define AR_SREV_REVISION_9485_11 1
+#define AR_SREV_VERSION_9340 0x300
+
+#define AR_SREV_5416(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
+ ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE))
+#define AR_SREV_5416_20_OR_LATER(_ah) \
+ (((AR_SREV_5416(_ah)) && \
+ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \
+ ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
+#define AR_SREV_5416_22_OR_LATER(_ah) \
+ (((AR_SREV_5416(_ah)) && \
+ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \
+ ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
+
+#define AR_SREV_9100(ah) \
+ ((ah->hw_version.macVersion) == AR_SREV_VERSION_9100)
+#define AR_SREV_9100_OR_LATER(_ah) \
+ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
+
+#define AR_SREV_9160(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9160))
+#define AR_SREV_9160_10_OR_LATER(_ah) \
+ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9160))
+#define AR_SREV_9160_11(_ah) \
+ (AR_SREV_9160(_ah) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11))
+#define AR_SREV_9280(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280))
+#define AR_SREV_9280_20_OR_LATER(_ah) \
+ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280))
+#define AR_SREV_9280_20(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280))
+
+#define AR_SREV_9285(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285))
+#define AR_SREV_9285_12_OR_LATER(_ah) \
+ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285))
+
+#define AR_SREV_9287(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287))
+#define AR_SREV_9287_11_OR_LATER(_ah) \
+ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9287))
+#define AR_SREV_9287_11(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_11))
+#define AR_SREV_9287_12(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_12))
+#define AR_SREV_9287_12_OR_LATER(_ah) \
+ (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
+ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_12)))
+#define AR_SREV_9287_13_OR_LATER(_ah) \
+ (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
+ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_13)))
+
+#define AR_SREV_9271(_ah) \
+ (((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271)
+#define AR_SREV_9271_10(_ah) \
+ (AR_SREV_9271(_ah) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_10))
+#define AR_SREV_9271_11(_ah) \
+ (AR_SREV_9271(_ah) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11))
+
+#define AR_SREV_9300(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))
+#define AR_SREV_9300_20_OR_LATER(_ah) \
+ ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300)
+
+#define AR_SREV_9485(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
+#define AR_SREV_9485_10(_ah) \
+ (AR_SREV_9485(_ah) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_10))
+#define AR_SREV_9485_11(_ah) \
+ (AR_SREV_9485(_ah) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11))
+#define AR_SREV_9485_OR_LATER(_ah) \
+ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485))
+
+#define AR_SREV_9340(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9340))
+
+#define AR_SREV_9285E_20(_ah) \
+ (AR_SREV_9285_12_OR_LATER(_ah) && \
+ ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
+
+enum ath_usb_dev {
+ AR9280_USB = 1, /* AR7010 + AR9280, UB94 */
+ AR9287_USB = 2, /* AR7010 + AR9287, UB95 */
+ STORAGE_DEVICE = 3,
+};
+
+#define AR_DEVID_7010(_ah) \
+ (((_ah)->hw_version.usbdev == AR9280_USB) || \
+ ((_ah)->hw_version.usbdev == AR9287_USB))
+
+#define AR_RADIO_SREV_MAJOR 0xf0
+#define AR_RAD5133_SREV_MAJOR 0xc0
+#define AR_RAD2133_SREV_MAJOR 0xd0
+#define AR_RAD5122_SREV_MAJOR 0xe0
+#define AR_RAD2122_SREV_MAJOR 0xf0
+
+#define AR_AHB_MODE 0x4024
+#define AR_AHB_EXACT_WR_EN 0x00000000
+#define AR_AHB_BUF_WR_EN 0x00000001
+#define AR_AHB_EXACT_RD_EN 0x00000000
+#define AR_AHB_CACHELINE_RD_EN 0x00000002
+#define AR_AHB_PREFETCH_RD_EN 0x00000004
+#define AR_AHB_PAGE_SIZE_1K 0x00000000
+#define AR_AHB_PAGE_SIZE_2K 0x00000008
+#define AR_AHB_PAGE_SIZE_4K 0x00000010
+#define AR_AHB_CUSTOM_BURST_EN 0x000000C0
+#define AR_AHB_CUSTOM_BURST_EN_S 6
+#define AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL 3
+
+#define AR_INTR_RTC_IRQ 0x00000001
+#define AR_INTR_MAC_IRQ 0x00000002
+#define AR_INTR_EEP_PROT_ACCESS 0x00000004
+#define AR_INTR_MAC_AWAKE 0x00020000
+#define AR_INTR_MAC_ASLEEP 0x00040000
+#define AR_INTR_SPURIOUS 0xFFFFFFFF
+
+
+#define AR_INTR_SYNC_CAUSE (AR_SREV_9340(ah) ? 0x4010 : 0x4028)
+#define AR_INTR_SYNC_CAUSE_CLR (AR_SREV_9340(ah) ? 0x4010 : 0x4028)
+
+
+#define AR_INTR_SYNC_ENABLE (AR_SREV_9340(ah) ? 0x4014 : 0x402c)
+#define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000
+#define AR_INTR_SYNC_ENABLE_GPIO_S 18
+
+enum {
+ AR_INTR_SYNC_RTC_IRQ = 0x00000001,
+ AR_INTR_SYNC_MAC_IRQ = 0x00000002,
+ AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS = 0x00000004,
+ AR_INTR_SYNC_APB_TIMEOUT = 0x00000008,
+ AR_INTR_SYNC_PCI_MODE_CONFLICT = 0x00000010,
+ AR_INTR_SYNC_HOST1_FATAL = 0x00000020,
+ AR_INTR_SYNC_HOST1_PERR = 0x00000040,
+ AR_INTR_SYNC_TRCV_FIFO_PERR = 0x00000080,
+ AR_INTR_SYNC_RADM_CPL_EP = 0x00000100,
+ AR_INTR_SYNC_RADM_CPL_DLLP_ABORT = 0x00000200,
+ AR_INTR_SYNC_RADM_CPL_TLP_ABORT = 0x00000400,
+ AR_INTR_SYNC_RADM_CPL_ECRC_ERR = 0x00000800,
+ AR_INTR_SYNC_RADM_CPL_TIMEOUT = 0x00001000,
+ AR_INTR_SYNC_LOCAL_TIMEOUT = 0x00002000,
+ AR_INTR_SYNC_PM_ACCESS = 0x00004000,
+ AR_INTR_SYNC_MAC_AWAKE = 0x00008000,
+ AR_INTR_SYNC_MAC_ASLEEP = 0x00010000,
+ AR_INTR_SYNC_MAC_SLEEP_ACCESS = 0x00020000,
+ AR_INTR_SYNC_ALL = 0x0003FFFF,
+
+
+ AR_INTR_SYNC_DEFAULT = (AR_INTR_SYNC_HOST1_FATAL |
+ AR_INTR_SYNC_HOST1_PERR |
+ AR_INTR_SYNC_RADM_CPL_EP |
+ AR_INTR_SYNC_RADM_CPL_DLLP_ABORT |
+ AR_INTR_SYNC_RADM_CPL_TLP_ABORT |
+ AR_INTR_SYNC_RADM_CPL_ECRC_ERR |
+ AR_INTR_SYNC_RADM_CPL_TIMEOUT |
+ AR_INTR_SYNC_LOCAL_TIMEOUT |
+ AR_INTR_SYNC_MAC_SLEEP_ACCESS),
+
+ AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF,
+
+};
+
+#define AR_INTR_ASYNC_MASK (AR_SREV_9340(ah) ? 0x4018 : 0x4030)
+#define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000
+#define AR_INTR_ASYNC_MASK_GPIO_S 18
+
+#define AR_INTR_SYNC_MASK (AR_SREV_9340(ah) ? 0x401c : 0x4034)
+#define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000
+#define AR_INTR_SYNC_MASK_GPIO_S 18
+
+#define AR_INTR_ASYNC_CAUSE_CLR (AR_SREV_9340(ah) ? 0x4020 : 0x4038)
+#define AR_INTR_ASYNC_CAUSE (AR_SREV_9340(ah) ? 0x4020 : 0x4038)
+
+#define AR_INTR_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4024 : 0x403c)
+#define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000
+#define AR_INTR_ASYNC_ENABLE_GPIO_S 18
+
+#define AR_PCIE_SERDES 0x4040
+#define AR_PCIE_SERDES2 0x4044
+#define AR_PCIE_PM_CTRL (AR_SREV_9340(ah) ? 0x4004 : 0x4014)
+#define AR_PCIE_PM_CTRL_ENA 0x00080000
+
+#define AR_NUM_GPIO 14
+#define AR928X_NUM_GPIO 10
+#define AR9285_NUM_GPIO 12
+#define AR9287_NUM_GPIO 11
+#define AR9271_NUM_GPIO 16
+#define AR9300_NUM_GPIO 17
+#define AR7010_NUM_GPIO 16
+
+#define AR_GPIO_IN_OUT (AR_SREV_9340(ah) ? 0x4028 : 0x4048)
+#define AR_GPIO_IN_VAL 0x0FFFC000
+#define AR_GPIO_IN_VAL_S 14
+#define AR928X_GPIO_IN_VAL 0x000FFC00
+#define AR928X_GPIO_IN_VAL_S 10
+#define AR9285_GPIO_IN_VAL 0x00FFF000
+#define AR9285_GPIO_IN_VAL_S 12
+#define AR9287_GPIO_IN_VAL 0x003FF800
+#define AR9287_GPIO_IN_VAL_S 11
+#define AR9271_GPIO_IN_VAL 0xFFFF0000
+#define AR9271_GPIO_IN_VAL_S 16
+#define AR7010_GPIO_IN_VAL 0x0000FFFF
+#define AR7010_GPIO_IN_VAL_S 0
+
+#define AR_GPIO_IN (AR_SREV_9340(ah) ? 0x402c : 0x404c)
+#define AR9300_GPIO_IN_VAL 0x0001FFFF
+#define AR9300_GPIO_IN_VAL_S 0
+
+#define AR_GPIO_OE_OUT (AR_SREV_9340(ah) ? 0x4030 : \
+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c))
+#define AR_GPIO_OE_OUT_DRV 0x3
+#define AR_GPIO_OE_OUT_DRV_NO 0x0
+#define AR_GPIO_OE_OUT_DRV_LOW 0x1
+#define AR_GPIO_OE_OUT_DRV_HI 0x2
+#define AR_GPIO_OE_OUT_DRV_ALL 0x3
+
+#define AR7010_GPIO_OE 0x52000
+#define AR7010_GPIO_OE_MASK 0x1
+#define AR7010_GPIO_OE_AS_OUTPUT 0x0
+#define AR7010_GPIO_OE_AS_INPUT 0x1
+#define AR7010_GPIO_IN 0x52004
+#define AR7010_GPIO_OUT 0x52008
+#define AR7010_GPIO_SET 0x5200C
+#define AR7010_GPIO_CLEAR 0x52010
+#define AR7010_GPIO_INT 0x52014
+#define AR7010_GPIO_INT_TYPE 0x52018
+#define AR7010_GPIO_INT_POLARITY 0x5201C
+#define AR7010_GPIO_PENDING 0x52020
+#define AR7010_GPIO_INT_MASK 0x52024
+#define AR7010_GPIO_FUNCTION 0x52028
+
+#define AR_GPIO_INTR_POL (AR_SREV_9340(ah) ? 0x4038 : \
+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050))
+#define AR_GPIO_INTR_POL_VAL 0x0001FFFF
+#define AR_GPIO_INTR_POL_VAL_S 0
+
+#define AR_GPIO_INPUT_EN_VAL (AR_SREV_9340(ah) ? 0x403c : \
+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x405c : 0x4054))
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2
+#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008
+#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_S 3
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF 0x00000010
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S 4
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB 0x00000400
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S 10
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15
+#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000
+#define AR_GPIO_JTAG_DISABLE 0x00020000
+
+#define AR_GPIO_INPUT_MUX1 (AR_SREV_9340(ah) ? 0x4040 : \
+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4060 : 0x4058))
+#define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000
+#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16
+#define AR_GPIO_INPUT_MUX1_BT_PRIORITY 0x00000f00
+#define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8
+
+#define AR_GPIO_INPUT_MUX2 (AR_SREV_9340(ah) ? 0x4044 : \
+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4064 : 0x405c))
+#define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f
+#define AR_GPIO_INPUT_MUX2_CLK25_S 0
+#define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0
+#define AR_GPIO_INPUT_MUX2_RFSILENT_S 4
+#define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00
+#define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8
+
+#define AR_GPIO_OUTPUT_MUX1 (AR_SREV_9340(ah) ? 0x4048 : \
+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4068 : 0x4060))
+#define AR_GPIO_OUTPUT_MUX2 (AR_SREV_9340(ah) ? 0x404c : \
+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x406c : 0x4064))
+#define AR_GPIO_OUTPUT_MUX3 (AR_SREV_9340(ah) ? 0x4050 : \
+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4070 : 0x4068))
+
+#define AR_INPUT_STATE (AR_SREV_9340(ah) ? 0x4054 : \
+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4074 : 0x406c))
+
+#define AR_EEPROM_STATUS_DATA (AR_SREV_9340(ah) ? 0x40c8 : \
+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4084 : 0x407c))
+#define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff
+#define AR_EEPROM_STATUS_DATA_VAL_S 0
+#define AR_EEPROM_STATUS_DATA_BUSY 0x00010000
+#define AR_EEPROM_STATUS_DATA_BUSY_ACCESS 0x00020000
+#define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000
+#define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000
+
+#define AR_OBS (AR_SREV_9340(ah) ? 0x405c : \
+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4088 : 0x4080))
+
+#define AR_GPIO_PDPU (AR_SREV_9300_20_OR_LATER(ah) ? 0x4090 : 0x4088)
+
+#define AR_PCIE_MSI (AR_SREV_9340(ah) ? 0x40d8 : \
+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094))
+#define AR_PCIE_MSI_ENABLE 0x00000001
+
+#define AR_INTR_PRIO_SYNC_ENABLE (AR_SREV_9340(ah) ? 0x4088 : 0x40c4)
+#define AR_INTR_PRIO_ASYNC_MASK (AR_SREV_9340(ah) ? 0x408c : 0x40c8)
+#define AR_INTR_PRIO_SYNC_MASK (AR_SREV_9340(ah) ? 0x4090 : 0x40cc)
+#define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4)
+#define AR_ENT_OTP 0x40d8
+#define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000
+#define AR_ENT_OTP_MPSD 0x00800000
+
+#define AR_CH0_BB_DPLL1 0x16180
+#define AR_CH0_BB_DPLL1_REFDIV 0xF8000000
+#define AR_CH0_BB_DPLL1_REFDIV_S 27
+#define AR_CH0_BB_DPLL1_NINI 0x07FC0000
+#define AR_CH0_BB_DPLL1_NINI_S 18
+#define AR_CH0_BB_DPLL1_NFRAC 0x0003FFFF
+#define AR_CH0_BB_DPLL1_NFRAC_S 0
+
+#define AR_CH0_BB_DPLL2 0x16184
+#define AR_CH0_BB_DPLL2_LOCAL_PLL 0x40000000
+#define AR_CH0_BB_DPLL2_LOCAL_PLL_S 30
+#define AR_CH0_DPLL2_KI 0x3C000000
+#define AR_CH0_DPLL2_KI_S 26
+#define AR_CH0_DPLL2_KD 0x03F80000
+#define AR_CH0_DPLL2_KD_S 19
+#define AR_CH0_BB_DPLL2_EN_NEGTRIG 0x00040000
+#define AR_CH0_BB_DPLL2_EN_NEGTRIG_S 18
+#define AR_CH0_BB_DPLL2_PLL_PWD 0x00010000
+#define AR_CH0_BB_DPLL2_PLL_PWD_S 16
+#define AR_CH0_BB_DPLL2_OUTDIV 0x0000E000
+#define AR_CH0_BB_DPLL2_OUTDIV_S 13
+
+#define AR_CH0_BB_DPLL3 0x16188
+#define AR_CH0_BB_DPLL3_PHASE_SHIFT 0x3F800000
+#define AR_CH0_BB_DPLL3_PHASE_SHIFT_S 23
+
+#define AR_CH0_DDR_DPLL2 0x16244
+#define AR_CH0_DDR_DPLL3 0x16248
+#define AR_CH0_DPLL3_PHASE_SHIFT 0x3F800000
+#define AR_CH0_DPLL3_PHASE_SHIFT_S 23
+#define AR_PHY_CCA_NOM_VAL_2GHZ -118
+
+#define AR_RTC_9300_PLL_DIV 0x000003ff
+#define AR_RTC_9300_PLL_DIV_S 0
+#define AR_RTC_9300_PLL_REFDIV 0x00003C00
+#define AR_RTC_9300_PLL_REFDIV_S 10
+#define AR_RTC_9300_PLL_CLKSEL 0x0000C000
+#define AR_RTC_9300_PLL_CLKSEL_S 14
+
+#define AR_RTC_9160_PLL_DIV 0x000003ff
+#define AR_RTC_9160_PLL_DIV_S 0
+#define AR_RTC_9160_PLL_REFDIV 0x00003C00
+#define AR_RTC_9160_PLL_REFDIV_S 10
+#define AR_RTC_9160_PLL_CLKSEL 0x0000C000
+#define AR_RTC_9160_PLL_CLKSEL_S 14
+
+#define AR_RTC_BASE 0x00020000
+#define AR_RTC_RC \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000)
+#define AR_RTC_RC_M 0x00000003
+#define AR_RTC_RC_MAC_WARM 0x00000001
+#define AR_RTC_RC_MAC_COLD 0x00000002
+#define AR_RTC_RC_COLD_RESET 0x00000004
+#define AR_RTC_RC_WARM_RESET 0x00000008
+
+/* Crystal Control */
+#define AR_RTC_XTAL_CONTROL 0x7004
+
+/* Reg Control 0 */
+#define AR_RTC_REG_CONTROL0 0x7008
+
+/* Reg Control 1 */
+#define AR_RTC_REG_CONTROL1 0x700c
+#define AR_RTC_REG_CONTROL1_SWREG_PROGRAM 0x00000001
+
+#define AR_RTC_PLL_CONTROL \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014)
+
+#define AR_RTC_PLL_CONTROL2 0x703c
+
+#define AR_RTC_PLL_DIV 0x0000001f
+#define AR_RTC_PLL_DIV_S 0
+#define AR_RTC_PLL_DIV2 0x00000020
+#define AR_RTC_PLL_REFDIV_5 0x000000c0
+#define AR_RTC_PLL_CLKSEL 0x00000300
+#define AR_RTC_PLL_CLKSEL_S 8
+#define AR_RTC_PLL_BYPASS 0x00010000
+
+#define PLL3 0x16188
+#define PLL3_DO_MEAS_MASK 0x40000000
+#define PLL4 0x1618c
+#define PLL4_MEAS_DONE 0x8
+#define SQSUM_DVC_MASK 0x007ffff8
+
+#define AR_RTC_RESET \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040)
+#define AR_RTC_RESET_EN (0x00000001)
+
+#define AR_RTC_STATUS \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0044) : 0x7044)
+
+#define AR_RTC_STATUS_M \
+ ((AR_SREV_9100(ah)) ? 0x0000003f : 0x0000000f)
+
+#define AR_RTC_PM_STATUS_M 0x0000000f
+
+#define AR_RTC_STATUS_SHUTDOWN 0x00000001
+#define AR_RTC_STATUS_ON 0x00000002
+#define AR_RTC_STATUS_SLEEP 0x00000004
+#define AR_RTC_STATUS_WAKEUP 0x00000008
+
+#define AR_RTC_SLEEP_CLK \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0048) : 0x7048)
+#define AR_RTC_FORCE_DERIVED_CLK 0x2
+#define AR_RTC_FORCE_SWREG_PRD 0x00000004
+
+#define AR_RTC_FORCE_WAKE \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x004c) : 0x704c)
+#define AR_RTC_FORCE_WAKE_EN 0x00000001
+#define AR_RTC_FORCE_WAKE_ON_INT 0x00000002
+
+
+#define AR_RTC_INTR_CAUSE \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0050) : 0x7050)
+
+#define AR_RTC_INTR_ENABLE \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0054) : 0x7054)
+
+#define AR_RTC_INTR_MASK \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058)
+
+/* RTC_DERIVED_* - only for AR9100 */
+
+#define AR_RTC_DERIVED_CLK \
+ (AR_SREV_9100(ah) ? (AR_RTC_BASE + 0x0038) : 0x7038)
+#define AR_RTC_DERIVED_CLK_PERIOD 0x0000fffe
+#define AR_RTC_DERIVED_CLK_PERIOD_S 1
+
+#define AR_SEQ_MASK 0x8060
+
+#define AR_AN_RF2G1_CH0 0x7810
+#define AR_AN_RF2G1_CH0_OB 0x03800000
+#define AR_AN_RF2G1_CH0_OB_S 23
+#define AR_AN_RF2G1_CH0_DB 0x1C000000
+#define AR_AN_RF2G1_CH0_DB_S 26
+
+#define AR_AN_RF5G1_CH0 0x7818
+#define AR_AN_RF5G1_CH0_OB5 0x00070000
+#define AR_AN_RF5G1_CH0_OB5_S 16
+#define AR_AN_RF5G1_CH0_DB5 0x00380000
+#define AR_AN_RF5G1_CH0_DB5_S 19
+
+#define AR_AN_RF2G1_CH1 0x7834
+#define AR_AN_RF2G1_CH1_OB 0x03800000
+#define AR_AN_RF2G1_CH1_OB_S 23
+#define AR_AN_RF2G1_CH1_DB 0x1C000000
+#define AR_AN_RF2G1_CH1_DB_S 26
+
+#define AR_AN_RF5G1_CH1 0x783C
+#define AR_AN_RF5G1_CH1_OB5 0x00070000
+#define AR_AN_RF5G1_CH1_OB5_S 16
+#define AR_AN_RF5G1_CH1_DB5 0x00380000
+#define AR_AN_RF5G1_CH1_DB5_S 19
+
+#define AR_AN_TOP1 0x7890
+#define AR_AN_TOP1_DACIPMODE 0x00040000
+#define AR_AN_TOP1_DACIPMODE_S 18
+
+#define AR_AN_TOP2 0x7894
+#define AR_AN_TOP2_XPABIAS_LVL 0xC0000000
+#define AR_AN_TOP2_XPABIAS_LVL_S 30
+#define AR_AN_TOP2_LOCALBIAS 0x00200000
+#define AR_AN_TOP2_LOCALBIAS_S 21
+#define AR_AN_TOP2_PWDCLKIND 0x00400000
+#define AR_AN_TOP2_PWDCLKIND_S 22
+
+#define AR_AN_SYNTH9 0x7868
+#define AR_AN_SYNTH9_REFDIVA 0xf8000000
+#define AR_AN_SYNTH9_REFDIVA_S 27
+
+#define AR9285_AN_RF2G1 0x7820
+#define AR9285_AN_RF2G1_ENPACAL 0x00000800
+#define AR9285_AN_RF2G1_ENPACAL_S 11
+#define AR9285_AN_RF2G1_PDPADRV1 0x02000000
+#define AR9285_AN_RF2G1_PDPADRV1_S 25
+#define AR9285_AN_RF2G1_PDPADRV2 0x01000000
+#define AR9285_AN_RF2G1_PDPADRV2_S 24
+#define AR9285_AN_RF2G1_PDPAOUT 0x00800000
+#define AR9285_AN_RF2G1_PDPAOUT_S 23
+
+
+#define AR9285_AN_RF2G2 0x7824
+#define AR9285_AN_RF2G2_OFFCAL 0x00001000
+#define AR9285_AN_RF2G2_OFFCAL_S 12
+
+#define AR9285_AN_RF2G3 0x7828
+#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000
+#define AR9285_AN_RF2G3_PDVCCOMP_S 25
+#define AR9285_AN_RF2G3_OB_0 0x00E00000
+#define AR9285_AN_RF2G3_OB_0_S 21
+#define AR9285_AN_RF2G3_OB_1 0x001C0000
+#define AR9285_AN_RF2G3_OB_1_S 18
+#define AR9285_AN_RF2G3_OB_2 0x00038000
+#define AR9285_AN_RF2G3_OB_2_S 15
+#define AR9285_AN_RF2G3_OB_3 0x00007000
+#define AR9285_AN_RF2G3_OB_3_S 12
+#define AR9285_AN_RF2G3_OB_4 0x00000E00
+#define AR9285_AN_RF2G3_OB_4_S 9
+
+#define AR9285_AN_RF2G3_DB1_0 0x000001C0
+#define AR9285_AN_RF2G3_DB1_0_S 6
+#define AR9285_AN_RF2G3_DB1_1 0x00000038
+#define AR9285_AN_RF2G3_DB1_1_S 3
+#define AR9285_AN_RF2G3_DB1_2 0x00000007
+#define AR9285_AN_RF2G3_DB1_2_S 0
+#define AR9285_AN_RF2G4 0x782C
+#define AR9285_AN_RF2G4_DB1_3 0xE0000000
+#define AR9285_AN_RF2G4_DB1_3_S 29
+#define AR9285_AN_RF2G4_DB1_4 0x1C000000
+#define AR9285_AN_RF2G4_DB1_4_S 26
+
+#define AR9285_AN_RF2G4_DB2_0 0x03800000
+#define AR9285_AN_RF2G4_DB2_0_S 23
+#define AR9285_AN_RF2G4_DB2_1 0x00700000
+#define AR9285_AN_RF2G4_DB2_1_S 20
+#define AR9285_AN_RF2G4_DB2_2 0x000E0000
+#define AR9285_AN_RF2G4_DB2_2_S 17
+#define AR9285_AN_RF2G4_DB2_3 0x0001C000
+#define AR9285_AN_RF2G4_DB2_3_S 14
+#define AR9285_AN_RF2G4_DB2_4 0x00003800
+#define AR9285_AN_RF2G4_DB2_4_S 11
+
+#define AR9285_RF2G5 0x7830
+#define AR9285_RF2G5_IC50TX 0xfffff8ff
+#define AR9285_RF2G5_IC50TX_SET 0x00000400
+#define AR9285_RF2G5_IC50TX_XE_SET 0x00000500
+#define AR9285_RF2G5_IC50TX_CLEAR 0x00000700
+#define AR9285_RF2G5_IC50TX_CLEAR_S 8
+
+/* AR9271 : 0x7828, 0x782c different setting from AR9285 */
+#define AR9271_AN_RF2G3_OB_cck 0x001C0000
+#define AR9271_AN_RF2G3_OB_cck_S 18
+#define AR9271_AN_RF2G3_OB_psk 0x00038000
+#define AR9271_AN_RF2G3_OB_psk_S 15
+#define AR9271_AN_RF2G3_OB_qam 0x00007000
+#define AR9271_AN_RF2G3_OB_qam_S 12
+
+#define AR9271_AN_RF2G3_DB_1 0x00E00000
+#define AR9271_AN_RF2G3_DB_1_S 21
+
+#define AR9271_AN_RF2G3_CCOMP 0xFFF
+#define AR9271_AN_RF2G3_CCOMP_S 0
+
+#define AR9271_AN_RF2G4_DB_2 0xE0000000
+#define AR9271_AN_RF2G4_DB_2_S 29
+
+#define AR9285_AN_RF2G6 0x7834
+#define AR9285_AN_RF2G6_CCOMP 0x00007800
+#define AR9285_AN_RF2G6_CCOMP_S 11
+#define AR9285_AN_RF2G6_OFFS 0x03f00000
+#define AR9285_AN_RF2G6_OFFS_S 20
+
+#define AR9271_AN_RF2G6_OFFS 0x07f00000
+#define AR9271_AN_RF2G6_OFFS_S 20
+
+#define AR9285_AN_RF2G7 0x7838
+#define AR9285_AN_RF2G7_PWDDB 0x00000002
+#define AR9285_AN_RF2G7_PWDDB_S 1
+#define AR9285_AN_RF2G7_PADRVGN2TAB0 0xE0000000
+#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29
+
+#define AR9285_AN_RF2G8 0x783C
+#define AR9285_AN_RF2G8_PADRVGN2TAB0 0x0001C000
+#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14
+
+
+#define AR9285_AN_RF2G9 0x7840
+#define AR9285_AN_RXTXBB1 0x7854
+#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020
+#define AR9285_AN_RXTXBB1_PDRXTXBB1_S 5
+#define AR9285_AN_RXTXBB1_PDV2I 0x00000080
+#define AR9285_AN_RXTXBB1_PDV2I_S 7
+#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100
+#define AR9285_AN_RXTXBB1_PDDACIF_S 8
+#define AR9285_AN_RXTXBB1_SPARE9 0x00000001
+#define AR9285_AN_RXTXBB1_SPARE9_S 0
+
+#define AR9285_AN_TOP2 0x7868
+
+#define AR9285_AN_TOP3 0x786c
+#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C
+#define AR9285_AN_TOP3_XPABIAS_LVL_S 2
+#define AR9285_AN_TOP3_PWDDAC 0x00800000
+#define AR9285_AN_TOP3_PWDDAC_S 23
+
+#define AR9285_AN_TOP4 0x7870
+#define AR9285_AN_TOP4_DEFAULT 0x10142c00
+
+#define AR9287_AN_RF2G3_CH0 0x7808
+#define AR9287_AN_RF2G3_CH1 0x785c
+#define AR9287_AN_RF2G3_DB1 0xE0000000
+#define AR9287_AN_RF2G3_DB1_S 29
+#define AR9287_AN_RF2G3_DB2 0x1C000000
+#define AR9287_AN_RF2G3_DB2_S 26
+#define AR9287_AN_RF2G3_OB_CCK 0x03800000
+#define AR9287_AN_RF2G3_OB_CCK_S 23
+#define AR9287_AN_RF2G3_OB_PSK 0x00700000
+#define AR9287_AN_RF2G3_OB_PSK_S 20
+#define AR9287_AN_RF2G3_OB_QAM 0x000E0000
+#define AR9287_AN_RF2G3_OB_QAM_S 17
+#define AR9287_AN_RF2G3_OB_PAL_OFF 0x0001C000
+#define AR9287_AN_RF2G3_OB_PAL_OFF_S 14
+
+#define AR9287_AN_TXPC0 0x7898
+#define AR9287_AN_TXPC0_TXPCMODE 0x0000C000
+#define AR9287_AN_TXPC0_TXPCMODE_S 14
+#define AR9287_AN_TXPC0_TXPCMODE_NORMAL 0
+#define AR9287_AN_TXPC0_TXPCMODE_TEST 1
+#define AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE 2
+#define AR9287_AN_TXPC0_TXPCMODE_ATBTEST 3
+
+#define AR9287_AN_TOP2 0x78b4
+#define AR9287_AN_TOP2_XPABIAS_LVL 0xC0000000
+#define AR9287_AN_TOP2_XPABIAS_LVL_S 30
+
+/* AR9271 specific stuff */
+#define AR9271_RESET_POWER_DOWN_CONTROL 0x50044
+#define AR9271_RADIO_RF_RST 0x20
+#define AR9271_GATE_MAC_CTL 0x4000
+
+#define AR_STA_ID0 0x8000
+#define AR_STA_ID1 0x8004
+#define AR_STA_ID1_SADH_MASK 0x0000FFFF
+#define AR_STA_ID1_STA_AP 0x00010000
+#define AR_STA_ID1_ADHOC 0x00020000
+#define AR_STA_ID1_PWR_SAV 0x00040000
+#define AR_STA_ID1_KSRCHDIS 0x00080000
+#define AR_STA_ID1_PCF 0x00100000
+#define AR_STA_ID1_USE_DEFANT 0x00200000
+#define AR_STA_ID1_DEFANT_UPDATE 0x00400000
+#define AR_STA_ID1_AR9100_BA_FIX 0x00400000
+#define AR_STA_ID1_RTS_USE_DEF 0x00800000
+#define AR_STA_ID1_ACKCTS_6MB 0x01000000
+#define AR_STA_ID1_BASE_RATE_11B 0x02000000
+#define AR_STA_ID1_SECTOR_SELF_GEN 0x04000000
+#define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000
+#define AR_STA_ID1_KSRCH_MODE 0x10000000
+#define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000
+#define AR_STA_ID1_CBCIV_ENDIAN 0x40000000
+#define AR_STA_ID1_MCAST_KSRCH 0x80000000
+
+#define AR_BSS_ID0 0x8008
+#define AR_BSS_ID1 0x800C
+#define AR_BSS_ID1_U16 0x0000FFFF
+#define AR_BSS_ID1_AID 0x07FF0000
+#define AR_BSS_ID1_AID_S 16
+
+#define AR_BCN_RSSI_AVE 0x8010
+#define AR_BCN_RSSI_AVE_MASK 0x00000FFF
+
+#define AR_TIME_OUT 0x8014
+#define AR_TIME_OUT_ACK 0x00003FFF
+#define AR_TIME_OUT_ACK_S 0
+#define AR_TIME_OUT_CTS 0x3FFF0000
+#define AR_TIME_OUT_CTS_S 16
+#define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR 0x16001D56
+
+#define AR_RSSI_THR 0x8018
+#define AR_RSSI_THR_MASK 0x000000FF
+#define AR_RSSI_THR_BM_THR 0x0000FF00
+#define AR_RSSI_THR_BM_THR_S 8
+#define AR_RSSI_BCN_WEIGHT 0x1F000000
+#define AR_RSSI_BCN_WEIGHT_S 24
+#define AR_RSSI_BCN_RSSI_RST 0x20000000
+
+#define AR_USEC 0x801c
+#define AR_USEC_USEC 0x0000007F
+#define AR_USEC_TX_LAT 0x007FC000
+#define AR_USEC_TX_LAT_S 14
+#define AR_USEC_RX_LAT 0x1F800000
+#define AR_USEC_RX_LAT_S 23
+#define AR_USEC_ASYNC_FIFO_DUR 0x12e00074
+
+#define AR_RESET_TSF 0x8020
+#define AR_RESET_TSF_ONCE 0x01000000
+
+#define AR_MAX_CFP_DUR 0x8038
+#define AR_CFP_VAL 0x0000FFFF
+
+#define AR_RX_FILTER 0x803C
+
+#define AR_MCAST_FIL0 0x8040
+#define AR_MCAST_FIL1 0x8044
+
+/*
+ * AR_DIAG_SW - Register which can be used for diagnostics and testing purposes.
+ *
+ * The force RX abort (AR_DIAG_RX_ABORT, bit 25) can be used in conjunction with
+ * RX block (AR_DIAG_RX_DIS, bit 5) to help fast channel change to shut down
+ * receive. The force RX abort bit will kill any frame which is currently being
+ * transferred between the MAC and baseband. The RX block bit (AR_DIAG_RX_DIS)
+ * will prevent any new frames from getting started.
+ */
+#define AR_DIAG_SW 0x8048
+#define AR_DIAG_CACHE_ACK 0x00000001
+#define AR_DIAG_ACK_DIS 0x00000002
+#define AR_DIAG_CTS_DIS 0x00000004
+#define AR_DIAG_ENCRYPT_DIS 0x00000008
+#define AR_DIAG_DECRYPT_DIS 0x00000010
+#define AR_DIAG_RX_DIS 0x00000020 /* RX block */
+#define AR_DIAG_LOOP_BACK 0x00000040
+#define AR_DIAG_CORR_FCS 0x00000080
+#define AR_DIAG_CHAN_INFO 0x00000100
+#define AR_DIAG_SCRAM_SEED 0x0001FE00
+#define AR_DIAG_SCRAM_SEED_S 8
+#define AR_DIAG_FRAME_NV0 0x00020000
+#define AR_DIAG_OBS_PT_SEL1 0x000C0000
+#define AR_DIAG_OBS_PT_SEL1_S 18
+#define AR_DIAG_FORCE_RX_CLEAR 0x00100000 /* force rx_clear high */
+#define AR_DIAG_IGNORE_VIRT_CS 0x00200000
+#define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000
+#define AR_DIAG_EIFS_CTRL_ENA 0x00800000
+#define AR_DIAG_DUAL_CHAIN_INFO 0x01000000
+#define AR_DIAG_RX_ABORT 0x02000000 /* Force RX abort */
+#define AR_DIAG_SATURATE_CYCLE_CNT 0x04000000
+#define AR_DIAG_OBS_PT_SEL2 0x08000000
+#define AR_DIAG_RX_CLEAR_CTL_LOW 0x10000000
+#define AR_DIAG_RX_CLEAR_EXT_LOW 0x20000000
+
+#define AR_TSF_L32 0x804c
+#define AR_TSF_U32 0x8050
+
+#define AR_TST_ADDAC 0x8054
+#define AR_DEF_ANTENNA 0x8058
+
+#define AR_AES_MUTE_MASK0 0x805c
+#define AR_AES_MUTE_MASK0_FC 0x0000FFFF
+#define AR_AES_MUTE_MASK0_QOS 0xFFFF0000
+#define AR_AES_MUTE_MASK0_QOS_S 16
+
+#define AR_AES_MUTE_MASK1 0x8060
+#define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF
+#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000
+#define AR_AES_MUTE_MASK1_FC_MGMT_S 16
+
+#define AR_GATED_CLKS 0x8064
+#define AR_GATED_CLKS_TX 0x00000002
+#define AR_GATED_CLKS_RX 0x00000004
+#define AR_GATED_CLKS_REG 0x00000008
+
+#define AR_OBS_BUS_CTRL 0x8068
+#define AR_OBS_BUS_SEL_1 0x00040000
+#define AR_OBS_BUS_SEL_2 0x00080000
+#define AR_OBS_BUS_SEL_3 0x000C0000
+#define AR_OBS_BUS_SEL_4 0x08040000
+#define AR_OBS_BUS_SEL_5 0x08080000
+
+#define AR_OBS_BUS_1 0x806c
+#define AR_OBS_BUS_1_PCU 0x00000001
+#define AR_OBS_BUS_1_RX_END 0x00000002
+#define AR_OBS_BUS_1_RX_WEP 0x00000004
+#define AR_OBS_BUS_1_RX_BEACON 0x00000008
+#define AR_OBS_BUS_1_RX_FILTER 0x00000010
+#define AR_OBS_BUS_1_TX_HCF 0x00000020
+#define AR_OBS_BUS_1_QUIET_TIME 0x00000040
+#define AR_OBS_BUS_1_CHAN_IDLE 0x00000080
+#define AR_OBS_BUS_1_TX_HOLD 0x00000100
+#define AR_OBS_BUS_1_TX_FRAME 0x00000200
+#define AR_OBS_BUS_1_RX_FRAME 0x00000400
+#define AR_OBS_BUS_1_RX_CLEAR 0x00000800
+#define AR_OBS_BUS_1_WEP_STATE 0x0003F000
+#define AR_OBS_BUS_1_WEP_STATE_S 12
+#define AR_OBS_BUS_1_RX_STATE 0x01F00000
+#define AR_OBS_BUS_1_RX_STATE_S 20
+#define AR_OBS_BUS_1_TX_STATE 0x7E000000
+#define AR_OBS_BUS_1_TX_STATE_S 25
+
+#define AR_LAST_TSTP 0x8080
+#define AR_NAV 0x8084
+#define AR_RTS_OK 0x8088
+#define AR_RTS_FAIL 0x808c
+#define AR_ACK_FAIL 0x8090
+#define AR_FCS_FAIL 0x8094
+#define AR_BEACON_CNT 0x8098
+
+#define AR_SLEEP1 0x80d4
+#define AR_SLEEP1_ASSUME_DTIM 0x00080000
+#define AR_SLEEP1_CAB_TIMEOUT 0xFFE00000
+#define AR_SLEEP1_CAB_TIMEOUT_S 21
+
+#define AR_SLEEP2 0x80d8
+#define AR_SLEEP2_BEACON_TIMEOUT 0xFFE00000
+#define AR_SLEEP2_BEACON_TIMEOUT_S 21
+
+#define AR_TPC 0x80e8
+#define AR_TPC_ACK 0x0000003f
+#define AR_TPC_ACK_S 0x00
+#define AR_TPC_CTS 0x00003f00
+#define AR_TPC_CTS_S 0x08
+#define AR_TPC_CHIRP 0x003f0000
+#define AR_TPC_CHIRP_S 0x16
+
+#define AR_QUIET1 0x80fc
+#define AR_QUIET1_NEXT_QUIET_S 0
+#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff
+#define AR_QUIET1_QUIET_ENABLE 0x00010000
+#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000
+#define AR_QUIET1_QUIET_ACK_CTS_ENABLE_S 17
+#define AR_QUIET2 0x8100
+#define AR_QUIET2_QUIET_PERIOD_S 0
+#define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff
+#define AR_QUIET2_QUIET_DUR_S 16
+#define AR_QUIET2_QUIET_DUR 0xffff0000
+
+#define AR_TSF_PARM 0x8104
+#define AR_TSF_INCREMENT_M 0x000000ff
+#define AR_TSF_INCREMENT_S 0x00
+
+#define AR_QOS_NO_ACK 0x8108
+#define AR_QOS_NO_ACK_TWO_BIT 0x0000000f
+#define AR_QOS_NO_ACK_TWO_BIT_S 0
+#define AR_QOS_NO_ACK_BIT_OFF 0x00000070
+#define AR_QOS_NO_ACK_BIT_OFF_S 4
+#define AR_QOS_NO_ACK_BYTE_OFF 0x00000180
+#define AR_QOS_NO_ACK_BYTE_OFF_S 7
+
+#define AR_PHY_ERR 0x810c
+
+#define AR_PHY_ERR_DCHIRP 0x00000008
+#define AR_PHY_ERR_RADAR 0x00000020
+#define AR_PHY_ERR_OFDM_TIMING 0x00020000
+#define AR_PHY_ERR_CCK_TIMING 0x02000000
+
+#define AR_RXFIFO_CFG 0x8114
+
+
+#define AR_MIC_QOS_CONTROL 0x8118
+#define AR_MIC_QOS_SELECT 0x811c
+
+#define AR_PCU_MISC 0x8120
+#define AR_PCU_FORCE_BSSID_MATCH 0x00000001
+#define AR_PCU_MIC_NEW_LOC_ENA 0x00000004
+#define AR_PCU_TX_ADD_TSF 0x00000008
+#define AR_PCU_CCK_SIFS_MODE 0x00000010
+#define AR_PCU_RX_ANT_UPDT 0x00000800
+#define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000
+#define AR_PCU_MISS_BCN_IN_SLEEP 0x00004000
+#define AR_PCU_BUG_12306_FIX_ENA 0x00020000
+#define AR_PCU_FORCE_QUIET_COLL 0x00040000
+#define AR_PCU_TBTT_PROTECT 0x00200000
+#define AR_PCU_CLEAR_VMF 0x01000000
+#define AR_PCU_CLEAR_BA_VALID 0x04000000
+#define AR_PCU_ALWAYS_PERFORM_KEYSEARCH 0x10000000
+
+#define AR_PCU_BT_ANT_PREVENT_RX 0x00100000
+#define AR_PCU_BT_ANT_PREVENT_RX_S 20
+
+#define AR_FILT_OFDM 0x8124
+#define AR_FILT_OFDM_COUNT 0x00FFFFFF
+
+#define AR_FILT_CCK 0x8128
+#define AR_FILT_CCK_COUNT 0x00FFFFFF
+
+#define AR_PHY_ERR_1 0x812c
+#define AR_PHY_ERR_1_COUNT 0x00FFFFFF
+#define AR_PHY_ERR_MASK_1 0x8130
+
+#define AR_PHY_ERR_2 0x8134
+#define AR_PHY_ERR_2_COUNT 0x00FFFFFF
+#define AR_PHY_ERR_MASK_2 0x8138
+
+#define AR_PHY_COUNTMAX (3 << 22)
+#define AR_MIBCNT_INTRMASK (3 << 22)
+
+#define AR_TSFOOR_THRESHOLD 0x813c
+#define AR_TSFOOR_THRESHOLD_VAL 0x0000FFFF
+
+#define AR_PHY_ERR_EIFS_MASK 0x8144
+
+#define AR_PHY_ERR_3 0x8168
+#define AR_PHY_ERR_3_COUNT 0x00FFFFFF
+#define AR_PHY_ERR_MASK_3 0x816c
+
+#define AR_BT_COEX_MODE 0x8170
+#define AR_BT_TIME_EXTEND 0x000000ff
+#define AR_BT_TIME_EXTEND_S 0
+#define AR_BT_TXSTATE_EXTEND 0x00000100
+#define AR_BT_TXSTATE_EXTEND_S 8
+#define AR_BT_TX_FRAME_EXTEND 0x00000200
+#define AR_BT_TX_FRAME_EXTEND_S 9
+#define AR_BT_MODE 0x00000c00
+#define AR_BT_MODE_S 10
+#define AR_BT_QUIET 0x00001000
+#define AR_BT_QUIET_S 12
+#define AR_BT_QCU_THRESH 0x0001e000
+#define AR_BT_QCU_THRESH_S 13
+#define AR_BT_RX_CLEAR_POLARITY 0x00020000
+#define AR_BT_RX_CLEAR_POLARITY_S 17
+#define AR_BT_PRIORITY_TIME 0x00fc0000
+#define AR_BT_PRIORITY_TIME_S 18
+#define AR_BT_FIRST_SLOT_TIME 0xff000000
+#define AR_BT_FIRST_SLOT_TIME_S 24
+
+#define AR_BT_COEX_WEIGHT 0x8174
+#define AR_BT_COEX_WGHT 0xff55
+#define AR_STOMP_ALL_WLAN_WGHT 0xfcfc
+#define AR_STOMP_LOW_WLAN_WGHT 0xa8a8
+#define AR_STOMP_NONE_WLAN_WGHT 0x0000
+#define AR_BTCOEX_BT_WGHT 0x0000ffff
+#define AR_BTCOEX_BT_WGHT_S 0
+#define AR_BTCOEX_WL_WGHT 0xffff0000
+#define AR_BTCOEX_WL_WGHT_S 16
+
+#define AR_BT_COEX_WL_WEIGHTS0 0x8174
+#define AR_BT_COEX_WL_WEIGHTS1 0x81c4
+
+#define AR_BT_COEX_BT_WEIGHTS0 0x83ac
+#define AR_BT_COEX_BT_WEIGHTS1 0x83b0
+#define AR_BT_COEX_BT_WEIGHTS2 0x83b4
+#define AR_BT_COEX_BT_WEIGHTS3 0x83b8
+
+#define AR9300_BT_WGHT 0xcccc4444
+#define AR9300_STOMP_ALL_WLAN_WGHT0 0xfffffff0
+#define AR9300_STOMP_ALL_WLAN_WGHT1 0xfffffff0
+#define AR9300_STOMP_LOW_WLAN_WGHT0 0x88888880
+#define AR9300_STOMP_LOW_WLAN_WGHT1 0x88888880
+#define AR9300_STOMP_NONE_WLAN_WGHT0 0x00000000
+#define AR9300_STOMP_NONE_WLAN_WGHT1 0x00000000
+
+#define AR_BT_COEX_MODE2 0x817c
+#define AR_BT_BCN_MISS_THRESH 0x000000ff
+#define AR_BT_BCN_MISS_THRESH_S 0
+#define AR_BT_BCN_MISS_CNT 0x0000ff00
+#define AR_BT_BCN_MISS_CNT_S 8
+#define AR_BT_HOLD_RX_CLEAR 0x00010000
+#define AR_BT_HOLD_RX_CLEAR_S 16
+#define AR_BT_DISABLE_BT_ANT 0x00100000
+#define AR_BT_DISABLE_BT_ANT_S 20
+
+#define AR_TXSIFS 0x81d0
+#define AR_TXSIFS_TIME 0x000000FF
+#define AR_TXSIFS_TX_LATENCY 0x00000F00
+#define AR_TXSIFS_TX_LATENCY_S 8
+#define AR_TXSIFS_ACK_SHIFT 0x00007000
+#define AR_TXSIFS_ACK_SHIFT_S 12
+
+#define AR_TXOP_X 0x81ec
+#define AR_TXOP_X_VAL 0x000000FF
+
+
+#define AR_TXOP_0_3 0x81f0
+#define AR_TXOP_4_7 0x81f4
+#define AR_TXOP_8_11 0x81f8
+#define AR_TXOP_12_15 0x81fc
+
+#define AR_NEXT_NDP2_TIMER 0x8180
+#define AR_FIRST_NDP_TIMER 7
+#define AR_NDP2_PERIOD 0x81a0
+#define AR_NDP2_TIMER_MODE 0x81c0
+
+#define AR_GEN_TIMERS(_i) (0x8200 + ((_i) << 2))
+#define AR_NEXT_TBTT_TIMER AR_GEN_TIMERS(0)
+#define AR_NEXT_DMA_BEACON_ALERT AR_GEN_TIMERS(1)
+#define AR_NEXT_SWBA AR_GEN_TIMERS(2)
+#define AR_NEXT_CFP AR_GEN_TIMERS(2)
+#define AR_NEXT_HCF AR_GEN_TIMERS(3)
+#define AR_NEXT_TIM AR_GEN_TIMERS(4)
+#define AR_NEXT_DTIM AR_GEN_TIMERS(5)
+#define AR_NEXT_QUIET_TIMER AR_GEN_TIMERS(6)
+#define AR_NEXT_NDP_TIMER AR_GEN_TIMERS(7)
+
+#define AR_BEACON_PERIOD AR_GEN_TIMERS(8)
+#define AR_DMA_BEACON_PERIOD AR_GEN_TIMERS(9)
+#define AR_SWBA_PERIOD AR_GEN_TIMERS(10)
+#define AR_HCF_PERIOD AR_GEN_TIMERS(11)
+#define AR_TIM_PERIOD AR_GEN_TIMERS(12)
+#define AR_DTIM_PERIOD AR_GEN_TIMERS(13)
+#define AR_QUIET_PERIOD AR_GEN_TIMERS(14)
+#define AR_NDP_PERIOD AR_GEN_TIMERS(15)
+
+#define AR_TIMER_MODE 0x8240
+#define AR_TBTT_TIMER_EN 0x00000001
+#define AR_DBA_TIMER_EN 0x00000002
+#define AR_SWBA_TIMER_EN 0x00000004
+#define AR_HCF_TIMER_EN 0x00000008
+#define AR_TIM_TIMER_EN 0x00000010
+#define AR_DTIM_TIMER_EN 0x00000020
+#define AR_QUIET_TIMER_EN 0x00000040
+#define AR_NDP_TIMER_EN 0x00000080
+#define AR_TIMER_OVERFLOW_INDEX 0x00000700
+#define AR_TIMER_OVERFLOW_INDEX_S 8
+#define AR_TIMER_THRESH 0xFFFFF000
+#define AR_TIMER_THRESH_S 12
+
+#define AR_SLP32_MODE 0x8244
+#define AR_SLP32_HALF_CLK_LATENCY 0x000FFFFF
+#define AR_SLP32_ENA 0x00100000
+#define AR_SLP32_TSF_WRITE_STATUS 0x00200000
+
+#define AR_SLP32_WAKE 0x8248
+#define AR_SLP32_WAKE_XTL_TIME 0x0000FFFF
+
+#define AR_SLP32_INC 0x824c
+#define AR_SLP32_TST_INC 0x000FFFFF
+
+#define AR_SLP_CNT 0x8250
+#define AR_SLP_CYCLE_CNT 0x8254
+
+#define AR_SLP_MIB_CTRL 0x8258
+#define AR_SLP_MIB_CLEAR 0x00000001
+#define AR_SLP_MIB_PENDING 0x00000002
+
+#define AR_MAC_PCU_LOGIC_ANALYZER 0x8264
+#define AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768 0x20000000
+
+
+#define AR_2040_MODE 0x8318
+#define AR_2040_JOINED_RX_CLEAR 0x00000001
+
+
+#define AR_EXTRCCNT 0x8328
+
+#define AR_SELFGEN_MASK 0x832c
+
+#define AR_PCU_TXBUF_CTRL 0x8340
+#define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF
+#define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700
+#define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380
+
+#define AR_PCU_MISC_MODE2 0x8344
+#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002
+#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004
+
+#define AR_PCU_MISC_MODE2_RESERVED 0x00000038
+#define AR_PCU_MISC_MODE2_ADHOC_MCAST_KEYID_ENABLE 0x00000040
+#define AR_PCU_MISC_MODE2_CFP_IGNORE 0x00000080
+#define AR_PCU_MISC_MODE2_MGMT_QOS 0x0000FF00
+#define AR_PCU_MISC_MODE2_MGMT_QOS_S 8
+#define AR_PCU_MISC_MODE2_ENABLE_LOAD_NAV_BEACON_DURATION 0x00010000
+#define AR_PCU_MISC_MODE2_ENABLE_AGGWEP 0x00020000
+#define AR_PCU_MISC_MODE2_HWWAR1 0x00100000
+#define AR_PCU_MISC_MODE2_HWWAR2 0x02000000
+#define AR_PCU_MISC_MODE2_RESERVED2 0xFFFE0000
+
+#define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000
+
+
+#define AR_AES_MUTE_MASK0 0x805c
+#define AR_AES_MUTE_MASK0_FC 0x0000FFFF
+#define AR_AES_MUTE_MASK0_QOS 0xFFFF0000
+#define AR_AES_MUTE_MASK0_QOS_S 16
+
+#define AR_AES_MUTE_MASK1 0x8060
+#define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF
+#define AR_AES_MUTE_MASK1_SEQ_S 0
+#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000
+#define AR_AES_MUTE_MASK1_FC_MGMT_S 16
+
+#define AR_RATE_DURATION_0 0x8700
+#define AR_RATE_DURATION_31 0x87CC
+#define AR_RATE_DURATION_32 0x8780
+#define AR_RATE_DURATION(_n) (AR_RATE_DURATION_0 + ((_n)<<2))
+
+
+#define AR_KEYTABLE_0 0x8800
+#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))
+#define AR_KEY_CACHE_SIZE 128
+#define AR_RSVD_KEYTABLE_ENTRIES 4
+#define AR_KEY_TYPE 0x00000007
+#define AR_KEYTABLE_TYPE_40 0x00000000
+#define AR_KEYTABLE_TYPE_104 0x00000001
+#define AR_KEYTABLE_TYPE_128 0x00000003
+#define AR_KEYTABLE_TYPE_TKIP 0x00000004
+#define AR_KEYTABLE_TYPE_AES 0x00000005
+#define AR_KEYTABLE_TYPE_CCM 0x00000006
+#define AR_KEYTABLE_TYPE_CLR 0x00000007
+#define AR_KEYTABLE_ANT 0x00000008
+#define AR_KEYTABLE_VALID 0x00008000
+#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0)
+#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4)
+#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8)
+#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12)
+#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16)
+#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20)
+#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24)
+#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28)
+
+#define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */
+#define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */
+
+#define AR_AGG_WEP_ENABLE_FIX 0x00000008 /* This allows the use of AR_AGG_WEP_ENABLE */
+#define AR_ADHOC_MCAST_KEYID_ENABLE 0x00000040 /* This bit enables the Multicast search
+ * based on both MAC Address and Key ID.
+ * If bit is 0, then Multicast search is
+ * based on MAC address only.
+ * For Merlin and above only.
+ */
+#define AR_AGG_WEP_ENABLE 0x00020000 /* This field enables AGG_WEP feature,
+ * when it is enable, AGG_WEP would takes
+ * charge of the encryption interface of
+ * pcu_txsm.
+ */
+
+#define AR9300_SM_BASE 0xa200
+#define AR9002_PHY_AGC_CONTROL 0x9860
+#define AR9003_PHY_AGC_CONTROL AR9300_SM_BASE + 0xc4
+#define AR_PHY_AGC_CONTROL (AR_SREV_9300_20_OR_LATER(ah) ? AR9003_PHY_AGC_CONTROL : AR9002_PHY_AGC_CONTROL)
+#define AR_PHY_AGC_CONTROL_CAL 0x00000001 /* do internal calibration */
+#define AR_PHY_AGC_CONTROL_NF 0x00000002 /* do noise-floor calibration */
+#define AR_PHY_AGC_CONTROL_OFFSET_CAL 0x00000800 /* allow offset calibration */
+#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 /* enable noise floor calibration to happen */
+#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 /* allow tx filter calibration */
+#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 /* don't update noise floor automatically */
+#define AR_PHY_AGC_CONTROL_EXT_NF_PWR_MEAS 0x00040000 /* extend noise floor power measurement */
+#define AR_PHY_AGC_CONTROL_CLC_SUCCESS 0x00080000 /* carrier leak calibration done */
+#define AR_PHY_AGC_CONTROL_YCOK_MAX 0x000003c0
+#define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_hw.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_hw.c
new file mode 100644
index 00000000..8e312886
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_hw.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2009 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+
+#include "ath.h"
+#include "reg.h"
+
+#define REG_READ (common->ops->read)
+#define REG_WRITE (common->ops->write)
+
+/**
+ * ath_hw_set_bssid_mask - filter out bssids we listen
+ *
+ * @common: the ath_common struct for the device.
+ *
+ * BSSID masking is a method used by AR5212 and newer hardware to inform PCU
+ * which bits of the interface's MAC address should be looked at when trying
+ * to decide which packets to ACK. In station mode and AP mode with a single
+ * BSS every bit matters since we lock to only one BSS. In AP mode with
+ * multiple BSSes (virtual interfaces) not every bit matters because hw must
+ * accept frames for all BSSes and so we tweak some bits of our mac address
+ * in order to have multiple BSSes.
+ *
+ * NOTE: This is a simple filter and does *not* filter out all
+ * relevant frames. Some frames that are not for us might get ACKed from us
+ * by PCU because they just match the mask.
+ *
+ * When handling multiple BSSes you can get the BSSID mask by computing the
+ * set of ~ ( MAC XOR BSSID ) for all bssids we handle.
+ *
+ * When you do this you are essentially computing the common bits of all your
+ * BSSes. Later it is assumed the hardware will "and" (&) the BSSID mask with
+ * the MAC address to obtain the relevant bits and compare the result with
+ * (frame's BSSID & mask) to see if they match.
+ *
+ * Simple example: on your card you have have two BSSes you have created with
+ * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
+ * There is another BSSID-03 but you are not part of it. For simplicity's sake,
+ * assuming only 4 bits for a mac address and for BSSIDs you can then have:
+ *
+ * \
+ * MAC: 0001 |
+ * BSSID-01: 0100 | --> Belongs to us
+ * BSSID-02: 1001 |
+ * /
+ * -------------------
+ * BSSID-03: 0110 | --> External
+ * -------------------
+ *
+ * Our bssid_mask would then be:
+ *
+ * On loop iteration for BSSID-01:
+ * ~(0001 ^ 0100) -> ~(0101)
+ * -> 1010
+ * bssid_mask = 1010
+ *
+ * On loop iteration for BSSID-02:
+ * bssid_mask &= ~(0001 ^ 1001)
+ * bssid_mask = (1010) & ~(0001 ^ 1001)
+ * bssid_mask = (1010) & ~(1000)
+ * bssid_mask = (1010) & (0111)
+ * bssid_mask = 0010
+ *
+ * A bssid_mask of 0010 means "only pay attention to the second least
+ * significant bit". This is because its the only bit common
+ * amongst the MAC and all BSSIDs we support. To findout what the real
+ * common bit is we can simply "&" the bssid_mask now with any BSSID we have
+ * or our MAC address (we assume the hardware uses the MAC address).
+ *
+ * Now, suppose there's an incoming frame for BSSID-03:
+ *
+ * IFRAME-01: 0110
+ *
+ * An easy eye-inspeciton of this already should tell you that this frame
+ * will not pass our check. This is because the bssid_mask tells the
+ * hardware to only look at the second least significant bit and the
+ * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
+ * as 1, which does not match 0.
+ *
+ * So with IFRAME-01 we *assume* the hardware will do:
+ *
+ * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
+ * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
+ * --> allow = (0010) == 0000 ? 1 : 0;
+ * --> allow = 0
+ *
+ * Lets now test a frame that should work:
+ *
+ * IFRAME-02: 0001 (we should allow)
+ *
+ * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
+ * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0;
+ * --> allow = (0000) == (0000)
+ * --> allow = 1
+ *
+ * Other examples:
+ *
+ * IFRAME-03: 0100 --> allowed
+ * IFRAME-04: 1001 --> allowed
+ * IFRAME-05: 1101 --> allowed but its not for us!!!
+ *
+ */
+void ath_hw_setbssidmask(struct ath_common *common)
+{
+ void *ah = common->ah;
+
+ REG_WRITE(ah, get_unaligned_le32(common->bssidmask), AR_BSSMSKL);
+ REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
+}
+
+
+/**
+ * ath_hw_cycle_counters_update - common function to update cycle counters
+ *
+ * @common: the ath_common struct for the device.
+ *
+ * This function is used to update all cycle counters in one place.
+ * It has to be called while holding common->cc_lock!
+ */
+void ath_hw_cycle_counters_update(struct ath_common *common)
+{
+ u32 cycles, busy, rx, tx;
+ void *ah = common->ah;
+
+ /* freeze */
+ REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC);
+
+ /* read */
+ cycles = REG_READ(ah, AR_CCCNT);
+ busy = REG_READ(ah, AR_RCCNT);
+ rx = REG_READ(ah, AR_RFCNT);
+ tx = REG_READ(ah, AR_TFCNT);
+
+ /* clear */
+ REG_WRITE(ah, 0, AR_CCCNT);
+ REG_WRITE(ah, 0, AR_RFCNT);
+ REG_WRITE(ah, 0, AR_RCCNT);
+ REG_WRITE(ah, 0, AR_TFCNT);
+
+ /* unfreeze */
+ REG_WRITE(ah, 0, AR_MIBC);
+
+ /* update all cycle counters here */
+ common->cc_ani.cycles += cycles;
+ common->cc_ani.rx_busy += busy;
+ common->cc_ani.rx_frame += rx;
+ common->cc_ani.tx_frame += tx;
+
+ common->cc_survey.cycles += cycles;
+ common->cc_survey.rx_busy += busy;
+ common->cc_survey.rx_frame += rx;
+ common->cc_survey.tx_frame += tx;
+}
+
+int32_t ath_hw_get_listen_time(struct ath_common *common)
+{
+ struct ath_cycle_counters *cc = &common->cc_ani;
+ int32_t listen_time;
+
+ listen_time = (cc->cycles - cc->rx_frame - cc->tx_frame) /
+ (common->clockrate * 1000);
+
+ memset(cc, 0, sizeof(*cc));
+
+ return listen_time;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_key.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_key.c
new file mode 100644
index 00000000..d269a45a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_key.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2009 Atheros Communications Inc.
+ * Copyright (c) 2010 Bruno Randolf <br1@einfach.org>
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath.h"
+#include "reg.h"
+
+#define REG_READ (common->ops->read)
+#define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg)
+#define ENABLE_REGWRITE_BUFFER(_ah) \
+ if (common->ops->enable_write_buffer) \
+ common->ops->enable_write_buffer((_ah));
+
+#define REGWRITE_BUFFER_FLUSH(_ah) \
+ if (common->ops->write_flush) \
+ common->ops->write_flush((_ah));
+
+
+#define IEEE80211_WEP_NKID 4 /* number of key ids */
+
+/************************/
+/* Key Cache Management */
+/************************/
+
+int ath_hw_keyreset(struct ath_common *common, u16 entry)
+{
+ u32 keyType;
+ void *ah = common->ah;
+
+ if (entry >= common->keymax) {
+ DBG("ath: keycache entry %d out of range\n", entry);
+ return 0;
+ }
+
+ keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
+ REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
+
+ if (keyType == AR_KEYTABLE_TYPE_TKIP) {
+ u16 micentry = entry + 64;
+
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+ if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+ AR_KEYTABLE_TYPE_CLR);
+ }
+
+ }
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ return 1;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_main.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_main.c
new file mode 100644
index 00000000..85d159a3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_main.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2009 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ipxe/io.h>
+
+#include "ath.h"
+
+struct io_buffer *ath_rxbuf_alloc(struct ath_common *common,
+ u32 len,
+ u32 *iob_addr)
+{
+ struct io_buffer *iob;
+ u32 off;
+
+ /*
+ * Cache-line-align. This is important (for the
+ * 5210 at least) as not doing so causes bogus data
+ * in rx'd frames.
+ */
+
+ /* Note: the kernel can allocate a value greater than
+ * what we ask it to give us. We really only need 4 KB as that
+ * is this hardware supports and in fact we need at least 3849
+ * as that is the MAX AMSDU size this hardware supports.
+ * Unfortunately this means we may get 8 KB here from the
+ * kernel... and that is actually what is observed on some
+ * systems :( */
+ iob = alloc_iob(len + common->cachelsz - 1);
+ if (iob != NULL) {
+ *iob_addr = virt_to_bus(iob->data);
+ off = ((unsigned long) iob->data) % common->cachelsz;
+ if (off != 0)
+ {
+ iob_reserve(iob, common->cachelsz - off);
+ *iob_addr += common->cachelsz - off;
+ }
+ } else {
+ DBG("ath: iobuffer alloc of size %d failed\n", len);
+ return NULL;
+ }
+
+ return iob;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_regd.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_regd.c
new file mode 100644
index 00000000..190b1f9f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/ath_regd.c
@@ -0,0 +1,602 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "regd.h"
+#include "regd_common.h"
+
+/*
+ * This is a set of common rules used by our world regulatory domains.
+ * We have 12 world regulatory domains. To save space we consolidate
+ * the regulatory domains in 5 structures by frequency and change
+ * the flags on our reg_notifier() on a case by case basis.
+ */
+
+/* Only these channels all allow active scan on all world regulatory domains */
+#define ATH9K_2GHZ_CH01_11 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
+
+/* We enable active scan on these a case by case basis by regulatory domain */
+#define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\
+ NL80211_RRF_PASSIVE_SCAN)
+#define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\
+ NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
+
+/* We allow IBSS on these on a case by case basis by regulatory domain */
+#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 40, 0, 30,\
+ NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 40, 0, 30,\
+ NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 40, 0, 30,\
+ NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+
+#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \
+ ATH9K_2GHZ_CH12_13, \
+ ATH9K_2GHZ_CH14
+
+#define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \
+ ATH9K_5GHZ_5470_5850
+
+/* This one skips what we call "mid band" */
+#define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \
+ ATH9K_5GHZ_5725_5850
+
+///* Can be used for:
+// * 0x60, 0x61, 0x62 */
+//static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
+// .n_reg_rules = 5,
+// .alpha2 = "99",
+// .reg_rules = {
+// ATH9K_2GHZ_ALL,
+// ATH9K_5GHZ_ALL,
+// }
+//};
+//
+///* Can be used by 0x63 and 0x65 */
+//static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
+// .n_reg_rules = 4,
+// .alpha2 = "99",
+// .reg_rules = {
+// ATH9K_2GHZ_CH01_11,
+// ATH9K_2GHZ_CH12_13,
+// ATH9K_5GHZ_NO_MIDBAND,
+// }
+//};
+//
+///* Can be used by 0x64 only */
+//static const struct ieee80211_regdomain ath_world_regdom_64 = {
+// .n_reg_rules = 3,
+// .alpha2 = "99",
+// .reg_rules = {
+// ATH9K_2GHZ_CH01_11,
+// ATH9K_5GHZ_NO_MIDBAND,
+// }
+//};
+//
+///* Can be used by 0x66 and 0x69 */
+//static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
+// .n_reg_rules = 3,
+// .alpha2 = "99",
+// .reg_rules = {
+// ATH9K_2GHZ_CH01_11,
+// ATH9K_5GHZ_ALL,
+// }
+//};
+//
+///* Can be used by 0x67, 0x68, 0x6A and 0x6C */
+//static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
+// .n_reg_rules = 4,
+// .alpha2 = "99",
+// .reg_rules = {
+// ATH9K_2GHZ_CH01_11,
+// ATH9K_2GHZ_CH12_13,
+// ATH9K_5GHZ_ALL,
+// }
+//};
+//
+//static inline int is_wwr_sku(u16 regd)
+//{
+// return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) &&
+// (((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) ||
+// (regd == WORLD));
+//}
+//
+//static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
+//{
+// return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
+//}
+//
+//int ath_is_world_regd(struct ath_regulatory *reg)
+//{
+// return is_wwr_sku(ath_regd_get_eepromRD(reg));
+//}
+//
+//static const struct ieee80211_regdomain *ath_default_world_regdomain(void)
+//{
+// /* this is the most restrictive */
+// return &ath_world_regdom_64;
+//}
+//
+//static const struct
+//ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)
+//{
+// switch (reg->regpair->regDmnEnum) {
+// case 0x60:
+// case 0x61:
+// case 0x62:
+// return &ath_world_regdom_60_61_62;
+// case 0x63:
+// case 0x65:
+// return &ath_world_regdom_63_65;
+// case 0x64:
+// return &ath_world_regdom_64;
+// case 0x66:
+// case 0x69:
+// return &ath_world_regdom_66_69;
+// case 0x67:
+// case 0x68:
+// case 0x6A:
+// case 0x6C:
+// return &ath_world_regdom_67_68_6A_6C;
+// default:
+// WARN_ON(1);
+// return ath_default_world_regdomain();
+// }
+//}
+//
+//int ath_is_49ghz_allowed(u16 regdomain)
+//{
+// /* possibly more */
+// return regdomain == MKK9_MKKC;
+//}
+//
+///* Frequency is one where radar detection is required */
+//static int ath_is_radar_freq(u16 center_freq)
+//{
+// return (center_freq >= 5260 && center_freq <= 5700);
+//}
+//
+///*
+// * N.B: These exception rules do not apply radar freqs.
+// *
+// * - We enable adhoc (or beaconing) if allowed by 11d
+// * - We enable active scan if the channel is allowed by 11d
+// * - If no country IE has been processed and a we determine we have
+// * received a beacon on a channel we can enable active scan and
+// * adhoc (or beaconing).
+// */
+//static void
+//ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
+// enum nl80211_reg_initiator initiator)
+//{
+// int band;
+// struct ieee80211_supported_band *sband;
+// const struct ieee80211_reg_rule *reg_rule;
+// struct net80211_channel *ch;
+// unsigned int i;
+// u32 bandwidth = 0;
+// int r;
+//
+// for (band = 0; band < NET80211_NR_BANDS; band++) {
+//
+// if (!wiphy->bands[band])
+// continue;
+//
+// sband = wiphy->bands[band];
+//
+// for (i = 0; i < sband->n_channels; i++) {
+//
+// ch = &sband->channels[i];
+//
+// if (ath_is_radar_freq(ch->center_freq) ||
+// (ch->flags & IEEE80211_CHAN_RADAR))
+// continue;
+//
+// if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
+// r = freq_reg_info(wiphy,
+// ch->center_freq,
+// bandwidth,
+// &reg_rule);
+// if (r)
+// continue;
+// /*
+// * If 11d had a rule for this channel ensure
+// * we enable adhoc/beaconing if it allows us to
+// * use it. Note that we would have disabled it
+// * by applying our static world regdomain by
+// * default during init, prior to calling our
+// * regulatory_hint().
+// */
+// if (!(reg_rule->flags &
+// NL80211_RRF_NO_IBSS))
+// ch->flags &=
+// ~IEEE80211_CHAN_NO_IBSS;
+// if (!(reg_rule->flags &
+// NL80211_RRF_PASSIVE_SCAN))
+// ch->flags &=
+// ~IEEE80211_CHAN_PASSIVE_SCAN;
+// } else {
+// if (ch->beacon_found)
+// ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
+// IEEE80211_CHAN_PASSIVE_SCAN);
+// }
+// }
+// }
+//
+//}
+//
+///* Allows active scan scan on Ch 12 and 13 */
+//static void
+//ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
+// enum nl80211_reg_initiator initiator)
+//{
+// struct ieee80211_supported_band *sband;
+// struct net80211_channel *ch;
+// const struct ieee80211_reg_rule *reg_rule;
+// u32 bandwidth = 0;
+// int r;
+//
+// sband = wiphy->bands[NET80211_BAND_2GHZ];
+//
+// /*
+// * If no country IE has been received always enable active scan
+// * on these channels. This is only done for specific regulatory SKUs
+// */
+// if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
+// ch = &sband->channels[11]; /* CH 12 */
+// if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+// ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+// ch = &sband->channels[12]; /* CH 13 */
+// if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+// ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+// return;
+// }
+//
+// /*
+// * If a country IE has been received check its rule for this
+// * channel first before enabling active scan. The passive scan
+// * would have been enforced by the initial processing of our
+// * custom regulatory domain.
+// */
+//
+// ch = &sband->channels[11]; /* CH 12 */
+// r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
+// if (!r) {
+// if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
+// if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+// ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+// }
+//
+// ch = &sband->channels[12]; /* CH 13 */
+// r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
+// if (!r) {
+// if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
+// if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+// ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+// }
+//}
+//
+///* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */
+//static void ath_reg_apply_radar_flags(struct wiphy *wiphy)
+//{
+// struct ieee80211_supported_band *sband;
+// struct net80211_channel *ch;
+// unsigned int i;
+//
+// if (!wiphy->bands[NET80211_BAND_5GHZ])
+// return;
+//
+// sband = wiphy->bands[NET80211_BAND_5GHZ];
+//
+// for (i = 0; i < sband->n_channels; i++) {
+// ch = &sband->channels[i];
+// if (!ath_is_radar_freq(ch->center_freq))
+// continue;
+// /* We always enable radar detection/DFS on this
+// * frequency range. Additionally we also apply on
+// * this frequency range:
+// * - If STA mode does not yet have DFS supports disable
+// * active scanning
+// * - If adhoc mode does not support DFS yet then
+// * disable adhoc in the frequency.
+// * - If AP mode does not yet support radar detection/DFS
+// * do not allow AP mode
+// */
+// if (!(ch->flags & IEEE80211_CHAN_DISABLED))
+// ch->flags |= IEEE80211_CHAN_RADAR |
+// IEEE80211_CHAN_NO_IBSS |
+// IEEE80211_CHAN_PASSIVE_SCAN;
+// }
+//}
+//
+//static void ath_reg_apply_world_flags(struct wiphy *wiphy,
+// enum nl80211_reg_initiator initiator,
+// struct ath_regulatory *reg)
+//{
+// switch (reg->regpair->regDmnEnum) {
+// case 0x60:
+// case 0x63:
+// case 0x66:
+// case 0x67:
+// case 0x6C:
+// ath_reg_apply_beaconing_flags(wiphy, initiator);
+// break;
+// case 0x68:
+// ath_reg_apply_beaconing_flags(wiphy, initiator);
+// ath_reg_apply_active_scan_flags(wiphy, initiator);
+// break;
+// }
+//}
+//
+//int ath_reg_notifier_apply(struct wiphy *wiphy,
+// struct regulatory_request *request,
+// struct ath_regulatory *reg)
+//{
+// /* We always apply this */
+// ath_reg_apply_radar_flags(wiphy);
+//
+// /*
+// * This would happen when we have sent a custom regulatory request
+// * a world regulatory domain and the scheduler hasn't yet processed
+// * any pending requests in the queue.
+// */
+// if (!request)
+// return 0;
+//
+// switch (request->initiator) {
+// case NL80211_REGDOM_SET_BY_DRIVER:
+// case NL80211_REGDOM_SET_BY_CORE:
+// case NL80211_REGDOM_SET_BY_USER:
+// break;
+// case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+// if (ath_is_world_regd(reg))
+// ath_reg_apply_world_flags(wiphy, request->initiator,
+// reg);
+// break;
+// }
+//
+// return 0;
+//}
+//
+//static int ath_regd_is_eeprom_valid(struct ath_regulatory *reg)
+//{
+// u16 rd = ath_regd_get_eepromRD(reg);
+// int i;
+//
+// if (rd & COUNTRY_ERD_FLAG) {
+// /* EEPROM value is a country code */
+// u16 cc = rd & ~COUNTRY_ERD_FLAG;
+// DBG2(
+// "ath: EEPROM indicates we should expect "
+// "a country code\n");
+// for (i = 0; i < ARRAY_SIZE(allCountries); i++)
+// if (allCountries[i].countryCode == cc)
+// return 1;
+// } else {
+// /* EEPROM value is a regpair value */
+// if (rd != CTRY_DEFAULT)
+// DBG2("ath: EEPROM indicates we "
+// "should expect a direct regpair map\n");
+// for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
+// if (regDomainPairs[i].regDmnEnum == rd)
+// return 1;
+// }
+// DBG(
+// "ath: invalid regulatory domain/country code 0x%x\n", rd);
+// return 0;
+//}
+//
+///* EEPROM country code to regpair mapping */
+//static struct country_code_to_enum_rd*
+//ath_regd_find_country(u16 countryCode)
+//{
+// int i;
+//
+// for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
+// if (allCountries[i].countryCode == countryCode)
+// return &allCountries[i];
+// }
+// return NULL;
+//}
+//
+///* EEPROM rd code to regpair mapping */
+//static struct country_code_to_enum_rd*
+//ath_regd_find_country_by_rd(int regdmn)
+//{
+// int i;
+//
+// for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
+// if (allCountries[i].regDmnEnum == regdmn)
+// return &allCountries[i];
+// }
+// return NULL;
+//}
+//
+///* Returns the map of the EEPROM set RD to a country code */
+//static u16 ath_regd_get_default_country(u16 rd)
+//{
+// if (rd & COUNTRY_ERD_FLAG) {
+// struct country_code_to_enum_rd *country = NULL;
+// u16 cc = rd & ~COUNTRY_ERD_FLAG;
+//
+// country = ath_regd_find_country(cc);
+// if (country != NULL)
+// return cc;
+// }
+//
+// return CTRY_DEFAULT;
+//}
+//
+//static struct reg_dmn_pair_mapping*
+//ath_get_regpair(int regdmn)
+//{
+// int i;
+//
+// if (regdmn == NO_ENUMRD)
+// return NULL;
+// for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
+// if (regDomainPairs[i].regDmnEnum == regdmn)
+// return &regDomainPairs[i];
+// }
+// return NULL;
+//}
+//
+//static int
+//ath_regd_init_wiphy(struct ath_regulatory *reg,
+// struct wiphy *wiphy,
+// int (*reg_notifier)(struct wiphy *wiphy,
+// struct regulatory_request *request))
+//{
+// const struct ieee80211_regdomain *regd;
+//
+// wiphy->reg_notifier = reg_notifier;
+// wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
+//
+// if (ath_is_world_regd(reg)) {
+// /*
+// * Anything applied here (prior to wiphy registration) gets
+// * saved on the wiphy orig_* parameters
+// */
+// regd = ath_world_regdomain(reg);
+// wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+// } else {
+// /*
+// * This gets applied in the case of the absence of CRDA,
+// * it's our own custom world regulatory domain, similar to
+// * cfg80211's but we enable passive scanning.
+// */
+// regd = ath_default_world_regdomain();
+// }
+// wiphy_apply_custom_regulatory(wiphy, regd);
+// ath_reg_apply_radar_flags(wiphy);
+// ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
+// return 0;
+//}
+//
+///*
+// * Some users have reported their EEPROM programmed with
+// * 0x8000 set, this is not a supported regulatory domain
+// * but since we have more than one user with it we need
+// * a solution for them. We default to 0x64, which is the
+// * default Atheros world regulatory domain.
+// */
+//static void ath_regd_sanitize(struct ath_regulatory *reg)
+//{
+// if (reg->current_rd != COUNTRY_ERD_FLAG)
+// return;
+// DBG2("ath: EEPROM regdomain sanitized\n");
+// reg->current_rd = 0x64;
+//}
+//
+//int
+//ath_regd_init(struct ath_regulatory *reg,
+// struct wiphy *wiphy,
+// int (*reg_notifier)(struct wiphy *wiphy,
+// struct regulatory_request *request))
+//{
+// struct country_code_to_enum_rd *country = NULL;
+// u16 regdmn;
+//
+// if (!reg)
+// return -EINVAL;
+//
+// ath_regd_sanitize(reg);
+//
+// DBG2("ath: EEPROM regdomain: 0x%0x\n", reg->current_rd);
+//
+// if (!ath_regd_is_eeprom_valid(reg)) {
+// DBG("ath: Invalid EEPROM contents\n");
+// return -EINVAL;
+// }
+//
+// regdmn = ath_regd_get_eepromRD(reg);
+// reg->country_code = ath_regd_get_default_country(regdmn);
+//
+// if (reg->country_code == CTRY_DEFAULT &&
+// regdmn == CTRY_DEFAULT) {
+// DBG2("ath: EEPROM indicates default "
+// "country code should be used\n");
+// reg->country_code = CTRY_UNITED_STATES;
+// }
+//
+// if (reg->country_code == CTRY_DEFAULT) {
+// country = NULL;
+// } else {
+// DBG2("ath: doing EEPROM country->regdmn "
+// "map search\n");
+// country = ath_regd_find_country(reg->country_code);
+// if (country == NULL) {
+// DBG(
+// "ath: no valid country maps found for "
+// "country code: 0x%0x\n",
+// reg->country_code);
+// return -EINVAL;
+// } else {
+// regdmn = country->regDmnEnum;
+// DBG2("ath: country maps to "
+// "regdmn code: 0x%0x\n",
+// regdmn);
+// }
+// }
+//
+// reg->regpair = ath_get_regpair(regdmn);
+//
+// if (!reg->regpair) {
+// DBG("ath: "
+// "No regulatory domain pair found, cannot continue\n");
+// return -EINVAL;
+// }
+//
+// if (!country)
+// country = ath_regd_find_country_by_rd(regdmn);
+//
+// if (country) {
+// reg->alpha2[0] = country->isoName[0];
+// reg->alpha2[1] = country->isoName[1];
+// } else {
+// reg->alpha2[0] = '0';
+// reg->alpha2[1] = '0';
+// }
+//
+// DBG2("ath: Country alpha2 being used: %c%c\n",
+// reg->alpha2[0], reg->alpha2[1]);
+// DBG2("ath: Regpair used: 0x%0x\n",
+// reg->regpair->regDmnEnum);
+//
+// ath_regd_init_wiphy(reg, wiphy, reg_notifier);
+// return 0;
+//}
+
+u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
+ int band)
+{
+ /* TODO Cottsay: reg */
+// if (!reg->regpair ||
+// (reg->country_code == CTRY_DEFAULT &&
+// is_wwr_sku(ath_regd_get_eepromRD(reg)))) {
+// return SD_NO_CTL;
+// }
+
+ switch (band) {
+ case NET80211_BAND_2GHZ:
+ return reg->regpair->reg_2ghz_ctl;
+ case NET80211_BAND_5GHZ:
+ return reg->regpair->reg_5ghz_ctl;
+ default:
+ return NO_CTL;
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/reg.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/reg.h
new file mode 100644
index 00000000..484a8f1c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/reg.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ATH_REGISTERS_H
+#define ATH_REGISTERS_H
+
+#define AR_MIBC 0x0040
+#define AR_MIBC_COW 0x00000001
+#define AR_MIBC_FMC 0x00000002
+#define AR_MIBC_CMC 0x00000004
+#define AR_MIBC_MCS 0x00000008
+
+/*
+ * BSSID mask registers. See ath_hw_set_bssid_mask()
+ * for detailed documentation about these registers.
+ */
+#define AR_BSSMSKL 0x80e0
+#define AR_BSSMSKU 0x80e4
+
+#define AR_TFCNT 0x80ec
+#define AR_RFCNT 0x80f0
+#define AR_RCCNT 0x80f4
+#define AR_CCCNT 0x80f8
+
+#define AR_KEYTABLE_0 0x8800
+#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))
+#define AR_KEY_CACHE_SIZE 128
+#define AR_RSVD_KEYTABLE_ENTRIES 4
+#define AR_KEY_TYPE 0x00000007
+#define AR_KEYTABLE_TYPE_40 0x00000000
+#define AR_KEYTABLE_TYPE_104 0x00000001
+#define AR_KEYTABLE_TYPE_128 0x00000003
+#define AR_KEYTABLE_TYPE_TKIP 0x00000004
+#define AR_KEYTABLE_TYPE_AES 0x00000005
+#define AR_KEYTABLE_TYPE_CCM 0x00000006
+#define AR_KEYTABLE_TYPE_CLR 0x00000007
+#define AR_KEYTABLE_ANT 0x00000008
+#define AR_KEYTABLE_VALID 0x00008000
+#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0)
+#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4)
+#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8)
+#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12)
+#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16)
+#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20)
+#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24)
+#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28)
+
+#endif /* ATH_REGISTERS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/regd.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/regd.h
new file mode 100644
index 00000000..6954c5f3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/regd.h
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef REGD_H
+#define REGD_H
+
+#include "ath.h"
+
+enum ctl_group {
+ CTL_FCC = 0x10,
+ CTL_MKK = 0x40,
+ CTL_ETSI = 0x30,
+};
+
+#define NO_CTL 0xff
+#define SD_NO_CTL 0xE0
+#define NO_CTL 0xff
+#define CTL_11A 0
+#define CTL_11B 1
+#define CTL_11G 2
+#define CTL_2GHT20 5
+#define CTL_5GHT20 6
+#define CTL_2GHT40 7
+#define CTL_5GHT40 8
+
+#define CTRY_DEBUG 0x1ff
+#define CTRY_DEFAULT 0
+
+#define COUNTRY_ERD_FLAG 0x8000
+#define WORLDWIDE_ROAMING_FLAG 0x4000
+
+#define MULTI_DOMAIN_MASK 0xFF00
+
+#define WORLD_SKU_MASK 0x00F0
+#define WORLD_SKU_PREFIX 0x0060
+
+#define CHANNEL_HALF_BW 10
+#define CHANNEL_QUARTER_BW 5
+
+struct country_code_to_enum_rd {
+ u16 countryCode;
+ u16 regDmnEnum;
+ const char *isoName;
+};
+
+enum CountryCode {
+ CTRY_ALBANIA = 8,
+ CTRY_ALGERIA = 12,
+ CTRY_ARGENTINA = 32,
+ CTRY_ARMENIA = 51,
+ CTRY_ARUBA = 533,
+ CTRY_AUSTRALIA = 36,
+ CTRY_AUSTRIA = 40,
+ CTRY_AZERBAIJAN = 31,
+ CTRY_BAHRAIN = 48,
+ CTRY_BANGLADESH = 50,
+ CTRY_BARBADOS = 52,
+ CTRY_BELARUS = 112,
+ CTRY_BELGIUM = 56,
+ CTRY_BELIZE = 84,
+ CTRY_BOLIVIA = 68,
+ CTRY_BOSNIA_HERZ = 70,
+ CTRY_BRAZIL = 76,
+ CTRY_BRUNEI_DARUSSALAM = 96,
+ CTRY_BULGARIA = 100,
+ CTRY_CAMBODIA = 116,
+ CTRY_CANADA = 124,
+ CTRY_CHILE = 152,
+ CTRY_CHINA = 156,
+ CTRY_COLOMBIA = 170,
+ CTRY_COSTA_RICA = 188,
+ CTRY_CROATIA = 191,
+ CTRY_CYPRUS = 196,
+ CTRY_CZECH = 203,
+ CTRY_DENMARK = 208,
+ CTRY_DOMINICAN_REPUBLIC = 214,
+ CTRY_ECUADOR = 218,
+ CTRY_EGYPT = 818,
+ CTRY_EL_SALVADOR = 222,
+ CTRY_ESTONIA = 233,
+ CTRY_FAEROE_ISLANDS = 234,
+ CTRY_FINLAND = 246,
+ CTRY_FRANCE = 250,
+ CTRY_GEORGIA = 268,
+ CTRY_GERMANY = 276,
+ CTRY_GREECE = 300,
+ CTRY_GREENLAND = 304,
+ CTRY_GRENEDA = 308,
+ CTRY_GUAM = 316,
+ CTRY_GUATEMALA = 320,
+ CTRY_HAITI = 332,
+ CTRY_HONDURAS = 340,
+ CTRY_HONG_KONG = 344,
+ CTRY_HUNGARY = 348,
+ CTRY_ICELAND = 352,
+ CTRY_INDIA = 356,
+ CTRY_INDONESIA = 360,
+ CTRY_IRAN = 364,
+ CTRY_IRAQ = 368,
+ CTRY_IRELAND = 372,
+ CTRY_ISRAEL = 376,
+ CTRY_ITALY = 380,
+ CTRY_JAMAICA = 388,
+ CTRY_JAPAN = 392,
+ CTRY_JORDAN = 400,
+ CTRY_KAZAKHSTAN = 398,
+ CTRY_KENYA = 404,
+ CTRY_KOREA_NORTH = 408,
+ CTRY_KOREA_ROC = 410,
+ CTRY_KOREA_ROC2 = 411,
+ CTRY_KOREA_ROC3 = 412,
+ CTRY_KUWAIT = 414,
+ CTRY_LATVIA = 428,
+ CTRY_LEBANON = 422,
+ CTRY_LIBYA = 434,
+ CTRY_LIECHTENSTEIN = 438,
+ CTRY_LITHUANIA = 440,
+ CTRY_LUXEMBOURG = 442,
+ CTRY_MACAU = 446,
+ CTRY_MACEDONIA = 807,
+ CTRY_MALAYSIA = 458,
+ CTRY_MALTA = 470,
+ CTRY_MEXICO = 484,
+ CTRY_MONACO = 492,
+ CTRY_MOROCCO = 504,
+ CTRY_NEPAL = 524,
+ CTRY_NETHERLANDS = 528,
+ CTRY_NETHERLANDS_ANTILLES = 530,
+ CTRY_NEW_ZEALAND = 554,
+ CTRY_NICARAGUA = 558,
+ CTRY_NORWAY = 578,
+ CTRY_OMAN = 512,
+ CTRY_PAKISTAN = 586,
+ CTRY_PANAMA = 591,
+ CTRY_PAPUA_NEW_GUINEA = 598,
+ CTRY_PARAGUAY = 600,
+ CTRY_PERU = 604,
+ CTRY_PHILIPPINES = 608,
+ CTRY_POLAND = 616,
+ CTRY_PORTUGAL = 620,
+ CTRY_PUERTO_RICO = 630,
+ CTRY_QATAR = 634,
+ CTRY_ROMANIA = 642,
+ CTRY_RUSSIA = 643,
+ CTRY_SAUDI_ARABIA = 682,
+ CTRY_SERBIA_MONTENEGRO = 891,
+ CTRY_SINGAPORE = 702,
+ CTRY_SLOVAKIA = 703,
+ CTRY_SLOVENIA = 705,
+ CTRY_SOUTH_AFRICA = 710,
+ CTRY_SPAIN = 724,
+ CTRY_SRI_LANKA = 144,
+ CTRY_SWEDEN = 752,
+ CTRY_SWITZERLAND = 756,
+ CTRY_SYRIA = 760,
+ CTRY_TAIWAN = 158,
+ CTRY_THAILAND = 764,
+ CTRY_TRINIDAD_Y_TOBAGO = 780,
+ CTRY_TUNISIA = 788,
+ CTRY_TURKEY = 792,
+ CTRY_UAE = 784,
+ CTRY_UKRAINE = 804,
+ CTRY_UNITED_KINGDOM = 826,
+ CTRY_UNITED_STATES = 840,
+ CTRY_UNITED_STATES_FCC49 = 842,
+ CTRY_URUGUAY = 858,
+ CTRY_UZBEKISTAN = 860,
+ CTRY_VENEZUELA = 862,
+ CTRY_VIET_NAM = 704,
+ CTRY_YEMEN = 887,
+ CTRY_ZIMBABWE = 716,
+ CTRY_JAPAN1 = 393,
+ CTRY_JAPAN2 = 394,
+ CTRY_JAPAN3 = 395,
+ CTRY_JAPAN4 = 396,
+ CTRY_JAPAN5 = 397,
+ CTRY_JAPAN6 = 4006,
+ CTRY_JAPAN7 = 4007,
+ CTRY_JAPAN8 = 4008,
+ CTRY_JAPAN9 = 4009,
+ CTRY_JAPAN10 = 4010,
+ CTRY_JAPAN11 = 4011,
+ CTRY_JAPAN12 = 4012,
+ CTRY_JAPAN13 = 4013,
+ CTRY_JAPAN14 = 4014,
+ CTRY_JAPAN15 = 4015,
+ CTRY_JAPAN16 = 4016,
+ CTRY_JAPAN17 = 4017,
+ CTRY_JAPAN18 = 4018,
+ CTRY_JAPAN19 = 4019,
+ CTRY_JAPAN20 = 4020,
+ CTRY_JAPAN21 = 4021,
+ CTRY_JAPAN22 = 4022,
+ CTRY_JAPAN23 = 4023,
+ CTRY_JAPAN24 = 4024,
+ CTRY_JAPAN25 = 4025,
+ CTRY_JAPAN26 = 4026,
+ CTRY_JAPAN27 = 4027,
+ CTRY_JAPAN28 = 4028,
+ CTRY_JAPAN29 = 4029,
+ CTRY_JAPAN30 = 4030,
+ CTRY_JAPAN31 = 4031,
+ CTRY_JAPAN32 = 4032,
+ CTRY_JAPAN33 = 4033,
+ CTRY_JAPAN34 = 4034,
+ CTRY_JAPAN35 = 4035,
+ CTRY_JAPAN36 = 4036,
+ CTRY_JAPAN37 = 4037,
+ CTRY_JAPAN38 = 4038,
+ CTRY_JAPAN39 = 4039,
+ CTRY_JAPAN40 = 4040,
+ CTRY_JAPAN41 = 4041,
+ CTRY_JAPAN42 = 4042,
+ CTRY_JAPAN43 = 4043,
+ CTRY_JAPAN44 = 4044,
+ CTRY_JAPAN45 = 4045,
+ CTRY_JAPAN46 = 4046,
+ CTRY_JAPAN47 = 4047,
+ CTRY_JAPAN48 = 4048,
+ CTRY_JAPAN49 = 4049,
+ CTRY_JAPAN50 = 4050,
+ CTRY_JAPAN51 = 4051,
+ CTRY_JAPAN52 = 4052,
+ CTRY_JAPAN53 = 4053,
+ CTRY_JAPAN54 = 4054,
+ CTRY_JAPAN55 = 4055,
+ CTRY_JAPAN56 = 4056,
+ CTRY_JAPAN57 = 4057,
+ CTRY_JAPAN58 = 4058,
+ CTRY_JAPAN59 = 4059,
+ CTRY_AUSTRALIA2 = 5000,
+ CTRY_CANADA2 = 5001,
+ CTRY_BELGIUM2 = 5002
+};
+
+int ath_is_world_regd(struct ath_regulatory *reg);
+int ath_is_49ghz_allowed(u16 redomain);
+//int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy,
+// int (*reg_notifier)(struct wiphy *wiphy,
+// struct regulatory_request *request));
+u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
+ int band);
+//int ath_reg_notifier_apply(struct wiphy *wiphy,
+// struct regulatory_request *request,
+// struct ath_regulatory *reg);
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/regd_common.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/regd_common.h
new file mode 100644
index 00000000..ee1ac3f4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ath/regd_common.h
@@ -0,0 +1,481 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
+ * Original from Linux kernel 3.0.1
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef REGD_COMMON_H
+#define REGD_COMMON_H
+
+enum EnumRd {
+ NO_ENUMRD = 0x00,
+ NULL1_WORLD = 0x03,
+ NULL1_ETSIB = 0x07,
+ NULL1_ETSIC = 0x08,
+ FCC1_FCCA = 0x10,
+ FCC1_WORLD = 0x11,
+ FCC4_FCCA = 0x12,
+ FCC5_FCCA = 0x13,
+ FCC6_FCCA = 0x14,
+
+ FCC2_FCCA = 0x20,
+ FCC2_WORLD = 0x21,
+ FCC2_ETSIC = 0x22,
+ FCC6_WORLD = 0x23,
+ FRANCE_RES = 0x31,
+ FCC3_FCCA = 0x3A,
+ FCC3_WORLD = 0x3B,
+
+ ETSI1_WORLD = 0x37,
+ ETSI3_ETSIA = 0x32,
+ ETSI2_WORLD = 0x35,
+ ETSI3_WORLD = 0x36,
+ ETSI4_WORLD = 0x30,
+ ETSI4_ETSIC = 0x38,
+ ETSI5_WORLD = 0x39,
+ ETSI6_WORLD = 0x34,
+ ETSI_RESERVED = 0x33,
+
+ MKK1_MKKA = 0x40,
+ MKK1_MKKB = 0x41,
+ APL4_WORLD = 0x42,
+ MKK2_MKKA = 0x43,
+ APL_RESERVED = 0x44,
+ APL2_WORLD = 0x45,
+ APL2_APLC = 0x46,
+ APL3_WORLD = 0x47,
+ MKK1_FCCA = 0x48,
+ APL2_APLD = 0x49,
+ MKK1_MKKA1 = 0x4A,
+ MKK1_MKKA2 = 0x4B,
+ MKK1_MKKC = 0x4C,
+
+ APL3_FCCA = 0x50,
+ APL1_WORLD = 0x52,
+ APL1_FCCA = 0x53,
+ APL1_APLA = 0x54,
+ APL1_ETSIC = 0x55,
+ APL2_ETSIC = 0x56,
+ APL5_WORLD = 0x58,
+ APL6_WORLD = 0x5B,
+ APL7_FCCA = 0x5C,
+ APL8_WORLD = 0x5D,
+ APL9_WORLD = 0x5E,
+
+ WOR0_WORLD = 0x60,
+ WOR1_WORLD = 0x61,
+ WOR2_WORLD = 0x62,
+ WOR3_WORLD = 0x63,
+ WOR4_WORLD = 0x64,
+ WOR5_ETSIC = 0x65,
+
+ WOR01_WORLD = 0x66,
+ WOR02_WORLD = 0x67,
+ EU1_WORLD = 0x68,
+
+ WOR9_WORLD = 0x69,
+ WORA_WORLD = 0x6A,
+ WORB_WORLD = 0x6B,
+ WORC_WORLD = 0x6C,
+
+ MKK3_MKKB = 0x80,
+ MKK3_MKKA2 = 0x81,
+ MKK3_MKKC = 0x82,
+
+ MKK4_MKKB = 0x83,
+ MKK4_MKKA2 = 0x84,
+ MKK4_MKKC = 0x85,
+
+ MKK5_MKKB = 0x86,
+ MKK5_MKKA2 = 0x87,
+ MKK5_MKKC = 0x88,
+
+ MKK6_MKKB = 0x89,
+ MKK6_MKKA2 = 0x8A,
+ MKK6_MKKC = 0x8B,
+
+ MKK7_MKKB = 0x8C,
+ MKK7_MKKA2 = 0x8D,
+ MKK7_MKKC = 0x8E,
+
+ MKK8_MKKB = 0x8F,
+ MKK8_MKKA2 = 0x90,
+ MKK8_MKKC = 0x91,
+
+ MKK14_MKKA1 = 0x92,
+ MKK15_MKKA1 = 0x93,
+
+ MKK10_FCCA = 0xD0,
+ MKK10_MKKA1 = 0xD1,
+ MKK10_MKKC = 0xD2,
+ MKK10_MKKA2 = 0xD3,
+
+ MKK11_MKKA = 0xD4,
+ MKK11_FCCA = 0xD5,
+ MKK11_MKKA1 = 0xD6,
+ MKK11_MKKC = 0xD7,
+ MKK11_MKKA2 = 0xD8,
+
+ MKK12_MKKA = 0xD9,
+ MKK12_FCCA = 0xDA,
+ MKK12_MKKA1 = 0xDB,
+ MKK12_MKKC = 0xDC,
+ MKK12_MKKA2 = 0xDD,
+
+ MKK13_MKKB = 0xDE,
+
+ MKK3_MKKA = 0xF0,
+ MKK3_MKKA1 = 0xF1,
+ MKK3_FCCA = 0xF2,
+ MKK4_MKKA = 0xF3,
+ MKK4_MKKA1 = 0xF4,
+ MKK4_FCCA = 0xF5,
+ MKK9_MKKA = 0xF6,
+ MKK10_MKKA = 0xF7,
+ MKK6_MKKA1 = 0xF8,
+ MKK6_FCCA = 0xF9,
+ MKK7_MKKA1 = 0xFA,
+ MKK7_FCCA = 0xFB,
+ MKK9_FCCA = 0xFC,
+ MKK9_MKKA1 = 0xFD,
+ MKK9_MKKC = 0xFE,
+ MKK9_MKKA2 = 0xFF,
+
+ WORLD = 0x0199,
+ DEBUG_REG_DMN = 0x01ff,
+};
+
+///* Regpair to CTL band mapping */
+//static struct reg_dmn_pair_mapping regDomainPairs[] = {
+// /* regpair, 5 GHz CTL, 2 GHz CTL */
+// {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN},
+// {NULL1_WORLD, NO_CTL, CTL_ETSI},
+// {NULL1_ETSIB, NO_CTL, CTL_ETSI},
+// {NULL1_ETSIC, NO_CTL, CTL_ETSI},
+//
+// {FCC2_FCCA, CTL_FCC, CTL_FCC},
+// {FCC2_WORLD, CTL_FCC, CTL_ETSI},
+// {FCC2_ETSIC, CTL_FCC, CTL_ETSI},
+// {FCC3_FCCA, CTL_FCC, CTL_FCC},
+// {FCC3_WORLD, CTL_FCC, CTL_ETSI},
+// {FCC4_FCCA, CTL_FCC, CTL_FCC},
+// {FCC5_FCCA, CTL_FCC, CTL_FCC},
+// {FCC6_FCCA, CTL_FCC, CTL_FCC},
+// {FCC6_WORLD, CTL_FCC, CTL_ETSI},
+//
+// {ETSI1_WORLD, CTL_ETSI, CTL_ETSI},
+// {ETSI2_WORLD, CTL_ETSI, CTL_ETSI},
+// {ETSI3_WORLD, CTL_ETSI, CTL_ETSI},
+// {ETSI4_WORLD, CTL_ETSI, CTL_ETSI},
+// {ETSI5_WORLD, CTL_ETSI, CTL_ETSI},
+// {ETSI6_WORLD, CTL_ETSI, CTL_ETSI},
+//
+// /* XXX: For ETSI3_ETSIA, Was NO_CTL meant for the 2 GHz band ? */
+// {ETSI3_ETSIA, CTL_ETSI, CTL_ETSI},
+// {FRANCE_RES, CTL_ETSI, CTL_ETSI},
+//
+// {FCC1_WORLD, CTL_FCC, CTL_ETSI},
+// {FCC1_FCCA, CTL_FCC, CTL_FCC},
+// {APL1_WORLD, CTL_FCC, CTL_ETSI},
+// {APL2_WORLD, CTL_FCC, CTL_ETSI},
+// {APL3_WORLD, CTL_FCC, CTL_ETSI},
+// {APL4_WORLD, CTL_FCC, CTL_ETSI},
+// {APL5_WORLD, CTL_FCC, CTL_ETSI},
+// {APL6_WORLD, CTL_ETSI, CTL_ETSI},
+// {APL8_WORLD, CTL_ETSI, CTL_ETSI},
+// {APL9_WORLD, CTL_ETSI, CTL_ETSI},
+//
+// {APL3_FCCA, CTL_FCC, CTL_FCC},
+// {APL7_FCCA, CTL_FCC, CTL_FCC},
+// {APL1_ETSIC, CTL_FCC, CTL_ETSI},
+// {APL2_ETSIC, CTL_FCC, CTL_ETSI},
+// {APL2_APLD, CTL_FCC, NO_CTL},
+//
+// {MKK1_MKKA, CTL_MKK, CTL_MKK},
+// {MKK1_MKKB, CTL_MKK, CTL_MKK},
+// {MKK1_FCCA, CTL_MKK, CTL_FCC},
+// {MKK1_MKKA1, CTL_MKK, CTL_MKK},
+// {MKK1_MKKA2, CTL_MKK, CTL_MKK},
+// {MKK1_MKKC, CTL_MKK, CTL_MKK},
+//
+// {MKK2_MKKA, CTL_MKK, CTL_MKK},
+// {MKK3_MKKA, CTL_MKK, CTL_MKK},
+// {MKK3_MKKB, CTL_MKK, CTL_MKK},
+// {MKK3_MKKA1, CTL_MKK, CTL_MKK},
+// {MKK3_MKKA2, CTL_MKK, CTL_MKK},
+// {MKK3_MKKC, CTL_MKK, CTL_MKK},
+// {MKK3_FCCA, CTL_MKK, CTL_FCC},
+//
+// {MKK4_MKKA, CTL_MKK, CTL_MKK},
+// {MKK4_MKKB, CTL_MKK, CTL_MKK},
+// {MKK4_MKKA1, CTL_MKK, CTL_MKK},
+// {MKK4_MKKA2, CTL_MKK, CTL_MKK},
+// {MKK4_MKKC, CTL_MKK, CTL_MKK},
+// {MKK4_FCCA, CTL_MKK, CTL_FCC},
+//
+// {MKK5_MKKB, CTL_MKK, CTL_MKK},
+// {MKK5_MKKA2, CTL_MKK, CTL_MKK},
+// {MKK5_MKKC, CTL_MKK, CTL_MKK},
+//
+// {MKK6_MKKB, CTL_MKK, CTL_MKK},
+// {MKK6_MKKA1, CTL_MKK, CTL_MKK},
+// {MKK6_MKKA2, CTL_MKK, CTL_MKK},
+// {MKK6_MKKC, CTL_MKK, CTL_MKK},
+// {MKK6_FCCA, CTL_MKK, CTL_FCC},
+//
+// {MKK7_MKKB, CTL_MKK, CTL_MKK},
+// {MKK7_MKKA1, CTL_MKK, CTL_MKK},
+// {MKK7_MKKA2, CTL_MKK, CTL_MKK},
+// {MKK7_MKKC, CTL_MKK, CTL_MKK},
+// {MKK7_FCCA, CTL_MKK, CTL_FCC},
+//
+// {MKK8_MKKB, CTL_MKK, CTL_MKK},
+// {MKK8_MKKA2, CTL_MKK, CTL_MKK},
+// {MKK8_MKKC, CTL_MKK, CTL_MKK},
+//
+// {MKK9_MKKA, CTL_MKK, CTL_MKK},
+// {MKK9_FCCA, CTL_MKK, CTL_FCC},
+// {MKK9_MKKA1, CTL_MKK, CTL_MKK},
+// {MKK9_MKKA2, CTL_MKK, CTL_MKK},
+// {MKK9_MKKC, CTL_MKK, CTL_MKK},
+//
+// {MKK10_MKKA, CTL_MKK, CTL_MKK},
+// {MKK10_FCCA, CTL_MKK, CTL_FCC},
+// {MKK10_MKKA1, CTL_MKK, CTL_MKK},
+// {MKK10_MKKA2, CTL_MKK, CTL_MKK},
+// {MKK10_MKKC, CTL_MKK, CTL_MKK},
+//
+// {MKK11_MKKA, CTL_MKK, CTL_MKK},
+// {MKK11_FCCA, CTL_MKK, CTL_FCC},
+// {MKK11_MKKA1, CTL_MKK, CTL_MKK},
+// {MKK11_MKKA2, CTL_MKK, CTL_MKK},
+// {MKK11_MKKC, CTL_MKK, CTL_MKK},
+//
+// {MKK12_MKKA, CTL_MKK, CTL_MKK},
+// {MKK12_FCCA, CTL_MKK, CTL_FCC},
+// {MKK12_MKKA1, CTL_MKK, CTL_MKK},
+// {MKK12_MKKA2, CTL_MKK, CTL_MKK},
+// {MKK12_MKKC, CTL_MKK, CTL_MKK},
+//
+// {MKK13_MKKB, CTL_MKK, CTL_MKK},
+// {MKK14_MKKA1, CTL_MKK, CTL_MKK},
+// {MKK15_MKKA1, CTL_MKK, CTL_MKK},
+//
+// {WOR0_WORLD, NO_CTL, NO_CTL},
+// {WOR1_WORLD, NO_CTL, NO_CTL},
+// {WOR2_WORLD, NO_CTL, NO_CTL},
+// {WOR3_WORLD, NO_CTL, NO_CTL},
+// {WOR4_WORLD, NO_CTL, NO_CTL},
+// {WOR5_ETSIC, NO_CTL, NO_CTL},
+// {WOR01_WORLD, NO_CTL, NO_CTL},
+// {WOR02_WORLD, NO_CTL, NO_CTL},
+// {EU1_WORLD, NO_CTL, NO_CTL},
+// {WOR9_WORLD, NO_CTL, NO_CTL},
+// {WORA_WORLD, NO_CTL, NO_CTL},
+// {WORB_WORLD, NO_CTL, NO_CTL},
+// {WORC_WORLD, NO_CTL, NO_CTL},
+//};
+//
+//static struct country_code_to_enum_rd allCountries[] = {
+// {CTRY_DEBUG, NO_ENUMRD, "DB"},
+// {CTRY_DEFAULT, FCC1_FCCA, "CO"},
+// {CTRY_ALBANIA, NULL1_WORLD, "AL"},
+// {CTRY_ALGERIA, NULL1_WORLD, "DZ"},
+// {CTRY_ARGENTINA, FCC3_WORLD, "AR"},
+// {CTRY_ARMENIA, ETSI4_WORLD, "AM"},
+// {CTRY_ARUBA, ETSI1_WORLD, "AW"},
+// {CTRY_AUSTRALIA, FCC2_WORLD, "AU"},
+// {CTRY_AUSTRALIA2, FCC6_WORLD, "AU"},
+// {CTRY_AUSTRIA, ETSI1_WORLD, "AT"},
+// {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"},
+// {CTRY_BAHRAIN, APL6_WORLD, "BH"},
+// {CTRY_BANGLADESH, NULL1_WORLD, "BD"},
+// {CTRY_BARBADOS, FCC2_WORLD, "BB"},
+// {CTRY_BELARUS, ETSI1_WORLD, "BY"},
+// {CTRY_BELGIUM, ETSI1_WORLD, "BE"},
+// {CTRY_BELGIUM2, ETSI4_WORLD, "BL"},
+// {CTRY_BELIZE, APL1_ETSIC, "BZ"},
+// {CTRY_BOLIVIA, APL1_ETSIC, "BO"},
+// {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA"},
+// {CTRY_BRAZIL, FCC3_WORLD, "BR"},
+// {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"},
+// {CTRY_BULGARIA, ETSI6_WORLD, "BG"},
+// {CTRY_CAMBODIA, ETSI1_WORLD, "KH"},
+// {CTRY_CANADA, FCC3_FCCA, "CA"},
+// {CTRY_CANADA2, FCC6_FCCA, "CA"},
+// {CTRY_CHILE, APL6_WORLD, "CL"},
+// {CTRY_CHINA, APL1_WORLD, "CN"},
+// {CTRY_COLOMBIA, FCC1_FCCA, "CO"},
+// {CTRY_COSTA_RICA, FCC1_WORLD, "CR"},
+// {CTRY_CROATIA, ETSI1_WORLD, "HR"},
+// {CTRY_CYPRUS, ETSI1_WORLD, "CY"},
+// {CTRY_CZECH, ETSI3_WORLD, "CZ"},
+// {CTRY_DENMARK, ETSI1_WORLD, "DK"},
+// {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO"},
+// {CTRY_ECUADOR, FCC1_WORLD, "EC"},
+// {CTRY_EGYPT, ETSI3_WORLD, "EG"},
+// {CTRY_EL_SALVADOR, FCC1_WORLD, "SV"},
+// {CTRY_ESTONIA, ETSI1_WORLD, "EE"},
+// {CTRY_FINLAND, ETSI1_WORLD, "FI"},
+// {CTRY_FRANCE, ETSI1_WORLD, "FR"},
+// {CTRY_GEORGIA, ETSI4_WORLD, "GE"},
+// {CTRY_GERMANY, ETSI1_WORLD, "DE"},
+// {CTRY_GREECE, ETSI1_WORLD, "GR"},
+// {CTRY_GREENLAND, ETSI1_WORLD, "GL"},
+// {CTRY_GRENEDA, FCC3_FCCA, "GD"},
+// {CTRY_GUAM, FCC1_FCCA, "GU"},
+// {CTRY_GUATEMALA, FCC1_FCCA, "GT"},
+// {CTRY_HAITI, ETSI1_WORLD, "HT"},
+// {CTRY_HONDURAS, NULL1_WORLD, "HN"},
+// {CTRY_HONG_KONG, FCC3_WORLD, "HK"},
+// {CTRY_HUNGARY, ETSI1_WORLD, "HU"},
+// {CTRY_ICELAND, ETSI1_WORLD, "IS"},
+// {CTRY_INDIA, APL6_WORLD, "IN"},
+// {CTRY_INDONESIA, NULL1_WORLD, "ID"},
+// {CTRY_IRAN, APL1_WORLD, "IR"},
+// {CTRY_IRELAND, ETSI1_WORLD, "IE"},
+// {CTRY_ISRAEL, NULL1_WORLD, "IL"},
+// {CTRY_ITALY, ETSI1_WORLD, "IT"},
+// {CTRY_JAMAICA, FCC3_WORLD, "JM"},
+//
+// {CTRY_JAPAN, MKK1_MKKA, "JP"},
+// {CTRY_JAPAN1, MKK1_MKKB, "JP"},
+// {CTRY_JAPAN2, MKK1_FCCA, "JP"},
+// {CTRY_JAPAN3, MKK2_MKKA, "JP"},
+// {CTRY_JAPAN4, MKK1_MKKA1, "JP"},
+// {CTRY_JAPAN5, MKK1_MKKA2, "JP"},
+// {CTRY_JAPAN6, MKK1_MKKC, "JP"},
+// {CTRY_JAPAN7, MKK3_MKKB, "JP"},
+// {CTRY_JAPAN8, MKK3_MKKA2, "JP"},
+// {CTRY_JAPAN9, MKK3_MKKC, "JP"},
+// {CTRY_JAPAN10, MKK4_MKKB, "JP"},
+// {CTRY_JAPAN11, MKK4_MKKA2, "JP"},
+// {CTRY_JAPAN12, MKK4_MKKC, "JP"},
+// {CTRY_JAPAN13, MKK5_MKKB, "JP"},
+// {CTRY_JAPAN14, MKK5_MKKA2, "JP"},
+// {CTRY_JAPAN15, MKK5_MKKC, "JP"},
+// {CTRY_JAPAN16, MKK6_MKKB, "JP"},
+// {CTRY_JAPAN17, MKK6_MKKA2, "JP"},
+// {CTRY_JAPAN18, MKK6_MKKC, "JP"},
+// {CTRY_JAPAN19, MKK7_MKKB, "JP"},
+// {CTRY_JAPAN20, MKK7_MKKA2, "JP"},
+// {CTRY_JAPAN21, MKK7_MKKC, "JP"},
+// {CTRY_JAPAN22, MKK8_MKKB, "JP"},
+// {CTRY_JAPAN23, MKK8_MKKA2, "JP"},
+// {CTRY_JAPAN24, MKK8_MKKC, "JP"},
+// {CTRY_JAPAN25, MKK3_MKKA, "JP"},
+// {CTRY_JAPAN26, MKK3_MKKA1, "JP"},
+// {CTRY_JAPAN27, MKK3_FCCA, "JP"},
+// {CTRY_JAPAN28, MKK4_MKKA1, "JP"},
+// {CTRY_JAPAN29, MKK4_FCCA, "JP"},
+// {CTRY_JAPAN30, MKK6_MKKA1, "JP"},
+// {CTRY_JAPAN31, MKK6_FCCA, "JP"},
+// {CTRY_JAPAN32, MKK7_MKKA1, "JP"},
+// {CTRY_JAPAN33, MKK7_FCCA, "JP"},
+// {CTRY_JAPAN34, MKK9_MKKA, "JP"},
+// {CTRY_JAPAN35, MKK10_MKKA, "JP"},
+// {CTRY_JAPAN36, MKK4_MKKA, "JP"},
+// {CTRY_JAPAN37, MKK9_FCCA, "JP"},
+// {CTRY_JAPAN38, MKK9_MKKA1, "JP"},
+// {CTRY_JAPAN39, MKK9_MKKC, "JP"},
+// {CTRY_JAPAN40, MKK9_MKKA2, "JP"},
+// {CTRY_JAPAN41, MKK10_FCCA, "JP"},
+// {CTRY_JAPAN42, MKK10_MKKA1, "JP"},
+// {CTRY_JAPAN43, MKK10_MKKC, "JP"},
+// {CTRY_JAPAN44, MKK10_MKKA2, "JP"},
+// {CTRY_JAPAN45, MKK11_MKKA, "JP"},
+// {CTRY_JAPAN46, MKK11_FCCA, "JP"},
+// {CTRY_JAPAN47, MKK11_MKKA1, "JP"},
+// {CTRY_JAPAN48, MKK11_MKKC, "JP"},
+// {CTRY_JAPAN49, MKK11_MKKA2, "JP"},
+// {CTRY_JAPAN50, MKK12_MKKA, "JP"},
+// {CTRY_JAPAN51, MKK12_FCCA, "JP"},
+// {CTRY_JAPAN52, MKK12_MKKA1, "JP"},
+// {CTRY_JAPAN53, MKK12_MKKC, "JP"},
+// {CTRY_JAPAN54, MKK12_MKKA2, "JP"},
+// {CTRY_JAPAN57, MKK13_MKKB, "JP"},
+// {CTRY_JAPAN58, MKK14_MKKA1, "JP"},
+// {CTRY_JAPAN59, MKK15_MKKA1, "JP"},
+//
+// {CTRY_JORDAN, ETSI2_WORLD, "JO"},
+// {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ"},
+// {CTRY_KOREA_NORTH, APL9_WORLD, "KP"},
+// {CTRY_KOREA_ROC, APL9_WORLD, "KR"},
+// {CTRY_KOREA_ROC2, APL2_WORLD, "K2"},
+// {CTRY_KOREA_ROC3, APL9_WORLD, "K3"},
+// {CTRY_KUWAIT, ETSI3_WORLD, "KW"},
+// {CTRY_LATVIA, ETSI1_WORLD, "LV"},
+// {CTRY_LEBANON, NULL1_WORLD, "LB"},
+// {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"},
+// {CTRY_LITHUANIA, ETSI1_WORLD, "LT"},
+// {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU"},
+// {CTRY_MACAU, FCC2_WORLD, "MO"},
+// {CTRY_MACEDONIA, NULL1_WORLD, "MK"},
+// {CTRY_MALAYSIA, APL8_WORLD, "MY"},
+// {CTRY_MALTA, ETSI1_WORLD, "MT"},
+// {CTRY_MEXICO, FCC1_FCCA, "MX"},
+// {CTRY_MONACO, ETSI4_WORLD, "MC"},
+// {CTRY_MOROCCO, APL4_WORLD, "MA"},
+// {CTRY_NEPAL, APL1_WORLD, "NP"},
+// {CTRY_NETHERLANDS, ETSI1_WORLD, "NL"},
+// {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"},
+// {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"},
+// {CTRY_NORWAY, ETSI1_WORLD, "NO"},
+// {CTRY_OMAN, FCC3_WORLD, "OM"},
+// {CTRY_PAKISTAN, NULL1_WORLD, "PK"},
+// {CTRY_PANAMA, FCC1_FCCA, "PA"},
+// {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"},
+// {CTRY_PERU, APL1_WORLD, "PE"},
+// {CTRY_PHILIPPINES, APL1_WORLD, "PH"},
+// {CTRY_POLAND, ETSI1_WORLD, "PL"},
+// {CTRY_PORTUGAL, ETSI1_WORLD, "PT"},
+// {CTRY_PUERTO_RICO, FCC1_FCCA, "PR"},
+// {CTRY_QATAR, APL1_WORLD, "QA"},
+// {CTRY_ROMANIA, NULL1_WORLD, "RO"},
+// {CTRY_RUSSIA, NULL1_WORLD, "RU"},
+// {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"},
+// {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS"},
+// {CTRY_SINGAPORE, APL6_WORLD, "SG"},
+// {CTRY_SLOVAKIA, ETSI1_WORLD, "SK"},
+// {CTRY_SLOVENIA, ETSI1_WORLD, "SI"},
+// {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA"},
+// {CTRY_SPAIN, ETSI1_WORLD, "ES"},
+// {CTRY_SRI_LANKA, FCC3_WORLD, "LK"},
+// {CTRY_SWEDEN, ETSI1_WORLD, "SE"},
+// {CTRY_SWITZERLAND, ETSI1_WORLD, "CH"},
+// {CTRY_SYRIA, NULL1_WORLD, "SY"},
+// {CTRY_TAIWAN, APL3_FCCA, "TW"},
+// {CTRY_THAILAND, FCC3_WORLD, "TH"},
+// {CTRY_TRINIDAD_Y_TOBAGO, FCC3_WORLD, "TT"},
+// {CTRY_TUNISIA, ETSI3_WORLD, "TN"},
+// {CTRY_TURKEY, ETSI3_WORLD, "TR"},
+// {CTRY_UKRAINE, NULL1_WORLD, "UA"},
+// {CTRY_UAE, NULL1_WORLD, "AE"},
+// {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
+// {CTRY_UNITED_STATES, FCC3_FCCA, "US"},
+// /* This "PS" is for US public safety actually... to support this we
+// * would need to assign new special alpha2 to CRDA db as with the world
+// * regdomain and use another alpha2 */
+// {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"},
+// {CTRY_URUGUAY, FCC3_WORLD, "UY"},
+// {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"},
+// {CTRY_VENEZUELA, APL2_ETSIC, "VE"},
+// {CTRY_VIET_NAM, NULL1_WORLD, "VN"},
+// {CTRY_YEMEN, NULL1_WORLD, "YE"},
+// {CTRY_ZIMBABWE, NULL1_WORLD, "ZW"},
+//};
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/atl1e.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/atl1e.c
new file mode 100644
index 00000000..e4dd5c97
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/atl1e.c
@@ -0,0 +1,1749 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * Modified for iPXE, October 2009 by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "atl1e.h"
+
+/* User-tweakable parameters: */
+#define TX_DESC_COUNT 32 /* TX descriptors, minimum 32 */
+#define RX_MEM_SIZE 8192 /* RX area size, minimum 8kb */
+#define MAX_FRAME_SIZE 1500 /* Maximum MTU supported, minimum 1500 */
+
+/* Arcane parameters: */
+#define PREAMBLE_LEN 7
+#define RX_JUMBO_THRESH ((MAX_FRAME_SIZE + ETH_HLEN + \
+ VLAN_HLEN + ETH_FCS_LEN + 7) >> 3)
+#define IMT_VAL 100 /* interrupt moderator timer, us */
+#define ICT_VAL 50000 /* interrupt clear timer, us */
+#define SMB_TIMER 200000
+#define RRD_THRESH 1 /* packets to queue before interrupt */
+#define TPD_BURST 5
+#define TPD_THRESH (TX_DESC_COUNT / 2)
+#define RX_COUNT_DOWN 4
+#define TX_COUNT_DOWN (IMT_VAL * 4 / 3)
+#define DMAR_DLY_CNT 15
+#define DMAW_DLY_CNT 4
+
+#define PCI_DEVICE_ID_ATTANSIC_L1E 0x1026
+
+/*
+ * atl1e_pci_tbl - PCI Device ID Table
+ *
+ * Wildcard entries (PCI_ANY_ID) should come last
+ * Last entry must be all 0s
+ *
+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
+ * Class, Class Mask, private data (not used) }
+ */
+static struct pci_device_id atl1e_pci_tbl[] = {
+ PCI_ROM(0x1969, 0x1026, "atl1e_26", "Attansic L1E 0x1026", 0),
+ PCI_ROM(0x1969, 0x1066, "atl1e_66", "Attansic L1E 0x1066", 0),
+};
+
+static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter);
+
+static const u16
+atl1e_rx_page_vld_regs[AT_PAGE_NUM_PER_QUEUE] =
+{
+ REG_HOST_RXF0_PAGE0_VLD, REG_HOST_RXF0_PAGE1_VLD
+};
+
+static const u16
+atl1e_rx_page_lo_addr_regs[AT_PAGE_NUM_PER_QUEUE] =
+{
+ REG_HOST_RXF0_PAGE0_LO, REG_HOST_RXF0_PAGE1_LO
+};
+
+static const u16
+atl1e_rx_page_write_offset_regs[AT_PAGE_NUM_PER_QUEUE] =
+{
+ REG_HOST_RXF0_MB0_LO, REG_HOST_RXF0_MB1_LO
+};
+
+static const u16 atl1e_pay_load_size[] = {
+ 128, 256, 512, 1024, 2048, 4096,
+};
+
+/*
+ * atl1e_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_enable(struct atl1e_adapter *adapter)
+{
+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+ AT_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK);
+ AT_WRITE_FLUSH(&adapter->hw);
+}
+
+/*
+ * atl1e_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_disable(struct atl1e_adapter *adapter)
+{
+ AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+ AT_WRITE_FLUSH(&adapter->hw);
+}
+
+/*
+ * atl1e_irq_reset - reset interrupt confiure on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_reset(struct atl1e_adapter *adapter)
+{
+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+ AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+ AT_WRITE_FLUSH(&adapter->hw);
+}
+
+static void atl1e_reset(struct atl1e_adapter *adapter)
+{
+ atl1e_down(adapter);
+ atl1e_up(adapter);
+}
+
+static int atl1e_check_link(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ int err = 0;
+ u16 speed, duplex, phy_data;
+
+ /* MII_BMSR must read twise */
+ atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+ atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+
+ if ((phy_data & BMSR_LSTATUS) == 0) {
+ /* link down */
+ if (netdev_link_ok(netdev)) { /* old link state: Up */
+ u32 value;
+ /* disable rx */
+ value = AT_READ_REG(hw, REG_MAC_CTRL);
+ value &= ~MAC_CTRL_RX_EN;
+ AT_WRITE_REG(hw, REG_MAC_CTRL, value);
+ adapter->link_speed = SPEED_0;
+
+ DBG("atl1e: %s link is down\n", netdev->name);
+ netdev_link_down(netdev);
+ }
+ } else {
+ /* Link Up */
+ err = atl1e_get_speed_and_duplex(hw, &speed, &duplex);
+ if (err)
+ return err;
+
+ /* link result is our setting */
+ if (adapter->link_speed != speed ||
+ adapter->link_duplex != duplex) {
+ adapter->link_speed = speed;
+ adapter->link_duplex = duplex;
+ atl1e_setup_mac_ctrl(adapter);
+
+ DBG("atl1e: %s link is up, %d Mbps, %s duplex\n",
+ netdev->name, adapter->link_speed,
+ adapter->link_duplex == FULL_DUPLEX ?
+ "full" : "half");
+ netdev_link_up(netdev);
+ }
+ }
+ return 0;
+}
+
+static int atl1e_mdio_read(struct net_device *netdev, int phy_id __unused,
+ int reg_num)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ u16 result;
+
+ atl1e_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result);
+ return result;
+}
+
+static void atl1e_mdio_write(struct net_device *netdev, int phy_id __unused,
+ int reg_num, int val)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ atl1e_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
+}
+
+static void atl1e_setup_pcicmd(struct pci_device *pdev)
+{
+ u16 cmd;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ cmd |= (PCI_COMMAND_MEM | PCI_COMMAND_MASTER);
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+
+ /*
+ * some motherboards BIOS(PXE/EFI) driver may set PME
+ * while they transfer control to OS (Windows/Linux)
+ * so we should clear this bit before NIC work normally
+ */
+ pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0);
+ mdelay(1);
+}
+
+/*
+ * atl1e_sw_init - Initialize general software structures (struct atl1e_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl1e_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+static int atl1e_sw_init(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ struct pci_device *pdev = adapter->pdev;
+ u32 phy_status_data = 0;
+ u8 rev_id = 0;
+
+ adapter->link_speed = SPEED_0; /* hardware init */
+ adapter->link_duplex = FULL_DUPLEX;
+
+ /* PCI config space info */
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
+
+ phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
+ /* nic type */
+ if (rev_id >= 0xF0) {
+ hw->nic_type = athr_l2e_revB;
+ } else {
+ if (phy_status_data & PHY_STATUS_100M)
+ hw->nic_type = athr_l1e;
+ else
+ hw->nic_type = athr_l2e_revA;
+ }
+
+ phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
+
+ hw->emi_ca = !!(phy_status_data & PHY_STATUS_EMI_CA);
+
+ hw->phy_configured = 0;
+
+ /* need confirm */
+
+ hw->dmar_block = atl1e_dma_req_1024;
+ hw->dmaw_block = atl1e_dma_req_1024;
+
+ return 0;
+}
+
+/*
+ * atl1e_clean_tx_ring - free all Tx buffers for device close
+ * @adapter: board private structure
+ */
+static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = (struct atl1e_tx_ring *)
+ &adapter->tx_ring;
+ struct atl1e_tx_buffer *tx_buffer = NULL;
+ u16 index, ring_count = tx_ring->count;
+
+ if (tx_ring->desc == NULL || tx_ring->tx_buffer == NULL)
+ return;
+
+ for (index = 0; index < ring_count; index++) {
+ tx_buffer = &tx_ring->tx_buffer[index];
+ if (tx_buffer->iob) {
+ netdev_tx_complete(adapter->netdev, tx_buffer->iob);
+ tx_buffer->dma = 0;
+ tx_buffer->iob = NULL;
+ }
+ }
+
+ /* Zero out Tx-buffers */
+ memset(tx_ring->desc, 0, sizeof(struct atl1e_tpd_desc) *
+ ring_count);
+ memset(tx_ring->tx_buffer, 0, sizeof(struct atl1e_tx_buffer) *
+ ring_count);
+}
+
+/*
+ * atl1e_clean_rx_ring - Free rx-reservation iobs
+ * @adapter: board private structure
+ */
+static void atl1e_clean_rx_ring(struct atl1e_adapter *adapter)
+{
+ struct atl1e_rx_ring *rx_ring =
+ (struct atl1e_rx_ring *)&adapter->rx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc = &rx_ring->rx_page_desc;
+ u16 j;
+
+ if (adapter->ring_vir_addr == NULL)
+ return;
+
+ /* Zero out the descriptor ring */
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ if (rx_page_desc->rx_page[j].addr != NULL) {
+ memset(rx_page_desc->rx_page[j].addr, 0,
+ rx_ring->real_page_size);
+ }
+ }
+}
+
+static void atl1e_cal_ring_size(struct atl1e_adapter *adapter, u32 *ring_size)
+{
+ *ring_size = ((u32)(adapter->tx_ring.count *
+ sizeof(struct atl1e_tpd_desc) + 7
+ /* tx ring, qword align */
+ + adapter->rx_ring.real_page_size * AT_PAGE_NUM_PER_QUEUE
+ + 31
+ /* rx ring, 32 bytes align */
+ + (1 + AT_PAGE_NUM_PER_QUEUE) *
+ sizeof(u32) + 3));
+ /* tx, rx cmd, dword align */
+}
+
+static void atl1e_init_ring_resources(struct atl1e_adapter *adapter)
+{
+ struct atl1e_rx_ring *rx_ring = &adapter->rx_ring;
+
+ rx_ring->real_page_size = adapter->rx_ring.page_size
+ + MAX_FRAME_SIZE
+ + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
+ rx_ring->real_page_size = (rx_ring->real_page_size + 31) & ~31;
+ atl1e_cal_ring_size(adapter, &adapter->ring_size);
+
+ adapter->ring_vir_addr = NULL;
+ adapter->rx_ring.desc = NULL;
+
+ return;
+}
+
+/*
+ * Read / Write Ptr Initialize:
+ */
+static void atl1e_init_ring_ptrs(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = NULL;
+ struct atl1e_rx_ring *rx_ring = NULL;
+ struct atl1e_rx_page_desc *rx_page_desc = NULL;
+ int j;
+
+ tx_ring = &adapter->tx_ring;
+ rx_ring = &adapter->rx_ring;
+ rx_page_desc = &rx_ring->rx_page_desc;
+
+ tx_ring->next_to_use = 0;
+ tx_ring->next_to_clean = 0;
+
+ rx_page_desc->rx_using = 0;
+ rx_page_desc->rx_nxseq = 0;
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ *rx_page_desc->rx_page[j].write_offset_addr = 0;
+ rx_page_desc->rx_page[j].read_offset = 0;
+ }
+}
+
+/*
+ * atl1e_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+static void atl1e_free_ring_resources(struct atl1e_adapter *adapter)
+{
+ atl1e_clean_tx_ring(adapter);
+ atl1e_clean_rx_ring(adapter);
+
+ if (adapter->ring_vir_addr) {
+ free_dma(adapter->ring_vir_addr, adapter->ring_size);
+ adapter->ring_vir_addr = NULL;
+ adapter->ring_dma = 0;
+ }
+
+ if (adapter->tx_ring.tx_buffer) {
+ free(adapter->tx_ring.tx_buffer);
+ adapter->tx_ring.tx_buffer = NULL;
+ }
+}
+
+/*
+ * atl1e_setup_mem_resources - allocate Tx / RX descriptor resources
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ */
+static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring;
+ struct atl1e_rx_ring *rx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc;
+ int size, j;
+ u32 offset = 0;
+ int err = 0;
+
+ if (adapter->ring_vir_addr != NULL)
+ return 0; /* alloced already */
+
+ tx_ring = &adapter->tx_ring;
+ rx_ring = &adapter->rx_ring;
+
+ /* real ring DMA buffer */
+
+ size = adapter->ring_size;
+ adapter->ring_vir_addr = malloc_dma(adapter->ring_size, 32);
+
+ if (adapter->ring_vir_addr == NULL) {
+ DBG("atl1e: out of memory allocating %d bytes for %s ring\n",
+ adapter->ring_size, adapter->netdev->name);
+ return -ENOMEM;
+ }
+
+ adapter->ring_dma = virt_to_bus(adapter->ring_vir_addr);
+ memset(adapter->ring_vir_addr, 0, adapter->ring_size);
+
+ rx_page_desc = &rx_ring->rx_page_desc;
+
+ /* Init TPD Ring */
+ tx_ring->dma = (adapter->ring_dma + 7) & ~7;
+ offset = tx_ring->dma - adapter->ring_dma;
+ tx_ring->desc = (struct atl1e_tpd_desc *)
+ (adapter->ring_vir_addr + offset);
+ size = sizeof(struct atl1e_tx_buffer) * (tx_ring->count);
+ tx_ring->tx_buffer = zalloc(size);
+ if (tx_ring->tx_buffer == NULL) {
+ DBG("atl1e: out of memory allocating %d bytes for %s txbuf\n",
+ size, adapter->netdev->name);
+ err = -ENOMEM;
+ goto failed;
+ }
+
+ /* Init RXF-Pages */
+ offset += (sizeof(struct atl1e_tpd_desc) * tx_ring->count);
+ offset = (offset + 31) & ~31;
+
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ rx_page_desc->rx_page[j].dma =
+ adapter->ring_dma + offset;
+ rx_page_desc->rx_page[j].addr =
+ adapter->ring_vir_addr + offset;
+ offset += rx_ring->real_page_size;
+ }
+
+ /* Init CMB dma address */
+ tx_ring->cmb_dma = adapter->ring_dma + offset;
+ tx_ring->cmb = (u32 *)(adapter->ring_vir_addr + offset);
+ offset += sizeof(u32);
+
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ rx_page_desc->rx_page[j].write_offset_dma =
+ adapter->ring_dma + offset;
+ rx_page_desc->rx_page[j].write_offset_addr =
+ adapter->ring_vir_addr + offset;
+ offset += sizeof(u32);
+ }
+
+ if (offset > adapter->ring_size) {
+ DBG("atl1e: ring miscalculation! need %d > %d bytes\n",
+ offset, adapter->ring_size);
+ err = -EINVAL;
+ goto failed;
+ }
+
+ return 0;
+failed:
+ atl1e_free_ring_resources(adapter);
+ return err;
+}
+
+static inline void atl1e_configure_des_ring(const struct atl1e_adapter *adapter)
+{
+
+ struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+ struct atl1e_rx_ring *rx_ring =
+ (struct atl1e_rx_ring *)&adapter->rx_ring;
+ struct atl1e_tx_ring *tx_ring =
+ (struct atl1e_tx_ring *)&adapter->tx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc = NULL;
+ int j;
+
+ AT_WRITE_REG(hw, REG_DESC_BASE_ADDR_HI, 0);
+ AT_WRITE_REG(hw, REG_TPD_BASE_ADDR_LO, tx_ring->dma);
+ AT_WRITE_REG(hw, REG_TPD_RING_SIZE, (u16)(tx_ring->count));
+ AT_WRITE_REG(hw, REG_HOST_TX_CMB_LO, tx_ring->cmb_dma);
+
+ rx_page_desc = &rx_ring->rx_page_desc;
+
+ /* RXF Page Physical address / Page Length */
+ AT_WRITE_REG(hw, REG_RXF0_BASE_ADDR_HI, 0);
+
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ u32 page_phy_addr;
+ u32 offset_phy_addr;
+
+ page_phy_addr = rx_page_desc->rx_page[j].dma;
+ offset_phy_addr = rx_page_desc->rx_page[j].write_offset_dma;
+
+ AT_WRITE_REG(hw, atl1e_rx_page_lo_addr_regs[j], page_phy_addr);
+ AT_WRITE_REG(hw, atl1e_rx_page_write_offset_regs[j],
+ offset_phy_addr);
+ AT_WRITE_REGB(hw, atl1e_rx_page_vld_regs[j], 1);
+ }
+
+ /* Page Length */
+ AT_WRITE_REG(hw, REG_HOST_RXFPAGE_SIZE, rx_ring->page_size);
+ /* Load all of base address above */
+ AT_WRITE_REG(hw, REG_LOAD_PTR, 1);
+
+ return;
+}
+
+static inline void atl1e_configure_tx(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+ u32 dev_ctrl_data = 0;
+ u32 max_pay_load = 0;
+ u32 jumbo_thresh = 0;
+ u32 extra_size = 0; /* Jumbo frame threshold in QWORD unit */
+
+ /* configure TXQ param */
+ if (hw->nic_type != athr_l2e_revB) {
+ extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
+ jumbo_thresh = MAX_FRAME_SIZE + extra_size;
+ AT_WRITE_REG(hw, REG_TX_EARLY_TH, (jumbo_thresh + 7) >> 3);
+ }
+
+ dev_ctrl_data = AT_READ_REG(hw, REG_DEVICE_CTRL);
+
+ max_pay_load = ((dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT)) &
+ DEVICE_CTRL_MAX_PAYLOAD_MASK;
+ if (max_pay_load < hw->dmaw_block)
+ hw->dmaw_block = max_pay_load;
+
+ max_pay_load = ((dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT)) &
+ DEVICE_CTRL_MAX_RREQ_SZ_MASK;
+ if (max_pay_load < hw->dmar_block)
+ hw->dmar_block = max_pay_load;
+
+ if (hw->nic_type != athr_l2e_revB)
+ AT_WRITE_REGW(hw, REG_TXQ_CTRL + 2,
+ atl1e_pay_load_size[hw->dmar_block]);
+ /* enable TXQ */
+ AT_WRITE_REGW(hw, REG_TXQ_CTRL,
+ ((TPD_BURST & TXQ_CTRL_NUM_TPD_BURST_MASK)
+ << TXQ_CTRL_NUM_TPD_BURST_SHIFT)
+ | TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN);
+ return;
+}
+
+static inline void atl1e_configure_rx(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+ u32 rxf_len = 0;
+ u32 rxf_low = 0;
+ u32 rxf_high = 0;
+ u32 rxf_thresh_data = 0;
+ u32 rxq_ctrl_data = 0;
+
+ if (hw->nic_type != athr_l2e_revB) {
+ AT_WRITE_REGW(hw, REG_RXQ_JMBOSZ_RRDTIM,
+ (u16)((RX_JUMBO_THRESH & RXQ_JMBOSZ_TH_MASK) <<
+ RXQ_JMBOSZ_TH_SHIFT |
+ (1 & RXQ_JMBO_LKAH_MASK) <<
+ RXQ_JMBO_LKAH_SHIFT));
+
+ rxf_len = AT_READ_REG(hw, REG_SRAM_RXF_LEN);
+ rxf_high = rxf_len * 4 / 5;
+ rxf_low = rxf_len / 5;
+ rxf_thresh_data = ((rxf_high & RXQ_RXF_PAUSE_TH_HI_MASK)
+ << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+ ((rxf_low & RXQ_RXF_PAUSE_TH_LO_MASK)
+ << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+
+ AT_WRITE_REG(hw, REG_RXQ_RXF_PAUSE_THRESH, rxf_thresh_data);
+ }
+
+ /* RRS */
+ AT_WRITE_REG(hw, REG_IDT_TABLE, 0);
+ AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, 0);
+
+ rxq_ctrl_data |= RXQ_CTRL_PBA_ALIGN_32 |
+ RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN;
+
+ AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
+ return;
+}
+
+static inline void atl1e_configure_dma(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 dma_ctrl_data = 0;
+
+ dma_ctrl_data = DMA_CTRL_RXCMB_EN;
+ dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+ << DMA_CTRL_DMAR_BURST_LEN_SHIFT;
+ dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
+ << DMA_CTRL_DMAW_BURST_LEN_SHIFT;
+ dma_ctrl_data |= DMA_CTRL_DMAR_REQ_PRI | DMA_CTRL_DMAR_OUT_ORDER;
+ dma_ctrl_data |= (DMAR_DLY_CNT & DMA_CTRL_DMAR_DLY_CNT_MASK)
+ << DMA_CTRL_DMAR_DLY_CNT_SHIFT;
+ dma_ctrl_data |= (DMAW_DLY_CNT & DMA_CTRL_DMAW_DLY_CNT_MASK)
+ << DMA_CTRL_DMAW_DLY_CNT_SHIFT;
+
+ AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data);
+ return;
+}
+
+static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter)
+{
+ u32 value;
+ struct atl1e_hw *hw = &adapter->hw;
+
+ /* Config MAC CTRL Register */
+ value = MAC_CTRL_TX_EN |
+ MAC_CTRL_RX_EN ;
+
+ if (FULL_DUPLEX == adapter->link_duplex)
+ value |= MAC_CTRL_DUPLX;
+
+ value |= ((u32)((SPEED_1000 == adapter->link_speed) ?
+ MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
+ MAC_CTRL_SPEED_SHIFT);
+ value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+
+ value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+ value |= ((PREAMBLE_LEN & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+
+ value |= MAC_CTRL_BC_EN;
+ value |= MAC_CTRL_MC_ALL_EN;
+
+ AT_WRITE_REG(hw, REG_MAC_CTRL, value);
+}
+
+/*
+ * atl1e_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static int atl1e_configure(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 intr_status_data = 0;
+
+ /* clear interrupt status */
+ AT_WRITE_REG(hw, REG_ISR, ~0);
+
+ /* 1. set MAC Address */
+ atl1e_hw_set_mac_addr(hw);
+
+ /* 2. Init the Multicast HASH table (clear) */
+ AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+ AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+ /* 3. Clear any WOL status */
+ AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+
+ /* 4. Descripter Ring BaseMem/Length/Read ptr/Write ptr
+ * TPD Ring/SMB/RXF0 Page CMBs, they use the same
+ * High 32bits memory */
+ atl1e_configure_des_ring(adapter);
+
+ /* 5. set Interrupt Moderator Timer */
+ AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, IMT_VAL);
+ AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER2_INIT, IMT_VAL);
+ AT_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_LED_MODE |
+ MASTER_CTRL_ITIMER_EN | MASTER_CTRL_ITIMER2_EN);
+
+ /* 6. rx/tx threshold to trig interrupt */
+ AT_WRITE_REGW(hw, REG_TRIG_RRD_THRESH, RRD_THRESH);
+ AT_WRITE_REGW(hw, REG_TRIG_TPD_THRESH, TPD_THRESH);
+ AT_WRITE_REGW(hw, REG_TRIG_RXTIMER, RX_COUNT_DOWN);
+ AT_WRITE_REGW(hw, REG_TRIG_TXTIMER, TX_COUNT_DOWN);
+
+ /* 7. set Interrupt Clear Timer */
+ AT_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, ICT_VAL);
+
+ /* 8. set MTU */
+ AT_WRITE_REG(hw, REG_MTU, MAX_FRAME_SIZE + ETH_HLEN +
+ VLAN_HLEN + ETH_FCS_LEN);
+
+ /* 9. config TXQ early tx threshold */
+ atl1e_configure_tx(adapter);
+
+ /* 10. config RXQ */
+ atl1e_configure_rx(adapter);
+
+ /* 11. config DMA Engine */
+ atl1e_configure_dma(adapter);
+
+ /* 12. smb timer to trig interrupt */
+ AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, SMB_TIMER);
+
+ intr_status_data = AT_READ_REG(hw, REG_ISR);
+ if ((intr_status_data & ISR_PHY_LINKDOWN) != 0) {
+ DBG("atl1e: configure failed, PCIE phy link down\n");
+ return -1;
+ }
+
+ AT_WRITE_REG(hw, REG_ISR, 0x7fffffff);
+ return 0;
+}
+
+static inline void atl1e_clear_phy_int(struct atl1e_adapter *adapter)
+{
+ u16 phy_data;
+
+ atl1e_read_phy_reg(&adapter->hw, MII_INT_STATUS, &phy_data);
+}
+
+static int atl1e_clean_tx_irq(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = (struct atl1e_tx_ring *)
+ &adapter->tx_ring;
+ struct atl1e_tx_buffer *tx_buffer = NULL;
+ u16 hw_next_to_clean = AT_READ_REGW(&adapter->hw, REG_TPD_CONS_IDX);
+ u16 next_to_clean = tx_ring->next_to_clean;
+
+ while (next_to_clean != hw_next_to_clean) {
+ tx_buffer = &tx_ring->tx_buffer[next_to_clean];
+
+ tx_buffer->dma = 0;
+ if (tx_buffer->iob) {
+ netdev_tx_complete(adapter->netdev, tx_buffer->iob);
+ tx_buffer->iob = NULL;
+ }
+
+ if (++next_to_clean == tx_ring->count)
+ next_to_clean = 0;
+ }
+
+ tx_ring->next_to_clean = next_to_clean;
+
+ return 1;
+}
+
+static struct atl1e_rx_page *atl1e_get_rx_page(struct atl1e_adapter *adapter)
+{
+ struct atl1e_rx_page_desc *rx_page_desc =
+ (struct atl1e_rx_page_desc *) &adapter->rx_ring.rx_page_desc;
+ u8 rx_using = rx_page_desc->rx_using;
+
+ return (struct atl1e_rx_page *)&(rx_page_desc->rx_page[rx_using]);
+}
+
+static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct atl1e_rx_ring *rx_ring = (struct atl1e_rx_ring *)
+ &adapter->rx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc =
+ (struct atl1e_rx_page_desc *) &rx_ring->rx_page_desc;
+ struct io_buffer *iob = NULL;
+ struct atl1e_rx_page *rx_page = atl1e_get_rx_page(adapter);
+ u32 packet_size, write_offset;
+ struct atl1e_recv_ret_status *prrs;
+
+ write_offset = *(rx_page->write_offset_addr);
+ if (rx_page->read_offset >= write_offset)
+ return;
+
+ do {
+ /* get new packet's rrs */
+ prrs = (struct atl1e_recv_ret_status *) (rx_page->addr +
+ rx_page->read_offset);
+ /* check sequence number */
+ if (prrs->seq_num != rx_page_desc->rx_nxseq) {
+ DBG("atl1e %s: RX sequence number error (%d != %d)\n",
+ netdev->name, prrs->seq_num,
+ rx_page_desc->rx_nxseq);
+ rx_page_desc->rx_nxseq++;
+ goto fatal_err;
+ }
+
+ rx_page_desc->rx_nxseq++;
+
+ /* error packet */
+ if (prrs->pkt_flag & RRS_IS_ERR_FRAME) {
+ if (prrs->err_flag & (RRS_ERR_BAD_CRC |
+ RRS_ERR_DRIBBLE | RRS_ERR_CODE |
+ RRS_ERR_TRUNC)) {
+ /* hardware error, discard this
+ packet */
+ netdev_rx_err(netdev, NULL, EIO);
+ goto skip_pkt;
+ }
+ }
+
+ packet_size = ((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
+ RRS_PKT_SIZE_MASK) - ETH_FCS_LEN;
+ iob = alloc_iob(packet_size + NET_IP_ALIGN);
+ if (iob == NULL) {
+ DBG("atl1e %s: dropping packet under memory pressure\n",
+ netdev->name);
+ goto skip_pkt;
+ }
+ iob_reserve(iob, NET_IP_ALIGN);
+ memcpy(iob->data, (u8 *)(prrs + 1), packet_size);
+ iob_put(iob, packet_size);
+
+ netdev_rx(netdev, iob);
+
+skip_pkt:
+ /* skip current packet whether it's ok or not. */
+ rx_page->read_offset +=
+ (((u32)((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
+ RRS_PKT_SIZE_MASK) +
+ sizeof(struct atl1e_recv_ret_status) + 31) &
+ 0xFFFFFFE0);
+
+ if (rx_page->read_offset >= rx_ring->page_size) {
+ /* mark this page clean */
+ u16 reg_addr;
+ u8 rx_using;
+
+ rx_page->read_offset =
+ *(rx_page->write_offset_addr) = 0;
+ rx_using = rx_page_desc->rx_using;
+ reg_addr =
+ atl1e_rx_page_vld_regs[rx_using];
+ AT_WRITE_REGB(&adapter->hw, reg_addr, 1);
+ rx_page_desc->rx_using ^= 1;
+ rx_page = atl1e_get_rx_page(adapter);
+ }
+ write_offset = *(rx_page->write_offset_addr);
+ } while (rx_page->read_offset < write_offset);
+
+ return;
+
+fatal_err:
+ if (!netdev_link_ok(adapter->netdev))
+ atl1e_reset(adapter);
+}
+
+/*
+ * atl1e_poll - poll for completed transmissions and received packets
+ * @netdev: network device
+ */
+static void atl1e_poll(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+ int max_ints = 64;
+ u32 status;
+
+ do {
+ status = AT_READ_REG(hw, REG_ISR);
+ if ((status & IMR_NORMAL_MASK) == 0)
+ break;
+
+ /* link event */
+ if (status & ISR_GPHY)
+ atl1e_clear_phy_int(adapter);
+ /* Ack ISR */
+ AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);
+
+ /* check if PCIE PHY Link down */
+ if (status & ISR_PHY_LINKDOWN) {
+ DBG("atl1e: PCI-E PHY link down: %x\n", status);
+ if (netdev_link_ok(adapter->netdev)) {
+ /* reset MAC */
+ atl1e_irq_reset(adapter);
+ atl1e_reset(adapter);
+ break;
+ }
+ }
+
+ /* check if DMA read/write error */
+ if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+ DBG("atl1e: PCI-E DMA RW error: %x\n", status);
+ atl1e_irq_reset(adapter);
+ atl1e_reset(adapter);
+ break;
+ }
+
+ /* link event */
+ if (status & (ISR_GPHY | ISR_MANUAL)) {
+ atl1e_check_link(adapter);
+ break;
+ }
+
+ /* transmit event */
+ if (status & ISR_TX_EVENT)
+ atl1e_clean_tx_irq(adapter);
+
+ if (status & ISR_RX_EVENT)
+ atl1e_clean_rx_irq(adapter);
+ } while (--max_ints > 0);
+
+ /* re-enable Interrupt*/
+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+
+ return;
+}
+
+static inline u16 atl1e_tpd_avail(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+ u16 next_to_use = 0;
+ u16 next_to_clean = 0;
+
+ next_to_clean = tx_ring->next_to_clean;
+ next_to_use = tx_ring->next_to_use;
+
+ return (u16)(next_to_clean > next_to_use) ?
+ (next_to_clean - next_to_use - 1) :
+ (tx_ring->count + next_to_clean - next_to_use - 1);
+}
+
+/*
+ * get next usable tpd
+ * Note: should call atl1e_tdp_avail to make sure
+ * there is enough tpd to use
+ */
+static struct atl1e_tpd_desc *atl1e_get_tpd(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+ u16 next_to_use = 0;
+
+ next_to_use = tx_ring->next_to_use;
+ if (++tx_ring->next_to_use == tx_ring->count)
+ tx_ring->next_to_use = 0;
+
+ memset(&tx_ring->desc[next_to_use], 0, sizeof(struct atl1e_tpd_desc));
+ return (struct atl1e_tpd_desc *)&tx_ring->desc[next_to_use];
+}
+
+static struct atl1e_tx_buffer *
+atl1e_get_tx_buffer(struct atl1e_adapter *adapter, struct atl1e_tpd_desc *tpd)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+
+ return &tx_ring->tx_buffer[tpd - tx_ring->desc];
+}
+
+static void atl1e_tx_map(struct atl1e_adapter *adapter,
+ struct io_buffer *iob, struct atl1e_tpd_desc *tpd)
+{
+ struct atl1e_tx_buffer *tx_buffer = NULL;
+ u16 buf_len = iob_len(iob);
+
+ tx_buffer = atl1e_get_tx_buffer(adapter, tpd);
+ tx_buffer->iob = iob;
+ tx_buffer->length = buf_len;
+ tx_buffer->dma = virt_to_bus(iob->data);
+ tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
+ tpd->word2 = ((tpd->word2 & ~TPD_BUFLEN_MASK) |
+ ((cpu_to_le32(buf_len) & TPD_BUFLEN_MASK) <<
+ TPD_BUFLEN_SHIFT));
+ tpd->word3 |= 1 << TPD_EOP_SHIFT;
+}
+
+static void atl1e_tx_queue(struct atl1e_adapter *adapter, u16 count __unused,
+ struct atl1e_tpd_desc *tpd __unused)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+ wmb();
+ AT_WRITE_REG(&adapter->hw, REG_MB_TPD_PROD_IDX, tx_ring->next_to_use);
+}
+
+static int atl1e_xmit_frame(struct net_device *netdev, struct io_buffer *iob)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ u16 tpd_req = 1;
+ struct atl1e_tpd_desc *tpd;
+
+ if (!netdev_link_ok(netdev)) {
+ return -EINVAL;
+ }
+
+ if (atl1e_tpd_avail(adapter) < tpd_req) {
+ return -EBUSY;
+ }
+
+ tpd = atl1e_get_tpd(adapter);
+
+ atl1e_tx_map(adapter, iob, tpd);
+ atl1e_tx_queue(adapter, tpd_req, tpd);
+
+ return 0;
+}
+
+int atl1e_up(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int err = 0;
+ u32 val;
+
+ /* hardware has been reset, we need to reload some things */
+ err = atl1e_init_hw(&adapter->hw);
+ if (err) {
+ return -EIO;
+ }
+ atl1e_init_ring_ptrs(adapter);
+
+ memcpy(adapter->hw.mac_addr, netdev->ll_addr, ETH_ALEN);
+
+ if (atl1e_configure(adapter) != 0) {
+ return -EIO;
+ }
+
+ atl1e_irq_disable(adapter);
+
+ val = AT_READ_REG(&adapter->hw, REG_MASTER_CTRL);
+ AT_WRITE_REG(&adapter->hw, REG_MASTER_CTRL,
+ val | MASTER_CTRL_MANUAL_INT);
+
+ return err;
+}
+
+void atl1e_irq(struct net_device *netdev, int enable)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ if (enable)
+ atl1e_irq_enable(adapter);
+ else
+ atl1e_irq_disable(adapter);
+}
+
+void atl1e_down(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ /* reset MAC to disable all RX/TX */
+ atl1e_reset_hw(&adapter->hw);
+ mdelay(1);
+
+ netdev_link_down(netdev);
+ adapter->link_speed = SPEED_0;
+ adapter->link_duplex = -1;
+
+ atl1e_clean_tx_ring(adapter);
+ atl1e_clean_rx_ring(adapter);
+}
+
+/*
+ * atl1e_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP). At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ */
+static int atl1e_open(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ int err;
+
+ /* allocate rx/tx dma buffer & descriptors */
+ atl1e_init_ring_resources(adapter);
+ err = atl1e_setup_ring_resources(adapter);
+ if (err)
+ return err;
+
+ err = atl1e_up(adapter);
+ if (err)
+ goto err_up;
+
+ return 0;
+
+err_up:
+ atl1e_free_ring_resources(adapter);
+ atl1e_reset_hw(&adapter->hw);
+
+ return err;
+}
+
+/*
+ * atl1e_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS. The hardware is still under the drivers control, but
+ * needs to be disabled. A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ */
+static void atl1e_close(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ atl1e_down(adapter);
+ atl1e_free_ring_resources(adapter);
+}
+
+static struct net_device_operations atl1e_netdev_ops = {
+ .open = atl1e_open,
+ .close = atl1e_close,
+ .transmit = atl1e_xmit_frame,
+ .poll = atl1e_poll,
+ .irq = atl1e_irq,
+};
+
+static void atl1e_init_netdev(struct net_device *netdev, struct pci_device *pdev)
+{
+ netdev_init(netdev, &atl1e_netdev_ops);
+
+ netdev->dev = &pdev->dev;
+ pci_set_drvdata(pdev, netdev);
+}
+
+/*
+ * atl1e_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in atl1e_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * atl1e_probe initializes an adapter identified by a pci_device structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ */
+static int atl1e_probe(struct pci_device *pdev)
+{
+ struct net_device *netdev;
+ struct atl1e_adapter *adapter = NULL;
+ static int cards_found;
+
+ int err = 0;
+
+ adjust_pci_device(pdev);
+
+ netdev = alloc_etherdev(sizeof(struct atl1e_adapter));
+ if (netdev == NULL) {
+ err = -ENOMEM;
+ DBG("atl1e: out of memory allocating net_device\n");
+ goto err;
+ }
+
+ atl1e_init_netdev(netdev, pdev);
+
+ adapter = netdev_priv(netdev);
+ adapter->bd_number = cards_found;
+ adapter->netdev = netdev;
+ adapter->pdev = pdev;
+ adapter->hw.adapter = adapter;
+ if (!pdev->membase) {
+ err = -EIO;
+ DBG("atl1e: cannot map device registers\n");
+ goto err_free_netdev;
+ }
+ adapter->hw.hw_addr = bus_to_virt(pdev->membase);
+
+ /* init mii data */
+ adapter->mii.dev = netdev;
+ adapter->mii.mdio_read = atl1e_mdio_read;
+ adapter->mii.mdio_write = atl1e_mdio_write;
+ adapter->mii.phy_id_mask = 0x1f;
+ adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK;
+
+ /* get user settings */
+ adapter->tx_ring.count = TX_DESC_COUNT;
+ adapter->rx_ring.page_size = RX_MEM_SIZE;
+
+ atl1e_setup_pcicmd(pdev);
+
+ /* setup the private structure */
+ err = atl1e_sw_init(adapter);
+ if (err) {
+ DBG("atl1e: private data init failed\n");
+ goto err_free_netdev;
+ }
+
+ /* Init GPHY as early as possible due to power saving issue */
+ atl1e_phy_init(&adapter->hw);
+
+ /* reset the controller to
+ * put the device in a known good starting state */
+ err = atl1e_reset_hw(&adapter->hw);
+ if (err) {
+ err = -EIO;
+ goto err_free_netdev;
+ }
+
+ /* This may have been run by a zero-wait timer around
+ now... unclear. */
+ atl1e_restart_autoneg(&adapter->hw);
+
+ if (atl1e_read_mac_addr(&adapter->hw) != 0) {
+ DBG("atl1e: cannot read MAC address from EEPROM\n");
+ err = -EIO;
+ goto err_free_netdev;
+ }
+
+ memcpy(netdev->hw_addr, adapter->hw.perm_mac_addr, ETH_ALEN);
+ memcpy(netdev->ll_addr, adapter->hw.mac_addr, ETH_ALEN);
+ DBG("atl1e: Attansic L1E Ethernet controller on %s, "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n", adapter->netdev->name,
+ adapter->hw.mac_addr[0], adapter->hw.mac_addr[1],
+ adapter->hw.mac_addr[2], adapter->hw.mac_addr[3],
+ adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]);
+
+ err = register_netdev(netdev);
+ if (err) {
+ DBG("atl1e: cannot register network device\n");
+ goto err_free_netdev;
+ }
+
+ cards_found++;
+ return 0;
+
+err_free_netdev:
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+err:
+ return err;
+}
+
+/*
+ * atl1e_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * atl1e_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device. The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ */
+static void atl1e_remove(struct pci_device *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ unregister_netdev(netdev);
+ atl1e_free_ring_resources(adapter);
+ atl1e_force_ps(&adapter->hw);
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+}
+
+struct pci_driver atl1e_driver __pci_driver = {
+ .ids = atl1e_pci_tbl,
+ .id_count = (sizeof(atl1e_pci_tbl) / sizeof(atl1e_pci_tbl[0])),
+ .probe = atl1e_probe,
+ .remove = atl1e_remove,
+};
+
+/********** Hardware-level functions: **********/
+
+/*
+ * check_eeprom_exist
+ * return 0 if eeprom exist
+ */
+int atl1e_check_eeprom_exist(struct atl1e_hw *hw)
+{
+ u32 value;
+
+ value = AT_READ_REG(hw, REG_SPI_FLASH_CTRL);
+ if (value & SPI_FLASH_CTRL_EN_VPD) {
+ value &= ~SPI_FLASH_CTRL_EN_VPD;
+ AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
+ }
+ value = AT_READ_REGW(hw, REG_PCIE_CAP_LIST);
+ return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
+}
+
+void atl1e_hw_set_mac_addr(struct atl1e_hw *hw)
+{
+ u32 value;
+ /*
+ * 00-0B-6A-F6-00-DC
+ * 0: 6AF600DC 1: 000B
+ * low dword
+ */
+ value = (((u32)hw->mac_addr[2]) << 24) |
+ (((u32)hw->mac_addr[3]) << 16) |
+ (((u32)hw->mac_addr[4]) << 8) |
+ (((u32)hw->mac_addr[5])) ;
+ AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
+ /* hight dword */
+ value = (((u32)hw->mac_addr[0]) << 8) |
+ (((u32)hw->mac_addr[1])) ;
+ AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
+}
+
+/*
+ * atl1e_get_permanent_address
+ * return 0 if get valid mac address,
+ */
+static int atl1e_get_permanent_address(struct atl1e_hw *hw)
+{
+ union {
+ u32 dword[2];
+ u8 byte[8];
+ } hw_addr;
+ u32 i;
+ u32 twsi_ctrl_data;
+ u8 eth_addr[ETH_ALEN];
+
+ if (!atl1e_check_eeprom_exist(hw)) {
+ /* eeprom exist */
+ twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
+ twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
+ AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
+ for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
+ mdelay(10);
+ twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
+ if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
+ break;
+ }
+ if (i >= AT_TWSI_EEPROM_TIMEOUT)
+ return AT_ERR_TIMEOUT;
+ }
+
+ /* maybe MAC-address is from BIOS */
+ hw_addr.dword[0] = AT_READ_REG(hw, REG_MAC_STA_ADDR);
+ hw_addr.dword[1] = AT_READ_REG(hw, REG_MAC_STA_ADDR + 4);
+ for (i = 0; i < ETH_ALEN; i++) {
+ eth_addr[ETH_ALEN - i - 1] = hw_addr.byte[i];
+ }
+
+ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+ return 0;
+}
+
+void atl1e_force_ps(struct atl1e_hw *hw)
+{
+ AT_WRITE_REGW(hw, REG_GPHY_CTRL,
+ GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
+}
+
+/*
+ * Reads the adapter's MAC address from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+int atl1e_read_mac_addr(struct atl1e_hw *hw)
+{
+ int err = 0;
+
+ err = atl1e_get_permanent_address(hw);
+ if (err)
+ return AT_ERR_EEPROM;
+ memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
+ return 0;
+}
+
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+int atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+ u32 val;
+ int i;
+
+ val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+ MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
+ MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+ wmb();
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = AT_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ wmb();
+ }
+ if (!(val & (MDIO_START | MDIO_BUSY))) {
+ *phy_data = (u16)val;
+ return 0;
+ }
+
+ return AT_ERR_PHY;
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+int atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data)
+{
+ int i;
+ u32 val;
+
+ val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
+ (reg_addr&MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+ MDIO_SUP_PREAMBLE |
+ MDIO_START |
+ MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+ wmb();
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = AT_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ wmb();
+ }
+
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ return 0;
+
+ return AT_ERR_PHY;
+}
+
+/*
+ * atl1e_init_pcie - init PCIE module
+ */
+static void atl1e_init_pcie(struct atl1e_hw *hw)
+{
+ u32 value;
+ /* comment 2lines below to save more power when sususpend
+ value = LTSSM_TEST_MODE_DEF;
+ AT_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value);
+ */
+
+ /* pcie flow control mode change */
+ value = AT_READ_REG(hw, 0x1008);
+ value |= 0x8000;
+ AT_WRITE_REG(hw, 0x1008, value);
+}
+/*
+ * Configures PHY autoneg and flow control advertisement settings
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw)
+{
+ s32 ret_val;
+ u16 mii_autoneg_adv_reg;
+ u16 mii_1000t_ctrl_reg;
+
+ if (0 != hw->mii_autoneg_adv_reg)
+ return 0;
+ /* Read the MII Auto-Neg Advertisement Register (Address 4/9). */
+ mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
+ mii_1000t_ctrl_reg = MII_AT001_CR_1000T_DEFAULT_CAP_MASK;
+
+ /*
+ * First we clear all the 10/100 mb speed bits in the Auto-Neg
+ * Advertisement Register (Address 4) and the 1000 mb speed bits in
+ * the 1000Base-T control Register (Address 9).
+ */
+ mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+ mii_1000t_ctrl_reg &= ~MII_AT001_CR_1000T_SPEED_MASK;
+
+ /* Assume auto-detect media type */
+ mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
+ MII_AR_10T_FD_CAPS |
+ MII_AR_100TX_HD_CAPS |
+ MII_AR_100TX_FD_CAPS);
+ if (hw->nic_type == athr_l1e) {
+ mii_1000t_ctrl_reg |= MII_AT001_CR_1000T_FD_CAPS;
+ }
+
+ /* flow control fixed to enable all */
+ mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+
+ hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
+ hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
+
+ ret_val = atl1e_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
+ if (ret_val)
+ return ret_val;
+
+ if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
+ ret_val = atl1e_write_phy_reg(hw, MII_AT001_CR,
+ mii_1000t_ctrl_reg);
+ if (ret_val)
+ return ret_val;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Resets the PHY and make all config validate
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sets bit 15 and 12 of the MII control regiser (for F001 bug)
+ */
+int atl1e_phy_commit(struct atl1e_hw *hw)
+{
+ int ret_val;
+ u16 phy_data;
+
+ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG;
+
+ ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data);
+ if (ret_val) {
+ u32 val;
+ int i;
+ /**************************************
+ * pcie serdes link may be down !
+ **************************************/
+ for (i = 0; i < 25; i++) {
+ mdelay(1);
+ val = AT_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ }
+
+ if (0 != (val & (MDIO_START | MDIO_BUSY))) {
+ DBG("atl1e: PCI-E link down for at least 25ms\n");
+ return ret_val;
+ }
+
+ DBG("atl1e: PCI-E link up after %d ms\n", i);
+ }
+ return 0;
+}
+
+int atl1e_phy_init(struct atl1e_hw *hw)
+{
+ s32 ret_val;
+ u16 phy_val;
+
+ if (hw->phy_configured) {
+ if (hw->re_autoneg) {
+ hw->re_autoneg = 0;
+ return atl1e_restart_autoneg(hw);
+ }
+ return 0;
+ }
+
+ /* RESET GPHY Core */
+ AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
+ mdelay(2);
+ AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
+ GPHY_CTRL_EXT_RESET);
+ mdelay(2);
+
+ /* patches */
+ /* p1. eable hibernation mode */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0xB);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0xBC00);
+ if (ret_val)
+ return ret_val;
+ /* p2. set Class A/B for all modes */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0);
+ if (ret_val)
+ return ret_val;
+ phy_val = 0x02ef;
+ /* remove Class AB */
+ /* phy_val = hw->emi_ca ? 0x02ef : 0x02df; */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, phy_val);
+ if (ret_val)
+ return ret_val;
+ /* p3. 10B ??? */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x12);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x4C04);
+ if (ret_val)
+ return ret_val;
+ /* p4. 1000T power */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x4);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x8BBB);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x5);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x2C46);
+ if (ret_val)
+ return ret_val;
+
+ mdelay(1);
+
+ /*Enable PHY LinkChange Interrupt */
+ ret_val = atl1e_write_phy_reg(hw, MII_INT_CTRL, 0xC00);
+ if (ret_val) {
+ DBG("atl1e: Error enable PHY linkChange Interrupt\n");
+ return ret_val;
+ }
+ /* setup AutoNeg parameters */
+ ret_val = atl1e_phy_setup_autoneg_adv(hw);
+ if (ret_val) {
+ DBG("atl1e: Error Setting up Auto-Negotiation\n");
+ return ret_val;
+ }
+ /* SW.Reset & En-Auto-Neg to restart Auto-Neg*/
+ DBG("atl1e: Restarting Auto-Neg");
+ ret_val = atl1e_phy_commit(hw);
+ if (ret_val) {
+ DBG("atl1e: Error Resetting the phy");
+ return ret_val;
+ }
+
+ hw->phy_configured = 1;
+
+ return 0;
+}
+
+/*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ * hw - Struct containing variables accessed by shared code
+ * return : 0 or idle status (if error)
+ */
+int atl1e_reset_hw(struct atl1e_hw *hw)
+{
+ struct atl1e_adapter *adapter = hw->adapter;
+ struct pci_device *pdev = adapter->pdev;
+ int timeout = 0;
+ u32 idle_status_data = 0;
+ u16 pci_cfg_cmd_word = 0;
+
+ /* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_cfg_cmd_word);
+ if ((pci_cfg_cmd_word & (PCI_COMMAND_IO | PCI_COMMAND_MEM |
+ PCI_COMMAND_MASTER))
+ != (PCI_COMMAND_IO | PCI_COMMAND_MEM |
+ PCI_COMMAND_MASTER)) {
+ pci_cfg_cmd_word |= (PCI_COMMAND_IO | PCI_COMMAND_MEM |
+ PCI_COMMAND_MASTER);
+ pci_write_config_word(pdev, PCI_COMMAND, pci_cfg_cmd_word);
+ }
+
+ /*
+ * Issue Soft Reset to the MAC. This will reset the chip's
+ * transmit, receive, DMA. It will not effect
+ * the current PCI configuration. The global reset bit is self-
+ * clearing, and should clear within a microsecond.
+ */
+ AT_WRITE_REG(hw, REG_MASTER_CTRL,
+ MASTER_CTRL_LED_MODE | MASTER_CTRL_SOFT_RST);
+ wmb();
+ mdelay(1);
+
+ /* Wait at least 10ms for All module to be Idle */
+ for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+ idle_status_data = AT_READ_REG(hw, REG_IDLE_STATUS);
+ if (idle_status_data == 0)
+ break;
+ mdelay(1);
+ }
+
+ if (timeout >= AT_HW_MAX_IDLE_DELAY) {
+ DBG("atl1e: MAC reset timeout\n");
+ return AT_ERR_TIMEOUT;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Performs basic configuration of the adapter.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * Assumes that the controller has previously been reset and is in a
+ * post-reset uninitialized state. Initializes multicast table,
+ * and Calls routines to setup link
+ * Leaves the transmit and receive units disabled and uninitialized.
+ */
+int atl1e_init_hw(struct atl1e_hw *hw)
+{
+ s32 ret_val = 0;
+
+ atl1e_init_pcie(hw);
+
+ /* Zero out the Multicast HASH table */
+ /* clear the old settings from the multicast hash table */
+ AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+ AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+ ret_val = atl1e_phy_init(hw);
+
+ return ret_val;
+}
+
+/*
+ * Detects the current speed and duplex settings of the hardware.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+int atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex)
+{
+ int err;
+ u16 phy_data;
+
+ /* Read PHY Specific Status Register (17) */
+ err = atl1e_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
+ if (err)
+ return err;
+
+ if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED))
+ return AT_ERR_PHY_RES;
+
+ switch (phy_data & MII_AT001_PSSR_SPEED) {
+ case MII_AT001_PSSR_1000MBS:
+ *speed = SPEED_1000;
+ break;
+ case MII_AT001_PSSR_100MBS:
+ *speed = SPEED_100;
+ break;
+ case MII_AT001_PSSR_10MBS:
+ *speed = SPEED_10;
+ break;
+ default:
+ return AT_ERR_PHY_SPEED;
+ break;
+ }
+
+ if (phy_data & MII_AT001_PSSR_DPLX)
+ *duplex = FULL_DUPLEX;
+ else
+ *duplex = HALF_DUPLEX;
+
+ return 0;
+}
+
+int atl1e_restart_autoneg(struct atl1e_hw *hw)
+{
+ int err = 0;
+
+ err = atl1e_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+ if (err)
+ return err;
+
+ if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
+ err = atl1e_write_phy_reg(hw, MII_AT001_CR,
+ hw->mii_1000t_ctrl_reg);
+ if (err)
+ return err;
+ }
+
+ err = atl1e_write_phy_reg(hw, MII_BMCR,
+ MII_CR_RESET | MII_CR_AUTO_NEG_EN |
+ MII_CR_RESTART_AUTO_NEG);
+ return err;
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/atl1e.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/atl1e.h
new file mode 100644
index 00000000..e759ea49
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/atl1e.h
@@ -0,0 +1,1033 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ * Copyright(c) 2007 xiong huang <xiong.huang@atheros.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * Modified for iPXE, October 2009 by Joshua Oreman <oremanj@rwcr.net>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef _ATL1E_H_
+#define _ATL1E_H_
+
+#include <mii.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/malloc.h>
+#include <ipxe/pci.h>
+#include <ipxe/pci_io.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/io.h>
+
+#define ETH_FCS_LEN 4
+#define VLAN_HLEN 4
+#define NET_IP_ALIGN 2
+
+#define SPEED_0 0xffff
+#define SPEED_10 10
+#define SPEED_100 100
+#define SPEED_1000 1000
+#define HALF_DUPLEX 1
+#define FULL_DUPLEX 2
+
+/* Error Codes */
+#define AT_ERR_EEPROM 1
+#define AT_ERR_PHY 2
+#define AT_ERR_CONFIG 3
+#define AT_ERR_PARAM 4
+#define AT_ERR_MAC_TYPE 5
+#define AT_ERR_PHY_TYPE 6
+#define AT_ERR_PHY_SPEED 7
+#define AT_ERR_PHY_RES 8
+#define AT_ERR_TIMEOUT 9
+
+#define AT_MAX_RECEIVE_QUEUE 4
+#define AT_PAGE_NUM_PER_QUEUE 2
+
+#define AT_TWSI_EEPROM_TIMEOUT 100
+#define AT_HW_MAX_IDLE_DELAY 10
+
+#define AT_REGS_LEN 75
+#define AT_EEPROM_LEN 512
+
+/* tpd word 2 */
+#define TPD_BUFLEN_MASK 0x3FFF
+#define TPD_BUFLEN_SHIFT 0
+
+/* tpd word 3 bits 0:4 */
+#define TPD_EOP_MASK 0x0001
+#define TPD_EOP_SHIFT 0
+
+struct atl1e_tpd_desc {
+ u64 buffer_addr;
+ u32 word2;
+ u32 word3;
+};
+
+#define MAX_TX_BUF_LEN 0x2000
+#define MAX_TX_BUF_SHIFT 13
+
+/* rrs word 1 bit 0:31 */
+#define RRS_RX_CSUM_MASK 0xFFFF
+#define RRS_RX_CSUM_SHIFT 0
+#define RRS_PKT_SIZE_MASK 0x3FFF
+#define RRS_PKT_SIZE_SHIFT 16
+#define RRS_CPU_NUM_MASK 0x0003
+#define RRS_CPU_NUM_SHIFT 30
+
+#define RRS_IS_RSS_IPV4 0x0001
+#define RRS_IS_RSS_IPV4_TCP 0x0002
+#define RRS_IS_RSS_IPV6 0x0004
+#define RRS_IS_RSS_IPV6_TCP 0x0008
+#define RRS_IS_IPV6 0x0010
+#define RRS_IS_IP_FRAG 0x0020
+#define RRS_IS_IP_DF 0x0040
+#define RRS_IS_802_3 0x0080
+#define RRS_IS_VLAN_TAG 0x0100
+#define RRS_IS_ERR_FRAME 0x0200
+#define RRS_IS_IPV4 0x0400
+#define RRS_IS_UDP 0x0800
+#define RRS_IS_TCP 0x1000
+#define RRS_IS_BCAST 0x2000
+#define RRS_IS_MCAST 0x4000
+#define RRS_IS_PAUSE 0x8000
+
+#define RRS_ERR_BAD_CRC 0x0001
+#define RRS_ERR_CODE 0x0002
+#define RRS_ERR_DRIBBLE 0x0004
+#define RRS_ERR_RUNT 0x0008
+#define RRS_ERR_RX_OVERFLOW 0x0010
+#define RRS_ERR_TRUNC 0x0020
+#define RRS_ERR_IP_CSUM 0x0040
+#define RRS_ERR_L4_CSUM 0x0080
+#define RRS_ERR_LENGTH 0x0100
+#define RRS_ERR_DES_ADDR 0x0200
+
+struct atl1e_recv_ret_status {
+ u16 seq_num;
+ u16 hash_lo;
+ u32 word1;
+ u16 pkt_flag;
+ u16 err_flag;
+ u16 hash_hi;
+ u16 vtag;
+};
+
+enum atl1e_dma_req_block {
+ atl1e_dma_req_128 = 0,
+ atl1e_dma_req_256 = 1,
+ atl1e_dma_req_512 = 2,
+ atl1e_dma_req_1024 = 3,
+ atl1e_dma_req_2048 = 4,
+ atl1e_dma_req_4096 = 5
+};
+
+enum atl1e_nic_type {
+ athr_l1e = 0,
+ athr_l2e_revA = 1,
+ athr_l2e_revB = 2
+};
+
+struct atl1e_hw {
+ u8 *hw_addr; /* inner register address */
+ struct atl1e_adapter *adapter;
+ enum atl1e_nic_type nic_type;
+ u8 mac_addr[ETH_ALEN];
+ u8 perm_mac_addr[ETH_ALEN];
+
+ u16 mii_autoneg_adv_reg;
+ u16 mii_1000t_ctrl_reg;
+
+ enum atl1e_dma_req_block dmar_block;
+ enum atl1e_dma_req_block dmaw_block;
+
+ int phy_configured;
+ int re_autoneg;
+ int emi_ca;
+};
+
+/*
+ * wrapper around a pointer to a socket buffer,
+ * so a DMA handle can be stored along with the buffer
+ */
+struct atl1e_tx_buffer {
+ struct io_buffer *iob;
+ u16 length;
+ u32 dma;
+};
+
+struct atl1e_rx_page {
+ u32 dma; /* receive rage DMA address */
+ u8 *addr; /* receive rage virtual address */
+ u32 write_offset_dma; /* the DMA address which contain the
+ receive data offset in the page */
+ u32 *write_offset_addr; /* the virtaul address which contain
+ the receive data offset in the page */
+ u32 read_offset; /* the offset where we have read */
+};
+
+struct atl1e_rx_page_desc {
+ struct atl1e_rx_page rx_page[AT_PAGE_NUM_PER_QUEUE];
+ u8 rx_using;
+ u16 rx_nxseq;
+};
+
+/* transmit packet descriptor (tpd) ring */
+struct atl1e_tx_ring {
+ struct atl1e_tpd_desc *desc; /* descriptor ring virtual address */
+ u32 dma; /* descriptor ring physical address */
+ u16 count; /* the count of transmit rings */
+ u16 next_to_use;
+ u16 next_to_clean;
+ struct atl1e_tx_buffer *tx_buffer;
+ u32 cmb_dma;
+ u32 *cmb;
+};
+
+/* receive packet descriptor ring */
+struct atl1e_rx_ring {
+ void *desc;
+ u32 dma;
+ int size;
+ u32 page_size; /* bytes length of rxf page */
+ u32 real_page_size; /* real_page_size = page_size + jumbo + aliagn */
+ struct atl1e_rx_page_desc rx_page_desc;
+};
+
+/* board specific private data structure */
+struct atl1e_adapter {
+ struct net_device *netdev;
+ struct pci_device *pdev;
+ struct mii_if_info mii; /* MII interface info */
+ struct atl1e_hw hw;
+
+ u16 link_speed;
+ u16 link_duplex;
+
+ /* All Descriptor memory */
+ u32 ring_dma;
+ void *ring_vir_addr;
+ u32 ring_size;
+
+ struct atl1e_tx_ring tx_ring;
+ struct atl1e_rx_ring rx_ring;
+
+ int bd_number; /* board number;*/
+};
+
+#define AT_WRITE_REG(a, reg, value) \
+ writel((value), ((a)->hw_addr + reg))
+
+#define AT_WRITE_FLUSH(a) \
+ readl((a)->hw_addr)
+
+#define AT_READ_REG(a, reg) \
+ readl((a)->hw_addr + reg)
+
+#define AT_WRITE_REGB(a, reg, value) \
+ writeb((value), ((a)->hw_addr + reg))
+
+#define AT_READ_REGB(a, reg) \
+ readb((a)->hw_addr + reg)
+
+#define AT_WRITE_REGW(a, reg, value) \
+ writew((value), ((a)->hw_addr + reg))
+
+#define AT_READ_REGW(a, reg) \
+ readw((a)->hw_addr + reg)
+
+#define AT_WRITE_REG_ARRAY(a, reg, offset, value) \
+ writel((value), (((a)->hw_addr + reg) + ((offset) << 2)))
+
+#define AT_READ_REG_ARRAY(a, reg, offset) \
+ readl(((a)->hw_addr + reg) + ((offset) << 2))
+
+extern int atl1e_up(struct atl1e_adapter *adapter);
+extern void atl1e_down(struct atl1e_adapter *adapter);
+extern s32 atl1e_reset_hw(struct atl1e_hw *hw);
+
+/********** Hardware-level functionality: **********/
+
+/* function prototype */
+s32 atl1e_reset_hw(struct atl1e_hw *hw);
+s32 atl1e_read_mac_addr(struct atl1e_hw *hw);
+s32 atl1e_init_hw(struct atl1e_hw *hw);
+s32 atl1e_phy_commit(struct atl1e_hw *hw);
+s32 atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex);
+u32 atl1e_auto_get_fc(struct atl1e_adapter *adapter, u16 duplex);
+s32 atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data);
+s32 atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data);
+s32 atl1e_validate_mdi_setting(struct atl1e_hw *hw);
+void atl1e_hw_set_mac_addr(struct atl1e_hw *hw);
+s32 atl1e_phy_enter_power_saving(struct atl1e_hw *hw);
+s32 atl1e_phy_leave_power_saving(struct atl1e_hw *hw);
+s32 atl1e_phy_init(struct atl1e_hw *hw);
+int atl1e_check_eeprom_exist(struct atl1e_hw *hw);
+void atl1e_force_ps(struct atl1e_hw *hw);
+s32 atl1e_restart_autoneg(struct atl1e_hw *hw);
+
+/* register definition */
+#define REG_PM_CTRLSTAT 0x44
+
+#define REG_PCIE_CAP_LIST 0x58
+
+#define REG_DEVICE_CAP 0x5C
+#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7
+#define DEVICE_CAP_MAX_PAYLOAD_SHIFT 0
+
+#define REG_DEVICE_CTRL 0x60
+#define DEVICE_CTRL_MAX_PAYLOAD_MASK 0x7
+#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT 5
+#define DEVICE_CTRL_MAX_RREQ_SZ_MASK 0x7
+#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT 12
+
+#define REG_VPD_CAP 0x6C
+#define VPD_CAP_ID_MASK 0xff
+#define VPD_CAP_ID_SHIFT 0
+#define VPD_CAP_NEXT_PTR_MASK 0xFF
+#define VPD_CAP_NEXT_PTR_SHIFT 8
+#define VPD_CAP_VPD_ADDR_MASK 0x7FFF
+#define VPD_CAP_VPD_ADDR_SHIFT 16
+#define VPD_CAP_VPD_FLAG 0x80000000
+
+#define REG_VPD_DATA 0x70
+
+#define REG_SPI_FLASH_CTRL 0x200
+#define SPI_FLASH_CTRL_STS_NON_RDY 0x1
+#define SPI_FLASH_CTRL_STS_WEN 0x2
+#define SPI_FLASH_CTRL_STS_WPEN 0x80
+#define SPI_FLASH_CTRL_DEV_STS_MASK 0xFF
+#define SPI_FLASH_CTRL_DEV_STS_SHIFT 0
+#define SPI_FLASH_CTRL_INS_MASK 0x7
+#define SPI_FLASH_CTRL_INS_SHIFT 8
+#define SPI_FLASH_CTRL_START 0x800
+#define SPI_FLASH_CTRL_EN_VPD 0x2000
+#define SPI_FLASH_CTRL_LDSTART 0x8000
+#define SPI_FLASH_CTRL_CS_HI_MASK 0x3
+#define SPI_FLASH_CTRL_CS_HI_SHIFT 16
+#define SPI_FLASH_CTRL_CS_HOLD_MASK 0x3
+#define SPI_FLASH_CTRL_CS_HOLD_SHIFT 18
+#define SPI_FLASH_CTRL_CLK_LO_MASK 0x3
+#define SPI_FLASH_CTRL_CLK_LO_SHIFT 20
+#define SPI_FLASH_CTRL_CLK_HI_MASK 0x3
+#define SPI_FLASH_CTRL_CLK_HI_SHIFT 22
+#define SPI_FLASH_CTRL_CS_SETUP_MASK 0x3
+#define SPI_FLASH_CTRL_CS_SETUP_SHIFT 24
+#define SPI_FLASH_CTRL_EROM_PGSZ_MASK 0x3
+#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT 26
+#define SPI_FLASH_CTRL_WAIT_READY 0x10000000
+
+#define REG_SPI_ADDR 0x204
+
+#define REG_SPI_DATA 0x208
+
+#define REG_SPI_FLASH_CONFIG 0x20C
+#define SPI_FLASH_CONFIG_LD_ADDR_MASK 0xFFFFFF
+#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT 0
+#define SPI_FLASH_CONFIG_VPD_ADDR_MASK 0x3
+#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24
+#define SPI_FLASH_CONFIG_LD_EXIST 0x4000000
+
+
+#define REG_SPI_FLASH_OP_PROGRAM 0x210
+#define REG_SPI_FLASH_OP_SC_ERASE 0x211
+#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212
+#define REG_SPI_FLASH_OP_RDID 0x213
+#define REG_SPI_FLASH_OP_WREN 0x214
+#define REG_SPI_FLASH_OP_RDSR 0x215
+#define REG_SPI_FLASH_OP_WRSR 0x216
+#define REG_SPI_FLASH_OP_READ 0x217
+
+#define REG_TWSI_CTRL 0x218
+#define TWSI_CTRL_LD_OFFSET_MASK 0xFF
+#define TWSI_CTRL_LD_OFFSET_SHIFT 0
+#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7
+#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8
+#define TWSI_CTRL_SW_LDSTART 0x800
+#define TWSI_CTRL_HW_LDSTART 0x1000
+#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x0x7F
+#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15
+#define TWSI_CTRL_LD_EXIST 0x400000
+#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3
+#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23
+#define TWSI_CTRL_FREQ_SEL_100K 0
+#define TWSI_CTRL_FREQ_SEL_200K 1
+#define TWSI_CTRL_FREQ_SEL_300K 2
+#define TWSI_CTRL_FREQ_SEL_400K 3
+#define TWSI_CTRL_SMB_SLV_ADDR
+#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3
+#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24
+
+
+#define REG_PCIE_DEV_MISC_CTRL 0x21C
+#define PCIE_DEV_MISC_CTRL_EXT_PIPE 0x2
+#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1
+#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4
+#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN 0x8
+#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN 0x10
+
+#define REG_PCIE_PHYMISC 0x1000
+#define PCIE_PHYMISC_FORCE_RCV_DET 0x4
+
+#define REG_LTSSM_TEST_MODE 0x12FC
+#define LTSSM_TEST_MODE_DEF 0xE000
+
+/* Selene Master Control Register */
+#define REG_MASTER_CTRL 0x1400
+#define MASTER_CTRL_SOFT_RST 0x1
+#define MASTER_CTRL_MTIMER_EN 0x2
+#define MASTER_CTRL_ITIMER_EN 0x4
+#define MASTER_CTRL_MANUAL_INT 0x8
+#define MASTER_CTRL_ITIMER2_EN 0x20
+#define MASTER_CTRL_INT_RDCLR 0x40
+#define MASTER_CTRL_LED_MODE 0x200
+#define MASTER_CTRL_REV_NUM_SHIFT 16
+#define MASTER_CTRL_REV_NUM_MASK 0xff
+#define MASTER_CTRL_DEV_ID_SHIFT 24
+#define MASTER_CTRL_DEV_ID_MASK 0xff
+
+/* Timer Initial Value Register */
+#define REG_MANUAL_TIMER_INIT 0x1404
+
+
+/* IRQ ModeratorTimer Initial Value Register */
+#define REG_IRQ_MODU_TIMER_INIT 0x1408 /* w */
+#define REG_IRQ_MODU_TIMER2_INIT 0x140A /* w */
+
+
+#define REG_GPHY_CTRL 0x140C
+#define GPHY_CTRL_EXT_RESET 1
+#define GPHY_CTRL_PIPE_MOD 2
+#define GPHY_CTRL_TEST_MODE_MASK 3
+#define GPHY_CTRL_TEST_MODE_SHIFT 2
+#define GPHY_CTRL_BERT_START 0x10
+#define GPHY_CTRL_GATE_25M_EN 0x20
+#define GPHY_CTRL_LPW_EXIT 0x40
+#define GPHY_CTRL_PHY_IDDQ 0x80
+#define GPHY_CTRL_PHY_IDDQ_DIS 0x100
+#define GPHY_CTRL_PCLK_SEL_DIS 0x200
+#define GPHY_CTRL_HIB_EN 0x400
+#define GPHY_CTRL_HIB_PULSE 0x800
+#define GPHY_CTRL_SEL_ANA_RST 0x1000
+#define GPHY_CTRL_PHY_PLL_ON 0x2000
+#define GPHY_CTRL_PWDOWN_HW 0x4000
+#define GPHY_CTRL_DEFAULT (\
+ GPHY_CTRL_PHY_PLL_ON |\
+ GPHY_CTRL_SEL_ANA_RST |\
+ GPHY_CTRL_HIB_PULSE |\
+ GPHY_CTRL_HIB_EN)
+
+#define GPHY_CTRL_PW_WOL_DIS (\
+ GPHY_CTRL_PHY_PLL_ON |\
+ GPHY_CTRL_SEL_ANA_RST |\
+ GPHY_CTRL_HIB_PULSE |\
+ GPHY_CTRL_HIB_EN |\
+ GPHY_CTRL_PWDOWN_HW |\
+ GPHY_CTRL_PCLK_SEL_DIS |\
+ GPHY_CTRL_PHY_IDDQ)
+
+/* IRQ Anti-Lost Timer Initial Value Register */
+#define REG_CMBDISDMA_TIMER 0x140E
+
+
+/* Block IDLE Status Register */
+#define REG_IDLE_STATUS 0x1410
+#define IDLE_STATUS_RXMAC 1 /* 1: RXMAC state machine is in non-IDLE state. 0: RXMAC is idling */
+#define IDLE_STATUS_TXMAC 2 /* 1: TXMAC state machine is in non-IDLE state. 0: TXMAC is idling */
+#define IDLE_STATUS_RXQ 4 /* 1: RXQ state machine is in non-IDLE state. 0: RXQ is idling */
+#define IDLE_STATUS_TXQ 8 /* 1: TXQ state machine is in non-IDLE state. 0: TXQ is idling */
+#define IDLE_STATUS_DMAR 0x10 /* 1: DMAR state machine is in non-IDLE state. 0: DMAR is idling */
+#define IDLE_STATUS_DMAW 0x20 /* 1: DMAW state machine is in non-IDLE state. 0: DMAW is idling */
+#define IDLE_STATUS_SMB 0x40 /* 1: SMB state machine is in non-IDLE state. 0: SMB is idling */
+#define IDLE_STATUS_CMB 0x80 /* 1: CMB state machine is in non-IDLE state. 0: CMB is idling */
+
+/* MDIO Control Register */
+#define REG_MDIO_CTRL 0x1414
+#define MDIO_DATA_MASK 0xffff /* On MDIO write, the 16-bit control data to write to PHY MII management register */
+#define MDIO_DATA_SHIFT 0 /* On MDIO read, the 16-bit status data that was read from the PHY MII management register*/
+#define MDIO_REG_ADDR_MASK 0x1f /* MDIO register address */
+#define MDIO_REG_ADDR_SHIFT 16
+#define MDIO_RW 0x200000 /* 1: read, 0: write */
+#define MDIO_SUP_PREAMBLE 0x400000 /* Suppress preamble */
+#define MDIO_START 0x800000 /* Write 1 to initiate the MDIO master. And this bit is self cleared after one cycle*/
+#define MDIO_CLK_SEL_SHIFT 24
+#define MDIO_CLK_25_4 0
+#define MDIO_CLK_25_6 2
+#define MDIO_CLK_25_8 3
+#define MDIO_CLK_25_10 4
+#define MDIO_CLK_25_14 5
+#define MDIO_CLK_25_20 6
+#define MDIO_CLK_25_28 7
+#define MDIO_BUSY 0x8000000
+#define MDIO_AP_EN 0x10000000
+#define MDIO_WAIT_TIMES 10
+
+/* MII PHY Status Register */
+#define REG_PHY_STATUS 0x1418
+#define PHY_STATUS_100M 0x20000
+#define PHY_STATUS_EMI_CA 0x40000
+
+/* BIST Control and Status Register0 (for the Packet Memory) */
+#define REG_BIST0_CTRL 0x141c
+#define BIST0_NOW 0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
+/* BIST process and reset to zero when BIST is done */
+#define BIST0_SRAM_FAIL 0x2 /* 1: The SRAM failure is un-repairable because it has address */
+/* decoder failure or more than 1 cell stuck-to-x failure */
+#define BIST0_FUSE_FLAG 0x4 /* 1: Indicating one cell has been fixed */
+
+/* BIST Control and Status Register1(for the retry buffer of PCI Express) */
+#define REG_BIST1_CTRL 0x1420
+#define BIST1_NOW 0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
+/* BIST process and reset to zero when BIST is done */
+#define BIST1_SRAM_FAIL 0x2 /* 1: The SRAM failure is un-repairable because it has address */
+/* decoder failure or more than 1 cell stuck-to-x failure.*/
+#define BIST1_FUSE_FLAG 0x4
+
+/* SerDes Lock Detect Control and Status Register */
+#define REG_SERDES_LOCK 0x1424
+#define SERDES_LOCK_DETECT 1 /* 1: SerDes lock detected . This signal comes from Analog SerDes */
+#define SERDES_LOCK_DETECT_EN 2 /* 1: Enable SerDes Lock detect function */
+
+/* MAC Control Register */
+#define REG_MAC_CTRL 0x1480
+#define MAC_CTRL_TX_EN 1 /* 1: Transmit Enable */
+#define MAC_CTRL_RX_EN 2 /* 1: Receive Enable */
+#define MAC_CTRL_TX_FLOW 4 /* 1: Transmit Flow Control Enable */
+#define MAC_CTRL_RX_FLOW 8 /* 1: Receive Flow Control Enable */
+#define MAC_CTRL_LOOPBACK 0x10 /* 1: Loop back at G/MII Interface */
+#define MAC_CTRL_DUPLX 0x20 /* 1: Full-duplex mode 0: Half-duplex mode */
+#define MAC_CTRL_ADD_CRC 0x40 /* 1: Instruct MAC to attach CRC on all egress Ethernet frames */
+#define MAC_CTRL_PAD 0x80 /* 1: Instruct MAC to pad short frames to 60-bytes, and then attach CRC. This bit has higher priority over CRC_EN */
+#define MAC_CTRL_LENCHK 0x100 /* 1: Instruct MAC to check if length field matches the real packet length */
+#define MAC_CTRL_HUGE_EN 0x200 /* 1: receive Jumbo frame enable */
+#define MAC_CTRL_PRMLEN_SHIFT 10 /* Preamble length */
+#define MAC_CTRL_PRMLEN_MASK 0xf
+#define MAC_CTRL_RMV_VLAN 0x4000 /* 1: to remove VLAN Tag automatically from all receive packets */
+#define MAC_CTRL_PROMIS_EN 0x8000 /* 1: Promiscuous Mode Enable */
+#define MAC_CTRL_TX_PAUSE 0x10000 /* 1: transmit test pause */
+#define MAC_CTRL_SCNT 0x20000 /* 1: shortcut slot time counter */
+#define MAC_CTRL_SRST_TX 0x40000 /* 1: synchronized reset Transmit MAC module */
+#define MAC_CTRL_TX_SIMURST 0x80000 /* 1: transmit simulation reset */
+#define MAC_CTRL_SPEED_SHIFT 20 /* 10: gigabit 01:10M/100M */
+#define MAC_CTRL_SPEED_MASK 0x300000
+#define MAC_CTRL_SPEED_1000 2
+#define MAC_CTRL_SPEED_10_100 1
+#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000 /* 1: transmit maximum backoff (half-duplex test bit) */
+#define MAC_CTRL_TX_HUGE 0x800000 /* 1: transmit huge enable */
+#define MAC_CTRL_RX_CHKSUM_EN 0x1000000 /* 1: RX checksum enable */
+#define MAC_CTRL_MC_ALL_EN 0x2000000 /* 1: upload all multicast frame without error to system */
+#define MAC_CTRL_BC_EN 0x4000000 /* 1: upload all broadcast frame without error to system */
+#define MAC_CTRL_DBG 0x8000000 /* 1: upload all received frame to system (Debug Mode) */
+
+/* MAC IPG/IFG Control Register */
+#define REG_MAC_IPG_IFG 0x1484
+#define MAC_IPG_IFG_IPGT_SHIFT 0 /* Desired back to back inter-packet gap. The default is 96-bit time */
+#define MAC_IPG_IFG_IPGT_MASK 0x7f
+#define MAC_IPG_IFG_MIFG_SHIFT 8 /* Minimum number of IFG to enforce in between RX frames */
+#define MAC_IPG_IFG_MIFG_MASK 0xff /* Frame gap below such IFP is dropped */
+#define MAC_IPG_IFG_IPGR1_SHIFT 16 /* 64bit Carrier-Sense window */
+#define MAC_IPG_IFG_IPGR1_MASK 0x7f
+#define MAC_IPG_IFG_IPGR2_SHIFT 24 /* 96-bit IPG window */
+#define MAC_IPG_IFG_IPGR2_MASK 0x7f
+
+/* MAC STATION ADDRESS */
+#define REG_MAC_STA_ADDR 0x1488
+
+/* Hash table for multicast address */
+#define REG_RX_HASH_TABLE 0x1490
+
+
+/* MAC Half-Duplex Control Register */
+#define REG_MAC_HALF_DUPLX_CTRL 0x1498
+#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT 0 /* Collision Window */
+#define MAC_HALF_DUPLX_CTRL_LCOL_MASK 0x3ff
+#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12 /* Retransmission maximum, afterwards the packet will be discarded */
+#define MAC_HALF_DUPLX_CTRL_RETRY_MASK 0xf
+#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN 0x10000 /* 1: Allow the transmission of a packet which has been excessively deferred */
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_C 0x20000 /* 1: No back-off on collision, immediately start the retransmission */
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_P 0x40000 /* 1: No back-off on backpressure, immediately start the transmission after back pressure */
+#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */
+#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20 /* Maximum binary exponential number */
+#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xf
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24 /* IPG to start JAM for collision based flow control in half-duplex */
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xf /* mode. In unit of 8-bit time */
+
+/* Maximum Frame Length Control Register */
+#define REG_MTU 0x149c
+
+/* Wake-On-Lan control register */
+#define REG_WOL_CTRL 0x14a0
+#define WOL_PATTERN_EN 0x00000001
+#define WOL_PATTERN_PME_EN 0x00000002
+#define WOL_MAGIC_EN 0x00000004
+#define WOL_MAGIC_PME_EN 0x00000008
+#define WOL_LINK_CHG_EN 0x00000010
+#define WOL_LINK_CHG_PME_EN 0x00000020
+#define WOL_PATTERN_ST 0x00000100
+#define WOL_MAGIC_ST 0x00000200
+#define WOL_LINKCHG_ST 0x00000400
+#define WOL_CLK_SWITCH_EN 0x00008000
+#define WOL_PT0_EN 0x00010000
+#define WOL_PT1_EN 0x00020000
+#define WOL_PT2_EN 0x00040000
+#define WOL_PT3_EN 0x00080000
+#define WOL_PT4_EN 0x00100000
+#define WOL_PT5_EN 0x00200000
+#define WOL_PT6_EN 0x00400000
+/* WOL Length ( 2 DWORD ) */
+#define REG_WOL_PATTERN_LEN 0x14a4
+#define WOL_PT_LEN_MASK 0x7f
+#define WOL_PT0_LEN_SHIFT 0
+#define WOL_PT1_LEN_SHIFT 8
+#define WOL_PT2_LEN_SHIFT 16
+#define WOL_PT3_LEN_SHIFT 24
+#define WOL_PT4_LEN_SHIFT 0
+#define WOL_PT5_LEN_SHIFT 8
+#define WOL_PT6_LEN_SHIFT 16
+
+/* Internal SRAM Partition Register */
+#define REG_SRAM_TRD_ADDR 0x1518
+#define REG_SRAM_TRD_LEN 0x151C
+#define REG_SRAM_RXF_ADDR 0x1520
+#define REG_SRAM_RXF_LEN 0x1524
+#define REG_SRAM_TXF_ADDR 0x1528
+#define REG_SRAM_TXF_LEN 0x152C
+#define REG_SRAM_TCPH_ADDR 0x1530
+#define REG_SRAM_PKTH_ADDR 0x1532
+
+/* Load Ptr Register */
+#define REG_LOAD_PTR 0x1534 /* Software sets this bit after the initialization of the head and tail */
+
+/*
+ * addresses of all descriptors, as well as the following descriptor
+ * control register, which triggers each function block to load the head
+ * pointer to prepare for the operation. This bit is then self-cleared
+ * after one cycle.
+ */
+
+/* Descriptor Control register */
+#define REG_RXF3_BASE_ADDR_HI 0x153C
+#define REG_DESC_BASE_ADDR_HI 0x1540
+#define REG_RXF0_BASE_ADDR_HI 0x1540 /* share with DESC BASE ADDR HI */
+#define REG_HOST_RXF0_PAGE0_LO 0x1544
+#define REG_HOST_RXF0_PAGE1_LO 0x1548
+#define REG_TPD_BASE_ADDR_LO 0x154C
+#define REG_RXF1_BASE_ADDR_HI 0x1550
+#define REG_RXF2_BASE_ADDR_HI 0x1554
+#define REG_HOST_RXFPAGE_SIZE 0x1558
+#define REG_TPD_RING_SIZE 0x155C
+/* RSS about */
+#define REG_RSS_KEY0 0x14B0
+#define REG_RSS_KEY1 0x14B4
+#define REG_RSS_KEY2 0x14B8
+#define REG_RSS_KEY3 0x14BC
+#define REG_RSS_KEY4 0x14C0
+#define REG_RSS_KEY5 0x14C4
+#define REG_RSS_KEY6 0x14C8
+#define REG_RSS_KEY7 0x14CC
+#define REG_RSS_KEY8 0x14D0
+#define REG_RSS_KEY9 0x14D4
+#define REG_IDT_TABLE4 0x14E0
+#define REG_IDT_TABLE5 0x14E4
+#define REG_IDT_TABLE6 0x14E8
+#define REG_IDT_TABLE7 0x14EC
+#define REG_IDT_TABLE0 0x1560
+#define REG_IDT_TABLE1 0x1564
+#define REG_IDT_TABLE2 0x1568
+#define REG_IDT_TABLE3 0x156C
+#define REG_IDT_TABLE REG_IDT_TABLE0
+#define REG_RSS_HASH_VALUE 0x1570
+#define REG_RSS_HASH_FLAG 0x1574
+#define REG_BASE_CPU_NUMBER 0x157C
+
+
+/* TXQ Control Register */
+#define REG_TXQ_CTRL 0x1580
+#define TXQ_CTRL_NUM_TPD_BURST_MASK 0xF
+#define TXQ_CTRL_NUM_TPD_BURST_SHIFT 0
+#define TXQ_CTRL_EN 0x20 /* 1: Enable TXQ */
+#define TXQ_CTRL_ENH_MODE 0x40 /* Performance enhancement mode, in which up to two back-to-back DMA read commands might be dispatched. */
+#define TXQ_CTRL_TXF_BURST_NUM_SHIFT 16 /* Number of data byte to read in a cache-aligned burst. Each SRAM entry is 8-byte in length. */
+#define TXQ_CTRL_TXF_BURST_NUM_MASK 0xffff
+
+/* Jumbo packet Threshold for task offload */
+#define REG_TX_EARLY_TH 0x1584 /* Jumbo frame threshold in QWORD unit. Packet greater than */
+/* JUMBO_TASK_OFFLOAD_THRESHOLD will not be task offloaded. */
+#define TX_TX_EARLY_TH_MASK 0x7ff
+#define TX_TX_EARLY_TH_SHIFT 0
+
+
+/* RXQ Control Register */
+#define REG_RXQ_CTRL 0x15A0
+#define RXQ_CTRL_PBA_ALIGN_32 0 /* rx-packet alignment */
+#define RXQ_CTRL_PBA_ALIGN_64 1
+#define RXQ_CTRL_PBA_ALIGN_128 2
+#define RXQ_CTRL_PBA_ALIGN_256 3
+#define RXQ_CTRL_Q1_EN 0x10
+#define RXQ_CTRL_Q2_EN 0x20
+#define RXQ_CTRL_Q3_EN 0x40
+#define RXQ_CTRL_IPV6_XSUM_VERIFY_EN 0x80
+#define RXQ_CTRL_HASH_TLEN_SHIFT 8
+#define RXQ_CTRL_HASH_TLEN_MASK 0xFF
+#define RXQ_CTRL_HASH_TYPE_IPV4 0x10000
+#define RXQ_CTRL_HASH_TYPE_IPV4_TCP 0x20000
+#define RXQ_CTRL_HASH_TYPE_IPV6 0x40000
+#define RXQ_CTRL_HASH_TYPE_IPV6_TCP 0x80000
+#define RXQ_CTRL_RSS_MODE_DISABLE 0
+#define RXQ_CTRL_RSS_MODE_SQSINT 0x4000000
+#define RXQ_CTRL_RSS_MODE_MQUESINT 0x8000000
+#define RXQ_CTRL_RSS_MODE_MQUEMINT 0xC000000
+#define RXQ_CTRL_NIP_QUEUE_SEL_TBL 0x10000000
+#define RXQ_CTRL_HASH_ENABLE 0x20000000
+#define RXQ_CTRL_CUT_THRU_EN 0x40000000
+#define RXQ_CTRL_EN 0x80000000
+
+/* Rx jumbo packet threshold and rrd retirement timer */
+#define REG_RXQ_JMBOSZ_RRDTIM 0x15A4
+/*
+ * Jumbo packet threshold for non-VLAN packet, in QWORD (64-bit) unit.
+ * When the packet length greater than or equal to this value, RXQ
+ * shall start cut-through forwarding of the received packet.
+ */
+#define RXQ_JMBOSZ_TH_MASK 0x7ff
+#define RXQ_JMBOSZ_TH_SHIFT 0 /* RRD retirement timer. Decrement by 1 after every 512ns passes*/
+#define RXQ_JMBO_LKAH_MASK 0xf
+#define RXQ_JMBO_LKAH_SHIFT 11
+
+/* RXF flow control register */
+#define REG_RXQ_RXF_PAUSE_THRESH 0x15A8
+#define RXQ_RXF_PAUSE_TH_HI_SHIFT 0
+#define RXQ_RXF_PAUSE_TH_HI_MASK 0xfff
+#define RXQ_RXF_PAUSE_TH_LO_SHIFT 16
+#define RXQ_RXF_PAUSE_TH_LO_MASK 0xfff
+
+
+/* DMA Engine Control Register */
+#define REG_DMA_CTRL 0x15C0
+#define DMA_CTRL_DMAR_IN_ORDER 0x1
+#define DMA_CTRL_DMAR_ENH_ORDER 0x2
+#define DMA_CTRL_DMAR_OUT_ORDER 0x4
+#define DMA_CTRL_RCB_VALUE 0x8
+#define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4
+#define DMA_CTRL_DMAR_BURST_LEN_MASK 7
+#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7
+#define DMA_CTRL_DMAW_BURST_LEN_MASK 7
+#define DMA_CTRL_DMAR_REQ_PRI 0x400
+#define DMA_CTRL_DMAR_DLY_CNT_MASK 0x1F
+#define DMA_CTRL_DMAR_DLY_CNT_SHIFT 11
+#define DMA_CTRL_DMAW_DLY_CNT_MASK 0xF
+#define DMA_CTRL_DMAW_DLY_CNT_SHIFT 16
+#define DMA_CTRL_TXCMB_EN 0x100000
+#define DMA_CTRL_RXCMB_EN 0x200000
+
+
+/* CMB/SMB Control Register */
+#define REG_SMB_STAT_TIMER 0x15C4
+#define REG_TRIG_RRD_THRESH 0x15CA
+#define REG_TRIG_TPD_THRESH 0x15C8
+#define REG_TRIG_TXTIMER 0x15CC
+#define REG_TRIG_RXTIMER 0x15CE
+
+/* HOST RXF Page 1,2,3 address */
+#define REG_HOST_RXF1_PAGE0_LO 0x15D0
+#define REG_HOST_RXF1_PAGE1_LO 0x15D4
+#define REG_HOST_RXF2_PAGE0_LO 0x15D8
+#define REG_HOST_RXF2_PAGE1_LO 0x15DC
+#define REG_HOST_RXF3_PAGE0_LO 0x15E0
+#define REG_HOST_RXF3_PAGE1_LO 0x15E4
+
+/* Mail box */
+#define REG_MB_RXF1_RADDR 0x15B4
+#define REG_MB_RXF2_RADDR 0x15B8
+#define REG_MB_RXF3_RADDR 0x15BC
+#define REG_MB_TPD_PROD_IDX 0x15F0
+
+/* RXF-Page 0-3 PageNo & Valid bit */
+#define REG_HOST_RXF0_PAGE0_VLD 0x15F4
+#define HOST_RXF_VALID 1
+#define HOST_RXF_PAGENO_SHIFT 1
+#define HOST_RXF_PAGENO_MASK 0x7F
+#define REG_HOST_RXF0_PAGE1_VLD 0x15F5
+#define REG_HOST_RXF1_PAGE0_VLD 0x15F6
+#define REG_HOST_RXF1_PAGE1_VLD 0x15F7
+#define REG_HOST_RXF2_PAGE0_VLD 0x15F8
+#define REG_HOST_RXF2_PAGE1_VLD 0x15F9
+#define REG_HOST_RXF3_PAGE0_VLD 0x15FA
+#define REG_HOST_RXF3_PAGE1_VLD 0x15FB
+
+/* Interrupt Status Register */
+#define REG_ISR 0x1600
+#define ISR_SMB 1
+#define ISR_TIMER 2 /* Interrupt when Timer is counted down to zero */
+/*
+ * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set
+ * in Table 51 Selene Master Control Register (Offset 0x1400).
+ */
+#define ISR_MANUAL 4
+#define ISR_HW_RXF_OV 8 /* RXF overflow interrupt */
+#define ISR_HOST_RXF0_OV 0x10
+#define ISR_HOST_RXF1_OV 0x20
+#define ISR_HOST_RXF2_OV 0x40
+#define ISR_HOST_RXF3_OV 0x80
+#define ISR_TXF_UN 0x100
+#define ISR_RX0_PAGE_FULL 0x200
+#define ISR_DMAR_TO_RST 0x400
+#define ISR_DMAW_TO_RST 0x800
+#define ISR_GPHY 0x1000
+#define ISR_TX_CREDIT 0x2000
+#define ISR_GPHY_LPW 0x4000 /* GPHY low power state interrupt */
+#define ISR_RX_PKT 0x10000 /* One packet received, triggered by RFD */
+#define ISR_TX_PKT 0x20000 /* One packet transmitted, triggered by TPD */
+#define ISR_TX_DMA 0x40000
+#define ISR_RX_PKT_1 0x80000
+#define ISR_RX_PKT_2 0x100000
+#define ISR_RX_PKT_3 0x200000
+#define ISR_MAC_RX 0x400000
+#define ISR_MAC_TX 0x800000
+#define ISR_UR_DETECTED 0x1000000
+#define ISR_FERR_DETECTED 0x2000000
+#define ISR_NFERR_DETECTED 0x4000000
+#define ISR_CERR_DETECTED 0x8000000
+#define ISR_PHY_LINKDOWN 0x10000000
+#define ISR_DIS_INT 0x80000000
+
+
+/* Interrupt Mask Register */
+#define REG_IMR 0x1604
+
+
+#define IMR_NORMAL_MASK (\
+ ISR_SMB |\
+ ISR_TXF_UN |\
+ ISR_HW_RXF_OV |\
+ ISR_HOST_RXF0_OV|\
+ ISR_MANUAL |\
+ ISR_GPHY |\
+ ISR_GPHY_LPW |\
+ ISR_DMAR_TO_RST |\
+ ISR_DMAW_TO_RST |\
+ ISR_PHY_LINKDOWN|\
+ ISR_RX_PKT |\
+ ISR_TX_PKT)
+
+#define ISR_TX_EVENT (ISR_TXF_UN | ISR_TX_PKT)
+#define ISR_RX_EVENT (ISR_HOST_RXF0_OV | ISR_HW_RXF_OV | ISR_RX_PKT)
+
+#define REG_MAC_RX_STATUS_BIN 0x1700
+#define REG_MAC_RX_STATUS_END 0x175c
+#define REG_MAC_TX_STATUS_BIN 0x1760
+#define REG_MAC_TX_STATUS_END 0x17c0
+
+/* Hardware Offset Register */
+#define REG_HOST_RXF0_PAGEOFF 0x1800
+#define REG_TPD_CONS_IDX 0x1804
+#define REG_HOST_RXF1_PAGEOFF 0x1808
+#define REG_HOST_RXF2_PAGEOFF 0x180C
+#define REG_HOST_RXF3_PAGEOFF 0x1810
+
+/* RXF-Page 0-3 Offset DMA Address */
+#define REG_HOST_RXF0_MB0_LO 0x1820
+#define REG_HOST_RXF0_MB1_LO 0x1824
+#define REG_HOST_RXF1_MB0_LO 0x1828
+#define REG_HOST_RXF1_MB1_LO 0x182C
+#define REG_HOST_RXF2_MB0_LO 0x1830
+#define REG_HOST_RXF2_MB1_LO 0x1834
+#define REG_HOST_RXF3_MB0_LO 0x1838
+#define REG_HOST_RXF3_MB1_LO 0x183C
+
+/* Tpd CMB DMA Address */
+#define REG_HOST_TX_CMB_LO 0x1840
+#define REG_HOST_SMB_ADDR_LO 0x1844
+
+/* DEBUG ADDR */
+#define REG_DEBUG_DATA0 0x1900
+#define REG_DEBUG_DATA1 0x1904
+
+/***************************** MII definition ***************************************/
+/* PHY Common Register */
+#define MII_BMCR 0x00
+#define MII_BMSR 0x01
+#define MII_PHYSID1 0x02
+#define MII_PHYSID2 0x03
+#define MII_ADVERTISE 0x04
+#define MII_LPA 0x05
+#define MII_EXPANSION 0x06
+#define MII_AT001_CR 0x09
+#define MII_AT001_SR 0x0A
+#define MII_AT001_ESR 0x0F
+#define MII_AT001_PSCR 0x10
+#define MII_AT001_PSSR 0x11
+#define MII_INT_CTRL 0x12
+#define MII_INT_STATUS 0x13
+#define MII_SMARTSPEED 0x14
+#define MII_RERRCOUNTER 0x15
+#define MII_SREVISION 0x16
+#define MII_RESV1 0x17
+#define MII_LBRERROR 0x18
+#define MII_PHYADDR 0x19
+#define MII_RESV2 0x1a
+#define MII_TPISTATUS 0x1b
+#define MII_NCONFIG 0x1c
+
+#define MII_DBG_ADDR 0x1D
+#define MII_DBG_DATA 0x1E
+
+
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN 0x0800 /* Power down */
+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+#define MII_CR_SPEED_MASK 0x2040
+#define MII_CR_SPEED_1000 0x0040
+#define MII_CR_SPEED_100 0x2000
+#define MII_CR_SPEED_10 0x0000
+
+
+/* PHY Status Register */
+#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
+#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
+
+/* Link partner ability register. */
+#define MII_LPA_SLCT 0x001f /* Same as advertise selector */
+#define MII_LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
+#define MII_LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
+#define MII_LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
+#define MII_LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
+#define MII_LPA_100BASE4 0x0200 /* 100BASE-T4 */
+#define MII_LPA_PAUSE 0x0400 /* PAUSE */
+#define MII_LPA_ASYPAUSE 0x0800 /* Asymmetrical PAUSE */
+#define MII_LPA_RFAULT 0x2000 /* Link partner faulted */
+#define MII_LPA_LPACK 0x4000 /* Link partner acked us */
+#define MII_LPA_NPAGE 0x8000 /* Next page bit */
+
+/* Autoneg Advertisement Register */
+#define MII_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */
+#define MII_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
+#define MII_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
+#define MII_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
+#define MII_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
+#define MII_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
+#define MII_AR_PAUSE 0x0400 /* Pause operation desired */
+#define MII_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
+#define MII_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
+#define MII_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */
+#define MII_AR_SPEED_MASK 0x01E0
+#define MII_AR_DEFAULT_CAP_MASK 0x0DE0
+
+/* 1000BASE-T Control Register */
+#define MII_AT001_CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
+#define MII_AT001_CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
+#define MII_AT001_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */
+/* 0=DTE device */
+#define MII_AT001_CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */
+/* 0=Configure PHY as Slave */
+#define MII_AT001_CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */
+/* 0=Automatic Master/Slave config */
+#define MII_AT001_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
+#define MII_AT001_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
+#define MII_AT001_CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */
+#define MII_AT001_CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */
+#define MII_AT001_CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */
+#define MII_AT001_CR_1000T_SPEED_MASK 0x0300
+#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK 0x0300
+
+/* 1000BASE-T Status Register */
+#define MII_AT001_SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
+#define MII_AT001_SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
+#define MII_AT001_SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */
+#define MII_AT001_SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */
+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS_SHIFT 12
+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS_SHIFT 13
+
+/* Extended Status Register */
+#define MII_AT001_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
+#define MII_AT001_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
+#define MII_AT001_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
+#define MII_AT001_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
+
+/* AT001 PHY Specific Control Register */
+#define MII_AT001_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */
+#define MII_AT001_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */
+#define MII_AT001_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */
+#define MII_AT001_PSCR_MAC_POWERDOWN 0x0008
+#define MII_AT001_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low,
+ * 0=CLK125 toggling
+ */
+#define MII_AT001_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */
+/* Manual MDI configuration */
+#define MII_AT001_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
+#define MII_AT001_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover,
+ * 100BASE-TX/10BASE-T:
+ * MDI Mode
+ */
+#define MII_AT001_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled
+ * all speeds.
+ */
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE 0x0080
+/* 1=Enable Extended 10BASE-T distance
+ * (Lower 10BASE-T RX Threshold)
+ * 0=Normal 10BASE-T RX Threshold */
+#define MII_AT001_PSCR_MII_5BIT_ENABLE 0x0100
+/* 1=5-Bit interface in 100BASE-TX
+ * 0=MII interface in 100BASE-TX */
+#define MII_AT001_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */
+#define MII_AT001_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */
+#define MII_AT001_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
+#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT 1
+#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT 5
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
+/* AT001 PHY Specific Status Register */
+#define MII_AT001_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
+#define MII_AT001_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
+#define MII_AT001_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
+#define MII_AT001_PSSR_10MBS 0x0000 /* 00=10Mbs */
+#define MII_AT001_PSSR_100MBS 0x4000 /* 01=100Mbs */
+#define MII_AT001_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
+
+
+#endif /* _ATL1_E_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/b44.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/b44.c
new file mode 100644
index 00000000..66fa8ea3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/b44.c
@@ -0,0 +1,953 @@
+/*
+ * Copyright (c) 2008 Stefan Hajnoczi <stefanha@gmail.com>
+ * Copyright (c) 2008 Pantelis Koukousoulas <pktoss@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This driver is a port of the b44 linux driver version 1.01
+ *
+ * Copyright (c) 2002 David S. Miller <davem@redhat.com>
+ * Copyright (c) Pekka Pietikainen <pp@ee.oulu.fi>
+ * Copyright (C) 2006 Broadcom Corporation.
+ *
+ * Some ssb bits copied from version 2.0 of the b44 driver
+ * Copyright (c) Michael Buesch
+ *
+ * Copyright (c) a lot of people too. Please respect their work.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/io.h>
+#include <mii.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/pci.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include "b44.h"
+
+
+static inline int ring_next(int index)
+{
+ /* B44_RING_SIZE is a power of 2 :) */
+ return (index + 1) & (B44_RING_SIZE - 1);
+}
+
+
+/* Memory-mapped I/O wrappers */
+
+static inline u32 br32(const struct b44_private *bp, u32 reg)
+{
+ return readl(bp->regs + reg);
+}
+
+
+static inline void bw32(const struct b44_private *bp, u32 reg, u32 val)
+{
+ writel(val, bp->regs + reg);
+}
+
+
+static inline void bflush(const struct b44_private *bp, u32 reg, u32 timeout)
+{
+ readl(bp->regs + reg);
+ udelay(timeout);
+}
+
+
+#define VIRT_TO_B44(addr) ( virt_to_bus(addr) + SB_PCI_DMA )
+
+
+/**
+ * Return non-zero if the installed RAM is within
+ * the limit given and zero if it is outside.
+ * Hopefully will be removed soon.
+ */
+int phys_ram_within_limit(u64 limit)
+{
+ struct memory_map memmap;
+ struct memory_region *highest = NULL;
+ get_memmap(&memmap);
+
+ if (memmap.count == 0)
+ return 0;
+ highest = &memmap.regions[memmap.count - 1];
+
+ return (highest->end < limit);
+}
+
+
+/**
+ * Ring cells waiting to be processed are between 'tx_cur' and 'pending'
+ * indexes in the ring.
+ */
+static u32 pending_tx_index(struct b44_private *bp)
+{
+ u32 pending = br32(bp, B44_DMATX_STAT);
+ pending &= DMATX_STAT_CDMASK;
+
+ pending /= sizeof(struct dma_desc);
+ return pending & (B44_RING_SIZE - 1);
+}
+
+
+/**
+ * Ring cells waiting to be processed are between 'rx_cur' and 'pending'
+ * indexes in the ring.
+ */
+static u32 pending_rx_index(struct b44_private *bp)
+{
+ u32 pending = br32(bp, B44_DMARX_STAT);
+ pending &= DMARX_STAT_CDMASK;
+
+ pending /= sizeof(struct dma_desc);
+ return pending & (B44_RING_SIZE - 1);
+}
+
+
+/**
+ * Wait until the given bit is set/cleared.
+ */
+static int b44_wait_bit(struct b44_private *bp, unsigned long reg, u32 bit,
+ unsigned long timeout, const int clear)
+{
+ unsigned long i;
+
+ for (i = 0; i < timeout; i++) {
+ u32 val = br32(bp, reg);
+
+ if (clear && !(val & bit))
+ break;
+
+ if (!clear && (val & bit))
+ break;
+
+ udelay(10);
+ }
+ if (i == timeout) {
+ return -ENODEV;
+ }
+ return 0;
+}
+
+
+/*
+ * Sonics Silicon Backplane support. SSB is a mini-bus interconnecting
+ * so-called IP Cores. One of those cores implements the Fast Ethernet
+ * functionality and another one the PCI engine.
+ *
+ * You need to switch to the core you want to talk to before actually
+ * sending commands.
+ *
+ * See: http://bcm-v4.sipsolutions.net/Backplane for (reverse-engineered)
+ * specs.
+ */
+
+static inline u32 ssb_get_core_rev(struct b44_private *bp)
+{
+ return (br32(bp, B44_SBIDHIGH) & SBIDHIGH_RC_MASK);
+}
+
+
+static inline int ssb_is_core_up(struct b44_private *bp)
+{
+ return ((br32(bp, B44_SBTMSLOW) & (SSB_CORE_DOWN | SBTMSLOW_CLOCK))
+ == SBTMSLOW_CLOCK);
+}
+
+
+static u32 ssb_pci_setup(struct b44_private *bp, u32 cores)
+{
+ u32 bar_orig, pci_rev, val;
+
+ pci_read_config_dword(bp->pci, SSB_BAR0_WIN, &bar_orig);
+ pci_write_config_dword(bp->pci, SSB_BAR0_WIN,
+ BCM4400_PCI_CORE_ADDR);
+ pci_rev = ssb_get_core_rev(bp);
+
+ val = br32(bp, B44_SBINTVEC);
+ val |= cores;
+ bw32(bp, B44_SBINTVEC, val);
+
+ val = br32(bp, SSB_PCI_TRANS_2);
+ val |= SSB_PCI_PREF | SSB_PCI_BURST;
+ bw32(bp, SSB_PCI_TRANS_2, val);
+
+ pci_write_config_dword(bp->pci, SSB_BAR0_WIN, bar_orig);
+
+ return pci_rev;
+}
+
+
+static void ssb_core_disable(struct b44_private *bp)
+{
+ if (br32(bp, B44_SBTMSLOW) & SBTMSLOW_RESET)
+ return;
+
+ bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK));
+ b44_wait_bit(bp, B44_SBTMSLOW, SBTMSLOW_REJECT, 100000, 0);
+ b44_wait_bit(bp, B44_SBTMSHIGH, SBTMSHIGH_BUSY, 100000, 1);
+
+ bw32(bp, B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK |
+ SSB_CORE_DOWN));
+ bflush(bp, B44_SBTMSLOW, 1);
+
+ bw32(bp, B44_SBTMSLOW, SSB_CORE_DOWN);
+ bflush(bp, B44_SBTMSLOW, 1);
+}
+
+
+static void ssb_core_reset(struct b44_private *bp)
+{
+ u32 val;
+ const u32 mask = (SBTMSLOW_CLOCK | SBTMSLOW_FGC | SBTMSLOW_RESET);
+
+ ssb_core_disable(bp);
+
+ bw32(bp, B44_SBTMSLOW, mask);
+ bflush(bp, B44_SBTMSLOW, 1);
+
+ /* Clear SERR if set, this is a hw bug workaround. */
+ if (br32(bp, B44_SBTMSHIGH) & SBTMSHIGH_SERR)
+ bw32(bp, B44_SBTMSHIGH, 0);
+
+ val = br32(bp, B44_SBIMSTATE);
+ if (val & (SBIMSTATE_BAD)) {
+ bw32(bp, B44_SBIMSTATE, val & ~SBIMSTATE_BAD);
+ }
+
+ bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC));
+ bflush(bp, B44_SBTMSLOW, 1);
+
+ bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK));
+ bflush(bp, B44_SBTMSLOW, 1);
+}
+
+
+/*
+ * Driver helper functions
+ */
+
+/*
+ * Chip reset provides power to the b44 MAC & PCI cores, which
+ * is necessary for MAC register access. We only do a partial
+ * reset in case of transmit/receive errors (ISTAT_ERRORS) to
+ * avoid the chip being hung for an unnecessary long time in
+ * this case.
+ *
+ * Called-by: b44_close, b44_halt, b44_inithw(b44_open), b44_probe
+ */
+static void b44_chip_reset(struct b44_private *bp, int reset_kind)
+{
+ if (ssb_is_core_up(bp)) {
+ bw32(bp, B44_RCV_LAZY, 0);
+
+ bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
+
+ b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1);
+
+ bw32(bp, B44_DMATX_CTRL, 0);
+
+ bp->tx_dirty = bp->tx_cur = 0;
+
+ if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK)
+ b44_wait_bit(bp, B44_DMARX_STAT, DMARX_STAT_SIDLE,
+ 100, 0);
+
+ bw32(bp, B44_DMARX_CTRL, 0);
+
+ bp->rx_cur = 0;
+ } else {
+ ssb_pci_setup(bp, SBINTVEC_ENET0);
+ }
+
+ ssb_core_reset(bp);
+
+ /* Don't enable PHY if we are only doing a partial reset. */
+ if (reset_kind == B44_CHIP_RESET_PARTIAL)
+ return;
+
+ /* Make PHY accessible. */
+ bw32(bp, B44_MDIO_CTRL,
+ (MDIO_CTRL_PREAMBLE | (0x0d & MDIO_CTRL_MAXF_MASK)));
+ bflush(bp, B44_MDIO_CTRL, 1);
+
+ /* Enable internal or external PHY */
+ if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
+ bw32(bp, B44_ENET_CTRL, ENET_CTRL_EPSEL);
+ bflush(bp, B44_ENET_CTRL, 1);
+ } else {
+ u32 val = br32(bp, B44_DEVCTRL);
+ if (val & DEVCTRL_EPR) {
+ bw32(bp, B44_DEVCTRL, (val & ~DEVCTRL_EPR));
+ bflush(bp, B44_DEVCTRL, 100);
+ }
+ }
+}
+
+
+/**
+ * called by b44_poll in the error path
+ */
+static void b44_halt(struct b44_private *bp)
+{
+ /* disable ints */
+ bw32(bp, B44_IMASK, 0);
+ bflush(bp, B44_IMASK, 1);
+
+ DBG("b44: powering down PHY\n");
+ bw32(bp, B44_MAC_CTRL, MAC_CTRL_PHY_PDOWN);
+
+ /*
+ * Now reset the chip, but without enabling
+ * the MAC&PHY part of it.
+ * This has to be done _after_ we shut down the PHY
+ */
+ b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);
+}
+
+
+
+/*
+ * Called at device open time to get the chip ready for
+ * packet processing.
+ *
+ * Called-by: b44_open
+ */
+static void b44_init_hw(struct b44_private *bp, int reset_kind)
+{
+ u32 val;
+#define CTRL_MASK (DMARX_CTRL_ENABLE | (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT))
+
+ b44_chip_reset(bp, B44_CHIP_RESET_FULL);
+ if (reset_kind == B44_FULL_RESET) {
+ b44_phy_reset(bp);
+ }
+
+ /* Enable CRC32, set proper LED modes and power on PHY */
+ bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
+ bw32(bp, B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));
+
+ /* This sets the MAC address too. */
+ b44_set_rx_mode(bp->netdev);
+
+ /* MTU + eth header + possible VLAN tag + struct rx_header */
+ bw32(bp, B44_RXMAXLEN, B44_MAX_MTU + ETH_HLEN + 8 + RX_HEADER_LEN);
+ bw32(bp, B44_TXMAXLEN, B44_MAX_MTU + ETH_HLEN + 8 + RX_HEADER_LEN);
+
+ bw32(bp, B44_TX_HIWMARK, TX_HIWMARK_DEFLT);
+ if (reset_kind == B44_PARTIAL_RESET) {
+ bw32(bp, B44_DMARX_CTRL, CTRL_MASK);
+ } else {
+ bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
+ bw32(bp, B44_DMATX_ADDR, VIRT_TO_B44(bp->tx));
+
+ bw32(bp, B44_DMARX_CTRL, CTRL_MASK);
+ bw32(bp, B44_DMARX_ADDR, VIRT_TO_B44(bp->rx));
+ bw32(bp, B44_DMARX_PTR, B44_RX_RING_LEN_BYTES);
+
+ bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
+ }
+
+ val = br32(bp, B44_ENET_CTRL);
+ bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
+#undef CTRL_MASK
+}
+
+
+/*** Management of ring descriptors ***/
+
+
+static void b44_populate_rx_descriptor(struct b44_private *bp, u32 idx)
+{
+ struct rx_header *rh;
+ u32 ctrl, addr;
+
+ rh = bp->rx_iobuf[idx]->data;
+ rh->len = 0;
+ rh->flags = 0;
+ ctrl = DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET);
+ if (idx == B44_RING_LAST) {
+ ctrl |= DESC_CTRL_EOT;
+ }
+ addr = VIRT_TO_B44(bp->rx_iobuf[idx]->data);
+
+ bp->rx[idx].ctrl = cpu_to_le32(ctrl);
+ bp->rx[idx].addr = cpu_to_le32(addr);
+ bw32(bp, B44_DMARX_PTR, idx * sizeof(struct dma_desc));
+}
+
+
+/*
+ * Refill RX ring descriptors with buffers. This is needed
+ * because during rx we are passing ownership of descriptor
+ * buffers to the network stack.
+ */
+static void b44_rx_refill(struct b44_private *bp, u32 pending)
+{
+ u32 i;
+
+ // skip pending
+ for (i = pending + 1; i != bp->rx_cur; i = ring_next(i)) {
+ if (bp->rx_iobuf[i] != NULL)
+ continue;
+
+ bp->rx_iobuf[i] = alloc_iob(RX_PKT_BUF_SZ);
+ if (!bp->rx_iobuf[i]) {
+ DBG("Refill rx ring failed!!\n");
+ break;
+ }
+
+ b44_populate_rx_descriptor(bp, i);
+ }
+}
+
+
+static void b44_free_rx_ring(struct b44_private *bp)
+{
+ u32 i;
+
+ if (bp->rx) {
+ for (i = 0; i < B44_RING_SIZE; i++) {
+ free_iob(bp->rx_iobuf[i]);
+ bp->rx_iobuf[i] = NULL;
+ }
+ free_dma(bp->rx, B44_RX_RING_LEN_BYTES);
+ bp->rx = NULL;
+ }
+}
+
+
+static int b44_init_rx_ring(struct b44_private *bp)
+{
+ b44_free_rx_ring(bp);
+
+ bp->rx = malloc_dma(B44_RX_RING_LEN_BYTES, B44_DMA_ALIGNMENT);
+ if (!bp->rx)
+ return -ENOMEM;
+
+ memset(bp->rx_iobuf, 0, sizeof(bp->rx_iobuf));
+
+ bp->rx_iobuf[0] = alloc_iob(RX_PKT_BUF_SZ);
+ b44_populate_rx_descriptor(bp, 0);
+ b44_rx_refill(bp, 0);
+
+ DBG("Init RX rings: rx=0x%08lx\n", VIRT_TO_B44(bp->rx));
+ return 0;
+}
+
+
+static void b44_free_tx_ring(struct b44_private *bp)
+{
+ if (bp->tx) {
+ free_dma(bp->tx, B44_TX_RING_LEN_BYTES);
+ bp->tx = NULL;
+ }
+}
+
+
+static int b44_init_tx_ring(struct b44_private *bp)
+{
+ b44_free_tx_ring(bp);
+
+ bp->tx = malloc_dma(B44_TX_RING_LEN_BYTES, B44_DMA_ALIGNMENT);
+ if (!bp->tx)
+ return -ENOMEM;
+
+ memset(bp->tx, 0, B44_TX_RING_LEN_BYTES);
+ memset(bp->tx_iobuf, 0, sizeof(bp->tx_iobuf));
+
+ DBG("Init TX rings: tx=0x%08lx\n", VIRT_TO_B44(bp->tx));
+ return 0;
+}
+
+
+/*** Interaction with the PHY ***/
+
+
+static int b44_phy_read(struct b44_private *bp, int reg, u32 * val)
+{
+ int err;
+
+ u32 arg1 = (MDIO_OP_READ << MDIO_DATA_OP_SHIFT);
+ u32 arg2 = (bp->phy_addr << MDIO_DATA_PMD_SHIFT);
+ u32 arg3 = (reg << MDIO_DATA_RA_SHIFT);
+ u32 arg4 = (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT);
+ u32 argv = arg1 | arg2 | arg3 | arg4;
+
+ bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
+ bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | argv));
+ err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
+ *val = br32(bp, B44_MDIO_DATA) & MDIO_DATA_DATA;
+
+ return err;
+}
+
+
+static int b44_phy_write(struct b44_private *bp, int reg, u32 val)
+{
+ u32 arg1 = (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT);
+ u32 arg2 = (bp->phy_addr << MDIO_DATA_PMD_SHIFT);
+ u32 arg3 = (reg << MDIO_DATA_RA_SHIFT);
+ u32 arg4 = (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT);
+ u32 arg5 = (val & MDIO_DATA_DATA);
+ u32 argv = arg1 | arg2 | arg3 | arg4 | arg5;
+
+
+ bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
+ bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | argv));
+ return b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
+}
+
+
+static int b44_phy_reset(struct b44_private *bp)
+{
+ u32 val;
+ int err;
+
+ err = b44_phy_write(bp, MII_BMCR, BMCR_RESET);
+ if (err)
+ return err;
+
+ udelay(100);
+ err = b44_phy_read(bp, MII_BMCR, &val);
+ if (!err) {
+ if (val & BMCR_RESET) {
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * The BCM44xx CAM (Content Addressable Memory) stores the MAC
+ * and PHY address.
+ */
+static void b44_cam_write(struct b44_private *bp, unsigned char *data,
+ int index)
+{
+ u32 val;
+
+ val = ((u32) data[2]) << 24;
+ val |= ((u32) data[3]) << 16;
+ val |= ((u32) data[4]) << 8;
+ val |= ((u32) data[5]) << 0;
+ bw32(bp, B44_CAM_DATA_LO, val);
+
+
+ val = (CAM_DATA_HI_VALID |
+ (((u32) data[0]) << 8) | (((u32) data[1]) << 0));
+
+ bw32(bp, B44_CAM_DATA_HI, val);
+
+ val = CAM_CTRL_WRITE | (index << CAM_CTRL_INDEX_SHIFT);
+ bw32(bp, B44_CAM_CTRL, val);
+
+ b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
+}
+
+
+static void b44_set_mac_addr(struct b44_private *bp)
+{
+ u32 val;
+ bw32(bp, B44_CAM_CTRL, 0);
+ b44_cam_write(bp, bp->netdev->ll_addr, 0);
+ val = br32(bp, B44_CAM_CTRL);
+ bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
+}
+
+
+/* Read 128-bytes of EEPROM. */
+static void b44_read_eeprom(struct b44_private *bp, u8 * data)
+{
+ long i;
+ u16 *ptr = (u16 *) data;
+
+ for (i = 0; i < 128; i += 2)
+ ptr[i / 2] = cpu_to_le16(readw(bp->regs + 4096 + i));
+}
+
+
+static void b44_load_mac_and_phy_addr(struct b44_private *bp)
+{
+ u8 eeprom[128];
+
+ /* Load MAC address, note byteswapping */
+ b44_read_eeprom(bp, &eeprom[0]);
+ bp->netdev->hw_addr[0] = eeprom[79];
+ bp->netdev->hw_addr[1] = eeprom[78];
+ bp->netdev->hw_addr[2] = eeprom[81];
+ bp->netdev->hw_addr[3] = eeprom[80];
+ bp->netdev->hw_addr[4] = eeprom[83];
+ bp->netdev->hw_addr[5] = eeprom[82];
+
+ /* Load PHY address */
+ bp->phy_addr = eeprom[90] & 0x1f;
+}
+
+
+static void b44_set_rx_mode(struct net_device *netdev)
+{
+ struct b44_private *bp = netdev_priv(netdev);
+ unsigned char zero[6] = { 0, 0, 0, 0, 0, 0 };
+ u32 val;
+ int i;
+
+ val = br32(bp, B44_RXCONFIG);
+ val &= ~RXCONFIG_PROMISC;
+ val |= RXCONFIG_ALLMULTI;
+
+ b44_set_mac_addr(bp);
+
+ for (i = 1; i < 64; i++)
+ b44_cam_write(bp, zero, i);
+
+ bw32(bp, B44_RXCONFIG, val);
+ val = br32(bp, B44_CAM_CTRL);
+ bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
+}
+
+
+/*** Implementation of iPXE driver callbacks ***/
+
+/**
+ * Probe device
+ *
+ * @v pci PCI device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+static int b44_probe(struct pci_device *pci)
+{
+ struct net_device *netdev;
+ struct b44_private *bp;
+ int rc;
+
+ /*
+ * Bail out if more than 1GB of physical RAM is installed.
+ * This limitation will be removed later when dma mapping
+ * is merged into mainline.
+ */
+ if (!phys_ram_within_limit(B44_30BIT_DMA_MASK)) {
+ DBG("Sorry, this version of the driver does not\n"
+ "support systems with more than 1GB of RAM.\n");
+ return -ENOMEM;
+ }
+
+ /* Set up netdev */
+ netdev = alloc_etherdev(sizeof(*bp));
+ if (!netdev)
+ return -ENOMEM;
+
+ netdev_init(netdev, &b44_operations);
+ pci_set_drvdata(pci, netdev);
+ netdev->dev = &pci->dev;
+
+ /* Set up private data */
+ bp = netdev_priv(netdev);
+ memset(bp, 0, sizeof(*bp));
+ bp->netdev = netdev;
+ bp->pci = pci;
+
+ /* Map device registers */
+ bp->regs = ioremap(pci->membase, B44_REGS_SIZE);
+ if (!bp->regs) {
+ netdev_put(netdev);
+ return -ENOMEM;
+ }
+
+ /* Enable PCI bus mastering */
+ adjust_pci_device(pci);
+
+ b44_load_mac_and_phy_addr(bp);
+
+ rc = register_netdev(netdev);
+ if (rc != 0) {
+ iounmap(bp->regs);
+ netdev_put(netdev);
+ return rc;
+ }
+
+ /* Link management currently not implemented */
+ netdev_link_up(netdev);
+
+ b44_chip_reset(bp, B44_CHIP_RESET_FULL);
+
+ DBG("b44 %s (%04x:%04x) regs=%p MAC=%s\n", pci->id->name,
+ pci->id->vendor, pci->id->device, bp->regs,
+ eth_ntoa(netdev->ll_addr));
+
+ return 0;
+}
+
+
+/**
+ * Remove device
+ *
+ * @v pci PCI device
+ */
+static void b44_remove(struct pci_device *pci)
+{
+ struct net_device *netdev = pci_get_drvdata(pci);
+ struct b44_private *bp = netdev_priv(netdev);
+
+ ssb_core_disable(bp);
+ unregister_netdev(netdev);
+ iounmap(bp->regs);
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+}
+
+
+/** Enable or disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void b44_irq(struct net_device *netdev, int enable)
+{
+ struct b44_private *bp = netdev_priv(netdev);
+
+ /* Interrupt mask specifies which events generate interrupts */
+ bw32(bp, B44_IMASK, enable ? IMASK_DEF : IMASK_DISABLE);
+}
+
+
+/** Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int b44_open(struct net_device *netdev)
+{
+ struct b44_private *bp = netdev_priv(netdev);
+ int rc;
+
+ rc = b44_init_tx_ring(bp);
+ if (rc != 0)
+ return rc;
+
+ rc = b44_init_rx_ring(bp);
+ if (rc != 0)
+ return rc;
+
+ b44_init_hw(bp, B44_FULL_RESET);
+
+ /* Disable interrupts */
+ b44_irq(netdev, 0);
+
+ return 0;
+}
+
+
+/** Close network device
+ *
+ * @v netdev Network device
+ */
+static void b44_close(struct net_device *netdev)
+{
+ struct b44_private *bp = netdev_priv(netdev);
+
+ b44_chip_reset(bp, B44_FULL_RESET);
+ b44_free_tx_ring(bp);
+ b44_free_rx_ring(bp);
+}
+
+
+/** Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int b44_transmit(struct net_device *netdev, struct io_buffer *iobuf)
+{
+ struct b44_private *bp = netdev_priv(netdev);
+ u32 cur = bp->tx_cur;
+ u32 ctrl;
+
+ /* Check for TX ring overflow */
+ if (bp->tx[cur].ctrl) {
+ DBG("tx overflow\n");
+ return -ENOBUFS;
+ }
+
+ /* Will call netdev_tx_complete() on the iobuf later */
+ bp->tx_iobuf[cur] = iobuf;
+
+ /* Set up TX descriptor */
+ ctrl = (iob_len(iobuf) & DESC_CTRL_LEN) |
+ DESC_CTRL_IOC | DESC_CTRL_SOF | DESC_CTRL_EOF;
+
+ if (cur == B44_RING_LAST)
+ ctrl |= DESC_CTRL_EOT;
+
+ bp->tx[cur].ctrl = cpu_to_le32(ctrl);
+ bp->tx[cur].addr = cpu_to_le32(VIRT_TO_B44(iobuf->data));
+
+ /* Update next available descriptor index */
+ cur = ring_next(cur);
+ bp->tx_cur = cur;
+ wmb();
+
+ /* Tell card that a new TX descriptor is ready */
+ bw32(bp, B44_DMATX_PTR, cur * sizeof(struct dma_desc));
+ return 0;
+}
+
+
+/** Recycles sent TX descriptors and notifies network stack
+ *
+ * @v bp Driver state
+ */
+static void b44_tx_complete(struct b44_private *bp)
+{
+ u32 cur, i;
+
+ cur = pending_tx_index(bp);
+
+ for (i = bp->tx_dirty; i != cur; i = ring_next(i)) {
+ /* Free finished frame */
+ netdev_tx_complete(bp->netdev, bp->tx_iobuf[i]);
+ bp->tx_iobuf[i] = NULL;
+
+ /* Clear TX descriptor */
+ bp->tx[i].ctrl = 0;
+ bp->tx[i].addr = 0;
+ }
+ bp->tx_dirty = cur;
+}
+
+
+static void b44_process_rx_packets(struct b44_private *bp)
+{
+ struct io_buffer *iob; /* received data */
+ struct rx_header *rh;
+ u32 pending, i;
+ u16 len;
+
+ pending = pending_rx_index(bp);
+
+ for (i = bp->rx_cur; i != pending; i = ring_next(i)) {
+ iob = bp->rx_iobuf[i];
+ if (iob == NULL)
+ break;
+
+ rh = iob->data;
+ len = le16_to_cpu(rh->len);
+
+ /*
+ * Guard against incompletely written RX descriptors.
+ * Without this, things can get really slow!
+ */
+ if (len == 0)
+ break;
+
+ /* Discard CRC that is generated by the card */
+ len -= 4;
+
+ /* Check for invalid packets and errors */
+ if (len > RX_PKT_BUF_SZ - RX_PKT_OFFSET ||
+ (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
+ DBG("rx error len=%d flags=%04x\n", len,
+ cpu_to_le16(rh->flags));
+ rh->len = 0;
+ rh->flags = 0;
+ netdev_rx_err(bp->netdev, iob, -EINVAL);
+ continue;
+ }
+
+ /* Clear RX descriptor */
+ rh->len = 0;
+ rh->flags = 0;
+ bp->rx_iobuf[i] = NULL;
+
+ /* Hand off the IO buffer to the network stack */
+ iob_reserve(iob, RX_PKT_OFFSET);
+ iob_put(iob, len);
+ netdev_rx(bp->netdev, iob);
+ }
+ bp->rx_cur = i;
+ b44_rx_refill(bp, pending_rx_index(bp));
+}
+
+
+/** Poll for completed and received packets
+ *
+ * @v netdev Network device
+ */
+static void b44_poll(struct net_device *netdev)
+{
+ struct b44_private *bp = netdev_priv(netdev);
+ u32 istat;
+
+ /* Interrupt status */
+ istat = br32(bp, B44_ISTAT);
+ istat &= IMASK_DEF; /* only the events we care about */
+
+ if (!istat)
+ return;
+ if (istat & ISTAT_TX)
+ b44_tx_complete(bp);
+ if (istat & ISTAT_RX)
+ b44_process_rx_packets(bp);
+ if (istat & ISTAT_ERRORS) {
+ DBG("b44 error istat=0x%08x\n", istat);
+
+ /* Reset B44 core partially to avoid long waits */
+ b44_irq(bp->netdev, 0);
+ b44_halt(bp);
+ b44_init_tx_ring(bp);
+ b44_init_rx_ring(bp);
+ b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
+ }
+
+ /* Acknowledge interrupt */
+ bw32(bp, B44_ISTAT, 0);
+ bflush(bp, B44_ISTAT, 1);
+}
+
+
+static struct net_device_operations b44_operations = {
+ .open = b44_open,
+ .close = b44_close,
+ .transmit = b44_transmit,
+ .poll = b44_poll,
+ .irq = b44_irq,
+};
+
+
+static struct pci_device_id b44_nics[] = {
+ PCI_ROM(0x14e4, 0x4401, "BCM4401", "BCM4401", 0),
+ PCI_ROM(0x14e4, 0x170c, "BCM4401-B0", "BCM4401-B0", 0),
+ PCI_ROM(0x14e4, 0x4402, "BCM4401-B1", "BCM4401-B1", 0),
+};
+
+
+struct pci_driver b44_driver __pci_driver = {
+ .ids = b44_nics,
+ .id_count = sizeof b44_nics / sizeof b44_nics[0],
+ .probe = b44_probe,
+ .remove = b44_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/b44.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/b44.h
new file mode 100644
index 00000000..2d1f206e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/b44.h
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2008 Stefan Hajnoczi <stefanha@gmail.com>
+ * Copyright (c) 2008 Pantelis Koukousoulas <pktoss@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This driver is a port of the b44 linux driver version 1.01
+ *
+ * Copyright (c) 2002 David S. Miller <davem@redhat.com>
+ * Copyright (c) Pekka Pietikainen <pp@ee.oulu.fi>
+ * Copyright (C) 2006 Broadcom Corporation.
+ *
+ * Some ssb bits copied from version 2.0 of the b44 driver
+ * Copyright (c) Michael Buesch
+ *
+ * Copyright (c) a lot of people too. Please respect their work.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef _B44_H
+#define _B44_H
+
+/* BCM44xx Register layout */
+#define B44_DEVCTRL 0x0000UL /* Device Control */
+#define DEVCTRL_MPM 0x00000040 /* MP PME Enable (B0 only) */
+#define DEVCTRL_PFE 0x00000080 /* Pattern Filtering Enable */
+#define DEVCTRL_IPP 0x00000400 /* Internal EPHY Present */
+#define DEVCTRL_EPR 0x00008000 /* EPHY Reset */
+#define DEVCTRL_PME 0x00001000 /* PHY Mode Enable */
+#define DEVCTRL_PMCE 0x00002000 /* PHY Mode Clocks Enable */
+#define DEVCTRL_PADDR 0x0007c000 /* PHY Address */
+#define DEVCTRL_PADDR_SHIFT 18
+#define B44_BIST_STAT 0x000CUL /* Built-In Self-Test Status */
+#define B44_WKUP_LEN 0x0010UL /* Wakeup Length */
+#define WKUP_LEN_P0_MASK 0x0000007f /* Pattern 0 */
+#define WKUP_LEN_D0 0x00000080
+#define WKUP_LEN_P1_MASK 0x00007f00 /* Pattern 1 */
+#define WKUP_LEN_P1_SHIFT 8
+#define WKUP_LEN_D1 0x00008000
+#define WKUP_LEN_P2_MASK 0x007f0000 /* Pattern 2 */
+#define WKUP_LEN_P2_SHIFT 16
+#define WKUP_LEN_D2 0x00000000
+#define WKUP_LEN_P3_MASK 0x7f000000 /* Pattern 3 */
+#define WKUP_LEN_P3_SHIFT 24
+#define WKUP_LEN_D3 0x80000000
+#define WKUP_LEN_DISABLE 0x80808080
+#define WKUP_LEN_ENABLE_TWO 0x80800000
+#define WKUP_LEN_ENABLE_THREE 0x80000000
+#define B44_ISTAT 0x0020UL /* Interrupt Status */
+#define ISTAT_LS 0x00000020 /* Link Change (B0 only) */
+#define ISTAT_PME 0x00000040 /* Power Management Event */
+#define ISTAT_TO 0x00000080 /* General Purpose Timeout */
+#define ISTAT_DSCE 0x00000400 /* Descriptor Error */
+#define ISTAT_DATAE 0x00000800 /* Data Error */
+#define ISTAT_DPE 0x00001000 /* Descr. Protocol Error */
+#define ISTAT_RDU 0x00002000 /* Receive Descr. Underflow */
+#define ISTAT_RFO 0x00004000 /* Receive FIFO Overflow */
+#define ISTAT_TFU 0x00008000 /* Transmit FIFO Underflow */
+#define ISTAT_RX 0x00010000 /* RX Interrupt */
+#define ISTAT_TX 0x01000000 /* TX Interrupt */
+#define ISTAT_EMAC 0x04000000 /* EMAC Interrupt */
+#define ISTAT_MII_WRITE 0x08000000 /* MII Write Interrupt */
+#define ISTAT_MII_READ 0x10000000 /* MII Read Interrupt */
+#define ISTAT_ERRORS (ISTAT_DSCE|ISTAT_DATAE|ISTAT_DPE|\
+ ISTAT_RDU|ISTAT_RFO|ISTAT_TFU)
+#define B44_IMASK 0x0024UL /* Interrupt Mask */
+#define IMASK_DEF (ISTAT_ERRORS | ISTAT_RX | ISTAT_TX)
+#define IMASK_DISABLE 0
+#define B44_GPTIMER 0x0028UL /* General Purpose Timer */
+#define B44_ADDR_LO 0x0088UL /* ENET Address Lo (B0 only) */
+#define B44_ADDR_HI 0x008CUL /* ENET Address Hi (B0 only) */
+#define B44_FILT_ADDR 0x0090UL /* ENET Filter Address */
+#define B44_FILT_DATA 0x0094UL /* ENET Filter Data */
+#define B44_TXBURST 0x00A0UL /* TX Max Burst Length */
+#define B44_RXBURST 0x00A4UL /* RX Max Burst Length */
+#define B44_MAC_CTRL 0x00A8UL /* MAC Control */
+#define MAC_CTRL_CRC32_ENAB 0x00000001 /* CRC32 Generation Enable */
+#define MAC_CTRL_PHY_PDOWN 0x00000004 /* Onchip EPHY Powerdown */
+#define MAC_CTRL_PHY_EDET 0x00000008 /* Onchip EPHY Energy Detected*/
+#define MAC_CTRL_PHY_LEDCTRL 0x000000e0 /* Onchip EPHY LED Control */
+#define MAC_CTRL_PHY_LEDCTRL_SHIFT 5
+#define B44_MAC_FLOW 0x00ACUL /* MAC Flow Control */
+#define MAC_FLOW_RX_HI_WATER 0x000000ff /* Receive FIFO HI Water Mark */
+#define MAC_FLOW_PAUSE_ENAB 0x00008000 /* Enbl Pause Frm Generation */
+#define B44_RCV_LAZY 0x0100UL /* Lazy Interrupt Control */
+#define RCV_LAZY_TO_MASK 0x00ffffff /* Timeout */
+#define RCV_LAZY_FC_MASK 0xff000000 /* Frame Count */
+#define RCV_LAZY_FC_SHIFT 24
+#define B44_DMATX_CTRL 0x0200UL /* DMA TX Control */
+#define DMATX_CTRL_ENABLE 0x00000001 /* Enable */
+#define DMATX_CTRL_SUSPEND 0x00000002 /* Suepend Request */
+#define DMATX_CTRL_LPBACK 0x00000004 /* Loopback Enable */
+#define DMATX_CTRL_FAIRPRIOR 0x00000008 /* Fair Priority */
+#define DMATX_CTRL_FLUSH 0x00000010 /* Flush Request */
+#define B44_DMATX_ADDR 0x0204UL /* DMA TX Descriptor Ring Addr */
+#define B44_DMATX_PTR 0x0208UL /* DMA TX Last Posted Desc. */
+#define B44_DMATX_STAT 0x020CUL /* DMA TX Cur Actve Desc. + Sts */
+#define DMATX_STAT_CDMASK 0x00000fff /* Current Descriptor Mask */
+#define DMATX_STAT_SMASK 0x0000f000 /* State Mask */
+#define DMATX_STAT_SDISABLED 0x00000000 /* State Disabled */
+#define DMATX_STAT_SACTIVE 0x00001000 /* State Active */
+#define DMATX_STAT_SIDLE 0x00002000 /* State Idle Wait */
+#define DMATX_STAT_SSTOPPED 0x00003000 /* State Stopped */
+#define DMATX_STAT_SSUSP 0x00004000 /* State Suspend Pending */
+#define DMATX_STAT_EMASK 0x000f0000 /* Error Mask */
+#define DMATX_STAT_ENONE 0x00000000 /* Error None */
+#define DMATX_STAT_EDPE 0x00010000 /* Error Desc. Protocol Error */
+#define DMATX_STAT_EDFU 0x00020000 /* Error Data FIFO Underrun */
+#define DMATX_STAT_EBEBR 0x00030000 /* Bus Error on Buffer Read */
+#define DMATX_STAT_EBEDA 0x00040000 /* Bus Error on Desc. Access */
+#define DMATX_STAT_FLUSHED 0x00100000 /* Flushed */
+#define B44_DMARX_CTRL 0x0210UL /* DMA RX Control */
+#define DMARX_CTRL_ENABLE 0x00000001 /* Enable */
+#define DMARX_CTRL_ROMASK 0x000000fe /* Receive Offset Mask */
+#define DMARX_CTRL_ROSHIFT 1 /* Receive Offset Shift */
+#define B44_DMARX_ADDR 0x0214UL /* DMA RX Descriptor Ring Addr */
+#define B44_DMARX_PTR 0x0218UL /* DMA RX Last Posted Desc */
+#define B44_DMARX_STAT 0x021CUL /* Cur Active Desc. + Status */
+#define DMARX_STAT_CDMASK 0x00000fff /* Current Descriptor Mask */
+#define DMARX_STAT_SMASK 0x0000f000 /* State Mask */
+#define DMARX_STAT_SDISABLED 0x00000000 /* State Disbaled */
+#define DMARX_STAT_SACTIVE 0x00001000 /* State Active */
+#define DMARX_STAT_SIDLE 0x00002000 /* State Idle Wait */
+#define DMARX_STAT_SSTOPPED 0x00003000 /* State Stopped */
+#define DMARX_STAT_EMASK 0x000f0000 /* Error Mask */
+#define DMARX_STAT_ENONE 0x00000000 /* Error None */
+#define DMARX_STAT_EDPE 0x00010000 /* Error Desc. Protocol Error */
+#define DMARX_STAT_EDFO 0x00020000 /* Error Data FIFO Overflow */
+#define DMARX_STAT_EBEBW 0x00030000 /* Error on Buffer Write */
+#define DMARX_STAT_EBEDA 0x00040000 /* Bus Error on Desc. Access */
+#define B44_DMAFIFO_AD 0x0220UL /* DMA FIFO Diag Address */
+#define DMAFIFO_AD_OMASK 0x0000ffff /* Offset Mask */
+#define DMAFIFO_AD_SMASK 0x000f0000 /* Select Mask */
+#define DMAFIFO_AD_SXDD 0x00000000 /* Select Transmit DMA Data */
+#define DMAFIFO_AD_SXDP 0x00010000 /* Sel Transmit DMA Pointers */
+#define DMAFIFO_AD_SRDD 0x00040000 /* Select Receive DMA Data */
+#define DMAFIFO_AD_SRDP 0x00050000 /* Sel Receive DMA Pointers */
+#define DMAFIFO_AD_SXFD 0x00080000 /* Select Transmit FIFO Data */
+#define DMAFIFO_AD_SXFP 0x00090000 /* Sel Transmit FIFO Pointers */
+#define DMAFIFO_AD_SRFD 0x000c0000 /* Select Receive FIFO Data */
+#define DMAFIFO_AD_SRFP 0x000c0000 /* Sel Receive FIFO Pointers */
+#define B44_DMAFIFO_LO 0x0224UL /* DMA FIFO Diag Low Data */
+#define B44_DMAFIFO_HI 0x0228UL /* DMA FIFO Diag High Data */
+#define B44_RXCONFIG 0x0400UL /* EMAC RX Config */
+#define RXCONFIG_DBCAST 0x00000001 /* Disable Broadcast */
+#define RXCONFIG_ALLMULTI 0x00000002 /* Accept All Multicast */
+#define RXCONFIG_NORX_WHILE_TX 0x00000004 /* Rcv Disble While TX */
+#define RXCONFIG_PROMISC 0x00000008 /* Promiscuous Enable */
+#define RXCONFIG_LPBACK 0x00000010 /* Loopback Enable */
+#define RXCONFIG_FLOW 0x00000020 /* Flow Control Enable */
+#define RXCONFIG_FLOW_ACCEPT 0x00000040 /* Accept UFC Frame */
+#define RXCONFIG_RFILT 0x00000080 /* Reject Filter */
+#define B44_RXMAXLEN 0x0404UL /* EMAC RX Max Packet Length */
+#define B44_TXMAXLEN 0x0408UL /* EMAC TX Max Packet Length */
+#define B44_MDIO_CTRL 0x0410UL /* EMAC MDIO Control */
+#define MDIO_CTRL_MAXF_MASK 0x0000007f /* MDC Frequency */
+#define MDIO_CTRL_PREAMBLE 0x00000080 /* MII Preamble Enable */
+#define B44_MDIO_DATA 0x0414UL /* EMAC MDIO Data */
+#define MDIO_DATA_DATA 0x0000ffff /* R/W Data */
+#define MDIO_DATA_TA_MASK 0x00030000 /* Turnaround Value */
+#define MDIO_DATA_TA_SHIFT 16
+#define MDIO_TA_VALID 2
+#define MDIO_DATA_RA_MASK 0x007c0000 /* Register Address */
+#define MDIO_DATA_RA_SHIFT 18
+#define MDIO_DATA_PMD_MASK 0x0f800000 /* Physical Media Device */
+#define MDIO_DATA_PMD_SHIFT 23
+#define MDIO_DATA_OP_MASK 0x30000000 /* Opcode */
+#define MDIO_DATA_OP_SHIFT 28
+#define MDIO_OP_WRITE 1
+#define MDIO_OP_READ 2
+#define MDIO_DATA_SB_MASK 0xc0000000 /* Start Bits */
+#define MDIO_DATA_SB_SHIFT 30
+#define MDIO_DATA_SB_START 0x40000000 /* Start Of Frame */
+#define B44_EMAC_IMASK 0x0418UL /* EMAC Interrupt Mask */
+#define B44_EMAC_ISTAT 0x041CUL /* EMAC Interrupt Status */
+#define EMAC_INT_MII 0x00000001 /* MII MDIO Interrupt */
+#define EMAC_INT_MIB 0x00000002 /* MIB Interrupt */
+#define EMAC_INT_FLOW 0x00000003 /* Flow Control Interrupt */
+#define B44_CAM_DATA_LO 0x0420UL /* EMAC CAM Data Low */
+#define B44_CAM_DATA_HI 0x0424UL /* EMAC CAM Data High */
+#define CAM_DATA_HI_VALID 0x00010000 /* Valid Bit */
+#define B44_CAM_CTRL 0x0428UL /* EMAC CAM Control */
+#define CAM_CTRL_ENABLE 0x00000001 /* CAM Enable */
+#define CAM_CTRL_MSEL 0x00000002 /* Mask Select */
+#define CAM_CTRL_READ 0x00000004 /* Read */
+#define CAM_CTRL_WRITE 0x00000008 /* Read */
+#define CAM_CTRL_INDEX_MASK 0x003f0000 /* Index Mask */
+#define CAM_CTRL_INDEX_SHIFT 16
+#define CAM_CTRL_BUSY 0x80000000 /* CAM Busy */
+#define B44_ENET_CTRL 0x042CUL /* EMAC ENET Control */
+#define ENET_CTRL_ENABLE 0x00000001 /* EMAC Enable */
+#define ENET_CTRL_DISABLE 0x00000002 /* EMAC Disable */
+#define ENET_CTRL_SRST 0x00000004 /* EMAC Soft Reset */
+#define ENET_CTRL_EPSEL 0x00000008 /* External PHY Select */
+#define B44_TX_CTRL 0x0430UL /* EMAC TX Control */
+#define TX_CTRL_DUPLEX 0x00000001 /* Full Duplex */
+#define TX_CTRL_FMODE 0x00000002 /* Flow Mode */
+#define TX_CTRL_SBENAB 0x00000004 /* Single Backoff Enable */
+#define TX_CTRL_SMALL_SLOT 0x00000008 /* Small Slottime */
+#define B44_TX_HIWMARK 0x0434UL /* EMAC TX High Watermark */
+#define TX_HIWMARK_DEFLT 56 /* Default used in all drivers */
+#define B44_MIB_CTRL 0x0438UL /* EMAC MIB Control */
+#define MIB_CTRL_CLR_ON_READ 0x00000001 /* Autoclear on Read */
+#define B44_TX_GOOD_O 0x0500UL /* MIB TX Good Octets */
+#define B44_TX_GOOD_P 0x0504UL /* MIB TX Good Packets */
+#define B44_TX_O 0x0508UL /* MIB TX Octets */
+#define B44_TX_P 0x050CUL /* MIB TX Packets */
+#define B44_TX_BCAST 0x0510UL /* MIB TX Broadcast Packets */
+#define B44_TX_MCAST 0x0514UL /* MIB TX Multicast Packets */
+#define B44_TX_64 0x0518UL /* MIB TX <= 64 byte Packets */
+#define B44_TX_65_127 0x051CUL /* MIB TX 65 to 127 byte Pkts */
+#define B44_TX_128_255 0x0520UL /* MIB TX 128 to 255 byte Pkts */
+#define B44_TX_256_511 0x0524UL /* MIB TX 256 to 511 byte Pkts */
+#define B44_TX_512_1023 0x0528UL /* MIB TX 512 to 1023 byte Pkts */
+#define B44_TX_1024_MAX 0x052CUL /* MIB TX 1024 to max byte Pkts */
+#define B44_TX_JABBER 0x0530UL /* MIB TX Jabber Packets */
+#define B44_TX_OSIZE 0x0534UL /* MIB TX Oversize Packets */
+#define B44_TX_FRAG 0x0538UL /* MIB TX Fragment Packets */
+#define B44_TX_URUNS 0x053CUL /* MIB TX Underruns */
+#define B44_TX_TCOLS 0x0540UL /* MIB TX Total Collisions */
+#define B44_TX_SCOLS 0x0544UL /* MIB TX Single Collisions */
+#define B44_TX_MCOLS 0x0548UL /* MIB TX Multiple Collisions */
+#define B44_TX_ECOLS 0x054CUL /* MIB TX Excessive Collisions */
+#define B44_TX_LCOLS 0x0550UL /* MIB TX Late Collisions */
+#define B44_TX_DEFERED 0x0554UL /* MIB TX Defered Packets */
+#define B44_TX_CLOST 0x0558UL /* MIB TX Carrier Lost */
+#define B44_TX_PAUSE 0x055CUL /* MIB TX Pause Packets */
+#define B44_RX_GOOD_O 0x0580UL /* MIB RX Good Octets */
+#define B44_RX_GOOD_P 0x0584UL /* MIB RX Good Packets */
+#define B44_RX_O 0x0588UL /* MIB RX Octets */
+#define B44_RX_P 0x058CUL /* MIB RX Packets */
+#define B44_RX_BCAST 0x0590UL /* MIB RX Broadcast Packets */
+#define B44_RX_MCAST 0x0594UL /* MIB RX Multicast Packets */
+#define B44_RX_64 0x0598UL /* MIB RX <= 64 byte Packets */
+#define B44_RX_65_127 0x059CUL /* MIB RX 65 to 127 byte Pkts */
+#define B44_RX_128_255 0x05A0UL /* MIB RX 128 to 255 byte Pkts */
+#define B44_RX_256_511 0x05A4UL /* MIB RX 256 to 511 byte Pkts */
+#define B44_RX_512_1023 0x05A8UL /* MIB RX 512 to 1023 byte Pkts */
+#define B44_RX_1024_MAX 0x05ACUL /* MIB RX 1024 to max byte Pkts */
+#define B44_RX_JABBER 0x05B0UL /* MIB RX Jabber Packets */
+#define B44_RX_OSIZE 0x05B4UL /* MIB RX Oversize Packets */
+#define B44_RX_FRAG 0x05B8UL /* MIB RX Fragment Packets */
+#define B44_RX_MISS 0x05BCUL /* MIB RX Missed Packets */
+#define B44_RX_CRCA 0x05C0UL /* MIB RX CRC Align Errors */
+#define B44_RX_USIZE 0x05C4UL /* MIB RX Undersize Packets */
+#define B44_RX_CRC 0x05C8UL /* MIB RX CRC Errors */
+#define B44_RX_ALIGN 0x05CCUL /* MIB RX Align Errors */
+#define B44_RX_SYM 0x05D0UL /* MIB RX Symbol Errors */
+#define B44_RX_PAUSE 0x05D4UL /* MIB RX Pause Packets */
+#define B44_RX_NPAUSE 0x05D8UL /* MIB RX Non-Pause Packets */
+
+/* Sonics Silicon backplane register definitions */
+#define B44_SBIMSTATE 0x0F90UL /* SB Initiator Agent State */
+#define SBIMSTATE_PC 0x0000000f /* Pipe Count */
+#define SBIMSTATE_AP_MASK 0x00000030 /* Arbitration Priority */
+#define SBIMSTATE_AP_BOTH 0x00000000 /* both timeslices and token */
+#define SBIMSTATE_AP_TS 0x00000010 /* Use timeslices only */
+#define SBIMSTATE_AP_TK 0x00000020 /* Use token only */
+#define SBIMSTATE_AP_RSV 0x00000030 /* Reserved */
+#define SBIMSTATE_IBE 0x00020000 /* In Band Error */
+#define SBIMSTATE_TO 0x00040000 /* Timeout */
+#define SBIMSTATE_BAD ( SBIMSTATE_IBE | SBIMSTATE_TO )
+#define B44_SBINTVEC 0x0F94UL /* SB Interrupt Mask */
+#define SBINTVEC_PCI 0x00000001 /* Enable interrupts for PCI */
+#define SBINTVEC_ENET0 0x00000002 /* Enable ints for enet 0 */
+#define SBINTVEC_ILINE20 0x00000004 /* Enable ints for iline20 */
+#define SBINTVEC_CODEC 0x00000008 /* Enable ints for v90 codec */
+#define SBINTVEC_USB 0x00000010 /* Enable intts for usb */
+#define SBINTVEC_EXTIF 0x00000020 /* Enable ints for ext i/f */
+#define SBINTVEC_ENET1 0x00000040 /* Enable ints for enet 1 */
+#define B44_SBTMSLOW 0x0F98UL /* SB Target State Low */
+#define SBTMSLOW_RESET 0x00000001 /* Reset */
+#define SBTMSLOW_REJECT 0x00000002 /* Reject */
+#define SBTMSLOW_CLOCK 0x00010000 /* Clock Enable */
+#define SBTMSLOW_FGC 0x00020000 /* Force Gated Clocks On */
+#define SBTMSLOW_PE 0x40000000 /* Power Management Enable */
+#define SBTMSLOW_BE 0x80000000 /* BIST Enable */
+#define B44_SBTMSHIGH 0x0F9CUL /* SB Target State High */
+#define SBTMSHIGH_SERR 0x00000001 /* S-error */
+#define SBTMSHIGH_INT 0x00000002 /* Interrupt */
+#define SBTMSHIGH_BUSY 0x00000004 /* Busy */
+#define SBTMSHIGH_GCR 0x20000000 /* Gated Clock Request */
+#define SBTMSHIGH_BISTF 0x40000000 /* BIST Failed */
+#define SBTMSHIGH_BISTD 0x80000000 /* BIST Done */
+#define B44_SBIDHIGH 0x0FFCUL /* SB Identification High */
+#define SBIDHIGH_RC_MASK 0x0000000f /* Revision Code */
+#define SBIDHIGH_CC_MASK 0x0000fff0 /* Core Code */
+#define SBIDHIGH_CC_SHIFT 4
+#define SBIDHIGH_VC_MASK 0xffff0000 /* Vendor Code */
+#define SBIDHIGH_VC_SHIFT 16
+
+/* SSB PCI config space registers. */
+#define SSB_PMCSR 0x44
+#define SSB_PE 0x100
+#define SSB_BAR0_WIN 0x80
+#define SSB_BAR1_WIN 0x84
+#define SSB_SPROM_CONTROL 0x88
+#define SSB_BAR1_CONTROL 0x8c
+
+/* SSB core and host control registers. */
+#define SSB_CONTROL 0x0000UL
+#define SSB_ARBCONTROL 0x0010UL
+#define SSB_ISTAT 0x0020UL
+#define SSB_IMASK 0x0024UL
+#define SSB_MBOX 0x0028UL
+#define SSB_BCAST_ADDR 0x0050UL
+#define SSB_BCAST_DATA 0x0054UL
+#define SSB_PCI_TRANS_0 0x0100UL
+#define SSB_PCI_TRANS_1 0x0104UL
+#define SSB_PCI_TRANS_2 0x0108UL
+#define SSB_SPROM 0x0800UL
+
+#define SSB_PCI_MEM 0x00000000
+#define SSB_PCI_IO 0x00000001
+#define SSB_PCI_CFG0 0x00000002
+#define SSB_PCI_CFG1 0x00000003
+#define SSB_PCI_PREF 0x00000004
+#define SSB_PCI_BURST 0x00000008
+#define SSB_PCI_MASK0 0xfc000000
+#define SSB_PCI_MASK1 0xfc000000
+#define SSB_PCI_MASK2 0xc0000000
+
+/* 4400 PHY registers */
+#define B44_MII_AUXCTRL 24 /* Auxiliary Control */
+#define MII_AUXCTRL_DUPLEX 0x0001 /* Full Duplex */
+#define MII_AUXCTRL_SPEED 0x0002 /* 1=100Mbps, 0=10Mbps */
+#define MII_AUXCTRL_FORCED 0x0004 /* Forced 10/100 */
+#define B44_MII_ALEDCTRL 26 /* Activity LED */
+#define MII_ALEDCTRL_ALLMSK 0x7fff
+#define B44_MII_TLEDCTRL 27 /* Traffic Meter LED */
+#define MII_TLEDCTRL_ENABLE 0x0040
+
+/* RX/TX descriptor */
+struct dma_desc {
+ u32 ctrl; /* length of data and flags */
+ u32 addr; /* address of data */
+};
+
+/* There are only 12 bits in the DMA engine for descriptor offsetting
+ * so the table must be aligned on a boundary of this.
+ */
+#define B44_DMA_ALIGNMENT 4096
+
+/* The DMA engine can only address the first gigabyte of address space
+ */
+#define B44_30BIT_DMA_MASK 0x3fffffff
+
+#define DESC_CTRL_LEN 0x00001fff
+#define DESC_CTRL_CMASK 0x0ff00000 /* Core specific bits */
+#define DESC_CTRL_EOT 0x10000000 /* End of Table */
+#define DESC_CTRL_IOC 0x20000000 /* Interrupt On Completion */
+#define DESC_CTRL_EOF 0x40000000 /* End of Frame */
+#define DESC_CTRL_SOF 0x80000000 /* Start of Frame */
+
+struct rx_header {
+ u16 len;
+ u16 flags;
+ u16 pad[12];
+};
+#define RX_HEADER_LEN 28
+
+#define RX_FLAG_OFIFO 0x00000001 /* FIFO Overflow */
+#define RX_FLAG_CRCERR 0x00000002 /* CRC Error */
+#define RX_FLAG_SERR 0x00000004 /* Receive Symbol Error */
+#define RX_FLAG_ODD 0x00000008 /* Frame has odd number of nibbles */
+#define RX_FLAG_LARGE 0x00000010 /* Frame is > RX MAX Length */
+#define RX_FLAG_MCAST 0x00000020 /* Dest is Multicast Address */
+#define RX_FLAG_BCAST 0x00000040 /* Dest is Broadcast Address */
+#define RX_FLAG_MISS 0x00000080 /* Received due to promisc mode */
+#define RX_FLAG_LAST 0x00000800 /* Last buffer in frame */
+#define RX_FLAG_ERRORS (RX_FLAG_ODD | RX_FLAG_SERR |\
+ RX_FLAG_CRCERR | RX_FLAG_OFIFO)
+
+/* Client Mode PCI memory access space (1 GB) */
+#define SB_PCI_DMA 0x40000000
+
+ /* Address of PCI core on BCM4400 cards */
+#define BCM4400_PCI_CORE_ADDR 0x18002000
+
+/* Hardware minimum and maximum for a single frame's data payload */
+#define B44_MIN_MTU 60
+#define B44_MAX_MTU 1500
+
+#define B44_RING_SIZE 8
+#define B44_RING_LAST ( B44_RING_SIZE - 1 )
+
+#define B44_RX_RING_LEN_BYTES ( sizeof bp->rx[0] * B44_RING_SIZE )
+#define B44_TX_RING_LEN_BYTES ( sizeof bp->tx[0] * B44_RING_SIZE )
+
+#define RX_PKT_OFFSET 30
+#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET + 64)
+
+#define B44_FULL_RESET 1
+#define B44_FULL_RESET_SKIP_PHY 2
+#define B44_PARTIAL_RESET 3
+#define B44_CHIP_RESET_FULL 4
+#define B44_CHIP_RESET_PARTIAL 5
+
+#define SSB_CORE_DOWN ( SBTMSLOW_RESET | SBTMSLOW_REJECT )
+
+#define B44_REGS_SIZE 8192
+
+/** Driver private state */
+struct b44_private {
+ struct net_device *netdev;
+ struct pci_device *pci;
+ u8 *regs; /* memory-mapped registers */
+ u8 phy_addr;
+
+ struct dma_desc *tx;
+ struct io_buffer *tx_iobuf[B44_RING_SIZE];
+ u32 tx_cur; /* next available descriptor */
+ u32 tx_dirty; /* oldest pending descriptor */
+
+ struct dma_desc *rx;
+ struct io_buffer *rx_iobuf[B44_RING_SIZE];
+ u32 rx_cur; /* next descriptor to read */
+};
+
+
+static void ssb_core_reset ( struct b44_private *bp );
+static void ssb_core_disable ( struct b44_private *bp );
+static u32 ssb_pci_setup ( struct b44_private *bp, u32 cores );
+
+static void b44_chip_reset ( struct b44_private *bp, int reset_kind );
+static void b44_init_hw ( struct b44_private *bp, int reset_kind );
+static void b44_cam_write ( struct b44_private *bp, u8 *data, int index );
+static void b44_set_mac_addr ( struct b44_private *bp );
+static void b44_set_rx_mode ( struct net_device *netdev );
+static void b44_halt(struct b44_private *);
+
+static int b44_phy_reset ( struct b44_private *bp );
+static int b44_phy_write ( struct b44_private *bp, int reg, u32 val );
+static int b44_phy_read ( struct b44_private *bp, int reg, u32 *val );
+
+static int b44_init_tx_ring ( struct b44_private *bp );
+static void b44_free_tx_ring ( struct b44_private *bp );
+static int b44_init_rx_ring ( struct b44_private *bp );
+static void b44_free_rx_ring ( struct b44_private *bp );
+static void b44_rx_refill ( struct b44_private *bp, u32 pending );
+static void b44_populate_rx_descriptor (struct b44_private *bp, u32 index);
+
+static int b44_probe ( struct pci_device *pci );
+static void b44_remove ( struct pci_device *pci );
+
+static int b44_open ( struct net_device *netdev );
+static void b44_close ( struct net_device *netdev );
+static void b44_irq ( struct net_device *netdev, int enable );
+static void b44_poll ( struct net_device *netdev );
+static void b44_process_rx_packets ( struct b44_private *bp );
+static int b44_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf );
+
+static struct net_device_operations b44_operations;
+
+#endif /* _B44_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/bnx2.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/bnx2.c
new file mode 100644
index 00000000..a986bdef
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/bnx2.c
@@ -0,0 +1,2697 @@
+/* bnx2.c: Broadcom NX2 network driver.
+ *
+ * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Michael Chan (mchan@broadcom.com)
+ *
+ * Etherboot port by Ryan Jackson (rjackson@lnxi.com), based on driver
+ * version 1.4.40 from linux 2.6.17
+ */
+
+FILE_LICENCE ( GPL_ANY );
+
+#include "etherboot.h"
+#include "nic.h"
+#include <errno.h>
+#include <ipxe/pci.h>
+#include <ipxe/ethernet.h>
+#include "string.h"
+#include <mii.h>
+#include "bnx2.h"
+#include "bnx2_fw.h"
+
+#if 0
+/* Dummy defines for error handling */
+#define EBUSY 1
+#define ENODEV 2
+#define EINVAL 3
+#define ENOMEM 4
+#define EIO 5
+#endif
+
+/* The bnx2 seems to be picky about the alignment of the receive buffers
+ * and possibly the status block.
+ */
+static struct bss {
+ struct tx_bd tx_desc_ring[TX_DESC_CNT];
+ struct rx_bd rx_desc_ring[RX_DESC_CNT];
+ unsigned char rx_buf[RX_BUF_CNT][RX_BUF_SIZE];
+ struct status_block status_blk;
+ struct statistics_block stats_blk;
+} bnx2_bss;
+
+static struct bnx2 bnx2;
+
+static struct flash_spec flash_table[] =
+{
+ /* Slow EEPROM */
+ {0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400,
+ 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
+ SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
+ "EEPROM - slow"},
+ /* Expansion entry 0001 */
+ {0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 0001"},
+ /* Saifun SA25F010 (non-buffered flash) */
+ /* strap, cfg1, & write1 need updates */
+ {0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2,
+ "Non-buffered flash (128kB)"},
+ /* Saifun SA25F020 (non-buffered flash) */
+ /* strap, cfg1, & write1 need updates */
+ {0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4,
+ "Non-buffered flash (256kB)"},
+ /* Expansion entry 0100 */
+ {0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 0100"},
+ /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */
+ {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406,
+ 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
+ ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2,
+ "Entry 0101: ST M45PE10 (128kB non-bufferred)"},
+ /* Entry 0110: ST M45PE20 (non-buffered flash)*/
+ {0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406,
+ 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
+ ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4,
+ "Entry 0110: ST M45PE20 (256kB non-bufferred)"},
+ /* Saifun SA25F005 (non-buffered flash) */
+ /* strap, cfg1, & write1 need updates */
+ {0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE,
+ "Non-buffered flash (64kB)"},
+ /* Fast EEPROM */
+ {0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400,
+ 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
+ SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
+ "EEPROM - fast"},
+ /* Expansion entry 1001 */
+ {0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1001"},
+ /* Expansion entry 1010 */
+ {0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1010"},
+ /* ATMEL AT45DB011B (buffered flash) */
+ {0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400,
+ 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
+ BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE,
+ "Buffered flash (128kB)"},
+ /* Expansion entry 1100 */
+ {0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1100"},
+ /* Expansion entry 1101 */
+ {0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1101"},
+ /* Ateml Expansion entry 1110 */
+ {0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400,
+ 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
+ BUFFERED_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1110 (Atmel)"},
+ /* ATMEL AT45DB021B (buffered flash) */
+ {0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400,
+ 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
+ BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2,
+ "Buffered flash (256kB)"},
+};
+
+static u32
+bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
+{
+ REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
+ return (REG_RD(bp, BNX2_PCICFG_REG_WINDOW));
+}
+
+static void
+bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val)
+{
+ REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
+ REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
+}
+
+static void
+bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
+{
+ offset += cid_addr;
+ REG_WR(bp, BNX2_CTX_DATA_ADR, offset);
+ REG_WR(bp, BNX2_CTX_DATA, val);
+}
+
+static int
+bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
+{
+ u32 val1;
+ int i, ret;
+
+ if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
+
+ REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+
+ udelay(40);
+ }
+
+ val1 = (bp->phy_addr << 21) | (reg << 16) |
+ BNX2_EMAC_MDIO_COMM_COMMAND_READ | BNX2_EMAC_MDIO_COMM_DISEXT |
+ BNX2_EMAC_MDIO_COMM_START_BUSY;
+ REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
+
+ for (i = 0; i < 50; i++) {
+ udelay(10);
+
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+ if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
+ udelay(5);
+
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+ val1 &= BNX2_EMAC_MDIO_COMM_DATA;
+
+ break;
+ }
+ }
+
+ if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY) {
+ *val = 0x0;
+ ret = -EBUSY;
+ }
+ else {
+ *val = val1;
+ ret = 0;
+ }
+
+ if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
+
+ REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+
+ udelay(40);
+ }
+
+ return ret;
+}
+
+static int
+bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val)
+{
+ u32 val1;
+ int i, ret;
+
+ if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
+
+ REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+
+ udelay(40);
+ }
+
+ val1 = (bp->phy_addr << 21) | (reg << 16) | val |
+ BNX2_EMAC_MDIO_COMM_COMMAND_WRITE |
+ BNX2_EMAC_MDIO_COMM_START_BUSY | BNX2_EMAC_MDIO_COMM_DISEXT;
+ REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
+
+ for (i = 0; i < 50; i++) {
+ udelay(10);
+
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+ if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
+ udelay(5);
+ break;
+ }
+ }
+
+ if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)
+ ret = -EBUSY;
+ else
+ ret = 0;
+
+ if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
+
+ REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+
+ udelay(40);
+ }
+
+ return ret;
+}
+
+static void
+bnx2_disable_int(struct bnx2 *bp)
+{
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
+ REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
+
+}
+
+static int
+bnx2_alloc_mem(struct bnx2 *bp)
+{
+ bp->tx_desc_ring = bnx2_bss.tx_desc_ring;
+ bp->tx_desc_mapping = virt_to_bus(bp->tx_desc_ring);
+
+ bp->rx_desc_ring = bnx2_bss.rx_desc_ring;
+ memset(bp->rx_desc_ring, 0, sizeof(struct rx_bd) * RX_DESC_CNT);
+ bp->rx_desc_mapping = virt_to_bus(bp->rx_desc_ring);
+
+ memset(&bnx2_bss.status_blk, 0, sizeof(struct status_block));
+ bp->status_blk = &bnx2_bss.status_blk;
+ bp->status_blk_mapping = virt_to_bus(&bnx2_bss.status_blk);
+
+ bp->stats_blk = &bnx2_bss.stats_blk;
+ memset(&bnx2_bss.stats_blk, 0, sizeof(struct statistics_block));
+ bp->stats_blk_mapping = virt_to_bus(&bnx2_bss.stats_blk);
+
+ return 0;
+}
+
+static void
+bnx2_report_fw_link(struct bnx2 *bp)
+{
+ u32 fw_link_status = 0;
+
+ if (bp->link_up) {
+ u32 bmsr;
+
+ switch (bp->line_speed) {
+ case SPEED_10:
+ if (bp->duplex == DUPLEX_HALF)
+ fw_link_status = BNX2_LINK_STATUS_10HALF;
+ else
+ fw_link_status = BNX2_LINK_STATUS_10FULL;
+ break;
+ case SPEED_100:
+ if (bp->duplex == DUPLEX_HALF)
+ fw_link_status = BNX2_LINK_STATUS_100HALF;
+ else
+ fw_link_status = BNX2_LINK_STATUS_100FULL;
+ break;
+ case SPEED_1000:
+ if (bp->duplex == DUPLEX_HALF)
+ fw_link_status = BNX2_LINK_STATUS_1000HALF;
+ else
+ fw_link_status = BNX2_LINK_STATUS_1000FULL;
+ break;
+ case SPEED_2500:
+ if (bp->duplex == DUPLEX_HALF)
+ fw_link_status = BNX2_LINK_STATUS_2500HALF;
+ else
+ fw_link_status = BNX2_LINK_STATUS_2500FULL;
+ break;
+ }
+
+ fw_link_status |= BNX2_LINK_STATUS_LINK_UP;
+
+ if (bp->autoneg) {
+ fw_link_status |= BNX2_LINK_STATUS_AN_ENABLED;
+
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+
+ if (!(bmsr & BMSR_ANEGCOMPLETE) ||
+ bp->phy_flags & PHY_PARALLEL_DETECT_FLAG)
+ fw_link_status |= BNX2_LINK_STATUS_PARALLEL_DET;
+ else
+ fw_link_status |= BNX2_LINK_STATUS_AN_COMPLETE;
+ }
+ }
+ else
+ fw_link_status = BNX2_LINK_STATUS_LINK_DOWN;
+
+ REG_WR_IND(bp, bp->shmem_base + BNX2_LINK_STATUS, fw_link_status);
+}
+
+static void
+bnx2_report_link(struct bnx2 *bp)
+{
+ if (bp->link_up) {
+ printf("NIC Link is Up, ");
+
+ printf("%d Mbps ", bp->line_speed);
+
+ if (bp->duplex == DUPLEX_FULL)
+ printf("full duplex");
+ else
+ printf("half duplex");
+
+ if (bp->flow_ctrl) {
+ if (bp->flow_ctrl & FLOW_CTRL_RX) {
+ printf(", receive ");
+ if (bp->flow_ctrl & FLOW_CTRL_TX)
+ printf("& transmit ");
+ }
+ else {
+ printf(", transmit ");
+ }
+ printf("flow control ON");
+ }
+ printf("\n");
+ }
+ else {
+ printf("NIC Link is Down\n");
+ }
+
+ bnx2_report_fw_link(bp);
+}
+
+static void
+bnx2_resolve_flow_ctrl(struct bnx2 *bp)
+{
+ u32 local_adv, remote_adv;
+
+ bp->flow_ctrl = 0;
+ if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) !=
+ (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) {
+
+ if (bp->duplex == DUPLEX_FULL) {
+ bp->flow_ctrl = bp->req_flow_ctrl;
+ }
+ return;
+ }
+
+ if (bp->duplex != DUPLEX_FULL) {
+ return;
+ }
+
+ if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+ (CHIP_NUM(bp) == CHIP_NUM_5708)) {
+ u32 val;
+
+ bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val);
+ if (val & BCM5708S_1000X_STAT1_TX_PAUSE)
+ bp->flow_ctrl |= FLOW_CTRL_TX;
+ if (val & BCM5708S_1000X_STAT1_RX_PAUSE)
+ bp->flow_ctrl |= FLOW_CTRL_RX;
+ return;
+ }
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
+ bnx2_read_phy(bp, MII_LPA, &remote_adv);
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ u32 new_local_adv = 0;
+ u32 new_remote_adv = 0;
+
+ if (local_adv & ADVERTISE_1000XPAUSE)
+ new_local_adv |= ADVERTISE_PAUSE_CAP;
+ if (local_adv & ADVERTISE_1000XPSE_ASYM)
+ new_local_adv |= ADVERTISE_PAUSE_ASYM;
+ if (remote_adv & ADVERTISE_1000XPAUSE)
+ new_remote_adv |= ADVERTISE_PAUSE_CAP;
+ if (remote_adv & ADVERTISE_1000XPSE_ASYM)
+ new_remote_adv |= ADVERTISE_PAUSE_ASYM;
+
+ local_adv = new_local_adv;
+ remote_adv = new_remote_adv;
+ }
+
+ /* See Table 28B-3 of 802.3ab-1999 spec. */
+ if (local_adv & ADVERTISE_PAUSE_CAP) {
+ if(local_adv & ADVERTISE_PAUSE_ASYM) {
+ if (remote_adv & ADVERTISE_PAUSE_CAP) {
+ bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ }
+ else if (remote_adv & ADVERTISE_PAUSE_ASYM) {
+ bp->flow_ctrl = FLOW_CTRL_RX;
+ }
+ }
+ else {
+ if (remote_adv & ADVERTISE_PAUSE_CAP) {
+ bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ }
+ }
+ }
+ else if (local_adv & ADVERTISE_PAUSE_ASYM) {
+ if ((remote_adv & ADVERTISE_PAUSE_CAP) &&
+ (remote_adv & ADVERTISE_PAUSE_ASYM)) {
+
+ bp->flow_ctrl = FLOW_CTRL_TX;
+ }
+ }
+}
+
+static int
+bnx2_5708s_linkup(struct bnx2 *bp)
+{
+ u32 val;
+
+ bp->link_up = 1;
+ bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val);
+ switch (val & BCM5708S_1000X_STAT1_SPEED_MASK) {
+ case BCM5708S_1000X_STAT1_SPEED_10:
+ bp->line_speed = SPEED_10;
+ break;
+ case BCM5708S_1000X_STAT1_SPEED_100:
+ bp->line_speed = SPEED_100;
+ break;
+ case BCM5708S_1000X_STAT1_SPEED_1G:
+ bp->line_speed = SPEED_1000;
+ break;
+ case BCM5708S_1000X_STAT1_SPEED_2G5:
+ bp->line_speed = SPEED_2500;
+ break;
+ }
+ if (val & BCM5708S_1000X_STAT1_FD)
+ bp->duplex = DUPLEX_FULL;
+ else
+ bp->duplex = DUPLEX_HALF;
+
+ return 0;
+}
+
+static int
+bnx2_5706s_linkup(struct bnx2 *bp)
+{
+ u32 bmcr, local_adv, remote_adv, common;
+
+ bp->link_up = 1;
+ bp->line_speed = SPEED_1000;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ if (bmcr & BMCR_FULLDPLX) {
+ bp->duplex = DUPLEX_FULL;
+ }
+ else {
+ bp->duplex = DUPLEX_HALF;
+ }
+
+ if (!(bmcr & BMCR_ANENABLE)) {
+ return 0;
+ }
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
+ bnx2_read_phy(bp, MII_LPA, &remote_adv);
+
+ common = local_adv & remote_adv;
+ if (common & (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL)) {
+
+ if (common & ADVERTISE_1000XFULL) {
+ bp->duplex = DUPLEX_FULL;
+ }
+ else {
+ bp->duplex = DUPLEX_HALF;
+ }
+ }
+
+ return 0;
+}
+
+static int
+bnx2_copper_linkup(struct bnx2 *bp)
+{
+ u32 bmcr;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ if (bmcr & BMCR_ANENABLE) {
+ u32 local_adv, remote_adv, common;
+
+ bnx2_read_phy(bp, MII_CTRL1000, &local_adv);
+ bnx2_read_phy(bp, MII_STAT1000, &remote_adv);
+
+ common = local_adv & (remote_adv >> 2);
+ if (common & ADVERTISE_1000FULL) {
+ bp->line_speed = SPEED_1000;
+ bp->duplex = DUPLEX_FULL;
+ }
+ else if (common & ADVERTISE_1000HALF) {
+ bp->line_speed = SPEED_1000;
+ bp->duplex = DUPLEX_HALF;
+ }
+ else {
+ bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
+ bnx2_read_phy(bp, MII_LPA, &remote_adv);
+
+ common = local_adv & remote_adv;
+ if (common & ADVERTISE_100FULL) {
+ bp->line_speed = SPEED_100;
+ bp->duplex = DUPLEX_FULL;
+ }
+ else if (common & ADVERTISE_100HALF) {
+ bp->line_speed = SPEED_100;
+ bp->duplex = DUPLEX_HALF;
+ }
+ else if (common & ADVERTISE_10FULL) {
+ bp->line_speed = SPEED_10;
+ bp->duplex = DUPLEX_FULL;
+ }
+ else if (common & ADVERTISE_10HALF) {
+ bp->line_speed = SPEED_10;
+ bp->duplex = DUPLEX_HALF;
+ }
+ else {
+ bp->line_speed = 0;
+ bp->link_up = 0;
+ }
+ }
+ }
+ else {
+ if (bmcr & BMCR_SPEED100) {
+ bp->line_speed = SPEED_100;
+ }
+ else {
+ bp->line_speed = SPEED_10;
+ }
+ if (bmcr & BMCR_FULLDPLX) {
+ bp->duplex = DUPLEX_FULL;
+ }
+ else {
+ bp->duplex = DUPLEX_HALF;
+ }
+ }
+
+ return 0;
+}
+
+static int
+bnx2_set_mac_link(struct bnx2 *bp)
+{
+ u32 val;
+
+ REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620);
+ if (bp->link_up && (bp->line_speed == SPEED_1000) &&
+ (bp->duplex == DUPLEX_HALF)) {
+ REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff);
+ }
+
+ /* Configure the EMAC mode register. */
+ val = REG_RD(bp, BNX2_EMAC_MODE);
+
+ val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
+ BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
+ BNX2_EMAC_MODE_25G);
+
+ if (bp->link_up) {
+ switch (bp->line_speed) {
+ case SPEED_10:
+ if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ val |= BNX2_EMAC_MODE_PORT_MII_10;
+ break;
+ }
+ /* fall through */
+ case SPEED_100:
+ val |= BNX2_EMAC_MODE_PORT_MII;
+ break;
+ case SPEED_2500:
+ val |= BNX2_EMAC_MODE_25G;
+ /* fall through */
+ case SPEED_1000:
+ val |= BNX2_EMAC_MODE_PORT_GMII;
+ break;
+ }
+ }
+ else {
+ val |= BNX2_EMAC_MODE_PORT_GMII;
+ }
+
+ /* Set the MAC to operate in the appropriate duplex mode. */
+ if (bp->duplex == DUPLEX_HALF)
+ val |= BNX2_EMAC_MODE_HALF_DUPLEX;
+ REG_WR(bp, BNX2_EMAC_MODE, val);
+
+ /* Enable/disable rx PAUSE. */
+ bp->rx_mode &= ~BNX2_EMAC_RX_MODE_FLOW_EN;
+
+ if (bp->flow_ctrl & FLOW_CTRL_RX)
+ bp->rx_mode |= BNX2_EMAC_RX_MODE_FLOW_EN;
+ REG_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode);
+
+ /* Enable/disable tx PAUSE. */
+ val = REG_RD(bp, BNX2_EMAC_TX_MODE);
+ val &= ~BNX2_EMAC_TX_MODE_FLOW_EN;
+
+ if (bp->flow_ctrl & FLOW_CTRL_TX)
+ val |= BNX2_EMAC_TX_MODE_FLOW_EN;
+ REG_WR(bp, BNX2_EMAC_TX_MODE, val);
+
+ /* Acknowledge the interrupt. */
+ REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
+
+ return 0;
+}
+
+static int
+bnx2_set_link(struct bnx2 *bp)
+{
+ u32 bmsr;
+ u8 link_up;
+
+ if (bp->loopback == MAC_LOOPBACK) {
+ bp->link_up = 1;
+ return 0;
+ }
+
+ link_up = bp->link_up;
+
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+
+ if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+ (CHIP_NUM(bp) == CHIP_NUM_5706)) {
+ u32 val;
+
+ val = REG_RD(bp, BNX2_EMAC_STATUS);
+ if (val & BNX2_EMAC_STATUS_LINK)
+ bmsr |= BMSR_LSTATUS;
+ else
+ bmsr &= ~BMSR_LSTATUS;
+ }
+
+ if (bmsr & BMSR_LSTATUS) {
+ bp->link_up = 1;
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ if (CHIP_NUM(bp) == CHIP_NUM_5706)
+ bnx2_5706s_linkup(bp);
+ else if (CHIP_NUM(bp) == CHIP_NUM_5708)
+ bnx2_5708s_linkup(bp);
+ }
+ else {
+ bnx2_copper_linkup(bp);
+ }
+ bnx2_resolve_flow_ctrl(bp);
+ }
+ else {
+ if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+ (bp->autoneg & AUTONEG_SPEED)) {
+
+ u32 bmcr;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ if (!(bmcr & BMCR_ANENABLE)) {
+ bnx2_write_phy(bp, MII_BMCR, bmcr |
+ BMCR_ANENABLE);
+ }
+ }
+ bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
+ bp->link_up = 0;
+ }
+
+ if (bp->link_up != link_up) {
+ bnx2_report_link(bp);
+ }
+
+ bnx2_set_mac_link(bp);
+
+ return 0;
+}
+
+static int
+bnx2_reset_phy(struct bnx2 *bp)
+{
+ int i;
+ u32 reg;
+
+ bnx2_write_phy(bp, MII_BMCR, BMCR_RESET);
+
+#define PHY_RESET_MAX_WAIT 100
+ for (i = 0; i < PHY_RESET_MAX_WAIT; i++) {
+ udelay(10);
+
+ bnx2_read_phy(bp, MII_BMCR, &reg);
+ if (!(reg & BMCR_RESET)) {
+ udelay(20);
+ break;
+ }
+ }
+ if (i == PHY_RESET_MAX_WAIT) {
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static u32
+bnx2_phy_get_pause_adv(struct bnx2 *bp)
+{
+ u32 adv = 0;
+
+ if ((bp->req_flow_ctrl & (FLOW_CTRL_RX | FLOW_CTRL_TX)) ==
+ (FLOW_CTRL_RX | FLOW_CTRL_TX)) {
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ adv = ADVERTISE_1000XPAUSE;
+ }
+ else {
+ adv = ADVERTISE_PAUSE_CAP;
+ }
+ }
+ else if (bp->req_flow_ctrl & FLOW_CTRL_TX) {
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ adv = ADVERTISE_1000XPSE_ASYM;
+ }
+ else {
+ adv = ADVERTISE_PAUSE_ASYM;
+ }
+ }
+ else if (bp->req_flow_ctrl & FLOW_CTRL_RX) {
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ adv = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
+ }
+ else {
+ adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+ }
+ }
+ return adv;
+}
+
+static int
+bnx2_setup_serdes_phy(struct bnx2 *bp)
+{
+ u32 adv, bmcr, up1;
+ u32 new_adv = 0;
+
+ if (!(bp->autoneg & AUTONEG_SPEED)) {
+ u32 new_bmcr;
+ int force_link_down = 0;
+
+ if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ bnx2_read_phy(bp, BCM5708S_UP1, &up1);
+ if (up1 & BCM5708S_UP1_2G5) {
+ up1 &= ~BCM5708S_UP1_2G5;
+ bnx2_write_phy(bp, BCM5708S_UP1, up1);
+ force_link_down = 1;
+ }
+ }
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &adv);
+ adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF);
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ new_bmcr = bmcr & ~BMCR_ANENABLE;
+ new_bmcr |= BMCR_SPEED1000;
+ if (bp->req_duplex == DUPLEX_FULL) {
+ adv |= ADVERTISE_1000XFULL;
+ new_bmcr |= BMCR_FULLDPLX;
+ }
+ else {
+ adv |= ADVERTISE_1000XHALF;
+ new_bmcr &= ~BMCR_FULLDPLX;
+ }
+ if ((new_bmcr != bmcr) || (force_link_down)) {
+ /* Force a link down visible on the other side */
+ if (bp->link_up) {
+ bnx2_write_phy(bp, MII_ADVERTISE, adv &
+ ~(ADVERTISE_1000XFULL |
+ ADVERTISE_1000XHALF));
+ bnx2_write_phy(bp, MII_BMCR, bmcr |
+ BMCR_ANRESTART | BMCR_ANENABLE);
+
+ bp->link_up = 0;
+ bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+ }
+ bnx2_write_phy(bp, MII_ADVERTISE, adv);
+ bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+ }
+ return 0;
+ }
+
+ if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) {
+ bnx2_read_phy(bp, BCM5708S_UP1, &up1);
+ up1 |= BCM5708S_UP1_2G5;
+ bnx2_write_phy(bp, BCM5708S_UP1, up1);
+ }
+
+ if (bp->advertising & ADVERTISED_1000baseT_Full)
+ new_adv |= ADVERTISE_1000XFULL;
+
+ new_adv |= bnx2_phy_get_pause_adv(bp);
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &adv);
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+
+ bp->serdes_an_pending = 0;
+ if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) {
+ /* Force a link down visible on the other side */
+ if (bp->link_up) {
+ int i;
+
+ bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
+ for (i = 0; i < 110; i++) {
+ udelay(100);
+ }
+ }
+
+ bnx2_write_phy(bp, MII_ADVERTISE, new_adv);
+ bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART |
+ BMCR_ANENABLE);
+#if 0
+ if (CHIP_NUM(bp) == CHIP_NUM_5706) {
+ /* Speed up link-up time when the link partner
+ * does not autonegotiate which is very common
+ * in blade servers. Some blade servers use
+ * IPMI for kerboard input and it's important
+ * to minimize link disruptions. Autoneg. involves
+ * exchanging base pages plus 3 next pages and
+ * normally completes in about 120 msec.
+ */
+ bp->current_interval = SERDES_AN_TIMEOUT;
+ bp->serdes_an_pending = 1;
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
+ }
+#endif
+ }
+
+ return 0;
+}
+
+#define ETHTOOL_ALL_FIBRE_SPEED \
+ (ADVERTISED_1000baseT_Full)
+
+#define ETHTOOL_ALL_COPPER_SPEED \
+ (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
+ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
+ ADVERTISED_1000baseT_Full)
+
+#define PHY_ALL_10_100_SPEED (ADVERTISE_10HALF | ADVERTISE_10FULL | \
+ ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_CSMA)
+
+#define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL)
+
+static int
+bnx2_setup_copper_phy(struct bnx2 *bp)
+{
+ u32 bmcr;
+ u32 new_bmcr;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+
+ if (bp->autoneg & AUTONEG_SPEED) {
+ u32 adv_reg, adv1000_reg;
+ u32 new_adv_reg = 0;
+ u32 new_adv1000_reg = 0;
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &adv_reg);
+ adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP |
+ ADVERTISE_PAUSE_ASYM);
+
+ bnx2_read_phy(bp, MII_CTRL1000, &adv1000_reg);
+ adv1000_reg &= PHY_ALL_1000_SPEED;
+
+ if (bp->advertising & ADVERTISED_10baseT_Half)
+ new_adv_reg |= ADVERTISE_10HALF;
+ if (bp->advertising & ADVERTISED_10baseT_Full)
+ new_adv_reg |= ADVERTISE_10FULL;
+ if (bp->advertising & ADVERTISED_100baseT_Half)
+ new_adv_reg |= ADVERTISE_100HALF;
+ if (bp->advertising & ADVERTISED_100baseT_Full)
+ new_adv_reg |= ADVERTISE_100FULL;
+ if (bp->advertising & ADVERTISED_1000baseT_Full)
+ new_adv1000_reg |= ADVERTISE_1000FULL;
+
+ new_adv_reg |= ADVERTISE_CSMA;
+
+ new_adv_reg |= bnx2_phy_get_pause_adv(bp);
+
+ if ((adv1000_reg != new_adv1000_reg) ||
+ (adv_reg != new_adv_reg) ||
+ ((bmcr & BMCR_ANENABLE) == 0)) {
+
+ bnx2_write_phy(bp, MII_ADVERTISE, new_adv_reg);
+ bnx2_write_phy(bp, MII_CTRL1000, new_adv1000_reg);
+ bnx2_write_phy(bp, MII_BMCR, BMCR_ANRESTART |
+ BMCR_ANENABLE);
+ }
+ else if (bp->link_up) {
+ /* Flow ctrl may have changed from auto to forced */
+ /* or vice-versa. */
+
+ bnx2_resolve_flow_ctrl(bp);
+ bnx2_set_mac_link(bp);
+ }
+ return 0;
+ }
+
+ new_bmcr = 0;
+ if (bp->req_line_speed == SPEED_100) {
+ new_bmcr |= BMCR_SPEED100;
+ }
+ if (bp->req_duplex == DUPLEX_FULL) {
+ new_bmcr |= BMCR_FULLDPLX;
+ }
+ if (new_bmcr != bmcr) {
+ u32 bmsr;
+ int i = 0;
+
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+
+ if (bmsr & BMSR_LSTATUS) {
+ /* Force link down */
+ bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
+ do {
+ udelay(100);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ i++;
+ } while ((bmsr & BMSR_LSTATUS) && (i < 620));
+ }
+
+ bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+
+ /* Normally, the new speed is setup after the link has
+ * gone down and up again. In some cases, link will not go
+ * down so we need to set up the new speed here.
+ */
+ if (bmsr & BMSR_LSTATUS) {
+ bp->line_speed = bp->req_line_speed;
+ bp->duplex = bp->req_duplex;
+ bnx2_resolve_flow_ctrl(bp);
+ bnx2_set_mac_link(bp);
+ }
+ }
+ return 0;
+}
+
+static int
+bnx2_setup_phy(struct bnx2 *bp)
+{
+ if (bp->loopback == MAC_LOOPBACK)
+ return 0;
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ return (bnx2_setup_serdes_phy(bp));
+ }
+ else {
+ return (bnx2_setup_copper_phy(bp));
+ }
+}
+
+static int
+bnx2_init_5708s_phy(struct bnx2 *bp)
+{
+ u32 val;
+
+ bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG3);
+ bnx2_write_phy(bp, BCM5708S_DIG_3_0, BCM5708S_DIG_3_0_USE_IEEE);
+ bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG);
+
+ bnx2_read_phy(bp, BCM5708S_1000X_CTL1, &val);
+ val |= BCM5708S_1000X_CTL1_FIBER_MODE | BCM5708S_1000X_CTL1_AUTODET_EN;
+ bnx2_write_phy(bp, BCM5708S_1000X_CTL1, val);
+
+ bnx2_read_phy(bp, BCM5708S_1000X_CTL2, &val);
+ val |= BCM5708S_1000X_CTL2_PLLEL_DET_EN;
+ bnx2_write_phy(bp, BCM5708S_1000X_CTL2, val);
+
+ if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) {
+ bnx2_read_phy(bp, BCM5708S_UP1, &val);
+ val |= BCM5708S_UP1_2G5;
+ bnx2_write_phy(bp, BCM5708S_UP1, val);
+ }
+
+ if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
+ (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
+ (CHIP_ID(bp) == CHIP_ID_5708_B1)) {
+ /* increase tx signal amplitude */
+ bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
+ BCM5708S_BLK_ADDR_TX_MISC);
+ bnx2_read_phy(bp, BCM5708S_TX_ACTL1, &val);
+ val &= ~BCM5708S_TX_ACTL1_DRIVER_VCM;
+ bnx2_write_phy(bp, BCM5708S_TX_ACTL1, val);
+ bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG);
+ }
+
+ val = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG) &
+ BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK;
+
+ if (val) {
+ u32 is_backplane;
+
+ is_backplane = REG_RD_IND(bp, bp->shmem_base +
+ BNX2_SHARED_HW_CFG_CONFIG);
+ if (is_backplane & BNX2_SHARED_HW_CFG_PHY_BACKPLANE) {
+ bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
+ BCM5708S_BLK_ADDR_TX_MISC);
+ bnx2_write_phy(bp, BCM5708S_TX_ACTL3, val);
+ bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
+ BCM5708S_BLK_ADDR_DIG);
+ }
+ }
+ return 0;
+}
+
+static int
+bnx2_init_5706s_phy(struct bnx2 *bp)
+{
+ u32 val;
+
+ bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
+
+ if (CHIP_NUM(bp) == CHIP_NUM_5706) {
+ REG_WR(bp, BNX2_MISC_UNUSED0, 0x300);
+ }
+
+
+ bnx2_write_phy(bp, 0x18, 0x7);
+ bnx2_read_phy(bp, 0x18, &val);
+ bnx2_write_phy(bp, 0x18, val & ~0x4007);
+
+ bnx2_write_phy(bp, 0x1c, 0x6c00);
+ bnx2_read_phy(bp, 0x1c, &val);
+ bnx2_write_phy(bp, 0x1c, (val & 0x3fd) | 0xec00);
+
+ return 0;
+}
+
+static int
+bnx2_init_copper_phy(struct bnx2 *bp)
+{
+ u32 val;
+
+ bp->phy_flags |= PHY_CRC_FIX_FLAG;
+
+ if (bp->phy_flags & PHY_CRC_FIX_FLAG) {
+ bnx2_write_phy(bp, 0x18, 0x0c00);
+ bnx2_write_phy(bp, 0x17, 0x000a);
+ bnx2_write_phy(bp, 0x15, 0x310b);
+ bnx2_write_phy(bp, 0x17, 0x201f);
+ bnx2_write_phy(bp, 0x15, 0x9506);
+ bnx2_write_phy(bp, 0x17, 0x401f);
+ bnx2_write_phy(bp, 0x15, 0x14e2);
+ bnx2_write_phy(bp, 0x18, 0x0400);
+ }
+
+ bnx2_write_phy(bp, 0x18, 0x7);
+ bnx2_read_phy(bp, 0x18, &val);
+ bnx2_write_phy(bp, 0x18, val & ~0x4007);
+
+ bnx2_read_phy(bp, 0x10, &val);
+ bnx2_write_phy(bp, 0x10, val & ~0x1);
+
+ /* ethernet@wirespeed */
+ bnx2_write_phy(bp, 0x18, 0x7007);
+ bnx2_read_phy(bp, 0x18, &val);
+ bnx2_write_phy(bp, 0x18, val | (1 << 15) | (1 << 4));
+ return 0;
+}
+
+static int
+bnx2_init_phy(struct bnx2 *bp)
+{
+ u32 val;
+ int rc = 0;
+
+ bp->phy_flags &= ~PHY_INT_MODE_MASK_FLAG;
+ bp->phy_flags |= PHY_INT_MODE_LINK_READY_FLAG;
+
+ REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
+
+ bnx2_reset_phy(bp);
+
+ bnx2_read_phy(bp, MII_PHYSID1, &val);
+ bp->phy_id = val << 16;
+ bnx2_read_phy(bp, MII_PHYSID2, &val);
+ bp->phy_id |= val & 0xffff;
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ if (CHIP_NUM(bp) == CHIP_NUM_5706)
+ rc = bnx2_init_5706s_phy(bp);
+ else if (CHIP_NUM(bp) == CHIP_NUM_5708)
+ rc = bnx2_init_5708s_phy(bp);
+ }
+ else {
+ rc = bnx2_init_copper_phy(bp);
+ }
+
+ bnx2_setup_phy(bp);
+
+ return rc;
+}
+
+static int
+bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent)
+{
+ int i;
+ u32 val;
+
+ bp->fw_wr_seq++;
+ msg_data |= bp->fw_wr_seq;
+
+ REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data);
+
+ /* wait for an acknowledgement. */
+ for (i = 0; i < (FW_ACK_TIME_OUT_MS / 50); i++) {
+ mdelay(50);
+
+ val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_MB);
+
+ if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ))
+ break;
+ }
+ if ((msg_data & BNX2_DRV_MSG_DATA) == BNX2_DRV_MSG_DATA_WAIT0)
+ return 0;
+
+ /* If we timed out, inform the firmware that this is the case. */
+ if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) {
+ if (!silent)
+ printf("fw sync timeout, reset code = %x\n", (unsigned int) msg_data);
+
+ msg_data &= ~BNX2_DRV_MSG_CODE;
+ msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT;
+
+ REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data);
+
+ return -EBUSY;
+ }
+
+ if ((val & BNX2_FW_MSG_STATUS_MASK) != BNX2_FW_MSG_STATUS_OK)
+ return -EIO;
+
+ return 0;
+}
+
+static void
+bnx2_init_context(struct bnx2 *bp)
+{
+ u32 vcid;
+
+ vcid = 96;
+ while (vcid) {
+ u32 vcid_addr, pcid_addr, offset;
+
+ vcid--;
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ u32 new_vcid;
+
+ vcid_addr = GET_PCID_ADDR(vcid);
+ if (vcid & 0x8) {
+ new_vcid = 0x60 + (vcid & 0xf0) + (vcid & 0x7);
+ }
+ else {
+ new_vcid = vcid;
+ }
+ pcid_addr = GET_PCID_ADDR(new_vcid);
+ }
+ else {
+ vcid_addr = GET_CID_ADDR(vcid);
+ pcid_addr = vcid_addr;
+ }
+
+ REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00);
+ REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+
+ /* Zero out the context. */
+ for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) {
+ CTX_WR(bp, 0x00, offset, 0);
+ }
+
+ REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
+ REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+ }
+}
+
+static int
+bnx2_alloc_bad_rbuf(struct bnx2 *bp)
+{
+ u16 good_mbuf[512];
+ u32 good_mbuf_cnt;
+ u32 val;
+
+ REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+ BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE);
+
+ good_mbuf_cnt = 0;
+
+ /* Allocate a bunch of mbufs and save the good ones in an array. */
+ val = REG_RD_IND(bp, BNX2_RBUF_STATUS1);
+ while (val & BNX2_RBUF_STATUS1_FREE_COUNT) {
+ REG_WR_IND(bp, BNX2_RBUF_COMMAND, BNX2_RBUF_COMMAND_ALLOC_REQ);
+
+ val = REG_RD_IND(bp, BNX2_RBUF_FW_BUF_ALLOC);
+
+ val &= BNX2_RBUF_FW_BUF_ALLOC_VALUE;
+
+ /* The addresses with Bit 9 set are bad memory blocks. */
+ if (!(val & (1 << 9))) {
+ good_mbuf[good_mbuf_cnt] = (u16) val;
+ good_mbuf_cnt++;
+ }
+
+ val = REG_RD_IND(bp, BNX2_RBUF_STATUS1);
+ }
+
+ /* Free the good ones back to the mbuf pool thus discarding
+ * all the bad ones. */
+ while (good_mbuf_cnt) {
+ good_mbuf_cnt--;
+
+ val = good_mbuf[good_mbuf_cnt];
+ val = (val << 9) | val | 1;
+
+ REG_WR_IND(bp, BNX2_RBUF_FW_BUF_FREE, val);
+ }
+ return 0;
+}
+
+static void
+bnx2_set_mac_addr(struct bnx2 *bp)
+{
+ u32 val;
+ u8 *mac_addr = bp->nic->node_addr;
+
+ val = (mac_addr[0] << 8) | mac_addr[1];
+
+ REG_WR(bp, BNX2_EMAC_MAC_MATCH0, val);
+
+ val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
+ (mac_addr[4] << 8) | mac_addr[5];
+
+ REG_WR(bp, BNX2_EMAC_MAC_MATCH1, val);
+}
+
+static void
+bnx2_set_rx_mode(struct nic *nic __unused)
+{
+ struct bnx2 *bp = &bnx2;
+ u32 rx_mode, sort_mode;
+ int i;
+
+ rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
+ BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
+ sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN;
+
+ if (!(bp->flags & ASF_ENABLE_FLAG)) {
+ rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
+ }
+
+ /* Accept all multicasts */
+ for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
+ REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
+ 0xffffffff);
+ }
+ sort_mode |= BNX2_RPM_SORT_USER0_MC_EN;
+
+ if (rx_mode != bp->rx_mode) {
+ bp->rx_mode = rx_mode;
+ REG_WR(bp, BNX2_EMAC_RX_MODE, rx_mode);
+ }
+
+ REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
+ REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode);
+ REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA);
+}
+
+static void
+load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len, u32 rv2p_proc)
+{
+ unsigned int i;
+ u32 val;
+
+
+ for (i = 0; i < rv2p_code_len; i += 8) {
+ REG_WR(bp, BNX2_RV2P_INSTR_HIGH, *rv2p_code);
+ rv2p_code++;
+ REG_WR(bp, BNX2_RV2P_INSTR_LOW, *rv2p_code);
+ rv2p_code++;
+
+ if (rv2p_proc == RV2P_PROC1) {
+ val = (i / 8) | BNX2_RV2P_PROC1_ADDR_CMD_RDWR;
+ REG_WR(bp, BNX2_RV2P_PROC1_ADDR_CMD, val);
+ }
+ else {
+ val = (i / 8) | BNX2_RV2P_PROC2_ADDR_CMD_RDWR;
+ REG_WR(bp, BNX2_RV2P_PROC2_ADDR_CMD, val);
+ }
+ }
+
+ /* Reset the processor, un-stall is done later. */
+ if (rv2p_proc == RV2P_PROC1) {
+ REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET);
+ }
+ else {
+ REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET);
+ }
+}
+
+static void
+load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
+{
+ u32 offset;
+ u32 val;
+
+ /* Halt the CPU. */
+ val = REG_RD_IND(bp, cpu_reg->mode);
+ val |= cpu_reg->mode_value_halt;
+ REG_WR_IND(bp, cpu_reg->mode, val);
+ REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear);
+
+ /* Load the Text area. */
+ offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
+ if (fw->text) {
+ unsigned int j;
+
+ for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->text[j]);
+ }
+ }
+
+ /* Load the Data area. */
+ offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base);
+ if (fw->data) {
+ unsigned int j;
+
+ for (j = 0; j < (fw->data_len / 4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->data[j]);
+ }
+ }
+
+ /* Load the SBSS area. */
+ offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base);
+ if (fw->sbss) {
+ unsigned int j;
+
+ for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->sbss[j]);
+ }
+ }
+
+ /* Load the BSS area. */
+ offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base);
+ if (fw->bss) {
+ unsigned int j;
+
+ for (j = 0; j < (fw->bss_len/4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->bss[j]);
+ }
+ }
+
+ /* Load the Read-Only area. */
+ offset = cpu_reg->spad_base +
+ (fw->rodata_addr - cpu_reg->mips_view_base);
+ if (fw->rodata) {
+ unsigned int j;
+
+ for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->rodata[j]);
+ }
+ }
+
+ /* Clear the pre-fetch instruction. */
+ REG_WR_IND(bp, cpu_reg->inst, 0);
+ REG_WR_IND(bp, cpu_reg->pc, fw->start_addr);
+
+ /* Start the CPU. */
+ val = REG_RD_IND(bp, cpu_reg->mode);
+ val &= ~cpu_reg->mode_value_halt;
+ REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear);
+ REG_WR_IND(bp, cpu_reg->mode, val);
+}
+
+static void
+bnx2_init_cpus(struct bnx2 *bp)
+{
+ struct cpu_reg cpu_reg;
+ struct fw_info fw;
+
+ /* Unfortunately, it looks like we need to load the firmware
+ * before the card will work properly. That means this driver
+ * will be huge by Etherboot standards (approx. 50K compressed).
+ */
+
+ /* Initialize the RV2P processor. */
+ load_rv2p_fw(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), RV2P_PROC1);
+ load_rv2p_fw(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), RV2P_PROC2);
+
+ /* Initialize the RX Processor. */
+ cpu_reg.mode = BNX2_RXP_CPU_MODE;
+ cpu_reg.mode_value_halt = BNX2_RXP_CPU_MODE_SOFT_HALT;
+ cpu_reg.mode_value_sstep = BNX2_RXP_CPU_MODE_STEP_ENA;
+ cpu_reg.state = BNX2_RXP_CPU_STATE;
+ cpu_reg.state_value_clear = 0xffffff;
+ cpu_reg.gpr0 = BNX2_RXP_CPU_REG_FILE;
+ cpu_reg.evmask = BNX2_RXP_CPU_EVENT_MASK;
+ cpu_reg.pc = BNX2_RXP_CPU_PROGRAM_COUNTER;
+ cpu_reg.inst = BNX2_RXP_CPU_INSTRUCTION;
+ cpu_reg.bp = BNX2_RXP_CPU_HW_BREAKPOINT;
+ cpu_reg.spad_base = BNX2_RXP_SCRATCH;
+ cpu_reg.mips_view_base = 0x8000000;
+
+ fw.ver_major = bnx2_RXP_b06FwReleaseMajor;
+ fw.ver_minor = bnx2_RXP_b06FwReleaseMinor;
+ fw.ver_fix = bnx2_RXP_b06FwReleaseFix;
+ fw.start_addr = bnx2_RXP_b06FwStartAddr;
+
+ fw.text_addr = bnx2_RXP_b06FwTextAddr;
+ fw.text_len = bnx2_RXP_b06FwTextLen;
+ fw.text_index = 0;
+ fw.text = bnx2_RXP_b06FwText;
+
+ fw.data_addr = bnx2_RXP_b06FwDataAddr;
+ fw.data_len = bnx2_RXP_b06FwDataLen;
+ fw.data_index = 0;
+ fw.data = bnx2_RXP_b06FwData;
+
+ fw.sbss_addr = bnx2_RXP_b06FwSbssAddr;
+ fw.sbss_len = bnx2_RXP_b06FwSbssLen;
+ fw.sbss_index = 0;
+ fw.sbss = bnx2_RXP_b06FwSbss;
+
+ fw.bss_addr = bnx2_RXP_b06FwBssAddr;
+ fw.bss_len = bnx2_RXP_b06FwBssLen;
+ fw.bss_index = 0;
+ fw.bss = bnx2_RXP_b06FwBss;
+
+ fw.rodata_addr = bnx2_RXP_b06FwRodataAddr;
+ fw.rodata_len = bnx2_RXP_b06FwRodataLen;
+ fw.rodata_index = 0;
+ fw.rodata = bnx2_RXP_b06FwRodata;
+
+ load_cpu_fw(bp, &cpu_reg, &fw);
+
+ /* Initialize the TX Processor. */
+ cpu_reg.mode = BNX2_TXP_CPU_MODE;
+ cpu_reg.mode_value_halt = BNX2_TXP_CPU_MODE_SOFT_HALT;
+ cpu_reg.mode_value_sstep = BNX2_TXP_CPU_MODE_STEP_ENA;
+ cpu_reg.state = BNX2_TXP_CPU_STATE;
+ cpu_reg.state_value_clear = 0xffffff;
+ cpu_reg.gpr0 = BNX2_TXP_CPU_REG_FILE;
+ cpu_reg.evmask = BNX2_TXP_CPU_EVENT_MASK;
+ cpu_reg.pc = BNX2_TXP_CPU_PROGRAM_COUNTER;
+ cpu_reg.inst = BNX2_TXP_CPU_INSTRUCTION;
+ cpu_reg.bp = BNX2_TXP_CPU_HW_BREAKPOINT;
+ cpu_reg.spad_base = BNX2_TXP_SCRATCH;
+ cpu_reg.mips_view_base = 0x8000000;
+
+ fw.ver_major = bnx2_TXP_b06FwReleaseMajor;
+ fw.ver_minor = bnx2_TXP_b06FwReleaseMinor;
+ fw.ver_fix = bnx2_TXP_b06FwReleaseFix;
+ fw.start_addr = bnx2_TXP_b06FwStartAddr;
+
+ fw.text_addr = bnx2_TXP_b06FwTextAddr;
+ fw.text_len = bnx2_TXP_b06FwTextLen;
+ fw.text_index = 0;
+ fw.text = bnx2_TXP_b06FwText;
+
+ fw.data_addr = bnx2_TXP_b06FwDataAddr;
+ fw.data_len = bnx2_TXP_b06FwDataLen;
+ fw.data_index = 0;
+ fw.data = bnx2_TXP_b06FwData;
+
+ fw.sbss_addr = bnx2_TXP_b06FwSbssAddr;
+ fw.sbss_len = bnx2_TXP_b06FwSbssLen;
+ fw.sbss_index = 0;
+ fw.sbss = bnx2_TXP_b06FwSbss;
+
+ fw.bss_addr = bnx2_TXP_b06FwBssAddr;
+ fw.bss_len = bnx2_TXP_b06FwBssLen;
+ fw.bss_index = 0;
+ fw.bss = bnx2_TXP_b06FwBss;
+
+ fw.rodata_addr = bnx2_TXP_b06FwRodataAddr;
+ fw.rodata_len = bnx2_TXP_b06FwRodataLen;
+ fw.rodata_index = 0;
+ fw.rodata = bnx2_TXP_b06FwRodata;
+
+ load_cpu_fw(bp, &cpu_reg, &fw);
+
+ /* Initialize the TX Patch-up Processor. */
+ cpu_reg.mode = BNX2_TPAT_CPU_MODE;
+ cpu_reg.mode_value_halt = BNX2_TPAT_CPU_MODE_SOFT_HALT;
+ cpu_reg.mode_value_sstep = BNX2_TPAT_CPU_MODE_STEP_ENA;
+ cpu_reg.state = BNX2_TPAT_CPU_STATE;
+ cpu_reg.state_value_clear = 0xffffff;
+ cpu_reg.gpr0 = BNX2_TPAT_CPU_REG_FILE;
+ cpu_reg.evmask = BNX2_TPAT_CPU_EVENT_MASK;
+ cpu_reg.pc = BNX2_TPAT_CPU_PROGRAM_COUNTER;
+ cpu_reg.inst = BNX2_TPAT_CPU_INSTRUCTION;
+ cpu_reg.bp = BNX2_TPAT_CPU_HW_BREAKPOINT;
+ cpu_reg.spad_base = BNX2_TPAT_SCRATCH;
+ cpu_reg.mips_view_base = 0x8000000;
+
+ fw.ver_major = bnx2_TPAT_b06FwReleaseMajor;
+ fw.ver_minor = bnx2_TPAT_b06FwReleaseMinor;
+ fw.ver_fix = bnx2_TPAT_b06FwReleaseFix;
+ fw.start_addr = bnx2_TPAT_b06FwStartAddr;
+
+ fw.text_addr = bnx2_TPAT_b06FwTextAddr;
+ fw.text_len = bnx2_TPAT_b06FwTextLen;
+ fw.text_index = 0;
+ fw.text = bnx2_TPAT_b06FwText;
+
+ fw.data_addr = bnx2_TPAT_b06FwDataAddr;
+ fw.data_len = bnx2_TPAT_b06FwDataLen;
+ fw.data_index = 0;
+ fw.data = bnx2_TPAT_b06FwData;
+
+ fw.sbss_addr = bnx2_TPAT_b06FwSbssAddr;
+ fw.sbss_len = bnx2_TPAT_b06FwSbssLen;
+ fw.sbss_index = 0;
+ fw.sbss = bnx2_TPAT_b06FwSbss;
+
+ fw.bss_addr = bnx2_TPAT_b06FwBssAddr;
+ fw.bss_len = bnx2_TPAT_b06FwBssLen;
+ fw.bss_index = 0;
+ fw.bss = bnx2_TPAT_b06FwBss;
+
+ fw.rodata_addr = bnx2_TPAT_b06FwRodataAddr;
+ fw.rodata_len = bnx2_TPAT_b06FwRodataLen;
+ fw.rodata_index = 0;
+ fw.rodata = bnx2_TPAT_b06FwRodata;
+
+ load_cpu_fw(bp, &cpu_reg, &fw);
+
+ /* Initialize the Completion Processor. */
+ cpu_reg.mode = BNX2_COM_CPU_MODE;
+ cpu_reg.mode_value_halt = BNX2_COM_CPU_MODE_SOFT_HALT;
+ cpu_reg.mode_value_sstep = BNX2_COM_CPU_MODE_STEP_ENA;
+ cpu_reg.state = BNX2_COM_CPU_STATE;
+ cpu_reg.state_value_clear = 0xffffff;
+ cpu_reg.gpr0 = BNX2_COM_CPU_REG_FILE;
+ cpu_reg.evmask = BNX2_COM_CPU_EVENT_MASK;
+ cpu_reg.pc = BNX2_COM_CPU_PROGRAM_COUNTER;
+ cpu_reg.inst = BNX2_COM_CPU_INSTRUCTION;
+ cpu_reg.bp = BNX2_COM_CPU_HW_BREAKPOINT;
+ cpu_reg.spad_base = BNX2_COM_SCRATCH;
+ cpu_reg.mips_view_base = 0x8000000;
+
+ fw.ver_major = bnx2_COM_b06FwReleaseMajor;
+ fw.ver_minor = bnx2_COM_b06FwReleaseMinor;
+ fw.ver_fix = bnx2_COM_b06FwReleaseFix;
+ fw.start_addr = bnx2_COM_b06FwStartAddr;
+
+ fw.text_addr = bnx2_COM_b06FwTextAddr;
+ fw.text_len = bnx2_COM_b06FwTextLen;
+ fw.text_index = 0;
+ fw.text = bnx2_COM_b06FwText;
+
+ fw.data_addr = bnx2_COM_b06FwDataAddr;
+ fw.data_len = bnx2_COM_b06FwDataLen;
+ fw.data_index = 0;
+ fw.data = bnx2_COM_b06FwData;
+
+ fw.sbss_addr = bnx2_COM_b06FwSbssAddr;
+ fw.sbss_len = bnx2_COM_b06FwSbssLen;
+ fw.sbss_index = 0;
+ fw.sbss = bnx2_COM_b06FwSbss;
+
+ fw.bss_addr = bnx2_COM_b06FwBssAddr;
+ fw.bss_len = bnx2_COM_b06FwBssLen;
+ fw.bss_index = 0;
+ fw.bss = bnx2_COM_b06FwBss;
+
+ fw.rodata_addr = bnx2_COM_b06FwRodataAddr;
+ fw.rodata_len = bnx2_COM_b06FwRodataLen;
+ fw.rodata_index = 0;
+ fw.rodata = bnx2_COM_b06FwRodata;
+
+ load_cpu_fw(bp, &cpu_reg, &fw);
+
+}
+
+static int
+bnx2_set_power_state_0(struct bnx2 *bp)
+{
+ u16 pmcsr;
+ u32 val;
+
+ pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
+
+ pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
+ (pmcsr & ~PCI_PM_CTRL_STATE_MASK) |
+ PCI_PM_CTRL_PME_STATUS);
+
+ if (pmcsr & PCI_PM_CTRL_STATE_MASK)
+ /* delay required during transition out of D3hot */
+ mdelay(20);
+
+ val = REG_RD(bp, BNX2_EMAC_MODE);
+ val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD;
+ val &= ~BNX2_EMAC_MODE_MPKT;
+ REG_WR(bp, BNX2_EMAC_MODE, val);
+
+ val = REG_RD(bp, BNX2_RPM_CONFIG);
+ val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
+ REG_WR(bp, BNX2_RPM_CONFIG, val);
+
+ return 0;
+}
+
+static void
+bnx2_enable_nvram_access(struct bnx2 *bp)
+{
+ u32 val;
+
+ val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
+ /* Enable both bits, even on read. */
+ REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
+ val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN);
+}
+
+static void
+bnx2_disable_nvram_access(struct bnx2 *bp)
+{
+ u32 val;
+
+ val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
+ /* Disable both bits, even after read. */
+ REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
+ val & ~(BNX2_NVM_ACCESS_ENABLE_EN |
+ BNX2_NVM_ACCESS_ENABLE_WR_EN));
+}
+
+static int
+bnx2_init_nvram(struct bnx2 *bp)
+{
+ u32 val;
+ int j, entry_count, rc;
+ struct flash_spec *flash;
+
+ /* Determine the selected interface. */
+ val = REG_RD(bp, BNX2_NVM_CFG1);
+
+ entry_count = sizeof(flash_table) / sizeof(struct flash_spec);
+
+ rc = 0;
+ if (val & 0x40000000) {
+ /* Flash interface has been reconfigured */
+ for (j = 0, flash = &flash_table[0]; j < entry_count;
+ j++, flash++) {
+ if ((val & FLASH_BACKUP_STRAP_MASK) ==
+ (flash->config1 & FLASH_BACKUP_STRAP_MASK)) {
+ bp->flash_info = flash;
+ break;
+ }
+ }
+ }
+ else {
+ u32 mask;
+ /* Not yet been reconfigured */
+
+ if (val & (1 << 23))
+ mask = FLASH_BACKUP_STRAP_MASK;
+ else
+ mask = FLASH_STRAP_MASK;
+
+ for (j = 0, flash = &flash_table[0]; j < entry_count;
+ j++, flash++) {
+
+ if ((val & mask) == (flash->strapping & mask)) {
+ bp->flash_info = flash;
+
+ /* Enable access to flash interface */
+ bnx2_enable_nvram_access(bp);
+
+ /* Reconfigure the flash interface */
+ REG_WR(bp, BNX2_NVM_CFG1, flash->config1);
+ REG_WR(bp, BNX2_NVM_CFG2, flash->config2);
+ REG_WR(bp, BNX2_NVM_CFG3, flash->config3);
+ REG_WR(bp, BNX2_NVM_WRITE1, flash->write1);
+
+ /* Disable access to flash interface */
+ bnx2_disable_nvram_access(bp);
+
+ break;
+ }
+ }
+ } /* if (val & 0x40000000) */
+
+ if (j == entry_count) {
+ bp->flash_info = NULL;
+ printf("Unknown flash/EEPROM type.\n");
+ return -ENODEV;
+ }
+
+ val = REG_RD_IND(bp, bp->shmem_base + BNX2_SHARED_HW_CFG_CONFIG2);
+ val &= BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK;
+ if (val) {
+ bp->flash_size = val;
+ }
+ else {
+ bp->flash_size = bp->flash_info->total_size;
+ }
+
+ return rc;
+}
+
+static int
+bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
+{
+ u32 val;
+ int i, rc = 0;
+
+ /* Wait for the current PCI transaction to complete before
+ * issuing a reset. */
+ REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
+ BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
+ BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
+ BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
+ BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
+ val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
+ udelay(5);
+
+
+ /* Wait for the firmware to tell us it is ok to issue a reset. */
+ bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1);
+
+ /* Deposit a driver reset signature so the firmware knows that
+ * this is a soft reset. */
+ REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_RESET_SIGNATURE,
+ BNX2_DRV_RESET_SIGNATURE_MAGIC);
+
+ /* Do a dummy read to force the chip to complete all current transaction
+ * before we issue a reset. */
+ val = REG_RD(bp, BNX2_MISC_ID);
+
+ val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
+ BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+ BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
+
+ /* Chip reset. */
+ REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
+
+ if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
+ (CHIP_ID(bp) == CHIP_ID_5706_A1))
+ mdelay(15);
+
+ /* Reset takes approximate 30 usec */
+ for (i = 0; i < 10; i++) {
+ val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG);
+ if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
+ BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) {
+ break;
+ }
+ udelay(10);
+ }
+
+ if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
+ BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
+ printf("Chip reset did not complete\n");
+ return -EBUSY;
+ }
+
+ /* Make sure byte swapping is properly configured. */
+ val = REG_RD(bp, BNX2_PCI_SWAP_DIAG0);
+ if (val != 0x01020304) {
+ printf("Chip not in correct endian mode\n");
+ return -ENODEV;
+ }
+
+ /* Wait for the firmware to finish its initialization. */
+ rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code, 0);
+ if (rc) {
+ return rc;
+ }
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ /* Adjust the voltage regular to two steps lower. The default
+ * of this register is 0x0000000e. */
+ REG_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa);
+
+ /* Remove bad rbuf memory from the free pool. */
+ rc = bnx2_alloc_bad_rbuf(bp);
+ }
+
+ return rc;
+}
+
+static void
+bnx2_disable(struct nic *nic __unused)
+{
+ struct bnx2* bp = &bnx2;
+
+ if (bp->regview) {
+ bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_UNLOAD);
+ iounmap(bp->regview);
+ }
+}
+
+static int
+bnx2_init_chip(struct bnx2 *bp)
+{
+ u32 val;
+ int rc;
+
+ /* Make sure the interrupt is not active. */
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
+
+ val = BNX2_DMA_CONFIG_DATA_BYTE_SWAP |
+ BNX2_DMA_CONFIG_DATA_WORD_SWAP |
+#if __BYTE_ORDER == __BIG_ENDIAN
+ BNX2_DMA_CONFIG_CNTL_BYTE_SWAP |
+#endif
+ BNX2_DMA_CONFIG_CNTL_WORD_SWAP |
+ DMA_READ_CHANS << 12 |
+ DMA_WRITE_CHANS << 16;
+
+ val |= (0x2 << 20) | (1 << 11);
+
+ if ((bp->flags & PCIX_FLAG) && (bp->bus_speed_mhz == 133))
+ val |= (1 << 23);
+
+ if ((CHIP_NUM(bp) == CHIP_NUM_5706) &&
+ (CHIP_ID(bp) != CHIP_ID_5706_A0) && !(bp->flags & PCIX_FLAG))
+ val |= BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA;
+
+ REG_WR(bp, BNX2_DMA_CONFIG, val);
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ val = REG_RD(bp, BNX2_TDMA_CONFIG);
+ val |= BNX2_TDMA_CONFIG_ONE_DMA;
+ REG_WR(bp, BNX2_TDMA_CONFIG, val);
+ }
+
+ if (bp->flags & PCIX_FLAG) {
+ u16 val16;
+
+ pci_read_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD,
+ &val16);
+ pci_write_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD,
+ val16 & ~PCI_X_CMD_ERO);
+ }
+
+ REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+ BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
+ BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
+ BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
+
+ /* Initialize context mapping and zero out the quick contexts. The
+ * context block must have already been enabled. */
+ bnx2_init_context(bp);
+
+ bnx2_init_nvram(bp);
+ bnx2_init_cpus(bp);
+
+ bnx2_set_mac_addr(bp);
+
+ val = REG_RD(bp, BNX2_MQ_CONFIG);
+ val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
+ val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
+ REG_WR(bp, BNX2_MQ_CONFIG, val);
+
+ val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE);
+ REG_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val);
+ REG_WR(bp, BNX2_MQ_KNL_WIND_END, val);
+
+ val = (BCM_PAGE_BITS - 8) << 24;
+ REG_WR(bp, BNX2_RV2P_CONFIG, val);
+
+ /* Configure page size. */
+ val = REG_RD(bp, BNX2_TBDR_CONFIG);
+ val &= ~BNX2_TBDR_CONFIG_PAGE_SIZE;
+ val |= (BCM_PAGE_BITS - 8) << 24 | 0x40;
+ REG_WR(bp, BNX2_TBDR_CONFIG, val);
+
+ val = bp->mac_addr[0] +
+ (bp->mac_addr[1] << 8) +
+ (bp->mac_addr[2] << 16) +
+ bp->mac_addr[3] +
+ (bp->mac_addr[4] << 8) +
+ (bp->mac_addr[5] << 16);
+ REG_WR(bp, BNX2_EMAC_BACKOFF_SEED, val);
+
+ /* Program the MTU. Also include 4 bytes for CRC32. */
+ val = ETH_MAX_MTU + ETH_HLEN + 4;
+ if (val > (MAX_ETHERNET_PACKET_SIZE + 4))
+ val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA;
+ REG_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
+
+ bp->last_status_idx = 0;
+ bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE;
+
+ /* Set up how to generate a link change interrupt. */
+ REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
+
+ REG_WR(bp, BNX2_HC_STATUS_ADDR_L,
+ (u64) bp->status_blk_mapping & 0xffffffff);
+ REG_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32);
+
+ REG_WR(bp, BNX2_HC_STATISTICS_ADDR_L,
+ (u64) bp->stats_blk_mapping & 0xffffffff);
+ REG_WR(bp, BNX2_HC_STATISTICS_ADDR_H,
+ (u64) bp->stats_blk_mapping >> 32);
+
+ REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP,
+ (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip);
+
+ REG_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP,
+ (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip);
+
+ REG_WR(bp, BNX2_HC_COMP_PROD_TRIP,
+ (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip);
+
+ REG_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks);
+
+ REG_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks);
+
+ REG_WR(bp, BNX2_HC_COM_TICKS,
+ (bp->com_ticks_int << 16) | bp->com_ticks);
+
+ REG_WR(bp, BNX2_HC_CMD_TICKS,
+ (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
+
+ REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00);
+ REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A1)
+ REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_COLLECT_STATS);
+ else {
+ REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_RX_TMR_MODE |
+ BNX2_HC_CONFIG_TX_TMR_MODE |
+ BNX2_HC_CONFIG_COLLECT_STATS);
+ }
+
+ /* Clear internal stats counters. */
+ REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
+
+ REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE);
+
+ if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) &
+ BNX2_PORT_FEATURE_ASF_ENABLED)
+ bp->flags |= ASF_ENABLE_FLAG;
+
+ /* Initialize the receive filter. */
+ bnx2_set_rx_mode(bp->nic);
+
+ rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
+ 0);
+
+ REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff);
+ REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
+
+ udelay(20);
+
+ bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND);
+
+ return rc;
+}
+
+static void
+bnx2_init_tx_ring(struct bnx2 *bp)
+{
+ struct tx_bd *txbd;
+ u32 val;
+
+ txbd = &bp->tx_desc_ring[MAX_TX_DESC_CNT];
+
+ /* Etherboot lives below 4GB, so hi is always 0 */
+ txbd->tx_bd_haddr_hi = 0;
+ txbd->tx_bd_haddr_lo = bp->tx_desc_mapping;
+
+ bp->tx_prod = 0;
+ bp->tx_cons = 0;
+ bp->hw_tx_cons = 0;
+ bp->tx_prod_bseq = 0;
+
+ val = BNX2_L2CTX_TYPE_TYPE_L2;
+ val |= BNX2_L2CTX_TYPE_SIZE_L2;
+ CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TYPE, val);
+
+ val = BNX2_L2CTX_CMD_TYPE_TYPE_L2;
+ val |= 8 << 16;
+ CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_CMD_TYPE, val);
+
+ /* Etherboot lives below 4GB, so hi is always 0 */
+ CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_HI, 0);
+
+ val = (u64) bp->tx_desc_mapping & 0xffffffff;
+ CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_LO, val);
+}
+
+static void
+bnx2_init_rx_ring(struct bnx2 *bp)
+{
+ struct rx_bd *rxbd;
+ unsigned int i;
+ u16 prod, ring_prod;
+ u32 val;
+
+ bp->rx_buf_use_size = RX_BUF_USE_SIZE;
+ bp->rx_buf_size = RX_BUF_SIZE;
+
+ ring_prod = prod = bp->rx_prod = 0;
+ bp->rx_cons = 0;
+ bp->hw_rx_cons = 0;
+ bp->rx_prod_bseq = 0;
+
+ memset(bnx2_bss.rx_buf, 0, sizeof(bnx2_bss.rx_buf));
+
+ rxbd = &bp->rx_desc_ring[0];
+ for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
+ rxbd->rx_bd_len = bp->rx_buf_use_size;
+ rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
+ }
+ rxbd->rx_bd_haddr_hi = 0;
+ rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping & 0xffffffff;
+
+ val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
+ val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
+ val |= 0x02 << 8;
+ CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_CTX_TYPE, val);
+
+ /* Etherboot doesn't use memory above 4GB, so this is always 0 */
+ CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_HI, 0);
+
+ val = bp->rx_desc_mapping & 0xffffffff;
+ CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val);
+
+ for (i = 0; (int) i < bp->rx_ring_size; i++) {
+ rxbd = &bp->rx_desc_ring[RX_RING_IDX(ring_prod)];
+ rxbd->rx_bd_haddr_hi = 0;
+ rxbd->rx_bd_haddr_lo = virt_to_bus(&bnx2_bss.rx_buf[ring_prod][0]);
+ bp->rx_prod_bseq += bp->rx_buf_use_size;
+ prod = NEXT_RX_BD(prod);
+ ring_prod = RX_RING_IDX(prod);
+ }
+ bp->rx_prod = prod;
+
+ REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, bp->rx_prod);
+
+ REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq);
+}
+
+static int
+bnx2_reset_nic(struct bnx2 *bp, u32 reset_code)
+{
+ int rc;
+
+ rc = bnx2_reset_chip(bp, reset_code);
+ if (rc) {
+ return rc;
+ }
+
+ bnx2_init_chip(bp);
+ bnx2_init_tx_ring(bp);
+ bnx2_init_rx_ring(bp);
+ return 0;
+}
+
+static int
+bnx2_init_nic(struct bnx2 *bp)
+{
+ int rc;
+
+ if ((rc = bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET)) != 0)
+ return rc;
+
+ bnx2_init_phy(bp);
+ bnx2_set_link(bp);
+ return 0;
+}
+
+static int
+bnx2_init_board(struct pci_device *pdev, struct nic *nic)
+{
+ unsigned long bnx2reg_base, bnx2reg_len;
+ struct bnx2 *bp = &bnx2;
+ int rc;
+ u32 reg;
+
+ bp->flags = 0;
+ bp->phy_flags = 0;
+
+ /* enable device (incl. PCI PM wakeup), and bus-mastering */
+ adjust_pci_device(pdev);
+
+ nic->ioaddr = pdev->ioaddr & ~3;
+ nic->irqno = 0;
+
+ rc = 0;
+ bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
+ if (bp->pm_cap == 0) {
+ printf("Cannot find power management capability, aborting.\n");
+ rc = -EIO;
+ goto err_out_disable;
+ }
+
+ bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
+ if (bp->pcix_cap == 0) {
+ printf("Cannot find PCIX capability, aborting.\n");
+ rc = -EIO;
+ goto err_out_disable;
+ }
+
+ bp->pdev = pdev;
+ bp->nic = nic;
+
+ bnx2reg_base = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
+ bnx2reg_len = MB_GET_CID_ADDR(17);
+
+ bp->regview = ioremap(bnx2reg_base, bnx2reg_len);
+
+ if (!bp->regview) {
+ printf("Cannot map register space, aborting.\n");
+ rc = -EIO;
+ goto err_out_disable;
+ }
+
+ /* Configure byte swap and enable write to the reg_window registers.
+ * Rely on CPU to do target byte swapping on big endian systems
+ * The chip's target access swapping will not swap all accesses
+ */
+ pci_write_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG,
+ BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+ BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
+
+ bnx2_set_power_state_0(bp);
+
+ bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
+
+ /* Get bus information. */
+ reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS);
+ if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) {
+ u32 clkreg;
+
+ bp->flags |= PCIX_FLAG;
+
+ clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS);
+
+ clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
+ switch (clkreg) {
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
+ bp->bus_speed_mhz = 133;
+ break;
+
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
+ bp->bus_speed_mhz = 100;
+ break;
+
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
+ bp->bus_speed_mhz = 66;
+ break;
+
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
+ bp->bus_speed_mhz = 50;
+ break;
+
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW:
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
+ bp->bus_speed_mhz = 33;
+ break;
+ }
+ }
+ else {
+ if (reg & BNX2_PCICFG_MISC_STATUS_M66EN)
+ bp->bus_speed_mhz = 66;
+ else
+ bp->bus_speed_mhz = 33;
+ }
+
+ if (reg & BNX2_PCICFG_MISC_STATUS_32BIT_DET)
+ bp->flags |= PCI_32BIT_FLAG;
+
+ /* 5706A0 may falsely detect SERR and PERR. */
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ reg = REG_RD(bp, PCI_COMMAND);
+ reg &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
+ REG_WR(bp, PCI_COMMAND, reg);
+ }
+ else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) &&
+ !(bp->flags & PCIX_FLAG)) {
+
+ printf("5706 A1 can only be used in a PCIX bus, aborting.\n");
+ goto err_out_disable;
+ }
+
+ bnx2_init_nvram(bp);
+
+ reg = REG_RD_IND(bp, BNX2_SHM_HDR_SIGNATURE);
+
+ if ((reg & BNX2_SHM_HDR_SIGNATURE_SIG_MASK) ==
+ BNX2_SHM_HDR_SIGNATURE_SIG)
+ bp->shmem_base = REG_RD_IND(bp, BNX2_SHM_HDR_ADDR_0);
+ else
+ bp->shmem_base = HOST_VIEW_SHMEM_BASE;
+
+ /* Get the permanent MAC address. First we need to make sure the
+ * firmware is actually running.
+ */
+ reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_SIGNATURE);
+
+ if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
+ BNX2_DEV_INFO_SIGNATURE_MAGIC) {
+ printf("Firmware not running, aborting.\n");
+ rc = -ENODEV;
+ goto err_out_disable;
+ }
+
+ bp->fw_ver = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV);
+
+ reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_UPPER);
+ bp->mac_addr[0] = (u8) (reg >> 8);
+ bp->mac_addr[1] = (u8) reg;
+
+ reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_LOWER);
+ bp->mac_addr[2] = (u8) (reg >> 24);
+ bp->mac_addr[3] = (u8) (reg >> 16);
+ bp->mac_addr[4] = (u8) (reg >> 8);
+ bp->mac_addr[5] = (u8) reg;
+
+ bp->tx_ring_size = MAX_TX_DESC_CNT;
+ bp->rx_ring_size = RX_BUF_CNT;
+ bp->rx_max_ring_idx = MAX_RX_DESC_CNT;
+
+ bp->rx_offset = RX_OFFSET;
+
+ bp->tx_quick_cons_trip_int = 20;
+ bp->tx_quick_cons_trip = 20;
+ bp->tx_ticks_int = 80;
+ bp->tx_ticks = 80;
+
+ bp->rx_quick_cons_trip_int = 6;
+ bp->rx_quick_cons_trip = 6;
+ bp->rx_ticks_int = 18;
+ bp->rx_ticks = 18;
+
+ bp->stats_ticks = 1000000 & 0xffff00;
+
+ bp->phy_addr = 1;
+
+ /* No need for WOL support in Etherboot */
+ bp->flags |= NO_WOL_FLAG;
+
+ /* Disable WOL support if we are running on a SERDES chip. */
+ if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) {
+ bp->phy_flags |= PHY_SERDES_FLAG;
+ if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ bp->phy_addr = 2;
+ reg = REG_RD_IND(bp, bp->shmem_base +
+ BNX2_SHARED_HW_CFG_CONFIG);
+ if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
+ bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG;
+ }
+ }
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ bp->tx_quick_cons_trip_int =
+ bp->tx_quick_cons_trip;
+ bp->tx_ticks_int = bp->tx_ticks;
+ bp->rx_quick_cons_trip_int =
+ bp->rx_quick_cons_trip;
+ bp->rx_ticks_int = bp->rx_ticks;
+ bp->comp_prod_trip_int = bp->comp_prod_trip;
+ bp->com_ticks_int = bp->com_ticks;
+ bp->cmd_ticks_int = bp->cmd_ticks;
+ }
+
+ bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL;
+ bp->req_line_speed = 0;
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
+
+ reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG);
+ reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
+ if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
+ bp->autoneg = 0;
+ bp->req_line_speed = bp->line_speed = SPEED_1000;
+ bp->req_duplex = DUPLEX_FULL;
+ }
+ }
+ else {
+ bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
+ }
+
+ bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX;
+
+ /* Disable driver heartbeat checking */
+ REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB,
+ BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE);
+ REG_RD_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB);
+
+ return 0;
+
+err_out_disable:
+ bnx2_disable(nic);
+
+ return rc;
+}
+
+static void
+bnx2_transmit(struct nic *nic, const char *dst_addr,
+ unsigned int type, unsigned int size, const char *packet)
+{
+ /* Sometimes the nic will be behind by a frame. Using two transmit
+ * buffers prevents us from timing out in that case.
+ */
+ static struct eth_frame {
+ uint8_t dst_addr[ETH_ALEN];
+ uint8_t src_addr[ETH_ALEN];
+ uint16_t type;
+ uint8_t data [ETH_FRAME_LEN - ETH_HLEN];
+ } frame[2];
+ static int frame_idx = 0;
+
+ /* send the packet to destination */
+ struct tx_bd *txbd;
+ struct bnx2 *bp = &bnx2;
+ u16 prod, ring_prod;
+ u16 hw_cons;
+ int i = 0;
+
+ prod = bp->tx_prod;
+ ring_prod = TX_RING_IDX(prod);
+ hw_cons = bp->status_blk->status_tx_quick_consumer_index0;
+ if ((hw_cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT) {
+ hw_cons++;
+ }
+
+ while((hw_cons != prod) && (hw_cons != (PREV_TX_BD(prod)))) {
+ mdelay(10); /* give the nic a chance */
+ //poll_interruptions();
+ if (++i > 500) { /* timeout 5s for transmit */
+ printf("transmit timed out\n");
+ bnx2_disable(bp->nic);
+ bnx2_init_board(bp->pdev, bp->nic);
+ return;
+ }
+ }
+ if (i != 0) {
+ printf("#");
+ }
+
+ /* Copy the packet to the our local buffer */
+ memcpy(&frame[frame_idx].dst_addr, dst_addr, ETH_ALEN);
+ memcpy(&frame[frame_idx].src_addr, nic->node_addr, ETH_ALEN);
+ frame[frame_idx].type = htons(type);
+ memset(&frame[frame_idx].data, 0, sizeof(frame[frame_idx].data));
+ memcpy(&frame[frame_idx].data, packet, size);
+
+ /* Setup the ring buffer entry to transmit */
+ txbd = &bp->tx_desc_ring[ring_prod];
+ txbd->tx_bd_haddr_hi = 0; /* Etherboot runs under 4GB */
+ txbd->tx_bd_haddr_lo = virt_to_bus(&frame[frame_idx]);
+ txbd->tx_bd_mss_nbytes = (size + ETH_HLEN);
+ txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END;
+
+ /* Advance to the next entry */
+ prod = NEXT_TX_BD(prod);
+ frame_idx ^= 1;
+
+ bp->tx_prod_bseq += (size + ETH_HLEN);
+
+ REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, prod);
+ REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq);
+
+ wmb();
+
+ bp->tx_prod = prod;
+}
+
+static int
+bnx2_poll_link(struct bnx2 *bp)
+{
+ u32 new_link_state, old_link_state, emac_status;
+
+ new_link_state = bp->status_blk->status_attn_bits &
+ STATUS_ATTN_BITS_LINK_STATE;
+
+ old_link_state = bp->status_blk->status_attn_bits_ack &
+ STATUS_ATTN_BITS_LINK_STATE;
+
+ if (!new_link_state && !old_link_state) {
+ /* For some reason the card doesn't always update the link
+ * status bits properly. Kick the stupid thing and try again.
+ */
+ u32 bmsr;
+
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+
+ if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+ (CHIP_NUM(bp) == CHIP_NUM_5706)) {
+ REG_RD(bp, BNX2_EMAC_STATUS);
+ }
+
+ new_link_state = bp->status_blk->status_attn_bits &
+ STATUS_ATTN_BITS_LINK_STATE;
+
+ old_link_state = bp->status_blk->status_attn_bits_ack &
+ STATUS_ATTN_BITS_LINK_STATE;
+
+ /* Okay, for some reason the above doesn't work with some
+ * switches (like HP ProCurve). If the above doesn't work,
+ * check the MAC directly to see if we have a link. Perhaps we
+ * should always check the MAC instead probing the MII.
+ */
+ if (!new_link_state && !old_link_state) {
+ emac_status = REG_RD(bp, BNX2_EMAC_STATUS);
+ if (emac_status & BNX2_EMAC_STATUS_LINK_CHANGE) {
+ /* Acknowledge the link change */
+ REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
+ } else if (emac_status & BNX2_EMAC_STATUS_LINK) {
+ new_link_state = !old_link_state;
+ }
+ }
+
+ }
+
+ if (new_link_state != old_link_state) {
+ if (new_link_state) {
+ REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD,
+ STATUS_ATTN_BITS_LINK_STATE);
+ }
+ else {
+ REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD,
+ STATUS_ATTN_BITS_LINK_STATE);
+ }
+
+ bnx2_set_link(bp);
+
+ /* This is needed to take care of transient status
+ * during link changes.
+ */
+
+ REG_WR(bp, BNX2_HC_COMMAND,
+ bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+ REG_RD(bp, BNX2_HC_COMMAND);
+
+ }
+
+ return bp->link_up;
+}
+
+static int
+bnx2_poll(struct nic* nic, int retrieve)
+{
+ struct bnx2 *bp = &bnx2;
+ struct rx_bd *cons_bd, *prod_bd;
+ u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
+ struct l2_fhdr *rx_hdr;
+ int result = 0;
+ unsigned int len;
+ unsigned char *data;
+ u32 status;
+
+#if 0
+ if ((bp->status_blk->status_idx == bp->last_status_idx) &&
+ (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
+ BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) {
+
+ bp->last_status_idx = bp->status_blk->status_idx;
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
+ bp->last_status_idx);
+ return 0;
+ }
+#endif
+
+ if ((bp->status_blk->status_rx_quick_consumer_index0 != bp->rx_cons) && !retrieve)
+ return 1;
+
+ if (bp->status_blk->status_rx_quick_consumer_index0 != bp->rx_cons) {
+
+ hw_cons = bp->hw_rx_cons = bp->status_blk->status_rx_quick_consumer_index0;
+ if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) {
+ hw_cons++;
+ }
+ sw_cons = bp->rx_cons;
+ sw_prod = bp->rx_prod;
+
+ rmb();
+ if (sw_cons != hw_cons) {
+
+ sw_ring_cons = RX_RING_IDX(sw_cons);
+ sw_ring_prod = RX_RING_IDX(sw_prod);
+
+ data = bus_to_virt(bp->rx_desc_ring[sw_ring_cons].rx_bd_haddr_lo);
+
+ rx_hdr = (struct l2_fhdr *)data;
+ len = rx_hdr->l2_fhdr_pkt_len - 4;
+ if ((len > (ETH_MAX_MTU + ETH_HLEN)) ||
+ ((status = rx_hdr->l2_fhdr_status) &
+ (L2_FHDR_ERRORS_BAD_CRC |
+ L2_FHDR_ERRORS_PHY_DECODE |
+ L2_FHDR_ERRORS_ALIGNMENT |
+ L2_FHDR_ERRORS_TOO_SHORT |
+ L2_FHDR_ERRORS_GIANT_FRAME))) {
+ result = 0;
+ }
+ else
+ {
+ nic->packetlen = len;
+ memcpy(nic->packet, data + bp->rx_offset, len);
+ result = 1;
+ }
+
+ /* Reuse the buffer */
+ bp->rx_prod_bseq += bp->rx_buf_use_size;
+ if (sw_cons != sw_prod) {
+ cons_bd = &bp->rx_desc_ring[sw_ring_cons];
+ prod_bd = &bp->rx_desc_ring[sw_ring_prod];
+ prod_bd->rx_bd_haddr_hi = 0; /* Etherboot runs under 4GB */
+ prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
+ }
+
+ sw_cons = NEXT_RX_BD(sw_cons);
+ sw_prod = NEXT_RX_BD(sw_prod);
+
+ }
+
+ bp->rx_cons = sw_cons;
+ bp->rx_prod = sw_prod;
+
+ REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, bp->rx_prod);
+
+ REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq);
+
+ wmb();
+
+ }
+
+ bnx2_poll_link(bp);
+
+#if 0
+ bp->last_status_idx = bp->status_blk->status_idx;
+ rmb();
+
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
+ bp->last_status_idx);
+
+ REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+#endif
+
+ return result;
+}
+
+static void
+bnx2_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE: break;
+ case ENABLE: break;
+ case FORCE: break;
+ }
+}
+
+static struct nic_operations bnx2_operations = {
+ .connect = dummy_connect,
+ .poll = bnx2_poll,
+ .transmit = bnx2_transmit,
+ .irq = bnx2_irq,
+};
+
+static int
+bnx2_probe(struct nic *nic, struct pci_device *pdev)
+{
+ struct bnx2 *bp = &bnx2;
+ int i, rc;
+
+ if (pdev == 0)
+ return 0;
+
+ memset(bp, 0, sizeof(*bp));
+
+ rc = bnx2_init_board(pdev, nic);
+ if (rc < 0) {
+ return 0;
+ }
+
+ /*
+ nic->disable = bnx2_disable;
+ nic->transmit = bnx2_transmit;
+ nic->poll = bnx2_poll;
+ nic->irq = bnx2_irq;
+ */
+
+ nic->nic_op = &bnx2_operations;
+
+ memcpy(nic->node_addr, bp->mac_addr, ETH_ALEN);
+ printf("Ethernet addr: %s\n", eth_ntoa( nic->node_addr ) );
+ printf("Broadcom NetXtreme II (%c%d) PCI%s %s %dMHz\n",
+ (int) ((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
+ (int) ((CHIP_ID(bp) & 0x0ff0) >> 4),
+ ((bp->flags & PCIX_FLAG) ? "-X" : ""),
+ ((bp->flags & PCI_32BIT_FLAG) ? "32-bit" : "64-bit"),
+ bp->bus_speed_mhz);
+
+ bnx2_set_power_state_0(bp);
+ bnx2_disable_int(bp);
+
+ bnx2_alloc_mem(bp);
+
+ rc = bnx2_init_nic(bp);
+ if (rc) {
+ return 0;
+ }
+
+ bnx2_poll_link(bp);
+ for(i = 0; !bp->link_up && (i < VALID_LINK_TIMEOUT*100); i++) {
+ mdelay(1);
+ bnx2_poll_link(bp);
+ }
+#if 1
+ if (!bp->link_up){
+ printf("Valid link not established\n");
+ goto err_out_disable;
+ }
+#endif
+
+ return 1;
+
+err_out_disable:
+ bnx2_disable(nic);
+ return 0;
+}
+
+static struct pci_device_id bnx2_nics[] = {
+ PCI_ROM(0x14e4, 0x164a, "bnx2-5706", "Broadcom NetXtreme II BCM5706", 0),
+ PCI_ROM(0x14e4, 0x164c, "bnx2-5708", "Broadcom NetXtreme II BCM5708", 0),
+ PCI_ROM(0x14e4, 0x16aa, "bnx2-5706S", "Broadcom NetXtreme II BCM5706S", 0),
+ PCI_ROM(0x14e4, 0x16ac, "bnx2-5708S", "Broadcom NetXtreme II BCM5708S", 0),
+};
+
+PCI_DRIVER ( bnx2_driver, bnx2_nics, PCI_NO_CLASS );
+
+DRIVER ( "BNX2", nic_driver, pci_driver, bnx2_driver, bnx2_probe, bnx2_disable );
+
+/*
+static struct pci_driver bnx2_driver __pci_driver = {
+ .type = NIC_DRIVER,
+ .name = "BNX2",
+ .probe = bnx2_probe,
+ .ids = bnx2_nics,
+ .id_count = sizeof(bnx2_nics)/sizeof(bnx2_nics[0]),
+ .class = 0,
+};
+*/
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/bnx2.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/bnx2.h
new file mode 100644
index 00000000..92678680
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/bnx2.h
@@ -0,0 +1,4598 @@
+/* bnx2.h: Broadcom NX2 network driver.
+ *
+ * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Michael Chan (mchan@broadcom.com)
+ */
+
+FILE_LICENCE ( GPL_ANY );
+
+#ifndef BNX2_H
+#define BNX2_H
+
+#define L1_CACHE_BYTES 128 /* Rough approximaition of the cache line size */
+#define L1_CACHE_ALIGN(X) (((X) + L1_CACHE_BYTES-1)&~(L1_CACHE_BYTES -1))
+
+typedef unsigned long dma_addr_t;
+
+/* From pci.h */
+typedef int pci_power_t;
+
+#define PCI_D0 ((pci_power_t) 0)
+#define PCI_D1 ((pci_power_t) 1)
+#define PCI_D2 ((pci_power_t) 2)
+#define PCI_D3hot ((pci_power_t) 3)
+#define PCI_D3cold ((pci_power_t) 4)
+#define PCI_UNKNOWN ((pci_power_t) 5)
+#define PCI_POWER_ERROR ((pci_power_t) -1)
+
+/* From pci_regs.h */
+
+#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */
+#define PCI_X_CMD 2 /* Modes & Features */
+#define PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */
+
+/* From mii.h */
+
+/* Indicates what features are advertised by the interface. */
+#define ADVERTISED_10baseT_Half (1 << 0)
+#define ADVERTISED_10baseT_Full (1 << 1)
+#define ADVERTISED_100baseT_Half (1 << 2)
+#define ADVERTISED_100baseT_Full (1 << 3)
+#define ADVERTISED_1000baseT_Half (1 << 4)
+#define ADVERTISED_1000baseT_Full (1 << 5)
+#define ADVERTISED_Autoneg (1 << 6)
+#define ADVERTISED_TP (1 << 7)
+#define ADVERTISED_AUI (1 << 8)
+#define ADVERTISED_MII (1 << 9)
+#define ADVERTISED_FIBRE (1 << 10)
+#define ADVERTISED_BNC (1 << 11)
+
+/* The following are all involved in forcing a particular link
+ * mode for the device for setting things. When getting the
+ * devices settings, these indicate the current mode and whether
+ * it was foced up into this mode or autonegotiated.
+ */
+
+/* Duplex, half or full. */
+#define DUPLEX_HALF 0x00
+#define DUPLEX_FULL 0x01
+#define DUPLEX_INVALID 0x02
+
+/* Which connector port. */
+#define PORT_TP 0x00
+#define PORT_AUI 0x01
+#define PORT_MII 0x02
+#define PORT_FIBRE 0x03
+#define PORT_BNC 0x04
+
+/* Which tranceiver to use. */
+#define XCVR_INTERNAL 0x00
+#define XCVR_EXTERNAL 0x01
+#define XCVR_DUMMY1 0x02
+#define XCVR_DUMMY2 0x03
+#define XCVR_DUMMY3 0x04
+
+/* Enable or disable autonegotiation. If this is set to enable,
+ * the forced link modes above are completely ignored.
+ */
+#define AUTONEG_DISABLE 0x00
+#define AUTONEG_ENABLE 0x01
+
+/* Wake-On-Lan options. */
+#define WAKE_PHY (1 << 0)
+#define WAKE_UCAST (1 << 1)
+#define WAKE_MCAST (1 << 2)
+#define WAKE_BCAST (1 << 3)
+#define WAKE_ARP (1 << 4)
+#define WAKE_MAGIC (1 << 5)
+#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */
+
+/* The following are all involved in forcing a particular link
+ * * mode for the device for setting things. When getting the
+ * * devices settings, these indicate the current mode and whether
+ * * it was foced up into this mode or autonegotiated.
+ * */
+
+/* The forced speed, 10Mb, 100Mb, gigabit. */
+#define SPEED_10 10
+#define SPEED_100 100
+#define SPEED_1000 1000
+#define SPEED_2500 2500
+#define SPEED_INVALID 0 /* XXX was 3 */
+
+
+/* Duplex, half or full. */
+#define DUPLEX_HALF 0x00
+#define DUPLEX_FULL 0x01
+#define DUPLEX_INVALID 0x02
+
+/* Which connector port. */
+#define PORT_TP 0x00
+#define PORT_AUI 0x01
+#define PORT_MII 0x02
+#define PORT_FIBRE 0x03
+#define PORT_BNC 0x04
+
+/* Which tranceiver to use. */
+#define XCVR_INTERNAL 0x00
+#define XCVR_EXTERNAL 0x01
+#define XCVR_DUMMY1 0x02
+#define XCVR_DUMMY2 0x03
+#define XCVR_DUMMY3 0x04
+
+/* Enable or disable autonegotiation. If this is set to enable,
+ * * the forced link modes above are completely ignored.
+ * */
+#define AUTONEG_DISABLE 0x00
+#define AUTONEG_ENABLE 0x01
+
+/* Wake-On-Lan options. */
+#define WAKE_PHY (1 << 0)
+#define WAKE_UCAST (1 << 1)
+#define WAKE_MCAST (1 << 2)
+#define WAKE_BCAST (1 << 3)
+#define WAKE_ARP (1 << 4)
+#define WAKE_MAGIC (1 << 5)
+#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */
+
+/* Hardware data structures and register definitions automatically
+ * generated from RTL code. Do not modify.
+ */
+
+/*
+ * tx_bd definition
+ */
+struct tx_bd {
+ u32 tx_bd_haddr_hi;
+ u32 tx_bd_haddr_lo;
+ u32 tx_bd_mss_nbytes;
+ u32 tx_bd_vlan_tag_flags;
+ #define TX_BD_FLAGS_CONN_FAULT (1<<0)
+ #define TX_BD_FLAGS_TCP_UDP_CKSUM (1<<1)
+ #define TX_BD_FLAGS_IP_CKSUM (1<<2)
+ #define TX_BD_FLAGS_VLAN_TAG (1<<3)
+ #define TX_BD_FLAGS_COAL_NOW (1<<4)
+ #define TX_BD_FLAGS_DONT_GEN_CRC (1<<5)
+ #define TX_BD_FLAGS_END (1<<6)
+ #define TX_BD_FLAGS_START (1<<7)
+ #define TX_BD_FLAGS_SW_OPTION_WORD (0x1f<<8)
+ #define TX_BD_FLAGS_SW_FLAGS (1<<13)
+ #define TX_BD_FLAGS_SW_SNAP (1<<14)
+ #define TX_BD_FLAGS_SW_LSO (1<<15)
+
+};
+
+
+/*
+ * rx_bd definition
+ */
+struct rx_bd {
+ u32 rx_bd_haddr_hi;
+ u32 rx_bd_haddr_lo;
+ u32 rx_bd_len;
+ u32 rx_bd_flags;
+ #define RX_BD_FLAGS_NOPUSH (1<<0)
+ #define RX_BD_FLAGS_DUMMY (1<<1)
+ #define RX_BD_FLAGS_END (1<<2)
+ #define RX_BD_FLAGS_START (1<<3)
+
+};
+
+
+/*
+ * status_block definition
+ */
+struct status_block {
+ u32 status_attn_bits;
+ #define STATUS_ATTN_BITS_LINK_STATE (1L<<0)
+ #define STATUS_ATTN_BITS_TX_SCHEDULER_ABORT (1L<<1)
+ #define STATUS_ATTN_BITS_TX_BD_READ_ABORT (1L<<2)
+ #define STATUS_ATTN_BITS_TX_BD_CACHE_ABORT (1L<<3)
+ #define STATUS_ATTN_BITS_TX_PROCESSOR_ABORT (1L<<4)
+ #define STATUS_ATTN_BITS_TX_DMA_ABORT (1L<<5)
+ #define STATUS_ATTN_BITS_TX_PATCHUP_ABORT (1L<<6)
+ #define STATUS_ATTN_BITS_TX_ASSEMBLER_ABORT (1L<<7)
+ #define STATUS_ATTN_BITS_RX_PARSER_MAC_ABORT (1L<<8)
+ #define STATUS_ATTN_BITS_RX_PARSER_CATCHUP_ABORT (1L<<9)
+ #define STATUS_ATTN_BITS_RX_MBUF_ABORT (1L<<10)
+ #define STATUS_ATTN_BITS_RX_LOOKUP_ABORT (1L<<11)
+ #define STATUS_ATTN_BITS_RX_PROCESSOR_ABORT (1L<<12)
+ #define STATUS_ATTN_BITS_RX_V2P_ABORT (1L<<13)
+ #define STATUS_ATTN_BITS_RX_BD_CACHE_ABORT (1L<<14)
+ #define STATUS_ATTN_BITS_RX_DMA_ABORT (1L<<15)
+ #define STATUS_ATTN_BITS_COMPLETION_ABORT (1L<<16)
+ #define STATUS_ATTN_BITS_HOST_COALESCE_ABORT (1L<<17)
+ #define STATUS_ATTN_BITS_MAILBOX_QUEUE_ABORT (1L<<18)
+ #define STATUS_ATTN_BITS_CONTEXT_ABORT (1L<<19)
+ #define STATUS_ATTN_BITS_CMD_SCHEDULER_ABORT (1L<<20)
+ #define STATUS_ATTN_BITS_CMD_PROCESSOR_ABORT (1L<<21)
+ #define STATUS_ATTN_BITS_MGMT_PROCESSOR_ABORT (1L<<22)
+ #define STATUS_ATTN_BITS_MAC_ABORT (1L<<23)
+ #define STATUS_ATTN_BITS_TIMER_ABORT (1L<<24)
+ #define STATUS_ATTN_BITS_DMAE_ABORT (1L<<25)
+ #define STATUS_ATTN_BITS_FLSH_ABORT (1L<<26)
+ #define STATUS_ATTN_BITS_GRC_ABORT (1L<<27)
+ #define STATUS_ATTN_BITS_PARITY_ERROR (1L<<31)
+
+ u32 status_attn_bits_ack;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ u16 status_tx_quick_consumer_index0;
+ u16 status_tx_quick_consumer_index1;
+ u16 status_tx_quick_consumer_index2;
+ u16 status_tx_quick_consumer_index3;
+ u16 status_rx_quick_consumer_index0;
+ u16 status_rx_quick_consumer_index1;
+ u16 status_rx_quick_consumer_index2;
+ u16 status_rx_quick_consumer_index3;
+ u16 status_rx_quick_consumer_index4;
+ u16 status_rx_quick_consumer_index5;
+ u16 status_rx_quick_consumer_index6;
+ u16 status_rx_quick_consumer_index7;
+ u16 status_rx_quick_consumer_index8;
+ u16 status_rx_quick_consumer_index9;
+ u16 status_rx_quick_consumer_index10;
+ u16 status_rx_quick_consumer_index11;
+ u16 status_rx_quick_consumer_index12;
+ u16 status_rx_quick_consumer_index13;
+ u16 status_rx_quick_consumer_index14;
+ u16 status_rx_quick_consumer_index15;
+ u16 status_completion_producer_index;
+ u16 status_cmd_consumer_index;
+ u16 status_idx;
+ u16 status_unused;
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+ u16 status_tx_quick_consumer_index1;
+ u16 status_tx_quick_consumer_index0;
+ u16 status_tx_quick_consumer_index3;
+ u16 status_tx_quick_consumer_index2;
+ u16 status_rx_quick_consumer_index1;
+ u16 status_rx_quick_consumer_index0;
+ u16 status_rx_quick_consumer_index3;
+ u16 status_rx_quick_consumer_index2;
+ u16 status_rx_quick_consumer_index5;
+ u16 status_rx_quick_consumer_index4;
+ u16 status_rx_quick_consumer_index7;
+ u16 status_rx_quick_consumer_index6;
+ u16 status_rx_quick_consumer_index9;
+ u16 status_rx_quick_consumer_index8;
+ u16 status_rx_quick_consumer_index11;
+ u16 status_rx_quick_consumer_index10;
+ u16 status_rx_quick_consumer_index13;
+ u16 status_rx_quick_consumer_index12;
+ u16 status_rx_quick_consumer_index15;
+ u16 status_rx_quick_consumer_index14;
+ u16 status_cmd_consumer_index;
+ u16 status_completion_producer_index;
+ u16 status_unused;
+ u16 status_idx;
+#endif
+};
+
+
+/*
+ * statistics_block definition
+ */
+struct statistics_block {
+ u32 stat_IfHCInOctets_hi;
+ u32 stat_IfHCInOctets_lo;
+ u32 stat_IfHCInBadOctets_hi;
+ u32 stat_IfHCInBadOctets_lo;
+ u32 stat_IfHCOutOctets_hi;
+ u32 stat_IfHCOutOctets_lo;
+ u32 stat_IfHCOutBadOctets_hi;
+ u32 stat_IfHCOutBadOctets_lo;
+ u32 stat_IfHCInUcastPkts_hi;
+ u32 stat_IfHCInUcastPkts_lo;
+ u32 stat_IfHCInMulticastPkts_hi;
+ u32 stat_IfHCInMulticastPkts_lo;
+ u32 stat_IfHCInBroadcastPkts_hi;
+ u32 stat_IfHCInBroadcastPkts_lo;
+ u32 stat_IfHCOutUcastPkts_hi;
+ u32 stat_IfHCOutUcastPkts_lo;
+ u32 stat_IfHCOutMulticastPkts_hi;
+ u32 stat_IfHCOutMulticastPkts_lo;
+ u32 stat_IfHCOutBroadcastPkts_hi;
+ u32 stat_IfHCOutBroadcastPkts_lo;
+ u32 stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
+ u32 stat_Dot3StatsCarrierSenseErrors;
+ u32 stat_Dot3StatsFCSErrors;
+ u32 stat_Dot3StatsAlignmentErrors;
+ u32 stat_Dot3StatsSingleCollisionFrames;
+ u32 stat_Dot3StatsMultipleCollisionFrames;
+ u32 stat_Dot3StatsDeferredTransmissions;
+ u32 stat_Dot3StatsExcessiveCollisions;
+ u32 stat_Dot3StatsLateCollisions;
+ u32 stat_EtherStatsCollisions;
+ u32 stat_EtherStatsFragments;
+ u32 stat_EtherStatsJabbers;
+ u32 stat_EtherStatsUndersizePkts;
+ u32 stat_EtherStatsOverrsizePkts;
+ u32 stat_EtherStatsPktsRx64Octets;
+ u32 stat_EtherStatsPktsRx65Octetsto127Octets;
+ u32 stat_EtherStatsPktsRx128Octetsto255Octets;
+ u32 stat_EtherStatsPktsRx256Octetsto511Octets;
+ u32 stat_EtherStatsPktsRx512Octetsto1023Octets;
+ u32 stat_EtherStatsPktsRx1024Octetsto1522Octets;
+ u32 stat_EtherStatsPktsRx1523Octetsto9022Octets;
+ u32 stat_EtherStatsPktsTx64Octets;
+ u32 stat_EtherStatsPktsTx65Octetsto127Octets;
+ u32 stat_EtherStatsPktsTx128Octetsto255Octets;
+ u32 stat_EtherStatsPktsTx256Octetsto511Octets;
+ u32 stat_EtherStatsPktsTx512Octetsto1023Octets;
+ u32 stat_EtherStatsPktsTx1024Octetsto1522Octets;
+ u32 stat_EtherStatsPktsTx1523Octetsto9022Octets;
+ u32 stat_XonPauseFramesReceived;
+ u32 stat_XoffPauseFramesReceived;
+ u32 stat_OutXonSent;
+ u32 stat_OutXoffSent;
+ u32 stat_FlowControlDone;
+ u32 stat_MacControlFramesReceived;
+ u32 stat_XoffStateEntered;
+ u32 stat_IfInFramesL2FilterDiscards;
+ u32 stat_IfInRuleCheckerDiscards;
+ u32 stat_IfInFTQDiscards;
+ u32 stat_IfInMBUFDiscards;
+ u32 stat_IfInRuleCheckerP4Hit;
+ u32 stat_CatchupInRuleCheckerDiscards;
+ u32 stat_CatchupInFTQDiscards;
+ u32 stat_CatchupInMBUFDiscards;
+ u32 stat_CatchupInRuleCheckerP4Hit;
+ u32 stat_GenStat00;
+ u32 stat_GenStat01;
+ u32 stat_GenStat02;
+ u32 stat_GenStat03;
+ u32 stat_GenStat04;
+ u32 stat_GenStat05;
+ u32 stat_GenStat06;
+ u32 stat_GenStat07;
+ u32 stat_GenStat08;
+ u32 stat_GenStat09;
+ u32 stat_GenStat10;
+ u32 stat_GenStat11;
+ u32 stat_GenStat12;
+ u32 stat_GenStat13;
+ u32 stat_GenStat14;
+ u32 stat_GenStat15;
+};
+
+
+/*
+ * l2_fhdr definition
+ */
+struct l2_fhdr {
+ u32 l2_fhdr_status;
+ #define L2_FHDR_STATUS_RULE_CLASS (0x7<<0)
+ #define L2_FHDR_STATUS_RULE_P2 (1<<3)
+ #define L2_FHDR_STATUS_RULE_P3 (1<<4)
+ #define L2_FHDR_STATUS_RULE_P4 (1<<5)
+ #define L2_FHDR_STATUS_L2_VLAN_TAG (1<<6)
+ #define L2_FHDR_STATUS_L2_LLC_SNAP (1<<7)
+ #define L2_FHDR_STATUS_RSS_HASH (1<<8)
+ #define L2_FHDR_STATUS_IP_DATAGRAM (1<<13)
+ #define L2_FHDR_STATUS_TCP_SEGMENT (1<<14)
+ #define L2_FHDR_STATUS_UDP_DATAGRAM (1<<15)
+
+ #define L2_FHDR_ERRORS_BAD_CRC (1<<17)
+ #define L2_FHDR_ERRORS_PHY_DECODE (1<<18)
+ #define L2_FHDR_ERRORS_ALIGNMENT (1<<19)
+ #define L2_FHDR_ERRORS_TOO_SHORT (1<<20)
+ #define L2_FHDR_ERRORS_GIANT_FRAME (1<<21)
+ #define L2_FHDR_ERRORS_TCP_XSUM (1<<28)
+ #define L2_FHDR_ERRORS_UDP_XSUM (1<<31)
+
+ u32 l2_fhdr_hash;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ u16 l2_fhdr_pkt_len;
+ u16 l2_fhdr_vlan_tag;
+ u16 l2_fhdr_ip_xsum;
+ u16 l2_fhdr_tcp_udp_xsum;
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+ u16 l2_fhdr_vlan_tag;
+ u16 l2_fhdr_pkt_len;
+ u16 l2_fhdr_tcp_udp_xsum;
+ u16 l2_fhdr_ip_xsum;
+#endif
+};
+
+
+/*
+ * l2_context definition
+ */
+#define BNX2_L2CTX_TYPE 0x00000000
+#define BNX2_L2CTX_TYPE_SIZE_L2 ((0xc0/0x20)<<16)
+#define BNX2_L2CTX_TYPE_TYPE (0xf<<28)
+#define BNX2_L2CTX_TYPE_TYPE_EMPTY (0<<28)
+#define BNX2_L2CTX_TYPE_TYPE_L2 (1<<28)
+
+#define BNX2_L2CTX_TX_HOST_BIDX 0x00000088
+#define BNX2_L2CTX_EST_NBD 0x00000088
+#define BNX2_L2CTX_CMD_TYPE 0x00000088
+#define BNX2_L2CTX_CMD_TYPE_TYPE (0xf<<24)
+#define BNX2_L2CTX_CMD_TYPE_TYPE_L2 (0<<24)
+#define BNX2_L2CTX_CMD_TYPE_TYPE_TCP (1<<24)
+
+#define BNX2_L2CTX_TX_HOST_BSEQ 0x00000090
+#define BNX2_L2CTX_TSCH_BSEQ 0x00000094
+#define BNX2_L2CTX_TBDR_BSEQ 0x00000098
+#define BNX2_L2CTX_TBDR_BOFF 0x0000009c
+#define BNX2_L2CTX_TBDR_BIDX 0x0000009c
+#define BNX2_L2CTX_TBDR_BHADDR_HI 0x000000a0
+#define BNX2_L2CTX_TBDR_BHADDR_LO 0x000000a4
+#define BNX2_L2CTX_TXP_BOFF 0x000000a8
+#define BNX2_L2CTX_TXP_BIDX 0x000000a8
+#define BNX2_L2CTX_TXP_BSEQ 0x000000ac
+
+
+/*
+ * l2_bd_chain_context definition
+ */
+#define BNX2_L2CTX_BD_PRE_READ 0x00000000
+#define BNX2_L2CTX_CTX_SIZE 0x00000000
+#define BNX2_L2CTX_CTX_TYPE 0x00000000
+#define BNX2_L2CTX_CTX_TYPE_SIZE_L2 ((0x20/20)<<16)
+#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE (0xf<<28)
+#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_UNDEFINED (0<<28)
+#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE (1<<28)
+
+#define BNX2_L2CTX_HOST_BDIDX 0x00000004
+#define BNX2_L2CTX_HOST_BSEQ 0x00000008
+#define BNX2_L2CTX_NX_BSEQ 0x0000000c
+#define BNX2_L2CTX_NX_BDHADDR_HI 0x00000010
+#define BNX2_L2CTX_NX_BDHADDR_LO 0x00000014
+#define BNX2_L2CTX_NX_BDIDX 0x00000018
+
+
+/*
+ * pci_config_l definition
+ * offset: 0000
+ */
+#define BNX2_PCICFG_MISC_CONFIG 0x00000068
+#define BNX2_PCICFG_MISC_CONFIG_TARGET_BYTE_SWAP (1L<<2)
+#define BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP (1L<<3)
+#define BNX2_PCICFG_MISC_CONFIG_CLOCK_CTL_ENA (1L<<5)
+#define BNX2_PCICFG_MISC_CONFIG_TARGET_GRC_WORD_SWAP (1L<<6)
+#define BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA (1L<<7)
+#define BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ (1L<<8)
+#define BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY (1L<<9)
+#define BNX2_PCICFG_MISC_CONFIG_ASIC_METAL_REV (0xffL<<16)
+#define BNX2_PCICFG_MISC_CONFIG_ASIC_BASE_REV (0xfL<<24)
+#define BNX2_PCICFG_MISC_CONFIG_ASIC_ID (0xfL<<28)
+
+#define BNX2_PCICFG_MISC_STATUS 0x0000006c
+#define BNX2_PCICFG_MISC_STATUS_INTA_VALUE (1L<<0)
+#define BNX2_PCICFG_MISC_STATUS_32BIT_DET (1L<<1)
+#define BNX2_PCICFG_MISC_STATUS_M66EN (1L<<2)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_DET (1L<<3)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED (0x3L<<4)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_66 (0L<<4)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_100 (1L<<4)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_133 (2L<<4)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_PCI_MODE (3L<<4)
+
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS 0x00000070
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ (0L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ (1L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ (2L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ (3L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ (4L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ (5L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ (6L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ (7L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW (0xfL<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE (1L<<6)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT (1L<<7)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC (0x7L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF (0L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PLAY_DEAD (1L<<11)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_PLL_STOP (1L<<17)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_USE_SPD_DET (1L<<19)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20)
+
+#define BNX2_PCICFG_REG_WINDOW_ADDRESS 0x00000078
+#define BNX2_PCICFG_REG_WINDOW 0x00000080
+#define BNX2_PCICFG_INT_ACK_CMD 0x00000084
+#define BNX2_PCICFG_INT_ACK_CMD_INDEX (0xffffL<<0)
+#define BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID (1L<<16)
+#define BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM (1L<<17)
+#define BNX2_PCICFG_INT_ACK_CMD_MASK_INT (1L<<18)
+
+#define BNX2_PCICFG_STATUS_BIT_SET_CMD 0x00000088
+#define BNX2_PCICFG_STATUS_BIT_CLEAR_CMD 0x0000008c
+#define BNX2_PCICFG_MAILBOX_QUEUE_ADDR 0x00000090
+#define BNX2_PCICFG_MAILBOX_QUEUE_DATA 0x00000094
+
+
+/*
+ * pci_reg definition
+ * offset: 0x400
+ */
+#define BNX2_PCI_GRC_WINDOW_ADDR 0x00000400
+#define BNX2_PCI_GRC_WINDOW_ADDR_PCI_GRC_WINDOW_ADDR_VALUE (0x3ffffL<<8)
+
+#define BNX2_PCI_CONFIG_1 0x00000404
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY (0x7L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_OFF (0L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_16 (1L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_32 (2L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_64 (3L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_128 (4L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_256 (5L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_512 (6L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_1024 (7L<<8)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY (0x7L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_OFF (0L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_16 (1L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_32 (2L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_64 (3L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_128 (4L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_256 (5L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_512 (6L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_1024 (7L<<11)
+
+#define BNX2_PCI_CONFIG_2 0x00000408
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE (0xfL<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_DISABLED (0L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_64K (1L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_128K (2L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_256K (3L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_512K (4L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_1M (5L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_2M (6L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_4M (7L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_8M (8L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_16M (9L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_32M (10L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_64M (11L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_128M (12L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_256M (13L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_512M (14L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_1G (15L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_64ENA (1L<<4)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_RETRY (1L<<5)
+#define BNX2_PCI_CONFIG_2_CFG_CYCLE_RETRY (1L<<6)
+#define BNX2_PCI_CONFIG_2_FIRST_CFG_DONE (1L<<7)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE (0xffL<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_DISABLED (0L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1K (1L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2K (2L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4K (3L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8K (4L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16K (5L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_32K (6L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_64K (7L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_128K (8L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_256K (9L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_512K (10L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1M (11L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2M (12L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4M (13L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8M (14L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16M (15L<<8)
+#define BNX2_PCI_CONFIG_2_MAX_SPLIT_LIMIT (0x1fL<<16)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT (0x3L<<21)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_512 (0L<<21)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_1K (1L<<21)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_2K (2L<<21)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_4K (3L<<21)
+#define BNX2_PCI_CONFIG_2_FORCE_32_BIT_MSTR (1L<<23)
+#define BNX2_PCI_CONFIG_2_FORCE_32_BIT_TGT (1L<<24)
+#define BNX2_PCI_CONFIG_2_KEEP_REQ_ASSERT (1L<<25)
+
+#define BNX2_PCI_CONFIG_3 0x0000040c
+#define BNX2_PCI_CONFIG_3_STICKY_BYTE (0xffL<<0)
+#define BNX2_PCI_CONFIG_3_FORCE_PME (1L<<24)
+#define BNX2_PCI_CONFIG_3_PME_STATUS (1L<<25)
+#define BNX2_PCI_CONFIG_3_PME_ENABLE (1L<<26)
+#define BNX2_PCI_CONFIG_3_PM_STATE (0x3L<<27)
+#define BNX2_PCI_CONFIG_3_VAUX_PRESET (1L<<30)
+#define BNX2_PCI_CONFIG_3_PCI_POWER (1L<<31)
+
+#define BNX2_PCI_PM_DATA_A 0x00000410
+#define BNX2_PCI_PM_DATA_A_PM_DATA_0_PRG (0xffL<<0)
+#define BNX2_PCI_PM_DATA_A_PM_DATA_1_PRG (0xffL<<8)
+#define BNX2_PCI_PM_DATA_A_PM_DATA_2_PRG (0xffL<<16)
+#define BNX2_PCI_PM_DATA_A_PM_DATA_3_PRG (0xffL<<24)
+
+#define BNX2_PCI_PM_DATA_B 0x00000414
+#define BNX2_PCI_PM_DATA_B_PM_DATA_4_PRG (0xffL<<0)
+#define BNX2_PCI_PM_DATA_B_PM_DATA_5_PRG (0xffL<<8)
+#define BNX2_PCI_PM_DATA_B_PM_DATA_6_PRG (0xffL<<16)
+#define BNX2_PCI_PM_DATA_B_PM_DATA_7_PRG (0xffL<<24)
+
+#define BNX2_PCI_SWAP_DIAG0 0x00000418
+#define BNX2_PCI_SWAP_DIAG1 0x0000041c
+#define BNX2_PCI_EXP_ROM_ADDR 0x00000420
+#define BNX2_PCI_EXP_ROM_ADDR_ADDRESS (0x3fffffL<<2)
+#define BNX2_PCI_EXP_ROM_ADDR_REQ (1L<<31)
+
+#define BNX2_PCI_EXP_ROM_DATA 0x00000424
+#define BNX2_PCI_VPD_INTF 0x00000428
+#define BNX2_PCI_VPD_INTF_INTF_REQ (1L<<0)
+
+#define BNX2_PCI_VPD_ADDR_FLAG 0x0000042c
+#define BNX2_PCI_VPD_ADDR_FLAG_ADDRESS (0x1fff<<2)
+#define BNX2_PCI_VPD_ADDR_FLAG_WR (1<<15)
+
+#define BNX2_PCI_VPD_DATA 0x00000430
+#define BNX2_PCI_ID_VAL1 0x00000434
+#define BNX2_PCI_ID_VAL1_DEVICE_ID (0xffffL<<0)
+#define BNX2_PCI_ID_VAL1_VENDOR_ID (0xffffL<<16)
+
+#define BNX2_PCI_ID_VAL2 0x00000438
+#define BNX2_PCI_ID_VAL2_SUBSYSTEM_VENDOR_ID (0xffffL<<0)
+#define BNX2_PCI_ID_VAL2_SUBSYSTEM_ID (0xffffL<<16)
+
+#define BNX2_PCI_ID_VAL3 0x0000043c
+#define BNX2_PCI_ID_VAL3_CLASS_CODE (0xffffffL<<0)
+#define BNX2_PCI_ID_VAL3_REVISION_ID (0xffL<<24)
+
+#define BNX2_PCI_ID_VAL4 0x00000440
+#define BNX2_PCI_ID_VAL4_CAP_ENA (0xfL<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_0 (0L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_1 (1L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_2 (2L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_3 (3L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_4 (4L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_5 (5L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_6 (6L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_7 (7L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_8 (8L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_9 (9L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_10 (10L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_11 (11L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_12 (12L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_13 (13L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_14 (14L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_15 (15L<<0)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG (0x3L<<6)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_0 (0L<<6)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_1 (1L<<6)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_2 (2L<<6)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_3 (3L<<6)
+#define BNX2_PCI_ID_VAL4_MSI_LIMIT (0x7L<<9)
+#define BNX2_PCI_ID_VAL4_MSI_ADVERTIZE (0x7L<<12)
+#define BNX2_PCI_ID_VAL4_MSI_ENABLE (1L<<15)
+#define BNX2_PCI_ID_VAL4_MAX_64_ADVERTIZE (1L<<16)
+#define BNX2_PCI_ID_VAL4_MAX_133_ADVERTIZE (1L<<17)
+#define BNX2_PCI_ID_VAL4_MAX_MEM_READ_SIZE (0x3L<<21)
+#define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE (0x7L<<23)
+#define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE (0x7L<<26)
+
+#define BNX2_PCI_ID_VAL5 0x00000444
+#define BNX2_PCI_ID_VAL5_D1_SUPPORT (1L<<0)
+#define BNX2_PCI_ID_VAL5_D2_SUPPORT (1L<<1)
+#define BNX2_PCI_ID_VAL5_PME_IN_D0 (1L<<2)
+#define BNX2_PCI_ID_VAL5_PME_IN_D1 (1L<<3)
+#define BNX2_PCI_ID_VAL5_PME_IN_D2 (1L<<4)
+#define BNX2_PCI_ID_VAL5_PME_IN_D3_HOT (1L<<5)
+
+#define BNX2_PCI_PCIX_EXTENDED_STATUS 0x00000448
+#define BNX2_PCI_PCIX_EXTENDED_STATUS_NO_SNOOP (1L<<8)
+#define BNX2_PCI_PCIX_EXTENDED_STATUS_LONG_BURST (1L<<9)
+#define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_CLASS (0xfL<<16)
+#define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_IDX (0xffL<<24)
+
+#define BNX2_PCI_ID_VAL6 0x0000044c
+#define BNX2_PCI_ID_VAL6_MAX_LAT (0xffL<<0)
+#define BNX2_PCI_ID_VAL6_MIN_GNT (0xffL<<8)
+#define BNX2_PCI_ID_VAL6_BIST (0xffL<<16)
+
+#define BNX2_PCI_MSI_DATA 0x00000450
+#define BNX2_PCI_MSI_DATA_PCI_MSI_DATA (0xffffL<<0)
+
+#define BNX2_PCI_MSI_ADDR_H 0x00000454
+#define BNX2_PCI_MSI_ADDR_L 0x00000458
+
+
+/*
+ * misc_reg definition
+ * offset: 0x800
+ */
+#define BNX2_MISC_COMMAND 0x00000800
+#define BNX2_MISC_COMMAND_ENABLE_ALL (1L<<0)
+#define BNX2_MISC_COMMAND_DISABLE_ALL (1L<<1)
+#define BNX2_MISC_COMMAND_CORE_RESET (1L<<4)
+#define BNX2_MISC_COMMAND_HARD_RESET (1L<<5)
+#define BNX2_MISC_COMMAND_PAR_ERROR (1L<<8)
+#define BNX2_MISC_COMMAND_PAR_ERR_RAM (0x7fL<<16)
+
+#define BNX2_MISC_CFG 0x00000804
+#define BNX2_MISC_CFG_PCI_GRC_TMOUT (1L<<0)
+#define BNX2_MISC_CFG_NVM_WR_EN (0x3L<<1)
+#define BNX2_MISC_CFG_NVM_WR_EN_PROTECT (0L<<1)
+#define BNX2_MISC_CFG_NVM_WR_EN_PCI (1L<<1)
+#define BNX2_MISC_CFG_NVM_WR_EN_ALLOW (2L<<1)
+#define BNX2_MISC_CFG_NVM_WR_EN_ALLOW2 (3L<<1)
+#define BNX2_MISC_CFG_BIST_EN (1L<<3)
+#define BNX2_MISC_CFG_CK25_OUT_ALT_SRC (1L<<4)
+#define BNX2_MISC_CFG_BYPASS_BSCAN (1L<<5)
+#define BNX2_MISC_CFG_BYPASS_EJTAG (1L<<6)
+#define BNX2_MISC_CFG_CLK_CTL_OVERRIDE (1L<<7)
+#define BNX2_MISC_CFG_LEDMODE (0x3L<<8)
+#define BNX2_MISC_CFG_LEDMODE_MAC (0L<<8)
+#define BNX2_MISC_CFG_LEDMODE_GPHY1 (1L<<8)
+#define BNX2_MISC_CFG_LEDMODE_GPHY2 (2L<<8)
+
+#define BNX2_MISC_ID 0x00000808
+#define BNX2_MISC_ID_BOND_ID (0xfL<<0)
+#define BNX2_MISC_ID_CHIP_METAL (0xffL<<4)
+#define BNX2_MISC_ID_CHIP_REV (0xfL<<12)
+#define BNX2_MISC_ID_CHIP_NUM (0xffffL<<16)
+
+#define BNX2_MISC_ENABLE_STATUS_BITS 0x0000080c
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_READ_ENABLE (1L<<1)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_DMA_ENABLE (1L<<4)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PATCHUP_ENABLE (1L<<5)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+#define BNX2_MISC_ENABLE_STATUS_BITS_EMAC_ENABLE (1L<<9)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_MBUF_ENABLE (1L<<12)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_LOOKUP_ENABLE (1L<<13)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE (1L<<15)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_DMA_ENABLE (1L<<17)
+#define BNX2_MISC_ENABLE_STATUS_BITS_COMPLETION_ENABLE (1L<<18)
+#define BNX2_MISC_ENABLE_STATUS_BITS_HOST_COALESCE_ENABLE (1L<<19)
+#define BNX2_MISC_ENABLE_STATUS_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+#define BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE (1L<<21)
+#define BNX2_MISC_ENABLE_STATUS_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+#define BNX2_MISC_ENABLE_STATUS_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+#define BNX2_MISC_ENABLE_STATUS_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TIMER_ENABLE (1L<<25)
+#define BNX2_MISC_ENABLE_STATUS_BITS_DMA_ENGINE_ENABLE (1L<<26)
+#define BNX2_MISC_ENABLE_STATUS_BITS_UMP_ENABLE (1L<<27)
+
+#define BNX2_MISC_ENABLE_SET_BITS 0x00000810
+#define BNX2_MISC_ENABLE_SET_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_BD_READ_ENABLE (1L<<1)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_DMA_ENABLE (1L<<4)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_PATCHUP_ENABLE (1L<<5)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+#define BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE (1L<<9)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE (1L<<12)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_LOOKUP_ENABLE (1L<<13)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_V2P_ENABLE (1L<<15)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_DMA_ENABLE (1L<<17)
+#define BNX2_MISC_ENABLE_SET_BITS_COMPLETION_ENABLE (1L<<18)
+#define BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE (1L<<19)
+#define BNX2_MISC_ENABLE_SET_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+#define BNX2_MISC_ENABLE_SET_BITS_CONTEXT_ENABLE (1L<<21)
+#define BNX2_MISC_ENABLE_SET_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+#define BNX2_MISC_ENABLE_SET_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+#define BNX2_MISC_ENABLE_SET_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+#define BNX2_MISC_ENABLE_SET_BITS_TIMER_ENABLE (1L<<25)
+#define BNX2_MISC_ENABLE_SET_BITS_DMA_ENGINE_ENABLE (1L<<26)
+#define BNX2_MISC_ENABLE_SET_BITS_UMP_ENABLE (1L<<27)
+
+#define BNX2_MISC_ENABLE_CLR_BITS 0x00000814
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_READ_ENABLE (1L<<1)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE (1L<<4)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_PATCHUP_ENABLE (1L<<5)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+#define BNX2_MISC_ENABLE_CLR_BITS_EMAC_ENABLE (1L<<9)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_MBUF_ENABLE (1L<<12)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_LOOKUP_ENABLE (1L<<13)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_V2P_ENABLE (1L<<15)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE (1L<<17)
+#define BNX2_MISC_ENABLE_CLR_BITS_COMPLETION_ENABLE (1L<<18)
+#define BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE (1L<<19)
+#define BNX2_MISC_ENABLE_CLR_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+#define BNX2_MISC_ENABLE_CLR_BITS_CONTEXT_ENABLE (1L<<21)
+#define BNX2_MISC_ENABLE_CLR_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+#define BNX2_MISC_ENABLE_CLR_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+#define BNX2_MISC_ENABLE_CLR_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+#define BNX2_MISC_ENABLE_CLR_BITS_TIMER_ENABLE (1L<<25)
+#define BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE (1L<<26)
+#define BNX2_MISC_ENABLE_CLR_BITS_UMP_ENABLE (1L<<27)
+
+#define BNX2_MISC_CLOCK_CONTROL_BITS 0x00000818
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ (0L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ (1L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ (2L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ (3L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ (4L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ (5L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ (6L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ (7L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW (0xfL<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE (1L<<6)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT (1L<<7)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC (0x7L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF (0L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PLAY_DEAD (1L<<11)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_PLL_STOP (1L<<17)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_USE_SPD_DET (1L<<19)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20)
+
+#define BNX2_MISC_GPIO 0x0000081c
+#define BNX2_MISC_GPIO_VALUE (0xffL<<0)
+#define BNX2_MISC_GPIO_SET (0xffL<<8)
+#define BNX2_MISC_GPIO_CLR (0xffL<<16)
+#define BNX2_MISC_GPIO_FLOAT (0xffL<<24)
+
+#define BNX2_MISC_GPIO_INT 0x00000820
+#define BNX2_MISC_GPIO_INT_INT_STATE (0xfL<<0)
+#define BNX2_MISC_GPIO_INT_OLD_VALUE (0xfL<<8)
+#define BNX2_MISC_GPIO_INT_OLD_SET (0xfL<<16)
+#define BNX2_MISC_GPIO_INT_OLD_CLR (0xfL<<24)
+
+#define BNX2_MISC_CONFIG_LFSR 0x00000824
+#define BNX2_MISC_CONFIG_LFSR_DIV (0xffffL<<0)
+
+#define BNX2_MISC_LFSR_MASK_BITS 0x00000828
+#define BNX2_MISC_LFSR_MASK_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_BD_READ_ENABLE (1L<<1)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_DMA_ENABLE (1L<<4)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_PATCHUP_ENABLE (1L<<5)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+#define BNX2_MISC_LFSR_MASK_BITS_EMAC_ENABLE (1L<<9)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_MBUF_ENABLE (1L<<12)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_LOOKUP_ENABLE (1L<<13)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_V2P_ENABLE (1L<<15)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_DMA_ENABLE (1L<<17)
+#define BNX2_MISC_LFSR_MASK_BITS_COMPLETION_ENABLE (1L<<18)
+#define BNX2_MISC_LFSR_MASK_BITS_HOST_COALESCE_ENABLE (1L<<19)
+#define BNX2_MISC_LFSR_MASK_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+#define BNX2_MISC_LFSR_MASK_BITS_CONTEXT_ENABLE (1L<<21)
+#define BNX2_MISC_LFSR_MASK_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+#define BNX2_MISC_LFSR_MASK_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+#define BNX2_MISC_LFSR_MASK_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+#define BNX2_MISC_LFSR_MASK_BITS_TIMER_ENABLE (1L<<25)
+#define BNX2_MISC_LFSR_MASK_BITS_DMA_ENGINE_ENABLE (1L<<26)
+#define BNX2_MISC_LFSR_MASK_BITS_UMP_ENABLE (1L<<27)
+
+#define BNX2_MISC_ARB_REQ0 0x0000082c
+#define BNX2_MISC_ARB_REQ1 0x00000830
+#define BNX2_MISC_ARB_REQ2 0x00000834
+#define BNX2_MISC_ARB_REQ3 0x00000838
+#define BNX2_MISC_ARB_REQ4 0x0000083c
+#define BNX2_MISC_ARB_FREE0 0x00000840
+#define BNX2_MISC_ARB_FREE1 0x00000844
+#define BNX2_MISC_ARB_FREE2 0x00000848
+#define BNX2_MISC_ARB_FREE3 0x0000084c
+#define BNX2_MISC_ARB_FREE4 0x00000850
+#define BNX2_MISC_ARB_REQ_STATUS0 0x00000854
+#define BNX2_MISC_ARB_REQ_STATUS1 0x00000858
+#define BNX2_MISC_ARB_REQ_STATUS2 0x0000085c
+#define BNX2_MISC_ARB_REQ_STATUS3 0x00000860
+#define BNX2_MISC_ARB_REQ_STATUS4 0x00000864
+#define BNX2_MISC_ARB_GNT0 0x00000868
+#define BNX2_MISC_ARB_GNT0_0 (0x7L<<0)
+#define BNX2_MISC_ARB_GNT0_1 (0x7L<<4)
+#define BNX2_MISC_ARB_GNT0_2 (0x7L<<8)
+#define BNX2_MISC_ARB_GNT0_3 (0x7L<<12)
+#define BNX2_MISC_ARB_GNT0_4 (0x7L<<16)
+#define BNX2_MISC_ARB_GNT0_5 (0x7L<<20)
+#define BNX2_MISC_ARB_GNT0_6 (0x7L<<24)
+#define BNX2_MISC_ARB_GNT0_7 (0x7L<<28)
+
+#define BNX2_MISC_ARB_GNT1 0x0000086c
+#define BNX2_MISC_ARB_GNT1_8 (0x7L<<0)
+#define BNX2_MISC_ARB_GNT1_9 (0x7L<<4)
+#define BNX2_MISC_ARB_GNT1_10 (0x7L<<8)
+#define BNX2_MISC_ARB_GNT1_11 (0x7L<<12)
+#define BNX2_MISC_ARB_GNT1_12 (0x7L<<16)
+#define BNX2_MISC_ARB_GNT1_13 (0x7L<<20)
+#define BNX2_MISC_ARB_GNT1_14 (0x7L<<24)
+#define BNX2_MISC_ARB_GNT1_15 (0x7L<<28)
+
+#define BNX2_MISC_ARB_GNT2 0x00000870
+#define BNX2_MISC_ARB_GNT2_16 (0x7L<<0)
+#define BNX2_MISC_ARB_GNT2_17 (0x7L<<4)
+#define BNX2_MISC_ARB_GNT2_18 (0x7L<<8)
+#define BNX2_MISC_ARB_GNT2_19 (0x7L<<12)
+#define BNX2_MISC_ARB_GNT2_20 (0x7L<<16)
+#define BNX2_MISC_ARB_GNT2_21 (0x7L<<20)
+#define BNX2_MISC_ARB_GNT2_22 (0x7L<<24)
+#define BNX2_MISC_ARB_GNT2_23 (0x7L<<28)
+
+#define BNX2_MISC_ARB_GNT3 0x00000874
+#define BNX2_MISC_ARB_GNT3_24 (0x7L<<0)
+#define BNX2_MISC_ARB_GNT3_25 (0x7L<<4)
+#define BNX2_MISC_ARB_GNT3_26 (0x7L<<8)
+#define BNX2_MISC_ARB_GNT3_27 (0x7L<<12)
+#define BNX2_MISC_ARB_GNT3_28 (0x7L<<16)
+#define BNX2_MISC_ARB_GNT3_29 (0x7L<<20)
+#define BNX2_MISC_ARB_GNT3_30 (0x7L<<24)
+#define BNX2_MISC_ARB_GNT3_31 (0x7L<<28)
+
+#define BNX2_MISC_PRBS_CONTROL 0x00000878
+#define BNX2_MISC_PRBS_CONTROL_EN (1L<<0)
+#define BNX2_MISC_PRBS_CONTROL_RSTB (1L<<1)
+#define BNX2_MISC_PRBS_CONTROL_INV (1L<<2)
+#define BNX2_MISC_PRBS_CONTROL_ERR_CLR (1L<<3)
+#define BNX2_MISC_PRBS_CONTROL_ORDER (0x3L<<4)
+#define BNX2_MISC_PRBS_CONTROL_ORDER_7TH (0L<<4)
+#define BNX2_MISC_PRBS_CONTROL_ORDER_15TH (1L<<4)
+#define BNX2_MISC_PRBS_CONTROL_ORDER_23RD (2L<<4)
+#define BNX2_MISC_PRBS_CONTROL_ORDER_31ST (3L<<4)
+
+#define BNX2_MISC_PRBS_STATUS 0x0000087c
+#define BNX2_MISC_PRBS_STATUS_LOCK (1L<<0)
+#define BNX2_MISC_PRBS_STATUS_STKY (1L<<1)
+#define BNX2_MISC_PRBS_STATUS_ERRORS (0x3fffL<<2)
+#define BNX2_MISC_PRBS_STATUS_STATE (0xfL<<16)
+
+#define BNX2_MISC_SM_ASF_CONTROL 0x00000880
+#define BNX2_MISC_SM_ASF_CONTROL_ASF_RST (1L<<0)
+#define BNX2_MISC_SM_ASF_CONTROL_TSC_EN (1L<<1)
+#define BNX2_MISC_SM_ASF_CONTROL_WG_TO (1L<<2)
+#define BNX2_MISC_SM_ASF_CONTROL_HB_TO (1L<<3)
+#define BNX2_MISC_SM_ASF_CONTROL_PA_TO (1L<<4)
+#define BNX2_MISC_SM_ASF_CONTROL_PL_TO (1L<<5)
+#define BNX2_MISC_SM_ASF_CONTROL_RT_TO (1L<<6)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_EVENT (1L<<7)
+#define BNX2_MISC_SM_ASF_CONTROL_RES (0xfL<<8)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_EN (1L<<12)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_BB_EN (1L<<13)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_NO_ADDR_FILT (1L<<14)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_AUTOREAD (1L<<15)
+#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR1 (0x3fL<<16)
+#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR2 (0x3fL<<24)
+#define BNX2_MISC_SM_ASF_CONTROL_EN_NIC_SMB_ADDR_0 (1L<<30)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_EARLY_ATTN (1L<<31)
+
+#define BNX2_MISC_SMB_IN 0x00000884
+#define BNX2_MISC_SMB_IN_DAT_IN (0xffL<<0)
+#define BNX2_MISC_SMB_IN_RDY (1L<<8)
+#define BNX2_MISC_SMB_IN_DONE (1L<<9)
+#define BNX2_MISC_SMB_IN_FIRSTBYTE (1L<<10)
+#define BNX2_MISC_SMB_IN_STATUS (0x7L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_OK (0x0L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_PEC (0x1L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_OFLOW (0x2L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_STOP (0x3L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_TIMEOUT (0x4L<<11)
+
+#define BNX2_MISC_SMB_OUT 0x00000888
+#define BNX2_MISC_SMB_OUT_DAT_OUT (0xffL<<0)
+#define BNX2_MISC_SMB_OUT_RDY (1L<<8)
+#define BNX2_MISC_SMB_OUT_START (1L<<9)
+#define BNX2_MISC_SMB_OUT_LAST (1L<<10)
+#define BNX2_MISC_SMB_OUT_ACC_TYPE (1L<<11)
+#define BNX2_MISC_SMB_OUT_ENB_PEC (1L<<12)
+#define BNX2_MISC_SMB_OUT_GET_RX_LEN (1L<<13)
+#define BNX2_MISC_SMB_OUT_SMB_READ_LEN (0x3fL<<14)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS (0xfL<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_OK (0L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_NACK (1L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_NACK (9L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_UFLOW (2L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_STOP (3L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_TIMEOUT (4L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_LOST (5L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_LOST (0xdL<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_BADACK (0x6L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_SLAVEMODE (1L<<24)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_EN (1L<<25)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_IN (1L<<26)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_EN (1L<<27)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_IN (1L<<28)
+
+#define BNX2_MISC_SMB_WATCHDOG 0x0000088c
+#define BNX2_MISC_SMB_WATCHDOG_WATCHDOG (0xffffL<<0)
+
+#define BNX2_MISC_SMB_HEARTBEAT 0x00000890
+#define BNX2_MISC_SMB_HEARTBEAT_HEARTBEAT (0xffffL<<0)
+
+#define BNX2_MISC_SMB_POLL_ASF 0x00000894
+#define BNX2_MISC_SMB_POLL_ASF_POLL_ASF (0xffffL<<0)
+
+#define BNX2_MISC_SMB_POLL_LEGACY 0x00000898
+#define BNX2_MISC_SMB_POLL_LEGACY_POLL_LEGACY (0xffffL<<0)
+
+#define BNX2_MISC_SMB_RETRAN 0x0000089c
+#define BNX2_MISC_SMB_RETRAN_RETRAN (0xffL<<0)
+
+#define BNX2_MISC_SMB_TIMESTAMP 0x000008a0
+#define BNX2_MISC_SMB_TIMESTAMP_TIMESTAMP (0xffffffffL<<0)
+
+#define BNX2_MISC_PERR_ENA0 0x000008a4
+#define BNX2_MISC_PERR_ENA0_COM_MISC_CTXC (1L<<0)
+#define BNX2_MISC_PERR_ENA0_COM_MISC_REGF (1L<<1)
+#define BNX2_MISC_PERR_ENA0_COM_MISC_SCPAD (1L<<2)
+#define BNX2_MISC_PERR_ENA0_CP_MISC_CTXC (1L<<3)
+#define BNX2_MISC_PERR_ENA0_CP_MISC_REGF (1L<<4)
+#define BNX2_MISC_PERR_ENA0_CP_MISC_SCPAD (1L<<5)
+#define BNX2_MISC_PERR_ENA0_CS_MISC_TMEM (1L<<6)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM0 (1L<<7)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM1 (1L<<8)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM2 (1L<<9)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM3 (1L<<10)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM4 (1L<<11)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM5 (1L<<12)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_PGTBL (1L<<13)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR0 (1L<<14)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR1 (1L<<15)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR2 (1L<<16)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR3 (1L<<17)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR4 (1L<<18)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW0 (1L<<19)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW1 (1L<<20)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW2 (1L<<21)
+#define BNX2_MISC_PERR_ENA0_HC_MISC_DMA (1L<<22)
+#define BNX2_MISC_PERR_ENA0_MCP_MISC_REGF (1L<<23)
+#define BNX2_MISC_PERR_ENA0_MCP_MISC_SCPAD (1L<<24)
+#define BNX2_MISC_PERR_ENA0_MQ_MISC_CTX (1L<<25)
+#define BNX2_MISC_PERR_ENA0_RBDC_MISC (1L<<26)
+#define BNX2_MISC_PERR_ENA0_RBUF_MISC_MB (1L<<27)
+#define BNX2_MISC_PERR_ENA0_RBUF_MISC_PTR (1L<<28)
+#define BNX2_MISC_PERR_ENA0_RDE_MISC_RPC (1L<<29)
+#define BNX2_MISC_PERR_ENA0_RDE_MISC_RPM (1L<<30)
+#define BNX2_MISC_PERR_ENA0_RV2P_MISC_CB0REGS (1L<<31)
+
+#define BNX2_MISC_PERR_ENA1 0x000008a8
+#define BNX2_MISC_PERR_ENA1_RV2P_MISC_CB1REGS (1L<<0)
+#define BNX2_MISC_PERR_ENA1_RV2P_MISC_P1IRAM (1L<<1)
+#define BNX2_MISC_PERR_ENA1_RV2P_MISC_P2IRAM (1L<<2)
+#define BNX2_MISC_PERR_ENA1_RXP_MISC_CTXC (1L<<3)
+#define BNX2_MISC_PERR_ENA1_RXP_MISC_REGF (1L<<4)
+#define BNX2_MISC_PERR_ENA1_RXP_MISC_SCPAD (1L<<5)
+#define BNX2_MISC_PERR_ENA1_RXP_MISC_RBUFC (1L<<6)
+#define BNX2_MISC_PERR_ENA1_TBDC_MISC (1L<<7)
+#define BNX2_MISC_PERR_ENA1_TDMA_MISC (1L<<8)
+#define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB0 (1L<<9)
+#define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB1 (1L<<10)
+#define BNX2_MISC_PERR_ENA1_TPAT_MISC_REGF (1L<<11)
+#define BNX2_MISC_PERR_ENA1_TPAT_MISC_SCPAD (1L<<12)
+#define BNX2_MISC_PERR_ENA1_TPBUF_MISC_MB (1L<<13)
+#define BNX2_MISC_PERR_ENA1_TSCH_MISC_LR (1L<<14)
+#define BNX2_MISC_PERR_ENA1_TXP_MISC_CTXC (1L<<15)
+#define BNX2_MISC_PERR_ENA1_TXP_MISC_REGF (1L<<16)
+#define BNX2_MISC_PERR_ENA1_TXP_MISC_SCPAD (1L<<17)
+#define BNX2_MISC_PERR_ENA1_UMP_MISC_FIORX (1L<<18)
+#define BNX2_MISC_PERR_ENA1_UMP_MISC_FIOTX (1L<<19)
+#define BNX2_MISC_PERR_ENA1_UMP_MISC_RX (1L<<20)
+#define BNX2_MISC_PERR_ENA1_UMP_MISC_TX (1L<<21)
+#define BNX2_MISC_PERR_ENA1_RDMAQ_MISC (1L<<22)
+#define BNX2_MISC_PERR_ENA1_CSQ_MISC (1L<<23)
+#define BNX2_MISC_PERR_ENA1_CPQ_MISC (1L<<24)
+#define BNX2_MISC_PERR_ENA1_MCPQ_MISC (1L<<25)
+#define BNX2_MISC_PERR_ENA1_RV2PMQ_MISC (1L<<26)
+#define BNX2_MISC_PERR_ENA1_RV2PPQ_MISC (1L<<27)
+#define BNX2_MISC_PERR_ENA1_RV2PTQ_MISC (1L<<28)
+#define BNX2_MISC_PERR_ENA1_RXPQ_MISC (1L<<29)
+#define BNX2_MISC_PERR_ENA1_RXPCQ_MISC (1L<<30)
+#define BNX2_MISC_PERR_ENA1_RLUPQ_MISC (1L<<31)
+
+#define BNX2_MISC_PERR_ENA2 0x000008ac
+#define BNX2_MISC_PERR_ENA2_COMQ_MISC (1L<<0)
+#define BNX2_MISC_PERR_ENA2_COMXQ_MISC (1L<<1)
+#define BNX2_MISC_PERR_ENA2_COMTQ_MISC (1L<<2)
+#define BNX2_MISC_PERR_ENA2_TSCHQ_MISC (1L<<3)
+#define BNX2_MISC_PERR_ENA2_TBDRQ_MISC (1L<<4)
+#define BNX2_MISC_PERR_ENA2_TXPQ_MISC (1L<<5)
+#define BNX2_MISC_PERR_ENA2_TDMAQ_MISC (1L<<6)
+#define BNX2_MISC_PERR_ENA2_TPATQ_MISC (1L<<7)
+#define BNX2_MISC_PERR_ENA2_TASQ_MISC (1L<<8)
+
+#define BNX2_MISC_DEBUG_VECTOR_SEL 0x000008b0
+#define BNX2_MISC_DEBUG_VECTOR_SEL_0 (0xfffL<<0)
+#define BNX2_MISC_DEBUG_VECTOR_SEL_1 (0xfffL<<12)
+
+#define BNX2_MISC_VREG_CONTROL 0x000008b4
+#define BNX2_MISC_VREG_CONTROL_1_2 (0xfL<<0)
+#define BNX2_MISC_VREG_CONTROL_2_5 (0xfL<<4)
+
+#define BNX2_MISC_FINAL_CLK_CTL_VAL 0x000008b8
+#define BNX2_MISC_FINAL_CLK_CTL_VAL_MISC_FINAL_CLK_CTL_VAL (0x3ffffffL<<6)
+
+#define BNX2_MISC_UNUSED0 0x000008bc
+
+
+/*
+ * nvm_reg definition
+ * offset: 0x6400
+ */
+#define BNX2_NVM_COMMAND 0x00006400
+#define BNX2_NVM_COMMAND_RST (1L<<0)
+#define BNX2_NVM_COMMAND_DONE (1L<<3)
+#define BNX2_NVM_COMMAND_DOIT (1L<<4)
+#define BNX2_NVM_COMMAND_WR (1L<<5)
+#define BNX2_NVM_COMMAND_ERASE (1L<<6)
+#define BNX2_NVM_COMMAND_FIRST (1L<<7)
+#define BNX2_NVM_COMMAND_LAST (1L<<8)
+#define BNX2_NVM_COMMAND_WREN (1L<<16)
+#define BNX2_NVM_COMMAND_WRDI (1L<<17)
+#define BNX2_NVM_COMMAND_EWSR (1L<<18)
+#define BNX2_NVM_COMMAND_WRSR (1L<<19)
+
+#define BNX2_NVM_STATUS 0x00006404
+#define BNX2_NVM_STATUS_PI_FSM_STATE (0xfL<<0)
+#define BNX2_NVM_STATUS_EE_FSM_STATE (0xfL<<4)
+#define BNX2_NVM_STATUS_EQ_FSM_STATE (0xfL<<8)
+
+#define BNX2_NVM_WRITE 0x00006408
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE (0xffffffffL<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_BIT_BANG (0L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EECLK (1L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EEDATA (2L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SCLK (4L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B (8L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO (16L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI (32L<<0)
+
+#define BNX2_NVM_ADDR 0x0000640c
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_BIT_BANG (0L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EECLK (1L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EEDATA (2L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SCLK (4L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B (8L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO (16L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI (32L<<0)
+
+#define BNX2_NVM_READ 0x00006410
+#define BNX2_NVM_READ_NVM_READ_VALUE (0xffffffffL<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_BIT_BANG (0L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_EECLK (1L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_EEDATA (2L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_SCLK (4L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_CS_B (8L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_SO (16L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_SI (32L<<0)
+
+#define BNX2_NVM_CFG1 0x00006414
+#define BNX2_NVM_CFG1_FLASH_MODE (1L<<0)
+#define BNX2_NVM_CFG1_BUFFER_MODE (1L<<1)
+#define BNX2_NVM_CFG1_PASS_MODE (1L<<2)
+#define BNX2_NVM_CFG1_BITBANG_MODE (1L<<3)
+#define BNX2_NVM_CFG1_STATUS_BIT (0x7L<<4)
+#define BNX2_NVM_CFG1_STATUS_BIT_FLASH_RDY (0L<<4)
+#define BNX2_NVM_CFG1_STATUS_BIT_BUFFER_RDY (7L<<4)
+#define BNX2_NVM_CFG1_SPI_CLK_DIV (0xfL<<7)
+#define BNX2_NVM_CFG1_SEE_CLK_DIV (0x7ffL<<11)
+#define BNX2_NVM_CFG1_PROTECT_MODE (1L<<24)
+#define BNX2_NVM_CFG1_FLASH_SIZE (1L<<25)
+#define BNX2_NVM_CFG1_COMPAT_BYPASSS (1L<<31)
+
+#define BNX2_NVM_CFG2 0x00006418
+#define BNX2_NVM_CFG2_ERASE_CMD (0xffL<<0)
+#define BNX2_NVM_CFG2_DUMMY (0xffL<<8)
+#define BNX2_NVM_CFG2_STATUS_CMD (0xffL<<16)
+
+#define BNX2_NVM_CFG3 0x0000641c
+#define BNX2_NVM_CFG3_BUFFER_RD_CMD (0xffL<<0)
+#define BNX2_NVM_CFG3_WRITE_CMD (0xffL<<8)
+#define BNX2_NVM_CFG3_BUFFER_WRITE_CMD (0xffL<<16)
+#define BNX2_NVM_CFG3_READ_CMD (0xffL<<24)
+
+#define BNX2_NVM_SW_ARB 0x00006420
+#define BNX2_NVM_SW_ARB_ARB_REQ_SET0 (1L<<0)
+#define BNX2_NVM_SW_ARB_ARB_REQ_SET1 (1L<<1)
+#define BNX2_NVM_SW_ARB_ARB_REQ_SET2 (1L<<2)
+#define BNX2_NVM_SW_ARB_ARB_REQ_SET3 (1L<<3)
+#define BNX2_NVM_SW_ARB_ARB_REQ_CLR0 (1L<<4)
+#define BNX2_NVM_SW_ARB_ARB_REQ_CLR1 (1L<<5)
+#define BNX2_NVM_SW_ARB_ARB_REQ_CLR2 (1L<<6)
+#define BNX2_NVM_SW_ARB_ARB_REQ_CLR3 (1L<<7)
+#define BNX2_NVM_SW_ARB_ARB_ARB0 (1L<<8)
+#define BNX2_NVM_SW_ARB_ARB_ARB1 (1L<<9)
+#define BNX2_NVM_SW_ARB_ARB_ARB2 (1L<<10)
+#define BNX2_NVM_SW_ARB_ARB_ARB3 (1L<<11)
+#define BNX2_NVM_SW_ARB_REQ0 (1L<<12)
+#define BNX2_NVM_SW_ARB_REQ1 (1L<<13)
+#define BNX2_NVM_SW_ARB_REQ2 (1L<<14)
+#define BNX2_NVM_SW_ARB_REQ3 (1L<<15)
+
+#define BNX2_NVM_ACCESS_ENABLE 0x00006424
+#define BNX2_NVM_ACCESS_ENABLE_EN (1L<<0)
+#define BNX2_NVM_ACCESS_ENABLE_WR_EN (1L<<1)
+
+#define BNX2_NVM_WRITE1 0x00006428
+#define BNX2_NVM_WRITE1_WREN_CMD (0xffL<<0)
+#define BNX2_NVM_WRITE1_WRDI_CMD (0xffL<<8)
+#define BNX2_NVM_WRITE1_SR_DATA (0xffL<<16)
+
+
+
+/*
+ * dma_reg definition
+ * offset: 0xc00
+ */
+#define BNX2_DMA_COMMAND 0x00000c00
+#define BNX2_DMA_COMMAND_ENABLE (1L<<0)
+
+#define BNX2_DMA_STATUS 0x00000c04
+#define BNX2_DMA_STATUS_PAR_ERROR_STATE (1L<<0)
+#define BNX2_DMA_STATUS_READ_TRANSFERS_STAT (1L<<16)
+#define BNX2_DMA_STATUS_READ_DELAY_PCI_CLKS_STAT (1L<<17)
+#define BNX2_DMA_STATUS_BIG_READ_TRANSFERS_STAT (1L<<18)
+#define BNX2_DMA_STATUS_BIG_READ_DELAY_PCI_CLKS_STAT (1L<<19)
+#define BNX2_DMA_STATUS_BIG_READ_RETRY_AFTER_DATA_STAT (1L<<20)
+#define BNX2_DMA_STATUS_WRITE_TRANSFERS_STAT (1L<<21)
+#define BNX2_DMA_STATUS_WRITE_DELAY_PCI_CLKS_STAT (1L<<22)
+#define BNX2_DMA_STATUS_BIG_WRITE_TRANSFERS_STAT (1L<<23)
+#define BNX2_DMA_STATUS_BIG_WRITE_DELAY_PCI_CLKS_STAT (1L<<24)
+#define BNX2_DMA_STATUS_BIG_WRITE_RETRY_AFTER_DATA_STAT (1L<<25)
+
+#define BNX2_DMA_CONFIG 0x00000c08
+#define BNX2_DMA_CONFIG_DATA_BYTE_SWAP (1L<<0)
+#define BNX2_DMA_CONFIG_DATA_WORD_SWAP (1L<<1)
+#define BNX2_DMA_CONFIG_CNTL_BYTE_SWAP (1L<<4)
+#define BNX2_DMA_CONFIG_CNTL_WORD_SWAP (1L<<5)
+#define BNX2_DMA_CONFIG_ONE_DMA (1L<<6)
+#define BNX2_DMA_CONFIG_CNTL_TWO_DMA (1L<<7)
+#define BNX2_DMA_CONFIG_CNTL_FPGA_MODE (1L<<8)
+#define BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA (1L<<10)
+#define BNX2_DMA_CONFIG_CNTL_PCI_COMP_DLY (1L<<11)
+#define BNX2_DMA_CONFIG_NO_RCHANS_IN_USE (0xfL<<12)
+#define BNX2_DMA_CONFIG_NO_WCHANS_IN_USE (0xfL<<16)
+#define BNX2_DMA_CONFIG_PCI_CLK_CMP_BITS (0x7L<<20)
+#define BNX2_DMA_CONFIG_PCI_FAST_CLK_CMP (1L<<23)
+#define BNX2_DMA_CONFIG_BIG_SIZE (0xfL<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_NONE (0x0L<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_64 (0x1L<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_128 (0x2L<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_256 (0x4L<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_512 (0x8L<<24)
+
+#define BNX2_DMA_BLACKOUT 0x00000c0c
+#define BNX2_DMA_BLACKOUT_RD_RETRY_BLACKOUT (0xffL<<0)
+#define BNX2_DMA_BLACKOUT_2ND_RD_RETRY_BLACKOUT (0xffL<<8)
+#define BNX2_DMA_BLACKOUT_WR_RETRY_BLACKOUT (0xffL<<16)
+
+#define BNX2_DMA_RCHAN_STAT 0x00000c30
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_0 (0x7L<<0)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_0 (1L<<3)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_1 (0x7L<<4)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_1 (1L<<7)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_2 (0x7L<<8)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_2 (1L<<11)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_3 (0x7L<<12)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_3 (1L<<15)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_4 (0x7L<<16)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_4 (1L<<19)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_5 (0x7L<<20)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_5 (1L<<23)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_6 (0x7L<<24)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_6 (1L<<27)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_7 (0x7L<<28)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_7 (1L<<31)
+
+#define BNX2_DMA_WCHAN_STAT 0x00000c34
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_0 (0x7L<<0)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_0 (1L<<3)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_1 (0x7L<<4)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_1 (1L<<7)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_2 (0x7L<<8)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_2 (1L<<11)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_3 (0x7L<<12)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_3 (1L<<15)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_4 (0x7L<<16)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_4 (1L<<19)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_5 (0x7L<<20)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_5 (1L<<23)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_6 (0x7L<<24)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_6 (1L<<27)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_7 (0x7L<<28)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_7 (1L<<31)
+
+#define BNX2_DMA_RCHAN_ASSIGNMENT 0x00000c38
+#define BNX2_DMA_RCHAN_ASSIGNMENT_0 (0xfL<<0)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_1 (0xfL<<4)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_2 (0xfL<<8)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_3 (0xfL<<12)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_4 (0xfL<<16)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_5 (0xfL<<20)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_6 (0xfL<<24)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_7 (0xfL<<28)
+
+#define BNX2_DMA_WCHAN_ASSIGNMENT 0x00000c3c
+#define BNX2_DMA_WCHAN_ASSIGNMENT_0 (0xfL<<0)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_1 (0xfL<<4)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_2 (0xfL<<8)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_3 (0xfL<<12)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_4 (0xfL<<16)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_5 (0xfL<<20)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_6 (0xfL<<24)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_7 (0xfL<<28)
+
+#define BNX2_DMA_RCHAN_STAT_00 0x00000c40
+#define BNX2_DMA_RCHAN_STAT_00_RCHAN_STA_HOST_ADDR_LOW (0xffffffffL<<0)
+
+#define BNX2_DMA_RCHAN_STAT_01 0x00000c44
+#define BNX2_DMA_RCHAN_STAT_01_RCHAN_STA_HOST_ADDR_HIGH (0xffffffffL<<0)
+
+#define BNX2_DMA_RCHAN_STAT_02 0x00000c48
+#define BNX2_DMA_RCHAN_STAT_02_LENGTH (0xffffL<<0)
+#define BNX2_DMA_RCHAN_STAT_02_WORD_SWAP (1L<<16)
+#define BNX2_DMA_RCHAN_STAT_02_BYTE_SWAP (1L<<17)
+#define BNX2_DMA_RCHAN_STAT_02_PRIORITY_LVL (1L<<18)
+
+#define BNX2_DMA_RCHAN_STAT_10 0x00000c4c
+#define BNX2_DMA_RCHAN_STAT_11 0x00000c50
+#define BNX2_DMA_RCHAN_STAT_12 0x00000c54
+#define BNX2_DMA_RCHAN_STAT_20 0x00000c58
+#define BNX2_DMA_RCHAN_STAT_21 0x00000c5c
+#define BNX2_DMA_RCHAN_STAT_22 0x00000c60
+#define BNX2_DMA_RCHAN_STAT_30 0x00000c64
+#define BNX2_DMA_RCHAN_STAT_31 0x00000c68
+#define BNX2_DMA_RCHAN_STAT_32 0x00000c6c
+#define BNX2_DMA_RCHAN_STAT_40 0x00000c70
+#define BNX2_DMA_RCHAN_STAT_41 0x00000c74
+#define BNX2_DMA_RCHAN_STAT_42 0x00000c78
+#define BNX2_DMA_RCHAN_STAT_50 0x00000c7c
+#define BNX2_DMA_RCHAN_STAT_51 0x00000c80
+#define BNX2_DMA_RCHAN_STAT_52 0x00000c84
+#define BNX2_DMA_RCHAN_STAT_60 0x00000c88
+#define BNX2_DMA_RCHAN_STAT_61 0x00000c8c
+#define BNX2_DMA_RCHAN_STAT_62 0x00000c90
+#define BNX2_DMA_RCHAN_STAT_70 0x00000c94
+#define BNX2_DMA_RCHAN_STAT_71 0x00000c98
+#define BNX2_DMA_RCHAN_STAT_72 0x00000c9c
+#define BNX2_DMA_WCHAN_STAT_00 0x00000ca0
+#define BNX2_DMA_WCHAN_STAT_00_WCHAN_STA_HOST_ADDR_LOW (0xffffffffL<<0)
+
+#define BNX2_DMA_WCHAN_STAT_01 0x00000ca4
+#define BNX2_DMA_WCHAN_STAT_01_WCHAN_STA_HOST_ADDR_HIGH (0xffffffffL<<0)
+
+#define BNX2_DMA_WCHAN_STAT_02 0x00000ca8
+#define BNX2_DMA_WCHAN_STAT_02_LENGTH (0xffffL<<0)
+#define BNX2_DMA_WCHAN_STAT_02_WORD_SWAP (1L<<16)
+#define BNX2_DMA_WCHAN_STAT_02_BYTE_SWAP (1L<<17)
+#define BNX2_DMA_WCHAN_STAT_02_PRIORITY_LVL (1L<<18)
+
+#define BNX2_DMA_WCHAN_STAT_10 0x00000cac
+#define BNX2_DMA_WCHAN_STAT_11 0x00000cb0
+#define BNX2_DMA_WCHAN_STAT_12 0x00000cb4
+#define BNX2_DMA_WCHAN_STAT_20 0x00000cb8
+#define BNX2_DMA_WCHAN_STAT_21 0x00000cbc
+#define BNX2_DMA_WCHAN_STAT_22 0x00000cc0
+#define BNX2_DMA_WCHAN_STAT_30 0x00000cc4
+#define BNX2_DMA_WCHAN_STAT_31 0x00000cc8
+#define BNX2_DMA_WCHAN_STAT_32 0x00000ccc
+#define BNX2_DMA_WCHAN_STAT_40 0x00000cd0
+#define BNX2_DMA_WCHAN_STAT_41 0x00000cd4
+#define BNX2_DMA_WCHAN_STAT_42 0x00000cd8
+#define BNX2_DMA_WCHAN_STAT_50 0x00000cdc
+#define BNX2_DMA_WCHAN_STAT_51 0x00000ce0
+#define BNX2_DMA_WCHAN_STAT_52 0x00000ce4
+#define BNX2_DMA_WCHAN_STAT_60 0x00000ce8
+#define BNX2_DMA_WCHAN_STAT_61 0x00000cec
+#define BNX2_DMA_WCHAN_STAT_62 0x00000cf0
+#define BNX2_DMA_WCHAN_STAT_70 0x00000cf4
+#define BNX2_DMA_WCHAN_STAT_71 0x00000cf8
+#define BNX2_DMA_WCHAN_STAT_72 0x00000cfc
+#define BNX2_DMA_ARB_STAT_00 0x00000d00
+#define BNX2_DMA_ARB_STAT_00_MASTER (0xffffL<<0)
+#define BNX2_DMA_ARB_STAT_00_MASTER_ENC (0xffL<<16)
+#define BNX2_DMA_ARB_STAT_00_CUR_BINMSTR (0xffL<<24)
+
+#define BNX2_DMA_ARB_STAT_01 0x00000d04
+#define BNX2_DMA_ARB_STAT_01_LPR_RPTR (0xfL<<0)
+#define BNX2_DMA_ARB_STAT_01_LPR_WPTR (0xfL<<4)
+#define BNX2_DMA_ARB_STAT_01_LPB_RPTR (0xfL<<8)
+#define BNX2_DMA_ARB_STAT_01_LPB_WPTR (0xfL<<12)
+#define BNX2_DMA_ARB_STAT_01_HPR_RPTR (0xfL<<16)
+#define BNX2_DMA_ARB_STAT_01_HPR_WPTR (0xfL<<20)
+#define BNX2_DMA_ARB_STAT_01_HPB_RPTR (0xfL<<24)
+#define BNX2_DMA_ARB_STAT_01_HPB_WPTR (0xfL<<28)
+
+#define BNX2_DMA_FUSE_CTRL0_CMD 0x00000f00
+#define BNX2_DMA_FUSE_CTRL0_CMD_PWRUP_DONE (1L<<0)
+#define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT_DONE (1L<<1)
+#define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT (1L<<2)
+#define BNX2_DMA_FUSE_CTRL0_CMD_LOAD (1L<<3)
+#define BNX2_DMA_FUSE_CTRL0_CMD_SEL (0xfL<<8)
+
+#define BNX2_DMA_FUSE_CTRL0_DATA 0x00000f04
+#define BNX2_DMA_FUSE_CTRL1_CMD 0x00000f08
+#define BNX2_DMA_FUSE_CTRL1_CMD_PWRUP_DONE (1L<<0)
+#define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT_DONE (1L<<1)
+#define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT (1L<<2)
+#define BNX2_DMA_FUSE_CTRL1_CMD_LOAD (1L<<3)
+#define BNX2_DMA_FUSE_CTRL1_CMD_SEL (0xfL<<8)
+
+#define BNX2_DMA_FUSE_CTRL1_DATA 0x00000f0c
+#define BNX2_DMA_FUSE_CTRL2_CMD 0x00000f10
+#define BNX2_DMA_FUSE_CTRL2_CMD_PWRUP_DONE (1L<<0)
+#define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT_DONE (1L<<1)
+#define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT (1L<<2)
+#define BNX2_DMA_FUSE_CTRL2_CMD_LOAD (1L<<3)
+#define BNX2_DMA_FUSE_CTRL2_CMD_SEL (0xfL<<8)
+
+#define BNX2_DMA_FUSE_CTRL2_DATA 0x00000f14
+
+
+/*
+ * context_reg definition
+ * offset: 0x1000
+ */
+#define BNX2_CTX_COMMAND 0x00001000
+#define BNX2_CTX_COMMAND_ENABLED (1L<<0)
+
+#define BNX2_CTX_STATUS 0x00001004
+#define BNX2_CTX_STATUS_LOCK_WAIT (1L<<0)
+#define BNX2_CTX_STATUS_READ_STAT (1L<<16)
+#define BNX2_CTX_STATUS_WRITE_STAT (1L<<17)
+#define BNX2_CTX_STATUS_ACC_STALL_STAT (1L<<18)
+#define BNX2_CTX_STATUS_LOCK_STALL_STAT (1L<<19)
+
+#define BNX2_CTX_VIRT_ADDR 0x00001008
+#define BNX2_CTX_VIRT_ADDR_VIRT_ADDR (0x7fffL<<6)
+
+#define BNX2_CTX_PAGE_TBL 0x0000100c
+#define BNX2_CTX_PAGE_TBL_PAGE_TBL (0x3fffL<<6)
+
+#define BNX2_CTX_DATA_ADR 0x00001010
+#define BNX2_CTX_DATA_ADR_DATA_ADR (0x7ffffL<<2)
+
+#define BNX2_CTX_DATA 0x00001014
+#define BNX2_CTX_LOCK 0x00001018
+#define BNX2_CTX_LOCK_TYPE (0x7L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_VOID (0x0L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_COMPLETE (0x7L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_PROTOCOL (0x1L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TX (0x2L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TIMER (0x4L<<0)
+#define BNX2_CTX_LOCK_CID_VALUE (0x3fffL<<7)
+#define BNX2_CTX_LOCK_GRANTED (1L<<26)
+#define BNX2_CTX_LOCK_MODE (0x7L<<27)
+#define BNX2_CTX_LOCK_MODE_UNLOCK (0x0L<<27)
+#define BNX2_CTX_LOCK_MODE_IMMEDIATE (0x1L<<27)
+#define BNX2_CTX_LOCK_MODE_SURE (0x2L<<27)
+#define BNX2_CTX_LOCK_STATUS (1L<<30)
+#define BNX2_CTX_LOCK_REQ (1L<<31)
+
+#define BNX2_CTX_ACCESS_STATUS 0x00001040
+#define BNX2_CTX_ACCESS_STATUS_MASTERENCODED (0xfL<<0)
+#define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYSM (0x3L<<10)
+#define BNX2_CTX_ACCESS_STATUS_PAGETABLEINITSM (0x3L<<12)
+#define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYINITSM (0x3L<<14)
+#define BNX2_CTX_ACCESS_STATUS_QUALIFIED_REQUEST (0x7ffL<<17)
+
+#define BNX2_CTX_DBG_LOCK_STATUS 0x00001044
+#define BNX2_CTX_DBG_LOCK_STATUS_SM (0x3ffL<<0)
+#define BNX2_CTX_DBG_LOCK_STATUS_MATCH (0x3ffL<<22)
+
+#define BNX2_CTX_CHNL_LOCK_STATUS_0 0x00001080
+#define BNX2_CTX_CHNL_LOCK_STATUS_0_CID (0x3fffL<<0)
+#define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE (0x3L<<14)
+#define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE (1L<<16)
+
+#define BNX2_CTX_CHNL_LOCK_STATUS_1 0x00001084
+#define BNX2_CTX_CHNL_LOCK_STATUS_2 0x00001088
+#define BNX2_CTX_CHNL_LOCK_STATUS_3 0x0000108c
+#define BNX2_CTX_CHNL_LOCK_STATUS_4 0x00001090
+#define BNX2_CTX_CHNL_LOCK_STATUS_5 0x00001094
+#define BNX2_CTX_CHNL_LOCK_STATUS_6 0x00001098
+#define BNX2_CTX_CHNL_LOCK_STATUS_7 0x0000109c
+#define BNX2_CTX_CHNL_LOCK_STATUS_8 0x000010a0
+
+
+/*
+ * emac_reg definition
+ * offset: 0x1400
+ */
+#define BNX2_EMAC_MODE 0x00001400
+#define BNX2_EMAC_MODE_RESET (1L<<0)
+#define BNX2_EMAC_MODE_HALF_DUPLEX (1L<<1)
+#define BNX2_EMAC_MODE_PORT (0x3L<<2)
+#define BNX2_EMAC_MODE_PORT_NONE (0L<<2)
+#define BNX2_EMAC_MODE_PORT_MII (1L<<2)
+#define BNX2_EMAC_MODE_PORT_GMII (2L<<2)
+#define BNX2_EMAC_MODE_PORT_MII_10 (3L<<2)
+#define BNX2_EMAC_MODE_MAC_LOOP (1L<<4)
+#define BNX2_EMAC_MODE_25G (1L<<5)
+#define BNX2_EMAC_MODE_TAGGED_MAC_CTL (1L<<7)
+#define BNX2_EMAC_MODE_TX_BURST (1L<<8)
+#define BNX2_EMAC_MODE_MAX_DEFER_DROP_ENA (1L<<9)
+#define BNX2_EMAC_MODE_EXT_LINK_POL (1L<<10)
+#define BNX2_EMAC_MODE_FORCE_LINK (1L<<11)
+#define BNX2_EMAC_MODE_MPKT (1L<<18)
+#define BNX2_EMAC_MODE_MPKT_RCVD (1L<<19)
+#define BNX2_EMAC_MODE_ACPI_RCVD (1L<<20)
+
+#define BNX2_EMAC_STATUS 0x00001404
+#define BNX2_EMAC_STATUS_LINK (1L<<11)
+#define BNX2_EMAC_STATUS_LINK_CHANGE (1L<<12)
+#define BNX2_EMAC_STATUS_MI_COMPLETE (1L<<22)
+#define BNX2_EMAC_STATUS_MI_INT (1L<<23)
+#define BNX2_EMAC_STATUS_AP_ERROR (1L<<24)
+#define BNX2_EMAC_STATUS_PARITY_ERROR_STATE (1L<<31)
+
+#define BNX2_EMAC_ATTENTION_ENA 0x00001408
+#define BNX2_EMAC_ATTENTION_ENA_LINK (1L<<11)
+#define BNX2_EMAC_ATTENTION_ENA_MI_COMPLETE (1L<<22)
+#define BNX2_EMAC_ATTENTION_ENA_MI_INT (1L<<23)
+#define BNX2_EMAC_ATTENTION_ENA_AP_ERROR (1L<<24)
+
+#define BNX2_EMAC_LED 0x0000140c
+#define BNX2_EMAC_LED_OVERRIDE (1L<<0)
+#define BNX2_EMAC_LED_1000MB_OVERRIDE (1L<<1)
+#define BNX2_EMAC_LED_100MB_OVERRIDE (1L<<2)
+#define BNX2_EMAC_LED_10MB_OVERRIDE (1L<<3)
+#define BNX2_EMAC_LED_TRAFFIC_OVERRIDE (1L<<4)
+#define BNX2_EMAC_LED_BLNK_TRAFFIC (1L<<5)
+#define BNX2_EMAC_LED_TRAFFIC (1L<<6)
+#define BNX2_EMAC_LED_1000MB (1L<<7)
+#define BNX2_EMAC_LED_100MB (1L<<8)
+#define BNX2_EMAC_LED_10MB (1L<<9)
+#define BNX2_EMAC_LED_TRAFFIC_STAT (1L<<10)
+#define BNX2_EMAC_LED_BLNK_RATE (0xfffL<<19)
+#define BNX2_EMAC_LED_BLNK_RATE_ENA (1L<<31)
+
+#define BNX2_EMAC_MAC_MATCH0 0x00001410
+#define BNX2_EMAC_MAC_MATCH1 0x00001414
+#define BNX2_EMAC_MAC_MATCH2 0x00001418
+#define BNX2_EMAC_MAC_MATCH3 0x0000141c
+#define BNX2_EMAC_MAC_MATCH4 0x00001420
+#define BNX2_EMAC_MAC_MATCH5 0x00001424
+#define BNX2_EMAC_MAC_MATCH6 0x00001428
+#define BNX2_EMAC_MAC_MATCH7 0x0000142c
+#define BNX2_EMAC_MAC_MATCH8 0x00001430
+#define BNX2_EMAC_MAC_MATCH9 0x00001434
+#define BNX2_EMAC_MAC_MATCH10 0x00001438
+#define BNX2_EMAC_MAC_MATCH11 0x0000143c
+#define BNX2_EMAC_MAC_MATCH12 0x00001440
+#define BNX2_EMAC_MAC_MATCH13 0x00001444
+#define BNX2_EMAC_MAC_MATCH14 0x00001448
+#define BNX2_EMAC_MAC_MATCH15 0x0000144c
+#define BNX2_EMAC_MAC_MATCH16 0x00001450
+#define BNX2_EMAC_MAC_MATCH17 0x00001454
+#define BNX2_EMAC_MAC_MATCH18 0x00001458
+#define BNX2_EMAC_MAC_MATCH19 0x0000145c
+#define BNX2_EMAC_MAC_MATCH20 0x00001460
+#define BNX2_EMAC_MAC_MATCH21 0x00001464
+#define BNX2_EMAC_MAC_MATCH22 0x00001468
+#define BNX2_EMAC_MAC_MATCH23 0x0000146c
+#define BNX2_EMAC_MAC_MATCH24 0x00001470
+#define BNX2_EMAC_MAC_MATCH25 0x00001474
+#define BNX2_EMAC_MAC_MATCH26 0x00001478
+#define BNX2_EMAC_MAC_MATCH27 0x0000147c
+#define BNX2_EMAC_MAC_MATCH28 0x00001480
+#define BNX2_EMAC_MAC_MATCH29 0x00001484
+#define BNX2_EMAC_MAC_MATCH30 0x00001488
+#define BNX2_EMAC_MAC_MATCH31 0x0000148c
+#define BNX2_EMAC_BACKOFF_SEED 0x00001498
+#define BNX2_EMAC_BACKOFF_SEED_EMAC_BACKOFF_SEED (0x3ffL<<0)
+
+#define BNX2_EMAC_RX_MTU_SIZE 0x0000149c
+#define BNX2_EMAC_RX_MTU_SIZE_MTU_SIZE (0xffffL<<0)
+#define BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA (1L<<31)
+
+#define BNX2_EMAC_SERDES_CNTL 0x000014a4
+#define BNX2_EMAC_SERDES_CNTL_RXR (0x7L<<0)
+#define BNX2_EMAC_SERDES_CNTL_RXG (0x3L<<3)
+#define BNX2_EMAC_SERDES_CNTL_RXCKSEL (1L<<6)
+#define BNX2_EMAC_SERDES_CNTL_TXBIAS (0x7L<<7)
+#define BNX2_EMAC_SERDES_CNTL_BGMAX (1L<<10)
+#define BNX2_EMAC_SERDES_CNTL_BGMIN (1L<<11)
+#define BNX2_EMAC_SERDES_CNTL_TXMODE (1L<<12)
+#define BNX2_EMAC_SERDES_CNTL_TXEDGE (1L<<13)
+#define BNX2_EMAC_SERDES_CNTL_SERDES_MODE (1L<<14)
+#define BNX2_EMAC_SERDES_CNTL_PLLTEST (1L<<15)
+#define BNX2_EMAC_SERDES_CNTL_CDET_EN (1L<<16)
+#define BNX2_EMAC_SERDES_CNTL_TBI_LBK (1L<<17)
+#define BNX2_EMAC_SERDES_CNTL_REMOTE_LBK (1L<<18)
+#define BNX2_EMAC_SERDES_CNTL_REV_PHASE (1L<<19)
+#define BNX2_EMAC_SERDES_CNTL_REGCTL12 (0x3L<<20)
+#define BNX2_EMAC_SERDES_CNTL_REGCTL25 (0x3L<<22)
+
+#define BNX2_EMAC_SERDES_STATUS 0x000014a8
+#define BNX2_EMAC_SERDES_STATUS_RX_STAT (0xffL<<0)
+#define BNX2_EMAC_SERDES_STATUS_COMMA_DET (1L<<8)
+
+#define BNX2_EMAC_MDIO_COMM 0x000014ac
+#define BNX2_EMAC_MDIO_COMM_DATA (0xffffL<<0)
+#define BNX2_EMAC_MDIO_COMM_REG_ADDR (0x1fL<<16)
+#define BNX2_EMAC_MDIO_COMM_PHY_ADDR (0x1fL<<21)
+#define BNX2_EMAC_MDIO_COMM_COMMAND (0x3L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_0 (0L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE (1L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_READ (2L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_3 (3L<<26)
+#define BNX2_EMAC_MDIO_COMM_FAIL (1L<<28)
+#define BNX2_EMAC_MDIO_COMM_START_BUSY (1L<<29)
+#define BNX2_EMAC_MDIO_COMM_DISEXT (1L<<30)
+
+#define BNX2_EMAC_MDIO_STATUS 0x000014b0
+#define BNX2_EMAC_MDIO_STATUS_LINK (1L<<0)
+#define BNX2_EMAC_MDIO_STATUS_10MB (1L<<1)
+
+#define BNX2_EMAC_MDIO_MODE 0x000014b4
+#define BNX2_EMAC_MDIO_MODE_SHORT_PREAMBLE (1L<<1)
+#define BNX2_EMAC_MDIO_MODE_AUTO_POLL (1L<<4)
+#define BNX2_EMAC_MDIO_MODE_BIT_BANG (1L<<8)
+#define BNX2_EMAC_MDIO_MODE_MDIO (1L<<9)
+#define BNX2_EMAC_MDIO_MODE_MDIO_OE (1L<<10)
+#define BNX2_EMAC_MDIO_MODE_MDC (1L<<11)
+#define BNX2_EMAC_MDIO_MODE_MDINT (1L<<12)
+#define BNX2_EMAC_MDIO_MODE_CLOCK_CNT (0x1fL<<16)
+
+#define BNX2_EMAC_MDIO_AUTO_STATUS 0x000014b8
+#define BNX2_EMAC_MDIO_AUTO_STATUS_AUTO_ERR (1L<<0)
+
+#define BNX2_EMAC_TX_MODE 0x000014bc
+#define BNX2_EMAC_TX_MODE_RESET (1L<<0)
+#define BNX2_EMAC_TX_MODE_EXT_PAUSE_EN (1L<<3)
+#define BNX2_EMAC_TX_MODE_FLOW_EN (1L<<4)
+#define BNX2_EMAC_TX_MODE_BIG_BACKOFF (1L<<5)
+#define BNX2_EMAC_TX_MODE_LONG_PAUSE (1L<<6)
+#define BNX2_EMAC_TX_MODE_LINK_AWARE (1L<<7)
+
+#define BNX2_EMAC_TX_STATUS 0x000014c0
+#define BNX2_EMAC_TX_STATUS_XOFFED (1L<<0)
+#define BNX2_EMAC_TX_STATUS_XOFF_SENT (1L<<1)
+#define BNX2_EMAC_TX_STATUS_XON_SENT (1L<<2)
+#define BNX2_EMAC_TX_STATUS_LINK_UP (1L<<3)
+#define BNX2_EMAC_TX_STATUS_UNDERRUN (1L<<4)
+
+#define BNX2_EMAC_TX_LENGTHS 0x000014c4
+#define BNX2_EMAC_TX_LENGTHS_SLOT (0xffL<<0)
+#define BNX2_EMAC_TX_LENGTHS_IPG (0xfL<<8)
+#define BNX2_EMAC_TX_LENGTHS_IPG_CRS (0x3L<<12)
+
+#define BNX2_EMAC_RX_MODE 0x000014c8
+#define BNX2_EMAC_RX_MODE_RESET (1L<<0)
+#define BNX2_EMAC_RX_MODE_FLOW_EN (1L<<2)
+#define BNX2_EMAC_RX_MODE_KEEP_MAC_CONTROL (1L<<3)
+#define BNX2_EMAC_RX_MODE_KEEP_PAUSE (1L<<4)
+#define BNX2_EMAC_RX_MODE_ACCEPT_OVERSIZE (1L<<5)
+#define BNX2_EMAC_RX_MODE_ACCEPT_RUNTS (1L<<6)
+#define BNX2_EMAC_RX_MODE_LLC_CHK (1L<<7)
+#define BNX2_EMAC_RX_MODE_PROMISCUOUS (1L<<8)
+#define BNX2_EMAC_RX_MODE_NO_CRC_CHK (1L<<9)
+#define BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG (1L<<10)
+#define BNX2_EMAC_RX_MODE_FILT_BROADCAST (1L<<11)
+#define BNX2_EMAC_RX_MODE_SORT_MODE (1L<<12)
+
+#define BNX2_EMAC_RX_STATUS 0x000014cc
+#define BNX2_EMAC_RX_STATUS_FFED (1L<<0)
+#define BNX2_EMAC_RX_STATUS_FF_RECEIVED (1L<<1)
+#define BNX2_EMAC_RX_STATUS_N_RECEIVED (1L<<2)
+
+#define BNX2_EMAC_MULTICAST_HASH0 0x000014d0
+#define BNX2_EMAC_MULTICAST_HASH1 0x000014d4
+#define BNX2_EMAC_MULTICAST_HASH2 0x000014d8
+#define BNX2_EMAC_MULTICAST_HASH3 0x000014dc
+#define BNX2_EMAC_MULTICAST_HASH4 0x000014e0
+#define BNX2_EMAC_MULTICAST_HASH5 0x000014e4
+#define BNX2_EMAC_MULTICAST_HASH6 0x000014e8
+#define BNX2_EMAC_MULTICAST_HASH7 0x000014ec
+#define BNX2_EMAC_RX_STAT_IFHCINOCTETS 0x00001500
+#define BNX2_EMAC_RX_STAT_IFHCINBADOCTETS 0x00001504
+#define BNX2_EMAC_RX_STAT_ETHERSTATSFRAGMENTS 0x00001508
+#define BNX2_EMAC_RX_STAT_IFHCINUCASTPKTS 0x0000150c
+#define BNX2_EMAC_RX_STAT_IFHCINMULTICASTPKTS 0x00001510
+#define BNX2_EMAC_RX_STAT_IFHCINBROADCASTPKTS 0x00001514
+#define BNX2_EMAC_RX_STAT_DOT3STATSFCSERRORS 0x00001518
+#define BNX2_EMAC_RX_STAT_DOT3STATSALIGNMENTERRORS 0x0000151c
+#define BNX2_EMAC_RX_STAT_DOT3STATSCARRIERSENSEERRORS 0x00001520
+#define BNX2_EMAC_RX_STAT_XONPAUSEFRAMESRECEIVED 0x00001524
+#define BNX2_EMAC_RX_STAT_XOFFPAUSEFRAMESRECEIVED 0x00001528
+#define BNX2_EMAC_RX_STAT_MACCONTROLFRAMESRECEIVED 0x0000152c
+#define BNX2_EMAC_RX_STAT_XOFFSTATEENTERED 0x00001530
+#define BNX2_EMAC_RX_STAT_DOT3STATSFRAMESTOOLONG 0x00001534
+#define BNX2_EMAC_RX_STAT_ETHERSTATSJABBERS 0x00001538
+#define BNX2_EMAC_RX_STAT_ETHERSTATSUNDERSIZEPKTS 0x0000153c
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS64OCTETS 0x00001540
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS 0x00001544
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS 0x00001548
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x0000154c
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001550
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x00001554
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1523OCTETSTO9022OCTETS 0x00001558
+#define BNX2_EMAC_RXMAC_DEBUG0 0x0000155c
+#define BNX2_EMAC_RXMAC_DEBUG1 0x00001560
+#define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_NE_BYTE_COUNT (1L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_OUT_RANGE (1L<<1)
+#define BNX2_EMAC_RXMAC_DEBUG1_BAD_CRC (1L<<2)
+#define BNX2_EMAC_RXMAC_DEBUG1_RX_ERROR (1L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG1_ALIGN_ERROR (1L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG1_LAST_DATA (1L<<5)
+#define BNX2_EMAC_RXMAC_DEBUG1_ODD_BYTE_START (1L<<6)
+#define BNX2_EMAC_RXMAC_DEBUG1_BYTE_COUNT (0xffffL<<7)
+#define BNX2_EMAC_RXMAC_DEBUG1_SLOT_TIME (0xffL<<23)
+
+#define BNX2_EMAC_RXMAC_DEBUG2 0x00001564
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE (0x7L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_IDLE (0x0L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SFD (0x1L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DATA (0x2L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SKEEP (0x3L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_EXT (0x4L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DROP (0x5L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SDROP (0x6L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_FC (0x7L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE (0xfL<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_IDLE (0x0L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA0 (0x1L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA1 (0x2L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA2 (0x3L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA3 (0x4L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_ABORT (0x5L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_WAIT (0x6L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_STATUS (0x7L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_LAST (0x8L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_BYTE_IN (0xffL<<7)
+#define BNX2_EMAC_RXMAC_DEBUG2_FALSEC (1L<<15)
+#define BNX2_EMAC_RXMAC_DEBUG2_TAGGED (1L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE (1L<<18)
+#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_IDLE (0L<<18)
+#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_PAUSED (1L<<18)
+#define BNX2_EMAC_RXMAC_DEBUG2_SE_COUNTER (0xfL<<19)
+#define BNX2_EMAC_RXMAC_DEBUG2_QUANTA (0x1fL<<23)
+
+#define BNX2_EMAC_RXMAC_DEBUG3 0x00001568
+#define BNX2_EMAC_RXMAC_DEBUG3_PAUSE_CTR (0xffffL<<0)
+#define BNX2_EMAC_RXMAC_DEBUG3_TMP_PAUSE_CTR (0xffffL<<16)
+
+#define BNX2_EMAC_RXMAC_DEBUG4 0x0000156c
+#define BNX2_EMAC_RXMAC_DEBUG4_TYPE_FIELD (0xffffL<<0)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE (0x3fL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_IDLE (0x0L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC2 (0x1L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC3 (0x2L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UNI (0x3L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC2 (0x7L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC3 (0x5L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA1 (0x6L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA2 (0x7L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA3 (0x8L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC2 (0x9L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC3 (0xaL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT1 (0xeL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT2 (0xfL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MCHECK (0x10L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC (0x11L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC2 (0x12L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC3 (0x13L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA1 (0x14L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA2 (0x15L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA3 (0x16L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BTYPE (0x17L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC (0x18L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PTYPE (0x19L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_CMD (0x1aL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MAC (0x1bL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_LATCH (0x1cL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XOFF (0x1dL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XON (0x1eL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PAUSED (0x1fL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_NPAUSED (0x20L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TTYPE (0x21L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TVAL (0x22L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA1 (0x23L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA2 (0x24L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA3 (0x25L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTYPE (0x26L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTTYPE (0x27L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTVAL (0x28L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MTYPE (0x29L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_DROP (0x2aL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_DROP_PKT (1L<<22)
+#define BNX2_EMAC_RXMAC_DEBUG4_SLOT_FILLED (1L<<23)
+#define BNX2_EMAC_RXMAC_DEBUG4_FALSE_CARRIER (1L<<24)
+#define BNX2_EMAC_RXMAC_DEBUG4_LAST_DATA (1L<<25)
+#define BNX2_EMAC_RXMAC_DEBUG4_sfd_FOUND (1L<<26)
+#define BNX2_EMAC_RXMAC_DEBUG4_ADVANCE (1L<<27)
+#define BNX2_EMAC_RXMAC_DEBUG4_START (1L<<28)
+
+#define BNX2_EMAC_RXMAC_DEBUG5 0x00001570
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM (0x7L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_IDLE (0L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_EOF (1L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_STAT (2L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4FCRC (3L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4RDE (4L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4ALL (5L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_1WD_WAIT_STAT (6L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1 (0x7L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_VDW (0x0L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_STAT (0x1L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_AEOF (0x2L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_NEOF (0x3L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SOF (0x4L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SAEOF (0x6L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SNEOF (0x7L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_EOF_DETECTED (1L<<7)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF0 (0x7L<<8)
+#define BNX2_EMAC_RXMAC_DEBUG5_RPM_IDI_FIFO_FULL (1L<<11)
+#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_CCODE (1L<<12)
+#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_DATA (1L<<13)
+#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_STAT (1L<<14)
+#define BNX2_EMAC_RXMAC_DEBUG5_CLR_STAT (1L<<15)
+#define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_CCODE (0x3L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_ACCEPT (1L<<19)
+#define BNX2_EMAC_RXMAC_DEBUG5_FMLEN (0xfffL<<20)
+
+#define BNX2_EMAC_RX_STAT_AC0 0x00001580
+#define BNX2_EMAC_RX_STAT_AC1 0x00001584
+#define BNX2_EMAC_RX_STAT_AC2 0x00001588
+#define BNX2_EMAC_RX_STAT_AC3 0x0000158c
+#define BNX2_EMAC_RX_STAT_AC4 0x00001590
+#define BNX2_EMAC_RX_STAT_AC5 0x00001594
+#define BNX2_EMAC_RX_STAT_AC6 0x00001598
+#define BNX2_EMAC_RX_STAT_AC7 0x0000159c
+#define BNX2_EMAC_RX_STAT_AC8 0x000015a0
+#define BNX2_EMAC_RX_STAT_AC9 0x000015a4
+#define BNX2_EMAC_RX_STAT_AC10 0x000015a8
+#define BNX2_EMAC_RX_STAT_AC11 0x000015ac
+#define BNX2_EMAC_RX_STAT_AC12 0x000015b0
+#define BNX2_EMAC_RX_STAT_AC13 0x000015b4
+#define BNX2_EMAC_RX_STAT_AC14 0x000015b8
+#define BNX2_EMAC_RX_STAT_AC15 0x000015bc
+#define BNX2_EMAC_RX_STAT_AC16 0x000015c0
+#define BNX2_EMAC_RX_STAT_AC17 0x000015c4
+#define BNX2_EMAC_RX_STAT_AC18 0x000015c8
+#define BNX2_EMAC_RX_STAT_AC19 0x000015cc
+#define BNX2_EMAC_RX_STAT_AC20 0x000015d0
+#define BNX2_EMAC_RX_STAT_AC21 0x000015d4
+#define BNX2_EMAC_RX_STAT_AC22 0x000015d8
+#define BNX2_EMAC_RXMAC_SUC_DBG_OVERRUNVEC 0x000015dc
+#define BNX2_EMAC_TX_STAT_IFHCOUTOCTETS 0x00001600
+#define BNX2_EMAC_TX_STAT_IFHCOUTBADOCTETS 0x00001604
+#define BNX2_EMAC_TX_STAT_ETHERSTATSCOLLISIONS 0x00001608
+#define BNX2_EMAC_TX_STAT_OUTXONSENT 0x0000160c
+#define BNX2_EMAC_TX_STAT_OUTXOFFSENT 0x00001610
+#define BNX2_EMAC_TX_STAT_FLOWCONTROLDONE 0x00001614
+#define BNX2_EMAC_TX_STAT_DOT3STATSSINGLECOLLISIONFRAMES 0x00001618
+#define BNX2_EMAC_TX_STAT_DOT3STATSMULTIPLECOLLISIONFRAMES 0x0000161c
+#define BNX2_EMAC_TX_STAT_DOT3STATSDEFERREDTRANSMISSIONS 0x00001620
+#define BNX2_EMAC_TX_STAT_DOT3STATSEXCESSIVECOLLISIONS 0x00001624
+#define BNX2_EMAC_TX_STAT_DOT3STATSLATECOLLISIONS 0x00001628
+#define BNX2_EMAC_TX_STAT_IFHCOUTUCASTPKTS 0x0000162c
+#define BNX2_EMAC_TX_STAT_IFHCOUTMULTICASTPKTS 0x00001630
+#define BNX2_EMAC_TX_STAT_IFHCOUTBROADCASTPKTS 0x00001634
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS64OCTETS 0x00001638
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS 0x0000163c
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS 0x00001640
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x00001644
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001648
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x0000164c
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1523OCTETSTO9022OCTETS 0x00001650
+#define BNX2_EMAC_TX_STAT_DOT3STATSINTERNALMACTRANSMITERRORS 0x00001654
+#define BNX2_EMAC_TXMAC_DEBUG0 0x00001658
+#define BNX2_EMAC_TXMAC_DEBUG1 0x0000165c
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE (0xfL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_IDLE (0x0L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_START0 (0x1L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA0 (0x4L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA1 (0x5L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA2 (0x6L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA3 (0x7L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT0 (0x8L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT1 (0x9L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_CRS_ENABLE (1L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG1_BAD_CRC (1L<<5)
+#define BNX2_EMAC_TXMAC_DEBUG1_SE_COUNTER (0xfL<<6)
+#define BNX2_EMAC_TXMAC_DEBUG1_SEND_PAUSE (1L<<10)
+#define BNX2_EMAC_TXMAC_DEBUG1_LATE_COLLISION (1L<<11)
+#define BNX2_EMAC_TXMAC_DEBUG1_MAX_DEFER (1L<<12)
+#define BNX2_EMAC_TXMAC_DEBUG1_DEFERRED (1L<<13)
+#define BNX2_EMAC_TXMAC_DEBUG1_ONE_BYTE (1L<<14)
+#define BNX2_EMAC_TXMAC_DEBUG1_IPG_TIME (0xfL<<15)
+#define BNX2_EMAC_TXMAC_DEBUG1_SLOT_TIME (0xffL<<19)
+
+#define BNX2_EMAC_TXMAC_DEBUG2 0x00001660
+#define BNX2_EMAC_TXMAC_DEBUG2_BACK_OFF (0x3ffL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG2_BYTE_COUNT (0xffffL<<10)
+#define BNX2_EMAC_TXMAC_DEBUG2_COL_COUNT (0x1fL<<26)
+#define BNX2_EMAC_TXMAC_DEBUG2_COL_BIT (1L<<31)
+
+#define BNX2_EMAC_TXMAC_DEBUG3 0x00001664
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE (0xfL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_IDLE (0x0L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE1 (0x1L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE2 (0x2L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SFD (0x3L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_DATA (0x4L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC1 (0x5L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC2 (0x6L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EXT (0x7L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATB (0x8L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATG (0x9L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_JAM (0xaL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EJAM (0xbL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BJAM (0xcL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SWAIT (0xdL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BACKOFF (0xeL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE (0x7L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_IDLE (0x0L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_WAIT (0x1L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_UNI (0x2L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_MC (0x3L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC2 (0x4L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC3 (0x5L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC (0x6L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_CRS_DONE (1L<<7)
+#define BNX2_EMAC_TXMAC_DEBUG3_XOFF (1L<<8)
+#define BNX2_EMAC_TXMAC_DEBUG3_SE_COUNTER (0xfL<<9)
+#define BNX2_EMAC_TXMAC_DEBUG3_QUANTA_COUNTER (0x1fL<<13)
+
+#define BNX2_EMAC_TXMAC_DEBUG4 0x00001668
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_COUNTER (0xffffL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE (0xfL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_IDLE (0x0L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA1 (0x2L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA2 (0x3L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA3 (0x6L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC1 (0x7L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC2 (0x5L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC3 (0x4L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TYPE (0xcL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CMD (0xeL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TIME (0xaL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC1 (0x8L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC2 (0x9L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_WAIT (0xdL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_STATS0_VALID (1L<<20)
+#define BNX2_EMAC_TXMAC_DEBUG4_APPEND_CRC (1L<<21)
+#define BNX2_EMAC_TXMAC_DEBUG4_SLOT_FILLED (1L<<22)
+#define BNX2_EMAC_TXMAC_DEBUG4_MAX_DEFER (1L<<23)
+#define BNX2_EMAC_TXMAC_DEBUG4_SEND_EXTEND (1L<<24)
+#define BNX2_EMAC_TXMAC_DEBUG4_SEND_PADDING (1L<<25)
+#define BNX2_EMAC_TXMAC_DEBUG4_EOF_LOC (1L<<26)
+#define BNX2_EMAC_TXMAC_DEBUG4_COLLIDING (1L<<27)
+#define BNX2_EMAC_TXMAC_DEBUG4_COL_IN (1L<<28)
+#define BNX2_EMAC_TXMAC_DEBUG4_BURSTING (1L<<29)
+#define BNX2_EMAC_TXMAC_DEBUG4_ADVANCE (1L<<30)
+#define BNX2_EMAC_TXMAC_DEBUG4_GO (1L<<31)
+
+#define BNX2_EMAC_TX_STAT_AC0 0x00001680
+#define BNX2_EMAC_TX_STAT_AC1 0x00001684
+#define BNX2_EMAC_TX_STAT_AC2 0x00001688
+#define BNX2_EMAC_TX_STAT_AC3 0x0000168c
+#define BNX2_EMAC_TX_STAT_AC4 0x00001690
+#define BNX2_EMAC_TX_STAT_AC5 0x00001694
+#define BNX2_EMAC_TX_STAT_AC6 0x00001698
+#define BNX2_EMAC_TX_STAT_AC7 0x0000169c
+#define BNX2_EMAC_TX_STAT_AC8 0x000016a0
+#define BNX2_EMAC_TX_STAT_AC9 0x000016a4
+#define BNX2_EMAC_TX_STAT_AC10 0x000016a8
+#define BNX2_EMAC_TX_STAT_AC11 0x000016ac
+#define BNX2_EMAC_TX_STAT_AC12 0x000016b0
+#define BNX2_EMAC_TX_STAT_AC13 0x000016b4
+#define BNX2_EMAC_TX_STAT_AC14 0x000016b8
+#define BNX2_EMAC_TX_STAT_AC15 0x000016bc
+#define BNX2_EMAC_TX_STAT_AC16 0x000016c0
+#define BNX2_EMAC_TX_STAT_AC17 0x000016c4
+#define BNX2_EMAC_TX_STAT_AC18 0x000016c8
+#define BNX2_EMAC_TX_STAT_AC19 0x000016cc
+#define BNX2_EMAC_TX_STAT_AC20 0x000016d0
+#define BNX2_EMAC_TX_STAT_AC21 0x000016d4
+#define BNX2_EMAC_TXMAC_SUC_DBG_OVERRUNVEC 0x000016d8
+
+
+/*
+ * rpm_reg definition
+ * offset: 0x1800
+ */
+#define BNX2_RPM_COMMAND 0x00001800
+#define BNX2_RPM_COMMAND_ENABLED (1L<<0)
+#define BNX2_RPM_COMMAND_OVERRUN_ABORT (1L<<4)
+
+#define BNX2_RPM_STATUS 0x00001804
+#define BNX2_RPM_STATUS_MBUF_WAIT (1L<<0)
+#define BNX2_RPM_STATUS_FREE_WAIT (1L<<1)
+
+#define BNX2_RPM_CONFIG 0x00001808
+#define BNX2_RPM_CONFIG_NO_PSD_HDR_CKSUM (1L<<0)
+#define BNX2_RPM_CONFIG_ACPI_ENA (1L<<1)
+#define BNX2_RPM_CONFIG_ACPI_KEEP (1L<<2)
+#define BNX2_RPM_CONFIG_MP_KEEP (1L<<3)
+#define BNX2_RPM_CONFIG_SORT_VECT_VAL (0xfL<<4)
+#define BNX2_RPM_CONFIG_IGNORE_VLAN (1L<<31)
+
+#define BNX2_RPM_VLAN_MATCH0 0x00001810
+#define BNX2_RPM_VLAN_MATCH0_RPM_VLAN_MTCH0_VALUE (0xfffL<<0)
+
+#define BNX2_RPM_VLAN_MATCH1 0x00001814
+#define BNX2_RPM_VLAN_MATCH1_RPM_VLAN_MTCH1_VALUE (0xfffL<<0)
+
+#define BNX2_RPM_VLAN_MATCH2 0x00001818
+#define BNX2_RPM_VLAN_MATCH2_RPM_VLAN_MTCH2_VALUE (0xfffL<<0)
+
+#define BNX2_RPM_VLAN_MATCH3 0x0000181c
+#define BNX2_RPM_VLAN_MATCH3_RPM_VLAN_MTCH3_VALUE (0xfffL<<0)
+
+#define BNX2_RPM_SORT_USER0 0x00001820
+#define BNX2_RPM_SORT_USER0_PM_EN (0xffffL<<0)
+#define BNX2_RPM_SORT_USER0_BC_EN (1L<<16)
+#define BNX2_RPM_SORT_USER0_MC_EN (1L<<17)
+#define BNX2_RPM_SORT_USER0_MC_HSH_EN (1L<<18)
+#define BNX2_RPM_SORT_USER0_PROM_EN (1L<<19)
+#define BNX2_RPM_SORT_USER0_VLAN_EN (0xfL<<20)
+#define BNX2_RPM_SORT_USER0_PROM_VLAN (1L<<24)
+#define BNX2_RPM_SORT_USER0_ENA (1L<<31)
+
+#define BNX2_RPM_SORT_USER1 0x00001824
+#define BNX2_RPM_SORT_USER1_PM_EN (0xffffL<<0)
+#define BNX2_RPM_SORT_USER1_BC_EN (1L<<16)
+#define BNX2_RPM_SORT_USER1_MC_EN (1L<<17)
+#define BNX2_RPM_SORT_USER1_MC_HSH_EN (1L<<18)
+#define BNX2_RPM_SORT_USER1_PROM_EN (1L<<19)
+#define BNX2_RPM_SORT_USER1_VLAN_EN (0xfL<<20)
+#define BNX2_RPM_SORT_USER1_PROM_VLAN (1L<<24)
+#define BNX2_RPM_SORT_USER1_ENA (1L<<31)
+
+#define BNX2_RPM_SORT_USER2 0x00001828
+#define BNX2_RPM_SORT_USER2_PM_EN (0xffffL<<0)
+#define BNX2_RPM_SORT_USER2_BC_EN (1L<<16)
+#define BNX2_RPM_SORT_USER2_MC_EN (1L<<17)
+#define BNX2_RPM_SORT_USER2_MC_HSH_EN (1L<<18)
+#define BNX2_RPM_SORT_USER2_PROM_EN (1L<<19)
+#define BNX2_RPM_SORT_USER2_VLAN_EN (0xfL<<20)
+#define BNX2_RPM_SORT_USER2_PROM_VLAN (1L<<24)
+#define BNX2_RPM_SORT_USER2_ENA (1L<<31)
+
+#define BNX2_RPM_SORT_USER3 0x0000182c
+#define BNX2_RPM_SORT_USER3_PM_EN (0xffffL<<0)
+#define BNX2_RPM_SORT_USER3_BC_EN (1L<<16)
+#define BNX2_RPM_SORT_USER3_MC_EN (1L<<17)
+#define BNX2_RPM_SORT_USER3_MC_HSH_EN (1L<<18)
+#define BNX2_RPM_SORT_USER3_PROM_EN (1L<<19)
+#define BNX2_RPM_SORT_USER3_VLAN_EN (0xfL<<20)
+#define BNX2_RPM_SORT_USER3_PROM_VLAN (1L<<24)
+#define BNX2_RPM_SORT_USER3_ENA (1L<<31)
+
+#define BNX2_RPM_STAT_L2_FILTER_DISCARDS 0x00001840
+#define BNX2_RPM_STAT_RULE_CHECKER_DISCARDS 0x00001844
+#define BNX2_RPM_STAT_IFINFTQDISCARDS 0x00001848
+#define BNX2_RPM_STAT_IFINMBUFDISCARD 0x0000184c
+#define BNX2_RPM_STAT_RULE_CHECKER_P4_HIT 0x00001850
+#define BNX2_RPM_STAT_AC0 0x00001880
+#define BNX2_RPM_STAT_AC1 0x00001884
+#define BNX2_RPM_STAT_AC2 0x00001888
+#define BNX2_RPM_STAT_AC3 0x0000188c
+#define BNX2_RPM_STAT_AC4 0x00001890
+#define BNX2_RPM_RC_CNTL_0 0x00001900
+#define BNX2_RPM_RC_CNTL_0_OFFSET (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_0_CLASS (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_0_PRIORITY (1L<<11)
+#define BNX2_RPM_RC_CNTL_0_P4 (1L<<12)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_START (0L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_IP (1L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP (2L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_UDP (3L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_DATA (4L<<13)
+#define BNX2_RPM_RC_CNTL_0_COMP (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_0_COMP_EQUAL (0L<<16)
+#define BNX2_RPM_RC_CNTL_0_COMP_NEQUAL (1L<<16)
+#define BNX2_RPM_RC_CNTL_0_COMP_GREATER (2L<<16)
+#define BNX2_RPM_RC_CNTL_0_COMP_LESS (3L<<16)
+#define BNX2_RPM_RC_CNTL_0_SBIT (1L<<19)
+#define BNX2_RPM_RC_CNTL_0_CMDSEL (0xfL<<20)
+#define BNX2_RPM_RC_CNTL_0_MAP (1L<<24)
+#define BNX2_RPM_RC_CNTL_0_DISCARD (1L<<25)
+#define BNX2_RPM_RC_CNTL_0_MASK (1L<<26)
+#define BNX2_RPM_RC_CNTL_0_P1 (1L<<27)
+#define BNX2_RPM_RC_CNTL_0_P2 (1L<<28)
+#define BNX2_RPM_RC_CNTL_0_P3 (1L<<29)
+#define BNX2_RPM_RC_CNTL_0_NBIT (1L<<30)
+
+#define BNX2_RPM_RC_VALUE_MASK_0 0x00001904
+#define BNX2_RPM_RC_VALUE_MASK_0_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_0_MASK (0xffffL<<16)
+
+#define BNX2_RPM_RC_CNTL_1 0x00001908
+#define BNX2_RPM_RC_CNTL_1_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_1_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_1 0x0000190c
+#define BNX2_RPM_RC_CNTL_2 0x00001910
+#define BNX2_RPM_RC_CNTL_2_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_2_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_2 0x00001914
+#define BNX2_RPM_RC_CNTL_3 0x00001918
+#define BNX2_RPM_RC_CNTL_3_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_3_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_3 0x0000191c
+#define BNX2_RPM_RC_CNTL_4 0x00001920
+#define BNX2_RPM_RC_CNTL_4_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_4_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_4 0x00001924
+#define BNX2_RPM_RC_CNTL_5 0x00001928
+#define BNX2_RPM_RC_CNTL_5_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_5_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_5 0x0000192c
+#define BNX2_RPM_RC_CNTL_6 0x00001930
+#define BNX2_RPM_RC_CNTL_6_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_6_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_6 0x00001934
+#define BNX2_RPM_RC_CNTL_7 0x00001938
+#define BNX2_RPM_RC_CNTL_7_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_7_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_7 0x0000193c
+#define BNX2_RPM_RC_CNTL_8 0x00001940
+#define BNX2_RPM_RC_CNTL_8_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_8_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_8 0x00001944
+#define BNX2_RPM_RC_CNTL_9 0x00001948
+#define BNX2_RPM_RC_CNTL_9_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_9_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_9 0x0000194c
+#define BNX2_RPM_RC_CNTL_10 0x00001950
+#define BNX2_RPM_RC_CNTL_10_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_10_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_10 0x00001954
+#define BNX2_RPM_RC_CNTL_11 0x00001958
+#define BNX2_RPM_RC_CNTL_11_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_11_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_11 0x0000195c
+#define BNX2_RPM_RC_CNTL_12 0x00001960
+#define BNX2_RPM_RC_CNTL_12_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_12_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_12 0x00001964
+#define BNX2_RPM_RC_CNTL_13 0x00001968
+#define BNX2_RPM_RC_CNTL_13_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_13_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_13 0x0000196c
+#define BNX2_RPM_RC_CNTL_14 0x00001970
+#define BNX2_RPM_RC_CNTL_14_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_14_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_14 0x00001974
+#define BNX2_RPM_RC_CNTL_15 0x00001978
+#define BNX2_RPM_RC_CNTL_15_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_15_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_15 0x0000197c
+#define BNX2_RPM_RC_CONFIG 0x00001980
+#define BNX2_RPM_RC_CONFIG_RULE_ENABLE (0xffffL<<0)
+#define BNX2_RPM_RC_CONFIG_DEF_CLASS (0x7L<<24)
+
+#define BNX2_RPM_DEBUG0 0x00001984
+#define BNX2_RPM_DEBUG0_FM_BCNT (0xffffL<<0)
+#define BNX2_RPM_DEBUG0_T_DATA_OFST_VLD (1L<<16)
+#define BNX2_RPM_DEBUG0_T_UDP_OFST_VLD (1L<<17)
+#define BNX2_RPM_DEBUG0_T_TCP_OFST_VLD (1L<<18)
+#define BNX2_RPM_DEBUG0_T_IP_OFST_VLD (1L<<19)
+#define BNX2_RPM_DEBUG0_IP_MORE_FRGMT (1L<<20)
+#define BNX2_RPM_DEBUG0_T_IP_NO_TCP_UDP_HDR (1L<<21)
+#define BNX2_RPM_DEBUG0_LLC_SNAP (1L<<22)
+#define BNX2_RPM_DEBUG0_FM_STARTED (1L<<23)
+#define BNX2_RPM_DEBUG0_DONE (1L<<24)
+#define BNX2_RPM_DEBUG0_WAIT_4_DONE (1L<<25)
+#define BNX2_RPM_DEBUG0_USE_TPBUF_CKSUM (1L<<26)
+#define BNX2_RPM_DEBUG0_RX_NO_PSD_HDR_CKSUM (1L<<27)
+#define BNX2_RPM_DEBUG0_IGNORE_VLAN (1L<<28)
+#define BNX2_RPM_DEBUG0_RP_ENA_ACTIVE (1L<<31)
+
+#define BNX2_RPM_DEBUG1 0x00001988
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST (0xffffL<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IDLE (0L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_ALL (1L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IPLLC (2L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_IP (4L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IP (8L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP_START (16L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP (32L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_TCP (64L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_UDP (128L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_AH (256L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP (512L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP_PAYLOAD (1024L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_DATA (2048L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRY (0x2000L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRYOUT (0x4000L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_LATCH_RESULT (0x8000L<<0)
+#define BNX2_RPM_DEBUG1_HDR_BCNT (0x7ffL<<16)
+#define BNX2_RPM_DEBUG1_UNKNOWN_ETYPE_D (1L<<28)
+#define BNX2_RPM_DEBUG1_VLAN_REMOVED_D2 (1L<<29)
+#define BNX2_RPM_DEBUG1_VLAN_REMOVED_D1 (1L<<30)
+#define BNX2_RPM_DEBUG1_EOF_0XTRA_WD (1L<<31)
+
+#define BNX2_RPM_DEBUG2 0x0000198c
+#define BNX2_RPM_DEBUG2_CMD_HIT_VEC (0xffffL<<0)
+#define BNX2_RPM_DEBUG2_IP_BCNT (0xffL<<16)
+#define BNX2_RPM_DEBUG2_THIS_CMD_M4 (1L<<24)
+#define BNX2_RPM_DEBUG2_THIS_CMD_M3 (1L<<25)
+#define BNX2_RPM_DEBUG2_THIS_CMD_M2 (1L<<26)
+#define BNX2_RPM_DEBUG2_THIS_CMD_M1 (1L<<27)
+#define BNX2_RPM_DEBUG2_IPIPE_EMPTY (1L<<28)
+#define BNX2_RPM_DEBUG2_FM_DISCARD (1L<<29)
+#define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D2 (1L<<30)
+#define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D1 (1L<<31)
+
+#define BNX2_RPM_DEBUG3 0x00001990
+#define BNX2_RPM_DEBUG3_AVAIL_MBUF_PTR (0x1ffL<<0)
+#define BNX2_RPM_DEBUG3_RDE_RLUPQ_WR_REQ_INT (1L<<9)
+#define BNX2_RPM_DEBUG3_RDE_RBUF_WR_LAST_INT (1L<<10)
+#define BNX2_RPM_DEBUG3_RDE_RBUF_WR_REQ_INT (1L<<11)
+#define BNX2_RPM_DEBUG3_RDE_RBUF_FREE_REQ (1L<<12)
+#define BNX2_RPM_DEBUG3_RDE_RBUF_ALLOC_REQ (1L<<13)
+#define BNX2_RPM_DEBUG3_DFSM_MBUF_NOTAVAIL (1L<<14)
+#define BNX2_RPM_DEBUG3_RBUF_RDE_SOF_DROP (1L<<15)
+#define BNX2_RPM_DEBUG3_DFIFO_VLD_ENTRY_CT (0xfL<<16)
+#define BNX2_RPM_DEBUG3_RDE_SRC_FIFO_ALMFULL (1L<<21)
+#define BNX2_RPM_DEBUG3_DROP_NXT_VLD (1L<<22)
+#define BNX2_RPM_DEBUG3_DROP_NXT (1L<<23)
+#define BNX2_RPM_DEBUG3_FTQ_FSM (0x3L<<24)
+#define BNX2_RPM_DEBUG3_FTQ_FSM_IDLE (0x0L<<24)
+#define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_ACK (0x1L<<24)
+#define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_FREE (0x2L<<24)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM (0x3L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_SOF (0x0L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_GET_MBUF (0x1L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_DMA_DATA (0x2L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DATA (0x3L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_EOF (0x4L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_MF_ACK (0x5L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DROP_NXT_VLD (0x6L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_DONE (0x7L<<26)
+#define BNX2_RPM_DEBUG3_MBFREE_FSM (1L<<29)
+#define BNX2_RPM_DEBUG3_MBFREE_FSM_IDLE (0L<<29)
+#define BNX2_RPM_DEBUG3_MBFREE_FSM_WAIT_ACK (1L<<29)
+#define BNX2_RPM_DEBUG3_MBALLOC_FSM (1L<<30)
+#define BNX2_RPM_DEBUG3_MBALLOC_FSM_ET_MBUF (0x0L<<30)
+#define BNX2_RPM_DEBUG3_MBALLOC_FSM_IVE_MBUF (0x1L<<30)
+#define BNX2_RPM_DEBUG3_CCODE_EOF_ERROR (1L<<31)
+
+#define BNX2_RPM_DEBUG4 0x00001994
+#define BNX2_RPM_DEBUG4_DFSM_MBUF_CLUSTER (0x1ffffffL<<0)
+#define BNX2_RPM_DEBUG4_DFIFO_CUR_CCODE (0x7L<<25)
+#define BNX2_RPM_DEBUG4_MBWRITE_FSM (0x7L<<28)
+#define BNX2_RPM_DEBUG4_DFIFO_EMPTY (1L<<31)
+
+#define BNX2_RPM_DEBUG5 0x00001998
+#define BNX2_RPM_DEBUG5_RDROP_WPTR (0x1fL<<0)
+#define BNX2_RPM_DEBUG5_RDROP_ACPI_RPTR (0x1fL<<5)
+#define BNX2_RPM_DEBUG5_RDROP_MC_RPTR (0x1fL<<10)
+#define BNX2_RPM_DEBUG5_RDROP_RC_RPTR (0x1fL<<15)
+#define BNX2_RPM_DEBUG5_RDROP_ACPI_EMPTY (1L<<20)
+#define BNX2_RPM_DEBUG5_RDROP_MC_EMPTY (1L<<21)
+#define BNX2_RPM_DEBUG5_RDROP_AEOF_VEC_AT_RDROP_MC_RPTR (1L<<22)
+#define BNX2_RPM_DEBUG5_HOLDREG_WOL_DROP_INT (1L<<23)
+#define BNX2_RPM_DEBUG5_HOLDREG_DISCARD (1L<<24)
+#define BNX2_RPM_DEBUG5_HOLDREG_MBUF_NOTAVAIL (1L<<25)
+#define BNX2_RPM_DEBUG5_HOLDREG_MC_EMPTY (1L<<26)
+#define BNX2_RPM_DEBUG5_HOLDREG_RC_EMPTY (1L<<27)
+#define BNX2_RPM_DEBUG5_HOLDREG_FC_EMPTY (1L<<28)
+#define BNX2_RPM_DEBUG5_HOLDREG_ACPI_EMPTY (1L<<29)
+#define BNX2_RPM_DEBUG5_HOLDREG_FULL_T (1L<<30)
+#define BNX2_RPM_DEBUG5_HOLDREG_RD (1L<<31)
+
+#define BNX2_RPM_DEBUG6 0x0000199c
+#define BNX2_RPM_DEBUG6_ACPI_VEC (0xffffL<<0)
+#define BNX2_RPM_DEBUG6_VEC (0xffffL<<16)
+
+#define BNX2_RPM_DEBUG7 0x000019a0
+#define BNX2_RPM_DEBUG7_RPM_DBG7_LAST_CRC (0xffffffffL<<0)
+
+#define BNX2_RPM_DEBUG8 0x000019a4
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM (0xfL<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_IDLE (0L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W1_ADDR (1L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W2_ADDR (2L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W3_ADDR (3L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_WAIT_THBUF (4L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_DATA (5L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W0_ADDR (6L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W1_ADDR (7L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W2_ADDR (8L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_ADDR (9L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_WAIT_THBUF (10L<<0)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_W0 (1L<<4)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_W3_DATA (1L<<5)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_WAIT (1L<<6)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W3 (1L<<7)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W2 (1L<<8)
+#define BNX2_RPM_DEBUG8_EOF_W_LTEQ6_VLDBYTES (1L<<9)
+#define BNX2_RPM_DEBUG8_EOF_W_LTEQ4_VLDBYTES (1L<<10)
+#define BNX2_RPM_DEBUG8_NXT_EOF_W_12_VLDBYTES (1L<<11)
+#define BNX2_RPM_DEBUG8_EOF_DET (1L<<12)
+#define BNX2_RPM_DEBUG8_SOF_DET (1L<<13)
+#define BNX2_RPM_DEBUG8_WAIT_4_SOF (1L<<14)
+#define BNX2_RPM_DEBUG8_ALL_DONE (1L<<15)
+#define BNX2_RPM_DEBUG8_THBUF_ADDR (0x7fL<<16)
+#define BNX2_RPM_DEBUG8_BYTE_CTR (0xffL<<24)
+
+#define BNX2_RPM_DEBUG9 0x000019a8
+#define BNX2_RPM_DEBUG9_OUTFIFO_COUNT (0x7L<<0)
+#define BNX2_RPM_DEBUG9_RDE_ACPI_RDY (1L<<3)
+#define BNX2_RPM_DEBUG9_VLD_RD_ENTRY_CT (0x7L<<4)
+#define BNX2_RPM_DEBUG9_OUTFIFO_OVERRUN_OCCURRED (1L<<28)
+#define BNX2_RPM_DEBUG9_INFIFO_OVERRUN_OCCURRED (1L<<29)
+#define BNX2_RPM_DEBUG9_ACPI_MATCH_INT (1L<<30)
+#define BNX2_RPM_DEBUG9_ACPI_ENABLE_SYN (1L<<31)
+
+#define BNX2_RPM_ACPI_DBG_BUF_W00 0x000019c0
+#define BNX2_RPM_ACPI_DBG_BUF_W01 0x000019c4
+#define BNX2_RPM_ACPI_DBG_BUF_W02 0x000019c8
+#define BNX2_RPM_ACPI_DBG_BUF_W03 0x000019cc
+#define BNX2_RPM_ACPI_DBG_BUF_W10 0x000019d0
+#define BNX2_RPM_ACPI_DBG_BUF_W11 0x000019d4
+#define BNX2_RPM_ACPI_DBG_BUF_W12 0x000019d8
+#define BNX2_RPM_ACPI_DBG_BUF_W13 0x000019dc
+#define BNX2_RPM_ACPI_DBG_BUF_W20 0x000019e0
+#define BNX2_RPM_ACPI_DBG_BUF_W21 0x000019e4
+#define BNX2_RPM_ACPI_DBG_BUF_W22 0x000019e8
+#define BNX2_RPM_ACPI_DBG_BUF_W23 0x000019ec
+#define BNX2_RPM_ACPI_DBG_BUF_W30 0x000019f0
+#define BNX2_RPM_ACPI_DBG_BUF_W31 0x000019f4
+#define BNX2_RPM_ACPI_DBG_BUF_W32 0x000019f8
+#define BNX2_RPM_ACPI_DBG_BUF_W33 0x000019fc
+
+
+/*
+ * rbuf_reg definition
+ * offset: 0x200000
+ */
+#define BNX2_RBUF_COMMAND 0x00200000
+#define BNX2_RBUF_COMMAND_ENABLED (1L<<0)
+#define BNX2_RBUF_COMMAND_FREE_INIT (1L<<1)
+#define BNX2_RBUF_COMMAND_RAM_INIT (1L<<2)
+#define BNX2_RBUF_COMMAND_OVER_FREE (1L<<4)
+#define BNX2_RBUF_COMMAND_ALLOC_REQ (1L<<5)
+
+#define BNX2_RBUF_STATUS1 0x00200004
+#define BNX2_RBUF_STATUS1_FREE_COUNT (0x3ffL<<0)
+
+#define BNX2_RBUF_STATUS2 0x00200008
+#define BNX2_RBUF_STATUS2_FREE_TAIL (0x3ffL<<0)
+#define BNX2_RBUF_STATUS2_FREE_HEAD (0x3ffL<<16)
+
+#define BNX2_RBUF_CONFIG 0x0020000c
+#define BNX2_RBUF_CONFIG_XOFF_TRIP (0x3ffL<<0)
+#define BNX2_RBUF_CONFIG_XON_TRIP (0x3ffL<<16)
+
+#define BNX2_RBUF_FW_BUF_ALLOC 0x00200010
+#define BNX2_RBUF_FW_BUF_ALLOC_VALUE (0x1ffL<<7)
+
+#define BNX2_RBUF_FW_BUF_FREE 0x00200014
+#define BNX2_RBUF_FW_BUF_FREE_COUNT (0x7fL<<0)
+#define BNX2_RBUF_FW_BUF_FREE_TAIL (0x1ffL<<7)
+#define BNX2_RBUF_FW_BUF_FREE_HEAD (0x1ffL<<16)
+
+#define BNX2_RBUF_FW_BUF_SEL 0x00200018
+#define BNX2_RBUF_FW_BUF_SEL_COUNT (0x7fL<<0)
+#define BNX2_RBUF_FW_BUF_SEL_TAIL (0x1ffL<<7)
+#define BNX2_RBUF_FW_BUF_SEL_HEAD (0x1ffL<<16)
+
+#define BNX2_RBUF_CONFIG2 0x0020001c
+#define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP (0x3ffL<<0)
+#define BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP (0x3ffL<<16)
+
+#define BNX2_RBUF_CONFIG3 0x00200020
+#define BNX2_RBUF_CONFIG3_CU_DROP_TRIP (0x3ffL<<0)
+#define BNX2_RBUF_CONFIG3_CU_KEEP_TRIP (0x3ffL<<16)
+
+#define BNX2_RBUF_PKT_DATA 0x00208000
+#define BNX2_RBUF_CLIST_DATA 0x00210000
+#define BNX2_RBUF_BUF_DATA 0x00220000
+
+
+/*
+ * rv2p_reg definition
+ * offset: 0x2800
+ */
+#define BNX2_RV2P_COMMAND 0x00002800
+#define BNX2_RV2P_COMMAND_ENABLED (1L<<0)
+#define BNX2_RV2P_COMMAND_PROC1_INTRPT (1L<<1)
+#define BNX2_RV2P_COMMAND_PROC2_INTRPT (1L<<2)
+#define BNX2_RV2P_COMMAND_ABORT0 (1L<<4)
+#define BNX2_RV2P_COMMAND_ABORT1 (1L<<5)
+#define BNX2_RV2P_COMMAND_ABORT2 (1L<<6)
+#define BNX2_RV2P_COMMAND_ABORT3 (1L<<7)
+#define BNX2_RV2P_COMMAND_ABORT4 (1L<<8)
+#define BNX2_RV2P_COMMAND_ABORT5 (1L<<9)
+#define BNX2_RV2P_COMMAND_PROC1_RESET (1L<<16)
+#define BNX2_RV2P_COMMAND_PROC2_RESET (1L<<17)
+#define BNX2_RV2P_COMMAND_CTXIF_RESET (1L<<18)
+
+#define BNX2_RV2P_STATUS 0x00002804
+#define BNX2_RV2P_STATUS_ALWAYS_0 (1L<<0)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT0_CNT (1L<<8)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT1_CNT (1L<<9)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT2_CNT (1L<<10)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT3_CNT (1L<<11)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT4_CNT (1L<<12)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT5_CNT (1L<<13)
+
+#define BNX2_RV2P_CONFIG 0x00002808
+#define BNX2_RV2P_CONFIG_STALL_PROC1 (1L<<0)
+#define BNX2_RV2P_CONFIG_STALL_PROC2 (1L<<1)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT0 (1L<<8)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT1 (1L<<9)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT2 (1L<<10)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT3 (1L<<11)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT4 (1L<<12)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT5 (1L<<13)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT0 (1L<<16)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT1 (1L<<17)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT2 (1L<<18)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT3 (1L<<19)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT4 (1L<<20)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT5 (1L<<21)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE (0xfL<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_256 (0L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_512 (1L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_1K (2L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_2K (3L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_4K (4L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_8K (5L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_16K (6L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_32K (7L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_64K (8L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_128K (9L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_256K (10L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_512K (11L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_1M (12L<<24)
+
+#define BNX2_RV2P_GEN_BFR_ADDR_0 0x00002810
+#define BNX2_RV2P_GEN_BFR_ADDR_0_VALUE (0xffffL<<16)
+
+#define BNX2_RV2P_GEN_BFR_ADDR_1 0x00002814
+#define BNX2_RV2P_GEN_BFR_ADDR_1_VALUE (0xffffL<<16)
+
+#define BNX2_RV2P_GEN_BFR_ADDR_2 0x00002818
+#define BNX2_RV2P_GEN_BFR_ADDR_2_VALUE (0xffffL<<16)
+
+#define BNX2_RV2P_GEN_BFR_ADDR_3 0x0000281c
+#define BNX2_RV2P_GEN_BFR_ADDR_3_VALUE (0xffffL<<16)
+
+#define BNX2_RV2P_INSTR_HIGH 0x00002830
+#define BNX2_RV2P_INSTR_HIGH_HIGH (0x1fL<<0)
+
+#define BNX2_RV2P_INSTR_LOW 0x00002834
+#define BNX2_RV2P_PROC1_ADDR_CMD 0x00002838
+#define BNX2_RV2P_PROC1_ADDR_CMD_ADD (0x3ffL<<0)
+#define BNX2_RV2P_PROC1_ADDR_CMD_RDWR (1L<<31)
+
+#define BNX2_RV2P_PROC2_ADDR_CMD 0x0000283c
+#define BNX2_RV2P_PROC2_ADDR_CMD_ADD (0x3ffL<<0)
+#define BNX2_RV2P_PROC2_ADDR_CMD_RDWR (1L<<31)
+
+#define BNX2_RV2P_PROC1_GRC_DEBUG 0x00002840
+#define BNX2_RV2P_PROC2_GRC_DEBUG 0x00002844
+#define BNX2_RV2P_GRC_PROC_DEBUG 0x00002848
+#define BNX2_RV2P_DEBUG_VECT_PEEK 0x0000284c
+#define BNX2_RV2P_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_RV2P_PFTQ_DATA 0x00002b40
+#define BNX2_RV2P_PFTQ_CMD 0x00002b78
+#define BNX2_RV2P_PFTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RV2P_PFTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RV2P_PFTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RV2P_PFTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RV2P_PFTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RV2P_PFTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RV2P_PFTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RV2P_PFTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RV2P_PFTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RV2P_PFTQ_CMD_POP (1L<<30)
+#define BNX2_RV2P_PFTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RV2P_PFTQ_CTL 0x00002b7c
+#define BNX2_RV2P_PFTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RV2P_PFTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RV2P_PFTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RV2P_PFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RV2P_PFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_RV2P_TFTQ_DATA 0x00002b80
+#define BNX2_RV2P_TFTQ_CMD 0x00002bb8
+#define BNX2_RV2P_TFTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RV2P_TFTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RV2P_TFTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RV2P_TFTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RV2P_TFTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RV2P_TFTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RV2P_TFTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RV2P_TFTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RV2P_TFTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RV2P_TFTQ_CMD_POP (1L<<30)
+#define BNX2_RV2P_TFTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RV2P_TFTQ_CTL 0x00002bbc
+#define BNX2_RV2P_TFTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RV2P_TFTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RV2P_TFTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RV2P_TFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RV2P_TFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_RV2P_MFTQ_DATA 0x00002bc0
+#define BNX2_RV2P_MFTQ_CMD 0x00002bf8
+#define BNX2_RV2P_MFTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RV2P_MFTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RV2P_MFTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RV2P_MFTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RV2P_MFTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RV2P_MFTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RV2P_MFTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RV2P_MFTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RV2P_MFTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RV2P_MFTQ_CMD_POP (1L<<30)
+#define BNX2_RV2P_MFTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RV2P_MFTQ_CTL 0x00002bfc
+#define BNX2_RV2P_MFTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RV2P_MFTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RV2P_MFTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RV2P_MFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RV2P_MFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+
+
+/*
+ * mq_reg definition
+ * offset: 0x3c00
+ */
+#define BNX2_MQ_COMMAND 0x00003c00
+#define BNX2_MQ_COMMAND_ENABLED (1L<<0)
+#define BNX2_MQ_COMMAND_OVERFLOW (1L<<4)
+#define BNX2_MQ_COMMAND_WR_ERROR (1L<<5)
+#define BNX2_MQ_COMMAND_RD_ERROR (1L<<6)
+
+#define BNX2_MQ_STATUS 0x00003c04
+#define BNX2_MQ_STATUS_CTX_ACCESS_STAT (1L<<16)
+#define BNX2_MQ_STATUS_CTX_ACCESS64_STAT (1L<<17)
+#define BNX2_MQ_STATUS_PCI_STALL_STAT (1L<<18)
+
+#define BNX2_MQ_CONFIG 0x00003c08
+#define BNX2_MQ_CONFIG_TX_HIGH_PRI (1L<<0)
+#define BNX2_MQ_CONFIG_HALT_DIS (1L<<1)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE (0x7L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256 (0L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_512 (1L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_1K (2L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_2K (3L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_4K (4L<<4)
+#define BNX2_MQ_CONFIG_MAX_DEPTH (0x7fL<<8)
+#define BNX2_MQ_CONFIG_CUR_DEPTH (0x7fL<<20)
+
+#define BNX2_MQ_ENQUEUE1 0x00003c0c
+#define BNX2_MQ_ENQUEUE1_OFFSET (0x3fL<<2)
+#define BNX2_MQ_ENQUEUE1_CID (0x3fffL<<8)
+#define BNX2_MQ_ENQUEUE1_BYTE_MASK (0xfL<<24)
+#define BNX2_MQ_ENQUEUE1_KNL_MODE (1L<<28)
+
+#define BNX2_MQ_ENQUEUE2 0x00003c10
+#define BNX2_MQ_BAD_WR_ADDR 0x00003c14
+#define BNX2_MQ_BAD_RD_ADDR 0x00003c18
+#define BNX2_MQ_KNL_BYP_WIND_START 0x00003c1c
+#define BNX2_MQ_KNL_BYP_WIND_START_VALUE (0xfffffL<<12)
+
+#define BNX2_MQ_KNL_WIND_END 0x00003c20
+#define BNX2_MQ_KNL_WIND_END_VALUE (0xffffffL<<8)
+
+#define BNX2_MQ_KNL_WRITE_MASK1 0x00003c24
+#define BNX2_MQ_KNL_TX_MASK1 0x00003c28
+#define BNX2_MQ_KNL_CMD_MASK1 0x00003c2c
+#define BNX2_MQ_KNL_COND_ENQUEUE_MASK1 0x00003c30
+#define BNX2_MQ_KNL_RX_V2P_MASK1 0x00003c34
+#define BNX2_MQ_KNL_WRITE_MASK2 0x00003c38
+#define BNX2_MQ_KNL_TX_MASK2 0x00003c3c
+#define BNX2_MQ_KNL_CMD_MASK2 0x00003c40
+#define BNX2_MQ_KNL_COND_ENQUEUE_MASK2 0x00003c44
+#define BNX2_MQ_KNL_RX_V2P_MASK2 0x00003c48
+#define BNX2_MQ_KNL_BYP_WRITE_MASK1 0x00003c4c
+#define BNX2_MQ_KNL_BYP_TX_MASK1 0x00003c50
+#define BNX2_MQ_KNL_BYP_CMD_MASK1 0x00003c54
+#define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK1 0x00003c58
+#define BNX2_MQ_KNL_BYP_RX_V2P_MASK1 0x00003c5c
+#define BNX2_MQ_KNL_BYP_WRITE_MASK2 0x00003c60
+#define BNX2_MQ_KNL_BYP_TX_MASK2 0x00003c64
+#define BNX2_MQ_KNL_BYP_CMD_MASK2 0x00003c68
+#define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK2 0x00003c6c
+#define BNX2_MQ_KNL_BYP_RX_V2P_MASK2 0x00003c70
+#define BNX2_MQ_MEM_WR_ADDR 0x00003c74
+#define BNX2_MQ_MEM_WR_ADDR_VALUE (0x3fL<<0)
+
+#define BNX2_MQ_MEM_WR_DATA0 0x00003c78
+#define BNX2_MQ_MEM_WR_DATA0_VALUE (0xffffffffL<<0)
+
+#define BNX2_MQ_MEM_WR_DATA1 0x00003c7c
+#define BNX2_MQ_MEM_WR_DATA1_VALUE (0xffffffffL<<0)
+
+#define BNX2_MQ_MEM_WR_DATA2 0x00003c80
+#define BNX2_MQ_MEM_WR_DATA2_VALUE (0x3fffffffL<<0)
+
+#define BNX2_MQ_MEM_RD_ADDR 0x00003c84
+#define BNX2_MQ_MEM_RD_ADDR_VALUE (0x3fL<<0)
+
+#define BNX2_MQ_MEM_RD_DATA0 0x00003c88
+#define BNX2_MQ_MEM_RD_DATA0_VALUE (0xffffffffL<<0)
+
+#define BNX2_MQ_MEM_RD_DATA1 0x00003c8c
+#define BNX2_MQ_MEM_RD_DATA1_VALUE (0xffffffffL<<0)
+
+#define BNX2_MQ_MEM_RD_DATA2 0x00003c90
+#define BNX2_MQ_MEM_RD_DATA2_VALUE (0x3fffffffL<<0)
+
+
+
+/*
+ * tbdr_reg definition
+ * offset: 0x5000
+ */
+#define BNX2_TBDR_COMMAND 0x00005000
+#define BNX2_TBDR_COMMAND_ENABLE (1L<<0)
+#define BNX2_TBDR_COMMAND_SOFT_RST (1L<<1)
+#define BNX2_TBDR_COMMAND_MSTR_ABORT (1L<<4)
+
+#define BNX2_TBDR_STATUS 0x00005004
+#define BNX2_TBDR_STATUS_DMA_WAIT (1L<<0)
+#define BNX2_TBDR_STATUS_FTQ_WAIT (1L<<1)
+#define BNX2_TBDR_STATUS_FIFO_OVERFLOW (1L<<2)
+#define BNX2_TBDR_STATUS_FIFO_UNDERFLOW (1L<<3)
+#define BNX2_TBDR_STATUS_SEARCHMISS_ERROR (1L<<4)
+#define BNX2_TBDR_STATUS_FTQ_ENTRY_CNT (1L<<5)
+#define BNX2_TBDR_STATUS_BURST_CNT (1L<<6)
+
+#define BNX2_TBDR_CONFIG 0x00005008
+#define BNX2_TBDR_CONFIG_MAX_BDS (0xffL<<0)
+#define BNX2_TBDR_CONFIG_SWAP_MODE (1L<<8)
+#define BNX2_TBDR_CONFIG_PRIORITY (1L<<9)
+#define BNX2_TBDR_CONFIG_CACHE_NEXT_PAGE_PTRS (1L<<10)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE (0xfL<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_256 (0L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_512 (1L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_1K (2L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_2K (3L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_4K (4L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_8K (5L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_16K (6L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_32K (7L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_64K (8L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_128K (9L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_256K (10L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_512K (11L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_1M (12L<<24)
+
+#define BNX2_TBDR_DEBUG_VECT_PEEK 0x0000500c
+#define BNX2_TBDR_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_TBDR_FTQ_DATA 0x000053c0
+#define BNX2_TBDR_FTQ_CMD 0x000053f8
+#define BNX2_TBDR_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_TBDR_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_TBDR_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_TBDR_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_TBDR_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_TBDR_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_TBDR_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_TBDR_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_TBDR_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_TBDR_FTQ_CMD_POP (1L<<30)
+#define BNX2_TBDR_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_TBDR_FTQ_CTL 0x000053fc
+#define BNX2_TBDR_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_TBDR_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_TBDR_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_TBDR_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_TBDR_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+
+
+/*
+ * tdma_reg definition
+ * offset: 0x5c00
+ */
+#define BNX2_TDMA_COMMAND 0x00005c00
+#define BNX2_TDMA_COMMAND_ENABLED (1L<<0)
+#define BNX2_TDMA_COMMAND_MASTER_ABORT (1L<<4)
+#define BNX2_TDMA_COMMAND_BAD_L2_LENGTH_ABORT (1L<<7)
+
+#define BNX2_TDMA_STATUS 0x00005c04
+#define BNX2_TDMA_STATUS_DMA_WAIT (1L<<0)
+#define BNX2_TDMA_STATUS_PAYLOAD_WAIT (1L<<1)
+#define BNX2_TDMA_STATUS_PATCH_FTQ_WAIT (1L<<2)
+#define BNX2_TDMA_STATUS_LOCK_WAIT (1L<<3)
+#define BNX2_TDMA_STATUS_FTQ_ENTRY_CNT (1L<<16)
+#define BNX2_TDMA_STATUS_BURST_CNT (1L<<17)
+
+#define BNX2_TDMA_CONFIG 0x00005c08
+#define BNX2_TDMA_CONFIG_ONE_DMA (1L<<0)
+#define BNX2_TDMA_CONFIG_ONE_RECORD (1L<<1)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ (0xfL<<4)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ_64 (0L<<4)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ_128 (0x4L<<4)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ_256 (0x6L<<4)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ_512 (0x8L<<4)
+#define BNX2_TDMA_CONFIG_LINE_SZ (0xfL<<8)
+#define BNX2_TDMA_CONFIG_LINE_SZ_64 (0L<<8)
+#define BNX2_TDMA_CONFIG_LINE_SZ_128 (4L<<8)
+#define BNX2_TDMA_CONFIG_LINE_SZ_256 (6L<<8)
+#define BNX2_TDMA_CONFIG_LINE_SZ_512 (8L<<8)
+#define BNX2_TDMA_CONFIG_ALIGN_ENA (1L<<15)
+#define BNX2_TDMA_CONFIG_CHK_L2_BD (1L<<16)
+#define BNX2_TDMA_CONFIG_FIFO_CMP (0xfL<<20)
+
+#define BNX2_TDMA_PAYLOAD_PROD 0x00005c0c
+#define BNX2_TDMA_PAYLOAD_PROD_VALUE (0x1fffL<<3)
+
+#define BNX2_TDMA_DBG_WATCHDOG 0x00005c10
+#define BNX2_TDMA_DBG_TRIGGER 0x00005c14
+#define BNX2_TDMA_DMAD_FSM 0x00005c80
+#define BNX2_TDMA_DMAD_FSM_BD_INVLD (1L<<0)
+#define BNX2_TDMA_DMAD_FSM_PUSH (0xfL<<4)
+#define BNX2_TDMA_DMAD_FSM_ARB_TBDC (0x3L<<8)
+#define BNX2_TDMA_DMAD_FSM_ARB_CTX (1L<<12)
+#define BNX2_TDMA_DMAD_FSM_DR_INTF (1L<<16)
+#define BNX2_TDMA_DMAD_FSM_DMAD (0x7L<<20)
+#define BNX2_TDMA_DMAD_FSM_BD (0xfL<<24)
+
+#define BNX2_TDMA_DMAD_STATUS 0x00005c84
+#define BNX2_TDMA_DMAD_STATUS_RHOLD_PUSH_ENTRY (0x3L<<0)
+#define BNX2_TDMA_DMAD_STATUS_RHOLD_DMAD_ENTRY (0x3L<<4)
+#define BNX2_TDMA_DMAD_STATUS_RHOLD_BD_ENTRY (0x3L<<8)
+#define BNX2_TDMA_DMAD_STATUS_IFTQ_ENUM (0xfL<<12)
+
+#define BNX2_TDMA_DR_INTF_FSM 0x00005c88
+#define BNX2_TDMA_DR_INTF_FSM_L2_COMP (0x3L<<0)
+#define BNX2_TDMA_DR_INTF_FSM_TPATQ (0x7L<<4)
+#define BNX2_TDMA_DR_INTF_FSM_TPBUF (0x3L<<8)
+#define BNX2_TDMA_DR_INTF_FSM_DR_BUF (0x7L<<12)
+#define BNX2_TDMA_DR_INTF_FSM_DMAD (0x7L<<16)
+
+#define BNX2_TDMA_DR_INTF_STATUS 0x00005c8c
+#define BNX2_TDMA_DR_INTF_STATUS_HOLE_PHASE (0x7L<<0)
+#define BNX2_TDMA_DR_INTF_STATUS_DATA_AVAIL (0x3L<<4)
+#define BNX2_TDMA_DR_INTF_STATUS_SHIFT_ADDR (0x7L<<8)
+#define BNX2_TDMA_DR_INTF_STATUS_NXT_PNTR (0xfL<<12)
+#define BNX2_TDMA_DR_INTF_STATUS_BYTE_COUNT (0x7L<<16)
+
+#define BNX2_TDMA_FTQ_DATA 0x00005fc0
+#define BNX2_TDMA_FTQ_CMD 0x00005ff8
+#define BNX2_TDMA_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_TDMA_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_TDMA_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_TDMA_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_TDMA_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_TDMA_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_TDMA_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_TDMA_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_TDMA_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_TDMA_FTQ_CMD_POP (1L<<30)
+#define BNX2_TDMA_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_TDMA_FTQ_CTL 0x00005ffc
+#define BNX2_TDMA_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_TDMA_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_TDMA_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_TDMA_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_TDMA_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+
+
+/*
+ * hc_reg definition
+ * offset: 0x6800
+ */
+#define BNX2_HC_COMMAND 0x00006800
+#define BNX2_HC_COMMAND_ENABLE (1L<<0)
+#define BNX2_HC_COMMAND_SKIP_ABORT (1L<<4)
+#define BNX2_HC_COMMAND_COAL_NOW (1L<<16)
+#define BNX2_HC_COMMAND_COAL_NOW_WO_INT (1L<<17)
+#define BNX2_HC_COMMAND_STATS_NOW (1L<<18)
+#define BNX2_HC_COMMAND_FORCE_INT (0x3L<<19)
+#define BNX2_HC_COMMAND_FORCE_INT_NULL (0L<<19)
+#define BNX2_HC_COMMAND_FORCE_INT_HIGH (1L<<19)
+#define BNX2_HC_COMMAND_FORCE_INT_LOW (2L<<19)
+#define BNX2_HC_COMMAND_FORCE_INT_FREE (3L<<19)
+#define BNX2_HC_COMMAND_CLR_STAT_NOW (1L<<21)
+
+#define BNX2_HC_STATUS 0x00006804
+#define BNX2_HC_STATUS_MASTER_ABORT (1L<<0)
+#define BNX2_HC_STATUS_PARITY_ERROR_STATE (1L<<1)
+#define BNX2_HC_STATUS_PCI_CLK_CNT_STAT (1L<<16)
+#define BNX2_HC_STATUS_CORE_CLK_CNT_STAT (1L<<17)
+#define BNX2_HC_STATUS_NUM_STATUS_BLOCKS_STAT (1L<<18)
+#define BNX2_HC_STATUS_NUM_INT_GEN_STAT (1L<<19)
+#define BNX2_HC_STATUS_NUM_INT_MBOX_WR_STAT (1L<<20)
+#define BNX2_HC_STATUS_CORE_CLKS_TO_HW_INTACK_STAT (1L<<23)
+#define BNX2_HC_STATUS_CORE_CLKS_TO_SW_INTACK_STAT (1L<<24)
+#define BNX2_HC_STATUS_CORE_CLKS_DURING_SW_INTACK_STAT (1L<<25)
+
+#define BNX2_HC_CONFIG 0x00006808
+#define BNX2_HC_CONFIG_COLLECT_STATS (1L<<0)
+#define BNX2_HC_CONFIG_RX_TMR_MODE (1L<<1)
+#define BNX2_HC_CONFIG_TX_TMR_MODE (1L<<2)
+#define BNX2_HC_CONFIG_COM_TMR_MODE (1L<<3)
+#define BNX2_HC_CONFIG_CMD_TMR_MODE (1L<<4)
+#define BNX2_HC_CONFIG_STATISTIC_PRIORITY (1L<<5)
+#define BNX2_HC_CONFIG_STATUS_PRIORITY (1L<<6)
+#define BNX2_HC_CONFIG_STAT_MEM_ADDR (0xffL<<8)
+
+#define BNX2_HC_ATTN_BITS_ENABLE 0x0000680c
+#define BNX2_HC_STATUS_ADDR_L 0x00006810
+#define BNX2_HC_STATUS_ADDR_H 0x00006814
+#define BNX2_HC_STATISTICS_ADDR_L 0x00006818
+#define BNX2_HC_STATISTICS_ADDR_H 0x0000681c
+#define BNX2_HC_TX_QUICK_CONS_TRIP 0x00006820
+#define BNX2_HC_TX_QUICK_CONS_TRIP_VALUE (0xffL<<0)
+#define BNX2_HC_TX_QUICK_CONS_TRIP_INT (0xffL<<16)
+
+#define BNX2_HC_COMP_PROD_TRIP 0x00006824
+#define BNX2_HC_COMP_PROD_TRIP_VALUE (0xffL<<0)
+#define BNX2_HC_COMP_PROD_TRIP_INT (0xffL<<16)
+
+#define BNX2_HC_RX_QUICK_CONS_TRIP 0x00006828
+#define BNX2_HC_RX_QUICK_CONS_TRIP_VALUE (0xffL<<0)
+#define BNX2_HC_RX_QUICK_CONS_TRIP_INT (0xffL<<16)
+
+#define BNX2_HC_RX_TICKS 0x0000682c
+#define BNX2_HC_RX_TICKS_VALUE (0x3ffL<<0)
+#define BNX2_HC_RX_TICKS_INT (0x3ffL<<16)
+
+#define BNX2_HC_TX_TICKS 0x00006830
+#define BNX2_HC_TX_TICKS_VALUE (0x3ffL<<0)
+#define BNX2_HC_TX_TICKS_INT (0x3ffL<<16)
+
+#define BNX2_HC_COM_TICKS 0x00006834
+#define BNX2_HC_COM_TICKS_VALUE (0x3ffL<<0)
+#define BNX2_HC_COM_TICKS_INT (0x3ffL<<16)
+
+#define BNX2_HC_CMD_TICKS 0x00006838
+#define BNX2_HC_CMD_TICKS_VALUE (0x3ffL<<0)
+#define BNX2_HC_CMD_TICKS_INT (0x3ffL<<16)
+
+#define BNX2_HC_PERIODIC_TICKS 0x0000683c
+#define BNX2_HC_PERIODIC_TICKS_HC_PERIODIC_TICKS (0xffffL<<0)
+
+#define BNX2_HC_STAT_COLLECT_TICKS 0x00006840
+#define BNX2_HC_STAT_COLLECT_TICKS_HC_STAT_COLL_TICKS (0xffL<<4)
+
+#define BNX2_HC_STATS_TICKS 0x00006844
+#define BNX2_HC_STATS_TICKS_HC_STAT_TICKS (0xffffL<<8)
+
+#define BNX2_HC_STAT_MEM_DATA 0x0000684c
+#define BNX2_HC_STAT_GEN_SEL_0 0x00006850
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0 (0x7fL<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT0 (0L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT1 (1L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT2 (2L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT3 (3L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT4 (4L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT5 (5L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT6 (6L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT7 (7L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT8 (8L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT9 (9L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT10 (10L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT11 (11L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT0 (12L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT1 (13L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT2 (14L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT3 (15L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT4 (16L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT5 (17L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT6 (18L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT7 (19L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT0 (20L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT1 (21L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT2 (22L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT3 (23L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT4 (24L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT5 (25L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT6 (26L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT7 (27L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT8 (28L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT9 (29L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT10 (30L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT11 (31L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT0 (32L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT1 (33L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT2 (34L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT3 (35L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT0 (36L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT1 (37L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT2 (38L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT3 (39L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT4 (40L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT5 (41L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT6 (42L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT7 (43L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT0 (44L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT1 (45L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT2 (46L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT3 (47L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT4 (48L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT5 (49L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT6 (50L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT7 (51L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_PCI_CLK_CNT (52L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CORE_CLK_CNT (53L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS (54L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN (55L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR (56L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK (59L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK (60L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK (61L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_CMD_CNT (62L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_SLOT_CNT (63L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_CMD_CNT (64L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_SLOT_CNT (65L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUPQ_VALID_CNT (66L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPQ_VALID_CNT (67L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPCQ_VALID_CNT (68L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PPQ_VALID_CNT (69L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PMQ_VALID_CNT (70L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PTQ_VALID_CNT (71L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMAQ_VALID_CNT (72L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCHQ_VALID_CNT (73L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDRQ_VALID_CNT (74L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXPQ_VALID_CNT (75L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMAQ_VALID_CNT (76L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPATQ_VALID_CNT (77L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TASQ_VALID_CNT (78L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSQ_VALID_CNT (79L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CPQ_VALID_CNT (80L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMXQ_VALID_CNT (81L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMTQ_VALID_CNT (82L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMQ_VALID_CNT (83L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MGMQ_VALID_CNT (84L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_TRANSFERS_CNT (85L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_DELAY_PCI_CLKS_CNT (86L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_TRANSFERS_CNT (87L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_DELAY_PCI_CLKS_CNT (88L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_RETRY_AFTER_DATA_CNT (89L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_TRANSFERS_CNT (90L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_DELAY_PCI_CLKS_CNT (91L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_TRANSFERS_CNT (92L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_DELAY_PCI_CLKS_CNT (93L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_RETRY_AFTER_DATA_CNT (94L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_WR_CNT64 (95L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_RD_CNT64 (96L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_ACC_STALL_CLKS (97L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_LOCK_STALL_CLKS (98L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS_STAT (99L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS64_STAT (100L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_PCI_STALL_STAT (101L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_FTQ_ENTRY_CNT (102L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_BURST_CNT (103L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_FTQ_ENTRY_CNT (104L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_BURST_CNT (105L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_FTQ_ENTRY_CNT (106L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_BURST_CNT (107L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUP_MATCH_CNT (108L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_POLL_PASS_CNT (109L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR1_CNT (110L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR2_CNT (111L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR3_CNT (112L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR4_CNT (113L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR5_CNT (114L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT0 (115L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT1 (116L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT2 (117L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT3 (118L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT4 (119L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT5 (120L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC1_MISS (121L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC2_MISS (122L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_BURST_CNT (127L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1 (0x7fL<<8)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2 (0x7fL<<16)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3 (0x7fL<<24)
+
+#define BNX2_HC_STAT_GEN_SEL_1 0x00006854
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4 (0x7fL<<0)
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5 (0x7fL<<8)
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6 (0x7fL<<16)
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7 (0x7fL<<24)
+
+#define BNX2_HC_STAT_GEN_SEL_2 0x00006858
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8 (0x7fL<<0)
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9 (0x7fL<<8)
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10 (0x7fL<<16)
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11 (0x7fL<<24)
+
+#define BNX2_HC_STAT_GEN_SEL_3 0x0000685c
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12 (0x7fL<<0)
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13 (0x7fL<<8)
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14 (0x7fL<<16)
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15 (0x7fL<<24)
+
+#define BNX2_HC_STAT_GEN_STAT0 0x00006888
+#define BNX2_HC_STAT_GEN_STAT1 0x0000688c
+#define BNX2_HC_STAT_GEN_STAT2 0x00006890
+#define BNX2_HC_STAT_GEN_STAT3 0x00006894
+#define BNX2_HC_STAT_GEN_STAT4 0x00006898
+#define BNX2_HC_STAT_GEN_STAT5 0x0000689c
+#define BNX2_HC_STAT_GEN_STAT6 0x000068a0
+#define BNX2_HC_STAT_GEN_STAT7 0x000068a4
+#define BNX2_HC_STAT_GEN_STAT8 0x000068a8
+#define BNX2_HC_STAT_GEN_STAT9 0x000068ac
+#define BNX2_HC_STAT_GEN_STAT10 0x000068b0
+#define BNX2_HC_STAT_GEN_STAT11 0x000068b4
+#define BNX2_HC_STAT_GEN_STAT12 0x000068b8
+#define BNX2_HC_STAT_GEN_STAT13 0x000068bc
+#define BNX2_HC_STAT_GEN_STAT14 0x000068c0
+#define BNX2_HC_STAT_GEN_STAT15 0x000068c4
+#define BNX2_HC_STAT_GEN_STAT_AC0 0x000068c8
+#define BNX2_HC_STAT_GEN_STAT_AC1 0x000068cc
+#define BNX2_HC_STAT_GEN_STAT_AC2 0x000068d0
+#define BNX2_HC_STAT_GEN_STAT_AC3 0x000068d4
+#define BNX2_HC_STAT_GEN_STAT_AC4 0x000068d8
+#define BNX2_HC_STAT_GEN_STAT_AC5 0x000068dc
+#define BNX2_HC_STAT_GEN_STAT_AC6 0x000068e0
+#define BNX2_HC_STAT_GEN_STAT_AC7 0x000068e4
+#define BNX2_HC_STAT_GEN_STAT_AC8 0x000068e8
+#define BNX2_HC_STAT_GEN_STAT_AC9 0x000068ec
+#define BNX2_HC_STAT_GEN_STAT_AC10 0x000068f0
+#define BNX2_HC_STAT_GEN_STAT_AC11 0x000068f4
+#define BNX2_HC_STAT_GEN_STAT_AC12 0x000068f8
+#define BNX2_HC_STAT_GEN_STAT_AC13 0x000068fc
+#define BNX2_HC_STAT_GEN_STAT_AC14 0x00006900
+#define BNX2_HC_STAT_GEN_STAT_AC15 0x00006904
+#define BNX2_HC_VIS 0x00006908
+#define BNX2_HC_VIS_STAT_BUILD_STATE (0xfL<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_IDLE (0L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_START (1L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_REQUEST (2L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE64 (3L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE32 (4L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE_DONE (5L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_DMA (6L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_CONTROL (7L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_LOW (8L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_HIGH (9L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_DATA (10L<<0)
+#define BNX2_HC_VIS_DMA_STAT_STATE (0xfL<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_IDLE (0L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_PARAM (1L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_DMA (2L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP (3L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_COMP (4L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_PARAM (5L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_DMA (6L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_1 (7L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_2 (8L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_WAIT (9L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_ABORT (15L<<8)
+#define BNX2_HC_VIS_DMA_MSI_STATE (0x7L<<12)
+#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE (0x3L<<15)
+#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_IDLE (0L<<15)
+#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_COUNT (1L<<15)
+#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_START (2L<<15)
+
+#define BNX2_HC_VIS_1 0x0000690c
+#define BNX2_HC_VIS_1_HW_INTACK_STATE (1L<<4)
+#define BNX2_HC_VIS_1_HW_INTACK_STATE_IDLE (0L<<4)
+#define BNX2_HC_VIS_1_HW_INTACK_STATE_COUNT (1L<<4)
+#define BNX2_HC_VIS_1_SW_INTACK_STATE (1L<<5)
+#define BNX2_HC_VIS_1_SW_INTACK_STATE_IDLE (0L<<5)
+#define BNX2_HC_VIS_1_SW_INTACK_STATE_COUNT (1L<<5)
+#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE (1L<<6)
+#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_IDLE (0L<<6)
+#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_COUNT (1L<<6)
+#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE (1L<<7)
+#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_IDLE (0L<<7)
+#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_COUNT (1L<<7)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE (0xfL<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_IDLE (0L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_DMA (1L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_UPDATE (2L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_ASSIGN (3L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_WAIT (4L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_UPDATE (5L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_ASSIGN (6L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_WAIT (7L<<17)
+#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE (0x3L<<21)
+#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_NORMAL (0L<<21)
+#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_CLEAR (1L<<21)
+#define BNX2_HC_VIS_1_INT_GEN_STATE (1L<<23)
+#define BNX2_HC_VIS_1_INT_GEN_STATE_DLE (0L<<23)
+#define BNX2_HC_VIS_1_INT_GEN_STATE_NTERRUPT (1L<<23)
+#define BNX2_HC_VIS_1_STAT_CHAN_ID (0x7L<<24)
+#define BNX2_HC_VIS_1_INT_B (1L<<27)
+
+#define BNX2_HC_DEBUG_VECT_PEEK 0x00006910
+#define BNX2_HC_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_HC_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_HC_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_HC_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_HC_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_HC_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+
+
+/*
+ * txp_reg definition
+ * offset: 0x40000
+ */
+#define BNX2_TXP_CPU_MODE 0x00045000
+#define BNX2_TXP_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_TXP_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_TXP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_TXP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_TXP_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_TXP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_TXP_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_TXP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_TXP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_TXP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_TXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_TXP_CPU_STATE 0x00045004
+#define BNX2_TXP_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_TXP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_TXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_TXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_TXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_TXP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_TXP_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_TXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_TXP_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_TXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_TXP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_TXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_TXP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_TXP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_TXP_CPU_EVENT_MASK 0x00045008
+#define BNX2_TXP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_TXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_TXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_TXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_TXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_TXP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_TXP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_TXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_TXP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_TXP_CPU_PROGRAM_COUNTER 0x0004501c
+#define BNX2_TXP_CPU_INSTRUCTION 0x00045020
+#define BNX2_TXP_CPU_DATA_ACCESS 0x00045024
+#define BNX2_TXP_CPU_INTERRUPT_ENABLE 0x00045028
+#define BNX2_TXP_CPU_INTERRUPT_VECTOR 0x0004502c
+#define BNX2_TXP_CPU_INTERRUPT_SAVED_PC 0x00045030
+#define BNX2_TXP_CPU_HW_BREAKPOINT 0x00045034
+#define BNX2_TXP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_TXP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK 0x00045038
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR 0x00045048
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_TXP_CPU_REG_FILE 0x00045200
+#define BNX2_TXP_FTQ_DATA 0x000453c0
+#define BNX2_TXP_FTQ_CMD 0x000453f8
+#define BNX2_TXP_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_TXP_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_TXP_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_TXP_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_TXP_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_TXP_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_TXP_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_TXP_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_TXP_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_TXP_FTQ_CMD_POP (1L<<30)
+#define BNX2_TXP_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_TXP_FTQ_CTL 0x000453fc
+#define BNX2_TXP_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_TXP_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_TXP_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_TXP_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_TXP_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_TXP_SCRATCH 0x00060000
+
+
+/*
+ * tpat_reg definition
+ * offset: 0x80000
+ */
+#define BNX2_TPAT_CPU_MODE 0x00085000
+#define BNX2_TPAT_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_TPAT_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_TPAT_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_TPAT_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_TPAT_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_TPAT_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_TPAT_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_TPAT_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_TPAT_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_TPAT_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_TPAT_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_TPAT_CPU_STATE 0x00085004
+#define BNX2_TPAT_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_TPAT_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_TPAT_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_TPAT_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_TPAT_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_TPAT_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_TPAT_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_TPAT_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_TPAT_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_TPAT_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_TPAT_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_TPAT_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_TPAT_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_TPAT_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_TPAT_CPU_EVENT_MASK 0x00085008
+#define BNX2_TPAT_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_TPAT_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_TPAT_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_TPAT_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_TPAT_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_TPAT_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_TPAT_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_TPAT_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_TPAT_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_TPAT_CPU_PROGRAM_COUNTER 0x0008501c
+#define BNX2_TPAT_CPU_INSTRUCTION 0x00085020
+#define BNX2_TPAT_CPU_DATA_ACCESS 0x00085024
+#define BNX2_TPAT_CPU_INTERRUPT_ENABLE 0x00085028
+#define BNX2_TPAT_CPU_INTERRUPT_VECTOR 0x0008502c
+#define BNX2_TPAT_CPU_INTERRUPT_SAVED_PC 0x00085030
+#define BNX2_TPAT_CPU_HW_BREAKPOINT 0x00085034
+#define BNX2_TPAT_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_TPAT_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK 0x00085038
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR 0x00085048
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_TPAT_CPU_REG_FILE 0x00085200
+#define BNX2_TPAT_FTQ_DATA 0x000853c0
+#define BNX2_TPAT_FTQ_CMD 0x000853f8
+#define BNX2_TPAT_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_TPAT_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_TPAT_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_TPAT_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_TPAT_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_TPAT_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_TPAT_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_TPAT_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_TPAT_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_TPAT_FTQ_CMD_POP (1L<<30)
+#define BNX2_TPAT_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_TPAT_FTQ_CTL 0x000853fc
+#define BNX2_TPAT_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_TPAT_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_TPAT_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_TPAT_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_TPAT_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_TPAT_SCRATCH 0x000a0000
+
+
+/*
+ * rxp_reg definition
+ * offset: 0xc0000
+ */
+#define BNX2_RXP_CPU_MODE 0x000c5000
+#define BNX2_RXP_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_RXP_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_RXP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_RXP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_RXP_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_RXP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_RXP_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_RXP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_RXP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_RXP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_RXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_RXP_CPU_STATE 0x000c5004
+#define BNX2_RXP_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_RXP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_RXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_RXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_RXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_RXP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_RXP_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_RXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_RXP_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_RXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_RXP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_RXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_RXP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_RXP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_RXP_CPU_EVENT_MASK 0x000c5008
+#define BNX2_RXP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_RXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_RXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_RXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_RXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_RXP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_RXP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_RXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_RXP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_RXP_CPU_PROGRAM_COUNTER 0x000c501c
+#define BNX2_RXP_CPU_INSTRUCTION 0x000c5020
+#define BNX2_RXP_CPU_DATA_ACCESS 0x000c5024
+#define BNX2_RXP_CPU_INTERRUPT_ENABLE 0x000c5028
+#define BNX2_RXP_CPU_INTERRUPT_VECTOR 0x000c502c
+#define BNX2_RXP_CPU_INTERRUPT_SAVED_PC 0x000c5030
+#define BNX2_RXP_CPU_HW_BREAKPOINT 0x000c5034
+#define BNX2_RXP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_RXP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK 0x000c5038
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR 0x000c5048
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_RXP_CPU_REG_FILE 0x000c5200
+#define BNX2_RXP_CFTQ_DATA 0x000c5380
+#define BNX2_RXP_CFTQ_CMD 0x000c53b8
+#define BNX2_RXP_CFTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RXP_CFTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RXP_CFTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RXP_CFTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RXP_CFTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RXP_CFTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RXP_CFTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RXP_CFTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RXP_CFTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RXP_CFTQ_CMD_POP (1L<<30)
+#define BNX2_RXP_CFTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RXP_CFTQ_CTL 0x000c53bc
+#define BNX2_RXP_CFTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RXP_CFTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RXP_CFTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RXP_CFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RXP_CFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_RXP_FTQ_DATA 0x000c53c0
+#define BNX2_RXP_FTQ_CMD 0x000c53f8
+#define BNX2_RXP_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RXP_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RXP_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RXP_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RXP_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RXP_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RXP_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RXP_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RXP_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RXP_FTQ_CMD_POP (1L<<30)
+#define BNX2_RXP_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RXP_FTQ_CTL 0x000c53fc
+#define BNX2_RXP_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RXP_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RXP_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RXP_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RXP_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_RXP_SCRATCH 0x000e0000
+
+
+/*
+ * com_reg definition
+ * offset: 0x100000
+ */
+#define BNX2_COM_CPU_MODE 0x00105000
+#define BNX2_COM_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_COM_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_COM_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_COM_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_COM_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_COM_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_COM_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_COM_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_COM_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_COM_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_COM_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_COM_CPU_STATE 0x00105004
+#define BNX2_COM_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_COM_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_COM_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_COM_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_COM_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_COM_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_COM_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_COM_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_COM_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_COM_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_COM_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_COM_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_COM_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_COM_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_COM_CPU_EVENT_MASK 0x00105008
+#define BNX2_COM_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_COM_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_COM_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_COM_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_COM_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_COM_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_COM_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_COM_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_COM_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_COM_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_COM_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_COM_CPU_PROGRAM_COUNTER 0x0010501c
+#define BNX2_COM_CPU_INSTRUCTION 0x00105020
+#define BNX2_COM_CPU_DATA_ACCESS 0x00105024
+#define BNX2_COM_CPU_INTERRUPT_ENABLE 0x00105028
+#define BNX2_COM_CPU_INTERRUPT_VECTOR 0x0010502c
+#define BNX2_COM_CPU_INTERRUPT_SAVED_PC 0x00105030
+#define BNX2_COM_CPU_HW_BREAKPOINT 0x00105034
+#define BNX2_COM_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_COM_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK 0x00105038
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR 0x00105048
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_COM_CPU_REG_FILE 0x00105200
+#define BNX2_COM_COMXQ_FTQ_DATA 0x00105340
+#define BNX2_COM_COMXQ_FTQ_CMD 0x00105378
+#define BNX2_COM_COMXQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_COM_COMXQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_COM_COMXQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_COM_COMXQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_COM_COMXQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_COM_COMXQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_COM_COMXQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_COM_COMXQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_COM_COMXQ_FTQ_CTL 0x0010537c
+#define BNX2_COM_COMXQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_COM_COMXQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_COM_COMXQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_COM_COMXQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_COM_COMXQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_COM_COMTQ_FTQ_DATA 0x00105380
+#define BNX2_COM_COMTQ_FTQ_CMD 0x001053b8
+#define BNX2_COM_COMTQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_COM_COMTQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_COM_COMTQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_COM_COMTQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_COM_COMTQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_COM_COMTQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_COM_COMTQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_COM_COMTQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_COM_COMTQ_FTQ_CTL 0x001053bc
+#define BNX2_COM_COMTQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_COM_COMTQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_COM_COMTQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_COM_COMTQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_COM_COMTQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_COM_COMQ_FTQ_DATA 0x001053c0
+#define BNX2_COM_COMQ_FTQ_CMD 0x001053f8
+#define BNX2_COM_COMQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_COM_COMQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_COM_COMQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_COM_COMQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_COM_COMQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_COM_COMQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_COM_COMQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_COM_COMQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_COM_COMQ_FTQ_CTL 0x001053fc
+#define BNX2_COM_COMQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_COM_COMQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_COM_COMQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_COM_COMQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_COM_COMQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_COM_SCRATCH 0x00120000
+
+
+/*
+ * cp_reg definition
+ * offset: 0x180000
+ */
+#define BNX2_CP_CPU_MODE 0x00185000
+#define BNX2_CP_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_CP_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_CP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_CP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_CP_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_CP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_CP_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_CP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_CP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_CP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_CP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_CP_CPU_STATE 0x00185004
+#define BNX2_CP_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_CP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_CP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_CP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_CP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_CP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_CP_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_CP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_CP_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_CP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_CP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_CP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_CP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_CP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_CP_CPU_EVENT_MASK 0x00185008
+#define BNX2_CP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_CP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_CP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_CP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_CP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_CP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_CP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_CP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_CP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_CP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_CP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_CP_CPU_PROGRAM_COUNTER 0x0018501c
+#define BNX2_CP_CPU_INSTRUCTION 0x00185020
+#define BNX2_CP_CPU_DATA_ACCESS 0x00185024
+#define BNX2_CP_CPU_INTERRUPT_ENABLE 0x00185028
+#define BNX2_CP_CPU_INTERRUPT_VECTOR 0x0018502c
+#define BNX2_CP_CPU_INTERRUPT_SAVED_PC 0x00185030
+#define BNX2_CP_CPU_HW_BREAKPOINT 0x00185034
+#define BNX2_CP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_CP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK 0x00185038
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR 0x00185048
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_CP_CPU_REG_FILE 0x00185200
+#define BNX2_CP_CPQ_FTQ_DATA 0x001853c0
+#define BNX2_CP_CPQ_FTQ_CMD 0x001853f8
+#define BNX2_CP_CPQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_CP_CPQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_CP_CPQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_CP_CPQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_CP_CPQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_CP_CPQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_CP_CPQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_CP_CPQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_CP_CPQ_FTQ_CTL 0x001853fc
+#define BNX2_CP_CPQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_CP_CPQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_CP_CPQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_CP_CPQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_CP_CPQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_CP_SCRATCH 0x001a0000
+
+
+/*
+ * mcp_reg definition
+ * offset: 0x140000
+ */
+#define BNX2_MCP_CPU_MODE 0x00145000
+#define BNX2_MCP_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_MCP_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_MCP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_MCP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_MCP_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_MCP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_MCP_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_MCP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_MCP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_MCP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_MCP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_MCP_CPU_STATE 0x00145004
+#define BNX2_MCP_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_MCP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_MCP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_MCP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_MCP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_MCP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_MCP_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_MCP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_MCP_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_MCP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_MCP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_MCP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_MCP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_MCP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_MCP_CPU_EVENT_MASK 0x00145008
+#define BNX2_MCP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_MCP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_MCP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_MCP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_MCP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_MCP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_MCP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_MCP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_MCP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_MCP_CPU_PROGRAM_COUNTER 0x0014501c
+#define BNX2_MCP_CPU_INSTRUCTION 0x00145020
+#define BNX2_MCP_CPU_DATA_ACCESS 0x00145024
+#define BNX2_MCP_CPU_INTERRUPT_ENABLE 0x00145028
+#define BNX2_MCP_CPU_INTERRUPT_VECTOR 0x0014502c
+#define BNX2_MCP_CPU_INTERRUPT_SAVED_PC 0x00145030
+#define BNX2_MCP_CPU_HW_BREAKPOINT 0x00145034
+#define BNX2_MCP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_MCP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK 0x00145038
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR 0x00145048
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_MCP_CPU_REG_FILE 0x00145200
+#define BNX2_MCP_MCPQ_FTQ_DATA 0x001453c0
+#define BNX2_MCP_MCPQ_FTQ_CMD 0x001453f8
+#define BNX2_MCP_MCPQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_MCP_MCPQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_MCP_MCPQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_MCP_MCPQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_MCP_MCPQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_MCP_MCPQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_MCP_MCPQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_MCP_MCPQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_MCP_MCPQ_FTQ_CTL 0x001453fc
+#define BNX2_MCP_MCPQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_MCP_MCPQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_MCP_MCPQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_MCP_MCPQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_MCP_MCPQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_MCP_ROM 0x00150000
+#define BNX2_MCP_SCRATCH 0x00160000
+
+#define BNX2_SHM_HDR_SIGNATURE BNX2_MCP_SCRATCH
+#define BNX2_SHM_HDR_SIGNATURE_SIG_MASK 0xffff0000
+#define BNX2_SHM_HDR_SIGNATURE_SIG 0x53530000
+#define BNX2_SHM_HDR_SIGNATURE_VER_MASK 0x000000ff
+#define BNX2_SHM_HDR_SIGNATURE_VER_ONE 0x00000001
+
+#define BNX2_SHM_HDR_ADDR_0 BNX2_MCP_SCRATCH + 4
+#define BNX2_SHM_HDR_ADDR_1 BNX2_MCP_SCRATCH + 8
+
+
+#define NUM_MC_HASH_REGISTERS 8
+
+
+/* PHY_ID1: bits 31-16; PHY_ID2: bits 15-0. */
+#define PHY_BCM5706_PHY_ID 0x00206160
+
+#define PHY_ID(id) ((id) & 0xfffffff0)
+#define PHY_REV_ID(id) ((id) & 0xf)
+
+/* 5708 Serdes PHY registers */
+
+#define BCM5708S_UP1 0xb
+
+#define BCM5708S_UP1_2G5 0x1
+
+#define BCM5708S_BLK_ADDR 0x1f
+
+#define BCM5708S_BLK_ADDR_DIG 0x0000
+#define BCM5708S_BLK_ADDR_DIG3 0x0002
+#define BCM5708S_BLK_ADDR_TX_MISC 0x0005
+
+/* Digital Block */
+#define BCM5708S_1000X_CTL1 0x10
+
+#define BCM5708S_1000X_CTL1_FIBER_MODE 0x0001
+#define BCM5708S_1000X_CTL1_AUTODET_EN 0x0010
+
+#define BCM5708S_1000X_CTL2 0x11
+
+#define BCM5708S_1000X_CTL2_PLLEL_DET_EN 0x0001
+
+#define BCM5708S_1000X_STAT1 0x14
+
+#define BCM5708S_1000X_STAT1_SGMII 0x0001
+#define BCM5708S_1000X_STAT1_LINK 0x0002
+#define BCM5708S_1000X_STAT1_FD 0x0004
+#define BCM5708S_1000X_STAT1_SPEED_MASK 0x0018
+#define BCM5708S_1000X_STAT1_SPEED_10 0x0000
+#define BCM5708S_1000X_STAT1_SPEED_100 0x0008
+#define BCM5708S_1000X_STAT1_SPEED_1G 0x0010
+#define BCM5708S_1000X_STAT1_SPEED_2G5 0x0018
+#define BCM5708S_1000X_STAT1_TX_PAUSE 0x0020
+#define BCM5708S_1000X_STAT1_RX_PAUSE 0x0040
+
+/* Digital3 Block */
+#define BCM5708S_DIG_3_0 0x10
+
+#define BCM5708S_DIG_3_0_USE_IEEE 0x0001
+
+/* Tx/Misc Block */
+#define BCM5708S_TX_ACTL1 0x15
+
+#define BCM5708S_TX_ACTL1_DRIVER_VCM 0x30
+
+#define BCM5708S_TX_ACTL3 0x17
+
+#define MIN_ETHERNET_PACKET_SIZE 60
+#define MAX_ETHERNET_PACKET_SIZE 1514
+#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014
+
+#define RX_COPY_THRESH 92
+
+#define DMA_READ_CHANS 5
+#define DMA_WRITE_CHANS 3
+
+#define BCM_PAGE_BITS 12
+#define BCM_PAGE_SIZE (1 << BCM_PAGE_BITS)
+
+#define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct tx_bd))
+#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
+
+#define MAX_RX_RINGS 4
+#define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct rx_bd))
+#define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
+#define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS)
+
+#define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \
+ (MAX_TX_DESC_CNT - 1)) ? \
+ (x) + 2 : (x) + 1
+
+#define PREV_TX_BD(x) ((((x)-1) & (MAX_TX_DESC_CNT)) == \
+ (MAX_TX_DESC_CNT)) ? \
+ (x) - 2 : (x) - 1
+
+#define TX_RING_IDX(x) ((x) & MAX_TX_DESC_CNT)
+
+#define NEXT_RX_BD(x) (((x) & (MAX_RX_DESC_CNT - 1)) == \
+ (MAX_RX_DESC_CNT - 1)) ? \
+ (x) + 2 : (x) + 1
+
+#define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
+
+//#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> 8)
+#define RX_IDX(x) ((x) & MAX_RX_DESC_CNT)
+
+/* Context size. */
+#define CTX_SHIFT 7
+#define CTX_SIZE (1 << CTX_SHIFT)
+#define CTX_MASK (CTX_SIZE - 1)
+#define GET_CID_ADDR(_cid) ((_cid) << CTX_SHIFT)
+#define GET_CID(_cid_addr) ((_cid_addr) >> CTX_SHIFT)
+
+#define PHY_CTX_SHIFT 6
+#define PHY_CTX_SIZE (1 << PHY_CTX_SHIFT)
+#define PHY_CTX_MASK (PHY_CTX_SIZE - 1)
+#define GET_PCID_ADDR(_pcid) ((_pcid) << PHY_CTX_SHIFT)
+#define GET_PCID(_pcid_addr) ((_pcid_addr) >> PHY_CTX_SHIFT)
+
+#define MB_KERNEL_CTX_SHIFT 8
+#define MB_KERNEL_CTX_SIZE (1 << MB_KERNEL_CTX_SHIFT)
+#define MB_KERNEL_CTX_MASK (MB_KERNEL_CTX_SIZE - 1)
+#define MB_GET_CID_ADDR(_cid) (0x10000 + ((_cid) << MB_KERNEL_CTX_SHIFT))
+
+#define MAX_CID_CNT 0x4000
+#define MAX_CID_ADDR (GET_CID_ADDR(MAX_CID_CNT))
+#define INVALID_CID_ADDR 0xffffffff
+
+#define TX_CID 16
+#define RX_CID 0
+
+#define MB_TX_CID_ADDR MB_GET_CID_ADDR(TX_CID)
+#define MB_RX_CID_ADDR MB_GET_CID_ADDR(RX_CID)
+
+#if 0
+struct sw_bd {
+ struct sk_buff *skb;
+ DECLARE_PCI_UNMAP_ADDR(mapping)
+};
+#endif
+
+/* Buffered flash (Atmel: AT45DB011B) specific information */
+#define SEEPROM_PAGE_BITS 2
+#define SEEPROM_PHY_PAGE_SIZE (1 << SEEPROM_PAGE_BITS)
+#define SEEPROM_BYTE_ADDR_MASK (SEEPROM_PHY_PAGE_SIZE-1)
+#define SEEPROM_PAGE_SIZE 4
+#define SEEPROM_TOTAL_SIZE 65536
+
+#define BUFFERED_FLASH_PAGE_BITS 9
+#define BUFFERED_FLASH_PHY_PAGE_SIZE (1 << BUFFERED_FLASH_PAGE_BITS)
+#define BUFFERED_FLASH_BYTE_ADDR_MASK (BUFFERED_FLASH_PHY_PAGE_SIZE-1)
+#define BUFFERED_FLASH_PAGE_SIZE 264
+#define BUFFERED_FLASH_TOTAL_SIZE 0x21000
+
+#define SAIFUN_FLASH_PAGE_BITS 8
+#define SAIFUN_FLASH_PHY_PAGE_SIZE (1 << SAIFUN_FLASH_PAGE_BITS)
+#define SAIFUN_FLASH_BYTE_ADDR_MASK (SAIFUN_FLASH_PHY_PAGE_SIZE-1)
+#define SAIFUN_FLASH_PAGE_SIZE 256
+#define SAIFUN_FLASH_BASE_TOTAL_SIZE 65536
+
+#define ST_MICRO_FLASH_PAGE_BITS 8
+#define ST_MICRO_FLASH_PHY_PAGE_SIZE (1 << ST_MICRO_FLASH_PAGE_BITS)
+#define ST_MICRO_FLASH_BYTE_ADDR_MASK (ST_MICRO_FLASH_PHY_PAGE_SIZE-1)
+#define ST_MICRO_FLASH_PAGE_SIZE 256
+#define ST_MICRO_FLASH_BASE_TOTAL_SIZE 65536
+
+#define NVRAM_TIMEOUT_COUNT 30000
+
+
+#define FLASH_STRAP_MASK (BNX2_NVM_CFG1_FLASH_MODE | \
+ BNX2_NVM_CFG1_BUFFER_MODE | \
+ BNX2_NVM_CFG1_PROTECT_MODE | \
+ BNX2_NVM_CFG1_FLASH_SIZE)
+
+#define FLASH_BACKUP_STRAP_MASK (0xf << 26)
+
+struct flash_spec {
+ u32 strapping;
+ u32 config1;
+ u32 config2;
+ u32 config3;
+ u32 write1;
+ u32 buffered;
+ u32 page_bits;
+ u32 page_size;
+ u32 addr_mask;
+ u32 total_size;
+ char *name;
+};
+
+struct bnx2 {
+ /* Fields used in the tx and intr/napi performance paths are grouped */
+ /* together in the beginning of the structure. */
+ void /*__iomem*/ *regview;
+
+ struct nic *nic;
+ struct pci_device *pdev;
+
+ /* atomic_t intr_sem; */
+
+ struct status_block *status_blk;
+ u32 last_status_idx;
+
+ u32 flags;
+#define PCIX_FLAG 1
+#define PCI_32BIT_FLAG 2
+#define ONE_TDMA_FLAG 4 /* no longer used */
+#define NO_WOL_FLAG 8
+#define USING_DAC_FLAG 0x10
+#define USING_MSI_FLAG 0x20
+#define ASF_ENABLE_FLAG 0x40
+
+ /* Put tx producer and consumer fields in separate cache lines. */
+ u32 tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES)));
+ u16 tx_prod;
+
+ struct tx_bd *tx_desc_ring;
+ struct sw_bd *tx_buf_ring;
+ int tx_ring_size;
+
+ u16 tx_cons __attribute__((aligned(L1_CACHE_BYTES)));
+ u16 hw_tx_cons;
+
+#ifdef BCM_VLAN
+ struct vlan_group *vlgrp;
+#endif
+
+ u32 rx_offset;
+ u32 rx_buf_use_size; /* useable size */
+ u32 rx_buf_size; /* with alignment */
+ u32 rx_max_ring_idx;
+
+ u32 rx_prod_bseq;
+ u16 rx_prod;
+ u16 rx_cons;
+ u16 hw_rx_cons;
+
+ u32 rx_csum;
+
+#if 0
+ struct rx_bd *rx_desc_ring[MAX_RX_RINGS];
+#endif
+ struct rx_bd *rx_desc_ring;
+
+ /* End of fields used in the performance code paths. */
+
+ char *name;
+
+#if 0
+ int timer_interval;
+ int current_interval;
+ struct timer_list timer;
+ struct work_struct reset_task;
+ int in_reset_task;
+
+ /* Used to synchronize phy accesses. */
+ spinlock_t phy_lock;
+#endif
+
+ u32 phy_flags;
+#define PHY_SERDES_FLAG 1
+#define PHY_CRC_FIX_FLAG 2
+#define PHY_PARALLEL_DETECT_FLAG 4
+#define PHY_2_5G_CAPABLE_FLAG 8
+#define PHY_INT_MODE_MASK_FLAG 0x300
+#define PHY_INT_MODE_AUTO_POLLING_FLAG 0x100
+#define PHY_INT_MODE_LINK_READY_FLAG 0x200
+
+ u32 chip_id;
+ /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
+#define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000)
+#define CHIP_NUM_5706 0x57060000
+#define CHIP_NUM_5708 0x57080000
+
+#define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000)
+#define CHIP_REV_Ax 0x00000000
+#define CHIP_REV_Bx 0x00001000
+#define CHIP_REV_Cx 0x00002000
+
+#define CHIP_METAL(bp) (((bp)->chip_id) & 0x00000ff0)
+#define CHIP_BONDING(bp) (((bp)->chip_id) & 0x0000000f)
+
+#define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0)
+#define CHIP_ID_5706_A0 0x57060000
+#define CHIP_ID_5706_A1 0x57060010
+#define CHIP_ID_5706_A2 0x57060020
+#define CHIP_ID_5708_A0 0x57080000
+#define CHIP_ID_5708_B0 0x57081000
+#define CHIP_ID_5708_B1 0x57081010
+
+#define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf)
+
+/* A serdes chip will have the first bit of the bond id set. */
+#define CHIP_BOND_ID_SERDES_BIT 0x01
+
+ u32 phy_addr;
+ u32 phy_id;
+
+ u16 bus_speed_mhz;
+ u8 wol;
+
+ u8 pad;
+
+ u16 fw_wr_seq;
+ u16 fw_drv_pulse_wr_seq;
+
+ dma_addr_t tx_desc_mapping;
+
+
+ int rx_max_ring;
+ int rx_ring_size;
+#if 0
+ dma_addr_t rx_desc_mapping[MAX_RX_RINGS];
+#endif
+ dma_addr_t rx_desc_mapping;
+
+ u16 tx_quick_cons_trip;
+ u16 tx_quick_cons_trip_int;
+ u16 rx_quick_cons_trip;
+ u16 rx_quick_cons_trip_int;
+ u16 comp_prod_trip;
+ u16 comp_prod_trip_int;
+ u16 tx_ticks;
+ u16 tx_ticks_int;
+ u16 com_ticks;
+ u16 com_ticks_int;
+ u16 cmd_ticks;
+ u16 cmd_ticks_int;
+ u16 rx_ticks;
+ u16 rx_ticks_int;
+
+ u32 stats_ticks;
+
+ dma_addr_t status_blk_mapping;
+
+ struct statistics_block *stats_blk;
+ dma_addr_t stats_blk_mapping;
+
+ u32 hc_cmd;
+ u32 rx_mode;
+
+ u16 req_line_speed;
+ u8 req_duplex;
+
+ u8 link_up;
+
+ u16 line_speed;
+ u8 duplex;
+ u8 flow_ctrl; /* actual flow ctrl settings */
+ /* may be different from */
+ /* req_flow_ctrl if autoneg */
+#define FLOW_CTRL_TX 1
+#define FLOW_CTRL_RX 2
+
+ u32 advertising;
+
+ u8 req_flow_ctrl; /* flow ctrl advertisement */
+ /* settings or forced */
+ /* settings */
+ u8 autoneg;
+#define AUTONEG_SPEED 1
+#define AUTONEG_FLOW_CTRL 2
+
+ u8 loopback;
+#define MAC_LOOPBACK 1
+#define PHY_LOOPBACK 2
+
+ u8 serdes_an_pending;
+#define SERDES_AN_TIMEOUT (HZ / 3)
+
+ u8 mac_addr[8];
+
+ u32 shmem_base;
+
+ u32 fw_ver;
+
+ int pm_cap;
+ int pcix_cap;
+
+ /* struct net_device_stats net_stats; */
+
+ struct flash_spec *flash_info;
+ u32 flash_size;
+
+ int status_stats_size;
+};
+
+static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
+static void bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val);
+
+#define REG_RD(bp, offset) \
+ readl(bp->regview + offset)
+
+#define REG_WR(bp, offset, val) \
+ writel(val, bp->regview + offset)
+
+#define REG_WR16(bp, offset, val) \
+ writew(val, bp->regview + offset)
+
+#define REG_RD_IND(bp, offset) \
+ bnx2_reg_rd_ind(bp, offset)
+
+#define REG_WR_IND(bp, offset, val) \
+ bnx2_reg_wr_ind(bp, offset, val)
+
+/* Indirect context access. Unlike the MBQ_WR, these macros will not
+ * trigger a chip event. */
+static void bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val);
+
+#define CTX_WR(bp, cid_addr, offset, val) \
+ bnx2_ctx_wr(bp, cid_addr, offset, val)
+
+struct cpu_reg {
+ u32 mode;
+ u32 mode_value_halt;
+ u32 mode_value_sstep;
+
+ u32 state;
+ u32 state_value_clear;
+
+ u32 gpr0;
+ u32 evmask;
+ u32 pc;
+ u32 inst;
+ u32 bp;
+
+ u32 spad_base;
+
+ u32 mips_view_base;
+};
+
+struct fw_info {
+ u32 ver_major;
+ u32 ver_minor;
+ u32 ver_fix;
+
+ u32 start_addr;
+
+ /* Text section. */
+ u32 text_addr;
+ u32 text_len;
+ u32 text_index;
+ u32 *text;
+
+ /* Data section. */
+ u32 data_addr;
+ u32 data_len;
+ u32 data_index;
+ u32 *data;
+
+ /* SBSS section. */
+ u32 sbss_addr;
+ u32 sbss_len;
+ u32 sbss_index;
+ u32 *sbss;
+
+ /* BSS section. */
+ u32 bss_addr;
+ u32 bss_len;
+ u32 bss_index;
+ u32 *bss;
+
+ /* Read-only section. */
+ u32 rodata_addr;
+ u32 rodata_len;
+ u32 rodata_index;
+ u32 *rodata;
+};
+
+#define RV2P_PROC1 0
+#define RV2P_PROC2 1
+
+
+/* This value (in milliseconds) determines the frequency of the driver
+ * issuing the PULSE message code. The firmware monitors this periodic
+ * pulse to determine when to switch to an OS-absent mode. */
+#define DRV_PULSE_PERIOD_MS 250
+
+/* This value (in milliseconds) determines how long the driver should
+ * wait for an acknowledgement from the firmware before timing out. Once
+ * the firmware has timed out, the driver will assume there is no firmware
+ * running and there won't be any firmware-driver synchronization during a
+ * driver reset. */
+#define FW_ACK_TIME_OUT_MS 100
+
+
+#define BNX2_DRV_RESET_SIGNATURE 0x00000000
+#define BNX2_DRV_RESET_SIGNATURE_MAGIC 0x4841564b /* HAVK */
+//#define DRV_RESET_SIGNATURE_MAGIC 0x47495352 /* RSIG */
+
+#define BNX2_DRV_MB 0x00000004
+#define BNX2_DRV_MSG_CODE 0xff000000
+#define BNX2_DRV_MSG_CODE_RESET 0x01000000
+#define BNX2_DRV_MSG_CODE_UNLOAD 0x02000000
+#define BNX2_DRV_MSG_CODE_SHUTDOWN 0x03000000
+#define BNX2_DRV_MSG_CODE_SUSPEND_WOL 0x04000000
+#define BNX2_DRV_MSG_CODE_FW_TIMEOUT 0x05000000
+#define BNX2_DRV_MSG_CODE_PULSE 0x06000000
+#define BNX2_DRV_MSG_CODE_DIAG 0x07000000
+#define BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL 0x09000000
+
+#define BNX2_DRV_MSG_DATA 0x00ff0000
+#define BNX2_DRV_MSG_DATA_WAIT0 0x00010000
+#define BNX2_DRV_MSG_DATA_WAIT1 0x00020000
+#define BNX2_DRV_MSG_DATA_WAIT2 0x00030000
+#define BNX2_DRV_MSG_DATA_WAIT3 0x00040000
+
+#define BNX2_DRV_MSG_SEQ 0x0000ffff
+
+#define BNX2_FW_MB 0x00000008
+#define BNX2_FW_MSG_ACK 0x0000ffff
+#define BNX2_FW_MSG_STATUS_MASK 0x00ff0000
+#define BNX2_FW_MSG_STATUS_OK 0x00000000
+#define BNX2_FW_MSG_STATUS_FAILURE 0x00ff0000
+
+#define BNX2_LINK_STATUS 0x0000000c
+#define BNX2_LINK_STATUS_INIT_VALUE 0xffffffff
+#define BNX2_LINK_STATUS_LINK_UP 0x1
+#define BNX2_LINK_STATUS_LINK_DOWN 0x0
+#define BNX2_LINK_STATUS_SPEED_MASK 0x1e
+#define BNX2_LINK_STATUS_AN_INCOMPLETE (0<<1)
+#define BNX2_LINK_STATUS_10HALF (1<<1)
+#define BNX2_LINK_STATUS_10FULL (2<<1)
+#define BNX2_LINK_STATUS_100HALF (3<<1)
+#define BNX2_LINK_STATUS_100BASE_T4 (4<<1)
+#define BNX2_LINK_STATUS_100FULL (5<<1)
+#define BNX2_LINK_STATUS_1000HALF (6<<1)
+#define BNX2_LINK_STATUS_1000FULL (7<<1)
+#define BNX2_LINK_STATUS_2500HALF (8<<1)
+#define BNX2_LINK_STATUS_2500FULL (9<<1)
+#define BNX2_LINK_STATUS_AN_ENABLED (1<<5)
+#define BNX2_LINK_STATUS_AN_COMPLETE (1<<6)
+#define BNX2_LINK_STATUS_PARALLEL_DET (1<<7)
+#define BNX2_LINK_STATUS_RESERVED (1<<8)
+#define BNX2_LINK_STATUS_PARTNER_AD_1000FULL (1<<9)
+#define BNX2_LINK_STATUS_PARTNER_AD_1000HALF (1<<10)
+#define BNX2_LINK_STATUS_PARTNER_AD_100BT4 (1<<11)
+#define BNX2_LINK_STATUS_PARTNER_AD_100FULL (1<<12)
+#define BNX2_LINK_STATUS_PARTNER_AD_100HALF (1<<13)
+#define BNX2_LINK_STATUS_PARTNER_AD_10FULL (1<<14)
+#define BNX2_LINK_STATUS_PARTNER_AD_10HALF (1<<15)
+#define BNX2_LINK_STATUS_TX_FC_ENABLED (1<<16)
+#define BNX2_LINK_STATUS_RX_FC_ENABLED (1<<17)
+#define BNX2_LINK_STATUS_PARTNER_SYM_PAUSE_CAP (1<<18)
+#define BNX2_LINK_STATUS_PARTNER_ASYM_PAUSE_CAP (1<<19)
+#define BNX2_LINK_STATUS_SERDES_LINK (1<<20)
+#define BNX2_LINK_STATUS_PARTNER_AD_2500FULL (1<<21)
+#define BNX2_LINK_STATUS_PARTNER_AD_2500HALF (1<<22)
+
+#define BNX2_DRV_PULSE_MB 0x00000010
+#define BNX2_DRV_PULSE_SEQ_MASK 0x00007fff
+
+/* Indicate to the firmware not to go into the
+ * OS absent when it is not getting driver pulse.
+ * This is used for debugging. */
+#define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00080000
+
+#define BNX2_DEV_INFO_SIGNATURE 0x00000020
+#define BNX2_DEV_INFO_SIGNATURE_MAGIC 0x44564900
+#define BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK 0xffffff00
+#define BNX2_DEV_INFO_FEATURE_CFG_VALID 0x01
+#define BNX2_DEV_INFO_SECONDARY_PORT 0x80
+#define BNX2_DEV_INFO_DRV_ALWAYS_ALIVE 0x40
+
+#define BNX2_SHARED_HW_CFG_PART_NUM 0x00000024
+
+#define BNX2_SHARED_HW_CFG_POWER_DISSIPATED 0x00000034
+#define BNX2_SHARED_HW_CFG_POWER_STATE_D3_MASK 0xff000000
+#define BNX2_SHARED_HW_CFG_POWER_STATE_D2_MASK 0xff0000
+#define BNX2_SHARED_HW_CFG_POWER_STATE_D1_MASK 0xff00
+#define BNX2_SHARED_HW_CFG_POWER_STATE_D0_MASK 0xff
+
+#define BNX2_SHARED_HW_CFG POWER_CONSUMED 0x00000038
+#define BNX2_SHARED_HW_CFG_CONFIG 0x0000003c
+#define BNX2_SHARED_HW_CFG_DESIGN_NIC 0
+#define BNX2_SHARED_HW_CFG_DESIGN_LOM 0x1
+#define BNX2_SHARED_HW_CFG_PHY_COPPER 0
+#define BNX2_SHARED_HW_CFG_PHY_FIBER 0x2
+#define BNX2_SHARED_HW_CFG_PHY_2_5G 0x20
+#define BNX2_SHARED_HW_CFG_PHY_BACKPLANE 0x40
+#define BNX2_SHARED_HW_CFG_LED_MODE_SHIFT_BITS 8
+#define BNX2_SHARED_HW_CFG_LED_MODE_MASK 0x300
+#define BNX2_SHARED_HW_CFG_LED_MODE_MAC 0
+#define BNX2_SHARED_HW_CFG_LED_MODE_GPHY1 0x100
+#define BNX2_SHARED_HW_CFG_LED_MODE_GPHY2 0x200
+
+#define BNX2_SHARED_HW_CFG_CONFIG2 0x00000040
+#define BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK 0x00fff000
+
+#define BNX2_DEV_INFO_BC_REV 0x0000004c
+
+#define BNX2_PORT_HW_CFG_MAC_UPPER 0x00000050
+#define BNX2_PORT_HW_CFG_UPPERMAC_MASK 0xffff
+
+#define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054
+#define BNX2_PORT_HW_CFG_CONFIG 0x00000058
+#define BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK 0x0000ffff
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK 0x001f0000
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_AN 0x00000000
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G 0x00030000
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_2_5G 0x00040000
+
+#define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER 0x00000068
+#define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER 0x0000006c
+#define BNX2_PORT_HW_CFG_IMD_MAC_B_UPPER 0x00000070
+#define BNX2_PORT_HW_CFG_IMD_MAC_B_LOWER 0x00000074
+#define BNX2_PORT_HW_CFG_ISCSI_MAC_UPPER 0x00000078
+#define BNX2_PORT_HW_CFG_ISCSI_MAC_LOWER 0x0000007c
+
+#define BNX2_DEV_INFO_PER_PORT_HW_CONFIG2 0x000000b4
+
+#define BNX2_DEV_INFO_FORMAT_REV 0x000000c4
+#define BNX2_DEV_INFO_FORMAT_REV_MASK 0xff000000
+#define BNX2_DEV_INFO_FORMAT_REV_ID ('A' << 24)
+
+#define BNX2_SHARED_FEATURE 0x000000c8
+#define BNX2_SHARED_FEATURE_MASK 0xffffffff
+
+#define BNX2_PORT_FEATURE 0x000000d8
+#define BNX2_PORT2_FEATURE 0x00000014c
+#define BNX2_PORT_FEATURE_WOL_ENABLED 0x01000000
+#define BNX2_PORT_FEATURE_MBA_ENABLED 0x02000000
+#define BNX2_PORT_FEATURE_ASF_ENABLED 0x04000000
+#define BNX2_PORT_FEATURE_IMD_ENABLED 0x08000000
+#define BNX2_PORT_FEATURE_BAR1_SIZE_MASK 0xf
+#define BNX2_PORT_FEATURE_BAR1_SIZE_DISABLED 0x0
+#define BNX2_PORT_FEATURE_BAR1_SIZE_64K 0x1
+#define BNX2_PORT_FEATURE_BAR1_SIZE_128K 0x2
+#define BNX2_PORT_FEATURE_BAR1_SIZE_256K 0x3
+#define BNX2_PORT_FEATURE_BAR1_SIZE_512K 0x4
+#define BNX2_PORT_FEATURE_BAR1_SIZE_1M 0x5
+#define BNX2_PORT_FEATURE_BAR1_SIZE_2M 0x6
+#define BNX2_PORT_FEATURE_BAR1_SIZE_4M 0x7
+#define BNX2_PORT_FEATURE_BAR1_SIZE_8M 0x8
+#define BNX2_PORT_FEATURE_BAR1_SIZE_16M 0x9
+#define BNX2_PORT_FEATURE_BAR1_SIZE_32M 0xa
+#define BNX2_PORT_FEATURE_BAR1_SIZE_64M 0xb
+#define BNX2_PORT_FEATURE_BAR1_SIZE_128M 0xc
+#define BNX2_PORT_FEATURE_BAR1_SIZE_256M 0xd
+#define BNX2_PORT_FEATURE_BAR1_SIZE_512M 0xe
+#define BNX2_PORT_FEATURE_BAR1_SIZE_1G 0xf
+
+#define BNX2_PORT_FEATURE_WOL 0xdc
+#define BNX2_PORT2_FEATURE_WOL 0x150
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_SHIFT_BITS 4
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_MASK 0x30
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_DISABLE 0
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC 0x10
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_ACPI 0x20
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI 0x30
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_MASK 0xf
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_AUTONEG 0
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10HALF 1
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10FULL 2
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100HALF 3
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100FULL 4
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000HALF 5
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000FULL 6
+#define BNX2_PORT_FEATURE_WOL_AUTONEG_ADVERTISE_1000 0x40
+#define BNX2_PORT_FEATURE_WOL_RESERVED_PAUSE_CAP 0x400
+#define BNX2_PORT_FEATURE_WOL_RESERVED_ASYM_PAUSE_CAP 0x800
+
+#define BNX2_PORT_FEATURE_MBA 0xe0
+#define BNX2_PORT2_FEATURE_MBA 0x154
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT_BITS 0
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK 0x3
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE 0
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL 1
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP 2
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_SHIFT_BITS 2
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_MASK 0x3c
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_AUTONEG 0
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10HALF 0x4
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10FULL 0x8
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100HALF 0xc
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100FULL 0x10
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000HALF 0x14
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000FULL 0x18
+#define BNX2_PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE 0x40
+#define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_S 0
+#define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_B 0x80
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT_BITS 8
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK 0xff00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED 0
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1K 0x100
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2K 0x200
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4K 0x300
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8K 0x400
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16K 0x500
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_32K 0x600
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_64K 0x700
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_128K 0x800
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_256K 0x900
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_512K 0xa00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1M 0xb00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2M 0xc00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4M 0xd00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8M 0xe00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16M 0xf00
+#define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT_BITS 16
+#define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_MASK 0xf0000
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT_BITS 20
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK 0x300000
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO 0
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS 0x100000
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H 0x200000
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H 0x300000
+
+#define BNX2_PORT_FEATURE_IMD 0xe4
+#define BNX2_PORT2_FEATURE_IMD 0x158
+#define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_DEFAULT 0
+#define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_ENABLE 1
+
+#define BNX2_PORT_FEATURE_VLAN 0xe8
+#define BNX2_PORT2_FEATURE_VLAN 0x15c
+#define BNX2_PORT_FEATURE_MBA_VLAN_TAG_MASK 0xffff
+#define BNX2_PORT_FEATURE_MBA_VLAN_ENABLE 0x10000
+
+#define BNX2_BC_STATE_RESET_TYPE 0x000001c0
+#define BNX2_BC_STATE_RESET_TYPE_SIG 0x00005254
+#define BNX2_BC_STATE_RESET_TYPE_SIG_MASK 0x0000ffff
+#define BNX2_BC_STATE_RESET_TYPE_NONE (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ 0x00010000)
+#define BNX2_BC_STATE_RESET_TYPE_PCI (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ 0x00020000)
+#define BNX2_BC_STATE_RESET_TYPE_VAUX (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ 0x00030000)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_MASK DRV_MSG_CODE
+#define BNX2_BC_STATE_RESET_TYPE_DRV_RESET (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_RESET)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_UNLOAD (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_UNLOAD)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_SHUTDOWN (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_SHUTDOWN)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_WOL (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_WOL)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_DIAG (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_DIAG)
+#define BNX2_BC_STATE_RESET_TYPE_VALUE(msg) (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ (msg))
+
+#define BNX2_BC_STATE 0x000001c4
+#define BNX2_BC_STATE_ERR_MASK 0x0000ff00
+#define BNX2_BC_STATE_SIGN 0x42530000
+#define BNX2_BC_STATE_SIGN_MASK 0xffff0000
+#define BNX2_BC_STATE_BC1_START (BNX2_BC_STATE_SIGN | 0x1)
+#define BNX2_BC_STATE_GET_NVM_CFG1 (BNX2_BC_STATE_SIGN | 0x2)
+#define BNX2_BC_STATE_PROG_BAR (BNX2_BC_STATE_SIGN | 0x3)
+#define BNX2_BC_STATE_INIT_VID (BNX2_BC_STATE_SIGN | 0x4)
+#define BNX2_BC_STATE_GET_NVM_CFG2 (BNX2_BC_STATE_SIGN | 0x5)
+#define BNX2_BC_STATE_APPLY_WKARND (BNX2_BC_STATE_SIGN | 0x6)
+#define BNX2_BC_STATE_LOAD_BC2 (BNX2_BC_STATE_SIGN | 0x7)
+#define BNX2_BC_STATE_GOING_BC2 (BNX2_BC_STATE_SIGN | 0x8)
+#define BNX2_BC_STATE_GOING_DIAG (BNX2_BC_STATE_SIGN | 0x9)
+#define BNX2_BC_STATE_RT_FINAL_INIT (BNX2_BC_STATE_SIGN | 0x81)
+#define BNX2_BC_STATE_RT_WKARND (BNX2_BC_STATE_SIGN | 0x82)
+#define BNX2_BC_STATE_RT_DRV_PULSE (BNX2_BC_STATE_SIGN | 0x83)
+#define BNX2_BC_STATE_RT_FIOEVTS (BNX2_BC_STATE_SIGN | 0x84)
+#define BNX2_BC_STATE_RT_DRV_CMD (BNX2_BC_STATE_SIGN | 0x85)
+#define BNX2_BC_STATE_RT_LOW_POWER (BNX2_BC_STATE_SIGN | 0x86)
+#define BNX2_BC_STATE_RT_SET_WOL (BNX2_BC_STATE_SIGN | 0x87)
+#define BNX2_BC_STATE_RT_OTHER_FW (BNX2_BC_STATE_SIGN | 0x88)
+#define BNX2_BC_STATE_RT_GOING_D3 (BNX2_BC_STATE_SIGN | 0x89)
+#define BNX2_BC_STATE_ERR_BAD_VERSION (BNX2_BC_STATE_SIGN | 0x0100)
+#define BNX2_BC_STATE_ERR_BAD_BC2_CRC (BNX2_BC_STATE_SIGN | 0x0200)
+#define BNX2_BC_STATE_ERR_BC1_LOOP (BNX2_BC_STATE_SIGN | 0x0300)
+#define BNX2_BC_STATE_ERR_UNKNOWN_CMD (BNX2_BC_STATE_SIGN | 0x0400)
+#define BNX2_BC_STATE_ERR_DRV_DEAD (BNX2_BC_STATE_SIGN | 0x0500)
+#define BNX2_BC_STATE_ERR_NO_RXP (BNX2_BC_STATE_SIGN | 0x0600)
+#define BNX2_BC_STATE_ERR_TOO_MANY_RBUF (BNX2_BC_STATE_SIGN | 0x0700)
+
+#define BNX2_BC_STATE_DEBUG_CMD 0x1dc
+#define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE 0x42440000
+#define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE_MASK 0xffff0000
+#define BNX2_BC_STATE_BC_DBG_CMD_LOOP_CNT_MASK 0xffff
+#define BNX2_BC_STATE_BC_DBG_CMD_LOOP_INFINITE 0xffff
+
+#define HOST_VIEW_SHMEM_BASE 0x167c00
+
+/* Enable or disable autonegotiation. If this is set to enable,
+ * the forced link modes above are completely ignored.
+ */
+#define AUTONEG_DISABLE 0x00
+#define AUTONEG_ENABLE 0x01
+
+#define RX_OFFSET (sizeof(struct l2_fhdr) + 2)
+
+#define RX_BUF_CNT 20
+
+/* 8 for CRC and VLAN */
+#define RX_BUF_USE_SIZE (ETH_MAX_MTU + ETH_HLEN + RX_OFFSET + 8)
+
+/* 8 for alignment */
+//#define RX_BUF_SIZE (RX_BUF_USE_SIZE + 8)
+#define RX_BUF_SIZE (L1_CACHE_ALIGN(RX_BUF_USE_SIZE + 8))
+
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/bnx2_fw.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/bnx2_fw.h
new file mode 100644
index 00000000..8158974c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/bnx2_fw.h
@@ -0,0 +1,3494 @@
+/* bnx2_fw.h: Broadcom NX2 network driver.
+ *
+ * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, except as noted below.
+ *
+ * This file contains firmware data derived from proprietary unpublished
+ * source code, Copyright (c) 2004, 2005 Broadcom Corporation.
+ *
+ * Permission is hereby granted for the distribution of this firmware data
+ * in hexadecimal or equivalent format, provided this copyright notice is
+ * accompanying it.
+ */
+
+static const int bnx2_COM_b06FwReleaseMajor = 0x1;
+static const int bnx2_COM_b06FwReleaseMinor = 0x0;
+static const int bnx2_COM_b06FwReleaseFix = 0x0;
+static const u32 bnx2_COM_b06FwStartAddr = 0x080008b4;
+static const u32 bnx2_COM_b06FwTextAddr = 0x08000000;
+static const int bnx2_COM_b06FwTextLen = 0x57bc;
+static const u32 bnx2_COM_b06FwDataAddr = 0x08005840;
+static const int bnx2_COM_b06FwDataLen = 0x0;
+static const u32 bnx2_COM_b06FwRodataAddr = 0x080057c0;
+static const int bnx2_COM_b06FwRodataLen = 0x58;
+static const u32 bnx2_COM_b06FwBssAddr = 0x08005860;
+static const int bnx2_COM_b06FwBssLen = 0x88;
+static const u32 bnx2_COM_b06FwSbssAddr = 0x08005840;
+static const int bnx2_COM_b06FwSbssLen = 0x1c;
+static u32 bnx2_COM_b06FwText[(0x57bc/4) + 1] = {
+ 0x0a00022d, 0x00000000, 0x00000000, 0x0000000d, 0x636f6d20, 0x322e352e,
+ 0x38000000, 0x02050802, 0x00000000, 0x00000003, 0x00000014, 0x00000032,
+ 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000010, 0x000003e8, 0x0000ea60, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000002, 0x00000020, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, 0x24425840,
+ 0x3c030800, 0x246358e8, 0xac400000, 0x0043202b, 0x1480fffd, 0x24420004,
+ 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x261008b4, 0x3c1c0800,
+ 0x279c5840, 0x0e0002f7, 0x00000000, 0x0000000d, 0x27bdffe8, 0x3c1a8000,
+ 0x3c020008, 0x0342d825, 0x3c036010, 0xafbf0010, 0x8c655000, 0x3c020800,
+ 0x24470f30, 0x3c040800, 0x24865860, 0x2402ff7f, 0x00a22824, 0x34a5380c,
+ 0xac655000, 0x00002821, 0x24020037, 0x24030c80, 0xaf420008, 0xaf430024,
+ 0xacc70000, 0x24a50001, 0x2ca20016, 0x1440fffc, 0x24c60004, 0x24845860,
+ 0x3c020800, 0x24420f3c, 0x3c030800, 0x24630e2c, 0xac820004, 0x3c020800,
+ 0x24420a2c, 0x3c050800, 0x24a51268, 0xac82000c, 0x3c020800, 0x244243dc,
+ 0xac830008, 0x3c030800, 0x24633698, 0xac820014, 0x3c020800, 0x24423c24,
+ 0xac830018, 0xac83001c, 0x3c030800, 0x24630f44, 0xac820024, 0x3c020800,
+ 0x244243ac, 0xac83002c, 0x3c030800, 0x246343cc, 0xac820030, 0x3c020800,
+ 0x244242f0, 0xac830034, 0x3c030800, 0x24633d78, 0xac82003c, 0x3c020800,
+ 0x24420fd4, 0xac850010, 0xac850020, 0xac830040, 0x0e0010b7, 0xac820050,
+ 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe0, 0xafb00010, 0x27500100,
+ 0xafbf0018, 0xafb10014, 0x9203000b, 0x24020003, 0x1462005b, 0x96110008,
+ 0x32220001, 0x10400009, 0x27430080, 0x8e020000, 0x96040014, 0x000211c2,
+ 0x00021040, 0x00621821, 0xa4640000, 0x0a0002d0, 0x3c020800, 0x3c020800,
+ 0x8c430020, 0x1060002a, 0x3c030800, 0x0e00148e, 0x00000000, 0x97420108,
+ 0x8f850018, 0x9743010c, 0x3042003e, 0x00021400, 0x00621825, 0xaca30000,
+ 0x8f840018, 0x8f420100, 0xac820004, 0x97430116, 0x9742010e, 0x8f840018,
+ 0x00031c00, 0x00431025, 0xac820008, 0x97430110, 0x97440112, 0x8f850018,
+ 0x00031c00, 0x00832025, 0xaca4000c, 0x97420114, 0x8f840018, 0x3042ffff,
+ 0xac820010, 0x8f830018, 0xac600014, 0x8f820018, 0x3c030800, 0xac400018,
+ 0x946258ce, 0x8f840018, 0x3c032000, 0x00431025, 0xac82001c, 0x0e0014cc,
+ 0x24040001, 0x3c030800, 0x8c620040, 0x24420001, 0xac620040, 0x3c020800,
+ 0x8c430044, 0x32240004, 0x24630001, 0x10800017, 0xac430044, 0x8f4202b8,
+ 0x04430007, 0x8e020020, 0x3c040800, 0x8c830060, 0x24020001, 0x24630001,
+ 0x0a0002f2, 0xac830060, 0x3c060800, 0x8cc4005c, 0xaf420280, 0x96030016,
+ 0x00001021, 0xa7430284, 0x8e050004, 0x24840001, 0x3c031000, 0xaf450288,
+ 0xaf4302b8, 0x0a0002f2, 0xacc4005c, 0x32220002, 0x0a0002f2, 0x0002102b,
+ 0x3c026000, 0xac400808, 0x0000000d, 0x00001021, 0x8fbf0018, 0x8fb10014,
+ 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffc8, 0xafbf0034, 0xafbe0030,
+ 0xafb7002c, 0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c, 0xafb20018,
+ 0xafb10014, 0x0e000244, 0xafb00010, 0x3c170800, 0x3c160800, 0x24110020,
+ 0x24150030, 0x2794000c, 0x27930008, 0x3c124000, 0x3c1e0800, 0x8f820004,
+ 0x3c040800, 0x8c830020, 0x10430005, 0x8ee200a4, 0xaf830004, 0x0e001593,
+ 0x00000000, 0x8ee200a4, 0x8ec300a0, 0x10430004, 0x26c400a0, 0x94820002,
+ 0xa742009e, 0xaee300a4, 0x8f500000, 0x32020007, 0x1040ffee, 0x32020001,
+ 0x1040002c, 0x32020002, 0x8f420100, 0xaf420020, 0x8f430104, 0xaf4300a8,
+ 0x9342010b, 0x93630000, 0x306300ff, 0x10710005, 0x304400ff, 0x10750006,
+ 0x2c820016, 0x0a000333, 0x00000000, 0xaf940000, 0x0a000334, 0x2c820016,
+ 0xaf930000, 0x0a000334, 0x00000000, 0xaf800000, 0x14400005, 0x00041880,
+ 0x0e0003cc, 0x00000000, 0x0a000340, 0x00000000, 0x3c020800, 0x24425860,
+ 0x00621821, 0x8c620000, 0x0040f809, 0x00000000, 0x10400005, 0x3c030800,
+ 0x8f420104, 0x3c016020, 0xac220014, 0x3c030800, 0x8c620034, 0xaf520138,
+ 0x24420001, 0xac620034, 0x32020002, 0x1040001a, 0x32020004, 0x8f420140,
+ 0xaf420020, 0x93630000, 0x306300ff, 0x10710005, 0x00000000, 0x10750006,
+ 0x00000000, 0x0a00035d, 0x00000000, 0xaf940000, 0x0a00035e, 0x00000000,
+ 0xaf930000, 0x0a00035e, 0x00000000, 0xaf800000, 0x0e000c7b, 0x00000000,
+ 0x3c040800, 0x8c820038, 0xaf520178, 0x24420001, 0xac820038, 0x32020004,
+ 0x1040ffa4, 0x00000000, 0x8f420180, 0xaf420020, 0x93630000, 0x306300ff,
+ 0x10710005, 0x00000000, 0x10750006, 0x00000000, 0x0a000378, 0x00000000,
+ 0xaf940000, 0x0a000379, 0x00000000, 0xaf930000, 0x0a000379, 0x00000000,
+ 0xaf800000, 0x8f430180, 0x24020f00, 0x14620005, 0x00000000, 0x8f420188,
+ 0xa742009c, 0x0a000387, 0x8fc2003c, 0x93620000, 0x14510004, 0x8fc2003c,
+ 0x0e000bad, 0x00000000, 0x8fc2003c, 0xaf5201b8, 0x24420001, 0x0a00030b,
+ 0xafc2003c, 0x27bdffe8, 0xafbf0010, 0x97420108, 0x24033000, 0x30447000,
+ 0x10830016, 0x28823001, 0x10400007, 0x24024000, 0x1080000b, 0x24022000,
+ 0x1082000c, 0x00000000, 0x0a0003b3, 0x00000000, 0x10820010, 0x24025000,
+ 0x10820012, 0x00000000, 0x0a0003b3, 0x00000000, 0x0000000d, 0x0a0003b5,
+ 0x00001021, 0x0e000442, 0x00000000, 0x0a0003b6, 0x8fbf0010, 0x0e00041a,
+ 0x00000000, 0x0a0003b5, 0x00001021, 0x0e000669, 0x00000000, 0x0a0003b5,
+ 0x00001021, 0x0e001467, 0x00000000, 0x0a0003b5, 0x00001021, 0x0000000d,
+ 0x00001021, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x93620000, 0x24030020,
+ 0x304400ff, 0x10830005, 0x24020030, 0x10820007, 0x00000000, 0x0a0003c9,
+ 0x00000000, 0x2782000c, 0xaf820000, 0x03e00008, 0x00000000, 0x27820008,
+ 0xaf820000, 0x03e00008, 0x00000000, 0xaf800000, 0x03e00008, 0x00000000,
+ 0x0000000d, 0x03e00008, 0x00001021, 0x03e00008, 0x00001021, 0x27440100,
+ 0x94830008, 0x30620004, 0x10400017, 0x30620002, 0x8f4202b8, 0x04430007,
+ 0x8c820020, 0x3c040800, 0x8c830060, 0x24020001, 0x24630001, 0x03e00008,
+ 0xac830060, 0xaf420280, 0x94830016, 0x3c060800, 0xa7430284, 0x8c850004,
+ 0x8cc4005c, 0x00001021, 0x3c031000, 0x24840001, 0xaf450288, 0xaf4302b8,
+ 0x03e00008, 0xacc4005c, 0x14400003, 0x3c040800, 0x03e00008, 0x00001021,
+ 0x8c830084, 0x24020001, 0x24630001, 0x03e00008, 0xac830084, 0x27450100,
+ 0x3c040800, 0x8c820088, 0x94a3000c, 0x24420001, 0x007a1821, 0xac820088,
+ 0x8ca40018, 0x90664000, 0xaf440038, 0x8ca2001c, 0x2403fff8, 0x00063600,
+ 0x00431024, 0x34420004, 0x3c030005, 0xaf42003c, 0xaf430030, 0x00000000,
+ 0x00000000, 0x00000000, 0xaf460404, 0x00000000, 0x00000000, 0x00000000,
+ 0x3c020006, 0x34420001, 0xaf420030, 0x00000000, 0x00000000, 0x00000000,
+ 0x8f420000, 0x30420010, 0x1040fffd, 0x00001021, 0x03e00008, 0x00000000,
+ 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x1060001e,
+ 0xafbf0014, 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020018, 0xac620000,
+ 0x8f840018, 0x9602000c, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018,
+ 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f840018,
+ 0x3c026000, 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce,
+ 0x8f850018, 0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c,
+ 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafb00010,
+ 0x27500100, 0xafbf0014, 0x92020009, 0x14400003, 0x3c020800, 0x0a00046c,
+ 0x24020001, 0x8c430020, 0x1060001f, 0x00001021, 0x0e00148e, 0x00000000,
+ 0x8f830018, 0x8e020018, 0xac620000, 0x8f840018, 0x9602000c, 0xac820004,
+ 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
+ 0x8f820018, 0xac400014, 0x8f840018, 0x3c026000, 0x8c434448, 0xac830018,
+ 0x96020008, 0x3c030800, 0x946458ce, 0x8f850018, 0x00021400, 0x00441025,
+ 0x24040001, 0x0e0014cc, 0xaca2001c, 0x00001021, 0x8fbf0014, 0x8fb00010,
+ 0x03e00008, 0x27bd0018, 0x3c0b0800, 0x8d6808b0, 0x3c070800, 0x24e700b0,
+ 0x00084900, 0x01271821, 0xac640000, 0x93620005, 0x97660008, 0x00e95021,
+ 0x93630023, 0x9364003f, 0x25080001, 0x00021600, 0x00063400, 0x00461025,
+ 0x00031a00, 0x00431025, 0x00822025, 0xad440004, 0x9362007e, 0x9366007f,
+ 0x8f630178, 0x9364007a, 0x00021600, 0x00063400, 0x00461025, 0x00031a00,
+ 0x00431025, 0x00822025, 0xad440008, 0x93620080, 0x9363007d, 0x3108007f,
+ 0x01403821, 0xad6808b0, 0x00021600, 0x00031c00, 0x00431025, 0x00451025,
+ 0x03e00008, 0xace2000c, 0x27bdffb8, 0xafb3002c, 0x00009821, 0xafbe0040,
+ 0x0000f021, 0xafb50034, 0x27550100, 0xafbf0044, 0xafb7003c, 0xafb60038,
+ 0xafb40030, 0xafb20028, 0xafb10024, 0xafb00020, 0xafa00010, 0xafa00014,
+ 0x96a20008, 0x8f540100, 0x8eb10018, 0x30420001, 0x10400037, 0x02a0b821,
+ 0x8f630054, 0x2622ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d,
+ 0x00000000, 0x2400015c, 0x0a0004e5, 0x00002021, 0x8f62004c, 0x02221023,
+ 0x18400028, 0x00002021, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c,
+ 0x308400ff, 0x24420001, 0x30a500ff, 0x00803821, 0x1485000b, 0xac62008c,
+ 0x3c040800, 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001,
+ 0x00021023, 0x30420005, 0x0a0004e5, 0x34440004, 0x27660100, 0x00041080,
+ 0x00c21021, 0x8c430000, 0x02231823, 0x04600004, 0x24820001, 0x30440007,
+ 0x1485fff9, 0x00041080, 0x10870007, 0x3c030800, 0xa3640121, 0x8c620094,
+ 0x24040005, 0x24420001, 0x0a0004e5, 0xac620094, 0x24040004, 0x00809821,
+ 0x9362003f, 0x304400ff, 0x38830016, 0x2c630001, 0x38820010, 0x2c420001,
+ 0x00621825, 0x1460000c, 0x24020001, 0x38830008, 0x2c630001, 0x38820014,
+ 0x2c420001, 0x00621825, 0x14600005, 0x24020001, 0x24020012, 0x14820002,
+ 0x00001021, 0x24020001, 0x10400009, 0x00000000, 0x8ea20020, 0x8f630040,
+ 0x0040b021, 0x00431023, 0x5c400010, 0x8f760040, 0x0a000511, 0x00000000,
+ 0x9343010b, 0x24020004, 0x1462000a, 0x8eb60020, 0x8f630040, 0x3c021000,
+ 0x00761823, 0x0043102a, 0x10400004, 0x00000000, 0x0000000d, 0x00000000,
+ 0x240002fa, 0x9343010b, 0x24020004, 0x5462000b, 0x96a20008, 0x24020001,
+ 0xafa20010, 0x96a20008, 0x24030001, 0xafa30018, 0x8eb2001c, 0x36730002,
+ 0x30420020, 0x0a000526, 0xafa20014, 0x36730080, 0x30420002, 0x10400003,
+ 0xafa00018, 0x0a000526, 0x8eb2001c, 0x8eb20014, 0x2402fffb, 0x02628024,
+ 0x1200002a, 0x3c030800, 0x8c620030, 0x02021024, 0x10400026, 0x3c020800,
+ 0x8c430020, 0x10600024, 0x32620004, 0x0e00148e, 0x00000000, 0x8f830018,
+ 0x8f420100, 0xac620000, 0x8f840018, 0x02401821, 0x32620002, 0xac900004,
+ 0x8f840018, 0x54400001, 0x02c01821, 0xac830008, 0x8f830018, 0x8ee20020,
+ 0xac62000c, 0x8f840018, 0x8f620040, 0xac820010, 0x8f830018, 0x8ee20018,
+ 0xac620014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800,
+ 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, 0x00621825, 0x0e0014cc,
+ 0xaca3001c, 0x32620004, 0x10400063, 0x00003821, 0x3c029000, 0x34420001,
+ 0x3c038000, 0x02821025, 0xa360007c, 0xaf420020, 0x8f420020, 0x00431024,
+ 0x1440fffd, 0x00000000, 0x93620023, 0x30420080, 0x10400011, 0x00000000,
+ 0x8f65005c, 0x8f63004c, 0x9764003c, 0x8f620064, 0x00a32823, 0x00852821,
+ 0x00a2102b, 0x54400006, 0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023,
+ 0xaf710064, 0x3c023fff, 0x0a000580, 0x3442ffff, 0x8f62005c, 0x02221023,
+ 0x04400011, 0x00000000, 0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff,
+ 0x3442ffff, 0xaf710064, 0x00a32823, 0x00852821, 0x0045102b, 0x10400004,
+ 0x02251021, 0x3c053fff, 0x34a5ffff, 0x02251021, 0xaf62005c, 0x24070001,
+ 0xaf71004c, 0x8f620054, 0x16220005, 0x00000000, 0x93620023, 0x30420040,
+ 0x10400017, 0x24020001, 0x9762006a, 0x00022880, 0x50a00001, 0x24050001,
+ 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804,
+ 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b,
+ 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021,
+ 0xaf62000c, 0x93620082, 0x30420080, 0x50400001, 0xa3600081, 0x3c028000,
+ 0x34420001, 0x02821025, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004,
+ 0x00000000, 0x0e0013c4, 0x00000000, 0x00403821, 0x54e00001, 0x241e0001,
+ 0x8f700040, 0x8f620040, 0x14520003, 0x00521023, 0x0a0005bf, 0x00001021,
+ 0x28420001, 0x10400041, 0x8fa20010, 0x0e000fae, 0x02402021, 0xaf720040,
+ 0x9362003e, 0x30420001, 0x1440000b, 0x3c029000, 0x93620022, 0x24420001,
+ 0xa3620022, 0x93630022, 0x3c020800, 0x8c440098, 0x0064182b, 0x14600027,
+ 0x3c020800, 0x3c029000, 0x34420001, 0x02821025, 0xaf420020, 0x3c038000,
+ 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000,
+ 0x34420001, 0xa362007d, 0x8f640074, 0x34630001, 0x02831825, 0xaf430020,
+ 0x04810006, 0x3c038000, 0x02802021, 0x0e000470, 0x24050273, 0x0a0005f2,
+ 0x24050001, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000,
+ 0xaf5401c0, 0xa34201c4, 0xaf4301f8, 0x24050001, 0x24020001, 0xa7620012,
+ 0xa3600022, 0x0a0005fe, 0x2ca20001, 0x9743007a, 0x9444002a, 0x00002821,
+ 0x00641821, 0x3063fffe, 0xa7630012, 0x2ca20001, 0x00021023, 0x03c2f024,
+ 0x8fa20010, 0x10400004, 0x8fa30014, 0x0e0013c1, 0x00000000, 0x8fa30014,
+ 0x10600003, 0x00000000, 0x0e0010eb, 0x00000000, 0x13c0001f, 0x3c029000,
+ 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
+ 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074,
+ 0x34630001, 0x02831825, 0xaf430020, 0x04810006, 0x3c038000, 0x02802021,
+ 0x0e000470, 0x2405036c, 0x0a00062b, 0x8fa20018, 0x8f4201f8, 0x00431024,
+ 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5401c0, 0xa34201c4, 0xaf4301f8,
+ 0x8fa20018, 0x5040002f, 0x96a20008, 0x8f620048, 0x8f630024, 0x00761821,
+ 0xaf630048, 0x9764003c, 0x00501023, 0x0044102b, 0x10400025, 0x3c029000,
+ 0x34420001, 0x3c040800, 0x8c830080, 0x8f450100, 0x3c068000, 0x24630001,
+ 0x00a21025, 0xac830080, 0xaf420020, 0x8f420020, 0x00461024, 0x1440fffd,
+ 0x00000000, 0x9362007d, 0x3c038000, 0x34420004, 0xa362007d, 0x8f640074,
+ 0x34630001, 0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021,
+ 0x0e000470, 0x2405038a, 0x0a00065b, 0x96a20008, 0x8f4201f8, 0x00431024,
+ 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8,
+ 0x96a20008, 0x8fbf0044, 0x8fbe0040, 0x8fb7003c, 0x8fb60038, 0x8fb50034,
+ 0x8fb40030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, 0x00021042,
+ 0x30420001, 0x03e00008, 0x27bd0048, 0x27bdffe0, 0xafbf0018, 0x97420108,
+ 0x24030019, 0x304400ff, 0x10830065, 0x2882001a, 0x1040001a, 0x2882000a,
+ 0x1040000f, 0x28820008, 0x10400040, 0x24020001, 0x1082003a, 0x28820002,
+ 0x50400005, 0x24020006, 0x10800032, 0x3c026000, 0x0a0006fb, 0x00000000,
+ 0x1082003d, 0x00000000, 0x0a0006fb, 0x00000000, 0x2402000b, 0x10820044,
+ 0x2882000b, 0x1440004b, 0x2402000e, 0x10820045, 0x00000000, 0x0a0006fb,
+ 0x00000000, 0x24020020, 0x10820062, 0x28820021, 0x1040000e, 0x2402001c,
+ 0x1082004c, 0x2882001d, 0x10400005, 0x2402001b, 0x10820043, 0x00000000,
+ 0x0a0006fb, 0x00000000, 0x2402001f, 0x10820050, 0x00000000, 0x0a0006fb,
+ 0x00000000, 0x240200c1, 0x10820042, 0x288200c2, 0x10400005, 0x24020080,
+ 0x10820021, 0x00000000, 0x0a0006fb, 0x00000000, 0x240200c2, 0x1082003d,
+ 0x240200c9, 0x50820049, 0xafa00010, 0x0a0006fb, 0x00000000, 0x0e001163,
+ 0xac400808, 0x0a0006fd, 0x8fbf0018, 0x3c026000, 0x8c444448, 0x3c030800,
+ 0xac640064, 0x0e001163, 0x00000000, 0x3c026000, 0x8c444448, 0x3c030800,
+ 0x0a0006fc, 0xac640068, 0x8f440100, 0x0e0006ff, 0x00000000, 0x3c026000,
+ 0x8c444448, 0x3c030800, 0x0a0006fc, 0xac64006c, 0x0e001191, 0x00000000,
+ 0x0a0006fd, 0x8fbf0018, 0x8f440100, 0x0e0011bb, 0x00000000, 0x0a0006fd,
+ 0x8fbf0018, 0x0e001202, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0000000d,
+ 0x0a0006fd, 0x8fbf0018, 0x0e000826, 0x00000000, 0x0a0006fd, 0x8fbf0018,
+ 0x8f440100, 0x0e001264, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e00134e,
+ 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e00087c, 0x27440100, 0x0a0006fd,
+ 0x8fbf0018, 0x8f640040, 0x0e000fae, 0x00000000, 0x0a0006fd, 0x8fbf0018,
+ 0x8f440100, 0x0e001059, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e001417,
+ 0x00000000, 0x0a0006fd, 0x8fbf0018, 0xafa00014, 0x8f440100, 0x8f450118,
+ 0x8f46011c, 0x0e001439, 0x8f470120, 0x0a0006fd, 0x8fbf0018, 0x0000000d,
+ 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010, 0x9742010c,
+ 0x1440005e, 0x00803821, 0x3c029000, 0x34420001, 0x00e21025, 0xaf420020,
+ 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023,
+ 0x30420010, 0x14400026, 0x3c030800, 0x8f630074, 0x3c027fff, 0x3442ffff,
+ 0x00621824, 0xaf630074, 0x93620005, 0x34420001, 0xa3620005, 0x8f63004c,
+ 0x8f620054, 0x10620021, 0x24040001, 0x9762006a, 0x00022880, 0x50a00001,
+ 0x24050001, 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821,
+ 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050,
+ 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824,
+ 0x00a21021, 0xaf62000c, 0x0a00073d, 0x24040001, 0x8c6200a8, 0x00002021,
+ 0x24420001, 0xac6200a8, 0x0000000d, 0x00000000, 0x2400044d, 0x3c028000,
+ 0x34420001, 0x00e21025, 0xaf420020, 0x1080001f, 0x3c029000, 0x34420001,
+ 0x00e21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001,
+ 0x00e31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00e02021, 0x0e000470,
+ 0x24050455, 0x0a000761, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd,
+ 0x24020002, 0x3c031000, 0xaf4701c0, 0xa34201c4, 0xaf4301f8, 0x0e001163,
+ 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffd8, 0xafbf0024,
+ 0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x93630005,
+ 0x00809821, 0x24020030, 0x30630030, 0x146200ac, 0x00a0a021, 0x3c020800,
+ 0x8c430020, 0x106000a6, 0x00000000, 0x0e00148e, 0x00000000, 0x8f830018,
+ 0xac730000, 0x936200c4, 0x30420002, 0x10400004, 0x24020001, 0x8f830018,
+ 0x0a000784, 0x00000000, 0x8f830018, 0x24020003, 0xac620004, 0x8f6200dc,
+ 0x8f630040, 0x00431023, 0x18400004, 0x00000000, 0x0000000d, 0x00000000,
+ 0x24000509, 0x8f840018, 0x8f6200dc, 0xac820008, 0x8f830018, 0xac60000c,
+ 0x8f820018, 0xac400010, 0x8f830018, 0x8f62004c, 0x3c100800, 0xac620014,
+ 0x8f850018, 0x3c026000, 0x8c434448, 0x261258c0, 0x00002021, 0xaca30018,
+ 0x9642000e, 0x8f850018, 0x3c034010, 0x00431025, 0x0e0014cc, 0xaca2001c,
+ 0x8f830018, 0xac730000, 0x9362003e, 0x9363003f, 0x8f840018, 0x00021200,
+ 0x00621825, 0xac830004, 0x93620081, 0x93630082, 0x8f840018, 0x00021600,
+ 0x00031c00, 0x00431025, 0xac820008, 0x8f830018, 0x8f620040, 0xac62000c,
+ 0x8f840018, 0x8f620048, 0xac820010, 0x8f71004c, 0x8f820018, 0xac510014,
+ 0x8f620050, 0x8f850018, 0x00401821, 0x02221023, 0x5c400001, 0x02201821,
+ 0x00002021, 0xaca30018, 0x9642000e, 0x8f850018, 0x3c03c00b, 0x00431025,
+ 0x0e0014cc, 0xaca2001c, 0x8f620054, 0x8f840018, 0x00401821, 0x02221023,
+ 0x5c400001, 0x02201821, 0xac830000, 0x8f840018, 0x8f630058, 0xac830004,
+ 0x93620023, 0x30420010, 0x10400004, 0x00000000, 0x8f830018, 0x0a0007dd,
+ 0x8f620148, 0x8f830018, 0x8f62005c, 0xac620008, 0x8f830018, 0x8f620060,
+ 0xac62000c, 0x8f840018, 0x8f620064, 0xac820010, 0x97630068, 0x9762006a,
+ 0x8f840018, 0x00031c00, 0x00431025, 0xac820014, 0x8f850018, 0x00002021,
+ 0x2402ffff, 0x260358c0, 0xaca20018, 0x9462000e, 0x8f850018, 0x3c03c00c,
+ 0x00431025, 0x0e0014cc, 0xaca2001c, 0x8f840018, 0x8f630018, 0xac830000,
+ 0x936200c4, 0x30420002, 0x10400006, 0x00000000, 0x976200c8, 0x8f830018,
+ 0x3042ffff, 0x0a000803, 0xac620004, 0x8f820018, 0xac400004, 0x8f830018,
+ 0x8f62006c, 0xac620008, 0x8f840018, 0x8f6200dc, 0xac82000c, 0x8f830018,
+ 0xac600010, 0x93620005, 0x8f830018, 0x00021600, 0x00541025, 0xac620014,
+ 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x260258c0, 0xaca30018,
+ 0x9443000e, 0x8f850018, 0x3c02400d, 0x00621825, 0x0e0014cc, 0xaca3001c,
+ 0x0e00122e, 0x02602021, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
+ 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0028, 0x27bdffe0, 0xafb00010,
+ 0x27500100, 0xafbf0018, 0xafb10014, 0x9603000c, 0x240200c1, 0x54620024,
+ 0x8e040000, 0x3c029000, 0x8f450100, 0x34420001, 0x3c038000, 0x00a21025,
+ 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d,
+ 0x3c038000, 0x34420004, 0xa362007d, 0x8f640074, 0x34630001, 0x00a31825,
+ 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, 0x0e000470, 0x240505b2,
+ 0x0a000878, 0x8fbf0018, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002,
+ 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, 0x0a000878, 0x8fbf0018,
+ 0x8f65004c, 0x24060001, 0x0e0012a3, 0x240705be, 0x3c020800, 0x8c430020,
+ 0x9611000c, 0x1060001d, 0x8e100000, 0x0e00148e, 0x00000000, 0x8f820018,
+ 0xac500000, 0x8f840018, 0x00111400, 0xac820004, 0x8f830018, 0xac600008,
+ 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f840018, 0x240205c1,
+ 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800,
+ 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024019, 0x00621825, 0x0e0014cc,
+ 0xaca3001c, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
+ 0x27bdffb0, 0xafb5003c, 0x0000a821, 0xafbe0048, 0x0000f021, 0xafb70044,
+ 0x0000b821, 0xafb30034, 0x00009821, 0xafb60040, 0x0080b021, 0xafbf004c,
+ 0xafb40038, 0xafb20030, 0xafb1002c, 0xafb00028, 0xafa00010, 0x8f620040,
+ 0x8ec30014, 0x96d1000c, 0x00431023, 0x04410025, 0x8ed40000, 0x32220401,
+ 0x1040030c, 0x3c029000, 0x34420001, 0x02821025, 0xaf420020, 0x3c038000,
+ 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000,
+ 0x34420004, 0xa362007d, 0x8f640074, 0x34630001, 0x02831825, 0xaf430020,
+ 0x04810006, 0x3c038000, 0x02802021, 0x0e000470, 0x24050664, 0x0a000ba2,
+ 0x8fbf004c, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000,
+ 0xaf5401c0, 0xa34201c4, 0xaf4301f8, 0x0a000ba2, 0x8fbf004c, 0x32220010,
+ 0x1040006b, 0x00003021, 0x9362003f, 0x92c6000f, 0x304500ff, 0x24c3fff8,
+ 0x2c62000f, 0x10400057, 0x3c020800, 0x244257c0, 0x00031880, 0x00621821,
+ 0x8c640000, 0x00800008, 0x00000000, 0x38a20012, 0x0a000924, 0x0002a82b,
+ 0x2402000e, 0x14a20004, 0x2402000c, 0x24150001, 0x0a000924, 0x24060010,
+ 0x10a20049, 0x38a30010, 0x2c630001, 0x38a20016, 0x2c420001, 0x00621825,
+ 0x1460004d, 0x0000a821, 0x24020014, 0x10a2004a, 0x00000000, 0x0000000d,
+ 0x00000000, 0x2400069c, 0x0a000924, 0x0000a821, 0x24020016, 0x14a20005,
+ 0x2402000c, 0x24150001, 0x24060010, 0x0a000924, 0x3231fffd, 0x10a20032,
+ 0x38a30010, 0x2c630001, 0x38a2000e, 0x2c420001, 0x00621825, 0x14600036,
+ 0x0000a821, 0x24020014, 0x14a20003, 0x24150001, 0x0a000924, 0x24060012,
+ 0x0000000d, 0x00000000, 0x240006bc, 0x0a000924, 0x0000a821, 0x2402000e,
+ 0x14a20004, 0x24020016, 0x24150001, 0x0a000924, 0x3231fffb, 0x14a20004,
+ 0x24020014, 0x24150001, 0x0a000924, 0x3231fffd, 0x54a20013, 0x92c2000e,
+ 0x24150001, 0x24060012, 0x0a000924, 0x3231fffd, 0x2402000c, 0x54a2000c,
+ 0x92c2000e, 0x92c3000e, 0x2402000a, 0x10620005, 0x24150001, 0x0000000d,
+ 0x00000000, 0x240006e8, 0x24150001, 0x0a000924, 0x24060014, 0x92c2000e,
+ 0x14a20003, 0x00000000, 0x0a000924, 0x24150001, 0x10a6ffc1, 0x24020012,
+ 0x10a20005, 0x0000a821, 0x0000000d, 0x00000000, 0x24000704, 0x0000a821,
+ 0x12a00022, 0x32220004, 0x10400002, 0x24020001, 0xafa20010, 0x32230102,
+ 0x24020002, 0x1462000f, 0x00000000, 0x92c2000a, 0x30420020, 0x1440000b,
+ 0x00000000, 0x8f630048, 0x8f620040, 0x14620004, 0x00000000, 0x8f620048,
+ 0x24420001, 0xaf620048, 0x8f620040, 0x24420001, 0xaf620040, 0xa366003f,
+ 0x38c30012, 0x2c630001, 0x38c20010, 0x2c420001, 0x00621825, 0x10600005,
+ 0x3c030800, 0x8c620074, 0x24420001, 0x0e00140d, 0xac620074, 0x32220040,
+ 0x32230020, 0xafa30020, 0x32230080, 0xafa30024, 0x32230001, 0xafa30018,
+ 0x32230008, 0xafa3001c, 0x32230100, 0x104000c4, 0xafa30014, 0x8ec60010,
+ 0x8f630054, 0x24c2ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d,
+ 0x00000000, 0x2400015c, 0x0a000989, 0x00009021, 0x8f62004c, 0x00c21023,
+ 0x18400028, 0x00009021, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c,
+ 0x308400ff, 0x24420001, 0x30a500ff, 0x00804021, 0x1485000b, 0xac62008c,
+ 0x3c040800, 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001,
+ 0x00021023, 0x30420005, 0x0a000989, 0x34520004, 0x27670100, 0x00041080,
+ 0x00e21021, 0x8c430000, 0x00c31823, 0x04600004, 0x24820001, 0x30440007,
+ 0x1485fff9, 0x00041080, 0x10880007, 0x3c030800, 0xa3640121, 0x8c620094,
+ 0x24120005, 0x24420001, 0x0a000989, 0xac620094, 0x24120004, 0x32420001,
+ 0x10400021, 0x3c020800, 0x8c430020, 0x8ed00000, 0x1060001c, 0x8ed30010,
+ 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001,
+ 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
+ 0xac600010, 0x8f820018, 0xac530014, 0x8f850018, 0x3c026000, 0x8c434448,
+ 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010,
+ 0x00621825, 0x0e0014cc, 0xaca3001c, 0x24130001, 0x32420004, 0x10400068,
+ 0x00003821, 0x3c029000, 0x8ec60010, 0x34420001, 0x3c038000, 0x02821025,
+ 0xa360007c, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000,
+ 0x93620023, 0x30420080, 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c,
+ 0x9764003c, 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006,
+ 0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023, 0xaf660064, 0x3c023fff,
+ 0x0a0009da, 0x3442ffff, 0x8f62005c, 0x00c21023, 0x04400011, 0x00000000,
+ 0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf660064,
+ 0x00a32823, 0x00852821, 0x0045102b, 0x10400004, 0x00c51021, 0x3c053fff,
+ 0x34a5ffff, 0x00c51021, 0xaf62005c, 0x24070001, 0xaf66004c, 0x8fa20010,
+ 0x10400003, 0x00000000, 0xaf660050, 0xaf660054, 0x8f620054, 0x14c20005,
+ 0x00000000, 0x93620023, 0x30420040, 0x10400017, 0x24020001, 0x9762006a,
+ 0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800,
+ 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021,
+ 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074,
+ 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x93620082, 0x30420080,
+ 0x50400001, 0xa3600081, 0x3c028000, 0x34420001, 0x02821025, 0xaf420020,
+ 0x9363007e, 0x9362007a, 0x10620005, 0x00e0b821, 0x0e0013c4, 0x00000000,
+ 0x00403821, 0x00e0b821, 0x8fa30020, 0x10600009, 0x8fa20010, 0x8ec20018,
+ 0xaf620018, 0x8ec3001c, 0xaf63001c, 0x8ec20020, 0x24170001, 0xaf620058,
+ 0x8fa20010, 0x10400057, 0x8fa30024, 0x93620023, 0x30420040, 0x10400053,
+ 0x00000000, 0x16600021, 0x3c120800, 0x8e420020, 0x8f70004c, 0x1040001e,
+ 0x24130001, 0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018,
+ 0x24020001, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c,
+ 0x8f830018, 0xac600010, 0x8f820018, 0xac500014, 0x8f850018, 0x3c026000,
+ 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
+ 0x3c024010, 0x00621825, 0xaca3001c, 0x0e0014cc, 0x24130001, 0x8e420020,
+ 0x1040001c, 0x8ed00000, 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000,
+ 0x8f830018, 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c,
+ 0x8f820018, 0xac400010, 0x8f830018, 0x24020798, 0xac620014, 0x8f850018,
+ 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce,
+ 0x8f850018, 0x3c024019, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000,
+ 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
+ 0x1440fffd, 0x24020001, 0xaf62000c, 0x93630023, 0x3c028000, 0x34420001,
+ 0x02821025, 0x306300bf, 0xa3630023, 0xaf420020, 0x8fa30024, 0x10600012,
+ 0x8fa30018, 0x9362007c, 0x24420001, 0xa362007c, 0x9363007e, 0x9362007a,
+ 0x1462000b, 0x8fa30018, 0x9362007c, 0x3c030800, 0x8c640024, 0x0044102b,
+ 0x14400005, 0x8fa30018, 0x0e0013c4, 0x00000000, 0x02e2b825, 0x8fa30018,
+ 0x3062ffff, 0x10400003, 0x32220200, 0x0a000a94, 0x241e0004, 0x10400003,
+ 0x00000000, 0x241e0040, 0x24170001, 0x12a000d0, 0x32220002, 0x104000cf,
+ 0x8fa2001c, 0x92c2000a, 0x30420002, 0x5040003b, 0x92c2000a, 0x93620023,
+ 0x30420008, 0x54400037, 0x92c2000a, 0x3c020800, 0x8c430020, 0x10600023,
+ 0x3c029000, 0x0e00148e, 0x00000000, 0x8f840018, 0x8ec30000, 0xac830000,
+ 0x92c2000a, 0x8f830018, 0x00021600, 0xac620004, 0x8f840018, 0x8f620040,
+ 0xac820008, 0x8f850018, 0x8f63004c, 0xaca3000c, 0x9362003f, 0x8f840018,
+ 0x304200ff, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f850018,
+ 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
+ 0x3c02401a, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001,
+ 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x34630008,
+ 0xa3630023, 0xaf420020, 0x92c2000a, 0x30420020, 0x1040008e, 0x8fa2001c,
+ 0x93620023, 0x30420001, 0x14400035, 0x3c020800, 0x8c430020, 0x10600023,
+ 0x3c029000, 0x0e00148e, 0x00000000, 0x8f840018, 0x8ec30000, 0xac830000,
+ 0x92c2000a, 0x8f830018, 0x00021600, 0xac620004, 0x8f840018, 0x8f620040,
+ 0xac820008, 0x8f850018, 0x8f63004c, 0xaca3000c, 0x9362003f, 0x8f840018,
+ 0x304200ff, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f850018,
+ 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
+ 0x3c02401a, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001,
+ 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x34630001,
+ 0xa3630023, 0xaf420020, 0x93620023, 0x30420040, 0x10400052, 0x8fa2001c,
+ 0x16600020, 0x3c120800, 0x8e420020, 0x8f70004c, 0x1040003c, 0x3c029000,
+ 0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018, 0x24020001,
+ 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
+ 0xac600010, 0x8f820018, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448,
+ 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010,
+ 0x00621825, 0x0e0014cc, 0xaca3001c, 0x8e420020, 0x1040001e, 0x3c029000,
+ 0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018, 0x3c02008d,
+ 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
+ 0xac600010, 0x8f840018, 0x240207ee, 0xac820014, 0x8f850018, 0x3c026000,
+ 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
+ 0x3c024019, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001,
+ 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x306300bf,
+ 0xa3630023, 0xaf420020, 0x8fa2001c, 0x1040000e, 0x8fa20014, 0x92c2000a,
+ 0xa3620082, 0x57c00005, 0x37de0008, 0x8fa30014, 0x10600004, 0x00000000,
+ 0x37de0008, 0x0a000b75, 0x24170001, 0x0e0012cf, 0x02802021, 0x8fa20014,
+ 0x10400003, 0x00000000, 0x37de0010, 0x24170001, 0x12e00020, 0x3c029000,
+ 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
+ 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x03c21025, 0xa362007d,
+ 0x8f640074, 0x34630001, 0x02831825, 0xaf430020, 0x04810006, 0x3c038000,
+ 0x02802021, 0x0e000470, 0x2405082a, 0x0a000b9b, 0x00000000, 0x8f4201f8,
+ 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5401c0, 0xa34201c4,
+ 0xaf4301f8, 0x9363003f, 0x24020012, 0x14620004, 0x8fbf004c, 0x0e00140d,
+ 0x00000000, 0x8fbf004c, 0x8fbe0048, 0x8fb70044, 0x8fb60040, 0x8fb5003c,
+ 0x8fb40038, 0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x03e00008,
+ 0x27bd0050, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f500180, 0x97420184,
+ 0x30420200, 0x14400015, 0x00000000, 0x8f430188, 0x3c02ff00, 0x00621824,
+ 0x3c020200, 0x10620031, 0x0043102b, 0x14400007, 0x3c020300, 0x1060000b,
+ 0x3c020100, 0x1062000d, 0x00000000, 0x0a000c2c, 0x00000000, 0x10620027,
+ 0x3c020400, 0x1062003e, 0x02002021, 0x0a000c2c, 0x00000000, 0x0e000c31,
+ 0x02002021, 0x0a000c2e, 0x8fbf0014, 0x93620005, 0x30420020, 0x1440005e,
+ 0x8fbf0014, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000,
+ 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000,
+ 0x34630001, 0x02031825, 0x34420020, 0xa3620005, 0xaf430020, 0x93620005,
+ 0x30420020, 0x14400003, 0x02002021, 0x0000000d, 0x02002021, 0x0e000766,
+ 0x24055854, 0x0a000c2e, 0x8fbf0014, 0x93620005, 0x30420001, 0x1040003f,
+ 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000, 0x8f420020,
+ 0x00431024, 0x1440fffd, 0x00000000, 0x93620023, 0x34420004, 0xa3620023,
+ 0x93630005, 0x3c048000, 0x3c020800, 0x306300fe, 0xa3630005, 0x8c430020,
+ 0x34840001, 0x02042025, 0x0a000c0a, 0xaf440020, 0x00002821, 0x00003021,
+ 0x0e000fb1, 0x240708d9, 0x3c020800, 0x8c430020, 0x10600023, 0x8fbf0014,
+ 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x93630082, 0x9362003f,
+ 0x8f840018, 0x00031a00, 0x00431025, 0xac820004, 0x8f830018, 0xac600008,
+ 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014,
+ 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018,
+ 0x944358ce, 0x8f850018, 0x3c02400a, 0x00621825, 0x0e0014cc, 0xaca3001c,
+ 0x0a000c2e, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010, 0x03e00008,
+ 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x8f420188, 0x00803021, 0x93640000,
+ 0x24030020, 0x00021402, 0x10830008, 0x304500ff, 0x3c036018, 0x8c625000,
+ 0x34420400, 0xac625000, 0x0000000d, 0x00000000, 0x24000955, 0x9363003f,
+ 0x24020012, 0x14620023, 0x3c029000, 0x34420001, 0x3c038000, 0x00c21025,
+ 0xaf650178, 0xa365007a, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001,
+ 0x00c31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00c02021, 0x0e000470,
+ 0x24050963, 0x0a000c79, 0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd,
+ 0x24020002, 0x3c031000, 0xaf4601c0, 0xa34201c4, 0xaf4301f8, 0x0a000c79,
+ 0x8fbf0010, 0x9362007e, 0x1445000e, 0x00000000, 0x8f620178, 0x1045000b,
+ 0x00000000, 0x8f820000, 0xaf650178, 0x8f660178, 0x8f440180, 0x8f65004c,
+ 0x8c430000, 0x0060f809, 0x30c600ff, 0x0a000c79, 0x8fbf0010, 0xaf650178,
+ 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x93630000,
+ 0x24020020, 0x10620005, 0x00000000, 0x93630000, 0x24020030, 0x1462004d,
+ 0x8fbf0010, 0x93420148, 0x2444ffff, 0x2c830005, 0x10600047, 0x3c020800,
+ 0x24425800, 0x00041880, 0x00621821, 0x8c640000, 0x00800008, 0x00000000,
+ 0x8f430144, 0x8f62000c, 0x14620006, 0x24020001, 0xaf62000c, 0x0e000d59,
+ 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x8f62000c, 0x0a000cca, 0x00000000,
+ 0x97630010, 0x8f420144, 0x14430006, 0x24020001, 0xa7620010, 0x0e00137a,
+ 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620010, 0x0a000cca, 0x00000000,
+ 0x97630012, 0x8f420144, 0x14430006, 0x24020001, 0xa7620012, 0x0e001395,
+ 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620012, 0x0a000cca, 0x00000000,
+ 0x97630014, 0x8f420144, 0x14430006, 0x24020001, 0xa7620014, 0x0e0013bb,
+ 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620014, 0x0a000cca, 0x00000000,
+ 0x97630016, 0x8f420144, 0x14430006, 0x24020001, 0xa7620016, 0x0e0013be,
+ 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620016, 0x14400006, 0x8fbf0010,
+ 0x3c030800, 0x8c620070, 0x24420001, 0xac620070, 0x8fbf0010, 0x03e00008,
+ 0x27bd0018, 0x27bdffe0, 0x3c029000, 0xafbf001c, 0xafb20018, 0xafb10014,
+ 0xafb00010, 0x8f500140, 0x34420001, 0x3c038000, 0x02021025, 0xaf420020,
+ 0x8f420020, 0x00431024, 0x1440fffd, 0x24020012, 0x24030080, 0xa362003f,
+ 0xa3630082, 0x93620023, 0x30420040, 0x10400007, 0x00008821, 0x93620023,
+ 0x24110001, 0x304200bf, 0xa3620023, 0x0a000cf0, 0x3c028000, 0x3c028000,
+ 0x34420001, 0x3c039000, 0x34630001, 0x3c048000, 0x02021025, 0x02031825,
+ 0xaf420020, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000,
+ 0x9362007d, 0x3c038000, 0x34420020, 0xa362007d, 0x8f640074, 0x34630001,
+ 0x02031825, 0xaf430020, 0x04810006, 0x3c038000, 0x02002021, 0x0e000470,
+ 0x24050a63, 0x0a000d13, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd,
+ 0x24020002, 0x3c031000, 0xaf5001c0, 0xa34201c4, 0xaf4301f8, 0x1220003f,
+ 0x3c120800, 0x8e420020, 0x8f71004c, 0x1040003c, 0x8fbf001c, 0x0e00148e,
+ 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, 0xac820004,
+ 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
+ 0x8f820018, 0xac510014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001,
+ 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, 0x00621825,
+ 0x0e0014cc, 0xaca3001c, 0x8e420020, 0x1040001e, 0x8fbf001c, 0x0e00148e,
+ 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x3c02008d, 0xac820004,
+ 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
+ 0x8f840018, 0x24020a6a, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448,
+ 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024019,
+ 0x00621825, 0x0e0014cc, 0xaca3001c, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+ 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010, 0x93620081,
+ 0x3c030800, 0x8c640048, 0x0044102b, 0x14400005, 0x00000000, 0x0e000cd3,
+ 0x00000000, 0x0a000da4, 0x8fbf0010, 0x93620081, 0x24420001, 0x0e0013c4,
+ 0xa3620081, 0x9763006a, 0x00032880, 0x14a00002, 0x00403821, 0x24050001,
+ 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804,
+ 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b,
+ 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021,
+ 0xaf62000c, 0x10e00021, 0x3c029000, 0x8f450140, 0x34420001, 0x3c038000,
+ 0x00a21025, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000,
+ 0x9362007d, 0x3c038000, 0x34420004, 0xa362007d, 0x8f640074, 0x34630001,
+ 0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, 0x0e000470,
+ 0x24050a92, 0x0a000da4, 0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd,
+ 0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, 0x8fbf0010,
+ 0x03e00008, 0x27bd0018, 0x27bdffd8, 0xafb3001c, 0x27530100, 0xafbf0024,
+ 0xafb40020, 0xafb20018, 0xafb10014, 0xafb00010, 0x96620008, 0x3c140800,
+ 0x8f520100, 0x30420001, 0x104000da, 0x00000000, 0x8e700018, 0x8f630054,
+ 0x2602ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d, 0x00000000,
+ 0x2400015c, 0x0a000dea, 0x00008821, 0x8f62004c, 0x02021023, 0x18400028,
+ 0x00008821, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c, 0x308400ff,
+ 0x24420001, 0x30a500ff, 0x00803821, 0x1485000b, 0xac62008c, 0x3c040800,
+ 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001, 0x00021023,
+ 0x30420005, 0x0a000dea, 0x34510004, 0x27660100, 0x00041080, 0x00c21021,
+ 0x8c430000, 0x02031823, 0x04600004, 0x24820001, 0x30440007, 0x1485fff9,
+ 0x00041080, 0x10870007, 0x3c030800, 0xa3640121, 0x8c620094, 0x24110005,
+ 0x24420001, 0x0a000dea, 0xac620094, 0x24110004, 0x32220001, 0x1040001e,
+ 0x8e820020, 0x1040001d, 0x32220004, 0x0e00148e, 0x00000000, 0x8f820018,
+ 0xac520000, 0x8f840018, 0x24020001, 0xac820004, 0x8f830018, 0xac600008,
+ 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac500014,
+ 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018,
+ 0x944358ce, 0x8f850018, 0x3c024010, 0x00621825, 0x0e0014cc, 0xaca3001c,
+ 0x32220004, 0x10400081, 0x00003821, 0x3c029000, 0x34420001, 0x3c038000,
+ 0x02421025, 0xa360007c, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x93620023, 0x30420080, 0x10400011, 0x00000000, 0x8f65005c,
+ 0x8f63004c, 0x9764003c, 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b,
+ 0x54400006, 0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023, 0xaf700064,
+ 0x3c023fff, 0x0a000e37, 0x3442ffff, 0x8f62005c, 0x02021023, 0x04400011,
+ 0x00000000, 0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff,
+ 0xaf700064, 0x00a32823, 0x00852821, 0x0045102b, 0x10400004, 0x02051021,
+ 0x3c053fff, 0x34a5ffff, 0x02051021, 0xaf62005c, 0x24070001, 0xaf70004c,
+ 0x8f620054, 0x16020005, 0x00000000, 0x93620023, 0x30420040, 0x10400017,
+ 0x24020001, 0x9762006a, 0x00022880, 0x50a00001, 0x24050001, 0x97630068,
+ 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b,
+ 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001,
+ 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c,
+ 0x93620082, 0x30420080, 0x50400001, 0xa3600081, 0x3c028000, 0x34420001,
+ 0x02421025, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004, 0x00000000,
+ 0x0e0013c4, 0x00000000, 0x00403821, 0x10e0001f, 0x3c029000, 0x34420001,
+ 0x02421025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001,
+ 0x02431825, 0xaf430020, 0x04810006, 0x3c038000, 0x02402021, 0x0e000470,
+ 0x24050b3d, 0x0a000e8d, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd,
+ 0x24020002, 0x3c031000, 0xaf5201c0, 0xa34201c4, 0xaf4301f8, 0x9342010b,
+ 0x9343010b, 0x8e820020, 0x27500100, 0x38630006, 0x10400029, 0x2c710001,
+ 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018,
+ 0x96020008, 0xac820004, 0x8f830018, 0x8e020014, 0xac620008, 0x8f850018,
+ 0x3c026000, 0x8c434448, 0xaca3000c, 0x8f840018, 0x96020012, 0xac820010,
+ 0x8f850018, 0x8e030020, 0xaca30014, 0x9602000c, 0x9603000e, 0x8f840018,
+ 0x00021400, 0x00431025, 0xac820018, 0x12200005, 0x3c020800, 0x944358ce,
+ 0x8f840018, 0x0a000eb8, 0x3c024013, 0x944358ce, 0x8f840018, 0x3c024014,
+ 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8e700014, 0x8f620040,
+ 0x14500003, 0x00501023, 0x0a000ec3, 0x00001021, 0x28420001, 0x1040003a,
+ 0x00000000, 0x0e000fae, 0x02002021, 0xaf700040, 0x9362003e, 0x30420001,
+ 0x1440000b, 0x3c029000, 0x93620022, 0x24420001, 0xa3620022, 0x93630022,
+ 0x3c020800, 0x8c440098, 0x0064182b, 0x14600025, 0x3c020800, 0x3c029000,
+ 0x34420001, 0x02421025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
+ 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x34420001, 0xa362007d,
+ 0x8f640074, 0x34630001, 0x02431825, 0xaf430020, 0x04810006, 0x3c038000,
+ 0x02402021, 0x0e000470, 0x24050273, 0x0a000ef6, 0x24020001, 0x8f4201f8,
+ 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5201c0, 0xa34201c4,
+ 0xaf4301f8, 0x24020001, 0xa7620012, 0x0a000efe, 0xa3600022, 0x9743007a,
+ 0x9444002a, 0x00641821, 0x3063fffe, 0xa7630012, 0x97420108, 0x8fbf0024,
+ 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x00021042,
+ 0x30420001, 0x03e00008, 0x27bd0028, 0x27bdffe0, 0xafb20018, 0x3c120800,
+ 0x8e420020, 0xafb00010, 0x27500100, 0xafbf001c, 0x10400046, 0xafb10014,
+ 0x0e00148e, 0x00000000, 0x8f840018, 0x8e020000, 0xac820000, 0x936300b1,
+ 0x936200c5, 0x8f850018, 0x00031e00, 0x00021400, 0x34420100, 0x00621825,
+ 0xaca30004, 0x8f840018, 0x8e02001c, 0xac820008, 0x8f830018, 0x8f620048,
+ 0xac62000c, 0x8f840018, 0x96020012, 0xac820010, 0x8f830018, 0x8f620040,
+ 0x24040001, 0xac620014, 0x8f850018, 0x3c026000, 0x8c434448, 0x3c020800,
+ 0x245158c0, 0xaca30018, 0x9623000e, 0x8f850018, 0x3c024016, 0x00621825,
+ 0x0e0014cc, 0xaca3001c, 0x96030008, 0x30630010, 0x1060001c, 0x8e420020,
+ 0x1040001a, 0x8e100000, 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000,
+ 0x8f830018, 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c,
+ 0x8f820018, 0xac400010, 0x8f830018, 0xac600014, 0x8f850018, 0x3c036000,
+ 0x8c634448, 0x24040001, 0xaca30018, 0x9622000e, 0x8f850018, 0x3c034015,
+ 0x00431025, 0x0e0014cc, 0xaca2001c, 0x00001021, 0x8fbf001c, 0x8fb20018,
+ 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe0, 0xafb20018,
+ 0x3c120800, 0x8e420020, 0xafb00010, 0x27500100, 0xafbf001c, 0x10400041,
+ 0xafb10014, 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000,
+ 0x8f840018, 0x24020100, 0xac820004, 0x8f830018, 0x8e02001c, 0xac620008,
+ 0x8f840018, 0x8e020018, 0xac82000c, 0x8f830018, 0x96020012, 0xac620010,
+ 0x8f840018, 0x96020008, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448,
+ 0x24040001, 0x3c020800, 0x245158c0, 0xaca30018, 0x9623000e, 0x8f850018,
+ 0x3c024017, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x96030008, 0x30630010,
+ 0x1060001c, 0x8e420020, 0x1040001a, 0x8e100000, 0x0e00148e, 0x00000000,
+ 0x8f820018, 0xac500000, 0x8f830018, 0xac600004, 0x8f820018, 0xac400008,
+ 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, 0x8f830018, 0xac600014,
+ 0x8f850018, 0x3c036000, 0x8c634448, 0x24040001, 0xaca30018, 0x9622000e,
+ 0x8f850018, 0x3c034015, 0x00431025, 0x0e0014cc, 0xaca2001c, 0x00001021,
+ 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
+ 0x27bdfff0, 0x03e00008, 0x27bd0010, 0x27bdffd0, 0xafb10014, 0x00808821,
+ 0xafb40020, 0x00c0a021, 0xafbf0028, 0xafb50024, 0xafb3001c, 0xafb20018,
+ 0xafb00010, 0x93620023, 0x00e0a821, 0x30420040, 0x1040003e, 0x30b3ffff,
+ 0x3c120800, 0x8e420020, 0x1040003a, 0x8f70004c, 0x0e00148e, 0x00000000,
+ 0x8f820018, 0xac510000, 0x8f840018, 0x24020001, 0xac820004, 0x8f830018,
+ 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018,
+ 0x24040001, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448, 0x3c020800,
+ 0x245058c0, 0xaca30018, 0x9603000e, 0x8f850018, 0x3c024010, 0x00621825,
+ 0x0e0014cc, 0xaca3001c, 0x8e430020, 0x1060001b, 0x00000000, 0x0e00148e,
+ 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x3c02008d, 0xac820004,
+ 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
+ 0x8f820018, 0xac550014, 0x8f850018, 0x3c036000, 0x8c634448, 0x24040001,
+ 0xaca30018, 0x9602000e, 0x8f850018, 0x3c034019, 0x00431025, 0x0e0014cc,
+ 0xaca2001c, 0x93620023, 0x30420020, 0x14400003, 0x3c120800, 0x1280003f,
+ 0x3c029000, 0x8e420020, 0x8f70004c, 0x1040003b, 0x3c029000, 0x0e00148e,
+ 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x24020001, 0xac820004,
+ 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
+ 0x8f820018, 0x24040001, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448,
+ 0x3c020800, 0x245058c0, 0xaca30018, 0x9603000e, 0x8f850018, 0x3c024010,
+ 0x00621825, 0x0e0014cc, 0xaca3001c, 0x8e430020, 0x1060001c, 0x3c029000,
+ 0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x00131400,
+ 0xac820004, 0x8f830018, 0xac750008, 0x8f820018, 0xac40000c, 0x8f830018,
+ 0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c036000, 0x8c634448,
+ 0x24040001, 0xaca30018, 0x9602000e, 0x8f850018, 0x3c03401b, 0x00431025,
+ 0x0e0014cc, 0xaca2001c, 0x3c029000, 0x34420001, 0x02221025, 0xaf420020,
+ 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93630023,
+ 0x3c028000, 0x34420001, 0x02221025, 0x8fbf0028, 0x8fb50024, 0x8fb40020,
+ 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3063009f, 0xa3630023,
+ 0xaf420020, 0x03e00008, 0x27bd0030, 0x27bdffe0, 0xafb10014, 0x27510100,
+ 0x3c029000, 0x34420001, 0xafb00010, 0x00808021, 0x02021025, 0x3c038000,
+ 0xafbf0018, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000,
+ 0xa7600008, 0x8f63005c, 0x3c028000, 0x34420001, 0xaf630148, 0x8f640050,
+ 0x02021025, 0x3c039000, 0xaf64017c, 0xaf420020, 0x8f450100, 0x34630001,
+ 0x3c048000, 0x00a31825, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd,
+ 0x00000000, 0x9362007d, 0x3c038000, 0x34420001, 0xa362007d, 0x8f640074,
+ 0x34630001, 0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021,
+ 0x0e000470, 0x24050de5, 0x0a001093, 0x3c020800, 0x8f4201f8, 0x00431024,
+ 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8,
+ 0x3c020800, 0x8c430020, 0x1060001e, 0x8fbf0018, 0x0e00148e, 0x00000000,
+ 0x8f830018, 0xac700000, 0x9622000c, 0x8f840018, 0x00021400, 0xac820004,
+ 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
+ 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001,
+ 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c02401f, 0x00621825,
+ 0x0e0014cc, 0xaca3001c, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008,
+ 0x27bd0020, 0x3c020800, 0x24424c3c, 0xaf82000c, 0x03e00008, 0x00000000,
+ 0x27bdffe8, 0xafb00010, 0x27500100, 0xafbf0014, 0x8e02001c, 0x14400003,
+ 0x3c020800, 0x0000000d, 0x3c020800, 0x8c430020, 0x10600020, 0x00001021,
+ 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018,
+ 0x8e02001c, 0xac820004, 0x8f830018, 0xac600008, 0x8f840018, 0x8e020018,
+ 0xac82000c, 0x8f850018, 0x96020012, 0xaca20010, 0x8f830018, 0x3c026000,
+ 0xac600014, 0x8f840018, 0x8c434448, 0x3c020800, 0xac830018, 0x944358ce,
+ 0x8f840018, 0x3c024012, 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001,
+ 0x00001021, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800,
+ 0x97430078, 0x9444002e, 0x00001021, 0x00641821, 0x3063fffe, 0x03e00008,
+ 0xa7630010, 0x27bdfff0, 0x00001021, 0x03e00008, 0x27bd0010, 0x8f420100,
+ 0x34420001, 0xaf4200a4, 0x03e00008, 0x00001021, 0x27bdffe0, 0xafbf0018,
+ 0xafb10014, 0xafb00010, 0x9362007e, 0x30d000ff, 0x16020031, 0x00808821,
+ 0x8f620178, 0x1602002e, 0x00000000, 0x9362007f, 0x1602002b, 0x00000000,
+ 0x9362007a, 0x16020004, 0x00000000, 0x0000000d, 0x00000000, 0x240009d2,
+ 0x0e0013e6, 0x00000000, 0x3c039000, 0x34630001, 0x3c048000, 0x02231825,
+ 0xa370007a, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000,
+ 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001, 0x02231825,
+ 0xaf430020, 0x04810006, 0x3c038000, 0x02202021, 0x0e000470, 0x240509dd,
+ 0x0a001138, 0x8fbf0018, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002,
+ 0x3c031000, 0xaf5101c0, 0xa34201c4, 0xaf4301f8, 0x0a001138, 0x8fbf0018,
+ 0x0000000d, 0x00000000, 0x240009e2, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+ 0x03e00008, 0x27bd0020, 0x27bdffe8, 0x30a500ff, 0x3c029000, 0x34420001,
+ 0x00803821, 0x00e21025, 0x3c038000, 0xafbf0010, 0xaf420020, 0x8f420020,
+ 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x00a21025,
+ 0xa362007d, 0x8f640074, 0x34630001, 0x00e31825, 0xaf430020, 0x04810006,
+ 0x3c038000, 0x00e02021, 0x0e000470, 0x00c02821, 0x0a001161, 0x8fbf0010,
+ 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4701c0,
+ 0xa34201c4, 0xaf4301f8, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800,
+ 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x10600024, 0xafbf0014,
+ 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018,
+ 0x8e020004, 0xac820004, 0x8f830018, 0x8e020018, 0xac620008, 0x8f840018,
+ 0x8e03001c, 0xac83000c, 0x9602000c, 0x9203000a, 0x8f840018, 0x00021400,
+ 0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018,
+ 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce, 0x8f850018,
+ 0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c, 0x8fbf0014,
+ 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8,
+ 0xafb00010, 0x27500100, 0x10600020, 0xafbf0014, 0x0e00148e, 0x00000000,
+ 0x8f820018, 0xac400000, 0x8f830018, 0xac600004, 0x8f820018, 0xac400008,
+ 0x8f830018, 0xac60000c, 0x9602000c, 0x9603000e, 0x8f840018, 0x00021400,
+ 0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018,
+ 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce, 0x8f850018,
+ 0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c, 0x8fbf0014,
+ 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafb00010, 0x27500100,
+ 0xafbf0014, 0x9602000c, 0x10400024, 0x00802821, 0x3c020800, 0x8c430020,
+ 0x1060003a, 0x8fbf0014, 0x0e00148e, 0x00000000, 0x8f840018, 0x8e030000,
+ 0xac830000, 0x9602000c, 0x8f840018, 0x00021400, 0xac820004, 0x8f830018,
+ 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018,
+ 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800,
+ 0xaca30018, 0x944358ce, 0x8f850018, 0x3c02400b, 0x00621825, 0x0e0014cc,
+ 0xaca3001c, 0x0a0011ff, 0x8fbf0014, 0x93620005, 0x30420010, 0x14400015,
+ 0x3c029000, 0x34420001, 0x00a21025, 0xaf420020, 0x3c038000, 0x8f420020,
+ 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, 0x93620005, 0x34630001,
+ 0x00a02021, 0x00a31825, 0x24055852, 0x34420010, 0xa3620005, 0x0e000766,
+ 0xaf430020, 0x0a0011ff, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010,
+ 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010,
+ 0x27500100, 0x10600022, 0xafbf0014, 0x0e00148e, 0x00000000, 0x8f840018,
+ 0x8e020004, 0xac820000, 0x9603000c, 0x9762002c, 0x8f840018, 0x00031c00,
+ 0x00431025, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c,
+ 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000,
+ 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
+ 0x3c02400e, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x0e00122e, 0x8e040000,
+ 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c038000, 0x8f420278,
+ 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf440240, 0xa3420244,
+ 0x03e00008, 0xaf430278, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb10014,
+ 0x00808821, 0xafb20018, 0x00c09021, 0xafb00010, 0x30b0ffff, 0x1060001c,
+ 0xafbf001c, 0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f840018,
+ 0x00101400, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c,
+ 0x8f830018, 0xac600010, 0x8f820018, 0xac520014, 0x8f840018, 0x3c026000,
+ 0x8c434448, 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024019,
+ 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018,
+ 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0x27450100,
+ 0xafbf0010, 0x94a3000c, 0x240200c1, 0x14620031, 0x00803021, 0x3c029000,
+ 0x34420001, 0x00c21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
+ 0x1440fffd, 0x3c028000, 0x34420001, 0x3c049000, 0x34840001, 0x3c058000,
+ 0x24030012, 0x00c21025, 0x00c42025, 0xa363003f, 0xaf420020, 0xaf440020,
+ 0x8f420020, 0x00451024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000,
+ 0x34420020, 0xa362007d, 0x8f640074, 0x34630001, 0x00c31825, 0xaf430020,
+ 0x04810006, 0x3c038000, 0x00c02021, 0x0e000470, 0x24050906, 0x0a0012a1,
+ 0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000,
+ 0xaf4601c0, 0xa34201c4, 0xaf4301f8, 0x0a0012a1, 0x8fbf0010, 0x00c02021,
+ 0x94a5000c, 0x24060001, 0x0e000fb1, 0x2407090e, 0x8fbf0010, 0x03e00008,
+ 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb00010, 0x00808021,
+ 0xafb20018, 0x00a09021, 0xafb10014, 0x30d100ff, 0x1060001c, 0xafbf001c,
+ 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001,
+ 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
+ 0xac600010, 0x8f820018, 0xac520014, 0x8f840018, 0x3c026000, 0x8c434448,
+ 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024010, 0x00621825,
+ 0xac83001c, 0x0e0014cc, 0x02202021, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+ 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014, 0xafb00010,
+ 0x93620005, 0x30420001, 0x10400036, 0x00808021, 0x3c029000, 0x34420001,
+ 0x02021025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x93620023, 0x34420004, 0xa3620023, 0x93630005, 0x3c048000,
+ 0x3c020800, 0x306300fe, 0xa3630005, 0x8c430020, 0x34840001, 0x02042025,
+ 0xaf440020, 0x10600020, 0x8fbf0014, 0x0e00148e, 0x00000000, 0x8f820018,
+ 0xac500000, 0x93630082, 0x9362003f, 0x8f840018, 0x00031a00, 0x00431025,
+ 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
+ 0xac600010, 0x8f820018, 0xac400014, 0x8f840018, 0x3c026000, 0x8c434448,
+ 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c02400a, 0x00621825,
+ 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf0014, 0x8fb00010, 0x03e00008,
+ 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb10014, 0x00808821,
+ 0xafb20018, 0x00a09021, 0xafb00010, 0x30d000ff, 0x1060002f, 0xafbf001c,
+ 0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f830018, 0xac700004,
+ 0x8f820018, 0xac520008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010,
+ 0x9763006a, 0x00032880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081,
+ 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001,
+ 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021,
+ 0x8f830018, 0x2402fffe, 0x00822824, 0x3c026000, 0xac650014, 0x8f840018,
+ 0x8c434448, 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024011,
+ 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018,
+ 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014,
+ 0xafb00010, 0x8f440100, 0x27500100, 0x8f650050, 0x0e0010fc, 0x9206001b,
+ 0x3c020800, 0x8c430020, 0x1060001d, 0x8e100018, 0x0e00148e, 0x00000000,
+ 0x8f840018, 0x8f420100, 0xac820000, 0x8f830018, 0xac700004, 0x8f840018,
+ 0x8f620050, 0xac820008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010,
+ 0x8f830018, 0x3c026000, 0xac600014, 0x8f850018, 0x8c434448, 0x24040001,
+ 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c02401c, 0x00621825,
+ 0x0e0014cc, 0xaca3001c, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018,
+ 0x8f430238, 0x3c020800, 0x04610013, 0x8c44009c, 0x2406fffe, 0x3c050800,
+ 0x3c038000, 0x2484ffff, 0x14800009, 0x00000000, 0x97420078, 0x8ca3007c,
+ 0x24420001, 0x00461024, 0x24630001, 0xa7620010, 0x03e00008, 0xaca3007c,
+ 0x8f420238, 0x00431024, 0x1440fff3, 0x2484ffff, 0x8f420140, 0x3c031000,
+ 0xaf420200, 0x03e00008, 0xaf430238, 0x27bdffe8, 0x3c029000, 0xafbf0010,
+ 0x8f450140, 0x34420001, 0x3c038000, 0x00a21025, 0xaf420020, 0x8f420020,
+ 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x34420001,
+ 0xa362007d, 0x8f640074, 0x34630001, 0x00a31825, 0xaf430020, 0x04810006,
+ 0x3c038000, 0x00a02021, 0x0e000470, 0x24050ac7, 0x0a0013b9, 0x8fbf0010,
+ 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0,
+ 0xa34201c4, 0xaf4301f8, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x0000000d,
+ 0x03e00008, 0x00000000, 0x0000000d, 0x03e00008, 0x00000000, 0x24020001,
+ 0x03e00008, 0xa7620010, 0x9362003f, 0x304400ff, 0x3883000e, 0x2c630001,
+ 0x38820010, 0x2c420001, 0x00621825, 0x14600003, 0x24020012, 0x14820003,
+ 0x00000000, 0x03e00008, 0x00001021, 0x9363007e, 0x9362007a, 0x14620006,
+ 0x00000000, 0x9363007e, 0x24020001, 0x24630001, 0x03e00008, 0xa363007e,
+ 0x9362007e, 0x8f630178, 0x304200ff, 0x14430006, 0x00000000, 0x9363000b,
+ 0x24020001, 0x24630001, 0x03e00008, 0xa363000b, 0x03e00008, 0x00001021,
+ 0x9362000b, 0x10400023, 0x00001021, 0xa360000b, 0x9362003f, 0x304400ff,
+ 0x3883000e, 0x2c630001, 0x38820010, 0x2c420001, 0x00621825, 0x14600017,
+ 0x00001821, 0x24020012, 0x10820014, 0x00000000, 0x9363007e, 0x9362007a,
+ 0x14620007, 0x00000000, 0x9362007e, 0x24030001, 0x24420001, 0xa362007e,
+ 0x03e00008, 0x00601021, 0x9362007e, 0x8f630178, 0x304200ff, 0x14430005,
+ 0x00001821, 0x9362000b, 0x24030001, 0x24420001, 0xa362000b, 0x03e00008,
+ 0x00601021, 0x03e00008, 0x00000000, 0x24040001, 0xaf64000c, 0x8f6300dc,
+ 0x8f6200cc, 0x50620001, 0xa7640010, 0xa7640012, 0xa7640014, 0x03e00008,
+ 0xa7640016, 0x3c020800, 0x8c430020, 0x27bdffe8, 0x1060001b, 0xafbf0010,
+ 0x0e00148e, 0x00000000, 0x8f820018, 0xac400000, 0x8f830018, 0xac600004,
+ 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010,
+ 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, 0x8c434448, 0x3c020800,
+ 0xac830018, 0x944358ce, 0x8f840018, 0x3c024020, 0x00621825, 0xac83001c,
+ 0x0e0014cc, 0x24040001, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800,
+ 0x8c430020, 0x27bdffe0, 0xafb00010, 0x00a08021, 0xafb10014, 0x00c08821,
+ 0xafb20018, 0x00e09021, 0x1060001e, 0xafbf001c, 0x0e00148e, 0x00000000,
+ 0x8f840018, 0x8f420100, 0xac820000, 0x8f830018, 0xac700004, 0x8f820018,
+ 0xac510008, 0x8f830018, 0xac72000c, 0x8f840018, 0x8fa20030, 0xac820010,
+ 0x8f830018, 0x8fa20034, 0xac620014, 0x8f840018, 0x3c026000, 0x8c434448,
+ 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c0240c9, 0x00621825,
+ 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+ 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c020800, 0x8c430020, 0x27bdffe8,
+ 0xafb00010, 0x27500100, 0x1060001d, 0xafbf0014, 0x0e00148e, 0x00000000,
+ 0x8f830018, 0x8e020004, 0xac620000, 0x8f840018, 0x8e020018, 0xac820004,
+ 0x8f850018, 0x8e020000, 0xaca20008, 0x8f830018, 0xac60000c, 0x8f820018,
+ 0xac400010, 0x8f830018, 0xac600014, 0x8f820018, 0xac400018, 0x96030008,
+ 0x3c020800, 0x944458ce, 0x8f850018, 0x00031c00, 0x00641825, 0x24040001,
+ 0x0e0014cc, 0xaca3001c, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018,
+ 0x3c060800, 0x24c558c0, 0x3c02000a, 0x03421821, 0x94640006, 0x94a2000a,
+ 0x00441023, 0x00021400, 0x00021c03, 0x04610006, 0xa4a40006, 0x0000000d,
+ 0x00000000, 0x2400005a, 0x0a0014a3, 0x24020001, 0x8f820014, 0x0062102b,
+ 0x14400002, 0x00001021, 0x24020001, 0x304200ff, 0x1040001c, 0x274a0400,
+ 0x3c07000a, 0x3c020800, 0x244558c0, 0x94a9000a, 0x8f880014, 0x03471021,
+ 0x94430006, 0x00402021, 0xa4a30006, 0x94820006, 0xa4a20006, 0x01221023,
+ 0x00021400, 0x00021403, 0x04410006, 0x0048102b, 0x0000000d, 0x00000000,
+ 0x2400005a, 0x0a0014be, 0x24020001, 0x14400002, 0x00001021, 0x24020001,
+ 0x304200ff, 0x1440ffec, 0x03471021, 0x24c458c0, 0x8c820010, 0xaf420038,
+ 0x8c830014, 0x3c020005, 0xaf43003c, 0xaf420030, 0xaf800010, 0xaf8a0018,
+ 0x03e00008, 0x00000000, 0x27bdffe0, 0x8f820010, 0x8f850018, 0x3c070800,
+ 0x24e858c0, 0xafbf001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x9503000a,
+ 0x8d060014, 0x00009021, 0x309000ff, 0x00e08821, 0x24420001, 0x24a50020,
+ 0x24630001, 0xaf820010, 0xaf850018, 0xa503000a, 0x24c30020, 0x3c028000,
+ 0x04c10007, 0xad030014, 0x00621024, 0x14400005, 0x262258c0, 0x8d020010,
+ 0x24420001, 0xad020010, 0x262258c0, 0x9444000a, 0x94450018, 0x0010102b,
+ 0x00a41826, 0x2c630001, 0x00621825, 0x1060001c, 0x3c030006, 0x8f820010,
+ 0x24120001, 0x00021140, 0x00431025, 0xaf420030, 0x00000000, 0x00000000,
+ 0x00000000, 0x27450400, 0x8f420000, 0x30420010, 0x1040fffd, 0x262258c0,
+ 0x9444000a, 0x94430018, 0xaf800010, 0xaf850018, 0x14830012, 0x262758c0,
+ 0x0e00155a, 0x00000000, 0x1600000e, 0x262758c0, 0x0e00148e, 0x00000000,
+ 0x0a001517, 0x262758c0, 0x00041c00, 0x00031c03, 0x00051400, 0x00021403,
+ 0x00621823, 0x18600002, 0x3c026000, 0xac400808, 0x262758c0, 0x94e2000e,
+ 0x94e3000c, 0x24420001, 0xa4e2000e, 0x3042ffff, 0x50430001, 0xa4e0000e,
+ 0x12000005, 0x3c02000a, 0x94e2000a, 0xa74200a2, 0x0a001554, 0x02401021,
+ 0x03421821, 0x94640006, 0x94e2000a, 0x00441023, 0x00021400, 0x00021c03,
+ 0x04610006, 0xa4e40006, 0x0000000d, 0x00000000, 0x2400005a, 0x0a001536,
+ 0x24020001, 0x8f820014, 0x0062102b, 0x14400002, 0x00001021, 0x24020001,
+ 0x304200ff, 0x1040001b, 0x3c020800, 0x3c06000a, 0x244558c0, 0x94a8000a,
+ 0x8f870014, 0x03461021, 0x94430006, 0x00402021, 0xa4a30006, 0x94820006,
+ 0xa4a20006, 0x01021023, 0x00021400, 0x00021403, 0x04410006, 0x0047102b,
+ 0x0000000d, 0x00000000, 0x2400005a, 0x0a001550, 0x24020001, 0x14400002,
+ 0x00001021, 0x24020001, 0x304200ff, 0x1440ffec, 0x03461021, 0x02401021,
+ 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
+ 0x3c020800, 0x244558c0, 0x94a3001a, 0x8ca40024, 0x00403021, 0x000318c0,
+ 0x00832021, 0xaf44003c, 0x8ca20020, 0xaf420038, 0x3c020050, 0x34420008,
+ 0xaf420030, 0x00000000, 0x00000000, 0x00000000, 0x8f420000, 0x30420020,
+ 0x1040fffd, 0x00000000, 0x8f430400, 0x24c658c0, 0xacc30010, 0x8f420404,
+ 0x3c030020, 0xacc20014, 0xaf430030, 0x94c40018, 0x94c3001c, 0x94c2001a,
+ 0x94c5001e, 0x00832021, 0x24420001, 0xa4c2001a, 0x3042ffff, 0x14450002,
+ 0xa4c40018, 0xa4c0001a, 0x03e00008, 0x00000000, 0x8f820010, 0x3c030006,
+ 0x00021140, 0x00431025, 0xaf420030, 0x00000000, 0x00000000, 0x00000000,
+ 0x27430400, 0x8f420000, 0x30420010, 0x1040fffd, 0x00000000, 0xaf800010,
+ 0xaf830018, 0x03e00008, 0x00000000, 0x27bdffe8, 0xafb00010, 0x3c100800,
+ 0x261058c0, 0x3c05000a, 0x02002021, 0x03452821, 0xafbf0014, 0x0e0015b0,
+ 0x2406000a, 0x96020002, 0x9603001e, 0x3042000f, 0x24420003, 0x00431804,
+ 0x24027fff, 0x0043102b, 0xaf830014, 0x10400004, 0x00000000, 0x0000000d,
+ 0x00000000, 0x24000043, 0x0e00155a, 0x00000000, 0x8fbf0014, 0x8fb00010,
+ 0x03e00008, 0x27bd0018, 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff,
+ 0x24a50004, 0xac820000, 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000,
+ 0x0a0015c1, 0x00a01021, 0xac860000, 0x00000000, 0x00000000, 0x24840004,
+ 0x00a01021, 0x1440fffa, 0x24a5ffff, 0x03e00008, 0x00000000, 0x3c036000,
+ 0x8c642b7c, 0x3c036010, 0x8c6553fc, 0x00041582, 0x00042302, 0x308403ff,
+ 0x00052d82, 0x00441026, 0x0002102b, 0x0005282b, 0x00451025, 0x1440000d,
+ 0x3c020050, 0x34420004, 0xaf400038, 0xaf40003c, 0xaf420030, 0x00000000,
+ 0x00000000, 0x8f420000, 0x30420020, 0x1040fffd, 0x3c020020, 0xaf420030,
+ 0x0000000d, 0x03e00008, 0x00000000, 0x3c020050, 0x34420004, 0xaf440038,
+ 0xaf45003c, 0xaf420030, 0x00000000, 0x00000000, 0x8f420000, 0x30420020,
+ 0x1040fffd, 0x3c020020, 0xaf420030, 0x03e00008, 0x00000000, 0x00000000};
+
+static u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x0 };
+static u32 bnx2_COM_b06FwRodata[(0x58/4) + 1] = {
+ 0x08002428, 0x0800245c, 0x0800245c, 0x0800245c, 0x0800245c, 0x0800245c,
+ 0x08002380, 0x0800245c, 0x080023e4, 0x0800245c, 0x0800231c, 0x0800245c,
+ 0x0800245c, 0x0800245c, 0x08002328, 0x00000000, 0x08003240, 0x08003270,
+ 0x080032a0, 0x080032d0, 0x08003300, 0x00000000, 0x00000000 };
+static u32 bnx2_COM_b06FwBss[(0x88/4) + 1] = { 0x0 };
+static u32 bnx2_COM_b06FwSbss[(0x1c/4) + 1] = { 0x0 };
+
+static int bnx2_RXP_b06FwReleaseMajor = 0x1;
+static int bnx2_RXP_b06FwReleaseMinor = 0x0;
+static int bnx2_RXP_b06FwReleaseFix = 0x0;
+static u32 bnx2_RXP_b06FwStartAddr = 0x08003184;
+static u32 bnx2_RXP_b06FwTextAddr = 0x08000000;
+static int bnx2_RXP_b06FwTextLen = 0x588c;
+static u32 bnx2_RXP_b06FwDataAddr = 0x080058e0;
+static int bnx2_RXP_b06FwDataLen = 0x0;
+static u32 bnx2_RXP_b06FwRodataAddr = 0x08005890;
+static int bnx2_RXP_b06FwRodataLen = 0x28;
+static u32 bnx2_RXP_b06FwBssAddr = 0x08005900;
+static int bnx2_RXP_b06FwBssLen = 0x13a4;
+static u32 bnx2_RXP_b06FwSbssAddr = 0x080058e0;
+static int bnx2_RXP_b06FwSbssLen = 0x1c;
+static u32 bnx2_RXP_b06FwText[(0x588c/4) + 1] = {
+ 0x0a000c61, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x322e362e,
+ 0x31000000, 0x02060103, 0x00000000, 0x0000000d, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d,
+ 0x3c020800, 0x244258e0, 0x3c030800, 0x24636ca4, 0xac400000, 0x0043202b,
+ 0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800,
+ 0x26103184, 0x3c1c0800, 0x279c58e0, 0x0e00104a, 0x00000000, 0x0000000d,
+ 0x27bdffe8, 0xafb00010, 0xafbf0014, 0x0e000f1d, 0x00808021, 0x1440000d,
+ 0x00000000, 0x8f820010, 0x10400005, 0x00000000, 0x9743011c, 0x9742011e,
+ 0x0a000c89, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825,
+ 0xaf830004, 0x8f840008, 0x3c020020, 0x34424000, 0x00821824, 0x54620004,
+ 0x3c020020, 0x8f820014, 0x0a000c9a, 0x34421000, 0x34428000, 0x00821824,
+ 0x14620004, 0x00000000, 0x8f820014, 0x34428000, 0xaf820014, 0x8f820008,
+ 0x9743010c, 0x00403021, 0x30421000, 0x10400010, 0x3069ffff, 0x30c20020,
+ 0x1440000e, 0x24070005, 0x3c021000, 0x00c21024, 0x10400009, 0x3c030dff,
+ 0x3463ffff, 0x3c020e00, 0x00c21024, 0x0062182b, 0x50600004, 0x24070001,
+ 0x0a000cb2, 0x3c020800, 0x24070001, 0x3c020800, 0x8c430034, 0x1460001d,
+ 0x00405821, 0x8f820014, 0x30424000, 0x1440001a, 0x3c020001, 0x3c021f01,
+ 0x00c24024, 0x3c031000, 0x15030015, 0x3c020001, 0x31220200, 0x14400012,
+ 0x3c020001, 0x9744010e, 0x24020003, 0xa342018b, 0x97850016, 0x24020002,
+ 0x34e30002, 0xaf400180, 0xa742018c, 0xa7430188, 0x24840004, 0x30a5bfff,
+ 0xa744018e, 0xa74501a6, 0xaf4801b8, 0x0a000f19, 0x00001021, 0x3c020001,
+ 0x00c21024, 0x1040002f, 0x00000000, 0x9742010e, 0x3c038000, 0x3046ffff,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9784000a,
+ 0x8f850004, 0x8f870014, 0x24020080, 0x24030002, 0xaf420180, 0x24020003,
+ 0xa743018c, 0xa746018e, 0xa7420188, 0x30e28000, 0xa7440190, 0x1040000c,
+ 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000,
+ 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014,
+ 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff,
+ 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19,
+ 0x00001021, 0x8f820014, 0x30434000, 0x10600016, 0x00404021, 0x3c020f00,
+ 0x00c21024, 0x14400012, 0x00000000, 0x93420116, 0x34424000, 0x03421821,
+ 0x94650002, 0x2ca21389, 0x1040000b, 0x3c020800, 0x24425900, 0x00051942,
+ 0x00031880, 0x00621821, 0x30a5001f, 0x8c640000, 0x24020001, 0x00a21004,
+ 0x00822024, 0x02048025, 0x12000030, 0x3c021000, 0x9742010e, 0x34e80002,
+ 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180,
+ 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000,
+ 0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
+ 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
+ 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
+ 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
+ 0xaf4201b8, 0x0a000f19, 0x00001021, 0x00c21024, 0x104000c0, 0x3c020800,
+ 0x8c430030, 0x10600037, 0x31024000, 0x10400035, 0x3c030f00, 0x00c31824,
+ 0x3c020100, 0x0043102b, 0x14400031, 0x3c030800, 0x9742010e, 0x34e80002,
+ 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020080,
+ 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000,
+ 0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
+ 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
+ 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
+ 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
+ 0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800, 0x8c620024, 0x30420008,
+ 0x10400035, 0x34ea0002, 0x3c020f00, 0x00c21024, 0x14400032, 0x8d620034,
+ 0x31220200, 0x1040002f, 0x8d620034, 0x9742010e, 0x30e8fffb, 0x3c038000,
+ 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
+ 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180, 0x24030002,
+ 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000, 0xa7440190,
+ 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
+ 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024,
+ 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
+ 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
+ 0x8d620034, 0x8f860008, 0x10400012, 0x30c20100, 0x10400010, 0x3c020f00,
+ 0x00c21024, 0x3c030200, 0x1043000c, 0x3c020800, 0x8c430038, 0x8f840004,
+ 0x3c020800, 0x2442003c, 0x2463ffff, 0x00832024, 0x00822021, 0x90830000,
+ 0x24630004, 0x0a000de1, 0x000329c0, 0x00000000, 0x00061602, 0x3042000f,
+ 0x000229c0, 0x3c04fc00, 0x00441021, 0x3c030300, 0x0062182b, 0x50600001,
+ 0x24050800, 0x9742010e, 0x3148ffff, 0x3c038000, 0x24420004, 0x3046ffff,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
+ 0x8f840004, 0x8f870014, 0x24020002, 0xaf450180, 0xa742018c, 0xa746018e,
+ 0xa7480188, 0x30e28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116,
+ 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004,
+ 0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c,
+ 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
+ 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x8f424000,
+ 0x30420100, 0x104000d5, 0x3c020800, 0x8c440024, 0x24030001, 0x1483002f,
+ 0x00405021, 0x9742010e, 0x34e70002, 0x3c038000, 0x24420004, 0x3045ffff,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
+ 0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c, 0xa745018e,
+ 0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116,
+ 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004,
+ 0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016, 0x9743010c,
+ 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
+ 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x30820001,
+ 0x1040002e, 0x30eb0004, 0x9742010e, 0x30e9fffb, 0x3c038000, 0x24420004,
+ 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b,
+ 0x9783000a, 0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c,
+ 0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8,
+ 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff,
+ 0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016,
+ 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825,
+ 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x3127ffff, 0x8d420024,
+ 0x30420004, 0x10400030, 0x8d420024, 0x9742010e, 0x30e9fffb, 0x3c038000,
+ 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
+ 0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020100, 0x24030002,
+ 0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000, 0xa7440190,
+ 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
+ 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x01021024,
+ 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
+ 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
+ 0x3127ffff, 0x8d420024, 0x30420008, 0x1040002d, 0x00000000, 0x9742010e,
+ 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020180,
+ 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000,
+ 0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
+ 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
+ 0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
+ 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
+ 0xaf4201b8, 0x15600041, 0x00001021, 0x27440180, 0x3c038000, 0x8f4201b8,
+ 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b,
+ 0xa4800010, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800,
+ 0x8c620024, 0x30420001, 0x1040002e, 0x00001021, 0x9742010e, 0x34e70002,
+ 0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x24020003, 0xa342018b, 0x9783000a, 0x8f840004, 0x8f860014, 0x24020002,
+ 0xaf400180, 0xa742018c, 0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190,
+ 0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
+ 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024,
+ 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
+ 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
+ 0x00001021, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x8f4b0070,
+ 0x93420112, 0x8f840008, 0x00022882, 0x30820100, 0x14400003, 0x24a30003,
+ 0x03e00008, 0x00001021, 0x30824000, 0x10400010, 0x27424000, 0x00031880,
+ 0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021,
+ 0x8c490000, 0x93430116, 0x27424000, 0x306300fc, 0x00431021, 0x8c4a0000,
+ 0x0a000f45, 0x3c030800, 0x30822000, 0x1040ffea, 0x00031880, 0x27424000,
+ 0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021,
+ 0x8c490000, 0x00005021, 0x3c030800, 0x24680100, 0x00071602, 0x00021080,
+ 0x00481021, 0x8c460000, 0x00071b82, 0x306303fc, 0x01031821, 0x8c640400,
+ 0x00071182, 0x304203fc, 0x01021021, 0x8c450800, 0x30e300ff, 0x00031880,
+ 0x01031821, 0x00091602, 0x00021080, 0x01021021, 0x00c43026, 0x8c640c00,
+ 0x8c431000, 0x00c53026, 0x00091382, 0x304203fc, 0x01021021, 0x8c451400,
+ 0x312200ff, 0x00021080, 0x01021021, 0x00c43026, 0x00c33026, 0x00091982,
+ 0x306303fc, 0x01031821, 0x8c641800, 0x8c431c00, 0x00c53026, 0x00c43026,
+ 0x11400015, 0x00c33026, 0x000a1602, 0x00021080, 0x01021021, 0x8c432000,
+ 0x000a1382, 0x304203fc, 0x01021021, 0x8c452400, 0x314200ff, 0x00021080,
+ 0x01021021, 0x00c33026, 0x000a1982, 0x306303fc, 0x01031821, 0x8c642800,
+ 0x8c432c00, 0x00c53026, 0x00c43026, 0x00c33026, 0x8f430070, 0x3c050800,
+ 0x8ca43100, 0x2c820020, 0x10400008, 0x006b5823, 0x3c020800, 0x24423104,
+ 0x00041880, 0x00621821, 0x24820001, 0xac6b0000, 0xaca23100, 0xaf860004,
+ 0x03e00008, 0x24020001, 0x27bdffe8, 0xafbf0010, 0x8f460128, 0x8f840010,
+ 0xaf460020, 0x8f450104, 0x8f420100, 0x24030800, 0xaf850008, 0xaf820014,
+ 0xaf4301b8, 0x1080000a, 0x3c020800, 0x8c430034, 0x10600007, 0x30a22000,
+ 0x10400005, 0x34a30100, 0x8f82000c, 0xaf830008, 0x24420001, 0xaf82000c,
+ 0x3c020800, 0x8c4300c0, 0x10600006, 0x3c030800, 0x8c6200c4, 0x24040001,
+ 0x24420001, 0x0a000fd5, 0xac6200c4, 0x8f820008, 0x3c030010, 0x00431024,
+ 0x14400009, 0x3c02001f, 0x3c030800, 0x8c620020, 0x00002021, 0x24420001,
+ 0x0e000c78, 0xac620020, 0x0a000fd5, 0x00402021, 0x3442ff00, 0x14c20009,
+ 0x2403bfff, 0x3c030800, 0x8c620020, 0x24040001, 0x24420001, 0x0e000c78,
+ 0xac620020, 0x0a000fd5, 0x00402021, 0x8f820014, 0x00431024, 0x14400006,
+ 0x00000000, 0xaf400048, 0x0e0011a9, 0xaf400040, 0x0a000fd5, 0x00402021,
+ 0x0e001563, 0x00000000, 0x00402021, 0x10800005, 0x3c024000, 0x8f430124,
+ 0x3c026020, 0xac430014, 0x3c024000, 0xaf420138, 0x00000000, 0x8fbf0010,
+ 0x03e00008, 0x27bd0018, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010,
+ 0x8f420140, 0xaf420020, 0x8f430148, 0x3c027000, 0x00621824, 0x3c023000,
+ 0x10620021, 0x0043102b, 0x14400006, 0x3c024000, 0x3c022000, 0x10620009,
+ 0x3c024000, 0x0a001040, 0x00000000, 0x10620045, 0x3c025000, 0x10620047,
+ 0x3c024000, 0x0a001040, 0x00000000, 0x27440180, 0x3c038000, 0x8f4201b8,
+ 0x00431024, 0x1440fffd, 0x00000000, 0x8f420148, 0x24030002, 0xa083000b,
+ 0x00021402, 0xa4820008, 0x8f430148, 0xa4830010, 0x8f420144, 0x3c031000,
+ 0xac820024, 0xaf4301b8, 0x0a001040, 0x3c024000, 0x8f420148, 0x24030002,
+ 0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003,
+ 0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001027, 0x3c038000,
+ 0x12020007, 0x00000000, 0x0a001034, 0x00000000, 0x0e00112c, 0x00000000,
+ 0x0a001025, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000,
+ 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008,
+ 0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8,
+ 0x0a001040, 0x3c024000, 0x0000000d, 0x00000000, 0x240002bf, 0x0a001040,
+ 0x3c024000, 0x0e001441, 0x00000000, 0x0a001040, 0x3c024000, 0x0e0015ea,
+ 0x00000000, 0x3c024000, 0xaf420178, 0x00000000, 0x8fbf0018, 0x8fb10014,
+ 0x8fb00010, 0x03e00008, 0x27bd0020, 0x24020800, 0x03e00008, 0xaf4201b8,
+ 0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000,
+ 0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000,
+ 0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800,
+ 0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001,
+ 0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000,
+ 0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c,
+ 0x8e021980, 0x34420200, 0xae021980, 0x8f500000, 0x32020003, 0x1040fffd,
+ 0x32020001, 0x10400004, 0x32020002, 0x0e000f92, 0x00000000, 0x32020002,
+ 0x1040fff6, 0x00000000, 0x0e000fe0, 0x00000000, 0x0a001071, 0x00000000,
+ 0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000,
+ 0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000,
+ 0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800,
+ 0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001,
+ 0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000,
+ 0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c,
+ 0x8e021980, 0x8fbf0014, 0x34420200, 0xae021980, 0x8fb00010, 0x03e00008,
+ 0x27bd0018, 0x00804821, 0x30a5ffff, 0x30c6ffff, 0x30e7ffff, 0x3c038000,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
+ 0x8f840004, 0x8f880014, 0xaf490180, 0xa745018c, 0xa746018e, 0xa7470188,
+ 0x31028000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc,
+ 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff,
+ 0x34427fff, 0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104,
+ 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac,
+ 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, 0x3c038000,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008,
+ 0xa083000b, 0xa4800010, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000,
+ 0x27440180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
+ 0x8f420148, 0x24030002, 0xa083000b, 0x00021402, 0xa4820008, 0x8f430148,
+ 0xa4830010, 0x8f420144, 0x3c031000, 0xac820024, 0x03e00008, 0xaf4301b8,
+ 0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420148, 0x24030002,
+ 0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003,
+ 0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001117, 0x3c038000,
+ 0x12020007, 0x00000000, 0x0a001124, 0x00000000, 0x0e00112c, 0x00000000,
+ 0x0a001115, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000,
+ 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008,
+ 0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8,
+ 0x0a001128, 0x8fbf0018, 0x0000000d, 0x00000000, 0x240002bf, 0x8fbf0018,
+ 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3084ffff, 0x2c821389,
+ 0x1040000d, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880,
+ 0x00a32821, 0x3086001f, 0x8ca40000, 0x24030001, 0x00c31804, 0x00832025,
+ 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x3084ffff, 0x2c821389,
+ 0x1040000e, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880,
+ 0x00a32821, 0x3086001f, 0x24030001, 0x8ca40000, 0x00c31804, 0x00031827,
+ 0x00832024, 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x9482000c,
+ 0x24870014, 0x00021302, 0x00021080, 0x00824021, 0x00e8182b, 0x1060004f,
+ 0x00000000, 0x90e30000, 0x2c620009, 0x10400047, 0x3c020800, 0x24425890,
+ 0x00031880, 0x00621821, 0x8c640000, 0x00800008, 0x00000000, 0x0a0011a4,
+ 0x24e70001, 0x90e30001, 0x2402000a, 0x54620024, 0x01003821, 0x01071023,
+ 0x2c42000a, 0x54400020, 0x01003821, 0x3c050800, 0x8ca26c98, 0x24e70002,
+ 0x34420100, 0xaca26c98, 0x90e30000, 0x90e20001, 0x90e40002, 0x90e60003,
+ 0x24e70004, 0x24a56c98, 0x00031e00, 0x00021400, 0x00621825, 0x00042200,
+ 0x00641825, 0x00661825, 0xaca30004, 0x90e20000, 0x90e30001, 0x90e40002,
+ 0x90e60003, 0x24e70004, 0x00021600, 0x00031c00, 0x00431025, 0x00042200,
+ 0x00441025, 0x00461025, 0x0a0011a4, 0xaca20008, 0x90e30001, 0x24020004,
+ 0x1062000e, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020003,
+ 0x10620008, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020002,
+ 0x14620003, 0x01001021, 0x00601021, 0x00e21021, 0x0a0011a4, 0x00403821,
+ 0x90e20001, 0x0a0011a4, 0x00e23821, 0x01003821, 0x00e8102b, 0x5440ffb4,
+ 0x90e30000, 0x03e00008, 0x24020001, 0x27bdff90, 0x3c030800, 0xafbf006c,
+ 0xafbe0068, 0xafb70064, 0xafb60060, 0xafb5005c, 0xafb40058, 0xafb30054,
+ 0xafb20050, 0xafb1004c, 0xafb00048, 0xac606c98, 0x93620023, 0x30420010,
+ 0x1440027c, 0x24020001, 0x93420116, 0x93630005, 0x34424000, 0x30630001,
+ 0x14600005, 0x0342b021, 0x0e0015e0, 0x00000000, 0x0a001436, 0x8fbf006c,
+ 0x93420112, 0x8f430104, 0x3c040020, 0x34424000, 0x00641824, 0x10600012,
+ 0x03422821, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x8f420128, 0xaca20000, 0x8f640040, 0x24030008, 0x240240c1,
+ 0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000, 0x0a0011f1, 0xa0a3000a,
+ 0x8f420104, 0x3c030040, 0x00431024, 0x1040001d, 0x3c038000, 0x27450180,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000,
+ 0x8f640040, 0x24030010, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a3000a,
+ 0x24030008, 0xa0a2000b, 0x3c021000, 0xa4a30010, 0xa0a00012, 0xa0a00013,
+ 0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c, 0xaca40018, 0x0e0015e0,
+ 0xaf4201b8, 0x0a001436, 0x8fbf006c, 0x8f820000, 0x10400016, 0x00000000,
+ 0x8f420104, 0x3c030001, 0x00431024, 0x10400011, 0x00000000, 0x8ca3000c,
+ 0x8f620030, 0x1462022d, 0x24020001, 0x8ca30010, 0x8f62002c, 0x14620229,
+ 0x24020001, 0x9763003a, 0x96c20000, 0x14430225, 0x24020001, 0x97630038,
+ 0x96c20002, 0x14430221, 0x24020001, 0xaf400048, 0xaf400054, 0xaf400040,
+ 0x8f740040, 0x8f650048, 0x00b43023, 0x04c10004, 0x00000000, 0x0000000d,
+ 0x00000000, 0x240001af, 0x9742011a, 0x3052ffff, 0x12400004, 0x8ed30004,
+ 0x02721021, 0x0a001228, 0x2451ffff, 0x02608821, 0x92d7000d, 0xa7a00020,
+ 0xa3a0001a, 0xafa00028, 0x9362003f, 0x32e30004, 0x1060003a, 0x305000ff,
+ 0x24040012, 0x16040006, 0x24020001, 0x3c040800, 0x8c830028, 0x24630001,
+ 0x0a001328, 0xac830028, 0x8f620044, 0x16620010, 0x27a60010, 0x27450180,
+ 0x3c038000, 0x2402001a, 0xa7a20020, 0x24020020, 0xafb40028, 0xa3b00022,
+ 0xa3a40023, 0xa3a2001a, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
+ 0x0a00130d, 0x00000000, 0x8f620044, 0x02621023, 0x0440001a, 0x02651023,
+ 0x044100d9, 0x24020001, 0x3c020800, 0x8c4300d8, 0x10600004, 0x24020001,
+ 0xa7a20020, 0x0a00125e, 0xafb40028, 0x2402001a, 0xa7a20020, 0x24020020,
+ 0xafb40028, 0xa3b00022, 0xa3a40023, 0xa3a2001a, 0x27a60010, 0x27450180,
+ 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d,
+ 0x00000000, 0x0a001328, 0x24020001, 0x0293f023, 0x1bc00016, 0x025e102a,
+ 0x54400007, 0x32f700fe, 0x57d2000f, 0x027e9821, 0x32e20001, 0x5440000c,
+ 0x027e9821, 0x32f700fe, 0x0240f021, 0x3c040800, 0x8c8300c8, 0x00009021,
+ 0x24020001, 0xa7a20020, 0xafb40028, 0x24630001, 0x0a001282, 0xac8300c8,
+ 0x025e1023, 0x0a001282, 0x3052ffff, 0x0000f021, 0x24a2ffff, 0x02221823,
+ 0x1860001f, 0x0072102a, 0x54400019, 0x00a08821, 0x97a20020, 0x3c040800,
+ 0x8c8300cc, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020, 0x02741026,
+ 0x2c420001, 0xac8300cc, 0x2cc30001, 0x00431024, 0x1440000a, 0x02401821,
+ 0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x0a00130d, 0x00000000, 0x00a08821, 0x02431023, 0x3052ffff,
+ 0x0a0012ae, 0x32f700f6, 0x02741023, 0x18400008, 0x97a20020, 0x3c040800,
+ 0x8c8300d4, 0xafb30028, 0x34420400, 0x24630001, 0xa7a20020, 0xac8300d4,
+ 0x32e20002, 0x1040001c, 0x32e20010, 0x8f620044, 0x1662000d, 0x27a60010,
+ 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000,
+ 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000,
+ 0x54400003, 0x8ed50008, 0x0a001328, 0x24020001, 0x8f630054, 0x26a2ffff,
+ 0x00431023, 0x18400011, 0x27a60010, 0x97a20020, 0x3c040800, 0x8c8300d0,
+ 0x27450180, 0x3c078000, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020,
+ 0xac8300d0, 0x8f4201b8, 0x00471024, 0x1440fffd, 0x00000000, 0x0a00130d,
+ 0x00000000, 0x32e20020, 0x10400011, 0x00000000, 0x96c20012, 0x0052102b,
+ 0x10400008, 0x97a20020, 0x96d20012, 0x12400003, 0x02721021, 0x0a0012f2,
+ 0x2451ffff, 0x02608821, 0x97a20020, 0x93a3001a, 0x34420008, 0x34630004,
+ 0xa7a20020, 0xa3a3001a, 0x8f420104, 0x3c030080, 0x00431024, 0x10400037,
+ 0x3a03000a, 0x0e001151, 0x02c02021, 0x24030002, 0x1443002b, 0x3c030800,
+ 0x27a60010, 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001,
+ 0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128,
+ 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, 0x90c4000a,
+ 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, 0x90c30012,
+ 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, 0x8cc20024,
+ 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001, 0x3c031000,
+ 0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a001436, 0x8fbf006c,
+ 0x8c626c98, 0x30420100, 0x10400003, 0x24636c98, 0x8c620004, 0xaf62017c,
+ 0x3a03000a, 0x2c630001, 0x3a02000c, 0x2c420001, 0x00621825, 0x14600003,
+ 0x2402000e, 0x56020030, 0x00009021, 0x52400008, 0x96c4000e, 0x12400004,
+ 0xa7b20040, 0x02721021, 0x0a001343, 0x2451ffff, 0x02608821, 0x96c4000e,
+ 0x93630035, 0x8f62004c, 0x00642004, 0x00952021, 0x00821023, 0x18400015,
+ 0x00000000, 0x8f620018, 0x02621023, 0x1c400015, 0x97a20020, 0x8f620018,
+ 0x1662001c, 0x00000000, 0x8f62001c, 0x02a21023, 0x1c40000e, 0x97a20020,
+ 0x8f62001c, 0x16a20015, 0x00000000, 0x8f620058, 0x00821023, 0x18400011,
+ 0x97a20020, 0x0a001364, 0xafb10028, 0x8f620058, 0x00821023, 0x0441000b,
+ 0x97a20020, 0xafb10028, 0xafb30034, 0xafb50038, 0xafa4003c, 0x34420020,
+ 0x0a00136d, 0xa7a20020, 0x02809821, 0x02608821, 0x8f640058, 0x8f62004c,
+ 0x02a21023, 0x18400009, 0x00000000, 0x8f620054, 0x02a21023, 0x1c400005,
+ 0x97a20020, 0xafb10028, 0xafb50024, 0x0a001385, 0x34420040, 0x9742011a,
+ 0x1440000c, 0x24020014, 0x8f620058, 0x14820009, 0x24020014, 0x8f63004c,
+ 0x8f620054, 0x10620004, 0x97a20020, 0xafb10028, 0x34420080, 0xa7a20020,
+ 0x24020014, 0x1202000a, 0x2a020015, 0x10400005, 0x2402000c, 0x12020006,
+ 0x32e20001, 0x0a0013c6, 0x00000000, 0x24020016, 0x16020035, 0x32e20001,
+ 0x8f620084, 0x24420001, 0x16a20031, 0x32e20001, 0x24020014, 0x12020021,
+ 0x2a020015, 0x10400005, 0x2402000c, 0x12020008, 0x32e20001, 0x0a0013c6,
+ 0x00000000, 0x24020016, 0x1202000c, 0x32e20001, 0x0a0013c6, 0x00000000,
+ 0x97a30020, 0x2402000e, 0xafb10028, 0xa3b00022, 0xa3a20023, 0xafb50024,
+ 0x34630054, 0x0a0013c5, 0xa7a30020, 0x97a20020, 0x93a4001a, 0x24030010,
+ 0xafb10028, 0xa3b00022, 0xa3a30023, 0xafb50024, 0x3442005d, 0x34840002,
+ 0xa7a20020, 0x0a0013c5, 0xa3a4001a, 0x97a20020, 0x24030012, 0xa3a30023,
+ 0x93a3001a, 0xafb10028, 0xa3b00022, 0xafb50024, 0x3042fffe, 0x3442005c,
+ 0x34630002, 0xa7a20020, 0xa3a3001a, 0x32e20001, 0x10400030, 0x2402000c,
+ 0x12020013, 0x2a02000d, 0x10400005, 0x2402000a, 0x12020008, 0x97a20020,
+ 0x0a0013f8, 0x32e20009, 0x2402000e, 0x1202001b, 0x32e20009, 0x0a0013f9,
+ 0x0002102b, 0x93a4001a, 0x24030008, 0xafb10028, 0xa3b00022, 0xa3a30023,
+ 0x0a0013f4, 0x34420013, 0x97a30020, 0x30620004, 0x14400005, 0x93a2001a,
+ 0x3463001b, 0xa7a30020, 0x0a0013e7, 0x24030016, 0x3463001b, 0xa7a30020,
+ 0x24030010, 0xafb10028, 0xa3b00022, 0xa3a30023, 0x34420002, 0x0a0013f7,
+ 0xa3a2001a, 0x97a20020, 0x93a4001a, 0x24030010, 0xafb10028, 0xa3b00022,
+ 0xa3a30023, 0x3442001b, 0x34840002, 0xa7a20020, 0xa3a4001a, 0x32e20009,
+ 0x0002102b, 0x00021023, 0x30420007, 0x12400015, 0x34450003, 0x8f820018,
+ 0x24030800, 0x27440180, 0x24420001, 0xaf820018, 0x24020004, 0xaf4301b8,
+ 0xa4850008, 0xa082000b, 0x93430120, 0x00003021, 0x3c021000, 0xa492000e,
+ 0xac950024, 0xac930028, 0x007e1821, 0xa483000c, 0xaf4201b8, 0x0a001413,
+ 0x97a20020, 0x24060001, 0x97a20020, 0x10400020, 0x27450180, 0x3c038000,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000,
+ 0x8fa30028, 0x240240c1, 0xa4a20008, 0xaca30018, 0x93a4001a, 0x24020002,
+ 0xa0a2000b, 0xa0a4000a, 0x97a20020, 0xa4a20010, 0x93a30022, 0xa0a30012,
+ 0x93a20023, 0xa0a20013, 0x8fa30024, 0xaca30014, 0x8fa20034, 0xaca20024,
+ 0x8fa30038, 0xaca30028, 0x8fa2003c, 0x3c031000, 0xaca2002c, 0xaf4301b8,
+ 0x00c01021, 0x8fbf006c, 0x8fbe0068, 0x8fb70064, 0x8fb60060, 0x8fb5005c,
+ 0x8fb40058, 0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048, 0x03e00008,
+ 0x27bd0070, 0x8f470140, 0x8f460148, 0x3c028000, 0x00c24024, 0x00062c02,
+ 0x30a300ff, 0x24020019, 0x106200e7, 0x27440180, 0x2862001a, 0x1040001f,
+ 0x24020008, 0x106200be, 0x28620009, 0x1040000d, 0x24020001, 0x10620046,
+ 0x28620002, 0x50400005, 0x24020006, 0x1060002e, 0x00a01821, 0x0a00155e,
+ 0x00000000, 0x1062005b, 0x00a01821, 0x0a00155e, 0x00000000, 0x2402000b,
+ 0x10620084, 0x2862000c, 0x10400005, 0x24020009, 0x106200bc, 0x00061c02,
+ 0x0a00155e, 0x00000000, 0x2402000e, 0x106200b7, 0x00061c02, 0x0a00155e,
+ 0x00000000, 0x28620021, 0x10400009, 0x2862001f, 0x104000c1, 0x2402001b,
+ 0x106200bf, 0x2402001c, 0x1062009a, 0x00061c02, 0x0a00155e, 0x00000000,
+ 0x240200c2, 0x106200ca, 0x286200c3, 0x10400005, 0x24020080, 0x1062005a,
+ 0x00a01821, 0x0a00155e, 0x00000000, 0x240200c9, 0x106200cd, 0x30c5ffff,
+ 0x0a00155e, 0x00000000, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd,
+ 0x24020001, 0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a,
+ 0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024,
+ 0x3c036000, 0xaf4201b8, 0x03e00008, 0xac600808, 0x11000009, 0x00a01821,
+ 0x3c020800, 0x24030002, 0xa0436c88, 0x24426c88, 0xac470008, 0x8f430144,
+ 0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd,
+ 0x24020002, 0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b,
+ 0xa4860010, 0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x3c026000,
+ 0xaf4301b8, 0x03e00008, 0xac400808, 0x3c080800, 0x3c058000, 0x8f4201b8,
+ 0x00451024, 0x1440fffd, 0x00000000, 0xac870000, 0x91026c88, 0x00002821,
+ 0x10400002, 0x25076c88, 0x8ce50008, 0xac850004, 0xa4830008, 0x91036c88,
+ 0x24020002, 0xa082000b, 0xa4860010, 0x34630001, 0xa083000a, 0x8f420144,
+ 0xac820024, 0x91036c88, 0x10600002, 0x00001021, 0x8ce20004, 0xac820028,
+ 0x3c021000, 0xaf4201b8, 0x3c026000, 0xa1006c88, 0x03e00008, 0xac400808,
+ 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, 0xa082000b,
+ 0xa4830008, 0xa4860010, 0x8f420144, 0x3c031000, 0xa4820012, 0x03e00008,
+ 0xaf4301b8, 0x30c2ffff, 0x14400028, 0x00061c02, 0x93620005, 0x30420004,
+ 0x14400020, 0x3c029000, 0x34420001, 0x00e21025, 0xaf420020, 0x3c038000,
+ 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000,
+ 0x34630001, 0x00e31825, 0x34420004, 0xa3620005, 0xaf430020, 0x93620005,
+ 0x30420004, 0x14400003, 0x3c038000, 0x0000000d, 0x3c038000, 0x8f4201b8,
+ 0x00431024, 0x1440fffd, 0x24020005, 0x3c031000, 0xac870000, 0xa082000b,
+ 0xaf4301b8, 0x0a00150d, 0x00061c02, 0x0000000d, 0x03e00008, 0x00000000,
+ 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001,
+ 0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a, 0xa083000b,
+ 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024, 0x03e00008,
+ 0xaf4201b8, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002,
+ 0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b, 0xa4860010,
+ 0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x03e00008, 0xaf4301b8,
+ 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001,
+ 0xa4830008, 0x24030002, 0xa082000a, 0x3c021000, 0xac870000, 0xac800004,
+ 0xa083000b, 0xa4860010, 0xac800024, 0xac800028, 0x03e00008, 0xaf4201b8,
+ 0x00a01821, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002,
+ 0xac870000, 0xac800004, 0xa4830008, 0xa080000a, 0x0a001518, 0xa082000b,
+ 0x8f440144, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002,
+ 0x240340c9, 0xaf470180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4401a4,
+ 0xaf4501a8, 0xaf4001ac, 0x03e00008, 0xaf4201b8, 0x0000000d, 0x03e00008,
+ 0x00000000, 0x03e00008, 0x00000000, 0x8f420100, 0x3042003e, 0x14400011,
+ 0x24020001, 0xaf400048, 0x8f420100, 0x304207c0, 0x10400005, 0x00000000,
+ 0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001, 0xaf400054, 0xaf400040,
+ 0x8f420100, 0x30423800, 0x54400001, 0xaf400044, 0x24020001, 0x03e00008,
+ 0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002,
+ 0x240340c9, 0xaf440180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4501a4,
+ 0xaf4601a8, 0xaf4701ac, 0x03e00008, 0xaf4201b8, 0x3c029000, 0x34420001,
+ 0x00822025, 0xaf440020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x03e00008, 0x00000000, 0x3c028000, 0x34420001, 0x00822025,
+ 0x03e00008, 0xaf440020, 0x308600ff, 0x27450180, 0x3c038000, 0x8f4201b8,
+ 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8f640040,
+ 0x24030008, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000,
+ 0xa0a6000a, 0xa4a30010, 0xa0a00012, 0xa0a00013, 0xaca00014, 0xaca00024,
+ 0xaca00028, 0xaca0002c, 0xaca40018, 0x03e00008, 0xaf4201b8, 0x24020001,
+ 0xacc40000, 0x03e00008, 0xa4e50000, 0x24020001, 0xaf400044, 0x03e00008,
+ 0xaf400050, 0x00803021, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024,
+ 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1,
+ 0xa4a20008, 0xaca30018, 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a,
+ 0x94c20010, 0xa4a20010, 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013,
+ 0x8cc30014, 0xaca30014, 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028,
+ 0x8cc2002c, 0x3c031000, 0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044,
+ 0x03e00008, 0xaf400050, 0x27bdffe8, 0xafbf0010, 0x0e001047, 0x00000000,
+ 0x00002021, 0x0e000c78, 0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018,
+ 0x8f460148, 0x27450180, 0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8,
+ 0x00431024, 0x1440fffd, 0x00000000, 0x8f440140, 0x00061202, 0x304200ff,
+ 0x00061c02, 0xaca20004, 0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b,
+ 0xaca30024, 0x10e0000a, 0xaca40000, 0x28e20004, 0x14400005, 0x24020001,
+ 0x24020005, 0x54e20005, 0xa0a0000a, 0x24020001, 0x0a001609, 0xa0a2000a,
+ 0xa0a0000a, 0x3c021000, 0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021,
+ 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000,
+ 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a00161f, 0x00a01021,
+ 0xac860000, 0x00000000, 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa,
+ 0x24a5ffff, 0x03e00008, 0x00000000, 0x00000000 };
+
+static u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x0 };
+static u32 bnx2_RXP_b06FwRodata[(0x28/4) + 1] = {
+ 0x0800468c, 0x0800458c, 0x08004630, 0x08004648, 0x08004660, 0x08004680,
+ 0x0800468c, 0x0800468c, 0x08004594, 0x00000000, 0x00000000 };
+static u32 bnx2_RXP_b06FwBss[(0x13a4/4) + 1] = { 0x0 };
+static u32 bnx2_RXP_b06FwSbss[(0x1c/4) + 1] = { 0x0 };
+
+static u32 bnx2_rv2p_proc1[] = {
+ 0x00000008, 0xac000001, 0x0000000c, 0x2f800001, 0x00000010, 0x213f0004,
+ 0x00000010, 0x20bf002c, 0x00000010, 0x203f0143, 0x00000018, 0x8000fffd,
+ 0x00000010, 0xb1b8b017, 0x0000000b, 0x2fdf0002, 0x00000000, 0x03d80000,
+ 0x00000000, 0x2c380000, 0x00000008, 0x2c800000, 0x00000008, 0x2d000000,
+ 0x00000010, 0x91d40000, 0x00000008, 0x2d800108, 0x00000008, 0x02000002,
+ 0x00000010, 0x91de0000, 0x0000000f, 0x42e0001c, 0x00000010, 0x91840a08,
+ 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, 0x00000008, 0x2d800150,
+ 0x00000000, 0x00000000, 0x00000010, 0x91de0000, 0x00000010, 0x2c620002,
+ 0x00000018, 0x80000012, 0x0000000b, 0x2fdf0002, 0x0000000c, 0x1f800002,
+ 0x00000000, 0x2c070000, 0x00000018, 0x8000ffe6, 0x00000008, 0x02000002,
+ 0x0000000f, 0x42e0001c, 0x00000010, 0x91840a08, 0x00000008, 0x2c8000b0,
+ 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800108,
+ 0x00000000, 0x00000000, 0x00000010, 0x91de0000, 0x00000018, 0x80000004,
+ 0x0000000c, 0x1f800002, 0x00000000, 0x00000000, 0x00000018, 0x8000ffd9,
+ 0x0000000c, 0x29800002, 0x0000000c, 0x1f800002, 0x00000000, 0x2adf0000,
+ 0x00000008, 0x2a000005, 0x00000018, 0x8000ffd4, 0x00000008, 0x02240030,
+ 0x00000018, 0x00040000, 0x00000018, 0x80000015, 0x00000018, 0x80000017,
+ 0x00000018, 0x8000001b, 0x00000018, 0x8000004c, 0x00000018, 0x8000008c,
+ 0x00000018, 0x8000000f, 0x00000018, 0x8000000e, 0x00000018, 0x8000000d,
+ 0x00000018, 0x8000000c, 0x00000018, 0x800000c2, 0x00000018, 0x8000000a,
+ 0x00000018, 0x80000009, 0x00000018, 0x80000008, 0x00000018, 0x800000fd,
+ 0x00000018, 0x80000006, 0x00000018, 0x80000005, 0x00000018, 0x800000ff,
+ 0x00000018, 0x80000104, 0x00000018, 0x80000002, 0x00000018, 0x80000098,
+ 0x00000018, 0x80000000, 0x0000000c, 0x1f800001, 0x00000000, 0x00000000,
+ 0x00000018, 0x8000ffba, 0x00000010, 0x91d40000, 0x0000000c, 0x29800001,
+ 0x0000000c, 0x1f800001, 0x00000008, 0x2a000002, 0x00000018, 0x8000ffb5,
+ 0x00000010, 0xb1a0b012, 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c200000,
+ 0x00000008, 0x2c800000, 0x00000008, 0x2d000000, 0x00000010, 0x91d40000,
+ 0x00000008, 0x2d80011c, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
+ 0x0000000f, 0x47600008, 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000,
+ 0x00000000, 0x0f580000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
+ 0x00000000, 0x0b660000, 0x00000000, 0x0d610000, 0x00000018, 0x80000013,
+ 0x0000000f, 0x47600008, 0x0000000b, 0x2fdf0002, 0x00000008, 0x2c800000,
+ 0x00000008, 0x2d000000, 0x00000010, 0x91d40000, 0x00000008, 0x2d80011c,
+ 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000, 0x00000000, 0x0f580000,
+ 0x00000010, 0x91de0000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
+ 0x00000000, 0x0b660000, 0x00000000, 0x0d610000, 0x00000000, 0x02620000,
+ 0x0000000b, 0x2fdf0002, 0x00000000, 0x309a0000, 0x00000000, 0x31040000,
+ 0x00000000, 0x0c961800, 0x00000009, 0x0c99ffff, 0x00000004, 0xcc993400,
+ 0x00000010, 0xb1963202, 0x00000008, 0x0f800000, 0x0000000c, 0x29800001,
+ 0x00000010, 0x00220002, 0x0000000c, 0x29520001, 0x0000000c, 0x29520000,
+ 0x00000008, 0x22000001, 0x0000000c, 0x1f800001, 0x00000000, 0x2adf0000,
+ 0x00000008, 0x2a000003, 0x00000018, 0x8000ff83, 0x00000010, 0xb1a0b01d,
+ 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c200000, 0x00000008, 0x2c8000b0,
+ 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800150,
+ 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800000,
+ 0x00000008, 0x2d000000, 0x00000008, 0x2d800108, 0x00000000, 0x00000000,
+ 0x00000010, 0x91de0000, 0x0000000f, 0x47600008, 0x00000000, 0x060e0000,
+ 0x00000010, 0x001f0000, 0x00000000, 0x0f580000, 0x00000010, 0x91de0000,
+ 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, 0x00000000, 0x0b670000,
+ 0x00000000, 0x0d620000, 0x00000000, 0x0ce71800, 0x00000009, 0x0c99ffff,
+ 0x00000004, 0xcc993400, 0x00000010, 0xb1963220, 0x00000008, 0x0f800000,
+ 0x00000018, 0x8000001e, 0x0000000f, 0x47600008, 0x0000000b, 0x2fdf0002,
+ 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, 0x00000010, 0x91d40000,
+ 0x00000008, 0x2d80012c, 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000,
+ 0x00000000, 0x0f580000, 0x00000010, 0x91de0000, 0x00000000, 0x0a640000,
+ 0x00000000, 0x0ae50000, 0x00000000, 0x0b670000, 0x00000000, 0x0d620000,
+ 0x00000000, 0x02630000, 0x0000000f, 0x47620010, 0x00000000, 0x0ce71800,
+ 0x0000000b, 0x2fdf0002, 0x00000000, 0x311a0000, 0x00000000, 0x31840000,
+ 0x0000000b, 0xc20000ff, 0x00000002, 0x42040000, 0x00000001, 0x31620800,
+ 0x0000000f, 0x020e0010, 0x00000002, 0x31620800, 0x00000009, 0x0c99ffff,
+ 0x00000004, 0xcc993400, 0x00000010, 0xb1963202, 0x00000008, 0x0f800000,
+ 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x0000000c, 0x61420006,
+ 0x00000008, 0x22000008, 0x00000000, 0x2adf0000, 0x00000008, 0x2a000004,
+ 0x00000018, 0x8000ff42, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008,
+ 0x00000010, 0x91a0b008, 0x00000010, 0x91d40000, 0x0000000c, 0x31620018,
+ 0x00000008, 0x2d800001, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
+ 0x00000008, 0xac000001, 0x00000018, 0x8000000e, 0x00000000, 0x0380b000,
+ 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c004000, 0x00000010, 0x91d40000,
+ 0x00000008, 0x2d800101, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
+ 0x0000000c, 0x31620018, 0x00000008, 0x2d800001, 0x00000000, 0x00000000,
+ 0x00000010, 0x91de0000, 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c000e00,
+ 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000008, 0x2a000007,
+ 0x00000018, 0x8000ff27, 0x00000010, 0xb1a0b016, 0x0000000b, 0x2fdf0002,
+ 0x00000000, 0x03d80000, 0x00000000, 0x2c200000, 0x00000008, 0x2c8000b0,
+ 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800150,
+ 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800000,
+ 0x00000008, 0x2d000000, 0x00000008, 0x2d800108, 0x00000008, 0x07000001,
+ 0x00000010, 0xb5de1c00, 0x00000010, 0x2c620002, 0x00000018, 0x8000000a,
+ 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c070000, 0x0000000c, 0x1f800001,
+ 0x00000010, 0x91de0000, 0x00000018, 0x8000ff11, 0x00000008, 0x2c8000b0,
+ 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800108,
+ 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000010, 0x91de0000,
+ 0x00000000, 0x2adf0000, 0x00000008, 0x2a00000a, 0x00000018, 0x8000ff07,
+ 0x00000000, 0x82265600, 0x0000000f, 0x47220008, 0x00000009, 0x070e000f,
+ 0x00000008, 0x070e0008, 0x00000008, 0x02800001, 0x00000007, 0x02851c00,
+ 0x00000008, 0x82850001, 0x00000000, 0x02840a00, 0x00000007, 0x42851c00,
+ 0x00000003, 0xc3aa5200, 0x00000000, 0x03b10e00, 0x00000010, 0x001f0000,
+ 0x0000000f, 0x0f280007, 0x00000007, 0x4b071c00, 0x00000000, 0x00000000,
+ 0x0000000f, 0x0a960003, 0x00000000, 0x0a955c00, 0x00000000, 0x4a005a00,
+ 0x00000000, 0x0c960a00, 0x00000009, 0x0c99ffff, 0x00000008, 0x0d00ffff,
+ 0x00000010, 0xb1963202, 0x00000008, 0x0f800005, 0x00000010, 0x00220020,
+ 0x00000000, 0x02a70000, 0x00000010, 0xb1850002, 0x00000008, 0x82850200,
+ 0x00000000, 0x02000000, 0x00000000, 0x03a60000, 0x00000018, 0x8000004e,
+ 0x00000000, 0x072b0000, 0x00000001, 0x878c1c00, 0x00000000, 0x870e1e00,
+ 0x00000000, 0x860c1e00, 0x00000000, 0x03061e00, 0x00000010, 0xb18e0003,
+ 0x00000018, 0x80000047, 0x00000018, 0x8000fffa, 0x00000010, 0x918c0003,
+ 0x00000010, 0xb1870002, 0x00000018, 0x80000043, 0x00000010, 0x91d40000,
+ 0x0000000c, 0x29800001, 0x00000000, 0x2a860000, 0x00000000, 0x230c0000,
+ 0x00000000, 0x2b070000, 0x00000010, 0xb187000e, 0x00000008, 0x2a000008,
+ 0x00000018, 0x8000003b, 0x00000010, 0x91d40000, 0x00000000, 0x28d18c00,
+ 0x00000000, 0x2a860000, 0x00000000, 0x230c0000, 0x00000000, 0x2b070000,
+ 0x00000018, 0x8000fff8, 0x00000010, 0x91d40000, 0x0000000c, 0x29800001,
+ 0x00000000, 0x2aab0000, 0x00000000, 0xa3265600, 0x00000000, 0x2b000000,
+ 0x0000000c, 0x1f800001, 0x00000008, 0x2a000008, 0x00000018, 0x8000fec8,
+ 0x00000010, 0x91d40000, 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001,
+ 0x00000008, 0x2a000009, 0x00000018, 0x8000fec3, 0x00000010, 0x91d40000,
+ 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000000, 0x29420000,
+ 0x00000008, 0x2a000002, 0x00000018, 0x8000febd, 0x00000018, 0x8000febc,
+ 0x00000010, 0xb1bcb016, 0x0000000b, 0x2fdf0002, 0x00000000, 0x03d80000,
+ 0x00000000, 0x2c3c0000, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008,
+ 0x00000010, 0x91d40000, 0x00000008, 0x2d800150, 0x00000000, 0x00000000,
+ 0x00000010, 0x205f0000, 0x00000008, 0x2c800000, 0x00000008, 0x2d000000,
+ 0x00000008, 0x2d800108, 0x00000008, 0x07000001, 0x00000010, 0xb5de1c00,
+ 0x00000010, 0x2c620002, 0x00000018, 0x8000000a, 0x0000000b, 0x2fdf0002,
+ 0x00000000, 0x2c070000, 0x0000000c, 0x1f800000, 0x00000010, 0x91de0000,
+ 0x00000018, 0x8000fea6, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008,
+ 0x00000010, 0x91d40000, 0x00000008, 0x2d800108, 0x0000000c, 0x29800000,
+ 0x0000000c, 0x1f800000, 0x00000010, 0x91de0000, 0x00000000, 0x2adf0000,
+ 0x00000008, 0x2a000006, 0x00000018, 0x8000fe9c, 0x00000008, 0x03050004,
+ 0x00000006, 0x83040c00, 0x00000008, 0x02850200, 0x00000000, 0x86050c00,
+ 0x00000001, 0x860c0e00, 0x00000008, 0x02040004, 0x00000000, 0x02041800,
+ 0x00000000, 0x83871800, 0x00000018, 0x00020000 };
+
+static u32 bnx2_rv2p_proc2[] = {
+ 0x00000000, 0x2a000000, 0x00000010, 0xb1d40000, 0x00000008, 0x02540003,
+ 0x00000018, 0x00040000, 0x00000018, 0x8000000a, 0x00000018, 0x8000000a,
+ 0x00000018, 0x8000000e, 0x00000018, 0x80000056, 0x00000018, 0x800001b9,
+ 0x00000018, 0x800001e1, 0x00000018, 0x8000019b, 0x00000018, 0x800001f9,
+ 0x00000018, 0x8000019f, 0x00000018, 0x800001a6, 0x00000018, 0x80000000,
+ 0x0000000c, 0x29800001, 0x00000000, 0x2a000000, 0x0000000c, 0x29800000,
+ 0x00000010, 0x20530000, 0x00000018, 0x8000ffee, 0x0000000c, 0x29800001,
+ 0x00000010, 0x91de0000, 0x00000010, 0x001f0000, 0x00000000, 0x2f80aa00,
+ 0x00000000, 0x2a000000, 0x00000000, 0x0d610000, 0x00000000, 0x03620000,
+ 0x00000000, 0x2c400000, 0x00000000, 0x02638c00, 0x00000000, 0x26460000,
+ 0x00000010, 0x00420002, 0x00000008, 0x02040012, 0x00000010, 0xb9060836,
+ 0x00000000, 0x0f580000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
+ 0x00000000, 0x0b660000, 0x00000000, 0x0c000000, 0x00000000, 0x0b800000,
+ 0x00000010, 0x00420009, 0x00000008, 0x0cc60012, 0x00000008, 0x0f800003,
+ 0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000008, 0x27110012,
+ 0x00000000, 0x66900000, 0x00000008, 0xa31b0012, 0x00000018, 0x80000008,
+ 0x00000000, 0x0cc60000, 0x00000008, 0x0f800003, 0x00000000, 0x00000000,
+ 0x00000010, 0x009f0000, 0x00000000, 0x27110000, 0x00000000, 0x66900000,
+ 0x00000000, 0x231b0000, 0x00000010, 0xb197320e, 0x00000000, 0x25960000,
+ 0x00000000, 0x021b0000, 0x00000010, 0x001f0000, 0x00000008, 0x0f800003,
+ 0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000000, 0x22c50800,
+ 0x00000010, 0x009f0000, 0x00000000, 0x27002200, 0x00000000, 0x26802000,
+ 0x00000000, 0x231b0000, 0x0000000c, 0x69520001, 0x00000018, 0x8000fff3,
+ 0x00000010, 0x01130002, 0x00000010, 0xb1980003, 0x00000010, 0x001f0000,
+ 0x00000008, 0x0f800004, 0x00000008, 0x22000003, 0x00000008, 0x2c80000c,
+ 0x00000008, 0x2d00000c, 0x00000010, 0x009f0000, 0x00000000, 0x25960000,
+ 0x0000000c, 0x29800000, 0x00000000, 0x32140000, 0x00000000, 0x32950000,
+ 0x00000000, 0x33160000, 0x00000000, 0x31e32e00, 0x00000008, 0x2d800010,
+ 0x00000010, 0x20530000, 0x00000018, 0x8000ffac, 0x00000000, 0x23000000,
+ 0x00000000, 0x25e60000, 0x00000008, 0x2200000b, 0x0000000c, 0x69520000,
+ 0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000018, 0x8000ffa5,
+ 0x0000000c, 0x29800001, 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000,
+ 0x00000010, 0x001f0000, 0x00000000, 0x02700000, 0x00000000, 0x0d620000,
+ 0x00000000, 0xbb630800, 0x00000000, 0x2a000000, 0x00000009, 0x076000ff,
+ 0x0000000f, 0x2c0e0007, 0x00000008, 0x2c800000, 0x00000008, 0x2d000064,
+ 0x00000008, 0x2d80011c, 0x00000009, 0x06420002, 0x0000000c, 0x61420001,
+ 0x00000000, 0x0f400000, 0x00000000, 0x02d08c00, 0x00000000, 0x23000000,
+ 0x00000004, 0x826da000, 0x00000000, 0x8304a000, 0x00000000, 0x22c50c00,
+ 0x00000000, 0x03760000, 0x00000004, 0x83860a00, 0x00000000, 0x83870c00,
+ 0x00000010, 0x91de0000, 0x00000000, 0x037c0000, 0x00000000, 0x837b0c00,
+ 0x00000001, 0x83060e00, 0x00000000, 0x83870c00, 0x00000000, 0x82850e00,
+ 0x00000010, 0xb1860016, 0x0000000f, 0x47610018, 0x00000000, 0x068e0000,
+ 0x0000000f, 0x47670010, 0x0000000f, 0x47e20010, 0x00000000, 0x870e1e00,
+ 0x00000010, 0xb70e1a10, 0x00000010, 0x0ce7000e, 0x00000008, 0x22000009,
+ 0x00000000, 0x286d0000, 0x0000000f, 0x65680010, 0x00000003, 0xf66c9400,
+ 0x00000010, 0xb972a003, 0x0000000c, 0x73e70019, 0x0000000c, 0x21420004,
+ 0x00000018, 0x8000023f, 0x00000000, 0x37ed0000, 0x0000000c, 0x73e7001a,
+ 0x00000010, 0x20530000, 0x00000008, 0x22000008, 0x0000000c, 0x61420004,
+ 0x00000000, 0x02f60000, 0x00000004, 0x82840a00, 0x00000010, 0xb1840a2b,
+ 0x00000010, 0x2d67000a, 0x00000010, 0xb96d0804, 0x00000004, 0xb6ed0a00,
+ 0x00000000, 0x37ed0000, 0x00000018, 0x80000029, 0x0000000c, 0x61420000,
+ 0x00000000, 0x37040000, 0x00000000, 0x37850000, 0x0000000c, 0x33e7001a,
+ 0x00000018, 0x80000024, 0x00000010, 0xb96d0809, 0x00000004, 0xb6ed0a00,
+ 0x00000000, 0x036d0000, 0x00000004, 0xb76e0c00, 0x00000010, 0x91ee0c1f,
+ 0x0000000c, 0x73e7001a, 0x00000004, 0xb6ef0c00, 0x00000000, 0x37ed0000,
+ 0x00000018, 0x8000001b, 0x0000000c, 0x61420000, 0x00000010, 0xb7ee0a05,
+ 0x00000010, 0xb96f0815, 0x00000003, 0xb76e0800, 0x00000004, 0xb7ef0a00,
+ 0x00000018, 0x80000015, 0x00000010, 0x0ce7000c, 0x00000008, 0x22000009,
+ 0x00000000, 0x286d0000, 0x0000000f, 0x65680010, 0x00000003, 0xf66c9400,
+ 0x00000010, 0xb972a003, 0x0000000c, 0x73e70019, 0x0000000c, 0x21420004,
+ 0x00000018, 0x80000215, 0x00000010, 0x20530000, 0x00000008, 0x22000008,
+ 0x0000000c, 0x61420004, 0x00000000, 0x37040000, 0x00000000, 0x37850000,
+ 0x00000000, 0x036d0000, 0x00000003, 0xb8f10c00, 0x00000018, 0x80000004,
+ 0x00000000, 0x02840000, 0x00000002, 0x21421800, 0x0000000c, 0x61420000,
+ 0x00000000, 0x286d0000, 0x0000000f, 0x65ed0010, 0x00000009, 0x266dffff,
+ 0x00000000, 0x23000000, 0x00000010, 0xb1840a3d, 0x00000010, 0x01420002,
+ 0x00000004, 0xb8f10a00, 0x00000003, 0x83760a00, 0x00000010, 0xb8040c39,
+ 0x00000010, 0xb7e6080a, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
+ 0x00000009, 0x0c68ffff, 0x00000009, 0x0b67ffff, 0x00000000, 0x0be60000,
+ 0x00000000, 0x0c840000, 0x00000010, 0xb197320c, 0x00000008, 0x0f800002,
+ 0x00000018, 0x8000000a, 0x00000000, 0x0a6a0000, 0x00000000, 0x0aeb0000,
+ 0x00000000, 0x0c000000, 0x00000009, 0x0b6cffff, 0x00000000, 0x0be90000,
+ 0x00000000, 0x0c840000, 0x00000010, 0xb1973203, 0x00000008, 0x0f800002,
+ 0x00000018, 0x80000001, 0x00000010, 0x001f0000, 0x00000000, 0x0c860000,
+ 0x00000000, 0x06980000, 0x00000008, 0x0f800003, 0x00000000, 0x00000000,
+ 0x00000010, 0x009f0000, 0x00000010, 0xb1973210, 0x00000000, 0x231b0000,
+ 0x00000000, 0x02043600, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
+ 0x00000009, 0x2607ffff, 0x00000000, 0x27111a00, 0x00000000, 0x66900000,
+ 0x0000000c, 0x29000000, 0x00000018, 0x800001de, 0x00000000, 0x06980000,
+ 0x00000010, 0x20530000, 0x00000000, 0x22c58c00, 0x00000010, 0x001f0000,
+ 0x00000008, 0x0f800003, 0x00000018, 0x8000fff0, 0x00000000, 0x02043600,
+ 0x00000000, 0x231b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
+ 0x00000009, 0x2607ffff, 0x00000000, 0x27111a00, 0x00000000, 0x66900000,
+ 0x0000000c, 0x29000000, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
+ 0x00000000, 0x32140000, 0x00000000, 0x32950000, 0x00000005, 0x73e72c00,
+ 0x00000005, 0x74683000, 0x00000000, 0x33170000, 0x00000018, 0x80000138,
+ 0x00000010, 0x91c60004, 0x00000008, 0x07000004, 0x00000010, 0xb1c41c02,
+ 0x00000010, 0x91840a04, 0x00000018, 0x800001c3, 0x00000010, 0x20530000,
+ 0x00000000, 0x22c58c00, 0x00000010, 0xb1840a8e, 0x0000000c, 0x21420006,
+ 0x00000010, 0x0ce7001a, 0x0000000f, 0x43680010, 0x00000000, 0x03f30c00,
+ 0x00000010, 0x91870850, 0x0000000f, 0x46ec0010, 0x00000010, 0xb68d0c4e,
+ 0x00000000, 0x838d0c00, 0x00000000, 0xa3050800, 0x00000001, 0xa3460e00,
+ 0x00000000, 0x02048c00, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
+ 0x00000010, 0x001f0000, 0x00000008, 0x22000008, 0x00000003, 0x8384a000,
+ 0x0000000f, 0x65870010, 0x00000009, 0x2607ffff, 0x00000000, 0x27750c00,
+ 0x00000000, 0x66f40000, 0x0000000c, 0x29000000, 0x00000018, 0x800001aa,
+ 0x00000000, 0x03068c00, 0x00000003, 0xf4680c00, 0x00000010, 0x20530000,
+ 0x00000000, 0x22c58c00, 0x00000018, 0x8000ffe5, 0x00000000, 0x39760000,
+ 0x00000000, 0x39840000, 0x0000000c, 0x33e70019, 0x00000010, 0x001f0000,
+ 0x00000000, 0x031e0000, 0x00000000, 0x0760fe00, 0x0000000f, 0x0f0e0007,
+ 0x00000000, 0x83850800, 0x00000000, 0x0a7d0000, 0x00000000, 0x0afe0000,
+ 0x00000000, 0x0b7f0000, 0x00000000, 0x0d7a0000, 0x00000000, 0x0c000000,
+ 0x00000000, 0x0bfc0000, 0x00000000, 0x0c970e00, 0x00000008, 0x0f800003,
+ 0x0000000f, 0x47670010, 0x00000008, 0x070e0001, 0x0000000b, 0xc38000ff,
+ 0x00000002, 0x43870000, 0x00000001, 0x33e70e00, 0x0000000f, 0x038e0010,
+ 0x00000002, 0x33e70e00, 0x00000000, 0x28f30000, 0x00000010, 0x009f0000,
+ 0x00000000, 0x02043600, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
+ 0x00000008, 0x22000006, 0x00000000, 0x231b0000, 0x00000000, 0x23ff0000,
+ 0x00000000, 0x241b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
+ 0x00000009, 0x2607ffff, 0x00000000, 0x27110000, 0x00000000, 0x26900000,
+ 0x0000000c, 0x29000000, 0x00000018, 0x8000017e, 0x00000003, 0xf4683600,
+ 0x00000000, 0x3a100000, 0x00000000, 0x3a910000, 0x00000003, 0xf66c2400,
+ 0x00000010, 0x001f0000, 0x00000010, 0xb1923604, 0x00000008, 0x0f800004,
+ 0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000000, 0x3e170000,
+ 0x00000000, 0x3e940000, 0x00000000, 0x3f150000, 0x00000000, 0x3f960000,
+ 0x00000010, 0x001f0000, 0x00000000, 0x0f060000, 0x00000010, 0x20530000,
+ 0x00000000, 0x22c53600, 0x00000018, 0x8000ffac, 0x00000010, 0x001f0000,
+ 0x00000000, 0x031e0000, 0x00000000, 0x83850800, 0x00000009, 0x076000ff,
+ 0x0000000f, 0x0f0e0007, 0x00000000, 0x0c000000, 0x00000000, 0x0a7d0000,
+ 0x00000000, 0x0afe0000, 0x00000000, 0x0b7f0000, 0x00000000, 0x0d7a0000,
+ 0x00000000, 0x0bfc0000, 0x00000000, 0x0c970e00, 0x00000008, 0x0f800003,
+ 0x0000000f, 0x47670010, 0x00000008, 0x070e0001, 0x0000000b, 0xc38000ff,
+ 0x00000002, 0x43870000, 0x00000001, 0x33e70e00, 0x0000000f, 0x038e0010,
+ 0x00000002, 0x33e70e00, 0x00000000, 0x39840000, 0x00000003, 0xb9720800,
+ 0x00000000, 0x28f30000, 0x0000000f, 0x65680010, 0x00000010, 0x009f0000,
+ 0x00000000, 0x02043600, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
+ 0x00000008, 0x22000007, 0x00000000, 0x231b0000, 0x00000000, 0x23ff0000,
+ 0x00000000, 0x241b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
+ 0x00000009, 0x2607ffff, 0x00000000, 0x27110000, 0x00000000, 0x26900000,
+ 0x0000000c, 0x29000000, 0x00000018, 0x80000145, 0x00000003, 0xf4683600,
+ 0x00000000, 0x3a100000, 0x00000000, 0x3a910000, 0x00000003, 0xf66c2400,
+ 0x00000010, 0x001f0000, 0x00000010, 0xb1923604, 0x00000008, 0x0f800004,
+ 0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000000, 0x3e170000,
+ 0x00000000, 0x3e940000, 0x00000000, 0x3f150000, 0x00000000, 0x3f960000,
+ 0x00000010, 0x001f0000, 0x00000000, 0x0f060000, 0x00000010, 0x20530000,
+ 0x00000000, 0x22c53600, 0x00000018, 0x8000ff73, 0x00000010, 0x0ce70005,
+ 0x00000008, 0x2c80000c, 0x00000008, 0x2d000070, 0x00000008, 0x2d800010,
+ 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000018, 0x8000011d,
+ 0x00000000, 0x2c1e0000, 0x00000008, 0x2c8000b8, 0x00000008, 0x2d000010,
+ 0x00000008, 0x2d800048, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
+ 0x00000018, 0x8000fe5d, 0x0000000c, 0x29800001, 0x00000000, 0x2a000000,
+ 0x00000010, 0x001f0000, 0x00000000, 0x0f008000, 0x00000008, 0x0f800007,
+ 0x00000018, 0x80000006, 0x0000000c, 0x29800001, 0x00000000, 0x2a000000,
+ 0x00000010, 0x001f0000, 0x0000000f, 0x0f470007, 0x00000008, 0x0f800008,
+ 0x00000018, 0x80000119, 0x00000010, 0x20530000, 0x00000018, 0x8000fe4f,
+ 0x0000000c, 0x29800001, 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000,
+ 0x00000000, 0x2a000000, 0x00000009, 0x0261ffff, 0x0000000d, 0x70e10001,
+ 0x00000018, 0x80000101, 0x00000000, 0x2c400000, 0x00000008, 0x2c8000c4,
+ 0x00000008, 0x2d00001c, 0x00000008, 0x2d800001, 0x00000005, 0x70e10800,
+ 0x00000010, 0x91de0000, 0x00000018, 0x8000fe41, 0x0000000c, 0x29800001,
+ 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000, 0x00000010, 0x001f0000,
+ 0x00000000, 0x02700000, 0x00000000, 0x0d620000, 0x00000000, 0xbb630800,
+ 0x00000000, 0x2a000000, 0x00000000, 0x0f400000, 0x00000000, 0x2c400000,
+ 0x0000000c, 0x73e7001b, 0x00000010, 0x0ce7000e, 0x00000000, 0x286d0000,
+ 0x0000000f, 0x65ed0010, 0x00000009, 0x266dffff, 0x00000018, 0x80000069,
+ 0x00000008, 0x02000004, 0x00000010, 0x91c40803, 0x00000018, 0x800000f6,
+ 0x00000010, 0x20530000, 0x00000018, 0x800000e5, 0x00000008, 0x2c8000b8,
+ 0x00000008, 0x2d000010, 0x00000008, 0x2d800048, 0x00000018, 0x80000005,
+ 0x00000008, 0x2c8000c4, 0x00000008, 0x2d00001c, 0x00000008, 0x2d800001,
+ 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800048,
+ 0x00000008, 0x2d000068, 0x00000008, 0x2d800104, 0x00000000, 0x00000000,
+ 0x00000010, 0x91de0000, 0x00000000, 0x27f60000, 0x00000010, 0xb87a9e04,
+ 0x00000008, 0x2200000d, 0x00000018, 0x800000e2, 0x00000010, 0x20530000,
+ 0x00000018, 0x8000fe18, 0x0000000c, 0x29800001, 0x00000010, 0x91de0000,
+ 0x00000000, 0x2fd50000, 0x00000010, 0x001f0000, 0x00000000, 0x02700000,
+ 0x00000000, 0x0d620000, 0x00000000, 0xbb630800, 0x00000000, 0x2a000000,
+ 0x00000010, 0x0e670011, 0x00000000, 0x286d0000, 0x0000000f, 0x65ed0010,
+ 0x00000009, 0x266dffff, 0x00000004, 0xb8f1a000, 0x00000000, 0x0f400000,
+ 0x0000000c, 0x73e7001c, 0x00000018, 0x80000040, 0x00000008, 0x02000004,
+ 0x00000010, 0x91c40802, 0x00000018, 0x800000cd, 0x00000000, 0x2c1e0000,
+ 0x00000008, 0x2c8000b8, 0x00000008, 0x2d000010, 0x00000008, 0x2d800048,
+ 0x00000010, 0x20530000, 0x00000010, 0x91de0000, 0x00000018, 0x8000fdfe,
+ 0x0000000c, 0x29800001, 0x00000000, 0x03550000, 0x00000000, 0x06460000,
+ 0x00000000, 0x03d60000, 0x00000000, 0x2a000000, 0x0000000f, 0x0f480007,
+ 0x00000010, 0xb18c0027, 0x0000000f, 0x47420008, 0x00000009, 0x070e000f,
+ 0x00000008, 0x070e0008, 0x00000010, 0x001f0000, 0x00000008, 0x09000001,
+ 0x00000007, 0x09121c00, 0x00000003, 0xcbca9200, 0x00000000, 0x0b97a200,
+ 0x00000007, 0x4b171c00, 0x0000000f, 0x0a960003, 0x00000000, 0x0a959c00,
+ 0x00000000, 0x4a009a00, 0x00000008, 0x82120001, 0x00000001, 0x0c170800,
+ 0x00000000, 0x02180000, 0x00000000, 0x0c971800, 0x00000008, 0x0d00ffff,
+ 0x00000008, 0x0f800006, 0x0000000c, 0x29000000, 0x00000008, 0x22000001,
+ 0x00000000, 0x22c50c00, 0x00000010, 0x009f0000, 0x00000010, 0xb197320b,
+ 0x00000000, 0x231b0000, 0x00000000, 0x27110800, 0x00000000, 0x66900000,
+ 0x00000018, 0x800000a4, 0x00000000, 0x02180000, 0x00000010, 0x20530000,
+ 0x00000000, 0x22c53600, 0x00000010, 0x001f0000, 0x00000008, 0x0f800006,
+ 0x00000018, 0x8000fff5, 0x00000010, 0x91870002, 0x00000008, 0x2200000a,
+ 0x00000000, 0x231b0000, 0x00000000, 0x27110800, 0x00000000, 0x66900000,
+ 0x00000018, 0x80000098, 0x00000008, 0x0200000a, 0x00000010, 0x91c40804,
+ 0x00000010, 0x02c20003, 0x00000010, 0x001f0000, 0x00000008, 0x0f800008,
+ 0x00000010, 0x20530000, 0x00000018, 0x8000fdc9, 0x00000000, 0x06820000,
+ 0x00000010, 0x001f0000, 0x00000010, 0x0ce70028, 0x00000000, 0x03720000,
+ 0x00000000, 0xa8760c00, 0x00000000, 0x0cf60000, 0x00000010, 0xb8723224,
+ 0x00000000, 0x03440000, 0x00000008, 0x22000010, 0x00000000, 0x03ca0000,
+ 0x0000000f, 0x65680010, 0x00000000, 0x0bcf0000, 0x00000000, 0x27f20000,
+ 0x00000010, 0xb7ef3203, 0x0000000c, 0x21420004, 0x0000000c, 0x73e70019,
+ 0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x00000018, 0x8000007e,
+ 0x00000004, 0xb9723200, 0x00000010, 0x20530000, 0x00000000, 0x22060000,
+ 0x0000000c, 0x61420004, 0x00000000, 0x25070000, 0x00000000, 0x27970000,
+ 0x00000000, 0x290e0000, 0x00000010, 0x0ce70010, 0x00000010, 0xb873320f,
+ 0x0000000f, 0x436c0010, 0x00000000, 0x03f30c00, 0x00000000, 0x03f30000,
+ 0x00000000, 0x83990e00, 0x00000001, 0x83860e00, 0x00000000, 0x83060e00,
+ 0x00000003, 0xf66c0c00, 0x00000000, 0x39f30e00, 0x00000000, 0x3af50e00,
+ 0x00000000, 0x7a740000, 0x0000000f, 0x43680010, 0x00000001, 0x83860e00,
+ 0x00000000, 0x83060e00, 0x00000003, 0xf4680c00, 0x00000000, 0x286d0000,
+ 0x00000000, 0x03690000, 0x00000010, 0xb1f60c54, 0x00000000, 0x0a6a0000,
+ 0x00000000, 0x0aeb0000, 0x00000009, 0x0b6cffff, 0x00000000, 0x0c000000,
+ 0x00000000, 0x0be90000, 0x00000003, 0x8cf6a000, 0x0000000c, 0x09800002,
+ 0x00000010, 0x009f0000, 0x00000010, 0xb8173209, 0x00000000, 0x35140000,
+ 0x00000000, 0x35950000, 0x00000005, 0x766c2c00, 0x00000000, 0x34970000,
+ 0x00000004, 0xb8f12e00, 0x00000010, 0x001f0000, 0x00000008, 0x0f800004,
+ 0x00000018, 0x8000fff7, 0x00000000, 0x03e90000, 0x00000010, 0xb8f6a01a,
+ 0x00000010, 0x20130019, 0x00000010, 0xb1f10e18, 0x00000000, 0x83973200,
+ 0x00000000, 0x38700e00, 0x00000000, 0xbb760e00, 0x00000000, 0x37d00000,
+ 0x0000000c, 0x73e7001a, 0x00000003, 0xb8f1a000, 0x00000000, 0x32140000,
+ 0x00000000, 0x32950000, 0x00000005, 0x73e72c00, 0x00000000, 0x33190000,
+ 0x00000005, 0x74680000, 0x00000010, 0x0ce7000d, 0x00000008, 0x22000009,
+ 0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x0000000c, 0x73e70019,
+ 0x0000000f, 0x65680010, 0x0000000c, 0x21420004, 0x00000018, 0x8000003c,
+ 0x00000010, 0x20530000, 0x0000000c, 0x61420004, 0x00000000, 0x290e0000,
+ 0x00000018, 0x80000002, 0x00000010, 0x91973206, 0x00000000, 0x35140000,
+ 0x00000000, 0x35950000, 0x00000005, 0x766c2c00, 0x00000000, 0x34990000,
+ 0x00000004, 0xb8f13200, 0x00000000, 0x83690c00, 0x00000010, 0xb1860013,
+ 0x00000000, 0x28e90000, 0x00000008, 0x22000004, 0x00000000, 0x23ec0000,
+ 0x00000000, 0x03690000, 0x00000010, 0xb8660c07, 0x00000009, 0x036cffff,
+ 0x00000000, 0x326a0000, 0x00000000, 0x32eb0000, 0x00000005, 0x73e70c00,
+ 0x00000000, 0x33690000, 0x00000005, 0x74680000, 0x0000000c, 0x73e7001c,
+ 0x00000000, 0x03690000, 0x00000010, 0xb1f60c12, 0x00000010, 0xb1d00c11,
+ 0x0000000c, 0x21420005, 0x0000000c, 0x33e7001c, 0x00000018, 0x8000000e,
+ 0x00000010, 0x2e67000d, 0x00000000, 0x03690000, 0x00000010, 0xb1f60c0b,
+ 0x00000010, 0xb1d00c0a, 0x00000000, 0x03440000, 0x00000008, 0x2200000c,
+ 0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x00000018, 0x80000015,
+ 0x0000000c, 0x33e7001c, 0x00000010, 0x20530000, 0x00000000, 0x22060000,
+ 0x00000000, 0x290e0000, 0x00000018, 0x000d0000, 0x00000000, 0x06820000,
+ 0x00000010, 0x2de7000d, 0x00000010, 0x0ce7000c, 0x00000000, 0x27f20000,
+ 0x00000010, 0xb96d9e0a, 0x00000000, 0xa86d9e00, 0x00000009, 0x0361ffff,
+ 0x00000010, 0xb7500c07, 0x00000008, 0x2200000f, 0x0000000f, 0x65680010,
+ 0x00000000, 0x29000000, 0x00000018, 0x80000004, 0x0000000c, 0x33e7001b,
+ 0x00000010, 0x20530000, 0x00000018, 0x000d0000, 0x00000000, 0x2b820000,
+ 0x00000010, 0x20d2002f, 0x00000010, 0x0052002e, 0x00000009, 0x054e0007,
+ 0x00000010, 0xb18a002c, 0x00000000, 0x050a8c00, 0x00000008, 0x850a0008,
+ 0x00000010, 0x918a0029, 0x00000003, 0xc5008800, 0x00000008, 0xa3460001,
+ 0x00000010, 0xb1c60007, 0x00000008, 0x22000001, 0x0000000c, 0x29800000,
+ 0x00000010, 0x20530000, 0x00000000, 0x274e8c00, 0x00000000, 0x66cd0000,
+ 0x00000000, 0x22c58c00, 0x00000008, 0x22000014, 0x00000003, 0x22c58e00,
+ 0x00000003, 0x23c58e00, 0x00000003, 0x22c58e00, 0x00000003, 0x26cd9e00,
+ 0x00000003, 0x27cd9e00, 0x00000003, 0x26cd9e00, 0x00000003, 0x274ea000,
+ 0x00000003, 0x284ea000, 0x00000003, 0x274ea000, 0x0000000c, 0x69520000,
+ 0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000003, 0x22c58e00,
+ 0x00000003, 0x23c58e00, 0x00000003, 0x22c58e00, 0x00000003, 0x26cd9e00,
+ 0x00000003, 0x27cd9e00, 0x00000003, 0x26cd9e00, 0x00000003, 0x274ea000,
+ 0x00000003, 0x284ea000, 0x00000003, 0x274ea000, 0x00000000, 0xa2c58c00,
+ 0x00000000, 0xa74e8c00, 0x00000000, 0xe6cd0000, 0x0000000f, 0x620a0010,
+ 0x00000008, 0x23460001, 0x0000000c, 0x29800000, 0x00000010, 0x20530000,
+ 0x0000000c, 0x29520000, 0x00000018, 0x80000002, 0x0000000c, 0x29800000,
+ 0x00000018, 0x00570000 };
+
+static const int bnx2_TPAT_b06FwReleaseMajor = 0x1;
+static const int bnx2_TPAT_b06FwReleaseMinor = 0x0;
+static const int bnx2_TPAT_b06FwReleaseFix = 0x0;
+static const u32 bnx2_TPAT_b06FwStartAddr = 0x08000860;
+static const u32 bnx2_TPAT_b06FwTextAddr = 0x08000800;
+static const int bnx2_TPAT_b06FwTextLen = 0x122c;
+static const u32 bnx2_TPAT_b06FwDataAddr = 0x08001a60;
+static const int bnx2_TPAT_b06FwDataLen = 0x0;
+static const u32 bnx2_TPAT_b06FwRodataAddr = 0x00000000;
+static const int bnx2_TPAT_b06FwRodataLen = 0x0;
+static const u32 bnx2_TPAT_b06FwBssAddr = 0x08001aa0;
+static const int bnx2_TPAT_b06FwBssLen = 0x250;
+static const u32 bnx2_TPAT_b06FwSbssAddr = 0x08001a60;
+static const int bnx2_TPAT_b06FwSbssLen = 0x34;
+static u32 bnx2_TPAT_b06FwText[(0x122c/4) + 1] = {
+ 0x0a000218, 0x00000000, 0x00000000, 0x0000000d, 0x74706174, 0x20322e35,
+ 0x2e313100, 0x02050b01, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800,
+ 0x24421a60, 0x3c030800, 0x24631cf0, 0xac400000, 0x0043202b, 0x1480fffd,
+ 0x24420004, 0x3c1d0800, 0x37bd2ffc, 0x03a0f021, 0x3c100800, 0x26100860,
+ 0x3c1c0800, 0x279c1a60, 0x0e000546, 0x00000000, 0x0000000d, 0x8f820010,
+ 0x8c450008, 0x24030800, 0xaf430178, 0x97430104, 0x3c020008, 0xaf420140,
+ 0x8f820024, 0x30420001, 0x10400007, 0x3069ffff, 0x24020002, 0x2523fffe,
+ 0xa7420146, 0xa7430148, 0x0a000242, 0x3c020800, 0xa7400146, 0x3c020800,
+ 0x8c43083c, 0x1460000e, 0x24020f00, 0x8f820024, 0x30430020, 0x0003182b,
+ 0x00031823, 0x30650009, 0x30420c00, 0x24030400, 0x14430002, 0x34a40001,
+ 0x34a40005, 0xa744014a, 0x0a000264, 0x3c020800, 0x8f830014, 0x14620008,
+ 0x00000000, 0x8f820024, 0x30420020, 0x0002102b, 0x00021023, 0x3042000d,
+ 0x0a000262, 0x34420005, 0x8f820024, 0x30420020, 0x0002102b, 0x00021023,
+ 0x30420009, 0x34420001, 0xa742014a, 0x3c020800, 0x8c430820, 0x8f840024,
+ 0x3c020048, 0x00621825, 0x30840006, 0x24020002, 0x1082000d, 0x2c820003,
+ 0x50400005, 0x24020004, 0x10800012, 0x3c020001, 0x0a000284, 0x00000000,
+ 0x10820007, 0x24020006, 0x1482000f, 0x3c020111, 0x0a00027c, 0x00621025,
+ 0x0a00027b, 0x3c020101, 0x3c020011, 0x00621025, 0x24030001, 0xaf421000,
+ 0xaf830020, 0x0a000284, 0x00000000, 0x00621025, 0xaf421000, 0xaf800020,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8f830020, 0x1060003f,
+ 0x3c048000, 0x8f421000, 0x00441024, 0x1040fffd, 0x00000000, 0x10600039,
+ 0x00000000, 0x8f421000, 0x3c030020, 0x00431024, 0x10400034, 0x00000000,
+ 0x97421014, 0x14400031, 0x00000000, 0x97421008, 0x8f840010, 0x24420006,
+ 0x00024082, 0x00081880, 0x00643821, 0x8ce50000, 0x30430003, 0x30420001,
+ 0x10400004, 0x00000000, 0x0000000d, 0x0a0002c3, 0x00081080, 0x5460000f,
+ 0x30a5ffff, 0x3c06ffff, 0x00a62824, 0x0005182b, 0x00a61026, 0x0002102b,
+ 0x00621824, 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x240001fb,
+ 0x8ce20000, 0x0a0002c2, 0x00462825, 0x0005182b, 0x38a2ffff, 0x0002102b,
+ 0x00621824, 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x24000205,
+ 0x8ce20000, 0x3445ffff, 0x00081080, 0x00441021, 0x3c030800, 0xac450000,
+ 0x8c620830, 0x24420001, 0xac620830, 0x8f840018, 0x01202821, 0x24820008,
+ 0x30421fff, 0x24434000, 0x0343d821, 0x30a30007, 0xaf84000c, 0xaf820018,
+ 0xaf420084, 0x10600002, 0x24a20007, 0x3045fff8, 0x8f820030, 0x8f840000,
+ 0x00451821, 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023,
+ 0xaf820030, 0x8f840030, 0x34028000, 0x00821021, 0x03421821, 0x3c021000,
+ 0xaf830010, 0xaf440080, 0x03e00008, 0xaf420178, 0x8f830024, 0x27bdffe0,
+ 0xafbf0018, 0xafb10014, 0x30620200, 0x14400004, 0xafb00010, 0x0000000d,
+ 0x00000000, 0x24000242, 0x00031a82, 0x30630003, 0x000310c0, 0x00431021,
+ 0x00021080, 0x00431021, 0x00021080, 0x3c030800, 0x24631aa0, 0x00438821,
+ 0x8e240000, 0x10800004, 0x00000000, 0x0000000d, 0x00000000, 0x2400024d,
+ 0x8f850010, 0x24020001, 0xae220000, 0x8ca70008, 0xa2200007, 0x8f620004,
+ 0x26300014, 0x02002021, 0x00021402, 0xa2220004, 0x304600ff, 0x24c60005,
+ 0x0e000673, 0x00063082, 0x8f620004, 0xa6220008, 0x8f430108, 0x3c021000,
+ 0x00621824, 0x10600008, 0x00000000, 0x97420104, 0x92230007, 0x2442ffec,
+ 0x3045ffff, 0x34630002, 0x0a000321, 0xa2230007, 0x97420104, 0x2442fff0,
+ 0x3045ffff, 0x8f620004, 0x3042ffff, 0x2c420013, 0x54400005, 0x92230007,
+ 0x92220007, 0x34420001, 0xa2220007, 0x92230007, 0x24020001, 0x10620009,
+ 0x28620002, 0x14400014, 0x24020002, 0x10620012, 0x24020003, 0x1062000a,
+ 0x00000000, 0x0a000342, 0x00000000, 0x8f820010, 0x8c43000c, 0x3c04ffff,
+ 0x00641824, 0x00651825, 0x0a000342, 0xac43000c, 0x8f820010, 0x8c430010,
+ 0x3c04ffff, 0x00641824, 0x00651825, 0xac430010, 0x8f620004, 0x3042ffff,
+ 0x24420002, 0x00021083, 0xa2220005, 0x304500ff, 0x8f820010, 0x3c04ffff,
+ 0x00052880, 0x00a22821, 0x8ca70000, 0x96220008, 0x97430104, 0x00e42024,
+ 0x24420002, 0x00621823, 0x00833825, 0xaca70000, 0x92240005, 0x00041080,
+ 0x02021021, 0x90430000, 0x3c05fff6, 0x34a5ffff, 0x3063000f, 0x00832021,
+ 0xa2240006, 0x308200ff, 0x24420003, 0x00021080, 0x02021021, 0x8c460000,
+ 0x308300ff, 0x8f820010, 0x3c04ff3f, 0x00031880, 0x00c53824, 0x00621821,
+ 0xae26000c, 0xac67000c, 0x8e22000c, 0x92230006, 0x3484ffff, 0x00441024,
+ 0x24630003, 0x00031880, 0x02031821, 0x00e42024, 0xae22000c, 0xac640000,
+ 0x92220006, 0x24420004, 0x00021080, 0x02021021, 0x94470002, 0xac470000,
+ 0x92230006, 0x8f820010, 0x00031880, 0x00621821, 0x24020010, 0xac670010,
+ 0x24030002, 0xa7420140, 0xa7400142, 0xa7400144, 0xa7430146, 0x97420104,
+ 0x24030001, 0x2442fffe, 0xa7420148, 0xa743014a, 0x8f820024, 0x24030002,
+ 0x30440006, 0x1083000d, 0x2c820003, 0x10400005, 0x24020004, 0x10800011,
+ 0x3c020009, 0x0a0003a5, 0x00000000, 0x10820007, 0x24020006, 0x1482000d,
+ 0x3c020119, 0x0a00039f, 0x24030001, 0x0a00039e, 0x3c020109, 0x3c020019,
+ 0x24030001, 0xaf421000, 0xaf830020, 0x0a0003a5, 0x00000000, 0xaf421000,
+ 0xaf800020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x92220004,
+ 0x24030008, 0x8f840020, 0x24420002, 0x30420007, 0x00621823, 0x30630007,
+ 0x10800006, 0xae230010, 0x3c038000, 0x8f421000, 0x00431024, 0x1040fffd,
+ 0x00000000, 0x8f820018, 0xaf82000c, 0x24420010, 0x30421fff, 0xaf820018,
+ 0xaf420084, 0x97430104, 0x24424000, 0x0342d821, 0x3063ffff, 0x30620007,
+ 0x10400002, 0x24620007, 0x3043fff8, 0x8f820030, 0x8f840000, 0x00431821,
+ 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, 0xaf820030,
+ 0x8f840030, 0x34028000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x00821021,
+ 0x03421821, 0x3c021000, 0xaf830010, 0xaf440080, 0xaf420178, 0x03e00008,
+ 0x27bd0020, 0x8f830024, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0x30620200,
+ 0x14400004, 0xafb00010, 0x0000000d, 0x00000000, 0x240002e4, 0x00031a82,
+ 0x30630003, 0x000310c0, 0x00431021, 0x00021080, 0x00431021, 0x00021080,
+ 0x3c030800, 0x24631aa0, 0x00438021, 0x8e040000, 0x14800004, 0x00000000,
+ 0x0000000d, 0x00000000, 0x240002e9, 0x8f620004, 0x04410008, 0x26050014,
+ 0x92020006, 0x8e03000c, 0x24420003, 0x00021080, 0x00a21021, 0xac430000,
+ 0xae000000, 0x92020005, 0x24420001, 0x00021080, 0x00a21021, 0x8c430000,
+ 0x3c040001, 0x00641821, 0xac430000, 0x92060004, 0x27710008, 0x02202021,
+ 0x24c60005, 0x0e000673, 0x00063082, 0x92040006, 0x3c057fff, 0x8f620004,
+ 0x00042080, 0x00912021, 0x8c830004, 0x34a5ffff, 0x00451024, 0x00621821,
+ 0xac830004, 0x92050005, 0x3c07ffff, 0x92040004, 0x00052880, 0x00b12821,
+ 0x8ca30000, 0x97420104, 0x96060008, 0x00671824, 0x00441021, 0x00461023,
+ 0x3042ffff, 0x00621825, 0xaca30000, 0x92030007, 0x24020001, 0x1062000a,
+ 0x28620002, 0x1440001d, 0x2402000a, 0x24020002, 0x10620019, 0x24020003,
+ 0x1062000e, 0x2402000a, 0x0a000447, 0x00000000, 0x92020004, 0x97430104,
+ 0x8e24000c, 0x00621821, 0x2463fff2, 0x3063ffff, 0x00872024, 0x00832025,
+ 0xae24000c, 0x0a000447, 0x2402000a, 0x92020004, 0x97430104, 0x8e240010,
+ 0x00621821, 0x2463ffee, 0x3063ffff, 0x00872024, 0x00832025, 0xae240010,
+ 0x2402000a, 0xa7420140, 0x96030012, 0x8f840024, 0xa7430142, 0x92020004,
+ 0xa7420144, 0xa7400146, 0x97430104, 0x30840006, 0x24020001, 0xa7430148,
+ 0xa742014a, 0x24020002, 0x1082000d, 0x2c820003, 0x10400005, 0x24020004,
+ 0x10800011, 0x3c020041, 0x0a00046c, 0x00000000, 0x10820007, 0x24020006,
+ 0x1482000d, 0x3c020151, 0x0a000466, 0x24030001, 0x0a000465, 0x3c020141,
+ 0x3c020051, 0x24030001, 0xaf421000, 0xaf830020, 0x0a00046c, 0x00000000,
+ 0xaf421000, 0xaf800020, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x8f820020, 0x8f840018, 0x10400006, 0x92030004, 0x3c058000, 0x8f421000,
+ 0x00451024, 0x1040fffd, 0x00000000, 0x2463000a, 0x30620007, 0x10400002,
+ 0x24620007, 0x304303f8, 0x00831021, 0x30421fff, 0xaf84000c, 0xaf820018,
+ 0xaf420084, 0x97430104, 0x24424000, 0x0342d821, 0x3063ffff, 0x30620007,
+ 0x10400002, 0x24620007, 0x3043fff8, 0x8f820030, 0x8f840000, 0x00431821,
+ 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, 0xaf820030,
+ 0x8f840030, 0x34028000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x00821021,
+ 0x03421821, 0x3c021000, 0xaf830010, 0xaf440080, 0xaf420178, 0x03e00008,
+ 0x27bd0020, 0x8f620000, 0x97430104, 0x3c048000, 0x3045ffff, 0x3066ffff,
+ 0x8f420178, 0x00441024, 0x1440fffd, 0x2402000a, 0x30a30007, 0xa7420140,
+ 0x24020008, 0x00431023, 0x30420007, 0x24a3fffe, 0xa7420142, 0xa7430144,
+ 0xa7400146, 0xa7460148, 0x8f420108, 0x8f830024, 0x30420020, 0x0002102b,
+ 0x00021023, 0x30420009, 0x34420001, 0x30630006, 0xa742014a, 0x24020002,
+ 0x1062000d, 0x2c620003, 0x10400005, 0x24020004, 0x10600011, 0x3c020041,
+ 0x0a0004d6, 0x00000000, 0x10620007, 0x24020006, 0x1462000d, 0x3c020151,
+ 0x0a0004d0, 0x24030001, 0x0a0004cf, 0x3c020141, 0x3c020051, 0x24030001,
+ 0xaf421000, 0xaf830020, 0x0a0004d6, 0x00000000, 0xaf421000, 0xaf800020,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8f820020, 0x24a30008,
+ 0x8f850018, 0x10400006, 0x30c6ffff, 0x3c048000, 0x8f421000, 0x00441024,
+ 0x1040fffd, 0x00000000, 0x3063ffff, 0x30620007, 0x10400002, 0x24620007,
+ 0x3043fff8, 0x00a31021, 0x30421fff, 0x24434000, 0x0343d821, 0x00c02021,
+ 0x30830007, 0xaf85000c, 0xaf820018, 0xaf420084, 0x10600002, 0x24820007,
+ 0x3044fff8, 0x8f820030, 0x8f850000, 0x00441821, 0xaf82001c, 0x0065102b,
+ 0xaf830030, 0x14400002, 0x00651023, 0xaf820030, 0x8f840030, 0x34028000,
+ 0x3c030800, 0x8c650834, 0x00821021, 0x03421821, 0xaf830010, 0xaf440080,
+ 0x10a00006, 0x2402000e, 0x9383002f, 0x14620004, 0x3c021000, 0x2402043f,
+ 0xa7420148, 0x3c021000, 0x03e00008, 0xaf420178, 0x8f820024, 0x30424000,
+ 0x10400005, 0x24020800, 0x0000000d, 0x00000000, 0x2400040e, 0x24020800,
+ 0xaf420178, 0x97440104, 0x3c030008, 0xaf430140, 0x8f820024, 0x30420001,
+ 0x10400006, 0x3085ffff, 0x24020002, 0x24a3fffe, 0xa7420146, 0x0a000526,
+ 0xa7430148, 0xa7400146, 0x8f840018, 0x2402000d, 0xa742014a, 0x24830008,
+ 0x30631fff, 0x24624000, 0x0342d821, 0x30a20007, 0xaf84000c, 0xaf830018,
+ 0xaf430084, 0x10400002, 0x24a20007, 0x3045fff8, 0x8f820030, 0x8f840000,
+ 0x00451821, 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023,
+ 0xaf820030, 0x8f840030, 0x34028000, 0x00821021, 0x03421821, 0x3c021000,
+ 0xaf830010, 0xaf440080, 0x03e00008, 0xaf420178, 0x27bdffe8, 0x3c046008,
+ 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, 0x375b4000,
+ 0x00431024, 0x3442380c, 0xac825000, 0x8f430008, 0x3c100800, 0x37428000,
+ 0x34630001, 0xaf430008, 0xaf820010, 0x3c02601c, 0xaf800018, 0xaf400080,
+ 0xaf400084, 0x8c450008, 0x3c036000, 0x8c620808, 0x3c040800, 0x3c030080,
+ 0xac830820, 0x3042fff0, 0x38420010, 0x2c420001, 0xaf850000, 0xaf820004,
+ 0x0e000658, 0x00000000, 0x8f420000, 0x30420001, 0x1040fffb, 0x00000000,
+ 0x8f430108, 0x8f440100, 0x30622000, 0xaf830024, 0xaf840014, 0x10400004,
+ 0x8e02082c, 0x24420001, 0x0a0005c6, 0xae02082c, 0x30620200, 0x14400003,
+ 0x24020f00, 0x14820027, 0x24020d00, 0x97420104, 0x1040001c, 0x30624000,
+ 0x14400005, 0x00000000, 0x0e00022f, 0x00000000, 0x0a0005bb, 0x00000000,
+ 0x8f620008, 0x8f630000, 0x24020030, 0x00031e02, 0x306300f0, 0x10620007,
+ 0x28620031, 0x1440002f, 0x24020040, 0x10620007, 0x00000000, 0x0a0005bb,
+ 0x00000000, 0x0e0002e8, 0x00000000, 0x0a0005bb, 0x00000000, 0x0e0003db,
+ 0x00000000, 0x0a0005bb, 0x00000000, 0x30620040, 0x1440002b, 0x00000000,
+ 0x0000000d, 0x00000000, 0x240004b2, 0x0a0005c6, 0x00000000, 0x1482000f,
+ 0x30620006, 0x97420104, 0x10400005, 0x30620040, 0x0e000510, 0x00000000,
+ 0x0a0005bb, 0x00000000, 0x1440001b, 0x00000000, 0x0000000d, 0x00000000,
+ 0x240004c4, 0x0a0005c6, 0x00000000, 0x1040000e, 0x30621000, 0x10400005,
+ 0x00000000, 0x0e000688, 0x00000000, 0x0a0005bb, 0x00000000, 0x0e0004a1,
+ 0x00000000, 0x8f82002c, 0x24420001, 0xaf82002c, 0x0a0005c6, 0x00000000,
+ 0x30620040, 0x14400004, 0x00000000, 0x0000000d, 0x00000000, 0x240004db,
+ 0x8f420138, 0x3c034000, 0x00431025, 0xaf420138, 0x0a000566, 0x00000000,
+ 0x3c046008, 0x8c835000, 0x3c1a8000, 0x2402ff7f, 0x375b4000, 0x00621824,
+ 0x3463380c, 0xac835000, 0x8f420008, 0x3c056000, 0x3c03601c, 0x34420001,
+ 0xaf420008, 0x37428000, 0xaf800018, 0xaf820010, 0xaf400080, 0xaf400084,
+ 0x8c660008, 0x8ca20808, 0x3c040800, 0x3c030080, 0xac830820, 0x3042fff0,
+ 0x38420010, 0x2c420001, 0xaf860000, 0xaf820004, 0x03e00008, 0x00000000,
+ 0x3084ffff, 0x30820007, 0x10400002, 0x24820007, 0x3044fff8, 0x8f820018,
+ 0x00441821, 0x30631fff, 0x24644000, 0x0344d821, 0xaf82000c, 0xaf830018,
+ 0x03e00008, 0xaf430084, 0x3084ffff, 0x30820007, 0x10400002, 0x24820007,
+ 0x3044fff8, 0x8f820030, 0x8f830000, 0x00442021, 0xaf82001c, 0x0083102b,
+ 0xaf840030, 0x14400002, 0x00831023, 0xaf820030, 0x8f820030, 0x34038000,
+ 0x00431821, 0x03432021, 0xaf840010, 0x03e00008, 0xaf420080, 0x8f830024,
+ 0x24020002, 0x30630006, 0x1062000d, 0x2c620003, 0x50400005, 0x24020004,
+ 0x10600012, 0x3c020001, 0x0a00062a, 0x00000000, 0x10620007, 0x24020006,
+ 0x1462000f, 0x3c020111, 0x0a000622, 0x00821025, 0x0a000621, 0x3c020101,
+ 0x3c020011, 0x00821025, 0x24030001, 0xaf421000, 0xaf830020, 0x0a00062a,
+ 0x00000000, 0x00821025, 0xaf421000, 0xaf800020, 0x00000000, 0x00000000,
+ 0x00000000, 0x03e00008, 0x00000000, 0x8f820020, 0x10400005, 0x3c038000,
+ 0x8f421000, 0x00431024, 0x1040fffd, 0x00000000, 0x03e00008, 0x00000000,
+ 0x8f820024, 0x27bdffe8, 0x30424000, 0x14400005, 0xafbf0010, 0x0e00022f,
+ 0x00000000, 0x0a000656, 0x8fbf0010, 0x8f620008, 0x8f630000, 0x24020030,
+ 0x00031e02, 0x306300f0, 0x10620008, 0x28620031, 0x1440000d, 0x8fbf0010,
+ 0x24020040, 0x10620007, 0x00000000, 0x0a000656, 0x00000000, 0x0e0002e8,
+ 0x00000000, 0x0a000656, 0x8fbf0010, 0x0e0003db, 0x00000000, 0x8fbf0010,
+ 0x03e00008, 0x27bd0018, 0x8f840028, 0x1080000f, 0x3c026000, 0x8c430c3c,
+ 0x30630fff, 0xaf830008, 0x14600011, 0x3082000f, 0x10400005, 0x308200f0,
+ 0x10400003, 0x30820f00, 0x14400006, 0x00000000, 0x0000000d, 0x00000000,
+ 0x2400051a, 0x03e00008, 0x00000000, 0x0000000d, 0x00000000, 0x2400051f,
+ 0x03e00008, 0x00000000, 0xaf830028, 0x03e00008, 0x00000000, 0x10c00007,
+ 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb,
+ 0x24840004, 0x03e00008, 0x00000000, 0x0a000684, 0x00a01021, 0xac860000,
+ 0x00000000, 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa, 0x24a5ffff,
+ 0x03e00008, 0x00000000, 0x0000000d, 0x03e00008, 0x00000000, 0x00000000};
+
+static u32 bnx2_TPAT_b06FwData[(0x0/4) + 1] = { 0x0 };
+static u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 };
+static u32 bnx2_TPAT_b06FwBss[(0x250/4) + 1] = { 0x0 };
+static u32 bnx2_TPAT_b06FwSbss[(0x34/4) + 1] = { 0x0 };
+
+static const int bnx2_TXP_b06FwReleaseMajor = 0x1;
+static const int bnx2_TXP_b06FwReleaseMinor = 0x0;
+static const int bnx2_TXP_b06FwReleaseFix = 0x0;
+static const u32 bnx2_TXP_b06FwStartAddr = 0x080034b0;
+static const u32 bnx2_TXP_b06FwTextAddr = 0x08000000;
+static const int bnx2_TXP_b06FwTextLen = 0x5748;
+static const u32 bnx2_TXP_b06FwDataAddr = 0x08005760;
+static const int bnx2_TXP_b06FwDataLen = 0x0;
+static const u32 bnx2_TXP_b06FwRodataAddr = 0x00000000;
+static const int bnx2_TXP_b06FwRodataLen = 0x0;
+static const u32 bnx2_TXP_b06FwBssAddr = 0x080057a0;
+static const int bnx2_TXP_b06FwBssLen = 0x1c4;
+static const u32 bnx2_TXP_b06FwSbssAddr = 0x08005760;
+static const int bnx2_TXP_b06FwSbssLen = 0x38;
+static u32 bnx2_TXP_b06FwText[(0x5748/4) + 1] = {
+ 0x0a000d2c, 0x00000000, 0x00000000, 0x0000000d, 0x74787020, 0x322e352e,
+ 0x38000000, 0x02050800, 0x0000000a, 0x000003e8, 0x0000ea60, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800,
+ 0x24425760, 0x3c030800, 0x24635964, 0xac400000, 0x0043202b, 0x1480fffd,
+ 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x261034b0,
+ 0x3c1c0800, 0x279c5760, 0x0e000f5b, 0x00000000, 0x0000000d, 0x8f840014,
+ 0x27bdffe8, 0xafb10014, 0xafb00010, 0x8f460104, 0x8f830008, 0x8c8500ac,
+ 0xaf430080, 0x948200a8, 0xa7420e10, 0x948300aa, 0xa7430e12, 0x8c8200ac,
+ 0xaf420e18, 0x97430e10, 0xa7430e14, 0x97420e12, 0x00008021, 0xa7420e16,
+ 0x8f430e18, 0x00006021, 0x00c53023, 0xaf430e1c, 0x10c001a2, 0x2d820001,
+ 0x3c0e1000, 0x2419fff8, 0x24110010, 0x240f0f00, 0x3c188100, 0x93620008,
+ 0x10400009, 0x00000000, 0x97620010, 0x00c2102b, 0x14400005, 0x00000000,
+ 0x97620010, 0x3042ffff, 0x0a000d6d, 0xaf420e00, 0xaf460e00, 0x8f420000,
+ 0x30420008, 0x1040fffd, 0x00000000, 0x97420e08, 0x8f450e04, 0x3044ffff,
+ 0x30820001, 0x14400005, 0x00000000, 0x14a00005, 0x3083a040, 0x0a000f34,
+ 0x00000000, 0x0000000d, 0x3083a040, 0x24020040, 0x1462004f, 0x3082a000,
+ 0x308a0036, 0x8f88000c, 0x30890008, 0x24020800, 0xaf420178, 0x01001821,
+ 0x9742008a, 0x00431023, 0x2442ffff, 0x30421fff, 0x2c420008, 0x1440fffa,
+ 0x00a06021, 0x8f820018, 0x00cc3023, 0x24070001, 0x8f830008, 0x304b00ff,
+ 0x24420001, 0xaf820018, 0x25024000, 0x106f0005, 0x03422021, 0x93820012,
+ 0x30420007, 0x00021240, 0x34470001, 0x000b1400, 0x3c030100, 0x00431025,
+ 0xac820000, 0x8f830018, 0x00ea3825, 0x1120000f, 0xac830004, 0x97430e0a,
+ 0x8f84000c, 0x00ee3825, 0x2402000e, 0x00781825, 0xaf430160, 0x25830006,
+ 0x24840008, 0x30841fff, 0xa742015a, 0xa7430158, 0xaf84000c, 0x0a000db7,
+ 0x00000000, 0x8f83000c, 0x25820002, 0xa7420158, 0x24630008, 0x30631fff,
+ 0xaf83000c, 0x54c0000f, 0x8f420e14, 0x8f820008, 0x504f0002, 0x24100001,
+ 0x34e70040, 0x97420e10, 0x97430e12, 0x8f850014, 0x00021400, 0x00621825,
+ 0xaca300a8, 0x8f840014, 0x8f420e18, 0xac8200ac, 0x8f420e14, 0x8f430e1c,
+ 0xaf420144, 0xaf430148, 0xa34b0152, 0xaf470154, 0x0a000efb, 0xaf4e0178,
+ 0x10400165, 0x00000000, 0x93620008, 0x50400008, 0xafa60008, 0x97620010,
+ 0x00a2102b, 0x10400003, 0x30820040, 0x1040015c, 0x00000000, 0xafa60008,
+ 0xa7840010, 0xaf850004, 0x93620008, 0x1440005f, 0x27ac0008, 0xaf60000c,
+ 0x97820010, 0x30424000, 0x10400002, 0x2403000e, 0x24030016, 0xa363000a,
+ 0x24034007, 0xaf630014, 0x93820012, 0x8f630014, 0x30420007, 0x00021240,
+ 0x00621825, 0xaf630014, 0x97820010, 0x8f630014, 0x30420010, 0x00621825,
+ 0xaf630014, 0x97820010, 0x30420008, 0x5040000e, 0x00002821, 0x8f620014,
+ 0x004e1025, 0xaf620014, 0x97430e0a, 0x2402000e, 0x00781825, 0xaf630004,
+ 0xa3620002, 0x9363000a, 0x3405fffc, 0x24630004, 0x0a000e06, 0xa363000a,
+ 0xaf600004, 0xa3600002, 0x97820010, 0x9363000a, 0x30421f00, 0x00021182,
+ 0x24420028, 0x00621821, 0xa3630009, 0x97420e0c, 0xa7620010, 0x93630009,
+ 0x24020008, 0x24630002, 0x30630007, 0x00431023, 0x30420007, 0xa362000b,
+ 0x93640009, 0x97620010, 0x8f890004, 0x97830010, 0x00441021, 0x00a21021,
+ 0x30630040, 0x10600007, 0x3045ffff, 0x00a9102b, 0x14400005, 0x0125102b,
+ 0x3c068000, 0x0a000e3a, 0x00005821, 0x0125102b, 0x544000c7, 0x00006021,
+ 0x97420e14, 0xa7420e10, 0x97430e16, 0xa7430e12, 0x8f420e1c, 0xaf420e18,
+ 0xaf450e00, 0x8f420000, 0x30420008, 0x1040fffd, 0x00000000, 0x97420e08,
+ 0x00a04821, 0xa7820010, 0x8f430e04, 0x00003021, 0x240b0001, 0xaf830004,
+ 0x97620010, 0x0a000e4c, 0x304dffff, 0x8f890004, 0x97820010, 0x30420040,
+ 0x10400004, 0x01206821, 0x3c068000, 0x0a000e4c, 0x00005821, 0x97630010,
+ 0x8f820004, 0x10430003, 0x00003021, 0x0a000eee, 0x00006021, 0x240b0001,
+ 0x8d820000, 0x00491023, 0x1440000d, 0xad820000, 0x8f620014, 0x34420040,
+ 0xaf620014, 0x97430e10, 0x97420e12, 0x8f840014, 0x00031c00, 0x00431025,
+ 0xac8200a8, 0x8f830014, 0x8f420e18, 0xac6200ac, 0x93620008, 0x1440003e,
+ 0x00000000, 0x25260002, 0x8f84000c, 0x9743008a, 0x3063ffff, 0xafa30000,
+ 0x8fa20000, 0x00441023, 0x2442ffff, 0x30421fff, 0x2c420010, 0x1440fff7,
+ 0x00000000, 0x8f82000c, 0x8f830018, 0x00021082, 0x00021080, 0x24424000,
+ 0x03422821, 0x00605021, 0x24630001, 0x314200ff, 0x00021400, 0xaf830018,
+ 0x3c033200, 0x00431025, 0xaca20000, 0x93630009, 0x9362000a, 0x00031c00,
+ 0x00431025, 0xaca20004, 0x8f830018, 0xaca30008, 0x97820010, 0x30420008,
+ 0x10400002, 0x00c04021, 0x25280006, 0x97430e14, 0x93640002, 0x8f450e1c,
+ 0x8f660004, 0x8f670014, 0x3063ffff, 0xa7430144, 0x97420e16, 0xa7420146,
+ 0xaf450148, 0xa34a0152, 0x8f82000c, 0x308400ff, 0xa744015a, 0xaf460160,
+ 0xa7480158, 0xaf470154, 0xaf4e0178, 0x00511021, 0x30421fff, 0xaf82000c,
+ 0x0a000ed9, 0x8d820000, 0x93620009, 0x9363000b, 0x8f85000c, 0x2463000a,
+ 0x00435021, 0x25440007, 0x00992024, 0x9743008a, 0x3063ffff, 0xafa30000,
+ 0x8fa20000, 0x00451023, 0x2442ffff, 0x30421fff, 0x0044102b, 0x1440fff7,
+ 0x00000000, 0x8f82000c, 0x8f840018, 0x00021082, 0x00021080, 0x24424000,
+ 0x03422821, 0x00804021, 0x24840001, 0xaf840018, 0x93630009, 0x310200ff,
+ 0x00022400, 0x3c024100, 0x24630002, 0x00621825, 0x00832025, 0xaca40000,
+ 0x8f62000c, 0x00461025, 0xaca20004, 0x97430e14, 0x93640002, 0x8f450e1c,
+ 0x8f660004, 0x8f670014, 0x3063ffff, 0xa7430144, 0x97420e16, 0x308400ff,
+ 0xa7420146, 0xaf450148, 0xa3480152, 0x8f83000c, 0x25420007, 0x00591024,
+ 0xa744015a, 0xaf460160, 0xa7490158, 0xaf470154, 0xaf4e0178, 0x00621821,
+ 0x30631fff, 0xaf83000c, 0x8d820000, 0x14400005, 0x00000000, 0x8f620014,
+ 0x2403ffbf, 0x00431024, 0xaf620014, 0x8f62000c, 0x004d1021, 0xaf62000c,
+ 0x93630008, 0x14600008, 0x00000000, 0x11600006, 0x00000000, 0x8f630014,
+ 0x3c02efff, 0x3442fffe, 0x00621824, 0xaf630014, 0xa36b0008, 0x01206021,
+ 0x1580000c, 0x8fa60008, 0x97420e14, 0x97430e16, 0x8f850014, 0x00021400,
+ 0x00621825, 0xaca300a8, 0x8f840014, 0x8f420e1c, 0xac8200ac, 0x0a000efd,
+ 0x2d820001, 0x14c0fe65, 0x2d820001, 0x00501025, 0x10400058, 0x24020f00,
+ 0x8f830008, 0x14620023, 0x3c048000, 0x11800009, 0x3c038000, 0x97420e08,
+ 0x30420040, 0x14400005, 0x00000000, 0x0000000d, 0x00000000, 0x2400032c,
+ 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x00000000, 0x97420e10,
+ 0x3c030500, 0x00431025, 0xaf42014c, 0x97430e14, 0xa7430144, 0x97420e16,
+ 0xa7420146, 0x8f430e1c, 0x24022000, 0xaf430148, 0x3c031000, 0xa3400152,
+ 0xa740015a, 0xaf400160, 0xa7400158, 0xaf420154, 0xaf430178, 0x8f830008,
+ 0x3c048000, 0x8f420178, 0x00441024, 0x1440fffd, 0x24020f00, 0x10620016,
+ 0x00000000, 0x97420e14, 0xa7420144, 0x97430e16, 0xa7430146, 0x8f420e1c,
+ 0x3c031000, 0xaf420148, 0x0a000f51, 0x24020240, 0x97420e14, 0x97430e16,
+ 0x8f840014, 0x00021400, 0x00621825, 0xac8300a8, 0x8f850014, 0x8f420e1c,
+ 0x00006021, 0xaca200ac, 0x0a000efd, 0x2d820001, 0xaf40014c, 0x11800007,
+ 0x00000000, 0x97420e10, 0xa7420144, 0x97430e12, 0xa7430146, 0x0a000f4e,
+ 0x8f420e18, 0x97420e14, 0xa7420144, 0x97430e16, 0xa7430146, 0x8f420e1c,
+ 0xaf420148, 0x24020040, 0x3c031000, 0xa3400152, 0xa740015a, 0xaf400160,
+ 0xa7400158, 0xaf420154, 0xaf430178, 0x8fb10014, 0x8fb00010, 0x03e00008,
+ 0x27bd0018, 0x27bdffd0, 0x3c1a8000, 0x3c0420ff, 0x3484fffd, 0x3c020008,
+ 0x03421821, 0xafbf002c, 0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c,
+ 0xafb20018, 0xafb10014, 0xafb00010, 0xaf830014, 0xaf440e00, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3c0200ff, 0x3442fffd,
+ 0x3c046004, 0xaf420e00, 0x8c835000, 0x24160800, 0x24150d00, 0x3c140800,
+ 0x24130f00, 0x3c120800, 0x3c114000, 0x2402ff7f, 0x00621824, 0x3463380c,
+ 0x24020009, 0xac835000, 0xaf420008, 0xaf800018, 0xaf80000c, 0x0e001559,
+ 0x00000000, 0x0e000ff0, 0x00000000, 0x3c020800, 0x245057c0, 0x8f420000,
+ 0x30420001, 0x1040fffd, 0x00000000, 0x8f440100, 0xaf840008, 0xaf440020,
+ 0xaf560178, 0x93430108, 0xa3830012, 0x93820012, 0x30420001, 0x10400008,
+ 0x00000000, 0x93820012, 0x30420006, 0x00021100, 0x0e000d43, 0x0050d821,
+ 0x0a000fac, 0x00000000, 0x14950005, 0x00000000, 0x0e000d43, 0x269b5840,
+ 0x0a000fac, 0x00000000, 0x14930005, 0x00000000, 0x0e000d43, 0x265b5860,
+ 0x0a000fac, 0x00000000, 0x0e0010ea, 0x00000000, 0xaf510138, 0x0a000f89,
+ 0x00000000, 0x27bdfff8, 0x3084ffff, 0x24820007, 0x3044fff8, 0x8f85000c,
+ 0x9743008a, 0x3063ffff, 0xafa30000, 0x8fa20000, 0x00451023, 0x2442ffff,
+ 0x30421fff, 0x0044102b, 0x1440fff7, 0x00000000, 0x8f82000c, 0x00021082,
+ 0x00021080, 0x24424000, 0x03421021, 0x03e00008, 0x27bd0008, 0x3084ffff,
+ 0x8f82000c, 0x24840007, 0x3084fff8, 0x00441021, 0x30421fff, 0xaf82000c,
+ 0x03e00008, 0x00000000, 0x27bdffe8, 0x3c1a8000, 0x3c0420ff, 0x3484fffd,
+ 0x3c020008, 0x03421821, 0xafbf0010, 0xaf830014, 0xaf440e00, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3c0200ff, 0x3442fffd,
+ 0x3c046004, 0xaf420e00, 0x8c825000, 0x2403ff7f, 0x00431024, 0x3442380c,
+ 0x24030009, 0xac825000, 0xaf430008, 0xaf800018, 0xaf80000c, 0x0e001559,
+ 0x00000000, 0x0e000ff0, 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018,
+ 0x27bdffe8, 0x3c02000a, 0x03421821, 0x3c040800, 0x24845880, 0x24050019,
+ 0xafbf0010, 0xaf830024, 0x0e001565, 0x00003021, 0x3c050800, 0x3c020800,
+ 0x24425330, 0xaca258e8, 0x24a558e8, 0x3c020800, 0x244254f8, 0x3c030800,
+ 0x2463550c, 0x3c040800, 0xaca20004, 0x3c020800, 0x24425338, 0xaca30008,
+ 0xac825900, 0x24845900, 0x3c020800, 0x244253c4, 0x3c070800, 0x24e75404,
+ 0x3c060800, 0x24c65520, 0x3c050800, 0x24a55438, 0x3c030800, 0xac820004,
+ 0x3c020800, 0x24425528, 0xac870008, 0xac86000c, 0xac850010, 0xac625920,
+ 0x24635920, 0x8fbf0010, 0x3c020800, 0x24425540, 0xac620004, 0x3c020800,
+ 0xac670008, 0xac66000c, 0xac650010, 0xac400048, 0x03e00008, 0x27bd0018,
+ 0x974309da, 0x00804021, 0xad030000, 0x8f4209dc, 0xad020004, 0x8f4309e0,
+ 0xad030008, 0x934409d9, 0x24020001, 0x30840003, 0x1082001f, 0x30a900ff,
+ 0x28820002, 0x10400005, 0x24020002, 0x10800009, 0x3c0a0800, 0x0a001078,
+ 0x93420934, 0x1082000b, 0x24020003, 0x10820026, 0x3c0a0800, 0x0a001078,
+ 0x93420934, 0x974209e4, 0x00021400, 0x34420800, 0xad02000c, 0x0a001077,
+ 0x25080010, 0x974209e4, 0x00021400, 0x34428100, 0xad02000c, 0x974309e8,
+ 0x3c0a0800, 0x00031c00, 0x34630800, 0xad030010, 0x0a001077, 0x25080014,
+ 0x974409e4, 0x3c050800, 0x24a25880, 0x9443001c, 0x94460014, 0x94470010,
+ 0x00a05021, 0x24020800, 0xad000010, 0xad020014, 0x00042400, 0x00661821,
+ 0x00671823, 0x2463fff2, 0x00832025, 0xad04000c, 0x0a001077, 0x25080018,
+ 0x974209e4, 0x3c050800, 0x00021400, 0x34428100, 0xad02000c, 0x974409e8,
+ 0x24a25880, 0x9443001c, 0x94460014, 0x94470010, 0x00a05021, 0x24020800,
+ 0xad000014, 0xad020018, 0x00042400, 0x00661821, 0x00671823, 0x2463ffee,
+ 0x00832025, 0xad040010, 0x2508001c, 0x93420934, 0x93450921, 0x3c074000,
+ 0x25445880, 0x94830018, 0x94860014, 0x00021082, 0x00021600, 0x00052c00,
+ 0x00a72825, 0x00451025, 0x00661821, 0x00431025, 0xad020000, 0x9783002c,
+ 0x974209ea, 0x00621821, 0x00031c00, 0xad030004, 0x9782002c, 0x24420001,
+ 0x30427fff, 0xa782002c, 0x93430920, 0x3c020006, 0x00031e00, 0x00621825,
+ 0xad030008, 0x8f42092c, 0xad02000c, 0x8f430930, 0xad030010, 0x8f440938,
+ 0x25080014, 0xad040000, 0x8f820020, 0x11200004, 0xad020004, 0x8f420940,
+ 0x0a0010a1, 0x2442ffff, 0x8f420940, 0xad020008, 0x8f440948, 0x8f420940,
+ 0x93430936, 0x00823023, 0x00663006, 0x3402ffff, 0x0046102b, 0x54400001,
+ 0x3406ffff, 0x93420937, 0x25445880, 0x90830024, 0xad000010, 0x00021700,
+ 0x34630010, 0x00031c00, 0x00431025, 0x00461025, 0xad02000c, 0x8c830008,
+ 0x14600031, 0x25080014, 0x3c020800, 0x8c430048, 0x1060002d, 0x00000000,
+ 0x9342010b, 0xad020000, 0x8f830000, 0x8c6200b0, 0xad020004, 0x8f830000,
+ 0x8c6200b4, 0xad020008, 0x8f830000, 0x8c6200c0, 0xad02000c, 0x8f830000,
+ 0x8c6200c4, 0xad020010, 0x8f830000, 0x8c6200c8, 0xad020014, 0x8f830000,
+ 0x8c6200cc, 0xad020018, 0x8f830000, 0x8c6200e0, 0xad02001c, 0x8f830000,
+ 0x8c6200e8, 0xad020020, 0x8f830000, 0x8c6200f0, 0x3c04600e, 0xad020024,
+ 0x8c8200d0, 0xad020028, 0x8c8300d4, 0xad03002c, 0x8f820028, 0x3c046012,
+ 0xad020030, 0x8c8200a8, 0xad020034, 0x8c8300ac, 0x3c026000, 0xad030038,
+ 0x8c434448, 0xad03003c, 0x03e00008, 0x01001021, 0x27bdffa8, 0x3c020008,
+ 0x03423021, 0xafbf0054, 0xafbe0050, 0xafb7004c, 0xafb60048, 0xafb50044,
+ 0xafb40040, 0xafb3003c, 0xafb20038, 0xafb10034, 0xafb00030, 0xaf860000,
+ 0x24020040, 0xaf420814, 0xaf400810, 0x8f420944, 0x8f430950, 0x8f440954,
+ 0x8f45095c, 0xaf820034, 0xaf830020, 0xaf84001c, 0xaf850030, 0x90c20000,
+ 0x24030020, 0x304400ff, 0x10830005, 0x24020030, 0x10820022, 0x3c030800,
+ 0x0a001139, 0x8c62002c, 0x24020088, 0xaf420818, 0x3c020800, 0x244258e8,
+ 0xafa20020, 0x93430109, 0x3c020800, 0x10600009, 0x24575900, 0x3c026000,
+ 0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000,
+ 0x24000376, 0x9342010a, 0x30420080, 0x14400021, 0x24020800, 0x3c026000,
+ 0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000,
+ 0x2400037d, 0x0a001141, 0x24020800, 0x93430109, 0x3063007f, 0x00031140,
+ 0x000318c0, 0x00431021, 0x24430088, 0xaf430818, 0x0000000d, 0x3c020800,
+ 0x24425940, 0x3c030800, 0x24775950, 0x0a001140, 0xafa20020, 0x24420001,
+ 0xac62002c, 0x0000000d, 0x00000000, 0x24000395, 0x0a0014c1, 0x8fbf0054,
+ 0x24020800, 0xaf420178, 0x8f450104, 0x8f420988, 0x00a21023, 0x58400005,
+ 0x8f4309a0, 0x0000000d, 0x00000000, 0x240003b1, 0x8f4309a0, 0x3c100800,
+ 0xae0358b0, 0x8f4209a4, 0x8f830020, 0x260458b0, 0x2491ffd0, 0xae220034,
+ 0x00a21023, 0xae230028, 0xac82ffd0, 0x8fa30020, 0x8c620000, 0x0040f809,
+ 0x0200b021, 0x00409021, 0x32440010, 0x32420002, 0x10400007, 0xafa40024,
+ 0x8e220020, 0x32530040, 0x2403ffbf, 0x00431024, 0x0a001493, 0xae220020,
+ 0x32420020, 0x10400002, 0x3c020800, 0x24575920, 0x32420001, 0x14400007,
+ 0x00000000, 0x8f820008, 0xaf420080, 0x8ec358b0, 0xaf430e10, 0x8e220034,
+ 0xaf420e18, 0x9343010b, 0x93420905, 0x30420008, 0x1040003c, 0x307400ff,
+ 0x8f820000, 0x8c430074, 0x0460000a, 0x00000000, 0x3c026000, 0x24030100,
+ 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x240003ed,
+ 0x8f820000, 0x9044007b, 0x9343010a, 0x14830027, 0x32530040, 0x00003821,
+ 0x24052000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd,
+ 0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030100,
+ 0xaf420148, 0x24020047, 0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000,
+ 0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001, 0xad230030,
+ 0x9342010a, 0x3c030047, 0xafa50014, 0x00021600, 0x00431025, 0x00471025,
+ 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b,
+ 0x3c070100, 0x3c050800, 0x24a25880, 0x0a001250, 0x8c430020, 0x32820002,
+ 0x10400050, 0x00000000, 0x0e0015b9, 0x32530040, 0x3c039000, 0x34630001,
+ 0x8f820008, 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020, 0x00441024,
+ 0x1440fffd, 0x00000000, 0x8f830000, 0x90620005, 0x34420008, 0xa0620005,
+ 0x8f840000, 0x8c820074, 0x3c038000, 0x00431025, 0xac820074, 0x90830000,
+ 0x24020020, 0x10620004, 0x00000000, 0x0000000d, 0x00000000, 0x2400040b,
+ 0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, 0x9084007b,
+ 0x9342010a, 0x14820028, 0x3c030800, 0x00003821, 0x24052000, 0x3c090800,
+ 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0, 0x26c458b0,
+ 0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030100, 0xaf420148, 0x24020046,
+ 0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7470158, 0xaf450154,
+ 0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030046,
+ 0xafa50014, 0x00021600, 0x00431025, 0x00471025, 0xafa20010, 0x9343010b,
+ 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x3c070100, 0x3c030800,
+ 0x24625880, 0x0a001250, 0x8c430020, 0x93420108, 0x30420010, 0x50400056,
+ 0x9343093f, 0x8f860000, 0x90c2007f, 0x8cc30178, 0x304800ff, 0x15030004,
+ 0x00000000, 0x0000000d, 0x00000000, 0x24000425, 0x90c2007e, 0x90c40080,
+ 0x00081c00, 0x00021600, 0x00431025, 0x00042200, 0x90c3007a, 0x90c5000a,
+ 0x00441025, 0x11050028, 0x00623825, 0xa0c8000a, 0x00004021, 0x24056000,
+ 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0,
+ 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, 0xaf420148, 0x24020052,
+ 0xaf47014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7480158, 0xaf450154,
+ 0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030052,
+ 0xafa50014, 0x00021600, 0x00431025, 0x00481025, 0xafa20010, 0x9343010b,
+ 0xafa30018, 0x8f440100, 0x0e00159b, 0x8f450104, 0x0a00124a, 0x00000000,
+ 0x3c026000, 0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d,
+ 0x00000000, 0x2400043e, 0x16800009, 0x3c050800, 0x3c040800, 0x24825880,
+ 0x8c430020, 0x32530040, 0x2404ffbf, 0x00641824, 0x0a001493, 0xac430020,
+ 0x8ca25880, 0x10400005, 0x3c030800, 0x8c620034, 0xaca05880, 0x24420001,
+ 0xac620034, 0x9343093f, 0x24020012, 0x5462000e, 0x97420908, 0x32820038,
+ 0x14400009, 0x3c030800, 0x8f830000, 0x8c62004c, 0xac62005c, 0x3c020800,
+ 0x24445880, 0x8c820020, 0x0a001285, 0x32530040, 0xac605880, 0x97420908,
+ 0x5440001c, 0x97420908, 0x3c039000, 0x34630001, 0x8f820008, 0x32530040,
+ 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020, 0x00441024, 0x1440fffd,
+ 0x3c028000, 0x8f840000, 0x8f850008, 0x8c830050, 0x34420001, 0x00a22825,
+ 0xaf830020, 0xac830070, 0xac83005c, 0xaf450020, 0x3c050800, 0x24a45880,
+ 0x8c820020, 0x2403ffbf, 0x00431024, 0x0a001493, 0xac820020, 0x000211c0,
+ 0xaf420024, 0x97420908, 0x3c030080, 0x34630003, 0x000211c0, 0xaf42080c,
+ 0xaf43081c, 0x974209ec, 0x8f4309a4, 0xa782002c, 0x3c020800, 0x24445880,
+ 0xac83002c, 0x93420937, 0x93430934, 0x00021080, 0x00621821, 0xa4830018,
+ 0x934209d8, 0x32850038, 0xafa50028, 0x00621821, 0xa483001a, 0x934209d8,
+ 0x93430934, 0x3c1e0800, 0x00809821, 0x00431021, 0x24420010, 0xa4820016,
+ 0x24020006, 0xae620020, 0x8fa20028, 0x10400003, 0x0000a821, 0x0a0012f0,
+ 0x24120008, 0x8f420958, 0x8f830020, 0x8f840030, 0x00431023, 0x00832023,
+ 0x04800003, 0xae620004, 0x04410003, 0x0082102b, 0x0a0012bc, 0xae600004,
+ 0x54400001, 0xae640004, 0x8ee20000, 0x0040f809, 0x00000000, 0x00409021,
+ 0x32420001, 0x5440001e, 0x8ee20004, 0x8e630008, 0x1060002b, 0x3c02c000,
+ 0x00621025, 0xaf420e00, 0x8f420000, 0x30420008, 0x1040fffd, 0x00000000,
+ 0x97420e08, 0xa7820010, 0x8f430e04, 0x8e620008, 0xaf830004, 0x8f840004,
+ 0x0044102b, 0x1040000b, 0x24150001, 0x24020100, 0x3c016000, 0xac22081c,
+ 0x3c020001, 0x3c016000, 0xac22081c, 0x0000000d, 0x00000000, 0x240004cd,
+ 0x24150001, 0x8ee20004, 0x0040f809, 0x00000000, 0x02429025, 0x32420002,
+ 0x5040001d, 0x8f470940, 0x12a00006, 0x8ec258b0, 0x8f830000, 0xac6200a8,
+ 0x8f840000, 0x8e620034, 0xac8200ac, 0x32420004, 0x50400013, 0x8f470940,
+ 0x3c020800, 0x3283007d, 0x10600110, 0x24575920, 0x32820001, 0x50400006,
+ 0x36520002, 0x8f830034, 0x8f420940, 0x10620109, 0x00000000, 0x36520002,
+ 0x24020008, 0xa6600010, 0xa6620012, 0xae600008, 0xa2600024, 0x8f470940,
+ 0x3c030800, 0x24685880, 0x8d02002c, 0x8d050008, 0x95040010, 0x9506000a,
+ 0x95030026, 0x00451021, 0x00862021, 0x00641821, 0xaf870034, 0xad02002c,
+ 0x32820030, 0x10400008, 0xa5030014, 0x91020024, 0x32910040, 0x34420004,
+ 0xa1020024, 0xaf400048, 0x0a001345, 0x3c040800, 0x93420923, 0x30420002,
+ 0x10400029, 0x32910040, 0x8f830000, 0x8f840020, 0x8c620084, 0x00441023,
+ 0x0442000a, 0x3c039000, 0x95020014, 0x8c630084, 0x00821021, 0x00621823,
+ 0x1c600004, 0x3c039000, 0x91020024, 0x34420001, 0xa1020024, 0x34630001,
+ 0x8f820008, 0x32910040, 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020,
+ 0x00441024, 0x1440fffd, 0x00000000, 0x8f840000, 0x9083003f, 0x2402000a,
+ 0x10620005, 0x2402000c, 0x9083003f, 0x24020008, 0x14620002, 0x24020014,
+ 0xa082003f, 0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020,
+ 0x3c040800, 0x24865880, 0x94c20010, 0x94c3001a, 0x8cc40008, 0x00432821,
+ 0x14800006, 0xa4c5001c, 0x3c020800, 0x8c430048, 0x10600002, 0x24a20040,
+ 0xa4c2001c, 0x27d05880, 0x9604001c, 0x96020012, 0x00822021, 0x24840002,
+ 0x0e000faf, 0x3084ffff, 0x8f850018, 0x00a01821, 0xa2030025, 0x8ee60008,
+ 0x00402021, 0x24a50001, 0xaf850018, 0x00c0f809, 0x00000000, 0x00402021,
+ 0x0e001026, 0x02202821, 0x8ee3000c, 0x0060f809, 0x00402021, 0x9604001c,
+ 0x96020012, 0x00822021, 0x24840002, 0x0e000fc5, 0x3084ffff, 0x8fc25880,
+ 0x8e030008, 0x00431023, 0x14400012, 0xafc25880, 0x54600006, 0x8e020020,
+ 0x3243004a, 0x24020002, 0x14620005, 0x00000000, 0x8e020020, 0x34420040,
+ 0x0a001382, 0xae020020, 0x52a00006, 0x36520002, 0x8e020030, 0xaf420e10,
+ 0x8e030034, 0xaf430e18, 0x36520002, 0x52a00008, 0x96670014, 0x8f830000,
+ 0x8f420e10, 0xac6200a8, 0x8f840000, 0x8f420e18, 0xac8200ac, 0x96670014,
+ 0x92680024, 0x24020040, 0xaf420814, 0x8f830020, 0x8f82001c, 0x00671821,
+ 0x00621023, 0xaf830020, 0x18400008, 0x00000000, 0x8f820000, 0xaf83001c,
+ 0xac430054, 0x54e00005, 0xaf400040, 0x0a0013a0, 0x8f42095c, 0x54e00001,
+ 0xaf400044, 0x8f42095c, 0x31030008, 0xaf820030, 0x1060001a, 0x00000000,
+ 0x8f840000, 0x90820120, 0x90830121, 0x304600ff, 0x00c31823, 0x30630007,
+ 0x24020007, 0x1062000e, 0x00000000, 0x90820122, 0x304200fe, 0xa0820122,
+ 0x8f850000, 0x00061880, 0x8f840020, 0x24a20100, 0x00431021, 0x24c30001,
+ 0x30630007, 0xac440000, 0x0a0013bd, 0xa0a30120, 0x90820122, 0x34420001,
+ 0xa0820122, 0x14e00003, 0x31020001, 0x10400031, 0x32510002, 0x8f820000,
+ 0x8c43000c, 0x30630001, 0x1060002c, 0x32510002, 0x3c029000, 0x8f830008,
+ 0x34420001, 0x3c048000, 0x00621825, 0xaf430020, 0x8f420020, 0x00441024,
+ 0x1440fffd, 0x00000000, 0x8f870000, 0x8ce2000c, 0x30420001, 0x10400018,
+ 0x00000000, 0x94e2006a, 0x00022880, 0x50a00001, 0x24050001, 0x94e30068,
+ 0x90e40081, 0x3c020800, 0x8c460024, 0x00652821, 0x00852804, 0x00c5102b,
+ 0x54400001, 0x00a03021, 0x3c020800, 0x8c440028, 0x00c4182b, 0x54600001,
+ 0x00c02021, 0x8f430074, 0x2402fffe, 0x00822824, 0x00a31821, 0xace3000c,
+ 0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, 0x8f820020,
+ 0x3c050800, 0x24b05880, 0xae020028, 0x8ee30010, 0x0060f809, 0x00000000,
+ 0x8f820028, 0x24420001, 0xaf820028, 0x12a00005, 0xaf40004c, 0x8f420e10,
+ 0xae020030, 0x8f430e18, 0xae030034, 0x1220fea7, 0x24020006, 0x8f870024,
+ 0x9786002c, 0x8f830000, 0x8f820034, 0x8f840020, 0x8f85001c, 0x32530040,
+ 0xa4e6002c, 0xac620044, 0x32420008, 0xac640050, 0xac650054, 0x1040007a,
+ 0x32820020, 0x10400027, 0x32910010, 0x00003821, 0x24052000, 0x3c090800,
+ 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0, 0x26c458b0,
+ 0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030400, 0xaf420148, 0x24020041,
+ 0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7470158, 0xaf450154,
+ 0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030041,
+ 0xafa50014, 0x00021600, 0x00431025, 0x00471025, 0xafa20010, 0x9343010b,
+ 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x3c070400, 0x12200028,
+ 0x00003821, 0x24052000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024,
+ 0x1440fffd, 0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034,
+ 0x3c030300, 0xaf420148, 0x2402004e, 0xaf43014c, 0xa3420152, 0x8d230030,
+ 0x3c021000, 0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001,
+ 0xad230030, 0x9342010a, 0x3c03004e, 0xafa50014, 0x00021600, 0x00431025,
+ 0x00471025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104,
+ 0x0e00159b, 0x3c070300, 0x0a00148b, 0x8fa20024, 0x32820008, 0x10400026,
+ 0x24052000, 0x00003821, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024,
+ 0x1440fffd, 0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034,
+ 0x3c030200, 0xaf420148, 0x2402004b, 0xaf43014c, 0xa3420152, 0x8d230030,
+ 0x3c021000, 0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001,
+ 0xad230030, 0x9342010a, 0x3c03004b, 0xafa50014, 0x00021600, 0x00431025,
+ 0x00471025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104,
+ 0x0e00159b, 0x3c070200, 0x8fa20024, 0x14400004, 0x8fa30020, 0x32420010,
+ 0x10400004, 0x00000000, 0x8c620004, 0x0040f809, 0x00000000, 0x12600006,
+ 0x8fa40020, 0x8c820008, 0x0040f809, 0x00000000, 0x0a0014c1, 0x8fbf0054,
+ 0x3c030800, 0x8c6258a0, 0x30420040, 0x14400023, 0x8fbf0054, 0x00002821,
+ 0x24040040, 0x8f870020, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd,
+ 0x8ec258b0, 0x26c358b0, 0x2463ffd0, 0xaf420144, 0x8c620034, 0xaf420148,
+ 0x24020049, 0xaf47014c, 0xa3420152, 0x3c021000, 0xa7450158, 0xaf440154,
+ 0xaf420178, 0x8c660034, 0x9342010a, 0x3c030049, 0xafa40014, 0x00021600,
+ 0x00431025, 0x00451025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100,
+ 0x0e00159b, 0x8f450104, 0x8fbf0054, 0x8fbe0050, 0x8fb7004c, 0x8fb60048,
+ 0x8fb50044, 0x8fb40040, 0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
+ 0x03e00008, 0x27bd0058, 0x03e00008, 0x00001021, 0x3c020800, 0x24435880,
+ 0x8c650004, 0x8c445880, 0x0085182b, 0x10600002, 0x00403021, 0x00802821,
+ 0x9744093c, 0x00a4102b, 0x54400001, 0x00a02021, 0x93420923, 0x0004182b,
+ 0x00021042, 0x30420001, 0x00431024, 0x1040000d, 0x24c25880, 0x8f850000,
+ 0x8f830020, 0x8ca20084, 0x00431023, 0x04420007, 0x24c25880, 0x8ca20084,
+ 0x00641821, 0x00431023, 0x28420001, 0x00822023, 0x24c25880, 0xac440008,
+ 0xa4400026, 0x03e00008, 0x00001021, 0x8f850004, 0x97840010, 0x3c030800,
+ 0x24635880, 0x24020008, 0xa4620012, 0x8f820004, 0xa4600010, 0x000420c2,
+ 0x30840008, 0x2c420001, 0x00021023, 0x30420006, 0xac650008, 0x03e00008,
+ 0xa0640024, 0x3c020800, 0x24425880, 0x90450025, 0x9443001c, 0x3c021100,
+ 0xac800004, 0x00052c00, 0x24630002, 0x00621825, 0x00a32825, 0x24820008,
+ 0x03e00008, 0xac850000, 0x27bdffd8, 0x3c020800, 0x24425880, 0xafbf0020,
+ 0x90480025, 0x8c440008, 0x8c460020, 0x8f870020, 0x3c030800, 0x3c058000,
+ 0x8f420178, 0x00451024, 0x1440fffd, 0x8c6258b0, 0x246358b0, 0x2469ffd0,
+ 0xaf420144, 0x8d220034, 0x30c32000, 0xaf420148, 0x3c021000, 0xaf47014c,
+ 0xa3480152, 0xa7440158, 0xaf460154, 0xaf420178, 0x10600004, 0x3c030800,
+ 0x8c620030, 0x24420001, 0xac620030, 0x9342010a, 0x00081c00, 0x3084ffff,
+ 0xafa60014, 0x00021600, 0x00431025, 0x00441025, 0xafa20010, 0x9343010b,
+ 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x8d260034, 0x8fbf0020,
+ 0x03e00008, 0x27bd0028, 0x0000000d, 0x00000000, 0x2400019d, 0x03e00008,
+ 0x00000000, 0x0000000d, 0x00000000, 0x240001a9, 0x03e00008, 0x00000000,
+ 0x03e00008, 0x00000000, 0x3c020800, 0x24425880, 0xac400008, 0xa4400026,
+ 0x03e00008, 0x24020001, 0x3c020800, 0x24425880, 0x24030008, 0xac400008,
+ 0xa4400010, 0xa4430012, 0xa0400024, 0x03e00008, 0x24020004, 0x03e00008,
+ 0x00001021, 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004,
+ 0xac820000, 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a00156c,
+ 0x00a01021, 0xac860000, 0x00000000, 0x00000000, 0x24840004, 0x00a01021,
+ 0x1440fffa, 0x24a5ffff, 0x03e00008, 0x00000000, 0x3c0a0800, 0x8d490068,
+ 0x3c050800, 0x24a52098, 0x00093140, 0x00c51021, 0xac440000, 0x8f440e04,
+ 0x00a61021, 0xac440004, 0x97430e08, 0x97420e0c, 0x00a62021, 0x00031c00,
+ 0x00431025, 0xac820008, 0x8f430e10, 0x00801021, 0xac43000c, 0x8f440e14,
+ 0xac440010, 0x8f430e18, 0x3c0800ff, 0xac430014, 0x8f470e1c, 0x3508ffff,
+ 0x25290001, 0xac470018, 0x3c070800, 0x8ce3006c, 0x9344010a, 0x3c026000,
+ 0x24630001, 0xace3006c, 0x8c434448, 0x3129007f, 0x00a62821, 0xad490068,
+ 0x00042600, 0x00681824, 0x00832025, 0x03e00008, 0xaca4001c, 0x8fac0010,
+ 0x8fad0014, 0x8fae0018, 0x3c0b0800, 0x8d6a0060, 0x3c080800, 0x25080080,
+ 0x000a4940, 0x01281021, 0x01091821, 0xac440000, 0x00601021, 0xac650004,
+ 0xac460008, 0xac67000c, 0xac4c0010, 0xac6d0014, 0x3c036000, 0xac4e0018,
+ 0x8c654448, 0x3c040800, 0x8c820064, 0x254a0001, 0x314a00ff, 0x01094021,
+ 0xad6a0060, 0x24420001, 0xac820064, 0x03e00008, 0xad05001c, 0x3c030800,
+ 0x3c090800, 0x8d250070, 0x246330b0, 0x8f460100, 0x00053900, 0x00e31021,
+ 0xac460000, 0x8f440104, 0x00671021, 0xac440004, 0x8f460108, 0x8f840014,
+ 0x24a50001, 0xac460008, 0x8c880074, 0x3c060800, 0x8cc20074, 0x30a5003f,
+ 0x00671821, 0xad250070, 0x24420001, 0xacc20074, 0x03e00008, 0xac68000c,
+ 0x00000000 };
+
+static u32 bnx2_TXP_b06FwData[(0x0/4) + 1] = { 0x0 };
+static u32 bnx2_TXP_b06FwRodata[(0x0/4) + 1] = { 0x0 };
+static u32 bnx2_TXP_b06FwBss[(0x1c4/4) + 1] = { 0x0 };
+static u32 bnx2_TXP_b06FwSbss[(0x38/4) + 1] = { 0x0 };
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/cs89x0.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/cs89x0.c
new file mode 100644
index 00000000..876b8785
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/cs89x0.c
@@ -0,0 +1,738 @@
+#ifdef ALLMULTI
+#error multicast support is not yet implemented
+#endif
+
+/**
+ Per an email message from Russ Nelson <nelson@crynwr.com> on
+ 18 March 2008 this file is now licensed under GPL Version 2.
+
+ From: Russ Nelson <nelson@crynwr.com>
+ Date: Tue, 18 Mar 2008 12:42:00 -0400
+ Subject: Re: [Etherboot-developers] cs89x0 driver in etherboot
+ -- quote from email
+ As copyright holder, if I say it doesn't conflict with the GPL,
+ then it doesn't conflict with the GPL.
+
+ However, there's no point in causing people's brains to overheat,
+ so yes, I grant permission for the code to be relicensed under the
+ GPLv2. Please make sure that this change in licensing makes its
+ way upstream. -russ
+ -- quote from email
+**/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for etherboot. */
+/*
+ Permission is granted to distribute the enclosed cs89x0.[ch] driver
+ only in conjunction with the Etherboot package. The code is
+ ordinarily distributed under the GPL.
+
+ Russ Nelson, January 2000
+
+ ChangeLog:
+
+ Thu Dec 6 22:40:00 1996 Markus Gutschke <gutschk@math.uni-muenster.de>
+
+ * disabled all "advanced" features; this should make the code more reliable
+
+ * reorganized the reset function
+
+ * always reset the address port, so that autoprobing will continue working
+
+ * some cosmetic changes
+
+ * 2.5
+
+ Thu Dec 5 21:00:00 1996 Markus Gutschke <gutschk@math.uni-muenster.de>
+
+ * tested the code against a CS8900 card
+
+ * lots of minor bug fixes and adjustments
+
+ * this is the first release, that actually works! it still requires some
+ changes in order to be more tolerant to different environments
+
+ * 4
+
+ Fri Nov 22 23:00:00 1996 Markus Gutschke <gutschk@math.uni-muenster.de>
+
+ * read the manuals for the CS89x0 chipsets and took note of all the
+ changes that will be neccessary in order to adapt Russel Nelson's code
+ to the requirements of a BOOT-Prom
+
+ * 6
+
+ Thu Nov 19 22:00:00 1996 Markus Gutschke <gutschk@math.uni-muenster.de>
+
+ * Synched with Russel Nelson's current code (v1.00)
+
+ * 2
+
+ Thu Nov 12 18:00:00 1996 Markus Gutschke <gutschk@math.uni-muenster.de>
+
+ * Cleaned up some of the code and tried to optimize the code size.
+
+ * 1.5
+
+ Sun Nov 10 16:30:00 1996 Markus Gutschke <gutschk@math.uni-muenster.de>
+
+ * First experimental release. This code compiles fine, but I
+ have no way of testing whether it actually works.
+
+ * I did not (yet) bother to make the code 16bit aware, so for
+ the time being, it will only work for Etherboot/32.
+
+ * 12
+
+ */
+
+#include <errno.h>
+#include <ipxe/ethernet.h>
+#include "etherboot.h"
+#include "nic.h"
+#include <ipxe/isa.h>
+#include "cs89x0.h"
+
+static unsigned short eth_nic_base;
+static unsigned long eth_mem_start;
+static unsigned short eth_irqno;
+static unsigned short eth_cs_type; /* one of: CS8900, CS8920, CS8920M */
+static unsigned short eth_auto_neg_cnf;
+static unsigned short eth_adapter_cnf;
+static unsigned short eth_linectl;
+
+/*************************************************************************
+ CS89x0 - specific routines
+**************************************************************************/
+
+static inline int readreg(int portno)
+{
+ outw(portno, eth_nic_base + ADD_PORT);
+ return inw(eth_nic_base + DATA_PORT);
+}
+
+static inline void writereg(int portno, int value)
+{
+ outw(portno, eth_nic_base + ADD_PORT);
+ outw(value, eth_nic_base + DATA_PORT);
+ return;
+}
+
+/*************************************************************************
+EEPROM access
+**************************************************************************/
+
+static int wait_eeprom_ready(void)
+{
+ unsigned long tmo = currticks() + 4*TICKS_PER_SEC;
+
+ /* check to see if the EEPROM is ready, a timeout is used -
+ just in case EEPROM is ready when SI_BUSY in the
+ PP_SelfST is clear */
+ while(readreg(PP_SelfST) & SI_BUSY) {
+ if (currticks() >= tmo)
+ return -1; }
+ return 0;
+}
+
+static int get_eeprom_data(int off, int len, unsigned short *buffer)
+{
+ int i;
+
+#ifdef EDEBUG
+ printf("\ncs: EEPROM data from %hX for %hX:",off,len);
+#endif
+ for (i = 0; i < len; i++) {
+ if (wait_eeprom_ready() < 0)
+ return -1;
+ /* Now send the EEPROM read command and EEPROM location
+ to read */
+ writereg(PP_EECMD, (off + i) | EEPROM_READ_CMD);
+ if (wait_eeprom_ready() < 0)
+ return -1;
+ buffer[i] = readreg(PP_EEData);
+#ifdef EDEBUG
+ if (!(i%10))
+ printf("\ncs: ");
+ printf("%hX ", buffer[i]);
+#endif
+ }
+#ifdef EDEBUG
+ putchar('\n');
+#endif
+
+ return(0);
+}
+
+static int get_eeprom_chksum(int off __unused, int len, unsigned short *buffer)
+{
+ int i, cksum;
+
+ cksum = 0;
+ for (i = 0; i < len; i++)
+ cksum += buffer[i];
+ cksum &= 0xffff;
+ if (cksum == 0)
+ return 0;
+ return -1;
+}
+
+/*************************************************************************
+Activate all of the available media and probe for network
+**************************************************************************/
+
+static void clrline(void)
+{
+ int i;
+
+ putchar('\r');
+ for (i = 79; i--; ) putchar(' ');
+ printf("\rcs: ");
+ return;
+}
+
+static void control_dc_dc(int on_not_off)
+{
+ unsigned int selfcontrol;
+ unsigned long tmo = currticks() + TICKS_PER_SEC;
+
+ /* control the DC to DC convertor in the SelfControl register. */
+ selfcontrol = HCB1_ENBL; /* Enable the HCB1 bit as an output */
+ if (((eth_adapter_cnf & A_CNF_DC_DC_POLARITY) != 0) ^ on_not_off)
+ selfcontrol |= HCB1;
+ else
+ selfcontrol &= ~HCB1;
+ writereg(PP_SelfCTL, selfcontrol);
+
+ /* Wait for the DC/DC converter to power up - 1000ms */
+ while (currticks() < tmo);
+
+ return;
+}
+
+static int detect_tp(void)
+{
+ unsigned long tmo;
+
+ /* Turn on the chip auto detection of 10BT/ AUI */
+
+ clrline(); printf("attempting %s:","TP");
+
+ /* If connected to another full duplex capable 10-Base-T card
+ the link pulses seem to be lost when the auto detect bit in
+ the LineCTL is set. To overcome this the auto detect bit
+ will be cleared whilst testing the 10-Base-T interface.
+ This would not be necessary for the sparrow chip but is
+ simpler to do it anyway. */
+ writereg(PP_LineCTL, eth_linectl &~ AUI_ONLY);
+ control_dc_dc(0);
+
+ /* Delay for the hardware to work out if the TP cable is
+ present - 150ms */
+ for (tmo = currticks() + 4; currticks() < tmo; );
+
+ if ((readreg(PP_LineST) & LINK_OK) == 0)
+ return 0;
+
+ if (eth_cs_type != CS8900) {
+
+ writereg(PP_AutoNegCTL, eth_auto_neg_cnf & AUTO_NEG_MASK);
+
+ if ((eth_auto_neg_cnf & AUTO_NEG_BITS) == AUTO_NEG_ENABLE) {
+ printf(" negotiating duplex... ");
+ while (readreg(PP_AutoNegST) & AUTO_NEG_BUSY) {
+ if (currticks() - tmo > 40*TICKS_PER_SEC) {
+ printf("time out ");
+ break;
+ }
+ }
+ }
+ if (readreg(PP_AutoNegST) & FDX_ACTIVE)
+ printf("using full duplex");
+ else
+ printf("using half duplex");
+ }
+
+ return A_CNF_MEDIA_10B_T;
+}
+
+/* send a test packet - return true if carrier bits are ok */
+static int send_test_pkt(struct nic *nic)
+{
+ static unsigned char testpacket[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
+ 0, 46, /*A 46 in network order */
+ 0, 0, /*DSAP=0 & SSAP=0 fields */
+ 0xf3,0 /*Control (Test Req+P bit set)*/ };
+ unsigned long tmo;
+
+ writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_TX_ON);
+
+ memcpy(testpacket, nic->node_addr, ETH_ALEN);
+ memcpy(testpacket+ETH_ALEN, nic->node_addr, ETH_ALEN);
+
+ outw(TX_AFTER_ALL, eth_nic_base + TX_CMD_PORT);
+ outw(ETH_ZLEN, eth_nic_base + TX_LEN_PORT);
+
+ /* Test to see if the chip has allocated memory for the packet */
+ for (tmo = currticks() + 2;
+ (readreg(PP_BusST) & READY_FOR_TX_NOW) == 0; )
+ if (currticks() >= tmo)
+ return(0);
+
+ /* Write the contents of the packet */
+ outsw(eth_nic_base + TX_FRAME_PORT, testpacket,
+ (ETH_ZLEN+1)>>1);
+
+ printf(" sending test packet ");
+ /* wait a couple of timer ticks for packet to be received */
+ for (tmo = currticks() + 2; currticks() < tmo; );
+
+ if ((readreg(PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
+ printf("succeeded");
+ return 1;
+ }
+ printf("failed");
+ return 0;
+}
+
+
+static int detect_aui(struct nic *nic)
+{
+ clrline(); printf("attempting %s:","AUI");
+ control_dc_dc(0);
+
+ writereg(PP_LineCTL, (eth_linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
+
+ if (send_test_pkt(nic)) {
+ return A_CNF_MEDIA_AUI; }
+ else
+ return 0;
+}
+
+static int detect_bnc(struct nic *nic)
+{
+ clrline(); printf("attempting %s:","BNC");
+ control_dc_dc(1);
+
+ writereg(PP_LineCTL, (eth_linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
+
+ if (send_test_pkt(nic)) {
+ return A_CNF_MEDIA_10B_2; }
+ else
+ return 0;
+}
+
+/**************************************************************************
+ETH_RESET - Reset adapter
+***************************************************************************/
+
+static void cs89x0_reset(struct nic *nic)
+{
+ int i;
+ unsigned long reset_tmo;
+
+ writereg(PP_SelfCTL, readreg(PP_SelfCTL) | POWER_ON_RESET);
+
+ /* wait for two ticks; that is 2*55ms */
+ for (reset_tmo = currticks() + 2; currticks() < reset_tmo; );
+
+ if (eth_cs_type != CS8900) {
+ /* Hardware problem requires PNP registers to be reconfigured
+ after a reset */
+ if (eth_irqno != 0xFFFF) {
+ outw(PP_CS8920_ISAINT, eth_nic_base + ADD_PORT);
+ outb(eth_irqno, eth_nic_base + DATA_PORT);
+ outb(0, eth_nic_base + DATA_PORT + 1); }
+
+ if (eth_mem_start) {
+ outw(PP_CS8920_ISAMemB, eth_nic_base + ADD_PORT);
+ outb((eth_mem_start >> 8) & 0xff, eth_nic_base + DATA_PORT);
+ outb((eth_mem_start >> 24) & 0xff, eth_nic_base + DATA_PORT + 1); } }
+
+ /* Wait until the chip is reset */
+ for (reset_tmo = currticks() + 2;
+ (readreg(PP_SelfST) & INIT_DONE) == 0 &&
+ currticks() < reset_tmo; );
+
+ /* disable interrupts and memory accesses */
+ writereg(PP_BusCTL, 0);
+
+ /* set the ethernet address */
+ for (i=0; i < ETH_ALEN/2; i++)
+ writereg(PP_IA+i*2,
+ nic->node_addr[i*2] |
+ (nic->node_addr[i*2+1] << 8));
+
+ /* receive only error free packets addressed to this card */
+ writereg(PP_RxCTL, DEF_RX_ACCEPT);
+
+ /* do not generate any interrupts on receive operations */
+ writereg(PP_RxCFG, 0);
+
+ /* do not generate any interrupts on transmit operations */
+ writereg(PP_TxCFG, 0);
+
+ /* do not generate any interrupts on buffer operations */
+ writereg(PP_BufCFG, 0);
+
+ /* reset address port, so that autoprobing will keep working */
+ outw(PP_ChipID, eth_nic_base + ADD_PORT);
+
+ return;
+}
+
+/**************************************************************************
+ETH_TRANSMIT - Transmit a frame
+***************************************************************************/
+
+static void cs89x0_transmit(
+ struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ unsigned long tmo;
+ int sr;
+
+ /* does this size have to be rounded??? please,
+ somebody have a look in the specs */
+ if ((sr = ((s + ETH_HLEN + 1)&~1)) < ETH_ZLEN)
+ sr = ETH_ZLEN;
+
+retry:
+ /* initiate a transmit sequence */
+ outw(TX_AFTER_ALL, eth_nic_base + TX_CMD_PORT);
+ outw(sr, eth_nic_base + TX_LEN_PORT);
+
+ /* Test to see if the chip has allocated memory for the packet */
+ if ((readreg(PP_BusST) & READY_FOR_TX_NOW) == 0) {
+ /* Oops... this should not happen! */
+ printf("cs: unable to send packet; retrying...\n");
+ for (tmo = currticks() + 5*TICKS_PER_SEC; currticks() < tmo; );
+ cs89x0_reset(nic);
+ goto retry; }
+
+ /* Write the contents of the packet */
+ outsw(eth_nic_base + TX_FRAME_PORT, d, ETH_ALEN/2);
+ outsw(eth_nic_base + TX_FRAME_PORT, nic->node_addr,
+ ETH_ALEN/2);
+ outw(((t >> 8)&0xFF)|(t << 8), eth_nic_base + TX_FRAME_PORT);
+ outsw(eth_nic_base + TX_FRAME_PORT, p, (s+1)/2);
+ for (sr = sr/2 - (s+1)/2 - ETH_ALEN - 1; sr > 0; sr--)
+ outw(0, eth_nic_base + TX_FRAME_PORT);
+
+ /* wait for transfer to succeed */
+ for (tmo = currticks()+5*TICKS_PER_SEC;
+ (s = readreg(PP_TxEvent)&~0x1F) == 0 && currticks() < tmo;)
+ /* nothing */ ;
+ if ((s & TX_SEND_OK_BITS) != TX_OK) {
+ printf("\ntransmission error %#hX\n", s);
+ }
+
+ return;
+}
+
+/**************************************************************************
+ETH_POLL - Wait for a frame
+***************************************************************************/
+
+static int cs89x0_poll(struct nic *nic, int retrieve)
+{
+ int status;
+
+ status = readreg(PP_RxEvent);
+
+ if ((status & RX_OK) == 0)
+ return(0);
+
+ if ( ! retrieve ) return 1;
+
+ status = inw(eth_nic_base + RX_FRAME_PORT);
+ nic->packetlen = inw(eth_nic_base + RX_FRAME_PORT);
+ insw(eth_nic_base + RX_FRAME_PORT, nic->packet, nic->packetlen >> 1);
+ if (nic->packetlen & 1)
+ nic->packet[nic->packetlen-1] = inw(eth_nic_base + RX_FRAME_PORT);
+ return 1;
+}
+
+static void cs89x0_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations cs89x0_operations = {
+ .connect = dummy_connect,
+ .poll = cs89x0_poll,
+ .transmit = cs89x0_transmit,
+ .irq = cs89x0_irq,
+};
+
+/**************************************************************************
+ETH_PROBE - Look for an adapter
+***************************************************************************/
+
+static int cs89x0_probe_addr ( isa_probe_addr_t ioaddr ) {
+ /* if they give us an odd I/O address, then do ONE write to
+ the address port, to get it back to address zero, where we
+ expect to find the EISA signature word. */
+ if (ioaddr & 1) {
+ ioaddr &= ~1;
+ if ((inw(ioaddr + ADD_PORT) & ADD_MASK) != ADD_SIG)
+ return 0;
+ outw(PP_ChipID, ioaddr + ADD_PORT);
+ }
+
+ if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG)
+ return 0;
+
+ return 1;
+}
+
+static int cs89x0_probe ( struct nic *nic, struct isa_device *isa __unused ) {
+ int i, result = -1;
+ unsigned rev_type = 0, isa_cnf, cs_revision;
+ unsigned short eeprom_buff[CHKSUM_LEN];
+
+ nic->ioaddr &= ~1; /* LSB = 1 indicates a more aggressive probe */
+ eth_nic_base = nic->ioaddr;
+
+ /* get the chip type */
+ rev_type = readreg(PRODUCT_ID_ADD);
+ eth_cs_type = rev_type &~ REVISON_BITS;
+ cs_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
+
+ printf("\ncs: cs89%c0%s rev %c, base %#hX",
+ eth_cs_type==CS8900?'0':'2',
+ eth_cs_type==CS8920M?"M":"",
+ cs_revision,
+ eth_nic_base);
+#ifndef EMBEDDED
+ /* First check to see if an EEPROM is attached*/
+ if ((readreg(PP_SelfST) & EEPROM_PRESENT) == 0) {
+ printf("\ncs: no EEPROM...\n");
+ outw(PP_ChipID, eth_nic_base + ADD_PORT);
+ return 0;
+ } else if (get_eeprom_data(START_EEPROM_DATA,CHKSUM_LEN,
+ eeprom_buff) < 0) {
+ printf("\ncs: EEPROM read failed...\n");
+ outw(PP_ChipID, eth_nic_base + ADD_PORT);
+ return 0;
+ } else if (get_eeprom_chksum(START_EEPROM_DATA,CHKSUM_LEN,
+ eeprom_buff) < 0) {
+ printf("\ncs: EEPROM checksum bad...\n");
+ outw(PP_ChipID, eth_nic_base + ADD_PORT);
+ return 0;
+ }
+
+ /* get transmission control word but keep the
+ autonegotiation bits */
+ eth_auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET/2];
+ /* Store adapter configuration */
+ eth_adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET/2];
+ /* Store ISA configuration */
+ isa_cnf = eeprom_buff[ISA_CNF_OFFSET/2];
+
+ /* store the initial memory base address */
+ eth_mem_start = eeprom_buff[PACKET_PAGE_OFFSET/2] << 8;
+
+ printf("%s%s%s, addr ",
+ (eth_adapter_cnf & A_CNF_10B_T)?", RJ-45":"",
+ (eth_adapter_cnf & A_CNF_AUI)?", AUI":"",
+ (eth_adapter_cnf & A_CNF_10B_2)?", BNC":"");
+
+ /* If this is a CS8900 then no pnp soft */
+ if (eth_cs_type != CS8900 &&
+ /* Check if the ISA IRQ has been set */
+ (i = readreg(PP_CS8920_ISAINT) & 0xff,
+ (i != 0 && i < CS8920_NO_INTS)))
+ eth_irqno = i;
+ else {
+ i = isa_cnf & INT_NO_MASK;
+ if (eth_cs_type == CS8900) {
+ /* the table that follows is dependent
+ upon how you wired up your cs8900
+ in your system. The table is the
+ same as the cs8900 engineering demo
+ board. irq_map also depends on the
+ contents of the table. Also see
+ write_irq, which is the reverse
+ mapping of the table below. */
+ if (i < 4) i = "\012\013\014\005"[i];
+ else printf("\ncs: BUG: isa_config is %d\n", i); }
+ eth_irqno = i; }
+
+ nic->irqno = eth_irqno;
+
+ /* Retrieve and print the ethernet address. */
+ for (i=0; i<ETH_ALEN; i++) {
+ nic->node_addr[i] = ((unsigned char *)eeprom_buff)[i];
+ }
+
+ DBG ( "%s\n", eth_ntoa ( nic->node_addr ) );
+
+#endif
+#ifdef EMBEDDED
+ /* Retrieve and print the ethernet address. */
+ {
+ unsigned char MAC_HW_ADDR[6]={MAC_HW_ADDR_DRV};
+ memcpy(nic->node_addr, MAC_HW_ADDR, 6);
+ }
+
+ DBG ( "%s\n", eth_ntoa ( nic->node_addr ) );
+
+ eth_adapter_cnf = A_CNF_10B_T | A_CNF_MEDIA_10B_T;
+ eth_auto_neg_cnf = EE_AUTO_NEG_ENABLE | IMM_BIT;
+#endif
+#ifndef EMBEDDED
+ /* Set the LineCTL quintuplet based on adapter
+ configuration read from EEPROM */
+ if ((eth_adapter_cnf & A_CNF_EXTND_10B_2) &&
+ (eth_adapter_cnf & A_CNF_LOW_RX_SQUELCH))
+ eth_linectl = LOW_RX_SQUELCH;
+ else
+ eth_linectl = 0;
+
+ /* check to make sure that they have the "right"
+ hardware available */
+ switch(eth_adapter_cnf & A_CNF_MEDIA_TYPE) {
+ case A_CNF_MEDIA_10B_T: result = eth_adapter_cnf & A_CNF_10B_T;
+ break;
+ case A_CNF_MEDIA_AUI: result = eth_adapter_cnf & A_CNF_AUI;
+ break;
+ case A_CNF_MEDIA_10B_2: result = eth_adapter_cnf & A_CNF_10B_2;
+ break;
+ default: result = eth_adapter_cnf & (A_CNF_10B_T | A_CNF_AUI |
+ A_CNF_10B_2);
+ }
+ if (!result) {
+ printf("cs: EEPROM is configured for unavailable media\n");
+ error:
+ writereg(PP_LineCTL, readreg(PP_LineCTL) &
+ ~(SERIAL_TX_ON | SERIAL_RX_ON));
+ outw(PP_ChipID, eth_nic_base + ADD_PORT);
+ return 0;
+ }
+#endif
+ /* Initialize the card for probing of the attached media */
+ cs89x0_reset(nic);
+
+ /* set the hardware to the configured choice */
+ switch(eth_adapter_cnf & A_CNF_MEDIA_TYPE) {
+ case A_CNF_MEDIA_10B_T:
+ result = detect_tp();
+ if (!result) {
+ clrline();
+ printf("10Base-T (RJ-45%s",
+ ") has no cable\n"); }
+ /* check "ignore missing media" bit */
+ if (eth_auto_neg_cnf & IMM_BIT)
+ /* Yes! I don't care if I see a link pulse */
+ result = A_CNF_MEDIA_10B_T;
+ break;
+ case A_CNF_MEDIA_AUI:
+ result = detect_aui(nic);
+ if (!result) {
+ clrline();
+ printf("10Base-5 (AUI%s",
+ ") has no cable\n"); }
+ /* check "ignore missing media" bit */
+ if (eth_auto_neg_cnf & IMM_BIT)
+ /* Yes! I don't care if I see a carrrier */
+ result = A_CNF_MEDIA_AUI;
+ break;
+ case A_CNF_MEDIA_10B_2:
+ result = detect_bnc(nic);
+ if (!result) {
+ clrline();
+ printf("10Base-2 (BNC%s",
+ ") has no cable\n"); }
+ /* check "ignore missing media" bit */
+ if (eth_auto_neg_cnf & IMM_BIT)
+ /* Yes! I don't care if I can xmit a packet */
+ result = A_CNF_MEDIA_10B_2;
+ break;
+ case A_CNF_MEDIA_AUTO:
+ writereg(PP_LineCTL, eth_linectl | AUTO_AUI_10BASET);
+ if (eth_adapter_cnf & A_CNF_10B_T)
+ if ((result = detect_tp()) != 0)
+ break;
+ if (eth_adapter_cnf & A_CNF_AUI)
+ if ((result = detect_aui(nic)) != 0)
+ break;
+ if (eth_adapter_cnf & A_CNF_10B_2)
+ if ((result = detect_bnc(nic)) != 0)
+ break;
+ clrline(); printf("no media detected\n");
+ goto error;
+ }
+ clrline();
+ switch(result) {
+ case 0: printf("no network cable attached to configured media\n");
+ goto error;
+ case A_CNF_MEDIA_10B_T: printf("using 10Base-T (RJ-45)\n");
+ break;
+ case A_CNF_MEDIA_AUI: printf("using 10Base-5 (AUI)\n");
+ break;
+ case A_CNF_MEDIA_10B_2: printf("using 10Base-2 (BNC)\n");
+ break;
+ }
+
+ /* Turn on both receive and transmit operations */
+ writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_RX_ON |
+ SERIAL_TX_ON);
+
+ return 0;
+#ifdef EMBEDDED
+ error:
+ writereg(PP_LineCTL, readreg(PP_LineCTL) &
+ ~(SERIAL_TX_ON | SERIAL_RX_ON));
+ outw(PP_ChipID, eth_nic_base + ADD_PORT);
+ return 0;
+#endif
+
+ nic->nic_op = &cs89x0_operations;
+ return 1;
+}
+
+static void cs89x0_disable ( struct nic *nic,
+ struct isa_device *isa __unused ) {
+ cs89x0_reset(nic);
+}
+
+static isa_probe_addr_t cs89x0_probe_addrs[] = {
+#ifndef EMBEDDED
+ /* use "conservative" default values for autoprobing */
+ 0x300, 0x320, 0x340, 0x200, 0x220, 0x240,
+ 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0,
+ /* if that did not work, then be more aggressive */
+ 0x301, 0x321, 0x341, 0x201, 0x221, 0x241,
+ 0x261, 0x281, 0x2a1, 0x2c1, 0x2e1,
+#else
+ 0x01000300,
+#endif
+};
+
+ISA_DRIVER ( cs89x0_driver, cs89x0_probe_addrs, cs89x0_probe_addr,
+ ISAPNP_VENDOR('C','S','C'), 0x0007 );
+
+DRIVER ( "cs89x0", nic_driver, isa_driver, cs89x0_driver,
+ cs89x0_probe, cs89x0_disable );
+
+ISA_ROM ( "cs89x0", "Crystal Semiconductor CS89x0" );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/cs89x0.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/cs89x0.h
new file mode 100644
index 00000000..a36b907c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/cs89x0.h
@@ -0,0 +1,481 @@
+/**
+ Per an email message from Russ Nelson <nelson@crynwr.com> on
+ 18 March 2008 this file is now licensed under GPL Version 2.
+
+ From: Russ Nelson <nelson@crynwr.com>
+ Date: Tue, 18 Mar 2008 12:42:00 -0400
+ Subject: Re: [Etherboot-developers] cs89x0 driver in etherboot
+ -- quote from email
+ As copyright holder, if I say it doesn't conflict with the GPL,
+ then it doesn't conflict with the GPL.
+
+ However, there's no point in causing people's brains to overheat,
+ so yes, I grant permission for the code to be relicensed under the
+ GPLv2. Please make sure that this change in licensing makes its
+ way upstream. -russ
+ -- quote from email
+**/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/* Copyright, 1988-1992, Russell Nelson, Crynwr Software
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, version 1.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define PP_ChipID 0x0000 /* offset 0h -> Corp -ID */
+ /* offset 2h -> Model/Product Number */
+ /* offset 3h -> Chip Revision Number */
+
+#define PP_ISAIOB 0x0020 /* IO base address */
+#define PP_CS8900_ISAINT 0x0022 /* ISA interrupt select */
+#define PP_CS8920_ISAINT 0x0370 /* ISA interrupt select */
+#define PP_CS8900_ISADMA 0x0024 /* ISA Rec DMA channel */
+#define PP_CS8920_ISADMA 0x0374 /* ISA Rec DMA channel */
+#define PP_ISASOF 0x0026 /* ISA DMA offset */
+#define PP_DmaFrameCnt 0x0028 /* ISA DMA Frame count */
+#define PP_DmaByteCnt 0x002A /* ISA DMA Byte count */
+#define PP_CS8900_ISAMemB 0x002C /* Memory base */
+#define PP_CS8920_ISAMemB 0x0348 /* */
+
+#define PP_ISABootBase 0x0030 /* Boot Prom base */
+#define PP_ISABootMask 0x0034 /* Boot Prom Mask */
+
+/* EEPROM data and command registers */
+#define PP_EECMD 0x0040 /* NVR Interface Command register */
+#define PP_EEData 0x0042 /* NVR Interface Data Register */
+#define PP_DebugReg 0x0044 /* Debug Register */
+
+#define PP_RxCFG 0x0102 /* Rx Bus config */
+#define PP_RxCTL 0x0104 /* Receive Control Register */
+#define PP_TxCFG 0x0106 /* Transmit Config Register */
+#define PP_TxCMD 0x0108 /* Transmit Command Register */
+#define PP_BufCFG 0x010A /* Bus configuration Register */
+#define PP_LineCTL 0x0112 /* Line Config Register */
+#define PP_SelfCTL 0x0114 /* Self Command Register */
+#define PP_BusCTL 0x0116 /* ISA bus control Register */
+#define PP_TestCTL 0x0118 /* Test Register */
+#define PP_AutoNegCTL 0x011C /* Auto Negotiation Ctrl */
+
+#define PP_ISQ 0x0120 /* Interrupt Status */
+#define PP_RxEvent 0x0124 /* Rx Event Register */
+#define PP_TxEvent 0x0128 /* Tx Event Register */
+#define PP_BufEvent 0x012C /* Bus Event Register */
+#define PP_RxMiss 0x0130 /* Receive Miss Count */
+#define PP_TxCol 0x0132 /* Transmit Collision Count */
+#define PP_LineST 0x0134 /* Line State Register */
+#define PP_SelfST 0x0136 /* Self State register */
+#define PP_BusST 0x0138 /* Bus Status */
+#define PP_TDR 0x013C /* Time Domain Reflectometry */
+#define PP_AutoNegST 0x013E /* Auto Neg Status */
+#define PP_TxCommand 0x0144 /* Tx Command */
+#define PP_TxLength 0x0146 /* Tx Length */
+#define PP_LAF 0x0150 /* Hash Table */
+#define PP_IA 0x0158 /* Physical Address Register */
+
+#define PP_RxStatus 0x0400 /* Receive start of frame */
+#define PP_RxLength 0x0402 /* Receive Length of frame */
+#define PP_RxFrame 0x0404 /* Receive frame pointer */
+#define PP_TxFrame 0x0A00 /* Transmit frame pointer */
+
+/* Primary I/O Base Address. If no I/O base is supplied by the user, then this */
+/* can be used as the default I/O base to access the PacketPage Area. */
+#define DEFAULTIOBASE 0x0300
+#define FIRST_IO 0x020C /* First I/O port to check */
+#define LAST_IO 0x037C /* Last I/O port to check (+10h) */
+#define ADD_MASK 0x3000 /* Mask it use of the ADD_PORT register */
+#define ADD_SIG 0x3000 /* Expected ID signature */
+
+#define CHIP_EISA_ID_SIG 0x630E /* Product ID Code for Crystal Chip (CS8900 spec 4.3) */
+
+#ifdef IBMEIPKT
+#define EISA_ID_SIG 0x4D24 /* IBM */
+#define PART_NO_SIG 0x1010 /* IBM */
+#define MONGOOSE_BIT 0x0000 /* IBM */
+#else
+#define EISA_ID_SIG 0x630E /* PnP Vendor ID (same as chip id for Crystal board) */
+#define PART_NO_SIG 0x4000 /* ID code CS8920 board (PnP Vendor Product code) */
+#define MONGOOSE_BIT 0x2000 /* PART_NO_SIG + MONGOOSE_BUT => ID of mongoose */
+#endif
+
+#define PRODUCT_ID_ADD 0x0002 /* Address of product ID */
+
+/* Mask to find out the types of registers */
+#define REG_TYPE_MASK 0x001F
+
+/* Eeprom Commands */
+#define ERSE_WR_ENBL 0x00F0
+#define ERSE_WR_DISABLE 0x0000
+
+/* Defines Control/Config register quintuplet numbers */
+#define RX_BUF_CFG 0x0003
+#define RX_CONTROL 0x0005
+#define TX_CFG 0x0007
+#define TX_COMMAND 0x0009
+#define BUF_CFG 0x000B
+#define LINE_CONTROL 0x0013
+#define SELF_CONTROL 0x0015
+#define BUS_CONTROL 0x0017
+#define TEST_CONTROL 0x0019
+
+/* Defines Status/Count registers quintuplet numbers */
+#define RX_EVENT 0x0004
+#define TX_EVENT 0x0008
+#define BUF_EVENT 0x000C
+#define RX_MISS_COUNT 0x0010
+#define TX_COL_COUNT 0x0012
+#define LINE_STATUS 0x0014
+#define SELF_STATUS 0x0016
+#define BUS_STATUS 0x0018
+#define TDR 0x001C
+
+/* PP_RxCFG - Receive Configuration and Interrupt Mask bit definition - Read/write */
+#define SKIP_1 0x0040
+#define RX_STREAM_ENBL 0x0080
+#define RX_OK_ENBL 0x0100
+#define RX_DMA_ONLY 0x0200
+#define AUTO_RX_DMA 0x0400
+#define BUFFER_CRC 0x0800
+#define RX_CRC_ERROR_ENBL 0x1000
+#define RX_RUNT_ENBL 0x2000
+#define RX_EXTRA_DATA_ENBL 0x4000
+
+/* PP_RxCTL - Receive Control bit definition - Read/write */
+#define RX_IA_HASH_ACCEPT 0x0040
+#define RX_PROM_ACCEPT 0x0080
+#define RX_OK_ACCEPT 0x0100
+#define RX_MULTCAST_ACCEPT 0x0200
+#define RX_IA_ACCEPT 0x0400
+#define RX_BROADCAST_ACCEPT 0x0800
+#define RX_BAD_CRC_ACCEPT 0x1000
+#define RX_RUNT_ACCEPT 0x2000
+#define RX_EXTRA_DATA_ACCEPT 0x4000
+#define RX_ALL_ACCEPT (RX_PROM_ACCEPT|RX_BAD_CRC_ACCEPT|RX_RUNT_ACCEPT|RX_EXTRA_DATA_ACCEPT)
+/* Default receive mode - individually addressed, broadcast, and error free */
+#define DEF_RX_ACCEPT (RX_IA_ACCEPT | RX_BROADCAST_ACCEPT | RX_OK_ACCEPT)
+
+/* PP_TxCFG - Transmit Configuration Interrupt Mask bit definition - Read/write */
+#define TX_LOST_CRS_ENBL 0x0040
+#define TX_SQE_ERROR_ENBL 0x0080
+#define TX_OK_ENBL 0x0100
+#define TX_LATE_COL_ENBL 0x0200
+#define TX_JBR_ENBL 0x0400
+#define TX_ANY_COL_ENBL 0x0800
+#define TX_16_COL_ENBL 0x8000
+
+/* PP_TxCMD - Transmit Command bit definition - Read-only */
+#define TX_START_4_BYTES 0x0000
+#define TX_START_64_BYTES 0x0040
+#define TX_START_128_BYTES 0x0080
+#define TX_START_ALL_BYTES 0x00C0
+#define TX_FORCE 0x0100
+#define TX_ONE_COL 0x0200
+#define TX_TWO_PART_DEFF_DISABLE 0x0400
+#define TX_NO_CRC 0x1000
+#define TX_RUNT 0x2000
+
+/* PP_BufCFG - Buffer Configuration Interrupt Mask bit definition - Read/write */
+#define GENERATE_SW_INTERRUPT 0x0040
+#define RX_DMA_ENBL 0x0080
+#define READY_FOR_TX_ENBL 0x0100
+#define TX_UNDERRUN_ENBL 0x0200
+#define RX_MISS_ENBL 0x0400
+#define RX_128_BYTE_ENBL 0x0800
+#define TX_COL_COUNT_OVRFLOW_ENBL 0x1000
+#define RX_MISS_COUNT_OVRFLOW_ENBL 0x2000
+#define RX_DEST_MATCH_ENBL 0x8000
+
+/* PP_LineCTL - Line Control bit definition - Read/write */
+#define SERIAL_RX_ON 0x0040
+#define SERIAL_TX_ON 0x0080
+#define AUI_ONLY 0x0100
+#define AUTO_AUI_10BASET 0x0200
+#define MODIFIED_BACKOFF 0x0800
+#define NO_AUTO_POLARITY 0x1000
+#define TWO_PART_DEFDIS 0x2000
+#define LOW_RX_SQUELCH 0x4000
+
+/* PP_SelfCTL - Software Self Control bit definition - Read/write */
+#define POWER_ON_RESET 0x0040
+#define SW_STOP 0x0100
+#define SLEEP_ON 0x0200
+#define AUTO_WAKEUP 0x0400
+#define HCB0_ENBL 0x1000
+#define HCB1_ENBL 0x2000
+#define HCB0 0x4000
+#define HCB1 0x8000
+
+/* PP_BusCTL - ISA Bus Control bit definition - Read/write */
+#define RESET_RX_DMA 0x0040
+#define MEMORY_ON 0x0400
+#define DMA_BURST_MODE 0x0800
+#define IO_CHANNEL_READY_ON 0x1000
+#define RX_DMA_SIZE_64K 0x2000
+#define ENABLE_IRQ 0x8000
+
+/* PP_TestCTL - Test Control bit definition - Read/write */
+#define LINK_OFF 0x0080
+#define ENDEC_LOOPBACK 0x0200
+#define AUI_LOOPBACK 0x0400
+#define BACKOFF_OFF 0x0800
+#define FAST_TEST 0x8000
+
+/* PP_RxEvent - Receive Event Bit definition - Read-only */
+#define RX_IA_HASHED 0x0040
+#define RX_DRIBBLE 0x0080
+#define RX_OK 0x0100
+#define RX_HASHED 0x0200
+#define RX_IA 0x0400
+#define RX_BROADCAST 0x0800
+#define RX_CRC_ERROR 0x1000
+#define RX_RUNT 0x2000
+#define RX_EXTRA_DATA 0x4000
+
+#define HASH_INDEX_MASK 0x0FC00
+
+/* PP_TxEvent - Transmit Event Bit definition - Read-only */
+#define TX_LOST_CRS 0x0040
+#define TX_SQE_ERROR 0x0080
+#define TX_OK 0x0100
+#define TX_LATE_COL 0x0200
+#define TX_JBR 0x0400
+#define TX_16_COL 0x8000
+#define TX_SEND_OK_BITS (TX_OK|TX_LOST_CRS)
+#define TX_COL_COUNT_MASK 0x7800
+
+/* PP_BufEvent - Buffer Event Bit definition - Read-only */
+#define SW_INTERRUPT 0x0040
+#define RX_DMA 0x0080
+#define READY_FOR_TX 0x0100
+#define TX_UNDERRUN 0x0200
+#define RX_MISS 0x0400
+#define RX_128_BYTE 0x0800
+#define TX_COL_OVRFLW 0x1000
+#define RX_MISS_OVRFLW 0x2000
+#define RX_DEST_MATCH 0x8000
+
+/* PP_LineST - Ethernet Line Status bit definition - Read-only */
+#define LINK_OK 0x0080
+#define AUI_ON 0x0100
+#define TENBASET_ON 0x0200
+#define POLARITY_OK 0x1000
+#define CRS_OK 0x4000
+
+/* PP_SelfST - Chip Software Status bit definition */
+#define ACTIVE_33V 0x0040
+#define INIT_DONE 0x0080
+#define SI_BUSY 0x0100
+#define EEPROM_PRESENT 0x0200
+#define EEPROM_OK 0x0400
+#define EL_PRESENT 0x0800
+#define EE_SIZE_64 0x1000
+
+/* PP_BusST - ISA Bus Status bit definition */
+#define TX_BID_ERROR 0x0080
+#define READY_FOR_TX_NOW 0x0100
+
+/* PP_AutoNegCTL - Auto Negotiation Control bit definition */
+#define RE_NEG_NOW 0x0040
+#define ALLOW_FDX 0x0080
+#define AUTO_NEG_ENABLE 0x0100
+#define NLP_ENABLE 0x0200
+#define FORCE_FDX 0x8000
+#define AUTO_NEG_BITS (FORCE_FDX|NLP_ENABLE|AUTO_NEG_ENABLE)
+#define AUTO_NEG_MASK (FORCE_FDX|NLP_ENABLE|AUTO_NEG_ENABLE|ALLOW_FDX|RE_NEG_NOW)
+
+/* PP_AutoNegST - Auto Negotiation Status bit definition */
+#define AUTO_NEG_BUSY 0x0080
+#define FLP_LINK 0x0100
+#define FLP_LINK_GOOD 0x0800
+#define LINK_FAULT 0x1000
+#define HDX_ACTIVE 0x4000
+#define FDX_ACTIVE 0x8000
+
+/* The following block defines the ISQ event types */
+#define ISQ_RECEIVER_EVENT 0x04
+#define ISQ_TRANSMITTER_EVENT 0x08
+#define ISQ_BUFFER_EVENT 0x0c
+#define ISQ_RX_MISS_EVENT 0x10
+#define ISQ_TX_COL_EVENT 0x12
+
+#define ISQ_EVENT_MASK 0x003F /* ISQ mask to find out type of event */
+#define ISQ_HIST 16 /* small history buffer */
+#define AUTOINCREMENT 0x8000 /* Bit mask to set bit-15 for autoincrement */
+
+#define TXRXBUFSIZE 0x0600
+#define RXDMABUFSIZE 0x8000
+#define RXDMASIZE 0x4000
+#define TXRX_LENGTH_MASK 0x07FF
+
+/* rx options bits */
+#define RCV_WITH_RXON 1 /* Set SerRx ON */
+#define RCV_COUNTS 2 /* Use Framecnt1 */
+#define RCV_PONG 4 /* Pong respondent */
+#define RCV_DONG 8 /* Dong operation */
+#define RCV_POLLING 0x10 /* Poll RxEvent */
+#define RCV_ISQ 0x20 /* Use ISQ, int */
+#define RCV_AUTO_DMA 0x100 /* Set AutoRxDMAE */
+#define RCV_DMA 0x200 /* Set RxDMA only */
+#define RCV_DMA_ALL 0x400 /* Copy all DMA'ed */
+#define RCV_FIXED_DATA 0x800 /* Every frame same */
+#define RCV_IO 0x1000 /* Use ISA IO only */
+#define RCV_MEMORY 0x2000 /* Use ISA Memory */
+
+#define RAM_SIZE 0x1000 /* The card has 4k bytes or RAM */
+#define PKT_START PP_TxFrame /* Start of packet RAM */
+
+#define RX_FRAME_PORT 0x0000
+#define TX_FRAME_PORT RX_FRAME_PORT
+#define TX_CMD_PORT 0x0004
+#define TX_NOW 0x0000 /* Tx packet after 5 bytes copied */
+#define TX_AFTER_381 0x0020 /* Tx packet after 381 bytes copied */
+#define TX_AFTER_ALL 0x00C0 /* Tx packet after all bytes copied */
+#define TX_LEN_PORT 0x0006
+#define ISQ_PORT 0x0008
+#define ADD_PORT 0x000A
+#define DATA_PORT 0x000C
+
+#define EEPROM_WRITE_EN 0x00F0
+#define EEPROM_WRITE_DIS 0x0000
+#define EEPROM_WRITE_CMD 0x0100
+#define EEPROM_READ_CMD 0x0200
+
+/* Receive Header */
+/* Description of header of each packet in receive area of memory */
+#define RBUF_EVENT_LOW 0 /* Low byte of RxEvent - status of received frame */
+#define RBUF_EVENT_HIGH 1 /* High byte of RxEvent - status of received frame */
+#define RBUF_LEN_LOW 2 /* Length of received data - low byte */
+#define RBUF_LEN_HI 3 /* Length of received data - high byte */
+#define RBUF_HEAD_LEN 4 /* Length of this header */
+
+#define CHIP_READ 0x1 /* Used to mark state of the repins code (chip or dma) */
+#define DMA_READ 0x2 /* Used to mark state of the repins code (chip or dma) */
+
+/* for bios scan */
+/* */
+#ifdef CSDEBUG
+/* use these values for debugging bios scan */
+#define BIOS_START_SEG 0x00000
+#define BIOS_OFFSET_INC 0x0010
+#else
+#define BIOS_START_SEG 0x0c000
+#define BIOS_OFFSET_INC 0x0200
+#endif
+
+#define BIOS_LAST_OFFSET 0x0fc00
+
+/* Byte offsets into the EEPROM configuration buffer */
+#define ISA_CNF_OFFSET 0x6
+#define TX_CTL_OFFSET (ISA_CNF_OFFSET + 8) /* 8900 eeprom */
+#define AUTO_NEG_CNF_OFFSET (ISA_CNF_OFFSET + 8) /* 8920 eeprom */
+
+ /* the assumption here is that the bits in the eeprom are generally */
+ /* in the same position as those in the autonegctl register. */
+ /* Of course the IMM bit is not in that register so it must be */
+ /* masked out */
+#define EE_FORCE_FDX 0x8000
+#define EE_NLP_ENABLE 0x0200
+#define EE_AUTO_NEG_ENABLE 0x0100
+#define EE_ALLOW_FDX 0x0080
+#define EE_AUTO_NEG_CNF_MASK (EE_FORCE_FDX|EE_NLP_ENABLE|EE_AUTO_NEG_ENABLE|EE_ALLOW_FDX)
+
+#define IMM_BIT 0x0040 /* ignore missing media */
+
+#define ADAPTER_CNF_OFFSET (AUTO_NEG_CNF_OFFSET + 2)
+#define A_CNF_10B_T 0x0001
+#define A_CNF_AUI 0x0002
+#define A_CNF_10B_2 0x0004
+#define A_CNF_MEDIA_TYPE 0x0060
+#define A_CNF_MEDIA_AUTO 0x0000
+#define A_CNF_MEDIA_10B_T 0x0020
+#define A_CNF_MEDIA_AUI 0x0040
+#define A_CNF_MEDIA_10B_2 0x0060
+#define A_CNF_DC_DC_POLARITY 0x0080
+#define A_CNF_NO_AUTO_POLARITY 0x2000
+#define A_CNF_LOW_RX_SQUELCH 0x4000
+#define A_CNF_EXTND_10B_2 0x8000
+
+#define PACKET_PAGE_OFFSET 0x8
+
+/* Bit definitions for the ISA configuration word from the EEPROM */
+#define INT_NO_MASK 0x000F
+#define DMA_NO_MASK 0x0070
+#define ISA_DMA_SIZE 0x0200
+#define ISA_AUTO_RxDMA 0x0400
+#define ISA_RxDMA 0x0800
+#define DMA_BURST 0x1000
+#define STREAM_TRANSFER 0x2000
+#define ANY_ISA_DMA (ISA_AUTO_RxDMA | ISA_RxDMA)
+
+/* DMA controller registers */
+#define DMA_BASE 0x00 /* DMA controller base */
+#define DMA_BASE_2 0x0C0 /* DMA controller base */
+
+#define DMA_STAT 0x0D0 /* DMA controller status register */
+#define DMA_MASK 0x0D4 /* DMA controller mask register */
+#define DMA_MODE 0x0D6 /* DMA controller mode register */
+#define DMA_RESETFF 0x0D8 /* DMA controller first/last flip flop */
+
+/* DMA data */
+#define DMA_DISABLE 0x04 /* Disable channel n */
+#define DMA_ENABLE 0x00 /* Enable channel n */
+/* Demand transfers, incr. address, auto init, writes, ch. n */
+#define DMA_RX_MODE 0x14
+/* Demand transfers, incr. address, auto init, reads, ch. n */
+#define DMA_TX_MODE 0x18
+
+#define DMA_SIZE (16*1024) /* Size of dma buffer - 16k */
+
+#define CS8900 0x0000
+#define CS8920 0x4000
+#define CS8920M 0x6000
+#define REVISON_BITS 0x1F00
+#define EEVER_NUMBER 0x12
+#define CHKSUM_LEN 0x14
+#define CHKSUM_VAL 0x0000
+#define START_EEPROM_DATA 0x001c /* Offset into eeprom for start of data */
+#define IRQ_MAP_EEPROM_DATA 0x0046 /* Offset into eeprom for the IRQ map */
+#define IRQ_MAP_LEN 0x0004 /* No of bytes to read for the IRQ map */
+#define PNP_IRQ_FRMT 0x0022 /* PNP small item IRQ format */
+#define CS8900_IRQ_MAP 0x1c20 /* This IRQ map is fixed */
+
+#define CS8920_NO_INTS 0x0F /* Max CS8920 interrupt select # */
+
+#define PNP_ADD_PORT 0x0279
+#define PNP_WRITE_PORT 0x0A79
+
+#define GET_PNP_ISA_STRUCT 0x40
+#define PNP_ISA_STRUCT_LEN 0x06
+#define PNP_CSN_CNT_OFF 0x01
+#define PNP_RD_PORT_OFF 0x02
+#define PNP_FUNCTION_OK 0x00
+#define PNP_WAKE 0x03
+#define PNP_RSRC_DATA 0x04
+#define PNP_RSRC_READY 0x01
+#define PNP_STATUS 0x05
+#define PNP_ACTIVATE 0x30
+#define PNP_CNF_IO_H 0x60
+#define PNP_CNF_IO_L 0x61
+#define PNP_CNF_INT 0x70
+#define PNP_CNF_DMA 0x74
+#define PNP_CNF_MEM 0x48
+
+#define BIT0 1
+#define BIT15 0x8000
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/cs89x0.txt b/src/VBox/Devices/PC/ipxe/src/drivers/net/cs89x0.txt
new file mode 100644
index 00000000..72b7df28
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/cs89x0.txt
@@ -0,0 +1,45 @@
+/**
+ Per an email message from Russ Nelson <nelson@crynwr.com> on
+ 18 March 2008 the files cs89x0.[ch] are now licensed under GPL
+ Version 2.
+
+ From: Russ Nelson <nelson@crynwr.com>
+ Date: Tue, 18 Mar 2008 12:42:00 -0400
+ Subject: Re: [Etherboot-developers] cs89x0 driver in etherboot
+ -- quote from email
+ As copyright holder, if I say it doesn't conflict with the GPL,
+ then it doesn't conflict with the GPL.
+
+ However, there's no point in causing people's brains to overheat,
+ so yes, I grant permission for the code to be relicensed under the
+ GPLv2. Please make sure that this change in licensing makes its
+ way upstream. -russ
+ -- quote from email
+**/
+
+Permission is granted to distribute the enclosed cs89x0.[ch] driver
+only in conjunction with the Etherboot package. The code is
+ordinarily distributed under the GPL.
+
+Russ Nelson, January 2000
+
+CREDITS
+
+I want to thank
+
+ Mike Cruse <mcruse@cti-ltd.com>
+ for providing an evaluation NIC and for sponsoring the
+ development of this driver.
+
+ Randall Sears <sears@crystal.cirrus.com>
+ Deva Bodas <bodas@crystal.cirrus.com>
+ Andreas Kraemer <akraemer@crystal.cirrus.com>
+ Wolfgang Krause <100303.2673@compuserve.com>
+ for excellent technical support and for providing the required
+ programming information. I appreciate Crystal Semiconductor's
+ commitment towards free software.
+
+ Russell Nelson <nelson@crynwr.com>
+ for writing the Linux device driver for the CS89x0
+ chipset. Russel's code is very well designed and simplified my
+ job a lot.
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/davicom.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/davicom.c
new file mode 100644
index 00000000..14117742
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/davicom.c
@@ -0,0 +1,708 @@
+#ifdef ALLMULTI
+#error multicast support is not yet implemented
+#endif
+/*
+ DAVICOM DM9009/DM9102/DM9102A Etherboot Driver V1.00
+
+ This driver was ported from Marty Connor's Tulip Etherboot driver.
+ Thanks Marty Connor (mdc@etherboot.org)
+
+ This davicom etherboot driver supports DM9009/DM9102/DM9102A/
+ DM9102A+DM9801/DM9102A+DM9802 NICs.
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License, incorporated herein by reference.
+
+*/
+
+FILE_LICENCE ( GPL_ANY );
+
+/*********************************************************************/
+/* Revision History */
+/*********************************************************************/
+
+/*
+ 19 OCT 2000 Sten 1.00
+ Different half and full duplex mode
+ Do the different programming for DM9801/DM9802
+
+ 12 OCT 2000 Sten 0.90
+ This driver was ported from tulip driver and it
+ has the following difference.
+ Changed symbol tulip/TULIP to davicom/DAVICOM
+ Deleted some code that did not use in this driver.
+ Used chain-strcture to replace ring structure
+ for both TX/RX descriptor.
+ Allocated two tx descriptor.
+ According current media mode to set operating
+ register(CR6)
+*/
+
+
+/*********************************************************************/
+/* Declarations */
+/*********************************************************************/
+
+#include "etherboot.h"
+#include "nic.h"
+#include <ipxe/pci.h>
+#include <ipxe/ethernet.h>
+
+#define TX_TIME_OUT 2*TICKS_PER_SEC
+
+/* Register offsets for davicom device */
+enum davicom_offsets {
+ CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
+ CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
+ CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x80, CSR20=0xA0
+};
+
+/* EEPROM Address width definitions */
+#define EEPROM_ADDRLEN 6
+#define EEPROM_SIZE 32 /* 1 << EEPROM_ADDRLEN */
+/* Used to be 128, but we only need to read enough to get the MAC
+ address at bytes 20..25 */
+
+/* Data Read from the EEPROM */
+static unsigned char ee_data[EEPROM_SIZE];
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD (5 << addr_len)
+#define EE_READ_CMD (6 << addr_len)
+#define EE_ERASE_CMD (7 << addr_len)
+
+/* EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */
+#define EE_CS 0x01 /* EEPROM chip select. */
+#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
+#define EE_WRITE_0 0x01
+#define EE_WRITE_1 0x05
+#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
+#define EE_ENB (0x4800 | EE_CS)
+
+/* Sten 10/11 for phyxcer */
+#define PHY_DATA_0 0x0
+#define PHY_DATA_1 0x20000
+#define MDCLKH 0x10000
+
+/* Delay between EEPROM clock transitions. Even at 33Mhz current PCI
+ implementations don't overrun the EEPROM clock. We add a bus
+ turn-around to insure that this remains true. */
+#define eeprom_delay() inl(ee_addr)
+
+/* helpful macro if on a big_endian machine for changing byte order.
+ not strictly needed on Intel
+ Already defined in Etherboot includes
+#define le16_to_cpu(val) (val)
+*/
+
+/* transmit and receive descriptor format */
+struct txdesc {
+ volatile unsigned long status; /* owner, status */
+ unsigned long buf1sz:11, /* size of buffer 1 */
+ buf2sz:11, /* size of buffer 2 */
+ control:10; /* control bits */
+ const unsigned char *buf1addr; /* buffer 1 address */
+ const unsigned char *buf2addr; /* buffer 2 address */
+};
+
+struct rxdesc {
+ volatile unsigned long status; /* owner, status */
+ unsigned long buf1sz:11, /* size of buffer 1 */
+ buf2sz:11, /* size of buffer 2 */
+ control:10; /* control bits */
+ unsigned char *buf1addr; /* buffer 1 address */
+ unsigned char *buf2addr; /* buffer 2 address */
+};
+
+/* Size of transmit and receive buffers */
+#define BUFLEN 1536
+
+/*********************************************************************/
+/* Global Storage */
+/*********************************************************************/
+
+static struct nic_operations davicom_operations;
+
+/* PCI Bus parameters */
+static unsigned short vendor, dev_id;
+static unsigned long ioaddr;
+
+/* Note: transmit and receive buffers must be longword aligned and
+ longword divisable */
+
+/* transmit descriptor and buffer */
+#define NTXD 2
+#define NRXD 4
+struct {
+ struct txdesc txd[NTXD] __attribute__ ((aligned(4)));
+ unsigned char txb[BUFLEN] __attribute__ ((aligned(4)));
+ struct rxdesc rxd[NRXD] __attribute__ ((aligned(4)));
+ unsigned char rxb[NRXD * BUFLEN] __attribute__ ((aligned(4)));
+} davicom_bufs __shared;
+#define txd davicom_bufs.txd
+#define txb davicom_bufs.txb
+#define rxd davicom_bufs.rxd
+#define rxb davicom_bufs.rxb
+static int rxd_tail;
+static int TxPtr;
+
+
+/*********************************************************************/
+/* Function Prototypes */
+/*********************************************************************/
+static void whereami(const char *str);
+static int read_eeprom(unsigned long ioaddr, int location, int addr_len);
+static int davicom_probe(struct nic *nic,struct pci_device *pci);
+static void davicom_init_chain(struct nic *nic); /* Sten 10/9 */
+static void davicom_reset(struct nic *nic);
+static void davicom_transmit(struct nic *nic, const char *d, unsigned int t,
+ unsigned int s, const char *p);
+static int davicom_poll(struct nic *nic, int retrieve);
+static void davicom_disable(struct nic *nic);
+static void davicom_wait(unsigned int nticks);
+static int phy_read(int);
+static void phy_write(int, u16);
+static void phy_write_1bit(u32, u32);
+static int phy_read_1bit(u32);
+static void davicom_media_chk(struct nic *);
+
+
+/*********************************************************************/
+/* Utility Routines */
+/*********************************************************************/
+static inline void whereami(const char *str)
+{
+ DBGP("%s\n", str);
+ /* sleep(2); */
+}
+
+static void davicom_wait(unsigned int nticks)
+{
+ unsigned int to = currticks() + nticks;
+ while (currticks() < to)
+ /* wait */ ;
+}
+
+
+/*********************************************************************/
+/* For DAVICOM phyxcer register by MII interface */
+/*********************************************************************/
+/*
+ Read a word data from phy register
+*/
+static int phy_read(int location)
+{
+ int i, phy_addr=1;
+ u16 phy_data;
+ u32 io_dcr9;
+
+ whereami("phy_read\n");
+
+ io_dcr9 = ioaddr + CSR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i=0; i<34; i++)
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(io_dcr9, PHY_DATA_0);
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+
+ /* Send read command(10) to Phy */
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+ phy_write_1bit(io_dcr9, PHY_DATA_0);
+
+ /* Send Phy addres */
+ for (i=0x10; i>0; i=i>>1)
+ phy_write_1bit(io_dcr9, phy_addr&i ? PHY_DATA_1: PHY_DATA_0);
+
+ /* Send register addres */
+ for (i=0x10; i>0; i=i>>1)
+ phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0);
+
+ /* Skip transition state */
+ phy_read_1bit(io_dcr9);
+
+ /* read 16bit data */
+ for (phy_data=0, i=0; i<16; i++) {
+ phy_data<<=1;
+ phy_data|=phy_read_1bit(io_dcr9);
+ }
+
+ return phy_data;
+}
+
+/*
+ Write a word to Phy register
+*/
+static void phy_write(int location, u16 phy_data)
+{
+ u16 i, phy_addr=1;
+ u32 io_dcr9;
+
+ whereami("phy_write\n");
+
+ io_dcr9 = ioaddr + CSR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i=0; i<34; i++)
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(io_dcr9, PHY_DATA_0);
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+
+ /* Send write command(01) to Phy */
+ phy_write_1bit(io_dcr9, PHY_DATA_0);
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+
+ /* Send Phy addres */
+ for (i=0x10; i>0; i=i>>1)
+ phy_write_1bit(io_dcr9, phy_addr&i ? PHY_DATA_1: PHY_DATA_0);
+
+ /* Send register addres */
+ for (i=0x10; i>0; i=i>>1)
+ phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0);
+
+ /* written trasnition */
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+ phy_write_1bit(io_dcr9, PHY_DATA_0);
+
+ /* Write a word data to PHY controller */
+ for (i=0x8000; i>0; i>>=1)
+ phy_write_1bit(io_dcr9, phy_data&i ? PHY_DATA_1: PHY_DATA_0);
+}
+
+/*
+ Write one bit data to Phy Controller
+*/
+static void phy_write_1bit(u32 ee_addr, u32 phy_data)
+{
+ whereami("phy_write_1bit\n");
+ outl(phy_data, ee_addr); /* MII Clock Low */
+ eeprom_delay();
+ outl(phy_data|MDCLKH, ee_addr); /* MII Clock High */
+ eeprom_delay();
+ outl(phy_data, ee_addr); /* MII Clock Low */
+ eeprom_delay();
+}
+
+/*
+ Read one bit phy data from PHY controller
+*/
+static int phy_read_1bit(u32 ee_addr)
+{
+ int phy_data;
+
+ whereami("phy_read_1bit\n");
+
+ outl(0x50000, ee_addr);
+ eeprom_delay();
+
+ phy_data=(inl(ee_addr)>>19) & 0x1;
+
+ outl(0x40000, ee_addr);
+ eeprom_delay();
+
+ return phy_data;
+}
+
+/*
+ DM9801/DM9802 present check and program
+*/
+static void HPNA_process(void)
+{
+
+ if ( (phy_read(3) & 0xfff0) == 0xb900 ) {
+ if ( phy_read(31) == 0x4404 ) {
+ /* DM9801 present */
+ if (phy_read(3) == 0xb901)
+ phy_write(16, 0x5); /* DM9801 E4 */
+ else
+ phy_write(16, 0x1005); /* DM9801 E3 and others */
+ phy_write(25, ((phy_read(24) + 3) & 0xff) | 0xf000);
+ } else {
+ /* DM9802 present */
+ phy_write(16, 0x5);
+ phy_write(25, (phy_read(25) & 0xff00) + 2);
+ }
+ }
+}
+
+/*
+ Sense media mode and set CR6
+*/
+static void davicom_media_chk(struct nic * nic __unused)
+{
+ unsigned long to, csr6;
+
+ csr6 = 0x00200000; /* SF */
+ outl(csr6, ioaddr + CSR6);
+
+#define PCI_DEVICE_ID_DM9009 0x9009
+ if (vendor == PCI_VENDOR_ID_DAVICOM && dev_id == PCI_DEVICE_ID_DM9009) {
+ /* Set to 10BaseT mode for DM9009 */
+ phy_write(0, 0);
+ } else {
+ /* For DM9102/DM9102A */
+ to = currticks() + 2 * TICKS_PER_SEC;
+ while ( ((phy_read(1) & 0x24)!=0x24) && (currticks() < to))
+ /* wait */ ;
+
+ if ( (phy_read(1) & 0x24) == 0x24 ) {
+ if (phy_read(17) & 0xa000)
+ csr6 |= 0x00000200; /* Full Duplex mode */
+ } else
+ csr6 |= 0x00040000; /* Select DM9801/DM9802 when Ethernet link failed */
+ }
+
+ /* set the chip's operating mode */
+ outl(csr6, ioaddr + CSR6);
+
+ /* DM9801/DM9802 present check & program */
+ if (csr6 & 0x40000)
+ HPNA_process();
+}
+
+
+/*********************************************************************/
+/* EEPROM Reading Code */
+/*********************************************************************/
+/* EEPROM routines adapted from the Linux Tulip Code */
+/* Reading a serial EEPROM is a "bit" grungy, but we work our way
+ through:->.
+*/
+static int read_eeprom(unsigned long ioaddr, int location, int addr_len)
+{
+ int i;
+ unsigned short retval = 0;
+ long ee_addr = ioaddr + CSR9;
+ int read_cmd = location | EE_READ_CMD;
+
+ whereami("read_eeprom\n");
+
+ outl(EE_ENB & ~EE_CS, ee_addr);
+ outl(EE_ENB, ee_addr);
+
+ /* Shift the read command bits out. */
+ for (i = 4 + addr_len; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ outl(EE_ENB | dataval, ee_addr);
+ eeprom_delay();
+ outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay();
+ }
+ outl(EE_ENB, ee_addr);
+
+ for (i = 16; i > 0; i--) {
+ outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay();
+ retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
+ outl(EE_ENB, ee_addr);
+ eeprom_delay();
+ }
+
+ /* Terminate the EEPROM access. */
+ outl(EE_ENB & ~EE_CS, ee_addr);
+ return retval;
+}
+
+/*********************************************************************/
+/* davicom_init_chain - setup the tx and rx descriptors */
+/* Sten 10/9 */
+/*********************************************************************/
+static void davicom_init_chain(struct nic *nic)
+{
+ int i;
+
+ /* setup the transmit descriptor */
+ /* Sten: Set 2 TX descriptor but use one TX buffer because
+ it transmit a packet and wait complete every time. */
+ for (i=0; i<NTXD; i++) {
+ txd[i].buf1addr = (void *)virt_to_bus(&txb[0]); /* Used same TX buffer */
+ txd[i].buf2addr = (void *)virt_to_bus(&txd[i+1]); /* Point to Next TX desc */
+ txd[i].buf1sz = 0;
+ txd[i].buf2sz = 0;
+ txd[i].control = 0x184; /* Begin/End/Chain */
+ txd[i].status = 0x00000000; /* give ownership to Host */
+ }
+
+ /* construct perfect filter frame with mac address as first match
+ and broadcast address for all others */
+ for (i=0; i<192; i++) txb[i] = 0xFF;
+ txb[0] = nic->node_addr[0];
+ txb[1] = nic->node_addr[1];
+ txb[4] = nic->node_addr[2];
+ txb[5] = nic->node_addr[3];
+ txb[8] = nic->node_addr[4];
+ txb[9] = nic->node_addr[5];
+
+ /* setup receive descriptor */
+ for (i=0; i<NRXD; i++) {
+ rxd[i].buf1addr = (void *)virt_to_bus(&rxb[i * BUFLEN]);
+ rxd[i].buf2addr = (void *)virt_to_bus(&rxd[i+1]); /* Point to Next RX desc */
+ rxd[i].buf1sz = BUFLEN;
+ rxd[i].buf2sz = 0; /* not used */
+ rxd[i].control = 0x4; /* Chain Structure */
+ rxd[i].status = 0x80000000; /* give ownership to device */
+ }
+
+ /* Chain the last descriptor to first */
+ txd[NTXD - 1].buf2addr = (void *)virt_to_bus(&txd[0]);
+ rxd[NRXD - 1].buf2addr = (void *)virt_to_bus(&rxd[0]);
+ TxPtr = 0;
+ rxd_tail = 0;
+}
+
+
+/*********************************************************************/
+/* davicom_reset - Reset adapter */
+/*********************************************************************/
+static void davicom_reset(struct nic *nic)
+{
+ unsigned long to;
+
+ whereami("davicom_reset\n");
+
+ /* Stop Tx and RX */
+ outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
+
+ /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
+ outl(0x00000001, ioaddr + CSR0);
+
+ davicom_wait(TICKS_PER_SEC);
+
+ /* TX/RX descriptor burst */
+ outl(0x0C00000, ioaddr + CSR0); /* Sten 10/9 */
+
+ /* set up transmit and receive descriptors */
+ davicom_init_chain(nic); /* Sten 10/9 */
+
+ /* Point to receive descriptor */
+ outl(virt_to_bus(&rxd[0]), ioaddr + CSR3);
+ outl(virt_to_bus(&txd[0]), ioaddr + CSR4); /* Sten 10/9 */
+
+ /* According phyxcer media mode to set CR6,
+ DM9102/A phyxcer can auto-detect media mode */
+ davicom_media_chk(nic);
+
+ /* Prepare Setup Frame Sten 10/9 */
+ txd[TxPtr].buf1sz = 192;
+ txd[TxPtr].control = 0x024; /* SF/CE */
+ txd[TxPtr].status = 0x80000000; /* Give ownership to device */
+
+ /* Start Tx */
+ outl(inl(ioaddr + CSR6) | 0x00002000, ioaddr + CSR6);
+ /* immediate transmit demand */
+ outl(0, ioaddr + CSR1);
+
+ to = currticks() + TX_TIME_OUT;
+ while ((txd[TxPtr].status & 0x80000000) && (currticks() < to)) /* Sten 10/9 */
+ /* wait */ ;
+
+ if (currticks() >= to) {
+ DBG ("TX Setup Timeout!\n");
+ }
+ /* Point to next TX descriptor */
+ TxPtr = (++TxPtr >= NTXD) ? 0:TxPtr; /* Sten 10/9 */
+
+ DBG("txd.status = %lX\n", txd[TxPtr].status);
+ DBG("ticks = %ld\n", currticks() - (to - TX_TIME_OUT));
+ DBG_MORE();
+
+ /* enable RX */
+ outl(inl(ioaddr + CSR6) | 0x00000002, ioaddr + CSR6);
+ /* immediate poll demand */
+ outl(0, ioaddr + CSR2);
+}
+
+
+/*********************************************************************/
+/* eth_transmit - Transmit a frame */
+/*********************************************************************/
+static void davicom_transmit(struct nic *nic, const char *d, unsigned int t,
+ unsigned int s, const char *p)
+{
+ unsigned long to;
+
+ whereami("davicom_transmit\n");
+
+ /* Stop Tx */
+ /* outl(inl(ioaddr + CSR6) & ~0x00002000, ioaddr + CSR6); */
+
+ /* setup ethernet header */
+ memcpy(&txb[0], d, ETH_ALEN); /* DA 6byte */
+ memcpy(&txb[ETH_ALEN], nic->node_addr, ETH_ALEN); /* SA 6byte*/
+ txb[ETH_ALEN*2] = (t >> 8) & 0xFF; /* Frame type: 2byte */
+ txb[ETH_ALEN*2+1] = t & 0xFF;
+ memcpy(&txb[ETH_HLEN], p, s); /* Frame data */
+
+ /* setup the transmit descriptor */
+ txd[TxPtr].buf1sz = ETH_HLEN+s;
+ txd[TxPtr].control = 0x00000184; /* LS+FS+CE */
+ txd[TxPtr].status = 0x80000000; /* give ownership to device */
+
+ /* immediate transmit demand */
+ outl(0, ioaddr + CSR1);
+
+ to = currticks() + TX_TIME_OUT;
+ while ((txd[TxPtr].status & 0x80000000) && (currticks() < to))
+ /* wait */ ;
+
+ if (currticks() >= to) {
+ DBG ("TX Timeout!\n");
+ }
+
+ /* Point to next TX descriptor */
+ TxPtr = (++TxPtr >= NTXD) ? 0:TxPtr; /* Sten 10/9 */
+
+}
+
+/*********************************************************************/
+/* eth_poll - Wait for a frame */
+/*********************************************************************/
+static int davicom_poll(struct nic *nic, int retrieve)
+{
+ whereami("davicom_poll\n");
+
+ if (rxd[rxd_tail].status & 0x80000000)
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+ whereami("davicom_poll got one\n");
+
+ nic->packetlen = (rxd[rxd_tail].status & 0x3FFF0000) >> 16;
+
+ if( rxd[rxd_tail].status & 0x00008000){
+ rxd[rxd_tail].status = 0x80000000;
+ rxd_tail++;
+ if (rxd_tail == NRXD) rxd_tail = 0;
+ return 0;
+ }
+
+ /* copy packet to working buffer */
+ /* XXX - this copy could be avoided with a little more work
+ but for now we are content with it because the optimised
+ memcpy is quite fast */
+
+ memcpy(nic->packet, rxb + rxd_tail * BUFLEN, nic->packetlen);
+
+ /* return the descriptor and buffer to receive ring */
+ rxd[rxd_tail].status = 0x80000000;
+ rxd_tail++;
+ if (rxd_tail == NRXD) rxd_tail = 0;
+
+ return 1;
+}
+
+/*********************************************************************/
+/* eth_disable - Disable the interface */
+/*********************************************************************/
+static void davicom_disable ( struct nic *nic ) {
+
+ whereami("davicom_disable\n");
+
+ davicom_reset(nic);
+
+ /* disable interrupts */
+ outl(0x00000000, ioaddr + CSR7);
+
+ /* Stop the chip's Tx and Rx processes. */
+ outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
+
+ /* Clear the missed-packet counter. */
+ inl(ioaddr + CSR8);
+}
+
+
+/*********************************************************************/
+/* eth_irq - enable, disable and force interrupts */
+/*********************************************************************/
+static void davicom_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+
+/*********************************************************************/
+/* eth_probe - Look for an adapter */
+/*********************************************************************/
+static int davicom_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ unsigned int i;
+
+ whereami("davicom_probe\n");
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ vendor = pci->vendor;
+ dev_id = pci->device;
+ ioaddr = pci->ioaddr;
+
+ nic->ioaddr = pci->ioaddr;
+ nic->irqno = 0;
+
+ /* wakeup chip */
+ pci_write_config_dword(pci, 0x40, 0x00000000);
+
+ /* Stop the chip's Tx and Rx processes. */
+ outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
+
+ /* Clear the missed-packet counter. */
+ inl(ioaddr + CSR8);
+
+ /* Get MAC Address */
+ /* read EEPROM data */
+ for (i = 0; i < sizeof(ee_data)/2; i++)
+ ((unsigned short *)ee_data)[i] =
+ le16_to_cpu(read_eeprom(ioaddr, i, EEPROM_ADDRLEN));
+
+ /* extract MAC address from EEPROM buffer */
+ for (i=0; i<ETH_ALEN; i++)
+ nic->node_addr[i] = ee_data[20+i];
+
+ DBG ( "Davicom %s at IOADDR %4.4lx\n", eth_ntoa ( nic->node_addr ), ioaddr );
+
+ /* initialize device */
+ davicom_reset(nic);
+ nic->nic_op = &davicom_operations;
+ return 1;
+}
+
+static struct nic_operations davicom_operations = {
+ .connect = dummy_connect,
+ .poll = davicom_poll,
+ .transmit = davicom_transmit,
+ .irq = davicom_irq,
+
+};
+
+static struct pci_device_id davicom_nics[] = {
+PCI_ROM(0x1282, 0x9100, "davicom9100", "Davicom 9100", 0),
+PCI_ROM(0x1282, 0x9102, "davicom9102", "Davicom 9102", 0),
+PCI_ROM(0x1282, 0x9009, "davicom9009", "Davicom 9009", 0),
+PCI_ROM(0x1282, 0x9132, "davicom9132", "Davicom 9132", 0), /* Needs probably some fixing */
+};
+
+PCI_DRIVER ( davicom_driver, davicom_nics, PCI_NO_CLASS );
+
+DRIVER ( "DAVICOM", nic_driver, pci_driver, davicom_driver,
+ davicom_probe, davicom_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/depca.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/depca.c
new file mode 100644
index 00000000..016f28bb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/depca.c
@@ -0,0 +1,804 @@
+/* #warning "depca.c: FIXME: fix relocation" */
+
+FILE_LICENCE ( GPL_ANY );
+
+#if 0
+/* Not fixed for relocation yet. Probably won't work relocated above 16MB */
+#ifdef ALLMULTI
+#error multicast support is not yet implemented
+#endif
+/* Etherboot: depca.h merged, comments from Linux driver retained */
+/* depca.c: A DIGITAL DEPCA & EtherWORKS ethernet driver for linux.
+
+ Written 1994, 1995 by David C. Davies.
+
+
+ Copyright 1994 David C. Davies
+ and
+ United States Government
+ (as represented by the Director, National Security Agency).
+
+ Copyright 1995 Digital Equipment Corporation.
+
+
+ This software may be used and distributed according to the terms of
+ the GNU Public License, incorporated herein by reference.
+
+ This driver is written for the Digital Equipment Corporation series
+ of DEPCA and EtherWORKS ethernet cards:
+
+ DEPCA (the original)
+ DE100
+ DE101
+ DE200 Turbo
+ DE201 Turbo
+ DE202 Turbo (TP BNC)
+ DE210
+ DE422 (EISA)
+
+ The driver has been tested on DE100, DE200 and DE202 cards in a
+ relatively busy network. The DE422 has been tested a little.
+
+ This driver will NOT work for the DE203, DE204 and DE205 series of
+ cards, since they have a new custom ASIC in place of the AMD LANCE
+ chip. See the 'ewrk3.c' driver in the Linux source tree for running
+ those cards.
+
+ I have benchmarked the driver with a DE100 at 595kB/s to (542kB/s from)
+ a DECstation 5000/200.
+
+ The author may be reached at davies@maniac.ultranet.com
+
+ =========================================================================
+
+ The driver was originally based on the 'lance.c' driver from Donald
+ Becker which is included with the standard driver distribution for
+ linux. V0.4 is a complete re-write with only the kernel interface
+ remaining from the original code.
+
+ 1) Lance.c code in /linux/drivers/net/
+ 2) "Ethernet/IEEE 802.3 Family. 1992 World Network Data Book/Handbook",
+ AMD, 1992 [(800) 222-9323].
+ 3) "Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE)",
+ AMD, Pub. #17881, May 1993.
+ 4) "Am79C960 PCnet-ISA(tm), Single-Chip Ethernet Controller for ISA",
+ AMD, Pub. #16907, May 1992
+ 5) "DEC EtherWORKS LC Ethernet Controller Owners Manual",
+ Digital Equipment corporation, 1990, Pub. #EK-DE100-OM.003
+ 6) "DEC EtherWORKS Turbo Ethernet Controller Owners Manual",
+ Digital Equipment corporation, 1990, Pub. #EK-DE200-OM.003
+ 7) "DEPCA Hardware Reference Manual", Pub. #EK-DEPCA-PR
+ Digital Equipment Corporation, 1989
+ 8) "DEC EtherWORKS Turbo_(TP BNC) Ethernet Controller Owners Manual",
+ Digital Equipment corporation, 1991, Pub. #EK-DE202-OM.001
+
+
+ Peter Bauer's depca.c (V0.5) was referred to when debugging V0.1 of this
+ driver.
+
+ The original DEPCA card requires that the ethernet ROM address counter
+ be enabled to count and has an 8 bit NICSR. The ROM counter enabling is
+ only done when a 0x08 is read as the first address octet (to minimise
+ the chances of writing over some other hardware's I/O register). The
+ NICSR accesses have been changed to byte accesses for all the cards
+ supported by this driver, since there is only one useful bit in the MSB
+ (remote boot timeout) and it is not used. Also, there is a maximum of
+ only 48kB network RAM for this card. My thanks to Torbjorn Lindh for
+ help debugging all this (and holding my feet to the fire until I got it
+ right).
+
+ The DE200 series boards have on-board 64kB RAM for use as a shared
+ memory network buffer. Only the DE100 cards make use of a 2kB buffer
+ mode which has not been implemented in this driver (only the 32kB and
+ 64kB modes are supported [16kB/48kB for the original DEPCA]).
+
+ At the most only 2 DEPCA cards can be supported on the ISA bus because
+ there is only provision for two I/O base addresses on each card (0x300
+ and 0x200). The I/O address is detected by searching for a byte sequence
+ in the Ethernet station address PROM at the expected I/O address for the
+ Ethernet PROM. The shared memory base address is 'autoprobed' by
+ looking for the self test PROM and detecting the card name. When a
+ second DEPCA is detected, information is placed in the base_addr
+ variable of the next device structure (which is created if necessary),
+ thus enabling ethif_probe initialization for the device. More than 2
+ EISA cards can be supported, but care will be needed assigning the
+ shared memory to ensure that each slot has the correct IRQ, I/O address
+ and shared memory address assigned.
+
+ ************************************************************************
+
+ NOTE: If you are using two ISA DEPCAs, it is important that you assign
+ the base memory addresses correctly. The driver autoprobes I/O 0x300
+ then 0x200. The base memory address for the first device must be less
+ than that of the second so that the auto probe will correctly assign the
+ I/O and memory addresses on the same card. I can't think of a way to do
+ this unambiguously at the moment, since there is nothing on the cards to
+ tie I/O and memory information together.
+
+ I am unable to test 2 cards together for now, so this code is
+ unchecked. All reports, good or bad, are welcome.
+
+ ************************************************************************
+
+ The board IRQ setting must be at an unused IRQ which is auto-probed
+ using Donald Becker's autoprobe routines. DEPCA and DE100 board IRQs are
+ {2,3,4,5,7}, whereas the DE200 is at {5,9,10,11,15}. Note that IRQ2 is
+ really IRQ9 in machines with 16 IRQ lines.
+
+ No 16MB memory limitation should exist with this driver as DMA is not
+ used and the common memory area is in low memory on the network card (my
+ current system has 20MB and I've not had problems yet).
+
+ The ability to load this driver as a loadable module has been added. To
+ utilise this ability, you have to do <8 things:
+
+ 0) have a copy of the loadable modules code installed on your system.
+ 1) copy depca.c from the /linux/drivers/net directory to your favourite
+ temporary directory.
+ 2) if you wish, edit the source code near line 1530 to reflect the I/O
+ address and IRQ you're using (see also 5).
+ 3) compile depca.c, but include -DMODULE in the command line to ensure
+ that the correct bits are compiled (see end of source code).
+ 4) if you are wanting to add a new card, goto 5. Otherwise, recompile a
+ kernel with the depca configuration turned off and reboot.
+ 5) insmod depca.o [irq=7] [io=0x200] [mem=0xd0000] [adapter_name=DE100]
+ [Alan Cox: Changed the code to allow command line irq/io assignments]
+ [Dave Davies: Changed the code to allow command line mem/name
+ assignments]
+ 6) run the net startup bits for your eth?? interface manually
+ (usually /etc/rc.inet[12] at boot time).
+ 7) enjoy!
+
+ Note that autoprobing is not allowed in loadable modules - the system is
+ already up and running and you're messing with interrupts.
+
+ To unload a module, turn off the associated interface
+ 'ifconfig eth?? down' then 'rmmod depca'.
+
+ To assign a base memory address for the shared memory when running as a
+ loadable module, see 5 above. To include the adapter name (if you have
+ no PROM but know the card name) also see 5 above. Note that this last
+ option will not work with kernel built-in depca's.
+
+ The shared memory assignment for a loadable module makes sense to avoid
+ the 'memory autoprobe' picking the wrong shared memory (for the case of
+ 2 depca's in a PC).
+
+ ************************************************************************
+ Support for MCA EtherWORKS cards added 11-3-98.
+ Verified to work with up to 2 DE212 cards in a system (although not
+ fully stress-tested).
+
+ Currently known bugs/limitations:
+
+ Note: with the MCA stuff as a module, it trusts the MCA configuration,
+ not the command line for IRQ and memory address. You can
+ specify them if you want, but it will throw your values out.
+ You still have to pass the IO address it was configured as
+ though.
+
+ ************************************************************************
+ TO DO:
+ ------
+
+
+ Revision History
+ ----------------
+
+ Version Date Description
+
+ 0.1 25-jan-94 Initial writing.
+ 0.2 27-jan-94 Added LANCE TX hardware buffer chaining.
+ 0.3 1-feb-94 Added multiple DEPCA support.
+ 0.31 4-feb-94 Added DE202 recognition.
+ 0.32 19-feb-94 Tidy up. Improve multi-DEPCA support.
+ 0.33 25-feb-94 Fix DEPCA ethernet ROM counter enable.
+ Add jabber packet fix from murf@perftech.com
+ and becker@super.org
+ 0.34 7-mar-94 Fix DEPCA max network memory RAM & NICSR access.
+ 0.35 8-mar-94 Added DE201 recognition. Tidied up.
+ 0.351 30-apr-94 Added EISA support. Added DE422 recognition.
+ 0.36 16-may-94 DE422 fix released.
+ 0.37 22-jul-94 Added MODULE support
+ 0.38 15-aug-94 Added DBR ROM switch in depca_close().
+ Multi DEPCA bug fix.
+ 0.38axp 15-sep-94 Special version for Alpha AXP Linux V1.0.
+ 0.381 12-dec-94 Added DE101 recognition, fix multicast bug.
+ 0.382 9-feb-95 Fix recognition bug reported by <bkm@star.rl.ac.uk>.
+ 0.383 22-feb-95 Fix for conflict with VESA SCSI reported by
+ <stromain@alf.dec.com>
+ 0.384 17-mar-95 Fix a ring full bug reported by <bkm@star.rl.ac.uk>
+ 0.385 3-apr-95 Fix a recognition bug reported by
+ <ryan.niemi@lastfrontier.com>
+ 0.386 21-apr-95 Fix the last fix...sorry, must be galloping senility
+ 0.40 25-May-95 Rewrite for portability & updated.
+ ALPHA support from <jestabro@amt.tay1.dec.com>
+ 0.41 26-Jun-95 Added verify_area() calls in depca_ioctl() from
+ suggestion by <heiko@colossus.escape.de>
+ 0.42 27-Dec-95 Add 'mem' shared memory assignment for loadable
+ modules.
+ Add 'adapter_name' for loadable modules when no PROM.
+ Both above from a suggestion by
+ <pchen@woodruffs121.residence.gatech.edu>.
+ Add new multicasting code.
+ 0.421 22-Apr-96 Fix alloc_device() bug <jari@markkus2.fimr.fi>
+ 0.422 29-Apr-96 Fix depca_hw_init() bug <jari@markkus2.fimr.fi>
+ 0.423 7-Jun-96 Fix module load bug <kmg@barco.be>
+ 0.43 16-Aug-96 Update alloc_device() to conform to de4x5.c
+ 0.44 1-Sep-97 Fix *_probe() to test check_region() first - bug
+ reported by <mmogilvi@elbert.uccs.edu>
+ 0.45 3-Nov-98 Added support for MCA EtherWORKS (DE210/DE212) cards
+ by <tymm@computer.org>
+ 0.451 5-Nov-98 Fixed mca stuff cuz I'm a dummy. <tymm@computer.org>
+ 0.5 14-Nov-98 Re-spin for 2.1.x kernels.
+ 0.51 27-Jun-99 Correct received packet length for CRC from
+ report by <worm@dkik.dk>
+
+ =========================================================================
+*/
+
+#include "etherboot.h"
+#include "nic.h"
+#include <ipxe/isa.h>
+#include <ipxe/ethernet.h>
+
+/*
+** I/O addresses. Note that the 2k buffer option is not supported in
+** this driver.
+*/
+#define DEPCA_NICSR 0x00 /* Network interface CSR */
+#define DEPCA_RBI 0x02 /* RAM buffer index (2k buffer mode) */
+#define DEPCA_DATA 0x04 /* LANCE registers' data port */
+#define DEPCA_ADDR 0x06 /* LANCE registers' address port */
+#define DEPCA_HBASE 0x08 /* EISA high memory base address reg. */
+#define DEPCA_PROM 0x0c /* Ethernet address ROM data port */
+#define DEPCA_CNFG 0x0c /* EISA Configuration port */
+#define DEPCA_RBSA 0x0e /* RAM buffer starting address (2k buff.) */
+
+/*
+** These are LANCE registers addressable through nic->ioaddr + DEPCA_ADDR
+*/
+#define CSR0 0
+#define CSR1 1
+#define CSR2 2
+#define CSR3 3
+
+/*
+** NETWORK INTERFACE CSR (NI_CSR) bit definitions
+*/
+
+#define TO 0x0100 /* Time Out for remote boot */
+#define SHE 0x0080 /* SHadow memory Enable */
+#define BS 0x0040 /* Bank Select */
+#define BUF 0x0020 /* BUFfer size (1->32k, 0->64k) */
+#define RBE 0x0010 /* Remote Boot Enable (1->net boot) */
+#define AAC 0x0008 /* Address ROM Address Counter (1->enable) */
+#define _128KB 0x0008 /* 128kB Network RAM (1->enable) */
+#define IM 0x0004 /* Interrupt Mask (1->mask) */
+#define IEN 0x0002 /* Interrupt tristate ENable (1->enable) */
+#define LED 0x0001 /* LED control */
+
+/*
+** Control and Status Register 0 (CSR0) bit definitions
+*/
+
+#define ERR 0x8000 /* Error summary */
+#define BABL 0x4000 /* Babble transmitter timeout error */
+#define CERR 0x2000 /* Collision Error */
+#define MISS 0x1000 /* Missed packet */
+#define MERR 0x0800 /* Memory Error */
+#define RINT 0x0400 /* Receiver Interrupt */
+#define TINT 0x0200 /* Transmit Interrupt */
+#define IDON 0x0100 /* Initialization Done */
+#define INTR 0x0080 /* Interrupt Flag */
+#define INEA 0x0040 /* Interrupt Enable */
+#define RXON 0x0020 /* Receiver on */
+#define TXON 0x0010 /* Transmitter on */
+#define TDMD 0x0008 /* Transmit Demand */
+#define STOP 0x0004 /* Stop */
+#define STRT 0x0002 /* Start */
+#define INIT 0x0001 /* Initialize */
+#define INTM 0xff00 /* Interrupt Mask */
+#define INTE 0xfff0 /* Interrupt Enable */
+
+/*
+** CONTROL AND STATUS REGISTER 3 (CSR3)
+*/
+
+#define BSWP 0x0004 /* Byte SWaP */
+#define ACON 0x0002 /* ALE control */
+#define BCON 0x0001 /* Byte CONtrol */
+
+/*
+** Initialization Block Mode Register
+*/
+
+#define PROM 0x8000 /* Promiscuous Mode */
+#define EMBA 0x0080 /* Enable Modified Back-off Algorithm */
+#define INTL 0x0040 /* Internal Loopback */
+#define DRTY 0x0020 /* Disable Retry */
+#define COLL 0x0010 /* Force Collision */
+#define DTCR 0x0008 /* Disable Transmit CRC */
+#define LOOP 0x0004 /* Loopback */
+#define DTX 0x0002 /* Disable the Transmitter */
+#define DRX 0x0001 /* Disable the Receiver */
+
+/*
+** Receive Message Descriptor 1 (RMD1) bit definitions.
+*/
+
+#define R_OWN 0x80000000 /* Owner bit 0 = host, 1 = lance */
+#define R_ERR 0x4000 /* Error Summary */
+#define R_FRAM 0x2000 /* Framing Error */
+#define R_OFLO 0x1000 /* Overflow Error */
+#define R_CRC 0x0800 /* CRC Error */
+#define R_BUFF 0x0400 /* Buffer Error */
+#define R_STP 0x0200 /* Start of Packet */
+#define R_ENP 0x0100 /* End of Packet */
+
+/*
+** Transmit Message Descriptor 1 (TMD1) bit definitions.
+*/
+
+#define T_OWN 0x80000000 /* Owner bit 0 = host, 1 = lance */
+#define T_ERR 0x4000 /* Error Summary */
+#define T_ADD_FCS 0x2000 /* More the 1 retry needed to Xmit */
+#define T_MORE 0x1000 /* >1 retry to transmit packet */
+#define T_ONE 0x0800 /* 1 try needed to transmit the packet */
+#define T_DEF 0x0400 /* Deferred */
+#define T_STP 0x02000000 /* Start of Packet */
+#define T_ENP 0x01000000 /* End of Packet */
+#define T_FLAGS 0xff000000 /* TX Flags Field */
+
+/*
+** Transmit Message Descriptor 3 (TMD3) bit definitions.
+*/
+
+#define TMD3_BUFF 0x8000 /* BUFFer error */
+#define TMD3_UFLO 0x4000 /* UnderFLOw error */
+#define TMD3_RES 0x2000 /* REServed */
+#define TMD3_LCOL 0x1000 /* Late COLlision */
+#define TMD3_LCAR 0x0800 /* Loss of CARrier */
+#define TMD3_RTRY 0x0400 /* ReTRY error */
+
+/*
+** Ethernet PROM defines
+*/
+#define PROBE_LENGTH 32
+
+/*
+** Set the number of Tx and Rx buffers. Ensure that the memory requested
+** here is <= to the amount of shared memory set up by the board switches.
+** The number of descriptors MUST BE A POWER OF 2.
+**
+** total_memory = NUM_RX_DESC*(8+RX_BUFF_SZ) + NUM_TX_DESC*(8+TX_BUFF_SZ)
+*/
+#define NUM_RX_DESC 2 /* Number of RX descriptors */
+#define NUM_TX_DESC 2 /* Number of TX descriptors */
+#define RX_BUFF_SZ 1536 /* Buffer size for each Rx buffer */
+#define TX_BUFF_SZ 1536 /* Buffer size for each Tx buffer */
+
+/*
+** ISA Bus defines
+*/
+#ifndef DEPCA_MODEL
+#define DEPCA_MODEL DEPCA
+#endif
+
+static enum {
+ DEPCA, DE100, DE101, DE200, DE201, DE202, DE210, DE212, DE422, unknown
+} adapter = DEPCA_MODEL;
+
+/*
+** Name <-> Adapter mapping
+*/
+
+static char *adapter_name[] = {
+ "DEPCA",
+ "DE100","DE101",
+ "DE200","DE201","DE202",
+ "DE210","DE212",
+ "DE422",
+ ""
+};
+
+#ifndef DEPCA_RAM_BASE
+#define DEPCA_RAM_BASE 0xd0000
+#endif
+
+/*
+** Memory Alignment. Each descriptor is 4 longwords long. To force a
+** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and
+** DESC_ALIGN. ALIGN aligns the start address of the private memory area
+** and hence the RX descriptor ring's first entry.
+*/
+#define ALIGN4 ((u32)4 - 1) /* 1 longword align */
+#define ALIGN8 ((u32)8 - 1) /* 2 longword (quadword) align */
+#define ALIGN ALIGN8 /* Keep the LANCE happy... */
+
+/*
+** The DEPCA Rx and Tx ring descriptors.
+*/
+struct depca_rx_desc {
+ volatile s32 base;
+ s16 buf_length; /* This length is negative 2's complement! */
+ s16 msg_length; /* This length is "normal". */
+};
+
+struct depca_tx_desc {
+ volatile s32 base;
+ s16 length; /* This length is negative 2's complement! */
+ s16 misc; /* Errors and TDR info */
+};
+
+#define LA_MASK 0x0000ffff /* LANCE address mask for mapping network RAM
+ to LANCE memory address space */
+
+/*
+** The Lance initialization block, described in databook, in common memory.
+*/
+struct depca_init {
+ u16 mode; /* Mode register */
+ u8 phys_addr[ETH_ALEN]; /* Physical ethernet address */
+ u8 mcast_table[8]; /* Multicast Hash Table. */
+ u32 rx_ring; /* Rx ring base pointer & ring length */
+ u32 tx_ring; /* Tx ring base pointer & ring length */
+};
+
+struct depca_private {
+ struct depca_rx_desc *rx_ring;
+ struct depca_tx_desc *tx_ring;
+ struct depca_init init_block; /* Shadow init block */
+ char *rx_memcpy[NUM_RX_DESC];
+ char *tx_memcpy[NUM_TX_DESC];
+ u32 bus_offset; /* ISA bus address offset */
+ u32 sh_mem; /* address of shared mem */
+ u32 dma_buffs; /* Rx & Tx buffer start */
+ int rx_cur, tx_cur; /* Next free ring entry */
+ int txRingMask, rxRingMask;
+ s32 rx_rlen, tx_rlen;
+ /* log2([rt]xRingMask+1) for the descriptors */
+};
+
+static Address mem_start = DEPCA_RAM_BASE;
+static Address mem_len, offset;
+static struct depca_private lp;
+
+/*
+** Miscellaneous defines...
+*/
+#define STOP_DEPCA(ioaddr) \
+ outw(CSR0, ioaddr + DEPCA_ADDR);\
+ outw(STOP, ioaddr + DEPCA_DATA)
+
+/* Initialize the lance Rx and Tx descriptor rings. */
+static void depca_init_ring(struct nic *nic)
+{
+ int i;
+ u32 p;
+
+ lp.rx_cur = lp.tx_cur = 0;
+ /* Initialize the base addresses and length of each buffer in the ring */
+ for (i = 0; i <= lp.rxRingMask; i++) {
+ writel((p = lp.dma_buffs + i * RX_BUFF_SZ) | R_OWN, &lp.rx_ring[i].base);
+ writew(-RX_BUFF_SZ, &lp.rx_ring[i].buf_length);
+ lp.rx_memcpy[i] = (char *) (p + lp.bus_offset);
+ }
+ for (i = 0; i <= lp.txRingMask; i++) {
+ writel((p = lp.dma_buffs + (i + lp.txRingMask + 1) * TX_BUFF_SZ) & 0x00ffffff, &lp.tx_ring[i].base);
+ lp.tx_memcpy[i] = (char *) (p + lp.bus_offset);
+ }
+
+ /* Set up the initialization block */
+ lp.init_block.rx_ring = ((u32) ((u32) lp.rx_ring) & LA_MASK) | lp.rx_rlen;
+ lp.init_block.tx_ring = ((u32) ((u32) lp.tx_ring) & LA_MASK) | lp.tx_rlen;
+ for (i = 0; i < ETH_ALEN; i++)
+ lp.init_block.phys_addr[i] = nic->node_addr[i];
+ lp.init_block.mode = 0x0000; /* Enable the Tx and Rx */
+ memset(lp.init_block.mcast_table, 0, sizeof(lp.init_block.mcast_table));
+}
+
+static inline void LoadCSRs(struct nic *nic)
+{
+ outw(CSR1, nic->ioaddr + DEPCA_ADDR); /* initialisation block address LSW */
+ outw((u16) (lp.sh_mem & LA_MASK), nic->ioaddr + DEPCA_DATA);
+ outw(CSR2, nic->ioaddr + DEPCA_ADDR); /* initialisation block address MSW */
+ outw((u16) ((lp.sh_mem & LA_MASK) >> 16), nic->ioaddr + DEPCA_DATA);
+ outw(CSR3, nic->ioaddr + DEPCA_ADDR); /* ALE control */
+ outw(ACON, nic->ioaddr + DEPCA_DATA);
+ outw(CSR0, nic->ioaddr + DEPCA_ADDR); /* Point back to CSR0 */
+}
+
+static inline int InitRestartDepca(struct nic *nic)
+{
+ int i;
+
+ /* Copy the shadow init_block to shared memory */
+ memcpy_toio((char *)lp.sh_mem, &lp.init_block, sizeof(struct depca_init));
+ outw(CSR0, nic->ioaddr + DEPCA_ADDR); /* point back to CSR0 */
+ outw(INIT, nic->ioaddr + DEPCA_DATA); /* initialise DEPCA */
+
+ for (i = 0; i < 100 && !(inw(nic->ioaddr + DEPCA_DATA) & IDON); i++)
+ ;
+ if (i < 100) {
+ /* clear IDON by writing a 1, and start LANCE */
+ outw(IDON | STRT, nic->ioaddr + DEPCA_DATA);
+ } else {
+ printf("DEPCA not initialised\n");
+ return (1);
+ }
+ return (0);
+}
+
+/**************************************************************************
+RESET - Reset adapter
+***************************************************************************/
+static void depca_reset(struct nic *nic)
+{
+ s16 nicsr;
+ int i, j;
+
+ STOP_DEPCA(nic->ioaddr);
+ nicsr = inb(nic->ioaddr + DEPCA_NICSR);
+ nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM);
+ outb(nicsr, nic->ioaddr + DEPCA_NICSR);
+ if (inw(nic->ioaddr + DEPCA_DATA) != STOP)
+ {
+ printf("depca: Cannot stop NIC\n");
+ return;
+ }
+
+ /* Initialisation block */
+ lp.sh_mem = mem_start;
+ mem_start += sizeof(struct depca_init);
+ /* Tx & Rx descriptors (aligned to a quadword boundary) */
+ mem_start = (mem_start + ALIGN) & ~ALIGN;
+ lp.rx_ring = (struct depca_rx_desc *) mem_start;
+ mem_start += (sizeof(struct depca_rx_desc) * NUM_RX_DESC);
+ lp.tx_ring = (struct depca_tx_desc *) mem_start;
+ mem_start += (sizeof(struct depca_tx_desc) * NUM_TX_DESC);
+
+ lp.bus_offset = mem_start & 0x00ff0000;
+ /* LANCE re-mapped start address */
+ lp.dma_buffs = mem_start & LA_MASK;
+
+ /* Finish initialising the ring information. */
+ lp.rxRingMask = NUM_RX_DESC - 1;
+ lp.txRingMask = NUM_TX_DESC - 1;
+
+ /* Calculate Tx/Rx RLEN size for the descriptors. */
+ for (i = 0, j = lp.rxRingMask; j > 0; i++) {
+ j >>= 1;
+ }
+ lp.rx_rlen = (s32) (i << 29);
+ for (i = 0, j = lp.txRingMask; j > 0; i++) {
+ j >>= 1;
+ }
+ lp.tx_rlen = (s32) (i << 29);
+
+ /* Load the initialisation block */
+ depca_init_ring(nic);
+ LoadCSRs(nic);
+ InitRestartDepca(nic);
+}
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int depca_poll(struct nic *nic, int retrieve)
+{
+ int entry;
+ u32 status;
+
+ entry = lp.rx_cur;
+ if ((status = readl(&lp.rx_ring[entry].base) & R_OWN))
+ return (0);
+
+ if ( ! retrieve ) return 1;
+
+ memcpy(nic->packet, lp.rx_memcpy[entry], nic->packetlen = lp.rx_ring[entry].msg_length);
+ lp.rx_ring[entry].base |= R_OWN;
+ lp.rx_cur = (++lp.rx_cur) & lp.rxRingMask;
+ return (1);
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void depca_transmit(
+ struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ int entry, len;
+ char *mem;
+
+ /* send the packet to destination */
+ /*
+ ** Caution: the right order is important here... dont
+ ** setup the ownership rights until all the other
+ ** information is in place
+ */
+ mem = lp.tx_memcpy[entry = lp.tx_cur];
+ memcpy_toio(mem, d, ETH_ALEN);
+ memcpy_toio(mem + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ mem[ETH_ALEN * 2] = t >> 8;
+ mem[ETH_ALEN * 2 + 1] = t;
+ memcpy_toio(mem + ETH_HLEN, p, s);
+ s += ETH_HLEN;
+ len = (s < ETH_ZLEN ? ETH_ZLEN : s);
+ /* clean out flags */
+ writel(readl(&lp.tx_ring[entry].base) & ~T_FLAGS, &lp.tx_ring[entry].base);
+ /* clears other error flags */
+ writew(0x0000, &lp.tx_ring[entry].misc);
+ /* packet length in buffer */
+ writew(-len, &lp.tx_ring[entry].length);
+ /* start and end of packet, ownership */
+ writel(readl(&lp.tx_ring[entry].base) | (T_STP|T_ENP|T_OWN), &lp.tx_ring[entry].base);
+ /* update current pointers */
+ lp.tx_cur = (++lp.tx_cur) & lp.txRingMask;
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void depca_disable ( struct nic *nic ) {
+ depca_reset(nic);
+
+ STOP_DEPCA(nic->ioaddr);
+}
+
+/**************************************************************************
+IRQ - Interrupt Control
+***************************************************************************/
+static void depca_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+/*
+** Look for a special sequence in the Ethernet station address PROM that
+** is common across all DEPCA products. Note that the original DEPCA needs
+** its ROM address counter to be initialized and enabled. Only enable
+** if the first address octet is a 0x08 - this minimises the chances of
+** messing around with some other hardware, but it assumes that this DEPCA
+** card initialized itself correctly.
+**
+** Search the Ethernet address ROM for the signature. Since the ROM address
+** counter can start at an arbitrary point, the search must include the entire
+** probe sequence length plus the (length_of_the_signature - 1).
+** Stop the search IMMEDIATELY after the signature is found so that the
+** PROM address counter is correctly positioned at the start of the
+** ethernet address for later read out.
+*/
+
+
+/*
+ * Ugly, ugly, ugly. I can't quite make out where the split should be
+ * between probe1 and probe()...
+ *
+ */
+static u8 nicsr;
+
+
+static int depca_probe1 ( isa_probe_addr_t ioaddr ) {
+ u8 data;
+ /* This is only correct for little endian machines, but then
+ Etherboot doesn't work on anything but a PC */
+ u8 sig[] = { 0xFF, 0x00, 0x55, 0xAA, 0xFF, 0x00, 0x55, 0xAA };
+ int i, j;
+
+ data = inb(ioaddr + DEPCA_PROM); /* clear counter on DEPCA */
+ data = inb(ioaddr + DEPCA_PROM); /* read data */
+ if (data == 0x8) {
+ nicsr = inb(ioaddr + DEPCA_NICSR);
+ nicsr |= AAC;
+ outb(nicsr, ioaddr + DEPCA_NICSR);
+ }
+ for (i = 0, j = 0; j < (int)sizeof(sig) && i < PROBE_LENGTH+((int)sizeof(sig))-1; ++i) {
+ data = inb(ioaddr + DEPCA_PROM);
+ if (data == sig[j]) /* track signature */
+ ++j;
+ else
+ j = (data == sig[0]) ? 1 : 0;
+ }
+ if (j != sizeof(sig))
+ return (0);
+ /* put the card in its initial state */
+ STOP_DEPCA(ioaddr);
+ nicsr = ((inb(ioaddr + DEPCA_NICSR) & ~SHE & ~RBE & ~IEN) | IM);
+ outb(nicsr, ioaddr + DEPCA_NICSR);
+ if (inw(ioaddr + DEPCA_DATA) != STOP)
+ return (0);
+ memcpy((char *)mem_start, sig, sizeof(sig));
+ if (memcmp((char *)mem_start, sig, sizeof(sig)) != 0)
+ return (0);
+
+ return 1;
+}
+
+static struct nic_operations depca_operations = {
+ .connect = dummy_connect,
+ .poll = depca_poll,
+ .transmit = depca_transmit,
+ .irq = depca_irq,
+
+};
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+static int depca_probe ( struct nic *nic, struct isa_device *isa ) {
+
+ int i, j;
+ long sum, chksum;
+
+ nic->irqno = 0;
+ nic->ioaddr = isa->ioaddr;
+
+ for (i = 0, j = 0, sum = 0; j < 3; j++) {
+ sum <<= 1;
+ if (sum > 0xFFFF)
+ sum -= 0xFFFF;
+ sum += (u8)(nic->node_addr[i++] = inb(nic->ioaddr + DEPCA_PROM));
+ sum += (u16)((nic->node_addr[i++] = inb(nic->ioaddr + DEPCA_PROM)) << 8);
+ if (sum > 0xFFFF)
+ sum -= 0xFFFF;
+ }
+ if (sum == 0xFFFF)
+ sum = 0;
+ chksum = (u8)inb(nic->ioaddr + DEPCA_PROM);
+ chksum |= (u16)(inb(nic->ioaddr + DEPCA_PROM) << 8);
+ mem_len = (adapter == DEPCA) ? (48 << 10) : (64 << 10);
+ offset = 0;
+ if (nicsr & BUF) {
+ offset = 0x8000;
+ nicsr &= ~BS;
+ mem_len -= (32 << 10);
+ }
+ if (adapter != DEPCA) /* enable shadow RAM */
+ outb(nicsr |= SHE, nic->ioaddr + DEPCA_NICSR);
+ DBG ( "%s base %4.4x, memory [%4.4lx-%4.4lx] addr %s",
+ adapter_name[adapter], nic->ioaddr, mem_start,
+ mem_start + mem_len, eth_ntoa ( nic->node_addr ) );
+ if (sum != chksum)
+ printf(" (bad checksum)");
+ putchar('\n');
+
+ depca_reset(nic);
+
+ /* point to NIC specific routines */
+ nic->nic_op = &depca_operations;
+ return 1;
+}
+
+static isa_probe_addr_t depca_probe_addrs[] = {
+ 0x300, 0x200,
+};
+
+ISA_DRIVER ( depca_driver, depca_probe_addrs, depca_probe1,
+ GENERIC_ISAPNP_VENDOR, 0x80f7 );
+
+DRIVER ( "depce", nic_driver, isa_driver, depca_driver,
+ depca_probe, depca_disable );
+
+ISA_ROM ( "depca", "Digital DE100 and DE200" );
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/dmfe.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/dmfe.c
new file mode 100644
index 00000000..21092951
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/dmfe.c
@@ -0,0 +1,1236 @@
+/**************************************************************************
+*
+* dmfe.c -- Etherboot device driver for the Davicom
+* DM9102/DM9102A/DM9102A+DM9801/DM9102A+DM9802 NIC fast ethernet card
+*
+* Written 2003-2003 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code based on:
+*
+* dmfe.c: A Davicom DM9102/DM9102A/DM9102A+DM9801/DM9102A+DM9802
+* NIC fast ethernet driver for Linux.
+* Copyright (C) 1997 Sten Wang
+* (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
+*
+*
+* REVISION HISTORY:
+* ================
+* v1.0 10-02-2004 timlegge Boots ltsp needs cleanup
+*
+* Indent Options: indent -kr -i8
+*
+*
+***************************************************************************/
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* to get some global routines like printf */
+#include "etherboot.h"
+/* to get the interface to the body of the program */
+#include "nic.h"
+/* to get the PCI support functions, if this is a PCI NIC */
+#include <ipxe/pci.h>
+#include <ipxe/ethernet.h>
+
+/* #define EDEBUG 1 */
+#ifdef EDEBUG
+#define dprintf(x) printf x
+#else
+#define dprintf(x)
+#endif
+
+/* Condensed operations for readability. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+/* Board/System/Debug information/definition ---------------- */
+#define PCI_DM9132_ID 0x91321282 /* Davicom DM9132 ID */
+#define PCI_DM9102_ID 0x91021282 /* Davicom DM9102 ID */
+#define PCI_DM9100_ID 0x91001282 /* Davicom DM9100 ID */
+#define PCI_DM9009_ID 0x90091282 /* Davicom DM9009 ID */
+
+#define DM9102_IO_SIZE 0x80
+#define DM9102A_IO_SIZE 0x100
+#define TX_MAX_SEND_CNT 0x1 /* Maximum tx packet per time */
+#define TX_DESC_CNT 0x10 /* Allocated Tx descriptors */
+#define RX_DESC_CNT 0x20 /* Allocated Rx descriptors */
+#define TX_FREE_DESC_CNT (TX_DESC_CNT - 2) /* Max TX packet count */
+#define TX_WAKE_DESC_CNT (TX_DESC_CNT - 3) /* TX wakeup count */
+#define DESC_ALL_CNT (TX_DESC_CNT + RX_DESC_CNT)
+#define TX_BUF_ALLOC 0x600
+#define RX_ALLOC_SIZE 0x620
+#define DM910X_RESET 1
+#define CR0_DEFAULT 0x00E00000 /* TX & RX burst mode */
+#define CR6_DEFAULT 0x00080000 /* HD */
+#define CR7_DEFAULT 0x180c1
+#define CR15_DEFAULT 0x06 /* TxJabber RxWatchdog */
+#define TDES0_ERR_MASK 0x4302 /* TXJT, LC, EC, FUE */
+#define MAX_PACKET_SIZE 1514
+#define DMFE_MAX_MULTICAST 14
+#define RX_COPY_SIZE 100
+#define MAX_CHECK_PACKET 0x8000
+#define DM9801_NOISE_FLOOR 8
+#define DM9802_NOISE_FLOOR 5
+
+#define DMFE_10MHF 0
+#define DMFE_100MHF 1
+#define DMFE_10MFD 4
+#define DMFE_100MFD 5
+#define DMFE_AUTO 8
+#define DMFE_1M_HPNA 0x10
+
+#define DMFE_TXTH_72 0x400000 /* TX TH 72 byte */
+#define DMFE_TXTH_96 0x404000 /* TX TH 96 byte */
+#define DMFE_TXTH_128 0x0000 /* TX TH 128 byte */
+#define DMFE_TXTH_256 0x4000 /* TX TH 256 byte */
+#define DMFE_TXTH_512 0x8000 /* TX TH 512 byte */
+#define DMFE_TXTH_1K 0xC000 /* TX TH 1K byte */
+
+#define DMFE_TIMER_WUT (jiffies + HZ * 1) /* timer wakeup time : 1 second */
+#define DMFE_TX_TIMEOUT ((3*HZ)/2) /* tx packet time-out time 1.5 s" */
+#define DMFE_TX_KICK (HZ/2) /* tx packet Kick-out time 0.5 s" */
+
+#define DMFE_DBUG(dbug_now, msg, value) if (dmfe_debug || (dbug_now)) printk(KERN_ERR DRV_NAME ": %s %lx\n", (msg), (long) (value))
+
+#define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR DRV_NAME ": Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
+
+
+/* CR9 definition: SROM/MII */
+#define CR9_SROM_READ 0x4800
+#define CR9_SRCS 0x1
+#define CR9_SRCLK 0x2
+#define CR9_CRDOUT 0x8
+#define SROM_DATA_0 0x0
+#define SROM_DATA_1 0x4
+#define PHY_DATA_1 0x20000
+#define PHY_DATA_0 0x00000
+#define MDCLKH 0x10000
+
+#define PHY_POWER_DOWN 0x800
+
+#define SROM_V41_CODE 0x14
+
+#define SROM_CLK_WRITE(data, ioaddr) outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5);
+
+#define __CHK_IO_SIZE(pci_id, dev_rev) ( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? DM9102A_IO_SIZE: DM9102_IO_SIZE
+#define CHK_IO_SIZE(pci_dev, dev_rev) __CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev)
+
+/* Sten Check */
+#define DEVICE net_device
+
+/* Structure/enum declaration ------------------------------- */
+struct tx_desc {
+ u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */
+ void * tx_buf_ptr; /* Data for us */
+ struct tx_desc * next_tx_desc;
+} __attribute__ ((aligned(32)));
+
+struct rx_desc {
+ u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */
+ void * rx_skb_ptr; /* Data for us */
+ struct rx_desc * next_rx_desc;
+} __attribute__ ((aligned(32)));
+
+static struct dmfe_private {
+ u32 chip_id; /* Chip vendor/Device ID */
+ u32 chip_revision; /* Chip revision */
+ u32 cr0_data;
+// u32 cr5_data;
+ u32 cr6_data;
+ u32 cr7_data;
+ u32 cr15_data;
+
+ u16 HPNA_command; /* For HPNA register 16 */
+ u16 HPNA_timer; /* For HPNA remote device check */
+ u16 NIC_capability; /* NIC media capability */
+ u16 PHY_reg4; /* Saved Phyxcer register 4 value */
+
+ u8 HPNA_present; /* 0:none, 1:DM9801, 2:DM9802 */
+ u8 chip_type; /* Keep DM9102A chip type */
+ u8 media_mode; /* user specify media mode */
+ u8 op_mode; /* real work media mode */
+ u8 phy_addr;
+ u8 dm910x_chk_mode; /* Operating mode check */
+
+ /* NIC SROM data */
+ unsigned char srom[128];
+ /* Etherboot Only */
+ u8 cur_tx;
+ u8 cur_rx;
+} dfx;
+
+static struct dmfe_private *db;
+
+enum dmfe_offsets {
+ DCR0 = 0x00, DCR1 = 0x08, DCR2 = 0x10, DCR3 = 0x18, DCR4 = 0x20,
+ DCR5 = 0x28, DCR6 = 0x30, DCR7 = 0x38, DCR8 = 0x40, DCR9 = 0x48,
+ DCR10 = 0x50, DCR11 = 0x58, DCR12 = 0x60, DCR13 = 0x68, DCR14 =
+ 0x70,
+ DCR15 = 0x78
+};
+
+enum dmfe_CR6_bits {
+ CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80,
+ CR6_FDM = 0x200, CR6_TXSC = 0x2000, CR6_STI = 0x100000,
+ CR6_SFT = 0x200000, CR6_RXA = 0x40000000, CR6_NO_PURGE = 0x20000000
+};
+
+/* Global variable declaration ----------------------------- */
+static struct nic_operations dmfe_operations;
+
+static unsigned char dmfe_media_mode = DMFE_AUTO;
+static u32 dmfe_cr6_user_set;
+
+/* For module input parameter */
+static u8 chkmode = 1;
+static u8 HPNA_mode; /* Default: Low Power/High Speed */
+static u8 HPNA_rx_cmd; /* Default: Disable Rx remote command */
+static u8 HPNA_tx_cmd; /* Default: Don't issue remote command */
+static u8 HPNA_NoiseFloor; /* Default: HPNA NoiseFloor */
+static u8 SF_mode; /* Special Function: 1:VLAN, 2:RX Flow Control
+ 4: TX pause packet */
+
+
+/**********************************************
+* Descriptor Ring and Buffer defination
+***********************************************/
+struct {
+ struct tx_desc txd[TX_DESC_CNT] __attribute__ ((aligned(32)));
+ unsigned char txb[TX_BUF_ALLOC * TX_DESC_CNT]
+ __attribute__ ((aligned(32)));
+ struct rx_desc rxd[RX_DESC_CNT] __attribute__ ((aligned(32)));
+ unsigned char rxb[RX_ALLOC_SIZE * RX_DESC_CNT]
+ __attribute__ ((aligned(32)));
+} dmfe_bufs __shared;
+#define txd dmfe_bufs.txd
+#define txb dmfe_bufs.txb
+#define rxd dmfe_bufs.rxd
+#define rxb dmfe_bufs.rxb
+
+/* NIC specific static variables go here */
+static long int BASE;
+
+static u16 read_srom_word(long ioaddr, int offset);
+static void dmfe_init_dm910x(struct nic *nic);
+static void dmfe_descriptor_init(struct nic *, unsigned long ioaddr);
+static void update_cr6(u32, unsigned long);
+static void send_filter_frame(struct nic *nic);
+static void dm9132_id_table(struct nic *nic);
+
+static u16 phy_read(unsigned long, u8, u8, u32);
+static void phy_write(unsigned long, u8, u8, u16, u32);
+static void phy_write_1bit(unsigned long, u32);
+static u16 phy_read_1bit(unsigned long);
+static void dmfe_set_phyxcer(struct nic *nic);
+
+static void dmfe_parse_srom(struct nic *nic);
+static void dmfe_program_DM9801(struct nic *nic, int);
+static void dmfe_program_DM9802(struct nic *nic);
+
+static void dmfe_reset(struct nic *nic)
+{
+ /* system variable init */
+ db->cr6_data = CR6_DEFAULT | dmfe_cr6_user_set;
+
+ db->NIC_capability = 0xf; /* All capability */
+ db->PHY_reg4 = 0x1e0;
+
+ /* CR6 operation mode decision */
+ if (!chkmode || (db->chip_id == PCI_DM9132_ID) ||
+ (db->chip_revision >= 0x02000030)) {
+ db->cr6_data |= DMFE_TXTH_256;
+ db->cr0_data = CR0_DEFAULT;
+ db->dm910x_chk_mode = 4; /* Enter the normal mode */
+ } else {
+ db->cr6_data |= CR6_SFT; /* Store & Forward mode */
+ db->cr0_data = 0;
+ db->dm910x_chk_mode = 1; /* Enter the check mode */
+ }
+ /* Initilize DM910X board */
+ dmfe_init_dm910x(nic);
+
+ return;
+}
+
+/* Initilize DM910X board
+ * Reset DM910X board
+ * Initilize TX/Rx descriptor chain structure
+ * Send the set-up frame
+ * Enable Tx/Rx machine
+ */
+
+static void dmfe_init_dm910x(struct nic *nic)
+{
+ unsigned long ioaddr = BASE;
+
+ /* Reset DM910x MAC controller */
+ outl(DM910X_RESET, ioaddr + DCR0); /* RESET MAC */
+ udelay(100);
+ outl(db->cr0_data, ioaddr + DCR0);
+ udelay(5);
+
+ /* Phy addr : DM910(A)2/DM9132/9801, phy address = 1 */
+ db->phy_addr = 1;
+
+ /* Parser SROM and media mode */
+ dmfe_parse_srom(nic);
+ db->media_mode = dmfe_media_mode;
+
+ /* RESET Phyxcer Chip by GPR port bit 7 */
+ outl(0x180, ioaddr + DCR12); /* Let bit 7 output port */
+ if (db->chip_id == PCI_DM9009_ID) {
+ outl(0x80, ioaddr + DCR12); /* Issue RESET signal */
+ mdelay(300); /* Delay 300 ms */
+ }
+ outl(0x0, ioaddr + DCR12); /* Clear RESET signal */
+
+ /* Process Phyxcer Media Mode */
+ if (!(db->media_mode & 0x10)) /* Force 1M mode */
+ dmfe_set_phyxcer(nic);
+
+ /* Media Mode Process */
+ if (!(db->media_mode & DMFE_AUTO))
+ db->op_mode = db->media_mode; /* Force Mode */
+
+ /* Initiliaze Transmit/Receive decriptor and CR3/4 */
+ dmfe_descriptor_init(nic, ioaddr);
+
+ /* tx descriptor start pointer */
+ outl(virt_to_le32desc(&txd[0]), ioaddr + DCR4); /* TX DESC address */
+
+ /* rx descriptor start pointer */
+ outl(virt_to_le32desc(&rxd[0]), ioaddr + DCR3); /* RX DESC address */
+
+ /* Init CR6 to program DM910x operation */
+ update_cr6(db->cr6_data, ioaddr);
+
+ /* Send setup frame */
+ if (db->chip_id == PCI_DM9132_ID) {
+ dm9132_id_table(nic); /* DM9132 */
+ } else {
+ send_filter_frame(nic); /* DM9102/DM9102A */
+ }
+
+ /* Init CR7, interrupt active bit */
+ db->cr7_data = CR7_DEFAULT;
+ outl(db->cr7_data, ioaddr + DCR7);
+ /* Init CR15, Tx jabber and Rx watchdog timer */
+ outl(db->cr15_data, ioaddr + DCR15);
+ /* Enable DM910X Tx/Rx function */
+ db->cr6_data |= CR6_RXSC | CR6_TXSC | 0x40000;
+ update_cr6(db->cr6_data, ioaddr);
+}
+#ifdef EDEBUG
+void hex_dump(const char *data, const unsigned int len);
+#endif
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int dmfe_poll(struct nic *nic, int retrieve)
+{
+ u32 rdes0;
+ int entry = db->cur_rx % RX_DESC_CNT;
+ int rxlen;
+ rdes0 = le32_to_cpu(rxd[entry].rdes0);
+ if (rdes0 & 0x80000000)
+ return 0;
+
+ if (!retrieve)
+ return 1;
+
+ if ((rdes0 & 0x300) != 0x300) {
+ /* A packet without First/Last flag */
+ printf("strange Packet\n");
+ rxd[entry].rdes0 = cpu_to_le32(0x80000000);
+ return 0;
+ } else {
+ /* A packet with First/Last flag */
+ rxlen = ((rdes0 >> 16) & 0x3fff) - 4;
+ /* error summary bit check */
+ if (rdes0 & 0x8000) {
+ printf("Error\n");
+ return 0;
+ }
+ if (!(rdes0 & 0x8000) ||
+ ((db->cr6_data & CR6_PM) && (rxlen > 6))) {
+ if (db->dm910x_chk_mode & 1)
+ printf("Silly check mode\n");
+
+ nic->packetlen = rxlen;
+ memcpy(nic->packet, rxb + (entry * RX_ALLOC_SIZE),
+ nic->packetlen);
+ }
+ }
+ rxd[entry].rdes0 = cpu_to_le32(0x80000000);
+ db->cur_rx++;
+ return 1;
+}
+
+static void dmfe_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void dmfe_transmit(struct nic *nic,
+ const char *dest, /* Destination */
+ unsigned int type, /* Type */
+ unsigned int size, /* size */
+ const char *packet) /* Packet */
+{
+ u16 nstype;
+ u8 *ptxb;
+
+ ptxb = &txb[db->cur_tx];
+
+ /* Stop Tx */
+ outl(0, BASE + DCR7);
+ memcpy(ptxb, dest, ETH_ALEN);
+ memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ nstype = htons((u16) type);
+ memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2);
+ memcpy(ptxb + ETH_HLEN, packet, size);
+
+ size += ETH_HLEN;
+ while (size < ETH_ZLEN)
+ ptxb[size++] = '\0';
+
+ /* setup the transmit descriptor */
+ txd[db->cur_tx].tdes1 = cpu_to_le32(0xe1000000 | size);
+ txd[db->cur_tx].tdes0 = cpu_to_le32(0x80000000); /* give ownership to device */
+
+ /* immediate transmit demand */
+ outl(0x1, BASE + DCR1);
+ outl(db->cr7_data, BASE + DCR7);
+
+ /* Point to next TX descriptor */
+ db->cur_tx++;
+ db->cur_tx = db->cur_tx % TX_DESC_CNT;
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void dmfe_disable ( struct nic *nic __unused ) {
+ /* Reset & stop DM910X board */
+ outl(DM910X_RESET, BASE + DCR0);
+ udelay(5);
+ phy_write(BASE, db->phy_addr, 0, 0x8000, db->chip_id);
+
+}
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+
+#define board_found 1
+#define valid_link 0
+static int dmfe_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ uint32_t dev_rev, pci_pmr;
+ int i;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ BASE = pci->ioaddr;
+ printf("dmfe.c: Found %s Vendor=0x%hX Device=0x%hX\n",
+ pci->id->name, pci->vendor, pci->device);
+
+ /* Read Chip revision */
+ pci_read_config_dword(pci, PCI_REVISION_ID, &dev_rev);
+ dprintf(("Revision %lX\n", dev_rev));
+
+ /* point to private storage */
+ db = &dfx;
+
+ db->chip_id = ((u32) pci->device << 16) | pci->vendor;
+ BASE = pci_bar_start(pci, PCI_BASE_ADDRESS_0);
+ db->chip_revision = dev_rev;
+
+ pci_read_config_dword(pci, 0x50, &pci_pmr);
+ pci_pmr &= 0x70000;
+ if ((pci_pmr == 0x10000) && (dev_rev == 0x02000031))
+ db->chip_type = 1; /* DM9102A E3 */
+ else
+ db->chip_type = 0;
+
+ dprintf(("Chip type : %d\n", db->chip_type));
+
+ /* read 64 word srom data */
+ for (i = 0; i < 64; i++)
+ ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(BASE, i));
+
+ /* Set Node address */
+ for (i = 0; i < 6; i++)
+ nic->node_addr[i] = db->srom[20 + i];
+
+ /* Print out some hardware info */
+ DBG ( "%s: %s at ioaddr %4.4lx\n",
+ pci->id->name, eth_ntoa ( nic->node_addr ), BASE );
+
+ /* Set the card as PCI Bus Master */
+ adjust_pci_device(pci);
+
+ dmfe_reset(nic);
+
+ nic->irqno = 0;
+ nic->ioaddr = pci->ioaddr;
+
+ /* point to NIC specific routines */
+ nic->nic_op = &dmfe_operations;
+
+ return 1;
+}
+
+/*
+ * Initialize transmit/Receive descriptor
+ * Using Chain structure, and allocate Tx/Rx buffer
+ */
+
+static void dmfe_descriptor_init(struct nic *nic __unused, unsigned long ioaddr)
+{
+ int i;
+ db->cur_tx = 0;
+ db->cur_rx = 0;
+
+ /* tx descriptor start pointer */
+ outl(virt_to_le32desc(&txd[0]), ioaddr + DCR4); /* TX DESC address */
+
+ /* rx descriptor start pointer */
+ outl(virt_to_le32desc(&rxd[0]), ioaddr + DCR3); /* RX DESC address */
+
+ /* Init Transmit chain */
+ for (i = 0; i < TX_DESC_CNT; i++) {
+ txd[i].tx_buf_ptr = &txb[i];
+ txd[i].tdes0 = cpu_to_le32(0);
+ txd[i].tdes1 = cpu_to_le32(0x81000000); /* IC, chain */
+ txd[i].tdes2 = cpu_to_le32(virt_to_bus(&txb[i]));
+ txd[i].tdes3 = cpu_to_le32(virt_to_bus(&txd[i + 1]));
+ txd[i].next_tx_desc = &txd[i + 1];
+ }
+ /* Mark the last entry as wrapping the ring */
+ txd[i - 1].tdes3 = virt_to_le32desc(&txd[0]);
+ txd[i - 1].next_tx_desc = &txd[0];
+
+ /* receive descriptor chain */
+ for (i = 0; i < RX_DESC_CNT; i++) {
+ rxd[i].rx_skb_ptr = &rxb[i * RX_ALLOC_SIZE];
+ rxd[i].rdes0 = cpu_to_le32(0x80000000);
+ rxd[i].rdes1 = cpu_to_le32(0x01000600);
+ rxd[i].rdes2 =
+ cpu_to_le32(virt_to_bus(&rxb[i * RX_ALLOC_SIZE]));
+ rxd[i].rdes3 = cpu_to_le32(virt_to_bus(&rxd[i + 1]));
+ rxd[i].next_rx_desc = &rxd[i + 1];
+ }
+ /* Mark the last entry as wrapping the ring */
+ rxd[i - 1].rdes3 = cpu_to_le32(virt_to_bus(&rxd[0]));
+ rxd[i - 1].next_rx_desc = &rxd[0];
+
+}
+
+/*
+ * Update CR6 value
+ * Firstly stop DM910X , then written value and start
+ */
+
+static void update_cr6(u32 cr6_data, unsigned long ioaddr)
+{
+ u32 cr6_tmp;
+
+ cr6_tmp = cr6_data & ~0x2002; /* stop Tx/Rx */
+ outl(cr6_tmp, ioaddr + DCR6);
+ udelay(5);
+ outl(cr6_data, ioaddr + DCR6);
+ udelay(5);
+}
+
+
+/*
+ * Send a setup frame for DM9132
+ * This setup frame initilize DM910X addres filter mode
+*/
+
+static void dm9132_id_table(struct nic *nic __unused)
+{
+#ifdef LINUX
+ u16 *addrptr;
+ u8 dmi_addr[8];
+ unsigned long ioaddr = BASE + 0xc0; /* ID Table */
+ u32 hash_val;
+ u16 i, hash_table[4];
+#endif
+ dprintf(("dm9132_id_table\n"));
+
+ printf("FIXME: This function is broken. If you have this card contact "
+ "Timothy Legge at the etherboot-user list\n");
+
+#ifdef LINUX
+ //DMFE_DBUG(0, "dm9132_id_table()", 0);
+
+ /* Node address */
+ addrptr = (u16 *) nic->node_addr;
+ outw(addrptr[0], ioaddr);
+ ioaddr += 4;
+ outw(addrptr[1], ioaddr);
+ ioaddr += 4;
+ outw(addrptr[2], ioaddr);
+ ioaddr += 4;
+
+ /* Clear Hash Table */
+ for (i = 0; i < 4; i++)
+ hash_table[i] = 0x0;
+
+ /* broadcast address */
+ hash_table[3] = 0x8000;
+
+ /* the multicast address in Hash Table : 64 bits */
+ for (mcptr = mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
+ hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f;
+ hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
+ }
+
+ /* Write the hash table to MAC MD table */
+ for (i = 0; i < 4; i++, ioaddr += 4)
+ outw(hash_table[i], ioaddr);
+#endif
+}
+
+
+/*
+ * Send a setup frame for DM9102/DM9102A
+ * This setup frame initilize DM910X addres filter mode
+ */
+
+static void send_filter_frame(struct nic *nic)
+{
+
+ u8 *ptxb;
+ int i;
+
+ dprintf(("send_filter_frame\n"));
+ /* point to the current txb incase multiple tx_rings are used */
+ ptxb = &txb[db->cur_tx];
+
+ /* construct perfect filter frame with mac address as first match
+ and broadcast address for all others */
+ for (i = 0; i < 192; i++)
+ ptxb[i] = 0xFF;
+ ptxb[0] = nic->node_addr[0];
+ ptxb[1] = nic->node_addr[1];
+ ptxb[4] = nic->node_addr[2];
+ ptxb[5] = nic->node_addr[3];
+ ptxb[8] = nic->node_addr[4];
+ ptxb[9] = nic->node_addr[5];
+
+ /* prepare the setup frame */
+ txd[db->cur_tx].tdes1 = cpu_to_le32(0x890000c0);
+ txd[db->cur_tx].tdes0 = cpu_to_le32(0x80000000);
+ update_cr6(db->cr6_data | 0x2000, BASE);
+ outl(0x1, BASE + DCR1); /* Issue Tx polling */
+ update_cr6(db->cr6_data, BASE);
+ db->cur_tx++;
+}
+
+/*
+ * Read one word data from the serial ROM
+ */
+
+static u16 read_srom_word(long ioaddr, int offset)
+{
+ int i;
+ u16 srom_data = 0;
+ long cr9_ioaddr = ioaddr + DCR9;
+
+ outl(CR9_SROM_READ, cr9_ioaddr);
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+ /* Send the Read Command 110b */
+ SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+ SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+ SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr);
+
+ /* Send the offset */
+ for (i = 5; i >= 0; i--) {
+ srom_data =
+ (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0;
+ SROM_CLK_WRITE(srom_data, cr9_ioaddr);
+ }
+
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+ for (i = 16; i > 0; i--) {
+ outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);
+ udelay(5);
+ srom_data =
+ (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1
+ : 0);
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+ udelay(5);
+ }
+
+ outl(CR9_SROM_READ, cr9_ioaddr);
+ return srom_data;
+}
+
+
+/*
+ * Auto sense the media mode
+ */
+
+#if 0 /* not used */
+static u8 dmfe_sense_speed(struct nic *nic __unused)
+{
+ u8 ErrFlag = 0;
+ u16 phy_mode;
+
+ /* CR6 bit18=0, select 10/100M */
+ update_cr6((db->cr6_data & ~0x40000), BASE);
+
+ phy_mode = phy_read(BASE, db->phy_addr, 1, db->chip_id);
+ phy_mode = phy_read(BASE, db->phy_addr, 1, db->chip_id);
+
+ if ((phy_mode & 0x24) == 0x24) {
+ if (db->chip_id == PCI_DM9132_ID) /* DM9132 */
+ phy_mode =
+ phy_read(BASE, db->phy_addr, 7,
+ db->chip_id) & 0xf000;
+ else /* DM9102/DM9102A */
+ phy_mode =
+ phy_read(BASE, db->phy_addr, 17,
+ db->chip_id) & 0xf000;
+ /* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */
+ switch (phy_mode) {
+ case 0x1000:
+ db->op_mode = DMFE_10MHF;
+ break;
+ case 0x2000:
+ db->op_mode = DMFE_10MFD;
+ break;
+ case 0x4000:
+ db->op_mode = DMFE_100MHF;
+ break;
+ case 0x8000:
+ db->op_mode = DMFE_100MFD;
+ break;
+ default:
+ db->op_mode = DMFE_10MHF;
+ ErrFlag = 1;
+ break;
+ }
+ } else {
+ db->op_mode = DMFE_10MHF;
+ //DMFE_DBUG(0, "Link Failed :", phy_mode);
+ ErrFlag = 1;
+ }
+
+ return ErrFlag;
+}
+#endif
+
+/*
+ * Set 10/100 phyxcer capability
+ * AUTO mode : phyxcer register4 is NIC capability
+ * Force mode: phyxcer register4 is the force media
+ */
+
+static void dmfe_set_phyxcer(struct nic *nic __unused)
+{
+ u16 phy_reg;
+
+ /* Select 10/100M phyxcer */
+ db->cr6_data &= ~0x40000;
+ update_cr6(db->cr6_data, BASE);
+
+ /* DM9009 Chip: Phyxcer reg18 bit12=0 */
+ if (db->chip_id == PCI_DM9009_ID) {
+ phy_reg =
+ phy_read(BASE, db->phy_addr, 18,
+ db->chip_id) & ~0x1000;
+ phy_write(BASE, db->phy_addr, 18, phy_reg, db->chip_id);
+ }
+
+ /* Phyxcer capability setting */
+ phy_reg = phy_read(BASE, db->phy_addr, 4, db->chip_id) & ~0x01e0;
+
+ if (db->media_mode & DMFE_AUTO) {
+ /* AUTO Mode */
+ phy_reg |= db->PHY_reg4;
+ } else {
+ /* Force Mode */
+ switch (db->media_mode) {
+ case DMFE_10MHF:
+ phy_reg |= 0x20;
+ break;
+ case DMFE_10MFD:
+ phy_reg |= 0x40;
+ break;
+ case DMFE_100MHF:
+ phy_reg |= 0x80;
+ break;
+ case DMFE_100MFD:
+ phy_reg |= 0x100;
+ break;
+ }
+ if (db->chip_id == PCI_DM9009_ID)
+ phy_reg &= 0x61;
+ }
+
+ /* Write new capability to Phyxcer Reg4 */
+ if (!(phy_reg & 0x01e0)) {
+ phy_reg |= db->PHY_reg4;
+ db->media_mode |= DMFE_AUTO;
+ }
+ phy_write(BASE, db->phy_addr, 4, phy_reg, db->chip_id);
+
+ /* Restart Auto-Negotiation */
+ if (db->chip_type && (db->chip_id == PCI_DM9102_ID))
+ phy_write(BASE, db->phy_addr, 0, 0x1800, db->chip_id);
+ if (!db->chip_type)
+ phy_write(BASE, db->phy_addr, 0, 0x1200, db->chip_id);
+}
+
+
+/*
+ * Process op-mode
+ * AUTO mode : PHY controller in Auto-negotiation Mode
+ * Force mode: PHY controller in force mode with HUB
+ * N-way force capability with SWITCH
+ */
+
+#if 0 /* not used */
+static void dmfe_process_mode(struct nic *nic __unused)
+{
+ u16 phy_reg;
+
+ /* Full Duplex Mode Check */
+ if (db->op_mode & 0x4)
+ db->cr6_data |= CR6_FDM; /* Set Full Duplex Bit */
+ else
+ db->cr6_data &= ~CR6_FDM; /* Clear Full Duplex Bit */
+
+ /* Transciver Selection */
+ if (db->op_mode & 0x10) /* 1M HomePNA */
+ db->cr6_data |= 0x40000; /* External MII select */
+ else
+ db->cr6_data &= ~0x40000; /* Internal 10/100 transciver */
+
+ update_cr6(db->cr6_data, BASE);
+
+ /* 10/100M phyxcer force mode need */
+ if (!(db->media_mode & 0x18)) {
+ /* Forece Mode */
+ phy_reg = phy_read(BASE, db->phy_addr, 6, db->chip_id);
+ if (!(phy_reg & 0x1)) {
+ /* parter without N-Way capability */
+ phy_reg = 0x0;
+ switch (db->op_mode) {
+ case DMFE_10MHF:
+ phy_reg = 0x0;
+ break;
+ case DMFE_10MFD:
+ phy_reg = 0x100;
+ break;
+ case DMFE_100MHF:
+ phy_reg = 0x2000;
+ break;
+ case DMFE_100MFD:
+ phy_reg = 0x2100;
+ break;
+ }
+ phy_write(BASE, db->phy_addr, 0, phy_reg,
+ db->chip_id);
+ if (db->chip_type
+ && (db->chip_id == PCI_DM9102_ID))
+ mdelay(20);
+ phy_write(BASE, db->phy_addr, 0, phy_reg,
+ db->chip_id);
+ }
+ }
+}
+#endif
+
+/*
+ * Write a word to Phy register
+ */
+
+static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset,
+ u16 phy_data, u32 chip_id)
+{
+ u16 i;
+ unsigned long ioaddr;
+
+ if (chip_id == PCI_DM9132_ID) {
+ ioaddr = iobase + 0x80 + offset * 4;
+ outw(phy_data, ioaddr);
+ } else {
+ /* DM9102/DM9102A Chip */
+ ioaddr = iobase + DCR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i = 0; i < 35; i++)
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0);
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+
+ /* Send write command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0);
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+
+ /* Send Phy addres */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr,
+ phy_addr & i ? PHY_DATA_1 :
+ PHY_DATA_0);
+
+ /* Send register addres */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr,
+ offset & i ? PHY_DATA_1 :
+ PHY_DATA_0);
+
+ /* written trasnition */
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+ phy_write_1bit(ioaddr, PHY_DATA_0);
+
+ /* Write a word data to PHY controller */
+ for (i = 0x8000; i > 0; i >>= 1)
+ phy_write_1bit(ioaddr,
+ phy_data & i ? PHY_DATA_1 :
+ PHY_DATA_0);
+ }
+}
+
+
+/*
+ * Read a word data from phy register
+ */
+
+static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset,
+ u32 chip_id)
+{
+ int i;
+ u16 phy_data;
+ unsigned long ioaddr;
+
+ if (chip_id == PCI_DM9132_ID) {
+ /* DM9132 Chip */
+ ioaddr = iobase + 0x80 + offset * 4;
+ phy_data = inw(ioaddr);
+ } else {
+ /* DM9102/DM9102A Chip */
+ ioaddr = iobase + DCR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i = 0; i < 35; i++)
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0);
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+
+ /* Send read command(10) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+ phy_write_1bit(ioaddr, PHY_DATA_0);
+
+ /* Send Phy addres */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr,
+ phy_addr & i ? PHY_DATA_1 :
+ PHY_DATA_0);
+
+ /* Send register addres */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr,
+ offset & i ? PHY_DATA_1 :
+ PHY_DATA_0);
+
+ /* Skip transition state */
+ phy_read_1bit(ioaddr);
+
+ /* read 16bit data */
+ for (phy_data = 0, i = 0; i < 16; i++) {
+ phy_data <<= 1;
+ phy_data |= phy_read_1bit(ioaddr);
+ }
+ }
+
+ return phy_data;
+}
+
+
+/*
+ * Write one bit data to Phy Controller
+ */
+
+static void phy_write_1bit(unsigned long ioaddr, u32 phy_data)
+{
+ outl(phy_data, ioaddr); /* MII Clock Low */
+ udelay(1);
+ outl(phy_data | MDCLKH, ioaddr); /* MII Clock High */
+ udelay(1);
+ outl(phy_data, ioaddr); /* MII Clock Low */
+ udelay(1);
+}
+
+
+/*
+ * Read one bit phy data from PHY controller
+ */
+
+static u16 phy_read_1bit(unsigned long ioaddr)
+{
+ u16 phy_data;
+
+ outl(0x50000, ioaddr);
+ udelay(1);
+ phy_data = (inl(ioaddr) >> 19) & 0x1;
+ outl(0x40000, ioaddr);
+ udelay(1);
+
+ return phy_data;
+}
+
+
+/*
+ * Parser SROM and media mode
+ */
+
+static void dmfe_parse_srom(struct nic *nic)
+{
+ unsigned char *srom = db->srom;
+ int dmfe_mode, tmp_reg;
+
+ /* Init CR15 */
+ db->cr15_data = CR15_DEFAULT;
+
+ /* Check SROM Version */
+ if (((int) srom[18] & 0xff) == SROM_V41_CODE) {
+ /* SROM V4.01 */
+ /* Get NIC support media mode */
+ db->NIC_capability = *(u16 *) (srom + 34);
+ db->PHY_reg4 = 0;
+ for (tmp_reg = 1; tmp_reg < 0x10; tmp_reg <<= 1) {
+ switch (db->NIC_capability & tmp_reg) {
+ case 0x1:
+ db->PHY_reg4 |= 0x0020;
+ break;
+ case 0x2:
+ db->PHY_reg4 |= 0x0040;
+ break;
+ case 0x4:
+ db->PHY_reg4 |= 0x0080;
+ break;
+ case 0x8:
+ db->PHY_reg4 |= 0x0100;
+ break;
+ }
+ }
+
+ /* Media Mode Force or not check */
+ dmfe_mode = *((int *) srom + 34) & *((int *) srom + 36);
+ switch (dmfe_mode) {
+ case 0x4:
+ dmfe_media_mode = DMFE_100MHF;
+ break; /* 100MHF */
+ case 0x2:
+ dmfe_media_mode = DMFE_10MFD;
+ break; /* 10MFD */
+ case 0x8:
+ dmfe_media_mode = DMFE_100MFD;
+ break; /* 100MFD */
+ case 0x100:
+ case 0x200:
+ dmfe_media_mode = DMFE_1M_HPNA;
+ break; /* HomePNA */
+ }
+
+ /* Special Function setting */
+ /* VLAN function */
+ if ((SF_mode & 0x1) || (srom[43] & 0x80))
+ db->cr15_data |= 0x40;
+
+ /* Flow Control */
+ if ((SF_mode & 0x2) || (srom[40] & 0x1))
+ db->cr15_data |= 0x400;
+
+ /* TX pause packet */
+ if ((SF_mode & 0x4) || (srom[40] & 0xe))
+ db->cr15_data |= 0x9800;
+ }
+
+ /* Parse HPNA parameter */
+ db->HPNA_command = 1;
+
+ /* Accept remote command or not */
+ if (HPNA_rx_cmd == 0)
+ db->HPNA_command |= 0x8000;
+
+ /* Issue remote command & operation mode */
+ if (HPNA_tx_cmd == 1)
+ switch (HPNA_mode) { /* Issue Remote Command */
+ case 0:
+ db->HPNA_command |= 0x0904;
+ break;
+ case 1:
+ db->HPNA_command |= 0x0a00;
+ break;
+ case 2:
+ db->HPNA_command |= 0x0506;
+ break;
+ case 3:
+ db->HPNA_command |= 0x0602;
+ break;
+ } else
+ switch (HPNA_mode) { /* Don't Issue */
+ case 0:
+ db->HPNA_command |= 0x0004;
+ break;
+ case 1:
+ db->HPNA_command |= 0x0000;
+ break;
+ case 2:
+ db->HPNA_command |= 0x0006;
+ break;
+ case 3:
+ db->HPNA_command |= 0x0002;
+ break;
+ }
+
+ /* Check DM9801 or DM9802 present or not */
+ db->HPNA_present = 0;
+ update_cr6(db->cr6_data | 0x40000, BASE);
+ tmp_reg = phy_read(BASE, db->phy_addr, 3, db->chip_id);
+ if ((tmp_reg & 0xfff0) == 0xb900) {
+ /* DM9801 or DM9802 present */
+ db->HPNA_timer = 8;
+ if (phy_read(BASE, db->phy_addr, 31, db->chip_id) ==
+ 0x4404) {
+ /* DM9801 HomeRun */
+ db->HPNA_present = 1;
+ dmfe_program_DM9801(nic, tmp_reg);
+ } else {
+ /* DM9802 LongRun */
+ db->HPNA_present = 2;
+ dmfe_program_DM9802(nic);
+ }
+ }
+
+}
+
+/*
+ * Init HomeRun DM9801
+ */
+
+static void dmfe_program_DM9801(struct nic *nic __unused, int HPNA_rev)
+{
+ u32 reg17, reg25;
+
+ if (!HPNA_NoiseFloor)
+ HPNA_NoiseFloor = DM9801_NOISE_FLOOR;
+ switch (HPNA_rev) {
+ case 0xb900: /* DM9801 E3 */
+ db->HPNA_command |= 0x1000;
+ reg25 = phy_read(BASE, db->phy_addr, 24, db->chip_id);
+ reg25 = ((reg25 + HPNA_NoiseFloor) & 0xff) | 0xf000;
+ reg17 = phy_read(BASE, db->phy_addr, 17, db->chip_id);
+ break;
+ case 0xb901: /* DM9801 E4 */
+ reg25 = phy_read(BASE, db->phy_addr, 25, db->chip_id);
+ reg25 = (reg25 & 0xff00) + HPNA_NoiseFloor;
+ reg17 = phy_read(BASE, db->phy_addr, 17, db->chip_id);
+ reg17 = (reg17 & 0xfff0) + HPNA_NoiseFloor + 3;
+ break;
+ case 0xb902: /* DM9801 E5 */
+ case 0xb903: /* DM9801 E6 */
+ default:
+ db->HPNA_command |= 0x1000;
+ reg25 = phy_read(BASE, db->phy_addr, 25, db->chip_id);
+ reg25 = (reg25 & 0xff00) + HPNA_NoiseFloor - 5;
+ reg17 = phy_read(BASE, db->phy_addr, 17, db->chip_id);
+ reg17 = (reg17 & 0xfff0) + HPNA_NoiseFloor;
+ break;
+ }
+ phy_write(BASE, db->phy_addr, 16, db->HPNA_command, db->chip_id);
+ phy_write(BASE, db->phy_addr, 17, reg17, db->chip_id);
+ phy_write(BASE, db->phy_addr, 25, reg25, db->chip_id);
+}
+
+
+/*
+ * Init HomeRun DM9802
+ */
+
+static void dmfe_program_DM9802(struct nic *nic __unused)
+{
+ u32 phy_reg;
+
+ if (!HPNA_NoiseFloor)
+ HPNA_NoiseFloor = DM9802_NOISE_FLOOR;
+ phy_write(BASE, db->phy_addr, 16, db->HPNA_command, db->chip_id);
+ phy_reg = phy_read(BASE, db->phy_addr, 25, db->chip_id);
+ phy_reg = (phy_reg & 0xff00) + HPNA_NoiseFloor;
+ phy_write(BASE, db->phy_addr, 25, phy_reg, db->chip_id);
+}
+
+static struct nic_operations dmfe_operations = {
+ .connect = dummy_connect,
+ .poll = dmfe_poll,
+ .transmit = dmfe_transmit,
+ .irq = dmfe_irq,
+
+};
+
+static struct pci_device_id dmfe_nics[] = {
+ PCI_ROM(0x1282, 0x9100, "dmfe9100", "Davicom 9100", 0),
+ PCI_ROM(0x1282, 0x9102, "dmfe9102", "Davicom 9102", 0),
+ PCI_ROM(0x1282, 0x9009, "dmfe9009", "Davicom 9009", 0),
+ PCI_ROM(0x1282, 0x9132, "dmfe9132", "Davicom 9132", 0), /* Needs probably some fixing */
+};
+
+PCI_DRIVER ( dmfe_driver, dmfe_nics, PCI_NO_CLASS );
+
+DRIVER ( "DMFE/PCI", nic_driver, pci_driver, dmfe_driver,
+ dmfe_probe, dmfe_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/eepro.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/eepro.c
new file mode 100644
index 00000000..387e2fee
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/eepro.c
@@ -0,0 +1,647 @@
+#ifdef ALLMULTI
+#error multicast support is not yet implemented
+#endif
+/**************************************************************************
+Etherboot - BOOTP/TFTP Bootstrap Program
+Intel EEPRO/10 NIC driver for Etherboot
+Adapted from Linux eepro.c from kernel 2.2.17
+
+This board accepts a 32 pin EEPROM (29C256), however a test with a
+27C010 shows that this EPROM also works in the socket, but it's not clear
+how repeatably. The two top address pins appear to be held low, thus
+the bottom 32kB of the 27C010 is visible in the CPU's address space.
+To be sure you could put 4 copies of the code in the 27C010, then
+it doesn't matter whether the extra lines are held low or high, just
+hopefully not floating as CMOS chips don't like floating inputs.
+
+Be careful with seating the EPROM as the socket on my board actually
+has 34 pins, the top row of 2 are not used.
+***************************************************************************/
+
+/*
+
+ timlegge 2005-05-18 remove the relocation changes cards that
+ write directly to the hardware don't need it
+*/
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "etherboot.h"
+#include <errno.h>
+#include "nic.h"
+#include <ipxe/isa.h>
+#include <ipxe/ethernet.h>
+
+/* Different 82595 chips */
+#define LAN595 0
+#define LAN595TX 1
+#define LAN595FX 2
+#define LAN595FX_10ISA 3
+
+#define SLOW_DOWN inb(0x80);
+
+/* The station (ethernet) address prefix, used for IDing the board. */
+#define SA_ADDR0 0x00 /* Etherexpress Pro/10 */
+#define SA_ADDR1 0xaa
+#define SA_ADDR2 0x00
+
+#define GetBit(x,y) ((x & (1<<y))>>y)
+
+/* EEPROM Word 0: */
+#define ee_PnP 0 /* Plug 'n Play enable bit */
+#define ee_Word1 1 /* Word 1? */
+#define ee_BusWidth 2 /* 8/16 bit */
+#define ee_FlashAddr 3 /* Flash Address */
+#define ee_FlashMask 0x7 /* Mask */
+#define ee_AutoIO 6 /* */
+#define ee_reserved0 7 /* =0! */
+#define ee_Flash 8 /* Flash there? */
+#define ee_AutoNeg 9 /* Auto Negotiation enabled? */
+#define ee_IO0 10 /* IO Address LSB */
+#define ee_IO0Mask 0x /*...*/
+#define ee_IO1 15 /* IO MSB */
+
+/* EEPROM Word 1: */
+#define ee_IntSel 0 /* Interrupt */
+#define ee_IntMask 0x7
+#define ee_LI 3 /* Link Integrity 0= enabled */
+#define ee_PC 4 /* Polarity Correction 0= enabled */
+#define ee_TPE_AUI 5 /* PortSelection 1=TPE */
+#define ee_Jabber 6 /* Jabber prevention 0= enabled */
+#define ee_AutoPort 7 /* Auto Port Selection 1= Disabled */
+#define ee_SMOUT 8 /* SMout Pin Control 0= Input */
+#define ee_PROM 9 /* Flash EPROM / PROM 0=Flash */
+#define ee_reserved1 10 /* .. 12 =0! */
+#define ee_AltReady 13 /* Alternate Ready, 0=normal */
+#define ee_reserved2 14 /* =0! */
+#define ee_Duplex 15
+
+/* Word2,3,4: */
+#define ee_IA5 0 /*bit start for individual Addr Byte 5 */
+#define ee_IA4 8 /*bit start for individual Addr Byte 5 */
+#define ee_IA3 0 /*bit start for individual Addr Byte 5 */
+#define ee_IA2 8 /*bit start for individual Addr Byte 5 */
+#define ee_IA1 0 /*bit start for individual Addr Byte 5 */
+#define ee_IA0 8 /*bit start for individual Addr Byte 5 */
+
+/* Word 5: */
+#define ee_BNC_TPE 0 /* 0=TPE */
+#define ee_BootType 1 /* 00=None, 01=IPX, 10=ODI, 11=NDIS */
+#define ee_BootTypeMask 0x3
+#define ee_NumConn 3 /* Number of Connections 0= One or Two */
+#define ee_FlashSock 4 /* Presence of Flash Socket 0= Present */
+#define ee_PortTPE 5
+#define ee_PortBNC 6
+#define ee_PortAUI 7
+#define ee_PowerMgt 10 /* 0= disabled */
+#define ee_CP 13 /* Concurrent Processing */
+#define ee_CPMask 0x7
+
+/* Word 6: */
+#define ee_Stepping 0 /* Stepping info */
+#define ee_StepMask 0x0F
+#define ee_BoardID 4 /* Manucaturer Board ID, reserved */
+#define ee_BoardMask 0x0FFF
+
+/* Word 7: */
+#define ee_INT_TO_IRQ 0 /* int to IRQ Mapping = 0x1EB8 for Pro/10+ */
+#define ee_FX_INT2IRQ 0x1EB8 /* the _only_ mapping allowed for FX chips */
+
+/*..*/
+#define ee_SIZE 0x40 /* total EEprom Size */
+#define ee_Checksum 0xBABA /* initial and final value for adding checksum */
+
+
+/* Card identification via EEprom: */
+#define ee_addr_vendor 0x10 /* Word offset for EISA Vendor ID */
+#define ee_addr_id 0x11 /* Word offset for Card ID */
+#define ee_addr_SN 0x12 /* Serial Number */
+#define ee_addr_CRC_8 0x14 /* CRC over last thee Bytes */
+
+
+#define ee_vendor_intel0 0x25 /* Vendor ID Intel */
+#define ee_vendor_intel1 0xD4
+#define ee_id_eepro10p0 0x10 /* ID for eepro/10+ */
+#define ee_id_eepro10p1 0x31
+
+/* now this section could be used by both boards: the oldies and the ee10:
+ * ee10 uses tx buffer before of rx buffer and the oldies the inverse.
+ * (aris)
+ */
+#define RAM_SIZE 0x8000
+
+#define RCV_HEADER 8
+#define RCV_DEFAULT_RAM 0x6000
+#define RCV_RAM rcv_ram
+
+static unsigned rcv_ram = RCV_DEFAULT_RAM;
+
+#define XMT_HEADER 8
+#define XMT_RAM (RAM_SIZE - RCV_RAM)
+
+#define XMT_START ((rcv_start + RCV_RAM) % RAM_SIZE)
+
+#define RCV_LOWER_LIMIT (rcv_start >> 8)
+#define RCV_UPPER_LIMIT (((rcv_start + RCV_RAM) - 2) >> 8)
+#define XMT_LOWER_LIMIT (XMT_START >> 8)
+#define XMT_UPPER_LIMIT (((XMT_START + XMT_RAM) - 2) >> 8)
+
+#define RCV_START_PRO 0x00
+#define RCV_START_10 XMT_RAM
+ /* by default the old driver */
+static unsigned rcv_start = RCV_START_PRO;
+
+#define RCV_DONE 0x0008
+#define RX_OK 0x2000
+#define RX_ERROR 0x0d81
+
+#define TX_DONE_BIT 0x0080
+#define CHAIN_BIT 0x8000
+#define XMT_STATUS 0x02
+#define XMT_CHAIN 0x04
+#define XMT_COUNT 0x06
+
+#define BANK0_SELECT 0x00
+#define BANK1_SELECT 0x40
+#define BANK2_SELECT 0x80
+
+/* Bank 0 registers */
+#define COMMAND_REG 0x00 /* Register 0 */
+#define MC_SETUP 0x03
+#define XMT_CMD 0x04
+#define DIAGNOSE_CMD 0x07
+#define RCV_ENABLE_CMD 0x08
+#define RCV_DISABLE_CMD 0x0a
+#define STOP_RCV_CMD 0x0b
+#define RESET_CMD 0x0e
+#define POWER_DOWN_CMD 0x18
+#define RESUME_XMT_CMD 0x1c
+#define SEL_RESET_CMD 0x1e
+#define STATUS_REG 0x01 /* Register 1 */
+#define RX_INT 0x02
+#define TX_INT 0x04
+#define EXEC_STATUS 0x30
+#define ID_REG 0x02 /* Register 2 */
+#define R_ROBIN_BITS 0xc0 /* round robin counter */
+#define ID_REG_MASK 0x2c
+#define ID_REG_SIG 0x24
+#define AUTO_ENABLE 0x10
+#define INT_MASK_REG 0x03 /* Register 3 */
+#define RX_STOP_MASK 0x01
+#define RX_MASK 0x02
+#define TX_MASK 0x04
+#define EXEC_MASK 0x08
+#define ALL_MASK 0x0f
+#define IO_32_BIT 0x10
+#define RCV_BAR 0x04 /* The following are word (16-bit) registers */
+#define RCV_STOP 0x06
+
+#define XMT_BAR_PRO 0x0a
+#define XMT_BAR_10 0x0b
+static unsigned xmt_bar = XMT_BAR_PRO;
+
+#define HOST_ADDRESS_REG 0x0c
+#define IO_PORT 0x0e
+#define IO_PORT_32_BIT 0x0c
+
+/* Bank 1 registers */
+#define REG1 0x01
+#define WORD_WIDTH 0x02
+#define INT_ENABLE 0x80
+#define INT_NO_REG 0x02
+#define RCV_LOWER_LIMIT_REG 0x08
+#define RCV_UPPER_LIMIT_REG 0x09
+
+#define XMT_LOWER_LIMIT_REG_PRO 0x0a
+#define XMT_UPPER_LIMIT_REG_PRO 0x0b
+#define XMT_LOWER_LIMIT_REG_10 0x0b
+#define XMT_UPPER_LIMIT_REG_10 0x0a
+static unsigned xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO;
+static unsigned xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO;
+
+/* Bank 2 registers */
+#define XMT_Chain_Int 0x20 /* Interrupt at the end of the transmit chain */
+#define XMT_Chain_ErrStop 0x40 /* Interrupt at the end of the chain even if there are errors */
+#define RCV_Discard_BadFrame 0x80 /* Throw bad frames away, and continue to receive others */
+#define REG2 0x02
+#define PRMSC_Mode 0x01
+#define Multi_IA 0x20
+#define REG3 0x03
+#define TPE_BIT 0x04
+#define BNC_BIT 0x20
+#define REG13 0x0d
+#define FDX 0x00
+#define A_N_ENABLE 0x02
+
+#define I_ADD_REG0 0x04
+#define I_ADD_REG1 0x05
+#define I_ADD_REG2 0x06
+#define I_ADD_REG3 0x07
+#define I_ADD_REG4 0x08
+#define I_ADD_REG5 0x09
+
+#define EEPROM_REG_PRO 0x0a
+#define EEPROM_REG_10 0x0b
+static unsigned eeprom_reg = EEPROM_REG_PRO;
+
+#define EESK 0x01
+#define EECS 0x02
+#define EEDI 0x04
+#define EEDO 0x08
+
+/* The horrible routine to read a word from the serial EEPROM. */
+/* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */
+
+/* The delay between EEPROM clock transitions. */
+#define eeprom_delay() { udelay(40); }
+#define EE_READ_CMD (6 << 6)
+
+/* do a full reset; data sheet asks for 250us delay */
+#define eepro_full_reset(ioaddr) outb(RESET_CMD, ioaddr); udelay(255);
+
+/* do a nice reset */
+#define eepro_sel_reset(ioaddr) \
+ do { \
+ outb ( SEL_RESET_CMD, ioaddr ); \
+ (void) SLOW_DOWN; \
+ (void) SLOW_DOWN; \
+ } while (0)
+
+/* clear all interrupts */
+#define eepro_clear_int(ioaddr) outb(ALL_MASK, ioaddr + STATUS_REG)
+
+/* enable rx */
+#define eepro_en_rx(ioaddr) outb(RCV_ENABLE_CMD, ioaddr)
+
+/* disable rx */
+#define eepro_dis_rx(ioaddr) outb(RCV_DISABLE_CMD, ioaddr)
+
+/* switch bank */
+#define eepro_sw2bank0(ioaddr) outb(BANK0_SELECT, ioaddr)
+#define eepro_sw2bank1(ioaddr) outb(BANK1_SELECT, ioaddr)
+#define eepro_sw2bank2(ioaddr) outb(BANK2_SELECT, ioaddr)
+
+static unsigned int rx_start, tx_start;
+static int tx_last;
+static unsigned int tx_end;
+static int eepro = 0;
+static unsigned int mem_start, mem_end = RCV_DEFAULT_RAM / 1024;
+
+/**************************************************************************
+RESET - Reset adapter
+***************************************************************************/
+static void eepro_reset(struct nic *nic)
+{
+ int temp_reg, i;
+
+ /* put the card in its initial state */
+ eepro_sw2bank2(nic->ioaddr); /* be careful, bank2 now */
+ temp_reg = inb(nic->ioaddr + eeprom_reg);
+ DBG("Stepping %d\n", temp_reg >> 5);
+ if (temp_reg & 0x10) /* check the TurnOff Enable bit */
+ outb(temp_reg & 0xEF, nic->ioaddr + eeprom_reg);
+ for (i = 0; i < ETH_ALEN; i++) /* fill the MAC address */
+ outb(nic->node_addr[i], nic->ioaddr + I_ADD_REG0 + i);
+ temp_reg = inb(nic->ioaddr + REG1);
+ /* setup Transmit Chaining and discard bad RCV frames */
+ outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop
+ | RCV_Discard_BadFrame, nic->ioaddr + REG1);
+ temp_reg = inb(nic->ioaddr + REG2); /* match broadcast */
+ outb(temp_reg | 0x14, nic->ioaddr + REG2);
+ temp_reg = inb(nic->ioaddr + REG3);
+ outb(temp_reg & 0x3F, nic->ioaddr + REG3); /* clear test mode */
+ /* set the receiving mode */
+ eepro_sw2bank1(nic->ioaddr); /* be careful, bank1 now */
+ /* initialise the RCV and XMT upper and lower limits */
+ outb(RCV_LOWER_LIMIT, nic->ioaddr + RCV_LOWER_LIMIT_REG);
+ outb(RCV_UPPER_LIMIT, nic->ioaddr + RCV_UPPER_LIMIT_REG);
+ outb(XMT_LOWER_LIMIT, nic->ioaddr + xmt_lower_limit_reg);
+ outb(XMT_UPPER_LIMIT, nic->ioaddr + xmt_upper_limit_reg);
+ eepro_sw2bank0(nic->ioaddr); /* Switch back to bank 0 */
+ eepro_clear_int(nic->ioaddr);
+ /* Initialise RCV */
+ outw(rx_start = (RCV_LOWER_LIMIT << 8), nic->ioaddr + RCV_BAR);
+ outw(((RCV_UPPER_LIMIT << 8) | 0xFE), nic->ioaddr + RCV_STOP);
+ /* Make sure 1st poll won't find a valid packet header */
+ outw((RCV_LOWER_LIMIT << 8), nic->ioaddr + HOST_ADDRESS_REG);
+ outw(0, nic->ioaddr + IO_PORT);
+ /* Intialise XMT */
+ outw((XMT_LOWER_LIMIT << 8), nic->ioaddr + xmt_bar);
+ eepro_sel_reset(nic->ioaddr);
+ tx_start = tx_end = (unsigned int) (XMT_LOWER_LIMIT << 8);
+ tx_last = 0;
+ eepro_en_rx(nic->ioaddr);
+}
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int eepro_poll(struct nic *nic, int retrieve)
+{
+ unsigned int rcv_car = rx_start;
+ unsigned int rcv_event, rcv_status, rcv_next_frame, rcv_size;
+
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+#if 0
+ if ((inb(nic->ioaddr + STATUS_REG) & 0x40) == 0)
+ return (0);
+ outb(0x40, nic->ioaddr + STATUS_REG);
+#endif
+ outw(rcv_car, nic->ioaddr + HOST_ADDRESS_REG);
+ rcv_event = inw(nic->ioaddr + IO_PORT);
+ if (rcv_event != RCV_DONE)
+ return (0);
+
+ /* FIXME: I'm guessing this might not work with this card, since
+ it looks like once a rcv_event is started it must be completed.
+ maybe there's another way. */
+ if ( ! retrieve ) return 1;
+
+ rcv_status = inw(nic->ioaddr + IO_PORT);
+ rcv_next_frame = inw(nic->ioaddr + IO_PORT);
+ rcv_size = inw(nic->ioaddr + IO_PORT);
+#if 0
+ printf("%hX %hX %d %hhX\n", rcv_status, rcv_next_frame, rcv_size,
+ inb(nic->ioaddr + STATUS_REG));
+#endif
+ if ((rcv_status & (RX_OK|RX_ERROR)) != RX_OK) {
+ printf("Receive error %hX\n", rcv_status);
+ return (0);
+ }
+ rcv_size &= 0x3FFF;
+ insw(nic->ioaddr + IO_PORT, nic->packet, ((rcv_size + 3) >> 1));
+#if 0
+{
+ int i;
+ for (i = 0; i < 48; i++) {
+ printf("%hhX", nic->packet[i]);
+ putchar(i % 16 == 15 ? '\n' : ' ');
+ }
+}
+#endif
+ nic->packetlen = rcv_size;
+ rcv_car = (rx_start + RCV_HEADER + rcv_size);
+ rx_start = rcv_next_frame;
+/*
+ hex_dump(rcv_car, nic->packetlen);
+*/
+
+ if (rcv_car == 0)
+ rcv_car = ((RCV_UPPER_LIMIT << 8) | 0xff);
+ outw(rcv_car - 1, nic->ioaddr + RCV_STOP);
+ return (1);
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void eepro_transmit(
+ struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ unsigned int status, tx_available, last, end, length;
+ unsigned short type;
+ int boguscount = 20;
+
+ length = s + ETH_HLEN;
+ if (tx_end > tx_start)
+ tx_available = XMT_RAM - (tx_end - tx_start);
+ else if (tx_end < tx_start)
+ tx_available = tx_start - tx_end;
+ else
+ tx_available = XMT_RAM;
+ assert ( length <= tx_available );
+ last = tx_end;
+ end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
+ if (end >= (XMT_UPPER_LIMIT << 8)) {
+ last = (XMT_LOWER_LIMIT << 8);
+ end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
+ }
+ outw(last, nic->ioaddr + HOST_ADDRESS_REG);
+ outw(XMT_CMD, nic->ioaddr + IO_PORT);
+ outw(0, nic->ioaddr + IO_PORT);
+ outw(end, nic->ioaddr + IO_PORT);
+ outw(length, nic->ioaddr + IO_PORT);
+ outsw(nic->ioaddr + IO_PORT, d, ETH_ALEN / 2);
+ outsw(nic->ioaddr + IO_PORT, nic->node_addr, ETH_ALEN / 2);
+ type = htons(t);
+ outsw(nic->ioaddr + IO_PORT, &type, sizeof(type) / 2);
+ outsw(nic->ioaddr + IO_PORT, p, (s + 3) >> 1);
+ /* A dummy read to flush the DRAM write pipeline */
+ status = inw(nic->ioaddr + IO_PORT);
+ outw(last, nic->ioaddr + xmt_bar);
+ outb(XMT_CMD, nic->ioaddr);
+ tx_start = last;
+ tx_last = last;
+ tx_end = end;
+#if 0
+ printf("%d %d\n", tx_start, tx_end);
+#endif
+ while (boguscount > 0) {
+ if (((status = inw(nic->ioaddr + IO_PORT)) & TX_DONE_BIT) == 0) {
+ udelay(40);
+ boguscount--;
+ continue;
+ }
+ if ((status & 0x2000) == 0) {
+ DBG("Transmit status %hX\n", status);
+ }
+ }
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void eepro_disable ( struct nic *nic, struct isa_device *isa __unused ) {
+ eepro_sw2bank0(nic->ioaddr); /* Switch to bank 0 */
+ /* Flush the Tx and disable Rx */
+ outb(STOP_RCV_CMD, nic->ioaddr);
+ tx_start = tx_end = (XMT_LOWER_LIMIT << 8);
+ tx_last = 0;
+ /* Reset the 82595 */
+ eepro_full_reset(nic->ioaddr);
+}
+
+/**************************************************************************
+DISABLE - Enable, Disable, or Force interrupts
+***************************************************************************/
+static void eepro_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static int read_eeprom(uint16_t ioaddr, int location)
+{
+ int i;
+ unsigned short retval = 0;
+ int ee_addr = ioaddr + eeprom_reg;
+ int read_cmd = location | EE_READ_CMD;
+ int ctrl_val = EECS;
+
+ if (eepro == LAN595FX_10ISA) {
+ eepro_sw2bank1(ioaddr);
+ outb(0x00, ioaddr + STATUS_REG);
+ }
+ eepro_sw2bank2(ioaddr);
+ outb(ctrl_val, ee_addr);
+ /* shift the read command bits out */
+ for (i = 8; i >= 0; i--) {
+ short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI : ctrl_val;
+ outb(outval, ee_addr);
+ outb(outval | EESK, ee_addr); /* EEPROM clock tick */
+ eeprom_delay();
+ outb(outval, ee_addr); /* finish EEPROM clock tick */
+ eeprom_delay();
+ }
+ outb(ctrl_val, ee_addr);
+ for (i = 16; i > 0; i--) {
+ outb(ctrl_val | EESK, ee_addr);
+ eeprom_delay();
+ retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0);
+ outb(ctrl_val, ee_addr);
+ eeprom_delay();
+ }
+ /* terminate the EEPROM access */
+ ctrl_val &= ~EECS;
+ outb(ctrl_val | EESK, ee_addr);
+ eeprom_delay();
+ outb(ctrl_val, ee_addr);
+ eeprom_delay();
+ eepro_sw2bank0(ioaddr);
+ return (retval);
+}
+
+static int eepro_probe1 ( isa_probe_addr_t ioaddr ) {
+ int id, counter;
+
+ id = inb(ioaddr + ID_REG);
+ if ((id & ID_REG_MASK) != ID_REG_SIG)
+ return (0);
+ counter = id & R_ROBIN_BITS;
+ if (((id = inb(ioaddr + ID_REG)) & R_ROBIN_BITS) != (counter + 0x40))
+ return (0);
+ /* yes the 82595 has been found */
+ return (1);
+}
+
+static struct nic_operations eepro_operations = {
+ .connect = dummy_connect,
+ .poll = eepro_poll,
+ .transmit = eepro_transmit,
+ .irq = eepro_irq,
+
+};
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+static int eepro_probe ( struct nic *nic, struct isa_device *isa ) {
+
+ int i, l_eepro = 0;
+ union {
+ unsigned char caddr[ETH_ALEN];
+ unsigned short saddr[ETH_ALEN/2];
+ } station_addr;
+ const char *name;
+
+ nic->irqno = 0;
+ nic->ioaddr = isa->ioaddr;
+
+ station_addr.saddr[2] = read_eeprom(nic->ioaddr,2);
+ if ( ( station_addr.saddr[2] == 0x0000 ) ||
+ ( station_addr.saddr[2] == 0xFFFF ) ) {
+ l_eepro = 3;
+ eepro = LAN595FX_10ISA;
+ eeprom_reg= EEPROM_REG_10;
+ rcv_start = RCV_START_10;
+ xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;
+ xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10;
+ station_addr.saddr[2] = read_eeprom(nic->ioaddr,2);
+ }
+ station_addr.saddr[1] = read_eeprom(nic->ioaddr,3);
+ station_addr.saddr[0] = read_eeprom(nic->ioaddr,4);
+ if (l_eepro)
+ name = "Intel EtherExpress 10 ISA";
+ else if (read_eeprom(nic->ioaddr,7) == ee_FX_INT2IRQ) {
+ name = "Intel EtherExpress Pro/10+ ISA";
+ l_eepro = 2;
+ } else if (station_addr.saddr[0] == SA_ADDR1) {
+ name = "Intel EtherExpress Pro/10 ISA";
+ l_eepro = 1;
+ } else {
+ l_eepro = 0;
+ name = "Intel 82595-based LAN card";
+ }
+ station_addr.saddr[0] = swap16(station_addr.saddr[0]);
+ station_addr.saddr[1] = swap16(station_addr.saddr[1]);
+ station_addr.saddr[2] = swap16(station_addr.saddr[2]);
+ for (i = 0; i < ETH_ALEN; i++) {
+ nic->node_addr[i] = station_addr.caddr[i];
+ }
+
+ DBG ( "%s ioaddr %#hX, addr %s", name, nic->ioaddr, eth_ntoa ( nic->node_addr ) );
+
+ mem_start = RCV_LOWER_LIMIT << 8;
+ if ((mem_end & 0x3F) < 3 || (mem_end & 0x3F) > 29)
+ mem_end = RCV_UPPER_LIMIT << 8;
+ else {
+ mem_end = mem_end * 1024 + (RCV_LOWER_LIMIT << 8);
+ rcv_ram = mem_end - (RCV_LOWER_LIMIT << 8);
+ }
+ printf(", Rx mem %dK, if %s\n", (mem_end - mem_start) >> 10,
+ GetBit(read_eeprom(nic->ioaddr,5), ee_BNC_TPE) ? "BNC" : "TP");
+
+ eepro_reset(nic);
+
+ /* point to NIC specific routines */
+ nic->nic_op = &eepro_operations;
+ return 1;
+}
+
+static isa_probe_addr_t eepro_probe_addrs[] = {
+ 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360,
+};
+
+ISA_DRIVER ( eepro_driver, eepro_probe_addrs, eepro_probe1,
+ GENERIC_ISAPNP_VENDOR, 0x828a );
+
+DRIVER ( "eepro", nic_driver, isa_driver, eepro_driver,
+ eepro_probe, eepro_disable );
+
+ISA_ROM ( "eepro", "Intel Etherexpress Pro/10" );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/eepro100.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/eepro100.c
new file mode 100644
index 00000000..a2d99b43
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/eepro100.c
@@ -0,0 +1,1173 @@
+/*
+ * eepro100.c -- This is a driver for Intel Fast Ethernet Controllers
+ * (ifec).
+ *
+ * Originally written for Etherboot by:
+ *
+ * Copyright (C) AW Computer Systems.
+ * written by R.E.Wolff -- R.E.Wolff@BitWizard.nl
+ *
+ * AW Computer Systems is contributing to the free software community
+ * by paying for this driver and then putting the result under GPL.
+ *
+ * If you need a Linux device driver, please contact BitWizard for a
+ * quote.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * date version by what
+ * Written: May 29 1997 V0.10 REW Initial revision.
+ * changes: May 31 1997 V0.90 REW Works!
+ * Jun 1 1997 V0.91 REW Cleanup
+ * Jun 2 1997 V0.92 REW Add some code documentation
+ * Jul 25 1997 V1.00 REW Tested by AW to work in a PROM
+ * Cleanup for publication
+ * Dez 11 2004 V1.10 Kiszka Add RX ring buffer support
+ * Jun 2008 v2.0 mdeck Updated to iPXE. Changed much.
+ *
+ * Cleanups and fixes by Thomas Miletich<thomas.miletich@gmail.com>
+ *
+ * This is the etherboot intel etherexpress Pro/100B driver.
+ *
+ * It was written from scratch, with Donald Beckers eepro100.c kernel
+ * driver as a guideline. Mostly the 82557 related definitions and the
+ * lower level routines have been cut-and-pasted into this source.
+ *
+ * The driver was finished before Intel got the NDA out of the closet.
+ *
+ * Datasheet is now published and available from
+ * ftp://download.intel.com/design/network/manuals/8255X_OpenSDM.pdf
+ * - Michael Brown
+ * */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * General Theory of Operation
+ *
+ * Initialization
+ *
+ * ifec_pci_probe() is called by iPXE during initialization. Typical NIC
+ * initialization is performed. EEPROM data is read.
+ *
+ * Network Boot
+ *
+ * ifec_net_open() is called by iPXE before attempting to network boot from the
+ * card. Here, the Command Unit & Receive Unit are initialized. The tx & rx
+ * rings are setup. The MAC address is programmed and the card is configured.
+ *
+ * Transmit
+ *
+ * ifec_net_transmit() enqueues a packet in the tx ring - active::tcbs[] The tx
+ * ring is composed of TCBs linked to each other into a ring. A tx request
+ * fills out the next available TCB with a pointer to the packet data.
+ * The last enqueued tx is always at active::tcb_head. Thus, a tx request fills
+ * out the TCB following tcb_head.
+ * active::tcb_tail points to the TCB we're awaiting completion of.
+ * ifec_tx_process() checks tcb_tail, and once complete,
+ * blindly increments tcb_tail to the next ring TCB.
+ *
+ * Receive
+ *
+ * priv::rfds[] is an array of Receive Frame Descriptors. The RFDs are linked
+ * together to form a ring.
+ * ifec_net_poll() calls ifec_rx_process(), which checks the next RFD for
+ * data. If we received a packet, we allocate a new io_buffer and copy the
+ * packet data into it. If alloc_iob() fails, we don't touch the RFD and try
+ * again on the next poll.
+ */
+
+/*
+ * Debugging levels:
+ * - DBG() is for any errors, i.e. failed alloc_iob(), malloc_dma(),
+ * TX overflow, corrupted packets, ...
+ * - DBG2() is for successful events, like packet received,
+ * packet transmitted, and other general notifications.
+ * - DBGP() prints the name of each called function on entry
+ */
+
+#include <stdint.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/pci.h>
+#include <ipxe/spi_bit.h>
+#include <ipxe/timer.h>
+#include <ipxe/nvs.h>
+#include <ipxe/threewire.h>
+#include <ipxe/netdevice.h>
+#include "eepro100.h"
+
+/****************************** Global data **********************************/
+
+/*
+ * This is the default configuration command data. The values were copied from
+ * the Linux kernel initialization for the eepro100.
+ */
+static struct ifec_cfg ifec_cfg = {
+ .status = 0,
+ .command = CmdConfigure | CmdSuspend,
+ .link = 0, /* Filled in later */
+ .byte = { 22, /* How many bytes in this array */
+ ( TX_FIFO << 4 ) | RX_FIFO, /* Rx & Tx FIFO limits */
+ 0, 0, /* Adaptive Interframe Spacing */
+ RX_DMA_COUNT, /* Rx DMA max byte count */
+ TX_DMA_COUNT + 0x80, /* Tx DMA max byte count */
+ 0x32, /* Many bits. */
+ 0x03, /* Discard short receive & Underrun retries */
+ 1, /* 1=Use MII 0=Use AUI */
+ 0,
+ 0x2E, /* NSAI, Preamble length, & Loopback*/
+ 0, /* Linear priority */
+ 0x60, /* L PRI MODE & Interframe spacing */
+ 0, 0xf2,
+ 0x48, /* Promiscuous, Broadcast disable, CRS & CDT */
+ 0, 0x40,
+ 0xf2, /* Stripping, Padding, Receive CRC Transfer */
+ 0x80, /* 0x40=Force full-duplex, 0x80=Allowfull-duplex*/
+ 0x3f, /* Multiple IA */
+ 0x0D } /* Multicast all */
+};
+
+static struct net_device_operations ifec_operations = {
+ .open = ifec_net_open,
+ .close = ifec_net_close,
+ .transmit = ifec_net_transmit,
+ .poll = ifec_net_poll,
+ .irq = ifec_net_irq
+};
+
+/******************* iPXE PCI Device Driver API functions ********************/
+
+/*
+ * Initialize the PCI device.
+ *
+ * @v pci The device's associated pci_device structure.
+ * @v id The PCI device + vendor id.
+ * @ret rc Returns zero if successfully initialized.
+ *
+ * This function is called very early on, while iPXE is initializing.
+ * This is a iPXE PCI Device Driver API function.
+ */
+static int ifec_pci_probe ( struct pci_device *pci )
+{
+ struct net_device *netdev;
+ struct ifec_private *priv;
+ int rc;
+
+ DBGP ( "ifec_pci_probe: " );
+
+ if ( pci->ioaddr == 0 )
+ return -EINVAL;
+
+ netdev = alloc_etherdev ( sizeof(*priv) );
+ if ( !netdev )
+ return -ENOMEM;
+
+ netdev_init ( netdev, &ifec_operations );
+ priv = netdev->priv;
+
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+
+ /* enable bus master, etc */
+ adjust_pci_device( pci );
+
+ DBGP ( "pci " );
+
+ memset ( priv, 0, sizeof(*priv) );
+ priv->ioaddr = pci->ioaddr;
+
+ ifec_reset ( netdev );
+ DBGP ( "reset " );
+
+ ifec_init_eeprom ( netdev );
+
+ /* read MAC address */
+ nvs_read ( &priv->eeprom.nvs, EEPROM_ADDR_MAC_0, netdev->hw_addr,
+ ETH_ALEN );
+ /* read mdio_register */
+ nvs_read ( &priv->eeprom.nvs, EEPROM_ADDR_MDIO_REGISTER,
+ &priv->mdio_register, 2 );
+
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto error;
+
+ netdev_link_up ( netdev );
+
+ DBGP ( "ints\n" );
+
+ return 0;
+
+error:
+ ifec_reset ( netdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+
+ return rc;
+}
+
+/*
+ * Remove a device from the PCI device list.
+ *
+ * @v pci PCI device to remove.
+ *
+ * This is a PCI Device Driver API function.
+ */
+static void ifec_pci_remove ( struct pci_device *pci )
+{
+ struct net_device *netdev = pci_get_drvdata ( pci );
+
+ DBGP ( "ifec_pci_remove\n" );
+
+ unregister_netdev ( netdev );
+ ifec_reset ( netdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/****************** iPXE Network Device Driver API functions *****************/
+
+/*
+ * Close a network device.
+ *
+ * @v netdev Device to close.
+ *
+ * This is a iPXE Network Device Driver API function.
+ */
+static void ifec_net_close ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev->priv;
+ unsigned long ioaddr = priv->ioaddr;
+ unsigned short intr_status;
+
+ DBGP ( "ifec_net_close\n" );
+
+ /* disable interrupts */
+ ifec_net_irq ( netdev, 0 );
+
+ /* Ack & clear ints */
+ intr_status = inw ( ioaddr + SCBStatus );
+ outw ( intr_status, ioaddr + SCBStatus );
+ inw ( ioaddr + SCBStatus );
+
+ ifec_reset ( netdev );
+
+ /* Free any resources */
+ ifec_free ( netdev );
+}
+
+/* Interrupts to be masked */
+#define INTERRUPT_MASK ( SCBMaskEarlyRx | SCBMaskFlowCtl )
+
+/*
+ * Enable or disable IRQ masking.
+ *
+ * @v netdev Device to control.
+ * @v enable Zero to mask off IRQ, non-zero to enable IRQ.
+ *
+ * This is a iPXE Network Driver API function.
+ */
+static void ifec_net_irq ( struct net_device *netdev, int enable )
+{
+ struct ifec_private *priv = netdev->priv;
+ unsigned long ioaddr = priv->ioaddr;
+
+ DBGP ( "ifec_net_irq\n" );
+
+ outw ( enable ? INTERRUPT_MASK : SCBMaskAll, ioaddr + SCBCmd );
+}
+
+/*
+ * Opens a network device.
+ *
+ * @v netdev Device to be opened.
+ * @ret rc Non-zero if failed to open.
+ *
+ * This enables tx and rx on the device.
+ * This is a iPXE Network Device Driver API function.
+ */
+static int ifec_net_open ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev->priv;
+ struct ifec_ias *ias = NULL;
+ struct ifec_cfg *cfg = NULL;
+ int i, options;
+ int rc = -ENOMEM;
+
+ DBGP ( "ifec_net_open: " );
+
+ /* Ensure interrupts are disabled. */
+ ifec_net_irq ( netdev, 0 );
+
+ /* Initialize Command Unit and Receive Unit base addresses. */
+ ifec_scb_cmd ( netdev, 0, RUAddrLoad );
+ ifec_scb_cmd ( netdev, virt_to_bus ( &priv->stats ), CUStatsAddr );
+ ifec_scb_cmd ( netdev, 0, CUCmdBase );
+
+ /* Initialize both rings */
+ if ( ( rc = ifec_rx_setup ( netdev ) ) != 0 )
+ goto error;
+ if ( ( rc = ifec_tx_setup ( netdev ) ) != 0 )
+ goto error;
+
+ /* Initialize MDIO */
+ options = 0x00; /* 0x40 = 10mbps half duplex, 0x00 = Autosense */
+ ifec_mdio_setup ( netdev, options );
+
+ /* Prepare MAC address w/ Individual Address Setup (ias) command.*/
+ ias = malloc_dma ( sizeof ( *ias ), CB_ALIGN );
+ if ( !ias ) {
+ rc = -ENOMEM;
+ goto error;
+ }
+ ias->command = CmdIASetup;
+ ias->status = 0;
+ memcpy ( ias->ia, netdev->ll_addr, ETH_ALEN );
+
+ /* Prepare operating parameters w/ a configure command. */
+ cfg = malloc_dma ( sizeof ( *cfg ), CB_ALIGN );
+ if ( !cfg ) {
+ rc = -ENOMEM;
+ goto error;
+ }
+ memcpy ( cfg, &ifec_cfg, sizeof ( *cfg ) );
+ cfg->link = virt_to_bus ( priv->tcbs );
+ cfg->byte[19] = ( options & 0x10 ) ? 0xC0 : 0x80;
+ ias->link = virt_to_bus ( cfg );
+
+ /* Issue the ias and configure commands. */
+ ifec_scb_cmd ( netdev, virt_to_bus ( ias ), CUStart );
+ ifec_scb_cmd_wait ( netdev );
+ priv->configured = 1;
+
+ /* Wait up to 10 ms for configuration to initiate */
+ for ( i = 10; i && !cfg->status; i-- )
+ mdelay ( 1 );
+ if ( ! cfg->status ) {
+ DBG ( "Failed to initiate!\n" );
+ goto error;
+ }
+ free_dma ( ias, sizeof ( *ias ) );
+ free_dma ( cfg, sizeof ( *cfg ) );
+ DBG2 ( "cfg " );
+
+ /* Enable rx by sending ring address to card */
+ if ( priv->rfds[0] != NULL ) {
+ ifec_scb_cmd ( netdev, virt_to_bus( priv->rfds[0] ), RUStart );
+ ifec_scb_cmd_wait ( netdev );
+ }
+ DBG2 ( "rx_start\n" );
+
+ return 0;
+
+error:
+ free_dma ( cfg, sizeof ( *cfg ) );
+ free_dma ( ias, sizeof ( *ias ) );
+ ifec_free ( netdev );
+ ifec_reset ( netdev );
+ return rc;
+}
+
+/*
+ * This function allows a driver to process events during operation.
+ *
+ * @v netdev Device being polled.
+ *
+ * This is called periodically by iPXE to let the driver check the status of
+ * transmitted packets and to allow the driver to check for received packets.
+ * This is a iPXE Network Device Driver API function.
+ */
+static void ifec_net_poll ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev->priv;
+ unsigned short intr_status;
+
+ DBGP ( "ifec_net_poll\n" );
+
+ /* acknowledge interrupts ASAP */
+ intr_status = inw ( priv->ioaddr + SCBStatus );
+ outw ( intr_status, priv->ioaddr + SCBStatus );
+ inw ( priv->ioaddr + SCBStatus );
+
+ DBG2 ( "poll - status: 0x%04X\n", intr_status );
+
+ /* anything to do here? */
+ if ( ( intr_status & ( ~INTERRUPT_MASK ) ) == 0 )
+ return;
+
+ /* process received and transmitted packets */
+ ifec_tx_process ( netdev );
+ ifec_rx_process ( netdev );
+
+ ifec_check_ru_status ( netdev, intr_status );
+
+ return;
+}
+
+/*
+ * This transmits a packet.
+ *
+ * @v netdev Device to transmit from.
+ * @v iobuf Data to transmit.
+ * @ret rc Non-zero if failed to transmit.
+ *
+ * This is a iPXE Network Driver API function.
+ */
+static int ifec_net_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf )
+{
+ struct ifec_private *priv = netdev->priv;
+ struct ifec_tcb *tcb = priv->tcb_head->next;
+ unsigned long ioaddr = priv->ioaddr;
+
+ DBGP ( "ifec_net_transmit\n" );
+
+ /* Wait for TCB to become available. */
+ if ( tcb->status || tcb->iob ) {
+ DBG ( "TX overflow\n" );
+ return -ENOBUFS;
+ }
+
+ DBG2 ( "transmitting packet (%zd bytes). status = %hX, cmd=%hX\n",
+ iob_len ( iobuf ), tcb->status, inw ( ioaddr + SCBCmd ) );
+
+ tcb->command = CmdSuspend | CmdTx | CmdTxFlex;
+ tcb->count = 0x01208000;
+ tcb->tbd_addr0 = virt_to_bus ( iobuf->data );
+ tcb->tbd_size0 = 0x3FFF & iob_len ( iobuf );
+ tcb->iob = iobuf;
+
+ ifec_tx_wake ( netdev );
+
+ /* Append to end of ring. */
+ priv->tcb_head = tcb;
+
+ return 0;
+}
+
+/*************************** Local support functions *************************/
+
+/* Define what each GPIO Pin does */
+static const uint16_t ifec_ee_bits[] = {
+ [SPI_BIT_SCLK] = EE_SHIFT_CLK,
+ [SPI_BIT_MOSI] = EE_DATA_WRITE,
+ [SPI_BIT_MISO] = EE_DATA_READ,
+ [SPI_BIT_SS(0)] = EE_ENB,
+};
+
+/*
+ * Read a single bit from the GPIO pins used for SPI.
+ * should be called by SPI bitbash functions only
+ *
+ * @v basher Bitbash device
+ * @v bit_id Line to be read
+ */
+static int ifec_spi_read_bit ( struct bit_basher *basher,
+ unsigned int bit_id )
+{
+ struct ifec_private *priv =
+ container_of ( basher, struct ifec_private, spi.basher );
+ unsigned long ee_addr = priv->ioaddr + CSREeprom;
+ unsigned int ret = 0;
+ uint16_t mask;
+
+ DBGP ( "ifec_spi_read_bit\n" );
+
+ mask = ifec_ee_bits[bit_id];
+ ret = inw (ee_addr);
+
+ return ( ret & mask ) ? 1 : 0;
+}
+
+/*
+ * Write a single bit to the GPIO pins used for SPI.
+ * should be called by SPI bitbash functions only
+ *
+ * @v basher Bitbash device
+ * @v bit_id Line to write to
+ * @v data Value to write
+ */
+static void ifec_spi_write_bit ( struct bit_basher *basher,
+ unsigned int bit_id,
+ unsigned long data )
+{
+ struct ifec_private *priv =
+ container_of ( basher, struct ifec_private, spi.basher );
+ unsigned long ee_addr = priv->ioaddr + CSREeprom;
+ short val;
+ uint16_t mask = ifec_ee_bits[bit_id];
+
+ DBGP ( "ifec_spi_write_bit\n" );
+
+ val = inw ( ee_addr );
+ val &= ~mask;
+ val |= data & mask;
+
+ outw ( val, ee_addr );
+}
+
+/* set function pointer to SPI read- and write-bit functions */
+static struct bit_basher_operations ifec_basher_ops = {
+ .read = ifec_spi_read_bit,
+ .write = ifec_spi_write_bit,
+};
+
+/*
+ * Initialize the eeprom stuff
+ *
+ * @v netdev Network device
+ */
+static void ifec_init_eeprom ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev->priv;
+
+ DBGP ( "ifec_init_eeprom\n" );
+
+ priv->spi.basher.op = &ifec_basher_ops;
+ priv->spi.bus.mode = SPI_MODE_THREEWIRE;
+ init_spi_bit_basher ( &priv->spi );
+
+ priv->eeprom.bus = &priv->spi.bus;
+
+ /* init as 93c46(93c14 compatible) first, to set the command len,
+ * block size and word len. Needs to be set for address len detection.
+ */
+ init_at93c46 ( &priv->eeprom, 16 );
+
+ /* detect address length, */
+ threewire_detect_address_len ( &priv->eeprom );
+
+ /* address len == 8 means 93c66 instead of 93c46 */
+ if ( priv->eeprom.address_len == 8 )
+ init_at93c66 ( &priv->eeprom, 16 );
+}
+
+/*
+ * Support function: ifec_mdio_read
+ *
+ * This probably reads a register in the "physical media interface chip".
+ * -- REW
+ */
+static int ifec_mdio_read ( struct net_device *netdev, int phy_id,
+ int location )
+{
+ struct ifec_private *priv = netdev->priv;
+ unsigned long ioaddr = priv->ioaddr;
+ int val;
+ int boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */
+
+ DBGP ( "ifec_mdio_read\n" );
+
+ outl ( 0x08000000 | ( location << 16 ) | ( phy_id << 21 ),
+ ioaddr + CSRCtrlMDI );
+ do {
+ udelay ( 16 );
+
+ val = inl ( ioaddr + CSRCtrlMDI );
+
+ if ( --boguscnt < 0 ) {
+ DBG ( " ifec_mdio_read() time out with val = %X.\n",
+ val );
+ break;
+ }
+ } while (! ( val & 0x10000000 ) );
+ return val & 0xffff;
+}
+
+/*
+ * Initializes MDIO.
+ *
+ * @v netdev Network device
+ * @v options MDIO options
+ */
+static void ifec_mdio_setup ( struct net_device *netdev, int options )
+{
+ struct ifec_private *priv = netdev->priv;
+ unsigned short mdio_register = priv->mdio_register;
+
+ DBGP ( "ifec_mdio_setup\n" );
+
+ if ( ( (mdio_register>>8) & 0x3f ) == DP83840
+ || ( (mdio_register>>8) & 0x3f ) == DP83840A ) {
+ int mdi_reg23 = ifec_mdio_read ( netdev, mdio_register
+ & 0x1f, 23 ) | 0x0422;
+ if (CONGENB)
+ mdi_reg23 |= 0x0100;
+ DBG2 ( "DP83840 specific setup, setting register 23 to "
+ "%hX.\n", mdi_reg23 );
+ ifec_mdio_write ( netdev, mdio_register & 0x1f, 23, mdi_reg23 );
+ }
+ DBG2 ( "dp83840 " );
+ if ( options != 0 ) {
+ ifec_mdio_write ( netdev, mdio_register & 0x1f, 0,
+ ( (options & 0x20) ? 0x2000 : 0 ) |
+ ( (options & 0x10) ? 0x0100 : 0 ) );
+ DBG2 ( "set mdio_register. " );
+ }
+}
+
+/*
+ * Support function: ifec_mdio_write
+ *
+ * This probably writes to the "physical media interface chip".
+ * -- REW
+ */
+static int ifec_mdio_write ( struct net_device *netdev,
+ int phy_id, int location, int value )
+{
+ struct ifec_private *priv = netdev->priv;
+ unsigned long ioaddr = priv->ioaddr;
+ int val;
+ int boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */
+
+ DBGP ( "ifec_mdio_write\n" );
+
+ outl ( 0x04000000 | ( location << 16 ) | ( phy_id << 21 ) | value,
+ ioaddr + CSRCtrlMDI );
+ do {
+ udelay ( 16 );
+
+ val = inl ( ioaddr + CSRCtrlMDI );
+ if ( --boguscnt < 0 ) {
+ DBG ( " ifec_mdio_write() time out with val = %X.\n",
+ val );
+ break;
+ }
+ } while (! ( val & 0x10000000 ) );
+ return val & 0xffff;
+}
+
+/*
+ * Resets the hardware.
+ *
+ * @v netdev Network device
+ */
+static void ifec_reset ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev->priv;
+ unsigned long ioaddr = priv->ioaddr;
+
+ DBGP ( "ifec_reset\n" );
+
+ /* do partial reset first */
+ outl ( PortPartialReset, ioaddr + CSRPort );
+ inw ( ioaddr + SCBStatus );
+ udelay ( 20 );
+
+ /* full reset */
+ outl ( PortReset, ioaddr + CSRPort );
+ inw ( ioaddr + SCBStatus );
+ udelay ( 20 );
+
+ /* disable interrupts again */
+ ifec_net_irq ( netdev, 0 );
+}
+
+/*
+ * free()s the tx/rx rings.
+ *
+ * @v netdev Network device
+ */
+static void ifec_free ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev_priv ( netdev );
+ int i;
+
+ DBGP ( "ifec_free\n" );
+
+ /* free all allocated receive io_buffers */
+ for ( i = 0; i < RFD_COUNT; i++ ) {
+ free_iob ( priv->rx_iobs[i] );
+ priv->rx_iobs[i] = NULL;
+ priv->rfds[i] = NULL;
+ }
+
+ /* free TX ring buffer */
+ free_dma ( priv->tcbs, TX_RING_BYTES );
+
+ priv->tcbs = NULL;
+}
+
+/*
+ * Initializes an RFD.
+ *
+ * @v rfd RFD struct to initialize
+ * @v command Command word
+ * @v link Link value
+ */
+static void ifec_rfd_init ( struct ifec_rfd *rfd, s16 command, u32 link )
+{
+ DBGP ( "ifec_rfd_init\n" );
+
+ rfd->status = 0;
+ rfd->command = command;
+ rfd->rx_buf_addr = 0xFFFFFFFF;
+ rfd->count = 0;
+ rfd->size = RFD_PACKET_LEN;
+ rfd->link = link;
+}
+
+/*
+ * Send address of new RFD to card
+ *
+ * @v netdev Network device
+ */
+static void ifec_reprime_ru ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev->priv;
+ int cur_rx = priv->cur_rx;
+
+ DBGP ( "ifec_reprime_ru\n" );
+
+ if ( priv->rfds[cur_rx] != NULL ) {
+ ifec_scb_cmd ( netdev, virt_to_bus ( priv->rfds[cur_rx] ),
+ RUStart );
+ ifec_scb_cmd_wait ( netdev );
+ }
+}
+
+/*
+ * Check if reprime of RU needed
+ *
+ * @v netdev Network device
+ */
+static void ifec_check_ru_status ( struct net_device *netdev,
+ unsigned short intr_status )
+{
+ struct ifec_private *priv = netdev->priv;
+
+ DBGP ( "ifec_check_ru_status\n" );
+
+ /*
+ * The chip may have suspended reception for various reasons.
+ * Check for that, and re-prime it should this be the case.
+ */
+ switch ( ( intr_status >> 2 ) & 0xf ) {
+ case 0: /* Idle */
+ case 4: /* Ready */
+ break;
+ case 1: /* Suspended */
+ case 2: /* No resources (RFDs) */
+ case 9: /* Suspended with no more RBDs */
+ case 10: /* No resources due to no RBDs */
+ case 12: /* Ready with no RBDs */
+ DBG ( "ifec_net_poll: RU reprimed.\n" );
+ ifec_reprime_ru ( netdev );
+ break;
+ default:
+ /* reserved values */
+ DBG ( "ifec_net_poll: RU state anomaly: %i\n",
+ ( inw ( priv->ioaddr + SCBStatus ) >> 2 ) & 0xf );
+ break;
+ }
+}
+
+#define RFD_STATUS ( RFD_OK | RFDRxCol | RFDRxErr | RFDShort | \
+ RFDDMAOverrun | RFDNoBufs | RFDCRCError )
+/*
+ * Looks for received packets in the rx ring, reports success or error to
+ * the core accordingly. Starts reallocation of rx ring.
+ *
+ * @v netdev Network device
+ */
+static void ifec_rx_process ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev->priv;
+ int cur_rx = priv->cur_rx;
+ struct io_buffer *iob = priv->rx_iobs[cur_rx];
+ struct ifec_rfd *rfd = priv->rfds[cur_rx];
+ unsigned int rx_len;
+ s16 status;
+
+ DBGP ( "ifec_rx_process\n" );
+
+ /* Process any received packets */
+ while ( iob && rfd && ( status = rfd->status ) ) {
+ rx_len = rfd->count & RFDMaskCount;
+
+ DBG2 ( "Got a packet: Len = %d, cur_rx = %d.\n", rx_len,
+ cur_rx );
+ DBGIO_HD ( (void*)rfd->packet, 0x30 );
+
+ if ( ( status & ( RFD_STATUS & ~RFDShort ) ) != RFD_OK ) {
+ DBG ( "Corrupted packet received. "
+ "Status = %#08hx\n", status );
+ netdev_rx_err ( netdev, iob, -EINVAL );
+ } else {
+ /* Hand off the packet to the network subsystem */
+ iob_put ( iob, rx_len );
+ DBG2 ( "Received packet: %p, len: %d\n", iob, rx_len );
+ netdev_rx ( netdev, iob );
+ }
+
+ /* make sure we don't reuse this RFD */
+ priv->rx_iobs[cur_rx] = NULL;
+ priv->rfds[cur_rx] = NULL;
+
+ /* Next RFD */
+ priv->cur_rx = ( cur_rx + 1 ) % RFD_COUNT;
+ cur_rx = priv->cur_rx;
+ iob = priv->rx_iobs[cur_rx];
+ rfd = priv->rfds[cur_rx];
+ }
+
+ ifec_refill_rx_ring ( netdev );
+}
+
+/*
+ * Allocates io_buffer, set pointers in ifec_private structure accordingly,
+ * reserves space for RFD header in io_buffer.
+ *
+ * @v netdev Network device
+ * @v cur Descriptor number to work on
+ * @v cmd Value to set cmd field in RFD to
+ * @v link Pointer to ned RFD
+ * @ret rc 0 on success, negative on failure
+ */
+static int ifec_get_rx_desc ( struct net_device *netdev, int cur, int cmd,
+ int link )
+{
+ struct ifec_private *priv = netdev->priv;
+ struct ifec_rfd *rfd = priv->rfds[cur];
+
+ DBGP ( "ifec_get_rx_desc\n" );
+
+ priv->rx_iobs[cur] = alloc_iob ( sizeof ( *rfd ) );
+ if ( ! priv->rx_iobs[cur] ) {
+ DBG ( "alloc_iob failed. desc. nr: %d\n", cur );
+ priv->rfds[cur] = NULL;
+ return -ENOMEM;
+ }
+
+ /* Initialize new tail. */
+ priv->rfds[cur] = priv->rx_iobs[cur]->data;
+ ifec_rfd_init ( priv->rfds[cur], cmd, link );
+ iob_reserve ( priv->rx_iobs[cur], RFD_HEADER_LEN );
+
+ return 0;
+}
+
+/*
+ * Allocate new descriptor entries and initialize them if needed
+ *
+ * @v netdev Network device
+ */
+static void ifec_refill_rx_ring ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev->priv;
+ int i, cur_rx;
+ unsigned short intr_status;
+
+ DBGP ( "ifec_refill_rx_ring\n" );
+
+ for ( i = 0; i < RFD_COUNT; i++ ) {
+ cur_rx = ( priv->cur_rx + i ) % RFD_COUNT;
+ /* only refill if empty */
+ if ( priv->rfds[cur_rx] != NULL ||
+ priv->rx_iobs[cur_rx] != NULL )
+ continue;
+
+ DBG2 ( "refilling RFD %d\n", cur_rx );
+
+ if ( ifec_get_rx_desc ( netdev, cur_rx,
+ CmdSuspend | CmdEndOfList, 0 ) == 0 ) {
+ if ( i > 0 ) {
+ int prev_rx = ( ( ( cur_rx + RFD_COUNT ) - 1 )
+ % RFD_COUNT );
+ struct ifec_rfd *rfd = priv->rfds[prev_rx];
+
+ rfd->command = 0;
+ rfd->link = virt_to_bus ( priv->rfds[cur_rx] );
+ }
+ }
+ }
+
+ intr_status = inw ( priv->ioaddr + SCBStatus );
+ ifec_check_ru_status ( netdev, intr_status );
+}
+
+/*
+ * Initial allocation & initialization of the rx ring.
+ *
+ * @v netdev Device of rx ring.
+ * @ret rc Non-zero if error occured
+ */
+static int ifec_rx_setup ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev->priv;
+ int i;
+
+ DBGP ( "ifec_rx_setup\n" );
+
+ priv->cur_rx = 0;
+
+ /* init values for ifec_refill_rx_ring() */
+ for ( i = 0; i < RFD_COUNT; i++ ) {
+ priv->rfds[i] = NULL;
+ priv->rx_iobs[i] = NULL;
+ }
+ ifec_refill_rx_ring ( netdev );
+
+ return 0;
+}
+
+/*
+ * Initiates a SCB command.
+ *
+ * @v netdev Network device
+ * @v ptr General pointer value for command.
+ * @v cmd Command to issue.
+ * @ret rc Non-zero if command not issued.
+ */
+static int ifec_scb_cmd ( struct net_device *netdev, u32 ptr, u8 cmd )
+{
+ struct ifec_private *priv = netdev->priv;
+ unsigned long ioaddr = priv->ioaddr;
+ int rc;
+
+ DBGP ( "ifec_scb_cmd\n" );
+
+ rc = ifec_scb_cmd_wait ( netdev ); /* Wait until ready */
+ if ( !rc ) {
+ outl ( ptr, ioaddr + SCBPointer );
+ outb ( cmd, ioaddr + SCBCmd ); /* Issue command */
+ }
+ return rc;
+}
+
+/*
+ * Wait for command unit to accept a command.
+ *
+ * @v cmd_ioaddr I/O address of command register.
+ * @ret rc Non-zero if command timed out.
+ */
+static int ifec_scb_cmd_wait ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev->priv;
+ unsigned long cmd_ioaddr = priv->ioaddr + SCBCmd;
+ int rc, wait = CU_CMD_TIMEOUT;
+
+ DBGP ( "ifec_scb_cmd_wait\n" );
+
+ for ( ; wait && ( rc = inb ( cmd_ioaddr ) ); wait-- )
+ udelay ( 1 );
+
+ if ( !wait )
+ DBG ( "ifec_scb_cmd_wait timeout!\n" );
+ return rc;
+}
+
+/*
+ * Check status of transmitted packets & perform tx completions.
+ *
+ * @v netdev Network device.
+ */
+static void ifec_tx_process ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev->priv;
+ struct ifec_tcb *tcb = priv->tcb_tail;
+ s16 status;
+
+ DBGP ( "ifec_tx_process\n" );
+
+ /* Check status of transmitted packets */
+ while ( ( status = tcb->status ) && tcb->iob ) {
+ if ( status & TCB_U ) {
+ /* report error to iPXE */
+ DBG ( "ifec_tx_process : tx error!\n " );
+ netdev_tx_complete_err ( netdev, tcb->iob, -EINVAL );
+ } else {
+ /* report successful transmit */
+ netdev_tx_complete ( netdev, tcb->iob );
+ }
+ DBG2 ( "tx completion\n" );
+
+ tcb->iob = NULL;
+ tcb->status = 0;
+
+ priv->tcb_tail = tcb->next; /* Next TCB */
+ tcb = tcb->next;
+ }
+}
+
+/*
+ * Allocates & initialize tx resources.
+ *
+ * @v netdev Network device.
+ * @ret rc Non-zero if error occurred.
+ */
+static int ifec_tx_setup ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev->priv;
+ struct ifec_tcb *tcb;
+ int i;
+
+ DBGP ( "ifec_tx_setup\n" );
+
+ /* allocate tx ring */
+ priv->tcbs = malloc_dma ( TX_RING_BYTES, CB_ALIGN );
+ if ( !priv->tcbs ) {
+ DBG ( "TX-ring allocation failed\n" );
+ return -ENOMEM;
+ }
+
+ tcb = priv->tcb_tail = priv->tcbs;
+ priv->tx_curr = priv->tx_tail = 0;
+ priv->tx_cnt = 0;
+
+ for ( i = 0; i < TCB_COUNT; i++, tcb++ ) {
+ tcb->status = 0;
+ tcb->count = 0x01208000;
+ tcb->iob = NULL;
+ tcb->tbda_addr = virt_to_bus ( &tcb->tbd_addr0 );
+ tcb->link = virt_to_bus ( tcb + 1 );
+ tcb->next = tcb + 1;
+ }
+ /* We point tcb_head at the last TCB, so the first ifec_net_transmit()
+ * will use the first (head->next) TCB to transmit. */
+ priv->tcb_head = --tcb;
+ tcb->link = virt_to_bus ( priv->tcbs );
+ tcb->next = priv->tcbs;
+
+ return 0;
+}
+
+/*
+ * Wake up the Command Unit and issue a Resume/Start.
+ *
+ * @v netdev Network device containing Command Unit
+ *
+ * The time between clearing the S bit and issuing Resume must be as short as
+ * possible to prevent a race condition. As noted in linux eepro100.c :
+ * Note: Watch out for the potential race condition here: imagine
+ * erasing the previous suspend
+ * the chip processes the previous command
+ * the chip processes the final command, and suspends
+ * doing the CU_RESUME
+ * the chip processes the next-yet-valid post-final-command.
+ * So blindly sending a CU_RESUME is only safe if we do it immediately after
+ * erasing the previous CmdSuspend, without the possibility of an intervening
+ * delay.
+ */
+void ifec_tx_wake ( struct net_device *netdev )
+{
+ struct ifec_private *priv = netdev->priv;
+ unsigned long ioaddr = priv->ioaddr;
+ struct ifec_tcb *tcb = priv->tcb_head->next;
+
+ DBGP ( "ifec_tx_wake\n" );
+
+ /* For the special case of the first transmit, we issue a START. The
+ * card won't RESUME after the configure command. */
+ if ( priv->configured ) {
+ priv->configured = 0;
+ ifec_scb_cmd ( netdev, virt_to_bus ( tcb ), CUStart );
+ ifec_scb_cmd_wait ( netdev );
+ return;
+ }
+
+ /* Resume if suspended. */
+ switch ( ( inw ( ioaddr + SCBStatus ) >> 6 ) & 0x3 ) {
+ case 0: /* Idle - We should not reach this state. */
+ DBG2 ( "ifec_tx_wake: tx idle!\n" );
+ ifec_scb_cmd ( netdev, virt_to_bus ( tcb ), CUStart );
+ ifec_scb_cmd_wait ( netdev );
+ return;
+ case 1: /* Suspended */
+ DBG2 ( "s" );
+ break;
+ default: /* Active */
+ DBG2 ( "a" );
+ }
+ ifec_scb_cmd_wait ( netdev );
+ outl ( 0, ioaddr + SCBPointer );
+ priv->tcb_head->command &= ~CmdSuspend;
+ /* Immediately issue Resume command */
+ outb ( CUResume, ioaddr + SCBCmd );
+ ifec_scb_cmd_wait ( netdev );
+}
+
+/*********************************************************************/
+
+static struct pci_device_id ifec_nics[] = {
+PCI_ROM(0x8086, 0x1029, "id1029", "Intel EtherExpressPro100 ID1029", 0),
+PCI_ROM(0x8086, 0x1030, "id1030", "Intel EtherExpressPro100 ID1030", 0),
+PCI_ROM(0x8086, 0x1031, "82801cam", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0),
+PCI_ROM(0x8086, 0x1032, "eepro100-1032", "Intel PRO/100 VE Network Connection", 0),
+PCI_ROM(0x8086, 0x1033, "eepro100-1033", "Intel PRO/100 VM Network Connection", 0),
+PCI_ROM(0x8086, 0x1034, "eepro100-1034", "Intel PRO/100 VM Network Connection", 0),
+PCI_ROM(0x8086, 0x1035, "eepro100-1035", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0),
+PCI_ROM(0x8086, 0x1036, "eepro100-1036", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0),
+PCI_ROM(0x8086, 0x1037, "eepro100-1037", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0),
+PCI_ROM(0x8086, 0x1038, "id1038", "Intel PRO/100 VM Network Connection", 0),
+PCI_ROM(0x8086, 0x1039, "82562et", "Intel PRO100 VE 82562ET", 0),
+PCI_ROM(0x8086, 0x103a, "id103a", "Intel Corporation 82559 InBusiness 10/100", 0),
+PCI_ROM(0x8086, 0x103b, "82562etb", "Intel PRO100 VE 82562ETB", 0),
+PCI_ROM(0x8086, 0x103c, "eepro100-103c", "Intel PRO/100 VM Network Connection", 0),
+PCI_ROM(0x8086, 0x103d, "eepro100-103d", "Intel PRO/100 VE Network Connection", 0),
+PCI_ROM(0x8086, 0x103e, "eepro100-103e", "Intel PRO/100 VM Network Connection", 0),
+PCI_ROM(0x8086, 0x1051, "prove", "Intel PRO/100 VE Network Connection", 0),
+PCI_ROM(0x8086, 0x1059, "82551qm", "Intel PRO/100 M Mobile Connection", 0),
+PCI_ROM(0x8086, 0x1209, "82559er", "Intel EtherExpressPro100 82559ER", 0),
+PCI_ROM(0x8086, 0x1227, "82865", "Intel 82865 EtherExpress PRO/100A", 0),
+PCI_ROM(0x8086, 0x1228, "82556", "Intel 82556 EtherExpress PRO/100 Smart", 0),
+PCI_ROM(0x8086, 0x1229, "eepro100", "Intel EtherExpressPro100", 0),
+PCI_ROM(0x8086, 0x2449, "82562em", "Intel EtherExpressPro100 82562EM", 0),
+PCI_ROM(0x8086, 0x2459, "82562-1", "Intel 82562 based Fast Ethernet Connection", 0),
+PCI_ROM(0x8086, 0x245d, "82562-2", "Intel 82562 based Fast Ethernet Connection", 0),
+PCI_ROM(0x8086, 0x1050, "82562ez", "Intel 82562EZ Network Connection", 0),
+PCI_ROM(0x8086, 0x1051, "eepro100-1051", "Intel 82801EB/ER (ICH5/ICH5R) Chipset Ethernet Controller", 0),
+PCI_ROM(0x8086, 0x1065, "82562-3", "Intel 82562 based Fast Ethernet Connection", 0),
+PCI_ROM(0x8086, 0x5200, "eepro100-5200", "Intel EtherExpress PRO/100 Intelligent Server", 0),
+PCI_ROM(0x8086, 0x5201, "eepro100-5201", "Intel EtherExpress PRO/100 Intelligent Server", 0),
+PCI_ROM(0x8086, 0x1092, "82562-3", "Intel Pro/100 VE Network", 0),
+PCI_ROM(0x8086, 0x27dc, "eepro100-27dc", "Intel 82801G (ICH7) Chipset Ethernet Controller", 0),
+PCI_ROM(0x8086, 0x10fe, "82552", "Intel 82552 10/100 Network Connection", 0),
+};
+
+/* Cards with device ids 0x1030 to 0x103F, 0x2449, 0x2459 or 0x245D might need
+ * a workaround for hardware bug on 10 mbit half duplex (see linux driver eepro100.c)
+ * 2003/03/17 gbaum */
+
+struct pci_driver ifec_driver __pci_driver = {
+ .ids = ifec_nics,
+ .id_count = ( sizeof (ifec_nics) / sizeof (ifec_nics[0]) ),
+ .probe = ifec_pci_probe,
+ .remove = ifec_pci_remove
+};
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/eepro100.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/eepro100.h
new file mode 100644
index 00000000..3f72f59e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/eepro100.h
@@ -0,0 +1,204 @@
+
+#ifndef __EEPRO100_H_
+#define __EEPRO100_H_
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#define CONGENB 0 /* Enable congestion control in the DP83840. */
+#define TX_FIFO 8 /* Tx FIFO threshold in 4 byte units, 0-15 */
+#define RX_FIFO 8 /* Rx FIFO threshold, default 32 bytes. */
+#define TX_DMA_COUNT 0 /* Tx DMA burst length, 0-127, default 0. */
+#define RX_DMA_COUNT 0 /* Rx DMA length, 0 means no preemption. */
+#define CU_CMD_TIMEOUT 1000 /* CU command accept timeout in microseconds */
+#define LINK_CHECK_PERIOD 1000 /* # of poll() calls between link checks */
+
+#define RFD_PACKET_LEN 1518
+#define RFD_IOB_LEN 1536
+#define RFD_HEADER_LEN 16
+#define CB_ALIGN 2 /* Alignment of command blocks */
+
+#define RFD_COUNT 4
+#define TCB_COUNT 4
+#define RX_RING_BYTES ( RFD_COUNT * sizeof ( struct ifec_rfd ) )
+#define TX_RING_BYTES ( TCB_COUNT * sizeof ( struct ifec_tcb ) )
+
+/* some EEPROM addresses */
+#define EEPROM_ADDR_MAC_0 0
+#define EEPROM_ADDR_MDIO_REGISTER 6
+
+/* Control / Status Register byte offsets - SDM Table 11 */
+enum CSROffsets {
+ SCBStatus=0, SCBCmd=2, SCBPointer = 4,
+ CSRPort=8, CSRFlash=12, CSREeprom = 14,
+ CSRCtrlMDI=16, CSREarlyRx=20
+};
+
+/* System Control Block Command Word - SDM Table 12 */
+enum SCBCmdBits {
+ /* SCB Interrupt Masks - SDM Table 14 */
+ SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000,
+ SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400,
+ SCBTriggerIntr=0x0200, SCBMaskAll=0x0100,
+ /* SCB Control Commands - SDM Table 14-16 */
+ CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040,
+ CUShowStats=0x0050, CUCmdBase=0x0060, CUDumpStats=0x0070,
+ RUStart=0x0001, RUResume=0x0002, RUAbort=0x0004,
+ RUAddrLoad=0x0006, RUResumeNoResources=0x0007
+};
+
+enum SCBPortCmds {
+ PortReset=0, PortSelfTest=1, PortPartialReset=2, PortDump=3
+};
+
+/* Action Commands - SDM Table 14,37 */
+enum ActionCommands {
+ CmdNOp = 0, CmdIASetup = 1, CmdConfigure = 2,
+ CmdMulticastList = 3, CmdTx = 4, CmdTDR = 5,
+ CmdDump = 6, CmdDiagnose = 7,
+ /* And some extra flags: */
+ CmdEndOfList = 0x8000,
+ CmdSuspend = 0x4000, CmdIntr = 0x2000, CmdTxFlex = 0x0008
+};
+
+enum TCBBits {
+ TCB_C=0x8000, TCB_OK=0x2000, TCB_U=0x1000
+};
+
+enum RFDBits {
+ /* Status Word Bits */
+ RFDRxCol=0x0001, RFDIAMatch=0x0002, RFDNoMatch=0x0004,
+ RFDReserved3=0x0008, RFDRxErr=0x0010, RFDEthType=0x0020,
+ RFDReserved6=0x0040, RFDShort=0x0080, RFDDMAOverrun=0x0100,
+ RFDNoBufs=0x0200, RFDCRCAlign=0x0400, RFDCRCError=0x0800,
+ RFDReserved12=0x1000, RFD_OK=0x2000, RFDComplete=0x8000,
+ /* Command Word Bits */
+ //RFD_SF=0x0008, RFDSuspend=0x4000, RFDEndOfList=0x8000,
+ /* Other */
+ RFDMaskCount=0x3FFF
+};
+
+enum phy_chips {
+ NonSuchPhy=0, I82553AB, I82553C,
+ I82503, DP83840, S80C240,
+ S80C24, PhyUndefined, DP83840A=10
+};
+
+/* Serial EEPROM section.
+ A "bit" grungy, but we work our way through bit-by-bit :->. */
+/* EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */
+#define EE_CS 0x02 /* EEPROM chip select. */
+#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
+#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
+#define EE_ENB ( 0x4800 | EE_CS )
+
+/* Elements of the dump_statistics block. This block must be lword aligned. */
+struct ifec_stats {
+ u32
+ tx_good_frames, tx_coll16_errs, tx_late_colls,
+ tx_underruns, tx_lost_carrier, tx_deferred,
+ tx_one_colls, tx_multi_colls, tx_total_colls,
+ rx_good_frames, rx_crc_errs, rx_align_errs,
+ rx_resource_errs, rx_overrun_errs, rx_colls_errs,
+ rx_runt_errs, done_marker;
+};
+
+struct ifec_tcb { /* A Transmit Command Block & TBD. Must be */
+ volatile s16 status; /* word (even address) aligned */
+ u16 command;
+ u32 link; /* PHYSICAL next ifec_tcb, doesn't change */
+ u32 tbda_addr; /* TBD Array, points to TBD below */
+ s32 count; /* # of TBD, Tx start thresh., etc. */
+ /* The following constitutes a Transmit Buffer Descriptor (TBD).
+ * TBDs must be aligned on an even address (word-aligned). */
+ u32 tbd_addr0; /* PHYSICAL ptr to Tx data */
+ s32 tbd_size0; /* Length of Tx data */
+ /* Driver-specific data; not part of TCB format. */
+ struct io_buffer *iob; /* Exists from tx() to completion poll() */
+ struct ifec_tcb *next; /* VIRTUAL next ifec_tcb, doesn't change */
+};
+
+struct ifec_rfd { /* A Receive Frame Descriptor. Must be aligned */
+ volatile s16 status; /* on a physical word (even address) */
+ s16 command;
+ u32 link; /* PHYSICAL next ifec_rfd, doesn't change */
+ u32 rx_buf_addr; /* Unused. Flex rx mode is not documented */
+ u16 count; /* and may be impossible */
+ u16 size;
+ char packet[RFD_PACKET_LEN];
+};
+
+struct ifec_ias { /* Individual Address Setup command block. */
+ volatile s16 status; /* Must be word (even address) aligned. */
+ u16 command;
+ u32 link; /* PHYSICAL next command block to process */
+ u8 ia[6];
+};
+
+struct ifec_cfg { /* The configure command format. */
+ volatile s16 status;
+ u16 command;
+ u32 link; /* PHYSICAL next command block to process */
+ u8 byte[22]; /* 22 configuration bytes */
+};
+
+struct ifec_private {
+ unsigned long ioaddr;
+ struct ifec_stats stats;
+ unsigned short mdio_register;
+
+ struct ifec_tcb *tcbs;
+ struct ifec_rfd *rfds[RFD_COUNT];
+ struct ifec_tcb *tcb_head, *tcb_tail;
+ struct io_buffer *tx_iobs[TCB_COUNT];
+ struct io_buffer *rx_iobs[RFD_COUNT];
+ int cur_rx;
+ int tx_curr;
+ int tx_tail;
+ int tx_cnt;
+ /*
+ * The configured flag indicates if a Config command was last issued.
+ * The following attempt to issue a command (in ifec_tx_wake) will
+ * use a START rather than RESUME SCB command. It seems the card won't
+ * RESUME after a configure command.
+ */
+ int configured;
+ struct spi_bit_basher spi;
+ struct spi_device eeprom;
+
+};
+
+/**************************** Function prototypes ****************************/
+
+/* PCI device API prototypes */
+static int ifec_pci_probe ( struct pci_device *pci );
+static void ifec_pci_remove ( struct pci_device *pci );
+
+/* Network device API prototypes */
+static void ifec_net_close ( struct net_device* );
+static void ifec_net_irq ( struct net_device*, int enable );
+static int ifec_net_open ( struct net_device* );
+static void ifec_net_poll ( struct net_device* );
+static int ifec_net_transmit ( struct net_device*, struct io_buffer *iobuf );
+
+/* Local function prototypes */
+static void ifec_init_eeprom ( struct net_device * );
+static int ifec_mdio_read ( struct net_device *, int phy, int location );
+static void ifec_mdio_setup ( struct net_device *, int options );
+static int ifec_mdio_write ( struct net_device *, int phy, int loc, int val);
+static void ifec_reset ( struct net_device * );
+static void ifec_free ( struct net_device * );
+static void ifec_rfd_init ( struct ifec_rfd *rfd, s16 command, u32 link );
+static void ifec_rx_process ( struct net_device * );
+static void ifec_reprime_ru ( struct net_device * );
+static void ifec_check_ru_status ( struct net_device *, unsigned short );
+static int ifec_get_rx_desc ( struct net_device *, int ,int ,int );
+static void ifec_refill_rx_ring ( struct net_device * );
+static int ifec_rx_setup ( struct net_device * );
+static int ifec_scb_cmd ( struct net_device *, u32 ptr, u8 cmd );
+static int ifec_scb_cmd_wait ( struct net_device * );
+static void ifec_tx_process ( struct net_device * );
+static int ifec_tx_setup ( struct net_device * );
+static void ifec_tx_wake ( struct net_device * );
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snp.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snp.h
new file mode 100644
index 00000000..4d6b1014
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snp.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _SNP_H
+#define _SNP_H
+
+/** @file
+ *
+ * SNP driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/device.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/efi/Protocol/SimpleNetwork.h>
+
+/** A network device that consumes the EFI Simple Network Protocol */
+struct snp_device {
+ /** Underlying simple network protocol instance */
+ EFI_SIMPLE_NETWORK_PROTOCOL *snp;
+
+ /** Generic device */
+ struct device dev;
+
+ /** Network device */
+ struct net_device *netdev;
+
+ /** State to put the snp in when removing the device */
+ uint32 removal_state;
+};
+
+#endif /* _SNP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snpnet.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snpnet.c
new file mode 100644
index 00000000..97790815
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snpnet.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2010 VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <string.h>
+#include <ipxe/io.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/Protocol/SimpleNetwork.h>
+#include "snp.h"
+#include "snpnet.h"
+
+/** @file
+ *
+ * SNP network device driver
+ *
+ */
+
+/** SNP net device structure */
+struct snpnet_device {
+ /** The underlying simple network protocol */
+ EFI_SIMPLE_NETWORK_PROTOCOL *snp;
+
+ /** State that the SNP should be in after close */
+ UINT32 close_state;
+};
+
+/**
+ * Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int snpnet_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct snpnet_device *snpnetdev = netdev->priv;
+ EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
+ EFI_STATUS efirc;
+ void *txbuf=NULL;
+ size_t len = iob_len ( iobuf );
+
+ efirc = snp->Transmit ( snp, 0, len, iobuf->data, NULL, NULL, NULL );
+ if (efirc) {
+ return EFIRC_TO_RC ( efirc );
+ }
+ /* since GetStatus is so inconsistent, don't try more than one outstanding transmit at a time */
+ while ( txbuf == NULL ) {
+ efirc = snp->GetStatus ( snp, NULL, &txbuf );
+ if ( efirc ) {
+ DBGC ( snp, "SNP %p could not get status %s\n", snp,
+ efi_strerror ( efirc ) );
+ break;
+ }
+
+ }
+ netdev_tx_complete ( netdev, iobuf );
+ return 0;
+}
+
+/**
+ * Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void snpnet_poll ( struct net_device *netdev ) {
+ struct snpnet_device *snpnetdev = netdev->priv;
+ EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
+ EFI_STATUS efirc;
+ struct io_buffer *iobuf = NULL;
+ UINTN len;
+
+ /* Process received packets */
+ while ( 1 ) {
+ /* The spec is not clear if the max packet size refers to the
+ * payload or the entire packet including headers. The Receive
+ * function needs a buffer large enough to contain the headers,
+ * and potentially a 4-byte CRC and 4-byte VLAN tag (?), so add
+ * some breathing room.
+ */
+ len = snp->Mode->MaxPacketSize + ETH_HLEN + 8;
+ iobuf = alloc_iob ( len );
+ if ( iobuf == NULL ) {
+ netdev_rx_err ( netdev, NULL, -ENOMEM );
+ break;
+ }
+
+ efirc = snp->Receive ( snp, NULL, &len, iobuf->data,
+ NULL, NULL, NULL );
+
+ /* No packets left? */
+ if ( efirc == EFI_NOT_READY ) {
+ free_iob ( iobuf );
+ break;
+ }
+
+ /* Other error? */
+ if ( efirc ) {
+ DBGC ( snp, "SNP %p receive packet error: %s "
+ "(len was %zd, is now %zd)\n",
+ snp, efi_strerror ( efirc ), iob_len(iobuf),
+ (size_t)len );
+ netdev_rx_err ( netdev, iobuf, efirc );
+ break;
+ }
+
+ /* Packet is valid, deliver it */
+ iob_put ( iobuf, len );
+ netdev_rx ( netdev, iob_disown ( iobuf ) );
+ }
+}
+
+/**
+ * Open NIC
+ *
+ * @v netdev Net device
+ * @ret rc Return status code
+ */
+static int snpnet_open ( struct net_device *netdev ) {
+ struct snpnet_device *snpnetdev = netdev->priv;
+ EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
+ EFI_STATUS efirc;
+ UINT32 enableFlags, disableFlags;
+
+ snpnetdev->close_state = snp->Mode->State;
+ if ( snp->Mode->State != EfiSimpleNetworkInitialized ) {
+ efirc = snp->Initialize ( snp, 0, 0 );
+ if ( efirc ) {
+ DBGC ( snp, "SNP %p could not initialize: %s\n",
+ snp, efi_strerror ( efirc ) );
+ return EFIRC_TO_RC ( efirc );
+ }
+ }
+
+ /* Use the default MAC address */
+ efirc = snp->StationAddress ( snp, FALSE,
+ (EFI_MAC_ADDRESS *)netdev->ll_addr );
+ if ( efirc ) {
+ DBGC ( snp, "SNP %p could not reset station address: %s\n",
+ snp, efi_strerror ( efirc ) );
+ }
+
+ /* Set up receive filters to receive unicast and broadcast packets
+ * always. Also, enable either promiscuous multicast (if possible) or
+ * promiscuous operation, in order to catch all multicast packets.
+ */
+ enableFlags = snp->Mode->ReceiveFilterMask &
+ ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST );
+ disableFlags = snp->Mode->ReceiveFilterMask &
+ ( EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
+ EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST );
+ if ( snp->Mode->ReceiveFilterMask &
+ EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST ) {
+ enableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
+ } else if ( snp->Mode->ReceiveFilterMask &
+ EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS ) {
+ enableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
+ }
+ disableFlags &= ~enableFlags;
+ efirc = snp->ReceiveFilters ( snp, enableFlags, disableFlags,
+ FALSE, 0, NULL );
+ if ( efirc ) {
+ DBGC ( snp, "SNP %p could not set receive filters: %s\n",
+ snp, efi_strerror ( efirc ) );
+ }
+
+ DBGC ( snp, "SNP %p opened\n", snp );
+ return 0;
+}
+
+/**
+ * Close NIC
+ *
+ * @v netdev Net device
+ */
+static void snpnet_close ( struct net_device *netdev ) {
+ struct snpnet_device *snpnetdev = netdev->priv;
+ EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
+ EFI_STATUS efirc;
+
+ if ( snpnetdev->close_state != EfiSimpleNetworkInitialized ) {
+ efirc = snp->Shutdown ( snp );
+ if ( efirc ) {
+ DBGC ( snp, "SNP %p could not shut down: %s\n",
+ snp, efi_strerror ( efirc ) );
+ }
+ }
+}
+
+/**
+ * Enable/disable interrupts
+ *
+ * @v netdev Net device
+ * @v enable Interrupts should be enabled
+ */
+static void snpnet_irq ( struct net_device *netdev, int enable ) {
+ struct snpnet_device *snpnetdev = netdev->priv;
+ EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
+
+ /* On EFI, interrupts are never necessary. (This function is only
+ * required for BIOS PXE.) If interrupts were required, they could be
+ * simulated using a fast timer.
+ */
+ DBGC ( snp, "SNP %p cannot %s interrupts\n",
+ snp, ( enable ? "enable" : "disable" ) );
+}
+
+/** SNP network device operations */
+static struct net_device_operations snpnet_operations = {
+ .open = snpnet_open,
+ .close = snpnet_close,
+ .transmit = snpnet_transmit,
+ .poll = snpnet_poll,
+ .irq = snpnet_irq,
+};
+
+/**
+ * Probe SNP device
+ *
+ * @v snpdev SNP device
+ * @ret rc Return status code
+ */
+int snpnet_probe ( struct snp_device *snpdev ) {
+ EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpdev->snp;
+ EFI_STATUS efirc;
+ struct net_device *netdev;
+ struct snpnet_device *snpnetdev;
+ int rc;
+
+ DBGC ( snp, "SNP %p probing...\n", snp );
+
+ /* Allocate net device */
+ netdev = alloc_etherdev ( sizeof ( struct snpnet_device ) );
+ if ( ! netdev )
+ return -ENOMEM;
+ netdev_init ( netdev, &snpnet_operations );
+ netdev->dev = &snpdev->dev;
+ snpdev->netdev = netdev;
+ snpnetdev = netdev->priv;
+ snpnetdev->snp = snp;
+ snpdev->removal_state = snp->Mode->State;
+
+ /* Start the interface */
+ if ( snp->Mode->State == EfiSimpleNetworkStopped ) {
+ efirc = snp->Start ( snp );
+ if ( efirc ) {
+ DBGC ( snp, "SNP %p could not start: %s\n", snp,
+ efi_strerror ( efirc ) );
+ rc = EFIRC_TO_RC ( efirc );
+ goto err_start;
+ }
+ }
+
+ if ( snp->Mode->HwAddressSize > sizeof ( netdev->hw_addr ) ) {
+ DBGC ( snp, "SNP %p hardware address is too large\n", snp );
+ rc = -EINVAL;
+ goto err_hwaddr;
+ }
+ memcpy ( netdev->hw_addr, snp->Mode->PermanentAddress.Addr,
+ snp->Mode->HwAddressSize );
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register;
+
+ /* Mark as link up; we don't handle link state */
+ netdev_link_up ( netdev );
+
+ DBGC ( snp, "SNP %p added\n", snp );
+ return 0;
+
+err_register:
+err_hwaddr:
+ if ( snpdev->removal_state == EfiSimpleNetworkStopped )
+ snp->Stop ( snp );
+
+err_start:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ snpdev->netdev = NULL;
+ return rc;
+}
+
+/**
+ * Remove SNP device
+ *
+ * @v snpdev SNP device
+ */
+void snpnet_remove ( struct snp_device *snpdev ) {
+ EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpdev->snp;
+ EFI_STATUS efirc;
+ struct net_device *netdev = snpdev->netdev;
+
+ if ( snp->Mode->State == EfiSimpleNetworkInitialized &&
+ snpdev->removal_state != EfiSimpleNetworkInitialized ) {
+ DBGC ( snp, "SNP %p shutting down\n", snp );
+ efirc = snp->Shutdown ( snp );
+ if ( efirc ) {
+ DBGC ( snp, "SNP %p could not shut down: %s\n",
+ snp, efi_strerror ( efirc ) );
+ }
+ }
+
+ if ( snp->Mode->State == EfiSimpleNetworkStarted &&
+ snpdev->removal_state == EfiSimpleNetworkStopped ) {
+ DBGC ( snp, "SNP %p stopping\n", snp );
+ efirc = snp->Stop ( snp );
+ if ( efirc ) {
+ DBGC ( snp, "SNP %p could not be stopped\n", snp );
+ }
+ }
+
+ /* Unregister net device */
+ unregister_netdev ( netdev );
+
+ /* Free network device */
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+
+ DBGC ( snp, "SNP %p removed\n", snp );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snpnet.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snpnet.h
new file mode 100644
index 00000000..72b4a7d6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snpnet.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _SNPNET_H
+#define _SNPNET_H
+
+/** @file
+ *
+ * EFI Simple Network Protocol network device driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct snp_device;
+
+extern int snpnet_probe ( struct snp_device *snpdev );
+extern void snpnet_remove ( struct snp_device *snpdev );
+
+#endif /* _SNPNET_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snponly.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snponly.c
new file mode 100644
index 00000000..6fcc54a0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/efi/snponly.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <errno.h>
+#include <ipxe/device.h>
+#include <ipxe/init.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/Protocol/SimpleNetwork.h>
+#include "snp.h"
+#include "snpnet.h"
+
+/** @file
+ *
+ * Chain-loading Simple Network Protocol Bus Driver
+ *
+ * This bus driver allows iPXE to use the EFI Simple Network Protocol provided
+ * by the platform to transmit and receive packets. It attaches to only the
+ * device handle that iPXE was loaded from, that is, it will only use the
+ * Simple Network Protocol on the current loaded image's device handle.
+ *
+ * Eseentially, this driver provides the EFI equivalent of the "undionly"
+ * driver.
+ */
+
+/** The one and only SNP network device */
+static struct snp_device snponly_dev;
+
+/** EFI simple network protocol GUID */
+static EFI_GUID efi_simple_network_protocol_guid
+ = EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
+
+/**
+ * Probe SNP root bus
+ *
+ * @v rootdev SNP bus root device
+ *
+ * Look at the loaded image's device handle and see if the simple network
+ * protocol exists. If so, register a driver for it.
+ */
+static int snpbus_probe ( struct root_device *rootdev ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_STATUS efirc;
+ int rc;
+ void *snp;
+
+ efirc = bs->OpenProtocol ( efi_loaded_image->DeviceHandle,
+ &efi_simple_network_protocol_guid,
+ &snp, efi_image_handle, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+ if ( efirc ) {
+ DBG ( "Could not find Simple Network Protocol!\n" );
+ return -ENODEV;
+ }
+ snponly_dev.snp = snp;
+
+ /* Add to device hierarchy */
+ strncpy ( snponly_dev.dev.name, "EFI SNP",
+ ( sizeof ( snponly_dev.dev.name ) - 1 ) );
+ snponly_dev.dev.parent = &rootdev->dev;
+ list_add ( &snponly_dev.dev.siblings, &rootdev->dev.children);
+ INIT_LIST_HEAD ( &snponly_dev.dev.children );
+
+ /* Create network device */
+ if ( ( rc = snpnet_probe ( &snponly_dev ) ) != 0 )
+ goto err;
+
+ return 0;
+
+err:
+ list_del ( &snponly_dev.dev.siblings );
+ return rc;
+}
+
+/**
+ * Remove SNP root bus
+ *
+ * @v rootdev SNP bus root device
+ */
+static void snpbus_remove ( struct root_device *rootdev __unused ) {
+ snpnet_remove ( &snponly_dev );
+ list_del ( &snponly_dev.dev.siblings );
+}
+
+/** SNP bus root device driver */
+static struct root_driver snp_root_driver = {
+ .probe = snpbus_probe,
+ .remove = snpbus_remove,
+};
+
+/** SNP bus root device */
+struct root_device snp_root_device __root_device = {
+ .dev = { .name = "EFI SNP" },
+ .driver = &snp_root_driver,
+};
+
+/**
+ * Prepare for exit
+ *
+ * @v booting System is shutting down for OS boot
+ */
+static void snponly_shutdown ( int booting ) {
+ /* If we are shutting down to boot an OS, make sure the SNP does not
+ * stay active.
+ */
+ if ( booting )
+ snponly_dev.removal_state = EfiSimpleNetworkStopped;
+}
+
+struct startup_fn startup_snponly __startup_fn ( STARTUP_LATE ) = {
+ .shutdown = snponly_shutdown,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/epic100.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/epic100.c
new file mode 100644
index 00000000..b478fab5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/epic100.c
@@ -0,0 +1,536 @@
+
+/* epic100.c: A SMC 83c170 EPIC/100 fast ethernet driver for Etherboot */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* 05/06/2003 timlegge Fixed relocation and implemented Multicast */
+#define LINUX_OUT_MACROS
+
+#include "etherboot.h"
+#include <ipxe/pci.h>
+#include <ipxe/ethernet.h>
+#include "nic.h"
+#include "epic100.h"
+
+/* Condensed operations for readability */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+#define TX_RING_SIZE 2 /* use at least 2 buffers for TX */
+#define RX_RING_SIZE 2
+
+#define PKT_BUF_SZ 1536 /* Size of each temporary Tx/Rx buffer.*/
+
+/*
+#define DEBUG_RX
+#define DEBUG_TX
+#define DEBUG_EEPROM
+*/
+
+#define EPIC_DEBUG 0 /* debug level */
+
+/* The EPIC100 Rx and Tx buffer descriptors. */
+struct epic_rx_desc {
+ unsigned long status;
+ unsigned long bufaddr;
+ unsigned long buflength;
+ unsigned long next;
+};
+/* description of the tx descriptors control bits commonly used */
+#define TD_STDFLAGS TD_LASTDESC
+
+struct epic_tx_desc {
+ unsigned long status;
+ unsigned long bufaddr;
+ unsigned long buflength;
+ unsigned long next;
+};
+
+#define delay(nanosec) do { int _i = 3; while (--_i > 0) \
+ { __SLOW_DOWN_IO; }} while (0)
+
+static void epic100_open(void);
+static void epic100_init_ring(void);
+static void epic100_disable(struct nic *nic);
+static int epic100_poll(struct nic *nic, int retrieve);
+static void epic100_transmit(struct nic *nic, const char *destaddr,
+ unsigned int type, unsigned int len, const char *data);
+#ifdef DEBUG_EEPROM
+static int read_eeprom(int location);
+#endif
+static int mii_read(int phy_id, int location);
+static void epic100_irq(struct nic *nic, irq_action_t action);
+
+static struct nic_operations epic100_operations;
+
+static int ioaddr;
+
+static int command;
+static int intstat;
+static int intmask;
+static int genctl ;
+static int eectl ;
+static int test ;
+static int mmctl ;
+static int mmdata ;
+static int lan0 ;
+static int mc0 ;
+static int rxcon ;
+static int txcon ;
+static int prcdar ;
+static int ptcdar ;
+static int eththr ;
+
+static unsigned int cur_rx, cur_tx; /* The next free ring entry */
+#ifdef DEBUG_EEPROM
+static unsigned short eeprom[64];
+#endif
+static signed char phys[4]; /* MII device addresses. */
+struct {
+ struct epic_rx_desc rx_ring[RX_RING_SIZE]
+ __attribute__ ((aligned(4)));
+ struct epic_tx_desc tx_ring[TX_RING_SIZE]
+ __attribute__ ((aligned(4)));
+ unsigned char rx_packet[PKT_BUF_SZ * RX_RING_SIZE];
+ unsigned char tx_packet[PKT_BUF_SZ * TX_RING_SIZE];
+} epic100_bufs __shared;
+#define rx_ring epic100_bufs.rx_ring
+#define tx_ring epic100_bufs.tx_ring
+#define rx_packet epic100_bufs.rx_packet
+#define tx_packet epic100_bufs.tx_packet
+
+/***********************************************************************/
+/* Externally visible functions */
+/***********************************************************************/
+
+
+static int
+epic100_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ int i;
+ unsigned short* ap;
+ unsigned int phy, phy_idx;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ /* Ideally we would detect all network cards in slot order. That would
+ be best done a central PCI probe dispatch, which wouldn't work
+ well with the current structure. So instead we detect just the
+ Epic cards in slot order. */
+
+ ioaddr = pci->ioaddr;
+
+ nic->irqno = 0;
+ nic->ioaddr = pci->ioaddr & ~3;
+
+ /* compute all used static epic100 registers address */
+ command = ioaddr + COMMAND; /* Control Register */
+ intstat = ioaddr + INTSTAT; /* Interrupt Status */
+ intmask = ioaddr + INTMASK; /* Interrupt Mask */
+ genctl = ioaddr + GENCTL; /* General Control */
+ eectl = ioaddr + EECTL; /* EEPROM Control */
+ test = ioaddr + TEST; /* Test register (clocks) */
+ mmctl = ioaddr + MMCTL; /* MII Management Interface Control */
+ mmdata = ioaddr + MMDATA; /* MII Management Interface Data */
+ lan0 = ioaddr + LAN0; /* MAC address. (0x40-0x48) */
+ mc0 = ioaddr + MC0; /* Multicast Control */
+ rxcon = ioaddr + RXCON; /* Receive Control */
+ txcon = ioaddr + TXCON; /* Transmit Control */
+ prcdar = ioaddr + PRCDAR; /* PCI Receive Current Descr Address */
+ ptcdar = ioaddr + PTCDAR; /* PCI Transmit Current Descr Address */
+ eththr = ioaddr + ETHTHR; /* Early Transmit Threshold */
+
+ /* Reset the chip & bring it out of low-power mode. */
+ outl(GC_SOFT_RESET, genctl);
+
+ /* Disable ALL interrupts by setting the interrupt mask. */
+ outl(INTR_DISABLE, intmask);
+
+ /*
+ * set the internal clocks:
+ * Application Note 7.15 says:
+ * In order to set the CLOCK TEST bit in the TEST register,
+ * perform the following:
+ *
+ * Write 0x0008 to the test register at least sixteen
+ * consecutive times.
+ *
+ * The CLOCK TEST bit is Write-Only. Writing it several times
+ * consecutively insures a successful write to the bit...
+ */
+
+ for (i = 0; i < 16; i++) {
+ outl(0x00000008, test);
+ }
+
+#ifdef DEBUG_EEPROM
+{
+ unsigned short sum = 0;
+ unsigned short value;
+ for (i = 0; i < 64; i++) {
+ value = read_eeprom(i);
+ eeprom[i] = value;
+ sum += value;
+ }
+}
+
+#if (EPIC_DEBUG > 1)
+ printf("EEPROM contents\n");
+ for (i = 0; i < 64; i++) {
+ printf(" %hhX%s", eeprom[i], i % 16 == 15 ? "\n" : "");
+ }
+#endif
+#endif
+
+ /* This could also be read from the EEPROM. */
+ ap = (unsigned short*)nic->node_addr;
+ for (i = 0; i < 3; i++)
+ *ap++ = inw(lan0 + i*4);
+
+ DBG ( " I/O %4.4x %s ", ioaddr, eth_ntoa ( nic->node_addr ) );
+
+ /* Find the connected MII xcvrs. */
+ for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(phys); phy++) {
+ int mii_status = mii_read(phy, 0);
+
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ phys[phy_idx++] = phy;
+#if (EPIC_DEBUG > 1)
+ printf("MII transceiver found at address %d.\n", phy);
+#endif
+ }
+ }
+ if (phy_idx == 0) {
+#if (EPIC_DEBUG > 1)
+ printf("***WARNING***: No MII transceiver found!\n");
+#endif
+ /* Use the known PHY address of the EPII. */
+ phys[0] = 3;
+ }
+
+ epic100_open();
+ nic->nic_op = &epic100_operations;
+
+ return 1;
+}
+
+static void set_rx_mode(void)
+{
+ unsigned char mc_filter[8];
+ int i;
+ memset(mc_filter, 0xff, sizeof(mc_filter));
+ outl(0x0C, rxcon);
+ for(i = 0; i < 4; i++)
+ outw(((unsigned short *)mc_filter)[i], mc0 + i*4);
+ return;
+}
+
+ static void
+epic100_open(void)
+{
+ int mii_reg5;
+ unsigned long tmp;
+
+ epic100_init_ring();
+
+ /* Pull the chip out of low-power mode, and set for PCI read multiple. */
+ outl(GC_RX_FIFO_THR_64 | GC_MRC_READ_MULT | GC_ONE_COPY, genctl);
+
+ outl(TX_FIFO_THRESH, eththr);
+
+ tmp = TC_EARLY_TX_ENABLE | TX_SLOT_TIME;
+
+ mii_reg5 = mii_read(phys[0], 5);
+ if (mii_reg5 != 0xffff && (mii_reg5 & 0x0100)) {
+ printf(" full-duplex mode");
+ tmp |= TC_LM_FULL_DPX;
+ } else
+ tmp |= TC_LM_NORMAL;
+
+ outl(tmp, txcon);
+
+ /* Give adress of RX and TX ring to the chip */
+ outl(virt_to_le32desc(&rx_ring), prcdar);
+ outl(virt_to_le32desc(&tx_ring), ptcdar);
+
+ /* Start the chip's Rx process: receive unicast and broadcast */
+ set_rx_mode();
+ outl(CR_START_RX | CR_QUEUE_RX, command);
+
+ putchar('\n');
+}
+
+/* Initialize the Rx and Tx rings. */
+ static void
+epic100_init_ring(void)
+{
+ int i;
+
+ cur_rx = cur_tx = 0;
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_ring[i].status = cpu_to_le32(RRING_OWN); /* Owned by Epic chip */
+ rx_ring[i].buflength = cpu_to_le32(PKT_BUF_SZ);
+ rx_ring[i].bufaddr = virt_to_bus(&rx_packet[i * PKT_BUF_SZ]);
+ rx_ring[i].next = virt_to_le32desc(&rx_ring[i + 1]) ;
+ }
+ /* Mark the last entry as wrapping the ring. */
+ rx_ring[i-1].next = virt_to_le32desc(&rx_ring[0]);
+
+ /*
+ *The Tx buffer descriptor is filled in as needed,
+ * but we do need to clear the ownership bit.
+ */
+
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ tx_ring[i].status = 0x0000; /* Owned by CPU */
+ tx_ring[i].buflength = 0x0000 | cpu_to_le32(TD_STDFLAGS << 16);
+ tx_ring[i].bufaddr = virt_to_bus(&tx_packet[i * PKT_BUF_SZ]);
+ tx_ring[i].next = virt_to_le32desc(&tx_ring[i + 1]);
+ }
+ tx_ring[i-1].next = virt_to_le32desc(&tx_ring[0]);
+}
+
+/* function: epic100_transmit
+ * This transmits a packet.
+ *
+ * Arguments: char d[6]: destination ethernet address.
+ * unsigned short t: ethernet protocol type.
+ * unsigned short s: size of the data-part of the packet.
+ * char *p: the data for the packet.
+ * returns: void.
+ */
+ static void
+epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type,
+ unsigned int len, const char *data)
+{
+ unsigned short nstype;
+ unsigned char *txp;
+ int entry;
+ unsigned long ct;
+
+ /* Calculate the next Tx descriptor entry. */
+ entry = cur_tx % TX_RING_SIZE;
+
+ if ((tx_ring[entry].status & TRING_OWN) == TRING_OWN) {
+ printf("eth_transmit: Unable to transmit. status=%4.4lx. Resetting...\n",
+ tx_ring[entry].status);
+
+ epic100_open();
+ return;
+ }
+
+ txp = tx_packet + (entry * PKT_BUF_SZ);
+
+ memcpy(txp, destaddr, ETH_ALEN);
+ memcpy(txp + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ nstype = htons(type);
+ memcpy(txp + 12, (char*)&nstype, 2);
+ memcpy(txp + ETH_HLEN, data, len);
+
+ len += ETH_HLEN;
+ len &= 0x0FFF;
+ while(len < ETH_ZLEN)
+ txp[len++] = '\0';
+ /*
+ * Caution: the write order is important here,
+ * set the base address with the "ownership"
+ * bits last.
+ */
+
+ tx_ring[entry].buflength |= cpu_to_le32(len);
+ tx_ring[entry].status = cpu_to_le32(len << 16) |
+ cpu_to_le32(TRING_OWN); /* Pass ownership to the chip. */
+
+ cur_tx++;
+
+ /* Trigger an immediate transmit demand. */
+ outl(CR_QUEUE_TX, command);
+
+ ct = currticks();
+ /* timeout 10 ms for transmit */
+ while ((le32_to_cpu(tx_ring[entry].status) & (TRING_OWN)) &&
+ ct + 10*1000 < currticks())
+ /* Wait */;
+
+ if ((le32_to_cpu(tx_ring[entry].status) & TRING_OWN) != 0)
+ printf("Oops, transmitter timeout, status=%4.4lX\n",
+ tx_ring[entry].status);
+}
+
+/* function: epic100_poll / eth_poll
+ * This receives a packet from the network.
+ *
+ * Arguments: none
+ *
+ * returns: 1 if a packet was received.
+ * 0 if no pacet was received.
+ * side effects:
+ * returns the packet in the array nic->packet.
+ * returns the length of the packet in nic->packetlen.
+ */
+
+ static int
+epic100_poll(struct nic *nic, int retrieve)
+{
+ int entry;
+ int retcode;
+ int status;
+ entry = cur_rx % RX_RING_SIZE;
+
+ if ((rx_ring[entry].status & cpu_to_le32(RRING_OWN)) == RRING_OWN)
+ return (0);
+
+ if ( ! retrieve ) return 1;
+
+ status = le32_to_cpu(rx_ring[entry].status);
+ /* We own the next entry, it's a new packet. Send it up. */
+
+#if (EPIC_DEBUG > 4)
+ printf("epic_poll: entry %d status %hX\n", entry, status);
+#endif
+
+ cur_rx++;
+ if (status & 0x2000) {
+ printf("epic_poll: Giant packet\n");
+ retcode = 0;
+ } else if (status & 0x0006) {
+ /* Rx Frame errors are counted in hardware. */
+ printf("epic_poll: Frame received with errors\n");
+ retcode = 0;
+ } else {
+ /* Omit the four octet CRC from the length. */
+ nic->packetlen = le32_to_cpu((rx_ring[entry].buflength))- 4;
+ memcpy(nic->packet, &rx_packet[entry * PKT_BUF_SZ], nic->packetlen);
+ retcode = 1;
+ }
+
+ /* Clear all error sources. */
+ outl(status & INTR_CLEARERRS, intstat);
+
+ /* Give the descriptor back to the chip */
+ rx_ring[entry].status = RRING_OWN;
+
+ /* Restart Receiver */
+ outl(CR_START_RX | CR_QUEUE_RX, command);
+
+ return retcode;
+}
+
+
+static void epic100_disable ( struct nic *nic __unused ) {
+ /* Soft reset the chip. */
+ outl(GC_SOFT_RESET, genctl);
+}
+
+static void epic100_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+#ifdef DEBUG_EEPROM
+/* Serial EEPROM section. */
+
+/* EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */
+#define EE_CS 0x02 /* EEPROM chip select. */
+#define EE_DATA_WRITE 0x08 /* EEPROM chip data in. */
+#define EE_WRITE_0 0x01
+#define EE_WRITE_1 0x09
+#define EE_DATA_READ 0x10 /* EEPROM chip data out. */
+#define EE_ENB (0x0001 | EE_CS)
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD (5 << 6)
+#define EE_READ_CMD (6 << 6)
+#define EE_ERASE_CMD (7 << 6)
+
+#define eeprom_delay(n) delay(n)
+
+ static int
+read_eeprom(int location)
+{
+ int i;
+ int retval = 0;
+ int read_cmd = location | EE_READ_CMD;
+
+ outl(EE_ENB & ~EE_CS, eectl);
+ outl(EE_ENB, eectl);
+
+ /* Shift the read command bits out. */
+ for (i = 10; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ outl(EE_ENB | dataval, eectl);
+ eeprom_delay(100);
+ outl(EE_ENB | dataval | EE_SHIFT_CLK, eectl);
+ eeprom_delay(150);
+ outl(EE_ENB | dataval, eectl); /* Finish EEPROM a clock tick. */
+ eeprom_delay(250);
+ }
+ outl(EE_ENB, eectl);
+
+ for (i = 16; i > 0; i--) {
+ outl(EE_ENB | EE_SHIFT_CLK, eectl);
+ eeprom_delay(100);
+ retval = (retval << 1) | ((inl(eectl) & EE_DATA_READ) ? 1 : 0);
+ outl(EE_ENB, eectl);
+ eeprom_delay(100);
+ }
+
+ /* Terminate the EEPROM access. */
+ outl(EE_ENB & ~EE_CS, eectl);
+ return retval;
+}
+#endif
+
+
+#define MII_READOP 1
+#define MII_WRITEOP 2
+
+ static int
+mii_read(int phy_id, int location)
+{
+ int i;
+
+ outl((phy_id << 9) | (location << 4) | MII_READOP, mmctl);
+ /* Typical operation takes < 50 ticks. */
+
+ for (i = 4000; i > 0; i--)
+ if ((inl(mmctl) & MII_READOP) == 0)
+ break;
+ return inw(mmdata);
+}
+
+static struct nic_operations epic100_operations = {
+ .connect = dummy_connect,
+ .poll = epic100_poll,
+ .transmit = epic100_transmit,
+ .irq = epic100_irq,
+
+};
+
+static struct pci_device_id epic100_nics[] = {
+PCI_ROM(0x10b8, 0x0005, "epic100", "SMC EtherPowerII", 0), /* SMC 83c170 EPIC/100 */
+PCI_ROM(0x10b8, 0x0006, "smc-83c175", "SMC EPIC/C 83c175", 0),
+};
+
+PCI_DRIVER ( epic100_driver, epic100_nics, PCI_NO_CLASS );
+
+DRIVER ( "EPIC100", nic_driver, pci_driver, epic100_driver,
+ epic100_probe, epic100_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/epic100.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/epic100.h
new file mode 100644
index 00000000..f290b103
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/epic100.h
@@ -0,0 +1,190 @@
+#ifndef _EPIC100_H_
+# define _EPIC100_H_
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef PCI_VENDOR_SMC
+# define PCI_VENDOR_SMC 0x10B8
+#endif
+
+#ifndef PCI_DEVICE_SMC_EPIC100
+# define PCI_DEVICE_SMC_EPIC100 0x0005
+#endif
+
+#define PCI_DEVICE_ID_NONE 0xFFFF
+
+/* Offsets to registers (using SMC names). */
+enum epic100_registers {
+ COMMAND= 0, /* Control Register */
+ INTSTAT= 4, /* Interrupt Status */
+ INTMASK= 8, /* Interrupt Mask */
+ GENCTL = 0x0C, /* General Control */
+ NVCTL = 0x10, /* Non Volatile Control */
+ EECTL = 0x14, /* EEPROM Control */
+ TEST = 0x1C, /* Test register: marked as reserved (see in source code) */
+ CRCCNT = 0x20, /* CRC Error Counter */
+ ALICNT = 0x24, /* Frame Alignment Error Counter */
+ MPCNT = 0x28, /* Missed Packet Counter */
+ MMCTL = 0x30, /* MII Management Interface Control */
+ MMDATA = 0x34, /* MII Management Interface Data */
+ MIICFG = 0x38, /* MII Configuration */
+ IPG = 0x3C, /* InterPacket Gap */
+ LAN0 = 0x40, /* MAC address. (0x40-0x48) */
+ IDCHK = 0x4C, /* BoardID/ Checksum */
+ MC0 = 0x50, /* Multicast filter table. (0x50-0x5c) */
+ RXCON = 0x60, /* Receive Control */
+ TXCON = 0x70, /* Transmit Control */
+ TXSTAT = 0x74, /* Transmit Status */
+ PRCDAR = 0x84, /* PCI Receive Current Descriptor Address */
+ PRSTAT = 0xA4, /* PCI Receive DMA Status */
+ PRCPTHR= 0xB0, /* PCI Receive Copy Threshold */
+ PTCDAR = 0xC4, /* PCI Transmit Current Descriptor Address */
+ ETHTHR = 0xDC /* Early Transmit Threshold */
+};
+
+/* Command register (CR_) bits */
+#define CR_STOP_RX (0x00000001)
+#define CR_START_RX (0x00000002)
+#define CR_QUEUE_TX (0x00000004)
+#define CR_QUEUE_RX (0x00000008)
+#define CR_NEXTFRAME (0x00000010)
+#define CR_STOP_TX_DMA (0x00000020)
+#define CR_STOP_RX_DMA (0x00000040)
+#define CR_TX_UGO (0x00000080)
+
+/* Interrupt register bits. NI means No Interrupt generated */
+
+#define INTR_RX_THR_STA (0x00400000) /* rx copy threshold status NI */
+#define INTR_RX_BUFF_EMPTY (0x00200000) /* rx buffers empty. NI */
+#define INTR_TX_IN_PROG (0x00100000) /* tx copy in progess. NI */
+#define INTR_RX_IN_PROG (0x00080000) /* rx copy in progress. NI */
+#define INTR_TXIDLE (0x00040000) /* tx idle. NI */
+#define INTR_RXIDLE (0x00020000) /* rx idle. NI */
+#define INTR_INTR_ACTIVE (0x00010000) /* Interrupt active. NI */
+#define INTR_RX_STATUS_OK (0x00008000) /* rx status valid. NI */
+#define INTR_PCI_TGT_ABT (0x00004000) /* PCI Target abort */
+#define INTR_PCI_MASTER_ABT (0x00002000) /* PCI Master abort */
+#define INTR_PCI_PARITY_ERR (0x00001000) /* PCI adress parity error */
+#define INTR_PCI_DATA_ERR (0x00000800) /* PCI data parity error */
+#define INTR_RX_THR_CROSSED (0x00000400) /* rx copy threshold crossed */
+#define INTR_CNTFULL (0x00000200) /* Counter overflow */
+#define INTR_TXUNDERRUN (0x00000100) /* tx underrun. */
+#define INTR_TXEMPTY (0x00000080) /* tx queue empty */
+#define INTR_TX_CH_COMPLETE (0x00000040) /* tx chain complete */
+#define INTR_TXDONE (0x00000020) /* tx complete (w or w/o err) */
+#define INTR_RXERROR (0x00000010) /* rx error (CRC) */
+#define INTR_RXOVERFLOW (0x00000008) /* rx buffer overflow */
+#define INTR_RX_QUEUE_EMPTY (0x00000004) /* rx queue empty. */
+#define INTR_RXHEADER (0x00000002) /* header copy complete */
+#define INTR_RXDONE (0x00000001) /* Receive copy complete */
+
+#define INTR_CLEARINTR (0x00007FFF)
+#define INTR_VALIDBITS (0x007FFFFF)
+#define INTR_DISABLE (0x00000000)
+#define INTR_CLEARERRS (0x00007F18)
+#define INTR_ABNINTR (INTR_CNTFULL | INTR_TXUNDERRUN | INTR_RXOVERFLOW)
+
+/* General Control (GC_) bits */
+
+#define GC_SOFT_RESET (0x00000001)
+#define GC_INTR_ENABLE (0x00000002)
+#define GC_SOFT_INTR (0x00000004)
+#define GC_POWER_DOWN (0x00000008)
+#define GC_ONE_COPY (0x00000010)
+#define GC_BIG_ENDIAN (0x00000020)
+#define GC_RX_PREEMPT_TX (0x00000040)
+#define GC_TX_PREEMPT_RX (0x00000080)
+
+/*
+ * Receive FIFO Threshold values
+ * Control the level at which the PCI burst state machine
+ * begins to empty the receive FIFO. Possible values: 0-3
+ *
+ * 0 => 32, 1 => 64, 2 => 96 3 => 128 bytes.
+ */
+#define GC_RX_FIFO_THR_32 (0x00000000)
+#define GC_RX_FIFO_THR_64 (0x00000100)
+#define GC_RX_FIFO_THR_96 (0x00000200)
+#define GC_RX_FIFO_THR_128 (0x00000300)
+
+/* Memory Read Control (MRC_) values */
+#define GC_MRC_MEM_READ (0x00000000)
+#define GC_MRC_READ_MULT (0x00000400)
+#define GC_MRC_READ_LINE (0x00000800)
+
+#define GC_SOFTBIT0 (0x00001000)
+#define GC_SOFTBIT1 (0x00002000)
+#define GC_RESET_PHY (0x00004000)
+
+/* Definitions of the Receive Control (RC_) register bits */
+
+#define RC_SAVE_ERRORED_PKT (0x00000001)
+#define RC_SAVE_RUNT_FRAMES (0x00000002)
+#define RC_RCV_BROADCAST (0x00000004)
+#define RC_RCV_MULTICAST (0x00000008)
+#define RC_RCV_INVERSE_PKT (0x00000010)
+#define RC_PROMISCUOUS_MODE (0x00000020)
+#define RC_MONITOR_MODE (0x00000040)
+#define RC_EARLY_RCV_ENABLE (0x00000080)
+
+/* description of the rx descriptors control bits */
+#define RD_FRAGLIST (0x0001) /* Desc points to a fragment list */
+#define RD_LLFORM (0x0002) /* Frag list format */
+#define RD_HDR_CPY (0x0004) /* Desc used for header copy */
+
+/* Definition of the Transmit CONTROL (TC) register bits */
+
+#define TC_EARLY_TX_ENABLE (0x00000001)
+
+/* Loopback Mode (LM_) Select valuesbits */
+#define TC_LM_NORMAL (0x00000000)
+#define TC_LM_INTERNAL (0x00000002)
+#define TC_LM_EXTERNAL (0x00000004)
+#define TC_LM_FULL_DPX (0x00000006)
+
+#define TX_SLOT_TIME (0x00000078)
+
+/* Bytes transferred to chip before transmission starts. */
+#define TX_FIFO_THRESH 128 /* Rounded down to 4 byte units. */
+
+/* description of rx descriptors status bits */
+#define RRING_PKT_INTACT (0x0001)
+#define RRING_ALIGN_ERR (0x0002)
+#define RRING_CRC_ERR (0x0004)
+#define RRING_MISSED_PKT (0x0008)
+#define RRING_MULTICAST (0x0010)
+#define RRING_BROADCAST (0x0020)
+#define RRING_RECEIVER_DISABLE (0x0040)
+#define RRING_STATUS_VALID (0x1000)
+#define RRING_FRAGLIST_ERR (0x2000)
+#define RRING_HDR_COPIED (0x4000)
+#define RRING_OWN (0x8000)
+
+/* error summary */
+#define RRING_ERROR (RRING_ALIGN_ERR|RRING_CRC_ERR)
+
+/* description of tx descriptors status bits */
+#define TRING_PKT_INTACT (0x0001) /* pkt transmitted. */
+#define TRING_PKT_NONDEFER (0x0002) /* pkt xmitted w/o deferring */
+#define TRING_COLL (0x0004) /* pkt xmitted w collisions */
+#define TRING_CARR (0x0008) /* carrier sense lost */
+#define TRING_UNDERRUN (0x0010) /* DMA underrun */
+#define TRING_HB_COLL (0x0020) /* Collision detect Heartbeat */
+#define TRING_WIN_COLL (0x0040) /* out of window collision */
+#define TRING_DEFERRED (0x0080) /* Deferring */
+#define TRING_COLL_COUNT (0x0F00) /* collision counter (mask) */
+#define TRING_COLL_EXCESS (0x1000) /* tx aborted: excessive colls */
+#define TRING_OWN (0x8000) /* desc ownership bit */
+
+/* error summary */
+#define TRING_ABORT (TRING_COLL_EXCESS|TRING_WIN_COLL|TRING_UNDERRUN)
+#define TRING_ERROR (TRING_DEFERRED|TRING_WIN_COLL|TRING_UNDERRUN|TRING_CARR/*|TRING_COLL*/ )
+
+/* description of the tx descriptors control bits */
+#define TD_FRAGLIST (0x0001) /* Desc points to a fragment list */
+#define TD_LLFORM (0x0002) /* Frag list format */
+#define TD_IAF (0x0004) /* Generate Interrupt after tx */
+#define TD_NOCRC (0x0008) /* No CRC generated */
+#define TD_LASTDESC (0x0010) /* Last desc for this frame */
+
+#endif /* _EPIC100_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/etherfabric.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/etherfabric.c
new file mode 100644
index 00000000..a0a009cb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/etherfabric.c
@@ -0,0 +1,4224 @@
+/**************************************************************************
+ *
+ * Etherboot driver for Level 5 Etherfabric network cards
+ *
+ * Written by Michael Brown <mbrown@fensystems.co.uk>
+ *
+ * Copyright Fen Systems Ltd. 2005
+ * Copyright Level 5 Networks Inc. 2005
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice.
+ *
+ **************************************************************************
+ */
+
+FILE_LICENCE ( GPL_ANY );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/io.h>
+#include <ipxe/pci.h>
+#include <ipxe/malloc.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/timer.h>
+#include <mii.h>
+#include "etherfabric.h"
+#include "etherfabric_nic.h"
+
+/**************************************************************************
+ *
+ * Constants and macros
+ *
+ **************************************************************************
+ */
+
+#define EFAB_REGDUMP(...)
+#define EFAB_TRACE(...) DBGP(__VA_ARGS__)
+
+// printf() is not allowed within drivers. Use DBG() instead.
+#define EFAB_LOG(...) DBG(__VA_ARGS__)
+#define EFAB_ERR(...) DBG(__VA_ARGS__)
+
+#define FALCON_USE_IO_BAR 0
+
+#define HZ 100
+#define EFAB_BYTE 1
+
+/**************************************************************************
+ *
+ * Hardware data structures and sizing
+ *
+ **************************************************************************
+ */
+extern int __invalid_queue_size;
+#define FQS(_prefix, _x) \
+ ( ( (_x) == 512 ) ? _prefix ## _SIZE_512 : \
+ ( ( (_x) == 1024 ) ? _prefix ## _SIZE_1K : \
+ ( ( (_x) == 2048 ) ? _prefix ## _SIZE_2K : \
+ ( ( (_x) == 4096) ? _prefix ## _SIZE_4K : \
+ __invalid_queue_size ) ) ) )
+
+
+#define EFAB_MAX_FRAME_LEN(mtu) \
+ ( ( ( ( mtu ) + 4/* FCS */ ) + 7 ) & ~7 )
+
+/**************************************************************************
+ *
+ * GMII routines
+ *
+ **************************************************************************
+ */
+
+static void falcon_mdio_write (struct efab_nic *efab, int device,
+ int location, int value );
+static int falcon_mdio_read ( struct efab_nic *efab, int device, int location );
+
+/* GMII registers */
+#define GMII_PSSR 0x11 /* PHY-specific status register */
+
+/* Pseudo extensions to the link partner ability register */
+#define LPA_EF_1000FULL 0x00020000
+#define LPA_EF_1000HALF 0x00010000
+#define LPA_EF_10000FULL 0x00040000
+#define LPA_EF_10000HALF 0x00080000
+
+#define LPA_EF_1000 ( LPA_EF_1000FULL | LPA_EF_1000HALF )
+#define LPA_EF_10000 ( LPA_EF_10000FULL | LPA_EF_10000HALF )
+#define LPA_EF_DUPLEX ( LPA_10FULL | LPA_100FULL | LPA_EF_1000FULL | \
+ LPA_EF_10000FULL )
+
+/* Mask of bits not associated with speed or duplexity. */
+#define LPA_OTHER ~( LPA_10FULL | LPA_10HALF | LPA_100FULL | \
+ LPA_100HALF | LPA_EF_1000FULL | LPA_EF_1000HALF )
+
+/* PHY-specific status register */
+#define PSSR_LSTATUS 0x0400 /* Bit 10 - link status */
+
+/**
+ * Retrieve GMII autonegotiation advertised abilities
+ *
+ */
+static unsigned int
+gmii_autoneg_advertised ( struct efab_nic *efab )
+{
+ unsigned int mii_advertise;
+ unsigned int gmii_advertise;
+
+ /* Extended bits are in bits 8 and 9 of MII_CTRL1000 */
+ mii_advertise = falcon_mdio_read ( efab, 0, MII_ADVERTISE );
+ gmii_advertise = ( ( falcon_mdio_read ( efab, 0, MII_CTRL1000 ) >> 8 )
+ & 0x03 );
+ return ( ( gmii_advertise << 16 ) | mii_advertise );
+}
+
+/**
+ * Retrieve GMII autonegotiation link partner abilities
+ *
+ */
+static unsigned int
+gmii_autoneg_lpa ( struct efab_nic *efab )
+{
+ unsigned int mii_lpa;
+ unsigned int gmii_lpa;
+
+ /* Extended bits are in bits 10 and 11 of MII_STAT1000 */
+ mii_lpa = falcon_mdio_read ( efab, 0, MII_LPA );
+ gmii_lpa = ( falcon_mdio_read ( efab, 0, MII_STAT1000 ) >> 10 ) & 0x03;
+ return ( ( gmii_lpa << 16 ) | mii_lpa );
+}
+
+/**
+ * Calculate GMII autonegotiated link technology
+ *
+ */
+static unsigned int
+gmii_nway_result ( unsigned int negotiated )
+{
+ unsigned int other_bits;
+
+ /* Mask out the speed and duplexity bits */
+ other_bits = negotiated & LPA_OTHER;
+
+ if ( negotiated & LPA_EF_1000FULL )
+ return ( other_bits | LPA_EF_1000FULL );
+ else if ( negotiated & LPA_EF_1000HALF )
+ return ( other_bits | LPA_EF_1000HALF );
+ else if ( negotiated & LPA_100FULL )
+ return ( other_bits | LPA_100FULL );
+ else if ( negotiated & LPA_100BASE4 )
+ return ( other_bits | LPA_100BASE4 );
+ else if ( negotiated & LPA_100HALF )
+ return ( other_bits | LPA_100HALF );
+ else if ( negotiated & LPA_10FULL )
+ return ( other_bits | LPA_10FULL );
+ else return ( other_bits | LPA_10HALF );
+}
+
+/**
+ * Check GMII PHY link status
+ *
+ */
+static int
+gmii_link_ok ( struct efab_nic *efab )
+{
+ int status;
+ int phy_status;
+
+ /* BMSR is latching - it returns "link down" if the link has
+ * been down at any point since the last read. To get a
+ * real-time status, we therefore read the register twice and
+ * use the result of the second read.
+ */
+ (void) falcon_mdio_read ( efab, 0, MII_BMSR );
+ status = falcon_mdio_read ( efab, 0, MII_BMSR );
+
+ /* Read the PHY-specific Status Register. This is
+ * non-latching, so we need do only a single read.
+ */
+ phy_status = falcon_mdio_read ( efab, 0, GMII_PSSR );
+
+ return ( ( status & BMSR_LSTATUS ) && ( phy_status & PSSR_LSTATUS ) );
+}
+
+/**************************************************************************
+ *
+ * MDIO routines
+ *
+ **************************************************************************
+ */
+
+/* Numbering of the MDIO Manageable Devices (MMDs) */
+/* Physical Medium Attachment/ Physical Medium Dependent sublayer */
+#define MDIO_MMD_PMAPMD (1)
+/* WAN Interface Sublayer */
+#define MDIO_MMD_WIS (2)
+/* Physical Coding Sublayer */
+#define MDIO_MMD_PCS (3)
+/* PHY Extender Sublayer */
+#define MDIO_MMD_PHYXS (4)
+/* Extender Sublayer */
+#define MDIO_MMD_DTEXS (5)
+/* Transmission convergence */
+#define MDIO_MMD_TC (6)
+/* Auto negotiation */
+#define MDIO_MMD_AN (7)
+
+/* Generic register locations */
+#define MDIO_MMDREG_CTRL1 (0)
+#define MDIO_MMDREG_STAT1 (1)
+#define MDIO_MMDREG_DEVS0 (5)
+#define MDIO_MMDREG_STAT2 (8)
+
+/* Bits in MMDREG_CTRL1 */
+/* Reset */
+#define MDIO_MMDREG_CTRL1_RESET_LBN (15)
+#define MDIO_MMDREG_CTRL1_RESET_WIDTH (1)
+
+/* Bits in MMDREG_STAT1 */
+#define MDIO_MMDREG_STAT1_FAULT_LBN (7)
+#define MDIO_MMDREG_STAT1_FAULT_WIDTH (1)
+
+/* Link state */
+#define MDIO_MMDREG_STAT1_LINK_LBN (2)
+#define MDIO_MMDREG_STAT1_LINK_WIDTH (1)
+
+/* Bits in MMDREG_DEVS0. */
+#define DEV_PRESENT_BIT(_b) (1 << _b)
+
+#define MDIO_MMDREG_DEVS0_DTEXS DEV_PRESENT_BIT(MDIO_MMD_DTEXS)
+#define MDIO_MMDREG_DEVS0_PHYXS DEV_PRESENT_BIT(MDIO_MMD_PHYXS)
+#define MDIO_MMDREG_DEVS0_PCS DEV_PRESENT_BIT(MDIO_MMD_PCS)
+#define MDIO_MMDREG_DEVS0_WIS DEV_PRESENT_BIT(MDIO_MMD_WIS)
+#define MDIO_MMDREG_DEVS0_PMAPMD DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)
+
+#define MDIO_MMDREG_DEVS0_AN DEV_PRESENT_BIT(MDIO_MMD_AN)
+
+/* Bits in MMDREG_STAT2 */
+#define MDIO_MMDREG_STAT2_PRESENT_VAL (2)
+#define MDIO_MMDREG_STAT2_PRESENT_LBN (14)
+#define MDIO_MMDREG_STAT2_PRESENT_WIDTH (2)
+
+/* PHY XGXS lane state */
+#define MDIO_PHYXS_LANE_STATE (0x18)
+#define MDIO_PHYXS_LANE_ALIGNED_LBN (12)
+#define MDIO_PHYXS_LANE_SYNC0_LBN (0)
+#define MDIO_PHYXS_LANE_SYNC1_LBN (1)
+#define MDIO_PHYXS_LANE_SYNC2_LBN (2)
+#define MDIO_PHYXS_LANE_SYNC3_LBN (3)
+
+/* This ought to be ridiculous overkill. We expect it to fail rarely */
+#define MDIO45_RESET_TRIES 100
+#define MDIO45_RESET_SPINTIME 10
+
+static int
+mdio_clause45_wait_reset_mmds ( struct efab_nic* efab )
+{
+ int tries = MDIO45_RESET_TRIES;
+ int in_reset;
+
+ while(tries) {
+ int mask = efab->phy_op->mmds;
+ int mmd = 0;
+ in_reset = 0;
+ while(mask) {
+ if (mask & 1) {
+ int stat = falcon_mdio_read ( efab, mmd,
+ MDIO_MMDREG_CTRL1 );
+ if (stat < 0) {
+ EFAB_ERR("Failed to read status of MMD %d\n",
+ mmd );
+ in_reset = 1;
+ break;
+ }
+ if (stat & (1 << MDIO_MMDREG_CTRL1_RESET_LBN))
+ in_reset |= (1 << mmd);
+ }
+ mask = mask >> 1;
+ mmd++;
+ }
+ if (!in_reset)
+ break;
+ tries--;
+ mdelay ( MDIO45_RESET_SPINTIME );
+ }
+ if (in_reset != 0) {
+ EFAB_ERR("Not all MMDs came out of reset in time. MMDs "
+ "still in reset: %x\n", in_reset);
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+static int
+mdio_clause45_reset_mmd ( struct efab_nic *efab, int mmd )
+{
+ int tries = MDIO45_RESET_TRIES;
+ int ctrl;
+
+ falcon_mdio_write ( efab, mmd, MDIO_MMDREG_CTRL1,
+ ( 1 << MDIO_MMDREG_CTRL1_RESET_LBN ) );
+
+ /* Wait for the reset bit to clear. */
+ do {
+ mdelay ( MDIO45_RESET_SPINTIME );
+
+ ctrl = falcon_mdio_read ( efab, mmd, MDIO_MMDREG_CTRL1 );
+ if ( ~ctrl & ( 1 << MDIO_MMDREG_CTRL1_RESET_LBN ) )
+ return 0;
+ } while ( --tries );
+
+ EFAB_ERR ( "Failed to reset mmd %d\n", mmd );
+
+ return -ETIMEDOUT;
+}
+
+static int
+mdio_clause45_links_ok(struct efab_nic *efab )
+{
+ int status, good;
+ int ok = 1;
+ int mmd = 0;
+ int mmd_mask = efab->phy_op->mmds;
+
+ while (mmd_mask) {
+ if (mmd_mask & 1) {
+ /* Double reads because link state is latched, and a
+ * read moves the current state into the register */
+ status = falcon_mdio_read ( efab, mmd,
+ MDIO_MMDREG_STAT1 );
+ status = falcon_mdio_read ( efab, mmd,
+ MDIO_MMDREG_STAT1 );
+
+ good = status & (1 << MDIO_MMDREG_STAT1_LINK_LBN);
+ ok = ok && good;
+ }
+ mmd_mask = (mmd_mask >> 1);
+ mmd++;
+ }
+ return ok;
+}
+
+static int
+mdio_clause45_check_mmds ( struct efab_nic *efab )
+{
+ int mmd = 0;
+ int devices = falcon_mdio_read ( efab, MDIO_MMD_PHYXS,
+ MDIO_MMDREG_DEVS0 );
+ int mmd_mask = efab->phy_op->mmds;
+
+ /* Check all the expected MMDs are present */
+ if ( devices < 0 ) {
+ EFAB_ERR ( "Failed to read devices present\n" );
+ return -EIO;
+ }
+ if ( ( devices & mmd_mask ) != mmd_mask ) {
+ EFAB_ERR ( "required MMDs not present: got %x, wanted %x\n",
+ devices, mmd_mask );
+ return -EIO;
+ }
+
+ /* Check all required MMDs are responding and happy. */
+ while ( mmd_mask ) {
+ if ( mmd_mask & 1 ) {
+ efab_dword_t reg;
+ int status;
+ reg.opaque = falcon_mdio_read ( efab, mmd,
+ MDIO_MMDREG_STAT2 );
+ status = EFAB_DWORD_FIELD ( reg,
+ MDIO_MMDREG_STAT2_PRESENT );
+ if ( status != MDIO_MMDREG_STAT2_PRESENT_VAL ) {
+
+
+ return -EIO;
+ }
+ }
+ mmd_mask >>= 1;
+ mmd++;
+ }
+
+ return 0;
+}
+
+/* I/O BAR address register */
+#define FCN_IOM_IND_ADR_REG 0x0
+
+/* I/O BAR data register */
+#define FCN_IOM_IND_DAT_REG 0x4
+
+/* Address region register */
+#define FCN_ADR_REGION_REG_KER 0x00
+#define FCN_ADR_REGION0_LBN 0
+#define FCN_ADR_REGION0_WIDTH 18
+#define FCN_ADR_REGION1_LBN 32
+#define FCN_ADR_REGION1_WIDTH 18
+#define FCN_ADR_REGION2_LBN 64
+#define FCN_ADR_REGION2_WIDTH 18
+#define FCN_ADR_REGION3_LBN 96
+#define FCN_ADR_REGION3_WIDTH 18
+
+/* Interrupt enable register */
+#define FCN_INT_EN_REG_KER 0x0010
+#define FCN_MEM_PERR_INT_EN_KER_LBN 5
+#define FCN_MEM_PERR_INT_EN_KER_WIDTH 1
+#define FCN_KER_INT_CHAR_LBN 4
+#define FCN_KER_INT_CHAR_WIDTH 1
+#define FCN_KER_INT_KER_LBN 3
+#define FCN_KER_INT_KER_WIDTH 1
+#define FCN_ILL_ADR_ERR_INT_EN_KER_LBN 2
+#define FCN_ILL_ADR_ERR_INT_EN_KER_WIDTH 1
+#define FCN_SRM_PERR_INT_EN_KER_LBN 1
+#define FCN_SRM_PERR_INT_EN_KER_WIDTH 1
+#define FCN_DRV_INT_EN_KER_LBN 0
+#define FCN_DRV_INT_EN_KER_WIDTH 1
+
+/* Interrupt status register */
+#define FCN_INT_ADR_REG_KER 0x0030
+#define FCN_INT_ADR_KER_LBN 0
+#define FCN_INT_ADR_KER_WIDTH EFAB_DMA_TYPE_WIDTH ( 64 )
+
+/* Interrupt status register (B0 only) */
+#define INT_ISR0_B0 0x90
+#define INT_ISR1_B0 0xA0
+
+/* Interrupt acknowledge register (A0/A1 only) */
+#define FCN_INT_ACK_KER_REG_A1 0x0050
+#define INT_ACK_DUMMY_DATA_LBN 0
+#define INT_ACK_DUMMY_DATA_WIDTH 32
+
+/* Interrupt acknowledge work-around register (A0/A1 only )*/
+#define WORK_AROUND_BROKEN_PCI_READS_REG_KER_A1 0x0070
+
+/* Hardware initialisation register */
+#define FCN_HW_INIT_REG_KER 0x00c0
+#define FCN_BCSR_TARGET_MASK_LBN 101
+#define FCN_BCSR_TARGET_MASK_WIDTH 4
+
+/* SPI host command register */
+#define FCN_EE_SPI_HCMD_REG 0x0100
+#define FCN_EE_SPI_HCMD_CMD_EN_LBN 31
+#define FCN_EE_SPI_HCMD_CMD_EN_WIDTH 1
+#define FCN_EE_WR_TIMER_ACTIVE_LBN 28
+#define FCN_EE_WR_TIMER_ACTIVE_WIDTH 1
+#define FCN_EE_SPI_HCMD_SF_SEL_LBN 24
+#define FCN_EE_SPI_HCMD_SF_SEL_WIDTH 1
+#define FCN_EE_SPI_EEPROM 0
+#define FCN_EE_SPI_FLASH 1
+#define FCN_EE_SPI_HCMD_DABCNT_LBN 16
+#define FCN_EE_SPI_HCMD_DABCNT_WIDTH 5
+#define FCN_EE_SPI_HCMD_READ_LBN 15
+#define FCN_EE_SPI_HCMD_READ_WIDTH 1
+#define FCN_EE_SPI_READ 1
+#define FCN_EE_SPI_WRITE 0
+#define FCN_EE_SPI_HCMD_DUBCNT_LBN 12
+#define FCN_EE_SPI_HCMD_DUBCNT_WIDTH 2
+#define FCN_EE_SPI_HCMD_ADBCNT_LBN 8
+#define FCN_EE_SPI_HCMD_ADBCNT_WIDTH 2
+#define FCN_EE_SPI_HCMD_ENC_LBN 0
+#define FCN_EE_SPI_HCMD_ENC_WIDTH 8
+
+/* SPI host address register */
+#define FCN_EE_SPI_HADR_REG 0x0110
+#define FCN_EE_SPI_HADR_DUBYTE_LBN 24
+#define FCN_EE_SPI_HADR_DUBYTE_WIDTH 8
+#define FCN_EE_SPI_HADR_ADR_LBN 0
+#define FCN_EE_SPI_HADR_ADR_WIDTH 24
+
+/* SPI host data register */
+#define FCN_EE_SPI_HDATA_REG 0x0120
+#define FCN_EE_SPI_HDATA3_LBN 96
+#define FCN_EE_SPI_HDATA3_WIDTH 32
+#define FCN_EE_SPI_HDATA2_LBN 64
+#define FCN_EE_SPI_HDATA2_WIDTH 32
+#define FCN_EE_SPI_HDATA1_LBN 32
+#define FCN_EE_SPI_HDATA1_WIDTH 32
+#define FCN_EE_SPI_HDATA0_LBN 0
+#define FCN_EE_SPI_HDATA0_WIDTH 32
+
+/* VPD Config 0 Register register */
+#define FCN_EE_VPD_CFG_REG 0x0140
+#define FCN_EE_VPD_EN_LBN 0
+#define FCN_EE_VPD_EN_WIDTH 1
+#define FCN_EE_VPD_EN_AD9_MODE_LBN 1
+#define FCN_EE_VPD_EN_AD9_MODE_WIDTH 1
+#define FCN_EE_EE_CLOCK_DIV_LBN 112
+#define FCN_EE_EE_CLOCK_DIV_WIDTH 7
+#define FCN_EE_SF_CLOCK_DIV_LBN 120
+#define FCN_EE_SF_CLOCK_DIV_WIDTH 7
+
+
+/* NIC status register */
+#define FCN_NIC_STAT_REG 0x0200
+#define FCN_ONCHIP_SRAM_LBN 16
+#define FCN_ONCHIP_SRAM_WIDTH 1
+#define FCN_SF_PRST_LBN 9
+#define FCN_SF_PRST_WIDTH 1
+#define FCN_EE_PRST_LBN 8
+#define FCN_EE_PRST_WIDTH 1
+#define FCN_EE_STRAP_LBN 7
+#define FCN_EE_STRAP_WIDTH 1
+#define FCN_PCI_PCIX_MODE_LBN 4
+#define FCN_PCI_PCIX_MODE_WIDTH 3
+#define FCN_PCI_PCIX_MODE_PCI33_DECODE 0
+#define FCN_PCI_PCIX_MODE_PCI66_DECODE 1
+#define FCN_PCI_PCIX_MODE_PCIX66_DECODE 5
+#define FCN_PCI_PCIX_MODE_PCIX100_DECODE 6
+#define FCN_PCI_PCIX_MODE_PCIX133_DECODE 7
+#define FCN_STRAP_ISCSI_EN_LBN 3
+#define FCN_STRAP_ISCSI_EN_WIDTH 1
+#define FCN_STRAP_PINS_LBN 0
+#define FCN_STRAP_PINS_WIDTH 3
+#define FCN_STRAP_10G_LBN 2
+#define FCN_STRAP_10G_WIDTH 1
+#define FCN_STRAP_DUAL_PORT_LBN 1
+#define FCN_STRAP_DUAL_PORT_WIDTH 1
+#define FCN_STRAP_PCIE_LBN 0
+#define FCN_STRAP_PCIE_WIDTH 1
+
+/* Falcon revisions */
+#define FALCON_REV_A0 0
+#define FALCON_REV_A1 1
+#define FALCON_REV_B0 2
+
+/* GPIO control register */
+#define FCN_GPIO_CTL_REG_KER 0x0210
+#define FCN_GPIO_CTL_REG_KER 0x0210
+
+#define FCN_GPIO3_OEN_LBN 27
+#define FCN_GPIO3_OEN_WIDTH 1
+#define FCN_GPIO2_OEN_LBN 26
+#define FCN_GPIO2_OEN_WIDTH 1
+#define FCN_GPIO1_OEN_LBN 25
+#define FCN_GPIO1_OEN_WIDTH 1
+#define FCN_GPIO0_OEN_LBN 24
+#define FCN_GPIO0_OEN_WIDTH 1
+
+#define FCN_GPIO3_OUT_LBN 19
+#define FCN_GPIO3_OUT_WIDTH 1
+#define FCN_GPIO2_OUT_LBN 18
+#define FCN_GPIO2_OUT_WIDTH 1
+#define FCN_GPIO1_OUT_LBN 17
+#define FCN_GPIO1_OUT_WIDTH 1
+#define FCN_GPIO0_OUT_LBN 16
+#define FCN_GPIO0_OUT_WIDTH 1
+
+#define FCN_GPIO3_IN_LBN 11
+#define FCN_GPIO3_IN_WIDTH 1
+#define FCN_GPIO2_IN_LBN 10
+#define FCN_GPIO2_IN_WIDTH 1
+#define FCN_GPIO1_IN_LBN 9
+#define FCN_GPIO1_IN_WIDTH 1
+#define FCN_GPIO0_IN_LBN 8
+#define FCN_GPIO0_IN_WIDTH 1
+
+#define FCN_FLASH_PRESENT_LBN 7
+#define FCN_FLASH_PRESENT_WIDTH 1
+#define FCN_EEPROM_PRESENT_LBN 6
+#define FCN_EEPROM_PRESENT_WIDTH 1
+#define FCN_BOOTED_USING_NVDEVICE_LBN 3
+#define FCN_BOOTED_USING_NVDEVICE_WIDTH 1
+
+/* Defines for extra non-volatile storage */
+#define FCN_NV_MAGIC_NUMBER 0xFA1C
+
+/* Global control register */
+#define FCN_GLB_CTL_REG_KER 0x0220
+#define FCN_EXT_PHY_RST_CTL_LBN 63
+#define FCN_EXT_PHY_RST_CTL_WIDTH 1
+#define FCN_PCIE_SD_RST_CTL_LBN 61
+#define FCN_PCIE_SD_RST_CTL_WIDTH 1
+#define FCN_PCIE_STCK_RST_CTL_LBN 59
+#define FCN_PCIE_STCK_RST_CTL_WIDTH 1
+#define FCN_PCIE_NSTCK_RST_CTL_LBN 58
+#define FCN_PCIE_NSTCK_RST_CTL_WIDTH 1
+#define FCN_PCIE_CORE_RST_CTL_LBN 57
+#define FCN_PCIE_CORE_RST_CTL_WIDTH 1
+#define FCN_EE_RST_CTL_LBN 49
+#define FCN_EE_RST_CTL_WIDTH 1
+#define FCN_RST_EXT_PHY_LBN 31
+#define FCN_RST_EXT_PHY_WIDTH 1
+#define FCN_EXT_PHY_RST_DUR_LBN 1
+#define FCN_EXT_PHY_RST_DUR_WIDTH 3
+#define FCN_SWRST_LBN 0
+#define FCN_SWRST_WIDTH 1
+#define INCLUDE_IN_RESET 0
+#define EXCLUDE_FROM_RESET 1
+
+/* FPGA build version */
+#define FCN_ALTERA_BUILD_REG_KER 0x0300
+#define FCN_VER_MAJOR_LBN 24
+#define FCN_VER_MAJOR_WIDTH 8
+#define FCN_VER_MINOR_LBN 16
+#define FCN_VER_MINOR_WIDTH 8
+#define FCN_VER_BUILD_LBN 0
+#define FCN_VER_BUILD_WIDTH 16
+#define FCN_VER_ALL_LBN 0
+#define FCN_VER_ALL_WIDTH 32
+
+/* Spare EEPROM bits register (flash 0x390) */
+#define FCN_SPARE_REG_KER 0x310
+#define FCN_MEM_PERR_EN_TX_DATA_LBN 72
+#define FCN_MEM_PERR_EN_TX_DATA_WIDTH 2
+
+/* Timer table for kernel access */
+#define FCN_TIMER_CMD_REG_KER 0x420
+#define FCN_TIMER_MODE_LBN 12
+#define FCN_TIMER_MODE_WIDTH 2
+#define FCN_TIMER_MODE_DIS 0
+#define FCN_TIMER_MODE_INT_HLDOFF 1
+#define FCN_TIMER_VAL_LBN 0
+#define FCN_TIMER_VAL_WIDTH 12
+
+/* Receive configuration register */
+#define FCN_RX_CFG_REG_KER 0x800
+#define FCN_RX_XOFF_EN_LBN 0
+#define FCN_RX_XOFF_EN_WIDTH 1
+
+/* SRAM receive descriptor cache configuration register */
+#define FCN_SRM_RX_DC_CFG_REG_KER 0x610
+#define FCN_SRM_RX_DC_BASE_ADR_LBN 0
+#define FCN_SRM_RX_DC_BASE_ADR_WIDTH 21
+
+/* SRAM transmit descriptor cache configuration register */
+#define FCN_SRM_TX_DC_CFG_REG_KER 0x620
+#define FCN_SRM_TX_DC_BASE_ADR_LBN 0
+#define FCN_SRM_TX_DC_BASE_ADR_WIDTH 21
+
+/* SRAM configuration register */
+#define FCN_SRM_CFG_REG_KER 0x630
+#define FCN_SRAM_OOB_ADR_INTEN_LBN 5
+#define FCN_SRAM_OOB_ADR_INTEN_WIDTH 1
+#define FCN_SRAM_OOB_BUF_INTEN_LBN 4
+#define FCN_SRAM_OOB_BUF_INTEN_WIDTH 1
+#define FCN_SRAM_OOB_BT_INIT_EN_LBN 3
+#define FCN_SRAM_OOB_BT_INIT_EN_WIDTH 1
+#define FCN_SRM_NUM_BANK_LBN 2
+#define FCN_SRM_NUM_BANK_WIDTH 1
+#define FCN_SRM_BANK_SIZE_LBN 0
+#define FCN_SRM_BANK_SIZE_WIDTH 2
+#define FCN_SRM_NUM_BANKS_AND_BANK_SIZE_LBN 0
+#define FCN_SRM_NUM_BANKS_AND_BANK_SIZE_WIDTH 3
+
+#define FCN_RX_CFG_REG_KER 0x800
+#define FCN_RX_INGR_EN_B0_LBN 47
+#define FCN_RX_INGR_EN_B0_WIDTH 1
+#define FCN_RX_USR_BUF_SIZE_B0_LBN 19
+#define FCN_RX_USR_BUF_SIZE_B0_WIDTH 9
+#define FCN_RX_XON_MAC_TH_B0_LBN 10
+#define FCN_RX_XON_MAC_TH_B0_WIDTH 9
+#define FCN_RX_XOFF_MAC_TH_B0_LBN 1
+#define FCN_RX_XOFF_MAC_TH_B0_WIDTH 9
+#define FCN_RX_XOFF_MAC_EN_B0_LBN 0
+#define FCN_RX_XOFF_MAC_EN_B0_WIDTH 1
+#define FCN_RX_USR_BUF_SIZE_A1_LBN 11
+#define FCN_RX_USR_BUF_SIZE_A1_WIDTH 9
+#define FCN_RX_XON_MAC_TH_A1_LBN 6
+#define FCN_RX_XON_MAC_TH_A1_WIDTH 5
+#define FCN_RX_XOFF_MAC_TH_A1_LBN 1
+#define FCN_RX_XOFF_MAC_TH_A1_WIDTH 5
+#define FCN_RX_XOFF_MAC_EN_A1_LBN 0
+#define FCN_RX_XOFF_MAC_EN_A1_WIDTH 1
+
+#define FCN_RX_USR_BUF_SIZE_A1_LBN 11
+#define FCN_RX_USR_BUF_SIZE_A1_WIDTH 9
+#define FCN_RX_XOFF_MAC_EN_A1_LBN 0
+#define FCN_RX_XOFF_MAC_EN_A1_WIDTH 1
+
+/* Receive filter control register */
+#define FCN_RX_FILTER_CTL_REG_KER 0x810
+#define FCN_UDP_FULL_SRCH_LIMIT_LBN 32
+#define FCN_UDP_FULL_SRCH_LIMIT_WIDTH 8
+#define FCN_NUM_KER_LBN 24
+#define FCN_NUM_KER_WIDTH 2
+#define FCN_UDP_WILD_SRCH_LIMIT_LBN 16
+#define FCN_UDP_WILD_SRCH_LIMIT_WIDTH 8
+#define FCN_TCP_WILD_SRCH_LIMIT_LBN 8
+#define FCN_TCP_WILD_SRCH_LIMIT_WIDTH 8
+#define FCN_TCP_FULL_SRCH_LIMIT_LBN 0
+#define FCN_TCP_FULL_SRCH_LIMIT_WIDTH 8
+
+/* RX queue flush register */
+#define FCN_RX_FLUSH_DESCQ_REG_KER 0x0820
+#define FCN_RX_FLUSH_DESCQ_CMD_LBN 24
+#define FCN_RX_FLUSH_DESCQ_CMD_WIDTH 1
+#define FCN_RX_FLUSH_DESCQ_LBN 0
+#define FCN_RX_FLUSH_DESCQ_WIDTH 12
+
+/* Receive descriptor update register */
+#define FCN_RX_DESC_UPD_REG_KER 0x0830
+#define FCN_RX_DESC_WPTR_LBN 96
+#define FCN_RX_DESC_WPTR_WIDTH 12
+#define FCN_RX_DESC_UPD_REG_KER_DWORD ( FCN_RX_DESC_UPD_REG_KER + 12 )
+#define FCN_RX_DESC_WPTR_DWORD_LBN 0
+#define FCN_RX_DESC_WPTR_DWORD_WIDTH 12
+
+/* Receive descriptor cache configuration register */
+#define FCN_RX_DC_CFG_REG_KER 0x840
+#define FCN_RX_DC_SIZE_LBN 0
+#define FCN_RX_DC_SIZE_WIDTH 2
+
+#define FCN_RX_SELF_RST_REG_KER 0x890
+#define FCN_RX_ISCSI_DIS_LBN 17
+#define FCN_RX_ISCSI_DIS_WIDTH 1
+#define FCN_RX_NODESC_WAIT_DIS_LBN 9
+#define FCN_RX_NODESC_WAIT_DIS_WIDTH 1
+#define FCN_RX_RECOVERY_EN_LBN 8
+#define FCN_RX_RECOVERY_EN_WIDTH 1
+
+/* TX queue flush register */
+#define FCN_TX_FLUSH_DESCQ_REG_KER 0x0a00
+#define FCN_TX_FLUSH_DESCQ_CMD_LBN 12
+#define FCN_TX_FLUSH_DESCQ_CMD_WIDTH 1
+#define FCN_TX_FLUSH_DESCQ_LBN 0
+#define FCN_TX_FLUSH_DESCQ_WIDTH 12
+
+/* Transmit configuration register 2 */
+#define FCN_TX_CFG2_REG_KER 0xa80
+#define FCN_TX_DIS_NON_IP_EV_LBN 17
+#define FCN_TX_DIS_NON_IP_EV_WIDTH 1
+
+/* Transmit descriptor update register */
+#define FCN_TX_DESC_UPD_REG_KER 0x0a10
+#define FCN_TX_DESC_WPTR_LBN 96
+#define FCN_TX_DESC_WPTR_WIDTH 12
+#define FCN_TX_DESC_UPD_REG_KER_DWORD ( FCN_TX_DESC_UPD_REG_KER + 12 )
+#define FCN_TX_DESC_WPTR_DWORD_LBN 0
+#define FCN_TX_DESC_WPTR_DWORD_WIDTH 12
+
+/* Transmit descriptor cache configuration register */
+#define FCN_TX_DC_CFG_REG_KER 0xa20
+#define FCN_TX_DC_SIZE_LBN 0
+#define FCN_TX_DC_SIZE_WIDTH 2
+
+/* PHY management transmit data register */
+#define FCN_MD_TXD_REG_KER 0xc00
+#define FCN_MD_TXD_LBN 0
+#define FCN_MD_TXD_WIDTH 16
+
+/* PHY management receive data register */
+#define FCN_MD_RXD_REG_KER 0xc10
+#define FCN_MD_RXD_LBN 0
+#define FCN_MD_RXD_WIDTH 16
+
+/* PHY management configuration & status register */
+#define FCN_MD_CS_REG_KER 0xc20
+#define FCN_MD_GC_LBN 4
+#define FCN_MD_GC_WIDTH 1
+#define FCN_MD_RIC_LBN 2
+#define FCN_MD_RIC_WIDTH 1
+#define FCN_MD_RDC_LBN 1
+#define FCN_MD_RDC_WIDTH 1
+#define FCN_MD_WRC_LBN 0
+#define FCN_MD_WRC_WIDTH 1
+
+/* PHY management PHY address register */
+#define FCN_MD_PHY_ADR_REG_KER 0xc30
+#define FCN_MD_PHY_ADR_LBN 0
+#define FCN_MD_PHY_ADR_WIDTH 16
+
+/* PHY management ID register */
+#define FCN_MD_ID_REG_KER 0xc40
+#define FCN_MD_PRT_ADR_LBN 11
+#define FCN_MD_PRT_ADR_WIDTH 5
+#define FCN_MD_DEV_ADR_LBN 6
+#define FCN_MD_DEV_ADR_WIDTH 5
+
+/* PHY management status & mask register */
+#define FCN_MD_STAT_REG_KER 0xc50
+#define FCN_MD_PINT_LBN 4
+#define FCN_MD_PINT_WIDTH 1
+#define FCN_MD_DONE_LBN 3
+#define FCN_MD_DONE_WIDTH 1
+#define FCN_MD_BSERR_LBN 2
+#define FCN_MD_BSERR_WIDTH 1
+#define FCN_MD_LNFL_LBN 1
+#define FCN_MD_LNFL_WIDTH 1
+#define FCN_MD_BSY_LBN 0
+#define FCN_MD_BSY_WIDTH 1
+
+/* Port 0 and 1 MAC control registers */
+#define FCN_MAC0_CTRL_REG_KER 0xc80
+#define FCN_MAC1_CTRL_REG_KER 0xc90
+#define FCN_MAC_XOFF_VAL_LBN 16
+#define FCN_MAC_XOFF_VAL_WIDTH 16
+#define FCN_MAC_BCAD_ACPT_LBN 4
+#define FCN_MAC_BCAD_ACPT_WIDTH 1
+#define FCN_MAC_UC_PROM_LBN 3
+#define FCN_MAC_UC_PROM_WIDTH 1
+#define FCN_MAC_LINK_STATUS_LBN 2
+#define FCN_MAC_LINK_STATUS_WIDTH 1
+#define FCN_MAC_SPEED_LBN 0
+#define FCN_MAC_SPEED_WIDTH 2
+
+/* 10Gig Xaui XGXS Default Values */
+#define XX_TXDRV_DEQ_DEFAULT 0xe /* deq=.6 */
+#define XX_TXDRV_DTX_DEFAULT 0x5 /* 1.25 */
+#define XX_SD_CTL_DRV_DEFAULT 0 /* 20mA */
+
+/* GMAC registers */
+#define FALCON_GMAC_REGBANK 0xe00
+#define FALCON_GMAC_REGBANK_SIZE 0x200
+#define FALCON_GMAC_REG_SIZE 0x10
+
+/* XGMAC registers */
+#define FALCON_XMAC_REGBANK 0x1200
+#define FALCON_XMAC_REGBANK_SIZE 0x200
+#define FALCON_XMAC_REG_SIZE 0x10
+
+/* XGMAC address register low */
+#define FCN_XM_ADR_LO_REG_MAC 0x00
+#define FCN_XM_ADR_3_LBN 24
+#define FCN_XM_ADR_3_WIDTH 8
+#define FCN_XM_ADR_2_LBN 16
+#define FCN_XM_ADR_2_WIDTH 8
+#define FCN_XM_ADR_1_LBN 8
+#define FCN_XM_ADR_1_WIDTH 8
+#define FCN_XM_ADR_0_LBN 0
+#define FCN_XM_ADR_0_WIDTH 8
+
+/* XGMAC address register high */
+#define FCN_XM_ADR_HI_REG_MAC 0x01
+#define FCN_XM_ADR_5_LBN 8
+#define FCN_XM_ADR_5_WIDTH 8
+#define FCN_XM_ADR_4_LBN 0
+#define FCN_XM_ADR_4_WIDTH 8
+
+/* XGMAC global configuration - port 0*/
+#define FCN_XM_GLB_CFG_REG_MAC 0x02
+#define FCN_XM_RX_STAT_EN_LBN 11
+#define FCN_XM_RX_STAT_EN_WIDTH 1
+#define FCN_XM_TX_STAT_EN_LBN 10
+#define FCN_XM_TX_STAT_EN_WIDTH 1
+#define FCN_XM_RX_JUMBO_MODE_LBN 6
+#define FCN_XM_RX_JUMBO_MODE_WIDTH 1
+#define FCN_XM_CORE_RST_LBN 0
+#define FCN_XM_CORE_RST_WIDTH 1
+
+/* XGMAC transmit configuration - port 0 */
+#define FCN_XM_TX_CFG_REG_MAC 0x03
+#define FCN_XM_IPG_LBN 16
+#define FCN_XM_IPG_WIDTH 4
+#define FCN_XM_FCNTL_LBN 10
+#define FCN_XM_FCNTL_WIDTH 1
+#define FCN_XM_TXCRC_LBN 8
+#define FCN_XM_TXCRC_WIDTH 1
+#define FCN_XM_AUTO_PAD_LBN 5
+#define FCN_XM_AUTO_PAD_WIDTH 1
+#define FCN_XM_TX_PRMBL_LBN 2
+#define FCN_XM_TX_PRMBL_WIDTH 1
+#define FCN_XM_TXEN_LBN 1
+#define FCN_XM_TXEN_WIDTH 1
+
+/* XGMAC receive configuration - port 0 */
+#define FCN_XM_RX_CFG_REG_MAC 0x04
+#define FCN_XM_PASS_CRC_ERR_LBN 25
+#define FCN_XM_PASS_CRC_ERR_WIDTH 1
+#define FCN_XM_AUTO_DEPAD_LBN 8
+#define FCN_XM_AUTO_DEPAD_WIDTH 1
+#define FCN_XM_RXEN_LBN 1
+#define FCN_XM_RXEN_WIDTH 1
+
+/* XGMAC management interrupt mask register */
+#define FCN_XM_MGT_INT_MSK_REG_MAC_B0 0x5
+#define FCN_XM_MSK_PRMBLE_ERR_LBN 2
+#define FCN_XM_MSK_PRMBLE_ERR_WIDTH 1
+#define FCN_XM_MSK_RMTFLT_LBN 1
+#define FCN_XM_MSK_RMTFLT_WIDTH 1
+#define FCN_XM_MSK_LCLFLT_LBN 0
+#define FCN_XM_MSK_LCLFLT_WIDTH 1
+
+/* XGMAC flow control register */
+#define FCN_XM_FC_REG_MAC 0x7
+#define FCN_XM_PAUSE_TIME_LBN 16
+#define FCN_XM_PAUSE_TIME_WIDTH 16
+#define FCN_XM_DIS_FCNTL_LBN 0
+#define FCN_XM_DIS_FCNTL_WIDTH 1
+
+/* XGMAC transmit parameter register */
+#define FCN_XM_TX_PARAM_REG_MAC 0x0d
+#define FCN_XM_TX_JUMBO_MODE_LBN 31
+#define FCN_XM_TX_JUMBO_MODE_WIDTH 1
+#define FCN_XM_MAX_TX_FRM_SIZE_LBN 16
+#define FCN_XM_MAX_TX_FRM_SIZE_WIDTH 14
+#define FCN_XM_ACPT_ALL_MCAST_LBN 11
+#define FCN_XM_ACPT_ALL_MCAST_WIDTH 1
+
+/* XGMAC receive parameter register */
+#define FCN_XM_RX_PARAM_REG_MAC 0x0e
+#define FCN_XM_MAX_RX_FRM_SIZE_LBN 0
+#define FCN_XM_MAX_RX_FRM_SIZE_WIDTH 14
+
+/* XGMAC management interrupt status register */
+#define FCN_XM_MGT_INT_REG_MAC_B0 0x0f
+#define FCN_XM_PRMBLE_ERR 2
+#define FCN_XM_PRMBLE_WIDTH 1
+#define FCN_XM_RMTFLT_LBN 1
+#define FCN_XM_RMTFLT_WIDTH 1
+#define FCN_XM_LCLFLT_LBN 0
+#define FCN_XM_LCLFLT_WIDTH 1
+
+/* XAUI XGXS core status register */
+#define FCN_XX_ALIGN_DONE_LBN 20
+#define FCN_XX_ALIGN_DONE_WIDTH 1
+#define FCN_XX_CORE_STAT_REG_MAC 0x16
+#define FCN_XX_SYNC_STAT_LBN 16
+#define FCN_XX_SYNC_STAT_WIDTH 4
+#define FCN_XX_SYNC_STAT_DECODE_SYNCED 0xf
+#define FCN_XX_COMMA_DET_LBN 12
+#define FCN_XX_COMMA_DET_WIDTH 4
+#define FCN_XX_COMMA_DET_RESET 0xf
+#define FCN_XX_CHARERR_LBN 4
+#define FCN_XX_CHARERR_WIDTH 4
+#define FCN_XX_CHARERR_RESET 0xf
+#define FCN_XX_DISPERR_LBN 0
+#define FCN_XX_DISPERR_WIDTH 4
+#define FCN_XX_DISPERR_RESET 0xf
+
+/* XGXS/XAUI powerdown/reset register */
+#define FCN_XX_PWR_RST_REG_MAC 0x10
+#define FCN_XX_PWRDND_EN_LBN 15
+#define FCN_XX_PWRDND_EN_WIDTH 1
+#define FCN_XX_PWRDNC_EN_LBN 14
+#define FCN_XX_PWRDNC_EN_WIDTH 1
+#define FCN_XX_PWRDNB_EN_LBN 13
+#define FCN_XX_PWRDNB_EN_WIDTH 1
+#define FCN_XX_PWRDNA_EN_LBN 12
+#define FCN_XX_PWRDNA_EN_WIDTH 1
+#define FCN_XX_RSTPLLCD_EN_LBN 9
+#define FCN_XX_RSTPLLCD_EN_WIDTH 1
+#define FCN_XX_RSTPLLAB_EN_LBN 8
+#define FCN_XX_RSTPLLAB_EN_WIDTH 1
+#define FCN_XX_RESETD_EN_LBN 7
+#define FCN_XX_RESETD_EN_WIDTH 1
+#define FCN_XX_RESETC_EN_LBN 6
+#define FCN_XX_RESETC_EN_WIDTH 1
+#define FCN_XX_RESETB_EN_LBN 5
+#define FCN_XX_RESETB_EN_WIDTH 1
+#define FCN_XX_RESETA_EN_LBN 4
+#define FCN_XX_RESETA_EN_WIDTH 1
+#define FCN_XX_RSTXGXSRX_EN_LBN 2
+#define FCN_XX_RSTXGXSRX_EN_WIDTH 1
+#define FCN_XX_RSTXGXSTX_EN_LBN 1
+#define FCN_XX_RSTXGXSTX_EN_WIDTH 1
+#define FCN_XX_RST_XX_EN_LBN 0
+#define FCN_XX_RST_XX_EN_WIDTH 1
+
+
+/* XGXS/XAUI powerdown/reset control register */
+#define FCN_XX_SD_CTL_REG_MAC 0x11
+#define FCN_XX_TERMADJ1_LBN 17
+#define FCN_XX_TERMADJ1_WIDTH 1
+#define FCN_XX_TERMADJ0_LBN 16
+#define FCN_XX_TERMADJ0_WIDTH 1
+#define FCN_XX_HIDRVD_LBN 15
+#define FCN_XX_HIDRVD_WIDTH 1
+#define FCN_XX_LODRVD_LBN 14
+#define FCN_XX_LODRVD_WIDTH 1
+#define FCN_XX_HIDRVC_LBN 13
+#define FCN_XX_HIDRVC_WIDTH 1
+#define FCN_XX_LODRVC_LBN 12
+#define FCN_XX_LODRVC_WIDTH 1
+#define FCN_XX_HIDRVB_LBN 11
+#define FCN_XX_HIDRVB_WIDTH 1
+#define FCN_XX_LODRVB_LBN 10
+#define FCN_XX_LODRVB_WIDTH 1
+#define FCN_XX_HIDRVA_LBN 9
+#define FCN_XX_HIDRVA_WIDTH 1
+#define FCN_XX_LODRVA_LBN 8
+#define FCN_XX_LODRVA_WIDTH 1
+#define FCN_XX_LPBKD_LBN 3
+#define FCN_XX_LPBKD_WIDTH 1
+#define FCN_XX_LPBKC_LBN 2
+#define FCN_XX_LPBKC_WIDTH 1
+#define FCN_XX_LPBKB_LBN 1
+#define FCN_XX_LPBKB_WIDTH 1
+#define FCN_XX_LPBKA_LBN 0
+#define FCN_XX_LPBKA_WIDTH 1
+
+#define FCN_XX_TXDRV_CTL_REG_MAC 0x12
+#define FCN_XX_DEQD_LBN 28
+#define FCN_XX_DEQD_WIDTH 4
+#define FCN_XX_DEQC_LBN 24
+#define FCN_XX_DEQC_WIDTH 4
+#define FCN_XX_DEQB_LBN 20
+#define FCN_XX_DEQB_WIDTH 4
+#define FCN_XX_DEQA_LBN 16
+#define FCN_XX_DEQA_WIDTH 4
+#define FCN_XX_DTXD_LBN 12
+#define FCN_XX_DTXD_WIDTH 4
+#define FCN_XX_DTXC_LBN 8
+#define FCN_XX_DTXC_WIDTH 4
+#define FCN_XX_DTXB_LBN 4
+#define FCN_XX_DTXB_WIDTH 4
+#define FCN_XX_DTXA_LBN 0
+#define FCN_XX_DTXA_WIDTH 4
+
+/* Receive filter table */
+#define FCN_RX_FILTER_TBL0 0xF00000
+
+/* Receive descriptor pointer table */
+#define FCN_RX_DESC_PTR_TBL_KER_A1 0x11800
+#define FCN_RX_DESC_PTR_TBL_KER_B0 0xF40000
+#define FCN_RX_ISCSI_DDIG_EN_LBN 88
+#define FCN_RX_ISCSI_DDIG_EN_WIDTH 1
+#define FCN_RX_ISCSI_HDIG_EN_LBN 87
+#define FCN_RX_ISCSI_HDIG_EN_WIDTH 1
+#define FCN_RX_DESCQ_BUF_BASE_ID_LBN 36
+#define FCN_RX_DESCQ_BUF_BASE_ID_WIDTH 20
+#define FCN_RX_DESCQ_EVQ_ID_LBN 24
+#define FCN_RX_DESCQ_EVQ_ID_WIDTH 12
+#define FCN_RX_DESCQ_OWNER_ID_LBN 10
+#define FCN_RX_DESCQ_OWNER_ID_WIDTH 14
+#define FCN_RX_DESCQ_SIZE_LBN 3
+#define FCN_RX_DESCQ_SIZE_WIDTH 2
+#define FCN_RX_DESCQ_SIZE_4K 3
+#define FCN_RX_DESCQ_SIZE_2K 2
+#define FCN_RX_DESCQ_SIZE_1K 1
+#define FCN_RX_DESCQ_SIZE_512 0
+#define FCN_RX_DESCQ_TYPE_LBN 2
+#define FCN_RX_DESCQ_TYPE_WIDTH 1
+#define FCN_RX_DESCQ_JUMBO_LBN 1
+#define FCN_RX_DESCQ_JUMBO_WIDTH 1
+#define FCN_RX_DESCQ_EN_LBN 0
+#define FCN_RX_DESCQ_EN_WIDTH 1
+
+/* Transmit descriptor pointer table */
+#define FCN_TX_DESC_PTR_TBL_KER_A1 0x11900
+#define FCN_TX_DESC_PTR_TBL_KER_B0 0xF50000
+#define FCN_TX_NON_IP_DROP_DIS_B0_LBN 91
+#define FCN_TX_NON_IP_DROP_DIS_B0_WIDTH 1
+#define FCN_TX_DESCQ_EN_LBN 88
+#define FCN_TX_DESCQ_EN_WIDTH 1
+#define FCN_TX_ISCSI_DDIG_EN_LBN 87
+#define FCN_TX_ISCSI_DDIG_EN_WIDTH 1
+#define FCN_TX_ISCSI_HDIG_EN_LBN 86
+#define FCN_TX_ISCSI_HDIG_EN_WIDTH 1
+#define FCN_TX_DESCQ_BUF_BASE_ID_LBN 36
+#define FCN_TX_DESCQ_BUF_BASE_ID_WIDTH 20
+#define FCN_TX_DESCQ_EVQ_ID_LBN 24
+#define FCN_TX_DESCQ_EVQ_ID_WIDTH 12
+#define FCN_TX_DESCQ_OWNER_ID_LBN 10
+#define FCN_TX_DESCQ_OWNER_ID_WIDTH 14
+#define FCN_TX_DESCQ_SIZE_LBN 3
+#define FCN_TX_DESCQ_SIZE_WIDTH 2
+#define FCN_TX_DESCQ_SIZE_4K 3
+#define FCN_TX_DESCQ_SIZE_2K 2
+#define FCN_TX_DESCQ_SIZE_1K 1
+#define FCN_TX_DESCQ_SIZE_512 0
+#define FCN_TX_DESCQ_TYPE_LBN 1
+#define FCN_TX_DESCQ_TYPE_WIDTH 2
+#define FCN_TX_DESCQ_FLUSH_LBN 0
+#define FCN_TX_DESCQ_FLUSH_WIDTH 1
+
+/* Event queue pointer */
+#define FCN_EVQ_PTR_TBL_KER_A1 0x11a00
+#define FCN_EVQ_PTR_TBL_KER_B0 0xf60000
+#define FCN_EVQ_EN_LBN 23
+#define FCN_EVQ_EN_WIDTH 1
+#define FCN_EVQ_SIZE_LBN 20
+#define FCN_EVQ_SIZE_WIDTH 3
+#define FCN_EVQ_SIZE_32K 6
+#define FCN_EVQ_SIZE_16K 5
+#define FCN_EVQ_SIZE_8K 4
+#define FCN_EVQ_SIZE_4K 3
+#define FCN_EVQ_SIZE_2K 2
+#define FCN_EVQ_SIZE_1K 1
+#define FCN_EVQ_SIZE_512 0
+#define FCN_EVQ_BUF_BASE_ID_LBN 0
+#define FCN_EVQ_BUF_BASE_ID_WIDTH 20
+
+/* RSS indirection table */
+#define FCN_RX_RSS_INDIR_TBL_B0 0xFB0000
+
+/* Event queue read pointer */
+#define FCN_EVQ_RPTR_REG_KER_A1 0x11b00
+#define FCN_EVQ_RPTR_REG_KER_B0 0xfa0000
+#define FCN_EVQ_RPTR_LBN 0
+#define FCN_EVQ_RPTR_WIDTH 14
+#define FCN_EVQ_RPTR_REG_KER_DWORD_A1 ( FCN_EVQ_RPTR_REG_KER_A1 + 0 )
+#define FCN_EVQ_RPTR_REG_KER_DWORD_B0 ( FCN_EVQ_RPTR_REG_KER_B0 + 0 )
+#define FCN_EVQ_RPTR_DWORD_LBN 0
+#define FCN_EVQ_RPTR_DWORD_WIDTH 14
+
+/* Special buffer descriptors */
+#define FCN_BUF_FULL_TBL_KER_A1 0x18000
+#define FCN_BUF_FULL_TBL_KER_B0 0x800000
+#define FCN_IP_DAT_BUF_SIZE_LBN 50
+#define FCN_IP_DAT_BUF_SIZE_WIDTH 1
+#define FCN_IP_DAT_BUF_SIZE_8K 1
+#define FCN_IP_DAT_BUF_SIZE_4K 0
+#define FCN_BUF_ADR_FBUF_LBN 14
+#define FCN_BUF_ADR_FBUF_WIDTH 34
+#define FCN_BUF_OWNER_ID_FBUF_LBN 0
+#define FCN_BUF_OWNER_ID_FBUF_WIDTH 14
+
+/** Offset of a GMAC register within Falcon */
+#define FALCON_GMAC_REG( efab, mac_reg ) \
+ ( FALCON_GMAC_REGBANK + \
+ ( (mac_reg) * FALCON_GMAC_REG_SIZE ) )
+
+/** Offset of an XMAC register within Falcon */
+#define FALCON_XMAC_REG( efab_port, mac_reg ) \
+ ( FALCON_XMAC_REGBANK + \
+ ( (mac_reg) * FALCON_XMAC_REG_SIZE ) )
+
+#define FCN_MAC_DATA_LBN 0
+#define FCN_MAC_DATA_WIDTH 32
+
+/* Transmit descriptor */
+#define FCN_TX_KER_PORT_LBN 63
+#define FCN_TX_KER_PORT_WIDTH 1
+#define FCN_TX_KER_BYTE_CNT_LBN 48
+#define FCN_TX_KER_BYTE_CNT_WIDTH 14
+#define FCN_TX_KER_BUF_ADR_LBN 0
+#define FCN_TX_KER_BUF_ADR_WIDTH EFAB_DMA_TYPE_WIDTH ( 46 )
+
+
+/* Receive descriptor */
+#define FCN_RX_KER_BUF_SIZE_LBN 48
+#define FCN_RX_KER_BUF_SIZE_WIDTH 14
+#define FCN_RX_KER_BUF_ADR_LBN 0
+#define FCN_RX_KER_BUF_ADR_WIDTH EFAB_DMA_TYPE_WIDTH ( 46 )
+
+/* Event queue entries */
+#define FCN_EV_CODE_LBN 60
+#define FCN_EV_CODE_WIDTH 4
+#define FCN_RX_IP_EV_DECODE 0
+#define FCN_TX_IP_EV_DECODE 2
+#define FCN_DRIVER_EV_DECODE 5
+
+/* Receive events */
+#define FCN_RX_EV_PKT_OK_LBN 56
+#define FCN_RX_EV_PKT_OK_WIDTH 1
+#define FCN_RX_PORT_LBN 30
+#define FCN_RX_PORT_WIDTH 1
+#define FCN_RX_EV_BYTE_CNT_LBN 16
+#define FCN_RX_EV_BYTE_CNT_WIDTH 14
+#define FCN_RX_EV_DESC_PTR_LBN 0
+#define FCN_RX_EV_DESC_PTR_WIDTH 12
+
+/* Transmit events */
+#define FCN_TX_EV_DESC_PTR_LBN 0
+#define FCN_TX_EV_DESC_PTR_WIDTH 12
+
+/*******************************************************************************
+ *
+ *
+ * Low-level hardware access
+ *
+ *
+ *******************************************************************************/
+
+#define FCN_REVISION_REG(efab, reg) \
+ ( ( efab->pci_revision == FALCON_REV_B0 ) ? reg ## _B0 : reg ## _A1 )
+
+#define EFAB_SET_OWORD_FIELD_VER(efab, reg, field, val) \
+ if ( efab->pci_revision == FALCON_REV_B0 ) \
+ EFAB_SET_OWORD_FIELD ( reg, field ## _B0, val ); \
+ else \
+ EFAB_SET_OWORD_FIELD ( reg, field ## _A1, val );
+
+#if FALCON_USE_IO_BAR
+
+/* Write dword via the I/O BAR */
+static inline void _falcon_writel ( struct efab_nic *efab, uint32_t value,
+ unsigned int reg ) {
+ outl ( reg, efab->iobase + FCN_IOM_IND_ADR_REG );
+ outl ( value, efab->iobase + FCN_IOM_IND_DAT_REG );
+}
+
+/* Read dword via the I/O BAR */
+static inline uint32_t _falcon_readl ( struct efab_nic *efab,
+ unsigned int reg ) {
+ outl ( reg, efab->iobase + FCN_IOM_IND_ADR_REG );
+ return inl ( efab->iobase + FCN_IOM_IND_DAT_REG );
+}
+
+#else /* FALCON_USE_IO_BAR */
+
+#define _falcon_writel( efab, value, reg ) \
+ writel ( (value), (efab)->membase + (reg) )
+#define _falcon_readl( efab, reg ) readl ( (efab)->membase + (reg) )
+
+#endif /* FALCON_USE_IO_BAR */
+
+/**
+ * Write to a Falcon register
+ *
+ */
+static inline void
+falcon_write ( struct efab_nic *efab, efab_oword_t *value, unsigned int reg )
+{
+
+ EFAB_REGDUMP ( "Writing register %x with " EFAB_OWORD_FMT "\n",
+ reg, EFAB_OWORD_VAL ( *value ) );
+
+ _falcon_writel ( efab, value->u32[0], reg + 0 );
+ _falcon_writel ( efab, value->u32[1], reg + 4 );
+ _falcon_writel ( efab, value->u32[2], reg + 8 );
+ wmb();
+ _falcon_writel ( efab, value->u32[3], reg + 12 );
+ wmb();
+}
+
+/**
+ * Write to Falcon SRAM
+ *
+ */
+static inline void
+falcon_write_sram ( struct efab_nic *efab, efab_qword_t *value,
+ unsigned int index )
+{
+ unsigned int reg = ( FCN_REVISION_REG ( efab, FCN_BUF_FULL_TBL_KER ) +
+ ( index * sizeof ( *value ) ) );
+
+ EFAB_REGDUMP ( "Writing SRAM register %x with " EFAB_QWORD_FMT "\n",
+ reg, EFAB_QWORD_VAL ( *value ) );
+
+ _falcon_writel ( efab, value->u32[0], reg + 0 );
+ _falcon_writel ( efab, value->u32[1], reg + 4 );
+ wmb();
+}
+
+/**
+ * Write dword to Falcon register that allows partial writes
+ *
+ */
+static inline void
+falcon_writel ( struct efab_nic *efab, efab_dword_t *value, unsigned int reg )
+{
+ EFAB_REGDUMP ( "Writing partial register %x with " EFAB_DWORD_FMT "\n",
+ reg, EFAB_DWORD_VAL ( *value ) );
+ _falcon_writel ( efab, value->u32[0], reg );
+}
+
+/**
+ * Read from a Falcon register
+ *
+ */
+static inline void
+falcon_read ( struct efab_nic *efab, efab_oword_t *value, unsigned int reg )
+{
+ value->u32[0] = _falcon_readl ( efab, reg + 0 );
+ wmb();
+ value->u32[1] = _falcon_readl ( efab, reg + 4 );
+ value->u32[2] = _falcon_readl ( efab, reg + 8 );
+ value->u32[3] = _falcon_readl ( efab, reg + 12 );
+
+ EFAB_REGDUMP ( "Read from register %x, got " EFAB_OWORD_FMT "\n",
+ reg, EFAB_OWORD_VAL ( *value ) );
+}
+
+/**
+ * Read from Falcon SRAM
+ *
+ */
+static inline void
+falcon_read_sram ( struct efab_nic *efab, efab_qword_t *value,
+ unsigned int index )
+{
+ unsigned int reg = ( FCN_REVISION_REG ( efab, FCN_BUF_FULL_TBL_KER ) +
+ ( index * sizeof ( *value ) ) );
+
+ value->u32[0] = _falcon_readl ( efab, reg + 0 );
+ value->u32[1] = _falcon_readl ( efab, reg + 4 );
+ EFAB_REGDUMP ( "Read from SRAM register %x, got " EFAB_QWORD_FMT "\n",
+ reg, EFAB_QWORD_VAL ( *value ) );
+}
+
+/**
+ * Read dword from a portion of a Falcon register
+ *
+ */
+static inline void
+falcon_readl ( struct efab_nic *efab, efab_dword_t *value, unsigned int reg )
+{
+ value->u32[0] = _falcon_readl ( efab, reg );
+ EFAB_REGDUMP ( "Read from register %x, got " EFAB_DWORD_FMT "\n",
+ reg, EFAB_DWORD_VAL ( *value ) );
+}
+
+#define FCN_DUMP_REG( efab, _reg ) do { \
+ efab_oword_t reg; \
+ falcon_read ( efab, &reg, _reg ); \
+ EFAB_LOG ( #_reg " = " EFAB_OWORD_FMT "\n", \
+ EFAB_OWORD_VAL ( reg ) ); \
+ } while ( 0 );
+
+#define FCN_DUMP_MAC_REG( efab, _mac_reg ) do { \
+ efab_dword_t reg; \
+ efab->mac_op->mac_readl ( efab, &reg, _mac_reg ); \
+ EFAB_LOG ( #_mac_reg " = " EFAB_DWORD_FMT "\n", \
+ EFAB_DWORD_VAL ( reg ) ); \
+ } while ( 0 );
+
+/**
+ * See if an event is present
+ *
+ * @v event Falcon event structure
+ * @ret True An event is pending
+ * @ret False No event is pending
+ *
+ * We check both the high and low dword of the event for all ones. We
+ * wrote all ones when we cleared the event, and no valid event can
+ * have all ones in either its high or low dwords. This approach is
+ * robust against reordering.
+ *
+ * Note that using a single 64-bit comparison is incorrect; even
+ * though the CPU read will be atomic, the DMA write may not be.
+ */
+static inline int
+falcon_event_present ( falcon_event_t* event )
+{
+ return ( ! ( EFAB_DWORD_IS_ALL_ONES ( event->dword[0] ) |
+ EFAB_DWORD_IS_ALL_ONES ( event->dword[1] ) ) );
+}
+
+static void
+falcon_eventq_read_ack ( struct efab_nic *efab, struct efab_ev_queue *ev_queue )
+{
+ efab_dword_t reg;
+
+ EFAB_POPULATE_DWORD_1 ( reg, FCN_EVQ_RPTR_DWORD, ev_queue->read_ptr );
+ falcon_writel ( efab, &reg,
+ FCN_REVISION_REG ( efab, FCN_EVQ_RPTR_REG_KER_DWORD ) );
+}
+
+#if 0
+/**
+ * Dump register contents (for debugging)
+ *
+ * Marked as static inline so that it will not be compiled in if not
+ * used.
+ */
+static inline void
+falcon_dump_regs ( struct efab_nic *efab )
+{
+ FCN_DUMP_REG ( efab, FCN_INT_EN_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_INT_ADR_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_GLB_CTL_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_TIMER_CMD_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_SRM_RX_DC_CFG_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_SRM_TX_DC_CFG_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_RX_FILTER_CTL_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_RX_DC_CFG_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_TX_DC_CFG_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_MAC0_CTRL_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_MAC1_CTRL_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_REVISION_REG ( efab, FCN_RX_DESC_PTR_TBL_KER ) );
+ FCN_DUMP_REG ( efab, FCN_REVISION_REG ( efab, FCN_TX_DESC_PTR_TBL_KER ) );
+ FCN_DUMP_REG ( efab, FCN_REVISION_REG ( efab, FCN_EVQ_PTR_TBL_KER ) );
+ FCN_DUMP_MAC_REG ( efab, GM_CFG1_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GM_CFG2_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GM_MAX_FLEN_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GM_MII_MGMT_CFG_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GM_ADR1_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GM_ADR2_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GMF_CFG0_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GMF_CFG1_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GMF_CFG2_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GMF_CFG3_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GMF_CFG4_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GMF_CFG5_REG_MAC );
+}
+#endif
+
+static void
+falcon_interrupts ( struct efab_nic *efab, int enabled, int force )
+{
+ efab_oword_t int_en_reg_ker;
+
+ EFAB_POPULATE_OWORD_2 ( int_en_reg_ker,
+ FCN_KER_INT_KER, force,
+ FCN_DRV_INT_EN_KER, enabled );
+ falcon_write ( efab, &int_en_reg_ker, FCN_INT_EN_REG_KER );
+}
+
+/*******************************************************************************
+ *
+ *
+ * SPI access
+ *
+ *
+ *******************************************************************************/
+
+
+/** Maximum length for a single SPI transaction */
+#define FALCON_SPI_MAX_LEN 16
+
+static int
+falcon_spi_wait ( struct efab_nic *efab )
+{
+ efab_oword_t reg;
+ int count;
+
+ count = 0;
+ do {
+ udelay ( 100 );
+ falcon_read ( efab, &reg, FCN_EE_SPI_HCMD_REG );
+ if ( EFAB_OWORD_FIELD ( reg, FCN_EE_SPI_HCMD_CMD_EN ) == 0 )
+ return 0;
+ } while ( ++count < 1000 );
+
+ EFAB_ERR ( "Timed out waiting for SPI\n" );
+ return -ETIMEDOUT;
+}
+
+static int
+falcon_spi_rw ( struct spi_bus* bus, struct spi_device *device,
+ unsigned int command, int address,
+ const void* data_out, void *data_in, size_t len )
+{
+ struct efab_nic *efab = container_of ( bus, struct efab_nic, spi_bus );
+ int address_len, rc, device_id, read_cmd;
+ efab_oword_t reg;
+
+ /* falcon_init_spi_device() should have reduced the block size
+ * down so this constraint holds */
+ assert ( len <= FALCON_SPI_MAX_LEN );
+
+ /* Is this the FLASH or EEPROM device? */
+ if ( device == &efab->spi_flash )
+ device_id = FCN_EE_SPI_FLASH;
+ else if ( device == &efab->spi_eeprom )
+ device_id = FCN_EE_SPI_EEPROM;
+ else {
+ EFAB_ERR ( "Unknown device %p\n", device );
+ return -EINVAL;
+ }
+
+ EFAB_TRACE ( "Executing spi command %d on device %d at %d for %zd bytes\n",
+ command, device_id, address, len );
+
+ /* The bus must be idle */
+ rc = falcon_spi_wait ( efab );
+ if ( rc )
+ goto fail1;
+
+ /* Copy data out */
+ if ( data_out ) {
+ memcpy ( &reg, data_out, len );
+ falcon_write ( efab, &reg, FCN_EE_SPI_HDATA_REG );
+ }
+
+ /* Program address register */
+ if ( address >= 0 ) {
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_EE_SPI_HADR_ADR, address );
+ falcon_write ( efab, &reg, FCN_EE_SPI_HADR_REG );
+ }
+
+ /* Issue command */
+ address_len = ( address >= 0 ) ? device->address_len / 8 : 0;
+ read_cmd = ( data_in ? FCN_EE_SPI_READ : FCN_EE_SPI_WRITE );
+ EFAB_POPULATE_OWORD_7 ( reg,
+ FCN_EE_SPI_HCMD_CMD_EN, 1,
+ FCN_EE_SPI_HCMD_SF_SEL, device_id,
+ FCN_EE_SPI_HCMD_DABCNT, len,
+ FCN_EE_SPI_HCMD_READ, read_cmd,
+ FCN_EE_SPI_HCMD_DUBCNT, 0,
+ FCN_EE_SPI_HCMD_ADBCNT, address_len,
+ FCN_EE_SPI_HCMD_ENC, command );
+ falcon_write ( efab, &reg, FCN_EE_SPI_HCMD_REG );
+
+ /* Wait for the command to complete */
+ rc = falcon_spi_wait ( efab );
+ if ( rc )
+ goto fail2;
+
+ /* Copy data in */
+ if ( data_in ) {
+ falcon_read ( efab, &reg, FCN_EE_SPI_HDATA_REG );
+ memcpy ( data_in, &reg, len );
+ }
+
+ return 0;
+
+fail2:
+fail1:
+ EFAB_ERR ( "Failed SPI command %d to device %d address 0x%x len 0x%zx\n",
+ command, device_id, address, len );
+
+ return rc;
+}
+
+/*******************************************************************************
+ *
+ *
+ * Falcon bit-bashed I2C interface
+ *
+ *
+ *******************************************************************************/
+
+static void
+falcon_i2c_bit_write ( struct bit_basher *basher, unsigned int bit_id,
+ unsigned long data )
+{
+ struct efab_nic *efab = container_of ( basher, struct efab_nic,
+ i2c_bb.basher );
+ efab_oword_t reg;
+
+ falcon_read ( efab, &reg, FCN_GPIO_CTL_REG_KER );
+ switch ( bit_id ) {
+ case I2C_BIT_SCL:
+ EFAB_SET_OWORD_FIELD ( reg, FCN_GPIO0_OEN, ( data ? 0 : 1 ) );
+ break;
+ case I2C_BIT_SDA:
+ EFAB_SET_OWORD_FIELD ( reg, FCN_GPIO3_OEN, ( data ? 0 : 1 ) );
+ break;
+ default:
+ EFAB_ERR ( "%s bit=%d\n", __func__, bit_id );
+ break;
+ }
+
+ falcon_write ( efab, &reg, FCN_GPIO_CTL_REG_KER );
+}
+
+static int
+falcon_i2c_bit_read ( struct bit_basher *basher, unsigned int bit_id )
+{
+ struct efab_nic *efab = container_of ( basher, struct efab_nic,
+ i2c_bb.basher );
+ efab_oword_t reg;
+
+ falcon_read ( efab, &reg, FCN_GPIO_CTL_REG_KER );
+ switch ( bit_id ) {
+ case I2C_BIT_SCL:
+ return EFAB_OWORD_FIELD ( reg, FCN_GPIO0_IN );
+ break;
+ case I2C_BIT_SDA:
+ return EFAB_OWORD_FIELD ( reg, FCN_GPIO3_IN );
+ break;
+ default:
+ EFAB_ERR ( "%s bit=%d\n", __func__, bit_id );
+ break;
+ }
+
+ return -1;
+}
+
+static struct bit_basher_operations falcon_i2c_bit_ops = {
+ .read = falcon_i2c_bit_read,
+ .write = falcon_i2c_bit_write,
+};
+
+
+/*******************************************************************************
+ *
+ *
+ * MDIO access
+ *
+ *
+ *******************************************************************************/
+
+static int
+falcon_gmii_wait ( struct efab_nic *efab )
+{
+ efab_dword_t md_stat;
+ int count;
+
+ /* wait upto 10ms */
+ for (count = 0; count < 1000; count++) {
+ falcon_readl ( efab, &md_stat, FCN_MD_STAT_REG_KER );
+ if ( EFAB_DWORD_FIELD ( md_stat, FCN_MD_BSY ) == 0 ) {
+ if ( EFAB_DWORD_FIELD ( md_stat, FCN_MD_LNFL ) != 0 ||
+ EFAB_DWORD_FIELD ( md_stat, FCN_MD_BSERR ) != 0 ) {
+ EFAB_ERR ( "Error from GMII access "
+ EFAB_DWORD_FMT"\n",
+ EFAB_DWORD_VAL ( md_stat ));
+ return -EIO;
+ }
+ return 0;
+ }
+ udelay(10);
+ }
+
+ EFAB_ERR ( "Timed out waiting for GMII\n" );
+ return -ETIMEDOUT;
+}
+
+static void
+falcon_mdio_write ( struct efab_nic *efab, int device,
+ int location, int value )
+{
+ efab_oword_t reg;
+
+ EFAB_TRACE ( "Writing GMII %d register %02x with %04x\n",
+ device, location, value );
+
+ /* Check MII not currently being accessed */
+ if ( falcon_gmii_wait ( efab ) )
+ return;
+
+ /* Write the address/ID register */
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_MD_PHY_ADR, location );
+ falcon_write ( efab, &reg, FCN_MD_PHY_ADR_REG_KER );
+
+ if ( efab->phy_10g ) {
+ /* clause45 */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_PRT_ADR, efab->phy_addr,
+ FCN_MD_DEV_ADR, device );
+ }
+ else {
+ /* clause22 */
+ assert ( device == 0 );
+
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_PRT_ADR, efab->phy_addr,
+ FCN_MD_DEV_ADR, location );
+ }
+ falcon_write ( efab, &reg, FCN_MD_ID_REG_KER );
+
+
+ /* Write data */
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_MD_TXD, value );
+ falcon_write ( efab, &reg, FCN_MD_TXD_REG_KER );
+
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_WRC, 1,
+ FCN_MD_GC, ( efab->phy_10g ? 0 : 1 ) );
+ falcon_write ( efab, &reg, FCN_MD_CS_REG_KER );
+
+ /* Wait for data to be written */
+ if ( falcon_gmii_wait ( efab ) ) {
+ /* Abort the write operation */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_WRC, 0,
+ FCN_MD_GC, 1);
+ falcon_write ( efab, &reg, FCN_MD_CS_REG_KER );
+ udelay(10);
+ }
+}
+
+static int
+falcon_mdio_read ( struct efab_nic *efab, int device, int location )
+{
+ efab_oword_t reg;
+ int value;
+
+ /* Check MII not currently being accessed */
+ if ( falcon_gmii_wait ( efab ) )
+ return -1;
+
+ if ( efab->phy_10g ) {
+ /* clause45 */
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_MD_PHY_ADR, location );
+ falcon_write ( efab, &reg, FCN_MD_PHY_ADR_REG_KER );
+
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_PRT_ADR, efab->phy_addr,
+ FCN_MD_DEV_ADR, device );
+ falcon_write ( efab, &reg, FCN_MD_ID_REG_KER);
+
+ /* request data to be read */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_RDC, 1,
+ FCN_MD_GC, 0 );
+ }
+ else {
+ /* clause22 */
+ assert ( device == 0 );
+
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_PRT_ADR, efab->phy_addr,
+ FCN_MD_DEV_ADR, location );
+ falcon_write ( efab, &reg, FCN_MD_ID_REG_KER );
+
+ /* Request data to be read */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_RIC, 1,
+ FCN_MD_GC, 1 );
+ }
+
+ falcon_write ( efab, &reg, FCN_MD_CS_REG_KER );
+
+ /* Wait for data to become available */
+ if ( falcon_gmii_wait ( efab ) ) {
+ /* Abort the read operation */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_RIC, 0,
+ FCN_MD_GC, 1 );
+ falcon_write ( efab, &reg, FCN_MD_CS_REG_KER );
+ udelay ( 10 );
+ value = -1;
+ }
+ else {
+ /* Read the data */
+ falcon_read ( efab, &reg, FCN_MD_RXD_REG_KER );
+ value = EFAB_OWORD_FIELD ( reg, FCN_MD_RXD );
+ }
+
+ EFAB_TRACE ( "Read from GMII %d register %02x, got %04x\n",
+ device, location, value );
+
+ return value;
+}
+
+/*******************************************************************************
+ *
+ *
+ * MAC wrapper
+ *
+ *
+ *******************************************************************************/
+
+static void
+falcon_reconfigure_mac_wrapper ( struct efab_nic *efab )
+{
+ efab_oword_t reg;
+ int link_speed;
+
+ if ( efab->link_options & LPA_EF_10000 ) {
+ link_speed = 0x3;
+ } else if ( efab->link_options & LPA_EF_1000 ) {
+ link_speed = 0x2;
+ } else if ( efab->link_options & LPA_100 ) {
+ link_speed = 0x1;
+ } else {
+ link_speed = 0x0;
+ }
+ EFAB_POPULATE_OWORD_5 ( reg,
+ FCN_MAC_XOFF_VAL, 0xffff /* datasheet */,
+ FCN_MAC_BCAD_ACPT, 1,
+ FCN_MAC_UC_PROM, 0,
+ FCN_MAC_LINK_STATUS, 1,
+ FCN_MAC_SPEED, link_speed );
+
+ falcon_write ( efab, &reg, FCN_MAC0_CTRL_REG_KER );
+}
+
+/*******************************************************************************
+ *
+ *
+ * GMAC handling
+ *
+ *
+ *******************************************************************************/
+
+/* GMAC configuration register 1 */
+#define GM_CFG1_REG_MAC 0x00
+#define GM_SW_RST_LBN 31
+#define GM_SW_RST_WIDTH 1
+#define GM_RX_FC_EN_LBN 5
+#define GM_RX_FC_EN_WIDTH 1
+#define GM_TX_FC_EN_LBN 4
+#define GM_TX_FC_EN_WIDTH 1
+#define GM_RX_EN_LBN 2
+#define GM_RX_EN_WIDTH 1
+#define GM_TX_EN_LBN 0
+#define GM_TX_EN_WIDTH 1
+
+/* GMAC configuration register 2 */
+#define GM_CFG2_REG_MAC 0x01
+#define GM_PAMBL_LEN_LBN 12
+#define GM_PAMBL_LEN_WIDTH 4
+#define GM_IF_MODE_LBN 8
+#define GM_IF_MODE_WIDTH 2
+#define GM_PAD_CRC_EN_LBN 2
+#define GM_PAD_CRC_EN_WIDTH 1
+#define GM_FD_LBN 0
+#define GM_FD_WIDTH 1
+
+/* GMAC maximum frame length register */
+#define GM_MAX_FLEN_REG_MAC 0x04
+#define GM_MAX_FLEN_LBN 0
+#define GM_MAX_FLEN_WIDTH 16
+
+/* GMAC MII management configuration register */
+#define GM_MII_MGMT_CFG_REG_MAC 0x08
+#define GM_MGMT_CLK_SEL_LBN 0
+#define GM_MGMT_CLK_SEL_WIDTH 3
+
+/* GMAC MII management command register */
+#define GM_MII_MGMT_CMD_REG_MAC 0x09
+#define GM_MGMT_SCAN_CYC_LBN 1
+#define GM_MGMT_SCAN_CYC_WIDTH 1
+#define GM_MGMT_RD_CYC_LBN 0
+#define GM_MGMT_RD_CYC_WIDTH 1
+
+/* GMAC MII management address register */
+#define GM_MII_MGMT_ADR_REG_MAC 0x0a
+#define GM_MGMT_PHY_ADDR_LBN 8
+#define GM_MGMT_PHY_ADDR_WIDTH 5
+#define GM_MGMT_REG_ADDR_LBN 0
+#define GM_MGMT_REG_ADDR_WIDTH 5
+
+/* GMAC MII management control register */
+#define GM_MII_MGMT_CTL_REG_MAC 0x0b
+#define GM_MGMT_CTL_LBN 0
+#define GM_MGMT_CTL_WIDTH 16
+
+/* GMAC MII management status register */
+#define GM_MII_MGMT_STAT_REG_MAC 0x0c
+#define GM_MGMT_STAT_LBN 0
+#define GM_MGMT_STAT_WIDTH 16
+
+/* GMAC MII management indicators register */
+#define GM_MII_MGMT_IND_REG_MAC 0x0d
+#define GM_MGMT_BUSY_LBN 0
+#define GM_MGMT_BUSY_WIDTH 1
+
+/* GMAC station address register 1 */
+#define GM_ADR1_REG_MAC 0x10
+#define GM_HWADDR_5_LBN 24
+#define GM_HWADDR_5_WIDTH 8
+#define GM_HWADDR_4_LBN 16
+#define GM_HWADDR_4_WIDTH 8
+#define GM_HWADDR_3_LBN 8
+#define GM_HWADDR_3_WIDTH 8
+#define GM_HWADDR_2_LBN 0
+#define GM_HWADDR_2_WIDTH 8
+
+/* GMAC station address register 2 */
+#define GM_ADR2_REG_MAC 0x11
+#define GM_HWADDR_1_LBN 24
+#define GM_HWADDR_1_WIDTH 8
+#define GM_HWADDR_0_LBN 16
+#define GM_HWADDR_0_WIDTH 8
+
+/* GMAC FIFO configuration register 0 */
+#define GMF_CFG0_REG_MAC 0x12
+#define GMF_FTFENREQ_LBN 12
+#define GMF_FTFENREQ_WIDTH 1
+#define GMF_STFENREQ_LBN 11
+#define GMF_STFENREQ_WIDTH 1
+#define GMF_FRFENREQ_LBN 10
+#define GMF_FRFENREQ_WIDTH 1
+#define GMF_SRFENREQ_LBN 9
+#define GMF_SRFENREQ_WIDTH 1
+#define GMF_WTMENREQ_LBN 8
+#define GMF_WTMENREQ_WIDTH 1
+
+/* GMAC FIFO configuration register 1 */
+#define GMF_CFG1_REG_MAC 0x13
+#define GMF_CFGFRTH_LBN 16
+#define GMF_CFGFRTH_WIDTH 5
+#define GMF_CFGXOFFRTX_LBN 0
+#define GMF_CFGXOFFRTX_WIDTH 16
+
+/* GMAC FIFO configuration register 2 */
+#define GMF_CFG2_REG_MAC 0x14
+#define GMF_CFGHWM_LBN 16
+#define GMF_CFGHWM_WIDTH 6
+#define GMF_CFGLWM_LBN 0
+#define GMF_CFGLWM_WIDTH 6
+
+/* GMAC FIFO configuration register 3 */
+#define GMF_CFG3_REG_MAC 0x15
+#define GMF_CFGHWMFT_LBN 16
+#define GMF_CFGHWMFT_WIDTH 6
+#define GMF_CFGFTTH_LBN 0
+#define GMF_CFGFTTH_WIDTH 6
+
+/* GMAC FIFO configuration register 4 */
+#define GMF_CFG4_REG_MAC 0x16
+#define GMF_HSTFLTRFRM_PAUSE_LBN 12
+#define GMF_HSTFLTRFRM_PAUSE_WIDTH 12
+
+/* GMAC FIFO configuration register 5 */
+#define GMF_CFG5_REG_MAC 0x17
+#define GMF_CFGHDPLX_LBN 22
+#define GMF_CFGHDPLX_WIDTH 1
+#define GMF_CFGBYTMODE_LBN 19
+#define GMF_CFGBYTMODE_WIDTH 1
+#define GMF_HSTDRPLT64_LBN 18
+#define GMF_HSTDRPLT64_WIDTH 1
+#define GMF_HSTFLTRFRMDC_PAUSE_LBN 12
+#define GMF_HSTFLTRFRMDC_PAUSE_WIDTH 1
+
+static void
+falcon_gmac_writel ( struct efab_nic *efab, efab_dword_t *value,
+ unsigned int mac_reg )
+{
+ efab_oword_t temp;
+
+ EFAB_POPULATE_OWORD_1 ( temp, FCN_MAC_DATA,
+ EFAB_DWORD_FIELD ( *value, FCN_MAC_DATA ) );
+ falcon_write ( efab, &temp, FALCON_GMAC_REG ( efab, mac_reg ) );
+}
+
+static void
+falcon_gmac_readl ( struct efab_nic *efab, efab_dword_t *value,
+ unsigned int mac_reg )
+{
+ efab_oword_t temp;
+
+ falcon_read ( efab, &temp, FALCON_GMAC_REG ( efab, mac_reg ) );
+ EFAB_POPULATE_DWORD_1 ( *value, FCN_MAC_DATA,
+ EFAB_OWORD_FIELD ( temp, FCN_MAC_DATA ) );
+}
+
+static void
+mentormac_reset ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+
+ /* Take into reset */
+ EFAB_POPULATE_DWORD_1 ( reg, GM_SW_RST, 1 );
+ falcon_gmac_writel ( efab, &reg, GM_CFG1_REG_MAC );
+ udelay ( 1000 );
+
+ /* Take out of reset */
+ EFAB_POPULATE_DWORD_1 ( reg, GM_SW_RST, 0 );
+ falcon_gmac_writel ( efab, &reg, GM_CFG1_REG_MAC );
+ udelay ( 1000 );
+
+ /* Configure GMII interface so PHY is accessible. Note that
+ * GMII interface is connected only to port 0, and that on
+ * Falcon this is a no-op.
+ */
+ EFAB_POPULATE_DWORD_1 ( reg, GM_MGMT_CLK_SEL, 0x4 );
+ falcon_gmac_writel ( efab, &reg, GM_MII_MGMT_CFG_REG_MAC );
+ udelay ( 10 );
+}
+
+static void
+mentormac_init ( struct efab_nic *efab )
+{
+ int pause, if_mode, full_duplex, bytemode, half_duplex;
+ efab_dword_t reg;
+
+ /* Configuration register 1 */
+ pause = ( efab->link_options & LPA_PAUSE_CAP ) ? 1 : 0;
+ if ( ! ( efab->link_options & LPA_EF_DUPLEX ) ) {
+ /* Half-duplex operation requires TX flow control */
+ pause = 1;
+ }
+ EFAB_POPULATE_DWORD_4 ( reg,
+ GM_TX_EN, 1,
+ GM_TX_FC_EN, pause,
+ GM_RX_EN, 1,
+ GM_RX_FC_EN, 1 );
+ falcon_gmac_writel ( efab, &reg, GM_CFG1_REG_MAC );
+ udelay ( 10 );
+
+ /* Configuration register 2 */
+ if_mode = ( efab->link_options & LPA_EF_1000 ) ? 2 : 1;
+ full_duplex = ( efab->link_options & LPA_EF_DUPLEX ) ? 1 : 0;
+ EFAB_POPULATE_DWORD_4 ( reg,
+ GM_IF_MODE, if_mode,
+ GM_PAD_CRC_EN, 1,
+ GM_FD, full_duplex,
+ GM_PAMBL_LEN, 0x7 /* ? */ );
+ falcon_gmac_writel ( efab, &reg, GM_CFG2_REG_MAC );
+ udelay ( 10 );
+
+ /* Max frame len register */
+ EFAB_POPULATE_DWORD_1 ( reg, GM_MAX_FLEN,
+ EFAB_MAX_FRAME_LEN ( ETH_FRAME_LEN ) );
+ falcon_gmac_writel ( efab, &reg, GM_MAX_FLEN_REG_MAC );
+ udelay ( 10 );
+
+ /* FIFO configuration register 0 */
+ EFAB_POPULATE_DWORD_5 ( reg,
+ GMF_FTFENREQ, 1,
+ GMF_STFENREQ, 1,
+ GMF_FRFENREQ, 1,
+ GMF_SRFENREQ, 1,
+ GMF_WTMENREQ, 1 );
+ falcon_gmac_writel ( efab, &reg, GMF_CFG0_REG_MAC );
+ udelay ( 10 );
+
+ /* FIFO configuration register 1 */
+ EFAB_POPULATE_DWORD_2 ( reg,
+ GMF_CFGFRTH, 0x12,
+ GMF_CFGXOFFRTX, 0xffff );
+ falcon_gmac_writel ( efab, &reg, GMF_CFG1_REG_MAC );
+ udelay ( 10 );
+
+ /* FIFO configuration register 2 */
+ EFAB_POPULATE_DWORD_2 ( reg,
+ GMF_CFGHWM, 0x3f,
+ GMF_CFGLWM, 0xa );
+ falcon_gmac_writel ( efab, &reg, GMF_CFG2_REG_MAC );
+ udelay ( 10 );
+
+ /* FIFO configuration register 3 */
+ EFAB_POPULATE_DWORD_2 ( reg,
+ GMF_CFGHWMFT, 0x1c,
+ GMF_CFGFTTH, 0x08 );
+ falcon_gmac_writel ( efab, &reg, GMF_CFG3_REG_MAC );
+ udelay ( 10 );
+
+ /* FIFO configuration register 4 */
+ EFAB_POPULATE_DWORD_1 ( reg, GMF_HSTFLTRFRM_PAUSE, 1 );
+ falcon_gmac_writel ( efab, &reg, GMF_CFG4_REG_MAC );
+ udelay ( 10 );
+
+ /* FIFO configuration register 5 */
+ bytemode = ( efab->link_options & LPA_EF_1000 ) ? 1 : 0;
+ half_duplex = ( efab->link_options & LPA_EF_DUPLEX ) ? 0 : 1;
+ falcon_gmac_readl ( efab, &reg, GMF_CFG5_REG_MAC );
+ EFAB_SET_DWORD_FIELD ( reg, GMF_CFGBYTMODE, bytemode );
+ EFAB_SET_DWORD_FIELD ( reg, GMF_CFGHDPLX, half_duplex );
+ EFAB_SET_DWORD_FIELD ( reg, GMF_HSTDRPLT64, half_duplex );
+ EFAB_SET_DWORD_FIELD ( reg, GMF_HSTFLTRFRMDC_PAUSE, 0 );
+ falcon_gmac_writel ( efab, &reg, GMF_CFG5_REG_MAC );
+ udelay ( 10 );
+
+ /* MAC address */
+ EFAB_POPULATE_DWORD_4 ( reg,
+ GM_HWADDR_5, efab->mac_addr[5],
+ GM_HWADDR_4, efab->mac_addr[4],
+ GM_HWADDR_3, efab->mac_addr[3],
+ GM_HWADDR_2, efab->mac_addr[2] );
+ falcon_gmac_writel ( efab, &reg, GM_ADR1_REG_MAC );
+ udelay ( 10 );
+ EFAB_POPULATE_DWORD_2 ( reg,
+ GM_HWADDR_1, efab->mac_addr[1],
+ GM_HWADDR_0, efab->mac_addr[0] );
+ falcon_gmac_writel ( efab, &reg, GM_ADR2_REG_MAC );
+ udelay ( 10 );
+}
+
+static int
+falcon_init_gmac ( struct efab_nic *efab )
+{
+ /* Reset the MAC */
+ mentormac_reset ( efab );
+
+ /* Initialise PHY */
+ efab->phy_op->init ( efab );
+
+ /* check the link is up */
+ if ( !efab->link_up )
+ return -EAGAIN;
+
+ /* Initialise MAC */
+ mentormac_init ( efab );
+
+ /* reconfigure the MAC wrapper */
+ falcon_reconfigure_mac_wrapper ( efab );
+
+ return 0;
+}
+
+static struct efab_mac_operations falcon_gmac_operations = {
+ .init = falcon_init_gmac,
+};
+
+
+/*******************************************************************************
+ *
+ *
+ * XMAC handling
+ *
+ *
+ *******************************************************************************/
+
+/**
+ * Write dword to a Falcon XMAC register
+ *
+ */
+static void
+falcon_xmac_writel ( struct efab_nic *efab, efab_dword_t *value,
+ unsigned int mac_reg )
+{
+ efab_oword_t temp;
+
+ EFAB_POPULATE_OWORD_1 ( temp, FCN_MAC_DATA,
+ EFAB_DWORD_FIELD ( *value, FCN_MAC_DATA ) );
+ falcon_write ( efab, &temp,
+ FALCON_XMAC_REG ( efab, mac_reg ) );
+}
+
+/**
+ * Read dword from a Falcon XMAC register
+ *
+ */
+static void
+falcon_xmac_readl ( struct efab_nic *efab, efab_dword_t *value,
+ unsigned int mac_reg )
+{
+ efab_oword_t temp;
+
+ falcon_read ( efab, &temp,
+ FALCON_XMAC_REG ( efab, mac_reg ) );
+ EFAB_POPULATE_DWORD_1 ( *value, FCN_MAC_DATA,
+ EFAB_OWORD_FIELD ( temp, FCN_MAC_DATA ) );
+}
+
+/**
+ * Configure Falcon XAUI output
+ */
+static void
+falcon_setup_xaui ( struct efab_nic *efab )
+{
+ efab_dword_t sdctl, txdrv;
+
+ falcon_xmac_readl ( efab, &sdctl, FCN_XX_SD_CTL_REG_MAC );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_HIDRVD, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_LODRVD, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_HIDRVC, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_LODRVC, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_HIDRVB, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_LODRVB, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_HIDRVA, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_LODRVA, XX_SD_CTL_DRV_DEFAULT );
+ falcon_xmac_writel ( efab, &sdctl, FCN_XX_SD_CTL_REG_MAC );
+
+ EFAB_POPULATE_DWORD_8 ( txdrv,
+ FCN_XX_DEQD, XX_TXDRV_DEQ_DEFAULT,
+ FCN_XX_DEQC, XX_TXDRV_DEQ_DEFAULT,
+ FCN_XX_DEQB, XX_TXDRV_DEQ_DEFAULT,
+ FCN_XX_DEQA, XX_TXDRV_DEQ_DEFAULT,
+ FCN_XX_DTXD, XX_TXDRV_DTX_DEFAULT,
+ FCN_XX_DTXC, XX_TXDRV_DTX_DEFAULT,
+ FCN_XX_DTXB, XX_TXDRV_DTX_DEFAULT,
+ FCN_XX_DTXA, XX_TXDRV_DTX_DEFAULT);
+ falcon_xmac_writel ( efab, &txdrv, FCN_XX_TXDRV_CTL_REG_MAC);
+}
+
+static int
+falcon_xgmii_status ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+
+ if ( efab->pci_revision < FALCON_REV_B0 )
+ return 1;
+ /* The ISR latches, so clear it and re-read */
+ falcon_xmac_readl ( efab, &reg, FCN_XM_MGT_INT_REG_MAC_B0 );
+ falcon_xmac_readl ( efab, &reg, FCN_XM_MGT_INT_REG_MAC_B0 );
+
+ if ( EFAB_DWORD_FIELD ( reg, FCN_XM_LCLFLT ) ||
+ EFAB_DWORD_FIELD ( reg, FCN_XM_RMTFLT ) ) {
+ EFAB_TRACE ( "MGT_INT: "EFAB_DWORD_FMT"\n",
+ EFAB_DWORD_VAL ( reg ) );
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+falcon_mask_status_intr ( struct efab_nic *efab, int enable )
+{
+ efab_dword_t reg;
+
+ if ( efab->pci_revision < FALCON_REV_B0 )
+ return;
+
+ /* Flush the ISR */
+ if ( enable )
+ falcon_xmac_readl ( efab, &reg, FCN_XM_MGT_INT_REG_MAC_B0 );
+
+ EFAB_POPULATE_DWORD_2 ( reg,
+ FCN_XM_MSK_RMTFLT, !enable,
+ FCN_XM_MSK_LCLFLT, !enable);
+ falcon_xmac_readl ( efab, &reg, FCN_XM_MGT_INT_MSK_REG_MAC_B0 );
+}
+
+/**
+ * Reset 10G MAC connected to port
+ *
+ */
+static int
+falcon_reset_xmac ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+ int count;
+
+ EFAB_POPULATE_DWORD_1 ( reg, FCN_XM_CORE_RST, 1 );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_GLB_CFG_REG_MAC );
+
+ for ( count = 0 ; count < 1000 ; count++ ) {
+ udelay ( 10 );
+ falcon_xmac_readl ( efab, &reg,
+ FCN_XM_GLB_CFG_REG_MAC );
+ if ( EFAB_DWORD_FIELD ( reg, FCN_XM_CORE_RST ) == 0 )
+ return 0;
+ }
+ return -ETIMEDOUT;
+}
+
+
+static int
+falcon_reset_xaui ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+ int count;
+
+ if (!efab->is_asic)
+ return 0;
+
+ EFAB_POPULATE_DWORD_1 ( reg, FCN_XX_RST_XX_EN, 1 );
+ falcon_xmac_writel ( efab, &reg, FCN_XX_PWR_RST_REG_MAC );
+
+ /* Give some time for the link to establish */
+ for (count = 0; count < 1000; count++) { /* wait upto 10ms */
+ falcon_xmac_readl ( efab, &reg, FCN_XX_PWR_RST_REG_MAC );
+ if ( EFAB_DWORD_FIELD ( reg, FCN_XX_RST_XX_EN ) == 0 ) {
+ falcon_setup_xaui ( efab );
+ return 0;
+ }
+ udelay(10);
+ }
+ EFAB_ERR ( "timed out waiting for XAUI/XGXS reset\n" );
+ return -ETIMEDOUT;
+}
+
+static int
+falcon_xaui_link_ok ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+ int align_done, lane_status, sync;
+ int has_phyxs;
+ int link_ok = 1;
+
+ /* Read Falcon XAUI side */
+ if ( efab->is_asic ) {
+ /* Read link status */
+ falcon_xmac_readl ( efab, &reg, FCN_XX_CORE_STAT_REG_MAC );
+ align_done = EFAB_DWORD_FIELD ( reg, FCN_XX_ALIGN_DONE );
+
+ sync = EFAB_DWORD_FIELD ( reg, FCN_XX_SYNC_STAT );
+ sync = ( sync == FCN_XX_SYNC_STAT_DECODE_SYNCED );
+
+ link_ok = align_done && sync;
+ }
+
+ /* Clear link status ready for next read */
+ EFAB_SET_DWORD_FIELD ( reg, FCN_XX_COMMA_DET, FCN_XX_COMMA_DET_RESET );
+ EFAB_SET_DWORD_FIELD ( reg, FCN_XX_CHARERR, FCN_XX_CHARERR_RESET);
+ EFAB_SET_DWORD_FIELD ( reg, FCN_XX_DISPERR, FCN_XX_DISPERR_RESET);
+ falcon_xmac_writel ( efab, &reg, FCN_XX_CORE_STAT_REG_MAC );
+
+ has_phyxs = ( efab->phy_op->mmds & ( 1 << MDIO_MMD_PHYXS ) );
+ if ( link_ok && has_phyxs ) {
+ lane_status = falcon_mdio_read ( efab, MDIO_MMD_PHYXS,
+ MDIO_PHYXS_LANE_STATE );
+ link_ok = ( lane_status & ( 1 << MDIO_PHYXS_LANE_ALIGNED_LBN ) );
+
+ if (!link_ok )
+ EFAB_LOG ( "XGXS lane status: %x\n", lane_status );
+ }
+
+ return link_ok;
+}
+
+/**
+ * Initialise XMAC
+ *
+ */
+static void
+falcon_reconfigure_xmac ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+ int max_frame_len;
+
+ /* Configure MAC - cut-thru mode is hard wired on */
+ EFAB_POPULATE_DWORD_3 ( reg,
+ FCN_XM_RX_JUMBO_MODE, 1,
+ FCN_XM_TX_STAT_EN, 1,
+ FCN_XM_RX_STAT_EN, 1);
+ falcon_xmac_writel ( efab, &reg, FCN_XM_GLB_CFG_REG_MAC );
+
+ /* Configure TX */
+ EFAB_POPULATE_DWORD_6 ( reg,
+ FCN_XM_TXEN, 1,
+ FCN_XM_TX_PRMBL, 1,
+ FCN_XM_AUTO_PAD, 1,
+ FCN_XM_TXCRC, 1,
+ FCN_XM_FCNTL, 1,
+ FCN_XM_IPG, 0x3 );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_TX_CFG_REG_MAC );
+
+ /* Configure RX */
+ EFAB_POPULATE_DWORD_4 ( reg,
+ FCN_XM_RXEN, 1,
+ FCN_XM_AUTO_DEPAD, 0,
+ FCN_XM_ACPT_ALL_MCAST, 1,
+ FCN_XM_PASS_CRC_ERR, 1 );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_RX_CFG_REG_MAC );
+
+ /* Set frame length */
+ max_frame_len = EFAB_MAX_FRAME_LEN ( ETH_FRAME_LEN );
+ EFAB_POPULATE_DWORD_1 ( reg,
+ FCN_XM_MAX_RX_FRM_SIZE, max_frame_len );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_RX_PARAM_REG_MAC );
+ EFAB_POPULATE_DWORD_2 ( reg,
+ FCN_XM_MAX_TX_FRM_SIZE, max_frame_len,
+ FCN_XM_TX_JUMBO_MODE, 1 );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_TX_PARAM_REG_MAC );
+
+ /* Enable flow control receipt */
+ EFAB_POPULATE_DWORD_2 ( reg,
+ FCN_XM_PAUSE_TIME, 0xfffe,
+ FCN_XM_DIS_FCNTL, 0 );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_FC_REG_MAC );
+
+ /* Set MAC address */
+ EFAB_POPULATE_DWORD_4 ( reg,
+ FCN_XM_ADR_0, efab->mac_addr[0],
+ FCN_XM_ADR_1, efab->mac_addr[1],
+ FCN_XM_ADR_2, efab->mac_addr[2],
+ FCN_XM_ADR_3, efab->mac_addr[3] );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_ADR_LO_REG_MAC );
+ EFAB_POPULATE_DWORD_2 ( reg,
+ FCN_XM_ADR_4, efab->mac_addr[4],
+ FCN_XM_ADR_5, efab->mac_addr[5] );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_ADR_HI_REG_MAC );
+}
+
+static int
+falcon_init_xmac ( struct efab_nic *efab )
+{
+ int count, rc;
+
+ /* Mask the PHY management interrupt */
+ falcon_mask_status_intr ( efab, 0 );
+
+ /* Initialise the PHY to instantiate the clock. */
+ rc = efab->phy_op->init ( efab );
+ if ( rc ) {
+ EFAB_ERR ( "unable to initialise PHY\n" );
+ goto fail1;
+ }
+
+ falcon_reset_xaui ( efab );
+
+ /* Give the PHY and MAC time to faff */
+ mdelay ( 100 );
+
+ /* Reset and reconfigure the XMAC */
+ rc = falcon_reset_xmac ( efab );
+ if ( rc )
+ goto fail2;
+ falcon_reconfigure_xmac ( efab );
+ falcon_reconfigure_mac_wrapper ( efab );
+ /**
+ * Now wait for the link to come up. This may take a while
+ * for some slower PHY's.
+ */
+ for (count=0; count<50; count++) {
+ int link_ok = 1;
+
+ /* Wait a while for the link to come up. */
+ mdelay ( 100 );
+ if ((count % 5) == 0)
+ putchar ( '.' );
+
+ /* Does the PHY think the wire-side link is up? */
+ link_ok = mdio_clause45_links_ok ( efab );
+ /* Ensure the XAUI link to the PHY is good */
+ if ( link_ok ) {
+ link_ok = falcon_xaui_link_ok ( efab );
+ if ( !link_ok )
+ falcon_reset_xaui ( efab );
+ }
+
+ /* Check fault indication */
+ if ( link_ok )
+ link_ok = falcon_xgmii_status ( efab );
+
+ efab->link_up = link_ok;
+ if ( link_ok ) {
+ /* unmask the status interrupt */
+ falcon_mask_status_intr ( efab, 1 );
+ return 0;
+ }
+ }
+
+ /* Link failed to come up, but initialisation was fine. */
+ rc = -ETIMEDOUT;
+
+fail2:
+fail1:
+ return rc;
+}
+
+static struct efab_mac_operations falcon_xmac_operations = {
+ .init = falcon_init_xmac,
+};
+
+/*******************************************************************************
+ *
+ *
+ * Null PHY handling
+ *
+ *
+ *******************************************************************************/
+
+static int
+falcon_xaui_phy_init ( struct efab_nic *efab )
+{
+ /* CX4 is always 10000FD only */
+ efab->link_options = LPA_EF_10000FULL;
+
+ /* There is no PHY! */
+ return 0;
+}
+
+static struct efab_phy_operations falcon_xaui_phy_ops = {
+ .init = falcon_xaui_phy_init,
+ .mmds = 0,
+};
+
+
+/*******************************************************************************
+ *
+ *
+ * Alaska PHY
+ *
+ *
+ *******************************************************************************/
+
+/**
+ * Initialise Alaska PHY
+ *
+ */
+static int
+alaska_init ( struct efab_nic *efab )
+{
+ unsigned int advertised, lpa;
+
+ /* Read link up status */
+ efab->link_up = gmii_link_ok ( efab );
+
+ if ( ! efab->link_up )
+ return -EIO;
+
+ /* Determine link options from PHY. */
+ advertised = gmii_autoneg_advertised ( efab );
+ lpa = gmii_autoneg_lpa ( efab );
+ efab->link_options = gmii_nway_result ( advertised & lpa );
+
+ return 0;
+}
+
+static struct efab_phy_operations falcon_alaska_phy_ops = {
+ .init = alaska_init,
+};
+
+/*******************************************************************************
+ *
+ *
+ * xfp
+ *
+ *
+ *******************************************************************************/
+
+#define XFP_REQUIRED_DEVS ( MDIO_MMDREG_DEVS0_PCS | \
+ MDIO_MMDREG_DEVS0_PMAPMD | \
+ MDIO_MMDREG_DEVS0_PHYXS )
+
+static int
+falcon_xfp_phy_init ( struct efab_nic *efab )
+{
+ int rc;
+
+ /* Optical link is always 10000FD only */
+ efab->link_options = LPA_EF_10000FULL;
+
+ /* Reset the PHY */
+ rc = mdio_clause45_reset_mmd ( efab, MDIO_MMD_PHYXS );
+ if ( rc )
+ return rc;
+
+ return 0;
+}
+
+static struct efab_phy_operations falcon_xfp_phy_ops = {
+ .init = falcon_xfp_phy_init,
+ .mmds = XFP_REQUIRED_DEVS,
+};
+
+/*******************************************************************************
+ *
+ *
+ * txc43128
+ *
+ *
+ *******************************************************************************/
+
+/* Command register */
+#define TXC_GLRGS_GLCMD (0xc004)
+#define TXC_GLCMD_LMTSWRST_LBN (14)
+
+/* Amplitude on lanes 0+1, 2+3 */
+#define TXC_ALRGS_ATXAMP0 (0xc041)
+#define TXC_ALRGS_ATXAMP1 (0xc042)
+/* Bit position of value for lane 0+2, 1+3 */
+#define TXC_ATXAMP_LANE02_LBN (3)
+#define TXC_ATXAMP_LANE13_LBN (11)
+
+#define TXC_ATXAMP_1280_mV (0)
+#define TXC_ATXAMP_1200_mV (8)
+#define TXC_ATXAMP_1120_mV (12)
+#define TXC_ATXAMP_1060_mV (14)
+#define TXC_ATXAMP_0820_mV (25)
+#define TXC_ATXAMP_0720_mV (26)
+#define TXC_ATXAMP_0580_mV (27)
+#define TXC_ATXAMP_0440_mV (28)
+
+#define TXC_ATXAMP_0820_BOTH ( (TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE02_LBN) | \
+ (TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE13_LBN) )
+
+#define TXC_ATXAMP_DEFAULT (0x6060) /* From databook */
+
+/* Preemphasis on lanes 0+1, 2+3 */
+#define TXC_ALRGS_ATXPRE0 (0xc043)
+#define TXC_ALRGS_ATXPRE1 (0xc044)
+
+#define TXC_ATXPRE_NONE (0)
+#define TXC_ATXPRE_DEFAULT (0x1010) /* From databook */
+
+#define TXC_REQUIRED_DEVS ( MDIO_MMDREG_DEVS0_PCS | \
+ MDIO_MMDREG_DEVS0_PMAPMD | \
+ MDIO_MMDREG_DEVS0_PHYXS )
+
+static int
+falcon_txc_logic_reset ( struct efab_nic *efab )
+{
+ int val;
+ int tries = 50;
+
+ val = falcon_mdio_read ( efab, MDIO_MMD_PCS, TXC_GLRGS_GLCMD );
+ val |= (1 << TXC_GLCMD_LMTSWRST_LBN);
+ falcon_mdio_write ( efab, MDIO_MMD_PCS, TXC_GLRGS_GLCMD, val );
+
+ while ( tries--) {
+ val = falcon_mdio_read ( efab, MDIO_MMD_PCS, TXC_GLRGS_GLCMD );
+ if ( ~val & ( 1 << TXC_GLCMD_LMTSWRST_LBN ) )
+ return 0;
+ udelay(1);
+ }
+
+ EFAB_ERR ( "logic reset failed\n" );
+
+ return -ETIMEDOUT;
+}
+
+static int
+falcon_txc_phy_init ( struct efab_nic *efab )
+{
+ int rc;
+
+ /* CX4 is always 10000FD only */
+ efab->link_options = LPA_EF_10000FULL;
+
+ /* reset the phy */
+ rc = mdio_clause45_reset_mmd ( efab, MDIO_MMD_PMAPMD );
+ if ( rc )
+ goto fail1;
+
+ rc = mdio_clause45_check_mmds ( efab );
+ if ( rc )
+ goto fail2;
+
+ /* Turn amplitude down and preemphasis off on the host side
+ * (PHY<->MAC) as this is believed less likely to upset falcon
+ * and no adverse effects have been noted. It probably also
+ * saves a picowatt or two */
+
+ /* Turn off preemphasis */
+ falcon_mdio_write ( efab, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE0,
+ TXC_ATXPRE_NONE );
+ falcon_mdio_write ( efab, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE1,
+ TXC_ATXPRE_NONE );
+
+ /* Turn down the amplitude */
+ falcon_mdio_write ( efab, MDIO_MMD_PHYXS, TXC_ALRGS_ATXAMP0,
+ TXC_ATXAMP_0820_BOTH );
+ falcon_mdio_write ( efab, MDIO_MMD_PHYXS, TXC_ALRGS_ATXAMP1,
+ TXC_ATXAMP_0820_BOTH );
+
+ /* Set the line side amplitude and preemphasis to the databook
+ * defaults as an erratum causes them to be 0 on at least some
+ * PHY rev.s */
+ falcon_mdio_write ( efab, MDIO_MMD_PMAPMD, TXC_ALRGS_ATXPRE0,
+ TXC_ATXPRE_DEFAULT );
+ falcon_mdio_write ( efab, MDIO_MMD_PMAPMD, TXC_ALRGS_ATXPRE1,
+ TXC_ATXPRE_DEFAULT );
+ falcon_mdio_write ( efab, MDIO_MMD_PMAPMD, TXC_ALRGS_ATXAMP0,
+ TXC_ATXAMP_DEFAULT );
+ falcon_mdio_write ( efab, MDIO_MMD_PMAPMD, TXC_ALRGS_ATXAMP1,
+ TXC_ATXAMP_DEFAULT );
+
+ rc = falcon_txc_logic_reset ( efab );
+ if ( rc )
+ goto fail3;
+
+ return 0;
+
+fail3:
+fail2:
+fail1:
+ return rc;
+}
+
+static struct efab_phy_operations falcon_txc_phy_ops = {
+ .init = falcon_txc_phy_init,
+ .mmds = TXC_REQUIRED_DEVS,
+};
+
+/*******************************************************************************
+ *
+ *
+ * tenxpress
+ *
+ *
+ *******************************************************************************/
+
+
+#define TENXPRESS_REQUIRED_DEVS ( MDIO_MMDREG_DEVS0_PMAPMD | \
+ MDIO_MMDREG_DEVS0_PCS | \
+ MDIO_MMDREG_DEVS0_PHYXS )
+
+#define PCS_TEST_SELECT_REG 0xd807 /* PRM 10.5.8 */
+#define CLK312_EN_LBN 3
+#define CLK312_EN_WIDTH 1
+
+#define PCS_CLOCK_CTRL_REG 0xd801
+#define PLL312_RST_N_LBN 2
+
+/* Special Software reset register */
+#define PMA_PMD_EXT_CTRL_REG 49152
+#define PMA_PMD_EXT_SSR_LBN 15
+
+/* Boot status register */
+#define PCS_BOOT_STATUS_REG 0xd000
+#define PCS_BOOT_FATAL_ERR_LBN 0
+#define PCS_BOOT_PROGRESS_LBN 1
+#define PCS_BOOT_PROGRESS_WIDTH 2
+#define PCS_BOOT_COMPLETE_LBN 3
+
+#define PCS_SOFT_RST2_REG 0xd806
+#define SERDES_RST_N_LBN 13
+#define XGXS_RST_N_LBN 12
+
+static int
+falcon_tenxpress_check_c11 ( struct efab_nic *efab )
+{
+ int count;
+ uint32_t boot_stat;
+
+ /* Check that the C11 CPU has booted */
+ for (count=0; count<10; count++) {
+ boot_stat = falcon_mdio_read ( efab, MDIO_MMD_PCS,
+ PCS_BOOT_STATUS_REG );
+ if ( boot_stat & ( 1 << PCS_BOOT_COMPLETE_LBN ) )
+ return 0;
+
+ udelay(10);
+ }
+
+ EFAB_ERR ( "C11 failed to boot\n" );
+ return -ETIMEDOUT;
+}
+
+static int
+falcon_tenxpress_phy_init ( struct efab_nic *efab )
+{
+ int rc, reg;
+
+ /* 10XPRESS is always 10000FD (at the moment) */
+ efab->link_options = LPA_EF_10000FULL;
+
+ /* Wait for the blocks to come out of reset */
+ rc = mdio_clause45_wait_reset_mmds ( efab );
+ if ( rc )
+ goto fail1;
+
+ rc = mdio_clause45_check_mmds ( efab );
+ if ( rc )
+ goto fail2;
+
+ /* Turn on the clock */
+ reg = (1 << CLK312_EN_LBN);
+ falcon_mdio_write ( efab, MDIO_MMD_PCS, PCS_TEST_SELECT_REG, reg);
+
+ /* Wait 200ms for the PHY to boot */
+ mdelay(200);
+
+ rc = falcon_tenxpress_check_c11 ( efab );
+ if ( rc )
+ goto fail3;
+
+ return 0;
+
+fail3:
+fail2:
+fail1:
+ return rc;
+}
+
+static struct efab_phy_operations falcon_tenxpress_phy_ops = {
+ .init = falcon_tenxpress_phy_init,
+ .mmds = TENXPRESS_REQUIRED_DEVS,
+};
+
+/*******************************************************************************
+ *
+ *
+ * PM8358
+ *
+ *
+ *******************************************************************************/
+
+/* The PM8358 just presents a DTE XS */
+#define PM8358_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_DTEXS)
+
+/* PHY-specific definitions */
+/* Master ID and Global Performance Monitor Update */
+#define PMC_MASTER_REG (0xd000)
+/* Analog Tx Rx settings under software control */
+#define PMC_MASTER_ANLG_CTRL (1<< 11)
+
+/* Master Configuration register 2 */
+#define PMC_MCONF2_REG (0xd002)
+/* Drive Tx off centre of data eye (1) vs. clock edge (0) */
+#define PMC_MCONF2_TEDGE (1 << 2)
+/* Drive Rx off centre of data eye (1) vs. clock edge (0) */
+#define PMC_MCONF2_REDGE (1 << 3)
+
+/* Analog Rx settings */
+#define PMC_ANALOG_RX_CFG0 (0xd025)
+#define PMC_ANALOG_RX_CFG1 (0xd02d)
+#define PMC_ANALOG_RX_CFG2 (0xd035)
+#define PMC_ANALOG_RX_CFG3 (0xd03d)
+
+
+#define PMC_ANALOG_RX_TERM (1 << 15) /* Bit 15 of RX CFG: 0 for 100 ohms float,
+ 1 for 50 to 1.2V */
+#define PMC_ANALOG_RX_EQ_MASK (3 << 8)
+#define PMC_ANALOG_RX_EQ_NONE (0 << 8)
+#define PMC_ANALOG_RX_EQ_HALF (1 << 8)
+#define PMC_ANALOG_RX_EQ_FULL (2 << 8)
+#define PMC_ANALOG_RX_EQ_RSVD (3 << 8)
+
+static int
+falcon_pm8358_phy_init ( struct efab_nic *efab )
+{
+ int rc, reg, i;
+
+ /* This is a XAUI retimer part */
+ efab->link_options = LPA_EF_10000FULL;
+
+ rc = mdio_clause45_reset_mmd ( efab, MDIO_MMDREG_DEVS0_DTEXS );
+ if ( rc )
+ return rc;
+
+ /* Enable software control of analogue settings */
+ reg = falcon_mdio_read ( efab, MDIO_MMD_DTEXS, PMC_MASTER_REG );
+ reg |= PMC_MASTER_ANLG_CTRL;
+ falcon_mdio_write ( efab, MDIO_MMD_DTEXS, PMC_MASTER_REG, reg );
+
+ /* Turn rx eq on for all channels */
+ for (i=0; i< 3; i++) {
+ /* The analog CFG registers are evenly spaced 8 apart */
+ uint16_t addr = PMC_ANALOG_RX_CFG0 + 8*i;
+ reg = falcon_mdio_read ( efab, MDIO_MMD_DTEXS, addr );
+ reg = ( reg & ~PMC_ANALOG_RX_EQ_MASK ) | PMC_ANALOG_RX_EQ_FULL;
+ falcon_mdio_write ( efab, MDIO_MMD_DTEXS, addr, reg );
+ }
+
+ /* Set TEDGE, clear REDGE */
+ reg = falcon_mdio_read ( efab, MDIO_MMD_DTEXS, PMC_MCONF2_REG );
+ reg = ( reg & ~PMC_MCONF2_REDGE) | PMC_MCONF2_TEDGE;
+ falcon_mdio_write ( efab, MDIO_MMD_DTEXS, PMC_MCONF2_REG, reg );
+
+ return 0;
+}
+
+static struct efab_phy_operations falcon_pm8358_phy_ops = {
+ .init = falcon_pm8358_phy_init,
+ .mmds = PM8358_REQUIRED_DEVS,
+};
+
+/*******************************************************************************
+ *
+ *
+ * SFE4001 support
+ *
+ *
+ *******************************************************************************/
+
+#define MAX_TEMP_THRESH 90
+
+/* I2C Expander */
+#define PCA9539 0x74
+
+#define P0_IN 0x00
+#define P0_OUT 0x02
+#define P0_CONFIG 0x06
+
+#define P0_EN_1V0X_LBN 0
+#define P0_EN_1V0X_WIDTH 1
+#define P0_EN_1V2_LBN 1
+#define P0_EN_1V2_WIDTH 1
+#define P0_EN_2V5_LBN 2
+#define P0_EN_2V5_WIDTH 1
+#define P0_EN_3V3X_LBN 3
+#define P0_EN_3V3X_WIDTH 1
+#define P0_EN_5V_LBN 4
+#define P0_EN_5V_WIDTH 1
+#define P0_X_TRST_LBN 6
+#define P0_X_TRST_WIDTH 1
+
+#define P1_IN 0x01
+#define P1_CONFIG 0x07
+
+#define P1_AFE_PWD_LBN 0
+#define P1_AFE_PWD_WIDTH 1
+#define P1_DSP_PWD25_LBN 1
+#define P1_DSP_PWD25_WIDTH 1
+#define P1_SPARE_LBN 4
+#define P1_SPARE_WIDTH 4
+
+/* Temperature Sensor */
+#define MAX6647 0x4e
+
+#define RSL 0x02
+#define RLHN 0x05
+#define WLHO 0x0b
+
+static struct i2c_device i2c_pca9539 = {
+ .dev_addr = PCA9539,
+ .dev_addr_len = 1,
+ .word_addr_len = 1,
+};
+
+
+static struct i2c_device i2c_max6647 = {
+ .dev_addr = MAX6647,
+ .dev_addr_len = 1,
+ .word_addr_len = 1,
+};
+
+static int
+sfe4001_init ( struct efab_nic *efab )
+{
+ struct i2c_interface *i2c = &efab->i2c_bb.i2c;
+ efab_dword_t reg;
+ uint8_t in, cfg, out;
+ int count, rc;
+
+ EFAB_LOG ( "Initialise SFE4001 board\n" );
+
+ /* Ensure XGXS and XAUI SerDes are held in reset */
+ EFAB_POPULATE_DWORD_7 ( reg,
+ FCN_XX_PWRDNA_EN, 1,
+ FCN_XX_PWRDNB_EN, 1,
+ FCN_XX_RSTPLLAB_EN, 1,
+ FCN_XX_RESETA_EN, 1,
+ FCN_XX_RESETB_EN, 1,
+ FCN_XX_RSTXGXSRX_EN, 1,
+ FCN_XX_RSTXGXSTX_EN, 1 );
+ falcon_xmac_writel ( efab, &reg, FCN_XX_PWR_RST_REG_MAC);
+ udelay(10);
+
+ /* Set DSP over-temperature alert threshold */
+ cfg = MAX_TEMP_THRESH;
+ rc = i2c->write ( i2c, &i2c_max6647, WLHO, &cfg, EFAB_BYTE );
+ if ( rc )
+ goto fail1;
+
+ /* Read it back and verify */
+ rc = i2c->read ( i2c, &i2c_max6647, RLHN, &in, EFAB_BYTE );
+ if ( rc )
+ goto fail2;
+
+ if ( in != MAX_TEMP_THRESH ) {
+ EFAB_ERR ( "Unable to verify MAX6647 limit (requested=%d "
+ "confirmed=%d)\n", cfg, in );
+ rc = -EIO;
+ goto fail3;
+ }
+
+ /* Clear any previous over-temperature alert */
+ rc = i2c->read ( i2c, &i2c_max6647, RSL, &in, EFAB_BYTE );
+ if ( rc )
+ goto fail4;
+
+ /* Enable port 0 and 1 outputs on IO expander */
+ cfg = 0x00;
+ rc = i2c->write ( i2c, &i2c_pca9539, P0_CONFIG, &cfg, EFAB_BYTE );
+ if ( rc )
+ goto fail5;
+ cfg = 0xff & ~(1 << P1_SPARE_LBN);
+ rc = i2c->write ( i2c, &i2c_pca9539, P1_CONFIG, &cfg, EFAB_BYTE );
+ if ( rc )
+ goto fail6;
+
+ /* Turn all power off then wait 1 sec. This ensures PHY is reset */
+ out = 0xff & ~((0 << P0_EN_1V2_LBN) | (0 << P0_EN_2V5_LBN) |
+ (0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) |
+ (0 << P0_EN_1V0X_LBN));
+
+ rc = i2c->write ( i2c, &i2c_pca9539, P0_OUT, &out, EFAB_BYTE );
+ if ( rc )
+ goto fail7;
+
+ mdelay(1000);
+
+ for (count=0; count<20; count++) {
+ /* Turn on 1.2V, 2.5V, 3.3V and 5V power rails */
+ out = 0xff & ~( (1 << P0_EN_1V2_LBN) | (1 << P0_EN_2V5_LBN) |
+ (1 << P0_EN_3V3X_LBN) | (1 << P0_EN_5V_LBN) |
+ (1 << P0_X_TRST_LBN) );
+
+ rc = i2c->write ( i2c, &i2c_pca9539, P0_OUT, &out, EFAB_BYTE );
+ if ( rc )
+ goto fail8;
+
+ mdelay ( 10 );
+
+ /* Turn on the 1V power rail */
+ out &= ~( 1 << P0_EN_1V0X_LBN );
+ rc = i2c->write ( i2c, &i2c_pca9539, P0_OUT, &out, EFAB_BYTE );
+ if ( rc )
+ goto fail9;
+
+ EFAB_LOG ( "Waiting for power...(attempt %d)\n", count);
+ mdelay ( 1000 );
+
+ /* Check DSP is powered */
+ rc = i2c->read ( i2c, &i2c_pca9539, P1_IN, &in, EFAB_BYTE );
+ if ( rc )
+ goto fail10;
+
+ if ( in & ( 1 << P1_AFE_PWD_LBN ) )
+ return 0;
+ }
+
+ rc = -ETIMEDOUT;
+
+fail10:
+fail9:
+fail8:
+fail7:
+ /* Turn off power rails */
+ out = 0xff;
+ (void) i2c->write ( i2c, &i2c_pca9539, P0_OUT, &out, EFAB_BYTE );
+ /* Disable port 1 outputs on IO expander */
+ out = 0xff;
+ (void) i2c->write ( i2c, &i2c_pca9539, P1_CONFIG, &out, EFAB_BYTE );
+fail6:
+ /* Disable port 0 outputs */
+ out = 0xff;
+ (void) i2c->write ( i2c, &i2c_pca9539, P1_CONFIG, &out, EFAB_BYTE );
+fail5:
+fail4:
+fail3:
+fail2:
+fail1:
+ EFAB_ERR ( "Failed initialising SFE4001 board\n" );
+ return rc;
+}
+
+static void
+sfe4001_fini ( struct efab_nic *efab )
+{
+ struct i2c_interface *i2c = &efab->i2c_bb.i2c;
+ uint8_t in, cfg, out;
+
+ EFAB_ERR ( "Turning off SFE4001\n" );
+
+ /* Turn off all power rails */
+ out = 0xff;
+ (void) i2c->write ( i2c, &i2c_pca9539, P0_OUT, &out, EFAB_BYTE );
+
+ /* Disable port 1 outputs on IO expander */
+ cfg = 0xff;
+ (void) i2c->write ( i2c, &i2c_pca9539, P1_CONFIG, &cfg, EFAB_BYTE );
+
+ /* Disable port 0 outputs on IO expander */
+ cfg = 0xff;
+ (void) i2c->write ( i2c, &i2c_pca9539, P0_CONFIG, &cfg, EFAB_BYTE );
+
+ /* Clear any over-temperature alert */
+ (void) i2c->read ( i2c, &i2c_max6647, RSL, &in, EFAB_BYTE );
+}
+
+struct efab_board_operations sfe4001_ops = {
+ .init = sfe4001_init,
+ .fini = sfe4001_fini,
+};
+
+static int sfe4002_init ( struct efab_nic *efab __attribute__((unused)) )
+{
+ return 0;
+}
+static void sfe4002_fini ( struct efab_nic *efab __attribute__((unused)) )
+{
+}
+
+struct efab_board_operations sfe4002_ops = {
+ .init = sfe4002_init,
+ .fini = sfe4002_fini,
+};
+
+static int sfe4003_init ( struct efab_nic *efab __attribute__((unused)) )
+{
+ return 0;
+}
+static void sfe4003_fini ( struct efab_nic *efab __attribute__((unused)) )
+{
+}
+
+struct efab_board_operations sfe4003_ops = {
+ .init = sfe4003_init,
+ .fini = sfe4003_fini,
+};
+
+/*******************************************************************************
+ *
+ *
+ * Hardware initialisation
+ *
+ *
+ *******************************************************************************/
+
+static void
+falcon_free_special_buffer ( void *p )
+{
+ /* We don't bother cleaning up the buffer table entries -
+ * we're hardly limited */
+ free_dma ( p, EFAB_BUF_ALIGN );
+}
+
+static void*
+falcon_alloc_special_buffer ( struct efab_nic *efab, int bytes,
+ struct efab_special_buffer *entry )
+{
+ void* buffer;
+ int remaining;
+ efab_qword_t buf_desc;
+ unsigned long dma_addr;
+
+ /* Allocate the buffer, aligned on a buffer address boundary */
+ buffer = malloc_dma ( bytes, EFAB_BUF_ALIGN );
+ if ( ! buffer )
+ return NULL;
+
+ /* Push buffer table entries to back the buffer */
+ entry->id = efab->buffer_head;
+ entry->dma_addr = dma_addr = virt_to_bus ( buffer );
+ assert ( ( dma_addr & ( EFAB_BUF_ALIGN - 1 ) ) == 0 );
+
+ remaining = bytes;
+ while ( remaining > 0 ) {
+ EFAB_POPULATE_QWORD_3 ( buf_desc,
+ FCN_IP_DAT_BUF_SIZE, FCN_IP_DAT_BUF_SIZE_4K,
+ FCN_BUF_ADR_FBUF, ( dma_addr >> 12 ),
+ FCN_BUF_OWNER_ID_FBUF, 0 );
+
+ falcon_write_sram ( efab, &buf_desc, efab->buffer_head );
+
+ ++efab->buffer_head;
+ dma_addr += EFAB_BUF_ALIGN;
+ remaining -= EFAB_BUF_ALIGN;
+ }
+
+ EFAB_TRACE ( "Allocated 0x%x bytes at %p backed by buffer table "
+ "entries 0x%x..0x%x\n", bytes, buffer, entry->id,
+ efab->buffer_head - 1 );
+
+ return buffer;
+}
+
+static void
+clear_b0_fpga_memories ( struct efab_nic *efab)
+{
+ efab_oword_t blanko, temp;
+ int offset;
+
+ EFAB_ZERO_OWORD ( blanko );
+
+ /* Clear the address region register */
+ EFAB_POPULATE_OWORD_4 ( temp,
+ FCN_ADR_REGION0, 0,
+ FCN_ADR_REGION1, ( 1 << 16 ),
+ FCN_ADR_REGION2, ( 2 << 16 ),
+ FCN_ADR_REGION3, ( 3 << 16 ) );
+ falcon_write ( efab, &temp, FCN_ADR_REGION_REG_KER );
+
+ EFAB_TRACE ( "Clearing filter and RSS tables\n" );
+
+ for ( offset = FCN_RX_FILTER_TBL0 ;
+ offset < FCN_RX_RSS_INDIR_TBL_B0+0x800 ;
+ offset += 0x10 ) {
+ falcon_write ( efab, &blanko, offset );
+ }
+
+ EFAB_TRACE ( "Wiping buffer tables\n" );
+
+ /* Notice the 8 byte access mode */
+ for ( offset = 0x2800000 ;
+ offset < 0x3000000 ;
+ offset += 0x8) {
+ _falcon_writel ( efab, 0, offset );
+ _falcon_writel ( efab, 0, offset + 4 );
+ wmb();
+ }
+}
+
+static int
+falcon_reset ( struct efab_nic *efab )
+{
+ efab_oword_t glb_ctl_reg_ker;
+
+ /* Initiate software reset */
+ EFAB_POPULATE_OWORD_6 ( glb_ctl_reg_ker,
+ FCN_PCIE_CORE_RST_CTL, EXCLUDE_FROM_RESET,
+ FCN_PCIE_NSTCK_RST_CTL, EXCLUDE_FROM_RESET,
+ FCN_PCIE_SD_RST_CTL, EXCLUDE_FROM_RESET,
+ FCN_EE_RST_CTL, EXCLUDE_FROM_RESET,
+ FCN_EXT_PHY_RST_DUR, 0x7, /* 10ms */
+ FCN_SWRST, 1 );
+
+ falcon_write ( efab, &glb_ctl_reg_ker, FCN_GLB_CTL_REG_KER );
+
+ /* Allow 50ms for reset */
+ mdelay ( 50 );
+
+ /* Check for device reset complete */
+ falcon_read ( efab, &glb_ctl_reg_ker, FCN_GLB_CTL_REG_KER );
+ if ( EFAB_OWORD_FIELD ( glb_ctl_reg_ker, FCN_SWRST ) != 0 ) {
+ EFAB_ERR ( "Reset failed\n" );
+ return -ETIMEDOUT;
+ }
+
+ if ( ( efab->pci_revision == FALCON_REV_B0 ) && !efab->is_asic ) {
+ clear_b0_fpga_memories ( efab );
+ }
+
+ return 0;
+}
+
+/** Offset of MAC address within EEPROM or Flash */
+#define FALCON_MAC_ADDRESS_OFFSET 0x310
+
+/*
+ * Falcon EEPROM structure
+ */
+#define SF_NV_CONFIG_BASE 0x300
+#define SF_NV_CONFIG_EXTRA 0xA0
+
+struct falcon_nv_config_ver2 {
+ uint16_t nports;
+ uint8_t port0_phy_addr;
+ uint8_t port0_phy_type;
+ uint8_t port1_phy_addr;
+ uint8_t port1_phy_type;
+ uint16_t asic_sub_revision;
+ uint16_t board_revision;
+ uint8_t mac_location;
+};
+
+struct falcon_nv_extra {
+ uint16_t magicnumber;
+ uint16_t structure_version;
+ uint16_t checksum;
+ union {
+ struct falcon_nv_config_ver2 ver2;
+ } ver_specific;
+};
+
+#define BOARD_TYPE(_rev) (_rev >> 8)
+
+static void
+falcon_probe_nic_variant ( struct efab_nic *efab, struct pci_device *pci )
+{
+ efab_oword_t altera_build, nic_stat;
+ int fpga_version;
+ uint8_t revision;
+
+ /* PCI revision */
+ pci_read_config_byte ( pci, PCI_CLASS_REVISION, &revision );
+ efab->pci_revision = revision;
+
+ /* Asic vs FPGA */
+ falcon_read ( efab, &altera_build, FCN_ALTERA_BUILD_REG_KER );
+ fpga_version = EFAB_OWORD_FIELD ( altera_build, FCN_VER_ALL );
+ efab->is_asic = (fpga_version == 0);
+
+ /* MAC and PCI type */
+ falcon_read ( efab, &nic_stat, FCN_NIC_STAT_REG );
+ if ( efab->pci_revision == FALCON_REV_B0 ) {
+ efab->phy_10g = EFAB_OWORD_FIELD ( nic_stat, FCN_STRAP_10G );
+ }
+ else if ( efab->is_asic ) {
+ efab->phy_10g = EFAB_OWORD_FIELD ( nic_stat, FCN_STRAP_10G );
+ }
+ else {
+ int minor = EFAB_OWORD_FIELD ( altera_build, FCN_VER_MINOR );
+ efab->phy_10g = ( minor == 0x14 );
+ }
+}
+
+static void
+falcon_init_spi_device ( struct efab_nic *efab, struct spi_device *spi )
+{
+ /* Falcon's SPI interface only supports reads/writes of up to 16 bytes.
+ * Reduce the nvs block size down to satisfy this - which means callers
+ * should use the nvs_* functions rather than spi_*. */
+ if ( spi->nvs.block_size > FALCON_SPI_MAX_LEN )
+ spi->nvs.block_size = FALCON_SPI_MAX_LEN;
+
+ spi->bus = &efab->spi_bus;
+ efab->spi = spi;
+}
+
+static int
+falcon_probe_spi ( struct efab_nic *efab )
+{
+ efab_oword_t nic_stat, gpio_ctl, ee_vpd_cfg;
+ int has_flash, has_eeprom, ad9bit;
+
+ falcon_read ( efab, &nic_stat, FCN_NIC_STAT_REG );
+ falcon_read ( efab, &gpio_ctl, FCN_GPIO_CTL_REG_KER );
+ falcon_read ( efab, &ee_vpd_cfg, FCN_EE_VPD_CFG_REG );
+
+ /* determine if FLASH / EEPROM is present */
+ if ( ( efab->pci_revision >= FALCON_REV_B0 ) || efab->is_asic ) {
+ has_flash = EFAB_OWORD_FIELD ( nic_stat, FCN_SF_PRST );
+ has_eeprom = EFAB_OWORD_FIELD ( nic_stat, FCN_EE_PRST );
+ } else {
+ has_flash = EFAB_OWORD_FIELD ( gpio_ctl, FCN_FLASH_PRESENT );
+ has_eeprom = EFAB_OWORD_FIELD ( gpio_ctl, FCN_EEPROM_PRESENT );
+ }
+ ad9bit = EFAB_OWORD_FIELD ( ee_vpd_cfg, FCN_EE_VPD_EN_AD9_MODE );
+
+ /* Configure the SPI and I2C bus */
+ efab->spi_bus.rw = falcon_spi_rw;
+ init_i2c_bit_basher ( &efab->i2c_bb, &falcon_i2c_bit_ops );
+
+ /* Configure the EEPROM SPI device. Generally, an Atmel 25040
+ * (or similar) is used, but this is only possible if there is also
+ * a flash device present to store the boot-time chip configuration.
+ */
+ if ( has_eeprom ) {
+ if ( has_flash && ad9bit )
+ init_at25040 ( &efab->spi_eeprom );
+ else
+ init_mc25xx640 ( &efab->spi_eeprom );
+ falcon_init_spi_device ( efab, &efab->spi_eeprom );
+ }
+
+ /* Configure the FLASH SPI device */
+ if ( has_flash ) {
+ init_at25f1024 ( &efab->spi_flash );
+ falcon_init_spi_device ( efab, &efab->spi_flash );
+ }
+
+ EFAB_LOG ( "flash is %s, EEPROM is %s%s\n",
+ ( has_flash ? "present" : "absent" ),
+ ( has_eeprom ? "present " : "absent" ),
+ ( has_eeprom ? (ad9bit ? "(9bit)" : "(16bit)") : "") );
+
+ /* The device MUST have flash or eeprom */
+ if ( ! efab->spi ) {
+ EFAB_ERR ( "Device appears to have no flash or eeprom\n" );
+ return -EIO;
+ }
+
+ /* If the device has EEPROM attached, then advertise NVO space */
+ if ( has_eeprom ) {
+ nvo_init ( &efab->nvo, &efab->spi_eeprom.nvs, 0x100, 0xf0,
+ NULL, &efab->netdev->refcnt );
+ }
+
+ return 0;
+}
+
+static int
+falcon_probe_nvram ( struct efab_nic *efab )
+{
+ struct nvs_device *nvs = &efab->spi->nvs;
+ struct falcon_nv_extra nv;
+ int rc, board_revision;
+
+ /* Read the MAC address */
+ rc = nvs_read ( nvs, FALCON_MAC_ADDRESS_OFFSET,
+ efab->mac_addr, ETH_ALEN );
+ if ( rc )
+ return rc;
+
+ /* Poke through the NVRAM structure for the PHY type. */
+ rc = nvs_read ( nvs, SF_NV_CONFIG_BASE + SF_NV_CONFIG_EXTRA,
+ &nv, sizeof ( nv ) );
+ if ( rc )
+ return rc;
+
+ /* Handle each supported NVRAM version */
+ if ( ( le16_to_cpu ( nv.magicnumber ) == FCN_NV_MAGIC_NUMBER ) &&
+ ( le16_to_cpu ( nv.structure_version ) >= 2 ) ) {
+ struct falcon_nv_config_ver2* ver2 = &nv.ver_specific.ver2;
+
+ /* Get the PHY type */
+ efab->phy_addr = le16_to_cpu ( ver2->port0_phy_addr );
+ efab->phy_type = le16_to_cpu ( ver2->port0_phy_type );
+ board_revision = le16_to_cpu ( ver2->board_revision );
+ }
+ else {
+ EFAB_ERR ( "NVram is not recognised\n" );
+ return -EINVAL;
+ }
+
+ efab->board_type = BOARD_TYPE ( board_revision );
+
+ EFAB_TRACE ( "Falcon board %d phy %d @ addr %d\n",
+ efab->board_type, efab->phy_type, efab->phy_addr );
+
+ /* Patch in the board operations */
+ switch ( efab->board_type ) {
+ case EFAB_BOARD_SFE4001:
+ efab->board_op = &sfe4001_ops;
+ break;
+ case EFAB_BOARD_SFE4002:
+ efab->board_op = &sfe4002_ops;
+ break;
+ case EFAB_BOARD_SFE4003:
+ efab->board_op = &sfe4003_ops;
+ break;
+ default:
+ EFAB_ERR ( "Unrecognised board type\n" );
+ return -EINVAL;
+ }
+
+ /* Patch in MAC operations */
+ if ( efab->phy_10g )
+ efab->mac_op = &falcon_xmac_operations;
+ else
+ efab->mac_op = &falcon_gmac_operations;
+
+ /* Hook in the PHY ops */
+ switch ( efab->phy_type ) {
+ case PHY_TYPE_10XPRESS:
+ efab->phy_op = &falcon_tenxpress_phy_ops;
+ break;
+ case PHY_TYPE_CX4:
+ efab->phy_op = &falcon_xaui_phy_ops;
+ break;
+ case PHY_TYPE_XFP:
+ efab->phy_op = &falcon_xfp_phy_ops;
+ break;
+ case PHY_TYPE_CX4_RTMR:
+ efab->phy_op = &falcon_txc_phy_ops;
+ break;
+ case PHY_TYPE_PM8358:
+ efab->phy_op = &falcon_pm8358_phy_ops;
+ break;
+ case PHY_TYPE_1GIG_ALASKA:
+ efab->phy_op = &falcon_alaska_phy_ops;
+ break;
+ default:
+ EFAB_ERR ( "Unknown PHY type: %d\n", efab->phy_type );
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+falcon_init_sram ( struct efab_nic *efab )
+{
+ efab_oword_t reg;
+ int count;
+
+ /* use card in internal SRAM mode */
+ falcon_read ( efab, &reg, FCN_NIC_STAT_REG );
+ EFAB_SET_OWORD_FIELD ( reg, FCN_ONCHIP_SRAM, 1 );
+ falcon_write ( efab, &reg, FCN_NIC_STAT_REG );
+
+ /* Deactivate any external SRAM that might be present */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_GPIO1_OEN, 1,
+ FCN_GPIO1_OUT, 1 );
+ falcon_write ( efab, &reg, FCN_GPIO_CTL_REG_KER );
+
+ /* Initiate SRAM reset */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_SRAM_OOB_BT_INIT_EN, 1,
+ FCN_SRM_NUM_BANKS_AND_BANK_SIZE, 0 );
+ falcon_write ( efab, &reg, FCN_SRM_CFG_REG_KER );
+
+ /* Wait for SRAM reset to complete */
+ count = 0;
+ do {
+ /* SRAM reset is slow; expect around 16ms */
+ mdelay ( 20 );
+
+ /* Check for reset complete */
+ falcon_read ( efab, &reg, FCN_SRM_CFG_REG_KER );
+ if ( !EFAB_OWORD_FIELD ( reg, FCN_SRAM_OOB_BT_INIT_EN ) )
+ return 0;
+ } while (++count < 20); /* wait upto 0.4 sec */
+
+ EFAB_ERR ( "timed out waiting for SRAM reset\n");
+ return -ETIMEDOUT;
+}
+
+static void
+falcon_setup_nic ( struct efab_nic *efab )
+{
+ efab_dword_t timer_cmd;
+ efab_oword_t reg;
+ int tx_fc, xoff_thresh, xon_thresh;
+
+ /* bug5129: Clear the parity enables on the TX data fifos as
+ * they produce false parity errors because of timing issues
+ */
+ falcon_read ( efab, &reg, FCN_SPARE_REG_KER );
+ EFAB_SET_OWORD_FIELD ( reg, FCN_MEM_PERR_EN_TX_DATA, 0 );
+ falcon_write ( efab, &reg, FCN_SPARE_REG_KER );
+
+ /* Set up TX and RX descriptor caches in SRAM */
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_SRM_TX_DC_BASE_ADR, 0x130000 );
+ falcon_write ( efab, &reg, FCN_SRM_TX_DC_CFG_REG_KER );
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_TX_DC_SIZE, 1 /* 16 descriptors */ );
+ falcon_write ( efab, &reg, FCN_TX_DC_CFG_REG_KER );
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_SRM_RX_DC_BASE_ADR, 0x100000 );
+ falcon_write ( efab, &reg, FCN_SRM_RX_DC_CFG_REG_KER );
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_RX_DC_SIZE, 2 /* 32 descriptors */ );
+ falcon_write ( efab, &reg, FCN_RX_DC_CFG_REG_KER );
+
+ /* Set number of RSS CPUs
+ * bug7244: Increase filter depth to reduce RX_RESET likelyhood
+ */
+ EFAB_POPULATE_OWORD_5 ( reg,
+ FCN_NUM_KER, 0,
+ FCN_UDP_FULL_SRCH_LIMIT, 8,
+ FCN_UDP_WILD_SRCH_LIMIT, 8,
+ FCN_TCP_WILD_SRCH_LIMIT, 8,
+ FCN_TCP_FULL_SRCH_LIMIT, 8);
+ falcon_write ( efab, &reg, FCN_RX_FILTER_CTL_REG_KER );
+ udelay ( 1000 );
+
+ /* Setup RX. Wait for descriptor is broken and must
+ * be disabled. RXDP recovery shouldn't be needed, but is.
+ * disable ISCSI parsing because we don't need it
+ */
+ falcon_read ( efab, &reg, FCN_RX_SELF_RST_REG_KER );
+ EFAB_SET_OWORD_FIELD ( reg, FCN_RX_NODESC_WAIT_DIS, 1 );
+ EFAB_SET_OWORD_FIELD ( reg, FCN_RX_RECOVERY_EN, 1 );
+ EFAB_SET_OWORD_FIELD ( reg, FCN_RX_ISCSI_DIS, 1 );
+ falcon_write ( efab, &reg, FCN_RX_SELF_RST_REG_KER );
+
+ /* Determine recommended flow control settings. *
+ * Flow control is qualified on B0 and A1/1G, not on A1/10G */
+ if ( efab->pci_revision == FALCON_REV_B0 ) {
+ tx_fc = 1;
+ xoff_thresh = 54272; /* ~80Kb - 3*max MTU */
+ xon_thresh = 27648; /* ~3*max MTU */
+ }
+ else if ( !efab->phy_10g ) {
+ tx_fc = 1;
+ xoff_thresh = 2048;
+ xon_thresh = 512;
+ }
+ else {
+ tx_fc = xoff_thresh = xon_thresh = 0;
+ }
+
+ /* Setup TX and RX */
+ falcon_read ( efab, &reg, FCN_TX_CFG2_REG_KER );
+ EFAB_SET_OWORD_FIELD ( reg, FCN_TX_DIS_NON_IP_EV, 1 );
+ falcon_write ( efab, &reg, FCN_TX_CFG2_REG_KER );
+
+ falcon_read ( efab, &reg, FCN_RX_CFG_REG_KER );
+ EFAB_SET_OWORD_FIELD_VER ( efab, reg, FCN_RX_USR_BUF_SIZE,
+ (3*4096) / 32 );
+ if ( efab->pci_revision == FALCON_REV_B0)
+ EFAB_SET_OWORD_FIELD ( reg, FCN_RX_INGR_EN_B0, 1 );
+ EFAB_SET_OWORD_FIELD_VER ( efab, reg, FCN_RX_XON_MAC_TH,
+ xon_thresh / 256);
+ EFAB_SET_OWORD_FIELD_VER ( efab, reg, FCN_RX_XOFF_MAC_TH,
+ xoff_thresh / 256);
+ EFAB_SET_OWORD_FIELD_VER ( efab, reg, FCN_RX_XOFF_MAC_EN, tx_fc);
+ falcon_write ( efab, &reg, FCN_RX_CFG_REG_KER );
+
+ /* Set timer register */
+ EFAB_POPULATE_DWORD_2 ( timer_cmd,
+ FCN_TIMER_MODE, FCN_TIMER_MODE_DIS,
+ FCN_TIMER_VAL, 0 );
+ falcon_writel ( efab, &timer_cmd, FCN_TIMER_CMD_REG_KER );
+}
+
+static void
+falcon_init_resources ( struct efab_nic *efab )
+{
+ struct efab_ev_queue *ev_queue = &efab->ev_queue;
+ struct efab_rx_queue *rx_queue = &efab->rx_queue;
+ struct efab_tx_queue *tx_queue = &efab->tx_queue;
+
+ efab_oword_t reg;
+ int jumbo;
+
+ /* Initialise the ptrs */
+ tx_queue->read_ptr = tx_queue->write_ptr = 0;
+ rx_queue->read_ptr = rx_queue->write_ptr = 0;
+ ev_queue->read_ptr = 0;
+
+ /* Push the event queue to the hardware */
+ EFAB_POPULATE_OWORD_3 ( reg,
+ FCN_EVQ_EN, 1,
+ FCN_EVQ_SIZE, FQS(FCN_EVQ, EFAB_EVQ_SIZE),
+ FCN_EVQ_BUF_BASE_ID, ev_queue->entry.id );
+ falcon_write ( efab, &reg,
+ FCN_REVISION_REG ( efab, FCN_EVQ_PTR_TBL_KER ) );
+
+ /* Push the tx queue to the hardware */
+ EFAB_POPULATE_OWORD_8 ( reg,
+ FCN_TX_DESCQ_EN, 1,
+ FCN_TX_ISCSI_DDIG_EN, 0,
+ FCN_TX_ISCSI_DDIG_EN, 0,
+ FCN_TX_DESCQ_BUF_BASE_ID, tx_queue->entry.id,
+ FCN_TX_DESCQ_EVQ_ID, 0,
+ FCN_TX_DESCQ_SIZE, FQS(FCN_TX_DESCQ, EFAB_TXD_SIZE),
+ FCN_TX_DESCQ_TYPE, 0 /* kernel queue */,
+ FCN_TX_NON_IP_DROP_DIS_B0, 1 );
+ falcon_write ( efab, &reg,
+ FCN_REVISION_REG ( efab, FCN_TX_DESC_PTR_TBL_KER ) );
+
+ /* Push the rx queue to the hardware */
+ jumbo = ( efab->pci_revision == FALCON_REV_B0 ) ? 0 : 1;
+ EFAB_POPULATE_OWORD_8 ( reg,
+ FCN_RX_ISCSI_DDIG_EN, 0,
+ FCN_RX_ISCSI_HDIG_EN, 0,
+ FCN_RX_DESCQ_BUF_BASE_ID, rx_queue->entry.id,
+ FCN_RX_DESCQ_EVQ_ID, 0,
+ FCN_RX_DESCQ_SIZE, FQS(FCN_RX_DESCQ, EFAB_RXD_SIZE),
+ FCN_RX_DESCQ_TYPE, 0 /* kernel queue */,
+ FCN_RX_DESCQ_JUMBO, jumbo,
+ FCN_RX_DESCQ_EN, 1 );
+ falcon_write ( efab, &reg,
+ FCN_REVISION_REG ( efab, FCN_RX_DESC_PTR_TBL_KER ) );
+
+ /* Program INT_ADR_REG_KER */
+ EFAB_POPULATE_OWORD_1 ( reg,
+ FCN_INT_ADR_KER, virt_to_bus ( &efab->int_ker ) );
+ falcon_write ( efab, &reg, FCN_INT_ADR_REG_KER );
+
+ /* Ack the event queue */
+ falcon_eventq_read_ack ( efab, ev_queue );
+}
+
+static void
+falcon_fini_resources ( struct efab_nic *efab )
+{
+ efab_oword_t cmd;
+
+ /* Disable interrupts */
+ falcon_interrupts ( efab, 0, 0 );
+
+ /* Flush the dma queues */
+ EFAB_POPULATE_OWORD_2 ( cmd,
+ FCN_TX_FLUSH_DESCQ_CMD, 1,
+ FCN_TX_FLUSH_DESCQ, 0 );
+ falcon_write ( efab, &cmd,
+ FCN_REVISION_REG ( efab, FCN_TX_DESC_PTR_TBL_KER ) );
+
+ EFAB_POPULATE_OWORD_2 ( cmd,
+ FCN_RX_FLUSH_DESCQ_CMD, 1,
+ FCN_RX_FLUSH_DESCQ, 0 );
+ falcon_write ( efab, &cmd,
+ FCN_REVISION_REG ( efab, FCN_RX_DESC_PTR_TBL_KER ) );
+
+ mdelay ( 100 );
+
+ /* Remove descriptor rings from card */
+ EFAB_ZERO_OWORD ( cmd );
+ falcon_write ( efab, &cmd,
+ FCN_REVISION_REG ( efab, FCN_TX_DESC_PTR_TBL_KER ) );
+ falcon_write ( efab, &cmd,
+ FCN_REVISION_REG ( efab, FCN_RX_DESC_PTR_TBL_KER ) );
+ falcon_write ( efab, &cmd,
+ FCN_REVISION_REG ( efab, FCN_EVQ_PTR_TBL_KER ) );
+}
+
+/*******************************************************************************
+ *
+ *
+ * Hardware rx path
+ *
+ *
+ *******************************************************************************/
+
+static void
+falcon_build_rx_desc ( falcon_rx_desc_t *rxd, struct io_buffer *iob )
+{
+ EFAB_POPULATE_QWORD_2 ( *rxd,
+ FCN_RX_KER_BUF_SIZE, EFAB_RX_BUF_SIZE,
+ FCN_RX_KER_BUF_ADR, virt_to_bus ( iob->data ) );
+}
+
+static void
+falcon_notify_rx_desc ( struct efab_nic *efab, struct efab_rx_queue *rx_queue )
+{
+ efab_dword_t reg;
+ int ptr = rx_queue->write_ptr % EFAB_RXD_SIZE;
+
+ EFAB_POPULATE_DWORD_1 ( reg, FCN_RX_DESC_WPTR_DWORD, ptr );
+ falcon_writel ( efab, &reg, FCN_RX_DESC_UPD_REG_KER_DWORD );
+}
+
+
+/*******************************************************************************
+ *
+ *
+ * Hardware tx path
+ *
+ *
+ *******************************************************************************/
+
+static void
+falcon_build_tx_desc ( falcon_tx_desc_t *txd, struct io_buffer *iob )
+{
+ EFAB_POPULATE_QWORD_2 ( *txd,
+ FCN_TX_KER_BYTE_CNT, iob_len ( iob ),
+ FCN_TX_KER_BUF_ADR, virt_to_bus ( iob->data ) );
+}
+
+static void
+falcon_notify_tx_desc ( struct efab_nic *efab,
+ struct efab_tx_queue *tx_queue )
+{
+ efab_dword_t reg;
+ int ptr = tx_queue->write_ptr % EFAB_TXD_SIZE;
+
+ EFAB_POPULATE_DWORD_1 ( reg, FCN_TX_DESC_WPTR_DWORD, ptr );
+ falcon_writel ( efab, &reg, FCN_TX_DESC_UPD_REG_KER_DWORD );
+}
+
+
+/*******************************************************************************
+ *
+ *
+ * Software receive interface
+ *
+ *
+ *******************************************************************************/
+
+static int
+efab_fill_rx_queue ( struct efab_nic *efab,
+ struct efab_rx_queue *rx_queue )
+{
+ int fill_level = rx_queue->write_ptr - rx_queue->read_ptr;
+ int space = EFAB_NUM_RX_DESC - fill_level - 1;
+ int pushed = 0;
+
+ while ( space ) {
+ int buf_id = rx_queue->write_ptr % EFAB_NUM_RX_DESC;
+ int desc_id = rx_queue->write_ptr % EFAB_RXD_SIZE;
+ struct io_buffer *iob;
+ falcon_rx_desc_t *rxd;
+
+ assert ( rx_queue->buf[buf_id] == NULL );
+ iob = alloc_iob ( EFAB_RX_BUF_SIZE );
+ if ( !iob )
+ break;
+
+ EFAB_TRACE ( "pushing rx_buf[%d] iob %p data %p\n",
+ buf_id, iob, iob->data );
+
+ rx_queue->buf[buf_id] = iob;
+ rxd = rx_queue->ring + desc_id;
+ falcon_build_rx_desc ( rxd, iob );
+ ++rx_queue->write_ptr;
+ ++pushed;
+ --space;
+ }
+
+ if ( pushed ) {
+ /* Push the ptr to hardware */
+ falcon_notify_rx_desc ( efab, rx_queue );
+
+ fill_level = rx_queue->write_ptr - rx_queue->read_ptr;
+ EFAB_TRACE ( "pushed %d rx buffers to fill level %d\n",
+ pushed, fill_level );
+ }
+
+ if ( fill_level == 0 )
+ return -ENOMEM;
+ return 0;
+}
+
+static void
+efab_receive ( struct efab_nic *efab, unsigned int id, int len, int drop )
+{
+ struct efab_rx_queue *rx_queue = &efab->rx_queue;
+ struct io_buffer *iob;
+ unsigned int read_ptr = rx_queue->read_ptr % EFAB_RXD_SIZE;
+ unsigned int buf_ptr = rx_queue->read_ptr % EFAB_NUM_RX_DESC;
+
+ assert ( id == read_ptr );
+
+ /* Pop this rx buffer out of the software ring */
+ iob = rx_queue->buf[buf_ptr];
+ rx_queue->buf[buf_ptr] = NULL;
+
+ EFAB_TRACE ( "popping rx_buf[%d] iob %p data %p with %d bytes %s\n",
+ id, iob, iob->data, len, drop ? "bad" : "ok" );
+
+ /* Pass the packet up if required */
+ if ( drop )
+ free_iob ( iob );
+ else {
+ iob_put ( iob, len );
+ netdev_rx ( efab->netdev, iob );
+ }
+
+ ++rx_queue->read_ptr;
+}
+
+/*******************************************************************************
+ *
+ *
+ * Software transmit interface
+ *
+ *
+ *******************************************************************************/
+
+static int
+efab_transmit ( struct net_device *netdev, struct io_buffer *iob )
+{
+ struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_tx_queue *tx_queue = &efab->tx_queue;
+ int fill_level, space;
+ falcon_tx_desc_t *txd;
+ int buf_id;
+
+ fill_level = tx_queue->write_ptr - tx_queue->read_ptr;
+ space = EFAB_TXD_SIZE - fill_level - 1;
+ if ( space < 1 )
+ return -ENOBUFS;
+
+ /* Save the iobuffer for later completion */
+ buf_id = tx_queue->write_ptr % EFAB_TXD_SIZE;
+ assert ( tx_queue->buf[buf_id] == NULL );
+ tx_queue->buf[buf_id] = iob;
+
+ EFAB_TRACE ( "tx_buf[%d] for iob %p data %p len %zd\n",
+ buf_id, iob, iob->data, iob_len ( iob ) );
+
+ /* Form the descriptor, and push it to hardware */
+ txd = tx_queue->ring + buf_id;
+ falcon_build_tx_desc ( txd, iob );
+ ++tx_queue->write_ptr;
+ falcon_notify_tx_desc ( efab, tx_queue );
+
+ return 0;
+}
+
+static int
+efab_transmit_done ( struct efab_nic *efab, int id )
+{
+ struct efab_tx_queue *tx_queue = &efab->tx_queue;
+ unsigned int read_ptr, stop;
+
+ /* Complete all buffers from read_ptr up to and including id */
+ read_ptr = tx_queue->read_ptr % EFAB_TXD_SIZE;
+ stop = ( id + 1 ) % EFAB_TXD_SIZE;
+
+ while ( read_ptr != stop ) {
+ struct io_buffer *iob = tx_queue->buf[read_ptr];
+ assert ( iob );
+
+ /* Complete the tx buffer */
+ if ( iob )
+ netdev_tx_complete ( efab->netdev, iob );
+ tx_queue->buf[read_ptr] = NULL;
+
+ ++tx_queue->read_ptr;
+ read_ptr = tx_queue->read_ptr % EFAB_TXD_SIZE;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ *
+ *
+ * Hardware event path
+ *
+ *
+ *******************************************************************************/
+
+static void
+falcon_clear_interrupts ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+
+ if ( efab->pci_revision == FALCON_REV_B0 ) {
+ /* read the ISR */
+ falcon_readl( efab, &reg, INT_ISR0_B0 );
+ }
+ else {
+ /* write to the INT_ACK register */
+ falcon_writel ( efab, 0, FCN_INT_ACK_KER_REG_A1 );
+ mb();
+ falcon_readl ( efab, &reg,
+ WORK_AROUND_BROKEN_PCI_READS_REG_KER_A1 );
+ }
+}
+
+static void
+falcon_handle_event ( struct efab_nic *efab, falcon_event_t *evt )
+{
+ int ev_code, desc_ptr, len, drop;
+
+ /* Decode event */
+ ev_code = EFAB_QWORD_FIELD ( *evt, FCN_EV_CODE );
+ switch ( ev_code ) {
+ case FCN_TX_IP_EV_DECODE:
+ desc_ptr = EFAB_QWORD_FIELD ( *evt, FCN_TX_EV_DESC_PTR );
+ efab_transmit_done ( efab, desc_ptr );
+ break;
+
+ case FCN_RX_IP_EV_DECODE:
+ desc_ptr = EFAB_QWORD_FIELD ( *evt, FCN_RX_EV_DESC_PTR );
+ len = EFAB_QWORD_FIELD ( *evt, FCN_RX_EV_BYTE_CNT );
+ drop = !EFAB_QWORD_FIELD ( *evt, FCN_RX_EV_PKT_OK );
+
+ efab_receive ( efab, desc_ptr, len, drop );
+ break;
+
+ default:
+ EFAB_TRACE ( "Unknown event type %d\n", ev_code );
+ break;
+ }
+}
+
+/*******************************************************************************
+ *
+ *
+ * Software (polling) interrupt handler
+ *
+ *
+ *******************************************************************************/
+
+static void
+efab_poll ( struct net_device *netdev )
+{
+ struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_ev_queue *ev_queue = &efab->ev_queue;
+ struct efab_rx_queue *rx_queue = &efab->rx_queue;
+ falcon_event_t *evt;
+
+ /* Read the event queue by directly looking for events
+ * (we don't even bother to read the eventq write ptr) */
+ evt = ev_queue->ring + ev_queue->read_ptr;
+ while ( falcon_event_present ( evt ) ) {
+
+ EFAB_TRACE ( "Event at index 0x%x address %p is "
+ EFAB_QWORD_FMT "\n", ev_queue->read_ptr,
+ evt, EFAB_QWORD_VAL ( *evt ) );
+
+ falcon_handle_event ( efab, evt );
+
+ /* Clear the event */
+ EFAB_SET_QWORD ( *evt );
+
+ /* Move to the next event. We don't ack the event
+ * queue until the end */
+ ev_queue->read_ptr = ( ( ev_queue->read_ptr + 1 ) %
+ EFAB_EVQ_SIZE );
+ evt = ev_queue->ring + ev_queue->read_ptr;
+ }
+
+ /* Push more buffers if needed */
+ (void) efab_fill_rx_queue ( efab, rx_queue );
+
+ /* Clear any pending interrupts */
+ falcon_clear_interrupts ( efab );
+
+ /* Ack the event queue */
+ falcon_eventq_read_ack ( efab, ev_queue );
+}
+
+static void
+efab_irq ( struct net_device *netdev, int enable )
+{
+ struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_ev_queue *ev_queue = &efab->ev_queue;
+
+ switch ( enable ) {
+ case 0:
+ falcon_interrupts ( efab, 0, 0 );
+ break;
+ case 1:
+ falcon_interrupts ( efab, 1, 0 );
+ falcon_eventq_read_ack ( efab, ev_queue );
+ break;
+ case 2:
+ falcon_interrupts ( efab, 1, 1 );
+ break;
+ }
+}
+
+/*******************************************************************************
+ *
+ *
+ * Software open/close
+ *
+ *
+ *******************************************************************************/
+
+static void
+efab_free_resources ( struct efab_nic *efab )
+{
+ struct efab_ev_queue *ev_queue = &efab->ev_queue;
+ struct efab_rx_queue *rx_queue = &efab->rx_queue;
+ struct efab_tx_queue *tx_queue = &efab->tx_queue;
+ int i;
+
+ for ( i = 0; i < EFAB_NUM_RX_DESC; i++ ) {
+ if ( rx_queue->buf[i] )
+ free_iob ( rx_queue->buf[i] );
+ }
+
+ for ( i = 0; i < EFAB_TXD_SIZE; i++ ) {
+ if ( tx_queue->buf[i] )
+ netdev_tx_complete ( efab->netdev, tx_queue->buf[i] );
+ }
+
+ if ( rx_queue->ring )
+ falcon_free_special_buffer ( rx_queue->ring );
+
+ if ( tx_queue->ring )
+ falcon_free_special_buffer ( tx_queue->ring );
+
+ if ( ev_queue->ring )
+ falcon_free_special_buffer ( ev_queue->ring );
+
+ memset ( rx_queue, 0, sizeof ( *rx_queue ) );
+ memset ( tx_queue, 0, sizeof ( *tx_queue ) );
+ memset ( ev_queue, 0, sizeof ( *ev_queue ) );
+
+ /* Ensure subsequent buffer allocations start at id 0 */
+ efab->buffer_head = 0;
+}
+
+static int
+efab_alloc_resources ( struct efab_nic *efab )
+{
+ struct efab_ev_queue *ev_queue = &efab->ev_queue;
+ struct efab_rx_queue *rx_queue = &efab->rx_queue;
+ struct efab_tx_queue *tx_queue = &efab->tx_queue;
+ size_t bytes;
+
+ /* Allocate the hardware event queue */
+ bytes = sizeof ( falcon_event_t ) * EFAB_TXD_SIZE;
+ ev_queue->ring = falcon_alloc_special_buffer ( efab, bytes,
+ &ev_queue->entry );
+ if ( !ev_queue->ring )
+ goto fail1;
+
+ /* Initialise the hardware event queue */
+ memset ( ev_queue->ring, 0xff, bytes );
+
+ /* Allocate the hardware tx queue */
+ bytes = sizeof ( falcon_tx_desc_t ) * EFAB_TXD_SIZE;
+ tx_queue->ring = falcon_alloc_special_buffer ( efab, bytes,
+ &tx_queue->entry );
+ if ( ! tx_queue->ring )
+ goto fail2;
+
+ /* Allocate the hardware rx queue */
+ bytes = sizeof ( falcon_rx_desc_t ) * EFAB_RXD_SIZE;
+ rx_queue->ring = falcon_alloc_special_buffer ( efab, bytes,
+ &rx_queue->entry );
+ if ( ! rx_queue->ring )
+ goto fail3;
+
+ return 0;
+
+fail3:
+ falcon_free_special_buffer ( tx_queue->ring );
+ tx_queue->ring = NULL;
+fail2:
+ falcon_free_special_buffer ( ev_queue->ring );
+ ev_queue->ring = NULL;
+fail1:
+ return -ENOMEM;
+}
+
+static int
+efab_init_mac ( struct efab_nic *efab )
+{
+ int count, rc;
+
+ /* This can take several seconds */
+ EFAB_LOG ( "Waiting for link..\n" );
+ for ( count=0; count<5; count++ ) {
+ rc = efab->mac_op->init ( efab );
+ if ( rc ) {
+ EFAB_ERR ( "Failed reinitialising MAC, error %s\n",
+ strerror ( rc ));
+ return rc;
+ }
+
+ /* Sleep for 2s to wait for the link to settle, either
+ * because we want to use it, or because we're about
+ * to reset the mac anyway
+ */
+ sleep ( 2 );
+
+ if ( ! efab->link_up ) {
+ EFAB_ERR ( "!\n" );
+ continue;
+ }
+
+ EFAB_LOG ( "\n%dMbps %s-duplex\n",
+ ( efab->link_options & LPA_EF_10000 ? 10000 :
+ ( efab->link_options & LPA_EF_1000 ? 1000 :
+ ( efab->link_options & LPA_100 ? 100 : 10 ) ) ),
+ ( efab->link_options & LPA_EF_DUPLEX ?
+ "full" : "half" ) );
+
+ /* TODO: Move link state handling to the poll() routine */
+ netdev_link_up ( efab->netdev );
+ return 0;
+ }
+
+ EFAB_ERR ( "timed initialising MAC\n" );
+ return -ETIMEDOUT;
+}
+
+static void
+efab_close ( struct net_device *netdev )
+{
+ struct efab_nic *efab = netdev_priv ( netdev );
+
+ falcon_fini_resources ( efab );
+ efab_free_resources ( efab );
+ efab->board_op->fini ( efab );
+ falcon_reset ( efab );
+}
+
+static int
+efab_open ( struct net_device *netdev )
+{
+ struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_rx_queue *rx_queue = &efab->rx_queue;
+ int rc;
+
+ rc = falcon_reset ( efab );
+ if ( rc )
+ goto fail1;
+
+ rc = efab->board_op->init ( efab );
+ if ( rc )
+ goto fail2;
+
+ rc = falcon_init_sram ( efab );
+ if ( rc )
+ goto fail3;
+
+ /* Configure descriptor caches before pushing hardware queues */
+ falcon_setup_nic ( efab );
+
+ rc = efab_alloc_resources ( efab );
+ if ( rc )
+ goto fail4;
+
+ falcon_init_resources ( efab );
+
+ /* Push rx buffers */
+ rc = efab_fill_rx_queue ( efab, rx_queue );
+ if ( rc )
+ goto fail5;
+
+ /* Try and bring the interface up */
+ rc = efab_init_mac ( efab );
+ if ( rc )
+ goto fail6;
+
+ return 0;
+
+fail6:
+fail5:
+ efab_free_resources ( efab );
+fail4:
+fail3:
+ efab->board_op->fini ( efab );
+fail2:
+ falcon_reset ( efab );
+fail1:
+ return rc;
+}
+
+static struct net_device_operations efab_operations = {
+ .open = efab_open,
+ .close = efab_close,
+ .transmit = efab_transmit,
+ .poll = efab_poll,
+ .irq = efab_irq,
+};
+
+static void
+efab_remove ( struct pci_device *pci )
+{
+ struct net_device *netdev = pci_get_drvdata ( pci );
+ struct efab_nic *efab = netdev_priv ( netdev );
+
+ if ( efab->membase ) {
+ falcon_reset ( efab );
+
+ iounmap ( efab->membase );
+ efab->membase = NULL;
+ }
+
+ if ( efab->nvo.nvs ) {
+ unregister_nvo ( &efab->nvo );
+ efab->nvo.nvs = NULL;
+ }
+
+ unregister_netdev ( netdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+static int
+efab_probe ( struct pci_device *pci )
+{
+ struct net_device *netdev;
+ struct efab_nic *efab;
+ unsigned long mmio_start, mmio_len;
+ int rc;
+
+ /* Create the network adapter */
+ netdev = alloc_etherdev ( sizeof ( struct efab_nic ) );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ goto fail1;
+ }
+
+ /* Initialise the network adapter, and initialise private storage */
+ netdev_init ( netdev, &efab_operations );
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+
+ efab = netdev_priv ( netdev );
+ memset ( efab, 0, sizeof ( *efab ) );
+ efab->netdev = netdev;
+
+ /* Get iobase/membase */
+ mmio_start = pci_bar_start ( pci, PCI_BASE_ADDRESS_2 );
+ mmio_len = pci_bar_size ( pci, PCI_BASE_ADDRESS_2 );
+ efab->membase = ioremap ( mmio_start, mmio_len );
+ EFAB_TRACE ( "BAR of %lx bytes at phys %lx mapped at %p\n",
+ mmio_len, mmio_start, efab->membase );
+
+ /* Enable the PCI device */
+ adjust_pci_device ( pci );
+ efab->iobase = pci->ioaddr & ~3;
+
+ /* Determine the NIC variant */
+ falcon_probe_nic_variant ( efab, pci );
+
+ /* Read the SPI interface and determine the MAC address,
+ * and the board and phy variant. Hook in the op tables */
+ rc = falcon_probe_spi ( efab );
+ if ( rc )
+ goto fail2;
+ rc = falcon_probe_nvram ( efab );
+ if ( rc )
+ goto fail3;
+
+ memcpy ( netdev->hw_addr, efab->mac_addr, ETH_ALEN );
+
+ rc = register_netdev ( netdev );
+ if ( rc )
+ goto fail4;
+ netdev_link_up ( netdev );
+
+ /* Advertise non-volatile storage */
+ if ( efab->nvo.nvs ) {
+ rc = register_nvo ( &efab->nvo, netdev_settings ( netdev ) );
+ if ( rc )
+ goto fail5;
+ }
+
+ EFAB_LOG ( "Found %s EtherFabric %s %s revision %d\n", pci->id->name,
+ efab->is_asic ? "ASIC" : "FPGA",
+ efab->phy_10g ? "10G" : "1G",
+ efab->pci_revision );
+
+ return 0;
+
+fail5:
+ unregister_netdev ( netdev );
+fail4:
+fail3:
+fail2:
+ iounmap ( efab->membase );
+ efab->membase = NULL;
+ netdev_put ( netdev );
+fail1:
+ return rc;
+}
+
+
+static struct pci_device_id efab_nics[] = {
+ PCI_ROM(0x1924, 0x0703, "falcon", "EtherFabric Falcon", 0),
+ PCI_ROM(0x1924, 0x0710, "falconb0", "EtherFabric FalconB0", 0),
+};
+
+struct pci_driver etherfabric_driver __pci_driver = {
+ .ids = efab_nics,
+ .id_count = sizeof ( efab_nics ) / sizeof ( efab_nics[0] ),
+ .probe = efab_probe,
+ .remove = efab_remove,
+};
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/etherfabric.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/etherfabric.h
new file mode 100644
index 00000000..9657eb7e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/etherfabric.h
@@ -0,0 +1,553 @@
+/**************************************************************************
+ *
+ * GPL net driver for Level 5 Etherfabric network cards
+ *
+ * Written by Michael Brown <mbrown@fensystems.co.uk>
+ *
+ * Copyright Fen Systems Ltd. 2005
+ * Copyright Level 5 Networks Inc. 2005
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice. This file is not a complete program and may only be used
+ * when the entire operating system is licensed under the GPL.
+ *
+ **************************************************************************
+ */
+
+FILE_LICENCE ( GPL_ANY );
+
+#ifndef EFAB_BITFIELD_H
+#define EFAB_BITFIELD_H
+
+/** @file
+ *
+ * Etherfabric bitfield access
+ *
+ * Etherfabric NICs make extensive use of bitfields up to 128 bits
+ * wide. Since there is no native 128-bit datatype on most systems,
+ * and since 64-bit datatypes are inefficient on 32-bit systems and
+ * vice versa, we wrap accesses in a way that uses the most efficient
+ * datatype.
+ *
+ * The NICs are PCI devices and therefore little-endian. Since most
+ * of the quantities that we deal with are DMAed to/from host memory,
+ * we define our datatypes (efab_oword_t, efab_qword_t and
+ * efab_dword_t) to be little-endian.
+ *
+ * In the less common case of using PIO for individual register
+ * writes, we construct the little-endian datatype in host memory and
+ * then use non-swapping equivalents of writel/writeq, rather than
+ * constructing a native-endian datatype and relying on the implicit
+ * byte-swapping done by writel/writeq. (We use a similar strategy
+ * for register reads.)
+ */
+
+/** Dummy field low bit number */
+#define EFAB_DUMMY_FIELD_LBN 0
+/** Dummy field width */
+#define EFAB_DUMMY_FIELD_WIDTH 0
+/** Dword 0 low bit number */
+#define EFAB_DWORD_0_LBN 0
+/** Dword 0 width */
+#define EFAB_DWORD_0_WIDTH 32
+/** Dword 1 low bit number */
+#define EFAB_DWORD_1_LBN 32
+/** Dword 1 width */
+#define EFAB_DWORD_1_WIDTH 32
+/** Dword 2 low bit number */
+#define EFAB_DWORD_2_LBN 64
+/** Dword 2 width */
+#define EFAB_DWORD_2_WIDTH 32
+/** Dword 3 low bit number */
+#define EFAB_DWORD_3_LBN 96
+/** Dword 3 width */
+#define EFAB_DWORD_3_WIDTH 32
+
+/** Specified attribute (e.g. LBN) of the specified field */
+#define EFAB_VAL(field,attribute) field ## _ ## attribute
+/** Low bit number of the specified field */
+#define EFAB_LOW_BIT( field ) EFAB_VAL ( field, LBN )
+/** Bit width of the specified field */
+#define EFAB_WIDTH( field ) EFAB_VAL ( field, WIDTH )
+/** High bit number of the specified field */
+#define EFAB_HIGH_BIT(field) ( EFAB_LOW_BIT(field) + EFAB_WIDTH(field) - 1 )
+/** Mask equal in width to the specified field.
+ *
+ * For example, a field with width 5 would have a mask of 0x1f.
+ *
+ * The maximum width mask that can be generated is 64 bits.
+ */
+#define EFAB_MASK64( field ) \
+ ( EFAB_WIDTH(field) == 64 ? ~( ( uint64_t ) 0 ) : \
+ ( ( ( ( ( uint64_t ) 1 ) << EFAB_WIDTH(field) ) ) - 1 ) )
+
+/** Mask equal in width to the specified field.
+ *
+ * For example, a field with width 5 would have a mask of 0x1f.
+ *
+ * The maximum width mask that can be generated is 32 bits. Use
+ * EFAB_MASK64 for higher width fields.
+ */
+#define EFAB_MASK32( field ) \
+ ( EFAB_WIDTH(field) == 32 ? ~( ( uint32_t ) 0 ) : \
+ ( ( ( ( ( uint32_t ) 1 ) << EFAB_WIDTH(field) ) ) - 1 ) )
+
+/** A doubleword (i.e. 4 byte) datatype
+ *
+ * This datatype is defined to be little-endian.
+ */
+typedef union efab_dword {
+ uint32_t u32[1];
+ uint32_t opaque; /* For bitwise operations between two efab_dwords */
+} efab_dword_t;
+
+/** A quadword (i.e. 8 byte) datatype
+ *
+ * This datatype is defined to be little-endian.
+ */
+typedef union efab_qword {
+ uint64_t u64[1];
+ uint32_t u32[2];
+ efab_dword_t dword[2];
+} efab_qword_t;
+
+/**
+ * An octword (eight-word, i.e. 16 byte) datatype
+ *
+ * This datatype is defined to be little-endian.
+ */
+typedef union efab_oword {
+ uint64_t u64[2];
+ efab_qword_t qword[2];
+ uint32_t u32[4];
+ efab_dword_t dword[4];
+} efab_oword_t;
+
+/** Format string for printing an efab_dword_t */
+#define EFAB_DWORD_FMT "%08x"
+
+/** Format string for printing an efab_qword_t */
+#define EFAB_QWORD_FMT "%08x:%08x"
+
+/** Format string for printing an efab_oword_t */
+#define EFAB_OWORD_FMT "%08x:%08x:%08x:%08x"
+
+/** printk parameters for printing an efab_dword_t */
+#define EFAB_DWORD_VAL(dword) \
+ ( ( unsigned int ) le32_to_cpu ( (dword).u32[0] ) )
+
+/** printk parameters for printing an efab_qword_t */
+#define EFAB_QWORD_VAL(qword) \
+ ( ( unsigned int ) le32_to_cpu ( (qword).u32[1] ) ), \
+ ( ( unsigned int ) le32_to_cpu ( (qword).u32[0] ) )
+
+/** printk parameters for printing an efab_oword_t */
+#define EFAB_OWORD_VAL(oword) \
+ ( ( unsigned int ) le32_to_cpu ( (oword).u32[3] ) ), \
+ ( ( unsigned int ) le32_to_cpu ( (oword).u32[2] ) ), \
+ ( ( unsigned int ) le32_to_cpu ( (oword).u32[1] ) ), \
+ ( ( unsigned int ) le32_to_cpu ( (oword).u32[0] ) )
+
+/**
+ * Extract bit field portion [low,high) from the native-endian element
+ * which contains bits [min,max).
+ *
+ * For example, suppose "element" represents the high 32 bits of a
+ * 64-bit value, and we wish to extract the bits belonging to the bit
+ * field occupying bits 28-45 of this 64-bit value.
+ *
+ * Then EFAB_EXTRACT ( element, 32, 63, 28, 45 ) would give
+ *
+ * ( element ) << 4
+ *
+ * The result will contain the relevant bits filled in in the range
+ * [0,high-low), with garbage in bits [high-low+1,...).
+ */
+#define EFAB_EXTRACT_NATIVE( native_element, min ,max ,low ,high ) \
+ ( ( ( low > max ) || ( high < min ) ) ? 0 : \
+ ( ( low > min ) ? \
+ ( (native_element) >> ( low - min ) ) : \
+ ( (native_element) << ( min - low ) ) ) )
+
+/**
+ * Extract bit field portion [low,high) from the 64-bit little-endian
+ * element which contains bits [min,max)
+ */
+#define EFAB_EXTRACT64( element, min, max, low, high ) \
+ EFAB_EXTRACT_NATIVE ( le64_to_cpu(element), min, max, low, high )
+
+/**
+ * Extract bit field portion [low,high) from the 32-bit little-endian
+ * element which contains bits [min,max)
+ */
+#define EFAB_EXTRACT32( element, min, max, low, high ) \
+ EFAB_EXTRACT_NATIVE ( le32_to_cpu(element), min, max, low, high )
+
+#define EFAB_EXTRACT_OWORD64( oword, low, high ) \
+ ( EFAB_EXTRACT64 ( (oword).u64[0], 0, 63, low, high ) | \
+ EFAB_EXTRACT64 ( (oword).u64[1], 64, 127, low, high ) )
+
+#define EFAB_EXTRACT_QWORD64( qword, low, high ) \
+ ( EFAB_EXTRACT64 ( (qword).u64[0], 0, 63, low, high ) )
+
+#define EFAB_EXTRACT_OWORD32( oword, low, high ) \
+ ( EFAB_EXTRACT32 ( (oword).u32[0], 0, 31, low, high ) | \
+ EFAB_EXTRACT32 ( (oword).u32[1], 32, 63, low, high ) | \
+ EFAB_EXTRACT32 ( (oword).u32[2], 64, 95, low, high ) | \
+ EFAB_EXTRACT32 ( (oword).u32[3], 96, 127, low, high ) )
+
+#define EFAB_EXTRACT_QWORD32( qword, low, high ) \
+ ( EFAB_EXTRACT32 ( (qword).u32[0], 0, 31, low, high ) | \
+ EFAB_EXTRACT32 ( (qword).u32[1], 32, 63, low, high ) )
+
+#define EFAB_EXTRACT_DWORD( dword, low, high ) \
+ ( EFAB_EXTRACT32 ( (dword).u32[0], 0, 31, low, high ) )
+
+#define EFAB_OWORD_FIELD64( oword, field ) \
+ ( EFAB_EXTRACT_OWORD64 ( oword, EFAB_LOW_BIT ( field ), \
+ EFAB_HIGH_BIT ( field ) ) & \
+ EFAB_MASK64 ( field ) )
+
+#define EFAB_QWORD_FIELD64( qword, field ) \
+ ( EFAB_EXTRACT_QWORD64 ( qword, EFAB_LOW_BIT ( field ), \
+ EFAB_HIGH_BIT ( field ) ) & \
+ EFAB_MASK64 ( field ) )
+
+#define EFAB_OWORD_FIELD32( oword, field ) \
+ ( EFAB_EXTRACT_OWORD32 ( oword, EFAB_LOW_BIT ( field ), \
+ EFAB_HIGH_BIT ( field ) ) & \
+ EFAB_MASK32 ( field ) )
+
+#define EFAB_QWORD_FIELD32( qword, field ) \
+ ( EFAB_EXTRACT_QWORD32 ( qword, EFAB_LOW_BIT ( field ), \
+ EFAB_HIGH_BIT ( field ) ) & \
+ EFAB_MASK32 ( field ) )
+
+#define EFAB_DWORD_FIELD( dword, field ) \
+ ( EFAB_EXTRACT_DWORD ( dword, EFAB_LOW_BIT ( field ), \
+ EFAB_HIGH_BIT ( field ) ) & \
+ EFAB_MASK32 ( field ) )
+
+#define EFAB_OWORD_IS_ZERO64( oword ) \
+ ( ! ( (oword).u64[0] || (oword).u64[1] ) )
+
+#define EFAB_QWORD_IS_ZERO64( qword ) \
+ ( ! ( (qword).u64[0] ) )
+
+#define EFAB_OWORD_IS_ZERO32( oword ) \
+ ( ! ( (oword).u32[0] || (oword).u32[1] || \
+ (oword).u32[2] || (oword).u32[3] ) )
+
+#define EFAB_QWORD_IS_ZERO32( qword ) \
+ ( ! ( (qword).u32[0] || (qword).u32[1] ) )
+
+#define EFAB_DWORD_IS_ZERO( dword ) \
+ ( ! ( (dword).u32[0] ) )
+
+#define EFAB_OWORD_IS_ALL_ONES64( oword ) \
+ ( ( (oword).u64[0] & (oword).u64[1] ) == ~( ( uint64_t ) 0 ) )
+
+#define EFAB_QWORD_IS_ALL_ONES64( qword ) \
+ ( (qword).u64[0] == ~( ( uint64_t ) 0 ) )
+
+#define EFAB_OWORD_IS_ALL_ONES32( oword ) \
+ ( ( (oword).u32[0] & (oword).u32[1] & \
+ (oword).u32[2] & (oword).u32[3] ) == ~( ( uint32_t ) 0 ) )
+
+#define EFAB_QWORD_IS_ALL_ONES32( qword ) \
+ ( ( (qword).u32[0] & (qword).u32[1] ) == ~( ( uint32_t ) 0 ) )
+
+#define EFAB_DWORD_IS_ALL_ONES( dword ) \
+ ( (dword).u32[0] == ~( ( uint32_t ) 0 ) )
+
+#if ( BITS_PER_LONG == 64 )
+#define EFAB_OWORD_FIELD EFAB_OWORD_FIELD64
+#define EFAB_QWORD_FIELD EFAB_QWORD_FIELD64
+#define EFAB_OWORD_IS_ZERO EFAB_OWORD_IS_ZERO64
+#define EFAB_QWORD_IS_ZERO EFAB_QWORD_IS_ZERO64
+#define EFAB_OWORD_IS_ALL_ONES EFAB_OWORD_IS_ALL_ONES64
+#define EFAB_QWORD_IS_ALL_ONES EFAB_QWORD_IS_ALL_ONES64
+#else
+#define EFAB_OWORD_FIELD EFAB_OWORD_FIELD32
+#define EFAB_QWORD_FIELD EFAB_QWORD_FIELD32
+#define EFAB_OWORD_IS_ZERO EFAB_OWORD_IS_ZERO32
+#define EFAB_QWORD_IS_ZERO EFAB_QWORD_IS_ZERO32
+#define EFAB_OWORD_IS_ALL_ONES EFAB_OWORD_IS_ALL_ONES32
+#define EFAB_QWORD_IS_ALL_ONES EFAB_QWORD_IS_ALL_ONES32
+#endif
+
+/**
+ * Construct bit field portion
+ *
+ * Creates the portion of the bit field [low,high) that lies within
+ * the range [min,max).
+ */
+#define EFAB_INSERT_NATIVE64( min, max, low, high, value ) \
+ ( ( ( low > max ) || ( high < min ) ) ? 0 : \
+ ( ( low > min ) ? \
+ ( ( ( uint64_t ) (value) ) << ( low - min ) ) : \
+ ( ( ( uint64_t ) (value) ) >> ( min - low ) ) ) )
+
+#define EFAB_INSERT_NATIVE32( min, max, low, high, value ) \
+ ( ( ( low > max ) || ( high < min ) ) ? 0 : \
+ ( ( low > min ) ? \
+ ( ( ( uint32_t ) (value) ) << ( low - min ) ) : \
+ ( ( ( uint32_t ) (value) ) >> ( min - low ) ) ) )
+
+#define EFAB_INSERT_NATIVE( min, max, low, high, value ) \
+ ( ( ( ( max - min ) >= 32 ) || \
+ ( ( high - low ) >= 32 ) ) \
+ ? EFAB_INSERT_NATIVE64 ( min, max, low, high, value ) \
+ : EFAB_INSERT_NATIVE32 ( min, max, low, high, value ) )
+
+/**
+ * Construct bit field portion
+ *
+ * Creates the portion of the named bit field that lies within the
+ * range [min,max).
+ */
+#define EFAB_INSERT_FIELD_NATIVE( min, max, field, value ) \
+ EFAB_INSERT_NATIVE ( min, max, EFAB_LOW_BIT ( field ), \
+ EFAB_HIGH_BIT ( field ), value )
+
+/**
+ * Construct bit field
+ *
+ * Creates the portion of the named bit fields that lie within the
+ * range [min,max).
+ */
+#define EFAB_INSERT_FIELDS_NATIVE( min, max, \
+ field1, value1, \
+ field2, value2, \
+ field3, value3, \
+ field4, value4, \
+ field5, value5, \
+ field6, value6, \
+ field7, value7, \
+ field8, value8, \
+ field9, value9, \
+ field10, value10 ) \
+ ( EFAB_INSERT_FIELD_NATIVE ( min, max, field1, value1 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field2, value2 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field3, value3 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field4, value4 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field5, value5 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field6, value6 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field7, value7 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field8, value8 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field9, value9 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field10, value10 ) )
+
+#define EFAB_INSERT_FIELDS64( ... ) \
+ cpu_to_le64 ( EFAB_INSERT_FIELDS_NATIVE ( __VA_ARGS__ ) )
+
+#define EFAB_INSERT_FIELDS32( ... ) \
+ cpu_to_le32 ( EFAB_INSERT_FIELDS_NATIVE ( __VA_ARGS__ ) )
+
+#define EFAB_POPULATE_OWORD64( oword, ... ) do { \
+ (oword).u64[0] = EFAB_INSERT_FIELDS64 ( 0, 63, __VA_ARGS__ );\
+ (oword).u64[1] = EFAB_INSERT_FIELDS64 ( 64, 127, __VA_ARGS__ );\
+ } while ( 0 )
+
+#define EFAB_POPULATE_QWORD64( qword, ... ) do { \
+ (qword).u64[0] = EFAB_INSERT_FIELDS64 ( 0, 63, __VA_ARGS__ );\
+ } while ( 0 )
+
+#define EFAB_POPULATE_OWORD32( oword, ... ) do { \
+ (oword).u32[0] = EFAB_INSERT_FIELDS32 ( 0, 31, __VA_ARGS__ );\
+ (oword).u32[1] = EFAB_INSERT_FIELDS32 ( 32, 63, __VA_ARGS__ );\
+ (oword).u32[2] = EFAB_INSERT_FIELDS32 ( 64, 95, __VA_ARGS__ );\
+ (oword).u32[3] = EFAB_INSERT_FIELDS32 ( 96, 127, __VA_ARGS__ );\
+ } while ( 0 )
+
+#define EFAB_POPULATE_QWORD32( qword, ... ) do { \
+ (qword).u32[0] = EFAB_INSERT_FIELDS32 ( 0, 31, __VA_ARGS__ );\
+ (qword).u32[1] = EFAB_INSERT_FIELDS32 ( 32, 63, __VA_ARGS__ );\
+ } while ( 0 )
+
+#define EFAB_POPULATE_DWORD( dword, ... ) do { \
+ (dword).u32[0] = EFAB_INSERT_FIELDS32 ( 0, 31, __VA_ARGS__ );\
+ } while ( 0 )
+
+#if ( BITS_PER_LONG == 64 )
+#define EFAB_POPULATE_OWORD EFAB_POPULATE_OWORD64
+#define EFAB_POPULATE_QWORD EFAB_POPULATE_QWORD64
+#else
+#define EFAB_POPULATE_OWORD EFAB_POPULATE_OWORD32
+#define EFAB_POPULATE_QWORD EFAB_POPULATE_QWORD32
+#endif
+
+/* Populate an octword field with various numbers of arguments */
+#define EFAB_POPULATE_OWORD_10 EFAB_POPULATE_OWORD
+#define EFAB_POPULATE_OWORD_9( oword, ... ) \
+ EFAB_POPULATE_OWORD_10 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_8( oword, ... ) \
+ EFAB_POPULATE_OWORD_9 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_7( oword, ... ) \
+ EFAB_POPULATE_OWORD_8 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_6( oword, ... ) \
+ EFAB_POPULATE_OWORD_7 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_5( oword, ... ) \
+ EFAB_POPULATE_OWORD_6 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_4( oword, ... ) \
+ EFAB_POPULATE_OWORD_5 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_3( oword, ... ) \
+ EFAB_POPULATE_OWORD_4 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_2( oword, ... ) \
+ EFAB_POPULATE_OWORD_3 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_1( oword, ... ) \
+ EFAB_POPULATE_OWORD_2 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_ZERO_OWORD( oword ) \
+ EFAB_POPULATE_OWORD_1 ( oword, EFAB_DUMMY_FIELD, 0 )
+#define EFAB_SET_OWORD( oword ) \
+ EFAB_POPULATE_OWORD_4 ( oword, \
+ EFAB_DWORD_0, 0xffffffff, \
+ EFAB_DWORD_1, 0xffffffff, \
+ EFAB_DWORD_2, 0xffffffff, \
+ EFAB_DWORD_3, 0xffffffff )
+
+/* Populate a quadword field with various numbers of arguments */
+#define EFAB_POPULATE_QWORD_10 EFAB_POPULATE_QWORD
+#define EFAB_POPULATE_QWORD_9( qword, ... ) \
+ EFAB_POPULATE_QWORD_10 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_8( qword, ... ) \
+ EFAB_POPULATE_QWORD_9 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_7( qword, ... ) \
+ EFAB_POPULATE_QWORD_8 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_6( qword, ... ) \
+ EFAB_POPULATE_QWORD_7 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_5( qword, ... ) \
+ EFAB_POPULATE_QWORD_6 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_4( qword, ... ) \
+ EFAB_POPULATE_QWORD_5 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_3( qword, ... ) \
+ EFAB_POPULATE_QWORD_4 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_2( qword, ... ) \
+ EFAB_POPULATE_QWORD_3 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_1( qword, ... ) \
+ EFAB_POPULATE_QWORD_2 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_ZERO_QWORD( qword ) \
+ EFAB_POPULATE_QWORD_1 ( qword, EFAB_DUMMY_FIELD, 0 )
+#define EFAB_SET_QWORD( qword ) \
+ EFAB_POPULATE_QWORD_2 ( qword, \
+ EFAB_DWORD_0, 0xffffffff, \
+ EFAB_DWORD_1, 0xffffffff )
+
+/* Populate a dword field with various numbers of arguments */
+#define EFAB_POPULATE_DWORD_10 EFAB_POPULATE_DWORD
+#define EFAB_POPULATE_DWORD_9( dword, ... ) \
+ EFAB_POPULATE_DWORD_10 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_8( dword, ... ) \
+ EFAB_POPULATE_DWORD_9 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_7( dword, ... ) \
+ EFAB_POPULATE_DWORD_8 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_6( dword, ... ) \
+ EFAB_POPULATE_DWORD_7 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_5( dword, ... ) \
+ EFAB_POPULATE_DWORD_6 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_4( dword, ... ) \
+ EFAB_POPULATE_DWORD_5 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_3( dword, ... ) \
+ EFAB_POPULATE_DWORD_4 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_2( dword, ... ) \
+ EFAB_POPULATE_DWORD_3 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_1( dword, ... ) \
+ EFAB_POPULATE_DWORD_2 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_ZERO_DWORD( dword ) \
+ EFAB_POPULATE_DWORD_1 ( dword, EFAB_DUMMY_FIELD, 0 )
+#define EFAB_SET_DWORD( dword ) \
+ EFAB_POPULATE_DWORD_1 ( dword, EFAB_DWORD_0, 0xffffffff )
+
+/*
+ * Modify a named field within an already-populated structure. Used
+ * for read-modify-write operations.
+ *
+ */
+
+#define EFAB_INSERT_FIELD64( ... ) \
+ cpu_to_le64 ( EFAB_INSERT_FIELD_NATIVE ( __VA_ARGS__ ) )
+
+#define EFAB_INSERT_FIELD32( ... ) \
+ cpu_to_le32 ( EFAB_INSERT_FIELD_NATIVE ( __VA_ARGS__ ) )
+
+#define EFAB_INPLACE_MASK64( min, max, field ) \
+ EFAB_INSERT_FIELD64 ( min, max, field, EFAB_MASK64 ( field ) )
+
+#define EFAB_INPLACE_MASK32( min, max, field ) \
+ EFAB_INSERT_FIELD32 ( min, max, field, EFAB_MASK32 ( field ) )
+
+#define EFAB_SET_OWORD_FIELD64( oword, field, value ) do { \
+ (oword).u64[0] = ( ( (oword).u64[0] \
+ & ~EFAB_INPLACE_MASK64 ( 0, 63, field ) ) \
+ | EFAB_INSERT_FIELD64 ( 0, 63, field, value ) ); \
+ (oword).u64[1] = ( ( (oword).u64[1] \
+ & ~EFAB_INPLACE_MASK64 ( 64, 127, field ) ) \
+ | EFAB_INSERT_FIELD64 ( 64, 127, field, value ) ); \
+ } while ( 0 )
+
+#define EFAB_SET_QWORD_FIELD64( qword, field, value ) do { \
+ (qword).u64[0] = ( ( (qword).u64[0] \
+ & ~EFAB_INPLACE_MASK64 ( 0, 63, field ) ) \
+ | EFAB_INSERT_FIELD64 ( 0, 63, field, value ) ); \
+ } while ( 0 )
+
+#define EFAB_SET_OWORD_FIELD32( oword, field, value ) do { \
+ (oword).u32[0] = ( ( (oword).u32[0] \
+ & ~EFAB_INPLACE_MASK32 ( 0, 31, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 0, 31, field, value ) ); \
+ (oword).u32[1] = ( ( (oword).u32[1] \
+ & ~EFAB_INPLACE_MASK32 ( 32, 63, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 32, 63, field, value ) ); \
+ (oword).u32[2] = ( ( (oword).u32[2] \
+ & ~EFAB_INPLACE_MASK32 ( 64, 95, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 64, 95, field, value ) ); \
+ (oword).u32[3] = ( ( (oword).u32[3] \
+ & ~EFAB_INPLACE_MASK32 ( 96, 127, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 96, 127, field, value ) ); \
+ } while ( 0 )
+
+#define EFAB_SET_QWORD_FIELD32( qword, field, value ) do { \
+ (qword).u32[0] = ( ( (qword).u32[0] \
+ & ~EFAB_INPLACE_MASK32 ( 0, 31, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 0, 31, field, value ) ); \
+ (qword).u32[1] = ( ( (qword).u32[1] \
+ & ~EFAB_INPLACE_MASK32 ( 32, 63, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 32, 63, field, value ) ); \
+ } while ( 0 )
+
+#define EFAB_SET_DWORD_FIELD( dword, field, value ) do { \
+ (dword).u32[0] = ( ( (dword).u32[0] \
+ & ~EFAB_INPLACE_MASK32 ( 0, 31, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 0, 31, field, value ) ); \
+ } while ( 0 )
+
+#if ( BITS_PER_LONG == 64 )
+#define EFAB_SET_OWORD_FIELD EFAB_SET_OWORD_FIELD64
+#define EFAB_SET_QWORD_FIELD EFAB_SET_QWORD_FIELD64
+#else
+#define EFAB_SET_OWORD_FIELD EFAB_SET_OWORD_FIELD32
+#define EFAB_SET_QWORD_FIELD EFAB_SET_QWORD_FIELD32
+#endif
+
+/* Used to avoid compiler warnings about shift range exceeding width
+ * of the data types when dma_addr_t is only 32 bits wide.
+ */
+#define DMA_ADDR_T_WIDTH ( 8 * sizeof ( dma_addr_t ) )
+#define EFAB_DMA_TYPE_WIDTH( width ) \
+ ( ( (width) < DMA_ADDR_T_WIDTH ) ? (width) : DMA_ADDR_T_WIDTH )
+#define EFAB_DMA_MAX_MASK ( ( DMA_ADDR_T_WIDTH == 64 ) ? \
+ ~( ( uint64_t ) 0 ) : ~( ( uint32_t ) 0 ) )
+#define EFAB_DMA_MASK(mask) ( (mask) & EFAB_DMA_MAX_MASK )
+
+#endif /* EFAB_BITFIELD_H */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/etherfabric_nic.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/etherfabric_nic.h
new file mode 100644
index 00000000..a767e12a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/etherfabric_nic.h
@@ -0,0 +1,204 @@
+/**************************************************************************
+ *
+ * Etherboot driver for Level 5 Etherfabric network cards
+ *
+ * Written by Michael Brown <mbrown@fensystems.co.uk>
+ *
+ * Copyright Fen Systems Ltd. 2005
+ * Copyright Level 5 Networks Inc. 2005
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice.
+ *
+ **************************************************************************
+ */
+
+FILE_LICENCE ( GPL_ANY );
+
+#ifndef EFAB_NIC_H
+#define EFAB_NIC_H
+#include <ipxe/bitbash.h>
+#include <ipxe/i2c.h>
+#include <ipxe/spi.h>
+#include <ipxe/nvo.h>
+#include <ipxe/if_ether.h>
+/**************************************************************************
+ *
+ * Constants and macros
+ *
+ **************************************************************************
+ */
+/* Board IDs. Early boards have no board_type, (e.g. EF1002 and 401/403)
+ * But newer boards are getting bigger...
+ */
+typedef enum {
+ EFAB_BOARD_INVALID = 0, /* Early boards do not have board rev. info. */
+ EFAB_BOARD_SFE4001 = 1,
+ EFAB_BOARD_SFE4002 = 2,
+ EFAB_BOARD_SFE4003 = 3,
+ /* Insert new types before here */
+ EFAB_BOARD_MAX
+} efab_board_type;
+
+/* PHY types. */
+typedef enum {
+ PHY_TYPE_AUTO = 0, /* on development board detect between CX4 & alaska */
+ PHY_TYPE_CX4_RTMR = 1,
+ PHY_TYPE_1GIG_ALASKA = 2,
+ PHY_TYPE_10XPRESS = 3,
+ PHY_TYPE_XFP = 4,
+ PHY_TYPE_CX4 = 5,
+ PHY_TYPE_PM8358 = 6,
+} phy_type_t;
+
+/**************************************************************************
+ *
+ * Hardware data structures and sizing
+ *
+ **************************************************************************
+ */
+
+#define dma_addr_t unsigned long
+typedef efab_qword_t falcon_rx_desc_t;
+typedef efab_qword_t falcon_tx_desc_t;
+typedef efab_qword_t falcon_event_t;
+
+#define EFAB_BUF_ALIGN 4096
+#define EFAB_RXD_SIZE 512
+#define EFAB_TXD_SIZE 512
+#define EFAB_EVQ_SIZE 512
+
+#define EFAB_NUM_RX_DESC 16
+#define EFAB_RX_BUF_SIZE 1600
+
+/**************************************************************************
+ *
+ * Data structures
+ *
+ **************************************************************************
+ */
+
+struct efab_nic;
+
+/* A buffer table allocation backing a tx dma, rx dma or eventq */
+struct efab_special_buffer {
+ dma_addr_t dma_addr;
+ int id;
+};
+
+/* A TX queue */
+struct efab_tx_queue {
+ /* The hardware ring */
+ falcon_tx_desc_t *ring;
+
+ /* The software ring storing io_buffers. */
+ struct io_buffer *buf[EFAB_TXD_SIZE];
+
+ /* The buffer table reservation pushed to hardware */
+ struct efab_special_buffer entry;
+
+ /* Software descriptor write ptr */
+ unsigned int write_ptr;
+
+ /* Hardware descriptor read ptr */
+ unsigned int read_ptr;
+};
+
+/* An RX queue */
+struct efab_rx_queue {
+ /* The hardware ring */
+ falcon_rx_desc_t *ring;
+
+ /* The software ring storing io_buffers */
+ struct io_buffer *buf[EFAB_NUM_RX_DESC];
+
+ /* The buffer table reservation pushed to hardware */
+ struct efab_special_buffer entry;
+
+ /* Descriptor write ptr, into both the hardware and software rings */
+ unsigned int write_ptr;
+
+ /* Hardware completion ptr */
+ unsigned int read_ptr;
+};
+
+/* An event queue */
+struct efab_ev_queue {
+ /* The hardware ring to push to hardware.
+ * Must be the first entry in the structure */
+ falcon_event_t *ring;
+
+ /* The buffer table reservation pushed to hardware */
+ struct efab_special_buffer entry;
+
+ /* Pointers into the ring */
+ unsigned int read_ptr;
+};
+
+struct efab_mac_operations {
+ int ( * init ) ( struct efab_nic *efab );
+};
+
+struct efab_phy_operations {
+ int ( * init ) ( struct efab_nic *efab );
+ unsigned int mmds;
+};
+
+struct efab_board_operations {
+ int ( * init ) ( struct efab_nic *efab );
+ void ( * fini ) ( struct efab_nic *efab );
+};
+
+struct efab_nic {
+ struct net_device *netdev;
+ int pci_revision;
+ int is_asic;
+
+ /* I2C bit-bashed interface */
+ struct i2c_bit_basher i2c_bb;
+
+ /** SPI bus and devices, and the user visible NVO area */
+ struct spi_bus spi_bus;
+ struct spi_device spi_flash;
+ struct spi_device spi_eeprom;
+ struct spi_device *spi;
+ struct nvo_block nvo;
+
+ /** Board, MAC, and PHY operations tables */
+ struct efab_board_operations *board_op;
+ struct efab_mac_operations *mac_op;
+ struct efab_phy_operations *phy_op;
+
+ /* PHY and board types */
+ int phy_addr;
+ int phy_type;
+ int phy_10g;
+ int board_type;
+
+ /** Memory and IO base */
+ void *membase;
+ unsigned int iobase;
+
+ /* Buffer table allocation head */
+ int buffer_head;
+
+ /* Queues */
+ struct efab_rx_queue rx_queue;
+ struct efab_tx_queue tx_queue;
+ struct efab_ev_queue ev_queue;
+
+ /** MAC address */
+ uint8_t mac_addr[ETH_ALEN];
+ /** GMII link options */
+ unsigned int link_options;
+ /** Link status */
+ int link_up;
+
+ /** INT_REG_KER */
+ efab_oword_t int_ker __attribute__ (( aligned ( 16 ) ));
+};
+#endif /* EFAB_NIC_H */
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/forcedeth.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/forcedeth.c
new file mode 100644
index 00000000..34c59223
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/forcedeth.c
@@ -0,0 +1,1979 @@
+/*
+ * forcedeth.c -- Driver for NVIDIA nForce media access controllers for iPXE
+ * Copyright (c) 2010 Andrei Faur <da3drus@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Portions of this code are taken from the Linux forcedeth driver that was
+ * based on a cleanroom reimplementation which was based on reverse engineered
+ * documentation written by Carl-Daniel Hailfinger and Andrew de Quincey:
+ * Copyright (C) 2003,4,5 Manfred Spraul
+ * Copyright (C) 2004 Andrew de Quincey (wol support)
+ * Copyright (C) 2004 Carl-Daniel Hailfinger (invalid MAC handling, insane
+ * IRQ rate fixes, bigendian fixes, cleanups, verification)
+ * Copyright (c) 2004,2005,2006,2007,2008,2009 NVIDIA Corporation
+ *
+ * The probe, remove, open and close functions, along with the functions they
+ * call, are direct copies of the above mentioned driver, modified where
+ * necessary to make them work for iPXE.
+ *
+ * The poll and transmit functions were completely rewritten to make use of
+ * the iPXE API. This process was aided by constant referencing of the above
+ * mentioned Linux driver. This driver would not have been possible without this
+ * prior work.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/io.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/crypto.h>
+#include <ipxe/pci.h>
+#include <ipxe/timer.h>
+#include <mii.h>
+#include "forcedeth.h"
+
+static inline void pci_push ( void *ioaddr )
+{
+ /* force out pending posted writes */
+ wmb();
+ readl ( ioaddr );
+}
+
+static int
+reg_delay ( struct forcedeth_private *priv, int offset, u32 mask,
+ u32 target, int delay, int delaymax, const char *msg )
+{
+ void *ioaddr = priv->mmio_addr;
+
+ pci_push ( ioaddr );
+ do {
+ udelay ( delay );
+ delaymax -= delay;
+ if ( delaymax < 0 ) {
+ if ( msg )
+ DBG ( "%s\n", msg );
+ return 1;
+ }
+ } while ( ( readl ( ioaddr + offset ) & mask ) != target );
+
+ return 0;
+}
+
+/* read/write a register on the PHY */
+static int
+mii_rw ( struct forcedeth_private *priv, int addr, int miireg, int value )
+{
+ void *ioaddr = priv->mmio_addr;
+ u32 reg;
+ int retval;
+
+ writel ( NVREG_MIISTAT_MASK_RW, ioaddr + NvRegMIIStatus );
+
+ reg = readl ( ioaddr + NvRegMIIControl );
+ if ( reg & NVREG_MIICTL_INUSE ) {
+ writel ( NVREG_MIICTL_INUSE, ioaddr + NvRegMIIControl );
+ udelay ( NV_MIIBUSY_DELAY );
+ }
+
+ reg = ( addr << NVREG_MIICTL_ADDRSHIFT ) | miireg;
+ if ( value != MII_READ ) {
+ writel ( value, ioaddr + NvRegMIIData );
+ reg |= NVREG_MIICTL_WRITE;
+ }
+ writel ( reg, ioaddr + NvRegMIIControl );
+
+ if ( reg_delay ( priv, NvRegMIIControl, NVREG_MIICTL_INUSE, 0,
+ NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL ) ) {
+ DBG ( "mii_rw of reg %d at PHY %d timed out.\n",
+ miireg, addr );
+ retval = -1;
+ } else if ( value != MII_READ ) {
+ /* it was a write operation - fewer failures are detectable */
+ DBG ( "mii_rw wrote 0x%x to reg %d at PHY %d\n",
+ value, miireg, addr );
+ retval = 0;
+ } else if ( readl ( ioaddr + NvRegMIIStatus ) & NVREG_MIISTAT_ERROR ) {
+ DBG ( "mii_rw of reg %d at PHY %d failed.\n",
+ miireg, addr );
+ retval = -1;
+ } else {
+ retval = readl ( ioaddr + NvRegMIIData );
+ DBG ( "mii_rw read from reg %d at PHY %d: 0x%x.\n",
+ miireg, addr, retval );
+ }
+
+ return retval;
+}
+
+static void
+nv_txrx_gate ( struct forcedeth_private *priv, int gate )
+{
+ void *ioaddr = priv->mmio_addr;
+ u32 powerstate;
+
+ if ( ! priv->mac_in_use &&
+ ( priv->driver_data & DEV_HAS_POWER_CNTRL ) ) {
+ powerstate = readl ( ioaddr + NvRegPowerState2 );
+ if ( gate )
+ powerstate |= NVREG_POWERSTATE2_GATE_CLOCKS;
+ else
+ powerstate &= ~NVREG_POWERSTATE2_GATE_CLOCKS;
+ writel ( powerstate, ioaddr + NvRegPowerState2 );
+ }
+}
+
+static void
+nv_mac_reset ( struct forcedeth_private * priv )
+{
+ void *ioaddr = priv->mmio_addr;
+ u32 temp1, temp2, temp3;
+
+ writel ( NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | NVREG_TXRXCTL_DESC_1,
+ ioaddr + NvRegTxRxControl );
+ pci_push ( ioaddr );
+
+ /* save registers since they will be cleared on reset */
+ temp1 = readl ( ioaddr + NvRegMacAddrA );
+ temp2 = readl ( ioaddr + NvRegMacAddrB );
+ temp3 = readl ( ioaddr + NvRegTransmitPoll );
+
+ writel ( NVREG_MAC_RESET_ASSERT, ioaddr + NvRegMacReset );
+ pci_push ( ioaddr );
+ udelay ( NV_MAC_RESET_DELAY );
+ writel ( 0, ioaddr + NvRegMacReset );
+ pci_push ( ioaddr );
+ udelay ( NV_MAC_RESET_DELAY );
+
+ /* restore saved registers */
+ writel ( temp1, ioaddr + NvRegMacAddrA );
+ writel ( temp2, ioaddr + NvRegMacAddrB );
+ writel ( temp3, ioaddr + NvRegTransmitPoll );
+
+ writel ( NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_DESC_1,
+ ioaddr + NvRegTxRxControl );
+ pci_push ( ioaddr );
+}
+
+static void
+nv_init_tx_ring ( struct forcedeth_private *priv )
+{
+ int i;
+
+ for ( i = 0; i < TX_RING_SIZE; i++ ) {
+ priv->tx_ring[i].flaglen = 0;
+ priv->tx_ring[i].buf = 0;
+ priv->tx_iobuf[i] = NULL;
+ }
+
+ priv->tx_fill_ctr = 0;
+ priv->tx_curr = 0;
+ priv->tx_tail = 0;
+}
+
+/**
+ * nv_alloc_rx - Allocates iobufs for every Rx descriptor
+ * that doesn't have one and isn't in use by the hardware
+ *
+ * @v priv Driver private structure
+ */
+static void
+nv_alloc_rx ( struct forcedeth_private *priv )
+{
+ struct ring_desc *rx_curr_desc;
+ int i;
+ u32 status;
+
+ DBGP ( "nv_alloc_rx\n" );
+
+ for ( i = 0; i < RX_RING_SIZE; i++ ) {
+ rx_curr_desc = priv->rx_ring + i;
+ status = le32_to_cpu ( rx_curr_desc->flaglen );
+
+ /* Don't touch the descriptors owned by the hardware */
+ if ( status & NV_RX_AVAIL )
+ continue;
+
+ /* Descriptors with iobufs still need to be processed */
+ if ( priv->rx_iobuf[i] != NULL )
+ continue;
+
+ /* If alloc_iob fails, try again later (next poll) */
+ if ( ! ( priv->rx_iobuf[i] = alloc_iob ( RX_BUF_SZ ) ) ) {
+ DBG ( "Refill rx_ring failed, size %d\n", RX_BUF_SZ );
+ break;
+ }
+
+ rx_curr_desc->buf =
+ cpu_to_le32 ( virt_to_bus ( priv->rx_iobuf[i]->data ) );
+ wmb();
+ rx_curr_desc->flaglen =
+ cpu_to_le32 ( RX_BUF_SZ | NV_RX_AVAIL );
+ }
+}
+
+static void
+nv_init_rx_ring ( struct forcedeth_private *priv )
+{
+ int i;
+
+ for ( i = 0; i < RX_RING_SIZE; i++ ) {
+ priv->rx_ring[i].flaglen = 0;
+ priv->rx_ring[i].buf = 0;
+ priv->rx_iobuf[i] = NULL;
+ }
+
+ priv->rx_curr = 0;
+}
+
+/**
+ * nv_init_rings - Allocate and intialize descriptor rings
+ *
+ * @v priv Driver private structure
+ *
+ * @ret rc Return status code
+ **/
+static int
+nv_init_rings ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+ int rc = -ENOMEM;
+
+ /* Allocate ring for both TX and RX */
+ priv->rx_ring =
+ malloc_dma ( sizeof(struct ring_desc) * RXTX_RING_SIZE, 32 );
+ if ( ! priv->rx_ring )
+ goto err_malloc;
+ priv->tx_ring = &priv->rx_ring[RX_RING_SIZE];
+
+ /* Initialize rings */
+ nv_init_tx_ring ( priv );
+ nv_init_rx_ring ( priv );
+
+ /* Allocate iobufs for RX */
+ nv_alloc_rx ( priv );
+
+ /* Give hw rings */
+ writel ( cpu_to_le32 ( virt_to_bus ( priv->rx_ring ) ),
+ ioaddr + NvRegRxRingPhysAddr );
+ writel ( cpu_to_le32 ( virt_to_bus ( priv->tx_ring ) ),
+ ioaddr + NvRegTxRingPhysAddr );
+
+ DBG ( "RX ring at phys addr: %#08lx\n",
+ virt_to_bus ( priv->rx_ring ) );
+ DBG ( "TX ring at phys addr: %#08lx\n",
+ virt_to_bus ( priv->tx_ring ) );
+
+ writel ( ( ( RX_RING_SIZE - 1 ) << NVREG_RINGSZ_RXSHIFT ) +
+ ( ( TX_RING_SIZE - 1 ) << NVREG_RINGSZ_TXSHIFT ),
+ ioaddr + NvRegRingSizes );
+
+ return 0;
+
+err_malloc:
+ DBG ( "Could not allocate descriptor rings\n");
+ return rc;
+}
+
+static void
+nv_free_rxtx_resources ( struct forcedeth_private *priv )
+{
+ int i;
+
+ DBGP ( "nv_free_rxtx_resources\n" );
+
+ free_dma ( priv->rx_ring, sizeof(struct ring_desc) * RXTX_RING_SIZE );
+
+ for ( i = 0; i < RX_RING_SIZE; i++ ) {
+ free_iob ( priv->rx_iobuf[i] );
+ priv->rx_iobuf[i] = NULL;
+ }
+}
+
+static void
+nv_txrx_reset ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+
+ writel ( NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | NVREG_TXRXCTL_DESC_1,
+ ioaddr + NvRegTxRxControl );
+ pci_push ( ioaddr );
+ udelay ( NV_TXRX_RESET_DELAY );
+ writel ( NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_DESC_1,
+ ioaddr + NvRegTxRxControl );
+ pci_push ( ioaddr );
+}
+
+static void
+nv_disable_hw_interrupts ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+
+ writel ( 0, ioaddr + NvRegIrqMask );
+ pci_push ( ioaddr );
+}
+
+static void
+nv_enable_hw_interrupts ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+
+ writel ( NVREG_IRQMASK_THROUGHPUT, ioaddr + NvRegIrqMask );
+}
+
+static void
+nv_start_rx ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+ u32 rx_ctrl = readl ( ioaddr + NvRegReceiverControl );
+
+ DBGP ( "nv_start_rx\n" );
+ /* Already running? Stop it. */
+ if ( ( readl ( ioaddr + NvRegReceiverControl ) & NVREG_RCVCTL_START ) && !priv->mac_in_use ) {
+ rx_ctrl &= ~NVREG_RCVCTL_START;
+ writel ( rx_ctrl, ioaddr + NvRegReceiverControl );
+ pci_push ( ioaddr );
+ }
+ writel ( priv->linkspeed, ioaddr + NvRegLinkSpeed );
+ pci_push ( ioaddr );
+ rx_ctrl |= NVREG_RCVCTL_START;
+ if ( priv->mac_in_use )
+ rx_ctrl &= ~NVREG_RCVCTL_RX_PATH_EN;
+ writel ( rx_ctrl, ioaddr + NvRegReceiverControl );
+ DBG ( "nv_start_rx to duplex %d, speed 0x%08x.\n",
+ priv->duplex, priv->linkspeed);
+ pci_push ( ioaddr );
+}
+
+static void
+nv_stop_rx ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+ u32 rx_ctrl = readl ( ioaddr + NvRegReceiverControl );
+
+ DBGP ( "nv_stop_rx\n" );
+ if ( ! priv->mac_in_use )
+ rx_ctrl &= ~NVREG_RCVCTL_START;
+ else
+ rx_ctrl |= NVREG_RCVCTL_RX_PATH_EN;
+ writel ( rx_ctrl, ioaddr + NvRegReceiverControl );
+ reg_delay ( priv, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0,
+ NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX,
+ "nv_stop_rx: ReceiverStatus remained busy");
+
+ udelay ( NV_RXSTOP_DELAY2 );
+ if ( ! priv->mac_in_use )
+ writel ( 0, priv + NvRegLinkSpeed );
+}
+
+static void
+nv_start_tx ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+ u32 tx_ctrl = readl ( ioaddr + NvRegTransmitterControl );
+
+ DBGP ( "nv_start_tx\n" );
+ tx_ctrl |= NVREG_XMITCTL_START;
+ if ( priv->mac_in_use )
+ tx_ctrl &= ~NVREG_XMITCTL_TX_PATH_EN;
+ writel ( tx_ctrl, ioaddr + NvRegTransmitterControl );
+ pci_push ( ioaddr );
+}
+
+static void
+nv_stop_tx ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+ u32 tx_ctrl = readl ( ioaddr + NvRegTransmitterControl );
+
+ DBGP ( "nv_stop_tx");
+
+ if ( ! priv->mac_in_use )
+ tx_ctrl &= ~NVREG_XMITCTL_START;
+ else
+ tx_ctrl |= NVREG_XMITCTL_TX_PATH_EN;
+ writel ( tx_ctrl, ioaddr + NvRegTransmitterControl );
+ reg_delay ( priv, NvRegTransmitterStatus, NVREG_XMITSTAT_BUSY, 0,
+ NV_TXSTOP_DELAY1, NV_TXSTOP_DELAY1MAX,
+ "nv_stop_tx: TransmitterStatus remained busy");
+
+ udelay ( NV_TXSTOP_DELAY2 );
+ if ( ! priv->mac_in_use )
+ writel( readl ( ioaddr + NvRegTransmitPoll) &
+ NVREG_TRANSMITPOLL_MAC_ADDR_REV,
+ ioaddr + NvRegTransmitPoll);
+}
+
+
+static void
+nv_update_pause ( struct forcedeth_private *priv, u32 pause_flags )
+{
+ void *ioaddr = priv->mmio_addr;
+
+ priv->pause_flags &= ~ ( NV_PAUSEFRAME_TX_ENABLE |
+ NV_PAUSEFRAME_RX_ENABLE );
+
+ if ( priv->pause_flags & NV_PAUSEFRAME_RX_CAPABLE ) {
+ u32 pff = readl ( ioaddr + NvRegPacketFilterFlags ) & ~NVREG_PFF_PAUSE_RX;
+ if ( pause_flags & NV_PAUSEFRAME_RX_ENABLE ) {
+ writel ( pff | NVREG_PFF_PAUSE_RX, ioaddr + NvRegPacketFilterFlags );
+ priv->pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+ } else {
+ writel ( pff, ioaddr + NvRegPacketFilterFlags );
+ }
+ }
+ if ( priv->pause_flags & NV_PAUSEFRAME_TX_CAPABLE ) {
+ u32 regmisc = readl ( ioaddr + NvRegMisc1 ) & ~NVREG_MISC1_PAUSE_TX;
+ if ( pause_flags & NV_PAUSEFRAME_TX_ENABLE ) {
+ u32 pause_enable = NVREG_TX_PAUSEFRAME_ENABLE_V1;
+ if ( priv->driver_data & DEV_HAS_PAUSEFRAME_TX_V2 )
+ pause_enable = NVREG_TX_PAUSEFRAME_ENABLE_V2;
+ if ( priv->driver_data & DEV_HAS_PAUSEFRAME_TX_V3 ) {
+ pause_enable = NVREG_TX_PAUSEFRAME_ENABLE_V3;
+ /* limit the number of tx pause frames to a default of 8 */
+ writel ( readl ( ioaddr + NvRegTxPauseFrameLimit ) |
+ NVREG_TX_PAUSEFRAMELIMIT_ENABLE,
+ ioaddr + NvRegTxPauseFrameLimit );
+ }
+ writel ( pause_enable, ioaddr + NvRegTxPauseFrame );
+ writel ( regmisc | NVREG_MISC1_PAUSE_TX, ioaddr + NvRegMisc1 );
+ priv->pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+ } else {
+ writel ( NVREG_TX_PAUSEFRAME_DISABLE, ioaddr + NvRegTxPauseFrame );
+ writel ( regmisc, ioaddr + NvRegMisc1 );
+ }
+ }
+}
+
+static int
+nv_update_linkspeed ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+ int adv = 0;
+ int lpa = 0;
+ int adv_lpa, adv_pause, lpa_pause;
+ u32 newls = priv->linkspeed;
+ int newdup = priv->duplex;
+ int mii_status;
+ int retval = 0;
+ u32 control_1000, status_1000, phyreg, pause_flags, txreg;
+ u32 txrxFlags = 0;
+ u32 phy_exp;
+
+ /* BMSR_LSTATUS is latched, read it twice:
+ * we want the current value.
+ */
+ mii_rw ( priv, priv->phyaddr, MII_BMSR, MII_READ );
+ mii_status = mii_rw ( priv, priv->phyaddr, MII_BMSR, MII_READ );
+
+ if ( ! ( mii_status & BMSR_LSTATUS ) ) {
+ DBG ( "No link detected by phy - falling back to 10HD.\n" );
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
+ newdup = 0;
+ retval = 0;
+ goto set_speed;
+ }
+
+ /* check auto negotiation is complete */
+ if ( ! ( mii_status & BMSR_ANEGCOMPLETE ) ) {
+ /* still in autonegotiation - configure nic for 10 MBit HD and wait. */
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
+ newdup = 0;
+ retval = 0;
+ DBG ( "autoneg not completed - falling back to 10HD.\n" );
+ goto set_speed;
+ }
+
+ adv = mii_rw ( priv, priv->phyaddr, MII_ADVERTISE, MII_READ );
+ lpa = mii_rw ( priv, priv->phyaddr, MII_LPA, MII_READ );
+ DBG ( "nv_update_linkspeed: PHY advertises 0x%04x, lpa 0x%04x.\n", adv, lpa );
+
+ retval = 1;
+ if ( priv->gigabit == PHY_GIGABIT ) {
+ control_1000 = mii_rw ( priv, priv->phyaddr, MII_CTRL1000, MII_READ);
+ status_1000 = mii_rw ( priv, priv->phyaddr, MII_STAT1000, MII_READ);
+
+ if ( ( control_1000 & ADVERTISE_1000FULL ) &&
+ ( status_1000 & LPA_1000FULL ) ) {
+ DBG ( "nv_update_linkspeed: GBit ethernet detected.\n" );
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_1000;
+ newdup = 1;
+ goto set_speed;
+ }
+ }
+
+ /* FIXME: handle parallel detection properly */
+ adv_lpa = lpa & adv;
+ if ( adv_lpa & LPA_100FULL ) {
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100;
+ newdup = 1;
+ } else if ( adv_lpa & LPA_100HALF ) {
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100;
+ newdup = 0;
+ } else if ( adv_lpa & LPA_10FULL ) {
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
+ newdup = 1;
+ } else if ( adv_lpa & LPA_10HALF ) {
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
+ newdup = 0;
+ } else {
+ DBG ( "bad ability %04x - falling back to 10HD.\n", adv_lpa);
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
+ newdup = 0;
+ }
+
+set_speed:
+ if ( priv->duplex == newdup && priv->linkspeed == newls )
+ return retval;
+
+ DBG ( "changing link setting from %d/%d to %d/%d.\n",
+ priv->linkspeed, priv->duplex, newls, newdup);
+
+ priv->duplex = newdup;
+ priv->linkspeed = newls;
+
+ /* The transmitter and receiver must be restarted for safe update */
+ if ( readl ( ioaddr + NvRegTransmitterControl ) & NVREG_XMITCTL_START ) {
+ txrxFlags |= NV_RESTART_TX;
+ nv_stop_tx ( priv );
+ }
+ if ( readl ( ioaddr + NvRegReceiverControl ) & NVREG_RCVCTL_START) {
+ txrxFlags |= NV_RESTART_RX;
+ nv_stop_rx ( priv );
+ }
+
+ if ( priv->gigabit == PHY_GIGABIT ) {
+ phyreg = readl ( ioaddr + NvRegSlotTime );
+ phyreg &= ~(0x3FF00);
+ if ( ( ( priv->linkspeed & 0xFFF ) == NVREG_LINKSPEED_10 ) ||
+ ( ( priv->linkspeed & 0xFFF ) == NVREG_LINKSPEED_100) )
+ phyreg |= NVREG_SLOTTIME_10_100_FULL;
+ else if ( ( priv->linkspeed & 0xFFF ) == NVREG_LINKSPEED_1000 )
+ phyreg |= NVREG_SLOTTIME_1000_FULL;
+ writel( phyreg, priv + NvRegSlotTime );
+ }
+
+ phyreg = readl ( ioaddr + NvRegPhyInterface );
+ phyreg &= ~( PHY_HALF | PHY_100 | PHY_1000 );
+ if ( priv->duplex == 0 )
+ phyreg |= PHY_HALF;
+ if ( ( priv->linkspeed & NVREG_LINKSPEED_MASK ) == NVREG_LINKSPEED_100 )
+ phyreg |= PHY_100;
+ else if ( ( priv->linkspeed & NVREG_LINKSPEED_MASK ) == NVREG_LINKSPEED_1000 )
+ phyreg |= PHY_1000;
+ writel ( phyreg, ioaddr + NvRegPhyInterface );
+
+ phy_exp = mii_rw ( priv, priv->phyaddr, MII_EXPANSION, MII_READ ) & EXPANSION_NWAY; /* autoneg capable */
+ if ( phyreg & PHY_RGMII ) {
+ if ( ( priv->linkspeed & NVREG_LINKSPEED_MASK ) == NVREG_LINKSPEED_1000 ) {
+ txreg = NVREG_TX_DEFERRAL_RGMII_1000;
+ } else {
+ if ( !phy_exp && !priv->duplex && ( priv->driver_data & DEV_HAS_COLLISION_FIX ) ) {
+ if ( ( priv->linkspeed & NVREG_LINKSPEED_MASK ) == NVREG_LINKSPEED_10 )
+ txreg = NVREG_TX_DEFERRAL_RGMII_STRETCH_10;
+ else
+ txreg = NVREG_TX_DEFERRAL_RGMII_STRETCH_100;
+ } else {
+ txreg = NVREG_TX_DEFERRAL_RGMII_10_100;
+ }
+ }
+ } else {
+ if ( !phy_exp && !priv->duplex && ( priv->driver_data & DEV_HAS_COLLISION_FIX ) )
+ txreg = NVREG_TX_DEFERRAL_MII_STRETCH;
+ else
+ txreg = NVREG_TX_DEFERRAL_DEFAULT;
+ }
+ writel ( txreg, ioaddr + NvRegTxDeferral );
+
+ txreg = NVREG_TX_WM_DESC1_DEFAULT;
+ writel ( txreg, ioaddr + NvRegTxWatermark );
+
+ writel ( NVREG_MISC1_FORCE | ( priv->duplex ? 0 : NVREG_MISC1_HD ), ioaddr + NvRegMisc1 );
+ pci_push ( ioaddr );
+ writel ( priv->linkspeed, priv + NvRegLinkSpeed);
+ pci_push ( ioaddr );
+
+ pause_flags = 0;
+ /* setup pause frame */
+ if ( priv->duplex != 0 ) {
+ if ( priv->pause_flags & NV_PAUSEFRAME_AUTONEG ) {
+ adv_pause = adv & ( ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM );
+ lpa_pause = lpa & ( LPA_PAUSE_CAP | LPA_PAUSE_ASYM );
+
+ switch ( adv_pause ) {
+ case ADVERTISE_PAUSE_CAP:
+ if ( lpa_pause & LPA_PAUSE_CAP ) {
+ pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+ if ( priv->pause_flags & NV_PAUSEFRAME_TX_REQ )
+ pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+ }
+ break;
+ case ADVERTISE_PAUSE_ASYM:
+ if ( lpa_pause == ( LPA_PAUSE_CAP | LPA_PAUSE_ASYM ) )
+ {
+ pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+ }
+ break;
+ case ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM:
+ if ( lpa_pause & LPA_PAUSE_CAP )
+ {
+ pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+ if ( priv->pause_flags & NV_PAUSEFRAME_TX_REQ )
+ pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+ }
+ if ( lpa_pause == LPA_PAUSE_ASYM )
+ {
+ pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+ }
+ break;
+ }
+ } else {
+ pause_flags = priv->pause_flags;
+ }
+ }
+ nv_update_pause ( priv, pause_flags );
+
+ if ( txrxFlags & NV_RESTART_TX )
+ nv_start_tx ( priv );
+ if ( txrxFlags & NV_RESTART_RX )
+ nv_start_rx ( priv );
+
+ return retval;
+}
+
+
+/**
+ * open - Called when a network interface is made active
+ *
+ * @v netdev Network device
+ * @ret rc Return status code, 0 on success, negative value on failure
+ **/
+static int
+forcedeth_open ( struct net_device *netdev )
+{
+ struct forcedeth_private *priv = netdev_priv ( netdev );
+ void *ioaddr = priv->mmio_addr;
+ int i;
+ int rc;
+ u32 low;
+
+ DBGP ( "forcedeth_open\n" );
+
+ /* Power up phy */
+ mii_rw ( priv, priv->phyaddr, MII_BMCR,
+ mii_rw ( priv, priv->phyaddr, MII_BMCR, MII_READ ) & ~BMCR_PDOWN );
+
+ nv_txrx_gate ( priv, 0 );
+
+ /* Erase previous misconfiguration */
+ if ( priv->driver_data & DEV_HAS_POWER_CNTRL )
+ nv_mac_reset ( priv );
+
+ /* Clear multicast masks and addresses, enter promiscuous mode */
+ writel ( 0, ioaddr + NvRegMulticastAddrA );
+ writel ( 0, ioaddr + NvRegMulticastAddrB );
+ writel ( NVREG_MCASTMASKA_NONE, ioaddr + NvRegMulticastMaskA );
+ writel ( NVREG_MCASTMASKB_NONE, ioaddr + NvRegMulticastMaskB );
+ writel ( NVREG_PFF_PROMISC, ioaddr + NvRegPacketFilterFlags );
+
+ writel ( 0, ioaddr + NvRegTransmitterControl );
+ writel ( 0, ioaddr + NvRegReceiverControl );
+
+ writel ( 0, ioaddr + NvRegAdapterControl );
+
+ writel ( 0, ioaddr + NvRegLinkSpeed );
+ writel ( readl ( ioaddr + NvRegTransmitPoll ) & NVREG_TRANSMITPOLL_MAC_ADDR_REV,
+ ioaddr + NvRegTransmitPoll );
+ nv_txrx_reset ( priv );
+ writel ( 0, ioaddr + NvRegUnknownSetupReg6 );
+
+ /* Initialize descriptor rings */
+ if ( ( rc = nv_init_rings ( priv ) ) != 0 )
+ goto err_init_rings;
+
+ writel ( priv->linkspeed, ioaddr + NvRegLinkSpeed );
+ writel ( NVREG_TX_WM_DESC1_DEFAULT, ioaddr + NvRegTxWatermark );
+ writel ( NVREG_TXRXCTL_DESC_1, ioaddr + NvRegTxRxControl );
+ writel ( 0 , ioaddr + NvRegVlanControl );
+ pci_push ( ioaddr );
+ writel ( NVREG_TXRXCTL_BIT1 | NVREG_TXRXCTL_DESC_1,
+ ioaddr + NvRegTxRxControl );
+ reg_delay ( priv, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31,
+ NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
+ "open: SetupReg5, Bit 31 remained off\n" );
+
+ writel ( 0, ioaddr + NvRegMIIMask );
+ writel ( NVREG_IRQSTAT_MASK, ioaddr + NvRegIrqStatus );
+ writel ( NVREG_MIISTAT_MASK_ALL, ioaddr + NvRegMIIStatus );
+
+ writel ( NVREG_MISC1_FORCE | NVREG_MISC1_HD, ioaddr + NvRegMisc1 );
+ writel ( readl ( ioaddr + NvRegTransmitterStatus ),
+ ioaddr + NvRegTransmitterStatus );
+ writel ( RX_BUF_SZ, ioaddr + NvRegOffloadConfig );
+
+ writel ( readl ( ioaddr + NvRegReceiverStatus),
+ ioaddr + NvRegReceiverStatus );
+
+ /* Set up slot time */
+ low = ( random() & NVREG_SLOTTIME_MASK );
+ writel ( low | NVREG_SLOTTIME_DEFAULT, ioaddr + NvRegSlotTime );
+
+ writel ( NVREG_TX_DEFERRAL_DEFAULT , ioaddr + NvRegTxDeferral );
+ writel ( NVREG_RX_DEFERRAL_DEFAULT , ioaddr + NvRegRxDeferral );
+
+ writel ( NVREG_POLL_DEFAULT_THROUGHPUT, ioaddr + NvRegPollingInterval );
+
+ writel ( NVREG_UNKSETUP6_VAL, ioaddr + NvRegUnknownSetupReg6 );
+ writel ( ( priv->phyaddr << NVREG_ADAPTCTL_PHYSHIFT ) |
+ NVREG_ADAPTCTL_PHYVALID | NVREG_ADAPTCTL_RUNNING,
+ ioaddr + NvRegAdapterControl );
+ writel ( NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY, ioaddr + NvRegMIISpeed );
+ writel ( NVREG_MII_LINKCHANGE, ioaddr + NvRegMIIMask );
+
+ i = readl ( ioaddr + NvRegPowerState );
+ if ( ( i & NVREG_POWERSTATE_POWEREDUP ) == 0 )
+ writel ( NVREG_POWERSTATE_POWEREDUP | i, ioaddr + NvRegPowerState );
+
+ pci_push ( ioaddr );
+ udelay ( 10 );
+ writel ( readl ( ioaddr + NvRegPowerState ) | NVREG_POWERSTATE_VALID,
+ ioaddr + NvRegPowerState );
+
+ nv_disable_hw_interrupts ( priv );
+ writel ( NVREG_MIISTAT_MASK_ALL, ioaddr + NvRegMIIStatus );
+ writel ( NVREG_IRQSTAT_MASK, ioaddr + NvRegIrqStatus );
+ pci_push ( ioaddr );
+
+ readl ( ioaddr + NvRegMIIStatus );
+ writel ( NVREG_MIISTAT_MASK_ALL, ioaddr + NvRegMIIStatus );
+ priv->linkspeed = 0;
+ nv_update_linkspeed ( priv );
+ nv_start_rx ( priv );
+ nv_start_tx ( priv );
+
+ return 0;
+
+err_init_rings:
+ return rc;
+}
+
+/**
+ * transmit - Transmit a packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ */
+static int
+forcedeth_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
+{
+ struct forcedeth_private *priv = netdev_priv ( netdev );
+ void *ioaddr = priv->mmio_addr;
+ struct ring_desc *tx_curr_desc;
+ u32 size = iob_len ( iobuf );
+
+ DBGP ( "forcedeth_transmit\n" );
+
+ /* NOTE: Some NICs have a hw bug that causes them to malfunction
+ * when there are more than 16 outstanding TXs. Increasing the TX
+ * ring size might trigger this bug */
+ if ( priv->tx_fill_ctr == TX_RING_SIZE ) {
+ DBG ( "Tx overflow\n" );
+ return -ENOBUFS;
+ }
+
+ /* Pad small packets to minimum length */
+ iob_pad ( iobuf, ETH_ZLEN );
+
+ priv->tx_iobuf[priv->tx_curr] = iobuf;
+
+ tx_curr_desc = priv->tx_ring + priv->tx_curr;
+
+ /* Configure current descriptor to transmit packet
+ * ( NV_TX_VALID sets the ownership bit ) */
+ tx_curr_desc->buf =
+ cpu_to_le32 ( virt_to_bus ( iobuf->data ) );
+ wmb();
+ /* Since we don't do fragmentation offloading, we always have
+ * the last packet bit set */
+ tx_curr_desc->flaglen =
+ cpu_to_le32 ( ( size - 1 ) | NV_TX_VALID | NV_TX_LASTPACKET );
+
+ DBG ( "forcedeth_transmit: flaglen = %#04x\n",
+ ( size - 1 ) | NV_TX_VALID | NV_TX_LASTPACKET );
+ DBG ( "forcedeth_transmit: tx_fill_ctr = %d\n",
+ priv->tx_fill_ctr );
+
+ writel ( NVREG_TXRXCTL_KICK | NVREG_TXRXCTL_DESC_1,
+ ioaddr + NvRegTxRxControl );
+ pci_push ( ioaddr );
+
+ /* Point to the next free descriptor */
+ priv->tx_curr = ( priv->tx_curr + 1 ) % TX_RING_SIZE;
+
+ /* Increment number of descriptors in use */
+ priv->tx_fill_ctr++;
+
+ return 0;
+}
+
+/**
+ * nv_process_tx_packets - Checks for successfully sent packets,
+ * reports them to iPXE with netdev_tx_complete()
+ *
+ * @v netdev Network device
+ */
+static void
+nv_process_tx_packets ( struct net_device *netdev )
+{
+ struct forcedeth_private *priv = netdev_priv ( netdev );
+ struct ring_desc *tx_curr_desc;
+ u32 flaglen;
+
+ DBGP ( "nv_process_tx_packets\n" );
+
+ while ( priv->tx_tail != priv->tx_curr ) {
+
+ tx_curr_desc = priv->tx_ring + priv->tx_tail;
+ flaglen = le32_to_cpu ( tx_curr_desc->flaglen );
+ rmb();
+
+ /* Skip this descriptor if hardware still owns it */
+ if ( flaglen & NV_TX_VALID )
+ break;
+
+ DBG ( "Transmitted packet.\n" );
+ DBG ( "priv->tx_fill_ctr= %d\n", priv->tx_fill_ctr );
+ DBG ( "priv->tx_tail = %d\n", priv->tx_tail );
+ DBG ( "priv->tx_curr = %d\n", priv->tx_curr );
+ DBG ( "flaglen = %#04x\n", flaglen );
+
+ /* This packet is ready for completion */
+ netdev_tx_complete ( netdev, priv->tx_iobuf[priv->tx_tail] );
+
+ /* Clear the descriptor */
+ memset ( tx_curr_desc, 0, sizeof(*tx_curr_desc) );
+
+ /* Reduce the number of tx descriptors in use */
+ priv->tx_fill_ctr--;
+
+ /* Go to next available descriptor */
+ priv->tx_tail = ( priv->tx_tail + 1 ) % TX_RING_SIZE;
+ }
+}
+
+/**
+ * nv_process_rx_packets - Checks for received packets, reports them
+ * to iPXE with netdev_rx() or netdev_rx_err() if there was an error receiving
+ * the packet
+ *
+ * @v netdev Network device
+ */
+static void
+nv_process_rx_packets ( struct net_device *netdev )
+{
+ struct forcedeth_private *priv = netdev_priv ( netdev );
+ struct io_buffer *curr_iob;
+ struct ring_desc *rx_curr_desc;
+ u32 flags, len;
+ int i;
+
+ DBGP ( "nv_process_rx_packets\n" );
+
+ for ( i = 0; i < RX_RING_SIZE; i++ ) {
+
+ rx_curr_desc = priv->rx_ring + priv->rx_curr;
+ flags = le32_to_cpu ( rx_curr_desc->flaglen );
+ rmb();
+
+ /* Skip this descriptor if hardware still owns it */
+ if ( flags & NV_RX_AVAIL )
+ break;
+
+ /* We own the descriptor, but it has not been refilled yet */
+ curr_iob = priv->rx_iobuf[priv->rx_curr];
+ DBG ( "%p %p\n", curr_iob, priv->rx_iobuf[priv->rx_curr] );
+ if ( curr_iob == NULL )
+ break;
+
+ DBG ( "Received packet.\n" );
+ DBG ( "priv->rx_curr = %d\n", priv->rx_curr );
+ DBG ( "flags = %#04x\n", flags );
+
+ /* Check for errors */
+ if ( ( flags & NV_RX_DESCRIPTORVALID ) &&
+ ( flags & NV_RX_ERROR ) ) {
+ netdev_rx_err ( netdev, curr_iob, -EINVAL );
+ DBG ( " Corrupted packet received!\n" );
+ } else {
+ len = flags & LEN_MASK_V1;
+
+ iob_put ( curr_iob, len );
+ netdev_rx ( netdev, curr_iob );
+ }
+
+ /* Invalidate iobuf */
+ priv->rx_iobuf[priv->rx_curr] = NULL;
+
+ /* Invalidate descriptor */
+ memset ( rx_curr_desc, 0, sizeof(*rx_curr_desc) );
+
+ /* Point to the next free descriptor */
+ priv->rx_curr = ( priv->rx_curr + 1 ) % RX_RING_SIZE;
+ }
+
+ nv_alloc_rx ( priv );
+}
+
+/**
+ * check_link - Check for link status change
+ *
+ * @v netdev Network device
+ */
+static void
+forcedeth_link_status ( struct net_device *netdev )
+{
+ struct forcedeth_private *priv = netdev_priv ( netdev );
+ void *ioaddr = priv->mmio_addr;
+
+ /* Clear the MII link change status by reading the MIIStatus register */
+ readl ( ioaddr + NvRegMIIStatus );
+ writel ( NVREG_MIISTAT_LINKCHANGE, ioaddr + NvRegMIIStatus );
+
+ if ( nv_update_linkspeed ( priv ) == 1 )
+ netdev_link_up ( netdev );
+ else
+ netdev_link_down ( netdev );
+}
+
+/**
+ * poll - Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void
+forcedeth_poll ( struct net_device *netdev )
+{
+ struct forcedeth_private *priv = netdev_priv ( netdev );
+ void *ioaddr = priv->mmio_addr;
+ u32 status;
+
+ DBGP ( "forcedeth_poll\n" );
+
+ status = readl ( ioaddr + NvRegIrqStatus ) & NVREG_IRQSTAT_MASK;
+
+ /* Return when no interrupts have been triggered */
+ if ( ! status )
+ return;
+
+ /* Clear interrupts */
+ writel ( NVREG_IRQSTAT_MASK, ioaddr + NvRegIrqStatus );
+
+ DBG ( "forcedeth_poll: status = %#04x\n", status );
+
+ /* Link change interrupt occured. Call always if link is down,
+ * to give auto-neg a chance to finish */
+ if ( ( status & NVREG_IRQ_LINK ) || ! ( netdev_link_ok ( netdev ) ) )
+ forcedeth_link_status ( netdev );
+
+ /* Process transmitted packets */
+ nv_process_tx_packets ( netdev );
+
+ /* Process received packets */
+ nv_process_rx_packets ( netdev );
+}
+
+/**
+ * close - Disable network interface
+ *
+ * @v netdev network interface device structure
+ **/
+static void
+forcedeth_close ( struct net_device *netdev )
+{
+ struct forcedeth_private *priv = netdev_priv ( netdev );
+
+ DBGP ( "forcedeth_close\n" );
+
+ nv_stop_rx ( priv );
+ nv_stop_tx ( priv );
+ nv_txrx_reset ( priv );
+
+ /* Disable interrupts on the nic or we will lock up */
+ nv_disable_hw_interrupts ( priv );
+
+ nv_free_rxtx_resources ( priv );
+
+ nv_txrx_gate ( priv, 0 );
+
+ /* FIXME: power down nic */
+}
+
+/**
+ * irq - enable or disable interrupts
+ *
+ * @v netdev network adapter
+ * @v action requested interrupt action
+ **/
+static void
+forcedeth_irq ( struct net_device *netdev, int action )
+{
+ struct forcedeth_private *priv = netdev_priv ( netdev );
+
+ DBGP ( "forcedeth_irq\n" );
+
+ switch ( action ) {
+ case 0:
+ nv_disable_hw_interrupts ( priv );
+ break;
+ default:
+ nv_enable_hw_interrupts ( priv );
+ break;
+ }
+}
+
+static struct net_device_operations forcedeth_operations = {
+ .open = forcedeth_open,
+ .transmit = forcedeth_transmit,
+ .poll = forcedeth_poll,
+ .close = forcedeth_close,
+ .irq = forcedeth_irq,
+};
+
+static int
+nv_setup_mac_addr ( struct forcedeth_private *priv )
+{
+ struct net_device *dev = priv->netdev;
+ void *ioaddr = priv->mmio_addr;
+ u32 orig_mac[2];
+ u32 txreg;
+
+ orig_mac[0] = readl ( ioaddr + NvRegMacAddrA );
+ orig_mac[1] = readl ( ioaddr + NvRegMacAddrB );
+
+ txreg = readl ( ioaddr + NvRegTransmitPoll );
+
+ if ( ( priv->driver_data & DEV_HAS_CORRECT_MACADDR ) ||
+ ( txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV ) ) {
+ /* mac address is already in correct order */
+ dev->hw_addr[0] = ( orig_mac[0] >> 0 ) & 0xff;
+ dev->hw_addr[1] = ( orig_mac[0] >> 8 ) & 0xff;
+ dev->hw_addr[2] = ( orig_mac[0] >> 16 ) & 0xff;
+ dev->hw_addr[3] = ( orig_mac[0] >> 24 ) & 0xff;
+ dev->hw_addr[4] = ( orig_mac[1] >> 0 ) & 0xff;
+ dev->hw_addr[5] = ( orig_mac[1] >> 8 ) & 0xff;
+ } else {
+ /* need to reverse mac address to correct order */
+ dev->hw_addr[0] = ( orig_mac[1] >> 8 ) & 0xff;
+ dev->hw_addr[1] = ( orig_mac[1] >> 0 ) & 0xff;
+ dev->hw_addr[2] = ( orig_mac[0] >> 24 ) & 0xff;
+ dev->hw_addr[3] = ( orig_mac[0] >> 16 ) & 0xff;
+ dev->hw_addr[4] = ( orig_mac[0] >> 8 ) & 0xff;
+ dev->hw_addr[5] = ( orig_mac[0] >> 0 ) & 0xff;
+ }
+
+ if ( ! is_valid_ether_addr ( dev->hw_addr ) )
+ return -EADDRNOTAVAIL;
+
+ DBG ( "MAC address is: %s\n", eth_ntoa ( dev->hw_addr ) );
+
+ return 0;
+}
+
+static int
+nv_mgmt_acquire_sema ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+ int i;
+ u32 tx_ctrl, mgmt_sema;
+
+ for ( i = 0; i < 10; i++ ) {
+ mgmt_sema = readl ( ioaddr + NvRegTransmitterControl ) &
+ NVREG_XMITCTL_MGMT_SEMA_MASK;
+ if ( mgmt_sema == NVREG_XMITCTL_MGMT_SEMA_FREE )
+ break;
+ mdelay ( 500 );
+ }
+
+ if ( mgmt_sema != NVREG_XMITCTL_MGMT_SEMA_FREE )
+ return 0;
+
+ for ( i = 0; i < 2; i++ ) {
+ tx_ctrl = readl ( ioaddr + NvRegTransmitterControl );
+ tx_ctrl |= NVREG_XMITCTL_HOST_SEMA_ACQ;
+ writel ( tx_ctrl, ioaddr + NvRegTransmitterControl );
+
+ /* verify that the semaphore was acquired */
+ tx_ctrl = readl ( ioaddr + NvRegTransmitterControl );
+ if ( ( ( tx_ctrl & NVREG_XMITCTL_HOST_SEMA_MASK ) ==
+ NVREG_XMITCTL_HOST_SEMA_ACQ ) &&
+ ( ( tx_ctrl & NVREG_XMITCTL_MGMT_SEMA_MASK ) ==
+ NVREG_XMITCTL_MGMT_SEMA_FREE ) ) {
+ priv->mgmt_sema = 1;
+ return 1;
+ } else {
+ udelay ( 50 );
+ }
+ }
+
+ return 0;
+}
+
+static void
+nv_mgmt_release_sema ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+ u32 tx_ctrl;
+
+ if ( priv->driver_data & DEV_HAS_MGMT_UNIT ) {
+ if ( priv->mgmt_sema ) {
+ tx_ctrl = readl (ioaddr + NvRegTransmitterControl );
+ tx_ctrl &= ~NVREG_XMITCTL_HOST_SEMA_ACQ;
+ writel ( tx_ctrl, ioaddr + NvRegTransmitterControl );
+ }
+ }
+}
+
+static int
+nv_mgmt_get_version ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+ u32 data_ready = readl ( ioaddr + NvRegTransmitterControl );
+ u32 data_ready2 = 0;
+ unsigned long start;
+ int ready = 0;
+
+ writel ( NVREG_MGMTUNITGETVERSION,
+ ioaddr + NvRegMgmtUnitGetVersion );
+ writel ( data_ready ^ NVREG_XMITCTL_DATA_START,
+ ioaddr + NvRegTransmitterControl );
+ start = currticks();
+
+ while ( currticks() > start + 5 * ticks_per_sec() ) {
+ data_ready2 = readl ( ioaddr + NvRegTransmitterControl );
+ if ( ( data_ready & NVREG_XMITCTL_DATA_READY ) !=
+ ( data_ready2 & NVREG_XMITCTL_DATA_READY ) ) {
+ ready = 1;
+ break;
+ }
+ mdelay ( 1000 );
+ }
+
+ if ( ! ready || ( data_ready2 & NVREG_XMITCTL_DATA_ERROR ) )
+ return 0;
+
+ priv->mgmt_version =
+ readl ( ioaddr + NvRegMgmtUnitVersion ) & NVREG_MGMTUNITVERSION;
+
+ return 1;
+}
+
+
+
+static int
+phy_reset ( struct forcedeth_private *priv, u32 bmcr_setup )
+{
+ u32 miicontrol;
+ unsigned int tries = 0;
+
+ miicontrol = BMCR_RESET | bmcr_setup;
+ if ( mii_rw ( priv, priv->phyaddr, MII_BMCR, miicontrol ) ) {
+ return -1;
+ }
+
+ mdelay ( 500 );
+
+ /* must wait till reset is deasserted */
+ while ( miicontrol & BMCR_RESET ) {
+ mdelay ( 10 );
+ miicontrol = mii_rw ( priv, priv->phyaddr, MII_BMCR, MII_READ );
+ if ( tries++ > 100 )
+ return -1;
+ }
+ return 0;
+}
+
+static int
+phy_init ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+ u32 phyinterface, phy_reserved, mii_status;
+ u32 mii_control, mii_control_1000, reg;
+
+ /* phy errata for E3016 phy */
+ if ( priv->phy_model == PHY_MODEL_MARVELL_E3016 ) {
+ reg = mii_rw ( priv, priv->phyaddr, MII_NCONFIG, MII_READ );
+ reg &= ~PHY_MARVELL_E3016_INITMASK;
+ if ( mii_rw ( priv, priv->phyaddr, MII_NCONFIG, reg ) ) {
+ DBG ( "PHY write to errata reg failed.\n" );
+ return PHY_ERROR;
+ }
+ }
+
+ if ( priv->phy_oui == PHY_OUI_REALTEK ) {
+ if ( priv->phy_model == PHY_MODEL_REALTEK_8211 &&
+ priv->phy_rev == PHY_REV_REALTEK_8211B ) {
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ }
+
+ if ( priv->phy_model == PHY_MODEL_REALTEK_8211 &&
+ priv->phy_rev == PHY_REV_REALTEK_8211C ) {
+ u32 powerstate = readl ( ioaddr + NvRegPowerState2 );
+
+ /* need to perform hw phy reset */
+ powerstate |= NVREG_POWERSTATE2_PHY_RESET;
+ writel ( powerstate , ioaddr + NvRegPowerState2 );
+ mdelay ( 25 );
+
+ powerstate &= ~NVREG_POWERSTATE2_PHY_RESET;
+ writel ( powerstate , ioaddr + NvRegPowerState2 );
+ mdelay ( 25 );
+
+ reg = mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG6, MII_READ );
+ reg |= PHY_REALTEK_INIT9;
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG6, reg ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT10 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+
+ reg = mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG7, MII_READ );
+ if ( ! ( reg & PHY_REALTEK_INIT11 ) ) {
+ reg |= PHY_REALTEK_INIT11;
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG7, reg ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ }
+ if ( priv->phy_model == PHY_MODEL_REALTEK_8201 ) {
+ if ( priv->driver_data & DEV_NEED_PHY_INIT_FIX ) {
+ phy_reserved = mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG6,
+ MII_READ );
+ phy_reserved |= PHY_REALTEK_INIT7;
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG6,
+ phy_reserved ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ }
+ }
+ }
+
+ /* set advertise register */
+ reg = mii_rw ( priv, priv->phyaddr, MII_ADVERTISE, MII_READ );
+ reg |= ( ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF |
+ ADVERTISE_100FULL | ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP );
+ if ( mii_rw ( priv, priv->phyaddr, MII_ADVERTISE, reg ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+
+ /* get phy interface type */
+ phyinterface = readl ( ioaddr + NvRegPhyInterface );
+
+ /* see if gigabit phy */
+ mii_status = mii_rw ( priv, priv->phyaddr, MII_BMSR, MII_READ );
+ if ( mii_status & PHY_GIGABIT ) {
+ priv->gigabit = PHY_GIGABIT;
+ mii_control_1000 =
+ mii_rw ( priv, priv->phyaddr, MII_CTRL1000, MII_READ );
+ mii_control_1000 &= ~ADVERTISE_1000HALF;
+ if ( phyinterface & PHY_RGMII )
+ mii_control_1000 |= ADVERTISE_1000FULL;
+ else
+ mii_control_1000 &= ~ADVERTISE_1000FULL;
+
+ if ( mii_rw ( priv, priv->phyaddr, MII_CTRL1000, mii_control_1000)) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ } else {
+ priv->gigabit = 0;
+ }
+
+ mii_control = mii_rw ( priv, priv->phyaddr, MII_BMCR, MII_READ );
+ mii_control |= BMCR_ANENABLE;
+
+ if ( priv->phy_oui == PHY_OUI_REALTEK &&
+ priv->phy_model == PHY_MODEL_REALTEK_8211 &&
+ priv->phy_rev == PHY_REV_REALTEK_8211C ) {
+ /* start autoneg since we already performed hw reset above */
+ mii_control |= BMCR_ANRESTART;
+ if ( mii_rw ( priv, priv->phyaddr, MII_BMCR, mii_control ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ } else {
+ /* reset the phy
+ * (certain phys need bmcr to be setup with reset )
+ */
+ if ( phy_reset ( priv, mii_control ) ) {
+ DBG ( "PHY reset failed\n" );
+ return PHY_ERROR;
+ }
+ }
+
+ /* phy vendor specific configuration */
+ if ( ( priv->phy_oui == PHY_OUI_CICADA ) && ( phyinterface & PHY_RGMII ) ) {
+ phy_reserved = mii_rw ( priv, priv->phyaddr, MII_RESV1, MII_READ );
+ phy_reserved &= ~( PHY_CICADA_INIT1 | PHY_CICADA_INIT2 );
+ phy_reserved |= ( PHY_CICADA_INIT3 | PHY_CICADA_INIT4 );
+ if ( mii_rw ( priv, priv->phyaddr, MII_RESV1, phy_reserved ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw ( priv, priv->phyaddr, MII_NCONFIG, MII_READ );
+ phy_reserved |= PHY_CICADA_INIT5;
+ if ( mii_rw ( priv, priv->phyaddr, MII_NCONFIG, phy_reserved ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ }
+ if ( priv->phy_oui == PHY_OUI_CICADA ) {
+ phy_reserved = mii_rw ( priv, priv->phyaddr, MII_SREVISION, MII_READ );
+ phy_reserved |= PHY_CICADA_INIT6;
+ if ( mii_rw ( priv, priv->phyaddr, MII_SREVISION, phy_reserved ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ }
+ if ( priv->phy_oui == PHY_OUI_VITESSE ) {
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG1,
+ PHY_VITESSE_INIT1)) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG2,
+ PHY_VITESSE_INIT2)) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw ( priv, priv->phyaddr,
+ PHY_VITESSE_INIT_REG4, MII_READ);
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG4,
+ phy_reserved ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw ( priv, priv->phyaddr,
+ PHY_VITESSE_INIT_REG3, MII_READ);
+ phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
+ phy_reserved |= PHY_VITESSE_INIT3;
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG3,
+ phy_reserved ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG2,
+ PHY_VITESSE_INIT4 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG2,
+ PHY_VITESSE_INIT5 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw ( priv, priv->phyaddr,
+ PHY_VITESSE_INIT_REG4, MII_READ);
+ phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
+ phy_reserved |= PHY_VITESSE_INIT3;
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG4,
+ phy_reserved ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw ( priv, priv->phyaddr,
+ PHY_VITESSE_INIT_REG3, MII_READ);
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG3,
+ phy_reserved ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG2,
+ PHY_VITESSE_INIT6 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG2,
+ PHY_VITESSE_INIT7 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw ( priv, priv->phyaddr,
+ PHY_VITESSE_INIT_REG4, MII_READ);
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG4,
+ phy_reserved ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw ( priv, priv->phyaddr,
+ PHY_VITESSE_INIT_REG3, MII_READ);
+ phy_reserved &= ~PHY_VITESSE_INIT_MSK2;
+ phy_reserved |= PHY_VITESSE_INIT8;
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG3,
+ phy_reserved ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG2,
+ PHY_VITESSE_INIT9 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr, PHY_VITESSE_INIT_REG1,
+ PHY_VITESSE_INIT10 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ }
+
+ if ( priv->phy_oui == PHY_OUI_REALTEK ) {
+ if ( priv->phy_model == PHY_MODEL_REALTEK_8211 &&
+ priv->phy_rev == PHY_REV_REALTEK_8211B ) {
+ /* reset could have cleared these out, set them back */
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ }
+ if ( priv->phy_model == PHY_MODEL_REALTEK_8201 ) {
+ if ( priv->driver_data & DEV_NEED_PHY_INIT_FIX ) {
+ phy_reserved = mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG6,
+ MII_READ );
+ phy_reserved |= PHY_REALTEK_INIT7;
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG6,
+ phy_reserved ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ }
+
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG1,
+ PHY_REALTEK_INIT3 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG2,
+ MII_READ );
+ phy_reserved &= ~PHY_REALTEK_INIT_MSK1;
+ phy_reserved |= PHY_REALTEK_INIT3;
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG2,
+ phy_reserved ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ if ( mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG1,
+ PHY_REALTEK_INIT1 ) ) {
+ DBG ( "PHY init failed.\n" );
+ return PHY_ERROR;
+ }
+ }
+ }
+
+ /* some phys clear out pause advertisement on reset, set it back */
+ mii_rw ( priv, priv->phyaddr, MII_ADVERTISE, reg );
+
+ /* restart auto negotiation, power down phy */
+ mii_control = mii_rw ( priv, priv->phyaddr, MII_BMCR, MII_READ );
+ mii_control |= ( BMCR_ANRESTART | BMCR_ANENABLE );
+ if ( mii_rw ( priv, priv->phyaddr, MII_BMCR, mii_control ) ) {
+ return PHY_ERROR;
+ }
+
+ return 0;
+}
+
+/**
+ * nv_setup_phy - Find PHY and initialize it
+ *
+ * @v priv Driver private structure
+ *
+ * @ret rc Return status code
+ **/
+static int
+nv_setup_phy ( struct forcedeth_private *priv )
+{
+ void *ioaddr = priv->mmio_addr;
+ u32 phystate_orig = 0, phystate;
+ int phyinitialised = 0;
+ u32 powerstate;
+ int rc = 0;
+ int i;
+
+ if ( priv->driver_data & DEV_HAS_POWER_CNTRL ) {
+ /* take phy and nic out of low power mode */
+ powerstate = readl ( ioaddr + NvRegPowerState2 );
+ powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK;
+ if ( ( priv->driver_data & DEV_NEED_LOW_POWER_FIX ) &&
+ ( ( priv->pci_dev->class & 0xff ) >= 0xA3 ) )
+ powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3;
+ writel ( powerstate, ioaddr + NvRegPowerState2 );
+ }
+
+
+ /* clear phy state and temporarily halt phy interrupts */
+ writel ( 0, ioaddr + NvRegMIIMask );
+ phystate = readl ( ioaddr + NvRegAdapterControl );
+ if ( phystate & NVREG_ADAPTCTL_RUNNING ) {
+ phystate_orig = 1;
+ phystate &= ~NVREG_ADAPTCTL_RUNNING;
+ writel ( phystate, ioaddr + NvRegAdapterControl );
+ }
+ writel ( NVREG_MIISTAT_MASK_ALL, ioaddr + NvRegMIIStatus );
+
+ if ( priv->driver_data & DEV_HAS_MGMT_UNIT ) {
+ /* management unit running on the mac? */
+ if ( ( readl ( ioaddr + NvRegTransmitterControl ) & NVREG_XMITCTL_MGMT_ST ) &&
+ ( readl ( ioaddr + NvRegTransmitterControl ) & NVREG_XMITCTL_SYNC_PHY_INIT ) &&
+ nv_mgmt_acquire_sema ( priv ) &&
+ nv_mgmt_get_version ( priv ) ) {
+ priv->mac_in_use = 1;
+ if ( priv->mgmt_version > 0 ) {
+ priv->mac_in_use = readl ( ioaddr + NvRegMgmtUnitControl ) & NVREG_MGMTUNITCONTROL_INUSE;
+ }
+
+ DBG ( "mgmt unit is running. mac in use\n" );
+
+ /* management unit setup the phy already? */
+ if ( priv->mac_in_use &&
+ ( ( readl ( ioaddr + NvRegTransmitterControl ) & NVREG_XMITCTL_SYNC_MASK ) ==
+ NVREG_XMITCTL_SYNC_PHY_INIT ) ) {
+ /* phy is inited by mgmt unit */
+ phyinitialised = 1;
+ DBG ( "Phy already initialized by mgmt unit" );
+ }
+ }
+ }
+
+ /* find a suitable phy */
+ for ( i = 1; i <= 32; i++ ) {
+ int id1, id2;
+ int phyaddr = i & 0x1f;
+
+ id1 = mii_rw ( priv, phyaddr, MII_PHYSID1, MII_READ );
+ if ( id1 < 0 || id1 == 0xffff )
+ continue;
+ id2 = mii_rw ( priv, phyaddr, MII_PHYSID2, MII_READ );
+ if ( id2 < 0 || id2 == 0xffff )
+ continue;
+
+ priv->phy_model = id2 & PHYID2_MODEL_MASK;
+ id1 = ( id1 & PHYID1_OUI_MASK ) << PHYID1_OUI_SHFT;
+ id2 = ( id2 & PHYID2_OUI_MASK ) >> PHYID2_OUI_SHFT;
+ DBG ( "Found PHY: %04x:%04x at address %d\n", id1, id2, phyaddr );
+ priv->phyaddr = phyaddr;
+ priv->phy_oui = id1 | id2;
+
+ /* Realtek hardcoded phy id1 to all zeros on certain phys */
+ if ( priv->phy_oui == PHY_OUI_REALTEK2 )
+ priv->phy_oui = PHY_OUI_REALTEK;
+ /* Setup phy revision for Realtek */
+ if ( priv->phy_oui == PHY_OUI_REALTEK &&
+ priv->phy_model == PHY_MODEL_REALTEK_8211 )
+ priv->phy_rev = mii_rw ( priv, phyaddr, MII_RESV1,
+ MII_READ ) & PHY_REV_MASK;
+ break;
+ }
+ if ( i == 33 ) {
+ DBG ( "Could not find a valid PHY.\n" );
+ rc = -ENODEV;
+ goto err_phy;
+ }
+
+ if ( ! phyinitialised ) {
+ /* reset it */
+ phy_init ( priv );
+ } else {
+ u32 mii_status = mii_rw ( priv, priv->phyaddr, MII_BMSR, MII_READ );
+ if ( mii_status & PHY_GIGABIT ) {
+ priv->gigabit = PHY_GIGABIT;
+ }
+ }
+
+ return 0;
+
+err_phy:
+ if ( phystate_orig )
+ writel ( phystate | NVREG_ADAPTCTL_RUNNING,
+ ioaddr + NvRegAdapterControl );
+ return rc;
+}
+
+/**
+ * forcedeth_map_regs - Find a suitable BAR for the NIC and
+ * map the registers in memory
+ *
+ * @v priv Driver private structure
+ *
+ * @ret rc Return status code
+ **/
+static int
+forcedeth_map_regs ( struct forcedeth_private *priv )
+{
+ void *ioaddr;
+ uint32_t bar;
+ unsigned long addr;
+ u32 register_size;
+ int reg;
+ int rc;
+
+ /* Set register size based on NIC */
+ if ( priv->driver_data & ( DEV_HAS_VLAN | DEV_HAS_MSI_X |
+ DEV_HAS_POWER_CNTRL | DEV_HAS_STATISTICS_V2 |
+ DEV_HAS_STATISTICS_V3 ) ) {
+ register_size = NV_PCI_REGSZ_VER3;
+ } else if ( priv->driver_data & DEV_HAS_STATISTICS_V1 ) {
+ register_size = NV_PCI_REGSZ_VER2;
+ } else {
+ register_size = NV_PCI_REGSZ_VER1;
+ }
+
+ /* Find an appropriate region for all the registers */
+ rc = -EINVAL;
+ addr = 0;
+ for ( reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4 ) {
+ pci_read_config_dword ( priv->pci_dev, reg, &bar );
+
+ if ( ( ( bar & PCI_BASE_ADDRESS_SPACE ) ==
+ PCI_BASE_ADDRESS_SPACE_MEMORY ) &&
+ ( pci_bar_size ( priv->pci_dev, reg ) >=
+ register_size ) ) {
+ addr = pci_bar_start ( priv->pci_dev, reg );
+ break;
+ }
+ }
+
+ if ( reg > PCI_BASE_ADDRESS_5 ) {
+ DBG ( "Couldn't find register window\n" );
+ goto err_bar_sz;
+ }
+
+ rc = -ENOMEM;
+ ioaddr = ioremap ( addr, register_size );
+ if ( ! ioaddr ) {
+ DBG ( "Cannot remap MMIO\n" );
+ goto err_ioremap;
+ }
+
+ priv->mmio_addr = ioaddr;
+
+ return 0;
+
+err_bar_sz:
+err_ioremap:
+ return rc;
+}
+
+/**
+ * probe - Initial configuration of NIC
+ *
+ * @v pdev PCI device
+ * @v ent PCI IDs
+ *
+ * @ret rc Return status code
+ **/
+static int
+forcedeth_probe ( struct pci_device *pdev )
+{
+ struct net_device *netdev;
+ struct forcedeth_private *priv;
+ void *ioaddr;
+ int rc;
+
+ DBGP ( "forcedeth_probe\n" );
+
+ DBG ( "Found %s, vendor = %#04x, device = %#04x\n",
+ pdev->id->name, pdev->id->vendor, pdev->id->device );
+
+ /* Allocate our private data */
+ netdev = alloc_etherdev ( sizeof ( *priv ) );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ DBG ( "Failed to allocate net device\n" );
+ goto err_alloc_etherdev;
+ }
+
+ /* Link our operations to the netdev struct */
+ netdev_init ( netdev, &forcedeth_operations );
+
+ /* Link the PCI device to the netdev struct */
+ pci_set_drvdata ( pdev, netdev );
+ netdev->dev = &pdev->dev;
+
+ /* Get a reference to our private data */
+ priv = netdev_priv ( netdev );
+
+ /* We'll need these set up for the rest of the routines */
+ priv->pci_dev = pdev;
+ priv->netdev = netdev;
+ priv->driver_data = pdev->id->driver_data;
+
+ adjust_pci_device ( pdev );
+
+ /* Use memory mapped I/O */
+ if ( ( rc = forcedeth_map_regs ( priv ) ) != 0 )
+ goto err_map_regs;
+ ioaddr = priv->mmio_addr;
+
+ /* Verify and get MAC address */
+ if ( ( rc = nv_setup_mac_addr ( priv ) ) != 0 ) {
+ DBG ( "Invalid MAC address detected\n" );
+ goto err_mac_addr;
+ }
+
+ /* Disable WOL */
+ writel ( 0, ioaddr + NvRegWakeUpFlags );
+
+ if ( ( rc = nv_setup_phy ( priv ) ) != 0 )
+ goto err_setup_phy;
+
+ /* Set Pause Frame parameters */
+ priv->pause_flags = NV_PAUSEFRAME_RX_CAPABLE |
+ NV_PAUSEFRAME_RX_REQ |
+ NV_PAUSEFRAME_AUTONEG;
+ if ( ( priv->driver_data & DEV_HAS_PAUSEFRAME_TX_V1 ) ||
+ ( priv->driver_data & DEV_HAS_PAUSEFRAME_TX_V2 ) ||
+ ( priv->driver_data & DEV_HAS_PAUSEFRAME_TX_V3 ) ) {
+ priv->pause_flags |= NV_PAUSEFRAME_TX_CAPABLE | NV_PAUSEFRAME_TX_REQ;
+ }
+
+ if ( priv->pause_flags & NV_PAUSEFRAME_TX_CAPABLE )
+ writel ( NVREG_TX_PAUSEFRAME_DISABLE, ioaddr + NvRegTxPauseFrame );
+
+ /* Set default link speed settings */
+ priv->linkspeed = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
+ priv->duplex = 0;
+
+ if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
+ DBG ( "Error registering netdev\n" );
+ goto err_register_netdev;
+ }
+
+ forcedeth_link_status ( netdev );
+
+ return 0;
+
+err_register_netdev:
+err_setup_phy:
+err_mac_addr:
+ iounmap ( priv->mmio_addr );
+err_map_regs:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+err_alloc_etherdev:
+ return rc;
+}
+
+static void
+nv_restore_phy ( struct forcedeth_private *priv )
+{
+ u16 phy_reserved, mii_control;
+
+ if ( priv->phy_oui == PHY_OUI_REALTEK &&
+ priv->phy_model == PHY_MODEL_REALTEK_8201 ) {
+ mii_rw ( priv, priv->phyaddr, PHY_REALTEK_INIT_REG1,
+ PHY_REALTEK_INIT3 );
+ phy_reserved = mii_rw ( priv, priv->phyaddr,
+ PHY_REALTEK_INIT_REG2, MII_READ );
+ phy_reserved &= ~PHY_REALTEK_INIT_MSK1;
+ phy_reserved |= PHY_REALTEK_INIT8;
+ mii_rw ( priv, priv->phyaddr, PHY_REALTEK_INIT_REG2,
+ phy_reserved );
+ mii_rw ( priv, priv->phyaddr, PHY_REALTEK_INIT_REG1,
+ PHY_REALTEK_INIT1 );
+
+ /* restart auto negotiation */
+ mii_control = mii_rw ( priv, priv->phyaddr, MII_BMCR, MII_READ );
+ mii_control |= ( BMCR_ANRESTART | BMCR_ANENABLE );
+ mii_rw ( priv, priv->phyaddr, MII_BMCR, mii_control );
+ }
+}
+
+/**
+ * remove - Device Removal Routine
+ *
+ * @v pdev PCI device information struct
+ **/
+static void
+forcedeth_remove ( struct pci_device *pdev )
+{
+ struct net_device *netdev = pci_get_drvdata ( pdev );
+ struct forcedeth_private *priv = netdev->priv;
+
+ DBGP ( "forcedeth_remove\n" );
+
+ unregister_netdev ( netdev );
+
+ nv_restore_phy ( priv );
+
+ nv_mgmt_release_sema ( priv );
+
+ iounmap ( priv->mmio_addr );
+
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+static struct pci_device_id forcedeth_nics[] = {
+ PCI_ROM(0x10DE, 0x01C3, "nForce", "nForce Ethernet Controller", DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER),
+ PCI_ROM(0x10DE, 0x0066, "nForce2", "nForce2 Ethernet Controller", DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER),
+ PCI_ROM(0x10DE, 0x00D6, "nForce3", "nForce3 Ethernet Controller", DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER),
+ PCI_ROM(0x10DE, 0x0086, "nForce3", "nForce3 Ethernet Controller", DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC| DEV_HAS_CHECKSUM),
+ PCI_ROM(0x10DE, 0x008C, "nForce3", "nForce3 Ethernet Controller", DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC| DEV_HAS_CHECKSUM),
+ PCI_ROM(0x10DE, 0x00E6, "nForce3", "nForce3 Ethernet Controller", DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC| DEV_HAS_CHECKSUM),
+ PCI_ROM(0x10DE, 0x00DF, "nForce3", "nForce3 Ethernet Controller", DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC| DEV_HAS_CHECKSUM),
+ PCI_ROM(0x10DE, 0x0056, "CK804", "CK804 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM| DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT),
+ PCI_ROM(0x10DE, 0x0057, "CK804", "CK804 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM| DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT),
+ PCI_ROM(0x10DE, 0x0037, "MCP04", "MCP04 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM| DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT),
+ PCI_ROM(0x10DE, 0x0038, "MCP04", "MCP04 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM| DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT),
+ PCI_ROM(0x10DE, 0x0268, "MCP51", "MCP51 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_STATISTICS_V1|DEV_NEED_LOW_POWER_FIX),
+ PCI_ROM(0x10DE, 0x0269, "MCP51", "MCP51 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_STATISTICS_V1|DEV_NEED_LOW_POWER_FIX),
+ PCI_ROM(0x10DE, 0x0372, "MCP55", "MCP55 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM| DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X| DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1| DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED| DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0373, "MCP55", "MCP55 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM| DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X| DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1| DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT| DEV_NEED_TX_LIMIT|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x03E5, "MCP61", "MCP61 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2| DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR| DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x03E6, "MCP61", "MCP61 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2| DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR| DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x03EE, "MCP61", "MCP61 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2| DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR| DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x03EF, "MCP61", "MCP61 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2| DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR| DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0450, "MCP65", "MCP65 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA| DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1| DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT| DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE| DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0451, "MCP65", "MCP65 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA| DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1| DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT| DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE| DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0452, "MCP65", "MCP65 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA| DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1| DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT| DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE| DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0453, "MCP65", "MCP65 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA| DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1| DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT| DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE| DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x054C, "MCP67", "MCP67 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2| DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR| DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x054D, "MCP67", "MCP67 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2| DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR| DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x054E, "MCP67", "MCP67 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2| DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR| DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x054F, "MCP67", "MCP67 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2| DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR| DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x07DC, "MCP73", "MCP73 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2| DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR| DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x07DD, "MCP73", "MCP73 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2| DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR| DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x07DE, "MCP73", "MCP73 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2| DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR| DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x07DF, "MCP73", "MCP73 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL| DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2| DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR| DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0760, "MCP77", "MCP77 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA| DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2| DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT| DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX| DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX| DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0761, "MCP77", "MCP77 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA| DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2| DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT| DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX| DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX| DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0762, "MCP77", "MCP77 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA| DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2| DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT| DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX| DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX| DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0763, "MCP77", "MCP77 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA| DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2| DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT| DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX| DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX| DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0AB0, "MCP79", "MCP79 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM| DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL| DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3| DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR| DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE| DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0AB1, "MCP79", "MCP79 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM| DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL| DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3| DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR| DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE| DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0AB2, "MCP79", "MCP79 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM| DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL| DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3| DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR| DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE| DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0AB3, "MCP79", "MCP79 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM| DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL| DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3| DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR| DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE| DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX),
+ PCI_ROM(0x10DE, 0x0D7D, "MCP89", "MCP89 Ethernet Controller", DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM| DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL| DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3| DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR| DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX),
+};
+
+struct pci_driver forcedeth_driver __pci_driver = {
+ .ids = forcedeth_nics,
+ .id_count = ARRAY_SIZE(forcedeth_nics),
+ .probe = forcedeth_probe,
+ .remove = forcedeth_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/forcedeth.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/forcedeth.h
new file mode 100644
index 00000000..70686d15
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/forcedeth.h
@@ -0,0 +1,601 @@
+/*
+ * forcedeth.h -- Driver for NVIDIA nForce media access controllers for iPXE
+ * Copyright (c) 2010 Andrei Faur <da3drus@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Portions of this code are taken from the Linux forcedeth driver that was
+ * based on a cleanroom reimplementation which was based on reverse engineered
+ * documentation written by Carl-Daniel Hailfinger and Andrew de Quincey:
+ * Copyright (C) 2003,4,5 Manfred Spraul
+ * Copyright (C) 2004 Andrew de Quincey (wol support)
+ * Copyright (C) 2004 Carl-Daniel Hailfinger (invalid MAC handling, insane
+ * IRQ rate fixes, bigendian fixes, cleanups, verification)
+ * Copyright (c) 2004,2005,2006,2007,2008,2009 NVIDIA Corporation
+ *
+ * This header is a direct copy of #define lines and structs found in the
+ * above mentioned driver, modified where necessary to make them work for iPXE.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef _FORCEDETH_H_
+#define _FORCEDETH_H_
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+struct ring_desc {
+ u32 buf;
+ u32 flaglen;
+};
+
+struct ring_desc_ex {
+ u32 bufhigh;
+ u32 buflow;
+ u32 txvlan;
+ u32 flaglen;
+};
+
+#define DESC_VER_1 1
+#define DESC_VER_2 2
+#define DESC_VER_3 3
+
+#define RX_RING_SIZE 16
+#define TX_RING_SIZE 16
+#define RXTX_RING_SIZE ( ( RX_RING_SIZE ) + ( TX_RING_SIZE ) )
+#define RX_RING_MIN 128
+#define TX_RING_MIN 64
+#define RING_MAX_DESC_VER_1 1024
+#define RING_MAX_DESC_VER_2_3 16384
+
+#define NV_RX_ALLOC_PAD (64)
+
+#define NV_RX_HEADERS (64)
+
+#define RX_BUF_SZ ( ( ETH_FRAME_LEN ) + ( NV_RX_HEADERS ) )
+
+#define NV_PKTLIMIT_1 1500
+#define NV_PKTLIMIT_2 9100
+
+#define NV_LINK_POLL_FREQUENCY 128
+
+/* PHY defines */
+#define PHY_OUI_MARVELL 0x5043
+#define PHY_OUI_CICADA 0x03f1
+#define PHY_OUI_VITESSE 0x01c1
+#define PHY_OUI_REALTEK 0x0732
+#define PHY_OUI_REALTEK2 0x0020
+#define PHYID1_OUI_MASK 0x03ff
+#define PHYID1_OUI_SHFT 6
+#define PHYID2_OUI_MASK 0xfc00
+#define PHYID2_OUI_SHFT 10
+#define PHYID2_MODEL_MASK 0x03f0
+#define PHY_MODEL_REALTEK_8211 0x0110
+#define PHY_REV_MASK 0x0001
+#define PHY_REV_REALTEK_8211B 0x0000
+#define PHY_REV_REALTEK_8211C 0x0001
+#define PHY_MODEL_REALTEK_8201 0x0200
+#define PHY_MODEL_MARVELL_E3016 0x0220
+#define PHY_MARVELL_E3016_INITMASK 0x0300
+#define PHY_CICADA_INIT1 0x0f000
+#define PHY_CICADA_INIT2 0x0e00
+#define PHY_CICADA_INIT3 0x01000
+#define PHY_CICADA_INIT4 0x0200
+#define PHY_CICADA_INIT5 0x0004
+#define PHY_CICADA_INIT6 0x02000
+#define PHY_VITESSE_INIT_REG1 0x1f
+#define PHY_VITESSE_INIT_REG2 0x10
+#define PHY_VITESSE_INIT_REG3 0x11
+#define PHY_VITESSE_INIT_REG4 0x12
+#define PHY_VITESSE_INIT_MSK1 0xc
+#define PHY_VITESSE_INIT_MSK2 0x0180
+#define PHY_VITESSE_INIT1 0x52b5
+#define PHY_VITESSE_INIT2 0xaf8a
+#define PHY_VITESSE_INIT3 0x8
+#define PHY_VITESSE_INIT4 0x8f8a
+#define PHY_VITESSE_INIT5 0xaf86
+#define PHY_VITESSE_INIT6 0x8f86
+#define PHY_VITESSE_INIT7 0xaf82
+#define PHY_VITESSE_INIT8 0x0100
+#define PHY_VITESSE_INIT9 0x8f82
+#define PHY_VITESSE_INIT10 0x0
+#define PHY_REALTEK_INIT_REG1 0x1f
+#define PHY_REALTEK_INIT_REG2 0x19
+#define PHY_REALTEK_INIT_REG3 0x13
+#define PHY_REALTEK_INIT_REG4 0x14
+#define PHY_REALTEK_INIT_REG5 0x18
+#define PHY_REALTEK_INIT_REG6 0x11
+#define PHY_REALTEK_INIT_REG7 0x01
+#define PHY_REALTEK_INIT1 0x0000
+#define PHY_REALTEK_INIT2 0x8e00
+#define PHY_REALTEK_INIT3 0x0001
+#define PHY_REALTEK_INIT4 0xad17
+#define PHY_REALTEK_INIT5 0xfb54
+#define PHY_REALTEK_INIT6 0xf5c7
+#define PHY_REALTEK_INIT7 0x1000
+#define PHY_REALTEK_INIT8 0x0003
+#define PHY_REALTEK_INIT9 0x0008
+#define PHY_REALTEK_INIT10 0x0005
+#define PHY_REALTEK_INIT11 0x0200
+#define PHY_REALTEK_INIT_MSK1 0x0003
+
+#define PHY_GIGABIT 0x0100
+
+#define PHY_TIMEOUT 0x1
+#define PHY_ERROR 0x2
+
+#define PHY_100 0x1
+#define PHY_1000 0x2
+#define PHY_HALF 0x100
+
+
+#define NV_PAUSEFRAME_RX_CAPABLE 0x0001
+#define NV_PAUSEFRAME_TX_CAPABLE 0x0002
+#define NV_PAUSEFRAME_RX_ENABLE 0x0004
+#define NV_PAUSEFRAME_TX_ENABLE 0x0008
+#define NV_PAUSEFRAME_RX_REQ 0x0010
+#define NV_PAUSEFRAME_TX_REQ 0x0020
+#define NV_PAUSEFRAME_AUTONEG 0x0040
+
+/* MSI/MSI-X defines */
+#define NV_MSI_X_MAX_VECTORS 8
+#define NV_MSI_X_VECTORS_MASK 0x000f
+#define NV_MSI_CAPABLE 0x0010
+#define NV_MSI_X_CAPABLE 0x0020
+#define NV_MSI_ENABLED 0x0040
+#define NV_MSI_X_ENABLED 0x0080
+
+#define NV_MSI_X_VECTOR_ALL 0x0
+#define NV_MSI_X_VECTOR_RX 0x0
+#define NV_MSI_X_VECTOR_TX 0x1
+#define NV_MSI_X_VECTOR_OTHER 0x2
+
+#define NV_MSI_PRIV_OFFSET 0x68
+#define NV_MSI_PRIV_VALUE 0xffffffff
+
+
+#define NV_MIIBUSY_DELAY 50
+#define NV_MIIPHY_DELAY 10
+#define NV_MIIPHY_DELAYMAX 10000
+
+/* Hardware access */
+#define DEV_NEED_TIMERIRQ 0x0000001 /* set the timer irq flag in the irq mask */
+#define DEV_NEED_LINKTIMER 0x0000002 /* poll link settings. Relies on the timer irq */
+#define DEV_HAS_LARGEDESC 0x0000004 /* device supports jumbo frames and needs packet format 2 */
+#define DEV_HAS_HIGH_DMA 0x0000008 /* device supports 64bit dma */
+#define DEV_HAS_CHECKSUM 0x0000010 /* device supports tx and rx checksum offloads */
+#define DEV_HAS_VLAN 0x0000020 /* device supports vlan tagging and striping */
+#define DEV_HAS_MSI 0x0000040 /* device supports MSI */
+#define DEV_HAS_MSI_X 0x0000080 /* device supports MSI-X */
+#define DEV_HAS_POWER_CNTRL 0x0000100 /* device supports power savings */
+#define DEV_HAS_STATISTICS_V1 0x0000200 /* device supports hw statistics version 1 */
+#define DEV_HAS_STATISTICS_V2 0x0000600 /* device supports hw statistics version 2 */
+#define DEV_HAS_STATISTICS_V3 0x0000e00 /* device supports hw statistics version 3 */
+#define DEV_HAS_TEST_EXTENDED 0x0001000 /* device supports extended diagnostic test */
+#define DEV_HAS_MGMT_UNIT 0x0002000 /* device supports management unit */
+#define DEV_HAS_CORRECT_MACADDR 0x0004000 /* device supports correct mac address order */
+#define DEV_HAS_COLLISION_FIX 0x0008000 /* device supports tx collision fix */
+#define DEV_HAS_PAUSEFRAME_TX_V1 0x0010000 /* device supports tx pause frames version 1 */
+#define DEV_HAS_PAUSEFRAME_TX_V2 0x0020000 /* device supports tx pause frames version 2 */
+#define DEV_HAS_PAUSEFRAME_TX_V3 0x0040000 /* device supports tx pause frames version 3 */
+#define DEV_NEED_TX_LIMIT 0x0080000 /* device needs to limit tx */
+#define DEV_NEED_TX_LIMIT2 0x0180000 /* device needs to limit tx, expect for some revs */
+#define DEV_HAS_GEAR_MODE 0x0200000 /* device supports gear mode */
+#define DEV_NEED_PHY_INIT_FIX 0x0400000 /* device needs specific phy workaround */
+#define DEV_NEED_LOW_POWER_FIX 0x0800000 /* device needs special power up workaround */
+#define DEV_NEED_MSI_FIX 0x1000000 /* device needs msi workaround */
+
+#define FLAG_MASK_V1 0xffff0000
+#define FLAG_MASK_V2 0xffffc000
+#define LEN_MASK_V1 (0xffffffff ^ FLAG_MASK_V1)
+#define LEN_MASK_V2 (0xffffffff ^ FLAG_MASK_V2)
+
+#define NV_TX_LASTPACKET (1<<16)
+#define NV_TX_RETRYERROR (1<<19)
+#define NV_TX_RETRYCOUNT_MASK (0xF<<20)
+#define NV_TX_FORCED_INTERRUPT (1<<24)
+#define NV_TX_DEFERRED (1<<26)
+#define NV_TX_CARRIERLOST (1<<27)
+#define NV_TX_LATECOLLISION (1<<28)
+#define NV_TX_UNDERFLOW (1<<29)
+#define NV_TX_ERROR (1<<30)
+#define NV_TX_VALID (1<<31)
+
+#define NV_TX2_LASTPACKET (1<<29)
+#define NV_TX2_RETRYERROR (1<<18)
+#define NV_TX2_RETRYCOUNT_MASK (0xF<<19)
+#define NV_TX2_FORCED_INTERRUPT (1<<30)
+#define NV_TX2_DEFERRED (1<<25)
+#define NV_TX2_CARRIERLOST (1<<26)
+#define NV_TX2_LATECOLLISION (1<<27)
+#define NV_TX2_UNDERFLOW (1<<28)
+/* error and valid are the same for both */
+#define NV_TX2_ERROR (1<<30)
+#define NV_TX2_VALID (1<<31)
+#define NV_TX2_TSO (1<<28)
+#define NV_TX2_TSO_SHIFT 14
+#define NV_TX2_TSO_MAX_SHIFT 14
+#define NV_TX2_TSO_MAX_SIZE (1<<NV_TX2_TSO_MAX_SHIFT)
+#define NV_TX2_CHECKSUM_L3 (1<<27)
+#define NV_TX2_CHECKSUM_L4 (1<<26)
+
+#define NV_TX3_VLAN_TAG_PRESENT (1<<18)
+
+#define NV_RX_DESCRIPTORVALID (1<<16)
+#define NV_RX_MISSEDFRAME (1<<17)
+#define NV_RX_SUBSTRACT1 (1<<18)
+#define NV_RX_ERROR1 (1<<23)
+#define NV_RX_ERROR2 (1<<24)
+#define NV_RX_ERROR3 (1<<25)
+#define NV_RX_ERROR4 (1<<26)
+#define NV_RX_CRCERR (1<<27)
+#define NV_RX_OVERFLOW (1<<28)
+#define NV_RX_FRAMINGERR (1<<29)
+#define NV_RX_ERROR (1<<30)
+#define NV_RX_AVAIL (1<<31)
+#define NV_RX_ERROR_MASK (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3|NV_RX_ERROR4|NV_RX_CRCERR|NV_RX_OVERFLOW|NV_RX_FRAMINGERR)
+
+#define NV_RX2_CHECKSUMMASK (0x1C000000)
+#define NV_RX2_CHECKSUM_IP (0x10000000)
+#define NV_RX2_CHECKSUM_IP_TCP (0x14000000)
+#define NV_RX2_CHECKSUM_IP_UDP (0x18000000)
+#define NV_RX2_DESCRIPTORVALID (1<<29)
+#define NV_RX2_SUBSTRACT1 (1<<25)
+#define NV_RX2_ERROR1 (1<<18)
+#define NV_RX2_ERROR2 (1<<19)
+#define NV_RX2_ERROR3 (1<<20)
+#define NV_RX2_ERROR4 (1<<21)
+#define NV_RX2_CRCERR (1<<22)
+#define NV_RX2_OVERFLOW (1<<23)
+#define NV_RX2_FRAMINGERR (1<<24)
+/* error and avail are the same for both */
+#define NV_RX2_ERROR (1<<30)
+#define NV_RX2_AVAIL (1<<31)
+#define NV_RX2_ERROR_MASK (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3|NV_RX2_ERROR4|NV_RX2_CRCERR|NV_RX2_OVERFLOW|NV_RX2_FRAMINGERR)
+
+#define NV_RX3_VLAN_TAG_PRESENT (1<<16)
+#define NV_RX3_VLAN_TAG_MASK (0x0000FFFF)
+
+/* Miscellaneous hardware related defines */
+#define NV_PCI_REGSZ_VER1 0x270
+#define NV_PCI_REGSZ_VER2 0x2d4
+#define NV_PCI_REGSZ_VER3 0x604
+#define NV_PCI_REGSZ_MAX 0x604
+
+/* various timeout delays: all in usec */
+#define NV_TXRX_RESET_DELAY 4
+#define NV_TXSTOP_DELAY1 10
+#define NV_TXSTOP_DELAY1MAX 500000
+#define NV_TXSTOP_DELAY2 100
+#define NV_RXSTOP_DELAY1 10
+#define NV_RXSTOP_DELAY1MAX 500000
+#define NV_RXSTOP_DELAY2 100
+#define NV_SETUP5_DELAY 5
+#define NV_SETUP5_DELAYMAX 50000
+#define NV_POWERUP_DELAY 5
+#define NV_POWERUP_DELAYMAX 5000
+#define NV_MIIBUSY_DELAY 50
+#define NV_MIIPHY_DELAY 10
+#define NV_MIIPHY_DELAYMAX 10000
+#define NV_MAC_RESET_DELAY 64
+
+#define NV_MSI_X_CAPABLE 0x0020
+
+#define MII_READ (-1)
+
+struct forcedeth_private {
+ struct pci_device *pci_dev;
+ struct net_device *netdev;
+
+ void *mmio_addr;
+
+ u32 linkspeed;
+ int duplex;
+
+ int phyaddr;
+ unsigned int phy_oui;
+ unsigned int phy_rev;
+ unsigned int phy_model;
+
+ u16 gigabit;
+ u32 mac_in_use;
+ int mgmt_version;
+ int mgmt_sema;
+
+ /* rx specific fields */
+ struct ring_desc *rx_ring;
+ struct io_buffer *rx_iobuf[RX_RING_SIZE];
+ int rx_curr;
+
+ /* tx specific fields */
+ struct ring_desc *tx_ring;
+ struct io_buffer *tx_iobuf[TX_RING_SIZE];
+ int tx_fill_ctr;
+ int tx_curr;
+ int tx_tail;
+
+ /* flow control */
+ u32 pause_flags;
+
+ unsigned long driver_data;
+};
+
+enum {
+ NvRegIrqStatus = 0x000,
+#define NVREG_IRQSTAT_MIIEVENT 0x040
+#define NVREG_IRQSTAT_MASK 0x83ff
+ NvRegIrqMask = 0x004,
+#define NVREG_IRQ_RX_ERROR 0x0001
+#define NVREG_IRQ_RX 0x0002
+#define NVREG_IRQ_RX_NOBUF 0x0004
+#define NVREG_IRQ_TX_ERR 0x0008
+#define NVREG_IRQ_TX_OK 0x0010
+#define NVREG_IRQ_TIMER 0x0020
+#define NVREG_IRQ_LINK 0x0040
+#define NVREG_IRQ_RX_FORCED 0x0080
+#define NVREG_IRQ_TX_FORCED 0x0100
+#define NVREG_IRQ_RECOVER_ERROR 0x8200
+#define NVREG_IRQMASK_THROUGHPUT 0x00df
+#define NVREG_IRQMASK_CPU 0x0060
+#define NVREG_IRQ_TX_ALL (NVREG_IRQ_TX_ERR|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_FORCED)
+#define NVREG_IRQ_RX_ALL (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_RX_FORCED)
+#define NVREG_IRQ_OTHER (NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RECOVER_ERROR)
+
+ NvRegUnknownSetupReg6 = 0x008,
+#define NVREG_UNKSETUP6_VAL 3
+
+/*
+ * NVREG_POLL_DEFAULT is the interval length of the timer source on the nic
+ * NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms
+ */
+ NvRegPollingInterval = 0x00c,
+#define NVREG_POLL_DEFAULT_THROUGHPUT 65535 /* backup tx cleanup if loop max reached */
+#define NVREG_POLL_DEFAULT_CPU 13
+ NvRegMSIMap0 = 0x020,
+ NvRegMSIMap1 = 0x024,
+ NvRegMSIIrqMask = 0x030,
+#define NVREG_MSI_VECTOR_0_ENABLED 0x01
+ NvRegMisc1 = 0x080,
+#define NVREG_MISC1_PAUSE_TX 0x01
+#define NVREG_MISC1_HD 0x02
+#define NVREG_MISC1_FORCE 0x3b0f3c
+
+ NvRegMacReset = 0x34,
+#define NVREG_MAC_RESET_ASSERT 0x0F3
+ NvRegTransmitterControl = 0x084,
+#define NVREG_XMITCTL_START 0x01
+#define NVREG_XMITCTL_MGMT_ST 0x40000000
+#define NVREG_XMITCTL_SYNC_MASK 0x000f0000
+#define NVREG_XMITCTL_SYNC_NOT_READY 0x0
+#define NVREG_XMITCTL_SYNC_PHY_INIT 0x00040000
+#define NVREG_XMITCTL_MGMT_SEMA_MASK 0x00000f00
+#define NVREG_XMITCTL_MGMT_SEMA_FREE 0x0
+#define NVREG_XMITCTL_HOST_SEMA_MASK 0x0000f000
+#define NVREG_XMITCTL_HOST_SEMA_ACQ 0x0000f000
+#define NVREG_XMITCTL_HOST_LOADED 0x00004000
+#define NVREG_XMITCTL_TX_PATH_EN 0x01000000
+#define NVREG_XMITCTL_DATA_START 0x00100000
+#define NVREG_XMITCTL_DATA_READY 0x00010000
+#define NVREG_XMITCTL_DATA_ERROR 0x00020000
+ NvRegTransmitterStatus = 0x088,
+#define NVREG_XMITSTAT_BUSY 0x01
+
+ NvRegPacketFilterFlags = 0x8c,
+#define NVREG_PFF_PAUSE_RX 0x08
+#define NVREG_PFF_ALWAYS 0x7F0000
+#define NVREG_PFF_PROMISC 0x80
+#define NVREG_PFF_MYADDR 0x20
+#define NVREG_PFF_LOOPBACK 0x10
+
+ NvRegOffloadConfig = 0x90,
+#define NVREG_OFFLOAD_HOMEPHY 0x601
+#define NVREG_OFFLOAD_NORMAL RX_NIC_BUFSIZE
+ NvRegReceiverControl = 0x094,
+#define NVREG_RCVCTL_START 0x01
+#define NVREG_RCVCTL_RX_PATH_EN 0x01000000
+ NvRegReceiverStatus = 0x98,
+#define NVREG_RCVSTAT_BUSY 0x01
+
+ NvRegSlotTime = 0x9c,
+#define NVREG_SLOTTIME_LEGBF_ENABLED 0x80000000
+#define NVREG_SLOTTIME_10_100_FULL 0x00007f00
+#define NVREG_SLOTTIME_1000_FULL 0x0003ff00
+#define NVREG_SLOTTIME_HALF 0x0000ff00
+#define NVREG_SLOTTIME_DEFAULT 0x00007f00
+#define NVREG_SLOTTIME_MASK 0x000000ff
+
+ NvRegTxDeferral = 0xA0,
+#define NVREG_TX_DEFERRAL_DEFAULT 0x15050f
+#define NVREG_TX_DEFERRAL_RGMII_10_100 0x16070f
+#define NVREG_TX_DEFERRAL_RGMII_1000 0x14050f
+#define NVREG_TX_DEFERRAL_RGMII_STRETCH_10 0x16190f
+#define NVREG_TX_DEFERRAL_RGMII_STRETCH_100 0x16300f
+#define NVREG_TX_DEFERRAL_MII_STRETCH 0x152000
+ NvRegRxDeferral = 0xA4,
+#define NVREG_RX_DEFERRAL_DEFAULT 0x16
+ NvRegMacAddrA = 0xA8,
+ NvRegMacAddrB = 0xAC,
+ NvRegMulticastAddrA = 0xB0,
+#define NVREG_MCASTADDRA_FORCE 0x01
+ NvRegMulticastAddrB = 0xB4,
+ NvRegMulticastMaskA = 0xB8,
+#define NVREG_MCASTMASKA_NONE 0xffffffff
+ NvRegMulticastMaskB = 0xBC,
+#define NVREG_MCASTMASKB_NONE 0xffff
+
+ NvRegPhyInterface = 0xC0,
+#define PHY_RGMII 0x10000000
+ NvRegBackOffControl = 0xC4,
+#define NVREG_BKOFFCTRL_DEFAULT 0x70000000
+#define NVREG_BKOFFCTRL_SEED_MASK 0x000003ff
+#define NVREG_BKOFFCTRL_SELECT 24
+#define NVREG_BKOFFCTRL_GEAR 12
+
+ NvRegTxRingPhysAddr = 0x100,
+ NvRegRxRingPhysAddr = 0x104,
+ NvRegRingSizes = 0x108,
+#define NVREG_RINGSZ_TXSHIFT 0
+#define NVREG_RINGSZ_RXSHIFT 16
+ NvRegTransmitPoll = 0x10c,
+#define NVREG_TRANSMITPOLL_MAC_ADDR_REV 0x00008000
+ NvRegLinkSpeed = 0x110,
+#define NVREG_LINKSPEED_FORCE 0x10000
+#define NVREG_LINKSPEED_10 1000
+#define NVREG_LINKSPEED_100 100
+#define NVREG_LINKSPEED_1000 50
+#define NVREG_LINKSPEED_MASK (0xFFF)
+ NvRegUnknownSetupReg5 = 0x130,
+#define NVREG_UNKSETUP5_BIT31 (1<<31)
+ NvRegTxWatermark = 0x13c,
+#define NVREG_TX_WM_DESC1_DEFAULT 0x0200010
+#define NVREG_TX_WM_DESC2_3_DEFAULT 0x1e08000
+#define NVREG_TX_WM_DESC2_3_1000 0xfe08000
+ NvRegTxRxControl = 0x144,
+#define NVREG_TXRXCTL_KICK 0x0001
+#define NVREG_TXRXCTL_BIT1 0x0002
+#define NVREG_TXRXCTL_BIT2 0x0004
+#define NVREG_TXRXCTL_IDLE 0x0008
+#define NVREG_TXRXCTL_RESET 0x0010
+#define NVREG_TXRXCTL_RXCHECK 0x0400
+#define NVREG_TXRXCTL_DESC_1 0
+#define NVREG_TXRXCTL_DESC_2 0x002100
+#define NVREG_TXRXCTL_DESC_3 0xc02200
+#define NVREG_TXRXCTL_VLANSTRIP 0x00040
+#define NVREG_TXRXCTL_VLANINS 0x00080
+ NvRegTxRingPhysAddrHigh = 0x148,
+ NvRegRxRingPhysAddrHigh = 0x14C,
+ NvRegTxPauseFrame = 0x170,
+#define NVREG_TX_PAUSEFRAME_DISABLE 0x0fff0080
+#define NVREG_TX_PAUSEFRAME_ENABLE_V1 0x01800010
+#define NVREG_TX_PAUSEFRAME_ENABLE_V2 0x056003f0
+#define NVREG_TX_PAUSEFRAME_ENABLE_V3 0x09f00880
+ NvRegTxPauseFrameLimit = 0x174,
+#define NVREG_TX_PAUSEFRAMELIMIT_ENABLE 0x00010000
+ NvRegMIIStatus = 0x180,
+#define NVREG_MIISTAT_ERROR 0x0001
+#define NVREG_MIISTAT_LINKCHANGE 0x0008
+#define NVREG_MIISTAT_MASK_RW 0x0007
+#define NVREG_MIISTAT_MASK_ALL 0x000f
+ NvRegMIIMask = 0x184,
+#define NVREG_MII_LINKCHANGE 0x0008
+
+ NvRegAdapterControl = 0x188,
+#define NVREG_ADAPTCTL_START 0x02
+#define NVREG_ADAPTCTL_LINKUP 0x04
+#define NVREG_ADAPTCTL_PHYVALID 0x40000
+#define NVREG_ADAPTCTL_RUNNING 0x100000
+#define NVREG_ADAPTCTL_PHYSHIFT 24
+ NvRegMIISpeed = 0x18c,
+#define NVREG_MIISPEED_BIT8 (1<<8)
+#define NVREG_MIIDELAY 5
+ NvRegMIIControl = 0x190,
+#define NVREG_MIICTL_INUSE 0x08000
+#define NVREG_MIICTL_WRITE 0x00400
+#define NVREG_MIICTL_ADDRSHIFT 5
+ NvRegMIIData = 0x194,
+ NvRegTxUnicast = 0x1a0,
+ NvRegTxMulticast = 0x1a4,
+ NvRegTxBroadcast = 0x1a8,
+ NvRegWakeUpFlags = 0x200,
+#define NVREG_WAKEUPFLAGS_VAL 0x7770
+#define NVREG_WAKEUPFLAGS_BUSYSHIFT 24
+#define NVREG_WAKEUPFLAGS_ENABLESHIFT 16
+#define NVREG_WAKEUPFLAGS_D3SHIFT 12
+#define NVREG_WAKEUPFLAGS_D2SHIFT 8
+#define NVREG_WAKEUPFLAGS_D1SHIFT 4
+#define NVREG_WAKEUPFLAGS_D0SHIFT 0
+#define NVREG_WAKEUPFLAGS_ACCEPT_MAGPAT 0x01
+#define NVREG_WAKEUPFLAGS_ACCEPT_WAKEUPPAT 0x02
+#define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE 0x04
+#define NVREG_WAKEUPFLAGS_ENABLE 0x1111
+
+ NvRegMgmtUnitGetVersion = 0x204,
+#define NVREG_MGMTUNITGETVERSION 0x01
+ NvRegMgmtUnitVersion = 0x208,
+#define NVREG_MGMTUNITVERSION 0x08
+ NvRegPowerCap = 0x268,
+#define NVREG_POWERCAP_D3SUPP (1<<30)
+#define NVREG_POWERCAP_D2SUPP (1<<26)
+#define NVREG_POWERCAP_D1SUPP (1<<25)
+ NvRegPowerState = 0x26c,
+#define NVREG_POWERSTATE_POWEREDUP 0x8000
+#define NVREG_POWERSTATE_VALID 0x0100
+#define NVREG_POWERSTATE_MASK 0x0003
+#define NVREG_POWERSTATE_D0 0x0000
+#define NVREG_POWERSTATE_D1 0x0001
+#define NVREG_POWERSTATE_D2 0x0002
+#define NVREG_POWERSTATE_D3 0x0003
+ NvRegMgmtUnitControl = 0x278,
+#define NVREG_MGMTUNITCONTROL_INUSE 0x20000
+ NvRegTxCnt = 0x280,
+ NvRegTxZeroReXmt = 0x284,
+ NvRegTxOneReXmt = 0x288,
+ NvRegTxManyReXmt = 0x28c,
+ NvRegTxLateCol = 0x290,
+ NvRegTxUnderflow = 0x294,
+ NvRegTxLossCarrier = 0x298,
+ NvRegTxExcessDef = 0x29c,
+ NvRegTxRetryErr = 0x2a0,
+ NvRegRxFrameErr = 0x2a4,
+ NvRegRxExtraByte = 0x2a8,
+ NvRegRxLateCol = 0x2ac,
+ NvRegRxRunt = 0x2b0,
+ NvRegRxFrameTooLong = 0x2b4,
+ NvRegRxOverflow = 0x2b8,
+ NvRegRxFCSErr = 0x2bc,
+ NvRegRxFrameAlignErr = 0x2c0,
+ NvRegRxLenErr = 0x2c4,
+ NvRegRxUnicast = 0x2c8,
+ NvRegRxMulticast = 0x2cc,
+ NvRegRxBroadcast = 0x2d0,
+ NvRegTxDef = 0x2d4,
+ NvRegTxFrame = 0x2d8,
+ NvRegRxCnt = 0x2dc,
+ NvRegTxPause = 0x2e0,
+ NvRegRxPause = 0x2e4,
+ NvRegRxDropFrame = 0x2e8,
+ NvRegVlanControl = 0x300,
+#define NVREG_VLANCONTROL_ENABLE 0x2000
+ NvRegMSIXMap0 = 0x3e0,
+ NvRegMSIXMap1 = 0x3e4,
+ NvRegMSIXIrqStatus = 0x3f0,
+
+ NvRegPowerState2 = 0x600,
+#define NVREG_POWERSTATE2_POWERUP_MASK 0x0F15
+#define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001
+#define NVREG_POWERSTATE2_PHY_RESET 0x0004
+#define NVREG_POWERSTATE2_GATE_CLOCKS 0x0F00
+};
+
+enum {
+ NV_OPTIMIZATION_MODE_THROUGHPUT,
+ NV_OPTIMIZATION_MODE_CPU,
+ NV_OPTIMIZATION_MODE_DYNAMIC
+};
+
+enum {
+ NV_CROSSOVER_DETECTION_DISABLED,
+ NV_CROSSOVER_DETECTION_ENABLED
+};
+
+
+#define NV_SETUP_RX_RING 0x01
+#define NV_SETUP_TX_RING 0x02
+
+#define NV_RESTART_TX 0x1
+#define NV_RESTART_RX 0x2
+
+#endif /* _FORCEDETH_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/hfa384x.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/hfa384x.h
new file mode 100644
index 00000000..2e3ccf52
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/hfa384x.h
@@ -0,0 +1,3069 @@
+/* src/prism2/include/prism2/hfa384x.h
+*
+* Defines the constants and data structures for the hfa384x
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* [Implementation and usage notes]
+*
+* [References]
+* CW10 Programmer's Manual v1.5
+* IEEE 802.11 D10.0
+*
+* --------------------------------------------------------------------
+*/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#ifndef _HFA384x_H
+#define _HFA384x_H
+
+/*=============================================================*/
+#define HFA384x_FIRMWARE_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+
+#define HFA384x_LEVEL_TO_dBm(v) (0x100 + (v) * 100 / 255 - 100)
+
+/*------ Constants --------------------------------------------*/
+/*--- Mins & Maxs -----------------------------------*/
+#define HFA384x_CMD_ALLOC_LEN_MIN ((UINT16)4)
+#define HFA384x_CMD_ALLOC_LEN_MAX ((UINT16)2400)
+#define HFA384x_BAP_DATALEN_MAX ((UINT16)4096)
+#define HFA384x_BAP_OFFSET_MAX ((UINT16)4096)
+#define HFA384x_PORTID_MAX ((UINT16)7)
+#define HFA384x_NUMPORTS_MAX ((UINT16)(HFA384x_PORTID_MAX+1))
+#define HFA384x_PDR_LEN_MAX ((UINT16)512) /* in bytes, from EK */
+#define HFA384x_PDA_RECS_MAX ((UINT16)200) /* a guess */
+#define HFA384x_PDA_LEN_MAX ((UINT16)1024) /* in bytes, from EK */
+#define HFA384x_SCANRESULT_MAX ((UINT16)31)
+#define HFA384x_HSCANRESULT_MAX ((UINT16)31)
+#define HFA384x_CHINFORESULT_MAX ((UINT16)16)
+#define HFA384x_DRVR_FIDSTACKLEN_MAX (10)
+#define HFA384x_DRVR_TXBUF_MAX (sizeof(hfa384x_tx_frame_t) + \
+ WLAN_DATA_MAXLEN - \
+ WLAN_WEP_IV_LEN - \
+ WLAN_WEP_ICV_LEN + 2)
+#define HFA384x_DRVR_MAGIC (0x4a2d)
+#define HFA384x_INFODATA_MAXLEN (sizeof(hfa384x_infodata_t))
+#define HFA384x_INFOFRM_MAXLEN (sizeof(hfa384x_InfFrame_t))
+#define HFA384x_RID_GUESSING_MAXLEN 2048 /* I'm not really sure */
+#define HFA384x_RIDDATA_MAXLEN HFA384x_RID_GUESSING_MAXLEN
+#define HFA384x_USB_RWMEM_MAXLEN 2048
+
+/*--- Support Constants -----------------------------*/
+#define HFA384x_BAP_PROC ((UINT16)0)
+#define HFA384x_BAP_INT ((UINT16)1)
+#define HFA384x_PORTTYPE_IBSS ((UINT16)0)
+#define HFA384x_PORTTYPE_BSS ((UINT16)1)
+#define HFA384x_PORTTYPE_WDS ((UINT16)2)
+#define HFA384x_PORTTYPE_PSUEDOIBSS ((UINT16)3)
+#define HFA384x_PORTTYPE_HOSTAP ((UINT16)6)
+#define HFA384x_WEPFLAGS_PRIVINVOKED ((UINT16)BIT0)
+#define HFA384x_WEPFLAGS_EXCLUDE ((UINT16)BIT1)
+#define HFA384x_WEPFLAGS_DISABLE_TXCRYPT ((UINT16)BIT4)
+#define HFA384x_WEPFLAGS_DISABLE_RXCRYPT ((UINT16)BIT7)
+#define HFA384x_WEPFLAGS_DISALLOW_MIXED ((UINT16)BIT11)
+#define HFA384x_WEPFLAGS_IV_INTERVAL1 ((UINT16)0)
+#define HFA384x_WEPFLAGS_IV_INTERVAL10 ((UINT16)BIT5)
+#define HFA384x_WEPFLAGS_IV_INTERVAL50 ((UINT16)BIT6)
+#define HFA384x_WEPFLAGS_IV_INTERVAL100 ((UINT16)(BIT5 | BIT6))
+#define HFA384x_WEPFLAGS_FIRMWARE_WPA ((UINT16)BIT8)
+#define HFA384x_WEPFLAGS_HOST_MIC ((UINT16)BIT9)
+#define HFA384x_ROAMMODE_FWSCAN_FWROAM ((UINT16)1)
+#define HFA384x_ROAMMODE_FWSCAN_HOSTROAM ((UINT16)2)
+#define HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM ((UINT16)3)
+#define HFA384x_PORTSTATUS_DISABLED ((UINT16)1)
+#define HFA384x_PORTSTATUS_INITSRCH ((UINT16)2)
+#define HFA384x_PORTSTATUS_CONN_IBSS ((UINT16)3)
+#define HFA384x_PORTSTATUS_CONN_ESS ((UINT16)4)
+#define HFA384x_PORTSTATUS_OOR_ESS ((UINT16)5)
+#define HFA384x_PORTSTATUS_CONN_WDS ((UINT16)6)
+#define HFA384x_PORTSTATUS_HOSTAP ((UINT16)8)
+#define HFA384x_RATEBIT_1 ((UINT16)1)
+#define HFA384x_RATEBIT_2 ((UINT16)2)
+#define HFA384x_RATEBIT_5dot5 ((UINT16)4)
+#define HFA384x_RATEBIT_11 ((UINT16)8)
+
+/*--- Just some symbolic names for legibility -------*/
+#define HFA384x_TXCMD_NORECL ((UINT16)0)
+#define HFA384x_TXCMD_RECL ((UINT16)1)
+
+/*--- MAC Internal memory constants and macros ------*/
+/* masks and macros used to manipulate MAC internal memory addresses. */
+/* MAC internal memory addresses are 23 bit quantities. The MAC uses
+ * a paged address space where the upper 16 bits are the page number
+ * and the lower 7 bits are the offset. There are various Host API
+ * elements that require two 16-bit quantities to specify a MAC
+ * internal memory address. Unfortunately, some of the API's use a
+ * page/offset format where the offset value is JUST the lower seven
+ * bits and the page is the remaining 16 bits. Some of the API's
+ * assume that the 23 bit address has been split at the 16th bit. We
+ * refer to these two formats as AUX format and CMD format. The
+ * macros below help handle some of this.
+ */
+
+/* Handy constant */
+#define HFA384x_ADDR_AUX_OFF_MAX ((UINT16)0x007f)
+
+/* Mask bits for discarding unwanted pieces in a flat address */
+#define HFA384x_ADDR_FLAT_AUX_PAGE_MASK (0x007fff80)
+#define HFA384x_ADDR_FLAT_AUX_OFF_MASK (0x0000007f)
+#define HFA384x_ADDR_FLAT_CMD_PAGE_MASK (0xffff0000)
+#define HFA384x_ADDR_FLAT_CMD_OFF_MASK (0x0000ffff)
+
+/* Mask bits for discarding unwanted pieces in AUX format 16-bit address parts */
+#define HFA384x_ADDR_AUX_PAGE_MASK (0xffff)
+#define HFA384x_ADDR_AUX_OFF_MASK (0x007f)
+
+/* Mask bits for discarding unwanted pieces in CMD format 16-bit address parts */
+#define HFA384x_ADDR_CMD_PAGE_MASK (0x007f)
+#define HFA384x_ADDR_CMD_OFF_MASK (0xffff)
+
+/* Make a 32-bit flat address from AUX format 16-bit page and offset */
+#define HFA384x_ADDR_AUX_MKFLAT(p,o) \
+ (((UINT32)(((UINT16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) <<7) | \
+ ((UINT32)(((UINT16)(o))&HFA384x_ADDR_AUX_OFF_MASK))
+
+/* Make a 32-bit flat address from CMD format 16-bit page and offset */
+#define HFA384x_ADDR_CMD_MKFLAT(p,o) \
+ (((UINT32)(((UINT16)(p))&HFA384x_ADDR_CMD_PAGE_MASK)) <<16) | \
+ ((UINT32)(((UINT16)(o))&HFA384x_ADDR_CMD_OFF_MASK))
+
+/* Make AUX format offset and page from a 32-bit flat address */
+#define HFA384x_ADDR_AUX_MKPAGE(f) \
+ ((UINT16)((((UINT32)(f))&HFA384x_ADDR_FLAT_AUX_PAGE_MASK)>>7))
+#define HFA384x_ADDR_AUX_MKOFF(f) \
+ ((UINT16)(((UINT32)(f))&HFA384x_ADDR_FLAT_AUX_OFF_MASK))
+
+/* Make CMD format offset and page from a 32-bit flat address */
+#define HFA384x_ADDR_CMD_MKPAGE(f) \
+ ((UINT16)((((UINT32)(f))&HFA384x_ADDR_FLAT_CMD_PAGE_MASK)>>16))
+#define HFA384x_ADDR_CMD_MKOFF(f) \
+ ((UINT16)(((UINT32)(f))&HFA384x_ADDR_FLAT_CMD_OFF_MASK))
+
+/*--- Aux register masks/tests ----------------------*/
+/* Some of the upper bits of the AUX offset register are used to */
+/* select address space. */
+#define HFA384x_AUX_CTL_EXTDS (0x00)
+#define HFA384x_AUX_CTL_NV (0x01)
+#define HFA384x_AUX_CTL_PHY (0x02)
+#define HFA384x_AUX_CTL_ICSRAM (0x03)
+
+/* Make AUX register offset and page values from a flat address */
+#define HFA384x_AUX_MKOFF(f, c) \
+ (HFA384x_ADDR_AUX_MKOFF(f) | (((UINT16)(c))<<12))
+#define HFA384x_AUX_MKPAGE(f) HFA384x_ADDR_AUX_MKPAGE(f)
+
+
+/*--- Controller Memory addresses -------------------*/
+#define HFA3842_PDA_BASE (0x007f0000UL)
+#define HFA3841_PDA_BASE (0x003f0000UL)
+#define HFA3841_PDA_BOGUS_BASE (0x00390000UL)
+
+/*--- Driver Download states -----------------------*/
+#define HFA384x_DLSTATE_DISABLED 0
+#define HFA384x_DLSTATE_RAMENABLED 1
+#define HFA384x_DLSTATE_FLASHENABLED 2
+#define HFA384x_DLSTATE_FLASHWRITTEN 3
+#define HFA384x_DLSTATE_FLASHWRITEPENDING 4
+#define HFA384x_DLSTATE_GENESIS 5
+
+/*--- Register I/O offsets --------------------------*/
+#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX))
+
+#define HFA384x_CMD_OFF (0x00)
+#define HFA384x_PARAM0_OFF (0x02)
+#define HFA384x_PARAM1_OFF (0x04)
+#define HFA384x_PARAM2_OFF (0x06)
+#define HFA384x_STATUS_OFF (0x08)
+#define HFA384x_RESP0_OFF (0x0A)
+#define HFA384x_RESP1_OFF (0x0C)
+#define HFA384x_RESP2_OFF (0x0E)
+#define HFA384x_INFOFID_OFF (0x10)
+#define HFA384x_RXFID_OFF (0x20)
+#define HFA384x_ALLOCFID_OFF (0x22)
+#define HFA384x_TXCOMPLFID_OFF (0x24)
+#define HFA384x_SELECT0_OFF (0x18)
+#define HFA384x_OFFSET0_OFF (0x1C)
+#define HFA384x_DATA0_OFF (0x36)
+#define HFA384x_SELECT1_OFF (0x1A)
+#define HFA384x_OFFSET1_OFF (0x1E)
+#define HFA384x_DATA1_OFF (0x38)
+#define HFA384x_EVSTAT_OFF (0x30)
+#define HFA384x_INTEN_OFF (0x32)
+#define HFA384x_EVACK_OFF (0x34)
+#define HFA384x_CONTROL_OFF (0x14)
+#define HFA384x_SWSUPPORT0_OFF (0x28)
+#define HFA384x_SWSUPPORT1_OFF (0x2A)
+#define HFA384x_SWSUPPORT2_OFF (0x2C)
+#define HFA384x_AUXPAGE_OFF (0x3A)
+#define HFA384x_AUXOFFSET_OFF (0x3C)
+#define HFA384x_AUXDATA_OFF (0x3E)
+
+#elif (WLAN_HOSTIF == WLAN_PCI || WLAN_HOSTIF == WLAN_USB)
+
+#define HFA384x_CMD_OFF (0x00)
+#define HFA384x_PARAM0_OFF (0x04)
+#define HFA384x_PARAM1_OFF (0x08)
+#define HFA384x_PARAM2_OFF (0x0c)
+#define HFA384x_STATUS_OFF (0x10)
+#define HFA384x_RESP0_OFF (0x14)
+#define HFA384x_RESP1_OFF (0x18)
+#define HFA384x_RESP2_OFF (0x1c)
+#define HFA384x_INFOFID_OFF (0x20)
+#define HFA384x_RXFID_OFF (0x40)
+#define HFA384x_ALLOCFID_OFF (0x44)
+#define HFA384x_TXCOMPLFID_OFF (0x48)
+#define HFA384x_SELECT0_OFF (0x30)
+#define HFA384x_OFFSET0_OFF (0x38)
+#define HFA384x_DATA0_OFF (0x6c)
+#define HFA384x_SELECT1_OFF (0x34)
+#define HFA384x_OFFSET1_OFF (0x3c)
+#define HFA384x_DATA1_OFF (0x70)
+#define HFA384x_EVSTAT_OFF (0x60)
+#define HFA384x_INTEN_OFF (0x64)
+#define HFA384x_EVACK_OFF (0x68)
+#define HFA384x_CONTROL_OFF (0x28)
+#define HFA384x_SWSUPPORT0_OFF (0x50)
+#define HFA384x_SWSUPPORT1_OFF (0x54)
+#define HFA384x_SWSUPPORT2_OFF (0x58)
+#define HFA384x_AUXPAGE_OFF (0x74)
+#define HFA384x_AUXOFFSET_OFF (0x78)
+#define HFA384x_AUXDATA_OFF (0x7c)
+#define HFA384x_PCICOR_OFF (0x4c)
+#define HFA384x_PCIHCR_OFF (0x5c)
+#define HFA384x_PCI_M0_ADDRH_OFF (0x80)
+#define HFA384x_PCI_M0_ADDRL_OFF (0x84)
+#define HFA384x_PCI_M0_LEN_OFF (0x88)
+#define HFA384x_PCI_M0_CTL_OFF (0x8c)
+#define HFA384x_PCI_STATUS_OFF (0x98)
+#define HFA384x_PCI_M1_ADDRH_OFF (0xa0)
+#define HFA384x_PCI_M1_ADDRL_OFF (0xa4)
+#define HFA384x_PCI_M1_LEN_OFF (0xa8)
+#define HFA384x_PCI_M1_CTL_OFF (0xac)
+
+#endif
+
+/*--- Register Field Masks --------------------------*/
+#define HFA384x_CMD_BUSY ((UINT16)BIT15)
+#define HFA384x_CMD_AINFO ((UINT16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8))
+#define HFA384x_CMD_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8))
+#define HFA384x_CMD_RECL ((UINT16)BIT8)
+#define HFA384x_CMD_WRITE ((UINT16)BIT8)
+#define HFA384x_CMD_PROGMODE ((UINT16)(BIT9 | BIT8))
+#define HFA384x_CMD_CMDCODE ((UINT16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0))
+
+#define HFA384x_STATUS_RESULT ((UINT16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8))
+#define HFA384x_STATUS_CMDCODE ((UINT16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0))
+
+#define HFA384x_OFFSET_BUSY ((UINT16)BIT15)
+#define HFA384x_OFFSET_ERR ((UINT16)BIT14)
+#define HFA384x_OFFSET_DATAOFF ((UINT16)(BIT11 | BIT10 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1))
+
+#define HFA384x_EVSTAT_TICK ((UINT16)BIT15)
+#define HFA384x_EVSTAT_WTERR ((UINT16)BIT14)
+#define HFA384x_EVSTAT_INFDROP ((UINT16)BIT13)
+#define HFA384x_EVSTAT_INFO ((UINT16)BIT7)
+#define HFA384x_EVSTAT_DTIM ((UINT16)BIT5)
+#define HFA384x_EVSTAT_CMD ((UINT16)BIT4)
+#define HFA384x_EVSTAT_ALLOC ((UINT16)BIT3)
+#define HFA384x_EVSTAT_TXEXC ((UINT16)BIT2)
+#define HFA384x_EVSTAT_TX ((UINT16)BIT1)
+#define HFA384x_EVSTAT_RX ((UINT16)BIT0)
+
+#define HFA384x_INT_BAP_OP (HFA384x_EVSTAT_INFO|HFA384x_EVSTAT_RX|HFA384x_EVSTAT_TX|HFA384x_EVSTAT_TXEXC)
+
+#define HFA384x_INT_NORMAL (HFA384x_EVSTAT_INFO|HFA384x_EVSTAT_RX|HFA384x_EVSTAT_TX|HFA384x_EVSTAT_TXEXC|HFA384x_EVSTAT_INFDROP|HFA384x_EVSTAT_ALLOC|HFA384x_EVSTAT_DTIM)
+
+#define HFA384x_INTEN_TICK ((UINT16)BIT15)
+#define HFA384x_INTEN_WTERR ((UINT16)BIT14)
+#define HFA384x_INTEN_INFDROP ((UINT16)BIT13)
+#define HFA384x_INTEN_INFO ((UINT16)BIT7)
+#define HFA384x_INTEN_DTIM ((UINT16)BIT5)
+#define HFA384x_INTEN_CMD ((UINT16)BIT4)
+#define HFA384x_INTEN_ALLOC ((UINT16)BIT3)
+#define HFA384x_INTEN_TXEXC ((UINT16)BIT2)
+#define HFA384x_INTEN_TX ((UINT16)BIT1)
+#define HFA384x_INTEN_RX ((UINT16)BIT0)
+
+#define HFA384x_EVACK_TICK ((UINT16)BIT15)
+#define HFA384x_EVACK_WTERR ((UINT16)BIT14)
+#define HFA384x_EVACK_INFDROP ((UINT16)BIT13)
+#define HFA384x_EVACK_INFO ((UINT16)BIT7)
+#define HFA384x_EVACK_DTIM ((UINT16)BIT5)
+#define HFA384x_EVACK_CMD ((UINT16)BIT4)
+#define HFA384x_EVACK_ALLOC ((UINT16)BIT3)
+#define HFA384x_EVACK_TXEXC ((UINT16)BIT2)
+#define HFA384x_EVACK_TX ((UINT16)BIT1)
+#define HFA384x_EVACK_RX ((UINT16)BIT0)
+
+#define HFA384x_CONTROL_AUXEN ((UINT16)(BIT15 | BIT14))
+
+
+/*--- Command Code Constants --------------------------*/
+/*--- Controller Commands --------------------------*/
+#define HFA384x_CMDCODE_INIT ((UINT16)0x00)
+#define HFA384x_CMDCODE_ENABLE ((UINT16)0x01)
+#define HFA384x_CMDCODE_DISABLE ((UINT16)0x02)
+#define HFA384x_CMDCODE_DIAG ((UINT16)0x03)
+
+/*--- Buffer Mgmt Commands --------------------------*/
+#define HFA384x_CMDCODE_ALLOC ((UINT16)0x0A)
+#define HFA384x_CMDCODE_TX ((UINT16)0x0B)
+#define HFA384x_CMDCODE_CLRPRST ((UINT16)0x12)
+
+/*--- Regulate Commands --------------------------*/
+#define HFA384x_CMDCODE_NOTIFY ((UINT16)0x10)
+#define HFA384x_CMDCODE_INQ ((UINT16)0x11)
+
+/*--- Configure Commands --------------------------*/
+#define HFA384x_CMDCODE_ACCESS ((UINT16)0x21)
+#define HFA384x_CMDCODE_DOWNLD ((UINT16)0x22)
+
+/*--- Debugging Commands -----------------------------*/
+#define HFA384x_CMDCODE_MONITOR ((UINT16)(0x38))
+#define HFA384x_MONITOR_ENABLE ((UINT16)(0x0b))
+#define HFA384x_MONITOR_DISABLE ((UINT16)(0x0f))
+
+/*--- Result Codes --------------------------*/
+#define HFA384x_SUCCESS ((UINT16)(0x00))
+#define HFA384x_CARD_FAIL ((UINT16)(0x01))
+#define HFA384x_NO_BUFF ((UINT16)(0x05))
+#define HFA384x_CMD_ERR ((UINT16)(0x7F))
+
+/*--- Programming Modes --------------------------
+ MODE 0: Disable programming
+ MODE 1: Enable volatile memory programming
+ MODE 2: Enable non-volatile memory programming
+ MODE 3: Program non-volatile memory section
+--------------------------------------------------*/
+#define HFA384x_PROGMODE_DISABLE ((UINT16)0x00)
+#define HFA384x_PROGMODE_RAM ((UINT16)0x01)
+#define HFA384x_PROGMODE_NV ((UINT16)0x02)
+#define HFA384x_PROGMODE_NVWRITE ((UINT16)0x03)
+
+/*--- AUX register enable --------------------------*/
+#define HFA384x_AUXPW0 ((UINT16)0xfe01)
+#define HFA384x_AUXPW1 ((UINT16)0xdc23)
+#define HFA384x_AUXPW2 ((UINT16)0xba45)
+
+#define HFA384x_CONTROL_AUX_ISDISABLED ((UINT16)0x0000)
+#define HFA384x_CONTROL_AUX_ISENABLED ((UINT16)0xc000)
+#define HFA384x_CONTROL_AUX_DOENABLE ((UINT16)0x8000)
+#define HFA384x_CONTROL_AUX_DODISABLE ((UINT16)0x4000)
+
+/*--- Record ID Constants --------------------------*/
+/*--------------------------------------------------------------------
+Configuration RIDs: Network Parameters, Static Configuration Entities
+--------------------------------------------------------------------*/
+#define HFA384x_RID_CNFPORTTYPE ((UINT16)0xFC00)
+#define HFA384x_RID_CNFOWNMACADDR ((UINT16)0xFC01)
+#define HFA384x_RID_CNFDESIREDSSID ((UINT16)0xFC02)
+#define HFA384x_RID_CNFOWNCHANNEL ((UINT16)0xFC03)
+#define HFA384x_RID_CNFOWNSSID ((UINT16)0xFC04)
+#define HFA384x_RID_CNFOWNATIMWIN ((UINT16)0xFC05)
+#define HFA384x_RID_CNFSYSSCALE ((UINT16)0xFC06)
+#define HFA384x_RID_CNFMAXDATALEN ((UINT16)0xFC07)
+#define HFA384x_RID_CNFWDSADDR ((UINT16)0xFC08)
+#define HFA384x_RID_CNFPMENABLED ((UINT16)0xFC09)
+#define HFA384x_RID_CNFPMEPS ((UINT16)0xFC0A)
+#define HFA384x_RID_CNFMULTICASTRX ((UINT16)0xFC0B)
+#define HFA384x_RID_CNFMAXSLEEPDUR ((UINT16)0xFC0C)
+#define HFA384x_RID_CNFPMHOLDDUR ((UINT16)0xFC0D)
+#define HFA384x_RID_CNFOWNNAME ((UINT16)0xFC0E)
+#define HFA384x_RID_CNFOWNDTIMPER ((UINT16)0xFC10)
+#define HFA384x_RID_CNFWDSADDR1 ((UINT16)0xFC11)
+#define HFA384x_RID_CNFWDSADDR2 ((UINT16)0xFC12)
+#define HFA384x_RID_CNFWDSADDR3 ((UINT16)0xFC13)
+#define HFA384x_RID_CNFWDSADDR4 ((UINT16)0xFC14)
+#define HFA384x_RID_CNFWDSADDR5 ((UINT16)0xFC15)
+#define HFA384x_RID_CNFWDSADDR6 ((UINT16)0xFC16)
+#define HFA384x_RID_CNFMCASTPMBUFF ((UINT16)0xFC17)
+
+/*--------------------------------------------------------------------
+Configuration RID lengths: Network Params, Static Config Entities
+ This is the length of JUST the DATA part of the RID (does not
+ include the len or code fields)
+--------------------------------------------------------------------*/
+/* TODO: fill in the rest of these */
+#define HFA384x_RID_CNFPORTTYPE_LEN ((UINT16)2)
+#define HFA384x_RID_CNFOWNMACADDR_LEN ((UINT16)6)
+#define HFA384x_RID_CNFDESIREDSSID_LEN ((UINT16)34)
+#define HFA384x_RID_CNFOWNCHANNEL_LEN ((UINT16)2)
+#define HFA384x_RID_CNFOWNSSID_LEN ((UINT16)34)
+#define HFA384x_RID_CNFOWNATIMWIN_LEN ((UINT16)2)
+#define HFA384x_RID_CNFSYSSCALE_LEN ((UINT16)0)
+#define HFA384x_RID_CNFMAXDATALEN_LEN ((UINT16)0)
+#define HFA384x_RID_CNFWDSADDR_LEN ((UINT16)6)
+#define HFA384x_RID_CNFPMENABLED_LEN ((UINT16)0)
+#define HFA384x_RID_CNFPMEPS_LEN ((UINT16)0)
+#define HFA384x_RID_CNFMULTICASTRX_LEN ((UINT16)0)
+#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((UINT16)0)
+#define HFA384x_RID_CNFPMHOLDDUR_LEN ((UINT16)0)
+#define HFA384x_RID_CNFOWNNAME_LEN ((UINT16)34)
+#define HFA384x_RID_CNFOWNDTIMPER_LEN ((UINT16)0)
+#define HFA384x_RID_CNFWDSADDR1_LEN ((UINT16)6)
+#define HFA384x_RID_CNFWDSADDR2_LEN ((UINT16)6)
+#define HFA384x_RID_CNFWDSADDR3_LEN ((UINT16)6)
+#define HFA384x_RID_CNFWDSADDR4_LEN ((UINT16)6)
+#define HFA384x_RID_CNFWDSADDR5_LEN ((UINT16)6)
+#define HFA384x_RID_CNFWDSADDR6_LEN ((UINT16)6)
+#define HFA384x_RID_CNFMCASTPMBUFF_LEN ((UINT16)0)
+#define HFA384x_RID_CNFAUTHENTICATION_LEN ((UINT16)sizeof(UINT16))
+#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((UINT16)0)
+
+/*--------------------------------------------------------------------
+Configuration RIDs: Network Parameters, Dynamic Configuration Entities
+--------------------------------------------------------------------*/
+#define HFA384x_RID_GROUPADDR ((UINT16)0xFC80)
+#define HFA384x_RID_CREATEIBSS ((UINT16)0xFC81)
+#define HFA384x_RID_FRAGTHRESH ((UINT16)0xFC82)
+#define HFA384x_RID_RTSTHRESH ((UINT16)0xFC83)
+#define HFA384x_RID_TXRATECNTL ((UINT16)0xFC84)
+#define HFA384x_RID_PROMISCMODE ((UINT16)0xFC85)
+#define HFA384x_RID_FRAGTHRESH0 ((UINT16)0xFC90)
+#define HFA384x_RID_FRAGTHRESH1 ((UINT16)0xFC91)
+#define HFA384x_RID_FRAGTHRESH2 ((UINT16)0xFC92)
+#define HFA384x_RID_FRAGTHRESH3 ((UINT16)0xFC93)
+#define HFA384x_RID_FRAGTHRESH4 ((UINT16)0xFC94)
+#define HFA384x_RID_FRAGTHRESH5 ((UINT16)0xFC95)
+#define HFA384x_RID_FRAGTHRESH6 ((UINT16)0xFC96)
+#define HFA384x_RID_RTSTHRESH0 ((UINT16)0xFC97)
+#define HFA384x_RID_RTSTHRESH1 ((UINT16)0xFC98)
+#define HFA384x_RID_RTSTHRESH2 ((UINT16)0xFC99)
+#define HFA384x_RID_RTSTHRESH3 ((UINT16)0xFC9A)
+#define HFA384x_RID_RTSTHRESH4 ((UINT16)0xFC9B)
+#define HFA384x_RID_RTSTHRESH5 ((UINT16)0xFC9C)
+#define HFA384x_RID_RTSTHRESH6 ((UINT16)0xFC9D)
+#define HFA384x_RID_TXRATECNTL0 ((UINT16)0xFC9E)
+#define HFA384x_RID_TXRATECNTL1 ((UINT16)0xFC9F)
+#define HFA384x_RID_TXRATECNTL2 ((UINT16)0xFCA0)
+#define HFA384x_RID_TXRATECNTL3 ((UINT16)0xFCA1)
+#define HFA384x_RID_TXRATECNTL4 ((UINT16)0xFCA2)
+#define HFA384x_RID_TXRATECNTL5 ((UINT16)0xFCA3)
+#define HFA384x_RID_TXRATECNTL6 ((UINT16)0xFCA4)
+
+/*--------------------------------------------------------------------
+Configuration RID Lengths: Network Param, Dynamic Config Entities
+ This is the length of JUST the DATA part of the RID (does not
+ include the len or code fields)
+--------------------------------------------------------------------*/
+/* TODO: fill in the rest of these */
+#define HFA384x_RID_GROUPADDR_LEN ((UINT16)16 * WLAN_ADDR_LEN)
+#define HFA384x_RID_CREATEIBSS_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL_LEN ((UINT16)4)
+#define HFA384x_RID_PROMISCMODE_LEN ((UINT16)2)
+#define HFA384x_RID_FRAGTHRESH0_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH1_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH2_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH3_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH4_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH5_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH6_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH0_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH1_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH2_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH3_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH4_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH5_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH6_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL0_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL1_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL2_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL3_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL4_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL5_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL6_LEN ((UINT16)0)
+
+/*--------------------------------------------------------------------
+Configuration RIDs: Behavior Parameters
+--------------------------------------------------------------------*/
+#define HFA384x_RID_ITICKTIME ((UINT16)0xFCE0)
+
+/*--------------------------------------------------------------------
+Configuration RID Lengths: Behavior Parameters
+ This is the length of JUST the DATA part of the RID (does not
+ include the len or code fields)
+--------------------------------------------------------------------*/
+#define HFA384x_RID_ITICKTIME_LEN ((UINT16)2)
+
+/*----------------------------------------------------------------------
+Information RIDs: NIC Information
+--------------------------------------------------------------------*/
+#define HFA384x_RID_MAXLOADTIME ((UINT16)0xFD00)
+#define HFA384x_RID_DOWNLOADBUFFER ((UINT16)0xFD01)
+#define HFA384x_RID_PRIIDENTITY ((UINT16)0xFD02)
+#define HFA384x_RID_PRISUPRANGE ((UINT16)0xFD03)
+#define HFA384x_RID_PRI_CFIACTRANGES ((UINT16)0xFD04)
+#define HFA384x_RID_NICSERIALNUMBER ((UINT16)0xFD0A)
+#define HFA384x_RID_NICIDENTITY ((UINT16)0xFD0B)
+#define HFA384x_RID_MFISUPRANGE ((UINT16)0xFD0C)
+#define HFA384x_RID_CFISUPRANGE ((UINT16)0xFD0D)
+#define HFA384x_RID_CHANNELLIST ((UINT16)0xFD10)
+#define HFA384x_RID_REGULATORYDOMAINS ((UINT16)0xFD11)
+#define HFA384x_RID_TEMPTYPE ((UINT16)0xFD12)
+#define HFA384x_RID_CIS ((UINT16)0xFD13)
+#define HFA384x_RID_STAIDENTITY ((UINT16)0xFD20)
+#define HFA384x_RID_STASUPRANGE ((UINT16)0xFD21)
+#define HFA384x_RID_STA_MFIACTRANGES ((UINT16)0xFD22)
+#define HFA384x_RID_STA_CFIACTRANGES ((UINT16)0xFD23)
+#define HFA384x_RID_BUILDSEQ ((UINT16)0xFFFE)
+#define HFA384x_RID_FWID ((UINT16)0xFFFF)
+
+/*----------------------------------------------------------------------
+Information RID Lengths: NIC Information
+ This is the length of JUST the DATA part of the RID (does not
+ include the len or code fields)
+--------------------------------------------------------------------*/
+#define HFA384x_RID_MAXLOADTIME_LEN ((UINT16)0)
+#define HFA384x_RID_DOWNLOADBUFFER_LEN ((UINT16)sizeof(hfa384x_downloadbuffer_t))
+#define HFA384x_RID_PRIIDENTITY_LEN ((UINT16)8)
+#define HFA384x_RID_PRISUPRANGE_LEN ((UINT16)10)
+#define HFA384x_RID_CFIACTRANGES_LEN ((UINT16)10)
+#define HFA384x_RID_NICSERIALNUMBER_LEN ((UINT16)12)
+#define HFA384x_RID_NICIDENTITY_LEN ((UINT16)8)
+#define HFA384x_RID_MFISUPRANGE_LEN ((UINT16)10)
+#define HFA384x_RID_CFISUPRANGE_LEN ((UINT16)10)
+#define HFA384x_RID_CHANNELLIST_LEN ((UINT16)0)
+#define HFA384x_RID_REGULATORYDOMAINS_LEN ((UINT16)12)
+#define HFA384x_RID_TEMPTYPE_LEN ((UINT16)0)
+#define HFA384x_RID_CIS_LEN ((UINT16)480)
+#define HFA384x_RID_STAIDENTITY_LEN ((UINT16)8)
+#define HFA384x_RID_STASUPRANGE_LEN ((UINT16)10)
+#define HFA384x_RID_MFIACTRANGES_LEN ((UINT16)10)
+#define HFA384x_RID_CFIACTRANGES2_LEN ((UINT16)10)
+#define HFA384x_RID_BUILDSEQ_LEN ((UINT16)sizeof(hfa384x_BuildSeq_t))
+#define HFA384x_RID_FWID_LEN ((UINT16)sizeof(hfa384x_FWID_t))
+
+/*--------------------------------------------------------------------
+Information RIDs: MAC Information
+--------------------------------------------------------------------*/
+#define HFA384x_RID_PORTSTATUS ((UINT16)0xFD40)
+#define HFA384x_RID_CURRENTSSID ((UINT16)0xFD41)
+#define HFA384x_RID_CURRENTBSSID ((UINT16)0xFD42)
+#define HFA384x_RID_COMMSQUALITY ((UINT16)0xFD43)
+#define HFA384x_RID_CURRENTTXRATE ((UINT16)0xFD44)
+#define HFA384x_RID_CURRENTBCNINT ((UINT16)0xFD45)
+#define HFA384x_RID_CURRENTSCALETHRESH ((UINT16)0xFD46)
+#define HFA384x_RID_PROTOCOLRSPTIME ((UINT16)0xFD47)
+#define HFA384x_RID_SHORTRETRYLIMIT ((UINT16)0xFD48)
+#define HFA384x_RID_LONGRETRYLIMIT ((UINT16)0xFD49)
+#define HFA384x_RID_MAXTXLIFETIME ((UINT16)0xFD4A)
+#define HFA384x_RID_MAXRXLIFETIME ((UINT16)0xFD4B)
+#define HFA384x_RID_CFPOLLABLE ((UINT16)0xFD4C)
+#define HFA384x_RID_AUTHALGORITHMS ((UINT16)0xFD4D)
+#define HFA384x_RID_PRIVACYOPTIMP ((UINT16)0xFD4F)
+#define HFA384x_RID_DBMCOMMSQUALITY ((UINT16)0xFD51)
+#define HFA384x_RID_CURRENTTXRATE1 ((UINT16)0xFD80)
+#define HFA384x_RID_CURRENTTXRATE2 ((UINT16)0xFD81)
+#define HFA384x_RID_CURRENTTXRATE3 ((UINT16)0xFD82)
+#define HFA384x_RID_CURRENTTXRATE4 ((UINT16)0xFD83)
+#define HFA384x_RID_CURRENTTXRATE5 ((UINT16)0xFD84)
+#define HFA384x_RID_CURRENTTXRATE6 ((UINT16)0xFD85)
+#define HFA384x_RID_OWNMACADDRESS ((UINT16)0xFD86)
+// #define HFA384x_RID_PCFINFO ((UINT16)0xFD87)
+#define HFA384x_RID_SCANRESULTS ((UINT16)0xFD88) // NEW
+#define HFA384x_RID_HOSTSCANRESULTS ((UINT16)0xFD89) // NEW
+#define HFA384x_RID_AUTHENTICATIONUSED ((UINT16)0xFD8A) // NEW
+#define HFA384x_RID_ASSOCIATEFAILURE ((UINT16)0xFD8D) // 1.8.0
+
+/*--------------------------------------------------------------------
+Information RID Lengths: MAC Information
+ This is the length of JUST the DATA part of the RID (does not
+ include the len or code fields)
+--------------------------------------------------------------------*/
+#define HFA384x_RID_PORTSTATUS_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTSSID_LEN ((UINT16)34)
+#define HFA384x_RID_CURRENTBSSID_LEN ((UINT16)WLAN_BSSID_LEN)
+#define HFA384x_RID_COMMSQUALITY_LEN ((UINT16)sizeof(hfa384x_commsquality_t))
+#define HFA384x_RID_DBMCOMMSQUALITY_LEN ((UINT16)sizeof(hfa384x_dbmcommsquality_t))
+#define HFA384x_RID_CURRENTTXRATE_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTBCNINT_LEN ((UINT16)0)
+#define HFA384x_RID_STACURSCALETHRESH_LEN ((UINT16)12)
+#define HFA384x_RID_APCURSCALETHRESH_LEN ((UINT16)6)
+#define HFA384x_RID_PROTOCOLRSPTIME_LEN ((UINT16)0)
+#define HFA384x_RID_SHORTRETRYLIMIT_LEN ((UINT16)0)
+#define HFA384x_RID_LONGRETRYLIMIT_LEN ((UINT16)0)
+#define HFA384x_RID_MAXTXLIFETIME_LEN ((UINT16)0)
+#define HFA384x_RID_MAXRXLIFETIME_LEN ((UINT16)0)
+#define HFA384x_RID_CFPOLLABLE_LEN ((UINT16)0)
+#define HFA384x_RID_AUTHALGORITHMS_LEN ((UINT16)4)
+#define HFA384x_RID_PRIVACYOPTIMP_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTTXRATE1_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTTXRATE2_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTTXRATE3_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTTXRATE4_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTTXRATE5_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTTXRATE6_LEN ((UINT16)0)
+#define HFA384x_RID_OWNMACADDRESS_LEN ((UINT16)6)
+#define HFA384x_RID_PCFINFO_LEN ((UINT16)6)
+#define HFA384x_RID_CNFAPPCFINFO_LEN ((UINT16)sizeof(hfa384x_PCFInfo_data_t))
+#define HFA384x_RID_SCANREQUEST_LEN ((UINT16)sizeof(hfa384x_ScanRequest_data_t))
+#define HFA384x_RID_JOINREQUEST_LEN ((UINT16)sizeof(hfa384x_JoinRequest_data_t))
+#define HFA384x_RID_AUTHENTICATESTA_LEN ((UINT16)sizeof(hfa384x_authenticateStation_data_t))
+#define HFA384x_RID_CHANNELINFOREQUEST_LEN ((UINT16)sizeof(hfa384x_ChannelInfoRequest_data_t))
+/*--------------------------------------------------------------------
+Information RIDs: Modem Information
+--------------------------------------------------------------------*/
+#define HFA384x_RID_PHYTYPE ((UINT16)0xFDC0)
+#define HFA384x_RID_CURRENTCHANNEL ((UINT16)0xFDC1)
+#define HFA384x_RID_CURRENTPOWERSTATE ((UINT16)0xFDC2)
+#define HFA384x_RID_CCAMODE ((UINT16)0xFDC3)
+#define HFA384x_RID_SUPPORTEDDATARATES ((UINT16)0xFDC6)
+#define HFA384x_RID_LFOSTATUS ((UINT16)0xFDC7) // 1.7.1
+
+/*--------------------------------------------------------------------
+Information RID Lengths: Modem Information
+ This is the length of JUST the DATA part of the RID (does not
+ include the len or code fields)
+--------------------------------------------------------------------*/
+#define HFA384x_RID_PHYTYPE_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTCHANNEL_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTPOWERSTATE_LEN ((UINT16)0)
+#define HFA384x_RID_CCAMODE_LEN ((UINT16)0)
+#define HFA384x_RID_SUPPORTEDDATARATES_LEN ((UINT16)10)
+
+/*--------------------------------------------------------------------
+API ENHANCEMENTS (NOT ALREADY IMPLEMENTED)
+--------------------------------------------------------------------*/
+#define HFA384x_RID_CNFWEPDEFAULTKEYID ((UINT16)0xFC23)
+#define HFA384x_RID_CNFWEPDEFAULTKEY0 ((UINT16)0xFC24)
+#define HFA384x_RID_CNFWEPDEFAULTKEY1 ((UINT16)0xFC25)
+#define HFA384x_RID_CNFWEPDEFAULTKEY2 ((UINT16)0xFC26)
+#define HFA384x_RID_CNFWEPDEFAULTKEY3 ((UINT16)0xFC27)
+#define HFA384x_RID_CNFWEPFLAGS ((UINT16)0xFC28)
+#define HFA384x_RID_CNFWEPKEYMAPTABLE ((UINT16)0xFC29)
+#define HFA384x_RID_CNFAUTHENTICATION ((UINT16)0xFC2A)
+#define HFA384x_RID_CNFMAXASSOCSTATIONS ((UINT16)0xFC2B)
+#define HFA384x_RID_CNFTXCONTROL ((UINT16)0xFC2C)
+#define HFA384x_RID_CNFROAMINGMODE ((UINT16)0xFC2D)
+#define HFA384x_RID_CNFHOSTAUTHASSOC ((UINT16)0xFC2E)
+#define HFA384x_RID_CNFRCVCRCERROR ((UINT16)0xFC30)
+// #define HFA384x_RID_CNFMMLIFE ((UINT16)0xFC31)
+#define HFA384x_RID_CNFALTRETRYCNT ((UINT16)0xFC32)
+#define HFA384x_RID_CNFAPBCNINT ((UINT16)0xFC33)
+#define HFA384x_RID_CNFAPPCFINFO ((UINT16)0xFC34)
+#define HFA384x_RID_CNFSTAPCFINFO ((UINT16)0xFC35)
+#define HFA384x_RID_CNFPRIORITYQUSAGE ((UINT16)0xFC37)
+#define HFA384x_RID_CNFTIMCTRL ((UINT16)0xFC40)
+#define HFA384x_RID_CNFTHIRTY2TALLY ((UINT16)0xFC42)
+#define HFA384x_RID_CNFENHSECURITY ((UINT16)0xFC43)
+#define HFA384x_RID_CNFDBMADJUST ((UINT16)0xFC46) // NEW
+#define HFA384x_RID_CNFWPADATA ((UINT16)0xFC48) // 1.7.0
+#define HFA384x_RID_CNFPROPOGATIONDELAY ((UINT16)0xFC49) // 1.7.6
+#define HFA384x_RID_CNFSHORTPREAMBLE ((UINT16)0xFCB0)
+#define HFA384x_RID_CNFEXCLONGPREAMBLE ((UINT16)0xFCB1)
+#define HFA384x_RID_CNFAUTHRSPTIMEOUT ((UINT16)0xFCB2)
+#define HFA384x_RID_CNFBASICRATES ((UINT16)0xFCB3)
+#define HFA384x_RID_CNFSUPPRATES ((UINT16)0xFCB4)
+#define HFA384x_RID_CNFFALLBACKCTRL ((UINT16)0xFCB5) // NEW
+#define HFA384x_RID_WEPKEYSTATUS ((UINT16)0xFCB6) // NEW
+#define HFA384x_RID_WEPKEYMAPINDEX ((UINT16)0xFCB7) // NEW
+#define HFA384x_RID_BROADCASTKEYID ((UINT16)0xFCB8) // NEW
+#define HFA384x_RID_ENTSECFLAGEYID ((UINT16)0xFCB9) // NEW
+#define HFA384x_RID_CNFPASSIVESCANCTRL ((UINT16)0xFCBA) // NEW STA
+#define HFA384x_RID_CNFWPAHANDLING ((UINT16)0xFCBB) // 1.7.0
+#define HFA384x_RID_MDCCONTROL ((UINT16)0xFCBC) // 1.7.0/1.4.0
+#define HFA384x_RID_MDCCOUNTRY ((UINT16)0xFCBD) // 1.7.0/1.4.0
+#define HFA384x_RID_TXPOWERMAX ((UINT16)0xFCBE) // 1.7.0/1.4.0
+#define HFA384x_RID_CNFLFOENBLED ((UINT16)0xFCBF) // 1.6.3
+#define HFA384x_RID_CAPINFO ((UINT16)0xFCC0) // 1.7.0/1.3.7
+#define HFA384x_RID_LISTENINTERVAL ((UINT16)0xFCC1) // 1.7.0/1.3.7
+#define HFA384x_RID_DIVERSITYENABLED ((UINT16)0xFCC2) // 1.7.0/1.3.7
+#define HFA384x_RID_LED_CONTROL ((UINT16)0xFCC4) // 1.7.6
+#define HFA384x_RID_HFO_DELAY ((UINT16)0xFCC5) // 1.7.6
+#define HFA384x_RID_DISSALOWEDBSSID ((UINT16)0xFCC6) // 1.8.0
+#define HFA384x_RID_SCANREQUEST ((UINT16)0xFCE1)
+#define HFA384x_RID_JOINREQUEST ((UINT16)0xFCE2)
+#define HFA384x_RID_AUTHENTICATESTA ((UINT16)0xFCE3)
+#define HFA384x_RID_CHANNELINFOREQUEST ((UINT16)0xFCE4)
+#define HFA384x_RID_HOSTSCAN ((UINT16)0xFCE5) // NEW STA
+#define HFA384x_RID_ASSOCIATESTA ((UINT16)0xFCE6)
+
+#define HFA384x_RID_CNFWEPDEFAULTKEY_LEN ((UINT16)6)
+#define HFA384x_RID_CNFWEP128DEFAULTKEY_LEN ((UINT16)14)
+#define HFA384x_RID_CNFPRIOQUSAGE_LEN ((UINT16)4)
+/*--------------------------------------------------------------------
+PD Record codes
+--------------------------------------------------------------------*/
+#define HFA384x_PDR_PCB_PARTNUM ((UINT16)0x0001)
+#define HFA384x_PDR_PDAVER ((UINT16)0x0002)
+#define HFA384x_PDR_NIC_SERIAL ((UINT16)0x0003)
+#define HFA384x_PDR_MKK_MEASUREMENTS ((UINT16)0x0004)
+#define HFA384x_PDR_NIC_RAMSIZE ((UINT16)0x0005)
+#define HFA384x_PDR_MFISUPRANGE ((UINT16)0x0006)
+#define HFA384x_PDR_CFISUPRANGE ((UINT16)0x0007)
+#define HFA384x_PDR_NICID ((UINT16)0x0008)
+//#define HFA384x_PDR_REFDAC_MEASUREMENTS ((UINT16)0x0010)
+//#define HFA384x_PDR_VGDAC_MEASUREMENTS ((UINT16)0x0020)
+//#define HFA384x_PDR_LEVEL_COMP_MEASUREMENTS ((UINT16)0x0030)
+//#define HFA384x_PDR_MODEM_TRIMDAC_MEASUREMENTS ((UINT16)0x0040)
+//#define HFA384x_PDR_COREGA_HACK ((UINT16)0x00ff)
+#define HFA384x_PDR_MAC_ADDRESS ((UINT16)0x0101)
+//#define HFA384x_PDR_MKK_CALLNAME ((UINT16)0x0102)
+#define HFA384x_PDR_REGDOMAIN ((UINT16)0x0103)
+#define HFA384x_PDR_ALLOWED_CHANNEL ((UINT16)0x0104)
+#define HFA384x_PDR_DEFAULT_CHANNEL ((UINT16)0x0105)
+//#define HFA384x_PDR_PRIVACY_OPTION ((UINT16)0x0106)
+#define HFA384x_PDR_TEMPTYPE ((UINT16)0x0107)
+//#define HFA384x_PDR_REFDAC_SETUP ((UINT16)0x0110)
+//#define HFA384x_PDR_VGDAC_SETUP ((UINT16)0x0120)
+//#define HFA384x_PDR_LEVEL_COMP_SETUP ((UINT16)0x0130)
+//#define HFA384x_PDR_TRIMDAC_SETUP ((UINT16)0x0140)
+#define HFA384x_PDR_IFR_SETTING ((UINT16)0x0200)
+#define HFA384x_PDR_RFR_SETTING ((UINT16)0x0201)
+#define HFA384x_PDR_HFA3861_BASELINE ((UINT16)0x0202)
+#define HFA384x_PDR_HFA3861_SHADOW ((UINT16)0x0203)
+#define HFA384x_PDR_HFA3861_IFRF ((UINT16)0x0204)
+#define HFA384x_PDR_HFA3861_CHCALSP ((UINT16)0x0300)
+#define HFA384x_PDR_HFA3861_CHCALI ((UINT16)0x0301)
+#define HFA384x_PDR_MAX_TX_POWER ((UINT16)0x0302)
+#define HFA384x_PDR_MASTER_CHAN_LIST ((UINT16)0x0303)
+#define HFA384x_PDR_3842_NIC_CONFIG ((UINT16)0x0400)
+#define HFA384x_PDR_USB_ID ((UINT16)0x0401)
+#define HFA384x_PDR_PCI_ID ((UINT16)0x0402)
+#define HFA384x_PDR_PCI_IFCONF ((UINT16)0x0403)
+#define HFA384x_PDR_PCI_PMCONF ((UINT16)0x0404)
+#define HFA384x_PDR_RFENRGY ((UINT16)0x0406)
+#define HFA384x_PDR_USB_POWER_TYPE ((UINT16)0x0407)
+//#define HFA384x_PDR_UNKNOWN408 ((UINT16)0x0408)
+#define HFA384x_PDR_USB_MAX_POWER ((UINT16)0x0409)
+#define HFA384x_PDR_USB_MANUFACTURER ((UINT16)0x0410)
+#define HFA384x_PDR_USB_PRODUCT ((UINT16)0x0411)
+#define HFA384x_PDR_ANT_DIVERSITY ((UINT16)0x0412)
+#define HFA384x_PDR_HFO_DELAY ((UINT16)0x0413)
+#define HFA384x_PDR_SCALE_THRESH ((UINT16)0x0414)
+
+#define HFA384x_PDR_HFA3861_MANF_TESTSP ((UINT16)0x0900)
+#define HFA384x_PDR_HFA3861_MANF_TESTI ((UINT16)0x0901)
+#define HFA384x_PDR_END_OF_PDA ((UINT16)0x0000)
+
+
+/*=============================================================*/
+/*------ Macros -----------------------------------------------*/
+
+/*--- Register ID macros ------------------------*/
+
+#define HFA384x_CMD HFA384x_CMD_OFF
+#define HFA384x_PARAM0 HFA384x_PARAM0_OFF
+#define HFA384x_PARAM1 HFA384x_PARAM1_OFF
+#define HFA384x_PARAM2 HFA384x_PARAM2_OFF
+#define HFA384x_STATUS HFA384x_STATUS_OFF
+#define HFA384x_RESP0 HFA384x_RESP0_OFF
+#define HFA384x_RESP1 HFA384x_RESP1_OFF
+#define HFA384x_RESP2 HFA384x_RESP2_OFF
+#define HFA384x_INFOFID HFA384x_INFOFID_OFF
+#define HFA384x_RXFID HFA384x_RXFID_OFF
+#define HFA384x_ALLOCFID HFA384x_ALLOCFID_OFF
+#define HFA384x_TXCOMPLFID HFA384x_TXCOMPLFID_OFF
+#define HFA384x_SELECT0 HFA384x_SELECT0_OFF
+#define HFA384x_OFFSET0 HFA384x_OFFSET0_OFF
+#define HFA384x_DATA0 HFA384x_DATA0_OFF
+#define HFA384x_SELECT1 HFA384x_SELECT1_OFF
+#define HFA384x_OFFSET1 HFA384x_OFFSET1_OFF
+#define HFA384x_DATA1 HFA384x_DATA1_OFF
+#define HFA384x_EVSTAT HFA384x_EVSTAT_OFF
+#define HFA384x_INTEN HFA384x_INTEN_OFF
+#define HFA384x_EVACK HFA384x_EVACK_OFF
+#define HFA384x_CONTROL HFA384x_CONTROL_OFF
+#define HFA384x_SWSUPPORT0 HFA384x_SWSUPPORT0_OFF
+#define HFA384x_SWSUPPORT1 HFA384x_SWSUPPORT1_OFF
+#define HFA384x_SWSUPPORT2 HFA384x_SWSUPPORT2_OFF
+#define HFA384x_AUXPAGE HFA384x_AUXPAGE_OFF
+#define HFA384x_AUXOFFSET HFA384x_AUXOFFSET_OFF
+#define HFA384x_AUXDATA HFA384x_AUXDATA_OFF
+#define HFA384x_PCICOR HFA384x_PCICOR_OFF
+#define HFA384x_PCIHCR HFA384x_PCIHCR_OFF
+
+
+/*--- Register Test/Get/Set Field macros ------------------------*/
+
+#define HFA384x_CMD_ISBUSY(value) ((UINT16)(((UINT16)value) & HFA384x_CMD_BUSY))
+#define HFA384x_CMD_AINFO_GET(value) ((UINT16)(((UINT16)(value) & HFA384x_CMD_AINFO) >> 8))
+#define HFA384x_CMD_AINFO_SET(value) ((UINT16)((UINT16)(value) << 8))
+#define HFA384x_CMD_MACPORT_GET(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_MACPORT)))
+#define HFA384x_CMD_MACPORT_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET(value))
+#define HFA384x_CMD_ISRECL(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_RECL)))
+#define HFA384x_CMD_RECL_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET(value))
+#define HFA384x_CMD_QOS_GET(value) ((UINT16((((UINT16)(value))&((UINT16)0x3000)) >> 12))
+#define HFA384x_CMD_QOS_SET(value) ((UINT16)((((UINT16)(value)) << 12) & 0x3000))
+#define HFA384x_CMD_ISWRITE(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_WRITE)))
+#define HFA384x_CMD_WRITE_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET((UINT16)value))
+#define HFA384x_CMD_PROGMODE_GET(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_PROGMODE)))
+#define HFA384x_CMD_PROGMODE_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET((UINT16)value))
+#define HFA384x_CMD_CMDCODE_GET(value) ((UINT16)(((UINT16)(value)) & HFA384x_CMD_CMDCODE))
+#define HFA384x_CMD_CMDCODE_SET(value) ((UINT16)(value))
+
+#define HFA384x_STATUS_RESULT_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_STATUS_RESULT) >> 8))
+#define HFA384x_STATUS_RESULT_SET(value) (((UINT16)(value)) << 8)
+#define HFA384x_STATUS_CMDCODE_GET(value) (((UINT16)(value)) & HFA384x_STATUS_CMDCODE)
+#define HFA384x_STATUS_CMDCODE_SET(value) ((UINT16)(value))
+
+#define HFA384x_OFFSET_ISBUSY(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_BUSY))
+#define HFA384x_OFFSET_ISERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_ERR))
+#define HFA384x_OFFSET_DATAOFF_GET(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_DATAOFF))
+#define HFA384x_OFFSET_DATAOFF_SET(value) ((UINT16)(value))
+
+#define HFA384x_EVSTAT_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TICK))
+#define HFA384x_EVSTAT_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_WTERR))
+#define HFA384x_EVSTAT_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_INFDROP))
+#define HFA384x_EVSTAT_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_INFO))
+#define HFA384x_EVSTAT_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_DTIM))
+#define HFA384x_EVSTAT_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_CMD))
+#define HFA384x_EVSTAT_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_ALLOC))
+#define HFA384x_EVSTAT_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TXEXC))
+#define HFA384x_EVSTAT_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TX))
+#define HFA384x_EVSTAT_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_RX))
+
+#define HFA384x_EVSTAT_ISBAP_OP(value) ((UINT16)(((UINT16)(value)) & HFA384x_INT_BAP_OP))
+
+#define HFA384x_INTEN_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TICK))
+#define HFA384x_INTEN_TICK_SET(value) ((UINT16)(((UINT16)(value)) << 15))
+#define HFA384x_INTEN_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_WTERR))
+#define HFA384x_INTEN_WTERR_SET(value) ((UINT16)(((UINT16)(value)) << 14))
+#define HFA384x_INTEN_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_INFDROP))
+#define HFA384x_INTEN_INFDROP_SET(value) ((UINT16)(((UINT16)(value)) << 13))
+#define HFA384x_INTEN_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_INFO))
+#define HFA384x_INTEN_INFO_SET(value) ((UINT16)(((UINT16)(value)) << 7))
+#define HFA384x_INTEN_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_DTIM))
+#define HFA384x_INTEN_DTIM_SET(value) ((UINT16)(((UINT16)(value)) << 5))
+#define HFA384x_INTEN_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_CMD))
+#define HFA384x_INTEN_CMD_SET(value) ((UINT16)(((UINT16)(value)) << 4))
+#define HFA384x_INTEN_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_ALLOC))
+#define HFA384x_INTEN_ALLOC_SET(value) ((UINT16)(((UINT16)(value)) << 3))
+#define HFA384x_INTEN_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TXEXC))
+#define HFA384x_INTEN_TXEXC_SET(value) ((UINT16)(((UINT16)(value)) << 2))
+#define HFA384x_INTEN_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TX))
+#define HFA384x_INTEN_TX_SET(value) ((UINT16)(((UINT16)(value)) << 1))
+#define HFA384x_INTEN_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_RX))
+#define HFA384x_INTEN_RX_SET(value) ((UINT16)(((UINT16)(value)) << 0))
+
+#define HFA384x_EVACK_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TICK))
+#define HFA384x_EVACK_TICK_SET(value) ((UINT16)(((UINT16)(value)) << 15))
+#define HFA384x_EVACK_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_WTERR))
+#define HFA384x_EVACK_WTERR_SET(value) ((UINT16)(((UINT16)(value)) << 14))
+#define HFA384x_EVACK_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_INFDROP))
+#define HFA384x_EVACK_INFDROP_SET(value) ((UINT16)(((UINT16)(value)) << 13))
+#define HFA384x_EVACK_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_INFO))
+#define HFA384x_EVACK_INFO_SET(value) ((UINT16)(((UINT16)(value)) << 7))
+#define HFA384x_EVACK_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_DTIM))
+#define HFA384x_EVACK_DTIM_SET(value) ((UINT16)(((UINT16)(value)) << 5))
+#define HFA384x_EVACK_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_CMD))
+#define HFA384x_EVACK_CMD_SET(value) ((UINT16)(((UINT16)(value)) << 4))
+#define HFA384x_EVACK_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_ALLOC))
+#define HFA384x_EVACK_ALLOC_SET(value) ((UINT16)(((UINT16)(value)) << 3))
+#define HFA384x_EVACK_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TXEXC))
+#define HFA384x_EVACK_TXEXC_SET(value) ((UINT16)(((UINT16)(value)) << 2))
+#define HFA384x_EVACK_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TX))
+#define HFA384x_EVACK_TX_SET(value) ((UINT16)(((UINT16)(value)) << 1))
+#define HFA384x_EVACK_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_RX))
+#define HFA384x_EVACK_RX_SET(value) ((UINT16)(((UINT16)(value)) << 0))
+
+#define HFA384x_CONTROL_AUXEN_SET(value) ((UINT16)(((UINT16)(value)) << 14))
+#define HFA384x_CONTROL_AUXEN_GET(value) ((UINT16)(((UINT16)(value)) >> 14))
+
+/* Byte Order */
+#ifdef __KERNEL__
+#define hfa384x2host_16(n) (__le16_to_cpu((UINT16)(n)))
+#define hfa384x2host_32(n) (__le32_to_cpu((UINT32)(n)))
+#define host2hfa384x_16(n) (__cpu_to_le16((UINT16)(n)))
+#define host2hfa384x_32(n) (__cpu_to_le32((UINT32)(n)))
+#endif
+
+/* Host Maintained State Info */
+#define HFA384x_STATE_PREINIT 0
+#define HFA384x_STATE_INIT 1
+#define HFA384x_STATE_RUNNING 2
+
+/*=============================================================*/
+/*------ Types and their related constants --------------------*/
+
+#define HFA384x_HOSTAUTHASSOC_HOSTAUTH BIT0
+#define HFA384x_HOSTAUTHASSOC_HOSTASSOC BIT1
+
+#define HFA384x_WHAHANDLING_DISABLED 0
+#define HFA384x_WHAHANDLING_PASSTHROUGH BIT1
+
+/*-------------------------------------------------------------*/
+/* Commonly used basic types */
+typedef struct hfa384x_bytestr
+{
+ UINT16 len;
+ UINT8 data[0];
+} __WLAN_ATTRIB_PACK__ hfa384x_bytestr_t;
+
+typedef struct hfa384x_bytestr32
+{
+ UINT16 len;
+ UINT8 data[32];
+} __WLAN_ATTRIB_PACK__ hfa384x_bytestr32_t;
+
+/*--------------------------------------------------------------------
+Configuration Record Structures:
+ Network Parameters, Static Configuration Entities
+--------------------------------------------------------------------*/
+/* Prototype structure: all configuration record structures start with
+these members */
+
+typedef struct hfa384x_record
+{
+ UINT16 reclen;
+ UINT16 rid;
+} __WLAN_ATTRIB_PACK__ hfa384x_rec_t;
+
+typedef struct hfa384x_record16
+{
+ UINT16 reclen;
+ UINT16 rid;
+ UINT16 val;
+} __WLAN_ATTRIB_PACK__ hfa384x_rec16_t;
+
+typedef struct hfa384x_record32
+{
+ UINT16 reclen;
+ UINT16 rid;
+ UINT32 val;
+} __WLAN_ATTRIB_PACK__ hfa384x_rec32;
+
+/*-- Hardware/Firmware Component Information ----------*/
+typedef struct hfa384x_compident
+{
+ UINT16 id;
+ UINT16 variant;
+ UINT16 major;
+ UINT16 minor;
+} __WLAN_ATTRIB_PACK__ hfa384x_compident_t;
+
+typedef struct hfa384x_caplevel
+{
+ UINT16 role;
+ UINT16 id;
+ UINT16 variant;
+ UINT16 bottom;
+ UINT16 top;
+} __WLAN_ATTRIB_PACK__ hfa384x_caplevel_t;
+
+/*-- Configuration Record: cnfPortType --*/
+typedef struct hfa384x_cnfPortType
+{
+ UINT16 cnfPortType;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfPortType_t;
+
+/*-- Configuration Record: cnfOwnMACAddress --*/
+typedef struct hfa384x_cnfOwnMACAddress
+{
+ UINT8 cnfOwnMACAddress[6];
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnMACAddress_t;
+
+/*-- Configuration Record: cnfDesiredSSID --*/
+typedef struct hfa384x_cnfDesiredSSID
+{
+ UINT8 cnfDesiredSSID[34];
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfDesiredSSID_t;
+
+/*-- Configuration Record: cnfOwnChannel --*/
+typedef struct hfa384x_cnfOwnChannel
+{
+ UINT16 cnfOwnChannel;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnChannel_t;
+
+/*-- Configuration Record: cnfOwnSSID --*/
+typedef struct hfa384x_cnfOwnSSID
+{
+ UINT8 cnfOwnSSID[34];
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnSSID_t;
+
+/*-- Configuration Record: cnfOwnATIMWindow --*/
+typedef struct hfa384x_cnfOwnATIMWindow
+{
+ UINT16 cnfOwnATIMWindow;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnATIMWindow_t;
+
+/*-- Configuration Record: cnfSystemScale --*/
+typedef struct hfa384x_cnfSystemScale
+{
+ UINT16 cnfSystemScale;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfSystemScale_t;
+
+/*-- Configuration Record: cnfMaxDataLength --*/
+typedef struct hfa384x_cnfMaxDataLength
+{
+ UINT16 cnfMaxDataLength;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxDataLength_t;
+
+/*-- Configuration Record: cnfWDSAddress --*/
+typedef struct hfa384x_cnfWDSAddress
+{
+ UINT8 cnfWDSAddress[6];
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddress_t;
+
+/*-- Configuration Record: cnfPMEnabled --*/
+typedef struct hfa384x_cnfPMEnabled
+{
+ UINT16 cnfPMEnabled;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEnabled_t;
+
+/*-- Configuration Record: cnfPMEPS --*/
+typedef struct hfa384x_cnfPMEPS
+{
+ UINT16 cnfPMEPS;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEPS_t;
+
+/*-- Configuration Record: cnfMulticastReceive --*/
+typedef struct hfa384x_cnfMulticastReceive
+{
+ UINT16 cnfMulticastReceive;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfMulticastReceive_t;
+
+/*-- Configuration Record: cnfAuthentication --*/
+#define HFA384x_CNFAUTHENTICATION_OPENSYSTEM 0x0001
+#define HFA384x_CNFAUTHENTICATION_SHAREDKEY 0x0002
+#define HFA384x_CNFAUTHENTICATION_LEAP 0x0004
+
+/*-- Configuration Record: cnfMaxSleepDuration --*/
+typedef struct hfa384x_cnfMaxSleepDuration
+{
+ UINT16 cnfMaxSleepDuration;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxSleepDuration_t;
+
+/*-- Configuration Record: cnfPMHoldoverDuration --*/
+typedef struct hfa384x_cnfPMHoldoverDuration
+{
+ UINT16 cnfPMHoldoverDuration;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMHoldoverDuration_t;
+
+/*-- Configuration Record: cnfOwnName --*/
+typedef struct hfa384x_cnfOwnName
+{
+ UINT8 cnfOwnName[34];
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnName_t;
+
+/*-- Configuration Record: cnfOwnDTIMPeriod --*/
+typedef struct hfa384x_cnfOwnDTIMPeriod
+{
+ UINT16 cnfOwnDTIMPeriod;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnDTIMPeriod_t;
+
+/*-- Configuration Record: cnfWDSAddress --*/
+typedef struct hfa384x_cnfWDSAddressN
+{
+ UINT8 cnfWDSAddress[6];
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddressN_t;
+
+/*-- Configuration Record: cnfMulticastPMBuffering --*/
+typedef struct hfa384x_cnfMulticastPMBuffering
+{
+ UINT16 cnfMulticastPMBuffering;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfMulticastPMBuffering_t;
+
+/*--------------------------------------------------------------------
+Configuration Record Structures:
+ Network Parameters, Dynamic Configuration Entities
+--------------------------------------------------------------------*/
+
+/*-- Configuration Record: GroupAddresses --*/
+typedef struct hfa384x_GroupAddresses
+{
+ UINT8 MACAddress[16][6];
+} __WLAN_ATTRIB_PACK__ hfa384x_GroupAddresses_t;
+
+/*-- Configuration Record: CreateIBSS --*/
+typedef struct hfa384x_CreateIBSS
+{
+ UINT16 CreateIBSS;
+} __WLAN_ATTRIB_PACK__ hfa384x_CreateIBSS_t;
+
+#define HFA384x_CREATEIBSS_JOINCREATEIBSS 0
+#define HFA384x_CREATEIBSS_JOINESS_JOINCREATEIBSS 1
+#define HFA384x_CREATEIBSS_JOINIBSS 2
+#define HFA384x_CREATEIBSS_JOINESS_JOINIBSS 3
+
+/*-- Configuration Record: FragmentationThreshold --*/
+typedef struct hfa384x_FragmentationThreshold
+{
+ UINT16 FragmentationThreshold;
+} __WLAN_ATTRIB_PACK__ hfa384x_FragmentationThreshold_t;
+
+/*-- Configuration Record: RTSThreshold --*/
+typedef struct hfa384x_RTSThreshold
+{
+ UINT16 RTSThreshold;
+} __WLAN_ATTRIB_PACK__ hfa384x_RTSThreshold_t;
+
+/*-- Configuration Record: TxRateControl --*/
+typedef struct hfa384x_TxRateControl
+{
+ UINT16 TxRateControl;
+} __WLAN_ATTRIB_PACK__ hfa384x_TxRateControl_t;
+
+/*-- Configuration Record: PromiscuousMode --*/
+typedef struct hfa384x_PromiscuousMode
+{
+ UINT16 PromiscuousMode;
+} __WLAN_ATTRIB_PACK__ hfa384x_PromiscuousMode_t;
+
+/*-- Configuration Record: ScanRequest (data portion only) --*/
+typedef struct hfa384x_ScanRequest_data
+{
+ UINT16 channelList;
+ UINT16 txRate;
+} __WLAN_ATTRIB_PACK__ hfa384x_ScanRequest_data_t;
+
+/*-- Configuration Record: HostScanRequest (data portion only) --*/
+typedef struct hfa384x_HostScanRequest_data
+{
+ UINT16 channelList;
+ UINT16 txRate;
+ hfa384x_bytestr32_t ssid;
+} __WLAN_ATTRIB_PACK__ hfa384x_HostScanRequest_data_t;
+
+/*-- Configuration Record: JoinRequest (data portion only) --*/
+typedef struct hfa384x_JoinRequest_data
+{
+ UINT8 bssid[WLAN_BSSID_LEN];
+ UINT16 channel;
+} __WLAN_ATTRIB_PACK__ hfa384x_JoinRequest_data_t;
+
+/*-- Configuration Record: authenticateStation (data portion only) --*/
+typedef struct hfa384x_authenticateStation_data
+{
+ UINT8 address[WLAN_ADDR_LEN];
+ UINT16 status;
+ UINT16 algorithm;
+} __WLAN_ATTRIB_PACK__ hfa384x_authenticateStation_data_t;
+
+/*-- Configuration Record: associateStation (data portion only) --*/
+typedef struct hfa384x_associateStation_data
+{
+ UINT8 address[WLAN_ADDR_LEN];
+ UINT16 status;
+ UINT16 type;
+} __WLAN_ATTRIB_PACK__ hfa384x_associateStation_data_t;
+
+/*-- Configuration Record: ChannelInfoRequest (data portion only) --*/
+typedef struct hfa384x_ChannelInfoRequest_data
+{
+ UINT16 channelList;
+ UINT16 channelDwellTime;
+} __WLAN_ATTRIB_PACK__ hfa384x_ChannelInfoRequest_data_t;
+
+/*-- Configuration Record: WEPKeyMapping (data portion only) --*/
+typedef struct hfa384x_WEPKeyMapping
+{
+ UINT8 address[WLAN_ADDR_LEN];
+ UINT16 key_index;
+ UINT8 key[16];
+ UINT8 mic_transmit_key[4];
+ UINT8 mic_receive_key[4];
+} __WLAN_ATTRIB_PACK__ hfa384x_WEPKeyMapping_t;
+
+/*-- Configuration Record: WPAData (data portion only) --*/
+typedef struct hfa384x_WPAData
+{
+ UINT16 datalen;
+ UINT8 data[0]; // max 80
+} __WLAN_ATTRIB_PACK__ hfa384x_WPAData_t;
+
+/*--------------------------------------------------------------------
+Configuration Record Structures: Behavior Parameters
+--------------------------------------------------------------------*/
+
+/*-- Configuration Record: TickTime --*/
+typedef struct hfa384x_TickTime
+{
+ UINT16 TickTime;
+} __WLAN_ATTRIB_PACK__ hfa384x_TickTime_t;
+
+/*--------------------------------------------------------------------
+Information Record Structures: NIC Information
+--------------------------------------------------------------------*/
+
+/*-- Information Record: MaxLoadTime --*/
+typedef struct hfa384x_MaxLoadTime
+{
+ UINT16 MaxLoadTime;
+} __WLAN_ATTRIB_PACK__ hfa384x_MaxLoadTime_t;
+
+/*-- Information Record: DownLoadBuffer --*/
+/* NOTE: The page and offset are in AUX format */
+typedef struct hfa384x_downloadbuffer
+{
+ UINT16 page;
+ UINT16 offset;
+ UINT16 len;
+} __WLAN_ATTRIB_PACK__ hfa384x_downloadbuffer_t;
+
+/*-- Information Record: PRIIdentity --*/
+typedef struct hfa384x_PRIIdentity
+{
+ UINT16 PRICompID;
+ UINT16 PRIVariant;
+ UINT16 PRIMajorVersion;
+ UINT16 PRIMinorVersion;
+} __WLAN_ATTRIB_PACK__ hfa384x_PRIIdentity_t;
+
+/*-- Information Record: PRISupRange --*/
+typedef struct hfa384x_PRISupRange
+{
+ UINT16 PRIRole;
+ UINT16 PRIID;
+ UINT16 PRIVariant;
+ UINT16 PRIBottom;
+ UINT16 PRITop;
+} __WLAN_ATTRIB_PACK__ hfa384x_PRISupRange_t;
+
+/*-- Information Record: CFIActRanges --*/
+typedef struct hfa384x_CFIActRanges
+{
+ UINT16 CFIRole;
+ UINT16 CFIID;
+ UINT16 CFIVariant;
+ UINT16 CFIBottom;
+ UINT16 CFITop;
+} __WLAN_ATTRIB_PACK__ hfa384x_CFIActRanges_t;
+
+/*-- Information Record: NICSerialNumber --*/
+typedef struct hfa384x_NICSerialNumber
+{
+ UINT8 NICSerialNumber[12];
+} __WLAN_ATTRIB_PACK__ hfa384x_NICSerialNumber_t;
+
+/*-- Information Record: NICIdentity --*/
+typedef struct hfa384x_NICIdentity
+{
+ UINT16 NICCompID;
+ UINT16 NICVariant;
+ UINT16 NICMajorVersion;
+ UINT16 NICMinorVersion;
+} __WLAN_ATTRIB_PACK__ hfa384x_NICIdentity_t;
+
+/*-- Information Record: MFISupRange --*/
+typedef struct hfa384x_MFISupRange
+{
+ UINT16 MFIRole;
+ UINT16 MFIID;
+ UINT16 MFIVariant;
+ UINT16 MFIBottom;
+ UINT16 MFITop;
+} __WLAN_ATTRIB_PACK__ hfa384x_MFISupRange_t;
+
+/*-- Information Record: CFISupRange --*/
+typedef struct hfa384x_CFISupRange
+{
+ UINT16 CFIRole;
+ UINT16 CFIID;
+ UINT16 CFIVariant;
+ UINT16 CFIBottom;
+ UINT16 CFITop;
+} __WLAN_ATTRIB_PACK__ hfa384x_CFISupRange_t;
+
+/*-- Information Record: BUILDSEQ:BuildSeq --*/
+typedef struct hfa384x_BuildSeq {
+ UINT16 primary;
+ UINT16 secondary;
+} __WLAN_ATTRIB_PACK__ hfa384x_BuildSeq_t;
+
+/*-- Information Record: FWID --*/
+#define HFA384x_FWID_LEN 14
+typedef struct hfa384x_FWID {
+ UINT8 primary[HFA384x_FWID_LEN];
+ UINT8 secondary[HFA384x_FWID_LEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_FWID_t;
+
+/*-- Information Record: ChannelList --*/
+typedef struct hfa384x_ChannelList
+{
+ UINT16 ChannelList;
+} __WLAN_ATTRIB_PACK__ hfa384x_ChannelList_t;
+
+/*-- Information Record: RegulatoryDomains --*/
+typedef struct hfa384x_RegulatoryDomains
+{
+ UINT8 RegulatoryDomains[12];
+} __WLAN_ATTRIB_PACK__ hfa384x_RegulatoryDomains_t;
+
+/*-- Information Record: TempType --*/
+typedef struct hfa384x_TempType
+{
+ UINT16 TempType;
+} __WLAN_ATTRIB_PACK__ hfa384x_TempType_t;
+
+/*-- Information Record: CIS --*/
+typedef struct hfa384x_CIS
+{
+ UINT8 CIS[480];
+} __WLAN_ATTRIB_PACK__ hfa384x_CIS_t;
+
+/*-- Information Record: STAIdentity --*/
+typedef struct hfa384x_STAIdentity
+{
+ UINT16 STACompID;
+ UINT16 STAVariant;
+ UINT16 STAMajorVersion;
+ UINT16 STAMinorVersion;
+} __WLAN_ATTRIB_PACK__ hfa384x_STAIdentity_t;
+
+/*-- Information Record: STASupRange --*/
+typedef struct hfa384x_STASupRange
+{
+ UINT16 STARole;
+ UINT16 STAID;
+ UINT16 STAVariant;
+ UINT16 STABottom;
+ UINT16 STATop;
+} __WLAN_ATTRIB_PACK__ hfa384x_STASupRange_t;
+
+/*-- Information Record: MFIActRanges --*/
+typedef struct hfa384x_MFIActRanges
+{
+ UINT16 MFIRole;
+ UINT16 MFIID;
+ UINT16 MFIVariant;
+ UINT16 MFIBottom;
+ UINT16 MFITop;
+} __WLAN_ATTRIB_PACK__ hfa384x_MFIActRanges_t;
+
+/*--------------------------------------------------------------------
+Information Record Structures: NIC Information
+--------------------------------------------------------------------*/
+
+/*-- Information Record: PortStatus --*/
+typedef struct hfa384x_PortStatus
+{
+ UINT16 PortStatus;
+} __WLAN_ATTRIB_PACK__ hfa384x_PortStatus_t;
+
+#define HFA384x_PSTATUS_DISABLED ((UINT16)1)
+#define HFA384x_PSTATUS_SEARCHING ((UINT16)2)
+#define HFA384x_PSTATUS_CONN_IBSS ((UINT16)3)
+#define HFA384x_PSTATUS_CONN_ESS ((UINT16)4)
+#define HFA384x_PSTATUS_OUTOFRANGE ((UINT16)5)
+#define HFA384x_PSTATUS_CONN_WDS ((UINT16)6)
+
+/*-- Information Record: CurrentSSID --*/
+typedef struct hfa384x_CurrentSSID
+{
+ UINT8 CurrentSSID[34];
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentSSID_t;
+
+/*-- Information Record: CurrentBSSID --*/
+typedef struct hfa384x_CurrentBSSID
+{
+ UINT8 CurrentBSSID[6];
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentBSSID_t;
+
+/*-- Information Record: commsquality --*/
+typedef struct hfa384x_commsquality
+{
+ UINT16 CQ_currBSS;
+ UINT16 ASL_currBSS;
+ UINT16 ANL_currFC;
+} __WLAN_ATTRIB_PACK__ hfa384x_commsquality_t;
+
+/*-- Information Record: dmbcommsquality --*/
+typedef struct hfa384x_dbmcommsquality
+{
+ UINT16 CQdbm_currBSS;
+ UINT16 ASLdbm_currBSS;
+ UINT16 ANLdbm_currFC;
+} __WLAN_ATTRIB_PACK__ hfa384x_dbmcommsquality_t;
+
+/*-- Information Record: CurrentTxRate --*/
+typedef struct hfa384x_CurrentTxRate
+{
+ UINT16 CurrentTxRate;
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentTxRate_t;
+
+/*-- Information Record: CurrentBeaconInterval --*/
+typedef struct hfa384x_CurrentBeaconInterval
+{
+ UINT16 CurrentBeaconInterval;
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentBeaconInterval_t;
+
+/*-- Information Record: CurrentScaleThresholds --*/
+typedef struct hfa384x_CurrentScaleThresholds
+{
+ UINT16 EnergyDetectThreshold;
+ UINT16 CarrierDetectThreshold;
+ UINT16 DeferDetectThreshold;
+ UINT16 CellSearchThreshold; /* Stations only */
+ UINT16 DeadSpotThreshold; /* Stations only */
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentScaleThresholds_t;
+
+/*-- Information Record: ProtocolRspTime --*/
+typedef struct hfa384x_ProtocolRspTime
+{
+ UINT16 ProtocolRspTime;
+} __WLAN_ATTRIB_PACK__ hfa384x_ProtocolRspTime_t;
+
+/*-- Information Record: ShortRetryLimit --*/
+typedef struct hfa384x_ShortRetryLimit
+{
+ UINT16 ShortRetryLimit;
+} __WLAN_ATTRIB_PACK__ hfa384x_ShortRetryLimit_t;
+
+/*-- Information Record: LongRetryLimit --*/
+typedef struct hfa384x_LongRetryLimit
+{
+ UINT16 LongRetryLimit;
+} __WLAN_ATTRIB_PACK__ hfa384x_LongRetryLimit_t;
+
+/*-- Information Record: MaxTransmitLifetime --*/
+typedef struct hfa384x_MaxTransmitLifetime
+{
+ UINT16 MaxTransmitLifetime;
+} __WLAN_ATTRIB_PACK__ hfa384x_MaxTransmitLifetime_t;
+
+/*-- Information Record: MaxReceiveLifetime --*/
+typedef struct hfa384x_MaxReceiveLifetime
+{
+ UINT16 MaxReceiveLifetime;
+} __WLAN_ATTRIB_PACK__ hfa384x_MaxReceiveLifetime_t;
+
+/*-- Information Record: CFPollable --*/
+typedef struct hfa384x_CFPollable
+{
+ UINT16 CFPollable;
+} __WLAN_ATTRIB_PACK__ hfa384x_CFPollable_t;
+
+/*-- Information Record: AuthenticationAlgorithms --*/
+typedef struct hfa384x_AuthenticationAlgorithms
+{
+ UINT16 AuthenticationType;
+ UINT16 TypeEnabled;
+} __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_t;
+
+/*-- Information Record: AuthenticationAlgorithms
+(data only --*/
+typedef struct hfa384x_AuthenticationAlgorithms_data
+{
+ UINT16 AuthenticationType;
+ UINT16 TypeEnabled;
+} __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_data_t;
+
+/*-- Information Record: PrivacyOptionImplemented --*/
+typedef struct hfa384x_PrivacyOptionImplemented
+{
+ UINT16 PrivacyOptionImplemented;
+} __WLAN_ATTRIB_PACK__ hfa384x_PrivacyOptionImplemented_t;
+
+/*-- Information Record: OwnMACAddress --*/
+typedef struct hfa384x_OwnMACAddress
+{
+ UINT8 OwnMACAddress[6];
+} __WLAN_ATTRIB_PACK__ hfa384x_OwnMACAddress_t;
+
+/*-- Information Record: PCFInfo --*/
+typedef struct hfa384x_PCFInfo
+{
+ UINT16 MediumOccupancyLimit;
+ UINT16 CFPPeriod;
+ UINT16 CFPMaxDuration;
+ UINT16 CFPFlags;
+} __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_t;
+
+/*-- Information Record: PCFInfo (data portion only) --*/
+typedef struct hfa384x_PCFInfo_data
+{
+ UINT16 MediumOccupancyLimit;
+ UINT16 CFPPeriod;
+ UINT16 CFPMaxDuration;
+ UINT16 CFPFlags;
+} __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_data_t;
+
+/*--------------------------------------------------------------------
+Information Record Structures: Modem Information Records
+--------------------------------------------------------------------*/
+
+/*-- Information Record: PHYType --*/
+typedef struct hfa384x_PHYType
+{
+ UINT16 PHYType;
+} __WLAN_ATTRIB_PACK__ hfa384x_PHYType_t;
+
+/*-- Information Record: CurrentChannel --*/
+typedef struct hfa384x_CurrentChannel
+{
+ UINT16 CurrentChannel;
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentChannel_t;
+
+/*-- Information Record: CurrentPowerState --*/
+typedef struct hfa384x_CurrentPowerState
+{
+ UINT16 CurrentPowerState;
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentPowerState_t;
+
+/*-- Information Record: CCAMode --*/
+typedef struct hfa384x_CCAMode
+{
+ UINT16 CCAMode;
+} __WLAN_ATTRIB_PACK__ hfa384x_CCAMode_t;
+
+/*-- Information Record: SupportedDataRates --*/
+typedef struct hfa384x_SupportedDataRates
+{
+ UINT8 SupportedDataRates[10];
+} __WLAN_ATTRIB_PACK__ hfa384x_SupportedDataRates_t;
+
+/*-- Information Record: LFOStatus --*/
+typedef struct hfa384x_LFOStatus
+{
+ UINT16 TestResults;
+ UINT16 LFOResult;
+ UINT16 VRHFOResult;
+} __WLAN_ATTRIB_PACK__ hfa384x_LFOStatus_t;
+
+#define HFA384x_TESTRESULT_ALLPASSED BIT0
+#define HFA384x_TESTRESULT_LFO_FAIL BIT1
+#define HFA384x_TESTRESULT_VR_HF0_FAIL BIT2
+#define HFA384x_HOST_FIRM_COORDINATE BIT7
+#define HFA384x_TESTRESULT_COORDINATE BIT15
+
+/*-- Information Record: LEDControl --*/
+typedef struct hfa384x_LEDControl
+{
+ UINT16 searching_on;
+ UINT16 searching_off;
+ UINT16 assoc_on;
+ UINT16 assoc_off;
+ UINT16 activity;
+} __WLAN_ATTRIB_PACK__ hfa384x_LEDControl_t;
+
+/*--------------------------------------------------------------------
+ FRAME DESCRIPTORS AND FRAME STRUCTURES
+
+FRAME DESCRIPTORS: Offsets
+
+----------------------------------------------------------------------
+Control Info (offset 44-51)
+--------------------------------------------------------------------*/
+#define HFA384x_FD_STATUS_OFF ((UINT16)0x44)
+#define HFA384x_FD_TIME_OFF ((UINT16)0x46)
+#define HFA384x_FD_SWSUPPORT_OFF ((UINT16)0x4A)
+#define HFA384x_FD_SILENCE_OFF ((UINT16)0x4A)
+#define HFA384x_FD_SIGNAL_OFF ((UINT16)0x4B)
+#define HFA384x_FD_RATE_OFF ((UINT16)0x4C)
+#define HFA384x_FD_RXFLOW_OFF ((UINT16)0x4D)
+#define HFA384x_FD_RESERVED_OFF ((UINT16)0x4E)
+#define HFA384x_FD_TXCONTROL_OFF ((UINT16)0x50)
+/*--------------------------------------------------------------------
+802.11 Header (offset 52-6B)
+--------------------------------------------------------------------*/
+#define HFA384x_FD_FRAMECONTROL_OFF ((UINT16)0x52)
+#define HFA384x_FD_DURATIONID_OFF ((UINT16)0x54)
+#define HFA384x_FD_ADDRESS1_OFF ((UINT16)0x56)
+#define HFA384x_FD_ADDRESS2_OFF ((UINT16)0x5C)
+#define HFA384x_FD_ADDRESS3_OFF ((UINT16)0x62)
+#define HFA384x_FD_SEQCONTROL_OFF ((UINT16)0x68)
+#define HFA384x_FD_ADDRESS4_OFF ((UINT16)0x6A)
+#define HFA384x_FD_DATALEN_OFF ((UINT16)0x70)
+/*--------------------------------------------------------------------
+802.3 Header (offset 72-7F)
+--------------------------------------------------------------------*/
+#define HFA384x_FD_DESTADDRESS_OFF ((UINT16)0x72)
+#define HFA384x_FD_SRCADDRESS_OFF ((UINT16)0x78)
+#define HFA384x_FD_DATALENGTH_OFF ((UINT16)0x7E)
+
+/*--------------------------------------------------------------------
+FRAME STRUCTURES: Communication Frames
+----------------------------------------------------------------------
+Communication Frames: Transmit Frames
+--------------------------------------------------------------------*/
+/*-- Communication Frame: Transmit Frame Structure --*/
+typedef struct hfa384x_tx_frame
+{
+ UINT16 status;
+ UINT16 reserved1;
+ UINT16 reserved2;
+ UINT32 sw_support;
+ UINT8 tx_retrycount;
+ UINT8 tx_rate;
+ UINT16 tx_control;
+
+ /*-- 802.11 Header Information --*/
+
+ UINT16 frame_control;
+ UINT16 duration_id;
+ UINT8 address1[6];
+ UINT8 address2[6];
+ UINT8 address3[6];
+ UINT16 sequence_control;
+ UINT8 address4[6];
+ UINT16 data_len; /* little endian format */
+
+ /*-- 802.3 Header Information --*/
+
+ UINT8 dest_addr[6];
+ UINT8 src_addr[6];
+ UINT16 data_length; /* big endian format */
+} __WLAN_ATTRIB_PACK__ hfa384x_tx_frame_t;
+/*--------------------------------------------------------------------
+Communication Frames: Field Masks for Transmit Frames
+--------------------------------------------------------------------*/
+/*-- Status Field --*/
+#define HFA384x_TXSTATUS_ACKERR ((UINT16)BIT5)
+#define HFA384x_TXSTATUS_FORMERR ((UINT16)BIT3)
+#define HFA384x_TXSTATUS_DISCON ((UINT16)BIT2)
+#define HFA384x_TXSTATUS_AGEDERR ((UINT16)BIT1)
+#define HFA384x_TXSTATUS_RETRYERR ((UINT16)BIT0)
+/*-- Transmit Control Field --*/
+#define HFA384x_TX_CFPOLL ((UINT16)BIT12)
+#define HFA384x_TX_PRST ((UINT16)BIT11)
+#define HFA384x_TX_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8))
+#define HFA384x_TX_NOENCRYPT ((UINT16)BIT7)
+#define HFA384x_TX_RETRYSTRAT ((UINT16)(BIT6 | BIT5))
+#define HFA384x_TX_STRUCTYPE ((UINT16)(BIT4 | BIT3))
+#define HFA384x_TX_TXEX ((UINT16)BIT2)
+#define HFA384x_TX_TXOK ((UINT16)BIT1)
+/*--------------------------------------------------------------------
+Communication Frames: Test/Get/Set Field Values for Transmit Frames
+--------------------------------------------------------------------*/
+/*-- Status Field --*/
+#define HFA384x_TXSTATUS_ISERROR(v) \
+ (((UINT16)(v))&\
+ (HFA384x_TXSTATUS_ACKERR|HFA384x_TXSTATUS_FORMERR|\
+ HFA384x_TXSTATUS_DISCON|HFA384x_TXSTATUS_AGEDERR|\
+ HFA384x_TXSTATUS_RETRYERR))
+
+#define HFA384x_TXSTATUS_ISACKERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_ACKERR))
+#define HFA384x_TXSTATUS_ISFORMERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_FORMERR))
+#define HFA384x_TXSTATUS_ISDISCON(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_DISCON))
+#define HFA384x_TXSTATUS_ISAGEDERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_AGEDERR))
+#define HFA384x_TXSTATUS_ISRETRYERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_RETRYERR))
+
+#define HFA384x_TX_GET(v,m,s) ((((UINT16)(v))&((UINT16)(m)))>>((UINT16)(s)))
+#define HFA384x_TX_SET(v,m,s) ((((UINT16)(v))<<((UINT16)(s)))&((UINT16)(m)))
+
+#define HFA384x_TX_CFPOLL_GET(v) HFA384x_TX_GET(v, HFA384x_TX_CFPOLL,12)
+#define HFA384x_TX_CFPOLL_SET(v) HFA384x_TX_SET(v, HFA384x_TX_CFPOLL,12)
+#define HFA384x_TX_PRST_GET(v) HFA384x_TX_GET(v, HFA384x_TX_PRST,11)
+#define HFA384x_TX_PRST_SET(v) HFA384x_TX_SET(v, HFA384x_TX_PRST,11)
+#define HFA384x_TX_MACPORT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_MACPORT, 8)
+#define HFA384x_TX_MACPORT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_MACPORT, 8)
+#define HFA384x_TX_NOENCRYPT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_NOENCRYPT, 7)
+#define HFA384x_TX_NOENCRYPT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_NOENCRYPT, 7)
+#define HFA384x_TX_RETRYSTRAT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_RETRYSTRAT, 5)
+#define HFA384x_TX_RETRYSTRAT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_RETRYSTRAT, 5)
+#define HFA384x_TX_STRUCTYPE_GET(v) HFA384x_TX_GET(v, HFA384x_TX_STRUCTYPE, 3)
+#define HFA384x_TX_STRUCTYPE_SET(v) HFA384x_TX_SET(v, HFA384x_TX_STRUCTYPE, 3)
+#define HFA384x_TX_TXEX_GET(v) HFA384x_TX_GET(v, HFA384x_TX_TXEX, 2)
+#define HFA384x_TX_TXEX_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXEX, 2)
+#define HFA384x_TX_TXOK_GET(v) HFA384x_TX_GET(v, HFA384x_TX_TXOK, 1)
+#define HFA384x_TX_TXOK_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXOK, 1)
+/*--------------------------------------------------------------------
+Communication Frames: Receive Frames
+--------------------------------------------------------------------*/
+/*-- Communication Frame: Receive Frame Structure --*/
+typedef struct hfa384x_rx_frame
+{
+ /*-- MAC rx descriptor (hfa384x byte order) --*/
+ UINT16 status;
+ UINT32 time;
+ UINT8 silence;
+ UINT8 signal;
+ UINT8 rate;
+ UINT8 rx_flow;
+ UINT16 reserved1;
+ UINT16 reserved2;
+
+ /*-- 802.11 Header Information (802.11 byte order) --*/
+ UINT16 frame_control;
+ UINT16 duration_id;
+ UINT8 address1[6];
+ UINT8 address2[6];
+ UINT8 address3[6];
+ UINT16 sequence_control;
+ UINT8 address4[6];
+ UINT16 data_len; /* hfa384x (little endian) format */
+
+ /*-- 802.3 Header Information --*/
+ UINT8 dest_addr[6];
+ UINT8 src_addr[6];
+ UINT16 data_length; /* IEEE? (big endian) format */
+} __WLAN_ATTRIB_PACK__ hfa384x_rx_frame_t;
+/*--------------------------------------------------------------------
+Communication Frames: Field Masks for Receive Frames
+--------------------------------------------------------------------*/
+/*-- Offsets --------*/
+#define HFA384x_RX_DATA_LEN_OFF ((UINT16)44)
+#define HFA384x_RX_80211HDR_OFF ((UINT16)14)
+#define HFA384x_RX_DATA_OFF ((UINT16)60)
+
+/*-- Status Fields --*/
+#define HFA384x_RXSTATUS_MSGTYPE ((UINT16)(BIT15 | BIT14 | BIT13))
+#define HFA384x_RXSTATUS_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8))
+#define HFA384x_RXSTATUS_UNDECR ((UINT16)BIT1)
+#define HFA384x_RXSTATUS_FCSERR ((UINT16)BIT0)
+/*--------------------------------------------------------------------
+Communication Frames: Test/Get/Set Field Values for Receive Frames
+--------------------------------------------------------------------*/
+#define HFA384x_RXSTATUS_MSGTYPE_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_RXSTATUS_MSGTYPE) >> 13))
+#define HFA384x_RXSTATUS_MSGTYPE_SET(value) ((UINT16)(((UINT16)(value)) << 13))
+#define HFA384x_RXSTATUS_MACPORT_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_RXSTATUS_MACPORT) >> 8))
+#define HFA384x_RXSTATUS_MACPORT_SET(value) ((UINT16)(((UINT16)(value)) << 8))
+#define HFA384x_RXSTATUS_ISUNDECR(value) ((UINT16)(((UINT16)(value)) & HFA384x_RXSTATUS_UNDECR))
+#define HFA384x_RXSTATUS_ISFCSERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_RXSTATUS_FCSERR))
+/*--------------------------------------------------------------------
+ FRAME STRUCTURES: Information Types and Information Frame Structures
+----------------------------------------------------------------------
+Information Types
+--------------------------------------------------------------------*/
+#define HFA384x_IT_HANDOVERADDR ((UINT16)0xF000UL)
+#define HFA384x_IT_HANDOVERDEAUTHADDRESS ((UINT16)0xF001UL)//AP 1.3.7
+#define HFA384x_IT_COMMTALLIES ((UINT16)0xF100UL)
+#define HFA384x_IT_SCANRESULTS ((UINT16)0xF101UL)
+#define HFA384x_IT_CHINFORESULTS ((UINT16)0xF102UL)
+#define HFA384x_IT_HOSTSCANRESULTS ((UINT16)0xF103UL)
+#define HFA384x_IT_LINKSTATUS ((UINT16)0xF200UL)
+#define HFA384x_IT_ASSOCSTATUS ((UINT16)0xF201UL)
+#define HFA384x_IT_AUTHREQ ((UINT16)0xF202UL)
+#define HFA384x_IT_PSUSERCNT ((UINT16)0xF203UL)
+#define HFA384x_IT_KEYIDCHANGED ((UINT16)0xF204UL)
+#define HFA384x_IT_ASSOCREQ ((UINT16)0xF205UL)
+#define HFA384x_IT_MICFAILURE ((UINT16)0xF206UL)
+
+/*--------------------------------------------------------------------
+Information Frames Structures
+----------------------------------------------------------------------
+Information Frames: Notification Frame Structures
+--------------------------------------------------------------------*/
+/*-- Notification Frame,MAC Mgmt: Handover Address --*/
+typedef struct hfa384x_HandoverAddr
+{
+ UINT16 framelen;
+ UINT16 infotype;
+ UINT8 handover_addr[WLAN_BSSID_LEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_HandoverAddr_t;
+
+/*-- Inquiry Frame, Diagnose: Communication Tallies --*/
+typedef struct hfa384x_CommTallies16
+{
+ UINT16 txunicastframes;
+ UINT16 txmulticastframes;
+ UINT16 txfragments;
+ UINT16 txunicastoctets;
+ UINT16 txmulticastoctets;
+ UINT16 txdeferredtrans;
+ UINT16 txsingleretryframes;
+ UINT16 txmultipleretryframes;
+ UINT16 txretrylimitexceeded;
+ UINT16 txdiscards;
+ UINT16 rxunicastframes;
+ UINT16 rxmulticastframes;
+ UINT16 rxfragments;
+ UINT16 rxunicastoctets;
+ UINT16 rxmulticastoctets;
+ UINT16 rxfcserrors;
+ UINT16 rxdiscardsnobuffer;
+ UINT16 txdiscardswrongsa;
+ UINT16 rxdiscardswepundecr;
+ UINT16 rxmsginmsgfrag;
+ UINT16 rxmsginbadmsgfrag;
+} __WLAN_ATTRIB_PACK__ hfa384x_CommTallies16_t;
+
+typedef struct hfa384x_CommTallies32
+{
+ UINT32 txunicastframes;
+ UINT32 txmulticastframes;
+ UINT32 txfragments;
+ UINT32 txunicastoctets;
+ UINT32 txmulticastoctets;
+ UINT32 txdeferredtrans;
+ UINT32 txsingleretryframes;
+ UINT32 txmultipleretryframes;
+ UINT32 txretrylimitexceeded;
+ UINT32 txdiscards;
+ UINT32 rxunicastframes;
+ UINT32 rxmulticastframes;
+ UINT32 rxfragments;
+ UINT32 rxunicastoctets;
+ UINT32 rxmulticastoctets;
+ UINT32 rxfcserrors;
+ UINT32 rxdiscardsnobuffer;
+ UINT32 txdiscardswrongsa;
+ UINT32 rxdiscardswepundecr;
+ UINT32 rxmsginmsgfrag;
+ UINT32 rxmsginbadmsgfrag;
+} __WLAN_ATTRIB_PACK__ hfa384x_CommTallies32_t;
+
+/*-- Inquiry Frame, Diagnose: Scan Results & Subfields--*/
+typedef struct hfa384x_ScanResultSub
+{
+ UINT16 chid;
+ UINT16 anl;
+ UINT16 sl;
+ UINT8 bssid[WLAN_BSSID_LEN];
+ UINT16 bcnint;
+ UINT16 capinfo;
+ hfa384x_bytestr32_t ssid;
+ UINT8 supprates[10]; /* 802.11 info element */
+ UINT16 proberesp_rate;
+} __WLAN_ATTRIB_PACK__ hfa384x_ScanResultSub_t;
+
+typedef struct hfa384x_ScanResult
+{
+ UINT16 rsvd;
+ UINT16 scanreason;
+ hfa384x_ScanResultSub_t
+ result[HFA384x_SCANRESULT_MAX];
+} __WLAN_ATTRIB_PACK__ hfa384x_ScanResult_t;
+
+/*-- Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/
+typedef struct hfa384x_ChInfoResultSub
+{
+ UINT16 chid;
+ UINT16 anl;
+ UINT16 pnl;
+ UINT16 active;
+} __WLAN_ATTRIB_PACK__ hfa384x_ChInfoResultSub_t;
+
+#define HFA384x_CHINFORESULT_BSSACTIVE BIT0
+#define HFA384x_CHINFORESULT_PCFACTIVE BIT1
+
+typedef struct hfa384x_ChInfoResult
+{
+ UINT16 scanchannels;
+ hfa384x_ChInfoResultSub_t
+ result[HFA384x_CHINFORESULT_MAX];
+} __WLAN_ATTRIB_PACK__ hfa384x_ChInfoResult_t;
+
+/*-- Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/
+typedef struct hfa384x_HScanResultSub
+{
+ UINT16 chid;
+ UINT16 anl;
+ UINT16 sl;
+ UINT8 bssid[WLAN_BSSID_LEN];
+ UINT16 bcnint;
+ UINT16 capinfo;
+ hfa384x_bytestr32_t ssid;
+ UINT8 supprates[10]; /* 802.11 info element */
+ UINT16 proberesp_rate;
+ UINT16 atim;
+} __WLAN_ATTRIB_PACK__ hfa384x_HScanResultSub_t;
+
+typedef struct hfa384x_HScanResult
+{
+ UINT16 nresult;
+ UINT16 rsvd;
+ hfa384x_HScanResultSub_t
+ result[HFA384x_HSCANRESULT_MAX];
+} __WLAN_ATTRIB_PACK__ hfa384x_HScanResult_t;
+
+/*-- Unsolicited Frame, MAC Mgmt: LinkStatus --*/
+
+#define HFA384x_LINK_NOTCONNECTED ((UINT16)0)
+#define HFA384x_LINK_CONNECTED ((UINT16)1)
+#define HFA384x_LINK_DISCONNECTED ((UINT16)2)
+#define HFA384x_LINK_AP_CHANGE ((UINT16)3)
+#define HFA384x_LINK_AP_OUTOFRANGE ((UINT16)4)
+#define HFA384x_LINK_AP_INRANGE ((UINT16)5)
+#define HFA384x_LINK_ASSOCFAIL ((UINT16)6)
+
+typedef struct hfa384x_LinkStatus
+{
+ UINT16 linkstatus;
+} __WLAN_ATTRIB_PACK__ hfa384x_LinkStatus_t;
+
+
+/*-- Unsolicited Frame, MAC Mgmt: AssociationStatus (--*/
+
+#define HFA384x_ASSOCSTATUS_STAASSOC ((UINT16)1)
+#define HFA384x_ASSOCSTATUS_REASSOC ((UINT16)2)
+#define HFA384x_ASSOCSTATUS_DISASSOC ((UINT16)3)
+#define HFA384x_ASSOCSTATUS_ASSOCFAIL ((UINT16)4)
+#define HFA384x_ASSOCSTATUS_AUTHFAIL ((UINT16)5)
+
+typedef struct hfa384x_AssocStatus
+{
+ UINT16 assocstatus;
+ UINT8 sta_addr[WLAN_ADDR_LEN];
+ /* old_ap_addr is only valid if assocstatus == 2 */
+ UINT8 old_ap_addr[WLAN_ADDR_LEN];
+ UINT16 reason;
+ UINT16 reserved;
+} __WLAN_ATTRIB_PACK__ hfa384x_AssocStatus_t;
+
+/*-- Unsolicited Frame, MAC Mgmt: AuthRequest (AP Only) --*/
+
+typedef struct hfa384x_AuthRequest
+{
+ UINT8 sta_addr[WLAN_ADDR_LEN];
+ UINT16 algorithm;
+} __WLAN_ATTRIB_PACK__ hfa384x_AuthReq_t;
+
+/*-- Unsolicited Frame, MAC Mgmt: AssocRequest (AP Only) --*/
+
+typedef struct hfa384x_AssocRequest
+{
+ UINT8 sta_addr[WLAN_ADDR_LEN];
+ UINT16 type;
+ UINT8 wpa_data[80];
+} __WLAN_ATTRIB_PACK__ hfa384x_AssocReq_t;
+
+
+#define HFA384x_ASSOCREQ_TYPE_ASSOC 0
+#define HFA384x_ASSOCREQ_TYPE_REASSOC 1
+
+/*-- Unsolicited Frame, MAC Mgmt: MIC Failure (AP Only) --*/
+
+typedef struct hfa384x_MicFailure
+{
+ UINT8 sender[WLAN_ADDR_LEN];
+ UINT8 dest[WLAN_ADDR_LEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_MicFailure_t;
+
+/*-- Unsolicited Frame, MAC Mgmt: PSUserCount (AP Only) --*/
+
+typedef struct hfa384x_PSUserCount
+{
+ UINT16 usercnt;
+} __WLAN_ATTRIB_PACK__ hfa384x_PSUserCount_t;
+
+typedef struct hfa384x_KeyIDChanged
+{
+ UINT8 sta_addr[WLAN_ADDR_LEN];
+ UINT16 keyid;
+} __WLAN_ATTRIB_PACK__ hfa384x_KeyIDChanged_t;
+
+/*-- Collection of all Inf frames ---------------*/
+typedef union hfa384x_infodata {
+ hfa384x_CommTallies16_t commtallies16;
+ hfa384x_CommTallies32_t commtallies32;
+ hfa384x_ScanResult_t scanresult;
+ hfa384x_ChInfoResult_t chinforesult;
+ hfa384x_HScanResult_t hscanresult;
+ hfa384x_LinkStatus_t linkstatus;
+ hfa384x_AssocStatus_t assocstatus;
+ hfa384x_AuthReq_t authreq;
+ hfa384x_PSUserCount_t psusercnt;
+ hfa384x_KeyIDChanged_t keyidchanged;
+} __WLAN_ATTRIB_PACK__ hfa384x_infodata_t;
+
+typedef struct hfa384x_InfFrame
+{
+ UINT16 framelen;
+ UINT16 infotype;
+ hfa384x_infodata_t info;
+} __WLAN_ATTRIB_PACK__ hfa384x_InfFrame_t;
+
+#if (WLAN_HOSTIF == WLAN_USB)
+/*--------------------------------------------------------------------
+USB Packet structures and constants.
+--------------------------------------------------------------------*/
+
+/* Should be sent to the ctrlout endpoint */
+#define HFA384x_USB_ENBULKIN 6
+
+/* Should be sent to the bulkout endpoint */
+#define HFA384x_USB_TXFRM 0
+#define HFA384x_USB_CMDREQ 1
+#define HFA384x_USB_WRIDREQ 2
+#define HFA384x_USB_RRIDREQ 3
+#define HFA384x_USB_WMEMREQ 4
+#define HFA384x_USB_RMEMREQ 5
+
+/* Received from the bulkin endpoint */
+#define HFA384x_USB_ISFRM(a) (!((a) & 0x8000))
+#define HFA384x_USB_ISTXFRM(a) (((a) & 0x9000) == 0x1000)
+#define HFA384x_USB_ISRXFRM(a) (!((a) & 0x9000))
+#define HFA384x_USB_INFOFRM 0x8000
+#define HFA384x_USB_CMDRESP 0x8001
+#define HFA384x_USB_WRIDRESP 0x8002
+#define HFA384x_USB_RRIDRESP 0x8003
+#define HFA384x_USB_WMEMRESP 0x8004
+#define HFA384x_USB_RMEMRESP 0x8005
+#define HFA384x_USB_BUFAVAIL 0x8006
+#define HFA384x_USB_ERROR 0x8007
+
+/*------------------------------------*/
+/* Request (bulk OUT) packet contents */
+
+typedef struct hfa384x_usb_txfrm {
+ hfa384x_tx_frame_t desc;
+ UINT8 data[WLAN_DATA_MAXLEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_txfrm_t;
+
+typedef struct hfa384x_usb_cmdreq {
+ UINT16 type;
+ UINT16 cmd;
+ UINT16 parm0;
+ UINT16 parm1;
+ UINT16 parm2;
+ UINT8 pad[54];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdreq_t;
+
+typedef struct hfa384x_usb_wridreq {
+ UINT16 type;
+ UINT16 frmlen;
+ UINT16 rid;
+ UINT8 data[HFA384x_RIDDATA_MAXLEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_wridreq_t;
+
+typedef struct hfa384x_usb_rridreq {
+ UINT16 type;
+ UINT16 frmlen;
+ UINT16 rid;
+ UINT8 pad[58];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_rridreq_t;
+
+typedef struct hfa384x_usb_wmemreq {
+ UINT16 type;
+ UINT16 frmlen;
+ UINT16 offset;
+ UINT16 page;
+ UINT8 data[HFA384x_USB_RWMEM_MAXLEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_wmemreq_t;
+
+typedef struct hfa384x_usb_rmemreq {
+ UINT16 type;
+ UINT16 frmlen;
+ UINT16 offset;
+ UINT16 page;
+ UINT8 pad[56];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemreq_t;
+
+/*------------------------------------*/
+/* Response (bulk IN) packet contents */
+
+typedef struct hfa384x_usb_rxfrm {
+ hfa384x_rx_frame_t desc;
+ UINT8 data[WLAN_DATA_MAXLEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_rxfrm_t;
+
+typedef struct hfa384x_usb_infofrm {
+ UINT16 type;
+ hfa384x_InfFrame_t info;
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_infofrm_t;
+
+typedef struct hfa384x_usb_statusresp {
+ UINT16 type;
+ UINT16 status;
+ UINT16 resp0;
+ UINT16 resp1;
+ UINT16 resp2;
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdresp_t;
+
+typedef hfa384x_usb_cmdresp_t hfa384x_usb_wridresp_t;
+
+typedef struct hfa384x_usb_rridresp {
+ UINT16 type;
+ UINT16 frmlen;
+ UINT16 rid;
+ UINT8 data[HFA384x_RIDDATA_MAXLEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_rridresp_t;
+
+typedef hfa384x_usb_cmdresp_t hfa384x_usb_wmemresp_t;
+
+typedef struct hfa384x_usb_rmemresp {
+ UINT16 type;
+ UINT16 frmlen;
+ UINT8 data[HFA384x_USB_RWMEM_MAXLEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemresp_t;
+
+typedef struct hfa384x_usb_bufavail {
+ UINT16 type;
+ UINT16 frmlen;
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_bufavail_t;
+
+typedef struct hfa384x_usb_error {
+ UINT16 type;
+ UINT16 errortype;
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_error_t;
+
+/*----------------------------------------------------------*/
+/* Unions for packaging all the known packet types together */
+
+typedef union hfa384x_usbout {
+ UINT16 type;
+ hfa384x_usb_txfrm_t txfrm;
+ hfa384x_usb_cmdreq_t cmdreq;
+ hfa384x_usb_wridreq_t wridreq;
+ hfa384x_usb_rridreq_t rridreq;
+ hfa384x_usb_wmemreq_t wmemreq;
+ hfa384x_usb_rmemreq_t rmemreq;
+} __WLAN_ATTRIB_PACK__ hfa384x_usbout_t;
+
+typedef union hfa384x_usbin {
+ UINT16 type;
+ hfa384x_usb_rxfrm_t rxfrm;
+ hfa384x_usb_txfrm_t txfrm;
+ hfa384x_usb_infofrm_t infofrm;
+ hfa384x_usb_cmdresp_t cmdresp;
+ hfa384x_usb_wridresp_t wridresp;
+ hfa384x_usb_rridresp_t rridresp;
+ hfa384x_usb_wmemresp_t wmemresp;
+ hfa384x_usb_rmemresp_t rmemresp;
+ hfa384x_usb_bufavail_t bufavail;
+ hfa384x_usb_error_t usberror;
+ UINT8 boguspad[3000];
+} __WLAN_ATTRIB_PACK__ hfa384x_usbin_t;
+
+#endif /* WLAN_USB */
+
+/*--------------------------------------------------------------------
+PD record structures.
+--------------------------------------------------------------------*/
+
+typedef struct hfa384x_pdr_pcb_partnum
+{
+ UINT8 num[8];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_partnum_t;
+
+typedef struct hfa384x_pdr_pcb_tracenum
+{
+ UINT8 num[8];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_tracenum_t;
+
+typedef struct hfa384x_pdr_nic_serial
+{
+ UINT8 num[12];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_serial_t;
+
+typedef struct hfa384x_pdr_mkk_measurements
+{
+ double carrier_freq;
+ double occupied_band;
+ double power_density;
+ double tx_spur_f1;
+ double tx_spur_f2;
+ double tx_spur_f3;
+ double tx_spur_f4;
+ double tx_spur_l1;
+ double tx_spur_l2;
+ double tx_spur_l3;
+ double tx_spur_l4;
+ double rx_spur_f1;
+ double rx_spur_f2;
+ double rx_spur_l1;
+ double rx_spur_l2;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mkk_measurements_t;
+
+typedef struct hfa384x_pdr_nic_ramsize
+{
+ UINT8 size[12]; /* units of KB */
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_ramsize_t;
+
+typedef struct hfa384x_pdr_mfisuprange
+{
+ UINT16 id;
+ UINT16 variant;
+ UINT16 bottom;
+ UINT16 top;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mfisuprange_t;
+
+typedef struct hfa384x_pdr_cfisuprange
+{
+ UINT16 id;
+ UINT16 variant;
+ UINT16 bottom;
+ UINT16 top;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_cfisuprange_t;
+
+typedef struct hfa384x_pdr_nicid
+{
+ UINT16 id;
+ UINT16 variant;
+ UINT16 major;
+ UINT16 minor;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nicid_t;
+
+
+typedef struct hfa384x_pdr_refdac_measurements
+{
+ UINT16 value[0];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_measurements_t;
+
+typedef struct hfa384x_pdr_vgdac_measurements
+{
+ UINT16 value[0];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_measurements_t;
+
+typedef struct hfa384x_pdr_level_comp_measurements
+{
+ UINT16 value[0];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_compc_measurements_t;
+
+typedef struct hfa384x_pdr_mac_address
+{
+ UINT8 addr[6];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mac_address_t;
+
+typedef struct hfa384x_pdr_mkk_callname
+{
+ UINT8 callname[8];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mkk_callname_t;
+
+typedef struct hfa384x_pdr_regdomain
+{
+ UINT16 numdomains;
+ UINT16 domain[5];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_regdomain_t;
+
+typedef struct hfa384x_pdr_allowed_channel
+{
+ UINT16 ch_bitmap;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_allowed_channel_t;
+
+typedef struct hfa384x_pdr_default_channel
+{
+ UINT16 channel;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_default_channel_t;
+
+typedef struct hfa384x_pdr_privacy_option
+{
+ UINT16 available;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_privacy_option_t;
+
+typedef struct hfa384x_pdr_temptype
+{
+ UINT16 type;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_temptype_t;
+
+typedef struct hfa384x_pdr_refdac_setup
+{
+ UINT16 ch_value[14];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_setup_t;
+
+typedef struct hfa384x_pdr_vgdac_setup
+{
+ UINT16 ch_value[14];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_setup_t;
+
+typedef struct hfa384x_pdr_level_comp_setup
+{
+ UINT16 ch_value[14];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_comp_setup_t;
+
+typedef struct hfa384x_pdr_trimdac_setup
+{
+ UINT16 trimidac;
+ UINT16 trimqdac;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_trimdac_setup_t;
+
+typedef struct hfa384x_pdr_ifr_setting
+{
+ UINT16 value[3];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_ifr_setting_t;
+
+typedef struct hfa384x_pdr_rfr_setting
+{
+ UINT16 value[3];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_rfr_setting_t;
+
+typedef struct hfa384x_pdr_hfa3861_baseline
+{
+ UINT16 value[50];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_baseline_t;
+
+typedef struct hfa384x_pdr_hfa3861_shadow
+{
+ UINT32 value[32];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_shadow_t;
+
+typedef struct hfa384x_pdr_hfa3861_ifrf
+{
+ UINT32 value[20];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_ifrf_t;
+
+typedef struct hfa384x_pdr_hfa3861_chcalsp
+{
+ UINT16 value[14];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcalsp_t;
+
+typedef struct hfa384x_pdr_hfa3861_chcali
+{
+ UINT16 value[17];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcali_t;
+
+typedef struct hfa384x_pdr_hfa3861_nic_config
+{
+ UINT16 config_bitmap;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_config_t;
+
+typedef struct hfa384x_pdr_hfo_delay
+{
+ UINT8 hfo_delay;
+} __WLAN_ATTRIB_PACK__ hfa384x_hfo_delay_t;
+
+typedef struct hfa384x_pdr_hfa3861_manf_testsp
+{
+ UINT16 value[30];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testsp_t;
+
+typedef struct hfa384x_pdr_hfa3861_manf_testi
+{
+ UINT16 value[30];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testi_t;
+
+typedef struct hfa384x_end_of_pda
+{
+ UINT16 crc;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_end_of_pda_t;
+
+typedef struct hfa384x_pdrec
+{
+ UINT16 len; /* in words */
+ UINT16 code;
+ union pdr {
+ hfa384x_pdr_pcb_partnum_t pcb_partnum;
+ hfa384x_pdr_pcb_tracenum_t pcb_tracenum;
+ hfa384x_pdr_nic_serial_t nic_serial;
+ hfa384x_pdr_mkk_measurements_t mkk_measurements;
+ hfa384x_pdr_nic_ramsize_t nic_ramsize;
+ hfa384x_pdr_mfisuprange_t mfisuprange;
+ hfa384x_pdr_cfisuprange_t cfisuprange;
+ hfa384x_pdr_nicid_t nicid;
+ hfa384x_pdr_refdac_measurements_t refdac_measurements;
+ hfa384x_pdr_vgdac_measurements_t vgdac_measurements;
+ hfa384x_pdr_level_compc_measurements_t level_compc_measurements;
+ hfa384x_pdr_mac_address_t mac_address;
+ hfa384x_pdr_mkk_callname_t mkk_callname;
+ hfa384x_pdr_regdomain_t regdomain;
+ hfa384x_pdr_allowed_channel_t allowed_channel;
+ hfa384x_pdr_default_channel_t default_channel;
+ hfa384x_pdr_privacy_option_t privacy_option;
+ hfa384x_pdr_temptype_t temptype;
+ hfa384x_pdr_refdac_setup_t refdac_setup;
+ hfa384x_pdr_vgdac_setup_t vgdac_setup;
+ hfa384x_pdr_level_comp_setup_t level_comp_setup;
+ hfa384x_pdr_trimdac_setup_t trimdac_setup;
+ hfa384x_pdr_ifr_setting_t ifr_setting;
+ hfa384x_pdr_rfr_setting_t rfr_setting;
+ hfa384x_pdr_hfa3861_baseline_t hfa3861_baseline;
+ hfa384x_pdr_hfa3861_shadow_t hfa3861_shadow;
+ hfa384x_pdr_hfa3861_ifrf_t hfa3861_ifrf;
+ hfa384x_pdr_hfa3861_chcalsp_t hfa3861_chcalsp;
+ hfa384x_pdr_hfa3861_chcali_t hfa3861_chcali;
+ hfa384x_pdr_nic_config_t nic_config;
+ hfa384x_hfo_delay_t hfo_delay;
+ hfa384x_pdr_hfa3861_manf_testsp_t hfa3861_manf_testsp;
+ hfa384x_pdr_hfa3861_manf_testi_t hfa3861_manf_testi;
+ hfa384x_pdr_end_of_pda_t end_of_pda;
+
+ } data;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdrec_t;
+
+
+#ifdef __KERNEL__
+/*--------------------------------------------------------------------
+--- MAC state structure, argument to all functions --
+--- Also, a collection of support types --
+--------------------------------------------------------------------*/
+typedef struct hfa384x_statusresult
+{
+ UINT16 status;
+ UINT16 resp0;
+ UINT16 resp1;
+ UINT16 resp2;
+} hfa384x_cmdresult_t;
+
+#if (WLAN_HOSTIF == WLAN_USB)
+
+/* USB Control Exchange (CTLX):
+ * A queue of the structure below is maintained for all of the
+ * Request/Response type USB packets supported by Prism2.
+ */
+/* The following hfa384x_* structures are arguments to
+ * the usercb() for the different CTLX types.
+ */
+typedef hfa384x_cmdresult_t hfa384x_wridresult_t;
+typedef hfa384x_cmdresult_t hfa384x_wmemresult_t;
+
+typedef struct hfa384x_rridresult
+{
+ UINT16 rid;
+ const void *riddata;
+ UINT riddata_len;
+} hfa384x_rridresult_t;
+
+enum ctlx_state {
+ CTLX_START = 0, /* Start state, not queued */
+
+ CTLX_COMPLETE, /* CTLX successfully completed */
+ CTLX_REQ_FAILED, /* OUT URB completed w/ error */
+
+ CTLX_PENDING, /* Queued, data valid */
+ CTLX_REQ_SUBMITTED, /* OUT URB submitted */
+ CTLX_REQ_COMPLETE, /* OUT URB complete */
+ CTLX_RESP_COMPLETE /* IN URB received */
+};
+typedef enum ctlx_state CTLX_STATE;
+
+struct hfa384x_usbctlx;
+struct hfa384x;
+
+typedef void (*ctlx_cmdcb_t)( struct hfa384x*, const struct hfa384x_usbctlx* );
+
+typedef void (*ctlx_usercb_t)(
+ struct hfa384x *hw,
+ void *ctlxresult,
+ void *usercb_data);
+
+typedef struct hfa384x_usbctlx
+{
+ struct list_head list;
+
+ size_t outbufsize;
+ hfa384x_usbout_t outbuf; /* pkt buf for OUT */
+ hfa384x_usbin_t inbuf; /* pkt buf for IN(a copy) */
+
+ CTLX_STATE state; /* Tracks running state */
+
+ struct completion done;
+ volatile int reapable; /* Food for the reaper task */
+
+ ctlx_cmdcb_t cmdcb; /* Async command callback */
+ ctlx_usercb_t usercb; /* Async user callback, */
+ void *usercb_data; /* at CTLX completion */
+
+ int variant; /* Identifies cmd variant */
+} hfa384x_usbctlx_t;
+
+typedef struct hfa384x_usbctlxq
+{
+ spinlock_t lock;
+ struct list_head pending;
+ struct list_head active;
+ struct list_head completing;
+ struct list_head reapable;
+} hfa384x_usbctlxq_t;
+#endif
+
+typedef struct hfa484x_metacmd
+{
+ UINT16 cmd;
+
+ UINT16 parm0;
+ UINT16 parm1;
+ UINT16 parm2;
+
+#if 0 //XXX cmd irq stuff
+ UINT16 bulkid; /* what RID/FID to copy down. */
+ int bulklen; /* how much to copy from BAP */
+ char *bulkdata; /* And to where? */
+#endif
+
+ hfa384x_cmdresult_t result;
+} hfa384x_metacmd_t;
+
+#define MAX_PRISM2_GRP_ADDR 16
+#define MAX_GRP_ADDR 32
+#define WLAN_COMMENT_MAX 80 /* Max. length of user comment string. */
+
+#define MM_SAT_PCF (BIT14)
+#define MM_GCSD_PCF (BIT15)
+#define MM_GCSD_PCF_EB (BIT14 | BIT15)
+
+#define WLAN_STATE_STOPPED 0 /* Network is not active. */
+#define WLAN_STATE_STARTED 1 /* Network has been started. */
+
+#define WLAN_AUTH_MAX 60 /* Max. # of authenticated stations. */
+#define WLAN_ACCESS_MAX 60 /* Max. # of stations in an access list. */
+#define WLAN_ACCESS_NONE 0 /* No stations may be authenticated. */
+#define WLAN_ACCESS_ALL 1 /* All stations may be authenticated. */
+#define WLAN_ACCESS_ALLOW 2 /* Authenticate only "allowed" stations. */
+#define WLAN_ACCESS_DENY 3 /* Do not authenticate "denied" stations. */
+
+/* XXX These are going away ASAP */
+typedef struct prism2sta_authlist
+{
+ UINT cnt;
+ UINT8 addr[WLAN_AUTH_MAX][WLAN_ADDR_LEN];
+ UINT8 assoc[WLAN_AUTH_MAX];
+} prism2sta_authlist_t;
+
+typedef struct prism2sta_accesslist
+{
+ UINT modify;
+ UINT cnt;
+ UINT8 addr[WLAN_ACCESS_MAX][WLAN_ADDR_LEN];
+ UINT cnt1;
+ UINT8 addr1[WLAN_ACCESS_MAX][WLAN_ADDR_LEN];
+} prism2sta_accesslist_t;
+
+typedef struct hfa384x
+{
+#if (WLAN_HOSTIF != WLAN_USB)
+ /* Resource config */
+ UINT32 iobase;
+ char __iomem *membase;
+ UINT32 irq;
+#else
+ /* USB support data */
+ struct usb_device *usb;
+ struct urb rx_urb;
+ struct sk_buff *rx_urb_skb;
+ struct urb tx_urb;
+ struct urb ctlx_urb;
+ hfa384x_usbout_t txbuff;
+ hfa384x_usbctlxq_t ctlxq;
+ struct timer_list reqtimer;
+ struct timer_list resptimer;
+
+ struct timer_list throttle;
+
+ struct tasklet_struct reaper_bh;
+ struct tasklet_struct completion_bh;
+
+ struct work_struct usb_work;
+
+ unsigned long usb_flags;
+#define THROTTLE_RX 0
+#define THROTTLE_TX 1
+#define WORK_RX_HALT 2
+#define WORK_TX_HALT 3
+#define WORK_RX_RESUME 4
+#define WORK_TX_RESUME 5
+
+ unsigned short req_timer_done:1;
+ unsigned short resp_timer_done:1;
+
+ int endp_in;
+ int endp_out;
+#endif /* !USB */
+
+#if (WLAN_HOSTIF == WLAN_PCMCIA)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ struct pcmcia_device *pdev;
+#else
+ dev_link_t *link;
+#endif
+ dev_node_t node;
+#endif
+
+ int sniff_fcs;
+ int sniff_channel;
+ int sniff_truncate;
+ int sniffhdr;
+
+ wait_queue_head_t cmdq; /* wait queue itself */
+
+ /* Controller state */
+ UINT32 state;
+ UINT32 isap;
+ UINT8 port_enabled[HFA384x_NUMPORTS_MAX];
+#if (WLAN_HOSTIF != WLAN_USB)
+ UINT auxen;
+ UINT isram16;
+#endif /* !USB */
+
+ /* Download support */
+ UINT dlstate;
+ hfa384x_downloadbuffer_t bufinfo;
+ UINT16 dltimeout;
+
+#if (WLAN_HOSTIF != WLAN_USB)
+ spinlock_t cmdlock;
+ volatile int cmdflag; /* wait queue flag */
+ hfa384x_metacmd_t *cmddata; /* for our async callback */
+
+ /* BAP support */
+ spinlock_t baplock;
+ struct tasklet_struct bap_tasklet;
+
+ /* MAC buffer ids */
+ UINT16 txfid_head;
+ UINT16 txfid_tail;
+ UINT txfid_N;
+ UINT16 txfid_queue[HFA384x_DRVR_FIDSTACKLEN_MAX];
+ UINT16 infofid;
+ struct semaphore infofid_sem;
+#endif /* !USB */
+
+ int scanflag; /* to signal scan comlete */
+ int join_ap; /* are we joined to a specific ap */
+ int join_retries; /* number of join retries till we fail */
+ hfa384x_JoinRequest_data_t joinreq; /* join request saved data */
+
+ wlandevice_t *wlandev;
+ /* Timer to allow for the deferred processing of linkstatus messages */
+ struct work_struct link_bh;
+
+ struct work_struct commsqual_bh;
+ hfa384x_commsquality_t qual;
+ struct timer_list commsqual_timer;
+
+ UINT16 link_status;
+ UINT16 link_status_new;
+ struct sk_buff_head authq;
+
+ /* And here we have stuff that used to be in priv */
+
+ /* State variables */
+ UINT presniff_port_type;
+ UINT16 presniff_wepflags;
+ UINT32 dot11_desired_bss_type;
+ int ap; /* AP flag: 0 - Station, 1 - Access Point. */
+
+ int dbmadjust;
+
+ /* Group Addresses - right now, there are up to a total
+ of MAX_GRP_ADDR group addresses */
+ UINT8 dot11_grp_addr[MAX_GRP_ADDR][WLAN_ADDR_LEN];
+ UINT dot11_grpcnt;
+
+ /* Component Identities */
+ hfa384x_compident_t ident_nic;
+ hfa384x_compident_t ident_pri_fw;
+ hfa384x_compident_t ident_sta_fw;
+ hfa384x_compident_t ident_ap_fw;
+ UINT16 mm_mods;
+
+ /* Supplier compatibility ranges */
+ hfa384x_caplevel_t cap_sup_mfi;
+ hfa384x_caplevel_t cap_sup_cfi;
+ hfa384x_caplevel_t cap_sup_pri;
+ hfa384x_caplevel_t cap_sup_sta;
+ hfa384x_caplevel_t cap_sup_ap;
+
+ /* Actor compatibility ranges */
+ hfa384x_caplevel_t cap_act_pri_cfi; /* pri f/w to controller interface */
+ hfa384x_caplevel_t cap_act_sta_cfi; /* sta f/w to controller interface */
+ hfa384x_caplevel_t cap_act_sta_mfi; /* sta f/w to modem interface */
+ hfa384x_caplevel_t cap_act_ap_cfi; /* ap f/w to controller interface */
+ hfa384x_caplevel_t cap_act_ap_mfi; /* ap f/w to modem interface */
+
+ UINT32 psusercount; /* Power save user count. */
+ hfa384x_CommTallies32_t tallies; /* Communication tallies. */
+ UINT8 comment[WLAN_COMMENT_MAX+1]; /* User comment */
+
+ /* Channel Info request results (AP only) */
+ struct {
+ atomic_t done;
+ UINT8 count;
+ hfa384x_ChInfoResult_t results;
+ } channel_info;
+
+ hfa384x_InfFrame_t *scanresults;
+
+
+ prism2sta_authlist_t authlist; /* Authenticated station list. */
+ UINT accessmode; /* Access mode. */
+ prism2sta_accesslist_t allow; /* Allowed station list. */
+ prism2sta_accesslist_t deny; /* Denied station list. */
+
+} hfa384x_t;
+
+/*=============================================================*/
+/*--- Function Declarations -----------------------------------*/
+/*=============================================================*/
+#if (WLAN_HOSTIF == WLAN_USB)
+void
+hfa384x_create(
+ hfa384x_t *hw,
+ struct usb_device *usb);
+#else
+void
+hfa384x_create(
+ hfa384x_t *hw,
+ UINT irq,
+ UINT32 iobase,
+ UINT8 __iomem *membase);
+#endif
+
+void hfa384x_destroy(hfa384x_t *hw);
+
+irqreturn_t
+hfa384x_interrupt(int irq, void *dev_id PT_REGS);
+int
+hfa384x_corereset( hfa384x_t *hw, int holdtime, int settletime, int genesis);
+int
+hfa384x_drvr_chinforesults( hfa384x_t *hw);
+int
+hfa384x_drvr_commtallies( hfa384x_t *hw);
+int
+hfa384x_drvr_disable(hfa384x_t *hw, UINT16 macport);
+int
+hfa384x_drvr_enable(hfa384x_t *hw, UINT16 macport);
+int
+hfa384x_drvr_flashdl_enable(hfa384x_t *hw);
+int
+hfa384x_drvr_flashdl_disable(hfa384x_t *hw);
+int
+hfa384x_drvr_flashdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len);
+int
+hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len);
+int
+hfa384x_drvr_handover( hfa384x_t *hw, UINT8 *addr);
+int
+hfa384x_drvr_hostscanresults( hfa384x_t *hw);
+int
+hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd);
+int
+hfa384x_drvr_mmi_read(hfa384x_t *hw, UINT32 address, UINT32 *result);
+int
+hfa384x_drvr_mmi_write(hfa384x_t *hw, UINT32 address, UINT32 data);
+int
+hfa384x_drvr_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr);
+int
+hfa384x_drvr_ramdl_disable(hfa384x_t *hw);
+int
+hfa384x_drvr_ramdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len);
+int
+hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len);
+int
+hfa384x_drvr_scanresults( hfa384x_t *hw);
+
+int
+hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len);
+
+static inline int
+hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val)
+{
+ int result = 0;
+ result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16));
+ if ( result == 0 ) {
+ *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val));
+ }
+ return result;
+}
+
+static inline int
+hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val)
+{
+ int result = 0;
+
+ result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32));
+ if ( result == 0 ) {
+ *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val));
+ }
+
+ return result;
+}
+
+static inline int
+hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 val)
+{
+ UINT16 value = host2hfa384x_16(val);
+ return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value));
+}
+
+static inline int
+hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 val)
+{
+ UINT32 value = host2hfa384x_32(val);
+ return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value));
+}
+
+#if (WLAN_HOSTIF == WLAN_USB)
+int
+hfa384x_drvr_getconfig_async(hfa384x_t *hw,
+ UINT16 rid,
+ ctlx_usercb_t usercb,
+ void *usercb_data);
+
+int
+hfa384x_drvr_setconfig_async(hfa384x_t *hw,
+ UINT16 rid,
+ void *buf,
+ UINT16 len,
+ ctlx_usercb_t usercb,
+ void *usercb_data);
+#else
+static inline int
+hfa384x_drvr_setconfig_async(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len,
+ void *ptr1, void *ptr2)
+{
+ (void)ptr1;
+ (void)ptr2;
+ return hfa384x_drvr_setconfig(hw, rid, buf, len);
+}
+#endif
+
+static inline int
+hfa384x_drvr_setconfig16_async(hfa384x_t *hw, UINT16 rid, UINT16 val)
+{
+ UINT16 value = host2hfa384x_16(val);
+ return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value),
+ NULL , NULL);
+}
+
+static inline int
+hfa384x_drvr_setconfig32_async(hfa384x_t *hw, UINT16 rid, UINT32 val)
+{
+ UINT32 value = host2hfa384x_32(val);
+ return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value),
+ NULL , NULL);
+}
+
+
+int
+hfa384x_drvr_start(hfa384x_t *hw);
+int
+hfa384x_drvr_stop(hfa384x_t *hw);
+int
+hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep);
+void
+hfa384x_tx_timeout(wlandevice_t *wlandev);
+
+int
+hfa384x_cmd_initialize(hfa384x_t *hw);
+int
+hfa384x_cmd_enable(hfa384x_t *hw, UINT16 macport);
+int
+hfa384x_cmd_disable(hfa384x_t *hw, UINT16 macport);
+int
+hfa384x_cmd_diagnose(hfa384x_t *hw);
+int
+hfa384x_cmd_allocate(hfa384x_t *hw, UINT16 len);
+int
+hfa384x_cmd_transmit(hfa384x_t *hw, UINT16 reclaim, UINT16 qos, UINT16 fid);
+int
+hfa384x_cmd_clearpersist(hfa384x_t *hw, UINT16 fid);
+int
+hfa384x_cmd_notify(hfa384x_t *hw, UINT16 reclaim, UINT16 fid, void *buf, UINT16 len);
+int
+hfa384x_cmd_inquire(hfa384x_t *hw, UINT16 fid);
+int
+hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid, void *buf, UINT16 len);
+int
+hfa384x_cmd_monitor(hfa384x_t *hw, UINT16 enable);
+int
+hfa384x_cmd_download(
+ hfa384x_t *hw,
+ UINT16 mode,
+ UINT16 lowaddr,
+ UINT16 highaddr,
+ UINT16 codelen);
+int
+hfa384x_cmd_aux_enable(hfa384x_t *hw, int force);
+int
+hfa384x_cmd_aux_disable(hfa384x_t *hw);
+int
+hfa384x_copy_from_bap(
+ hfa384x_t *hw,
+ UINT16 bap,
+ UINT16 id,
+ UINT16 offset,
+ void *buf,
+ UINT len);
+int
+hfa384x_copy_to_bap(
+ hfa384x_t *hw,
+ UINT16 bap,
+ UINT16 id,
+ UINT16 offset,
+ void *buf,
+ UINT len);
+void
+hfa384x_copy_from_aux(
+ hfa384x_t *hw,
+ UINT32 cardaddr,
+ UINT32 auxctl,
+ void *buf,
+ UINT len);
+void
+hfa384x_copy_to_aux(
+ hfa384x_t *hw,
+ UINT32 cardaddr,
+ UINT32 auxctl,
+ void *buf,
+ UINT len);
+
+#if (WLAN_HOSTIF != WLAN_USB)
+
+/*
+ HFA384x is a LITTLE ENDIAN part.
+
+ the get/setreg functions implicitly byte-swap the data to LE.
+ the _noswap variants do not perform a byte-swap on the data.
+*/
+
+static inline UINT16
+__hfa384x_getreg(hfa384x_t *hw, UINT reg);
+
+static inline void
+__hfa384x_setreg(hfa384x_t *hw, UINT16 val, UINT reg);
+
+static inline UINT16
+__hfa384x_getreg_noswap(hfa384x_t *hw, UINT reg);
+
+static inline void
+__hfa384x_setreg_noswap(hfa384x_t *hw, UINT16 val, UINT reg);
+
+#ifdef REVERSE_ENDIAN
+#define hfa384x_getreg __hfa384x_getreg_noswap
+#define hfa384x_setreg __hfa384x_setreg_noswap
+#define hfa384x_getreg_noswap __hfa384x_getreg
+#define hfa384x_setreg_noswap __hfa384x_setreg
+#else
+#define hfa384x_getreg __hfa384x_getreg
+#define hfa384x_setreg __hfa384x_setreg
+#define hfa384x_getreg_noswap __hfa384x_getreg_noswap
+#define hfa384x_setreg_noswap __hfa384x_setreg_noswap
+#endif
+
+/*----------------------------------------------------------------
+* hfa384x_getreg
+*
+* Retrieve the value of one of the MAC registers. Done here
+* because different PRISM2 MAC parts use different buses and such.
+* NOTE: This function returns the value in HOST ORDER!!!!!!
+*
+* Arguments:
+* hw MAC part structure
+* reg Register identifier (offset for I/O based i/f)
+*
+* Returns:
+* Value from the register in HOST ORDER!!!!
+----------------------------------------------------------------*/
+static inline UINT16
+__hfa384x_getreg(hfa384x_t *hw, UINT reg)
+{
+/* printk(KERN_DEBUG "Reading from 0x%0x\n", hw->membase + reg); */
+#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX))
+ return wlan_inw_le16_to_cpu(hw->iobase+reg);
+#elif (WLAN_HOSTIF == WLAN_PCI)
+ return __le16_to_cpu(readw(hw->membase + reg));
+#endif
+}
+
+/*----------------------------------------------------------------
+* hfa384x_setreg
+*
+* Set the value of one of the MAC registers. Done here
+* because different PRISM2 MAC parts use different buses and such.
+* NOTE: This function assumes the value is in HOST ORDER!!!!!!
+*
+* Arguments:
+* hw MAC part structure
+* val Value, in HOST ORDER!!, to put in the register
+* reg Register identifier (offset for I/O based i/f)
+*
+* Returns:
+* Nothing
+----------------------------------------------------------------*/
+static inline void
+__hfa384x_setreg(hfa384x_t *hw, UINT16 val, UINT reg)
+{
+#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX))
+ wlan_outw_cpu_to_le16( val, hw->iobase + reg);
+ return;
+#elif (WLAN_HOSTIF == WLAN_PCI)
+ writew(__cpu_to_le16(val), hw->membase + reg);
+ return;
+#endif
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_getreg_noswap
+*
+* Retrieve the value of one of the MAC registers. Done here
+* because different PRISM2 MAC parts use different buses and such.
+*
+* Arguments:
+* hw MAC part structure
+* reg Register identifier (offset for I/O based i/f)
+*
+* Returns:
+* Value from the register.
+----------------------------------------------------------------*/
+static inline UINT16
+__hfa384x_getreg_noswap(hfa384x_t *hw, UINT reg)
+{
+#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX))
+ return wlan_inw(hw->iobase+reg);
+#elif (WLAN_HOSTIF == WLAN_PCI)
+ return readw(hw->membase + reg);
+#endif
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_setreg_noswap
+*
+* Set the value of one of the MAC registers. Done here
+* because different PRISM2 MAC parts use different buses and such.
+*
+* Arguments:
+* hw MAC part structure
+* val Value to put in the register
+* reg Register identifier (offset for I/O based i/f)
+*
+* Returns:
+* Nothing
+----------------------------------------------------------------*/
+static inline void
+__hfa384x_setreg_noswap(hfa384x_t *hw, UINT16 val, UINT reg)
+{
+#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX))
+ wlan_outw( val, hw->iobase + reg);
+ return;
+#elif (WLAN_HOSTIF == WLAN_PCI)
+ writew(val, hw->membase + reg);
+ return;
+#endif
+}
+
+
+static inline void hfa384x_events_all(hfa384x_t *hw)
+{
+ hfa384x_setreg(hw,
+ HFA384x_INT_NORMAL
+#ifdef CMD_IRQ
+ | HFA384x_INTEN_CMD_SET(1)
+#endif
+ ,
+ HFA384x_INTEN);
+
+}
+
+static inline void hfa384x_events_nobap(hfa384x_t *hw)
+{
+ hfa384x_setreg(hw,
+ (HFA384x_INT_NORMAL & ~HFA384x_INT_BAP_OP)
+#ifdef CMD_IRQ
+ | HFA384x_INTEN_CMD_SET(1)
+#endif
+ ,
+ HFA384x_INTEN);
+
+}
+
+#endif /* WLAN_HOSTIF != WLAN_USB */
+#endif /* __KERNEL__ */
+
+#endif /* _HFA384x_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf.h
new file mode 100644
index 00000000..74f99c61
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf.h
@@ -0,0 +1,377 @@
+/*******************************************************************************
+
+ Intel(R) 82576 Virtual Function Linux driver
+ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/* Linux PRO/1000 Ethernet Driver main header file */
+
+#ifndef _IGBVF_H_
+#define _IGBVF_H_
+
+#include "igbvf_vf.h"
+
+/* Forward declarations */
+struct igbvf_info;
+struct igbvf_adapter;
+
+/* Interrupt defines */
+#define IGBVF_START_ITR 648 /* ~6000 ints/sec */
+
+/* Tx/Rx descriptor defines */
+#define IGBVF_DEFAULT_TXD 256
+#define IGBVF_MAX_TXD 4096
+#define IGBVF_MIN_TXD 80
+
+#define IGBVF_DEFAULT_RXD 256
+#define IGBVF_MAX_RXD 4096
+#define IGBVF_MIN_RXD 80
+
+#define IGBVF_MIN_ITR_USECS 10 /* 100000 irq/sec */
+#define IGBVF_MAX_ITR_USECS 10000 /* 100 irq/sec */
+
+/* RX descriptor control thresholds.
+ * PTHRESH - MAC will consider prefetch if it has fewer than this number of
+ * descriptors available in its onboard memory.
+ * Setting this to 0 disables RX descriptor prefetch.
+ * HTHRESH - MAC will only prefetch if there are at least this many descriptors
+ * available in host memory.
+ * If PTHRESH is 0, this should also be 0.
+ * WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
+ * descriptors until either it has this many to write back, or the
+ * ITR timer expires.
+ */
+#define IGBVF_RX_PTHRESH 16
+#define IGBVF_RX_HTHRESH 8
+#define IGBVF_RX_WTHRESH 1
+
+#define IGBVF_TX_PTHRESH 8
+#define IGBVF_TX_HTHRESH 1
+#define IGBVF_TX_WTHRESH 1
+
+/* this is the size past which hardware will drop packets when setting LPE=0 */
+#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
+
+#define IGBVF_FC_PAUSE_TIME 0x0680 /* 858 usec */
+
+/* How many Tx Descriptors do we need to call netif_wake_queue ? */
+#define IGBVF_TX_QUEUE_WAKE 32
+/* How many Rx Buffers do we bundle into one write to the hardware ? */
+#define IGBVF_RX_BUFFER_WRITE 16 /* Must be power of 2 */
+
+#define AUTO_ALL_MODES 0
+#define IGBVF_EEPROM_APME 0x0400
+
+#define IGBVF_MNG_VLAN_NONE (-1)
+
+enum igbvf_boards {
+ board_vf,
+};
+
+struct igbvf_queue_stats {
+ u64 packets;
+ u64 bytes;
+};
+
+/*
+ * wrappers around a pointer to a socket buffer,
+ * so a DMA handle can be stored along with the buffer
+ */
+struct igbvf_buffer {
+#if 0
+ dma_addr_t dma;
+ dma_addr_t page_dma;
+ struct sk_buff *skb;
+ union {
+ /* Tx */
+ struct {
+ unsigned long time_stamp;
+ u16 length;
+ u16 next_to_watch;
+ };
+ /* Rx */
+ struct {
+ struct page *page;
+ unsigned int page_offset;
+ };
+ };
+ struct page *page;
+#endif
+};
+
+struct igbvf_ring {
+#if 0
+ struct igbvf_adapter *adapter; /* backlink */
+ void *desc; /* pointer to ring memory */
+ dma_addr_t dma; /* phys address of ring */
+ unsigned int size; /* length of ring in bytes */
+ unsigned int count; /* number of desc. in ring */
+
+ u16 next_to_use;
+ u16 next_to_clean;
+
+ u16 head;
+ u16 tail;
+
+ /* array of buffer information structs */
+ struct igbvf_buffer *buffer_info;
+ struct napi_struct napi;
+
+ char name[IFNAMSIZ + 5];
+ u32 eims_value;
+ u32 itr_val;
+ u16 itr_register;
+ int set_itr;
+
+ struct sk_buff *rx_skb_top;
+
+ struct igbvf_queue_stats stats;
+#endif
+};
+
+/* board specific private data structure */
+struct igbvf_adapter {
+#if 0
+ struct timer_list watchdog_timer;
+ struct timer_list blink_timer;
+
+ struct work_struct reset_task;
+ struct work_struct watchdog_task;
+
+ const struct igbvf_info *ei;
+
+ struct vlan_group *vlgrp;
+ u32 bd_number;
+ u32 rx_buffer_len;
+ u32 polling_interval;
+ u16 mng_vlan_id;
+ u16 link_speed;
+ u16 link_duplex;
+
+ spinlock_t tx_queue_lock; /* prevent concurrent tail updates */
+
+ /* track device up/down/testing state */
+ unsigned long state;
+
+ /* Interrupt Throttle Rate */
+ u32 itr;
+ u32 itr_setting;
+ u16 tx_itr;
+ u16 rx_itr;
+
+ /*
+ * Tx
+ */
+ struct igbvf_ring *tx_ring /* One per active queue */
+ ____cacheline_aligned_in_smp;
+
+ unsigned long tx_queue_len;
+ unsigned int restart_queue;
+ u32 txd_cmd;
+
+ bool detect_tx_hung;
+ u8 tx_timeout_factor;
+
+ unsigned int total_tx_bytes;
+ unsigned int total_tx_packets;
+ unsigned int total_rx_bytes;
+ unsigned int total_rx_packets;
+
+ /* Tx stats */
+ u32 tx_timeout_count;
+ u32 tx_fifo_head;
+ u32 tx_head_addr;
+ u32 tx_fifo_size;
+ u32 tx_dma_failed;
+
+ /*
+ * Rx
+ */
+ struct igbvf_ring *rx_ring;
+
+ /* Rx stats */
+ u64 hw_csum_err;
+ u64 hw_csum_good;
+ u64 rx_hdr_split;
+ u32 alloc_rx_buff_failed;
+ u32 rx_dma_failed;
+
+ unsigned int rx_ps_hdr_size;
+ u32 max_frame_size;
+ u32 min_frame_size;
+
+ /* OS defined structs */
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ struct net_device_stats net_stats;
+ spinlock_t stats_lock; /* prevent concurrent stats updates */
+
+ /* structs defined in e1000_hw.h */
+ struct e1000_hw hw;
+
+ /* The VF counters don't clear on read so we have to get a base
+ * count on driver start up and always subtract that base on
+ * on the first update, thus the flag..
+ */
+ struct e1000_vf_stats stats;
+ u64 zero_base;
+
+ struct igbvf_ring test_tx_ring;
+ struct igbvf_ring test_rx_ring;
+ u32 test_icr;
+
+ u32 msg_enable;
+ struct msix_entry *msix_entries;
+ int int_mode;
+ u32 eims_enable_mask;
+ u32 eims_other;
+ u32 int_counter0;
+ u32 int_counter1;
+
+ u32 eeprom_wol;
+ u32 wol;
+ u32 pba;
+
+ bool fc_autoneg;
+
+ unsigned long led_status;
+
+ unsigned int flags;
+ unsigned long last_reset;
+ u32 *config_space;
+#endif
+ /* OS defined structs */
+ struct net_device *netdev;
+ struct pci_device *pdev;
+ struct net_device_stats net_stats;
+
+ /* structs defined in e1000_hw.h */
+ struct e1000_hw hw;
+
+ u32 min_frame_size;
+ u32 max_frame_size;
+
+ u32 max_hw_frame_size;
+
+#define NUM_TX_DESC 8
+#define NUM_RX_DESC 8
+
+ struct io_buffer *tx_iobuf[NUM_TX_DESC];
+ struct io_buffer *rx_iobuf[NUM_RX_DESC];
+
+ union e1000_adv_tx_desc *tx_base;
+ union e1000_adv_rx_desc *rx_base;
+
+ uint32_t tx_ring_size;
+ uint32_t rx_ring_size;
+
+ uint32_t tx_head;
+ uint32_t tx_tail;
+ uint32_t tx_fill_ctr;
+
+ uint32_t rx_curr;
+
+ uint32_t ioaddr;
+ uint32_t irqno;
+
+ uint32_t tx_int_delay;
+ uint32_t tx_abs_int_delay;
+ uint32_t txd_cmd;
+};
+
+struct igbvf_info {
+ enum e1000_mac_type mac;
+ unsigned int flags;
+ u32 pba;
+ void (*init_ops)(struct e1000_hw *);
+ s32 (*get_variants)(struct igbvf_adapter *);
+};
+
+/* hardware capability, feature, and workaround flags */
+#define IGBVF_FLAG_RX_CSUM_DISABLED (1 << 0)
+
+#define IGBVF_DESC_UNUSED(R) \
+ ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
+ (R)->next_to_clean - (R)->next_to_use - 1)
+
+#define IGBVF_RX_DESC_ADV(R, i) \
+ (&(((union e1000_adv_rx_desc *)((R).desc))[i]))
+#define IGBVF_TX_DESC_ADV(R, i) \
+ (&(((union e1000_adv_tx_desc *)((R).desc))[i]))
+#define IGBVF_TX_CTXTDESC_ADV(R, i) \
+ (&(((struct e1000_adv_tx_context_desc *)((R).desc))[i]))
+
+enum igbvf_state_t {
+ __IGBVF_TESTING,
+ __IGBVF_RESETTING,
+ __IGBVF_DOWN
+};
+
+enum latency_range {
+ lowest_latency = 0,
+ low_latency = 1,
+ bulk_latency = 2,
+ latency_invalid = 255
+};
+
+extern char igbvf_driver_name[];
+extern const char igbvf_driver_version[];
+
+extern void igbvf_check_options(struct igbvf_adapter *adapter);
+extern void igbvf_set_ethtool_ops(struct net_device *netdev);
+#ifdef ETHTOOL_OPS_COMPAT
+extern int ethtool_ioctl(struct ifreq *ifr);
+#endif
+
+extern int igbvf_up(struct igbvf_adapter *adapter);
+extern void igbvf_down(struct igbvf_adapter *adapter);
+extern void igbvf_reinit_locked(struct igbvf_adapter *adapter);
+extern void igbvf_reset(struct igbvf_adapter *adapter);
+extern int igbvf_setup_rx_resources(struct igbvf_adapter *adapter);
+extern int igbvf_setup_tx_resources(struct igbvf_adapter *adapter);
+extern void igbvf_free_rx_resources(struct igbvf_adapter *adapter);
+extern void igbvf_free_tx_resources(struct igbvf_adapter *adapter);
+extern void igbvf_update_stats(struct igbvf_adapter *adapter);
+extern void igbvf_set_interrupt_capability(struct igbvf_adapter *adapter);
+extern void igbvf_reset_interrupt_capability(struct igbvf_adapter *adapter);
+
+extern unsigned int copybreak;
+
+static inline u32 __er32(struct e1000_hw *hw, unsigned long reg)
+{
+ return readl(hw->hw_addr + reg);
+}
+
+static inline void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val)
+{
+ writel(val, hw->hw_addr + reg);
+}
+#define er32(reg) E1000_READ_REG(hw, E1000_##reg)
+#define ew32(reg,val) E1000_WRITE_REG(hw, E1000_##reg, (val))
+#define e1e_flush() er32(STATUS)
+
+#endif /* _IGBVF_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_defines.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_defines.h
new file mode 100644
index 00000000..7cf4ddb9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_defines.h
@@ -0,0 +1,1395 @@
+/*******************************************************************************
+
+ Intel(R) 82576 Virtual Function Linux driver
+ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#ifndef _IGBVF_DEFINES_H_
+#define _IGBVF_DEFINES_H_
+
+/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
+#define REQ_TX_DESCRIPTOR_MULTIPLE 8
+#define REQ_RX_DESCRIPTOR_MULTIPLE 8
+
+/* Definitions for power management and wakeup registers */
+/* Wake Up Control */
+#define E1000_WUC_APME 0x00000001 /* APM Enable */
+#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */
+#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */
+#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */
+#define E1000_WUC_LSCWE 0x00000010 /* Link Status wake up enable */
+#define E1000_WUC_LSCWO 0x00000020 /* Link Status wake up override */
+#define E1000_WUC_SPM 0x80000000 /* Enable SPM */
+#define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */
+
+/* Wake Up Filter Control */
+#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
+#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
+#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */
+#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
+#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */
+#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */
+#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */
+#define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */
+#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */
+#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */
+#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */
+#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */
+#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */
+#define E1000_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */
+#define E1000_WUFC_FLX_FILTERS 0x000F0000 /*Mask for the 4 flexible filters */
+
+/* Wake Up Status */
+#define E1000_WUS_LNKC E1000_WUFC_LNKC
+#define E1000_WUS_MAG E1000_WUFC_MAG
+#define E1000_WUS_EX E1000_WUFC_EX
+#define E1000_WUS_MC E1000_WUFC_MC
+#define E1000_WUS_BC E1000_WUFC_BC
+#define E1000_WUS_ARP E1000_WUFC_ARP
+#define E1000_WUS_IPV4 E1000_WUFC_IPV4
+#define E1000_WUS_IPV6 E1000_WUFC_IPV6
+#define E1000_WUS_FLX0 E1000_WUFC_FLX0
+#define E1000_WUS_FLX1 E1000_WUFC_FLX1
+#define E1000_WUS_FLX2 E1000_WUFC_FLX2
+#define E1000_WUS_FLX3 E1000_WUFC_FLX3
+#define E1000_WUS_FLX_FILTERS E1000_WUFC_FLX_FILTERS
+
+/* Wake Up Packet Length */
+#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */
+
+/* Four Flexible Filters are supported */
+#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4
+
+/* Each Flexible Filter is at most 128 (0x80) bytes in length */
+#define E1000_FLEXIBLE_FILTER_SIZE_MAX 128
+
+#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX
+#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
+#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
+
+/* Extended Device Control */
+#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */
+#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */
+#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN
+#define E1000_CTRL_EXT_GPI2_EN 0x00000004 /* Maps SDP6 to GPI2 */
+#define E1000_CTRL_EXT_GPI3_EN 0x00000008 /* Maps SDP7 to GPI3 */
+/* Reserved (bits 4,5) in >= 82575 */
+#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Definable Pin 4 */
+#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Definable Pin 5 */
+#define E1000_CTRL_EXT_PHY_INT E1000_CTRL_EXT_SDP5_DATA
+#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Definable Pin 6 */
+#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Definable Pin 3 */
+/* SDP 4/5 (bits 8,9) are reserved in >= 82575 */
+#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */
+#define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */
+#define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */
+#define E1000_CTRL_EXT_SDP3_DIR 0x00000800 /* Direction of SDP3 0=in 1=out */
+#define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */
+#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
+#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */
+#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
+#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
+#define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */
+#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
+#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
+#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000
+#define E1000_CTRL_EXT_LINK_MODE_KMRN 0x00000000
+#define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000
+#define E1000_CTRL_EXT_LINK_MODE_PCIX_SERDES 0x00800000
+#define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000
+#define E1000_CTRL_EXT_EIAME 0x01000000
+#define E1000_CTRL_EXT_IRCA 0x00000001
+#define E1000_CTRL_EXT_WR_WMARK_MASK 0x03000000
+#define E1000_CTRL_EXT_WR_WMARK_256 0x00000000
+#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000
+#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000
+#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000
+#define E1000_CTRL_EXT_CANC 0x04000000 /* Int delay cancellation */
+#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */
+/* IAME enable bit (27) was removed in >= 82575 */
+#define E1000_CTRL_EXT_IAME 0x08000000 /* Int acknowledge Auto-mask */
+#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error
+ * detection enabled */
+#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity
+ * error detection enable */
+#define E1000_CTRL_EXT_GHOST_PAREN 0x40000000
+#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */
+#define E1000_I2CCMD_REG_ADDR_SHIFT 16
+#define E1000_I2CCMD_REG_ADDR 0x00FF0000
+#define E1000_I2CCMD_PHY_ADDR_SHIFT 24
+#define E1000_I2CCMD_PHY_ADDR 0x07000000
+#define E1000_I2CCMD_OPCODE_READ 0x08000000
+#define E1000_I2CCMD_OPCODE_WRITE 0x00000000
+#define E1000_I2CCMD_RESET 0x10000000
+#define E1000_I2CCMD_READY 0x20000000
+#define E1000_I2CCMD_INTERRUPT_ENA 0x40000000
+#define E1000_I2CCMD_ERROR 0x80000000
+#define E1000_MAX_SGMII_PHY_REG_ADDR 255
+#define E1000_I2CCMD_PHY_TIMEOUT 200
+
+/* Receive Descriptor bit definitions */
+#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
+#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */
+#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */
+#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
+#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
+#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
+#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */
+#define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */
+#define E1000_RXD_STAT_CRCV 0x100 /* Speculative CRC Valid */
+#define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */
+#define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */
+#define E1000_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */
+#define E1000_RXD_STAT_ACK 0x8000 /* ACK Packet indication */
+#define E1000_RXD_ERR_CE 0x01 /* CRC Error */
+#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
+#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */
+#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */
+#define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */
+#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */
+#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */
+#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
+#define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */
+#define E1000_RXD_SPC_PRI_SHIFT 13
+#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */
+#define E1000_RXD_SPC_CFI_SHIFT 12
+
+#define E1000_RXDEXT_STATERR_CE 0x01000000
+#define E1000_RXDEXT_STATERR_SE 0x02000000
+#define E1000_RXDEXT_STATERR_SEQ 0x04000000
+#define E1000_RXDEXT_STATERR_CXE 0x10000000
+#define E1000_RXDEXT_STATERR_TCPE 0x20000000
+#define E1000_RXDEXT_STATERR_IPE 0x40000000
+#define E1000_RXDEXT_STATERR_RXE 0x80000000
+
+/* mask to determine if packets should be dropped due to frame errors */
+#define E1000_RXD_ERR_FRAME_ERR_MASK ( \
+ E1000_RXD_ERR_CE | \
+ E1000_RXD_ERR_SE | \
+ E1000_RXD_ERR_SEQ | \
+ E1000_RXD_ERR_CXE | \
+ E1000_RXD_ERR_RXE)
+
+/* Same mask, but for extended and packet split descriptors */
+#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \
+ E1000_RXDEXT_STATERR_CE | \
+ E1000_RXDEXT_STATERR_SE | \
+ E1000_RXDEXT_STATERR_SEQ | \
+ E1000_RXDEXT_STATERR_CXE | \
+ E1000_RXDEXT_STATERR_RXE)
+
+#define E1000_MRQC_ENABLE_MASK 0x00000007
+#define E1000_MRQC_ENABLE_RSS_2Q 0x00000001
+#define E1000_MRQC_ENABLE_RSS_INT 0x00000004
+#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000
+#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
+#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000
+#define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000
+#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000
+
+#define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000
+#define E1000_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF
+
+/* Management Control */
+#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */
+#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */
+#define E1000_MANC_R_ON_FORCE 0x00000004 /* Reset on Force TCO - RO */
+#define E1000_MANC_RMCP_EN 0x00000100 /* Enable RCMP 026Fh Filtering */
+#define E1000_MANC_0298_EN 0x00000200 /* Enable RCMP 0298h Filtering */
+#define E1000_MANC_IPV4_EN 0x00000400 /* Enable IPv4 */
+#define E1000_MANC_IPV6_EN 0x00000800 /* Enable IPv6 */
+#define E1000_MANC_SNAP_EN 0x00001000 /* Accept LLC/SNAP */
+#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */
+/* Enable Neighbor Discovery Filtering */
+#define E1000_MANC_NEIGHBOR_EN 0x00004000
+#define E1000_MANC_ARP_RES_EN 0x00008000 /* Enable ARP response Filtering */
+#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */
+#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
+#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
+#define E1000_MANC_RCV_ALL 0x00080000 /* Receive All Enabled */
+#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */
+/* Enable MAC address filtering */
+#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000
+/* Enable MNG packets to host memory */
+#define E1000_MANC_EN_MNG2HOST 0x00200000
+/* Enable IP address filtering */
+#define E1000_MANC_EN_IP_ADDR_FILTER 0x00400000
+#define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Enable checksum filtering */
+#define E1000_MANC_BR_EN 0x01000000 /* Enable broadcast filtering */
+#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */
+#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */
+#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */
+#define E1000_MANC_SMB_DATA_IN 0x08000000 /* SMBus Data In */
+#define E1000_MANC_SMB_DATA_OUT 0x10000000 /* SMBus Data Out */
+#define E1000_MANC_SMB_CLK_OUT 0x20000000 /* SMBus Clock Out */
+
+#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */
+#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */
+
+/* Receive Control */
+#define E1000_RCTL_RST 0x00000001 /* Software reset */
+#define E1000_RCTL_EN 0x00000002 /* enable */
+#define E1000_RCTL_SBP 0x00000004 /* store bad packet */
+#define E1000_RCTL_UPE 0x00000008 /* unicast promisc enable */
+#define E1000_RCTL_MPE 0x00000010 /* multicast promisc enable */
+#define E1000_RCTL_LPE 0x00000020 /* long packet enable */
+#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */
+#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
+#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */
+#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
+#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */
+#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */
+#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min thresh size */
+#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min thresh size */
+#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min thresh size */
+#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */
+#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */
+#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */
+#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */
+#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */
+#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */
+#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */
+/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
+#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */
+#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */
+#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */
+#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */
+/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
+#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */
+#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */
+#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */
+#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */
+#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */
+#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */
+#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */
+#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */
+#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
+#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
+#define E1000_RCTL_FLXBUF_MASK 0x78000000 /* Flexible buffer size */
+#define E1000_RCTL_FLXBUF_SHIFT 27 /* Flexible buffer shift */
+
+/*
+ * Use byte values for the following shift parameters
+ * Usage:
+ * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) &
+ * E1000_PSRCTL_BSIZE0_MASK) |
+ * ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) &
+ * E1000_PSRCTL_BSIZE1_MASK) |
+ * ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) &
+ * E1000_PSRCTL_BSIZE2_MASK) |
+ * ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |;
+ * E1000_PSRCTL_BSIZE3_MASK))
+ * where value0 = [128..16256], default=256
+ * value1 = [1024..64512], default=4096
+ * value2 = [0..64512], default=4096
+ * value3 = [0..64512], default=0
+ */
+
+#define E1000_PSRCTL_BSIZE0_MASK 0x0000007F
+#define E1000_PSRCTL_BSIZE1_MASK 0x00003F00
+#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000
+#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000
+
+#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */
+#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */
+#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */
+#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */
+
+/* SWFW_SYNC Definitions */
+#define E1000_SWFW_EEP_SM 0x01
+#define E1000_SWFW_PHY0_SM 0x02
+#define E1000_SWFW_PHY1_SM 0x04
+#define E1000_SWFW_CSR_SM 0x08
+
+/* FACTPS Definitions */
+#define E1000_FACTPS_LFS 0x40000000 /* LAN Function Select */
+/* Device Control */
+#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */
+#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */
+#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */
+#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master reqs */
+#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */
+#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */
+#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */
+#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */
+#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */
+#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */
+#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */
+#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */
+#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */
+#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */
+#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */
+#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */
+#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
+#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */
+#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock
+ * indication in SDP[0] */
+#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through
+ * PHYRST_N pin */
+#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external
+ * LINK_0 and LINK_1 pins */
+#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
+#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
+#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */
+#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */
+#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */
+#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */
+#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */
+#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */
+#define E1000_CTRL_RST 0x04000000 /* Global reset */
+#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */
+#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */
+#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */
+#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
+#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */
+#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to ME */
+#define E1000_CTRL_I2C_ENA 0x02000000 /* I2C enable */
+
+/*
+ * Bit definitions for the Management Data IO (MDIO) and Management Data
+ * Clock (MDC) pins in the Device Control Register.
+ */
+#define E1000_CTRL_PHY_RESET_DIR E1000_CTRL_SWDPIO0
+#define E1000_CTRL_PHY_RESET E1000_CTRL_SWDPIN0
+#define E1000_CTRL_MDIO_DIR E1000_CTRL_SWDPIO2
+#define E1000_CTRL_MDIO E1000_CTRL_SWDPIN2
+#define E1000_CTRL_MDC_DIR E1000_CTRL_SWDPIO3
+#define E1000_CTRL_MDC E1000_CTRL_SWDPIN3
+#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR
+#define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA
+
+#define E1000_CONNSW_ENRGSRC 0x4
+#define E1000_PCS_CFG_PCS_EN 8
+#define E1000_PCS_LCTL_FLV_LINK_UP 1
+#define E1000_PCS_LCTL_FSV_10 0
+#define E1000_PCS_LCTL_FSV_100 2
+#define E1000_PCS_LCTL_FSV_1000 4
+#define E1000_PCS_LCTL_FDV_FULL 8
+#define E1000_PCS_LCTL_FSD 0x10
+#define E1000_PCS_LCTL_FORCE_LINK 0x20
+#define E1000_PCS_LCTL_LOW_LINK_LATCH 0x40
+#define E1000_PCS_LCTL_FORCE_FCTRL 0x80
+#define E1000_PCS_LCTL_AN_ENABLE 0x10000
+#define E1000_PCS_LCTL_AN_RESTART 0x20000
+#define E1000_PCS_LCTL_AN_TIMEOUT 0x40000
+#define E1000_PCS_LCTL_AN_SGMII_BYPASS 0x80000
+#define E1000_PCS_LCTL_AN_SGMII_TRIGGER 0x100000
+#define E1000_PCS_LCTL_FAST_LINK_TIMER 0x1000000
+#define E1000_PCS_LCTL_LINK_OK_FIX 0x2000000
+#define E1000_PCS_LCTL_CRS_ON_NI 0x4000000
+#define E1000_ENABLE_SERDES_LOOPBACK 0x0410
+
+#define E1000_PCS_LSTS_LINK_OK 1
+#define E1000_PCS_LSTS_SPEED_10 0
+#define E1000_PCS_LSTS_SPEED_100 2
+#define E1000_PCS_LSTS_SPEED_1000 4
+#define E1000_PCS_LSTS_DUPLEX_FULL 8
+#define E1000_PCS_LSTS_SYNK_OK 0x10
+#define E1000_PCS_LSTS_AN_COMPLETE 0x10000
+#define E1000_PCS_LSTS_AN_PAGE_RX 0x20000
+#define E1000_PCS_LSTS_AN_TIMED_OUT 0x40000
+#define E1000_PCS_LSTS_AN_REMOTE_FAULT 0x80000
+#define E1000_PCS_LSTS_AN_ERROR_RWS 0x100000
+
+/* Device Status */
+#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
+#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
+#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */
+#define E1000_STATUS_FUNC_SHIFT 2
+#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */
+#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */
+#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */
+#define E1000_STATUS_TBIMODE 0x00000020 /* TBI mode */
+#define E1000_STATUS_SPEED_MASK 0x000000C0
+#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */
+#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
+#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
+#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */
+#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */
+#define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */
+#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state.
+ * Clear on write '0'. */
+#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master request status */
+#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */
+#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */
+#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */
+#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */
+#define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */
+#define E1000_STATUS_BMC_SKU_0 0x00100000 /* BMC USB redirect disabled */
+#define E1000_STATUS_BMC_SKU_1 0x00200000 /* BMC SRAM disabled */
+#define E1000_STATUS_BMC_SKU_2 0x00400000 /* BMC SDRAM disabled */
+#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */
+#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution
+ * disabled */
+#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */
+#define E1000_STATUS_FUSE_8 0x04000000
+#define E1000_STATUS_FUSE_9 0x08000000
+#define E1000_STATUS_SERDES0_DIS 0x10000000 /* SERDES disabled on port 0 */
+#define E1000_STATUS_SERDES1_DIS 0x20000000 /* SERDES disabled on port 1 */
+
+/* Constants used to interpret the masked PCI-X bus speed. */
+#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */
+#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */
+#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /*PCI-X bus speed 100-133 MHz*/
+
+#define SPEED_10 10
+#define SPEED_100 100
+#define SPEED_1000 1000
+#define HALF_DUPLEX 1
+#define FULL_DUPLEX 2
+
+#define PHY_FORCE_TIME 20
+
+#define ADVERTISE_10_HALF 0x0001
+#define ADVERTISE_10_FULL 0x0002
+#define ADVERTISE_100_HALF 0x0004
+#define ADVERTISE_100_FULL 0x0008
+#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */
+#define ADVERTISE_1000_FULL 0x0020
+
+/* 1000/H is not supported, nor spec-compliant. */
+#define E1000_ALL_SPEED_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \
+ ADVERTISE_100_HALF | ADVERTISE_100_FULL | \
+ ADVERTISE_1000_FULL)
+#define E1000_ALL_NOT_GIG (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \
+ ADVERTISE_100_HALF | ADVERTISE_100_FULL)
+#define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL)
+#define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL)
+#define E1000_ALL_FULL_DUPLEX (ADVERTISE_10_FULL | ADVERTISE_100_FULL | \
+ ADVERTISE_1000_FULL)
+#define E1000_ALL_HALF_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_100_HALF)
+
+#define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX
+
+/* LED Control */
+#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F
+#define E1000_LEDCTL_LED0_MODE_SHIFT 0
+#define E1000_LEDCTL_LED0_BLINK_RATE 0x00000020
+#define E1000_LEDCTL_LED0_IVRT 0x00000040
+#define E1000_LEDCTL_LED0_BLINK 0x00000080
+#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00
+#define E1000_LEDCTL_LED1_MODE_SHIFT 8
+#define E1000_LEDCTL_LED1_BLINK_RATE 0x00002000
+#define E1000_LEDCTL_LED1_IVRT 0x00004000
+#define E1000_LEDCTL_LED1_BLINK 0x00008000
+#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000
+#define E1000_LEDCTL_LED2_MODE_SHIFT 16
+#define E1000_LEDCTL_LED2_BLINK_RATE 0x00200000
+#define E1000_LEDCTL_LED2_IVRT 0x00400000
+#define E1000_LEDCTL_LED2_BLINK 0x00800000
+#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000
+#define E1000_LEDCTL_LED3_MODE_SHIFT 24
+#define E1000_LEDCTL_LED3_BLINK_RATE 0x20000000
+#define E1000_LEDCTL_LED3_IVRT 0x40000000
+#define E1000_LEDCTL_LED3_BLINK 0x80000000
+
+#define E1000_LEDCTL_MODE_LINK_10_1000 0x0
+#define E1000_LEDCTL_MODE_LINK_100_1000 0x1
+#define E1000_LEDCTL_MODE_LINK_UP 0x2
+#define E1000_LEDCTL_MODE_ACTIVITY 0x3
+#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4
+#define E1000_LEDCTL_MODE_LINK_10 0x5
+#define E1000_LEDCTL_MODE_LINK_100 0x6
+#define E1000_LEDCTL_MODE_LINK_1000 0x7
+#define E1000_LEDCTL_MODE_PCIX_MODE 0x8
+#define E1000_LEDCTL_MODE_FULL_DUPLEX 0x9
+#define E1000_LEDCTL_MODE_COLLISION 0xA
+#define E1000_LEDCTL_MODE_BUS_SPEED 0xB
+#define E1000_LEDCTL_MODE_BUS_SIZE 0xC
+#define E1000_LEDCTL_MODE_PAUSED 0xD
+#define E1000_LEDCTL_MODE_LED_ON 0xE
+#define E1000_LEDCTL_MODE_LED_OFF 0xF
+
+/* Transmit Descriptor bit definitions */
+#define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */
+#define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */
+#define E1000_TXD_POPTS_SHIFT 8 /* POPTS shift */
+#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
+#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
+#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */
+#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
+#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */
+#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */
+#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */
+#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */
+#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */
+#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */
+#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */
+#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */
+#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */
+#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */
+#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */
+#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */
+#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */
+#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */
+/* Extended desc bits for Linksec and timesync */
+
+/* Transmit Control */
+#define E1000_TCTL_RST 0x00000001 /* software reset */
+#define E1000_TCTL_EN 0x00000002 /* enable tx */
+#define E1000_TCTL_BCE 0x00000004 /* busy check enable */
+#define E1000_TCTL_PSP 0x00000008 /* pad short packets */
+#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */
+#define E1000_TCTL_COLD 0x003ff000 /* collision distance */
+#define E1000_TCTL_SWXOFF 0x00400000 /* SW Xoff transmission */
+#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */
+#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */
+#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */
+#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */
+
+/* Transmit Arbitration Count */
+#define E1000_TARC0_ENABLE 0x00000400 /* Enable Tx Queue 0 */
+
+/* SerDes Control */
+#define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400
+
+/* Receive Checksum Control */
+#define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */
+#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */
+#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */
+#define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */
+#define E1000_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */
+#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
+#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
+
+/* Header split receive */
+#define E1000_RFCTL_ISCSI_DIS 0x00000001
+#define E1000_RFCTL_ISCSI_DWC_MASK 0x0000003E
+#define E1000_RFCTL_ISCSI_DWC_SHIFT 1
+#define E1000_RFCTL_NFSW_DIS 0x00000040
+#define E1000_RFCTL_NFSR_DIS 0x00000080
+#define E1000_RFCTL_NFS_VER_MASK 0x00000300
+#define E1000_RFCTL_NFS_VER_SHIFT 8
+#define E1000_RFCTL_IPV6_DIS 0x00000400
+#define E1000_RFCTL_IPV6_XSUM_DIS 0x00000800
+#define E1000_RFCTL_ACK_DIS 0x00001000
+#define E1000_RFCTL_ACKD_DIS 0x00002000
+#define E1000_RFCTL_IPFRSP_DIS 0x00004000
+#define E1000_RFCTL_EXTEN 0x00008000
+#define E1000_RFCTL_IPV6_EX_DIS 0x00010000
+#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000
+#define E1000_RFCTL_LEF 0x00040000
+
+/* Collision related configuration parameters */
+#define E1000_COLLISION_THRESHOLD 15
+#define E1000_CT_SHIFT 4
+#define E1000_COLLISION_DISTANCE 63
+#define E1000_COLD_SHIFT 12
+
+/* Default values for the transmit IPG register */
+#define DEFAULT_82543_TIPG_IPGT_FIBER 9
+#define DEFAULT_82543_TIPG_IPGT_COPPER 8
+
+#define E1000_TIPG_IPGT_MASK 0x000003FF
+#define E1000_TIPG_IPGR1_MASK 0x000FFC00
+#define E1000_TIPG_IPGR2_MASK 0x3FF00000
+
+#define DEFAULT_82543_TIPG_IPGR1 8
+#define E1000_TIPG_IPGR1_SHIFT 10
+
+#define DEFAULT_82543_TIPG_IPGR2 6
+#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7
+#define E1000_TIPG_IPGR2_SHIFT 20
+
+/* Ethertype field values */
+#define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */
+
+#define ETHERNET_FCS_SIZE 4
+#define MAX_JUMBO_FRAME_SIZE 0x3F00
+
+/* Extended Configuration Control and Size */
+#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020
+#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001
+#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008
+#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020
+#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000
+#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16
+#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000
+#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT 16
+
+#define E1000_PHY_CTRL_SPD_EN 0x00000001
+#define E1000_PHY_CTRL_D0A_LPLU 0x00000002
+#define E1000_PHY_CTRL_NOND0A_LPLU 0x00000004
+#define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008
+#define E1000_PHY_CTRL_GBE_DISABLE 0x00000040
+
+#define E1000_KABGTXD_BGSQLBIAS 0x00050000
+
+/* PBA constants */
+#define E1000_PBA_6K 0x0006 /* 6KB */
+#define E1000_PBA_8K 0x0008 /* 8KB */
+#define E1000_PBA_10K 0x000A /* 10KB */
+#define E1000_PBA_12K 0x000C /* 12KB */
+#define E1000_PBA_14K 0x000E /* 14KB */
+#define E1000_PBA_16K 0x0010 /* 16KB */
+#define E1000_PBA_18K 0x0012
+#define E1000_PBA_20K 0x0014
+#define E1000_PBA_22K 0x0016
+#define E1000_PBA_24K 0x0018
+#define E1000_PBA_26K 0x001A
+#define E1000_PBA_30K 0x001E
+#define E1000_PBA_32K 0x0020
+#define E1000_PBA_34K 0x0022
+#define E1000_PBA_35K 0x0023
+#define E1000_PBA_38K 0x0026
+#define E1000_PBA_40K 0x0028
+#define E1000_PBA_48K 0x0030 /* 48KB */
+#define E1000_PBA_64K 0x0040 /* 64KB */
+
+#define E1000_PBS_16K E1000_PBA_16K
+#define E1000_PBS_24K E1000_PBA_24K
+
+#define IFS_MAX 80
+#define IFS_MIN 40
+#define IFS_RATIO 4
+#define IFS_STEP 10
+#define MIN_NUM_XMITS 1000
+
+/* SW Semaphore Register */
+#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
+#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
+#define E1000_SWSM_WMNG 0x00000004 /* Wake MNG Clock */
+#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */
+
+#define E1000_SWSM2_LOCK 0x00000002 /* Secondary driver semaphore bit */
+
+/* Interrupt Cause Read */
+#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */
+#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */
+#define E1000_ICR_LSC 0x00000004 /* Link Status Change */
+#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */
+#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */
+#define E1000_ICR_RXO 0x00000040 /* rx overrun */
+#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */
+#define E1000_ICR_VMMB 0x00000100 /* VM MB event */
+#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */
+#define E1000_ICR_RXCFG 0x00000400 /* Rx /c/ ordered set */
+#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */
+#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */
+#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */
+#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */
+#define E1000_ICR_TXD_LOW 0x00008000
+#define E1000_ICR_SRPD 0x00010000
+#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */
+#define E1000_ICR_MNG 0x00040000 /* Manageability event */
+#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */
+#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver
+ * should claim the interrupt */
+#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* Q0 Rx desc FIFO parity error */
+#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* Q0 Tx desc FIFO parity error */
+#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity err */
+#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */
+#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* Q1 Rx desc FIFO parity error */
+#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* Q1 Tx desc FIFO parity error */
+#define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */
+#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW
+ * bit in the FWSM */
+#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates
+ * an interrupt */
+#define E1000_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */
+#define E1000_ICR_EPRST 0x00100000 /* ME hardware reset occurs */
+
+
+/*
+ * This defines the bits that are set in the Interrupt Mask
+ * Set/Read Register. Each bit is documented below:
+ * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
+ * o RXSEQ = Receive Sequence Error
+ */
+#define POLL_IMS_ENABLE_MASK ( \
+ E1000_IMS_RXDMT0 | \
+ E1000_IMS_RXSEQ)
+
+/*
+ * This defines the bits that are set in the Interrupt Mask
+ * Set/Read Register. Each bit is documented below:
+ * o RXT0 = Receiver Timer Interrupt (ring 0)
+ * o TXDW = Transmit Descriptor Written Back
+ * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
+ * o RXSEQ = Receive Sequence Error
+ * o LSC = Link Status Change
+ */
+#define IMS_ENABLE_MASK ( \
+ E1000_IMS_RXT0 | \
+ E1000_IMS_TXDW | \
+ E1000_IMS_RXDMT0 | \
+ E1000_IMS_RXSEQ | \
+ E1000_IMS_LSC)
+
+/* Interrupt Mask Set */
+#define E1000_IMS_TXDW E1000_ICR_TXDW /* Tx desc written back */
+#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
+#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */
+#define E1000_IMS_VMMB E1000_ICR_VMMB /* Mail box activity */
+#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
+#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
+#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */
+#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
+#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */
+#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* Rx /c/ ordered set */
+#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */
+#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */
+#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */
+#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
+#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW
+#define E1000_IMS_SRPD E1000_ICR_SRPD
+#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */
+#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */
+#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */
+#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* Q0 Rx desc FIFO
+ * parity error */
+#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* Q0 Tx desc FIFO
+ * parity error */
+#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer
+ * parity error */
+#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity
+ * error */
+#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* Q1 Rx desc FIFO
+ * parity error */
+#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* Q1 Tx desc FIFO
+ * parity error */
+#define E1000_IMS_DSW E1000_ICR_DSW
+#define E1000_IMS_PHYINT E1000_ICR_PHYINT
+#define E1000_IMS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */
+#define E1000_IMS_EPRST E1000_ICR_EPRST
+
+/* Interrupt Cause Set */
+#define E1000_ICS_TXDW E1000_ICR_TXDW /* Tx desc written back */
+#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
+#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
+#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
+#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
+#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */
+#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
+#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */
+#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* Rx /c/ ordered set */
+#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */
+#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */
+#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */
+#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
+#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW
+#define E1000_ICS_SRPD E1000_ICR_SRPD
+#define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */
+#define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */
+#define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */
+#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* Q0 Rx desc FIFO
+ * parity error */
+#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* Q0 Tx desc FIFO
+ * parity error */
+#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer
+ * parity error */
+#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity
+ * error */
+#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* Q1 Rx desc FIFO
+ * parity error */
+#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* Q1 Tx desc FIFO
+ * parity error */
+#define E1000_ICS_DSW E1000_ICR_DSW
+#define E1000_ICS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */
+#define E1000_ICS_PHYINT E1000_ICR_PHYINT
+#define E1000_ICS_EPRST E1000_ICR_EPRST
+
+/* Transmit Descriptor Control */
+#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
+#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */
+#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
+#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */
+#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
+#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
+#define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */
+/* Enable the counting of descriptors still to be processed. */
+#define E1000_TXDCTL_COUNT_DESC 0x00400000
+
+/* Flow Control Constants */
+#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001
+#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
+#define FLOW_CONTROL_TYPE 0x8808
+
+/* 802.1q VLAN Packet Size */
+#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */
+#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
+
+/* Receive Address */
+/*
+ * Number of high/low register pairs in the RAR. The RAR (Receive Address
+ * Registers) holds the directed and multicast addresses that we monitor.
+ * Technically, we have 16 spots. However, we reserve one of these spots
+ * (RAR[15]) for our directed address used by controllers with
+ * manageability enabled, allowing us room for 15 multicast addresses.
+ */
+#define E1000_RAR_ENTRIES 15
+#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */
+#define E1000_RAL_MAC_ADDR_LEN 4
+#define E1000_RAH_MAC_ADDR_LEN 2
+#define E1000_RAH_POOL_MASK 0x03FC0000
+#define E1000_RAH_POOL_1 0x00040000
+
+/* Error Codes */
+#define E1000_SUCCESS 0
+#define E1000_ERR_NVM 1
+#define E1000_ERR_PHY 2
+#define E1000_ERR_CONFIG 3
+#define E1000_ERR_PARAM 4
+#define E1000_ERR_MAC_INIT 5
+#define E1000_ERR_PHY_TYPE 6
+#define E1000_ERR_RESET 9
+#define E1000_ERR_MASTER_REQUESTS_PENDING 10
+#define E1000_ERR_HOST_INTERFACE_COMMAND 11
+#define E1000_BLK_PHY_RESET 12
+#define E1000_ERR_SWFW_SYNC 13
+#define E1000_NOT_IMPLEMENTED 14
+#define E1000_ERR_MBX 15
+
+/* Loop limit on how long we wait for auto-negotiation to complete */
+#define FIBER_LINK_UP_LIMIT 50
+#define COPPER_LINK_UP_LIMIT 10
+#define PHY_AUTO_NEG_LIMIT 45
+#define PHY_FORCE_LIMIT 20
+/* Number of 100 microseconds we wait for PCI Express master disable */
+#define MASTER_DISABLE_TIMEOUT 800
+/* Number of milliseconds we wait for PHY configuration done after MAC reset */
+#define PHY_CFG_TIMEOUT 100
+/* Number of 2 milliseconds we wait for acquiring MDIO ownership. */
+#define MDIO_OWNERSHIP_TIMEOUT 10
+/* Number of milliseconds for NVM auto read done after MAC reset. */
+#define AUTO_READ_DONE_TIMEOUT 10
+
+/* Flow Control */
+#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */
+#define E1000_FCRTH_XFCE 0x80000000 /* External Flow Control Enable */
+#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */
+#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */
+
+/* Transmit Configuration Word */
+#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */
+#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */
+#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */
+#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */
+#define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */
+#define E1000_TXCW_RF 0x00003000 /* TXCW remote fault */
+#define E1000_TXCW_NP 0x00008000 /* TXCW next page */
+#define E1000_TXCW_CW 0x0000ffff /* TxConfigWord mask */
+#define E1000_TXCW_TXC 0x40000000 /* Transmit Config control */
+#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */
+
+/* Receive Configuration Word */
+#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */
+#define E1000_RXCW_NC 0x04000000 /* Receive config no carrier */
+#define E1000_RXCW_IV 0x08000000 /* Receive config invalid */
+#define E1000_RXCW_CC 0x10000000 /* Receive config change */
+#define E1000_RXCW_C 0x20000000 /* Receive config */
+#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */
+#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */
+
+
+/* PCI Express Control */
+#define E1000_GCR_RXD_NO_SNOOP 0x00000001
+#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002
+#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004
+#define E1000_GCR_TXD_NO_SNOOP 0x00000008
+#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010
+#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020
+#define E1000_GCR_CMPL_TMOUT_MASK 0x0000F000
+#define E1000_GCR_CMPL_TMOUT_10ms 0x00001000
+#define E1000_GCR_CMPL_TMOUT_RESEND 0x00010000
+#define E1000_GCR_CAP_VER2 0x00040000
+
+#define PCIE_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \
+ E1000_GCR_RXDSCW_NO_SNOOP | \
+ E1000_GCR_RXDSCR_NO_SNOOP | \
+ E1000_GCR_TXD_NO_SNOOP | \
+ E1000_GCR_TXDSCW_NO_SNOOP | \
+ E1000_GCR_TXDSCR_NO_SNOOP)
+
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN 0x0800 /* Power down */
+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+#define MII_CR_SPEED_1000 0x0040
+#define MII_CR_SPEED_100 0x2000
+#define MII_CR_SPEED_10 0x0000
+
+/* PHY Status Register */
+#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
+#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
+
+/* Autoneg Advertisement Register */
+#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */
+#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
+#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
+#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
+#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
+#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
+#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */
+#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
+#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
+#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */
+
+/* Link Partner Ability Register (Base Page) */
+#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */
+#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */
+#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */
+#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */
+#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */
+#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */
+#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
+#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
+#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */
+#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */
+#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */
+
+/* Autoneg Expansion Register */
+#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */
+#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */
+#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */
+#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */
+#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */
+
+/* 1000BASE-T Control Register */
+#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */
+#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
+#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
+#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */
+ /* 0=DTE device */
+#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */
+ /* 0=Configure PHY as Slave */
+#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */
+ /* 0=Automatic Master/Slave config */
+#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
+#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
+#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */
+#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */
+#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */
+
+/* 1000BASE-T Status Register */
+#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */
+#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */
+#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
+#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
+#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
+#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
+#define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local Tx is Master, 0=Slave */
+#define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */
+
+#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5
+
+/* PHY 1000 MII Register/Bit Definitions */
+/* PHY Registers defined by IEEE */
+#define PHY_CONTROL 0x00 /* Control Register */
+#define PHY_STATUS 0x01 /* Status Register */
+#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */
+#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */
+#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
+#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
+#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */
+#define PHY_NEXT_PAGE_TX 0x07 /* Next Page Tx */
+#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
+#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */
+#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
+#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */
+
+#define PHY_CONTROL_LB 0x4000 /* PHY Loopback bit */
+
+/* NVM Control */
+#define E1000_EECD_SK 0x00000001 /* NVM Clock */
+#define E1000_EECD_CS 0x00000002 /* NVM Chip Select */
+#define E1000_EECD_DI 0x00000004 /* NVM Data In */
+#define E1000_EECD_DO 0x00000008 /* NVM Data Out */
+#define E1000_EECD_FWE_MASK 0x00000030
+#define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */
+#define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */
+#define E1000_EECD_FWE_SHIFT 4
+#define E1000_EECD_REQ 0x00000040 /* NVM Access Request */
+#define E1000_EECD_GNT 0x00000080 /* NVM Access Grant */
+#define E1000_EECD_PRES 0x00000100 /* NVM Present */
+#define E1000_EECD_SIZE 0x00000200 /* NVM Size (0=64 word 1=256 word) */
+/* NVM Addressing bits based on type 0=small, 1=large */
+#define E1000_EECD_ADDR_BITS 0x00000400
+#define E1000_EECD_TYPE 0x00002000 /* NVM Type (1-SPI, 0-Microwire) */
+#define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */
+#define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */
+#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */
+#define E1000_EECD_SIZE_EX_SHIFT 11
+#define E1000_EECD_NVADDS 0x00018000 /* NVM Address Size */
+#define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */
+#define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */
+#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */
+#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */
+#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */
+#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
+#define E1000_EECD_SECVAL_SHIFT 22
+#define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES)
+
+#define E1000_NVM_SWDPIN0 0x0001 /* SWDPIN 0 NVM Value */
+#define E1000_NVM_LED_LOGIC 0x0020 /* Led Logic Word */
+#define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write regs */
+#define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
+#define E1000_NVM_RW_REG_START 1 /* Start operation */
+#define E1000_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
+#define E1000_NVM_POLL_WRITE 1 /* Flag for polling for write complete */
+#define E1000_NVM_POLL_READ 0 /* Flag for polling for read complete */
+#define E1000_FLASH_UPDATES 2000
+
+/* NVM Word Offsets */
+#define NVM_COMPAT 0x0003
+#define NVM_ID_LED_SETTINGS 0x0004
+#define NVM_VERSION 0x0005
+#define NVM_SERDES_AMPLITUDE 0x0006 /* SERDES output amplitude */
+#define NVM_PHY_CLASS_WORD 0x0007
+#define NVM_INIT_CONTROL1_REG 0x000A
+#define NVM_INIT_CONTROL2_REG 0x000F
+#define NVM_SWDEF_PINS_CTRL_PORT_1 0x0010
+#define NVM_INIT_CONTROL3_PORT_B 0x0014
+#define NVM_INIT_3GIO_3 0x001A
+#define NVM_SWDEF_PINS_CTRL_PORT_0 0x0020
+#define NVM_INIT_CONTROL3_PORT_A 0x0024
+#define NVM_CFG 0x0012
+#define NVM_FLASH_VERSION 0x0032
+#define NVM_ALT_MAC_ADDR_PTR 0x0037
+#define NVM_CHECKSUM_REG 0x003F
+
+#define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */
+#define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */
+
+/* Mask bits for fields in Word 0x0f of the NVM */
+#define NVM_WORD0F_PAUSE_MASK 0x3000
+#define NVM_WORD0F_PAUSE 0x1000
+#define NVM_WORD0F_ASM_DIR 0x2000
+#define NVM_WORD0F_ANE 0x0800
+#define NVM_WORD0F_SWPDIO_EXT_MASK 0x00F0
+#define NVM_WORD0F_LPLU 0x0001
+
+/* Mask bits for fields in Word 0x1a of the NVM */
+#define NVM_WORD1A_ASPM_MASK 0x000C
+
+/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
+#define NVM_SUM 0xBABA
+
+#define NVM_MAC_ADDR_OFFSET 0
+#define NVM_PBA_OFFSET_0 8
+#define NVM_PBA_OFFSET_1 9
+#define NVM_RESERVED_WORD 0xFFFF
+#define NVM_PHY_CLASS_A 0x8000
+#define NVM_SERDES_AMPLITUDE_MASK 0x000F
+#define NVM_SIZE_MASK 0x1C00
+#define NVM_SIZE_SHIFT 10
+#define NVM_WORD_SIZE_BASE_SHIFT 6
+#define NVM_SWDPIO_EXT_SHIFT 4
+
+/* NVM Commands - SPI */
+#define NVM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */
+#define NVM_READ_OPCODE_SPI 0x03 /* NVM read opcode */
+#define NVM_WRITE_OPCODE_SPI 0x02 /* NVM write opcode */
+#define NVM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */
+#define NVM_WREN_OPCODE_SPI 0x06 /* NVM set Write Enable latch */
+#define NVM_WRDI_OPCODE_SPI 0x04 /* NVM reset Write Enable latch */
+#define NVM_RDSR_OPCODE_SPI 0x05 /* NVM read Status register */
+#define NVM_WRSR_OPCODE_SPI 0x01 /* NVM write Status register */
+
+/* SPI NVM Status Register */
+#define NVM_STATUS_RDY_SPI 0x01
+#define NVM_STATUS_WEN_SPI 0x02
+#define NVM_STATUS_BP0_SPI 0x04
+#define NVM_STATUS_BP1_SPI 0x08
+#define NVM_STATUS_WPEN_SPI 0x80
+
+/* Word definitions for ID LED Settings */
+#define ID_LED_RESERVED_0000 0x0000
+#define ID_LED_RESERVED_FFFF 0xFFFF
+#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \
+ (ID_LED_OFF1_OFF2 << 8) | \
+ (ID_LED_DEF1_DEF2 << 4) | \
+ (ID_LED_DEF1_DEF2))
+#define ID_LED_DEF1_DEF2 0x1
+#define ID_LED_DEF1_ON2 0x2
+#define ID_LED_DEF1_OFF2 0x3
+#define ID_LED_ON1_DEF2 0x4
+#define ID_LED_ON1_ON2 0x5
+#define ID_LED_ON1_OFF2 0x6
+#define ID_LED_OFF1_DEF2 0x7
+#define ID_LED_OFF1_ON2 0x8
+#define ID_LED_OFF1_OFF2 0x9
+
+#define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF
+#define IGP_ACTIVITY_LED_ENABLE 0x0300
+#define IGP_LED3_MODE 0x07000000
+
+/* PCI/PCI-X/PCI-EX Config space */
+#define PCI_HEADER_TYPE_REGISTER 0x0E
+#define PCIE_LINK_STATUS 0x12
+#define PCIE_DEVICE_CONTROL2 0x28
+
+#define PCI_HEADER_TYPE_MULTIFUNC 0x80
+#define PCIE_LINK_WIDTH_MASK 0x3F0
+#define PCIE_LINK_WIDTH_SHIFT 4
+#define PCIE_DEVICE_CONTROL2_16ms 0x0005
+
+#ifndef ETH_ADDR_LEN
+#define ETH_ADDR_LEN 6
+#endif
+
+#define PHY_REVISION_MASK 0xFFFFFFF0
+#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
+#define MAX_PHY_MULTI_PAGE_REG 0xF
+
+/* Bit definitions for valid PHY IDs. */
+/*
+ * I = Integrated
+ * E = External
+ */
+#define M88E1000_E_PHY_ID 0x01410C50
+#define M88E1000_I_PHY_ID 0x01410C30
+#define M88E1011_I_PHY_ID 0x01410C20
+#define IGP01E1000_I_PHY_ID 0x02A80380
+#define M88E1011_I_REV_4 0x04
+#define M88E1111_I_PHY_ID 0x01410CC0
+#define GG82563_E_PHY_ID 0x01410CA0
+#define IGP03E1000_E_PHY_ID 0x02A80390
+#define IFE_E_PHY_ID 0x02A80330
+#define IFE_PLUS_E_PHY_ID 0x02A80320
+#define IFE_C_E_PHY_ID 0x02A80310
+#define M88_VENDOR 0x0141
+
+/* M88E1000 Specific Registers */
+#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
+#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */
+#define M88E1000_INT_ENABLE 0x12 /* Interrupt Enable Register */
+#define M88E1000_INT_STATUS 0x13 /* Interrupt Status Register */
+#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */
+#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */
+
+#define M88E1000_PHY_EXT_CTRL 0x1A /* PHY extend control register */
+#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */
+#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */
+#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */
+#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */
+
+/* M88E1000 PHY Specific Control Register */
+#define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */
+#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reverse enabled */
+#define M88E1000_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */
+/* 1=CLK125 low, 0=CLK125 toggling */
+#define M88E1000_PSCR_CLK125_DISABLE 0x0010
+#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */
+ /* Manual MDI configuration */
+#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
+/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
+#define M88E1000_PSCR_AUTO_X_1000T 0x0040
+/* Auto crossover enabled all speeds */
+#define M88E1000_PSCR_AUTO_X_MODE 0x0060
+/*
+ * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold
+ * 0=Normal 10BASE-T Rx Threshold
+ */
+#define M88E1000_PSCR_EN_10BT_EXT_DIST 0x0080
+/* 1=5-bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */
+#define M88E1000_PSCR_MII_5BIT_ENABLE 0x0100
+#define M88E1000_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */
+#define M88E1000_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */
+#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Tx */
+
+/* M88E1000 PHY Specific Status Register */
+#define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */
+#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */
+#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */
+#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */
+/*
+ * 0 = <50M
+ * 1 = 50-80M
+ * 2 = 80-110M
+ * 3 = 110-140M
+ * 4 = >140M
+ */
+#define M88E1000_PSSR_CABLE_LENGTH 0x0380
+#define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */
+#define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
+#define M88E1000_PSSR_PAGE_RCVD 0x1000 /* 1=Page received */
+#define M88E1000_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
+#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
+#define M88E1000_PSSR_10MBS 0x0000 /* 00=10Mbs */
+#define M88E1000_PSSR_100MBS 0x4000 /* 01=100Mbs */
+#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
+
+#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
+
+/* M88E1000 Extended PHY Specific Control Register */
+#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */
+/*
+ * 1 = Lost lock detect enabled.
+ * Will assert lost lock and bring
+ * link down if idle not seen
+ * within 1ms in 1000BASE-T
+ */
+#define M88E1000_EPSCR_DOWN_NO_IDLE 0x8000
+/*
+ * Number of times we will attempt to autonegotiate before downshifting if we
+ * are the master
+ */
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X 0x0400
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X 0x0800
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X 0x0C00
+/*
+ * Number of times we will attempt to autonegotiate before downshifting if we
+ * are the slave
+ */
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_DIS 0x0000
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X 0x0200
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X 0x0300
+#define M88E1000_EPSCR_TX_CLK_2_5 0x0060 /* 2.5 MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */
+
+/* M88EC018 Rev 2 specific DownShift settings */
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_1X 0x0000
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_2X 0x0200
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_3X 0x0400
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_4X 0x0600
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_6X 0x0A00
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X 0x0C00
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X 0x0E00
+
+/*
+ * Bits...
+ * 15-5: page
+ * 4-0: register offset
+ */
+#define GG82563_PAGE_SHIFT 5
+#define GG82563_REG(page, reg) \
+ (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
+#define GG82563_MIN_ALT_REG 30
+
+/* GG82563 Specific Registers */
+#define GG82563_PHY_SPEC_CTRL \
+ GG82563_REG(0, 16) /* PHY Specific Control */
+#define GG82563_PHY_SPEC_STATUS \
+ GG82563_REG(0, 17) /* PHY Specific Status */
+#define GG82563_PHY_INT_ENABLE \
+ GG82563_REG(0, 18) /* Interrupt Enable */
+#define GG82563_PHY_SPEC_STATUS_2 \
+ GG82563_REG(0, 19) /* PHY Specific Status 2 */
+#define GG82563_PHY_RX_ERR_CNTR \
+ GG82563_REG(0, 21) /* Receive Error Counter */
+#define GG82563_PHY_PAGE_SELECT \
+ GG82563_REG(0, 22) /* Page Select */
+#define GG82563_PHY_SPEC_CTRL_2 \
+ GG82563_REG(0, 26) /* PHY Specific Control 2 */
+#define GG82563_PHY_PAGE_SELECT_ALT \
+ GG82563_REG(0, 29) /* Alternate Page Select */
+#define GG82563_PHY_TEST_CLK_CTRL \
+ GG82563_REG(0, 30) /* Test Clock Control (use reg. 29 to select) */
+
+#define GG82563_PHY_MAC_SPEC_CTRL \
+ GG82563_REG(2, 21) /* MAC Specific Control Register */
+#define GG82563_PHY_MAC_SPEC_CTRL_2 \
+ GG82563_REG(2, 26) /* MAC Specific Control 2 */
+
+#define GG82563_PHY_DSP_DISTANCE \
+ GG82563_REG(5, 26) /* DSP Distance */
+
+/* Page 193 - Port Control Registers */
+#define GG82563_PHY_KMRN_MODE_CTRL \
+ GG82563_REG(193, 16) /* Kumeran Mode Control */
+#define GG82563_PHY_PORT_RESET \
+ GG82563_REG(193, 17) /* Port Reset */
+#define GG82563_PHY_REVISION_ID \
+ GG82563_REG(193, 18) /* Revision ID */
+#define GG82563_PHY_DEVICE_ID \
+ GG82563_REG(193, 19) /* Device ID */
+#define GG82563_PHY_PWR_MGMT_CTRL \
+ GG82563_REG(193, 20) /* Power Management Control */
+#define GG82563_PHY_RATE_ADAPT_CTRL \
+ GG82563_REG(193, 25) /* Rate Adaptation Control */
+
+/* Page 194 - KMRN Registers */
+#define GG82563_PHY_KMRN_FIFO_CTRL_STAT \
+ GG82563_REG(194, 16) /* FIFO's Control/Status */
+#define GG82563_PHY_KMRN_CTRL \
+ GG82563_REG(194, 17) /* Control */
+#define GG82563_PHY_INBAND_CTRL \
+ GG82563_REG(194, 18) /* Inband Control */
+#define GG82563_PHY_KMRN_DIAGNOSTIC \
+ GG82563_REG(194, 19) /* Diagnostic */
+#define GG82563_PHY_ACK_TIMEOUTS \
+ GG82563_REG(194, 20) /* Acknowledge Timeouts */
+#define GG82563_PHY_ADV_ABILITY \
+ GG82563_REG(194, 21) /* Advertised Ability */
+#define GG82563_PHY_LINK_PARTNER_ADV_ABILITY \
+ GG82563_REG(194, 23) /* Link Partner Advertised Ability */
+#define GG82563_PHY_ADV_NEXT_PAGE \
+ GG82563_REG(194, 24) /* Advertised Next Page */
+#define GG82563_PHY_LINK_PARTNER_ADV_NEXT_PAGE \
+ GG82563_REG(194, 25) /* Link Partner Advertised Next page */
+#define GG82563_PHY_KMRN_MISC \
+ GG82563_REG(194, 26) /* Misc. */
+
+/* MDI Control */
+#define E1000_MDIC_DATA_MASK 0x0000FFFF
+#define E1000_MDIC_REG_MASK 0x001F0000
+#define E1000_MDIC_REG_SHIFT 16
+#define E1000_MDIC_PHY_MASK 0x03E00000
+#define E1000_MDIC_PHY_SHIFT 21
+#define E1000_MDIC_OP_WRITE 0x04000000
+#define E1000_MDIC_OP_READ 0x08000000
+#define E1000_MDIC_READY 0x10000000
+#define E1000_MDIC_INT_EN 0x20000000
+#define E1000_MDIC_ERROR 0x40000000
+
+/* SerDes Control */
+#define E1000_GEN_CTL_READY 0x80000000
+#define E1000_GEN_CTL_ADDRESS_SHIFT 8
+#define E1000_GEN_POLL_TIMEOUT 640
+
+#endif /* _IGBVF_DEFINES_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_main.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_main.c
new file mode 100644
index 00000000..cd189ecb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_main.c
@@ -0,0 +1,955 @@
+/*******************************************************************************
+
+ Intel(R) 82576 Virtual Function Linux driver
+ Copyright(c) 2009 Intel Corporation.
+
+ Copyright(c) 2010 Eric Keller <ekeller@princeton.edu>
+ Copyright(c) 2010 Red Hat Inc.
+ Alex Williamson <alex.williamson@redhat.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include "igbvf.h"
+
+/**
+ * igbvf_setup_tx_resources - allocate Tx resources (Descriptors)
+ *
+ * @v adapter e1000 private structure
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ **/
+int igbvf_setup_tx_resources ( struct igbvf_adapter *adapter )
+{
+ DBG ( "igbvf_setup_tx_resources\n" );
+
+ /* Allocate transmit descriptor ring memory.
+ It must not cross a 64K boundary because of hardware errata #23
+ so we use malloc_dma() requesting a 128 byte block that is
+ 128 byte aligned. This should guarantee that the memory
+ allocated will not cross a 64K boundary, because 128 is an
+ even multiple of 65536 ( 65536 / 128 == 512 ), so all possible
+ allocations of 128 bytes on a 128 byte boundary will not
+ cross 64K bytes.
+ */
+
+ adapter->tx_base =
+ malloc_dma ( adapter->tx_ring_size, adapter->tx_ring_size );
+
+ if ( ! adapter->tx_base ) {
+ return -ENOMEM;
+ }
+
+ memset ( adapter->tx_base, 0, adapter->tx_ring_size );
+
+ DBG ( "adapter->tx_base = %#08lx\n", virt_to_bus ( adapter->tx_base ) );
+
+ return 0;
+}
+
+/**
+ * igbvf_free_tx_resources - Free Tx Resources per Queue
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ **/
+void igbvf_free_tx_resources ( struct igbvf_adapter *adapter )
+{
+ DBG ( "igbvf_free_tx_resources\n" );
+
+ free_dma ( adapter->tx_base, adapter->tx_ring_size );
+}
+
+/**
+ * igbvf_free_rx_resources - Free Rx Resources
+ * @adapter: board private structure
+ *
+ * Free all receive software resources
+ **/
+void igbvf_free_rx_resources ( struct igbvf_adapter *adapter )
+{
+ int i;
+
+ DBG ( "igbvf_free_rx_resources\n" );
+
+ free_dma ( adapter->rx_base, adapter->rx_ring_size );
+
+ for ( i = 0; i < NUM_RX_DESC; i++ ) {
+ free_iob ( adapter->rx_iobuf[i] );
+ }
+}
+
+/**
+ * igbvf_refill_rx_ring - allocate Rx io_buffers
+ *
+ * @v adapter e1000 private structure
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ **/
+static int igbvf_refill_rx_ring ( struct igbvf_adapter *adapter )
+{
+ int i, rx_curr;
+ int rc = 0;
+ union e1000_adv_rx_desc *rx_curr_desc;
+ struct e1000_hw *hw = &adapter->hw;
+ struct io_buffer *iob;
+
+ DBGP ("igbvf_refill_rx_ring\n");
+
+ for ( i = 0; i < NUM_RX_DESC; i++ ) {
+ rx_curr = ( ( adapter->rx_curr + i ) % NUM_RX_DESC );
+ rx_curr_desc = adapter->rx_base + rx_curr;
+
+ if ( rx_curr_desc->wb.upper.status_error & E1000_RXD_STAT_DD )
+ continue;
+
+ if ( adapter->rx_iobuf[rx_curr] != NULL )
+ continue;
+
+ DBG2 ( "Refilling rx desc %d\n", rx_curr );
+
+ iob = alloc_iob ( MAXIMUM_ETHERNET_VLAN_SIZE );
+ adapter->rx_iobuf[rx_curr] = iob;
+
+ rx_curr_desc->wb.upper.status_error = 0;
+
+ if ( ! iob ) {
+ DBG ( "alloc_iob failed\n" );
+ rc = -ENOMEM;
+ break;
+ } else {
+ rx_curr_desc->read.pkt_addr = virt_to_bus ( iob->data );
+ rx_curr_desc->read.hdr_addr = 0;
+ ew32 ( RDT(0), rx_curr );
+ }
+ }
+ return rc;
+}
+
+/**
+ * igbvf_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+static void igbvf_irq_disable ( struct igbvf_adapter *adapter )
+{
+ struct e1000_hw *hw = &adapter->hw;
+
+ ew32 ( EIMC, ~0 );
+}
+
+/**
+ * igbvf_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ **/
+static void igbvf_irq_enable ( struct igbvf_adapter *adapter )
+{
+ struct e1000_hw *hw = &adapter->hw;
+
+ ew32 ( EIAC, IMS_ENABLE_MASK );
+ ew32 ( EIAM, IMS_ENABLE_MASK );
+ ew32 ( EIMS, IMS_ENABLE_MASK );
+}
+
+/**
+ * igbvf_irq - enable or Disable interrupts
+ *
+ * @v adapter e1000 adapter
+ * @v action requested interrupt action
+ **/
+static void igbvf_irq ( struct net_device *netdev, int enable )
+{
+ struct igbvf_adapter *adapter = netdev_priv ( netdev );
+
+ DBG ( "igbvf_irq\n" );
+
+ if ( enable ) {
+ igbvf_irq_enable ( adapter );
+ } else {
+ igbvf_irq_disable ( adapter );
+ }
+}
+
+/**
+ * igbvf_process_tx_packets - process transmitted packets
+ *
+ * @v netdev network interface device structure
+ **/
+static void igbvf_process_tx_packets ( struct net_device *netdev )
+{
+ struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ uint32_t i;
+ uint32_t tx_status;
+ union e1000_adv_tx_desc *tx_curr_desc;
+
+ /* Check status of transmitted packets
+ */
+ DBGP ( "process_tx_packets: tx_head = %d, tx_tail = %d\n", adapter->tx_head,
+ adapter->tx_tail );
+
+ while ( ( i = adapter->tx_head ) != adapter->tx_tail ) {
+
+ tx_curr_desc = ( void * ) ( adapter->tx_base ) +
+ ( i * sizeof ( *adapter->tx_base ) );
+
+ tx_status = tx_curr_desc->wb.status;
+ DBG ( " tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
+ DBG ( " tx_status = %#08x\n", tx_status );
+
+ /* if the packet at tx_head is not owned by hardware it is for us */
+ if ( ! ( tx_status & E1000_TXD_STAT_DD ) )
+ break;
+
+ DBG ( "Sent packet. tx_head: %d tx_tail: %d tx_status: %#08x\n",
+ adapter->tx_head, adapter->tx_tail, tx_status );
+
+ netdev_tx_complete ( netdev, adapter->tx_iobuf[i] );
+ DBG ( "Success transmitting packet, tx_status: %#08x\n",
+ tx_status );
+
+ /* Decrement count of used descriptors, clear this descriptor
+ */
+ adapter->tx_fill_ctr--;
+ memset ( tx_curr_desc, 0, sizeof ( *tx_curr_desc ) );
+
+ adapter->tx_head = ( adapter->tx_head + 1 ) % NUM_TX_DESC;
+ }
+}
+
+/**
+ * igbvf_process_rx_packets - process received packets
+ *
+ * @v netdev network interface device structure
+ **/
+static void igbvf_process_rx_packets ( struct net_device *netdev )
+{
+ struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ struct e1000_hw *hw = &adapter->hw;
+ uint32_t i;
+ uint32_t rx_status;
+ uint32_t rx_len;
+ uint32_t rx_err;
+ union e1000_adv_rx_desc *rx_curr_desc;
+
+ DBGP ( "igbvf_process_rx_packets\n" );
+
+ /* Process received packets
+ */
+ while ( 1 ) {
+ i = adapter->rx_curr;
+
+ rx_curr_desc = ( void * ) ( adapter->rx_base ) +
+ ( i * sizeof ( *adapter->rx_base ) );
+ rx_status = rx_curr_desc->wb.upper.status_error;
+
+ DBG2 ( "Before DD Check RX_status: %#08x, rx_curr: %d\n",
+ rx_status, i );
+
+ if ( ! ( rx_status & E1000_RXD_STAT_DD ) )
+ break;
+
+ if ( adapter->rx_iobuf[i] == NULL )
+ break;
+
+ DBG ( "E1000_RCTL = %#08x\n", er32 (RCTL) );
+
+ rx_len = rx_curr_desc->wb.upper.length;
+
+ DBG ( "Received packet, rx_curr: %d rx_status: %#08x rx_len: %d\n",
+ i, rx_status, rx_len );
+
+ rx_err = rx_status;
+
+ iob_put ( adapter->rx_iobuf[i], rx_len );
+
+ if ( rx_err & E1000_RXDEXT_ERR_FRAME_ERR_MASK ) {
+
+ netdev_rx_err ( netdev, adapter->rx_iobuf[i], -EINVAL );
+ DBG ( "igbvf_process_rx_packets: Corrupted packet received!"
+ " rx_err: %#08x\n", rx_err );
+ } else {
+ /* Add this packet to the receive queue. */
+ netdev_rx ( netdev, adapter->rx_iobuf[i] );
+ }
+ adapter->rx_iobuf[i] = NULL;
+
+ memset ( rx_curr_desc, 0, sizeof ( *rx_curr_desc ) );
+
+ adapter->rx_curr = ( adapter->rx_curr + 1 ) % NUM_RX_DESC;
+ }
+}
+
+/**
+ * igbvf_poll - Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void igbvf_poll ( struct net_device *netdev )
+{
+ struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ uint32_t rx_status;
+ union e1000_adv_rx_desc *rx_curr_desc;
+
+ DBGP ( "igbvf_poll\n" );
+
+ rx_curr_desc = ( void * ) ( adapter->rx_base ) +
+ ( adapter->rx_curr * sizeof ( *adapter->rx_base ) );
+ rx_status = rx_curr_desc->wb.upper.status_error;
+
+ if ( ! ( rx_status & E1000_RXD_STAT_DD ) )
+ return;
+
+ igbvf_process_tx_packets ( netdev );
+
+ igbvf_process_rx_packets ( netdev );
+
+ igbvf_refill_rx_ring ( adapter );
+}
+
+/**
+ * igbvf_config_collision_dist_generic - Configure collision distance
+ * @hw: pointer to the HW structure
+ *
+ * Configures the collision distance to the default value and is used
+ * during link setup. Currently no func pointer exists and all
+ * implementations are handled in the generic version of this function.
+ **/
+void igbvf_config_collision_dist ( struct e1000_hw *hw )
+{
+ u32 tctl;
+
+ DBG ("igbvf_config_collision_dist");
+
+ tctl = er32 (TCTL);
+
+ tctl &= ~E1000_TCTL_COLD;
+ tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+
+ ew32 (TCTL, tctl);
+ e1e_flush();
+}
+
+/**
+ * igbvf_configure_tx - Configure Transmit Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx unit of the MAC after a reset.
+ **/
+static void igbvf_configure_tx ( struct igbvf_adapter *adapter )
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 tctl, txdctl;
+
+ DBG ( "igbvf_configure_tx\n" );
+
+ /* disable transmits while setting up the descriptors */
+ tctl = er32 ( TCTL );
+ ew32 ( TCTL, tctl & ~E1000_TCTL_EN );
+ e1e_flush();
+ mdelay (10);
+
+ ew32 ( TDBAH(0), 0 );
+ ew32 ( TDBAL(0), virt_to_bus ( adapter->tx_base ) );
+ ew32 ( TDLEN(0), adapter->tx_ring_size );
+
+ DBG ( "E1000_TDBAL(0): %#08x\n", er32 ( TDBAL(0) ) );
+ DBG ( "E1000_TDLEN(0): %d\n", er32 ( TDLEN(0) ) );
+
+ /* Setup the HW Tx Head and Tail descriptor pointers */
+ ew32 ( TDH(0), 0 );
+ ew32 ( TDT(0), 0 );
+
+ adapter->tx_head = 0;
+ adapter->tx_tail = 0;
+ adapter->tx_fill_ctr = 0;
+
+ txdctl = er32(TXDCTL(0));
+ txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
+ ew32 ( TXDCTL(0), txdctl );
+
+ txdctl = er32 ( TXDCTL(0) );
+ txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
+ ew32 ( TXDCTL(0), txdctl );
+
+ /* Setup Transmit Descriptor Settings for eop descriptor */
+ adapter->txd_cmd = E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_IFCS;
+
+ /* Advanced descriptor */
+ adapter->txd_cmd |= E1000_ADVTXD_DCMD_DEXT;
+
+ /* (not part of cmd, but in same 32 bit word...) */
+ adapter->txd_cmd |= E1000_ADVTXD_DTYP_DATA;
+
+ /* enable Report Status bit */
+ adapter->txd_cmd |= E1000_ADVTXD_DCMD_RS;
+
+ /* Program the Transmit Control Register */
+ tctl &= ~E1000_TCTL_CT;
+ tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
+ (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
+
+ igbvf_config_collision_dist ( hw );
+
+ /* Enable transmits */
+ tctl |= E1000_TCTL_EN;
+ ew32(TCTL, tctl);
+ e1e_flush();
+}
+
+/* igbvf_reset - bring the hardware into a known good state
+ *
+ * This function boots the hardware and enables some settings that
+ * require a configuration cycle of the hardware - those cannot be
+ * set/changed during runtime. After reset the device needs to be
+ * properly configured for Rx, Tx etc.
+ */
+void igbvf_reset ( struct igbvf_adapter *adapter )
+{
+ struct e1000_mac_info *mac = &adapter->hw.mac;
+ struct net_device *netdev = adapter->netdev;
+ struct e1000_hw *hw = &adapter->hw;
+
+ /* Allow time for pending master requests to run */
+ if ( mac->ops.reset_hw(hw) )
+ DBG ("PF still resetting\n");
+
+ mac->ops.init_hw ( hw );
+
+ if ( is_valid_ether_addr(adapter->hw.mac.addr) ) {
+ memcpy ( netdev->hw_addr, adapter->hw.mac.addr, ETH_ALEN );
+ }
+}
+
+extern void igbvf_init_function_pointers_vf(struct e1000_hw *hw);
+
+/**
+ * igbvf_sw_init - Initialize general software structures (struct igbvf_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * igbvf_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ **/
+static int __devinit igbvf_sw_init ( struct igbvf_adapter *adapter )
+{
+ struct e1000_hw *hw = &adapter->hw;
+ struct pci_device *pdev = adapter->pdev;
+ int rc;
+
+ /* PCI config space info */
+
+ hw->vendor_id = pdev->vendor;
+ hw->device_id = pdev->device;
+
+ pci_read_config_byte ( pdev, PCI_REVISION_ID, &hw->revision_id );
+
+ pci_read_config_word ( pdev, PCI_COMMAND, &hw->bus.pci_cmd_word );
+
+ adapter->max_frame_size = MAXIMUM_ETHERNET_VLAN_SIZE + ETH_HLEN + ETH_FCS_LEN;
+ adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+
+ /* Set various function pointers */
+ igbvf_init_function_pointers_vf ( &adapter->hw );
+
+ rc = adapter->hw.mac.ops.init_params ( &adapter->hw );
+ if (rc) {
+ DBG ("hw.mac.ops.init_params(&adapter->hw) Failure\n");
+ return rc;
+ }
+
+ rc = adapter->hw.mbx.ops.init_params ( &adapter->hw );
+ if (rc) {
+ DBG ("hw.mbx.ops.init_params(&adapter->hw) Failure\n");
+ return rc;
+ }
+
+ /* Explicitly disable IRQ since the NIC can be in any state. */
+ igbvf_irq_disable ( adapter );
+
+ return 0;
+}
+
+/**
+ * igbvf_setup_srrctl - configure the receive control registers
+ * @adapter: Board private structure
+ **/
+static void igbvf_setup_srrctl ( struct igbvf_adapter *adapter )
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 srrctl = 0;
+
+ DBG ( "igbvf_setup_srrctl\n" );
+
+ srrctl &= ~(E1000_SRRCTL_DESCTYPE_MASK |
+ E1000_SRRCTL_BSIZEHDR_MASK |
+ E1000_SRRCTL_BSIZEPKT_MASK);
+
+ /* Enable queue drop to avoid head of line blocking */
+ srrctl |= E1000_SRRCTL_DROP_EN;
+
+ /* Setup buffer sizes */
+ srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+ srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
+
+ ew32 ( SRRCTL(0), srrctl );
+}
+
+/**
+ * igbvf_configure_rx - Configure 8254x Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Rx unit of the MAC after a reset.
+ **/
+static void igbvf_configure_rx ( struct igbvf_adapter *adapter )
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 rxdctl;
+
+ DBG ( "igbvf_configure_rx\n" );
+
+ /* disable receives */
+ rxdctl = er32 ( RXDCTL(0) );
+ ew32 ( RXDCTL(0), rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE );
+ msleep ( 10 );
+
+ /*
+ * Setup the HW Rx Head and Tail Descriptor Pointers and
+ * the Base and Length of the Rx Descriptor Ring
+ */
+ ew32 ( RDBAL(0), virt_to_bus (adapter->rx_base) );
+ ew32 ( RDBAH(0), 0 );
+ ew32 ( RDLEN(0), adapter->rx_ring_size );
+ adapter->rx_curr = 0;
+ ew32 ( RDH(0), 0 );
+ ew32 ( RDT(0), 0 );
+
+ rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
+ rxdctl &= 0xFFF00000;
+ rxdctl |= IGBVF_RX_PTHRESH;
+ rxdctl |= IGBVF_RX_HTHRESH << 8;
+ rxdctl |= IGBVF_RX_WTHRESH << 16;
+
+ igbvf_rlpml_set_vf ( hw, adapter->max_frame_size );
+
+ /* enable receives */
+ ew32 ( RXDCTL(0), rxdctl );
+ ew32 ( RDT(0), NUM_RX_DESC );
+}
+
+/**
+ * igbvf_setup_rx_resources - allocate Rx resources (Descriptors)
+ *
+ * @v adapter e1000 private structure
+ **/
+int igbvf_setup_rx_resources ( struct igbvf_adapter *adapter )
+{
+ int i;
+ union e1000_adv_rx_desc *rx_curr_desc;
+ struct io_buffer *iob;
+
+ DBG ( "igbvf_setup_rx_resources\n" );
+
+ /* Allocate receive descriptor ring memory.
+ It must not cross a 64K boundary because of hardware errata
+ */
+
+ adapter->rx_base =
+ malloc_dma ( adapter->rx_ring_size, adapter->rx_ring_size );
+
+ if ( ! adapter->rx_base ) {
+ return -ENOMEM;
+ }
+ memset ( adapter->rx_base, 0, adapter->rx_ring_size );
+
+ for ( i = 0; i < NUM_RX_DESC; i++ ) {
+ rx_curr_desc = adapter->rx_base + i;
+ iob = alloc_iob ( MAXIMUM_ETHERNET_VLAN_SIZE );
+ adapter->rx_iobuf[i] = iob;
+ rx_curr_desc->wb.upper.status_error = 0;
+ if ( ! iob ) {
+ DBG ( "alloc_iob failed\n" );
+ return -ENOMEM;
+ } else {
+ rx_curr_desc->read.pkt_addr = virt_to_bus ( iob->data );
+ rx_curr_desc->read.hdr_addr = 0;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * igbvf_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP). At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ **/
+static int igbvf_open ( struct net_device *netdev )
+{
+ struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ int err;
+
+ DBG ("igbvf_open\n");
+
+ /* allocate transmit descriptors */
+ err = igbvf_setup_tx_resources ( adapter );
+ if (err) {
+ DBG ( "Error setting up TX resources!\n" );
+ goto err_setup_tx;
+ }
+
+ igbvf_configure_tx ( adapter );
+
+ igbvf_setup_srrctl( adapter );
+
+ err = igbvf_setup_rx_resources( adapter );
+ if (err) {
+ DBG ( "Error setting up RX resources!\n" );
+ goto err_setup_rx;
+ }
+
+ igbvf_configure_rx ( adapter );
+
+ return 0;
+
+err_setup_rx:
+ DBG ( "err_setup_rx\n" );
+ igbvf_free_tx_resources ( adapter );
+ return err;
+
+err_setup_tx:
+ DBG ( "err_setup_tx\n" );
+ igbvf_reset ( adapter );
+
+ return err;
+}
+
+/**
+ * igbvf_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS. The hardware is still under the drivers control, but
+ * needs to be disabled. A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ **/
+static void igbvf_close ( struct net_device *netdev )
+{
+ struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ struct e1000_hw *hw = &adapter->hw;
+ uint32_t rxdctl;
+
+ DBG ( "igbvf_close\n" );
+
+ /* Disable and acknowledge interrupts */
+ igbvf_irq_disable ( adapter );
+ er32(EICR);
+
+ /* disable receives */
+ rxdctl = er32 ( RXDCTL(0) );
+ ew32 ( RXDCTL(0), rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE );
+ mdelay ( 10 );
+
+ igbvf_reset ( adapter );
+
+ igbvf_free_tx_resources( adapter );
+ igbvf_free_rx_resources( adapter );
+}
+
+/**
+ * igbvf_transmit - Transmit a packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ */
+static int igbvf_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
+{
+ struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ struct e1000_hw *hw = &adapter->hw;
+ uint32_t tx_curr = adapter->tx_tail;
+ union e1000_adv_tx_desc *tx_curr_desc;
+
+ DBGP ("igbvf_transmit\n");
+
+ if ( adapter->tx_fill_ctr == NUM_TX_DESC ) {
+ DBG ("TX overflow\n");
+ return -ENOBUFS;
+ }
+
+ /* Save pointer to iobuf we have been given to transmit,
+ netdev_tx_complete() will need it later
+ */
+ adapter->tx_iobuf[tx_curr] = iobuf;
+
+ tx_curr_desc = ( void * ) ( adapter->tx_base ) +
+ ( tx_curr * sizeof ( *adapter->tx_base ) );
+
+ DBG ( "tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
+ DBG ( "tx_curr_desc + 16 = %#08lx\n", virt_to_bus ( tx_curr_desc ) + 16 );
+ DBG ( "iobuf->data = %#08lx\n", virt_to_bus ( iobuf->data ) );
+
+ /* Add the packet to TX ring
+ */
+ tx_curr_desc->read.buffer_addr = virt_to_bus ( iobuf->data );
+ tx_curr_desc->read.cmd_type_len = adapter->txd_cmd |(iob_len ( iobuf )) ;
+ // minus hdr_len ????
+ tx_curr_desc->read.olinfo_status = ((iob_len ( iobuf )) << E1000_ADVTXD_PAYLEN_SHIFT);
+
+ DBG ( "TX fill: %d tx_curr: %d addr: %#08lx len: %zd\n", adapter->tx_fill_ctr,
+ tx_curr, virt_to_bus ( iobuf->data ), iob_len ( iobuf ) );
+
+ /* Point to next free descriptor */
+ adapter->tx_tail = ( adapter->tx_tail + 1 ) % NUM_TX_DESC;
+ adapter->tx_fill_ctr++;
+
+ /* Write new tail to NIC, making packet available for transmit
+ */
+ ew32 ( TDT(0), adapter->tx_tail );
+ e1e_flush ();
+
+ return 0;
+}
+
+/** igbvf net device operations */
+static struct net_device_operations igbvf_operations = {
+ .open = igbvf_open,
+ .close = igbvf_close,
+ .transmit = igbvf_transmit,
+ .poll = igbvf_poll,
+ .irq = igbvf_irq,
+};
+
+/**
+ * igbvf_get_hw_control - get control of the h/w from f/w
+ * @adapter: address of board private structure
+ *
+ * igb_get_hw_control sets CTRL_EXT:DRV_LOAD bit.
+ * For ASF and Pass Through versions of f/w this means that
+ * the driver is loaded.
+ *
+ **/
+void igbvf_get_hw_control ( struct igbvf_adapter *adapter )
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 ctrl_ext;
+
+ /* Let firmware know the driver has taken over */
+ ctrl_ext = er32 ( CTRL_EXT );
+ ew32 ( CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD );
+}
+
+/**
+ * igbvf_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in igbvf_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * igbvf_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ **/
+int igbvf_probe ( struct pci_device *pdev )
+{
+ int err;
+ struct net_device *netdev;
+ struct igbvf_adapter *adapter;
+ unsigned long mmio_start, mmio_len;
+ struct e1000_hw *hw;
+
+ DBG ( "igbvf_probe\n" );
+
+ err = -ENOMEM;
+
+ /* Allocate net device ( also allocates memory for netdev->priv
+ and makes netdev-priv point to it ) */
+ netdev = alloc_etherdev ( sizeof ( struct igbvf_adapter ) );
+ if ( ! netdev )
+ goto err_alloc_etherdev;
+
+ /* Associate igbvf-specific network operations operations with
+ * generic network device layer */
+ netdev_init ( netdev, &igbvf_operations );
+
+ /* Associate this network device with given PCI device */
+ pci_set_drvdata ( pdev, netdev );
+ netdev->dev = &pdev->dev;
+
+ /* Initialize driver private storage */
+ adapter = netdev_priv ( netdev );
+ memset ( adapter, 0, ( sizeof ( *adapter ) ) );
+
+ adapter->pdev = pdev;
+
+ adapter->ioaddr = pdev->ioaddr;
+ adapter->hw.io_base = pdev->ioaddr;
+
+ hw = &adapter->hw;
+ hw->vendor_id = pdev->vendor;
+ hw->device_id = pdev->device;
+
+ adapter->irqno = pdev->irq;
+ adapter->netdev = netdev;
+ adapter->hw.back = adapter;
+
+ adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+ adapter->max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN;
+
+ adapter->tx_ring_size = sizeof ( *adapter->tx_base ) * NUM_TX_DESC;
+ adapter->rx_ring_size = sizeof ( *adapter->rx_base ) * NUM_RX_DESC;
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pdev );
+
+ err = -EIO;
+
+ mmio_start = pci_bar_start ( pdev, PCI_BASE_ADDRESS_0 );
+ mmio_len = pci_bar_size ( pdev, PCI_BASE_ADDRESS_0 );
+
+ DBG ( "mmio_start: %#08lx\n", mmio_start );
+ DBG ( "mmio_len: %#08lx\n", mmio_len );
+
+ adapter->hw.hw_addr = ioremap ( mmio_start, mmio_len );
+ DBG ( "adapter->hw.hw_addr: %p\n", adapter->hw.hw_addr );
+
+ if ( ! adapter->hw.hw_addr ) {
+ DBG ( "err_ioremap\n" );
+ goto err_ioremap;
+ }
+
+ /* setup adapter struct */
+ err = igbvf_sw_init ( adapter );
+ if (err) {
+ DBG ( "err_sw_init\n" );
+ goto err_sw_init;
+ }
+
+ /* reset the controller to put the device in a known good state */
+ err = hw->mac.ops.reset_hw ( hw );
+ if ( err ) {
+ DBG ("PF still in reset state, assigning new address\n");
+ netdev->hw_addr[0] = 0x21;
+ netdev->hw_addr[1] = 0x21;
+ netdev->hw_addr[2] = 0x21;
+ netdev->hw_addr[3] = 0x21;
+ netdev->hw_addr[4] = 0x21;
+ netdev->hw_addr[5] = 0x21;
+ netdev->hw_addr[6] = 0x21;
+ } else {
+ err = hw->mac.ops.read_mac_addr(hw);
+ if (err) {
+ DBG ("Error reading MAC address\n");
+ goto err_hw_init;
+ }
+ }
+
+ memcpy ( netdev->hw_addr, adapter->hw.mac.addr, ETH_ALEN );
+
+ if ( ! is_valid_ether_addr( netdev->hw_addr ) ) {
+ DBG ("Invalid MAC Address: "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ netdev->hw_addr[0], netdev->hw_addr[1],
+ netdev->hw_addr[2], netdev->hw_addr[3],
+ netdev->hw_addr[4], netdev->hw_addr[5]);
+ err = -EIO;
+ goto err_hw_init;
+ }
+
+ /* reset the hardware with the new settings */
+ igbvf_reset ( adapter );
+
+ /* let the f/w know that the h/w is now under the control of the
+ * driver. */
+ igbvf_get_hw_control ( adapter );
+
+ /* Mark as link up; we don't yet handle link state */
+ netdev_link_up ( netdev );
+
+ if ( ( err = register_netdev ( netdev ) ) != 0) {
+ DBG ( "err_register\n" );
+ goto err_register;
+ }
+
+ DBG ("igbvf_probe_succeeded\n");
+
+ return 0;
+
+err_register:
+err_hw_init:
+err_sw_init:
+ iounmap ( adapter->hw.hw_addr );
+err_ioremap:
+ netdev_put ( netdev );
+err_alloc_etherdev:
+ return err;
+}
+
+/**
+ * igbvf_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * igbvf_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device. The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ **/
+void igbvf_remove ( struct pci_device *pdev )
+{
+ struct net_device *netdev = pci_get_drvdata ( pdev );
+ struct igbvf_adapter *adapter = netdev_priv ( netdev );
+
+ DBG ( "igbvf_remove\n" );
+
+ if ( adapter->hw.flash_address )
+ iounmap ( adapter->hw.flash_address );
+ if ( adapter->hw.hw_addr )
+ iounmap ( adapter->hw.hw_addr );
+
+ unregister_netdev ( netdev );
+ igbvf_reset ( adapter );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+static struct pci_device_id igbvf_pci_tbl[] = {
+ PCI_ROM(0x8086, 0x10CA, "igbvf", "E1000_DEV_ID_82576_VF", 0),
+ PCI_ROM(0x8086, 0x1520, "i350vf", "E1000_DEV_ID_I350_VF", 0),
+};
+
+
+struct pci_driver igbvf_driver __pci_driver = {
+ .ids = igbvf_pci_tbl,
+ .id_count = (sizeof(igbvf_pci_tbl) / sizeof(igbvf_pci_tbl[0])),
+ .probe = igbvf_probe,
+ .remove = igbvf_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_mbx.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_mbx.c
new file mode 100644
index 00000000..65809389
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_mbx.c
@@ -0,0 +1,404 @@
+/*******************************************************************************
+
+ Intel(R) 82576 Virtual Function Linux driver
+ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include "igbvf_mbx.h"
+
+/**
+ * igbvf_poll_for_msg - Wait for message notification
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully received a message notification
+ **/
+static s32 igbvf_poll_for_msg(struct e1000_hw *hw, u16 mbx_id)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ int countdown = mbx->timeout;
+
+ DEBUGFUNC("igbvf_poll_for_msg");
+
+ if (!countdown || !mbx->ops.check_for_msg)
+ goto out;
+
+ while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
+ countdown--;
+ if (!countdown)
+ break;
+ usec_delay(mbx->usec_delay);
+ }
+
+ /* if we failed, all future posted messages fail until reset */
+ if (!countdown)
+ mbx->timeout = 0;
+out:
+ return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
+}
+
+/**
+ * igbvf_poll_for_ack - Wait for message acknowledgement
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully received a message acknowledgement
+ **/
+static s32 igbvf_poll_for_ack(struct e1000_hw *hw, u16 mbx_id)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ int countdown = mbx->timeout;
+
+ DEBUGFUNC("igbvf_poll_for_ack");
+
+ if (!countdown || !mbx->ops.check_for_ack)
+ goto out;
+
+ while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
+ countdown--;
+ if (!countdown)
+ break;
+ usec_delay(mbx->usec_delay);
+ }
+
+ /* if we failed, all future posted messages fail until reset */
+ if (!countdown)
+ mbx->timeout = 0;
+out:
+ return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
+}
+
+/**
+ * igbvf_read_posted_mbx - Wait for message notification and receive message
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully received a message notification and
+ * copied it into the receive buffer.
+ **/
+static s32 igbvf_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
+ u16 mbx_id)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = -E1000_ERR_MBX;
+
+ DEBUGFUNC("igbvf_read_posted_mbx");
+
+ if (!mbx->ops.read)
+ goto out;
+
+ ret_val = igbvf_poll_for_msg(hw, mbx_id);
+
+ /* if ack received read message, otherwise we timed out */
+ if (!ret_val)
+ ret_val = mbx->ops.read(hw, msg, size, mbx_id);
+out:
+ return ret_val;
+}
+
+/**
+ * igbvf_write_posted_mbx - Write a message to the mailbox, wait for ack
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully copied message into the buffer and
+ * received an ack to that message within delay * timeout period
+ **/
+static s32 igbvf_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
+ u16 mbx_id)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ s32 ret_val = -E1000_ERR_MBX;
+
+ DEBUGFUNC("igbvf_write_posted_mbx");
+
+ /* exit if either we can't write or there isn't a defined timeout */
+ if (!mbx->ops.write || !mbx->timeout)
+ goto out;
+
+ /* send msg */
+ ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+
+ /* if msg sent wait until we receive an ack */
+ if (!ret_val)
+ ret_val = igbvf_poll_for_ack(hw, mbx_id);
+out:
+ return ret_val;
+}
+
+/**
+ * igbvf_init_mbx_ops_generic - Initialize NVM function pointers
+ * @hw: pointer to the HW structure
+ *
+ * Setups up the function pointers to no-op functions
+ **/
+void igbvf_init_mbx_ops_generic(struct e1000_hw *hw)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ mbx->ops.read_posted = igbvf_read_posted_mbx;
+ mbx->ops.write_posted = igbvf_write_posted_mbx;
+}
+
+/**
+ * igbvf_read_v2p_mailbox - read v2p mailbox
+ * @hw: pointer to the HW structure
+ *
+ * This function is used to read the v2p mailbox without losing the read to
+ * clear status bits.
+ **/
+static u32 igbvf_read_v2p_mailbox(struct e1000_hw *hw)
+{
+ u32 v2p_mailbox = E1000_READ_REG(hw, E1000_V2PMAILBOX(0));
+
+ v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox;
+ hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS;
+
+ return v2p_mailbox;
+}
+
+/**
+ * igbvf_check_for_bit_vf - Determine if a status bit was set
+ * @hw: pointer to the HW structure
+ * @mask: bitmask for bits to be tested and cleared
+ *
+ * This function is used to check for the read to clear bits within
+ * the V2P mailbox.
+ **/
+static s32 igbvf_check_for_bit_vf(struct e1000_hw *hw, u32 mask)
+{
+ u32 v2p_mailbox = igbvf_read_v2p_mailbox(hw);
+ s32 ret_val = -E1000_ERR_MBX;
+
+ if (v2p_mailbox & mask)
+ ret_val = E1000_SUCCESS;
+
+ hw->dev_spec.vf.v2p_mailbox &= ~mask;
+
+ return ret_val;
+}
+
+/**
+ * igbvf_check_for_msg_vf - checks to see if the PF has sent mail
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns SUCCESS if the PF has set the Status bit or else ERR_MBX
+ **/
+static s32 igbvf_check_for_msg_vf(struct e1000_hw *hw, u16 mbx_id __unused)
+{
+ s32 ret_val = -E1000_ERR_MBX;
+
+ DEBUGFUNC("igbvf_check_for_msg_vf");
+
+ if (!igbvf_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) {
+ ret_val = E1000_SUCCESS;
+ hw->mbx.stats.reqs++;
+ }
+
+ return ret_val;
+}
+
+/**
+ * igbvf_check_for_ack_vf - checks to see if the PF has ACK'd
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
+ **/
+static s32 igbvf_check_for_ack_vf(struct e1000_hw *hw, u16 mbx_id __unused)
+{
+ s32 ret_val = -E1000_ERR_MBX;
+
+ DEBUGFUNC("igbvf_check_for_ack_vf");
+
+ if (!igbvf_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) {
+ ret_val = E1000_SUCCESS;
+ hw->mbx.stats.acks++;
+ }
+
+ return ret_val;
+}
+
+/**
+ * igbvf_check_for_rst_vf - checks to see if the PF has reset
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns true if the PF has set the reset done bit or else false
+ **/
+static s32 igbvf_check_for_rst_vf(struct e1000_hw *hw, u16 mbx_id __unused)
+{
+ s32 ret_val = -E1000_ERR_MBX;
+
+ DEBUGFUNC("igbvf_check_for_rst_vf");
+
+ if (!igbvf_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD |
+ E1000_V2PMAILBOX_RSTI))) {
+ ret_val = E1000_SUCCESS;
+ hw->mbx.stats.rsts++;
+ }
+
+ return ret_val;
+}
+
+/**
+ * igbvf_obtain_mbx_lock_vf - obtain mailbox lock
+ * @hw: pointer to the HW structure
+ *
+ * return SUCCESS if we obtained the mailbox lock
+ **/
+static s32 igbvf_obtain_mbx_lock_vf(struct e1000_hw *hw)
+{
+ s32 ret_val = -E1000_ERR_MBX;
+
+ DEBUGFUNC("igbvf_obtain_mbx_lock_vf");
+
+ /* Take ownership of the buffer */
+ E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
+
+ /* reserve mailbox for vf use */
+ if (igbvf_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU)
+ ret_val = E1000_SUCCESS;
+
+ return ret_val;
+}
+
+/**
+ * igbvf_write_mbx_vf - Write a message to the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully copied message into the buffer
+ **/
+static s32 igbvf_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size,
+ u16 mbx_id __unused)
+{
+ s32 ret_val;
+ u16 i;
+
+
+ DEBUGFUNC("igbvf_write_mbx_vf");
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ ret_val = igbvf_obtain_mbx_lock_vf(hw);
+ if (ret_val)
+ goto out_no_write;
+
+ /* flush msg and acks as we are overwriting the message buffer */
+ igbvf_check_for_msg_vf(hw, 0);
+ igbvf_check_for_ack_vf(hw, 0);
+
+ /* copy the caller specified message to the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ E1000_WRITE_REG_ARRAY(hw, E1000_VMBMEM(0), i, msg[i]);
+
+ /* update stats */
+ hw->mbx.stats.msgs_tx++;
+
+ /* Drop VFU and interrupt the PF to tell it a message has been sent */
+ E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_REQ);
+
+out_no_write:
+ return ret_val;
+}
+
+/**
+ * igbvf_read_mbx_vf - Reads a message from the inbox intended for vf
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to read
+ *
+ * returns SUCCESS if it successfuly read message from buffer
+ **/
+static s32 igbvf_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size,
+ u16 mbx_id __unused)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 i;
+
+ DEBUGFUNC("igbvf_read_mbx_vf");
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ ret_val = igbvf_obtain_mbx_lock_vf(hw);
+ if (ret_val)
+ goto out_no_read;
+
+ /* copy the message from the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ msg[i] = E1000_READ_REG_ARRAY(hw, E1000_VMBMEM(0), i);
+
+ /* Acknowledge receipt and release mailbox, then we're done */
+ E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_ACK);
+
+ /* update stats */
+ hw->mbx.stats.msgs_rx++;
+
+out_no_read:
+ return ret_val;
+}
+
+/**
+ * igbvf_init_mbx_params_vf - set initial values for vf mailbox
+ * @hw: pointer to the HW structure
+ *
+ * Initializes the hw->mbx struct to correct values for vf mailbox
+ */
+s32 igbvf_init_mbx_params_vf(struct e1000_hw *hw)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+
+ /* start mailbox as timed out and let the reset_hw call set the timeout
+ * value to begin communications */
+ mbx->timeout = 0;
+ mbx->usec_delay = E1000_VF_MBX_INIT_DELAY;
+
+ mbx->size = E1000_VFMAILBOX_SIZE;
+
+ mbx->ops.read = igbvf_read_mbx_vf;
+ mbx->ops.write = igbvf_write_mbx_vf;
+ mbx->ops.read_posted = igbvf_read_posted_mbx;
+ mbx->ops.write_posted = igbvf_write_posted_mbx;
+ mbx->ops.check_for_msg = igbvf_check_for_msg_vf;
+ mbx->ops.check_for_ack = igbvf_check_for_ack_vf;
+ mbx->ops.check_for_rst = igbvf_check_for_rst_vf;
+
+ mbx->stats.msgs_tx = 0;
+ mbx->stats.msgs_rx = 0;
+ mbx->stats.reqs = 0;
+ mbx->stats.acks = 0;
+ mbx->stats.rsts = 0;
+
+ return E1000_SUCCESS;
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_mbx.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_mbx.h
new file mode 100644
index 00000000..c21af6c0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_mbx.h
@@ -0,0 +1,87 @@
+/*******************************************************************************
+
+ Intel(R) 82576 Virtual Function Linux driver
+ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#ifndef _IGBVF_MBX_H_
+#define _IGBVF_MBX_H_
+
+#include "igbvf_vf.h"
+
+/* Define mailbox specific registers */
+#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n)))
+#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
+
+/* Define mailbox register bits */
+#define E1000_V2PMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */
+#define E1000_V2PMAILBOX_ACK 0x00000002 /* Ack PF message received */
+#define E1000_V2PMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
+#define E1000_V2PMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
+#define E1000_V2PMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */
+#define E1000_V2PMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */
+#define E1000_V2PMAILBOX_RSTI 0x00000040 /* PF has reset indication */
+#define E1000_V2PMAILBOX_RSTD 0x00000080 /* PF has indicated reset done */
+#define E1000_V2PMAILBOX_R2C_BITS 0x000000B0 /* All read to clear bits */
+
+#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
+
+/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the
+ * PF. The reverse is true if it is E1000_PF_*.
+ * Message ACK's are the value or'd with 0xF0000000
+ */
+#define E1000_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with
+ * this are the ACK */
+#define E1000_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with
+ * this are the NACK */
+#define E1000_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still
+ clear to send requests */
+#define E1000_VT_MSGINFO_SHIFT 16
+/* bits 23:16 are used for exra info for certain messages */
+#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT)
+
+#define E1000_VF_RESET 0x01 /* VF requests reset */
+#define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests to set MAC addr */
+#define E1000_VF_SET_MULTICAST 0x03 /* VF requests to set MC addr */
+#define E1000_VF_SET_MULTICAST_COUNT_MASK (0x1F << E1000_VT_MSGINFO_SHIFT)
+#define E1000_VF_SET_MULTICAST_OVERFLOW (0x80 << E1000_VT_MSGINFO_SHIFT)
+#define E1000_VF_SET_VLAN 0x04 /* VF requests to set VLAN */
+#define E1000_VF_SET_VLAN_ADD (0x01 << E1000_VT_MSGINFO_SHIFT)
+#define E1000_VF_SET_LPE 0x05 /* VF requests to set VMOLR.LPE */
+#define E1000_VF_SET_PROMISC 0x06 /*VF requests to clear VMOLR.ROPE/MPME*/
+#define E1000_VF_SET_PROMISC_UNICAST (0x01 << E1000_VT_MSGINFO_SHIFT)
+#define E1000_VF_SET_PROMISC_MULTICAST (0x02 << E1000_VT_MSGINFO_SHIFT)
+
+#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */
+
+#define E1000_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */
+#define E1000_VF_MBX_INIT_DELAY 500 /* microseconds between retries */
+
+void igbvf_init_mbx_ops_generic(struct e1000_hw *hw);
+s32 igbvf_init_mbx_params_vf(struct e1000_hw *);
+
+#endif /* _IGBVF_MBX_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_osdep.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_osdep.h
new file mode 100644
index 00000000..259b9ec3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_osdep.h
@@ -0,0 +1,121 @@
+/*******************************************************************************
+
+ Intel(R) 82576 Virtual Function Linux driver
+ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/* glue for the OS-dependent part of igbvf
+ * includes register access macros
+ */
+
+#ifndef _IGBVF_OSDEP_H_
+#define _IGBVF_OSDEP_H_
+
+#define u8 unsigned char
+#define bool boolean_t
+#define dma_addr_t unsigned long
+#define __le16 uint16_t
+#define __le32 uint32_t
+#define __le64 uint64_t
+
+#define __iomem
+#define __devinit
+#define ____cacheline_aligned_in_smp
+
+#define msleep(x) mdelay(x)
+
+#define ETH_FCS_LEN 4
+
+typedef int spinlock_t;
+typedef enum {
+ false = 0,
+ true = 1
+} boolean_t;
+
+#define TRUE 1
+#define FALSE 0
+
+#define usec_delay(x) udelay(x)
+#define msec_delay(x) mdelay(x)
+#define msec_delay_irq(x) mdelay(x)
+
+#define PCI_COMMAND_REGISTER PCI_COMMAND
+#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE
+#define ETH_ADDR_LEN ETH_ALEN
+
+
+#define DEBUGOUT(S) if (0) { printf(S); }
+#define DEBUGOUT1(S, A...) if (0) { printf(S, A); }
+
+#define DEBUGFUNC(F) DEBUGOUT(F "\n")
+#define DEBUGOUT2 DEBUGOUT1
+#define DEBUGOUT3 DEBUGOUT2
+#define DEBUGOUT7 DEBUGOUT3
+
+#define E1000_WRITE_REG(a, reg, value) do { \
+ writel((value), ((a)->hw_addr + reg)); } while (0)
+
+#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + reg))
+
+#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) do { \
+ writel((value), ((a)->hw_addr + reg + ((offset) << 2))); } while (0)
+
+#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
+ readl((a)->hw_addr + reg + ((offset) << 2)))
+
+#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
+#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
+
+#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
+ writew((value), ((a)->hw_addr + reg + ((offset) << 1))))
+
+#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
+ readw((a)->hw_addr + reg + ((offset) << 1)))
+
+#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
+ writeb((value), ((a)->hw_addr + reg + (offset))))
+
+#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
+ readb((a)->hw_addr + reg + (offset)))
+
+#define E1000_WRITE_REG_IO(a, reg, offset) do { \
+ outl(reg, ((a)->io_base)); \
+ outl(offset, ((a)->io_base + 4)); } while(0)
+
+#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS)
+
+#define E1000_WRITE_FLASH_REG(a, reg, value) ( \
+ writel((value), ((a)->flash_address + reg)))
+
+#define E1000_WRITE_FLASH_REG16(a, reg, value) ( \
+ writew((value), ((a)->flash_address + reg)))
+
+#define E1000_READ_FLASH_REG(a, reg) (readl((a)->flash_address + reg))
+
+#define E1000_READ_FLASH_REG16(a, reg) (readw((a)->flash_address + reg))
+
+#endif /* _IGBVF_OSDEP_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_regs.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_regs.h
new file mode 100644
index 00000000..21603d31
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_regs.h
@@ -0,0 +1,338 @@
+/*******************************************************************************
+
+ Intel(R) 82576 Virtual Function Linux driver
+ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#ifndef _IGBVF_REGS_H_
+#define _IGBVF_REGS_H_
+
+#define E1000_CTRL 0x00000 /* Device Control - RW */
+#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */
+#define E1000_STATUS 0x00008 /* Device Status - RO */
+#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
+#define E1000_EERD 0x00014 /* EEPROM Read - RW */
+#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
+#define E1000_FLA 0x0001C /* Flash Access - RW */
+#define E1000_MDIC 0x00020 /* MDI Control - RW */
+#define E1000_SCTL 0x00024 /* SerDes Control - RW */
+#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
+#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
+#define E1000_FEXT 0x0002C /* Future Extended - RW */
+#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */
+#define E1000_FCT 0x00030 /* Flow Control Type - RW */
+#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
+#define E1000_VET 0x00038 /* VLAN Ether Type - RW */
+#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */
+#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
+#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
+#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
+#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
+#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
+#define E1000_RCTL 0x00100 /* Rx Control - RW */
+#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
+#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */
+#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */
+#define E1000_TCTL 0x00400 /* Tx Control - RW */
+#define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */
+#define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */
+#define E1000_TBT 0x00448 /* Tx Burst Timer - RW */
+#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
+#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
+#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
+#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
+#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */
+#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
+#define E1000_PBS 0x01008 /* Packet Buffer Size */
+#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
+#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
+#define E1000_FLASHT 0x01028 /* FLASH Timer Register */
+#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */
+#define E1000_FLSWCTL 0x01030 /* FLASH control register */
+#define E1000_FLSWDATA 0x01034 /* FLASH data register */
+#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */
+#define E1000_FLOP 0x0103C /* FLASH Opcode Register */
+#define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */
+#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */
+#define E1000_WDSTP 0x01040 /* Watchdog Setup - RW */
+#define E1000_SWDSTS 0x01044 /* SW Device Status - RW */
+#define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */
+#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */
+#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
+#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
+#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */
+#define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n)))
+#define E1000_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */
+#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */
+/* Split and Replication Rx Control - RW */
+#define E1000_RDPUMB 0x025CC /* DMA Rx Descriptor uC Mailbox - RW */
+#define E1000_RDPUAD 0x025D0 /* DMA Rx Descriptor uC Addr Command - RW */
+#define E1000_RDPUWD 0x025D4 /* DMA Rx Descriptor uC Data Write - RW */
+#define E1000_RDPURD 0x025D8 /* DMA Rx Descriptor uC Data Read - RW */
+#define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */
+#define E1000_RXCTL(_n) (0x0C014 + (0x40 * (_n)))
+#define E1000_RQDPC(_n) (0x0C030 + (0x40 * (_n)))
+#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */
+#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */
+/*
+ * Convenience macros
+ *
+ * Note: "_n" is the queue number of the register to be written to.
+ *
+ * Example usage:
+ * E1000_RDBAL_REG(current_rx_queue)
+ */
+#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \
+ (0x0C000 + ((_n) * 0x40)))
+#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \
+ (0x0C004 + ((_n) * 0x40)))
+#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \
+ (0x0C008 + ((_n) * 0x40)))
+#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \
+ (0x0C00C + ((_n) * 0x40)))
+#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \
+ (0x0C010 + ((_n) * 0x40)))
+#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \
+ (0x0C018 + ((_n) * 0x40)))
+#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \
+ (0x0C028 + ((_n) * 0x40)))
+#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \
+ (0x0E000 + ((_n) * 0x40)))
+#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \
+ (0x0E004 + ((_n) * 0x40)))
+#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \
+ (0x0E008 + ((_n) * 0x40)))
+#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \
+ (0x0E010 + ((_n) * 0x40)))
+#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \
+ (0x0E018 + ((_n) * 0x40)))
+#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \
+ (0x0E028 + ((_n) * 0x40)))
+#define E1000_TARC(_n) (0x03840 + (_n << 8))
+#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8))
+#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8))
+#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \
+ (0x0E038 + ((_n) * 0x40)))
+#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \
+ (0x0E03C + ((_n) * 0x40)))
+#define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */
+#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */
+#define E1000_TXDMAC 0x03000 /* Tx DMA Control - RW */
+#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */
+#define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4))
+#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
+ (0x054E0 + ((_i - 16) * 8)))
+#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
+ (0x054E4 + ((_i - 16) * 8)))
+#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8))
+#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4))
+#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
+#define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8))
+#define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8))
+#define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8))
+#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */
+#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */
+#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */
+#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */
+#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */
+#define E1000_TDPUMB 0x0357C /* DMA Tx Descriptor uC Mail Box - RW */
+#define E1000_TDPUAD 0x03580 /* DMA Tx Descriptor uC Addr Command - RW */
+#define E1000_TDPUWD 0x03584 /* DMA Tx Descriptor uC Data Write - RW */
+#define E1000_TDPURD 0x03588 /* DMA Tx Descriptor uC Data Read - RW */
+#define E1000_TDPUCTL 0x0358C /* DMA Tx Descriptor uC Control - RW */
+#define E1000_DTXCTL 0x03590 /* DMA Tx Control - RW */
+#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */
+#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */
+#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
+#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
+#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
+#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
+#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */
+#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */
+#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */
+#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */
+#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */
+#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */
+#define E1000_COLC 0x04028 /* Collision Count - R/clr */
+#define E1000_DC 0x04030 /* Defer Count - R/clr */
+#define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */
+#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */
+#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */
+#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */
+#define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */
+#define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */
+#define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */
+#define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */
+#define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */
+#define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */
+#define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */
+#define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */
+#define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */
+#define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */
+#define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */
+#define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */
+#define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */
+#define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */
+#define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */
+#define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */
+#define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */
+#define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */
+#define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */
+#define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */
+#define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */
+#define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */
+#define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */
+#define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */
+#define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */
+#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
+#define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */
+#define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */
+#define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */
+#define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */
+#define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */
+#define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */
+#define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */
+#define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */
+#define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */
+#define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */
+#define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */
+#define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */
+#define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */
+#define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */
+#define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */
+#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */
+#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */
+#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
+#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */
+#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */
+#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */
+#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */
+#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */
+#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */
+#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */
+#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
+
+#define E1000_VFGPRC 0x00F10
+#define E1000_VFGORC 0x00F18
+#define E1000_VFMPRC 0x00F3C
+#define E1000_VFGPTC 0x00F14
+#define E1000_VFGOTC 0x00F34
+#define E1000_VFGOTLBC 0x00F50
+#define E1000_VFGPTLBC 0x00F44
+#define E1000_VFGORLBC 0x00F48
+#define E1000_VFGPRLBC 0x00F40
+#define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */
+#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */
+#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */
+#define E1000_CBTMPC 0x0402C /* Circuit Breaker Tx Packet Count */
+#define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */
+#define E1000_CBRDPC 0x04044 /* Circuit Breaker Rx Dropped Count */
+#define E1000_CBRMPC 0x040FC /* Circuit Breaker Rx Packet Count */
+#define E1000_RPTHC 0x04104 /* Rx Packets To Host */
+#define E1000_HGPTC 0x04118 /* Host Good Packets Tx Count */
+#define E1000_HTCBDPC 0x04124 /* Host Tx Circuit Breaker Dropped Count */
+#define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */
+#define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */
+#define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
+#define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
+#define E1000_LENERRS 0x04138 /* Length Errors Count */
+#define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */
+#define E1000_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */
+#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */
+#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */
+#define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */
+#define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Page - RW */
+#define E1000_1GSTAT_RCV 0x04228 /* 1GSTAT Code Violation Packet Count - RW */
+#define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */
+#define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */
+#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
+#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
+#define E1000_RA 0x05400 /* Receive Address - RW Array */
+#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
+#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */
+#define E1000_VFQA0 0x0B000 /* VLAN Filter Queue Array 0 - RW Array */
+#define E1000_VFQA1 0x0B200 /* VLAN Filter Queue Array 1 - RW Array */
+#define E1000_WUC 0x05800 /* Wakeup Control - RW */
+#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */
+#define E1000_WUS 0x05810 /* Wakeup Status - RO */
+#define E1000_MANC 0x05820 /* Management Control - RW */
+#define E1000_IPAV 0x05838 /* IP Address Valid - RW */
+#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */
+#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */
+#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */
+#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */
+#define E1000_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */
+#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */
+#define E1000_HOST_IF 0x08800 /* Host Interface */
+#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
+#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
+
+#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */
+#define E1000_MDPHYA 0x0003C /* PHY address - RW */
+#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */
+#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
+#define E1000_CCMCTL 0x05B48 /* CCM Control Register */
+#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */
+#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */
+#define E1000_GCR 0x05B00 /* PCI-Ex Control */
+#define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */
+#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */
+#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */
+#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */
+#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */
+#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
+#define E1000_SWSM 0x05B50 /* SW Semaphore */
+#define E1000_FWSM 0x05B54 /* FW Semaphore */
+#define E1000_SWSM2 0x05B58 /* Driver-only SW semaphore (not used by BOOT agents) */
+#define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */
+#define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */
+#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
+#define E1000_HICR 0x08F00 /* Host Interface Control */
+
+/* RSS registers */
+#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
+#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
+#define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */
+#define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate Interrupt Ext*/
+#define E1000_IMIRVP 0x05AC0 /* Immediate Interrupt Rx VLAN Priority - RW */
+#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Allocation Register
+ * (_i) - RW */
+#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10)) /* MSI-X Table entry addr
+ * low reg - RW */
+#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) /* MSI-X Table entry addr
+ * upper reg - RW */
+#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10)) /* MSI-X Table entry
+ * message reg - RW */
+#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) /* MSI-X Table entry
+ * vector ctrl reg - RW */
+#define E1000_MSIXPBA 0x0E000 /* MSI-X Pending bit array */
+#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */
+#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */
+#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
+#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
+
+#endif /* _IGBVF_REGS_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_vf.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_vf.c
new file mode 100644
index 00000000..f2dac8be
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_vf.c
@@ -0,0 +1,455 @@
+/*******************************************************************************
+
+ Intel(R) 82576 Virtual Function Linux driver
+ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include "igbvf_vf.h"
+
+
+static s32 igbvf_init_mac_params_vf(struct e1000_hw *hw);
+static s32 igbvf_check_for_link_vf(struct e1000_hw *hw);
+static s32 igbvf_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
+ u16 *duplex);
+static s32 igbvf_init_hw_vf(struct e1000_hw *hw);
+static s32 igbvf_reset_hw_vf(struct e1000_hw *hw);
+static void igbvf_update_mc_addr_list_vf(struct e1000_hw *hw, u8 *, u32);
+static void igbvf_rar_set_vf(struct e1000_hw *, u8 *, u32);
+static s32 igbvf_read_mac_addr_vf(struct e1000_hw *);
+
+/**
+ * igbvf_init_mac_params_vf - Inits MAC params
+ * @hw: pointer to the HW structure
+ **/
+static s32 igbvf_init_mac_params_vf(struct e1000_hw *hw)
+{
+ struct e1000_mac_info *mac = &hw->mac;
+
+ DEBUGFUNC("igbvf_init_mac_params_vf");
+
+ /* VF's have no MTA Registers - PF feature only */
+ mac->mta_reg_count = 128;
+ /* VF's have no access to RAR entries */
+ mac->rar_entry_count = 1;
+
+ /* Function pointers */
+ /* reset */
+ mac->ops.reset_hw = igbvf_reset_hw_vf;
+ /* hw initialization */
+ mac->ops.init_hw = igbvf_init_hw_vf;
+ /* check for link */
+ mac->ops.check_for_link = igbvf_check_for_link_vf;
+ /* link info */
+ mac->ops.get_link_up_info = igbvf_get_link_up_info_vf;
+ /* multicast address update */
+ mac->ops.update_mc_addr_list = igbvf_update_mc_addr_list_vf;
+ /* set mac address */
+ mac->ops.rar_set = igbvf_rar_set_vf;
+ /* read mac address */
+ mac->ops.read_mac_addr = igbvf_read_mac_addr_vf;
+
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * igbvf_init_function_pointers_vf - Inits function pointers
+ * @hw: pointer to the HW structure
+ **/
+void igbvf_init_function_pointers_vf(struct e1000_hw *hw)
+{
+ DEBUGFUNC("igbvf_init_function_pointers_vf");
+
+ hw->mac.ops.init_params = igbvf_init_mac_params_vf;
+ hw->mbx.ops.init_params = igbvf_init_mbx_params_vf;
+}
+
+/**
+ * igbvf_get_link_up_info_vf - Gets link info.
+ * @hw: pointer to the HW structure
+ * @speed: pointer to 16 bit value to store link speed.
+ * @duplex: pointer to 16 bit value to store duplex.
+ *
+ * Since we cannot read the PHY and get accurate link info, we must rely upon
+ * the status register's data which is often stale and inaccurate.
+ **/
+static s32 igbvf_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
+ u16 *duplex)
+{
+ s32 status;
+
+ DEBUGFUNC("igbvf_get_link_up_info_vf");
+
+ status = E1000_READ_REG(hw, E1000_STATUS);
+ if (status & E1000_STATUS_SPEED_1000) {
+ *speed = SPEED_1000;
+ DEBUGOUT("1000 Mbs, ");
+ } else if (status & E1000_STATUS_SPEED_100) {
+ *speed = SPEED_100;
+ DEBUGOUT("100 Mbs, ");
+ } else {
+ *speed = SPEED_10;
+ DEBUGOUT("10 Mbs, ");
+ }
+
+ if (status & E1000_STATUS_FD) {
+ *duplex = FULL_DUPLEX;
+ DEBUGOUT("Full Duplex\n");
+ } else {
+ *duplex = HALF_DUPLEX;
+ DEBUGOUT("Half Duplex\n");
+ }
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * igbvf_reset_hw_vf - Resets the HW
+ * @hw: pointer to the HW structure
+ *
+ * VF's provide a function level reset. This is done using bit 26 of ctrl_reg.
+ * This is all the reset we can perform on a VF.
+ **/
+static s32 igbvf_reset_hw_vf(struct e1000_hw *hw)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ u32 timeout = E1000_VF_INIT_TIMEOUT;
+ s32 ret_val = -E1000_ERR_MAC_INIT;
+ u32 ctrl, msgbuf[3];
+ u8 *addr = (u8 *)(&msgbuf[1]);
+
+ DEBUGFUNC("igbvf_reset_hw_vf");
+
+ DEBUGOUT("Issuing a function level reset to MAC\n");
+ ctrl = E1000_READ_REG(hw, E1000_CTRL);
+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
+
+ /* we cannot reset while the RSTI / RSTD bits are asserted */
+ while (!mbx->ops.check_for_rst(hw, 0) && timeout) {
+ timeout--;
+ usec_delay(5);
+ }
+
+ if (timeout) {
+ /* mailbox timeout can now become active */
+ mbx->timeout = E1000_VF_MBX_INIT_TIMEOUT;
+
+ msgbuf[0] = E1000_VF_RESET;
+ mbx->ops.write_posted(hw, msgbuf, 1, 0);
+
+ msec_delay(10);
+
+ /* set our "perm_addr" based on info provided by PF */
+ ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0);
+ if (!ret_val) {
+ if (msgbuf[0] == (E1000_VF_RESET |
+ E1000_VT_MSGTYPE_ACK))
+ memcpy(hw->mac.perm_addr, addr, 6);
+ else
+ ret_val = -E1000_ERR_MAC_INIT;
+ }
+ }
+
+ return ret_val;
+}
+
+/**
+ * igbvf_init_hw_vf - Inits the HW
+ * @hw: pointer to the HW structure
+ *
+ * Not much to do here except clear the PF Reset indication if there is one.
+ **/
+static s32 igbvf_init_hw_vf(struct e1000_hw *hw)
+{
+ DEBUGFUNC("igbvf_init_hw_vf");
+
+ /* attempt to set and restore our mac address */
+ igbvf_rar_set_vf(hw, hw->mac.addr, 0);
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * igbvf_rar_set_vf - set device MAC address
+ * @hw: pointer to the HW structure
+ * @addr: pointer to the receive address
+ * @index receive address array register
+ **/
+static void igbvf_rar_set_vf(struct e1000_hw *hw, u8 * addr, u32 index __unused)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ u32 msgbuf[3];
+ u8 *msg_addr = (u8 *)(&msgbuf[1]);
+ s32 ret_val;
+
+ memset(msgbuf, 0, 12);
+ msgbuf[0] = E1000_VF_SET_MAC_ADDR;
+ memcpy(msg_addr, addr, 6);
+ ret_val = mbx->ops.write_posted(hw, msgbuf, 3, 0);
+
+ if (!ret_val)
+ ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0);
+
+ msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS;
+
+ /* if nacked the address was rejected, use "perm_addr" */
+ if (!ret_val &&
+ (msgbuf[0] == (E1000_VF_SET_MAC_ADDR | E1000_VT_MSGTYPE_NACK)))
+ igbvf_read_mac_addr_vf(hw);
+}
+
+/**
+ * igbvf_hash_mc_addr_vf - Generate a multicast hash value
+ * @hw: pointer to the HW structure
+ * @mc_addr: pointer to a multicast address
+ *
+ * Generates a multicast address hash value which is used to determine
+ * the multicast filter table array address and new table value. See
+ * igbvf_mta_set_generic()
+ **/
+static u32 igbvf_hash_mc_addr_vf(struct e1000_hw *hw, u8 *mc_addr)
+{
+ u32 hash_value, hash_mask;
+ u8 bit_shift = 0;
+
+ DEBUGFUNC("igbvf_hash_mc_addr_generic");
+
+ /* Register count multiplied by bits per register */
+ hash_mask = (hw->mac.mta_reg_count * 32) - 1;
+
+ /*
+ * The bit_shift is the number of left-shifts
+ * where 0xFF would still fall within the hash mask.
+ */
+ while (hash_mask >> bit_shift != 0xFF)
+ bit_shift++;
+
+ hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
+ (((u16) mc_addr[5]) << bit_shift)));
+
+ return hash_value;
+}
+
+/**
+ * igbvf_update_mc_addr_list_vf - Update Multicast addresses
+ * @hw: pointer to the HW structure
+ * @mc_addr_list: array of multicast addresses to program
+ * @mc_addr_count: number of multicast addresses to program
+ *
+ * Updates the Multicast Table Array.
+ * The caller must have a packed mc_addr_list of multicast addresses.
+ **/
+void igbvf_update_mc_addr_list_vf(struct e1000_hw *hw,
+ u8 *mc_addr_list, u32 mc_addr_count)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ u32 msgbuf[E1000_VFMAILBOX_SIZE];
+ u16 *hash_list = (u16 *)&msgbuf[1];
+ u32 hash_value;
+ u32 i;
+
+ DEBUGFUNC("igbvf_update_mc_addr_list_vf");
+
+ /* Each entry in the list uses 1 16 bit word. We have 30
+ * 16 bit words available in our HW msg buffer (minus 1 for the
+ * msg type). That's 30 hash values if we pack 'em right. If
+ * there are more than 30 MC addresses to add then punt the
+ * extras for now and then add code to handle more than 30 later.
+ * It would be unusual for a server to request that many multi-cast
+ * addresses except for in large enterprise network environments.
+ */
+
+ DEBUGOUT1("MC Addr Count = %d\n", mc_addr_count);
+
+ msgbuf[0] = E1000_VF_SET_MULTICAST;
+
+ if (mc_addr_count > 30) {
+ msgbuf[0] |= E1000_VF_SET_MULTICAST_OVERFLOW;
+ mc_addr_count = 30;
+ }
+
+ msgbuf[0] |= mc_addr_count << E1000_VT_MSGINFO_SHIFT;
+
+ for (i = 0; i < mc_addr_count; i++) {
+ hash_value = igbvf_hash_mc_addr_vf(hw, mc_addr_list);
+ DEBUGOUT1("Hash value = 0x%03X\n", hash_value);
+ hash_list[i] = hash_value & 0x0FFF;
+ mc_addr_list += ETH_ADDR_LEN;
+ }
+
+ mbx->ops.write_posted(hw, msgbuf, E1000_VFMAILBOX_SIZE, 0);
+}
+
+/**
+ * igbvf_vfta_set_vf - Set/Unset vlan filter table address
+ * @hw: pointer to the HW structure
+ * @vid: determines the vfta register and bit to set/unset
+ * @set: if true then set bit, else clear bit
+ **/
+void igbvf_vfta_set_vf(struct e1000_hw *hw, u16 vid, bool set)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ u32 msgbuf[2];
+
+ msgbuf[0] = E1000_VF_SET_VLAN;
+ msgbuf[1] = vid;
+ /* Setting the 8 bit field MSG INFO to TRUE indicates "add" */
+ if (set)
+ msgbuf[0] |= E1000_VF_SET_VLAN_ADD;
+
+ mbx->ops.write_posted(hw, msgbuf, 2, 0);
+}
+
+/** igbvf_rlpml_set_vf - Set the maximum receive packet length
+ * @hw: pointer to the HW structure
+ * @max_size: value to assign to max frame size
+ **/
+void igbvf_rlpml_set_vf(struct e1000_hw *hw, u16 max_size)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ u32 msgbuf[2];
+
+ msgbuf[0] = E1000_VF_SET_LPE;
+ msgbuf[1] = max_size;
+
+ mbx->ops.write_posted(hw, msgbuf, 2, 0);
+}
+
+/**
+ * igbvf_promisc_set_vf - Set flags for Unicast or Multicast promisc
+ * @hw: pointer to the HW structure
+ * @uni: boolean indicating unicast promisc status
+ * @multi: boolean indicating multicast promisc status
+ **/
+s32 igbvf_promisc_set_vf(struct e1000_hw *hw, enum e1000_promisc_type type)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ u32 msgbuf = E1000_VF_SET_PROMISC;
+ s32 ret_val;
+
+ switch (type) {
+ case e1000_promisc_multicast:
+ msgbuf |= E1000_VF_SET_PROMISC_MULTICAST;
+ break;
+ case e1000_promisc_enabled:
+ msgbuf |= E1000_VF_SET_PROMISC_MULTICAST;
+ case e1000_promisc_unicast:
+ msgbuf |= E1000_VF_SET_PROMISC_UNICAST;
+ case e1000_promisc_disabled:
+ break;
+ default:
+ return -E1000_ERR_MAC_INIT;
+ }
+
+ ret_val = mbx->ops.write_posted(hw, &msgbuf, 1, 0);
+
+ if (!ret_val)
+ ret_val = mbx->ops.read_posted(hw, &msgbuf, 1, 0);
+
+ if (!ret_val && !(msgbuf & E1000_VT_MSGTYPE_ACK))
+ ret_val = -E1000_ERR_MAC_INIT;
+
+ return ret_val;
+}
+
+/**
+ * igbvf_read_mac_addr_vf - Read device MAC address
+ * @hw: pointer to the HW structure
+ **/
+static s32 igbvf_read_mac_addr_vf(struct e1000_hw *hw)
+{
+ int i;
+
+ for (i = 0; i < ETH_ADDR_LEN; i++)
+ hw->mac.addr[i] = hw->mac.perm_addr[i];
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * igbvf_check_for_link_vf - Check for link for a virtual interface
+ * @hw: pointer to the HW structure
+ *
+ * Checks to see if the underlying PF is still talking to the VF and
+ * if it is then it reports the link state to the hardware, otherwise
+ * it reports link down and returns an error.
+ **/
+static s32 igbvf_check_for_link_vf(struct e1000_hw *hw)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ struct e1000_mac_info *mac = &hw->mac;
+ s32 ret_val = E1000_SUCCESS;
+ u32 in_msg = 0;
+
+ DEBUGFUNC("igbvf_check_for_link_vf");
+
+ /*
+ * We only want to run this if there has been a rst asserted.
+ * in this case that could mean a link change, device reset,
+ * or a virtual function reset
+ */
+
+ /* If we were hit with a reset drop the link */
+ if (!mbx->ops.check_for_rst(hw, 0))
+ mac->get_link_status = true;
+
+ if (!mac->get_link_status)
+ goto out;
+
+ /* if link status is down no point in checking to see if pf is up */
+ if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU))
+ goto out;
+
+ /* if the read failed it could just be a mailbox collision, best wait
+ * until we are called again and don't report an error */
+ if (mbx->ops.read(hw, &in_msg, 1, 0))
+ goto out;
+
+ /* if incoming message isn't clear to send we are waiting on response */
+ if (!(in_msg & E1000_VT_MSGTYPE_CTS)) {
+ /* message is not CTS and is NACK we have lost CTS status */
+ if (in_msg & E1000_VT_MSGTYPE_NACK)
+ ret_val = -E1000_ERR_MAC_INIT;
+ goto out;
+ }
+
+ /* at this point we know the PF is talking to us, check and see if
+ * we are still accepting timeout or if we had a timeout failure.
+ * if we failed then we will need to reinit */
+ if (!mbx->timeout) {
+ ret_val = -E1000_ERR_MAC_INIT;
+ goto out;
+ }
+
+ /* if we passed all the tests above then the link is up and we no
+ * longer need to check for link */
+ mac->get_link_status = false;
+
+out:
+ return ret_val;
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_vf.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_vf.h
new file mode 100644
index 00000000..8d8963fe
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/igbvf/igbvf_vf.h
@@ -0,0 +1,346 @@
+/*******************************************************************************
+
+ Intel(R) 82576 Virtual Function Linux driver
+ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#ifndef _IGBVF_VF_H_
+#define _IGBVF_VF_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/pci.h>
+#include <ipxe/malloc.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/io.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+
+#include "igbvf_osdep.h"
+#include "igbvf_regs.h"
+#include "igbvf_defines.h"
+
+struct e1000_hw;
+
+#define E1000_DEV_ID_82576_VF 0x10CA
+#define E1000_DEV_ID_I350_VF 0x1520
+
+#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
+
+/* Additional Descriptor Control definitions */
+#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
+#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
+
+/* SRRCTL bit definitions */
+#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
+#define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00
+#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
+#define E1000_SRRCTL_DESCTYPE_LEGACY 0x00000000
+#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
+#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000
+#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
+#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000
+#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000
+#define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000
+#define E1000_SRRCTL_DROP_EN 0x80000000
+
+#define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F
+#define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00
+
+/* Interrupt Defines */
+#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
+#define E1000_EITR(_n) (0x01680 + ((_n) << 2))
+#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
+#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
+#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
+#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
+#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */
+#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */
+#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
+#define E1000_IVAR_VALID 0x80
+
+/* Receive Descriptor - Advanced */
+union e1000_adv_rx_desc {
+ struct {
+ u64 pkt_addr; /* Packet buffer address */
+ u64 hdr_addr; /* Header buffer address */
+ } read;
+ struct {
+ struct {
+ union {
+ u32 data;
+ struct {
+ u16 pkt_info; /* RSS type, Packet type */
+ u16 hdr_info; /* Split Header,
+ * header buffer length */
+ } hs_rss;
+ } lo_dword;
+ union {
+ u32 rss; /* RSS Hash */
+ struct {
+ u16 ip_id; /* IP id */
+ u16 csum; /* Packet Checksum */
+ } csum_ip;
+ } hi_dword;
+ } lower;
+ struct {
+ u32 status_error; /* ext status/error */
+ u16 length; /* Packet length */
+ u16 vlan; /* VLAN tag */
+ } upper;
+ } wb; /* writeback */
+};
+
+#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
+#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
+
+/* Transmit Descriptor - Advanced */
+union e1000_adv_tx_desc {
+ struct {
+ u64 buffer_addr; /* Address of descriptor's data buf */
+ u32 cmd_type_len;
+ u32 olinfo_status;
+ } read;
+ struct {
+ u64 rsvd; /* Reserved */
+ u32 nxtseq_seed;
+ u32 status;
+ } wb;
+};
+
+/* Adv Transmit Descriptor Config Masks */
+#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
+#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
+#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
+#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
+#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
+#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
+#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
+#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
+#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
+
+/* Context descriptors */
+struct e1000_adv_tx_context_desc {
+ u32 vlan_macip_lens;
+ u32 seqnum_seed;
+ u32 type_tucmd_mlhl;
+ u32 mss_l4len_idx;
+};
+
+#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
+#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
+#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
+#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
+#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
+
+enum e1000_mac_type {
+ e1000_undefined = 0,
+ e1000_vfadapt,
+ e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
+};
+
+struct e1000_vf_stats {
+ u64 base_gprc;
+ u64 base_gptc;
+ u64 base_gorc;
+ u64 base_gotc;
+ u64 base_mprc;
+ u64 base_gotlbc;
+ u64 base_gptlbc;
+ u64 base_gorlbc;
+ u64 base_gprlbc;
+
+ u32 last_gprc;
+ u32 last_gptc;
+ u32 last_gorc;
+ u32 last_gotc;
+ u32 last_mprc;
+ u32 last_gotlbc;
+ u32 last_gptlbc;
+ u32 last_gorlbc;
+ u32 last_gprlbc;
+
+ u64 gprc;
+ u64 gptc;
+ u64 gorc;
+ u64 gotc;
+ u64 mprc;
+ u64 gotlbc;
+ u64 gptlbc;
+ u64 gorlbc;
+ u64 gprlbc;
+};
+
+#include "igbvf_mbx.h"
+
+struct e1000_mac_operations {
+ /* Function pointers for the MAC. */
+ s32 (*init_params)(struct e1000_hw *);
+ s32 (*check_for_link)(struct e1000_hw *);
+ void (*clear_vfta)(struct e1000_hw *);
+ s32 (*get_bus_info)(struct e1000_hw *);
+ s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
+ void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32);
+ s32 (*reset_hw)(struct e1000_hw *);
+ s32 (*init_hw)(struct e1000_hw *);
+ s32 (*setup_link)(struct e1000_hw *);
+ void (*write_vfta)(struct e1000_hw *, u32, u32);
+ void (*mta_set)(struct e1000_hw *, u32);
+ void (*rar_set)(struct e1000_hw *, u8*, u32);
+ s32 (*read_mac_addr)(struct e1000_hw *);
+};
+
+struct e1000_mac_info {
+ struct e1000_mac_operations ops;
+ u8 addr[6];
+ u8 perm_addr[6];
+
+ enum e1000_mac_type type;
+
+ u16 mta_reg_count;
+ u16 rar_entry_count;
+
+ bool get_link_status;
+};
+
+enum e1000_bus_type {
+ e1000_bus_type_unknown = 0,
+ e1000_bus_type_pci,
+ e1000_bus_type_pcix,
+ e1000_bus_type_pci_express,
+ e1000_bus_type_reserved
+};
+
+enum e1000_bus_speed {
+ e1000_bus_speed_unknown = 0,
+ e1000_bus_speed_33,
+ e1000_bus_speed_66,
+ e1000_bus_speed_100,
+ e1000_bus_speed_120,
+ e1000_bus_speed_133,
+ e1000_bus_speed_2500,
+ e1000_bus_speed_5000,
+ e1000_bus_speed_reserved
+};
+
+enum e1000_bus_width {
+ e1000_bus_width_unknown = 0,
+ e1000_bus_width_pcie_x1,
+ e1000_bus_width_pcie_x2,
+ e1000_bus_width_pcie_x4 = 4,
+ e1000_bus_width_pcie_x8 = 8,
+ e1000_bus_width_32,
+ e1000_bus_width_64,
+ e1000_bus_width_reserved
+};
+
+struct e1000_bus_info {
+ enum e1000_bus_type type;
+ enum e1000_bus_speed speed;
+ enum e1000_bus_width width;
+
+ u16 func;
+ u16 pci_cmd_word;
+};
+
+struct e1000_mbx_operations {
+ s32 (*init_params)(struct e1000_hw *hw);
+ s32 (*read)(struct e1000_hw *, u32 *, u16, u16);
+ s32 (*write)(struct e1000_hw *, u32 *, u16, u16);
+ s32 (*read_posted)(struct e1000_hw *, u32 *, u16, u16);
+ s32 (*write_posted)(struct e1000_hw *, u32 *, u16, u16);
+ s32 (*check_for_msg)(struct e1000_hw *, u16);
+ s32 (*check_for_ack)(struct e1000_hw *, u16);
+ s32 (*check_for_rst)(struct e1000_hw *, u16);
+};
+
+struct e1000_mbx_stats {
+ u32 msgs_tx;
+ u32 msgs_rx;
+
+ u32 acks;
+ u32 reqs;
+ u32 rsts;
+};
+
+struct e1000_mbx_info {
+ struct e1000_mbx_operations ops;
+ struct e1000_mbx_stats stats;
+ u32 timeout;
+ u32 usec_delay;
+ u16 size;
+};
+
+struct e1000_dev_spec_vf {
+ u32 vf_number;
+ u32 v2p_mailbox;
+};
+
+struct e1000_hw {
+ void *back;
+
+ u8 __iomem *hw_addr;
+ u8 __iomem *flash_address;
+ unsigned long io_base;
+
+ struct e1000_mac_info mac;
+ struct e1000_bus_info bus;
+ struct e1000_mbx_info mbx;
+
+ union {
+ struct e1000_dev_spec_vf vf;
+ } dev_spec;
+
+ u16 device_id;
+ u16 subsystem_vendor_id;
+ u16 subsystem_device_id;
+ u16 vendor_id;
+
+ u8 revision_id;
+};
+
+enum e1000_promisc_type {
+ e1000_promisc_disabled = 0, /* all promisc modes disabled */
+ e1000_promisc_unicast = 1, /* unicast promiscuous enabled */
+ e1000_promisc_multicast = 2, /* multicast promiscuous enabled */
+ e1000_promisc_enabled = 3, /* both uni and multicast promisc */
+ e1000_num_promisc_types
+};
+
+/* These functions must be implemented by drivers */
+s32 igbvf_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
+void igbvf_vfta_set_vf(struct e1000_hw *, u16, bool);
+void igbvf_rlpml_set_vf(struct e1000_hw *, u16);
+s32 igbvf_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type);
+#endif /* _IGBVF_VF_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/intel.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/intel.c
new file mode 100644
index 00000000..0f4a1833
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/intel.c
@@ -0,0 +1,955 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/pci.h>
+#include "intel.h"
+
+/** @file
+ *
+ * Intel 10/100/1000 network card driver
+ *
+ */
+
+/******************************************************************************
+ *
+ * EEPROM interface
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Read data from EEPROM
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int intel_read_eeprom ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len ) {
+ struct intel_nic *intel =
+ container_of ( nvs, struct intel_nic, eeprom );
+ unsigned int i;
+ uint32_t value;
+ uint16_t *data_word = data;
+
+ /* Sanity check. We advertise a blocksize of one word, so
+ * should only ever receive single-word requests.
+ */
+ assert ( len == sizeof ( *data_word ) );
+
+ /* Initiate read */
+ writel ( ( INTEL_EERD_START | ( address << intel->eerd_addr_shift ) ),
+ intel->regs + INTEL_EERD );
+
+ /* Wait for read to complete */
+ for ( i = 0 ; i < INTEL_EEPROM_MAX_WAIT_MS ; i++ ) {
+
+ /* If read is not complete, delay 1ms and retry */
+ value = readl ( intel->regs + INTEL_EERD );
+ if ( ! ( value & intel->eerd_done ) ) {
+ mdelay ( 1 );
+ continue;
+ }
+
+ /* Extract data */
+ *data_word = cpu_to_le16 ( INTEL_EERD_DATA ( value ) );
+ return 0;
+ }
+
+ DBGC ( intel, "INTEL %p timed out waiting for EEPROM read\n", intel );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Write data to EEPROM
+ *
+ * @v nvs NVS device
+ * @v address Address to which to write
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int intel_write_eeprom ( struct nvs_device *nvs,
+ unsigned int address __unused,
+ const void *data __unused,
+ size_t len __unused ) {
+ struct intel_nic *intel =
+ container_of ( nvs, struct intel_nic, eeprom );
+
+ DBGC ( intel, "INTEL %p EEPROM write not supported\n", intel );
+ return -ENOTSUP;
+}
+
+/**
+ * Initialise EEPROM
+ *
+ * @v intel Intel device
+ * @ret rc Return status code
+ */
+static int intel_init_eeprom ( struct intel_nic *intel ) {
+ unsigned int i;
+ uint32_t value;
+
+ /* The NIC automatically detects the type of attached EEPROM.
+ * The EERD register provides access to only a single word at
+ * a time, so we pretend to have a single-word block size.
+ *
+ * The EEPROM size may be larger than the minimum size, but
+ * this doesn't matter to us since we access only the first
+ * few words.
+ */
+ intel->eeprom.word_len_log2 = INTEL_EEPROM_WORD_LEN_LOG2;
+ intel->eeprom.size = INTEL_EEPROM_MIN_SIZE_WORDS;
+ intel->eeprom.block_size = 1;
+ intel->eeprom.read = intel_read_eeprom;
+ intel->eeprom.write = intel_write_eeprom;
+
+ /* The layout of the EERD register was changed at some point
+ * to accommodate larger EEPROMs. Read from address zero (for
+ * which the request layouts are compatible) to determine
+ * which type of register we have.
+ */
+ writel ( INTEL_EERD_START, intel->regs + INTEL_EERD );
+ for ( i = 0 ; i < INTEL_EEPROM_MAX_WAIT_MS ; i++ ) {
+ value = readl ( intel->regs + INTEL_EERD );
+ if ( value & INTEL_EERD_DONE_LARGE ) {
+ DBGC ( intel, "INTEL %p has large-format EERD\n",
+ intel );
+ intel->eerd_done = INTEL_EERD_DONE_LARGE;
+ intel->eerd_addr_shift = INTEL_EERD_ADDR_SHIFT_LARGE;
+ return 0;
+ }
+ if ( value & INTEL_EERD_DONE_SMALL ) {
+ DBGC ( intel, "INTEL %p has small-format EERD\n",
+ intel );
+ intel->eerd_done = INTEL_EERD_DONE_SMALL;
+ intel->eerd_addr_shift = INTEL_EERD_ADDR_SHIFT_SMALL;
+ return 0;
+ }
+ mdelay ( 1 );
+ }
+
+ DBGC ( intel, "INTEL %p timed out waiting for initial EEPROM read "
+ "(value %08x)\n", intel, value );
+ return -ETIMEDOUT;
+}
+
+/******************************************************************************
+ *
+ * MAC address
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Fetch initial MAC address from EEPROM
+ *
+ * @v intel Intel device
+ * @v hw_addr Hardware address to fill in
+ * @ret rc Return status code
+ */
+static int intel_fetch_mac_eeprom ( struct intel_nic *intel,
+ uint8_t *hw_addr ) {
+ int rc;
+
+ /* Initialise EEPROM */
+ if ( ( rc = intel_init_eeprom ( intel ) ) != 0 )
+ return rc;
+
+ /* Read base MAC address from EEPROM */
+ if ( ( rc = nvs_read ( &intel->eeprom, INTEL_EEPROM_MAC,
+ hw_addr, ETH_ALEN ) ) != 0 ) {
+ DBGC ( intel, "INTEL %p could not read EEPROM base MAC "
+ "address: %s\n", intel, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Adjust MAC address for multi-port devices */
+ hw_addr[ETH_ALEN-1] ^= intel->port;
+
+ DBGC ( intel, "INTEL %p has EEPROM MAC address %s (port %d)\n",
+ intel, eth_ntoa ( hw_addr ), intel->port );
+ return 0;
+}
+
+/**
+ * Fetch initial MAC address
+ *
+ * @v intel Intel device
+ * @v hw_addr Hardware address to fill in
+ * @ret rc Return status code
+ */
+static int intel_fetch_mac ( struct intel_nic *intel, uint8_t *hw_addr ) {
+ union intel_receive_address mac;
+ int rc;
+
+ /* Read current address from RAL0/RAH0 */
+ mac.reg.low = cpu_to_le32 ( readl ( intel->regs + INTEL_RAL0 ) );
+ mac.reg.high = cpu_to_le32 ( readl ( intel->regs + INTEL_RAH0 ) );
+ DBGC ( intel, "INTEL %p has autoloaded MAC address %s\n",
+ intel, eth_ntoa ( mac.raw ) );
+
+ /* Try to read address from EEPROM */
+ if ( ( rc = intel_fetch_mac_eeprom ( intel, hw_addr ) ) == 0 )
+ return 0;
+
+ /* Use current address if valid */
+ if ( is_valid_ether_addr ( mac.raw ) ) {
+ memcpy ( hw_addr, mac.raw, ETH_ALEN );
+ return 0;
+ }
+
+ DBGC ( intel, "INTEL %p has no MAC address to use\n", intel );
+ return -ENOENT;
+}
+
+/******************************************************************************
+ *
+ * Diagnostics
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Dump diagnostic information
+ *
+ * @v intel Intel device
+ */
+static void __attribute__ (( unused )) intel_diag ( struct intel_nic *intel ) {
+
+ DBGC ( intel, "INTEL %p TDH=%04x TDT=%04x RDH=%04x RDT=%04x\n", intel,
+ readl ( intel->regs + INTEL_TDH ),
+ readl ( intel->regs + INTEL_TDT ),
+ readl ( intel->regs + INTEL_RDH ),
+ readl ( intel->regs + INTEL_RDT ) );
+}
+
+/******************************************************************************
+ *
+ * Device reset
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Reset hardware
+ *
+ * @v intel Intel device
+ * @ret rc Return status code
+ */
+static int intel_reset ( struct intel_nic *intel ) {
+ uint32_t pbs;
+ uint32_t ctrl;
+ uint32_t status;
+
+ /* Force RX and TX packet buffer allocation, to work around an
+ * errata in ICH devices.
+ */
+ pbs = readl ( intel->regs + INTEL_PBS );
+ if ( ( pbs == 0x14 ) || ( pbs == 0x18 ) ) {
+ DBGC ( intel, "INTEL %p WARNING: applying ICH PBS/PBA errata\n",
+ intel );
+ writel ( 0x08, intel->regs + INTEL_PBA );
+ writel ( 0x10, intel->regs + INTEL_PBS );
+ }
+
+ /* Always reset MAC. Required to reset the TX and RX rings. */
+ ctrl = readl ( intel->regs + INTEL_CTRL );
+ writel ( ( ctrl | INTEL_CTRL_RST ), intel->regs + INTEL_CTRL );
+ mdelay ( INTEL_RESET_DELAY_MS );
+
+ /* Set a sensible default configuration */
+ ctrl |= ( INTEL_CTRL_SLU | INTEL_CTRL_ASDE );
+ ctrl &= ~( INTEL_CTRL_LRST | INTEL_CTRL_FRCSPD | INTEL_CTRL_FRCDPLX );
+ writel ( ctrl, intel->regs + INTEL_CTRL );
+ mdelay ( INTEL_RESET_DELAY_MS );
+
+ /* If link is already up, do not attempt to reset the PHY. On
+ * some models (notably ICH), performing a PHY reset seems to
+ * drop the link speed to 10Mbps.
+ */
+ status = readl ( intel->regs + INTEL_STATUS );
+ if ( status & INTEL_STATUS_LU ) {
+ DBGC ( intel, "INTEL %p MAC reset (ctrl %08x)\n",
+ intel, ctrl );
+ return 0;
+ }
+
+ /* Reset PHY and MAC simultaneously */
+ writel ( ( ctrl | INTEL_CTRL_RST | INTEL_CTRL_PHY_RST ),
+ intel->regs + INTEL_CTRL );
+ mdelay ( INTEL_RESET_DELAY_MS );
+
+ /* PHY reset is not self-clearing on all models */
+ writel ( ctrl, intel->regs + INTEL_CTRL );
+ mdelay ( INTEL_RESET_DELAY_MS );
+
+ DBGC ( intel, "INTEL %p MAC+PHY reset (ctrl %08x)\n", intel, ctrl );
+ return 0;
+}
+
+/******************************************************************************
+ *
+ * Link state
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Check link state
+ *
+ * @v netdev Network device
+ */
+static void intel_check_link ( struct net_device *netdev ) {
+ struct intel_nic *intel = netdev->priv;
+ uint32_t status;
+
+ /* Read link status */
+ status = readl ( intel->regs + INTEL_STATUS );
+ DBGC ( intel, "INTEL %p link status is %08x\n", intel, status );
+
+ /* Update network device */
+ if ( status & INTEL_STATUS_LU ) {
+ netdev_link_up ( netdev );
+ } else {
+ netdev_link_down ( netdev );
+ }
+}
+
+/******************************************************************************
+ *
+ * Network device interface
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Create descriptor ring
+ *
+ * @v intel Intel device
+ * @v ring Descriptor ring
+ * @ret rc Return status code
+ */
+static int intel_create_ring ( struct intel_nic *intel,
+ struct intel_ring *ring ) {
+ physaddr_t address;
+
+ /* Allocate descriptor ring. Align ring on its own size to
+ * prevent any possible page-crossing errors due to hardware
+ * errata.
+ */
+ ring->desc = malloc_dma ( ring->len, ring->len );
+ if ( ! ring->desc )
+ return -ENOMEM;
+
+ /* Initialise descriptor ring */
+ memset ( ring->desc, 0, ring->len );
+
+ /* Program ring address */
+ address = virt_to_bus ( ring->desc );
+ writel ( ( address & 0xffffffffUL ),
+ ( intel->regs + ring->reg + INTEL_xDBAL ) );
+ if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) {
+ writel ( ( ( ( uint64_t ) address ) >> 32 ),
+ ( intel->regs + ring->reg + INTEL_xDBAH ) );
+ } else {
+ writel ( 0, intel->regs + ring->reg + INTEL_xDBAH );
+ }
+
+ /* Program ring length */
+ writel ( ring->len, ( intel->regs + ring->reg + INTEL_xDLEN ) );
+
+ /* Reset head and tail pointers */
+ writel ( 0, ( intel->regs + ring->reg + INTEL_xDH ) );
+ writel ( 0, ( intel->regs + ring->reg + INTEL_xDT ) );
+
+ DBGC ( intel, "INTEL %p ring %05x is at [%08llx,%08llx)\n",
+ intel, ring->reg, ( ( unsigned long long ) address ),
+ ( ( unsigned long long ) address + ring->len ) );
+
+ return 0;
+}
+
+/**
+ * Destroy descriptor ring
+ *
+ * @v intel Intel device
+ * @v ring Descriptor ring
+ */
+static void intel_destroy_ring ( struct intel_nic *intel,
+ struct intel_ring *ring ) {
+
+ /* Clear ring length */
+ writel ( 0, ( intel->regs + ring->reg + INTEL_xDLEN ) );
+
+ /* Clear ring address */
+ writel ( 0, ( intel->regs + ring->reg + INTEL_xDBAL ) );
+ writel ( 0, ( intel->regs + ring->reg + INTEL_xDBAH ) );
+
+ /* Free descriptor ring */
+ free_dma ( ring->desc, ring->len );
+ ring->desc = NULL;
+ ring->prod = 0;
+ ring->cons = 0;
+}
+
+/**
+ * Refill receive descriptor ring
+ *
+ * @v intel Intel device
+ */
+static void intel_refill_rx ( struct intel_nic *intel ) {
+ struct intel_descriptor *rx;
+ struct io_buffer *iobuf;
+ unsigned int rx_idx;
+ unsigned int rx_tail;
+ physaddr_t address;
+
+ while ( ( intel->rx.prod - intel->rx.cons ) < INTEL_RX_FILL ) {
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( INTEL_RX_MAX_LEN );
+ if ( ! iobuf ) {
+ /* Wait for next refill */
+ return;
+ }
+
+ /* Get next receive descriptor */
+ rx_idx = ( intel->rx.prod++ % INTEL_NUM_RX_DESC );
+ rx_tail = ( intel->rx.prod % INTEL_NUM_RX_DESC );
+ rx = &intel->rx.desc[rx_idx];
+
+ /* Populate receive descriptor */
+ address = virt_to_bus ( iobuf->data );
+ rx->address = cpu_to_le64 ( address );
+ rx->length = 0;
+ rx->status = 0;
+ rx->errors = 0;
+ wmb();
+
+ /* Record I/O buffer */
+ assert ( intel->rx_iobuf[rx_idx] == NULL );
+ intel->rx_iobuf[rx_idx] = iobuf;
+
+ /* Push descriptor to card */
+ writel ( rx_tail, intel->regs + INTEL_RDT );
+
+ DBGC2 ( intel, "INTEL %p RX %d is [%llx,%llx)\n", intel, rx_idx,
+ ( ( unsigned long long ) address ),
+ ( ( unsigned long long ) address + INTEL_RX_MAX_LEN ) );
+ }
+}
+
+/**
+ * Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int intel_open ( struct net_device *netdev ) {
+ struct intel_nic *intel = netdev->priv;
+ union intel_receive_address mac;
+ uint32_t tctl;
+ uint32_t rctl;
+ int rc;
+
+ /* Create transmit descriptor ring */
+ if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 )
+ goto err_create_tx;
+
+ /* Create receive descriptor ring */
+ if ( ( rc = intel_create_ring ( intel, &intel->rx ) ) != 0 )
+ goto err_create_rx;
+
+ /* Fill receive ring */
+ intel_refill_rx ( intel );
+
+ /* Program MAC address */
+ memset ( &mac, 0, sizeof ( mac ) );
+ memcpy ( mac.raw, netdev->ll_addr, sizeof ( mac.raw ) );
+ writel ( le32_to_cpu ( mac.reg.low ), intel->regs + INTEL_RAL0 );
+ writel ( ( le32_to_cpu ( mac.reg.high ) | INTEL_RAH0_AV ),
+ intel->regs + INTEL_RAH0 );
+
+ /* Enable transmitter */
+ tctl = readl ( intel->regs + INTEL_TCTL );
+ tctl &= ~( INTEL_TCTL_CT_MASK | INTEL_TCTL_COLD_MASK );
+ tctl |= ( INTEL_TCTL_EN | INTEL_TCTL_PSP | INTEL_TCTL_CT_DEFAULT |
+ INTEL_TCTL_COLD_DEFAULT );
+ writel ( tctl, intel->regs + INTEL_TCTL );
+
+ /* Enable receiver */
+ rctl = readl ( intel->regs + INTEL_RCTL );
+ rctl &= ~( INTEL_RCTL_BSIZE_BSEX_MASK );
+ rctl |= ( INTEL_RCTL_EN | INTEL_RCTL_UPE | INTEL_RCTL_MPE |
+ INTEL_RCTL_BAM | INTEL_RCTL_BSIZE_2048 | INTEL_RCTL_SECRC );
+ writel ( rctl, intel->regs + INTEL_RCTL );
+
+ /* Update link state */
+ intel_check_link ( netdev );
+
+ return 0;
+
+ intel_destroy_ring ( intel, &intel->rx );
+ err_create_rx:
+ intel_destroy_ring ( intel, &intel->tx );
+ err_create_tx:
+ return rc;
+}
+
+/**
+ * Close network device
+ *
+ * @v netdev Network device
+ */
+static void intel_close ( struct net_device *netdev ) {
+ struct intel_nic *intel = netdev->priv;
+ unsigned int i;
+
+ /* Disable receiver */
+ writel ( 0, intel->regs + INTEL_RCTL );
+
+ /* Disable transmitter */
+ writel ( 0, intel->regs + INTEL_TCTL );
+
+ /* Destroy receive descriptor ring */
+ intel_destroy_ring ( intel, &intel->rx );
+
+ /* Discard any unused receive buffers */
+ for ( i = 0 ; i < INTEL_NUM_RX_DESC ; i++ ) {
+ if ( intel->rx_iobuf[i] )
+ free_iob ( intel->rx_iobuf[i] );
+ intel->rx_iobuf[i] = NULL;
+ }
+
+ /* Destroy transmit descriptor ring */
+ intel_destroy_ring ( intel, &intel->tx );
+
+ /* Reset the NIC, to flush the transmit and receive FIFOs */
+ intel_reset ( intel );
+}
+
+/**
+ * Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int intel_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct intel_nic *intel = netdev->priv;
+ struct intel_descriptor *tx;
+ unsigned int tx_idx;
+ unsigned int tx_tail;
+ physaddr_t address;
+
+ /* Get next transmit descriptor */
+ if ( ( intel->tx.prod - intel->tx.cons ) >= INTEL_NUM_TX_DESC ) {
+ DBGC ( intel, "INTEL %p out of transmit descriptors\n", intel );
+ return -ENOBUFS;
+ }
+ tx_idx = ( intel->tx.prod++ % INTEL_NUM_TX_DESC );
+ tx_tail = ( intel->tx.prod % INTEL_NUM_TX_DESC );
+ tx = &intel->tx.desc[tx_idx];
+
+ /* Populate transmit descriptor */
+ address = virt_to_bus ( iobuf->data );
+ tx->address = cpu_to_le64 ( address );
+ tx->length = cpu_to_le16 ( iob_len ( iobuf ) );
+ tx->command = ( INTEL_DESC_CMD_RS | INTEL_DESC_CMD_IFCS |
+ INTEL_DESC_CMD_EOP );
+ tx->status = 0;
+ wmb();
+
+ /* Notify card that there are packets ready to transmit */
+ writel ( tx_tail, intel->regs + INTEL_TDT );
+
+ DBGC2 ( intel, "INTEL %p TX %d is [%llx,%llx)\n", intel, tx_idx,
+ ( ( unsigned long long ) address ),
+ ( ( unsigned long long ) address + iob_len ( iobuf ) ) );
+
+ return 0;
+}
+
+/**
+ * Poll for completed packets
+ *
+ * @v netdev Network device
+ */
+static void intel_poll_tx ( struct net_device *netdev ) {
+ struct intel_nic *intel = netdev->priv;
+ struct intel_descriptor *tx;
+ unsigned int tx_idx;
+
+ /* Check for completed packets */
+ while ( intel->tx.cons != intel->tx.prod ) {
+
+ /* Get next transmit descriptor */
+ tx_idx = ( intel->tx.cons % INTEL_NUM_TX_DESC );
+ tx = &intel->tx.desc[tx_idx];
+
+ /* Stop if descriptor is still in use */
+ if ( ! ( tx->status & INTEL_DESC_STATUS_DD ) )
+ return;
+
+ DBGC2 ( intel, "INTEL %p TX %d complete\n", intel, tx_idx );
+
+ /* Complete TX descriptor */
+ netdev_tx_complete_next ( netdev );
+ intel->tx.cons++;
+ }
+}
+
+/**
+ * Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void intel_poll_rx ( struct net_device *netdev ) {
+ struct intel_nic *intel = netdev->priv;
+ struct intel_descriptor *rx;
+ struct io_buffer *iobuf;
+ unsigned int rx_idx;
+ size_t len;
+
+ /* Check for received packets */
+ while ( intel->rx.cons != intel->rx.prod ) {
+
+ /* Get next receive descriptor */
+ rx_idx = ( intel->rx.cons % INTEL_NUM_RX_DESC );
+ rx = &intel->rx.desc[rx_idx];
+
+ /* Stop if descriptor is still in use */
+ if ( ! ( rx->status & INTEL_DESC_STATUS_DD ) )
+ return;
+
+ /* Populate I/O buffer */
+ iobuf = intel->rx_iobuf[rx_idx];
+ intel->rx_iobuf[rx_idx] = NULL;
+ len = le16_to_cpu ( rx->length );
+ iob_put ( iobuf, len );
+
+ /* Hand off to network stack */
+ if ( rx->errors ) {
+ DBGC ( intel, "INTEL %p RX %d error (length %zd, "
+ "errors %02x)\n",
+ intel, rx_idx, len, rx->errors );
+ netdev_rx_err ( netdev, iobuf, -EIO );
+ } else {
+ DBGC2 ( intel, "INTEL %p RX %d complete (length %zd)\n",
+ intel, rx_idx, len );
+ netdev_rx ( netdev, iobuf );
+ }
+ intel->rx.cons++;
+ }
+}
+
+/**
+ * Poll for completed and received packets
+ *
+ * @v netdev Network device
+ */
+static void intel_poll ( struct net_device *netdev ) {
+ struct intel_nic *intel = netdev->priv;
+ uint32_t icr;
+
+ /* Check for and acknowledge interrupts */
+ icr = readl ( intel->regs + INTEL_ICR );
+ if ( ! icr )
+ return;
+
+ /* Poll for TX completions, if applicable */
+ if ( icr & INTEL_IRQ_TXDW )
+ intel_poll_tx ( netdev );
+
+ /* Poll for RX completionsm, if applicable */
+ if ( icr & INTEL_IRQ_RXT0 )
+ intel_poll_rx ( netdev );
+
+ /* Check link state, if applicable */
+ if ( icr & INTEL_IRQ_LSC )
+ intel_check_link ( netdev );
+
+ /* Refill RX ring */
+ intel_refill_rx ( intel );
+}
+
+/**
+ * Enable or disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void intel_irq ( struct net_device *netdev, int enable ) {
+ struct intel_nic *intel = netdev->priv;
+ uint32_t mask;
+
+ mask = ( INTEL_IRQ_TXDW | INTEL_IRQ_LSC | INTEL_IRQ_RXT0 );
+ if ( enable ) {
+ writel ( mask, intel->regs + INTEL_IMS );
+ } else {
+ writel ( mask, intel->regs + INTEL_IMC );
+ }
+}
+
+/** Intel network device operations */
+static struct net_device_operations intel_operations = {
+ .open = intel_open,
+ .close = intel_close,
+ .transmit = intel_transmit,
+ .poll = intel_poll,
+ .irq = intel_irq,
+};
+
+/******************************************************************************
+ *
+ * PCI interface
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @ret rc Return status code
+ */
+static int intel_probe ( struct pci_device *pci ) {
+ struct net_device *netdev;
+ struct intel_nic *intel;
+ int rc;
+
+ /* Allocate and initialise net device */
+ netdev = alloc_etherdev ( sizeof ( *intel ) );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ netdev_init ( netdev, &intel_operations );
+ intel = netdev->priv;
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+ memset ( intel, 0, sizeof ( *intel ) );
+ intel->port = PCI_FUNC ( pci->busdevfn );
+ intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTEL_TD );
+ intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTEL_RD );
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* Map registers */
+ intel->regs = ioremap ( pci->membase, INTEL_BAR_SIZE );
+
+ /* Reset the NIC */
+ if ( ( rc = intel_reset ( intel ) ) != 0 )
+ goto err_reset;
+
+ /* Fetch MAC address */
+ if ( ( rc = intel_fetch_mac ( intel, netdev->hw_addr ) ) != 0 )
+ goto err_fetch_mac;
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register_netdev;
+
+ /* Set initial link state */
+ intel_check_link ( netdev );
+
+ return 0;
+
+ unregister_netdev ( netdev );
+ err_register_netdev:
+ err_fetch_mac:
+ intel_reset ( intel );
+ err_reset:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void intel_remove ( struct pci_device *pci ) {
+ struct net_device *netdev = pci_get_drvdata ( pci );
+ struct intel_nic *intel = netdev->priv;
+
+ /* Unregister network device */
+ unregister_netdev ( netdev );
+
+ /* Reset the NIC */
+ intel_reset ( intel );
+
+ /* Free network device */
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/** Intel PCI device IDs */
+static struct pci_device_id intel_nics[] = {
+ PCI_ROM ( 0x8086, 0x0438, "dh8900cc", "DH8900CC", 0 ),
+ PCI_ROM ( 0x8086, 0x043a, "dh8900cc-f", "DH8900CC Fiber", 0 ),
+ PCI_ROM ( 0x8086, 0x043c, "dh8900cc-b", "DH8900CC Backplane", 0 ),
+ PCI_ROM ( 0x8086, 0x0440, "dh8900cc-s", "DH8900CC SFP", 0 ),
+ PCI_ROM ( 0x8086, 0x1000, "82542-f", "82542 (Fiber)", 0 ),
+ PCI_ROM ( 0x8086, 0x1001, "82543gc-f", "82543GC (Fiber)", 0 ),
+ PCI_ROM ( 0x8086, 0x1004, "82543gc", "82543GC (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x1008, "82544ei", "82544EI (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x1009, "82544ei-f", "82544EI (Fiber)", 0 ),
+ PCI_ROM ( 0x8086, 0x100c, "82544gc", "82544GC (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x100d, "82544gc-l", "82544GC (LOM)", 0 ),
+ PCI_ROM ( 0x8086, 0x100e, "82540em", "82540EM", 0 ),
+ PCI_ROM ( 0x8086, 0x100f, "82545em", "82545EM (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x1010, "82546eb", "82546EB (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x1011, "82545em-f", "82545EM (Fiber)", 0 ),
+ PCI_ROM ( 0x8086, 0x1012, "82546eb-f", "82546EB (Fiber)", 0 ),
+ PCI_ROM ( 0x8086, 0x1013, "82541ei", "82541EI", 0 ),
+ PCI_ROM ( 0x8086, 0x1014, "82541er", "82541ER", 0 ),
+ PCI_ROM ( 0x8086, 0x1015, "82540em-l", "82540EM (LOM)", 0 ),
+ PCI_ROM ( 0x8086, 0x1016, "82540ep-m", "82540EP (Mobile)", 0 ),
+ PCI_ROM ( 0x8086, 0x1017, "82540ep", "82540EP", 0 ),
+ PCI_ROM ( 0x8086, 0x1018, "82541ei", "82541EI", 0 ),
+ PCI_ROM ( 0x8086, 0x1019, "82547ei", "82547EI", 0 ),
+ PCI_ROM ( 0x8086, 0x101a, "82547ei-m", "82547EI (Mobile)", 0 ),
+ PCI_ROM ( 0x8086, 0x101d, "82546eb", "82546EB", 0 ),
+ PCI_ROM ( 0x8086, 0x101e, "82540ep-m", "82540EP (Mobile)", 0 ),
+ PCI_ROM ( 0x8086, 0x1026, "82545gm", "82545GM", 0 ),
+ PCI_ROM ( 0x8086, 0x1027, "82545gm-1", "82545GM", 0 ),
+ PCI_ROM ( 0x8086, 0x1028, "82545gm-2", "82545GM", 0 ),
+ PCI_ROM ( 0x8086, 0x1049, "82566mm", "82566MM", 0 ),
+ PCI_ROM ( 0x8086, 0x104a, "82566dm", "82566DM", 0 ),
+ PCI_ROM ( 0x8086, 0x104b, "82566dc", "82566DC", 0 ),
+ PCI_ROM ( 0x8086, 0x104c, "82562v", "82562V 10/100", 0 ),
+ PCI_ROM ( 0x8086, 0x104d, "82566mc", "82566MC", 0 ),
+ PCI_ROM ( 0x8086, 0x105e, "82571eb", "82571EB", 0 ),
+ PCI_ROM ( 0x8086, 0x105f, "82571eb-1", "82571EB", 0 ),
+ PCI_ROM ( 0x8086, 0x1060, "82571eb-2", "82571EB", 0 ),
+ PCI_ROM ( 0x8086, 0x1075, "82547gi", "82547GI", 0 ),
+ PCI_ROM ( 0x8086, 0x1076, "82541gi", "82541GI", 0 ),
+ PCI_ROM ( 0x8086, 0x1077, "82541gi-1", "82541GI", 0 ),
+ PCI_ROM ( 0x8086, 0x1078, "82541er", "82541ER", 0 ),
+ PCI_ROM ( 0x8086, 0x1079, "82546gb", "82546GB", 0 ),
+ PCI_ROM ( 0x8086, 0x107a, "82546gb-1", "82546GB", 0 ),
+ PCI_ROM ( 0x8086, 0x107b, "82546gb-2", "82546GB", 0 ),
+ PCI_ROM ( 0x8086, 0x107c, "82541pi", "82541PI", 0 ),
+ PCI_ROM ( 0x8086, 0x107d, "82572ei", "82572EI (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x107e, "82572ei-f", "82572EI (Fiber)", 0 ),
+ PCI_ROM ( 0x8086, 0x107f, "82572ei", "82572EI", 0 ),
+ PCI_ROM ( 0x8086, 0x108a, "82546gb-3", "82546GB", 0 ),
+ PCI_ROM ( 0x8086, 0x108b, "82573v", "82573V (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x108c, "82573e", "82573E (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x1096, "80003es2lan", "80003ES2LAN (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x1098, "80003es2lan-s", "80003ES2LAN (Serdes)", 0 ),
+ PCI_ROM ( 0x8086, 0x1099, "82546gb-4", "82546GB (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x109a, "82573l", "82573L", 0 ),
+ PCI_ROM ( 0x8086, 0x10a4, "82571eb", "82571EB", 0 ),
+ PCI_ROM ( 0x8086, 0x10a5, "82571eb", "82571EB (Fiber)", 0 ),
+ PCI_ROM ( 0x8086, 0x10a7, "82575eb", "82575EB", 0 ),
+ PCI_ROM ( 0x8086, 0x10a9, "82575eb", "82575EB Backplane", 0 ),
+ PCI_ROM ( 0x8086, 0x10b5, "82546gb", "82546GB (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x10b9, "82572ei", "82572EI (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x10ba, "80003es2lan", "80003ES2LAN (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x10bb, "80003es2lan", "80003ES2LAN (Serdes)", 0 ),
+ PCI_ROM ( 0x8086, 0x10bc, "82571eb", "82571EB (Copper)", 0 ),
+ PCI_ROM ( 0x8086, 0x10bd, "82566dm-2", "82566DM-2", 0 ),
+ PCI_ROM ( 0x8086, 0x10bf, "82567lf", "82567LF", 0 ),
+ PCI_ROM ( 0x8086, 0x10c0, "82562v-2", "82562V-2 10/100", 0 ),
+ PCI_ROM ( 0x8086, 0x10c2, "82562g-2", "82562G-2 10/100", 0 ),
+ PCI_ROM ( 0x8086, 0x10c3, "82562gt-2", "82562GT-2 10/100", 0 ),
+ PCI_ROM ( 0x8086, 0x10c4, "82562gt", "82562GT 10/100", 0 ),
+ PCI_ROM ( 0x8086, 0x10c5, "82562g", "82562G 10/100", 0 ),
+ PCI_ROM ( 0x8086, 0x10c9, "82576", "82576", 0 ),
+ PCI_ROM ( 0x8086, 0x10cb, "82567v", "82567V", 0 ),
+ PCI_ROM ( 0x8086, 0x10cc, "82567lm-2", "82567LM-2", 0 ),
+ PCI_ROM ( 0x8086, 0x10cd, "82567lf-2", "82567LF-2", 0 ),
+ PCI_ROM ( 0x8086, 0x10ce, "82567v-2", "82567V-2", 0 ),
+ PCI_ROM ( 0x8086, 0x10d3, "82574l", "82574L", 0 ),
+ PCI_ROM ( 0x8086, 0x10d5, "82571pt", "82571PT PT Quad", 0 ),
+ PCI_ROM ( 0x8086, 0x10d6, "82575gb", "82575GB", 0 ),
+ PCI_ROM ( 0x8086, 0x10d9, "82571eb-d", "82571EB Dual Mezzanine", 0 ),
+ PCI_ROM ( 0x8086, 0x10da, "82571eb-q", "82571EB Quad Mezzanine", 0 ),
+ PCI_ROM ( 0x8086, 0x10de, "82567lm-3", "82567LM-3", 0 ),
+ PCI_ROM ( 0x8086, 0x10df, "82567lf-3", "82567LF-3", 0 ),
+ PCI_ROM ( 0x8086, 0x10e5, "82567lm-4", "82567LM-4", 0 ),
+ PCI_ROM ( 0x8086, 0x10e6, "82576", "82576", 0 ),
+ PCI_ROM ( 0x8086, 0x10e7, "82576-2", "82576", 0 ),
+ PCI_ROM ( 0x8086, 0x10e8, "82576-3", "82576", 0 ),
+ PCI_ROM ( 0x8086, 0x10ea, "82577lm", "82577LM", 0 ),
+ PCI_ROM ( 0x8086, 0x10eb, "82577lc", "82577LC", 0 ),
+ PCI_ROM ( 0x8086, 0x10ef, "82578dm", "82578DM", 0 ),
+ PCI_ROM ( 0x8086, 0x10f0, "82578dc", "82578DC", 0 ),
+ PCI_ROM ( 0x8086, 0x10f5, "82567lm", "82567LM", 0 ),
+ PCI_ROM ( 0x8086, 0x10f6, "82574l", "82574L", 0 ),
+ PCI_ROM ( 0x8086, 0x1501, "82567v-3", "82567V-3", 0 ),
+ PCI_ROM ( 0x8086, 0x1502, "82579lm", "82579LM", 0 ),
+ PCI_ROM ( 0x8086, 0x1503, "82579v", "82579V", 0 ),
+ PCI_ROM ( 0x8086, 0x150a, "82576ns", "82576NS", 0 ),
+ PCI_ROM ( 0x8086, 0x150c, "82583v", "82583V", 0 ),
+ PCI_ROM ( 0x8086, 0x150d, "82576-4", "82576 Backplane", 0 ),
+ PCI_ROM ( 0x8086, 0x150e, "82580", "82580", 0 ),
+ PCI_ROM ( 0x8086, 0x150f, "82580-f", "82580 Fiber", 0 ),
+ PCI_ROM ( 0x8086, 0x1510, "82580-b", "82580 Backplane", 0 ),
+ PCI_ROM ( 0x8086, 0x1511, "82580-s", "82580 SFP", 0 ),
+ PCI_ROM ( 0x8086, 0x1516, "82580-2", "82580", 0 ),
+ PCI_ROM ( 0x8086, 0x1518, "82576ns", "82576NS SerDes", 0 ),
+ PCI_ROM ( 0x8086, 0x1521, "i350", "I350", 0 ),
+ PCI_ROM ( 0x8086, 0x1522, "i350-f", "I350 Fiber", 0 ),
+ PCI_ROM ( 0x8086, 0x1523, "i350-b", "I350 Backplane", 0 ),
+ PCI_ROM ( 0x8086, 0x1524, "i350-2", "I350", 0 ),
+ PCI_ROM ( 0x8086, 0x1525, "82567v-4", "82567V-4", 0 ),
+ PCI_ROM ( 0x8086, 0x1526, "82576-5", "82576", 0 ),
+ PCI_ROM ( 0x8086, 0x1527, "82580-f2", "82580 Fiber", 0 ),
+ PCI_ROM ( 0x8086, 0x294c, "82566dc-2", "82566DC-2", 0 ),
+ PCI_ROM ( 0x8086, 0x2e6e, "cemedia", "CE Media Processor", 0 ),
+};
+
+/** Intel PCI driver */
+struct pci_driver intel_driver __pci_driver = {
+ .ids = intel_nics,
+ .id_count = ( sizeof ( intel_nics ) / sizeof ( intel_nics[0] ) ),
+ .probe = intel_probe,
+ .remove = intel_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/intel.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/intel.h
new file mode 100644
index 00000000..6f941d17
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/intel.h
@@ -0,0 +1,252 @@
+#ifndef _INTEL_H
+#define _INTEL_H
+
+/** @file
+ *
+ * Intel 10/100/1000 network card driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/nvs.h>
+
+/** Intel BAR size */
+#define INTEL_BAR_SIZE ( 128 * 1024 )
+
+/** A packet descriptor */
+struct intel_descriptor {
+ /** Buffer address */
+ uint64_t address;
+ /** Length */
+ uint16_t length;
+ /** Reserved */
+ uint8_t reserved_a;
+ /** Command */
+ uint8_t command;
+ /** Status */
+ uint8_t status;
+ /** Errors */
+ uint8_t errors;
+ /** Reserved */
+ uint16_t reserved_b;
+} __attribute__ (( packed ));
+
+/** Packet descriptor command bits */
+enum intel_descriptor_command {
+ /** Report status */
+ INTEL_DESC_CMD_RS = 0x08,
+ /** Insert frame checksum (CRC) */
+ INTEL_DESC_CMD_IFCS = 0x02,
+ /** End of packet */
+ INTEL_DESC_CMD_EOP = 0x01,
+};
+
+/** Packet descriptor status bits */
+enum intel_descriptor_status {
+ /** Descriptor done */
+ INTEL_DESC_STATUS_DD = 0x01,
+};
+
+/** Device Control Register */
+#define INTEL_CTRL 0x00000UL
+#define INTEL_CTRL_LRST 0x00000008UL /**< Link reset */
+#define INTEL_CTRL_ASDE 0x00000020UL /**< Auto-speed detection */
+#define INTEL_CTRL_SLU 0x00000040UL /**< Set link up */
+#define INTEL_CTRL_FRCSPD 0x00000800UL /**< Force speed */
+#define INTEL_CTRL_FRCDPLX 0x00001000UL /**< Force duplex */
+#define INTEL_CTRL_RST 0x04000000UL /**< Device reset */
+#define INTEL_CTRL_PHY_RST 0x80000000UL /**< PHY reset */
+
+/** Time to delay for device reset, in milliseconds */
+#define INTEL_RESET_DELAY_MS 20
+
+/** Device Status Register */
+#define INTEL_STATUS 0x00008UL
+#define INTEL_STATUS_LU 0x00000002UL /**< Link up */
+
+/** EEPROM Read Register */
+#define INTEL_EERD 0x00014UL
+#define INTEL_EERD_START 0x00000001UL /**< Start read */
+#define INTEL_EERD_DONE_SMALL 0x00000010UL /**< Read done (small EERD) */
+#define INTEL_EERD_DONE_LARGE 0x00000002UL /**< Read done (large EERD) */
+#define INTEL_EERD_ADDR_SHIFT_SMALL 8 /**< Address shift (small) */
+#define INTEL_EERD_ADDR_SHIFT_LARGE 2 /**< Address shift (large) */
+#define INTEL_EERD_DATA(value) ( (value) >> 16 ) /**< Read data */
+
+/** Maximum time to wait for EEPROM read, in milliseconds */
+#define INTEL_EEPROM_MAX_WAIT_MS 100
+
+/** EEPROM word length */
+#define INTEL_EEPROM_WORD_LEN_LOG2 1
+
+/** Minimum EEPROM size, in words */
+#define INTEL_EEPROM_MIN_SIZE_WORDS 64
+
+/** Offset of MAC address within EEPROM */
+#define INTEL_EEPROM_MAC 0x00
+
+/** Interrupt Cause Read Register */
+#define INTEL_ICR 0x000c0UL
+#define INTEL_IRQ_TXDW 0x00000001UL /**< Transmit descriptor done */
+#define INTEL_IRQ_LSC 0x00000004UL /**< Link status change */
+#define INTEL_IRQ_RXT0 0x00000080UL /**< Receive timer */
+
+/** Interrupt Mask Set/Read Register */
+#define INTEL_IMS 0x000d0UL
+
+/** Interrupt Mask Clear Register */
+#define INTEL_IMC 0x000d8UL
+
+/** Receive Control Register */
+#define INTEL_RCTL 0x00100UL
+#define INTEL_RCTL_EN 0x00000002UL /**< Receive enable */
+#define INTEL_RCTL_UPE 0x00000008UL /**< Unicast promiscuous mode */
+#define INTEL_RCTL_MPE 0x00000010UL /**< Multicast promiscuous */
+#define INTEL_RCTL_BAM 0x00008000UL /**< Broadcast accept mode */
+#define INTEL_RCTL_BSIZE_BSEX(bsex,bsize) \
+ ( ( (bsize) << 16 ) | ( (bsex) << 25 ) ) /**< Buffer size */
+#define INTEL_RCTL_BSIZE_2048 INTEL_RCTL_BSIZE_BSEX ( 0, 0 )
+#define INTEL_RCTL_BSIZE_BSEX_MASK INTEL_RCTL_BSIZE_BSEX ( 1, 3 )
+#define INTEL_RCTL_SECRC 0x04000000UL /**< Strip CRC */
+
+/** Transmit Control Register */
+#define INTEL_TCTL 0x00400UL
+#define INTEL_TCTL_EN 0x00000002UL /**< Transmit enable */
+#define INTEL_TCTL_PSP 0x00000008UL /**< Pad short packets */
+#define INTEL_TCTL_CT(x) ( (x) << 4 ) /**< Collision threshold */
+#define INTEL_TCTL_CT_DEFAULT INTEL_TCTL_CT ( 0x0f )
+#define INTEL_TCTL_CT_MASK INTEL_TCTL_CT ( 0xff )
+#define INTEL_TCTL_COLD(x) ( (x) << 12 ) /**< Collision distance */
+#define INTEL_TCTL_COLD_DEFAULT INTEL_TCTL_COLD ( 0x040 )
+#define INTEL_TCTL_COLD_MASK INTEL_TCTL_COLD ( 0x3ff )
+
+/** Packet Buffer Allocation */
+#define INTEL_PBA 0x01000UL
+
+/** Packet Buffer Size */
+#define INTEL_PBS 0x01008UL
+
+/** Receive Descriptor register block */
+#define INTEL_RD 0x02800UL
+
+/** Number of receive descriptors
+ *
+ * Minimum value is 8, since the descriptor ring length must be a
+ * multiple of 128.
+ */
+#define INTEL_NUM_RX_DESC 8
+
+/** Receive descriptor ring fill level */
+#define INTEL_RX_FILL 4
+
+/** Receive buffer length */
+#define INTEL_RX_MAX_LEN 2048
+
+/** Transmit Descriptor register block */
+#define INTEL_TD 0x03800UL
+
+/** Number of transmit descriptors
+ *
+ * Descriptor ring length must be a multiple of 16. ICH8/9/10
+ * requires a minimum of 16 TX descriptors.
+ */
+#define INTEL_NUM_TX_DESC 16
+
+/** Receive/Transmit Descriptor Base Address Low (offset) */
+#define INTEL_xDBAL 0x00
+
+/** Receive/Transmit Descriptor Base Address High (offset) */
+#define INTEL_xDBAH 0x04
+
+/** Receive/Transmit Descriptor Length (offset) */
+#define INTEL_xDLEN 0x08
+
+/** Receive/Transmit Descriptor Head (offset) */
+#define INTEL_xDH 0x10
+
+/** Receive/Transmit Descriptor Tail (offset) */
+#define INTEL_xDT 0x18
+
+/** Receive Descriptor Head */
+#define INTEL_RDH ( INTEL_RD + INTEL_xDH )
+
+/** Receive Descriptor Tail */
+#define INTEL_RDT ( INTEL_RD + INTEL_xDT )
+
+/** Transmit Descriptor Head */
+#define INTEL_TDH ( INTEL_TD + INTEL_xDH )
+
+/** Transmit Descriptor Tail */
+#define INTEL_TDT ( INTEL_TD + INTEL_xDT )
+
+/** Receive Address Low */
+#define INTEL_RAL0 0x05400UL
+
+/** Receive Address High */
+#define INTEL_RAH0 0x05404UL
+#define INTEL_RAH0_AV 0x80000000UL /**< Address valid */
+
+/** Receive address */
+union intel_receive_address {
+ struct {
+ uint32_t low;
+ uint32_t high;
+ } __attribute__ (( packed )) reg;
+ uint8_t raw[ETH_ALEN];
+};
+
+/** An Intel descriptor ring */
+struct intel_ring {
+ /** Descriptors */
+ struct intel_descriptor *desc;
+ /** Producer index */
+ unsigned int prod;
+ /** Consumer index */
+ unsigned int cons;
+
+ /** Register block */
+ unsigned int reg;
+ /** Length (in bytes) */
+ size_t len;
+};
+
+/**
+ * Initialise descriptor ring
+ *
+ * @v ring Descriptor ring
+ * @v count Number of descriptors
+ * @v reg Descriptor register block
+ */
+static inline __attribute__ (( always_inline)) void
+intel_init_ring ( struct intel_ring *ring, unsigned int count,
+ unsigned int reg ) {
+ ring->len = ( count * sizeof ( ring->desc[0] ) );
+ ring->reg = reg;
+}
+
+/** An Intel network card */
+struct intel_nic {
+ /** Registers */
+ void *regs;
+ /** Port number (for multi-port devices) */
+ unsigned int port;
+
+ /** EEPROM */
+ struct nvs_device eeprom;
+ /** EEPROM done flag */
+ uint32_t eerd_done;
+ /** EEPROM address shift */
+ unsigned int eerd_addr_shift;
+
+ /** Transmit descriptor ring */
+ struct intel_ring tx;
+ /** Receive descriptor ring */
+ struct intel_ring rx;
+ /** Receive I/O buffers */
+ struct io_buffer *rx_iobuf[INTEL_NUM_RX_DESC];
+};
+
+#endif /* _INTEL_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ipoib.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ipoib.c
new file mode 100644
index 00000000..30ba10c7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ipoib.c
@@ -0,0 +1,795 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/errortab.h>
+#include <ipxe/if_arp.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/ib_pathrec.h>
+#include <ipxe/ib_mcast.h>
+#include <ipxe/ipoib.h>
+
+/** @file
+ *
+ * IP over Infiniband
+ */
+
+/** Number of IPoIB send work queue entries */
+#define IPOIB_NUM_SEND_WQES 2
+
+/** Number of IPoIB receive work queue entries */
+#define IPOIB_NUM_RECV_WQES 4
+
+/** Number of IPoIB completion entries */
+#define IPOIB_NUM_CQES 8
+
+/** An IPoIB device */
+struct ipoib_device {
+ /** Network device */
+ struct net_device *netdev;
+ /** Underlying Infiniband device */
+ struct ib_device *ibdev;
+ /** Completion queue */
+ struct ib_completion_queue *cq;
+ /** Queue pair */
+ struct ib_queue_pair *qp;
+ /** Broadcast MAC */
+ struct ipoib_mac broadcast;
+ /** Joined to IPv4 broadcast multicast group
+ *
+ * This flag indicates whether or not we have initiated the
+ * join to the IPv4 broadcast multicast group.
+ */
+ int broadcast_joined;
+ /** IPv4 broadcast multicast group membership */
+ struct ib_mc_membership broadcast_membership;
+};
+
+/** Broadcast IPoIB address */
+static struct ipoib_mac ipoib_broadcast = {
+ .flags__qpn = htonl ( IB_QPN_BROADCAST ),
+ .gid.bytes = { 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff },
+};
+
+/** Link status for "broadcast join in progress" */
+#define EINPROGRESS_JOINING __einfo_error ( EINFO_EINPROGRESS_JOINING )
+#define EINFO_EINPROGRESS_JOINING __einfo_uniqify \
+ ( EINFO_EINPROGRESS, 0x01, "Joining" )
+
+/** Human-readable message for the link status */
+struct errortab ipoib_errors[] __errortab = {
+ __einfo_errortab ( EINFO_EINPROGRESS_JOINING ),
+};
+
+/****************************************************************************
+ *
+ * IPoIB peer cache
+ *
+ ****************************************************************************
+ */
+
+/**
+ * IPoIB peer address
+ *
+ * The IPoIB link-layer header is only four bytes long and so does not
+ * have sufficient room to store IPoIB MAC address(es). We therefore
+ * maintain a cache of MAC addresses identified by a single-byte key,
+ * and abuse the spare two bytes within the link-layer header to
+ * communicate these MAC addresses between the link-layer code and the
+ * netdevice driver.
+ */
+struct ipoib_peer {
+ /** Key */
+ uint8_t key;
+ /** MAC address */
+ struct ipoib_mac mac;
+};
+
+/** Number of IPoIB peer cache entries
+ *
+ * Must be a power of two.
+ */
+#define IPOIB_NUM_CACHED_PEERS 4
+
+/** IPoIB peer address cache */
+static struct ipoib_peer ipoib_peer_cache[IPOIB_NUM_CACHED_PEERS];
+
+/** Oldest IPoIB peer cache entry index */
+static unsigned int ipoib_peer_cache_idx = 0;
+
+/** IPoIB peer cache entry validity flag */
+#define IPOIB_PEER_KEY_VALID 0x80
+
+/**
+ * Look up cached peer by key
+ *
+ * @v key Peer cache key
+ * @ret peer Peer cache entry, or NULL
+ */
+static struct ipoib_peer * ipoib_lookup_peer_by_key ( unsigned int key ) {
+ struct ipoib_peer *peer;
+ unsigned int i;
+
+ if ( ! key )
+ return NULL;
+
+ for ( i = 0 ; i < IPOIB_NUM_CACHED_PEERS ; i++ ) {
+ peer = &ipoib_peer_cache[i];
+ if ( peer->key == key )
+ return peer;
+ }
+
+ DBG ( "IPoIB warning: peer cache lost track of key %x while still in "
+ "use\n", key );
+ return NULL;
+}
+
+/**
+ * Store GID and QPN in peer cache
+ *
+ * @v mac Peer MAC address
+ * @ret peer Peer cache entry
+ */
+static struct ipoib_peer * ipoib_cache_peer ( const struct ipoib_mac *mac ) {
+ struct ipoib_peer *peer;
+ uint8_t key;
+ unsigned int i;
+
+ /* Look for existing cache entry */
+ for ( i = 0 ; i < IPOIB_NUM_CACHED_PEERS ; i++ ) {
+ peer = &ipoib_peer_cache[i];
+ if ( memcmp ( &peer->mac, mac, sizeof ( peer->mac ) ) == 0 )
+ return peer;
+ }
+
+ /* No entry found: create a new one */
+ key = ( ipoib_peer_cache_idx++ | IPOIB_PEER_KEY_VALID );
+ peer = &ipoib_peer_cache[ key % IPOIB_NUM_CACHED_PEERS ];
+ if ( peer->key )
+ DBG ( "IPoIB peer %x evicted from cache\n", peer->key );
+
+ memset ( peer, 0, sizeof ( *peer ) );
+ peer->key = key;
+ memcpy ( &peer->mac, mac, sizeof ( peer->mac ) );
+ DBG ( "IPoIB peer %x has MAC %s\n",
+ peer->key, ipoib_ntoa ( &peer->mac ) );
+ return peer;
+}
+
+/****************************************************************************
+ *
+ * IPoIB link layer
+ *
+ ****************************************************************************
+ */
+
+/**
+ * Add IPoIB link-layer header
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Source link-layer address
+ * @v net_proto Network-layer protocol, in network-byte order
+ * @ret rc Return status code
+ */
+static int ipoib_push ( struct net_device *netdev __unused,
+ struct io_buffer *iobuf, const void *ll_dest,
+ const void *ll_source __unused, uint16_t net_proto ) {
+ struct ipoib_hdr *ipoib_hdr =
+ iob_push ( iobuf, sizeof ( *ipoib_hdr ) );
+ const struct ipoib_mac *dest_mac = ll_dest;
+ const struct ipoib_mac *src_mac = ll_source;
+ struct ipoib_peer *dest;
+ struct ipoib_peer *src;
+
+ /* Add link-layer addresses to cache */
+ dest = ipoib_cache_peer ( dest_mac );
+ src = ipoib_cache_peer ( src_mac );
+
+ /* Build IPoIB header */
+ ipoib_hdr->proto = net_proto;
+ ipoib_hdr->u.peer.dest = dest->key;
+ ipoib_hdr->u.peer.src = src->key;
+
+ return 0;
+}
+
+/**
+ * Remove IPoIB link-layer header
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret ll_dest Link-layer destination address
+ * @ret ll_source Source link-layer address
+ * @ret net_proto Network-layer protocol, in network-byte order
+ * @ret flags Packet flags
+ * @ret rc Return status code
+ */
+static int ipoib_pull ( struct net_device *netdev,
+ struct io_buffer *iobuf, const void **ll_dest,
+ const void **ll_source, uint16_t *net_proto,
+ unsigned int *flags ) {
+ struct ipoib_device *ipoib = netdev->priv;
+ struct ipoib_hdr *ipoib_hdr = iobuf->data;
+ struct ipoib_peer *dest;
+ struct ipoib_peer *source;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
+ DBG ( "IPoIB packet too short for link-layer header\n" );
+ DBG_HD ( iobuf->data, iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+
+ /* Strip off IPoIB header */
+ iob_pull ( iobuf, sizeof ( *ipoib_hdr ) );
+
+ /* Identify source and destination addresses, and clear
+ * reserved word in IPoIB header
+ */
+ dest = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest );
+ source = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.src );
+ ipoib_hdr->u.reserved = 0;
+
+ /* Fill in required fields */
+ *ll_dest = ( dest ? &dest->mac : &ipoib->broadcast );
+ *ll_source = ( source ? &source->mac : &ipoib->broadcast );
+ *net_proto = ipoib_hdr->proto;
+ *flags = ( ( *ll_dest == &ipoib->broadcast ) ?
+ ( LL_MULTICAST | LL_BROADCAST ) : 0 );
+
+ return 0;
+}
+
+/**
+ * Initialise IPoIB link-layer address
+ *
+ * @v hw_addr Hardware address
+ * @v ll_addr Link-layer address
+ */
+static void ipoib_init_addr ( const void *hw_addr, void *ll_addr ) {
+ const union ib_guid *guid = hw_addr;
+ struct ipoib_mac *mac = ll_addr;
+
+ memset ( mac, 0, sizeof ( *mac ) );
+ memcpy ( &mac->gid.s.guid, guid, sizeof ( mac->gid.s.guid ) );
+}
+
+/**
+ * Transcribe IPoIB link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @ret string Link-layer address in human-readable format
+ */
+const char * ipoib_ntoa ( const void *ll_addr ) {
+ static char buf[45];
+ const struct ipoib_mac *mac = ll_addr;
+
+ snprintf ( buf, sizeof ( buf ), "%08x:%08x:%08x:%08x:%08x",
+ htonl ( mac->flags__qpn ), htonl ( mac->gid.dwords[0] ),
+ htonl ( mac->gid.dwords[1] ),
+ htonl ( mac->gid.dwords[2] ),
+ htonl ( mac->gid.dwords[3] ) );
+ return buf;
+}
+
+/**
+ * Hash multicast address
+ *
+ * @v af Address family
+ * @v net_addr Network-layer address
+ * @v ll_addr Link-layer address to fill in
+ * @ret rc Return status code
+ */
+static int ipoib_mc_hash ( unsigned int af __unused,
+ const void *net_addr __unused,
+ void *ll_addr __unused ) {
+
+ return -ENOTSUP;
+}
+
+/**
+ * Generate Mellanox Ethernet-compatible compressed link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @v eth_addr Ethernet-compatible address to fill in
+ */
+static int ipoib_mlx_eth_addr ( const union ib_guid *guid,
+ uint8_t *eth_addr ) {
+ eth_addr[0] = ( ( guid->bytes[3] == 2 ) ? 0x00 : 0x02 );
+ eth_addr[1] = guid->bytes[1];
+ eth_addr[2] = guid->bytes[2];
+ eth_addr[3] = guid->bytes[5];
+ eth_addr[4] = guid->bytes[6];
+ eth_addr[5] = guid->bytes[7];
+ return 0;
+}
+
+/** An IPoIB Ethernet-compatible compressed link-layer address generator */
+struct ipoib_eth_addr_handler {
+ /** GUID byte 1 */
+ uint8_t byte1;
+ /** GUID byte 2 */
+ uint8_t byte2;
+ /** Handler */
+ int ( * eth_addr ) ( const union ib_guid *guid,
+ uint8_t *eth_addr );
+};
+
+/** IPoIB Ethernet-compatible compressed link-layer address generators */
+static struct ipoib_eth_addr_handler ipoib_eth_addr_handlers[] = {
+ { 0x02, 0xc9, ipoib_mlx_eth_addr },
+};
+
+/**
+ * Generate Ethernet-compatible compressed link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @v eth_addr Ethernet-compatible address to fill in
+ */
+static int ipoib_eth_addr ( const void *ll_addr, void *eth_addr ) {
+ const struct ipoib_mac *ipoib_addr = ll_addr;
+ const union ib_guid *guid = &ipoib_addr->gid.s.guid;
+ struct ipoib_eth_addr_handler *handler;
+ unsigned int i;
+
+ for ( i = 0 ; i < ( sizeof ( ipoib_eth_addr_handlers ) /
+ sizeof ( ipoib_eth_addr_handlers[0] ) ) ; i++ ) {
+ handler = &ipoib_eth_addr_handlers[i];
+ if ( ( handler->byte1 == guid->bytes[1] ) &&
+ ( handler->byte2 == guid->bytes[2] ) ) {
+ return handler->eth_addr ( guid, eth_addr );
+ }
+ }
+ return -ENOTSUP;
+}
+
+/** IPoIB protocol */
+struct ll_protocol ipoib_protocol __ll_protocol = {
+ .name = "IPoIB",
+ .ll_proto = htons ( ARPHRD_INFINIBAND ),
+ .hw_addr_len = sizeof ( union ib_guid ),
+ .ll_addr_len = IPOIB_ALEN,
+ .ll_header_len = IPOIB_HLEN,
+ .push = ipoib_push,
+ .pull = ipoib_pull,
+ .init_addr = ipoib_init_addr,
+ .ntoa = ipoib_ntoa,
+ .mc_hash = ipoib_mc_hash,
+ .eth_addr = ipoib_eth_addr,
+};
+
+/**
+ * Allocate IPoIB device
+ *
+ * @v priv_size Size of driver private data
+ * @ret netdev Network device, or NULL
+ */
+struct net_device * alloc_ipoibdev ( size_t priv_size ) {
+ struct net_device *netdev;
+
+ netdev = alloc_netdev ( priv_size );
+ if ( netdev ) {
+ netdev->ll_protocol = &ipoib_protocol;
+ netdev->ll_broadcast = ( uint8_t * ) &ipoib_broadcast;
+ netdev->max_pkt_len = IB_MAX_PAYLOAD_SIZE;
+ }
+ return netdev;
+}
+
+/****************************************************************************
+ *
+ * IPoIB network device
+ *
+ ****************************************************************************
+ */
+
+/**
+ * Transmit packet via IPoIB network device
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int ipoib_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct ipoib_device *ipoib = netdev->priv;
+ struct ib_device *ibdev = ipoib->ibdev;
+ struct ipoib_hdr *ipoib_hdr;
+ struct ipoib_peer *dest;
+ struct ib_address_vector av;
+ int rc;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
+ DBGC ( ipoib, "IPoIB %p buffer too short\n", ipoib );
+ return -EINVAL;
+ }
+ ipoib_hdr = iobuf->data;
+
+ /* Attempting transmission while link is down will put the
+ * queue pair into an error state, so don't try it.
+ */
+ if ( ! ib_link_ok ( ibdev ) )
+ return -ENETUNREACH;
+
+ /* Identify destination address */
+ dest = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest );
+ if ( ! dest )
+ return -ENXIO;
+ ipoib_hdr->u.reserved = 0;
+
+ /* Construct address vector */
+ memset ( &av, 0, sizeof ( av ) );
+ av.qpn = ( ntohl ( dest->mac.flags__qpn ) & IB_QPN_MASK );
+ av.gid_present = 1;
+ memcpy ( &av.gid, &dest->mac.gid, sizeof ( av.gid ) );
+ if ( ( rc = ib_resolve_path ( ibdev, &av ) ) != 0 ) {
+ /* Path not resolved yet */
+ return rc;
+ }
+
+ return ib_post_send ( ibdev, ipoib->qp, &av, iobuf );
+}
+
+/**
+ * Handle IPoIB send completion
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+static void ipoib_complete_send ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf, int rc ) {
+ struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
+
+ netdev_tx_complete_err ( ipoib->netdev, iobuf, rc );
+}
+
+/**
+ * Handle IPoIB receive completion
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector, or NULL
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+static void ipoib_complete_recv ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc ) {
+ struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
+ struct net_device *netdev = ipoib->netdev;
+ struct ipoib_hdr *ipoib_hdr;
+ struct ipoib_mac ll_src;
+ struct ipoib_peer *src;
+
+ /* Record errors */
+ if ( rc != 0 ) {
+ netdev_rx_err ( netdev, iobuf, rc );
+ return;
+ }
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( struct ipoib_hdr ) ) {
+ DBGC ( ipoib, "IPoIB %p received packet too short to "
+ "contain IPoIB header\n", ipoib );
+ DBGC_HD ( ipoib, iobuf->data, iob_len ( iobuf ) );
+ netdev_rx_err ( netdev, iobuf, -EIO );
+ return;
+ }
+ ipoib_hdr = iobuf->data;
+ if ( ! av ) {
+ DBGC ( ipoib, "IPoIB %p received packet without address "
+ "vector\n", ipoib );
+ netdev_rx_err ( netdev, iobuf, -ENOTTY );
+ return;
+ }
+
+ /* Parse source address */
+ if ( av->gid_present ) {
+ ll_src.flags__qpn = htonl ( av->qpn );
+ memcpy ( &ll_src.gid, &av->gid, sizeof ( ll_src.gid ) );
+ src = ipoib_cache_peer ( &ll_src );
+ ipoib_hdr->u.peer.src = src->key;
+ }
+
+ /* Hand off to network layer */
+ netdev_rx ( netdev, iobuf );
+}
+
+/** IPoIB completion operations */
+static struct ib_completion_queue_operations ipoib_cq_op = {
+ .complete_send = ipoib_complete_send,
+ .complete_recv = ipoib_complete_recv,
+};
+
+/**
+ * Poll IPoIB network device
+ *
+ * @v netdev Network device
+ */
+static void ipoib_poll ( struct net_device *netdev ) {
+ struct ipoib_device *ipoib = netdev->priv;
+ struct ib_device *ibdev = ipoib->ibdev;
+
+ ib_poll_eq ( ibdev );
+}
+
+/**
+ * Handle IPv4 broadcast multicast group join completion
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v membership Multicast group membership
+ * @v rc Status code
+ * @v mad Response MAD (or NULL on error)
+ */
+void ipoib_join_complete ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp __unused,
+ struct ib_mc_membership *membership, int rc,
+ union ib_mad *mad __unused ) {
+ struct ipoib_device *ipoib = container_of ( membership,
+ struct ipoib_device, broadcast_membership );
+
+ /* Record join status as link status */
+ netdev_link_err ( ipoib->netdev, rc );
+}
+
+/**
+ * Join IPv4 broadcast multicast group
+ *
+ * @v ipoib IPoIB device
+ * @ret rc Return status code
+ */
+static int ipoib_join_broadcast_group ( struct ipoib_device *ipoib ) {
+ int rc;
+
+ if ( ( rc = ib_mcast_join ( ipoib->ibdev, ipoib->qp,
+ &ipoib->broadcast_membership,
+ &ipoib->broadcast.gid,
+ ipoib_join_complete ) ) != 0 ) {
+ DBGC ( ipoib, "IPoIB %p could not join broadcast group: %s\n",
+ ipoib, strerror ( rc ) );
+ return rc;
+ }
+ ipoib->broadcast_joined = 1;
+
+ return 0;
+}
+
+/**
+ * Leave IPv4 broadcast multicast group
+ *
+ * @v ipoib IPoIB device
+ */
+static void ipoib_leave_broadcast_group ( struct ipoib_device *ipoib ) {
+
+ if ( ipoib->broadcast_joined ) {
+ ib_mcast_leave ( ipoib->ibdev, ipoib->qp,
+ &ipoib->broadcast_membership );
+ ipoib->broadcast_joined = 0;
+ }
+}
+
+/**
+ * Handle link status change
+ *
+ * @v ibdev Infiniband device
+ */
+static void ipoib_link_state_changed ( struct ib_device *ibdev ) {
+ struct net_device *netdev = ib_get_ownerdata ( ibdev );
+ struct ipoib_device *ipoib = netdev->priv;
+ struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
+ int rc;
+
+ /* Leave existing broadcast group */
+ ipoib_leave_broadcast_group ( ipoib );
+
+ /* Update MAC address based on potentially-new GID prefix */
+ memcpy ( &mac->gid.s.prefix, &ibdev->gid.s.prefix,
+ sizeof ( mac->gid.s.prefix ) );
+
+ /* Update broadcast GID based on potentially-new partition key */
+ ipoib->broadcast.gid.words[2] =
+ htons ( ibdev->pkey | IB_PKEY_FULL );
+
+ /* Set net device link state to reflect Infiniband link state */
+ rc = ib_link_rc ( ibdev );
+ netdev_link_err ( netdev, ( rc ? rc : -EINPROGRESS_JOINING ) );
+
+ /* Join new broadcast group */
+ if ( ib_is_open ( ibdev ) && ib_link_ok ( ibdev ) &&
+ ( ( rc = ipoib_join_broadcast_group ( ipoib ) ) != 0 ) ) {
+ DBGC ( ipoib, "IPoIB %p could not rejoin broadcast group: "
+ "%s\n", ipoib, strerror ( rc ) );
+ netdev_link_err ( netdev, rc );
+ return;
+ }
+}
+
+/**
+ * Open IPoIB network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int ipoib_open ( struct net_device *netdev ) {
+ struct ipoib_device *ipoib = netdev->priv;
+ struct ib_device *ibdev = ipoib->ibdev;
+ struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
+ int rc;
+
+ /* Open IB device */
+ if ( ( rc = ib_open ( ibdev ) ) != 0 ) {
+ DBGC ( ipoib, "IPoIB %p could not open device: %s\n",
+ ipoib, strerror ( rc ) );
+ goto err_ib_open;
+ }
+
+ /* Allocate completion queue */
+ ipoib->cq = ib_create_cq ( ibdev, IPOIB_NUM_CQES, &ipoib_cq_op );
+ if ( ! ipoib->cq ) {
+ DBGC ( ipoib, "IPoIB %p could not allocate completion queue\n",
+ ipoib );
+ rc = -ENOMEM;
+ goto err_create_cq;
+ }
+
+ /* Allocate queue pair */
+ ipoib->qp = ib_create_qp ( ibdev, IB_QPT_UD,
+ IPOIB_NUM_SEND_WQES, ipoib->cq,
+ IPOIB_NUM_RECV_WQES, ipoib->cq );
+ if ( ! ipoib->qp ) {
+ DBGC ( ipoib, "IPoIB %p could not allocate queue pair\n",
+ ipoib );
+ rc = -ENOMEM;
+ goto err_create_qp;
+ }
+ ib_qp_set_ownerdata ( ipoib->qp, ipoib );
+
+ /* Update MAC address with QPN */
+ mac->flags__qpn = htonl ( ipoib->qp->qpn );
+
+ /* Fill receive rings */
+ ib_refill_recv ( ibdev, ipoib->qp );
+
+ /* Fake a link status change to join the broadcast group */
+ ipoib_link_state_changed ( ibdev );
+
+ return 0;
+
+ ib_destroy_qp ( ibdev, ipoib->qp );
+ err_create_qp:
+ ib_destroy_cq ( ibdev, ipoib->cq );
+ err_create_cq:
+ ib_close ( ibdev );
+ err_ib_open:
+ return rc;
+}
+
+/**
+ * Close IPoIB network device
+ *
+ * @v netdev Network device
+ */
+static void ipoib_close ( struct net_device *netdev ) {
+ struct ipoib_device *ipoib = netdev->priv;
+ struct ib_device *ibdev = ipoib->ibdev;
+ struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
+
+ /* Leave broadcast group */
+ ipoib_leave_broadcast_group ( ipoib );
+
+ /* Remove QPN from MAC address */
+ mac->flags__qpn = 0;
+
+ /* Tear down the queues */
+ ib_destroy_qp ( ibdev, ipoib->qp );
+ ib_destroy_cq ( ibdev, ipoib->cq );
+
+ /* Close IB device */
+ ib_close ( ibdev );
+}
+
+/** IPoIB network device operations */
+static struct net_device_operations ipoib_operations = {
+ .open = ipoib_open,
+ .close = ipoib_close,
+ .transmit = ipoib_transmit,
+ .poll = ipoib_poll,
+};
+
+/**
+ * Probe IPoIB device
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+static int ipoib_probe ( struct ib_device *ibdev ) {
+ struct net_device *netdev;
+ struct ipoib_device *ipoib;
+ int rc;
+
+ /* Allocate network device */
+ netdev = alloc_ipoibdev ( sizeof ( *ipoib ) );
+ if ( ! netdev )
+ return -ENOMEM;
+ netdev_init ( netdev, &ipoib_operations );
+ ipoib = netdev->priv;
+ ib_set_ownerdata ( ibdev, netdev );
+ netdev->dev = ibdev->dev;
+ memset ( ipoib, 0, sizeof ( *ipoib ) );
+ ipoib->netdev = netdev;
+ ipoib->ibdev = ibdev;
+
+ /* Extract hardware address */
+ memcpy ( netdev->hw_addr, &ibdev->gid.s.guid,
+ sizeof ( ibdev->gid.s.guid ) );
+
+ /* Set default broadcast address */
+ memcpy ( &ipoib->broadcast, &ipoib_broadcast,
+ sizeof ( ipoib->broadcast ) );
+ netdev->ll_broadcast = ( ( uint8_t * ) &ipoib->broadcast );
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register_netdev;
+
+ return 0;
+
+ err_register_netdev:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ return rc;
+}
+
+/**
+ * Remove IPoIB device
+ *
+ * @v ibdev Infiniband device
+ */
+static void ipoib_remove ( struct ib_device *ibdev ) {
+ struct net_device *netdev = ib_get_ownerdata ( ibdev );
+
+ unregister_netdev ( netdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/** IPoIB driver */
+struct ib_driver ipoib_driver __ib_driver = {
+ .name = "IPoIB",
+ .probe = ipoib_probe,
+ .notify = ipoib_link_state_changed,
+ .remove = ipoib_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/jme.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/jme.c
new file mode 100644
index 00000000..54540265
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/jme.c
@@ -0,0 +1,1308 @@
+/*
+ * JMicron JMC2x0 series PCIe Ethernet gPXE Device Driver
+ *
+ * Copyright 2010 Guo-Fu Tseng <cooldavid@cooldavid.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ipxe/io.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/malloc.h>
+#include <mii.h>
+#include "jme.h"
+
+static int
+jme_mdio_read(struct net_device *netdev, int phy, int reg)
+{
+ struct jme_adapter *jme = netdev->priv;
+ int i, val, again = (reg == MII_BMSR) ? 1 : 0;
+
+read_again:
+ jwrite32(jme, JME_SMI, SMI_OP_REQ |
+ smi_phy_addr(phy) |
+ smi_reg_addr(reg));
+
+ for (i = JME_PHY_TIMEOUT * 50 ; i > 0 ; --i) {
+ udelay(20);
+ val = jread32(jme, JME_SMI);
+ if ((val & SMI_OP_REQ) == 0)
+ break;
+ }
+
+ if (i == 0) {
+ DBG("phy(%d) read timeout : %d\n", phy, reg);
+ return 0;
+ }
+
+ if (again--)
+ goto read_again;
+
+ return (val & SMI_DATA_MASK) >> SMI_DATA_SHIFT;
+}
+
+static void
+jme_mdio_write(struct net_device *netdev,
+ int phy, int reg, int val)
+{
+ struct jme_adapter *jme = netdev->priv;
+ int i;
+
+ jwrite32(jme, JME_SMI, SMI_OP_WRITE | SMI_OP_REQ |
+ ((val << SMI_DATA_SHIFT) & SMI_DATA_MASK) |
+ smi_phy_addr(phy) | smi_reg_addr(reg));
+
+ wmb();
+ for (i = JME_PHY_TIMEOUT * 50 ; i > 0 ; --i) {
+ udelay(20);
+ if ((jread32(jme, JME_SMI) & SMI_OP_REQ) == 0)
+ break;
+ }
+
+ if (i == 0)
+ DBG("phy(%d) write timeout : %d\n", phy, reg);
+
+ return;
+}
+
+static void
+jme_reset_phy_processor(struct jme_adapter *jme)
+{
+ u32 val;
+
+ jme_mdio_write(jme->mii_if.dev,
+ jme->mii_if.phy_id,
+ MII_ADVERTISE, ADVERTISE_ALL |
+ ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+
+ if (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250)
+ jme_mdio_write(jme->mii_if.dev,
+ jme->mii_if.phy_id,
+ MII_CTRL1000,
+ ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+
+ val = jme_mdio_read(jme->mii_if.dev,
+ jme->mii_if.phy_id,
+ MII_BMCR);
+
+ jme_mdio_write(jme->mii_if.dev,
+ jme->mii_if.phy_id,
+ MII_BMCR, val | BMCR_RESET);
+
+ return;
+}
+
+static void
+jme_phy_init(struct jme_adapter *jme)
+{
+ u16 reg26;
+
+ reg26 = jme_mdio_read(jme->mii_if.dev, jme->mii_if.phy_id, 26);
+ jme_mdio_write(jme->mii_if.dev, jme->mii_if.phy_id, 26, reg26 | 0x1000);
+}
+
+static void
+jme_set_phyfifoa(struct jme_adapter *jme)
+{
+ jme_mdio_write(jme->mii_if.dev, jme->mii_if.phy_id, 27, 0x0004);
+}
+
+static void
+jme_set_phyfifob(struct jme_adapter *jme)
+{
+ jme_mdio_write(jme->mii_if.dev, jme->mii_if.phy_id, 27, 0x0000);
+}
+
+static void
+jme_phy_off(struct jme_adapter *jme)
+{
+ jme_mdio_write(jme->mii_if.dev, jme->mii_if.phy_id, MII_BMCR, BMCR_PDOWN);
+}
+
+static void
+jme_restart_an(struct jme_adapter *jme)
+{
+ uint32_t bmcr;
+
+ bmcr = jme_mdio_read(jme->mii_if.dev, jme->mii_if.phy_id, MII_BMCR);
+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ jme_mdio_write(jme->mii_if.dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
+}
+
+static void
+jme_reset_ghc_speed(struct jme_adapter *jme)
+{
+ jme->reg_ghc &= ~(GHC_SPEED_1000M | GHC_DPX);
+ jwrite32(jme, JME_GHC, jme->reg_ghc);
+}
+
+static void
+jme_start_irq(struct jme_adapter *jme)
+{
+ /*
+ * Enable Interrupts
+ */
+ jwrite32(jme, JME_IENS, INTR_ENABLE);
+}
+
+static void
+jme_stop_irq(struct jme_adapter *jme)
+{
+ /*
+ * Disable Interrupts
+ */
+ jwrite32f(jme, JME_IENC, INTR_ENABLE);
+}
+
+static void
+jme_setup_wakeup_frame(struct jme_adapter *jme,
+ u32 *mask, u32 crc, int fnr)
+{
+ int i;
+
+ /*
+ * Setup CRC pattern
+ */
+ jwrite32(jme, JME_WFOI, WFOI_CRC_SEL | (fnr & WFOI_FRAME_SEL));
+ wmb();
+ jwrite32(jme, JME_WFODP, crc);
+ wmb();
+
+ /*
+ * Setup Mask
+ */
+ for (i = 0 ; i < WAKEUP_FRAME_MASK_DWNR ; ++i) {
+ jwrite32(jme, JME_WFOI,
+ ((i << WFOI_MASK_SHIFT) & WFOI_MASK_SEL) |
+ (fnr & WFOI_FRAME_SEL));
+ wmb();
+ jwrite32(jme, JME_WFODP, mask[i]);
+ wmb();
+ }
+}
+
+static void
+jme_reset_mac_processor(struct jme_adapter *jme)
+{
+ u32 mask[WAKEUP_FRAME_MASK_DWNR] = {0, 0, 0, 0};
+ u32 crc = 0xCDCDCDCD;
+ int i;
+
+ jwrite32(jme, JME_GHC, jme->reg_ghc | GHC_SWRST);
+ udelay(2);
+ jwrite32(jme, JME_GHC, jme->reg_ghc);
+
+ jwrite32(jme, JME_RXDBA_LO, 0x00000000);
+ jwrite32(jme, JME_RXDBA_HI, 0x00000000);
+ jwrite32(jme, JME_RXQDC, 0x00000000);
+ jwrite32(jme, JME_RXNDA, 0x00000000);
+ jwrite32(jme, JME_TXDBA_LO, 0x00000000);
+ jwrite32(jme, JME_TXDBA_HI, 0x00000000);
+ jwrite32(jme, JME_TXQDC, 0x00000000);
+ jwrite32(jme, JME_TXNDA, 0x00000000);
+
+ jwrite32(jme, JME_RXMCHT_LO, 0x00000000);
+ jwrite32(jme, JME_RXMCHT_HI, 0x00000000);
+ for (i = 0 ; i < WAKEUP_FRAME_NR ; ++i)
+ jme_setup_wakeup_frame(jme, mask, crc, i);
+ jwrite32(jme, JME_GPREG0, GPREG0_DEFAULT);
+ jwrite32(jme, JME_GPREG1, GPREG1_DEFAULT);
+}
+
+static void
+jme_free_tx_buffers(struct jme_adapter *jme)
+{
+ struct jme_ring *txring = &jme->txring;
+ struct io_buffer *txbi;
+ unsigned int i;
+
+ for (i = 0; i < jme->tx_ring_size; ++i) {
+ txbi = txring->bufinf[i];
+ if (txbi) {
+ netdev_tx_complete_err(jme->mii_if.dev,
+ txbi, -ENOLINK);
+ txring->bufinf[i] = NULL;
+ }
+ }
+}
+
+static void
+jme_free_tx_resources(struct jme_adapter *jme)
+{
+ struct jme_ring *txring = &jme->txring;
+
+ if (txring->desc) {
+ if (txring->bufinf) {
+ memset(txring->bufinf, 0,
+ sizeof(struct io_buffer *) * jme->tx_ring_size);
+ free(txring->bufinf);
+ }
+ free_dma(txring->desc, jme->tx_ring_size * TX_DESC_SIZE);
+ txring->desc = NULL;
+ txring->dma = 0;
+ txring->bufinf = NULL;
+ }
+ txring->next_to_use = 0;
+ txring->next_to_clean = 0;
+ txring->nr_free = 0;
+}
+
+static int
+jme_alloc_tx_resources(struct jme_adapter *jme)
+{
+ struct jme_ring *txring = &jme->txring;
+
+ txring->desc = malloc_dma(jme->tx_ring_size * TX_DESC_SIZE,
+ RING_DESC_ALIGN);
+ if (!txring->desc) {
+ DBG("Can not allocate transmit ring descriptors.\n");
+ goto err_out;
+ }
+
+ /*
+ * 16 Bytes align
+ */
+ txring->dma = virt_to_bus(txring->desc);
+ txring->bufinf = malloc(sizeof(struct io_buffer *) *
+ jme->tx_ring_size);
+ if (!(txring->bufinf)) {
+ DBG("Can not allocate transmit buffer info.\n");
+ goto err_out;
+ }
+
+ /*
+ * Initialize Transmit Buffer Pointers
+ */
+ memset(txring->bufinf, 0,
+ sizeof(struct io_buffer *) * jme->tx_ring_size);
+
+ return 0;
+
+err_out:
+ jme_free_tx_resources(jme);
+ return -ENOMEM;
+}
+
+static void
+jme_init_tx_ring(struct jme_adapter *jme)
+{
+ struct jme_ring *txring = &jme->txring;
+
+ txring->next_to_clean = 0;
+ txring->next_to_use = 0;
+ txring->nr_free = jme->tx_ring_size;
+
+ /*
+ * Initialize Transmit Descriptors
+ */
+ memset(txring->desc, 0, jme->tx_ring_size * TX_DESC_SIZE);
+ jme_free_tx_buffers(jme);
+}
+
+static void
+jme_enable_tx_engine(struct jme_adapter *jme)
+{
+ /*
+ * Select Queue 0
+ */
+ jwrite32(jme, JME_TXCS, TXCS_DEFAULT | TXCS_SELECT_QUEUE0);
+ wmb();
+
+ /*
+ * Setup TX Queue 0 DMA Bass Address
+ */
+ jwrite32(jme, JME_TXDBA_LO, (uint64_t)jme->txring.dma & 0xFFFFFFFFUL);
+ jwrite32(jme, JME_TXDBA_HI, (uint64_t)(jme->txring.dma) >> 32);
+ jwrite32(jme, JME_TXNDA, (uint64_t)jme->txring.dma & 0xFFFFFFFFUL);
+
+ /*
+ * Setup TX Descptor Count
+ */
+ jwrite32(jme, JME_TXQDC, jme->tx_ring_size);
+
+ /*
+ * Enable TX Engine
+ */
+ wmb();
+ jwrite32(jme, JME_TXCS, jme->reg_txcs |
+ TXCS_SELECT_QUEUE0 |
+ TXCS_ENABLE);
+
+}
+
+static void
+jme_disable_tx_engine(struct jme_adapter *jme)
+{
+ int i;
+ u32 val;
+
+ /*
+ * Disable TX Engine
+ */
+ jwrite32(jme, JME_TXCS, jme->reg_txcs | TXCS_SELECT_QUEUE0);
+ wmb();
+
+ val = jread32(jme, JME_TXCS);
+ for (i = JME_TX_DISABLE_TIMEOUT ; (val & TXCS_ENABLE) && i > 0 ; --i) {
+ mdelay(1);
+ val = jread32(jme, JME_TXCS);
+ rmb();
+ }
+
+ if (!i)
+ DBG("Disable TX engine timeout.\n");
+}
+
+
+static void
+jme_set_clean_rxdesc(struct jme_adapter *jme, int i)
+{
+ struct jme_ring *rxring = &jme->rxring;
+ register struct rxdesc *rxdesc = rxring->desc;
+ struct io_buffer *rxbi = rxring->bufinf[i];
+ uint64_t mapping;
+
+ rxdesc += i;
+ mapping = virt_to_bus(rxbi->data);
+
+ rxdesc->dw[0] = 0;
+ rxdesc->dw[1] = 0;
+ rxdesc->desc1.bufaddrh = cpu_to_le32(mapping >> 32);
+ rxdesc->desc1.bufaddrl = cpu_to_le32(mapping & 0xFFFFFFFFUL);
+ rxdesc->desc1.datalen = cpu_to_le16(RX_ALLOC_LEN);
+ wmb();
+ rxdesc->desc1.flags |= RXFLAG_OWN | RXFLAG_INT;
+}
+
+static int
+jme_make_new_rx_buf(struct io_buffer **rxbip)
+{
+ struct io_buffer *inbuf;
+
+ /*
+ * IOB_ALIGN == 2048
+ */
+ inbuf = alloc_iob(RX_ALLOC_LEN);
+ if (!inbuf) {
+ DBG("Allocate receive iob error.\n");
+ return -ENOMEM;
+ }
+ *rxbip = inbuf;
+
+ return 0;
+}
+
+static void
+jme_free_rx_buf(struct jme_adapter *jme, int i)
+{
+ struct jme_ring *rxring = &jme->rxring;
+ struct io_buffer *rxbi = rxring->bufinf[i];
+
+ if (rxbi) {
+ free_iob(rxbi);
+ rxring->bufinf[i] = NULL;
+ }
+}
+
+static void
+jme_free_rx_resources(struct jme_adapter *jme)
+{
+ unsigned int i;
+ struct jme_ring *rxring = &jme->rxring;
+
+ if (rxring->desc) {
+ if (rxring->bufinf) {
+ for (i = 0 ; i < jme->rx_ring_size ; ++i)
+ jme_free_rx_buf(jme, i);
+ free(rxring->bufinf);
+ }
+
+ free_dma(rxring->desc, jme->rx_ring_size * RX_DESC_SIZE);
+ rxring->desc = NULL;
+ rxring->dma = 0;
+ rxring->bufinf = NULL;
+ }
+ rxring->next_to_fill = 0;
+ rxring->next_to_clean = 0;
+}
+
+static int
+jme_alloc_rx_resources(struct jme_adapter *jme)
+{
+ unsigned int i;
+ struct jme_ring *rxring = &jme->rxring;
+ struct io_buffer **bufinf;
+
+ rxring->desc = malloc_dma(jme->rx_ring_size * RX_DESC_SIZE,
+ RING_DESC_ALIGN);
+ if (!rxring->desc) {
+ DBG("Can not allocate receive ring descriptors.\n");
+ goto err_out;
+ }
+
+ /*
+ * 16 Bytes align
+ */
+ rxring->dma = virt_to_bus(rxring->desc);
+ rxring->bufinf = malloc(sizeof(struct io_buffer *) *
+ jme->rx_ring_size);
+ if (!(rxring->bufinf)) {
+ DBG("Can not allocate receive buffer info.\n");
+ goto err_out;
+ }
+
+ /*
+ * Initiallize Receive Buffer Pointers
+ */
+ bufinf = rxring->bufinf;
+ memset(bufinf, 0, sizeof(struct io_buffer *) * jme->rx_ring_size);
+ for (i = 0 ; i < jme->rx_ring_size ; ++i) {
+ if (jme_make_new_rx_buf(bufinf))
+ goto err_out;
+ ++bufinf;
+ }
+
+ return 0;
+
+err_out:
+ jme_free_rx_resources(jme);
+ return -ENOMEM;
+}
+
+static void
+jme_init_rx_ring(struct jme_adapter *jme)
+{
+ unsigned int i;
+ struct jme_ring *rxring = &jme->rxring;
+
+ for (i = 0 ; i < jme->rx_ring_size ; ++i)
+ jme_set_clean_rxdesc(jme, i);
+
+ rxring->next_to_fill = 0;
+ rxring->next_to_clean = 0;
+}
+
+static void
+jme_set_multi(struct jme_adapter *jme)
+{
+ /*
+ * Just receive all kind of packet for new.
+ */
+ jme->reg_rxmcs |= RXMCS_ALLFRAME | RXMCS_BRDFRAME | RXMCS_UNIFRAME;
+ jwrite32(jme, JME_RXMCS, jme->reg_rxmcs);
+}
+
+static void
+jme_enable_rx_engine(struct jme_adapter *jme)
+{
+ /*
+ * Select Queue 0
+ */
+ jwrite32(jme, JME_RXCS, jme->reg_rxcs |
+ RXCS_QUEUESEL_Q0);
+ wmb();
+
+ /*
+ * Setup RX DMA Bass Address
+ */
+ jwrite32(jme, JME_RXDBA_LO, (uint64_t)(jme->rxring.dma) & 0xFFFFFFFFUL);
+ jwrite32(jme, JME_RXDBA_HI, (uint64_t)(jme->rxring.dma) >> 32);
+ jwrite32(jme, JME_RXNDA, (uint64_t)(jme->rxring.dma) & 0xFFFFFFFFUL);
+
+ /*
+ * Setup RX Descriptor Count
+ */
+ jwrite32(jme, JME_RXQDC, jme->rx_ring_size);
+
+ /*
+ * Setup Unicast Filter
+ */
+ jme_set_multi(jme);
+
+ /*
+ * Enable RX Engine
+ */
+ wmb();
+ jwrite32(jme, JME_RXCS, jme->reg_rxcs |
+ RXCS_QUEUESEL_Q0 |
+ RXCS_ENABLE |
+ RXCS_QST);
+}
+
+static void
+jme_restart_rx_engine(struct jme_adapter *jme)
+{
+ /*
+ * Start RX Engine
+ */
+ jwrite32(jme, JME_RXCS, jme->reg_rxcs |
+ RXCS_QUEUESEL_Q0 |
+ RXCS_ENABLE |
+ RXCS_QST);
+}
+
+static void
+jme_disable_rx_engine(struct jme_adapter *jme)
+{
+ int i;
+ u32 val;
+
+ /*
+ * Disable RX Engine
+ */
+ jwrite32(jme, JME_RXCS, jme->reg_rxcs);
+ wmb();
+
+ val = jread32(jme, JME_RXCS);
+ for (i = JME_RX_DISABLE_TIMEOUT ; (val & RXCS_ENABLE) && i > 0 ; --i) {
+ mdelay(1);
+ val = jread32(jme, JME_RXCS);
+ rmb();
+ }
+
+ if (!i)
+ DBG("Disable RX engine timeout.\n");
+
+}
+
+static void
+jme_refill_rx_ring(struct jme_adapter *jme, int curhole)
+{
+ struct jme_ring *rxring = &jme->rxring;
+ int i = rxring->next_to_fill;
+ struct io_buffer **bufinf = rxring->bufinf;
+ int mask = jme->rx_ring_mask;
+ int limit = jme->rx_ring_size;
+
+ while (limit--) {
+ if (!bufinf[i]) {
+ if (jme_make_new_rx_buf(bufinf + i))
+ break;
+ jme_set_clean_rxdesc(jme, i);
+ }
+ if (i == curhole)
+ limit = 0;
+ i = (i + 1) & mask;
+ }
+ rxring->next_to_fill = i;
+}
+
+static void
+jme_alloc_and_feed_iob(struct jme_adapter *jme, int idx)
+{
+ struct jme_ring *rxring = &jme->rxring;
+ struct rxdesc *rxdesc = rxring->desc;
+ struct io_buffer *rxbi = rxring->bufinf[idx];
+ struct net_device *netdev = jme->mii_if.dev;
+ int framesize;
+
+ rxdesc += idx;
+
+ framesize = le16_to_cpu(rxdesc->descwb.framesize);
+ iob_put(rxbi, framesize);
+ netdev_rx(netdev, rxbi);
+
+ rxring->bufinf[idx] = NULL;
+ jme_refill_rx_ring(jme, idx);
+}
+
+static void
+jme_process_receive(struct jme_adapter *jme)
+{
+ struct jme_ring *rxring = &jme->rxring;
+ struct rxdesc *rxdesc = rxring->desc;
+ struct net_device *netdev = jme->mii_if.dev;
+ int i, j, ccnt, desccnt, mask = jme->rx_ring_mask;
+ unsigned int limit = jme->rx_ring_size;
+
+ i = rxring->next_to_clean;
+ rxdesc += i;
+ while (rxring->bufinf[i] &&
+ !(rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_OWN)) &&
+ (rxdesc->descwb.desccnt & RXWBDCNT_WBCPL) &&
+ limit--) {
+
+ rmb();
+ desccnt = rxdesc->descwb.desccnt & RXWBDCNT_DCNT;
+ DBG2("Cleaning rx desc=%d, cnt=%d\n", i, desccnt);
+
+ if (desccnt > 1 || rxdesc->descwb.errstat & RXWBERR_ALLERR) {
+ for (j = i, ccnt = desccnt ; ccnt-- ; ) {
+ jme_set_clean_rxdesc(jme, j);
+ j = (j + 1) & (mask);
+ }
+ DBG("Dropped packet due to ");
+ if (desccnt > 1)
+ DBG("long packet.(%d descriptors)\n", desccnt);
+ else
+ DBG("Packet error.\n");
+ netdev_rx_err(netdev, NULL, -EINVAL);
+ } else {
+ jme_alloc_and_feed_iob(jme, i);
+ }
+
+ i = (i + desccnt) & (mask);
+ rxdesc = rxring->desc;
+ rxdesc += i;
+ }
+ rxring->next_to_clean = i;
+
+ return;
+}
+
+static void
+jme_set_custom_macaddr(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev->priv;
+ uint8_t *addr = netdev->ll_addr;
+ u32 val;
+
+ val = (addr[3] & 0xff) << 24 |
+ (addr[2] & 0xff) << 16 |
+ (addr[1] & 0xff) << 8 |
+ (addr[0] & 0xff);
+ jwrite32(jme, JME_RXUMA_LO, val);
+ val = (addr[5] & 0xff) << 8 |
+ (addr[4] & 0xff);
+ jwrite32(jme, JME_RXUMA_HI, val);
+}
+
+/**
+ * Open NIC
+ *
+ * @v netdev Net device
+ * @ret rc Return status code
+ */
+static int
+jme_open(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev->priv;
+ int rc;
+
+ /*
+ * Allocate receive resources
+ */
+ rc = jme_alloc_rx_resources(jme);
+ if (rc) {
+ DBG("Allocate receive resources error.\n");
+ goto nomem_out;
+ }
+
+ /*
+ * Allocate transmit resources
+ */
+ rc = jme_alloc_tx_resources(jme);
+ if (rc) {
+ DBG("Allocate transmit resources error.\n");
+ goto free_rx_resources_out;
+ }
+
+ jme_set_custom_macaddr(netdev);
+ jme_reset_phy_processor(jme);
+ jme_restart_an(jme);
+
+ return 0;
+
+free_rx_resources_out:
+ jme_free_rx_resources(jme);
+nomem_out:
+ return rc;
+}
+
+/**
+ * Close NIC
+ *
+ * @v netdev Net device
+ */
+static void
+jme_close(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev->priv;
+
+ jme_free_tx_resources(jme);
+ jme_free_rx_resources(jme);
+ jme_reset_mac_processor(jme);
+ jme->phylink = 0;
+ jme_phy_off(jme);
+ netdev_link_down(netdev);
+}
+
+static int
+jme_alloc_txdesc(struct jme_adapter *jme)
+{
+ struct jme_ring *txring = &jme->txring;
+ int idx;
+
+ idx = txring->next_to_use;
+ if (txring->nr_free < 1)
+ return -1;
+ --(txring->nr_free);
+ txring->next_to_use = (txring->next_to_use + 1) & jme->tx_ring_mask;
+
+ return idx;
+}
+
+static void
+jme_fill_tx_desc(struct jme_adapter *jme, struct io_buffer *iob, int idx)
+{
+ struct jme_ring *txring = &jme->txring;
+ struct txdesc *txdesc = txring->desc;
+ uint16_t len = iob_len(iob);
+ unsigned long int mapping;
+
+ txdesc += idx;
+ mapping = virt_to_bus(iob->data);
+ DBG2("TX buffer address: %p(%08lx+%x)\n",
+ iob->data, mapping, len);
+ txdesc->dw[0] = 0;
+ txdesc->dw[1] = 0;
+ txdesc->dw[2] = 0;
+ txdesc->dw[3] = 0;
+ txdesc->desc1.datalen = cpu_to_le16(len);
+ txdesc->desc1.pktsize = cpu_to_le16(len);
+ txdesc->desc1.bufaddr = cpu_to_le32(mapping);
+ /*
+ * Set OWN bit at final.
+ * When kernel transmit faster than NIC.
+ * And NIC trying to send this descriptor before we tell
+ * it to start sending this TX queue.
+ * Other fields are already filled correctly.
+ */
+ wmb();
+ txdesc->desc1.flags = TXFLAG_OWN | TXFLAG_INT;
+ /*
+ * Set tx buffer info after telling NIC to send
+ * For better tx_clean timing
+ */
+ wmb();
+ txring->bufinf[idx] = iob;
+}
+
+/**
+ * Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int
+jme_transmit(struct net_device *netdev, struct io_buffer *iobuf)
+{
+ struct jme_adapter *jme = netdev->priv;
+ int idx;
+
+ idx = jme_alloc_txdesc(jme);
+ if (idx < 0) {
+ /*
+ * Pause transmit queue somehow if possible.
+ */
+ DBG("TX ring full!\n");
+ return -EOVERFLOW;
+ }
+
+ jme_fill_tx_desc(jme, iobuf, idx);
+
+ jwrite32(jme, JME_TXCS, jme->reg_txcs |
+ TXCS_SELECT_QUEUE0 |
+ TXCS_QUEUE0S |
+ TXCS_ENABLE);
+ DBG2("xmit: idx=%d\n", idx);
+
+ return 0;
+}
+
+static int
+jme_check_link(struct net_device *netdev, int testonly)
+{
+ struct jme_adapter *jme = netdev->priv;
+ u32 phylink, ghc, cnt = JME_SPDRSV_TIMEOUT, gpreg1;
+ int rc = 0;
+
+ phylink = jread32(jme, JME_PHY_LINK);
+
+ if (phylink & PHY_LINK_UP) {
+ /*
+ * Keep polling for speed/duplex resolve complete
+ */
+ while (!(phylink & PHY_LINK_SPEEDDPU_RESOLVED) &&
+ --cnt) {
+
+ udelay(1);
+ phylink = jread32(jme, JME_PHY_LINK);
+ }
+ if (!cnt)
+ DBG("Waiting speed resolve timeout.\n");
+
+ if (jme->phylink == phylink) {
+ rc = 1;
+ goto out;
+ }
+ if (testonly)
+ goto out;
+
+ jme->phylink = phylink;
+
+ ghc = jme->reg_ghc & ~(GHC_SPEED | GHC_DPX |
+ GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE |
+ GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY);
+ switch (phylink & PHY_LINK_SPEED_MASK) {
+ case PHY_LINK_SPEED_10M:
+ ghc |= GHC_SPEED_10M |
+ GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
+ break;
+ case PHY_LINK_SPEED_100M:
+ ghc |= GHC_SPEED_100M |
+ GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
+ break;
+ case PHY_LINK_SPEED_1000M:
+ ghc |= GHC_SPEED_1000M |
+ GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY;
+ break;
+ default:
+ break;
+ }
+
+ if (phylink & PHY_LINK_DUPLEX) {
+ jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT);
+ ghc |= GHC_DPX;
+ } else {
+ jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT |
+ TXMCS_BACKOFF |
+ TXMCS_CARRIERSENSE |
+ TXMCS_COLLISION);
+ jwrite32(jme, JME_TXTRHD, TXTRHD_TXPEN |
+ ((0x2000 << TXTRHD_TXP_SHIFT) & TXTRHD_TXP) |
+ TXTRHD_TXREN |
+ ((8 << TXTRHD_TXRL_SHIFT) & TXTRHD_TXRL));
+ }
+
+ gpreg1 = GPREG1_DEFAULT;
+ if (is_buggy250(jme->pdev->device, jme->chiprev)) {
+ if (!(phylink & PHY_LINK_DUPLEX))
+ gpreg1 |= GPREG1_HALFMODEPATCH;
+ switch (phylink & PHY_LINK_SPEED_MASK) {
+ case PHY_LINK_SPEED_10M:
+ jme_set_phyfifoa(jme);
+ gpreg1 |= GPREG1_RSSPATCH;
+ break;
+ case PHY_LINK_SPEED_100M:
+ jme_set_phyfifob(jme);
+ gpreg1 |= GPREG1_RSSPATCH;
+ break;
+ case PHY_LINK_SPEED_1000M:
+ jme_set_phyfifoa(jme);
+ break;
+ default:
+ break;
+ }
+ }
+
+ jwrite32(jme, JME_GPREG1, gpreg1);
+ jwrite32(jme, JME_GHC, ghc);
+ jme->reg_ghc = ghc;
+
+ DBG("Link is up at %d Mbps, %s-Duplex, MDI%s.\n",
+ ((phylink & PHY_LINK_SPEED_MASK)
+ == PHY_LINK_SPEED_1000M) ? 1000 :
+ ((phylink & PHY_LINK_SPEED_MASK)
+ == PHY_LINK_SPEED_100M) ? 100 : 10,
+ (phylink & PHY_LINK_DUPLEX) ? "Full" : "Half",
+ (phylink & PHY_LINK_MDI_STAT) ? "-X" : "");
+ netdev_link_up(netdev);
+ } else {
+ if (testonly)
+ goto out;
+
+ DBG("Link is down.\n");
+ jme->phylink = 0;
+ netdev_link_down(netdev);
+ }
+
+out:
+ return rc;
+}
+
+static void
+jme_link_change(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev->priv;
+
+ /*
+ * Do nothing if the link status did not change.
+ */
+ if (jme_check_link(netdev, 1))
+ return;
+
+ if (netdev_link_ok(netdev)) {
+ netdev_link_down(netdev);
+ jme_disable_rx_engine(jme);
+ jme_disable_tx_engine(jme);
+ jme_reset_ghc_speed(jme);
+ jme_reset_mac_processor(jme);
+ }
+
+ jme_check_link(netdev, 0);
+ if (netdev_link_ok(netdev)) {
+ jme_init_rx_ring(jme);
+ jme_enable_rx_engine(jme);
+ jme_init_tx_ring(jme);
+ jme_enable_tx_engine(jme);
+ }
+
+ return;
+}
+
+static void
+jme_tx_clean(struct jme_adapter *jme)
+{
+ struct jme_ring *txring = &jme->txring;
+ struct txdesc *txdesc = txring->desc;
+ struct io_buffer *txbi;
+ struct net_device *netdev = jme->mii_if.dev;
+ int i, cnt = 0, max, err, mask;
+
+ max = jme->tx_ring_size - txring->nr_free;
+ mask = jme->tx_ring_mask;
+
+ for (i = txring->next_to_clean ; cnt < max ; ++cnt) {
+
+ txbi = txring->bufinf[i];
+
+ if (txbi && !(txdesc[i].descwb.flags & TXWBFLAG_OWN)) {
+ DBG2("TX clean address: %08lx(%08lx+%zx)\n",
+ (unsigned long)txbi->data,
+ virt_to_bus(txbi->data),
+ iob_len(txbi));
+ err = txdesc[i].descwb.flags & TXWBFLAG_ALLERR;
+ if (err)
+ netdev_tx_complete_err(netdev, txbi, -EIO);
+ else
+ netdev_tx_complete(netdev, txbi);
+ txring->bufinf[i] = NULL;
+ } else {
+ break;
+ }
+
+ i = (i + 1) & mask;
+ }
+
+ DBG2("txclean: next %d\n", i);
+ txring->next_to_clean = i;
+ txring->nr_free += cnt;
+}
+/**
+ * Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void
+jme_poll(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev->priv;
+ u32 intrstat;
+
+ intrstat = jread32(jme, JME_IEVE);
+
+ /*
+ * Check if any actions needs to perform.
+ */
+ if ((intrstat & INTR_ENABLE) == 0)
+ return;
+
+ /*
+ * Check if the device still exist
+ */
+ if (intrstat == ~((typeof(intrstat))0))
+ return;
+
+ DBG2("intrstat 0x%08x\n", intrstat);
+ if (intrstat & (INTR_LINKCH | INTR_SWINTR)) {
+ DBG2("Link changed\n");
+ jme_link_change(netdev);
+
+ /*
+ * Clear all interrupt status
+ */
+ jwrite32(jme, JME_IEVE, intrstat);
+
+ /*
+ * Link change event is critical
+ * all other events are ignored
+ */
+ return;
+ }
+
+ /*
+ * Process transmission complete first to free more memory.
+ */
+ if (intrstat & INTR_TX0) {
+ DBG2("Packet transmit complete\n");
+ jme_tx_clean(jme);
+ jwrite32(jme, JME_IEVE, intrstat & INTR_TX0);
+ }
+
+ if (intrstat & (INTR_RX0 | INTR_RX0EMP)) {
+ DBG2("Packet received\n");
+ jme_process_receive(jme);
+ jwrite32(jme, JME_IEVE,
+ intrstat & (INTR_RX0 | INTR_RX0EMP));
+ if (intrstat & INTR_RX0EMP)
+ jme_restart_rx_engine(jme);
+ }
+
+ /*
+ * Clean all other interrupt status
+ */
+ jwrite32(jme, JME_IEVE,
+ intrstat & ~(INTR_RX0 | INTR_RX0EMP | INTR_TX0));
+}
+
+/**
+ * Enable/disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void
+jme_irq(struct net_device *netdev, int enable)
+{
+ struct jme_adapter *jme = netdev->priv;
+
+ DBG("jme interrupts %s\n", (enable ? "enabled" : "disabled"));
+ if (enable)
+ jme_start_irq(jme);
+ else
+ jme_stop_irq(jme);
+}
+
+/** JME net device operations */
+static struct net_device_operations jme_operations = {
+ .open = jme_open,
+ .close = jme_close,
+ .transmit = jme_transmit,
+ .poll = jme_poll,
+ .irq = jme_irq,
+};
+
+static void
+jme_check_hw_ver(struct jme_adapter *jme)
+{
+ u32 chipmode;
+
+ chipmode = jread32(jme, JME_CHIPMODE);
+
+ jme->fpgaver = (chipmode & CM_FPGAVER_MASK) >> CM_FPGAVER_SHIFT;
+ jme->chiprev = (chipmode & CM_CHIPREV_MASK) >> CM_CHIPREV_SHIFT;
+}
+
+static int
+jme_reload_eeprom(struct jme_adapter *jme)
+{
+ u32 val;
+ int i;
+
+ val = jread32(jme, JME_SMBCSR);
+
+ if (val & SMBCSR_EEPROMD) {
+ val |= SMBCSR_CNACK;
+ jwrite32(jme, JME_SMBCSR, val);
+ val |= SMBCSR_RELOAD;
+ jwrite32(jme, JME_SMBCSR, val);
+ mdelay(12);
+
+ for (i = JME_EEPROM_RELOAD_TIMEOUT; i > 0; --i) {
+ mdelay(1);
+ if ((jread32(jme, JME_SMBCSR) & SMBCSR_RELOAD) == 0)
+ break;
+ }
+
+ if (i == 0) {
+ DBG("eeprom reload timeout\n");
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static void
+jme_load_macaddr(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ unsigned char macaddr[6];
+ u32 val;
+
+ val = jread32(jme, JME_RXUMA_LO);
+ macaddr[0] = (val >> 0) & 0xFF;
+ macaddr[1] = (val >> 8) & 0xFF;
+ macaddr[2] = (val >> 16) & 0xFF;
+ macaddr[3] = (val >> 24) & 0xFF;
+ val = jread32(jme, JME_RXUMA_HI);
+ macaddr[4] = (val >> 0) & 0xFF;
+ macaddr[5] = (val >> 8) & 0xFF;
+ memcpy(netdev->hw_addr, macaddr, 6);
+}
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @v id PCI ID
+ * @ret rc Return status code
+ */
+static int
+jme_probe(struct pci_device *pci)
+{
+ struct net_device *netdev;
+ struct jme_adapter *jme;
+ int rc;
+ uint8_t mrrs;
+
+ /* Allocate net device */
+ netdev = alloc_etherdev(sizeof(*jme));
+ if (!netdev)
+ return -ENOMEM;
+ netdev_init(netdev, &jme_operations);
+ jme = netdev->priv;
+ pci_set_drvdata(pci, netdev);
+ netdev->dev = &pci->dev;
+ jme->regs = ioremap(pci->membase, JME_REGS_SIZE);
+ if (!(jme->regs)) {
+ DBG("Mapping PCI resource region error.\n");
+ rc = -ENOMEM;
+ goto err_out;
+ }
+ jme->reg_ghc = 0;
+ jme->reg_rxcs = RXCS_DEFAULT;
+ jme->reg_rxmcs = RXMCS_DEFAULT;
+ jme->phylink = 0;
+ jme->pdev = pci;
+ jme->mii_if.dev = netdev;
+ jme->mii_if.phy_id = 1;
+ jme->mii_if.mdio_read = jme_mdio_read;
+ jme->mii_if.mdio_write = jme_mdio_write;
+ jme->rx_ring_size = 1 << 4;
+ jme->rx_ring_mask = jme->rx_ring_size - 1;
+ jme->tx_ring_size = 1 << 4;
+ jme->tx_ring_mask = jme->tx_ring_size - 1;
+
+ /* Fix up PCI device */
+ adjust_pci_device(pci);
+
+ /*
+ * Get Max Read Req Size from PCI Config Space
+ */
+ pci_read_config_byte(pci, PCI_DCSR_MRRS, &mrrs);
+ mrrs &= PCI_DCSR_MRRS_MASK;
+ switch (mrrs) {
+ case MRRS_128B:
+ jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_128B;
+ break;
+ case MRRS_256B:
+ jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_256B;
+ break;
+ default:
+ jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_512B;
+ break;
+ };
+
+ /*
+ * Get basic hardware info.
+ */
+ jme_check_hw_ver(jme);
+ if (pci->device == PCI_DEVICE_ID_JMICRON_JMC250)
+ jme->mii_if.supports_gmii = 1;
+ else
+ jme->mii_if.supports_gmii = 0;
+
+ /*
+ * Initialize PHY
+ */
+ jme_set_phyfifoa(jme);
+ jme_phy_init(jme);
+
+ /*
+ * Bring down phy before interface is opened.
+ */
+ jme_phy_off(jme);
+
+ /*
+ * Reset MAC processor and reload EEPROM for MAC Address
+ */
+ jme_reset_mac_processor(jme);
+ rc = jme_reload_eeprom(jme);
+ if (rc) {
+ DBG("Reload eeprom for reading MAC Address error.\n");
+ goto err_unmap;
+ }
+ jme_load_macaddr(netdev);
+
+ /* Register network device */
+ if ((rc = register_netdev(netdev)) != 0) {
+ DBG("Register net_device error.\n");
+ goto err_unmap;
+ }
+
+ return 0;
+
+err_unmap:
+ iounmap(jme->regs);
+err_out:
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void
+jme_remove(struct pci_device *pci)
+{
+ struct net_device *netdev = pci_get_drvdata(pci);
+ struct jme_adapter *jme = netdev->priv;
+
+ iounmap(jme->regs);
+ unregister_netdev(netdev);
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+}
+
+static struct pci_device_id jm_nics[] = {
+PCI_ROM(0x197b, 0x0250, "jme", "JMicron Gigabit Ethernet", 0),
+PCI_ROM(0x197b, 0x0260, "jmfe", "JMicron Fast Ethernet", 0),
+};
+
+struct pci_driver jme_driver __pci_driver = {
+ .ids = jm_nics,
+ .id_count = ( sizeof ( jm_nics ) / sizeof ( jm_nics[0] ) ),
+ .probe = jme_probe,
+ .remove = jme_remove,
+};
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/jme.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/jme.h
new file mode 100644
index 00000000..7e225430
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/jme.h
@@ -0,0 +1,914 @@
+/*
+ * JMicron JMC2x0 series PCIe Ethernet gPXE Device Driver
+ *
+ * Copyright 2010 Guo-Fu Tseng <cooldavid@cooldavid.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef __JME_H_INCLUDED__
+#define __JME_H_INCLUDED__
+
+#define PCI_VENDOR_ID_JMICRON 0x197b
+#define PCI_DEVICE_ID_JMICRON_JMC250 0x0250
+#define PCI_DEVICE_ID_JMICRON_JMC260 0x0260
+
+/*
+ * Extra PCI Configuration space interface
+ */
+#define PCI_DCSR_MRRS 0x59
+#define PCI_DCSR_MRRS_MASK 0x70
+
+enum pci_dcsr_mrrs_vals {
+ MRRS_128B = 0x00,
+ MRRS_256B = 0x10,
+ MRRS_512B = 0x20,
+ MRRS_1024B = 0x30,
+ MRRS_2048B = 0x40,
+ MRRS_4096B = 0x50,
+};
+
+/*
+ * TX/RX Descriptors
+ *
+ * TX/RX Ring DESC Count Must be multiple of 16 and <= 1024
+ */
+#define RING_DESC_ALIGN 16 /* Descriptor alignment */
+#define TX_DESC_SIZE 16
+
+struct txdesc {
+ union {
+ uint8_t all[16];
+ uint32_t dw[4];
+ struct {
+ /* DW0 */
+ uint16_t vlan;
+ uint8_t rsv1;
+ uint8_t flags;
+
+ /* DW1 */
+ uint16_t datalen;
+ uint16_t mss;
+
+ /* DW2 */
+ uint16_t pktsize;
+ uint16_t rsv2;
+
+ /* DW3 */
+ uint32_t bufaddr;
+ } desc1;
+ struct {
+ /* DW0 */
+ uint16_t rsv1;
+ uint8_t rsv2;
+ uint8_t flags;
+
+ /* DW1 */
+ uint16_t datalen;
+ uint16_t rsv3;
+
+ /* DW2 */
+ uint32_t bufaddrh;
+
+ /* DW3 */
+ uint32_t bufaddrl;
+ } desc2;
+ struct {
+ /* DW0 */
+ uint8_t ehdrsz;
+ uint8_t rsv1;
+ uint8_t rsv2;
+ uint8_t flags;
+
+ /* DW1 */
+ uint16_t trycnt;
+ uint16_t segcnt;
+
+ /* DW2 */
+ uint16_t pktsz;
+ uint16_t rsv3;
+
+ /* DW3 */
+ uint32_t bufaddrl;
+ } descwb;
+ };
+};
+
+enum jme_txdesc_flags_bits {
+ TXFLAG_OWN = 0x80,
+ TXFLAG_INT = 0x40,
+ TXFLAG_64BIT = 0x20,
+ TXFLAG_TCPCS = 0x10,
+ TXFLAG_UDPCS = 0x08,
+ TXFLAG_IPCS = 0x04,
+ TXFLAG_LSEN = 0x02,
+ TXFLAG_TAGON = 0x01,
+};
+
+#define TXDESC_MSS_SHIFT 2
+enum jme_txwbdesc_flags_bits {
+ TXWBFLAG_OWN = 0x80,
+ TXWBFLAG_INT = 0x40,
+ TXWBFLAG_TMOUT = 0x20,
+ TXWBFLAG_TRYOUT = 0x10,
+ TXWBFLAG_COL = 0x08,
+
+ TXWBFLAG_ALLERR = TXWBFLAG_TMOUT |
+ TXWBFLAG_TRYOUT |
+ TXWBFLAG_COL,
+};
+
+#define RX_DESC_SIZE 16
+#define RX_BUF_DMA_ALIGN 8
+#define RX_PREPAD_SIZE 10
+#define ETH_CRC_LEN 2
+#define RX_VLANHDR_LEN 2
+#define RX_EXTRA_LEN (ETH_HLEN + \
+ ETH_CRC_LEN + \
+ RX_VLANHDR_LEN + \
+ RX_BUF_DMA_ALIGN)
+#define FIXED_MTU 1500
+#define RX_ALLOC_LEN (FIXED_MTU + RX_EXTRA_LEN)
+
+struct rxdesc {
+ union {
+ uint8_t all[16];
+ uint32_t dw[4];
+ struct {
+ /* DW0 */
+ uint16_t rsv2;
+ uint8_t rsv1;
+ uint8_t flags;
+
+ /* DW1 */
+ uint16_t datalen;
+ uint16_t wbcpl;
+
+ /* DW2 */
+ uint32_t bufaddrh;
+
+ /* DW3 */
+ uint32_t bufaddrl;
+ } desc1;
+ struct {
+ /* DW0 */
+ uint16_t vlan;
+ uint16_t flags;
+
+ /* DW1 */
+ uint16_t framesize;
+ uint8_t errstat;
+ uint8_t desccnt;
+
+ /* DW2 */
+ uint32_t rsshash;
+
+ /* DW3 */
+ uint8_t hashfun;
+ uint8_t hashtype;
+ uint16_t resrv;
+ } descwb;
+ };
+};
+
+enum jme_rxdesc_flags_bits {
+ RXFLAG_OWN = 0x80,
+ RXFLAG_INT = 0x40,
+ RXFLAG_64BIT = 0x20,
+};
+
+enum jme_rxwbdesc_flags_bits {
+ RXWBFLAG_OWN = 0x8000,
+ RXWBFLAG_INT = 0x4000,
+ RXWBFLAG_MF = 0x2000,
+ RXWBFLAG_64BIT = 0x2000,
+ RXWBFLAG_TCPON = 0x1000,
+ RXWBFLAG_UDPON = 0x0800,
+ RXWBFLAG_IPCS = 0x0400,
+ RXWBFLAG_TCPCS = 0x0200,
+ RXWBFLAG_UDPCS = 0x0100,
+ RXWBFLAG_TAGON = 0x0080,
+ RXWBFLAG_IPV4 = 0x0040,
+ RXWBFLAG_IPV6 = 0x0020,
+ RXWBFLAG_PAUSE = 0x0010,
+ RXWBFLAG_MAGIC = 0x0008,
+ RXWBFLAG_WAKEUP = 0x0004,
+ RXWBFLAG_DEST = 0x0003,
+ RXWBFLAG_DEST_UNI = 0x0001,
+ RXWBFLAG_DEST_MUL = 0x0002,
+ RXWBFLAG_DEST_BRO = 0x0003,
+};
+
+enum jme_rxwbdesc_desccnt_mask {
+ RXWBDCNT_WBCPL = 0x80,
+ RXWBDCNT_DCNT = 0x7F,
+};
+
+enum jme_rxwbdesc_errstat_bits {
+ RXWBERR_LIMIT = 0x80,
+ RXWBERR_MIIER = 0x40,
+ RXWBERR_NIBON = 0x20,
+ RXWBERR_COLON = 0x10,
+ RXWBERR_ABORT = 0x08,
+ RXWBERR_SHORT = 0x04,
+ RXWBERR_OVERUN = 0x02,
+ RXWBERR_CRCERR = 0x01,
+ RXWBERR_ALLERR = 0xFF,
+};
+
+/*
+ * The structure holding buffer information and ring descriptors all together.
+ */
+struct jme_ring {
+ void *desc; /* pointer to ring memory */
+ unsigned long dma; /* phys address for ring dma */
+
+ /* Buffer information corresponding to each descriptor */
+ struct io_buffer **bufinf;
+
+ int next_to_clean;
+ int next_to_fill;
+ int next_to_use;
+ int nr_free;
+};
+
+/*
+ * Jmac Adapter Private data
+ */
+struct jme_adapter {
+ void *regs;
+ struct mii_if_info mii_if;
+ struct pci_device *pdev;
+ unsigned int fpgaver;
+ unsigned int chiprev;
+ uint32_t reg_ghc;
+ uint32_t reg_txcs;
+ uint32_t reg_rxcs;
+ uint32_t reg_rxmcs;
+ uint32_t phylink;
+ struct jme_ring rxring;
+ uint32_t rx_ring_size;
+ uint32_t rx_ring_mask;
+ struct jme_ring txring;
+ uint32_t tx_ring_size;
+ uint32_t tx_ring_mask;
+};
+
+/*
+ * I/O Resters
+ */
+enum jme_iomap_regs_value {
+ JME_REGS_SIZE = 0x1000,
+};
+
+enum jme_iomap_offsets {
+ JME_MAC = 0x0000,
+ JME_PHY = 0x0400,
+ JME_MISC = 0x0800,
+ JME_RSS = 0x0C00,
+};
+
+enum jme_iomap_lens {
+ JME_MAC_LEN = 0x80,
+ JME_PHY_LEN = 0x58,
+ JME_MISC_LEN = 0x98,
+ JME_RSS_LEN = 0xFF,
+};
+
+enum jme_iomap_regs {
+ JME_TXCS = JME_MAC | 0x00, /* Transmit Control and Status */
+ JME_TXDBA_LO = JME_MAC | 0x04, /* Transmit Queue Desc Base Addr */
+ JME_TXDBA_HI = JME_MAC | 0x08, /* Transmit Queue Desc Base Addr */
+ JME_TXQDC = JME_MAC | 0x0C, /* Transmit Queue Desc Count */
+ JME_TXNDA = JME_MAC | 0x10, /* Transmit Queue Next Desc Addr */
+ JME_TXMCS = JME_MAC | 0x14, /* Transmit MAC Control Status */
+ JME_TXPFC = JME_MAC | 0x18, /* Transmit Pause Frame Control */
+ JME_TXTRHD = JME_MAC | 0x1C, /* Transmit Timer/Retry@Half-Dup */
+
+ JME_RXCS = JME_MAC | 0x20, /* Receive Control and Status */
+ JME_RXDBA_LO = JME_MAC | 0x24, /* Receive Queue Desc Base Addr */
+ JME_RXDBA_HI = JME_MAC | 0x28, /* Receive Queue Desc Base Addr */
+ JME_RXQDC = JME_MAC | 0x2C, /* Receive Queue Desc Count */
+ JME_RXNDA = JME_MAC | 0x30, /* Receive Queue Next Desc Addr */
+ JME_RXMCS = JME_MAC | 0x34, /* Receive MAC Control Status */
+ JME_RXUMA_LO = JME_MAC | 0x38, /* Receive Unicast MAC Address */
+ JME_RXUMA_HI = JME_MAC | 0x3C, /* Receive Unicast MAC Address */
+ JME_RXMCHT_LO = JME_MAC | 0x40, /* Recv Multicast Addr HashTable */
+ JME_RXMCHT_HI = JME_MAC | 0x44, /* Recv Multicast Addr HashTable */
+ JME_WFODP = JME_MAC | 0x48, /* Wakeup Frame Output Data Port */
+ JME_WFOI = JME_MAC | 0x4C, /* Wakeup Frame Output Interface */
+
+ JME_SMI = JME_MAC | 0x50, /* Station Management Interface */
+ JME_GHC = JME_MAC | 0x54, /* Global Host Control */
+ JME_PMCS = JME_MAC | 0x60, /* Power Management Control/Stat */
+
+
+ JME_PHY_CS = JME_PHY | 0x28, /* PHY Ctrl and Status Register */
+ JME_PHY_LINK = JME_PHY | 0x30, /* PHY Link Status Register */
+ JME_SMBCSR = JME_PHY | 0x40, /* SMB Control and Status */
+ JME_SMBINTF = JME_PHY | 0x44, /* SMB Interface */
+
+
+ JME_TMCSR = JME_MISC | 0x00, /* Timer Control/Status Register */
+ JME_GPREG0 = JME_MISC | 0x08, /* General purpose REG-0 */
+ JME_GPREG1 = JME_MISC | 0x0C, /* General purpose REG-1 */
+ JME_IEVE = JME_MISC | 0x20, /* Interrupt Event Status */
+ JME_IREQ = JME_MISC | 0x24, /* Intr Req Status(For Debug) */
+ JME_IENS = JME_MISC | 0x28, /* Intr Enable - Setting Port */
+ JME_IENC = JME_MISC | 0x2C, /* Interrupt Enable - Clear Port */
+ JME_PCCRX0 = JME_MISC | 0x30, /* PCC Control for RX Queue 0 */
+ JME_PCCTX = JME_MISC | 0x40, /* PCC Control for TX Queues */
+ JME_CHIPMODE = JME_MISC | 0x44, /* Identify FPGA Version */
+ JME_SHBA_HI = JME_MISC | 0x48, /* Shadow Register Base HI */
+ JME_SHBA_LO = JME_MISC | 0x4C, /* Shadow Register Base LO */
+ JME_TIMER1 = JME_MISC | 0x70, /* Timer1 */
+ JME_TIMER2 = JME_MISC | 0x74, /* Timer2 */
+ JME_APMC = JME_MISC | 0x7C, /* Aggressive Power Mode Control */
+ JME_PCCSRX0 = JME_MISC | 0x80, /* PCC Status of RX0 */
+};
+
+/*
+ * TX Control/Status Bits
+ */
+enum jme_txcs_bits {
+ TXCS_QUEUE7S = 0x00008000,
+ TXCS_QUEUE6S = 0x00004000,
+ TXCS_QUEUE5S = 0x00002000,
+ TXCS_QUEUE4S = 0x00001000,
+ TXCS_QUEUE3S = 0x00000800,
+ TXCS_QUEUE2S = 0x00000400,
+ TXCS_QUEUE1S = 0x00000200,
+ TXCS_QUEUE0S = 0x00000100,
+ TXCS_FIFOTH = 0x000000C0,
+ TXCS_DMASIZE = 0x00000030,
+ TXCS_BURST = 0x00000004,
+ TXCS_ENABLE = 0x00000001,
+};
+
+enum jme_txcs_value {
+ TXCS_FIFOTH_16QW = 0x000000C0,
+ TXCS_FIFOTH_12QW = 0x00000080,
+ TXCS_FIFOTH_8QW = 0x00000040,
+ TXCS_FIFOTH_4QW = 0x00000000,
+
+ TXCS_DMASIZE_64B = 0x00000000,
+ TXCS_DMASIZE_128B = 0x00000010,
+ TXCS_DMASIZE_256B = 0x00000020,
+ TXCS_DMASIZE_512B = 0x00000030,
+
+ TXCS_SELECT_QUEUE0 = 0x00000000,
+ TXCS_SELECT_QUEUE1 = 0x00010000,
+ TXCS_SELECT_QUEUE2 = 0x00020000,
+ TXCS_SELECT_QUEUE3 = 0x00030000,
+ TXCS_SELECT_QUEUE4 = 0x00040000,
+ TXCS_SELECT_QUEUE5 = 0x00050000,
+ TXCS_SELECT_QUEUE6 = 0x00060000,
+ TXCS_SELECT_QUEUE7 = 0x00070000,
+
+ TXCS_DEFAULT = TXCS_FIFOTH_4QW |
+ TXCS_BURST,
+};
+
+#define JME_TX_DISABLE_TIMEOUT 10 /* 10 msec */
+
+/*
+ * TX MAC Control/Status Bits
+ */
+enum jme_txmcs_bit_masks {
+ TXMCS_IFG2 = 0xC0000000,
+ TXMCS_IFG1 = 0x30000000,
+ TXMCS_TTHOLD = 0x00000300,
+ TXMCS_FBURST = 0x00000080,
+ TXMCS_CARRIEREXT = 0x00000040,
+ TXMCS_DEFER = 0x00000020,
+ TXMCS_BACKOFF = 0x00000010,
+ TXMCS_CARRIERSENSE = 0x00000008,
+ TXMCS_COLLISION = 0x00000004,
+ TXMCS_CRC = 0x00000002,
+ TXMCS_PADDING = 0x00000001,
+};
+
+enum jme_txmcs_values {
+ TXMCS_IFG2_6_4 = 0x00000000,
+ TXMCS_IFG2_8_5 = 0x40000000,
+ TXMCS_IFG2_10_6 = 0x80000000,
+ TXMCS_IFG2_12_7 = 0xC0000000,
+
+ TXMCS_IFG1_8_4 = 0x00000000,
+ TXMCS_IFG1_12_6 = 0x10000000,
+ TXMCS_IFG1_16_8 = 0x20000000,
+ TXMCS_IFG1_20_10 = 0x30000000,
+
+ TXMCS_TTHOLD_1_8 = 0x00000000,
+ TXMCS_TTHOLD_1_4 = 0x00000100,
+ TXMCS_TTHOLD_1_2 = 0x00000200,
+ TXMCS_TTHOLD_FULL = 0x00000300,
+
+ TXMCS_DEFAULT = TXMCS_IFG2_8_5 |
+ TXMCS_IFG1_16_8 |
+ TXMCS_TTHOLD_FULL |
+ TXMCS_DEFER |
+ TXMCS_CRC |
+ TXMCS_PADDING,
+};
+
+enum jme_txpfc_bits_masks {
+ TXPFC_VLAN_TAG = 0xFFFF0000,
+ TXPFC_VLAN_EN = 0x00008000,
+ TXPFC_PF_EN = 0x00000001,
+};
+
+enum jme_txtrhd_bits_masks {
+ TXTRHD_TXPEN = 0x80000000,
+ TXTRHD_TXP = 0x7FFFFF00,
+ TXTRHD_TXREN = 0x00000080,
+ TXTRHD_TXRL = 0x0000007F,
+};
+
+enum jme_txtrhd_shifts {
+ TXTRHD_TXP_SHIFT = 8,
+ TXTRHD_TXRL_SHIFT = 0,
+};
+
+/*
+ * RX Control/Status Bits
+ */
+enum jme_rxcs_bit_masks {
+ /* FIFO full threshold for transmitting Tx Pause Packet */
+ RXCS_FIFOTHTP = 0x30000000,
+ /* FIFO threshold for processing next packet */
+ RXCS_FIFOTHNP = 0x0C000000,
+ RXCS_DMAREQSZ = 0x03000000, /* DMA Request Size */
+ RXCS_QUEUESEL = 0x00030000, /* Queue selection */
+ RXCS_RETRYGAP = 0x0000F000, /* RX Desc full retry gap */
+ RXCS_RETRYCNT = 0x00000F00, /* RX Desc full retry counter */
+ RXCS_WAKEUP = 0x00000040, /* Enable receive wakeup packet */
+ RXCS_MAGIC = 0x00000020, /* Enable receive magic packet */
+ RXCS_SHORT = 0x00000010, /* Enable receive short packet */
+ RXCS_ABORT = 0x00000008, /* Enable receive errorr packet */
+ RXCS_QST = 0x00000004, /* Receive queue start */
+ RXCS_SUSPEND = 0x00000002,
+ RXCS_ENABLE = 0x00000001,
+};
+
+enum jme_rxcs_values {
+ RXCS_FIFOTHTP_16T = 0x00000000,
+ RXCS_FIFOTHTP_32T = 0x10000000,
+ RXCS_FIFOTHTP_64T = 0x20000000,
+ RXCS_FIFOTHTP_128T = 0x30000000,
+
+ RXCS_FIFOTHNP_16QW = 0x00000000,
+ RXCS_FIFOTHNP_32QW = 0x04000000,
+ RXCS_FIFOTHNP_64QW = 0x08000000,
+ RXCS_FIFOTHNP_128QW = 0x0C000000,
+
+ RXCS_DMAREQSZ_16B = 0x00000000,
+ RXCS_DMAREQSZ_32B = 0x01000000,
+ RXCS_DMAREQSZ_64B = 0x02000000,
+ RXCS_DMAREQSZ_128B = 0x03000000,
+
+ RXCS_QUEUESEL_Q0 = 0x00000000,
+ RXCS_QUEUESEL_Q1 = 0x00010000,
+ RXCS_QUEUESEL_Q2 = 0x00020000,
+ RXCS_QUEUESEL_Q3 = 0x00030000,
+
+ RXCS_RETRYGAP_256ns = 0x00000000,
+ RXCS_RETRYGAP_512ns = 0x00001000,
+ RXCS_RETRYGAP_1024ns = 0x00002000,
+ RXCS_RETRYGAP_2048ns = 0x00003000,
+ RXCS_RETRYGAP_4096ns = 0x00004000,
+ RXCS_RETRYGAP_8192ns = 0x00005000,
+ RXCS_RETRYGAP_16384ns = 0x00006000,
+ RXCS_RETRYGAP_32768ns = 0x00007000,
+
+ RXCS_RETRYCNT_0 = 0x00000000,
+ RXCS_RETRYCNT_4 = 0x00000100,
+ RXCS_RETRYCNT_8 = 0x00000200,
+ RXCS_RETRYCNT_12 = 0x00000300,
+ RXCS_RETRYCNT_16 = 0x00000400,
+ RXCS_RETRYCNT_20 = 0x00000500,
+ RXCS_RETRYCNT_24 = 0x00000600,
+ RXCS_RETRYCNT_28 = 0x00000700,
+ RXCS_RETRYCNT_32 = 0x00000800,
+ RXCS_RETRYCNT_36 = 0x00000900,
+ RXCS_RETRYCNT_40 = 0x00000A00,
+ RXCS_RETRYCNT_44 = 0x00000B00,
+ RXCS_RETRYCNT_48 = 0x00000C00,
+ RXCS_RETRYCNT_52 = 0x00000D00,
+ RXCS_RETRYCNT_56 = 0x00000E00,
+ RXCS_RETRYCNT_60 = 0x00000F00,
+
+ RXCS_DEFAULT = RXCS_FIFOTHTP_128T |
+ RXCS_FIFOTHNP_128QW |
+ RXCS_DMAREQSZ_128B |
+ RXCS_RETRYGAP_256ns |
+ RXCS_RETRYCNT_32,
+};
+
+#define JME_RX_DISABLE_TIMEOUT 10 /* 10 msec */
+
+/*
+ * RX MAC Control/Status Bits
+ */
+enum jme_rxmcs_bits {
+ RXMCS_ALLFRAME = 0x00000800,
+ RXMCS_BRDFRAME = 0x00000400,
+ RXMCS_MULFRAME = 0x00000200,
+ RXMCS_UNIFRAME = 0x00000100,
+ RXMCS_ALLMULFRAME = 0x00000080,
+ RXMCS_MULFILTERED = 0x00000040,
+ RXMCS_RXCOLLDEC = 0x00000020,
+ RXMCS_FLOWCTRL = 0x00000008,
+ RXMCS_VTAGRM = 0x00000004,
+ RXMCS_PREPAD = 0x00000002,
+ RXMCS_CHECKSUM = 0x00000001,
+
+ RXMCS_DEFAULT = RXMCS_VTAGRM |
+ RXMCS_FLOWCTRL |
+ RXMCS_CHECKSUM,
+};
+
+/*
+ * Wakeup Frame setup interface registers
+ */
+#define WAKEUP_FRAME_NR 8
+#define WAKEUP_FRAME_MASK_DWNR 4
+
+enum jme_wfoi_bit_masks {
+ WFOI_MASK_SEL = 0x00000070,
+ WFOI_CRC_SEL = 0x00000008,
+ WFOI_FRAME_SEL = 0x00000007,
+};
+
+enum jme_wfoi_shifts {
+ WFOI_MASK_SHIFT = 4,
+};
+
+/*
+ * SMI Related definitions
+ */
+enum jme_smi_bit_mask {
+ SMI_DATA_MASK = 0xFFFF0000,
+ SMI_REG_ADDR_MASK = 0x0000F800,
+ SMI_PHY_ADDR_MASK = 0x000007C0,
+ SMI_OP_WRITE = 0x00000020,
+ /* Set to 1, after req done it'll be cleared to 0 */
+ SMI_OP_REQ = 0x00000010,
+ SMI_OP_MDIO = 0x00000008, /* Software assess In/Out */
+ SMI_OP_MDOE = 0x00000004, /* Software Output Enable */
+ SMI_OP_MDC = 0x00000002, /* Software CLK Control */
+ SMI_OP_MDEN = 0x00000001, /* Software access Enable */
+};
+
+enum jme_smi_bit_shift {
+ SMI_DATA_SHIFT = 16,
+ SMI_REG_ADDR_SHIFT = 11,
+ SMI_PHY_ADDR_SHIFT = 6,
+};
+
+static inline uint32_t smi_reg_addr(int x)
+{
+ return (x << SMI_REG_ADDR_SHIFT) & SMI_REG_ADDR_MASK;
+}
+
+static inline uint32_t smi_phy_addr(int x)
+{
+ return (x << SMI_PHY_ADDR_SHIFT) & SMI_PHY_ADDR_MASK;
+}
+
+#define JME_PHY_TIMEOUT 100 /* 100 msec */
+#define JME_PHY_REG_NR 32
+
+/*
+ * Global Host Control
+ */
+enum jme_ghc_bit_mask {
+ GHC_SWRST = 0x40000000,
+ GHC_DPX = 0x00000040,
+ GHC_SPEED = 0x00000030,
+ GHC_LINK_POLL = 0x00000001,
+};
+
+enum jme_ghc_speed_val {
+ GHC_SPEED_10M = 0x00000010,
+ GHC_SPEED_100M = 0x00000020,
+ GHC_SPEED_1000M = 0x00000030,
+};
+
+enum jme_ghc_to_clk {
+ GHC_TO_CLK_OFF = 0x00000000,
+ GHC_TO_CLK_GPHY = 0x00400000,
+ GHC_TO_CLK_PCIE = 0x00800000,
+ GHC_TO_CLK_INVALID = 0x00C00000,
+};
+
+enum jme_ghc_txmac_clk {
+ GHC_TXMAC_CLK_OFF = 0x00000000,
+ GHC_TXMAC_CLK_GPHY = 0x00100000,
+ GHC_TXMAC_CLK_PCIE = 0x00200000,
+ GHC_TXMAC_CLK_INVALID = 0x00300000,
+};
+
+/*
+ * Power management control and status register
+ */
+enum jme_pmcs_bit_masks {
+ PMCS_WF7DET = 0x80000000,
+ PMCS_WF6DET = 0x40000000,
+ PMCS_WF5DET = 0x20000000,
+ PMCS_WF4DET = 0x10000000,
+ PMCS_WF3DET = 0x08000000,
+ PMCS_WF2DET = 0x04000000,
+ PMCS_WF1DET = 0x02000000,
+ PMCS_WF0DET = 0x01000000,
+ PMCS_LFDET = 0x00040000,
+ PMCS_LRDET = 0x00020000,
+ PMCS_MFDET = 0x00010000,
+ PMCS_WF7EN = 0x00008000,
+ PMCS_WF6EN = 0x00004000,
+ PMCS_WF5EN = 0x00002000,
+ PMCS_WF4EN = 0x00001000,
+ PMCS_WF3EN = 0x00000800,
+ PMCS_WF2EN = 0x00000400,
+ PMCS_WF1EN = 0x00000200,
+ PMCS_WF0EN = 0x00000100,
+ PMCS_LFEN = 0x00000004,
+ PMCS_LREN = 0x00000002,
+ PMCS_MFEN = 0x00000001,
+};
+
+/*
+ * Giga PHY Status Registers
+ */
+enum jme_phy_link_bit_mask {
+ PHY_LINK_SPEED_MASK = 0x0000C000,
+ PHY_LINK_DUPLEX = 0x00002000,
+ PHY_LINK_SPEEDDPU_RESOLVED = 0x00000800,
+ PHY_LINK_UP = 0x00000400,
+ PHY_LINK_AUTONEG_COMPLETE = 0x00000200,
+ PHY_LINK_MDI_STAT = 0x00000040,
+};
+
+enum jme_phy_link_speed_val {
+ PHY_LINK_SPEED_10M = 0x00000000,
+ PHY_LINK_SPEED_100M = 0x00004000,
+ PHY_LINK_SPEED_1000M = 0x00008000,
+};
+
+#define JME_SPDRSV_TIMEOUT 500 /* 500 us */
+
+/*
+ * SMB Control and Status
+ */
+enum jme_smbcsr_bit_mask {
+ SMBCSR_CNACK = 0x00020000,
+ SMBCSR_RELOAD = 0x00010000,
+ SMBCSR_EEPROMD = 0x00000020,
+ SMBCSR_INITDONE = 0x00000010,
+ SMBCSR_BUSY = 0x0000000F,
+};
+
+enum jme_smbintf_bit_mask {
+ SMBINTF_HWDATR = 0xFF000000,
+ SMBINTF_HWDATW = 0x00FF0000,
+ SMBINTF_HWADDR = 0x0000FF00,
+ SMBINTF_HWRWN = 0x00000020,
+ SMBINTF_HWCMD = 0x00000010,
+ SMBINTF_FASTM = 0x00000008,
+ SMBINTF_GPIOSCL = 0x00000004,
+ SMBINTF_GPIOSDA = 0x00000002,
+ SMBINTF_GPIOEN = 0x00000001,
+};
+
+enum jme_smbintf_vals {
+ SMBINTF_HWRWN_READ = 0x00000020,
+ SMBINTF_HWRWN_WRITE = 0x00000000,
+};
+
+enum jme_smbintf_shifts {
+ SMBINTF_HWDATR_SHIFT = 24,
+ SMBINTF_HWDATW_SHIFT = 16,
+ SMBINTF_HWADDR_SHIFT = 8,
+};
+
+#define JME_EEPROM_RELOAD_TIMEOUT 2000 /* 2000 msec */
+#define JME_SMB_BUSY_TIMEOUT 20 /* 20 msec */
+#define JME_SMB_LEN 256
+#define JME_EEPROM_MAGIC 0x250
+
+/*
+ * Timer Control/Status Register
+ */
+enum jme_tmcsr_bit_masks {
+ TMCSR_SWIT = 0x80000000,
+ TMCSR_EN = 0x01000000,
+ TMCSR_CNT = 0x00FFFFFF,
+};
+
+/*
+ * General Purpose REG-0
+ */
+enum jme_gpreg0_masks {
+ GPREG0_DISSH = 0xFF000000,
+ GPREG0_PCIRLMT = 0x00300000,
+ GPREG0_PCCNOMUTCLR = 0x00040000,
+ GPREG0_LNKINTPOLL = 0x00001000,
+ GPREG0_PCCTMR = 0x00000300,
+ GPREG0_PHYADDR = 0x0000001F,
+};
+
+enum jme_gpreg0_vals {
+ GPREG0_DISSH_DW7 = 0x80000000,
+ GPREG0_DISSH_DW6 = 0x40000000,
+ GPREG0_DISSH_DW5 = 0x20000000,
+ GPREG0_DISSH_DW4 = 0x10000000,
+ GPREG0_DISSH_DW3 = 0x08000000,
+ GPREG0_DISSH_DW2 = 0x04000000,
+ GPREG0_DISSH_DW1 = 0x02000000,
+ GPREG0_DISSH_DW0 = 0x01000000,
+ GPREG0_DISSH_ALL = 0xFF000000,
+
+ GPREG0_PCIRLMT_8 = 0x00000000,
+ GPREG0_PCIRLMT_6 = 0x00100000,
+ GPREG0_PCIRLMT_5 = 0x00200000,
+ GPREG0_PCIRLMT_4 = 0x00300000,
+
+ GPREG0_PCCTMR_16ns = 0x00000000,
+ GPREG0_PCCTMR_256ns = 0x00000100,
+ GPREG0_PCCTMR_1us = 0x00000200,
+ GPREG0_PCCTMR_1ms = 0x00000300,
+
+ GPREG0_PHYADDR_1 = 0x00000001,
+
+ GPREG0_DEFAULT = GPREG0_DISSH_ALL |
+ GPREG0_PCIRLMT_4 |
+ GPREG0_PCCTMR_1us |
+ GPREG0_PHYADDR_1,
+};
+
+/*
+ * General Purpose REG-1
+ * Note: All theses bits defined here are for
+ * Chip mode revision 0x11 only
+ */
+enum jme_gpreg1_masks {
+ GPREG1_INTRDELAYUNIT = 0x00000018,
+ GPREG1_INTRDELAYENABLE = 0x00000007,
+};
+
+enum jme_gpreg1_vals {
+ GPREG1_RSSPATCH = 0x00000040,
+ GPREG1_HALFMODEPATCH = 0x00000020,
+
+ GPREG1_INTDLYUNIT_16NS = 0x00000000,
+ GPREG1_INTDLYUNIT_256NS = 0x00000008,
+ GPREG1_INTDLYUNIT_1US = 0x00000010,
+ GPREG1_INTDLYUNIT_16US = 0x00000018,
+
+ GPREG1_INTDLYEN_1U = 0x00000001,
+ GPREG1_INTDLYEN_2U = 0x00000002,
+ GPREG1_INTDLYEN_3U = 0x00000003,
+ GPREG1_INTDLYEN_4U = 0x00000004,
+ GPREG1_INTDLYEN_5U = 0x00000005,
+ GPREG1_INTDLYEN_6U = 0x00000006,
+ GPREG1_INTDLYEN_7U = 0x00000007,
+
+ GPREG1_DEFAULT = 0x00000000,
+};
+
+/*
+ * Interrupt Status Bits
+ */
+enum jme_interrupt_bits {
+ INTR_SWINTR = 0x80000000,
+ INTR_TMINTR = 0x40000000,
+ INTR_LINKCH = 0x20000000,
+ INTR_PAUSERCV = 0x10000000,
+ INTR_MAGICRCV = 0x08000000,
+ INTR_WAKERCV = 0x04000000,
+ INTR_PCCRX0TO = 0x02000000,
+ INTR_PCCRX1TO = 0x01000000,
+ INTR_PCCRX2TO = 0x00800000,
+ INTR_PCCRX3TO = 0x00400000,
+ INTR_PCCTXTO = 0x00200000,
+ INTR_PCCRX0 = 0x00100000,
+ INTR_PCCRX1 = 0x00080000,
+ INTR_PCCRX2 = 0x00040000,
+ INTR_PCCRX3 = 0x00020000,
+ INTR_PCCTX = 0x00010000,
+ INTR_RX3EMP = 0x00008000,
+ INTR_RX2EMP = 0x00004000,
+ INTR_RX1EMP = 0x00002000,
+ INTR_RX0EMP = 0x00001000,
+ INTR_RX3 = 0x00000800,
+ INTR_RX2 = 0x00000400,
+ INTR_RX1 = 0x00000200,
+ INTR_RX0 = 0x00000100,
+ INTR_TX7 = 0x00000080,
+ INTR_TX6 = 0x00000040,
+ INTR_TX5 = 0x00000020,
+ INTR_TX4 = 0x00000010,
+ INTR_TX3 = 0x00000008,
+ INTR_TX2 = 0x00000004,
+ INTR_TX1 = 0x00000002,
+ INTR_TX0 = 0x00000001,
+};
+
+static const uint32_t INTR_ENABLE = INTR_LINKCH |
+ INTR_RX0EMP |
+ INTR_RX0 |
+ INTR_TX0;
+
+/*
+ * PCC Control Registers
+ */
+enum jme_pccrx_masks {
+ PCCRXTO_MASK = 0xFFFF0000,
+ PCCRX_MASK = 0x0000FF00,
+};
+
+enum jme_pcctx_masks {
+ PCCTXTO_MASK = 0xFFFF0000,
+ PCCTX_MASK = 0x0000FF00,
+ PCCTX_QS_MASK = 0x000000FF,
+};
+
+enum jme_pccrx_shifts {
+ PCCRXTO_SHIFT = 16,
+ PCCRX_SHIFT = 8,
+};
+
+enum jme_pcctx_shifts {
+ PCCTXTO_SHIFT = 16,
+ PCCTX_SHIFT = 8,
+};
+
+enum jme_pcctx_bits {
+ PCCTXQ0_EN = 0x00000001,
+ PCCTXQ1_EN = 0x00000002,
+ PCCTXQ2_EN = 0x00000004,
+ PCCTXQ3_EN = 0x00000008,
+ PCCTXQ4_EN = 0x00000010,
+ PCCTXQ5_EN = 0x00000020,
+ PCCTXQ6_EN = 0x00000040,
+ PCCTXQ7_EN = 0x00000080,
+};
+
+/*
+ * Chip Mode Register
+ */
+enum jme_chipmode_bit_masks {
+ CM_FPGAVER_MASK = 0xFFFF0000,
+ CM_CHIPREV_MASK = 0x0000FF00,
+ CM_CHIPMODE_MASK = 0x0000000F,
+};
+
+enum jme_chipmode_shifts {
+ CM_FPGAVER_SHIFT = 16,
+ CM_CHIPREV_SHIFT = 8,
+};
+
+/*
+ * Workaround
+ */
+static inline int is_buggy250(unsigned short device, unsigned int chiprev)
+{
+ return device == PCI_DEVICE_ID_JMICRON_JMC250 && chiprev == 0x11;
+}
+
+/*
+ * Read/Write I/O Registers
+ */
+static inline uint32_t jread32(struct jme_adapter *jme, uint32_t reg)
+{
+ return readl(jme->regs + reg);
+}
+
+static inline void jwrite32(struct jme_adapter *jme, uint32_t reg, uint32_t val)
+{
+ writel(val, jme->regs + reg);
+}
+
+static void jwrite32f(struct jme_adapter *jme, uint32_t reg, uint32_t val)
+{
+ /*
+ * Read after write should cause flush
+ */
+ writel(val, jme->regs + reg);
+ readl(jme->regs + reg);
+}
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/legacy.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/legacy.c
new file mode 100644
index 00000000..4edbef16
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/legacy.c
@@ -0,0 +1,157 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/iobuf.h>
+#include <nic.h>
+
+/*
+ * Quick and dirty compatibility layer
+ *
+ * This should allow old-API PCI drivers to at least function until
+ * they are updated. It will not help non-PCI drivers.
+ *
+ * No drivers should rely on this code. It will be removed asap.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct nic nic;
+
+static int legacy_registered = 0;
+
+static int legacy_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
+ struct nic *nic = netdev->priv;
+ struct ethhdr *ethhdr;
+
+ DBG ( "Transmitting %zd bytes\n", iob_len ( iobuf ) );
+ iob_pad ( iobuf, ETH_ZLEN );
+ ethhdr = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *ethhdr ) );
+ nic->nic_op->transmit ( nic, ( const char * ) ethhdr->h_dest,
+ ntohs ( ethhdr->h_protocol ),
+ iob_len ( iobuf ), iobuf->data );
+ netdev_tx_complete ( netdev, iobuf );
+ return 0;
+}
+
+static void legacy_poll ( struct net_device *netdev ) {
+ struct nic *nic = netdev->priv;
+ struct io_buffer *iobuf;
+
+ iobuf = alloc_iob ( ETH_FRAME_LEN );
+ if ( ! iobuf )
+ return;
+
+ nic->packet = iobuf->data;
+ if ( nic->nic_op->poll ( nic, 1 ) ) {
+ DBG ( "Received %d bytes\n", nic->packetlen );
+ iob_put ( iobuf, nic->packetlen );
+ netdev_rx ( netdev, iobuf );
+ } else {
+ free_iob ( iobuf );
+ }
+}
+
+static int legacy_open ( struct net_device *netdev __unused ) {
+ /* Nothing to do */
+ return 0;
+}
+
+static void legacy_close ( struct net_device *netdev __unused ) {
+ /* Nothing to do */
+}
+
+static void legacy_irq ( struct net_device *netdev __unused, int enable ) {
+ struct nic *nic = netdev->priv;
+
+ nic->nic_op->irq ( nic, ( enable ? ENABLE : DISABLE ) );
+}
+
+static struct net_device_operations legacy_operations = {
+ .open = legacy_open,
+ .close = legacy_close,
+ .transmit = legacy_transmit,
+ .poll = legacy_poll,
+ .irq = legacy_irq,
+};
+
+int legacy_probe ( void *hwdev,
+ void ( * set_drvdata ) ( void *hwdev, void *priv ),
+ struct device *dev,
+ int ( * probe ) ( struct nic *nic, void *hwdev ),
+ void ( * disable ) ( struct nic *nic, void *hwdev ) ) {
+ struct net_device *netdev;
+ int rc;
+
+ if ( legacy_registered )
+ return -EBUSY;
+
+ netdev = alloc_etherdev ( 0 );
+ if ( ! netdev )
+ return -ENOMEM;
+ netdev_init ( netdev, &legacy_operations );
+ netdev->priv = &nic;
+ memset ( &nic, 0, sizeof ( nic ) );
+ set_drvdata ( hwdev, netdev );
+ netdev->dev = dev;
+
+ nic.node_addr = netdev->hw_addr;
+ nic.irqno = dev->desc.irq;
+
+ if ( ! probe ( &nic, hwdev ) ) {
+ rc = -ENODEV;
+ goto err_probe;
+ }
+
+ /* Overwrite the IRQ number. Some legacy devices set
+ * nic->irqno to 0 in the probe routine to indicate that they
+ * don't support interrupts; doing this allows the timer
+ * interrupt to be used instead.
+ */
+ dev->desc.irq = nic.irqno;
+
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register;
+
+ /* Mark as link up; legacy devices don't handle link state */
+ netdev_link_up ( netdev );
+
+ /* Do not remove this message */
+ printf ( "WARNING: Using legacy NIC wrapper on %s\n",
+ netdev->ll_protocol->ntoa ( nic.node_addr ) );
+
+ legacy_registered = 1;
+ return 0;
+
+ err_register:
+ disable ( &nic, hwdev );
+ err_probe:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ return rc;
+}
+
+void legacy_remove ( void *hwdev,
+ void * ( * get_drvdata ) ( void *hwdev ),
+ void ( * disable ) ( struct nic *nic, void *hwdev ) ) {
+ struct net_device *netdev = get_drvdata ( hwdev );
+ struct nic *nic = netdev->priv;
+
+ unregister_netdev ( netdev );
+ disable ( nic, hwdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ legacy_registered = 0;
+}
+
+int dummy_connect ( struct nic *nic __unused ) {
+ return 1;
+}
+
+void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
+ return;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/mii.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/mii.c
new file mode 100644
index 00000000..e6bf6068
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/mii.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ipxe/mii.h>
+
+/** @file
+ *
+ * Media Independent Interface
+ *
+ */
+
+/**
+ * Reset MII interface
+ *
+ * @v mii MII interface
+ * @ret rc Return status code
+ */
+int mii_reset ( struct mii_interface *mii ) {
+ unsigned int i;
+ int bmcr;
+ int rc;
+
+ /* Power-up, enable autonegotiation and initiate reset */
+ if ( ( rc = mii_write ( mii, MII_BMCR,
+ ( BMCR_RESET | BMCR_ANENABLE ) ) ) != 0 ) {
+ DBGC ( mii, "MII %p could not write BMCR: %s\n",
+ mii, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Wait for reset to complete */
+ for ( i = 0 ; i < MII_RESET_MAX_WAIT_MS ; i++ ) {
+
+ /* Check if reset has completed */
+ bmcr = mii_read ( mii, MII_BMCR );
+ if ( bmcr < 0 ) {
+ rc = bmcr;
+ DBGC ( mii, "MII %p could not read BMCR: %s\n",
+ mii, strerror ( rc ) );
+ return rc;
+ }
+
+ /* If reset is not complete, delay 1ms and retry */
+ if ( bmcr & BMCR_RESET ) {
+ mdelay ( 1 );
+ continue;
+ }
+
+ /* Force autonegotation on again, in case it was
+ * cleared by the reset.
+ */
+ if ( ( rc = mii_write ( mii, MII_BMCR, BMCR_ANENABLE ) ) != 0 ){
+ DBGC ( mii, "MII %p could not write BMCR: %s\n",
+ mii, strerror ( rc ) );
+ return rc;
+ }
+
+ DBGC ( mii, "MII %p reset after %dms\n", mii, i );
+ return 0;
+ }
+
+ DBGC ( mii, "MII %p timed out waiting for reset\n", mii );
+ return -ETIMEDOUT;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/myri10ge.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/myri10ge.c
new file mode 100644
index 00000000..2c9bf960
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/myri10ge.c
@@ -0,0 +1,1335 @@
+/************************************************* -*- linux-c -*-
+ * Myricom 10Gb Network Interface Card Software
+ * Copyright 2009, Myricom, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/*
+ * Author: Glenn Brown <glenn@myri.com>
+ */
+
+/*
+ * General Theory of Operation
+ *
+ * This is a minimal Myricom 10 gigabit Ethernet driver for network
+ * boot.
+ *
+ * Initialization
+ *
+ * myri10ge_pci_probe() is called by iPXE during initialization.
+ * Minimal NIC initialization is performed to minimize resources
+ * consumed when the driver is resident but unused.
+ *
+ * Network Boot
+ *
+ * myri10ge_net_open() is called by iPXE before attempting to network
+ * boot from the card. Packet buffers are allocated and the NIC
+ * interface is initialized.
+ *
+ * Transmit
+ *
+ * myri10ge_net_transmit() enqueues frames for transmission by writing
+ * discriptors to the NIC's tx ring. For simplicity and to avoid
+ * copies, we always have the NIC DMA up the packet. The sent I/O
+ * buffer is released once the NIC signals myri10ge_interrupt_handler()
+ * that the send has completed.
+ *
+ * Receive
+ *
+ * Receives are posted to the NIC's receive ring. The NIC fills a
+ * DMAable receive_completion ring with completion notifications.
+ * myri10ge_net_poll() polls for these receive notifications, posts
+ * replacement receive buffers to the NIC, and passes received frames
+ * to netdev_rx().
+ *
+ * NonVolatile Storage
+ *
+ * This driver supports NonVolatile Storage (nvs) in the NIC EEPROM.
+ * If the last EEPROM block is not otherwise filled, we tell
+ * iPXE it may store NonVolatile Options (nvo) there.
+ */
+
+/*
+ * Debugging levels:
+ * - DBG() is for any errors, i.e. failed alloc_iob(), malloc_dma(),
+ * TX overflow, corrupted packets, ...
+ * - DBG2() is for successful events, like packet received,
+ * packet transmitted, and other general notifications.
+ * - DBGP() prints the name of each called function on entry
+ */
+
+#include <stdint.h>
+
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/nvo.h>
+#include <ipxe/nvs.h>
+#include <ipxe/pci.h>
+#include <ipxe/timer.h>
+
+#include "myri10ge_mcp.h"
+
+/****************************************************************
+ * Forward declarations
+ ****************************************************************/
+
+/* PCI driver entry points */
+
+static int myri10ge_pci_probe ( struct pci_device* );
+static void myri10ge_pci_remove ( struct pci_device* );
+
+/* Network device operations */
+
+static void myri10ge_net_close ( struct net_device* );
+static void myri10ge_net_irq ( struct net_device*, int enable );
+static int myri10ge_net_open ( struct net_device* );
+static void myri10ge_net_poll ( struct net_device* );
+static int myri10ge_net_transmit ( struct net_device*, struct io_buffer* );
+
+/****************************************************************
+ * Constants
+ ****************************************************************/
+
+/* Maximum ring indices, used to wrap ring indices. These must be 2**N-1. */
+
+#define MYRI10GE_TRANSMIT_WRAP 1U
+#define MYRI10GE_RECEIVE_WRAP 7U
+#define MYRI10GE_RECEIVE_COMPLETION_WRAP 31U
+
+/****************************************************************
+ * Driver internal data types.
+ ****************************************************************/
+
+/* Structure holding all DMA buffers for a NIC, which we will
+ allocated as contiguous read/write DMAable memory when the NIC is
+ initialized. */
+
+struct myri10ge_dma_buffers
+{
+ /* The NIC DMAs receive completion notifications into this ring */
+
+ mcp_slot_t receive_completion[1+MYRI10GE_RECEIVE_COMPLETION_WRAP];
+
+ /* Interrupt details are DMAd here before interrupting. */
+
+ mcp_irq_data_t irq_data; /* 64B */
+
+ /* NIC command completion status is DMAd here. */
+
+ mcp_cmd_response_t command_response; /* 8B */
+};
+
+struct myri10ge_private
+{
+ /* Interrupt support */
+
+ uint32 *irq_claim; /* in NIC SRAM */
+ uint32 *irq_deassert; /* in NIC SRAM */
+
+ /* DMA buffers. */
+
+ struct myri10ge_dma_buffers *dma;
+
+ /*
+ * Transmit state.
+ *
+ * The counts here are uint32 for easy comparison with
+ * priv->dma->irq_data.send_done_count and with each other.
+ */
+
+ mcp_kreq_ether_send_t *transmit_ring; /* in NIC SRAM */
+ uint32 transmit_ring_wrap;
+ uint32 transmits_posted;
+ uint32 transmits_done;
+ struct io_buffer *transmit_iob[1 + MYRI10GE_TRANSMIT_WRAP];
+
+ /*
+ * Receive state.
+ */
+
+ mcp_kreq_ether_recv_t *receive_post_ring; /* in NIC SRAM */
+ unsigned int receive_post_ring_wrap;
+ unsigned int receives_posted;
+ unsigned int receives_done;
+ struct io_buffer *receive_iob[1 + MYRI10GE_RECEIVE_WRAP];
+
+ /* Address for writing commands to the firmware.
+ BEWARE: the value must be written 32 bits at a time. */
+
+ mcp_cmd_t *command;
+
+ /*
+ * Nonvolatile Storage for configuration options.
+ */
+
+ struct nvs_device nvs;
+ struct nvo_block nvo;
+ unsigned int nvo_registered;
+
+ /* Cached PCI capability locations. */
+
+ uint8 pci_cap_vs;
+};
+
+/****************************************************************
+ * Driver internal functions.
+ ****************************************************************/
+
+/* Print ring status when debugging. Use this only after a printed
+ value changes. */
+
+#define DBG2_RINGS( priv ) \
+ DBG2 ( "tx %x/%x rx %x/%x in %s() \n", \
+ ( priv ) ->transmits_done, ( priv ) -> transmits_posted, \
+ ( priv ) ->receives_done, ( priv ) -> receives_posted, \
+ __FUNCTION__ )
+
+/*
+ * Return a pointer to the driver private data for a network device.
+ *
+ * @v netdev Network device created by this driver.
+ * @ret priv The corresponding driver private data.
+ */
+static inline struct myri10ge_private *myri10ge_priv ( struct net_device *nd )
+{
+ /* Our private data always follows the network device in memory,
+ since we use alloc_netdev() to allocate the storage. */
+
+ return ( struct myri10ge_private * ) ( nd + 1 );
+}
+
+/*
+ * Convert a Myri10ge driver private data pointer to a netdev pointer.
+ *
+ * @v p Myri10ge device private data.
+ * @ret r The corresponding network device.
+ */
+static inline struct net_device *myri10ge_netdev ( struct myri10ge_private *p )
+{
+ return ( ( struct net_device * ) p ) - 1;
+}
+
+/*
+ * Convert a network device pointer to a PCI device pointer.
+ *
+ * @v netdev A Network Device.
+ * @ret r The corresponding PCI device.
+ */
+static inline struct pci_device *myri10ge_pcidev ( struct net_device *netdev )
+{
+ return container_of (netdev->dev, struct pci_device, dev);
+}
+
+/*
+ * Pass a receive buffer to the NIC to be filled.
+ *
+ * @v priv The network device to receive the buffer.
+ * @v iob The I/O buffer to fill.
+ *
+ * Receive buffers are filled in FIFO order.
+ */
+static void myri10ge_post_receive ( struct myri10ge_private *priv,
+ struct io_buffer *iob )
+{
+ unsigned int receives_posted;
+ mcp_kreq_ether_recv_t *request;
+
+ /* Record the posted I/O buffer, to be passed to netdev_rx() on
+ receive. */
+
+ receives_posted = priv->receives_posted;
+ priv->receive_iob[receives_posted & MYRI10GE_RECEIVE_WRAP] = iob;
+
+ /* Post the receive. */
+
+ request = &priv->receive_post_ring[receives_posted
+ & priv->receive_post_ring_wrap];
+ request->addr_high = 0;
+ wmb();
+ request->addr_low = htonl ( virt_to_bus ( iob->data ) );
+ priv->receives_posted = ++receives_posted;
+}
+
+/*
+ * Execute a command on the NIC.
+ *
+ * @v priv NIC to perform the command.
+ * @v cmd The command to perform.
+ * @v data I/O copy buffer for parameters/results
+ * @ret rc 0 on success, else an error code.
+ */
+static int myri10ge_command ( struct myri10ge_private *priv,
+ uint32 cmd,
+ uint32 data[3] )
+{
+ int i;
+ mcp_cmd_t *command;
+ uint32 result;
+ unsigned int slept_ms;
+ volatile mcp_cmd_response_t *response;
+
+ DBGP ( "myri10ge_command ( ,%d, ) \n", cmd );
+ command = priv->command;
+ response = &priv->dma->command_response;
+
+ /* Mark the command as incomplete. */
+
+ response->result = 0xFFFFFFFF;
+
+ /* Pass the command to the NIC. */
+
+ command->cmd = htonl ( cmd );
+ command->data0 = htonl ( data[0] );
+ command->data1 = htonl ( data[1] );
+ command->data2 = htonl ( data[2] );
+ command->response_addr.high = 0;
+ command->response_addr.low
+ = htonl ( virt_to_bus ( &priv->dma->command_response ) );
+ for ( i=0; i<9; i++ )
+ command->pad[i] = 0;
+ wmb();
+ command->pad[9] = 0;
+
+ /* Wait up to 2 seconds for a response. */
+
+ for ( slept_ms=0; slept_ms<2000; slept_ms++ ) {
+ result = response->result;
+ if ( result == 0 ) {
+ data[0] = ntohl ( response->data );
+ return 0;
+ } else if ( result != 0xFFFFFFFF ) {
+ DBG ( "cmd%d:0x%x\n",
+ cmd,
+ ntohl ( response->result ) );
+ return -EIO;
+ }
+ udelay ( 1000 );
+ rmb();
+ }
+ DBG ( "cmd%d:timed out\n", cmd );
+ return -ETIMEDOUT;
+}
+
+/*
+ * Handle any pending interrupt.
+ *
+ * @v netdev Device being polled for interrupts.
+ *
+ * This is called periodically to let the driver check for interrupts.
+ */
+static void myri10ge_interrupt_handler ( struct net_device *netdev )
+{
+ struct myri10ge_private *priv;
+ mcp_irq_data_t *irq_data;
+ uint8 valid;
+
+ priv = myri10ge_priv ( netdev );
+ irq_data = &priv->dma->irq_data;
+
+ /* Return if there was no interrupt. */
+
+ rmb();
+ valid = irq_data->valid;
+ if ( !valid )
+ return;
+ DBG2 ( "irq " );
+
+ /* Tell the NIC to deassert the interrupt and clear
+ irq_data->valid.*/
+
+ *priv->irq_deassert = 0; /* any value is OK. */
+ mb();
+
+ /* Handle any new receives. */
+
+ if ( valid & 1 ) {
+
+ /* Pass the receive interrupt token back to the NIC. */
+
+ DBG2 ( "rx " );
+ *priv->irq_claim = htonl ( 3 );
+ wmb();
+ }
+
+ /* Handle any sent packet by freeing its I/O buffer, now that
+ we know it has been DMAd. */
+
+ if ( valid & 2 ) {
+ unsigned int nic_done_count;
+
+ DBG2 ( "snt " );
+ nic_done_count = ntohl ( priv->dma->irq_data.send_done_count );
+ while ( priv->transmits_done != nic_done_count ) {
+ struct io_buffer *iob;
+
+ iob = priv->transmit_iob [priv->transmits_done
+ & MYRI10GE_TRANSMIT_WRAP];
+ DBG2 ( "%p ", iob );
+ netdev_tx_complete ( netdev, iob );
+ ++priv->transmits_done;
+ }
+ }
+
+ /* Record any statistics update. */
+
+ if ( irq_data->stats_updated ) {
+
+ /* Update the link status. */
+
+ DBG2 ( "stats " );
+ if ( ntohl ( irq_data->link_up ) == MXGEFW_LINK_UP )
+ netdev_link_up ( netdev );
+ else
+ netdev_link_down ( netdev );
+
+ /* Ignore all error counters from the NIC. */
+ }
+
+ /* Wait for the interrupt to be deasserted, as indicated by
+ irq_data->valid, which is set by the NIC after the deassert. */
+
+ DBG2 ( "wait " );
+ do {
+ mb();
+ } while ( irq_data->valid );
+
+ /* Claim the interrupt to enable future interrupt generation. */
+
+ DBG2 ( "claim\n" );
+ * ( priv->irq_claim + 1 ) = htonl ( 3 );
+ mb();
+}
+
+/* Constants for reading the STRING_SPECS via the Myricom
+ Vendor Specific PCI configuration space capability. */
+
+#define VS_EEPROM_READ_ADDR ( vs + 0x04 )
+#define VS_EEPROM_READ_DATA ( vs + 0x08 )
+#define VS_EEPROM_WRITE ( vs + 0x0C )
+#define VS_ADDR ( vs + 0x18 )
+#define VS_DATA ( vs + 0x14 )
+#define VS_MODE ( vs + 0x10 )
+#define VS_MODE_READ32 0x3
+#define VS_MODE_LOCATE 0x8
+#define VS_LOCATE_STRING_SPECS 0x3
+#define VS_MODE_EEPROM_STREAM_WRITE 0xB
+
+/*
+ * Read MAC address from its 'string specs' via the vendor-specific
+ * capability. (This capability allows NIC SRAM and ROM to be read
+ * before it is mapped.)
+ *
+ * @v pci The device.
+ * @v vs Offset of the PCI Vendor-Specific Capability.
+ * @v mac Buffer to store the MAC address.
+ * @ret rc Returns 0 on success, else an error code.
+ */
+static int mac_address_from_string_specs ( struct pci_device *pci,
+ unsigned int vs,
+ uint8 mac[ETH_ALEN] )
+{
+ char string_specs[256];
+ char *ptr, *limit;
+ char *to = string_specs;
+ uint32 addr;
+ uint32 len;
+ int mac_set = 0;
+
+ /* Locate the String specs in LANai SRAM. */
+
+ pci_write_config_byte ( pci, VS_MODE, VS_MODE_LOCATE );
+ pci_write_config_dword ( pci, VS_ADDR, VS_LOCATE_STRING_SPECS );
+ pci_read_config_dword ( pci, VS_ADDR, &addr );
+ pci_read_config_dword ( pci, VS_DATA, &len );
+ DBG2 ( "ss@%x,%x\n", addr, len );
+
+ /* Copy in the string specs. Use 32-bit reads for performance. */
+
+ if ( len > sizeof ( string_specs ) || ( len & 3 ) ) {
+ pci_write_config_byte ( pci, VS_MODE, 0 );
+ DBG ( "SS too big\n" );
+ return -ENOTSUP;
+ }
+
+ pci_write_config_byte ( pci, VS_MODE, VS_MODE_READ32 );
+ while ( len >= 4 ) {
+ uint32 tmp;
+
+ pci_write_config_byte ( pci, VS_ADDR, addr );
+ pci_read_config_dword ( pci, VS_DATA, &tmp );
+ tmp = ntohl ( tmp );
+ memcpy ( to, &tmp, 4 );
+ to += 4;
+ addr += 4;
+ len -= 4;
+ }
+ pci_write_config_byte ( pci, VS_MODE, 0 );
+
+ /* Parse the string specs. */
+
+ DBG2 ( "STRING_SPECS:\n" );
+ ptr = string_specs;
+ limit = string_specs + sizeof ( string_specs );
+ while ( *ptr != '\0' && ptr < limit ) {
+ DBG2 ( "%s\n", ptr );
+ if ( memcmp ( ptr, "MAC=", 4 ) == 0 ) {
+ unsigned int i;
+
+ ptr += 4;
+ for ( i=0; i<6; i++ ) {
+ if ( ( ptr + 2 ) > limit ) {
+ DBG ( "bad MAC addr\n" );
+ return -ENOTSUP;
+ }
+ mac[i] = strtoul ( ptr, &ptr, 16 );
+ ptr += 1;
+ }
+ mac_set = 1;
+ }
+ else
+ while ( ptr < limit && *ptr++ );
+ }
+
+ /* Verify we parsed all we need. */
+
+ if ( !mac_set ) {
+ DBG ( "no MAC addr\n" );
+ return -ENOTSUP;
+ }
+
+ DBG2 ( "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
+
+ return 0;
+}
+
+/****************************************************************
+ * NonVolatile Storage support
+ ****************************************************************/
+
+/*
+ * Fill a buffer with data read from nonvolatile storage.
+ *
+ * @v nvs The NonVolatile Storage device to be read.
+ * @v addr The first NonVolatile Storage address to be read.
+ * @v _buf Pointer to the data buffer to be filled.
+ * @v len The number of bytes to copy.
+ * @ret rc 0 on success, else nonzero.
+ */
+static int myri10ge_nvs_read ( struct nvs_device *nvs,
+ unsigned int addr,
+ void *_buf,
+ size_t len )
+{
+ struct myri10ge_private *priv =
+ container_of (nvs, struct myri10ge_private, nvs);
+ struct pci_device *pci = myri10ge_pcidev ( myri10ge_netdev ( priv ) );
+ unsigned int vs = priv->pci_cap_vs;
+ unsigned char *buf = (unsigned char *) _buf;
+ unsigned int data;
+ unsigned int i, j;
+
+ DBGP ( "myri10ge_nvs_read\n" );
+
+ /* Issue the first read address. */
+
+ pci_write_config_byte ( pci, VS_EEPROM_READ_ADDR + 3, addr>>16 );
+ pci_write_config_byte ( pci, VS_EEPROM_READ_ADDR + 2, addr>>8 );
+ pci_write_config_byte ( pci, VS_EEPROM_READ_ADDR + 1, addr );
+ addr++;
+
+ /* Issue all the reads, and harvest the results every 4th issue. */
+
+ for ( i=0; i<len; ++i,addr++ ) {
+
+ /* Issue the next read address, updating only the
+ bytes that need updating. We always update the
+ LSB, which triggers the read. */
+
+ if ( ( addr & 0xff ) == 0 ) {
+ if ( ( addr & 0xffff ) == 0 ) {
+ pci_write_config_byte ( pci,
+ VS_EEPROM_READ_ADDR + 3,
+ addr >> 16 );
+ }
+ pci_write_config_byte ( pci,
+ VS_EEPROM_READ_ADDR + 2,
+ addr >> 8 );
+ }
+ pci_write_config_byte ( pci, VS_EEPROM_READ_ADDR + 1, addr );
+
+ /* If 4 data bytes are available, read them with a single read. */
+
+ if ( ( i & 3 ) == 3 ) {
+ pci_read_config_dword ( pci,
+ VS_EEPROM_READ_DATA,
+ &data );
+ for ( j=0; j<4; j++ ) {
+ buf[i-j] = data;
+ data >>= 8;
+ }
+ }
+ }
+
+ /* Harvest any remaining results. */
+
+ if ( ( i & 3 ) != 0 ) {
+ pci_read_config_dword ( pci, VS_EEPROM_READ_DATA, &data );
+ for ( j=1; j<=(i&3); j++ ) {
+ buf[i-j] = data;
+ data >>= 8;
+ }
+ }
+
+ DBGP_HDA ( addr - len, _buf, len );
+ return 0;
+}
+
+/*
+ * Write a buffer into nonvolatile storage.
+ *
+ * @v nvs The NonVolatile Storage device to be written.
+ * @v address The NonVolatile Storage address to be written.
+ * @v _buf Pointer to the data to be written.
+ * @v len Length of the buffer to be written.
+ * @ret rc 0 on success, else nonzero.
+ */
+static int myri10ge_nvs_write ( struct nvs_device *nvs,
+ unsigned int addr,
+ const void *_buf,
+ size_t len )
+{
+ struct myri10ge_private *priv =
+ container_of (nvs, struct myri10ge_private, nvs);
+ struct pci_device *pci = myri10ge_pcidev ( myri10ge_netdev ( priv ) );
+ unsigned int vs = priv->pci_cap_vs;
+ const unsigned char *buf = (const unsigned char *)_buf;
+ unsigned int i;
+ uint8 verify;
+
+ DBGP ( "nvs_write " );
+ DBGP_HDA ( addr, _buf, len );
+
+ /* Start erase of the NonVolatile Options block. */
+
+ DBGP ( "erasing " );
+ pci_write_config_dword ( pci, VS_EEPROM_WRITE, ( addr << 8 ) | 0xff );
+
+ /* Wait for erase to complete. */
+
+ DBGP ( "waiting " );
+ pci_read_config_byte ( pci, VS_EEPROM_READ_DATA, &verify );
+ while ( verify != 0xff ) {
+ pci_write_config_byte ( pci, VS_EEPROM_READ_ADDR + 1, addr );
+ pci_read_config_byte ( pci, VS_EEPROM_READ_DATA, &verify );
+ }
+
+ /* Write the data one byte at a time. */
+
+ DBGP ( "writing " );
+ pci_write_config_byte ( pci, VS_MODE, VS_MODE_EEPROM_STREAM_WRITE );
+ pci_write_config_dword ( pci, VS_ADDR, addr );
+ for (i=0; i<len; i++, addr++)
+ pci_write_config_byte ( pci, VS_DATA, buf[i] );
+ pci_write_config_dword ( pci, VS_ADDR, 0xffffffff );
+ pci_write_config_byte ( pci, VS_MODE, 0 );
+
+ DBGP ( "done\n" );
+ return 0;
+}
+
+/*
+ * Initialize NonVolatile storage support for a device.
+ *
+ * @v priv Device private data for the device.
+ * @ret rc 0 on success, else an error code.
+ */
+
+static int myri10ge_nv_init ( struct myri10ge_private *priv )
+{
+ int rc;
+ struct myri10ge_eeprom_header
+ {
+ uint8 __jump[8];
+ uint32 eeprom_len;
+ uint32 eeprom_segment_len;
+ uint32 mcp1_offset;
+ uint32 mcp2_offset;
+ uint32 version;
+ } hdr;
+ uint32 mcp2_len;
+ unsigned int nvo_fragment_pos;
+
+ DBGP ( "myri10ge_nv_init\n" );
+
+ /* Read the EEPROM header, and byteswap the fields we will use.
+ This is safe even though priv->nvs is not yet initialized. */
+
+ rc = myri10ge_nvs_read ( &priv->nvs, 0, &hdr, sizeof ( hdr ) );
+ if ( rc ) {
+ DBG ( "EEPROM header unreadable\n" );
+ return rc;
+ }
+ hdr.eeprom_len = ntohl ( hdr.eeprom_len );
+ hdr.eeprom_segment_len = ntohl ( hdr.eeprom_segment_len );
+ hdr.mcp2_offset = ntohl ( hdr.mcp2_offset );
+ hdr.version = ntohl ( hdr.version );
+ DBG2 ( "eelen:%xh seglen:%xh mcp2@%xh ver%d\n", hdr.eeprom_len,
+ hdr.eeprom_segment_len, hdr.mcp2_offset, hdr.version );
+
+ /* If the firmware does not support EEPROM writes, simply return. */
+
+ if ( hdr.version < 1 ) {
+ DBG ( "No EEPROM write support\n" );
+ return 0;
+ }
+
+ /* Read the length of MCP2. */
+
+ rc = myri10ge_nvs_read ( &priv->nvs, hdr.mcp2_offset, &mcp2_len, 4 );
+ mcp2_len = ntohl ( mcp2_len );
+ DBG2 ( "mcp2len:%xh\n", mcp2_len );
+
+ /* Determine the position of the NonVolatile Options fragment and
+ simply return if it overlaps other data. */
+
+ nvo_fragment_pos = hdr.eeprom_len - hdr.eeprom_segment_len;
+ if ( hdr.mcp2_offset + mcp2_len > nvo_fragment_pos ) {
+ DBG ( "EEPROM full\n" );
+ return 0;
+ }
+
+ /* Initilize NonVolatile Storage state. */
+
+ priv->nvs.word_len_log2 = 0;
+ priv->nvs.size = hdr.eeprom_len;
+ priv->nvs.block_size = hdr.eeprom_segment_len;
+ priv->nvs.read = myri10ge_nvs_read;
+ priv->nvs.write = myri10ge_nvs_write;
+
+ /* Register the NonVolatile Options storage. */
+
+ nvo_init ( &priv->nvo,
+ &priv->nvs,
+ nvo_fragment_pos, 0x200,
+ NULL,
+ & myri10ge_netdev (priv) -> refcnt );
+ rc = register_nvo ( &priv->nvo,
+ netdev_settings ( myri10ge_netdev ( priv ) ) );
+ if ( rc ) {
+ DBG ("register_nvo failed");
+ return rc;
+ }
+
+ priv->nvo_registered = 1;
+ DBG2 ( "NVO supported\n" );
+ return 0;
+}
+
+void
+myri10ge_nv_fini ( struct myri10ge_private *priv )
+{
+ /* Simply return if nonvolatile access is not supported. */
+
+ if ( 0 == priv->nvo_registered )
+ return;
+
+ unregister_nvo ( &priv->nvo );
+}
+
+/****************************************************************
+ * iPXE PCI Device Driver API functions
+ ****************************************************************/
+
+/*
+ * Initialize the PCI device.
+ *
+ * @v pci The device's associated pci_device structure.
+ * @v id The PCI device + vendor id.
+ * @ret rc Returns zero if successfully initialized.
+ *
+ * This function is called very early on, while iPXE is initializing.
+ * This is a iPXE PCI Device Driver API function.
+ */
+static int myri10ge_pci_probe ( struct pci_device *pci )
+{
+ static struct net_device_operations myri10ge_operations = {
+ .open = myri10ge_net_open,
+ .close = myri10ge_net_close,
+ .transmit = myri10ge_net_transmit,
+ .poll = myri10ge_net_poll,
+ .irq = myri10ge_net_irq
+ };
+
+ const char *dbg;
+ int rc;
+ struct net_device *netdev;
+ struct myri10ge_private *priv;
+
+ DBGP ( "myri10ge_pci_probe: " );
+
+ netdev = alloc_etherdev ( sizeof ( *priv ) );
+ if ( !netdev ) {
+ rc = -ENOMEM;
+ dbg = "alloc_etherdev";
+ goto abort_with_nothing;
+ }
+
+ netdev_init ( netdev, &myri10ge_operations );
+ priv = myri10ge_priv ( netdev );
+
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+
+ /* Make sure interrupts are disabled. */
+
+ myri10ge_net_irq ( netdev, 0 );
+
+ /* Find the PCI Vendor-Specific capability. */
+
+ priv->pci_cap_vs = pci_find_capability ( pci , PCI_CAP_ID_VNDR );
+ if ( 0 == priv->pci_cap_vs ) {
+ rc = -ENOTSUP;
+ dbg = "no_vs";
+ goto abort_with_netdev_init;
+ }
+
+ /* Read the NIC HW address. */
+
+ rc = mac_address_from_string_specs ( pci,
+ priv->pci_cap_vs,
+ netdev->hw_addr );
+ if ( rc ) {
+ dbg = "mac_from_ss";
+ goto abort_with_netdev_init;
+ }
+ DBGP ( "mac " );
+
+ /* Enable bus master, etc. */
+
+ adjust_pci_device ( pci );
+ DBGP ( "pci " );
+
+ /* Register the initialized network device. */
+
+ rc = register_netdev ( netdev );
+ if ( rc ) {
+ dbg = "register_netdev";
+ goto abort_with_netdev_init;
+ }
+
+ /* Initialize NonVolatile Storage support. */
+
+ rc = myri10ge_nv_init ( priv );
+ if ( rc ) {
+ dbg = "myri10ge_nv_init";
+ goto abort_with_registered_netdev;
+ }
+
+ DBGP ( "done\n" );
+
+ return 0;
+
+abort_with_registered_netdev:
+ unregister_netdev ( netdev );
+abort_with_netdev_init:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+abort_with_nothing:
+ DBG ( "%s:%s\n", dbg, strerror ( rc ) );
+ return rc;
+}
+
+/*
+ * Remove a device from the PCI device list.
+ *
+ * @v pci PCI device to remove.
+ *
+ * This is a PCI Device Driver API function.
+ */
+static void myri10ge_pci_remove ( struct pci_device *pci )
+{
+ struct net_device *netdev;
+
+ DBGP ( "myri10ge_pci_remove\n" );
+ netdev = pci_get_drvdata ( pci );
+
+ myri10ge_nv_fini ( myri10ge_priv ( netdev ) );
+ unregister_netdev ( netdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/****************************************************************
+ * iPXE Network Device Driver Operations
+ ****************************************************************/
+
+/*
+ * Close a network device.
+ *
+ * @v netdev Device to close.
+ *
+ * This is a iPXE Network Device Driver API function.
+ */
+static void myri10ge_net_close ( struct net_device *netdev )
+{
+ struct myri10ge_private *priv;
+ uint32 data[3];
+
+ DBGP ( "myri10ge_net_close\n" );
+ priv = myri10ge_priv ( netdev );
+
+ /* disable interrupts */
+
+ myri10ge_net_irq ( netdev, 0 );
+
+ /* Reset the NIC interface, so we won't get any more events from
+ the NIC. */
+
+ myri10ge_command ( priv, MXGEFW_CMD_RESET, data );
+
+ /* Free receive buffers that were never filled. */
+
+ while ( priv->receives_done != priv->receives_posted ) {
+ free_iob ( priv->receive_iob[priv->receives_done
+ & MYRI10GE_RECEIVE_WRAP] );
+ ++priv->receives_done;
+ }
+
+ /* Release DMAable memory. */
+
+ free_dma ( priv->dma, sizeof ( *priv->dma ) );
+
+ /* Erase all state from the open. */
+
+ memset ( priv, 0, sizeof ( *priv ) );
+
+ DBG2_RINGS ( priv );
+}
+
+/*
+ * Enable or disable IRQ masking.
+ *
+ * @v netdev Device to control.
+ * @v enable Zero to mask off IRQ, non-zero to enable IRQ.
+ *
+ * This is a iPXE Network Driver API function.
+ */
+static void myri10ge_net_irq ( struct net_device *netdev, int enable )
+{
+ struct pci_device *pci_dev;
+ uint16 val;
+
+ DBGP ( "myri10ge_net_irq\n" );
+ pci_dev = ( struct pci_device * ) netdev->dev;
+
+ /* Adjust the Interrupt Disable bit in the Command register of the
+ PCI Device. */
+
+ pci_read_config_word ( pci_dev, PCI_COMMAND, &val );
+ if ( enable )
+ val &= ~PCI_COMMAND_INTX_DISABLE;
+ else
+ val |= PCI_COMMAND_INTX_DISABLE;
+ pci_write_config_word ( pci_dev, PCI_COMMAND, val );
+}
+
+/*
+ * Opens a network device.
+ *
+ * @v netdev Device to be opened.
+ * @ret rc Non-zero if failed to open.
+ *
+ * This enables tx and rx on the device.
+ * This is a iPXE Network Device Driver API function.
+ */
+static int myri10ge_net_open ( struct net_device *netdev )
+{
+ const char *dbg; /* printed upon error return */
+ int rc;
+ struct io_buffer *iob;
+ struct myri10ge_private *priv;
+ uint32 data[3];
+ struct pci_device *pci_dev;
+ void *membase;
+
+ DBGP ( "myri10ge_net_open\n" );
+ priv = myri10ge_priv ( netdev );
+ pci_dev = ( struct pci_device * ) netdev->dev;
+ membase = phys_to_virt ( pci_dev->membase );
+
+ /* Compute address for passing commands to the firmware. */
+
+ priv->command = membase + MXGEFW_ETH_CMD;
+
+ /* Ensure interrupts are disabled. */
+
+ myri10ge_net_irq ( netdev, 0 );
+
+ /* Allocate cleared DMAable buffers. */
+
+ priv->dma = malloc_dma ( sizeof ( *priv->dma ) , 128 );
+ if ( !priv->dma ) {
+ rc = -ENOMEM;
+ dbg = "DMA";
+ goto abort_with_nothing;
+ }
+ memset ( priv->dma, 0, sizeof ( *priv->dma ) );
+
+ /* Simplify following code. */
+
+#define TRY( prefix, base, suffix ) do { \
+ rc = myri10ge_command ( priv, \
+ MXGEFW_ \
+ ## prefix \
+ ## base \
+ ## suffix, \
+ data ); \
+ if ( rc ) { \
+ dbg = #base; \
+ goto abort_with_dma; \
+ } \
+ } while ( 0 )
+
+ /* Send a reset command to the card to see if it is alive,
+ and to reset its queue state. */
+
+ TRY ( CMD_, RESET , );
+
+ /* Set the interrupt queue size. */
+
+ data[0] = ( (uint32_t)( sizeof ( priv->dma->receive_completion ) )
+ | MXGEFW_CMD_SET_INTRQ_SIZE_FLAG_NO_STRICT_SIZE_CHECK );
+ TRY ( CMD_SET_ , INTRQ_SIZE , );
+
+ /* Set the interrupt queue DMA address. */
+
+ data[0] = virt_to_bus ( &priv->dma->receive_completion );
+ data[1] = 0;
+ TRY ( CMD_SET_, INTRQ_DMA, );
+
+ /* Get the NIC interrupt claim address. */
+
+ TRY ( CMD_GET_, IRQ_ACK, _OFFSET );
+ priv->irq_claim = membase + data[0];
+
+ /* Get the NIC interrupt assert address. */
+
+ TRY ( CMD_GET_, IRQ_DEASSERT, _OFFSET );
+ priv->irq_deassert = membase + data[0];
+
+ /* Disable interrupt coalescing, which is inappropriate for the
+ minimal buffering we provide. */
+
+ TRY ( CMD_GET_, INTR_COAL, _DELAY_OFFSET );
+ * ( ( uint32 * ) ( membase + data[0] ) ) = 0;
+
+ /* Set the NIC mac address. */
+
+ data[0] = ( netdev->ll_addr[0] << 24
+ | netdev->ll_addr[1] << 16
+ | netdev->ll_addr[2] << 8
+ | netdev->ll_addr[3] );
+ data[1] = ( ( netdev->ll_addr[4] << 8 )
+ | netdev->ll_addr[5] );
+ TRY ( SET_ , MAC_ADDRESS , );
+
+ /* Enable multicast receives, because some iPXE clients don't work
+ without multicast. . */
+
+ TRY ( ENABLE_ , ALLMULTI , );
+
+ /* Disable Ethernet flow control, so the NIC cannot deadlock the
+ network under any circumstances. */
+
+ TRY ( DISABLE_ , FLOW , _CONTROL );
+
+ /* Compute transmit ring sizes. */
+
+ data[0] = 0; /* slice 0 */
+ TRY ( CMD_GET_, SEND_RING, _SIZE );
+ priv->transmit_ring_wrap
+ = data[0] / sizeof ( mcp_kreq_ether_send_t ) - 1;
+ if ( priv->transmit_ring_wrap
+ & ( priv->transmit_ring_wrap + 1 ) ) {
+ rc = -EPROTO;
+ dbg = "TX_RING";
+ goto abort_with_dma;
+ }
+
+ /* Compute receive ring sizes. */
+
+ data[0] = 0; /* slice 0 */
+ TRY ( CMD_GET_ , RX_RING , _SIZE );
+ priv->receive_post_ring_wrap = data[0] / sizeof ( mcp_dma_addr_t ) - 1;
+ if ( priv->receive_post_ring_wrap
+ & ( priv->receive_post_ring_wrap + 1 ) ) {
+ rc = -EPROTO;
+ dbg = "RX_RING";
+ goto abort_with_dma;
+ }
+
+ /* Get NIC transmit ring address. */
+
+ data[0] = 0; /* slice 0. */
+ TRY ( CMD_GET_, SEND, _OFFSET );
+ priv->transmit_ring = membase + data[0];
+
+ /* Get the NIC receive ring address. */
+
+ data[0] = 0; /* slice 0. */
+ TRY ( CMD_GET_, SMALL_RX, _OFFSET );
+ priv->receive_post_ring = membase + data[0];
+
+ /* Set the Nic MTU. */
+
+ data[0] = ETH_FRAME_LEN;
+ TRY ( CMD_SET_, MTU, );
+
+ /* Tell the NIC our buffer sizes. ( We use only small buffers, so we
+ set both buffer sizes to the same value, which will force all
+ received frames to use small buffers. ) */
+
+ data[0] = MXGEFW_PAD + ETH_FRAME_LEN;
+ TRY ( CMD_SET_, SMALL_BUFFER, _SIZE );
+ data[0] = MXGEFW_PAD + ETH_FRAME_LEN;
+ TRY ( CMD_SET_, BIG_BUFFER, _SIZE );
+
+ /* Tell firmware where to DMA IRQ data */
+
+ data[0] = virt_to_bus ( &priv->dma->irq_data );
+ data[1] = 0;
+ data[2] = sizeof ( priv->dma->irq_data );
+ TRY ( CMD_SET_, STATS_DMA_V2, );
+
+ /* Post receives. */
+
+ while ( priv->receives_posted <= MYRI10GE_RECEIVE_WRAP ) {
+
+ /* Reserve 2 extra bytes at the start of packets, since
+ the firmware always skips the first 2 bytes of the buffer
+ so TCP headers will be aligned. */
+
+ iob = alloc_iob ( MXGEFW_PAD + ETH_FRAME_LEN );
+ if ( !iob ) {
+ rc = -ENOMEM;
+ dbg = "alloc_iob";
+ goto abort_with_receives_posted;
+ }
+ iob_reserve ( iob, MXGEFW_PAD );
+ myri10ge_post_receive ( priv, iob );
+ }
+
+ /* Bring up the link. */
+
+ TRY ( CMD_, ETHERNET_UP, );
+
+ DBG2_RINGS ( priv );
+ return 0;
+
+abort_with_receives_posted:
+ while ( priv->receives_posted-- )
+ free_iob ( priv->receive_iob[priv->receives_posted] );
+abort_with_dma:
+ /* Because the link is not up, we don't have to reset the NIC here. */
+ free_dma ( priv->dma, sizeof ( *priv->dma ) );
+abort_with_nothing:
+ /* Erase all signs of the failed open. */
+ memset ( priv, 0, sizeof ( *priv ) );
+ DBG ( "%s: %s\n", dbg, strerror ( rc ) );
+ return ( rc );
+}
+
+/*
+ * This function allows a driver to process events during operation.
+ *
+ * @v netdev Device being polled.
+ *
+ * This is called periodically by iPXE to let the driver check the status of
+ * transmitted packets and to allow the driver to check for received packets.
+ * This is a iPXE Network Device Driver API function.
+ */
+static void myri10ge_net_poll ( struct net_device *netdev )
+{
+ struct io_buffer *iob;
+ struct io_buffer *replacement;
+ struct myri10ge_dma_buffers *dma;
+ struct myri10ge_private *priv;
+ unsigned int length;
+ unsigned int orig_receives_posted;
+
+ DBGP ( "myri10ge_net_poll\n" );
+ priv = myri10ge_priv ( netdev );
+ dma = priv->dma;
+
+ /* Process any pending interrupt. */
+
+ myri10ge_interrupt_handler ( netdev );
+
+ /* Pass up received frames, but limit ourselves to receives posted
+ before this function was called, so we cannot livelock if
+ receives are arriving faster than we process them. */
+
+ orig_receives_posted = priv->receives_posted;
+ while ( priv->receives_done != orig_receives_posted ) {
+
+ /* Stop if there is no pending receive. */
+
+ length = ntohs ( dma->receive_completion
+ [priv->receives_done
+ & MYRI10GE_RECEIVE_COMPLETION_WRAP]
+ .length );
+ if ( length == 0 )
+ break;
+
+ /* Allocate a replacement buffer. If none is available,
+ stop passing up packets until a buffer is available.
+
+ Reserve 2 extra bytes at the start of packets, since
+ the firmware always skips the first 2 bytes of the buffer
+ so TCP headers will be aligned. */
+
+ replacement = alloc_iob ( MXGEFW_PAD + ETH_FRAME_LEN );
+ if ( !replacement ) {
+ DBG ( "NO RX BUF\n" );
+ break;
+ }
+ iob_reserve ( replacement, MXGEFW_PAD );
+
+ /* Pass up the received frame. */
+
+ iob = priv->receive_iob[priv->receives_done
+ & MYRI10GE_RECEIVE_WRAP];
+ iob_put ( iob, length );
+ netdev_rx ( netdev, iob );
+
+ /* We have consumed the packet, so clear the receive
+ notification. */
+
+ dma->receive_completion [priv->receives_done
+ & MYRI10GE_RECEIVE_COMPLETION_WRAP]
+ .length = 0;
+ wmb();
+
+ /* Replace the passed-up I/O buffer. */
+
+ myri10ge_post_receive ( priv, replacement );
+ ++priv->receives_done;
+ DBG2_RINGS ( priv );
+ }
+}
+
+/*
+ * This transmits a packet.
+ *
+ * @v netdev Device to transmit from.
+ * @v iobuf Data to transmit.
+ * @ret rc Non-zero if failed to transmit.
+ *
+ * This is a iPXE Network Driver API function.
+ */
+static int myri10ge_net_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf )
+{
+ mcp_kreq_ether_send_t *kreq;
+ size_t len;
+ struct myri10ge_private *priv;
+ uint32 transmits_posted;
+
+ DBGP ( "myri10ge_net_transmit\n" );
+ priv = myri10ge_priv ( netdev );
+
+ /* Confirm space in the send ring. */
+
+ transmits_posted = priv->transmits_posted;
+ if ( transmits_posted - priv->transmits_done
+ > MYRI10GE_TRANSMIT_WRAP ) {
+ DBG ( "TX ring full\n" );
+ return -ENOBUFS;
+ }
+
+ DBG2 ( "TX %p+%zd ", iobuf->data, iob_len ( iobuf ) );
+ DBG2_HD ( iobuf->data, 14 );
+
+ /* Record the packet being transmitted, so we can later report
+ send completion. */
+
+ priv->transmit_iob[transmits_posted & MYRI10GE_TRANSMIT_WRAP] = iobuf;
+
+ /* Copy and pad undersized frames, because the NIC does not pad,
+ and we would rather copy small frames than do a gather. */
+
+ len = iob_len ( iobuf );
+ if ( len < ETH_ZLEN ) {
+ iob_pad ( iobuf, ETH_ZLEN );
+ len = ETH_ZLEN;
+ }
+
+ /* Enqueue the packet by writing a descriptor to the NIC.
+ This is a bit tricky because the HW requires 32-bit writes,
+ but the structure has smaller fields. */
+
+ kreq = &priv->transmit_ring[transmits_posted
+ & priv->transmit_ring_wrap];
+ kreq->addr_high = 0;
+ kreq->addr_low = htonl ( virt_to_bus ( iobuf->data ) );
+ ( ( uint32 * ) kreq ) [2] = htonl (
+ 0x0000 << 16 /* pseudo_header_offset */
+ | ( len & 0xFFFF ) /* length */
+ );
+ wmb();
+ ( ( uint32 * ) kreq ) [3] = htonl (
+ 0x00 << 24 /* pad */
+ | 0x01 << 16 /* rdma_count */
+ | 0x00 << 8 /* cksum_offset */
+ | ( MXGEFW_FLAGS_SMALL
+ | MXGEFW_FLAGS_FIRST
+ | MXGEFW_FLAGS_NO_TSO ) /* flags */
+ );
+ wmb();
+
+ /* Mark the slot as consumed and return. */
+
+ priv->transmits_posted = ++transmits_posted;
+ DBG2_RINGS ( priv );
+ return 0;
+}
+
+static struct pci_device_id myri10ge_nics[] = {
+ /* Each of these macros must be a single line to satisfy a script. */
+ PCI_ROM ( 0x14c1, 0x0008, "myri10ge", "Myricom 10Gb Ethernet Adapter", 0 ) ,
+};
+
+struct pci_driver myri10ge_driver __pci_driver = {
+ .ids = myri10ge_nics,
+ .id_count = ( sizeof ( myri10ge_nics ) / sizeof ( myri10ge_nics[0] ) ) ,
+ .probe = myri10ge_pci_probe,
+ .remove = myri10ge_pci_remove
+};
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/myri10ge_mcp.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/myri10ge_mcp.h
new file mode 100644
index 00000000..391dab37
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/myri10ge_mcp.h
@@ -0,0 +1,514 @@
+/************************************************* -*- linux-c -*-
+ * Myricom 10Gb Network Interface Card Software
+ * Copyright 2005-2010, Myricom, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#ifndef _myri10ge_mcp_h
+#define _myri10ge_mcp_h
+
+#define MXGEFW_VERSION_MAJOR 1
+#define MXGEFW_VERSION_MINOR 4
+
+#ifdef MXGEFW
+#ifndef _stdint_h_
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+#endif
+#endif
+
+/* 8 Bytes */
+struct mcp_dma_addr {
+ uint32_t high;
+ uint32_t low;
+};
+typedef struct mcp_dma_addr mcp_dma_addr_t;
+
+/* 4 Bytes */
+struct mcp_slot {
+ uint16_t checksum;
+ uint16_t length;
+};
+typedef struct mcp_slot mcp_slot_t;
+
+#ifdef MXGEFW_NDIS
+/* 8-byte descriptor, exclusively used by NDIS drivers. */
+struct mcp_slot_8 {
+ /* Place hash value at the top so it gets written before length.
+ * The driver polls length.
+ */
+ uint32_t hash;
+ uint16_t checksum;
+ uint16_t length;
+};
+typedef struct mcp_slot_8 mcp_slot_8_t;
+
+/* Two bits of length in mcp_slot are used to indicate hash type. */
+#define MXGEFW_RSS_HASH_NULL (0 << 14) /* bit 15:14 = 00 */
+#define MXGEFW_RSS_HASH_IPV4 (1 << 14) /* bit 15:14 = 01 */
+#define MXGEFW_RSS_HASH_TCP_IPV4 (2 << 14) /* bit 15:14 = 10 */
+#define MXGEFW_RSS_HASH_MASK (3 << 14) /* bit 15:14 = 11 */
+#endif
+
+/* 64 Bytes */
+struct mcp_cmd {
+ uint32_t cmd;
+ uint32_t data0; /* will be low portion if data > 32 bits */
+ /* 8 */
+ uint32_t data1; /* will be high portion if data > 32 bits */
+ uint32_t data2; /* currently unused.. */
+ /* 16 */
+ struct mcp_dma_addr response_addr;
+ /* 24 */
+ uint32_t pad[10];
+};
+typedef struct mcp_cmd mcp_cmd_t;
+
+/* 8 Bytes */
+struct mcp_cmd_response {
+ uint32_t data;
+ uint32_t result;
+};
+typedef struct mcp_cmd_response mcp_cmd_response_t;
+
+
+
+/*
+ flags used in mcp_kreq_ether_send_t:
+
+ The SMALL flag is only needed in the first segment. It is raised
+ for packets that are total less or equal 512 bytes.
+
+ The CKSUM flag must be set in all segments.
+
+ The PADDED flags is set if the packet needs to be padded, and it
+ must be set for all segments.
+
+ The MXGEFW_FLAGS_ALIGN_ODD must be set if the cumulative
+ length of all previous segments was odd.
+*/
+
+
+#define MXGEFW_FLAGS_SMALL 0x1
+#define MXGEFW_FLAGS_TSO_HDR 0x1
+#define MXGEFW_FLAGS_FIRST 0x2
+#define MXGEFW_FLAGS_ALIGN_ODD 0x4
+#define MXGEFW_FLAGS_CKSUM 0x8
+#define MXGEFW_FLAGS_TSO_LAST 0x8
+#define MXGEFW_FLAGS_NO_TSO 0x10
+#define MXGEFW_FLAGS_TSO_CHOP 0x10
+#define MXGEFW_FLAGS_TSO_PLD 0x20
+
+#define MXGEFW_SEND_SMALL_SIZE 1520
+#define MXGEFW_MAX_MTU 9400
+
+union mcp_pso_or_cumlen {
+ uint16_t pseudo_hdr_offset;
+ uint16_t cum_len;
+};
+typedef union mcp_pso_or_cumlen mcp_pso_or_cumlen_t;
+
+#define MXGEFW_MAX_SEND_DESC 12
+#define MXGEFW_PAD 2
+
+/* 16 Bytes */
+struct mcp_kreq_ether_send {
+ uint32_t addr_high;
+ uint32_t addr_low;
+ uint16_t pseudo_hdr_offset;
+ uint16_t length;
+ uint8_t pad;
+ uint8_t rdma_count;
+ uint8_t cksum_offset; /* where to start computing cksum */
+ uint8_t flags; /* as defined above */
+};
+typedef struct mcp_kreq_ether_send mcp_kreq_ether_send_t;
+
+/* 8 Bytes */
+struct mcp_kreq_ether_recv {
+ uint32_t addr_high;
+ uint32_t addr_low;
+};
+typedef struct mcp_kreq_ether_recv mcp_kreq_ether_recv_t;
+
+
+/* Commands */
+
+#define MXGEFW_BOOT_HANDOFF 0xfc0000
+#define MXGEFW_BOOT_DUMMY_RDMA 0xfc01c0
+
+#define MXGEFW_ETH_CMD 0xf80000
+#define MXGEFW_ETH_SEND_4 0x200000
+#define MXGEFW_ETH_SEND_1 0x240000
+#define MXGEFW_ETH_SEND_2 0x280000
+#define MXGEFW_ETH_SEND_3 0x2c0000
+#define MXGEFW_ETH_RECV_SMALL 0x300000
+#define MXGEFW_ETH_RECV_BIG 0x340000
+#define MXGEFW_ETH_SEND_GO 0x380000
+#define MXGEFW_ETH_SEND_STOP 0x3C0000
+
+#define MXGEFW_ETH_SEND(n) (0x200000 + (((n) & 0x03) * 0x40000))
+#define MXGEFW_ETH_SEND_OFFSET(n) (MXGEFW_ETH_SEND(n) - MXGEFW_ETH_SEND_4)
+
+enum myri10ge_mcp_cmd_type {
+ MXGEFW_CMD_NONE = 0,
+ /* Reset the mcp, it is left in a safe state, waiting
+ for the driver to set all its parameters */
+ MXGEFW_CMD_RESET = 1,
+
+ /* get the version number of the current firmware..
+ (may be available in the eeprom strings..? */
+ MXGEFW_GET_MCP_VERSION = 2,
+
+
+ /* Parameters which must be set by the driver before it can
+ issue MXGEFW_CMD_ETHERNET_UP. They persist until the next
+ MXGEFW_CMD_RESET is issued */
+
+ MXGEFW_CMD_SET_INTRQ_DMA = 3,
+ /* data0 = LSW of the host address
+ * data1 = MSW of the host address
+ * data2 = slice number if multiple slices are used
+ */
+
+ MXGEFW_CMD_SET_BIG_BUFFER_SIZE = 4, /* in bytes, power of 2 */
+ MXGEFW_CMD_SET_SMALL_BUFFER_SIZE = 5, /* in bytes */
+
+
+ /* Parameters which refer to lanai SRAM addresses where the
+ driver must issue PIO writes for various things */
+
+ MXGEFW_CMD_GET_SEND_OFFSET = 6,
+ MXGEFW_CMD_GET_SMALL_RX_OFFSET = 7,
+ MXGEFW_CMD_GET_BIG_RX_OFFSET = 8,
+ /* data0 = slice number if multiple slices are used */
+
+ MXGEFW_CMD_GET_IRQ_ACK_OFFSET = 9,
+ MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET = 10,
+
+ /* Parameters which refer to rings stored on the MCP,
+ and whose size is controlled by the mcp */
+
+ MXGEFW_CMD_GET_SEND_RING_SIZE = 11, /* in bytes */
+ MXGEFW_CMD_GET_RX_RING_SIZE = 12, /* in bytes */
+
+ /* Parameters which refer to rings stored in the host,
+ and whose size is controlled by the host. Note that
+ all must be physically contiguous and must contain
+ a power of 2 number of entries. */
+
+ MXGEFW_CMD_SET_INTRQ_SIZE = 13, /* in bytes */
+#define MXGEFW_CMD_SET_INTRQ_SIZE_FLAG_NO_STRICT_SIZE_CHECK (1 << 31)
+
+ /* command to bring ethernet interface up. Above parameters
+ (plus mtu & mac address) must have been exchanged prior
+ to issuing this command */
+ MXGEFW_CMD_ETHERNET_UP = 14,
+
+ /* command to bring ethernet interface down. No further sends
+ or receives may be processed until an MXGEFW_CMD_ETHERNET_UP
+ is issued, and all interrupt queues must be flushed prior
+ to ack'ing this command */
+
+ MXGEFW_CMD_ETHERNET_DOWN = 15,
+
+ /* commands the driver may issue live, without resetting
+ the nic. Note that increasing the mtu "live" should
+ only be done if the driver has already supplied buffers
+ sufficiently large to handle the new mtu. Decreasing
+ the mtu live is safe */
+
+ MXGEFW_CMD_SET_MTU = 16,
+ MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET = 17, /* in microseconds */
+ MXGEFW_CMD_SET_STATS_INTERVAL = 18, /* in microseconds */
+ MXGEFW_CMD_SET_STATS_DMA_OBSOLETE = 19, /* replaced by SET_STATS_DMA_V2 */
+
+ MXGEFW_ENABLE_PROMISC = 20,
+ MXGEFW_DISABLE_PROMISC = 21,
+ MXGEFW_SET_MAC_ADDRESS = 22,
+
+ MXGEFW_ENABLE_FLOW_CONTROL = 23,
+ MXGEFW_DISABLE_FLOW_CONTROL = 24,
+
+ /* do a DMA test
+ data0,data1 = DMA address
+ data2 = RDMA length (MSH), WDMA length (LSH)
+ command return data = repetitions (MSH), 0.5-ms ticks (LSH)
+ */
+ MXGEFW_DMA_TEST = 25,
+
+ MXGEFW_ENABLE_ALLMULTI = 26,
+ MXGEFW_DISABLE_ALLMULTI = 27,
+
+ /* returns MXGEFW_CMD_ERROR_MULTICAST
+ if there is no room in the cache
+ data0,MSH(data1) = multicast group address */
+ MXGEFW_JOIN_MULTICAST_GROUP = 28,
+ /* returns MXGEFW_CMD_ERROR_MULTICAST
+ if the address is not in the cache,
+ or is equal to FF-FF-FF-FF-FF-FF
+ data0,MSH(data1) = multicast group address */
+ MXGEFW_LEAVE_MULTICAST_GROUP = 29,
+ MXGEFW_LEAVE_ALL_MULTICAST_GROUPS = 30,
+
+ MXGEFW_CMD_SET_STATS_DMA_V2 = 31,
+ /* data0, data1 = bus addr,
+ * data2 = sizeof(struct mcp_irq_data) from driver point of view, allows
+ * adding new stuff to mcp_irq_data without changing the ABI
+ *
+ * If multiple slices are used, data2 contains both the size of the
+ * structure (in the lower 16 bits) and the slice number
+ * (in the upper 16 bits).
+ */
+
+ MXGEFW_CMD_UNALIGNED_TEST = 32,
+ /* same than DMA_TEST (same args) but abort with UNALIGNED on unaligned
+ chipset */
+
+ MXGEFW_CMD_UNALIGNED_STATUS = 33,
+ /* return data = boolean, true if the chipset is known to be unaligned */
+
+ MXGEFW_CMD_ALWAYS_USE_N_BIG_BUFFERS = 34,
+ /* data0 = number of big buffers to use. It must be 0 or a power of 2.
+ * 0 indicates that the NIC consumes as many buffers as they are required
+ * for packet. This is the default behavior.
+ * A power of 2 number indicates that the NIC always uses the specified
+ * number of buffers for each big receive packet.
+ * It is up to the driver to ensure that this value is big enough for
+ * the NIC to be able to receive maximum-sized packets.
+ */
+
+ MXGEFW_CMD_GET_MAX_RSS_QUEUES = 35,
+ MXGEFW_CMD_ENABLE_RSS_QUEUES = 36,
+ /* data0 = number of slices n (0, 1, ..., n-1) to enable
+ * data1 = interrupt mode | use of multiple transmit queues.
+ * 0=share one INTx/MSI.
+ * 1=use one MSI-X per queue.
+ * If all queues share one interrupt, the driver must have set
+ * RSS_SHARED_INTERRUPT_DMA before enabling queues.
+ * 2=enable both receive and send queues.
+ * Without this bit set, only one send queue (slice 0's send queue)
+ * is enabled. The receive queues are always enabled.
+ */
+#define MXGEFW_SLICE_INTR_MODE_SHARED 0x0
+#define MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE 0x1
+#define MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES 0x2
+
+ MXGEFW_CMD_GET_RSS_SHARED_INTERRUPT_MASK_OFFSET = 37,
+ MXGEFW_CMD_SET_RSS_SHARED_INTERRUPT_DMA = 38,
+ /* data0, data1 = bus address lsw, msw */
+ MXGEFW_CMD_GET_RSS_TABLE_OFFSET = 39,
+ /* get the offset of the indirection table */
+ MXGEFW_CMD_SET_RSS_TABLE_SIZE = 40,
+ /* set the size of the indirection table */
+ MXGEFW_CMD_GET_RSS_KEY_OFFSET = 41,
+ /* get the offset of the secret key */
+ MXGEFW_CMD_RSS_KEY_UPDATED = 42,
+ /* tell nic that the secret key's been updated */
+ MXGEFW_CMD_SET_RSS_ENABLE = 43,
+ /* data0 = enable/disable rss
+ * 0: disable rss. nic does not distribute receive packets.
+ * 1: enable rss. nic distributes receive packets among queues.
+ * data1 = hash type
+ * 1: IPV4 (required by RSS)
+ * 2: TCP_IPV4 (required by RSS)
+ * 3: IPV4 | TCP_IPV4 (required by RSS)
+ * 4: source port
+ * 5: source port + destination port
+ */
+#define MXGEFW_RSS_HASH_TYPE_IPV4 0x1
+#define MXGEFW_RSS_HASH_TYPE_TCP_IPV4 0x2
+#define MXGEFW_RSS_HASH_TYPE_SRC_PORT 0x4
+#define MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT 0x5
+#define MXGEFW_RSS_HASH_TYPE_MAX 0x5
+
+ MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE = 44,
+ /* Return data = the max. size of the entire headers of a IPv6 TSO packet.
+ * If the header size of a IPv6 TSO packet is larger than the specified
+ * value, then the driver must not use TSO.
+ * This size restriction only applies to IPv6 TSO.
+ * For IPv4 TSO, the maximum size of the headers is fixed, and the NIC
+ * always has enough header buffer to store maximum-sized headers.
+ */
+
+ MXGEFW_CMD_SET_TSO_MODE = 45,
+ /* data0 = TSO mode.
+ * 0: Linux/FreeBSD style (NIC default)
+ * 1: NDIS/NetBSD style
+ */
+#define MXGEFW_TSO_MODE_LINUX 0
+#define MXGEFW_TSO_MODE_NDIS 1
+
+ MXGEFW_CMD_MDIO_READ = 46,
+ /* data0 = dev_addr (PMA/PMD or PCS ...), data1 = register/addr */
+ MXGEFW_CMD_MDIO_WRITE = 47,
+ /* data0 = dev_addr, data1 = register/addr, data2 = value */
+
+ MXGEFW_CMD_I2C_READ = 48,
+ /* Starts to get a fresh copy of one byte or of the module i2c table, the
+ * obtained data is cached inside the xaui-xfi chip :
+ * data0 : 0 => get one byte, 1=> get 256 bytes
+ * data1 : If data0 == 0: location to refresh
+ * bit 7:0 register location
+ * bit 8:15 is the i2c slave addr (0 is interpreted as 0xA1)
+ * bit 23:16 is the i2c bus number (for multi-port NICs)
+ * If data0 == 1: unused
+ * The operation might take ~1ms for a single byte or ~65ms when refreshing all 256 bytes
+ * During the i2c operation, MXGEFW_CMD_I2C_READ or MXGEFW_CMD_I2C_BYTE attempts
+ * will return MXGEFW_CMD_ERROR_BUSY
+ */
+ MXGEFW_CMD_I2C_BYTE = 49,
+ /* Return the last obtained copy of a given byte in the xfp i2c table
+ * (copy cached during the last relevant MXGEFW_CMD_I2C_READ)
+ * data0 : index of the desired table entry
+ * Return data = the byte stored at the requested index in the table
+ */
+
+ MXGEFW_CMD_GET_VPUMP_OFFSET = 50,
+ /* Return data = NIC memory offset of mcp_vpump_public_global */
+ MXGEFW_CMD_RESET_VPUMP = 51,
+ /* Resets the VPUMP state */
+
+ MXGEFW_CMD_SET_RSS_MCP_SLOT_TYPE = 52,
+ /* data0 = mcp_slot type to use.
+ * 0 = the default 4B mcp_slot
+ * 1 = 8B mcp_slot_8
+ */
+#define MXGEFW_RSS_MCP_SLOT_TYPE_MIN 0
+#define MXGEFW_RSS_MCP_SLOT_TYPE_WITH_HASH 1
+
+ MXGEFW_CMD_SET_THROTTLE_FACTOR = 53,
+ /* set the throttle factor for ethp_z8e
+ data0 = throttle_factor
+ throttle_factor = 256 * pcie-raw-speed / tx_speed
+ tx_speed = 256 * pcie-raw-speed / throttle_factor
+
+ For PCI-E x8: pcie-raw-speed == 16Gb/s
+ For PCI-E x4: pcie-raw-speed == 8Gb/s
+
+ ex1: throttle_factor == 0x1a0 (416), tx_speed == 1.23GB/s == 9.846 Gb/s
+ ex2: throttle_factor == 0x200 (512), tx_speed == 1.0GB/s == 8 Gb/s
+
+ with tx_boundary == 2048, max-throttle-factor == 8191 => min-speed == 500Mb/s
+ with tx_boundary == 4096, max-throttle-factor == 4095 => min-speed == 1Gb/s
+ */
+
+ MXGEFW_CMD_VPUMP_UP = 54,
+ /* Allocates VPump Connection, Send Request and Zero copy buffer address tables */
+ MXGEFW_CMD_GET_VPUMP_CLK = 55,
+ /* Get the lanai clock */
+
+ MXGEFW_CMD_GET_DCA_OFFSET = 56,
+ /* offset of dca control for WDMAs */
+
+ /* VMWare NetQueue commands */
+ MXGEFW_CMD_NETQ_GET_FILTERS_PER_QUEUE = 57,
+ MXGEFW_CMD_NETQ_ADD_FILTER = 58,
+ /* data0 = filter_id << 16 | queue << 8 | type */
+ /* data1 = MS4 of MAC Addr */
+ /* data2 = LS2_MAC << 16 | VLAN_tag */
+ MXGEFW_CMD_NETQ_DEL_FILTER = 59,
+ /* data0 = filter_id */
+ MXGEFW_CMD_NETQ_QUERY1 = 60,
+ MXGEFW_CMD_NETQ_QUERY2 = 61,
+ MXGEFW_CMD_NETQ_QUERY3 = 62,
+ MXGEFW_CMD_NETQ_QUERY4 = 63,
+
+ MXGEFW_CMD_RELAX_RXBUFFER_ALIGNMENT = 64,
+ /* When set, small receive buffers can cross page boundaries.
+ * Both small and big receive buffers may start at any address.
+ * This option has performance implications, so use with caution.
+ */
+};
+typedef enum myri10ge_mcp_cmd_type myri10ge_mcp_cmd_type_t;
+
+
+enum myri10ge_mcp_cmd_status {
+ MXGEFW_CMD_OK = 0,
+ MXGEFW_CMD_UNKNOWN = 1,
+ MXGEFW_CMD_ERROR_RANGE = 2,
+ MXGEFW_CMD_ERROR_BUSY = 3,
+ MXGEFW_CMD_ERROR_EMPTY = 4,
+ MXGEFW_CMD_ERROR_CLOSED = 5,
+ MXGEFW_CMD_ERROR_HASH_ERROR = 6,
+ MXGEFW_CMD_ERROR_BAD_PORT = 7,
+ MXGEFW_CMD_ERROR_RESOURCES = 8,
+ MXGEFW_CMD_ERROR_MULTICAST = 9,
+ MXGEFW_CMD_ERROR_UNALIGNED = 10,
+ MXGEFW_CMD_ERROR_NO_MDIO = 11,
+ MXGEFW_CMD_ERROR_I2C_FAILURE = 12,
+ MXGEFW_CMD_ERROR_I2C_ABSENT = 13,
+ MXGEFW_CMD_ERROR_BAD_PCIE_LINK = 14
+};
+typedef enum myri10ge_mcp_cmd_status myri10ge_mcp_cmd_status_t;
+
+
+#define MXGEFW_OLD_IRQ_DATA_LEN 40
+
+struct mcp_irq_data {
+ /* add new counters at the beginning */
+ uint32_t future_use[1];
+ uint32_t dropped_pause;
+ uint32_t dropped_unicast_filtered;
+ uint32_t dropped_bad_crc32;
+ uint32_t dropped_bad_phy;
+ uint32_t dropped_multicast_filtered;
+/* 40 Bytes */
+ uint32_t send_done_count;
+
+#define MXGEFW_LINK_DOWN 0
+#define MXGEFW_LINK_UP 1
+#define MXGEFW_LINK_MYRINET 2
+#define MXGEFW_LINK_UNKNOWN 3
+ uint32_t link_up;
+ uint32_t dropped_link_overflow;
+ uint32_t dropped_link_error_or_filtered;
+ uint32_t dropped_runt;
+ uint32_t dropped_overrun;
+ uint32_t dropped_no_small_buffer;
+ uint32_t dropped_no_big_buffer;
+ uint32_t rdma_tags_available;
+
+ uint8_t tx_stopped;
+ uint8_t link_down;
+ uint8_t stats_updated;
+ uint8_t valid;
+};
+typedef struct mcp_irq_data mcp_irq_data_t;
+
+#ifdef MXGEFW_NDIS
+/* Exclusively used by NDIS drivers */
+struct mcp_rss_shared_interrupt {
+ uint8_t pad[2];
+ uint8_t queue;
+ uint8_t valid;
+};
+#endif
+
+/* definitions for NETQ filter type */
+#define MXGEFW_NETQ_FILTERTYPE_NONE 0
+#define MXGEFW_NETQ_FILTERTYPE_MACADDR 1
+#define MXGEFW_NETQ_FILTERTYPE_VLAN 2
+#define MXGEFW_NETQ_FILTERTYPE_VLANMACADDR 3
+
+#endif /* _myri10ge_mcp_h */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/myson.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/myson.c
new file mode 100644
index 00000000..7b4641ea
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/myson.c
@@ -0,0 +1,677 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/pci.h>
+#include <ipxe/mii.h>
+#include "myson.h"
+
+/** @file
+ *
+ * Myson Technology network card driver
+ *
+ */
+
+/******************************************************************************
+ *
+ * Device reset
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Reset controller chip
+ *
+ * @v myson Myson device
+ * @ret rc Return status code
+ */
+static int myson_soft_reset ( struct myson_nic *myson ) {
+ uint32_t bcr;
+ unsigned int i;
+
+ /* Initiate reset */
+ bcr = readl ( myson->regs + MYSON_BCR );
+ writel ( ( bcr | MYSON_BCR_SWR ), myson->regs + MYSON_BCR );
+
+ /* Wait for reset to complete */
+ for ( i = 0 ; i < MYSON_RESET_MAX_WAIT_MS ; i++ ) {
+
+ /* If reset is not complete, delay 1ms and retry */
+ if ( readl ( myson->regs + MYSON_BCR ) & MYSON_BCR_SWR ) {
+ mdelay ( 1 );
+ continue;
+ }
+
+ /* Apply a sensible default bus configuration */
+ bcr = readl ( myson->regs + MYSON_BCR );
+ bcr &= ~MYSON_BCR_PBL_MASK;
+ bcr |= ( MYSON_BCR_RLE | MYSON_BCR_RME | MYSON_BCR_WIE |
+ MYSON_BCR_PBL_DEFAULT );
+ writel ( bcr, myson->regs + MYSON_BCR );
+ DBGC ( myson, "MYSON %p using configuration %08x\n",
+ myson, bcr );
+
+ return 0;
+ }
+
+ DBGC ( myson, "MYSON %p timed out waiting for reset\n", myson );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Reload configuration from EEPROM
+ *
+ * @v myson Myson device
+ * @ret rc Return status code
+ */
+static int myson_reload_config ( struct myson_nic *myson ) {
+ unsigned int i;
+
+ /* Initiate reload */
+ writel ( MYSON_ROM_AUTOLD, myson->regs + MYSON_ROM_MII );
+
+ /* Wait for reload to complete */
+ for ( i = 0 ; i < MYSON_AUTOLD_MAX_WAIT_MS ; i++ ) {
+
+ /* If reload is not complete, delay 1ms and retry */
+ if ( readl ( myson->regs + MYSON_ROM_MII ) & MYSON_ROM_AUTOLD ){
+ mdelay ( 1 );
+ continue;
+ }
+
+ return 0;
+ }
+
+ DBGC ( myson, "MYSON %p timed out waiting for configuration "
+ "reload\n", myson );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Reset hardware
+ *
+ * @v myson Myson device
+ * @ret rc Return status code
+ */
+static int myson_reset ( struct myson_nic *myson ) {
+ int rc;
+
+ /* Disable all interrupts */
+ writel ( 0, myson->regs + MYSON_IMR );
+
+ /* Perform soft reset */
+ if ( ( rc = myson_soft_reset ( myson ) ) != 0 )
+ return rc;
+
+ /* Reload configuration from EEPROM */
+ if ( ( rc = myson_reload_config ( myson ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/******************************************************************************
+ *
+ * Network device interface
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Create descriptor ring
+ *
+ * @v myson Myson device
+ * @v ring Descriptor ring
+ * @ret rc Return status code
+ */
+static int myson_create_ring ( struct myson_nic *myson,
+ struct myson_ring *ring ) {
+ size_t len = ( ring->count * sizeof ( ring->desc[0] ) );
+ struct myson_descriptor *desc;
+ struct myson_descriptor *next;
+ physaddr_t address;
+ unsigned int i;
+ int rc;
+
+ /* Allocate descriptor ring */
+ ring->desc = malloc_dma ( len, MYSON_RING_ALIGN );
+ if ( ! ring->desc ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ address = virt_to_bus ( ring->desc );
+
+ /* Check address is usable by card */
+ if ( ! myson_address_ok ( address + len ) ) {
+ DBGC ( myson, "MYSON %p cannot support 64-bit ring address\n",
+ myson );
+ rc = -ENOTSUP;
+ goto err_64bit;
+ }
+
+ /* Initialise descriptor ring */
+ memset ( ring->desc, 0, len );
+ for ( i = 0 ; i < ring->count ; i++ ) {
+ desc = &ring->desc[i];
+ next = &ring->desc[ ( i + 1 ) % ring->count ];
+ desc->next = cpu_to_le32 ( virt_to_bus ( next ) );
+ }
+
+ /* Program ring address */
+ writel ( address, myson->regs + ring->reg );
+ DBGC ( myson, "MYSON %p ring %02x is at [%08llx,%08llx)\n",
+ myson, ring->reg, ( ( unsigned long long ) address ),
+ ( ( unsigned long long ) address + len ) );
+
+ return 0;
+
+ err_64bit:
+ free_dma ( ring->desc, len );
+ ring->desc = NULL;
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Destroy descriptor ring
+ *
+ * @v myson Myson device
+ * @v ring Descriptor ring
+ */
+static void myson_destroy_ring ( struct myson_nic *myson,
+ struct myson_ring *ring ) {
+ size_t len = ( ring->count * sizeof ( ring->desc[0] ) );
+
+ /* Clear ring address */
+ writel ( 0, myson->regs + ring->reg );
+
+ /* Free descriptor ring */
+ free_dma ( ring->desc, len );
+ ring->desc = NULL;
+ ring->prod = 0;
+ ring->cons = 0;
+}
+
+/**
+ * Refill receive descriptor ring
+ *
+ * @v netdev Network device
+ */
+static void myson_refill_rx ( struct net_device *netdev ) {
+ struct myson_nic *myson = netdev->priv;
+ struct myson_descriptor *rx;
+ struct io_buffer *iobuf;
+ unsigned int rx_idx;
+ physaddr_t address;
+
+ while ( ( myson->rx.prod - myson->rx.cons ) < MYSON_NUM_RX_DESC ) {
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( MYSON_RX_MAX_LEN );
+ if ( ! iobuf ) {
+ /* Wait for next refill */
+ return;
+ }
+
+ /* Check address is usable by card */
+ address = virt_to_bus ( iobuf->data );
+ if ( ! myson_address_ok ( address ) ) {
+ DBGC ( myson, "MYSON %p cannot support 64-bit RX "
+ "buffer address\n", myson );
+ netdev_rx_err ( netdev, iobuf, -ENOTSUP );
+ return;
+ }
+
+ /* Get next receive descriptor */
+ rx_idx = ( myson->rx.prod++ % MYSON_NUM_RX_DESC );
+ rx = &myson->rx.desc[rx_idx];
+
+ /* Populate receive descriptor */
+ rx->address = cpu_to_le32 ( address );
+ rx->control =
+ cpu_to_le32 ( MYSON_RX_CTRL_RBS ( MYSON_RX_MAX_LEN ) );
+ wmb();
+ rx->status = cpu_to_le32 ( MYSON_RX_STAT_OWN );
+ wmb();
+
+ /* Record I/O buffer */
+ assert ( myson->rx_iobuf[rx_idx] == NULL );
+ myson->rx_iobuf[rx_idx] = iobuf;
+
+ /* Notify card that there are descriptors available */
+ writel ( 0, myson->regs + MYSON_RXPDR );
+
+ DBGC2 ( myson, "MYSON %p RX %d is [%llx,%llx)\n", myson,
+ rx_idx, ( ( unsigned long long ) address ),
+ ( ( unsigned long long ) address + MYSON_RX_MAX_LEN ) );
+ }
+}
+
+/**
+ * Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int myson_open ( struct net_device *netdev ) {
+ struct myson_nic *myson = netdev->priv;
+ union myson_physical_address mac;
+ int rc;
+
+ /* Set MAC address */
+ memset ( &mac, 0, sizeof ( mac ) );
+ memcpy ( mac.raw, netdev->ll_addr, ETH_ALEN );
+ writel ( le32_to_cpu ( mac.reg.low ), myson->regs + MYSON_PAR0 );
+ writel ( le32_to_cpu ( mac.reg.high ), myson->regs + MYSON_PAR4 );
+
+ /* Create transmit descriptor ring */
+ if ( ( rc = myson_create_ring ( myson, &myson->tx ) ) != 0 )
+ goto err_create_tx;
+
+ /* Create receive descriptor ring */
+ if ( ( rc = myson_create_ring ( myson, &myson->rx ) ) != 0 )
+ goto err_create_rx;
+
+ /* Configure transmitter and receiver */
+ writel ( ( MYSON_TCR_TE | MYSON_RCR_PROM | MYSON_RCR_AB | MYSON_RCR_AM |
+ MYSON_RCR_ARP | MYSON_RCR_ALP | MYSON_RCR_RE ),
+ myson->regs + MYSON_TCR_RCR );
+
+ /* Fill receive ring */
+ myson_refill_rx ( netdev );
+
+ return 0;
+
+ myson_destroy_ring ( myson, &myson->rx );
+ err_create_rx:
+ myson_destroy_ring ( myson, &myson->tx );
+ err_create_tx:
+ return rc;
+}
+
+/**
+ * Wait for transmit and receive to become idle
+ *
+ * @v myson Myson device
+ * @ret rc Return status code
+ */
+static int myson_wait_idle ( struct myson_nic *myson ) {
+ uint32_t tcr_rcr;
+ unsigned int i;
+
+ /* Wait for both transmit and receive to be idle */
+ for ( i = 0 ; i < MYSON_IDLE_MAX_WAIT_MS ; i++ ) {
+
+ /* If either process is running, delay 1ms and retry */
+ tcr_rcr = readl ( myson->regs + MYSON_TCR_RCR );
+ if ( tcr_rcr & ( MYSON_TCR_TXS | MYSON_RCR_RXS ) ) {
+ mdelay ( 1 );
+ continue;
+ }
+
+ return 0;
+ }
+
+ DBGC ( myson, "MYSON %p timed out waiting for idle state (status "
+ "%08x)\n", myson, tcr_rcr );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Close network device
+ *
+ * @v netdev Network device
+ */
+static void myson_close ( struct net_device *netdev ) {
+ struct myson_nic *myson = netdev->priv;
+ unsigned int i;
+
+ /* Disable receiver and transmitter */
+ writel ( 0, myson->regs + MYSON_TCR_RCR );
+
+ /* Allow time for receiver and transmitter to become idle */
+ myson_wait_idle ( myson );
+
+ /* Destroy receive descriptor ring */
+ myson_destroy_ring ( myson, &myson->rx );
+
+ /* Discard any unused receive buffers */
+ for ( i = 0 ; i < MYSON_NUM_RX_DESC ; i++ ) {
+ if ( myson->rx_iobuf[i] )
+ free_iob ( myson->rx_iobuf[i] );
+ myson->rx_iobuf[i] = NULL;
+ }
+
+ /* Destroy transmit descriptor ring */
+ myson_destroy_ring ( myson, &myson->tx );
+}
+
+/**
+ * Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int myson_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct myson_nic *myson = netdev->priv;
+ struct myson_descriptor *tx;
+ unsigned int tx_idx;
+ physaddr_t address;
+
+ /* Check address is usable by card */
+ address = virt_to_bus ( iobuf->data );
+ if ( ! myson_address_ok ( address ) ) {
+ DBGC ( myson, "MYSON %p cannot support 64-bit TX buffer "
+ "address\n", myson );
+ return -ENOTSUP;
+ }
+
+ /* Get next transmit descriptor */
+ if ( ( myson->tx.prod - myson->tx.cons ) >= MYSON_NUM_TX_DESC ) {
+ DBGC ( myson, "MYSON %p out of transmit descriptors\n",
+ myson );
+ return -ENOBUFS;
+ }
+ tx_idx = ( myson->tx.prod++ % MYSON_NUM_TX_DESC );
+ tx = &myson->tx.desc[tx_idx];
+
+ /* Populate transmit descriptor */
+ tx->address = cpu_to_le32 ( address );
+ tx->control = cpu_to_le32 ( MYSON_TX_CTRL_IC | MYSON_TX_CTRL_LD |
+ MYSON_TX_CTRL_FD | MYSON_TX_CTRL_CRC |
+ MYSON_TX_CTRL_PAD | MYSON_TX_CTRL_RTLC |
+ MYSON_TX_CTRL_PKTS ( iob_len ( iobuf ) ) |
+ MYSON_TX_CTRL_TBS ( iob_len ( iobuf ) ) );
+ wmb();
+ tx->status = cpu_to_le32 ( MYSON_TX_STAT_OWN );
+ wmb();
+
+ /* Notify card that there are packets ready to transmit */
+ writel ( 0, myson->regs + MYSON_TXPDR );
+
+ DBGC2 ( myson, "MYSON %p TX %d is [%llx,%llx)\n", myson, tx_idx,
+ ( ( unsigned long long ) address ),
+ ( ( unsigned long long ) address + iob_len ( iobuf ) ) );
+
+ return 0;
+}
+
+/**
+ * Poll for completed packets
+ *
+ * @v netdev Network device
+ */
+static void myson_poll_tx ( struct net_device *netdev ) {
+ struct myson_nic *myson = netdev->priv;
+ struct myson_descriptor *tx;
+ unsigned int tx_idx;
+
+ /* Check for completed packets */
+ while ( myson->tx.cons != myson->tx.prod ) {
+
+ /* Get next transmit descriptor */
+ tx_idx = ( myson->tx.cons % MYSON_NUM_TX_DESC );
+ tx = &myson->tx.desc[tx_idx];
+
+ /* Stop if descriptor is still in use */
+ if ( tx->status & cpu_to_le32 ( MYSON_TX_STAT_OWN ) )
+ return;
+
+ /* Complete TX descriptor */
+ if ( tx->status & cpu_to_le32 ( MYSON_TX_STAT_ABORT |
+ MYSON_TX_STAT_CSL ) ) {
+ DBGC ( myson, "MYSON %p TX %d completion error "
+ "(%08x)\n", myson, tx_idx,
+ le32_to_cpu ( tx->status ) );
+ netdev_tx_complete_next_err ( netdev, -EIO );
+ } else {
+ DBGC2 ( myson, "MYSON %p TX %d complete\n",
+ myson, tx_idx );
+ netdev_tx_complete_next ( netdev );
+ }
+ myson->tx.cons++;
+ }
+}
+
+/**
+ * Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void myson_poll_rx ( struct net_device *netdev ) {
+ struct myson_nic *myson = netdev->priv;
+ struct myson_descriptor *rx;
+ struct io_buffer *iobuf;
+ unsigned int rx_idx;
+ size_t len;
+
+ /* Check for received packets */
+ while ( myson->rx.cons != myson->rx.prod ) {
+
+ /* Get next receive descriptor */
+ rx_idx = ( myson->rx.cons % MYSON_NUM_RX_DESC );
+ rx = &myson->rx.desc[rx_idx];
+
+ /* Stop if descriptor is still in use */
+ if ( rx->status & MYSON_RX_STAT_OWN )
+ return;
+
+ /* Populate I/O buffer */
+ iobuf = myson->rx_iobuf[rx_idx];
+ myson->rx_iobuf[rx_idx] = NULL;
+ len = MYSON_RX_STAT_FLNG ( le32_to_cpu ( rx->status ) );
+ iob_put ( iobuf, len - 4 /* strip CRC */ );
+
+ /* Hand off to network stack */
+ if ( rx->status & cpu_to_le32 ( MYSON_RX_STAT_ES ) ) {
+ DBGC ( myson, "MYSON %p RX %d error (length %zd, "
+ "status %08x)\n", myson, rx_idx, len,
+ le32_to_cpu ( rx->status ) );
+ netdev_rx_err ( netdev, iobuf, -EIO );
+ } else {
+ DBGC2 ( myson, "MYSON %p RX %d complete (length "
+ "%zd)\n", myson, rx_idx, len );
+ netdev_rx ( netdev, iobuf );
+ }
+ myson->rx.cons++;
+ }
+}
+
+/**
+ * Poll for completed and received packets
+ *
+ * @v netdev Network device
+ */
+static void myson_poll ( struct net_device *netdev ) {
+ struct myson_nic *myson = netdev->priv;
+ uint32_t isr;
+ unsigned int i;
+
+ /* Polling the ISR seems to really upset this card; it ends up
+ * getting no useful PCI transfers done and, for some reason,
+ * flooding the network with invalid packets. Work around
+ * this by introducing deliberate delays between ISR reads.
+ */
+ for ( i = 0 ; i < MYSON_ISR_IODELAY_COUNT ; i++ )
+ iodelay();
+
+ /* Check for and acknowledge interrupts */
+ isr = readl ( myson->regs + MYSON_ISR );
+ if ( ! isr )
+ return;
+ writel ( isr, myson->regs + MYSON_ISR );
+
+ /* Poll for TX completions, if applicable */
+ if ( isr & MYSON_IRQ_TI )
+ myson_poll_tx ( netdev );
+
+ /* Poll for RX completionsm, if applicable */
+ if ( isr & MYSON_IRQ_RI )
+ myson_poll_rx ( netdev );
+
+ /* Refill RX ring */
+ myson_refill_rx ( netdev );
+}
+
+/**
+ * Enable or disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void myson_irq ( struct net_device *netdev, int enable ) {
+ struct myson_nic *myson = netdev->priv;
+ uint32_t imr;
+
+ imr = ( enable ? ( MYSON_IRQ_TI | MYSON_IRQ_RI ) : 0 );
+ writel ( imr, myson->regs + MYSON_IMR );
+}
+
+/** Myson network device operations */
+static struct net_device_operations myson_operations = {
+ .open = myson_open,
+ .close = myson_close,
+ .transmit = myson_transmit,
+ .poll = myson_poll,
+ .irq = myson_irq,
+};
+
+/******************************************************************************
+ *
+ * PCI interface
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @ret rc Return status code
+ */
+static int myson_probe ( struct pci_device *pci ) {
+ struct net_device *netdev;
+ struct myson_nic *myson;
+ union myson_physical_address mac;
+ int rc;
+
+ /* Allocate and initialise net device */
+ netdev = alloc_etherdev ( sizeof ( *myson ) );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ netdev_init ( netdev, &myson_operations );
+ myson = netdev->priv;
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+ memset ( myson, 0, sizeof ( *myson ) );
+ myson_init_ring ( &myson->tx, MYSON_NUM_TX_DESC, MYSON_TXLBA );
+ myson_init_ring ( &myson->rx, MYSON_NUM_RX_DESC, MYSON_RXLBA );
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* Map registers */
+ myson->regs = ioremap ( pci->membase, MYSON_BAR_SIZE );
+
+ /* Reset the NIC */
+ if ( ( rc = myson_reset ( myson ) ) != 0 )
+ goto err_reset;
+
+ /* Read MAC address */
+ mac.reg.low = cpu_to_le32 ( readl ( myson->regs + MYSON_PAR0 ) );
+ mac.reg.high = cpu_to_le32 ( readl ( myson->regs + MYSON_PAR4 ) );
+ memcpy ( netdev->hw_addr, mac.raw, ETH_ALEN );
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register_netdev;
+
+ /* Mark as link up; we don't yet handle link state */
+ netdev_link_up ( netdev );
+
+ return 0;
+
+ unregister_netdev ( netdev );
+ err_register_netdev:
+ myson_reset ( myson );
+ err_reset:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void myson_remove ( struct pci_device *pci ) {
+ struct net_device *netdev = pci_get_drvdata ( pci );
+ struct myson_nic *myson = netdev->priv;
+
+ /* Unregister network device */
+ unregister_netdev ( netdev );
+
+ /* Reset card */
+ myson_reset ( myson );
+
+ /* Free network device */
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/** Myson PCI device IDs */
+static struct pci_device_id myson_nics[] = {
+ PCI_ROM ( 0x1516, 0x0800, "mtd800", "MTD-8xx", 0 ),
+ PCI_ROM ( 0x1516, 0x0803, "mtd803", "Surecom EP-320X-S", 0 ),
+ PCI_ROM ( 0x1516, 0x0891, "mtd891", "MTD-8xx", 0 ),
+};
+
+/** Myson PCI driver */
+struct pci_driver myson_driver __pci_driver = {
+ .ids = myson_nics,
+ .id_count = ( sizeof ( myson_nics ) / sizeof ( myson_nics[0] ) ),
+ .probe = myson_probe,
+ .remove = myson_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/myson.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/myson.h
new file mode 100644
index 00000000..8d7cc585
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/myson.h
@@ -0,0 +1,200 @@
+#ifndef _MYSON_H
+#define _MYSON_H
+
+/** @file
+ *
+ * Myson Technology network card driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/if_ether.h>
+
+/** BAR size */
+#define MYSON_BAR_SIZE 256
+
+/** A packet descriptor */
+struct myson_descriptor {
+ /** Status */
+ uint32_t status;
+ /** Control */
+ uint32_t control;
+ /** Buffer start address */
+ uint32_t address;
+ /** Next descriptor address */
+ uint32_t next;
+} __attribute__ (( packed ));
+
+/* Transmit status */
+#define MYSON_TX_STAT_OWN 0x80000000UL /**< Owner */
+#define MYSON_TX_STAT_ABORT 0x00002000UL /**< Abort */
+#define MYSON_TX_STAT_CSL 0x00001000UL /**< Carrier sense lost */
+
+/* Transmit control */
+#define MYSON_TX_CTRL_IC 0x80000000UL /**< Interrupt control */
+#define MYSON_TX_CTRL_LD 0x20000000UL /**< Last descriptor */
+#define MYSON_TX_CTRL_FD 0x10000000UL /**< First descriptor */
+#define MYSON_TX_CTRL_CRC 0x08000000UL /**< CRC append */
+#define MYSON_TX_CTRL_PAD 0x04000000UL /**< Pad control */
+#define MYSON_TX_CTRL_RTLC 0x02000000UL /**< Retry late collision */
+#define MYSON_TX_CTRL_PKTS(x) ( (x) << 11 ) /**< Packet size */
+#define MYSON_TX_CTRL_TBS(x) ( (x) << 0 ) /**< Transmit buffer size */
+
+/* Receive status */
+#define MYSON_RX_STAT_OWN 0x80000000UL /**< Owner */
+#define MYSON_RX_STAT_FLNG(status) ( ( (status) >> 16 ) & 0xfff )
+#define MYSON_RX_STAT_ES 0x00000080UL /**< Error summary */
+
+/* Receive control */
+#define MYSON_RX_CTRL_RBS(x) ( (x) << 0 ) /**< Receive buffer size */
+
+/** Descriptor ring alignment */
+#define MYSON_RING_ALIGN 4
+
+/** Physical Address Register 0 */
+#define MYSON_PAR0 0x00
+
+/** Physical Address Register 4 */
+#define MYSON_PAR4 0x04
+
+/** Physical address */
+union myson_physical_address {
+ struct {
+ uint32_t low;
+ uint32_t high;
+ } __attribute__ (( packed )) reg;
+ uint8_t raw[ETH_ALEN];
+};
+
+/** Transmit and Receive Configuration Register */
+#define MYSON_TCR_RCR 0x18
+#define MYSON_TCR_TXS 0x80000000UL /**< Transmit status */
+#define MYSON_TCR_TE 0x00040000UL /**< Transmit enable */
+#define MYSON_RCR_RXS 0x00008000UL /**< Receive status */
+#define MYSON_RCR_PROM 0x00000080UL /**< Promiscuous mode */
+#define MYSON_RCR_AB 0x00000040UL /**< Accept broadcast */
+#define MYSON_RCR_AM 0x00000020UL /**< Accept multicast */
+#define MYSON_RCR_ARP 0x00000008UL /**< Accept runt packet */
+#define MYSON_RCR_ALP 0x00000004UL /**< Accept long packet */
+#define MYSON_RCR_RE 0x00000001UL /**< Receive enable */
+
+/** Maximum time to wait for transmit and receive to be idle, in milliseconds */
+#define MYSON_IDLE_MAX_WAIT_MS 100
+
+/** Bus Command Register */
+#define MYSON_BCR 0x1c
+#define MYSON_BCR_RLE 0x00000100UL /**< Read line enable */
+#define MYSON_BCR_RME 0x00000080UL /**< Read multiple enable */
+#define MYSON_BCR_WIE 0x00000040UL /**< Write and invalidate */
+#define MYSON_BCR_PBL(x) ( (x) << 3 ) /**< Burst length */
+#define MYSON_BCR_PBL_MASK MYSON_BCR_PBL ( 0x7 )
+#define MYSON_BCR_PBL_DEFAULT MYSON_BCR_PBL ( 0x6 )
+#define MYSON_BCR_SWR 0x00000001UL /**< Software reset */
+
+/** Maximum time to wait for a reset, in milliseconds */
+#define MYSON_RESET_MAX_WAIT_MS 100
+
+/** Transmit Poll Demand Register */
+#define MYSON_TXPDR 0x20
+
+/** Receive Poll Demand Register */
+#define MYSON_RXPDR 0x24
+
+/** Transmit List Base Address */
+#define MYSON_TXLBA 0x2c
+
+/** Number of transmit descriptors */
+#define MYSON_NUM_TX_DESC 4
+
+/** Receive List Base Address */
+#define MYSON_RXLBA 0x30
+
+/** Number of receive descriptors */
+#define MYSON_NUM_RX_DESC 4
+
+/** Receive buffer length */
+#define MYSON_RX_MAX_LEN ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ )
+
+/** Interrupt Status Register */
+#define MYSON_ISR 0x34
+#define MYSON_IRQ_TI 0x00000008UL /**< Transmit interrupt */
+#define MYSON_IRQ_RI 0x00000004UL /**< Receive interrupt */
+
+/** Number of I/O delays between ISR reads */
+#define MYSON_ISR_IODELAY_COUNT 4
+
+/** Interrupt Mask Register */
+#define MYSON_IMR 0x38
+
+/** Boot ROM / EEPROM / MII Management Register */
+#define MYSON_ROM_MII 0x40
+#define MYSON_ROM_AUTOLD 0x00100000UL /**< Auto load */
+
+/** Maximum time to wait for a configuration reload, in milliseconds */
+#define MYSON_AUTOLD_MAX_WAIT_MS 100
+
+/** A Myson descriptor ring */
+struct myson_ring {
+ /** Descriptors */
+ struct myson_descriptor *desc;
+ /** Producer index */
+ unsigned int prod;
+ /** Consumer index */
+ unsigned int cons;
+
+ /** Number of descriptors */
+ unsigned int count;
+ /** Descriptor start address register */
+ unsigned int reg;
+};
+
+/**
+ * Initialise descriptor ring
+ *
+ * @v ring Descriptor ring
+ * @v count Number of descriptors
+ * @v reg Descriptor base address register
+ */
+static inline __attribute__ (( always_inline)) void
+myson_init_ring ( struct myson_ring *ring, unsigned int count,
+ unsigned int reg ) {
+ ring->count = count;
+ ring->reg = reg;
+}
+
+/** A myson network card */
+struct myson_nic {
+ /** Registers */
+ void *regs;
+
+ /** Transmit descriptor ring */
+ struct myson_ring tx;
+ /** Receive descriptor ring */
+ struct myson_ring rx;
+ /** Receive I/O buffers */
+ struct io_buffer *rx_iobuf[MYSON_NUM_RX_DESC];
+};
+
+/**
+ * Check if card can access physical address
+ *
+ * @v address Physical address
+ * @v address_ok Card can access physical address
+ */
+static inline __attribute__ (( always_inline )) int
+myson_address_ok ( physaddr_t address ) {
+
+ /* In a 32-bit build, all addresses can be accessed */
+ if ( sizeof ( physaddr_t ) <= sizeof ( uint32_t ) )
+ return 1;
+
+ /* Card can access all addresses below 4GB */
+ if ( ( address & ~0xffffffffULL ) == 0 )
+ return 1;
+
+ return 0;
+}
+
+#endif /* _MYSON_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/natsemi.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/natsemi.c
new file mode 100644
index 00000000..00348191
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/natsemi.c
@@ -0,0 +1,936 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/pci.h>
+#include <ipxe/nvs.h>
+#include <ipxe/bitbash.h>
+#include <ipxe/spi_bit.h>
+#include <ipxe/threewire.h>
+#include "natsemi.h"
+
+/** @file
+ *
+ * National Semiconductor "MacPhyter" network card driver
+ *
+ * Based on the following datasheets:
+ *
+ * http://www.ti.com/lit/ds/symlink/dp83820.pdf
+ * http://www.datasheets.org.uk/indexdl/Datasheet-03/DSA0041338.pdf
+ *
+ */
+
+/******************************************************************************
+ *
+ * EEPROM interface
+ *
+ ******************************************************************************
+ */
+
+/** Pin mapping for SPI bit-bashing interface */
+static const uint8_t natsemi_eeprom_bits[] = {
+ [SPI_BIT_SCLK] = NATSEMI_MEAR_EECLK,
+ [SPI_BIT_MOSI] = NATSEMI_MEAR_EEDI,
+ [SPI_BIT_MISO] = NATSEMI_MEAR_EEDO,
+ [SPI_BIT_SS(0)] = NATSEMI_MEAR_EESEL,
+};
+
+/**
+ * Read input bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @ret zero Input is a logic 0
+ * @ret non-zero Input is a logic 1
+ */
+static int natsemi_spi_read_bit ( struct bit_basher *basher,
+ unsigned int bit_id ) {
+ struct natsemi_nic *natsemi = container_of ( basher, struct natsemi_nic,
+ spibit.basher );
+ uint32_t mask = natsemi_eeprom_bits[bit_id];
+ uint32_t reg;
+
+ DBG_DISABLE ( DBGLVL_IO );
+ reg = readl ( natsemi->regs + NATSEMI_MEAR );
+ DBG_ENABLE ( DBGLVL_IO );
+ return ( reg & mask );
+}
+
+/**
+ * Set/clear output bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @v data Value to write
+ */
+static void natsemi_spi_write_bit ( struct bit_basher *basher,
+ unsigned int bit_id, unsigned long data ) {
+ struct natsemi_nic *natsemi = container_of ( basher, struct natsemi_nic,
+ spibit.basher );
+ uint32_t mask = natsemi_eeprom_bits[bit_id];
+ uint32_t reg;
+
+ DBG_DISABLE ( DBGLVL_IO );
+ reg = readl ( natsemi->regs + NATSEMI_MEAR );
+ reg &= ~mask;
+ reg |= ( data & mask );
+ writel ( reg, natsemi->regs + NATSEMI_MEAR );
+ DBG_ENABLE ( DBGLVL_IO );
+}
+
+/** SPI bit-bashing interface */
+static struct bit_basher_operations natsemi_basher_ops = {
+ .read = natsemi_spi_read_bit,
+ .write = natsemi_spi_write_bit,
+};
+
+/**
+ * Initialise EEPROM
+ *
+ * @v natsemi National Semiconductor device
+ */
+static void natsemi_init_eeprom ( struct natsemi_nic *natsemi ) {
+
+ /* Initialise SPI bit-bashing interface */
+ natsemi->spibit.basher.op = &natsemi_basher_ops;
+ natsemi->spibit.bus.mode = SPI_MODE_THREEWIRE;
+ natsemi->spibit.endianness =
+ ( ( natsemi->flags & NATSEMI_EEPROM_LITTLE_ENDIAN ) ?
+ SPI_BIT_LITTLE_ENDIAN : SPI_BIT_BIG_ENDIAN );
+ init_spi_bit_basher ( &natsemi->spibit );
+
+ /* Initialise EEPROM device */
+ init_at93c06 ( &natsemi->eeprom, 16 );
+ natsemi->eeprom.bus = &natsemi->spibit.bus;
+}
+
+/**
+ * Get hardware address from sane EEPROM data
+ *
+ * @v natsemi National Semiconductor device
+ * @v eeprom EEPROM data
+ * @v hw_addr Hardware address to fill in
+ */
+static void natsemi_hwaddr_sane ( struct natsemi_nic *natsemi,
+ const uint16_t *eeprom, uint16_t *hw_addr ) {
+ int i;
+
+ /* Copy MAC address from EEPROM data */
+ for ( i = ( ( ETH_ALEN / 2 ) - 1 ) ; i >= 0 ; i-- )
+ *(hw_addr++) = eeprom[ NATSEMI_EEPROM_MAC_SANE + i ];
+
+ DBGC ( natsemi, "NATSEMI %p has sane EEPROM layout\n", natsemi );
+}
+
+/**
+ * Get hardware address from insane EEPROM data
+ *
+ * @v natsemi National Semiconductor device
+ * @v eeprom EEPROM data
+ * @v hw_addr Hardware address to fill in
+ */
+static void natsemi_hwaddr_insane ( struct natsemi_nic *natsemi,
+ const uint16_t *eeprom,
+ uint16_t *hw_addr ) {
+ unsigned int i;
+ unsigned int offset;
+ uint16_t word;
+
+ /* Copy MAC address from EEPROM data */
+ for ( i = 0 ; i < ( ETH_ALEN / 2 ) ; i++ ) {
+ offset = ( NATSEMI_EEPROM_MAC_INSANE + i );
+ word = ( ( le16_to_cpu ( eeprom[ offset ] ) >> 15 ) |
+ ( le16_to_cpu ( eeprom[ offset + 1 ] << 1 ) ) );
+ hw_addr[i] = cpu_to_le16 ( word );
+ }
+
+ DBGC ( natsemi, "NATSEMI %p has insane EEPROM layout\n", natsemi );
+}
+
+/**
+ * Get hardware address from EEPROM
+ *
+ * @v natsemi National Semiconductor device
+ * @v hw_addr Hardware address to fill in
+ * @ret rc Return status code
+ */
+static int natsemi_hwaddr ( struct natsemi_nic *natsemi, void *hw_addr ) {
+ uint16_t buf[NATSEMI_EEPROM_SIZE];
+ void ( * extract ) ( struct natsemi_nic *natsemi,
+ const uint16_t *eeprom, uint16_t *hw_addr );
+ int rc;
+
+ /* Read EEPROM contents */
+ if ( ( rc = nvs_read ( &natsemi->eeprom.nvs, 0, buf,
+ sizeof ( buf ) ) ) != 0 ) {
+ DBGC ( natsemi, "NATSEMI %p could not read EEPROM: %s\n",
+ natsemi, strerror ( rc ) );
+ return rc;
+ }
+ DBGC2 ( natsemi, "NATSEMI %p EEPROM contents:\n", natsemi );
+ DBGC2_HDA ( natsemi, 0, buf, sizeof ( buf ) );
+
+ /* Extract MAC address from EEPROM contents */
+ extract = ( ( natsemi->flags & NATSEMI_EEPROM_INSANE ) ?
+ natsemi_hwaddr_insane : natsemi_hwaddr_sane );
+ extract ( natsemi, buf, hw_addr );
+
+ return 0;
+}
+
+/******************************************************************************
+ *
+ * Device reset
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Reset controller chip
+ *
+ * @v natsemi National Semiconductor device
+ * @ret rc Return status code
+ */
+static int natsemi_soft_reset ( struct natsemi_nic *natsemi ) {
+ unsigned int i;
+
+ /* Initiate reset */
+ writel ( NATSEMI_CR_RST, natsemi->regs + NATSEMI_CR );
+
+ /* Wait for reset to complete */
+ for ( i = 0 ; i < NATSEMI_RESET_MAX_WAIT_MS ; i++ ) {
+
+ /* If reset is not complete, delay 1ms and retry */
+ if ( readl ( natsemi->regs + NATSEMI_CR ) & NATSEMI_CR_RST ) {
+ mdelay ( 1 );
+ continue;
+ }
+
+ return 0;
+ }
+
+ DBGC ( natsemi, "NATSEMI %p timed out waiting for reset\n", natsemi );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Reload configuration from EEPROM
+ *
+ * @v natsemi National Semiconductor device
+ * @ret rc Return status code
+ */
+static int natsemi_reload_config ( struct natsemi_nic *natsemi ) {
+ unsigned int i;
+
+ /* Initiate reload */
+ writel ( NATSEMI_PTSCR_EELOAD_EN, natsemi->regs + NATSEMI_PTSCR );
+
+ /* Wait for reload to complete */
+ for ( i = 0 ; i < NATSEMI_EELOAD_MAX_WAIT_MS ; i++ ) {
+
+ /* If reload is not complete, delay 1ms and retry */
+ if ( readl ( natsemi->regs + NATSEMI_PTSCR ) &
+ NATSEMI_PTSCR_EELOAD_EN ) {
+ mdelay ( 1 );
+ continue;
+ }
+
+ return 0;
+ }
+
+ DBGC ( natsemi, "NATSEMI %p timed out waiting for configuration "
+ "reload\n", natsemi );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Reset hardware
+ *
+ * @v natsemi National Semiconductor device
+ * @ret rc Return status code
+ */
+static int natsemi_reset ( struct natsemi_nic *natsemi ) {
+ uint32_t cfg;
+ int rc;
+
+ /* Perform soft reset */
+ if ( ( rc = natsemi_soft_reset ( natsemi ) ) != 0 )
+ return rc;
+
+ /* Reload configuration from EEPROM */
+ if ( ( rc = natsemi_reload_config ( natsemi ) ) != 0 )
+ return rc;
+
+ /* Configure 64-bit operation, if applicable */
+ cfg = readl ( natsemi->regs + NATSEMI_CFG );
+ if ( natsemi->flags & NATSEMI_64BIT ) {
+ cfg |= ( NATSEMI_CFG_M64ADDR | NATSEMI_CFG_EXTSTS_EN );
+ if ( ! ( cfg & NATSEMI_CFG_PCI64_DET ) )
+ cfg &= ~NATSEMI_CFG_DATA64_EN;
+ }
+ writel ( cfg, natsemi->regs + NATSEMI_CFG );
+
+ /* Invalidate link status cache to force an update */
+ natsemi->cfg = ~cfg;
+
+ DBGC ( natsemi, "NATSEMI %p using configuration %08x\n",
+ natsemi, cfg );
+ return 0;
+}
+
+/******************************************************************************
+ *
+ * Link state
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Check link state
+ *
+ * @v netdev Network device
+ */
+static void natsemi_check_link ( struct net_device *netdev ) {
+ struct natsemi_nic *natsemi = netdev->priv;
+ uint32_t cfg;
+
+ /* Read link status */
+ cfg = readl ( natsemi->regs + NATSEMI_CFG );
+
+ /* Do nothing unless link status has changed */
+ if ( cfg == natsemi->cfg )
+ return;
+
+ /* Set gigabit mode (if applicable) */
+ if ( natsemi->flags & NATSEMI_1000 ) {
+ cfg &= ~NATSEMI_CFG_MODE_1000;
+ if ( ! ( cfg & NATSEMI_CFG_SPDSTS1 ) )
+ cfg |= NATSEMI_CFG_MODE_1000;
+ writel ( cfg, natsemi->regs + NATSEMI_CFG );
+ }
+
+ /* Update link status */
+ natsemi->cfg = cfg;
+ DBGC ( natsemi, "NATSEMI %p link status is %08x\n", natsemi, cfg );
+
+ /* Update network device */
+ if ( cfg & NATSEMI_CFG_LNKSTS ) {
+ netdev_link_up ( netdev );
+ } else {
+ netdev_link_down ( netdev );
+ }
+}
+
+/******************************************************************************
+ *
+ * Network device interface
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Set perfect match filter address
+ *
+ * @v natsemi National Semiconductor device
+ * @v mac MAC address
+ */
+static void natsemi_pmatch ( struct natsemi_nic *natsemi, const void *mac ) {
+ const uint16_t *pmatch = mac;
+ uint32_t rfcr;
+ unsigned int rfaddr;
+ unsigned int i;
+
+ for ( i = 0 ; i < ETH_ALEN ; i += sizeof ( *pmatch ) ) {
+
+ /* Select receive filter register address */
+ rfaddr = ( NATSEMI_RFADDR_PMATCH_BASE + i );
+ rfcr = readl ( natsemi->regs + NATSEMI_RFCR );
+ rfcr &= ~NATSEMI_RFCR_RFADDR_MASK;
+ rfcr |= NATSEMI_RFCR_RFADDR ( rfaddr );
+ writel ( rfcr, natsemi->regs + NATSEMI_RFCR );
+
+ /* Write receive filter data */
+ writel ( ( le16_to_cpu ( *(pmatch++) ) | NATSEMI_RFDR_BMASK ),
+ natsemi->regs + NATSEMI_RFDR );
+ }
+}
+
+/**
+ * Create descriptor ring
+ *
+ * @v natsemi National Semiconductor device
+ * @v ring Descriptor ring
+ * @ret rc Return status code
+ */
+static int natsemi_create_ring ( struct natsemi_nic *natsemi,
+ struct natsemi_ring *ring ) {
+ size_t len = ( ring->count * sizeof ( ring->desc[0] ) );
+ union natsemi_descriptor *desc;
+ union natsemi_descriptor *linked_desc;
+ physaddr_t address;
+ physaddr_t link;
+ size_t offset;
+ unsigned int i;
+ int rc;
+
+ /* Calculate descriptor offset */
+ offset = ( ( natsemi->flags & NATSEMI_64BIT ) ? 0 :
+ offsetof ( typeof ( desc[i].d32pad ), d32 ) );
+
+ /* Allocate descriptor ring. Align ring on its own size to
+ * ensure that it can't possibly cross the boundary of 32-bit
+ * address space.
+ */
+ ring->desc = malloc_dma ( len, len );
+ if ( ! ring->desc ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ address = ( virt_to_bus ( ring->desc ) + offset );
+
+ /* Check address is usable by card */
+ if ( ! natsemi_address_ok ( natsemi, address ) ) {
+ DBGC ( natsemi, "NATSEMI %p cannot support 64-bit ring "
+ "address\n", natsemi );
+ rc = -ENOTSUP;
+ goto err_64bit;
+ }
+
+ /* Initialise descriptor ring */
+ memset ( ring->desc, 0, len );
+ for ( i = 0 ; i < ring->count ; i++ ) {
+ linked_desc = &ring->desc [ ( i + 1 ) % ring->count ];
+ link = ( virt_to_bus ( linked_desc ) + offset );
+ if ( natsemi->flags & NATSEMI_64BIT ) {
+ ring->desc[i].d64.link = cpu_to_le64 ( link );
+ } else {
+ ring->desc[i].d32pad.d32.link = cpu_to_le32 ( link );
+ }
+ }
+
+ /* Program ring address */
+ writel ( ( address & 0xffffffffUL ), natsemi->regs + ring->reg );
+ if ( natsemi->flags & NATSEMI_64BIT ) {
+ if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) {
+ writel ( ( ( ( uint64_t ) address ) >> 32 ),
+ natsemi->regs + ring->reg + 4 );
+ } else {
+ writel ( 0, natsemi->regs + ring->reg + 4 );
+ }
+ }
+
+ DBGC ( natsemi, "NATSEMI %p ring %02x is at [%08llx,%08llx)\n",
+ natsemi, ring->reg,
+ ( ( unsigned long long ) virt_to_bus ( ring->desc ) ),
+ ( ( unsigned long long ) virt_to_bus ( ring->desc ) + len ) );
+
+ return 0;
+
+ err_64bit:
+ free_dma ( ring->desc, len );
+ ring->desc = NULL;
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Destroy descriptor ring
+ *
+ * @v natsemi National Semiconductor device
+ * @v ring Descriptor ring
+ */
+static void natsemi_destroy_ring ( struct natsemi_nic *natsemi,
+ struct natsemi_ring *ring ) {
+ size_t len = ( ring->count * sizeof ( ring->desc[0] ) );
+
+ /* Clear ring address */
+ writel ( 0, natsemi->regs + ring->reg );
+ if ( natsemi->flags & NATSEMI_64BIT )
+ writel ( 0, natsemi->regs + ring->reg + 4 );
+
+ /* Free descriptor ring */
+ free_dma ( ring->desc, len );
+ ring->desc = NULL;
+ ring->prod = 0;
+ ring->cons = 0;
+}
+
+/**
+ * Refill receive descriptor ring
+ *
+ * @v netdev Network device
+ */
+static void natsemi_refill_rx ( struct net_device *netdev ) {
+ struct natsemi_nic *natsemi = netdev->priv;
+ union natsemi_descriptor *rx;
+ struct io_buffer *iobuf;
+ unsigned int rx_idx;
+ physaddr_t address;
+
+ while ( ( natsemi->rx.prod - natsemi->rx.cons ) < NATSEMI_NUM_RX_DESC ){
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( NATSEMI_RX_MAX_LEN );
+ if ( ! iobuf ) {
+ /* Wait for next refill */
+ return;
+ }
+
+ /* Check address is usable by card */
+ address = virt_to_bus ( iobuf->data );
+ if ( ! natsemi_address_ok ( natsemi, address ) ) {
+ DBGC ( natsemi, "NATSEMI %p cannot support 64-bit RX "
+ "buffer address\n", natsemi );
+ netdev_rx_err ( netdev, iobuf, -ENOTSUP );
+ return;
+ }
+
+ /* Get next receive descriptor */
+ rx_idx = ( natsemi->rx.prod++ % NATSEMI_NUM_RX_DESC );
+ rx = &natsemi->rx.desc[rx_idx];
+
+ /* Populate receive descriptor */
+ if ( natsemi->flags & NATSEMI_64BIT ) {
+ rx->d64.bufptr = cpu_to_le64 ( address );
+ } else {
+ rx->d32pad.d32.bufptr = cpu_to_le32 ( address );
+ }
+ wmb();
+ rx->common.cmdsts = cpu_to_le32 ( NATSEMI_DESC_INTR |
+ NATSEMI_RX_MAX_LEN );
+ wmb();
+
+ /* Record I/O buffer */
+ assert ( natsemi->rx_iobuf[rx_idx] == NULL );
+ natsemi->rx_iobuf[rx_idx] = iobuf;
+
+ /* Notify card that there are descriptors available */
+ writel ( NATSEMI_CR_RXE, natsemi->regs + NATSEMI_CR );
+
+ DBGC2 ( natsemi, "NATSEMI %p RX %d is [%llx,%llx)\n", natsemi,
+ rx_idx, ( ( unsigned long long ) address ),
+ ( ( unsigned long long ) address + NATSEMI_RX_MAX_LEN));
+ }
+}
+
+/**
+ * Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int natsemi_open ( struct net_device *netdev ) {
+ struct natsemi_nic *natsemi = netdev->priv;
+ int rc;
+
+ /* Set MAC address */
+ natsemi_pmatch ( natsemi, netdev->ll_addr );
+
+ /* Create transmit descriptor ring */
+ if ( ( rc = natsemi_create_ring ( natsemi, &natsemi->tx ) ) != 0 )
+ goto err_create_tx;
+
+ /* Set transmit configuration */
+ writel ( ( NATSEMI_TXCFG_CSI | NATSEMI_TXCFG_HBI | NATSEMI_TXCFG_ATP |
+ NATSEMI_TXCFG_ECRETRY | NATSEMI_TXCFG_MXDMA_DEFAULT |
+ NATSEMI_TXCFG_FLTH_DEFAULT | NATSEMI_TXCFG_DRTH_DEFAULT ),
+ ( natsemi->regs + ( ( natsemi->flags & NATSEMI_64BIT ) ?
+ NATSEMI_TXCFG_64 : NATSEMI_TXCFG_32 ) ) );
+
+ /* Create receive descriptor ring */
+ if ( ( rc = natsemi_create_ring ( natsemi, &natsemi->rx ) ) != 0 )
+ goto err_create_rx;
+
+ /* Set receive configuration */
+ writel ( ( NATSEMI_RXCFG_ARP | NATSEMI_RXCFG_ATX | NATSEMI_RXCFG_ALP |
+ NATSEMI_RXCFG_MXDMA_DEFAULT | NATSEMI_RXCFG_DRTH_DEFAULT ),
+ ( natsemi->regs + ( ( natsemi->flags & NATSEMI_64BIT ) ?
+ NATSEMI_RXCFG_64 : NATSEMI_RXCFG_32 ) ) );
+
+ /* Set receive filter configuration */
+ writel ( ( NATSEMI_RFCR_RFEN | NATSEMI_RFCR_AAB | NATSEMI_RFCR_AAM |
+ NATSEMI_RFCR_AAU ), natsemi->regs + NATSEMI_RFCR );
+
+ /* Fill receive ring */
+ natsemi_refill_rx ( netdev );
+
+ /* Unmask transmit and receive interrupts. (Interrupts will
+ * not be generated unless enabled via the IER.)
+ */
+ writel ( ( NATSEMI_IRQ_TXDESC | NATSEMI_IRQ_RXDESC ),
+ natsemi->regs + NATSEMI_IMR );
+
+ /* Update link state */
+ natsemi_check_link ( netdev );
+
+ return 0;
+
+ natsemi_destroy_ring ( natsemi, &natsemi->rx );
+ err_create_rx:
+ natsemi_destroy_ring ( natsemi, &natsemi->tx );
+ err_create_tx:
+ return rc;
+}
+
+/**
+ * Close network device
+ *
+ * @v netdev Network device
+ */
+static void natsemi_close ( struct net_device *netdev ) {
+ struct natsemi_nic *natsemi = netdev->priv;
+ unsigned int i;
+
+ /* Mask transmit and receive interrupts */
+ writel ( 0, natsemi->regs + NATSEMI_IMR );
+
+ /* Reset and disable transmitter and receiver */
+ writel ( ( NATSEMI_CR_RXR | NATSEMI_CR_TXR ),
+ natsemi->regs + NATSEMI_CR );
+
+ /* Discard any unused receive buffers */
+ for ( i = 0 ; i < NATSEMI_NUM_RX_DESC ; i++ ) {
+ if ( natsemi->rx_iobuf[i] )
+ free_iob ( natsemi->rx_iobuf[i] );
+ natsemi->rx_iobuf[i] = NULL;
+ }
+
+ /* Destroy receive descriptor ring */
+ natsemi_destroy_ring ( natsemi, &natsemi->rx );
+
+ /* Destroy transmit descriptor ring */
+ natsemi_destroy_ring ( natsemi, &natsemi->tx );
+}
+
+/**
+ * Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int natsemi_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct natsemi_nic *natsemi = netdev->priv;
+ union natsemi_descriptor *tx;
+ unsigned int tx_idx;
+ physaddr_t address;
+
+ /* Check address is usable by card */
+ address = virt_to_bus ( iobuf->data );
+ if ( ! natsemi_address_ok ( natsemi, address ) ) {
+ DBGC ( natsemi, "NATSEMI %p cannot support 64-bit TX buffer "
+ "address\n", natsemi );
+ return -ENOTSUP;
+ }
+
+ /* Get next transmit descriptor */
+ if ( ( natsemi->tx.prod - natsemi->tx.cons ) >= NATSEMI_NUM_TX_DESC ) {
+ DBGC ( natsemi, "NATSEMI %p out of transmit descriptors\n",
+ natsemi );
+ return -ENOBUFS;
+ }
+ tx_idx = ( natsemi->tx.prod++ % NATSEMI_NUM_TX_DESC );
+ tx = &natsemi->tx.desc[tx_idx];
+
+ /* Populate transmit descriptor */
+ if ( natsemi->flags & NATSEMI_64BIT ) {
+ tx->d64.bufptr = cpu_to_le64 ( address );
+ } else {
+ tx->d32pad.d32.bufptr = cpu_to_le32 ( address );
+ }
+ wmb();
+ tx->common.cmdsts = cpu_to_le32 ( NATSEMI_DESC_OWN | NATSEMI_DESC_INTR |
+ iob_len ( iobuf ) );
+ wmb();
+
+ /* Notify card that there are packets ready to transmit */
+ writel ( NATSEMI_CR_TXE, natsemi->regs + NATSEMI_CR );
+
+ DBGC2 ( natsemi, "NATSEMI %p TX %d is [%llx,%llx)\n", natsemi, tx_idx,
+ ( ( unsigned long long ) address ),
+ ( ( unsigned long long ) address + iob_len ( iobuf ) ) );
+
+ return 0;
+}
+
+/**
+ * Poll for completed packets
+ *
+ * @v netdev Network device
+ */
+static void natsemi_poll_tx ( struct net_device *netdev ) {
+ struct natsemi_nic *natsemi = netdev->priv;
+ union natsemi_descriptor *tx;
+ unsigned int tx_idx;
+
+ /* Check for completed packets */
+ while ( natsemi->tx.cons != natsemi->tx.prod ) {
+
+ /* Get next transmit descriptor */
+ tx_idx = ( natsemi->tx.cons % NATSEMI_NUM_TX_DESC );
+ tx = &natsemi->tx.desc[tx_idx];
+
+ /* Stop if descriptor is still in use */
+ if ( tx->common.cmdsts & cpu_to_le32 ( NATSEMI_DESC_OWN ) )
+ return;
+
+ /* Complete TX descriptor */
+ if ( tx->common.cmdsts & cpu_to_le32 ( NATSEMI_DESC_OK ) ) {
+ DBGC2 ( natsemi, "NATSEMI %p TX %d complete\n",
+ natsemi, tx_idx );
+ netdev_tx_complete_next ( netdev );
+ } else {
+ DBGC ( natsemi, "NATSEMI %p TX %d completion error "
+ "(%08x)\n", natsemi, tx_idx,
+ le32_to_cpu ( tx->common.cmdsts ) );
+ netdev_tx_complete_next_err ( netdev, -EIO );
+ }
+ natsemi->tx.cons++;
+ }
+}
+
+/**
+ * Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void natsemi_poll_rx ( struct net_device *netdev ) {
+ struct natsemi_nic *natsemi = netdev->priv;
+ union natsemi_descriptor *rx;
+ struct io_buffer *iobuf;
+ unsigned int rx_idx;
+ size_t len;
+
+ /* Check for received packets */
+ while ( natsemi->rx.cons != natsemi->rx.prod ) {
+
+ /* Get next receive descriptor */
+ rx_idx = ( natsemi->rx.cons % NATSEMI_NUM_RX_DESC );
+ rx = &natsemi->rx.desc[rx_idx];
+
+ /* Stop if descriptor is still in use */
+ if ( ! ( rx->common.cmdsts & NATSEMI_DESC_OWN ) )
+ return;
+
+ /* Populate I/O buffer */
+ iobuf = natsemi->rx_iobuf[rx_idx];
+ natsemi->rx_iobuf[rx_idx] = NULL;
+ len = ( le32_to_cpu ( rx->common.cmdsts ) &
+ NATSEMI_DESC_SIZE_MASK );
+ iob_put ( iobuf, len - 4 /* strip CRC */ );
+
+ /* Hand off to network stack */
+ if ( rx->common.cmdsts & cpu_to_le32 ( NATSEMI_DESC_OK ) ) {
+ DBGC2 ( natsemi, "NATSEMI %p RX %d complete (length "
+ "%zd)\n", natsemi, rx_idx, len );
+ netdev_rx ( netdev, iobuf );
+ } else {
+ DBGC ( natsemi, "NATSEMI %p RX %d error (length %zd, "
+ "status %08x)\n", natsemi, rx_idx, len,
+ le32_to_cpu ( rx->common.cmdsts ) );
+ netdev_rx_err ( netdev, iobuf, -EIO );
+ }
+ natsemi->rx.cons++;
+ }
+}
+
+/**
+ * Poll for completed and received packets
+ *
+ * @v netdev Network device
+ */
+static void natsemi_poll ( struct net_device *netdev ) {
+ struct natsemi_nic *natsemi = netdev->priv;
+ uint32_t isr;
+
+ /* Poll for link state. The PHY interrupt seems not to
+ * function as expected, and polling for the link state is
+ * only a single register read.
+ */
+ natsemi_check_link ( netdev );
+
+ /* Check for and acknowledge interrupts */
+ isr = readl ( natsemi->regs + NATSEMI_ISR );
+ if ( ! isr )
+ return;
+
+ /* Poll for TX completions, if applicable */
+ if ( isr & NATSEMI_IRQ_TXDESC )
+ natsemi_poll_tx ( netdev );
+
+ /* Poll for RX completionsm, if applicable */
+ if ( isr & NATSEMI_IRQ_RXDESC )
+ natsemi_poll_rx ( netdev );
+
+ /* Refill RX ring */
+ natsemi_refill_rx ( netdev );
+}
+
+/**
+ * Enable or disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void natsemi_irq ( struct net_device *netdev, int enable ) {
+ struct natsemi_nic *natsemi = netdev->priv;
+
+ /* Enable or disable interrupts */
+ writel ( ( enable ? NATSEMI_IER_IE : 0 ), natsemi->regs + NATSEMI_IER );
+}
+
+/** National Semiconductor network device operations */
+static struct net_device_operations natsemi_operations = {
+ .open = natsemi_open,
+ .close = natsemi_close,
+ .transmit = natsemi_transmit,
+ .poll = natsemi_poll,
+ .irq = natsemi_irq,
+};
+
+/******************************************************************************
+ *
+ * PCI interface
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @ret rc Return status code
+ */
+static int natsemi_probe ( struct pci_device *pci ) {
+ struct net_device *netdev;
+ struct natsemi_nic *natsemi;
+ int rc;
+
+ /* Allocate and initialise net device */
+ netdev = alloc_etherdev ( sizeof ( *natsemi ) );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ netdev_init ( netdev, &natsemi_operations );
+ natsemi = netdev->priv;
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+ memset ( natsemi, 0, sizeof ( *natsemi ) );
+ natsemi->flags = pci->id->driver_data;
+ natsemi_init_ring ( &natsemi->tx, NATSEMI_NUM_TX_DESC, NATSEMI_TXDP );
+ natsemi_init_ring ( &natsemi->rx, NATSEMI_NUM_RX_DESC, NATSEMI_RXDP );
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* Map registers */
+ natsemi->regs = ioremap ( pci->membase, NATSEMI_BAR_SIZE );
+
+ /* Reset the NIC */
+ if ( ( rc = natsemi_reset ( natsemi ) ) != 0 )
+ goto err_reset;
+
+ /* Initialise EEPROM */
+ natsemi_init_eeprom ( natsemi );
+
+ /* Read initial MAC address */
+ if ( ( rc = natsemi_hwaddr ( natsemi, netdev->hw_addr ) ) != 0 )
+ goto err_hwaddr;
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register_netdev;
+
+ /* Set initial link state */
+ natsemi_check_link ( netdev );
+
+ return 0;
+
+ unregister_netdev ( netdev );
+ err_register_netdev:
+ err_hwaddr:
+ natsemi_reset ( natsemi );
+ err_reset:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void natsemi_remove ( struct pci_device *pci ) {
+ struct net_device *netdev = pci_get_drvdata ( pci );
+ struct natsemi_nic *natsemi = netdev->priv;
+
+ /* Unregister network device */
+ unregister_netdev ( netdev );
+
+ /* Reset card */
+ natsemi_reset ( natsemi );
+
+ /* Free network device */
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/** Flags for DP83815 */
+#define DP83815_FLAGS ( NATSEMI_EEPROM_LITTLE_ENDIAN | NATSEMI_EEPROM_INSANE )
+
+/** Flags for DP83820 */
+#define DP83820_FLAGS ( NATSEMI_64BIT | NATSEMI_1000 )
+
+/** National Semiconductor PCI device IDs */
+static struct pci_device_id natsemi_nics[] = {
+ PCI_ROM ( 0x100b, 0x0020, "dp83815", "DP83815", DP83815_FLAGS ),
+ PCI_ROM ( 0x100b, 0x0022, "dp83820", "DP83820", DP83820_FLAGS ),
+};
+
+/** National Semiconductor PCI driver */
+struct pci_driver natsemi_driver __pci_driver = {
+ .ids = natsemi_nics,
+ .id_count = ( sizeof ( natsemi_nics ) / sizeof ( natsemi_nics[0] ) ),
+ .probe = natsemi_probe,
+ .remove = natsemi_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/natsemi.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/natsemi.h
new file mode 100644
index 00000000..7e8d6f80
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/natsemi.h
@@ -0,0 +1,329 @@
+#ifndef _NATSEMI_H
+#define _NATSEMI_H
+
+/** @file
+ *
+ * National Semiconductor "MacPhyter" network card driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/spi.h>
+#include <ipxe/spi_bit.h>
+
+/** BAR size */
+#define NATSEMI_BAR_SIZE 0x100
+
+/** A 32-bit packet descriptor */
+struct natsemi_descriptor_32 {
+ /** Link to next descriptor */
+ uint32_t link;
+ /** Command / status */
+ uint32_t cmdsts;
+ /** Buffer pointer */
+ uint32_t bufptr;
+} __attribute__ (( packed ));
+
+/** A 64-bit packet descriptor */
+struct natsemi_descriptor_64 {
+ /** Link to next descriptor */
+ uint64_t link;
+ /** Buffer pointer */
+ uint64_t bufptr;
+ /** Command / status */
+ uint32_t cmdsts;
+ /** Extended status */
+ uint32_t extsts;
+} __attribute__ (( packed ));
+
+/** A packet descriptor
+ *
+ * The 32-bit and 64-bit variants are overlaid such that "cmdsts" can
+ * be accessed as a common field, and the overall size is a power of
+ * two (to allow the descriptor ring length to be used as an
+ * alignment).
+ */
+union natsemi_descriptor {
+ /** Common fields */
+ struct {
+ /** Reserved */
+ uint8_t reserved_a[16];
+ /** Command / status */
+ uint32_t cmdsts;
+ /** Reserved */
+ uint8_t reserved_b[12];
+ } __attribute__ (( packed )) common;
+ /** 64-bit descriptor */
+ struct natsemi_descriptor_64 d64;
+ /** 32-bit descriptor */
+ struct {
+ /** Reserved */
+ uint8_t reserved[12];
+ /** Descriptor */
+ struct natsemi_descriptor_32 d32;
+ } __attribute__ (( packed )) d32pad;
+};
+
+/** Descriptor buffer size mask */
+#define NATSEMI_DESC_SIZE_MASK 0xfff
+
+/** Packet descriptor flags */
+enum natsemi_descriptor_flags {
+ /** Descriptor is owned by NIC */
+ NATSEMI_DESC_OWN = 0x80000000UL,
+ /** Request descriptor interrupt */
+ NATSEMI_DESC_INTR = 0x20000000UL,
+ /** Packet OK */
+ NATSEMI_DESC_OK = 0x08000000UL,
+};
+
+/** Command Register */
+#define NATSEMI_CR 0x0000
+#define NATSEMI_CR_RST 0x00000100UL /**< Reset */
+#define NATSEMI_CR_RXR 0x00000020UL /**< Receiver reset */
+#define NATSEMI_CR_TXR 0x00000010UL /**< Transmit reset */
+#define NATSEMI_CR_RXE 0x00000004UL /**< Receiver enable */
+#define NATSEMI_CR_TXE 0x00000001UL /**< Transmit enable */
+
+/** Maximum time to wait for a reset, in milliseconds */
+#define NATSEMI_RESET_MAX_WAIT_MS 100
+
+/** Configuration and Media Status Register */
+#define NATSEMI_CFG 0x0004
+#define NATSEMI_CFG_LNKSTS 0x80000000UL /**< Link status */
+#define NATSEMI_CFG_SPDSTS1 0x40000000UL /**< Speed status bit 1 */
+#define NATSEMI_CFG_MODE_1000 0x00400000UL /**< 1000 Mb/s mode control */
+#define NATSEMI_CFG_PCI64_DET 0x00002000UL /**< PCI 64-bit bus detected */
+#define NATSEMI_CFG_DATA64_EN 0x00001000UL /**< 64-bit data enable */
+#define NATSEMI_CFG_M64ADDR 0x00000800UL /**< 64-bit address enable */
+#define NATSEMI_CFG_EXTSTS_EN 0x00000100UL /**< Extended status enable */
+
+/** EEPROM Access Register */
+#define NATSEMI_MEAR 0x0008
+#define NATSEMI_MEAR_EESEL 0x00000008UL /**< EEPROM chip select */
+#define NATSEMI_MEAR_EECLK 0x00000004UL /**< EEPROM serial clock */
+#define NATSEMI_MEAR_EEDO 0x00000002UL /**< EEPROM data out */
+#define NATSEMI_MEAR_EEDI 0x00000001UL /**< EEPROM data in */
+
+/** Size of EEPROM (in bytes) */
+#define NATSEMI_EEPROM_SIZE 32
+
+/** Word offset of MAC address within sane EEPROM layout */
+#define NATSEMI_EEPROM_MAC_SANE 0x0a
+
+/** Word offset of MAC address within insane EEPROM layout */
+#define NATSEMI_EEPROM_MAC_INSANE 0x06
+
+/** PCI Test Control Register */
+#define NATSEMI_PTSCR 0x000c
+#define NATSEMI_PTSCR_EELOAD_EN 0x00000004UL /**< Enable EEPROM load */
+
+/** Maximum time to wait for a configuration reload, in milliseconds */
+#define NATSEMI_EELOAD_MAX_WAIT_MS 100
+
+/** Interrupt Status Register */
+#define NATSEMI_ISR 0x0010
+#define NATSEMI_IRQ_TXDESC 0x00000080UL /**< TX descriptor */
+#define NATSEMI_IRQ_RXDESC 0x00000002UL /**< RX descriptor */
+
+/** Interrupt Mask Register */
+#define NATSEMI_IMR 0x0014
+
+/** Interrupt Enable Register */
+#define NATSEMI_IER 0x0018
+#define NATSEMI_IER_IE 0x00000001UL /**< Interrupt enable */
+
+/** Transmit Descriptor Pointer */
+#define NATSEMI_TXDP 0x0020
+
+/** Transmit Descriptor Pointer High Dword (64-bit) */
+#define NATSEMI_TXDP_HI_64 0x0024
+
+/** Number of transmit descriptors */
+#define NATSEMI_NUM_TX_DESC 4
+
+/** Transmit configuration register (32-bit) */
+#define NATSEMI_TXCFG_32 0x24
+
+/** Transmit configuration register (64-bit) */
+#define NATSEMI_TXCFG_64 0x28
+#define NATSEMI_TXCFG_CSI 0x80000000UL /**< Carrier sense ignore */
+#define NATSEMI_TXCFG_HBI 0x40000000UL /**< Heartbeat ignore */
+#define NATSEMI_TXCFG_ATP 0x10000000UL /**< Automatic padding */
+#define NATSEMI_TXCFG_ECRETRY 0x00800000UL /**< Excess collision retry */
+#define NATSEMI_TXCFG_MXDMA(x) ( (x) << 20 ) /**< Max DMA burst size */
+#define NATSEMI_TXCFG_FLTH(x) ( (x) << 8 ) /**< Fill threshold */
+#define NATSEMI_TXCFG_DRTH(x) ( (x) << 0 ) /**< Drain threshold */
+
+/** Max DMA burst size (encoded value)
+ *
+ * This represents 256-byte bursts on 83815 controllers and 512-byte
+ * bursts on 83820 controllers.
+ */
+#define NATSEMI_TXCFG_MXDMA_DEFAULT NATSEMI_TXCFG_MXDMA ( 0x7 )
+
+/** Fill threshold (in units of 32 bytes)
+ *
+ * Must be at least as large as the max DMA burst size, so use a value
+ * of 512 bytes.
+ */
+#define NATSEMI_TXCFG_FLTH_DEFAULT NATSEMI_TXCFG_FLTH ( 512 / 32 )
+
+/** Drain threshold (in units of 32 bytes)
+ *
+ * Start transmission once we receive a conservative 1024 bytes, to
+ * avoid FIFO underrun errors. (83815 does not allow us to specify a
+ * value of 0 for "wait until whole packet is present".)
+ *
+ * Fill threshold plus drain threshold must be less than the transmit
+ * FIFO size, which is 2kB on 83815 and 8kB on 83820.
+ */
+#define NATSEMI_TXCFG_DRTH_DEFAULT NATSEMI_TXCFG_DRTH ( 1024 / 32 )
+
+/** Receive Descriptor Pointer */
+#define NATSEMI_RXDP 0x0030
+
+/** Receive Descriptor Pointer High Dword (64-bit) */
+#define NATSEMI_RXDP_HI_64 0x0034
+
+/** Number of receive descriptors */
+#define NATSEMI_NUM_RX_DESC 4
+
+/** Receive buffer length */
+#define NATSEMI_RX_MAX_LEN ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ )
+
+/** Receive configuration register (32-bit) */
+#define NATSEMI_RXCFG_32 0x34
+
+/** Receive configuration register (64-bit) */
+#define NATSEMI_RXCFG_64 0x38
+#define NATSEMI_RXCFG_ARP 0x40000000UL /**< Accept runt packets */
+#define NATSEMI_RXCFG_ATX 0x10000000UL /**< Accept transmit packets */
+#define NATSEMI_RXCFG_ALP 0x08000000UL /**< Accept long packets */
+#define NATSEMI_RXCFG_MXDMA(x) ( (x) << 20 ) /**< Max DMA burst size */
+#define NATSEMI_RXCFG_DRTH(x) ( (x) << 1 ) /**< Drain threshold */
+
+/** Max DMA burst size (encoded value)
+ *
+ * This represents 256-byte bursts on 83815 controllers and 512-byte
+ * bursts on 83820 controllers.
+ */
+#define NATSEMI_RXCFG_MXDMA_DEFAULT NATSEMI_RXCFG_MXDMA ( 0x7 )
+
+/** Drain threshold (in units of 8 bytes)
+ *
+ * Start draining after 64 bytes.
+ *
+ * Must be large enough to allow packet's accept/reject status to be
+ * determined before draining begins.
+ */
+#define NATSEMI_RXCFG_DRTH_DEFAULT NATSEMI_RXCFG_DRTH ( 64 / 8 )
+
+/** Receive Filter/Match Control Register */
+#define NATSEMI_RFCR 0x0048
+#define NATSEMI_RFCR_RFEN 0x80000000UL /**< RX filter enable */
+#define NATSEMI_RFCR_AAB 0x40000000UL /**< Accept all broadcast */
+#define NATSEMI_RFCR_AAM 0x20000000UL /**< Accept all multicast */
+#define NATSEMI_RFCR_AAU 0x10000000UL /**< Accept all unicast */
+#define NATSEMI_RFCR_RFADDR( addr ) ( (addr) << 0 ) /**< Extended address */
+#define NATSEMI_RFCR_RFADDR_MASK NATSEMI_RFCR_RFADDR ( 0x3ff )
+
+/** Perfect match filter address base */
+#define NATSEMI_RFADDR_PMATCH_BASE 0x000
+
+/** Receive Filter/Match Data Register */
+#define NATSEMI_RFDR 0x004c
+#define NATSEMI_RFDR_BMASK 0x00030000UL /**< Byte mask */
+#define NATSEMI_RFDR_DATA( value ) ( (value) & 0xffff ) /**< Filter data */
+
+/** National Semiconductor network card flags */
+enum natsemi_nic_flags {
+ /** EEPROM is little-endian */
+ NATSEMI_EEPROM_LITTLE_ENDIAN = 0x0001,
+ /** EEPROM layout is insane */
+ NATSEMI_EEPROM_INSANE = 0x0002,
+ /** Card supports 64-bit operation */
+ NATSEMI_64BIT = 0x0004,
+ /** Card supports 1000Mbps link */
+ NATSEMI_1000 = 0x0008,
+};
+
+/** A National Semiconductor descriptor ring */
+struct natsemi_ring {
+ /** Descriptors */
+ union natsemi_descriptor *desc;
+ /** Producer index */
+ unsigned int prod;
+ /** Consumer index */
+ unsigned int cons;
+
+ /** Number of descriptors */
+ unsigned int count;
+ /** Descriptor start address register */
+ unsigned int reg;
+};
+
+/**
+ * Initialise descriptor ring
+ *
+ * @v ring Descriptor ring
+ * @v count Number of descriptors
+ * @v reg Descriptor start address register
+ */
+static inline __attribute__ (( always_inline)) void
+natsemi_init_ring ( struct natsemi_ring *ring, unsigned int count,
+ unsigned int reg ) {
+ ring->count = count;
+ ring->reg = reg;
+}
+
+/** A National Semiconductor network card */
+struct natsemi_nic {
+ /** Flags */
+ unsigned int flags;
+ /** Registers */
+ void *regs;
+ /** SPI bit-bashing interface */
+ struct spi_bit_basher spibit;
+ /** EEPROM */
+ struct spi_device eeprom;
+
+ /** Transmit descriptor ring */
+ struct natsemi_ring tx;
+ /** Receive descriptor ring */
+ struct natsemi_ring rx;
+ /** Receive I/O buffers */
+ struct io_buffer *rx_iobuf[NATSEMI_NUM_RX_DESC];
+
+ /** Link status (cache) */
+ uint32_t cfg;
+};
+
+/**
+ * Check if card can access physical address
+ *
+ * @v natsemi National Semiconductor device
+ * @v address Physical address
+ * @v address_ok Card can access physical address
+ */
+static inline __attribute__ (( always_inline )) int
+natsemi_address_ok ( struct natsemi_nic *natsemi, physaddr_t address ) {
+
+ /* In a 32-bit build, all addresses can be accessed */
+ if ( sizeof ( physaddr_t ) <= sizeof ( uint32_t ) )
+ return 1;
+
+ /* A 64-bit card can access all addresses */
+ if ( natsemi->flags & NATSEMI_64BIT )
+ return 1;
+
+ /* A 32-bit card can access all addresses below 4GB */
+ if ( ( address & ~0xffffffffULL ) == 0 )
+ return 1;
+
+ return 0;
+}
+
+#endif /* _NATSEMI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ne.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ne.c
new file mode 100644
index 00000000..50347de9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ne.c
@@ -0,0 +1,6 @@
+/* ISA I/O mapped NS8390-based cards, including NE2000 */
+#if 0 /* Currently broken! */
+#define INCLUDE_NE 1
+#define NE_SCAN 0x300,0x280,0x320,0x340,0x380
+#include "ns8390.c"
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ne2k_isa.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ne2k_isa.c
new file mode 100644
index 00000000..a923fd3c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ne2k_isa.c
@@ -0,0 +1,375 @@
+/**************************************************************************
+ ETHERBOOT - BOOTP/TFTP Bootstrap Program
+
+ Author: Martin Renters
+ Date: May/94
+
+ This code is based heavily on David Greenman's if_ed.c driver
+
+ Copyright (C) 1993-1994, David Greenman, Martin Renters.
+ This software may be used, modified, copied, distributed, and sold, in
+ both source and binary form provided that the above copyright and these
+ terms are retained. Under no circumstances are the authors responsible for
+ the proper functioning of this software, nor do the authors assume any
+ responsibility for damages incurred with its use.
+
+ Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003
+ Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/02
+ Card Detect support adapted from the eCos driver (Christian Plessl <cplessl@ee.ethz.ch>)
+ Extracted from ns8390.c and adapted by Pantelis Koukousoulas <pktoss@gmail.com>
+ **************************************************************************/
+
+FILE_LICENCE ( BSD2 );
+
+#include "ns8390.h"
+#include "etherboot.h"
+#include "nic.h"
+#include <ipxe/ethernet.h>
+#include <ipxe/isa.h>
+#include <errno.h>
+
+#define ASIC_PIO NE_DATA
+
+static unsigned char eth_vendor, eth_flags;
+static unsigned short eth_nic_base, eth_asic_base;
+static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
+static Address eth_bmem, eth_rmem;
+static unsigned char eth_drain_receiver;
+
+static struct nic_operations ne_operations;
+static void ne_reset(struct nic *nic, struct isa_device *isa);
+
+static isa_probe_addr_t ne_probe_addrs[] = { 0x300, 0x280, 0x320, 0x340, 0x380, 0x220, };
+
+/**************************************************************************
+ ETH_PIO_READ - Read a frame via Programmed I/O
+ **************************************************************************/
+static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt) {
+ outb(D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+ outb(cnt, eth_nic_base + D8390_P0_RBCR0);
+ outb(cnt >> 8, eth_nic_base + D8390_P0_RBCR1);
+ outb(src, eth_nic_base + D8390_P0_RSAR0);
+ outb(src >> 8, eth_nic_base + D8390_P0_RSAR1);
+ outb(D8390_COMMAND_RD0 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+ if (eth_flags & FLAG_16BIT)
+ cnt = (cnt + 1) >> 1;
+
+ while (cnt--) {
+ if (eth_flags & FLAG_16BIT) {
+ *((unsigned short *) dst) = inw(eth_asic_base + ASIC_PIO);
+ dst += 2;
+ } else
+ *(dst++) = inb(eth_asic_base + ASIC_PIO);
+ }
+}
+
+/**************************************************************************
+ ETH_PIO_WRITE - Write a frame via Programmed I/O
+ **************************************************************************/
+static void eth_pio_write(const unsigned char *src, unsigned int dst,
+ unsigned int cnt) {
+ outb(D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+ outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
+ outb(cnt, eth_nic_base + D8390_P0_RBCR0);
+ outb(cnt >> 8, eth_nic_base + D8390_P0_RBCR1);
+ outb(dst, eth_nic_base + D8390_P0_RSAR0);
+ outb(dst >> 8, eth_nic_base + D8390_P0_RSAR1);
+ outb(D8390_COMMAND_RD1 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+ if (eth_flags & FLAG_16BIT)
+ cnt = (cnt + 1) >> 1;
+
+ while (cnt--) {
+
+ if (eth_flags & FLAG_16BIT) {
+ outw(*((unsigned short *) src), eth_asic_base + ASIC_PIO);
+ src += 2;
+ } else
+ outb(*(src++), eth_asic_base + ASIC_PIO);
+ }
+}
+
+/**************************************************************************
+ enable_multicast - Enable Multicast
+ **************************************************************************/
+static void enable_multicast(unsigned short eth_nic_base) {
+ unsigned char mcfilter[8];
+ int i;
+
+ memset(mcfilter, 0xFF, 8);
+ outb(4, eth_nic_base + D8390_P0_RCR);
+ outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND);
+ for (i = 0; i < 8; i++) {
+ outb(mcfilter[i], eth_nic_base + 8 + i);
+ if (inb(eth_nic_base + 8 + i) != mcfilter[i])
+ DBG("Error SMC 83C690 Multicast filter read/write mishap %d\n",
+ i);
+ }
+ outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND);
+ outb(4 | 0x08, eth_nic_base + D8390_P0_RCR);
+}
+
+/**************************************************************************
+ NE_PROBE1 - Look for an adapter on the ISA bus
+ **************************************************************************/
+static int ne_probe1(isa_probe_addr_t ioaddr) {
+ //From the eCos driver
+ unsigned int regd;
+ unsigned int state;
+
+ state = inb(ioaddr);
+ outb(ioaddr, D8390_COMMAND_RD2 | D8390_COMMAND_PS1 | D8390_COMMAND_STP);
+ regd = inb(ioaddr + D8390_P0_TCR);
+
+ if (inb(ioaddr + D8390_P0_TCR)) {
+ outb(ioaddr, state);
+ outb(ioaddr + 0x0d, regd);
+ return 0;
+ }
+
+ return 1;
+}
+
+/**************************************************************************
+ NE_PROBE - Initialize an adapter ???
+ **************************************************************************/
+static int ne_probe(struct nic *nic, struct isa_device *isa) {
+ int i;
+ unsigned char c;
+ unsigned char romdata[16];
+ unsigned char testbuf[32];
+
+ eth_vendor = VENDOR_NONE;
+ eth_drain_receiver = 0;
+
+ nic->irqno = 0;
+ nic->ioaddr = isa->ioaddr;
+ eth_nic_base = isa->ioaddr;
+
+ /******************************************************************
+ Search for NE1000/2000 if no WD/SMC or 3com cards
+ ******************************************************************/
+ if (eth_vendor == VENDOR_NONE) {
+
+ static unsigned char test[] = "NE*000 memory";
+
+ eth_bmem = 0; /* No shared memory */
+
+ eth_flags = FLAG_PIO;
+ eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
+ eth_memsize = MEM_16384;
+ eth_tx_start = 32;
+ eth_rx_start = 32 + D8390_TXBUF_SIZE;
+ c = inb(eth_asic_base + NE_RESET);
+ outb(c, eth_asic_base + NE_RESET);
+ (void) inb(0x84);
+ outb(D8390_COMMAND_STP | D8390_COMMAND_RD2, eth_nic_base
+ + D8390_P0_COMMAND);
+ outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
+ outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
+ outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
+ outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
+ eth_pio_write((unsigned char *) test, 8192, sizeof(test));
+ eth_pio_read(8192, testbuf, sizeof(test));
+ if (!memcmp(test, testbuf, sizeof(test)))
+ goto out;
+ eth_flags |= FLAG_16BIT;
+ eth_memsize = MEM_32768;
+ eth_tx_start = 64;
+ eth_rx_start = 64 + D8390_TXBUF_SIZE;
+ outb(D8390_DCR_WTS | D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base
+ + D8390_P0_DCR);
+ outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
+ outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
+ eth_pio_write((unsigned char *) test, 16384, sizeof(test));
+ eth_pio_read(16384, testbuf, sizeof(test));
+ if (!memcmp(testbuf, test, sizeof(test)))
+ goto out;
+
+
+out:
+ if (eth_nic_base == 0)
+ return (0);
+ if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
+ eth_flags |= FLAG_16BIT;
+ eth_vendor = VENDOR_NOVELL;
+ eth_pio_read(0, romdata, sizeof(romdata));
+ for (i = 0; i < ETH_ALEN; i++) {
+ nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
+ }
+ nic->ioaddr = eth_nic_base;
+ DBG("\nNE%c000 base %4.4x, MAC Addr %s\n",
+ (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base, eth_ntoa(
+ nic->node_addr));
+ }
+
+ if (eth_vendor == VENDOR_NONE)
+ return (0);
+
+ if (eth_vendor != VENDOR_3COM)
+ eth_rmem = eth_bmem;
+
+ ne_reset(nic, isa);
+ nic->nic_op = &ne_operations;
+ return 1;
+}
+
+
+/**************************************************************************
+ NE_DISABLE - Turn off adapter
+ **************************************************************************/
+static void ne_disable(struct nic *nic, struct isa_device *isa) {
+ ne_reset(nic, isa);
+}
+
+
+/**************************************************************************
+ NE_RESET - Reset adapter
+ **************************************************************************/
+static void ne_reset(struct nic *nic, struct isa_device *isa __unused)
+{
+ int i;
+
+ eth_drain_receiver = 0;
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
+ D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+ if (eth_flags & FLAG_16BIT)
+ outb(0x49, eth_nic_base+D8390_P0_DCR);
+ else
+ outb(0x48, eth_nic_base+D8390_P0_DCR);
+ outb(0, eth_nic_base+D8390_P0_RBCR0);
+ outb(0, eth_nic_base+D8390_P0_RBCR1);
+ outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */
+ outb(2, eth_nic_base+D8390_P0_TCR);
+ outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
+ outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
+
+ outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
+ outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
+ outb(0xFF, eth_nic_base+D8390_P0_ISR);
+ outb(0, eth_nic_base+D8390_P0_IMR);
+ outb(D8390_COMMAND_PS1 |
+ D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+
+ for (i=0; i<ETH_ALEN; i++)
+ outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
+ for (i=0; i<ETH_ALEN; i++)
+ outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
+ outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ outb(0xFF, eth_nic_base+D8390_P0_ISR);
+ outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */
+ outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */
+
+ enable_multicast(eth_nic_base);
+}
+
+
+/**************************************************************************
+ NE_POLL - Wait for a frame
+ **************************************************************************/
+static int ne_poll(struct nic *nic __unused, int retrieve __unused)
+{
+ int ret = 0;
+ unsigned char rstat, curr, next;
+ unsigned short len, frag;
+ unsigned short pktoff;
+ unsigned char *p;
+ struct ringbuffer pkthdr;
+
+ rstat = inb(eth_nic_base+D8390_P0_RSR);
+ if (!(rstat & D8390_RSTAT_PRX)) return(0);
+ next = inb(eth_nic_base+D8390_P0_BOUND)+1;
+ if (next >= eth_memsize) next = eth_rx_start;
+ outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
+ curr = inb(eth_nic_base+D8390_P1_CURR);
+ outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
+ if (curr >= eth_memsize) curr=eth_rx_start;
+ if (curr == next) return(0);
+
+ if ( ! retrieve ) return 1;
+
+ pktoff = next << 8;
+ if (eth_flags & FLAG_PIO)
+ eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4);
+ else
+ memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
+ pktoff += sizeof(pkthdr);
+ /* incoming length includes FCS so must sub 4 */
+ len = pkthdr.len - 4;
+ if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
+ || len> ETH_FRAME_LEN) {
+ DBG("Bogus packet, ignoring\n");
+ return (0);
+ }
+ else {
+ p = nic->packet;
+ nic->packetlen = len; /* available to caller */
+ frag = (eth_memsize << 8) - pktoff;
+ if (len> frag) { /* We have a wrap-around */
+ /* read first part */
+ if (eth_flags & FLAG_PIO)
+ eth_pio_read(pktoff, p, frag);
+ else
+ memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
+ pktoff = eth_rx_start << 8;
+ p += frag;
+ len -= frag;
+ }
+ /* read second part */
+ if (eth_flags & FLAG_PIO)
+ eth_pio_read(pktoff, p, len);
+ else
+ memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
+ ret = 1;
+ }
+ next = pkthdr.next; /* frame number of next packet */
+ if (next == eth_rx_start)
+ next = eth_memsize;
+ outb(next-1, eth_nic_base+D8390_P0_BOUND);
+ return(ret);
+}
+
+
+/**************************************************************************
+ NE_TRANSMIT - Transmit a frame
+ **************************************************************************/
+static void ne_transmit(struct nic *nic, const char *d, /* Destination */
+unsigned int t, /* Type */
+unsigned int s, /* size */
+const char *p) { /* Packet */
+
+ /* Programmed I/O */
+ unsigned short type;
+ type = (t >> 8) | (t << 8);
+ eth_pio_write((unsigned char *) d, eth_tx_start << 8, ETH_ALEN);
+ eth_pio_write(nic->node_addr, (eth_tx_start << 8) + ETH_ALEN, ETH_ALEN);
+ /* bcc generates worse code without (const+const) below */
+ eth_pio_write((unsigned char *) &type, (eth_tx_start << 8) + (ETH_ALEN
+ + ETH_ALEN), 2);
+ eth_pio_write((unsigned char *) p, (eth_tx_start << 8) + ETH_HLEN, s);
+ s += ETH_HLEN;
+ if (s < ETH_ZLEN)
+ s = ETH_ZLEN;
+
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | D8390_COMMAND_STA,
+ eth_nic_base + D8390_P0_COMMAND);
+ outb(eth_tx_start, eth_nic_base + D8390_P0_TPSR);
+ outb(s, eth_nic_base + D8390_P0_TBCR0);
+ outb(s >> 8, eth_nic_base + D8390_P0_TBCR1);
+
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_TXP | D8390_COMMAND_RD2
+ | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+}
+
+static struct nic_operations ne_operations = { .connect = dummy_connect,
+ .poll = ne_poll, .transmit = ne_transmit, .irq = dummy_irq,
+};
+
+ISA_DRIVER ( ne_driver, ne_probe_addrs, ne_probe1,
+ GENERIC_ISAPNP_VENDOR, 0x0600 );
+
+DRIVER ( "ne", nic_driver, isapnp_driver, ne_driver,
+ ne_probe, ne_disable );
+
+ISA_ROM("ne","NE1000/2000 and clones");
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ns8390.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/ns8390.c
new file mode 100644
index 00000000..a30f9361
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ns8390.c
@@ -0,0 +1,1037 @@
+/**************************************************************************
+ETHERBOOT - BOOTP/TFTP Bootstrap Program
+
+Author: Martin Renters
+ Date: May/94
+
+ This code is based heavily on David Greenman's if_ed.c driver
+
+ Copyright (C) 1993-1994, David Greenman, Martin Renters.
+ This software may be used, modified, copied, distributed, and sold, in
+ both source and binary form provided that the above copyright and these
+ terms are retained. Under no circumstances are the authors responsible for
+ the proper functioning of this software, nor do the authors assume any
+ responsibility for damages incurred with its use.
+
+Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003
+Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/02
+3c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94
+SMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/94
+3c503 PIO support added by Jim Hague (jim.hague@acm.org) on 2/17/98
+RX overrun by Klaus Espenlaub (espenlaub@informatik.uni-ulm.de) on 3/10/99
+ parts taken from the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
+SMC8416 PIO support added by Andrew Bettison (andrewb@zip.com.au) on 4/3/02
+ based on the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
+
+**************************************************************************/
+
+FILE_LICENCE ( BSD2 );
+
+/* #warning "ns8390.c: FIXME: split ISA and PCI, clean up" */
+
+#if 1
+
+#if !defined(INCLUDE_NS8390) && !defined(INCLUDE_WD) && \
+ !defined(INCLUDE_NE) && !defined(INCLUDE_3C503)
+ /* The driver named ns8390 is the PCI driver, often called
+ "PCI ne2000 clones". */
+# define INCLUDE_NS8390 1
+#endif
+
+#include "etherboot.h"
+#include "nic.h"
+#include "ns8390.h"
+#include <ipxe/ethernet.h>
+#ifdef INCLUDE_NS8390
+#include <ipxe/pci.h>
+#else
+#include <ipxe/isa.h>
+#endif
+
+static unsigned char eth_vendor, eth_flags;
+#ifdef INCLUDE_WD
+static unsigned char eth_laar;
+#endif
+static unsigned short eth_nic_base, eth_asic_base;
+static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
+static Address eth_bmem, eth_rmem;
+static unsigned char eth_drain_receiver;
+
+#ifdef INCLUDE_WD
+static struct wd_board {
+ const char *name;
+ char id;
+ char flags;
+ char memsize;
+} wd_boards[] = {
+ {"WD8003S", TYPE_WD8003S, 0, MEM_8192},
+ {"WD8003E", TYPE_WD8003E, 0, MEM_8192},
+ {"WD8013EBT", TYPE_WD8013EBT, FLAG_16BIT, MEM_16384},
+ {"WD8003W", TYPE_WD8003W, 0, MEM_8192},
+ {"WD8003EB", TYPE_WD8003EB, 0, MEM_8192},
+ {"WD8013W", TYPE_WD8013W, FLAG_16BIT, MEM_16384},
+ {"WD8003EP/WD8013EP",
+ TYPE_WD8013EP, 0, MEM_8192},
+ {"WD8013WC", TYPE_WD8013WC, FLAG_16BIT, MEM_16384},
+ {"WD8013EPC", TYPE_WD8013EPC, FLAG_16BIT, MEM_16384},
+ {"SMC8216T", TYPE_SMC8216T, FLAG_16BIT | FLAG_790, MEM_16384},
+ {"SMC8216C", TYPE_SMC8216C, FLAG_16BIT | FLAG_790, MEM_16384},
+ {"SMC8416T", TYPE_SMC8416T, FLAG_16BIT | FLAG_790, MEM_8192},
+ {"SMC8416C/BT", TYPE_SMC8416C, FLAG_16BIT | FLAG_790, MEM_8192},
+ {"SMC8013EBP", TYPE_SMC8013EBP,FLAG_16BIT, MEM_16384},
+ {NULL, 0, 0, 0}
+};
+#endif
+
+#ifdef INCLUDE_3C503
+static unsigned char t503_output; /* AUI or internal xcvr (Thinnet) */
+#endif
+
+#if defined(INCLUDE_WD)
+#define ASIC_PIO WD_IAR
+#define eth_probe wd_probe
+#if defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
+Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
+#endif
+#endif
+
+#if defined(INCLUDE_3C503)
+#define eth_probe t503_probe
+#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)
+Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
+#endif
+#endif
+
+#if defined(INCLUDE_NE)
+#define eth_probe ne_probe
+#if defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
+Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
+#endif
+#endif
+
+#if defined(INCLUDE_NS8390)
+#define eth_probe nepci_probe
+#if defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
+Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
+#endif
+#endif
+
+#if defined(INCLUDE_3C503)
+#define ASIC_PIO _3COM_RFMSB
+#else
+#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
+#define ASIC_PIO NE_DATA
+#endif
+#endif
+
+#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
+/**************************************************************************
+ETH_PIO_READ - Read a frame via Programmed I/O
+**************************************************************************/
+static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
+{
+#ifdef INCLUDE_WD
+ outb(src & 0xff, eth_asic_base + WD_GP2);
+ outb(src >> 8, eth_asic_base + WD_GP2);
+#else
+ outb(D8390_COMMAND_RD2 |
+ D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+ outb(cnt, eth_nic_base + D8390_P0_RBCR0);
+ outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
+ outb(src, eth_nic_base + D8390_P0_RSAR0);
+ outb(src>>8, eth_nic_base + D8390_P0_RSAR1);
+ outb(D8390_COMMAND_RD0 |
+ D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+
+#ifdef INCLUDE_3C503
+ outb(src & 0xff, eth_asic_base + _3COM_DALSB);
+ outb(src >> 8, eth_asic_base + _3COM_DAMSB);
+ outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);
+#endif
+#endif
+
+ if (eth_flags & FLAG_16BIT)
+ cnt = (cnt + 1) >> 1;
+
+ while(cnt--) {
+#ifdef INCLUDE_3C503
+ while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
+ ;
+#endif
+
+ if (eth_flags & FLAG_16BIT) {
+ *((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO);
+ dst += 2;
+ }
+ else
+ *(dst++) = inb(eth_asic_base + ASIC_PIO);
+ }
+
+#ifdef INCLUDE_3C503
+ outb(t503_output, eth_asic_base + _3COM_CR);
+#endif
+}
+
+/**************************************************************************
+ETH_PIO_WRITE - Write a frame via Programmed I/O
+**************************************************************************/
+static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
+{
+#ifdef COMPEX_RL2000_FIX
+ unsigned int x;
+#endif /* COMPEX_RL2000_FIX */
+#ifdef INCLUDE_WD
+ outb(dst & 0xff, eth_asic_base + WD_GP2);
+ outb(dst >> 8, eth_asic_base + WD_GP2);
+#else
+ outb(D8390_COMMAND_RD2 |
+ D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+ outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
+ outb(cnt, eth_nic_base + D8390_P0_RBCR0);
+ outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
+ outb(dst, eth_nic_base + D8390_P0_RSAR0);
+ outb(dst>>8, eth_nic_base + D8390_P0_RSAR1);
+ outb(D8390_COMMAND_RD1 |
+ D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+
+#ifdef INCLUDE_3C503
+ outb(dst & 0xff, eth_asic_base + _3COM_DALSB);
+ outb(dst >> 8, eth_asic_base + _3COM_DAMSB);
+
+ outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR);
+#endif
+#endif
+
+ if (eth_flags & FLAG_16BIT)
+ cnt = (cnt + 1) >> 1;
+
+ while(cnt--)
+ {
+#ifdef INCLUDE_3C503
+ while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
+ ;
+#endif
+
+ if (eth_flags & FLAG_16BIT) {
+ outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO);
+ src += 2;
+ }
+ else
+ outb(*(src++), eth_asic_base + ASIC_PIO);
+ }
+
+#ifdef INCLUDE_3C503
+ outb(t503_output, eth_asic_base + _3COM_CR);
+#else
+#ifdef COMPEX_RL2000_FIX
+ for (x = 0;
+ x < COMPEX_RL2000_TRIES &&
+ (inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
+ != D8390_ISR_RDC;
+ ++x);
+ if (x >= COMPEX_RL2000_TRIES)
+ printf("Warning: Compex RL2000 aborted wait!\n");
+#endif /* COMPEX_RL2000_FIX */
+#ifndef INCLUDE_WD
+ while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
+ != D8390_ISR_RDC);
+#endif
+#endif
+}
+#else
+/**************************************************************************
+ETH_PIO_READ - Dummy routine when NE2000 not compiled in
+**************************************************************************/
+static void eth_pio_read(unsigned int src __unused, unsigned char *dst __unused, unsigned int cnt __unused) {}
+#endif
+
+
+/**************************************************************************
+enable_multycast - Enable Multicast
+**************************************************************************/
+static void enable_multicast(unsigned short eth_nic_base)
+{
+ unsigned char mcfilter[8];
+ int i;
+ memset(mcfilter, 0xFF, 8);
+ outb(4, eth_nic_base+D8390_P0_RCR);
+ outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND);
+ for(i=0;i<8;i++)
+ {
+ outb(mcfilter[i], eth_nic_base + 8 + i);
+ if(inb(eth_nic_base + 8 + i)!=mcfilter[i])
+ printf("Error SMC 83C690 Multicast filter read/write mishap %d\n",i);
+ }
+ outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND);
+ outb(4 | 0x08, eth_nic_base+D8390_P0_RCR);
+}
+
+/**************************************************************************
+NS8390_RESET - Reset adapter
+**************************************************************************/
+static void ns8390_reset(struct nic *nic)
+{
+ int i;
+
+ eth_drain_receiver = 0;
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
+ D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+ if (eth_flags & FLAG_16BIT)
+ outb(0x49, eth_nic_base+D8390_P0_DCR);
+ else
+ outb(0x48, eth_nic_base+D8390_P0_DCR);
+ outb(0, eth_nic_base+D8390_P0_RBCR0);
+ outb(0, eth_nic_base+D8390_P0_RBCR1);
+ outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */
+ outb(2, eth_nic_base+D8390_P0_TCR);
+ outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
+ outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790) {
+#ifdef WD_790_PIO
+ outb(0x10, eth_asic_base + 0x06); /* disable interrupts, enable PIO */
+ outb(0x01, eth_nic_base + 0x09); /* enable ring read auto-wrap */
+#else
+ outb(0, eth_nic_base + 0x09);
+#endif
+ }
+#endif
+ outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
+ outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
+ outb(0xFF, eth_nic_base+D8390_P0_ISR);
+ outb(0, eth_nic_base+D8390_P0_IMR);
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS1 |
+ D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS1 |
+ D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+ for (i=0; i<ETH_ALEN; i++)
+ outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
+ for (i=0; i<ETH_ALEN; i++)
+ outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
+ outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ outb(0xFF, eth_nic_base+D8390_P0_ISR);
+ outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */
+ outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */
+
+ enable_multicast(eth_nic_base);
+
+#ifdef INCLUDE_3C503
+ /*
+ * No way to tell whether or not we're supposed to use
+ * the 3Com's transceiver unless the user tells us.
+ * 'flags' should have some compile time default value
+ * which can be changed from the command menu.
+ */
+ t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL;
+ outb(t503_output, eth_asic_base + _3COM_CR);
+#endif
+}
+
+static int ns8390_poll(struct nic *nic, int retrieve);
+
+#ifndef INCLUDE_3C503
+/**************************************************************************
+ETH_RX_OVERRUN - Bring adapter back to work after an RX overrun
+**************************************************************************/
+static void eth_rx_overrun(struct nic *nic)
+{
+ int start_time;
+
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
+ D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+
+ /* wait for at least 1.6ms - we wait one timer tick */
+ start_time = currticks();
+ while (currticks() - start_time <= 1)
+ /* Nothing */;
+
+ outb(0, eth_nic_base+D8390_P0_RBCR0); /* reset byte counter */
+ outb(0, eth_nic_base+D8390_P0_RBCR1);
+
+ /*
+ * Linux driver checks for interrupted TX here. This is not necessary,
+ * because the transmit routine waits until the frame is sent.
+ */
+
+ /* enter loopback mode and restart NIC */
+ outb(2, eth_nic_base+D8390_P0_TCR);
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
+ D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+
+ /* clear the RX ring, acknowledge overrun interrupt */
+ eth_drain_receiver = 1;
+ while (ns8390_poll(nic, 1))
+ /* Nothing */;
+ eth_drain_receiver = 0;
+ outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR);
+
+ /* leave loopback mode - no packets to be resent (see Linux driver) */
+ outb(0, eth_nic_base+D8390_P0_TCR);
+}
+#endif /* INCLUDE_3C503 */
+
+/**************************************************************************
+NS8390_TRANSMIT - Transmit a frame
+**************************************************************************/
+static void ns8390_transmit(
+ struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+#if defined(INCLUDE_3C503) || (defined(INCLUDE_WD) && ! defined(WD_790_PIO))
+ Address eth_vmem = bus_to_virt(eth_bmem);
+#endif
+#ifdef INCLUDE_3C503
+ if (!(eth_flags & FLAG_PIO)) {
+ memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
+ memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
+ *((char *)eth_vmem+12) = t>>8; /* type */
+ *((char *)eth_vmem+13) = t;
+ memcpy((char *)eth_vmem+ETH_HLEN, p, s);
+ s += ETH_HLEN;
+ while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
+ }
+#endif
+
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_16BIT) {
+ outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
+ inb(0x84);
+ }
+#ifndef WD_790_PIO
+ /* Memory interface */
+ if (eth_flags & FLAG_790) {
+ outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
+ inb(0x84);
+ }
+ inb(0x84);
+ memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
+ memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
+ *((char *)eth_vmem+12) = t>>8; /* type */
+ *((char *)eth_vmem+13) = t;
+ memcpy((char *)eth_vmem+ETH_HLEN, p, s);
+ s += ETH_HLEN;
+ while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
+ if (eth_flags & FLAG_790) {
+ outb(0, eth_asic_base + WD_MSR);
+ inb(0x84);
+ }
+#else
+ inb(0x84);
+#endif
+#endif
+
+#if defined(INCLUDE_3C503)
+ if (eth_flags & FLAG_PIO)
+#endif
+#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
+ {
+ /* Programmed I/O */
+ unsigned short type;
+ type = (t >> 8) | (t << 8);
+ eth_pio_write( (unsigned char *) d, eth_tx_start<<8, ETH_ALEN);
+ eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN);
+ /* bcc generates worse code without (const+const) below */
+ eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);
+ eth_pio_write( (unsigned char *) p, (eth_tx_start<<8)+ETH_HLEN, s);
+ s += ETH_HLEN;
+ if (s < ETH_ZLEN) s = ETH_ZLEN;
+ }
+#endif
+#if defined(INCLUDE_3C503)
+#endif
+
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_16BIT) {
+ outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
+ inb(0x84);
+ }
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
+ outb(s, eth_nic_base+D8390_P0_TBCR0);
+ outb(s>>8, eth_nic_base+D8390_P0_TBCR1);
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_TXP | D8390_COMMAND_RD2 |
+ D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+}
+
+/**************************************************************************
+NS8390_POLL - Wait for a frame
+**************************************************************************/
+static int ns8390_poll(struct nic *nic, int retrieve)
+{
+ int ret = 0;
+ unsigned char rstat, curr, next;
+ unsigned short len, frag;
+ unsigned short pktoff;
+ unsigned char *p;
+ struct ringbuffer pkthdr;
+
+#ifndef INCLUDE_3C503
+ /* avoid infinite recursion: see eth_rx_overrun() */
+ if (!eth_drain_receiver && (inb(eth_nic_base+D8390_P0_ISR) & D8390_ISR_OVW)) {
+ eth_rx_overrun(nic);
+ return(0);
+ }
+#endif /* INCLUDE_3C503 */
+ rstat = inb(eth_nic_base+D8390_P0_RSR);
+ if (!(rstat & D8390_RSTAT_PRX)) return(0);
+ next = inb(eth_nic_base+D8390_P0_BOUND)+1;
+ if (next >= eth_memsize) next = eth_rx_start;
+ outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
+ curr = inb(eth_nic_base+D8390_P1_CURR);
+ outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
+ if (curr >= eth_memsize) curr=eth_rx_start;
+ if (curr == next) return(0);
+
+ if ( ! retrieve ) return 1;
+
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_16BIT) {
+ outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
+ inb(0x84);
+ }
+#ifndef WD_790_PIO
+ if (eth_flags & FLAG_790) {
+ outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
+ inb(0x84);
+ }
+#endif
+ inb(0x84);
+#endif
+ pktoff = next << 8;
+ if (eth_flags & FLAG_PIO)
+ eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4);
+ else
+ memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
+ pktoff += sizeof(pkthdr);
+ /* incoming length includes FCS so must sub 4 */
+ len = pkthdr.len - 4;
+ if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
+ || len > ETH_FRAME_LEN) {
+ printf("Bogus packet, ignoring\n");
+ return (0);
+ }
+ else {
+ p = nic->packet;
+ nic->packetlen = len; /* available to caller */
+ frag = (eth_memsize << 8) - pktoff;
+ if (len > frag) { /* We have a wrap-around */
+ /* read first part */
+ if (eth_flags & FLAG_PIO)
+ eth_pio_read(pktoff, p, frag);
+ else
+ memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
+ pktoff = eth_rx_start << 8;
+ p += frag;
+ len -= frag;
+ }
+ /* read second part */
+ if (eth_flags & FLAG_PIO)
+ eth_pio_read(pktoff, p, len);
+ else
+ memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
+ ret = 1;
+ }
+#ifdef INCLUDE_WD
+#ifndef WD_790_PIO
+ if (eth_flags & FLAG_790) {
+ outb(0, eth_asic_base + WD_MSR);
+ inb(0x84);
+ }
+#endif
+ if (eth_flags & FLAG_16BIT) {
+ outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
+ inb(0x84);
+ }
+ inb(0x84);
+#endif
+ next = pkthdr.next; /* frame number of next packet */
+ if (next == eth_rx_start)
+ next = eth_memsize;
+ outb(next-1, eth_nic_base+D8390_P0_BOUND);
+ return(ret);
+}
+
+/**************************************************************************
+NS8390_DISABLE - Turn off adapter
+**************************************************************************/
+static void ns8390_disable ( struct nic *nic ) {
+ ns8390_reset(nic);
+}
+
+/**************************************************************************
+NS8390_IRQ - Enable, Disable, or Force interrupts
+**************************************************************************/
+static void ns8390_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations ns8390_operations;
+static struct nic_operations ns8390_operations = {
+ .connect = dummy_connect,
+ .poll = ns8390_poll,
+ .transmit = ns8390_transmit,
+ .irq = ns8390_irq,
+};
+
+/**************************************************************************
+ETH_PROBE - Look for an adapter
+**************************************************************************/
+#ifdef INCLUDE_NS8390
+static int eth_probe (struct nic *nic, struct pci_device *pci)
+#else
+static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused)
+#endif
+{
+ int i;
+#ifdef INCLUDE_NS8390
+ unsigned short pci_probe_addrs[] = { pci->ioaddr, 0 };
+ unsigned short *probe_addrs = pci_probe_addrs;
+#endif
+ eth_vendor = VENDOR_NONE;
+ eth_drain_receiver = 0;
+
+ nic->irqno = 0;
+
+#ifdef INCLUDE_WD
+{
+ /******************************************************************
+ Search for WD/SMC cards
+ ******************************************************************/
+ struct wd_board *brd;
+ unsigned short chksum;
+ unsigned char c;
+ for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE;
+ eth_asic_base += 0x20) {
+ chksum = 0;
+ for (i=8; i<16; i++)
+ chksum += inb(eth_asic_base+i);
+ /* Extra checks to avoid soundcard */
+ if ((chksum & 0xFF) == 0xFF &&
+ inb(eth_asic_base+8) != 0xFF &&
+ inb(eth_asic_base+9) != 0xFF)
+ break;
+ }
+ if (eth_asic_base > WD_HIGH_BASE)
+ return (0);
+ /* We've found a board */
+ eth_vendor = VENDOR_WD;
+ eth_nic_base = eth_asic_base + WD_NIC_ADDR;
+
+ nic->ioaddr = eth_nic_base;
+
+ c = inb(eth_asic_base+WD_BID); /* Get board id */
+ for (brd = wd_boards; brd->name; brd++)
+ if (brd->id == c) break;
+ if (!brd->name) {
+ printf("Unknown WD/SMC NIC type %hhX\n", c);
+ return (0); /* Unknown type */
+ }
+ eth_flags = brd->flags;
+ eth_memsize = brd->memsize;
+ eth_tx_start = 0;
+ eth_rx_start = D8390_TXBUF_SIZE;
+ if ((c == TYPE_WD8013EP) &&
+ (inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) {
+ eth_flags = FLAG_16BIT;
+ eth_memsize = MEM_16384;
+ }
+ if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
+ eth_bmem = (0x80000 |
+ ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
+ } else
+ eth_bmem = WD_DEFAULT_MEM;
+ if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
+ /* from Linux driver, 8416BT detects as 8216 sometimes */
+ unsigned int addr = inb(eth_asic_base + 0xb);
+ if (((addr >> 4) & 3) == 0) {
+ brd += 2;
+ eth_memsize = brd->memsize;
+ }
+ }
+ outb(0x80, eth_asic_base + WD_MSR); /* Reset */
+ for (i=0; i<ETH_ALEN; i++) {
+ nic->node_addr[i] = inb(i+eth_asic_base+WD_LAR);
+ }
+ DBG ( "\n%s base %4.4x", brd->name, eth_asic_base );
+ if (eth_flags & FLAG_790) {
+#ifdef WD_790_PIO
+ DBG ( ", PIO mode, addr %s\n", eth_ntoa ( nic->node_addr ) );
+ eth_bmem = 0;
+ eth_flags |= FLAG_PIO; /* force PIO mode */
+ outb(0, eth_asic_base+WD_MSR);
+#else
+ DBG ( ", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
+
+ outb(WD_MSR_MENB, eth_asic_base+WD_MSR);
+ outb((inb(eth_asic_base+0x04) |
+ 0x80), eth_asic_base+0x04);
+ outb(((unsigned)(eth_bmem >> 13) & 0x0F) |
+ ((unsigned)(eth_bmem >> 11) & 0x40) |
+ (inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
+ outb((inb(eth_asic_base+0x04) &
+ ~0x80), eth_asic_base+0x04);
+#endif
+ } else {
+
+ DBG (", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
+
+ outb(((unsigned)(eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR);
+ }
+ if (eth_flags & FLAG_16BIT) {
+ if (eth_flags & FLAG_790) {
+ eth_laar = inb(eth_asic_base + WD_LAAR);
+ outb(WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
+ } else {
+ outb((eth_laar =
+ WD_LAAR_L16EN | 1), eth_asic_base + WD_LAAR);
+/*
+ The previous line used to be
+ WD_LAAR_M16EN | WD_LAAR_L16EN | 1));
+ jluke@deakin.edu.au reported that removing WD_LAAR_M16EN made
+ it work for WD8013s. This seems to work for my 8013 boards. I
+ don't know what is really happening. I wish I had data sheets
+ or more time to decode the Linux driver. - Ken
+*/
+ }
+ inb(0x84);
+ }
+}
+#endif
+#ifdef INCLUDE_3C503
+#ifdef T503_AUI
+ nic->flags = 1; /* aui */
+#else
+ nic->flags = 0; /* no aui */
+#endif
+ /******************************************************************
+ Search for 3Com 3c503 if no WD/SMC cards
+ ******************************************************************/
+ if (eth_vendor == VENDOR_NONE) {
+ int idx;
+ int iobase_reg, membase_reg;
+ static unsigned short base[] = {
+ 0x300, 0x310, 0x330, 0x350,
+ 0x250, 0x280, 0x2A0, 0x2E0, 0 };
+
+ /* Loop through possible addresses checking each one */
+
+ for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) {
+
+ eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET;
+/*
+ * Note that we use the same settings for both 8 and 16 bit cards:
+ * both have an 8K bank of memory at page 1 while only the 16 bit
+ * cards have a bank at page 0.
+ */
+ eth_memsize = MEM_16384;
+ eth_tx_start = 32;
+ eth_rx_start = 32 + D8390_TXBUF_SIZE;
+
+ /* Check our base address. iobase and membase should */
+ /* both have a maximum of 1 bit set or be 0. */
+
+ iobase_reg = inb(eth_asic_base + _3COM_BCFR);
+ membase_reg = inb(eth_asic_base + _3COM_PCFR);
+
+ if ((iobase_reg & (iobase_reg - 1)) ||
+ (membase_reg & (membase_reg - 1)))
+ continue; /* nope */
+
+ /* Now get the shared memory address */
+
+ eth_flags = 0;
+
+ switch (membase_reg) {
+ case _3COM_PCFR_DC000:
+ eth_bmem = 0xdc000;
+ break;
+ case _3COM_PCFR_D8000:
+ eth_bmem = 0xd8000;
+ break;
+ case _3COM_PCFR_CC000:
+ eth_bmem = 0xcc000;
+ break;
+ case _3COM_PCFR_C8000:
+ eth_bmem = 0xc8000;
+ break;
+ case _3COM_PCFR_PIO:
+ eth_flags |= FLAG_PIO;
+ eth_bmem = 0;
+ break;
+ default:
+ continue; /* nope */
+ }
+ break;
+ }
+
+ if (base[idx] == 0) /* not found */
+ return (0);
+#ifndef T503_SHMEM
+ eth_flags |= FLAG_PIO; /* force PIO mode */
+ eth_bmem = 0;
+#endif
+ eth_vendor = VENDOR_3COM;
+
+
+ /* Need this to make ns8390_poll() happy. */
+
+ eth_rmem = eth_bmem - 0x2000;
+
+ /* Reset NIC and ASIC */
+
+ outb(_3COM_CR_RST | _3COM_CR_XSEL, eth_asic_base + _3COM_CR );
+ outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR );
+
+ /* Get our ethernet address */
+
+ outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR);
+ nic->ioaddr = eth_nic_base;
+ DBG ( "\n3Com 3c503 base %4.4x, ", eth_nic_base );
+ if (eth_flags & FLAG_PIO)
+ DBG ( "PIO mode" );
+ else
+ DBG ( "memory %4.4x", eth_bmem );
+ for (i=0; i<ETH_ALEN; i++) {
+ nic->node_addr[i] = inb(eth_nic_base+i);
+ }
+ DBG ( ", %s, MAC Addr %s\n", nic->flags ? "AUI" : "internal xcvr",
+ eth_ntoa ( nic->node_addr ) );
+
+ outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR);
+ /*
+ * Initialize GA configuration register. Set bank and enable shared
+ * mem. We always use bank 1. Disable interrupts.
+ */
+ outb(_3COM_GACFR_RSEL |
+ _3COM_GACFR_MBS0 | _3COM_GACFR_TCM | _3COM_GACFR_NIM, eth_asic_base + _3COM_GACFR);
+
+ outb(0xff, eth_asic_base + _3COM_VPTR2);
+ outb(0xff, eth_asic_base + _3COM_VPTR1);
+ outb(0x00, eth_asic_base + _3COM_VPTR0);
+ /*
+ * Clear memory and verify that it worked (we use only 8K)
+ */
+
+ if (!(eth_flags & FLAG_PIO)) {
+ memset(bus_to_virt(eth_bmem), 0, 0x2000);
+ for(i = 0; i < 0x2000; ++i)
+ if (*((char *)(bus_to_virt(eth_bmem+i)))) {
+ printf ("Failed to clear 3c503 shared mem.\n");
+ return (0);
+ }
+ }
+ /*
+ * Initialize GA page/start/stop registers.
+ */
+ outb(eth_tx_start, eth_asic_base + _3COM_PSTR);
+ outb(eth_memsize, eth_asic_base + _3COM_PSPR);
+ }
+#endif
+#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
+{
+ /******************************************************************
+ Search for NE1000/2000 if no WD/SMC or 3com cards
+ ******************************************************************/
+ unsigned char c;
+ if (eth_vendor == VENDOR_NONE) {
+ unsigned char romdata[16];
+ unsigned char testbuf[32];
+ int idx;
+ static unsigned char test[] = "NE*000 memory";
+ static unsigned short base[] = {
+#ifdef NE_SCAN
+ NE_SCAN,
+#endif
+ 0 };
+ /* if no addresses supplied, fall back on defaults */
+ if (probe_addrs == 0 || probe_addrs[0] == 0)
+ probe_addrs = base;
+ eth_bmem = 0; /* No shared memory */
+ for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
+ eth_flags = FLAG_PIO;
+ eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
+ eth_memsize = MEM_16384;
+ eth_tx_start = 32;
+ eth_rx_start = 32 + D8390_TXBUF_SIZE;
+ c = inb(eth_asic_base + NE_RESET);
+ outb(c, eth_asic_base + NE_RESET);
+ (void) inb(0x84);
+ outb(D8390_COMMAND_STP |
+ D8390_COMMAND_RD2, eth_nic_base + D8390_P0_COMMAND);
+ outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
+ outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
+ outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
+ outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
+#ifdef NS8390_FORCE_16BIT
+ eth_flags |= FLAG_16BIT; /* force 16-bit mode */
+#endif
+
+ eth_pio_write( (unsigned char *) test, 8192, sizeof(test));
+ eth_pio_read(8192, testbuf, sizeof(test));
+ if (!memcmp(test, testbuf, sizeof(test)))
+ break;
+ eth_flags |= FLAG_16BIT;
+ eth_memsize = MEM_32768;
+ eth_tx_start = 64;
+ eth_rx_start = 64 + D8390_TXBUF_SIZE;
+ outb(D8390_DCR_WTS |
+ D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
+ outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
+ outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
+ eth_pio_write( (unsigned char *) test, 16384, sizeof(test));
+ eth_pio_read(16384, testbuf, sizeof(test));
+ if (!memcmp(testbuf, test, sizeof(test)))
+ break;
+ }
+ if (eth_nic_base == 0)
+ return (0);
+ if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
+ eth_flags |= FLAG_16BIT;
+ eth_vendor = VENDOR_NOVELL;
+ eth_pio_read(0, romdata, sizeof(romdata));
+ for (i=0; i<ETH_ALEN; i++) {
+ nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
+ }
+ nic->ioaddr = eth_nic_base;
+ DBG ( "\nNE%c000 base %4.4x, MAC Addr %s\n",
+ (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base,
+ eth_ntoa ( nic->node_addr ) );
+ }
+}
+#endif
+ if (eth_vendor == VENDOR_NONE)
+ return(0);
+ if (eth_vendor != VENDOR_3COM)
+ eth_rmem = eth_bmem;
+ ns8390_reset(nic);
+ nic->nic_op = &ns8390_operations;
+
+ /* Based on PnP ISA map */
+#ifdef INCLUDE_WD
+ dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
+ dev->devid.device_id = htons(0x812a);
+#endif
+#ifdef INCLUDE_3C503
+ dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
+ dev->devid.device_id = htons(0x80f3);
+#endif
+#ifdef INCLUDE_NE
+ dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
+ dev->devid.device_id = htons(0x80d6);
+#endif
+ return 1;
+}
+
+#ifdef INCLUDE_WD
+struct isa_driver wd_driver __isa_driver = {
+ .type = NIC_DRIVER,
+ .name = "WD",
+ .probe = wd_probe,
+ .ioaddrs = 0,
+};
+ISA_ROM("wd","WD8003/8013, SMC8216/8416, SMC 83c790 (EtherEZ)");
+#endif
+
+#ifdef INCLUDE_3C503
+struct isa_driver t503_driver __isa_driver = {
+ .type = NIC_DRIVER,
+ .name = "3C503",
+ .probe = t503_probe,
+ .ioaddrs = 0,
+};
+ISA_ROM("3c503","3Com503, Etherlink II[/16]");
+#endif
+
+#ifdef INCLUDE_NE
+struct isa_driver ne_driver __isa_driver = {
+ .type = NIC_DRIVER,
+ .name = "NE*000",
+ .probe = ne_probe,
+ .ioaddrs = 0,
+};
+ISA_ROM("ne","NE1000/2000 and clones");
+#endif
+
+#ifdef INCLUDE_NS8390
+static struct pci_device_id nepci_nics[] = {
+/* A few NE2000 PCI clones, list not exhaustive */
+PCI_ROM(0x10ec, 0x8029, "rtl8029", "Realtek 8029", 0),
+PCI_ROM(0x1186, 0x0300, "dlink-528", "D-Link DE-528", 0),
+PCI_ROM(0x1050, 0x0940, "winbond940", "Winbond NE2000-PCI", 0), /* Winbond 86C940 / 89C940 */
+PCI_ROM(0x1050, 0x5a5a, "winbond940f", "Winbond W89c940F", 0), /* Winbond 89C940F */
+PCI_ROM(0x11f6, 0x1401, "compexrl2000", "Compex ReadyLink 2000", 0),
+PCI_ROM(0x8e2e, 0x3000, "ktiet32p2", "KTI ET32P2", 0),
+PCI_ROM(0x4a14, 0x5000, "nv5000sc", "NetVin NV5000SC", 0),
+PCI_ROM(0x12c3, 0x0058, "holtek80232", "Holtek HT80232", 0),
+PCI_ROM(0x12c3, 0x5598, "holtek80229", "Holtek HT80229", 0),
+PCI_ROM(0x10bd, 0x0e34, "surecom-ne34", "Surecom NE34", 0),
+PCI_ROM(0x1106, 0x0926, "via86c926", "Via 86c926", 0),
+};
+
+PCI_DRIVER ( nepci_driver, nepci_nics, PCI_NO_CLASS );
+
+DRIVER ( "NE2000/PCI", nic_driver, pci_driver, nepci_driver,
+ nepci_probe, ns8390_disable );
+
+#endif /* INCLUDE_NS8390 */
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/ns8390.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/ns8390.h
new file mode 100644
index 00000000..79728e75
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/ns8390.h
@@ -0,0 +1,240 @@
+/**************************************************************************
+ETHERBOOT - BOOTP/TFTP Bootstrap Program
+
+Author: Martin Renters
+ Date: Jun/94
+
+**************************************************************************/
+
+FILE_LICENCE ( BSD2 );
+
+#define VENDOR_NONE 0
+#define VENDOR_WD 1
+#define VENDOR_NOVELL 2
+#define VENDOR_3COM 3
+
+#define FLAG_PIO 0x01
+#define FLAG_16BIT 0x02
+#define FLAG_790 0x04
+
+#define MEM_8192 32
+#define MEM_16384 64
+#define MEM_32768 128
+
+#define ISA_MAX_ADDR 0x400
+
+/**************************************************************************
+Western Digital/SMC Board Definitions
+**************************************************************************/
+#define WD_LOW_BASE 0x200
+#define WD_HIGH_BASE 0x3e0
+#ifndef WD_DEFAULT_MEM
+#define WD_DEFAULT_MEM 0xD0000
+#endif
+#define WD_NIC_ADDR 0x10
+
+/**************************************************************************
+Western Digital/SMC ASIC Addresses
+**************************************************************************/
+#define WD_MSR 0x00
+#define WD_ICR 0x01
+#define WD_IAR 0x02
+#define WD_BIO 0x03
+#define WD_IRR 0x04
+#define WD_LAAR 0x05
+#define WD_IJR 0x06
+#define WD_GP2 0x07
+#define WD_LAR 0x08
+#define WD_BID 0x0E
+
+#define WD_ICR_16BIT 0x01
+
+#define WD_MSR_MENB 0x40
+
+#define WD_LAAR_L16EN 0x40
+#define WD_LAAR_M16EN 0x80
+
+#define WD_SOFTCONFIG 0x20
+
+/**************************************************************************
+Western Digital/SMC Board Types
+**************************************************************************/
+#define TYPE_WD8003S 0x02
+#define TYPE_WD8003E 0x03
+#define TYPE_WD8013EBT 0x05
+#define TYPE_WD8003W 0x24
+#define TYPE_WD8003EB 0x25
+#define TYPE_WD8013W 0x26
+#define TYPE_WD8013EP 0x27
+#define TYPE_WD8013WC 0x28
+#define TYPE_WD8013EPC 0x29
+#define TYPE_SMC8216T 0x2a
+#define TYPE_SMC8216C 0x2b
+#define TYPE_SMC8416T 0x00 /* Bogus entries: the 8416 generates the */
+#define TYPE_SMC8416C 0x00 /* the same codes as the 8216. */
+#define TYPE_SMC8013EBP 0x2c
+
+/**************************************************************************
+3com 3c503 definitions
+**************************************************************************/
+
+#ifndef _3COM_BASE
+#define _3COM_BASE 0x300
+#endif
+
+#define _3COM_TX_PAGE_OFFSET_8BIT 0x20
+#define _3COM_TX_PAGE_OFFSET_16BIT 0x0
+#define _3COM_RX_PAGE_OFFSET_16BIT 0x20
+
+#define _3COM_ASIC_OFFSET 0x400
+#define _3COM_NIC_OFFSET 0x0
+
+#define _3COM_PSTR 0
+#define _3COM_PSPR 1
+
+#define _3COM_BCFR 3
+#define _3COM_BCFR_2E0 0x01
+#define _3COM_BCFR_2A0 0x02
+#define _3COM_BCFR_280 0x04
+#define _3COM_BCFR_250 0x08
+#define _3COM_BCFR_350 0x10
+#define _3COM_BCFR_330 0x20
+#define _3COM_BCFR_310 0x40
+#define _3COM_BCFR_300 0x80
+#define _3COM_PCFR 4
+#define _3COM_PCFR_PIO 0
+#define _3COM_PCFR_C8000 0x10
+#define _3COM_PCFR_CC000 0x20
+#define _3COM_PCFR_D8000 0x40
+#define _3COM_PCFR_DC000 0x80
+#define _3COM_CR 6
+#define _3COM_CR_RST 0x01 /* Reset GA and NIC */
+#define _3COM_CR_XSEL 0x02 /* Transceiver select. BNC=1(def) AUI=0 */
+#define _3COM_CR_EALO 0x04 /* window EA PROM 0-15 to I/O base */
+#define _3COM_CR_EAHI 0x08 /* window EA PROM 16-31 to I/O base */
+#define _3COM_CR_SHARE 0x10 /* select interrupt sharing option */
+#define _3COM_CR_DBSEL 0x20 /* Double buffer select */
+#define _3COM_CR_DDIR 0x40 /* DMA direction select */
+#define _3COM_CR_START 0x80 /* Start DMA controller */
+#define _3COM_GACFR 5
+#define _3COM_GACFR_MBS0 0x01
+#define _3COM_GACFR_MBS1 0x02
+#define _3COM_GACFR_MBS2 0x04
+#define _3COM_GACFR_RSEL 0x08 /* enable shared memory */
+#define _3COM_GACFR_TEST 0x10 /* for GA testing */
+#define _3COM_GACFR_OWS 0x20 /* select 0WS access to GA */
+#define _3COM_GACFR_TCM 0x40 /* Mask DMA interrupts */
+#define _3COM_GACFR_NIM 0x80 /* Mask NIC interrupts */
+#define _3COM_STREG 7
+#define _3COM_STREG_REV 0x07 /* GA revision */
+#define _3COM_STREG_DIP 0x08 /* DMA in progress */
+#define _3COM_STREG_DTC 0x10 /* DMA terminal count */
+#define _3COM_STREG_OFLW 0x20 /* Overflow */
+#define _3COM_STREG_UFLW 0x40 /* Underflow */
+#define _3COM_STREG_DPRDY 0x80 /* Data port ready */
+#define _3COM_IDCFR 8
+#define _3COM_IDCFR_DRQ0 0x01 /* DMA request 1 select */
+#define _3COM_IDCFR_DRQ1 0x02 /* DMA request 2 select */
+#define _3COM_IDCFR_DRQ2 0x04 /* DMA request 3 select */
+#define _3COM_IDCFR_UNUSED 0x08 /* not used */
+#define _3COM_IDCFR_IRQ2 0x10 /* Interrupt request 2 select */
+#define _3COM_IDCFR_IRQ3 0x20 /* Interrupt request 3 select */
+#define _3COM_IDCFR_IRQ4 0x40 /* Interrupt request 4 select */
+#define _3COM_IDCFR_IRQ5 0x80 /* Interrupt request 5 select */
+#define _3COM_IRQ2 2
+#define _3COM_IRQ3 3
+#define _3COM_IRQ4 4
+#define _3COM_IRQ5 5
+#define _3COM_DAMSB 9
+#define _3COM_DALSB 0x0a
+#define _3COM_VPTR2 0x0b
+#define _3COM_VPTR1 0x0c
+#define _3COM_VPTR0 0x0d
+#define _3COM_RFMSB 0x0e
+#define _3COM_RFLSB 0x0f
+
+/**************************************************************************
+NE1000/2000 definitions
+**************************************************************************/
+#define NE_ASIC_OFFSET 0x10
+#define NE_RESET 0x0F /* Used to reset card */
+#define NE_DATA 0x00 /* Used to read/write NIC mem */
+
+#define COMPEX_RL2000_TRIES 200
+
+/**************************************************************************
+8390 Register Definitions
+**************************************************************************/
+#define D8390_P0_COMMAND 0x00
+#define D8390_P0_PSTART 0x01
+#define D8390_P0_PSTOP 0x02
+#define D8390_P0_BOUND 0x03
+#define D8390_P0_TSR 0x04
+#define D8390_P0_TPSR 0x04
+#define D8390_P0_TBCR0 0x05
+#define D8390_P0_TBCR1 0x06
+#define D8390_P0_ISR 0x07
+#define D8390_P0_RSAR0 0x08
+#define D8390_P0_RSAR1 0x09
+#define D8390_P0_RBCR0 0x0A
+#define D8390_P0_RBCR1 0x0B
+#define D8390_P0_RSR 0x0C
+#define D8390_P0_RCR 0x0C
+#define D8390_P0_TCR 0x0D
+#define D8390_P0_DCR 0x0E
+#define D8390_P0_IMR 0x0F
+#define D8390_P1_COMMAND 0x00
+#define D8390_P1_PAR0 0x01
+#define D8390_P1_PAR1 0x02
+#define D8390_P1_PAR2 0x03
+#define D8390_P1_PAR3 0x04
+#define D8390_P1_PAR4 0x05
+#define D8390_P1_PAR5 0x06
+#define D8390_P1_CURR 0x07
+#define D8390_P1_MAR0 0x08
+
+#define D8390_COMMAND_PS0 0x0 /* Page 0 select */
+#define D8390_COMMAND_PS1 0x40 /* Page 1 select */
+#define D8390_COMMAND_PS2 0x80 /* Page 2 select */
+#define D8390_COMMAND_RD2 0x20 /* Remote DMA control */
+#define D8390_COMMAND_RD1 0x10
+#define D8390_COMMAND_RD0 0x08
+#define D8390_COMMAND_TXP 0x04 /* transmit packet */
+#define D8390_COMMAND_STA 0x02 /* start */
+#define D8390_COMMAND_STP 0x01 /* stop */
+
+#define D8390_RCR_MON 0x20 /* monitor mode */
+
+#define D8390_DCR_FT1 0x40
+#define D8390_DCR_LS 0x08 /* Loopback select */
+#define D8390_DCR_WTS 0x01 /* Word transfer select */
+
+#define D8390_ISR_PRX 0x01 /* successful recv */
+#define D8390_ISR_PTX 0x02 /* successful xmit */
+#define D8390_ISR_RXE 0x04 /* receive error */
+#define D8390_ISR_TXE 0x08 /* transmit error */
+#define D8390_ISR_OVW 0x10 /* Overflow */
+#define D8390_ISR_CNT 0x20 /* Counter overflow */
+#define D8390_ISR_RDC 0x40 /* Remote DMA complete */
+#define D8390_ISR_RST 0x80 /* reset */
+
+#define D8390_RSTAT_PRX 0x01 /* successful recv */
+#define D8390_RSTAT_CRC 0x02 /* CRC error */
+#define D8390_RSTAT_FAE 0x04 /* Frame alignment error */
+#define D8390_RSTAT_OVER 0x08 /* FIFO overrun */
+
+#define D8390_TXBUF_SIZE 6
+#define D8390_RXBUF_END 32
+#define D8390_PAGE_SIZE 256
+
+struct ringbuffer {
+ unsigned char status;
+ unsigned char next;
+ unsigned short len;
+};
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/p80211hdr.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/p80211hdr.h
new file mode 100644
index 00000000..83546712
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/p80211hdr.h
@@ -0,0 +1,301 @@
+/* src/include/wlan/p80211hdr.h
+*
+* Macros, types, and functions for handling 802.11 MAC headers
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file declares the constants and types used in the interface
+* between a wlan driver and the user mode utilities.
+*
+* Note:
+* - Constant values are always in HOST byte order. To assign
+* values to multi-byte fields they _must_ be converted to
+* ieee byte order. To retrieve multi-byte values from incoming
+* frames, they must be converted to host order.
+*
+* All functions declared here are implemented in p80211.c
+* --------------------------------------------------------------------
+*/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#ifndef _P80211HDR_H
+#define _P80211HDR_H
+
+/*================================================================*/
+/* System Includes */
+
+/*================================================================*/
+/* Project Includes */
+
+#ifndef _WLAN_COMPAT_H
+#include <wlan/wlan_compat.h>
+#endif
+
+
+/*================================================================*/
+/* Constants */
+
+/*--- Sizes -----------------------------------------------*/
+#define WLAN_ADDR_LEN 6
+#define WLAN_CRC_LEN 4
+#define WLAN_BSSID_LEN 6
+#define WLAN_BSS_TS_LEN 8
+#define WLAN_HDR_A3_LEN 24
+#define WLAN_HDR_A4_LEN 30
+#define WLAN_SSID_MAXLEN 32
+#define WLAN_DATA_MAXLEN 2312
+#define WLAN_A3FR_MAXLEN (WLAN_HDR_A3_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN)
+#define WLAN_A4FR_MAXLEN (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN)
+#define WLAN_BEACON_FR_MAXLEN (WLAN_HDR_A3_LEN + 334)
+#define WLAN_ATIM_FR_MAXLEN (WLAN_HDR_A3_LEN + 0)
+#define WLAN_DISASSOC_FR_MAXLEN (WLAN_HDR_A3_LEN + 2)
+#define WLAN_ASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 48)
+#define WLAN_ASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16)
+#define WLAN_REASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 54)
+#define WLAN_REASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16)
+#define WLAN_PROBEREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 44)
+#define WLAN_PROBERESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 78)
+#define WLAN_AUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 261)
+#define WLAN_DEAUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 2)
+#define WLAN_WEP_NKEYS 4
+#define WLAN_WEP_MAXKEYLEN 13
+#define WLAN_CHALLENGE_IE_LEN 130
+#define WLAN_CHALLENGE_LEN 128
+#define WLAN_WEP_IV_LEN 4
+#define WLAN_WEP_ICV_LEN 4
+
+/*--- Frame Control Field -------------------------------------*/
+/* Frame Types */
+#define WLAN_FTYPE_MGMT 0x00
+#define WLAN_FTYPE_CTL 0x01
+#define WLAN_FTYPE_DATA 0x02
+
+/* Frame subtypes */
+/* Management */
+#define WLAN_FSTYPE_ASSOCREQ 0x00
+#define WLAN_FSTYPE_ASSOCRESP 0x01
+#define WLAN_FSTYPE_REASSOCREQ 0x02
+#define WLAN_FSTYPE_REASSOCRESP 0x03
+#define WLAN_FSTYPE_PROBEREQ 0x04
+#define WLAN_FSTYPE_PROBERESP 0x05
+#define WLAN_FSTYPE_BEACON 0x08
+#define WLAN_FSTYPE_ATIM 0x09
+#define WLAN_FSTYPE_DISASSOC 0x0a
+#define WLAN_FSTYPE_AUTHEN 0x0b
+#define WLAN_FSTYPE_DEAUTHEN 0x0c
+
+/* Control */
+#define WLAN_FSTYPE_BLOCKACKREQ 0x8
+#define WLAN_FSTYPE_BLOCKACK 0x9
+#define WLAN_FSTYPE_PSPOLL 0x0a
+#define WLAN_FSTYPE_RTS 0x0b
+#define WLAN_FSTYPE_CTS 0x0c
+#define WLAN_FSTYPE_ACK 0x0d
+#define WLAN_FSTYPE_CFEND 0x0e
+#define WLAN_FSTYPE_CFENDCFACK 0x0f
+
+/* Data */
+#define WLAN_FSTYPE_DATAONLY 0x00
+#define WLAN_FSTYPE_DATA_CFACK 0x01
+#define WLAN_FSTYPE_DATA_CFPOLL 0x02
+#define WLAN_FSTYPE_DATA_CFACK_CFPOLL 0x03
+#define WLAN_FSTYPE_NULL 0x04
+#define WLAN_FSTYPE_CFACK 0x05
+#define WLAN_FSTYPE_CFPOLL 0x06
+#define WLAN_FSTYPE_CFACK_CFPOLL 0x07
+
+
+/*================================================================*/
+/* Macros */
+
+/*--- FC Macros ----------------------------------------------*/
+/* Macros to get/set the bitfields of the Frame Control Field */
+/* GET_FC_??? - takes the host byte-order value of an FC */
+/* and retrieves the value of one of the */
+/* bitfields and moves that value so its lsb is */
+/* in bit 0. */
+/* SET_FC_??? - takes a host order value for one of the FC */
+/* bitfields and moves it to the proper bit */
+/* location for ORing into a host order FC. */
+/* To send the FC produced from SET_FC_???, */
+/* one must put the bytes in IEEE order. */
+/* e.g. */
+/* printf("the frame subtype is %x", */
+/* GET_FC_FTYPE( ieee2host( rx.fc ))) */
+/* */
+/* tx.fc = host2ieee( SET_FC_FTYPE(WLAN_FTYP_CTL) | */
+/* SET_FC_FSTYPE(WLAN_FSTYPE_RTS) ); */
+/*------------------------------------------------------------*/
+
+#define WLAN_GET_FC_PVER(n) (((UINT16)(n)) & (BIT0 | BIT1))
+#define WLAN_GET_FC_FTYPE(n) ((((UINT16)(n)) & (BIT2 | BIT3)) >> 2)
+#define WLAN_GET_FC_FSTYPE(n) ((((UINT16)(n)) & (BIT4|BIT5|BIT6|BIT7)) >> 4)
+#define WLAN_GET_FC_TODS(n) ((((UINT16)(n)) & (BIT8)) >> 8)
+#define WLAN_GET_FC_FROMDS(n) ((((UINT16)(n)) & (BIT9)) >> 9)
+#define WLAN_GET_FC_MOREFRAG(n) ((((UINT16)(n)) & (BIT10)) >> 10)
+#define WLAN_GET_FC_RETRY(n) ((((UINT16)(n)) & (BIT11)) >> 11)
+#define WLAN_GET_FC_PWRMGT(n) ((((UINT16)(n)) & (BIT12)) >> 12)
+#define WLAN_GET_FC_MOREDATA(n) ((((UINT16)(n)) & (BIT13)) >> 13)
+#define WLAN_GET_FC_ISWEP(n) ((((UINT16)(n)) & (BIT14)) >> 14)
+#define WLAN_GET_FC_ORDER(n) ((((UINT16)(n)) & (BIT15)) >> 15)
+
+#define WLAN_SET_FC_PVER(n) ((UINT16)(n))
+#define WLAN_SET_FC_FTYPE(n) (((UINT16)(n)) << 2)
+#define WLAN_SET_FC_FSTYPE(n) (((UINT16)(n)) << 4)
+#define WLAN_SET_FC_TODS(n) (((UINT16)(n)) << 8)
+#define WLAN_SET_FC_FROMDS(n) (((UINT16)(n)) << 9)
+#define WLAN_SET_FC_MOREFRAG(n) (((UINT16)(n)) << 10)
+#define WLAN_SET_FC_RETRY(n) (((UINT16)(n)) << 11)
+#define WLAN_SET_FC_PWRMGT(n) (((UINT16)(n)) << 12)
+#define WLAN_SET_FC_MOREDATA(n) (((UINT16)(n)) << 13)
+#define WLAN_SET_FC_ISWEP(n) (((UINT16)(n)) << 14)
+#define WLAN_SET_FC_ORDER(n) (((UINT16)(n)) << 15)
+
+/*--- Duration Macros ----------------------------------------*/
+/* Macros to get/set the bitfields of the Duration Field */
+/* - the duration value is only valid when bit15 is zero */
+/* - the firmware handles these values, so I'm not going */
+/* these macros right now. */
+/*------------------------------------------------------------*/
+
+/*--- Sequence Control Macros -------------------------------*/
+/* Macros to get/set the bitfields of the Sequence Control */
+/* Field. */
+/*------------------------------------------------------------*/
+#define WLAN_GET_SEQ_FRGNUM(n) (((UINT16)(n)) & (BIT0|BIT1|BIT2|BIT3))
+#define WLAN_GET_SEQ_SEQNUM(n) ((((UINT16)(n)) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4)
+
+/*--- Data ptr macro -----------------------------------------*/
+/* Creates a UINT8* to the data portion of a frame */
+/* Assumes you're passing in a ptr to the beginning of the hdr*/
+/*------------------------------------------------------------*/
+#define WLAN_HDR_A3_DATAP(p) (((UINT8*)(p)) + WLAN_HDR_A3_LEN)
+#define WLAN_HDR_A4_DATAP(p) (((UINT8*)(p)) + WLAN_HDR_A4_LEN)
+
+#define DOT11_RATE5_ISBASIC_GET(r) (((UINT8)(r)) & BIT7)
+
+/*================================================================*/
+/* Types */
+
+/* BSS Timestamp */
+typedef UINT8 wlan_bss_ts_t[WLAN_BSS_TS_LEN];
+
+/* Generic 802.11 Header types */
+
+typedef struct p80211_hdr_a3
+{
+ UINT16 fc;
+ UINT16 dur;
+ UINT8 a1[WLAN_ADDR_LEN];
+ UINT8 a2[WLAN_ADDR_LEN];
+ UINT8 a3[WLAN_ADDR_LEN];
+ UINT16 seq;
+} __WLAN_ATTRIB_PACK__ p80211_hdr_a3_t;
+
+typedef struct p80211_hdr_a4
+{
+ UINT16 fc;
+ UINT16 dur;
+ UINT8 a1[WLAN_ADDR_LEN];
+ UINT8 a2[WLAN_ADDR_LEN];
+ UINT8 a3[WLAN_ADDR_LEN];
+ UINT16 seq;
+ UINT8 a4[WLAN_ADDR_LEN];
+} __WLAN_ATTRIB_PACK__ p80211_hdr_a4_t;
+
+typedef union p80211_hdr
+{
+ p80211_hdr_a3_t a3;
+ p80211_hdr_a4_t a4;
+} __WLAN_ATTRIB_PACK__ p80211_hdr_t;
+
+
+/*================================================================*/
+/* Extern Declarations */
+
+
+/*================================================================*/
+/* Function Declarations */
+
+/* Frame and header lenght macros */
+
+#define WLAN_CTL_FRAMELEN(fstype) (\
+ (fstype) == WLAN_FSTYPE_BLOCKACKREQ ? 24 : \
+ (fstype) == WLAN_FSTYPE_BLOCKACK ? 152 : \
+ (fstype) == WLAN_FSTYPE_PSPOLL ? 20 : \
+ (fstype) == WLAN_FSTYPE_RTS ? 20 : \
+ (fstype) == WLAN_FSTYPE_CTS ? 14 : \
+ (fstype) == WLAN_FSTYPE_ACK ? 14 : \
+ (fstype) == WLAN_FSTYPE_CFEND ? 20 : \
+ (fstype) == WLAN_FSTYPE_CFENDCFACK ? 20 : 4)
+
+#define WLAN_FCS_LEN 4
+
+/* ftcl in HOST order */
+inline static UINT16 p80211_headerlen(UINT16 fctl)
+{
+ UINT16 hdrlen = 0;
+
+ switch ( WLAN_GET_FC_FTYPE(fctl) ) {
+ case WLAN_FTYPE_MGMT:
+ hdrlen = WLAN_HDR_A3_LEN;
+ break;
+ case WLAN_FTYPE_DATA:
+ hdrlen = WLAN_HDR_A3_LEN;
+ if ( WLAN_GET_FC_TODS(fctl) && WLAN_GET_FC_FROMDS(fctl) ) {
+ hdrlen += WLAN_ADDR_LEN;
+ }
+ break;
+ case WLAN_FTYPE_CTL:
+ hdrlen = WLAN_CTL_FRAMELEN(WLAN_GET_FC_FSTYPE(fctl)) -
+ WLAN_FCS_LEN;
+ break;
+ default:
+ hdrlen = WLAN_HDR_A3_LEN;
+ }
+
+ return hdrlen;
+}
+
+#endif /* _P80211HDR_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/pcnet32.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/pcnet32.c
new file mode 100644
index 00000000..d6da3c5e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/pcnet32.c
@@ -0,0 +1,1161 @@
+/*
+ * Copyright (c) 2010 Andrei Faur <da3drus@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/io.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/pci.h>
+#include <ipxe/timer.h>
+#include <mii.h>
+#include "pcnet32.h"
+
+static u16 pcnet32_wio_read_csr ( unsigned long addr, int index )
+{
+ outw ( index, addr + PCNET32_WIO_RAP );
+ return inw ( addr + PCNET32_WIO_RDP );
+}
+
+static void pcnet32_wio_write_csr ( unsigned long addr, int index, u16 val )
+{
+ outw ( index, addr + PCNET32_WIO_RAP );
+ outw ( val, addr + PCNET32_WIO_RDP );
+}
+
+static u16 pcnet32_wio_read_bcr ( unsigned long addr, int index )
+{
+ outw ( index, addr + PCNET32_WIO_RAP );
+ return inw ( addr + PCNET32_WIO_BDP );
+}
+
+static void pcnet32_wio_write_bcr ( unsigned long addr, int index, u16 val )
+{
+ outw ( index, addr + PCNET32_WIO_RAP );
+ outw ( val, addr + PCNET32_WIO_BDP );
+}
+
+static u16 pcnet32_wio_read_rap ( unsigned long addr )
+{
+ return inw ( addr + PCNET32_WIO_RAP );
+}
+
+static void pcnet32_wio_write_rap ( unsigned long addr , u16 val )
+{
+ outw ( val, addr + PCNET32_WIO_RAP );
+}
+
+static void pcnet32_wio_reset ( unsigned long addr )
+{
+ inw ( addr + PCNET32_WIO_RESET );
+}
+
+static int pcnet32_wio_check ( unsigned long addr )
+{
+ outw ( 88, addr + PCNET32_WIO_RAP );
+ return ( inw ( addr + PCNET32_WIO_RAP ) == 88 );
+}
+
+static struct pcnet32_access pcnet32_wio = {
+ .read_csr = pcnet32_wio_read_csr,
+ .write_csr = pcnet32_wio_write_csr,
+ .read_bcr = pcnet32_wio_read_bcr,
+ .write_bcr = pcnet32_wio_write_bcr,
+ .read_rap = pcnet32_wio_read_rap,
+ .write_rap = pcnet32_wio_write_rap,
+ .reset = pcnet32_wio_reset,
+};
+
+static u16 pcnet32_dwio_read_csr ( unsigned long addr, int index )
+{
+ outl ( index, addr + PCNET32_DWIO_RAP );
+ return ( inl ( addr + PCNET32_DWIO_RDP ) & 0xffff );
+}
+
+static void pcnet32_dwio_write_csr ( unsigned long addr, int index, u16 val )
+{
+ outl ( index, addr + PCNET32_DWIO_RAP );
+ outl ( val, addr + PCNET32_DWIO_RDP );
+}
+
+static u16 pcnet32_dwio_read_bcr ( unsigned long addr, int index )
+{
+ outl ( index, addr + PCNET32_DWIO_RAP );
+ return ( inl ( addr + PCNET32_DWIO_BDP ) & 0xffff );
+}
+
+static void pcnet32_dwio_write_bcr ( unsigned long addr, int index, u16 val )
+{
+ outl ( index, addr + PCNET32_DWIO_RAP );
+ outl ( val, addr + PCNET32_DWIO_BDP );
+}
+
+static u16 pcnet32_dwio_read_rap ( unsigned long addr )
+{
+ return ( inl ( addr + PCNET32_DWIO_RAP ) & 0xffff );
+}
+
+static void pcnet32_dwio_write_rap ( unsigned long addr , u16 val )
+{
+ outl ( val, addr + PCNET32_DWIO_RAP );
+}
+
+static void pcnet32_dwio_reset ( unsigned long addr )
+{
+ inl ( addr + PCNET32_DWIO_RESET );
+}
+
+static int pcnet32_dwio_check ( unsigned long addr )
+{
+ outl ( 88, addr + PCNET32_DWIO_RAP );
+ return ( ( inl ( addr + PCNET32_DWIO_RAP ) & 0xffff ) == 88 );
+}
+
+
+static struct pcnet32_access pcnet32_dwio = {
+ .read_csr = pcnet32_dwio_read_csr,
+ .write_csr = pcnet32_dwio_write_csr,
+ .read_bcr = pcnet32_dwio_read_bcr,
+ .write_bcr = pcnet32_dwio_write_bcr,
+ .read_rap = pcnet32_dwio_read_rap,
+ .write_rap = pcnet32_dwio_write_rap,
+ .reset = pcnet32_dwio_reset,
+};
+
+static int
+pcnet32_mdio_read ( struct net_device *netdev, int phy, int reg )
+{
+ struct pcnet32_private *priv = netdev->priv;
+ unsigned long ioaddr = priv->pci_dev->ioaddr;
+ u16 val_out;
+
+ if ( ! priv->mii )
+ return 0;
+
+ /* First, select PHY chip and the register we want to read */
+ priv->a->write_bcr ( ioaddr, 33,
+ ( ( phy & 0x1f ) << 5 ) | ( reg & 0x1f ) );
+
+ /* Read the selected register's value */
+ val_out = priv->a->read_bcr ( ioaddr, 34 );
+
+ return val_out;
+}
+
+static void
+__unused pcnet32_mdio_write ( struct net_device *netdev, int phy, int reg, int val )
+{
+ struct pcnet32_private *priv = netdev->priv;
+ unsigned long ioaddr = priv->pci_dev->ioaddr;
+
+ if ( ! priv->mii )
+ return;
+
+ /* First, select PHY chip and the register we want to write to */
+ priv->a->write_bcr ( ioaddr, 33,
+ ( ( phy & 0x1f ) << 5 ) | ( reg & 0x1f ) );
+
+ /* Write val to the selected register */
+ priv->a->write_bcr ( ioaddr, 34, val );
+}
+
+
+/**
+ * pcnet32_refill_rx_ring - Allocates iobufs for every Rx descriptor
+ * that doesn't have one and isn't in use by the hardware
+ *
+ * @v priv Driver private structure
+ */
+static void
+pcnet32_refill_rx_ring ( struct pcnet32_private *priv )
+{
+ struct pcnet32_rx_desc *rx_curr_desc;
+ u16 status;
+ int i;
+
+ DBGP ( "pcnet32_refill_rx_ring\n" );
+
+ for ( i = 0; i < RX_RING_SIZE; i++ ) {
+ rx_curr_desc = priv->rx_base + i;
+
+ status = le16_to_cpu ( rx_curr_desc->status );
+
+ /* Don't touch descriptors owned by the hardware */
+ if ( status & DescOwn )
+ continue;
+
+ /* Descriptors with iobufs still need to be processed */
+ if ( priv->rx_iobuf[i] != NULL )
+ continue;
+
+ /* If alloc_iob fails, try again later (next poll) */
+ if ( ! ( priv->rx_iobuf[i] = alloc_iob ( PKT_BUF_SIZE ) ) ) {
+ DBG ( "Refill rx ring failed\n" );
+ break;
+ }
+
+ rx_curr_desc->base =
+ cpu_to_le32 ( virt_to_bus ( priv->rx_iobuf[i]->data ) );
+ rx_curr_desc->buf_length = cpu_to_le16 ( -PKT_BUF_SIZE );
+ rx_curr_desc->msg_length = rx_curr_desc->reserved = 0;
+
+ /* Owner changes after the other status fields are set */
+ wmb();
+ rx_curr_desc->status = cpu_to_le16 ( DescOwn );
+ }
+
+}
+
+/**
+ * pcnet32_setup_rx_resources - allocate Rx resources (Descriptors)
+ *
+ * @v priv Driver private structure
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ */
+static int
+pcnet32_setup_rx_resources ( struct pcnet32_private *priv )
+{
+ DBGP ( "pcnet32_setup_rx_resources\n" );
+
+ priv->rx_base = malloc_dma ( RX_RING_BYTES, RX_RING_ALIGN );
+
+ DBG ( "priv->rx_base = %#08lx\n", virt_to_bus ( priv->rx_base ) );
+
+ if ( ! priv->rx_base ) {
+ return -ENOMEM;
+ }
+
+ memset ( priv->rx_base, 0, RX_RING_BYTES );
+
+ pcnet32_refill_rx_ring ( priv );
+
+ priv->rx_curr = 0;
+
+ return 0;
+}
+
+static void
+pcnet32_free_rx_resources ( struct pcnet32_private *priv )
+{
+ int i;
+
+ DBGP ( "pcnet32_free_rx_resources\n" );
+
+ free_dma ( priv->rx_base, RX_RING_BYTES );
+
+ for ( i = 0; i < RX_RING_SIZE; i++ ) {
+ free_iob ( priv->rx_iobuf[i] );
+ priv->rx_iobuf[i] = NULL;
+ }
+}
+
+/**
+ * pcnet32_setup_tx_resources - allocate Tx resources (Descriptors)
+ *
+ * @v priv Driver private structure
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ */
+static int
+pcnet32_setup_tx_resources ( struct pcnet32_private *priv )
+{
+ DBGP ( "pcnet32_setup_tx_resources\n" );
+
+ priv->tx_base = malloc_dma ( TX_RING_BYTES, TX_RING_ALIGN );
+
+ if ( ! priv->tx_base ) {
+ return -ENOMEM;
+ }
+
+ memset ( priv->tx_base, 0, TX_RING_BYTES );
+
+ DBG ( "priv->tx_base = %#08lx\n", virt_to_bus ( priv->tx_base ) );
+
+ priv->tx_curr = 0;
+ priv->tx_fill_ctr = 0;
+ priv->tx_tail = 0;
+
+ return 0;
+}
+
+static void
+pcnet32_free_tx_resources ( struct pcnet32_private *priv )
+{
+ DBGP ( "pcnet32_free_tx_resources\n" );
+
+ free_dma ( priv->tx_base, TX_RING_BYTES );
+}
+
+static int
+pcnet32_chip_detect ( struct pcnet32_private *priv )
+{
+ int fdx, mii, fset;
+ int media;
+ int rc;
+ unsigned long ioaddr;
+ struct pcnet32_access *a;
+ int chip_version;
+ char *chipname;
+
+ ioaddr = priv->pci_dev->ioaddr;
+ a = priv->a;
+
+ chip_version = a->read_csr ( ioaddr, 88 )
+ | ( a->read_csr ( ioaddr, 89 ) << 16 );
+
+ rc = -ENODEV;
+
+ DBG ( "PCnet chip version is 0x%X\n", chip_version );
+ if ( ( chip_version & 0xfff ) != 0x003 )
+ goto err_unsupported;
+
+ fdx = mii = fset = 0;
+ chip_version = ( chip_version >> 12 ) & 0xffff;
+
+ switch (chip_version) {
+ case 0x2420:
+ chipname = "PCnet/PCI 79C970";
+ break;
+ case 0x2430:
+ /* 970 gives the wrong chip id back */
+ chipname = "PCnet/PCI 79C970";
+ break;
+ case 0x2621:
+ chipname = "PCnet/PCI II 79C970A";
+ fdx = 1;
+ break;
+ case 0x2623:
+ chipname = "PCnet/FAST 79C971";
+ fdx = 1;
+ mii = 1;
+ fset = 1;
+ break;
+ case 0x2624:
+ chipname = "PCnet/FAST+ 79C972";
+ fdx = 1;
+ mii = 1;
+ fset = 1;
+ break;
+ case 0x2625:
+ chipname = "PCnet/FAST III 79C973";
+ fdx = 1;
+ mii = 1;
+ break;
+ case 0x2626:
+ chipname = "PCnet/Home 79C978";
+ fdx = 1;
+ /*
+ * This is based on specs published at www.amd.com. This section
+ * assumes that a NIC with a 79C978 wants to go into 1Mb HomePNA
+ * mode. The 79C978 can also go into standard ethernet, and
+ * there probably should be some sort of module option to select
+ * the mode by which the card should operate
+ */
+ /* switch to home wiring mode */
+ media = a->read_bcr(ioaddr, 49);
+
+ DBG ( "media reset to %#x.\n", media );
+ a->write_bcr(ioaddr, 49, media);
+ break;
+ case 0x2627:
+ chipname = "PCnet/FAST III 79C975";
+ fdx = 1;
+ mii = 1;
+ break;
+ case 0x2628:
+ chipname = "PCnet/PRO 79C976";
+ fdx = 1;
+ mii = 1;
+ break;
+ default:
+ chipname = "UNKNOWN";
+ DBG ( "PCnet version %#x, no PCnet32 chip.\n", chip_version );
+ goto err_unsupported;
+ }
+
+ DBG ( "PCnet chipname %s\n", chipname );
+
+ /*
+ * On selected chips turn on the BCR18:NOUFLO bit. This stops transmit
+ * starting until the packet is loaded. Strike one for reliability, lose
+ * one for latency - although on PCI this isnt a big loss. Older chips
+ * have FIFO's smaller than a packet, so you can't do this.
+ * Turn on BCR18:BurstRdEn and BCR18:BurstWrEn.
+ */
+ if (fset) {
+ a->write_bcr ( ioaddr, 18,
+ ( a->read_bcr ( ioaddr, 18 ) | 0x0860 ) );
+ a->write_csr ( ioaddr, 80,
+ ( a->read_csr ( ioaddr, 80 ) & 0x0C00) | 0x0C00 );
+ }
+
+ priv->full_duplex = fdx;
+ priv->mii = mii;
+
+ return 0;
+
+err_unsupported:
+ return rc;
+}
+
+/**
+ * pcnet32_set_ops - Determines the ops used to access the registers
+ *
+ * @v priv Driver private structure
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ */
+static int
+pcnet32_set_ops ( struct pcnet32_private *priv )
+{
+ int rc;
+ unsigned long ioaddr;
+
+ ioaddr = priv->pci_dev->ioaddr;
+
+ /* Check if CSR0 has its default value and perform a write / read
+ in the RAP register to see if it works. Based on these results
+ determine what mode the NIC is in (WIO / DWIO)
+ */
+ rc = -ENODEV;
+
+ if ( pcnet32_wio_read_csr ( ioaddr, 0 ) == 4 &&
+ pcnet32_wio_check ( ioaddr ) ) {
+ priv->a = &pcnet32_wio;
+ } else {
+ pcnet32_dwio_reset ( ioaddr );
+ if ( pcnet32_dwio_read_csr ( ioaddr, 0 ) == 4 &&
+ pcnet32_dwio_check ( ioaddr ) ) {
+ priv->a = &pcnet32_dwio;
+ } else {
+ goto err_unsupported;
+ }
+ }
+
+ return 0;
+
+err_unsupported:
+ return rc;
+}
+
+/**
+ * pcnet32_setup_init_block - setup the NICs initialization block
+ *
+ * @v priv Driver private structure
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ */
+static void
+pcnet32_setup_init_block ( struct pcnet32_private *priv )
+{
+ int i;
+
+ /* Configure the network port based on what we've established so far */
+ priv->init_block.mode =
+ cpu_to_le16 ( ( priv->options & PCNET32_PORT_PORTSEL ) << 7 );
+
+ /* Setup RLEN and TLEN fields */
+ priv->init_block.tlen_rlen =
+ cpu_to_le16 ( ( PCNET32_LOG_RX_BUFFERS << 4 ) |
+ ( PCNET32_LOG_TX_BUFFERS << 12 ) );
+
+ /* Fill in physical address */
+ for ( i = 0; i < ETH_ALEN; i++)
+ priv->init_block.phys_addr[i] = priv->netdev->hw_addr[i];
+
+ /* No multicasting scheme, accept everything */
+ priv->init_block.filter[0] = 0xffffffff;
+ priv->init_block.filter[1] = 0xffffffff;
+
+ priv->init_block.rx_ring =
+ cpu_to_le32 ( virt_to_bus ( priv->rx_base ) );
+ priv->init_block.tx_ring =
+ cpu_to_le32 ( virt_to_bus ( priv->tx_base ) );
+
+ /* Make sure all changes are visible */
+ wmb();
+}
+
+/**
+ * pcnet32_setup_probe_phy - go through all PHYs and see which one is present
+ *
+ * @v priv Driver private structure
+ */
+static void
+pcnet32_setup_probe_phy ( struct pcnet32_private *priv )
+{
+ unsigned long ioaddr = priv->pci_dev->ioaddr;
+ unsigned int phycount = 0;
+ int phy_id;
+ int i;
+
+ if ( priv->mii ) {
+ phy_id = ( ( priv->a->read_bcr ( ioaddr, 33 ) ) >> 5 ) & 0x1f;
+ for ( i = 0; i < PCNET32_MAX_PHYS; i++ ) {
+ unsigned short id1, id2;
+ id1 = pcnet32_mdio_read ( priv->netdev, i, MII_PHYSID1 );
+ if ( id1 == 0xffff )
+ continue;
+ id2 = pcnet32_mdio_read ( priv->netdev, i, MII_PHYSID2 );
+ if ( id2 == 0xffff )
+ continue;
+ if ( i == 31 && ( ( priv->chip_version + 1 ) & 0xfffe ) == 0x2624 )
+ continue;
+
+ phycount++;
+ phy_id = i;
+ }
+ priv->a->write_bcr ( ioaddr, 33, phy_id << 5 );
+ if ( phycount > 1 )
+ priv->options |= PCNET32_PORT_MII;
+ }
+}
+
+/**
+ * pcnet32_setup_mac_addr - check for inconsistency between CSR12-14
+ * and PROM addresses
+ *
+ * @v priv Driver private structure
+ */
+static int
+pcnet32_setup_mac_addr ( struct pcnet32_private *priv )
+{
+ int i;
+ u8 promaddr[ETH_ALEN];
+ unsigned long ioaddr = priv->pci_dev->ioaddr;
+
+ /* In most chips, after a chip reset, the ethernet address is read from
+ * the station address PROM at the base address and programmed into the
+ * "Physical Address Registers" CSR12-14.
+ * As a precautionary measure, we read the PROM values and complain if
+ * they disagree with the CSRs. If they miscompare, and the PROM addr
+ * is valid, then the PROM addr is used.
+ */
+ for ( i = 0; i < 3; i++ ) {
+ unsigned int val;
+ val = priv->a->read_csr ( ioaddr, i + 12 ) & 0x0ffff;
+ /* There may be endianness issues here. */
+ priv->netdev->hw_addr[2 * i] = val & 0x0ff;
+ priv->netdev->hw_addr[2 * i + 1] = ( val >> 8 ) & 0x0ff;
+ }
+
+ for ( i = 0; i < ETH_ALEN; i++ )
+ promaddr[i] = inb ( ioaddr + i );
+
+ if ( memcmp ( promaddr, priv->netdev->hw_addr, ETH_ALEN ) ||
+ ! is_valid_ether_addr ( priv->netdev->hw_addr ) ) {
+ if ( is_valid_ether_addr ( promaddr ) ) {
+ DBG ( "CSR address is invalid, using PROM addr\n" );
+ memcpy ( priv->netdev->hw_addr, promaddr, ETH_ALEN );
+ }
+ }
+
+ /* If ethernet address is not valid, return error */
+ if ( ! is_valid_ether_addr ( priv->netdev->hw_addr ) )
+ return -EADDRNOTAVAIL;
+
+ return 0;
+}
+
+/**
+ * pcnet32_setup_if_duplex - Sets the NICs used interface and duplex mode
+ *
+ * @v priv Driver private structure
+ */
+static void
+pcnet32_setup_if_duplex ( struct pcnet32_private *priv )
+{
+ unsigned long ioaddr = priv->pci_dev->ioaddr;
+ u16 val;
+
+ /* Set/Reset autoselect bit */
+ val = priv->a->read_bcr ( ioaddr, 2 ) & ~2;
+ if ( priv->options & PCNET32_PORT_ASEL )
+ val |= 2;
+ priv->a->write_bcr ( ioaddr, 2, val );
+
+ /* Handle full duplex setting */
+ if ( priv->full_duplex ) {
+ val = priv->a->read_bcr ( ioaddr, 9 ) & ~3;
+ if ( priv->options & PCNET32_PORT_FD ) {
+ val |= 1;
+ if ( priv->options == ( PCNET32_PORT_FD | PCNET32_PORT_AUI ) )
+ val |= 2;
+ } else if ( priv->options & PCNET32_PORT_ASEL ) {
+ /* Workaround of xSeries 250, on for 79C975 only */
+ if ( priv->chip_version == 0x2627 )
+ val |= 3;
+ }
+ priv->a->write_bcr ( ioaddr, 9, val );
+ }
+
+ /* Set/Reset GPSI bit in test register */
+ val = priv->a->read_csr ( ioaddr, 124 ) & ~0x10;
+ if ( ( priv->options & PCNET32_PORT_PORTSEL ) == PCNET32_PORT_GPSI )
+ val |= 0x10;
+ priv->a->write_bcr ( ioaddr, 124, val );
+
+ /* Allied Telesyn AT are 100Mbit only and do not negotiate */
+ u16 subsys_vend_id, subsys_dev_id;
+ pci_read_config_word ( priv->pci_dev,
+ PCI_SUBSYSTEM_VENDOR_ID,
+ &subsys_vend_id );
+ pci_read_config_word ( priv->pci_dev,
+ PCI_SUBSYSTEM_ID,
+ &subsys_dev_id );
+ if ( subsys_vend_id == PCI_VENDOR_ID_AT &&
+ ( ( subsys_dev_id == PCI_SUBDEVICE_ID_AT_2700FX ) ||
+ ( subsys_dev_id == PCI_SUBDEVICE_ID_AT_2701FX ) ) ) {
+ priv->options = PCNET32_PORT_FD | PCNET32_PORT_100;
+ }
+
+ if ( priv->mii && ! ( priv->options & PCNET32_PORT_ASEL ) ) {
+ /* Disable Auto Negotiation, set 10Mbps, HD */
+ val = priv->a->read_bcr ( ioaddr, 32 ) & ~0x38;
+ if ( priv->options & PCNET32_PORT_FD )
+ val |= 0x10;
+ if ( priv->options & PCNET32_PORT_100 )
+ val |= 0x08;
+ priv->a->write_bcr ( ioaddr, 32, val );
+ } else if ( priv->options & PCNET32_PORT_ASEL ) {
+ /* 79C970 chips do not have the BCR32 register */
+ if ( ( priv->chip_version != 0x2420 ) &&
+ ( priv->chip_version != 0x2621 ) ) {
+ /* Enable Auto Negotiation, setup, disable FD */
+ val = priv->a->read_bcr ( ioaddr, 32 ) & ~0x98;
+ val |= 0x20;
+ priv->a->write_bcr ( ioaddr, 32, val );
+ }
+ }
+}
+
+/**
+ * pcnet32_hw_start - Starts up the NIC
+ *
+ * @v priv Driver private structure
+ */
+static void
+pcnet32_hw_start ( struct pcnet32_private *priv )
+{
+ unsigned long ioaddr = priv->pci_dev->ioaddr;
+ int i;
+
+ /* Begin initialization procedure */
+ priv->a->write_csr ( ioaddr, 0, Init );
+
+ /* Wait for the initialization to be done */
+ i = 0;
+ while ( i++ < 100 )
+ if ( priv->a->read_csr ( ioaddr, 0 ) & InitDone )
+ break;
+
+ /* Start the chip */
+ priv->a->write_csr ( ioaddr, 0, Strt );
+}
+
+/**
+ * open - Called when a network interface is made active
+ *
+ * @v netdev Network device
+ * @ret rc Return status code, 0 on success, negative value on failure
+ **/
+static int
+pcnet32_open ( struct net_device *netdev )
+{
+ struct pcnet32_private *priv = netdev_priv ( netdev );
+ unsigned long ioaddr = priv->pci_dev->ioaddr;
+ int rc;
+ u16 val;
+
+ /* Setup TX and RX descriptors */
+ if ( ( rc = pcnet32_setup_tx_resources ( priv ) ) != 0 ) {
+ DBG ( "Error setting up TX resources\n" );
+ goto err_setup_tx;
+ }
+
+ if ( ( rc = pcnet32_setup_rx_resources ( priv ) ) != 0 ) {
+ DBG ( "Error setting up RX resources\n" );
+ goto err_setup_rx;
+ }
+
+ /* Reset the chip */
+ priv->a->reset ( ioaddr );
+
+ /* Switch pcnet32 to 32bit mode */
+ priv->a->write_bcr ( ioaddr, 20, PCNET32_SWSTYLE_PCNET32 );
+
+ /* Setup the interface and duplex mode */
+ pcnet32_setup_if_duplex ( priv );
+
+ /* Disable interrupts */
+ val = priv->a->read_csr ( ioaddr, 3 );
+ val |= BablMask | MissFrameMask | RxIntMask | TxIntMask | InitDoneMask;
+ priv->a->write_csr ( ioaddr, 3, val );
+
+ /* Setup initialization block */
+ pcnet32_setup_init_block ( priv );
+
+ /* Fill in the address of the initialization block */
+ priv->a->write_csr ( ioaddr, 1,
+ ( virt_to_bus ( &priv->init_block ) ) & 0xffff );
+ priv->a->write_csr ( ioaddr, 2,
+ ( virt_to_bus ( &priv->init_block ) ) >> 16 );
+
+ /* Enable Auto-Pad, disable interrupts */
+ priv->a->write_csr ( ioaddr, 4, 0x0915 );
+
+ pcnet32_hw_start ( priv );
+
+ return 0;
+
+err_setup_rx:
+ pcnet32_free_tx_resources ( priv );
+err_setup_tx:
+ priv->a->reset( priv->pci_dev->ioaddr );
+ return rc;
+}
+
+/**
+ * transmit - Transmit a packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ */
+static int
+pcnet32_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
+{
+ struct pcnet32_private *priv = netdev_priv ( netdev );
+ unsigned long ioaddr = priv->pci_dev->ioaddr;
+ uint32_t tx_len = iob_len ( iobuf );
+ struct pcnet32_tx_desc *tx_curr_desc;
+
+ DBGP ( "pcnet32_transmit\n" );
+
+ if ( priv->tx_fill_ctr == TX_RING_SIZE ) {
+ DBG ( "Tx overflow\n" );
+ return -ENOTSUP;
+ }
+
+ priv->tx_iobuf[priv->tx_curr] = iobuf;
+
+ tx_curr_desc = priv->tx_base + priv->tx_curr;
+
+ /* Configure current descriptor to transmit packet */
+ tx_curr_desc->length = cpu_to_le16 ( -tx_len );
+ tx_curr_desc->misc = 0x00000000;
+ tx_curr_desc->base = cpu_to_le32 ( virt_to_bus ( iobuf->data ) );
+
+ /* Owner changes after the other status fields are set */
+ wmb();
+ tx_curr_desc->status =
+ cpu_to_le16 ( DescOwn | StartOfPacket | EndOfPacket );
+
+ /* Trigger an immediate send poll */
+ priv->a->write_csr ( ioaddr, 0,
+ ( priv->irq_enabled ? IntEnable : 0 ) | TxDemand );
+
+ /* Point to the next free descriptor */
+ priv->tx_curr = ( priv->tx_curr + 1 ) % TX_RING_SIZE;
+
+ /* Increment number of tx descriptors in use */
+ priv->tx_fill_ctr++;
+
+ return 0;
+}
+
+/**
+ * pcnet32_process_tx_packets - Checks for successfully sent packets,
+ * reports them to iPXE with netdev_tx_complete()
+ *
+ * @v netdev Network device
+ */
+static void
+pcnet32_process_tx_packets ( struct net_device *netdev )
+{
+ struct pcnet32_private *priv = netdev_priv ( netdev );
+ struct pcnet32_tx_desc *tx_curr_desc;
+
+ DBGP ( "pcnet32_process_tx_packets\n" );
+
+ while ( priv->tx_tail != priv->tx_curr ) {
+ tx_curr_desc = priv->tx_base + priv->tx_tail;
+
+ u16 status = le16_to_cpu ( tx_curr_desc->status );
+
+ DBG ( "Before OWN bit check, status: %#08x\n", status );
+
+ /* Skip this descriptor if hardware still owns it */
+ if ( status & DescOwn )
+ break;
+
+ DBG ( "Transmitted packet.\n" );
+ DBG ( "priv->tx_fill_ctr= %d\n", priv->tx_fill_ctr );
+ DBG ( "priv->tx_tail = %d\n", priv->tx_tail );
+ DBG ( "priv->tx_curr = %d\n", priv->tx_curr );
+ DBG ( "tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
+
+ /* This packet is ready for completion */
+ netdev_tx_complete ( netdev, priv->tx_iobuf[priv->tx_tail]);
+
+ /* Clear the descriptor */
+ memset ( tx_curr_desc, 0, sizeof(*tx_curr_desc) );
+
+ /* Reduce the number of tx descriptors in use */
+ priv->tx_fill_ctr--;
+
+ /* Go to next available descriptor */
+ priv->tx_tail = ( priv->tx_tail + 1 ) % TX_RING_SIZE;
+ }
+}
+
+/**
+ * pcnet32_process_rx_packets - Checks for received packets, reports them
+ * to iPXE with netdev_rx() or netdev_rx_err() if there was an error receiving
+ * the packet
+ *
+ * @v netdev Network device
+ */
+static void
+pcnet32_process_rx_packets ( struct net_device *netdev )
+{
+ struct pcnet32_private *priv = netdev_priv ( netdev );
+ struct pcnet32_rx_desc *rx_curr_desc;
+ u16 status;
+ u32 len;
+ int i;
+
+ DBGP ( "pcnet32_process_rx_packets\n" );
+
+ for ( i = 0; i < RX_RING_SIZE; i++ ) {
+ rx_curr_desc = priv->rx_base + priv->rx_curr;
+
+ status = le16_to_cpu ( rx_curr_desc->status );
+ rmb();
+
+ DBG ( "Before OWN bit check, status: %#08x\n", status );
+
+ /* Skip this descriptor if hardware still owns it */
+ if ( status & DescOwn )
+ break;
+
+ /* We own the descriptor, but it has not been refilled yet */
+ if ( priv->rx_iobuf[priv->rx_curr] == NULL )
+ break;
+
+ DBG ( "Received packet.\n" );
+ DBG ( "priv->rx_curr = %d\n", priv->rx_curr );
+ DBG ( "rx_len = %d\n",
+ ( le32_to_cpu ( rx_curr_desc->msg_length ) & 0xfff ) - 4 );
+ DBG ( "rx_curr_desc = %#08lx\n",
+ virt_to_bus ( rx_curr_desc ) );
+
+ /* Check ERR bit */
+ if ( status & 0x4000 ) {
+ netdev_rx_err ( netdev, priv->rx_iobuf[priv->rx_curr],
+ -EINVAL );
+ DBG ( "Corrupted packet received!\n");
+ } else {
+ /* Adjust size of the iobuf to reflect received data */
+ len = ( le32_to_cpu ( rx_curr_desc->msg_length ) & 0xfff ) - 4;
+ iob_put ( priv->rx_iobuf[priv->rx_curr], len );
+
+ /* Add this packet to the receive queue */
+ netdev_rx ( netdev, priv->rx_iobuf[priv->rx_curr] );
+ }
+
+ /* Invalidate iobuf and descriptor */
+ priv->rx_iobuf[priv->rx_curr] = NULL;
+ memset ( rx_curr_desc, 0, sizeof(*rx_curr_desc) );
+
+ /* Point to the next free descriptor */
+ priv->rx_curr = ( priv->rx_curr + 1 ) % RX_RING_SIZE;
+ }
+
+ /* Allocate new iobufs where needed */
+ pcnet32_refill_rx_ring ( priv );
+}
+
+/**
+ * poll - Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void
+pcnet32_poll ( struct net_device *netdev )
+{
+ struct pcnet32_private *priv = netdev_priv ( netdev );
+ unsigned long ioaddr = priv->pci_dev->ioaddr;
+ u16 status;
+
+ DBGP ( "pcnet32_poll\n" );
+
+ status = priv->a->read_csr ( ioaddr, 0 );
+
+ /* Clear interrupts */
+ priv->a->write_csr ( ioaddr, 0, status );
+
+ DBG ( "pcnet32_poll: mask = %#04x, status = %#04x\n",
+ priv->a->read_csr ( ioaddr, 3 ), status );
+
+ /* Return when RINT or TINT are not set */
+ if ( ( status & 0x0500 ) == 0x0000 )
+ return;
+
+ /* Process transmitted packets */
+ pcnet32_process_tx_packets ( netdev );
+
+ /* Process received packets */
+ pcnet32_process_rx_packets ( netdev );
+}
+
+/**
+ * close - Disable network interface
+ *
+ * @v netdev network interface device structure
+ **/
+static void
+pcnet32_close ( struct net_device *netdev )
+{
+ struct pcnet32_private *priv = netdev_priv ( netdev );
+ unsigned long ioaddr = priv->pci_dev->ioaddr;
+
+ DBGP ( "pcnet32_close\n" );
+
+ /* Reset the chip */
+ pcnet32_wio_reset ( ioaddr );
+
+ /* Stop the PCNET32 - it occasionally polls memory if we don't */
+ priv->a->write_csr ( ioaddr, 0, Stop );
+
+ /* Switch back to 16bit mode to avoid problems with dumb
+ * DOS packet driver after a warm reboot */
+ priv->a->write_bcr ( ioaddr, 20, PCNET32_SWSTYLE_LANCE );
+
+ pcnet32_free_rx_resources ( priv );
+ pcnet32_free_tx_resources ( priv );
+}
+
+static void pcnet32_irq_enable ( struct pcnet32_private *priv )
+{
+ unsigned long ioaddr = priv->pci_dev->ioaddr;
+ u16 val;
+
+ DBGP ( "pcnet32_irq_enable\n" );
+
+ /* Enable TINT and RINT masks */
+ val = priv->a->read_csr ( ioaddr, 3 );
+ val &= ~( RxIntMask | TxIntMask );
+ priv->a->write_csr ( ioaddr, 3, val );
+
+ /* Enable interrupts */
+ priv->a->write_csr ( ioaddr, 0, IntEnable );
+
+ priv->irq_enabled = 1;
+}
+
+static void pcnet32_irq_disable ( struct pcnet32_private *priv )
+{
+ unsigned long ioaddr = priv->pci_dev->ioaddr;
+
+ DBGP ( "pcnet32_irq_disable\n" );
+
+ priv->a->write_csr ( ioaddr, 0, 0x0000 );
+
+ priv->irq_enabled = 0;
+}
+
+/**
+ * irq - enable or disable interrupts
+ *
+ * @v netdev network adapter
+ * @v action requested interrupt action
+ **/
+static void
+pcnet32_irq ( struct net_device *netdev, int action )
+{
+ struct pcnet32_private *priv = netdev_priv ( netdev );
+
+ DBGP ( "pcnet32_irq\n" );
+
+ switch ( action ) {
+ case 0:
+ pcnet32_irq_disable ( priv );
+ break;
+ default:
+ pcnet32_irq_enable ( priv );
+ break;
+ }
+}
+
+static struct net_device_operations pcnet32_operations = {
+ .open = pcnet32_open,
+ .transmit = pcnet32_transmit,
+ .poll = pcnet32_poll,
+ .close = pcnet32_close,
+ .irq = pcnet32_irq,
+};
+
+/**
+ * probe - Initial configuration of NIC
+ *
+ * @v pdev PCI device
+ * @v ent PCI IDs
+ *
+ * @ret rc Return status code
+ **/
+static int
+pcnet32_probe ( struct pci_device *pdev )
+{
+ struct net_device *netdev;
+ struct pcnet32_private *priv;
+ unsigned long ioaddr;
+ int rc;
+
+ DBGP ( "pcnet32_probe\n" );
+
+ DBG ( "Found %s, vendor = %#04x, device = %#04x\n",
+ pdev->id->name, pdev->id->vendor, pdev->id->device );
+
+ /* Allocate our private data */
+ netdev = alloc_etherdev ( sizeof ( *priv ) );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ goto err_alloc_etherdev;
+ }
+
+ /* Link our operations to the netdev struct */
+ netdev_init ( netdev, &pcnet32_operations );
+
+ /* Link the PCI device to the netdev struct */
+ pci_set_drvdata ( pdev, netdev );
+ netdev->dev = &pdev->dev;
+
+ /* Get a reference to our private data */
+ priv = netdev_priv ( netdev );
+
+ /* We'll need these set up for the rest of the routines */
+ priv->pci_dev = pdev;
+ priv->netdev = netdev;
+
+ ioaddr = pdev->ioaddr;
+
+ /* Only use irqs under UNDI */
+ priv->irq_enabled = 0;
+
+ /* Reset the chip */
+ pcnet32_wio_reset ( ioaddr );
+
+ if ( ( rc = pcnet32_set_ops ( priv ) ) != 0 ) {
+ DBG ( "Setting driver operations failed\n");
+ goto err_set_ops;
+ }
+
+ if ( ( rc = pcnet32_chip_detect ( priv ) ) != 0 ) {
+ DBG ( "pcnet32_chip_detect failed\n" );
+ goto err_chip_detect;
+ }
+
+ /* Enter bus mastering mode */
+ adjust_pci_device ( pdev );
+
+ /* Verify and get MAC address */
+ if ( ( rc = pcnet32_setup_mac_addr ( priv ) ) != 0 ) {
+ DBG ( "Setting MAC address failed\n" );
+ goto err_mac_addr;
+ }
+
+ DBG ( "IO Addr 0x%lX, MAC Addr %s\n", ioaddr,
+ eth_ntoa ( netdev->hw_addr ) );
+
+ priv->options = PCNET32_PORT_ASEL;
+
+ /* Detect special T1/E1 WAN card by checking for MAC address */
+ if ( netdev->hw_addr[0] == 0x00 &&
+ netdev->hw_addr[1] == 0xE0 &&
+ netdev->hw_addr[2] == 0x75 )
+ priv->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
+
+ /* Probe the PHY so we can check link state and speed */
+ pcnet32_setup_probe_phy ( priv );
+
+ if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
+ DBG ( "Error registering netdev\n" );
+ goto err_register;
+ }
+
+ netdev_link_up ( netdev );
+
+ return 0;
+
+err_register:
+ netdev_put ( netdev );
+err_chip_detect:
+err_set_ops:
+err_alloc_etherdev:
+err_mac_addr:
+ return rc;
+}
+
+/**
+ * remove - Device Removal Routine
+ *
+ * @v pdev PCI device information struct
+ **/
+static void
+pcnet32_remove ( struct pci_device *pdev )
+{
+ struct net_device *netdev = pci_get_drvdata ( pdev );
+ unsigned long ioaddr = pdev->ioaddr;
+
+ DBGP ( "pcnet32_remove\n" );
+
+ /* Reset the chip */
+ pcnet32_wio_reset ( ioaddr );
+
+ unregister_netdev ( netdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+static struct pci_device_id pcnet32_nics[] = {
+ PCI_ROM(0x1022, 0x2000, "pcnet32", "AMD PCnet/PCI", 0),
+ PCI_ROM(0x1022, 0x2625, "pcnetfastiii", "AMD PCNet FAST III", 0),
+ PCI_ROM(0x1022, 0x2001, "amdhomepna", "AMD PCnet/HomePNA", 0),
+};
+
+struct pci_driver pcnet32_driver __pci_driver = {
+ .ids = pcnet32_nics,
+ .id_count = ARRAY_SIZE ( pcnet32_nics ),
+ .probe = pcnet32_probe,
+ .remove = pcnet32_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/pcnet32.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/pcnet32.h
new file mode 100644
index 00000000..bd03cbc0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/pcnet32.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2010 Andrei Faur <da3drus@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef _PCNET32_H_
+#define _PCNET32_H_
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/*
+ * Set the number of Tx and Rx buffers, using Log_2(# buffers).
+ * Set default values to 16 Tx buffers and 32 Rx buffers.
+ */
+#define PCNET32_LOG_TX_BUFFERS 4
+#define PCNET32_LOG_RX_BUFFERS 5
+
+/* Maximum number of descriptor rings is 512 */
+#define PCNET32_LOG_MAX_TX_BUFFERS 9
+#define PCNET32_LOG_MAX_RX_BUFFERS 9
+
+#define TX_RING_SIZE ( 1 << ( PCNET32_LOG_TX_BUFFERS ) )
+#define TX_MAX_RING_SIZE ( 1 << ( PCNET32_LOG_MAX_TX_BUFFERS ) )
+
+#define RX_RING_SIZE ( 1 << ( PCNET32_LOG_RX_BUFFERS ) )
+#define RX_MAX_RING_SIZE ( 1 << ( PCNET32_LOG_MAX_RX_BUFFERS ) )
+
+#define RX_RING_BYTES ( RX_RING_SIZE * sizeof(struct pcnet32_rx_desc ) )
+#define TX_RING_BYTES ( TX_RING_SIZE * sizeof(struct pcnet32_tx_desc ) )
+
+#define PKT_BUF_SIZE 1536
+
+#define RX_RING_ALIGN 16
+#define TX_RING_ALIGN 16
+
+#define INIT_BLOCK_ALIGN 32
+
+#define PCNET32_WIO_RDP 0x10
+#define PCNET32_WIO_RAP 0x12
+#define PCNET32_WIO_RESET 0x14
+#define PCNET32_WIO_BDP 0x16
+
+#define PCNET32_DWIO_RDP 0x10
+#define PCNET32_DWIO_RAP 0x14
+#define PCNET32_DWIO_RESET 0x18
+#define PCNET32_DWIO_BDP 0x1C
+
+#define PCNET32_PORT_AUI 0x00
+#define PCNET32_PORT_10BT 0x01
+#define PCNET32_PORT_GPSI 0x02
+#define PCNET32_PORT_MII 0x03
+
+#define PCNET32_PORT_PORTSEL 0x03
+#define PCNET32_PORT_ASEL 0x04
+#define PCNET32_PORT_100 0x40
+#define PCNET32_PORT_FD 0x80
+
+#define PCNET32_SWSTYLE_LANCE 0x00
+#define PCNET32_SWSTYLE_ILACC 0x01
+#define PCNET32_SWSTYLE_PCNET32 0x02
+
+#define PCNET32_MAX_PHYS 32
+
+#ifndef PCI_VENDOR_ID_AT
+#define PCI_VENDOR_ID_AT 0x1259
+#endif
+
+#ifndef PCI_SUBDEVICE_ID_AT_2700FX
+#define PCI_SUBDEVICE_ID_AT_2700FX 0x2701
+#endif
+
+#ifndef PCI_SUBDEVICE_ID_AT_2701FX
+#define PCI_SUBDEVICE_ID_AT_2701FX 0x2703
+#endif
+
+struct pcnet32_rx_desc {
+ u32 base;
+ s16 buf_length;
+ s16 status;
+ u32 msg_length;
+ u32 reserved;
+};
+
+struct pcnet32_tx_desc {
+ u32 base;
+ s16 length;
+ s16 status;
+ u32 misc;
+ u32 reserved;
+};
+
+struct pcnet32_init_block {
+ u16 mode;
+ u16 tlen_rlen;
+ u8 phys_addr[6];
+ u16 reserved;
+ u32 filter[2];
+ u32 rx_ring;
+ u32 tx_ring;
+};
+
+struct pcnet32_access {
+ u16 ( *read_csr ) ( unsigned long, int );
+ void ( *write_csr ) ( unsigned long, int, u16 );
+ u16 ( *read_bcr ) ( unsigned long, int );
+ void ( *write_bcr ) ( unsigned long, int, u16 );
+ u16 ( *read_rap ) ( unsigned long );
+ void ( *write_rap ) ( unsigned long, u16 );
+ void ( *reset ) ( unsigned long );
+};
+
+struct pcnet32_private {
+ struct pcnet32_init_block init_block __attribute__((aligned(32)));
+ struct pci_device *pci_dev;
+ struct net_device *netdev;
+
+ struct io_buffer *rx_iobuf[RX_RING_SIZE];
+ struct io_buffer *tx_iobuf[TX_RING_SIZE];
+
+ struct pcnet32_rx_desc *rx_base;
+ struct pcnet32_tx_desc *tx_base;
+ uint32_t rx_curr;
+ uint32_t tx_curr;
+ uint32_t tx_tail;
+ uint32_t tx_fill_ctr;
+
+ struct pcnet32_access *a;
+ int options;
+ unsigned int mii:1,
+ full_duplex:1;
+
+ unsigned short chip_version;
+
+ char irq_enabled;
+};
+
+enum pcnet32_desc_status_bit {
+ DescOwn = (1 << 15),
+ StartOfPacket = (1 << 9),
+ EndOfPacket = (1 << 8)
+};
+
+enum pcnet32_register_content {
+ /* CSR0 bits - Controller status register */
+ RxInt = (1 << 10),
+ TxInt = (1 << 9),
+ InitDone = (1 << 8),
+ IntFlag = (1 << 7),
+ IntEnable = (1 << 6),
+ TxDemand = (1 << 3),
+ Stop = (1 << 2),
+ Strt = (1 << 1),
+ Init = (1 << 0),
+
+ /* CSR3 bits - Controller status register */
+ BablMask = (1 << 14),
+ MissFrameMask = (1 << 12),
+ MemErrMask = (1 << 11),
+ RxIntMask = (1 << 10),
+ TxIntMask = (1 << 9),
+ InitDoneMask = (1 << 8)
+
+};
+
+#endif /* _PCNET32_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/nx_bitops.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/nx_bitops.h
new file mode 100644
index 00000000..40686326
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/nx_bitops.h
@@ -0,0 +1,194 @@
+#ifndef _NX_BITOPS_H
+#define _NX_BITOPS_H
+
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * NetXen bit operations
+ *
+ */
+
+/** Datatype used to represent a bit in the pseudo-structures */
+typedef unsigned char pseudo_bit_t;
+
+/**
+ * Wrapper structure for pseudo_bit_t structures
+ *
+ * This structure provides a wrapper around pseudo_bit_t structures.
+ * It has the correct size, and also encapsulates type information
+ * about the underlying pseudo_bit_t-based structure, which allows the
+ * NX_FILL etc. macros to work without requiring explicit type
+ * information.
+ */
+#define NX_PSEUDO_BIT_STRUCT( _structure ) \
+ union { \
+ uint8_t bytes[ sizeof ( _structure ) / 8 ]; \
+ uint64_t qwords[ sizeof ( _structure ) / 64 ]; \
+ _structure *dummy[0]; \
+ } u;
+
+/** Get pseudo_bit_t structure type from wrapper structure pointer */
+#define NX_PSEUDO_STRUCT( _ptr ) \
+ typeof ( *((_ptr)->u.dummy[0]) )
+
+/** Bit offset of a field within a pseudo_bit_t structure */
+#define NX_BIT_OFFSET( _ptr, _field ) \
+ offsetof ( NX_PSEUDO_STRUCT ( _ptr ), _field )
+
+/** Bit width of a field within a pseudo_bit_t structure */
+#define NX_BIT_WIDTH( _ptr, _field ) \
+ sizeof ( ( ( NX_PSEUDO_STRUCT ( _ptr ) * ) NULL )->_field )
+
+/** Qword offset of a field within a pseudo_bit_t structure */
+#define NX_QWORD_OFFSET( _ptr, _field ) \
+ ( NX_BIT_OFFSET ( _ptr, _field ) / 64 )
+
+/** Qword bit offset of a field within a pseudo_bit_t structure
+ *
+ * Yes, using mod-64 would work, but would lose the check for the
+ * error of specifying a mismatched field name and qword index.
+ */
+#define NX_QWORD_BIT_OFFSET( _ptr, _index, _field ) \
+ ( NX_BIT_OFFSET ( _ptr, _field ) - ( 64 * (_index) ) )
+
+/** Bit mask for a field within a pseudo_bit_t structure */
+#define NX_BIT_MASK( _ptr, _field ) \
+ ( ( ~( ( uint64_t ) 0 ) ) >> \
+ ( 64 - NX_BIT_WIDTH ( _ptr, _field ) ) )
+
+/*
+ * Assemble native-endian qword from named fields and values
+ *
+ */
+
+#define NX_ASSEMBLE_1( _ptr, _index, _field, _value ) \
+ ( ( ( uint64_t) (_value) ) << \
+ NX_QWORD_BIT_OFFSET ( _ptr, _index, _field ) )
+
+#define NX_ASSEMBLE_2( _ptr, _index, _field, _value, ... ) \
+ ( NX_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ NX_ASSEMBLE_1 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_ASSEMBLE_3( _ptr, _index, _field, _value, ... ) \
+ ( NX_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ NX_ASSEMBLE_2 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_ASSEMBLE_4( _ptr, _index, _field, _value, ... ) \
+ ( NX_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ NX_ASSEMBLE_3 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_ASSEMBLE_5( _ptr, _index, _field, _value, ... ) \
+ ( NX_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ NX_ASSEMBLE_4 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_ASSEMBLE_6( _ptr, _index, _field, _value, ... ) \
+ ( NX_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ NX_ASSEMBLE_5 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_ASSEMBLE_7( _ptr, _index, _field, _value, ... ) \
+ ( NX_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ NX_ASSEMBLE_6 ( _ptr, _index, __VA_ARGS__ ) )
+
+/*
+ * Build native-endian (positive) qword bitmasks from named fields
+ *
+ */
+
+#define NX_MASK_1( _ptr, _index, _field ) \
+ ( NX_BIT_MASK ( _ptr, _field ) << \
+ NX_QWORD_BIT_OFFSET ( _ptr, _index, _field ) )
+
+#define NX_MASK_2( _ptr, _index, _field, ... ) \
+ ( NX_MASK_1 ( _ptr, _index, _field ) | \
+ NX_MASK_1 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_MASK_3( _ptr, _index, _field, ... ) \
+ ( NX_MASK_1 ( _ptr, _index, _field ) | \
+ NX_MASK_2 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_MASK_4( _ptr, _index, _field, ... ) \
+ ( NX_MASK_1 ( _ptr, _index, _field ) | \
+ NX_MASK_3 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_MASK_5( _ptr, _index, _field, ... ) \
+ ( NX_MASK_1 ( _ptr, _index, _field ) | \
+ NX_MASK_4 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_MASK_6( _ptr, _index, _field, ... ) \
+ ( NX_MASK_1 ( _ptr, _index, _field ) | \
+ NX_MASK_5 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_MASK_7( _ptr, _index, _field, ... ) \
+ ( NX_MASK_1 ( _ptr, _index, _field ) | \
+ NX_MASK_6 ( _ptr, _index, __VA_ARGS__ ) )
+
+/*
+ * Populate big-endian qwords from named fields and values
+ *
+ */
+
+#define NX_FILL( _ptr, _index, _assembled ) \
+ do { \
+ uint64_t *__ptr = &(_ptr)->u.qwords[(_index)]; \
+ uint64_t __assembled = (_assembled); \
+ *__ptr = cpu_to_le64 ( __assembled ); \
+ } while ( 0 )
+
+#define NX_FILL_1( _ptr, _index, ... ) \
+ NX_FILL ( _ptr, _index, NX_ASSEMBLE_1 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_FILL_2( _ptr, _index, ... ) \
+ NX_FILL ( _ptr, _index, NX_ASSEMBLE_2 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_FILL_3( _ptr, _index, ... ) \
+ NX_FILL ( _ptr, _index, NX_ASSEMBLE_3 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_FILL_4( _ptr, _index, ... ) \
+ NX_FILL ( _ptr, _index, NX_ASSEMBLE_4 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_FILL_5( _ptr, _index, ... ) \
+ NX_FILL ( _ptr, _index, NX_ASSEMBLE_5 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_FILL_6( _ptr, _index, ... ) \
+ NX_FILL ( _ptr, _index, NX_ASSEMBLE_6 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define NX_FILL_7( _ptr, _index, ... ) \
+ NX_FILL ( _ptr, _index, NX_ASSEMBLE_7 ( _ptr, _index, __VA_ARGS__ ) )
+
+/** Extract value of named field */
+#define NX_GET64( _ptr, _field ) \
+ ( { \
+ unsigned int __index = NX_QWORD_OFFSET ( _ptr, _field ); \
+ uint64_t *__ptr = &(_ptr)->u.qwords[__index]; \
+ uint64_t __value = le64_to_cpu ( *__ptr ); \
+ __value >>= \
+ NX_QWORD_BIT_OFFSET ( _ptr, __index, _field ); \
+ __value &= NX_BIT_MASK ( _ptr, _field ); \
+ __value; \
+ } )
+
+/** Extract value of named field (for fields up to the size of a long) */
+#define NX_GET( _ptr, _field ) \
+ ( ( unsigned long ) NX_GET64 ( _ptr, _field ) )
+
+#endif /* _NX_BITOPS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/nxhal_nic_interface.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/nxhal_nic_interface.h
new file mode 100644
index 00000000..f487624b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/nxhal_nic_interface.h
@@ -0,0 +1,501 @@
+FILE_LICENCE ( GPL2_ONLY );
+
+/*
+ * Data types and structure for HAL - NIC interface.
+ *
+ */
+
+#ifndef _NXHAL_NIC_INTERFACE_H_
+#define _NXHAL_NIC_INTERFACE_H_
+
+/*****************************************************************************
+ * Simple Types
+ *****************************************************************************/
+
+typedef U32 nx_reg_addr_t;
+
+/*****************************************************************************
+ * Root crb-based firmware commands
+ *****************************************************************************/
+
+/* CRB Root Command
+
+ A single set of crbs is used across all physical/virtual
+ functions for capability queries, initialization, and
+ context creation/destruction.
+
+ There are 4 CRBS:
+ Command/Response CRB
+ Argument1 CRB
+ Argument2 CRB
+ Argument3 CRB
+ Signature CRB
+
+ The cmd/rsp crb is always intiated by the host via
+ a command code and always responded by the card with
+ a response code. The cmd and rsp codes are disjoint.
+ The sequence of use is always CMD, RSP, CLEAR CMD.
+
+ The arguments are for passing in command specific
+ and response specific parameters/data.
+
+ The signature is composed of a magic value, the
+ pci function id, and a command sequence id:
+ [7:0] = pci function
+ [15:8] = version
+ [31:16] = magic of 0xcafe
+
+ The pci function allows the card to take correct
+ action for the given particular commands.
+ The firmware will attempt to detect
+ an errant driver that has died while holding
+ the root crb hardware lock. Such an error condition
+ shows up as the cmd/rsp crb stuck in a non-clear state.
+
+ Interface Sequence:
+ Host always makes requests and firmware always responds.
+ Note that data field is always set prior to command field.
+
+ [READ] CMD/RSP CRB ARGUMENT FIELD
+ Host grab lock
+ Host -> CMD optional parameter
+ FW <- (Good) RSP-OK DATA
+ FW <- (Fail) RSP-FAIL optional failure code
+ Host -> CLEAR
+ Host release lock
+
+ [WRITE] CMD/RSP CRB ARGUMENT FIELD
+ Host grab lock
+ Host -> CMD DATA
+ FW <- (Good) RSP-OK optional write status
+ FW <- (Write) RSP-FAIL optional failure code
+ Host -> CLEAR
+ Host release lock
+
+*/
+
+
+/*****************************************************************************
+ * CMD/RSP
+ *****************************************************************************/
+
+#define NX_CDRP_SIGNATURE_TO_PCIFN(sign) ((sign) & 0xff)
+#define NX_CDRP_SIGNATURE_TO_VERSION(sign) (((sign)>>8) & 0xff)
+#define NX_CDRP_SIGNATURE_TO_MAGIC(sign) (((sign)>>16) & 0xffff)
+#define NX_CDRP_SIGNATURE_VALID(sign) \
+ ( NX_CDRP_SIGNATURE_TO_MAGIC(sign) == 0xcafe && \
+ NX_CDRP_SIGNATURE_TO_PCIFN(sign) < 8)
+#define NX_CDRP_SIGNATURE_MAKE(pcifn,version) \
+ ( ((pcifn) & 0xff) | \
+ (((version) & 0xff) << 8) | \
+ (0xcafe << 16) )
+
+#define NX_CDRP_CLEAR 0x00000000
+#define NX_CDRP_CMD_BIT 0x80000000
+
+/* All responses must have the NX_CDRP_CMD_BIT cleared
+ * in the crb NX_CDRP_CRB_OFFSET. */
+#define NX_CDRP_FORM_RSP(rsp) (rsp)
+#define NX_CDRP_IS_RSP(rsp) (((rsp) & NX_CDRP_CMD_BIT) == 0)
+
+#define NX_CDRP_RSP_OK 0x00000001
+#define NX_CDRP_RSP_FAIL 0x00000002
+#define NX_CDRP_RSP_TIMEOUT 0x00000003
+
+/* All commands must have the NX_CDRP_CMD_BIT set in
+ * the crb NX_CDRP_CRB_OFFSET.
+ * The macros below do not have it explicitly set to
+ * allow their use in lookup tables */
+#define NX_CDRP_FORM_CMD(cmd) (NX_CDRP_CMD_BIT | (cmd))
+#define NX_CDRP_IS_CMD(cmd) (((cmd) & NX_CDRP_CMD_BIT) != 0)
+
+/* [CMD] Capability Vector [RSP] Capability Vector */
+#define NX_CDRP_CMD_SUBMIT_CAPABILITIES 0x00000001
+
+/* [CMD] - [RSP] Query Value */
+#define NX_CDRP_CMD_READ_MAX_RDS_PER_CTX 0x00000002
+
+/* [CMD] - [RSP] Query Value */
+#define NX_CDRP_CMD_READ_MAX_SDS_PER_CTX 0x00000003
+
+/* [CMD] - [RSP] Query Value */
+#define NX_CDRP_CMD_READ_MAX_RULES_PER_CTX 0x00000004
+
+/* [CMD] - [RSP] Query Value */
+#define NX_CDRP_CMD_READ_MAX_RX_CTX 0x00000005
+
+/* [CMD] - [RSP] Query Value */
+#define NX_CDRP_CMD_READ_MAX_TX_CTX 0x00000006
+
+/* [CMD] Rx Config DMA Addr [RSP] rcode */
+#define NX_CDRP_CMD_CREATE_RX_CTX 0x00000007
+
+/* [CMD] Rx Context Handle, Reset Kind [RSP] rcode */
+#define NX_CDRP_CMD_DESTROY_RX_CTX 0x00000008
+
+/* [CMD] Tx Config DMA Addr [RSP] rcode */
+#define NX_CDRP_CMD_CREATE_TX_CTX 0x00000009
+
+/* [CMD] Tx Context Handle, Reset Kind [RSP] rcode */
+#define NX_CDRP_CMD_DESTROY_TX_CTX 0x0000000a
+
+/* [CMD] Stat setup dma addr - [RSP] Handle, rcode */
+#define NX_CDRP_CMD_SETUP_STATISTICS 0x0000000e
+
+/* [CMD] Handle - [RSP] rcode */
+#define NX_CDRP_CMD_GET_STATISTICS 0x0000000f
+
+/* [CMD] Handle - [RSP] rcode */
+#define NX_CDRP_CMD_DELETE_STATISTICS 0x00000010
+
+#define NX_CDRP_CMD_MAX 0x00000011
+
+/*****************************************************************************
+ * Capabilities
+ *****************************************************************************/
+
+#define NX_CAP_BIT(class, bit) (1 << bit)
+
+/* Class 0 (i.e. ARGS 1)
+ */
+#define NX_CAP0_LEGACY_CONTEXT NX_CAP_BIT(0, 0)
+#define NX_CAP0_MULTI_CONTEXT NX_CAP_BIT(0, 1)
+#define NX_CAP0_LEGACY_MN NX_CAP_BIT(0, 2)
+#define NX_CAP0_LEGACY_MS NX_CAP_BIT(0, 3)
+#define NX_CAP0_CUT_THROUGH NX_CAP_BIT(0, 4)
+#define NX_CAP0_LRO NX_CAP_BIT(0, 5)
+#define NX_CAP0_LSO NX_CAP_BIT(0, 6)
+
+/* Class 1 (i.e. ARGS 2)
+ */
+#define NX_CAP1_NIC NX_CAP_BIT(1, 0)
+#define NX_CAP1_PXE NX_CAP_BIT(1, 1)
+#define NX_CAP1_CHIMNEY NX_CAP_BIT(1, 2)
+#define NX_CAP1_LSA NX_CAP_BIT(1, 3)
+#define NX_CAP1_RDMA NX_CAP_BIT(1, 4)
+#define NX_CAP1_ISCSI NX_CAP_BIT(1, 5)
+#define NX_CAP1_FCOE NX_CAP_BIT(1, 6)
+
+/* Class 2 (i.e. ARGS 3)
+ */
+
+/*****************************************************************************
+ * Rules
+ *****************************************************************************/
+
+typedef U32 nx_rx_rule_type_t;
+
+#define NX_RX_RULETYPE_DEFAULT 0
+#define NX_RX_RULETYPE_MAC 1
+#define NX_RX_RULETYPE_MAC_VLAN 2
+#define NX_RX_RULETYPE_MAC_RSS 3
+#define NX_RX_RULETYPE_MAC_VLAN_RSS 4
+#define NX_RX_RULETYPE_MAX 5
+
+typedef U32 nx_rx_rule_cmd_t;
+
+#define NX_RX_RULECMD_ADD 0
+#define NX_RX_RULECMD_REMOVE 1
+#define NX_RX_RULECMD_MAX 2
+
+typedef struct nx_rx_rule_arg_s {
+ union {
+ struct {
+ char mac[6];
+ } m;
+ struct {
+ char mac[6];
+ char vlan;
+ } mv;
+ struct {
+ char mac[6];
+ } mr;
+ struct {
+ char mac[6];
+ char vlan;
+ } mvr;
+ };
+ /* will be union of all the different args for rules */
+ U64 data;
+} nx_rx_rule_arg_t;
+
+typedef struct nx_rx_rule_s {
+ U32 id;
+ U32 active;
+ nx_rx_rule_arg_t arg;
+ nx_rx_rule_type_t type;
+} nx_rx_rule_t;
+
+/* MSG - REQUIRES TX CONTEXT */
+
+/* The rules can be added/deleted from both the
+ * host and card sides so rq/rsp are similar.
+ */
+typedef struct nx_hostmsg_rx_rule_s {
+ nx_rx_rule_cmd_t cmd;
+ nx_rx_rule_t rule;
+} nx_hostmsg_rx_rule_t;
+
+typedef struct nx_cardmsg_rx_rule_s {
+ nx_rcode_t rcode;
+ nx_rx_rule_cmd_t cmd;
+ nx_rx_rule_t rule;
+} nx_cardmsg_rx_rule_t;
+
+
+/*****************************************************************************
+ * Common to Rx/Tx contexts
+ *****************************************************************************/
+
+/*
+ * Context states
+ */
+
+typedef U32 nx_host_ctx_state_t;
+
+#define NX_HOST_CTX_STATE_FREED 0 /* Invalid state */
+#define NX_HOST_CTX_STATE_ALLOCATED 1 /* Not committed */
+/* The following states imply FW is aware of context */
+#define NX_HOST_CTX_STATE_ACTIVE 2
+#define NX_HOST_CTX_STATE_DISABLED 3
+#define NX_HOST_CTX_STATE_QUIESCED 4
+#define NX_HOST_CTX_STATE_MAX 5
+
+/*
+ * Interrupt mask crb use must be set identically on the Tx
+ * and Rx context configs across a pci function
+ */
+
+/* Rx and Tx have unique interrupt/crb */
+#define NX_HOST_INT_CRB_MODE_UNIQUE 0
+/* Rx and Tx share a common interrupt/crb */
+#define NX_HOST_INT_CRB_MODE_SHARED 1 /* <= LEGACY */
+/* Rx does not use a crb */
+#define NX_HOST_INT_CRB_MODE_NORX 2
+/* Tx does not use a crb */
+#define NX_HOST_INT_CRB_MODE_NOTX 3
+/* Neither Rx nor Tx use a crb */
+#define NX_HOST_INT_CRB_MODE_NORXTX 4
+
+/*
+ * Destroy Rx/Tx
+ */
+
+#define NX_DESTROY_CTX_RESET 0
+#define NX_DESTROY_CTX_D3_RESET 1
+#define NX_DESTROY_CTX_MAX 2
+
+
+/*****************************************************************************
+ * Tx
+ *****************************************************************************/
+
+/*
+ * Components of the host-request for Tx context creation.
+ * CRB - DOES NOT REQUIRE Rx/TX CONTEXT
+ */
+
+typedef struct nx_hostrq_cds_ring_s {
+ U64 host_phys_addr; /* Ring base addr */
+ U32 ring_size; /* Ring entries */
+ U32 rsvd; /* Padding */
+} nx_hostrq_cds_ring_t;
+
+typedef struct nx_hostrq_tx_ctx_s {
+ U64 host_rsp_dma_addr; /* Response dma'd here */
+ U64 cmd_cons_dma_addr; /* */
+ U64 dummy_dma_addr; /* */
+ U32 capabilities[4]; /* Flag bit vector */
+ U32 host_int_crb_mode; /* Interrupt crb usage */
+ U32 rsvd1; /* Padding */
+ U16 rsvd2; /* Padding */
+ U16 interrupt_ctl;
+ U16 msi_index;
+ U16 rsvd3; /* Padding */
+ nx_hostrq_cds_ring_t cds_ring; /* Desc of cds ring */
+ U8 reserved[128]; /* future expansion */
+} nx_hostrq_tx_ctx_t;
+
+typedef struct nx_cardrsp_cds_ring_s {
+ U32 host_producer_crb; /* Crb to use */
+ U32 interrupt_crb; /* Crb to use */
+} nx_cardrsp_cds_ring_t;
+
+typedef struct nx_cardrsp_tx_ctx_s {
+ U32 host_ctx_state; /* Starting state */
+ U16 context_id; /* Handle for context */
+ U8 phys_port; /* Physical id of port */
+ U8 virt_port; /* Virtual/Logical id of port */
+ nx_cardrsp_cds_ring_t cds_ring; /* Card cds settings */
+ U8 reserved[128]; /* future expansion */
+} nx_cardrsp_tx_ctx_t;
+
+#define SIZEOF_HOSTRQ_TX(HOSTRQ_TX) \
+ ( sizeof(HOSTRQ_TX))
+
+#define SIZEOF_CARDRSP_TX(CARDRSP_TX) \
+ ( sizeof(CARDRSP_TX))
+
+/*****************************************************************************
+ * Rx
+ *****************************************************************************/
+
+/*
+ * RDS ring mapping to producer crbs
+ */
+
+/* Each ring has a unique crb */
+#define NX_HOST_RDS_CRB_MODE_UNIQUE 0 /* <= LEGACY */
+
+/* All configured RDS Rings share common crb:
+ 1 Ring - same as unique
+ 2 Rings - 16, 16
+ 3 Rings - 10, 10, 10 */
+#define NX_HOST_RDS_CRB_MODE_SHARED 1
+
+/* Bit usage is specified per-ring using the
+ ring's size. Sum of bit lengths must be <= 32.
+ Packing is [Ring N] ... [Ring 1][Ring 0] */
+#define NX_HOST_RDS_CRB_MODE_CUSTOM 2
+#define NX_HOST_RDS_CRB_MODE_MAX 3
+
+
+/*
+ * RDS Ting Types
+ */
+
+#define NX_RDS_RING_TYPE_NORMAL 0
+#define NX_RDS_RING_TYPE_JUMBO 1
+#define NX_RDS_RING_TYPE_LRO 2
+#define NX_RDS_RING_TYPE_MAX 3
+
+/*
+ * Components of the host-request for Rx context creation.
+ * CRB - DOES NOT REQUIRE Rx/TX CONTEXT
+ */
+
+typedef struct nx_hostrq_sds_ring_s {
+ U64 host_phys_addr; /* Ring base addr */
+ U32 ring_size; /* Ring entries */
+ U16 msi_index;
+ U16 rsvd; /* Padding */
+} nx_hostrq_sds_ring_t;
+
+typedef struct nx_hostrq_rds_ring_s {
+ U64 host_phys_addr; /* Ring base addr */
+ U64 buff_size; /* Packet buffer size */
+ U32 ring_size; /* Ring entries */
+ U32 ring_kind; /* Class of ring */
+} nx_hostrq_rds_ring_t;
+
+typedef struct nx_hostrq_rx_ctx_s {
+ U64 host_rsp_dma_addr; /* Response dma'd here */
+ U32 capabilities[4]; /* Flag bit vector */
+ U32 host_int_crb_mode; /* Interrupt crb usage */
+ U32 host_rds_crb_mode; /* RDS crb usage */
+ /* These ring offsets are relative to data[0] below */
+ U32 rds_ring_offset; /* Offset to RDS config */
+ U32 sds_ring_offset; /* Offset to SDS config */
+ U16 num_rds_rings; /* Count of RDS rings */
+ U16 num_sds_rings; /* Count of SDS rings */
+ U16 rsvd1; /* Padding */
+ U16 rsvd2; /* Padding */
+ U8 reserved[128]; /* reserve space for future expansion*/
+ /* MUST BE 64-bit aligned.
+ The following is packed:
+ - N hostrq_rds_rings
+ - N hostrq_sds_rings */
+ char data[0];
+} nx_hostrq_rx_ctx_t;
+
+typedef struct nx_cardrsp_rds_ring_s {
+ U32 host_producer_crb; /* Crb to use */
+ U32 rsvd1; /* Padding */
+} nx_cardrsp_rds_ring_t;
+
+typedef struct nx_cardrsp_sds_ring_s {
+ U32 host_consumer_crb; /* Crb to use */
+ U32 interrupt_crb; /* Crb to use */
+} nx_cardrsp_sds_ring_t;
+
+typedef struct nx_cardrsp_rx_ctx_s {
+ /* These ring offsets are relative to data[0] below */
+ U32 rds_ring_offset; /* Offset to RDS config */
+ U32 sds_ring_offset; /* Offset to SDS config */
+ U32 host_ctx_state; /* Starting State */
+ U32 num_fn_per_port; /* How many PCI fn share the port */
+ U16 num_rds_rings; /* Count of RDS rings */
+ U16 num_sds_rings; /* Count of SDS rings */
+ U16 context_id; /* Handle for context */
+ U8 phys_port; /* Physical id of port */
+ U8 virt_port; /* Virtual/Logical id of port */
+ U8 reserved[128]; /* save space for future expansion */
+ /* MUST BE 64-bit aligned.
+ The following is packed:
+ - N cardrsp_rds_rings
+ - N cardrs_sds_rings */
+ char data[0];
+} nx_cardrsp_rx_ctx_t;
+
+#define SIZEOF_HOSTRQ_RX(HOSTRQ_RX, rds_rings, sds_rings) \
+ ( sizeof(HOSTRQ_RX) + \
+ (rds_rings)*(sizeof (nx_hostrq_rds_ring_t)) + \
+ (sds_rings)*(sizeof (nx_hostrq_sds_ring_t)) )
+
+#define SIZEOF_CARDRSP_RX(CARDRSP_RX, rds_rings, sds_rings) \
+ ( sizeof(CARDRSP_RX) + \
+ (rds_rings)*(sizeof (nx_cardrsp_rds_ring_t)) + \
+ (sds_rings)*(sizeof (nx_cardrsp_sds_ring_t)) )
+
+
+/*****************************************************************************
+ * Statistics
+ *****************************************************************************/
+
+/*
+ * The model of statistics update to use
+ */
+
+#define NX_STATISTICS_MODE_INVALID 0
+
+/* Permanent setup; Updates are only sent on explicit request
+ (NX_CDRP_CMD_GET_STATISTICS) */
+#define NX_STATISTICS_MODE_PULL 1
+
+/* Permanent setup; Updates are sent automatically and on
+ explicit request (NX_CDRP_CMD_GET_STATISTICS) */
+#define NX_STATISTICS_MODE_PUSH 2
+
+/* One time stat update. */
+#define NX_STATISTICS_MODE_SINGLE_SHOT 3
+
+#define NX_STATISTICS_MODE_MAX 4
+
+/*
+ * What set of stats
+ */
+#define NX_STATISTICS_TYPE_INVALID 0
+#define NX_STATISTICS_TYPE_NIC_RX_CORE 1
+#define NX_STATISTICS_TYPE_NIC_TX_CORE 2
+#define NX_STATISTICS_TYPE_NIC_RX_ALL 3
+#define NX_STATISTICS_TYPE_NIC_TX_ALL 4
+#define NX_STATISTICS_TYPE_MAX 5
+
+
+/*
+ * Request to setup statistics gathering.
+ * CRB - DOES NOT REQUIRE Rx/TX CONTEXT
+ */
+
+typedef struct nx_hostrq_stat_setup_s {
+ U64 host_stat_buffer; /* Where to dma stats */
+ U32 host_stat_size; /* Size of stat buffer */
+ U16 context_id; /* Which context */
+ U16 stat_type; /* What class of stats */
+ U16 stat_mode; /* When to update */
+ U16 stat_interval; /* Frequency of update */
+} nx_hostrq_stat_setup_t;
+
+
+
+#endif /* _NXHAL_NIC_INTERFACE_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/phantom.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/phantom.c
new file mode 100644
index 00000000..a55319ea
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/phantom.c
@@ -0,0 +1,2178 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ * Copyright (C) 2008 NetXen, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include <ipxe/io.h>
+#include <ipxe/malloc.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/spi.h>
+#include <ipxe/settings.h>
+#include "phantom.h"
+
+/**
+ * @file
+ *
+ * NetXen Phantom NICs
+ *
+ */
+
+/** Maximum number of ports */
+#define PHN_MAX_NUM_PORTS 8
+
+/** Maximum time to wait for command PEG to initialise
+ *
+ * BUGxxxx
+ *
+ * The command PEG will currently report initialisation complete only
+ * when at least one PHY has detected a link (so that the global PHY
+ * clock can be set to 10G/1G as appropriate). This can take a very,
+ * very long time.
+ *
+ * A future firmware revision should decouple PHY initialisation from
+ * firmware initialisation, at which point the command PEG will report
+ * initialisation complete much earlier, and this timeout can be
+ * reduced.
+ */
+#define PHN_CMDPEG_INIT_TIMEOUT_SEC 50
+
+/** Maximum time to wait for receive PEG to initialise */
+#define PHN_RCVPEG_INIT_TIMEOUT_SEC 2
+
+/** Maximum time to wait for firmware to accept a command */
+#define PHN_ISSUE_CMD_TIMEOUT_MS 2000
+
+/** Maximum time to wait for test memory */
+#define PHN_TEST_MEM_TIMEOUT_MS 100
+
+/** Maximum time to wait for CLP command to be issued */
+#define PHN_CLP_CMD_TIMEOUT_MS 500
+
+/** Link state poll frequency
+ *
+ * The link state will be checked once in every N calls to poll().
+ */
+#define PHN_LINK_POLL_FREQUENCY 4096
+
+/** Number of RX descriptors */
+#define PHN_NUM_RDS 32
+
+/** RX maximum fill level. Must be strictly less than PHN_NUM_RDS. */
+#define PHN_RDS_MAX_FILL 16
+
+/** RX buffer size */
+#define PHN_RX_BUFSIZE ( 32 /* max LL padding added by card */ + \
+ ETH_FRAME_LEN )
+
+/** Number of RX status descriptors */
+#define PHN_NUM_SDS 32
+
+/** Number of TX descriptors */
+#define PHN_NUM_CDS 8
+
+/** A Phantom descriptor ring set */
+struct phantom_descriptor_rings {
+ /** RX descriptors */
+ struct phantom_rds rds[PHN_NUM_RDS];
+ /** RX status descriptors */
+ struct phantom_sds sds[PHN_NUM_SDS];
+ /** TX descriptors */
+ union phantom_cds cds[PHN_NUM_CDS];
+ /** TX consumer index */
+ volatile uint32_t cmd_cons;
+};
+
+/** RX context creation request and response buffers */
+struct phantom_create_rx_ctx_rqrsp {
+ struct {
+ struct nx_hostrq_rx_ctx_s rx_ctx;
+ struct nx_hostrq_rds_ring_s rds;
+ struct nx_hostrq_sds_ring_s sds;
+ } __unm_dma_aligned hostrq;
+ struct {
+ struct nx_cardrsp_rx_ctx_s rx_ctx;
+ struct nx_cardrsp_rds_ring_s rds;
+ struct nx_cardrsp_sds_ring_s sds;
+ } __unm_dma_aligned cardrsp;
+};
+
+/** TX context creation request and response buffers */
+struct phantom_create_tx_ctx_rqrsp {
+ struct {
+ struct nx_hostrq_tx_ctx_s tx_ctx;
+ } __unm_dma_aligned hostrq;
+ struct {
+ struct nx_cardrsp_tx_ctx_s tx_ctx;
+ } __unm_dma_aligned cardrsp;
+};
+
+/** A Phantom NIC */
+struct phantom_nic {
+ /** BAR 0 */
+ void *bar0;
+ /** Current CRB window */
+ unsigned long crb_window;
+ /** CRB window access method */
+ unsigned long ( *crb_access ) ( struct phantom_nic *phantom,
+ unsigned long reg );
+
+
+ /** Port number */
+ unsigned int port;
+
+
+ /** RX context ID */
+ uint16_t rx_context_id;
+ /** RX descriptor producer CRB offset */
+ unsigned long rds_producer_crb;
+ /** RX status descriptor consumer CRB offset */
+ unsigned long sds_consumer_crb;
+ /** RX interrupt mask CRB offset */
+ unsigned long sds_irq_mask_crb;
+ /** RX interrupts enabled */
+ unsigned int sds_irq_enabled;
+
+ /** RX producer index */
+ unsigned int rds_producer_idx;
+ /** RX consumer index */
+ unsigned int rds_consumer_idx;
+ /** RX status consumer index */
+ unsigned int sds_consumer_idx;
+ /** RX I/O buffers */
+ struct io_buffer *rds_iobuf[PHN_RDS_MAX_FILL];
+
+
+ /** TX context ID */
+ uint16_t tx_context_id;
+ /** TX descriptor producer CRB offset */
+ unsigned long cds_producer_crb;
+
+ /** TX producer index */
+ unsigned int cds_producer_idx;
+ /** TX consumer index */
+ unsigned int cds_consumer_idx;
+ /** TX I/O buffers */
+ struct io_buffer *cds_iobuf[PHN_NUM_CDS];
+
+
+ /** Descriptor rings */
+ struct phantom_descriptor_rings *desc;
+
+
+ /** Last known link state */
+ uint32_t link_state;
+ /** Link state poll timer */
+ unsigned long link_poll_timer;
+
+
+ /** Non-volatile settings */
+ struct settings settings;
+};
+
+/** Interrupt mask registers */
+static const unsigned long phantom_irq_mask_reg[PHN_MAX_NUM_PORTS] = {
+ UNM_PCIE_IRQ_MASK_F0,
+ UNM_PCIE_IRQ_MASK_F1,
+ UNM_PCIE_IRQ_MASK_F2,
+ UNM_PCIE_IRQ_MASK_F3,
+ UNM_PCIE_IRQ_MASK_F4,
+ UNM_PCIE_IRQ_MASK_F5,
+ UNM_PCIE_IRQ_MASK_F6,
+ UNM_PCIE_IRQ_MASK_F7,
+};
+
+/** Interrupt status registers */
+static const unsigned long phantom_irq_status_reg[PHN_MAX_NUM_PORTS] = {
+ UNM_PCIE_IRQ_STATUS_F0,
+ UNM_PCIE_IRQ_STATUS_F1,
+ UNM_PCIE_IRQ_STATUS_F2,
+ UNM_PCIE_IRQ_STATUS_F3,
+ UNM_PCIE_IRQ_STATUS_F4,
+ UNM_PCIE_IRQ_STATUS_F5,
+ UNM_PCIE_IRQ_STATUS_F6,
+ UNM_PCIE_IRQ_STATUS_F7,
+};
+
+/***************************************************************************
+ *
+ * CRB register access
+ *
+ */
+
+/**
+ * Prepare for access to CRB register via 128MB BAR
+ *
+ * @v phantom Phantom NIC
+ * @v reg Register offset within abstract address space
+ * @ret offset Register offset within PCI BAR0
+ */
+static unsigned long phantom_crb_access_128m ( struct phantom_nic *phantom,
+ unsigned long reg ) {
+ unsigned long offset = ( 0x6000000 + ( reg & 0x1ffffff ) );
+ uint32_t window = ( reg & 0x2000000 );
+ uint32_t verify_window;
+
+ if ( phantom->crb_window != window ) {
+
+ /* Write to the CRB window register */
+ writel ( window, phantom->bar0 + UNM_128M_CRB_WINDOW );
+
+ /* Ensure that the write has reached the card */
+ verify_window = readl ( phantom->bar0 + UNM_128M_CRB_WINDOW );
+ assert ( verify_window == window );
+
+ /* Record new window */
+ phantom->crb_window = window;
+ }
+
+ return offset;
+}
+
+/**
+ * Prepare for access to CRB register via 32MB BAR
+ *
+ * @v phantom Phantom NIC
+ * @v reg Register offset within abstract address space
+ * @ret offset Register offset within PCI BAR0
+ */
+static unsigned long phantom_crb_access_32m ( struct phantom_nic *phantom,
+ unsigned long reg ) {
+ unsigned long offset = ( reg & 0x1ffffff );
+ uint32_t window = ( reg & 0x2000000 );
+ uint32_t verify_window;
+
+ if ( phantom->crb_window != window ) {
+
+ /* Write to the CRB window register */
+ writel ( window, phantom->bar0 + UNM_32M_CRB_WINDOW );
+
+ /* Ensure that the write has reached the card */
+ verify_window = readl ( phantom->bar0 + UNM_32M_CRB_WINDOW );
+ assert ( verify_window == window );
+
+ /* Record new window */
+ phantom->crb_window = window;
+ }
+
+ return offset;
+}
+
+/**
+ * Prepare for access to CRB register via 2MB BAR
+ *
+ * @v phantom Phantom NIC
+ * @v reg Register offset within abstract address space
+ * @ret offset Register offset within PCI BAR0
+ */
+static unsigned long phantom_crb_access_2m ( struct phantom_nic *phantom,
+ unsigned long reg ) {
+ static const struct {
+ uint8_t block;
+ uint16_t window_hi;
+ } reg_window_hi[] = {
+ { UNM_CRB_BLK_PCIE, 0x773 },
+ { UNM_CRB_BLK_CAM, 0x416 },
+ { UNM_CRB_BLK_ROMUSB, 0x421 },
+ { UNM_CRB_BLK_TEST, 0x295 },
+ { UNM_CRB_BLK_PEG_0, 0x340 },
+ { UNM_CRB_BLK_PEG_1, 0x341 },
+ { UNM_CRB_BLK_PEG_2, 0x342 },
+ { UNM_CRB_BLK_PEG_3, 0x343 },
+ { UNM_CRB_BLK_PEG_4, 0x34b },
+ };
+ unsigned int block = UNM_CRB_BLK ( reg );
+ unsigned long offset = UNM_CRB_OFFSET ( reg );
+ uint32_t window;
+ uint32_t verify_window;
+ unsigned int i;
+
+ for ( i = 0 ; i < ( sizeof ( reg_window_hi ) /
+ sizeof ( reg_window_hi[0] ) ) ; i++ ) {
+
+ if ( reg_window_hi[i].block != block )
+ continue;
+
+ window = ( ( reg_window_hi[i].window_hi << 20 ) |
+ ( offset & 0x000f0000 ) );
+
+ if ( phantom->crb_window != window ) {
+
+ /* Write to the CRB window register */
+ writel ( window, phantom->bar0 + UNM_2M_CRB_WINDOW );
+
+ /* Ensure that the write has reached the card */
+ verify_window = readl ( phantom->bar0 +
+ UNM_2M_CRB_WINDOW );
+ assert ( verify_window == window );
+
+ /* Record new window */
+ phantom->crb_window = window;
+ }
+
+ return ( 0x1e0000 + ( offset & 0xffff ) );
+ }
+
+ assert ( 0 );
+ return 0;
+}
+
+/**
+ * Read from Phantom CRB register
+ *
+ * @v phantom Phantom NIC
+ * @v reg Register offset within abstract address space
+ * @ret value Register value
+ */
+static uint32_t phantom_readl ( struct phantom_nic *phantom,
+ unsigned long reg ) {
+ unsigned long offset;
+
+ offset = phantom->crb_access ( phantom, reg );
+ return readl ( phantom->bar0 + offset );
+}
+
+/**
+ * Write to Phantom CRB register
+ *
+ * @v phantom Phantom NIC
+ * @v value Register value
+ * @v reg Register offset within abstract address space
+ */
+static void phantom_writel ( struct phantom_nic *phantom, uint32_t value,
+ unsigned long reg ) {
+ unsigned long offset;
+
+ offset = phantom->crb_access ( phantom, reg );
+ writel ( value, phantom->bar0 + offset );
+}
+
+/**
+ * Write to Phantom CRB HI/LO register pair
+ *
+ * @v phantom Phantom NIC
+ * @v value Register value
+ * @v lo_offset LO register offset within CRB
+ * @v hi_offset HI register offset within CRB
+ */
+static inline void phantom_write_hilo ( struct phantom_nic *phantom,
+ uint64_t value,
+ unsigned long lo_offset,
+ unsigned long hi_offset ) {
+ uint32_t lo = ( value & 0xffffffffUL );
+ uint32_t hi = ( value >> 32 );
+
+ phantom_writel ( phantom, lo, lo_offset );
+ phantom_writel ( phantom, hi, hi_offset );
+}
+
+/***************************************************************************
+ *
+ * Firmware message buffer access (for debug)
+ *
+ */
+
+/**
+ * Read from Phantom test memory
+ *
+ * @v phantom Phantom NIC
+ * @v offset Offset within test memory
+ * @v buf 8-byte buffer to fill
+ * @ret rc Return status code
+ */
+static int phantom_read_test_mem_block ( struct phantom_nic *phantom,
+ unsigned long offset,
+ uint32_t buf[2] ) {
+ unsigned int retries;
+ uint32_t test_control;
+
+ phantom_write_hilo ( phantom, offset, UNM_TEST_ADDR_LO,
+ UNM_TEST_ADDR_HI );
+ phantom_writel ( phantom, UNM_TEST_CONTROL_ENABLE, UNM_TEST_CONTROL );
+ phantom_writel ( phantom,
+ ( UNM_TEST_CONTROL_ENABLE | UNM_TEST_CONTROL_START ),
+ UNM_TEST_CONTROL );
+
+ for ( retries = 0 ; retries < PHN_TEST_MEM_TIMEOUT_MS ; retries++ ) {
+ test_control = phantom_readl ( phantom, UNM_TEST_CONTROL );
+ if ( ( test_control & UNM_TEST_CONTROL_BUSY ) == 0 ) {
+ buf[0] = phantom_readl ( phantom, UNM_TEST_RDDATA_LO );
+ buf[1] = phantom_readl ( phantom, UNM_TEST_RDDATA_HI );
+ return 0;
+ }
+ mdelay ( 1 );
+ }
+
+ DBGC ( phantom, "Phantom %p timed out waiting for test memory\n",
+ phantom );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Read single byte from Phantom test memory
+ *
+ * @v phantom Phantom NIC
+ * @v offset Offset within test memory
+ * @ret byte Byte read, or negative error
+ */
+static int phantom_read_test_mem ( struct phantom_nic *phantom,
+ unsigned long offset ) {
+ static union {
+ uint8_t bytes[8];
+ uint32_t dwords[2];
+ } cache;
+ static unsigned long cache_offset = -1UL;
+ unsigned long sub_offset;
+ int rc;
+
+ sub_offset = ( offset & ( sizeof ( cache ) - 1 ) );
+ offset = ( offset & ~( sizeof ( cache ) - 1 ) );
+
+ if ( cache_offset != offset ) {
+ if ( ( rc = phantom_read_test_mem_block ( phantom, offset,
+ cache.dwords )) !=0 )
+ return rc;
+ cache_offset = offset;
+ }
+
+ return cache.bytes[sub_offset];
+}
+
+/**
+ * Dump Phantom firmware dmesg log
+ *
+ * @v phantom Phantom NIC
+ * @v log Log number
+ * @v max_lines Maximum number of lines to show, or -1 to show all
+ * @ret rc Return status code
+ */
+static int phantom_dmesg ( struct phantom_nic *phantom, unsigned int log,
+ unsigned int max_lines ) {
+ uint32_t head;
+ uint32_t tail;
+ uint32_t sig;
+ uint32_t offset;
+ int byte;
+
+ /* Optimise out for non-debug builds */
+ if ( ! DBG_LOG )
+ return 0;
+
+ /* Locate log */
+ head = phantom_readl ( phantom, UNM_CAM_RAM_DMESG_HEAD ( log ) );
+ tail = phantom_readl ( phantom, UNM_CAM_RAM_DMESG_TAIL ( log ) );
+ sig = phantom_readl ( phantom, UNM_CAM_RAM_DMESG_SIG ( log ) );
+ DBGC ( phantom, "Phantom %p firmware dmesg buffer %d (%08x-%08x)\n",
+ phantom, log, head, tail );
+ assert ( ( head & 0x07 ) == 0 );
+ if ( sig != UNM_CAM_RAM_DMESG_SIG_MAGIC ) {
+ DBGC ( phantom, "Warning: bad signature %08x (want %08lx)\n",
+ sig, UNM_CAM_RAM_DMESG_SIG_MAGIC );
+ }
+
+ /* Locate start of last (max_lines) lines */
+ for ( offset = tail ; offset > head ; offset-- ) {
+ if ( ( byte = phantom_read_test_mem ( phantom,
+ ( offset - 1 ) ) ) < 0 )
+ return byte;
+ if ( ( byte == '\n' ) && ( max_lines-- == 0 ) )
+ break;
+ }
+
+ /* Print lines */
+ for ( ; offset < tail ; offset++ ) {
+ if ( ( byte = phantom_read_test_mem ( phantom, offset ) ) < 0 )
+ return byte;
+ DBG ( "%c", byte );
+ }
+ DBG ( "\n" );
+ return 0;
+}
+
+/**
+ * Dump Phantom firmware dmesg logs
+ *
+ * @v phantom Phantom NIC
+ * @v max_lines Maximum number of lines to show, or -1 to show all
+ */
+static void __attribute__ (( unused ))
+phantom_dmesg_all ( struct phantom_nic *phantom, unsigned int max_lines ) {
+ unsigned int i;
+
+ for ( i = 0 ; i < UNM_CAM_RAM_NUM_DMESG_BUFFERS ; i++ )
+ phantom_dmesg ( phantom, i, max_lines );
+}
+
+/***************************************************************************
+ *
+ * Firmware interface
+ *
+ */
+
+/**
+ * Wait for firmware to accept command
+ *
+ * @v phantom Phantom NIC
+ * @ret rc Return status code
+ */
+static int phantom_wait_for_cmd ( struct phantom_nic *phantom ) {
+ unsigned int retries;
+ uint32_t cdrp;
+
+ for ( retries = 0 ; retries < PHN_ISSUE_CMD_TIMEOUT_MS ; retries++ ) {
+ mdelay ( 1 );
+ cdrp = phantom_readl ( phantom, UNM_NIC_REG_NX_CDRP );
+ if ( NX_CDRP_IS_RSP ( cdrp ) ) {
+ switch ( NX_CDRP_FORM_RSP ( cdrp ) ) {
+ case NX_CDRP_RSP_OK:
+ return 0;
+ case NX_CDRP_RSP_FAIL:
+ return -EIO;
+ case NX_CDRP_RSP_TIMEOUT:
+ return -ETIMEDOUT;
+ default:
+ return -EPROTO;
+ }
+ }
+ }
+
+ DBGC ( phantom, "Phantom %p timed out waiting for firmware to accept "
+ "command\n", phantom );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Issue command to firmware
+ *
+ * @v phantom Phantom NIC
+ * @v command Firmware command
+ * @v arg1 Argument 1
+ * @v arg2 Argument 2
+ * @v arg3 Argument 3
+ * @ret rc Return status code
+ */
+static int phantom_issue_cmd ( struct phantom_nic *phantom,
+ uint32_t command, uint32_t arg1, uint32_t arg2,
+ uint32_t arg3 ) {
+ uint32_t signature;
+ int rc;
+
+ /* Issue command */
+ signature = NX_CDRP_SIGNATURE_MAKE ( phantom->port,
+ NXHAL_VERSION );
+ DBGC2 ( phantom, "Phantom %p issuing command %08x (%08x, %08x, "
+ "%08x)\n", phantom, command, arg1, arg2, arg3 );
+ phantom_writel ( phantom, signature, UNM_NIC_REG_NX_SIGN );
+ phantom_writel ( phantom, arg1, UNM_NIC_REG_NX_ARG1 );
+ phantom_writel ( phantom, arg2, UNM_NIC_REG_NX_ARG2 );
+ phantom_writel ( phantom, arg3, UNM_NIC_REG_NX_ARG3 );
+ phantom_writel ( phantom, NX_CDRP_FORM_CMD ( command ),
+ UNM_NIC_REG_NX_CDRP );
+
+ /* Wait for command to be accepted */
+ if ( ( rc = phantom_wait_for_cmd ( phantom ) ) != 0 ) {
+ DBGC ( phantom, "Phantom %p could not issue command: %s\n",
+ phantom, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Issue buffer-format command to firmware
+ *
+ * @v phantom Phantom NIC
+ * @v command Firmware command
+ * @v buffer Buffer to pass to firmware
+ * @v len Length of buffer
+ * @ret rc Return status code
+ */
+static int phantom_issue_buf_cmd ( struct phantom_nic *phantom,
+ uint32_t command, void *buffer,
+ size_t len ) {
+ uint64_t physaddr;
+
+ physaddr = virt_to_bus ( buffer );
+ return phantom_issue_cmd ( phantom, command, ( physaddr >> 32 ),
+ ( physaddr & 0xffffffffUL ), len );
+}
+
+/**
+ * Create Phantom RX context
+ *
+ * @v phantom Phantom NIC
+ * @ret rc Return status code
+ */
+static int phantom_create_rx_ctx ( struct phantom_nic *phantom ) {
+ struct phantom_create_rx_ctx_rqrsp *buf;
+ int rc;
+
+ /* Allocate context creation buffer */
+ buf = malloc_dma ( sizeof ( *buf ), UNM_DMA_BUFFER_ALIGN );
+ if ( ! buf ) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ memset ( buf, 0, sizeof ( *buf ) );
+
+ /* Prepare request */
+ buf->hostrq.rx_ctx.host_rsp_dma_addr =
+ cpu_to_le64 ( virt_to_bus ( &buf->cardrsp ) );
+ buf->hostrq.rx_ctx.capabilities[0] =
+ cpu_to_le32 ( NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN );
+ buf->hostrq.rx_ctx.host_int_crb_mode =
+ cpu_to_le32 ( NX_HOST_INT_CRB_MODE_SHARED );
+ buf->hostrq.rx_ctx.host_rds_crb_mode =
+ cpu_to_le32 ( NX_HOST_RDS_CRB_MODE_UNIQUE );
+ buf->hostrq.rx_ctx.rds_ring_offset = cpu_to_le32 ( 0 );
+ buf->hostrq.rx_ctx.sds_ring_offset =
+ cpu_to_le32 ( sizeof ( buf->hostrq.rds ) );
+ buf->hostrq.rx_ctx.num_rds_rings = cpu_to_le16 ( 1 );
+ buf->hostrq.rx_ctx.num_sds_rings = cpu_to_le16 ( 1 );
+ buf->hostrq.rds.host_phys_addr =
+ cpu_to_le64 ( virt_to_bus ( phantom->desc->rds ) );
+ buf->hostrq.rds.buff_size = cpu_to_le64 ( PHN_RX_BUFSIZE );
+ buf->hostrq.rds.ring_size = cpu_to_le32 ( PHN_NUM_RDS );
+ buf->hostrq.rds.ring_kind = cpu_to_le32 ( NX_RDS_RING_TYPE_NORMAL );
+ buf->hostrq.sds.host_phys_addr =
+ cpu_to_le64 ( virt_to_bus ( phantom->desc->sds ) );
+ buf->hostrq.sds.ring_size = cpu_to_le32 ( PHN_NUM_SDS );
+
+ DBGC ( phantom, "Phantom %p creating RX context\n", phantom );
+ DBGC2_HDA ( phantom, virt_to_bus ( &buf->hostrq ),
+ &buf->hostrq, sizeof ( buf->hostrq ) );
+
+ /* Issue request */
+ if ( ( rc = phantom_issue_buf_cmd ( phantom,
+ NX_CDRP_CMD_CREATE_RX_CTX,
+ &buf->hostrq,
+ sizeof ( buf->hostrq ) ) ) != 0 ) {
+ DBGC ( phantom, "Phantom %p could not create RX context: "
+ "%s\n", phantom, strerror ( rc ) );
+ DBGC ( phantom, "Request:\n" );
+ DBGC_HDA ( phantom, virt_to_bus ( &buf->hostrq ),
+ &buf->hostrq, sizeof ( buf->hostrq ) );
+ DBGC ( phantom, "Response:\n" );
+ DBGC_HDA ( phantom, virt_to_bus ( &buf->cardrsp ),
+ &buf->cardrsp, sizeof ( buf->cardrsp ) );
+ goto out;
+ }
+
+ /* Retrieve context parameters */
+ phantom->rx_context_id =
+ le16_to_cpu ( buf->cardrsp.rx_ctx.context_id );
+ phantom->rds_producer_crb =
+ ( UNM_CAM_RAM +
+ le32_to_cpu ( buf->cardrsp.rds.host_producer_crb ) );
+ phantom->sds_consumer_crb =
+ ( UNM_CAM_RAM +
+ le32_to_cpu ( buf->cardrsp.sds.host_consumer_crb ) );
+ phantom->sds_irq_mask_crb =
+ ( UNM_CAM_RAM +
+ le32_to_cpu ( buf->cardrsp.sds.interrupt_crb ) );
+
+ DBGC ( phantom, "Phantom %p created RX context (id %04x, port phys "
+ "%02x virt %02x)\n", phantom, phantom->rx_context_id,
+ buf->cardrsp.rx_ctx.phys_port, buf->cardrsp.rx_ctx.virt_port );
+ DBGC2_HDA ( phantom, virt_to_bus ( &buf->cardrsp ),
+ &buf->cardrsp, sizeof ( buf->cardrsp ) );
+ DBGC ( phantom, "Phantom %p RDS producer CRB is %08lx\n",
+ phantom, phantom->rds_producer_crb );
+ DBGC ( phantom, "Phantom %p SDS consumer CRB is %08lx\n",
+ phantom, phantom->sds_consumer_crb );
+ DBGC ( phantom, "Phantom %p SDS interrupt mask CRB is %08lx\n",
+ phantom, phantom->sds_irq_mask_crb );
+
+ out:
+ free_dma ( buf, sizeof ( *buf ) );
+ return rc;
+}
+
+/**
+ * Destroy Phantom RX context
+ *
+ * @v phantom Phantom NIC
+ * @ret rc Return status code
+ */
+static void phantom_destroy_rx_ctx ( struct phantom_nic *phantom ) {
+ int rc;
+
+ DBGC ( phantom, "Phantom %p destroying RX context (id %04x)\n",
+ phantom, phantom->rx_context_id );
+
+ /* Issue request */
+ if ( ( rc = phantom_issue_cmd ( phantom,
+ NX_CDRP_CMD_DESTROY_RX_CTX,
+ phantom->rx_context_id,
+ NX_DESTROY_CTX_RESET, 0 ) ) != 0 ) {
+ DBGC ( phantom, "Phantom %p could not destroy RX context: "
+ "%s\n", phantom, strerror ( rc ) );
+ /* We're probably screwed */
+ return;
+ }
+
+ /* Clear context parameters */
+ phantom->rx_context_id = 0;
+ phantom->rds_producer_crb = 0;
+ phantom->sds_consumer_crb = 0;
+
+ /* Reset software counters */
+ phantom->rds_producer_idx = 0;
+ phantom->rds_consumer_idx = 0;
+ phantom->sds_consumer_idx = 0;
+}
+
+/**
+ * Create Phantom TX context
+ *
+ * @v phantom Phantom NIC
+ * @ret rc Return status code
+ */
+static int phantom_create_tx_ctx ( struct phantom_nic *phantom ) {
+ struct phantom_create_tx_ctx_rqrsp *buf;
+ int rc;
+
+ /* Allocate context creation buffer */
+ buf = malloc_dma ( sizeof ( *buf ), UNM_DMA_BUFFER_ALIGN );
+ if ( ! buf ) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ memset ( buf, 0, sizeof ( *buf ) );
+
+ /* Prepare request */
+ buf->hostrq.tx_ctx.host_rsp_dma_addr =
+ cpu_to_le64 ( virt_to_bus ( &buf->cardrsp ) );
+ buf->hostrq.tx_ctx.cmd_cons_dma_addr =
+ cpu_to_le64 ( virt_to_bus ( &phantom->desc->cmd_cons ) );
+ buf->hostrq.tx_ctx.capabilities[0] =
+ cpu_to_le32 ( NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN );
+ buf->hostrq.tx_ctx.host_int_crb_mode =
+ cpu_to_le32 ( NX_HOST_INT_CRB_MODE_SHARED );
+ buf->hostrq.tx_ctx.cds_ring.host_phys_addr =
+ cpu_to_le64 ( virt_to_bus ( phantom->desc->cds ) );
+ buf->hostrq.tx_ctx.cds_ring.ring_size = cpu_to_le32 ( PHN_NUM_CDS );
+
+ DBGC ( phantom, "Phantom %p creating TX context\n", phantom );
+ DBGC2_HDA ( phantom, virt_to_bus ( &buf->hostrq ),
+ &buf->hostrq, sizeof ( buf->hostrq ) );
+
+ /* Issue request */
+ if ( ( rc = phantom_issue_buf_cmd ( phantom,
+ NX_CDRP_CMD_CREATE_TX_CTX,
+ &buf->hostrq,
+ sizeof ( buf->hostrq ) ) ) != 0 ) {
+ DBGC ( phantom, "Phantom %p could not create TX context: "
+ "%s\n", phantom, strerror ( rc ) );
+ DBGC ( phantom, "Request:\n" );
+ DBGC_HDA ( phantom, virt_to_bus ( &buf->hostrq ),
+ &buf->hostrq, sizeof ( buf->hostrq ) );
+ DBGC ( phantom, "Response:\n" );
+ DBGC_HDA ( phantom, virt_to_bus ( &buf->cardrsp ),
+ &buf->cardrsp, sizeof ( buf->cardrsp ) );
+ goto out;
+ }
+
+ /* Retrieve context parameters */
+ phantom->tx_context_id =
+ le16_to_cpu ( buf->cardrsp.tx_ctx.context_id );
+ phantom->cds_producer_crb =
+ ( UNM_CAM_RAM +
+ le32_to_cpu(buf->cardrsp.tx_ctx.cds_ring.host_producer_crb));
+
+ DBGC ( phantom, "Phantom %p created TX context (id %04x, port phys "
+ "%02x virt %02x)\n", phantom, phantom->tx_context_id,
+ buf->cardrsp.tx_ctx.phys_port, buf->cardrsp.tx_ctx.virt_port );
+ DBGC2_HDA ( phantom, virt_to_bus ( &buf->cardrsp ),
+ &buf->cardrsp, sizeof ( buf->cardrsp ) );
+ DBGC ( phantom, "Phantom %p CDS producer CRB is %08lx\n",
+ phantom, phantom->cds_producer_crb );
+
+ out:
+ free_dma ( buf, sizeof ( *buf ) );
+ return rc;
+}
+
+/**
+ * Destroy Phantom TX context
+ *
+ * @v phantom Phantom NIC
+ * @ret rc Return status code
+ */
+static void phantom_destroy_tx_ctx ( struct phantom_nic *phantom ) {
+ int rc;
+
+ DBGC ( phantom, "Phantom %p destroying TX context (id %04x)\n",
+ phantom, phantom->tx_context_id );
+
+ /* Issue request */
+ if ( ( rc = phantom_issue_cmd ( phantom,
+ NX_CDRP_CMD_DESTROY_TX_CTX,
+ phantom->tx_context_id,
+ NX_DESTROY_CTX_RESET, 0 ) ) != 0 ) {
+ DBGC ( phantom, "Phantom %p could not destroy TX context: "
+ "%s\n", phantom, strerror ( rc ) );
+ /* We're probably screwed */
+ return;
+ }
+
+ /* Clear context parameters */
+ phantom->tx_context_id = 0;
+ phantom->cds_producer_crb = 0;
+
+ /* Reset software counters */
+ phantom->cds_producer_idx = 0;
+ phantom->cds_consumer_idx = 0;
+}
+
+/***************************************************************************
+ *
+ * Descriptor ring management
+ *
+ */
+
+/**
+ * Allocate Phantom RX descriptor
+ *
+ * @v phantom Phantom NIC
+ * @ret index RX descriptor index, or negative error
+ */
+static int phantom_alloc_rds ( struct phantom_nic *phantom ) {
+ unsigned int rds_producer_idx;
+ unsigned int next_rds_producer_idx;
+
+ /* Check for space in the ring. RX descriptors are consumed
+ * out of order, but they are *read* by the hardware in strict
+ * order. We maintain a pessimistic consumer index, which is
+ * guaranteed never to be an overestimate of the number of
+ * descriptors read by the hardware.
+ */
+ rds_producer_idx = phantom->rds_producer_idx;
+ next_rds_producer_idx = ( ( rds_producer_idx + 1 ) % PHN_NUM_RDS );
+ if ( next_rds_producer_idx == phantom->rds_consumer_idx ) {
+ DBGC ( phantom, "Phantom %p RDS ring full (index %d not "
+ "consumed)\n", phantom, next_rds_producer_idx );
+ return -ENOBUFS;
+ }
+
+ return rds_producer_idx;
+}
+
+/**
+ * Post Phantom RX descriptor
+ *
+ * @v phantom Phantom NIC
+ * @v rds RX descriptor
+ */
+static void phantom_post_rds ( struct phantom_nic *phantom,
+ struct phantom_rds *rds ) {
+ unsigned int rds_producer_idx;
+ unsigned int next_rds_producer_idx;
+ struct phantom_rds *entry;
+
+ /* Copy descriptor to ring */
+ rds_producer_idx = phantom->rds_producer_idx;
+ entry = &phantom->desc->rds[rds_producer_idx];
+ memcpy ( entry, rds, sizeof ( *entry ) );
+ DBGC2 ( phantom, "Phantom %p posting RDS %ld (slot %d):\n",
+ phantom, NX_GET ( rds, handle ), rds_producer_idx );
+ DBGC2_HDA ( phantom, virt_to_bus ( entry ), entry, sizeof ( *entry ) );
+
+ /* Update producer index */
+ next_rds_producer_idx = ( ( rds_producer_idx + 1 ) % PHN_NUM_RDS );
+ phantom->rds_producer_idx = next_rds_producer_idx;
+ wmb();
+ phantom_writel ( phantom, phantom->rds_producer_idx,
+ phantom->rds_producer_crb );
+}
+
+/**
+ * Allocate Phantom TX descriptor
+ *
+ * @v phantom Phantom NIC
+ * @ret index TX descriptor index, or negative error
+ */
+static int phantom_alloc_cds ( struct phantom_nic *phantom ) {
+ unsigned int cds_producer_idx;
+ unsigned int next_cds_producer_idx;
+
+ /* Check for space in the ring. TX descriptors are consumed
+ * in strict order, so we just check for a collision against
+ * the consumer index.
+ */
+ cds_producer_idx = phantom->cds_producer_idx;
+ next_cds_producer_idx = ( ( cds_producer_idx + 1 ) % PHN_NUM_CDS );
+ if ( next_cds_producer_idx == phantom->cds_consumer_idx ) {
+ DBGC ( phantom, "Phantom %p CDS ring full (index %d not "
+ "consumed)\n", phantom, next_cds_producer_idx );
+ return -ENOBUFS;
+ }
+
+ return cds_producer_idx;
+}
+
+/**
+ * Post Phantom TX descriptor
+ *
+ * @v phantom Phantom NIC
+ * @v cds TX descriptor
+ */
+static void phantom_post_cds ( struct phantom_nic *phantom,
+ union phantom_cds *cds ) {
+ unsigned int cds_producer_idx;
+ unsigned int next_cds_producer_idx;
+ union phantom_cds *entry;
+
+ /* Copy descriptor to ring */
+ cds_producer_idx = phantom->cds_producer_idx;
+ entry = &phantom->desc->cds[cds_producer_idx];
+ memcpy ( entry, cds, sizeof ( *entry ) );
+ DBGC2 ( phantom, "Phantom %p posting CDS %d:\n",
+ phantom, cds_producer_idx );
+ DBGC2_HDA ( phantom, virt_to_bus ( entry ), entry, sizeof ( *entry ) );
+
+ /* Update producer index */
+ next_cds_producer_idx = ( ( cds_producer_idx + 1 ) % PHN_NUM_CDS );
+ phantom->cds_producer_idx = next_cds_producer_idx;
+ wmb();
+ phantom_writel ( phantom, phantom->cds_producer_idx,
+ phantom->cds_producer_crb );
+}
+
+/***************************************************************************
+ *
+ * MAC address management
+ *
+ */
+
+/**
+ * Add/remove MAC address
+ *
+ * @v phantom Phantom NIC
+ * @v ll_addr MAC address to add or remove
+ * @v opcode MAC request opcode
+ * @ret rc Return status code
+ */
+static int phantom_update_macaddr ( struct phantom_nic *phantom,
+ const uint8_t *ll_addr,
+ unsigned int opcode ) {
+ union phantom_cds cds;
+ int index;
+
+ /* Get descriptor ring entry */
+ index = phantom_alloc_cds ( phantom );
+ if ( index < 0 )
+ return index;
+
+ /* Fill descriptor ring entry */
+ memset ( &cds, 0, sizeof ( cds ) );
+ NX_FILL_1 ( &cds, 0,
+ nic_request.common.opcode, UNM_NIC_REQUEST );
+ NX_FILL_2 ( &cds, 1,
+ nic_request.header.opcode, UNM_MAC_EVENT,
+ nic_request.header.context_id, phantom->port );
+ NX_FILL_7 ( &cds, 2,
+ nic_request.body.mac_request.opcode, opcode,
+ nic_request.body.mac_request.mac_addr_0, ll_addr[0],
+ nic_request.body.mac_request.mac_addr_1, ll_addr[1],
+ nic_request.body.mac_request.mac_addr_2, ll_addr[2],
+ nic_request.body.mac_request.mac_addr_3, ll_addr[3],
+ nic_request.body.mac_request.mac_addr_4, ll_addr[4],
+ nic_request.body.mac_request.mac_addr_5, ll_addr[5] );
+
+ /* Post descriptor */
+ phantom_post_cds ( phantom, &cds );
+
+ return 0;
+}
+
+/**
+ * Add MAC address
+ *
+ * @v phantom Phantom NIC
+ * @v ll_addr MAC address to add or remove
+ * @ret rc Return status code
+ */
+static inline int phantom_add_macaddr ( struct phantom_nic *phantom,
+ const uint8_t *ll_addr ) {
+
+ DBGC ( phantom, "Phantom %p adding MAC address %s\n",
+ phantom, eth_ntoa ( ll_addr ) );
+
+ return phantom_update_macaddr ( phantom, ll_addr, UNM_MAC_ADD );
+}
+
+/**
+ * Remove MAC address
+ *
+ * @v phantom Phantom NIC
+ * @v ll_addr MAC address to add or remove
+ * @ret rc Return status code
+ */
+static inline int phantom_del_macaddr ( struct phantom_nic *phantom,
+ const uint8_t *ll_addr ) {
+
+ DBGC ( phantom, "Phantom %p removing MAC address %s\n",
+ phantom, eth_ntoa ( ll_addr ) );
+
+ return phantom_update_macaddr ( phantom, ll_addr, UNM_MAC_DEL );
+}
+
+/***************************************************************************
+ *
+ * Link state detection
+ *
+ */
+
+/**
+ * Poll link state
+ *
+ * @v netdev Network device
+ */
+static void phantom_poll_link_state ( struct net_device *netdev ) {
+ struct phantom_nic *phantom = netdev_priv ( netdev );
+ uint32_t xg_state_p3;
+ unsigned int link;
+
+ /* Read link state */
+ xg_state_p3 = phantom_readl ( phantom, UNM_NIC_REG_XG_STATE_P3 );
+
+ /* If there is no change, do nothing */
+ if ( phantom->link_state == xg_state_p3 )
+ return;
+
+ /* Record new link state */
+ DBGC ( phantom, "Phantom %p new link state %08x (was %08x)\n",
+ phantom, xg_state_p3, phantom->link_state );
+ phantom->link_state = xg_state_p3;
+
+ /* Indicate link state to iPXE */
+ link = UNM_NIC_REG_XG_STATE_P3_LINK ( phantom->port,
+ phantom->link_state );
+ switch ( link ) {
+ case UNM_NIC_REG_XG_STATE_P3_LINK_UP:
+ DBGC ( phantom, "Phantom %p link is up\n", phantom );
+ netdev_link_up ( netdev );
+ break;
+ case UNM_NIC_REG_XG_STATE_P3_LINK_DOWN:
+ DBGC ( phantom, "Phantom %p link is down\n", phantom );
+ netdev_link_down ( netdev );
+ break;
+ default:
+ DBGC ( phantom, "Phantom %p bad link state %d\n",
+ phantom, link );
+ break;
+ }
+}
+
+/***************************************************************************
+ *
+ * Main driver body
+ *
+ */
+
+/**
+ * Refill descriptor ring
+ *
+ * @v netdev Net device
+ */
+static void phantom_refill_rx_ring ( struct net_device *netdev ) {
+ struct phantom_nic *phantom = netdev_priv ( netdev );
+ struct io_buffer *iobuf;
+ struct phantom_rds rds;
+ unsigned int handle;
+ int index;
+
+ for ( handle = 0 ; handle < PHN_RDS_MAX_FILL ; handle++ ) {
+
+ /* Skip this index if the descriptor has not yet been
+ * consumed.
+ */
+ if ( phantom->rds_iobuf[handle] != NULL )
+ continue;
+
+ /* Allocate descriptor ring entry */
+ index = phantom_alloc_rds ( phantom );
+ assert ( PHN_RDS_MAX_FILL < PHN_NUM_RDS );
+ assert ( index >= 0 ); /* Guaranteed by MAX_FILL < NUM_RDS ) */
+
+ /* Try to allocate an I/O buffer */
+ iobuf = alloc_iob ( PHN_RX_BUFSIZE );
+ if ( ! iobuf ) {
+ /* Failure is non-fatal; we will retry later */
+ netdev_rx_err ( netdev, NULL, -ENOMEM );
+ break;
+ }
+
+ /* Fill descriptor ring entry */
+ memset ( &rds, 0, sizeof ( rds ) );
+ NX_FILL_2 ( &rds, 0,
+ handle, handle,
+ length, iob_len ( iobuf ) );
+ NX_FILL_1 ( &rds, 1,
+ dma_addr, virt_to_bus ( iobuf->data ) );
+
+ /* Record I/O buffer */
+ assert ( phantom->rds_iobuf[handle] == NULL );
+ phantom->rds_iobuf[handle] = iobuf;
+
+ /* Post descriptor */
+ phantom_post_rds ( phantom, &rds );
+ }
+}
+
+/**
+ * Open NIC
+ *
+ * @v netdev Net device
+ * @ret rc Return status code
+ */
+static int phantom_open ( struct net_device *netdev ) {
+ struct phantom_nic *phantom = netdev_priv ( netdev );
+ int rc;
+
+ /* Allocate and zero descriptor rings */
+ phantom->desc = malloc_dma ( sizeof ( *(phantom->desc) ),
+ UNM_DMA_BUFFER_ALIGN );
+ if ( ! phantom->desc ) {
+ rc = -ENOMEM;
+ goto err_alloc_desc;
+ }
+ memset ( phantom->desc, 0, sizeof ( *(phantom->desc) ) );
+
+ /* Create RX context */
+ if ( ( rc = phantom_create_rx_ctx ( phantom ) ) != 0 )
+ goto err_create_rx_ctx;
+
+ /* Create TX context */
+ if ( ( rc = phantom_create_tx_ctx ( phantom ) ) != 0 )
+ goto err_create_tx_ctx;
+
+ /* Fill the RX descriptor ring */
+ phantom_refill_rx_ring ( netdev );
+
+ /* Add MAC addresses
+ *
+ * BUG5583
+ *
+ * We would like to be able to enable receiving all multicast
+ * packets (or, failing that, promiscuous mode), but the
+ * firmware doesn't currently support this.
+ */
+ if ( ( rc = phantom_add_macaddr ( phantom,
+ netdev->ll_broadcast ) ) != 0 )
+ goto err_add_macaddr_broadcast;
+ if ( ( rc = phantom_add_macaddr ( phantom,
+ netdev->ll_addr ) ) != 0 )
+ goto err_add_macaddr_unicast;
+
+ return 0;
+
+ phantom_del_macaddr ( phantom, netdev->ll_addr );
+ err_add_macaddr_unicast:
+ phantom_del_macaddr ( phantom, netdev->ll_broadcast );
+ err_add_macaddr_broadcast:
+ phantom_destroy_tx_ctx ( phantom );
+ err_create_tx_ctx:
+ phantom_destroy_rx_ctx ( phantom );
+ err_create_rx_ctx:
+ free_dma ( phantom->desc, sizeof ( *(phantom->desc) ) );
+ phantom->desc = NULL;
+ err_alloc_desc:
+ return rc;
+}
+
+/**
+ * Close NIC
+ *
+ * @v netdev Net device
+ */
+static void phantom_close ( struct net_device *netdev ) {
+ struct phantom_nic *phantom = netdev_priv ( netdev );
+ struct io_buffer *iobuf;
+ unsigned int i;
+
+ /* Shut down the port */
+ phantom_del_macaddr ( phantom, netdev->ll_addr );
+ phantom_del_macaddr ( phantom, netdev->ll_broadcast );
+ phantom_destroy_tx_ctx ( phantom );
+ phantom_destroy_rx_ctx ( phantom );
+ free_dma ( phantom->desc, sizeof ( *(phantom->desc) ) );
+ phantom->desc = NULL;
+
+ /* Flush any uncompleted descriptors */
+ for ( i = 0 ; i < PHN_RDS_MAX_FILL ; i++ ) {
+ iobuf = phantom->rds_iobuf[i];
+ if ( iobuf ) {
+ free_iob ( iobuf );
+ phantom->rds_iobuf[i] = NULL;
+ }
+ }
+ for ( i = 0 ; i < PHN_NUM_CDS ; i++ ) {
+ iobuf = phantom->cds_iobuf[i];
+ if ( iobuf ) {
+ netdev_tx_complete_err ( netdev, iobuf, -ECANCELED );
+ phantom->cds_iobuf[i] = NULL;
+ }
+ }
+}
+
+/**
+ * Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int phantom_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct phantom_nic *phantom = netdev_priv ( netdev );
+ union phantom_cds cds;
+ int index;
+
+ /* Get descriptor ring entry */
+ index = phantom_alloc_cds ( phantom );
+ if ( index < 0 )
+ return index;
+
+ /* Fill descriptor ring entry */
+ memset ( &cds, 0, sizeof ( cds ) );
+ NX_FILL_3 ( &cds, 0,
+ tx.opcode, UNM_TX_ETHER_PKT,
+ tx.num_buffers, 1,
+ tx.length, iob_len ( iobuf ) );
+ NX_FILL_2 ( &cds, 2,
+ tx.port, phantom->port,
+ tx.context_id, phantom->port );
+ NX_FILL_1 ( &cds, 4,
+ tx.buffer1_dma_addr, virt_to_bus ( iobuf->data ) );
+ NX_FILL_1 ( &cds, 5,
+ tx.buffer1_length, iob_len ( iobuf ) );
+
+ /* Record I/O buffer */
+ assert ( phantom->cds_iobuf[index] == NULL );
+ phantom->cds_iobuf[index] = iobuf;
+
+ /* Post descriptor */
+ phantom_post_cds ( phantom, &cds );
+
+ return 0;
+}
+
+/**
+ * Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void phantom_poll ( struct net_device *netdev ) {
+ struct phantom_nic *phantom = netdev_priv ( netdev );
+ struct io_buffer *iobuf;
+ unsigned int irq_vector;
+ unsigned int irq_state;
+ unsigned int cds_consumer_idx;
+ unsigned int raw_new_cds_consumer_idx;
+ unsigned int new_cds_consumer_idx;
+ unsigned int rds_consumer_idx;
+ unsigned int sds_consumer_idx;
+ struct phantom_sds *sds;
+ unsigned int sds_handle;
+ unsigned int sds_opcode;
+
+ /* Occasionally poll the link state */
+ if ( phantom->link_poll_timer-- == 0 ) {
+ phantom_poll_link_state ( netdev );
+ /* Reset the link poll timer */
+ phantom->link_poll_timer = PHN_LINK_POLL_FREQUENCY;
+ }
+
+ /* Check for interrupts */
+ if ( phantom->sds_irq_enabled ) {
+
+ /* Do nothing unless an interrupt is asserted */
+ irq_vector = phantom_readl ( phantom, UNM_PCIE_IRQ_VECTOR );
+ if ( ! ( irq_vector & UNM_PCIE_IRQ_VECTOR_BIT( phantom->port )))
+ return;
+
+ /* Do nothing unless interrupt state machine has stabilised */
+ irq_state = phantom_readl ( phantom, UNM_PCIE_IRQ_STATE );
+ if ( ! UNM_PCIE_IRQ_STATE_TRIGGERED ( irq_state ) )
+ return;
+
+ /* Acknowledge interrupt */
+ phantom_writel ( phantom, UNM_PCIE_IRQ_STATUS_MAGIC,
+ phantom_irq_status_reg[phantom->port] );
+ phantom_readl ( phantom, UNM_PCIE_IRQ_VECTOR );
+ }
+
+ /* Check for TX completions */
+ cds_consumer_idx = phantom->cds_consumer_idx;
+ raw_new_cds_consumer_idx = phantom->desc->cmd_cons;
+ new_cds_consumer_idx = le32_to_cpu ( raw_new_cds_consumer_idx );
+ while ( cds_consumer_idx != new_cds_consumer_idx ) {
+ DBGC2 ( phantom, "Phantom %p CDS %d complete\n",
+ phantom, cds_consumer_idx );
+ /* Completions may be for commands other than TX, so
+ * there may not always be an associated I/O buffer.
+ */
+ if ( ( iobuf = phantom->cds_iobuf[cds_consumer_idx] ) ) {
+ netdev_tx_complete ( netdev, iobuf );
+ phantom->cds_iobuf[cds_consumer_idx] = NULL;
+ }
+ cds_consumer_idx = ( ( cds_consumer_idx + 1 ) % PHN_NUM_CDS );
+ phantom->cds_consumer_idx = cds_consumer_idx;
+ }
+
+ /* Check for received packets */
+ rds_consumer_idx = phantom->rds_consumer_idx;
+ sds_consumer_idx = phantom->sds_consumer_idx;
+ while ( 1 ) {
+ sds = &phantom->desc->sds[sds_consumer_idx];
+ if ( NX_GET ( sds, owner ) == 0 )
+ break;
+
+ DBGC2 ( phantom, "Phantom %p SDS %d status:\n",
+ phantom, sds_consumer_idx );
+ DBGC2_HDA ( phantom, virt_to_bus ( sds ), sds, sizeof (*sds) );
+
+ /* Check received opcode */
+ sds_opcode = NX_GET ( sds, opcode );
+ if ( ( sds_opcode == UNM_RXPKT_DESC ) ||
+ ( sds_opcode == UNM_SYN_OFFLOAD ) ) {
+
+ /* Sanity check: ensure that all of the SDS
+ * descriptor has been written.
+ */
+ if ( NX_GET ( sds, total_length ) == 0 ) {
+ DBGC ( phantom, "Phantom %p SDS %d "
+ "incomplete; deferring\n",
+ phantom, sds_consumer_idx );
+ /* Leave for next poll() */
+ break;
+ }
+
+ /* Process received packet */
+ sds_handle = NX_GET ( sds, handle );
+ iobuf = phantom->rds_iobuf[sds_handle];
+ assert ( iobuf != NULL );
+ iob_put ( iobuf, NX_GET ( sds, total_length ) );
+ iob_pull ( iobuf, NX_GET ( sds, pkt_offset ) );
+ DBGC2 ( phantom, "Phantom %p RDS %d complete\n",
+ phantom, sds_handle );
+ netdev_rx ( netdev, iobuf );
+ phantom->rds_iobuf[sds_handle] = NULL;
+
+ /* Update RDS consumer counter. This is a
+ * lower bound for the number of descriptors
+ * that have been read by the hardware, since
+ * the hardware must have read at least one
+ * descriptor for each completion that we
+ * receive.
+ */
+ rds_consumer_idx =
+ ( ( rds_consumer_idx + 1 ) % PHN_NUM_RDS );
+ phantom->rds_consumer_idx = rds_consumer_idx;
+
+ } else {
+
+ DBGC ( phantom, "Phantom %p unexpected SDS opcode "
+ "%02x\n", phantom, sds_opcode );
+ DBGC_HDA ( phantom, virt_to_bus ( sds ),
+ sds, sizeof ( *sds ) );
+ }
+
+ /* Clear status descriptor */
+ memset ( sds, 0, sizeof ( *sds ) );
+
+ /* Update SDS consumer index */
+ sds_consumer_idx = ( ( sds_consumer_idx + 1 ) % PHN_NUM_SDS );
+ phantom->sds_consumer_idx = sds_consumer_idx;
+ wmb();
+ phantom_writel ( phantom, phantom->sds_consumer_idx,
+ phantom->sds_consumer_crb );
+ }
+
+ /* Refill the RX descriptor ring */
+ phantom_refill_rx_ring ( netdev );
+}
+
+/**
+ * Enable/disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void phantom_irq ( struct net_device *netdev, int enable ) {
+ struct phantom_nic *phantom = netdev_priv ( netdev );
+
+ phantom_writel ( phantom, ( enable ? 1 : 0 ),
+ phantom->sds_irq_mask_crb );
+ phantom_writel ( phantom, UNM_PCIE_IRQ_MASK_MAGIC,
+ phantom_irq_mask_reg[phantom->port] );
+ phantom->sds_irq_enabled = enable;
+}
+
+/** Phantom net device operations */
+static struct net_device_operations phantom_operations = {
+ .open = phantom_open,
+ .close = phantom_close,
+ .transmit = phantom_transmit,
+ .poll = phantom_poll,
+ .irq = phantom_irq,
+};
+
+/***************************************************************************
+ *
+ * CLP settings
+ *
+ */
+
+/** Phantom CLP settings tag magic */
+#define PHN_CLP_TAG_MAGIC 0xc19c1900UL
+
+/** Phantom CLP settings tag magic mask */
+#define PHN_CLP_TAG_MAGIC_MASK 0xffffff00UL
+
+/** Phantom CLP data
+ *
+ */
+union phantom_clp_data {
+ /** Data bytes
+ *
+ * This field is right-aligned; if only N bytes are present
+ * then bytes[0]..bytes[7-N] should be zero, and the data
+ * should be in bytes[7-N+1] to bytes[7];
+ */
+ uint8_t bytes[8];
+ /** Dwords for the CLP interface */
+ struct {
+ /** High dword, in network byte order */
+ uint32_t hi;
+ /** Low dword, in network byte order */
+ uint32_t lo;
+ } dwords;
+};
+#define PHN_CLP_BLKSIZE ( sizeof ( union phantom_clp_data ) )
+
+/**
+ * Wait for Phantom CLP command to complete
+ *
+ * @v phantom Phantom NIC
+ * @ret rc Return status code
+ */
+static int phantom_clp_wait ( struct phantom_nic *phantom ) {
+ unsigned int retries;
+ uint32_t status;
+
+ for ( retries = 0 ; retries < PHN_CLP_CMD_TIMEOUT_MS ; retries++ ) {
+ status = phantom_readl ( phantom, UNM_CAM_RAM_CLP_STATUS );
+ if ( status & UNM_CAM_RAM_CLP_STATUS_DONE )
+ return 0;
+ mdelay ( 1 );
+ }
+
+ DBGC ( phantom, "Phantom %p timed out waiting for CLP command\n",
+ phantom );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Issue Phantom CLP command
+ *
+ * @v phantom Phantom NIC
+ * @v port Virtual port number
+ * @v opcode Opcode
+ * @v data_in Data in, or NULL
+ * @v data_out Data out, or NULL
+ * @v offset Offset within data
+ * @v len Data buffer length
+ * @ret len Total transfer length (for reads), or negative error
+ */
+static int phantom_clp_cmd ( struct phantom_nic *phantom, unsigned int port,
+ unsigned int opcode, const void *data_in,
+ void *data_out, size_t offset, size_t len ) {
+ union phantom_clp_data data;
+ unsigned int index = ( offset / sizeof ( data ) );
+ unsigned int last = 0;
+ size_t in_frag_len;
+ uint8_t *in_frag;
+ uint32_t command;
+ uint32_t status;
+ size_t read_len;
+ unsigned int error;
+ size_t out_frag_len;
+ uint8_t *out_frag;
+ int rc;
+
+ /* Sanity checks */
+ assert ( ( offset % sizeof ( data ) ) == 0 );
+ if ( len > 255 ) {
+ DBGC ( phantom, "Phantom %p invalid CLP length %zd\n",
+ phantom, len );
+ return -EINVAL;
+ }
+
+ /* Check that CLP interface is ready */
+ if ( ( rc = phantom_clp_wait ( phantom ) ) != 0 )
+ return rc;
+
+ /* Copy data in */
+ memset ( &data, 0, sizeof ( data ) );
+ if ( data_in ) {
+ assert ( offset < len );
+ in_frag_len = ( len - offset );
+ if ( in_frag_len > sizeof ( data ) ) {
+ in_frag_len = sizeof ( data );
+ } else {
+ last = 1;
+ }
+ in_frag = &data.bytes[ sizeof ( data ) - in_frag_len ];
+ memcpy ( in_frag, ( data_in + offset ), in_frag_len );
+ phantom_writel ( phantom, be32_to_cpu ( data.dwords.lo ),
+ UNM_CAM_RAM_CLP_DATA_LO );
+ phantom_writel ( phantom, be32_to_cpu ( data.dwords.hi ),
+ UNM_CAM_RAM_CLP_DATA_HI );
+ }
+
+ /* Issue CLP command */
+ command = ( ( index << 24 ) | ( ( data_in ? len : 0 ) << 16 ) |
+ ( port << 8 ) | ( last << 7 ) | ( opcode << 0 ) );
+ phantom_writel ( phantom, command, UNM_CAM_RAM_CLP_COMMAND );
+ mb();
+ phantom_writel ( phantom, UNM_CAM_RAM_CLP_STATUS_START,
+ UNM_CAM_RAM_CLP_STATUS );
+
+ /* Wait for command to complete */
+ if ( ( rc = phantom_clp_wait ( phantom ) ) != 0 )
+ return rc;
+
+ /* Get command status */
+ status = phantom_readl ( phantom, UNM_CAM_RAM_CLP_STATUS );
+ read_len = ( ( status >> 16 ) & 0xff );
+ error = ( ( status >> 8 ) & 0xff );
+ if ( error ) {
+ DBGC ( phantom, "Phantom %p CLP command error %02x\n",
+ phantom, error );
+ return -EIO;
+ }
+
+ /* Copy data out */
+ if ( data_out ) {
+ data.dwords.lo = cpu_to_be32 ( phantom_readl ( phantom,
+ UNM_CAM_RAM_CLP_DATA_LO ) );
+ data.dwords.hi = cpu_to_be32 ( phantom_readl ( phantom,
+ UNM_CAM_RAM_CLP_DATA_HI ) );
+ out_frag_len = ( read_len - offset );
+ if ( out_frag_len > sizeof ( data ) )
+ out_frag_len = sizeof ( data );
+ out_frag = &data.bytes[ sizeof ( data ) - out_frag_len ];
+ if ( out_frag_len > ( len - offset ) )
+ out_frag_len = ( len - offset );
+ memcpy ( ( data_out + offset ), out_frag, out_frag_len );
+ }
+
+ return read_len;
+}
+
+/**
+ * Store Phantom CLP setting
+ *
+ * @v phantom Phantom NIC
+ * @v port Virtual port number
+ * @v setting Setting number
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int phantom_clp_store ( struct phantom_nic *phantom, unsigned int port,
+ unsigned int setting, const void *data,
+ size_t len ) {
+ unsigned int opcode = setting;
+ size_t offset;
+ int rc;
+
+ for ( offset = 0 ; offset < len ; offset += PHN_CLP_BLKSIZE ) {
+ if ( ( rc = phantom_clp_cmd ( phantom, port, opcode, data,
+ NULL, offset, len ) ) < 0 )
+ return rc;
+ }
+ return 0;
+}
+
+/**
+ * Fetch Phantom CLP setting
+ *
+ * @v phantom Phantom NIC
+ * @v port Virtual port number
+ * @v setting Setting number
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret len Length of setting, or negative error
+ */
+static int phantom_clp_fetch ( struct phantom_nic *phantom, unsigned int port,
+ unsigned int setting, void *data, size_t len ) {
+ unsigned int opcode = ( setting + 1 );
+ size_t offset = 0;
+ int read_len;
+
+ while ( 1 ) {
+ read_len = phantom_clp_cmd ( phantom, port, opcode, NULL,
+ data, offset, len );
+ if ( read_len < 0 )
+ return read_len;
+ offset += PHN_CLP_BLKSIZE;
+ if ( offset >= ( unsigned ) read_len )
+ break;
+ if ( offset >= len )
+ break;
+ }
+ return read_len;
+}
+
+/** A Phantom CLP setting */
+struct phantom_clp_setting {
+ /** iPXE setting */
+ struct setting *setting;
+ /** Setting number */
+ unsigned int clp_setting;
+};
+
+/** Phantom CLP settings */
+static struct phantom_clp_setting clp_settings[] = {
+ { &mac_setting, 0x01 },
+};
+
+/**
+ * Find Phantom CLP setting
+ *
+ * @v setting iPXE setting
+ * @v clp_setting Setting number, or 0 if not found
+ */
+static unsigned int
+phantom_clp_setting ( struct phantom_nic *phantom, struct setting *setting ) {
+ struct phantom_clp_setting *clp_setting;
+ unsigned int i;
+
+ /* Search the list of explicitly-defined settings */
+ for ( i = 0 ; i < ( sizeof ( clp_settings ) /
+ sizeof ( clp_settings[0] ) ) ; i++ ) {
+ clp_setting = &clp_settings[i];
+ if ( setting_cmp ( setting, clp_setting->setting ) == 0 )
+ return clp_setting->clp_setting;
+ }
+
+ /* Allow for use of numbered settings */
+ if ( ( setting->tag & PHN_CLP_TAG_MAGIC_MASK ) == PHN_CLP_TAG_MAGIC )
+ return ( setting->tag & ~PHN_CLP_TAG_MAGIC_MASK );
+
+ DBGC2 ( phantom, "Phantom %p has no \"%s\" setting\n",
+ phantom, setting->name );
+
+ return 0;
+}
+
+/**
+ * Check applicability of Phantom CLP setting
+ *
+ * @v settings Settings block
+ * @v setting Setting
+ * @ret applies Setting applies within this settings block
+ */
+static int phantom_setting_applies ( struct settings *settings,
+ struct setting *setting ) {
+ struct phantom_nic *phantom =
+ container_of ( settings, struct phantom_nic, settings );
+ unsigned int clp_setting;
+
+ /* Find Phantom setting equivalent to iPXE setting */
+ clp_setting = phantom_clp_setting ( phantom, setting );
+ return ( clp_setting != 0 );
+}
+
+/**
+ * Store Phantom CLP setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+static int phantom_store_setting ( struct settings *settings,
+ struct setting *setting,
+ const void *data, size_t len ) {
+ struct phantom_nic *phantom =
+ container_of ( settings, struct phantom_nic, settings );
+ unsigned int clp_setting;
+ int rc;
+
+ /* Find Phantom setting equivalent to iPXE setting */
+ clp_setting = phantom_clp_setting ( phantom, setting );
+ assert ( clp_setting != 0 );
+
+ /* Store setting */
+ if ( ( rc = phantom_clp_store ( phantom, phantom->port,
+ clp_setting, data, len ) ) != 0 ) {
+ DBGC ( phantom, "Phantom %p could not store setting \"%s\": "
+ "%s\n", phantom, setting->name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Fetch Phantom CLP setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+static int phantom_fetch_setting ( struct settings *settings,
+ struct setting *setting,
+ void *data, size_t len ) {
+ struct phantom_nic *phantom =
+ container_of ( settings, struct phantom_nic, settings );
+ unsigned int clp_setting;
+ int read_len;
+ int rc;
+
+ /* Find Phantom setting equivalent to iPXE setting */
+ clp_setting = phantom_clp_setting ( phantom, setting );
+ assert ( clp_setting != 0 );
+
+ /* Fetch setting */
+ if ( ( read_len = phantom_clp_fetch ( phantom, phantom->port,
+ clp_setting, data, len ) ) < 0 ){
+ rc = read_len;
+ DBGC ( phantom, "Phantom %p could not fetch setting \"%s\": "
+ "%s\n", phantom, setting->name, strerror ( rc ) );
+ return rc;
+ }
+
+ return read_len;
+}
+
+/** Phantom CLP settings operations */
+static struct settings_operations phantom_settings_operations = {
+ .applies = phantom_setting_applies,
+ .store = phantom_store_setting,
+ .fetch = phantom_fetch_setting,
+};
+
+/***************************************************************************
+ *
+ * Initialisation
+ *
+ */
+
+/**
+ * Map Phantom CRB window
+ *
+ * @v phantom Phantom NIC
+ * @ret rc Return status code
+ */
+static int phantom_map_crb ( struct phantom_nic *phantom,
+ struct pci_device *pci ) {
+ unsigned long bar0_start;
+ unsigned long bar0_size;
+
+ bar0_start = pci_bar_start ( pci, PCI_BASE_ADDRESS_0 );
+ bar0_size = pci_bar_size ( pci, PCI_BASE_ADDRESS_0 );
+ DBGC ( phantom, "Phantom %p is " PCI_FMT " with BAR0 at %08lx+%lx\n",
+ phantom, PCI_ARGS ( pci ), bar0_start, bar0_size );
+
+ if ( ! bar0_start ) {
+ DBGC ( phantom, "Phantom %p BAR not assigned; ignoring\n",
+ phantom );
+ return -EINVAL;
+ }
+
+ switch ( bar0_size ) {
+ case ( 128 * 1024 * 1024 ) :
+ DBGC ( phantom, "Phantom %p has 128MB BAR\n", phantom );
+ phantom->crb_access = phantom_crb_access_128m;
+ break;
+ case ( 32 * 1024 * 1024 ) :
+ DBGC ( phantom, "Phantom %p has 32MB BAR\n", phantom );
+ phantom->crb_access = phantom_crb_access_32m;
+ break;
+ case ( 2 * 1024 * 1024 ) :
+ DBGC ( phantom, "Phantom %p has 2MB BAR\n", phantom );
+ phantom->crb_access = phantom_crb_access_2m;
+ break;
+ default:
+ DBGC ( phantom, "Phantom %p has bad BAR size\n", phantom );
+ return -EINVAL;
+ }
+
+ phantom->bar0 = ioremap ( bar0_start, bar0_size );
+ if ( ! phantom->bar0 ) {
+ DBGC ( phantom, "Phantom %p could not map BAR0\n", phantom );
+ return -EIO;
+ }
+
+ /* Mark current CRB window as invalid, so that the first
+ * read/write will set the current window.
+ */
+ phantom->crb_window = -1UL;
+
+ return 0;
+}
+
+/**
+ * Unhalt all PEGs
+ *
+ * @v phantom Phantom NIC
+ */
+static void phantom_unhalt_pegs ( struct phantom_nic *phantom ) {
+ uint32_t halt_status;
+
+ halt_status = phantom_readl ( phantom, UNM_PEG_0_HALT_STATUS );
+ phantom_writel ( phantom, halt_status, UNM_PEG_0_HALT_STATUS );
+ halt_status = phantom_readl ( phantom, UNM_PEG_1_HALT_STATUS );
+ phantom_writel ( phantom, halt_status, UNM_PEG_1_HALT_STATUS );
+ halt_status = phantom_readl ( phantom, UNM_PEG_2_HALT_STATUS );
+ phantom_writel ( phantom, halt_status, UNM_PEG_2_HALT_STATUS );
+ halt_status = phantom_readl ( phantom, UNM_PEG_3_HALT_STATUS );
+ phantom_writel ( phantom, halt_status, UNM_PEG_3_HALT_STATUS );
+ halt_status = phantom_readl ( phantom, UNM_PEG_4_HALT_STATUS );
+ phantom_writel ( phantom, halt_status, UNM_PEG_4_HALT_STATUS );
+}
+
+/**
+ * Initialise the Phantom command PEG
+ *
+ * @v phantom Phantom NIC
+ * @ret rc Return status code
+ */
+static int phantom_init_cmdpeg ( struct phantom_nic *phantom ) {
+ uint32_t cold_boot;
+ uint32_t sw_reset;
+ unsigned int retries;
+ uint32_t cmdpeg_state;
+ uint32_t last_cmdpeg_state = 0;
+
+ /* Check for a previous initialisation. This could have
+ * happened if, for example, the BIOS used the UNDI API to
+ * drive the NIC prior to a full PXE boot.
+ */
+ cmdpeg_state = phantom_readl ( phantom, UNM_NIC_REG_CMDPEG_STATE );
+ if ( cmdpeg_state == UNM_NIC_REG_CMDPEG_STATE_INITIALIZE_ACK ) {
+ DBGC ( phantom, "Phantom %p command PEG already initialized\n",
+ phantom );
+ /* Unhalt the PEGs. Previous firmware (e.g. BOFM) may
+ * have halted the PEGs to prevent internal bus
+ * collisions when the BIOS re-reads the expansion ROM.
+ */
+ phantom_unhalt_pegs ( phantom );
+ return 0;
+ }
+
+ /* If this was a cold boot, check that the hardware came up ok */
+ cold_boot = phantom_readl ( phantom, UNM_CAM_RAM_COLD_BOOT );
+ if ( cold_boot == UNM_CAM_RAM_COLD_BOOT_MAGIC ) {
+ DBGC ( phantom, "Phantom %p coming up from cold boot\n",
+ phantom );
+ sw_reset = phantom_readl ( phantom, UNM_ROMUSB_GLB_SW_RESET );
+ if ( sw_reset != UNM_ROMUSB_GLB_SW_RESET_MAGIC ) {
+ DBGC ( phantom, "Phantom %p reset failed: %08x\n",
+ phantom, sw_reset );
+ return -EIO;
+ }
+ } else {
+ DBGC ( phantom, "Phantom %p coming up from warm boot "
+ "(%08x)\n", phantom, cold_boot );
+ }
+ /* Clear cold-boot flag */
+ phantom_writel ( phantom, 0, UNM_CAM_RAM_COLD_BOOT );
+
+ /* Set port modes */
+ phantom_writel ( phantom, UNM_CAM_RAM_PORT_MODE_AUTO_NEG_1G,
+ UNM_CAM_RAM_WOL_PORT_MODE );
+
+ /* Pass dummy DMA area to card */
+ phantom_write_hilo ( phantom, 0,
+ UNM_NIC_REG_DUMMY_BUF_ADDR_LO,
+ UNM_NIC_REG_DUMMY_BUF_ADDR_HI );
+ phantom_writel ( phantom, UNM_NIC_REG_DUMMY_BUF_INIT,
+ UNM_NIC_REG_DUMMY_BUF );
+
+ /* Tell the hardware that tuning is complete */
+ phantom_writel ( phantom, UNM_ROMUSB_GLB_PEGTUNE_DONE_MAGIC,
+ UNM_ROMUSB_GLB_PEGTUNE_DONE );
+
+ /* Wait for command PEG to finish initialising */
+ DBGC ( phantom, "Phantom %p initialising command PEG (will take up to "
+ "%d seconds)...\n", phantom, PHN_CMDPEG_INIT_TIMEOUT_SEC );
+ for ( retries = 0; retries < PHN_CMDPEG_INIT_TIMEOUT_SEC; retries++ ) {
+ cmdpeg_state = phantom_readl ( phantom,
+ UNM_NIC_REG_CMDPEG_STATE );
+ if ( cmdpeg_state != last_cmdpeg_state ) {
+ DBGC ( phantom, "Phantom %p command PEG state is "
+ "%08x after %d seconds...\n",
+ phantom, cmdpeg_state, retries );
+ last_cmdpeg_state = cmdpeg_state;
+ }
+ if ( cmdpeg_state == UNM_NIC_REG_CMDPEG_STATE_INITIALIZED ) {
+ /* Acknowledge the PEG initialisation */
+ phantom_writel ( phantom,
+ UNM_NIC_REG_CMDPEG_STATE_INITIALIZE_ACK,
+ UNM_NIC_REG_CMDPEG_STATE );
+ return 0;
+ }
+ mdelay ( 1000 );
+ }
+
+ DBGC ( phantom, "Phantom %p timed out waiting for command PEG to "
+ "initialise (status %08x)\n", phantom, cmdpeg_state );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Read Phantom MAC address
+ *
+ * @v phanton_port Phantom NIC
+ * @v hw_addr Buffer to fill with MAC address
+ */
+static void phantom_get_macaddr ( struct phantom_nic *phantom,
+ uint8_t *hw_addr ) {
+ union {
+ uint8_t mac_addr[2][ETH_ALEN];
+ uint32_t dwords[3];
+ } u;
+ unsigned long offset;
+ int i;
+
+ /* Read the three dwords that include this MAC address and one other */
+ offset = ( UNM_CAM_RAM_MAC_ADDRS +
+ ( 12 * ( phantom->port / 2 ) ) );
+ for ( i = 0 ; i < 3 ; i++, offset += 4 ) {
+ u.dwords[i] = phantom_readl ( phantom, offset );
+ }
+
+ /* Copy out the relevant MAC address */
+ for ( i = 0 ; i < ETH_ALEN ; i++ ) {
+ hw_addr[ ETH_ALEN - i - 1 ] =
+ u.mac_addr[ phantom->port & 1 ][i];
+ }
+ DBGC ( phantom, "Phantom %p MAC address is %s\n",
+ phantom, eth_ntoa ( hw_addr ) );
+}
+
+/**
+ * Check Phantom is enabled for boot
+ *
+ * @v phanton_port Phantom NIC
+ * @ret rc Return status code
+ *
+ * This is something of an ugly hack to accommodate an OEM
+ * requirement. The NIC has only one expansion ROM BAR, rather than
+ * one per port. To allow individual ports to be selectively
+ * enabled/disabled for PXE boot (as required), we must therefore
+ * leave the expansion ROM always enabled, and place the per-port
+ * enable/disable logic within the iPXE driver.
+ */
+static int phantom_check_boot_enable ( struct phantom_nic *phantom ) {
+ unsigned long boot_enable;
+
+ boot_enable = phantom_readl ( phantom, UNM_CAM_RAM_BOOT_ENABLE );
+ if ( ! ( boot_enable & ( 1 << phantom->port ) ) ) {
+ DBGC ( phantom, "Phantom %p PXE boot is disabled\n",
+ phantom );
+ return -ENOTSUP;
+ }
+
+ return 0;
+}
+
+/**
+ * Initialise Phantom receive PEG
+ *
+ * @v phantom Phantom NIC
+ * @ret rc Return status code
+ */
+static int phantom_init_rcvpeg ( struct phantom_nic *phantom ) {
+ unsigned int retries;
+ uint32_t rcvpeg_state;
+ uint32_t last_rcvpeg_state = 0;
+
+ DBGC ( phantom, "Phantom %p initialising receive PEG (will take up to "
+ "%d seconds)...\n", phantom, PHN_RCVPEG_INIT_TIMEOUT_SEC );
+ for ( retries = 0; retries < PHN_RCVPEG_INIT_TIMEOUT_SEC; retries++ ) {
+ rcvpeg_state = phantom_readl ( phantom,
+ UNM_NIC_REG_RCVPEG_STATE );
+ if ( rcvpeg_state != last_rcvpeg_state ) {
+ DBGC ( phantom, "Phantom %p receive PEG state is "
+ "%08x after %d seconds...\n",
+ phantom, rcvpeg_state, retries );
+ last_rcvpeg_state = rcvpeg_state;
+ }
+ if ( rcvpeg_state == UNM_NIC_REG_RCVPEG_STATE_INITIALIZED )
+ return 0;
+ mdelay ( 1000 );
+ }
+
+ DBGC ( phantom, "Phantom %p timed out waiting for receive PEG to "
+ "initialise (status %08x)\n", phantom, rcvpeg_state );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @v id PCI ID
+ * @ret rc Return status code
+ */
+static int phantom_probe ( struct pci_device *pci ) {
+ struct net_device *netdev;
+ struct phantom_nic *phantom;
+ struct settings *parent_settings;
+ int rc;
+
+ /* Allocate Phantom device */
+ netdev = alloc_etherdev ( sizeof ( *phantom ) );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ goto err_alloc_etherdev;
+ }
+ netdev_init ( netdev, &phantom_operations );
+ phantom = netdev_priv ( netdev );
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+ memset ( phantom, 0, sizeof ( *phantom ) );
+ phantom->port = PCI_FUNC ( pci->busdevfn );
+ assert ( phantom->port < PHN_MAX_NUM_PORTS );
+ settings_init ( &phantom->settings,
+ &phantom_settings_operations,
+ &netdev->refcnt, PHN_CLP_TAG_MAGIC );
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* Map CRB */
+ if ( ( rc = phantom_map_crb ( phantom, pci ) ) != 0 )
+ goto err_map_crb;
+
+ /* BUG5945 - need to hack PCI config space on P3 B1 silicon.
+ * B2 will have this fixed; remove this hack when B1 is no
+ * longer in use.
+ */
+ if ( PCI_FUNC ( pci->busdevfn ) == 0 ) {
+ unsigned int i;
+ for ( i = 0 ; i < 8 ; i++ ) {
+ uint32_t temp;
+ pci->busdevfn =
+ PCI_BUSDEVFN ( PCI_BUS ( pci->busdevfn ),
+ PCI_SLOT ( pci->busdevfn ), i );
+ pci_read_config_dword ( pci, 0xc8, &temp );
+ pci_read_config_dword ( pci, 0xc8, &temp );
+ pci_write_config_dword ( pci, 0xc8, 0xf1000 );
+ }
+ pci->busdevfn = PCI_BUSDEVFN ( PCI_BUS ( pci->busdevfn ),
+ PCI_SLOT ( pci->busdevfn ), 0 );
+ }
+
+ /* Initialise the command PEG */
+ if ( ( rc = phantom_init_cmdpeg ( phantom ) ) != 0 )
+ goto err_init_cmdpeg;
+
+ /* Initialise the receive PEG */
+ if ( ( rc = phantom_init_rcvpeg ( phantom ) ) != 0 )
+ goto err_init_rcvpeg;
+
+ /* Read MAC addresses */
+ phantom_get_macaddr ( phantom, netdev->hw_addr );
+
+ /* Skip if boot disabled on NIC */
+ if ( ( rc = phantom_check_boot_enable ( phantom ) ) != 0 )
+ goto err_check_boot_enable;
+
+ /* Register network devices */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
+ DBGC ( phantom, "Phantom %p could not register net device: "
+ "%s\n", phantom, strerror ( rc ) );
+ goto err_register_netdev;
+ }
+
+ /* Register settings blocks */
+ parent_settings = netdev_settings ( netdev );
+ if ( ( rc = register_settings ( &phantom->settings,
+ parent_settings, "clp" ) ) != 0 ) {
+ DBGC ( phantom, "Phantom %p could not register settings: "
+ "%s\n", phantom, strerror ( rc ) );
+ goto err_register_settings;
+ }
+
+ return 0;
+
+ unregister_settings ( &phantom->settings );
+ err_register_settings:
+ unregister_netdev ( netdev );
+ err_register_netdev:
+ err_check_boot_enable:
+ err_init_rcvpeg:
+ err_init_cmdpeg:
+ err_map_crb:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ err_alloc_etherdev:
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void phantom_remove ( struct pci_device *pci ) {
+ struct net_device *netdev = pci_get_drvdata ( pci );
+ struct phantom_nic *phantom = netdev_priv ( netdev );
+
+ unregister_settings ( &phantom->settings );
+ unregister_netdev ( netdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/** Phantom PCI IDs */
+static struct pci_device_id phantom_nics[] = {
+ PCI_ROM ( 0x4040, 0x0100, "nx", "NX", 0 ),
+};
+
+/** Phantom PCI driver */
+struct pci_driver phantom_driver __pci_driver = {
+ .ids = phantom_nics,
+ .id_count = ( sizeof ( phantom_nics ) / sizeof ( phantom_nics[0] ) ),
+ .probe = phantom_probe,
+ .remove = phantom_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/phantom.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/phantom.h
new file mode 100644
index 00000000..a55f32fb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/phantom.h
@@ -0,0 +1,212 @@
+#ifndef _PHANTOM_H
+#define _PHANTOM_H
+
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ * Copyright (C) 2008 NetXen, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * NetXen Phantom NICs
+ *
+ */
+
+#include <stdint.h>
+
+/* Drag in hardware definitions */
+#include "nx_bitops.h"
+#include "phantom_hw.h"
+struct phantom_rds { NX_PSEUDO_BIT_STRUCT ( struct phantom_rds_pb ) };
+struct phantom_sds { NX_PSEUDO_BIT_STRUCT ( struct phantom_sds_pb ) };
+union phantom_cds { NX_PSEUDO_BIT_STRUCT ( union phantom_cds_pb ) };
+
+/* Drag in firmware interface definitions */
+typedef uint8_t U8;
+typedef uint16_t U16;
+typedef uint32_t U32;
+typedef uint64_t U64;
+typedef uint32_t nx_rcode_t;
+#define NXHAL_VERSION 1
+#include "nxhal_nic_interface.h"
+
+/** DMA buffer alignment */
+#define UNM_DMA_BUFFER_ALIGN 16
+
+/** Mark structure as DMA-aligned */
+#define __unm_dma_aligned __attribute__ (( aligned ( UNM_DMA_BUFFER_ALIGN ) ))
+
+/******************************************************************************
+ *
+ * Register definitions
+ *
+ */
+
+#define UNM_128M_CRB_WINDOW 0x6110210UL
+#define UNM_32M_CRB_WINDOW 0x0110210UL
+#define UNM_2M_CRB_WINDOW 0x0130060UL
+
+/**
+ * Phantom register blocks
+ *
+ * The upper address bits vary between cards. We define an abstract
+ * address space in which the upper 8 bits of the 32-bit register
+ * address encode the register block. This gets translated to a bus
+ * address by the phantom_crb_access_xxx() methods.
+ */
+enum unm_reg_blocks {
+ UNM_CRB_BLK_PCIE = 0x01,
+ UNM_CRB_BLK_CAM = 0x22,
+ UNM_CRB_BLK_ROMUSB = 0x33,
+ UNM_CRB_BLK_TEST = 0x02,
+ UNM_CRB_BLK_PEG_0 = 0x11,
+ UNM_CRB_BLK_PEG_1 = 0x12,
+ UNM_CRB_BLK_PEG_2 = 0x13,
+ UNM_CRB_BLK_PEG_3 = 0x14,
+ UNM_CRB_BLK_PEG_4 = 0x0f,
+};
+#define UNM_CRB_BASE(blk) ( (blk) << 20 )
+#define UNM_CRB_BLK(reg) ( (reg) >> 20 )
+#define UNM_CRB_OFFSET(reg) ( (reg) & 0x000fffff )
+
+#define UNM_CRB_PCIE UNM_CRB_BASE ( UNM_CRB_BLK_PCIE )
+#define UNM_PCIE_SEM2_LOCK ( UNM_CRB_PCIE + 0x1c010 )
+#define UNM_PCIE_SEM2_UNLOCK ( UNM_CRB_PCIE + 0x1c014 )
+#define UNM_PCIE_IRQ_VECTOR ( UNM_CRB_PCIE + 0x10100 )
+#define UNM_PCIE_IRQ_VECTOR_BIT(n) ( 1 << ( (n) + 7 ) )
+#define UNM_PCIE_IRQ_STATE ( UNM_CRB_PCIE + 0x1206c )
+#define UNM_PCIE_IRQ_STATE_TRIGGERED(state) (( (state) & 0x300 ) == 0x200 )
+#define UNM_PCIE_IRQ_MASK_F0 ( UNM_CRB_PCIE + 0x10128 )
+#define UNM_PCIE_IRQ_MASK_F1 ( UNM_CRB_PCIE + 0x10170 )
+#define UNM_PCIE_IRQ_MASK_F2 ( UNM_CRB_PCIE + 0x10174 )
+#define UNM_PCIE_IRQ_MASK_F3 ( UNM_CRB_PCIE + 0x10178 )
+#define UNM_PCIE_IRQ_MASK_F4 ( UNM_CRB_PCIE + 0x10370 )
+#define UNM_PCIE_IRQ_MASK_F5 ( UNM_CRB_PCIE + 0x10374 )
+#define UNM_PCIE_IRQ_MASK_F6 ( UNM_CRB_PCIE + 0x10378 )
+#define UNM_PCIE_IRQ_MASK_F7 ( UNM_CRB_PCIE + 0x1037c )
+#define UNM_PCIE_IRQ_MASK_MAGIC 0x0000fbffUL
+#define UNM_PCIE_IRQ_STATUS_F0 ( UNM_CRB_PCIE + 0x10118 )
+#define UNM_PCIE_IRQ_STATUS_F1 ( UNM_CRB_PCIE + 0x10160 )
+#define UNM_PCIE_IRQ_STATUS_F2 ( UNM_CRB_PCIE + 0x10164 )
+#define UNM_PCIE_IRQ_STATUS_F3 ( UNM_CRB_PCIE + 0x10168 )
+#define UNM_PCIE_IRQ_STATUS_F4 ( UNM_CRB_PCIE + 0x10360 )
+#define UNM_PCIE_IRQ_STATUS_F5 ( UNM_CRB_PCIE + 0x10364 )
+#define UNM_PCIE_IRQ_STATUS_F6 ( UNM_CRB_PCIE + 0x10368 )
+#define UNM_PCIE_IRQ_STATUS_F7 ( UNM_CRB_PCIE + 0x1036c )
+#define UNM_PCIE_IRQ_STATUS_MAGIC 0xffffffffUL
+
+#define UNM_CRB_CAM UNM_CRB_BASE ( UNM_CRB_BLK_CAM )
+
+#define UNM_CAM_RAM ( UNM_CRB_CAM + 0x02000 )
+#define UNM_CAM_RAM_PORT_MODE ( UNM_CAM_RAM + 0x00024 )
+#define UNM_CAM_RAM_PORT_MODE_AUTO_NEG 4
+#define UNM_CAM_RAM_PORT_MODE_AUTO_NEG_1G 5
+#define UNM_CAM_RAM_DMESG_HEAD(n) ( UNM_CAM_RAM + 0x00030 + (n) * 0x10 )
+#define UNM_CAM_RAM_DMESG_LEN(n) ( UNM_CAM_RAM + 0x00034 + (n) * 0x10 )
+#define UNM_CAM_RAM_DMESG_TAIL(n) ( UNM_CAM_RAM + 0x00038 + (n) * 0x10 )
+#define UNM_CAM_RAM_DMESG_SIG(n) ( UNM_CAM_RAM + 0x0003c + (n) * 0x10 )
+#define UNM_CAM_RAM_DMESG_SIG_MAGIC 0xcafebabeUL
+#define UNM_CAM_RAM_NUM_DMESG_BUFFERS 5
+#define UNM_CAM_RAM_CLP_COMMAND ( UNM_CAM_RAM + 0x000c0 )
+#define UNM_CAM_RAM_CLP_COMMAND_LAST 0x00000080UL
+#define UNM_CAM_RAM_CLP_DATA_LO ( UNM_CAM_RAM + 0x000c4 )
+#define UNM_CAM_RAM_CLP_DATA_HI ( UNM_CAM_RAM + 0x000c8 )
+#define UNM_CAM_RAM_CLP_STATUS ( UNM_CAM_RAM + 0x000cc )
+#define UNM_CAM_RAM_CLP_STATUS_START 0x00000001UL
+#define UNM_CAM_RAM_CLP_STATUS_DONE 0x00000002UL
+#define UNM_CAM_RAM_CLP_STATUS_ERROR 0x0000ff00UL
+#define UNM_CAM_RAM_CLP_STATUS_UNINITIALISED 0xffffffffUL
+#define UNM_CAM_RAM_BOOT_ENABLE ( UNM_CAM_RAM + 0x000fc )
+#define UNM_CAM_RAM_WOL_PORT_MODE ( UNM_CAM_RAM + 0x00198 )
+#define UNM_CAM_RAM_MAC_ADDRS ( UNM_CAM_RAM + 0x001c0 )
+#define UNM_CAM_RAM_COLD_BOOT ( UNM_CAM_RAM + 0x001fc )
+#define UNM_CAM_RAM_COLD_BOOT_MAGIC 0x55555555UL
+
+#define UNM_NIC_REG ( UNM_CRB_CAM + 0x02200 )
+#define UNM_NIC_REG_NX_CDRP ( UNM_NIC_REG + 0x00018 )
+#define UNM_NIC_REG_NX_ARG1 ( UNM_NIC_REG + 0x0001c )
+#define UNM_NIC_REG_NX_ARG2 ( UNM_NIC_REG + 0x00020 )
+#define UNM_NIC_REG_NX_ARG3 ( UNM_NIC_REG + 0x00024 )
+#define UNM_NIC_REG_NX_SIGN ( UNM_NIC_REG + 0x00028 )
+#define UNM_NIC_REG_DUMMY_BUF_ADDR_HI ( UNM_NIC_REG + 0x0003c )
+#define UNM_NIC_REG_DUMMY_BUF_ADDR_LO ( UNM_NIC_REG + 0x00040 )
+#define UNM_NIC_REG_CMDPEG_STATE ( UNM_NIC_REG + 0x00050 )
+#define UNM_NIC_REG_CMDPEG_STATE_INITIALIZED 0xff01
+#define UNM_NIC_REG_CMDPEG_STATE_INITIALIZE_ACK 0xf00f
+#define UNM_NIC_REG_DUMMY_BUF ( UNM_NIC_REG + 0x000fc )
+#define UNM_NIC_REG_DUMMY_BUF_INIT 0
+#define UNM_NIC_REG_XG_STATE_P3 ( UNM_NIC_REG + 0x00098 )
+#define UNM_NIC_REG_XG_STATE_P3_LINK( port, state_p3 ) \
+ ( ( (state_p3) >> ( (port) * 4 ) ) & 0x0f )
+#define UNM_NIC_REG_XG_STATE_P3_LINK_UP 0x01
+#define UNM_NIC_REG_XG_STATE_P3_LINK_DOWN 0x02
+#define UNM_NIC_REG_RCVPEG_STATE ( UNM_NIC_REG + 0x0013c )
+#define UNM_NIC_REG_RCVPEG_STATE_INITIALIZED 0xff01
+
+#define UNM_CRB_ROMUSB UNM_CRB_BASE ( UNM_CRB_BLK_ROMUSB )
+
+#define UNM_ROMUSB_GLB ( UNM_CRB_ROMUSB + 0x00000 )
+#define UNM_ROMUSB_GLB_STATUS ( UNM_ROMUSB_GLB + 0x00004 )
+#define UNM_ROMUSB_GLB_STATUS_ROM_DONE ( 1 << 1 )
+#define UNM_ROMUSB_GLB_SW_RESET ( UNM_ROMUSB_GLB + 0x00008 )
+#define UNM_ROMUSB_GLB_SW_RESET_MAGIC 0x0080000fUL
+#define UNM_ROMUSB_GLB_PEGTUNE_DONE ( UNM_ROMUSB_GLB + 0x0005c )
+#define UNM_ROMUSB_GLB_PEGTUNE_DONE_MAGIC 0x31
+
+#define UNM_ROMUSB_ROM ( UNM_CRB_ROMUSB + 0x10000 )
+#define UNM_ROMUSB_ROM_INSTR_OPCODE ( UNM_ROMUSB_ROM + 0x00004 )
+#define UNM_ROMUSB_ROM_ADDRESS ( UNM_ROMUSB_ROM + 0x00008 )
+#define UNM_ROMUSB_ROM_WDATA ( UNM_ROMUSB_ROM + 0x0000c )
+#define UNM_ROMUSB_ROM_ABYTE_CNT ( UNM_ROMUSB_ROM + 0x00010 )
+#define UNM_ROMUSB_ROM_DUMMY_BYTE_CNT ( UNM_ROMUSB_ROM + 0x00014 )
+#define UNM_ROMUSB_ROM_RDATA ( UNM_ROMUSB_ROM + 0x00018 )
+
+#define UNM_CRB_TEST UNM_CRB_BASE ( UNM_CRB_BLK_TEST )
+
+#define UNM_TEST_CONTROL ( UNM_CRB_TEST + 0x00090 )
+#define UNM_TEST_CONTROL_START 0x01
+#define UNM_TEST_CONTROL_ENABLE 0x02
+#define UNM_TEST_CONTROL_BUSY 0x08
+#define UNM_TEST_ADDR_LO ( UNM_CRB_TEST + 0x00094 )
+#define UNM_TEST_ADDR_HI ( UNM_CRB_TEST + 0x00098 )
+#define UNM_TEST_RDDATA_LO ( UNM_CRB_TEST + 0x000a8 )
+#define UNM_TEST_RDDATA_HI ( UNM_CRB_TEST + 0x000ac )
+
+#define UNM_CRB_PEG_0 UNM_CRB_BASE ( UNM_CRB_BLK_PEG_0 )
+#define UNM_PEG_0_HALT_STATUS ( UNM_CRB_PEG_0 + 0x00030 )
+#define UNM_PEG_0_HALT ( UNM_CRB_PEG_0 + 0x0003c )
+
+#define UNM_CRB_PEG_1 UNM_CRB_BASE ( UNM_CRB_BLK_PEG_1 )
+#define UNM_PEG_1_HALT_STATUS ( UNM_CRB_PEG_1 + 0x00030 )
+#define UNM_PEG_1_HALT ( UNM_CRB_PEG_1 + 0x0003c )
+
+#define UNM_CRB_PEG_2 UNM_CRB_BASE ( UNM_CRB_BLK_PEG_2 )
+#define UNM_PEG_2_HALT_STATUS ( UNM_CRB_PEG_2 + 0x00030 )
+#define UNM_PEG_2_HALT ( UNM_CRB_PEG_2 + 0x0003c )
+
+#define UNM_CRB_PEG_3 UNM_CRB_BASE ( UNM_CRB_BLK_PEG_3 )
+#define UNM_PEG_3_HALT_STATUS ( UNM_CRB_PEG_3 + 0x00030 )
+#define UNM_PEG_3_HALT ( UNM_CRB_PEG_3 + 0x0003c )
+
+#define UNM_CRB_PEG_4 UNM_CRB_BASE ( UNM_CRB_BLK_PEG_4 )
+#define UNM_PEG_4_HALT_STATUS ( UNM_CRB_PEG_4 + 0x00030 )
+#define UNM_PEG_4_HALT ( UNM_CRB_PEG_4 + 0x0003c )
+
+#endif /* _PHANTOM_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/phantom_hw.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/phantom_hw.h
new file mode 100644
index 00000000..950f36a4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/phantom/phantom_hw.h
@@ -0,0 +1,184 @@
+#ifndef _PHANTOM_HW_H
+#define _PHANTOM_HW_H
+
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ * Copyright (C) 2008 NetXen, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Phantom hardware definitions
+ *
+ */
+
+/** A Phantom RX descriptor */
+struct phantom_rds_pb {
+ pseudo_bit_t handle[16]; /**< Reference handle */
+ pseudo_bit_t flags[16]; /**< Flags */
+ pseudo_bit_t length[32]; /**< Buffer length */
+
+ /* --------------------------------------------------------------- */
+
+ pseudo_bit_t dma_addr[64]; /**< Buffer DMA address */
+
+};
+
+/** A Phantom RX status descriptor */
+struct phantom_sds_pb {
+ pseudo_bit_t port[4]; /**< Port number */
+ pseudo_bit_t status[4]; /**< Checksum status */
+ pseudo_bit_t type[4]; /**< Type */
+ pseudo_bit_t total_length[16]; /**< Total packet length */
+ pseudo_bit_t handle[16]; /**< Reference handle */
+ pseudo_bit_t protocol[4]; /**< Protocol */
+ pseudo_bit_t pkt_offset[5]; /**< Offset to packet start */
+ pseudo_bit_t desc_cnt[3]; /**< Descriptor count */
+ pseudo_bit_t owner[2]; /**< Owner */
+ pseudo_bit_t opcode[6]; /**< Opcode */
+
+ /* --------------------------------------------------------------- */
+
+ pseudo_bit_t hash_value[32]; /**< RSS hash value */
+ pseudo_bit_t hash_type[8]; /**< RSS hash type */
+ pseudo_bit_t lro[8]; /**< LRO data */
+};
+
+/** Phantom RX status opcodes */
+enum phantom_sds_opcode {
+ UNM_SYN_OFFLOAD = 0x03,
+ UNM_RXPKT_DESC = 0x04,
+};
+
+/** A Phantom TX descriptor */
+struct phantom_tx_cds_pb {
+ pseudo_bit_t tcp_hdr_offset[8]; /**< TCP header offset (LSO) */
+ pseudo_bit_t ip_hdr_offset[8]; /**< IP header offset (LSO) */
+ pseudo_bit_t flags[7]; /**< Flags */
+ pseudo_bit_t opcode[6]; /**< Opcode */
+ pseudo_bit_t hw_rsvd_0[3]; /**< (Reserved) */
+ pseudo_bit_t num_buffers[8]; /**< Total number of buffers */
+ pseudo_bit_t length[24]; /**< Total length */
+
+ /* --------------------------------------------------------------- */
+
+ pseudo_bit_t buffer2_dma_addr[64]; /**< Buffer 2 DMA address */
+
+ /* --------------------------------------------------------------- */
+
+ pseudo_bit_t handle[16]; /**< Reference handle (n/a) */
+ pseudo_bit_t port_mss[16]; /**< TCP MSS (LSO) */
+ pseudo_bit_t port[4]; /**< Port */
+ pseudo_bit_t context_id[4]; /**< Context ID */
+ pseudo_bit_t total_hdr_length[8]; /**< MAC+IP+TCP header (LSO) */
+ pseudo_bit_t conn_id[16]; /**< IPSec connection ID */
+
+ /* --------------------------------------------------------------- */
+
+ pseudo_bit_t buffer3_dma_addr[64]; /**< Buffer 3 DMA address */
+
+ /* --------------------------------------------------------------- */
+
+ pseudo_bit_t buffer1_dma_addr[64]; /**< Buffer 1 DMA address */
+
+ /* --------------------------------------------------------------- */
+
+ pseudo_bit_t buffer1_length[16]; /**< Buffer 1 length */
+ pseudo_bit_t buffer2_length[16]; /**< Buffer 2 length */
+ pseudo_bit_t buffer3_length[16]; /**< Buffer 3 length */
+ pseudo_bit_t buffer4_length[16]; /**< Buffer 4 length */
+
+ /* --------------------------------------------------------------- */
+
+ pseudo_bit_t buffer4_dma_addr[64]; /**< Buffer 4 DMA address */
+
+ /* --------------------------------------------------------------- */
+
+ pseudo_bit_t hw_rsvd_1[64]; /**< (Reserved) */
+};
+
+/** A Phantom MAC address request body */
+struct phantom_nic_request_body_mac_request_pb {
+ pseudo_bit_t opcode[8]; /**< Opcode */
+ pseudo_bit_t tag[8]; /**< Tag */
+ pseudo_bit_t mac_addr_0[8]; /**< MAC address byte 0 */
+ pseudo_bit_t mac_addr_1[8]; /**< MAC address byte 1 */
+ pseudo_bit_t mac_addr_2[8]; /**< MAC address byte 2 */
+ pseudo_bit_t mac_addr_3[8]; /**< MAC address byte 3 */
+ pseudo_bit_t mac_addr_4[8]; /**< MAC address byte 4 */
+ pseudo_bit_t mac_addr_5[8]; /**< MAC address byte 5 */
+};
+
+/** Phantom MAC request opcodes */
+enum phantom_mac_request_opcode {
+ UNM_MAC_ADD = 0x01, /**< Add MAC address */
+ UNM_MAC_DEL = 0x02, /**< Delete MAC address */
+};
+
+/** A Phantom NIC request command descriptor */
+struct phantom_nic_request_cds_pb {
+ struct {
+ pseudo_bit_t dst_minor[18];
+ pseudo_bit_t dst_subq[1];
+ pseudo_bit_t dst_major[4];
+ pseudo_bit_t opcode[6];
+ pseudo_bit_t hw_rsvd_0[3];
+ pseudo_bit_t msginfo[24];
+ pseudo_bit_t hw_rsvd_1[2];
+ pseudo_bit_t qmsg_type[6];
+ } common;
+
+ /* --------------------------------------------------------------- */
+
+ struct {
+ pseudo_bit_t opcode[8];
+ pseudo_bit_t comp_id [8];
+ pseudo_bit_t context_id[16];
+ pseudo_bit_t need_completion[1];
+ pseudo_bit_t hw_rsvd_0[23];
+ pseudo_bit_t sub_opcode[8];
+ } header;
+
+ /* --------------------------------------------------------------- */
+
+ union {
+ struct phantom_nic_request_body_mac_request_pb mac_request;
+ pseudo_bit_t padding[384];
+ } body;
+};
+
+/** Phantom NIC request opcodes */
+enum phantom_nic_request_opcode {
+ UNM_MAC_EVENT = 0x01, /**< Add/delete MAC address */
+};
+
+/** A Phantom command descriptor */
+union phantom_cds_pb {
+ struct phantom_tx_cds_pb tx;
+ struct phantom_nic_request_cds_pb nic_request;
+};
+
+/** Phantom command descriptor opcodes */
+enum phantom_cds_opcode {
+ UNM_TX_ETHER_PKT = 0x01, /**< Transmit raw Ethernet */
+ UNM_NIC_REQUEST = 0x14, /**< NIC request */
+};
+
+#endif /* _PHANTOM_HW_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/pnic.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/pnic.c
new file mode 100644
index 00000000..a02c9de3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/pnic.c
@@ -0,0 +1,289 @@
+/**************************************************************************
+Etherboot - BOOTP/TFTP Bootstrap Program
+Bochs Pseudo NIC driver for Etherboot
+***************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ *
+ * See pnic_api.h for an explanation of the Bochs Pseudo NIC.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <ipxe/io.h>
+#include <errno.h>
+#include <ipxe/pci.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+
+#include "pnic_api.h"
+
+struct pnic {
+ unsigned short ioaddr;
+};
+
+/*
+ * Utility functions: issue a PNIC command, retrieve result. Use
+ * pnic_command_quiet if you don't want failure codes to be
+ * automatically printed. Returns the PNIC status code.
+ *
+ * Set output_length to NULL only if you expect to receive exactly
+ * output_max_length bytes, otherwise it'll complain that you didn't
+ * get enough data (on the assumption that if you not interested in
+ * discovering the output length then you're expecting a fixed amount
+ * of data).
+ */
+
+static uint16_t pnic_command_quiet ( struct pnic *pnic, uint16_t command,
+ const void *input, uint16_t input_length,
+ void *output, uint16_t output_max_length,
+ uint16_t *output_length ) {
+ uint16_t status;
+ uint16_t _output_length;
+
+ if ( input != NULL ) {
+ /* Write input length */
+ outw ( input_length, pnic->ioaddr + PNIC_REG_LEN );
+ /* Write input data */
+ outsb ( pnic->ioaddr + PNIC_REG_DATA, input, input_length );
+ }
+ /* Write command */
+ outw ( command, pnic->ioaddr + PNIC_REG_CMD );
+ /* Retrieve status */
+ status = inw ( pnic->ioaddr + PNIC_REG_STAT );
+ /* Retrieve output length */
+ _output_length = inw ( pnic->ioaddr + PNIC_REG_LEN );
+ if ( output_length == NULL ) {
+ if ( _output_length != output_max_length ) {
+ printf ( "pnic_command %#hx: wrong data length "
+ "returned (expected %d, got %d)\n", command,
+ output_max_length, _output_length );
+ }
+ } else {
+ *output_length = _output_length;
+ }
+ if ( output != NULL ) {
+ if ( _output_length > output_max_length ) {
+ printf ( "pnic_command %#hx: output buffer too small "
+ "(have %d, need %d)\n", command,
+ output_max_length, _output_length );
+ _output_length = output_max_length;
+ }
+ /* Retrieve output data */
+ insb ( pnic->ioaddr + PNIC_REG_DATA, output, _output_length );
+ }
+ return status;
+}
+
+static uint16_t pnic_command ( struct pnic *pnic, uint16_t command,
+ const void *input, uint16_t input_length,
+ void *output, uint16_t output_max_length,
+ uint16_t *output_length ) {
+ uint16_t status = pnic_command_quiet ( pnic, command,
+ input, input_length,
+ output, output_max_length,
+ output_length );
+ if ( status == PNIC_STATUS_OK ) return status;
+ printf ( "PNIC command %#hx (len %#hx) failed with status %#hx\n",
+ command, input_length, status );
+ return status;
+}
+
+/* Check API version matches that of NIC */
+static int pnic_api_check ( uint16_t api_version ) {
+ if ( api_version != PNIC_API_VERSION ) {
+ printf ( "Warning: API version mismatch! "
+ "(NIC's is %d.%d, ours is %d.%d)\n",
+ api_version >> 8, api_version & 0xff,
+ PNIC_API_VERSION >> 8, PNIC_API_VERSION & 0xff );
+ }
+ if ( api_version < PNIC_API_VERSION ) {
+ printf ( "** You may need to update your copy of Bochs **\n" );
+ }
+ return ( api_version == PNIC_API_VERSION );
+}
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static void pnic_poll ( struct net_device *netdev ) {
+ struct pnic *pnic = netdev->priv;
+ struct io_buffer *iobuf;
+ uint16_t length;
+ uint16_t qlen;
+
+ /* Fetch all available packets */
+ while ( 1 ) {
+ if ( pnic_command ( pnic, PNIC_CMD_RECV_QLEN, NULL, 0,
+ &qlen, sizeof ( qlen ), NULL )
+ != PNIC_STATUS_OK )
+ return;
+ if ( qlen == 0 )
+ return;
+ iobuf = alloc_iob ( ETH_FRAME_LEN );
+ if ( ! iobuf ) {
+ DBG ( "could not allocate buffer\n" );
+ netdev_rx_err ( netdev, NULL, -ENOMEM );
+ return;
+ }
+ if ( pnic_command ( pnic, PNIC_CMD_RECV, NULL, 0,
+ iobuf->data, ETH_FRAME_LEN, &length )
+ != PNIC_STATUS_OK ) {
+ netdev_rx_err ( netdev, iobuf, -EIO );
+ return;
+ }
+ iob_put ( iobuf, length );
+ netdev_rx ( netdev, iobuf );
+ }
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static int pnic_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
+ struct pnic *pnic = netdev->priv;
+
+ /* Pad the packet */
+ iob_pad ( iobuf, ETH_ZLEN );
+
+ /* Send packet */
+ pnic_command ( pnic, PNIC_CMD_XMIT, iobuf->data, iob_len ( iobuf ),
+ NULL, 0, NULL );
+
+ netdev_tx_complete ( netdev, iobuf );
+ return 0;
+}
+
+/**************************************************************************
+OPEN - Open network device
+***************************************************************************/
+static int pnic_open ( struct net_device *netdev __unused ) {
+ /* Nothing to do */
+ return 0;
+}
+
+/**************************************************************************
+CLOSE - Close network device
+***************************************************************************/
+static void pnic_close ( struct net_device *netdev __unused ) {
+ /* Nothing to do */
+}
+
+/**************************************************************************
+IRQ - Enable/disable interrupts
+***************************************************************************/
+static void pnic_irq ( struct net_device *netdev, int enable ) {
+ struct pnic *pnic = netdev->priv;
+ uint8_t mask = ( enable ? 1 : 0 );
+
+ pnic_command ( pnic, PNIC_CMD_MASK_IRQ, &mask, sizeof ( mask ),
+ NULL, 0, NULL );
+}
+
+/**************************************************************************
+OPERATIONS TABLE
+***************************************************************************/
+static struct net_device_operations pnic_operations = {
+ .open = pnic_open,
+ .close = pnic_close,
+ .transmit = pnic_transmit,
+ .poll = pnic_poll,
+ .irq = pnic_irq,
+};
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void pnic_remove ( struct pci_device *pci ) {
+ struct net_device *netdev = pci_get_drvdata ( pci );
+ struct pnic *pnic = netdev->priv;
+
+ unregister_netdev ( netdev );
+ pnic_command ( pnic, PNIC_CMD_RESET, NULL, 0, NULL, 0, NULL );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+static int pnic_probe ( struct pci_device *pci ) {
+ struct net_device *netdev;
+ struct pnic *pnic;
+ uint16_t api_version;
+ uint16_t status;
+ int rc;
+
+ /* Allocate net device */
+ netdev = alloc_etherdev ( sizeof ( *pnic ) );
+ if ( ! netdev )
+ return -ENOMEM;
+ netdev_init ( netdev, &pnic_operations );
+ pnic = netdev->priv;
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+ pnic->ioaddr = pci->ioaddr;
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* API version check */
+ status = pnic_command_quiet ( pnic, PNIC_CMD_API_VER, NULL, 0,
+ &api_version,
+ sizeof ( api_version ), NULL );
+ if ( status != PNIC_STATUS_OK ) {
+ printf ( "PNIC failed installation check, code %#hx\n",
+ status );
+ rc = -EIO;
+ goto err;
+ }
+ pnic_api_check ( api_version );
+
+ /* Get MAC address */
+ status = pnic_command ( pnic, PNIC_CMD_READ_MAC, NULL, 0,
+ netdev->hw_addr, ETH_ALEN, NULL );
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err;
+
+ /* Mark as link up; PNIC has no concept of link state */
+ netdev_link_up ( netdev );
+
+ return 0;
+
+ err:
+ /* Free net device */
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ return rc;
+}
+
+static struct pci_device_id pnic_nics[] = {
+/* genrules.pl doesn't let us use macros for PCI IDs...*/
+PCI_ROM ( 0xfefe, 0xefef, "pnic", "Bochs Pseudo NIC Adaptor", 0 ),
+};
+
+struct pci_driver pnic_driver __pci_driver = {
+ .ids = pnic_nics,
+ .id_count = ( sizeof ( pnic_nics ) / sizeof ( pnic_nics[0] ) ),
+ .probe = pnic_probe,
+ .remove = pnic_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/pnic_api.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/pnic_api.h
new file mode 100644
index 00000000..27e02363
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/pnic_api.h
@@ -0,0 +1,61 @@
+/*
+ * Constants etc. for the Bochs/Etherboot pseudo-NIC
+ *
+ * This header file must be valid C and C++.
+ *
+ * Operation of the pseudo-NIC (PNIC) is pretty simple. To write a
+ * command plus data, first write the length of the data to
+ * PNIC_REG_LEN, then write the data a byte at a type to
+ * PNIC_REG_DATA, then write the command code to PNIC_REG_CMD. The
+ * status will be available from PNIC_REG_STAT. The length of any
+ * data returned will be in PNIC_REG_LEN and can be read a byte at a
+ * time from PNIC_REG_DATA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * PCI parameters
+ */
+#define PNIC_PCI_VENDOR 0xfefe /* Hopefully these won't clash with */
+#define PNIC_PCI_DEVICE 0xefef /* any real PCI device IDs. */
+
+/*
+ * 'Hardware' register addresses, offset from io_base
+ */
+#define PNIC_REG_CMD 0x00 /* Command register, 2 bytes, write only */
+#define PNIC_REG_STAT 0x00 /* Status register, 2 bytes, read only */
+#define PNIC_REG_LEN 0x02 /* Length register, 2 bytes, read-write */
+#define PNIC_REG_DATA 0x04 /* Data port, 1 byte, read-write */
+/*
+ * PNIC_MAX_REG used in Bochs to claim i/o space
+ */
+#define PNIC_MAX_REG 0x04
+
+/*
+ * Command code definitions: write these into PNIC_REG_CMD
+ */
+#define PNIC_CMD_NOOP 0x0000
+#define PNIC_CMD_API_VER 0x0001
+#define PNIC_CMD_READ_MAC 0x0002
+#define PNIC_CMD_RESET 0x0003
+#define PNIC_CMD_XMIT 0x0004
+#define PNIC_CMD_RECV 0x0005
+#define PNIC_CMD_RECV_QLEN 0x0006
+#define PNIC_CMD_MASK_IRQ 0x0007
+#define PNIC_CMD_FORCE_IRQ 0x0008
+
+/*
+ * Status code definitions: read these from PNIC_REG_STAT
+ *
+ * We avoid using status codes that might be confused with
+ * randomly-read data (e.g. 0x0000, 0xffff etc.)
+ */
+#define PNIC_STATUS_OK 0x4f4b /* 'OK' */
+#define PNIC_STATUS_UNKNOWN_CMD 0x3f3f /* '??' */
+
+/*
+ * Other miscellaneous information
+ */
+
+#define PNIC_API_VERSION 0x0101 /* 1.1 */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/prism2.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/prism2.c
new file mode 100644
index 00000000..f2df69d0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/prism2.c
@@ -0,0 +1,866 @@
+/**************************************************************************
+Etherboot - BOOTP/TFTP Bootstrap Program
+Prism2 NIC driver for Etherboot
+
+Written by Michael Brown of Fen Systems Ltd
+$Id: prism2.c $
+***************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <etherboot.h>
+#include <nic.h>
+#include <ipxe/pci.h>
+#include <ipxe/ethernet.h>
+
+/*
+ * Hard-coded SSID
+ * Leave blank in order to connect to any available SSID
+ */
+
+static const char hardcoded_ssid[] = "";
+
+/*
+ * Maximum number of info packets to wait for on a join attempt.
+ * Some APs (including the Linksys WAP11) will send a "you are disconnected" packet
+ * before sending the "you are connected" packet, if the card has previously been
+ * attached to the AP.
+ *
+ * 2 is probably a sensible value, but YMMV.
+ */
+
+#define MAX_JOIN_INFO_COUNT 2
+
+/*
+ * Type of Prism2 interface to support
+ * If not already defined, select PLX
+ */
+#ifndef WLAN_HOSTIF
+#define WLAN_HOSTIF WLAN_PLX
+#endif
+
+/*
+ * Include wlan_compat, p80211 and hfa384x header files from Linux Prism2 driver
+ * We need to hack some defines in order to avoid compiling kernel-specific routines
+ */
+
+#define __LINUX_WLAN__
+#undef __KERNEL__
+#define __I386__
+#include "wlan_compat.h"
+#include "p80211hdr.h"
+#include "hfa384x.h"
+#define BAP_TIMEOUT ( 5000 )
+
+/*
+ * A few hacks to make the coding environment more Linux-like. This makes it somewhat
+ * quicker to convert code from the Linux Prism2 driver.
+ */
+#include <errno.h>
+#define __le16_to_cpu(x) (x)
+#define __le32_to_cpu(x) (x)
+#define __cpu_to_le16(x) (x)
+#define __cpu_to_le32(x) (x)
+
+#define hfa384x2host_16(n) (__le16_to_cpu((UINT16)(n)))
+#define hfa384x2host_32(n) (__le32_to_cpu((UINT32)(n)))
+#define host2hfa384x_16(n) (__cpu_to_le16((UINT16)(n)))
+#define host2hfa384x_32(n) (__cpu_to_le32((UINT32)(n)))
+
+/*
+ * PLX9052 PCI register offsets
+ * Taken from PLX9052 datasheet available from http://www.plxtech.com/download/9052/databook/9052db-20.pdf
+ */
+
+#define PLX_LOCAL_CONFIG_REGISTER_BASE ( PCI_BASE_ADDRESS_1 )
+#define PLX_LOCAL_ADDRESS_SPACE_0_BASE ( PCI_BASE_ADDRESS_2 )
+#define PLX_LOCAL_ADDRESS_SPACE_1_BASE ( PCI_BASE_ADDRESS_3 )
+#define PLX_LOCAL_ADDRESS_SPACE_2_BASE ( PCI_BASE_ADDRESS_4 )
+#define PLX_LOCAL_ADDRESS_SPACE_3_BASE ( PCI_BASE_ADDRESS_5 )
+
+#define PRISM2_PLX_ATTR_MEM_BASE ( PLX_LOCAL_ADDRESS_SPACE_0_BASE )
+#define PRISM2_PLX_IO_BASE ( PLX_LOCAL_ADDRESS_SPACE_1_BASE )
+
+#define PRISM2_PCI_MEM_BASE ( PCI_BASE_ADDRESS_0 )
+
+/*
+ * PCMCIA CIS types
+ * Taken from cistpl.h in pcmcia-cs
+ */
+
+#define CISTPL_VERS_1 ( 0x15 )
+#define CISTPL_END ( 0xff )
+
+#define CIS_STEP ( 2 )
+#define CISTPL_HEADER_LEN ( 2 * CIS_STEP )
+#define CISTPL_LEN_OFF ( 1 * CIS_STEP )
+#define CISTPL_VERS_1_STR_OFF ( 4 * CIS_STEP )
+
+/*
+ * Prism2 constants
+ * Taken from prism2sta.c in linux-wlan-ng
+ */
+
+#define COR_OFFSET ( 0x3e0 ) /* COR attribute offset of Prism2 PC card */
+#define COR_VALUE ( 0x41 ) /* Enable PC card with irq in level trigger (but interrupts disabled) */
+
+/* NIC specific static variables */
+
+/* The hfa384x_t structure is used extensively in the Linux driver but is ifdef'd out in our include since __KERNEL__ is not defined.
+ * This is a dummy version that contains only the fields we are interested in.
+ */
+
+typedef struct hfa384x
+{
+ UINT32 iobase;
+ void *membase;
+ UINT16 lastcmd;
+ UINT16 status; /* in host order */
+ UINT16 resp0; /* in host order */
+ UINT16 resp1; /* in host order */
+ UINT16 resp2; /* in host order */
+ UINT8 bssid[WLAN_BSSID_LEN];
+} hfa384x_t;
+
+/* The global instance of the hardware (i.e. where we store iobase and membase, in the absence of anywhere better to put them */
+static hfa384x_t hw_global = {
+ 0, 0, 0, 0, 0, 0, 0, {0,0,0,0,0,0}
+};
+
+/*
+ * 802.11 headers in addition to those in hfa384x_tx_frame_t (LLC and SNAP)
+ * Taken from p80211conv.h
+ */
+
+typedef struct wlan_llc
+{
+ UINT8 dsap;
+ UINT8 ssap;
+ UINT8 ctl;
+} wlan_llc_t;
+
+static const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 }; /* LLC header indicating SNAP (?) */
+
+#define WLAN_IEEE_OUI_LEN 3
+typedef struct wlan_snap
+{
+ UINT8 oui[WLAN_IEEE_OUI_LEN];
+ UINT16 type;
+} wlan_snap_t;
+
+typedef struct wlan_80211hdr
+{
+ wlan_llc_t llc;
+ wlan_snap_t snap;
+} wlan_80211hdr_t;
+
+/*
+ * Function prototypes
+ */
+
+/*
+ * Hardware-level hfa384x functions
+ * These are based on the ones in hfa384x.h (which are ifdef'd out since __KERNEL__ is not defined).
+ * Basically, these functions are the result of hand-evaluating all the ifdefs and defines in the hfa384x.h versions.
+ */
+
+/* Retrieve the value of one of the MAC registers. */
+static inline UINT16 hfa384x_getreg( hfa384x_t *hw, UINT reg )
+{
+#if (WLAN_HOSTIF == WLAN_PLX)
+ return inw ( hw->iobase + reg );
+#elif (WLAN_HOSTIF == WLAN_PCI)
+ return readw ( hw->membase + reg );
+#endif
+}
+
+/* Set the value of one of the MAC registers. */
+static inline void hfa384x_setreg( hfa384x_t *hw, UINT16 val, UINT reg )
+{
+#if (WLAN_HOSTIF == WLAN_PLX)
+ outw ( val, hw->iobase + reg );
+#elif (WLAN_HOSTIF == WLAN_PCI)
+ writew ( val, hw->membase + reg );
+#endif
+ return;
+}
+
+/*
+ * Noswap versions
+ * Etherboot is i386 only, so swap and noswap are the same...
+ */
+static inline UINT16 hfa384x_getreg_noswap( hfa384x_t *hw, UINT reg )
+{
+ return hfa384x_getreg ( hw, reg );
+}
+static inline void hfa384x_setreg_noswap( hfa384x_t *hw, UINT16 val, UINT reg )
+{
+ hfa384x_setreg ( hw, val, reg );
+}
+
+/*
+ * Low-level hfa384x functions
+ * These are based on the ones in hfa384x.c, modified to work in the Etherboot environment.
+ */
+
+/*
+ * hfa384x_docmd_wait
+ *
+ * Waits for availability of the Command register, then
+ * issues the given command. Then polls the Evstat register
+ * waiting for command completion.
+ * Arguments:
+ * hw device structure
+ * cmd Command in host order
+ * parm0 Parameter0 in host order
+ * parm1 Parameter1 in host order
+ * parm2 Parameter2 in host order
+ * Returns:
+ * 0 success
+ * >0 command indicated error, Status and Resp0-2 are
+ * in hw structure.
+ */
+static int hfa384x_docmd_wait( hfa384x_t *hw, UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2)
+{
+ UINT16 reg = 0;
+ UINT16 counter = 0;
+
+ /* wait for the busy bit to clear */
+ counter = 0;
+ reg = hfa384x_getreg(hw, HFA384x_CMD);
+ while ( HFA384x_CMD_ISBUSY(reg) && (counter < 10) ) {
+ reg = hfa384x_getreg(hw, HFA384x_CMD);
+ counter++;
+ udelay(10);
+ }
+ if (HFA384x_CMD_ISBUSY(reg)) {
+ printf("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg);
+ return -ETIMEDOUT;
+ }
+
+ /* busy bit clear, write command */
+ hfa384x_setreg(hw, parm0, HFA384x_PARAM0);
+ hfa384x_setreg(hw, parm1, HFA384x_PARAM1);
+ hfa384x_setreg(hw, parm2, HFA384x_PARAM2);
+ hw->lastcmd = cmd;
+ hfa384x_setreg(hw, cmd, HFA384x_CMD);
+
+ /* Now wait for completion */
+ counter = 0;
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ /* Initialization is the problem. It takes about
+ 100ms. "normal" commands are typically is about
+ 200-400 us (I've never seen less than 200). Longer
+ is better so that we're not hammering the bus. */
+ while ( !HFA384x_EVSTAT_ISCMD(reg) && (counter < 5000)) {
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ counter++;
+ udelay(200);
+ }
+ if ( ! HFA384x_EVSTAT_ISCMD(reg) ) {
+ printf("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg);
+ return -ETIMEDOUT;
+ }
+
+ /* Read status and response */
+ hw->status = hfa384x_getreg(hw, HFA384x_STATUS);
+ hw->resp0 = hfa384x_getreg(hw, HFA384x_RESP0);
+ hw->resp1 = hfa384x_getreg(hw, HFA384x_RESP1);
+ hw->resp2 = hfa384x_getreg(hw, HFA384x_RESP2);
+ hfa384x_setreg(hw, HFA384x_EVACK_CMD, HFA384x_EVACK);
+ return HFA384x_STATUS_RESULT_GET(hw->status);
+}
+
+/*
+ * Prepare BAP for access. Assigns FID and RID, sets offset register
+ * and waits for BAP to become available.
+ *
+ * Arguments:
+ * hw device structure
+ * id FID or RID, destined for the select register (host order)
+ * offset An _even_ offset into the buffer for the given FID/RID.
+ * Returns:
+ * 0 success
+ */
+static int hfa384x_prepare_bap(hfa384x_t *hw, UINT16 id, UINT16 offset)
+{
+ int result = 0;
+ UINT16 reg;
+ UINT16 i;
+
+ /* Validate offset, buf, and len */
+ if ( (offset > HFA384x_BAP_OFFSET_MAX) || (offset % 2) ) {
+ result = -EINVAL;
+ } else {
+ /* Write fid/rid and offset */
+ hfa384x_setreg(hw, id, HFA384x_SELECT0);
+ udelay(10);
+ hfa384x_setreg(hw, offset, HFA384x_OFFSET0);
+ /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */
+ i = 0;
+ do {
+ reg = hfa384x_getreg(hw, HFA384x_OFFSET0);
+ if ( i > 0 ) udelay(2);
+ i++;
+ } while ( i < BAP_TIMEOUT && HFA384x_OFFSET_ISBUSY(reg));
+ if ( i >= BAP_TIMEOUT ) {
+ /* failure */
+ result = reg;
+ } else if ( HFA384x_OFFSET_ISERR(reg) ){
+ /* failure */
+ result = reg;
+ }
+ }
+ return result;
+}
+
+/*
+ * Copy data from BAP to memory.
+ *
+ * Arguments:
+ * hw device structure
+ * id FID or RID, destined for the select register (host order)
+ * offset An _even_ offset into the buffer for the given FID/RID.
+ * buf ptr to array of bytes
+ * len length of data to transfer in bytes
+ * Returns:
+ * 0 success
+ */
+static int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 id, UINT16 offset,
+ void *buf, UINT len)
+{
+ int result = 0;
+ UINT8 *d = (UINT8*)buf;
+ UINT16 i;
+ UINT16 reg = 0;
+
+ /* Prepare BAP */
+ result = hfa384x_prepare_bap ( hw, id, offset );
+ if ( result == 0 ) {
+ /* Read even(len) buf contents from data reg */
+ for ( i = 0; i < (len & 0xfffe); i+=2 ) {
+ *(UINT16*)(&(d[i])) = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
+ }
+ /* If len odd, handle last byte */
+ if ( len % 2 ){
+ reg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
+ d[len-1] = ((UINT8*)(&reg))[0];
+ }
+ }
+ if (result) {
+ printf ( "copy_from_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
+ }
+ return result;
+}
+
+/*
+ * Copy data from memory to BAP.
+ *
+ * Arguments:
+ * hw device structure
+ * id FID or RID, destined for the select register (host order)
+ * offset An _even_ offset into the buffer for the given FID/RID.
+ * buf ptr to array of bytes
+ * len length of data to transfer in bytes
+ * Returns:
+ * 0 success
+ */
+static int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 id, UINT16 offset,
+ void *buf, UINT len)
+{
+ int result = 0;
+ UINT8 *d = (UINT8*)buf;
+ UINT16 i;
+ UINT16 savereg;
+
+ /* Prepare BAP */
+ result = hfa384x_prepare_bap ( hw, id, offset );
+ if ( result == 0 ) {
+ /* Write even(len) buf contents to data reg */
+ for ( i = 0; i < (len & 0xfffe); i+=2 ) {
+ hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), HFA384x_DATA0);
+ }
+ /* If len odd, handle last byte */
+ if ( len % 2 ){
+ savereg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
+ result = hfa384x_prepare_bap ( hw, id, offset + (len & 0xfffe) );
+ if ( result == 0 ) {
+ ((UINT8*)(&savereg))[0] = d[len-1];
+ hfa384x_setreg_noswap(hw, savereg, HFA384x_DATA0);
+ }
+ }
+ }
+ if (result) {
+ printf ( "copy_to_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
+ }
+ return result;
+}
+
+/*
+ * Request a given record to be copied to/from the record buffer.
+ *
+ * Arguments:
+ * hw device structure
+ * write [0|1] copy the record buffer to the given
+ * configuration record. (host order)
+ * rid RID of the record to read/write. (host order)
+ *
+ * Returns:
+ * 0 success
+ */
+static inline int hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid)
+{
+ return hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | HFA384x_CMD_WRITE_SET(write), rid, 0, 0);
+}
+
+/*
+ * Performs the sequence necessary to read a config/info item.
+ *
+ * Arguments:
+ * hw device structure
+ * rid config/info record id (host order)
+ * buf host side record buffer. Upon return it will
+ * contain the body portion of the record (minus the
+ * RID and len).
+ * len buffer length (in bytes, should match record length)
+ *
+ * Returns:
+ * 0 success
+ */
+static int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
+{
+ int result = 0;
+ hfa384x_rec_t rec;
+
+ /* Request read of RID */
+ result = hfa384x_cmd_access( hw, 0, rid);
+ if ( result ) {
+ printf("Call to hfa384x_cmd_access failed\n");
+ return -1;
+ }
+ /* Copy out record length */
+ result = hfa384x_copy_from_bap( hw, rid, 0, &rec, sizeof(rec));
+ if ( result ) {
+ return -1;
+ }
+ /* Validate the record length */
+ if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) { /* note body len calculation in bytes */
+ printf ( "RID len mismatch, rid=%#hx hlen=%d fwlen=%d\n", rid, len, (hfa384x2host_16(rec.reclen)-1)*2);
+ return -1;
+ }
+ /* Copy out record data */
+ result = hfa384x_copy_from_bap( hw, rid, sizeof(rec), buf, len);
+ return result;
+}
+
+/*
+ * Performs the sequence necessary to read a 16/32 bit config/info item
+ * and convert it to host order.
+ *
+ * Arguments:
+ * hw device structure
+ * rid config/info record id (in host order)
+ * val ptr to 16/32 bit buffer to receive value (in host order)
+ *
+ * Returns:
+ * 0 success
+ */
+#if 0 /* Not actually used anywhere */
+static int hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val)
+{
+ int result = 0;
+ result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16));
+ if ( result == 0 ) {
+ *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val));
+ }
+ return result;
+}
+#endif
+#if 0 /* Not actually used anywhere */
+static int hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val)
+{
+ int result = 0;
+ result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32));
+ if ( result == 0 ) {
+ *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val));
+ }
+ return result;
+}
+#endif
+
+/*
+ * Performs the sequence necessary to write a config/info item.
+ *
+ * Arguments:
+ * hw device structure
+ * rid config/info record id (in host order)
+ * buf host side record buffer
+ * len buffer length (in bytes)
+ *
+ * Returns:
+ * 0 success
+ */
+static int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
+{
+ int result = 0;
+ hfa384x_rec_t rec;
+
+ rec.rid = host2hfa384x_16(rid);
+ rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */
+ /* write the record header */
+ result = hfa384x_copy_to_bap( hw, rid, 0, &rec, sizeof(rec));
+ if ( result ) {
+ printf("Failure writing record header\n");
+ return -1;
+ }
+ /* write the record data (if there is any) */
+ if ( len > 0 ) {
+ result = hfa384x_copy_to_bap( hw, rid, sizeof(rec), buf, len);
+ if ( result ) {
+ printf("Failure writing record data\n");
+ return -1;
+ }
+ }
+ /* Trigger setting of record */
+ result = hfa384x_cmd_access( hw, 1, rid);
+ return result;
+}
+
+/*
+ * Performs the sequence necessary to write a 16/32 bit config/info item.
+ *
+ * Arguments:
+ * hw device structure
+ * rid config/info record id (in host order)
+ * val 16/32 bit value to store (in host order)
+ *
+ * Returns:
+ * 0 success
+ */
+static int hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 *val)
+{
+ UINT16 value;
+ value = host2hfa384x_16(*val);
+ return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT16));
+}
+#if 0 /* Not actually used anywhere */
+static int hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 *val)
+{
+ UINT32 value;
+ value = host2hfa384x_32(*val);
+ return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT32));
+}
+#endif
+
+/*
+ * Wait for an event, with specified checking interval and timeout.
+ * Automatically acknolwedges events.
+ *
+ * Arguments:
+ * hw device structure
+ * event_mask EVSTAT register mask of events to wait for
+ * event_ack EVACK register set of events to be acknowledged if they happen (can be
+ * used to acknowledge "ignorable" events in addition to the "main" event)
+ * wait Time (in us) to wait between each poll of the register
+ * timeout Maximum number of polls before timing out
+ * descr Descriptive text string of what is being waited for
+ * (will be printed out if a timeout happens)
+ *
+ * Returns:
+ * value of EVSTAT register, or 0 on failure
+ */
+static int hfa384x_wait_for_event(hfa384x_t *hw, UINT16 event_mask, UINT16 event_ack, int wait, int timeout, const char *descr)
+{
+ UINT16 reg;
+ int count = 0;
+
+ do {
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ if ( count > 0 ) udelay(wait);
+ count++;
+ } while ( !(reg & event_mask) && count < timeout);
+ if ( count >= timeout ) {
+ printf("hfa384x: Timed out waiting for %s\n", descr);
+ return 0; /* Return failure */
+ }
+ /* Acknowledge all events that we were waiting on */
+ hfa384x_setreg(hw, reg & ( event_mask | event_ack ), HFA384x_EVACK);
+ return reg;
+}
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int prism2_poll(struct nic *nic, int retrieve)
+{
+ UINT16 reg;
+ UINT16 rxfid;
+ UINT16 result;
+ hfa384x_rx_frame_t rxdesc;
+ hfa384x_t *hw = &hw_global;
+
+ /* Check for received packet */
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ if ( ! HFA384x_EVSTAT_ISRX(reg) ) {
+ /* No packet received - return 0 */
+ return 0;
+ }
+
+ if ( ! retrieve ) return 1;
+
+ /* Acknowledge RX event */
+ hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), HFA384x_EVACK);
+ /* Get RX FID */
+ rxfid = hfa384x_getreg(hw, HFA384x_RXFID);
+ /* Get the descriptor (including headers) */
+ result = hfa384x_copy_from_bap(hw, rxfid, 0, &rxdesc, sizeof(rxdesc));
+ if ( result ) {
+ return 0; /* fail */
+ }
+ /* Byte order convert once up front. */
+ rxdesc.status = hfa384x2host_16(rxdesc.status);
+ rxdesc.time = hfa384x2host_32(rxdesc.time);
+ rxdesc.data_len = hfa384x2host_16(rxdesc.data_len);
+
+ /* Fill in nic->packetlen */
+ nic->packetlen = rxdesc.data_len;
+ if ( nic->packetlen > 0 ) {
+ /* Fill in nic->packet */
+ /*
+ * NOTE: Packets as received have an 8-byte header (LLC+SNAP(?)) terminating with the packet type.
+ * Etherboot expects a 14-byte header terminating with the packet type (it ignores the rest of the
+ * header), so we use a quick hack to achieve this.
+ */
+ result = hfa384x_copy_from_bap(hw, rxfid, HFA384x_RX_DATA_OFF,
+ nic->packet + ETH_HLEN - sizeof(wlan_80211hdr_t), nic->packetlen);
+ if ( result ) {
+ return 0; /* fail */
+ }
+ }
+ return 1; /* Packet successfully received */
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void prism2_transmit(
+ struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ hfa384x_t *hw = &hw_global;
+ hfa384x_tx_frame_t txdesc;
+ wlan_80211hdr_t p80211hdr = { wlan_llc_snap, {{0,0,0},0} };
+ UINT16 fid;
+ UINT16 status;
+ int result;
+
+ // Request FID allocation
+ result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC), HFA384x_DRVR_TXBUF_MAX, 0, 0);
+ if (result != 0) {
+ printf("hfa384x: Tx FID allocate command failed: Aborting transmit..\n");
+ return;
+ }
+ if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_ALLOC, HFA384x_EVACK_INFO, 10, 50, "Tx FID to be allocated\n" ) ) return;
+ fid = hfa384x_getreg(hw, HFA384x_ALLOCFID);
+
+ /* Build Tx frame structure */
+ memset(&txdesc, 0, sizeof(txdesc));
+ txdesc.tx_control = host2hfa384x_16( HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
+ HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1) );
+ txdesc.frame_control = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) |
+ WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) |
+ WLAN_SET_FC_TODS(1) );
+ memcpy(txdesc.address1, hw->bssid, WLAN_ADDR_LEN);
+ memcpy(txdesc.address2, nic->node_addr, WLAN_ADDR_LEN);
+ memcpy(txdesc.address3, d, WLAN_ADDR_LEN);
+ txdesc.data_len = host2hfa384x_16( sizeof(txdesc) + sizeof(p80211hdr) + s );
+ /* Set up SNAP header */
+ /* Let OUI default to RFC1042 (0x000000) */
+ p80211hdr.snap.type = htons(t);
+
+ /* Copy txdesc, p80211hdr and payload parts to FID */
+ result = hfa384x_copy_to_bap(hw, fid, 0, &txdesc, sizeof(txdesc));
+ if ( result ) return; /* fail */
+ result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc), &p80211hdr, sizeof(p80211hdr) );
+ if ( result ) return; /* fail */
+ result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc) + sizeof(p80211hdr), (UINT8*)p, s );
+ if ( result ) return; /* fail */
+
+ /* Issue Tx command */
+ result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX), fid, 0, 0);
+ if ( result != 0 ) {
+ printf("hfa384x: Transmit failed with result %#hx.\n", result);
+ return;
+ }
+
+ /* Wait for transmit completion (or exception) */
+ result = hfa384x_wait_for_event(hw, HFA384x_EVSTAT_TXEXC | HFA384x_EVSTAT_TX, HFA384x_EVACK_INFO,
+ 200, 500, "Tx to complete\n" );
+ if ( !result ) return; /* timeout failure */
+ if ( HFA384x_EVSTAT_ISTXEXC(result) ) {
+ fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID);
+ printf ( "Tx exception occurred with fid %#hx\n", fid );
+ result = hfa384x_copy_from_bap(hw, fid, 0, &status, sizeof(status));
+ if ( result ) return; /* fail */
+ printf("hfa384x: Tx error occurred (status %#hx):\n", status);
+ if ( HFA384x_TXSTATUS_ISACKERR(status) ) { printf(" ...acknowledgement error\n"); }
+ if ( HFA384x_TXSTATUS_ISFORMERR(status) ) { printf(" ...format error\n"); }
+ if ( HFA384x_TXSTATUS_ISDISCON(status) ) { printf(" ...disconnected error\n"); }
+ if ( HFA384x_TXSTATUS_ISAGEDERR(status) ) { printf(" ...AGED error\n"); }
+ if ( HFA384x_TXSTATUS_ISRETRYERR(status) ) { printf(" ...retry error\n"); }
+ return; /* fail */
+ }
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void prism2_disable ( struct nic *nic __unused ) {
+ /* put the card in its initial state */
+}
+
+/**************************************************************************
+IRQ - Enable, Disable, or Force interrupts
+***************************************************************************/
+static void prism2_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+/**************************************************************************
+Operations table
+***************************************************************************/
+static struct nic_operations prism2_operations = {
+ .connect = dummy_connect,
+ .poll = prism2_poll,
+ .transmit = prism2_transmit,
+ .irq = prism2_irq,
+};
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+You should omit the last argument struct pci_device * for a non-PCI NIC
+***************************************************************************/
+static int prism2_probe ( struct nic *nic, hfa384x_t *hw ) {
+ int result;
+ UINT16 tmp16 = 0;
+ UINT16 infofid;
+ hfa384x_InfFrame_t inf;
+ char ssid[HFA384x_RID_CNFDESIREDSSID_LEN];
+ int info_count = 0;
+
+ nic->irqno = 0;
+
+ /* Initialize card */
+ result = hfa384x_docmd_wait(hw, HFA384x_CMDCODE_INIT, 0,0,0); /* Send initialize command */
+ if ( result ) printf ( "Initialize command returned %#hx\n", result );
+ hfa384x_setreg(hw, 0, HFA384x_INTEN); /* Disable interrupts */
+ hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); /* Acknowledge any spurious events */
+
+ DBG ( "MAC address %s\n", eth_ntoa ( nic->node_addr ) );
+
+ /* Retrieve MAC address (and fill out nic->node_addr) */
+ hfa384x_drvr_getconfig ( hw, HFA384x_RID_CNFOWNMACADDR, nic->node_addr, HFA384x_RID_CNFOWNMACADDR_LEN );
+
+ /* Prepare card for autojoin */
+ /* This procedure is reverse-engineered from a register-level trace of the Linux driver's join process */
+ tmp16 = WLAN_DATA_MAXLEN; /* Set maximum data length */
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, &tmp16);
+ if ( result ) printf ( "Set Max Data Length command returned %#hx\n", result );
+ tmp16 = 0x000f; /* Set transmit rate(?) */
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, &tmp16);
+ if ( result ) printf ( "Set Transmit Rate command returned %#hx\n", result );
+ tmp16 = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; /* Set authentication type to OpenSystem */
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, &tmp16);
+ if ( result ) printf ( "Set Authentication Type command returned %#hx\n", result );
+ /* Set SSID */
+ memset(ssid, 0, HFA384x_RID_CNFDESIREDSSID_LEN);
+ for ( tmp16=0; tmp16<sizeof(hardcoded_ssid); tmp16++ ) { ssid[2+tmp16] = hardcoded_ssid[tmp16]; }
+ ssid[0] = sizeof(hardcoded_ssid) - 1; /* Ignore terminating zero */
+ result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, ssid, HFA384x_RID_CNFDESIREDSSID_LEN); /* Set the SSID */
+ if ( result ) printf ( "Set SSID command returned %#hx\n", result );
+ tmp16 = 1; /* Set port type to ESS port */
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, &tmp16);
+ if ( result ) printf ( "Set port type command returned %#hx\n", result );
+ /* Enable card */
+ result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | HFA384x_CMD_MACPORT_SET(0), 0,0,0);
+ if ( result ) printf ( "Enable command returned %#hx\n", result );
+
+ do {
+ /* Increment info_count, abort if too many attempts.
+ * See comment next to definition of MAX_JOIN_INFO_COUNT for explanation.
+ */
+ info_count++;
+ if ( info_count > MAX_JOIN_INFO_COUNT ) {
+ printf ( "Too many failed attempts - aborting\n" );
+ return 0;
+ }
+
+ /* Wait for info frame to indicate link status */
+ if ( sizeof(hardcoded_ssid) == 1 ) {
+ /* Empty SSID => join to any SSID */
+ printf ( "Attempting to autojoin to any available access point (attempt %d)...", info_count );
+ } else {
+ printf ( "Attempting to autojoin to SSID %s (attempt %d)...", &ssid[2], info_count );
+ }
+
+ if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_INFO, 0, 1000, 2000, "Info event" ) ) return 0;
+ printf("done\n");
+ infofid = hfa384x_getreg(hw, HFA384x_INFOFID);
+ /* Retrieve the length */
+ result = hfa384x_copy_from_bap( hw, infofid, 0, &inf.framelen, sizeof(UINT16));
+ if ( result ) return 0; /* fail */
+ inf.framelen = hfa384x2host_16(inf.framelen);
+ /* Retrieve the rest */
+ result = hfa384x_copy_from_bap( hw, infofid, sizeof(UINT16),
+ &(inf.infotype), inf.framelen * sizeof(UINT16));
+ if ( result ) return 0; /* fail */
+ if ( inf.infotype != HFA384x_IT_LINKSTATUS ) {
+ /* Not a Link Status info frame: die */
+ printf ( "Unexpected info frame type %#hx (not LinkStatus type)\n", inf.infotype );
+ return 0;
+ }
+ inf.info.linkstatus.linkstatus = hfa384x2host_16(inf.info.linkstatus.linkstatus);
+ if ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED ) {
+ /* Link not connected - retry */
+ printf ( "Link not connected (status %#hx)\n", inf.info.linkstatus.linkstatus );
+ }
+ } while ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED );
+
+ /* Retrieve BSSID and print Connected message */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, hw->bssid, WLAN_BSSID_LEN);
+
+ DBG ( "Link connected (BSSID %s - ", eth_ntoa ( hw->bssid ) );
+ DBG ( " MAC address %s)\n", eth_ntoa (nic->node_addr ) );
+
+ /* point to NIC specific routines */
+ nic->nic_op = &prism2_operations;
+ return 1;
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/prism2_pci.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/prism2_pci.c
new file mode 100644
index 00000000..145089a3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/prism2_pci.c
@@ -0,0 +1,67 @@
+/**************************************************************************
+Etherboot - BOOTP/TFTP Bootstrap Program
+Prism2 NIC driver for Etherboot
+Wrapper for prism2_pci
+
+Written by Michael Brown of Fen Systems Ltd
+$Id$
+***************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/pci.h>
+#include <nic.h>
+
+#define WLAN_HOSTIF WLAN_PCI
+#include "prism2.c"
+
+static int prism2_pci_probe ( struct nic *nic, struct pci_device *pci ) {
+ hfa384x_t *hw = &hw_global;
+
+ printf ( "Prism2.5 has registers at %#lx\n", pci->membase );
+ hw->membase = ioremap ( pci->membase, 0x100 );
+
+ nic->ioaddr = pci->membase;
+ nic->irqno = 0;
+
+ return prism2_probe ( nic, hw );
+}
+
+static void prism2_pci_disable ( struct nic *nic ) {
+ prism2_disable ( nic );
+}
+
+static struct pci_device_id prism2_pci_nics[] = {
+PCI_ROM(0x1260, 0x3873, "prism2_pci", "Harris Semiconductor Prism2.5 clone", 0),
+PCI_ROM(0x1260, 0x3873, "hwp01170", "ActionTec HWP01170", 0),
+PCI_ROM(0x1260, 0x3873, "dwl520", "DLink DWL-520", 0),
+};
+
+PCI_DRIVER ( prism2_pci_driver, prism2_pci_nics, PCI_NO_CLASS );
+
+DRIVER ( "Prism2/PCI", nic_driver, pci_driver, prism2_pci_driver,
+ prism2_pci_probe, prism2_pci_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/prism2_plx.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/prism2_plx.c
new file mode 100644
index 00000000..1317dddc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/prism2_plx.c
@@ -0,0 +1,131 @@
+/**************************************************************************
+Etherboot - BOOTP/TFTP Bootstrap Program
+Prism2 NIC driver for Etherboot
+Wrapper for prism2_plx
+
+Written by Michael Brown of Fen Systems Ltd
+$Id$
+***************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/pci.h>
+#include <nic.h>
+
+#define WLAN_HOSTIF WLAN_PLX
+#include "prism2.c"
+
+/*
+ * Find PLX card. Prints out information strings from PCMCIA CIS as visual
+ * confirmation of presence of card.
+ *
+ * Arguments:
+ * hw device structure to be filled in
+ * p PCI device structure
+ *
+ * Returns:
+ * 1 Success
+ */
+static int prism2_find_plx ( hfa384x_t *hw, struct pci_device *p )
+{
+ int found = 0;
+ uint32_t plx_lcr = 0; /* PLX9052 Local Configuration Register Base (I/O) */
+ uint32_t attr_mem = 0; /* Prism2 Attribute Memory Base */
+ uint32_t iobase = 0; /* Prism2 I/O Base */
+ unsigned char *cis_tpl = NULL;
+ unsigned char *cis_string;
+
+ /* Obtain all memory and IO base addresses */
+ pci_read_config_dword( p, PLX_LOCAL_CONFIG_REGISTER_BASE, &plx_lcr);
+ plx_lcr &= PCI_BASE_ADDRESS_IO_MASK;
+ pci_read_config_dword( p, PRISM2_PLX_ATTR_MEM_BASE, &attr_mem);
+ pci_read_config_dword( p, PRISM2_PLX_IO_BASE, &iobase);
+ iobase &= PCI_BASE_ADDRESS_IO_MASK;
+
+ /* Fill out hw structure */
+ hw->iobase = iobase;
+ printf ( "PLX9052 has local config registers at %#x\n", plx_lcr );
+ printf ( "Prism2 has attribute memory at %#x and I/O base at %#x\n", attr_mem, iobase );
+
+ /* Search for CIS strings */
+ printf ( "Searching for PCMCIA card...\n" );
+ cis_tpl = bus_to_virt(attr_mem);
+ while ( *cis_tpl != CISTPL_END ) {
+ if ( *cis_tpl == CISTPL_VERS_1 ) {
+ /* CISTPL_VERS_1 contains some nice text strings */
+ printf ( "...found " );
+ found = 1;
+ cis_string = cis_tpl + CISTPL_VERS_1_STR_OFF;
+ while ( ! ( ( *cis_string == 0 ) && ( *(cis_string+CIS_STEP) == 0 ) ) ) {
+ printf ( "%c", *cis_string == 0 ? ' ' : *cis_string );
+ cis_string += CIS_STEP;
+ }
+ printf ( "\n" );
+ }
+ /* printf ( "CIS tuple type %#hhx, length %#hhx\n", *cis_tpl, *(cis_tpl+CISTPL_LEN_OFF) ); */
+ cis_tpl += CISTPL_HEADER_LEN + CIS_STEP * ( *(cis_tpl+CISTPL_LEN_OFF) );
+ }
+ if ( found == 0 ) {
+ printf ( "...nothing found\n" );
+ }
+ ((unsigned char *)bus_to_virt(attr_mem))[COR_OFFSET] = COR_VALUE; /* Write COR to enable PC card */
+ return found;
+}
+
+static int prism2_plx_probe ( struct nic *nic, struct pci_device *pci ) {
+ hfa384x_t *hw = &hw_global;
+
+ /* Find and intialise PLX Prism2 card */
+ if ( ! prism2_find_plx ( hw, pci ) ) return 0;
+ nic->ioaddr = hw->iobase;
+ nic->irqno = 0;
+ return prism2_probe ( nic, hw );
+}
+
+static void prism2_plx_disable ( struct nic *nic ) {
+ prism2_disable ( nic );
+}
+
+static struct pci_device_id prism2_plx_nics[] = {
+PCI_ROM(0x1385, 0x4100, "ma301", "Netgear MA301", 0),
+PCI_ROM(0x10b7, 0x7770, "3c-airconnect", "3Com AirConnect", 0),
+PCI_ROM(0x111a, 0x1023, "ss1023", "Siemens SpeedStream SS1023", 0),
+PCI_ROM(0x15e8, 0x0130, "correga", "Correga", 0),
+PCI_ROM(0x1638, 0x1100, "smc2602w", "SMC EZConnect SMC2602W", 0), /* or Eumitcom PCI WL11000, Addtron AWA-100 */
+PCI_ROM(0x16ab, 0x1100, "gl24110p", "Global Sun Tech GL24110P", 0),
+PCI_ROM(0x16ab, 0x1101, "16ab-1101", "Unknown", 0),
+PCI_ROM(0x16ab, 0x1102, "wdt11", "Linksys WDT11", 0),
+PCI_ROM(0x16ec, 0x3685, "usr2415", "USR 2415", 0),
+PCI_ROM(0xec80, 0xec00, "f5d6000", "Belkin F5D6000", 0),
+PCI_ROM(0x126c, 0x8030, "emobility", "Nortel emobility", 0),
+};
+
+PCI_DRIVER ( prism2_plx_driver, prism2_plx_nics, PCI_NO_CLASS );
+
+
+DRIVER ( "Prism2/PLX", nic_driver, pci_driver, prism2_plx_driver,
+ prism2_plx_probe, prism2_plx_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/realtek.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/realtek.c
new file mode 100644
index 00000000..8a90ce8d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/realtek.c
@@ -0,0 +1,1070 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * (EEPROM code originally implemented for rtl8139.c)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/pci.h>
+#include <ipxe/nvs.h>
+#include <ipxe/threewire.h>
+#include <ipxe/bitbash.h>
+#include <ipxe/mii.h>
+#include "realtek.h"
+
+/** @file
+ *
+ * Realtek 10/100/1000 network card driver
+ *
+ * Based on the following datasheets:
+ *
+ * http://www.datasheetarchive.com/dl/Datasheets-8/DSA-153536.pdf
+ * http://www.datasheetarchive.com/indexdl/Datasheet-028/DSA00494723.pdf
+ */
+
+/******************************************************************************
+ *
+ * EEPROM interface
+ *
+ ******************************************************************************
+ */
+
+/** Pin mapping for SPI bit-bashing interface */
+static const uint8_t realtek_eeprom_bits[] = {
+ [SPI_BIT_SCLK] = RTL_9346CR_EESK,
+ [SPI_BIT_MOSI] = RTL_9346CR_EEDI,
+ [SPI_BIT_MISO] = RTL_9346CR_EEDO,
+ [SPI_BIT_SS(0)] = ( RTL_9346CR_EECS | RTL_9346CR_EEM1 ),
+};
+
+/**
+ * Read input bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @ret zero Input is a logic 0
+ * @ret non-zero Input is a logic 1
+ */
+static int realtek_spi_read_bit ( struct bit_basher *basher,
+ unsigned int bit_id ) {
+ struct realtek_nic *rtl = container_of ( basher, struct realtek_nic,
+ spibit.basher );
+ uint8_t mask = realtek_eeprom_bits[bit_id];
+ uint8_t reg;
+
+ DBG_DISABLE ( DBGLVL_IO );
+ reg = readb ( rtl->regs + RTL_9346CR );
+ DBG_ENABLE ( DBGLVL_IO );
+ return ( reg & mask );
+}
+
+/**
+ * Set/clear output bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @v data Value to write
+ */
+static void realtek_spi_write_bit ( struct bit_basher *basher,
+ unsigned int bit_id, unsigned long data ) {
+ struct realtek_nic *rtl = container_of ( basher, struct realtek_nic,
+ spibit.basher );
+ uint8_t mask = realtek_eeprom_bits[bit_id];
+ uint8_t reg;
+
+ DBG_DISABLE ( DBGLVL_IO );
+ reg = readb ( rtl->regs + RTL_9346CR );
+ reg &= ~mask;
+ reg |= ( data & mask );
+ writeb ( reg, rtl->regs + RTL_9346CR );
+ DBG_ENABLE ( DBGLVL_IO );
+}
+
+/** SPI bit-bashing interface */
+static struct bit_basher_operations realtek_basher_ops = {
+ .read = realtek_spi_read_bit,
+ .write = realtek_spi_write_bit,
+};
+
+/**
+ * Initialise EEPROM
+ *
+ * @v netdev Network device
+ */
+static void realtek_init_eeprom ( struct net_device *netdev ) {
+ struct realtek_nic *rtl = netdev->priv;
+
+ /* Initialise SPI bit-bashing interface */
+ rtl->spibit.basher.op = &realtek_basher_ops;
+ rtl->spibit.bus.mode = SPI_MODE_THREEWIRE;
+ init_spi_bit_basher ( &rtl->spibit );
+
+ /* Detect EEPROM type and initialise three-wire device */
+ if ( readl ( rtl->regs + RTL_RCR ) & RTL_RCR_9356SEL ) {
+ DBGC ( rtl, "REALTEK %p EEPROM is a 93C56\n", rtl );
+ init_at93c56 ( &rtl->eeprom, 16 );
+ } else {
+ DBGC ( rtl, "REALTEK %p EEPROM is a 93C46\n", rtl );
+ init_at93c46 ( &rtl->eeprom, 16 );
+ }
+ rtl->eeprom.bus = &rtl->spibit.bus;
+
+ /* Initialise space for non-volatile options, if available
+ *
+ * We use offset 0x40 (i.e. address 0x20), length 0x40. This
+ * block is marked as VPD in the Realtek datasheets, so we use
+ * it only if we detect that the card is not supporting VPD.
+ */
+ if ( readb ( rtl->regs + RTL_CONFIG1 ) & RTL_CONFIG1_VPD ) {
+ DBGC ( rtl, "REALTEK %p EEPROM in use for VPD; cannot use "
+ "for options\n", rtl );
+ } else {
+ nvo_init ( &rtl->nvo, &rtl->eeprom.nvs, RTL_EEPROM_VPD,
+ RTL_EEPROM_VPD_LEN, NULL, &netdev->refcnt );
+ }
+}
+
+/******************************************************************************
+ *
+ * MII interface
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Read from MII register
+ *
+ * @v mii MII interface
+ * @v reg Register address
+ * @ret value Data read, or negative error
+ */
+static int realtek_mii_read ( struct mii_interface *mii, unsigned int reg ) {
+ struct realtek_nic *rtl = container_of ( mii, struct realtek_nic, mii );
+ unsigned int i;
+ uint32_t value;
+
+ /* Fail if PHYAR register is not present */
+ if ( ! rtl->have_phy_regs )
+ return -ENOTSUP;
+
+ /* Initiate read */
+ writel ( RTL_PHYAR_VALUE ( 0, reg, 0 ), rtl->regs + RTL_PHYAR );
+
+ /* Wait for read to complete */
+ for ( i = 0 ; i < RTL_MII_MAX_WAIT_US ; i++ ) {
+
+ /* If read is not complete, delay 1us and retry */
+ value = readl ( rtl->regs + RTL_PHYAR );
+ if ( ! ( value & RTL_PHYAR_FLAG ) ) {
+ udelay ( 1 );
+ continue;
+ }
+
+ /* Return register value */
+ return ( RTL_PHYAR_DATA ( value ) );
+ }
+
+ DBGC ( rtl, "REALTEK %p timed out waiting for MII read\n", rtl );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Write to MII register
+ *
+ * @v mii MII interface
+ * @v reg Register address
+ * @v data Data to write
+ * @ret rc Return status code
+ */
+static int realtek_mii_write ( struct mii_interface *mii, unsigned int reg,
+ unsigned int data) {
+ struct realtek_nic *rtl = container_of ( mii, struct realtek_nic, mii );
+ unsigned int i;
+
+ /* Fail if PHYAR register is not present */
+ if ( ! rtl->have_phy_regs )
+ return -ENOTSUP;
+
+ /* Initiate write */
+ writel ( RTL_PHYAR_VALUE ( RTL_PHYAR_FLAG, reg, data ),
+ rtl->regs + RTL_PHYAR );
+
+ /* Wait for write to complete */
+ for ( i = 0 ; i < RTL_MII_MAX_WAIT_US ; i++ ) {
+
+ /* If write is not complete, delay 1us and retry */
+ if ( readl ( rtl->regs + RTL_PHYAR ) & RTL_PHYAR_FLAG ) {
+ udelay ( 1 );
+ continue;
+ }
+
+ return 0;
+ }
+
+ DBGC ( rtl, "REALTEK %p timed out waiting for MII write\n", rtl );
+ return -ETIMEDOUT;
+}
+
+/** Realtek MII operations */
+static struct mii_operations realtek_mii_operations = {
+ .read = realtek_mii_read,
+ .write = realtek_mii_write,
+};
+
+/******************************************************************************
+ *
+ * Device reset
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Reset hardware
+ *
+ * @v rtl Realtek device
+ * @ret rc Return status code
+ */
+static int realtek_reset ( struct realtek_nic *rtl ) {
+ unsigned int i;
+
+ /* Issue reset */
+ writeb ( RTL_CR_RST, rtl->regs + RTL_CR );
+
+ /* Wait for reset to complete */
+ for ( i = 0 ; i < RTL_RESET_MAX_WAIT_MS ; i++ ) {
+
+ /* If reset is not complete, delay 1ms and retry */
+ if ( readb ( rtl->regs + RTL_CR ) & RTL_CR_RST ) {
+ mdelay ( 1 );
+ continue;
+ }
+
+ return 0;
+ }
+
+ DBGC ( rtl, "REALTEK %p timed out waiting for reset\n", rtl );
+ return -ETIMEDOUT;
+}
+
+/******************************************************************************
+ *
+ * Link state
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Check link state
+ *
+ * @v netdev Network device
+ */
+static void realtek_check_link ( struct net_device *netdev ) {
+ struct realtek_nic *rtl = netdev->priv;
+ uint8_t phystatus;
+ uint8_t msr;
+ int link_up;
+
+ /* Determine link state */
+ if ( rtl->have_phy_regs ) {
+ phystatus = readb ( rtl->regs + RTL_PHYSTATUS );
+ link_up = ( phystatus & RTL_PHYSTATUS_LINKSTS );
+ DBGC ( rtl, "REALTEK %p PHY status is %02x\n", rtl, phystatus );
+ } else {
+ msr = readb ( rtl->regs + RTL_MSR );
+ link_up = ( ! ( msr & RTL_MSR_LINKB ) );
+ DBGC ( rtl, "REALTEK %p media status is %02x\n", rtl, msr );
+ }
+
+ /* Report link state */
+ if ( link_up ) {
+ netdev_link_up ( netdev );
+ } else {
+ netdev_link_down ( netdev );
+ }
+}
+
+/******************************************************************************
+ *
+ * Network device interface
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Create receive buffer (legacy mode)
+ *
+ * @v rtl Realtek device
+ * @ret rc Return status code
+ */
+static int realtek_create_buffer ( struct realtek_nic *rtl ) {
+ size_t len = ( RTL_RXBUF_LEN + RTL_RXBUF_PAD );
+ physaddr_t address;
+ int rc;
+
+ /* Do nothing unless in legacy mode */
+ if ( ! rtl->legacy )
+ return 0;
+
+ /* Allocate buffer */
+ rtl->rx_buffer = malloc_dma ( len, RTL_RXBUF_ALIGN );
+ if ( ! rtl->rx_buffer ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ address = virt_to_bus ( rtl->rx_buffer );
+
+ /* Check that card can support address */
+ if ( address & ~0xffffffffULL ) {
+ DBGC ( rtl, "REALTEK %p cannot support 64-bit RX buffer "
+ "address\n", rtl );
+ rc = -ENOTSUP;
+ goto err_64bit;
+ }
+
+ /* Program buffer address */
+ writel ( address, rtl->regs + RTL_RBSTART );
+ DBGC ( rtl, "REALTEK %p receive buffer is at [%08llx,%08llx,%08llx)\n",
+ rtl, ( ( unsigned long long ) address ),
+ ( ( unsigned long long ) address + RTL_RXBUF_LEN ),
+ ( ( unsigned long long ) address + len ) );
+
+ return 0;
+
+ err_64bit:
+ free_dma ( rtl->rx_buffer, len );
+ rtl->rx_buffer = NULL;
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Destroy receive buffer (legacy mode)
+ *
+ * @v rtl Realtek device
+ */
+static void realtek_destroy_buffer ( struct realtek_nic *rtl ) {
+ size_t len = ( RTL_RXBUF_LEN + RTL_RXBUF_PAD );
+
+ /* Do nothing unless in legacy mode */
+ if ( ! rtl->legacy )
+ return;
+
+ /* Clear buffer address */
+ writel ( 0, rtl->regs + RTL_RBSTART );
+
+ /* Free buffer */
+ free_dma ( rtl->rx_buffer, len );
+ rtl->rx_buffer = NULL;
+ rtl->rx_offset = 0;
+}
+
+/**
+ * Create descriptor ring
+ *
+ * @v rtl Realtek device
+ * @v ring Descriptor ring
+ * @ret rc Return status code
+ */
+static int realtek_create_ring ( struct realtek_nic *rtl,
+ struct realtek_ring *ring ) {
+ physaddr_t address;
+
+ /* Do nothing in legacy mode */
+ if ( rtl->legacy )
+ return 0;
+
+ /* Allocate descriptor ring */
+ ring->desc = malloc_dma ( ring->len, RTL_RING_ALIGN );
+ if ( ! ring->desc )
+ return -ENOMEM;
+
+ /* Initialise descriptor ring */
+ memset ( ring->desc, 0, ring->len );
+
+ /* Program ring address */
+ address = virt_to_bus ( ring->desc );
+ writel ( ( address & 0xffffffffUL ), rtl->regs + ring->reg );
+ if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) {
+ writel ( ( ( ( uint64_t ) address ) >> 32 ),
+ rtl->regs + ring->reg + 4 );
+ }
+ DBGC ( rtl, "REALTEK %p ring %02x is at [%08llx,%08llx)\n",
+ rtl, ring->reg, ( ( unsigned long long ) address ),
+ ( ( unsigned long long ) address + ring->len ) );
+
+ return 0;
+}
+
+/**
+ * Destroy descriptor ring
+ *
+ * @v rtl Realtek device
+ * @v ring Descriptor ring
+ */
+static void realtek_destroy_ring ( struct realtek_nic *rtl,
+ struct realtek_ring *ring ) {
+
+ /* Do nothing in legacy mode */
+ if ( rtl->legacy )
+ return;
+
+ /* Clear ring address */
+ writel ( 0, rtl->regs + ring->reg );
+ writel ( 0, rtl->regs + ring->reg + 4 );
+
+ /* Free descriptor ring */
+ free_dma ( ring->desc, ring->len );
+ ring->desc = NULL;
+ ring->prod = 0;
+ ring->cons = 0;
+}
+
+/**
+ * Refill receive descriptor ring
+ *
+ * @v rtl Realtek device
+ */
+static void realtek_refill_rx ( struct realtek_nic *rtl ) {
+ struct realtek_descriptor *rx;
+ struct io_buffer *iobuf;
+ unsigned int rx_idx;
+ physaddr_t address;
+ int is_last;
+
+ /* Do nothing in legacy mode */
+ if ( rtl->legacy )
+ return;
+
+ while ( ( rtl->rx.prod - rtl->rx.cons ) < RTL_NUM_RX_DESC ) {
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( RTL_RX_MAX_LEN );
+ if ( ! iobuf ) {
+ /* Wait for next refill */
+ return;
+ }
+
+ /* Get next receive descriptor */
+ rx_idx = ( rtl->rx.prod++ % RTL_NUM_RX_DESC );
+ is_last = ( rx_idx == ( RTL_NUM_RX_DESC - 1 ) );
+ rx = &rtl->rx.desc[rx_idx];
+
+ /* Populate receive descriptor */
+ address = virt_to_bus ( iobuf->data );
+ rx->address = cpu_to_le64 ( address );
+ rx->length = RTL_RX_MAX_LEN;
+ wmb();
+ rx->flags = ( cpu_to_le16 ( RTL_DESC_OWN ) |
+ ( is_last ? cpu_to_le16 ( RTL_DESC_EOR ) : 0 ) );
+ wmb();
+
+ /* Record I/O buffer */
+ assert ( rtl->rx_iobuf[rx_idx] == NULL );
+ rtl->rx_iobuf[rx_idx] = iobuf;
+
+ DBGC2 ( rtl, "REALTEK %p RX %d is [%llx,%llx)\n", rtl, rx_idx,
+ ( ( unsigned long long ) address ),
+ ( ( unsigned long long ) address + RTL_RX_MAX_LEN ) );
+ }
+}
+
+/**
+ * Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int realtek_open ( struct net_device *netdev ) {
+ struct realtek_nic *rtl = netdev->priv;
+ uint32_t rcr;
+ int rc;
+
+ /* Create transmit descriptor ring */
+ if ( ( rc = realtek_create_ring ( rtl, &rtl->tx ) ) != 0 )
+ goto err_create_tx;
+
+ /* Create receive descriptor ring */
+ if ( ( rc = realtek_create_ring ( rtl, &rtl->rx ) ) != 0 )
+ goto err_create_rx;
+
+ /* Create receive buffer */
+ if ( ( rc = realtek_create_buffer ( rtl ) ) != 0 )
+ goto err_create_buffer;
+
+ /* Accept all packets */
+ writel ( 0xffffffffUL, rtl->regs + RTL_MAR0 );
+ writel ( 0xffffffffUL, rtl->regs + RTL_MAR4 );
+
+ /* Enable transmitter and receiver. RTL8139 requires that
+ * this happens before writing to RCR.
+ */
+ writeb ( ( RTL_CR_TE | RTL_CR_RE ), rtl->regs + RTL_CR );
+
+ /* Configure receiver */
+ rcr = readl ( rtl->regs + RTL_RCR );
+ rcr &= ~( RTL_RCR_RBLEN_MASK );
+ rcr |= ( RTL_RCR_RBLEN_DEFAULT | RTL_RCR_WRAP | RTL_RCR_AB |
+ RTL_RCR_AM | RTL_RCR_APM | RTL_RCR_AAP );
+ writel ( rcr, rtl->regs + RTL_RCR );
+
+ /* Fill receive ring */
+ realtek_refill_rx ( rtl );
+
+ /* Update link state */
+ realtek_check_link ( netdev );
+
+ return 0;
+
+ realtek_destroy_buffer ( rtl );
+ err_create_buffer:
+ realtek_destroy_ring ( rtl, &rtl->rx );
+ err_create_rx:
+ realtek_destroy_ring ( rtl, &rtl->tx );
+ err_create_tx:
+ return rc;
+}
+
+/**
+ * Close network device
+ *
+ * @v netdev Network device
+ */
+static void realtek_close ( struct net_device *netdev ) {
+ struct realtek_nic *rtl = netdev->priv;
+ unsigned int i;
+
+ /* Disable receiver and transmitter */
+ writeb ( 0, rtl->regs + RTL_CR );
+
+ /* Destroy receive buffer */
+ realtek_destroy_buffer ( rtl );
+
+ /* Destroy receive descriptor ring */
+ realtek_destroy_ring ( rtl, &rtl->rx );
+
+ /* Discard any unused receive buffers */
+ for ( i = 0 ; i < RTL_NUM_RX_DESC ; i++ ) {
+ if ( rtl->rx_iobuf[i] )
+ free_iob ( rtl->rx_iobuf[i] );
+ rtl->rx_iobuf[i] = NULL;
+ }
+
+ /* Destroy transmit descriptor ring */
+ realtek_destroy_ring ( rtl, &rtl->tx );
+}
+
+/**
+ * Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int realtek_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct realtek_nic *rtl = netdev->priv;
+ struct realtek_descriptor *tx;
+ unsigned int tx_idx;
+ physaddr_t address;
+ int is_last;
+
+ /* Get next transmit descriptor */
+ if ( ( rtl->tx.prod - rtl->tx.cons ) >= RTL_NUM_TX_DESC ) {
+ DBGC ( rtl, "REALTEK %p out of transmit descriptors\n", rtl );
+ return -ENOBUFS;
+ }
+ tx_idx = ( rtl->tx.prod++ % RTL_NUM_TX_DESC );
+
+ /* Transmit packet */
+ if ( rtl->legacy ) {
+
+ /* Pad and align packet */
+ iob_pad ( iobuf, ETH_ZLEN );
+ address = virt_to_bus ( iobuf->data );
+
+ /* Check that card can support address */
+ if ( address & ~0xffffffffULL ) {
+ DBGC ( rtl, "REALTEK %p cannot support 64-bit TX "
+ "buffer address\n", rtl );
+ return -ENOTSUP;
+ }
+
+ /* Add to transmit ring */
+ writel ( address, rtl->regs + RTL_TSAD ( tx_idx ) );
+ writel ( ( RTL_TSD_ERTXTH_DEFAULT | iob_len ( iobuf ) ),
+ rtl->regs + RTL_TSD ( tx_idx ) );
+
+ } else {
+
+ /* Populate transmit descriptor */
+ address = virt_to_bus ( iobuf->data );
+ is_last = ( tx_idx == ( RTL_NUM_TX_DESC - 1 ) );
+ tx = &rtl->tx.desc[tx_idx];
+ tx->address = cpu_to_le64 ( address );
+ tx->length = cpu_to_le16 ( iob_len ( iobuf ) );
+ wmb();
+ tx->flags = ( cpu_to_le16 ( RTL_DESC_OWN | RTL_DESC_FS |
+ RTL_DESC_LS ) |
+ ( is_last ? cpu_to_le16 ( RTL_DESC_EOR ) : 0 ) );
+ wmb();
+
+ /* Notify card that there are packets ready to transmit */
+ writeb ( RTL_TPPOLL_NPQ, rtl->regs + rtl->tppoll );
+ }
+
+ DBGC2 ( rtl, "REALTEK %p TX %d is [%llx,%llx)\n", rtl, tx_idx,
+ ( ( unsigned long long ) virt_to_bus ( iobuf->data ) ),
+ ( ( ( unsigned long long ) virt_to_bus ( iobuf->data ) ) +
+ iob_len ( iobuf ) ) );
+
+ return 0;
+}
+
+/**
+ * Poll for completed packets
+ *
+ * @v netdev Network device
+ */
+static void realtek_poll_tx ( struct net_device *netdev ) {
+ struct realtek_nic *rtl = netdev->priv;
+ struct realtek_descriptor *tx;
+ unsigned int tx_idx;
+
+ /* Check for completed packets */
+ while ( rtl->tx.cons != rtl->tx.prod ) {
+
+ /* Get next transmit descriptor */
+ tx_idx = ( rtl->tx.cons % RTL_NUM_TX_DESC );
+
+ /* Stop if descriptor is still in use */
+ if ( rtl->legacy ) {
+
+ /* Check ownership bit in transmit status register */
+ if ( ! ( readl ( rtl->regs + RTL_TSD ( tx_idx ) ) &
+ RTL_TSD_OWN ) )
+ return;
+
+ } else {
+
+ /* Check ownership bit in descriptor */
+ tx = &rtl->tx.desc[tx_idx];
+ if ( tx->flags & cpu_to_le16 ( RTL_DESC_OWN ) )
+ return;
+ }
+
+ DBGC2 ( rtl, "REALTEK %p TX %d complete\n", rtl, tx_idx );
+
+ /* Complete TX descriptor */
+ netdev_tx_complete_next ( netdev );
+ rtl->tx.cons++;
+ }
+}
+
+/**
+ * Poll for received packets (legacy mode)
+ *
+ * @v netdev Network device
+ */
+static void realtek_legacy_poll_rx ( struct net_device *netdev ) {
+ struct realtek_nic *rtl = netdev->priv;
+ struct realtek_legacy_header *rx;
+ struct io_buffer *iobuf;
+ size_t len;
+
+ /* Check for received packets */
+ while ( ! ( readb ( rtl->regs + RTL_CR ) & RTL_CR_BUFE ) ) {
+
+ /* Extract packet from receive buffer */
+ rx = ( rtl->rx_buffer + rtl->rx_offset );
+ len = le16_to_cpu ( rx->length );
+ if ( rx->status & cpu_to_le16 ( RTL_STAT_ROK ) ) {
+
+ DBGC2 ( rtl, "REALTEK %p RX offset %x+%zx\n",
+ rtl, rtl->rx_offset, len );
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( len );
+ if ( ! iobuf ) {
+ netdev_rx_err ( netdev, NULL, -ENOMEM );
+ /* Leave packet for next poll */
+ break;
+ }
+
+ /* Copy data to I/O buffer */
+ memcpy ( iob_put ( iobuf, len ), rx->data, len );
+ iob_unput ( iobuf, 4 /* strip CRC */ );
+
+ /* Hand off to network stack */
+ netdev_rx ( netdev, iobuf );
+
+ } else {
+
+ DBGC ( rtl, "REALTEK %p RX offset %x+%zx error %04x\n",
+ rtl, rtl->rx_offset, len,
+ le16_to_cpu ( rx->status ) );
+ netdev_rx_err ( netdev, NULL, -EIO );
+ }
+
+ /* Update buffer offset */
+ rtl->rx_offset = ( rtl->rx_offset + sizeof ( *rx ) + len );
+ rtl->rx_offset = ( ( rtl->rx_offset + 3 ) & ~3 );
+ rtl->rx_offset = ( rtl->rx_offset % RTL_RXBUF_LEN );
+ writew ( ( rtl->rx_offset - 16 ), rtl->regs + RTL_CAPR );
+ }
+}
+
+/**
+ * Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void realtek_poll_rx ( struct net_device *netdev ) {
+ struct realtek_nic *rtl = netdev->priv;
+ struct realtek_descriptor *rx;
+ struct io_buffer *iobuf;
+ unsigned int rx_idx;
+ size_t len;
+
+ /* Poll receive buffer if in legacy mode */
+ if ( rtl->legacy ) {
+ realtek_legacy_poll_rx ( netdev );
+ return;
+ }
+
+ /* Check for received packets */
+ while ( rtl->rx.cons != rtl->rx.prod ) {
+
+ /* Get next receive descriptor */
+ rx_idx = ( rtl->rx.cons % RTL_NUM_RX_DESC );
+ rx = &rtl->rx.desc[rx_idx];
+
+ /* Stop if descriptor is still in use */
+ if ( rx->flags & cpu_to_le16 ( RTL_DESC_OWN ) )
+ return;
+
+ /* Populate I/O buffer */
+ iobuf = rtl->rx_iobuf[rx_idx];
+ rtl->rx_iobuf[rx_idx] = NULL;
+ len = ( le16_to_cpu ( rx->length ) & RTL_DESC_SIZE_MASK );
+ iob_put ( iobuf, ( len - 4 /* strip CRC */ ) );
+
+ DBGC2 ( rtl, "REALTEK %p RX %d complete (length %zd)\n",
+ rtl, rx_idx, len );
+
+ /* Hand off to network stack */
+ if ( rx->flags & cpu_to_le16 ( RTL_DESC_RES ) ) {
+ netdev_rx_err ( netdev, iobuf, -EIO );
+ } else {
+ netdev_rx ( netdev, iobuf );
+ }
+ rtl->rx.cons++;
+ }
+}
+
+/**
+ * Poll for completed and received packets
+ *
+ * @v netdev Network device
+ */
+static void realtek_poll ( struct net_device *netdev ) {
+ struct realtek_nic *rtl = netdev->priv;
+ uint16_t isr;
+
+ /* Check for and acknowledge interrupts */
+ isr = readw ( rtl->regs + RTL_ISR );
+ if ( ! isr )
+ return;
+ writew ( isr, rtl->regs + RTL_ISR );
+
+ /* Poll for TX completions, if applicable */
+ if ( isr & ( RTL_IRQ_TER | RTL_IRQ_TOK ) )
+ realtek_poll_tx ( netdev );
+
+ /* Poll for RX completionsm, if applicable */
+ if ( isr & ( RTL_IRQ_RER | RTL_IRQ_ROK ) )
+ realtek_poll_rx ( netdev );
+
+ /* Check link state, if applicable */
+ if ( isr & RTL_IRQ_PUN_LINKCHG )
+ realtek_check_link ( netdev );
+
+ /* Refill RX ring */
+ realtek_refill_rx ( rtl );
+}
+
+/**
+ * Enable or disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void realtek_irq ( struct net_device *netdev, int enable ) {
+ struct realtek_nic *rtl = netdev->priv;
+ uint16_t imr;
+
+ /* Set interrupt mask */
+ imr = ( enable ? ( RTL_IRQ_PUN_LINKCHG | RTL_IRQ_TER | RTL_IRQ_TOK |
+ RTL_IRQ_RER | RTL_IRQ_ROK ) : 0 );
+ writew ( imr, rtl->regs + RTL_IMR );
+}
+
+/** Realtek network device operations */
+static struct net_device_operations realtek_operations = {
+ .open = realtek_open,
+ .close = realtek_close,
+ .transmit = realtek_transmit,
+ .poll = realtek_poll,
+ .irq = realtek_irq,
+};
+
+/******************************************************************************
+ *
+ * PCI interface
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Detect device type
+ *
+ * @v rtl Realtek device
+ */
+static void realtek_detect ( struct realtek_nic *rtl ) {
+ uint16_t rms;
+ uint16_t check_rms;
+ uint16_t cpcr;
+ uint16_t check_cpcr;
+
+ /* The RX Packet Maximum Size register is present only on
+ * 8169. Try to set to our intended MTU.
+ */
+ rms = RTL_RX_MAX_LEN;
+ writew ( rms, rtl->regs + RTL_RMS );
+ check_rms = readw ( rtl->regs + RTL_RMS );
+
+ /* The C+ Command register is present only on 8169 and 8139C+.
+ * Try to enable C+ mode and PCI Dual Address Cycle (for
+ * 64-bit systems), if supported.
+ */
+ cpcr = ( RTL_CPCR_DAC | RTL_CPCR_MULRW | RTL_CPCR_CPRX |
+ RTL_CPCR_CPTX );
+ writew ( cpcr, rtl->regs + RTL_CPCR );
+ check_cpcr = readw ( rtl->regs + RTL_CPCR );
+
+ /* Detect device type */
+ if ( check_rms == rms ) {
+ DBGC ( rtl, "REALTEK %p appears to be an RTL8169\n", rtl );
+ rtl->have_phy_regs = 1;
+ rtl->tppoll = RTL_TPPOLL_8169;
+ } else {
+ if ( check_cpcr == cpcr ) {
+ DBGC ( rtl, "REALTEK %p appears to be an RTL8139C+\n",
+ rtl );
+ rtl->tppoll = RTL_TPPOLL_8139CP;
+ } else {
+ DBGC ( rtl, "REALTEK %p appears to be an RTL8139\n",
+ rtl );
+ rtl->legacy = 1;
+ }
+ }
+}
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @ret rc Return status code
+ */
+static int realtek_probe ( struct pci_device *pci ) {
+ struct net_device *netdev;
+ struct realtek_nic *rtl;
+ unsigned int i;
+ int rc;
+
+ /* Allocate and initialise net device */
+ netdev = alloc_etherdev ( sizeof ( *rtl ) );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ netdev_init ( netdev, &realtek_operations );
+ rtl = netdev->priv;
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+ memset ( rtl, 0, sizeof ( *rtl ) );
+ realtek_init_ring ( &rtl->tx, RTL_NUM_TX_DESC, RTL_TNPDS );
+ realtek_init_ring ( &rtl->rx, RTL_NUM_RX_DESC, RTL_RDSAR );
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* Map registers */
+ rtl->regs = ioremap ( pci->membase, RTL_BAR_SIZE );
+
+ /* Reset the NIC */
+ if ( ( rc = realtek_reset ( rtl ) ) != 0 )
+ goto err_reset;
+
+ /* Detect device type */
+ realtek_detect ( rtl );
+
+ /* Initialise EEPROM */
+ realtek_init_eeprom ( netdev );
+
+ /* Read MAC address from EEPROM */
+ if ( ( rc = nvs_read ( &rtl->eeprom.nvs, RTL_EEPROM_MAC,
+ netdev->hw_addr, ETH_ALEN ) ) != 0 ) {
+ DBGC ( rtl, "REALTEK %p could not read MAC address: %s\n",
+ rtl, strerror ( rc ) );
+ goto err_nvs_read;
+ }
+
+ /* The EEPROM may not be present for onboard NICs. Fall back
+ * to reading the current ID register value, which will
+ * hopefully have been programmed by the platform firmware.
+ */
+ if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) {
+ DBGC ( rtl, "REALTEK %p seems to have no EEPROM\n", rtl );
+ for ( i = 0 ; i < ETH_ALEN ; i++ )
+ netdev->hw_addr[i] = readb ( rtl->regs + RTL_IDR0 + i );
+ }
+
+ /* Initialise and reset MII interface */
+ mii_init ( &rtl->mii, &realtek_mii_operations );
+ if ( rtl->have_phy_regs &&
+ ( ( rc = mii_reset ( &rtl->mii ) ) != 0 ) ) {
+ DBGC ( rtl, "REALTEK %p could not reset MII: %s\n",
+ rtl, strerror ( rc ) );
+ goto err_mii_reset;
+ }
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register_netdev;
+
+ /* Set initial link state */
+ realtek_check_link ( netdev );
+
+ /* Register non-volatile options, if applicable */
+ if ( rtl->nvo.nvs ) {
+ if ( ( rc = register_nvo ( &rtl->nvo,
+ netdev_settings ( netdev ) ) ) != 0)
+ goto err_register_nvo;
+ }
+
+ return 0;
+
+ err_register_nvo:
+ unregister_netdev ( netdev );
+ err_register_netdev:
+ err_mii_reset:
+ err_nvs_read:
+ realtek_reset ( rtl );
+ err_reset:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void realtek_remove ( struct pci_device *pci ) {
+ struct net_device *netdev = pci_get_drvdata ( pci );
+ struct realtek_nic *rtl = netdev->priv;
+
+ /* Unregister non-volatile options, if applicable */
+ if ( rtl->nvo.nvs )
+ unregister_nvo ( &rtl->nvo );
+
+ /* Unregister network device */
+ unregister_netdev ( netdev );
+
+ /* Reset card */
+ realtek_reset ( rtl );
+
+ /* Free network device */
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/** Realtek PCI device IDs */
+static struct pci_device_id realtek_nics[] = {
+ PCI_ROM ( 0x0001, 0x8168, "clone8169", "Cloned 8169", 0 ),
+ PCI_ROM ( 0x018a, 0x0106, "fpc0106tx", "LevelOne FPC-0106TX", 0 ),
+ PCI_ROM ( 0x021b, 0x8139, "hne300", "Compaq HNE-300", 0 ),
+ PCI_ROM ( 0x02ac, 0x1012, "s1012", "SpeedStream 1012", 0 ),
+ PCI_ROM ( 0x0357, 0x000a, "ttpmon", "TTTech TTP-Monitoring", 0 ),
+ PCI_ROM ( 0x10ec, 0x8129, "rtl8129", "RTL-8129", 0 ),
+ PCI_ROM ( 0x10ec, 0x8136, "rtl8136", "RTL8101E/RTL8102E", 0 ),
+ PCI_ROM ( 0x10ec, 0x8138, "rtl8138", "RT8139 (B/C)", 0 ),
+ PCI_ROM ( 0x10ec, 0x8139, "rtl8139", "RTL-8139/8139C/8139C+", 0 ),
+ PCI_ROM ( 0x10ec, 0x8167, "rtl8167", "RTL-8110SC/8169SC", 0 ),
+ PCI_ROM ( 0x10ec, 0x8168, "rtl8168", "RTL8111/8168B", 0 ),
+ PCI_ROM ( 0x10ec, 0x8169, "rtl8169", "RTL-8169", 0 ),
+ PCI_ROM ( 0x1113, 0x1211, "smc1211", "SMC2-1211TX", 0 ),
+ PCI_ROM ( 0x1186, 0x1300, "dfe538", "DFE530TX+/DFE538TX", 0 ),
+ PCI_ROM ( 0x1186, 0x1340, "dfe690", "DFE-690TXD", 0 ),
+ PCI_ROM ( 0x1186, 0x4300, "dge528t", "DGE-528T", 0 ),
+ PCI_ROM ( 0x11db, 0x1234, "sega8139", "Sega Enterprises 8139", 0 ),
+ PCI_ROM ( 0x1259, 0xa117, "allied8139", "Allied Telesyn 8139", 0 ),
+ PCI_ROM ( 0x1259, 0xa11e, "allied81xx", "Allied Telesyn 81xx", 0 ),
+ PCI_ROM ( 0x1259, 0xc107, "allied8169", "Allied Telesyn 8169", 0 ),
+ PCI_ROM ( 0x126c, 0x1211, "northen8139","Northern Telecom 8139", 0 ),
+ PCI_ROM ( 0x13d1, 0xab06, "fe2000vx", "Abocom FE2000VX", 0 ),
+ PCI_ROM ( 0x1432, 0x9130, "edi8139", "Edimax 8139", 0 ),
+ PCI_ROM ( 0x14ea, 0xab06, "fnw3603tx", "Planex FNW-3603-TX", 0 ),
+ PCI_ROM ( 0x14ea, 0xab07, "fnw3800tx", "Planex FNW-3800-TX", 0 ),
+ PCI_ROM ( 0x1500, 0x1360, "delta8139", "Delta Electronics 8139", 0 ),
+ PCI_ROM ( 0x16ec, 0x0116, "usr997902", "USR997902", 0 ),
+ PCI_ROM ( 0x1737, 0x1032, "linksys8169","Linksys 8169", 0 ),
+ PCI_ROM ( 0x1743, 0x8139, "rolf100", "Peppercorn ROL/F-100", 0 ),
+ PCI_ROM ( 0x4033, 0x1360, "addron8139", "Addtron 8139", 0 ),
+ PCI_ROM ( 0xffff, 0x8139, "clonse8139", "Cloned 8139", 0 ),
+};
+
+/** Realtek PCI driver */
+struct pci_driver realtek_driver __pci_driver = {
+ .ids = realtek_nics,
+ .id_count = ( sizeof ( realtek_nics ) / sizeof ( realtek_nics[0] ) ),
+ .probe = realtek_probe,
+ .remove = realtek_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/realtek.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/realtek.h
new file mode 100644
index 00000000..1c6bc544
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/realtek.h
@@ -0,0 +1,273 @@
+#ifndef _REALTEK_H
+#define _REALTEK_H
+
+/** @file
+ *
+ * Realtek 10/100/1000 network card driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/spi.h>
+#include <ipxe/spi_bit.h>
+#include <ipxe/nvo.h>
+#include <ipxe/if_ether.h>
+
+/** PCI memory BAR size */
+#define RTL_BAR_SIZE 0x100
+
+/** A packet descriptor */
+struct realtek_descriptor {
+ /** Buffer size */
+ uint16_t length;
+ /** Flags */
+ uint16_t flags;
+ /** Reserved */
+ uint32_t reserved;
+ /** Buffer address */
+ uint64_t address;
+} __attribute__ (( packed ));
+
+/** Descriptor buffer size mask */
+#define RTL_DESC_SIZE_MASK 0x3fff
+
+/** Packet descriptor flags */
+enum realtek_descriptor_flags {
+ /** Descriptor is owned by NIC */
+ RTL_DESC_OWN = 0x8000,
+ /** End of descriptor ring */
+ RTL_DESC_EOR = 0x4000,
+ /** First segment descriptor */
+ RTL_DESC_FS = 0x2000,
+ /** Last segment descriptor */
+ RTL_DESC_LS = 0x1000,
+ /** Receive error summary */
+ RTL_DESC_RES = 0x0020,
+};
+
+/** Descriptor ring alignment */
+#define RTL_RING_ALIGN 256
+
+/** A legacy mode receive packet header */
+struct realtek_legacy_header {
+ /** Status */
+ uint16_t status;
+ /** Length */
+ uint16_t length;
+ /** Packet data */
+ uint8_t data[0];
+} __attribute__ (( packed ));
+
+/** Legacy mode status bits */
+enum realtek_legacy_status {
+ /** Received OK */
+ RTL_STAT_ROK = 0x0001,
+};
+
+/** ID Register 0 (6 bytes) */
+#define RTL_IDR0 0x00
+
+/** Multicast Register 0 (dword) */
+#define RTL_MAR0 0x08
+
+/** Multicast Register 4 (dword) */
+#define RTL_MAR4 0x0c
+
+/** Transmit Status of Descriptor N (dword, 8139 only) */
+#define RTL_TSD(n) ( 0x10 + 4 * (n) )
+#define RTL_TSD_ERTXTH(x) ( (x) << 16 ) /**< Early TX threshold */
+#define RTL_TSD_ERTXTH_DEFAULT RTL_TSD_ERTXTH ( 256 / 32 )
+#define RTL_TSD_OWN 0x00002000UL /**< Ownership */
+
+/** Transmit Start Address of Descriptor N (dword, 8139 only) */
+#define RTL_TSAD(n) ( 0x20 + 4 * (n) )
+
+/** Transmit Normal Priority Descriptors (qword) */
+#define RTL_TNPDS 0x20
+
+/** Number of transmit descriptors
+ *
+ * This is a hardware limit when using legacy mode.
+ */
+#define RTL_NUM_TX_DESC 4
+
+/** Receive Buffer Start Address (dword, 8139 only) */
+#define RTL_RBSTART 0x30
+
+/** Receive buffer length */
+#define RTL_RXBUF_LEN 8192
+
+/** Receive buffer padding */
+#define RTL_RXBUF_PAD 2038 /* Allow space for WRAP */
+
+/** Receive buffer alignment */
+#define RTL_RXBUF_ALIGN 16
+
+/** Command Register (byte) */
+#define RTL_CR 0x37
+#define RTL_CR_RST 0x10 /**< Reset */
+#define RTL_CR_RE 0x08 /**< Receiver Enable */
+#define RTL_CR_TE 0x04 /**< Transmit Enable */
+#define RTL_CR_BUFE 0x01 /**< Receive buffer empty */
+
+/** Maximum time to wait for a reset, in milliseconds */
+#define RTL_RESET_MAX_WAIT_MS 100
+
+/** Current Address of Packet Read (word, 8139 only) */
+#define RTL_CAPR 0x38
+
+/** Transmit Priority Polling Register (byte, 8169 only) */
+#define RTL_TPPOLL_8169 0x38
+#define RTL_TPPOLL_NPQ 0x40 /**< Normal Priority Queue Polling */
+
+/** Interrupt Mask Register (word) */
+#define RTL_IMR 0x3c
+#define RTL_IRQ_PUN_LINKCHG 0x0020 /**< Packet underrun / link change */
+#define RTL_IRQ_TER 0x0008 /**< Transmit error */
+#define RTL_IRQ_TOK 0x0004 /**< Transmit OK */
+#define RTL_IRQ_RER 0x0002 /**< Receive error */
+#define RTL_IRQ_ROK 0x0001 /**< Receive OK */
+
+/** Interrupt Status Register (word) */
+#define RTL_ISR 0x3e
+
+/** Receive (Rx) Configuration Register (dword) */
+#define RTL_RCR 0x44
+#define RTL_RCR_RBLEN(x) ( (x) << 11 ) /**< Receive buffer length */
+#define RTL_RCR_RBLEN_MASK RTL_RCR_RBLEN ( 0x3 )
+#define RTL_RCR_RBLEN_DEFAULT RTL_RCR_RBLEN ( 0 /* 8kB */ )
+#define RTL_RCR_WRAP 0x00000080UL /**< Overrun receive buffer */
+#define RTL_RCR_9356SEL 0x00000040UL /**< EEPROM is a 93C56 */
+#define RTL_RCR_AB 0x00000008UL /**< Accept broadcast packets */
+#define RTL_RCR_AM 0x00000004UL /**< Accept multicast packets */
+#define RTL_RCR_APM 0x00000002UL /**< Accept physical match */
+#define RTL_RCR_AAP 0x00000001UL /**< Accept all packets */
+
+/** 93C46 (93C56) Command Register (byte) */
+#define RTL_9346CR 0x50
+#define RTL_9346CR_EEM1 0x80 /**< Mode select bit 1 */
+#define RTL_9346CR_EEM0 0x40 /**< Mode select bit 0 */
+#define RTL_9346CR_EECS 0x08 /**< Chip select */
+#define RTL_9346CR_EESK 0x04 /**< Clock */
+#define RTL_9346CR_EEDI 0x02 /**< Data in */
+#define RTL_9346CR_EEDO 0x01 /**< Data out */
+
+/** Word offset of MAC address within EEPROM */
+#define RTL_EEPROM_MAC ( 0x0e / 2 )
+
+/** Word offset of VPD / non-volatile options within EEPROM */
+#define RTL_EEPROM_VPD ( 0x40 / 2 )
+
+/** Length of VPD / non-volatile options within EEPROM */
+#define RTL_EEPROM_VPD_LEN 0x40
+
+/** Configuration Register 1 (byte) */
+#define RTL_CONFIG1 0x52
+#define RTL_CONFIG1_VPD 0x02 /**< Vital Product Data enabled */
+
+/** Media Status Register (byte, 8139 only) */
+#define RTL_MSR 0x58
+#define RTL_MSR_LINKB 0x04 /**< Inverse of link status */
+
+/** PHY Access Register (dword, 8169 only) */
+#define RTL_PHYAR 0x60
+#define RTL_PHYAR_FLAG 0x80000000UL /**< Read/write flag */
+
+/** Construct PHY Access Register value */
+#define RTL_PHYAR_VALUE( flag, reg, data ) ( (flag) | ( (reg) << 16 ) | (data) )
+
+/** Extract PHY Access Register data */
+#define RTL_PHYAR_DATA( value ) ( (value) & 0xffff )
+
+/** Maximum time to wait for PHY access, in microseconds */
+#define RTL_MII_MAX_WAIT_US 500
+
+/** PHY (GMII, MII, or TBI) Status Register (byte, 8169 only) */
+#define RTL_PHYSTATUS 0x6c
+#define RTL_PHYSTATUS_LINKSTS 0x02 /**< Link ok */
+
+/** Transmit Priority Polling Register (byte, 8139C+ only) */
+#define RTL_TPPOLL_8139CP 0xd9
+
+/** RX Packet Maximum Size Register (word) */
+#define RTL_RMS 0xda
+
+/** C+ Command Register (word) */
+#define RTL_CPCR 0xe0
+#define RTL_CPCR_DAC 0x0010 /**< PCI Dual Address Cycle Enable */
+#define RTL_CPCR_MULRW 0x0008 /**< PCI Multiple Read/Write Enable */
+#define RTL_CPCR_CPRX 0x0002 /**< C+ receive enable */
+#define RTL_CPCR_CPTX 0x0001 /**< C+ transmit enable */
+
+/** Receive Descriptor Start Address Register (qword) */
+#define RTL_RDSAR 0xe4
+
+/** Number of receive descriptors */
+#define RTL_NUM_RX_DESC 4
+
+/** Receive buffer length */
+#define RTL_RX_MAX_LEN ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ )
+
+/** A Realtek descriptor ring */
+struct realtek_ring {
+ /** Descriptors */
+ struct realtek_descriptor *desc;
+ /** Producer index */
+ unsigned int prod;
+ /** Consumer index */
+ unsigned int cons;
+
+ /** Descriptor start address register */
+ unsigned int reg;
+ /** Length (in bytes) */
+ size_t len;
+};
+
+/**
+ * Initialise descriptor ring
+ *
+ * @v ring Descriptor ring
+ * @v count Number of descriptors
+ * @v reg Descriptor start address register
+ */
+static inline __attribute__ (( always_inline)) void
+realtek_init_ring ( struct realtek_ring *ring, unsigned int count,
+ unsigned int reg ) {
+ ring->len = ( count * sizeof ( ring->desc[0] ) );
+ ring->reg = reg;
+}
+
+/** A Realtek network card */
+struct realtek_nic {
+ /** Registers */
+ void *regs;
+ /** SPI bit-bashing interface */
+ struct spi_bit_basher spibit;
+ /** EEPROM */
+ struct spi_device eeprom;
+ /** Non-volatile options */
+ struct nvo_block nvo;
+ /** MII interface */
+ struct mii_interface mii;
+
+ /** Legacy datapath mode */
+ int legacy;
+ /** PHYAR and PHYSTATUS registers are present */
+ int have_phy_regs;
+ /** TPPoll register offset */
+ unsigned int tppoll;
+
+ /** Transmit descriptor ring */
+ struct realtek_ring tx;
+ /** Receive descriptor ring */
+ struct realtek_ring rx;
+ /** Receive I/O buffers */
+ struct io_buffer *rx_iobuf[RTL_NUM_RX_DESC];
+ /** Receive buffer (legacy mode) */
+ void *rx_buffer;
+ /** Offset within receive buffer (legacy mode) */
+ unsigned int rx_offset;
+};
+
+#endif /* _REALTEK_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180.c
new file mode 100644
index 00000000..8851d1bf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180.c
@@ -0,0 +1,17 @@
+/* Realtek 8180 card: rtl818x driver + rtl8180 RF modules */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <ipxe/pci.h>
+
+REQUIRE_OBJECT(rtl818x);
+REQUIRE_OBJECT(rtl8180_grf5101);
+REQUIRE_OBJECT(rtl8180_max2820);
+REQUIRE_OBJECT(rtl8180_sa2400);
+
+static struct pci_device_id rtl8180_nics[] __unused = {
+ PCI_ROM(0x10ec, 0x8180, "rtl8180", "Realtek 8180", 0),
+ PCI_ROM(0x1799, 0x6001, "f5d6001", "Belkin F5D6001", 0),
+ PCI_ROM(0x1799, 0x6020, "f5d6020", "Belkin F5D6020", 0),
+ PCI_ROM(0x1186, 0x3300, "dwl510", "D-Link DWL-510", 0),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180_grf5101.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180_grf5101.c
new file mode 100644
index 00000000..2b995030
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180_grf5101.c
@@ -0,0 +1,186 @@
+/*
+ * Radio tuning for GCT GRF5101 on RTL8180
+ *
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Modified slightly for iPXE, June 2009 by Joshua Oreman.
+ *
+ * Code from the BSD driver and the rtl8181 project have been
+ * very useful to understand certain things
+ *
+ * I want to thanks the Authors of such projects and the Ndiswrapper
+ * project Authors.
+ *
+ * A special Big Thanks also is for all people who donated me cards,
+ * making possible the creation of the original rtl8180 driver
+ * from which this code is derived!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <unistd.h>
+#include <ipxe/pci.h>
+#include <ipxe/net80211.h>
+
+#include "rtl818x.h"
+
+FILE_LICENCE(GPL2_ONLY);
+
+#define GRF5101_ANTENNA 0xA3
+
+static const int grf5101_encode[] = {
+ 0x0, 0x8, 0x4, 0xC,
+ 0x2, 0xA, 0x6, 0xE,
+ 0x1, 0x9, 0x5, 0xD,
+ 0x3, 0xB, 0x7, 0xF
+};
+
+static void write_grf5101(struct net80211_device *dev, u8 addr, u32 data)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u32 phy_config;
+
+ phy_config = grf5101_encode[(data >> 8) & 0xF];
+ phy_config |= grf5101_encode[(data >> 4) & 0xF] << 4;
+ phy_config |= grf5101_encode[data & 0xF] << 8;
+ phy_config |= grf5101_encode[(addr >> 1) & 0xF] << 12;
+ phy_config |= (addr & 1) << 16;
+ phy_config |= grf5101_encode[(data & 0xf000) >> 12] << 24;
+
+ /* MAC will bang bits to the chip */
+ phy_config |= 0x90000000;
+
+ /* This was originally a 32-bit write to a typecast
+ RFPinsOutput, but gcc complained about aliasing rules. -JBO */
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, phy_config & 0xffff);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, phy_config >> 16);
+
+ mdelay(3);
+}
+
+static void grf5101_write_phy_antenna(struct net80211_device *dev, short chan)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u8 ant = GRF5101_ANTENNA;
+
+ if (priv->rfparam & RF_PARAM_ANTBDEFAULT)
+ ant |= BB_ANTENNA_B;
+
+ if (chan == 14)
+ ant |= BB_ANTATTEN_CHAN14;
+
+ rtl818x_write_phy(dev, 0x10, ant);
+}
+
+static void grf5101_rf_set_channel(struct net80211_device *dev,
+ struct net80211_channel *channelp)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ int channel = channelp->channel_nr;
+ u32 txpw = priv->txpower[channel - 1] & 0xFF;
+ u32 chan = channel - 1;
+
+ /* set TX power */
+ write_grf5101(dev, 0x15, 0x0);
+ write_grf5101(dev, 0x06, txpw);
+ write_grf5101(dev, 0x15, 0x10);
+ write_grf5101(dev, 0x15, 0x0);
+
+ /* set frequency */
+ write_grf5101(dev, 0x07, 0x0);
+ write_grf5101(dev, 0x0B, chan);
+ write_grf5101(dev, 0x07, 0x1000);
+
+ grf5101_write_phy_antenna(dev, channel);
+}
+
+static void grf5101_rf_stop(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u32 anaparam;
+
+ anaparam = priv->anaparam;
+ anaparam &= 0x000fffff;
+ anaparam |= 0x3f900000;
+ rtl818x_set_anaparam(priv, anaparam);
+
+ write_grf5101(dev, 0x07, 0x0);
+ write_grf5101(dev, 0x1f, 0x45);
+ write_grf5101(dev, 0x1f, 0x5);
+ write_grf5101(dev, 0x00, 0x8e4);
+}
+
+static void grf5101_rf_init(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+
+ rtl818x_set_anaparam(priv, priv->anaparam);
+
+ write_grf5101(dev, 0x1f, 0x0);
+ write_grf5101(dev, 0x1f, 0x0);
+ write_grf5101(dev, 0x1f, 0x40);
+ write_grf5101(dev, 0x1f, 0x60);
+ write_grf5101(dev, 0x1f, 0x61);
+ write_grf5101(dev, 0x1f, 0x61);
+ write_grf5101(dev, 0x00, 0xae4);
+ write_grf5101(dev, 0x1f, 0x1);
+ write_grf5101(dev, 0x1f, 0x41);
+ write_grf5101(dev, 0x1f, 0x61);
+
+ write_grf5101(dev, 0x01, 0x1a23);
+ write_grf5101(dev, 0x02, 0x4971);
+ write_grf5101(dev, 0x03, 0x41de);
+ write_grf5101(dev, 0x04, 0x2d80);
+ write_grf5101(dev, 0x05, 0x68ff); /* 0x61ff original value */
+ write_grf5101(dev, 0x06, 0x0);
+ write_grf5101(dev, 0x07, 0x0);
+ write_grf5101(dev, 0x08, 0x7533);
+ write_grf5101(dev, 0x09, 0xc401);
+ write_grf5101(dev, 0x0a, 0x0);
+ write_grf5101(dev, 0x0c, 0x1c7);
+ write_grf5101(dev, 0x0d, 0x29d3);
+ write_grf5101(dev, 0x0e, 0x2e8);
+ write_grf5101(dev, 0x10, 0x192);
+ write_grf5101(dev, 0x11, 0x248);
+ write_grf5101(dev, 0x12, 0x0);
+ write_grf5101(dev, 0x13, 0x20c4);
+ write_grf5101(dev, 0x14, 0xf4fc);
+ write_grf5101(dev, 0x15, 0x0);
+ write_grf5101(dev, 0x16, 0x1500);
+
+ write_grf5101(dev, 0x07, 0x1000);
+
+ /* baseband configuration */
+ rtl818x_write_phy(dev, 0, 0xa8);
+ rtl818x_write_phy(dev, 3, 0x0);
+ rtl818x_write_phy(dev, 4, 0xc0);
+ rtl818x_write_phy(dev, 5, 0x90);
+ rtl818x_write_phy(dev, 6, 0x1e);
+ rtl818x_write_phy(dev, 7, 0x64);
+
+ grf5101_write_phy_antenna(dev, 1);
+
+ rtl818x_write_phy(dev, 0x11, 0x88);
+
+ if (rtl818x_ioread8(priv, &priv->map->CONFIG2) &
+ RTL818X_CONFIG2_ANTENNA_DIV)
+ rtl818x_write_phy(dev, 0x12, 0xc0); /* enable ant diversity */
+ else
+ rtl818x_write_phy(dev, 0x12, 0x40); /* disable ant diversity */
+
+ rtl818x_write_phy(dev, 0x13, 0x90 | priv->csthreshold);
+
+ rtl818x_write_phy(dev, 0x19, 0x0);
+ rtl818x_write_phy(dev, 0x1a, 0xa0);
+ rtl818x_write_phy(dev, 0x1b, 0x44);
+}
+
+struct rtl818x_rf_ops grf5101_rf_ops __rtl818x_rf_driver = {
+ .name = "GCT GRF5101",
+ .id = 5,
+ .init = grf5101_rf_init,
+ .stop = grf5101_rf_stop,
+ .set_chan = grf5101_rf_set_channel
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180_max2820.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180_max2820.c
new file mode 100644
index 00000000..ab380fcc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180_max2820.c
@@ -0,0 +1,158 @@
+/*
+ * Radio tuning for Maxim max2820 on RTL8180
+ *
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Modified slightly for iPXE, June 2009 by Joshua Oreman.
+ *
+ * Code from the BSD driver and the rtl8181 project have been
+ * very useful to understand certain things
+ *
+ * I want to thanks the Authors of such projects and the Ndiswrapper
+ * project Authors.
+ *
+ * A special Big Thanks also is for all people who donated me cards,
+ * making possible the creation of the original rtl8180 driver
+ * from which this code is derived!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <unistd.h>
+#include <ipxe/pci.h>
+#include <ipxe/net80211.h>
+
+#include "rtl818x.h"
+
+FILE_LICENCE(GPL2_ONLY);
+
+#define MAXIM_ANTENNA 0xb3
+
+static const u32 max2820_chan[] = {
+ 12, /* CH 1 */
+ 17,
+ 22,
+ 27,
+ 32,
+ 37,
+ 42,
+ 47,
+ 52,
+ 57,
+ 62,
+ 67,
+ 72,
+ 84, /* CH 14 */
+};
+
+static void write_max2820(struct net80211_device *dev, u8 addr, u32 data)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u32 phy_config;
+
+ phy_config = 0x90 + (data & 0xf);
+ phy_config <<= 16;
+ phy_config += addr;
+ phy_config <<= 8;
+ phy_config += (data >> 4) & 0xff;
+
+ /* This was originally a 32-bit write to a typecast
+ RFPinsOutput, but gcc complained about aliasing rules. -JBO */
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, phy_config & 0xffff);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, phy_config >> 16);
+
+ mdelay(1);
+}
+
+static void max2820_write_phy_antenna(struct net80211_device *dev, short chan)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u8 ant;
+
+ ant = MAXIM_ANTENNA;
+ if (priv->rfparam & RF_PARAM_ANTBDEFAULT)
+ ant |= BB_ANTENNA_B;
+ if (chan == 14)
+ ant |= BB_ANTATTEN_CHAN14;
+
+ rtl818x_write_phy(dev, 0x10, ant);
+}
+
+static void max2820_rf_set_channel(struct net80211_device *dev,
+ struct net80211_channel *channelp)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ int channel = channelp->channel_nr;
+ unsigned int chan_idx = channel - 1;
+ u32 txpw = priv->txpower[chan_idx] & 0xFF;
+ u32 chan = max2820_chan[chan_idx];
+
+ /* While philips SA2400 drive the PA bias from
+ * sa2400, for MAXIM we do this directly from BB */
+ rtl818x_write_phy(dev, 3, txpw);
+
+ max2820_write_phy_antenna(dev, channel);
+ write_max2820(dev, 3, chan);
+}
+
+static void max2820_rf_stop(struct net80211_device *dev)
+{
+ rtl818x_write_phy(dev, 3, 0x8);
+ write_max2820(dev, 1, 0);
+}
+
+
+static void max2820_rf_init(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+
+ /* MAXIM from netbsd driver */
+ write_max2820(dev, 0, 0x007); /* test mode as indicated in datasheet */
+ write_max2820(dev, 1, 0x01e); /* enable register */
+ write_max2820(dev, 2, 0x001); /* synt register */
+
+ max2820_rf_set_channel(dev, NULL);
+
+ write_max2820(dev, 4, 0x313); /* rx register */
+
+ /* PA is driven directly by the BB, we keep the MAXIM bias
+ * at the highest value in case that setting it to lower
+ * values may introduce some further attenuation somewhere..
+ */
+ write_max2820(dev, 5, 0x00f);
+
+ /* baseband configuration */
+ rtl818x_write_phy(dev, 0, 0x88); /* sys1 */
+ rtl818x_write_phy(dev, 3, 0x08); /* txagc */
+ rtl818x_write_phy(dev, 4, 0xf8); /* lnadet */
+ rtl818x_write_phy(dev, 5, 0x90); /* ifagcinit */
+ rtl818x_write_phy(dev, 6, 0x1a); /* ifagclimit */
+ rtl818x_write_phy(dev, 7, 0x64); /* ifagcdet */
+
+ max2820_write_phy_antenna(dev, 1);
+
+ rtl818x_write_phy(dev, 0x11, 0x88); /* trl */
+
+ if (rtl818x_ioread8(priv, &priv->map->CONFIG2) &
+ RTL818X_CONFIG2_ANTENNA_DIV)
+ rtl818x_write_phy(dev, 0x12, 0xc7);
+ else
+ rtl818x_write_phy(dev, 0x12, 0x47);
+
+ rtl818x_write_phy(dev, 0x13, 0x9b);
+
+ rtl818x_write_phy(dev, 0x19, 0x0); /* CHESTLIM */
+ rtl818x_write_phy(dev, 0x1a, 0x9f); /* CHSQLIM */
+
+ max2820_rf_set_channel(dev, NULL);
+}
+
+struct rtl818x_rf_ops max2820_rf_ops __rtl818x_rf_driver = {
+ .name = "Maxim max2820",
+ .id = 4,
+ .init = max2820_rf_init,
+ .stop = max2820_rf_stop,
+ .set_chan = max2820_rf_set_channel
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180_sa2400.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180_sa2400.c
new file mode 100644
index 00000000..9bd62bed
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8180_sa2400.c
@@ -0,0 +1,217 @@
+/*
+ * Radio tuning for Philips SA2400 on RTL8180
+ *
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Modified slightly for iPXE, June 2009 by Joshua Oreman.
+ *
+ * Code from the BSD driver and the rtl8181 project have been
+ * very useful to understand certain things
+ *
+ * I want to thanks the Authors of such projects and the Ndiswrapper
+ * project Authors.
+ *
+ * A special Big Thanks also is for all people who donated me cards,
+ * making possible the creation of the original rtl8180 driver
+ * from which this code is derived!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <unistd.h>
+#include <ipxe/pci.h>
+#include <ipxe/net80211.h>
+
+#include "rtl818x.h"
+
+FILE_LICENCE(GPL2_ONLY);
+
+#define SA2400_ANTENNA 0x91
+#define SA2400_DIG_ANAPARAM_PWR1_ON 0x8
+#define SA2400_ANA_ANAPARAM_PWR1_ON 0x28
+#define SA2400_ANAPARAM_PWR0_ON 0x3
+
+/* RX sensitivity in dbm */
+#define SA2400_MAX_SENS 85
+
+#define SA2400_REG4_FIRDAC_SHIFT 7
+
+static const u32 sa2400_chan[] = {
+ 0x00096c, /* ch1 */
+ 0x080970,
+ 0x100974,
+ 0x180978,
+ 0x000980,
+ 0x080984,
+ 0x100988,
+ 0x18098c,
+ 0x000994,
+ 0x080998,
+ 0x10099c,
+ 0x1809a0,
+ 0x0009a8,
+ 0x0009b4, /* ch 14 */
+};
+
+static void write_sa2400(struct net80211_device *dev, u8 addr, u32 data)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u32 phy_config;
+
+ /* MAC will bang bits to the sa2400. sw 3-wire is NOT used */
+ phy_config = 0xb0000000;
+
+ phy_config |= ((u32)(addr & 0xf)) << 24;
+ phy_config |= data & 0xffffff;
+
+ /* This was originally a 32-bit write to a typecast
+ RFPinsOutput, but gcc complained about aliasing rules. -JBO */
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, phy_config & 0xffff);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, phy_config >> 16);
+
+ mdelay(3);
+}
+
+static void sa2400_write_phy_antenna(struct net80211_device *dev, short chan)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u8 ant = SA2400_ANTENNA;
+
+ if (priv->rfparam & RF_PARAM_ANTBDEFAULT)
+ ant |= BB_ANTENNA_B;
+
+ if (chan == 14)
+ ant |= BB_ANTATTEN_CHAN14;
+
+ rtl818x_write_phy(dev, 0x10, ant);
+
+}
+
+static void sa2400_rf_set_channel(struct net80211_device *dev,
+ struct net80211_channel *channelp)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ int channel = channelp->channel_nr;
+ u32 txpw = priv->txpower[channel - 1] & 0xFF;
+ u32 chan = sa2400_chan[channel - 1];
+
+ write_sa2400(dev, 7, txpw);
+
+ sa2400_write_phy_antenna(dev, channel);
+
+ write_sa2400(dev, 0, chan);
+ write_sa2400(dev, 1, 0xbb50);
+ write_sa2400(dev, 2, 0x80);
+ write_sa2400(dev, 3, 0);
+}
+
+static void sa2400_rf_stop(struct net80211_device *dev)
+{
+ write_sa2400(dev, 4, 0);
+}
+
+static void sa2400_rf_init(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u32 anaparam, txconf;
+ u8 firdac;
+ int analogphy = priv->rfparam & RF_PARAM_ANALOGPHY;
+
+ anaparam = priv->anaparam;
+ anaparam &= ~(1 << ANAPARAM_TXDACOFF_SHIFT);
+ anaparam &= ~ANAPARAM_PWR1_MASK;
+ anaparam &= ~ANAPARAM_PWR0_MASK;
+
+ if (analogphy) {
+ anaparam |= SA2400_ANA_ANAPARAM_PWR1_ON << ANAPARAM_PWR1_SHIFT;
+ firdac = 0;
+ } else {
+ anaparam |= (SA2400_DIG_ANAPARAM_PWR1_ON << ANAPARAM_PWR1_SHIFT);
+ anaparam |= (SA2400_ANAPARAM_PWR0_ON << ANAPARAM_PWR0_SHIFT);
+ firdac = 1 << SA2400_REG4_FIRDAC_SHIFT;
+ }
+
+ rtl818x_set_anaparam(priv, anaparam);
+
+ write_sa2400(dev, 0, sa2400_chan[0]);
+ write_sa2400(dev, 1, 0xbb50);
+ write_sa2400(dev, 2, 0x80);
+ write_sa2400(dev, 3, 0);
+ write_sa2400(dev, 4, 0x19340 | firdac);
+ write_sa2400(dev, 5, 0x1dfb | (SA2400_MAX_SENS - 54) << 15);
+ write_sa2400(dev, 4, 0x19348 | firdac); /* calibrate VCO */
+
+ if (!analogphy)
+ write_sa2400(dev, 4, 0x1938c); /*???*/
+
+ write_sa2400(dev, 4, 0x19340 | firdac);
+
+ write_sa2400(dev, 0, sa2400_chan[0]);
+ write_sa2400(dev, 1, 0xbb50);
+ write_sa2400(dev, 2, 0x80);
+ write_sa2400(dev, 3, 0);
+ write_sa2400(dev, 4, 0x19344 | firdac); /* calibrate filter */
+
+ /* new from rtl8180 embedded driver (rtl8181 project) */
+ write_sa2400(dev, 6, 0x13ff | (1 << 23)); /* MANRX */
+ write_sa2400(dev, 8, 0); /* VCO */
+
+ if (analogphy) {
+ rtl818x_set_anaparam(priv, anaparam |
+ (1 << ANAPARAM_TXDACOFF_SHIFT));
+
+ txconf = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF,
+ txconf | RTL818X_TX_CONF_LOOPBACK_CONT);
+
+ write_sa2400(dev, 4, 0x19341); /* calibrates DC */
+
+ /* a 5us delay is required here,
+ * we rely on the 3ms delay introduced in write_sa2400 */
+
+ write_sa2400(dev, 4, 0x19345);
+
+ /* a 20us delay is required here,
+ * we rely on the 3ms delay introduced in write_sa2400 */
+
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF, txconf);
+
+ rtl818x_set_anaparam(priv, anaparam);
+ }
+ /* end new code */
+
+ write_sa2400(dev, 4, 0x19341 | firdac); /* RTX MODE */
+
+ /* baseband configuration */
+ rtl818x_write_phy(dev, 0, 0x98);
+ rtl818x_write_phy(dev, 3, 0x38);
+ rtl818x_write_phy(dev, 4, 0xe0);
+ rtl818x_write_phy(dev, 5, 0x90);
+ rtl818x_write_phy(dev, 6, 0x1a);
+ rtl818x_write_phy(dev, 7, 0x64);
+
+ sa2400_write_phy_antenna(dev, 1);
+
+ rtl818x_write_phy(dev, 0x11, 0x80);
+
+ if (rtl818x_ioread8(priv, &priv->map->CONFIG2) &
+ RTL818X_CONFIG2_ANTENNA_DIV)
+ rtl818x_write_phy(dev, 0x12, 0xc7); /* enable ant diversity */
+ else
+ rtl818x_write_phy(dev, 0x12, 0x47); /* disable ant diversity */
+
+ rtl818x_write_phy(dev, 0x13, 0x90 | priv->csthreshold);
+
+ rtl818x_write_phy(dev, 0x19, 0x0);
+ rtl818x_write_phy(dev, 0x1a, 0xa0);
+}
+
+struct rtl818x_rf_ops sa2400_rf_ops __rtl818x_rf_driver = {
+ .name = "Philips SA2400",
+ .id = 3,
+ .init = sa2400_rf_init,
+ .stop = sa2400_rf_stop,
+ .set_chan = sa2400_rf_set_channel
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8185.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8185.c
new file mode 100644
index 00000000..fd27e5c8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8185.c
@@ -0,0 +1,14 @@
+/* Realtek 8185 card: rtl818x driver + rtl8185_rtl8225 RF module */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <ipxe/pci.h>
+
+REQUIRE_OBJECT(rtl818x);
+REQUIRE_OBJECT(rtl8185_rtl8225);
+
+static struct pci_device_id rtl8185_nics[] __unused = {
+ PCI_ROM(0x10ec, 0x8185, "rtl8185", "Realtek 8185", 0),
+ PCI_ROM(0x1799, 0x700f, "f5d7000", "Belkin F5D7000", 0),
+ PCI_ROM(0x1799, 0x701f, "f5d7010", "Belkin F5D7010", 0),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8185_rtl8225.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8185_rtl8225.c
new file mode 100644
index 00000000..50cc84ad
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl8185_rtl8225.c
@@ -0,0 +1,804 @@
+/*
+ * Radio tuning for RTL8225 on RTL8185
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Modified slightly for iPXE, June 2009 by Joshua Oreman
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Thanks to Realtek for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <unistd.h>
+#include <ipxe/pci.h>
+#include <ipxe/net80211.h>
+
+#include "rtl818x.h"
+
+FILE_LICENCE(GPL2_ONLY);
+
+#define RTL8225_ANAPARAM_ON 0xa0000b59
+#define RTL8225_ANAPARAM2_ON 0x860dec11
+#define RTL8225_ANAPARAM_OFF 0xa00beb59
+#define RTL8225_ANAPARAM2_OFF 0x840dec11
+
+#define min(a,b) (((a)<(b))?(a):(b))
+#define ARRAY_SIZE(a) (int)(sizeof(a)/sizeof((a)[0]))
+
+static inline void rtl8225_write_phy_ofdm(struct net80211_device *dev,
+ u8 addr, u8 data)
+{
+ rtl818x_write_phy(dev, addr, data);
+}
+
+static inline void rtl8225_write_phy_cck(struct net80211_device *dev,
+ u8 addr, u8 data)
+{
+ rtl818x_write_phy(dev, addr, data | 0x10000);
+}
+
+static void rtl8225_write(struct net80211_device *dev, u8 addr, u16 data)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u16 reg80, reg84, reg82;
+ u32 bangdata;
+ int i;
+
+ bangdata = (data << 4) | (addr & 0xf);
+
+ reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
+ reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
+
+ reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7 | 0x400);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(10);
+
+ for (i = 15; i >= 0; i--) {
+ u16 reg = reg80 | !!(bangdata & (1 << i));
+
+ if (i & 1)
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+
+ if (!(i & 1))
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x400);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+}
+
+static u16 rtl8225_read(struct net80211_device *dev, u8 addr)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u16 reg80, reg82, reg84, out;
+ int i;
+
+ reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+ reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+ reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect) | 0x400;
+
+ reg80 &= ~0xF;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(4);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(5);
+
+ for (i = 4; i >= 0; i--) {
+ u16 reg = reg80 | ((addr >> i) & 1);
+
+ if (!(i & 1)) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(1);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg | (1 << 1));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg | (1 << 1));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+
+ if (i & 1) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(1);
+ }
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x000E);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x040E);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+
+ out = 0;
+ for (i = 11; i >= 0; i--) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(1);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+
+ if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
+ out |= 1 << i;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 2));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
+
+ return out;
+}
+
+static const u16 rtl8225bcd_rxgain[] = {
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+ 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+ 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+ 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+ 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+ 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+ 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+ 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+ 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+ 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+ 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
+ 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
+};
+
+static const u8 rtl8225_agc[] = {
+ 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
+ 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
+ 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
+ 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
+ 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
+ 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
+ 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
+ 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
+ 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
+ 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
+ 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
+ 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
+ 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+};
+
+static const u8 rtl8225_gain[] = {
+ 0x23, 0x88, 0x7c, 0xa5, /* -82dbm */
+ 0x23, 0x88, 0x7c, 0xb5, /* -82dbm */
+ 0x23, 0x88, 0x7c, 0xc5, /* -82dbm */
+ 0x33, 0x80, 0x79, 0xc5, /* -78dbm */
+ 0x43, 0x78, 0x76, 0xc5, /* -74dbm */
+ 0x53, 0x60, 0x73, 0xc5, /* -70dbm */
+ 0x63, 0x58, 0x70, 0xc5, /* -66dbm */
+};
+
+static const u8 rtl8225_threshold[] = {
+ 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
+};
+
+static const u8 rtl8225_tx_gain_cck_ofdm[] = {
+ 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
+};
+
+static const u8 rtl8225_tx_power_cck[] = {
+ 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
+ 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
+ 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
+ 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
+ 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
+ 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
+};
+
+static const u8 rtl8225_tx_power_cck_ch14[] = {
+ 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
+ 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
+ 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
+ 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225_tx_power_ofdm[] = {
+ 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
+};
+
+static const u32 rtl8225_chan[] = {
+ 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
+ 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
+};
+
+static void rtl8225_rf_set_tx_power(struct net80211_device *dev, int channel)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u8 cck_power, ofdm_power;
+ const u8 *tmp;
+ u32 reg;
+ int i;
+
+ cck_power = priv->txpower[channel - 1] & 0xFF;
+ ofdm_power = priv->txpower[channel - 1] >> 8;
+
+ cck_power = min(cck_power, (u8)35);
+ ofdm_power = min(ofdm_power, (u8)35);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+ rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
+
+ if (channel == 14)
+ tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
+ else
+ tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
+
+ for (i = 0; i < 8; i++)
+ rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+ mdelay(1); /* FIXME: optional? */
+
+ /* anaparam2 on */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+ rtl8225_tx_gain_cck_ofdm[ofdm_power/6] >> 1);
+
+ tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
+
+ rtl8225_write_phy_ofdm(dev, 5, *tmp);
+ rtl8225_write_phy_ofdm(dev, 7, *tmp);
+
+ mdelay(1);
+}
+
+static void rtl8225_rf_init(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ int i;
+
+ rtl818x_set_anaparam(priv, RTL8225_ANAPARAM_ON);
+
+ /* host_pci_init */
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ mdelay(200); /* FIXME: ehh?? */
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
+
+ rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
+
+ /* TODO: check if we need really to change BRSR to do RF config */
+ rtl818x_ioread16(priv, &priv->map->BRSR);
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
+ rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl8225_write(dev, 0x0, 0x067);
+ rtl8225_write(dev, 0x1, 0xFE0);
+ rtl8225_write(dev, 0x2, 0x44D);
+ rtl8225_write(dev, 0x3, 0x441);
+ rtl8225_write(dev, 0x4, 0x8BE);
+ rtl8225_write(dev, 0x5, 0xBF0); /* TODO: minipci */
+ rtl8225_write(dev, 0x6, 0xAE6);
+ rtl8225_write(dev, 0x7, rtl8225_chan[0]);
+ rtl8225_write(dev, 0x8, 0x01F);
+ rtl8225_write(dev, 0x9, 0x334);
+ rtl8225_write(dev, 0xA, 0xFD4);
+ rtl8225_write(dev, 0xB, 0x391);
+ rtl8225_write(dev, 0xC, 0x050);
+ rtl8225_write(dev, 0xD, 0x6DB);
+ rtl8225_write(dev, 0xE, 0x029);
+ rtl8225_write(dev, 0xF, 0x914); mdelay(1);
+
+ rtl8225_write(dev, 0x2, 0xC4D); mdelay(100);
+
+ rtl8225_write(dev, 0x0, 0x127);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
+ rtl8225_write(dev, 0x1, i + 1);
+ rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
+ }
+
+ rtl8225_write(dev, 0x0, 0x027);
+ rtl8225_write(dev, 0x0, 0x22F);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+ rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+ mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+ mdelay(1);
+ }
+
+ mdelay(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x00, 0x01); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x01, 0x02); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x02, 0x62); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x03, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x04, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x05, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x06, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x07, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x08, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x10, 0x84); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x11, 0x03); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x12, 0x20); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x13, 0x20); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x14, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x15, 0x40); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x16, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x17, 0x40); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x19, 0x19); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x27); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x22, 0x16); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x24, 0x46); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x25, 0x20); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x27, 0x88); mdelay(1);
+
+ rtl8225_write_phy_cck(dev, 0x00, 0x98); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x03, 0x20); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x04, 0x7e); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x05, 0x12); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x06, 0xfc); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x07, 0x78); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x08, 0x2e); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x10, 0x93); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x11, 0x88); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x12, 0x47); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+ rtl8225_write_phy_cck(dev, 0x19, 0x00);
+ rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+ rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+ rtl8225_write_phy_cck(dev, 0x40, 0x86);
+ rtl8225_write_phy_cck(dev, 0x41, 0x8d); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x42, 0x15); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x43, 0x18); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x44, 0x1f); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x45, 0x1e); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x46, 0x1a); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x47, 0x15); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x48, 0x10); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x49, 0x0a); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x4a, 0x05); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x4b, 0x02); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x4c, 0x05); mdelay(1);
+
+ rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); mdelay(1);
+
+ rtl8225_rf_set_tx_power(dev, 1);
+
+ /* RX antenna default to A */
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); mdelay(1); /* B: 0xDB */
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); /* B: 0x10 */
+
+ rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
+ mdelay(1);
+ rtl818x_iowrite32(priv, (u32 *)((u8 *)priv->map + 0x94), 0x15c00002);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+
+ rtl8225_write(dev, 0x0c, 0x50);
+ /* set OFDM initial gain */
+ rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[4 * 4]);
+ rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[4 * 4 + 1]);
+ rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[4 * 4 + 2]);
+ rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[4 * 4 + 3]);
+ /* set CCK threshold */
+ rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[0]);
+}
+
+static const u8 rtl8225z2_tx_power_cck_ch14[] = {
+ 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225z2_tx_power_cck_B[] = {
+ 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04
+};
+
+static const u8 rtl8225z2_tx_power_cck_A[] = {
+ 0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04
+};
+
+static const u8 rtl8225z2_tx_power_cck[] = {
+ 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
+};
+
+static void rtl8225z2_rf_set_tx_power(struct net80211_device *dev, int channel)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u8 cck_power, ofdm_power;
+ const u8 *tmp;
+ int i;
+
+ cck_power = priv->txpower[channel - 1] & 0xFF;
+ ofdm_power = priv->txpower[channel - 1] >> 8;
+
+ if (channel == 14)
+ tmp = rtl8225z2_tx_power_cck_ch14;
+ else if (cck_power == 12)
+ tmp = rtl8225z2_tx_power_cck_B;
+ else if (cck_power == 13)
+ tmp = rtl8225z2_tx_power_cck_A;
+ else
+ tmp = rtl8225z2_tx_power_cck;
+
+ for (i = 0; i < 8; i++)
+ rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+ cck_power = min(cck_power, (u8)35);
+ if (cck_power == 13 || cck_power == 14)
+ cck_power = 12;
+ if (cck_power >= 15)
+ cck_power -= 2;
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, cck_power);
+ rtl818x_ioread8(priv, &priv->map->TX_GAIN_CCK);
+ mdelay(1);
+
+ ofdm_power = min(ofdm_power, (u8)35);
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, ofdm_power);
+
+ rtl8225_write_phy_ofdm(dev, 2, 0x62);
+ rtl8225_write_phy_ofdm(dev, 5, 0x00);
+ rtl8225_write_phy_ofdm(dev, 6, 0x40);
+ rtl8225_write_phy_ofdm(dev, 7, 0x00);
+ rtl8225_write_phy_ofdm(dev, 8, 0x40);
+
+ mdelay(1);
+}
+
+static const u16 rtl8225z2_rxgain[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141,
+ 0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183,
+ 0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244,
+ 0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288,
+ 0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345,
+ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389,
+ 0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393,
+ 0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d,
+ 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9,
+ 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
+ 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
+};
+
+static void rtl8225z2_rf_init(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ int i;
+
+ rtl818x_set_anaparam(priv, RTL8225_ANAPARAM_ON);
+
+ /* host_pci_init */
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ mdelay(200); /* FIXME: ehh?? */
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
+
+ rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00088008);
+
+ /* TODO: check if we need really to change BRSR to do RF config */
+ rtl818x_ioread16(priv, &priv->map->BRSR);
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
+ rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+
+ rtl8225_write(dev, 0x0, 0x0B7); mdelay(1);
+ rtl8225_write(dev, 0x1, 0xEE0); mdelay(1);
+ rtl8225_write(dev, 0x2, 0x44D); mdelay(1);
+ rtl8225_write(dev, 0x3, 0x441); mdelay(1);
+ rtl8225_write(dev, 0x4, 0x8C3); mdelay(1);
+ rtl8225_write(dev, 0x5, 0xC72); mdelay(1);
+ rtl8225_write(dev, 0x6, 0x0E6); mdelay(1);
+ rtl8225_write(dev, 0x7, 0x82A); mdelay(1);
+ rtl8225_write(dev, 0x8, 0x03F); mdelay(1);
+ rtl8225_write(dev, 0x9, 0x335); mdelay(1);
+ rtl8225_write(dev, 0xa, 0x9D4); mdelay(1);
+ rtl8225_write(dev, 0xb, 0x7BB); mdelay(1);
+ rtl8225_write(dev, 0xc, 0x850); mdelay(1);
+ rtl8225_write(dev, 0xd, 0xCDF); mdelay(1);
+ rtl8225_write(dev, 0xe, 0x02B); mdelay(1);
+ rtl8225_write(dev, 0xf, 0x114); mdelay(100);
+
+ if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+ rtl8225_write(dev, 0x02, 0x0C4D);
+ mdelay(200);
+ rtl8225_write(dev, 0x02, 0x044D);
+ mdelay(100);
+ /* TODO: readd calibration failure message when the calibration
+ check works */
+ }
+
+ rtl8225_write(dev, 0x0, 0x1B7);
+ rtl8225_write(dev, 0x3, 0x002);
+ rtl8225_write(dev, 0x5, 0x004);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
+ rtl8225_write(dev, 0x1, i + 1);
+ rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
+ }
+
+ rtl8225_write(dev, 0x0, 0x0B7); mdelay(100);
+ rtl8225_write(dev, 0x2, 0xC4D);
+
+ mdelay(200);
+ rtl8225_write(dev, 0x2, 0x44D);
+ mdelay(100);
+
+ rtl8225_write(dev, 0x00, 0x2BF);
+ rtl8225_write(dev, 0xFF, 0xFFFF);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+ rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+ mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+ mdelay(1);
+ }
+
+ mdelay(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x00, 0x01); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x01, 0x02); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x02, 0x62); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x03, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x04, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x05, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x06, 0x40); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x07, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x08, 0x40); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
+ rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x10, 0x84); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x11, 0x06); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x12, 0x20); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x13, 0x20); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x14, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x15, 0x40); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x16, 0x00); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x17, 0x40); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x19, 0x19); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x1b, 0x11); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x1e, 0xb3); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x27); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x22, 0x16); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x23, 0x80); mdelay(1); /* FIXME: not needed? */
+ rtl8225_write_phy_ofdm(dev, 0x24, 0x46); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x25, 0x20); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);
+ rtl8225_write_phy_ofdm(dev, 0x27, 0x88); mdelay(1);
+
+ rtl8225_write_phy_cck(dev, 0x00, 0x98); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x03, 0x20); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x04, 0x7e); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x05, 0x12); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x06, 0xfc); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x07, 0x78); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x08, 0x2e); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x10, 0x93); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x11, 0x88); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x12, 0x47); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+ rtl8225_write_phy_cck(dev, 0x19, 0x00);
+ rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+ rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+ rtl8225_write_phy_cck(dev, 0x40, 0x86);
+ rtl8225_write_phy_cck(dev, 0x41, 0x8a); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x42, 0x15); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x43, 0x18); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x44, 0x36); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x45, 0x35); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x46, 0x2e); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x47, 0x25); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x48, 0x1c); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x49, 0x12); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x4a, 0x09); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x4b, 0x04); mdelay(1);
+ rtl8225_write_phy_cck(dev, 0x4c, 0x05); mdelay(1);
+
+ rtl818x_iowrite8(priv, (u8 *)priv->map + 0x5B, 0x0D); mdelay(1);
+
+ rtl8225z2_rf_set_tx_power(dev, 1);
+
+ /* RX antenna default to A */
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); mdelay(1); /* B: 0xDB */
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); /* B: 0x10 */
+
+ rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
+ mdelay(1);
+ rtl818x_iowrite32(priv, (u32 *)((u8 *)priv->map + 0x94), 0x15c00002);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+}
+
+static void rtl8225x_rf_init(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u16 reg8, reg9;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ mdelay(100);
+
+ rtl8225_write(dev, 0, 0x1B7);
+
+ reg8 = rtl8225_read(dev, 8);
+ reg9 = rtl8225_read(dev, 9);
+
+ rtl8225_write(dev, 0, 0x0B7);
+
+ if (reg8 != 0x588 || reg9 != 0x700) {
+ priv->rf_flag = 0;
+ rtl8225_rf_init(dev);
+ } else {
+ priv->rf_flag = 1;
+ rtl8225z2_rf_init(dev);
+ }
+}
+
+static void rtl8225_rf_stop(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u8 reg;
+
+ rtl8225_write(dev, 0x4, 0x1f); mdelay(1);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+}
+
+static void rtl8225_rf_set_channel(struct net80211_device *dev,
+ struct net80211_channel *channelp)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ int chan = channelp->channel_nr;
+
+ if (priv->rf_flag)
+ rtl8225z2_rf_set_tx_power(dev, chan);
+ else
+ rtl8225_rf_set_tx_power(dev, chan);
+
+ rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
+ mdelay(10);
+}
+
+static void rtl8225_rf_conf_erp(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+
+ if (dev->phy_flags & NET80211_PHY_USE_SHORT_SLOT) {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
+ rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 81);
+ rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
+ } else {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->SIFS, 0x44);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 81);
+ rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
+ }
+}
+
+struct rtl818x_rf_ops rtl8225_ops __rtl818x_rf_driver = {
+ .name = "rtl8225",
+ .id = 9,
+ .init = rtl8225x_rf_init,
+ .stop = rtl8225_rf_stop,
+ .set_chan = rtl8225_rf_set_channel,
+ .conf_erp = rtl8225_rf_conf_erp,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl818x.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl818x.c
new file mode 100644
index 00000000..cf4c7556
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl818x.c
@@ -0,0 +1,854 @@
+
+/*
+ * Linux device driver for RTL8180 / RTL8185
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Modified for iPXE, June 2009, by Joshua Oreman <oremanj@rwcr.net>
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Thanks to Realtek for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+FILE_LICENCE(GPL2_ONLY);
+
+#include <stdint.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/pci.h>
+#include <ipxe/net80211.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/threewire.h>
+
+#include "rtl818x.h"
+
+/* rtl818x_rates[hw rate number] = rate in 100kbps units */
+static const u16 rtl818x_rates[] = {
+ 10, 20, 55, 110, /* 802.11b */
+ 60, 90, 120, 180, 240, 360, 480, 540, /* 802.11g */
+ 0, 0, 0, 0, /* index safely using a value masked with 0xF */
+};
+#define RTL818X_NR_B_RATES 4
+#define RTL818X_NR_RATES 12
+
+/* used by RF drivers */
+void rtl818x_write_phy(struct net80211_device *dev, u8 addr, u32 data)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ int i = 10;
+ u32 buf;
+
+ buf = (data << 8) | addr;
+
+ rtl818x_iowrite32(priv, (u32 *)&priv->map->PHY[0], buf | 0x80);
+ while (i--) {
+ rtl818x_iowrite32(priv, (u32 *)&priv->map->PHY[0], buf);
+ if (rtl818x_ioread8(priv, &priv->map->PHY[2]) == (data & 0xFF))
+ return;
+ }
+}
+
+static void rtl818x_handle_rx(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ unsigned int count = RTL818X_RX_RING_SIZE;
+
+ while (count--) {
+ struct rtl818x_rx_desc *entry = &priv->rx_ring[priv->rx_idx];
+ struct io_buffer *iob = priv->rx_buf[priv->rx_idx];
+ u32 flags = le32_to_cpu(entry->flags);
+
+ if (flags & RTL818X_RX_DESC_FLAG_OWN)
+ return;
+
+ if (flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL |
+ RTL818X_RX_DESC_FLAG_FOF |
+ RTL818X_RX_DESC_FLAG_RX_ERR)) {
+ /* This is crappy hardware. The Linux driver
+ doesn't even log these. */
+ goto done;
+ } else if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) {
+ /* This is actually a corrupt packet. */
+ DBG2("rtl818x RX:%d CRC fail: flags %08x\n",
+ priv->rx_idx, flags);
+ net80211_rx_err(dev, NULL, EIO);
+ } else {
+ u32 flags2 = le32_to_cpu(entry->flags2);
+ struct io_buffer *new_iob = alloc_iob(MAX_RX_SIZE);
+ if (!new_iob) {
+ net80211_rx_err(dev, NULL, ENOMEM);
+ goto done;
+ }
+
+ DBGP("rtl818x RX:%d success: flags %08x %08x\n",
+ priv->rx_idx, flags, flags2);
+
+ iob_put(iob, flags & 0xFFF);
+
+ net80211_rx(dev, iob, (flags2 >> 8) & 0x7f,
+ rtl818x_rates[(flags >> 20) & 0xf]);
+
+ iob = new_iob;
+ priv->rx_buf[priv->rx_idx] = iob;
+ }
+
+ done:
+ entry->rx_buf = cpu_to_le32(virt_to_bus(iob->data));
+ entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN | MAX_RX_SIZE);
+
+ if (priv->rx_idx == RTL818X_RX_RING_SIZE - 1)
+ entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR);
+
+ priv->rx_idx = (priv->rx_idx + 1) % RTL818X_RX_RING_SIZE;
+ }
+}
+
+static void rtl818x_handle_tx(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ unsigned int count = RTL818X_TX_RING_SIZE;
+
+ while (count--) {
+ struct rtl818x_tx_desc *entry = &priv->tx_ring[priv->tx_cons];
+ struct io_buffer *iob = priv->tx_buf[priv->tx_cons];
+ u32 flags = le32_to_cpu(entry->flags);
+ int rc;
+
+ if ((flags & RTL818X_TX_DESC_FLAG_OWN) || !iob)
+ return;
+
+ rc = 0;
+ if (!(flags & RTL818X_TX_DESC_FLAG_TX_OK)) {
+ /* our packet was not ACKed properly */
+ rc = EIO;
+ }
+
+ net80211_tx_complete(dev, iob, flags & 0xFF, rc);
+
+ priv->tx_buf[priv->tx_cons] = NULL;
+ priv->tx_cons = (priv->tx_cons + 1) % RTL818X_TX_RING_SIZE;
+ }
+}
+
+static void rtl818x_poll(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u16 reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS);
+
+ if (reg == 0xFFFF)
+ return;
+
+ rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg);
+
+ if (reg & (RTL818X_INT_TXN_OK | RTL818X_INT_TXN_ERR))
+ rtl818x_handle_tx(dev);
+
+ if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR))
+ rtl818x_handle_rx(dev);
+}
+
+#define DIV_ROUND_UP(n,d) (((n)+(d)-1)/(d))
+
+static int rtl818x_tx(struct net80211_device *dev, struct io_buffer *iob)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ struct rtl818x_tx_desc *entry;
+ u32 tx_flags;
+ u16 plcp_len = 0;
+ int len = iob_len(iob);
+
+ tx_flags = RTL818X_TX_DESC_FLAG_OWN | RTL818X_TX_DESC_FLAG_FS |
+ RTL818X_TX_DESC_FLAG_LS | (priv->hw_rate << 24) | len;
+
+ if (priv->r8185) {
+ tx_flags |= RTL818X_TX_DESC_FLAG_DMA |
+ RTL818X_TX_DESC_FLAG_NO_ENC;
+ } else {
+ unsigned int remainder;
+
+ plcp_len = DIV_ROUND_UP(16 * (len + 4),
+ (dev->rates[dev->rate] * 2) / 10);
+ remainder = (16 * (len + 4)) %
+ ((dev->rates[dev->rate] * 2) / 10);
+
+ if (remainder > 0 && remainder <= 6)
+ plcp_len |= 1 << 15;
+ }
+
+ entry = &priv->tx_ring[priv->tx_prod];
+
+ if (dev->phy_flags & NET80211_PHY_USE_PROTECTION) {
+ tx_flags |= RTL818X_TX_DESC_FLAG_CTS;
+ tx_flags |= priv->hw_rtscts_rate << 19;
+ entry->rts_duration = net80211_cts_duration(dev, len);
+ } else {
+ entry->rts_duration = 0;
+ }
+
+ if (entry->flags & RTL818X_TX_DESC_FLAG_OWN) {
+ /* card hasn't processed the old packet yet! */
+ return -EBUSY;
+ }
+
+ priv->tx_buf[priv->tx_prod] = iob;
+ priv->tx_prod = (priv->tx_prod + 1) % RTL818X_TX_RING_SIZE;
+
+ entry->plcp_len = cpu_to_le16(plcp_len);
+ entry->tx_buf = cpu_to_le32(virt_to_bus(iob->data));
+ entry->frame_len = cpu_to_le32(len);
+ entry->flags2 = /* alternate retry rate in 100kbps << 4 */ 0;
+ entry->retry_limit = RTL818X_MAX_RETRIES;
+ entry->flags = cpu_to_le32(tx_flags);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << 5));
+
+ return 0;
+}
+
+void rtl818x_set_anaparam(struct rtl818x_priv *priv, u32 anaparam)
+{
+ u8 reg;
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3,
+ reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM, anaparam);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3,
+ reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+}
+
+static int rtl818x_init_hw(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u16 reg;
+
+ rtl818x_iowrite8(priv, &priv->map->CMD, 0);
+ rtl818x_ioread8(priv, &priv->map->CMD);
+ mdelay(10);
+
+ /* reset */
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+ rtl818x_ioread8(priv, &priv->map->CMD);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg &= (1 << 1);
+ reg |= RTL818X_CMD_RESET;
+ rtl818x_iowrite8(priv, &priv->map->CMD, RTL818X_CMD_RESET);
+ rtl818x_ioread8(priv, &priv->map->CMD);
+ mdelay(200);
+
+ /* check success of reset */
+ if (rtl818x_ioread8(priv, &priv->map->CMD) & RTL818X_CMD_RESET) {
+ DBG("rtl818x %s: reset timeout!\n", dev->netdev->name);
+ return -ETIMEDOUT;
+ }
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD);
+ rtl818x_ioread8(priv, &priv->map->CMD);
+ mdelay(200);
+
+ if (rtl818x_ioread8(priv, &priv->map->CONFIG3) & (1 << 3)) {
+ /* For cardbus */
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ reg |= 1 << 1;
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg);
+ reg = rtl818x_ioread16(priv, &priv->map->FEMR);
+ reg |= (1 << 15) | (1 << 14) | (1 << 4);
+ rtl818x_iowrite16(priv, &priv->map->FEMR, reg);
+ }
+
+ rtl818x_iowrite8(priv, &priv->map->MSR, 0);
+
+ if (!priv->r8185)
+ rtl818x_set_anaparam(priv, priv->anaparam);
+
+ rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma);
+ rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring_dma);
+
+ /* TODO: necessary? specs indicate not */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG2);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg & ~(1 << 3));
+ if (priv->r8185) {
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG2);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg | (1 << 4));
+ }
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ /* TODO: set CONFIG5 for calibrating AGC on rtl8180 + philips radio? */
+
+ /* TODO: turn off hw wep on rtl8180 */
+
+ rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
+
+ if (priv->r8185) {
+ rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
+ rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
+ rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0);
+
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+
+ /* TODO: set ClkRun enable? necessary? */
+ reg = rtl818x_ioread8(priv, &priv->map->GP_ENABLE);
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, reg & ~(1 << 6));
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | (1 << 2));
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+ } else {
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0x1);
+ rtl818x_iowrite8(priv, &priv->map->SECURITY, 0);
+
+ rtl818x_iowrite8(priv, &priv->map->PHY_DELAY, 0x6);
+ rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, 0x4C);
+ }
+
+ priv->rf->init(dev);
+ if (priv->r8185)
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+ return 0;
+}
+
+static int rtl818x_init_rx_ring(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ struct rtl818x_rx_desc *entry;
+ int i;
+
+ priv->rx_ring = malloc_dma(sizeof(*priv->rx_ring) * RTL818X_RX_RING_SIZE,
+ RTL818X_RING_ALIGN);
+ priv->rx_ring_dma = virt_to_bus(priv->rx_ring);
+ if (!priv->rx_ring) {
+ DBG("rtl818x %s: cannot allocate RX ring\n", dev->netdev->name);
+ return -ENOMEM;
+ }
+
+ memset(priv->rx_ring, 0, sizeof(*priv->rx_ring) * RTL818X_RX_RING_SIZE);
+ priv->rx_idx = 0;
+
+ for (i = 0; i < RTL818X_RX_RING_SIZE; i++) {
+ struct io_buffer *iob = alloc_iob(MAX_RX_SIZE);
+ entry = &priv->rx_ring[i];
+ if (!iob)
+ return -ENOMEM;
+
+ priv->rx_buf[i] = iob;
+ entry->rx_buf = cpu_to_le32(virt_to_bus(iob->data));
+ entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN |
+ MAX_RX_SIZE);
+ }
+ entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR);
+ return 0;
+}
+
+static void rtl818x_free_rx_ring(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ int i;
+
+ for (i = 0; i < RTL818X_RX_RING_SIZE; i++) {
+ free_iob(priv->rx_buf[i]);
+ priv->rx_buf[i] = NULL;
+ }
+
+ free_dma(priv->rx_ring, sizeof(*priv->rx_ring) * RTL818X_RX_RING_SIZE);
+ priv->rx_ring = NULL;
+}
+
+static int rtl818x_init_tx_ring(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ int i;
+
+ priv->tx_ring = malloc_dma(sizeof(*priv->tx_ring) * RTL818X_TX_RING_SIZE,
+ RTL818X_RING_ALIGN);
+ priv->tx_ring_dma = virt_to_bus(priv->tx_ring);
+ if (!priv->tx_ring) {
+ DBG("rtl818x %s: cannot allocate TX ring\n", dev->netdev->name);
+ return -ENOMEM;
+ }
+
+ memset(priv->tx_ring, 0, sizeof(*priv->tx_ring) * RTL818X_TX_RING_SIZE);
+ priv->tx_prod = priv->tx_cons = 0;
+
+ for (i = 0; i < RTL818X_TX_RING_SIZE; i++)
+ priv->tx_ring[i].next_tx_desc = cpu_to_le32(priv->tx_ring_dma +
+ ((i + 1) % RTL818X_TX_RING_SIZE) * sizeof(*priv->tx_ring));
+
+ return 0;
+}
+
+static void rtl818x_free_tx_ring(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ int i;
+
+ for (i = 0; i < RTL818X_TX_RING_SIZE; i++) {
+ if (priv->tx_buf[i])
+ net80211_tx_complete(dev, priv->tx_buf[i], 0, ECANCELED);
+ priv->tx_buf[i] = NULL;
+ }
+
+ free_dma(priv->tx_ring, sizeof(*priv->tx_ring) * RTL818X_TX_RING_SIZE);
+ priv->tx_ring = NULL;
+}
+
+static void rtl818x_irq(struct net80211_device *dev, int enable)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, enable? 0xFFFF : 0);
+}
+
+/* Sets the MAC address of the card. */
+static void rtl818x_set_hwaddr(struct net80211_device *dev, u8 *hwaddr)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ rtl818x_iowrite32(priv, (u32 *)&priv->map->MAC[0],
+ le32_to_cpu(*(u32 *)hwaddr));
+ rtl818x_iowrite16(priv, (u16 *)&priv->map->MAC[4],
+ le16_to_cpu(*(u16 *)(hwaddr + 4)));
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+}
+
+static int rtl818x_start(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ int ret;
+ u32 reg;
+
+ ret = rtl818x_init_rx_ring(dev);
+ if (ret)
+ return ret;
+
+ ret = rtl818x_init_tx_ring(dev);
+ if (ret)
+ goto err_free_rings;
+
+ ret = rtl818x_init_hw(dev);
+ if (ret)
+ goto err_free_rings;
+
+ rtl818x_set_hwaddr(dev, dev->netdev->ll_addr);
+
+ rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma);
+ rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring_dma);
+
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+ rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0);
+ rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0);
+
+ reg = RTL818X_RX_CONF_ONLYERLPKT |
+ RTL818X_RX_CONF_RX_AUTORESETPHY |
+ RTL818X_RX_CONF_MGMT |
+ RTL818X_RX_CONF_DATA |
+ (7 << 8 /* MAX RX DMA */) |
+ RTL818X_RX_CONF_BROADCAST |
+ RTL818X_RX_CONF_NICMAC;
+
+ if (priv->r8185)
+ reg |= RTL818X_RX_CONF_CSDM1 | RTL818X_RX_CONF_CSDM2;
+ else {
+ reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE1)
+ ? RTL818X_RX_CONF_CSDM1 : 0;
+ reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE2)
+ ? RTL818X_RX_CONF_CSDM2 : 0;
+ }
+
+ priv->rx_conf = reg;
+ rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
+
+ if (priv->r8185) {
+ reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
+ reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
+ reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
+ rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
+
+ reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
+ reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
+ reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
+ reg |= RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
+ rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
+
+ /* disable early TX */
+ rtl818x_iowrite8(priv, (u8 *)priv->map + 0xec, 0x3f);
+ }
+
+ reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+ reg |= (6 << 21 /* MAX TX DMA */) |
+ RTL818X_TX_CONF_NO_ICV;
+
+ if (priv->r8185)
+ reg &= ~RTL818X_TX_CONF_PROBE_DTS;
+ else
+ reg &= ~RTL818X_TX_CONF_HW_SEQNUM;
+
+ /* different meaning, same value on both rtl8185 and rtl8180 */
+ reg &= ~RTL818X_TX_CONF_SAT_HWPLCP;
+
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg |= RTL818X_CMD_RX_ENABLE;
+ reg |= RTL818X_CMD_TX_ENABLE;
+ rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+ DBG("%s rtl818x: started\n", dev->netdev->name);
+
+ return 0;
+
+ err_free_rings:
+ rtl818x_free_rx_ring(dev);
+ if (priv->tx_ring)
+ rtl818x_free_tx_ring(dev);
+
+ DBG("%s rtl818x: failed to start\n", dev->netdev->name);
+
+ return ret;
+}
+
+static void rtl818x_stop(struct net80211_device *dev)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ u8 reg;
+
+ rtl818x_irq(dev, 0);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg &= ~RTL818X_CMD_TX_ENABLE;
+ reg &= ~RTL818X_CMD_RX_ENABLE;
+ rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+ priv->rf->stop(dev);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl818x_free_rx_ring(dev);
+ rtl818x_free_tx_ring(dev);
+}
+
+static int rtl818x_config(struct net80211_device *dev, int changed)
+{
+ struct rtl818x_priv *priv = dev->priv;
+ int i;
+
+ if (changed & NET80211_CFG_CHANNEL)
+ priv->rf->set_chan(dev, &dev->channels[dev->channel]);
+
+ if (changed & NET80211_CFG_ASSOC) {
+ for (i = 0; i < ETH_ALEN; i++)
+ rtl818x_iowrite8(priv, &priv->map->BSSID[i], dev->bssid[i]);
+ rtl818x_iowrite8(priv, &priv->map->MSR,
+ dev->state & NET80211_ASSOCIATED?
+ RTL818X_MSR_INFRA : RTL818X_MSR_NO_LINK);
+ }
+
+ if (changed & NET80211_CFG_PHY_PARAMS)
+ priv->rf->conf_erp(dev);
+
+ if (changed & NET80211_CFG_RATE) {
+ /* figure out the hardware rate number for the new
+ logical rate */
+ int hw_rate;
+ for (hw_rate = 0; hw_rate < RTL818X_NR_RATES &&
+ rtl818x_rates[hw_rate] != dev->rates[dev->rate];
+ hw_rate++)
+ ;
+ if (hw_rate >= RTL818X_NR_RATES)
+ return -EINVAL;
+
+ priv->hw_rate = hw_rate;
+
+ /* and the RTS/CTS rate */
+ for (hw_rate = 0; hw_rate < RTL818X_NR_RATES &&
+ rtl818x_rates[hw_rate] !=
+ dev->rates[dev->rtscts_rate];
+ hw_rate++)
+ ;
+ if (hw_rate >= RTL818X_NR_RATES)
+ hw_rate = priv->hw_rate;
+
+ priv->hw_rtscts_rate = hw_rate;
+ }
+
+ return 0;
+}
+
+static const u8 rtl818x_eeprom_bits[] = {
+ [SPI_BIT_SCLK] = RTL818X_EEPROM_CMD_CK,
+ [SPI_BIT_MISO] = RTL818X_EEPROM_CMD_READ,
+ [SPI_BIT_MOSI] = RTL818X_EEPROM_CMD_WRITE,
+ [SPI_BIT_SS(0)] = RTL818X_EEPROM_CMD_CS,
+};
+
+static int rtl818x_spi_read_bit(struct bit_basher *basher, unsigned int bit_id)
+{
+ struct rtl818x_priv *priv = container_of(basher, struct rtl818x_priv,
+ spibit.basher);
+
+ u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ return reg & rtl818x_eeprom_bits[bit_id];
+}
+
+static void rtl818x_spi_write_bit(struct bit_basher *basher,
+ unsigned int bit_id, unsigned long data)
+{
+ struct rtl818x_priv *priv = container_of(basher, struct rtl818x_priv,
+ spibit.basher);
+
+ u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ u8 mask = rtl818x_eeprom_bits[bit_id];
+ reg = (reg & ~mask) | (data & mask);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg);
+
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(10);
+}
+
+static struct bit_basher_operations rtl818x_basher_ops = {
+ .read = rtl818x_spi_read_bit,
+ .write = rtl818x_spi_write_bit,
+};
+
+#if DBGLVL_MAX
+static const char *rtl818x_rf_names[] = {
+ NULL, /* no 0 */
+ "Intersil", "RFMD", /* unsupported 1-2 */
+ "SA2400", "max2820", "GRF5101", /* supported 3-5 */
+ NULL, NULL, NULL, /* no 6-8 */
+ "RTL8225", /* supported 9 */
+ "RTL8255", /* unsupported 10 */
+};
+#define RTL818X_NR_RF_NAMES 11
+#endif
+
+struct net80211_device_operations rtl818x_operations = {
+ .open = rtl818x_start,
+ .close = rtl818x_stop,
+ .transmit = rtl818x_tx,
+ .poll = rtl818x_poll,
+ .irq = rtl818x_irq,
+ .config = rtl818x_config,
+};
+
+static int rtl818x_probe(struct pci_device *pdev )
+{
+ struct net80211_device *dev;
+ struct rtl818x_priv *priv;
+ struct rtl818x_rf_ops *rf;
+ int err, i;
+ const char *chip_name;
+ u32 reg;
+ u16 eeprom_val;
+ struct net80211_hw_info *hwinfo;
+
+ hwinfo = zalloc(sizeof(*hwinfo));
+ if (!hwinfo) {
+ DBG("rtl818x: hwinfo alloc failed\n");
+ return -ENOMEM;
+ }
+
+ adjust_pci_device(pdev);
+
+ dev = net80211_alloc(sizeof(*priv));
+ if (!dev) {
+ DBG("rtl818x: net80211 alloc failed\n");
+ return -ENOMEM;
+ }
+
+ priv = dev->priv;
+ priv->pdev = pdev;
+ dev->netdev->dev = &pdev->dev;
+
+ priv->map = (struct rtl818x_csr *)pdev->ioaddr;
+ if (!priv->map) {
+ DBG("rtl818x: cannot find device memory\n");
+ err = -ENXIO;
+ goto err_free_dev;
+ }
+
+ reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+ reg &= RTL818X_TX_CONF_HWVER_MASK;
+ switch (reg) {
+ case RTL818X_TX_CONF_R8180_ABCD:
+ chip_name = "0";
+ break;
+ case RTL818X_TX_CONF_R8180_F:
+ chip_name = "0vF";
+ break;
+ case RTL818X_TX_CONF_R8185_ABC:
+ chip_name = "5";
+ break;
+ case RTL818X_TX_CONF_R8185_D:
+ chip_name = "5vD";
+ break;
+ default:
+ DBG("rtl818x: Unknown chip! (0x%x)\n", reg >> 25);
+ err = -ENOSYS;
+ goto err_free_dev;
+ }
+
+ priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC;
+
+ hwinfo->bands = NET80211_BAND_BIT_2GHZ;
+ hwinfo->flags = NET80211_HW_RX_HAS_FCS;
+ hwinfo->signal_type = NET80211_SIGNAL_ARBITRARY;
+ hwinfo->signal_max = 65;
+ hwinfo->channel_change_time = 1000;
+
+ memcpy(hwinfo->rates[NET80211_BAND_2GHZ], rtl818x_rates,
+ sizeof(*rtl818x_rates) * RTL818X_NR_RATES);
+
+ if (priv->r8185) {
+ hwinfo->modes = NET80211_MODE_B | NET80211_MODE_G;
+ hwinfo->nr_rates[NET80211_BAND_2GHZ] = RTL818X_NR_RATES;
+ } else {
+ hwinfo->modes = NET80211_MODE_B;
+ hwinfo->nr_rates[NET80211_BAND_2GHZ] = RTL818X_NR_B_RATES;
+ }
+
+ priv->spibit.basher.op = &rtl818x_basher_ops;
+ priv->spibit.bus.mode = SPI_MODE_THREEWIRE;
+ init_spi_bit_basher(&priv->spibit);
+
+ DBG2("rtl818x RX_CONF: %08x\n", rtl818x_ioread32(priv, &priv->map->RX_CONF));
+
+ if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6))
+ init_at93c66(&priv->eeprom, 16);
+ else
+ init_at93c46(&priv->eeprom, 16);
+ priv->eeprom.bus = &priv->spibit.bus;
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_PROGRAM);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(10);
+
+ nvs_read(&priv->eeprom.nvs, 0x06, &eeprom_val, 2);
+ DBG2("rtl818x eeprom val = %04x\n", eeprom_val);
+ eeprom_val &= 0xFF;
+
+ priv->rf = NULL;
+ for_each_table_entry(rf, RTL818X_RF_DRIVERS) {
+ if (rf->id == eeprom_val) {
+ priv->rf = rf;
+ break;
+ }
+ }
+
+ if (!priv->rf) {
+#if DBGLVL_MAX
+ if (eeprom_val < RTL818X_NR_RF_NAMES &&
+ rtl818x_rf_names[eeprom_val] != NULL)
+ DBG("rtl818x: %s RF frontend not supported!\n",
+ rtl818x_rf_names[eeprom_val]);
+ else
+ DBG("rtl818x: RF frontend #%d not recognized!\n",
+ eeprom_val);
+#endif
+
+ err = -ENOSYS;
+ goto err_free_dev;
+ }
+
+ nvs_read(&priv->eeprom.nvs, 0x17, &eeprom_val, 2);
+ priv->csthreshold = eeprom_val >> 8;
+ if (!priv->r8185) {
+ nvs_read(&priv->eeprom.nvs, 0xD, &priv->anaparam, 4);
+ nvs_read(&priv->eeprom.nvs, 0x19, &priv->rfparam, 2);
+ priv->anaparam = le32_to_cpu(priv->anaparam);
+ priv->rfparam = le16_to_cpu(priv->rfparam);
+ }
+
+ /* read the MAC address */
+ nvs_read(&priv->eeprom.nvs, 0x7, hwinfo->hwaddr, 6);
+
+ /* CCK TX power */
+ for (i = 0; i < 14; i += 2) {
+ u16 txpwr;
+ nvs_read(&priv->eeprom.nvs, 0x10 + (i >> 1), &txpwr, 2);
+ priv->txpower[i] = txpwr & 0xFF;
+ priv->txpower[i + 1] = txpwr >> 8;
+ }
+
+ /* OFDM TX power */
+ if (priv->r8185) {
+ for (i = 0; i < 14; i += 2) {
+ u16 txpwr;
+ nvs_read(&priv->eeprom.nvs, 0x20 + (i >> 1), &txpwr, 2);
+ priv->txpower[i] |= (txpwr & 0xFF) << 8;
+ priv->txpower[i + 1] |= txpwr & 0xFF00;
+ }
+ }
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ err = net80211_register(dev, &rtl818x_operations, hwinfo);
+ if (err) {
+ DBG("rtl818x: cannot register device\n");
+ goto err_free_dev;
+ }
+
+ free(hwinfo);
+
+ DBG("rtl818x: Realtek RTL818%s (RF chip %s) with address %s\n",
+ chip_name, priv->rf->name, netdev_addr(dev->netdev));
+
+ return 0;
+
+ err_free_dev:
+ pci_set_drvdata(pdev, NULL);
+ net80211_free(dev);
+ free(hwinfo);
+ return err;
+}
+
+static void rtl818x_remove(struct pci_device *pdev)
+{
+ struct net80211_device *dev = pci_get_drvdata(pdev);
+
+ if (!dev)
+ return;
+
+ net80211_unregister(dev);
+ net80211_free(dev);
+}
+
+/* Hide PCI_ROM definitions in here from parserom.pl; the definitions
+ that should be used are in rtl8180.c and rtl8185.c. */
+#define RTL_ROM PCI_ROM
+
+static struct pci_device_id rtl818x_nics[] = {
+ RTL_ROM(0x10ec, 0x8185, "rtl8185", "Realtek 8185", 0),
+ RTL_ROM(0x1799, 0x700f, "f5d7000", "Belkin F5D7000", 0),
+ RTL_ROM(0x1799, 0x701f, "f5d7010", "Belkin F5D7010", 0),
+
+ RTL_ROM(0x10ec, 0x8180, "rtl8180", "Realtek 8180", 0),
+ RTL_ROM(0x1799, 0x6001, "f5d6001", "Belkin F5D6001", 0),
+ RTL_ROM(0x1799, 0x6020, "f5d6020", "Belkin F5D6020", 0),
+ RTL_ROM(0x1186, 0x3300, "dwl510", "D-Link DWL-510", 0),
+};
+
+struct pci_driver rtl818x_driver __pci_driver = {
+ .ids = rtl818x_nics,
+ .id_count = sizeof(rtl818x_nics) / sizeof(rtl818x_nics[0]),
+ .probe = rtl818x_probe,
+ .remove = rtl818x_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl818x.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl818x.h
new file mode 100644
index 00000000..4e57d0bd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/rtl818x/rtl818x.h
@@ -0,0 +1,359 @@
+/*
+ * Definitions for RTL818x hardware
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Modified for iPXE, June 2009, by Joshua Oreman <oremanj@rwcr.net>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RTL818X_H
+#define RTL818X_H
+
+#include <ipxe/spi_bit.h>
+#include <ipxe/tables.h>
+
+FILE_LICENCE(GPL2_ONLY);
+
+struct rtl818x_csr {
+ u8 MAC[6];
+ u8 reserved_0[2];
+ u32 MAR[2];
+ u8 RX_FIFO_COUNT;
+ u8 reserved_1;
+ u8 TX_FIFO_COUNT;
+ u8 BQREQ;
+ u8 reserved_2[4];
+ u32 TSFT[2];
+ u32 TLPDA;
+ u32 TNPDA;
+ u32 THPDA;
+ u16 BRSR;
+ u8 BSSID[6];
+ u8 RESP_RATE;
+ u8 EIFS;
+ u8 reserved_3[1];
+ u8 CMD;
+#define RTL818X_CMD_TX_ENABLE (1 << 2)
+#define RTL818X_CMD_RX_ENABLE (1 << 3)
+#define RTL818X_CMD_RESET (1 << 4)
+ u8 reserved_4[4];
+ u16 INT_MASK;
+ u16 INT_STATUS;
+#define RTL818X_INT_RX_OK (1 << 0)
+#define RTL818X_INT_RX_ERR (1 << 1)
+#define RTL818X_INT_TXL_OK (1 << 2)
+#define RTL818X_INT_TXL_ERR (1 << 3)
+#define RTL818X_INT_RX_DU (1 << 4)
+#define RTL818X_INT_RX_FO (1 << 5)
+#define RTL818X_INT_TXN_OK (1 << 6)
+#define RTL818X_INT_TXN_ERR (1 << 7)
+#define RTL818X_INT_TXH_OK (1 << 8)
+#define RTL818X_INT_TXH_ERR (1 << 9)
+#define RTL818X_INT_TXB_OK (1 << 10)
+#define RTL818X_INT_TXB_ERR (1 << 11)
+#define RTL818X_INT_ATIM (1 << 12)
+#define RTL818X_INT_BEACON (1 << 13)
+#define RTL818X_INT_TIME_OUT (1 << 14)
+#define RTL818X_INT_TX_FO (1 << 15)
+ u32 TX_CONF;
+#define RTL818X_TX_CONF_LOOPBACK_MAC (1 << 17)
+#define RTL818X_TX_CONF_LOOPBACK_CONT (3 << 17)
+#define RTL818X_TX_CONF_NO_ICV (1 << 19)
+#define RTL818X_TX_CONF_DISCW (1 << 20)
+#define RTL818X_TX_CONF_SAT_HWPLCP (1 << 24)
+#define RTL818X_TX_CONF_R8180_ABCD (2 << 25)
+#define RTL818X_TX_CONF_R8180_F (3 << 25)
+#define RTL818X_TX_CONF_R8185_ABC (4 << 25)
+#define RTL818X_TX_CONF_R8185_D (5 << 25)
+#define RTL818X_TX_CONF_R8187vD (5 << 25)
+#define RTL818X_TX_CONF_R8187vD_B (6 << 25)
+#define RTL818X_TX_CONF_HWVER_MASK (7 << 25)
+#define RTL818X_TX_CONF_DISREQQSIZE (1 << 28)
+#define RTL818X_TX_CONF_PROBE_DTS (1 << 29)
+#define RTL818X_TX_CONF_HW_SEQNUM (1 << 30)
+#define RTL818X_TX_CONF_CW_MIN (1 << 31)
+ u32 RX_CONF;
+#define RTL818X_RX_CONF_MONITOR (1 << 0)
+#define RTL818X_RX_CONF_NICMAC (1 << 1)
+#define RTL818X_RX_CONF_MULTICAST (1 << 2)
+#define RTL818X_RX_CONF_BROADCAST (1 << 3)
+#define RTL818X_RX_CONF_FCS (1 << 5)
+#define RTL818X_RX_CONF_DATA (1 << 18)
+#define RTL818X_RX_CONF_CTRL (1 << 19)
+#define RTL818X_RX_CONF_MGMT (1 << 20)
+#define RTL818X_RX_CONF_ADDR3 (1 << 21)
+#define RTL818X_RX_CONF_PM (1 << 22)
+#define RTL818X_RX_CONF_BSSID (1 << 23)
+#define RTL818X_RX_CONF_RX_AUTORESETPHY (1 << 28)
+#define RTL818X_RX_CONF_CSDM1 (1 << 29)
+#define RTL818X_RX_CONF_CSDM2 (1 << 30)
+#define RTL818X_RX_CONF_ONLYERLPKT (1 << 31)
+ u32 INT_TIMEOUT;
+ u32 TBDA;
+ u8 EEPROM_CMD;
+#define RTL818X_EEPROM_CMD_READ (1 << 0)
+#define RTL818X_EEPROM_CMD_WRITE (1 << 1)
+#define RTL818X_EEPROM_CMD_CK (1 << 2)
+#define RTL818X_EEPROM_CMD_CS (1 << 3)
+#define RTL818X_EEPROM_CMD_NORMAL (0 << 6)
+#define RTL818X_EEPROM_CMD_LOAD (1 << 6)
+#define RTL818X_EEPROM_CMD_PROGRAM (2 << 6)
+#define RTL818X_EEPROM_CMD_CONFIG (3 << 6)
+ u8 CONFIG0;
+ u8 CONFIG1;
+ u8 CONFIG2;
+#define RTL818X_CONFIG2_ANTENNA_DIV (1 << 6)
+ u32 ANAPARAM;
+ u8 MSR;
+#define RTL818X_MSR_NO_LINK (0 << 2)
+#define RTL818X_MSR_ADHOC (1 << 2)
+#define RTL818X_MSR_INFRA (2 << 2)
+#define RTL818X_MSR_MASTER (3 << 2)
+#define RTL818X_MSR_ENEDCA (4 << 2)
+ u8 CONFIG3;
+#define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6)
+#define RTL818X_CONFIG3_GNT_SELECT (1 << 7)
+ u8 CONFIG4;
+#define RTL818X_CONFIG4_POWEROFF (1 << 6)
+#define RTL818X_CONFIG4_VCOOFF (1 << 7)
+ u8 TESTR;
+ u8 reserved_9[2];
+ u8 PGSELECT;
+ u8 SECURITY;
+ u32 ANAPARAM2;
+ u8 reserved_10[12];
+ u16 BEACON_INTERVAL;
+ u16 ATIM_WND;
+ u16 BEACON_INTERVAL_TIME;
+ u16 ATIMTR_INTERVAL;
+ u8 PHY_DELAY;
+ u8 CARRIER_SENSE_COUNTER;
+ u8 reserved_11[2];
+ u8 PHY[4];
+ u16 RFPinsOutput;
+ u16 RFPinsEnable;
+ u16 RFPinsSelect;
+ u16 RFPinsInput;
+ u32 RF_PARA;
+ u32 RF_TIMING;
+ u8 GP_ENABLE;
+ u8 GPIO;
+ u8 reserved_12[2];
+ u32 HSSI_PARA;
+ u8 reserved_13[4];
+ u8 TX_AGC_CTL;
+#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT (1 << 0)
+#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT (1 << 1)
+#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT (1 << 2)
+ u8 TX_GAIN_CCK;
+ u8 TX_GAIN_OFDM;
+ u8 TX_ANTENNA;
+ u8 reserved_14[16];
+ u8 WPA_CONF;
+ u8 reserved_15[3];
+ u8 SIFS;
+ u8 DIFS;
+ u8 SLOT;
+ u8 reserved_16[5];
+ u8 CW_CONF;
+#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT (1 << 0)
+#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT (1 << 1)
+ u8 CW_VAL;
+ u8 RATE_FALLBACK;
+#define RTL818X_RATE_FALLBACK_ENABLE (1 << 7)
+ u8 ACM_CONTROL;
+ u8 reserved_17[24];
+ u8 CONFIG5;
+ u8 TX_DMA_POLLING;
+ u8 reserved_18[2];
+ u16 CWR;
+ u8 RETRY_CTR;
+ u8 reserved_19[3];
+ u16 INT_MIG;
+/* RTL818X_R8187B_*: magic numbers from ioregisters */
+#define RTL818X_R8187B_B 0
+#define RTL818X_R8187B_D 1
+#define RTL818X_R8187B_E 2
+ u32 RDSAR;
+ u16 TID_AC_MAP;
+ u8 reserved_20[4];
+ u8 ANAPARAM3;
+ u8 reserved_21[5];
+ u16 FEMR;
+ u8 reserved_22[4];
+ u16 TALLY_CNT;
+ u8 TALLY_SEL;
+} __attribute__((packed));
+
+#define MAX_RX_SIZE IEEE80211_MAX_FRAME_LEN
+
+#define RF_PARAM_ANALOGPHY (1 << 0)
+#define RF_PARAM_ANTBDEFAULT (1 << 1)
+#define RF_PARAM_CARRIERSENSE1 (1 << 2)
+#define RF_PARAM_CARRIERSENSE2 (1 << 3)
+
+#define BB_ANTATTEN_CHAN14 0x0C
+#define BB_ANTENNA_B 0x40
+
+#define BB_HOST_BANG (1 << 30)
+#define BB_HOST_BANG_EN (1 << 2)
+#define BB_HOST_BANG_CLK (1 << 1)
+#define BB_HOST_BANG_DATA 1
+
+#define ANAPARAM_TXDACOFF_SHIFT 27
+#define ANAPARAM_PWR0_SHIFT 28
+#define ANAPARAM_PWR0_MASK (0x07 << ANAPARAM_PWR0_SHIFT)
+#define ANAPARAM_PWR1_SHIFT 20
+#define ANAPARAM_PWR1_MASK (0x7F << ANAPARAM_PWR1_SHIFT)
+
+#define RTL818X_RX_RING_SIZE 8 /* doesn't have to be a power of 2 */
+#define RTL818X_TX_RING_SIZE 8 /* nor this [but 2^n is very slightly faster] */
+#define RTL818X_RING_ALIGN 256
+
+#define RTL818X_MAX_RETRIES 4
+
+enum rtl818x_tx_desc_flags {
+ RTL818X_TX_DESC_FLAG_NO_ENC = (1 << 15),
+ RTL818X_TX_DESC_FLAG_TX_OK = (1 << 15),
+ RTL818X_TX_DESC_FLAG_SPLCP = (1 << 16),
+ RTL818X_TX_DESC_FLAG_RX_UNDER = (1 << 16),
+ RTL818X_TX_DESC_FLAG_MOREFRAG = (1 << 17),
+ RTL818X_TX_DESC_FLAG_CTS = (1 << 18),
+ RTL818X_TX_DESC_FLAG_RTS = (1 << 23),
+ RTL818X_TX_DESC_FLAG_LS = (1 << 28),
+ RTL818X_TX_DESC_FLAG_FS = (1 << 29),
+ RTL818X_TX_DESC_FLAG_DMA = (1 << 30),
+ RTL818X_TX_DESC_FLAG_OWN = (1 << 31)
+};
+
+struct rtl818x_tx_desc {
+ u32 flags;
+ u16 rts_duration;
+ u16 plcp_len;
+ u32 tx_buf;
+ u32 frame_len;
+ u32 next_tx_desc;
+ u8 cw;
+ u8 retry_limit;
+ u8 agc;
+ u8 flags2;
+ u32 reserved[2];
+} __attribute__ ((packed));
+
+enum rtl818x_rx_desc_flags {
+ RTL818X_RX_DESC_FLAG_ICV_ERR = (1 << 12),
+ RTL818X_RX_DESC_FLAG_CRC32_ERR = (1 << 13),
+ RTL818X_RX_DESC_FLAG_PM = (1 << 14),
+ RTL818X_RX_DESC_FLAG_RX_ERR = (1 << 15),
+ RTL818X_RX_DESC_FLAG_BCAST = (1 << 16),
+ RTL818X_RX_DESC_FLAG_PAM = (1 << 17),
+ RTL818X_RX_DESC_FLAG_MCAST = (1 << 18),
+ RTL818X_RX_DESC_FLAG_QOS = (1 << 19), /* RTL8187(B) only */
+ RTL818X_RX_DESC_FLAG_TRSW = (1 << 24), /* RTL8187(B) only */
+ RTL818X_RX_DESC_FLAG_SPLCP = (1 << 25),
+ RTL818X_RX_DESC_FLAG_FOF = (1 << 26),
+ RTL818X_RX_DESC_FLAG_DMA_FAIL = (1 << 27),
+ RTL818X_RX_DESC_FLAG_LS = (1 << 28),
+ RTL818X_RX_DESC_FLAG_FS = (1 << 29),
+ RTL818X_RX_DESC_FLAG_EOR = (1 << 30),
+ RTL818X_RX_DESC_FLAG_OWN = (1 << 31)
+};
+
+struct rtl818x_rx_desc {
+ u32 flags;
+ u32 flags2;
+ union {
+ u32 rx_buf;
+ u64 tsft;
+ };
+} __attribute__ ((packed));
+
+struct rtl818x_priv {
+ struct rtl818x_csr *map;
+ const struct rtl818x_rf_ops *rf;
+ int rf_flag; /* whatever RF driver wishes to use it for */
+ int hw_rate;
+ int hw_rtscts_rate;
+
+ struct spi_bit_basher spibit;
+ struct spi_device eeprom;
+
+ struct rtl818x_rx_desc *rx_ring;
+ u32 rx_ring_dma;
+ unsigned int rx_idx; /* next desc to be filled by card */
+ struct io_buffer *rx_buf[RTL818X_RX_RING_SIZE];
+
+ struct rtl818x_tx_desc *tx_ring;
+ u32 tx_ring_dma;
+ unsigned int tx_cons; /* next desc to be filled by card */
+ unsigned int tx_prod; /* next desc to be filled by driver */
+ struct io_buffer *tx_buf[RTL818X_TX_RING_SIZE];
+
+ struct pci_device *pdev;
+ u32 rx_conf;
+
+ u16 txpower[14];
+
+ int r8185;
+ u32 anaparam;
+ u16 rfparam;
+ u8 csthreshold;
+};
+
+void rtl818x_write_phy(struct net80211_device *dev, u8 addr, u32 data);
+void rtl818x_set_anaparam(struct rtl818x_priv *priv, u32 anaparam);
+
+static inline u8 rtl818x_ioread8(struct rtl818x_priv *priv __unused, u8 *addr)
+{
+ return inb(addr);
+}
+
+static inline u16 rtl818x_ioread16(struct rtl818x_priv *priv __unused, u16 *addr)
+{
+ return inw(addr);
+}
+
+static inline u32 rtl818x_ioread32(struct rtl818x_priv *priv __unused, u32 *addr)
+{
+ return inl(addr);
+}
+
+static inline void rtl818x_iowrite8(struct rtl818x_priv *priv __unused,
+ u8 *addr, u8 val)
+{
+ outb(val, addr);
+}
+
+static inline void rtl818x_iowrite16(struct rtl818x_priv *priv __unused,
+ u16 *addr, u16 val)
+{
+ outw(val, addr);
+}
+
+static inline void rtl818x_iowrite32(struct rtl818x_priv *priv __unused,
+ u32 *addr, u32 val)
+{
+ outl(val, addr);
+}
+
+#define RTL818X_RF_DRIVERS __table(struct rtl818x_rf_ops, "rtl818x_rf_drivers")
+#define __rtl818x_rf_driver __table_entry(RTL818X_RF_DRIVERS, 01)
+
+struct rtl818x_rf_ops {
+ char *name;
+ u8 id; /* as identified in EEPROM */
+ void (*init)(struct net80211_device *dev);
+ void (*stop)(struct net80211_device *dev);
+ void (*set_chan)(struct net80211_device *dev, struct net80211_channel *chan);
+ void (*conf_erp)(struct net80211_device *dev); /* set based on dev->erp_flags */
+};
+
+#endif /* RTL818X_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/sis190.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/sis190.c
new file mode 100644
index 00000000..991c30f9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/sis190.c
@@ -0,0 +1,1174 @@
+/*
+ sis190.c: Silicon Integrated Systems SiS190 ethernet driver
+
+ Copyright (c) 2003 K.M. Liu <kmliu@sis.com>
+ Copyright (c) 2003, 2004 Jeff Garzik <jgarzik@pobox.com>
+ Copyright (c) 2003, 2004, 2005 Francois Romieu <romieu@fr.zoreil.com>
+
+ Modified for iPXE 2009 by Thomas Miletich <thomas.miletich@gmail.com>
+
+ Based on r8169.c, tg3.c, 8139cp.c, skge.c, epic100.c and SiS 190/191
+ genuine driver.
+
+ This software may be used and distributed according to the terms of
+ the GNU General Public License (GPL), incorporated herein by reference.
+ Drivers based on or derived from this code fall under the GPL and must
+ retain the authorship, copyright and license notice. This file is not
+ a complete program and may only be used when the entire operating
+ system is licensed under the GPL.
+
+ See the file COPYING in this distribution for more information.
+
+ */
+
+FILE_LICENCE ( GPL_ANY );
+
+#include "sis190.h"
+
+static struct pci_device_id sis190_pci_tbl[] = {
+ PCI_ROM (0x1039, 0x0190, "sis190", "sis190", 0),
+ PCI_ROM (0x1039, 0x0191, "sis191", "sis191", 0),
+};
+
+/******************************************************************************
+ *************** HACK to keep ISA bridge in the PCI device list ***************
+ ******************************************************************************/
+
+/* Some sis190 variants store the MAC address in the BIOS CMOS. To read it, we
+ * have to use a PCI to ISA bridge. To access the bridge we need a few things
+ * from it's struct pci_device. We fake the successful probe of a driver to
+ * keep the bridge's struct pci_device in the list of pci_devices.
+ * See details in sis190_get_mac_addr_from_apc().
+ */
+
+static struct pci_device_id sis190_isa_bridge_tbl[] = {
+ PCI_ID (0x1039, 0x0965, "", "", 0),
+ PCI_ID (0x1039, 0x0966, "", "", 0),
+ PCI_ID (0x1039, 0x0968, "", "", 0),
+};
+
+static int sis190_isa_bridge_probe(struct pci_device *pdev __unused)
+{
+ return 0;
+}
+
+static void sis190_isa_bridge_remove(struct pci_device *pdev __unused)
+{
+ return;
+}
+
+struct pci_driver sis190_isa_bridge_driver __pci_driver = {
+ .ids = sis190_isa_bridge_tbl,
+ .id_count = (sizeof(sis190_isa_bridge_tbl) /
+ sizeof(sis190_isa_bridge_tbl[0])),
+ .probe = sis190_isa_bridge_probe,
+ .remove = sis190_isa_bridge_remove,
+};
+
+/******************************************************************************
+ *********************************** </HACK> **********************************
+ ******************************************************************************/
+
+static const u32 sis190_intr_mask =
+ RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt | LinkChange;
+
+/*
+ * Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
+ * The chips use a 64 element hash table based on the Ethernet CRC.
+ */
+static const int multicast_filter_limit = 32;
+
+static void __mdio_cmd(void *ioaddr, u32 ctl)
+{
+ unsigned int i;
+
+ SIS_W32(GMIIControl, ctl);
+
+ mdelay(1);
+
+ for (i = 0; i < 100; i++) {
+ if (!(SIS_R32(GMIIControl) & EhnMIInotDone))
+ break;
+ mdelay(1);
+ }
+
+ if (i > 99)
+ DBG("sis190: PHY command timed out !\n");
+}
+
+static void mdio_write(void *ioaddr, int phy_id, int reg, int val)
+{
+ __mdio_cmd(ioaddr, EhnMIIreq | EhnMIIwrite |
+ (((u32) reg) << EhnMIIregShift) | (phy_id << EhnMIIpmdShift) |
+ (((u32) val) << EhnMIIdataShift));
+}
+
+static int mdio_read(void *ioaddr, int phy_id, int reg)
+{
+ __mdio_cmd(ioaddr, EhnMIIreq | EhnMIIread |
+ (((u32) reg) << EhnMIIregShift) | (phy_id << EhnMIIpmdShift));
+
+ return (u16) (SIS_R32(GMIIControl) >> EhnMIIdataShift);
+}
+
+static void __mdio_write(struct net_device *dev, int phy_id, int reg, int val)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ mdio_write(tp->mmio_addr, phy_id, reg, val);
+}
+
+static int __mdio_read(struct net_device *dev, int phy_id, int reg)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return mdio_read(tp->mmio_addr, phy_id, reg);
+}
+
+static u16 mdio_read_latched(void *ioaddr, int phy_id, int reg)
+{
+ mdio_read(ioaddr, phy_id, reg);
+ return mdio_read(ioaddr, phy_id, reg);
+}
+
+static u16 sis190_read_eeprom(void *ioaddr, u32 reg)
+{
+ u16 data = 0xffff;
+ unsigned int i;
+
+ if (!(SIS_R32(ROMControl) & 0x0002))
+ return 0;
+
+ SIS_W32(ROMInterface, EEREQ | EEROP | (reg << 10));
+
+ for (i = 0; i < 200; i++) {
+ if (!(SIS_R32(ROMInterface) & EEREQ)) {
+ data = (SIS_R32(ROMInterface) & 0xffff0000) >> 16;
+ break;
+ }
+ mdelay(1);
+ }
+
+ return data;
+}
+
+static void sis190_irq_mask_and_ack(void *ioaddr)
+{
+ SIS_W32(IntrMask, 0x00);
+ SIS_W32(IntrStatus, 0xffffffff);
+ SIS_PCI_COMMIT();
+}
+
+static void sis190_asic_down(void *ioaddr)
+{
+ /* Stop the chip's Tx and Rx DMA processes. */
+
+ SIS_W32(TxControl, 0x1a00);
+ SIS_W32(RxControl, 0x1a00);
+
+ sis190_irq_mask_and_ack(ioaddr);
+}
+
+static inline void sis190_mark_as_last_descriptor(struct RxDesc *desc)
+{
+ desc->size |= cpu_to_le32(RingEnd);
+}
+
+static inline void sis190_give_to_asic(struct RxDesc *desc)
+{
+ u32 eor = le32_to_cpu(desc->size) & RingEnd;
+
+ desc->PSize = 0x0;
+ desc->size = cpu_to_le32((RX_BUF_SIZE & RX_BUF_MASK) | eor);
+ wmb();
+ desc->status = cpu_to_le32(OWNbit | INTbit);
+}
+
+static inline void sis190_map_to_asic(struct RxDesc *desc, u32 mapping)
+{
+ desc->addr = cpu_to_le32(mapping);
+ sis190_give_to_asic(desc);
+}
+
+static inline void sis190_make_unusable_by_asic(struct RxDesc *desc)
+{
+ desc->PSize = 0x0;
+ desc->addr = cpu_to_le32(0xdeadbeef);
+ desc->size &= cpu_to_le32(RingEnd);
+ wmb();
+ desc->status = 0x0;
+}
+
+static struct io_buffer *sis190_alloc_rx_iob(struct RxDesc *desc)
+{
+ struct io_buffer *iob;
+
+ iob = alloc_iob(RX_BUF_SIZE);
+ if (iob) {
+ u32 mapping;
+
+ mapping = virt_to_bus(iob->data);
+ sis190_map_to_asic(desc, mapping);
+ } else {
+ DBG("sis190: alloc_iob failed\n");
+ sis190_make_unusable_by_asic(desc);
+ }
+
+ return iob;
+}
+
+static u32 sis190_rx_fill(struct sis190_private *tp, u32 start, u32 end)
+{
+ u32 cur;
+
+ for (cur = start; cur < end; cur++) {
+ unsigned int i = cur % NUM_RX_DESC;
+
+ if (tp->Rx_iobuf[i])
+ continue;
+
+ tp->Rx_iobuf[i] = sis190_alloc_rx_iob(tp->RxDescRing + i);
+
+ if (!tp->Rx_iobuf[i])
+ break;
+ }
+ return cur - start;
+}
+
+static inline int sis190_rx_pkt_err(u32 status)
+{
+#define ErrMask (OVRUN | SHORT | LIMIT | MIIER | NIBON | COLON | ABORT)
+
+ if ((status & CRCOK) && !(status & ErrMask))
+ return 0;
+
+ return -1;
+}
+
+static int sis190_process_rx(struct sis190_private *tp)
+{
+ u32 rx_left, cur_rx = tp->cur_rx;
+ u32 delta, count;
+
+ rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
+
+ for (; rx_left > 0; rx_left--, cur_rx++) {
+ unsigned int entry = cur_rx % NUM_RX_DESC;
+ struct RxDesc *desc = tp->RxDescRing + entry;
+ u32 status;
+
+ if (le32_to_cpu(desc->status) & OWNbit)
+ break;
+
+ status = le32_to_cpu(desc->PSize);
+
+ if (sis190_rx_pkt_err(status) < 0) {
+ sis190_give_to_asic(desc);
+ } else {
+ struct io_buffer *iob = tp->Rx_iobuf[entry];
+ unsigned int pkt_size = (status & RxSizeMask) - 4;
+
+ if (pkt_size > RX_BUF_SIZE) {
+ DBG("sis190: (frag) status = %08x.\n", status);
+ sis190_give_to_asic(desc);
+ continue;
+ }
+
+ sis190_make_unusable_by_asic(desc);
+
+ iob_put(iob, pkt_size);
+
+ DBG2("sis190: received packet. len: %d\n", pkt_size);
+ netdev_rx(tp->dev, iob);
+ DBGIO_HD(iob->data, 60);
+ tp->Rx_iobuf[entry] = NULL;
+ }
+ }
+ count = cur_rx - tp->cur_rx;
+ tp->cur_rx = cur_rx;
+
+ delta = sis190_rx_fill(tp, tp->dirty_rx, tp->cur_rx);
+ if (!delta && count)
+ DBG("sis190: no Rx buffer allocated.\n");
+ tp->dirty_rx += delta;
+
+ if (((tp->dirty_rx + NUM_RX_DESC) == tp->cur_rx))
+ DBG("sis190: Rx buffers exhausted.\n");
+
+ return count;
+}
+
+static inline int sis190_tx_pkt_err(u32 status)
+{
+#define TxErrMask (WND | TABRT | FIFO | LINK)
+
+ if (!(status & TxErrMask))
+ return 0;
+
+ return -1;
+}
+
+static void sis190_process_tx(struct sis190_private *tp)
+{
+ u32 pending, dirty_tx = tp->dirty_tx;
+
+ pending = tp->cur_tx - dirty_tx;
+
+ for (; pending; pending--, dirty_tx++) {
+ unsigned int entry = dirty_tx % NUM_TX_DESC;
+ struct TxDesc *txd = tp->TxDescRing + entry;
+ u32 status = le32_to_cpu(txd->status);
+ struct io_buffer *iob;
+
+ if (status & OWNbit)
+ break;
+
+ iob = tp->Tx_iobuf[entry];
+
+ if (!iob)
+ break;
+
+ if (sis190_tx_pkt_err(status) == 0) {
+ DBG2("sis190: Transmitted packet: %#08x\n", status);
+ netdev_tx_complete(tp->dev, iob);
+ } else {
+ DBG("sis190: Transmit error: %#08x\n", status);
+ netdev_tx_complete_err(tp->dev, iob, -EINVAL);
+ }
+
+ tp->Tx_iobuf[entry] = NULL;
+ }
+
+ if (tp->dirty_tx != dirty_tx)
+ tp->dirty_tx = dirty_tx;
+}
+
+/*
+ * The interrupt handler does all of the Rx thread work and cleans up after
+ * the Tx thread.
+ */
+static void sis190_poll(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+ u32 status;
+
+ status = SIS_R32(IntrStatus);
+
+ if ((status == 0xffffffff) || !status)
+ return;
+
+ SIS_W32(IntrStatus, status);
+
+ /* sis190_phy_task() needs to be called in event of a LinkChange and
+ * after auto-negotiation is finished. Finishing auto-neg won't generate
+ * any indication, hence we call it every time if the link is bad. */
+ if ((status & LinkChange) || !netdev_link_ok(dev))
+ sis190_phy_task(tp);
+
+ if (status & RxQInt)
+ sis190_process_rx(tp);
+
+ if (status & TxQ0Int)
+ sis190_process_tx(tp);
+}
+
+static inline void sis190_init_ring_indexes(struct sis190_private *tp)
+{
+ tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
+}
+
+static int sis190_init_ring(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ sis190_init_ring_indexes(tp);
+
+ memset(tp->Tx_iobuf, 0, NUM_TX_DESC * sizeof(struct io_buffer *));
+ memset(tp->Rx_iobuf, 0, NUM_RX_DESC * sizeof(struct io_buffer *));
+
+ if (sis190_rx_fill(tp, 0, NUM_RX_DESC) != NUM_RX_DESC)
+ goto err;
+
+ sis190_mark_as_last_descriptor(tp->RxDescRing + NUM_RX_DESC - 1);
+
+ return 0;
+
+err:
+ sis190_free(dev);
+ return -ENOMEM;
+}
+
+static void sis190_set_rx_mode(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+ u32 mc_filter[2]; /* Multicast hash filter */
+ u16 rx_mode;
+
+ rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast;
+ mc_filter[1] = mc_filter[0] = 0xffffffff;
+
+ SIS_W16(RxMacControl, rx_mode | 0x2);
+ SIS_W32(RxHashTable, mc_filter[0]);
+ SIS_W32(RxHashTable + 4, mc_filter[1]);
+
+}
+
+static void sis190_soft_reset(void *ioaddr)
+{
+ SIS_W32(IntrControl, 0x8000);
+ SIS_PCI_COMMIT();
+ SIS_W32(IntrControl, 0x0);
+ sis190_asic_down(ioaddr);
+}
+
+static void sis190_hw_start(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+
+ sis190_soft_reset(ioaddr);
+
+ SIS_W32(TxDescStartAddr, tp->tx_dma);
+ SIS_W32(RxDescStartAddr, tp->rx_dma);
+
+ SIS_W32(IntrStatus, 0xffffffff);
+ SIS_W32(IntrMask, 0x0);
+ SIS_W32(GMIIControl, 0x0);
+ SIS_W32(TxMacControl, 0x60);
+ SIS_W16(RxMacControl, 0x02);
+ SIS_W32(RxHashTable, 0x0);
+ SIS_W32(0x6c, 0x0);
+ SIS_W32(RxWolCtrl, 0x0);
+ SIS_W32(RxWolData, 0x0);
+
+ SIS_PCI_COMMIT();
+
+ sis190_set_rx_mode(dev);
+
+ SIS_W32(TxControl, 0x1a00 | CmdTxEnb);
+ SIS_W32(RxControl, 0x1a1d);
+}
+
+static void sis190_phy_task(struct sis190_private *tp)
+{
+ struct net_device *dev = tp->dev;
+ void *ioaddr = tp->mmio_addr;
+ int phy_id = tp->mii_if.phy_id;
+ int cnt = 0;
+ u16 val;
+
+ val = mdio_read(ioaddr, phy_id, MII_BMCR);
+
+ /* 100ms timeout is completely arbitrary. I have no datasheet to
+ * check whether that's a sensible value or not.
+ */
+ while ((val & BMCR_RESET) && (cnt < 100)) {
+ val = mdio_read(ioaddr, phy_id, MII_BMCR);
+ mdelay(1);
+ cnt++;
+ }
+
+ if (cnt > 99) {
+ DBG("sis190: BMCR_RESET timeout\n");
+ return;
+ }
+
+ if (!(mdio_read_latched(ioaddr, phy_id, MII_BMSR) &
+ BMSR_ANEGCOMPLETE)) {
+ DBG("sis190: auto-negotiating...\n");
+ netdev_link_down(dev);
+ } else {
+ /* Rejoice ! */
+ struct {
+ int val;
+ u32 ctl;
+ const char *msg;
+ } reg31[] = {
+ { LPA_1000FULL, 0x07000c00 | 0x00001000,
+ "1000 Mbps Full Duplex" },
+ { LPA_1000HALF, 0x07000c00,
+ "1000 Mbps Half Duplex" },
+ { LPA_100FULL, 0x04000800 | 0x00001000,
+ "100 Mbps Full Duplex" },
+ { LPA_100HALF, 0x04000800,
+ "100 Mbps Half Duplex" },
+ { LPA_10FULL, 0x04000400 | 0x00001000,
+ "10 Mbps Full Duplex" },
+ { LPA_10HALF, 0x04000400,
+ "10 Mbps Half Duplex" },
+ { 0, 0x04000400, "unknown" }
+ }, *p = NULL;
+ u16 adv, autoexp, gigadv, gigrec;
+
+ val = mdio_read(ioaddr, phy_id, 0x1f);
+
+ val = mdio_read(ioaddr, phy_id, MII_LPA);
+ adv = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
+
+ autoexp = mdio_read(ioaddr, phy_id, MII_EXPANSION);
+
+ if (val & LPA_NPAGE && autoexp & EXPANSION_NWAY) {
+ /* check for gigabit speed */
+ gigadv = mdio_read(ioaddr, phy_id, MII_CTRL1000);
+ gigrec = mdio_read(ioaddr, phy_id, MII_STAT1000);
+ val = (gigadv & (gigrec >> 2));
+ if (val & ADVERTISE_1000FULL)
+ p = reg31;
+ else if (val & ADVERTISE_1000HALF)
+ p = reg31 + 1;
+ }
+
+ if (!p) {
+ val &= adv;
+
+ for (p = reg31; p->val; p++) {
+ if ((val & p->val) == p->val)
+ break;
+ }
+ }
+
+ p->ctl |= SIS_R32(StationControl) & ~0x0f001c00;
+
+ if ((tp->features & F_HAS_RGMII) &&
+ (tp->features & F_PHY_BCM5461)) {
+ // Set Tx Delay in RGMII mode.
+ mdio_write(ioaddr, phy_id, 0x18, 0xf1c7);
+ udelay(200);
+ mdio_write(ioaddr, phy_id, 0x1c, 0x8c00);
+ p->ctl |= 0x03000000;
+ }
+
+ SIS_W32(StationControl, p->ctl);
+
+ if (tp->features & F_HAS_RGMII) {
+ SIS_W32(RGDelay, 0x0441);
+ SIS_W32(RGDelay, 0x0440);
+ }
+
+ DBG("sis190: link on %s mode.\n", p->msg);
+ netdev_link_up(dev);
+ }
+}
+
+static int sis190_open(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ int rc;
+
+ /* Allocate TX ring */
+ tp->TxDescRing = malloc_dma(TX_RING_BYTES, RING_ALIGNMENT);
+ if (!tp->TxDescRing) {
+ DBG("sis190: TX ring allocation failed\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+ tp->tx_dma = cpu_to_le32(virt_to_bus(tp->TxDescRing));
+
+ /* Allocate RX ring */
+ tp->RxDescRing = malloc_dma(RX_RING_BYTES, RING_ALIGNMENT);
+ if (!tp->RxDescRing) {
+ DBG("sis190: RX ring allocation failed\n");
+ rc = -ENOMEM;
+ goto error;
+ }
+ tp->rx_dma = cpu_to_le32(virt_to_bus(tp->RxDescRing));
+
+ rc = sis190_init_ring(dev);
+ if (rc < 0)
+ goto error;
+
+ /* init rx filter, also program MAC address to card */
+ sis190_init_rxfilter(dev);
+
+ sis190_hw_start(dev);
+out:
+ return rc;
+
+error:
+ sis190_free(dev);
+ goto out;
+}
+
+static void sis190_down(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+
+ do {
+ sis190_asic_down(ioaddr);
+ } while (SIS_R32(IntrMask));
+}
+
+static void sis190_free(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ int i;
+
+ free_dma(tp->TxDescRing, TX_RING_BYTES);
+ free_dma(tp->RxDescRing, RX_RING_BYTES);
+
+ tp->TxDescRing = NULL;
+ tp->RxDescRing = NULL;
+
+ tp->tx_dma = 0;
+ tp->rx_dma = 0;
+
+ tp->cur_tx = tp->dirty_tx = 0;
+ tp->cur_rx = tp->dirty_rx = 0;
+
+ for (i = 0; i < NUM_RX_DESC; i++) {
+ free_iob(tp->Rx_iobuf[i]);
+ tp->Rx_iobuf[i] = NULL;
+ }
+
+ /* tx io_buffers aren't owned by the driver, so don't free them */
+ for(i = 0; i < NUM_TX_DESC; i++)
+ tp->Tx_iobuf[i] = NULL;
+}
+
+static void sis190_close(struct net_device *dev)
+{
+ sis190_down(dev);
+ sis190_free(dev);
+}
+
+static int sis190_transmit(struct net_device *dev, struct io_buffer *iob)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+ u32 len, entry;
+ struct TxDesc *desc;
+
+ len = iob_len(iob);
+ if (len < ETH_ZLEN) {
+ iob_pad(iob, ETH_ZLEN);
+ len = ETH_ZLEN;
+ }
+
+ entry = tp->cur_tx % NUM_TX_DESC;
+ desc = tp->TxDescRing + entry;
+
+ if (le32_to_cpu(desc->status) & OWNbit) {
+ DBG("sis190: Tx Ring full\n");
+ return -EINVAL;
+ }
+
+ tp->Tx_iobuf[entry] = iob;
+
+ desc->PSize = cpu_to_le32(len);
+ desc->addr = cpu_to_le32(virt_to_bus(iob->data));
+
+ desc->size = cpu_to_le32(len);
+ if (entry == (NUM_TX_DESC - 1))
+ desc->size |= cpu_to_le32(RingEnd);
+
+ wmb();
+
+ desc->status = cpu_to_le32(OWNbit | INTbit | DEFbit | CRCbit | PADbit);
+
+ tp->cur_tx++;
+
+ SIS_W32(TxControl, 0x1a00 | CmdReset | CmdTxEnb);
+
+ return 0;
+}
+
+static void sis190_free_phy(struct list_head *first_phy)
+{
+ struct sis190_phy *cur, *next;
+
+ list_for_each_entry_safe(cur, next, first_phy, list) {
+ free(cur);
+ }
+}
+
+/**
+ * sis190_default_phy - Select default PHY for sis190 mac.
+ * @dev: the net device to probe for
+ *
+ * Select first detected PHY with link as default.
+ * If no one is link on, select PHY whose types is HOME as default.
+ * If HOME doesn't exist, select LAN.
+ */
+static u16 sis190_default_phy(struct sis190_private *tp)
+{
+ struct sis190_phy *phy, *phy_home, *phy_default, *phy_lan;
+ struct mii_if_info *mii_if = &tp->mii_if;
+ void *ioaddr = tp->mmio_addr;
+ u16 status;
+
+ phy_home = phy_default = phy_lan = NULL;
+
+ list_for_each_entry(phy, &tp->first_phy, list) {
+ status = mdio_read_latched(ioaddr, phy->phy_id, MII_BMSR);
+
+ // Link ON & Not select default PHY & not ghost PHY.
+ if ((status & BMSR_LSTATUS) &&
+ !phy_default &&
+ (phy->type != UNKNOWN)) {
+ phy_default = phy;
+ } else {
+ status = mdio_read(ioaddr, phy->phy_id, MII_BMCR);
+ mdio_write(ioaddr, phy->phy_id, MII_BMCR,
+ status | BMCR_ANENABLE | BMCR_ISOLATE);
+ if (phy->type == HOME)
+ phy_home = phy;
+ else if (phy->type == LAN)
+ phy_lan = phy;
+ }
+ }
+
+ if (!phy_default) {
+ if (phy_home)
+ phy_default = phy_home;
+ else if (phy_lan)
+ phy_default = phy_lan;
+ else
+ phy_default = list_entry(&tp->first_phy,
+ struct sis190_phy, list);
+ }
+
+ if (mii_if->phy_id != phy_default->phy_id) {
+ mii_if->phy_id = phy_default->phy_id;
+ DBG("sis190: Using transceiver at address %d as default.\n",
+ mii_if->phy_id);
+ }
+
+ status = mdio_read(ioaddr, mii_if->phy_id, MII_BMCR);
+ status &= (~BMCR_ISOLATE);
+
+ mdio_write(ioaddr, mii_if->phy_id, MII_BMCR, status);
+ status = mdio_read_latched(ioaddr, mii_if->phy_id, MII_BMSR);
+
+ return status;
+}
+
+static void sis190_init_phy(struct sis190_private *tp,
+ struct sis190_phy *phy, unsigned int phy_id,
+ u16 mii_status)
+{
+ void *ioaddr = tp->mmio_addr;
+ struct mii_chip_info *p;
+
+ INIT_LIST_HEAD(&phy->list);
+ phy->status = mii_status;
+ phy->phy_id = phy_id;
+
+ phy->id[0] = mdio_read(ioaddr, phy_id, MII_PHYSID1);
+ phy->id[1] = mdio_read(ioaddr, phy_id, MII_PHYSID2);
+
+ for (p = mii_chip_table; p->type; p++) {
+ if ((p->id[0] == phy->id[0]) &&
+ (p->id[1] == (phy->id[1] & 0xfff0))) {
+ break;
+ }
+ }
+
+ if (p->id[1]) {
+ phy->type = (p->type == MIX) ?
+ ((mii_status & (BMSR_100FULL | BMSR_100HALF)) ?
+ LAN : HOME) : p->type;
+ tp->features |= p->feature;
+
+ DBG("sis190: %s transceiver at address %d.\n", p->name, phy_id);
+ } else {
+ phy->type = UNKNOWN;
+
+ DBG("sis190: unknown PHY 0x%x:0x%x transceiver at address %d\n",
+ phy->id[0], (phy->id[1] & 0xfff0), phy_id);
+ }
+}
+
+static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
+{
+ if (tp->features & F_PHY_88E1111) {
+ void *ioaddr = tp->mmio_addr;
+ int phy_id = tp->mii_if.phy_id;
+ u16 reg[2][2] = {
+ { 0x808b, 0x0ce1 },
+ { 0x808f, 0x0c60 }
+ }, *p;
+
+ p = (tp->features & F_HAS_RGMII) ? reg[0] : reg[1];
+
+ mdio_write(ioaddr, phy_id, 0x1b, p[0]);
+ udelay(200);
+ mdio_write(ioaddr, phy_id, 0x14, p[1]);
+ udelay(200);
+ }
+}
+
+/**
+ * sis190_mii_probe - Probe MII PHY for sis190
+ * @dev: the net device to probe for
+ *
+ * Search for total of 32 possible mii phy addresses.
+ * Identify and set current phy if found one,
+ * return error if it failed to found.
+ */
+static int sis190_mii_probe(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct mii_if_info *mii_if = &tp->mii_if;
+ void *ioaddr = tp->mmio_addr;
+ int phy_id;
+ int rc = 0;
+
+ INIT_LIST_HEAD(&tp->first_phy);
+
+ for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
+ struct sis190_phy *phy;
+ u16 status;
+
+ status = mdio_read_latched(ioaddr, phy_id, MII_BMSR);
+
+ // Try next mii if the current one is not accessible.
+ if (status == 0xffff || status == 0x0000)
+ continue;
+
+ phy = zalloc(sizeof(*phy));
+ if (!phy) {
+ sis190_free_phy(&tp->first_phy);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ DBG("sis190: found PHY\n");
+
+ sis190_init_phy(tp, phy, phy_id, status);
+
+ list_add(&tp->first_phy, &phy->list);
+ }
+
+ if (list_empty(&tp->first_phy)) {
+ DBG("sis190: No MII transceivers found!\n");
+ rc = -EIO;
+ goto out;
+ }
+
+ /* Select default PHY for mac */
+ sis190_default_phy(tp);
+
+ sis190_mii_probe_88e1111_fixup(tp);
+
+ mii_if->dev = dev;
+ mii_if->mdio_read = __mdio_read;
+ mii_if->mdio_write = __mdio_write;
+ mii_if->phy_id_mask = PHY_ID_ANY;
+ mii_if->reg_num_mask = MII_REG_ANY;
+out:
+ return rc;
+}
+
+static void sis190_mii_remove(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ sis190_free_phy(&tp->first_phy);
+}
+
+static int sis190_init_board(struct pci_device *pdev, struct net_device **netdev)
+{
+ struct sis190_private *tp;
+ struct net_device *dev;
+ void *ioaddr;
+ int rc;
+
+ dev = alloc_etherdev(sizeof(*tp));
+ if (!dev) {
+ DBG("sis190: unable to alloc new etherdev\n");
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ dev->dev = &pdev->dev;
+
+ tp = netdev_priv(dev);
+ memset(tp, 0, sizeof(*tp));
+
+ tp->dev = dev;
+
+ adjust_pci_device(pdev);
+
+ ioaddr = ioremap(pdev->membase, SIS190_REGS_SIZE);
+ if (!ioaddr) {
+ DBG("sis190: cannot remap MMIO, aborting\n");
+ rc = -EIO;
+ goto err;
+ }
+
+ tp->pci_device = pdev;
+ tp->mmio_addr = ioaddr;
+
+ sis190_irq_mask_and_ack(ioaddr);
+
+ sis190_soft_reset(ioaddr);
+
+ *netdev = dev;
+
+ return 0;
+
+err:
+ return rc;
+}
+
+static void sis190_set_rgmii(struct sis190_private *tp, u8 reg)
+{
+ tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0;
+}
+
+static int sis190_get_mac_addr_from_eeprom(struct pci_device *pdev __unused,
+ struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+ u16 sig;
+ int i;
+
+ DBG("sis190: Read MAC address from EEPROM\n");
+
+ /* Check to see if there is a sane EEPROM */
+ sig = (u16) sis190_read_eeprom(ioaddr, EEPROMSignature);
+
+ if ((sig == 0xffff) || (sig == 0x0000)) {
+ DBG("sis190: Error EEPROM read.\n");
+ return -EIO;
+ }
+
+ /* Get MAC address from EEPROM */
+ for (i = 0; i < ETH_ALEN / 2; i++) {
+ u16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i);
+
+ ((u16 *)dev->hw_addr)[i] = cpu_to_le16(w);
+ }
+
+ sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo));
+
+ return 0;
+}
+
+/**
+ * sis190_get_mac_addr_from_apc - Get MAC address for SiS96x model
+ * @pdev: PCI device
+ * @dev: network device to get address for
+ *
+ * SiS96x model, use APC CMOS RAM to store MAC address.
+ * APC CMOS RAM is accessed through ISA bridge.
+ * MAC address is read into @net_dev->dev_addr.
+ */
+static int sis190_get_mac_addr_from_apc(struct pci_device *pdev,
+ struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct pci_device *isa_bridge = NULL;
+ struct device *d;
+ u8 reg, tmp8;
+ unsigned int i;
+
+ DBG("sis190: Read MAC address from APC.\n");
+
+ list_for_each_entry(d, &(pdev->dev.siblings), siblings) {
+ unsigned int i;
+ isa_bridge = container_of(d, struct pci_device, dev);
+ for(i = 0; i < sis190_isa_bridge_driver.id_count; i++) {
+ if(isa_bridge->vendor ==
+ sis190_isa_bridge_driver.ids[i].vendor
+ && isa_bridge->device ==
+ sis190_isa_bridge_driver.ids[i].device) {
+ DBG("sis190: ISA bridge found\n");
+ break;
+ } else {
+ isa_bridge = NULL;
+ }
+ }
+ if(isa_bridge)
+ break;
+ }
+
+ if (!isa_bridge) {
+ DBG("sis190: Can not find ISA bridge.\n");
+ return -EIO;
+ }
+
+ /* Enable port 78h & 79h to access APC Registers. */
+ pci_read_config_byte(isa_bridge, 0x48, &tmp8);
+ reg = (tmp8 & ~0x02);
+ pci_write_config_byte(isa_bridge, 0x48, reg);
+ udelay(50);
+ pci_read_config_byte(isa_bridge, 0x48, &reg);
+
+ for (i = 0; i < ETH_ALEN; i++) {
+ outb(0x9 + i, 0x78);
+ dev->hw_addr[i] = inb(0x79);
+ }
+
+ outb(0x12, 0x78);
+ reg = inb(0x79);
+
+ sis190_set_rgmii(tp, reg);
+
+ /* Restore the value to ISA Bridge */
+ pci_write_config_byte(isa_bridge, 0x48, tmp8);
+
+ return 0;
+}
+
+/**
+ * sis190_init_rxfilter - Initialize the Rx filter
+ * @dev: network device to initialize
+ *
+ * Set receive filter address to our MAC address
+ * and enable packet filtering.
+ */
+static inline void sis190_init_rxfilter(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+ u16 ctl;
+ int i;
+
+ ctl = SIS_R16(RxMacControl);
+ /*
+ * Disable packet filtering before setting filter.
+ * Note: SiS's driver writes 32 bits but RxMacControl is 16 bits
+ * only and followed by RxMacAddr (6 bytes). Strange. -- FR
+ */
+ SIS_W16(RxMacControl, ctl & ~0x0f00);
+
+ for (i = 0; i < ETH_ALEN; i++)
+ SIS_W8(RxMacAddr + i, dev->ll_addr[i]);
+
+ SIS_W16(RxMacControl, ctl);
+ SIS_PCI_COMMIT();
+}
+
+static int sis190_get_mac_addr(struct pci_device *pdev,
+ struct net_device *dev)
+{
+ int rc;
+
+ rc = sis190_get_mac_addr_from_eeprom(pdev, dev);
+ if (rc < 0) {
+ u8 reg;
+
+ pci_read_config_byte(pdev, 0x73, &reg);
+
+ if (reg & 0x00000001)
+ rc = sis190_get_mac_addr_from_apc(pdev, dev);
+ }
+ return rc;
+}
+
+static void sis190_set_speed_auto(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+ int phy_id = tp->mii_if.phy_id;
+ int val;
+
+ DBG("sis190: Enabling Auto-negotiation.\n");
+
+ val = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
+
+ // Enable 10/100 Full/Half Mode, leave MII_ADVERTISE bit4:0
+ // unchanged.
+ mdio_write(ioaddr, phy_id, MII_ADVERTISE, (val & ADVERTISE_SLCT) |
+ ADVERTISE_100FULL | ADVERTISE_10FULL |
+ ADVERTISE_100HALF | ADVERTISE_10HALF);
+
+ // Enable 1000 Full Mode.
+ mdio_write(ioaddr, phy_id, MII_CTRL1000, ADVERTISE_1000FULL);
+
+ // Enable auto-negotiation and restart auto-negotiation.
+ mdio_write(ioaddr, phy_id, MII_BMCR,
+ BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET);
+}
+
+static void sis190_irq(struct net_device *dev, int enable)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+
+ SIS_W32(IntrStatus, 0xffffffff);
+
+ if (enable == 0)
+ SIS_W32(IntrMask, 0x00);
+ else
+ SIS_W32(IntrMask, sis190_intr_mask);
+
+ SIS_PCI_COMMIT();
+}
+
+static struct net_device_operations sis190_netdev_ops = {
+ .open = sis190_open,
+ .close = sis190_close,
+ .poll = sis190_poll,
+ .transmit = sis190_transmit,
+ .irq = sis190_irq,
+};
+
+static int sis190_probe(struct pci_device *pdev)
+{
+ struct sis190_private *tp;
+ struct net_device *dev;
+ int rc;
+
+ rc = sis190_init_board(pdev, &dev);
+ if (rc < 0)
+ goto out;
+ netdev_init(dev, &sis190_netdev_ops);
+
+ pci_set_drvdata(pdev, dev);
+
+ tp = netdev_priv(dev);
+
+ rc = sis190_get_mac_addr(pdev, dev);
+ if (rc < 0)
+ goto err;
+
+ rc = sis190_mii_probe(dev);
+ if (rc < 0)
+ goto err;
+
+ rc = register_netdev(dev);
+ if (rc < 0)
+ goto err;
+
+ sis190_set_speed_auto(dev);
+ sis190_phy_task(tp);
+
+out:
+ return rc;
+
+err:
+ sis190_mii_remove(dev);
+ iounmap(tp->mmio_addr);
+ goto out;
+}
+
+static void sis190_remove(struct pci_device *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct sis190_private *tp = dev->priv;
+ void *ioaddr = tp->mmio_addr;
+
+ sis190_mii_remove(dev);
+
+ /* shutdown chip, disable interrupts, etc */
+ sis190_soft_reset(ioaddr);
+
+ iounmap(tp->mmio_addr);
+
+ unregister_netdev(dev);
+ netdev_nullify(dev);
+ netdev_put(dev);
+}
+
+struct pci_driver sis190_pci_driver __pci_driver = {
+ .ids = sis190_pci_tbl,
+ .id_count = (sizeof(sis190_pci_tbl) / sizeof(sis190_pci_tbl[0])),
+ .probe = sis190_probe,
+ .remove = sis190_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/sis190.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/sis190.h
new file mode 100644
index 00000000..fc6cb4b6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/sis190.h
@@ -0,0 +1,311 @@
+#ifndef __SIS190_H__
+#define __SIS190_H__
+
+FILE_LICENCE ( GPL_ANY );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <mii.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/io.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/pci.h>
+#include <ipxe/timer.h>
+
+#define PCI_VENDOR_ID_SI 0x1039
+
+#define PHY_MAX_ADDR 32
+#define PHY_ID_ANY 0x1f
+#define MII_REG_ANY 0x1f
+
+#define DRV_VERSION "1.3"
+#define DRV_NAME "sis190"
+#define SIS190_DRIVER_NAME DRV_NAME " Gigabit Ethernet driver " DRV_VERSION
+#define PFX DRV_NAME ": "
+
+#define sis190_rx_quota(count, quota) count
+
+#define NUM_TX_DESC 8 /* [8..1024] */
+#define NUM_RX_DESC 8 /* [8..8192] */
+#define TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
+#define RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
+#define RX_BUF_SIZE 1536
+#define RX_BUF_MASK 0xfff8
+
+#define RING_ALIGNMENT 256
+
+#define SIS190_REGS_SIZE 0x80
+
+/* Enhanced PHY access register bit definitions */
+#define EhnMIIread 0x0000
+#define EhnMIIwrite 0x0020
+#define EhnMIIdataShift 16
+#define EhnMIIpmdShift 6 /* 7016 only */
+#define EhnMIIregShift 11
+#define EhnMIIreq 0x0010
+#define EhnMIInotDone 0x0010
+
+/* Write/read MMIO register */
+#define SIS_W8(reg, val) writeb ((val), ioaddr + (reg))
+#define SIS_W16(reg, val) writew ((val), ioaddr + (reg))
+#define SIS_W32(reg, val) writel ((val), ioaddr + (reg))
+#define SIS_R8(reg) readb (ioaddr + (reg))
+#define SIS_R16(reg) readw (ioaddr + (reg))
+#define SIS_R32(reg) readl (ioaddr + (reg))
+
+#define SIS_PCI_COMMIT() SIS_R32(IntrControl)
+
+enum sis190_registers {
+ TxControl = 0x00,
+ TxDescStartAddr = 0x04,
+ rsv0 = 0x08, // reserved
+ TxSts = 0x0c, // unused (Control/Status)
+ RxControl = 0x10,
+ RxDescStartAddr = 0x14,
+ rsv1 = 0x18, // reserved
+ RxSts = 0x1c, // unused
+ IntrStatus = 0x20,
+ IntrMask = 0x24,
+ IntrControl = 0x28,
+ IntrTimer = 0x2c, // unused (Interupt Timer)
+ PMControl = 0x30, // unused (Power Mgmt Control/Status)
+ rsv2 = 0x34, // reserved
+ ROMControl = 0x38,
+ ROMInterface = 0x3c,
+ StationControl = 0x40,
+ GMIIControl = 0x44,
+ GIoCR = 0x48, // unused (GMAC IO Compensation)
+ GIoCtrl = 0x4c, // unused (GMAC IO Control)
+ TxMacControl = 0x50,
+ TxLimit = 0x54, // unused (Tx MAC Timer/TryLimit)
+ RGDelay = 0x58, // unused (RGMII Tx Internal Delay)
+ rsv3 = 0x5c, // reserved
+ RxMacControl = 0x60,
+ RxMacAddr = 0x62,
+ RxHashTable = 0x68,
+ // Undocumented = 0x6c,
+ RxWolCtrl = 0x70,
+ RxWolData = 0x74, // unused (Rx WOL Data Access)
+ RxMPSControl = 0x78, // unused (Rx MPS Control)
+ rsv4 = 0x7c, // reserved
+};
+
+enum sis190_register_content {
+ /* IntrStatus */
+ SoftInt = 0x40000000, // unused
+ Timeup = 0x20000000, // unused
+ PauseFrame = 0x00080000, // unused
+ MagicPacket = 0x00040000, // unused
+ WakeupFrame = 0x00020000, // unused
+ LinkChange = 0x00010000,
+ RxQEmpty = 0x00000080,
+ RxQInt = 0x00000040,
+ TxQ1Empty = 0x00000020, // unused
+ TxQ1Int = 0x00000010,
+ TxQ0Empty = 0x00000008, // unused
+ TxQ0Int = 0x00000004,
+ RxHalt = 0x00000002,
+ TxHalt = 0x00000001,
+
+ /* {Rx/Tx}CmdBits */
+ CmdReset = 0x10,
+ CmdRxEnb = 0x08, // unused
+ CmdTxEnb = 0x01,
+ RxBufEmpty = 0x01, // unused
+
+ /* Cfg9346Bits */
+ Cfg9346_Lock = 0x00, // unused
+ Cfg9346_Unlock = 0xc0, // unused
+
+ /* RxMacControl */
+ AcceptErr = 0x20, // unused
+ AcceptRunt = 0x10, // unused
+ AcceptBroadcast = 0x0800,
+ AcceptMulticast = 0x0400,
+ AcceptMyPhys = 0x0200,
+ AcceptAllPhys = 0x0100,
+
+ /* RxConfigBits */
+ RxCfgFIFOShift = 13,
+ RxCfgDMAShift = 8, // 0x1a in RxControl ?
+
+ /* TxConfigBits */
+ TxInterFrameGapShift = 24,
+ TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
+
+ LinkStatus = 0x02, // unused
+ FullDup = 0x01, // unused
+
+ /* TBICSRBit */
+ TBILinkOK = 0x02000000, // unused
+};
+
+struct TxDesc {
+ volatile u32 PSize;
+ volatile u32 status;
+ volatile u32 addr;
+ volatile u32 size;
+};
+
+struct RxDesc {
+ volatile u32 PSize;
+ volatile u32 status;
+ volatile u32 addr;
+ volatile u32 size;
+};
+
+enum _DescStatusBit {
+ /* _Desc.status */
+ OWNbit = 0x80000000, // RXOWN/TXOWN
+ INTbit = 0x40000000, // RXINT/TXINT
+ CRCbit = 0x00020000, // CRCOFF/CRCEN
+ PADbit = 0x00010000, // PREADD/PADEN
+ /* _Desc.size */
+ RingEnd = 0x80000000,
+ /* TxDesc.status */
+ LSEN = 0x08000000, // TSO ? -- FR
+ IPCS = 0x04000000,
+ TCPCS = 0x02000000,
+ UDPCS = 0x01000000,
+ BSTEN = 0x00800000,
+ EXTEN = 0x00400000,
+ DEFEN = 0x00200000,
+ BKFEN = 0x00100000,
+ CRSEN = 0x00080000,
+ COLEN = 0x00040000,
+ THOL3 = 0x30000000,
+ THOL2 = 0x20000000,
+ THOL1 = 0x10000000,
+ THOL0 = 0x00000000,
+
+ WND = 0x00080000,
+ TABRT = 0x00040000,
+ FIFO = 0x00020000,
+ LINK = 0x00010000,
+ ColCountMask = 0x0000ffff,
+ /* RxDesc.status */
+ IPON = 0x20000000,
+ TCPON = 0x10000000,
+ UDPON = 0x08000000,
+ Wakup = 0x00400000,
+ Magic = 0x00200000,
+ Pause = 0x00100000,
+ DEFbit = 0x00200000,
+ BCAST = 0x000c0000,
+ MCAST = 0x00080000,
+ UCAST = 0x00040000,
+ /* RxDesc.PSize */
+ TAGON = 0x80000000,
+ RxDescCountMask = 0x7f000000, // multi-desc pkt when > 1 ? -- FR
+ ABORT = 0x00800000,
+ SHORT = 0x00400000,
+ LIMIT = 0x00200000,
+ MIIER = 0x00100000,
+ OVRUN = 0x00080000,
+ NIBON = 0x00040000,
+ COLON = 0x00020000,
+ CRCOK = 0x00010000,
+ RxSizeMask = 0x0000ffff
+ /*
+ * The asic could apparently do vlan, TSO, jumbo (sis191 only) and
+ * provide two (unused with Linux) Tx queues. No publically
+ * available documentation alas.
+ */
+};
+
+enum sis190_eeprom_access_register_bits {
+ EECS = 0x00000001, // unused
+ EECLK = 0x00000002, // unused
+ EEDO = 0x00000008, // unused
+ EEDI = 0x00000004, // unused
+ EEREQ = 0x00000080,
+ EEROP = 0x00000200,
+ EEWOP = 0x00000100 // unused
+};
+
+/* EEPROM Addresses */
+enum sis190_eeprom_address {
+ EEPROMSignature = 0x00,
+ EEPROMCLK = 0x01, // unused
+ EEPROMInfo = 0x02,
+ EEPROMMACAddr = 0x03
+};
+
+enum sis190_feature {
+ F_HAS_RGMII = 1,
+ F_PHY_88E1111 = 2,
+ F_PHY_BCM5461 = 4
+};
+
+struct sis190_private {
+ void *mmio_addr;
+ struct pci_device *pci_device;
+ struct net_device *dev;
+ u32 cur_rx;
+ u32 cur_tx;
+ u32 dirty_rx;
+ u32 dirty_tx;
+ u32 rx_dma;
+ u32 tx_dma;
+ struct RxDesc *RxDescRing;
+ struct TxDesc *TxDescRing;
+ struct io_buffer *Rx_iobuf[NUM_RX_DESC];
+ struct io_buffer *Tx_iobuf[NUM_TX_DESC];
+ struct mii_if_info mii_if;
+ struct list_head first_phy;
+ u32 features;
+};
+
+struct sis190_phy {
+ struct list_head list;
+ int phy_id;
+ u16 id[2];
+ u16 status;
+ u8 type;
+};
+
+enum sis190_phy_type {
+ UNKNOWN = 0x00,
+ HOME = 0x01,
+ LAN = 0x02,
+ MIX = 0x03
+};
+
+static struct mii_chip_info {
+ const char *name;
+ u16 id[2];
+ unsigned int type;
+ u32 feature;
+} mii_chip_table[] = {
+ { "Atheros PHY", { 0x004d, 0xd010 }, LAN, 0 },
+ { "Atheros PHY AR8012", { 0x004d, 0xd020 }, LAN, 0 },
+ { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 },
+ { "Broadcom PHY AC131", { 0x0143, 0xbc70 }, LAN, 0 },
+ { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 },
+ { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 },
+ { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN, 0 },
+ { NULL, { 0x00, 0x00 }, 0, 0 }
+};
+
+static const struct {
+ const char *name;
+} sis_chip_info[] = {
+ { "SiS 190 PCI Fast Ethernet adapter" },
+ { "SiS 191 PCI Gigabit Ethernet adapter" },
+};
+
+static void sis190_phy_task(struct sis190_private *tp);
+static void sis190_free(struct net_device *dev);
+static inline void sis190_init_rxfilter(struct net_device *dev);
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/sis900.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/sis900.c
new file mode 100644
index 00000000..92eb5ce2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/sis900.c
@@ -0,0 +1,1303 @@
+/* -*- Mode:C; c-basic-offset:4; -*- */
+
+/*
+ sis900.c: An SiS 900/7016 PCI Fast Ethernet driver for Etherboot
+ Copyright (C) 2001 Entity Cyber, Inc.
+
+ Revision: 1.0 March 1, 2001
+
+ Author: Marty Connor (mdc@etherboot.org)
+
+ Adapted from a Linux driver which was written by Donald Becker
+ and modified by Ollie Lho and Chin-Shan Li of SiS Corporation.
+ Rewritten for Etherboot by Marty Connor.
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License (GPL), incorporated herein by reference.
+
+ References:
+ SiS 7016 Fast Ethernet PCI Bus 10/100 Mbps LAN Controller with OnNow Support,
+ preliminary Rev. 1.0 Jan. 14, 1998
+ SiS 900 Fast Ethernet PCI Bus 10/100 Mbps LAN Single Chip with OnNow Support,
+ preliminary Rev. 1.0 Nov. 10, 1998
+ SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
+ preliminary Rev. 1.0 Jan. 18, 1998
+ http://www.sis.com.tw/support/databook.htm */
+
+FILE_LICENCE ( GPL_ANY );
+
+/* Revision History */
+
+/*
+ 07 Dec 2003 timlegge - Enabled Multicast Support
+ 06 Dec 2003 timlegge - Fixed relocation issue in 5.2
+ 04 Jan 2002 Chien-Yu Chen, Doug Ambrisko, Marty Connor Patch to Etherboot 5.0.5
+ Added support for the SiS 630ET plus various bug fixes from linux kernel
+ source 2.4.17.
+ 01 March 2001 mdc 1.0
+ Initial Release. Tested with PCI based sis900 card and ThinkNIC
+ computer.
+ 20 March 2001 P.Koegel
+ added support for sis630e and PHY ICS1893 and RTL8201
+ Testet with SIS730S chipset + ICS1893
+*/
+
+
+/* Includes */
+
+#include "etherboot.h"
+#include <ipxe/pci.h>
+#include "nic.h"
+
+#include "sis900.h"
+
+/* Globals */
+
+static struct nic_operations sis900_operations;
+
+static int sis900_debug = 0;
+
+static unsigned short vendor, dev_id;
+static unsigned long ioaddr;
+static u8 pci_revision;
+
+static unsigned int cur_phy;
+
+static unsigned int cur_rx;
+
+struct {
+ BufferDesc txd;
+ BufferDesc rxd[NUM_RX_DESC];
+ unsigned char txb[TX_BUF_SIZE];
+ unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
+} sis900_bufs __shared;
+#define txd sis900_bufs.txd
+#define rxd sis900_bufs.rxd
+#define txb sis900_bufs.txb
+#define rxb sis900_bufs.rxb
+
+#if 0
+static struct mac_chip_info {
+ const char *name;
+ u16 vendor_id, device_id, flags;
+ int io_size;
+} mac_chip_table[] = {
+ { "SiS 900 PCI Fast Ethernet", PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS900,
+ PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE},
+ { "SiS 7016 PCI Fast Ethernet",PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS7016,
+ PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE},
+ {0,0,0,0,0} /* 0 terminated list. */
+};
+#endif
+
+static void sis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
+static void amd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
+static void ics1893_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
+static void rtl8201_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
+static void vt6103_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
+
+static struct mii_chip_info {
+ const char * name;
+ u16 phy_id0;
+ u16 phy_id1;
+ void (*read_mode) (struct nic *nic, int phy_addr, int *speed, int *duplex);
+} mii_chip_table[] = {
+ {"SiS 900 Internal MII PHY", 0x001d, 0x8000, sis900_read_mode},
+ {"SiS 7014 Physical Layer Solution", 0x0016, 0xf830,sis900_read_mode},
+ {"SiS 900 on Foxconn 661 7MI", 0x0143, 0xBC70, sis900_read_mode},
+ {"AMD 79C901 10BASE-T PHY", 0x0000, 0x6B70, amd79c901_read_mode},
+ {"AMD 79C901 HomePNA PHY", 0x0000, 0x6B90, amd79c901_read_mode},
+ {"ICS 1893 Integrated PHYceiver" , 0x0015, 0xf440,ics1893_read_mode},
+// {"NS 83851 PHY",0x2000, 0x5C20, MIX },
+ {"RTL 8201 10/100Mbps Phyceiver" , 0x0000, 0x8200,rtl8201_read_mode},
+ {"VIA 6103 10/100Mbps Phyceiver", 0x0101, 0x8f20,vt6103_read_mode},
+ {0,0,0,0}
+};
+
+static struct mii_phy {
+ struct mii_phy * next;
+ struct mii_chip_info * chip_info;
+ int phy_addr;
+ u16 status;
+} mii;
+
+
+
+#if 0
+// PCI to ISA bridge for SIS640E access
+static struct pci_device_id pci_isa_bridge_list[] = {
+ { .vendor = 0x1039, .device = 0x0008,
+ .name = "SIS 85C503/5513 PCI to ISA bridge"},
+};
+
+PCI_DRIVER( sis_bridge_pci_driver, pci_isa_bridge_list, PCI_NO_CLASS );
+
+static struct device_driver sis_bridge_driver = {
+ .name = "SIS ISA bridge",
+ .bus_driver = &pci_driver,
+ .bus_driver_info = ( struct bus_driver_info * ) &sis_bridge_pci_driver,
+};
+#endif
+
+/* Function Prototypes */
+
+static int sis900_probe(struct nic *nic,struct pci_device *pci);
+
+static u16 sis900_read_eeprom(int location);
+static void sis900_mdio_reset(long mdio_addr);
+static void sis900_mdio_idle(long mdio_addr);
+static u16 sis900_mdio_read(int phy_id, int location);
+#if 0
+static void sis900_mdio_write(int phy_id, int location, int val);
+#endif
+static void sis900_init(struct nic *nic);
+
+static void sis900_reset(struct nic *nic);
+
+static void sis900_init_rxfilter(struct nic *nic);
+static void sis900_init_txd(struct nic *nic);
+static void sis900_init_rxd(struct nic *nic);
+static void sis900_set_rx_mode(struct nic *nic);
+static void sis900_check_mode(struct nic *nic);
+
+static void sis900_transmit(struct nic *nic, const char *d,
+ unsigned int t, unsigned int s, const char *p);
+static int sis900_poll(struct nic *nic, int retrieve);
+
+static void sis900_disable(struct nic *nic);
+
+static void sis900_irq(struct nic *nic, irq_action_t action);
+
+/**
+ * sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model
+ * @pci_dev: the sis900 pci device
+ * @net_dev: the net device to get address for
+ *
+ * Older SiS900 and friends, use EEPROM to store MAC address.
+ * MAC address is read from read_eeprom() into @net_dev->dev_addr.
+ */
+
+static int sis900_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
+{
+ u16 signature;
+ int i;
+
+ /* check to see if we have sane EEPROM */
+ signature = (u16) sis900_read_eeprom( EEPROMSignature);
+ if (signature == 0xffff || signature == 0x0000) {
+ printf ("sis900_probe: Error EERPOM read %hX\n", signature);
+ return 0;
+ }
+
+ /* get MAC address from EEPROM */
+ for (i = 0; i < 3; i++)
+ ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
+ return 1;
+}
+
+/**
+ * sis96x_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
+ * @pci_dev: the sis900 pci device
+ * @net_dev: the net device to get address for
+ *
+ * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM
+ * is shared by
+ * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first
+ * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access
+ * by LAN, otherwise is not. After MAC address is read from EEPROM, send
+ * EEDONE signal to refuse EEPROM access by LAN.
+ * The EEPROM map of SiS962 or SiS963 is different to SiS900.
+ * The signature field in SiS962 or SiS963 spec is meaningless.
+ * MAC address is read into @net_dev->dev_addr.
+ */
+
+static int sis96x_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
+{
+/* long ioaddr = net_dev->base_addr; */
+ long ee_addr = ioaddr + mear;
+ u32 waittime = 0;
+ int i;
+
+ printf("Alternate function\n");
+
+ outl(EEREQ, ee_addr);
+ while(waittime < 2000) {
+ if(inl(ee_addr) & EEGNT) {
+
+ /* get MAC address from EEPROM */
+ for (i = 0; i < 3; i++)
+ ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
+
+ outl(EEDONE, ee_addr);
+ return 1;
+ } else {
+ udelay(1);
+ waittime ++;
+ }
+ }
+ outl(EEDONE, ee_addr);
+ return 0;
+}
+
+/**
+ * sis630e_get_mac_addr: - Get MAC address for SiS630E model
+ * @pci_dev: the sis900 pci device
+ * @net_dev: the net device to get address for
+ *
+ * SiS630E model, use APC CMOS RAM to store MAC address.
+ * APC CMOS RAM is accessed through ISA bridge.
+ * MAC address is read into @net_dev->dev_addr.
+ */
+
+static int sis630e_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
+{
+#if 0
+ u8 reg;
+ int i;
+ struct bus_loc bus_loc;
+ union {
+ struct bus_dev bus_dev;
+ struct pci_device isa_bridge;
+ } u;
+
+ /* find PCI to ISA bridge */
+ memset(&bus_loc, 0, sizeof(bus_loc));
+ if ( ! find_by_driver ( &bus_loc, &u.bus_dev, &sis_bridge_driver, 0 ) )
+ return 0;
+
+ pci_read_config_byte(&u.isa_bridge, 0x48, &reg);
+ pci_write_config_byte(&u.isa_bridge, 0x48, reg | 0x40);
+
+ for (i = 0; i < ETH_ALEN; i++)
+ {
+ outb(0x09 + i, 0x70);
+ ((u8 *)(nic->node_addr))[i] = inb(0x71);
+ }
+ pci_write_config_byte(&u.isa_bridge, 0x48, reg & ~0x40);
+
+ return 1;
+#endif
+
+ /* Does not work with current bus/device model */
+ memset ( nic->node_addr, 0, sizeof ( nic->node_addr ) );
+ return 0;
+}
+
+/**
+ * sis630e_get_mac_addr: - Get MAC address for SiS630E model
+ * @pci_dev: the sis900 pci device
+ * @net_dev: the net device to get address for
+ *
+ * SiS630E model, use APC CMOS RAM to store MAC address.
+ * APC CMOS RAM is accessed through ISA bridge.
+ * MAC address is read into @net_dev->dev_addr.
+ */
+
+static int sis635_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
+{
+ u32 rfcrSave;
+ u32 i;
+
+
+ rfcrSave = inl(rfcr + ioaddr);
+
+ outl(rfcrSave | RELOAD, ioaddr + cr);
+ outl(0, ioaddr + cr);
+
+ /* disable packet filtering before setting filter */
+ outl(rfcrSave & ~RFEN, rfcr + ioaddr);
+
+ /* load MAC addr to filter data register */
+ for (i = 0 ; i < 3 ; i++) {
+ outl((i << RFADDR_shift), ioaddr + rfcr);
+ *( ((u16 *)nic->node_addr) + i) = inw(ioaddr + rfdr);
+ }
+
+ /* enable packet filitering */
+ outl(rfcrSave | RFEN, rfcr + ioaddr);
+
+ return 1;
+}
+
+/*
+ * Function: sis900_probe
+ *
+ * Description: initializes initializes the NIC, retrieves the
+ * MAC address of the card, and sets up some globals required by
+ * other routines.
+ *
+ * Side effects:
+ * leaves the ioaddress of the sis900 chip in the variable ioaddr.
+ * leaves the sis900 initialized, and ready to recieve packets.
+ *
+ * Returns: struct nic *: pointer to NIC data structure
+ */
+
+static int sis900_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ int i;
+ int found=0;
+ int phy_addr;
+ u8 revision;
+ int ret;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ nic->irqno = 0;
+ nic->ioaddr = pci->ioaddr;
+
+ ioaddr = pci->ioaddr;
+ vendor = pci->vendor;
+ dev_id = pci->device;
+
+ /* wakeup chip */
+ pci_write_config_dword(pci, 0x40, 0x00000000);
+
+ adjust_pci_device(pci);
+
+ /* get MAC address */
+ ret = 0;
+ pci_read_config_byte(pci, PCI_REVISION, &revision);
+
+ /* save for use later in sis900_reset() */
+ pci_revision = revision;
+
+ if (revision == SIS630E_900_REV)
+ ret = sis630e_get_mac_addr(pci, nic);
+ else if ((revision > 0x81) && (revision <= 0x90))
+ ret = sis635_get_mac_addr(pci, nic);
+ else if (revision == SIS96x_900_REV)
+ ret = sis96x_get_mac_addr(pci, nic);
+ else
+ ret = sis900_get_mac_addr(pci, nic);
+
+ if (ret == 0)
+ {
+ printf ("sis900_probe: Error MAC address not found\n");
+ return 0;
+ }
+
+ /* 630ET : set the mii access mode as software-mode */
+ if (revision == SIS630ET_900_REV)
+ outl(ACCESSMODE | inl(ioaddr + cr), ioaddr + cr);
+
+ DBG( "sis900_probe: Vendor:%#hX Device:%#hX\n", vendor, dev_id );
+
+ /* probe for mii transceiver */
+ /* search for total of 32 possible mii phy addresses */
+
+ found = 0;
+ for (phy_addr = 0; phy_addr < 32; phy_addr++) {
+ u16 mii_status;
+ u16 phy_id0, phy_id1;
+
+ mii_status = sis900_mdio_read(phy_addr, MII_STATUS);
+ if (mii_status == 0xffff || mii_status == 0x0000)
+ /* the mii is not accessable, try next one */
+ continue;
+
+ phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
+ phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
+
+ /* search our mii table for the current mii */
+ for (i = 0; mii_chip_table[i].phy_id1; i++) {
+
+ if ((phy_id0 == mii_chip_table[i].phy_id0) &&
+ ((phy_id1 & 0xFFF0) == mii_chip_table[i].phy_id1)){
+
+ printf("sis900_probe: %s transceiver found at address %d.\n",
+ mii_chip_table[i].name, phy_addr);
+
+ mii.chip_info = &mii_chip_table[i];
+ mii.phy_addr = phy_addr;
+ mii.status = sis900_mdio_read(phy_addr, MII_STATUS);
+ mii.next = NULL;
+
+ found=1;
+ break;
+ }
+ }
+ }
+
+ if (found == 0) {
+ printf("sis900_probe: No MII transceivers found!\n");
+ return 0;
+ }
+
+ /* Arbitrarily select the last PHY found as current PHY */
+ cur_phy = mii.phy_addr;
+ printf("sis900_probe: Using %s as default\n", mii.chip_info->name);
+
+ /* initialize device */
+ sis900_init(nic);
+ nic->nic_op = &sis900_operations;
+
+ return 1;
+}
+
+
+
+
+/*
+ * EEPROM Routines: These functions read and write to EEPROM for
+ * retrieving the MAC address and other configuration information about
+ * the card.
+ */
+
+/* Delay between EEPROM clock transitions. */
+#define eeprom_delay() inl(ee_addr)
+
+
+/* Function: sis900_read_eeprom
+ *
+ * Description: reads and returns a given location from EEPROM
+ *
+ * Arguments: int location: requested EEPROM location
+ *
+ * Returns: u16: contents of requested EEPROM location
+ *
+ */
+
+/* Read Serial EEPROM through EEPROM Access Register, Note that location is
+ in word (16 bits) unit */
+static u16 sis900_read_eeprom(int location)
+{
+ int i;
+ u16 retval = 0;
+ long ee_addr = ioaddr + mear;
+ u32 read_cmd = location | EEread;
+
+ outl(0, ee_addr);
+ eeprom_delay();
+ outl(EECS, ee_addr);
+ eeprom_delay();
+
+ /* Shift the read command (9) bits out. */
+ for (i = 8; i >= 0; i--) {
+ u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS;
+ outl(dataval, ee_addr);
+ eeprom_delay();
+ outl(dataval | EECLK, ee_addr);
+ eeprom_delay();
+ }
+ outl(EECS, ee_addr);
+ eeprom_delay();
+
+ /* read the 16-bits data in */
+ for (i = 16; i > 0; i--) {
+ outl(EECS, ee_addr);
+ eeprom_delay();
+ outl(EECS | EECLK, ee_addr);
+ eeprom_delay();
+ retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0);
+ eeprom_delay();
+ }
+
+ /* Terminate the EEPROM access. */
+ outl(0, ee_addr);
+ eeprom_delay();
+// outl(EECLK, ee_addr);
+
+ return (retval);
+}
+
+#define sis900_mdio_delay() inl(mdio_addr)
+
+
+/*
+ Read and write the MII management registers using software-generated
+ serial MDIO protocol. Note that the command bits and data bits are
+ send out seperately
+*/
+
+static void sis900_mdio_idle(long mdio_addr)
+{
+ outl(MDIO | MDDIR, mdio_addr);
+ sis900_mdio_delay();
+ outl(MDIO | MDDIR | MDC, mdio_addr);
+}
+
+/* Syncronize the MII management interface by shifting 32 one bits out. */
+static void sis900_mdio_reset(long mdio_addr)
+{
+ int i;
+
+ for (i = 31; i >= 0; i--) {
+ outl(MDDIR | MDIO, mdio_addr);
+ sis900_mdio_delay();
+ outl(MDDIR | MDIO | MDC, mdio_addr);
+ sis900_mdio_delay();
+ }
+ return;
+}
+
+static u16 sis900_mdio_read(int phy_id, int location)
+{
+ long mdio_addr = ioaddr + mear;
+ int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
+ u16 retval = 0;
+ int i;
+
+ sis900_mdio_reset(mdio_addr);
+ sis900_mdio_idle(mdio_addr);
+
+ for (i = 15; i >= 0; i--) {
+ int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
+ outl(dataval, mdio_addr);
+ sis900_mdio_delay();
+ outl(dataval | MDC, mdio_addr);
+ sis900_mdio_delay();
+ }
+
+ /* Read the 16 data bits. */
+ for (i = 16; i > 0; i--) {
+ outl(0, mdio_addr);
+ sis900_mdio_delay();
+ retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0);
+ outl(MDC, mdio_addr);
+ sis900_mdio_delay();
+ }
+ outl(0x00, mdio_addr);
+ return retval;
+}
+
+#if 0
+static void sis900_mdio_write(int phy_id, int location, int value)
+{
+ long mdio_addr = ioaddr + mear;
+ int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
+ int i;
+
+ sis900_mdio_reset(mdio_addr);
+ sis900_mdio_idle(mdio_addr);
+
+ /* Shift the command bits out. */
+ for (i = 15; i >= 0; i--) {
+ int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
+ outb(dataval, mdio_addr);
+ sis900_mdio_delay();
+ outb(dataval | MDC, mdio_addr);
+ sis900_mdio_delay();
+ }
+ sis900_mdio_delay();
+
+ /* Shift the value bits out. */
+ for (i = 15; i >= 0; i--) {
+ int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR;
+ outl(dataval, mdio_addr);
+ sis900_mdio_delay();
+ outl(dataval | MDC, mdio_addr);
+ sis900_mdio_delay();
+ }
+ sis900_mdio_delay();
+
+ /* Clear out extra bits. */
+ for (i = 2; i > 0; i--) {
+ outb(0, mdio_addr);
+ sis900_mdio_delay();
+ outb(MDC, mdio_addr);
+ sis900_mdio_delay();
+ }
+ outl(0x00, mdio_addr);
+ return;
+}
+#endif
+
+
+/* Function: sis900_init
+ *
+ * Description: resets the ethernet controller chip and various
+ * data structures required for sending and receiving packets.
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * returns: void.
+ */
+
+static void
+sis900_init(struct nic *nic)
+{
+ /* Soft reset the chip. */
+ sis900_reset(nic);
+
+ sis900_init_rxfilter(nic);
+
+ sis900_init_txd(nic);
+ sis900_init_rxd(nic);
+
+ sis900_set_rx_mode(nic);
+
+ sis900_check_mode(nic);
+
+ outl(RxENA| inl(ioaddr + cr), ioaddr + cr);
+}
+
+
+/*
+ * Function: sis900_reset
+ *
+ * Description: disables interrupts and soft resets the controller chip
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_reset(struct nic *nic __unused)
+{
+ int i = 0;
+ u32 status = TxRCMP | RxRCMP;
+
+ outl(0, ioaddr + ier);
+ outl(0, ioaddr + imr);
+ outl(0, ioaddr + rfcr);
+
+ outl(RxRESET | TxRESET | RESET | inl(ioaddr + cr), ioaddr + cr);
+
+ /* Check that the chip has finished the reset. */
+ while (status && (i++ < 1000)) {
+ status ^= (inl(isr + ioaddr) & status);
+ }
+
+ if( (pci_revision >= SIS635A_900_REV) || (pci_revision == SIS900B_900_REV) )
+ outl(PESEL | RND_CNT, ioaddr + cfg);
+ else
+ outl(PESEL, ioaddr + cfg);
+}
+
+
+/* Function: sis_init_rxfilter
+ *
+ * Description: sets receive filter address to our MAC address
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * returns: void.
+ */
+
+static void
+sis900_init_rxfilter(struct nic *nic)
+{
+ u32 rfcrSave;
+ int i;
+
+ rfcrSave = inl(rfcr + ioaddr);
+
+ /* disable packet filtering before setting filter */
+ outl(rfcrSave & ~RFEN, rfcr + ioaddr);
+
+ /* load MAC addr to filter data register */
+ for (i = 0 ; i < 3 ; i++) {
+ u32 w;
+
+ w = (u32) *((u16 *)(nic->node_addr)+i);
+ outl((i << RFADDR_shift), ioaddr + rfcr);
+ outl(w, ioaddr + rfdr);
+
+ if (sis900_debug > 0)
+ printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%X\n",
+ i, inl(ioaddr + rfdr));
+ }
+
+ /* enable packet filitering */
+ outl(rfcrSave | RFEN, rfcr + ioaddr);
+}
+
+
+/*
+ * Function: sis_init_txd
+ *
+ * Description: initializes the Tx descriptor
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * returns: void.
+ */
+
+static void
+sis900_init_txd(struct nic *nic __unused)
+{
+ txd.link = (u32) 0;
+ txd.cmdsts = (u32) 0;
+ txd.bufptr = virt_to_bus(&txb[0]);
+
+ /* load Transmit Descriptor Register */
+ outl(virt_to_bus(&txd), ioaddr + txdp);
+ if (sis900_debug > 0)
+ printf("sis900_init_txd: TX descriptor register loaded with: %X\n",
+ inl(ioaddr + txdp));
+}
+
+
+/* Function: sis_init_rxd
+ *
+ * Description: initializes the Rx descriptor ring
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_init_rxd(struct nic *nic __unused)
+{
+ int i;
+
+ cur_rx = 0;
+
+ /* init RX descriptor */
+ for (i = 0; i < NUM_RX_DESC; i++) {
+ rxd[i].link = virt_to_bus((i+1 < NUM_RX_DESC) ? &rxd[i+1] : &rxd[0]);
+ rxd[i].cmdsts = (u32) RX_BUF_SIZE;
+ rxd[i].bufptr = virt_to_bus(&rxb[i*RX_BUF_SIZE]);
+ if (sis900_debug > 0)
+ printf("sis900_init_rxd: rxd[%d]=%p link=%X cmdsts=%X bufptr=%X\n",
+ i, &rxd[i], (unsigned int) rxd[i].link, (unsigned int) rxd[i].cmdsts,
+ (unsigned int) rxd[i].bufptr);
+ }
+
+ /* load Receive Descriptor Register */
+ outl(virt_to_bus(&rxd[0]), ioaddr + rxdp);
+
+ if (sis900_debug > 0)
+ printf("sis900_init_rxd: RX descriptor register loaded with: %X\n",
+ inl(ioaddr + rxdp));
+
+}
+
+
+/* Function: sis_init_rxd
+ *
+ * Description:
+ * sets the receive mode to accept all broadcast packets and packets
+ * with our MAC address, and reject all multicast packets.
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void sis900_set_rx_mode(struct nic *nic __unused)
+{
+ int i, table_entries;
+ u32 rx_mode;
+ u16 mc_filter[16] = {0}; /* 256/128 bits multicast hash table */
+
+ if((pci_revision == SIS635A_900_REV) || (pci_revision == SIS900B_900_REV))
+ table_entries = 16;
+ else
+ table_entries = 8;
+
+ /* accept all multicast packet */
+ rx_mode = RFAAB | RFAAM;
+ for (i = 0; i < table_entries; i++)
+ mc_filter[i] = 0xffff;
+
+ /* update Multicast Hash Table in Receive Filter */
+ for (i = 0; i < table_entries; i++) {
+ /* why plus 0x04? That makes the correct value for hash table. */
+ outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr);
+ outl(mc_filter[i], ioaddr + rfdr);
+ }
+
+ /* Accept Broadcast and multicast packets, destination addresses that match
+ our MAC address */
+ outl(RFEN | rx_mode, ioaddr + rfcr);
+
+ return;
+}
+
+
+/* Function: sis900_check_mode
+ *
+ * Description: checks the state of transmit and receive
+ * parameters on the NIC, and updates NIC registers to match
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_check_mode(struct nic *nic)
+{
+ int speed, duplex;
+ u32 tx_flags = 0, rx_flags = 0;
+
+ mii.chip_info->read_mode(nic, cur_phy, &speed, &duplex);
+
+ if( inl(ioaddr + cfg) & EDB_MASTER_EN ) {
+ tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
+ rx_flags = DMA_BURST_64 << RxMXDMA_shift;
+ }
+ else {
+ tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
+ rx_flags = DMA_BURST_512 << RxMXDMA_shift;
+ }
+
+ if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) {
+ rx_flags |= (RxDRNT_10 << RxDRNT_shift);
+ tx_flags |= (TxDRNT_10 << TxDRNT_shift);
+ }
+ else {
+ rx_flags |= (RxDRNT_100 << RxDRNT_shift);
+ tx_flags |= (TxDRNT_100 << TxDRNT_shift);
+ }
+
+ if (duplex == FDX_CAPABLE_FULL_SELECTED) {
+ tx_flags |= (TxCSI | TxHBI);
+ rx_flags |= RxATX;
+ }
+
+ outl (tx_flags, ioaddr + txcfg);
+ outl (rx_flags, ioaddr + rxcfg);
+}
+
+
+/* Function: sis900_read_mode
+ *
+ * Description: retrieves and displays speed and duplex
+ * parameters from the NIC
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
+{
+ int i = 0;
+ u32 status;
+ u16 phy_id0, phy_id1;
+
+ /* STSOUT register is Latched on Transition, read operation updates it */
+ do {
+ status = sis900_mdio_read(phy_addr, MII_STSOUT);
+ } while (i++ < 2);
+
+ *speed = HW_SPEED_10_MBPS;
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+
+ if (status & (MII_NWAY_TX | MII_NWAY_TX_FDX))
+ *speed = HW_SPEED_100_MBPS;
+ if (status & ( MII_NWAY_TX_FDX | MII_NWAY_T_FDX))
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+
+ /* Workaround for Realtek RTL8201 PHY issue */
+ phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
+ phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
+ if((phy_id0 == 0x0000) && ((phy_id1 & 0xFFF0) == 0x8200)){
+ if(sis900_mdio_read(phy_addr, MII_CONTROL) & MII_CNTL_FDX)
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ if(sis900_mdio_read(phy_addr, 0x0019) & 0x01)
+ *speed = HW_SPEED_100_MBPS;
+ }
+
+ if (status & MII_STSOUT_LINK_FAIL)
+ printf("sis900_read_mode: Media Link Off\n");
+ else
+ printf("sis900_read_mode: Media Link On %s %s-duplex \n",
+ *speed == HW_SPEED_100_MBPS ?
+ "100mbps" : "10mbps",
+ *duplex == FDX_CAPABLE_FULL_SELECTED ?
+ "full" : "half");
+}
+
+
+/* Function: amd79c901_read_mode
+ *
+ * Description: retrieves and displays speed and duplex
+ * parameters from the NIC
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void
+amd79c901_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
+{
+ int i;
+ u16 status;
+
+ for (i = 0; i < 2; i++)
+ status = sis900_mdio_read(phy_addr, MII_STATUS);
+
+ if (status & MII_STAT_CAN_AUTO) {
+ /* 10BASE-T PHY */
+ for (i = 0; i < 2; i++)
+ status = sis900_mdio_read(phy_addr, MII_STATUS_SUMMARY);
+ if (status & MII_STSSUM_SPD)
+ *speed = HW_SPEED_100_MBPS;
+ else
+ *speed = HW_SPEED_10_MBPS;
+ if (status & MII_STSSUM_DPLX)
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ else
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+
+ if (status & MII_STSSUM_LINK)
+ printf("amd79c901_read_mode: Media Link On %s %s-duplex \n",
+ *speed == HW_SPEED_100_MBPS ?
+ "100mbps" : "10mbps",
+ *duplex == FDX_CAPABLE_FULL_SELECTED ?
+ "full" : "half");
+ else
+ printf("amd79c901_read_mode: Media Link Off\n");
+ }
+ else {
+ /* HomePNA */
+ *speed = HW_SPEED_HOME;
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+ if (status & MII_STAT_LINK)
+ printf("amd79c901_read_mode:Media Link On 1mbps half-duplex \n");
+ else
+ printf("amd79c901_read_mode: Media Link Off\n");
+ }
+}
+
+
+/**
+ * ics1893_read_mode: - read media mode for ICS1893 PHY
+ * @net_dev: the net device to read mode for
+ * @phy_addr: mii phy address
+ * @speed: the transmit speed to be determined
+ * @duplex: the duplex mode to be determined
+ *
+ * ICS1893 PHY use Quick Poll Detailed Status register
+ * to determine the speed and duplex mode for sis900
+ */
+
+static void ics1893_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
+{
+ int i = 0;
+ u32 status;
+
+ /* MII_QPDSTS is Latched, read twice in succession will reflect the current state */
+ for (i = 0; i < 2; i++)
+ status = sis900_mdio_read(phy_addr, MII_QPDSTS);
+
+ if (status & MII_STSICS_SPD)
+ *speed = HW_SPEED_100_MBPS;
+ else
+ *speed = HW_SPEED_10_MBPS;
+
+ if (status & MII_STSICS_DPLX)
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ else
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+
+ if (status & MII_STSICS_LINKSTS)
+ printf("ics1893_read_mode: Media Link On %s %s-duplex \n",
+ *speed == HW_SPEED_100_MBPS ?
+ "100mbps" : "10mbps",
+ *duplex == FDX_CAPABLE_FULL_SELECTED ?
+ "full" : "half");
+ else
+ printf("ics1893_read_mode: Media Link Off\n");
+}
+
+/**
+ * rtl8201_read_mode: - read media mode for rtl8201 phy
+ * @nic: the net device to read mode for
+ * @phy_addr: mii phy address
+ * @speed: the transmit speed to be determined
+ * @duplex: the duplex mode to be determined
+ *
+ * read MII_STATUS register from rtl8201 phy
+ * to determine the speed and duplex mode for sis900
+ */
+
+static void rtl8201_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
+{
+ u32 status;
+
+ status = sis900_mdio_read(phy_addr, MII_STATUS);
+
+ if (status & MII_STAT_CAN_TX_FDX) {
+ *speed = HW_SPEED_100_MBPS;
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ }
+ else if (status & MII_STAT_CAN_TX) {
+ *speed = HW_SPEED_100_MBPS;
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+ }
+ else if (status & MII_STAT_CAN_T_FDX) {
+ *speed = HW_SPEED_10_MBPS;
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ }
+ else if (status & MII_STAT_CAN_T) {
+ *speed = HW_SPEED_10_MBPS;
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+ }
+
+ if (status & MII_STAT_LINK)
+ printf("rtl8201_read_mode: Media Link On %s %s-duplex \n",
+ *speed == HW_SPEED_100_MBPS ?
+ "100mbps" : "10mbps",
+ *duplex == FDX_CAPABLE_FULL_SELECTED ?
+ "full" : "half");
+ else
+ printf("rtl8201_read_config_mode: Media Link Off\n");
+}
+
+/**
+ * vt6103_read_mode: - read media mode for vt6103 phy
+ * @nic: the net device to read mode for
+ * @phy_addr: mii phy address
+ * @speed: the transmit speed to be determined
+ * @duplex: the duplex mode to be determined
+ *
+ * read MII_STATUS register from rtl8201 phy
+ * to determine the speed and duplex mode for sis900
+ */
+
+static void vt6103_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
+{
+ u32 status;
+
+ status = sis900_mdio_read(phy_addr, MII_STATUS);
+
+ if (status & MII_STAT_CAN_TX_FDX) {
+ *speed = HW_SPEED_100_MBPS;
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ }
+ else if (status & MII_STAT_CAN_TX) {
+ *speed = HW_SPEED_100_MBPS;
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+ }
+ else if (status & MII_STAT_CAN_T_FDX) {
+ *speed = HW_SPEED_10_MBPS;
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ }
+ else if (status & MII_STAT_CAN_T) {
+ *speed = HW_SPEED_10_MBPS;
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+ }
+
+ if (status & MII_STAT_LINK)
+ printf("vt6103_read_mode: Media Link On %s %s-duplex \n",
+ *speed == HW_SPEED_100_MBPS ?
+ "100mbps" : "10mbps",
+ *duplex == FDX_CAPABLE_FULL_SELECTED ?
+ "full" : "half");
+ else
+ printf("vt6103_read_config_mode: Media Link Off\n");
+}
+
+/* Function: sis900_transmit
+ *
+ * Description: transmits a packet and waits for completion or timeout.
+ *
+ * Arguments: char d[6]: destination ethernet address.
+ * unsigned short t: ethernet protocol type.
+ * unsigned short s: size of the data-part of the packet.
+ * char *p: the data for the packet.
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_transmit(struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ u32 to, nstype;
+ volatile u32 tx_status;
+
+ /* Stop the transmitter */
+ outl(TxDIS | inl(ioaddr + cr), ioaddr + cr);
+
+ /* load Transmit Descriptor Register */
+ outl(virt_to_bus(&txd), ioaddr + txdp);
+ if (sis900_debug > 1)
+ printf("sis900_transmit: TX descriptor register loaded with: %X\n",
+ inl(ioaddr + txdp));
+
+ memcpy(txb, d, ETH_ALEN);
+ memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ nstype = htons(t);
+ memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2);
+ memcpy(txb + ETH_HLEN, p, s);
+
+ s += ETH_HLEN;
+ s &= DSIZE;
+
+ if (sis900_debug > 1)
+ printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t);
+
+ /* pad to minimum packet size */
+ while (s < ETH_ZLEN)
+ txb[s++] = '\0';
+
+ /* set the transmit buffer descriptor and enable Transmit State Machine */
+ txd.bufptr = virt_to_bus(&txb[0]);
+ txd.cmdsts = (u32) OWN | s;
+
+ /* restart the transmitter */
+ outl(TxENA | inl(ioaddr + cr), ioaddr + cr);
+
+ if (sis900_debug > 1)
+ printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s);
+
+ to = currticks() + TX_TIMEOUT;
+
+ while (((tx_status=txd.cmdsts) & OWN) && (currticks() < to))
+ /* wait */ ;
+
+ if (currticks() >= to) {
+ printf("sis900_transmit: TX Timeout! Tx status %X.\n",
+ (unsigned int) tx_status);
+ }
+
+ if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {
+ /* packet unsuccessfully transmited */
+ printf("sis900_transmit: Transmit error, Tx status %X.\n",
+ (unsigned int) tx_status);
+ }
+ /* Disable interrupts by clearing the interrupt mask. */
+ outl(0, ioaddr + imr);
+}
+
+
+/* Function: sis900_poll
+ *
+ * Description: checks for a received packet and returns it if found.
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: 1 if a packet was recieved.
+ * 0 if no pacet was recieved.
+ *
+ * Side effects:
+ * Returns (copies) the packet to the array nic->packet.
+ * Returns the length of the packet in nic->packetlen.
+ */
+
+static int
+sis900_poll(struct nic *nic, int retrieve)
+{
+ u32 rx_status = rxd[cur_rx].cmdsts;
+ int retstat = 0;
+
+ /* acknowledge interrupts by reading interrupt status register */
+ inl(ioaddr + isr);
+
+ if (sis900_debug > 2)
+ printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx,
+ (unsigned int) rx_status);
+
+ if (!(rx_status & OWN))
+ return retstat;
+
+ if (sis900_debug > 1)
+ printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n",
+ cur_rx, (unsigned int) rx_status);
+
+ if ( ! retrieve ) return 1;
+
+ nic->packetlen = (rx_status & DSIZE) - CRC_SIZE;
+
+ if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
+ /* corrupted packet received */
+ printf("sis900_poll: Corrupted packet received, buffer status = %X\n",
+ (unsigned int) rx_status);
+ retstat = 0;
+ } else {
+ /* give packet to higher level routine */
+ memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen);
+ retstat = 1;
+ }
+
+ /* return the descriptor and buffer to receive ring */
+ rxd[cur_rx].cmdsts = RX_BUF_SIZE;
+ rxd[cur_rx].bufptr = virt_to_bus(&rxb[cur_rx*RX_BUF_SIZE]);
+
+ if (++cur_rx == NUM_RX_DESC)
+ cur_rx = 0;
+
+ /* re-enable the potentially idle receive state machine */
+ outl(RxENA | inl(ioaddr + cr), ioaddr + cr);
+
+ return retstat;
+
+}
+
+
+/* Function: sis900_disable
+ *
+ * Description: Turns off interrupts and stops Tx and Rx engines
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_disable ( struct nic *nic ) {
+
+ sis900_init(nic);
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ outl(0, ioaddr + imr);
+ outl(0, ioaddr + ier);
+
+ /* Stop the chip's Tx and Rx Status Machine */
+ outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr);
+}
+
+
+/* Function: sis900_irq
+ *
+ * Description: Enable, Disable, or Force, interrupts
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ * irq_action_t action: Requested action
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ outl(0, ioaddr + imr);
+ break;
+ case ENABLE :
+ outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations sis900_operations = {
+ .connect = dummy_connect,
+ .poll = sis900_poll,
+ .transmit = sis900_transmit,
+ .irq = sis900_irq,
+};
+
+static struct pci_device_id sis900_nics[] = {
+PCI_ROM(0x1039, 0x0900, "sis900", "SIS900", 0),
+PCI_ROM(0x1039, 0x7016, "sis7016", "SIS7016", 0),
+};
+
+PCI_DRIVER ( sis900_driver, sis900_nics, PCI_NO_CLASS );
+
+DRIVER ( "SIS900", nic_driver, pci_driver, sis900_driver,
+ sis900_probe, sis900_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/sis900.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/sis900.h
new file mode 100644
index 00000000..7a5c6b53
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/sis900.h
@@ -0,0 +1,375 @@
+/* -*- Mode:C; c-basic-offset:4; -*- */
+
+/* Definitions for SiS ethernet controllers including 7014/7016 and 900
+ * References:
+ * SiS 7016 Fast Ethernet PCI Bus 10/100 Mbps LAN Controller with OnNow Support,
+ * preliminary Rev. 1.0 Jan. 14, 1998
+ * SiS 900 Fast Ethernet PCI Bus 10/100 Mbps LAN Single Chip with OnNow Support,
+ * preliminary Rev. 1.0 Nov. 10, 1998
+ * SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
+ * preliminary Rev. 1.0 Jan. 18, 1998
+ * http://www.sis.com.tw/support/databook.htm
+ */
+
+FILE_LICENCE ( GPL_ANY );
+
+/* MAC operationl registers of SiS 7016 and SiS 900 ethernet controller */
+/* The I/O extent, SiS 900 needs 256 bytes of io address */
+#define SIS900_TOTAL_SIZE 0x100
+
+/* Symbolic offsets to registers. */
+enum sis900_registers {
+ cr=0x0, /* Command Register */
+ cfg=0x4, /* Configuration Register */
+ mear=0x8, /* EEPROM Access Register */
+ ptscr=0xc, /* PCI Test Control Register */
+ isr=0x10, /* Interrupt Status Register */
+ imr=0x14, /* Interrupt Mask Register */
+ ier=0x18, /* Interrupt Enable Register */
+ epar=0x18, /* Enhanced PHY Access Register */
+ txdp=0x20, /* Transmit Descriptor Pointer Register */
+ txcfg=0x24, /* Transmit Configuration Register */
+ rxdp=0x30, /* Receive Descriptor Pointer Register */
+ rxcfg=0x34, /* Receive Configuration Register */
+ flctrl=0x38, /* Flow Control Register */
+ rxlen=0x3c, /* Receive Packet Length Register */
+ rfcr=0x48, /* Receive Filter Control Register */
+ rfdr=0x4C, /* Receive Filter Data Register */
+ pmctrl=0xB0, /* Power Management Control Register */
+ pmer=0xB4 /* Power Management Wake-up Event Register */
+};
+
+/* Symbolic names for bits in various registers */
+enum sis900_command_register_bits {
+ RELOAD = 0x00000400,
+ ACCESSMODE = 0x00000200,
+ RESET = 0x00000100,
+ SWI = 0x00000080,
+ RxRESET = 0x00000020,
+ TxRESET = 0x00000010,
+ RxDIS = 0x00000008,
+ RxENA = 0x00000004,
+ TxDIS = 0x00000002,
+ TxENA = 0x00000001
+};
+
+enum sis900_configuration_register_bits {
+ DESCRFMT = 0x00000100, /* 7016 specific */
+ REQALG = 0x00000080,
+ SB = 0x00000040,
+ POW = 0x00000020,
+ EXD = 0x00000010,
+ PESEL = 0x00000008,
+ LPM = 0x00000004,
+ BEM = 0x00000001,
+ RND_CNT = 0x00000400,
+ FAIR_BACKOFF = 0x00000200,
+ EDB_MASTER_EN = 0x00002000
+};
+
+enum sis900_eeprom_access_reigster_bits {
+ MDC = 0x00000040,
+ MDDIR = 0x00000020,
+ MDIO = 0x00000010, /* 7016 specific */
+ EECS = 0x00000008,
+ EECLK = 0x00000004,
+ EEDO = 0x00000002,
+ EEDI = 0x00000001
+};
+
+enum sis900_interrupt_register_bits {
+ WKEVT = 0x10000000,
+ TxPAUSEEND = 0x08000000,
+ TxPAUSE = 0x04000000,
+ TxRCMP = 0x02000000,
+ RxRCMP = 0x01000000,
+ DPERR = 0x00800000,
+ SSERR = 0x00400000,
+ RMABT = 0x00200000,
+ RTABT = 0x00100000,
+ RxSOVR = 0x00010000,
+ HIBERR = 0x00008000,
+ SWINT = 0x00001000,
+ MIBINT = 0x00000800,
+ TxURN = 0x00000400,
+ TxIDLE = 0x00000200,
+ TxERR = 0x00000100,
+ TxDESC = 0x00000080,
+ TxOK = 0x00000040,
+ RxORN = 0x00000020,
+ RxIDLE = 0x00000010,
+ RxEARLY = 0x00000008,
+ RxERR = 0x00000004,
+ RxDESC = 0x00000002,
+ RxOK = 0x00000001
+};
+
+enum sis900_interrupt_enable_reigster_bits {
+ IE = 0x00000001
+};
+
+/* maximum dma burst fro transmission and receive*/
+#define MAX_DMA_RANGE 7 /* actually 0 means MAXIMUM !! */
+#define TxMXDMA_shift 20
+#define RxMXDMA_shift 20
+#define TX_DMA_BURST 0
+#define RX_DMA_BURST 0
+
+enum sis900_tx_rx_dma{
+ DMA_BURST_512 = 0, DMA_BURST_64 = 5
+};
+
+/* transmit FIFO threshholds */
+#define TX_FILL_THRESH 16 /* 1/4 FIFO size */
+#define TxFILLT_shift 8
+#define TxDRNT_shift 0
+#define TxDRNT_100 48 /* 3/4 FIFO size */
+#define TxDRNT_10 16 /* 1/2 FIFO size */
+
+enum sis900_transmit_config_register_bits {
+ TxCSI = 0x80000000,
+ TxHBI = 0x40000000,
+ TxMLB = 0x20000000,
+ TxATP = 0x10000000,
+ TxIFG = 0x0C000000,
+ TxFILLT = 0x00003F00,
+ TxDRNT = 0x0000003F
+};
+
+/* recevie FIFO thresholds */
+#define RxDRNT_shift 1
+#define RxDRNT_100 16 /* 1/2 FIFO size */
+#define RxDRNT_10 24 /* 3/4 FIFO size */
+
+enum sis900_reveive_config_register_bits {
+ RxAEP = 0x80000000,
+ RxARP = 0x40000000,
+ RxATX = 0x10000000,
+ RxAJAB = 0x08000000,
+ RxDRNT = 0x0000007F
+};
+
+#define RFAA_shift 28
+#define RFADDR_shift 16
+
+enum sis900_receive_filter_control_register_bits {
+ RFEN = 0x80000000,
+ RFAAB = 0x40000000,
+ RFAAM = 0x20000000,
+ RFAAP = 0x10000000,
+ RFPromiscuous = (RFAAB|RFAAM|RFAAP)
+};
+
+enum sis900_reveive_filter_data_mask {
+ RFDAT = 0x0000FFFF
+};
+
+/* EEPROM Addresses */
+enum sis900_eeprom_address {
+ EEPROMSignature = 0x00,
+ EEPROMVendorID = 0x02,
+ EEPROMDeviceID = 0x03,
+ EEPROMMACAddr = 0x08,
+ EEPROMChecksum = 0x0b
+};
+
+/* The EEPROM commands include the alway-set leading bit. Refer to NM93Cxx datasheet */
+enum sis900_eeprom_command {
+ EEread = 0x0180,
+ EEwrite = 0x0140,
+ EEerase = 0x01C0,
+ EEwriteEnable = 0x0130,
+ EEwriteDisable = 0x0100,
+ EEeraseAll = 0x0120,
+ EEwriteAll = 0x0110,
+ EEaddrMask = 0x013F,
+ EEcmdShift = 16
+};
+/* For SiS962 or SiS963, request the eeprom software access */
+enum sis96x_eeprom_command {
+ EEREQ = 0x00000400, EEDONE = 0x00000200, EEGNT = 0x00000100
+};
+
+/* Manamgement Data I/O (mdio) frame */
+#define MIIread 0x6000
+#define MIIwrite 0x5002
+#define MIIpmdShift 7
+#define MIIregShift 2
+#define MIIcmdLen 16
+#define MIIcmdShift 16
+
+/* Buffer Descriptor Status*/
+enum sis900_buffer_status {
+ OWN = 0x80000000,
+ MORE = 0x40000000,
+ INTR = 0x20000000,
+ SUPCRC = 0x10000000,
+ INCCRC = 0x10000000,
+ OK = 0x08000000,
+ DSIZE = 0x00000FFF
+};
+
+/* Status for TX Buffers */
+enum sis900_tx_buffer_status {
+ ABORT = 0x04000000,
+ UNDERRUN = 0x02000000,
+ NOCARRIER = 0x01000000,
+ DEFERD = 0x00800000,
+ EXCDEFER = 0x00400000,
+ OWCOLL = 0x00200000,
+ EXCCOLL = 0x00100000,
+ COLCNT = 0x000F0000
+};
+
+enum sis900_rx_bufer_status {
+ OVERRUN = 0x02000000,
+ DEST = 0x00800000,
+ BCAST = 0x01800000,
+ MCAST = 0x01000000,
+ UNIMATCH = 0x00800000,
+ TOOLONG = 0x00400000,
+ RUNT = 0x00200000,
+ RXISERR = 0x00100000,
+ CRCERR = 0x00080000,
+ FAERR = 0x00040000,
+ LOOPBK = 0x00020000,
+ RXCOL = 0x00010000
+};
+
+/* MII register offsets */
+enum mii_registers {
+ MII_CONTROL = 0x0000,
+ MII_STATUS = 0x0001,
+ MII_PHY_ID0 = 0x0002,
+ MII_PHY_ID1 = 0x0003,
+ MII_ANADV = 0x0004,
+ MII_ANLPAR = 0x0005,
+ MII_ANEXT = 0x0006
+};
+
+/* mii registers specific to SiS 900 */
+enum sis_mii_registers {
+ MII_CONFIG1 = 0x0010,
+ MII_CONFIG2 = 0x0011,
+ MII_STSOUT = 0x0012,
+ MII_MASK = 0x0013,
+ MII_RESV = 0x0014
+};
+
+/* mii registers specific to AMD 79C901 */
+enum amd_mii_registers {
+ MII_STATUS_SUMMARY = 0x0018
+};
+
+/* mii registers specific to ICS 1893 */
+enum ics_mii_registers {
+ MII_EXTCTRL = 0x0010, MII_QPDSTS = 0x0011, MII_10BTOP = 0x0012,
+ MII_EXTCTRL2 = 0x0013
+};
+
+
+
+/* MII Control register bit definitions. */
+enum mii_control_register_bits {
+ MII_CNTL_FDX = 0x0100,
+ MII_CNTL_RST_AUTO = 0x0200,
+ MII_CNTL_ISOLATE = 0x0400,
+ MII_CNTL_PWRDWN = 0x0800,
+ MII_CNTL_AUTO = 0x1000,
+ MII_CNTL_SPEED = 0x2000,
+ MII_CNTL_LPBK = 0x4000,
+ MII_CNTL_RESET = 0x8000
+};
+
+/* MII Status register bit */
+enum mii_status_register_bits {
+ MII_STAT_EXT = 0x0001,
+ MII_STAT_JAB = 0x0002,
+ MII_STAT_LINK = 0x0004,
+ MII_STAT_CAN_AUTO = 0x0008,
+ MII_STAT_FAULT = 0x0010,
+ MII_STAT_AUTO_DONE = 0x0020,
+ MII_STAT_CAN_T = 0x0800,
+ MII_STAT_CAN_T_FDX = 0x1000,
+ MII_STAT_CAN_TX = 0x2000,
+ MII_STAT_CAN_TX_FDX = 0x4000,
+ MII_STAT_CAN_T4 = 0x8000
+};
+
+#define MII_ID1_OUI_LO 0xFC00 /* low bits of OUI mask */
+#define MII_ID1_MODEL 0x03F0 /* model number */
+#define MII_ID1_REV 0x000F /* model number */
+
+/* MII NWAY Register Bits ...
+ valid for the ANAR (Auto-Negotiation Advertisement) and
+ ANLPAR (Auto-Negotiation Link Partner) registers */
+enum mii_nway_register_bits {
+ MII_NWAY_NODE_SEL = 0x001f,
+ MII_NWAY_CSMA_CD = 0x0001,
+ MII_NWAY_T = 0x0020,
+ MII_NWAY_T_FDX = 0x0040,
+ MII_NWAY_TX = 0x0080,
+ MII_NWAY_TX_FDX = 0x0100,
+ MII_NWAY_T4 = 0x0200,
+ MII_NWAY_PAUSE = 0x0400,
+ MII_NWAY_RF = 0x2000,
+ MII_NWAY_ACK = 0x4000,
+ MII_NWAY_NP = 0x8000
+};
+
+enum mii_stsout_register_bits {
+ MII_STSOUT_LINK_FAIL = 0x4000,
+ MII_STSOUT_SPD = 0x0080,
+ MII_STSOUT_DPLX = 0x0040
+};
+
+enum mii_stsics_register_bits {
+ MII_STSICS_SPD = 0x8000, MII_STSICS_DPLX = 0x4000,
+ MII_STSICS_LINKSTS = 0x0001
+};
+
+enum mii_stssum_register_bits {
+ MII_STSSUM_LINK = 0x0008,
+ MII_STSSUM_DPLX = 0x0004,
+ MII_STSSUM_AUTO = 0x0002,
+ MII_STSSUM_SPD = 0x0001
+};
+
+enum sis900_revision_id {
+ SIS630A_900_REV = 0x80, SIS630E_900_REV = 0x81,
+ SIS630S_900_REV = 0x82, SIS630EA1_900_REV = 0x83,
+ SIS630ET_900_REV = 0x84, SIS635A_900_REV = 0x90,
+ SIS96x_900_REV = 0X91, SIS900B_900_REV = 0x03
+};
+
+enum sis630_revision_id {
+ SIS630A0 = 0x00, SIS630A1 = 0x01,
+ SIS630B0 = 0x10, SIS630B1 = 0x11
+};
+
+#define FDX_CAPABLE_DUPLEX_UNKNOWN 0
+#define FDX_CAPABLE_HALF_SELECTED 1
+#define FDX_CAPABLE_FULL_SELECTED 2
+
+#define HW_SPEED_UNCONFIG 0
+#define HW_SPEED_HOME 1
+#define HW_SPEED_10_MBPS 10
+#define HW_SPEED_100_MBPS 100
+#define HW_SPEED_DEFAULT (HW_SPEED_100_MBPS)
+
+#define CRC_SIZE 4
+#define MAC_HEADER_SIZE 14
+
+#define TX_BUF_SIZE 1536
+#define RX_BUF_SIZE 1536
+
+#define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */
+
+/* Time in ticks before concluding the transmitter is hung. */
+#define TX_TIMEOUT (4*TICKS_PER_SEC)
+
+typedef struct _BufferDesc {
+ u32 link;
+ volatile u32 cmdsts;
+ u32 bufptr;
+} BufferDesc;
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/skeleton.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/skeleton.c
new file mode 100644
index 00000000..6d4fae7f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/skeleton.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/pci.h>
+#include <ipxe/mii.h>
+#include "skeleton.h"
+
+/** @file
+ *
+ * Skeleton network driver
+ *
+ */
+
+/******************************************************************************
+ *
+ * MII interface
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Read from MII register
+ *
+ * @v mii MII interface
+ * @v reg Register address
+ * @ret value Data read, or negative error
+ */
+static int skeleton_mii_read ( struct mii_interface *mii, unsigned int reg ) {
+ struct skeleton_nic *skel =
+ container_of ( mii, struct skeleton_nic, mii );
+
+ DBGC ( skel, "SKELETON %p does not yet support MII read\n", skel );
+ ( void ) reg;
+ return -ENOTSUP;
+}
+
+/**
+ * Write to MII register
+ *
+ * @v mii MII interface
+ * @v reg Register address
+ * @v data Data to write
+ * @ret rc Return status code
+ */
+static int skeleton_mii_write ( struct mii_interface *mii, unsigned int reg,
+ unsigned int data) {
+ struct skeleton_nic *skel =
+ container_of ( mii, struct skeleton_nic, mii );
+
+ DBGC ( skel, "SKELETON %p does not yet support MII write\n", skel );
+ ( void ) reg;
+ ( void ) data;
+ return -ENOTSUP;
+}
+
+/** Skeleton MII operations */
+static struct mii_operations skeleton_mii_operations = {
+ .read = skeleton_mii_read,
+ .write = skeleton_mii_write,
+};
+
+/******************************************************************************
+ *
+ * Device reset
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Reset hardware
+ *
+ * @v skel Skeleton device
+ * @ret rc Return status code
+ */
+static int skeleton_reset ( struct skeleton_nic *skel ) {
+
+ DBGC ( skel, "SKELETON %p does not yet support reset\n", skel );
+ return -ENOTSUP;
+}
+
+/******************************************************************************
+ *
+ * Link state
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Check link state
+ *
+ * @v netdev Network device
+ */
+static void skeleton_check_link ( struct net_device *netdev ) {
+ struct skeleton_nic *skel = netdev->priv;
+
+ DBGC ( skel, "SKELETON %p does not yet support link state\n", skel );
+ netdev_link_err ( netdev, -ENOTSUP );
+}
+
+/******************************************************************************
+ *
+ * Network device interface
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int skeleton_open ( struct net_device *netdev ) {
+ struct skeleton_nic *skel = netdev->priv;
+
+ DBGC ( skel, "SKELETON %p does not yet support open\n", skel );
+ return -ENOTSUP;
+}
+
+/**
+ * Close network device
+ *
+ * @v netdev Network device
+ */
+static void skeleton_close ( struct net_device *netdev ) {
+ struct skeleton_nic *skel = netdev->priv;
+
+ DBGC ( skel, "SKELETON %p does not yet support close\n", skel );
+}
+
+/**
+ * Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int skeleton_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct skeleton_nic *skel = netdev->priv;
+
+ DBGC ( skel, "SKELETON %p does not yet support transmit\n", skel );
+ ( void ) iobuf;
+ return -ENOTSUP;
+}
+
+/**
+ * Poll for completed and received packets
+ *
+ * @v netdev Network device
+ */
+static void skeleton_poll ( struct net_device *netdev ) {
+ struct skeleton_nic *skel = netdev->priv;
+
+ /* Not yet implemented */
+ ( void ) skel;
+}
+
+/**
+ * Enable or disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void skeleton_irq ( struct net_device *netdev, int enable ) {
+ struct skeleton_nic *skel = netdev->priv;
+
+ DBGC ( skel, "SKELETON %p does not yet support interrupts\n", skel );
+ ( void ) enable;
+}
+
+/** Skeleton network device operations */
+static struct net_device_operations skeleton_operations = {
+ .open = skeleton_open,
+ .close = skeleton_close,
+ .transmit = skeleton_transmit,
+ .poll = skeleton_poll,
+ .irq = skeleton_irq,
+};
+
+/******************************************************************************
+ *
+ * PCI interface
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @ret rc Return status code
+ */
+static int skeleton_probe ( struct pci_device *pci ) {
+ struct net_device *netdev;
+ struct skeleton_nic *skel;
+ int rc;
+
+ /* Allocate and initialise net device */
+ netdev = alloc_etherdev ( sizeof ( *skel ) );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ netdev_init ( netdev, &skeleton_operations );
+ skel = netdev->priv;
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+ memset ( skel, 0, sizeof ( *skel ) );
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* Map registers */
+ skel->regs = ioremap ( pci->membase, SKELETON_BAR_SIZE );
+
+ /* Reset the NIC */
+ if ( ( rc = skeleton_reset ( skel ) ) != 0 )
+ goto err_reset;
+
+ /* Initialise and reset MII interface */
+ mii_init ( &skel->mii, &skeleton_mii_operations );
+ if ( ( rc = mii_reset ( &skel->mii ) ) != 0 ) {
+ DBGC ( skel, "SKELETON %p could not reset MII: %s\n",
+ skel, strerror ( rc ) );
+ goto err_mii_reset;
+ }
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register_netdev;
+
+ /* Set initial link state */
+ skeleton_check_link ( netdev );
+
+ return 0;
+
+ unregister_netdev ( netdev );
+ err_register_netdev:
+ err_mii_reset:
+ skeleton_reset ( skel );
+ err_reset:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void skeleton_remove ( struct pci_device *pci ) {
+ struct net_device *netdev = pci_get_drvdata ( pci );
+ struct skeleton_nic *skel = netdev->priv;
+
+ /* Unregister network device */
+ unregister_netdev ( netdev );
+
+ /* Reset card */
+ skeleton_reset ( skel );
+
+ /* Free network device */
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/** Skeleton PCI device IDs */
+static struct pci_device_id skeleton_nics[] = {
+ PCI_ROM ( 0x5ce1, 0x5ce1, "skel", "Skeleton", 0 ),
+};
+
+/** Skeleton PCI driver */
+struct pci_driver skeleton_driver __pci_driver = {
+ .ids = skeleton_nics,
+ .id_count = ( sizeof ( skeleton_nics ) / sizeof ( skeleton_nics[0] ) ),
+ .probe = skeleton_probe,
+ .remove = skeleton_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/skeleton.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/skeleton.h
new file mode 100644
index 00000000..3de2afa5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/skeleton.h
@@ -0,0 +1,23 @@
+#ifndef _SKELETON_H
+#define _SKELETON_H
+
+/** @file
+ *
+ * Skeleton network driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** Skeleton BAR size */
+#define SKELETON_BAR_SIZE 256
+
+/** A skeleton network card */
+struct skeleton_nic {
+ /** Registers */
+ void *regs;
+ /** MII interface */
+ struct mii_interface mii;
+};
+
+#endif /* _SKELETON_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/skge.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/skge.c
new file mode 100644
index 00000000..fea33841
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/skge.c
@@ -0,0 +1,2468 @@
+/*
+ * iPXE driver for Marvell Yukon chipset and SysKonnect Gigabit
+ * Ethernet adapters. Derived from Linux skge driver (v1.13), which was
+ * based on earlier sk98lin, e100 and FreeBSD if_sk drivers.
+ *
+ * This driver intentionally does not support all the features of the
+ * original driver such as link fail-over and link management because
+ * those should be done at higher levels.
+ *
+ * Copyright (C) 2004, 2005 Stephen Hemminger <shemminger@osdl.org>
+ *
+ * Modified for iPXE, July 2008 by Michael Decker <mrd999@gmail.com>
+ * Tested and Modified in December 2009 by
+ * Thomas Miletich <thomas.miletich@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include <stdint.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/pci.h>
+
+#include "skge.h"
+
+static struct pci_device_id skge_id_table[] = {
+ PCI_ROM(0x10b7, 0x1700, "3C940", "3COM 3C940", 0),
+ PCI_ROM(0x10b7, 0x80eb, "3C940B", "3COM 3C940", 0),
+ PCI_ROM(0x1148, 0x4300, "GE", "Syskonnect GE", 0),
+ PCI_ROM(0x1148, 0x4320, "YU", "Syskonnect YU", 0),
+ PCI_ROM(0x1186, 0x4C00, "DGE510T", "DLink DGE-510T", 0),
+ PCI_ROM(0x1186, 0x4b01, "DGE530T", "DLink DGE-530T", 0),
+ PCI_ROM(0x11ab, 0x4320, "id4320", "Marvell id4320", 0),
+ PCI_ROM(0x11ab, 0x5005, "id5005", "Marvell id5005", 0), /* Belkin */
+ PCI_ROM(0x1371, 0x434e, "Gigacard", "CNET Gigacard", 0),
+ PCI_ROM(0x1737, 0x1064, "EG1064", "Linksys EG1064", 0),
+ PCI_ROM(0x1737, 0xffff, "id_any", "Linksys [any]", 0)
+};
+
+static int skge_up(struct net_device *dev);
+static void skge_down(struct net_device *dev);
+static void skge_tx_clean(struct net_device *dev);
+static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
+static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
+static void yukon_init(struct skge_hw *hw, int port);
+static void genesis_mac_init(struct skge_hw *hw, int port);
+static void genesis_link_up(struct skge_port *skge);
+
+static void skge_phyirq(struct skge_hw *hw);
+static void skge_poll(struct net_device *dev);
+static int skge_xmit_frame(struct net_device *dev, struct io_buffer *iob);
+static void skge_net_irq ( struct net_device *dev, int enable );
+
+static void skge_rx_refill(struct net_device *dev);
+
+static struct net_device_operations skge_operations = {
+ .open = skge_up,
+ .close = skge_down,
+ .transmit = skge_xmit_frame,
+ .poll = skge_poll,
+ .irq = skge_net_irq
+};
+
+/* Avoid conditionals by using array */
+static const int txqaddr[] = { Q_XA1, Q_XA2 };
+static const int rxqaddr[] = { Q_R1, Q_R2 };
+static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
+static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
+static const u32 napimask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F };
+static const u32 portmask[] = { IS_PORT_1, IS_PORT_2 };
+
+/* Determine supported/advertised modes based on hardware.
+ * Note: ethtool ADVERTISED_xxx == SUPPORTED_xxx
+ */
+static u32 skge_supported_modes(const struct skge_hw *hw)
+{
+ u32 supported;
+
+ if (hw->copper) {
+ supported = SUPPORTED_10baseT_Half
+ | SUPPORTED_10baseT_Full
+ | SUPPORTED_100baseT_Half
+ | SUPPORTED_100baseT_Full
+ | SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full
+ | SUPPORTED_Autoneg| SUPPORTED_TP;
+
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ supported &= ~(SUPPORTED_10baseT_Half
+ | SUPPORTED_10baseT_Full
+ | SUPPORTED_100baseT_Half
+ | SUPPORTED_100baseT_Full);
+
+ else if (hw->chip_id == CHIP_ID_YUKON)
+ supported &= ~SUPPORTED_1000baseT_Half;
+ } else
+ supported = SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half
+ | SUPPORTED_FIBRE | SUPPORTED_Autoneg;
+
+ return supported;
+}
+
+/* Chip internal frequency for clock calculations */
+static inline u32 hwkhz(const struct skge_hw *hw)
+{
+ return (hw->chip_id == CHIP_ID_GENESIS) ? 53125 : 78125;
+}
+
+/* Microseconds to chip HZ */
+static inline u32 skge_usecs2clk(const struct skge_hw *hw, u32 usec)
+{
+ return hwkhz(hw) * usec / 1000;
+}
+
+enum led_mode { LED_MODE_OFF, LED_MODE_ON, LED_MODE_TST };
+static void skge_led(struct skge_port *skge, enum led_mode mode)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ if (hw->chip_id == CHIP_ID_GENESIS) {
+ switch (mode) {
+ case LED_MODE_OFF:
+ if (hw->phy_type == SK_PHY_BCOM)
+ xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+ else {
+ skge_write32(hw, SK_REG(port, TX_LED_VAL), 0);
+ skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_T_OFF);
+ }
+ skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
+ skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
+ skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
+ break;
+
+ case LED_MODE_ON:
+ skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
+ skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON);
+
+ skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
+ skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
+
+ break;
+
+ case LED_MODE_TST:
+ skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON);
+ skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
+ skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
+
+ if (hw->phy_type == SK_PHY_BCOM)
+ xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
+ else {
+ skge_write8(hw, SK_REG(port, TX_LED_TST), LED_T_ON);
+ skge_write32(hw, SK_REG(port, TX_LED_VAL), 100);
+ skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
+ }
+
+ }
+ } else {
+ switch (mode) {
+ case LED_MODE_OFF:
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ PHY_M_LED_MO_DUP(MO_LED_OFF) |
+ PHY_M_LED_MO_10(MO_LED_OFF) |
+ PHY_M_LED_MO_100(MO_LED_OFF) |
+ PHY_M_LED_MO_1000(MO_LED_OFF) |
+ PHY_M_LED_MO_RX(MO_LED_OFF));
+ break;
+ case LED_MODE_ON:
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL,
+ PHY_M_LED_PULS_DUR(PULS_170MS) |
+ PHY_M_LED_BLINK_RT(BLINK_84MS) |
+ PHY_M_LEDC_TX_CTRL |
+ PHY_M_LEDC_DP_CTRL);
+
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ PHY_M_LED_MO_RX(MO_LED_OFF) |
+ (skge->speed == SPEED_100 ?
+ PHY_M_LED_MO_100(MO_LED_ON) : 0));
+ break;
+ case LED_MODE_TST:
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ PHY_M_LED_MO_DUP(MO_LED_ON) |
+ PHY_M_LED_MO_10(MO_LED_ON) |
+ PHY_M_LED_MO_100(MO_LED_ON) |
+ PHY_M_LED_MO_1000(MO_LED_ON) |
+ PHY_M_LED_MO_RX(MO_LED_ON));
+ }
+ }
+}
+
+/*
+ * I've left in these EEPROM and VPD functions, as someone may desire to
+ * integrate them in the future. -mdeck
+ *
+ * static int skge_get_eeprom_len(struct net_device *dev)
+ * {
+ * struct skge_port *skge = netdev_priv(dev);
+ * u32 reg2;
+ *
+ * pci_read_config_dword(skge->hw->pdev, PCI_DEV_REG2, &reg2);
+ * return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
+ * }
+ *
+ * static u32 skge_vpd_read(struct pci_dev *pdev, int cap, u16 offset)
+ * {
+ * u32 val;
+ *
+ * pci_write_config_word(pdev, cap + PCI_VPD_ADDR, offset);
+ *
+ * do {
+ * pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset);
+ * } while (!(offset & PCI_VPD_ADDR_F));
+ *
+ * pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &val);
+ * return val;
+ * }
+ *
+ * static void skge_vpd_write(struct pci_dev *pdev, int cap, u16 offset, u32 val)
+ * {
+ * pci_write_config_dword(pdev, cap + PCI_VPD_DATA, val);
+ * pci_write_config_word(pdev, cap + PCI_VPD_ADDR,
+ * offset | PCI_VPD_ADDR_F);
+ *
+ * do {
+ * pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset);
+ * } while (offset & PCI_VPD_ADDR_F);
+ * }
+ *
+ * static int skge_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+ * u8 *data)
+ * {
+ * struct skge_port *skge = netdev_priv(dev);
+ * struct pci_dev *pdev = skge->hw->pdev;
+ * int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD);
+ * int length = eeprom->len;
+ * u16 offset = eeprom->offset;
+ *
+ * if (!cap)
+ * return -EINVAL;
+ *
+ * eeprom->magic = SKGE_EEPROM_MAGIC;
+ *
+ * while (length > 0) {
+ * u32 val = skge_vpd_read(pdev, cap, offset);
+ * int n = min_t(int, length, sizeof(val));
+ *
+ * memcpy(data, &val, n);
+ * length -= n;
+ * data += n;
+ * offset += n;
+ * }
+ * return 0;
+ * }
+ *
+ * static int skge_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+ * u8 *data)
+ * {
+ * struct skge_port *skge = netdev_priv(dev);
+ * struct pci_dev *pdev = skge->hw->pdev;
+ * int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD);
+ * int length = eeprom->len;
+ * u16 offset = eeprom->offset;
+ *
+ * if (!cap)
+ * return -EINVAL;
+ *
+ * if (eeprom->magic != SKGE_EEPROM_MAGIC)
+ * return -EINVAL;
+ *
+ * while (length > 0) {
+ * u32 val;
+ * int n = min_t(int, length, sizeof(val));
+ *
+ * if (n < sizeof(val))
+ * val = skge_vpd_read(pdev, cap, offset);
+ * memcpy(&val, data, n);
+ *
+ * skge_vpd_write(pdev, cap, offset, val);
+ *
+ * length -= n;
+ * data += n;
+ * offset += n;
+ * }
+ * return 0;
+ * }
+ */
+
+/*
+ * Allocate ring elements and chain them together
+ * One-to-one association of board descriptors with ring elements
+ */
+static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base,
+ size_t num)
+{
+ struct skge_tx_desc *d;
+ struct skge_element *e;
+ unsigned int i;
+
+ ring->start = zalloc(num*sizeof(*e));
+ if (!ring->start)
+ return -ENOMEM;
+
+ for (i = 0, e = ring->start, d = vaddr; i < num; i++, e++, d++) {
+ e->desc = d;
+ if (i == num - 1) {
+ e->next = ring->start;
+ d->next_offset = base;
+ } else {
+ e->next = e + 1;
+ d->next_offset = base + (i+1) * sizeof(*d);
+ }
+ }
+ ring->to_use = ring->to_clean = ring->start;
+
+ return 0;
+}
+
+/* Allocate and setup a new buffer for receiving */
+static void skge_rx_setup(struct skge_port *skge __unused,
+ struct skge_element *e,
+ struct io_buffer *iob, unsigned int bufsize)
+{
+ struct skge_rx_desc *rd = e->desc;
+ u64 map;
+
+ map = ( iob != NULL ) ? virt_to_bus(iob->data) : 0;
+
+ rd->dma_lo = map;
+ rd->dma_hi = map >> 32;
+ e->iob = iob;
+ rd->csum1_start = ETH_HLEN;
+ rd->csum2_start = ETH_HLEN;
+ rd->csum1 = 0;
+ rd->csum2 = 0;
+
+ wmb();
+
+ rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize;
+}
+
+/* Resume receiving using existing skb,
+ * Note: DMA address is not changed by chip.
+ * MTU not changed while receiver active.
+ */
+static inline void skge_rx_reuse(struct skge_element *e, unsigned int size)
+{
+ struct skge_rx_desc *rd = e->desc;
+
+ rd->csum2 = 0;
+ rd->csum2_start = ETH_HLEN;
+
+ wmb();
+
+ rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | size;
+}
+
+
+/* Free all buffers in receive ring, assumes receiver stopped */
+static void skge_rx_clean(struct skge_port *skge)
+{
+ struct skge_ring *ring = &skge->rx_ring;
+ struct skge_element *e;
+
+ e = ring->start;
+ do {
+ struct skge_rx_desc *rd = e->desc;
+ rd->control = 0;
+ if (e->iob) {
+ free_iob(e->iob);
+ e->iob = NULL;
+ }
+ } while ((e = e->next) != ring->start);
+}
+
+static void skge_link_up(struct skge_port *skge)
+{
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
+ LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
+
+ netdev_link_up(skge->netdev);
+
+ DBG2(PFX "%s: Link is up at %d Mbps, %s duplex\n",
+ skge->netdev->name, skge->speed,
+ skge->duplex == DUPLEX_FULL ? "full" : "half");
+}
+
+static void skge_link_down(struct skge_port *skge)
+{
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+ netdev_link_down(skge->netdev);
+
+ DBG2(PFX "%s: Link is down.\n", skge->netdev->name);
+}
+
+
+static void xm_link_down(struct skge_hw *hw, int port)
+{
+ struct net_device *dev = hw->dev[port];
+ struct skge_port *skge = netdev_priv(dev);
+
+ xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE);
+
+ if (netdev_link_ok(dev))
+ skge_link_down(skge);
+}
+
+static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
+{
+ int i;
+
+ xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
+ *val = xm_read16(hw, port, XM_PHY_DATA);
+
+ if (hw->phy_type == SK_PHY_XMAC)
+ goto ready;
+
+ for (i = 0; i < PHY_RETRIES; i++) {
+ if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY)
+ goto ready;
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+ ready:
+ *val = xm_read16(hw, port, XM_PHY_DATA);
+
+ return 0;
+}
+
+static u16 xm_phy_read(struct skge_hw *hw, int port, u16 reg)
+{
+ u16 v = 0;
+ if (__xm_phy_read(hw, port, reg, &v))
+ DBG(PFX "%s: phy read timed out\n",
+ hw->dev[port]->name);
+ return v;
+}
+
+static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
+{
+ int i;
+
+ xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
+ for (i = 0; i < PHY_RETRIES; i++) {
+ if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
+ goto ready;
+ udelay(1);
+ }
+ return -EIO;
+
+ ready:
+ xm_write16(hw, port, XM_PHY_DATA, val);
+ for (i = 0; i < PHY_RETRIES; i++) {
+ if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
+ return 0;
+ udelay(1);
+ }
+ return -ETIMEDOUT;
+}
+
+static void genesis_init(struct skge_hw *hw)
+{
+ /* set blink source counter */
+ skge_write32(hw, B2_BSC_INI, (SK_BLK_DUR * SK_FACT_53) / 100);
+ skge_write8(hw, B2_BSC_CTRL, BSC_START);
+
+ /* configure mac arbiter */
+ skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR);
+
+ /* configure mac arbiter timeout values */
+ skge_write8(hw, B3_MA_TOINI_RX1, SK_MAC_TO_53);
+ skge_write8(hw, B3_MA_TOINI_RX2, SK_MAC_TO_53);
+ skge_write8(hw, B3_MA_TOINI_TX1, SK_MAC_TO_53);
+ skge_write8(hw, B3_MA_TOINI_TX2, SK_MAC_TO_53);
+
+ skge_write8(hw, B3_MA_RCINI_RX1, 0);
+ skge_write8(hw, B3_MA_RCINI_RX2, 0);
+ skge_write8(hw, B3_MA_RCINI_TX1, 0);
+ skge_write8(hw, B3_MA_RCINI_TX2, 0);
+
+ /* configure packet arbiter timeout */
+ skge_write16(hw, B3_PA_CTRL, PA_RST_CLR);
+ skge_write16(hw, B3_PA_TOINI_RX1, SK_PKT_TO_MAX);
+ skge_write16(hw, B3_PA_TOINI_TX1, SK_PKT_TO_MAX);
+ skge_write16(hw, B3_PA_TOINI_RX2, SK_PKT_TO_MAX);
+ skge_write16(hw, B3_PA_TOINI_TX2, SK_PKT_TO_MAX);
+}
+
+static void genesis_reset(struct skge_hw *hw, int port)
+{
+ const u8 zero[8] = { 0 };
+ u32 reg;
+
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+
+ /* reset the statistics module */
+ xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
+ xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE);
+ xm_write32(hw, port, XM_MODE, 0); /* clear Mode Reg */
+ xm_write16(hw, port, XM_TX_CMD, 0); /* reset TX CMD Reg */
+ xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */
+
+ /* disable Broadcom PHY IRQ */
+ if (hw->phy_type == SK_PHY_BCOM)
+ xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
+
+ xm_outhash(hw, port, XM_HSM, zero);
+
+ /* Flush TX and RX fifo */
+ reg = xm_read32(hw, port, XM_MODE);
+ xm_write32(hw, port, XM_MODE, reg | XM_MD_FTF);
+ xm_write32(hw, port, XM_MODE, reg | XM_MD_FRF);
+}
+
+
+/* Convert mode to MII values */
+static const u16 phy_pause_map[] = {
+ [FLOW_MODE_NONE] = 0,
+ [FLOW_MODE_LOC_SEND] = PHY_AN_PAUSE_ASYM,
+ [FLOW_MODE_SYMMETRIC] = PHY_AN_PAUSE_CAP,
+ [FLOW_MODE_SYM_OR_REM] = PHY_AN_PAUSE_CAP | PHY_AN_PAUSE_ASYM,
+};
+
+/* special defines for FIBER (88E1011S only) */
+static const u16 fiber_pause_map[] = {
+ [FLOW_MODE_NONE] = PHY_X_P_NO_PAUSE,
+ [FLOW_MODE_LOC_SEND] = PHY_X_P_ASYM_MD,
+ [FLOW_MODE_SYMMETRIC] = PHY_X_P_SYM_MD,
+ [FLOW_MODE_SYM_OR_REM] = PHY_X_P_BOTH_MD,
+};
+
+
+/* Check status of Broadcom phy link */
+static void bcom_check_link(struct skge_hw *hw, int port)
+{
+ struct net_device *dev = hw->dev[port];
+ struct skge_port *skge = netdev_priv(dev);
+ u16 status;
+
+ /* read twice because of latch */
+ xm_phy_read(hw, port, PHY_BCOM_STAT);
+ status = xm_phy_read(hw, port, PHY_BCOM_STAT);
+
+ if ((status & PHY_ST_LSYNC) == 0) {
+ xm_link_down(hw, port);
+ return;
+ }
+
+ if (skge->autoneg == AUTONEG_ENABLE) {
+ u16 lpa, aux;
+
+ if (!(status & PHY_ST_AN_OVER))
+ return;
+
+ lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP);
+ if (lpa & PHY_B_AN_RF) {
+ DBG(PFX "%s: remote fault\n",
+ dev->name);
+ return;
+ }
+
+ aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT);
+
+ /* Check Duplex mismatch */
+ switch (aux & PHY_B_AS_AN_RES_MSK) {
+ case PHY_B_RES_1000FD:
+ skge->duplex = DUPLEX_FULL;
+ break;
+ case PHY_B_RES_1000HD:
+ skge->duplex = DUPLEX_HALF;
+ break;
+ default:
+ DBG(PFX "%s: duplex mismatch\n",
+ dev->name);
+ return;
+ }
+
+ /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+ switch (aux & PHY_B_AS_PAUSE_MSK) {
+ case PHY_B_AS_PAUSE_MSK:
+ skge->flow_status = FLOW_STAT_SYMMETRIC;
+ break;
+ case PHY_B_AS_PRR:
+ skge->flow_status = FLOW_STAT_REM_SEND;
+ break;
+ case PHY_B_AS_PRT:
+ skge->flow_status = FLOW_STAT_LOC_SEND;
+ break;
+ default:
+ skge->flow_status = FLOW_STAT_NONE;
+ }
+ skge->speed = SPEED_1000;
+ }
+
+ if (!netdev_link_ok(dev))
+ genesis_link_up(skge);
+}
+
+/* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional
+ * Phy on for 100 or 10Mbit operation
+ */
+static void bcom_phy_init(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ unsigned int i;
+ u16 id1, r, ext, ctl;
+
+ /* magic workaround patterns for Broadcom */
+ static const struct {
+ u16 reg;
+ u16 val;
+ } A1hack[] = {
+ { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 },
+ { 0x17, 0x0013 }, { 0x15, 0x0404 }, { 0x17, 0x8006 },
+ { 0x15, 0x0132 }, { 0x17, 0x8006 }, { 0x15, 0x0232 },
+ { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
+ }, C0hack[] = {
+ { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 },
+ { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 },
+ };
+
+ /* read Id from external PHY (all have the same address) */
+ id1 = xm_phy_read(hw, port, PHY_XMAC_ID1);
+
+ /* Optimize MDIO transfer by suppressing preamble. */
+ r = xm_read16(hw, port, XM_MMU_CMD);
+ r |= XM_MMU_NO_PRE;
+ xm_write16(hw, port, XM_MMU_CMD,r);
+
+ switch (id1) {
+ case PHY_BCOM_ID1_C0:
+ /*
+ * Workaround BCOM Errata for the C0 type.
+ * Write magic patterns to reserved registers.
+ */
+ for (i = 0; i < ARRAY_SIZE(C0hack); i++)
+ xm_phy_write(hw, port,
+ C0hack[i].reg, C0hack[i].val);
+
+ break;
+ case PHY_BCOM_ID1_A1:
+ /*
+ * Workaround BCOM Errata for the A1 type.
+ * Write magic patterns to reserved registers.
+ */
+ for (i = 0; i < ARRAY_SIZE(A1hack); i++)
+ xm_phy_write(hw, port,
+ A1hack[i].reg, A1hack[i].val);
+ break;
+ }
+
+ /*
+ * Workaround BCOM Errata (#10523) for all BCom PHYs.
+ * Disable Power Management after reset.
+ */
+ r = xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL);
+ r |= PHY_B_AC_DIS_PM;
+ xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, r);
+
+ /* Dummy read */
+ xm_read16(hw, port, XM_ISRC);
+
+ ext = PHY_B_PEC_EN_LTR; /* enable tx led */
+ ctl = PHY_CT_SP1000; /* always 1000mbit */
+
+ if (skge->autoneg == AUTONEG_ENABLE) {
+ /*
+ * Workaround BCOM Errata #1 for the C5 type.
+ * 1000Base-T Link Acquisition Failure in Slave Mode
+ * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
+ */
+ u16 adv = PHY_B_1000C_RD;
+ if (skge->advertising & ADVERTISED_1000baseT_Half)
+ adv |= PHY_B_1000C_AHD;
+ if (skge->advertising & ADVERTISED_1000baseT_Full)
+ adv |= PHY_B_1000C_AFD;
+ xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, adv);
+
+ ctl |= PHY_CT_ANE | PHY_CT_RE_CFG;
+ } else {
+ if (skge->duplex == DUPLEX_FULL)
+ ctl |= PHY_CT_DUP_MD;
+ /* Force to slave */
+ xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, PHY_B_1000C_MSE);
+ }
+
+ /* Set autonegotiation pause parameters */
+ xm_phy_write(hw, port, PHY_BCOM_AUNE_ADV,
+ phy_pause_map[skge->flow_control] | PHY_AN_CSMA);
+
+ xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ext);
+ xm_phy_write(hw, port, PHY_BCOM_CTRL, ctl);
+
+ /* Use link status change interrupt */
+ xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+}
+
+static void xm_phy_init(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ u16 ctrl = 0;
+
+ if (skge->autoneg == AUTONEG_ENABLE) {
+ if (skge->advertising & ADVERTISED_1000baseT_Half)
+ ctrl |= PHY_X_AN_HD;
+ if (skge->advertising & ADVERTISED_1000baseT_Full)
+ ctrl |= PHY_X_AN_FD;
+
+ ctrl |= fiber_pause_map[skge->flow_control];
+
+ xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl);
+
+ /* Restart Auto-negotiation */
+ ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
+ } else {
+ /* Set DuplexMode in Config register */
+ if (skge->duplex == DUPLEX_FULL)
+ ctrl |= PHY_CT_DUP_MD;
+ /*
+ * Do NOT enable Auto-negotiation here. This would hold
+ * the link down because no IDLEs are transmitted
+ */
+ }
+
+ xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl);
+
+ /* Poll PHY for status changes */
+ skge->use_xm_link_timer = 1;
+}
+
+static int xm_check_link(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ u16 status;
+
+ /* read twice because of latch */
+ xm_phy_read(hw, port, PHY_XMAC_STAT);
+ status = xm_phy_read(hw, port, PHY_XMAC_STAT);
+
+ if ((status & PHY_ST_LSYNC) == 0) {
+ xm_link_down(hw, port);
+ return 0;
+ }
+
+ if (skge->autoneg == AUTONEG_ENABLE) {
+ u16 lpa, res;
+
+ if (!(status & PHY_ST_AN_OVER))
+ return 0;
+
+ lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP);
+ if (lpa & PHY_B_AN_RF) {
+ DBG(PFX "%s: remote fault\n",
+ dev->name);
+ return 0;
+ }
+
+ res = xm_phy_read(hw, port, PHY_XMAC_RES_ABI);
+
+ /* Check Duplex mismatch */
+ switch (res & (PHY_X_RS_HD | PHY_X_RS_FD)) {
+ case PHY_X_RS_FD:
+ skge->duplex = DUPLEX_FULL;
+ break;
+ case PHY_X_RS_HD:
+ skge->duplex = DUPLEX_HALF;
+ break;
+ default:
+ DBG(PFX "%s: duplex mismatch\n",
+ dev->name);
+ return 0;
+ }
+
+ /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+ if ((skge->flow_control == FLOW_MODE_SYMMETRIC ||
+ skge->flow_control == FLOW_MODE_SYM_OR_REM) &&
+ (lpa & PHY_X_P_SYM_MD))
+ skge->flow_status = FLOW_STAT_SYMMETRIC;
+ else if (skge->flow_control == FLOW_MODE_SYM_OR_REM &&
+ (lpa & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD)
+ /* Enable PAUSE receive, disable PAUSE transmit */
+ skge->flow_status = FLOW_STAT_REM_SEND;
+ else if (skge->flow_control == FLOW_MODE_LOC_SEND &&
+ (lpa & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD)
+ /* Disable PAUSE receive, enable PAUSE transmit */
+ skge->flow_status = FLOW_STAT_LOC_SEND;
+ else
+ skge->flow_status = FLOW_STAT_NONE;
+
+ skge->speed = SPEED_1000;
+ }
+
+ if (!netdev_link_ok(dev))
+ genesis_link_up(skge);
+ return 1;
+}
+
+/* Poll to check for link coming up.
+ *
+ * Since internal PHY is wired to a level triggered pin, can't
+ * get an interrupt when carrier is detected, need to poll for
+ * link coming up.
+ */
+static void xm_link_timer(struct skge_port *skge)
+{
+ struct net_device *dev = skge->netdev;
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ int i;
+
+ /*
+ * Verify that the link by checking GPIO register three times.
+ * This pin has the signal from the link_sync pin connected to it.
+ */
+ for (i = 0; i < 3; i++) {
+ if (xm_read16(hw, port, XM_GP_PORT) & XM_GP_INP_ASS)
+ return;
+ }
+
+ /* Re-enable interrupt to detect link down */
+ if (xm_check_link(dev)) {
+ u16 msk = xm_read16(hw, port, XM_IMSK);
+ msk &= ~XM_IS_INP_ASS;
+ xm_write16(hw, port, XM_IMSK, msk);
+ xm_read16(hw, port, XM_ISRC);
+ }
+}
+
+static void genesis_mac_init(struct skge_hw *hw, int port)
+{
+ struct net_device *dev = hw->dev[port];
+ struct skge_port *skge = netdev_priv(dev);
+ int i;
+ u32 r;
+ const u8 zero[6] = { 0 };
+
+ for (i = 0; i < 10; i++) {
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1),
+ MFF_SET_MAC_RST);
+ if (skge_read16(hw, SK_REG(port, TX_MFF_CTRL1)) & MFF_SET_MAC_RST)
+ goto reset_ok;
+ udelay(1);
+ }
+
+ DBG(PFX "%s: genesis reset failed\n", dev->name);
+
+ reset_ok:
+ /* Unreset the XMAC. */
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+
+ /*
+ * Perform additional initialization for external PHYs,
+ * namely for the 1000baseTX cards that use the XMAC's
+ * GMII mode.
+ */
+ if (hw->phy_type != SK_PHY_XMAC) {
+ /* Take external Phy out of reset */
+ r = skge_read32(hw, B2_GP_IO);
+ if (port == 0)
+ r |= GP_DIR_0|GP_IO_0;
+ else
+ r |= GP_DIR_2|GP_IO_2;
+
+ skge_write32(hw, B2_GP_IO, r);
+
+ /* Enable GMII interface */
+ xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
+ }
+
+
+ switch(hw->phy_type) {
+ case SK_PHY_XMAC:
+ xm_phy_init(skge);
+ break;
+ case SK_PHY_BCOM:
+ bcom_phy_init(skge);
+ bcom_check_link(hw, port);
+ }
+
+ /* Set Station Address */
+ xm_outaddr(hw, port, XM_SA, dev->ll_addr);
+
+ /* We don't use match addresses so clear */
+ for (i = 1; i < 16; i++)
+ xm_outaddr(hw, port, XM_EXM(i), zero);
+
+ /* Clear MIB counters */
+ xm_write16(hw, port, XM_STAT_CMD,
+ XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+ /* Clear two times according to Errata #3 */
+ xm_write16(hw, port, XM_STAT_CMD,
+ XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+
+ /* configure Rx High Water Mark (XM_RX_HI_WM) */
+ xm_write16(hw, port, XM_RX_HI_WM, 1450);
+
+ /* We don't need the FCS appended to the packet. */
+ r = XM_RX_LENERR_OK | XM_RX_STRIP_FCS;
+
+ if (skge->duplex == DUPLEX_HALF) {
+ /*
+ * If in manual half duplex mode the other side might be in
+ * full duplex mode, so ignore if a carrier extension is not seen
+ * on frames received
+ */
+ r |= XM_RX_DIS_CEXT;
+ }
+ xm_write16(hw, port, XM_RX_CMD, r);
+
+ /* We want short frames padded to 60 bytes. */
+ xm_write16(hw, port, XM_TX_CMD, XM_TX_AUTO_PAD);
+
+ xm_write16(hw, port, XM_TX_THR, 512);
+
+ /*
+ * Enable the reception of all error frames. This is is
+ * a necessary evil due to the design of the XMAC. The
+ * XMAC's receive FIFO is only 8K in size, however jumbo
+ * frames can be up to 9000 bytes in length. When bad
+ * frame filtering is enabled, the XMAC's RX FIFO operates
+ * in 'store and forward' mode. For this to work, the
+ * entire frame has to fit into the FIFO, but that means
+ * that jumbo frames larger than 8192 bytes will be
+ * truncated. Disabling all bad frame filtering causes
+ * the RX FIFO to operate in streaming mode, in which
+ * case the XMAC will start transferring frames out of the
+ * RX FIFO as soon as the FIFO threshold is reached.
+ */
+ xm_write32(hw, port, XM_MODE, XM_DEF_MODE);
+
+
+ /*
+ * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
+ * - Enable all bits excepting 'Octets Rx OK Low CntOv'
+ * and 'Octets Rx OK Hi Cnt Ov'.
+ */
+ xm_write32(hw, port, XM_RX_EV_MSK, XMR_DEF_MSK);
+
+ /*
+ * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
+ * - Enable all bits excepting 'Octets Tx OK Low CntOv'
+ * and 'Octets Tx OK Hi Cnt Ov'.
+ */
+ xm_write32(hw, port, XM_TX_EV_MSK, XMT_DEF_MSK);
+
+ /* Configure MAC arbiter */
+ skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR);
+
+ /* configure timeout values */
+ skge_write8(hw, B3_MA_TOINI_RX1, 72);
+ skge_write8(hw, B3_MA_TOINI_RX2, 72);
+ skge_write8(hw, B3_MA_TOINI_TX1, 72);
+ skge_write8(hw, B3_MA_TOINI_TX2, 72);
+
+ skge_write8(hw, B3_MA_RCINI_RX1, 0);
+ skge_write8(hw, B3_MA_RCINI_RX2, 0);
+ skge_write8(hw, B3_MA_RCINI_TX1, 0);
+ skge_write8(hw, B3_MA_RCINI_TX2, 0);
+
+ /* Configure Rx MAC FIFO */
+ skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_CLR);
+ skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_TIM_PAT);
+ skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
+
+ /* Configure Tx MAC FIFO */
+ skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_CLR);
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
+ skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
+
+ /* enable timeout timers */
+ skge_write16(hw, B3_PA_CTRL,
+ (port == 0) ? PA_ENA_TO_TX1 : PA_ENA_TO_TX2);
+}
+
+static void genesis_stop(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ unsigned retries = 1000;
+ u16 cmd;
+
+ /* Disable Tx and Rx */
+ cmd = xm_read16(hw, port, XM_MMU_CMD);
+ cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+ xm_write16(hw, port, XM_MMU_CMD, cmd);
+
+ genesis_reset(hw, port);
+
+ /* Clear Tx packet arbiter timeout IRQ */
+ skge_write16(hw, B3_PA_CTRL,
+ port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
+
+ /* Reset the MAC */
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+ do {
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
+ if (!(skge_read16(hw, SK_REG(port, TX_MFF_CTRL1)) & MFF_SET_MAC_RST))
+ break;
+ } while (--retries > 0);
+
+ /* For external PHYs there must be special handling */
+ if (hw->phy_type != SK_PHY_XMAC) {
+ u32 reg = skge_read32(hw, B2_GP_IO);
+ if (port == 0) {
+ reg |= GP_DIR_0;
+ reg &= ~GP_IO_0;
+ } else {
+ reg |= GP_DIR_2;
+ reg &= ~GP_IO_2;
+ }
+ skge_write32(hw, B2_GP_IO, reg);
+ skge_read32(hw, B2_GP_IO);
+ }
+
+ xm_write16(hw, port, XM_MMU_CMD,
+ xm_read16(hw, port, XM_MMU_CMD)
+ & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
+
+ xm_read16(hw, port, XM_MMU_CMD);
+}
+
+static void genesis_link_up(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ u16 cmd, msk;
+ u32 mode;
+
+ cmd = xm_read16(hw, port, XM_MMU_CMD);
+
+ /*
+ * enabling pause frame reception is required for 1000BT
+ * because the XMAC is not reset if the link is going down
+ */
+ if (skge->flow_status == FLOW_STAT_NONE ||
+ skge->flow_status == FLOW_STAT_LOC_SEND)
+ /* Disable Pause Frame Reception */
+ cmd |= XM_MMU_IGN_PF;
+ else
+ /* Enable Pause Frame Reception */
+ cmd &= ~XM_MMU_IGN_PF;
+
+ xm_write16(hw, port, XM_MMU_CMD, cmd);
+
+ mode = xm_read32(hw, port, XM_MODE);
+ if (skge->flow_status== FLOW_STAT_SYMMETRIC ||
+ skge->flow_status == FLOW_STAT_LOC_SEND) {
+ /*
+ * Configure Pause Frame Generation
+ * Use internal and external Pause Frame Generation.
+ * Sending pause frames is edge triggered.
+ * Send a Pause frame with the maximum pause time if
+ * internal oder external FIFO full condition occurs.
+ * Send a zero pause time frame to re-start transmission.
+ */
+ /* XM_PAUSE_DA = '010000C28001' (default) */
+ /* XM_MAC_PTIME = 0xffff (maximum) */
+ /* remember this value is defined in big endian (!) */
+ xm_write16(hw, port, XM_MAC_PTIME, 0xffff);
+
+ mode |= XM_PAUSE_MODE;
+ skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
+ } else {
+ /*
+ * disable pause frame generation is required for 1000BT
+ * because the XMAC is not reset if the link is going down
+ */
+ /* Disable Pause Mode in Mode Register */
+ mode &= ~XM_PAUSE_MODE;
+
+ skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
+ }
+
+ xm_write32(hw, port, XM_MODE, mode);
+
+ /* Turn on detection of Tx underrun */
+ msk = xm_read16(hw, port, XM_IMSK);
+ msk &= ~XM_IS_TXF_UR;
+ xm_write16(hw, port, XM_IMSK, msk);
+
+ xm_read16(hw, port, XM_ISRC);
+
+ /* get MMU Command Reg. */
+ cmd = xm_read16(hw, port, XM_MMU_CMD);
+ if (hw->phy_type != SK_PHY_XMAC && skge->duplex == DUPLEX_FULL)
+ cmd |= XM_MMU_GMII_FD;
+
+ /*
+ * Workaround BCOM Errata (#10523) for all BCom Phys
+ * Enable Power Management after link up
+ */
+ if (hw->phy_type == SK_PHY_BCOM) {
+ xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
+ xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL)
+ & ~PHY_B_AC_DIS_PM);
+ xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+ }
+
+ /* enable Rx/Tx */
+ xm_write16(hw, port, XM_MMU_CMD,
+ cmd | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+ skge_link_up(skge);
+}
+
+
+static inline void bcom_phy_intr(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ u16 isrc;
+
+ isrc = xm_phy_read(hw, port, PHY_BCOM_INT_STAT);
+ DBGIO(PFX "%s: phy interrupt status 0x%x\n",
+ skge->netdev->name, isrc);
+
+ if (isrc & PHY_B_IS_PSE)
+ DBG(PFX "%s: uncorrectable pair swap error\n",
+ hw->dev[port]->name);
+
+ /* Workaround BCom Errata:
+ * enable and disable loopback mode if "NO HCD" occurs.
+ */
+ if (isrc & PHY_B_IS_NO_HDCL) {
+ u16 ctrl = xm_phy_read(hw, port, PHY_BCOM_CTRL);
+ xm_phy_write(hw, port, PHY_BCOM_CTRL,
+ ctrl | PHY_CT_LOOP);
+ xm_phy_write(hw, port, PHY_BCOM_CTRL,
+ ctrl & ~PHY_CT_LOOP);
+ }
+
+ if (isrc & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE))
+ bcom_check_link(hw, port);
+
+}
+
+static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
+{
+ int i;
+
+ gma_write16(hw, port, GM_SMI_DATA, val);
+ gma_write16(hw, port, GM_SMI_CTRL,
+ GM_SMI_CT_PHY_AD(hw->phy_addr) | GM_SMI_CT_REG_AD(reg));
+ for (i = 0; i < PHY_RETRIES; i++) {
+ udelay(1);
+
+ if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY))
+ return 0;
+ }
+
+ DBG(PFX "%s: phy write timeout port %x reg %x val %x\n",
+ hw->dev[port]->name,
+ port, reg, val);
+ return -EIO;
+}
+
+static int __gm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
+{
+ int i;
+
+ gma_write16(hw, port, GM_SMI_CTRL,
+ GM_SMI_CT_PHY_AD(hw->phy_addr)
+ | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD);
+
+ for (i = 0; i < PHY_RETRIES; i++) {
+ udelay(1);
+ if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL)
+ goto ready;
+ }
+
+ return -ETIMEDOUT;
+ ready:
+ *val = gma_read16(hw, port, GM_SMI_DATA);
+ return 0;
+}
+
+static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg)
+{
+ u16 v = 0;
+ if (__gm_phy_read(hw, port, reg, &v))
+ DBG(PFX "%s: phy read timeout port %x reg %x val %x\n",
+ hw->dev[port]->name,
+ port, reg, v);
+ return v;
+}
+
+/* Marvell Phy Initialization */
+static void yukon_init(struct skge_hw *hw, int port)
+{
+ struct skge_port *skge = netdev_priv(hw->dev[port]);
+ u16 ctrl, ct1000, adv;
+
+ if (skge->autoneg == AUTONEG_ENABLE) {
+ u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
+
+ ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
+ PHY_M_EC_MAC_S_MSK);
+ ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
+
+ ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
+
+ gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl);
+ }
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL);
+ if (skge->autoneg == AUTONEG_DISABLE)
+ ctrl &= ~PHY_CT_ANE;
+
+ ctrl |= PHY_CT_RESET;
+ gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+ ctrl = 0;
+ ct1000 = 0;
+ adv = PHY_AN_CSMA;
+
+ if (skge->autoneg == AUTONEG_ENABLE) {
+ if (hw->copper) {
+ if (skge->advertising & ADVERTISED_1000baseT_Full)
+ ct1000 |= PHY_M_1000C_AFD;
+ if (skge->advertising & ADVERTISED_1000baseT_Half)
+ ct1000 |= PHY_M_1000C_AHD;
+ if (skge->advertising & ADVERTISED_100baseT_Full)
+ adv |= PHY_M_AN_100_FD;
+ if (skge->advertising & ADVERTISED_100baseT_Half)
+ adv |= PHY_M_AN_100_HD;
+ if (skge->advertising & ADVERTISED_10baseT_Full)
+ adv |= PHY_M_AN_10_FD;
+ if (skge->advertising & ADVERTISED_10baseT_Half)
+ adv |= PHY_M_AN_10_HD;
+
+ /* Set Flow-control capabilities */
+ adv |= phy_pause_map[skge->flow_control];
+ } else {
+ if (skge->advertising & ADVERTISED_1000baseT_Full)
+ adv |= PHY_M_AN_1000X_AFD;
+ if (skge->advertising & ADVERTISED_1000baseT_Half)
+ adv |= PHY_M_AN_1000X_AHD;
+
+ adv |= fiber_pause_map[skge->flow_control];
+ }
+
+ /* Restart Auto-negotiation */
+ ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
+ } else {
+ /* forced speed/duplex settings */
+ ct1000 = PHY_M_1000C_MSE;
+
+ if (skge->duplex == DUPLEX_FULL)
+ ctrl |= PHY_CT_DUP_MD;
+
+ switch (skge->speed) {
+ case SPEED_1000:
+ ctrl |= PHY_CT_SP1000;
+ break;
+ case SPEED_100:
+ ctrl |= PHY_CT_SP100;
+ break;
+ }
+
+ ctrl |= PHY_CT_RESET;
+ }
+
+ gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
+
+ gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
+ gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+ /* Enable phy interrupt on autonegotiation complete (or link up) */
+ if (skge->autoneg == AUTONEG_ENABLE)
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_MSK);
+ else
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK);
+}
+
+static void yukon_reset(struct skge_hw *hw, int port)
+{
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);/* disable PHY IRQs */
+ gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */
+ gma_write16(hw, port, GM_MC_ADDR_H2, 0);
+ gma_write16(hw, port, GM_MC_ADDR_H3, 0);
+ gma_write16(hw, port, GM_MC_ADDR_H4, 0);
+
+ gma_write16(hw, port, GM_RX_CTRL,
+ gma_read16(hw, port, GM_RX_CTRL)
+ | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+}
+
+/* Apparently, early versions of Yukon-Lite had wrong chip_id? */
+static int is_yukon_lite_a0(struct skge_hw *hw)
+{
+ u32 reg;
+ int ret;
+
+ if (hw->chip_id != CHIP_ID_YUKON)
+ return 0;
+
+ reg = skge_read32(hw, B2_FAR);
+ skge_write8(hw, B2_FAR + 3, 0xff);
+ ret = (skge_read8(hw, B2_FAR + 3) != 0);
+ skge_write32(hw, B2_FAR, reg);
+ return ret;
+}
+
+static void yukon_mac_init(struct skge_hw *hw, int port)
+{
+ struct skge_port *skge = netdev_priv(hw->dev[port]);
+ int i;
+ u32 reg;
+ const u8 *addr = hw->dev[port]->ll_addr;
+
+ /* WA code for COMA mode -- set PHY reset */
+ if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ reg = skge_read32(hw, B2_GP_IO);
+ reg |= GP_DIR_9 | GP_IO_9;
+ skge_write32(hw, B2_GP_IO, reg);
+ }
+
+ /* hard reset */
+ skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+ skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
+
+ /* WA code for COMA mode -- clear PHY reset */
+ if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ reg = skge_read32(hw, B2_GP_IO);
+ reg |= GP_DIR_9;
+ reg &= ~GP_IO_9;
+ skge_write32(hw, B2_GP_IO, reg);
+ }
+
+ /* Set hardware config mode */
+ reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
+ GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE;
+ reg |= hw->copper ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
+
+ /* Clear GMC reset */
+ skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET);
+ skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_CLR);
+ skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
+
+ if (skge->autoneg == AUTONEG_DISABLE) {
+ reg = GM_GPCR_AU_ALL_DIS;
+ gma_write16(hw, port, GM_GP_CTRL,
+ gma_read16(hw, port, GM_GP_CTRL) | reg);
+
+ switch (skge->speed) {
+ case SPEED_1000:
+ reg &= ~GM_GPCR_SPEED_100;
+ reg |= GM_GPCR_SPEED_1000;
+ break;
+ case SPEED_100:
+ reg &= ~GM_GPCR_SPEED_1000;
+ reg |= GM_GPCR_SPEED_100;
+ break;
+ case SPEED_10:
+ reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100);
+ break;
+ }
+
+ if (skge->duplex == DUPLEX_FULL)
+ reg |= GM_GPCR_DUP_FULL;
+ } else
+ reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL;
+
+ switch (skge->flow_control) {
+ case FLOW_MODE_NONE:
+ skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+ reg |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+ break;
+ case FLOW_MODE_LOC_SEND:
+ /* disable Rx flow-control */
+ reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+ break;
+ case FLOW_MODE_SYMMETRIC:
+ case FLOW_MODE_SYM_OR_REM:
+ /* enable Tx & Rx flow-control */
+ break;
+ }
+
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+ skge_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
+
+ yukon_init(hw, port);
+
+ /* MIB clear */
+ reg = gma_read16(hw, port, GM_PHY_ADDR);
+ gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
+
+ for (i = 0; i < GM_MIB_CNT_SIZE; i++)
+ gma_read16(hw, port, GM_MIB_CNT_BASE + 8*i);
+ gma_write16(hw, port, GM_PHY_ADDR, reg);
+
+ /* transmit control */
+ gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF));
+
+ /* receive control reg: unicast + multicast + no FCS */
+ gma_write16(hw, port, GM_RX_CTRL,
+ GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA);
+
+ /* transmit flow control */
+ gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff);
+
+ /* transmit parameter */
+ gma_write16(hw, port, GM_TX_PARAM,
+ TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) |
+ TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) |
+ TX_IPG_JAM_DATA(TX_IPG_JAM_DEF));
+
+ /* configure the Serial Mode Register */
+ reg = DATA_BLIND_VAL(DATA_BLIND_DEF)
+ | GM_SMOD_VLAN_ENA
+ | IPG_DATA_VAL(IPG_DATA_DEF);
+
+ gma_write16(hw, port, GM_SERIAL_MODE, reg);
+
+ /* physical address: used for pause frames */
+ gma_set_addr(hw, port, GM_SRC_ADDR_1L, addr);
+ /* virtual address for data */
+ gma_set_addr(hw, port, GM_SRC_ADDR_2L, addr);
+
+ /* enable interrupt mask for counter overflows */
+ gma_write16(hw, port, GM_TX_IRQ_MSK, 0);
+ gma_write16(hw, port, GM_RX_IRQ_MSK, 0);
+ gma_write16(hw, port, GM_TR_IRQ_MSK, 0);
+
+ /* Initialize Mac Fifo */
+
+ /* Configure Rx MAC FIFO */
+ skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK);
+ reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
+
+ /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */
+ if (is_yukon_lite_a0(hw))
+ reg &= ~GMF_RX_F_FL_ON;
+
+ skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
+ skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
+ /*
+ * because Pause Packet Truncation in GMAC is not working
+ * we have to increase the Flush Threshold to 64 bytes
+ * in order to flush pause packets in Rx FIFO on Yukon-1
+ */
+ skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1);
+
+ /* Configure Tx MAC FIFO */
+ skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
+ skge_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
+}
+
+/* Go into power down mode */
+static void yukon_suspend(struct skge_hw *hw, int port)
+{
+ u16 ctrl;
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ ctrl |= PHY_M_PC_POL_R_DIS;
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL);
+ ctrl |= PHY_CT_RESET;
+ gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+ /* switch IEEE compatible power down mode on */
+ ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL);
+ ctrl |= PHY_CT_PDOWN;
+ gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+}
+
+static void yukon_stop(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+ yukon_reset(hw, port);
+
+ gma_write16(hw, port, GM_GP_CTRL,
+ gma_read16(hw, port, GM_GP_CTRL)
+ & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
+ gma_read16(hw, port, GM_GP_CTRL);
+
+ yukon_suspend(hw, port);
+
+ /* set GPHY Control reset */
+ skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+ skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
+}
+
+static u16 yukon_speed(const struct skge_hw *hw __unused, u16 aux)
+{
+ switch (aux & PHY_M_PS_SPEED_MSK) {
+ case PHY_M_PS_SPEED_1000:
+ return SPEED_1000;
+ case PHY_M_PS_SPEED_100:
+ return SPEED_100;
+ default:
+ return SPEED_10;
+ }
+}
+
+static void yukon_link_up(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ u16 reg;
+
+ /* Enable Transmit FIFO Underrun */
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
+
+ reg = gma_read16(hw, port, GM_GP_CTRL);
+ if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE)
+ reg |= GM_GPCR_DUP_FULL;
+
+ /* enable Rx/Tx */
+ reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK);
+ skge_link_up(skge);
+}
+
+static void yukon_link_down(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ u16 ctrl;
+
+ ctrl = gma_read16(hw, port, GM_GP_CTRL);
+ ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+ gma_write16(hw, port, GM_GP_CTRL, ctrl);
+
+ if (skge->flow_status == FLOW_STAT_REM_SEND) {
+ ctrl = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV);
+ ctrl |= PHY_M_AN_ASP;
+ /* restore Asymmetric Pause bit */
+ gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, ctrl);
+ }
+
+ skge_link_down(skge);
+
+ yukon_init(hw, port);
+}
+
+static void yukon_phy_intr(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ const char *reason = NULL;
+ u16 istatus, phystat;
+
+ istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT);
+ phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT);
+
+ DBGIO(PFX "%s: phy interrupt status 0x%x 0x%x\n",
+ skge->netdev->name, istatus, phystat);
+
+ if (istatus & PHY_M_IS_AN_COMPL) {
+ if (gm_phy_read(hw, port, PHY_MARV_AUNE_LP)
+ & PHY_M_AN_RF) {
+ reason = "remote fault";
+ goto failed;
+ }
+
+ if (gm_phy_read(hw, port, PHY_MARV_1000T_STAT) & PHY_B_1000S_MSF) {
+ reason = "master/slave fault";
+ goto failed;
+ }
+
+ if (!(phystat & PHY_M_PS_SPDUP_RES)) {
+ reason = "speed/duplex";
+ goto failed;
+ }
+
+ skge->duplex = (phystat & PHY_M_PS_FULL_DUP)
+ ? DUPLEX_FULL : DUPLEX_HALF;
+ skge->speed = yukon_speed(hw, phystat);
+
+ /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+ switch (phystat & PHY_M_PS_PAUSE_MSK) {
+ case PHY_M_PS_PAUSE_MSK:
+ skge->flow_status = FLOW_STAT_SYMMETRIC;
+ break;
+ case PHY_M_PS_RX_P_EN:
+ skge->flow_status = FLOW_STAT_REM_SEND;
+ break;
+ case PHY_M_PS_TX_P_EN:
+ skge->flow_status = FLOW_STAT_LOC_SEND;
+ break;
+ default:
+ skge->flow_status = FLOW_STAT_NONE;
+ }
+
+ if (skge->flow_status == FLOW_STAT_NONE ||
+ (skge->speed < SPEED_1000 && skge->duplex == DUPLEX_HALF))
+ skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+ else
+ skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
+ yukon_link_up(skge);
+ return;
+ }
+
+ if (istatus & PHY_M_IS_LSP_CHANGE)
+ skge->speed = yukon_speed(hw, phystat);
+
+ if (istatus & PHY_M_IS_DUP_CHANGE)
+ skge->duplex = (phystat & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
+ if (istatus & PHY_M_IS_LST_CHANGE) {
+ if (phystat & PHY_M_PS_LINK_UP)
+ yukon_link_up(skge);
+ else
+ yukon_link_down(skge);
+ }
+ return;
+ failed:
+ DBG(PFX "%s: autonegotiation failed (%s)\n",
+ skge->netdev->name, reason);
+
+ /* XXX restart autonegotiation? */
+}
+
+static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len)
+{
+ u32 end;
+
+ start /= 8;
+ len /= 8;
+ end = start + len - 1;
+
+ skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
+ skge_write32(hw, RB_ADDR(q, RB_START), start);
+ skge_write32(hw, RB_ADDR(q, RB_WP), start);
+ skge_write32(hw, RB_ADDR(q, RB_RP), start);
+ skge_write32(hw, RB_ADDR(q, RB_END), end);
+
+ if (q == Q_R1 || q == Q_R2) {
+ /* Set thresholds on receive queue's */
+ skge_write32(hw, RB_ADDR(q, RB_RX_UTPP),
+ start + (2*len)/3);
+ skge_write32(hw, RB_ADDR(q, RB_RX_LTPP),
+ start + (len/3));
+ } else {
+ /* Enable store & forward on Tx queue's because
+ * Tx FIFO is only 4K on Genesis and 1K on Yukon
+ */
+ skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD);
+ }
+
+ skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD);
+}
+
+/* Setup Bus Memory Interface */
+static void skge_qset(struct skge_port *skge, u16 q,
+ const struct skge_element *e)
+{
+ struct skge_hw *hw = skge->hw;
+ u32 watermark = 0x600;
+ u64 base = skge->dma + (e->desc - skge->mem);
+
+ /* optimization to reduce window on 32bit/33mhz */
+ if ((skge_read16(hw, B0_CTST) & (CS_BUS_CLOCK | CS_BUS_SLOT_SZ)) == 0)
+ watermark /= 2;
+
+ skge_write32(hw, Q_ADDR(q, Q_CSR), CSR_CLR_RESET);
+ skge_write32(hw, Q_ADDR(q, Q_F), watermark);
+ skge_write32(hw, Q_ADDR(q, Q_DA_H), (u32)(base >> 32));
+ skge_write32(hw, Q_ADDR(q, Q_DA_L), (u32)base);
+}
+
+void skge_free(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+
+ free(skge->rx_ring.start);
+ skge->rx_ring.start = NULL;
+
+ free(skge->tx_ring.start);
+ skge->tx_ring.start = NULL;
+
+ free_dma(skge->mem, RING_SIZE);
+ skge->mem = NULL;
+ skge->dma = 0;
+}
+
+static int skge_up(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ u32 chunk, ram_addr;
+ int err;
+
+ DBG2(PFX "%s: enabling interface\n", dev->name);
+
+ skge->mem = malloc_dma(RING_SIZE, SKGE_RING_ALIGN);
+ skge->dma = virt_to_bus(skge->mem);
+ if (!skge->mem)
+ return -ENOMEM;
+ memset(skge->mem, 0, RING_SIZE);
+
+ assert(!(skge->dma & 7));
+
+ /* FIXME: find out whether 64 bit iPXE will be loaded > 4GB */
+ if ((u64)skge->dma >> 32 != ((u64) skge->dma + RING_SIZE) >> 32) {
+ DBG(PFX "pci_alloc_consistent region crosses 4G boundary\n");
+ err = -EINVAL;
+ goto err;
+ }
+
+ err = skge_ring_alloc(&skge->rx_ring, skge->mem, skge->dma, NUM_RX_DESC);
+ if (err)
+ goto err;
+
+ /* this call relies on e->iob and d->control to be 0
+ * This is assured by calling memset() on skge->mem and using zalloc()
+ * for the skge_element structures.
+ */
+ skge_rx_refill(dev);
+
+ err = skge_ring_alloc(&skge->tx_ring, skge->mem + RX_RING_SIZE,
+ skge->dma + RX_RING_SIZE, NUM_TX_DESC);
+ if (err)
+ goto err;
+
+ /* Initialize MAC */
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_mac_init(hw, port);
+ else
+ yukon_mac_init(hw, port);
+
+ /* Configure RAMbuffers - equally between ports and tx/rx */
+ chunk = (hw->ram_size - hw->ram_offset) / (hw->ports * 2);
+ ram_addr = hw->ram_offset + 2 * chunk * port;
+
+ skge_ramset(hw, rxqaddr[port], ram_addr, chunk);
+ skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean);
+
+ assert(!(skge->tx_ring.to_use != skge->tx_ring.to_clean));
+ skge_ramset(hw, txqaddr[port], ram_addr+chunk, chunk);
+ skge_qset(skge, txqaddr[port], skge->tx_ring.to_use);
+
+ /* Start receiver BMU */
+ wmb();
+ skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
+ skge_led(skge, LED_MODE_ON);
+
+ hw->intr_mask |= portmask[port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+
+ return 0;
+
+ err:
+ skge_rx_clean(skge);
+ skge_free(dev);
+
+ return err;
+}
+
+/* stop receiver */
+static void skge_rx_stop(struct skge_hw *hw, int port)
+{
+ skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_STOP);
+ skge_write32(hw, RB_ADDR(port ? Q_R2 : Q_R1, RB_CTRL),
+ RB_RST_SET|RB_DIS_OP_MD);
+ skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET);
+}
+
+static void skge_down(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ if (skge->mem == NULL)
+ return;
+
+ DBG2(PFX "%s: disabling interface\n", dev->name);
+
+ if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
+ skge->use_xm_link_timer = 0;
+
+ netdev_link_down(dev);
+
+ hw->intr_mask &= ~portmask[port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_stop(skge);
+ else
+ yukon_stop(skge);
+
+ /* Stop transmitter */
+ skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
+ skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
+ RB_RST_SET|RB_DIS_OP_MD);
+
+
+ /* Disable Force Sync bit and Enable Alloc bit */
+ skge_write8(hw, SK_REG(port, TXA_CTRL),
+ TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+
+ /* Stop Interval Timer and Limit Counter of Tx Arbiter */
+ skge_write32(hw, SK_REG(port, TXA_ITI_INI), 0L);
+ skge_write32(hw, SK_REG(port, TXA_LIM_INI), 0L);
+
+ /* Reset PCI FIFO */
+ skge_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_SET_RESET);
+ skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
+
+ /* Reset the RAM Buffer async Tx queue */
+ skge_write8(hw, RB_ADDR(port == 0 ? Q_XA1 : Q_XA2, RB_CTRL), RB_RST_SET);
+
+ skge_rx_stop(hw, port);
+
+ if (hw->chip_id == CHIP_ID_GENESIS) {
+ skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET);
+ skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET);
+ } else {
+ skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
+ skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
+ }
+
+ skge_led(skge, LED_MODE_OFF);
+
+ skge_tx_clean(dev);
+
+ skge_rx_clean(skge);
+
+ skge_free(dev);
+ return;
+}
+
+static inline int skge_tx_avail(const struct skge_ring *ring)
+{
+ mb();
+ return ((ring->to_clean > ring->to_use) ? 0 : NUM_TX_DESC)
+ + (ring->to_clean - ring->to_use) - 1;
+}
+
+static int skge_xmit_frame(struct net_device *dev, struct io_buffer *iob)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ struct skge_element *e;
+ struct skge_tx_desc *td;
+ u32 control, len;
+ u64 map;
+
+ if (skge_tx_avail(&skge->tx_ring) < 1)
+ return -EBUSY;
+
+ e = skge->tx_ring.to_use;
+ td = e->desc;
+ assert(!(td->control & BMU_OWN));
+ e->iob = iob;
+ len = iob_len(iob);
+ map = virt_to_bus(iob->data);
+
+ td->dma_lo = map;
+ td->dma_hi = map >> 32;
+
+ control = BMU_CHECK;
+
+ control |= BMU_EOF| BMU_IRQ_EOF;
+ /* Make sure all the descriptors written */
+ wmb();
+ td->control = BMU_OWN | BMU_SW | BMU_STF | control | len;
+ wmb();
+
+ skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START);
+
+ DBGIO(PFX "%s: tx queued, slot %td, len %d\n",
+ dev->name, e - skge->tx_ring.start, (unsigned int)len);
+
+ skge->tx_ring.to_use = e->next;
+ wmb();
+
+ if (skge_tx_avail(&skge->tx_ring) <= 1) {
+ DBG(PFX "%s: transmit queue full\n", dev->name);
+ }
+
+ return 0;
+}
+
+/* Free all buffers in transmit ring */
+static void skge_tx_clean(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_element *e;
+
+ for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
+ struct skge_tx_desc *td = e->desc;
+ td->control = 0;
+ }
+
+ skge->tx_ring.to_clean = e;
+}
+
+static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 };
+
+static inline u16 phy_length(const struct skge_hw *hw, u32 status)
+{
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ return status >> XMR_FS_LEN_SHIFT;
+ else
+ return status >> GMR_FS_LEN_SHIFT;
+}
+
+static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
+{
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ return (status & (XMR_FS_ERR | XMR_FS_2L_VLAN)) != 0;
+ else
+ return (status & GMR_FS_ANY_ERR) ||
+ (status & GMR_FS_RX_OK) == 0;
+}
+
+/* Free all buffers in Tx ring which are no longer owned by device */
+static void skge_tx_done(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_ring *ring = &skge->tx_ring;
+ struct skge_element *e;
+
+ skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
+
+ for (e = ring->to_clean; e != ring->to_use; e = e->next) {
+ u32 control = ((const struct skge_tx_desc *) e->desc)->control;
+
+ if (control & BMU_OWN)
+ break;
+
+ netdev_tx_complete(dev, e->iob);
+ }
+ skge->tx_ring.to_clean = e;
+
+ /* Can run lockless until we need to synchronize to restart queue. */
+ mb();
+}
+
+static void skge_rx_refill(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_ring *ring = &skge->rx_ring;
+ struct skge_element *e;
+ struct io_buffer *iob;
+ struct skge_rx_desc *rd;
+ u32 control;
+ int i;
+
+ for (i = 0; i < NUM_RX_DESC; i++) {
+ e = ring->to_clean;
+ rd = e->desc;
+ iob = e->iob;
+ control = rd->control;
+
+ /* nothing to do here */
+ if (iob || (control & BMU_OWN))
+ continue;
+
+ DBG2("refilling rx desc %zd: ", (ring->to_clean - ring->start));
+
+ iob = alloc_iob(RX_BUF_SIZE);
+ if (iob) {
+ skge_rx_setup(skge, e, iob, RX_BUF_SIZE);
+ } else {
+ DBG("descr %zd: alloc_iob() failed\n",
+ (ring->to_clean - ring->start));
+ /* We pass the descriptor to the NIC even if the
+ * allocation failed. The card will stop as soon as it
+ * encounters a descriptor with the OWN bit set to 0,
+ * thus never getting to the next descriptor that might
+ * contain a valid io_buffer. This would effectively
+ * stall the receive.
+ */
+ skge_rx_setup(skge, e, NULL, 0);
+ }
+
+ ring->to_clean = e->next;
+ }
+}
+
+static void skge_rx_done(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_ring *ring = &skge->rx_ring;
+ struct skge_rx_desc *rd;
+ struct skge_element *e;
+ struct io_buffer *iob;
+ u32 control;
+ u16 len;
+ int i;
+
+ e = ring->to_clean;
+ for (i = 0; i < NUM_RX_DESC; i++) {
+ iob = e->iob;
+ rd = e->desc;
+
+ rmb();
+ control = rd->control;
+
+ if ((control & BMU_OWN))
+ break;
+
+ if (!iob)
+ continue;
+
+ len = control & BMU_BBC;
+
+ /* catch RX errors */
+ if ((bad_phy_status(skge->hw, rd->status)) ||
+ (phy_length(skge->hw, rd->status) != len)) {
+ /* report receive errors */
+ DBG("rx error\n");
+ netdev_rx_err(dev, iob, -EIO);
+ } else {
+ DBG2("received packet, len %d\n", len);
+ iob_put(iob, len);
+ netdev_rx(dev, iob);
+ }
+
+ /* io_buffer passed to core, make sure we don't reuse it */
+ e->iob = NULL;
+
+ e = e->next;
+ }
+ skge_rx_refill(dev);
+}
+
+static void skge_poll(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ u32 status;
+
+ /* reading this register ACKs interrupts */
+ status = skge_read32(hw, B0_SP_ISRC);
+
+ /* Link event? */
+ if (status & IS_EXT_REG) {
+ skge_phyirq(hw);
+ if (skge->use_xm_link_timer)
+ xm_link_timer(skge);
+ }
+
+ skge_tx_done(dev);
+
+ skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
+
+ skge_rx_done(dev);
+
+ /* restart receiver */
+ wmb();
+ skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_START);
+
+ skge_read32(hw, B0_IMSK);
+
+ return;
+}
+
+static void skge_phyirq(struct skge_hw *hw)
+{
+ int port;
+
+ for (port = 0; port < hw->ports; port++) {
+ struct net_device *dev = hw->dev[port];
+ struct skge_port *skge = netdev_priv(dev);
+
+ if (hw->chip_id != CHIP_ID_GENESIS)
+ yukon_phy_intr(skge);
+ else if (hw->phy_type == SK_PHY_BCOM)
+ bcom_phy_intr(skge);
+ }
+
+ hw->intr_mask |= IS_EXT_REG;
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+ skge_read32(hw, B0_IMSK);
+}
+
+static const struct {
+ u8 id;
+ const char *name;
+} skge_chips[] = {
+ { CHIP_ID_GENESIS, "Genesis" },
+ { CHIP_ID_YUKON, "Yukon" },
+ { CHIP_ID_YUKON_LITE, "Yukon-Lite"},
+ { CHIP_ID_YUKON_LP, "Yukon-LP"},
+};
+
+static const char *skge_board_name(const struct skge_hw *hw)
+{
+ unsigned int i;
+ static char buf[16];
+
+ for (i = 0; i < ARRAY_SIZE(skge_chips); i++)
+ if (skge_chips[i].id == hw->chip_id)
+ return skge_chips[i].name;
+
+ snprintf(buf, sizeof buf, "chipid 0x%x", hw->chip_id);
+ return buf;
+}
+
+
+/*
+ * Setup the board data structure, but don't bring up
+ * the port(s)
+ */
+static int skge_reset(struct skge_hw *hw)
+{
+ u32 reg;
+ u16 ctst, pci_status;
+ u8 t8, mac_cfg, pmd_type;
+ int i;
+
+ ctst = skge_read16(hw, B0_CTST);
+
+ /* do a SW reset */
+ skge_write8(hw, B0_CTST, CS_RST_SET);
+ skge_write8(hw, B0_CTST, CS_RST_CLR);
+
+ /* clear PCI errors, if any */
+ skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ skge_write8(hw, B2_TST_CTRL2, 0);
+
+ pci_read_config_word(hw->pdev, PCI_STATUS, &pci_status);
+ pci_write_config_word(hw->pdev, PCI_STATUS,
+ pci_status | PCI_STATUS_ERROR_BITS);
+ skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+ skge_write8(hw, B0_CTST, CS_MRST_CLR);
+
+ /* restore CLK_RUN bits (for Yukon-Lite) */
+ skge_write16(hw, B0_CTST,
+ ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA));
+
+ hw->chip_id = skge_read8(hw, B2_CHIP_ID);
+ hw->phy_type = skge_read8(hw, B2_E_1) & 0xf;
+ pmd_type = skge_read8(hw, B2_PMD_TYP);
+ hw->copper = (pmd_type == 'T' || pmd_type == '1');
+
+ switch (hw->chip_id) {
+ case CHIP_ID_GENESIS:
+ switch (hw->phy_type) {
+ case SK_PHY_XMAC:
+ hw->phy_addr = PHY_ADDR_XMAC;
+ break;
+ case SK_PHY_BCOM:
+ hw->phy_addr = PHY_ADDR_BCOM;
+ break;
+ default:
+ DBG(PFX "unsupported phy type 0x%x\n",
+ hw->phy_type);
+ return -EOPNOTSUPP;
+ }
+ break;
+
+ case CHIP_ID_YUKON:
+ case CHIP_ID_YUKON_LITE:
+ case CHIP_ID_YUKON_LP:
+ if (hw->phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
+ hw->copper = 1;
+
+ hw->phy_addr = PHY_ADDR_MARV;
+ break;
+
+ default:
+ DBG(PFX "unsupported chip type 0x%x\n",
+ hw->chip_id);
+ return -EOPNOTSUPP;
+ }
+
+ mac_cfg = skge_read8(hw, B2_MAC_CFG);
+ hw->ports = (mac_cfg & CFG_SNG_MAC) ? 1 : 2;
+ hw->chip_rev = (mac_cfg & CFG_CHIP_R_MSK) >> 4;
+
+ /* read the adapters RAM size */
+ t8 = skge_read8(hw, B2_E_0);
+ if (hw->chip_id == CHIP_ID_GENESIS) {
+ if (t8 == 3) {
+ /* special case: 4 x 64k x 36, offset = 0x80000 */
+ hw->ram_size = 0x100000;
+ hw->ram_offset = 0x80000;
+ } else
+ hw->ram_size = t8 * 512;
+ }
+ else if (t8 == 0)
+ hw->ram_size = 0x20000;
+ else
+ hw->ram_size = t8 * 4096;
+
+ hw->intr_mask = IS_HW_ERR;
+
+ /* Use PHY IRQ for all but fiber based Genesis board */
+ if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC))
+ hw->intr_mask |= IS_EXT_REG;
+
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_init(hw);
+ else {
+ /* switch power to VCC (WA for VAUX problem) */
+ skge_write8(hw, B0_POWER_CTRL,
+ PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON);
+
+ /* avoid boards with stuck Hardware error bits */
+ if ((skge_read32(hw, B0_ISRC) & IS_HW_ERR) &&
+ (skge_read32(hw, B0_HWE_ISRC) & IS_IRQ_SENSOR)) {
+ DBG(PFX "stuck hardware sensor bit\n");
+ hw->intr_mask &= ~IS_HW_ERR;
+ }
+
+ /* Clear PHY COMA */
+ skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ pci_read_config_dword(hw->pdev, PCI_DEV_REG1, &reg);
+ reg &= ~PCI_PHY_COMA;
+ pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg);
+ skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+
+ for (i = 0; i < hw->ports; i++) {
+ skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
+ skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+ }
+ }
+
+ /* turn off hardware timer (unused) */
+ skge_write8(hw, B2_TI_CTRL, TIM_STOP);
+ skge_write8(hw, B2_TI_CTRL, TIM_CLR_IRQ);
+ skge_write8(hw, B0_LED, LED_STAT_ON);
+
+ /* enable the Tx Arbiters */
+ for (i = 0; i < hw->ports; i++)
+ skge_write8(hw, SK_REG(i, TXA_CTRL), TXA_ENA_ARB);
+
+ /* Initialize ram interface */
+ skge_write16(hw, B3_RI_CTRL, RI_RST_CLR);
+
+ skge_write8(hw, B3_RI_WTO_R1, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_WTO_XA1, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_WTO_XS1, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_RTO_R1, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_RTO_XA1, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_RTO_XS1, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_WTO_R2, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_WTO_XA2, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_WTO_XS2, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_RTO_R2, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_RTO_XA2, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_RTO_XS2, SK_RI_TO_53);
+
+ skge_write32(hw, B0_HWE_IMSK, IS_ERR_MSK);
+
+ /* Set interrupt moderation for Transmit only
+ * Receive interrupts avoided by NAPI
+ */
+ skge_write32(hw, B2_IRQM_MSK, IS_XA1_F|IS_XA2_F);
+ skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100));
+ skge_write32(hw, B2_IRQM_CTRL, TIM_START);
+
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+
+ for (i = 0; i < hw->ports; i++) {
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_reset(hw, i);
+ else
+ yukon_reset(hw, i);
+ }
+
+ return 0;
+}
+
+/* Initialize network device */
+static struct net_device *skge_devinit(struct skge_hw *hw, int port,
+ int highmem __unused)
+{
+ struct skge_port *skge;
+ struct net_device *dev = alloc_etherdev(sizeof(*skge));
+
+ if (!dev) {
+ DBG(PFX "etherdev alloc failed\n");
+ return NULL;
+ }
+
+ dev->dev = &hw->pdev->dev;
+
+ skge = netdev_priv(dev);
+ skge->netdev = dev;
+ skge->hw = hw;
+
+ /* Auto speed and flow control */
+ skge->autoneg = AUTONEG_ENABLE;
+ skge->flow_control = FLOW_MODE_SYM_OR_REM;
+ skge->duplex = -1;
+ skge->speed = -1;
+ skge->advertising = skge_supported_modes(hw);
+
+ hw->dev[port] = dev;
+
+ skge->port = port;
+
+ /* read the mac address */
+ memcpy(dev->hw_addr, (void *) (hw->regs + B2_MAC_1 + port*8), ETH_ALEN);
+
+ return dev;
+}
+
+static void skge_show_addr(struct net_device *dev)
+{
+ DBG2(PFX "%s: addr %s\n",
+ dev->name, netdev_addr(dev));
+}
+
+static int skge_probe(struct pci_device *pdev)
+{
+ struct net_device *dev, *dev1;
+ struct skge_hw *hw;
+ int err, using_dac = 0;
+
+ adjust_pci_device(pdev);
+
+ err = -ENOMEM;
+ hw = zalloc(sizeof(*hw));
+ if (!hw) {
+ DBG(PFX "cannot allocate hardware struct\n");
+ goto err_out_free_regions;
+ }
+
+ hw->pdev = pdev;
+
+ hw->regs = (unsigned long)ioremap(pci_bar_start(pdev, PCI_BASE_ADDRESS_0),
+ SKGE_REG_SIZE);
+ if (!hw->regs) {
+ DBG(PFX "cannot map device registers\n");
+ goto err_out_free_hw;
+ }
+
+ err = skge_reset(hw);
+ if (err)
+ goto err_out_iounmap;
+
+ DBG(PFX " addr 0x%llx irq %d chip %s rev %d\n",
+ (unsigned long long)pdev->ioaddr, pdev->irq,
+ skge_board_name(hw), hw->chip_rev);
+
+ dev = skge_devinit(hw, 0, using_dac);
+ if (!dev)
+ goto err_out_led_off;
+
+ netdev_init ( dev, &skge_operations );
+
+ err = register_netdev(dev);
+ if (err) {
+ DBG(PFX "cannot register net device\n");
+ goto err_out_free_netdev;
+ }
+
+ skge_show_addr(dev);
+
+ if (hw->ports > 1 && (dev1 = skge_devinit(hw, 1, using_dac))) {
+ if (register_netdev(dev1) == 0)
+ skge_show_addr(dev1);
+ else {
+ /* Failure to register second port need not be fatal */
+ DBG(PFX "register of second port failed\n");
+ hw->dev[1] = NULL;
+ netdev_nullify(dev1);
+ netdev_put(dev1);
+ }
+ }
+ pci_set_drvdata(pdev, hw);
+
+ return 0;
+
+err_out_free_netdev:
+ netdev_nullify(dev);
+ netdev_put(dev);
+err_out_led_off:
+ skge_write16(hw, B0_LED, LED_STAT_OFF);
+err_out_iounmap:
+ iounmap((void*)hw->regs);
+err_out_free_hw:
+ free(hw);
+err_out_free_regions:
+ pci_set_drvdata(pdev, NULL);
+ return err;
+}
+
+static void skge_remove(struct pci_device *pdev)
+{
+ struct skge_hw *hw = pci_get_drvdata(pdev);
+ struct net_device *dev0, *dev1;
+
+ if (!hw)
+ return;
+
+ if ((dev1 = hw->dev[1]))
+ unregister_netdev(dev1);
+ dev0 = hw->dev[0];
+ unregister_netdev(dev0);
+
+ hw->intr_mask = 0;
+ skge_write32(hw, B0_IMSK, 0);
+ skge_read32(hw, B0_IMSK);
+
+ skge_write16(hw, B0_LED, LED_STAT_OFF);
+ skge_write8(hw, B0_CTST, CS_RST_SET);
+
+ if (dev1) {
+ netdev_nullify(dev1);
+ netdev_put(dev1);
+ }
+ netdev_nullify(dev0);
+ netdev_put(dev0);
+
+ iounmap((void*)hw->regs);
+ free(hw);
+ pci_set_drvdata(pdev, NULL);
+}
+
+/*
+ * Enable or disable IRQ masking.
+ *
+ * @v netdev Device to control.
+ * @v enable Zero to mask off IRQ, non-zero to enable IRQ.
+ *
+ * This is a iPXE Network Driver API function.
+ */
+static void skge_net_irq ( struct net_device *dev, int enable ) {
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+
+ if (enable)
+ hw->intr_mask |= portmask[skge->port];
+ else
+ hw->intr_mask &= ~portmask[skge->port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+}
+
+struct pci_driver skge_driver __pci_driver = {
+ .ids = skge_id_table,
+ .id_count = ( sizeof (skge_id_table) / sizeof (skge_id_table[0]) ),
+ .probe = skge_probe,
+ .remove = skge_remove
+};
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/skge.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/skge.h
new file mode 100644
index 00000000..8a6ba6b2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/skge.h
@@ -0,0 +1,2623 @@
+/*
+ * Definitions for the new Marvell Yukon / SysKonnect driver.
+ */
+#ifndef _SKGE_H
+#define _SKGE_H
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/* PCI config registers */
+#define PCI_DEV_REG1 0x40
+#define PCI_PHY_COMA 0x8000000
+#define PCI_VIO 0x2000000
+
+#define PCI_DEV_REG2 0x44
+#define PCI_VPD_ROM_SZ 7L<<14 /* VPD ROM size 0=256, 1=512, ... */
+#define PCI_REV_DESC 1<<2 /* Reverse Descriptor bytes */
+
+#define DRV_NAME "skge"
+#define DRV_VERSION "1.13"
+#define PFX DRV_NAME " "
+
+#define NUM_TX_DESC 8
+#define NUM_RX_DESC 8
+
+/* mdeck used a 16 byte alignment, but datasheet says 8 bytes is sufficient */
+#define SKGE_RING_ALIGN 8
+#define RX_BUF_SIZE 1536
+#define PHY_RETRIES 1000
+
+#define TX_RING_SIZE ( NUM_TX_DESC * sizeof ( struct skge_rx_desc ) )
+#define RX_RING_SIZE ( NUM_RX_DESC * sizeof ( struct skge_tx_desc ) )
+#define RING_SIZE ( TX_RING_SIZE + RX_RING_SIZE )
+
+#define SKGE_REG_SIZE 0x4000
+
+#define SKGE_EEPROM_MAGIC 0x9933aabb
+
+/* Added for iPXE ------------------ */
+
+/* from ethtool.h */
+#define AUTONEG_DISABLE 0x00
+#define AUTONEG_ENABLE 0x01
+
+#define DUPLEX_HALF 0x00
+#define DUPLEX_FULL 0x01
+
+#define SPEED_10 10
+#define SPEED_100 100
+#define SPEED_1000 1000
+
+#define ADVERTISED_10baseT_Half (1 << 0)
+#define ADVERTISED_10baseT_Full (1 << 1)
+#define ADVERTISED_100baseT_Half (1 << 2)
+#define ADVERTISED_100baseT_Full (1 << 3)
+#define ADVERTISED_1000baseT_Half (1 << 4)
+#define ADVERTISED_1000baseT_Full (1 << 5)
+
+#define SUPPORTED_10baseT_Half (1 << 0)
+#define SUPPORTED_10baseT_Full (1 << 1)
+#define SUPPORTED_100baseT_Half (1 << 2)
+#define SUPPORTED_100baseT_Full (1 << 3)
+#define SUPPORTED_1000baseT_Half (1 << 4)
+#define SUPPORTED_1000baseT_Full (1 << 5)
+#define SUPPORTED_Autoneg (1 << 6)
+#define SUPPORTED_TP (1 << 7)
+#define SUPPORTED_FIBRE (1 << 10)
+
+/* from kernel.h */
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+/* ----------------------------------- */
+
+#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
+ PCI_STATUS_SIG_SYSTEM_ERROR | \
+ PCI_STATUS_REC_MASTER_ABORT | \
+ PCI_STATUS_REC_TARGET_ABORT | \
+ PCI_STATUS_PARITY)
+
+enum csr_regs {
+ B0_RAP = 0x0000,
+ B0_CTST = 0x0004,
+ B0_LED = 0x0006,
+ B0_POWER_CTRL = 0x0007,
+ B0_ISRC = 0x0008,
+ B0_IMSK = 0x000c,
+ B0_HWE_ISRC = 0x0010,
+ B0_HWE_IMSK = 0x0014,
+ B0_SP_ISRC = 0x0018,
+ B0_XM1_IMSK = 0x0020,
+ B0_XM1_ISRC = 0x0028,
+ B0_XM1_PHY_ADDR = 0x0030,
+ B0_XM1_PHY_DATA = 0x0034,
+ B0_XM2_IMSK = 0x0040,
+ B0_XM2_ISRC = 0x0048,
+ B0_XM2_PHY_ADDR = 0x0050,
+ B0_XM2_PHY_DATA = 0x0054,
+ B0_R1_CSR = 0x0060,
+ B0_R2_CSR = 0x0064,
+ B0_XS1_CSR = 0x0068,
+ B0_XA1_CSR = 0x006c,
+ B0_XS2_CSR = 0x0070,
+ B0_XA2_CSR = 0x0074,
+
+ B2_MAC_1 = 0x0100,
+ B2_MAC_2 = 0x0108,
+ B2_MAC_3 = 0x0110,
+ B2_CONN_TYP = 0x0118,
+ B2_PMD_TYP = 0x0119,
+ B2_MAC_CFG = 0x011a,
+ B2_CHIP_ID = 0x011b,
+ B2_E_0 = 0x011c,
+ B2_E_1 = 0x011d,
+ B2_E_2 = 0x011e,
+ B2_E_3 = 0x011f,
+ B2_FAR = 0x0120,
+ B2_FDP = 0x0124,
+ B2_LD_CTRL = 0x0128,
+ B2_LD_TEST = 0x0129,
+ B2_TI_INI = 0x0130,
+ B2_TI_VAL = 0x0134,
+ B2_TI_CTRL = 0x0138,
+ B2_TI_TEST = 0x0139,
+ B2_IRQM_INI = 0x0140,
+ B2_IRQM_VAL = 0x0144,
+ B2_IRQM_CTRL = 0x0148,
+ B2_IRQM_TEST = 0x0149,
+ B2_IRQM_MSK = 0x014c,
+ B2_IRQM_HWE_MSK = 0x0150,
+ B2_TST_CTRL1 = 0x0158,
+ B2_TST_CTRL2 = 0x0159,
+ B2_GP_IO = 0x015c,
+ B2_I2C_CTRL = 0x0160,
+ B2_I2C_DATA = 0x0164,
+ B2_I2C_IRQ = 0x0168,
+ B2_I2C_SW = 0x016c,
+ B2_BSC_INI = 0x0170,
+ B2_BSC_VAL = 0x0174,
+ B2_BSC_CTRL = 0x0178,
+ B2_BSC_STAT = 0x0179,
+ B2_BSC_TST = 0x017a,
+
+ B3_RAM_ADDR = 0x0180,
+ B3_RAM_DATA_LO = 0x0184,
+ B3_RAM_DATA_HI = 0x0188,
+ B3_RI_WTO_R1 = 0x0190,
+ B3_RI_WTO_XA1 = 0x0191,
+ B3_RI_WTO_XS1 = 0x0192,
+ B3_RI_RTO_R1 = 0x0193,
+ B3_RI_RTO_XA1 = 0x0194,
+ B3_RI_RTO_XS1 = 0x0195,
+ B3_RI_WTO_R2 = 0x0196,
+ B3_RI_WTO_XA2 = 0x0197,
+ B3_RI_WTO_XS2 = 0x0198,
+ B3_RI_RTO_R2 = 0x0199,
+ B3_RI_RTO_XA2 = 0x019a,
+ B3_RI_RTO_XS2 = 0x019b,
+ B3_RI_TO_VAL = 0x019c,
+ B3_RI_CTRL = 0x01a0,
+ B3_RI_TEST = 0x01a2,
+ B3_MA_TOINI_RX1 = 0x01b0,
+ B3_MA_TOINI_RX2 = 0x01b1,
+ B3_MA_TOINI_TX1 = 0x01b2,
+ B3_MA_TOINI_TX2 = 0x01b3,
+ B3_MA_TOVAL_RX1 = 0x01b4,
+ B3_MA_TOVAL_RX2 = 0x01b5,
+ B3_MA_TOVAL_TX1 = 0x01b6,
+ B3_MA_TOVAL_TX2 = 0x01b7,
+ B3_MA_TO_CTRL = 0x01b8,
+ B3_MA_TO_TEST = 0x01ba,
+ B3_MA_RCINI_RX1 = 0x01c0,
+ B3_MA_RCINI_RX2 = 0x01c1,
+ B3_MA_RCINI_TX1 = 0x01c2,
+ B3_MA_RCINI_TX2 = 0x01c3,
+ B3_MA_RCVAL_RX1 = 0x01c4,
+ B3_MA_RCVAL_RX2 = 0x01c5,
+ B3_MA_RCVAL_TX1 = 0x01c6,
+ B3_MA_RCVAL_TX2 = 0x01c7,
+ B3_MA_RC_CTRL = 0x01c8,
+ B3_MA_RC_TEST = 0x01ca,
+ B3_PA_TOINI_RX1 = 0x01d0,
+ B3_PA_TOINI_RX2 = 0x01d4,
+ B3_PA_TOINI_TX1 = 0x01d8,
+ B3_PA_TOINI_TX2 = 0x01dc,
+ B3_PA_TOVAL_RX1 = 0x01e0,
+ B3_PA_TOVAL_RX2 = 0x01e4,
+ B3_PA_TOVAL_TX1 = 0x01e8,
+ B3_PA_TOVAL_TX2 = 0x01ec,
+ B3_PA_CTRL = 0x01f0,
+ B3_PA_TEST = 0x01f2,
+};
+
+/* B0_CTST 16 bit Control/Status register */
+enum {
+ CS_CLK_RUN_HOT = 1<<13,/* CLK_RUN hot m. (YUKON-Lite only) */
+ CS_CLK_RUN_RST = 1<<12,/* CLK_RUN reset (YUKON-Lite only) */
+ CS_CLK_RUN_ENA = 1<<11,/* CLK_RUN enable (YUKON-Lite only) */
+ CS_VAUX_AVAIL = 1<<10,/* VAUX available (YUKON only) */
+ CS_BUS_CLOCK = 1<<9, /* Bus Clock 0/1 = 33/66 MHz */
+ CS_BUS_SLOT_SZ = 1<<8, /* Slot Size 0/1 = 32/64 bit slot */
+ CS_ST_SW_IRQ = 1<<7, /* Set IRQ SW Request */
+ CS_CL_SW_IRQ = 1<<6, /* Clear IRQ SW Request */
+ CS_STOP_DONE = 1<<5, /* Stop Master is finished */
+ CS_STOP_MAST = 1<<4, /* Command Bit to stop the master */
+ CS_MRST_CLR = 1<<3, /* Clear Master reset */
+ CS_MRST_SET = 1<<2, /* Set Master reset */
+ CS_RST_CLR = 1<<1, /* Clear Software reset */
+ CS_RST_SET = 1, /* Set Software reset */
+
+/* B0_LED 8 Bit LED register */
+/* Bit 7.. 2: reserved */
+ LED_STAT_ON = 1<<1, /* Status LED on */
+ LED_STAT_OFF = 1, /* Status LED off */
+
+/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */
+ PC_VAUX_ENA = 1<<7, /* Switch VAUX Enable */
+ PC_VAUX_DIS = 1<<6, /* Switch VAUX Disable */
+ PC_VCC_ENA = 1<<5, /* Switch VCC Enable */
+ PC_VCC_DIS = 1<<4, /* Switch VCC Disable */
+ PC_VAUX_ON = 1<<3, /* Switch VAUX On */
+ PC_VAUX_OFF = 1<<2, /* Switch VAUX Off */
+ PC_VCC_ON = 1<<1, /* Switch VCC On */
+ PC_VCC_OFF = 1<<0, /* Switch VCC Off */
+};
+
+/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */
+enum {
+ IS_ALL_MSK = 0xbffffffful, /* All Interrupt bits */
+ IS_HW_ERR = 1<<31, /* Interrupt HW Error */
+ /* Bit 30: reserved */
+ IS_PA_TO_RX1 = 1<<29, /* Packet Arb Timeout Rx1 */
+ IS_PA_TO_RX2 = 1<<28, /* Packet Arb Timeout Rx2 */
+ IS_PA_TO_TX1 = 1<<27, /* Packet Arb Timeout Tx1 */
+ IS_PA_TO_TX2 = 1<<26, /* Packet Arb Timeout Tx2 */
+ IS_I2C_READY = 1<<25, /* IRQ on end of I2C Tx */
+ IS_IRQ_SW = 1<<24, /* SW forced IRQ */
+ IS_EXT_REG = 1<<23, /* IRQ from LM80 or PHY (GENESIS only) */
+ /* IRQ from PHY (YUKON only) */
+ IS_TIMINT = 1<<22, /* IRQ from Timer */
+ IS_MAC1 = 1<<21, /* IRQ from MAC 1 */
+ IS_LNK_SYNC_M1 = 1<<20, /* Link Sync Cnt wrap MAC 1 */
+ IS_MAC2 = 1<<19, /* IRQ from MAC 2 */
+ IS_LNK_SYNC_M2 = 1<<18, /* Link Sync Cnt wrap MAC 2 */
+/* Receive Queue 1 */
+ IS_R1_B = 1<<17, /* Q_R1 End of Buffer */
+ IS_R1_F = 1<<16, /* Q_R1 End of Frame */
+ IS_R1_C = 1<<15, /* Q_R1 Encoding Error */
+/* Receive Queue 2 */
+ IS_R2_B = 1<<14, /* Q_R2 End of Buffer */
+ IS_R2_F = 1<<13, /* Q_R2 End of Frame */
+ IS_R2_C = 1<<12, /* Q_R2 Encoding Error */
+/* Synchronous Transmit Queue 1 */
+ IS_XS1_B = 1<<11, /* Q_XS1 End of Buffer */
+ IS_XS1_F = 1<<10, /* Q_XS1 End of Frame */
+ IS_XS1_C = 1<<9, /* Q_XS1 Encoding Error */
+/* Asynchronous Transmit Queue 1 */
+ IS_XA1_B = 1<<8, /* Q_XA1 End of Buffer */
+ IS_XA1_F = 1<<7, /* Q_XA1 End of Frame */
+ IS_XA1_C = 1<<6, /* Q_XA1 Encoding Error */
+/* Synchronous Transmit Queue 2 */
+ IS_XS2_B = 1<<5, /* Q_XS2 End of Buffer */
+ IS_XS2_F = 1<<4, /* Q_XS2 End of Frame */
+ IS_XS2_C = 1<<3, /* Q_XS2 Encoding Error */
+/* Asynchronous Transmit Queue 2 */
+ IS_XA2_B = 1<<2, /* Q_XA2 End of Buffer */
+ IS_XA2_F = 1<<1, /* Q_XA2 End of Frame */
+ IS_XA2_C = 1<<0, /* Q_XA2 Encoding Error */
+
+ IS_TO_PORT1 = IS_PA_TO_RX1 | IS_PA_TO_TX1,
+ IS_TO_PORT2 = IS_PA_TO_RX2 | IS_PA_TO_TX2,
+
+ IS_PORT_1 = IS_XA1_F| IS_R1_F | IS_TO_PORT1 | IS_MAC1,
+ IS_PORT_2 = IS_XA2_F| IS_R2_F | IS_TO_PORT2 | IS_MAC2,
+};
+
+
+/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */
+enum {
+ IS_IRQ_TIST_OV = 1<<13, /* Time Stamp Timer Overflow (YUKON only) */
+ IS_IRQ_SENSOR = 1<<12, /* IRQ from Sensor (YUKON only) */
+ IS_IRQ_MST_ERR = 1<<11, /* IRQ master error detected */
+ IS_IRQ_STAT = 1<<10, /* IRQ status exception */
+ IS_NO_STAT_M1 = 1<<9, /* No Rx Status from MAC 1 */
+ IS_NO_STAT_M2 = 1<<8, /* No Rx Status from MAC 2 */
+ IS_NO_TIST_M1 = 1<<7, /* No Time Stamp from MAC 1 */
+ IS_NO_TIST_M2 = 1<<6, /* No Time Stamp from MAC 2 */
+ IS_RAM_RD_PAR = 1<<5, /* RAM Read Parity Error */
+ IS_RAM_WR_PAR = 1<<4, /* RAM Write Parity Error */
+ IS_M1_PAR_ERR = 1<<3, /* MAC 1 Parity Error */
+ IS_M2_PAR_ERR = 1<<2, /* MAC 2 Parity Error */
+ IS_R1_PAR_ERR = 1<<1, /* Queue R1 Parity Error */
+ IS_R2_PAR_ERR = 1<<0, /* Queue R2 Parity Error */
+
+ IS_ERR_MSK = IS_IRQ_MST_ERR | IS_IRQ_STAT
+ | IS_RAM_RD_PAR | IS_RAM_WR_PAR
+ | IS_M1_PAR_ERR | IS_M2_PAR_ERR
+ | IS_R1_PAR_ERR | IS_R2_PAR_ERR,
+};
+
+/* B2_TST_CTRL1 8 bit Test Control Register 1 */
+enum {
+ TST_FRC_DPERR_MR = 1<<7, /* force DATAPERR on MST RD */
+ TST_FRC_DPERR_MW = 1<<6, /* force DATAPERR on MST WR */
+ TST_FRC_DPERR_TR = 1<<5, /* force DATAPERR on TRG RD */
+ TST_FRC_DPERR_TW = 1<<4, /* force DATAPERR on TRG WR */
+ TST_FRC_APERR_M = 1<<3, /* force ADDRPERR on MST */
+ TST_FRC_APERR_T = 1<<2, /* force ADDRPERR on TRG */
+ TST_CFG_WRITE_ON = 1<<1, /* Enable Config Reg WR */
+ TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */
+};
+
+/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */
+enum {
+ CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */
+ /* Bit 3.. 2: reserved */
+ CFG_DIS_M2_CLK = 1<<1, /* Disable Clock for 2nd MAC */
+ CFG_SNG_MAC = 1<<0, /* MAC Config: 0=2 MACs / 1=1 MAC*/
+};
+
+/* B2_CHIP_ID 8 bit Chip Identification Number */
+enum {
+ CHIP_ID_GENESIS = 0x0a, /* Chip ID for GENESIS */
+ CHIP_ID_YUKON = 0xb0, /* Chip ID for YUKON */
+ CHIP_ID_YUKON_LITE = 0xb1, /* Chip ID for YUKON-Lite (Rev. A1-A3) */
+ CHIP_ID_YUKON_LP = 0xb2, /* Chip ID for YUKON-LP */
+ CHIP_ID_YUKON_XL = 0xb3, /* Chip ID for YUKON-2 XL */
+ CHIP_ID_YUKON_EC = 0xb6, /* Chip ID for YUKON-2 EC */
+ CHIP_ID_YUKON_FE = 0xb7, /* Chip ID for YUKON-2 FE */
+
+ CHIP_REV_YU_LITE_A1 = 3, /* Chip Rev. for YUKON-Lite A1,A2 */
+ CHIP_REV_YU_LITE_A3 = 7, /* Chip Rev. for YUKON-Lite A3 */
+};
+
+/* B2_TI_CTRL 8 bit Timer control */
+/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */
+enum {
+ TIM_START = 1<<2, /* Start Timer */
+ TIM_STOP = 1<<1, /* Stop Timer */
+ TIM_CLR_IRQ = 1<<0, /* Clear Timer IRQ (!IRQM) */
+};
+
+/* B2_TI_TEST 8 Bit Timer Test */
+/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */
+/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */
+enum {
+ TIM_T_ON = 1<<2, /* Test mode on */
+ TIM_T_OFF = 1<<1, /* Test mode off */
+ TIM_T_STEP = 1<<0, /* Test step */
+};
+
+/* B2_GP_IO 32 bit General Purpose I/O Register */
+enum {
+ GP_DIR_9 = 1<<25, /* IO_9 direct, 0=In/1=Out */
+ GP_DIR_8 = 1<<24, /* IO_8 direct, 0=In/1=Out */
+ GP_DIR_7 = 1<<23, /* IO_7 direct, 0=In/1=Out */
+ GP_DIR_6 = 1<<22, /* IO_6 direct, 0=In/1=Out */
+ GP_DIR_5 = 1<<21, /* IO_5 direct, 0=In/1=Out */
+ GP_DIR_4 = 1<<20, /* IO_4 direct, 0=In/1=Out */
+ GP_DIR_3 = 1<<19, /* IO_3 direct, 0=In/1=Out */
+ GP_DIR_2 = 1<<18, /* IO_2 direct, 0=In/1=Out */
+ GP_DIR_1 = 1<<17, /* IO_1 direct, 0=In/1=Out */
+ GP_DIR_0 = 1<<16, /* IO_0 direct, 0=In/1=Out */
+
+ GP_IO_9 = 1<<9, /* IO_9 pin */
+ GP_IO_8 = 1<<8, /* IO_8 pin */
+ GP_IO_7 = 1<<7, /* IO_7 pin */
+ GP_IO_6 = 1<<6, /* IO_6 pin */
+ GP_IO_5 = 1<<5, /* IO_5 pin */
+ GP_IO_4 = 1<<4, /* IO_4 pin */
+ GP_IO_3 = 1<<3, /* IO_3 pin */
+ GP_IO_2 = 1<<2, /* IO_2 pin */
+ GP_IO_1 = 1<<1, /* IO_1 pin */
+ GP_IO_0 = 1<<0, /* IO_0 pin */
+};
+
+/* Descriptor Bit Definition */
+/* TxCtrl Transmit Buffer Control Field */
+/* RxCtrl Receive Buffer Control Field */
+enum {
+ BMU_OWN = 1<<31, /* OWN bit: 0=host/1=BMU */
+ BMU_STF = 1<<30, /* Start of Frame */
+ BMU_EOF = 1<<29, /* End of Frame */
+ BMU_IRQ_EOB = 1<<28, /* Req "End of Buffer" IRQ */
+ BMU_IRQ_EOF = 1<<27, /* Req "End of Frame" IRQ */
+ /* TxCtrl specific bits */
+ BMU_STFWD = 1<<26, /* (Tx) Store & Forward Frame */
+ BMU_NO_FCS = 1<<25, /* (Tx) Disable MAC FCS (CRC) generation */
+ BMU_SW = 1<<24, /* (Tx) 1 bit res. for SW use */
+ /* RxCtrl specific bits */
+ BMU_DEV_0 = 1<<26, /* (Rx) Transfer data to Dev0 */
+ BMU_STAT_VAL = 1<<25, /* (Rx) Rx Status Valid */
+ BMU_TIST_VAL = 1<<24, /* (Rx) Rx TimeStamp Valid */
+ /* Bit 23..16: BMU Check Opcodes */
+ BMU_CHECK = 0x55<<16, /* Default BMU check */
+ BMU_TCP_CHECK = 0x56<<16, /* Descr with TCP ext */
+ BMU_UDP_CHECK = 0x57<<16, /* Descr with UDP ext (YUKON only) */
+ BMU_BBC = 0xffffL, /* Bit 15.. 0: Buffer Byte Counter */
+};
+
+/* B2_BSC_CTRL 8 bit Blink Source Counter Control */
+enum {
+ BSC_START = 1<<1, /* Start Blink Source Counter */
+ BSC_STOP = 1<<0, /* Stop Blink Source Counter */
+};
+
+/* B2_BSC_STAT 8 bit Blink Source Counter Status */
+enum {
+ BSC_SRC = 1<<0, /* Blink Source, 0=Off / 1=On */
+};
+
+/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */
+enum {
+ BSC_T_ON = 1<<2, /* Test mode on */
+ BSC_T_OFF = 1<<1, /* Test mode off */
+ BSC_T_STEP = 1<<0, /* Test step */
+};
+
+/* B3_RAM_ADDR 32 bit RAM Address, to read or write */
+ /* Bit 31..19: reserved */
+#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */
+/* RAM Interface Registers */
+
+/* B3_RI_CTRL 16 bit RAM Iface Control Register */
+enum {
+ RI_CLR_RD_PERR = 1<<9, /* Clear IRQ RAM Read Parity Err */
+ RI_CLR_WR_PERR = 1<<8, /* Clear IRQ RAM Write Parity Err*/
+
+ RI_RST_CLR = 1<<1, /* Clear RAM Interface Reset */
+ RI_RST_SET = 1<<0, /* Set RAM Interface Reset */
+};
+
+/* MAC Arbiter Registers */
+/* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */
+enum {
+ MA_FOE_ON = 1<<3, /* XMAC Fast Output Enable ON */
+ MA_FOE_OFF = 1<<2, /* XMAC Fast Output Enable OFF */
+ MA_RST_CLR = 1<<1, /* Clear MAC Arbiter Reset */
+ MA_RST_SET = 1<<0, /* Set MAC Arbiter Reset */
+
+};
+
+/* Timeout values */
+#define SK_MAC_TO_53 72 /* MAC arbiter timeout */
+#define SK_PKT_TO_53 0x2000 /* Packet arbiter timeout */
+#define SK_PKT_TO_MAX 0xffff /* Maximum value */
+#define SK_RI_TO_53 36 /* RAM interface timeout */
+
+/* Packet Arbiter Registers */
+/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */
+enum {
+ PA_CLR_TO_TX2 = 1<<13,/* Clear IRQ Packet Timeout TX2 */
+ PA_CLR_TO_TX1 = 1<<12,/* Clear IRQ Packet Timeout TX1 */
+ PA_CLR_TO_RX2 = 1<<11,/* Clear IRQ Packet Timeout RX2 */
+ PA_CLR_TO_RX1 = 1<<10,/* Clear IRQ Packet Timeout RX1 */
+ PA_ENA_TO_TX2 = 1<<9, /* Enable Timeout Timer TX2 */
+ PA_DIS_TO_TX2 = 1<<8, /* Disable Timeout Timer TX2 */
+ PA_ENA_TO_TX1 = 1<<7, /* Enable Timeout Timer TX1 */
+ PA_DIS_TO_TX1 = 1<<6, /* Disable Timeout Timer TX1 */
+ PA_ENA_TO_RX2 = 1<<5, /* Enable Timeout Timer RX2 */
+ PA_DIS_TO_RX2 = 1<<4, /* Disable Timeout Timer RX2 */
+ PA_ENA_TO_RX1 = 1<<3, /* Enable Timeout Timer RX1 */
+ PA_DIS_TO_RX1 = 1<<2, /* Disable Timeout Timer RX1 */
+ PA_RST_CLR = 1<<1, /* Clear MAC Arbiter Reset */
+ PA_RST_SET = 1<<0, /* Set MAC Arbiter Reset */
+};
+
+#define PA_ENA_TO_ALL (PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\
+ PA_ENA_TO_TX1 | PA_ENA_TO_TX2)
+
+
+/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */
+/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */
+/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */
+/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */
+/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */
+
+#define TXA_MAX_VAL 0x00ffffffUL /* Bit 23.. 0: Max TXA Timer/Cnt Val */
+
+/* TXA_CTRL 8 bit Tx Arbiter Control Register */
+enum {
+ TXA_ENA_FSYNC = 1<<7, /* Enable force of sync Tx queue */
+ TXA_DIS_FSYNC = 1<<6, /* Disable force of sync Tx queue */
+ TXA_ENA_ALLOC = 1<<5, /* Enable alloc of free bandwidth */
+ TXA_DIS_ALLOC = 1<<4, /* Disable alloc of free bandwidth */
+ TXA_START_RC = 1<<3, /* Start sync Rate Control */
+ TXA_STOP_RC = 1<<2, /* Stop sync Rate Control */
+ TXA_ENA_ARB = 1<<1, /* Enable Tx Arbiter */
+ TXA_DIS_ARB = 1<<0, /* Disable Tx Arbiter */
+};
+
+/*
+ * Bank 4 - 5
+ */
+/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */
+enum {
+ TXA_ITI_INI = 0x0200,/* 32 bit Tx Arb Interval Timer Init Val*/
+ TXA_ITI_VAL = 0x0204,/* 32 bit Tx Arb Interval Timer Value */
+ TXA_LIM_INI = 0x0208,/* 32 bit Tx Arb Limit Counter Init Val */
+ TXA_LIM_VAL = 0x020c,/* 32 bit Tx Arb Limit Counter Value */
+ TXA_CTRL = 0x0210,/* 8 bit Tx Arbiter Control Register */
+ TXA_TEST = 0x0211,/* 8 bit Tx Arbiter Test Register */
+ TXA_STAT = 0x0212,/* 8 bit Tx Arbiter Status Register */
+};
+
+
+enum {
+ B6_EXT_REG = 0x0300,/* External registers (GENESIS only) */
+ B7_CFG_SPC = 0x0380,/* copy of the Configuration register */
+ B8_RQ1_REGS = 0x0400,/* Receive Queue 1 */
+ B8_RQ2_REGS = 0x0480,/* Receive Queue 2 */
+ B8_TS1_REGS = 0x0600,/* Transmit sync queue 1 */
+ B8_TA1_REGS = 0x0680,/* Transmit async queue 1 */
+ B8_TS2_REGS = 0x0700,/* Transmit sync queue 2 */
+ B8_TA2_REGS = 0x0780,/* Transmit sync queue 2 */
+ B16_RAM_REGS = 0x0800,/* RAM Buffer Registers */
+};
+
+/* Queue Register Offsets, use Q_ADDR() to access */
+enum {
+ B8_Q_REGS = 0x0400, /* base of Queue registers */
+ Q_D = 0x00, /* 8*32 bit Current Descriptor */
+ Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */
+ Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */
+ Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */
+ Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */
+ Q_BC = 0x30, /* 32 bit Current Byte Counter */
+ Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */
+ Q_F = 0x38, /* 32 bit Flag Register */
+ Q_T1 = 0x3c, /* 32 bit Test Register 1 */
+ Q_T1_TR = 0x3c, /* 8 bit Test Register 1 Transfer SM */
+ Q_T1_WR = 0x3d, /* 8 bit Test Register 1 Write Descriptor SM */
+ Q_T1_RD = 0x3e, /* 8 bit Test Register 1 Read Descriptor SM */
+ Q_T1_SV = 0x3f, /* 8 bit Test Register 1 Supervisor SM */
+ Q_T2 = 0x40, /* 32 bit Test Register 2 */
+ Q_T3 = 0x44, /* 32 bit Test Register 3 */
+
+};
+#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
+
+/* RAM Buffer Register Offsets */
+enum {
+
+ RB_START= 0x00,/* 32 bit RAM Buffer Start Address */
+ RB_END = 0x04,/* 32 bit RAM Buffer End Address */
+ RB_WP = 0x08,/* 32 bit RAM Buffer Write Pointer */
+ RB_RP = 0x0c,/* 32 bit RAM Buffer Read Pointer */
+ RB_RX_UTPP= 0x10,/* 32 bit Rx Upper Threshold, Pause Packet */
+ RB_RX_LTPP= 0x14,/* 32 bit Rx Lower Threshold, Pause Packet */
+ RB_RX_UTHP= 0x18,/* 32 bit Rx Upper Threshold, High Prio */
+ RB_RX_LTHP= 0x1c,/* 32 bit Rx Lower Threshold, High Prio */
+ /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */
+ RB_PC = 0x20,/* 32 bit RAM Buffer Packet Counter */
+ RB_LEV = 0x24,/* 32 bit RAM Buffer Level Register */
+ RB_CTRL = 0x28,/* 32 bit RAM Buffer Control Register */
+ RB_TST1 = 0x29,/* 8 bit RAM Buffer Test Register 1 */
+ RB_TST2 = 0x2a,/* 8 bit RAM Buffer Test Register 2 */
+};
+
+/* Receive and Transmit Queues */
+enum {
+ Q_R1 = 0x0000, /* Receive Queue 1 */
+ Q_R2 = 0x0080, /* Receive Queue 2 */
+ Q_XS1 = 0x0200, /* Synchronous Transmit Queue 1 */
+ Q_XA1 = 0x0280, /* Asynchronous Transmit Queue 1 */
+ Q_XS2 = 0x0300, /* Synchronous Transmit Queue 2 */
+ Q_XA2 = 0x0380, /* Asynchronous Transmit Queue 2 */
+};
+
+/* Different MAC Types */
+enum {
+ SK_MAC_XMAC = 0, /* Xaqti XMAC II */
+ SK_MAC_GMAC = 1, /* Marvell GMAC */
+};
+
+/* Different PHY Types */
+enum {
+ SK_PHY_XMAC = 0,/* integrated in XMAC II */
+ SK_PHY_BCOM = 1,/* Broadcom BCM5400 */
+ SK_PHY_LONE = 2,/* Level One LXT1000 [not supported]*/
+ SK_PHY_NAT = 3,/* National DP83891 [not supported] */
+ SK_PHY_MARV_COPPER= 4,/* Marvell 88E1011S */
+ SK_PHY_MARV_FIBER = 5,/* Marvell 88E1011S working on fiber */
+};
+
+/* PHY addresses (bits 12..8 of PHY address reg) */
+enum {
+ PHY_ADDR_XMAC = 0<<8,
+ PHY_ADDR_BCOM = 1<<8,
+
+/* GPHY address (bits 15..11 of SMI control reg) */
+ PHY_ADDR_MARV = 0,
+};
+
+#define RB_ADDR(offs, queue) ((u16)B16_RAM_REGS + (u16)(queue) + (offs))
+
+/* Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only) */
+enum {
+ RX_MFF_EA = 0x0c00,/* 32 bit Receive MAC FIFO End Address */
+ RX_MFF_WP = 0x0c04,/* 32 bit Receive MAC FIFO Write Pointer */
+
+ RX_MFF_RP = 0x0c0c,/* 32 bit Receive MAC FIFO Read Pointer */
+ RX_MFF_PC = 0x0c10,/* 32 bit Receive MAC FIFO Packet Cnt */
+ RX_MFF_LEV = 0x0c14,/* 32 bit Receive MAC FIFO Level */
+ RX_MFF_CTRL1 = 0x0c18,/* 16 bit Receive MAC FIFO Control Reg 1*/
+ RX_MFF_STAT_TO = 0x0c1a,/* 8 bit Receive MAC Status Timeout */
+ RX_MFF_TIST_TO = 0x0c1b,/* 8 bit Receive MAC Time Stamp Timeout */
+ RX_MFF_CTRL2 = 0x0c1c,/* 8 bit Receive MAC FIFO Control Reg 2*/
+ RX_MFF_TST1 = 0x0c1d,/* 8 bit Receive MAC FIFO Test Reg 1 */
+ RX_MFF_TST2 = 0x0c1e,/* 8 bit Receive MAC FIFO Test Reg 2 */
+
+ RX_LED_INI = 0x0c20,/* 32 bit Receive LED Cnt Init Value */
+ RX_LED_VAL = 0x0c24,/* 32 bit Receive LED Cnt Current Value */
+ RX_LED_CTRL = 0x0c28,/* 8 bit Receive LED Cnt Control Reg */
+ RX_LED_TST = 0x0c29,/* 8 bit Receive LED Cnt Test Register */
+
+ LNK_SYNC_INI = 0x0c30,/* 32 bit Link Sync Cnt Init Value */
+ LNK_SYNC_VAL = 0x0c34,/* 32 bit Link Sync Cnt Current Value */
+ LNK_SYNC_CTRL = 0x0c38,/* 8 bit Link Sync Cnt Control Register */
+ LNK_SYNC_TST = 0x0c39,/* 8 bit Link Sync Cnt Test Register */
+ LNK_LED_REG = 0x0c3c,/* 8 bit Link LED Register */
+};
+
+/* Receive and Transmit MAC FIFO Registers (GENESIS only) */
+/* RX_MFF_CTRL1 16 bit Receive MAC FIFO Control Reg 1 */
+enum {
+ MFF_ENA_RDY_PAT = 1<<13, /* Enable Ready Patch */
+ MFF_DIS_RDY_PAT = 1<<12, /* Disable Ready Patch */
+ MFF_ENA_TIM_PAT = 1<<11, /* Enable Timing Patch */
+ MFF_DIS_TIM_PAT = 1<<10, /* Disable Timing Patch */
+ MFF_ENA_ALM_FUL = 1<<9, /* Enable AlmostFull Sign */
+ MFF_DIS_ALM_FUL = 1<<8, /* Disable AlmostFull Sign */
+ MFF_ENA_PAUSE = 1<<7, /* Enable Pause Signaling */
+ MFF_DIS_PAUSE = 1<<6, /* Disable Pause Signaling */
+ MFF_ENA_FLUSH = 1<<5, /* Enable Frame Flushing */
+ MFF_DIS_FLUSH = 1<<4, /* Disable Frame Flushing */
+ MFF_ENA_TIST = 1<<3, /* Enable Time Stamp Gener */
+ MFF_DIS_TIST = 1<<2, /* Disable Time Stamp Gener */
+ MFF_CLR_INTIST = 1<<1, /* Clear IRQ No Time Stamp */
+ MFF_CLR_INSTAT = 1<<0, /* Clear IRQ No Status */
+ MFF_RX_CTRL_DEF = MFF_ENA_TIM_PAT,
+};
+
+/* TX_MFF_CTRL1 16 bit Transmit MAC FIFO Control Reg 1 */
+enum {
+ MFF_CLR_PERR = 1<<15, /* Clear Parity Error IRQ */
+
+ MFF_ENA_PKT_REC = 1<<13, /* Enable Packet Recovery */
+ MFF_DIS_PKT_REC = 1<<12, /* Disable Packet Recovery */
+
+ MFF_ENA_W4E = 1<<7, /* Enable Wait for Empty */
+ MFF_DIS_W4E = 1<<6, /* Disable Wait for Empty */
+
+ MFF_ENA_LOOPB = 1<<3, /* Enable Loopback */
+ MFF_DIS_LOOPB = 1<<2, /* Disable Loopback */
+ MFF_CLR_MAC_RST = 1<<1, /* Clear XMAC Reset */
+ MFF_SET_MAC_RST = 1<<0, /* Set XMAC Reset */
+
+ MFF_TX_CTRL_DEF = MFF_ENA_PKT_REC | (u16) MFF_ENA_TIM_PAT | MFF_ENA_FLUSH,
+};
+
+
+/* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */
+/* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */
+enum {
+ MFF_WSP_T_ON = 1<<6, /* Tx: Write Shadow Ptr TestOn */
+ MFF_WSP_T_OFF = 1<<5, /* Tx: Write Shadow Ptr TstOff */
+ MFF_WSP_INC = 1<<4, /* Tx: Write Shadow Ptr Increment */
+ MFF_PC_DEC = 1<<3, /* Packet Counter Decrement */
+ MFF_PC_T_ON = 1<<2, /* Packet Counter Test On */
+ MFF_PC_T_OFF = 1<<1, /* Packet Counter Test Off */
+ MFF_PC_INC = 1<<0, /* Packet Counter Increment */
+};
+
+/* RX_MFF_TST1 8 bit Receive MAC FIFO Test Register 1 */
+/* TX_MFF_TST1 8 bit Transmit MAC FIFO Test Register 1 */
+enum {
+ MFF_WP_T_ON = 1<<6, /* Write Pointer Test On */
+ MFF_WP_T_OFF = 1<<5, /* Write Pointer Test Off */
+ MFF_WP_INC = 1<<4, /* Write Pointer Increm */
+
+ MFF_RP_T_ON = 1<<2, /* Read Pointer Test On */
+ MFF_RP_T_OFF = 1<<1, /* Read Pointer Test Off */
+ MFF_RP_DEC = 1<<0, /* Read Pointer Decrement */
+};
+
+/* RX_MFF_CTRL2 8 bit Receive MAC FIFO Control Reg 2 */
+/* TX_MFF_CTRL2 8 bit Transmit MAC FIFO Control Reg 2 */
+enum {
+ MFF_ENA_OP_MD = 1<<3, /* Enable Operation Mode */
+ MFF_DIS_OP_MD = 1<<2, /* Disable Operation Mode */
+ MFF_RST_CLR = 1<<1, /* Clear MAC FIFO Reset */
+ MFF_RST_SET = 1<<0, /* Set MAC FIFO Reset */
+};
+
+
+/* Link LED Counter Registers (GENESIS only) */
+
+/* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */
+/* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */
+/* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */
+enum {
+ LED_START = 1<<2, /* Start Timer */
+ LED_STOP = 1<<1, /* Stop Timer */
+ LED_STATE = 1<<0, /* Rx/Tx: LED State, 1=LED on */
+};
+
+/* RX_LED_TST 8 bit Receive LED Cnt Test Register */
+/* TX_LED_TST 8 bit Transmit LED Cnt Test Register */
+/* LNK_SYNC_TST 8 bit Link Sync Cnt Test Register */
+enum {
+ LED_T_ON = 1<<2, /* LED Counter Test mode On */
+ LED_T_OFF = 1<<1, /* LED Counter Test mode Off */
+ LED_T_STEP = 1<<0, /* LED Counter Step */
+};
+
+/* LNK_LED_REG 8 bit Link LED Register */
+enum {
+ LED_BLK_ON = 1<<5, /* Link LED Blinking On */
+ LED_BLK_OFF = 1<<4, /* Link LED Blinking Off */
+ LED_SYNC_ON = 1<<3, /* Use Sync Wire to switch LED */
+ LED_SYNC_OFF = 1<<2, /* Disable Sync Wire Input */
+ LED_ON = 1<<1, /* switch LED on */
+ LED_OFF = 1<<0, /* switch LED off */
+};
+
+/* Receive GMAC FIFO (YUKON) */
+enum {
+ RX_GMF_EA = 0x0c40,/* 32 bit Rx GMAC FIFO End Address */
+ RX_GMF_AF_THR = 0x0c44,/* 32 bit Rx GMAC FIFO Almost Full Thresh. */
+ RX_GMF_CTRL_T = 0x0c48,/* 32 bit Rx GMAC FIFO Control/Test */
+ RX_GMF_FL_MSK = 0x0c4c,/* 32 bit Rx GMAC FIFO Flush Mask */
+ RX_GMF_FL_THR = 0x0c50,/* 32 bit Rx GMAC FIFO Flush Threshold */
+ RX_GMF_WP = 0x0c60,/* 32 bit Rx GMAC FIFO Write Pointer */
+ RX_GMF_WLEV = 0x0c68,/* 32 bit Rx GMAC FIFO Write Level */
+ RX_GMF_RP = 0x0c70,/* 32 bit Rx GMAC FIFO Read Pointer */
+ RX_GMF_RLEV = 0x0c78,/* 32 bit Rx GMAC FIFO Read Level */
+};
+
+
+/* TXA_TEST 8 bit Tx Arbiter Test Register */
+enum {
+ TXA_INT_T_ON = 1<<5, /* Tx Arb Interval Timer Test On */
+ TXA_INT_T_OFF = 1<<4, /* Tx Arb Interval Timer Test Off */
+ TXA_INT_T_STEP = 1<<3, /* Tx Arb Interval Timer Step */
+ TXA_LIM_T_ON = 1<<2, /* Tx Arb Limit Timer Test On */
+ TXA_LIM_T_OFF = 1<<1, /* Tx Arb Limit Timer Test Off */
+ TXA_LIM_T_STEP = 1<<0, /* Tx Arb Limit Timer Step */
+};
+
+/* TXA_STAT 8 bit Tx Arbiter Status Register */
+enum {
+ TXA_PRIO_XS = 1<<0, /* sync queue has prio to send */
+};
+
+
+/* Q_BC 32 bit Current Byte Counter */
+
+/* BMU Control Status Registers */
+/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */
+/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */
+/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */
+/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */
+/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */
+/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */
+/* Q_CSR 32 bit BMU Control/Status Register */
+
+enum {
+ CSR_SV_IDLE = 1<<24, /* BMU SM Idle */
+
+ CSR_DESC_CLR = 1<<21, /* Clear Reset for Descr */
+ CSR_DESC_SET = 1<<20, /* Set Reset for Descr */
+ CSR_FIFO_CLR = 1<<19, /* Clear Reset for FIFO */
+ CSR_FIFO_SET = 1<<18, /* Set Reset for FIFO */
+ CSR_HPI_RUN = 1<<17, /* Release HPI SM */
+ CSR_HPI_RST = 1<<16, /* Reset HPI SM to Idle */
+ CSR_SV_RUN = 1<<15, /* Release Supervisor SM */
+ CSR_SV_RST = 1<<14, /* Reset Supervisor SM */
+ CSR_DREAD_RUN = 1<<13, /* Release Descr Read SM */
+ CSR_DREAD_RST = 1<<12, /* Reset Descr Read SM */
+ CSR_DWRITE_RUN = 1<<11, /* Release Descr Write SM */
+ CSR_DWRITE_RST = 1<<10, /* Reset Descr Write SM */
+ CSR_TRANS_RUN = 1<<9, /* Release Transfer SM */
+ CSR_TRANS_RST = 1<<8, /* Reset Transfer SM */
+ CSR_ENA_POL = 1<<7, /* Enable Descr Polling */
+ CSR_DIS_POL = 1<<6, /* Disable Descr Polling */
+ CSR_STOP = 1<<5, /* Stop Rx/Tx Queue */
+ CSR_START = 1<<4, /* Start Rx/Tx Queue */
+ CSR_IRQ_CL_P = 1<<3, /* (Rx) Clear Parity IRQ */
+ CSR_IRQ_CL_B = 1<<2, /* Clear EOB IRQ */
+ CSR_IRQ_CL_F = 1<<1, /* Clear EOF IRQ */
+ CSR_IRQ_CL_C = 1<<0, /* Clear ERR IRQ */
+};
+
+#define CSR_SET_RESET (CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\
+ CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\
+ CSR_TRANS_RST)
+#define CSR_CLR_RESET (CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\
+ CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\
+ CSR_TRANS_RUN)
+
+/* Q_F 32 bit Flag Register */
+enum {
+ F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */
+ F_EMPTY = 1<<27, /* Tx FIFO: empty flag */
+ F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */
+ F_WM_REACHED = 1<<25, /* Watermark reached */
+
+ F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */
+ F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */
+};
+
+/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
+/* RB_START 32 bit RAM Buffer Start Address */
+/* RB_END 32 bit RAM Buffer End Address */
+/* RB_WP 32 bit RAM Buffer Write Pointer */
+/* RB_RP 32 bit RAM Buffer Read Pointer */
+/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */
+/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */
+/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */
+/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */
+/* RB_PC 32 bit RAM Buffer Packet Counter */
+/* RB_LEV 32 bit RAM Buffer Level Register */
+
+#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */
+/* RB_TST2 8 bit RAM Buffer Test Register 2 */
+/* RB_TST1 8 bit RAM Buffer Test Register 1 */
+
+/* RB_CTRL 8 bit RAM Buffer Control Register */
+enum {
+ RB_ENA_STFWD = 1<<5, /* Enable Store & Forward */
+ RB_DIS_STFWD = 1<<4, /* Disable Store & Forward */
+ RB_ENA_OP_MD = 1<<3, /* Enable Operation Mode */
+ RB_DIS_OP_MD = 1<<2, /* Disable Operation Mode */
+ RB_RST_CLR = 1<<1, /* Clear RAM Buf STM Reset */
+ RB_RST_SET = 1<<0, /* Set RAM Buf STM Reset */
+};
+
+/* Transmit MAC FIFO and Transmit LED Registers (GENESIS only), */
+enum {
+ TX_MFF_EA = 0x0d00,/* 32 bit Transmit MAC FIFO End Address */
+ TX_MFF_WP = 0x0d04,/* 32 bit Transmit MAC FIFO WR Pointer */
+ TX_MFF_WSP = 0x0d08,/* 32 bit Transmit MAC FIFO WR Shadow Ptr */
+ TX_MFF_RP = 0x0d0c,/* 32 bit Transmit MAC FIFO RD Pointer */
+ TX_MFF_PC = 0x0d10,/* 32 bit Transmit MAC FIFO Packet Cnt */
+ TX_MFF_LEV = 0x0d14,/* 32 bit Transmit MAC FIFO Level */
+ TX_MFF_CTRL1 = 0x0d18,/* 16 bit Transmit MAC FIFO Ctrl Reg 1 */
+ TX_MFF_WAF = 0x0d1a,/* 8 bit Transmit MAC Wait after flush */
+
+ TX_MFF_CTRL2 = 0x0d1c,/* 8 bit Transmit MAC FIFO Ctrl Reg 2 */
+ TX_MFF_TST1 = 0x0d1d,/* 8 bit Transmit MAC FIFO Test Reg 1 */
+ TX_MFF_TST2 = 0x0d1e,/* 8 bit Transmit MAC FIFO Test Reg 2 */
+
+ TX_LED_INI = 0x0d20,/* 32 bit Transmit LED Cnt Init Value */
+ TX_LED_VAL = 0x0d24,/* 32 bit Transmit LED Cnt Current Val */
+ TX_LED_CTRL = 0x0d28,/* 8 bit Transmit LED Cnt Control Reg */
+ TX_LED_TST = 0x0d29,/* 8 bit Transmit LED Cnt Test Reg */
+};
+
+/* Counter and Timer constants, for a host clock of 62.5 MHz */
+#define SK_XMIT_DUR 0x002faf08UL /* 50 ms */
+#define SK_BLK_DUR 0x01dcd650UL /* 500 ms */
+
+#define SK_DPOLL_DEF 0x00ee6b28UL /* 250 ms at 62.5 MHz */
+
+#define SK_DPOLL_MAX 0x00ffffffUL /* 268 ms at 62.5 MHz */
+ /* 215 ms at 78.12 MHz */
+
+#define SK_FACT_62 100 /* is given in percent */
+#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */
+#define SK_FACT_78 125 /* on YUKON: 78.12 MHz */
+
+
+/* Transmit GMAC FIFO (YUKON only) */
+enum {
+ TX_GMF_EA = 0x0d40,/* 32 bit Tx GMAC FIFO End Address */
+ TX_GMF_AE_THR = 0x0d44,/* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/
+ TX_GMF_CTRL_T = 0x0d48,/* 32 bit Tx GMAC FIFO Control/Test */
+
+ TX_GMF_WP = 0x0d60,/* 32 bit Tx GMAC FIFO Write Pointer */
+ TX_GMF_WSP = 0x0d64,/* 32 bit Tx GMAC FIFO Write Shadow Ptr. */
+ TX_GMF_WLEV = 0x0d68,/* 32 bit Tx GMAC FIFO Write Level */
+
+ TX_GMF_RP = 0x0d70,/* 32 bit Tx GMAC FIFO Read Pointer */
+ TX_GMF_RSTP = 0x0d74,/* 32 bit Tx GMAC FIFO Restart Pointer */
+ TX_GMF_RLEV = 0x0d78,/* 32 bit Tx GMAC FIFO Read Level */
+
+ /* Descriptor Poll Timer Registers */
+ B28_DPT_INI = 0x0e00,/* 24 bit Descriptor Poll Timer Init Val */
+ B28_DPT_VAL = 0x0e04,/* 24 bit Descriptor Poll Timer Curr Val */
+ B28_DPT_CTRL = 0x0e08,/* 8 bit Descriptor Poll Timer Ctrl Reg */
+
+ B28_DPT_TST = 0x0e0a,/* 8 bit Descriptor Poll Timer Test Reg */
+
+ /* Time Stamp Timer Registers (YUKON only) */
+ GMAC_TI_ST_VAL = 0x0e14,/* 32 bit Time Stamp Timer Curr Val */
+ GMAC_TI_ST_CTRL = 0x0e18,/* 8 bit Time Stamp Timer Ctrl Reg */
+ GMAC_TI_ST_TST = 0x0e1a,/* 8 bit Time Stamp Timer Test Reg */
+};
+
+
+enum {
+ LINKLED_OFF = 0x01,
+ LINKLED_ON = 0x02,
+ LINKLED_LINKSYNC_OFF = 0x04,
+ LINKLED_LINKSYNC_ON = 0x08,
+ LINKLED_BLINK_OFF = 0x10,
+ LINKLED_BLINK_ON = 0x20,
+};
+
+/* GMAC and GPHY Control Registers (YUKON only) */
+enum {
+ GMAC_CTRL = 0x0f00,/* 32 bit GMAC Control Reg */
+ GPHY_CTRL = 0x0f04,/* 32 bit GPHY Control Reg */
+ GMAC_IRQ_SRC = 0x0f08,/* 8 bit GMAC Interrupt Source Reg */
+ GMAC_IRQ_MSK = 0x0f0c,/* 8 bit GMAC Interrupt Mask Reg */
+ GMAC_LINK_CTRL = 0x0f10,/* 16 bit Link Control Reg */
+
+/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
+
+ WOL_REG_OFFS = 0x20,/* HW-Bug: Address is + 0x20 against spec. */
+
+ WOL_CTRL_STAT = 0x0f20,/* 16 bit WOL Control/Status Reg */
+ WOL_MATCH_CTL = 0x0f22,/* 8 bit WOL Match Control Reg */
+ WOL_MATCH_RES = 0x0f23,/* 8 bit WOL Match Result Reg */
+ WOL_MAC_ADDR = 0x0f24,/* 32 bit WOL MAC Address */
+ WOL_PATT_RPTR = 0x0f2c,/* 8 bit WOL Pattern Read Pointer */
+
+/* WOL Pattern Length Registers (YUKON only) */
+
+ WOL_PATT_LEN_LO = 0x0f30,/* 32 bit WOL Pattern Length 3..0 */
+ WOL_PATT_LEN_HI = 0x0f34,/* 24 bit WOL Pattern Length 6..4 */
+
+/* WOL Pattern Counter Registers (YUKON only) */
+
+ WOL_PATT_CNT_0 = 0x0f38,/* 32 bit WOL Pattern Counter 3..0 */
+ WOL_PATT_CNT_4 = 0x0f3c,/* 24 bit WOL Pattern Counter 6..4 */
+};
+#define WOL_REGS(port, x) (x + (port)*0x80)
+
+enum {
+ WOL_PATT_RAM_1 = 0x1000,/* WOL Pattern RAM Link 1 */
+ WOL_PATT_RAM_2 = 0x1400,/* WOL Pattern RAM Link 2 */
+};
+#define WOL_PATT_RAM_BASE(port) (WOL_PATT_RAM_1 + (port)*0x400)
+
+enum {
+ BASE_XMAC_1 = 0x2000,/* XMAC 1 registers */
+ BASE_GMAC_1 = 0x2800,/* GMAC 1 registers */
+ BASE_XMAC_2 = 0x3000,/* XMAC 2 registers */
+ BASE_GMAC_2 = 0x3800,/* GMAC 2 registers */
+};
+
+/*
+ * Receive Frame Status Encoding
+ */
+enum {
+ XMR_FS_LEN = 0x3fff<<18, /* Bit 31..18: Rx Frame Length */
+ XMR_FS_LEN_SHIFT = 18,
+ XMR_FS_2L_VLAN = 1<<17, /* Bit 17: tagged wh 2Lev VLAN ID*/
+ XMR_FS_1_VLAN = 1<<16, /* Bit 16: tagged wh 1ev VLAN ID*/
+ XMR_FS_BC = 1<<15, /* Bit 15: Broadcast Frame */
+ XMR_FS_MC = 1<<14, /* Bit 14: Multicast Frame */
+ XMR_FS_UC = 1<<13, /* Bit 13: Unicast Frame */
+
+ XMR_FS_BURST = 1<<11, /* Bit 11: Burst Mode */
+ XMR_FS_CEX_ERR = 1<<10, /* Bit 10: Carrier Ext. Error */
+ XMR_FS_802_3 = 1<<9, /* Bit 9: 802.3 Frame */
+ XMR_FS_COL_ERR = 1<<8, /* Bit 8: Collision Error */
+ XMR_FS_CAR_ERR = 1<<7, /* Bit 7: Carrier Event Error */
+ XMR_FS_LEN_ERR = 1<<6, /* Bit 6: In-Range Length Error */
+ XMR_FS_FRA_ERR = 1<<5, /* Bit 5: Framing Error */
+ XMR_FS_RUNT = 1<<4, /* Bit 4: Runt Frame */
+ XMR_FS_LNG_ERR = 1<<3, /* Bit 3: Giant (Jumbo) Frame */
+ XMR_FS_FCS_ERR = 1<<2, /* Bit 2: Frame Check Sequ Err */
+ XMR_FS_ERR = 1<<1, /* Bit 1: Frame Error */
+ XMR_FS_MCTRL = 1<<0, /* Bit 0: MAC Control Packet */
+
+/*
+ * XMR_FS_ERR will be set if
+ * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT,
+ * XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR
+ * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue
+ * XMR_FS_ERR unless the corresponding bit in the Receive Command
+ * Register is set.
+ */
+};
+
+/*
+,* XMAC-PHY Registers, indirect addressed over the XMAC
+ */
+enum {
+ PHY_XMAC_CTRL = 0x00,/* 16 bit r/w PHY Control Register */
+ PHY_XMAC_STAT = 0x01,/* 16 bit r/w PHY Status Register */
+ PHY_XMAC_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */
+ PHY_XMAC_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */
+ PHY_XMAC_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */
+ PHY_XMAC_AUNE_LP = 0x05,/* 16 bit r/o Link Partner Abi Reg */
+ PHY_XMAC_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */
+ PHY_XMAC_NEPG = 0x07,/* 16 bit r/w Next Page Register */
+ PHY_XMAC_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */
+
+ PHY_XMAC_EXT_STAT = 0x0f,/* 16 bit r/o Ext Status Register */
+ PHY_XMAC_RES_ABI = 0x10,/* 16 bit r/o PHY Resolved Ability */
+};
+/*
+ * Broadcom-PHY Registers, indirect addressed over XMAC
+ */
+enum {
+ PHY_BCOM_CTRL = 0x00,/* 16 bit r/w PHY Control Register */
+ PHY_BCOM_STAT = 0x01,/* 16 bit r/o PHY Status Register */
+ PHY_BCOM_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */
+ PHY_BCOM_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */
+ PHY_BCOM_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */
+ PHY_BCOM_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */
+ PHY_BCOM_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */
+ PHY_BCOM_NEPG = 0x07,/* 16 bit r/w Next Page Register */
+ PHY_BCOM_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */
+ /* Broadcom-specific registers */
+ PHY_BCOM_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */
+ PHY_BCOM_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */
+ PHY_BCOM_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */
+ PHY_BCOM_P_EXT_CTRL = 0x10,/* 16 bit r/w PHY Extended Ctrl Reg */
+ PHY_BCOM_P_EXT_STAT = 0x11,/* 16 bit r/o PHY Extended Stat Reg */
+ PHY_BCOM_RE_CTR = 0x12,/* 16 bit r/w Receive Error Counter */
+ PHY_BCOM_FC_CTR = 0x13,/* 16 bit r/w False Carrier Sense Cnt */
+ PHY_BCOM_RNO_CTR = 0x14,/* 16 bit r/w Receiver NOT_OK Cnt */
+
+ PHY_BCOM_AUX_CTRL = 0x18,/* 16 bit r/w Auxiliary Control Reg */
+ PHY_BCOM_AUX_STAT = 0x19,/* 16 bit r/o Auxiliary Stat Summary */
+ PHY_BCOM_INT_STAT = 0x1a,/* 16 bit r/o Interrupt Status Reg */
+ PHY_BCOM_INT_MASK = 0x1b,/* 16 bit r/w Interrupt Mask Reg */
+};
+
+/*
+ * Marvel-PHY Registers, indirect addressed over GMAC
+ */
+enum {
+ PHY_MARV_CTRL = 0x00,/* 16 bit r/w PHY Control Register */
+ PHY_MARV_STAT = 0x01,/* 16 bit r/o PHY Status Register */
+ PHY_MARV_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */
+ PHY_MARV_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */
+ PHY_MARV_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */
+ PHY_MARV_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */
+ PHY_MARV_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */
+ PHY_MARV_NEPG = 0x07,/* 16 bit r/w Next Page Register */
+ PHY_MARV_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */
+ /* Marvel-specific registers */
+ PHY_MARV_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */
+ PHY_MARV_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */
+ PHY_MARV_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */
+ PHY_MARV_PHY_CTRL = 0x10,/* 16 bit r/w PHY Specific Ctrl Reg */
+ PHY_MARV_PHY_STAT = 0x11,/* 16 bit r/o PHY Specific Stat Reg */
+ PHY_MARV_INT_MASK = 0x12,/* 16 bit r/w Interrupt Mask Reg */
+ PHY_MARV_INT_STAT = 0x13,/* 16 bit r/o Interrupt Status Reg */
+ PHY_MARV_EXT_CTRL = 0x14,/* 16 bit r/w Ext. PHY Specific Ctrl */
+ PHY_MARV_RXE_CNT = 0x15,/* 16 bit r/w Receive Error Counter */
+ PHY_MARV_EXT_ADR = 0x16,/* 16 bit r/w Ext. Ad. for Cable Diag. */
+ PHY_MARV_PORT_IRQ = 0x17,/* 16 bit r/o Port 0 IRQ (88E1111 only) */
+ PHY_MARV_LED_CTRL = 0x18,/* 16 bit r/w LED Control Reg */
+ PHY_MARV_LED_OVER = 0x19,/* 16 bit r/w Manual LED Override Reg */
+ PHY_MARV_EXT_CTRL_2 = 0x1a,/* 16 bit r/w Ext. PHY Specific Ctrl 2 */
+ PHY_MARV_EXT_P_STAT = 0x1b,/* 16 bit r/w Ext. PHY Spec. Stat Reg */
+ PHY_MARV_CABLE_DIAG = 0x1c,/* 16 bit r/o Cable Diagnostic Reg */
+ PHY_MARV_PAGE_ADDR = 0x1d,/* 16 bit r/w Extended Page Address Reg */
+ PHY_MARV_PAGE_DATA = 0x1e,/* 16 bit r/w Extended Page Data Reg */
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+ PHY_MARV_FE_LED_PAR = 0x16,/* 16 bit r/w LED Parallel Select Reg. */
+ PHY_MARV_FE_LED_SER = 0x17,/* 16 bit r/w LED Stream Select S. LED */
+ PHY_MARV_FE_VCT_TX = 0x1a,/* 16 bit r/w VCT Reg. for TXP/N Pins */
+ PHY_MARV_FE_VCT_RX = 0x1b,/* 16 bit r/o VCT Reg. for RXP/N Pins */
+ PHY_MARV_FE_SPEC_2 = 0x1c,/* 16 bit r/w Specific Control Reg. 2 */
+};
+
+enum {
+ PHY_CT_RESET = 1<<15, /* Bit 15: (sc) clear all PHY related regs */
+ PHY_CT_LOOP = 1<<14, /* Bit 14: enable Loopback over PHY */
+ PHY_CT_SPS_LSB = 1<<13, /* Bit 13: Speed select, lower bit */
+ PHY_CT_ANE = 1<<12, /* Bit 12: Auto-Negotiation Enabled */
+ PHY_CT_PDOWN = 1<<11, /* Bit 11: Power Down Mode */
+ PHY_CT_ISOL = 1<<10, /* Bit 10: Isolate Mode */
+ PHY_CT_RE_CFG = 1<<9, /* Bit 9: (sc) Restart Auto-Negotiation */
+ PHY_CT_DUP_MD = 1<<8, /* Bit 8: Duplex Mode */
+ PHY_CT_COL_TST = 1<<7, /* Bit 7: Collision Test enabled */
+ PHY_CT_SPS_MSB = 1<<6, /* Bit 6: Speed select, upper bit */
+};
+
+enum {
+ PHY_CT_SP1000 = PHY_CT_SPS_MSB, /* enable speed of 1000 Mbps */
+ PHY_CT_SP100 = PHY_CT_SPS_LSB, /* enable speed of 100 Mbps */
+ PHY_CT_SP10 = 0, /* enable speed of 10 Mbps */
+};
+
+enum {
+ PHY_ST_EXT_ST = 1<<8, /* Bit 8: Extended Status Present */
+
+ PHY_ST_PRE_SUP = 1<<6, /* Bit 6: Preamble Suppression */
+ PHY_ST_AN_OVER = 1<<5, /* Bit 5: Auto-Negotiation Over */
+ PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occured */
+ PHY_ST_AN_CAP = 1<<3, /* Bit 3: Auto-Negotiation Capability */
+ PHY_ST_LSYNC = 1<<2, /* Bit 2: Link Synchronized */
+ PHY_ST_JAB_DET = 1<<1, /* Bit 1: Jabber Detected */
+ PHY_ST_EXT_REG = 1<<0, /* Bit 0: Extended Register available */
+};
+
+enum {
+ PHY_I1_OUI_MSK = 0x3f<<10, /* Bit 15..10: Organization Unique ID */
+ PHY_I1_MOD_NUM = 0x3f<<4, /* Bit 9.. 4: Model Number */
+ PHY_I1_REV_MSK = 0xf, /* Bit 3.. 0: Revision Number */
+};
+
+/* different Broadcom PHY Ids */
+enum {
+ PHY_BCOM_ID1_A1 = 0x6041,
+ PHY_BCOM_ID1_B2 = 0x6043,
+ PHY_BCOM_ID1_C0 = 0x6044,
+ PHY_BCOM_ID1_C5 = 0x6047,
+};
+
+/* different Marvell PHY Ids */
+enum {
+ PHY_MARV_ID0_VAL= 0x0141, /* Marvell Unique Identifier */
+ PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */
+ PHY_MARV_ID1_B2 = 0x0C25, /* Yukon-Plus (PHY 88E1011) */
+ PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */
+ PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */
+};
+
+/* Advertisement register bits */
+enum {
+ PHY_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */
+ PHY_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */
+ PHY_AN_RF = 1<<13, /* Bit 13: Remote Fault Bits */
+
+ PHY_AN_PAUSE_ASYM = 1<<11,/* Bit 11: Try for asymmetric */
+ PHY_AN_PAUSE_CAP = 1<<10, /* Bit 10: Try for pause */
+ PHY_AN_100BASE4 = 1<<9, /* Bit 9: Try for 100mbps 4k packets */
+ PHY_AN_100FULL = 1<<8, /* Bit 8: Try for 100mbps full-duplex */
+ PHY_AN_100HALF = 1<<7, /* Bit 7: Try for 100mbps half-duplex */
+ PHY_AN_10FULL = 1<<6, /* Bit 6: Try for 10mbps full-duplex */
+ PHY_AN_10HALF = 1<<5, /* Bit 5: Try for 10mbps half-duplex */
+ PHY_AN_CSMA = 1<<0, /* Bit 0: Only selector supported */
+ PHY_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/
+ PHY_AN_FULL = PHY_AN_100FULL | PHY_AN_10FULL | PHY_AN_CSMA,
+ PHY_AN_ALL = PHY_AN_10HALF | PHY_AN_10FULL |
+ PHY_AN_100HALF | PHY_AN_100FULL,
+};
+
+/* Xmac Specific */
+enum {
+ PHY_X_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */
+ PHY_X_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */
+ PHY_X_AN_RFB = 3<<12,/* Bit 13..12: Remote Fault Bits */
+
+ PHY_X_AN_PAUSE = 3<<7,/* Bit 8.. 7: Pause Bits */
+ PHY_X_AN_HD = 1<<6, /* Bit 6: Half Duplex */
+ PHY_X_AN_FD = 1<<5, /* Bit 5: Full Duplex */
+};
+
+/* Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding */
+enum {
+ PHY_X_P_NO_PAUSE= 0<<7,/* Bit 8..7: no Pause Mode */
+ PHY_X_P_SYM_MD = 1<<7, /* Bit 8..7: symmetric Pause Mode */
+ PHY_X_P_ASYM_MD = 2<<7,/* Bit 8..7: asymmetric Pause Mode */
+ PHY_X_P_BOTH_MD = 3<<7,/* Bit 8..7: both Pause Mode */
+};
+
+
+/***** PHY_XMAC_EXT_STAT 16 bit r/w Extended Status Register *****/
+enum {
+ PHY_X_EX_FD = 1<<15, /* Bit 15: Device Supports Full Duplex */
+ PHY_X_EX_HD = 1<<14, /* Bit 14: Device Supports Half Duplex */
+};
+
+/***** PHY_XMAC_RES_ABI 16 bit r/o PHY Resolved Ability *****/
+enum {
+ PHY_X_RS_PAUSE = 3<<7, /* Bit 8..7: selected Pause Mode */
+ PHY_X_RS_HD = 1<<6, /* Bit 6: Half Duplex Mode selected */
+ PHY_X_RS_FD = 1<<5, /* Bit 5: Full Duplex Mode selected */
+ PHY_X_RS_ABLMIS = 1<<4, /* Bit 4: duplex or pause cap mismatch */
+ PHY_X_RS_PAUMIS = 1<<3, /* Bit 3: pause capability mismatch */
+};
+
+/* Remote Fault Bits (PHY_X_AN_RFB) encoding */
+enum {
+ X_RFB_OK = 0<<12,/* Bit 13..12 No errors, Link OK */
+ X_RFB_LF = 1<<12,/* Bit 13..12 Link Failure */
+ X_RFB_OFF = 2<<12,/* Bit 13..12 Offline */
+ X_RFB_AN_ERR = 3<<12,/* Bit 13..12 Auto-Negotiation Error */
+};
+
+/* Broadcom-Specific */
+/***** PHY_BCOM_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
+enum {
+ PHY_B_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */
+ PHY_B_1000C_MSE = 1<<12, /* Bit 12: Master/Slave Enable */
+ PHY_B_1000C_MSC = 1<<11, /* Bit 11: M/S Configuration */
+ PHY_B_1000C_RD = 1<<10, /* Bit 10: Repeater/DTE */
+ PHY_B_1000C_AFD = 1<<9, /* Bit 9: Advertise Full Duplex */
+ PHY_B_1000C_AHD = 1<<8, /* Bit 8: Advertise Half Duplex */
+};
+
+/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+enum {
+ PHY_B_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */
+ PHY_B_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */
+ PHY_B_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */
+ PHY_B_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status */
+ PHY_B_1000S_LP_FD = 1<<11, /* Bit 11: Link Partner can FD */
+ PHY_B_1000S_LP_HD = 1<<10, /* Bit 10: Link Partner can HD */
+ /* Bit 9..8: reserved */
+ PHY_B_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */
+};
+
+/***** PHY_BCOM_EXT_STAT 16 bit r/o Extended Status Register *****/
+enum {
+ PHY_B_ES_X_FD_CAP = 1<<15, /* Bit 15: 1000Base-X FD capable */
+ PHY_B_ES_X_HD_CAP = 1<<14, /* Bit 14: 1000Base-X HD capable */
+ PHY_B_ES_T_FD_CAP = 1<<13, /* Bit 13: 1000Base-T FD capable */
+ PHY_B_ES_T_HD_CAP = 1<<12, /* Bit 12: 1000Base-T HD capable */
+};
+
+/***** PHY_BCOM_P_EXT_CTRL 16 bit r/w PHY Extended Control Reg *****/
+enum {
+ PHY_B_PEC_MAC_PHY = 1<<15, /* Bit 15: 10BIT/GMI-Interface */
+ PHY_B_PEC_DIS_CROSS = 1<<14, /* Bit 14: Disable MDI Crossover */
+ PHY_B_PEC_TX_DIS = 1<<13, /* Bit 13: Tx output Disabled */
+ PHY_B_PEC_INT_DIS = 1<<12, /* Bit 12: Interrupts Disabled */
+ PHY_B_PEC_F_INT = 1<<11, /* Bit 11: Force Interrupt */
+ PHY_B_PEC_BY_45 = 1<<10, /* Bit 10: Bypass 4B5B-Decoder */
+ PHY_B_PEC_BY_SCR = 1<<9, /* Bit 9: Bypass Scrambler */
+ PHY_B_PEC_BY_MLT3 = 1<<8, /* Bit 8: Bypass MLT3 Encoder */
+ PHY_B_PEC_BY_RXA = 1<<7, /* Bit 7: Bypass Rx Alignm. */
+ PHY_B_PEC_RES_SCR = 1<<6, /* Bit 6: Reset Scrambler */
+ PHY_B_PEC_EN_LTR = 1<<5, /* Bit 5: Ena LED Traffic Mode */
+ PHY_B_PEC_LED_ON = 1<<4, /* Bit 4: Force LED's on */
+ PHY_B_PEC_LED_OFF = 1<<3, /* Bit 3: Force LED's off */
+ PHY_B_PEC_EX_IPG = 1<<2, /* Bit 2: Extend Tx IPG Mode */
+ PHY_B_PEC_3_LED = 1<<1, /* Bit 1: Three Link LED mode */
+ PHY_B_PEC_HIGH_LA = 1<<0, /* Bit 0: GMII FIFO Elasticy */
+};
+
+/***** PHY_BCOM_P_EXT_STAT 16 bit r/o PHY Extended Status Reg *****/
+enum {
+ PHY_B_PES_CROSS_STAT = 1<<13, /* Bit 13: MDI Crossover Status */
+ PHY_B_PES_INT_STAT = 1<<12, /* Bit 12: Interrupt Status */
+ PHY_B_PES_RRS = 1<<11, /* Bit 11: Remote Receiver Stat. */
+ PHY_B_PES_LRS = 1<<10, /* Bit 10: Local Receiver Stat. */
+ PHY_B_PES_LOCKED = 1<<9, /* Bit 9: Locked */
+ PHY_B_PES_LS = 1<<8, /* Bit 8: Link Status */
+ PHY_B_PES_RF = 1<<7, /* Bit 7: Remote Fault */
+ PHY_B_PES_CE_ER = 1<<6, /* Bit 6: Carrier Ext Error */
+ PHY_B_PES_BAD_SSD = 1<<5, /* Bit 5: Bad SSD */
+ PHY_B_PES_BAD_ESD = 1<<4, /* Bit 4: Bad ESD */
+ PHY_B_PES_RX_ER = 1<<3, /* Bit 3: Receive Error */
+ PHY_B_PES_TX_ER = 1<<2, /* Bit 2: Transmit Error */
+ PHY_B_PES_LOCK_ER = 1<<1, /* Bit 1: Lock Error */
+ PHY_B_PES_MLT3_ER = 1<<0, /* Bit 0: MLT3 code Error */
+};
+
+/* PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
+/* PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
+enum {
+ PHY_B_AN_RF = 1<<13, /* Bit 13: Remote Fault */
+
+ PHY_B_AN_ASP = 1<<11, /* Bit 11: Asymmetric Pause */
+ PHY_B_AN_PC = 1<<10, /* Bit 10: Pause Capable */
+};
+
+
+/***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/
+enum {
+ PHY_B_FC_CTR = 0xff, /* Bit 7..0: False Carrier Counter */
+
+/***** PHY_BCOM_RNO_CTR 16 bit r/w Receive NOT_OK Counter *****/
+ PHY_B_RC_LOC_MSK = 0xff00, /* Bit 15..8: Local Rx NOT_OK cnt */
+ PHY_B_RC_REM_MSK = 0x00ff, /* Bit 7..0: Remote Rx NOT_OK cnt */
+
+/***** PHY_BCOM_AUX_CTRL 16 bit r/w Auxiliary Control Reg *****/
+ PHY_B_AC_L_SQE = 1<<15, /* Bit 15: Low Squelch */
+ PHY_B_AC_LONG_PACK = 1<<14, /* Bit 14: Rx Long Packets */
+ PHY_B_AC_ER_CTRL = 3<<12,/* Bit 13..12: Edgerate Control */
+ /* Bit 11: reserved */
+ PHY_B_AC_TX_TST = 1<<10, /* Bit 10: Tx test bit, always 1 */
+ /* Bit 9.. 8: reserved */
+ PHY_B_AC_DIS_PRF = 1<<7, /* Bit 7: dis part resp filter */
+ /* Bit 6: reserved */
+ PHY_B_AC_DIS_PM = 1<<5, /* Bit 5: dis power management */
+ /* Bit 4: reserved */
+ PHY_B_AC_DIAG = 1<<3, /* Bit 3: Diagnostic Mode */
+};
+
+/***** PHY_BCOM_AUX_STAT 16 bit r/o Auxiliary Status Reg *****/
+enum {
+ PHY_B_AS_AN_C = 1<<15, /* Bit 15: AutoNeg complete */
+ PHY_B_AS_AN_CA = 1<<14, /* Bit 14: AN Complete Ack */
+ PHY_B_AS_ANACK_D = 1<<13, /* Bit 13: AN Ack Detect */
+ PHY_B_AS_ANAB_D = 1<<12, /* Bit 12: AN Ability Detect */
+ PHY_B_AS_NPW = 1<<11, /* Bit 11: AN Next Page Wait */
+ PHY_B_AS_AN_RES_MSK = 7<<8,/* Bit 10..8: AN HDC */
+ PHY_B_AS_PDF = 1<<7, /* Bit 7: Parallel Detect. Fault */
+ PHY_B_AS_RF = 1<<6, /* Bit 6: Remote Fault */
+ PHY_B_AS_ANP_R = 1<<5, /* Bit 5: AN Page Received */
+ PHY_B_AS_LP_ANAB = 1<<4, /* Bit 4: LP AN Ability */
+ PHY_B_AS_LP_NPAB = 1<<3, /* Bit 3: LP Next Page Ability */
+ PHY_B_AS_LS = 1<<2, /* Bit 2: Link Status */
+ PHY_B_AS_PRR = 1<<1, /* Bit 1: Pause Resolution-Rx */
+ PHY_B_AS_PRT = 1<<0, /* Bit 0: Pause Resolution-Tx */
+};
+#define PHY_B_AS_PAUSE_MSK (PHY_B_AS_PRR | PHY_B_AS_PRT)
+
+/***** PHY_BCOM_INT_STAT 16 bit r/o Interrupt Status Reg *****/
+/***** PHY_BCOM_INT_MASK 16 bit r/w Interrupt Mask Reg *****/
+enum {
+ PHY_B_IS_PSE = 1<<14, /* Bit 14: Pair Swap Error */
+ PHY_B_IS_MDXI_SC = 1<<13, /* Bit 13: MDIX Status Change */
+ PHY_B_IS_HCT = 1<<12, /* Bit 12: counter above 32k */
+ PHY_B_IS_LCT = 1<<11, /* Bit 11: counter above 128 */
+ PHY_B_IS_AN_PR = 1<<10, /* Bit 10: Page Received */
+ PHY_B_IS_NO_HDCL = 1<<9, /* Bit 9: No HCD Link */
+ PHY_B_IS_NO_HDC = 1<<8, /* Bit 8: No HCD */
+ PHY_B_IS_NEG_USHDC = 1<<7, /* Bit 7: Negotiated Unsup. HCD */
+ PHY_B_IS_SCR_S_ER = 1<<6, /* Bit 6: Scrambler Sync Error */
+ PHY_B_IS_RRS_CHANGE = 1<<5, /* Bit 5: Remote Rx Stat Change */
+ PHY_B_IS_LRS_CHANGE = 1<<4, /* Bit 4: Local Rx Stat Change */
+ PHY_B_IS_DUP_CHANGE = 1<<3, /* Bit 3: Duplex Mode Change */
+ PHY_B_IS_LSP_CHANGE = 1<<2, /* Bit 2: Link Speed Change */
+ PHY_B_IS_LST_CHANGE = 1<<1, /* Bit 1: Link Status Changed */
+ PHY_B_IS_CRC_ER = 1<<0, /* Bit 0: CRC Error */
+};
+#define PHY_B_DEF_MSK \
+ (~(PHY_B_IS_PSE | PHY_B_IS_AN_PR | PHY_B_IS_DUP_CHANGE | \
+ PHY_B_IS_LSP_CHANGE | PHY_B_IS_LST_CHANGE))
+
+/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */
+enum {
+ PHY_B_P_NO_PAUSE = 0<<10,/* Bit 11..10: no Pause Mode */
+ PHY_B_P_SYM_MD = 1<<10, /* Bit 11..10: symmetric Pause Mode */
+ PHY_B_P_ASYM_MD = 2<<10,/* Bit 11..10: asymmetric Pause Mode */
+ PHY_B_P_BOTH_MD = 3<<10,/* Bit 11..10: both Pause Mode */
+};
+/*
+ * Resolved Duplex mode and Capabilities (Aux Status Summary Reg)
+ */
+enum {
+ PHY_B_RES_1000FD = 7<<8,/* Bit 10..8: 1000Base-T Full Dup. */
+ PHY_B_RES_1000HD = 6<<8,/* Bit 10..8: 1000Base-T Half Dup. */
+};
+
+/** Marvell-Specific */
+enum {
+ PHY_M_AN_NXT_PG = 1<<15, /* Request Next Page */
+ PHY_M_AN_ACK = 1<<14, /* (ro) Acknowledge Received */
+ PHY_M_AN_RF = 1<<13, /* Remote Fault */
+
+ PHY_M_AN_ASP = 1<<11, /* Asymmetric Pause */
+ PHY_M_AN_PC = 1<<10, /* MAC Pause implemented */
+ PHY_M_AN_100_T4 = 1<<9, /* Not cap. 100Base-T4 (always 0) */
+ PHY_M_AN_100_FD = 1<<8, /* Advertise 100Base-TX Full Duplex */
+ PHY_M_AN_100_HD = 1<<7, /* Advertise 100Base-TX Half Duplex */
+ PHY_M_AN_10_FD = 1<<6, /* Advertise 10Base-TX Full Duplex */
+ PHY_M_AN_10_HD = 1<<5, /* Advertise 10Base-TX Half Duplex */
+ PHY_M_AN_SEL_MSK =0x1f<<4, /* Bit 4.. 0: Selector Field Mask */
+};
+
+/* special defines for FIBER (88E1011S only) */
+enum {
+ PHY_M_AN_ASP_X = 1<<8, /* Asymmetric Pause */
+ PHY_M_AN_PC_X = 1<<7, /* MAC Pause implemented */
+ PHY_M_AN_1000X_AHD = 1<<6, /* Advertise 10000Base-X Half Duplex */
+ PHY_M_AN_1000X_AFD = 1<<5, /* Advertise 10000Base-X Full Duplex */
+};
+
+/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
+enum {
+ PHY_M_P_NO_PAUSE_X = 0<<7,/* Bit 8.. 7: no Pause Mode */
+ PHY_M_P_SYM_MD_X = 1<<7, /* Bit 8.. 7: symmetric Pause Mode */
+ PHY_M_P_ASYM_MD_X = 2<<7,/* Bit 8.. 7: asymmetric Pause Mode */
+ PHY_M_P_BOTH_MD_X = 3<<7,/* Bit 8.. 7: both Pause Mode */
+};
+
+/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
+enum {
+ PHY_M_1000C_TEST= 7<<13,/* Bit 15..13: Test Modes */
+ PHY_M_1000C_MSE = 1<<12, /* Manual Master/Slave Enable */
+ PHY_M_1000C_MSC = 1<<11, /* M/S Configuration (1=Master) */
+ PHY_M_1000C_MPD = 1<<10, /* Multi-Port Device */
+ PHY_M_1000C_AFD = 1<<9, /* Advertise Full Duplex */
+ PHY_M_1000C_AHD = 1<<8, /* Advertise Half Duplex */
+};
+
+/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/
+enum {
+ PHY_M_PC_TX_FFD_MSK = 3<<14,/* Bit 15..14: Tx FIFO Depth Mask */
+ PHY_M_PC_RX_FFD_MSK = 3<<12,/* Bit 13..12: Rx FIFO Depth Mask */
+ PHY_M_PC_ASS_CRS_TX = 1<<11, /* Assert CRS on Transmit */
+ PHY_M_PC_FL_GOOD = 1<<10, /* Force Link Good */
+ PHY_M_PC_EN_DET_MSK = 3<<8,/* Bit 9.. 8: Energy Detect Mask */
+ PHY_M_PC_ENA_EXT_D = 1<<7, /* Enable Ext. Distance (10BT) */
+ PHY_M_PC_MDIX_MSK = 3<<5,/* Bit 6.. 5: MDI/MDIX Config. Mask */
+ PHY_M_PC_DIS_125CLK = 1<<4, /* Disable 125 CLK */
+ PHY_M_PC_MAC_POW_UP = 1<<3, /* MAC Power up */
+ PHY_M_PC_SQE_T_ENA = 1<<2, /* SQE Test Enabled */
+ PHY_M_PC_POL_R_DIS = 1<<1, /* Polarity Reversal Disabled */
+ PHY_M_PC_DIS_JABBER = 1<<0, /* Disable Jabber */
+};
+
+enum {
+ PHY_M_PC_EN_DET = 2<<8, /* Energy Detect (Mode 1) */
+ PHY_M_PC_EN_DET_PLUS = 3<<8, /* Energy Detect Plus (Mode 2) */
+};
+
+enum {
+ PHY_M_PC_MAN_MDI = 0, /* 00 = Manual MDI configuration */
+ PHY_M_PC_MAN_MDIX = 1, /* 01 = Manual MDIX configuration */
+ PHY_M_PC_ENA_AUTO = 3, /* 11 = Enable Automatic Crossover */
+};
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+enum {
+ PHY_M_PC_ENA_DTE_DT = 1<<15, /* Enable Data Terminal Equ. (DTE) Detect */
+ PHY_M_PC_ENA_ENE_DT = 1<<14, /* Enable Energy Detect (sense & pulse) */
+ PHY_M_PC_DIS_NLP_CK = 1<<13, /* Disable Normal Link Puls (NLP) Check */
+ PHY_M_PC_ENA_LIP_NP = 1<<12, /* Enable Link Partner Next Page Reg. */
+ PHY_M_PC_DIS_NLP_GN = 1<<11, /* Disable Normal Link Puls Generation */
+
+ PHY_M_PC_DIS_SCRAMB = 1<<9, /* Disable Scrambler */
+ PHY_M_PC_DIS_FEFI = 1<<8, /* Disable Far End Fault Indic. (FEFI) */
+
+ PHY_M_PC_SH_TP_SEL = 1<<6, /* Shielded Twisted Pair Select */
+ PHY_M_PC_RX_FD_MSK = 3<<2,/* Bit 3.. 2: Rx FIFO Depth Mask */
+};
+
+/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/
+enum {
+ PHY_M_PS_SPEED_MSK = 3<<14, /* Bit 15..14: Speed Mask */
+ PHY_M_PS_SPEED_1000 = 1<<15, /* 10 = 1000 Mbps */
+ PHY_M_PS_SPEED_100 = 1<<14, /* 01 = 100 Mbps */
+ PHY_M_PS_SPEED_10 = 0, /* 00 = 10 Mbps */
+ PHY_M_PS_FULL_DUP = 1<<13, /* Full Duplex */
+ PHY_M_PS_PAGE_REC = 1<<12, /* Page Received */
+ PHY_M_PS_SPDUP_RES = 1<<11, /* Speed & Duplex Resolved */
+ PHY_M_PS_LINK_UP = 1<<10, /* Link Up */
+ PHY_M_PS_CABLE_MSK = 7<<7, /* Bit 9.. 7: Cable Length Mask */
+ PHY_M_PS_MDI_X_STAT = 1<<6, /* MDI Crossover Stat (1=MDIX) */
+ PHY_M_PS_DOWNS_STAT = 1<<5, /* Downshift Status (1=downsh.) */
+ PHY_M_PS_ENDET_STAT = 1<<4, /* Energy Detect Status (1=act) */
+ PHY_M_PS_TX_P_EN = 1<<3, /* Tx Pause Enabled */
+ PHY_M_PS_RX_P_EN = 1<<2, /* Rx Pause Enabled */
+ PHY_M_PS_POL_REV = 1<<1, /* Polarity Reversed */
+ PHY_M_PS_JABBER = 1<<0, /* Jabber */
+};
+
+#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+enum {
+ PHY_M_PS_DTE_DETECT = 1<<15, /* Data Terminal Equipment (DTE) Detected */
+ PHY_M_PS_RES_SPEED = 1<<14, /* Resolved Speed (1=100 Mbps, 0=10 Mbps */
+};
+
+enum {
+ PHY_M_IS_AN_ERROR = 1<<15, /* Auto-Negotiation Error */
+ PHY_M_IS_LSP_CHANGE = 1<<14, /* Link Speed Changed */
+ PHY_M_IS_DUP_CHANGE = 1<<13, /* Duplex Mode Changed */
+ PHY_M_IS_AN_PR = 1<<12, /* Page Received */
+ PHY_M_IS_AN_COMPL = 1<<11, /* Auto-Negotiation Completed */
+ PHY_M_IS_LST_CHANGE = 1<<10, /* Link Status Changed */
+ PHY_M_IS_SYMB_ERROR = 1<<9, /* Symbol Error */
+ PHY_M_IS_FALSE_CARR = 1<<8, /* False Carrier */
+ PHY_M_IS_FIFO_ERROR = 1<<7, /* FIFO Overflow/Underrun Error */
+ PHY_M_IS_MDI_CHANGE = 1<<6, /* MDI Crossover Changed */
+ PHY_M_IS_DOWNSH_DET = 1<<5, /* Downshift Detected */
+ PHY_M_IS_END_CHANGE = 1<<4, /* Energy Detect Changed */
+
+ PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */
+ PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */
+ PHY_M_IS_JABBER = 1<<0, /* Jabber */
+
+ PHY_M_IS_DEF_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE |
+ PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR,
+
+ PHY_M_IS_AN_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL,
+};
+
+/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/
+enum {
+ PHY_M_EC_ENA_BC_EXT = 1<<15, /* Enable Block Carr. Ext. (88E1111 only) */
+ PHY_M_EC_ENA_LIN_LB = 1<<14, /* Enable Line Loopback (88E1111 only) */
+
+ PHY_M_EC_DIS_LINK_P = 1<<12, /* Disable Link Pulses (88E1111 only) */
+ PHY_M_EC_M_DSC_MSK = 3<<10, /* Bit 11..10: Master Downshift Counter */
+ /* (88E1011 only) */
+ PHY_M_EC_S_DSC_MSK = 3<<8, /* Bit 9.. 8: Slave Downshift Counter */
+ /* (88E1011 only) */
+ PHY_M_EC_M_DSC_MSK2 = 7<<9, /* Bit 11.. 9: Master Downshift Counter */
+ /* (88E1111 only) */
+ PHY_M_EC_DOWN_S_ENA = 1<<8, /* Downshift Enable (88E1111 only) */
+ /* !!! Errata in spec. (1 = disable) */
+ PHY_M_EC_RX_TIM_CT = 1<<7, /* RGMII Rx Timing Control*/
+ PHY_M_EC_MAC_S_MSK = 7<<4, /* Bit 6.. 4: Def. MAC interface speed */
+ PHY_M_EC_FIB_AN_ENA = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */
+ PHY_M_EC_DTE_D_ENA = 1<<2, /* DTE Detect Enable (88E1111 only) */
+ PHY_M_EC_TX_TIM_CT = 1<<1, /* RGMII Tx Timing Control */
+ PHY_M_EC_TRANS_DIS = 1<<0, /* Transmitter Disable (88E1111 only) */};
+
+#define PHY_M_EC_M_DSC(x) ((u16)(x)<<10) /* 00=1x; 01=2x; 10=3x; 11=4x */
+#define PHY_M_EC_S_DSC(x) ((u16)(x)<<8) /* 00=dis; 01=1x; 10=2x; 11=3x */
+#define PHY_M_EC_MAC_S(x) ((u16)(x)<<4) /* 01X=0; 110=2.5; 111=25 (MHz) */
+
+#define PHY_M_EC_M_DSC_2(x) ((u16)(x)<<9) /* 000=1x; 001=2x; 010=3x; 011=4x */
+ /* 100=5x; 101=6x; 110=7x; 111=8x */
+enum {
+ MAC_TX_CLK_0_MHZ = 2,
+ MAC_TX_CLK_2_5_MHZ = 6,
+ MAC_TX_CLK_25_MHZ = 7,
+};
+
+/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/
+enum {
+ PHY_M_LEDC_DIS_LED = 1<<15, /* Disable LED */
+ PHY_M_LEDC_PULS_MSK = 7<<12,/* Bit 14..12: Pulse Stretch Mask */
+ PHY_M_LEDC_F_INT = 1<<11, /* Force Interrupt */
+ PHY_M_LEDC_BL_R_MSK = 7<<8,/* Bit 10.. 8: Blink Rate Mask */
+ PHY_M_LEDC_DP_C_LSB = 1<<7, /* Duplex Control (LSB, 88E1111 only) */
+ PHY_M_LEDC_TX_C_LSB = 1<<6, /* Tx Control (LSB, 88E1111 only) */
+ PHY_M_LEDC_LK_C_MSK = 7<<3,/* Bit 5.. 3: Link Control Mask */
+ /* (88E1111 only) */
+};
+#define PHY_M_LED_PULS_DUR(x) (((u16)(x)<<12) & PHY_M_LEDC_PULS_MSK)
+#define PHY_M_LED_BLINK_RT(x) (((u16)(x)<<8) & PHY_M_LEDC_BL_R_MSK)
+
+enum {
+ PHY_M_LEDC_LINK_MSK = 3<<3, /* Bit 4.. 3: Link Control Mask */
+ /* (88E1011 only) */
+ PHY_M_LEDC_DP_CTRL = 1<<2, /* Duplex Control */
+ PHY_M_LEDC_DP_C_MSB = 1<<2, /* Duplex Control (MSB, 88E1111 only) */
+ PHY_M_LEDC_RX_CTRL = 1<<1, /* Rx Activity / Link */
+ PHY_M_LEDC_TX_CTRL = 1<<0, /* Tx Activity / Link */
+ PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */
+};
+
+enum {
+ PULS_NO_STR = 0, /* no pulse stretching */
+ PULS_21MS = 1, /* 21 ms to 42 ms */
+ PULS_42MS = 2, /* 42 ms to 84 ms */
+ PULS_84MS = 3, /* 84 ms to 170 ms */
+ PULS_170MS = 4, /* 170 ms to 340 ms */
+ PULS_340MS = 5, /* 340 ms to 670 ms */
+ PULS_670MS = 6, /* 670 ms to 1.3 s */
+ PULS_1300MS = 7, /* 1.3 s to 2.7 s */
+};
+
+
+enum {
+ BLINK_42MS = 0, /* 42 ms */
+ BLINK_84MS = 1, /* 84 ms */
+ BLINK_170MS = 2, /* 170 ms */
+ BLINK_340MS = 3, /* 340 ms */
+ BLINK_670MS = 4, /* 670 ms */
+};
+
+/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/
+#define PHY_M_LED_MO_SGMII(x) ((x)<<14) /* Bit 15..14: SGMII AN Timer */
+ /* Bit 13..12: reserved */
+#define PHY_M_LED_MO_DUP(x) ((x)<<10) /* Bit 11..10: Duplex */
+#define PHY_M_LED_MO_10(x) ((x)<<8) /* Bit 9.. 8: Link 10 */
+#define PHY_M_LED_MO_100(x) ((x)<<6) /* Bit 7.. 6: Link 100 */
+#define PHY_M_LED_MO_1000(x) ((x)<<4) /* Bit 5.. 4: Link 1000 */
+#define PHY_M_LED_MO_RX(x) ((x)<<2) /* Bit 3.. 2: Rx */
+#define PHY_M_LED_MO_TX(x) ((x)<<0) /* Bit 1.. 0: Tx */
+
+enum {
+ MO_LED_NORM = 0,
+ MO_LED_BLINK = 1,
+ MO_LED_OFF = 2,
+ MO_LED_ON = 3,
+};
+
+/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/
+enum {
+ PHY_M_EC2_FI_IMPED = 1<<6, /* Fiber Input Impedance */
+ PHY_M_EC2_FO_IMPED = 1<<5, /* Fiber Output Impedance */
+ PHY_M_EC2_FO_M_CLK = 1<<4, /* Fiber Mode Clock Enable */
+ PHY_M_EC2_FO_BOOST = 1<<3, /* Fiber Output Boost */
+ PHY_M_EC2_FO_AM_MSK = 7, /* Bit 2.. 0: Fiber Output Amplitude */
+};
+
+/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/
+enum {
+ PHY_M_FC_AUTO_SEL = 1<<15, /* Fiber/Copper Auto Sel. Dis. */
+ PHY_M_FC_AN_REG_ACC = 1<<14, /* Fiber/Copper AN Reg. Access */
+ PHY_M_FC_RESOLUTION = 1<<13, /* Fiber/Copper Resolution */
+ PHY_M_SER_IF_AN_BP = 1<<12, /* Ser. IF AN Bypass Enable */
+ PHY_M_SER_IF_BP_ST = 1<<11, /* Ser. IF AN Bypass Status */
+ PHY_M_IRQ_POLARITY = 1<<10, /* IRQ polarity */
+ PHY_M_DIS_AUT_MED = 1<<9, /* Disable Aut. Medium Reg. Selection */
+ /* (88E1111 only) */
+ /* Bit 9.. 4: reserved (88E1011 only) */
+ PHY_M_UNDOC1 = 1<<7, /* undocumented bit !! */
+ PHY_M_DTE_POW_STAT = 1<<4, /* DTE Power Status (88E1111 only) */
+ PHY_M_MODE_MASK = 0xf, /* Bit 3.. 0: copy of HWCFG MODE[3:0] */
+};
+
+/***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/
+enum {
+ PHY_M_CABD_ENA_TEST = 1<<15, /* Enable Test (Page 0) */
+ PHY_M_CABD_DIS_WAIT = 1<<15, /* Disable Waiting Period (Page 1) */
+ /* (88E1111 only) */
+ PHY_M_CABD_STAT_MSK = 3<<13, /* Bit 14..13: Status Mask */
+ PHY_M_CABD_AMPL_MSK = 0x1f<<8, /* Bit 12.. 8: Amplitude Mask */
+ /* (88E1111 only) */
+ PHY_M_CABD_DIST_MSK = 0xff, /* Bit 7.. 0: Distance Mask */
+};
+
+/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */
+enum {
+ CABD_STAT_NORMAL= 0,
+ CABD_STAT_SHORT = 1,
+ CABD_STAT_OPEN = 2,
+ CABD_STAT_FAIL = 3,
+};
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+/***** PHY_MARV_FE_LED_PAR 16 bit r/w LED Parallel Select Reg. *****/
+ /* Bit 15..12: reserved (used internally) */
+enum {
+ PHY_M_FELP_LED2_MSK = 0xf<<8, /* Bit 11.. 8: LED2 Mask (LINK) */
+ PHY_M_FELP_LED1_MSK = 0xf<<4, /* Bit 7.. 4: LED1 Mask (ACT) */
+ PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */
+};
+
+#define PHY_M_FELP_LED2_CTRL(x) (((x)<<8) & PHY_M_FELP_LED2_MSK)
+#define PHY_M_FELP_LED1_CTRL(x) (((x)<<4) & PHY_M_FELP_LED1_MSK)
+#define PHY_M_FELP_LED0_CTRL(x) (((x)<<0) & PHY_M_FELP_LED0_MSK)
+
+enum {
+ LED_PAR_CTRL_COLX = 0x00,
+ LED_PAR_CTRL_ERROR = 0x01,
+ LED_PAR_CTRL_DUPLEX = 0x02,
+ LED_PAR_CTRL_DP_COL = 0x03,
+ LED_PAR_CTRL_SPEED = 0x04,
+ LED_PAR_CTRL_LINK = 0x05,
+ LED_PAR_CTRL_TX = 0x06,
+ LED_PAR_CTRL_RX = 0x07,
+ LED_PAR_CTRL_ACT = 0x08,
+ LED_PAR_CTRL_LNK_RX = 0x09,
+ LED_PAR_CTRL_LNK_AC = 0x0a,
+ LED_PAR_CTRL_ACT_BL = 0x0b,
+ LED_PAR_CTRL_TX_BL = 0x0c,
+ LED_PAR_CTRL_RX_BL = 0x0d,
+ LED_PAR_CTRL_COL_BL = 0x0e,
+ LED_PAR_CTRL_INACT = 0x0f
+};
+
+/*****,PHY_MARV_FE_SPEC_2 16 bit r/w Specific Control Reg. 2 *****/
+enum {
+ PHY_M_FESC_DIS_WAIT = 1<<2, /* Disable TDR Waiting Period */
+ PHY_M_FESC_ENA_MCLK = 1<<1, /* Enable MAC Rx Clock in sleep mode */
+ PHY_M_FESC_SEL_CL_A = 1<<0, /* Select Class A driver (100B-TX) */
+};
+
+
+/***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/
+enum {
+ PHY_M_LEDC_LOS_MSK = 0xf<<12, /* Bit 15..12: LOS LED Ctrl. Mask */
+ PHY_M_LEDC_INIT_MSK = 0xf<<8, /* Bit 11.. 8: INIT LED Ctrl. Mask */
+ PHY_M_LEDC_STA1_MSK = 0xf<<4, /* Bit 7.. 4: STAT1 LED Ctrl. Mask */
+ PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */
+};
+
+#define PHY_M_LEDC_LOS_CTRL(x) (((x)<<12) & PHY_M_LEDC_LOS_MSK)
+#define PHY_M_LEDC_INIT_CTRL(x) (((x)<<8) & PHY_M_LEDC_INIT_MSK)
+#define PHY_M_LEDC_STA1_CTRL(x) (((x)<<4) & PHY_M_LEDC_STA1_MSK)
+#define PHY_M_LEDC_STA0_CTRL(x) (((x)<<0) & PHY_M_LEDC_STA0_MSK)
+
+/* GMAC registers */
+/* Port Registers */
+enum {
+ GM_GP_STAT = 0x0000, /* 16 bit r/o General Purpose Status */
+ GM_GP_CTRL = 0x0004, /* 16 bit r/w General Purpose Control */
+ GM_TX_CTRL = 0x0008, /* 16 bit r/w Transmit Control Reg. */
+ GM_RX_CTRL = 0x000c, /* 16 bit r/w Receive Control Reg. */
+ GM_TX_FLOW_CTRL = 0x0010, /* 16 bit r/w Transmit Flow-Control */
+ GM_TX_PARAM = 0x0014, /* 16 bit r/w Transmit Parameter Reg. */
+ GM_SERIAL_MODE = 0x0018, /* 16 bit r/w Serial Mode Register */
+/* Source Address Registers */
+ GM_SRC_ADDR_1L = 0x001c, /* 16 bit r/w Source Address 1 (low) */
+ GM_SRC_ADDR_1M = 0x0020, /* 16 bit r/w Source Address 1 (middle) */
+ GM_SRC_ADDR_1H = 0x0024, /* 16 bit r/w Source Address 1 (high) */
+ GM_SRC_ADDR_2L = 0x0028, /* 16 bit r/w Source Address 2 (low) */
+ GM_SRC_ADDR_2M = 0x002c, /* 16 bit r/w Source Address 2 (middle) */
+ GM_SRC_ADDR_2H = 0x0030, /* 16 bit r/w Source Address 2 (high) */
+
+/* Multicast Address Hash Registers */
+ GM_MC_ADDR_H1 = 0x0034, /* 16 bit r/w Multicast Address Hash 1 */
+ GM_MC_ADDR_H2 = 0x0038, /* 16 bit r/w Multicast Address Hash 2 */
+ GM_MC_ADDR_H3 = 0x003c, /* 16 bit r/w Multicast Address Hash 3 */
+ GM_MC_ADDR_H4 = 0x0040, /* 16 bit r/w Multicast Address Hash 4 */
+
+/* Interrupt Source Registers */
+ GM_TX_IRQ_SRC = 0x0044, /* 16 bit r/o Tx Overflow IRQ Source */
+ GM_RX_IRQ_SRC = 0x0048, /* 16 bit r/o Rx Overflow IRQ Source */
+ GM_TR_IRQ_SRC = 0x004c, /* 16 bit r/o Tx/Rx Over. IRQ Source */
+
+/* Interrupt Mask Registers */
+ GM_TX_IRQ_MSK = 0x0050, /* 16 bit r/w Tx Overflow IRQ Mask */
+ GM_RX_IRQ_MSK = 0x0054, /* 16 bit r/w Rx Overflow IRQ Mask */
+ GM_TR_IRQ_MSK = 0x0058, /* 16 bit r/w Tx/Rx Over. IRQ Mask */
+
+/* Serial Management Interface (SMI) Registers */
+ GM_SMI_CTRL = 0x0080, /* 16 bit r/w SMI Control Register */
+ GM_SMI_DATA = 0x0084, /* 16 bit r/w SMI Data Register */
+ GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */
+};
+
+/* MIB Counters */
+#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */
+#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */
+
+/*
+ * MIB Counters base address definitions (low word) -
+ * use offset 4 for access to high word (32 bit r/o)
+ */
+enum {
+ GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */
+ GM_RXF_BC_OK = GM_MIB_CNT_BASE + 8, /* Broadcast Frames Received OK */
+ GM_RXF_MPAUSE = GM_MIB_CNT_BASE + 16, /* Pause MAC Ctrl Frames Received */
+ GM_RXF_MC_OK = GM_MIB_CNT_BASE + 24, /* Multicast Frames Received OK */
+ GM_RXF_FCS_ERR = GM_MIB_CNT_BASE + 32, /* Rx Frame Check Seq. Error */
+ /* GM_MIB_CNT_BASE + 40: reserved */
+ GM_RXO_OK_LO = GM_MIB_CNT_BASE + 48, /* Octets Received OK Low */
+ GM_RXO_OK_HI = GM_MIB_CNT_BASE + 56, /* Octets Received OK High */
+ GM_RXO_ERR_LO = GM_MIB_CNT_BASE + 64, /* Octets Received Invalid Low */
+ GM_RXO_ERR_HI = GM_MIB_CNT_BASE + 72, /* Octets Received Invalid High */
+ GM_RXF_SHT = GM_MIB_CNT_BASE + 80, /* Frames <64 Byte Received OK */
+ GM_RXE_FRAG = GM_MIB_CNT_BASE + 88, /* Frames <64 Byte Received with FCS Err */
+ GM_RXF_64B = GM_MIB_CNT_BASE + 96, /* 64 Byte Rx Frame */
+ GM_RXF_127B = GM_MIB_CNT_BASE + 104, /* 65-127 Byte Rx Frame */
+ GM_RXF_255B = GM_MIB_CNT_BASE + 112, /* 128-255 Byte Rx Frame */
+ GM_RXF_511B = GM_MIB_CNT_BASE + 120, /* 256-511 Byte Rx Frame */
+ GM_RXF_1023B = GM_MIB_CNT_BASE + 128, /* 512-1023 Byte Rx Frame */
+ GM_RXF_1518B = GM_MIB_CNT_BASE + 136, /* 1024-1518 Byte Rx Frame */
+ GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144, /* 1519-MaxSize Byte Rx Frame */
+ GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152, /* Rx Frame too Long Error */
+ GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160, /* Rx Jabber Packet Frame */
+ /* GM_MIB_CNT_BASE + 168: reserved */
+ GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176, /* Rx FIFO overflow Event */
+ /* GM_MIB_CNT_BASE + 184: reserved */
+ GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192, /* Unicast Frames Xmitted OK */
+ GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200, /* Broadcast Frames Xmitted OK */
+ GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208, /* Pause MAC Ctrl Frames Xmitted */
+ GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216, /* Multicast Frames Xmitted OK */
+ GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224, /* Octets Transmitted OK Low */
+ GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232, /* Octets Transmitted OK High */
+ GM_TXF_64B = GM_MIB_CNT_BASE + 240, /* 64 Byte Tx Frame */
+ GM_TXF_127B = GM_MIB_CNT_BASE + 248, /* 65-127 Byte Tx Frame */
+ GM_TXF_255B = GM_MIB_CNT_BASE + 256, /* 128-255 Byte Tx Frame */
+ GM_TXF_511B = GM_MIB_CNT_BASE + 264, /* 256-511 Byte Tx Frame */
+ GM_TXF_1023B = GM_MIB_CNT_BASE + 272, /* 512-1023 Byte Tx Frame */
+ GM_TXF_1518B = GM_MIB_CNT_BASE + 280, /* 1024-1518 Byte Tx Frame */
+ GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288, /* 1519-MaxSize Byte Tx Frame */
+
+ GM_TXF_COL = GM_MIB_CNT_BASE + 304, /* Tx Collision */
+ GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312, /* Tx Late Collision */
+ GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320, /* Tx aborted due to Exces. Col. */
+ GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328, /* Tx Multiple Collision */
+ GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336, /* Tx Single Collision */
+ GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344, /* Tx FIFO Underrun Event */
+};
+
+/* GMAC Bit Definitions */
+/* GM_GP_STAT 16 bit r/o General Purpose Status Register */
+enum {
+ GM_GPSR_SPEED = 1<<15, /* Bit 15: Port Speed (1 = 100 Mbps) */
+ GM_GPSR_DUPLEX = 1<<14, /* Bit 14: Duplex Mode (1 = Full) */
+ GM_GPSR_FC_TX_DIS = 1<<13, /* Bit 13: Tx Flow-Control Mode Disabled */
+ GM_GPSR_LINK_UP = 1<<12, /* Bit 12: Link Up Status */
+ GM_GPSR_PAUSE = 1<<11, /* Bit 11: Pause State */
+ GM_GPSR_TX_ACTIVE = 1<<10, /* Bit 10: Tx in Progress */
+ GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occured */
+ GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occured */
+
+ GM_GPSR_PHY_ST_CH = 1<<5, /* Bit 5: PHY Status Change */
+ GM_GPSR_GIG_SPEED = 1<<4, /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */
+ GM_GPSR_PART_MODE = 1<<3, /* Bit 3: Partition mode */
+ GM_GPSR_FC_RX_DIS = 1<<2, /* Bit 2: Rx Flow-Control Mode Disabled */
+ GM_GPSR_PROM_EN = 1<<1, /* Bit 1: Promiscuous Mode Enabled */
+};
+
+/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */
+enum {
+ GM_GPCR_PROM_ENA = 1<<14, /* Bit 14: Enable Promiscuous Mode */
+ GM_GPCR_FC_TX_DIS = 1<<13, /* Bit 13: Disable Tx Flow-Control Mode */
+ GM_GPCR_TX_ENA = 1<<12, /* Bit 12: Enable Transmit */
+ GM_GPCR_RX_ENA = 1<<11, /* Bit 11: Enable Receive */
+ GM_GPCR_BURST_ENA = 1<<10, /* Bit 10: Enable Burst Mode */
+ GM_GPCR_LOOP_ENA = 1<<9, /* Bit 9: Enable MAC Loopback Mode */
+ GM_GPCR_PART_ENA = 1<<8, /* Bit 8: Enable Partition Mode */
+ GM_GPCR_GIGS_ENA = 1<<7, /* Bit 7: Gigabit Speed (1000 Mbps) */
+ GM_GPCR_FL_PASS = 1<<6, /* Bit 6: Force Link Pass */
+ GM_GPCR_DUP_FULL = 1<<5, /* Bit 5: Full Duplex Mode */
+ GM_GPCR_FC_RX_DIS = 1<<4, /* Bit 4: Disable Rx Flow-Control Mode */
+ GM_GPCR_SPEED_100 = 1<<3, /* Bit 3: Port Speed 100 Mbps */
+ GM_GPCR_AU_DUP_DIS = 1<<2, /* Bit 2: Disable Auto-Update Duplex */
+ GM_GPCR_AU_FCT_DIS = 1<<1, /* Bit 1: Disable Auto-Update Flow-C. */
+ GM_GPCR_AU_SPD_DIS = 1<<0, /* Bit 0: Disable Auto-Update Speed */
+};
+
+#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
+#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS|GM_GPCR_AU_SPD_DIS)
+
+/* GM_TX_CTRL 16 bit r/w Transmit Control Register */
+enum {
+ GM_TXCR_FORCE_JAM = 1<<15, /* Bit 15: Force Jam / Flow-Control */
+ GM_TXCR_CRC_DIS = 1<<14, /* Bit 14: Disable insertion of CRC */
+ GM_TXCR_PAD_DIS = 1<<13, /* Bit 13: Disable padding of packets */
+ GM_TXCR_COL_THR_MSK = 7<<10, /* Bit 12..10: Collision Threshold */
+};
+
+#define TX_COL_THR(x) (((x)<<10) & GM_TXCR_COL_THR_MSK)
+#define TX_COL_DEF 0x04 /* late collision after 64 byte */
+
+/* GM_RX_CTRL 16 bit r/w Receive Control Register */
+enum {
+ GM_RXCR_UCF_ENA = 1<<15, /* Bit 15: Enable Unicast filtering */
+ GM_RXCR_MCF_ENA = 1<<14, /* Bit 14: Enable Multicast filtering */
+ GM_RXCR_CRC_DIS = 1<<13, /* Bit 13: Remove 4-byte CRC */
+ GM_RXCR_PASS_FC = 1<<12, /* Bit 12: Pass FC packets to FIFO */
+};
+
+/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */
+enum {
+ GM_TXPA_JAMLEN_MSK = 0x03<<14, /* Bit 15..14: Jam Length */
+ GM_TXPA_JAMIPG_MSK = 0x1f<<9, /* Bit 13..9: Jam IPG */
+ GM_TXPA_JAMDAT_MSK = 0x1f<<4, /* Bit 8..4: IPG Jam to Data */
+
+ TX_JAM_LEN_DEF = 0x03,
+ TX_JAM_IPG_DEF = 0x0b,
+ TX_IPG_JAM_DEF = 0x1c,
+};
+
+#define TX_JAM_LEN_VAL(x) (((x)<<14) & GM_TXPA_JAMLEN_MSK)
+#define TX_JAM_IPG_VAL(x) (((x)<<9) & GM_TXPA_JAMIPG_MSK)
+#define TX_IPG_JAM_DATA(x) (((x)<<4) & GM_TXPA_JAMDAT_MSK)
+
+
+/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */
+enum {
+ GM_SMOD_DATABL_MSK = 0x1f<<11, /* Bit 15..11: Data Blinder (r/o) */
+ GM_SMOD_LIMIT_4 = 1<<10, /* Bit 10: 4 consecutive Tx trials */
+ GM_SMOD_VLAN_ENA = 1<<9, /* Bit 9: Enable VLAN (Max. Frame Len) */
+ GM_SMOD_JUMBO_ENA = 1<<8, /* Bit 8: Enable Jumbo (Max. Frame Len) */
+ GM_SMOD_IPG_MSK = 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */
+};
+
+#define DATA_BLIND_VAL(x) (((x)<<11) & GM_SMOD_DATABL_MSK)
+#define DATA_BLIND_DEF 0x04
+
+#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK)
+#define IPG_DATA_DEF 0x1e
+
+/* GM_SMI_CTRL 16 bit r/w SMI Control Register */
+enum {
+ GM_SMI_CT_PHY_A_MSK = 0x1f<<11, /* Bit 15..11: PHY Device Address */
+ GM_SMI_CT_REG_A_MSK = 0x1f<<6, /* Bit 10.. 6: PHY Register Address */
+ GM_SMI_CT_OP_RD = 1<<5, /* Bit 5: OpCode Read (0=Write)*/
+ GM_SMI_CT_RD_VAL = 1<<4, /* Bit 4: Read Valid (Read completed) */
+ GM_SMI_CT_BUSY = 1<<3, /* Bit 3: Busy (Operation in progress) */
+};
+
+#define GM_SMI_CT_PHY_AD(x) (((x)<<11) & GM_SMI_CT_PHY_A_MSK)
+#define GM_SMI_CT_REG_AD(x) (((x)<<6) & GM_SMI_CT_REG_A_MSK)
+
+/* GM_PHY_ADDR 16 bit r/w GPHY Address Register */
+enum {
+ GM_PAR_MIB_CLR = 1<<5, /* Bit 5: Set MIB Clear Counter Mode */
+ GM_PAR_MIB_TST = 1<<4, /* Bit 4: MIB Load Counter (Test Mode) */
+};
+
+/* Receive Frame Status Encoding */
+enum {
+ GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */
+ GMR_FS_LEN_SHIFT = 16,
+ GMR_FS_VLAN = 1<<13, /* Bit 13: VLAN Packet */
+ GMR_FS_JABBER = 1<<12, /* Bit 12: Jabber Packet */
+ GMR_FS_UN_SIZE = 1<<11, /* Bit 11: Undersize Packet */
+ GMR_FS_MC = 1<<10, /* Bit 10: Multicast Packet */
+ GMR_FS_BC = 1<<9, /* Bit 9: Broadcast Packet */
+ GMR_FS_RX_OK = 1<<8, /* Bit 8: Receive OK (Good Packet) */
+ GMR_FS_GOOD_FC = 1<<7, /* Bit 7: Good Flow-Control Packet */
+ GMR_FS_BAD_FC = 1<<6, /* Bit 6: Bad Flow-Control Packet */
+ GMR_FS_MII_ERR = 1<<5, /* Bit 5: MII Error */
+ GMR_FS_LONG_ERR = 1<<4, /* Bit 4: Too Long Packet */
+ GMR_FS_FRAGMENT = 1<<3, /* Bit 3: Fragment */
+
+ GMR_FS_CRC_ERR = 1<<1, /* Bit 1: CRC Error */
+ GMR_FS_RX_FF_OV = 1<<0, /* Bit 0: Rx FIFO Overflow */
+
+/*
+ * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR)
+ */
+ GMR_FS_ANY_ERR = GMR_FS_CRC_ERR | GMR_FS_LONG_ERR |
+ GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC |
+ GMR_FS_JABBER,
+/* Rx GMAC FIFO Flush Mask (default) */
+ RX_FF_FL_DEF_MSK = GMR_FS_CRC_ERR | GMR_FS_RX_FF_OV |GMR_FS_MII_ERR |
+ GMR_FS_BAD_FC | GMR_FS_UN_SIZE | GMR_FS_JABBER,
+};
+
+/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */
+enum {
+ GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */
+ GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */
+ GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */
+
+ GMF_RP_TST_ON = 1<<10, /* Read Pointer Test On */
+ GMF_RP_TST_OFF = 1<<9, /* Read Pointer Test Off */
+ GMF_RP_STEP = 1<<8, /* Read Pointer Step/Increment */
+ GMF_RX_F_FL_ON = 1<<7, /* Rx FIFO Flush Mode On */
+ GMF_RX_F_FL_OFF = 1<<6, /* Rx FIFO Flush Mode Off */
+ GMF_CLI_RX_FO = 1<<5, /* Clear IRQ Rx FIFO Overrun */
+ GMF_CLI_RX_FC = 1<<4, /* Clear IRQ Rx Frame Complete */
+ GMF_OPER_ON = 1<<3, /* Operational Mode On */
+ GMF_OPER_OFF = 1<<2, /* Operational Mode Off */
+ GMF_RST_CLR = 1<<1, /* Clear GMAC FIFO Reset */
+ GMF_RST_SET = 1<<0, /* Set GMAC FIFO Reset */
+
+ RX_GMF_FL_THR_DEF = 0xa, /* flush threshold (default) */
+};
+
+
+/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */
+enum {
+ GMF_WSP_TST_ON = 1<<18, /* Write Shadow Pointer Test On */
+ GMF_WSP_TST_OFF = 1<<17, /* Write Shadow Pointer Test Off */
+ GMF_WSP_STEP = 1<<16, /* Write Shadow Pointer Step/Increment */
+
+ GMF_CLI_TX_FU = 1<<6, /* Clear IRQ Tx FIFO Underrun */
+ GMF_CLI_TX_FC = 1<<5, /* Clear IRQ Tx Frame Complete */
+ GMF_CLI_TX_PE = 1<<4, /* Clear IRQ Tx Parity Error */
+};
+
+/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */
+enum {
+ GMT_ST_START = 1<<2, /* Start Time Stamp Timer */
+ GMT_ST_STOP = 1<<1, /* Stop Time Stamp Timer */
+ GMT_ST_CLR_IRQ = 1<<0, /* Clear Time Stamp Timer IRQ */
+};
+
+/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */
+enum {
+ GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */
+ GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */
+ GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */
+ GMC_F_LOOPB_OFF = 1<<4, /* FIFO Loopback Off */
+ GMC_PAUSE_ON = 1<<3, /* Pause On */
+ GMC_PAUSE_OFF = 1<<2, /* Pause Off */
+ GMC_RST_CLR = 1<<1, /* Clear GMAC Reset */
+ GMC_RST_SET = 1<<0, /* Set GMAC Reset */
+};
+
+/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */
+enum {
+ GPC_SEL_BDT = 1<<28, /* Select Bi-Dir. Transfer for MDC/MDIO */
+ GPC_INT_POL_HI = 1<<27, /* IRQ Polarity is Active HIGH */
+ GPC_75_OHM = 1<<26, /* Use 75 Ohm Termination instead of 50 */
+ GPC_DIS_FC = 1<<25, /* Disable Automatic Fiber/Copper Detection */
+ GPC_DIS_SLEEP = 1<<24, /* Disable Energy Detect */
+ GPC_HWCFG_M_3 = 1<<23, /* HWCFG_MODE[3] */
+ GPC_HWCFG_M_2 = 1<<22, /* HWCFG_MODE[2] */
+ GPC_HWCFG_M_1 = 1<<21, /* HWCFG_MODE[1] */
+ GPC_HWCFG_M_0 = 1<<20, /* HWCFG_MODE[0] */
+ GPC_ANEG_0 = 1<<19, /* ANEG[0] */
+ GPC_ENA_XC = 1<<18, /* Enable MDI crossover */
+ GPC_DIS_125 = 1<<17, /* Disable 125 MHz clock */
+ GPC_ANEG_3 = 1<<16, /* ANEG[3] */
+ GPC_ANEG_2 = 1<<15, /* ANEG[2] */
+ GPC_ANEG_1 = 1<<14, /* ANEG[1] */
+ GPC_ENA_PAUSE = 1<<13, /* Enable Pause (SYM_OR_REM) */
+ GPC_PHYADDR_4 = 1<<12, /* Bit 4 of Phy Addr */
+ GPC_PHYADDR_3 = 1<<11, /* Bit 3 of Phy Addr */
+ GPC_PHYADDR_2 = 1<<10, /* Bit 2 of Phy Addr */
+ GPC_PHYADDR_1 = 1<<9, /* Bit 1 of Phy Addr */
+ GPC_PHYADDR_0 = 1<<8, /* Bit 0 of Phy Addr */
+ /* Bits 7..2: reserved */
+ GPC_RST_CLR = 1<<1, /* Clear GPHY Reset */
+ GPC_RST_SET = 1<<0, /* Set GPHY Reset */
+};
+
+#define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3|GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
+#define GPC_HWCFG_GMII_FIB (GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
+#define GPC_ANEG_ADV_ALL_M (GPC_ANEG_3 | GPC_ANEG_2 | GPC_ANEG_1 | GPC_ANEG_0)
+
+/* forced speed and duplex mode (don't mix with other ANEG bits) */
+#define GPC_FRC10MBIT_HALF 0
+#define GPC_FRC10MBIT_FULL GPC_ANEG_0
+#define GPC_FRC100MBIT_HALF GPC_ANEG_1
+#define GPC_FRC100MBIT_FULL (GPC_ANEG_0 | GPC_ANEG_1)
+
+/* auto-negotiation with limited advertised speeds */
+/* mix only with master/slave settings (for copper) */
+#define GPC_ADV_1000_HALF GPC_ANEG_2
+#define GPC_ADV_1000_FULL GPC_ANEG_3
+#define GPC_ADV_ALL (GPC_ANEG_2 | GPC_ANEG_3)
+
+/* master/slave settings */
+/* only for copper with 1000 Mbps */
+#define GPC_FORCE_MASTER 0
+#define GPC_FORCE_SLAVE GPC_ANEG_0
+#define GPC_PREF_MASTER GPC_ANEG_1
+#define GPC_PREF_SLAVE (GPC_ANEG_1 | GPC_ANEG_0)
+
+/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */
+/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */
+enum {
+ GM_IS_TX_CO_OV = 1<<5, /* Transmit Counter Overflow IRQ */
+ GM_IS_RX_CO_OV = 1<<4, /* Receive Counter Overflow IRQ */
+ GM_IS_TX_FF_UR = 1<<3, /* Transmit FIFO Underrun */
+ GM_IS_TX_COMPL = 1<<2, /* Frame Transmission Complete */
+ GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */
+ GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */
+
+#define GMAC_DEF_MSK (GM_IS_RX_FF_OR | GM_IS_TX_FF_UR)
+
+/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
+ /* Bits 15.. 2: reserved */
+ GMLC_RST_CLR = 1<<1, /* Clear GMAC Link Reset */
+ GMLC_RST_SET = 1<<0, /* Set GMAC Link Reset */
+
+
+/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */
+ WOL_CTL_LINK_CHG_OCC = 1<<15,
+ WOL_CTL_MAGIC_PKT_OCC = 1<<14,
+ WOL_CTL_PATTERN_OCC = 1<<13,
+ WOL_CTL_CLEAR_RESULT = 1<<12,
+ WOL_CTL_ENA_PME_ON_LINK_CHG = 1<<11,
+ WOL_CTL_DIS_PME_ON_LINK_CHG = 1<<10,
+ WOL_CTL_ENA_PME_ON_MAGIC_PKT = 1<<9,
+ WOL_CTL_DIS_PME_ON_MAGIC_PKT = 1<<8,
+ WOL_CTL_ENA_PME_ON_PATTERN = 1<<7,
+ WOL_CTL_DIS_PME_ON_PATTERN = 1<<6,
+ WOL_CTL_ENA_LINK_CHG_UNIT = 1<<5,
+ WOL_CTL_DIS_LINK_CHG_UNIT = 1<<4,
+ WOL_CTL_ENA_MAGIC_PKT_UNIT = 1<<3,
+ WOL_CTL_DIS_MAGIC_PKT_UNIT = 1<<2,
+ WOL_CTL_ENA_PATTERN_UNIT = 1<<1,
+ WOL_CTL_DIS_PATTERN_UNIT = 1<<0,
+};
+
+#define WOL_CTL_DEFAULT \
+ (WOL_CTL_DIS_PME_ON_LINK_CHG | \
+ WOL_CTL_DIS_PME_ON_PATTERN | \
+ WOL_CTL_DIS_PME_ON_MAGIC_PKT | \
+ WOL_CTL_DIS_LINK_CHG_UNIT | \
+ WOL_CTL_DIS_PATTERN_UNIT | \
+ WOL_CTL_DIS_MAGIC_PKT_UNIT)
+
+/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */
+#define WOL_CTL_PATT_ENA(x) (1 << (x))
+
+
+/* XMAC II registers */
+enum {
+ XM_MMU_CMD = 0x0000, /* 16 bit r/w MMU Command Register */
+ XM_POFF = 0x0008, /* 32 bit r/w Packet Offset Register */
+ XM_BURST = 0x000c, /* 32 bit r/w Burst Register for half duplex*/
+ XM_1L_VLAN_TAG = 0x0010, /* 16 bit r/w One Level VLAN Tag ID */
+ XM_2L_VLAN_TAG = 0x0014, /* 16 bit r/w Two Level VLAN Tag ID */
+ XM_TX_CMD = 0x0020, /* 16 bit r/w Transmit Command Register */
+ XM_TX_RT_LIM = 0x0024, /* 16 bit r/w Transmit Retry Limit Register */
+ XM_TX_STIME = 0x0028, /* 16 bit r/w Transmit Slottime Register */
+ XM_TX_IPG = 0x002c, /* 16 bit r/w Transmit Inter Packet Gap */
+ XM_RX_CMD = 0x0030, /* 16 bit r/w Receive Command Register */
+ XM_PHY_ADDR = 0x0034, /* 16 bit r/w PHY Address Register */
+ XM_PHY_DATA = 0x0038, /* 16 bit r/w PHY Data Register */
+ XM_GP_PORT = 0x0040, /* 32 bit r/w General Purpose Port Register */
+ XM_IMSK = 0x0044, /* 16 bit r/w Interrupt Mask Register */
+ XM_ISRC = 0x0048, /* 16 bit r/o Interrupt Status Register */
+ XM_HW_CFG = 0x004c, /* 16 bit r/w Hardware Config Register */
+ XM_TX_LO_WM = 0x0060, /* 16 bit r/w Tx FIFO Low Water Mark */
+ XM_TX_HI_WM = 0x0062, /* 16 bit r/w Tx FIFO High Water Mark */
+ XM_TX_THR = 0x0064, /* 16 bit r/w Tx Request Threshold */
+ XM_HT_THR = 0x0066, /* 16 bit r/w Host Request Threshold */
+ XM_PAUSE_DA = 0x0068, /* NA reg r/w Pause Destination Address */
+ XM_CTL_PARA = 0x0070, /* 32 bit r/w Control Parameter Register */
+ XM_MAC_OPCODE = 0x0074, /* 16 bit r/w Opcode for MAC control frames */
+ XM_MAC_PTIME = 0x0076, /* 16 bit r/w Pause time for MAC ctrl frames*/
+ XM_TX_STAT = 0x0078, /* 32 bit r/o Tx Status LIFO Register */
+
+ XM_EXM_START = 0x0080, /* r/w Start Address of the EXM Regs */
+#define XM_EXM(reg) (XM_EXM_START + ((reg) << 3))
+};
+
+enum {
+ XM_SRC_CHK = 0x0100, /* NA reg r/w Source Check Address Register */
+ XM_SA = 0x0108, /* NA reg r/w Station Address Register */
+ XM_HSM = 0x0110, /* 64 bit r/w Hash Match Address Registers */
+ XM_RX_LO_WM = 0x0118, /* 16 bit r/w Receive Low Water Mark */
+ XM_RX_HI_WM = 0x011a, /* 16 bit r/w Receive High Water Mark */
+ XM_RX_THR = 0x011c, /* 32 bit r/w Receive Request Threshold */
+ XM_DEV_ID = 0x0120, /* 32 bit r/o Device ID Register */
+ XM_MODE = 0x0124, /* 32 bit r/w Mode Register */
+ XM_LSA = 0x0128, /* NA reg r/o Last Source Register */
+ XM_TS_READ = 0x0130, /* 32 bit r/o Time Stamp Read Register */
+ XM_TS_LOAD = 0x0134, /* 32 bit r/o Time Stamp Load Value */
+ XM_STAT_CMD = 0x0200, /* 16 bit r/w Statistics Command Register */
+ XM_RX_CNT_EV = 0x0204, /* 32 bit r/o Rx Counter Event Register */
+ XM_TX_CNT_EV = 0x0208, /* 32 bit r/o Tx Counter Event Register */
+ XM_RX_EV_MSK = 0x020c, /* 32 bit r/w Rx Counter Event Mask */
+ XM_TX_EV_MSK = 0x0210, /* 32 bit r/w Tx Counter Event Mask */
+ XM_TXF_OK = 0x0280, /* 32 bit r/o Frames Transmitted OK Conuter */
+ XM_TXO_OK_HI = 0x0284, /* 32 bit r/o Octets Transmitted OK High Cnt*/
+ XM_TXO_OK_LO = 0x0288, /* 32 bit r/o Octets Transmitted OK Low Cnt */
+ XM_TXF_BC_OK = 0x028c, /* 32 bit r/o Broadcast Frames Xmitted OK */
+ XM_TXF_MC_OK = 0x0290, /* 32 bit r/o Multicast Frames Xmitted OK */
+ XM_TXF_UC_OK = 0x0294, /* 32 bit r/o Unicast Frames Xmitted OK */
+ XM_TXF_LONG = 0x0298, /* 32 bit r/o Tx Long Frame Counter */
+ XM_TXE_BURST = 0x029c, /* 32 bit r/o Tx Burst Event Counter */
+ XM_TXF_MPAUSE = 0x02a0, /* 32 bit r/o Tx Pause MAC Ctrl Frame Cnt */
+ XM_TXF_MCTRL = 0x02a4, /* 32 bit r/o Tx MAC Ctrl Frame Counter */
+ XM_TXF_SNG_COL = 0x02a8, /* 32 bit r/o Tx Single Collision Counter */
+ XM_TXF_MUL_COL = 0x02ac, /* 32 bit r/o Tx Multiple Collision Counter */
+ XM_TXF_ABO_COL = 0x02b0, /* 32 bit r/o Tx aborted due to Exces. Col. */
+ XM_TXF_LAT_COL = 0x02b4, /* 32 bit r/o Tx Late Collision Counter */
+ XM_TXF_DEF = 0x02b8, /* 32 bit r/o Tx Deferred Frame Counter */
+ XM_TXF_EX_DEF = 0x02bc, /* 32 bit r/o Tx Excessive Deferall Counter */
+ XM_TXE_FIFO_UR = 0x02c0, /* 32 bit r/o Tx FIFO Underrun Event Cnt */
+ XM_TXE_CS_ERR = 0x02c4, /* 32 bit r/o Tx Carrier Sense Error Cnt */
+ XM_TXP_UTIL = 0x02c8, /* 32 bit r/o Tx Utilization in % */
+ XM_TXF_64B = 0x02d0, /* 32 bit r/o 64 Byte Tx Frame Counter */
+ XM_TXF_127B = 0x02d4, /* 32 bit r/o 65-127 Byte Tx Frame Counter */
+ XM_TXF_255B = 0x02d8, /* 32 bit r/o 128-255 Byte Tx Frame Counter */
+ XM_TXF_511B = 0x02dc, /* 32 bit r/o 256-511 Byte Tx Frame Counter */
+ XM_TXF_1023B = 0x02e0, /* 32 bit r/o 512-1023 Byte Tx Frame Counter*/
+ XM_TXF_MAX_SZ = 0x02e4, /* 32 bit r/o 1024-MaxSize Byte Tx Frame Cnt*/
+ XM_RXF_OK = 0x0300, /* 32 bit r/o Frames Received OK */
+ XM_RXO_OK_HI = 0x0304, /* 32 bit r/o Octets Received OK High Cnt */
+ XM_RXO_OK_LO = 0x0308, /* 32 bit r/o Octets Received OK Low Counter*/
+ XM_RXF_BC_OK = 0x030c, /* 32 bit r/o Broadcast Frames Received OK */
+ XM_RXF_MC_OK = 0x0310, /* 32 bit r/o Multicast Frames Received OK */
+ XM_RXF_UC_OK = 0x0314, /* 32 bit r/o Unicast Frames Received OK */
+ XM_RXF_MPAUSE = 0x0318, /* 32 bit r/o Rx Pause MAC Ctrl Frame Cnt */
+ XM_RXF_MCTRL = 0x031c, /* 32 bit r/o Rx MAC Ctrl Frame Counter */
+ XM_RXF_INV_MP = 0x0320, /* 32 bit r/o Rx invalid Pause Frame Cnt */
+ XM_RXF_INV_MOC = 0x0324, /* 32 bit r/o Rx Frames with inv. MAC Opcode*/
+ XM_RXE_BURST = 0x0328, /* 32 bit r/o Rx Burst Event Counter */
+ XM_RXE_FMISS = 0x032c, /* 32 bit r/o Rx Missed Frames Event Cnt */
+ XM_RXF_FRA_ERR = 0x0330, /* 32 bit r/o Rx Framing Error Counter */
+ XM_RXE_FIFO_OV = 0x0334, /* 32 bit r/o Rx FIFO overflow Event Cnt */
+ XM_RXF_JAB_PKT = 0x0338, /* 32 bit r/o Rx Jabber Packet Frame Cnt */
+ XM_RXE_CAR_ERR = 0x033c, /* 32 bit r/o Rx Carrier Event Error Cnt */
+ XM_RXF_LEN_ERR = 0x0340, /* 32 bit r/o Rx in Range Length Error */
+ XM_RXE_SYM_ERR = 0x0344, /* 32 bit r/o Rx Symbol Error Counter */
+ XM_RXE_SHT_ERR = 0x0348, /* 32 bit r/o Rx Short Event Error Cnt */
+ XM_RXE_RUNT = 0x034c, /* 32 bit r/o Rx Runt Event Counter */
+ XM_RXF_LNG_ERR = 0x0350, /* 32 bit r/o Rx Frame too Long Error Cnt */
+ XM_RXF_FCS_ERR = 0x0354, /* 32 bit r/o Rx Frame Check Seq. Error Cnt */
+ XM_RXF_CEX_ERR = 0x035c, /* 32 bit r/o Rx Carrier Ext Error Frame Cnt*/
+ XM_RXP_UTIL = 0x0360, /* 32 bit r/o Rx Utilization in % */
+ XM_RXF_64B = 0x0368, /* 32 bit r/o 64 Byte Rx Frame Counter */
+ XM_RXF_127B = 0x036c, /* 32 bit r/o 65-127 Byte Rx Frame Counter */
+ XM_RXF_255B = 0x0370, /* 32 bit r/o 128-255 Byte Rx Frame Counter */
+ XM_RXF_511B = 0x0374, /* 32 bit r/o 256-511 Byte Rx Frame Counter */
+ XM_RXF_1023B = 0x0378, /* 32 bit r/o 512-1023 Byte Rx Frame Counter*/
+ XM_RXF_MAX_SZ = 0x037c, /* 32 bit r/o 1024-MaxSize Byte Rx Frame Cnt*/
+};
+
+/* XM_MMU_CMD 16 bit r/w MMU Command Register */
+enum {
+ XM_MMU_PHY_RDY = 1<<12, /* Bit 12: PHY Read Ready */
+ XM_MMU_PHY_BUSY = 1<<11, /* Bit 11: PHY Busy */
+ XM_MMU_IGN_PF = 1<<10, /* Bit 10: Ignore Pause Frame */
+ XM_MMU_MAC_LB = 1<<9, /* Bit 9: Enable MAC Loopback */
+ XM_MMU_FRC_COL = 1<<7, /* Bit 7: Force Collision */
+ XM_MMU_SIM_COL = 1<<6, /* Bit 6: Simulate Collision */
+ XM_MMU_NO_PRE = 1<<5, /* Bit 5: No MDIO Preamble */
+ XM_MMU_GMII_FD = 1<<4, /* Bit 4: GMII uses Full Duplex */
+ XM_MMU_RAT_CTRL = 1<<3, /* Bit 3: Enable Rate Control */
+ XM_MMU_GMII_LOOP= 1<<2, /* Bit 2: PHY is in Loopback Mode */
+ XM_MMU_ENA_RX = 1<<1, /* Bit 1: Enable Receiver */
+ XM_MMU_ENA_TX = 1<<0, /* Bit 0: Enable Transmitter */
+};
+
+
+/* XM_TX_CMD 16 bit r/w Transmit Command Register */
+enum {
+ XM_TX_BK2BK = 1<<6, /* Bit 6: Ignor Carrier Sense (Tx Bk2Bk)*/
+ XM_TX_ENC_BYP = 1<<5, /* Bit 5: Set Encoder in Bypass Mode */
+ XM_TX_SAM_LINE = 1<<4, /* Bit 4: (sc) Start utilization calculation */
+ XM_TX_NO_GIG_MD = 1<<3, /* Bit 3: Disable Carrier Extension */
+ XM_TX_NO_PRE = 1<<2, /* Bit 2: Disable Preamble Generation */
+ XM_TX_NO_CRC = 1<<1, /* Bit 1: Disable CRC Generation */
+ XM_TX_AUTO_PAD = 1<<0, /* Bit 0: Enable Automatic Padding */
+};
+
+/* XM_TX_RT_LIM 16 bit r/w Transmit Retry Limit Register */
+#define XM_RT_LIM_MSK 0x1f /* Bit 4..0: Tx Retry Limit */
+
+
+/* XM_TX_STIME 16 bit r/w Transmit Slottime Register */
+#define XM_STIME_MSK 0x7f /* Bit 6..0: Tx Slottime bits */
+
+
+/* XM_TX_IPG 16 bit r/w Transmit Inter Packet Gap */
+#define XM_IPG_MSK 0xff /* Bit 7..0: IPG value bits */
+
+
+/* XM_RX_CMD 16 bit r/w Receive Command Register */
+enum {
+ XM_RX_LENERR_OK = 1<<8, /* Bit 8 don't set Rx Err bit for */
+ /* inrange error packets */
+ XM_RX_BIG_PK_OK = 1<<7, /* Bit 7 don't set Rx Err bit for */
+ /* jumbo packets */
+ XM_RX_IPG_CAP = 1<<6, /* Bit 6 repl. type field with IPG */
+ XM_RX_TP_MD = 1<<5, /* Bit 5: Enable transparent Mode */
+ XM_RX_STRIP_FCS = 1<<4, /* Bit 4: Enable FCS Stripping */
+ XM_RX_SELF_RX = 1<<3, /* Bit 3: Enable Rx of own packets */
+ XM_RX_SAM_LINE = 1<<2, /* Bit 2: (sc) Start utilization calculation */
+ XM_RX_STRIP_PAD = 1<<1, /* Bit 1: Strip pad bytes of Rx frames */
+ XM_RX_DIS_CEXT = 1<<0, /* Bit 0: Disable carrier ext. check */
+};
+
+
+/* XM_GP_PORT 32 bit r/w General Purpose Port Register */
+enum {
+ XM_GP_ANIP = 1<<6, /* Bit 6: (ro) Auto-Neg. in progress */
+ XM_GP_FRC_INT = 1<<5, /* Bit 5: (sc) Force Interrupt */
+ XM_GP_RES_MAC = 1<<3, /* Bit 3: (sc) Reset MAC and FIFOs */
+ XM_GP_RES_STAT = 1<<2, /* Bit 2: (sc) Reset the statistics module */
+ XM_GP_INP_ASS = 1<<0, /* Bit 0: (ro) GP Input Pin asserted */
+};
+
+
+/* XM_IMSK 16 bit r/w Interrupt Mask Register */
+/* XM_ISRC 16 bit r/o Interrupt Status Register */
+enum {
+ XM_IS_LNK_AE = 1<<14, /* Bit 14: Link Asynchronous Event */
+ XM_IS_TX_ABORT = 1<<13, /* Bit 13: Transmit Abort, late Col. etc */
+ XM_IS_FRC_INT = 1<<12, /* Bit 12: Force INT bit set in GP */
+ XM_IS_INP_ASS = 1<<11, /* Bit 11: Input Asserted, GP bit 0 set */
+ XM_IS_LIPA_RC = 1<<10, /* Bit 10: Link Partner requests config */
+ XM_IS_RX_PAGE = 1<<9, /* Bit 9: Page Received */
+ XM_IS_TX_PAGE = 1<<8, /* Bit 8: Next Page Loaded for Transmit */
+ XM_IS_AND = 1<<7, /* Bit 7: Auto-Negotiation Done */
+ XM_IS_TSC_OV = 1<<6, /* Bit 6: Time Stamp Counter Overflow */
+ XM_IS_RXC_OV = 1<<5, /* Bit 5: Rx Counter Event Overflow */
+ XM_IS_TXC_OV = 1<<4, /* Bit 4: Tx Counter Event Overflow */
+ XM_IS_RXF_OV = 1<<3, /* Bit 3: Receive FIFO Overflow */
+ XM_IS_TXF_UR = 1<<2, /* Bit 2: Transmit FIFO Underrun */
+ XM_IS_TX_COMP = 1<<1, /* Bit 1: Frame Tx Complete */
+ XM_IS_RX_COMP = 1<<0, /* Bit 0: Frame Rx Complete */
+
+ XM_IMSK_DISABLE = 0xffff,
+};
+
+/* XM_HW_CFG 16 bit r/w Hardware Config Register */
+enum {
+ XM_HW_GEN_EOP = 1<<3, /* Bit 3: generate End of Packet pulse */
+ XM_HW_COM4SIG = 1<<2, /* Bit 2: use Comma Detect for Sig. Det.*/
+ XM_HW_GMII_MD = 1<<0, /* Bit 0: GMII Interface selected */
+};
+
+
+/* XM_TX_LO_WM 16 bit r/w Tx FIFO Low Water Mark */
+/* XM_TX_HI_WM 16 bit r/w Tx FIFO High Water Mark */
+#define XM_TX_WM_MSK 0x01ff /* Bit 9.. 0 Tx FIFO Watermark bits */
+
+/* XM_TX_THR 16 bit r/w Tx Request Threshold */
+/* XM_HT_THR 16 bit r/w Host Request Threshold */
+/* XM_RX_THR 16 bit r/w Rx Request Threshold */
+#define XM_THR_MSK 0x03ff /* Bit 10.. 0 Rx/Tx Request Threshold bits */
+
+
+/* XM_TX_STAT 32 bit r/o Tx Status LIFO Register */
+enum {
+ XM_ST_VALID = (1UL<<31), /* Bit 31: Status Valid */
+ XM_ST_BYTE_CNT = (0x3fffL<<17), /* Bit 30..17: Tx frame Length */
+ XM_ST_RETRY_CNT = (0x1fL<<12), /* Bit 16..12: Retry Count */
+ XM_ST_EX_COL = 1<<11, /* Bit 11: Excessive Collisions */
+ XM_ST_EX_DEF = 1<<10, /* Bit 10: Excessive Deferral */
+ XM_ST_BURST = 1<<9, /* Bit 9: p. xmitted in burst md*/
+ XM_ST_DEFER = 1<<8, /* Bit 8: packet was defered */
+ XM_ST_BC = 1<<7, /* Bit 7: Broadcast packet */
+ XM_ST_MC = 1<<6, /* Bit 6: Multicast packet */
+ XM_ST_UC = 1<<5, /* Bit 5: Unicast packet */
+ XM_ST_TX_UR = 1<<4, /* Bit 4: FIFO Underrun occured */
+ XM_ST_CS_ERR = 1<<3, /* Bit 3: Carrier Sense Error */
+ XM_ST_LAT_COL = 1<<2, /* Bit 2: Late Collision Error */
+ XM_ST_MUL_COL = 1<<1, /* Bit 1: Multiple Collisions */
+ XM_ST_SGN_COL = 1<<0, /* Bit 0: Single Collision */
+};
+
+/* XM_RX_LO_WM 16 bit r/w Receive Low Water Mark */
+/* XM_RX_HI_WM 16 bit r/w Receive High Water Mark */
+#define XM_RX_WM_MSK 0x03ff /* Bit 11.. 0: Rx FIFO Watermark bits */
+
+
+/* XM_DEV_ID 32 bit r/o Device ID Register */
+#define XM_DEV_OUI (0x00ffffffUL<<8) /* Bit 31..8: Device OUI */
+#define XM_DEV_REV (0x07L << 5) /* Bit 7..5: Chip Rev Num */
+
+
+/* XM_MODE 32 bit r/w Mode Register */
+enum {
+ XM_MD_ENA_REJ = 1<<26, /* Bit 26: Enable Frame Reject */
+ XM_MD_SPOE_E = 1<<25, /* Bit 25: Send Pause on Edge */
+ /* extern generated */
+ XM_MD_TX_REP = 1<<24, /* Bit 24: Transmit Repeater Mode */
+ XM_MD_SPOFF_I = 1<<23, /* Bit 23: Send Pause on FIFO full */
+ /* intern generated */
+ XM_MD_LE_STW = 1<<22, /* Bit 22: Rx Stat Word in Little Endian */
+ XM_MD_TX_CONT = 1<<21, /* Bit 21: Send Continuous */
+ XM_MD_TX_PAUSE = 1<<20, /* Bit 20: (sc) Send Pause Frame */
+ XM_MD_ATS = 1<<19, /* Bit 19: Append Time Stamp */
+ XM_MD_SPOL_I = 1<<18, /* Bit 18: Send Pause on Low */
+ /* intern generated */
+ XM_MD_SPOH_I = 1<<17, /* Bit 17: Send Pause on High */
+ /* intern generated */
+ XM_MD_CAP = 1<<16, /* Bit 16: Check Address Pair */
+ XM_MD_ENA_HASH = 1<<15, /* Bit 15: Enable Hashing */
+ XM_MD_CSA = 1<<14, /* Bit 14: Check Station Address */
+ XM_MD_CAA = 1<<13, /* Bit 13: Check Address Array */
+ XM_MD_RX_MCTRL = 1<<12, /* Bit 12: Rx MAC Control Frame */
+ XM_MD_RX_RUNT = 1<<11, /* Bit 11: Rx Runt Frames */
+ XM_MD_RX_IRLE = 1<<10, /* Bit 10: Rx in Range Len Err Frame */
+ XM_MD_RX_LONG = 1<<9, /* Bit 9: Rx Long Frame */
+ XM_MD_RX_CRCE = 1<<8, /* Bit 8: Rx CRC Error Frame */
+ XM_MD_RX_ERR = 1<<7, /* Bit 7: Rx Error Frame */
+ XM_MD_DIS_UC = 1<<6, /* Bit 6: Disable Rx Unicast */
+ XM_MD_DIS_MC = 1<<5, /* Bit 5: Disable Rx Multicast */
+ XM_MD_DIS_BC = 1<<4, /* Bit 4: Disable Rx Broadcast */
+ XM_MD_ENA_PROM = 1<<3, /* Bit 3: Enable Promiscuous */
+ XM_MD_ENA_BE = 1<<2, /* Bit 2: Enable Big Endian */
+ XM_MD_FTF = 1<<1, /* Bit 1: (sc) Flush Tx FIFO */
+ XM_MD_FRF = 1<<0, /* Bit 0: (sc) Flush Rx FIFO */
+};
+
+#define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I)
+#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\
+ XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA)
+
+/* XM_STAT_CMD 16 bit r/w Statistics Command Register */
+enum {
+ XM_SC_SNP_RXC = 1<<5, /* Bit 5: (sc) Snap Rx Counters */
+ XM_SC_SNP_TXC = 1<<4, /* Bit 4: (sc) Snap Tx Counters */
+ XM_SC_CP_RXC = 1<<3, /* Bit 3: Copy Rx Counters Continuously */
+ XM_SC_CP_TXC = 1<<2, /* Bit 2: Copy Tx Counters Continuously */
+ XM_SC_CLR_RXC = 1<<1, /* Bit 1: (sc) Clear Rx Counters */
+ XM_SC_CLR_TXC = 1<<0, /* Bit 0: (sc) Clear Tx Counters */
+};
+
+
+/* XM_RX_CNT_EV 32 bit r/o Rx Counter Event Register */
+/* XM_RX_EV_MSK 32 bit r/w Rx Counter Event Mask */
+enum {
+ XMR_MAX_SZ_OV = 1<<31, /* Bit 31: 1024-MaxSize Rx Cnt Ov*/
+ XMR_1023B_OV = 1<<30, /* Bit 30: 512-1023Byte Rx Cnt Ov*/
+ XMR_511B_OV = 1<<29, /* Bit 29: 256-511 Byte Rx Cnt Ov*/
+ XMR_255B_OV = 1<<28, /* Bit 28: 128-255 Byte Rx Cnt Ov*/
+ XMR_127B_OV = 1<<27, /* Bit 27: 65-127 Byte Rx Cnt Ov */
+ XMR_64B_OV = 1<<26, /* Bit 26: 64 Byte Rx Cnt Ov */
+ XMR_UTIL_OV = 1<<25, /* Bit 25: Rx Util Cnt Overflow */
+ XMR_UTIL_UR = 1<<24, /* Bit 24: Rx Util Cnt Underrun */
+ XMR_CEX_ERR_OV = 1<<23, /* Bit 23: CEXT Err Cnt Ov */
+ XMR_FCS_ERR_OV = 1<<21, /* Bit 21: Rx FCS Error Cnt Ov */
+ XMR_LNG_ERR_OV = 1<<20, /* Bit 20: Rx too Long Err Cnt Ov*/
+ XMR_RUNT_OV = 1<<19, /* Bit 19: Runt Event Cnt Ov */
+ XMR_SHT_ERR_OV = 1<<18, /* Bit 18: Rx Short Ev Err Cnt Ov*/
+ XMR_SYM_ERR_OV = 1<<17, /* Bit 17: Rx Sym Err Cnt Ov */
+ XMR_CAR_ERR_OV = 1<<15, /* Bit 15: Rx Carr Ev Err Cnt Ov */
+ XMR_JAB_PKT_OV = 1<<14, /* Bit 14: Rx Jabb Packet Cnt Ov */
+ XMR_FIFO_OV = 1<<13, /* Bit 13: Rx FIFO Ov Ev Cnt Ov */
+ XMR_FRA_ERR_OV = 1<<12, /* Bit 12: Rx Framing Err Cnt Ov */
+ XMR_FMISS_OV = 1<<11, /* Bit 11: Rx Missed Ev Cnt Ov */
+ XMR_BURST = 1<<10, /* Bit 10: Rx Burst Event Cnt Ov */
+ XMR_INV_MOC = 1<<9, /* Bit 9: Rx with inv. MAC OC Ov*/
+ XMR_INV_MP = 1<<8, /* Bit 8: Rx inv Pause Frame Ov */
+ XMR_MCTRL_OV = 1<<7, /* Bit 7: Rx MAC Ctrl-F Cnt Ov */
+ XMR_MPAUSE_OV = 1<<6, /* Bit 6: Rx Pause MAC Ctrl-F Ov*/
+ XMR_UC_OK_OV = 1<<5, /* Bit 5: Rx Unicast Frame CntOv*/
+ XMR_MC_OK_OV = 1<<4, /* Bit 4: Rx Multicast Cnt Ov */
+ XMR_BC_OK_OV = 1<<3, /* Bit 3: Rx Broadcast Cnt Ov */
+ XMR_OK_LO_OV = 1<<2, /* Bit 2: Octets Rx OK Low CntOv*/
+ XMR_OK_HI_OV = 1<<1, /* Bit 1: Octets Rx OK Hi Cnt Ov*/
+ XMR_OK_OV = 1<<0, /* Bit 0: Frames Received Ok Ov */
+};
+
+#define XMR_DEF_MSK (XMR_OK_LO_OV | XMR_OK_HI_OV)
+
+/* XM_TX_CNT_EV 32 bit r/o Tx Counter Event Register */
+/* XM_TX_EV_MSK 32 bit r/w Tx Counter Event Mask */
+enum {
+ XMT_MAX_SZ_OV = 1<<25, /* Bit 25: 1024-MaxSize Tx Cnt Ov*/
+ XMT_1023B_OV = 1<<24, /* Bit 24: 512-1023Byte Tx Cnt Ov*/
+ XMT_511B_OV = 1<<23, /* Bit 23: 256-511 Byte Tx Cnt Ov*/
+ XMT_255B_OV = 1<<22, /* Bit 22: 128-255 Byte Tx Cnt Ov*/
+ XMT_127B_OV = 1<<21, /* Bit 21: 65-127 Byte Tx Cnt Ov */
+ XMT_64B_OV = 1<<20, /* Bit 20: 64 Byte Tx Cnt Ov */
+ XMT_UTIL_OV = 1<<19, /* Bit 19: Tx Util Cnt Overflow */
+ XMT_UTIL_UR = 1<<18, /* Bit 18: Tx Util Cnt Underrun */
+ XMT_CS_ERR_OV = 1<<17, /* Bit 17: Tx Carr Sen Err Cnt Ov*/
+ XMT_FIFO_UR_OV = 1<<16, /* Bit 16: Tx FIFO Ur Ev Cnt Ov */
+ XMT_EX_DEF_OV = 1<<15, /* Bit 15: Tx Ex Deferall Cnt Ov */
+ XMT_DEF = 1<<14, /* Bit 14: Tx Deferred Cnt Ov */
+ XMT_LAT_COL_OV = 1<<13, /* Bit 13: Tx Late Col Cnt Ov */
+ XMT_ABO_COL_OV = 1<<12, /* Bit 12: Tx abo dueto Ex Col Ov*/
+ XMT_MUL_COL_OV = 1<<11, /* Bit 11: Tx Mult Col Cnt Ov */
+ XMT_SNG_COL = 1<<10, /* Bit 10: Tx Single Col Cnt Ov */
+ XMT_MCTRL_OV = 1<<9, /* Bit 9: Tx MAC Ctrl Counter Ov*/
+ XMT_MPAUSE = 1<<8, /* Bit 8: Tx Pause MAC Ctrl-F Ov*/
+ XMT_BURST = 1<<7, /* Bit 7: Tx Burst Event Cnt Ov */
+ XMT_LONG = 1<<6, /* Bit 6: Tx Long Frame Cnt Ov */
+ XMT_UC_OK_OV = 1<<5, /* Bit 5: Tx Unicast Cnt Ov */
+ XMT_MC_OK_OV = 1<<4, /* Bit 4: Tx Multicast Cnt Ov */
+ XMT_BC_OK_OV = 1<<3, /* Bit 3: Tx Broadcast Cnt Ov */
+ XMT_OK_LO_OV = 1<<2, /* Bit 2: Octets Tx OK Low CntOv*/
+ XMT_OK_HI_OV = 1<<1, /* Bit 1: Octets Tx OK Hi Cnt Ov*/
+ XMT_OK_OV = 1<<0, /* Bit 0: Frames Tx Ok Ov */
+};
+
+
+#define XMT_DEF_MSK (XMT_OK_LO_OV | XMT_OK_HI_OV)
+
+struct skge_rx_desc {
+ u32 control;
+ u32 next_offset;
+ u32 dma_lo;
+ u32 dma_hi;
+ u32 status;
+ u32 timestamp;
+ u16 csum2;
+ u16 csum1;
+ u16 csum2_start;
+ u16 csum1_start;
+};
+
+struct skge_tx_desc {
+ u32 control;
+ u32 next_offset;
+ u32 dma_lo;
+ u32 dma_hi;
+ u32 status;
+ u32 csum_offs;
+ u16 csum_write;
+ u16 csum_start;
+ u32 rsvd;
+};
+
+struct skge_element {
+ struct skge_element *next;
+ void *desc;
+ struct io_buffer *iob;
+};
+
+struct skge_ring {
+ struct skge_element *to_clean;
+ struct skge_element *to_use;
+ struct skge_element *start;
+};
+
+
+struct skge_hw {
+ unsigned long regs;
+ struct pci_device *pdev;
+ u32 intr_mask;
+ struct net_device *dev[2];
+
+ u8 chip_id;
+ u8 chip_rev;
+ u8 copper;
+ u8 ports;
+ u8 phy_type;
+
+ u32 ram_size;
+ u32 ram_offset;
+ u16 phy_addr;
+};
+
+enum pause_control {
+ FLOW_MODE_NONE = 1, /* No Flow-Control */
+ FLOW_MODE_LOC_SEND = 2, /* Local station sends PAUSE */
+ FLOW_MODE_SYMMETRIC = 3, /* Both stations may send PAUSE */
+ FLOW_MODE_SYM_OR_REM = 4, /* Both stations may send PAUSE or
+ * just the remote station may send PAUSE
+ */
+};
+
+enum pause_status {
+ FLOW_STAT_INDETERMINATED=0, /* indeterminated */
+ FLOW_STAT_NONE, /* No Flow Control */
+ FLOW_STAT_REM_SEND, /* Remote Station sends PAUSE */
+ FLOW_STAT_LOC_SEND, /* Local station sends PAUSE */
+ FLOW_STAT_SYMMETRIC, /* Both station may send PAUSE */
+};
+
+
+struct skge_port {
+ struct skge_hw *hw;
+ struct net_device *netdev;
+ int port;
+
+ struct skge_ring tx_ring;
+ struct skge_ring rx_ring;
+
+ enum pause_control flow_control;
+ enum pause_status flow_status;
+ u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */
+ u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */
+ u16 speed; /* SPEED_1000, SPEED_100, ... */
+ u32 advertising;
+
+ void *mem; /* PCI memory for rings */
+ u32 dma;
+ int use_xm_link_timer;
+};
+
+
+/* Register accessor for memory mapped device */
+static inline u32 skge_read32(const struct skge_hw *hw, int reg)
+{
+ return readl(hw->regs + reg);
+}
+
+static inline u16 skge_read16(const struct skge_hw *hw, int reg)
+{
+ return readw(hw->regs + reg);
+}
+
+static inline u8 skge_read8(const struct skge_hw *hw, int reg)
+{
+ return readb(hw->regs + reg);
+}
+
+static inline void skge_write32(const struct skge_hw *hw, int reg, u32 val)
+{
+ writel(val, hw->regs + reg);
+}
+
+static inline void skge_write16(const struct skge_hw *hw, int reg, u16 val)
+{
+ writew(val, hw->regs + reg);
+}
+
+static inline void skge_write8(const struct skge_hw *hw, int reg, u8 val)
+{
+ writeb(val, hw->regs + reg);
+}
+
+/* MAC Related Registers inside the device. */
+#define SK_REG(port,reg) (((port)<<7)+(u16)(reg))
+#define SK_XMAC_REG(port, reg) \
+ ((BASE_XMAC_1 + (port) * (BASE_XMAC_2 - BASE_XMAC_1)) | (reg) << 1)
+
+static inline u32 xm_read32(const struct skge_hw *hw, int port, int reg)
+{
+ u32 v;
+ v = skge_read16(hw, SK_XMAC_REG(port, reg));
+ v |= (u32)skge_read16(hw, SK_XMAC_REG(port, reg+2)) << 16;
+ return v;
+}
+
+static inline u16 xm_read16(const struct skge_hw *hw, int port, int reg)
+{
+ return skge_read16(hw, SK_XMAC_REG(port,reg));
+}
+
+static inline void xm_write32(const struct skge_hw *hw, int port, int r, u32 v)
+{
+ skge_write16(hw, SK_XMAC_REG(port,r), v & 0xffff);
+ skge_write16(hw, SK_XMAC_REG(port,r+2), v >> 16);
+}
+
+static inline void xm_write16(const struct skge_hw *hw, int port, int r, u16 v)
+{
+ skge_write16(hw, SK_XMAC_REG(port,r), v);
+}
+
+static inline void xm_outhash(const struct skge_hw *hw, int port, int reg,
+ const u8 *hash)
+{
+ xm_write16(hw, port, reg, (u16)hash[0] | ((u16)hash[1] << 8));
+ xm_write16(hw, port, reg+2, (u16)hash[2] | ((u16)hash[3] << 8));
+ xm_write16(hw, port, reg+4, (u16)hash[4] | ((u16)hash[5] << 8));
+ xm_write16(hw, port, reg+6, (u16)hash[6] | ((u16)hash[7] << 8));
+}
+
+static inline void xm_outaddr(const struct skge_hw *hw, int port, int reg,
+ const u8 *addr)
+{
+ xm_write16(hw, port, reg, (u16)addr[0] | ((u16)addr[1] << 8));
+ xm_write16(hw, port, reg+2, (u16)addr[2] | ((u16)addr[3] << 8));
+ xm_write16(hw, port, reg+4, (u16)addr[4] | ((u16)addr[5] << 8));
+}
+
+#define SK_GMAC_REG(port,reg) \
+ (BASE_GMAC_1 + (port) * (BASE_GMAC_2-BASE_GMAC_1) + (reg))
+
+static inline u16 gma_read16(const struct skge_hw *hw, int port, int reg)
+{
+ return skge_read16(hw, SK_GMAC_REG(port,reg));
+}
+
+static inline u32 gma_read32(const struct skge_hw *hw, int port, int reg)
+{
+ return (u32) skge_read16(hw, SK_GMAC_REG(port,reg))
+ | ((u32)skge_read16(hw, SK_GMAC_REG(port,reg+4)) << 16);
+}
+
+static inline void gma_write16(const struct skge_hw *hw, int port, int r, u16 v)
+{
+ skge_write16(hw, SK_GMAC_REG(port,r), v);
+}
+
+static inline void gma_set_addr(struct skge_hw *hw, int port, int reg,
+ const u8 *addr)
+{
+ gma_write16(hw, port, reg, (u16) addr[0] | ((u16) addr[1] << 8));
+ gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8));
+ gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8));
+}
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/sky2.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/sky2.c
new file mode 100644
index 00000000..5b5bd6b0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/sky2.c
@@ -0,0 +1,2393 @@
+/*
+ * iPXE driver for Marvell Yukon 2 chipset. Derived from Linux sky2 driver
+ * (v1.22), which was based on earlier sk98lin and skge drivers.
+ *
+ * This driver intentionally does not support all the features
+ * of the original driver such as link fail-over and link management because
+ * those should be done at higher levels.
+ *
+ * Copyright (C) 2005 Stephen Hemminger <shemminger@osdl.org>
+ *
+ * Modified for iPXE, April 2009 by Joshua Oreman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include <stdint.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/pci.h>
+#include <byteswap.h>
+#include <mii.h>
+
+#include "sky2.h"
+
+#define DRV_NAME "sky2"
+#define DRV_VERSION "1.22"
+#define PFX DRV_NAME " "
+
+/*
+ * The Yukon II chipset takes 64 bit command blocks (called list elements)
+ * that are organized into three (receive, transmit, status) different rings
+ * similar to Tigon3.
+ *
+ * Each ring start must be aligned to a 4k boundary. You will get mysterious
+ * "invalid LE" errors if they're not.
+ *
+ * The card silently forces each ring size to be at least 128. If you
+ * act as though one of them is smaller (by setting the below
+ * #defines) you'll get bad bugs.
+ */
+
+#define RX_LE_SIZE 128
+#define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le))
+#define RX_RING_ALIGN 4096
+#define RX_PENDING (RX_LE_SIZE/6 - 2)
+
+#define TX_RING_SIZE 128
+#define TX_PENDING (TX_RING_SIZE - 1)
+#define TX_RING_ALIGN 4096
+#define MAX_SKB_TX_LE 4
+
+#define STATUS_RING_SIZE 512 /* 2 ports * (TX + RX) */
+#define STATUS_LE_BYTES (STATUS_RING_SIZE*sizeof(struct sky2_status_le))
+#define STATUS_RING_ALIGN 4096
+#define PHY_RETRIES 1000
+
+#define SKY2_EEPROM_MAGIC 0x9955aabb
+
+
+#define RING_NEXT(x,s) (((x)+1) & ((s)-1))
+
+static struct pci_device_id sky2_id_table[] = {
+ PCI_ROM(0x1148, 0x9000, "sk9sxx", "Syskonnect SK-9Sxx", 0),
+ PCI_ROM(0x1148, 0x9e00, "sk9exx", "Syskonnect SK-9Exx", 0),
+ PCI_ROM(0x1186, 0x4b00, "dge560t", "D-Link DGE-560T", 0),
+ PCI_ROM(0x1186, 0x4001, "dge550sx", "D-Link DGE-550SX", 0),
+ PCI_ROM(0x1186, 0x4b02, "dge560sx", "D-Link DGE-560SX", 0),
+ PCI_ROM(0x1186, 0x4b03, "dge550t", "D-Link DGE-550T", 0),
+ PCI_ROM(0x11ab, 0x4340, "m88e8021", "Marvell 88E8021", 0),
+ PCI_ROM(0x11ab, 0x4341, "m88e8022", "Marvell 88E8022", 0),
+ PCI_ROM(0x11ab, 0x4342, "m88e8061", "Marvell 88E8061", 0),
+ PCI_ROM(0x11ab, 0x4343, "m88e8062", "Marvell 88E8062", 0),
+ PCI_ROM(0x11ab, 0x4344, "m88e8021b", "Marvell 88E8021", 0),
+ PCI_ROM(0x11ab, 0x4345, "m88e8022b", "Marvell 88E8022", 0),
+ PCI_ROM(0x11ab, 0x4346, "m88e8061b", "Marvell 88E8061", 0),
+ PCI_ROM(0x11ab, 0x4347, "m88e8062b", "Marvell 88E8062", 0),
+ PCI_ROM(0x11ab, 0x4350, "m88e8035", "Marvell 88E8035", 0),
+ PCI_ROM(0x11ab, 0x4351, "m88e8036", "Marvell 88E8036", 0),
+ PCI_ROM(0x11ab, 0x4352, "m88e8038", "Marvell 88E8038", 0),
+ PCI_ROM(0x11ab, 0x4353, "m88e8039", "Marvell 88E8039", 0),
+ PCI_ROM(0x11ab, 0x4354, "m88e8040", "Marvell 88E8040", 0),
+ PCI_ROM(0x11ab, 0x4355, "m88e8040t", "Marvell 88E8040T", 0),
+ PCI_ROM(0x11ab, 0x4356, "m88ec033", "Marvel 88EC033", 0),
+ PCI_ROM(0x11ab, 0x4357, "m88e8042", "Marvell 88E8042", 0),
+ PCI_ROM(0x11ab, 0x435a, "m88e8048", "Marvell 88E8048", 0),
+ PCI_ROM(0x11ab, 0x4360, "m88e8052", "Marvell 88E8052", 0),
+ PCI_ROM(0x11ab, 0x4361, "m88e8050", "Marvell 88E8050", 0),
+ PCI_ROM(0x11ab, 0x4362, "m88e8053", "Marvell 88E8053", 0),
+ PCI_ROM(0x11ab, 0x4363, "m88e8055", "Marvell 88E8055", 0),
+ PCI_ROM(0x11ab, 0x4364, "m88e8056", "Marvell 88E8056", 0),
+ PCI_ROM(0x11ab, 0x4365, "m88e8070", "Marvell 88E8070", 0),
+ PCI_ROM(0x11ab, 0x4366, "m88ec036", "Marvell 88EC036", 0),
+ PCI_ROM(0x11ab, 0x4367, "m88ec032", "Marvell 88EC032", 0),
+ PCI_ROM(0x11ab, 0x4368, "m88ec034", "Marvell 88EC034", 0),
+ PCI_ROM(0x11ab, 0x4369, "m88ec042", "Marvell 88EC042", 0),
+ PCI_ROM(0x11ab, 0x436a, "m88e8058", "Marvell 88E8058", 0),
+ PCI_ROM(0x11ab, 0x436b, "m88e8071", "Marvell 88E8071", 0),
+ PCI_ROM(0x11ab, 0x436c, "m88e8072", "Marvell 88E8072", 0),
+ PCI_ROM(0x11ab, 0x436d, "m88e8055b", "Marvell 88E8055", 0),
+ PCI_ROM(0x11ab, 0x4370, "m88e8075", "Marvell 88E8075", 0),
+ PCI_ROM(0x11ab, 0x4380, "m88e8057", "Marvell 88E8057", 0)
+};
+
+/* Avoid conditionals by using array */
+static const unsigned txqaddr[] = { Q_XA1, Q_XA2 };
+static const unsigned rxqaddr[] = { Q_R1, Q_R2 };
+static const u32 portirq_msk[] = { Y2_IS_PORT_1, Y2_IS_PORT_2 };
+
+static void sky2_set_multicast(struct net_device *dev);
+
+/* Access to PHY via serial interconnect */
+static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val)
+{
+ int i;
+
+ gma_write16(hw, port, GM_SMI_DATA, val);
+ gma_write16(hw, port, GM_SMI_CTRL,
+ GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg));
+
+ for (i = 0; i < PHY_RETRIES; i++) {
+ u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL);
+ if (ctrl == 0xffff)
+ goto io_error;
+
+ if (!(ctrl & GM_SMI_CT_BUSY))
+ return 0;
+
+ udelay(10);
+ }
+
+ DBG(PFX "%s: phy write timeout\n", hw->dev[port]->name);
+ return -ETIMEDOUT;
+
+io_error:
+ DBG(PFX "%s: phy I/O error\n", hw->dev[port]->name);
+ return -EIO;
+}
+
+static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val)
+{
+ int i;
+
+ gma_write16(hw, port, GM_SMI_CTRL, GM_SMI_CT_PHY_AD(PHY_ADDR_MARV)
+ | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD);
+
+ for (i = 0; i < PHY_RETRIES; i++) {
+ u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL);
+ if (ctrl == 0xffff)
+ goto io_error;
+
+ if (ctrl & GM_SMI_CT_RD_VAL) {
+ *val = gma_read16(hw, port, GM_SMI_DATA);
+ return 0;
+ }
+
+ udelay(10);
+ }
+
+ DBG(PFX "%s: phy read timeout\n", hw->dev[port]->name);
+ return -ETIMEDOUT;
+io_error:
+ DBG(PFX "%s: phy I/O error\n", hw->dev[port]->name);
+ return -EIO;
+}
+
+static inline u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg)
+{
+ u16 v = 0;
+ __gm_phy_read(hw, port, reg, &v);
+ return v;
+}
+
+
+static void sky2_power_on(struct sky2_hw *hw)
+{
+ /* switch power to VCC (WA for VAUX problem) */
+ sky2_write8(hw, B0_POWER_CTRL,
+ PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON);
+
+ /* disable Core Clock Division, */
+ sky2_write32(hw, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS);
+
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
+ /* enable bits are inverted */
+ sky2_write8(hw, B2_Y2_CLK_GATE,
+ Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS |
+ Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS |
+ Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS);
+ else
+ sky2_write8(hw, B2_Y2_CLK_GATE, 0);
+
+ if (hw->flags & SKY2_HW_ADV_POWER_CTL) {
+ u32 reg;
+
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+
+ reg = sky2_pci_read32(hw, PCI_DEV_REG4);
+ /* set all bits to 0 except bits 15..12 and 8 */
+ reg &= P_ASPM_CONTROL_MSK;
+ sky2_pci_write32(hw, PCI_DEV_REG4, reg);
+
+ reg = sky2_pci_read32(hw, PCI_DEV_REG5);
+ /* set all bits to 0 except bits 28 & 27 */
+ reg &= P_CTL_TIM_VMAIN_AV_MSK;
+ sky2_pci_write32(hw, PCI_DEV_REG5, reg);
+
+ sky2_pci_write32(hw, PCI_CFG_REG_1, 0);
+
+ /* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */
+ reg = sky2_read32(hw, B2_GP_IO);
+ reg |= GLB_GPIO_STAT_RACE_DIS;
+ sky2_write32(hw, B2_GP_IO, reg);
+
+ sky2_read32(hw, B2_GP_IO);
+ }
+}
+
+static void sky2_power_aux(struct sky2_hw *hw)
+{
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
+ sky2_write8(hw, B2_Y2_CLK_GATE, 0);
+ else
+ /* enable bits are inverted */
+ sky2_write8(hw, B2_Y2_CLK_GATE,
+ Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS |
+ Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS |
+ Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS);
+
+ /* switch power to VAUX */
+ if (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL)
+ sky2_write8(hw, B0_POWER_CTRL,
+ (PC_VAUX_ENA | PC_VCC_ENA |
+ PC_VAUX_ON | PC_VCC_OFF));
+}
+
+static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port)
+{
+ u16 reg;
+
+ /* disable all GMAC IRQ's */
+ sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+
+ gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */
+ gma_write16(hw, port, GM_MC_ADDR_H2, 0);
+ gma_write16(hw, port, GM_MC_ADDR_H3, 0);
+ gma_write16(hw, port, GM_MC_ADDR_H4, 0);
+
+ reg = gma_read16(hw, port, GM_RX_CTRL);
+ reg |= GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA;
+ gma_write16(hw, port, GM_RX_CTRL, reg);
+}
+
+/* flow control to advertise bits */
+static const u16 copper_fc_adv[] = {
+ [FC_NONE] = 0,
+ [FC_TX] = PHY_M_AN_ASP,
+ [FC_RX] = PHY_M_AN_PC,
+ [FC_BOTH] = PHY_M_AN_PC | PHY_M_AN_ASP,
+};
+
+/* flow control to advertise bits when using 1000BaseX */
+static const u16 fiber_fc_adv[] = {
+ [FC_NONE] = PHY_M_P_NO_PAUSE_X,
+ [FC_TX] = PHY_M_P_ASYM_MD_X,
+ [FC_RX] = PHY_M_P_SYM_MD_X,
+ [FC_BOTH] = PHY_M_P_BOTH_MD_X,
+};
+
+/* flow control to GMA disable bits */
+static const u16 gm_fc_disable[] = {
+ [FC_NONE] = GM_GPCR_FC_RX_DIS | GM_GPCR_FC_TX_DIS,
+ [FC_TX] = GM_GPCR_FC_RX_DIS,
+ [FC_RX] = GM_GPCR_FC_TX_DIS,
+ [FC_BOTH] = 0,
+};
+
+
+static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
+{
+ struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
+ u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg;
+
+ if (sky2->autoneg == AUTONEG_ENABLE &&
+ !(hw->flags & SKY2_HW_NEWER_PHY)) {
+ u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
+
+ ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
+ PHY_M_EC_MAC_S_MSK);
+ ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
+
+ /* on PHY 88E1040 Rev.D0 (and newer) downshift control changed */
+ if (hw->chip_id == CHIP_ID_YUKON_EC)
+ /* set downshift counter to 3x and enable downshift */
+ ectrl |= PHY_M_EC_DSC_2(2) | PHY_M_EC_DOWN_S_ENA;
+ else
+ /* set master & slave downshift counter to 1x */
+ ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
+
+ gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl);
+ }
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ if (sky2_is_copper(hw)) {
+ if (!(hw->flags & SKY2_HW_GIGABIT)) {
+ /* enable automatic crossover */
+ ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1;
+
+ if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0) {
+ u16 spec;
+
+ /* Enable Class A driver for FE+ A0 */
+ spec = gm_phy_read(hw, port, PHY_MARV_FE_SPEC_2);
+ spec |= PHY_M_FESC_SEL_CL_A;
+ gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec);
+ }
+ } else {
+ /* disable energy detect */
+ ctrl &= ~PHY_M_PC_EN_DET_MSK;
+
+ /* enable automatic crossover */
+ ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO);
+
+ /* downshift on PHY 88E1112 and 88E1149 is changed */
+ if (sky2->autoneg == AUTONEG_ENABLE
+ && (hw->flags & SKY2_HW_NEWER_PHY)) {
+ /* set downshift counter to 3x and enable downshift */
+ ctrl &= ~PHY_M_PC_DSC_MSK;
+ ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
+ }
+ }
+ } else {
+ /* workaround for deviation #4.88 (CRC errors) */
+ /* disable Automatic Crossover */
+
+ ctrl &= ~PHY_M_PC_MDIX_MSK;
+ }
+
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ /* special setup for PHY 88E1112 Fiber */
+ if (hw->chip_id == CHIP_ID_YUKON_XL && (hw->flags & SKY2_HW_FIBRE_PHY)) {
+ pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+
+ /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2);
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ ctrl &= ~PHY_M_MAC_MD_MSK;
+ ctrl |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX);
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ if (hw->pmd_type == 'P') {
+ /* select page 1 to access Fiber registers */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 1);
+
+ /* for SFP-module set SIGDET polarity to low */
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ ctrl |= PHY_M_FIB_SIGD_POL;
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+ }
+
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ }
+
+ ctrl = PHY_CT_RESET;
+ ct1000 = 0;
+ adv = PHY_AN_CSMA;
+ reg = 0;
+
+ if (sky2->autoneg == AUTONEG_ENABLE) {
+ if (sky2_is_copper(hw)) {
+ if (sky2->advertising & ADVERTISED_1000baseT_Full)
+ ct1000 |= PHY_M_1000C_AFD;
+ if (sky2->advertising & ADVERTISED_1000baseT_Half)
+ ct1000 |= PHY_M_1000C_AHD;
+ if (sky2->advertising & ADVERTISED_100baseT_Full)
+ adv |= PHY_M_AN_100_FD;
+ if (sky2->advertising & ADVERTISED_100baseT_Half)
+ adv |= PHY_M_AN_100_HD;
+ if (sky2->advertising & ADVERTISED_10baseT_Full)
+ adv |= PHY_M_AN_10_FD;
+ if (sky2->advertising & ADVERTISED_10baseT_Half)
+ adv |= PHY_M_AN_10_HD;
+
+ adv |= copper_fc_adv[sky2->flow_mode];
+ } else { /* special defines for FIBER (88E1040S only) */
+ if (sky2->advertising & ADVERTISED_1000baseT_Full)
+ adv |= PHY_M_AN_1000X_AFD;
+ if (sky2->advertising & ADVERTISED_1000baseT_Half)
+ adv |= PHY_M_AN_1000X_AHD;
+
+ adv |= fiber_fc_adv[sky2->flow_mode];
+ }
+
+ /* Restart Auto-negotiation */
+ ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
+ } else {
+ /* forced speed/duplex settings */
+ ct1000 = PHY_M_1000C_MSE;
+
+ /* Disable auto update for duplex flow control and speed */
+ reg |= GM_GPCR_AU_ALL_DIS;
+
+ switch (sky2->speed) {
+ case SPEED_1000:
+ ctrl |= PHY_CT_SP1000;
+ reg |= GM_GPCR_SPEED_1000;
+ break;
+ case SPEED_100:
+ ctrl |= PHY_CT_SP100;
+ reg |= GM_GPCR_SPEED_100;
+ break;
+ }
+
+ if (sky2->duplex == DUPLEX_FULL) {
+ reg |= GM_GPCR_DUP_FULL;
+ ctrl |= PHY_CT_DUP_MD;
+ } else if (sky2->speed < SPEED_1000)
+ sky2->flow_mode = FC_NONE;
+
+
+ reg |= gm_fc_disable[sky2->flow_mode];
+
+ /* Forward pause packets to GMAC? */
+ if (sky2->flow_mode & FC_RX)
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
+ else
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+ }
+
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+
+ if (hw->flags & SKY2_HW_GIGABIT)
+ gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
+
+ gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
+ gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+ /* Setup Phy LED's */
+ ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS);
+ ledover = 0;
+
+ switch (hw->chip_id) {
+ case CHIP_ID_YUKON_FE:
+ /* on 88E3082 these bits are at 11..9 (shifted left) */
+ ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) << 1;
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_FE_LED_PAR);
+
+ /* delete ACT LED control bits */
+ ctrl &= ~PHY_M_FELP_LED1_MSK;
+ /* change ACT LED control to blink mode */
+ ctrl |= PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_ACT_BL);
+ gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl);
+ break;
+
+ case CHIP_ID_YUKON_FE_P:
+ /* Enable Link Partner Next Page */
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ ctrl |= PHY_M_PC_ENA_LIP_NP;
+
+ /* disable Energy Detect and enable scrambler */
+ ctrl &= ~(PHY_M_PC_ENA_ENE_DT | PHY_M_PC_DIS_SCRAMB);
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ /* set LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED */
+ ctrl = PHY_M_FELP_LED2_CTRL(LED_PAR_CTRL_ACT_BL) |
+ PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_LINK) |
+ PHY_M_FELP_LED0_CTRL(LED_PAR_CTRL_SPEED);
+
+ gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl);
+ break;
+
+ case CHIP_ID_YUKON_XL:
+ pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+
+ /* select page 3 to access LED control register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+
+ /* set LED Function Control register */
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+ (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
+ PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */
+ PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */
+ PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */
+
+ /* set Polarity Control register */
+ gm_phy_write(hw, port, PHY_MARV_PHY_STAT,
+ (PHY_M_POLC_LS1_P_MIX(4) |
+ PHY_M_POLC_IS0_P_MIX(4) |
+ PHY_M_POLC_LOS_CTRL(2) |
+ PHY_M_POLC_INIT_CTRL(2) |
+ PHY_M_POLC_STA1_CTRL(2) |
+ PHY_M_POLC_STA0_CTRL(2)));
+
+ /* restore page register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ break;
+
+ case CHIP_ID_YUKON_EC_U:
+ case CHIP_ID_YUKON_EX:
+ case CHIP_ID_YUKON_SUPR:
+ pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+
+ /* select page 3 to access LED control register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+
+ /* set LED Function Control register */
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+ (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
+ PHY_M_LEDC_INIT_CTRL(8) | /* 10 Mbps */
+ PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */
+ PHY_M_LEDC_STA0_CTRL(7)));/* 1000 Mbps */
+
+ /* set Blink Rate in LED Timer Control Register */
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK,
+ ledctrl | PHY_M_LED_BLINK_RT(BLINK_84MS));
+ /* restore page register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ break;
+
+ default:
+ /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */
+ ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
+
+ /* turn off the Rx LED (LED_RX) */
+ ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
+ }
+
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_UL_2) {
+ /* apply fixes in PHY AFE */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 255);
+
+ /* increase differential signal amplitude in 10BASE-T */
+ gm_phy_write(hw, port, 0x18, 0xaa99);
+ gm_phy_write(hw, port, 0x17, 0x2011);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
+ /* fix for IEEE A/B Symmetry failure in 1000BASE-T */
+ gm_phy_write(hw, port, 0x18, 0xa204);
+ gm_phy_write(hw, port, 0x17, 0x2002);
+ }
+
+ /* set page register to 0 */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
+ } else if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0) {
+ /* apply workaround for integrated resistors calibration */
+ gm_phy_write(hw, port, PHY_MARV_PAGE_ADDR, 17);
+ gm_phy_write(hw, port, PHY_MARV_PAGE_DATA, 0x3f60);
+ } else if (hw->chip_id != CHIP_ID_YUKON_EX &&
+ hw->chip_id < CHIP_ID_YUKON_SUPR) {
+ /* no effect on Yukon-XL */
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
+
+ if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) {
+ /* turn on 100 Mbps LED (LED_LINK100) */
+ ledover |= PHY_M_LED_MO_100(MO_LED_ON);
+ }
+
+ if (ledover)
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+
+ }
+
+ /* Enable phy interrupt on auto-negotiation complete (or link up) */
+ if (sky2->autoneg == AUTONEG_ENABLE)
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
+ else
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+}
+
+static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD };
+static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA };
+
+static void sky2_phy_power_up(struct sky2_hw *hw, unsigned port)
+{
+ u32 reg1;
+
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
+ reg1 &= ~phy_power[port];
+
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
+ reg1 |= coma_mode[port];
+
+ sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+ sky2_pci_read32(hw, PCI_DEV_REG1);
+
+ if (hw->chip_id == CHIP_ID_YUKON_FE)
+ gm_phy_write(hw, port, PHY_MARV_CTRL, PHY_CT_ANE);
+ else if (hw->flags & SKY2_HW_ADV_POWER_CTL)
+ sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR);
+}
+
+static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
+{
+ u32 reg1;
+ u16 ctrl;
+
+ /* release GPHY Control reset */
+ sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR);
+
+ /* release GMAC reset */
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);
+
+ if (hw->flags & SKY2_HW_NEWER_PHY) {
+ /* select page 2 to access MAC control register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2);
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ /* allow GMII Power Down */
+ ctrl &= ~PHY_M_MAC_GMIF_PUP;
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ /* set page register back to 0 */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
+ }
+
+ /* setup General Purpose Control Register */
+ gma_write16(hw, port, GM_GP_CTRL,
+ GM_GPCR_FL_PASS | GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS);
+
+ if (hw->chip_id != CHIP_ID_YUKON_EC) {
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
+ /* select page 2 to access MAC control register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2);
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ /* enable Power Down */
+ ctrl |= PHY_M_PC_POW_D_ENA;
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ /* set page register back to 0 */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
+ }
+
+ /* set IEEE compatible Power Down Mode (dev. #4.99) */
+ gm_phy_write(hw, port, PHY_MARV_CTRL, PHY_CT_PDOWN);
+ }
+
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
+ reg1 |= phy_power[port]; /* set PHY to PowerDown/COMA Mode */
+ sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+}
+
+static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
+{
+ if ( (hw->chip_id == CHIP_ID_YUKON_EX &&
+ hw->chip_rev != CHIP_REV_YU_EX_A0) ||
+ hw->chip_id == CHIP_ID_YUKON_FE_P ||
+ hw->chip_id == CHIP_ID_YUKON_SUPR) {
+ /* disable jumbo frames on devices that support them */
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_JUMBO_DIS | TX_STFW_ENA);
+ } else {
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_ENA);
+ }
+}
+
+static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
+{
+ u16 reg;
+ u32 rx_reg;
+ int i;
+ const u8 *addr = hw->dev[port]->ll_addr;
+
+ sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+ sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR);
+
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);
+
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0 && port == 1) {
+ /* WA DEV_472 -- looks like crossed wires on port 2 */
+ /* clear GMAC 1 Control reset */
+ sky2_write8(hw, SK_REG(0, GMAC_CTRL), GMC_RST_CLR);
+ do {
+ sky2_write8(hw, SK_REG(1, GMAC_CTRL), GMC_RST_SET);
+ sky2_write8(hw, SK_REG(1, GMAC_CTRL), GMC_RST_CLR);
+ } while (gm_phy_read(hw, 1, PHY_MARV_ID0) != PHY_MARV_ID0_VAL ||
+ gm_phy_read(hw, 1, PHY_MARV_ID1) != PHY_MARV_ID1_Y2 ||
+ gm_phy_read(hw, 1, PHY_MARV_INT_MASK) != 0);
+ }
+
+ sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
+
+ /* Enable Transmit FIFO Underrun */
+ sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
+
+ sky2_phy_power_up(hw, port);
+ sky2_phy_init(hw, port);
+
+ /* MIB clear */
+ reg = gma_read16(hw, port, GM_PHY_ADDR);
+ gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
+
+ for (i = GM_MIB_CNT_BASE; i <= GM_MIB_CNT_END; i += 4)
+ gma_read16(hw, port, i);
+ gma_write16(hw, port, GM_PHY_ADDR, reg);
+
+ /* transmit control */
+ gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF));
+
+ /* receive control reg: unicast + multicast + no FCS */
+ gma_write16(hw, port, GM_RX_CTRL,
+ GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA);
+
+ /* transmit flow control */
+ gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff);
+
+ /* transmit parameter */
+ gma_write16(hw, port, GM_TX_PARAM,
+ TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) |
+ TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) |
+ TX_IPG_JAM_DATA(TX_IPG_JAM_DEF) |
+ TX_BACK_OFF_LIM(TX_BOF_LIM_DEF));
+
+ /* serial mode register */
+ reg = DATA_BLIND_VAL(DATA_BLIND_DEF) |
+ GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
+
+ gma_write16(hw, port, GM_SERIAL_MODE, reg);
+
+ /* virtual address for data */
+ gma_set_addr(hw, port, GM_SRC_ADDR_2L, addr);
+
+ /* physical address: used for pause frames */
+ gma_set_addr(hw, port, GM_SRC_ADDR_1L, addr);
+
+ /* ignore counter overflows */
+ gma_write16(hw, port, GM_TX_IRQ_MSK, 0);
+ gma_write16(hw, port, GM_RX_IRQ_MSK, 0);
+ gma_write16(hw, port, GM_TR_IRQ_MSK, 0);
+
+ /* Configure Rx MAC FIFO */
+ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
+ rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
+ if (hw->chip_id == CHIP_ID_YUKON_EX ||
+ hw->chip_id == CHIP_ID_YUKON_FE_P)
+ rx_reg |= GMF_RX_OVER_ON;
+
+ sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg);
+
+ if (hw->chip_id == CHIP_ID_YUKON_XL) {
+ /* Hardware errata - clear flush mask */
+ sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), 0);
+ } else {
+ /* Flush Rx MAC FIFO on any flow control or error */
+ sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
+ }
+
+ /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */
+ reg = RX_GMF_FL_THR_DEF + 1;
+ /* Another magic mystery workaround from sk98lin */
+ if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0)
+ reg = 0x178;
+ sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), reg);
+
+ /* Configure Tx MAC FIFO */
+ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
+ sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
+
+ /* On chips without ram buffer, pause is controled by MAC level */
+ if (!(hw->flags & SKY2_HW_RAM_BUFFER)) {
+ sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
+ sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
+
+ sky2_set_tx_stfwd(hw, port);
+ }
+
+ if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0) {
+ /* disable dynamic watermark */
+ reg = sky2_read16(hw, SK_REG(port, TX_GMF_EA));
+ reg &= ~TX_DYN_WM_ENA;
+ sky2_write16(hw, SK_REG(port, TX_GMF_EA), reg);
+ }
+}
+
+/* Assign Ram Buffer allocation to queue */
+static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 space)
+{
+ u32 end;
+
+ /* convert from K bytes to qwords used for hw register */
+ start *= 1024/8;
+ space *= 1024/8;
+ end = start + space - 1;
+
+ sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
+ sky2_write32(hw, RB_ADDR(q, RB_START), start);
+ sky2_write32(hw, RB_ADDR(q, RB_END), end);
+ sky2_write32(hw, RB_ADDR(q, RB_WP), start);
+ sky2_write32(hw, RB_ADDR(q, RB_RP), start);
+
+ if (q == Q_R1 || q == Q_R2) {
+ u32 tp = space - space/4;
+
+ /* On receive queue's set the thresholds
+ * give receiver priority when > 3/4 full
+ * send pause when down to 2K
+ */
+ sky2_write32(hw, RB_ADDR(q, RB_RX_UTHP), tp);
+ sky2_write32(hw, RB_ADDR(q, RB_RX_LTHP), space/2);
+
+ tp = space - 2048/8;
+ sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp);
+ sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4);
+ } else {
+ /* Enable store & forward on Tx queue's because
+ * Tx FIFO is only 1K on Yukon
+ */
+ sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD);
+ }
+
+ sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD);
+ sky2_read8(hw, RB_ADDR(q, RB_CTRL));
+}
+
+/* Setup Bus Memory Interface */
+static void sky2_qset(struct sky2_hw *hw, u16 q)
+{
+ sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_RESET);
+ sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_OPER_INIT);
+ sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_FIFO_OP_ON);
+ sky2_write32(hw, Q_ADDR(q, Q_WM), BMU_WM_DEFAULT);
+}
+
+/* Setup prefetch unit registers. This is the interface between
+ * hardware and driver list elements
+ */
+static void sky2_prefetch_init(struct sky2_hw *hw, u32 qaddr,
+ u64 addr, u32 last)
+{
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_RST_CLR);
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_ADDR_HI), addr >> 32);
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_ADDR_LO), (u32) addr);
+ sky2_write16(hw, Y2_QADDR(qaddr, PREF_UNIT_LAST_IDX), last);
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_OP_ON);
+
+ sky2_read32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL));
+}
+
+static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2)
+{
+ struct sky2_tx_le *le = sky2->tx_le + sky2->tx_prod;
+
+ sky2->tx_prod = RING_NEXT(sky2->tx_prod, TX_RING_SIZE);
+ le->ctrl = 0;
+ return le;
+}
+
+static void tx_init(struct sky2_port *sky2)
+{
+ struct sky2_tx_le *le;
+
+ sky2->tx_prod = sky2->tx_cons = 0;
+
+ le = get_tx_le(sky2);
+ le->addr = 0;
+ le->opcode = OP_ADDR64 | HW_OWNER;
+}
+
+static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2,
+ struct sky2_tx_le *le)
+{
+ return sky2->tx_ring + (le - sky2->tx_le);
+}
+
+/* Update chip's next pointer */
+static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx)
+{
+ /* Make sure write' to descriptors are complete before we tell hardware */
+ wmb();
+ sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx);
+ DBGIO(PFX "queue %#x idx <- %d\n", q, idx);
+}
+
+
+static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
+{
+ struct sky2_rx_le *le = sky2->rx_le + sky2->rx_put;
+
+ sky2->rx_put = RING_NEXT(sky2->rx_put, RX_LE_SIZE);
+ le->ctrl = 0;
+ return le;
+}
+
+/* Build description to hardware for one receive segment */
+static void sky2_rx_add(struct sky2_port *sky2, u8 op,
+ u32 map, unsigned len)
+{
+ struct sky2_rx_le *le;
+
+ le = sky2_next_rx(sky2);
+ le->addr = cpu_to_le32(map);
+ le->length = cpu_to_le16(len);
+ le->opcode = op | HW_OWNER;
+}
+
+/* Build description to hardware for one possibly fragmented skb */
+static void sky2_rx_submit(struct sky2_port *sky2,
+ const struct rx_ring_info *re)
+{
+ sky2_rx_add(sky2, OP_PACKET, re->data_addr, sky2->rx_data_size);
+}
+
+
+static void sky2_rx_map_iob(struct pci_device *pdev __unused,
+ struct rx_ring_info *re,
+ unsigned size __unused)
+{
+ struct io_buffer *iob = re->iob;
+ re->data_addr = virt_to_bus(iob->data);
+}
+
+/* Diable the checksum offloading.
+ */
+static void rx_set_checksum(struct sky2_port *sky2)
+{
+ struct sky2_rx_le *le = sky2_next_rx(sky2);
+
+ le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
+ le->ctrl = 0;
+ le->opcode = OP_TCPSTART | HW_OWNER;
+
+ sky2_write32(sky2->hw,
+ Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ BMU_DIS_RX_CHKSUM);
+}
+
+/*
+ * The RX Stop command will not work for Yukon-2 if the BMU does not
+ * reach the end of packet and since we can't make sure that we have
+ * incoming data, we must reset the BMU while it is not doing a DMA
+ * transfer. Since it is possible that the RX path is still active,
+ * the RX RAM buffer will be stopped first, so any possible incoming
+ * data will not trigger a DMA. After the RAM buffer is stopped, the
+ * BMU is polled until any DMA in progress is ended and only then it
+ * will be reset.
+ */
+static void sky2_rx_stop(struct sky2_port *sky2)
+{
+ struct sky2_hw *hw = sky2->hw;
+ unsigned rxq = rxqaddr[sky2->port];
+ int i;
+
+ /* disable the RAM Buffer receive queue */
+ sky2_write8(hw, RB_ADDR(rxq, RB_CTRL), RB_DIS_OP_MD);
+
+ for (i = 0; i < 0xffff; i++)
+ if (sky2_read8(hw, RB_ADDR(rxq, Q_RSL))
+ == sky2_read8(hw, RB_ADDR(rxq, Q_RL)))
+ goto stopped;
+
+ DBG(PFX "%s: receiver stop failed\n", sky2->netdev->name);
+stopped:
+ sky2_write32(hw, Q_ADDR(rxq, Q_CSR), BMU_RST_SET | BMU_FIFO_RST);
+
+ /* reset the Rx prefetch unit */
+ sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
+ wmb();
+}
+
+/* Clean out receive buffer area, assumes receiver hardware stopped */
+static void sky2_rx_clean(struct sky2_port *sky2)
+{
+ unsigned i;
+
+ memset(sky2->rx_le, 0, RX_LE_BYTES);
+ for (i = 0; i < RX_PENDING; i++) {
+ struct rx_ring_info *re = sky2->rx_ring + i;
+
+ if (re->iob) {
+ free_iob(re->iob);
+ re->iob = NULL;
+ }
+ }
+}
+
+/*
+ * Allocate an iob for receiving.
+ */
+static struct io_buffer *sky2_rx_alloc(struct sky2_port *sky2)
+{
+ struct io_buffer *iob;
+
+ iob = alloc_iob(sky2->rx_data_size + ETH_DATA_ALIGN);
+ if (!iob)
+ return NULL;
+
+ /*
+ * Cards with a RAM buffer hang in the rx FIFO if the
+ * receive buffer isn't aligned to (Linux module comments say
+ * 64 bytes, Linux module code says 8 bytes). Since io_buffers
+ * are always 2kb-aligned under iPXE, just leave it be
+ * without ETH_DATA_ALIGN in those cases.
+ *
+ * XXX This causes unaligned access to the IP header,
+ * which is undesirable, but it's less undesirable than the
+ * card hanging.
+ */
+ if (!(sky2->hw->flags & SKY2_HW_RAM_BUFFER)) {
+ iob_reserve(iob, ETH_DATA_ALIGN);
+ }
+
+ return iob;
+}
+
+static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq)
+{
+ sky2_put_idx(sky2->hw, rxq, sky2->rx_put);
+}
+
+/*
+ * Allocate and setup receiver buffer pool.
+ * Normal case this ends up creating one list element for skb
+ * in the receive ring. One element is used for checksum
+ * enable/disable, and one extra to avoid wrap.
+ */
+static int sky2_rx_start(struct sky2_port *sky2)
+{
+ struct sky2_hw *hw = sky2->hw;
+ struct rx_ring_info *re;
+ unsigned rxq = rxqaddr[sky2->port];
+ unsigned i, size, thresh;
+
+ sky2->rx_put = sky2->rx_next = 0;
+ sky2_qset(hw, rxq);
+
+ /* On PCI express lowering the watermark gives better performance */
+ if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP))
+ sky2_write32(hw, Q_ADDR(rxq, Q_WM), BMU_WM_PEX);
+
+ /* These chips have no ram buffer?
+ * MAC Rx RAM Read is controlled by hardware */
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
+ (hw->chip_rev == CHIP_REV_YU_EC_U_A1
+ || hw->chip_rev == CHIP_REV_YU_EC_U_B0))
+ sky2_write32(hw, Q_ADDR(rxq, Q_TEST), F_M_RX_RAM_DIS);
+
+ sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
+
+ if (!(hw->flags & SKY2_HW_NEW_LE))
+ rx_set_checksum(sky2);
+
+ /* Space needed for frame data + headers rounded up */
+ size = (ETH_FRAME_LEN + 8) & ~7;
+
+ /* Stopping point for hardware truncation */
+ thresh = (size - 8) / sizeof(u32);
+
+ sky2->rx_data_size = size;
+
+ /* Fill Rx ring */
+ for (i = 0; i < RX_PENDING; i++) {
+ re = sky2->rx_ring + i;
+
+ re->iob = sky2_rx_alloc(sky2);
+ if (!re->iob)
+ goto nomem;
+
+ sky2_rx_map_iob(hw->pdev, re, sky2->rx_data_size);
+ sky2_rx_submit(sky2, re);
+ }
+
+ /*
+ * The receiver hangs if it receives frames larger than the
+ * packet buffer. As a workaround, truncate oversize frames, but
+ * the register is limited to 9 bits, so if you do frames > 2052
+ * you better get the MTU right!
+ */
+ if (thresh > 0x1ff)
+ sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF);
+ else {
+ sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), thresh);
+ sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON);
+ }
+
+ /* Tell chip about available buffers */
+ sky2_rx_update(sky2, rxq);
+ return 0;
+nomem:
+ sky2_rx_clean(sky2);
+ return -ENOMEM;
+}
+
+/* Free the le and ring buffers */
+static void sky2_free_rings(struct sky2_port *sky2)
+{
+ free_dma(sky2->rx_le, RX_LE_BYTES);
+ free(sky2->rx_ring);
+
+ free_dma(sky2->tx_le, TX_RING_SIZE * sizeof(struct sky2_tx_le));
+ free(sky2->tx_ring);
+
+ sky2->tx_le = NULL;
+ sky2->rx_le = NULL;
+
+ sky2->rx_ring = NULL;
+ sky2->tx_ring = NULL;
+}
+
+/* Bring up network interface. */
+static int sky2_up(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u32 imask, ramsize;
+ int err = -ENOMEM;
+
+ netdev_link_down(dev);
+
+ /* must be power of 2 */
+ sky2->tx_le = malloc_dma(TX_RING_SIZE * sizeof(struct sky2_tx_le), TX_RING_ALIGN);
+ sky2->tx_le_map = virt_to_bus(sky2->tx_le);
+ if (!sky2->tx_le)
+ goto err_out;
+ memset(sky2->tx_le, 0, TX_RING_SIZE * sizeof(struct sky2_tx_le));
+
+ sky2->tx_ring = zalloc(TX_RING_SIZE * sizeof(struct tx_ring_info));
+ if (!sky2->tx_ring)
+ goto err_out;
+
+ tx_init(sky2);
+
+ sky2->rx_le = malloc_dma(RX_LE_BYTES, RX_RING_ALIGN);
+ sky2->rx_le_map = virt_to_bus(sky2->rx_le);
+ if (!sky2->rx_le)
+ goto err_out;
+ memset(sky2->rx_le, 0, RX_LE_BYTES);
+
+ sky2->rx_ring = zalloc(RX_PENDING * sizeof(struct rx_ring_info));
+ if (!sky2->rx_ring)
+ goto err_out;
+
+ sky2_mac_init(hw, port);
+
+ /* Register is number of 4K blocks on internal RAM buffer. */
+ ramsize = sky2_read8(hw, B2_E_0) * 4;
+ if (ramsize > 0) {
+ u32 rxspace;
+
+ hw->flags |= SKY2_HW_RAM_BUFFER;
+ DBG2(PFX "%s: ram buffer %dK\n", dev->name, ramsize);
+ if (ramsize < 16)
+ rxspace = ramsize / 2;
+ else
+ rxspace = 8 + (2*(ramsize - 16))/3;
+
+ sky2_ramset(hw, rxqaddr[port], 0, rxspace);
+ sky2_ramset(hw, txqaddr[port], rxspace, ramsize - rxspace);
+
+ /* Make sure SyncQ is disabled */
+ sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL),
+ RB_RST_SET);
+ }
+
+ sky2_qset(hw, txqaddr[port]);
+
+ /* This is copied from sk98lin 10.0.5.3; no one tells me about erratta's */
+ if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev == CHIP_REV_YU_EX_B0)
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_TEST), F_TX_CHK_AUTO_OFF);
+
+ /* Set almost empty threshold */
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U
+ && hw->chip_rev == CHIP_REV_YU_EC_U_A0)
+ sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), ECU_TXFF_LEV);
+
+ sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
+ TX_RING_SIZE - 1);
+
+ err = sky2_rx_start(sky2);
+ if (err)
+ goto err_out;
+
+ /* Enable interrupts from phy/mac for port */
+ imask = sky2_read32(hw, B0_IMSK);
+ imask |= portirq_msk[port];
+ sky2_write32(hw, B0_IMSK, imask);
+
+ DBGIO(PFX "%s: le bases: st %p [%x], rx %p [%x], tx %p [%x]\n",
+ dev->name, hw->st_le, hw->st_dma, sky2->rx_le, sky2->rx_le_map,
+ sky2->tx_le, sky2->tx_le_map);
+
+ sky2_set_multicast(dev);
+ return 0;
+
+err_out:
+ sky2_free_rings(sky2);
+ return err;
+}
+
+/* Modular subtraction in ring */
+static inline int tx_dist(unsigned tail, unsigned head)
+{
+ return (head - tail) & (TX_RING_SIZE - 1);
+}
+
+/* Number of list elements available for next tx */
+static inline int tx_avail(const struct sky2_port *sky2)
+{
+ return TX_PENDING - tx_dist(sky2->tx_cons, sky2->tx_prod);
+}
+
+
+/*
+ * Put one packet in ring for transmit.
+ * A single packet can generate multiple list elements, and
+ * the number of ring elements will probably be less than the number
+ * of list elements used.
+ */
+static int sky2_xmit_frame(struct net_device *dev, struct io_buffer *iob)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ struct sky2_tx_le *le = NULL;
+ struct tx_ring_info *re;
+ unsigned len;
+ u32 mapping;
+ u8 ctrl;
+
+ if (tx_avail(sky2) < 1)
+ return -EBUSY;
+
+ len = iob_len(iob);
+ mapping = virt_to_bus(iob->data);
+
+ DBGIO(PFX "%s: tx queued, slot %d, len %d\n", dev->name,
+ sky2->tx_prod, len);
+
+ ctrl = 0;
+
+ le = get_tx_le(sky2);
+ le->addr = cpu_to_le32((u32) mapping);
+ le->length = cpu_to_le16(len);
+ le->ctrl = ctrl;
+ le->opcode = (OP_PACKET | HW_OWNER);
+
+ re = tx_le_re(sky2, le);
+ re->iob = iob;
+
+ le->ctrl |= EOP;
+
+ sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod);
+
+ return 0;
+}
+
+/*
+ * Free ring elements from starting at tx_cons until "done"
+ *
+ * NB: the hardware will tell us about partial completion of multi-part
+ * buffers so make sure not to free iob too early.
+ */
+static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
+{
+ struct net_device *dev = sky2->netdev;
+ unsigned idx;
+
+ assert(done < TX_RING_SIZE);
+
+ for (idx = sky2->tx_cons; idx != done;
+ idx = RING_NEXT(idx, TX_RING_SIZE)) {
+ struct sky2_tx_le *le = sky2->tx_le + idx;
+ struct tx_ring_info *re = sky2->tx_ring + idx;
+
+ if (le->ctrl & EOP) {
+ DBGIO(PFX "%s: tx done %d\n", dev->name, idx);
+ netdev_tx_complete(dev, re->iob);
+ }
+ }
+
+ sky2->tx_cons = idx;
+ mb();
+}
+
+/* Cleanup all untransmitted buffers, assume transmitter not running */
+static void sky2_tx_clean(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ sky2_tx_complete(sky2, sky2->tx_prod);
+}
+
+/* Network shutdown */
+static void sky2_down(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 ctrl;
+ u32 imask;
+
+ /* Never really got started! */
+ if (!sky2->tx_le)
+ return;
+
+ DBG2(PFX "%s: disabling interface\n", dev->name);
+
+ /* Disable port IRQ */
+ imask = sky2_read32(hw, B0_IMSK);
+ imask &= ~portirq_msk[port];
+ sky2_write32(hw, B0_IMSK, imask);
+
+ sky2_gmac_reset(hw, port);
+
+ /* Stop transmitter */
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_STOP);
+ sky2_read32(hw, Q_ADDR(txqaddr[port], Q_CSR));
+
+ sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
+ RB_RST_SET | RB_DIS_OP_MD);
+
+ ctrl = gma_read16(hw, port, GM_GP_CTRL);
+ ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA);
+ gma_write16(hw, port, GM_GP_CTRL, ctrl);
+
+ sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+
+ /* Workaround shared GMAC reset */
+ if (!(hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0
+ && port == 0 && hw->dev[1]))
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
+
+ /* Disable Force Sync bit and Enable Alloc bit */
+ sky2_write8(hw, SK_REG(port, TXA_CTRL),
+ TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+
+ /* Stop Interval Timer and Limit Counter of Tx Arbiter */
+ sky2_write32(hw, SK_REG(port, TXA_ITI_INI), 0L);
+ sky2_write32(hw, SK_REG(port, TXA_LIM_INI), 0L);
+
+ /* Reset the PCI FIFO of the async Tx queue */
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR),
+ BMU_RST_SET | BMU_FIFO_RST);
+
+ /* Reset the Tx prefetch units */
+ sky2_write32(hw, Y2_QADDR(txqaddr[port], PREF_UNIT_CTRL),
+ PREF_UNIT_RST_SET);
+
+ sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
+
+ sky2_rx_stop(sky2);
+
+ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
+ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
+
+ sky2_phy_power_down(hw, port);
+
+ /* turn off LED's */
+ sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
+
+ sky2_tx_clean(dev);
+ sky2_rx_clean(sky2);
+
+ sky2_free_rings(sky2);
+
+ return;
+}
+
+static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux)
+{
+ if (hw->flags & SKY2_HW_FIBRE_PHY)
+ return SPEED_1000;
+
+ if (!(hw->flags & SKY2_HW_GIGABIT)) {
+ if (aux & PHY_M_PS_SPEED_100)
+ return SPEED_100;
+ else
+ return SPEED_10;
+ }
+
+ switch (aux & PHY_M_PS_SPEED_MSK) {
+ case PHY_M_PS_SPEED_1000:
+ return SPEED_1000;
+ case PHY_M_PS_SPEED_100:
+ return SPEED_100;
+ default:
+ return SPEED_10;
+ }
+}
+
+static void sky2_link_up(struct sky2_port *sky2)
+{
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 reg;
+ static const char *fc_name[] = {
+ [FC_NONE] = "none",
+ [FC_TX] = "tx",
+ [FC_RX] = "rx",
+ [FC_BOTH] = "both",
+ };
+
+ /* enable Rx/Tx */
+ reg = gma_read16(hw, port, GM_GP_CTRL);
+ reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+
+ netdev_link_up(sky2->netdev);
+
+ /* Turn on link LED */
+ sky2_write8(hw, SK_REG(port, LNK_LED_REG),
+ LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
+
+ DBG(PFX "%s: Link is up at %d Mbps, %s duplex, flow control %s\n",
+ sky2->netdev->name, sky2->speed,
+ sky2->duplex == DUPLEX_FULL ? "full" : "half",
+ fc_name[sky2->flow_status]);
+}
+
+static void sky2_link_down(struct sky2_port *sky2)
+{
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 reg;
+
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
+
+ reg = gma_read16(hw, port, GM_GP_CTRL);
+ reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+
+ netdev_link_down(sky2->netdev);
+
+ /* Turn on link LED */
+ sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
+
+ DBG(PFX "%s: Link is down.\n", sky2->netdev->name);
+
+ sky2_phy_init(hw, port);
+}
+
+static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
+{
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 advert, lpa;
+
+ advert = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV);
+ lpa = gm_phy_read(hw, port, PHY_MARV_AUNE_LP);
+ if (lpa & PHY_M_AN_RF) {
+ DBG(PFX "%s: remote fault\n", sky2->netdev->name);
+ return -1;
+ }
+
+ if (!(aux & PHY_M_PS_SPDUP_RES)) {
+ DBG(PFX "%s: speed/duplex mismatch\n", sky2->netdev->name);
+ return -1;
+ }
+
+ sky2->speed = sky2_phy_speed(hw, aux);
+ sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
+
+ /* Since the pause result bits seem to in different positions on
+ * different chips. look at registers.
+ */
+
+ sky2->flow_status = FC_NONE;
+ if (advert & ADVERTISE_PAUSE_CAP) {
+ if (lpa & LPA_PAUSE_CAP)
+ sky2->flow_status = FC_BOTH;
+ else if (advert & ADVERTISE_PAUSE_ASYM)
+ sky2->flow_status = FC_RX;
+ } else if (advert & ADVERTISE_PAUSE_ASYM) {
+ if ((lpa & LPA_PAUSE_CAP) && (lpa & LPA_PAUSE_ASYM))
+ sky2->flow_status = FC_TX;
+ }
+
+ if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000
+ && !(hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX))
+ sky2->flow_status = FC_NONE;
+
+ if (sky2->flow_status & FC_TX)
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
+ else
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+
+ return 0;
+}
+
+/* Interrupt from PHY */
+static void sky2_phy_intr(struct sky2_hw *hw, unsigned port)
+{
+ struct net_device *dev = hw->dev[port];
+ struct sky2_port *sky2 = netdev_priv(dev);
+ u16 istatus, phystat;
+
+ istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT);
+ phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT);
+
+ DBGIO(PFX "%s: phy interrupt status 0x%x 0x%x\n",
+ sky2->netdev->name, istatus, phystat);
+
+ if (sky2->autoneg == AUTONEG_ENABLE && (istatus & PHY_M_IS_AN_COMPL)) {
+ if (sky2_autoneg_done(sky2, phystat) == 0)
+ sky2_link_up(sky2);
+ return;
+ }
+
+ if (istatus & PHY_M_IS_LSP_CHANGE)
+ sky2->speed = sky2_phy_speed(hw, phystat);
+
+ if (istatus & PHY_M_IS_DUP_CHANGE)
+ sky2->duplex =
+ (phystat & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
+
+ if (istatus & PHY_M_IS_LST_CHANGE) {
+ if (phystat & PHY_M_PS_LINK_UP)
+ sky2_link_up(sky2);
+ else
+ sky2_link_down(sky2);
+ }
+}
+
+/* Normal packet - take iob from ring element and put in a new one */
+static struct io_buffer *receive_new(struct sky2_port *sky2,
+ struct rx_ring_info *re,
+ unsigned int length)
+{
+ struct io_buffer *iob, *niob;
+ unsigned hdr_space = sky2->rx_data_size;
+
+ /* Don't be tricky about reusing pages (yet) */
+ niob = sky2_rx_alloc(sky2);
+ if (!niob)
+ return NULL;
+
+ iob = re->iob;
+
+ re->iob = niob;
+ sky2_rx_map_iob(sky2->hw->pdev, re, hdr_space);
+
+ iob_put(iob, length);
+ return iob;
+}
+
+/*
+ * Receive one packet.
+ * For larger packets, get new buffer.
+ */
+static struct io_buffer *sky2_receive(struct net_device *dev,
+ u16 length, u32 status)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct rx_ring_info *re = sky2->rx_ring + sky2->rx_next;
+ struct io_buffer *iob = NULL;
+ u16 count = (status & GMR_FS_LEN) >> 16;
+
+ DBGIO(PFX "%s: rx slot %d status 0x%x len %d\n",
+ dev->name, sky2->rx_next, status, length);
+
+ sky2->rx_next = (sky2->rx_next + 1) % RX_PENDING;
+
+ /* This chip has hardware problems that generates bogus status.
+ * So do only marginal checking and expect higher level protocols
+ * to handle crap frames.
+ */
+ if (sky2->hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0 &&
+ length == count)
+ goto okay;
+
+ if (status & GMR_FS_ANY_ERR)
+ goto error;
+
+ if (!(status & GMR_FS_RX_OK))
+ goto resubmit;
+
+ /* if length reported by DMA does not match PHY, packet was truncated */
+ if (length != count)
+ goto len_error;
+
+okay:
+ iob = receive_new(sky2, re, length);
+resubmit:
+ sky2_rx_submit(sky2, re);
+
+ return iob;
+
+len_error:
+ /* Truncation of overlength packets
+ causes PHY length to not match MAC length */
+ DBG2(PFX "%s: rx length error: status %#x length %d\n",
+ dev->name, status, length);
+
+ /* Pass NULL as iob because we want to keep our iob in the
+ ring for the next packet. */
+ netdev_rx_err(dev, NULL, -EINVAL);
+ goto resubmit;
+
+error:
+ if (status & GMR_FS_RX_FF_OV) {
+ DBG2(PFX "%s: FIFO overflow error\n", dev->name);
+ netdev_rx_err(dev, NULL, -EBUSY);
+ goto resubmit;
+ }
+
+ DBG2(PFX "%s: rx error, status 0x%x length %d\n",
+ dev->name, status, length);
+ netdev_rx_err(dev, NULL, -EIO);
+
+ goto resubmit;
+}
+
+/* Transmit complete */
+static inline void sky2_tx_done(struct net_device *dev, u16 last)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ sky2_tx_complete(sky2, last);
+}
+
+/* Process status response ring */
+static void sky2_status_intr(struct sky2_hw *hw, u16 idx)
+{
+ unsigned rx[2] = { 0, 0 };
+
+ rmb();
+ do {
+ struct sky2_status_le *le = hw->st_le + hw->st_idx;
+ unsigned port;
+ struct net_device *dev;
+ struct io_buffer *iob;
+ u32 status;
+ u16 length;
+ u8 opcode = le->opcode;
+
+ if (!(opcode & HW_OWNER))
+ break;
+
+ port = le->css & CSS_LINK_BIT;
+ dev = hw->dev[port];
+ length = le16_to_cpu(le->length);
+ status = le32_to_cpu(le->status);
+
+ hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE);
+
+ le->opcode = 0;
+ switch (opcode & ~HW_OWNER) {
+ case OP_RXSTAT:
+ ++rx[port];
+ iob = sky2_receive(dev, length, status);
+ if (!iob) {
+ netdev_rx_err(dev, NULL, -ENOMEM);
+ break;
+ }
+
+ netdev_rx(dev, iob);
+ break;
+
+ case OP_RXCHKS:
+ DBG2(PFX "status OP_RXCHKS but checksum offloading disabled\n");
+ break;
+
+ case OP_TXINDEXLE:
+ /* TX index reports status for both ports */
+ assert(TX_RING_SIZE <= 0x1000);
+ sky2_tx_done(hw->dev[0], status & 0xfff);
+ if (hw->dev[1])
+ sky2_tx_done(hw->dev[1],
+ ((status >> 24) & 0xff)
+ | (u16)(length & 0xf) << 8);
+ break;
+
+ default:
+ DBG(PFX "unknown status opcode 0x%x\n", opcode);
+ }
+ } while (hw->st_idx != idx);
+
+ /* Fully processed status ring so clear irq */
+ sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+
+ if (rx[0])
+ sky2_rx_update(netdev_priv(hw->dev[0]), Q_R1);
+
+ if (rx[1])
+ sky2_rx_update(netdev_priv(hw->dev[1]), Q_R2);
+}
+
+static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status)
+{
+ struct net_device *dev = hw->dev[port];
+
+ DBGIO(PFX "%s: hw error interrupt status 0x%x\n", dev->name, status);
+
+ if (status & Y2_IS_PAR_RD1) {
+ DBG(PFX "%s: ram data read parity error\n", dev->name);
+ /* Clear IRQ */
+ sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_RD_PERR);
+ }
+
+ if (status & Y2_IS_PAR_WR1) {
+ DBG(PFX "%s: ram data write parity error\n", dev->name);
+ sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_WR_PERR);
+ }
+
+ if (status & Y2_IS_PAR_MAC1) {
+ DBG(PFX "%s: MAC parity error\n", dev->name);
+ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_PE);
+ }
+
+ if (status & Y2_IS_PAR_RX1) {
+ DBG(PFX "%s: RX parity error\n", dev->name);
+ sky2_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), BMU_CLR_IRQ_PAR);
+ }
+
+ if (status & Y2_IS_TCP_TXA1) {
+ DBG(PFX "%s: TCP segmentation error\n", dev->name);
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_CLR_IRQ_TCP);
+ }
+}
+
+static void sky2_hw_intr(struct sky2_hw *hw)
+{
+ u32 status = sky2_read32(hw, B0_HWE_ISRC);
+ u32 hwmsk = sky2_read32(hw, B0_HWE_IMSK);
+
+ status &= hwmsk;
+
+ if (status & Y2_IS_TIST_OV)
+ sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
+
+ if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) {
+ u16 pci_err;
+
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ pci_err = sky2_pci_read16(hw, PCI_STATUS);
+ DBG(PFX "PCI hardware error (0x%x)\n", pci_err);
+
+ sky2_pci_write16(hw, PCI_STATUS,
+ pci_err | PCI_STATUS_ERROR_BITS);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+ }
+
+ if (status & Y2_IS_PCI_EXP) {
+ /* PCI-Express uncorrectable Error occurred */
+ u32 err;
+
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
+ sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
+ 0xfffffffful);
+ DBG(PFX "PCI-Express error (0x%x)\n", err);
+
+ sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+ }
+
+ if (status & Y2_HWE_L1_MASK)
+ sky2_hw_error(hw, 0, status);
+ status >>= 8;
+ if (status & Y2_HWE_L1_MASK)
+ sky2_hw_error(hw, 1, status);
+}
+
+static void sky2_mac_intr(struct sky2_hw *hw, unsigned port)
+{
+ struct net_device *dev = hw->dev[port];
+ u8 status = sky2_read8(hw, SK_REG(port, GMAC_IRQ_SRC));
+
+ DBGIO(PFX "%s: mac interrupt status 0x%x\n", dev->name, status);
+
+ if (status & GM_IS_RX_CO_OV)
+ gma_read16(hw, port, GM_RX_IRQ_SRC);
+
+ if (status & GM_IS_TX_CO_OV)
+ gma_read16(hw, port, GM_TX_IRQ_SRC);
+
+ if (status & GM_IS_RX_FF_OR) {
+ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO);
+ }
+
+ if (status & GM_IS_TX_FF_UR) {
+ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU);
+ }
+}
+
+/* This should never happen it is a bug. */
+static void sky2_le_error(struct sky2_hw *hw, unsigned port,
+ u16 q, unsigned ring_size __unused)
+{
+ struct net_device *dev = hw->dev[port];
+ struct sky2_port *sky2 = netdev_priv(dev);
+ int idx;
+ const u64 *le = (q == Q_R1 || q == Q_R2)
+ ? (u64 *) sky2->rx_le : (u64 *) sky2->tx_le;
+
+ idx = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX));
+ DBG(PFX "%s: descriptor error q=%#x get=%d [%llx] last=%d put=%d should be %d\n",
+ dev->name, (unsigned) q, idx, (unsigned long long) le[idx],
+ (int) sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_LAST_IDX)),
+ (int) sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX)),
+ le == (u64 *)sky2->rx_le? sky2->rx_put : sky2->tx_prod);
+
+ sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK);
+}
+
+/* Hardware/software error handling */
+static void sky2_err_intr(struct sky2_hw *hw, u32 status)
+{
+ DBG(PFX "error interrupt status=%#x\n", status);
+
+ if (status & Y2_IS_HW_ERR)
+ sky2_hw_intr(hw);
+
+ if (status & Y2_IS_IRQ_MAC1)
+ sky2_mac_intr(hw, 0);
+
+ if (status & Y2_IS_IRQ_MAC2)
+ sky2_mac_intr(hw, 1);
+
+ if (status & Y2_IS_CHK_RX1)
+ sky2_le_error(hw, 0, Q_R1, RX_LE_SIZE);
+
+ if (status & Y2_IS_CHK_RX2)
+ sky2_le_error(hw, 1, Q_R2, RX_LE_SIZE);
+
+ if (status & Y2_IS_CHK_TXA1)
+ sky2_le_error(hw, 0, Q_XA1, TX_RING_SIZE);
+
+ if (status & Y2_IS_CHK_TXA2)
+ sky2_le_error(hw, 1, Q_XA2, TX_RING_SIZE);
+}
+
+static void sky2_poll(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
+ u16 idx;
+
+ if (status & Y2_IS_ERROR)
+ sky2_err_intr(hw, status);
+
+ if (status & Y2_IS_IRQ_PHY1)
+ sky2_phy_intr(hw, 0);
+
+ if (status & Y2_IS_IRQ_PHY2)
+ sky2_phy_intr(hw, 1);
+
+ while ((idx = sky2_read16(hw, STAT_PUT_IDX)) != hw->st_idx) {
+ sky2_status_intr(hw, idx);
+ }
+
+ /* Bug/Errata workaround?
+ * Need to kick the TX irq moderation timer.
+ */
+ if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
+ }
+ sky2_read32(hw, B0_Y2_SP_LISR);
+}
+
+/* Chip internal frequency for clock calculations */
+static u32 sky2_mhz(const struct sky2_hw *hw)
+{
+ switch (hw->chip_id) {
+ case CHIP_ID_YUKON_EC:
+ case CHIP_ID_YUKON_EC_U:
+ case CHIP_ID_YUKON_EX:
+ case CHIP_ID_YUKON_SUPR:
+ case CHIP_ID_YUKON_UL_2:
+ return 125;
+
+ case CHIP_ID_YUKON_FE:
+ return 100;
+
+ case CHIP_ID_YUKON_FE_P:
+ return 50;
+
+ case CHIP_ID_YUKON_XL:
+ return 156;
+
+ default:
+ DBG(PFX "unknown chip ID!\n");
+ return 100; /* bogus */
+ }
+}
+
+static inline u32 sky2_us2clk(const struct sky2_hw *hw, u32 us)
+{
+ return sky2_mhz(hw) * us;
+}
+
+static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
+{
+ return clk / sky2_mhz(hw);
+}
+
+static int sky2_init(struct sky2_hw *hw)
+{
+ u8 t8;
+
+ /* Enable all clocks and check for bad PCI access */
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+
+ sky2_write8(hw, B0_CTST, CS_RST_CLR);
+
+ hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
+ hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
+
+ switch(hw->chip_id) {
+ case CHIP_ID_YUKON_XL:
+ hw->flags = SKY2_HW_GIGABIT | SKY2_HW_NEWER_PHY;
+ break;
+
+ case CHIP_ID_YUKON_EC_U:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_ADV_POWER_CTL;
+ break;
+
+ case CHIP_ID_YUKON_EX:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_NEW_LE
+ | SKY2_HW_ADV_POWER_CTL;
+ break;
+
+ case CHIP_ID_YUKON_EC:
+ /* This rev is really old, and requires untested workarounds */
+ if (hw->chip_rev == CHIP_REV_YU_EC_A1) {
+ DBG(PFX "unsupported revision Yukon-EC rev A1\n");
+ return -EOPNOTSUPP;
+ }
+ hw->flags = SKY2_HW_GIGABIT;
+ break;
+
+ case CHIP_ID_YUKON_FE:
+ break;
+
+ case CHIP_ID_YUKON_FE_P:
+ hw->flags = SKY2_HW_NEWER_PHY
+ | SKY2_HW_NEW_LE
+ | SKY2_HW_AUTO_TX_SUM
+ | SKY2_HW_ADV_POWER_CTL;
+ break;
+
+ case CHIP_ID_YUKON_SUPR:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_NEW_LE
+ | SKY2_HW_AUTO_TX_SUM
+ | SKY2_HW_ADV_POWER_CTL;
+ break;
+
+ case CHIP_ID_YUKON_UL_2:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_ADV_POWER_CTL;
+ break;
+
+ default:
+ DBG(PFX "unsupported chip type 0x%x\n", hw->chip_id);
+ return -EOPNOTSUPP;
+ }
+
+ hw->pmd_type = sky2_read8(hw, B2_PMD_TYP);
+ if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P')
+ hw->flags |= SKY2_HW_FIBRE_PHY;
+
+ hw->ports = 1;
+ t8 = sky2_read8(hw, B2_Y2_HW_RES);
+ if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) {
+ if (!(sky2_read8(hw, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC))
+ ++hw->ports;
+ }
+
+ return 0;
+}
+
+static void sky2_reset(struct sky2_hw *hw)
+{
+ u16 status;
+ int i, cap;
+ u32 hwe_mask = Y2_HWE_ALL_MASK;
+
+ /* disable ASF */
+ if (hw->chip_id == CHIP_ID_YUKON_EX) {
+ status = sky2_read16(hw, HCU_CCSR);
+ status &= ~(HCU_CCSR_AHB_RST | HCU_CCSR_CPU_RST_MODE |
+ HCU_CCSR_UC_STATE_MSK);
+ sky2_write16(hw, HCU_CCSR, status);
+ } else
+ sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
+ sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE);
+
+ /* do a SW reset */
+ sky2_write8(hw, B0_CTST, CS_RST_SET);
+ sky2_write8(hw, B0_CTST, CS_RST_CLR);
+
+ /* allow writes to PCI config */
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+
+ /* clear PCI errors, if any */
+ status = sky2_pci_read16(hw, PCI_STATUS);
+ status |= PCI_STATUS_ERROR_BITS;
+ sky2_pci_write16(hw, PCI_STATUS, status);
+
+ sky2_write8(hw, B0_CTST, CS_MRST_CLR);
+
+ cap = pci_find_capability(hw->pdev, PCI_CAP_ID_EXP);
+ if (cap) {
+ sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
+ 0xfffffffful);
+
+ /* If an error bit is stuck on ignore it */
+ if (sky2_read32(hw, B0_HWE_ISRC) & Y2_IS_PCI_EXP)
+ DBG(PFX "ignoring stuck error report bit\n");
+ else
+ hwe_mask |= Y2_IS_PCI_EXP;
+ }
+
+ sky2_power_on(hw);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+ for (i = 0; i < hw->ports; i++) {
+ sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
+ sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EX ||
+ hw->chip_id == CHIP_ID_YUKON_SUPR)
+ sky2_write16(hw, SK_REG(i, GMAC_CTRL),
+ GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON
+ | GMC_BYP_RETR_ON);
+ }
+
+ /* Clear I2C IRQ noise */
+ sky2_write32(hw, B2_I2C_IRQ, 1);
+
+ /* turn off hardware timer (unused) */
+ sky2_write8(hw, B2_TI_CTRL, TIM_STOP);
+ sky2_write8(hw, B2_TI_CTRL, TIM_CLR_IRQ);
+
+ sky2_write8(hw, B0_Y2LED, LED_STAT_ON);
+
+ /* Turn off descriptor polling */
+ sky2_write32(hw, B28_DPT_CTRL, DPT_STOP);
+
+ /* Turn off receive timestamp */
+ sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_STOP);
+ sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
+
+ /* enable the Tx Arbiters */
+ for (i = 0; i < hw->ports; i++)
+ sky2_write8(hw, SK_REG(i, TXA_CTRL), TXA_ENA_ARB);
+
+ /* Initialize ram interface */
+ for (i = 0; i < hw->ports; i++) {
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_CTRL), RI_RST_CLR);
+
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_R1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XA1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XS1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_R1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XA1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_R2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XA2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XS2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_R2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XA2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS2), SK_RI_TO_53);
+ }
+
+ sky2_write32(hw, B0_HWE_IMSK, hwe_mask);
+
+ for (i = 0; i < hw->ports; i++)
+ sky2_gmac_reset(hw, i);
+
+ memset(hw->st_le, 0, STATUS_LE_BYTES);
+ hw->st_idx = 0;
+
+ sky2_write32(hw, STAT_CTRL, SC_STAT_RST_SET);
+ sky2_write32(hw, STAT_CTRL, SC_STAT_RST_CLR);
+
+ sky2_write32(hw, STAT_LIST_ADDR_LO, hw->st_dma);
+ sky2_write32(hw, STAT_LIST_ADDR_HI, (u64) hw->st_dma >> 32);
+
+ /* Set the list last index */
+ sky2_write16(hw, STAT_LAST_IDX, STATUS_RING_SIZE - 1);
+
+ sky2_write16(hw, STAT_TX_IDX_TH, 10);
+ sky2_write8(hw, STAT_FIFO_WM, 16);
+
+ /* set Status-FIFO ISR watermark */
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0)
+ sky2_write8(hw, STAT_FIFO_ISR_WM, 4);
+ else
+ sky2_write8(hw, STAT_FIFO_ISR_WM, 16);
+
+ sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000));
+ sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 20));
+ sky2_write32(hw, STAT_LEV_TIMER_INI, sky2_us2clk(hw, 100));
+
+ /* enable status unit */
+ sky2_write32(hw, STAT_CTRL, SC_STAT_OP_ON);
+
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
+ sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START);
+ sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
+}
+
+static u32 sky2_supported_modes(const struct sky2_hw *hw)
+{
+ if (sky2_is_copper(hw)) {
+ u32 modes = SUPPORTED_10baseT_Half
+ | SUPPORTED_10baseT_Full
+ | SUPPORTED_100baseT_Half
+ | SUPPORTED_100baseT_Full
+ | SUPPORTED_Autoneg | SUPPORTED_TP;
+
+ if (hw->flags & SKY2_HW_GIGABIT)
+ modes |= SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full;
+ return modes;
+ } else
+ return SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full
+ | SUPPORTED_Autoneg
+ | SUPPORTED_FIBRE;
+}
+
+static void sky2_set_multicast(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 reg;
+ u8 filter[8];
+
+ reg = gma_read16(hw, port, GM_RX_CTRL);
+ reg |= GM_RXCR_UCF_ENA;
+
+ memset(filter, 0xff, sizeof(filter));
+
+ gma_write16(hw, port, GM_MC_ADDR_H1,
+ (u16) filter[0] | ((u16) filter[1] << 8));
+ gma_write16(hw, port, GM_MC_ADDR_H2,
+ (u16) filter[2] | ((u16) filter[3] << 8));
+ gma_write16(hw, port, GM_MC_ADDR_H3,
+ (u16) filter[4] | ((u16) filter[5] << 8));
+ gma_write16(hw, port, GM_MC_ADDR_H4,
+ (u16) filter[6] | ((u16) filter[7] << 8));
+
+ gma_write16(hw, port, GM_RX_CTRL, reg);
+}
+
+/* Initialize network device */
+static struct net_device *sky2_init_netdev(struct sky2_hw *hw,
+ unsigned port)
+{
+ struct sky2_port *sky2;
+ struct net_device *dev = alloc_etherdev(sizeof(*sky2));
+
+ if (!dev) {
+ DBG(PFX "etherdev alloc failed\n");
+ return NULL;
+ }
+
+ dev->dev = &hw->pdev->dev;
+
+ sky2 = netdev_priv(dev);
+ sky2->netdev = dev;
+ sky2->hw = hw;
+
+ /* Auto speed and flow control */
+ sky2->autoneg = AUTONEG_ENABLE;
+ sky2->flow_mode = FC_BOTH;
+
+ sky2->duplex = -1;
+ sky2->speed = -1;
+ sky2->advertising = sky2_supported_modes(hw);
+
+ hw->dev[port] = dev;
+
+ sky2->port = port;
+
+ /* read the mac address */
+ memcpy(dev->hw_addr, (void *)(hw->regs + B2_MAC_1 + port * 8), ETH_ALEN);
+
+ return dev;
+}
+
+static void sky2_show_addr(struct net_device *dev)
+{
+ DBG2(PFX "%s: addr %s\n", dev->name, netdev_addr(dev));
+}
+
+#if DBGLVL_MAX
+/* This driver supports yukon2 chipset only */
+static const char *sky2_name(u8 chipid, char *buf, int sz)
+{
+ const char *name[] = {
+ "XL", /* 0xb3 */
+ "EC Ultra", /* 0xb4 */
+ "Extreme", /* 0xb5 */
+ "EC", /* 0xb6 */
+ "FE", /* 0xb7 */
+ "FE+", /* 0xb8 */
+ "Supreme", /* 0xb9 */
+ "UL 2", /* 0xba */
+ };
+
+ if (chipid >= CHIP_ID_YUKON_XL && chipid <= CHIP_ID_YUKON_UL_2)
+ strncpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz);
+ else
+ snprintf(buf, sz, "(chip %#x)", chipid);
+ return buf;
+}
+#endif
+
+static void sky2_net_irq(struct net_device *dev, int enable)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+
+ u32 imask = sky2_read32(hw, B0_IMSK);
+ if (enable)
+ imask |= portirq_msk[sky2->port];
+ else
+ imask &= ~portirq_msk[sky2->port];
+ sky2_write32(hw, B0_IMSK, imask);
+}
+
+static struct net_device_operations sky2_operations = {
+ .open = sky2_up,
+ .close = sky2_down,
+ .transmit = sky2_xmit_frame,
+ .poll = sky2_poll,
+ .irq = sky2_net_irq
+};
+
+static int sky2_probe(struct pci_device *pdev)
+{
+ struct net_device *dev;
+ struct sky2_hw *hw;
+ int err;
+ char buf1[16] __unused; /* only for debugging */
+
+ adjust_pci_device(pdev);
+
+ err = -ENOMEM;
+ hw = zalloc(sizeof(*hw));
+ if (!hw) {
+ DBG(PFX "cannot allocate hardware struct\n");
+ goto err_out;
+ }
+
+ hw->pdev = pdev;
+
+ hw->regs = (unsigned long)ioremap(pci_bar_start(pdev, PCI_BASE_ADDRESS_0), 0x4000);
+ if (!hw->regs) {
+ DBG(PFX "cannot map device registers\n");
+ goto err_out_free_hw;
+ }
+
+ /* ring for status responses */
+ hw->st_le = malloc_dma(STATUS_LE_BYTES, STATUS_RING_ALIGN);
+ if (!hw->st_le)
+ goto err_out_iounmap;
+ hw->st_dma = virt_to_bus(hw->st_le);
+ memset(hw->st_le, 0, STATUS_LE_BYTES);
+
+ err = sky2_init(hw);
+ if (err)
+ goto err_out_iounmap;
+
+#if DBGLVL_MAX
+ DBG2(PFX "Yukon-2 %s chip revision %d\n",
+ sky2_name(hw->chip_id, buf1, sizeof(buf1)), hw->chip_rev);
+#endif
+
+ sky2_reset(hw);
+
+ dev = sky2_init_netdev(hw, 0);
+ if (!dev) {
+ err = -ENOMEM;
+ goto err_out_free_pci;
+ }
+
+ netdev_init(dev, &sky2_operations);
+
+ err = register_netdev(dev);
+ if (err) {
+ DBG(PFX "cannot register net device\n");
+ goto err_out_free_netdev;
+ }
+
+ sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+
+ sky2_show_addr(dev);
+
+ if (hw->ports > 1) {
+ struct net_device *dev1;
+
+ dev1 = sky2_init_netdev(hw, 1);
+ if (!dev1)
+ DBG(PFX "allocation for second device failed\n");
+ else if ((err = register_netdev(dev1))) {
+ DBG(PFX "register of second port failed (%d)\n", err);
+ hw->dev[1] = NULL;
+ netdev_nullify(dev1);
+ netdev_put(dev1);
+ } else
+ sky2_show_addr(dev1);
+ }
+
+ pci_set_drvdata(pdev, dev);
+
+ return 0;
+
+err_out_free_netdev:
+ netdev_nullify(dev);
+ netdev_put(dev);
+err_out_free_pci:
+ sky2_write8(hw, B0_CTST, CS_RST_SET);
+ free_dma(hw->st_le, STATUS_LE_BYTES);
+err_out_iounmap:
+ iounmap((void *)hw->regs);
+err_out_free_hw:
+ free(hw);
+err_out:
+ pci_set_drvdata(pdev, NULL);
+ return err;
+}
+
+static void sky2_remove(struct pci_device *pdev)
+{
+ struct sky2_hw *hw = pci_get_drvdata(pdev);
+ int i;
+
+ if (!hw)
+ return;
+
+ for (i = hw->ports-1; i >= 0; --i)
+ unregister_netdev(hw->dev[i]);
+
+ sky2_write32(hw, B0_IMSK, 0);
+
+ sky2_power_aux(hw);
+
+ sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
+ sky2_write8(hw, B0_CTST, CS_RST_SET);
+ sky2_read8(hw, B0_CTST);
+
+ free_dma(hw->st_le, STATUS_LE_BYTES);
+
+ for (i = hw->ports-1; i >= 0; --i) {
+ netdev_nullify(hw->dev[i]);
+ netdev_put(hw->dev[i]);
+ }
+
+ iounmap((void *)hw->regs);
+ free(hw);
+
+ pci_set_drvdata(pdev, NULL);
+}
+
+struct pci_driver sky2_driver __pci_driver = {
+ .ids = sky2_id_table,
+ .id_count = (sizeof (sky2_id_table) / sizeof (sky2_id_table[0])),
+ .probe = sky2_probe,
+ .remove = sky2_remove
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/sky2.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/sky2.h
new file mode 100644
index 00000000..3e86b1de
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/sky2.h
@@ -0,0 +1,2176 @@
+/*
+ * Definitions for the new Marvell Yukon 2 driver.
+ */
+#ifndef _SKY2_H
+#define _SKY2_H
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/* Added for iPXE ------------------ */
+
+/* These were defined in Linux ethtool.h. Their values are arbitrary;
+ they aid only in bookkeeping for the driver. */
+
+#define AUTONEG_DISABLE 0x00
+#define AUTONEG_ENABLE 0x01
+
+#define DUPLEX_HALF 0x00
+#define DUPLEX_FULL 0x01
+
+#define SPEED_10 10
+#define SPEED_100 100
+#define SPEED_1000 1000
+
+#define ADVERTISED_10baseT_Half (1 << 0)
+#define ADVERTISED_10baseT_Full (1 << 1)
+#define ADVERTISED_100baseT_Half (1 << 2)
+#define ADVERTISED_100baseT_Full (1 << 3)
+#define ADVERTISED_1000baseT_Half (1 << 4)
+#define ADVERTISED_1000baseT_Full (1 << 5)
+
+#define SUPPORTED_10baseT_Half (1 << 0)
+#define SUPPORTED_10baseT_Full (1 << 1)
+#define SUPPORTED_100baseT_Half (1 << 2)
+#define SUPPORTED_100baseT_Full (1 << 3)
+#define SUPPORTED_1000baseT_Half (1 << 4)
+#define SUPPORTED_1000baseT_Full (1 << 5)
+#define SUPPORTED_Autoneg (1 << 6)
+#define SUPPORTED_TP (1 << 7)
+#define SUPPORTED_FIBRE (1 << 10)
+
+/* ----------------------------------- */
+
+/* PCI config registers */
+enum {
+ PCI_DEV_REG1 = 0x40,
+ PCI_DEV_REG2 = 0x44,
+ PCI_DEV_STATUS = 0x7c,
+ PCI_DEV_REG3 = 0x80,
+ PCI_DEV_REG4 = 0x84,
+ PCI_DEV_REG5 = 0x88,
+ PCI_CFG_REG_0 = 0x90,
+ PCI_CFG_REG_1 = 0x94,
+};
+
+/* Yukon-2 */
+enum pci_dev_reg_1 {
+ PCI_Y2_PIG_ENA = 1<<31, /* Enable Plug-in-Go (YUKON-2) */
+ PCI_Y2_DLL_DIS = 1<<30, /* Disable PCI DLL (YUKON-2) */
+ PCI_SW_PWR_ON_RST= 1<<30, /* SW Power on Reset (Yukon-EX) */
+ PCI_Y2_PHY2_COMA = 1<<29, /* Set PHY 2 to Coma Mode (YUKON-2) */
+ PCI_Y2_PHY1_COMA = 1<<28, /* Set PHY 1 to Coma Mode (YUKON-2) */
+ PCI_Y2_PHY2_POWD = 1<<27, /* Set PHY 2 to Power Down (YUKON-2) */
+ PCI_Y2_PHY1_POWD = 1<<26, /* Set PHY 1 to Power Down (YUKON-2) */
+ PCI_Y2_PME_LEGACY= 1<<15, /* PCI Express legacy power management mode */
+
+ PCI_PHY_LNK_TIM_MSK= 3L<<8,/* Bit 9.. 8: GPHY Link Trigger Timer */
+ PCI_ENA_L1_EVENT = 1<<7, /* Enable PEX L1 Event */
+ PCI_ENA_GPHY_LNK = 1<<6, /* Enable PEX L1 on GPHY Link down */
+ PCI_FORCE_PEX_L1 = 1<<5, /* Force to PEX L1 */
+};
+
+enum pci_dev_reg_2 {
+ PCI_VPD_WR_THR = 0xffL<<24, /* Bit 31..24: VPD Write Threshold */
+ PCI_DEV_SEL = 0x7fL<<17, /* Bit 23..17: EEPROM Device Select */
+ PCI_VPD_ROM_SZ = 7L<<14, /* Bit 16..14: VPD ROM Size */
+
+ PCI_PATCH_DIR = 0xfL<<8, /* Bit 11.. 8: Ext Patches dir 3..0 */
+ PCI_EXT_PATCHS = 0xfL<<4, /* Bit 7.. 4: Extended Patches 3..0 */
+ PCI_EN_DUMMY_RD = 1<<3, /* Enable Dummy Read */
+ PCI_REV_DESC = 1<<2, /* Reverse Desc. Bytes */
+
+ PCI_USEDATA64 = 1<<0, /* Use 64Bit Data bus ext */
+};
+
+/* PCI_OUR_REG_4 32 bit Our Register 4 (Yukon-ECU only) */
+enum pci_dev_reg_4 {
+ /* (Link Training & Status State Machine) */
+ P_PEX_LTSSM_STAT_MSK = 0x7fL<<25, /* Bit 31..25: PEX LTSSM Mask */
+#define P_PEX_LTSSM_STAT(x) ((x << 25) & P_PEX_LTSSM_STAT_MSK)
+ P_PEX_LTSSM_L1_STAT = 0x34,
+ P_PEX_LTSSM_DET_STAT = 0x01,
+ P_TIMER_VALUE_MSK = 0xffL<<16, /* Bit 23..16: Timer Value Mask */
+ /* (Active State Power Management) */
+ P_FORCE_ASPM_REQUEST = 1<<15, /* Force ASPM Request (A1 only) */
+ P_ASPM_GPHY_LINK_DOWN = 1<<14, /* GPHY Link Down (A1 only) */
+ P_ASPM_INT_FIFO_EMPTY = 1<<13, /* Internal FIFO Empty (A1 only) */
+ P_ASPM_CLKRUN_REQUEST = 1<<12, /* CLKRUN Request (A1 only) */
+
+ P_ASPM_FORCE_CLKREQ_ENA = 1<<4, /* Force CLKREQ Enable (A1b only) */
+ P_ASPM_CLKREQ_PAD_CTL = 1<<3, /* CLKREQ PAD Control (A1 only) */
+ P_ASPM_A1_MODE_SELECT = 1<<2, /* A1 Mode Select (A1 only) */
+ P_CLK_GATE_PEX_UNIT_ENA = 1<<1, /* Enable Gate PEX Unit Clock */
+ P_CLK_GATE_ROOT_COR_ENA = 1<<0, /* Enable Gate Root Core Clock */
+ P_ASPM_CONTROL_MSK = P_FORCE_ASPM_REQUEST | P_ASPM_GPHY_LINK_DOWN
+ | P_ASPM_CLKRUN_REQUEST | P_ASPM_INT_FIFO_EMPTY,
+};
+
+/* PCI_OUR_REG_5 32 bit Our Register 5 (Yukon-ECU only) */
+enum pci_dev_reg_5 {
+ /* Bit 31..27: for A3 & later */
+ P_CTL_DIV_CORE_CLK_ENA = 1<<31, /* Divide Core Clock Enable */
+ P_CTL_SRESET_VMAIN_AV = 1<<30, /* Soft Reset for Vmain_av De-Glitch */
+ P_CTL_BYPASS_VMAIN_AV = 1<<29, /* Bypass En. for Vmain_av De-Glitch */
+ P_CTL_TIM_VMAIN_AV_MSK = 3<<27, /* Bit 28..27: Timer Vmain_av Mask */
+ /* Bit 26..16: Release Clock on Event */
+ P_REL_PCIE_RST_DE_ASS = 1<<26, /* PCIe Reset De-Asserted */
+ P_REL_GPHY_REC_PACKET = 1<<25, /* GPHY Received Packet */
+ P_REL_INT_FIFO_N_EMPTY = 1<<24, /* Internal FIFO Not Empty */
+ P_REL_MAIN_PWR_AVAIL = 1<<23, /* Main Power Available */
+ P_REL_CLKRUN_REQ_REL = 1<<22, /* CLKRUN Request Release */
+ P_REL_PCIE_RESET_ASS = 1<<21, /* PCIe Reset Asserted */
+ P_REL_PME_ASSERTED = 1<<20, /* PME Asserted */
+ P_REL_PCIE_EXIT_L1_ST = 1<<19, /* PCIe Exit L1 State */
+ P_REL_LOADER_NOT_FIN = 1<<18, /* EPROM Loader Not Finished */
+ P_REL_PCIE_RX_EX_IDLE = 1<<17, /* PCIe Rx Exit Electrical Idle State */
+ P_REL_GPHY_LINK_UP = 1<<16, /* GPHY Link Up */
+
+ /* Bit 10.. 0: Mask for Gate Clock */
+ P_GAT_PCIE_RST_ASSERTED = 1<<10,/* PCIe Reset Asserted */
+ P_GAT_GPHY_N_REC_PACKET = 1<<9, /* GPHY Not Received Packet */
+ P_GAT_INT_FIFO_EMPTY = 1<<8, /* Internal FIFO Empty */
+ P_GAT_MAIN_PWR_N_AVAIL = 1<<7, /* Main Power Not Available */
+ P_GAT_CLKRUN_REQ_REL = 1<<6, /* CLKRUN Not Requested */
+ P_GAT_PCIE_RESET_ASS = 1<<5, /* PCIe Reset Asserted */
+ P_GAT_PME_DE_ASSERTED = 1<<4, /* PME De-Asserted */
+ P_GAT_PCIE_ENTER_L1_ST = 1<<3, /* PCIe Enter L1 State */
+ P_GAT_LOADER_FINISHED = 1<<2, /* EPROM Loader Finished */
+ P_GAT_PCIE_RX_EL_IDLE = 1<<1, /* PCIe Rx Electrical Idle State */
+ P_GAT_GPHY_LINK_DOWN = 1<<0, /* GPHY Link Down */
+
+ PCIE_OUR5_EVENT_CLK_D3_SET = P_REL_GPHY_REC_PACKET |
+ P_REL_INT_FIFO_N_EMPTY |
+ P_REL_PCIE_EXIT_L1_ST |
+ P_REL_PCIE_RX_EX_IDLE |
+ P_GAT_GPHY_N_REC_PACKET |
+ P_GAT_INT_FIFO_EMPTY |
+ P_GAT_PCIE_ENTER_L1_ST |
+ P_GAT_PCIE_RX_EL_IDLE,
+};
+
+#/* PCI_CFG_REG_1 32 bit Config Register 1 (Yukon-Ext only) */
+enum pci_cfg_reg1 {
+ P_CF1_DIS_REL_EVT_RST = 1<<24, /* Dis. Rel. Event during PCIE reset */
+ /* Bit 23..21: Release Clock on Event */
+ P_CF1_REL_LDR_NOT_FIN = 1<<23, /* EEPROM Loader Not Finished */
+ P_CF1_REL_VMAIN_AVLBL = 1<<22, /* Vmain available */
+ P_CF1_REL_PCIE_RESET = 1<<21, /* PCI-E reset */
+ /* Bit 20..18: Gate Clock on Event */
+ P_CF1_GAT_LDR_NOT_FIN = 1<<20, /* EEPROM Loader Finished */
+ P_CF1_GAT_PCIE_RX_IDLE = 1<<19, /* PCI-E Rx Electrical idle */
+ P_CF1_GAT_PCIE_RESET = 1<<18, /* PCI-E Reset */
+ P_CF1_PRST_PHY_CLKREQ = 1<<17, /* Enable PCI-E rst & PM2PHY gen. CLKREQ */
+ P_CF1_PCIE_RST_CLKREQ = 1<<16, /* Enable PCI-E rst generate CLKREQ */
+
+ P_CF1_ENA_CFG_LDR_DONE = 1<<8, /* Enable core level Config loader done */
+
+ P_CF1_ENA_TXBMU_RD_IDLE = 1<<1, /* Enable TX BMU Read IDLE for ASPM */
+ P_CF1_ENA_TXBMU_WR_IDLE = 1<<0, /* Enable TX BMU Write IDLE for ASPM */
+
+ PCIE_CFG1_EVENT_CLK_D3_SET = P_CF1_DIS_REL_EVT_RST |
+ P_CF1_REL_LDR_NOT_FIN |
+ P_CF1_REL_VMAIN_AVLBL |
+ P_CF1_REL_PCIE_RESET |
+ P_CF1_GAT_LDR_NOT_FIN |
+ P_CF1_GAT_PCIE_RESET |
+ P_CF1_PRST_PHY_CLKREQ |
+ P_CF1_ENA_CFG_LDR_DONE |
+ P_CF1_ENA_TXBMU_RD_IDLE |
+ P_CF1_ENA_TXBMU_WR_IDLE,
+};
+
+
+#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
+ PCI_STATUS_SIG_SYSTEM_ERROR | \
+ PCI_STATUS_REC_MASTER_ABORT | \
+ PCI_STATUS_REC_TARGET_ABORT | \
+ PCI_STATUS_PARITY)
+
+enum csr_regs {
+ B0_RAP = 0x0000,
+ B0_CTST = 0x0004,
+ B0_Y2LED = 0x0005,
+ B0_POWER_CTRL = 0x0007,
+ B0_ISRC = 0x0008,
+ B0_IMSK = 0x000c,
+ B0_HWE_ISRC = 0x0010,
+ B0_HWE_IMSK = 0x0014,
+
+ /* Special ISR registers (Yukon-2 only) */
+ B0_Y2_SP_ISRC2 = 0x001c,
+ B0_Y2_SP_ISRC3 = 0x0020,
+ B0_Y2_SP_EISR = 0x0024,
+ B0_Y2_SP_LISR = 0x0028,
+ B0_Y2_SP_ICR = 0x002c,
+
+ B2_MAC_1 = 0x0100,
+ B2_MAC_2 = 0x0108,
+ B2_MAC_3 = 0x0110,
+ B2_CONN_TYP = 0x0118,
+ B2_PMD_TYP = 0x0119,
+ B2_MAC_CFG = 0x011a,
+ B2_CHIP_ID = 0x011b,
+ B2_E_0 = 0x011c,
+
+ B2_Y2_CLK_GATE = 0x011d,
+ B2_Y2_HW_RES = 0x011e,
+ B2_E_3 = 0x011f,
+ B2_Y2_CLK_CTRL = 0x0120,
+
+ B2_TI_INI = 0x0130,
+ B2_TI_VAL = 0x0134,
+ B2_TI_CTRL = 0x0138,
+ B2_TI_TEST = 0x0139,
+
+ B2_TST_CTRL1 = 0x0158,
+ B2_TST_CTRL2 = 0x0159,
+ B2_GP_IO = 0x015c,
+
+ B2_I2C_CTRL = 0x0160,
+ B2_I2C_DATA = 0x0164,
+ B2_I2C_IRQ = 0x0168,
+ B2_I2C_SW = 0x016c,
+
+ B3_RAM_ADDR = 0x0180,
+ B3_RAM_DATA_LO = 0x0184,
+ B3_RAM_DATA_HI = 0x0188,
+
+/* RAM Interface Registers */
+/* Yukon-2: use RAM_BUFFER() to access the RAM buffer */
+/*
+ * The HW-Spec. calls this registers Timeout Value 0..11. But this names are
+ * not usable in SW. Please notice these are NOT real timeouts, these are
+ * the number of qWords transferred continuously.
+ */
+#define RAM_BUFFER(port, reg) (reg | (port <<6))
+
+ B3_RI_WTO_R1 = 0x0190,
+ B3_RI_WTO_XA1 = 0x0191,
+ B3_RI_WTO_XS1 = 0x0192,
+ B3_RI_RTO_R1 = 0x0193,
+ B3_RI_RTO_XA1 = 0x0194,
+ B3_RI_RTO_XS1 = 0x0195,
+ B3_RI_WTO_R2 = 0x0196,
+ B3_RI_WTO_XA2 = 0x0197,
+ B3_RI_WTO_XS2 = 0x0198,
+ B3_RI_RTO_R2 = 0x0199,
+ B3_RI_RTO_XA2 = 0x019a,
+ B3_RI_RTO_XS2 = 0x019b,
+ B3_RI_TO_VAL = 0x019c,
+ B3_RI_CTRL = 0x01a0,
+ B3_RI_TEST = 0x01a2,
+ B3_MA_TOINI_RX1 = 0x01b0,
+ B3_MA_TOINI_RX2 = 0x01b1,
+ B3_MA_TOINI_TX1 = 0x01b2,
+ B3_MA_TOINI_TX2 = 0x01b3,
+ B3_MA_TOVAL_RX1 = 0x01b4,
+ B3_MA_TOVAL_RX2 = 0x01b5,
+ B3_MA_TOVAL_TX1 = 0x01b6,
+ B3_MA_TOVAL_TX2 = 0x01b7,
+ B3_MA_TO_CTRL = 0x01b8,
+ B3_MA_TO_TEST = 0x01ba,
+ B3_MA_RCINI_RX1 = 0x01c0,
+ B3_MA_RCINI_RX2 = 0x01c1,
+ B3_MA_RCINI_TX1 = 0x01c2,
+ B3_MA_RCINI_TX2 = 0x01c3,
+ B3_MA_RCVAL_RX1 = 0x01c4,
+ B3_MA_RCVAL_RX2 = 0x01c5,
+ B3_MA_RCVAL_TX1 = 0x01c6,
+ B3_MA_RCVAL_TX2 = 0x01c7,
+ B3_MA_RC_CTRL = 0x01c8,
+ B3_MA_RC_TEST = 0x01ca,
+ B3_PA_TOINI_RX1 = 0x01d0,
+ B3_PA_TOINI_RX2 = 0x01d4,
+ B3_PA_TOINI_TX1 = 0x01d8,
+ B3_PA_TOINI_TX2 = 0x01dc,
+ B3_PA_TOVAL_RX1 = 0x01e0,
+ B3_PA_TOVAL_RX2 = 0x01e4,
+ B3_PA_TOVAL_TX1 = 0x01e8,
+ B3_PA_TOVAL_TX2 = 0x01ec,
+ B3_PA_CTRL = 0x01f0,
+ B3_PA_TEST = 0x01f2,
+
+ Y2_CFG_SPC = 0x1c00, /* PCI config space region */
+ Y2_CFG_AER = 0x1d00, /* PCI Advanced Error Report region */
+};
+
+/* B0_CTST 16 bit Control/Status register */
+enum {
+ Y2_VMAIN_AVAIL = 1<<17,/* VMAIN available (YUKON-2 only) */
+ Y2_VAUX_AVAIL = 1<<16,/* VAUX available (YUKON-2 only) */
+ Y2_HW_WOL_ON = 1<<15,/* HW WOL On (Yukon-EC Ultra A1 only) */
+ Y2_HW_WOL_OFF = 1<<14,/* HW WOL On (Yukon-EC Ultra A1 only) */
+ Y2_ASF_ENABLE = 1<<13,/* ASF Unit Enable (YUKON-2 only) */
+ Y2_ASF_DISABLE = 1<<12,/* ASF Unit Disable (YUKON-2 only) */
+ Y2_CLK_RUN_ENA = 1<<11,/* CLK_RUN Enable (YUKON-2 only) */
+ Y2_CLK_RUN_DIS = 1<<10,/* CLK_RUN Disable (YUKON-2 only) */
+ Y2_LED_STAT_ON = 1<<9, /* Status LED On (YUKON-2 only) */
+ Y2_LED_STAT_OFF = 1<<8, /* Status LED Off (YUKON-2 only) */
+
+ CS_ST_SW_IRQ = 1<<7, /* Set IRQ SW Request */
+ CS_CL_SW_IRQ = 1<<6, /* Clear IRQ SW Request */
+ CS_STOP_DONE = 1<<5, /* Stop Master is finished */
+ CS_STOP_MAST = 1<<4, /* Command Bit to stop the master */
+ CS_MRST_CLR = 1<<3, /* Clear Master reset */
+ CS_MRST_SET = 1<<2, /* Set Master reset */
+ CS_RST_CLR = 1<<1, /* Clear Software reset */
+ CS_RST_SET = 1, /* Set Software reset */
+};
+
+/* B0_LED 8 Bit LED register */
+enum {
+/* Bit 7.. 2: reserved */
+ LED_STAT_ON = 1<<1, /* Status LED on */
+ LED_STAT_OFF = 1, /* Status LED off */
+};
+
+/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */
+enum {
+ PC_VAUX_ENA = 1<<7, /* Switch VAUX Enable */
+ PC_VAUX_DIS = 1<<6, /* Switch VAUX Disable */
+ PC_VCC_ENA = 1<<5, /* Switch VCC Enable */
+ PC_VCC_DIS = 1<<4, /* Switch VCC Disable */
+ PC_VAUX_ON = 1<<3, /* Switch VAUX On */
+ PC_VAUX_OFF = 1<<2, /* Switch VAUX Off */
+ PC_VCC_ON = 1<<1, /* Switch VCC On */
+ PC_VCC_OFF = 1<<0, /* Switch VCC Off */
+};
+
+/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */
+
+/* B0_Y2_SP_ISRC2 32 bit Special Interrupt Source Reg 2 */
+/* B0_Y2_SP_ISRC3 32 bit Special Interrupt Source Reg 3 */
+/* B0_Y2_SP_EISR 32 bit Enter ISR Reg */
+/* B0_Y2_SP_LISR 32 bit Leave ISR Reg */
+enum {
+ Y2_IS_HW_ERR = 1<<31, /* Interrupt HW Error */
+ Y2_IS_STAT_BMU = 1<<30, /* Status BMU Interrupt */
+ Y2_IS_ASF = 1<<29, /* ASF subsystem Interrupt */
+
+ Y2_IS_POLL_CHK = 1<<27, /* Check IRQ from polling unit */
+ Y2_IS_TWSI_RDY = 1<<26, /* IRQ on end of TWSI Tx */
+ Y2_IS_IRQ_SW = 1<<25, /* SW forced IRQ */
+ Y2_IS_TIMINT = 1<<24, /* IRQ from Timer */
+
+ Y2_IS_IRQ_PHY2 = 1<<12, /* Interrupt from PHY 2 */
+ Y2_IS_IRQ_MAC2 = 1<<11, /* Interrupt from MAC 2 */
+ Y2_IS_CHK_RX2 = 1<<10, /* Descriptor error Rx 2 */
+ Y2_IS_CHK_TXS2 = 1<<9, /* Descriptor error TXS 2 */
+ Y2_IS_CHK_TXA2 = 1<<8, /* Descriptor error TXA 2 */
+
+ Y2_IS_IRQ_PHY1 = 1<<4, /* Interrupt from PHY 1 */
+ Y2_IS_IRQ_MAC1 = 1<<3, /* Interrupt from MAC 1 */
+ Y2_IS_CHK_RX1 = 1<<2, /* Descriptor error Rx 1 */
+ Y2_IS_CHK_TXS1 = 1<<1, /* Descriptor error TXS 1 */
+ Y2_IS_CHK_TXA1 = 1<<0, /* Descriptor error TXA 1 */
+
+ Y2_IS_BASE = Y2_IS_HW_ERR | Y2_IS_STAT_BMU,
+ Y2_IS_PORT_1 = Y2_IS_IRQ_PHY1 | Y2_IS_IRQ_MAC1
+ | Y2_IS_CHK_TXA1 | Y2_IS_CHK_RX1,
+ Y2_IS_PORT_2 = Y2_IS_IRQ_PHY2 | Y2_IS_IRQ_MAC2
+ | Y2_IS_CHK_TXA2 | Y2_IS_CHK_RX2,
+ Y2_IS_ERROR = Y2_IS_HW_ERR |
+ Y2_IS_IRQ_MAC1 | Y2_IS_CHK_TXA1 | Y2_IS_CHK_RX1 |
+ Y2_IS_IRQ_MAC2 | Y2_IS_CHK_TXA2 | Y2_IS_CHK_RX2,
+};
+
+/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */
+enum {
+ IS_ERR_MSK = 0x00003fff,/* All Error bits */
+
+ IS_IRQ_TIST_OV = 1<<13, /* Time Stamp Timer Overflow (YUKON only) */
+ IS_IRQ_SENSOR = 1<<12, /* IRQ from Sensor (YUKON only) */
+ IS_IRQ_MST_ERR = 1<<11, /* IRQ master error detected */
+ IS_IRQ_STAT = 1<<10, /* IRQ status exception */
+ IS_NO_STAT_M1 = 1<<9, /* No Rx Status from MAC 1 */
+ IS_NO_STAT_M2 = 1<<8, /* No Rx Status from MAC 2 */
+ IS_NO_TIST_M1 = 1<<7, /* No Time Stamp from MAC 1 */
+ IS_NO_TIST_M2 = 1<<6, /* No Time Stamp from MAC 2 */
+ IS_RAM_RD_PAR = 1<<5, /* RAM Read Parity Error */
+ IS_RAM_WR_PAR = 1<<4, /* RAM Write Parity Error */
+ IS_M1_PAR_ERR = 1<<3, /* MAC 1 Parity Error */
+ IS_M2_PAR_ERR = 1<<2, /* MAC 2 Parity Error */
+ IS_R1_PAR_ERR = 1<<1, /* Queue R1 Parity Error */
+ IS_R2_PAR_ERR = 1<<0, /* Queue R2 Parity Error */
+};
+
+/* Hardware error interrupt mask for Yukon 2 */
+enum {
+ Y2_IS_TIST_OV = 1<<29,/* Time Stamp Timer overflow interrupt */
+ Y2_IS_SENSOR = 1<<28, /* Sensor interrupt */
+ Y2_IS_MST_ERR = 1<<27, /* Master error interrupt */
+ Y2_IS_IRQ_STAT = 1<<26, /* Status exception interrupt */
+ Y2_IS_PCI_EXP = 1<<25, /* PCI-Express interrupt */
+ Y2_IS_PCI_NEXP = 1<<24, /* PCI-Express error similar to PCI error */
+ /* Link 2 */
+ Y2_IS_PAR_RD2 = 1<<13, /* Read RAM parity error interrupt */
+ Y2_IS_PAR_WR2 = 1<<12, /* Write RAM parity error interrupt */
+ Y2_IS_PAR_MAC2 = 1<<11, /* MAC hardware fault interrupt */
+ Y2_IS_PAR_RX2 = 1<<10, /* Parity Error Rx Queue 2 */
+ Y2_IS_TCP_TXS2 = 1<<9, /* TCP length mismatch sync Tx queue IRQ */
+ Y2_IS_TCP_TXA2 = 1<<8, /* TCP length mismatch async Tx queue IRQ */
+ /* Link 1 */
+ Y2_IS_PAR_RD1 = 1<<5, /* Read RAM parity error interrupt */
+ Y2_IS_PAR_WR1 = 1<<4, /* Write RAM parity error interrupt */
+ Y2_IS_PAR_MAC1 = 1<<3, /* MAC hardware fault interrupt */
+ Y2_IS_PAR_RX1 = 1<<2, /* Parity Error Rx Queue 1 */
+ Y2_IS_TCP_TXS1 = 1<<1, /* TCP length mismatch sync Tx queue IRQ */
+ Y2_IS_TCP_TXA1 = 1<<0, /* TCP length mismatch async Tx queue IRQ */
+
+ Y2_HWE_L1_MASK = Y2_IS_PAR_RD1 | Y2_IS_PAR_WR1 | Y2_IS_PAR_MAC1 |
+ Y2_IS_PAR_RX1 | Y2_IS_TCP_TXS1| Y2_IS_TCP_TXA1,
+ Y2_HWE_L2_MASK = Y2_IS_PAR_RD2 | Y2_IS_PAR_WR2 | Y2_IS_PAR_MAC2 |
+ Y2_IS_PAR_RX2 | Y2_IS_TCP_TXS2| Y2_IS_TCP_TXA2,
+
+ Y2_HWE_ALL_MASK = Y2_IS_TIST_OV | Y2_IS_MST_ERR | Y2_IS_IRQ_STAT |
+ Y2_HWE_L1_MASK | Y2_HWE_L2_MASK,
+};
+
+/* B28_DPT_CTRL 8 bit Descriptor Poll Timer Ctrl Reg */
+enum {
+ DPT_START = 1<<1,
+ DPT_STOP = 1<<0,
+};
+
+/* B2_TST_CTRL1 8 bit Test Control Register 1 */
+enum {
+ TST_FRC_DPERR_MR = 1<<7, /* force DATAPERR on MST RD */
+ TST_FRC_DPERR_MW = 1<<6, /* force DATAPERR on MST WR */
+ TST_FRC_DPERR_TR = 1<<5, /* force DATAPERR on TRG RD */
+ TST_FRC_DPERR_TW = 1<<4, /* force DATAPERR on TRG WR */
+ TST_FRC_APERR_M = 1<<3, /* force ADDRPERR on MST */
+ TST_FRC_APERR_T = 1<<2, /* force ADDRPERR on TRG */
+ TST_CFG_WRITE_ON = 1<<1, /* Enable Config Reg WR */
+ TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */
+};
+
+/* B2_GPIO */
+enum {
+ GLB_GPIO_CLK_DEB_ENA = 1<<31, /* Clock Debug Enable */
+ GLB_GPIO_CLK_DBG_MSK = 0xf<<26, /* Clock Debug */
+
+ GLB_GPIO_INT_RST_D3_DIS = 1<<15, /* Disable Internal Reset After D3 to D0 */
+ GLB_GPIO_LED_PAD_SPEED_UP = 1<<14, /* LED PAD Speed Up */
+ GLB_GPIO_STAT_RACE_DIS = 1<<13, /* Status Race Disable */
+ GLB_GPIO_TEST_SEL_MSK = 3<<11, /* Testmode Select */
+ GLB_GPIO_TEST_SEL_BASE = 1<<11,
+ GLB_GPIO_RAND_ENA = 1<<10, /* Random Enable */
+ GLB_GPIO_RAND_BIT_1 = 1<<9, /* Random Bit 1 */
+};
+
+/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */
+enum {
+ CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */
+ /* Bit 3.. 2: reserved */
+ CFG_DIS_M2_CLK = 1<<1, /* Disable Clock for 2nd MAC */
+ CFG_SNG_MAC = 1<<0, /* MAC Config: 0=2 MACs / 1=1 MAC*/
+};
+
+/* B2_CHIP_ID 8 bit Chip Identification Number */
+enum {
+ CHIP_ID_YUKON_XL = 0xb3, /* YUKON-2 XL */
+ CHIP_ID_YUKON_EC_U = 0xb4, /* YUKON-2 EC Ultra */
+ CHIP_ID_YUKON_EX = 0xb5, /* YUKON-2 Extreme */
+ CHIP_ID_YUKON_EC = 0xb6, /* YUKON-2 EC */
+ CHIP_ID_YUKON_FE = 0xb7, /* YUKON-2 FE */
+ CHIP_ID_YUKON_FE_P = 0xb8, /* YUKON-2 FE+ */
+ CHIP_ID_YUKON_SUPR = 0xb9, /* YUKON-2 Supreme */
+ CHIP_ID_YUKON_UL_2 = 0xba, /* YUKON-2 Ultra 2 */
+};
+enum yukon_ec_rev {
+ CHIP_REV_YU_EC_A1 = 0, /* Chip Rev. for Yukon-EC A1/A0 */
+ CHIP_REV_YU_EC_A2 = 1, /* Chip Rev. for Yukon-EC A2 */
+ CHIP_REV_YU_EC_A3 = 2, /* Chip Rev. for Yukon-EC A3 */
+};
+enum yukon_ec_u_rev {
+ CHIP_REV_YU_EC_U_A0 = 1,
+ CHIP_REV_YU_EC_U_A1 = 2,
+ CHIP_REV_YU_EC_U_B0 = 3,
+};
+enum yukon_fe_rev {
+ CHIP_REV_YU_FE_A1 = 1,
+ CHIP_REV_YU_FE_A2 = 2,
+};
+enum yukon_fe_p_rev {
+ CHIP_REV_YU_FE2_A0 = 0,
+};
+enum yukon_ex_rev {
+ CHIP_REV_YU_EX_A0 = 1,
+ CHIP_REV_YU_EX_B0 = 2,
+};
+enum yukon_supr_rev {
+ CHIP_REV_YU_SU_A0 = 0,
+};
+
+
+/* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */
+enum {
+ Y2_STATUS_LNK2_INAC = 1<<7, /* Status Link 2 inactive (0 = active) */
+ Y2_CLK_GAT_LNK2_DIS = 1<<6, /* Disable clock gating Link 2 */
+ Y2_COR_CLK_LNK2_DIS = 1<<5, /* Disable Core clock Link 2 */
+ Y2_PCI_CLK_LNK2_DIS = 1<<4, /* Disable PCI clock Link 2 */
+ Y2_STATUS_LNK1_INAC = 1<<3, /* Status Link 1 inactive (0 = active) */
+ Y2_CLK_GAT_LNK1_DIS = 1<<2, /* Disable clock gating Link 1 */
+ Y2_COR_CLK_LNK1_DIS = 1<<1, /* Disable Core clock Link 1 */
+ Y2_PCI_CLK_LNK1_DIS = 1<<0, /* Disable PCI clock Link 1 */
+};
+
+/* B2_Y2_HW_RES 8 bit HW Resources (Yukon-2 only) */
+enum {
+ CFG_LED_MODE_MSK = 7<<2, /* Bit 4.. 2: LED Mode Mask */
+ CFG_LINK_2_AVAIL = 1<<1, /* Link 2 available */
+ CFG_LINK_1_AVAIL = 1<<0, /* Link 1 available */
+};
+#define CFG_LED_MODE(x) (((x) & CFG_LED_MODE_MSK) >> 2)
+#define CFG_DUAL_MAC_MSK (CFG_LINK_2_AVAIL | CFG_LINK_1_AVAIL)
+
+
+/* B2_Y2_CLK_CTRL 32 bit Clock Frequency Control Register (Yukon-2/EC) */
+enum {
+ Y2_CLK_DIV_VAL_MSK = 0xff<<16,/* Bit 23..16: Clock Divisor Value */
+#define Y2_CLK_DIV_VAL(x) (((x)<<16) & Y2_CLK_DIV_VAL_MSK)
+ Y2_CLK_DIV_VAL2_MSK = 7<<21, /* Bit 23..21: Clock Divisor Value */
+ Y2_CLK_SELECT2_MSK = 0x1f<<16,/* Bit 20..16: Clock Select */
+#define Y2_CLK_DIV_VAL_2(x) (((x)<<21) & Y2_CLK_DIV_VAL2_MSK)
+#define Y2_CLK_SEL_VAL_2(x) (((x)<<16) & Y2_CLK_SELECT2_MSK)
+ Y2_CLK_DIV_ENA = 1<<1, /* Enable Core Clock Division */
+ Y2_CLK_DIV_DIS = 1<<0, /* Disable Core Clock Division */
+};
+
+/* B2_TI_CTRL 8 bit Timer control */
+/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */
+enum {
+ TIM_START = 1<<2, /* Start Timer */
+ TIM_STOP = 1<<1, /* Stop Timer */
+ TIM_CLR_IRQ = 1<<0, /* Clear Timer IRQ (!IRQM) */
+};
+
+/* B2_TI_TEST 8 Bit Timer Test */
+/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */
+/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */
+enum {
+ TIM_T_ON = 1<<2, /* Test mode on */
+ TIM_T_OFF = 1<<1, /* Test mode off */
+ TIM_T_STEP = 1<<0, /* Test step */
+};
+
+/* B3_RAM_ADDR 32 bit RAM Address, to read or write */
+ /* Bit 31..19: reserved */
+#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */
+/* RAM Interface Registers */
+
+/* B3_RI_CTRL 16 bit RAM Interface Control Register */
+enum {
+ RI_CLR_RD_PERR = 1<<9, /* Clear IRQ RAM Read Parity Err */
+ RI_CLR_WR_PERR = 1<<8, /* Clear IRQ RAM Write Parity Err*/
+
+ RI_RST_CLR = 1<<1, /* Clear RAM Interface Reset */
+ RI_RST_SET = 1<<0, /* Set RAM Interface Reset */
+};
+
+#define SK_RI_TO_53 36 /* RAM interface timeout */
+
+
+/* Port related registers FIFO, and Arbiter */
+#define SK_REG(port,reg) (((port)<<7)+(reg))
+
+/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */
+/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */
+/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */
+/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */
+/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */
+
+#define TXA_MAX_VAL 0x00ffffffUL /* Bit 23.. 0: Max TXA Timer/Cnt Val */
+
+/* TXA_CTRL 8 bit Tx Arbiter Control Register */
+enum {
+ TXA_ENA_FSYNC = 1<<7, /* Enable force of sync Tx queue */
+ TXA_DIS_FSYNC = 1<<6, /* Disable force of sync Tx queue */
+ TXA_ENA_ALLOC = 1<<5, /* Enable alloc of free bandwidth */
+ TXA_DIS_ALLOC = 1<<4, /* Disable alloc of free bandwidth */
+ TXA_START_RC = 1<<3, /* Start sync Rate Control */
+ TXA_STOP_RC = 1<<2, /* Stop sync Rate Control */
+ TXA_ENA_ARB = 1<<1, /* Enable Tx Arbiter */
+ TXA_DIS_ARB = 1<<0, /* Disable Tx Arbiter */
+};
+
+/*
+ * Bank 4 - 5
+ */
+/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */
+enum {
+ TXA_ITI_INI = 0x0200,/* 32 bit Tx Arb Interval Timer Init Val*/
+ TXA_ITI_VAL = 0x0204,/* 32 bit Tx Arb Interval Timer Value */
+ TXA_LIM_INI = 0x0208,/* 32 bit Tx Arb Limit Counter Init Val */
+ TXA_LIM_VAL = 0x020c,/* 32 bit Tx Arb Limit Counter Value */
+ TXA_CTRL = 0x0210,/* 8 bit Tx Arbiter Control Register */
+ TXA_TEST = 0x0211,/* 8 bit Tx Arbiter Test Register */
+ TXA_STAT = 0x0212,/* 8 bit Tx Arbiter Status Register */
+};
+
+
+enum {
+ B6_EXT_REG = 0x0300,/* External registers (GENESIS only) */
+ B7_CFG_SPC = 0x0380,/* copy of the Configuration register */
+ B8_RQ1_REGS = 0x0400,/* Receive Queue 1 */
+ B8_RQ2_REGS = 0x0480,/* Receive Queue 2 */
+ B8_TS1_REGS = 0x0600,/* Transmit sync queue 1 */
+ B8_TA1_REGS = 0x0680,/* Transmit async queue 1 */
+ B8_TS2_REGS = 0x0700,/* Transmit sync queue 2 */
+ B8_TA2_REGS = 0x0780,/* Transmit sync queue 2 */
+ B16_RAM_REGS = 0x0800,/* RAM Buffer Registers */
+};
+
+/* Queue Register Offsets, use Q_ADDR() to access */
+enum {
+ B8_Q_REGS = 0x0400, /* base of Queue registers */
+ Q_D = 0x00, /* 8*32 bit Current Descriptor */
+ Q_VLAN = 0x20, /* 16 bit Current VLAN Tag */
+ Q_DONE = 0x24, /* 16 bit Done Index */
+ Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */
+ Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */
+ Q_BC = 0x30, /* 32 bit Current Byte Counter */
+ Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */
+ Q_TEST = 0x38, /* 32 bit Test/Control Register */
+
+/* Yukon-2 */
+ Q_WM = 0x40, /* 16 bit FIFO Watermark */
+ Q_AL = 0x42, /* 8 bit FIFO Alignment */
+ Q_RSP = 0x44, /* 16 bit FIFO Read Shadow Pointer */
+ Q_RSL = 0x46, /* 8 bit FIFO Read Shadow Level */
+ Q_RP = 0x48, /* 8 bit FIFO Read Pointer */
+ Q_RL = 0x4a, /* 8 bit FIFO Read Level */
+ Q_WP = 0x4c, /* 8 bit FIFO Write Pointer */
+ Q_WSP = 0x4d, /* 8 bit FIFO Write Shadow Pointer */
+ Q_WL = 0x4e, /* 8 bit FIFO Write Level */
+ Q_WSL = 0x4f, /* 8 bit FIFO Write Shadow Level */
+};
+#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
+
+/* Q_TEST 32 bit Test Register */
+enum {
+ /* Transmit */
+ F_TX_CHK_AUTO_OFF = 1<<31, /* Tx checksum auto calc off (Yukon EX) */
+ F_TX_CHK_AUTO_ON = 1<<30, /* Tx checksum auto calc off (Yukon EX) */
+
+ /* Receive */
+ F_M_RX_RAM_DIS = 1<<24, /* MAC Rx RAM Read Port disable */
+
+ /* Hardware testbits not used */
+};
+
+/* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
+enum {
+ Y2_B8_PREF_REGS = 0x0450,
+
+ PREF_UNIT_CTRL = 0x00, /* 32 bit Control register */
+ PREF_UNIT_LAST_IDX = 0x04, /* 16 bit Last Index */
+ PREF_UNIT_ADDR_LO = 0x08, /* 32 bit List start addr, low part */
+ PREF_UNIT_ADDR_HI = 0x0c, /* 32 bit List start addr, high part*/
+ PREF_UNIT_GET_IDX = 0x10, /* 16 bit Get Index */
+ PREF_UNIT_PUT_IDX = 0x14, /* 16 bit Put Index */
+ PREF_UNIT_FIFO_WP = 0x20, /* 8 bit FIFO write pointer */
+ PREF_UNIT_FIFO_RP = 0x24, /* 8 bit FIFO read pointer */
+ PREF_UNIT_FIFO_WM = 0x28, /* 8 bit FIFO watermark */
+ PREF_UNIT_FIFO_LEV = 0x2c, /* 8 bit FIFO level */
+
+ PREF_UNIT_MASK_IDX = 0x0fff,
+};
+#define Y2_QADDR(q,reg) (Y2_B8_PREF_REGS + (q) + (reg))
+
+/* RAM Buffer Register Offsets */
+enum {
+
+ RB_START = 0x00,/* 32 bit RAM Buffer Start Address */
+ RB_END = 0x04,/* 32 bit RAM Buffer End Address */
+ RB_WP = 0x08,/* 32 bit RAM Buffer Write Pointer */
+ RB_RP = 0x0c,/* 32 bit RAM Buffer Read Pointer */
+ RB_RX_UTPP = 0x10,/* 32 bit Rx Upper Threshold, Pause Packet */
+ RB_RX_LTPP = 0x14,/* 32 bit Rx Lower Threshold, Pause Packet */
+ RB_RX_UTHP = 0x18,/* 32 bit Rx Upper Threshold, High Prio */
+ RB_RX_LTHP = 0x1c,/* 32 bit Rx Lower Threshold, High Prio */
+ /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */
+ RB_PC = 0x20,/* 32 bit RAM Buffer Packet Counter */
+ RB_LEV = 0x24,/* 32 bit RAM Buffer Level Register */
+ RB_CTRL = 0x28,/* 32 bit RAM Buffer Control Register */
+ RB_TST1 = 0x29,/* 8 bit RAM Buffer Test Register 1 */
+ RB_TST2 = 0x2a,/* 8 bit RAM Buffer Test Register 2 */
+};
+
+/* Receive and Transmit Queues */
+enum {
+ Q_R1 = 0x0000, /* Receive Queue 1 */
+ Q_R2 = 0x0080, /* Receive Queue 2 */
+ Q_XS1 = 0x0200, /* Synchronous Transmit Queue 1 */
+ Q_XA1 = 0x0280, /* Asynchronous Transmit Queue 1 */
+ Q_XS2 = 0x0300, /* Synchronous Transmit Queue 2 */
+ Q_XA2 = 0x0380, /* Asynchronous Transmit Queue 2 */
+};
+
+/* Different PHY Types */
+enum {
+ PHY_ADDR_MARV = 0,
+};
+
+#define RB_ADDR(offs, queue) ((u16) B16_RAM_REGS + (queue) + (offs))
+
+
+enum {
+ LNK_SYNC_INI = 0x0c30,/* 32 bit Link Sync Cnt Init Value */
+ LNK_SYNC_VAL = 0x0c34,/* 32 bit Link Sync Cnt Current Value */
+ LNK_SYNC_CTRL = 0x0c38,/* 8 bit Link Sync Cnt Control Register */
+ LNK_SYNC_TST = 0x0c39,/* 8 bit Link Sync Cnt Test Register */
+
+ LNK_LED_REG = 0x0c3c,/* 8 bit Link LED Register */
+
+/* Receive GMAC FIFO (YUKON and Yukon-2) */
+
+ RX_GMF_EA = 0x0c40,/* 32 bit Rx GMAC FIFO End Address */
+ RX_GMF_AF_THR = 0x0c44,/* 32 bit Rx GMAC FIFO Almost Full Thresh. */
+ RX_GMF_CTRL_T = 0x0c48,/* 32 bit Rx GMAC FIFO Control/Test */
+ RX_GMF_FL_MSK = 0x0c4c,/* 32 bit Rx GMAC FIFO Flush Mask */
+ RX_GMF_FL_THR = 0x0c50,/* 32 bit Rx GMAC FIFO Flush Threshold */
+ RX_GMF_TR_THR = 0x0c54,/* 32 bit Rx Truncation Threshold (Yukon-2) */
+ RX_GMF_UP_THR = 0x0c58,/* 8 bit Rx Upper Pause Thr (Yukon-EC_U) */
+ RX_GMF_LP_THR = 0x0c5a,/* 8 bit Rx Lower Pause Thr (Yukon-EC_U) */
+ RX_GMF_VLAN = 0x0c5c,/* 32 bit Rx VLAN Type Register (Yukon-2) */
+ RX_GMF_WP = 0x0c60,/* 32 bit Rx GMAC FIFO Write Pointer */
+
+ RX_GMF_WLEV = 0x0c68,/* 32 bit Rx GMAC FIFO Write Level */
+
+ RX_GMF_RP = 0x0c70,/* 32 bit Rx GMAC FIFO Read Pointer */
+
+ RX_GMF_RLEV = 0x0c78,/* 32 bit Rx GMAC FIFO Read Level */
+};
+
+
+/* Q_BC 32 bit Current Byte Counter */
+
+/* BMU Control Status Registers */
+/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */
+/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */
+/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */
+/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */
+/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */
+/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */
+/* Q_CSR 32 bit BMU Control/Status Register */
+
+/* Rx BMU Control / Status Registers (Yukon-2) */
+enum {
+ BMU_IDLE = 1<<31, /* BMU Idle State */
+ BMU_RX_TCP_PKT = 1<<30, /* Rx TCP Packet (when RSS Hash enabled) */
+ BMU_RX_IP_PKT = 1<<29, /* Rx IP Packet (when RSS Hash enabled) */
+
+ BMU_ENA_RX_RSS_HASH = 1<<15, /* Enable Rx RSS Hash */
+ BMU_DIS_RX_RSS_HASH = 1<<14, /* Disable Rx RSS Hash */
+ BMU_ENA_RX_CHKSUM = 1<<13, /* Enable Rx TCP/IP Checksum Check */
+ BMU_DIS_RX_CHKSUM = 1<<12, /* Disable Rx TCP/IP Checksum Check */
+ BMU_CLR_IRQ_PAR = 1<<11, /* Clear IRQ on Parity errors (Rx) */
+ BMU_CLR_IRQ_TCP = 1<<11, /* Clear IRQ on TCP segment. error (Tx) */
+ BMU_CLR_IRQ_CHK = 1<<10, /* Clear IRQ Check */
+ BMU_STOP = 1<<9, /* Stop Rx/Tx Queue */
+ BMU_START = 1<<8, /* Start Rx/Tx Queue */
+ BMU_FIFO_OP_ON = 1<<7, /* FIFO Operational On */
+ BMU_FIFO_OP_OFF = 1<<6, /* FIFO Operational Off */
+ BMU_FIFO_ENA = 1<<5, /* Enable FIFO */
+ BMU_FIFO_RST = 1<<4, /* Reset FIFO */
+ BMU_OP_ON = 1<<3, /* BMU Operational On */
+ BMU_OP_OFF = 1<<2, /* BMU Operational Off */
+ BMU_RST_CLR = 1<<1, /* Clear BMU Reset (Enable) */
+ BMU_RST_SET = 1<<0, /* Set BMU Reset */
+
+ BMU_CLR_RESET = BMU_FIFO_RST | BMU_OP_OFF | BMU_RST_CLR,
+ BMU_OPER_INIT = BMU_CLR_IRQ_PAR | BMU_CLR_IRQ_CHK | BMU_START |
+ BMU_FIFO_ENA | BMU_OP_ON,
+
+ BMU_WM_DEFAULT = 0x600,
+ BMU_WM_PEX = 0x80,
+};
+
+/* Tx BMU Control / Status Registers (Yukon-2) */
+ /* Bit 31: same as for Rx */
+enum {
+ BMU_TX_IPIDINCR_ON = 1<<13, /* Enable IP ID Increment */
+ BMU_TX_IPIDINCR_OFF = 1<<12, /* Disable IP ID Increment */
+ BMU_TX_CLR_IRQ_TCP = 1<<11, /* Clear IRQ on TCP segment length mismatch */
+};
+
+/* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
+/* PREF_UNIT_CTRL 32 bit Prefetch Control register */
+enum {
+ PREF_UNIT_OP_ON = 1<<3, /* prefetch unit operational */
+ PREF_UNIT_OP_OFF = 1<<2, /* prefetch unit not operational */
+ PREF_UNIT_RST_CLR = 1<<1, /* Clear Prefetch Unit Reset */
+ PREF_UNIT_RST_SET = 1<<0, /* Set Prefetch Unit Reset */
+};
+
+/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
+/* RB_START 32 bit RAM Buffer Start Address */
+/* RB_END 32 bit RAM Buffer End Address */
+/* RB_WP 32 bit RAM Buffer Write Pointer */
+/* RB_RP 32 bit RAM Buffer Read Pointer */
+/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */
+/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */
+/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */
+/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */
+/* RB_PC 32 bit RAM Buffer Packet Counter */
+/* RB_LEV 32 bit RAM Buffer Level Register */
+
+#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */
+/* RB_TST2 8 bit RAM Buffer Test Register 2 */
+/* RB_TST1 8 bit RAM Buffer Test Register 1 */
+
+/* RB_CTRL 8 bit RAM Buffer Control Register */
+enum {
+ RB_ENA_STFWD = 1<<5, /* Enable Store & Forward */
+ RB_DIS_STFWD = 1<<4, /* Disable Store & Forward */
+ RB_ENA_OP_MD = 1<<3, /* Enable Operation Mode */
+ RB_DIS_OP_MD = 1<<2, /* Disable Operation Mode */
+ RB_RST_CLR = 1<<1, /* Clear RAM Buf STM Reset */
+ RB_RST_SET = 1<<0, /* Set RAM Buf STM Reset */
+};
+
+
+/* Transmit GMAC FIFO (YUKON only) */
+enum {
+ TX_GMF_EA = 0x0d40,/* 32 bit Tx GMAC FIFO End Address */
+ TX_GMF_AE_THR = 0x0d44,/* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/
+ TX_GMF_CTRL_T = 0x0d48,/* 32 bit Tx GMAC FIFO Control/Test */
+
+ TX_GMF_WP = 0x0d60,/* 32 bit Tx GMAC FIFO Write Pointer */
+ TX_GMF_WSP = 0x0d64,/* 32 bit Tx GMAC FIFO Write Shadow Ptr. */
+ TX_GMF_WLEV = 0x0d68,/* 32 bit Tx GMAC FIFO Write Level */
+
+ TX_GMF_RP = 0x0d70,/* 32 bit Tx GMAC FIFO Read Pointer */
+ TX_GMF_RSTP = 0x0d74,/* 32 bit Tx GMAC FIFO Restart Pointer */
+ TX_GMF_RLEV = 0x0d78,/* 32 bit Tx GMAC FIFO Read Level */
+
+ /* Threshold values for Yukon-EC Ultra and Extreme */
+ ECU_AE_THR = 0x0070, /* Almost Empty Threshold */
+ ECU_TXFF_LEV = 0x01a0, /* Tx BMU FIFO Level */
+ ECU_JUMBO_WM = 0x0080, /* Jumbo Mode Watermark */
+};
+
+/* Descriptor Poll Timer Registers */
+enum {
+ B28_DPT_INI = 0x0e00,/* 24 bit Descriptor Poll Timer Init Val */
+ B28_DPT_VAL = 0x0e04,/* 24 bit Descriptor Poll Timer Curr Val */
+ B28_DPT_CTRL = 0x0e08,/* 8 bit Descriptor Poll Timer Ctrl Reg */
+
+ B28_DPT_TST = 0x0e0a,/* 8 bit Descriptor Poll Timer Test Reg */
+};
+
+/* Time Stamp Timer Registers (YUKON only) */
+enum {
+ GMAC_TI_ST_VAL = 0x0e14,/* 32 bit Time Stamp Timer Curr Val */
+ GMAC_TI_ST_CTRL = 0x0e18,/* 8 bit Time Stamp Timer Ctrl Reg */
+ GMAC_TI_ST_TST = 0x0e1a,/* 8 bit Time Stamp Timer Test Reg */
+};
+
+/* Polling Unit Registers (Yukon-2 only) */
+enum {
+ POLL_CTRL = 0x0e20, /* 32 bit Polling Unit Control Reg */
+ POLL_LAST_IDX = 0x0e24,/* 16 bit Polling Unit List Last Index */
+
+ POLL_LIST_ADDR_LO= 0x0e28,/* 32 bit Poll. List Start Addr (low) */
+ POLL_LIST_ADDR_HI= 0x0e2c,/* 32 bit Poll. List Start Addr (high) */
+};
+
+enum {
+ SMB_CFG = 0x0e40, /* 32 bit SMBus Config Register */
+ SMB_CSR = 0x0e44, /* 32 bit SMBus Control/Status Register */
+};
+
+enum {
+ CPU_WDOG = 0x0e48, /* 32 bit Watchdog Register */
+ CPU_CNTR = 0x0e4C, /* 32 bit Counter Register */
+ CPU_TIM = 0x0e50,/* 32 bit Timer Compare Register */
+ CPU_AHB_ADDR = 0x0e54, /* 32 bit CPU AHB Debug Register */
+ CPU_AHB_WDATA = 0x0e58, /* 32 bit CPU AHB Debug Register */
+ CPU_AHB_RDATA = 0x0e5C, /* 32 bit CPU AHB Debug Register */
+ HCU_MAP_BASE = 0x0e60, /* 32 bit Reset Mapping Base */
+ CPU_AHB_CTRL = 0x0e64, /* 32 bit CPU AHB Debug Register */
+ HCU_CCSR = 0x0e68, /* 32 bit CPU Control and Status Register */
+ HCU_HCSR = 0x0e6C, /* 32 bit Host Control and Status Register */
+};
+
+/* ASF Subsystem Registers (Yukon-2 only) */
+enum {
+ B28_Y2_SMB_CONFIG = 0x0e40,/* 32 bit ASF SMBus Config Register */
+ B28_Y2_SMB_CSD_REG = 0x0e44,/* 32 bit ASF SMB Control/Status/Data */
+ B28_Y2_ASF_IRQ_V_BASE=0x0e60,/* 32 bit ASF IRQ Vector Base */
+
+ B28_Y2_ASF_STAT_CMD= 0x0e68,/* 32 bit ASF Status and Command Reg */
+ B28_Y2_ASF_HOST_COM= 0x0e6c,/* 32 bit ASF Host Communication Reg */
+ B28_Y2_DATA_REG_1 = 0x0e70,/* 32 bit ASF/Host Data Register 1 */
+ B28_Y2_DATA_REG_2 = 0x0e74,/* 32 bit ASF/Host Data Register 2 */
+ B28_Y2_DATA_REG_3 = 0x0e78,/* 32 bit ASF/Host Data Register 3 */
+ B28_Y2_DATA_REG_4 = 0x0e7c,/* 32 bit ASF/Host Data Register 4 */
+};
+
+/* Status BMU Registers (Yukon-2 only)*/
+enum {
+ STAT_CTRL = 0x0e80,/* 32 bit Status BMU Control Reg */
+ STAT_LAST_IDX = 0x0e84,/* 16 bit Status BMU Last Index */
+
+ STAT_LIST_ADDR_LO= 0x0e88,/* 32 bit Status List Start Addr (low) */
+ STAT_LIST_ADDR_HI= 0x0e8c,/* 32 bit Status List Start Addr (high) */
+ STAT_TXA1_RIDX = 0x0e90,/* 16 bit Status TxA1 Report Index Reg */
+ STAT_TXS1_RIDX = 0x0e92,/* 16 bit Status TxS1 Report Index Reg */
+ STAT_TXA2_RIDX = 0x0e94,/* 16 bit Status TxA2 Report Index Reg */
+ STAT_TXS2_RIDX = 0x0e96,/* 16 bit Status TxS2 Report Index Reg */
+ STAT_TX_IDX_TH = 0x0e98,/* 16 bit Status Tx Index Threshold Reg */
+ STAT_PUT_IDX = 0x0e9c,/* 16 bit Status Put Index Reg */
+
+/* FIFO Control/Status Registers (Yukon-2 only)*/
+ STAT_FIFO_WP = 0x0ea0,/* 8 bit Status FIFO Write Pointer Reg */
+ STAT_FIFO_RP = 0x0ea4,/* 8 bit Status FIFO Read Pointer Reg */
+ STAT_FIFO_RSP = 0x0ea6,/* 8 bit Status FIFO Read Shadow Ptr */
+ STAT_FIFO_LEVEL = 0x0ea8,/* 8 bit Status FIFO Level Reg */
+ STAT_FIFO_SHLVL = 0x0eaa,/* 8 bit Status FIFO Shadow Level Reg */
+ STAT_FIFO_WM = 0x0eac,/* 8 bit Status FIFO Watermark Reg */
+ STAT_FIFO_ISR_WM= 0x0ead,/* 8 bit Status FIFO ISR Watermark Reg */
+
+/* Level and ISR Timer Registers (Yukon-2 only)*/
+ STAT_LEV_TIMER_INI= 0x0eb0,/* 32 bit Level Timer Init. Value Reg */
+ STAT_LEV_TIMER_CNT= 0x0eb4,/* 32 bit Level Timer Counter Reg */
+ STAT_LEV_TIMER_CTRL= 0x0eb8,/* 8 bit Level Timer Control Reg */
+ STAT_LEV_TIMER_TEST= 0x0eb9,/* 8 bit Level Timer Test Reg */
+ STAT_TX_TIMER_INI = 0x0ec0,/* 32 bit Tx Timer Init. Value Reg */
+ STAT_TX_TIMER_CNT = 0x0ec4,/* 32 bit Tx Timer Counter Reg */
+ STAT_TX_TIMER_CTRL = 0x0ec8,/* 8 bit Tx Timer Control Reg */
+ STAT_TX_TIMER_TEST = 0x0ec9,/* 8 bit Tx Timer Test Reg */
+ STAT_ISR_TIMER_INI = 0x0ed0,/* 32 bit ISR Timer Init. Value Reg */
+ STAT_ISR_TIMER_CNT = 0x0ed4,/* 32 bit ISR Timer Counter Reg */
+ STAT_ISR_TIMER_CTRL= 0x0ed8,/* 8 bit ISR Timer Control Reg */
+ STAT_ISR_TIMER_TEST= 0x0ed9,/* 8 bit ISR Timer Test Reg */
+};
+
+enum {
+ LINKLED_OFF = 0x01,
+ LINKLED_ON = 0x02,
+ LINKLED_LINKSYNC_OFF = 0x04,
+ LINKLED_LINKSYNC_ON = 0x08,
+ LINKLED_BLINK_OFF = 0x10,
+ LINKLED_BLINK_ON = 0x20,
+};
+
+/* GMAC and GPHY Control Registers (YUKON only) */
+enum {
+ GMAC_CTRL = 0x0f00,/* 32 bit GMAC Control Reg */
+ GPHY_CTRL = 0x0f04,/* 32 bit GPHY Control Reg */
+ GMAC_IRQ_SRC = 0x0f08,/* 8 bit GMAC Interrupt Source Reg */
+ GMAC_IRQ_MSK = 0x0f0c,/* 8 bit GMAC Interrupt Mask Reg */
+ GMAC_LINK_CTRL = 0x0f10,/* 16 bit Link Control Reg */
+
+/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
+ WOL_CTRL_STAT = 0x0f20,/* 16 bit WOL Control/Status Reg */
+ WOL_MATCH_CTL = 0x0f22,/* 8 bit WOL Match Control Reg */
+ WOL_MATCH_RES = 0x0f23,/* 8 bit WOL Match Result Reg */
+ WOL_MAC_ADDR = 0x0f24,/* 32 bit WOL MAC Address */
+ WOL_PATT_RPTR = 0x0f2c,/* 8 bit WOL Pattern Read Pointer */
+
+/* WOL Pattern Length Registers (YUKON only) */
+ WOL_PATT_LEN_LO = 0x0f30,/* 32 bit WOL Pattern Length 3..0 */
+ WOL_PATT_LEN_HI = 0x0f34,/* 24 bit WOL Pattern Length 6..4 */
+
+/* WOL Pattern Counter Registers (YUKON only) */
+ WOL_PATT_CNT_0 = 0x0f38,/* 32 bit WOL Pattern Counter 3..0 */
+ WOL_PATT_CNT_4 = 0x0f3c,/* 24 bit WOL Pattern Counter 6..4 */
+};
+#define WOL_REGS(port, x) (x + (port)*0x80)
+
+enum {
+ WOL_PATT_RAM_1 = 0x1000,/* WOL Pattern RAM Link 1 */
+ WOL_PATT_RAM_2 = 0x1400,/* WOL Pattern RAM Link 2 */
+};
+#define WOL_PATT_RAM_BASE(port) (WOL_PATT_RAM_1 + (port)*0x400)
+
+enum {
+ BASE_GMAC_1 = 0x2800,/* GMAC 1 registers */
+ BASE_GMAC_2 = 0x3800,/* GMAC 2 registers */
+};
+
+/*
+ * Marvel-PHY Registers, indirect addressed over GMAC
+ */
+enum {
+ PHY_MARV_CTRL = 0x00,/* 16 bit r/w PHY Control Register */
+ PHY_MARV_STAT = 0x01,/* 16 bit r/o PHY Status Register */
+ PHY_MARV_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */
+ PHY_MARV_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */
+ PHY_MARV_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */
+ PHY_MARV_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */
+ PHY_MARV_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */
+ PHY_MARV_NEPG = 0x07,/* 16 bit r/w Next Page Register */
+ PHY_MARV_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */
+ /* Marvel-specific registers */
+ PHY_MARV_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */
+ PHY_MARV_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */
+ PHY_MARV_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */
+ PHY_MARV_PHY_CTRL = 0x10,/* 16 bit r/w PHY Specific Ctrl Reg */
+ PHY_MARV_PHY_STAT = 0x11,/* 16 bit r/o PHY Specific Stat Reg */
+ PHY_MARV_INT_MASK = 0x12,/* 16 bit r/w Interrupt Mask Reg */
+ PHY_MARV_INT_STAT = 0x13,/* 16 bit r/o Interrupt Status Reg */
+ PHY_MARV_EXT_CTRL = 0x14,/* 16 bit r/w Ext. PHY Specific Ctrl */
+ PHY_MARV_RXE_CNT = 0x15,/* 16 bit r/w Receive Error Counter */
+ PHY_MARV_EXT_ADR = 0x16,/* 16 bit r/w Ext. Ad. for Cable Diag. */
+ PHY_MARV_PORT_IRQ = 0x17,/* 16 bit r/o Port 0 IRQ (88E1111 only) */
+ PHY_MARV_LED_CTRL = 0x18,/* 16 bit r/w LED Control Reg */
+ PHY_MARV_LED_OVER = 0x19,/* 16 bit r/w Manual LED Override Reg */
+ PHY_MARV_EXT_CTRL_2 = 0x1a,/* 16 bit r/w Ext. PHY Specific Ctrl 2 */
+ PHY_MARV_EXT_P_STAT = 0x1b,/* 16 bit r/w Ext. PHY Spec. Stat Reg */
+ PHY_MARV_CABLE_DIAG = 0x1c,/* 16 bit r/o Cable Diagnostic Reg */
+ PHY_MARV_PAGE_ADDR = 0x1d,/* 16 bit r/w Extended Page Address Reg */
+ PHY_MARV_PAGE_DATA = 0x1e,/* 16 bit r/w Extended Page Data Reg */
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+ PHY_MARV_FE_LED_PAR = 0x16,/* 16 bit r/w LED Parallel Select Reg. */
+ PHY_MARV_FE_LED_SER = 0x17,/* 16 bit r/w LED Stream Select S. LED */
+ PHY_MARV_FE_VCT_TX = 0x1a,/* 16 bit r/w VCT Reg. for TXP/N Pins */
+ PHY_MARV_FE_VCT_RX = 0x1b,/* 16 bit r/o VCT Reg. for RXP/N Pins */
+ PHY_MARV_FE_SPEC_2 = 0x1c,/* 16 bit r/w Specific Control Reg. 2 */
+};
+
+enum {
+ PHY_CT_RESET = 1<<15, /* Bit 15: (sc) clear all PHY related regs */
+ PHY_CT_LOOP = 1<<14, /* Bit 14: enable Loopback over PHY */
+ PHY_CT_SPS_LSB = 1<<13, /* Bit 13: Speed select, lower bit */
+ PHY_CT_ANE = 1<<12, /* Bit 12: Auto-Negotiation Enabled */
+ PHY_CT_PDOWN = 1<<11, /* Bit 11: Power Down Mode */
+ PHY_CT_ISOL = 1<<10, /* Bit 10: Isolate Mode */
+ PHY_CT_RE_CFG = 1<<9, /* Bit 9: (sc) Restart Auto-Negotiation */
+ PHY_CT_DUP_MD = 1<<8, /* Bit 8: Duplex Mode */
+ PHY_CT_COL_TST = 1<<7, /* Bit 7: Collision Test enabled */
+ PHY_CT_SPS_MSB = 1<<6, /* Bit 6: Speed select, upper bit */
+};
+
+enum {
+ PHY_CT_SP1000 = PHY_CT_SPS_MSB, /* enable speed of 1000 Mbps */
+ PHY_CT_SP100 = PHY_CT_SPS_LSB, /* enable speed of 100 Mbps */
+ PHY_CT_SP10 = 0, /* enable speed of 10 Mbps */
+};
+
+enum {
+ PHY_ST_EXT_ST = 1<<8, /* Bit 8: Extended Status Present */
+
+ PHY_ST_PRE_SUP = 1<<6, /* Bit 6: Preamble Suppression */
+ PHY_ST_AN_OVER = 1<<5, /* Bit 5: Auto-Negotiation Over */
+ PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occured */
+ PHY_ST_AN_CAP = 1<<3, /* Bit 3: Auto-Negotiation Capability */
+ PHY_ST_LSYNC = 1<<2, /* Bit 2: Link Synchronized */
+ PHY_ST_JAB_DET = 1<<1, /* Bit 1: Jabber Detected */
+ PHY_ST_EXT_REG = 1<<0, /* Bit 0: Extended Register available */
+};
+
+enum {
+ PHY_I1_OUI_MSK = 0x3f<<10, /* Bit 15..10: Organization Unique ID */
+ PHY_I1_MOD_NUM = 0x3f<<4, /* Bit 9.. 4: Model Number */
+ PHY_I1_REV_MSK = 0xf, /* Bit 3.. 0: Revision Number */
+};
+
+/* different Marvell PHY Ids */
+enum {
+ PHY_MARV_ID0_VAL= 0x0141, /* Marvell Unique Identifier */
+
+ PHY_BCOM_ID1_A1 = 0x6041,
+ PHY_BCOM_ID1_B2 = 0x6043,
+ PHY_BCOM_ID1_C0 = 0x6044,
+ PHY_BCOM_ID1_C5 = 0x6047,
+
+ PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */
+ PHY_MARV_ID1_B2 = 0x0C25, /* Yukon-Plus (PHY 88E1011) */
+ PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */
+ PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */
+ PHY_MARV_ID1_FE = 0x0C83, /* Yukon-FE (PHY 88E3082 Rev.A1) */
+ PHY_MARV_ID1_ECU= 0x0CB0, /* Yukon-ECU (PHY 88E1149 Rev.B2?) */
+};
+
+/* Advertisement register bits */
+enum {
+ PHY_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */
+ PHY_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */
+ PHY_AN_RF = 1<<13, /* Bit 13: Remote Fault Bits */
+
+ PHY_AN_PAUSE_ASYM = 1<<11,/* Bit 11: Try for asymmetric */
+ PHY_AN_PAUSE_CAP = 1<<10, /* Bit 10: Try for pause */
+ PHY_AN_100BASE4 = 1<<9, /* Bit 9: Try for 100mbps 4k packets */
+ PHY_AN_100FULL = 1<<8, /* Bit 8: Try for 100mbps full-duplex */
+ PHY_AN_100HALF = 1<<7, /* Bit 7: Try for 100mbps half-duplex */
+ PHY_AN_10FULL = 1<<6, /* Bit 6: Try for 10mbps full-duplex */
+ PHY_AN_10HALF = 1<<5, /* Bit 5: Try for 10mbps half-duplex */
+ PHY_AN_CSMA = 1<<0, /* Bit 0: Only selector supported */
+ PHY_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/
+ PHY_AN_FULL = PHY_AN_100FULL | PHY_AN_10FULL | PHY_AN_CSMA,
+ PHY_AN_ALL = PHY_AN_10HALF | PHY_AN_10FULL |
+ PHY_AN_100HALF | PHY_AN_100FULL,
+};
+
+/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+enum {
+ PHY_B_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */
+ PHY_B_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */
+ PHY_B_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */
+ PHY_B_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status */
+ PHY_B_1000S_LP_FD = 1<<11, /* Bit 11: Link Partner can FD */
+ PHY_B_1000S_LP_HD = 1<<10, /* Bit 10: Link Partner can HD */
+ /* Bit 9..8: reserved */
+ PHY_B_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */
+};
+
+/** Marvell-Specific */
+enum {
+ PHY_M_AN_NXT_PG = 1<<15, /* Request Next Page */
+ PHY_M_AN_ACK = 1<<14, /* (ro) Acknowledge Received */
+ PHY_M_AN_RF = 1<<13, /* Remote Fault */
+
+ PHY_M_AN_ASP = 1<<11, /* Asymmetric Pause */
+ PHY_M_AN_PC = 1<<10, /* MAC Pause implemented */
+ PHY_M_AN_100_T4 = 1<<9, /* Not cap. 100Base-T4 (always 0) */
+ PHY_M_AN_100_FD = 1<<8, /* Advertise 100Base-TX Full Duplex */
+ PHY_M_AN_100_HD = 1<<7, /* Advertise 100Base-TX Half Duplex */
+ PHY_M_AN_10_FD = 1<<6, /* Advertise 10Base-TX Full Duplex */
+ PHY_M_AN_10_HD = 1<<5, /* Advertise 10Base-TX Half Duplex */
+ PHY_M_AN_SEL_MSK =0x1f<<4, /* Bit 4.. 0: Selector Field Mask */
+};
+
+/* special defines for FIBER (88E1011S only) */
+enum {
+ PHY_M_AN_ASP_X = 1<<8, /* Asymmetric Pause */
+ PHY_M_AN_PC_X = 1<<7, /* MAC Pause implemented */
+ PHY_M_AN_1000X_AHD = 1<<6, /* Advertise 10000Base-X Half Duplex */
+ PHY_M_AN_1000X_AFD = 1<<5, /* Advertise 10000Base-X Full Duplex */
+};
+
+/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
+enum {
+ PHY_M_P_NO_PAUSE_X = 0<<7,/* Bit 8.. 7: no Pause Mode */
+ PHY_M_P_SYM_MD_X = 1<<7, /* Bit 8.. 7: symmetric Pause Mode */
+ PHY_M_P_ASYM_MD_X = 2<<7,/* Bit 8.. 7: asymmetric Pause Mode */
+ PHY_M_P_BOTH_MD_X = 3<<7,/* Bit 8.. 7: both Pause Mode */
+};
+
+/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
+enum {
+ PHY_M_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */
+ PHY_M_1000C_MSE = 1<<12, /* Manual Master/Slave Enable */
+ PHY_M_1000C_MSC = 1<<11, /* M/S Configuration (1=Master) */
+ PHY_M_1000C_MPD = 1<<10, /* Multi-Port Device */
+ PHY_M_1000C_AFD = 1<<9, /* Advertise Full Duplex */
+ PHY_M_1000C_AHD = 1<<8, /* Advertise Half Duplex */
+};
+
+/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/
+enum {
+ PHY_M_PC_TX_FFD_MSK = 3<<14,/* Bit 15..14: Tx FIFO Depth Mask */
+ PHY_M_PC_RX_FFD_MSK = 3<<12,/* Bit 13..12: Rx FIFO Depth Mask */
+ PHY_M_PC_ASS_CRS_TX = 1<<11, /* Assert CRS on Transmit */
+ PHY_M_PC_FL_GOOD = 1<<10, /* Force Link Good */
+ PHY_M_PC_EN_DET_MSK = 3<<8,/* Bit 9.. 8: Energy Detect Mask */
+ PHY_M_PC_ENA_EXT_D = 1<<7, /* Enable Ext. Distance (10BT) */
+ PHY_M_PC_MDIX_MSK = 3<<5,/* Bit 6.. 5: MDI/MDIX Config. Mask */
+ PHY_M_PC_DIS_125CLK = 1<<4, /* Disable 125 CLK */
+ PHY_M_PC_MAC_POW_UP = 1<<3, /* MAC Power up */
+ PHY_M_PC_SQE_T_ENA = 1<<2, /* SQE Test Enabled */
+ PHY_M_PC_POL_R_DIS = 1<<1, /* Polarity Reversal Disabled */
+ PHY_M_PC_DIS_JABBER = 1<<0, /* Disable Jabber */
+};
+
+enum {
+ PHY_M_PC_EN_DET = 2<<8, /* Energy Detect (Mode 1) */
+ PHY_M_PC_EN_DET_PLUS = 3<<8, /* Energy Detect Plus (Mode 2) */
+};
+
+#define PHY_M_PC_MDI_XMODE(x) (((u16)(x)<<5) & PHY_M_PC_MDIX_MSK)
+
+enum {
+ PHY_M_PC_MAN_MDI = 0, /* 00 = Manual MDI configuration */
+ PHY_M_PC_MAN_MDIX = 1, /* 01 = Manual MDIX configuration */
+ PHY_M_PC_ENA_AUTO = 3, /* 11 = Enable Automatic Crossover */
+};
+
+/* for Yukon-EC Ultra Gigabit Ethernet PHY (88E1149 only) */
+enum {
+ PHY_M_PC_COP_TX_DIS = 1<<3, /* Copper Transmitter Disable */
+ PHY_M_PC_POW_D_ENA = 1<<2, /* Power Down Enable */
+};
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+enum {
+ PHY_M_PC_ENA_DTE_DT = 1<<15, /* Enable Data Terminal Equ. (DTE) Detect */
+ PHY_M_PC_ENA_ENE_DT = 1<<14, /* Enable Energy Detect (sense & pulse) */
+ PHY_M_PC_DIS_NLP_CK = 1<<13, /* Disable Normal Link Puls (NLP) Check */
+ PHY_M_PC_ENA_LIP_NP = 1<<12, /* Enable Link Partner Next Page Reg. */
+ PHY_M_PC_DIS_NLP_GN = 1<<11, /* Disable Normal Link Puls Generation */
+
+ PHY_M_PC_DIS_SCRAMB = 1<<9, /* Disable Scrambler */
+ PHY_M_PC_DIS_FEFI = 1<<8, /* Disable Far End Fault Indic. (FEFI) */
+
+ PHY_M_PC_SH_TP_SEL = 1<<6, /* Shielded Twisted Pair Select */
+ PHY_M_PC_RX_FD_MSK = 3<<2,/* Bit 3.. 2: Rx FIFO Depth Mask */
+};
+
+/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/
+enum {
+ PHY_M_PS_SPEED_MSK = 3<<14, /* Bit 15..14: Speed Mask */
+ PHY_M_PS_SPEED_1000 = 1<<15, /* 10 = 1000 Mbps */
+ PHY_M_PS_SPEED_100 = 1<<14, /* 01 = 100 Mbps */
+ PHY_M_PS_SPEED_10 = 0, /* 00 = 10 Mbps */
+ PHY_M_PS_FULL_DUP = 1<<13, /* Full Duplex */
+ PHY_M_PS_PAGE_REC = 1<<12, /* Page Received */
+ PHY_M_PS_SPDUP_RES = 1<<11, /* Speed & Duplex Resolved */
+ PHY_M_PS_LINK_UP = 1<<10, /* Link Up */
+ PHY_M_PS_CABLE_MSK = 7<<7, /* Bit 9.. 7: Cable Length Mask */
+ PHY_M_PS_MDI_X_STAT = 1<<6, /* MDI Crossover Stat (1=MDIX) */
+ PHY_M_PS_DOWNS_STAT = 1<<5, /* Downshift Status (1=downsh.) */
+ PHY_M_PS_ENDET_STAT = 1<<4, /* Energy Detect Status (1=act) */
+ PHY_M_PS_TX_P_EN = 1<<3, /* Tx Pause Enabled */
+ PHY_M_PS_RX_P_EN = 1<<2, /* Rx Pause Enabled */
+ PHY_M_PS_POL_REV = 1<<1, /* Polarity Reversed */
+ PHY_M_PS_JABBER = 1<<0, /* Jabber */
+};
+
+#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+enum {
+ PHY_M_PS_DTE_DETECT = 1<<15, /* Data Terminal Equipment (DTE) Detected */
+ PHY_M_PS_RES_SPEED = 1<<14, /* Resolved Speed (1=100 Mbps, 0=10 Mbps */
+};
+
+enum {
+ PHY_M_IS_AN_ERROR = 1<<15, /* Auto-Negotiation Error */
+ PHY_M_IS_LSP_CHANGE = 1<<14, /* Link Speed Changed */
+ PHY_M_IS_DUP_CHANGE = 1<<13, /* Duplex Mode Changed */
+ PHY_M_IS_AN_PR = 1<<12, /* Page Received */
+ PHY_M_IS_AN_COMPL = 1<<11, /* Auto-Negotiation Completed */
+ PHY_M_IS_LST_CHANGE = 1<<10, /* Link Status Changed */
+ PHY_M_IS_SYMB_ERROR = 1<<9, /* Symbol Error */
+ PHY_M_IS_FALSE_CARR = 1<<8, /* False Carrier */
+ PHY_M_IS_FIFO_ERROR = 1<<7, /* FIFO Overflow/Underrun Error */
+ PHY_M_IS_MDI_CHANGE = 1<<6, /* MDI Crossover Changed */
+ PHY_M_IS_DOWNSH_DET = 1<<5, /* Downshift Detected */
+ PHY_M_IS_END_CHANGE = 1<<4, /* Energy Detect Changed */
+
+ PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */
+ PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */
+ PHY_M_IS_JABBER = 1<<0, /* Jabber */
+
+ PHY_M_DEF_MSK = PHY_M_IS_LSP_CHANGE | PHY_M_IS_LST_CHANGE
+ | PHY_M_IS_DUP_CHANGE,
+ PHY_M_AN_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL,
+};
+
+
+/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/
+enum {
+ PHY_M_EC_ENA_BC_EXT = 1<<15, /* Enable Block Carr. Ext. (88E1111 only) */
+ PHY_M_EC_ENA_LIN_LB = 1<<14, /* Enable Line Loopback (88E1111 only) */
+
+ PHY_M_EC_DIS_LINK_P = 1<<12, /* Disable Link Pulses (88E1111 only) */
+ PHY_M_EC_M_DSC_MSK = 3<<10, /* Bit 11..10: Master Downshift Counter */
+ /* (88E1011 only) */
+ PHY_M_EC_S_DSC_MSK = 3<<8,/* Bit 9.. 8: Slave Downshift Counter */
+ /* (88E1011 only) */
+ PHY_M_EC_M_DSC_MSK2 = 7<<9,/* Bit 11.. 9: Master Downshift Counter */
+ /* (88E1111 only) */
+ PHY_M_EC_DOWN_S_ENA = 1<<8, /* Downshift Enable (88E1111 only) */
+ /* !!! Errata in spec. (1 = disable) */
+ PHY_M_EC_RX_TIM_CT = 1<<7, /* RGMII Rx Timing Control*/
+ PHY_M_EC_MAC_S_MSK = 7<<4,/* Bit 6.. 4: Def. MAC interface speed */
+ PHY_M_EC_FIB_AN_ENA = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */
+ PHY_M_EC_DTE_D_ENA = 1<<2, /* DTE Detect Enable (88E1111 only) */
+ PHY_M_EC_TX_TIM_CT = 1<<1, /* RGMII Tx Timing Control */
+ PHY_M_EC_TRANS_DIS = 1<<0, /* Transmitter Disable (88E1111 only) */};
+
+#define PHY_M_EC_M_DSC(x) ((u16)(x)<<10 & PHY_M_EC_M_DSC_MSK)
+ /* 00=1x; 01=2x; 10=3x; 11=4x */
+#define PHY_M_EC_S_DSC(x) ((u16)(x)<<8 & PHY_M_EC_S_DSC_MSK)
+ /* 00=dis; 01=1x; 10=2x; 11=3x */
+#define PHY_M_EC_DSC_2(x) ((u16)(x)<<9 & PHY_M_EC_M_DSC_MSK2)
+ /* 000=1x; 001=2x; 010=3x; 011=4x */
+#define PHY_M_EC_MAC_S(x) ((u16)(x)<<4 & PHY_M_EC_MAC_S_MSK)
+ /* 01X=0; 110=2.5; 111=25 (MHz) */
+
+/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
+enum {
+ PHY_M_PC_DIS_LINK_Pa = 1<<15,/* Disable Link Pulses */
+ PHY_M_PC_DSC_MSK = 7<<12,/* Bit 14..12: Downshift Counter */
+ PHY_M_PC_DOWN_S_ENA = 1<<11,/* Downshift Enable */
+};
+/* !!! Errata in spec. (1 = disable) */
+
+#define PHY_M_PC_DSC(x) (((u16)(x)<<12) & PHY_M_PC_DSC_MSK)
+ /* 100=5x; 101=6x; 110=7x; 111=8x */
+enum {
+ MAC_TX_CLK_0_MHZ = 2,
+ MAC_TX_CLK_2_5_MHZ = 6,
+ MAC_TX_CLK_25_MHZ = 7,
+};
+
+/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/
+enum {
+ PHY_M_LEDC_DIS_LED = 1<<15, /* Disable LED */
+ PHY_M_LEDC_PULS_MSK = 7<<12,/* Bit 14..12: Pulse Stretch Mask */
+ PHY_M_LEDC_F_INT = 1<<11, /* Force Interrupt */
+ PHY_M_LEDC_BL_R_MSK = 7<<8,/* Bit 10.. 8: Blink Rate Mask */
+ PHY_M_LEDC_DP_C_LSB = 1<<7, /* Duplex Control (LSB, 88E1111 only) */
+ PHY_M_LEDC_TX_C_LSB = 1<<6, /* Tx Control (LSB, 88E1111 only) */
+ PHY_M_LEDC_LK_C_MSK = 7<<3,/* Bit 5.. 3: Link Control Mask */
+ /* (88E1111 only) */
+};
+
+enum {
+ PHY_M_LEDC_LINK_MSK = 3<<3,/* Bit 4.. 3: Link Control Mask */
+ /* (88E1011 only) */
+ PHY_M_LEDC_DP_CTRL = 1<<2, /* Duplex Control */
+ PHY_M_LEDC_DP_C_MSB = 1<<2, /* Duplex Control (MSB, 88E1111 only) */
+ PHY_M_LEDC_RX_CTRL = 1<<1, /* Rx Activity / Link */
+ PHY_M_LEDC_TX_CTRL = 1<<0, /* Tx Activity / Link */
+ PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */
+};
+
+#define PHY_M_LED_PULS_DUR(x) (((u16)(x)<<12) & PHY_M_LEDC_PULS_MSK)
+
+/***** PHY_MARV_PHY_STAT (page 3)16 bit r/w Polarity Control Reg. *****/
+enum {
+ PHY_M_POLC_LS1M_MSK = 0xf<<12, /* Bit 15..12: LOS,STAT1 Mix % Mask */
+ PHY_M_POLC_IS0M_MSK = 0xf<<8, /* Bit 11.. 8: INIT,STAT0 Mix % Mask */
+ PHY_M_POLC_LOS_MSK = 0x3<<6, /* Bit 7.. 6: LOS Pol. Ctrl. Mask */
+ PHY_M_POLC_INIT_MSK = 0x3<<4, /* Bit 5.. 4: INIT Pol. Ctrl. Mask */
+ PHY_M_POLC_STA1_MSK = 0x3<<2, /* Bit 3.. 2: STAT1 Pol. Ctrl. Mask */
+ PHY_M_POLC_STA0_MSK = 0x3, /* Bit 1.. 0: STAT0 Pol. Ctrl. Mask */
+};
+
+#define PHY_M_POLC_LS1_P_MIX(x) (((x)<<12) & PHY_M_POLC_LS1M_MSK)
+#define PHY_M_POLC_IS0_P_MIX(x) (((x)<<8) & PHY_M_POLC_IS0M_MSK)
+#define PHY_M_POLC_LOS_CTRL(x) (((x)<<6) & PHY_M_POLC_LOS_MSK)
+#define PHY_M_POLC_INIT_CTRL(x) (((x)<<4) & PHY_M_POLC_INIT_MSK)
+#define PHY_M_POLC_STA1_CTRL(x) (((x)<<2) & PHY_M_POLC_STA1_MSK)
+#define PHY_M_POLC_STA0_CTRL(x) (((x)<<0) & PHY_M_POLC_STA0_MSK)
+
+enum {
+ PULS_NO_STR = 0,/* no pulse stretching */
+ PULS_21MS = 1,/* 21 ms to 42 ms */
+ PULS_42MS = 2,/* 42 ms to 84 ms */
+ PULS_84MS = 3,/* 84 ms to 170 ms */
+ PULS_170MS = 4,/* 170 ms to 340 ms */
+ PULS_340MS = 5,/* 340 ms to 670 ms */
+ PULS_670MS = 6,/* 670 ms to 1.3 s */
+ PULS_1300MS = 7,/* 1.3 s to 2.7 s */
+};
+
+#define PHY_M_LED_BLINK_RT(x) (((u16)(x)<<8) & PHY_M_LEDC_BL_R_MSK)
+
+enum {
+ BLINK_42MS = 0,/* 42 ms */
+ BLINK_84MS = 1,/* 84 ms */
+ BLINK_170MS = 2,/* 170 ms */
+ BLINK_340MS = 3,/* 340 ms */
+ BLINK_670MS = 4,/* 670 ms */
+};
+
+/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/
+#define PHY_M_LED_MO_SGMII(x) ((x)<<14) /* Bit 15..14: SGMII AN Timer */
+
+#define PHY_M_LED_MO_DUP(x) ((x)<<10) /* Bit 11..10: Duplex */
+#define PHY_M_LED_MO_10(x) ((x)<<8) /* Bit 9.. 8: Link 10 */
+#define PHY_M_LED_MO_100(x) ((x)<<6) /* Bit 7.. 6: Link 100 */
+#define PHY_M_LED_MO_1000(x) ((x)<<4) /* Bit 5.. 4: Link 1000 */
+#define PHY_M_LED_MO_RX(x) ((x)<<2) /* Bit 3.. 2: Rx */
+#define PHY_M_LED_MO_TX(x) ((x)<<0) /* Bit 1.. 0: Tx */
+
+enum led_mode {
+ MO_LED_NORM = 0,
+ MO_LED_BLINK = 1,
+ MO_LED_OFF = 2,
+ MO_LED_ON = 3,
+};
+
+/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/
+enum {
+ PHY_M_EC2_FI_IMPED = 1<<6, /* Fiber Input Impedance */
+ PHY_M_EC2_FO_IMPED = 1<<5, /* Fiber Output Impedance */
+ PHY_M_EC2_FO_M_CLK = 1<<4, /* Fiber Mode Clock Enable */
+ PHY_M_EC2_FO_BOOST = 1<<3, /* Fiber Output Boost */
+ PHY_M_EC2_FO_AM_MSK = 7,/* Bit 2.. 0: Fiber Output Amplitude */
+};
+
+/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/
+enum {
+ PHY_M_FC_AUTO_SEL = 1<<15, /* Fiber/Copper Auto Sel. Dis. */
+ PHY_M_FC_AN_REG_ACC = 1<<14, /* Fiber/Copper AN Reg. Access */
+ PHY_M_FC_RESOLUTION = 1<<13, /* Fiber/Copper Resolution */
+ PHY_M_SER_IF_AN_BP = 1<<12, /* Ser. IF AN Bypass Enable */
+ PHY_M_SER_IF_BP_ST = 1<<11, /* Ser. IF AN Bypass Status */
+ PHY_M_IRQ_POLARITY = 1<<10, /* IRQ polarity */
+ PHY_M_DIS_AUT_MED = 1<<9, /* Disable Aut. Medium Reg. Selection */
+ /* (88E1111 only) */
+
+ PHY_M_UNDOC1 = 1<<7, /* undocumented bit !! */
+ PHY_M_DTE_POW_STAT = 1<<4, /* DTE Power Status (88E1111 only) */
+ PHY_M_MODE_MASK = 0xf, /* Bit 3.. 0: copy of HWCFG MODE[3:0] */
+};
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+/***** PHY_MARV_FE_LED_PAR 16 bit r/w LED Parallel Select Reg. *****/
+ /* Bit 15..12: reserved (used internally) */
+enum {
+ PHY_M_FELP_LED2_MSK = 0xf<<8, /* Bit 11.. 8: LED2 Mask (LINK) */
+ PHY_M_FELP_LED1_MSK = 0xf<<4, /* Bit 7.. 4: LED1 Mask (ACT) */
+ PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */
+};
+
+#define PHY_M_FELP_LED2_CTRL(x) (((u16)(x)<<8) & PHY_M_FELP_LED2_MSK)
+#define PHY_M_FELP_LED1_CTRL(x) (((u16)(x)<<4) & PHY_M_FELP_LED1_MSK)
+#define PHY_M_FELP_LED0_CTRL(x) (((u16)(x)<<0) & PHY_M_FELP_LED0_MSK)
+
+enum {
+ LED_PAR_CTRL_COLX = 0x00,
+ LED_PAR_CTRL_ERROR = 0x01,
+ LED_PAR_CTRL_DUPLEX = 0x02,
+ LED_PAR_CTRL_DP_COL = 0x03,
+ LED_PAR_CTRL_SPEED = 0x04,
+ LED_PAR_CTRL_LINK = 0x05,
+ LED_PAR_CTRL_TX = 0x06,
+ LED_PAR_CTRL_RX = 0x07,
+ LED_PAR_CTRL_ACT = 0x08,
+ LED_PAR_CTRL_LNK_RX = 0x09,
+ LED_PAR_CTRL_LNK_AC = 0x0a,
+ LED_PAR_CTRL_ACT_BL = 0x0b,
+ LED_PAR_CTRL_TX_BL = 0x0c,
+ LED_PAR_CTRL_RX_BL = 0x0d,
+ LED_PAR_CTRL_COL_BL = 0x0e,
+ LED_PAR_CTRL_INACT = 0x0f
+};
+
+/*****,PHY_MARV_FE_SPEC_2 16 bit r/w Specific Control Reg. 2 *****/
+enum {
+ PHY_M_FESC_DIS_WAIT = 1<<2, /* Disable TDR Waiting Period */
+ PHY_M_FESC_ENA_MCLK = 1<<1, /* Enable MAC Rx Clock in sleep mode */
+ PHY_M_FESC_SEL_CL_A = 1<<0, /* Select Class A driver (100B-TX) */
+};
+
+/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
+/***** PHY_MARV_PHY_CTRL (page 1) 16 bit r/w Fiber Specific Ctrl *****/
+enum {
+ PHY_M_FIB_FORCE_LNK = 1<<10,/* Force Link Good */
+ PHY_M_FIB_SIGD_POL = 1<<9, /* SIGDET Polarity */
+ PHY_M_FIB_TX_DIS = 1<<3, /* Transmitter Disable */
+};
+
+/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
+/***** PHY_MARV_PHY_CTRL (page 2) 16 bit r/w MAC Specific Ctrl *****/
+enum {
+ PHY_M_MAC_MD_MSK = 7<<7, /* Bit 9.. 7: Mode Select Mask */
+ PHY_M_MAC_GMIF_PUP = 1<<3, /* GMII Power Up (88E1149 only) */
+ PHY_M_MAC_MD_AUTO = 3,/* Auto Copper/1000Base-X */
+ PHY_M_MAC_MD_COPPER = 5,/* Copper only */
+ PHY_M_MAC_MD_1000BX = 7,/* 1000Base-X only */
+};
+#define PHY_M_MAC_MODE_SEL(x) (((x)<<7) & PHY_M_MAC_MD_MSK)
+
+/***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/
+enum {
+ PHY_M_LEDC_LOS_MSK = 0xf<<12,/* Bit 15..12: LOS LED Ctrl. Mask */
+ PHY_M_LEDC_INIT_MSK = 0xf<<8, /* Bit 11.. 8: INIT LED Ctrl. Mask */
+ PHY_M_LEDC_STA1_MSK = 0xf<<4,/* Bit 7.. 4: STAT1 LED Ctrl. Mask */
+ PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */
+};
+
+#define PHY_M_LEDC_LOS_CTRL(x) (((x)<<12) & PHY_M_LEDC_LOS_MSK)
+#define PHY_M_LEDC_INIT_CTRL(x) (((x)<<8) & PHY_M_LEDC_INIT_MSK)
+#define PHY_M_LEDC_STA1_CTRL(x) (((x)<<4) & PHY_M_LEDC_STA1_MSK)
+#define PHY_M_LEDC_STA0_CTRL(x) (((x)<<0) & PHY_M_LEDC_STA0_MSK)
+
+/* GMAC registers */
+/* Port Registers */
+enum {
+ GM_GP_STAT = 0x0000, /* 16 bit r/o General Purpose Status */
+ GM_GP_CTRL = 0x0004, /* 16 bit r/w General Purpose Control */
+ GM_TX_CTRL = 0x0008, /* 16 bit r/w Transmit Control Reg. */
+ GM_RX_CTRL = 0x000c, /* 16 bit r/w Receive Control Reg. */
+ GM_TX_FLOW_CTRL = 0x0010, /* 16 bit r/w Transmit Flow-Control */
+ GM_TX_PARAM = 0x0014, /* 16 bit r/w Transmit Parameter Reg. */
+ GM_SERIAL_MODE = 0x0018, /* 16 bit r/w Serial Mode Register */
+/* Source Address Registers */
+ GM_SRC_ADDR_1L = 0x001c, /* 16 bit r/w Source Address 1 (low) */
+ GM_SRC_ADDR_1M = 0x0020, /* 16 bit r/w Source Address 1 (middle) */
+ GM_SRC_ADDR_1H = 0x0024, /* 16 bit r/w Source Address 1 (high) */
+ GM_SRC_ADDR_2L = 0x0028, /* 16 bit r/w Source Address 2 (low) */
+ GM_SRC_ADDR_2M = 0x002c, /* 16 bit r/w Source Address 2 (middle) */
+ GM_SRC_ADDR_2H = 0x0030, /* 16 bit r/w Source Address 2 (high) */
+
+/* Multicast Address Hash Registers */
+ GM_MC_ADDR_H1 = 0x0034, /* 16 bit r/w Multicast Address Hash 1 */
+ GM_MC_ADDR_H2 = 0x0038, /* 16 bit r/w Multicast Address Hash 2 */
+ GM_MC_ADDR_H3 = 0x003c, /* 16 bit r/w Multicast Address Hash 3 */
+ GM_MC_ADDR_H4 = 0x0040, /* 16 bit r/w Multicast Address Hash 4 */
+
+/* Interrupt Source Registers */
+ GM_TX_IRQ_SRC = 0x0044, /* 16 bit r/o Tx Overflow IRQ Source */
+ GM_RX_IRQ_SRC = 0x0048, /* 16 bit r/o Rx Overflow IRQ Source */
+ GM_TR_IRQ_SRC = 0x004c, /* 16 bit r/o Tx/Rx Over. IRQ Source */
+
+/* Interrupt Mask Registers */
+ GM_TX_IRQ_MSK = 0x0050, /* 16 bit r/w Tx Overflow IRQ Mask */
+ GM_RX_IRQ_MSK = 0x0054, /* 16 bit r/w Rx Overflow IRQ Mask */
+ GM_TR_IRQ_MSK = 0x0058, /* 16 bit r/w Tx/Rx Over. IRQ Mask */
+
+/* Serial Management Interface (SMI) Registers */
+ GM_SMI_CTRL = 0x0080, /* 16 bit r/w SMI Control Register */
+ GM_SMI_DATA = 0x0084, /* 16 bit r/w SMI Data Register */
+ GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */
+/* MIB Counters */
+ GM_MIB_CNT_BASE = 0x0100, /* Base Address of MIB Counters */
+ GM_MIB_CNT_END = 0x025C, /* Last MIB counter */
+};
+
+
+/*
+ * MIB Counters base address definitions (low word) -
+ * use offset 4 for access to high word (32 bit r/o)
+ */
+enum {
+ GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */
+ GM_RXF_BC_OK = GM_MIB_CNT_BASE + 8, /* Broadcast Frames Received OK */
+ GM_RXF_MPAUSE = GM_MIB_CNT_BASE + 16, /* Pause MAC Ctrl Frames Received */
+ GM_RXF_MC_OK = GM_MIB_CNT_BASE + 24, /* Multicast Frames Received OK */
+ GM_RXF_FCS_ERR = GM_MIB_CNT_BASE + 32, /* Rx Frame Check Seq. Error */
+
+ GM_RXO_OK_LO = GM_MIB_CNT_BASE + 48, /* Octets Received OK Low */
+ GM_RXO_OK_HI = GM_MIB_CNT_BASE + 56, /* Octets Received OK High */
+ GM_RXO_ERR_LO = GM_MIB_CNT_BASE + 64, /* Octets Received Invalid Low */
+ GM_RXO_ERR_HI = GM_MIB_CNT_BASE + 72, /* Octets Received Invalid High */
+ GM_RXF_SHT = GM_MIB_CNT_BASE + 80, /* Frames <64 Byte Received OK */
+ GM_RXE_FRAG = GM_MIB_CNT_BASE + 88, /* Frames <64 Byte Received with FCS Err */
+ GM_RXF_64B = GM_MIB_CNT_BASE + 96, /* 64 Byte Rx Frame */
+ GM_RXF_127B = GM_MIB_CNT_BASE + 104,/* 65-127 Byte Rx Frame */
+ GM_RXF_255B = GM_MIB_CNT_BASE + 112,/* 128-255 Byte Rx Frame */
+ GM_RXF_511B = GM_MIB_CNT_BASE + 120,/* 256-511 Byte Rx Frame */
+ GM_RXF_1023B = GM_MIB_CNT_BASE + 128,/* 512-1023 Byte Rx Frame */
+ GM_RXF_1518B = GM_MIB_CNT_BASE + 136,/* 1024-1518 Byte Rx Frame */
+ GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144,/* 1519-MaxSize Byte Rx Frame */
+ GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152,/* Rx Frame too Long Error */
+ GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160,/* Rx Jabber Packet Frame */
+
+ GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176,/* Rx FIFO overflow Event */
+ GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192,/* Unicast Frames Xmitted OK */
+ GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200,/* Broadcast Frames Xmitted OK */
+ GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208,/* Pause MAC Ctrl Frames Xmitted */
+ GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216,/* Multicast Frames Xmitted OK */
+ GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224,/* Octets Transmitted OK Low */
+ GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232,/* Octets Transmitted OK High */
+ GM_TXF_64B = GM_MIB_CNT_BASE + 240,/* 64 Byte Tx Frame */
+ GM_TXF_127B = GM_MIB_CNT_BASE + 248,/* 65-127 Byte Tx Frame */
+ GM_TXF_255B = GM_MIB_CNT_BASE + 256,/* 128-255 Byte Tx Frame */
+ GM_TXF_511B = GM_MIB_CNT_BASE + 264,/* 256-511 Byte Tx Frame */
+ GM_TXF_1023B = GM_MIB_CNT_BASE + 272,/* 512-1023 Byte Tx Frame */
+ GM_TXF_1518B = GM_MIB_CNT_BASE + 280,/* 1024-1518 Byte Tx Frame */
+ GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288,/* 1519-MaxSize Byte Tx Frame */
+
+ GM_TXF_COL = GM_MIB_CNT_BASE + 304,/* Tx Collision */
+ GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312,/* Tx Late Collision */
+ GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320,/* Tx aborted due to Exces. Col. */
+ GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328,/* Tx Multiple Collision */
+ GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336,/* Tx Single Collision */
+ GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344,/* Tx FIFO Underrun Event */
+};
+
+/* GMAC Bit Definitions */
+/* GM_GP_STAT 16 bit r/o General Purpose Status Register */
+enum {
+ GM_GPSR_SPEED = 1<<15, /* Bit 15: Port Speed (1 = 100 Mbps) */
+ GM_GPSR_DUPLEX = 1<<14, /* Bit 14: Duplex Mode (1 = Full) */
+ GM_GPSR_FC_TX_DIS = 1<<13, /* Bit 13: Tx Flow-Control Mode Disabled */
+ GM_GPSR_LINK_UP = 1<<12, /* Bit 12: Link Up Status */
+ GM_GPSR_PAUSE = 1<<11, /* Bit 11: Pause State */
+ GM_GPSR_TX_ACTIVE = 1<<10, /* Bit 10: Tx in Progress */
+ GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occured */
+ GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occured */
+
+ GM_GPSR_PHY_ST_CH = 1<<5, /* Bit 5: PHY Status Change */
+ GM_GPSR_GIG_SPEED = 1<<4, /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */
+ GM_GPSR_PART_MODE = 1<<3, /* Bit 3: Partition mode */
+ GM_GPSR_FC_RX_DIS = 1<<2, /* Bit 2: Rx Flow-Control Mode Disabled */
+ GM_GPSR_PROM_EN = 1<<1, /* Bit 1: Promiscuous Mode Enabled */
+};
+
+/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */
+enum {
+ GM_GPCR_PROM_ENA = 1<<14, /* Bit 14: Enable Promiscuous Mode */
+ GM_GPCR_FC_TX_DIS = 1<<13, /* Bit 13: Disable Tx Flow-Control Mode */
+ GM_GPCR_TX_ENA = 1<<12, /* Bit 12: Enable Transmit */
+ GM_GPCR_RX_ENA = 1<<11, /* Bit 11: Enable Receive */
+ GM_GPCR_BURST_ENA = 1<<10, /* Bit 10: Enable Burst Mode */
+ GM_GPCR_LOOP_ENA = 1<<9, /* Bit 9: Enable MAC Loopback Mode */
+ GM_GPCR_PART_ENA = 1<<8, /* Bit 8: Enable Partition Mode */
+ GM_GPCR_GIGS_ENA = 1<<7, /* Bit 7: Gigabit Speed (1000 Mbps) */
+ GM_GPCR_FL_PASS = 1<<6, /* Bit 6: Force Link Pass */
+ GM_GPCR_DUP_FULL = 1<<5, /* Bit 5: Full Duplex Mode */
+ GM_GPCR_FC_RX_DIS = 1<<4, /* Bit 4: Disable Rx Flow-Control Mode */
+ GM_GPCR_SPEED_100 = 1<<3, /* Bit 3: Port Speed 100 Mbps */
+ GM_GPCR_AU_DUP_DIS = 1<<2, /* Bit 2: Disable Auto-Update Duplex */
+ GM_GPCR_AU_FCT_DIS = 1<<1, /* Bit 1: Disable Auto-Update Flow-C. */
+ GM_GPCR_AU_SPD_DIS = 1<<0, /* Bit 0: Disable Auto-Update Speed */
+};
+
+#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
+#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS|GM_GPCR_AU_SPD_DIS)
+
+/* GM_TX_CTRL 16 bit r/w Transmit Control Register */
+enum {
+ GM_TXCR_FORCE_JAM = 1<<15, /* Bit 15: Force Jam / Flow-Control */
+ GM_TXCR_CRC_DIS = 1<<14, /* Bit 14: Disable insertion of CRC */
+ GM_TXCR_PAD_DIS = 1<<13, /* Bit 13: Disable padding of packets */
+ GM_TXCR_COL_THR_MSK = 7<<10, /* Bit 12..10: Collision Threshold */
+};
+
+#define TX_COL_THR(x) (((x)<<10) & GM_TXCR_COL_THR_MSK)
+#define TX_COL_DEF 0x04
+
+/* GM_RX_CTRL 16 bit r/w Receive Control Register */
+enum {
+ GM_RXCR_UCF_ENA = 1<<15, /* Bit 15: Enable Unicast filtering */
+ GM_RXCR_MCF_ENA = 1<<14, /* Bit 14: Enable Multicast filtering */
+ GM_RXCR_CRC_DIS = 1<<13, /* Bit 13: Remove 4-byte CRC */
+ GM_RXCR_PASS_FC = 1<<12, /* Bit 12: Pass FC packets to FIFO */
+};
+
+/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */
+enum {
+ GM_TXPA_JAMLEN_MSK = 0x03<<14, /* Bit 15..14: Jam Length */
+ GM_TXPA_JAMIPG_MSK = 0x1f<<9, /* Bit 13..9: Jam IPG */
+ GM_TXPA_JAMDAT_MSK = 0x1f<<4, /* Bit 8..4: IPG Jam to Data */
+ GM_TXPA_BO_LIM_MSK = 0x0f, /* Bit 3.. 0: Backoff Limit Mask */
+
+ TX_JAM_LEN_DEF = 0x03,
+ TX_JAM_IPG_DEF = 0x0b,
+ TX_IPG_JAM_DEF = 0x1c,
+ TX_BOF_LIM_DEF = 0x04,
+};
+
+#define TX_JAM_LEN_VAL(x) (((x)<<14) & GM_TXPA_JAMLEN_MSK)
+#define TX_JAM_IPG_VAL(x) (((x)<<9) & GM_TXPA_JAMIPG_MSK)
+#define TX_IPG_JAM_DATA(x) (((x)<<4) & GM_TXPA_JAMDAT_MSK)
+#define TX_BACK_OFF_LIM(x) ((x) & GM_TXPA_BO_LIM_MSK)
+
+
+/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */
+enum {
+ GM_SMOD_DATABL_MSK = 0x1f<<11, /* Bit 15..11: Data Blinder (r/o) */
+ GM_SMOD_LIMIT_4 = 1<<10, /* Bit 10: 4 consecutive Tx trials */
+ GM_SMOD_VLAN_ENA = 1<<9, /* Bit 9: Enable VLAN (Max. Frame Len) */
+ GM_SMOD_JUMBO_ENA = 1<<8, /* Bit 8: Enable Jumbo (Max. Frame Len) */
+ GM_SMOD_IPG_MSK = 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */
+};
+
+#define DATA_BLIND_VAL(x) (((x)<<11) & GM_SMOD_DATABL_MSK)
+#define DATA_BLIND_DEF 0x04
+
+#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK)
+#define IPG_DATA_DEF 0x1e
+
+/* GM_SMI_CTRL 16 bit r/w SMI Control Register */
+enum {
+ GM_SMI_CT_PHY_A_MSK = 0x1f<<11,/* Bit 15..11: PHY Device Address */
+ GM_SMI_CT_REG_A_MSK = 0x1f<<6,/* Bit 10.. 6: PHY Register Address */
+ GM_SMI_CT_OP_RD = 1<<5, /* Bit 5: OpCode Read (0=Write)*/
+ GM_SMI_CT_RD_VAL = 1<<4, /* Bit 4: Read Valid (Read completed) */
+ GM_SMI_CT_BUSY = 1<<3, /* Bit 3: Busy (Operation in progress) */
+};
+
+#define GM_SMI_CT_PHY_AD(x) (((u16)(x)<<11) & GM_SMI_CT_PHY_A_MSK)
+#define GM_SMI_CT_REG_AD(x) (((u16)(x)<<6) & GM_SMI_CT_REG_A_MSK)
+
+/* GM_PHY_ADDR 16 bit r/w GPHY Address Register */
+enum {
+ GM_PAR_MIB_CLR = 1<<5, /* Bit 5: Set MIB Clear Counter Mode */
+ GM_PAR_MIB_TST = 1<<4, /* Bit 4: MIB Load Counter (Test Mode) */
+};
+
+/* Receive Frame Status Encoding */
+enum {
+ GMR_FS_LEN = 0x7fff<<16, /* Bit 30..16: Rx Frame Length */
+ GMR_FS_VLAN = 1<<13, /* VLAN Packet */
+ GMR_FS_JABBER = 1<<12, /* Jabber Packet */
+ GMR_FS_UN_SIZE = 1<<11, /* Undersize Packet */
+ GMR_FS_MC = 1<<10, /* Multicast Packet */
+ GMR_FS_BC = 1<<9, /* Broadcast Packet */
+ GMR_FS_RX_OK = 1<<8, /* Receive OK (Good Packet) */
+ GMR_FS_GOOD_FC = 1<<7, /* Good Flow-Control Packet */
+ GMR_FS_BAD_FC = 1<<6, /* Bad Flow-Control Packet */
+ GMR_FS_MII_ERR = 1<<5, /* MII Error */
+ GMR_FS_LONG_ERR = 1<<4, /* Too Long Packet */
+ GMR_FS_FRAGMENT = 1<<3, /* Fragment */
+
+ GMR_FS_CRC_ERR = 1<<1, /* CRC Error */
+ GMR_FS_RX_FF_OV = 1<<0, /* Rx FIFO Overflow */
+
+ GMR_FS_ANY_ERR = GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR |
+ GMR_FS_FRAGMENT | GMR_FS_LONG_ERR |
+ GMR_FS_MII_ERR | GMR_FS_BAD_FC |
+ GMR_FS_UN_SIZE | GMR_FS_JABBER,
+};
+
+/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */
+enum {
+ RX_TRUNC_ON = 1<<27, /* enable packet truncation */
+ RX_TRUNC_OFF = 1<<26, /* disable packet truncation */
+ RX_VLAN_STRIP_ON = 1<<25, /* enable VLAN stripping */
+ RX_VLAN_STRIP_OFF = 1<<24, /* disable VLAN stripping */
+
+ RX_MACSEC_FLUSH_ON = 1<<23,
+ RX_MACSEC_FLUSH_OFF = 1<<22,
+ RX_MACSEC_ASF_FLUSH_ON = 1<<21,
+ RX_MACSEC_ASF_FLUSH_OFF = 1<<20,
+
+ GMF_RX_OVER_ON = 1<<19, /* enable flushing on receive overrun */
+ GMF_RX_OVER_OFF = 1<<18, /* disable flushing on receive overrun */
+ GMF_ASF_RX_OVER_ON = 1<<17, /* enable flushing of ASF when overrun */
+ GMF_ASF_RX_OVER_OFF = 1<<16, /* disable flushing of ASF when overrun */
+
+ GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */
+ GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */
+ GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */
+
+ GMF_RP_TST_ON = 1<<10, /* Read Pointer Test On */
+ GMF_RP_TST_OFF = 1<<9, /* Read Pointer Test Off */
+ GMF_RP_STEP = 1<<8, /* Read Pointer Step/Increment */
+ GMF_RX_F_FL_ON = 1<<7, /* Rx FIFO Flush Mode On */
+ GMF_RX_F_FL_OFF = 1<<6, /* Rx FIFO Flush Mode Off */
+ GMF_CLI_RX_FO = 1<<5, /* Clear IRQ Rx FIFO Overrun */
+ GMF_CLI_RX_C = 1<<4, /* Clear IRQ Rx Frame Complete */
+
+ GMF_OPER_ON = 1<<3, /* Operational Mode On */
+ GMF_OPER_OFF = 1<<2, /* Operational Mode Off */
+ GMF_RST_CLR = 1<<1, /* Clear GMAC FIFO Reset */
+ GMF_RST_SET = 1<<0, /* Set GMAC FIFO Reset */
+
+ RX_GMF_FL_THR_DEF = 0xa, /* flush threshold (default) */
+
+ GMF_RX_CTRL_DEF = GMF_OPER_ON | GMF_RX_F_FL_ON,
+};
+
+/* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */
+enum {
+ TX_DYN_WM_ENA = 3, /* Yukon-FE+ specific */
+};
+
+/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */
+enum {
+ TX_STFW_DIS = 1<<31,/* Disable Store & Forward (Yukon-EC Ultra) */
+ TX_STFW_ENA = 1<<30,/* Enable Store & Forward (Yukon-EC Ultra) */
+
+ TX_VLAN_TAG_ON = 1<<25,/* enable VLAN tagging */
+ TX_VLAN_TAG_OFF = 1<<24,/* disable VLAN tagging */
+
+ TX_JUMBO_ENA = 1<<23,/* PCI Jumbo Mode enable (Yukon-EC Ultra) */
+ TX_JUMBO_DIS = 1<<22,/* PCI Jumbo Mode enable (Yukon-EC Ultra) */
+
+ GMF_WSP_TST_ON = 1<<18,/* Write Shadow Pointer Test On */
+ GMF_WSP_TST_OFF = 1<<17,/* Write Shadow Pointer Test Off */
+ GMF_WSP_STEP = 1<<16,/* Write Shadow Pointer Step/Increment */
+
+ GMF_CLI_TX_FU = 1<<6, /* Clear IRQ Tx FIFO Underrun */
+ GMF_CLI_TX_FC = 1<<5, /* Clear IRQ Tx Frame Complete */
+ GMF_CLI_TX_PE = 1<<4, /* Clear IRQ Tx Parity Error */
+};
+
+/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */
+enum {
+ GMT_ST_START = 1<<2, /* Start Time Stamp Timer */
+ GMT_ST_STOP = 1<<1, /* Stop Time Stamp Timer */
+ GMT_ST_CLR_IRQ = 1<<0, /* Clear Time Stamp Timer IRQ */
+};
+
+/* B28_Y2_ASF_STAT_CMD 32 bit ASF Status and Command Reg */
+enum {
+ Y2_ASF_OS_PRES = 1<<4, /* ASF operation system present */
+ Y2_ASF_RESET = 1<<3, /* ASF system in reset state */
+ Y2_ASF_RUNNING = 1<<2, /* ASF system operational */
+ Y2_ASF_CLR_HSTI = 1<<1, /* Clear ASF IRQ */
+ Y2_ASF_IRQ = 1<<0, /* Issue an IRQ to ASF system */
+
+ Y2_ASF_UC_STATE = 3<<2, /* ASF uC State */
+ Y2_ASF_CLK_HALT = 0, /* ASF system clock stopped */
+};
+
+/* B28_Y2_ASF_HOST_COM 32 bit ASF Host Communication Reg */
+enum {
+ Y2_ASF_CLR_ASFI = 1<<1, /* Clear host IRQ */
+ Y2_ASF_HOST_IRQ = 1<<0, /* Issue an IRQ to HOST system */
+};
+/* HCU_CCSR CPU Control and Status Register */
+enum {
+ HCU_CCSR_SMBALERT_MONITOR= 1<<27, /* SMBALERT pin monitor */
+ HCU_CCSR_CPU_SLEEP = 1<<26, /* CPU sleep status */
+ /* Clock Stretching Timeout */
+ HCU_CCSR_CS_TO = 1<<25,
+ HCU_CCSR_WDOG = 1<<24, /* Watchdog Reset */
+
+ HCU_CCSR_CLR_IRQ_HOST = 1<<17, /* Clear IRQ_HOST */
+ HCU_CCSR_SET_IRQ_HCU = 1<<16, /* Set IRQ_HCU */
+
+ HCU_CCSR_AHB_RST = 1<<9, /* Reset AHB bridge */
+ HCU_CCSR_CPU_RST_MODE = 1<<8, /* CPU Reset Mode */
+
+ HCU_CCSR_SET_SYNC_CPU = 1<<5,
+ HCU_CCSR_CPU_CLK_DIVIDE_MSK = 3<<3,/* CPU Clock Divide */
+ HCU_CCSR_CPU_CLK_DIVIDE_BASE= 1<<3,
+ HCU_CCSR_OS_PRSNT = 1<<2, /* ASF OS Present */
+/* Microcontroller State */
+ HCU_CCSR_UC_STATE_MSK = 3,
+ HCU_CCSR_UC_STATE_BASE = 1<<0,
+ HCU_CCSR_ASF_RESET = 0,
+ HCU_CCSR_ASF_HALTED = 1<<1,
+ HCU_CCSR_ASF_RUNNING = 1<<0,
+};
+
+/* HCU_HCSR Host Control and Status Register */
+enum {
+ HCU_HCSR_SET_IRQ_CPU = 1<<16, /* Set IRQ_CPU */
+
+ HCU_HCSR_CLR_IRQ_HCU = 1<<1, /* Clear IRQ_HCU */
+ HCU_HCSR_SET_IRQ_HOST = 1<<0, /* Set IRQ_HOST */
+};
+
+/* STAT_CTRL 32 bit Status BMU control register (Yukon-2 only) */
+enum {
+ SC_STAT_CLR_IRQ = 1<<4, /* Status Burst IRQ clear */
+ SC_STAT_OP_ON = 1<<3, /* Operational Mode On */
+ SC_STAT_OP_OFF = 1<<2, /* Operational Mode Off */
+ SC_STAT_RST_CLR = 1<<1, /* Clear Status Unit Reset (Enable) */
+ SC_STAT_RST_SET = 1<<0, /* Set Status Unit Reset */
+};
+
+/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */
+enum {
+ GMC_SET_RST = 1<<15,/* MAC SEC RST */
+ GMC_SEC_RST_OFF = 1<<14,/* MAC SEC RSt OFF */
+ GMC_BYP_MACSECRX_ON = 1<<13,/* Bypass macsec RX */
+ GMC_BYP_MACSECRX_OFF= 1<<12,/* Bypass macsec RX off */
+ GMC_BYP_MACSECTX_ON = 1<<11,/* Bypass macsec TX */
+ GMC_BYP_MACSECTX_OFF= 1<<10,/* Bypass macsec TX off*/
+ GMC_BYP_RETR_ON = 1<<9, /* Bypass retransmit FIFO On */
+ GMC_BYP_RETR_OFF= 1<<8, /* Bypass retransmit FIFO Off */
+
+ GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */
+ GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */
+ GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */
+ GMC_F_LOOPB_OFF = 1<<4, /* FIFO Loopback Off */
+ GMC_PAUSE_ON = 1<<3, /* Pause On */
+ GMC_PAUSE_OFF = 1<<2, /* Pause Off */
+ GMC_RST_CLR = 1<<1, /* Clear GMAC Reset */
+ GMC_RST_SET = 1<<0, /* Set GMAC Reset */
+};
+
+/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */
+enum {
+ GPC_TX_PAUSE = 1<<30, /* Tx pause enabled (ro) */
+ GPC_RX_PAUSE = 1<<29, /* Rx pause enabled (ro) */
+ GPC_SPEED = 3<<27, /* PHY speed (ro) */
+ GPC_LINK = 1<<26, /* Link up (ro) */
+ GPC_DUPLEX = 1<<25, /* Duplex (ro) */
+ GPC_CLOCK = 1<<24, /* 125Mhz clock stable (ro) */
+
+ GPC_PDOWN = 1<<23, /* Internal regulator 2.5 power down */
+ GPC_TSTMODE = 1<<22, /* Test mode */
+ GPC_REG18 = 1<<21, /* Reg18 Power down */
+ GPC_REG12SEL = 3<<19, /* Reg12 power setting */
+ GPC_REG18SEL = 3<<17, /* Reg18 power setting */
+ GPC_SPILOCK = 1<<16, /* SPI lock (ASF) */
+
+ GPC_LEDMUX = 3<<14, /* LED Mux */
+ GPC_INTPOL = 1<<13, /* Interrupt polarity */
+ GPC_DETECT = 1<<12, /* Energy detect */
+ GPC_1000HD = 1<<11, /* Enable 1000Mbit HD */
+ GPC_SLAVE = 1<<10, /* Slave mode */
+ GPC_PAUSE = 1<<9, /* Pause enable */
+ GPC_LEDCTL = 3<<6, /* GPHY Leds */
+
+ GPC_RST_CLR = 1<<1, /* Clear GPHY Reset */
+ GPC_RST_SET = 1<<0, /* Set GPHY Reset */
+};
+
+/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */
+/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */
+enum {
+ GM_IS_TX_CO_OV = 1<<5, /* Transmit Counter Overflow IRQ */
+ GM_IS_RX_CO_OV = 1<<4, /* Receive Counter Overflow IRQ */
+ GM_IS_TX_FF_UR = 1<<3, /* Transmit FIFO Underrun */
+ GM_IS_TX_COMPL = 1<<2, /* Frame Transmission Complete */
+ GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */
+ GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */
+
+#define GMAC_DEF_MSK GM_IS_TX_FF_UR
+};
+
+/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
+enum { /* Bits 15.. 2: reserved */
+ GMLC_RST_CLR = 1<<1, /* Clear GMAC Link Reset */
+ GMLC_RST_SET = 1<<0, /* Set GMAC Link Reset */
+};
+
+
+/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */
+enum {
+ WOL_CTL_LINK_CHG_OCC = 1<<15,
+ WOL_CTL_MAGIC_PKT_OCC = 1<<14,
+ WOL_CTL_PATTERN_OCC = 1<<13,
+ WOL_CTL_CLEAR_RESULT = 1<<12,
+ WOL_CTL_ENA_PME_ON_LINK_CHG = 1<<11,
+ WOL_CTL_DIS_PME_ON_LINK_CHG = 1<<10,
+ WOL_CTL_ENA_PME_ON_MAGIC_PKT = 1<<9,
+ WOL_CTL_DIS_PME_ON_MAGIC_PKT = 1<<8,
+ WOL_CTL_ENA_PME_ON_PATTERN = 1<<7,
+ WOL_CTL_DIS_PME_ON_PATTERN = 1<<6,
+ WOL_CTL_ENA_LINK_CHG_UNIT = 1<<5,
+ WOL_CTL_DIS_LINK_CHG_UNIT = 1<<4,
+ WOL_CTL_ENA_MAGIC_PKT_UNIT = 1<<3,
+ WOL_CTL_DIS_MAGIC_PKT_UNIT = 1<<2,
+ WOL_CTL_ENA_PATTERN_UNIT = 1<<1,
+ WOL_CTL_DIS_PATTERN_UNIT = 1<<0,
+};
+
+
+/* Control flags */
+enum {
+ UDPTCP = 1<<0,
+ CALSUM = 1<<1,
+ WR_SUM = 1<<2,
+ INIT_SUM= 1<<3,
+ LOCK_SUM= 1<<4,
+ INS_VLAN= 1<<5,
+ EOP = 1<<7,
+};
+
+enum {
+ HW_OWNER = 1<<7,
+ OP_TCPWRITE = 0x11,
+ OP_TCPSTART = 0x12,
+ OP_TCPINIT = 0x14,
+ OP_TCPLCK = 0x18,
+ OP_TCPCHKSUM = OP_TCPSTART,
+ OP_TCPIS = OP_TCPINIT | OP_TCPSTART,
+ OP_TCPLW = OP_TCPLCK | OP_TCPWRITE,
+ OP_TCPLSW = OP_TCPLCK | OP_TCPSTART | OP_TCPWRITE,
+ OP_TCPLISW = OP_TCPLCK | OP_TCPINIT | OP_TCPSTART | OP_TCPWRITE,
+
+ OP_ADDR64 = 0x21,
+ OP_VLAN = 0x22,
+ OP_ADDR64VLAN = OP_ADDR64 | OP_VLAN,
+ OP_LRGLEN = 0x24,
+ OP_LRGLENVLAN = OP_LRGLEN | OP_VLAN,
+ OP_MSS = 0x28,
+ OP_MSSVLAN = OP_MSS | OP_VLAN,
+
+ OP_BUFFER = 0x40,
+ OP_PACKET = 0x41,
+ OP_LARGESEND = 0x43,
+ OP_LSOV2 = 0x45,
+
+/* YUKON-2 STATUS opcodes defines */
+ OP_RXSTAT = 0x60,
+ OP_RXTIMESTAMP = 0x61,
+ OP_RXVLAN = 0x62,
+ OP_RXCHKS = 0x64,
+ OP_RXCHKSVLAN = OP_RXCHKS | OP_RXVLAN,
+ OP_RXTIMEVLAN = OP_RXTIMESTAMP | OP_RXVLAN,
+ OP_RSS_HASH = 0x65,
+ OP_TXINDEXLE = 0x68,
+ OP_MACSEC = 0x6c,
+ OP_PUTIDX = 0x70,
+};
+
+enum status_css {
+ CSS_TCPUDPCSOK = 1<<7, /* TCP / UDP checksum is ok */
+ CSS_ISUDP = 1<<6, /* packet is a UDP packet */
+ CSS_ISTCP = 1<<5, /* packet is a TCP packet */
+ CSS_ISIPFRAG = 1<<4, /* packet is a TCP/UDP frag, CS calc not done */
+ CSS_ISIPV6 = 1<<3, /* packet is a IPv6 packet */
+ CSS_IPV4CSUMOK = 1<<2, /* IP v4: TCP header checksum is ok */
+ CSS_ISIPV4 = 1<<1, /* packet is a IPv4 packet */
+ CSS_LINK_BIT = 1<<0, /* port number (legacy) */
+};
+
+/* Yukon 2 hardware interface */
+struct sky2_tx_le {
+ u32 addr;
+ u16 length; /* also vlan tag or checksum start */
+ u8 ctrl;
+ u8 opcode;
+} __attribute((packed));
+
+struct sky2_rx_le {
+ u32 addr;
+ u16 length;
+ u8 ctrl;
+ u8 opcode;
+} __attribute((packed));
+
+struct sky2_status_le {
+ u32 status; /* also checksum */
+ u16 length; /* also vlan tag */
+ u8 css;
+ u8 opcode;
+} __attribute((packed));
+
+struct tx_ring_info {
+ struct io_buffer *iob;
+ u32 mapaddr;
+ u32 maplen;
+};
+
+struct rx_ring_info {
+ struct io_buffer *iob;
+ u32 data_addr;
+ u32 data_size;
+};
+
+enum flow_control {
+ FC_NONE = 0,
+ FC_TX = 1,
+ FC_RX = 2,
+ FC_BOTH = 3,
+};
+
+struct sky2_port {
+ struct sky2_hw *hw;
+ struct net_device *netdev;
+ unsigned port;
+
+ struct tx_ring_info *tx_ring;
+ struct sky2_tx_le *tx_le;
+ u16 tx_cons; /* next le to check */
+ u16 tx_prod; /* next le to use */
+
+ struct rx_ring_info *rx_ring;
+ struct sky2_rx_le *rx_le;
+
+ u16 rx_next; /* next re to check */
+ u16 rx_put; /* next le index to use */
+ u16 rx_data_size;
+
+ u32 rx_le_map;
+ u32 tx_le_map;
+ u16 advertising; /* ADVERTISED_ bits */
+ u16 speed; /* SPEED_1000, SPEED_100, ... */
+ u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */
+ u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */
+ enum flow_control flow_mode;
+ enum flow_control flow_status;
+};
+
+struct sky2_hw {
+ unsigned long regs;
+ struct pci_device *pdev;
+ struct net_device *dev[2];
+ unsigned long flags;
+#define SKY2_HW_USE_MSI 0x00000001
+#define SKY2_HW_FIBRE_PHY 0x00000002
+#define SKY2_HW_GIGABIT 0x00000004
+#define SKY2_HW_NEWER_PHY 0x00000008
+#define SKY2_HW_RAM_BUFFER 0x00000010
+#define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */
+#define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */
+#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */
+
+ u8 chip_id;
+ u8 chip_rev;
+ u8 pmd_type;
+ u8 ports;
+
+ struct sky2_status_le *st_le;
+ u32 st_idx;
+ u32 st_dma;
+};
+
+static inline int sky2_is_copper(const struct sky2_hw *hw)
+{
+ return !(hw->flags & SKY2_HW_FIBRE_PHY);
+}
+
+/* Register accessor for memory mapped device */
+static inline u32 sky2_read32(const struct sky2_hw *hw, unsigned reg)
+{
+ return readl(hw->regs + reg);
+}
+
+static inline u16 sky2_read16(const struct sky2_hw *hw, unsigned reg)
+{
+ return readw(hw->regs + reg);
+}
+
+static inline u8 sky2_read8(const struct sky2_hw *hw, unsigned reg)
+{
+ return readb(hw->regs + reg);
+}
+
+static inline void sky2_write32(const struct sky2_hw *hw, unsigned reg, u32 val)
+{
+ writel(val, hw->regs + reg);
+}
+
+static inline void sky2_write16(const struct sky2_hw *hw, unsigned reg, u16 val)
+{
+ writew(val, hw->regs + reg);
+}
+
+static inline void sky2_write8(const struct sky2_hw *hw, unsigned reg, u8 val)
+{
+ writeb(val, hw->regs + reg);
+}
+
+/* Yukon PHY related registers */
+#define SK_GMAC_REG(port,reg) \
+ (BASE_GMAC_1 + (port) * (BASE_GMAC_2-BASE_GMAC_1) + (reg))
+#define GM_PHY_RETRIES 100
+
+static inline u16 gma_read16(const struct sky2_hw *hw, unsigned port, unsigned reg)
+{
+ return sky2_read16(hw, SK_GMAC_REG(port,reg));
+}
+
+static inline u32 gma_read32(struct sky2_hw *hw, unsigned port, unsigned reg)
+{
+ unsigned base = SK_GMAC_REG(port, reg);
+ return (u32) sky2_read16(hw, base)
+ | (u32) sky2_read16(hw, base+4) << 16;
+}
+
+static inline void gma_write16(const struct sky2_hw *hw, unsigned port, int r, u16 v)
+{
+ sky2_write16(hw, SK_GMAC_REG(port,r), v);
+}
+
+static inline void gma_set_addr(struct sky2_hw *hw, unsigned port, unsigned reg,
+ const u8 *addr)
+{
+ gma_write16(hw, port, reg, (u16) addr[0] | ((u16) addr[1] << 8));
+ gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8));
+ gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8));
+}
+
+/* PCI config space access */
+static inline u32 sky2_pci_read32(const struct sky2_hw *hw, unsigned reg)
+{
+ return sky2_read32(hw, Y2_CFG_SPC + reg);
+}
+
+static inline u16 sky2_pci_read16(const struct sky2_hw *hw, unsigned reg)
+{
+ return sky2_read16(hw, Y2_CFG_SPC + reg);
+}
+
+static inline void sky2_pci_write32(struct sky2_hw *hw, unsigned reg, u32 val)
+{
+ sky2_write32(hw, Y2_CFG_SPC + reg, val);
+}
+
+static inline void sky2_pci_write16(struct sky2_hw *hw, unsigned reg, u16 val)
+{
+ sky2_write16(hw, Y2_CFG_SPC + reg, val);
+}
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/smc9000.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/smc9000.c
new file mode 100644
index 00000000..31e418a9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/smc9000.c
@@ -0,0 +1,952 @@
+#ifdef ALLMULTI
+#error multicast support is not yet implemented
+#endif
+ /*------------------------------------------------------------------------
+ * smc9000.c
+ * This is a Etherboot driver for SMC's 9000 series of Ethernet cards.
+ *
+ * Copyright (C) 1998 Daniel Engström <daniel.engstrom@riksnett.no>
+ * Based on the Linux SMC9000 driver, smc9194.c by Eric Stahlman
+ * Copyright (C) 1996 by Erik Stahlman <eric@vt.edu>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ *
+ * "Features" of the SMC chip:
+ * 4608 byte packet memory. ( for the 91C92/4. Others have more )
+ * EEPROM for configuration
+ * AUI/TP selection
+ *
+ * Authors
+ * Erik Stahlman <erik@vt.edu>
+ * Daniel Engström <daniel.engstrom@riksnett.no>
+ *
+ * History
+ * 98-09-25 Daniel Engström Etherboot driver crated from Eric's
+ * Linux driver.
+ *
+ *---------------------------------------------------------------------------*/
+
+FILE_LICENCE ( GPL_ANY );
+
+#define LINUX_OUT_MACROS 1
+#define SMC9000_DEBUG 0
+
+#if SMC9000_DEBUG > 1
+#define PRINTK2 printf
+#else
+#define PRINTK2(args...)
+#endif
+
+#include <ipxe/ethernet.h>
+#include <errno.h>
+#include "etherboot.h"
+#include "nic.h"
+#include <ipxe/isa.h>
+#include "smc9000.h"
+
+# define _outb outb
+# define _outw outw
+
+static const char smc9000_version[] = "Version 0.99 98-09-30";
+static const char *interfaces[ 2 ] = { "TP", "AUI" };
+static const char *chip_ids[ 15 ] = {
+ NULL, NULL, NULL,
+ /* 3 */ "SMC91C90/91C92",
+ /* 4 */ "SMC91C94",
+ /* 5 */ "SMC91C95",
+ NULL,
+ /* 7 */ "SMC91C100",
+ /* 8 */ "SMC91C100FD",
+ /* 9 */ "SMC91C11xFD",
+ NULL, NULL,
+ NULL, NULL, NULL
+};
+static const char smc91c96_id[] = "SMC91C96";
+
+/*------------------------------------------------------------
+ . Reads a register from the MII Management serial interface
+ .-------------------------------------------------------------*/
+static word smc_read_phy_register(int ioaddr, byte phyaddr, byte phyreg)
+{
+ int oldBank;
+ unsigned int i;
+ byte mask;
+ word mii_reg;
+ byte bits[64];
+ int clk_idx = 0;
+ int input_idx;
+ word phydata;
+
+ // 32 consecutive ones on MDO to establish sync
+ for (i = 0; i < 32; ++i)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+ // Start code <01>
+ bits[clk_idx++] = MII_MDOE;
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+ // Read command <10>
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+ bits[clk_idx++] = MII_MDOE;
+
+ // Output the PHY address, msb first
+ mask = (byte)0x10;
+ for (i = 0; i < 5; ++i)
+ {
+ if (phyaddr & mask)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+ else
+ bits[clk_idx++] = MII_MDOE;
+
+ // Shift to next lowest bit
+ mask >>= 1;
+ }
+
+ // Output the phy register number, msb first
+ mask = (byte)0x10;
+ for (i = 0; i < 5; ++i)
+ {
+ if (phyreg & mask)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+ else
+ bits[clk_idx++] = MII_MDOE;
+
+ // Shift to next lowest bit
+ mask >>= 1;
+ }
+
+ // Tristate and turnaround (2 bit times)
+ bits[clk_idx++] = 0;
+ //bits[clk_idx++] = 0;
+
+ // Input starts at this bit time
+ input_idx = clk_idx;
+
+ // Will input 16 bits
+ for (i = 0; i < 16; ++i)
+ bits[clk_idx++] = 0;
+
+ // Final clock bit
+ bits[clk_idx++] = 0;
+
+ // Save the current bank
+ oldBank = inw( ioaddr+BANK_SELECT );
+
+ // Select bank 3
+ SMC_SELECT_BANK(ioaddr, 3);
+
+ // Get the current MII register value
+ mii_reg = inw( ioaddr+MII_REG );
+
+ // Turn off all MII Interface bits
+ mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
+
+ // Clock all 64 cycles
+ for (i = 0; i < sizeof(bits); ++i)
+ {
+ // Clock Low - output data
+ outw( mii_reg | bits[i], ioaddr+MII_REG );
+ udelay(50);
+
+
+ // Clock Hi - input data
+ outw( mii_reg | bits[i] | MII_MCLK, ioaddr+MII_REG );
+ udelay(50);
+ bits[i] |= inw( ioaddr+MII_REG ) & MII_MDI;
+ }
+
+ // Return to idle state
+ // Set clock to low, data to low, and output tristated
+ outw( mii_reg, ioaddr+MII_REG );
+ udelay(50);
+
+ // Restore original bank select
+ SMC_SELECT_BANK(ioaddr, oldBank);
+
+ // Recover input data
+ phydata = 0;
+ for (i = 0; i < 16; ++i)
+ {
+ phydata <<= 1;
+
+ if (bits[input_idx++] & MII_MDI)
+ phydata |= 0x0001;
+ }
+
+#if (SMC_DEBUG > 2 )
+ printf("smc_read_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n",
+ phyaddr, phyreg, phydata);
+#endif
+
+ return(phydata);
+}
+
+
+/*------------------------------------------------------------
+ . Writes a register to the MII Management serial interface
+ .-------------------------------------------------------------*/
+static void smc_write_phy_register(int ioaddr,
+ byte phyaddr, byte phyreg, word phydata)
+{
+ int oldBank;
+ unsigned int i;
+ word mask;
+ word mii_reg;
+ byte bits[65];
+ int clk_idx = 0;
+
+ // 32 consecutive ones on MDO to establish sync
+ for (i = 0; i < 32; ++i)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+ // Start code <01>
+ bits[clk_idx++] = MII_MDOE;
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+ // Write command <01>
+ bits[clk_idx++] = MII_MDOE;
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+ // Output the PHY address, msb first
+ mask = (byte)0x10;
+ for (i = 0; i < 5; ++i)
+ {
+ if (phyaddr & mask)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+ else
+ bits[clk_idx++] = MII_MDOE;
+
+ // Shift to next lowest bit
+ mask >>= 1;
+ }
+
+ // Output the phy register number, msb first
+ mask = (byte)0x10;
+ for (i = 0; i < 5; ++i)
+ {
+ if (phyreg & mask)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+ else
+ bits[clk_idx++] = MII_MDOE;
+
+ // Shift to next lowest bit
+ mask >>= 1;
+ }
+
+ // Tristate and turnaround (2 bit times)
+ bits[clk_idx++] = 0;
+ bits[clk_idx++] = 0;
+
+ // Write out 16 bits of data, msb first
+ mask = 0x8000;
+ for (i = 0; i < 16; ++i)
+ {
+ if (phydata & mask)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+ else
+ bits[clk_idx++] = MII_MDOE;
+
+ // Shift to next lowest bit
+ mask >>= 1;
+ }
+
+ // Final clock bit (tristate)
+ bits[clk_idx++] = 0;
+
+ // Save the current bank
+ oldBank = inw( ioaddr+BANK_SELECT );
+
+ // Select bank 3
+ SMC_SELECT_BANK(ioaddr, 3);
+
+ // Get the current MII register value
+ mii_reg = inw( ioaddr+MII_REG );
+
+ // Turn off all MII Interface bits
+ mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
+
+ // Clock all cycles
+ for (i = 0; i < sizeof(bits); ++i)
+ {
+ // Clock Low - output data
+ outw( mii_reg | bits[i], ioaddr+MII_REG );
+ udelay(50);
+
+
+ // Clock Hi - input data
+ outw( mii_reg | bits[i] | MII_MCLK, ioaddr+MII_REG );
+ udelay(50);
+ bits[i] |= inw( ioaddr+MII_REG ) & MII_MDI;
+ }
+
+ // Return to idle state
+ // Set clock to low, data to low, and output tristated
+ outw( mii_reg, ioaddr+MII_REG );
+ udelay(50);
+
+ // Restore original bank select
+ SMC_SELECT_BANK(ioaddr, oldBank);
+
+#if (SMC_DEBUG > 2 )
+ printf("smc_write_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n",
+ phyaddr, phyreg, phydata);
+#endif
+}
+
+
+/*------------------------------------------------------------
+ . Finds and reports the PHY address
+ .-------------------------------------------------------------*/
+static int smc_detect_phy(int ioaddr, byte *pphyaddr)
+{
+ word phy_id1;
+ word phy_id2;
+ int phyaddr;
+ int found = 0;
+
+ // Scan all 32 PHY addresses if necessary
+ for (phyaddr = 0; phyaddr < 32; ++phyaddr)
+ {
+ // Read the PHY identifiers
+ phy_id1 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID1_REG);
+ phy_id2 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID2_REG);
+
+ // Make sure it is a valid identifier
+ if ((phy_id2 > 0x0000) && (phy_id2 < 0xffff) &&
+ (phy_id1 > 0x0000) && (phy_id1 < 0xffff))
+ {
+ if ((phy_id1 != 0x8000) && (phy_id2 != 0x8000))
+ {
+ // Save the PHY's address
+ *pphyaddr = phyaddr;
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ printf("No PHY found\n");
+ return(0);
+ }
+
+ // Set the PHY type
+ if ( (phy_id1 == 0x0016) && ((phy_id2 & 0xFFF0) == 0xF840 ) )
+ {
+ printf("PHY=LAN83C183 (LAN91C111 Internal)\n");
+ }
+
+ if ( (phy_id1 == 0x0282) && ((phy_id2 & 0xFFF0) == 0x1C50) )
+ {
+ printf("PHY=LAN83C180\n");
+ }
+
+ return(1);
+}
+
+/*------------------------------------------------------------
+ . Configures the specified PHY using Autonegotiation. Calls
+ . smc_phy_fixed() if the user has requested a certain config.
+ .-------------------------------------------------------------*/
+static void smc_phy_configure(int ioaddr)
+{
+ int timeout;
+ byte phyaddr;
+ word my_phy_caps; // My PHY capabilities
+ word my_ad_caps; // My Advertised capabilities
+ word status;
+ int rpc_cur_mode = RPC_DEFAULT;
+ int lastPhy18;
+
+ // Find the address and type of our phy
+ if (!smc_detect_phy(ioaddr, &phyaddr))
+ {
+ return;
+ }
+
+ // Reset the PHY, setting all other bits to zero
+ smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, PHY_CNTL_RST);
+
+ // Wait for the reset to complete, or time out
+ timeout = 6; // Wait up to 3 seconds
+ while (timeout--)
+ {
+ if (!(smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG)
+ & PHY_CNTL_RST))
+ {
+ // reset complete
+ break;
+ }
+
+ mdelay(500); // wait 500 millisecs
+ }
+
+ if (timeout < 1)
+ {
+ PRINTK2("PHY reset timed out\n");
+ return;
+ }
+
+ // Read PHY Register 18, Status Output
+ lastPhy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG);
+
+ // Enable PHY Interrupts (for register 18)
+ // Interrupts listed here are disabled
+ smc_write_phy_register(ioaddr, phyaddr, PHY_MASK_REG,
+ PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD |
+ PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB |
+ PHY_INT_SPDDET | PHY_INT_DPLXDET);
+
+ /* Configure the Receive/Phy Control register */
+ SMC_SELECT_BANK(ioaddr, 0);
+ outw( rpc_cur_mode, ioaddr + RPC_REG );
+
+ // Copy our capabilities from PHY_STAT_REG to PHY_AD_REG
+ my_phy_caps = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
+ my_ad_caps = PHY_AD_CSMA; // I am CSMA capable
+
+ if (my_phy_caps & PHY_STAT_CAP_T4)
+ my_ad_caps |= PHY_AD_T4;
+
+ if (my_phy_caps & PHY_STAT_CAP_TXF)
+ my_ad_caps |= PHY_AD_TX_FDX;
+
+ if (my_phy_caps & PHY_STAT_CAP_TXH)
+ my_ad_caps |= PHY_AD_TX_HDX;
+
+ if (my_phy_caps & PHY_STAT_CAP_TF)
+ my_ad_caps |= PHY_AD_10_FDX;
+
+ if (my_phy_caps & PHY_STAT_CAP_TH)
+ my_ad_caps |= PHY_AD_10_HDX;
+
+ // Update our Auto-Neg Advertisement Register
+ smc_write_phy_register(ioaddr, phyaddr, PHY_AD_REG, my_ad_caps);
+
+ PRINTK2("phy caps=%x\n", my_phy_caps);
+ PRINTK2("phy advertised caps=%x\n", my_ad_caps);
+
+ // Restart auto-negotiation process in order to advertise my caps
+ smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG,
+ PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST );
+
+ // Wait for the auto-negotiation to complete. This may take from
+ // 2 to 3 seconds.
+ // Wait for the reset to complete, or time out
+ timeout = 20; // Wait up to 10 seconds
+ while (timeout--)
+ {
+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
+ if (status & PHY_STAT_ANEG_ACK)
+ {
+ // auto-negotiate complete
+ break;
+ }
+
+ mdelay(500); // wait 500 millisecs
+
+ // Restart auto-negotiation if remote fault
+ if (status & PHY_STAT_REM_FLT)
+ {
+ PRINTK2("PHY remote fault detected\n");
+
+ // Restart auto-negotiation
+ PRINTK2("PHY restarting auto-negotiation\n");
+ smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG,
+ PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST |
+ PHY_CNTL_SPEED | PHY_CNTL_DPLX);
+ }
+ }
+
+ if (timeout < 1)
+ {
+ PRINTK2("PHY auto-negotiate timed out\n");
+ }
+
+ // Fail if we detected an auto-negotiate remote fault
+ if (status & PHY_STAT_REM_FLT)
+ {
+ PRINTK2("PHY remote fault detected\n");
+ }
+
+ // Set our sysctl parameters to match auto-negotiation results
+ if ( lastPhy18 & PHY_INT_SPDDET )
+ {
+ PRINTK2("PHY 100BaseT\n");
+ rpc_cur_mode |= RPC_SPEED;
+ }
+ else
+ {
+ PRINTK2("PHY 10BaseT\n");
+ rpc_cur_mode &= ~RPC_SPEED;
+ }
+
+ if ( lastPhy18 & PHY_INT_DPLXDET )
+ {
+ PRINTK2("PHY Full Duplex\n");
+ rpc_cur_mode |= RPC_DPLX;
+ }
+ else
+ {
+ PRINTK2("PHY Half Duplex\n");
+ rpc_cur_mode &= ~RPC_DPLX;
+ }
+
+ // Re-Configure the Receive/Phy Control register
+ outw( rpc_cur_mode, ioaddr + RPC_REG );
+}
+
+/*
+ * Function: smc_reset( int ioaddr )
+ * Purpose:
+ * This sets the SMC91xx chip to its normal state, hopefully from whatever
+ * mess that any other DOS driver has put it in.
+ *
+ * Maybe I should reset more registers to defaults in here? SOFTRESET should
+ * do that for me.
+ *
+ * Method:
+ * 1. send a SOFT RESET
+ * 2. wait for it to finish
+ * 3. reset the memory management unit
+ * 4. clear all interrupts
+ *
+*/
+static void smc_reset(int ioaddr)
+{
+ /* This resets the registers mostly to defaults, but doesn't
+ * affect EEPROM. That seems unnecessary */
+ SMC_SELECT_BANK(ioaddr, 0);
+ _outw( RCR_SOFTRESET, ioaddr + RCR );
+
+ /* this should pause enough for the chip to be happy */
+ SMC_DELAY(ioaddr);
+
+ /* Set the transmit and receive configuration registers to
+ * default values */
+ _outw(RCR_CLEAR, ioaddr + RCR);
+ _outw(TCR_CLEAR, ioaddr + TCR);
+
+ /* Reset the MMU */
+ SMC_SELECT_BANK(ioaddr, 2);
+ _outw( MC_RESET, ioaddr + MMU_CMD );
+
+ /* Note: It doesn't seem that waiting for the MMU busy is needed here,
+ * but this is a place where future chipsets _COULD_ break. Be wary
+ * of issuing another MMU command right after this */
+ _outb(0, ioaddr + INT_MASK);
+}
+
+
+/*----------------------------------------------------------------------
+ * Function: smc9000_probe_addr( int ioaddr )
+ *
+ * Purpose:
+ * Tests to see if a given ioaddr points to an SMC9xxx chip.
+ * Returns a 1 on success
+ *
+ * Algorithm:
+ * (1) see if the high byte of BANK_SELECT is 0x33
+ * (2) compare the ioaddr with the base register's address
+ * (3) see if I recognize the chip ID in the appropriate register
+ *
+ * ---------------------------------------------------------------------
+ */
+static int smc9000_probe_addr( isa_probe_addr_t ioaddr )
+{
+ word bank;
+ word revision_register;
+ word base_address_register;
+
+ /* First, see if the high byte is 0x33 */
+ bank = inw(ioaddr + BANK_SELECT);
+ if ((bank & 0xFF00) != 0x3300) {
+ return 0;
+ }
+ /* The above MIGHT indicate a device, but I need to write to further
+ * test this. */
+ _outw(0x0, ioaddr + BANK_SELECT);
+ bank = inw(ioaddr + BANK_SELECT);
+ if ((bank & 0xFF00) != 0x3300) {
+ return 0;
+ }
+
+ /* well, we've already written once, so hopefully another time won't
+ * hurt. This time, I need to switch the bank register to bank 1,
+ * so I can access the base address register */
+ SMC_SELECT_BANK(ioaddr, 1);
+ base_address_register = inw(ioaddr + BASE);
+
+ if (ioaddr != (base_address_register >> 3 & 0x3E0)) {
+ DBG("SMC9000: IOADDR %hX doesn't match configuration (%hX)."
+ "Probably not a SMC chip\n",
+ ioaddr, base_address_register >> 3 & 0x3E0);
+ /* well, the base address register didn't match. Must not have
+ * been a SMC chip after all. */
+ return 0;
+ }
+
+
+ /* check if the revision register is something that I recognize.
+ * These might need to be added to later, as future revisions
+ * could be added. */
+ SMC_SELECT_BANK(ioaddr, 3);
+ revision_register = inw(ioaddr + REVISION);
+ if (!chip_ids[(revision_register >> 4) & 0xF]) {
+ /* I don't recognize this chip, so... */
+ DBG( "SMC9000: IO %hX: Unrecognized revision register:"
+ " %hX, Contact author.\n", ioaddr, revision_register );
+ return 0;
+ }
+
+ /* at this point I'll assume that the chip is an SMC9xxx.
+ * It might be prudent to check a listing of MAC addresses
+ * against the hardware address, or do some other tests. */
+ return 1;
+}
+
+
+/**************************************************************************
+ * ETH_TRANSMIT - Transmit a frame
+ ***************************************************************************/
+static void smc9000_transmit(
+ struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ word length; /* real, length incl. header */
+ word numPages;
+ unsigned long time_out;
+ byte packet_no;
+ word status;
+ int i;
+
+ /* We dont pad here since we can have the hardware doing it for us */
+ length = (s + ETH_HLEN + 1)&~1;
+
+ /* convert to MMU pages */
+ numPages = length / 256;
+
+ if (numPages > 7 ) {
+ DBG("SMC9000: Far too big packet error. \n");
+ return;
+ }
+
+ /* dont try more than, say 30 times */
+ for (i=0;i<30;i++) {
+ /* now, try to allocate the memory */
+ SMC_SELECT_BANK(nic->ioaddr, 2);
+ _outw(MC_ALLOC | numPages, nic->ioaddr + MMU_CMD);
+
+ status = 0;
+ /* wait for the memory allocation to finnish */
+ for (time_out = currticks() + 5*TICKS_PER_SEC; currticks() < time_out; ) {
+ status = inb(nic->ioaddr + INTERRUPT);
+ if ( status & IM_ALLOC_INT ) {
+ /* acknowledge the interrupt */
+ _outb(IM_ALLOC_INT, nic->ioaddr + INTERRUPT);
+ break;
+ }
+ }
+
+ if ((status & IM_ALLOC_INT) != 0 ) {
+ /* We've got the memory */
+ break;
+ } else {
+ printf("SMC9000: Memory allocation timed out, resetting MMU.\n");
+ _outw(MC_RESET, nic->ioaddr + MMU_CMD);
+ }
+ }
+
+ /* If I get here, I _know_ there is a packet slot waiting for me */
+ packet_no = inb(nic->ioaddr + PNR_ARR + 1);
+ if (packet_no & 0x80) {
+ /* or isn't there? BAD CHIP! */
+ printf("SMC9000: Memory allocation failed. \n");
+ return;
+ }
+
+ /* we have a packet address, so tell the card to use it */
+ _outb(packet_no, nic->ioaddr + PNR_ARR);
+
+ /* point to the beginning of the packet */
+ _outw(PTR_AUTOINC, nic->ioaddr + POINTER);
+
+#if SMC9000_DEBUG > 2
+ printf("Trying to xmit packet of length %hX\n", length );
+#endif
+
+ /* send the packet length ( +6 for status, length and ctl byte )
+ * and the status word ( set to zeros ) */
+ _outw(0, nic->ioaddr + DATA_1 );
+
+ /* send the packet length ( +6 for status words, length, and ctl) */
+ _outb((length+6) & 0xFF, nic->ioaddr + DATA_1);
+ _outb((length+6) >> 8 , nic->ioaddr + DATA_1);
+
+ /* Write the contents of the packet */
+
+ /* The ethernet header first... */
+ outsw(nic->ioaddr + DATA_1, d, ETH_ALEN >> 1);
+ outsw(nic->ioaddr + DATA_1, nic->node_addr, ETH_ALEN >> 1);
+ _outw(htons(t), nic->ioaddr + DATA_1);
+
+ /* ... the data ... */
+ outsw(nic->ioaddr + DATA_1 , p, s >> 1);
+
+ /* ... and the last byte, if there is one. */
+ if ((s & 1) == 0) {
+ _outw(0, nic->ioaddr + DATA_1);
+ } else {
+ _outb(p[s-1], nic->ioaddr + DATA_1);
+ _outb(0x20, nic->ioaddr + DATA_1);
+ }
+
+ /* and let the chipset deal with it */
+ _outw(MC_ENQUEUE , nic->ioaddr + MMU_CMD);
+
+ status = 0; time_out = currticks() + 5*TICKS_PER_SEC;
+ do {
+ status = inb(nic->ioaddr + INTERRUPT);
+
+ if ((status & IM_TX_INT ) != 0) {
+ word tx_status;
+
+ /* ack interrupt */
+ _outb(IM_TX_INT, nic->ioaddr + INTERRUPT);
+
+ packet_no = inw(nic->ioaddr + FIFO_PORTS);
+ packet_no &= 0x7F;
+
+ /* select this as the packet to read from */
+ _outb( packet_no, nic->ioaddr + PNR_ARR );
+
+ /* read the first word from this packet */
+ _outw( PTR_AUTOINC | PTR_READ, nic->ioaddr + POINTER );
+
+ tx_status = inw( nic->ioaddr + DATA_1 );
+
+ if (0 == (tx_status & TS_SUCCESS)) {
+ DBG("SMC9000: TX FAIL STATUS: %hX \n", tx_status);
+ /* re-enable transmit */
+ SMC_SELECT_BANK(nic->ioaddr, 0);
+ _outw(inw(nic->ioaddr + TCR ) | TCR_ENABLE, nic->ioaddr + TCR );
+ }
+
+ /* kill the packet */
+ SMC_SELECT_BANK(nic->ioaddr, 2);
+ _outw(MC_FREEPKT, nic->ioaddr + MMU_CMD);
+
+ return;
+ }
+ }while(currticks() < time_out);
+
+ printf("SMC9000: TX timed out, resetting board\n");
+ smc_reset(nic->ioaddr);
+ return;
+}
+
+/**************************************************************************
+ * ETH_POLL - Wait for a frame
+ ***************************************************************************/
+static int smc9000_poll(struct nic *nic, int retrieve)
+{
+ SMC_SELECT_BANK(nic->ioaddr, 2);
+ if (inw(nic->ioaddr + FIFO_PORTS) & FP_RXEMPTY)
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+ /* start reading from the start of the packet */
+ _outw(PTR_READ | PTR_RCV | PTR_AUTOINC, nic->ioaddr + POINTER);
+
+ /* First read the status and check that we're ok */
+ if (!(inw(nic->ioaddr + DATA_1) & RS_ERRORS)) {
+ /* Next: read the packet length and mask off the top bits */
+ nic->packetlen = (inw(nic->ioaddr + DATA_1) & 0x07ff);
+
+ /* the packet length includes the 3 extra words */
+ nic->packetlen -= 6;
+#if SMC9000_DEBUG > 2
+ printf(" Reading %d words (and %d byte(s))\n",
+ (nic->packetlen >> 1), nic->packetlen & 1);
+#endif
+ /* read the packet (and the last "extra" word) */
+ insw(nic->ioaddr + DATA_1, nic->packet, (nic->packetlen+2) >> 1);
+ /* is there an odd last byte ? */
+ if (nic->packet[nic->packetlen+1] & 0x20)
+ nic->packetlen++;
+
+ /* error or good, tell the card to get rid of this packet */
+ _outw(MC_RELEASE, nic->ioaddr + MMU_CMD);
+ return 1;
+ }
+
+ printf("SMC9000: RX error\n");
+ /* error or good, tell the card to get rid of this packet */
+ _outw(MC_RELEASE, nic->ioaddr + MMU_CMD);
+ return 0;
+}
+
+static void smc9000_disable ( struct nic *nic, struct isa_device *isa __unused ) {
+
+ smc_reset(nic->ioaddr);
+
+ /* no more interrupts for me */
+ SMC_SELECT_BANK(nic->ioaddr, 2);
+ _outb( 0, nic->ioaddr + INT_MASK);
+
+ /* and tell the card to stay away from that nasty outside world */
+ SMC_SELECT_BANK(nic->ioaddr, 0);
+ _outb( RCR_CLEAR, nic->ioaddr + RCR );
+ _outb( TCR_CLEAR, nic->ioaddr + TCR );
+}
+
+static void smc9000_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations smc9000_operations = {
+ .connect = dummy_connect,
+ .poll = smc9000_poll,
+ .transmit = smc9000_transmit,
+ .irq = smc9000_irq,
+
+};
+
+/**************************************************************************
+ * ETH_PROBE - Look for an adapter
+ ***************************************************************************/
+
+static int smc9000_probe ( struct nic *nic, struct isa_device *isa ) {
+
+ unsigned short revision;
+ int memory;
+ int media;
+ const char * version_string;
+ const char * if_string;
+ int i;
+
+ nic->irqno = 0;
+ nic->ioaddr = isa->ioaddr;
+
+ /*
+ * Get the MAC address ( bank 1, regs 4 - 9 )
+ */
+ SMC_SELECT_BANK(nic->ioaddr, 1);
+ for ( i = 0; i < 6; i += 2 ) {
+ word address;
+
+ address = inw(nic->ioaddr + ADDR0 + i);
+ nic->node_addr[i+1] = address >> 8;
+ nic->node_addr[i] = address & 0xFF;
+ }
+
+ /* get the memory information */
+ SMC_SELECT_BANK(nic->ioaddr, 0);
+ memory = ( inw(nic->ioaddr + MCR) >> 9 ) & 0x7; /* multiplier */
+ memory *= 256 * (inw(nic->ioaddr + MIR) & 0xFF);
+
+ /*
+ * Now, I want to find out more about the chip. This is sort of
+ * redundant, but it's cleaner to have it in both, rather than having
+ * one VERY long probe procedure.
+ */
+ SMC_SELECT_BANK(nic->ioaddr, 3);
+ revision = inw(nic->ioaddr + REVISION);
+ version_string = chip_ids[(revision >> 4) & 0xF];
+
+ if (((revision & 0xF0) >> 4 == CHIP_9196) &&
+ ((revision & 0x0F) >= REV_9196)) {
+ /* This is a 91c96. 'c96 has the same chip id as 'c94 (4) but
+ * a revision starting at 6 */
+ version_string = smc91c96_id;
+ }
+
+ if ( !version_string ) {
+ /* I shouldn't get here because this call was done before.... */
+ return 0;
+ }
+
+ /* is it using AUI or 10BaseT ? */
+ SMC_SELECT_BANK(nic->ioaddr, 1);
+ if (inw(nic->ioaddr + CONFIG) & CFG_AUI_SELECT)
+ media = 2;
+ else
+ media = 1;
+
+ if_string = interfaces[media - 1];
+
+ /* now, reset the chip, and put it into a known state */
+ smc_reset(nic->ioaddr);
+
+ printf("SMC9000 %s\n", smc9000_version);
+ DBG("Copyright (C) 1998 Daniel Engstr\x94m\n");
+ DBG("Copyright (C) 1996 Eric Stahlman\n");
+
+ printf("%s rev:%d I/O port:%hX Interface:%s RAM:%d bytes \n",
+ version_string, revision & 0xF,
+ nic->ioaddr, if_string, memory );
+
+ DBG ( "Ethernet MAC address: %s\n", eth_ntoa ( nic->node_addr ) );
+
+ SMC_SELECT_BANK(nic->ioaddr, 0);
+
+ /* see the header file for options in TCR/RCR NORMAL*/
+ _outw(TCR_NORMAL, nic->ioaddr + TCR);
+ _outw(RCR_NORMAL, nic->ioaddr + RCR);
+
+ /* Select which interface to use */
+ SMC_SELECT_BANK(nic->ioaddr, 1);
+ if ( media == 1 ) {
+ _outw( inw( nic->ioaddr + CONFIG ) & ~CFG_AUI_SELECT,
+ nic->ioaddr + CONFIG );
+ }
+ else if ( media == 2 ) {
+ _outw( inw( nic->ioaddr + CONFIG ) | CFG_AUI_SELECT,
+ nic->ioaddr + CONFIG );
+ }
+
+ smc_phy_configure(nic->ioaddr);
+
+ nic->nic_op = &smc9000_operations;
+ return 1;
+}
+
+/*
+ * The SMC9000 can be at any of the following port addresses. To
+ * change for a slightly different card, you can add it to the array.
+ *
+ */
+static isa_probe_addr_t smc9000_probe_addrs[] = {
+ 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
+ 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0,
+};
+
+ISA_DRIVER ( smc9000_driver, smc9000_probe_addrs, smc9000_probe_addr,
+ GENERIC_ISAPNP_VENDOR, 0x8228 );
+
+DRIVER ( "SMC9000", nic_driver, isa_driver, smc9000_driver,
+ smc9000_probe, smc9000_disable );
+
+ISA_ROM ( "smc9000", "SMC9000" );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/smc9000.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/smc9000.h
new file mode 100644
index 00000000..22b0e189
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/smc9000.h
@@ -0,0 +1,428 @@
+/*------------------------------------------------------------------------
+ * smc9000.h
+ *
+ * Copyright (C) 1998 by Daniel Engström
+ * Copyright (C) 1996 by Erik Stahlman
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ *
+ * This file contains register information and access macros for
+ * the SMC91xxx chipset.
+ *
+ * Information contained in this file was obtained from the SMC91C94
+ * manual from SMC. To get a copy, if you really want one, you can find
+ * information under www.smsc.com in the components division.
+ * ( this thanks to advice from Donald Becker ).
+ *
+ * Authors
+ * Daniel Engström <daniel.engstrom@riksnett.no>
+ * Erik Stahlman <erik@vt.edu>
+ *
+ * History
+ * 96-01-06 Erik Stahlman moved definitions here from main .c
+ * file
+ * 96-01-19 Erik Stahlman polished this up some, and added
+ * better error handling
+ * 98-09-25 Daniel Engström adjusted for Etherboot
+ * 98-09-27 Daniel Engström moved some static strings back to the
+ * main .c file
+ * --------------------------------------------------------------------------*/
+
+FILE_LICENCE ( GPL_ANY );
+
+#ifndef _SMC9000_H_
+# define _SMC9000_H_
+
+/* I want some simple types */
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned long int dword;
+
+/*---------------------------------------------------------------
+ *
+ * A description of the SMC registers is probably in order here,
+ * although for details, the SMC datasheet is invaluable.
+ *
+ * Basically, the chip has 4 banks of registers ( 0 to 3 ), which
+ * are accessed by writing a number into the BANK_SELECT register
+ * ( I also use a SMC_SELECT_BANK macro for this ).
+ *
+ * The banks are configured so that for most purposes, bank 2 is all
+ * that is needed for simple run time tasks.
+ * ----------------------------------------------------------------------*/
+
+/*
+ * Bank Select Register:
+ *
+ * yyyy yyyy 0000 00xx
+ * xx = bank number
+ * yyyy yyyy = 0x33, for identification purposes.
+ */
+#define BANK_SELECT 14
+
+/* BANK 0 */
+
+#define TCR 0 /* transmit control register */
+#define TCR_ENABLE 0x0001 /* if this is 1, we can transmit */
+#define TCR_FDUPLX 0x0800 /* receive packets sent out */
+#define TCR_STP_SQET 0x1000 /* stop transmitting if Signal quality error */
+#define TCR_MON_CNS 0x0400 /* monitors the carrier status */
+#define TCR_PAD_ENABLE 0x0080 /* pads short packets to 64 bytes */
+
+#define TCR_CLEAR 0 /* do NOTHING */
+/* the normal settings for the TCR register : */
+#define TCR_NORMAL (TCR_ENABLE | TCR_PAD_ENABLE)
+
+
+#define EPH_STATUS 2
+#define ES_LINK_OK 0x4000 /* is the link integrity ok ? */
+
+#define RCR 4
+#define RCR_SOFTRESET 0x8000 /* resets the chip */
+#define RCR_STRIP_CRC 0x200 /* strips CRC */
+#define RCR_ENABLE 0x100 /* IFF this is set, we can receive packets */
+#define RCR_ALMUL 0x4 /* receive all multicast packets */
+#define RCR_PROMISC 0x2 /* enable promiscuous mode */
+
+/* the normal settings for the RCR register : */
+#define RCR_NORMAL (RCR_STRIP_CRC | RCR_ENABLE)
+#define RCR_CLEAR 0x0 /* set it to a base state */
+
+#define COUNTER 6
+#define MIR 8
+#define MCR 10
+/* 12 is reserved */
+
+// Receive/Phy Control Register
+/* BANK 0 */
+#define RPC_REG 0x000A
+#define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode.
+#define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode
+#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode
+#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb
+#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb
+#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect
+#define RPC_LED_RES (0x01) // LED = Reserved
+#define RPC_LED_10 (0x02) // LED = 10Mbps link detect
+#define RPC_LED_FD (0x03) // LED = Full Duplex Mode
+#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred
+#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect
+#define RPC_LED_TX (0x06) // LED = TX packet occurred
+#define RPC_LED_RX (0x07) // LED = RX packet occurred
+#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX)
+
+// Receive/Phy Control Register
+/* BANK 0 */
+#define RPC_REG 0x000A
+#define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode.
+#define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode
+#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode
+#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb
+#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb
+#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect
+#define RPC_LED_RES (0x01) // LED = Reserved
+#define RPC_LED_10 (0x02) // LED = 10Mbps link detect
+#define RPC_LED_FD (0x03) // LED = Full Duplex Mode
+#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred
+#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect
+#define RPC_LED_TX (0x06) // LED = TX packet occurred
+#define RPC_LED_RX (0x07) // LED = RX packet occurred
+#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX)
+
+/* BANK 1 */
+#define CONFIG 0
+#define CFG_AUI_SELECT 0x100
+#define BASE 2
+#define ADDR0 4
+#define ADDR1 6
+#define ADDR2 8
+#define GENERAL 10
+#define CONTROL 12
+#define CTL_POWERDOWN 0x2000
+#define CTL_LE_ENABLE 0x80
+#define CTL_CR_ENABLE 0x40
+#define CTL_TE_ENABLE 0x0020
+#define CTL_AUTO_RELEASE 0x0800
+#define CTL_EPROM_ACCESS 0x0003 /* high if Eprom is being read */
+
+/* BANK 2 */
+#define MMU_CMD 0
+#define MC_BUSY 1 /* only readable bit in the register */
+#define MC_NOP 0
+#define MC_ALLOC 0x20 /* or with number of 256 byte packets */
+#define MC_RESET 0x40
+#define MC_REMOVE 0x60 /* remove the current rx packet */
+#define MC_RELEASE 0x80 /* remove and release the current rx packet */
+#define MC_FREEPKT 0xA0 /* Release packet in PNR register */
+#define MC_ENQUEUE 0xC0 /* Enqueue the packet for transmit */
+
+#define PNR_ARR 2
+#define FIFO_PORTS 4
+
+#define FP_RXEMPTY 0x8000
+#define FP_TXEMPTY 0x80
+
+#define POINTER 6
+#define PTR_READ 0x2000
+#define PTR_RCV 0x8000
+#define PTR_AUTOINC 0x4000
+#define PTR_AUTO_INC 0x0040
+
+#define DATA_1 8
+#define DATA_2 10
+#define INTERRUPT 12
+
+#define INT_MASK 13
+#define IM_RCV_INT 0x1
+#define IM_TX_INT 0x2
+#define IM_TX_EMPTY_INT 0x4
+#define IM_ALLOC_INT 0x8
+#define IM_RX_OVRN_INT 0x10
+#define IM_EPH_INT 0x20
+#define IM_ERCV_INT 0x40 /* not on SMC9192 */
+
+/* BANK 3 */
+#define MULTICAST1 0
+#define MULTICAST2 2
+#define MULTICAST3 4
+#define MULTICAST4 6
+#define MGMT 8
+#define REVISION 10 /* ( hi: chip id low: rev # ) */
+
+// Management Interface Register (MII)
+#define MII_REG 0x0008
+#define MII_MSK_CRS100 0x4000 // Disables CRS100 detection during tx half dup
+#define MII_MDOE 0x0008 // MII Output Enable
+#define MII_MCLK 0x0004 // MII Clock, pin MDCLK
+#define MII_MDI 0x0002 // MII Input, pin MDI
+#define MII_MDO 0x0001 // MII Output, pin MDO
+
+/* this is NOT on SMC9192 */
+#define ERCV 12
+
+/* Note that 9194 and 9196 have the smame chip id,
+ * the 9196 will have revisions starting at 6 */
+#define CHIP_9190 3
+#define CHIP_9194 4
+#define CHIP_9195 5
+#define CHIP_9196 4
+#define CHIP_91100 7
+#define CHIP_91100FD 8
+
+#define REV_9196 6
+
+/*
+ * Transmit status bits
+ */
+#define TS_SUCCESS 0x0001
+#define TS_LOSTCAR 0x0400
+#define TS_LATCOL 0x0200
+#define TS_16COL 0x0010
+
+/*
+ * Receive status bits
+ */
+#define RS_ALGNERR 0x8000
+#define RS_BADCRC 0x2000
+#define RS_ODDFRAME 0x1000
+#define RS_TOOLONG 0x0800
+#define RS_TOOSHORT 0x0400
+#define RS_MULTICAST 0x0001
+#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
+
+// PHY Register Addresses (LAN91C111 Internal PHY)
+
+// PHY Control Register
+#define PHY_CNTL_REG 0x00
+#define PHY_CNTL_RST 0x8000 // 1=PHY Reset
+#define PHY_CNTL_LPBK 0x4000 // 1=PHY Loopback
+#define PHY_CNTL_SPEED 0x2000 // 1=100Mbps, 0=10Mpbs
+#define PHY_CNTL_ANEG_EN 0x1000 // 1=Enable Auto negotiation
+#define PHY_CNTL_PDN 0x0800 // 1=PHY Power Down mode
+#define PHY_CNTL_MII_DIS 0x0400 // 1=MII 4 bit interface disabled
+#define PHY_CNTL_ANEG_RST 0x0200 // 1=Reset Auto negotiate
+#define PHY_CNTL_DPLX 0x0100 // 1=Full Duplex, 0=Half Duplex
+#define PHY_CNTL_COLTST 0x0080 // 1= MII Colision Test
+
+// PHY Status Register
+#define PHY_STAT_REG 0x01
+#define PHY_STAT_CAP_T4 0x8000 // 1=100Base-T4 capable
+#define PHY_STAT_CAP_TXF 0x4000 // 1=100Base-X full duplex capable
+#define PHY_STAT_CAP_TXH 0x2000 // 1=100Base-X half duplex capable
+#define PHY_STAT_CAP_TF 0x1000 // 1=10Mbps full duplex capable
+#define PHY_STAT_CAP_TH 0x0800 // 1=10Mbps half duplex capable
+#define PHY_STAT_CAP_SUPR 0x0040 // 1=recv mgmt frames with not preamble
+#define PHY_STAT_ANEG_ACK 0x0020 // 1=ANEG has completed
+#define PHY_STAT_REM_FLT 0x0010 // 1=Remote Fault detected
+#define PHY_STAT_CAP_ANEG 0x0008 // 1=Auto negotiate capable
+#define PHY_STAT_LINK 0x0004 // 1=valid link
+#define PHY_STAT_JAB 0x0002 // 1=10Mbps jabber condition
+#define PHY_STAT_EXREG 0x0001 // 1=extended registers implemented
+
+// PHY Identifier Registers
+#define PHY_ID1_REG 0x02 // PHY Identifier 1
+#define PHY_ID2_REG 0x03 // PHY Identifier 2
+
+// PHY Auto-Negotiation Advertisement Register
+#define PHY_AD_REG 0x04
+#define PHY_AD_NP 0x8000 // 1=PHY requests exchange of Next Page
+#define PHY_AD_ACK 0x4000 // 1=got link code word from remote
+#define PHY_AD_RF 0x2000 // 1=advertise remote fault
+#define PHY_AD_T4 0x0200 // 1=PHY is capable of 100Base-T4
+#define PHY_AD_TX_FDX 0x0100 // 1=PHY is capable of 100Base-TX FDPLX
+#define PHY_AD_TX_HDX 0x0080 // 1=PHY is capable of 100Base-TX HDPLX
+#define PHY_AD_10_FDX 0x0040 // 1=PHY is capable of 10Base-T FDPLX
+#define PHY_AD_10_HDX 0x0020 // 1=PHY is capable of 10Base-T HDPLX
+#define PHY_AD_CSMA 0x0001 // 1=PHY is capable of 802.3 CMSA
+
+// PHY Auto-negotiation Remote End Capability Register
+#define PHY_RMT_REG 0x05
+// Uses same bit definitions as PHY_AD_REG
+
+// PHY Configuration Register 1
+#define PHY_CFG1_REG 0x10
+#define PHY_CFG1_LNKDIS 0x8000 // 1=Rx Link Detect Function disabled
+#define PHY_CFG1_XMTDIS 0x4000 // 1=TP Transmitter Disabled
+#define PHY_CFG1_XMTPDN 0x2000 // 1=TP Transmitter Powered Down
+#define PHY_CFG1_BYPSCR 0x0400 // 1=Bypass scrambler/descrambler
+#define PHY_CFG1_UNSCDS 0x0200 // 1=Unscramble Idle Reception Disable
+#define PHY_CFG1_EQLZR 0x0100 // 1=Rx Equalizer Disabled
+#define PHY_CFG1_CABLE 0x0080 // 1=STP(150ohm), 0=UTP(100ohm)
+#define PHY_CFG1_RLVL0 0x0040 // 1=Rx Squelch level reduced by 4.5db
+#define PHY_CFG1_TLVL_SHIFT 2 // Transmit Output Level Adjust
+#define PHY_CFG1_TLVL_MASK 0x003C
+#define PHY_CFG1_TRF_MASK 0x0003 // Transmitter Rise/Fall time
+
+
+// PHY Configuration Register 2
+#define PHY_CFG2_REG 0x11
+#define PHY_CFG2_APOLDIS 0x0020 // 1=Auto Polarity Correction disabled
+#define PHY_CFG2_JABDIS 0x0010 // 1=Jabber disabled
+#define PHY_CFG2_MREG 0x0008 // 1=Multiple register access (MII mgt)
+#define PHY_CFG2_INTMDIO 0x0004 // 1=Interrupt signaled with MDIO pulseo
+
+// PHY Status Output (and Interrupt status) Register
+#define PHY_INT_REG 0x12 // Status Output (Interrupt Status)
+#define PHY_INT_INT 0x8000 // 1=bits have changed since last read
+#define PHY_INT_LNKFAIL 0x4000 // 1=Link Not detected
+#define PHY_INT_LOSSSYNC 0x2000 // 1=Descrambler has lost sync
+#define PHY_INT_CWRD 0x1000 // 1=Invalid 4B5B code detected on rx
+#define PHY_INT_SSD 0x0800 // 1=No Start Of Stream detected on rx
+#define PHY_INT_ESD 0x0400 // 1=No End Of Stream detected on rx
+#define PHY_INT_RPOL 0x0200 // 1=Reverse Polarity detected
+#define PHY_INT_JAB 0x0100 // 1=Jabber detected
+#define PHY_INT_SPDDET 0x0080 // 1=100Base-TX mode, 0=10Base-T mode
+#define PHY_INT_DPLXDET 0x0040 // 1=Device in Full Duplex
+
+// PHY Interrupt/Status Mask Register
+#define PHY_MASK_REG 0x13 // Interrupt Mask
+// Uses the same bit definitions as PHY_INT_REG
+
+
+// PHY Register Addresses (LAN91C111 Internal PHY)
+
+// PHY Control Register
+#define PHY_CNTL_REG 0x00
+#define PHY_CNTL_RST 0x8000 // 1=PHY Reset
+#define PHY_CNTL_LPBK 0x4000 // 1=PHY Loopback
+#define PHY_CNTL_SPEED 0x2000 // 1=100Mbps, 0=10Mpbs
+#define PHY_CNTL_ANEG_EN 0x1000 // 1=Enable Auto negotiation
+#define PHY_CNTL_PDN 0x0800 // 1=PHY Power Down mode
+#define PHY_CNTL_MII_DIS 0x0400 // 1=MII 4 bit interface disabled
+#define PHY_CNTL_ANEG_RST 0x0200 // 1=Reset Auto negotiate
+#define PHY_CNTL_DPLX 0x0100 // 1=Full Duplex, 0=Half Duplex
+#define PHY_CNTL_COLTST 0x0080 // 1= MII Colision Test
+
+// PHY Status Register
+#define PHY_STAT_REG 0x01
+#define PHY_STAT_CAP_T4 0x8000 // 1=100Base-T4 capable
+#define PHY_STAT_CAP_TXF 0x4000 // 1=100Base-X full duplex capable
+#define PHY_STAT_CAP_TXH 0x2000 // 1=100Base-X half duplex capable
+#define PHY_STAT_CAP_TF 0x1000 // 1=10Mbps full duplex capable
+#define PHY_STAT_CAP_TH 0x0800 // 1=10Mbps half duplex capable
+#define PHY_STAT_CAP_SUPR 0x0040 // 1=recv mgmt frames with not preamble
+#define PHY_STAT_ANEG_ACK 0x0020 // 1=ANEG has completed
+#define PHY_STAT_REM_FLT 0x0010 // 1=Remote Fault detected
+#define PHY_STAT_CAP_ANEG 0x0008 // 1=Auto negotiate capable
+#define PHY_STAT_LINK 0x0004 // 1=valid link
+#define PHY_STAT_JAB 0x0002 // 1=10Mbps jabber condition
+#define PHY_STAT_EXREG 0x0001 // 1=extended registers implemented
+
+// PHY Identifier Registers
+#define PHY_ID1_REG 0x02 // PHY Identifier 1
+#define PHY_ID2_REG 0x03 // PHY Identifier 2
+
+// PHY Auto-Negotiation Advertisement Register
+#define PHY_AD_REG 0x04
+#define PHY_AD_NP 0x8000 // 1=PHY requests exchange of Next Page
+#define PHY_AD_ACK 0x4000 // 1=got link code word from remote
+#define PHY_AD_RF 0x2000 // 1=advertise remote fault
+#define PHY_AD_T4 0x0200 // 1=PHY is capable of 100Base-T4
+#define PHY_AD_TX_FDX 0x0100 // 1=PHY is capable of 100Base-TX FDPLX
+#define PHY_AD_TX_HDX 0x0080 // 1=PHY is capable of 100Base-TX HDPLX
+#define PHY_AD_10_FDX 0x0040 // 1=PHY is capable of 10Base-T FDPLX
+#define PHY_AD_10_HDX 0x0020 // 1=PHY is capable of 10Base-T HDPLX
+#define PHY_AD_CSMA 0x0001 // 1=PHY is capable of 802.3 CMSA
+
+// PHY Auto-negotiation Remote End Capability Register
+#define PHY_RMT_REG 0x05
+// Uses same bit definitions as PHY_AD_REG
+
+// PHY Configuration Register 1
+#define PHY_CFG1_REG 0x10
+#define PHY_CFG1_LNKDIS 0x8000 // 1=Rx Link Detect Function disabled
+#define PHY_CFG1_XMTDIS 0x4000 // 1=TP Transmitter Disabled
+#define PHY_CFG1_XMTPDN 0x2000 // 1=TP Transmitter Powered Down
+#define PHY_CFG1_BYPSCR 0x0400 // 1=Bypass scrambler/descrambler
+#define PHY_CFG1_UNSCDS 0x0200 // 1=Unscramble Idle Reception Disable
+#define PHY_CFG1_EQLZR 0x0100 // 1=Rx Equalizer Disabled
+#define PHY_CFG1_CABLE 0x0080 // 1=STP(150ohm), 0=UTP(100ohm)
+#define PHY_CFG1_RLVL0 0x0040 // 1=Rx Squelch level reduced by 4.5db
+#define PHY_CFG1_TLVL_SHIFT 2 // Transmit Output Level Adjust
+#define PHY_CFG1_TLVL_MASK 0x003C
+#define PHY_CFG1_TRF_MASK 0x0003 // Transmitter Rise/Fall time
+
+
+// PHY Configuration Register 2
+#define PHY_CFG2_REG 0x11
+#define PHY_CFG2_APOLDIS 0x0020 // 1=Auto Polarity Correction disabled
+#define PHY_CFG2_JABDIS 0x0010 // 1=Jabber disabled
+#define PHY_CFG2_MREG 0x0008 // 1=Multiple register access (MII mgt)
+#define PHY_CFG2_INTMDIO 0x0004 // 1=Interrupt signaled with MDIO pulseo
+
+// PHY Status Output (and Interrupt status) Register
+#define PHY_INT_REG 0x12 // Status Output (Interrupt Status)
+#define PHY_INT_INT 0x8000 // 1=bits have changed since last read
+#define PHY_INT_LNKFAIL 0x4000 // 1=Link Not detected
+#define PHY_INT_LOSSSYNC 0x2000 // 1=Descrambler has lost sync
+#define PHY_INT_CWRD 0x1000 // 1=Invalid 4B5B code detected on rx
+#define PHY_INT_SSD 0x0800 // 1=No Start Of Stream detected on rx
+#define PHY_INT_ESD 0x0400 // 1=No End Of Stream detected on rx
+#define PHY_INT_RPOL 0x0200 // 1=Reverse Polarity detected
+#define PHY_INT_JAB 0x0100 // 1=Jabber detected
+#define PHY_INT_SPDDET 0x0080 // 1=100Base-TX mode, 0=10Base-T mode
+#define PHY_INT_DPLXDET 0x0040 // 1=Device in Full Duplex
+
+// PHY Interrupt/Status Mask Register
+#define PHY_MASK_REG 0x13 // Interrupt Mask
+// Uses the same bit definitions as PHY_INT_REG
+
+
+/*-------------------------------------------------------------------------
+ * I define some macros to make it easier to do somewhat common
+ * or slightly complicated, repeated tasks.
+ --------------------------------------------------------------------------*/
+
+/* select a register bank, 0 to 3 */
+
+#define SMC_SELECT_BANK(x, y) { _outw( y, x + BANK_SELECT ); }
+
+/* define a small delay for the reset */
+#define SMC_DELAY(x) { inw( x + RCR );\
+ inw( x + RCR );\
+ inw( x + RCR ); }
+
+
+#endif /* _SMC_9000_H_ */
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/sundance.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/sundance.c
new file mode 100644
index 00000000..5cc449df
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/sundance.c
@@ -0,0 +1,907 @@
+/**************************************************************************
+*
+* sundance.c -- Etherboot device driver for the Sundance ST201 "Alta".
+* Written 2002-2002 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code based on:
+* sundance.c: A Linux device driver for the Sundance ST201 "Alta"
+* Written 1999-2002 by Donald Becker
+*
+* tulip.c: Tulip and Clone Etherboot Driver
+* By Marty Conner
+* Copyright (C) 2001 Entity Cyber, Inc.
+*
+* Linux Driver Version LK1.09a, 10-Jul-2003 (2.4.25)
+*
+* REVISION HISTORY:
+* ================
+* v1.1 01-01-2003 timlegge Initial implementation
+* v1.7 04-10-2003 timlegge Transfers Linux Kernel (30 sec)
+* v1.8 04-13-2003 timlegge Fix multiple transmission bug
+* v1.9 08-19-2003 timlegge Support Multicast
+* v1.10 01-17-2004 timlegge Initial driver output cleanup
+* v1.11 03-21-2004 timlegge Remove unused variables
+* v1.12 03-21-2004 timlegge Remove excess MII defines
+* v1.13 03-24-2004 timlegge Update to Linux 2.4.25 driver
+*
+****************************************************************************/
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* to get some global routines like printf */
+#include "etherboot.h"
+/* to get the interface to the body of the program */
+#include "nic.h"
+/* to get the PCI support functions, if this is a PCI NIC */
+#include <ipxe/pci.h>
+#include "mii.h"
+
+#define drv_version "v1.12"
+#define drv_date "2004-03-21"
+
+#define HZ 100
+
+/* Condensed operations for readability. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+/* Set the mtu */
+static int mtu = 1514;
+
+/* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
+ The sundance uses a 64 element hash table based on the Ethernet CRC. */
+// static int multicast_filter_limit = 32;
+
+/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
+ Setting to > 1518 effectively disables this feature.
+ This chip can receive into any byte alignment buffers, so word-oriented
+ archs do not need a copy-align of the IP header. */
+static int rx_copybreak = 0;
+static int flowctrl = 1;
+
+/* Allow forcing the media type */
+/* media[] specifies the media type the NIC operates at.
+ autosense Autosensing active media.
+ 10mbps_hd 10Mbps half duplex.
+ 10mbps_fd 10Mbps full duplex.
+ 100mbps_hd 100Mbps half duplex.
+ 100mbps_fd 100Mbps full duplex.
+*/
+static char media[] = "autosense";
+
+/* Operational parameters that are set at compile time. */
+
+/* As Etherboot uses a Polling driver we can keep the number of rings
+to the minimum number required. In general that is 1 transmit and 4 receive receive rings. However some cards require that
+there be a minimum of 2 rings */
+#define TX_RING_SIZE 2
+#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */
+#define RX_RING_SIZE 4
+
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIME_OUT (4*HZ)
+#define PKT_BUF_SZ 1536
+
+/* Offsets to the device registers.
+ Unlike software-only systems, device drivers interact with complex hardware.
+ It's not useful to define symbolic names for every register bit in the
+ device. The name can only partially document the semantics and make
+ the driver longer and more difficult to read.
+ In general, only the important configuration values or bits changed
+ multiple times should be defined symbolically.
+*/
+enum alta_offsets {
+ DMACtrl = 0x00,
+ TxListPtr = 0x04,
+ TxDMABurstThresh = 0x08,
+ TxDMAUrgentThresh = 0x09,
+ TxDMAPollPeriod = 0x0a,
+ RxDMAStatus = 0x0c,
+ RxListPtr = 0x10,
+ DebugCtrl0 = 0x1a,
+ DebugCtrl1 = 0x1c,
+ RxDMABurstThresh = 0x14,
+ RxDMAUrgentThresh = 0x15,
+ RxDMAPollPeriod = 0x16,
+ LEDCtrl = 0x1a,
+ ASICCtrl = 0x30,
+ EEData = 0x34,
+ EECtrl = 0x36,
+ TxStartThresh = 0x3c,
+ RxEarlyThresh = 0x3e,
+ FlashAddr = 0x40,
+ FlashData = 0x44,
+ TxStatus = 0x46,
+ TxFrameId = 0x47,
+ DownCounter = 0x18,
+ IntrClear = 0x4a,
+ IntrEnable = 0x4c,
+ IntrStatus = 0x4e,
+ MACCtrl0 = 0x50,
+ MACCtrl1 = 0x52,
+ StationAddr = 0x54,
+ MaxFrameSize = 0x5A,
+ RxMode = 0x5c,
+ MIICtrl = 0x5e,
+ MulticastFilter0 = 0x60,
+ MulticastFilter1 = 0x64,
+ RxOctetsLow = 0x68,
+ RxOctetsHigh = 0x6a,
+ TxOctetsLow = 0x6c,
+ TxOctetsHigh = 0x6e,
+ TxFramesOK = 0x70,
+ RxFramesOK = 0x72,
+ StatsCarrierError = 0x74,
+ StatsLateColl = 0x75,
+ StatsMultiColl = 0x76,
+ StatsOneColl = 0x77,
+ StatsTxDefer = 0x78,
+ RxMissed = 0x79,
+ StatsTxXSDefer = 0x7a,
+ StatsTxAbort = 0x7b,
+ StatsBcastTx = 0x7c,
+ StatsBcastRx = 0x7d,
+ StatsMcastTx = 0x7e,
+ StatsMcastRx = 0x7f,
+ /* Aliased and bogus values! */
+ RxStatus = 0x0c,
+};
+enum ASICCtrl_HiWord_bit {
+ GlobalReset = 0x0001,
+ RxReset = 0x0002,
+ TxReset = 0x0004,
+ DMAReset = 0x0008,
+ FIFOReset = 0x0010,
+ NetworkReset = 0x0020,
+ HostReset = 0x0040,
+ ResetBusy = 0x0400,
+};
+
+/* Bits in the interrupt status/mask registers. */
+enum intr_status_bits {
+ IntrSummary = 0x0001, IntrPCIErr = 0x0002, IntrMACCtrl = 0x0008,
+ IntrTxDone = 0x0004, IntrRxDone = 0x0010, IntrRxStart = 0x0020,
+ IntrDrvRqst = 0x0040,
+ StatsMax = 0x0080, LinkChange = 0x0100,
+ IntrTxDMADone = 0x0200, IntrRxDMADone = 0x0400,
+};
+
+/* Bits in the RxMode register. */
+enum rx_mode_bits {
+ AcceptAllIPMulti = 0x20, AcceptMultiHash = 0x10, AcceptAll = 0x08,
+ AcceptBroadcast = 0x04, AcceptMulticast = 0x02, AcceptMyPhys =
+ 0x01,
+};
+/* Bits in MACCtrl. */
+enum mac_ctrl0_bits {
+ EnbFullDuplex = 0x20, EnbRcvLargeFrame = 0x40,
+ EnbFlowCtrl = 0x100, EnbPassRxCRC = 0x200,
+};
+enum mac_ctrl1_bits {
+ StatsEnable = 0x0020, StatsDisable = 0x0040, StatsEnabled = 0x0080,
+ TxEnable = 0x0100, TxDisable = 0x0200, TxEnabled = 0x0400,
+ RxEnable = 0x0800, RxDisable = 0x1000, RxEnabled = 0x2000,
+};
+
+/* The Rx and Tx buffer descriptors.
+ Using only 32 bit fields simplifies software endian correction.
+ This structure must be aligned, and should avoid spanning cache lines.
+*/
+struct netdev_desc {
+ u32 next_desc;
+ u32 status;
+ u32 addr;
+ u32 length;
+};
+
+/* Bits in netdev_desc.status */
+enum desc_status_bits {
+ DescOwn = 0x8000,
+ DescEndPacket = 0x4000,
+ DescEndRing = 0x2000,
+ LastFrag = 0x80000000,
+ DescIntrOnTx = 0x8000,
+ DescIntrOnDMADone = 0x80000000,
+ DisableAlign = 0x00000001,
+};
+
+/**********************************************
+* Descriptor Ring and Buffer defination
+***********************************************/
+/* Define the TX Descriptor */
+static struct netdev_desc tx_ring[TX_RING_SIZE];
+
+/* Define the RX Descriptor */
+static struct netdev_desc rx_ring[RX_RING_SIZE];
+
+/* Create a static buffer of size PKT_BUF_SZ for each RX and TX descriptor.
+ All descriptors point to a part of this buffer */
+struct {
+ unsigned char txb[PKT_BUF_SZ * TX_RING_SIZE];
+ unsigned char rxb[RX_RING_SIZE * PKT_BUF_SZ];
+} rx_tx_buf __shared;
+#define rxb rx_tx_buf.rxb
+#define txb rx_tx_buf.txb
+
+/* FIXME: Move BASE to the private structure */
+static u32 BASE;
+#define EEPROM_SIZE 128
+
+enum pci_id_flags_bits {
+ PCI_USES_IO = 1, PCI_USES_MEM = 2, PCI_USES_MASTER = 4,
+ PCI_ADDR0 = 0 << 4, PCI_ADDR1 = 1 << 4, PCI_ADDR2 =
+ 2 << 4, PCI_ADDR3 = 3 << 4,
+};
+
+enum chip_capability_flags { CanHaveMII = 1, KendinPktDropBug = 2, };
+#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0)
+
+#define MII_CNT 4
+static struct sundance_private {
+ const char *nic_name;
+ /* Frequently used values */
+
+ unsigned int cur_rx; /* Producer/consumer ring indicies */
+ unsigned int mtu;
+
+ /* These values keep track of the tranceiver/media in use */
+ unsigned int flowctrl:1;
+ unsigned int an_enable:1;
+
+ unsigned int speed;
+
+ /* MII tranceiver section */
+ struct mii_if_info mii_if;
+ int mii_preamble_required;
+ unsigned char phys[MII_CNT];
+ unsigned char pci_rev_id;
+} sdx;
+
+static struct sundance_private *sdc;
+
+/* Station Address location within the EEPROM */
+#define EEPROM_SA_OFFSET 0x10
+#define DEFAULT_INTR (IntrRxDMADone | IntrPCIErr | \
+ IntrDrvRqst | IntrTxDone | StatsMax | \
+ LinkChange)
+
+static int eeprom_read(long ioaddr, int location);
+static int mdio_read(struct nic *nic, int phy_id, unsigned int location);
+static void mdio_write(struct nic *nic, int phy_id, unsigned int location,
+ int value);
+static void set_rx_mode(struct nic *nic);
+
+static void check_duplex(struct nic *nic)
+{
+ int mii_lpa = mdio_read(nic, sdc->phys[0], MII_LPA);
+ int negotiated = mii_lpa & sdc->mii_if.advertising;
+ int duplex;
+
+ /* Force media */
+ if (!sdc->an_enable || mii_lpa == 0xffff) {
+ if (sdc->mii_if.full_duplex)
+ outw(inw(BASE + MACCtrl0) | EnbFullDuplex,
+ BASE + MACCtrl0);
+ return;
+ }
+
+ /* Autonegotiation */
+ duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
+ if (sdc->mii_if.full_duplex != duplex) {
+ sdc->mii_if.full_duplex = duplex;
+ DBG ("%s: Setting %s-duplex based on MII #%d "
+ "negotiated capability %4.4x.\n", sdc->nic_name,
+ duplex ? "full" : "half", sdc->phys[0],
+ negotiated );
+ outw(inw(BASE + MACCtrl0) | duplex ? 0x20 : 0,
+ BASE + MACCtrl0);
+ }
+}
+
+
+/**************************************************************************
+ * init_ring - setup the tx and rx descriptors
+ *************************************************************************/
+static void init_ring(struct nic *nic __unused)
+{
+ int i;
+
+ sdc->cur_rx = 0;
+
+ /* Initialize all the Rx descriptors */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_ring[i].next_desc = virt_to_le32desc(&rx_ring[i + 1]);
+ rx_ring[i].status = 0;
+ rx_ring[i].length = 0;
+ rx_ring[i].addr = 0;
+ }
+
+ /* Mark the last entry as wrapping the ring */
+ rx_ring[i - 1].next_desc = virt_to_le32desc(&rx_ring[0]);
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_ring[i].addr = virt_to_le32desc(&rxb[i * PKT_BUF_SZ]);
+ rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LastFrag);
+ }
+
+ /* We only use one transmit buffer, but two
+ * descriptors so transmit engines have somewhere
+ * to point should they feel the need */
+ tx_ring[0].status = 0x00000000;
+ tx_ring[0].addr = virt_to_bus(&txb[0]);
+ tx_ring[0].next_desc = 0; /* virt_to_bus(&tx_ring[1]); */
+
+ /* This descriptor is never used */
+ tx_ring[1].status = 0x00000000;
+ tx_ring[1].addr = 0; /*virt_to_bus(&txb[0]); */
+ tx_ring[1].next_desc = 0;
+
+ /* Mark the last entry as wrapping the ring,
+ * though this should never happen */
+ tx_ring[1].length = cpu_to_le32(LastFrag | PKT_BUF_SZ);
+}
+
+/**************************************************************************
+ * RESET - Reset Adapter
+ * ***********************************************************************/
+static void sundance_reset(struct nic *nic)
+{
+ int i;
+
+ init_ring(nic);
+
+ outl(virt_to_le32desc(&rx_ring[0]), BASE + RxListPtr);
+ /* The Tx List Pointer is written as packets are queued */
+
+ /* Initialize other registers. */
+ /* __set_mac_addr(dev); */
+ {
+ u16 addr16;
+
+ addr16 = (nic->node_addr[0] | (nic->node_addr[1] << 8));
+ outw(addr16, BASE + StationAddr);
+ addr16 = (nic->node_addr[2] | (nic->node_addr[3] << 8));
+ outw(addr16, BASE + StationAddr + 2);
+ addr16 = (nic->node_addr[4] | (nic->node_addr[5] << 8));
+ outw(addr16, BASE + StationAddr + 4);
+ }
+
+ outw(sdc->mtu + 14, BASE + MaxFrameSize);
+ if (sdc->mtu > 2047) /* this will never happen with default options */
+ outl(inl(BASE + ASICCtrl) | 0x0c, BASE + ASICCtrl);
+
+ set_rx_mode(nic);
+
+ outw(0, BASE + DownCounter);
+ /* Set the chip to poll every N*30nsec */
+ outb(100, BASE + RxDMAPollPeriod);
+
+ /* Fix DFE-580TX packet drop issue */
+ if (sdc->pci_rev_id >= 0x14)
+ writeb(0x01, BASE + DebugCtrl1);
+
+ outw(RxEnable | TxEnable, BASE + MACCtrl1);
+
+ /* Construct a perfect filter frame with the mac address as first match
+ * and broadcast for all others */
+ for (i = 0; i < 192; i++)
+ txb[i] = 0xFF;
+
+ txb[0] = nic->node_addr[0];
+ txb[1] = nic->node_addr[1];
+ txb[2] = nic->node_addr[2];
+ txb[3] = nic->node_addr[3];
+ txb[4] = nic->node_addr[4];
+ txb[5] = nic->node_addr[5];
+
+ DBG ( "%s: Done sundance_reset, status: Rx %hX Tx %hX "
+ "MAC Control %hX, %hX %hX\n",
+ sdc->nic_name, (int) inl(BASE + RxStatus),
+ (int) inw(BASE + TxStatus), (int) inl(BASE + MACCtrl0),
+ (int) inw(BASE + MACCtrl1), (int) inw(BASE + MACCtrl0) );
+}
+
+/**************************************************************************
+IRQ - Wait for a frame
+***************************************************************************/
+static void sundance_irq ( struct nic *nic, irq_action_t action ) {
+ unsigned int intr_status;
+
+ switch ( action ) {
+ case DISABLE :
+ case ENABLE :
+ intr_status = inw(nic->ioaddr + IntrStatus);
+ intr_status = intr_status & ~DEFAULT_INTR;
+ if ( action == ENABLE )
+ intr_status = intr_status | DEFAULT_INTR;
+ outw(intr_status, nic->ioaddr + IntrEnable);
+ break;
+ case FORCE :
+ outw(0x0200, BASE + ASICCtrl);
+ break;
+ }
+}
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int sundance_poll(struct nic *nic, int retreive)
+{
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+ int entry = sdc->cur_rx % RX_RING_SIZE;
+ u32 frame_status = le32_to_cpu(rx_ring[entry].status);
+ int intr_status;
+ int pkt_len = 0;
+
+ if (!(frame_status & DescOwn))
+ return 0;
+
+ /* There is a packet ready */
+ if(!retreive)
+ return 1;
+
+ intr_status = inw(nic->ioaddr + IntrStatus);
+ outw(intr_status, nic->ioaddr + IntrStatus);
+
+ pkt_len = frame_status & 0x1fff;
+
+ if (frame_status & 0x001f4000) {
+ DBG ( "Polling frame_status error\n" ); /* Do we really care about this */
+ } else {
+ if (pkt_len < rx_copybreak) {
+ /* FIXME: What should happen Will this ever occur */
+ printf("Poll Error: pkt_len < rx_copybreak");
+ } else {
+ nic->packetlen = pkt_len;
+ memcpy(nic->packet, rxb +
+ (sdc->cur_rx * PKT_BUF_SZ), nic->packetlen);
+
+ }
+ }
+ rx_ring[entry].length = cpu_to_le32(PKT_BUF_SZ | LastFrag);
+ rx_ring[entry].status = 0;
+ entry++;
+ sdc->cur_rx = entry % RX_RING_SIZE;
+ outw(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone),
+ nic->ioaddr + IntrStatus);
+ return 1;
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void sundance_transmit(struct nic *nic, const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p)
+{ /* Packet */
+ u16 nstype;
+ u32 to;
+
+ /* Disable the Tx */
+ outw(TxDisable, BASE + MACCtrl1);
+
+ memcpy(txb, d, ETH_ALEN);
+ memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ nstype = htons((u16) t);
+ memcpy(txb + 2 * ETH_ALEN, (u8 *) & nstype, 2);
+ memcpy(txb + ETH_HLEN, p, s);
+
+ s += ETH_HLEN;
+ s &= 0x0FFF;
+ while (s < ETH_ZLEN)
+ txb[s++] = '\0';
+
+ /* Setup the transmit descriptor */
+ tx_ring[0].length = cpu_to_le32(s | LastFrag);
+ tx_ring[0].status = cpu_to_le32(0x00000001);
+
+ /* Point to transmit descriptor */
+ outl(virt_to_le32desc(&tx_ring[0]), BASE + TxListPtr);
+
+ /* Enable Tx */
+ outw(TxEnable, BASE + MACCtrl1);
+ /* Trigger an immediate send */
+ outw(0, BASE + TxStatus);
+
+ to = currticks() + TX_TIME_OUT;
+ while (!(tx_ring[0].status & 0x00010000) && (currticks() < to)); /* wait */
+
+ if (currticks() >= to) {
+ printf("TX Time Out");
+ }
+ /* Disable Tx */
+ outw(TxDisable, BASE + MACCtrl1);
+
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void sundance_disable ( struct nic *nic __unused ) {
+ /* put the card in its initial state */
+ /* This function serves 3 purposes.
+ * This disables DMA and interrupts so we don't receive
+ * unexpected packets or interrupts from the card after
+ * etherboot has finished.
+ * This frees resources so etherboot may use
+ * this driver on another interface
+ * This allows etherboot to reinitialize the interface
+ * if something is something goes wrong.
+ */
+ outw(0x0000, BASE + IntrEnable);
+ /* Stop the Chipchips Tx and Rx Status */
+ outw(TxDisable | RxDisable | StatsDisable, BASE + MACCtrl1);
+}
+
+static struct nic_operations sundance_operations = {
+ .connect = dummy_connect,
+ .poll = sundance_poll,
+ .transmit = sundance_transmit,
+ .irq = sundance_irq,
+
+};
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+static int sundance_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ u8 ee_data[EEPROM_SIZE];
+ u16 mii_ctl;
+ int i;
+ int speed;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ /* BASE is used throughout to address the card */
+ BASE = pci->ioaddr;
+ printf(" sundance.c: Found %s Vendor=0x%hX Device=0x%hX\n",
+ pci->id->name, pci->vendor, pci->device);
+
+ /* Get the MAC Address by reading the EEPROM */
+ for (i = 0; i < 3; i++) {
+ ((u16 *) ee_data)[i] =
+ le16_to_cpu(eeprom_read(BASE, i + EEPROM_SA_OFFSET));
+ }
+ /* Update the nic structure with the MAC Address */
+ for (i = 0; i < ETH_ALEN; i++) {
+ nic->node_addr[i] = ee_data[i];
+ }
+
+ /* Set the card as PCI Bus Master */
+ adjust_pci_device(pci);
+
+// sdc->mii_if.dev = pci;
+// sdc->mii_if.phy_id_mask = 0x1f;
+// sdc->mii_if.reg_num_mask = 0x1f;
+
+ /* point to private storage */
+ sdc = &sdx;
+
+ sdc->nic_name = pci->id->name;
+ sdc->mtu = mtu;
+
+ pci_read_config_byte(pci, PCI_REVISION_ID, &sdc->pci_rev_id);
+
+ DBG ( "Device revision id: %hx\n", sdc->pci_rev_id );
+
+ /* Print out some hardware info */
+ DBG ( "%s: %s at ioaddr %hX, ",
+ pci->id->name, nic->node_addr, (unsigned int) BASE);
+
+ sdc->mii_preamble_required = 0;
+ if (1) {
+ int phy, phy_idx = 0;
+ sdc->phys[0] = 1; /* Default Setting */
+ sdc->mii_preamble_required++;
+ for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
+ int mii_status = mdio_read(nic, phy, MII_BMSR);
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ sdc->phys[phy_idx++] = phy;
+ sdc->mii_if.advertising =
+ mdio_read(nic, phy, MII_ADVERTISE);
+ if ((mii_status & 0x0040) == 0)
+ sdc->mii_preamble_required++;
+ DBG
+ ( "%s: MII PHY found at address %d, status " "%hX advertising %hX\n", sdc->nic_name, phy, mii_status, sdc->mii_if.advertising );
+ }
+ }
+ sdc->mii_preamble_required--;
+ if (phy_idx == 0)
+ printf("%s: No MII transceiver found!\n",
+ sdc->nic_name);
+ sdc->mii_if.phy_id = sdc->phys[0];
+ }
+
+ /* Parse override configuration */
+ sdc->an_enable = 1;
+ if (strcasecmp(media, "autosense") != 0) {
+ sdc->an_enable = 0;
+ if (strcasecmp(media, "100mbps_fd") == 0 ||
+ strcasecmp(media, "4") == 0) {
+ sdc->speed = 100;
+ sdc->mii_if.full_duplex = 1;
+ } else if (strcasecmp(media, "100mbps_hd") == 0
+ || strcasecmp(media, "3") == 0) {
+ sdc->speed = 100;
+ sdc->mii_if.full_duplex = 0;
+ } else if (strcasecmp(media, "10mbps_fd") == 0 ||
+ strcasecmp(media, "2") == 0) {
+ sdc->speed = 10;
+ sdc->mii_if.full_duplex = 1;
+ } else if (strcasecmp(media, "10mbps_hd") == 0 ||
+ strcasecmp(media, "1") == 0) {
+ sdc->speed = 10;
+ sdc->mii_if.full_duplex = 0;
+ } else {
+ sdc->an_enable = 1;
+ }
+ }
+ if (flowctrl == 1)
+ sdc->flowctrl = 1;
+
+ /* Fibre PHY? */
+ if (inl(BASE + ASICCtrl) & 0x80) {
+ /* Default 100Mbps Full */
+ if (sdc->an_enable) {
+ sdc->speed = 100;
+ sdc->mii_if.full_duplex = 1;
+ sdc->an_enable = 0;
+ }
+ }
+
+ /* The Linux driver uses flow control and resets the link here. This means the
+ mii section from above would need to be re done I believe. Since it serves
+ no real purpose leave it out. */
+
+ /* Force media type */
+ if (!sdc->an_enable) {
+ mii_ctl = 0;
+ mii_ctl |= (sdc->speed == 100) ? BMCR_SPEED100 : 0;
+ mii_ctl |= (sdc->mii_if.full_duplex) ? BMCR_FULLDPLX : 0;
+ mdio_write(nic, sdc->phys[0], MII_BMCR, mii_ctl);
+ printf("Override speed=%d, %s duplex\n",
+ sdc->speed,
+ sdc->mii_if.full_duplex ? "Full" : "Half");
+ }
+
+ /* Reset the chip to erase previous misconfiguration */
+ DBG ( "ASIC Control is %#x\n", inl(BASE + ASICCtrl) );
+ outw(0x007f, BASE + ASICCtrl + 2);
+
+ /*
+ * wait for reset to complete
+ * this is heavily inspired by the linux sundance driver
+ * according to the linux driver it can take up to 1ms for the reset
+ * to complete
+ */
+ i = 0;
+ while(inl(BASE + ASICCtrl) & (ResetBusy << 16)) {
+ if(i++ >= 10) {
+ DBG("sundance: NIC reset did not complete.\n");
+ break;
+ }
+ udelay(100);
+ }
+
+ DBG ( "ASIC Control is now %#x.\n", inl(BASE + ASICCtrl) );
+
+ sundance_reset(nic);
+ if (sdc->an_enable) {
+ u16 mii_advertise, mii_lpa;
+ mii_advertise =
+ mdio_read(nic, sdc->phys[0], MII_ADVERTISE);
+ mii_lpa = mdio_read(nic, sdc->phys[0], MII_LPA);
+ mii_advertise &= mii_lpa;
+ if (mii_advertise & ADVERTISE_100FULL)
+ sdc->speed = 100;
+ else if (mii_advertise & ADVERTISE_100HALF)
+ sdc->speed = 100;
+ else if (mii_advertise & ADVERTISE_10FULL)
+ sdc->speed = 10;
+ else if (mii_advertise & ADVERTISE_10HALF)
+ sdc->speed = 10;
+ } else {
+ mii_ctl = mdio_read(nic, sdc->phys[0], MII_BMCR);
+ speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10;
+ sdc->speed = speed;
+ printf("%s: Link changed: %dMbps ,", sdc->nic_name, speed);
+ printf("%s duplex.\n", (mii_ctl & BMCR_FULLDPLX) ?
+ "full" : "half");
+ }
+ check_duplex(nic);
+ if (sdc->flowctrl && sdc->mii_if.full_duplex) {
+ outw(inw(BASE + MulticastFilter1 + 2) | 0x0200,
+ BASE + MulticastFilter1 + 2);
+ outw(inw(BASE + MACCtrl0) | EnbFlowCtrl, BASE + MACCtrl0);
+ }
+ printf("%dMbps, %s-Duplex\n", sdc->speed,
+ sdc->mii_if.full_duplex ? "Full" : "Half");
+
+ /* point to NIC specific routines */
+ nic->nic_op = &sundance_operations;
+
+ nic->irqno = pci->irq;
+ nic->ioaddr = BASE;
+
+ return 1;
+}
+
+
+/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */
+static int eeprom_read(long ioaddr, int location)
+{
+ int boguscnt = 10000; /* Typical 1900 ticks */
+ outw(0x0200 | (location & 0xff), ioaddr + EECtrl);
+ do {
+ if (!(inw(ioaddr + EECtrl) & 0x8000)) {
+ return inw(ioaddr + EEData);
+ }
+ }
+ while (--boguscnt > 0);
+ return 0;
+}
+
+/* MII transceiver control section.
+ Read and write the MII registers using software-generated serial
+ MDIO protocol. See the MII specifications or DP83840A data sheet
+ for details.
+
+ The maximum data clock rate is 2.5 Mhz.
+ The timing is decoupled from the processor clock by flushing the write
+ from the CPU write buffer with a following read, and using PCI
+ transaction time. */
+
+#define mdio_in(mdio_addr) inb(mdio_addr)
+#define mdio_out(value, mdio_addr) outb(value, mdio_addr)
+#define mdio_delay(mdio_addr) inb(mdio_addr)
+
+enum mii_reg_bits {
+ MDIO_ShiftClk = 0x0001, MDIO_Data = 0x0002, MDIO_EnbOutput =
+ 0x0004,
+};
+#define MDIO_EnbIn (0)
+#define MDIO_WRITE0 (MDIO_EnbOutput)
+#define MDIO_WRITE1 (MDIO_Data | MDIO_EnbOutput)
+
+/* Generate the preamble required for initial synchronization and
+ a few older transceivers. */
+static void mdio_sync(long mdio_addr)
+{
+ int bits = 32;
+
+ /* Establish sync by sending at least 32 logic ones. */
+ while (--bits >= 0) {
+ mdio_out(MDIO_WRITE1, mdio_addr);
+ mdio_delay(mdio_addr);
+ mdio_out(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+}
+
+static int
+mdio_read(struct nic *nic __unused, int phy_id, unsigned int location)
+{
+ long mdio_addr = BASE + MIICtrl;
+ int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+ int i, retval = 0;
+
+ if (sdc->mii_preamble_required)
+ mdio_sync(mdio_addr);
+
+ /* Shift the read command bits out. */
+ for (i = 15; i >= 0; i--) {
+ int dataval =
+ (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
+
+ mdio_out(dataval, mdio_addr);
+ mdio_delay(mdio_addr);
+ mdio_out(dataval | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ /* Read the two transition, 16 data, and wire-idle bits. */
+ for (i = 19; i > 0; i--) {
+ mdio_out(MDIO_EnbIn, mdio_addr);
+ mdio_delay(mdio_addr);
+ retval = (retval << 1) | ((mdio_in(mdio_addr) & MDIO_Data)
+ ? 1 : 0);
+ mdio_out(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ return (retval >> 1) & 0xffff;
+}
+
+static void
+mdio_write(struct nic *nic __unused, int phy_id,
+ unsigned int location, int value)
+{
+ long mdio_addr = BASE + MIICtrl;
+ int mii_cmd =
+ (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
+ int i;
+
+ if (sdc->mii_preamble_required)
+ mdio_sync(mdio_addr);
+
+ /* Shift the command bits out. */
+ for (i = 31; i >= 0; i--) {
+ int dataval =
+ (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
+ mdio_out(dataval, mdio_addr);
+ mdio_delay(mdio_addr);
+ mdio_out(dataval | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ /* Clear out extra bits. */
+ for (i = 2; i > 0; i--) {
+ mdio_out(MDIO_EnbIn, mdio_addr);
+ mdio_delay(mdio_addr);
+ mdio_out(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ return;
+}
+
+static void set_rx_mode(struct nic *nic __unused)
+{
+ int i;
+ u16 mc_filter[4]; /* Multicast hash filter */
+ u32 rx_mode;
+
+ memset(mc_filter, 0xff, sizeof(mc_filter));
+ rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+
+ if (sdc->mii_if.full_duplex && sdc->flowctrl)
+ mc_filter[3] |= 0x0200;
+ for (i = 0; i < 4; i++)
+ outw(mc_filter[i], BASE + MulticastFilter0 + i * 2);
+ outb(rx_mode, BASE + RxMode);
+ return;
+}
+
+static struct pci_device_id sundance_nics[] = {
+ PCI_ROM(0x13f0, 0x0201, "sundance", "ST201 Sundance 'Alta' based Adaptor", 0),
+ PCI_ROM(0x1186, 0x1002, "dfe530txs", "D-Link DFE530TXS (Sundance ST201 Alta)", 0),
+ PCI_ROM(0x13f0, 0x0200, "ip100a", "IC+ IP100A", 0),
+};
+
+PCI_DRIVER ( sundance_driver, sundance_nics, PCI_NO_CLASS );
+
+DRIVER ( "SUNDANCE/PCI", nic_driver, pci_driver, sundance_driver,
+ sundance_probe, sundance_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3.c
new file mode 100644
index 00000000..b2cba72e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3.c
@@ -0,0 +1,941 @@
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include <mii.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/timer.h>
+#include <ipxe/malloc.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/netdevice.h>
+
+#include "tg3.h"
+
+#define TG3_DEF_RX_MODE 0
+#define TG3_DEF_TX_MODE 0
+
+static void tg3_refill_prod_ring(struct tg3 *tp);
+
+/* Do not place this n-ring entries value into the tp struct itself,
+ * we really want to expose these constants to GCC so that modulo et
+ * al. operations are done with shifts and masks instead of with
+ * hw multiply/modulo instructions. Another solution would be to
+ * replace things like '% foo' with '& (foo - 1)'.
+ */
+
+#define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \
+ TG3_TX_RING_SIZE)
+
+/* FIXME: does TG3_RX_RET_MAX_SIZE_5705 work for all cards? */
+#define TG3_RX_RCB_RING_BYTES(tp) \
+ (sizeof(struct tg3_rx_buffer_desc) * (TG3_RX_RET_MAX_SIZE_5705))
+
+#define TG3_RX_STD_RING_BYTES(tp) \
+ (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_MAX_SIZE_5700)
+
+void tg3_rx_prodring_fini(struct tg3_rx_prodring_set *tpr)
+{ DBGP("%s\n", __func__);
+
+ if (tpr->rx_std) {
+ free_dma(tpr->rx_std, TG3_RX_STD_RING_BYTES(tp));
+ tpr->rx_std = NULL;
+ }
+}
+
+/*
+ * Must not be invoked with interrupt sources disabled and
+ * the hardware shutdown down.
+ */
+static void tg3_free_consistent(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tp->tx_ring) {
+ free_dma(tp->tx_ring, TG3_TX_RING_BYTES);
+ tp->tx_ring = NULL;
+ }
+
+ free(tp->tx_buffers);
+ tp->tx_buffers = NULL;
+
+ if (tp->rx_rcb) {
+ free_dma(tp->rx_rcb, TG3_RX_RCB_RING_BYTES(tp));
+ tp->rx_rcb_mapping = 0;
+ tp->rx_rcb = NULL;
+ }
+
+ tg3_rx_prodring_fini(&tp->prodring);
+
+ if (tp->hw_status) {
+ free_dma(tp->hw_status, TG3_HW_STATUS_SIZE);
+ tp->status_mapping = 0;
+ tp->hw_status = NULL;
+ }
+}
+
+/*
+ * Must not be invoked with interrupt sources disabled and
+ * the hardware shutdown down. Can sleep.
+ */
+int tg3_alloc_consistent(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ struct tg3_hw_status *sblk;
+ struct tg3_rx_prodring_set *tpr = &tp->prodring;
+
+ tp->hw_status = malloc_dma(TG3_HW_STATUS_SIZE, TG3_DMA_ALIGNMENT);
+ if (!tp->hw_status) {
+ DBGC(tp->dev, "hw_status alloc failed\n");
+ goto err_out;
+ }
+ tp->status_mapping = virt_to_bus(tp->hw_status);
+
+ memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+ sblk = tp->hw_status;
+
+ tpr->rx_std = malloc_dma(TG3_RX_STD_RING_BYTES(tp), TG3_DMA_ALIGNMENT);
+ if (!tpr->rx_std) {
+ DBGC(tp->dev, "rx prodring alloc failed\n");
+ goto err_out;
+ }
+ tpr->rx_std_mapping = virt_to_bus(tpr->rx_std);
+ memset(tpr->rx_std, 0, TG3_RX_STD_RING_BYTES(tp));
+
+ tp->tx_buffers = zalloc(sizeof(struct ring_info) * TG3_TX_RING_SIZE);
+ if (!tp->tx_buffers)
+ goto err_out;
+
+ tp->tx_ring = malloc_dma(TG3_TX_RING_BYTES, TG3_DMA_ALIGNMENT);
+ if (!tp->tx_ring)
+ goto err_out;
+ tp->tx_desc_mapping = virt_to_bus(tp->tx_ring);
+
+ /*
+ * When RSS is enabled, the status block format changes
+ * slightly. The "rx_jumbo_consumer", "reserved",
+ * and "rx_mini_consumer" members get mapped to the
+ * other three rx return ring producer indexes.
+ */
+
+ tp->rx_rcb_prod_idx = &sblk->idx[0].rx_producer;
+
+ tp->rx_rcb = malloc_dma(TG3_RX_RCB_RING_BYTES(tp), TG3_DMA_ALIGNMENT);
+ if (!tp->rx_rcb)
+ goto err_out;
+ tp->rx_rcb_mapping = virt_to_bus(tp->rx_rcb);
+
+ memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+
+ return 0;
+
+err_out:
+ tg3_free_consistent(tp);
+ return -ENOMEM;
+}
+
+#define TG3_RX_STD_BUFF_RING_BYTES(tp) \
+ (sizeof(struct ring_info) * TG3_RX_STD_MAX_SIZE_5700)
+#define TG3_RX_STD_RING_BYTES(tp) \
+ (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_MAX_SIZE_5700)
+
+/* Initialize rx rings for packet processing.
+ *
+ * The chip has been shut down and the driver detached from
+ * the networking, so no interrupts or new tx packets will
+ * end up in the driver.
+ */
+static int tg3_rx_prodring_alloc(struct tg3 __unused *tp,
+ struct tg3_rx_prodring_set *tpr)
+{ DBGP("%s\n", __func__);
+
+ u32 i;
+
+ tpr->rx_std_cons_idx = 0;
+ tpr->rx_std_prod_idx = 0;
+
+ /* Initialize invariants of the rings, we only set this
+ * stuff once. This works because the card does not
+ * write into the rx buffer posting rings.
+ */
+ /* FIXME: does TG3_RX_STD_MAX_SIZE_5700 work on all cards? */
+ for (i = 0; i < TG3_RX_STD_MAX_SIZE_5700; i++) {
+ struct tg3_rx_buffer_desc *rxd;
+
+ rxd = &tpr->rx_std[i];
+ rxd->idx_len = (TG3_RX_STD_DMA_SZ - 64 - 2) << RXD_LEN_SHIFT;
+ rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT);
+ rxd->opaque = (RXD_OPAQUE_RING_STD |
+ (i << RXD_OPAQUE_INDEX_SHIFT));
+ }
+
+ return 0;
+}
+
+static void tg3_rx_iob_free(struct io_buffer *iobs[], int i)
+{ DBGP("%s\n", __func__);
+
+ if (iobs[i] == NULL)
+ return;
+
+ free_iob(iobs[i]);
+ iobs[i] = NULL;
+}
+
+static void tg3_rx_prodring_free(struct tg3_rx_prodring_set *tpr)
+{ DBGP("%s\n", __func__);
+
+ unsigned int i;
+
+ for (i = 0; i < TG3_DEF_RX_RING_PENDING; i++)
+ tg3_rx_iob_free(tpr->rx_iobufs, i);
+}
+
+/* Initialize tx/rx rings for packet processing.
+ *
+ * The chip has been shut down and the driver detached from
+ * the networking, so no interrupts or new tx packets will
+ * end up in the driver.
+ */
+int tg3_init_rings(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ /* Free up all the SKBs. */
+/// tg3_free_rings(tp);
+
+ tp->last_tag = 0;
+ tp->last_irq_tag = 0;
+ tp->hw_status->status = 0;
+ tp->hw_status->status_tag = 0;
+ memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+ tp->tx_prod = 0;
+ tp->tx_cons = 0;
+ if (tp->tx_ring)
+ memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
+
+ tp->rx_rcb_ptr = 0;
+ if (tp->rx_rcb)
+ memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+
+ if (tg3_rx_prodring_alloc(tp, &tp->prodring)) {
+ DBGC(tp->dev, "tg3_rx_prodring_alloc() failed\n");
+ tg3_rx_prodring_free(&tp->prodring);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int tg3_open(struct net_device *dev)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+ struct tg3_rx_prodring_set *tpr = &tp->prodring;
+ int err = 0;
+
+ tg3_set_power_state_0(tp);
+
+ /* Initialize MAC address and backoff seed. */
+ __tg3_set_mac_addr(tp, 0);
+
+ err = tg3_alloc_consistent(tp);
+ if (err)
+ return err;
+
+ tpr->rx_std_iob_cnt = 0;
+ tg3_refill_prod_ring(tp);
+
+ err = tg3_init_hw(tp, 1);
+ if (err != 0)
+ DBGC(tp->dev, "tg3_init_hw failed: %s\n", strerror(err));
+
+ return err;
+}
+
+static inline u32 tg3_tx_avail(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ /* Tell compiler to fetch tx indices from memory. */
+ barrier();
+ return TG3_DEF_TX_RING_PENDING -
+ ((tp->tx_prod - tp->tx_cons) & (TG3_TX_RING_SIZE - 1));
+}
+
+#if 0
+/**
+ *
+ * Prints all registers that could cause a set ERR bit in hw_status->status
+ */
+static void tg3_dump_err_reg(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ printf("FLOW_ATTN: %#08x\n", tr32(HOSTCC_FLOW_ATTN));
+ printf("MAC ATTN: %#08x\n", tr32(MAC_STATUS));
+ printf("MSI STATUS: %#08x\n", tr32(MSGINT_STATUS));
+ printf("DMA RD: %#08x\n", tr32(RDMAC_STATUS));
+ printf("DMA WR: %#08x\n", tr32(WDMAC_STATUS));
+ printf("TX CPU STATE: %#08x\n", tr32(TX_CPU_STATE));
+ printf("RX CPU STATE: %#08x\n", tr32(RX_CPU_STATE));
+}
+
+static void __unused tw32_mailbox2(struct tg3 *tp, uint32_t reg, uint32_t val)
+{ DBGP("%s\n", __func__);
+
+ tw32_mailbox(reg, val);
+ tr32(reg);
+}
+#endif
+
+#define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1))
+
+/* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and
+ * support TG3_FLAG_HW_TSO_1 or firmware TSO only.
+ */
+static int tg3_transmit(struct net_device *dev, struct io_buffer *iob)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+ u32 len, entry;
+ dma_addr_t mapping;
+ u32 bmsr;
+
+ if (tg3_tx_avail(tp) < 1) {
+ DBGC(dev, "Transmit ring full\n");
+ return -ENOBUFS;
+ }
+
+ entry = tp->tx_prod;
+
+ iob_pad(iob, ETH_ZLEN);
+ mapping = virt_to_bus(iob->data);
+ len = iob_len(iob);
+
+ tp->tx_buffers[entry].iob = iob;
+
+ tg3_set_txd(tp, entry, mapping, len, TXD_FLAG_END);
+
+ entry = NEXT_TX(entry);
+
+ /* Packets are ready, update Tx producer idx local and on card. */
+ tw32_tx_mbox(tp->prodmbox, entry);
+
+ writel(entry, tp->regs + MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW);
+
+ tp->tx_prod = entry;
+
+ mb();
+
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+
+ return 0;
+}
+
+static void tg3_tx_complete(struct net_device *dev)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+ u32 hw_idx = tp->hw_status->idx[0].tx_consumer;
+ u32 sw_idx = tp->tx_cons;
+
+ while (sw_idx != hw_idx) {
+ struct io_buffer *iob = tp->tx_buffers[sw_idx].iob;
+
+ DBGC2(dev, "Transmitted packet: %zd bytes\n", iob_len(iob));
+
+ netdev_tx_complete(dev, iob);
+ sw_idx = NEXT_TX(sw_idx);
+ }
+
+ tp->tx_cons = sw_idx;
+}
+
+#define TG3_RX_STD_BUFF_RING_BYTES(tp) \
+ (sizeof(struct ring_info) * TG3_RX_STD_MAX_SIZE_5700)
+#define TG3_RX_STD_RING_BYTES(tp) \
+ (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_MAX_SIZE_5700)
+
+/* Returns 0 or < 0 on error.
+ *
+ * We only need to fill in the address because the other members
+ * of the RX descriptor are invariant, see tg3_init_rings.
+ *
+ * Note the purposeful assymetry of cpu vs. chip accesses. For
+ * posting buffers we only dirty the first cache line of the RX
+ * descriptor (containing the address). Whereas for the RX status
+ * buffers the cpu only reads the last cacheline of the RX descriptor
+ * (to fetch the error flags, vlan tag, checksum, and opaque cookie).
+ */
+static int tg3_alloc_rx_iob(struct tg3_rx_prodring_set *tpr, u32 dest_idx_unmasked)
+{ DBGP("%s\n", __func__);
+
+ struct tg3_rx_buffer_desc *desc;
+ struct io_buffer *iob;
+ dma_addr_t mapping;
+ int dest_idx, iob_idx;
+
+ dest_idx = dest_idx_unmasked & (TG3_RX_STD_MAX_SIZE_5700 - 1);
+ desc = &tpr->rx_std[dest_idx];
+
+ /* Do not overwrite any of the map or rp information
+ * until we are sure we can commit to a new buffer.
+ *
+ * Callers depend upon this behavior and assume that
+ * we leave everything unchanged if we fail.
+ */
+ iob = alloc_iob(TG3_RX_STD_DMA_SZ);
+ if (iob == NULL)
+ return -ENOMEM;
+
+ iob_idx = dest_idx % TG3_DEF_RX_RING_PENDING;
+ tpr->rx_iobufs[iob_idx] = iob;
+
+ mapping = virt_to_bus(iob->data);
+
+ desc->addr_hi = ((u64)mapping >> 32);
+ desc->addr_lo = ((u64)mapping & 0xffffffff);
+
+ return 0;
+}
+
+static void tg3_refill_prod_ring(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ struct tg3_rx_prodring_set *tpr = &tp->prodring;
+ int idx = tpr->rx_std_prod_idx;
+
+ DBGCP(tp->dev, "%s\n", __func__);
+
+ while (tpr->rx_std_iob_cnt < TG3_DEF_RX_RING_PENDING) {
+ if (tpr->rx_iobufs[idx % TG3_DEF_RX_RING_PENDING] == NULL) {
+ if (tg3_alloc_rx_iob(tpr, idx) < 0) {
+ DBGC(tp->dev, "alloc_iob() failed for descriptor %d\n", idx);
+ break;
+ }
+ DBGC2(tp->dev, "allocated iob_buffer for descriptor %d\n", idx);
+ }
+
+ idx = (idx + 1) % TG3_RX_STD_MAX_SIZE_5700;
+ tpr->rx_std_iob_cnt++;
+ }
+
+ tpr->rx_std_prod_idx = idx;
+ tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, idx);
+}
+
+static void tg3_rx_complete(struct net_device *dev)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+
+ u32 sw_idx = tp->rx_rcb_ptr;
+ u16 hw_idx;
+ struct tg3_rx_prodring_set *tpr = &tp->prodring;
+
+ hw_idx = *(tp->rx_rcb_prod_idx);
+
+ while (sw_idx != hw_idx) {
+ struct tg3_rx_buffer_desc *desc = &tp->rx_rcb[sw_idx];
+ u32 desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
+ int iob_idx = desc_idx % TG3_DEF_RX_RING_PENDING;
+ struct io_buffer *iob = tpr->rx_iobufs[iob_idx];
+ unsigned int len;
+
+ DBGC2(dev, "RX - desc_idx: %d sw_idx: %d hw_idx: %d\n", desc_idx, sw_idx, hw_idx);
+
+ assert(iob != NULL);
+
+ if ((desc->err_vlan & RXD_ERR_MASK) != 0 &&
+ (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) {
+ /* drop packet */
+ DBGC(dev, "Corrupted packet received\n");
+ netdev_rx_err(dev, iob, -EINVAL);
+ } else {
+ len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) -
+ ETH_FCS_LEN;
+ iob_put(iob, len);
+ netdev_rx(dev, iob);
+
+ DBGC2(dev, "Received packet: %d bytes %d %d\n", len, sw_idx, hw_idx);
+ }
+
+ sw_idx++;
+ sw_idx &= TG3_RX_RET_MAX_SIZE_5705 - 1;
+
+ tpr->rx_iobufs[iob_idx] = NULL;
+ tpr->rx_std_iob_cnt--;
+ }
+
+ tp->rx_rcb_ptr = sw_idx;
+
+ tg3_refill_prod_ring(tp);
+}
+
+static void tg3_poll(struct net_device *dev)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+
+ /* ACK interrupts */
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00);
+ tp->hw_status->status &= ~SD_STATUS_UPDATED;
+
+ tg3_poll_link(tp);
+ tg3_tx_complete(dev);
+ tg3_rx_complete(dev);
+}
+
+static void tg3_close(struct net_device *dev)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+
+ DBGP("%s\n", __func__);
+
+ tg3_halt(tp);
+ tg3_rx_prodring_free(&tp->prodring);
+ tg3_flag_clear(tp, INIT_COMPLETE);
+
+ tg3_free_consistent(tp);
+
+}
+
+static void tg3_irq(struct net_device *dev, int enable)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+
+ DBGP("%s: %d\n", __func__, enable);
+
+ if (enable)
+ tg3_enable_ints(tp);
+ else
+ tg3_disable_ints(tp);
+}
+
+static struct net_device_operations tg3_netdev_ops = {
+ .open = tg3_open,
+ .close = tg3_close,
+ .poll = tg3_poll,
+ .transmit = tg3_transmit,
+ .irq = tg3_irq,
+};
+
+#define TEST_BUFFER_SIZE 0x2000
+
+int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, dma_addr_t buf_dma, int size, int to_device);
+void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val);
+
+static int tg3_test_dma(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ dma_addr_t buf_dma;
+ u32 *buf;
+ int ret = 0;
+
+ buf = malloc_dma(TEST_BUFFER_SIZE, TG3_DMA_ALIGNMENT);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto out_nofree;
+ }
+ buf_dma = virt_to_bus(buf);
+ DBGC2(tp->dev, "dma test buffer, virt: %p phys: %#08x\n", buf, buf_dma);
+
+ if (tg3_flag(tp, 57765_PLUS)) {
+ tp->dma_rwctrl = DMA_RWCTRL_DIS_CACHE_ALIGNMENT;
+ goto out;
+ }
+
+ tp->dma_rwctrl = ((0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
+ (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT));
+
+ if (tg3_flag(tp, PCI_EXPRESS)) {
+ /* DMA read watermark not used on PCIE */
+ tp->dma_rwctrl |= 0x00180000;
+ } else if (!tg3_flag(tp, PCIX_MODE)) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+ tp->dma_rwctrl |= 0x003f0000;
+ else
+ tp->dma_rwctrl |= 0x003f000f;
+ } else {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+ u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
+ u32 read_water = 0x7;
+
+ if (ccval == 0x6 || ccval == 0x7)
+ tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703)
+ read_water = 4;
+ /* Set bit 23 to enable PCIX hw bug fix */
+ tp->dma_rwctrl |=
+ (read_water << DMA_RWCTRL_READ_WATER_SHIFT) |
+ (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
+ (1 << 23);
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+ /* 5780 always in PCIX mode */
+ tp->dma_rwctrl |= 0x00144000;
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+ /* 5714 always in PCIX mode */
+ tp->dma_rwctrl |= 0x00148000;
+ } else {
+ tp->dma_rwctrl |= 0x001b000f;
+ }
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
+ tp->dma_rwctrl &= 0xfffffff0;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+ /* Remove this if it causes problems for some boards. */
+ tp->dma_rwctrl |= DMA_RWCTRL_USE_MEM_READ_MULT;
+
+ /* On 5700/5701 chips, we need to set this bit.
+ * Otherwise the chip will issue cacheline transactions
+ * to streamable DMA memory with not all the byte
+ * enables turned on. This is an error on several
+ * RISC PCI controllers, in particular sparc64.
+ *
+ * On 5703/5704 chips, this bit has been reassigned
+ * a different meaning. In particular, it is used
+ * on those chips to enable a PCI-X workaround.
+ */
+ tp->dma_rwctrl |= DMA_RWCTRL_ASSERT_ALL_BE;
+ }
+
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+
+#if 0
+ /* Unneeded, already done by tg3_get_invariants. */
+ tg3_switch_clocks(tp);
+#endif
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
+ goto out;
+
+ /* It is best to perform DMA test with maximum write burst size
+ * to expose the 5700/5701 write DMA bug.
+ */
+ tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+
+ while (1) {
+ u32 *p = buf, i;
+
+ for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++)
+ p[i] = i;
+
+ /* Send the buffer to the chip. */
+ ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 1);
+ if (ret) {
+ DBGC(&tp->pdev->dev,
+ "%s: Buffer write failed. err = %d\n",
+ __func__, ret);
+ break;
+ }
+
+ /* validate data reached card RAM correctly. */
+ for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
+ u32 val;
+ tg3_read_mem(tp, 0x2100 + (i*4), &val);
+ if (le32_to_cpu(val) != p[i]) {
+ DBGC(&tp->pdev->dev,
+ "%s: Buffer corrupted on device! "
+ "(%d != %d)\n", __func__, val, i);
+ /* ret = -ENODEV here? */
+ }
+ p[i] = 0;
+ }
+
+ /* Now read it back. */
+ ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0);
+ if (ret) {
+ DBGC(&tp->pdev->dev, "%s: Buffer read failed. "
+ "err = %d\n", __func__, ret);
+ break;
+ }
+
+ /* Verify it. */
+ for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
+ if (p[i] == i)
+ continue;
+
+ if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
+ DMA_RWCTRL_WRITE_BNDRY_16) {
+ tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+ tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+ break;
+ } else {
+ DBGC(&tp->pdev->dev,
+ "%s: Buffer corrupted on read back! "
+ "(%d != %d)\n", __func__, p[i], i);
+ ret = -ENODEV;
+ goto out;
+ }
+ }
+
+ if (i == (TEST_BUFFER_SIZE / sizeof(u32))) {
+ /* Success. */
+ ret = 0;
+ break;
+ }
+ }
+
+ if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
+ DMA_RWCTRL_WRITE_BNDRY_16) {
+ /* DMA test passed without adjusting DMA boundary,
+ * now look for chipsets that are known to expose the
+ * DMA bug without failing the test.
+ */
+ tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+ tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
+
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+ }
+
+out:
+ free_dma(buf, TEST_BUFFER_SIZE);
+out_nofree:
+ return ret;
+}
+
+static int tg3_init_one(struct pci_device *pdev)
+{ DBGP("%s\n", __func__);
+
+ struct net_device *dev;
+ struct tg3 *tp;
+ int err = 0;
+ unsigned long reg_base, reg_size;
+
+ adjust_pci_device(pdev);
+
+ dev = alloc_etherdev(sizeof(*tp));
+ if (!dev) {
+ DBGC(&pdev->dev, "Failed to allocate etherdev\n");
+ err = -ENOMEM;
+ goto err_out_disable_pdev;
+ }
+
+ netdev_init(dev, &tg3_netdev_ops);
+ pci_set_drvdata(pdev, dev);
+
+ dev->dev = &pdev->dev;
+
+ tp = netdev_priv(dev);
+ tp->pdev = pdev;
+ tp->dev = dev;
+ tp->rx_mode = TG3_DEF_RX_MODE;
+ tp->tx_mode = TG3_DEF_TX_MODE;
+
+ /* Subsystem IDs are required later */
+ pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->subsystem_vendor);
+ pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_ID, &tp->subsystem_device);
+
+ /* The word/byte swap controls here control register access byte
+ * swapping. DMA data byte swapping is controlled in the GRC_MODE
+ * setting below.
+ */
+ tp->misc_host_ctrl =
+ MISC_HOST_CTRL_MASK_PCI_INT |
+ MISC_HOST_CTRL_WORD_SWAP |
+ MISC_HOST_CTRL_INDIR_ACCESS |
+ MISC_HOST_CTRL_PCISTATE_RW;
+
+ /* The NONFRM (non-frame) byte/word swap controls take effect
+ * on descriptor entries, anything which isn't packet data.
+ *
+ * The StrongARM chips on the board (one for tx, one for rx)
+ * are running in big-endian mode.
+ */
+ tp->grc_mode = (GRC_MODE_WSWAP_DATA | GRC_MODE_BSWAP_DATA |
+ GRC_MODE_WSWAP_NONFRM_DATA);
+#if __BYTE_ORDER == __BIG_ENDIAN
+ tp->grc_mode |= GRC_MODE_BSWAP_NONFRM_DATA;
+#endif
+
+ /* FIXME: how can we detect errors here? */
+ reg_base = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
+ reg_size = pci_bar_size(pdev, PCI_BASE_ADDRESS_0);
+
+ tp->regs = ioremap(reg_base, reg_size);
+ if (!tp->regs) {
+ DBGC(&pdev->dev, "Failed to remap device registers\n");
+ errno = -ENOENT;
+ goto err_out_disable_pdev;
+ }
+
+ err = tg3_get_invariants(tp);
+ if (err) {
+ DBGC(&pdev->dev, "Problem fetching invariants of chip, aborting\n");
+ goto err_out_iounmap;
+ }
+
+ tg3_init_bufmgr_config(tp);
+
+ err = tg3_get_device_address(tp);
+ if (err) {
+ DBGC(&pdev->dev, "Could not obtain valid ethernet address, aborting\n");
+ goto err_out_iounmap;
+ }
+
+ /*
+ * Reset chip in case UNDI or EFI driver did not shutdown
+ * DMA self test will enable WDMAC and we'll see (spurious)
+ * pending DMA on the PCI bus at that point.
+ */
+ if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
+ (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
+ tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
+ tg3_halt(tp);
+ }
+
+ err = tg3_test_dma(tp);
+ if (err) {
+ DBGC(&pdev->dev, "DMA engine test failed, aborting\n");
+ goto err_out_iounmap;
+ }
+
+ tp->int_mbox = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW;
+ tp->consmbox = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW;
+ tp->prodmbox = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW;
+
+ tp->coal_now = HOSTCC_MODE_NOW;
+
+ err = register_netdev(dev);
+ if (err) {
+ DBGC(&pdev->dev, "Cannot register net device, aborting\n");
+ goto err_out_iounmap;
+ }
+
+ /* Call tg3_setup_phy() to start autoneg process, which saves time
+ * over starting autoneg in tg3_open();
+ */
+ err = tg3_setup_phy(tp, 0);
+ if (err) {
+ DBGC(tp->dev, "tg3_setup_phy() call failed in %s\n", __func__);
+ goto err_out_iounmap;
+ }
+
+ return 0;
+
+err_out_iounmap:
+ if (tp->regs) {
+ iounmap(tp->regs);
+ tp->regs = NULL;
+ }
+
+ netdev_put(dev);
+
+err_out_disable_pdev:
+ pci_set_drvdata(pdev, NULL);
+ return err;
+}
+
+static void tg3_remove_one(struct pci_device *pci)
+{ DBGP("%s\n", __func__);
+
+ struct net_device *netdev = pci_get_drvdata(pci);
+
+ unregister_netdev(netdev);
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+}
+
+static struct pci_device_id tg3_nics[] = {
+ PCI_ROM(0x14e4, 0x1644, "14e4-1644", "14e4-1644", 0),
+ PCI_ROM(0x14e4, 0x1645, "14e4-1645", "14e4-1645", 0),
+ PCI_ROM(0x14e4, 0x1646, "14e4-1646", "14e4-1646", 0),
+ PCI_ROM(0x14e4, 0x1647, "14e4-1647", "14e4-1647", 0),
+ PCI_ROM(0x14e4, 0x1648, "14e4-1648", "14e4-1648", 0),
+ PCI_ROM(0x14e4, 0x164d, "14e4-164d", "14e4-164d", 0),
+ PCI_ROM(0x14e4, 0x1653, "14e4-1653", "14e4-1653", 0),
+ PCI_ROM(0x14e4, 0x1654, "14e4-1654", "14e4-1654", 0),
+ PCI_ROM(0x14e4, 0x165d, "14e4-165d", "14e4-165d", 0),
+ PCI_ROM(0x14e4, 0x165e, "14e4-165e", "14e4-165e", 0),
+ PCI_ROM(0x14e4, 0x16a6, "14e4-16a6", "14e4-16a6", 0),
+ PCI_ROM(0x14e4, 0x16a7, "14e4-16a7", "14e4-16a7", 0),
+ PCI_ROM(0x14e4, 0x16a8, "14e4-16a8", "14e4-16a8", 0),
+ PCI_ROM(0x14e4, 0x16c6, "14e4-16c6", "14e4-16c6", 0),
+ PCI_ROM(0x14e4, 0x16c7, "14e4-16c7", "14e4-16c7", 0),
+ PCI_ROM(0x14e4, 0x1696, "14e4-1696", "14e4-1696", 0),
+ PCI_ROM(0x14e4, 0x169c, "14e4-169c", "14e4-169c", 0),
+ PCI_ROM(0x14e4, 0x169d, "14e4-169d", "14e4-169d", 0),
+ PCI_ROM(0x14e4, 0x170d, "14e4-170d", "14e4-170d", 0),
+ PCI_ROM(0x14e4, 0x170e, "14e4-170e", "14e4-170e", 0),
+ PCI_ROM(0x14e4, 0x1649, "14e4-1649", "14e4-1649", 0),
+ PCI_ROM(0x14e4, 0x166e, "14e4-166e", "14e4-166e", 0),
+ PCI_ROM(0x14e4, 0x1659, "14e4-1659", "14e4-1659", 0),
+ PCI_ROM(0x14e4, 0x165a, "14e4-165a", "14e4-165a", 0),
+ PCI_ROM(0x14e4, 0x1677, "14e4-1677", "14e4-1677", 0),
+ PCI_ROM(0x14e4, 0x167d, "14e4-167d", "14e4-167d", 0),
+ PCI_ROM(0x14e4, 0x167e, "14e4-167e", "14e4-167e", 0),
+ PCI_ROM(0x14e4, 0x1600, "14e4-1600", "14e4-1600", 0),
+ PCI_ROM(0x14e4, 0x1601, "14e4-1601", "14e4-1601", 0),
+ PCI_ROM(0x14e4, 0x16f7, "14e4-16f7", "14e4-16f7", 0),
+ PCI_ROM(0x14e4, 0x16fd, "14e4-16fd", "14e4-16fd", 0),
+ PCI_ROM(0x14e4, 0x16fe, "14e4-16fe", "14e4-16fe", 0),
+ PCI_ROM(0x14e4, 0x167a, "14e4-167a", "14e4-167a", 0),
+ PCI_ROM(0x14e4, 0x1672, "14e4-1672", "14e4-1672", 0),
+ PCI_ROM(0x14e4, 0x167b, "14e4-167b", "14e4-167b", 0),
+ PCI_ROM(0x14e4, 0x1673, "14e4-1673", "14e4-1673", 0),
+ PCI_ROM(0x14e4, 0x1674, "14e4-1674", "14e4-1674", 0),
+ PCI_ROM(0x14e4, 0x169a, "14e4-169a", "14e4-169a", 0),
+ PCI_ROM(0x14e4, 0x169b, "14e4-169b", "14e4-169b", 0),
+ PCI_ROM(0x14e4, 0x1693, "14e4-1693", "14e4-1693", 0),
+ PCI_ROM(0x14e4, 0x167f, "14e4-167f", "14e4-167f", 0),
+ PCI_ROM(0x14e4, 0x1668, "14e4-1668", "14e4-1668", 0),
+ PCI_ROM(0x14e4, 0x1669, "14e4-1669", "14e4-1669", 0),
+ PCI_ROM(0x14e4, 0x1678, "14e4-1678", "14e4-1678", 0),
+ PCI_ROM(0x14e4, 0x1679, "14e4-1679", "14e4-1679", 0),
+ PCI_ROM(0x14e4, 0x166a, "14e4-166a", "14e4-166a", 0),
+ PCI_ROM(0x14e4, 0x166b, "14e4-166b", "14e4-166b", 0),
+ PCI_ROM(0x14e4, 0x16dd, "14e4-16dd", "14e4-16dd", 0),
+ PCI_ROM(0x14e4, 0x1712, "14e4-1712", "14e4-1712", 0),
+ PCI_ROM(0x14e4, 0x1713, "14e4-1713", "14e4-1713", 0),
+ PCI_ROM(0x14e4, 0x1698, "14e4-1698", "14e4-1698", 0),
+ PCI_ROM(0x14e4, 0x1684, "14e4-1684", "14e4-1684", 0),
+ PCI_ROM(0x14e4, 0x165b, "14e4-165b", "14e4-165b", 0),
+ PCI_ROM(0x14e4, 0x1681, "14e4-1681", "14e4-1681", 0),
+ PCI_ROM(0x14e4, 0x1680, "14e4-1680", "14e4-1680", 0),
+ PCI_ROM(0x14e4, 0x1688, "14e4-1688", "14e4-1688", 0),
+ PCI_ROM(0x14e4, 0x1689, "14e4-1689", "14e4-1689", 0),
+ PCI_ROM(0x14e4, 0x1699, "14e4-1699", "14e4-1699", 0),
+ PCI_ROM(0x14e4, 0x16a0, "14e4-16a0", "14e4-16a0", 0),
+ PCI_ROM(0x14e4, 0x1692, "14e4-1692", "14e4-1692", 0),
+ PCI_ROM(0x14e4, 0x1690, "14e4-1690", "14e4-1690", 0),
+ PCI_ROM(0x14e4, 0x1694, "14e4-1694", "14e4-1694", 0),
+ PCI_ROM(0x14e4, 0x1691, "14e4-1691", "14e4-1691", 0),
+ PCI_ROM(0x14e4, 0x1655, "14e4-1655", "14e4-1655", 0),
+ PCI_ROM(0x14e4, 0x1656, "14e4-1656", "14e4-1656", 0),
+ PCI_ROM(0x14e4, 0x16b1, "14e4-16b1", "14e4-16b1", 0),
+ PCI_ROM(0x14e4, 0x16b5, "14e4-16b5", "14e4-16b5", 0),
+ PCI_ROM(0x14e4, 0x16b0, "14e4-16b0", "14e4-16b0", 0),
+ PCI_ROM(0x14e4, 0x16b4, "14e4-16b4", "14e4-16b4", 0),
+ PCI_ROM(0x14e4, 0x16b2, "14e4-16b2", "14e4-16b2", 0),
+ PCI_ROM(0x14e4, 0x16b6, "14e4-16b6", "14e4-16b6", 0),
+ PCI_ROM(0x14e4, 0x1657, "14e4-1657", "14e4-1657", 0),
+ PCI_ROM(0x14e4, 0x165f, "14e4-165f", "14e4-165f", 0),
+ PCI_ROM(0x1148, 0x4400, "1148-4400", "1148-4400", 0),
+ PCI_ROM(0x1148, 0x4500, "1148-4500", "1148-4500", 0),
+ PCI_ROM(0x173b, 0x03e8, "173b-03e8", "173b-03e8", 0),
+ PCI_ROM(0x173b, 0x03e9, "173b-03e9", "173b-03e9", 0),
+ PCI_ROM(0x173b, 0x03eb, "173b-03eb", "173b-03eb", 0),
+ PCI_ROM(0x173b, 0x03ea, "173b-03ea", "173b-03ea", 0),
+ PCI_ROM(0x106b, 0x1645, "106b-1645", "106b-1645", 0),
+};
+
+struct pci_driver tg3_pci_driver __pci_driver = {
+ .ids = tg3_nics,
+ .id_count = ARRAY_SIZE(tg3_nics),
+ .probe = tg3_init_one,
+ .remove = tg3_remove_one,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3.h
new file mode 100644
index 00000000..993034ae
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3.h
@@ -0,0 +1,3424 @@
+/* $Id: tg3.h $
+ * tg3.h: Definitions for Broadcom Tigon3 ethernet driver.
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com)
+ * Copyright (C) 2004 Sun Microsystems Inc.
+ * Copyright (C) 2007-2011 Broadcom Corporation.
+ */
+
+#ifndef _T3_H
+#define _T3_H
+
+#undef ERRFILE
+#define ERRFILE ERRFILE_tg3
+
+/* From linux/include/linux/pci_regs.h: */
+#define PCI_EXP_LNKCTL 16 /* Link Control */
+#define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */
+#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */
+
+#define PCI_X_CMD_READ_2K 0x0008 /* 2Kbyte maximum read byte count */
+#define PCI_X_CMD_MAX_READ 0x000c /* Max Memory Read Byte Count */
+
+#define PCI_X_CMD_MAX_SPLIT 0x0070 /* Max Outstanding Split Transactions */
+/* </pci_regs.h> */
+
+/* ethtool.h: */
+#define ADVERTISED_10baseT_Half (1 << 0)
+#define ADVERTISED_10baseT_Full (1 << 1)
+#define ADVERTISED_100baseT_Half (1 << 2)
+#define ADVERTISED_100baseT_Full (1 << 3)
+#define ADVERTISED_1000baseT_Half (1 << 4)
+#define ADVERTISED_1000baseT_Full (1 << 5)
+#define ADVERTISED_Autoneg (1 << 6)
+/* </ethtool.h> */
+
+/* mdio.h: */
+#define MDIO_AN_EEE_ADV 60 /* EEE advertisement */
+
+#define MDIO_MMD_AN 7 /* Auto-Negotiation */
+
+#define MDIO_AN_EEE_ADV_100TX 0x0002 /* Advertise 100TX EEE cap */
+#define MDIO_AN_EEE_ADV_1000T 0x0004 /* Advertise 1000T EEE cap */
+/* </mdio.h> */
+
+/* mii.h */
+#define FLOW_CTRL_TX 0x01
+#define FLOW_CTRL_RX 0x02
+/* </mii.h> */
+
+/* pci_regs.h */
+#define PCI_X_CMD 2 /* Modes & Features */
+#define PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */
+
+#define PCI_EXP_DEVCTL 8 /* Device Control */
+#define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */
+#define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */
+#define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */
+#define PCI_EXP_DEVSTA 10 /* Device Status */
+#define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */
+#define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */
+#define PCI_EXP_DEVSTA_FED 0x04 /* Fatal Error Detected */
+#define PCI_EXP_DEVSTA_URD 0x08 /* Unsupported Request Detected */
+/* </pci_regs.h> */
+
+/* pci_ids.h: */
+#define PCI_VENDOR_ID_BROADCOM 0x14e4
+#define PCI_DEVICE_ID_TIGON3_5752 0x1600
+#define PCI_DEVICE_ID_TIGON3_5752M 0x1601
+#define PCI_DEVICE_ID_NX2_5709 0x1639
+#define PCI_DEVICE_ID_NX2_5709S 0x163a
+#define PCI_DEVICE_ID_TIGON3_5700 0x1644
+#define PCI_DEVICE_ID_TIGON3_5701 0x1645
+#define PCI_DEVICE_ID_TIGON3_5702 0x1646
+#define PCI_DEVICE_ID_TIGON3_5703 0x1647
+#define PCI_DEVICE_ID_TIGON3_5704 0x1648
+#define PCI_DEVICE_ID_TIGON3_5704S_2 0x1649
+#define PCI_DEVICE_ID_NX2_5706 0x164a
+#define PCI_DEVICE_ID_NX2_5708 0x164c
+#define PCI_DEVICE_ID_TIGON3_5702FE 0x164d
+#define PCI_DEVICE_ID_NX2_57710 0x164e
+#define PCI_DEVICE_ID_NX2_57711 0x164f
+#define PCI_DEVICE_ID_NX2_57711E 0x1650
+#define PCI_DEVICE_ID_TIGON3_5705 0x1653
+#define PCI_DEVICE_ID_TIGON3_5705_2 0x1654
+#define PCI_DEVICE_ID_TIGON3_5721 0x1659
+#define PCI_DEVICE_ID_TIGON3_5722 0x165a
+#define PCI_DEVICE_ID_TIGON3_5723 0x165b
+#define PCI_DEVICE_ID_TIGON3_5705M 0x165d
+#define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e
+#define PCI_DEVICE_ID_NX2_57712 0x1662
+#define PCI_DEVICE_ID_NX2_57712E 0x1663
+#define PCI_DEVICE_ID_TIGON3_5714 0x1668
+#define PCI_DEVICE_ID_TIGON3_5714S 0x1669
+#define PCI_DEVICE_ID_TIGON3_5780 0x166a
+#define PCI_DEVICE_ID_TIGON3_5780S 0x166b
+#define PCI_DEVICE_ID_TIGON3_5705F 0x166e
+#define PCI_DEVICE_ID_TIGON3_5754M 0x1672
+#define PCI_DEVICE_ID_TIGON3_5755M 0x1673
+#define PCI_DEVICE_ID_TIGON3_5756 0x1674
+#define PCI_DEVICE_ID_TIGON3_5751 0x1677
+#define PCI_DEVICE_ID_TIGON3_5715 0x1678
+#define PCI_DEVICE_ID_TIGON3_5715S 0x1679
+#define PCI_DEVICE_ID_TIGON3_5754 0x167a
+#define PCI_DEVICE_ID_TIGON3_5755 0x167b
+#define PCI_DEVICE_ID_TIGON3_5751M 0x167d
+#define PCI_DEVICE_ID_TIGON3_5751F 0x167e
+#define PCI_DEVICE_ID_TIGON3_5787F 0x167f
+#define PCI_DEVICE_ID_TIGON3_5761E 0x1680
+#define PCI_DEVICE_ID_TIGON3_5761 0x1681
+#define PCI_DEVICE_ID_TIGON3_5764 0x1684
+#define PCI_DEVICE_ID_TIGON3_5787M 0x1693
+#define PCI_DEVICE_ID_TIGON3_5782 0x1696
+#define PCI_DEVICE_ID_TIGON3_5784 0x1698
+#define PCI_DEVICE_ID_TIGON3_5786 0x169a
+#define PCI_DEVICE_ID_TIGON3_5787 0x169b
+#define PCI_DEVICE_ID_TIGON3_5788 0x169c
+#define PCI_DEVICE_ID_TIGON3_5789 0x169d
+#define PCI_DEVICE_ID_TIGON3_5702X 0x16a6
+#define PCI_DEVICE_ID_TIGON3_5703X 0x16a7
+#define PCI_DEVICE_ID_TIGON3_5704S 0x16a8
+#define PCI_DEVICE_ID_NX2_5706S 0x16aa
+#define PCI_DEVICE_ID_NX2_5708S 0x16ac
+#define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6
+#define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7
+#define PCI_DEVICE_ID_TIGON3_5781 0x16dd
+#define PCI_DEVICE_ID_TIGON3_5753 0x16f7
+#define PCI_DEVICE_ID_TIGON3_5753M 0x16fd
+#define PCI_DEVICE_ID_TIGON3_5753F 0x16fe
+#define PCI_DEVICE_ID_TIGON3_5901 0x170d
+#define PCI_DEVICE_ID_TIGON3_5901_2 0x170e
+#define PCI_DEVICE_ID_TIGON3_5906 0x1712
+#define PCI_DEVICE_ID_TIGON3_5906M 0x1713
+/* </pci_ids.h> */
+
+#define SPEED_10 10
+#define SPEED_100 100
+#define SPEED_1000 1000
+
+#define DUPLEX_HALF 0x00
+#define DUPLEX_FULL 0x01
+
+#define TG3_64BIT_REG_HIGH 0x00UL
+#define TG3_64BIT_REG_LOW 0x04UL
+
+/* Descriptor block info. */
+#define TG3_BDINFO_HOST_ADDR 0x0UL /* 64-bit */
+#define TG3_BDINFO_MAXLEN_FLAGS 0x8UL /* 32-bit */
+#define BDINFO_FLAGS_USE_EXT_RECV 0x00000001 /* ext rx_buffer_desc */
+#define BDINFO_FLAGS_DISABLED 0x00000002
+#define BDINFO_FLAGS_MAXLEN_MASK 0xffff0000
+#define BDINFO_FLAGS_MAXLEN_SHIFT 16
+#define TG3_BDINFO_NIC_ADDR 0xcUL /* 32-bit */
+#define TG3_BDINFO_SIZE 0x10UL
+
+#define TG3_RX_STD_MAX_SIZE_5700 512
+#define TG3_RX_STD_MAX_SIZE_5717 2048
+#define TG3_RX_JMB_MAX_SIZE_5700 256
+#define TG3_RX_JMB_MAX_SIZE_5717 1024
+#define TG3_RX_RET_MAX_SIZE_5700 1024
+#define TG3_RX_RET_MAX_SIZE_5705 512
+#define TG3_RX_RET_MAX_SIZE_5717 4096
+
+/* First 256 bytes are a mirror of PCI config space. */
+#define TG3PCI_VENDOR 0x00000000
+#define TG3PCI_VENDOR_BROADCOM 0x14e4
+#define TG3PCI_DEVICE 0x00000002
+#define TG3PCI_DEVICE_TIGON3_1 0x1644 /* BCM5700 */
+#define TG3PCI_DEVICE_TIGON3_2 0x1645 /* BCM5701 */
+#define TG3PCI_DEVICE_TIGON3_3 0x1646 /* BCM5702 */
+#define TG3PCI_DEVICE_TIGON3_4 0x1647 /* BCM5703 */
+#define TG3PCI_DEVICE_TIGON3_5761S 0x1688
+#define TG3PCI_DEVICE_TIGON3_5761SE 0x1689
+#define TG3PCI_DEVICE_TIGON3_57780 0x1692
+#define TG3PCI_DEVICE_TIGON3_57760 0x1690
+#define TG3PCI_DEVICE_TIGON3_57790 0x1694
+#define TG3PCI_DEVICE_TIGON3_57788 0x1691
+#define TG3PCI_DEVICE_TIGON3_5785_G 0x1699 /* GPHY */
+#define TG3PCI_DEVICE_TIGON3_5785_F 0x16a0 /* 10/100 only */
+#define TG3PCI_DEVICE_TIGON3_5717 0x1655
+#define TG3PCI_DEVICE_TIGON3_5718 0x1656
+#define TG3PCI_DEVICE_TIGON3_57781 0x16b1
+#define TG3PCI_DEVICE_TIGON3_57785 0x16b5
+#define TG3PCI_DEVICE_TIGON3_57761 0x16b0
+#define TG3PCI_DEVICE_TIGON3_57765 0x16b4
+#define TG3PCI_DEVICE_TIGON3_57791 0x16b2
+#define TG3PCI_DEVICE_TIGON3_57795 0x16b6
+#define TG3PCI_DEVICE_TIGON3_5719 0x1657
+#define TG3PCI_DEVICE_TIGON3_5720 0x165f
+/* 0x04 --> 0x2c unused */
+#define TG3PCI_SUBVENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6 0x1644
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A5 0x0001
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95700T6 0x0002
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95700A9 0x0003
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701T1 0x0005
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701T8 0x0006
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A7 0x0007
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A10 0x0008
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A12 0x8008
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX1 0x0009
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX2 0x8009
+#define TG3PCI_SUBVENDOR_ID_3COM PCI_VENDOR_ID_3COM
+#define TG3PCI_SUBDEVICE_ID_3COM_3C996T 0x1000
+#define TG3PCI_SUBDEVICE_ID_3COM_3C996BT 0x1006
+#define TG3PCI_SUBDEVICE_ID_3COM_3C996SX 0x1004
+#define TG3PCI_SUBDEVICE_ID_3COM_3C1000T 0x1007
+#define TG3PCI_SUBDEVICE_ID_3COM_3C940BR01 0x1008
+#define TG3PCI_SUBVENDOR_ID_DELL PCI_VENDOR_ID_DELL
+#define TG3PCI_SUBDEVICE_ID_DELL_VIPER 0x00d1
+#define TG3PCI_SUBDEVICE_ID_DELL_JAGUAR 0x0106
+#define TG3PCI_SUBDEVICE_ID_DELL_MERLOT 0x0109
+#define TG3PCI_SUBDEVICE_ID_DELL_SLIM_MERLOT 0x010a
+#define TG3PCI_SUBVENDOR_ID_COMPAQ PCI_VENDOR_ID_COMPAQ
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE 0x007c
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE_2 0x009a
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_CHANGELING 0x007d
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780 0x0085
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2 0x0099
+#define TG3PCI_SUBVENDOR_ID_IBM PCI_VENDOR_ID_IBM
+#define TG3PCI_SUBDEVICE_ID_IBM_5703SAX2 0x0281
+/* 0x30 --> 0x64 unused */
+#define TG3PCI_MSI_DATA 0x00000064
+/* 0x66 --> 0x68 unused */
+#define TG3PCI_MISC_HOST_CTRL 0x00000068
+#define MISC_HOST_CTRL_CLEAR_INT 0x00000001
+#define MISC_HOST_CTRL_MASK_PCI_INT 0x00000002
+#define MISC_HOST_CTRL_BYTE_SWAP 0x00000004
+#define MISC_HOST_CTRL_WORD_SWAP 0x00000008
+#define MISC_HOST_CTRL_PCISTATE_RW 0x00000010
+#define MISC_HOST_CTRL_CLKREG_RW 0x00000020
+#define MISC_HOST_CTRL_REGWORD_SWAP 0x00000040
+#define MISC_HOST_CTRL_INDIR_ACCESS 0x00000080
+#define MISC_HOST_CTRL_IRQ_MASK_MODE 0x00000100
+#define MISC_HOST_CTRL_TAGGED_STATUS 0x00000200
+#define MISC_HOST_CTRL_CHIPREV 0xffff0000
+#define MISC_HOST_CTRL_CHIPREV_SHIFT 16
+#define GET_CHIP_REV_ID(MISC_HOST_CTRL) \
+ (((MISC_HOST_CTRL) & MISC_HOST_CTRL_CHIPREV) >> \
+ MISC_HOST_CTRL_CHIPREV_SHIFT)
+#define CHIPREV_ID_5700_A0 0x7000
+#define CHIPREV_ID_5700_A1 0x7001
+#define CHIPREV_ID_5700_B0 0x7100
+#define CHIPREV_ID_5700_B1 0x7101
+#define CHIPREV_ID_5700_B3 0x7102
+#define CHIPREV_ID_5700_ALTIMA 0x7104
+#define CHIPREV_ID_5700_C0 0x7200
+#define CHIPREV_ID_5701_A0 0x0000
+#define CHIPREV_ID_5701_B0 0x0100
+#define CHIPREV_ID_5701_B2 0x0102
+#define CHIPREV_ID_5701_B5 0x0105
+#define CHIPREV_ID_5703_A0 0x1000
+#define CHIPREV_ID_5703_A1 0x1001
+#define CHIPREV_ID_5703_A2 0x1002
+#define CHIPREV_ID_5703_A3 0x1003
+#define CHIPREV_ID_5704_A0 0x2000
+#define CHIPREV_ID_5704_A1 0x2001
+#define CHIPREV_ID_5704_A2 0x2002
+#define CHIPREV_ID_5704_A3 0x2003
+#define CHIPREV_ID_5705_A0 0x3000
+#define CHIPREV_ID_5705_A1 0x3001
+#define CHIPREV_ID_5705_A2 0x3002
+#define CHIPREV_ID_5705_A3 0x3003
+#define CHIPREV_ID_5750_A0 0x4000
+#define CHIPREV_ID_5750_A1 0x4001
+#define CHIPREV_ID_5750_A3 0x4003
+#define CHIPREV_ID_5750_C2 0x4202
+#define CHIPREV_ID_5752_A0_HW 0x5000
+#define CHIPREV_ID_5752_A0 0x6000
+#define CHIPREV_ID_5752_A1 0x6001
+#define CHIPREV_ID_5714_A2 0x9002
+#define CHIPREV_ID_5906_A1 0xc001
+#define CHIPREV_ID_57780_A0 0x57780000
+#define CHIPREV_ID_57780_A1 0x57780001
+#define CHIPREV_ID_5717_A0 0x05717000
+#define CHIPREV_ID_57765_A0 0x57785000
+#define CHIPREV_ID_5719_A0 0x05719000
+#define CHIPREV_ID_5720_A0 0x05720000
+#define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12)
+#define ASIC_REV_5700 0x07
+#define ASIC_REV_5701 0x00
+#define ASIC_REV_5703 0x01
+#define ASIC_REV_5704 0x02
+#define ASIC_REV_5705 0x03
+#define ASIC_REV_5750 0x04
+#define ASIC_REV_5752 0x06
+#define ASIC_REV_5780 0x08
+#define ASIC_REV_5714 0x09
+#define ASIC_REV_5755 0x0a
+#define ASIC_REV_5787 0x0b
+#define ASIC_REV_5906 0x0c
+#define ASIC_REV_USE_PROD_ID_REG 0x0f
+#define ASIC_REV_5784 0x5784
+#define ASIC_REV_5761 0x5761
+#define ASIC_REV_5785 0x5785
+#define ASIC_REV_57780 0x57780
+#define ASIC_REV_5717 0x5717
+#define ASIC_REV_57765 0x57785
+#define ASIC_REV_5719 0x5719
+#define ASIC_REV_5720 0x5720
+#define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8)
+#define CHIPREV_5700_AX 0x70
+#define CHIPREV_5700_BX 0x71
+#define CHIPREV_5700_CX 0x72
+#define CHIPREV_5701_AX 0x00
+#define CHIPREV_5703_AX 0x10
+#define CHIPREV_5704_AX 0x20
+#define CHIPREV_5704_BX 0x21
+#define CHIPREV_5750_AX 0x40
+#define CHIPREV_5750_BX 0x41
+#define CHIPREV_5784_AX 0x57840
+#define CHIPREV_5761_AX 0x57610
+#define CHIPREV_57765_AX 0x577650
+#define GET_METAL_REV(CHIP_REV_ID) ((CHIP_REV_ID) & 0xff)
+#define METAL_REV_A0 0x00
+#define METAL_REV_A1 0x01
+#define METAL_REV_B0 0x00
+#define METAL_REV_B1 0x01
+#define METAL_REV_B2 0x02
+#define TG3PCI_DMA_RW_CTRL 0x0000006c
+#define DMA_RWCTRL_DIS_CACHE_ALIGNMENT 0x00000001
+#define DMA_RWCTRL_TAGGED_STAT_WA 0x00000080
+#define DMA_RWCTRL_CRDRDR_RDMA_MRRS_MSK 0x00000380
+#define DMA_RWCTRL_READ_BNDRY_MASK 0x00000700
+#define DMA_RWCTRL_READ_BNDRY_DISAB 0x00000000
+#define DMA_RWCTRL_READ_BNDRY_16 0x00000100
+#define DMA_RWCTRL_READ_BNDRY_128_PCIX 0x00000100
+#define DMA_RWCTRL_READ_BNDRY_32 0x00000200
+#define DMA_RWCTRL_READ_BNDRY_256_PCIX 0x00000200
+#define DMA_RWCTRL_READ_BNDRY_64 0x00000300
+#define DMA_RWCTRL_READ_BNDRY_384_PCIX 0x00000300
+#define DMA_RWCTRL_READ_BNDRY_128 0x00000400
+#define DMA_RWCTRL_READ_BNDRY_256 0x00000500
+#define DMA_RWCTRL_READ_BNDRY_512 0x00000600
+#define DMA_RWCTRL_READ_BNDRY_1024 0x00000700
+#define DMA_RWCTRL_WRITE_BNDRY_MASK 0x00003800
+#define DMA_RWCTRL_WRITE_BNDRY_DISAB 0x00000000
+#define DMA_RWCTRL_WRITE_BNDRY_16 0x00000800
+#define DMA_RWCTRL_WRITE_BNDRY_128_PCIX 0x00000800
+#define DMA_RWCTRL_WRITE_BNDRY_32 0x00001000
+#define DMA_RWCTRL_WRITE_BNDRY_256_PCIX 0x00001000
+#define DMA_RWCTRL_WRITE_BNDRY_64 0x00001800
+#define DMA_RWCTRL_WRITE_BNDRY_384_PCIX 0x00001800
+#define DMA_RWCTRL_WRITE_BNDRY_128 0x00002000
+#define DMA_RWCTRL_WRITE_BNDRY_256 0x00002800
+#define DMA_RWCTRL_WRITE_BNDRY_512 0x00003000
+#define DMA_RWCTRL_WRITE_BNDRY_1024 0x00003800
+#define DMA_RWCTRL_ONE_DMA 0x00004000
+#define DMA_RWCTRL_READ_WATER 0x00070000
+#define DMA_RWCTRL_READ_WATER_SHIFT 16
+#define DMA_RWCTRL_WRITE_WATER 0x00380000
+#define DMA_RWCTRL_WRITE_WATER_SHIFT 19
+#define DMA_RWCTRL_USE_MEM_READ_MULT 0x00400000
+#define DMA_RWCTRL_ASSERT_ALL_BE 0x00800000
+#define DMA_RWCTRL_PCI_READ_CMD 0x0f000000
+#define DMA_RWCTRL_PCI_READ_CMD_SHIFT 24
+#define DMA_RWCTRL_PCI_WRITE_CMD 0xf0000000
+#define DMA_RWCTRL_PCI_WRITE_CMD_SHIFT 28
+#define DMA_RWCTRL_WRITE_BNDRY_64_PCIE 0x10000000
+#define DMA_RWCTRL_WRITE_BNDRY_128_PCIE 0x30000000
+#define DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE 0x70000000
+#define TG3PCI_PCISTATE 0x00000070
+#define PCISTATE_FORCE_RESET 0x00000001
+#define PCISTATE_INT_NOT_ACTIVE 0x00000002
+#define PCISTATE_CONV_PCI_MODE 0x00000004
+#define PCISTATE_BUS_SPEED_HIGH 0x00000008
+#define PCISTATE_BUS_32BIT 0x00000010
+#define PCISTATE_ROM_ENABLE 0x00000020
+#define PCISTATE_ROM_RETRY_ENABLE 0x00000040
+#define PCISTATE_FLAT_VIEW 0x00000100
+#define PCISTATE_RETRY_SAME_DMA 0x00002000
+#define PCISTATE_ALLOW_APE_CTLSPC_WR 0x00010000
+#define PCISTATE_ALLOW_APE_SHMEM_WR 0x00020000
+#define PCISTATE_ALLOW_APE_PSPACE_WR 0x00040000
+#define TG3PCI_CLOCK_CTRL 0x00000074
+#define CLOCK_CTRL_CORECLK_DISABLE 0x00000200
+#define CLOCK_CTRL_RXCLK_DISABLE 0x00000400
+#define CLOCK_CTRL_TXCLK_DISABLE 0x00000800
+#define CLOCK_CTRL_ALTCLK 0x00001000
+#define CLOCK_CTRL_PWRDOWN_PLL133 0x00008000
+#define CLOCK_CTRL_44MHZ_CORE 0x00040000
+#define CLOCK_CTRL_625_CORE 0x00100000
+#define CLOCK_CTRL_FORCE_CLKRUN 0x00200000
+#define CLOCK_CTRL_CLKRUN_OENABLE 0x00400000
+#define CLOCK_CTRL_DELAY_PCI_GRANT 0x80000000
+#define TG3PCI_REG_BASE_ADDR 0x00000078
+#define TG3PCI_MEM_WIN_BASE_ADDR 0x0000007c
+#define TG3PCI_REG_DATA 0x00000080
+#define TG3PCI_MEM_WIN_DATA 0x00000084
+#define TG3PCI_MISC_LOCAL_CTRL 0x00000090
+/* 0x94 --> 0x98 unused */
+#define TG3PCI_STD_RING_PROD_IDX 0x00000098 /* 64-bit */
+#define TG3PCI_RCV_RET_RING_CON_IDX 0x000000a0 /* 64-bit */
+/* 0xa8 --> 0xb8 unused */
+#define TG3PCI_DUAL_MAC_CTRL 0x000000b8
+#define DUAL_MAC_CTRL_CH_MASK 0x00000003
+#define DUAL_MAC_CTRL_ID 0x00000004
+#define TG3PCI_PRODID_ASICREV 0x000000bc
+#define PROD_ID_ASIC_REV_MASK 0x0fffffff
+/* 0xc0 --> 0xf4 unused */
+
+#define TG3PCI_GEN2_PRODID_ASICREV 0x000000f4
+#define TG3PCI_GEN15_PRODID_ASICREV 0x000000fc
+/* 0xf8 --> 0x200 unused */
+
+#define TG3_CORR_ERR_STAT 0x00000110
+#define TG3_CORR_ERR_STAT_CLEAR 0xffffffff
+/* 0x114 --> 0x200 unused */
+
+/* Mailbox registers */
+#define MAILBOX_INTERRUPT_0 0x00000200 /* 64-bit */
+#define MAILBOX_INTERRUPT_1 0x00000208 /* 64-bit */
+#define MAILBOX_INTERRUPT_2 0x00000210 /* 64-bit */
+#define MAILBOX_INTERRUPT_3 0x00000218 /* 64-bit */
+#define MAILBOX_GENERAL_0 0x00000220 /* 64-bit */
+#define MAILBOX_GENERAL_1 0x00000228 /* 64-bit */
+#define MAILBOX_GENERAL_2 0x00000230 /* 64-bit */
+#define MAILBOX_GENERAL_3 0x00000238 /* 64-bit */
+#define MAILBOX_GENERAL_4 0x00000240 /* 64-bit */
+#define MAILBOX_GENERAL_5 0x00000248 /* 64-bit */
+#define MAILBOX_GENERAL_6 0x00000250 /* 64-bit */
+#define MAILBOX_GENERAL_7 0x00000258 /* 64-bit */
+#define MAILBOX_RELOAD_STAT 0x00000260 /* 64-bit */
+#define MAILBOX_RCV_STD_PROD_IDX 0x00000268 /* 64-bit */
+#define TG3_RX_STD_PROD_IDX_REG (MAILBOX_RCV_STD_PROD_IDX + \
+ TG3_64BIT_REG_LOW)
+#define MAILBOX_RCV_JUMBO_PROD_IDX 0x00000270 /* 64-bit */
+#define TG3_RX_JMB_PROD_IDX_REG (MAILBOX_RCV_JUMBO_PROD_IDX + \
+ TG3_64BIT_REG_LOW)
+#define MAILBOX_RCV_MINI_PROD_IDX 0x00000278 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_0 0x00000280 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_1 0x00000288 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_2 0x00000290 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_3 0x00000298 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_4 0x000002a0 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_5 0x000002a8 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_6 0x000002b0 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_7 0x000002b8 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_8 0x000002c0 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_9 0x000002c8 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_10 0x000002d0 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_11 0x000002d8 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_12 0x000002e0 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_13 0x000002e8 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_14 0x000002f0 /* 64-bit */
+#define MAILBOX_RCVRET_CON_IDX_15 0x000002f8 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_0 0x00000300 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_1 0x00000308 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_2 0x00000310 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_3 0x00000318 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_4 0x00000320 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_5 0x00000328 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_6 0x00000330 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_7 0x00000338 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_8 0x00000340 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_9 0x00000348 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_10 0x00000350 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_11 0x00000358 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_12 0x00000360 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_13 0x00000368 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_14 0x00000370 /* 64-bit */
+#define MAILBOX_SNDHOST_PROD_IDX_15 0x00000378 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_0 0x00000380 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_1 0x00000388 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_2 0x00000390 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_3 0x00000398 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_4 0x000003a0 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_5 0x000003a8 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_6 0x000003b0 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_7 0x000003b8 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_8 0x000003c0 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_9 0x000003c8 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_10 0x000003d0 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_11 0x000003d8 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_12 0x000003e0 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_13 0x000003e8 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_14 0x000003f0 /* 64-bit */
+#define MAILBOX_SNDNIC_PROD_IDX_15 0x000003f8 /* 64-bit */
+
+/* MAC control registers */
+#define MAC_MODE 0x00000400
+#define MAC_MODE_RESET 0x00000001
+#define MAC_MODE_HALF_DUPLEX 0x00000002
+#define MAC_MODE_PORT_MODE_MASK 0x0000000c
+#define MAC_MODE_PORT_MODE_TBI 0x0000000c
+#define MAC_MODE_PORT_MODE_GMII 0x00000008
+#define MAC_MODE_PORT_MODE_MII 0x00000004
+#define MAC_MODE_PORT_MODE_NONE 0x00000000
+#define MAC_MODE_PORT_INT_LPBACK 0x00000010
+#define MAC_MODE_TAGGED_MAC_CTRL 0x00000080
+#define MAC_MODE_TX_BURSTING 0x00000100
+#define MAC_MODE_MAX_DEFER 0x00000200
+#define MAC_MODE_LINK_POLARITY 0x00000400
+#define MAC_MODE_RXSTAT_ENABLE 0x00000800
+#define MAC_MODE_RXSTAT_CLEAR 0x00001000
+#define MAC_MODE_RXSTAT_FLUSH 0x00002000
+#define MAC_MODE_TXSTAT_ENABLE 0x00004000
+#define MAC_MODE_TXSTAT_CLEAR 0x00008000
+#define MAC_MODE_TXSTAT_FLUSH 0x00010000
+#define MAC_MODE_SEND_CONFIGS 0x00020000
+#define MAC_MODE_MAGIC_PKT_ENABLE 0x00040000
+#define MAC_MODE_ACPI_ENABLE 0x00080000
+#define MAC_MODE_MIP_ENABLE 0x00100000
+#define MAC_MODE_TDE_ENABLE 0x00200000
+#define MAC_MODE_RDE_ENABLE 0x00400000
+#define MAC_MODE_FHDE_ENABLE 0x00800000
+#define MAC_MODE_KEEP_FRAME_IN_WOL 0x01000000
+#define MAC_MODE_APE_RX_EN 0x08000000
+#define MAC_MODE_APE_TX_EN 0x10000000
+#define MAC_STATUS 0x00000404
+#define MAC_STATUS_PCS_SYNCED 0x00000001
+#define MAC_STATUS_SIGNAL_DET 0x00000002
+#define MAC_STATUS_RCVD_CFG 0x00000004
+#define MAC_STATUS_CFG_CHANGED 0x00000008
+#define MAC_STATUS_SYNC_CHANGED 0x00000010
+#define MAC_STATUS_PORT_DEC_ERR 0x00000400
+#define MAC_STATUS_LNKSTATE_CHANGED 0x00001000
+#define MAC_STATUS_MI_COMPLETION 0x00400000
+#define MAC_STATUS_MI_INTERRUPT 0x00800000
+#define MAC_STATUS_AP_ERROR 0x01000000
+#define MAC_STATUS_ODI_ERROR 0x02000000
+#define MAC_STATUS_RXSTAT_OVERRUN 0x04000000
+#define MAC_STATUS_TXSTAT_OVERRUN 0x08000000
+#define MAC_EVENT 0x00000408
+#define MAC_EVENT_PORT_DECODE_ERR 0x00000400
+#define MAC_EVENT_LNKSTATE_CHANGED 0x00001000
+#define MAC_EVENT_MI_COMPLETION 0x00400000
+#define MAC_EVENT_MI_INTERRUPT 0x00800000
+#define MAC_EVENT_AP_ERROR 0x01000000
+#define MAC_EVENT_ODI_ERROR 0x02000000
+#define MAC_EVENT_RXSTAT_OVERRUN 0x04000000
+#define MAC_EVENT_TXSTAT_OVERRUN 0x08000000
+#define MAC_LED_CTRL 0x0000040c
+#define LED_CTRL_LNKLED_OVERRIDE 0x00000001
+#define LED_CTRL_1000MBPS_ON 0x00000002
+#define LED_CTRL_100MBPS_ON 0x00000004
+#define LED_CTRL_10MBPS_ON 0x00000008
+#define LED_CTRL_TRAFFIC_OVERRIDE 0x00000010
+#define LED_CTRL_TRAFFIC_BLINK 0x00000020
+#define LED_CTRL_TRAFFIC_LED 0x00000040
+#define LED_CTRL_1000MBPS_STATUS 0x00000080
+#define LED_CTRL_100MBPS_STATUS 0x00000100
+#define LED_CTRL_10MBPS_STATUS 0x00000200
+#define LED_CTRL_TRAFFIC_STATUS 0x00000400
+#define LED_CTRL_MODE_MAC 0x00000000
+#define LED_CTRL_MODE_PHY_1 0x00000800
+#define LED_CTRL_MODE_PHY_2 0x00001000
+#define LED_CTRL_MODE_SHASTA_MAC 0x00002000
+#define LED_CTRL_MODE_SHARED 0x00004000
+#define LED_CTRL_MODE_COMBO 0x00008000
+#define LED_CTRL_BLINK_RATE_MASK 0x7ff80000
+#define LED_CTRL_BLINK_RATE_SHIFT 19
+#define LED_CTRL_BLINK_PER_OVERRIDE 0x00080000
+#define LED_CTRL_BLINK_RATE_OVERRIDE 0x80000000
+#define MAC_ADDR_0_HIGH 0x00000410 /* upper 2 bytes */
+#define MAC_ADDR_0_LOW 0x00000414 /* lower 4 bytes */
+#define MAC_ADDR_1_HIGH 0x00000418 /* upper 2 bytes */
+#define MAC_ADDR_1_LOW 0x0000041c /* lower 4 bytes */
+#define MAC_ADDR_2_HIGH 0x00000420 /* upper 2 bytes */
+#define MAC_ADDR_2_LOW 0x00000424 /* lower 4 bytes */
+#define MAC_ADDR_3_HIGH 0x00000428 /* upper 2 bytes */
+#define MAC_ADDR_3_LOW 0x0000042c /* lower 4 bytes */
+#define MAC_ACPI_MBUF_PTR 0x00000430
+#define MAC_ACPI_LEN_OFFSET 0x00000434
+#define ACPI_LENOFF_LEN_MASK 0x0000ffff
+#define ACPI_LENOFF_LEN_SHIFT 0
+#define ACPI_LENOFF_OFF_MASK 0x0fff0000
+#define ACPI_LENOFF_OFF_SHIFT 16
+#define MAC_TX_BACKOFF_SEED 0x00000438
+#define TX_BACKOFF_SEED_MASK 0x000003ff
+#define MAC_RX_MTU_SIZE 0x0000043c
+#define RX_MTU_SIZE_MASK 0x0000ffff
+#define MAC_PCS_TEST 0x00000440
+#define PCS_TEST_PATTERN_MASK 0x000fffff
+#define PCS_TEST_PATTERN_SHIFT 0
+#define PCS_TEST_ENABLE 0x00100000
+#define MAC_TX_AUTO_NEG 0x00000444
+#define TX_AUTO_NEG_MASK 0x0000ffff
+#define TX_AUTO_NEG_SHIFT 0
+#define MAC_RX_AUTO_NEG 0x00000448
+#define RX_AUTO_NEG_MASK 0x0000ffff
+#define RX_AUTO_NEG_SHIFT 0
+#define MAC_MI_COM 0x0000044c
+#define MI_COM_CMD_MASK 0x0c000000
+#define MI_COM_CMD_WRITE 0x04000000
+#define MI_COM_CMD_READ 0x08000000
+#define MI_COM_READ_FAILED 0x10000000
+#define MI_COM_START 0x20000000
+#define MI_COM_BUSY 0x20000000
+#define MI_COM_PHY_ADDR_MASK 0x03e00000
+#define MI_COM_PHY_ADDR_SHIFT 21
+#define MI_COM_REG_ADDR_MASK 0x001f0000
+#define MI_COM_REG_ADDR_SHIFT 16
+#define MI_COM_DATA_MASK 0x0000ffff
+#define MAC_MI_STAT 0x00000450
+#define MAC_MI_STAT_LNKSTAT_ATTN_ENAB 0x00000001
+#define MAC_MI_STAT_10MBPS_MODE 0x00000002
+#define MAC_MI_MODE 0x00000454
+#define MAC_MI_MODE_CLK_10MHZ 0x00000001
+#define MAC_MI_MODE_SHORT_PREAMBLE 0x00000002
+#define MAC_MI_MODE_AUTO_POLL 0x00000010
+#define MAC_MI_MODE_500KHZ_CONST 0x00008000
+#define MAC_MI_MODE_BASE 0x000c0000 /* XXX magic values XXX */
+#define MAC_AUTO_POLL_STATUS 0x00000458
+#define MAC_AUTO_POLL_ERROR 0x00000001
+#define MAC_TX_MODE 0x0000045c
+#define TX_MODE_RESET 0x00000001
+#define TX_MODE_ENABLE 0x00000002
+#define TX_MODE_FLOW_CTRL_ENABLE 0x00000010
+#define TX_MODE_BIG_BCKOFF_ENABLE 0x00000020
+#define TX_MODE_LONG_PAUSE_ENABLE 0x00000040
+#define TX_MODE_MBUF_LOCKUP_FIX 0x00000100
+#define TX_MODE_JMB_FRM_LEN 0x00400000
+#define TX_MODE_CNT_DN_MODE 0x00800000
+#define MAC_TX_STATUS 0x00000460
+#define TX_STATUS_XOFFED 0x00000001
+#define TX_STATUS_SENT_XOFF 0x00000002
+#define TX_STATUS_SENT_XON 0x00000004
+#define TX_STATUS_LINK_UP 0x00000008
+#define TX_STATUS_ODI_UNDERRUN 0x00000010
+#define TX_STATUS_ODI_OVERRUN 0x00000020
+#define MAC_TX_LENGTHS 0x00000464
+#define TX_LENGTHS_SLOT_TIME_MASK 0x000000ff
+#define TX_LENGTHS_SLOT_TIME_SHIFT 0
+#define TX_LENGTHS_IPG_MASK 0x00000f00
+#define TX_LENGTHS_IPG_SHIFT 8
+#define TX_LENGTHS_IPG_CRS_MASK 0x00003000
+#define TX_LENGTHS_IPG_CRS_SHIFT 12
+#define TX_LENGTHS_JMB_FRM_LEN_MSK 0x00ff0000
+#define TX_LENGTHS_CNT_DWN_VAL_MSK 0xff000000
+#define MAC_RX_MODE 0x00000468
+#define RX_MODE_RESET 0x00000001
+#define RX_MODE_ENABLE 0x00000002
+#define RX_MODE_FLOW_CTRL_ENABLE 0x00000004
+#define RX_MODE_KEEP_MAC_CTRL 0x00000008
+#define RX_MODE_KEEP_PAUSE 0x00000010
+#define RX_MODE_ACCEPT_OVERSIZED 0x00000020
+#define RX_MODE_ACCEPT_RUNTS 0x00000040
+#define RX_MODE_LEN_CHECK 0x00000080
+#define RX_MODE_PROMISC 0x00000100
+#define RX_MODE_NO_CRC_CHECK 0x00000200
+#define RX_MODE_KEEP_VLAN_TAG 0x00000400
+#define RX_MODE_RSS_IPV4_HASH_EN 0x00010000
+#define RX_MODE_RSS_TCP_IPV4_HASH_EN 0x00020000
+#define RX_MODE_RSS_IPV6_HASH_EN 0x00040000
+#define RX_MODE_RSS_TCP_IPV6_HASH_EN 0x00080000
+#define RX_MODE_RSS_ITBL_HASH_BITS_7 0x00700000
+#define RX_MODE_RSS_ENABLE 0x00800000
+#define RX_MODE_IPV6_CSUM_ENABLE 0x01000000
+#define MAC_RX_STATUS 0x0000046c
+#define RX_STATUS_REMOTE_TX_XOFFED 0x00000001
+#define RX_STATUS_XOFF_RCVD 0x00000002
+#define RX_STATUS_XON_RCVD 0x00000004
+#define MAC_HASH_REG_0 0x00000470
+#define MAC_HASH_REG_1 0x00000474
+#define MAC_HASH_REG_2 0x00000478
+#define MAC_HASH_REG_3 0x0000047c
+#define MAC_RCV_RULE_0 0x00000480
+#define MAC_RCV_VALUE_0 0x00000484
+#define MAC_RCV_RULE_1 0x00000488
+#define MAC_RCV_VALUE_1 0x0000048c
+#define MAC_RCV_RULE_2 0x00000490
+#define MAC_RCV_VALUE_2 0x00000494
+#define MAC_RCV_RULE_3 0x00000498
+#define MAC_RCV_VALUE_3 0x0000049c
+#define MAC_RCV_RULE_4 0x000004a0
+#define MAC_RCV_VALUE_4 0x000004a4
+#define MAC_RCV_RULE_5 0x000004a8
+#define MAC_RCV_VALUE_5 0x000004ac
+#define MAC_RCV_RULE_6 0x000004b0
+#define MAC_RCV_VALUE_6 0x000004b4
+#define MAC_RCV_RULE_7 0x000004b8
+#define MAC_RCV_VALUE_7 0x000004bc
+#define MAC_RCV_RULE_8 0x000004c0
+#define MAC_RCV_VALUE_8 0x000004c4
+#define MAC_RCV_RULE_9 0x000004c8
+#define MAC_RCV_VALUE_9 0x000004cc
+#define MAC_RCV_RULE_10 0x000004d0
+#define MAC_RCV_VALUE_10 0x000004d4
+#define MAC_RCV_RULE_11 0x000004d8
+#define MAC_RCV_VALUE_11 0x000004dc
+#define MAC_RCV_RULE_12 0x000004e0
+#define MAC_RCV_VALUE_12 0x000004e4
+#define MAC_RCV_RULE_13 0x000004e8
+#define MAC_RCV_VALUE_13 0x000004ec
+#define MAC_RCV_RULE_14 0x000004f0
+#define MAC_RCV_VALUE_14 0x000004f4
+#define MAC_RCV_RULE_15 0x000004f8
+#define MAC_RCV_VALUE_15 0x000004fc
+#define RCV_RULE_DISABLE_MASK 0x7fffffff
+#define MAC_RCV_RULE_CFG 0x00000500
+#define RCV_RULE_CFG_DEFAULT_CLASS 0x00000008
+#define MAC_LOW_WMARK_MAX_RX_FRAME 0x00000504
+/* 0x508 --> 0x520 unused */
+#define MAC_HASHREGU_0 0x00000520
+#define MAC_HASHREGU_1 0x00000524
+#define MAC_HASHREGU_2 0x00000528
+#define MAC_HASHREGU_3 0x0000052c
+#define MAC_EXTADDR_0_HIGH 0x00000530
+#define MAC_EXTADDR_0_LOW 0x00000534
+#define MAC_EXTADDR_1_HIGH 0x00000538
+#define MAC_EXTADDR_1_LOW 0x0000053c
+#define MAC_EXTADDR_2_HIGH 0x00000540
+#define MAC_EXTADDR_2_LOW 0x00000544
+#define MAC_EXTADDR_3_HIGH 0x00000548
+#define MAC_EXTADDR_3_LOW 0x0000054c
+#define MAC_EXTADDR_4_HIGH 0x00000550
+#define MAC_EXTADDR_4_LOW 0x00000554
+#define MAC_EXTADDR_5_HIGH 0x00000558
+#define MAC_EXTADDR_5_LOW 0x0000055c
+#define MAC_EXTADDR_6_HIGH 0x00000560
+#define MAC_EXTADDR_6_LOW 0x00000564
+#define MAC_EXTADDR_7_HIGH 0x00000568
+#define MAC_EXTADDR_7_LOW 0x0000056c
+#define MAC_EXTADDR_8_HIGH 0x00000570
+#define MAC_EXTADDR_8_LOW 0x00000574
+#define MAC_EXTADDR_9_HIGH 0x00000578
+#define MAC_EXTADDR_9_LOW 0x0000057c
+#define MAC_EXTADDR_10_HIGH 0x00000580
+#define MAC_EXTADDR_10_LOW 0x00000584
+#define MAC_EXTADDR_11_HIGH 0x00000588
+#define MAC_EXTADDR_11_LOW 0x0000058c
+#define MAC_SERDES_CFG 0x00000590
+#define MAC_SERDES_CFG_EDGE_SELECT 0x00001000
+#define MAC_SERDES_STAT 0x00000594
+/* 0x598 --> 0x5a0 unused */
+#define MAC_PHYCFG1 0x000005a0
+#define MAC_PHYCFG1_RGMII_INT 0x00000001
+#define MAC_PHYCFG1_RXCLK_TO_MASK 0x00001ff0
+#define MAC_PHYCFG1_RXCLK_TIMEOUT 0x00001000
+#define MAC_PHYCFG1_TXCLK_TO_MASK 0x01ff0000
+#define MAC_PHYCFG1_TXCLK_TIMEOUT 0x01000000
+#define MAC_PHYCFG1_RGMII_EXT_RX_DEC 0x02000000
+#define MAC_PHYCFG1_RGMII_SND_STAT_EN 0x04000000
+#define MAC_PHYCFG1_TXC_DRV 0x20000000
+#define MAC_PHYCFG2 0x000005a4
+#define MAC_PHYCFG2_INBAND_ENABLE 0x00000001
+#define MAC_PHYCFG2_EMODE_MASK_MASK 0x000001c0
+#define MAC_PHYCFG2_EMODE_MASK_AC131 0x000000c0
+#define MAC_PHYCFG2_EMODE_MASK_50610 0x00000100
+#define MAC_PHYCFG2_EMODE_MASK_RT8211 0x00000000
+#define MAC_PHYCFG2_EMODE_MASK_RT8201 0x000001c0
+#define MAC_PHYCFG2_EMODE_COMP_MASK 0x00000e00
+#define MAC_PHYCFG2_EMODE_COMP_AC131 0x00000600
+#define MAC_PHYCFG2_EMODE_COMP_50610 0x00000400
+#define MAC_PHYCFG2_EMODE_COMP_RT8211 0x00000800
+#define MAC_PHYCFG2_EMODE_COMP_RT8201 0x00000000
+#define MAC_PHYCFG2_FMODE_MASK_MASK 0x00007000
+#define MAC_PHYCFG2_FMODE_MASK_AC131 0x00006000
+#define MAC_PHYCFG2_FMODE_MASK_50610 0x00004000
+#define MAC_PHYCFG2_FMODE_MASK_RT8211 0x00000000
+#define MAC_PHYCFG2_FMODE_MASK_RT8201 0x00007000
+#define MAC_PHYCFG2_FMODE_COMP_MASK 0x00038000
+#define MAC_PHYCFG2_FMODE_COMP_AC131 0x00030000
+#define MAC_PHYCFG2_FMODE_COMP_50610 0x00008000
+#define MAC_PHYCFG2_FMODE_COMP_RT8211 0x00038000
+#define MAC_PHYCFG2_FMODE_COMP_RT8201 0x00000000
+#define MAC_PHYCFG2_GMODE_MASK_MASK 0x001c0000
+#define MAC_PHYCFG2_GMODE_MASK_AC131 0x001c0000
+#define MAC_PHYCFG2_GMODE_MASK_50610 0x00100000
+#define MAC_PHYCFG2_GMODE_MASK_RT8211 0x00000000
+#define MAC_PHYCFG2_GMODE_MASK_RT8201 0x001c0000
+#define MAC_PHYCFG2_GMODE_COMP_MASK 0x00e00000
+#define MAC_PHYCFG2_GMODE_COMP_AC131 0x00e00000
+#define MAC_PHYCFG2_GMODE_COMP_50610 0x00000000
+#define MAC_PHYCFG2_GMODE_COMP_RT8211 0x00200000
+#define MAC_PHYCFG2_GMODE_COMP_RT8201 0x00000000
+#define MAC_PHYCFG2_ACT_MASK_MASK 0x03000000
+#define MAC_PHYCFG2_ACT_MASK_AC131 0x03000000
+#define MAC_PHYCFG2_ACT_MASK_50610 0x01000000
+#define MAC_PHYCFG2_ACT_MASK_RT8211 0x03000000
+#define MAC_PHYCFG2_ACT_MASK_RT8201 0x01000000
+#define MAC_PHYCFG2_ACT_COMP_MASK 0x0c000000
+#define MAC_PHYCFG2_ACT_COMP_AC131 0x00000000
+#define MAC_PHYCFG2_ACT_COMP_50610 0x00000000
+#define MAC_PHYCFG2_ACT_COMP_RT8211 0x00000000
+#define MAC_PHYCFG2_ACT_COMP_RT8201 0x08000000
+#define MAC_PHYCFG2_QUAL_MASK_MASK 0x30000000
+#define MAC_PHYCFG2_QUAL_MASK_AC131 0x30000000
+#define MAC_PHYCFG2_QUAL_MASK_50610 0x30000000
+#define MAC_PHYCFG2_QUAL_MASK_RT8211 0x30000000
+#define MAC_PHYCFG2_QUAL_MASK_RT8201 0x30000000
+#define MAC_PHYCFG2_QUAL_COMP_MASK 0xc0000000
+#define MAC_PHYCFG2_QUAL_COMP_AC131 0x00000000
+#define MAC_PHYCFG2_QUAL_COMP_50610 0x00000000
+#define MAC_PHYCFG2_QUAL_COMP_RT8211 0x00000000
+#define MAC_PHYCFG2_QUAL_COMP_RT8201 0x00000000
+#define MAC_PHYCFG2_50610_LED_MODES \
+ (MAC_PHYCFG2_EMODE_MASK_50610 | \
+ MAC_PHYCFG2_EMODE_COMP_50610 | \
+ MAC_PHYCFG2_FMODE_MASK_50610 | \
+ MAC_PHYCFG2_FMODE_COMP_50610 | \
+ MAC_PHYCFG2_GMODE_MASK_50610 | \
+ MAC_PHYCFG2_GMODE_COMP_50610 | \
+ MAC_PHYCFG2_ACT_MASK_50610 | \
+ MAC_PHYCFG2_ACT_COMP_50610 | \
+ MAC_PHYCFG2_QUAL_MASK_50610 | \
+ MAC_PHYCFG2_QUAL_COMP_50610)
+#define MAC_PHYCFG2_AC131_LED_MODES \
+ (MAC_PHYCFG2_EMODE_MASK_AC131 | \
+ MAC_PHYCFG2_EMODE_COMP_AC131 | \
+ MAC_PHYCFG2_FMODE_MASK_AC131 | \
+ MAC_PHYCFG2_FMODE_COMP_AC131 | \
+ MAC_PHYCFG2_GMODE_MASK_AC131 | \
+ MAC_PHYCFG2_GMODE_COMP_AC131 | \
+ MAC_PHYCFG2_ACT_MASK_AC131 | \
+ MAC_PHYCFG2_ACT_COMP_AC131 | \
+ MAC_PHYCFG2_QUAL_MASK_AC131 | \
+ MAC_PHYCFG2_QUAL_COMP_AC131)
+#define MAC_PHYCFG2_RTL8211C_LED_MODES \
+ (MAC_PHYCFG2_EMODE_MASK_RT8211 | \
+ MAC_PHYCFG2_EMODE_COMP_RT8211 | \
+ MAC_PHYCFG2_FMODE_MASK_RT8211 | \
+ MAC_PHYCFG2_FMODE_COMP_RT8211 | \
+ MAC_PHYCFG2_GMODE_MASK_RT8211 | \
+ MAC_PHYCFG2_GMODE_COMP_RT8211 | \
+ MAC_PHYCFG2_ACT_MASK_RT8211 | \
+ MAC_PHYCFG2_ACT_COMP_RT8211 | \
+ MAC_PHYCFG2_QUAL_MASK_RT8211 | \
+ MAC_PHYCFG2_QUAL_COMP_RT8211)
+#define MAC_PHYCFG2_RTL8201E_LED_MODES \
+ (MAC_PHYCFG2_EMODE_MASK_RT8201 | \
+ MAC_PHYCFG2_EMODE_COMP_RT8201 | \
+ MAC_PHYCFG2_FMODE_MASK_RT8201 | \
+ MAC_PHYCFG2_FMODE_COMP_RT8201 | \
+ MAC_PHYCFG2_GMODE_MASK_RT8201 | \
+ MAC_PHYCFG2_GMODE_COMP_RT8201 | \
+ MAC_PHYCFG2_ACT_MASK_RT8201 | \
+ MAC_PHYCFG2_ACT_COMP_RT8201 | \
+ MAC_PHYCFG2_QUAL_MASK_RT8201 | \
+ MAC_PHYCFG2_QUAL_COMP_RT8201)
+#define MAC_EXT_RGMII_MODE 0x000005a8
+#define MAC_RGMII_MODE_TX_ENABLE 0x00000001
+#define MAC_RGMII_MODE_TX_LOWPWR 0x00000002
+#define MAC_RGMII_MODE_TX_RESET 0x00000004
+#define MAC_RGMII_MODE_RX_INT_B 0x00000100
+#define MAC_RGMII_MODE_RX_QUALITY 0x00000200
+#define MAC_RGMII_MODE_RX_ACTIVITY 0x00000400
+#define MAC_RGMII_MODE_RX_ENG_DET 0x00000800
+/* 0x5ac --> 0x5b0 unused */
+#define SERDES_RX_CTRL 0x000005b0 /* 5780/5714 only */
+#define SERDES_RX_SIG_DETECT 0x00000400
+#define SG_DIG_CTRL 0x000005b0
+#define SG_DIG_USING_HW_AUTONEG 0x80000000
+#define SG_DIG_SOFT_RESET 0x40000000
+#define SG_DIG_DISABLE_LINKRDY 0x20000000
+#define SG_DIG_CRC16_CLEAR_N 0x01000000
+#define SG_DIG_EN10B 0x00800000
+#define SG_DIG_CLEAR_STATUS 0x00400000
+#define SG_DIG_LOCAL_DUPLEX_STATUS 0x00200000
+#define SG_DIG_LOCAL_LINK_STATUS 0x00100000
+#define SG_DIG_SPEED_STATUS_MASK 0x000c0000
+#define SG_DIG_SPEED_STATUS_SHIFT 18
+#define SG_DIG_JUMBO_PACKET_DISABLE 0x00020000
+#define SG_DIG_RESTART_AUTONEG 0x00010000
+#define SG_DIG_FIBER_MODE 0x00008000
+#define SG_DIG_REMOTE_FAULT_MASK 0x00006000
+#define SG_DIG_PAUSE_MASK 0x00001800
+#define SG_DIG_PAUSE_CAP 0x00000800
+#define SG_DIG_ASYM_PAUSE 0x00001000
+#define SG_DIG_GBIC_ENABLE 0x00000400
+#define SG_DIG_CHECK_END_ENABLE 0x00000200
+#define SG_DIG_SGMII_AUTONEG_TIMER 0x00000100
+#define SG_DIG_CLOCK_PHASE_SELECT 0x00000080
+#define SG_DIG_GMII_INPUT_SELECT 0x00000040
+#define SG_DIG_MRADV_CRC16_SELECT 0x00000020
+#define SG_DIG_COMMA_DETECT_ENABLE 0x00000010
+#define SG_DIG_AUTONEG_TIMER_REDUCE 0x00000008
+#define SG_DIG_AUTONEG_LOW_ENABLE 0x00000004
+#define SG_DIG_REMOTE_LOOPBACK 0x00000002
+#define SG_DIG_LOOPBACK 0x00000001
+#define SG_DIG_COMMON_SETUP (SG_DIG_CRC16_CLEAR_N | \
+ SG_DIG_LOCAL_DUPLEX_STATUS | \
+ SG_DIG_LOCAL_LINK_STATUS | \
+ (0x2 << SG_DIG_SPEED_STATUS_SHIFT) | \
+ SG_DIG_FIBER_MODE | SG_DIG_GBIC_ENABLE)
+#define SG_DIG_STATUS 0x000005b4
+#define SG_DIG_CRC16_BUS_MASK 0xffff0000
+#define SG_DIG_PARTNER_FAULT_MASK 0x00600000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_ASYM_PAUSE 0x00100000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_PAUSE_CAPABLE 0x00080000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_HALF_DUPLEX 0x00040000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_FULL_DUPLEX 0x00020000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_NEXT_PAGE 0x00010000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_AUTONEG_STATE_MASK 0x00000ff0
+#define SG_DIG_IS_SERDES 0x00000100
+#define SG_DIG_COMMA_DETECTOR 0x00000008
+#define SG_DIG_MAC_ACK_STATUS 0x00000004
+#define SG_DIG_AUTONEG_COMPLETE 0x00000002
+#define SG_DIG_AUTONEG_ERROR 0x00000001
+/* 0x5b8 --> 0x600 unused */
+#define MAC_TX_MAC_STATE_BASE 0x00000600 /* 16 bytes */
+#define MAC_RX_MAC_STATE_BASE 0x00000610 /* 20 bytes */
+/* 0x624 --> 0x670 unused */
+
+#define MAC_RSS_INDIR_TBL_0 0x00000630
+
+#define MAC_RSS_HASH_KEY_0 0x00000670
+#define MAC_RSS_HASH_KEY_1 0x00000674
+#define MAC_RSS_HASH_KEY_2 0x00000678
+#define MAC_RSS_HASH_KEY_3 0x0000067c
+#define MAC_RSS_HASH_KEY_4 0x00000680
+#define MAC_RSS_HASH_KEY_5 0x00000684
+#define MAC_RSS_HASH_KEY_6 0x00000688
+#define MAC_RSS_HASH_KEY_7 0x0000068c
+#define MAC_RSS_HASH_KEY_8 0x00000690
+#define MAC_RSS_HASH_KEY_9 0x00000694
+/* 0x698 --> 0x800 unused */
+
+#define MAC_TX_STATS_OCTETS 0x00000800
+#define MAC_TX_STATS_RESV1 0x00000804
+#define MAC_TX_STATS_COLLISIONS 0x00000808
+#define MAC_TX_STATS_XON_SENT 0x0000080c
+#define MAC_TX_STATS_XOFF_SENT 0x00000810
+#define MAC_TX_STATS_RESV2 0x00000814
+#define MAC_TX_STATS_MAC_ERRORS 0x00000818
+#define MAC_TX_STATS_SINGLE_COLLISIONS 0x0000081c
+#define MAC_TX_STATS_MULT_COLLISIONS 0x00000820
+#define MAC_TX_STATS_DEFERRED 0x00000824
+#define MAC_TX_STATS_RESV3 0x00000828
+#define MAC_TX_STATS_EXCESSIVE_COL 0x0000082c
+#define MAC_TX_STATS_LATE_COL 0x00000830
+#define MAC_TX_STATS_RESV4_1 0x00000834
+#define MAC_TX_STATS_RESV4_2 0x00000838
+#define MAC_TX_STATS_RESV4_3 0x0000083c
+#define MAC_TX_STATS_RESV4_4 0x00000840
+#define MAC_TX_STATS_RESV4_5 0x00000844
+#define MAC_TX_STATS_RESV4_6 0x00000848
+#define MAC_TX_STATS_RESV4_7 0x0000084c
+#define MAC_TX_STATS_RESV4_8 0x00000850
+#define MAC_TX_STATS_RESV4_9 0x00000854
+#define MAC_TX_STATS_RESV4_10 0x00000858
+#define MAC_TX_STATS_RESV4_11 0x0000085c
+#define MAC_TX_STATS_RESV4_12 0x00000860
+#define MAC_TX_STATS_RESV4_13 0x00000864
+#define MAC_TX_STATS_RESV4_14 0x00000868
+#define MAC_TX_STATS_UCAST 0x0000086c
+#define MAC_TX_STATS_MCAST 0x00000870
+#define MAC_TX_STATS_BCAST 0x00000874
+#define MAC_TX_STATS_RESV5_1 0x00000878
+#define MAC_TX_STATS_RESV5_2 0x0000087c
+#define MAC_RX_STATS_OCTETS 0x00000880
+#define MAC_RX_STATS_RESV1 0x00000884
+#define MAC_RX_STATS_FRAGMENTS 0x00000888
+#define MAC_RX_STATS_UCAST 0x0000088c
+#define MAC_RX_STATS_MCAST 0x00000890
+#define MAC_RX_STATS_BCAST 0x00000894
+#define MAC_RX_STATS_FCS_ERRORS 0x00000898
+#define MAC_RX_STATS_ALIGN_ERRORS 0x0000089c
+#define MAC_RX_STATS_XON_PAUSE_RECVD 0x000008a0
+#define MAC_RX_STATS_XOFF_PAUSE_RECVD 0x000008a4
+#define MAC_RX_STATS_MAC_CTRL_RECVD 0x000008a8
+#define MAC_RX_STATS_XOFF_ENTERED 0x000008ac
+#define MAC_RX_STATS_FRAME_TOO_LONG 0x000008b0
+#define MAC_RX_STATS_JABBERS 0x000008b4
+#define MAC_RX_STATS_UNDERSIZE 0x000008b8
+/* 0x8bc --> 0xc00 unused */
+
+/* Send data initiator control registers */
+#define SNDDATAI_MODE 0x00000c00
+#define SNDDATAI_MODE_RESET 0x00000001
+#define SNDDATAI_MODE_ENABLE 0x00000002
+#define SNDDATAI_MODE_STAT_OFLOW_ENAB 0x00000004
+#define SNDDATAI_STATUS 0x00000c04
+#define SNDDATAI_STATUS_STAT_OFLOW 0x00000004
+#define SNDDATAI_STATSCTRL 0x00000c08
+#define SNDDATAI_SCTRL_ENABLE 0x00000001
+#define SNDDATAI_SCTRL_FASTUPD 0x00000002
+#define SNDDATAI_SCTRL_CLEAR 0x00000004
+#define SNDDATAI_SCTRL_FLUSH 0x00000008
+#define SNDDATAI_SCTRL_FORCE_ZERO 0x00000010
+#define SNDDATAI_STATSENAB 0x00000c0c
+#define SNDDATAI_STATSINCMASK 0x00000c10
+#define ISO_PKT_TX 0x00000c20
+/* 0xc24 --> 0xc80 unused */
+#define SNDDATAI_COS_CNT_0 0x00000c80
+#define SNDDATAI_COS_CNT_1 0x00000c84
+#define SNDDATAI_COS_CNT_2 0x00000c88
+#define SNDDATAI_COS_CNT_3 0x00000c8c
+#define SNDDATAI_COS_CNT_4 0x00000c90
+#define SNDDATAI_COS_CNT_5 0x00000c94
+#define SNDDATAI_COS_CNT_6 0x00000c98
+#define SNDDATAI_COS_CNT_7 0x00000c9c
+#define SNDDATAI_COS_CNT_8 0x00000ca0
+#define SNDDATAI_COS_CNT_9 0x00000ca4
+#define SNDDATAI_COS_CNT_10 0x00000ca8
+#define SNDDATAI_COS_CNT_11 0x00000cac
+#define SNDDATAI_COS_CNT_12 0x00000cb0
+#define SNDDATAI_COS_CNT_13 0x00000cb4
+#define SNDDATAI_COS_CNT_14 0x00000cb8
+#define SNDDATAI_COS_CNT_15 0x00000cbc
+#define SNDDATAI_DMA_RDQ_FULL_CNT 0x00000cc0
+#define SNDDATAI_DMA_PRIO_RDQ_FULL_CNT 0x00000cc4
+#define SNDDATAI_SDCQ_FULL_CNT 0x00000cc8
+#define SNDDATAI_NICRNG_SSND_PIDX_CNT 0x00000ccc
+#define SNDDATAI_STATS_UPDATED_CNT 0x00000cd0
+#define SNDDATAI_INTERRUPTS_CNT 0x00000cd4
+#define SNDDATAI_AVOID_INTERRUPTS_CNT 0x00000cd8
+#define SNDDATAI_SND_THRESH_HIT_CNT 0x00000cdc
+/* 0xce0 --> 0x1000 unused */
+
+/* Send data completion control registers */
+#define SNDDATAC_MODE 0x00001000
+#define SNDDATAC_MODE_RESET 0x00000001
+#define SNDDATAC_MODE_ENABLE 0x00000002
+#define SNDDATAC_MODE_CDELAY 0x00000010
+/* 0x1004 --> 0x1400 unused */
+
+/* Send BD ring selector */
+#define SNDBDS_MODE 0x00001400
+#define SNDBDS_MODE_RESET 0x00000001
+#define SNDBDS_MODE_ENABLE 0x00000002
+#define SNDBDS_MODE_ATTN_ENABLE 0x00000004
+#define SNDBDS_STATUS 0x00001404
+#define SNDBDS_STATUS_ERROR_ATTN 0x00000004
+#define SNDBDS_HWDIAG 0x00001408
+/* 0x140c --> 0x1440 */
+#define SNDBDS_SEL_CON_IDX_0 0x00001440
+#define SNDBDS_SEL_CON_IDX_1 0x00001444
+#define SNDBDS_SEL_CON_IDX_2 0x00001448
+#define SNDBDS_SEL_CON_IDX_3 0x0000144c
+#define SNDBDS_SEL_CON_IDX_4 0x00001450
+#define SNDBDS_SEL_CON_IDX_5 0x00001454
+#define SNDBDS_SEL_CON_IDX_6 0x00001458
+#define SNDBDS_SEL_CON_IDX_7 0x0000145c
+#define SNDBDS_SEL_CON_IDX_8 0x00001460
+#define SNDBDS_SEL_CON_IDX_9 0x00001464
+#define SNDBDS_SEL_CON_IDX_10 0x00001468
+#define SNDBDS_SEL_CON_IDX_11 0x0000146c
+#define SNDBDS_SEL_CON_IDX_12 0x00001470
+#define SNDBDS_SEL_CON_IDX_13 0x00001474
+#define SNDBDS_SEL_CON_IDX_14 0x00001478
+#define SNDBDS_SEL_CON_IDX_15 0x0000147c
+/* 0x1480 --> 0x1800 unused */
+
+/* Send BD initiator control registers */
+#define SNDBDI_MODE 0x00001800
+#define SNDBDI_MODE_RESET 0x00000001
+#define SNDBDI_MODE_ENABLE 0x00000002
+#define SNDBDI_MODE_ATTN_ENABLE 0x00000004
+#define SNDBDI_MODE_MULTI_TXQ_EN 0x00000020
+#define SNDBDI_STATUS 0x00001804
+#define SNDBDI_STATUS_ERROR_ATTN 0x00000004
+#define SNDBDI_IN_PROD_IDX_0 0x00001808
+#define SNDBDI_IN_PROD_IDX_1 0x0000180c
+#define SNDBDI_IN_PROD_IDX_2 0x00001810
+#define SNDBDI_IN_PROD_IDX_3 0x00001814
+#define SNDBDI_IN_PROD_IDX_4 0x00001818
+#define SNDBDI_IN_PROD_IDX_5 0x0000181c
+#define SNDBDI_IN_PROD_IDX_6 0x00001820
+#define SNDBDI_IN_PROD_IDX_7 0x00001824
+#define SNDBDI_IN_PROD_IDX_8 0x00001828
+#define SNDBDI_IN_PROD_IDX_9 0x0000182c
+#define SNDBDI_IN_PROD_IDX_10 0x00001830
+#define SNDBDI_IN_PROD_IDX_11 0x00001834
+#define SNDBDI_IN_PROD_IDX_12 0x00001838
+#define SNDBDI_IN_PROD_IDX_13 0x0000183c
+#define SNDBDI_IN_PROD_IDX_14 0x00001840
+#define SNDBDI_IN_PROD_IDX_15 0x00001844
+/* 0x1848 --> 0x1c00 unused */
+
+/* Send BD completion control registers */
+#define SNDBDC_MODE 0x00001c00
+#define SNDBDC_MODE_RESET 0x00000001
+#define SNDBDC_MODE_ENABLE 0x00000002
+#define SNDBDC_MODE_ATTN_ENABLE 0x00000004
+/* 0x1c04 --> 0x2000 unused */
+
+/* Receive list placement control registers */
+#define RCVLPC_MODE 0x00002000
+#define RCVLPC_MODE_RESET 0x00000001
+#define RCVLPC_MODE_ENABLE 0x00000002
+#define RCVLPC_MODE_CLASS0_ATTN_ENAB 0x00000004
+#define RCVLPC_MODE_MAPOOR_AATTN_ENAB 0x00000008
+#define RCVLPC_MODE_STAT_OFLOW_ENAB 0x00000010
+#define RCVLPC_STATUS 0x00002004
+#define RCVLPC_STATUS_CLASS0 0x00000004
+#define RCVLPC_STATUS_MAPOOR 0x00000008
+#define RCVLPC_STATUS_STAT_OFLOW 0x00000010
+#define RCVLPC_LOCK 0x00002008
+#define RCVLPC_LOCK_REQ_MASK 0x0000ffff
+#define RCVLPC_LOCK_REQ_SHIFT 0
+#define RCVLPC_LOCK_GRANT_MASK 0xffff0000
+#define RCVLPC_LOCK_GRANT_SHIFT 16
+#define RCVLPC_NON_EMPTY_BITS 0x0000200c
+#define RCVLPC_NON_EMPTY_BITS_MASK 0x0000ffff
+#define RCVLPC_CONFIG 0x00002010
+#define RCVLPC_STATSCTRL 0x00002014
+#define RCVLPC_STATSCTRL_ENABLE 0x00000001
+#define RCVLPC_STATSCTRL_FASTUPD 0x00000002
+#define RCVLPC_STATS_ENABLE 0x00002018
+#define RCVLPC_STATSENAB_ASF_FIX 0x00000002
+#define RCVLPC_STATSENAB_DACK_FIX 0x00040000
+#define RCVLPC_STATSENAB_LNGBRST_RFIX 0x00400000
+#define RCVLPC_STATS_INCMASK 0x0000201c
+/* 0x2020 --> 0x2100 unused */
+#define RCVLPC_SELLST_BASE 0x00002100 /* 16 16-byte entries */
+#define SELLST_TAIL 0x00000004
+#define SELLST_CONT 0x00000008
+#define SELLST_UNUSED 0x0000000c
+#define RCVLPC_COS_CNTL_BASE 0x00002200 /* 16 4-byte entries */
+#define RCVLPC_DROP_FILTER_CNT 0x00002240
+#define RCVLPC_DMA_WQ_FULL_CNT 0x00002244
+#define RCVLPC_DMA_HIPRIO_WQ_FULL_CNT 0x00002248
+#define RCVLPC_NO_RCV_BD_CNT 0x0000224c
+#define RCVLPC_IN_DISCARDS_CNT 0x00002250
+#define RCVLPC_IN_ERRORS_CNT 0x00002254
+#define RCVLPC_RCV_THRESH_HIT_CNT 0x00002258
+/* 0x225c --> 0x2400 unused */
+
+/* Receive Data and Receive BD Initiator Control */
+#define RCVDBDI_MODE 0x00002400
+#define RCVDBDI_MODE_RESET 0x00000001
+#define RCVDBDI_MODE_ENABLE 0x00000002
+#define RCVDBDI_MODE_JUMBOBD_NEEDED 0x00000004
+#define RCVDBDI_MODE_FRM_TOO_BIG 0x00000008
+#define RCVDBDI_MODE_INV_RING_SZ 0x00000010
+#define RCVDBDI_MODE_LRG_RING_SZ 0x00010000
+#define RCVDBDI_STATUS 0x00002404
+#define RCVDBDI_STATUS_JUMBOBD_NEEDED 0x00000004
+#define RCVDBDI_STATUS_FRM_TOO_BIG 0x00000008
+#define RCVDBDI_STATUS_INV_RING_SZ 0x00000010
+#define RCVDBDI_SPLIT_FRAME_MINSZ 0x00002408
+/* 0x240c --> 0x2440 unused */
+#define RCVDBDI_JUMBO_BD 0x00002440 /* TG3_BDINFO_... */
+#define RCVDBDI_STD_BD 0x00002450 /* TG3_BDINFO_... */
+#define RCVDBDI_MINI_BD 0x00002460 /* TG3_BDINFO_... */
+#define RCVDBDI_JUMBO_CON_IDX 0x00002470
+#define RCVDBDI_STD_CON_IDX 0x00002474
+#define RCVDBDI_MINI_CON_IDX 0x00002478
+/* 0x247c --> 0x2480 unused */
+#define RCVDBDI_BD_PROD_IDX_0 0x00002480
+#define RCVDBDI_BD_PROD_IDX_1 0x00002484
+#define RCVDBDI_BD_PROD_IDX_2 0x00002488
+#define RCVDBDI_BD_PROD_IDX_3 0x0000248c
+#define RCVDBDI_BD_PROD_IDX_4 0x00002490
+#define RCVDBDI_BD_PROD_IDX_5 0x00002494
+#define RCVDBDI_BD_PROD_IDX_6 0x00002498
+#define RCVDBDI_BD_PROD_IDX_7 0x0000249c
+#define RCVDBDI_BD_PROD_IDX_8 0x000024a0
+#define RCVDBDI_BD_PROD_IDX_9 0x000024a4
+#define RCVDBDI_BD_PROD_IDX_10 0x000024a8
+#define RCVDBDI_BD_PROD_IDX_11 0x000024ac
+#define RCVDBDI_BD_PROD_IDX_12 0x000024b0
+#define RCVDBDI_BD_PROD_IDX_13 0x000024b4
+#define RCVDBDI_BD_PROD_IDX_14 0x000024b8
+#define RCVDBDI_BD_PROD_IDX_15 0x000024bc
+#define RCVDBDI_HWDIAG 0x000024c0
+/* 0x24c4 --> 0x2800 unused */
+
+/* Receive Data Completion Control */
+#define RCVDCC_MODE 0x00002800
+#define RCVDCC_MODE_RESET 0x00000001
+#define RCVDCC_MODE_ENABLE 0x00000002
+#define RCVDCC_MODE_ATTN_ENABLE 0x00000004
+/* 0x2804 --> 0x2c00 unused */
+
+/* Receive BD Initiator Control Registers */
+#define RCVBDI_MODE 0x00002c00
+#define RCVBDI_MODE_RESET 0x00000001
+#define RCVBDI_MODE_ENABLE 0x00000002
+#define RCVBDI_MODE_RCB_ATTN_ENAB 0x00000004
+#define RCVBDI_STATUS 0x00002c04
+#define RCVBDI_STATUS_RCB_ATTN 0x00000004
+#define RCVBDI_JUMBO_PROD_IDX 0x00002c08
+#define RCVBDI_STD_PROD_IDX 0x00002c0c
+#define RCVBDI_MINI_PROD_IDX 0x00002c10
+#define RCVBDI_MINI_THRESH 0x00002c14
+#define RCVBDI_STD_THRESH 0x00002c18
+#define RCVBDI_JUMBO_THRESH 0x00002c1c
+/* 0x2c20 --> 0x2d00 unused */
+
+#define STD_REPLENISH_LWM 0x00002d00
+#define JMB_REPLENISH_LWM 0x00002d04
+/* 0x2d08 --> 0x3000 unused */
+
+/* Receive BD Completion Control Registers */
+#define RCVCC_MODE 0x00003000
+#define RCVCC_MODE_RESET 0x00000001
+#define RCVCC_MODE_ENABLE 0x00000002
+#define RCVCC_MODE_ATTN_ENABLE 0x00000004
+#define RCVCC_STATUS 0x00003004
+#define RCVCC_STATUS_ERROR_ATTN 0x00000004
+#define RCVCC_JUMP_PROD_IDX 0x00003008
+#define RCVCC_STD_PROD_IDX 0x0000300c
+#define RCVCC_MINI_PROD_IDX 0x00003010
+/* 0x3014 --> 0x3400 unused */
+
+/* Receive list selector control registers */
+#define RCVLSC_MODE 0x00003400
+#define RCVLSC_MODE_RESET 0x00000001
+#define RCVLSC_MODE_ENABLE 0x00000002
+#define RCVLSC_MODE_ATTN_ENABLE 0x00000004
+#define RCVLSC_STATUS 0x00003404
+#define RCVLSC_STATUS_ERROR_ATTN 0x00000004
+/* 0x3408 --> 0x3600 unused */
+
+/* CPMU registers */
+#define TG3_CPMU_CTRL 0x00003600
+#define CPMU_CTRL_LINK_IDLE_MODE 0x00000200
+#define CPMU_CTRL_LINK_AWARE_MODE 0x00000400
+#define CPMU_CTRL_LINK_SPEED_MODE 0x00004000
+#define CPMU_CTRL_GPHY_10MB_RXONLY 0x00010000
+#define TG3_CPMU_LSPD_10MB_CLK 0x00003604
+#define CPMU_LSPD_10MB_MACCLK_MASK 0x001f0000
+#define CPMU_LSPD_10MB_MACCLK_6_25 0x00130000
+/* 0x3608 --> 0x360c unused */
+
+#define TG3_CPMU_LSPD_1000MB_CLK 0x0000360c
+#define CPMU_LSPD_1000MB_MACCLK_62_5 0x00000000
+#define CPMU_LSPD_1000MB_MACCLK_12_5 0x00110000
+#define CPMU_LSPD_1000MB_MACCLK_MASK 0x001f0000
+#define TG3_CPMU_LNK_AWARE_PWRMD 0x00003610
+#define CPMU_LNK_AWARE_MACCLK_MASK 0x001f0000
+#define CPMU_LNK_AWARE_MACCLK_6_25 0x00130000
+/* 0x3614 --> 0x361c unused */
+
+#define TG3_CPMU_HST_ACC 0x0000361c
+#define CPMU_HST_ACC_MACCLK_MASK 0x001f0000
+#define CPMU_HST_ACC_MACCLK_6_25 0x00130000
+/* 0x3620 --> 0x3630 unused */
+
+#define TG3_CPMU_CLCK_ORIDE 0x00003624
+#define CPMU_CLCK_ORIDE_MAC_ORIDE_EN 0x80000000
+
+#define TG3_CPMU_CLCK_STAT 0x00003630
+#define CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001f0000
+#define CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000
+#define CPMU_CLCK_STAT_MAC_CLCK_12_5 0x00110000
+#define CPMU_CLCK_STAT_MAC_CLCK_6_25 0x00130000
+/* 0x3634 --> 0x365c unused */
+
+#define TG3_CPMU_MUTEX_REQ 0x0000365c
+#define CPMU_MUTEX_REQ_DRIVER 0x00001000
+#define TG3_CPMU_MUTEX_GNT 0x00003660
+#define CPMU_MUTEX_GNT_DRIVER 0x00001000
+#define TG3_CPMU_PHY_STRAP 0x00003664
+#define TG3_CPMU_PHY_STRAP_IS_SERDES 0x00000020
+/* 0x3664 --> 0x36b0 unused */
+
+#define TG3_CPMU_EEE_MODE 0x000036b0
+#define TG3_CPMU_EEEMD_APE_TX_DET_EN 0x00000004
+#define TG3_CPMU_EEEMD_ERLY_L1_XIT_DET 0x00000008
+#define TG3_CPMU_EEEMD_SND_IDX_DET_EN 0x00000040
+#define TG3_CPMU_EEEMD_LPI_ENABLE 0x00000080
+#define TG3_CPMU_EEEMD_LPI_IN_TX 0x00000100
+#define TG3_CPMU_EEEMD_LPI_IN_RX 0x00000200
+#define TG3_CPMU_EEEMD_EEE_ENABLE 0x00100000
+#define TG3_CPMU_EEE_DBTMR1 0x000036b4
+#define TG3_CPMU_DBTMR1_PCIEXIT_2047US 0x07ff0000
+#define TG3_CPMU_DBTMR1_LNKIDLE_2047US 0x000070ff
+#define TG3_CPMU_EEE_DBTMR2 0x000036b8
+#define TG3_CPMU_DBTMR2_APE_TX_2047US 0x07ff0000
+#define TG3_CPMU_DBTMR2_TXIDXEQ_2047US 0x000070ff
+#define TG3_CPMU_EEE_LNKIDL_CTRL 0x000036bc
+#define TG3_CPMU_EEE_LNKIDL_PCIE_NL0 0x01000000
+#define TG3_CPMU_EEE_LNKIDL_UART_IDL 0x00000004
+/* 0x36c0 --> 0x36d0 unused */
+
+#define TG3_CPMU_EEE_CTRL 0x000036d0
+#define TG3_CPMU_EEE_CTRL_EXIT_16_5_US 0x0000019d
+#define TG3_CPMU_EEE_CTRL_EXIT_36_US 0x00000384
+#define TG3_CPMU_EEE_CTRL_EXIT_20_1_US 0x000001f8
+/* 0x36d4 --> 0x3800 unused */
+
+/* Mbuf cluster free registers */
+#define MBFREE_MODE 0x00003800
+#define MBFREE_MODE_RESET 0x00000001
+#define MBFREE_MODE_ENABLE 0x00000002
+#define MBFREE_STATUS 0x00003804
+/* 0x3808 --> 0x3c00 unused */
+
+/* Host coalescing control registers */
+#define HOSTCC_MODE 0x00003c00
+#define HOSTCC_MODE_RESET 0x00000001
+#define HOSTCC_MODE_ENABLE 0x00000002
+#define HOSTCC_MODE_ATTN 0x00000004
+#define HOSTCC_MODE_NOW 0x00000008
+#define HOSTCC_MODE_FULL_STATUS 0x00000000
+#define HOSTCC_MODE_64BYTE 0x00000080
+#define HOSTCC_MODE_32BYTE 0x00000100
+#define HOSTCC_MODE_CLRTICK_RXBD 0x00000200
+#define HOSTCC_MODE_CLRTICK_TXBD 0x00000400
+#define HOSTCC_MODE_NOINT_ON_NOW 0x00000800
+#define HOSTCC_MODE_NOINT_ON_FORCE 0x00001000
+#define HOSTCC_MODE_COAL_VEC1_NOW 0x00002000
+#define HOSTCC_STATUS 0x00003c04
+#define HOSTCC_STATUS_ERROR_ATTN 0x00000004
+#define HOSTCC_RXCOL_TICKS 0x00003c08
+#define LOW_RXCOL_TICKS 0x00000032
+#define LOW_RXCOL_TICKS_CLRTCKS 0x00000014
+#define DEFAULT_RXCOL_TICKS 0x00000048
+#define HIGH_RXCOL_TICKS 0x00000096
+#define MAX_RXCOL_TICKS 0x000003ff
+#define HOSTCC_TXCOL_TICKS 0x00003c0c
+#define LOW_TXCOL_TICKS 0x00000096
+#define LOW_TXCOL_TICKS_CLRTCKS 0x00000048
+#define DEFAULT_TXCOL_TICKS 0x0000012c
+#define HIGH_TXCOL_TICKS 0x00000145
+#define MAX_TXCOL_TICKS 0x000003ff
+#define HOSTCC_RXMAX_FRAMES 0x00003c10
+#define LOW_RXMAX_FRAMES 0x00000005
+#define DEFAULT_RXMAX_FRAMES 0x00000008
+#define HIGH_RXMAX_FRAMES 0x00000012
+#define MAX_RXMAX_FRAMES 0x000000ff
+#define HOSTCC_TXMAX_FRAMES 0x00003c14
+#define LOW_TXMAX_FRAMES 0x00000035
+#define DEFAULT_TXMAX_FRAMES 0x0000004b
+#define HIGH_TXMAX_FRAMES 0x00000052
+#define MAX_TXMAX_FRAMES 0x000000ff
+#define HOSTCC_RXCOAL_TICK_INT 0x00003c18
+#define DEFAULT_RXCOAL_TICK_INT 0x00000019
+#define DEFAULT_RXCOAL_TICK_INT_CLRTCKS 0x00000014
+#define MAX_RXCOAL_TICK_INT 0x000003ff
+#define HOSTCC_TXCOAL_TICK_INT 0x00003c1c
+#define DEFAULT_TXCOAL_TICK_INT 0x00000019
+#define DEFAULT_TXCOAL_TICK_INT_CLRTCKS 0x00000014
+#define MAX_TXCOAL_TICK_INT 0x000003ff
+#define HOSTCC_RXCOAL_MAXF_INT 0x00003c20
+#define DEFAULT_RXCOAL_MAXF_INT 0x00000005
+#define MAX_RXCOAL_MAXF_INT 0x000000ff
+#define HOSTCC_TXCOAL_MAXF_INT 0x00003c24
+#define DEFAULT_TXCOAL_MAXF_INT 0x00000005
+#define MAX_TXCOAL_MAXF_INT 0x000000ff
+#define HOSTCC_STAT_COAL_TICKS 0x00003c28
+#define DEFAULT_STAT_COAL_TICKS 0x000f4240
+#define MAX_STAT_COAL_TICKS 0xd693d400
+#define MIN_STAT_COAL_TICKS 0x00000064
+/* 0x3c2c --> 0x3c30 unused */
+#define HOSTCC_STATS_BLK_HOST_ADDR 0x00003c30 /* 64-bit */
+#define HOSTCC_STATUS_BLK_HOST_ADDR 0x00003c38 /* 64-bit */
+#define HOSTCC_STATS_BLK_NIC_ADDR 0x00003c40
+#define HOSTCC_STATUS_BLK_NIC_ADDR 0x00003c44
+#define HOSTCC_FLOW_ATTN 0x00003c48
+#define HOSTCC_FLOW_ATTN_MBUF_LWM 0x00000040
+/* 0x3c4c --> 0x3c50 unused */
+#define HOSTCC_JUMBO_CON_IDX 0x00003c50
+#define HOSTCC_STD_CON_IDX 0x00003c54
+#define HOSTCC_MINI_CON_IDX 0x00003c58
+/* 0x3c5c --> 0x3c80 unused */
+#define HOSTCC_RET_PROD_IDX_0 0x00003c80
+#define HOSTCC_RET_PROD_IDX_1 0x00003c84
+#define HOSTCC_RET_PROD_IDX_2 0x00003c88
+#define HOSTCC_RET_PROD_IDX_3 0x00003c8c
+#define HOSTCC_RET_PROD_IDX_4 0x00003c90
+#define HOSTCC_RET_PROD_IDX_5 0x00003c94
+#define HOSTCC_RET_PROD_IDX_6 0x00003c98
+#define HOSTCC_RET_PROD_IDX_7 0x00003c9c
+#define HOSTCC_RET_PROD_IDX_8 0x00003ca0
+#define HOSTCC_RET_PROD_IDX_9 0x00003ca4
+#define HOSTCC_RET_PROD_IDX_10 0x00003ca8
+#define HOSTCC_RET_PROD_IDX_11 0x00003cac
+#define HOSTCC_RET_PROD_IDX_12 0x00003cb0
+#define HOSTCC_RET_PROD_IDX_13 0x00003cb4
+#define HOSTCC_RET_PROD_IDX_14 0x00003cb8
+#define HOSTCC_RET_PROD_IDX_15 0x00003cbc
+#define HOSTCC_SND_CON_IDX_0 0x00003cc0
+#define HOSTCC_SND_CON_IDX_1 0x00003cc4
+#define HOSTCC_SND_CON_IDX_2 0x00003cc8
+#define HOSTCC_SND_CON_IDX_3 0x00003ccc
+#define HOSTCC_SND_CON_IDX_4 0x00003cd0
+#define HOSTCC_SND_CON_IDX_5 0x00003cd4
+#define HOSTCC_SND_CON_IDX_6 0x00003cd8
+#define HOSTCC_SND_CON_IDX_7 0x00003cdc
+#define HOSTCC_SND_CON_IDX_8 0x00003ce0
+#define HOSTCC_SND_CON_IDX_9 0x00003ce4
+#define HOSTCC_SND_CON_IDX_10 0x00003ce8
+#define HOSTCC_SND_CON_IDX_11 0x00003cec
+#define HOSTCC_SND_CON_IDX_12 0x00003cf0
+#define HOSTCC_SND_CON_IDX_13 0x00003cf4
+#define HOSTCC_SND_CON_IDX_14 0x00003cf8
+#define HOSTCC_SND_CON_IDX_15 0x00003cfc
+#define HOSTCC_STATBLCK_RING1 0x00003d00
+/* 0x3d00 --> 0x3d80 unused */
+
+#define HOSTCC_RXCOL_TICKS_VEC1 0x00003d80
+#define HOSTCC_TXCOL_TICKS_VEC1 0x00003d84
+#define HOSTCC_RXMAX_FRAMES_VEC1 0x00003d88
+#define HOSTCC_TXMAX_FRAMES_VEC1 0x00003d8c
+#define HOSTCC_RXCOAL_MAXF_INT_VEC1 0x00003d90
+#define HOSTCC_TXCOAL_MAXF_INT_VEC1 0x00003d94
+/* 0x3d98 --> 0x4000 unused */
+
+/* Memory arbiter control registers */
+#define MEMARB_MODE 0x00004000
+#define MEMARB_MODE_RESET 0x00000001
+#define MEMARB_MODE_ENABLE 0x00000002
+#define MEMARB_STATUS 0x00004004
+#define MEMARB_TRAP_ADDR_LOW 0x00004008
+#define MEMARB_TRAP_ADDR_HIGH 0x0000400c
+/* 0x4010 --> 0x4400 unused */
+
+/* Buffer manager control registers */
+#define BUFMGR_MODE 0x00004400
+#define BUFMGR_MODE_RESET 0x00000001
+#define BUFMGR_MODE_ENABLE 0x00000002
+#define BUFMGR_MODE_ATTN_ENABLE 0x00000004
+#define BUFMGR_MODE_BM_TEST 0x00000008
+#define BUFMGR_MODE_MBLOW_ATTN_ENAB 0x00000010
+#define BUFMGR_MODE_NO_TX_UNDERRUN 0x80000000
+#define BUFMGR_STATUS 0x00004404
+#define BUFMGR_STATUS_ERROR 0x00000004
+#define BUFMGR_STATUS_MBLOW 0x00000010
+#define BUFMGR_MB_POOL_ADDR 0x00004408
+#define BUFMGR_MB_POOL_SIZE 0x0000440c
+#define BUFMGR_MB_RDMA_LOW_WATER 0x00004410
+#define DEFAULT_MB_RDMA_LOW_WATER 0x00000050
+#define DEFAULT_MB_RDMA_LOW_WATER_5705 0x00000000
+#define DEFAULT_MB_RDMA_LOW_WATER_JUMBO 0x00000130
+#define DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780 0x00000000
+#define BUFMGR_MB_MACRX_LOW_WATER 0x00004414
+#define DEFAULT_MB_MACRX_LOW_WATER 0x00000020
+#define DEFAULT_MB_MACRX_LOW_WATER_5705 0x00000010
+#define DEFAULT_MB_MACRX_LOW_WATER_5906 0x00000004
+#define DEFAULT_MB_MACRX_LOW_WATER_57765 0x0000002a
+#define DEFAULT_MB_MACRX_LOW_WATER_JUMBO 0x00000098
+#define DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780 0x0000004b
+#define DEFAULT_MB_MACRX_LOW_WATER_JUMBO_57765 0x0000007e
+#define BUFMGR_MB_HIGH_WATER 0x00004418
+#define DEFAULT_MB_HIGH_WATER 0x00000060
+#define DEFAULT_MB_HIGH_WATER_5705 0x00000060
+#define DEFAULT_MB_HIGH_WATER_5906 0x00000010
+#define DEFAULT_MB_HIGH_WATER_57765 0x000000a0
+#define DEFAULT_MB_HIGH_WATER_JUMBO 0x0000017c
+#define DEFAULT_MB_HIGH_WATER_JUMBO_5780 0x00000096
+#define DEFAULT_MB_HIGH_WATER_JUMBO_57765 0x000000ea
+#define BUFMGR_RX_MB_ALLOC_REQ 0x0000441c
+#define BUFMGR_MB_ALLOC_BIT 0x10000000
+#define BUFMGR_RX_MB_ALLOC_RESP 0x00004420
+#define BUFMGR_TX_MB_ALLOC_REQ 0x00004424
+#define BUFMGR_TX_MB_ALLOC_RESP 0x00004428
+#define BUFMGR_DMA_DESC_POOL_ADDR 0x0000442c
+#define BUFMGR_DMA_DESC_POOL_SIZE 0x00004430
+#define BUFMGR_DMA_LOW_WATER 0x00004434
+#define DEFAULT_DMA_LOW_WATER 0x00000005
+#define BUFMGR_DMA_HIGH_WATER 0x00004438
+#define DEFAULT_DMA_HIGH_WATER 0x0000000a
+#define BUFMGR_RX_DMA_ALLOC_REQ 0x0000443c
+#define BUFMGR_RX_DMA_ALLOC_RESP 0x00004440
+#define BUFMGR_TX_DMA_ALLOC_REQ 0x00004444
+#define BUFMGR_TX_DMA_ALLOC_RESP 0x00004448
+#define BUFMGR_HWDIAG_0 0x0000444c
+#define BUFMGR_HWDIAG_1 0x00004450
+#define BUFMGR_HWDIAG_2 0x00004454
+/* 0x4458 --> 0x4800 unused */
+
+/* Read DMA control registers */
+#define RDMAC_MODE 0x00004800
+#define RDMAC_MODE_RESET 0x00000001
+#define RDMAC_MODE_ENABLE 0x00000002
+#define RDMAC_MODE_TGTABORT_ENAB 0x00000004
+#define RDMAC_MODE_MSTABORT_ENAB 0x00000008
+#define RDMAC_MODE_PARITYERR_ENAB 0x00000010
+#define RDMAC_MODE_ADDROFLOW_ENAB 0x00000020
+#define RDMAC_MODE_FIFOOFLOW_ENAB 0x00000040
+#define RDMAC_MODE_FIFOURUN_ENAB 0x00000080
+#define RDMAC_MODE_FIFOOREAD_ENAB 0x00000100
+#define RDMAC_MODE_LNGREAD_ENAB 0x00000200
+#define RDMAC_MODE_SPLIT_ENABLE 0x00000800
+#define RDMAC_MODE_BD_SBD_CRPT_ENAB 0x00000800
+#define RDMAC_MODE_SPLIT_RESET 0x00001000
+#define RDMAC_MODE_MBUF_RBD_CRPT_ENAB 0x00001000
+#define RDMAC_MODE_MBUF_SBD_CRPT_ENAB 0x00002000
+#define RDMAC_MODE_FIFO_SIZE_128 0x00020000
+#define RDMAC_MODE_FIFO_LONG_BURST 0x00030000
+#define RDMAC_MODE_MULT_DMA_RD_DIS 0x01000000
+#define RDMAC_MODE_IPV4_LSO_EN 0x08000000
+#define RDMAC_MODE_IPV6_LSO_EN 0x10000000
+#define RDMAC_MODE_H2BNC_VLAN_DET 0x20000000
+#define RDMAC_STATUS 0x00004804
+#define RDMAC_STATUS_TGTABORT 0x00000004
+#define RDMAC_STATUS_MSTABORT 0x00000008
+#define RDMAC_STATUS_PARITYERR 0x00000010
+#define RDMAC_STATUS_ADDROFLOW 0x00000020
+#define RDMAC_STATUS_FIFOOFLOW 0x00000040
+#define RDMAC_STATUS_FIFOURUN 0x00000080
+#define RDMAC_STATUS_FIFOOREAD 0x00000100
+#define RDMAC_STATUS_LNGREAD 0x00000200
+/* 0x4808 --> 0x4900 unused */
+
+#define TG3_RDMA_RSRVCTRL_REG 0x00004900
+#define TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX 0x00000004
+#define TG3_RDMA_RSRVCTRL_FIFO_LWM_1_5K 0x00000c00
+#define TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK 0x00000ff0
+#define TG3_RDMA_RSRVCTRL_FIFO_HWM_1_5K 0x000c0000
+#define TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK 0x000ff000
+#define TG3_RDMA_RSRVCTRL_TXMRGN_320B 0x28000000
+#define TG3_RDMA_RSRVCTRL_TXMRGN_MASK 0xffe00000
+/* 0x4904 --> 0x4910 unused */
+
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL 0x00004910
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K 0x00030000
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K 0x000c0000
+/* 0x4914 --> 0x4c00 unused */
+
+/* Write DMA control registers */
+#define WDMAC_MODE 0x00004c00
+#define WDMAC_MODE_RESET 0x00000001
+#define WDMAC_MODE_ENABLE 0x00000002
+#define WDMAC_MODE_TGTABORT_ENAB 0x00000004
+#define WDMAC_MODE_MSTABORT_ENAB 0x00000008
+#define WDMAC_MODE_PARITYERR_ENAB 0x00000010
+#define WDMAC_MODE_ADDROFLOW_ENAB 0x00000020
+#define WDMAC_MODE_FIFOOFLOW_ENAB 0x00000040
+#define WDMAC_MODE_FIFOURUN_ENAB 0x00000080
+#define WDMAC_MODE_FIFOOREAD_ENAB 0x00000100
+#define WDMAC_MODE_LNGREAD_ENAB 0x00000200
+#define WDMAC_MODE_RX_ACCEL 0x00000400
+#define WDMAC_MODE_STATUS_TAG_FIX 0x20000000
+#define WDMAC_MODE_BURST_ALL_DATA 0xc0000000
+#define WDMAC_STATUS 0x00004c04
+#define WDMAC_STATUS_TGTABORT 0x00000004
+#define WDMAC_STATUS_MSTABORT 0x00000008
+#define WDMAC_STATUS_PARITYERR 0x00000010
+#define WDMAC_STATUS_ADDROFLOW 0x00000020
+#define WDMAC_STATUS_FIFOOFLOW 0x00000040
+#define WDMAC_STATUS_FIFOURUN 0x00000080
+#define WDMAC_STATUS_FIFOOREAD 0x00000100
+#define WDMAC_STATUS_LNGREAD 0x00000200
+/* 0x4c08 --> 0x5000 unused */
+
+/* Per-cpu register offsets (arm9) */
+#define CPU_MODE 0x00000000
+#define CPU_MODE_RESET 0x00000001
+#define CPU_MODE_HALT 0x00000400
+#define CPU_STATE 0x00000004
+#define CPU_EVTMASK 0x00000008
+/* 0xc --> 0x1c reserved */
+#define CPU_PC 0x0000001c
+#define CPU_INSN 0x00000020
+#define CPU_SPAD_UFLOW 0x00000024
+#define CPU_WDOG_CLEAR 0x00000028
+#define CPU_WDOG_VECTOR 0x0000002c
+#define CPU_WDOG_PC 0x00000030
+#define CPU_HW_BP 0x00000034
+/* 0x38 --> 0x44 unused */
+#define CPU_WDOG_SAVED_STATE 0x00000044
+#define CPU_LAST_BRANCH_ADDR 0x00000048
+#define CPU_SPAD_UFLOW_SET 0x0000004c
+/* 0x50 --> 0x200 unused */
+#define CPU_R0 0x00000200
+#define CPU_R1 0x00000204
+#define CPU_R2 0x00000208
+#define CPU_R3 0x0000020c
+#define CPU_R4 0x00000210
+#define CPU_R5 0x00000214
+#define CPU_R6 0x00000218
+#define CPU_R7 0x0000021c
+#define CPU_R8 0x00000220
+#define CPU_R9 0x00000224
+#define CPU_R10 0x00000228
+#define CPU_R11 0x0000022c
+#define CPU_R12 0x00000230
+#define CPU_R13 0x00000234
+#define CPU_R14 0x00000238
+#define CPU_R15 0x0000023c
+#define CPU_R16 0x00000240
+#define CPU_R17 0x00000244
+#define CPU_R18 0x00000248
+#define CPU_R19 0x0000024c
+#define CPU_R20 0x00000250
+#define CPU_R21 0x00000254
+#define CPU_R22 0x00000258
+#define CPU_R23 0x0000025c
+#define CPU_R24 0x00000260
+#define CPU_R25 0x00000264
+#define CPU_R26 0x00000268
+#define CPU_R27 0x0000026c
+#define CPU_R28 0x00000270
+#define CPU_R29 0x00000274
+#define CPU_R30 0x00000278
+#define CPU_R31 0x0000027c
+/* 0x280 --> 0x400 unused */
+
+#define RX_CPU_BASE 0x00005000
+#define RX_CPU_MODE 0x00005000
+#define RX_CPU_STATE 0x00005004
+#define RX_CPU_PGMCTR 0x0000501c
+#define RX_CPU_HWBKPT 0x00005034
+#define TX_CPU_BASE 0x00005400
+#define TX_CPU_MODE 0x00005400
+#define TX_CPU_STATE 0x00005404
+#define TX_CPU_PGMCTR 0x0000541c
+
+#define VCPU_STATUS 0x00005100
+#define VCPU_STATUS_INIT_DONE 0x04000000
+#define VCPU_STATUS_DRV_RESET 0x08000000
+
+#define VCPU_CFGSHDW 0x00005104
+#define VCPU_CFGSHDW_WOL_ENABLE 0x00000001
+#define VCPU_CFGSHDW_WOL_MAGPKT 0x00000004
+#define VCPU_CFGSHDW_ASPM_DBNC 0x00001000
+
+/* Mailboxes */
+#define GRCMBOX_BASE 0x00005600
+#define GRCMBOX_INTERRUPT_0 0x00005800 /* 64-bit */
+#define GRCMBOX_INTERRUPT_1 0x00005808 /* 64-bit */
+#define GRCMBOX_INTERRUPT_2 0x00005810 /* 64-bit */
+#define GRCMBOX_INTERRUPT_3 0x00005818 /* 64-bit */
+#define GRCMBOX_GENERAL_0 0x00005820 /* 64-bit */
+#define GRCMBOX_GENERAL_1 0x00005828 /* 64-bit */
+#define GRCMBOX_GENERAL_2 0x00005830 /* 64-bit */
+#define GRCMBOX_GENERAL_3 0x00005838 /* 64-bit */
+#define GRCMBOX_GENERAL_4 0x00005840 /* 64-bit */
+#define GRCMBOX_GENERAL_5 0x00005848 /* 64-bit */
+#define GRCMBOX_GENERAL_6 0x00005850 /* 64-bit */
+#define GRCMBOX_GENERAL_7 0x00005858 /* 64-bit */
+#define GRCMBOX_RELOAD_STAT 0x00005860 /* 64-bit */
+#define GRCMBOX_RCVSTD_PROD_IDX 0x00005868 /* 64-bit */
+#define GRCMBOX_RCVJUMBO_PROD_IDX 0x00005870 /* 64-bit */
+#define GRCMBOX_RCVMINI_PROD_IDX 0x00005878 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_0 0x00005880 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_1 0x00005888 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_2 0x00005890 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_3 0x00005898 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_4 0x000058a0 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_5 0x000058a8 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_6 0x000058b0 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_7 0x000058b8 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_8 0x000058c0 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_9 0x000058c8 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_10 0x000058d0 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_11 0x000058d8 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_12 0x000058e0 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_13 0x000058e8 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_14 0x000058f0 /* 64-bit */
+#define GRCMBOX_RCVRET_CON_IDX_15 0x000058f8 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_0 0x00005900 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_1 0x00005908 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_2 0x00005910 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_3 0x00005918 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_4 0x00005920 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_5 0x00005928 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_6 0x00005930 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_7 0x00005938 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_8 0x00005940 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_9 0x00005948 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_10 0x00005950 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_11 0x00005958 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_12 0x00005960 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_13 0x00005968 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_14 0x00005970 /* 64-bit */
+#define GRCMBOX_SNDHOST_PROD_IDX_15 0x00005978 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_0 0x00005980 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_1 0x00005988 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_2 0x00005990 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_3 0x00005998 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_4 0x000059a0 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_5 0x000059a8 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_6 0x000059b0 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_7 0x000059b8 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_8 0x000059c0 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_9 0x000059c8 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_10 0x000059d0 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_11 0x000059d8 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_12 0x000059e0 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_13 0x000059e8 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_14 0x000059f0 /* 64-bit */
+#define GRCMBOX_SNDNIC_PROD_IDX_15 0x000059f8 /* 64-bit */
+#define GRCMBOX_HIGH_PRIO_EV_VECTOR 0x00005a00
+#define GRCMBOX_HIGH_PRIO_EV_MASK 0x00005a04
+#define GRCMBOX_LOW_PRIO_EV_VEC 0x00005a08
+#define GRCMBOX_LOW_PRIO_EV_MASK 0x00005a0c
+/* 0x5a10 --> 0x5c00 */
+
+/* Flow Through queues */
+#define FTQ_RESET 0x00005c00
+/* 0x5c04 --> 0x5c10 unused */
+#define FTQ_DMA_NORM_READ_CTL 0x00005c10
+#define FTQ_DMA_NORM_READ_FULL_CNT 0x00005c14
+#define FTQ_DMA_NORM_READ_FIFO_ENQDEQ 0x00005c18
+#define FTQ_DMA_NORM_READ_WRITE_PEEK 0x00005c1c
+#define FTQ_DMA_HIGH_READ_CTL 0x00005c20
+#define FTQ_DMA_HIGH_READ_FULL_CNT 0x00005c24
+#define FTQ_DMA_HIGH_READ_FIFO_ENQDEQ 0x00005c28
+#define FTQ_DMA_HIGH_READ_WRITE_PEEK 0x00005c2c
+#define FTQ_DMA_COMP_DISC_CTL 0x00005c30
+#define FTQ_DMA_COMP_DISC_FULL_CNT 0x00005c34
+#define FTQ_DMA_COMP_DISC_FIFO_ENQDEQ 0x00005c38
+#define FTQ_DMA_COMP_DISC_WRITE_PEEK 0x00005c3c
+#define FTQ_SEND_BD_COMP_CTL 0x00005c40
+#define FTQ_SEND_BD_COMP_FULL_CNT 0x00005c44
+#define FTQ_SEND_BD_COMP_FIFO_ENQDEQ 0x00005c48
+#define FTQ_SEND_BD_COMP_WRITE_PEEK 0x00005c4c
+#define FTQ_SEND_DATA_INIT_CTL 0x00005c50
+#define FTQ_SEND_DATA_INIT_FULL_CNT 0x00005c54
+#define FTQ_SEND_DATA_INIT_FIFO_ENQDEQ 0x00005c58
+#define FTQ_SEND_DATA_INIT_WRITE_PEEK 0x00005c5c
+#define FTQ_DMA_NORM_WRITE_CTL 0x00005c60
+#define FTQ_DMA_NORM_WRITE_FULL_CNT 0x00005c64
+#define FTQ_DMA_NORM_WRITE_FIFO_ENQDEQ 0x00005c68
+#define FTQ_DMA_NORM_WRITE_WRITE_PEEK 0x00005c6c
+#define FTQ_DMA_HIGH_WRITE_CTL 0x00005c70
+#define FTQ_DMA_HIGH_WRITE_FULL_CNT 0x00005c74
+#define FTQ_DMA_HIGH_WRITE_FIFO_ENQDEQ 0x00005c78
+#define FTQ_DMA_HIGH_WRITE_WRITE_PEEK 0x00005c7c
+#define FTQ_SWTYPE1_CTL 0x00005c80
+#define FTQ_SWTYPE1_FULL_CNT 0x00005c84
+#define FTQ_SWTYPE1_FIFO_ENQDEQ 0x00005c88
+#define FTQ_SWTYPE1_WRITE_PEEK 0x00005c8c
+#define FTQ_SEND_DATA_COMP_CTL 0x00005c90
+#define FTQ_SEND_DATA_COMP_FULL_CNT 0x00005c94
+#define FTQ_SEND_DATA_COMP_FIFO_ENQDEQ 0x00005c98
+#define FTQ_SEND_DATA_COMP_WRITE_PEEK 0x00005c9c
+#define FTQ_HOST_COAL_CTL 0x00005ca0
+#define FTQ_HOST_COAL_FULL_CNT 0x00005ca4
+#define FTQ_HOST_COAL_FIFO_ENQDEQ 0x00005ca8
+#define FTQ_HOST_COAL_WRITE_PEEK 0x00005cac
+#define FTQ_MAC_TX_CTL 0x00005cb0
+#define FTQ_MAC_TX_FULL_CNT 0x00005cb4
+#define FTQ_MAC_TX_FIFO_ENQDEQ 0x00005cb8
+#define FTQ_MAC_TX_WRITE_PEEK 0x00005cbc
+#define FTQ_MB_FREE_CTL 0x00005cc0
+#define FTQ_MB_FREE_FULL_CNT 0x00005cc4
+#define FTQ_MB_FREE_FIFO_ENQDEQ 0x00005cc8
+#define FTQ_MB_FREE_WRITE_PEEK 0x00005ccc
+#define FTQ_RCVBD_COMP_CTL 0x00005cd0
+#define FTQ_RCVBD_COMP_FULL_CNT 0x00005cd4
+#define FTQ_RCVBD_COMP_FIFO_ENQDEQ 0x00005cd8
+#define FTQ_RCVBD_COMP_WRITE_PEEK 0x00005cdc
+#define FTQ_RCVLST_PLMT_CTL 0x00005ce0
+#define FTQ_RCVLST_PLMT_FULL_CNT 0x00005ce4
+#define FTQ_RCVLST_PLMT_FIFO_ENQDEQ 0x00005ce8
+#define FTQ_RCVLST_PLMT_WRITE_PEEK 0x00005cec
+#define FTQ_RCVDATA_INI_CTL 0x00005cf0
+#define FTQ_RCVDATA_INI_FULL_CNT 0x00005cf4
+#define FTQ_RCVDATA_INI_FIFO_ENQDEQ 0x00005cf8
+#define FTQ_RCVDATA_INI_WRITE_PEEK 0x00005cfc
+#define FTQ_RCVDATA_COMP_CTL 0x00005d00
+#define FTQ_RCVDATA_COMP_FULL_CNT 0x00005d04
+#define FTQ_RCVDATA_COMP_FIFO_ENQDEQ 0x00005d08
+#define FTQ_RCVDATA_COMP_WRITE_PEEK 0x00005d0c
+#define FTQ_SWTYPE2_CTL 0x00005d10
+#define FTQ_SWTYPE2_FULL_CNT 0x00005d14
+#define FTQ_SWTYPE2_FIFO_ENQDEQ 0x00005d18
+#define FTQ_SWTYPE2_WRITE_PEEK 0x00005d1c
+/* 0x5d20 --> 0x6000 unused */
+
+/* Message signaled interrupt registers */
+#define MSGINT_MODE 0x00006000
+#define MSGINT_MODE_RESET 0x00000001
+#define MSGINT_MODE_ENABLE 0x00000002
+#define MSGINT_MODE_ONE_SHOT_DISABLE 0x00000020
+#define MSGINT_MODE_MULTIVEC_EN 0x00000080
+#define MSGINT_STATUS 0x00006004
+#define MSGINT_STATUS_MSI_REQ 0x00000001
+#define MSGINT_FIFO 0x00006008
+/* 0x600c --> 0x6400 unused */
+
+/* DMA completion registers */
+#define DMAC_MODE 0x00006400
+#define DMAC_MODE_RESET 0x00000001
+#define DMAC_MODE_ENABLE 0x00000002
+/* 0x6404 --> 0x6800 unused */
+
+/* GRC registers */
+#define GRC_MODE 0x00006800
+#define GRC_MODE_UPD_ON_COAL 0x00000001
+#define GRC_MODE_BSWAP_NONFRM_DATA 0x00000002
+#define GRC_MODE_WSWAP_NONFRM_DATA 0x00000004
+#define GRC_MODE_BSWAP_DATA 0x00000010
+#define GRC_MODE_WSWAP_DATA 0x00000020
+#define GRC_MODE_BYTE_SWAP_B2HRX_DATA 0x00000040
+#define GRC_MODE_WORD_SWAP_B2HRX_DATA 0x00000080
+#define GRC_MODE_SPLITHDR 0x00000100
+#define GRC_MODE_NOFRM_CRACKING 0x00000200
+#define GRC_MODE_INCL_CRC 0x00000400
+#define GRC_MODE_ALLOW_BAD_FRMS 0x00000800
+#define GRC_MODE_NOIRQ_ON_SENDS 0x00002000
+#define GRC_MODE_NOIRQ_ON_RCV 0x00004000
+#define GRC_MODE_FORCE_PCI32BIT 0x00008000
+#define GRC_MODE_B2HRX_ENABLE 0x00008000
+#define GRC_MODE_HOST_STACKUP 0x00010000
+#define GRC_MODE_HOST_SENDBDS 0x00020000
+#define GRC_MODE_HTX2B_ENABLE 0x00040000
+#define GRC_MODE_NO_TX_PHDR_CSUM 0x00100000
+#define GRC_MODE_NVRAM_WR_ENABLE 0x00200000
+#define GRC_MODE_PCIE_TL_SEL 0x00000000
+#define GRC_MODE_PCIE_PL_SEL 0x00400000
+#define GRC_MODE_NO_RX_PHDR_CSUM 0x00800000
+#define GRC_MODE_IRQ_ON_TX_CPU_ATTN 0x01000000
+#define GRC_MODE_IRQ_ON_RX_CPU_ATTN 0x02000000
+#define GRC_MODE_IRQ_ON_MAC_ATTN 0x04000000
+#define GRC_MODE_IRQ_ON_DMA_ATTN 0x08000000
+#define GRC_MODE_IRQ_ON_FLOW_ATTN 0x10000000
+#define GRC_MODE_4X_NIC_SEND_RINGS 0x20000000
+#define GRC_MODE_PCIE_DL_SEL 0x20000000
+#define GRC_MODE_MCAST_FRM_ENABLE 0x40000000
+#define GRC_MODE_PCIE_HI_1K_EN 0x80000000
+#define GRC_MODE_PCIE_PORT_MASK (GRC_MODE_PCIE_TL_SEL | \
+ GRC_MODE_PCIE_PL_SEL | \
+ GRC_MODE_PCIE_DL_SEL | \
+ GRC_MODE_PCIE_HI_1K_EN)
+#define GRC_MISC_CFG 0x00006804
+#define GRC_MISC_CFG_CORECLK_RESET 0x00000001
+#define GRC_MISC_CFG_PRESCALAR_MASK 0x000000fe
+#define GRC_MISC_CFG_PRESCALAR_SHIFT 1
+#define GRC_MISC_CFG_BOARD_ID_MASK 0x0001e000
+#define GRC_MISC_CFG_BOARD_ID_5700 0x0001e000
+#define GRC_MISC_CFG_BOARD_ID_5701 0x00000000
+#define GRC_MISC_CFG_BOARD_ID_5702FE 0x00004000
+#define GRC_MISC_CFG_BOARD_ID_5703 0x00000000
+#define GRC_MISC_CFG_BOARD_ID_5703S 0x00002000
+#define GRC_MISC_CFG_BOARD_ID_5704 0x00000000
+#define GRC_MISC_CFG_BOARD_ID_5704CIOBE 0x00004000
+#define GRC_MISC_CFG_BOARD_ID_5704_A2 0x00008000
+#define GRC_MISC_CFG_BOARD_ID_5788 0x00010000
+#define GRC_MISC_CFG_BOARD_ID_5788M 0x00018000
+#define GRC_MISC_CFG_BOARD_ID_AC91002A1 0x00018000
+#define GRC_MISC_CFG_EPHY_IDDQ 0x00200000
+#define GRC_MISC_CFG_KEEP_GPHY_POWER 0x04000000
+#define GRC_LOCAL_CTRL 0x00006808
+#define GRC_LCLCTRL_INT_ACTIVE 0x00000001
+#define GRC_LCLCTRL_CLEARINT 0x00000002
+#define GRC_LCLCTRL_SETINT 0x00000004
+#define GRC_LCLCTRL_INT_ON_ATTN 0x00000008
+#define GRC_LCLCTRL_GPIO_UART_SEL 0x00000010 /* 5755 only */
+#define GRC_LCLCTRL_USE_SIG_DETECT 0x00000010 /* 5714/5780 only */
+#define GRC_LCLCTRL_USE_EXT_SIG_DETECT 0x00000020 /* 5714/5780 only */
+#define GRC_LCLCTRL_GPIO_INPUT3 0x00000020
+#define GRC_LCLCTRL_GPIO_OE3 0x00000040
+#define GRC_LCLCTRL_GPIO_OUTPUT3 0x00000080
+#define GRC_LCLCTRL_GPIO_INPUT0 0x00000100
+#define GRC_LCLCTRL_GPIO_INPUT1 0x00000200
+#define GRC_LCLCTRL_GPIO_INPUT2 0x00000400
+#define GRC_LCLCTRL_GPIO_OE0 0x00000800
+#define GRC_LCLCTRL_GPIO_OE1 0x00001000
+#define GRC_LCLCTRL_GPIO_OE2 0x00002000
+#define GRC_LCLCTRL_GPIO_OUTPUT0 0x00004000
+#define GRC_LCLCTRL_GPIO_OUTPUT1 0x00008000
+#define GRC_LCLCTRL_GPIO_OUTPUT2 0x00010000
+#define GRC_LCLCTRL_EXTMEM_ENABLE 0x00020000
+#define GRC_LCLCTRL_MEMSZ_MASK 0x001c0000
+#define GRC_LCLCTRL_MEMSZ_256K 0x00000000
+#define GRC_LCLCTRL_MEMSZ_512K 0x00040000
+#define GRC_LCLCTRL_MEMSZ_1M 0x00080000
+#define GRC_LCLCTRL_MEMSZ_2M 0x000c0000
+#define GRC_LCLCTRL_MEMSZ_4M 0x00100000
+#define GRC_LCLCTRL_MEMSZ_8M 0x00140000
+#define GRC_LCLCTRL_MEMSZ_16M 0x00180000
+#define GRC_LCLCTRL_BANK_SELECT 0x00200000
+#define GRC_LCLCTRL_SSRAM_TYPE 0x00400000
+#define GRC_LCLCTRL_AUTO_SEEPROM 0x01000000
+#define GRC_TIMER 0x0000680c
+#define GRC_RX_CPU_EVENT 0x00006810
+#define GRC_RX_CPU_DRIVER_EVENT 0x00004000
+#define GRC_RX_TIMER_REF 0x00006814
+#define GRC_RX_CPU_SEM 0x00006818
+#define GRC_REMOTE_RX_CPU_ATTN 0x0000681c
+#define GRC_TX_CPU_EVENT 0x00006820
+#define GRC_TX_TIMER_REF 0x00006824
+#define GRC_TX_CPU_SEM 0x00006828
+#define GRC_REMOTE_TX_CPU_ATTN 0x0000682c
+#define GRC_MEM_POWER_UP 0x00006830 /* 64-bit */
+#define GRC_EEPROM_ADDR 0x00006838
+#define EEPROM_ADDR_WRITE 0x00000000
+#define EEPROM_ADDR_READ 0x80000000
+#define EEPROM_ADDR_COMPLETE 0x40000000
+#define EEPROM_ADDR_FSM_RESET 0x20000000
+#define EEPROM_ADDR_DEVID_MASK 0x1c000000
+#define EEPROM_ADDR_DEVID_SHIFT 26
+#define EEPROM_ADDR_START 0x02000000
+#define EEPROM_ADDR_CLKPERD_SHIFT 16
+#define EEPROM_ADDR_ADDR_MASK 0x0000ffff
+#define EEPROM_ADDR_ADDR_SHIFT 0
+#define EEPROM_DEFAULT_CLOCK_PERIOD 0x60
+#define EEPROM_CHIP_SIZE (64 * 1024)
+#define GRC_EEPROM_DATA 0x0000683c
+#define GRC_EEPROM_CTRL 0x00006840
+#define GRC_MDI_CTRL 0x00006844
+#define GRC_SEEPROM_DELAY 0x00006848
+/* 0x684c --> 0x6890 unused */
+#define GRC_VCPU_EXT_CTRL 0x00006890
+#define GRC_VCPU_EXT_CTRL_HALT_CPU 0x00400000
+#define GRC_VCPU_EXT_CTRL_DISABLE_WOL 0x20000000
+#define GRC_FASTBOOT_PC 0x00006894 /* 5752, 5755, 5787 */
+
+/* 0x6c00 --> 0x7000 unused */
+
+/* NVRAM Control registers */
+#define NVRAM_CMD 0x00007000
+#define NVRAM_CMD_RESET 0x00000001
+#define NVRAM_CMD_DONE 0x00000008
+#define NVRAM_CMD_GO 0x00000010
+#define NVRAM_CMD_WR 0x00000020
+#define NVRAM_CMD_RD 0x00000000
+#define NVRAM_CMD_ERASE 0x00000040
+#define NVRAM_CMD_FIRST 0x00000080
+#define NVRAM_CMD_LAST 0x00000100
+#define NVRAM_CMD_WREN 0x00010000
+#define NVRAM_CMD_WRDI 0x00020000
+#define NVRAM_STAT 0x00007004
+#define NVRAM_WRDATA 0x00007008
+#define NVRAM_ADDR 0x0000700c
+#define NVRAM_ADDR_MSK 0x00ffffff
+#define NVRAM_RDDATA 0x00007010
+#define NVRAM_CFG1 0x00007014
+#define NVRAM_CFG1_FLASHIF_ENAB 0x00000001
+#define NVRAM_CFG1_BUFFERED_MODE 0x00000002
+#define NVRAM_CFG1_PASS_THRU 0x00000004
+#define NVRAM_CFG1_STATUS_BITS 0x00000070
+#define NVRAM_CFG1_BIT_BANG 0x00000008
+#define NVRAM_CFG1_FLASH_SIZE 0x02000000
+#define NVRAM_CFG1_COMPAT_BYPASS 0x80000000
+#define NVRAM_CFG1_VENDOR_MASK 0x03000003
+#define FLASH_VENDOR_ATMEL_EEPROM 0x02000000
+#define FLASH_VENDOR_ATMEL_FLASH_BUFFERED 0x02000003
+#define FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED 0x00000003
+#define FLASH_VENDOR_ST 0x03000001
+#define FLASH_VENDOR_SAIFUN 0x01000003
+#define FLASH_VENDOR_SST_SMALL 0x00000001
+#define FLASH_VENDOR_SST_LARGE 0x02000001
+#define NVRAM_CFG1_5752VENDOR_MASK 0x03c00003
+#define FLASH_5752VENDOR_ATMEL_EEPROM_64KHZ 0x00000000
+#define FLASH_5752VENDOR_ATMEL_EEPROM_376KHZ 0x02000000
+#define FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED 0x02000003
+#define FLASH_5752VENDOR_ST_M45PE10 0x02400000
+#define FLASH_5752VENDOR_ST_M45PE20 0x02400002
+#define FLASH_5752VENDOR_ST_M45PE40 0x02400001
+#define FLASH_5755VENDOR_ATMEL_FLASH_1 0x03400001
+#define FLASH_5755VENDOR_ATMEL_FLASH_2 0x03400002
+#define FLASH_5755VENDOR_ATMEL_FLASH_3 0x03400000
+#define FLASH_5755VENDOR_ATMEL_FLASH_4 0x00000003
+#define FLASH_5755VENDOR_ATMEL_FLASH_5 0x02000003
+#define FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ 0x03c00003
+#define FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ 0x03c00002
+#define FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ 0x03000003
+#define FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ 0x03000002
+#define FLASH_5787VENDOR_MICRO_EEPROM_64KHZ 0x03000000
+#define FLASH_5787VENDOR_MICRO_EEPROM_376KHZ 0x02000000
+#define FLASH_5761VENDOR_ATMEL_MDB021D 0x00800003
+#define FLASH_5761VENDOR_ATMEL_MDB041D 0x00800000
+#define FLASH_5761VENDOR_ATMEL_MDB081D 0x00800002
+#define FLASH_5761VENDOR_ATMEL_MDB161D 0x00800001
+#define FLASH_5761VENDOR_ATMEL_ADB021D 0x00000003
+#define FLASH_5761VENDOR_ATMEL_ADB041D 0x00000000
+#define FLASH_5761VENDOR_ATMEL_ADB081D 0x00000002
+#define FLASH_5761VENDOR_ATMEL_ADB161D 0x00000001
+#define FLASH_5761VENDOR_ST_M_M45PE20 0x02800001
+#define FLASH_5761VENDOR_ST_M_M45PE40 0x02800000
+#define FLASH_5761VENDOR_ST_M_M45PE80 0x02800002
+#define FLASH_5761VENDOR_ST_M_M45PE16 0x02800003
+#define FLASH_5761VENDOR_ST_A_M45PE20 0x02000001
+#define FLASH_5761VENDOR_ST_A_M45PE40 0x02000000
+#define FLASH_5761VENDOR_ST_A_M45PE80 0x02000002
+#define FLASH_5761VENDOR_ST_A_M45PE16 0x02000003
+#define FLASH_57780VENDOR_ATMEL_AT45DB011D 0x00400000
+#define FLASH_57780VENDOR_ATMEL_AT45DB011B 0x03400000
+#define FLASH_57780VENDOR_ATMEL_AT45DB021D 0x00400002
+#define FLASH_57780VENDOR_ATMEL_AT45DB021B 0x03400002
+#define FLASH_57780VENDOR_ATMEL_AT45DB041D 0x00400001
+#define FLASH_57780VENDOR_ATMEL_AT45DB041B 0x03400001
+#define FLASH_5717VENDOR_ATMEL_EEPROM 0x02000001
+#define FLASH_5717VENDOR_MICRO_EEPROM 0x02000003
+#define FLASH_5717VENDOR_ATMEL_MDB011D 0x01000001
+#define FLASH_5717VENDOR_ATMEL_MDB021D 0x01000003
+#define FLASH_5717VENDOR_ST_M_M25PE10 0x02000000
+#define FLASH_5717VENDOR_ST_M_M25PE20 0x02000002
+#define FLASH_5717VENDOR_ST_M_M45PE10 0x00000001
+#define FLASH_5717VENDOR_ST_M_M45PE20 0x00000003
+#define FLASH_5717VENDOR_ATMEL_ADB011B 0x01400000
+#define FLASH_5717VENDOR_ATMEL_ADB021B 0x01400002
+#define FLASH_5717VENDOR_ATMEL_ADB011D 0x01400001
+#define FLASH_5717VENDOR_ATMEL_ADB021D 0x01400003
+#define FLASH_5717VENDOR_ST_A_M25PE10 0x02400000
+#define FLASH_5717VENDOR_ST_A_M25PE20 0x02400002
+#define FLASH_5717VENDOR_ST_A_M45PE10 0x02400001
+#define FLASH_5717VENDOR_ST_A_M45PE20 0x02400003
+#define FLASH_5717VENDOR_ATMEL_45USPT 0x03400000
+#define FLASH_5717VENDOR_ST_25USPT 0x03400002
+#define FLASH_5717VENDOR_ST_45USPT 0x03400001
+#define FLASH_5720_EEPROM_HD 0x00000001
+#define FLASH_5720_EEPROM_LD 0x00000003
+#define FLASH_5720VENDOR_M_ATMEL_DB011D 0x01000000
+#define FLASH_5720VENDOR_M_ATMEL_DB021D 0x01000002
+#define FLASH_5720VENDOR_M_ATMEL_DB041D 0x01000001
+#define FLASH_5720VENDOR_M_ATMEL_DB081D 0x01000003
+#define FLASH_5720VENDOR_M_ST_M25PE10 0x02000000
+#define FLASH_5720VENDOR_M_ST_M25PE20 0x02000002
+#define FLASH_5720VENDOR_M_ST_M25PE40 0x02000001
+#define FLASH_5720VENDOR_M_ST_M25PE80 0x02000003
+#define FLASH_5720VENDOR_M_ST_M45PE10 0x03000000
+#define FLASH_5720VENDOR_M_ST_M45PE20 0x03000002
+#define FLASH_5720VENDOR_M_ST_M45PE40 0x03000001
+#define FLASH_5720VENDOR_M_ST_M45PE80 0x03000003
+#define FLASH_5720VENDOR_A_ATMEL_DB011B 0x01800000
+#define FLASH_5720VENDOR_A_ATMEL_DB021B 0x01800002
+#define FLASH_5720VENDOR_A_ATMEL_DB041B 0x01800001
+#define FLASH_5720VENDOR_A_ATMEL_DB011D 0x01c00000
+#define FLASH_5720VENDOR_A_ATMEL_DB021D 0x01c00002
+#define FLASH_5720VENDOR_A_ATMEL_DB041D 0x01c00001
+#define FLASH_5720VENDOR_A_ATMEL_DB081D 0x01c00003
+#define FLASH_5720VENDOR_A_ST_M25PE10 0x02800000
+#define FLASH_5720VENDOR_A_ST_M25PE20 0x02800002
+#define FLASH_5720VENDOR_A_ST_M25PE40 0x02800001
+#define FLASH_5720VENDOR_A_ST_M25PE80 0x02800003
+#define FLASH_5720VENDOR_A_ST_M45PE10 0x02c00000
+#define FLASH_5720VENDOR_A_ST_M45PE20 0x02c00002
+#define FLASH_5720VENDOR_A_ST_M45PE40 0x02c00001
+#define FLASH_5720VENDOR_A_ST_M45PE80 0x02c00003
+#define FLASH_5720VENDOR_ATMEL_45USPT 0x03c00000
+#define FLASH_5720VENDOR_ST_25USPT 0x03c00002
+#define FLASH_5720VENDOR_ST_45USPT 0x03c00001
+#define NVRAM_CFG1_5752PAGE_SIZE_MASK 0x70000000
+#define FLASH_5752PAGE_SIZE_256 0x00000000
+#define FLASH_5752PAGE_SIZE_512 0x10000000
+#define FLASH_5752PAGE_SIZE_1K 0x20000000
+#define FLASH_5752PAGE_SIZE_2K 0x30000000
+#define FLASH_5752PAGE_SIZE_4K 0x40000000
+#define FLASH_5752PAGE_SIZE_264 0x50000000
+#define FLASH_5752PAGE_SIZE_528 0x60000000
+#define NVRAM_CFG2 0x00007018
+#define NVRAM_CFG3 0x0000701c
+#define NVRAM_SWARB 0x00007020
+#define SWARB_REQ_SET0 0x00000001
+#define SWARB_REQ_SET1 0x00000002
+#define SWARB_REQ_SET2 0x00000004
+#define SWARB_REQ_SET3 0x00000008
+#define SWARB_REQ_CLR0 0x00000010
+#define SWARB_REQ_CLR1 0x00000020
+#define SWARB_REQ_CLR2 0x00000040
+#define SWARB_REQ_CLR3 0x00000080
+#define SWARB_GNT0 0x00000100
+#define SWARB_GNT1 0x00000200
+#define SWARB_GNT2 0x00000400
+#define SWARB_GNT3 0x00000800
+#define SWARB_REQ0 0x00001000
+#define SWARB_REQ1 0x00002000
+#define SWARB_REQ2 0x00004000
+#define SWARB_REQ3 0x00008000
+#define NVRAM_ACCESS 0x00007024
+#define ACCESS_ENABLE 0x00000001
+#define ACCESS_WR_ENABLE 0x00000002
+#define NVRAM_WRITE1 0x00007028
+/* 0x702c unused */
+
+#define NVRAM_ADDR_LOCKOUT 0x00007030
+/* 0x7034 --> 0x7500 unused */
+
+#define OTP_MODE 0x00007500
+#define OTP_MODE_OTP_THRU_GRC 0x00000001
+#define OTP_CTRL 0x00007504
+#define OTP_CTRL_OTP_PROG_ENABLE 0x00200000
+#define OTP_CTRL_OTP_CMD_READ 0x00000000
+#define OTP_CTRL_OTP_CMD_INIT 0x00000008
+#define OTP_CTRL_OTP_CMD_START 0x00000001
+#define OTP_STATUS 0x00007508
+#define OTP_STATUS_CMD_DONE 0x00000001
+#define OTP_ADDRESS 0x0000750c
+#define OTP_ADDRESS_MAGIC1 0x000000a0
+#define OTP_ADDRESS_MAGIC2 0x00000080
+/* 0x7510 unused */
+
+#define OTP_READ_DATA 0x00007514
+/* 0x7518 --> 0x7c04 unused */
+
+#define PCIE_TRANSACTION_CFG 0x00007c04
+#define PCIE_TRANS_CFG_1SHOT_MSI 0x20000000
+#define PCIE_TRANS_CFG_LOM 0x00000020
+/* 0x7c08 --> 0x7d28 unused */
+
+#define PCIE_PWR_MGMT_THRESH 0x00007d28
+#define PCIE_PWR_MGMT_L1_THRESH_MSK 0x0000ff00
+#define PCIE_PWR_MGMT_L1_THRESH_4MS 0x0000ff00
+#define PCIE_PWR_MGMT_EXT_ASPM_TMR_EN 0x01000000
+/* 0x7d2c --> 0x7d54 unused */
+
+#define TG3_PCIE_LNKCTL 0x00007d54
+#define TG3_PCIE_LNKCTL_L1_PLL_PD_EN 0x00000008
+#define TG3_PCIE_LNKCTL_L1_PLL_PD_DIS 0x00000080
+/* 0x7d58 --> 0x7e70 unused */
+
+#define TG3_PCIE_PHY_TSTCTL 0x00007e2c
+#define TG3_PCIE_PHY_TSTCTL_PCIE10 0x00000040
+#define TG3_PCIE_PHY_TSTCTL_PSCRAM 0x00000020
+
+#define TG3_PCIE_EIDLE_DELAY 0x00007e70
+#define TG3_PCIE_EIDLE_DELAY_MASK 0x0000001f
+#define TG3_PCIE_EIDLE_DELAY_13_CLKS 0x0000000c
+/* 0x7e74 --> 0x8000 unused */
+
+
+/* Alternate PCIE definitions */
+#define TG3_PCIE_TLDLPL_PORT 0x00007c00
+#define TG3_PCIE_DL_LO_FTSMAX 0x0000000c
+#define TG3_PCIE_DL_LO_FTSMAX_MSK 0x000000ff
+#define TG3_PCIE_DL_LO_FTSMAX_VAL 0x0000002c
+#define TG3_PCIE_PL_LO_PHYCTL1 0x00000004
+#define TG3_PCIE_PL_LO_PHYCTL1_L1PLLPD_EN 0x00001000
+#define TG3_PCIE_PL_LO_PHYCTL5 0x00000014
+#define TG3_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ 0x80000000
+
+#define TG3_REG_BLK_SIZE 0x00008000
+
+/* OTP bit definitions */
+#define TG3_OTP_AGCTGT_MASK 0x000000e0
+#define TG3_OTP_AGCTGT_SHIFT 1
+#define TG3_OTP_HPFFLTR_MASK 0x00000300
+#define TG3_OTP_HPFFLTR_SHIFT 1
+#define TG3_OTP_HPFOVER_MASK 0x00000400
+#define TG3_OTP_HPFOVER_SHIFT 1
+#define TG3_OTP_LPFDIS_MASK 0x00000800
+#define TG3_OTP_LPFDIS_SHIFT 11
+#define TG3_OTP_VDAC_MASK 0xff000000
+#define TG3_OTP_VDAC_SHIFT 24
+#define TG3_OTP_10BTAMP_MASK 0x0000f000
+#define TG3_OTP_10BTAMP_SHIFT 8
+#define TG3_OTP_ROFF_MASK 0x00e00000
+#define TG3_OTP_ROFF_SHIFT 11
+#define TG3_OTP_RCOFF_MASK 0x001c0000
+#define TG3_OTP_RCOFF_SHIFT 16
+
+#define TG3_OTP_DEFAULT 0x286c1640
+
+
+/* Hardware Legacy NVRAM layout */
+#define TG3_NVM_VPD_OFF 0x100
+#define TG3_NVM_VPD_LEN 256
+
+/* Hardware Selfboot NVRAM layout */
+#define TG3_NVM_HWSB_CFG1 0x00000004
+#define TG3_NVM_HWSB_CFG1_MAJMSK 0xf8000000
+#define TG3_NVM_HWSB_CFG1_MAJSFT 27
+#define TG3_NVM_HWSB_CFG1_MINMSK 0x07c00000
+#define TG3_NVM_HWSB_CFG1_MINSFT 22
+
+#define TG3_EEPROM_MAGIC 0x669955aa
+#define TG3_EEPROM_MAGIC_FW 0xa5000000
+#define TG3_EEPROM_MAGIC_FW_MSK 0xff000000
+#define TG3_EEPROM_SB_FORMAT_MASK 0x00e00000
+#define TG3_EEPROM_SB_FORMAT_1 0x00200000
+#define TG3_EEPROM_SB_REVISION_MASK 0x001f0000
+#define TG3_EEPROM_SB_REVISION_0 0x00000000
+#define TG3_EEPROM_SB_REVISION_2 0x00020000
+#define TG3_EEPROM_SB_REVISION_3 0x00030000
+#define TG3_EEPROM_SB_REVISION_4 0x00040000
+#define TG3_EEPROM_SB_REVISION_5 0x00050000
+#define TG3_EEPROM_SB_REVISION_6 0x00060000
+#define TG3_EEPROM_MAGIC_HW 0xabcd
+#define TG3_EEPROM_MAGIC_HW_MSK 0xffff
+
+#define TG3_NVM_DIR_START 0x18
+#define TG3_NVM_DIR_END 0x78
+#define TG3_NVM_DIRENT_SIZE 0xc
+#define TG3_NVM_DIRTYPE_SHIFT 24
+#define TG3_NVM_DIRTYPE_LENMSK 0x003fffff
+#define TG3_NVM_DIRTYPE_ASFINI 1
+#define TG3_NVM_DIRTYPE_EXTVPD 20
+#define TG3_NVM_PTREV_BCVER 0x94
+#define TG3_NVM_BCVER_MAJMSK 0x0000ff00
+#define TG3_NVM_BCVER_MAJSFT 8
+#define TG3_NVM_BCVER_MINMSK 0x000000ff
+
+#define TG3_EEPROM_SB_F1R0_EDH_OFF 0x10
+#define TG3_EEPROM_SB_F1R2_EDH_OFF 0x14
+#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10
+#define TG3_EEPROM_SB_F1R3_EDH_OFF 0x18
+#define TG3_EEPROM_SB_F1R4_EDH_OFF 0x1c
+#define TG3_EEPROM_SB_F1R5_EDH_OFF 0x20
+#define TG3_EEPROM_SB_F1R6_EDH_OFF 0x4c
+#define TG3_EEPROM_SB_EDH_MAJ_MASK 0x00000700
+#define TG3_EEPROM_SB_EDH_MAJ_SHFT 8
+#define TG3_EEPROM_SB_EDH_MIN_MASK 0x000000ff
+#define TG3_EEPROM_SB_EDH_BLD_MASK 0x0000f800
+#define TG3_EEPROM_SB_EDH_BLD_SHFT 11
+
+
+/* 32K Window into NIC internal memory */
+#define NIC_SRAM_WIN_BASE 0x00008000
+
+/* Offsets into first 32k of NIC internal memory. */
+#define NIC_SRAM_PAGE_ZERO 0x00000000
+#define NIC_SRAM_SEND_RCB 0x00000100 /* 16 * TG3_BDINFO_... */
+#define NIC_SRAM_RCV_RET_RCB 0x00000200 /* 16 * TG3_BDINFO_... */
+#define NIC_SRAM_STATS_BLK 0x00000300
+#define NIC_SRAM_STATUS_BLK 0x00000b00
+
+#define NIC_SRAM_FIRMWARE_MBOX 0x00000b50
+#define NIC_SRAM_FIRMWARE_MBOX_MAGIC1 0x4B657654
+#define NIC_SRAM_FIRMWARE_MBOX_MAGIC2 0x4861764b /* !dma on linkchg */
+
+#define NIC_SRAM_DATA_SIG 0x00000b54
+#define NIC_SRAM_DATA_SIG_MAGIC 0x4b657654 /* ascii for 'KevT' */
+
+#define NIC_SRAM_DATA_CFG 0x00000b58
+#define NIC_SRAM_DATA_CFG_LED_MODE_MASK 0x0000000c
+#define NIC_SRAM_DATA_CFG_LED_MODE_MAC 0x00000000
+#define NIC_SRAM_DATA_CFG_LED_MODE_PHY_1 0x00000004
+#define NIC_SRAM_DATA_CFG_LED_MODE_PHY_2 0x00000008
+#define NIC_SRAM_DATA_CFG_PHY_TYPE_MASK 0x00000030
+#define NIC_SRAM_DATA_CFG_PHY_TYPE_UNKNOWN 0x00000000
+#define NIC_SRAM_DATA_CFG_PHY_TYPE_COPPER 0x00000010
+#define NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER 0x00000020
+#define NIC_SRAM_DATA_CFG_WOL_ENABLE 0x00000040
+#define NIC_SRAM_DATA_CFG_ASF_ENABLE 0x00000080
+#define NIC_SRAM_DATA_CFG_EEPROM_WP 0x00000100
+#define NIC_SRAM_DATA_CFG_MINI_PCI 0x00001000
+#define NIC_SRAM_DATA_CFG_FIBER_WOL 0x00004000
+#define NIC_SRAM_DATA_CFG_NO_GPIO2 0x00100000
+#define NIC_SRAM_DATA_CFG_APE_ENABLE 0x00200000
+
+#define NIC_SRAM_DATA_VER 0x00000b5c
+#define NIC_SRAM_DATA_VER_SHIFT 16
+
+#define NIC_SRAM_DATA_PHY_ID 0x00000b74
+#define NIC_SRAM_DATA_PHY_ID1_MASK 0xffff0000
+#define NIC_SRAM_DATA_PHY_ID2_MASK 0x0000ffff
+
+#define NIC_SRAM_FW_CMD_MBOX 0x00000b78
+#define FWCMD_NICDRV_ALIVE 0x00000001
+#define FWCMD_NICDRV_PAUSE_FW 0x00000002
+#define FWCMD_NICDRV_IPV4ADDR_CHG 0x00000003
+#define FWCMD_NICDRV_IPV6ADDR_CHG 0x00000004
+#define FWCMD_NICDRV_FIX_DMAR 0x00000005
+#define FWCMD_NICDRV_FIX_DMAW 0x00000006
+#define FWCMD_NICDRV_LINK_UPDATE 0x0000000c
+#define FWCMD_NICDRV_ALIVE2 0x0000000d
+#define FWCMD_NICDRV_ALIVE3 0x0000000e
+#define NIC_SRAM_FW_CMD_LEN_MBOX 0x00000b7c
+#define NIC_SRAM_FW_CMD_DATA_MBOX 0x00000b80
+#define NIC_SRAM_FW_ASF_STATUS_MBOX 0x00000c00
+#define NIC_SRAM_FW_DRV_STATE_MBOX 0x00000c04
+#define DRV_STATE_START 0x00000001
+#define DRV_STATE_START_DONE 0x80000001
+#define DRV_STATE_UNLOAD 0x00000002
+#define DRV_STATE_UNLOAD_DONE 0x80000002
+#define DRV_STATE_WOL 0x00000003
+#define DRV_STATE_SUSPEND 0x00000004
+
+#define NIC_SRAM_FW_RESET_TYPE_MBOX 0x00000c08
+
+#define NIC_SRAM_MAC_ADDR_HIGH_MBOX 0x00000c14
+#define NIC_SRAM_MAC_ADDR_LOW_MBOX 0x00000c18
+
+#define NIC_SRAM_WOL_MBOX 0x00000d30
+#define WOL_SIGNATURE 0x474c0000
+#define WOL_DRV_STATE_SHUTDOWN 0x00000001
+#define WOL_DRV_WOL 0x00000002
+#define WOL_SET_MAGIC_PKT 0x00000004
+
+#define NIC_SRAM_DATA_CFG_2 0x00000d38
+
+#define NIC_SRAM_DATA_CFG_2_APD_EN 0x00000400
+#define SHASTA_EXT_LED_MODE_MASK 0x00018000
+#define SHASTA_EXT_LED_LEGACY 0x00000000
+#define SHASTA_EXT_LED_SHARED 0x00008000
+#define SHASTA_EXT_LED_MAC 0x00010000
+#define SHASTA_EXT_LED_COMBO 0x00018000
+
+#define NIC_SRAM_DATA_CFG_3 0x00000d3c
+#define NIC_SRAM_ASPM_DEBOUNCE 0x00000002
+
+#define NIC_SRAM_DATA_CFG_4 0x00000d60
+#define NIC_SRAM_GMII_MODE 0x00000002
+#define NIC_SRAM_RGMII_INBAND_DISABLE 0x00000004
+#define NIC_SRAM_RGMII_EXT_IBND_RX_EN 0x00000008
+#define NIC_SRAM_RGMII_EXT_IBND_TX_EN 0x00000010
+
+#define NIC_SRAM_RX_MINI_BUFFER_DESC 0x00001000
+
+#define NIC_SRAM_DMA_DESC_POOL_BASE 0x00002000
+#define NIC_SRAM_DMA_DESC_POOL_SIZE 0x00002000
+#define NIC_SRAM_TX_BUFFER_DESC 0x00004000 /* 512 entries */
+#define NIC_SRAM_RX_BUFFER_DESC 0x00006000 /* 256 entries */
+#define NIC_SRAM_RX_JUMBO_BUFFER_DESC 0x00007000 /* 256 entries */
+#define NIC_SRAM_MBUF_POOL_BASE 0x00008000
+#define NIC_SRAM_MBUF_POOL_SIZE96 0x00018000
+#define NIC_SRAM_MBUF_POOL_SIZE64 0x00010000
+#define NIC_SRAM_MBUF_POOL_BASE5705 0x00010000
+#define NIC_SRAM_MBUF_POOL_SIZE5705 0x0000e000
+
+#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5700 128
+#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5755 64
+#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5906 32
+
+#define TG3_SRAM_RX_JMB_BDCACHE_SIZE_5700 64
+#define TG3_SRAM_RX_JMB_BDCACHE_SIZE_5717 16
+
+
+/* Currently this is fixed. */
+#define TG3_PHY_MII_ADDR 0x01
+
+
+/*** Tigon3 specific PHY MII registers. ***/
+#define TG3_BMCR_SPEED1000 0x0040
+
+#define MII_TG3_CTRL 0x09 /* 1000-baseT control register */
+#define MII_TG3_CTRL_ADV_1000_HALF 0x0100
+#define MII_TG3_CTRL_ADV_1000_FULL 0x0200
+#define MII_TG3_CTRL_AS_MASTER 0x0800
+#define MII_TG3_CTRL_ENABLE_AS_MASTER 0x1000
+
+#define MII_TG3_MMD_CTRL 0x0d /* MMD Access Control register */
+#define MII_TG3_MMD_CTRL_DATA_NOINC 0x4000
+#define MII_TG3_MMD_ADDRESS 0x0e /* MMD Address Data register */
+
+#define MII_TG3_EXT_CTRL 0x10 /* Extended control register */
+#define MII_TG3_EXT_CTRL_FIFO_ELASTIC 0x0001
+#define MII_TG3_EXT_CTRL_LNK3_LED_MODE 0x0002
+#define MII_TG3_EXT_CTRL_FORCE_LED_OFF 0x0008
+#define MII_TG3_EXT_CTRL_TBI 0x8000
+
+#define MII_TG3_EXT_STAT 0x11 /* Extended status register */
+#define MII_TG3_EXT_STAT_LPASS 0x0100
+
+#define MII_TG3_RXR_COUNTERS 0x14 /* Local/Remote Receiver Counts */
+#define MII_TG3_DSP_RW_PORT 0x15 /* DSP coefficient read/write port */
+#define MII_TG3_DSP_CONTROL 0x16 /* DSP control register */
+#define MII_TG3_DSP_ADDRESS 0x17 /* DSP address register */
+
+#define MII_TG3_DSP_TAP1 0x0001
+#define MII_TG3_DSP_TAP1_AGCTGT_DFLT 0x0007
+#define MII_TG3_DSP_TAP26 0x001a
+#define MII_TG3_DSP_TAP26_ALNOKO 0x0001
+#define MII_TG3_DSP_TAP26_RMRXSTO 0x0002
+#define MII_TG3_DSP_TAP26_OPCSINPT 0x0004
+#define MII_TG3_DSP_AADJ1CH0 0x001f
+#define MII_TG3_DSP_CH34TP2 0x4022
+#define MII_TG3_DSP_CH34TP2_HIBW01 0x017b
+#define MII_TG3_DSP_AADJ1CH3 0x601f
+#define MII_TG3_DSP_AADJ1CH3_ADCCKADJ 0x0002
+#define MII_TG3_DSP_EXP1_INT_STAT 0x0f01
+#define MII_TG3_DSP_EXP8 0x0f08
+#define MII_TG3_DSP_EXP8_REJ2MHz 0x0001
+#define MII_TG3_DSP_EXP8_AEDW 0x0200
+#define MII_TG3_DSP_EXP75 0x0f75
+#define MII_TG3_DSP_EXP96 0x0f96
+#define MII_TG3_DSP_EXP97 0x0f97
+
+#define MII_TG3_AUX_CTRL 0x18 /* auxiliary control register */
+
+#define MII_TG3_AUXCTL_SHDWSEL_AUXCTL 0x0000
+#define MII_TG3_AUXCTL_ACTL_TX_6DB 0x0400
+#define MII_TG3_AUXCTL_ACTL_SMDSP_ENA 0x0800
+#define MII_TG3_AUXCTL_ACTL_EXTPKTLEN 0x4000
+
+#define MII_TG3_AUXCTL_SHDWSEL_PWRCTL 0x0002
+#define MII_TG3_AUXCTL_PCTL_WOL_EN 0x0008
+#define MII_TG3_AUXCTL_PCTL_100TX_LPWR 0x0010
+#define MII_TG3_AUXCTL_PCTL_SPR_ISOLATE 0x0020
+#define MII_TG3_AUXCTL_PCTL_CL_AB_TXDAC 0x0040
+#define MII_TG3_AUXCTL_PCTL_VREG_11V 0x0180
+
+#define MII_TG3_AUXCTL_SHDWSEL_MISCTEST 0x0004
+
+#define MII_TG3_AUXCTL_SHDWSEL_MISC 0x0007
+#define MII_TG3_AUXCTL_MISC_WIRESPD_EN 0x0010
+#define MII_TG3_AUXCTL_MISC_FORCE_AMDIX 0x0200
+#define MII_TG3_AUXCTL_MISC_RDSEL_SHIFT 12
+#define MII_TG3_AUXCTL_MISC_WREN 0x8000
+
+
+#define MII_TG3_AUX_STAT 0x19 /* auxiliary status register */
+#define MII_TG3_AUX_STAT_LPASS 0x0004
+#define MII_TG3_AUX_STAT_SPDMASK 0x0700
+#define MII_TG3_AUX_STAT_10HALF 0x0100
+#define MII_TG3_AUX_STAT_10FULL 0x0200
+#define MII_TG3_AUX_STAT_100HALF 0x0300
+#define MII_TG3_AUX_STAT_100_4 0x0400
+#define MII_TG3_AUX_STAT_100FULL 0x0500
+#define MII_TG3_AUX_STAT_1000HALF 0x0600
+#define MII_TG3_AUX_STAT_1000FULL 0x0700
+#define MII_TG3_AUX_STAT_100 0x0008
+#define MII_TG3_AUX_STAT_FULL 0x0001
+
+#define MII_TG3_ISTAT 0x1a /* IRQ status register */
+#define MII_TG3_IMASK 0x1b /* IRQ mask register */
+
+/* ISTAT/IMASK event bits */
+#define MII_TG3_INT_LINKCHG 0x0002
+#define MII_TG3_INT_SPEEDCHG 0x0004
+#define MII_TG3_INT_DUPLEXCHG 0x0008
+#define MII_TG3_INT_ANEG_PAGE_RX 0x0400
+
+#define MII_TG3_MISC_SHDW 0x1c
+#define MII_TG3_MISC_SHDW_WREN 0x8000
+
+#define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001
+#define MII_TG3_MISC_SHDW_APD_ENABLE 0x0020
+#define MII_TG3_MISC_SHDW_APD_SEL 0x2800
+
+#define MII_TG3_MISC_SHDW_SCR5_C125OE 0x0001
+#define MII_TG3_MISC_SHDW_SCR5_DLLAPD 0x0002
+#define MII_TG3_MISC_SHDW_SCR5_SDTL 0x0004
+#define MII_TG3_MISC_SHDW_SCR5_DLPTLM 0x0008
+#define MII_TG3_MISC_SHDW_SCR5_LPED 0x0010
+#define MII_TG3_MISC_SHDW_SCR5_SEL 0x1400
+
+#define MII_TG3_TEST1 0x1e
+#define MII_TG3_TEST1_TRIM_EN 0x0010
+#define MII_TG3_TEST1_CRC_EN 0x8000
+
+/* Clause 45 expansion registers */
+#define TG3_CL45_D7_EEERES_STAT 0x803e
+#define TG3_CL45_D7_EEERES_STAT_LP_100TX 0x0002
+#define TG3_CL45_D7_EEERES_STAT_LP_1000T 0x0004
+
+
+/* Fast Ethernet Tranceiver definitions */
+#define MII_TG3_FET_PTEST 0x17
+#define MII_TG3_FET_PTEST_FRC_TX_LINK 0x1000
+#define MII_TG3_FET_PTEST_FRC_TX_LOCK 0x0800
+
+#define MII_TG3_FET_TEST 0x1f
+#define MII_TG3_FET_SHADOW_EN 0x0080
+
+#define MII_TG3_FET_SHDW_MISCCTRL 0x10
+#define MII_TG3_FET_SHDW_MISCCTRL_MDIX 0x4000
+
+#define MII_TG3_FET_SHDW_AUXMODE4 0x1a
+#define MII_TG3_FET_SHDW_AUXMODE4_SBPD 0x0008
+
+#define MII_TG3_FET_SHDW_AUXSTAT2 0x1b
+#define MII_TG3_FET_SHDW_AUXSTAT2_APD 0x0020
+
+
+/* APE registers. Accessible through BAR1 */
+#define TG3_APE_EVENT 0x000c
+#define APE_EVENT_1 0x00000001
+#define TG3_APE_LOCK_REQ 0x002c
+#define APE_LOCK_REQ_DRIVER 0x00001000
+#define TG3_APE_LOCK_GRANT 0x004c
+#define APE_LOCK_GRANT_DRIVER 0x00001000
+#define TG3_APE_SEG_SIG 0x4000
+#define APE_SEG_SIG_MAGIC 0x41504521
+
+/* APE shared memory. Accessible through BAR1 */
+#define TG3_APE_FW_STATUS 0x400c
+#define APE_FW_STATUS_READY 0x00000100
+#define TG3_APE_FW_FEATURES 0x4010
+#define TG3_APE_FW_FEATURE_NCSI 0x00000002
+#define TG3_APE_FW_VERSION 0x4018
+#define APE_FW_VERSION_MAJMSK 0xff000000
+#define APE_FW_VERSION_MAJSFT 24
+#define APE_FW_VERSION_MINMSK 0x00ff0000
+#define APE_FW_VERSION_MINSFT 16
+#define APE_FW_VERSION_REVMSK 0x0000ff00
+#define APE_FW_VERSION_REVSFT 8
+#define APE_FW_VERSION_BLDMSK 0x000000ff
+#define TG3_APE_HOST_SEG_SIG 0x4200
+#define APE_HOST_SEG_SIG_MAGIC 0x484f5354
+#define TG3_APE_HOST_SEG_LEN 0x4204
+#define APE_HOST_SEG_LEN_MAGIC 0x00000020
+#define TG3_APE_HOST_INIT_COUNT 0x4208
+#define TG3_APE_HOST_DRIVER_ID 0x420c
+#define APE_HOST_DRIVER_ID_LINUX 0xf0000000
+#define APE_HOST_DRIVER_ID_MAGIC(maj, min) \
+ (APE_HOST_DRIVER_ID_LINUX | (maj & 0xff) << 16 | (min & 0xff) << 8)
+#define TG3_APE_HOST_BEHAVIOR 0x4210
+#define APE_HOST_BEHAV_NO_PHYLOCK 0x00000001
+#define TG3_APE_HOST_HEARTBEAT_INT_MS 0x4214
+#define APE_HOST_HEARTBEAT_INT_DISABLE 0
+#define APE_HOST_HEARTBEAT_INT_5SEC 5000
+#define TG3_APE_HOST_HEARTBEAT_COUNT 0x4218
+#define TG3_APE_HOST_DRVR_STATE 0x421c
+#define TG3_APE_HOST_DRVR_STATE_START 0x00000001
+#define TG3_APE_HOST_DRVR_STATE_UNLOAD 0x00000002
+#define TG3_APE_HOST_DRVR_STATE_WOL 0x00000003
+#define TG3_APE_HOST_WOL_SPEED 0x4224
+#define TG3_APE_HOST_WOL_SPEED_AUTO 0x00008000
+
+#define TG3_APE_EVENT_STATUS 0x4300
+
+#define APE_EVENT_STATUS_DRIVER_EVNT 0x00000010
+#define APE_EVENT_STATUS_STATE_CHNGE 0x00000500
+#define APE_EVENT_STATUS_STATE_START 0x00010000
+#define APE_EVENT_STATUS_STATE_UNLOAD 0x00020000
+#define APE_EVENT_STATUS_STATE_WOL 0x00030000
+#define APE_EVENT_STATUS_STATE_SUSPEND 0x00040000
+#define APE_EVENT_STATUS_EVENT_PENDING 0x80000000
+
+#define TG3_APE_PER_LOCK_REQ 0x8400
+#define APE_LOCK_PER_REQ_DRIVER 0x00001000
+#define TG3_APE_PER_LOCK_GRANT 0x8420
+#define APE_PER_LOCK_GRANT_DRIVER 0x00001000
+
+/* APE convenience enumerations. */
+#define TG3_APE_LOCK_GRC 1
+#define TG3_APE_LOCK_MEM 4
+
+#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10
+
+
+/* There are two ways to manage the TX descriptors on the tigon3.
+ * Either the descriptors are in host DMA'able memory, or they
+ * exist only in the cards on-chip SRAM. All 16 send bds are under
+ * the same mode, they may not be configured individually.
+ *
+ * This driver always uses host memory TX descriptors.
+ *
+ * To use host memory TX descriptors:
+ * 1) Set GRC_MODE_HOST_SENDBDS in GRC_MODE register.
+ * Make sure GRC_MODE_4X_NIC_SEND_RINGS is clear.
+ * 2) Allocate DMA'able memory.
+ * 3) In NIC_SRAM_SEND_RCB (of desired index) of on-chip SRAM:
+ * a) Set TG3_BDINFO_HOST_ADDR to DMA address of memory
+ * obtained in step 2
+ * b) Set TG3_BDINFO_NIC_ADDR to NIC_SRAM_TX_BUFFER_DESC.
+ * c) Set len field of TG3_BDINFO_MAXLEN_FLAGS to number
+ * of TX descriptors. Leave flags field clear.
+ * 4) Access TX descriptors via host memory. The chip
+ * will refetch into local SRAM as needed when producer
+ * index mailboxes are updated.
+ *
+ * To use on-chip TX descriptors:
+ * 1) Set GRC_MODE_4X_NIC_SEND_RINGS in GRC_MODE register.
+ * Make sure GRC_MODE_HOST_SENDBDS is clear.
+ * 2) In NIC_SRAM_SEND_RCB (of desired index) of on-chip SRAM:
+ * a) Set TG3_BDINFO_HOST_ADDR to zero.
+ * b) Set TG3_BDINFO_NIC_ADDR to NIC_SRAM_TX_BUFFER_DESC
+ * c) TG3_BDINFO_MAXLEN_FLAGS is don't care.
+ * 3) Access TX descriptors directly in on-chip SRAM
+ * using normal {read,write}l(). (and not using
+ * pointer dereferencing of ioremap()'d memory like
+ * the broken Broadcom driver does)
+ *
+ * Note that BDINFO_FLAGS_DISABLED should be set in the flags field of
+ * TG3_BDINFO_MAXLEN_FLAGS of all unused SEND_RCB indices.
+ */
+struct tg3_tx_buffer_desc {
+ u32 addr_hi;
+ u32 addr_lo;
+
+ u32 len_flags;
+#define TXD_FLAG_TCPUDP_CSUM 0x0001
+#define TXD_FLAG_IP_CSUM 0x0002
+#define TXD_FLAG_END 0x0004
+#define TXD_FLAG_IP_FRAG 0x0008
+#define TXD_FLAG_JMB_PKT 0x0008
+#define TXD_FLAG_IP_FRAG_END 0x0010
+#define TXD_FLAG_VLAN 0x0040
+#define TXD_FLAG_COAL_NOW 0x0080
+#define TXD_FLAG_CPU_PRE_DMA 0x0100
+#define TXD_FLAG_CPU_POST_DMA 0x0200
+#define TXD_FLAG_ADD_SRC_ADDR 0x1000
+#define TXD_FLAG_CHOOSE_SRC_ADDR 0x6000
+#define TXD_FLAG_NO_CRC 0x8000
+#define TXD_LEN_SHIFT 16
+
+ u32 vlan_tag;
+#define TXD_VLAN_TAG_SHIFT 0
+#define TXD_MSS_SHIFT 16
+};
+
+#define TXD_ADDR 0x00UL /* 64-bit */
+#define TXD_LEN_FLAGS 0x08UL /* 32-bit (upper 16-bits are len) */
+#define TXD_VLAN_TAG 0x0cUL /* 32-bit (upper 16-bits are tag) */
+#define TXD_SIZE 0x10UL
+
+struct tg3_rx_buffer_desc {
+ u32 addr_hi;
+ u32 addr_lo;
+
+ u32 idx_len;
+#define RXD_IDX_MASK 0xffff0000
+#define RXD_IDX_SHIFT 16
+#define RXD_LEN_MASK 0x0000ffff
+#define RXD_LEN_SHIFT 0
+
+ u32 type_flags;
+#define RXD_TYPE_SHIFT 16
+#define RXD_FLAGS_SHIFT 0
+
+#define RXD_FLAG_END 0x0004
+#define RXD_FLAG_MINI 0x0800
+#define RXD_FLAG_JUMBO 0x0020
+#define RXD_FLAG_VLAN 0x0040
+#define RXD_FLAG_ERROR 0x0400
+#define RXD_FLAG_IP_CSUM 0x1000
+#define RXD_FLAG_TCPUDP_CSUM 0x2000
+#define RXD_FLAG_IS_TCP 0x4000
+
+ u32 ip_tcp_csum;
+#define RXD_IPCSUM_MASK 0xffff0000
+#define RXD_IPCSUM_SHIFT 16
+#define RXD_TCPCSUM_MASK 0x0000ffff
+#define RXD_TCPCSUM_SHIFT 0
+
+ u32 err_vlan;
+
+#define RXD_VLAN_MASK 0x0000ffff
+
+#define RXD_ERR_BAD_CRC 0x00010000
+#define RXD_ERR_COLLISION 0x00020000
+#define RXD_ERR_LINK_LOST 0x00040000
+#define RXD_ERR_PHY_DECODE 0x00080000
+#define RXD_ERR_ODD_NIBBLE_RCVD_MII 0x00100000
+#define RXD_ERR_MAC_ABRT 0x00200000
+#define RXD_ERR_TOO_SMALL 0x00400000
+#define RXD_ERR_NO_RESOURCES 0x00800000
+#define RXD_ERR_HUGE_FRAME 0x01000000
+#define RXD_ERR_MASK 0xffff0000
+
+ u32 reserved;
+ u32 opaque;
+#define RXD_OPAQUE_INDEX_MASK 0x0000ffff
+#define RXD_OPAQUE_INDEX_SHIFT 0
+#define RXD_OPAQUE_RING_STD 0x00010000
+#define RXD_OPAQUE_RING_JUMBO 0x00020000
+#define RXD_OPAQUE_RING_MINI 0x00040000
+#define RXD_OPAQUE_RING_MASK 0x00070000
+};
+
+struct tg3_ext_rx_buffer_desc {
+ struct {
+ u32 addr_hi;
+ u32 addr_lo;
+ } addrlist[3];
+ u32 len2_len1;
+ u32 resv_len3;
+ struct tg3_rx_buffer_desc std;
+};
+
+/* We only use this when testing out the DMA engine
+ * at probe time. This is the internal format of buffer
+ * descriptors used by the chip at NIC_SRAM_DMA_DESCS.
+ */
+struct tg3_internal_buffer_desc {
+ u32 addr_hi;
+ u32 addr_lo;
+ u32 nic_mbuf;
+ /* XXX FIX THIS */
+#if __BYTE_ORDER == __BIG_ENDIAN
+ u16 cqid_sqid;
+ u16 len;
+#else
+ u16 len;
+ u16 cqid_sqid;
+#endif
+ u32 flags;
+ u32 __cookie1;
+ u32 __cookie2;
+ u32 __cookie3;
+};
+
+#define TG3_HW_STATUS_SIZE 0x50
+struct tg3_hw_status {
+ u32 status;
+#define SD_STATUS_UPDATED 0x00000001
+#define SD_STATUS_LINK_CHG 0x00000002
+#define SD_STATUS_ERROR 0x00000004
+
+ u32 status_tag;
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+ u16 rx_consumer;
+ u16 rx_jumbo_consumer;
+#else
+ u16 rx_jumbo_consumer;
+ u16 rx_consumer;
+#endif
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+ u16 reserved;
+ u16 rx_mini_consumer;
+#else
+ u16 rx_mini_consumer;
+ u16 reserved;
+#endif
+ struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ u16 tx_consumer;
+ u16 rx_producer;
+#else
+ u16 rx_producer;
+ u16 tx_consumer;
+#endif
+ } idx[16];
+};
+
+typedef struct {
+ u32 high, low;
+} tg3_stat64_t;
+
+struct tg3_hw_stats {
+ u8 __reserved0[0x400-0x300];
+
+ /* Statistics maintained by Receive MAC. */
+ tg3_stat64_t rx_octets;
+ u64 __reserved1;
+ tg3_stat64_t rx_fragments;
+ tg3_stat64_t rx_ucast_packets;
+ tg3_stat64_t rx_mcast_packets;
+ tg3_stat64_t rx_bcast_packets;
+ tg3_stat64_t rx_fcs_errors;
+ tg3_stat64_t rx_align_errors;
+ tg3_stat64_t rx_xon_pause_rcvd;
+ tg3_stat64_t rx_xoff_pause_rcvd;
+ tg3_stat64_t rx_mac_ctrl_rcvd;
+ tg3_stat64_t rx_xoff_entered;
+ tg3_stat64_t rx_frame_too_long_errors;
+ tg3_stat64_t rx_jabbers;
+ tg3_stat64_t rx_undersize_packets;
+ tg3_stat64_t rx_in_length_errors;
+ tg3_stat64_t rx_out_length_errors;
+ tg3_stat64_t rx_64_or_less_octet_packets;
+ tg3_stat64_t rx_65_to_127_octet_packets;
+ tg3_stat64_t rx_128_to_255_octet_packets;
+ tg3_stat64_t rx_256_to_511_octet_packets;
+ tg3_stat64_t rx_512_to_1023_octet_packets;
+ tg3_stat64_t rx_1024_to_1522_octet_packets;
+ tg3_stat64_t rx_1523_to_2047_octet_packets;
+ tg3_stat64_t rx_2048_to_4095_octet_packets;
+ tg3_stat64_t rx_4096_to_8191_octet_packets;
+ tg3_stat64_t rx_8192_to_9022_octet_packets;
+
+ u64 __unused0[37];
+
+ /* Statistics maintained by Transmit MAC. */
+ tg3_stat64_t tx_octets;
+ u64 __reserved2;
+ tg3_stat64_t tx_collisions;
+ tg3_stat64_t tx_xon_sent;
+ tg3_stat64_t tx_xoff_sent;
+ tg3_stat64_t tx_flow_control;
+ tg3_stat64_t tx_mac_errors;
+ tg3_stat64_t tx_single_collisions;
+ tg3_stat64_t tx_mult_collisions;
+ tg3_stat64_t tx_deferred;
+ u64 __reserved3;
+ tg3_stat64_t tx_excessive_collisions;
+ tg3_stat64_t tx_late_collisions;
+ tg3_stat64_t tx_collide_2times;
+ tg3_stat64_t tx_collide_3times;
+ tg3_stat64_t tx_collide_4times;
+ tg3_stat64_t tx_collide_5times;
+ tg3_stat64_t tx_collide_6times;
+ tg3_stat64_t tx_collide_7times;
+ tg3_stat64_t tx_collide_8times;
+ tg3_stat64_t tx_collide_9times;
+ tg3_stat64_t tx_collide_10times;
+ tg3_stat64_t tx_collide_11times;
+ tg3_stat64_t tx_collide_12times;
+ tg3_stat64_t tx_collide_13times;
+ tg3_stat64_t tx_collide_14times;
+ tg3_stat64_t tx_collide_15times;
+ tg3_stat64_t tx_ucast_packets;
+ tg3_stat64_t tx_mcast_packets;
+ tg3_stat64_t tx_bcast_packets;
+ tg3_stat64_t tx_carrier_sense_errors;
+ tg3_stat64_t tx_discards;
+ tg3_stat64_t tx_errors;
+
+ u64 __unused1[31];
+
+ /* Statistics maintained by Receive List Placement. */
+ tg3_stat64_t COS_rx_packets[16];
+ tg3_stat64_t COS_rx_filter_dropped;
+ tg3_stat64_t dma_writeq_full;
+ tg3_stat64_t dma_write_prioq_full;
+ tg3_stat64_t rxbds_empty;
+ tg3_stat64_t rx_discards;
+ tg3_stat64_t rx_errors;
+ tg3_stat64_t rx_threshold_hit;
+
+ u64 __unused2[9];
+
+ /* Statistics maintained by Send Data Initiator. */
+ tg3_stat64_t COS_out_packets[16];
+ tg3_stat64_t dma_readq_full;
+ tg3_stat64_t dma_read_prioq_full;
+ tg3_stat64_t tx_comp_queue_full;
+
+ /* Statistics maintained by Host Coalescing. */
+ tg3_stat64_t ring_set_send_prod_index;
+ tg3_stat64_t ring_status_update;
+ tg3_stat64_t nic_irqs;
+ tg3_stat64_t nic_avoided_irqs;
+ tg3_stat64_t nic_tx_threshold_hit;
+
+ /* NOT a part of the hardware statistics block format.
+ * These stats are here as storage for tg3_periodic_fetch_stats().
+ */
+ tg3_stat64_t mbuf_lwm_thresh_hit;
+
+ u8 __reserved4[0xb00-0x9c8];
+};
+
+typedef u32 dma_addr_t;
+
+/* 'mapping' is superfluous as the chip does not write into
+ * the tx/rx post rings so we could just fetch it from there.
+ * But the cache behavior is better how we are doing it now.
+ */
+struct ring_info {
+ struct io_buffer *iob;
+/// dma_addr_t mapping;
+};
+
+struct tg3_link_config {
+ /* Describes what we're trying to get. */
+ u32 advertising;
+ u16 speed;
+ u8 duplex;
+ u8 autoneg;
+ u8 flowctrl;
+
+ /* Describes what we actually have. */
+ u8 active_flowctrl;
+
+ u8 active_duplex;
+#define SPEED_INVALID 0xffff
+#define DUPLEX_INVALID 0xff
+#define AUTONEG_INVALID 0xff
+ u16 active_speed;
+
+ /* When we go in and out of low power mode we need
+ * to swap with this state.
+ */
+ u16 orig_speed;
+ u8 orig_duplex;
+ u8 orig_autoneg;
+ u32 orig_advertising;
+};
+
+struct tg3_bufmgr_config {
+ u32 mbuf_read_dma_low_water;
+ u32 mbuf_mac_rx_low_water;
+ u32 mbuf_high_water;
+
+ u32 mbuf_read_dma_low_water_jumbo;
+ u32 mbuf_mac_rx_low_water_jumbo;
+ u32 mbuf_high_water_jumbo;
+
+ u32 dma_low_water;
+ u32 dma_high_water;
+};
+
+struct tg3_ethtool_stats {
+ /* Statistics maintained by Receive MAC. */
+ u64 rx_octets;
+ u64 rx_fragments;
+ u64 rx_ucast_packets;
+ u64 rx_mcast_packets;
+ u64 rx_bcast_packets;
+ u64 rx_fcs_errors;
+ u64 rx_align_errors;
+ u64 rx_xon_pause_rcvd;
+ u64 rx_xoff_pause_rcvd;
+ u64 rx_mac_ctrl_rcvd;
+ u64 rx_xoff_entered;
+ u64 rx_frame_too_long_errors;
+ u64 rx_jabbers;
+ u64 rx_undersize_packets;
+ u64 rx_in_length_errors;
+ u64 rx_out_length_errors;
+ u64 rx_64_or_less_octet_packets;
+ u64 rx_65_to_127_octet_packets;
+ u64 rx_128_to_255_octet_packets;
+ u64 rx_256_to_511_octet_packets;
+ u64 rx_512_to_1023_octet_packets;
+ u64 rx_1024_to_1522_octet_packets;
+ u64 rx_1523_to_2047_octet_packets;
+ u64 rx_2048_to_4095_octet_packets;
+ u64 rx_4096_to_8191_octet_packets;
+ u64 rx_8192_to_9022_octet_packets;
+
+ /* Statistics maintained by Transmit MAC. */
+ u64 tx_octets;
+ u64 tx_collisions;
+ u64 tx_xon_sent;
+ u64 tx_xoff_sent;
+ u64 tx_flow_control;
+ u64 tx_mac_errors;
+ u64 tx_single_collisions;
+ u64 tx_mult_collisions;
+ u64 tx_deferred;
+ u64 tx_excessive_collisions;
+ u64 tx_late_collisions;
+ u64 tx_collide_2times;
+ u64 tx_collide_3times;
+ u64 tx_collide_4times;
+ u64 tx_collide_5times;
+ u64 tx_collide_6times;
+ u64 tx_collide_7times;
+ u64 tx_collide_8times;
+ u64 tx_collide_9times;
+ u64 tx_collide_10times;
+ u64 tx_collide_11times;
+ u64 tx_collide_12times;
+ u64 tx_collide_13times;
+ u64 tx_collide_14times;
+ u64 tx_collide_15times;
+ u64 tx_ucast_packets;
+ u64 tx_mcast_packets;
+ u64 tx_bcast_packets;
+ u64 tx_carrier_sense_errors;
+ u64 tx_discards;
+ u64 tx_errors;
+
+ /* Statistics maintained by Receive List Placement. */
+ u64 dma_writeq_full;
+ u64 dma_write_prioq_full;
+ u64 rxbds_empty;
+ u64 rx_discards;
+ u64 rx_errors;
+ u64 rx_threshold_hit;
+
+ /* Statistics maintained by Send Data Initiator. */
+ u64 dma_readq_full;
+ u64 dma_read_prioq_full;
+ u64 tx_comp_queue_full;
+
+ /* Statistics maintained by Host Coalescing. */
+ u64 ring_set_send_prod_index;
+ u64 ring_status_update;
+ u64 nic_irqs;
+ u64 nic_avoided_irqs;
+ u64 nic_tx_threshold_hit;
+
+ u64 mbuf_lwm_thresh_hit;
+};
+
+/* number of io_buffers to allocate */
+#define TG3_DEF_RX_RING_PENDING 8
+
+struct tg3_rx_prodring_set {
+ u32 rx_std_prod_idx;
+ u32 rx_std_cons_idx;
+ u32 rx_std_iob_cnt;
+ struct tg3_rx_buffer_desc *rx_std;
+ struct io_buffer *rx_iobufs[TG3_DEF_RX_RING_PENDING];
+ dma_addr_t rx_std_mapping;
+};
+
+#define TG3_IRQ_MAX_VECS_RSS 5
+#define TG3_IRQ_MAX_VECS TG3_IRQ_MAX_VECS_RSS
+
+enum TG3_FLAGS {
+ TG3_FLAG_TAGGED_STATUS = 0,
+ TG3_FLAG_TXD_MBOX_HWBUG,
+ TG3_FLAG_USE_LINKCHG_REG,
+ TG3_FLAG_ERROR_PROCESSED,
+ TG3_FLAG_ENABLE_ASF,
+ TG3_FLAG_ASPM_WORKAROUND,
+ TG3_FLAG_POLL_SERDES,
+ TG3_FLAG_MBOX_WRITE_REORDER,
+ TG3_FLAG_PCIX_TARGET_HWBUG,
+ TG3_FLAG_WOL_SPEED_100MB,
+ TG3_FLAG_WOL_ENABLE,
+ TG3_FLAG_EEPROM_WRITE_PROT,
+ TG3_FLAG_NVRAM,
+ TG3_FLAG_NVRAM_BUFFERED,
+ TG3_FLAG_SUPPORT_MSI,
+ TG3_FLAG_SUPPORT_MSIX,
+ TG3_FLAG_PCIX_MODE,
+ TG3_FLAG_PCI_HIGH_SPEED,
+ TG3_FLAG_PCI_32BIT,
+ TG3_FLAG_SRAM_USE_CONFIG,
+ TG3_FLAG_TX_RECOVERY_PENDING,
+ TG3_FLAG_WOL_CAP,
+ TG3_FLAG_JUMBO_RING_ENABLE,
+ TG3_FLAG_PAUSE_AUTONEG,
+ TG3_FLAG_CPMU_PRESENT,
+ TG3_FLAG_BROKEN_CHECKSUMS,
+ TG3_FLAG_JUMBO_CAPABLE,
+ TG3_FLAG_CHIP_RESETTING,
+ TG3_FLAG_INIT_COMPLETE,
+ TG3_FLAG_RESTART_TIMER,
+ TG3_FLAG_TSO_BUG,
+ TG3_FLAG_IS_5788,
+ TG3_FLAG_MAX_RXPEND_64,
+ TG3_FLAG_TSO_CAPABLE,
+ TG3_FLAG_PCI_EXPRESS,
+ TG3_FLAG_ASF_NEW_HANDSHAKE,
+ TG3_FLAG_HW_AUTONEG,
+ TG3_FLAG_IS_NIC,
+ TG3_FLAG_FLASH,
+ TG3_FLAG_HW_TSO_1,
+ TG3_FLAG_5705_PLUS,
+ TG3_FLAG_5750_PLUS,
+ TG3_FLAG_HW_TSO_3,
+ TG3_FLAG_USING_MSI,
+ TG3_FLAG_USING_MSIX,
+ TG3_FLAG_ICH_WORKAROUND,
+ TG3_FLAG_5780_CLASS,
+ TG3_FLAG_HW_TSO_2,
+ TG3_FLAG_1SHOT_MSI,
+ TG3_FLAG_NO_FWARE_REPORTED,
+ TG3_FLAG_NO_NVRAM_ADDR_TRANS,
+ TG3_FLAG_ENABLE_APE,
+ TG3_FLAG_PROTECTED_NVRAM,
+ TG3_FLAG_MDIOBUS_INITED,
+ TG3_FLAG_LRG_PROD_RING_CAP,
+ TG3_FLAG_RGMII_INBAND_DISABLE,
+ TG3_FLAG_RGMII_EXT_IBND_RX_EN,
+ TG3_FLAG_RGMII_EXT_IBND_TX_EN,
+ TG3_FLAG_CLKREQ_BUG,
+ TG3_FLAG_5755_PLUS,
+ TG3_FLAG_NO_NVRAM,
+ TG3_FLAG_ENABLE_RSS,
+ TG3_FLAG_ENABLE_TSS,
+ TG3_FLAG_4G_DMA_BNDRY_BUG,
+ TG3_FLAG_USE_JUMBO_BDFLAG,
+ TG3_FLAG_L1PLLPD_EN,
+ TG3_FLAG_57765_PLUS,
+ TG3_FLAG_APE_HAS_NCSI,
+ TG3_FLAG_5717_PLUS,
+
+ /* Add new flags before this comment and TG3_FLAG_NUMBER_OF_FLAGS */
+ TG3_FLAG_NUMBER_OF_FLAGS, /* Last entry in enum TG3_FLAGS */
+};
+
+/* Following definition is copied from linux-3.0rc1/include/linux/kernel.h */
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+/* bitops.h */
+#define BITS_PER_BYTE 8
+#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+/* types.h: */
+#define DECLARE_BITMAP(name,bits) \
+ unsigned long name[BITS_TO_LONGS(bits)]
+
+struct tg3 {
+ /* begin "general, frequently-used members" cacheline section */
+
+ /* If the IRQ handler (which runs lockless) needs to be
+ * quiesced, the following bitmask state is used. The
+ * SYNC flag is set by non-IRQ context code to initiate
+ * the quiescence.
+ *
+ * When the IRQ handler notices that SYNC is set, it
+ * disables interrupts and returns.
+ *
+ * When all outstanding IRQ handlers have returned after
+ * the SYNC flag has been set, the setter can be assured
+ * that interrupts will no longer get run.
+ *
+ * In this way all SMP driver locks are never acquired
+ * in hw IRQ context, only sw IRQ context or lower.
+ */
+ unsigned int irq_sync;
+
+ /* SMP locking strategy:
+ *
+ * lock: Held during reset, PHY access, timer, and when
+ * updating tg3_flags.
+ *
+ * netif_tx_lock: Held during tg3_start_xmit. tg3_tx holds
+ * netif_tx_lock when it needs to call
+ * netif_wake_queue.
+ *
+ * Both of these locks are to be held with BH safety.
+ *
+ * Because the IRQ handler, tg3_poll, and tg3_start_xmit
+ * are running lockless, it is necessary to completely
+ * quiesce the chip with tg3_netif_stop and tg3_full_lock
+ * before reconfiguring the device.
+ *
+ * indirect_lock: Held when accessing registers indirectly
+ * with IRQ disabling.
+ */
+
+ u32 (*read32_mbox) (struct tg3 *, u32);
+ void (*write32_mbox) (struct tg3 *, u32,
+ u32);
+ void *regs;
+ struct net_device *dev;
+ struct pci_device *pdev;
+
+ u32 msg_enable;
+
+ /* begin "tx thread" cacheline section */
+ void (*write32_tx_mbox) (struct tg3 *, u32,
+ u32);
+
+ /* begin "rx thread" cacheline section */
+ void (*write32_rx_mbox) (struct tg3 *, u32,
+ u32);
+ u32 rx_std_max_post;
+ u32 rx_pkt_map_sz;
+
+ /* was struct tg3_napi: */
+ struct tg3_hw_status *hw_status;
+
+ u32 last_tag;
+ u32 last_irq_tag;
+ u32 int_mbox;
+ /* NOTE: there was a coal_now in struct tg3_napi and struct tg3. We
+ * didn't use coal_now in struct tg3, so it was removed */
+ u32 coal_now;
+
+ u32 consmbox;
+ u32 rx_rcb_ptr;
+ u16 *rx_rcb_prod_idx;
+ struct tg3_rx_prodring_set prodring;
+ struct tg3_rx_buffer_desc *rx_rcb;
+
+ u32 tx_prod;
+ u32 tx_cons;
+ u32 prodmbox;
+ struct tg3_tx_buffer_desc *tx_ring;
+ struct ring_info *tx_buffers;
+
+ dma_addr_t status_mapping;
+ dma_addr_t rx_rcb_mapping;
+ dma_addr_t tx_desc_mapping;
+ /* end tg3_napi */
+
+ /* begin "everything else" cacheline(s) section */
+ unsigned long rx_dropped;
+
+ DECLARE_BITMAP(tg3_flags, TG3_FLAG_NUMBER_OF_FLAGS);
+
+ union {
+ unsigned long phy_crc_errors;
+ };
+
+ u16 timer_counter;
+ u16 timer_multiplier;
+ u32 timer_offset;
+ u16 asf_counter;
+ u16 asf_multiplier;
+
+ /* 1 second counter for transient serdes link events */
+ u32 serdes_counter;
+#define SERDES_AN_TIMEOUT_5704S 2
+#define SERDES_PARALLEL_DET_TIMEOUT 1
+#define SERDES_AN_TIMEOUT_5714S 1
+
+ struct tg3_link_config link_config;
+ struct tg3_bufmgr_config bufmgr_config;
+
+ /* cache h/w values, often passed straight to h/w */
+ u32 rx_mode;
+ u32 tx_mode;
+ u32 mac_mode;
+ u32 mi_mode;
+ u32 misc_host_ctrl;
+ u32 grc_mode;
+ u32 grc_local_ctrl;
+ u32 dma_rwctrl;
+ u32 coalesce_mode;
+
+ /* PCI block */
+ u32 pci_chip_rev_id;
+ u16 pci_cmd;
+ u8 pci_cacheline_sz;
+ u8 pci_lat_timer;
+
+ int pm_cap;
+ union {
+ int pcix_cap;
+ int pcie_cap;
+ };
+ int pcie_readrq;
+
+ u8 phy_addr;
+
+ /* PHY info */
+ u32 phy_id;
+#define TG3_PHY_ID_MASK 0xfffffff0
+#define TG3_PHY_ID_BCM5400 0x60008040
+#define TG3_PHY_ID_BCM5401 0x60008050
+#define TG3_PHY_ID_BCM5411 0x60008070
+#define TG3_PHY_ID_BCM5701 0x60008110
+#define TG3_PHY_ID_BCM5703 0x60008160
+#define TG3_PHY_ID_BCM5704 0x60008190
+#define TG3_PHY_ID_BCM5705 0x600081a0
+#define TG3_PHY_ID_BCM5750 0x60008180
+#define TG3_PHY_ID_BCM5752 0x60008100
+#define TG3_PHY_ID_BCM5714 0x60008340
+#define TG3_PHY_ID_BCM5780 0x60008350
+#define TG3_PHY_ID_BCM5755 0xbc050cc0
+#define TG3_PHY_ID_BCM5787 0xbc050ce0
+#define TG3_PHY_ID_BCM5756 0xbc050ed0
+#define TG3_PHY_ID_BCM5784 0xbc050fa0
+#define TG3_PHY_ID_BCM5761 0xbc050fd0
+#define TG3_PHY_ID_BCM5718C 0x5c0d8a00
+#define TG3_PHY_ID_BCM5718S 0xbc050ff0
+#define TG3_PHY_ID_BCM57765 0x5c0d8a40
+#define TG3_PHY_ID_BCM5719C 0x5c0d8a20
+#define TG3_PHY_ID_BCM5720C 0x5c0d8b60
+#define TG3_PHY_ID_BCM5906 0xdc00ac40
+#define TG3_PHY_ID_BCM8002 0x60010140
+#define TG3_PHY_ID_INVALID 0xffffffff
+
+#define PHY_ID_RTL8211C 0x001cc910
+#define PHY_ID_RTL8201E 0x00008200
+
+#define TG3_PHY_ID_REV_MASK 0x0000000f
+#define TG3_PHY_REV_BCM5401_B0 0x1
+
+ /* This macro assumes the passed PHY ID is
+ * already masked with TG3_PHY_ID_MASK.
+ */
+#define TG3_KNOWN_PHY_ID(X) \
+ ((X) == TG3_PHY_ID_BCM5400 || (X) == TG3_PHY_ID_BCM5401 || \
+ (X) == TG3_PHY_ID_BCM5411 || (X) == TG3_PHY_ID_BCM5701 || \
+ (X) == TG3_PHY_ID_BCM5703 || (X) == TG3_PHY_ID_BCM5704 || \
+ (X) == TG3_PHY_ID_BCM5705 || (X) == TG3_PHY_ID_BCM5750 || \
+ (X) == TG3_PHY_ID_BCM5752 || (X) == TG3_PHY_ID_BCM5714 || \
+ (X) == TG3_PHY_ID_BCM5780 || (X) == TG3_PHY_ID_BCM5787 || \
+ (X) == TG3_PHY_ID_BCM5755 || (X) == TG3_PHY_ID_BCM5756 || \
+ (X) == TG3_PHY_ID_BCM5906 || (X) == TG3_PHY_ID_BCM5761 || \
+ (X) == TG3_PHY_ID_BCM5718C || (X) == TG3_PHY_ID_BCM5718S || \
+ (X) == TG3_PHY_ID_BCM57765 || (X) == TG3_PHY_ID_BCM5719C || \
+ (X) == TG3_PHY_ID_BCM8002)
+
+ u32 phy_flags;
+#define TG3_PHYFLG_IS_LOW_POWER 0x00000001
+#define TG3_PHYFLG_IS_CONNECTED 0x00000002
+#define TG3_PHYFLG_USE_MI_INTERRUPT 0x00000004
+#define TG3_PHYFLG_PHY_SERDES 0x00000010
+#define TG3_PHYFLG_MII_SERDES 0x00000020
+#define TG3_PHYFLG_ANY_SERDES (TG3_PHYFLG_PHY_SERDES | \
+ TG3_PHYFLG_MII_SERDES)
+#define TG3_PHYFLG_IS_FET 0x00000040
+#define TG3_PHYFLG_10_100_ONLY 0x00000080
+#define TG3_PHYFLG_ENABLE_APD 0x00000100
+#define TG3_PHYFLG_CAPACITIVE_COUPLING 0x00000200
+#define TG3_PHYFLG_NO_ETH_WIRE_SPEED 0x00000400
+#define TG3_PHYFLG_JITTER_BUG 0x00000800
+#define TG3_PHYFLG_ADJUST_TRIM 0x00001000
+#define TG3_PHYFLG_ADC_BUG 0x00002000
+#define TG3_PHYFLG_5704_A0_BUG 0x00004000
+#define TG3_PHYFLG_BER_BUG 0x00008000
+#define TG3_PHYFLG_SERDES_PREEMPHASIS 0x00010000
+#define TG3_PHYFLG_PARALLEL_DETECT 0x00020000
+#define TG3_PHYFLG_EEE_CAP 0x00040000
+
+ u32 led_ctrl;
+ u32 phy_otp;
+ u32 setlpicnt;
+
+#define TG3_BPN_SIZE 24
+ char board_part_number[TG3_BPN_SIZE];
+#define TG3_VER_SIZE 32
+ char fw_ver[TG3_VER_SIZE];
+ u32 nic_sram_data_cfg;
+ u32 pci_clock_ctrl;
+ struct pci_device *pdev_peer;
+
+ int nvram_lock_cnt;
+ u32 nvram_size;
+#define TG3_NVRAM_SIZE_2KB 0x00000800
+#define TG3_NVRAM_SIZE_64KB 0x00010000
+#define TG3_NVRAM_SIZE_128KB 0x00020000
+#define TG3_NVRAM_SIZE_256KB 0x00040000
+#define TG3_NVRAM_SIZE_512KB 0x00080000
+#define TG3_NVRAM_SIZE_1MB 0x00100000
+#define TG3_NVRAM_SIZE_2MB 0x00200000
+
+ u32 nvram_pagesize;
+ u32 nvram_jedecnum;
+
+#define JEDEC_ATMEL 0x1f
+#define JEDEC_ST 0x20
+#define JEDEC_SAIFUN 0x4f
+#define JEDEC_SST 0xbf
+
+#define ATMEL_AT24C02_CHIP_SIZE TG3_NVRAM_SIZE_2KB
+#define ATMEL_AT24C02_PAGE_SIZE (8)
+
+#define ATMEL_AT24C64_CHIP_SIZE TG3_NVRAM_SIZE_64KB
+#define ATMEL_AT24C64_PAGE_SIZE (32)
+
+#define ATMEL_AT24C512_CHIP_SIZE TG3_NVRAM_SIZE_512KB
+#define ATMEL_AT24C512_PAGE_SIZE (128)
+
+#define ATMEL_AT45DB0X1B_PAGE_POS 9
+#define ATMEL_AT45DB0X1B_PAGE_SIZE 264
+
+#define ATMEL_AT25F512_PAGE_SIZE 256
+
+#define ST_M45PEX0_PAGE_SIZE 256
+
+#define SAIFUN_SA25F0XX_PAGE_SIZE 256
+
+#define SST_25VF0X0_PAGE_SIZE 4098
+
+ u16 subsystem_vendor;
+ u16 subsystem_device;
+};
+
+#define ARRAY_SIZE(x) ( sizeof(x) / sizeof((x)[0]) )
+
+#define TG3_TX_RING_SIZE 512
+#define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1)
+
+/* FIXME: look up alignment requirement in datasheet, page align for now */
+#define TG3_DMA_ALIGNMENT 4096
+
+#define TG3_RX_STD_DMA_SZ (1536 + 64 + 2)
+
+static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val)
+{
+ tp->write32_mbox(tp, off, val);
+/// if (!tg3_flag(tp, MBOX_WRITE_REORDER) && !tg3_flag(tp, ICH_WORKAROUND))
+/// tp->read32_mbox(tp, off);
+}
+
+u32 tg3_read_indirect_reg32(struct tg3 *tp, u32 off);
+void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val);
+u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off);
+void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val);
+
+#define tw32(reg, val) tg3_write_indirect_reg32(tp, reg, val)
+///#define tw32_mailbox(reg, val) tg3_write_indirect_mbox(((val) & 0xffffffff), tp->regs + (reg))
+#define tw32_mailbox(reg, val) tg3_write_indirect_mbox(tp, (reg), (val))
+#define tw32_mailbox_f(reg, val) tw32_mailbox_flush(tp, (reg), (val))
+#define tw32_f(reg, val) _tw32_flush(tp, (reg), (val), 0)
+#define tw32_wait_f(reg, val, us) _tw32_flush(tp, (reg), (val), (us))
+
+#define tw32_tx_mbox(reg, val) tp->write32_tx_mbox(tp, reg, val)
+#define tw32_rx_mbox(reg, val) tp->write32_rx_mbox(tp, reg, val)
+
+#define tr32(reg) tg3_read_indirect_reg32(tp, reg)
+#define tr32_mailbox(reg) tp->read32_mbox(tp, reg)
+
+/* Functions & macros to verify TG3_FLAGS types */
+
+static inline int variable_test_bit(int nr, volatile const unsigned long *addr)
+{
+ int oldbit;
+
+ asm volatile("bt %2,%1\n\t"
+ "sbb %0,%0"
+ : "=r" (oldbit)
+ : "m" (*(unsigned long *)addr), "Ir" (nr));
+
+ return oldbit;
+}
+
+static inline int _tg3_flag(enum TG3_FLAGS flag, unsigned long *bits)
+{
+ return variable_test_bit(flag, bits);
+}
+
+#define BITOP_ADDR(x) "+m" (*(volatile long *) (x))
+
+static inline void __set_bit(int nr, volatile unsigned long *addr)
+{
+ asm volatile("bts %1,%0" : BITOP_ADDR(addr) : "Ir" (nr) : "memory");
+}
+
+static inline void _tg3_flag_set(enum TG3_FLAGS flag, unsigned long *bits)
+{
+ __set_bit(flag, bits);
+}
+
+static inline void __clear_bit(int nr, volatile unsigned long *addr)
+{
+ asm volatile("btr %1,%0" : BITOP_ADDR(addr) : "Ir" (nr));
+}
+
+static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
+{
+ __clear_bit(flag, bits);
+}
+
+#define tg3_flag(tp, flag) \
+ _tg3_flag(TG3_FLAG_##flag, (tp)->tg3_flags)
+#define tg3_flag_set(tp, flag) \
+ _tg3_flag_set(TG3_FLAG_##flag, (tp)->tg3_flags)
+#define tg3_flag_clear(tp, flag) \
+ _tg3_flag_clear(TG3_FLAG_##flag, (tp)->tg3_flags)
+
+/* tg3_main.c forward declarations */
+int tg3_init_rings(struct tg3 *tp);
+void tg3_rx_prodring_fini(struct tg3_rx_prodring_set *tpr);
+///int tg3_rx_prodring_init(struct tg3 *tp, struct tg3_rx_prodring_set *tpr);
+
+/* tg3_phy.c forward declarations */
+u32 tg3_read_otp_phycfg(struct tg3 *tp);
+void tg3_mdio_init(struct tg3 *tp);
+int tg3_phy_probe(struct tg3 *tp);
+int tg3_phy_reset(struct tg3 *tp);
+int tg3_setup_phy(struct tg3 *tp, int force_reset);
+int tg3_readphy(struct tg3 *tp, int reg, u32 *val);
+int tg3_writephy(struct tg3 *tp, int reg, u32 val);
+
+/* tg3_hw.c forward declarations */
+void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait);
+void tg3_write_mem(struct tg3 *tp, u32 off, u32 val);
+int tg3_get_invariants(struct tg3 *tp);
+void tg3_init_bufmgr_config(struct tg3 *tp);
+int tg3_get_device_address(struct tg3 *tp);
+int tg3_halt(struct tg3 *tp);
+void tg3_set_txd(struct tg3 *tp, int entry, dma_addr_t mapping, int len, u32 flags);
+void tg3_set_power_state_0(struct tg3 *tp);
+int tg3_alloc_consistent(struct tg3 *tp);
+int tg3_init_hw(struct tg3 *tp, int reset_phy);
+void tg3_poll_link(struct tg3 *tp);
+void tg3_wait_for_event_ack(struct tg3 *tp);
+void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1);
+void tg3_disable_ints(struct tg3 *tp);
+void tg3_enable_ints(struct tg3 *tp);
+
+static inline void tg3_generate_fw_event(struct tg3 *tp)
+{
+ u32 val;
+
+ val = tr32(GRC_RX_CPU_EVENT);
+ val |= GRC_RX_CPU_DRIVER_EVENT;
+ tw32_f(GRC_RX_CPU_EVENT, val);
+}
+
+/* linux-2.6.39, include/linux/mii.h: */
+/**
+ * mii_resolve_flowctrl_fdx
+ * @lcladv: value of MII ADVERTISE register
+ * @rmtadv: value of MII LPA register
+ *
+ * Resolve full duplex flow control as per IEEE 802.3-2005 table 28B-3
+ */
+static inline u8 mii_resolve_flowctrl_fdx(u16 lcladv, u16 rmtadv)
+{
+ u8 cap = 0;
+
+ if (lcladv & rmtadv & ADVERTISE_PAUSE_CAP) {
+ cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ } else if (lcladv & rmtadv & ADVERTISE_PAUSE_ASYM) {
+ if (lcladv & ADVERTISE_PAUSE_CAP)
+ cap = FLOW_CTRL_RX;
+ else if (rmtadv & ADVERTISE_PAUSE_CAP)
+ cap = FLOW_CTRL_TX;
+ }
+
+ return cap;
+}
+
+#define ETH_FCS_LEN 4
+
+#endif /* !(_T3_H) */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3_hw.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3_hw.c
new file mode 100644
index 00000000..13d5962c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3_hw.c
@@ -0,0 +1,2647 @@
+/*
+ * tg3.c: Broadcom Tigon3 ethernet driver.
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
+ * Copyright (C) 2004 Sun Microsystems Inc.
+ * Copyright (C) 2005-2011 Broadcom Corporation.
+ *
+ * Firmware is:
+ * Derived from proprietary unpublished source code,
+ * Copyright (C) 2000-2003 Broadcom Corporation.
+ *
+ * Permission is hereby granted for the distribution of this firmware
+ * data in hexadecimal or equivalent format, provided this copyright
+ * notice is accompanying it.
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include <mii.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/timer.h>
+#include <ipxe/malloc.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/netdevice.h>
+
+#include "tg3.h"
+
+#define RESET_KIND_SHUTDOWN 0
+#define RESET_KIND_INIT 1
+#define RESET_KIND_SUSPEND 2
+
+#define TG3_DEF_MAC_MODE 0
+
+void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
+{ DBGP("%s\n", __func__);
+
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
+}
+
+u32 tg3_read_indirect_reg32(struct tg3 *tp, u32 off)
+{ DBGP("%s\n", __func__);
+
+ u32 val;
+
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
+ pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
+ return val;
+}
+
+static u32 tg3_read32_mbox_5906(struct tg3 *tp, u32 off)
+{ DBGP("%s\n", __func__);
+
+ return readl(tp->regs + off + GRCMBOX_BASE);
+}
+
+static void tg3_write32_mbox_5906(struct tg3 *tp, u32 off, u32 val)
+{ DBGP("%s\n", __func__);
+
+ writel(val, tp->regs + off + GRCMBOX_BASE);
+}
+
+void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val)
+{ DBGP("%s\n", __func__);
+
+ if (off == (MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW)) {
+ pci_write_config_dword(tp->pdev, TG3PCI_RCV_RET_RING_CON_IDX +
+ TG3_64BIT_REG_LOW, val);
+ return;
+ }
+ if (off == TG3_RX_STD_PROD_IDX_REG) {
+ pci_write_config_dword(tp->pdev, TG3PCI_STD_RING_PROD_IDX +
+ TG3_64BIT_REG_LOW, val);
+ return;
+ }
+
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
+
+ /* In indirect mode when disabling interrupts, we also need
+ * to clear the interrupt bit in the GRC local ctrl register.
+ */
+ if ((off == (MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW)) &&
+ (val == 0x1)) {
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_LOCAL_CTRL,
+ tp->grc_local_ctrl|GRC_LCLCTRL_CLEARINT);
+ }
+}
+
+u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off)
+{ DBGP("%s\n", __func__);
+
+ u32 val;
+
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
+ pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
+
+ return val;
+}
+
+/* usec_wait specifies the wait time in usec when writing to certain registers
+ * where it is unsafe to read back the register without some delay.
+ * GRC_LOCAL_CTRL is one example if the GPIOs are toggled to switch power.
+ * TG3PCI_CLOCK_CTRL is another example if the clock frequencies are changed.
+ */
+void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait)
+{ DBGP("%s\n", __func__);
+
+ tw32(off, val);
+ if (usec_wait)
+ udelay(usec_wait);
+ tr32(off);
+
+ /* Wait again after the read for the posted method to guarantee that
+ * the wait time is met.
+ */
+ if (usec_wait)
+ udelay(usec_wait);
+}
+
+/* stolen from legacy etherboot tg3 driver */
+void tg3_set_power_state_0(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ uint16_t power_control;
+ int pm = tp->pm_cap;
+
+ /* Make sure register accesses (indirect or otherwise)
+ * will function correctly.
+ */
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
+
+ pci_read_config_word(tp->pdev, pm + PCI_PM_CTRL, &power_control);
+
+ power_control |= PCI_PM_CTRL_PME_STATUS;
+ power_control &= ~(PCI_PM_CTRL_STATE_MASK);
+ power_control |= 0;
+ pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
+
+ tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100);
+
+ return;
+}
+
+void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
+{ DBGP("%s\n", __func__);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
+ (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) {
+ *val = 0;
+ return;
+ }
+
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+ pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+
+ /* Always leave this as zero. */
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+}
+
+#define PCI_VENDOR_ID_ARIMA 0x161f
+
+static void tg3_get_eeprom_hw_cfg(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 val;
+ u16 pmcsr;
+
+ /* On some early chips the SRAM cannot be accessed in D3hot state,
+ * so need make sure we're in D0.
+ */
+ pci_read_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, &pmcsr);
+ pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+ pci_write_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, pmcsr);
+ mdelay(1);
+
+ /* Make sure register accesses (indirect or otherwise)
+ * will function correctly.
+ */
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
+
+ /* The memory arbiter has to be enabled in order for SRAM accesses
+ * to succeed. Normally on powerup the tg3 chip firmware will make
+ * sure it is enabled, but other entities such as system netboot
+ * code might disable it.
+ */
+ val = tr32(MEMARB_MODE);
+ tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
+
+ tp->phy_id = TG3_PHY_ID_INVALID;
+ tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
+ /* Assume an onboard device by default. */
+ tg3_flag_set(tp, EEPROM_WRITE_PROT);
+
+ tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
+ if (val == NIC_SRAM_DATA_SIG_MAGIC) {
+ u32 nic_cfg, led_cfg;
+ u32 nic_phy_id, ver, cfg2 = 0, cfg4 = 0, eeprom_phy_id;
+ int eeprom_phy_serdes = 0;
+
+ tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
+ tp->nic_sram_data_cfg = nic_cfg;
+
+ tg3_read_mem(tp, NIC_SRAM_DATA_VER, &ver);
+ ver >>= NIC_SRAM_DATA_VER_SHIFT;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5703 &&
+ (ver > 0) && (ver < 0x100))
+ tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &cfg2);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ tg3_read_mem(tp, NIC_SRAM_DATA_CFG_4, &cfg4);
+
+ if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
+ NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
+ eeprom_phy_serdes = 1;
+
+ tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
+ if (nic_phy_id != 0) {
+ u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
+ u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
+
+ eeprom_phy_id = (id1 >> 16) << 10;
+ eeprom_phy_id |= (id2 & 0xfc00) << 16;
+ eeprom_phy_id |= (id2 & 0x03ff) << 0;
+ } else
+ eeprom_phy_id = 0;
+
+ tp->phy_id = eeprom_phy_id;
+ if (eeprom_phy_serdes) {
+ if (!tg3_flag(tp, 5705_PLUS))
+ tp->phy_flags |= TG3_PHYFLG_PHY_SERDES;
+ else
+ tp->phy_flags |= TG3_PHYFLG_MII_SERDES;
+ }
+
+ if (tg3_flag(tp, 5750_PLUS))
+ led_cfg = cfg2 & (NIC_SRAM_DATA_CFG_LED_MODE_MASK |
+ SHASTA_EXT_LED_MODE_MASK);
+ else
+ led_cfg = nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK;
+
+ switch (led_cfg) {
+ default:
+ case NIC_SRAM_DATA_CFG_LED_MODE_PHY_1:
+ tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+ break;
+
+ case NIC_SRAM_DATA_CFG_LED_MODE_PHY_2:
+ tp->led_ctrl = LED_CTRL_MODE_PHY_2;
+ break;
+
+ case NIC_SRAM_DATA_CFG_LED_MODE_MAC:
+ tp->led_ctrl = LED_CTRL_MODE_MAC;
+
+ /* Default to PHY_1_MODE if 0 (MAC_MODE) is
+ * read on some older 5700/5701 bootcode.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+ ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) ==
+ ASIC_REV_5701)
+ tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
+ break;
+
+ case SHASTA_EXT_LED_SHARED:
+ tp->led_ctrl = LED_CTRL_MODE_SHARED;
+ if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 &&
+ tp->pci_chip_rev_id != CHIPREV_ID_5750_A1)
+ tp->led_ctrl |= (LED_CTRL_MODE_PHY_1 |
+ LED_CTRL_MODE_PHY_2);
+ break;
+
+ case SHASTA_EXT_LED_MAC:
+ tp->led_ctrl = LED_CTRL_MODE_SHASTA_MAC;
+ break;
+
+ case SHASTA_EXT_LED_COMBO:
+ tp->led_ctrl = LED_CTRL_MODE_COMBO;
+ if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0)
+ tp->led_ctrl |= (LED_CTRL_MODE_PHY_1 |
+ LED_CTRL_MODE_PHY_2);
+ break;
+
+ }
+
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) &&
+ tp->subsystem_vendor == PCI_VENDOR_ID_DELL)
+ tp->led_ctrl = LED_CTRL_MODE_PHY_2;
+
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX)
+ tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
+ if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
+ tg3_flag_set(tp, EEPROM_WRITE_PROT);
+ if ((tp->subsystem_vendor ==
+ PCI_VENDOR_ID_ARIMA) &&
+ (tp->subsystem_device == 0x205a ||
+ tp->subsystem_device == 0x2063))
+ tg3_flag_clear(tp, EEPROM_WRITE_PROT);
+ } else {
+ tg3_flag_clear(tp, EEPROM_WRITE_PROT);
+ tg3_flag_set(tp, IS_NIC);
+ }
+
+ if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
+ tg3_flag_set(tp, ENABLE_ASF);
+ if (tg3_flag(tp, 5750_PLUS))
+ tg3_flag_set(tp, ASF_NEW_HANDSHAKE);
+ }
+
+ if ((nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE) &&
+ tg3_flag(tp, 5750_PLUS))
+ tg3_flag_set(tp, ENABLE_APE);
+
+ if (cfg2 & (1 << 17))
+ tp->phy_flags |= TG3_PHYFLG_CAPACITIVE_COUPLING;
+
+ /* serdes signal pre-emphasis in register 0x590 set by */
+ /* bootcode if bit 18 is set */
+ if (cfg2 & (1 << 18))
+ tp->phy_flags |= TG3_PHYFLG_SERDES_PREEMPHASIS;
+
+ if ((tg3_flag(tp, 57765_PLUS) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+ GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX)) &&
+ (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN))
+ tp->phy_flags |= TG3_PHYFLG_ENABLE_APD;
+
+ if (tg3_flag(tp, PCI_EXPRESS) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+ !tg3_flag(tp, 57765_PLUS)) {
+ u32 cfg3;
+
+ tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &cfg3);
+ }
+
+ if (cfg4 & NIC_SRAM_RGMII_INBAND_DISABLE)
+ tg3_flag_set(tp, RGMII_INBAND_DISABLE);
+ if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_RX_EN)
+ tg3_flag_set(tp, RGMII_EXT_IBND_RX_EN);
+ if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_TX_EN)
+ tg3_flag_set(tp, RGMII_EXT_IBND_TX_EN);
+ }
+}
+
+static void tg3_switch_clocks(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 clock_ctrl;
+ u32 orig_clock_ctrl;
+
+ if (tg3_flag(tp, CPMU_PRESENT) || tg3_flag(tp, 5780_CLASS))
+ return;
+
+ clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
+
+ orig_clock_ctrl = clock_ctrl;
+ clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN |
+ CLOCK_CTRL_CLKRUN_OENABLE |
+ 0x1f);
+ tp->pci_clock_ctrl = clock_ctrl;
+
+ if (tg3_flag(tp, 5705_PLUS)) {
+ if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) {
+ tw32_wait_f(TG3PCI_CLOCK_CTRL,
+ clock_ctrl | CLOCK_CTRL_625_CORE, 40);
+ }
+ } else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
+ tw32_wait_f(TG3PCI_CLOCK_CTRL,
+ clock_ctrl |
+ (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK),
+ 40);
+ tw32_wait_f(TG3PCI_CLOCK_CTRL,
+ clock_ctrl | (CLOCK_CTRL_ALTCLK),
+ 40);
+ }
+ tw32_wait_f(TG3PCI_CLOCK_CTRL, clock_ctrl, 40);
+}
+
+int tg3_get_invariants(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 misc_ctrl_reg;
+ u32 pci_state_reg, grc_misc_cfg;
+ u32 val;
+ u16 pci_cmd;
+ int err;
+
+ /* Force memory write invalidate off. If we leave it on,
+ * then on 5700_BX chips we have to enable a workaround.
+ * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary
+ * to match the cacheline size. The Broadcom driver have this
+ * workaround but turns MWI off all the times so never uses
+ * it. This seems to suggest that the workaround is insufficient.
+ */
+ pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
+ pci_cmd &= ~PCI_COMMAND_INVALIDATE;
+ pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+
+ /* It is absolutely critical that TG3PCI_MISC_HOST_CTRL
+ * has the register indirect write enable bit set before
+ * we try to access any of the MMIO registers. It is also
+ * critical that the PCI-X hw workaround situation is decided
+ * before that as well.
+ */
+ pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ &misc_ctrl_reg);
+
+ tp->pci_chip_rev_id = (misc_ctrl_reg >>
+ MISC_HOST_CTRL_CHIPREV_SHIFT);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) {
+ u32 prod_id_asic_rev;
+
+ if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720)
+ pci_read_config_dword(tp->pdev,
+ TG3PCI_GEN2_PRODID_ASICREV,
+ &prod_id_asic_rev);
+ else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795)
+ pci_read_config_dword(tp->pdev,
+ TG3PCI_GEN15_PRODID_ASICREV,
+ &prod_id_asic_rev);
+ else
+ pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV,
+ &prod_id_asic_rev);
+
+ tp->pci_chip_rev_id = prod_id_asic_rev;
+ }
+
+ /* Wrong chip ID in 5752 A0. This code can be removed later
+ * as A0 is not in production.
+ */
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW)
+ tp->pci_chip_rev_id = CHIPREV_ID_5752_A0;
+
+ /* Initialize misc host control in PCI block. */
+ tp->misc_host_ctrl |= (misc_ctrl_reg &
+ MISC_HOST_CTRL_CHIPREV);
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+ tg3_flag_set(tp, 5717_PLUS);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 ||
+ tg3_flag(tp, 5717_PLUS))
+ tg3_flag_set(tp, 57765_PLUS);
+
+ /* Intentionally exclude ASIC_REV_5906 */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+ tg3_flag(tp, 57765_PLUS))
+ tg3_flag_set(tp, 5755_PLUS);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 ||
+ tg3_flag(tp, 5755_PLUS) ||
+ tg3_flag(tp, 5780_CLASS))
+ tg3_flag_set(tp, 5750_PLUS);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+ tg3_flag(tp, 5750_PLUS))
+ tg3_flag_set(tp, 5705_PLUS);
+
+ if (tg3_flag(tp, 5717_PLUS))
+ tg3_flag_set(tp, LRG_PROD_RING_CAP);
+
+ pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
+ &pci_state_reg);
+
+ tp->pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
+ if (tp->pcie_cap != 0) {
+ u16 lnkctl;
+
+ tg3_flag_set(tp, PCI_EXPRESS);
+
+ pci_read_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ &lnkctl);
+ if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_57780_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_57780_A1)
+ tg3_flag_set(tp, CLKREQ_BUG);
+ } else if (tp->pci_chip_rev_id == CHIPREV_ID_5717_A0) {
+ tg3_flag_set(tp, L1PLLPD_EN);
+ }
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+ tg3_flag_set(tp, PCI_EXPRESS);
+ } else if (!tg3_flag(tp, 5705_PLUS) ||
+ tg3_flag(tp, 5780_CLASS)) {
+ tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX);
+ if (!tp->pcix_cap) {
+ DBGC(&tp->pdev->dev,
+ "Cannot find PCI-X capability, aborting\n");
+ return -EIO;
+ }
+
+ if (!(pci_state_reg & PCISTATE_CONV_PCI_MODE))
+ tg3_flag_set(tp, PCIX_MODE);
+ }
+
+ /* If we have an AMD 762 or VIA K8T800 chipset, write
+ * reordering to the mailbox registers done by the host
+ * controller can cause major troubles. We read back from
+ * every mailbox register write to force the writes to be
+ * posted to the chip in order.
+ */
+
+ pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+ &tp->pci_cacheline_sz);
+ pci_read_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+ &tp->pci_lat_timer);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
+ tp->pci_lat_timer < 64) {
+ tp->pci_lat_timer = 64;
+ pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+ tp->pci_lat_timer);
+ }
+
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
+ /* 5700 BX chips need to have their TX producer index
+ * mailboxes written twice to workaround a bug.
+ */
+ tg3_flag_set(tp, TXD_MBOX_HWBUG);
+
+ /* If we are in PCI-X mode, enable register write workaround.
+ *
+ * The workaround is to use indirect register accesses
+ * for all chip writes not to mailbox registers.
+ */
+ if (tg3_flag(tp, PCIX_MODE)) {
+ u32 pm_reg;
+
+ tg3_flag_set(tp, PCIX_TARGET_HWBUG);
+
+ /* The chip can have it's power management PCI config
+ * space registers clobbered due to this bug.
+ * So explicitly force the chip into D0 here.
+ */
+ pci_read_config_dword(tp->pdev,
+ tp->pm_cap + PCI_PM_CTRL,
+ &pm_reg);
+ pm_reg &= ~PCI_PM_CTRL_STATE_MASK;
+ pm_reg |= PCI_PM_CTRL_PME_ENABLE | 0 /* D0 */;
+ pci_write_config_dword(tp->pdev,
+ tp->pm_cap + PCI_PM_CTRL,
+ pm_reg);
+
+ /* Also, force SERR#/PERR# in PCI command. */
+ pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
+ pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+ pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+ }
+ }
+
+ if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
+ tg3_flag_set(tp, PCI_HIGH_SPEED);
+ if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
+ tg3_flag_set(tp, PCI_32BIT);
+
+ /* Chip-specific fixup from Broadcom driver */
+ if ((tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) &&
+ (!(pci_state_reg & PCISTATE_RETRY_SAME_DMA))) {
+ pci_state_reg |= PCISTATE_RETRY_SAME_DMA;
+ pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg);
+ }
+
+ tp->write32_mbox = tg3_write_indirect_reg32;
+ tp->write32_rx_mbox = tg3_write_indirect_mbox;
+ tp->write32_tx_mbox = tg3_write_indirect_mbox;
+ tp->read32_mbox = tg3_read_indirect_mbox;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ tp->read32_mbox = tg3_read32_mbox_5906;
+ tp->write32_mbox = tg3_write32_mbox_5906;
+ tp->write32_tx_mbox = tg3_write32_mbox_5906;
+ tp->write32_rx_mbox = tg3_write32_mbox_5906;
+ }
+
+ /* Get eeprom hw config before calling tg3_set_power_state().
+ * In particular, the TG3_FLAG_IS_NIC flag must be
+ * determined before calling tg3_set_power_state() so that
+ * we know whether or not to switch out of Vaux power.
+ * When the flag is set, it means that GPIO1 is used for eeprom
+ * write protect and also implies that it is a LOM where GPIOs
+ * are not used to switch power.
+ */
+ tg3_get_eeprom_hw_cfg(tp);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+ tg3_flag(tp, 57765_PLUS))
+ tg3_flag_set(tp, CPMU_PRESENT);
+
+ /* Set up tp->grc_local_ctrl before calling tg3_power_up().
+ * GPIO1 driven high will bring 5700's external PHY out of reset.
+ * It is also used as eeprom write protect on LOMs.
+ */
+ tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ tg3_flag(tp, EEPROM_WRITE_PROT))
+ tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OUTPUT1);
+ /* Unused GPIO3 must be driven as output on 5752 because there
+ * are no pull-up resistors on unused GPIO pins.
+ */
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
+
+ if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) {
+ /* Turn off the debug UART. */
+ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
+ if (tg3_flag(tp, IS_NIC))
+ /* Keep VMain power. */
+ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 |
+ GRC_LCLCTRL_GPIO_OUTPUT0;
+ }
+
+ /* Force the chip into D0. */
+ tg3_set_power_state_0(tp);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ tp->phy_flags |= TG3_PHYFLG_IS_FET;
+
+ /* A few boards don't want Ethernet@WireSpeed phy feature */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+ (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) &&
+ (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)) ||
+ (tp->phy_flags & TG3_PHYFLG_IS_FET) ||
+ (tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
+ tp->phy_flags |= TG3_PHYFLG_NO_ETH_WIRE_SPEED;
+
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5703_AX ||
+ GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_AX)
+ tp->phy_flags |= TG3_PHYFLG_ADC_BUG;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
+ tp->phy_flags |= TG3_PHYFLG_5704_A0_BUG;
+
+ if (tg3_flag(tp, 5705_PLUS) &&
+ !(tp->phy_flags & TG3_PHYFLG_IS_FET) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780 &&
+ !tg3_flag(tp, 57765_PLUS)) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) {
+ if (tp->pdev->device != PCI_DEVICE_ID_TIGON3_5756 &&
+ tp->pdev->device != PCI_DEVICE_ID_TIGON3_5722)
+ tp->phy_flags |= TG3_PHYFLG_JITTER_BUG;
+ if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M)
+ tp->phy_flags |= TG3_PHYFLG_ADJUST_TRIM;
+ } else
+ tp->phy_flags |= TG3_PHYFLG_BER_BUG;
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+ GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) {
+ tp->phy_otp = tg3_read_otp_phycfg(tp);
+ if (tp->phy_otp == 0)
+ tp->phy_otp = TG3_OTP_DEFAULT;
+ }
+
+ if (tg3_flag(tp, CPMU_PRESENT))
+ tp->mi_mode = MAC_MI_MODE_500KHZ_CONST;
+ else
+ tp->mi_mode = MAC_MI_MODE_BASE;
+
+ tp->coalesce_mode = 0;
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX &&
+ GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX)
+ tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
+
+ /* Set these bits to enable statistics workaround. */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5719_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5720_A0) {
+ tp->coalesce_mode |= HOSTCC_MODE_ATTN;
+ tp->grc_mode |= GRC_MODE_IRQ_ON_FLOW_ATTN;
+ }
+
+ tg3_mdio_init(tp);
+
+ /* Initialize data/descriptor byte/word swapping. */
+ val = tr32(GRC_MODE);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+ val &= (GRC_MODE_BYTE_SWAP_B2HRX_DATA |
+ GRC_MODE_WORD_SWAP_B2HRX_DATA |
+ GRC_MODE_B2HRX_ENABLE |
+ GRC_MODE_HTX2B_ENABLE |
+ GRC_MODE_HOST_STACKUP);
+ else
+ val &= GRC_MODE_HOST_STACKUP;
+
+ tw32(GRC_MODE, val | tp->grc_mode);
+
+ tg3_switch_clocks(tp);
+
+ /* Clear this out for sanity. */
+ tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+
+ pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
+ &pci_state_reg);
+ if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 &&
+ !tg3_flag(tp, PCIX_TARGET_HWBUG)) {
+ u32 chiprevid = GET_CHIP_REV_ID(tp->misc_host_ctrl);
+
+ if (chiprevid == CHIPREV_ID_5701_A0 ||
+ chiprevid == CHIPREV_ID_5701_B0 ||
+ chiprevid == CHIPREV_ID_5701_B2 ||
+ chiprevid == CHIPREV_ID_5701_B5) {
+ void *sram_base;
+
+ /* Write some dummy words into the SRAM status block
+ * area, see if it reads back correctly. If the return
+ * value is bad, force enable the PCIX workaround.
+ */
+ sram_base = tp->regs + NIC_SRAM_WIN_BASE + NIC_SRAM_STATS_BLK;
+
+ writel(0x00000000, sram_base);
+ writel(0x00000000, sram_base + 4);
+ writel(0xffffffff, sram_base + 4);
+ if (readl(sram_base) != 0x00000000)
+ tg3_flag_set(tp, PCIX_TARGET_HWBUG);
+ }
+ }
+
+ udelay(50);
+ /* FIXME: do we need nvram access? */
+/// tg3_nvram_init(tp);
+
+ grc_misc_cfg = tr32(GRC_MISC_CFG);
+ grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+ (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
+ grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
+ tg3_flag_set(tp, IS_5788);
+
+ if (!tg3_flag(tp, IS_5788) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
+ tg3_flag_set(tp, TAGGED_STATUS);
+ if (tg3_flag(tp, TAGGED_STATUS)) {
+ tp->coalesce_mode |= (HOSTCC_MODE_CLRTICK_RXBD |
+ HOSTCC_MODE_CLRTICK_TXBD);
+
+ tp->misc_host_ctrl |= MISC_HOST_CTRL_TAGGED_STATUS;
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
+ }
+
+ /* Preserve the APE MAC_MODE bits */
+ if (tg3_flag(tp, ENABLE_APE))
+ tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+ else
+ tp->mac_mode = TG3_DEF_MAC_MODE;
+
+ /* these are limited to 10/100 only */
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
+ (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+ tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
+ (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 ||
+ tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 ||
+ tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
+ (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
+ (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
+ tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F ||
+ tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 ||
+ (tp->phy_flags & TG3_PHYFLG_IS_FET))
+ tp->phy_flags |= TG3_PHYFLG_10_100_ONLY;
+
+ err = tg3_phy_probe(tp);
+ if (err) {
+ DBGC(&tp->pdev->dev, "phy probe failed, err: %s\n", strerror(err));
+ /* ... but do not return immediately ... */
+ }
+
+ if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
+ tp->phy_flags &= ~TG3_PHYFLG_USE_MI_INTERRUPT;
+ } else {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
+ tp->phy_flags |= TG3_PHYFLG_USE_MI_INTERRUPT;
+ else
+ tp->phy_flags &= ~TG3_PHYFLG_USE_MI_INTERRUPT;
+ }
+
+ /* For all SERDES we poll the MAC status register. */
+ if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)
+ tg3_flag_set(tp, POLL_SERDES);
+ else
+ tg3_flag_clear(tp, POLL_SERDES);
+
+ /* Increment the rx prod index on the rx std ring by at most
+ * 8 for these chips to workaround hw errata.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+ tp->rx_std_max_post = 8;
+
+ return err;
+}
+
+void tg3_init_bufmgr_config(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, 57765_PLUS)) {
+ tp->bufmgr_config.mbuf_read_dma_low_water =
+ DEFAULT_MB_RDMA_LOW_WATER_5705;
+ tp->bufmgr_config.mbuf_mac_rx_low_water =
+ DEFAULT_MB_MACRX_LOW_WATER_57765;
+ tp->bufmgr_config.mbuf_high_water =
+ DEFAULT_MB_HIGH_WATER_57765;
+
+ tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
+ DEFAULT_MB_RDMA_LOW_WATER_5705;
+ tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo =
+ DEFAULT_MB_MACRX_LOW_WATER_JUMBO_57765;
+ tp->bufmgr_config.mbuf_high_water_jumbo =
+ DEFAULT_MB_HIGH_WATER_JUMBO_57765;
+ } else if (tg3_flag(tp, 5705_PLUS)) {
+ tp->bufmgr_config.mbuf_read_dma_low_water =
+ DEFAULT_MB_RDMA_LOW_WATER_5705;
+ tp->bufmgr_config.mbuf_mac_rx_low_water =
+ DEFAULT_MB_MACRX_LOW_WATER_5705;
+ tp->bufmgr_config.mbuf_high_water =
+ DEFAULT_MB_HIGH_WATER_5705;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ tp->bufmgr_config.mbuf_mac_rx_low_water =
+ DEFAULT_MB_MACRX_LOW_WATER_5906;
+ tp->bufmgr_config.mbuf_high_water =
+ DEFAULT_MB_HIGH_WATER_5906;
+ }
+
+ tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
+ DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780;
+ tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo =
+ DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780;
+ tp->bufmgr_config.mbuf_high_water_jumbo =
+ DEFAULT_MB_HIGH_WATER_JUMBO_5780;
+ } else {
+ tp->bufmgr_config.mbuf_read_dma_low_water =
+ DEFAULT_MB_RDMA_LOW_WATER;
+ tp->bufmgr_config.mbuf_mac_rx_low_water =
+ DEFAULT_MB_MACRX_LOW_WATER;
+ tp->bufmgr_config.mbuf_high_water =
+ DEFAULT_MB_HIGH_WATER;
+
+ tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
+ DEFAULT_MB_RDMA_LOW_WATER_JUMBO;
+ tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo =
+ DEFAULT_MB_MACRX_LOW_WATER_JUMBO;
+ tp->bufmgr_config.mbuf_high_water_jumbo =
+ DEFAULT_MB_HIGH_WATER_JUMBO;
+ }
+
+ tp->bufmgr_config.dma_low_water = DEFAULT_DMA_LOW_WATER;
+ tp->bufmgr_config.dma_high_water = DEFAULT_DMA_HIGH_WATER;
+}
+
+#define TG3_FW_EVENT_TIMEOUT_USEC 2500
+
+void tg3_wait_for_event_ack(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int i;
+
+ for (i = 0; i < TG3_FW_EVENT_TIMEOUT_USEC / 10; i++) {
+ if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT))
+ break;
+
+ udelay(10);
+ }
+}
+
+void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
+{ DBGP("%s\n", __func__);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
+ (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC))
+ return;
+
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+
+ /* Always leave this as zero. */
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+}
+
+static void tg3_stop_fw(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, ENABLE_ASF) && !tg3_flag(tp, ENABLE_APE)) {
+ /* Wait for RX cpu to ACK the previous event. */
+ tg3_wait_for_event_ack(tp);
+
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
+
+ tg3_generate_fw_event(tp);
+
+ /* Wait for RX cpu to ACK this event. */
+ tg3_wait_for_event_ack(tp);
+ }
+}
+
+static void tg3_write_sig_pre_reset(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
+ NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
+}
+
+void tg3_disable_ints(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ tw32(TG3PCI_MISC_HOST_CTRL,
+ (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
+
+ tw32_mailbox_f(tp->int_mbox, 0x00000001);
+}
+
+void tg3_enable_ints(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ tw32(TG3PCI_MISC_HOST_CTRL,
+ (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
+
+ tp->coal_now = tp->coalesce_mode | HOSTCC_MODE_ENABLE;
+
+ tw32_mailbox_f(tp->int_mbox, tp->last_tag << 24);
+
+ /* Force an initial interrupt */
+ if (!tg3_flag(tp, TAGGED_STATUS) &&
+ (tp->hw_status->status & SD_STATUS_UPDATED))
+ tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+ else
+ tw32(HOSTCC_MODE, tp->coal_now);
+}
+
+#define MAX_WAIT_CNT 1000
+
+/* To stop a block, clear the enable bit and poll till it clears. */
+static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit)
+{ DBGP("%s\n", __func__);
+
+ unsigned int i;
+ u32 val;
+
+ if (tg3_flag(tp, 5705_PLUS)) {
+ switch (ofs) {
+ case RCVLSC_MODE:
+ case DMAC_MODE:
+ case MBFREE_MODE:
+ case BUFMGR_MODE:
+ case MEMARB_MODE:
+ /* We can't enable/disable these bits of the
+ * 5705/5750, just say success.
+ */
+ return 0;
+
+ default:
+ break;
+ }
+ }
+
+ val = tr32(ofs);
+ val &= ~enable_bit;
+ tw32_f(ofs, val);
+
+ for (i = 0; i < MAX_WAIT_CNT; i++) {
+ udelay(100);
+ val = tr32(ofs);
+ if ((val & enable_bit) == 0)
+ break;
+ }
+
+ if (i == MAX_WAIT_CNT) {
+ DBGC(&tp->pdev->dev,
+ "tg3_stop_block timed out, ofs=%lx enable_bit=%x\n",
+ ofs, enable_bit);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int tg3_abort_hw(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int i, err;
+
+ tg3_disable_ints(tp);
+
+ tp->rx_mode &= ~RX_MODE_ENABLE;
+ tw32_f(MAC_RX_MODE, tp->rx_mode);
+ udelay(10);
+
+ err = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE);
+ err |= tg3_stop_block(tp, RCVLPC_MODE, RCVLPC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, RCVLSC_MODE, RCVLSC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, RCVDBDI_MODE, RCVDBDI_MODE_ENABLE);
+ err |= tg3_stop_block(tp, RCVDCC_MODE, RCVDCC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, RCVCC_MODE, RCVCC_MODE_ENABLE);
+
+ err |= tg3_stop_block(tp, SNDBDS_MODE, SNDBDS_MODE_ENABLE);
+ err |= tg3_stop_block(tp, SNDBDI_MODE, SNDBDI_MODE_ENABLE);
+ err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
+ err |= tg3_stop_block(tp, RDMAC_MODE, RDMAC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, DMAC_MODE, DMAC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, SNDBDC_MODE, SNDBDC_MODE_ENABLE);
+
+ tp->mac_mode &= ~MAC_MODE_TDE_ENABLE;
+ tw32_f(MAC_MODE, tp->mac_mode);
+ udelay(40);
+
+ tp->tx_mode &= ~TX_MODE_ENABLE;
+ tw32_f(MAC_TX_MODE, tp->tx_mode);
+
+ for (i = 0; i < MAX_WAIT_CNT; i++) {
+ udelay(100);
+ if (!(tr32(MAC_TX_MODE) & TX_MODE_ENABLE))
+ break;
+ }
+ if (i >= MAX_WAIT_CNT) {
+ DBGC(&tp->pdev->dev,
+ "%s timed out, TX_MODE_ENABLE will not clear "
+ "MAC_TX_MODE=%08x\n", __func__, tr32(MAC_TX_MODE));
+ err |= -ENODEV;
+ }
+
+ err |= tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, WDMAC_MODE, WDMAC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE);
+
+ tw32(FTQ_RESET, 0xffffffff);
+ tw32(FTQ_RESET, 0x00000000);
+
+ err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE);
+ err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE);
+
+ if (tp->hw_status)
+ memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+ return err;
+}
+
+void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
+{ DBGP("%s\n", __func__);
+
+ u32 addr_high, addr_low;
+ int i;
+
+ addr_high = ((tp->dev->ll_addr[0] << 8) |
+ tp->dev->ll_addr[1]);
+ addr_low = ((tp->dev->ll_addr[2] << 24) |
+ (tp->dev->ll_addr[3] << 16) |
+ (tp->dev->ll_addr[4] << 8) |
+ (tp->dev->ll_addr[5] << 0));
+ for (i = 0; i < 4; i++) {
+ if (i == 1 && skip_mac_1)
+ continue;
+ tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
+ tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+ for (i = 0; i < 12; i++) {
+ tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
+ tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
+ }
+ }
+
+ addr_high = (tp->dev->ll_addr[0] +
+ tp->dev->ll_addr[1] +
+ tp->dev->ll_addr[2] +
+ tp->dev->ll_addr[3] +
+ tp->dev->ll_addr[4] +
+ tp->dev->ll_addr[5]) &
+ TX_BACKOFF_SEED_MASK;
+ tw32(MAC_TX_BACKOFF_SEED, addr_high);
+}
+
+/* Save PCI command register before chip reset */
+static void tg3_save_pci_state(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ pci_read_config_word(tp->pdev, PCI_COMMAND, &tp->pci_cmd);
+}
+
+/* Restore PCI state after chip reset */
+static void tg3_restore_pci_state(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 val;
+
+ /* Re-enable indirect register accesses. */
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
+
+ /* Set MAX PCI retry to zero. */
+ val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
+ tg3_flag(tp, PCIX_MODE))
+ val |= PCISTATE_RETRY_SAME_DMA;
+
+ pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
+
+ pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) {
+ pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+ tp->pci_cacheline_sz);
+ pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+ tp->pci_lat_timer);
+ }
+
+
+ /* Make sure PCI-X relaxed ordering bit is clear. */
+ if (tg3_flag(tp, PCIX_MODE)) {
+ u16 pcix_cmd;
+
+ pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+ &pcix_cmd);
+ pcix_cmd &= ~PCI_X_CMD_ERO;
+ pci_write_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+ pcix_cmd);
+ }
+}
+
+static int tg3_poll_fw(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int i;
+ u32 val;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ /* Wait up to 20ms for init done. */
+ for (i = 0; i < 200; i++) {
+ if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE)
+ return 0;
+ udelay(100);
+ }
+ return -ENODEV;
+ }
+
+ /* Wait for firmware initialization to complete. */
+ for (i = 0; i < 100000; i++) {
+ tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
+ if (val == (u32)~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
+ break;
+ udelay(10);
+ }
+
+ /* Chip might not be fitted with firmware. Some Sun onboard
+ * parts are configured like that. So don't signal the timeout
+ * of the above loop as an error, but do report the lack of
+ * running firmware once.
+ */
+ if (i >= 100000 && !tg3_flag(tp, NO_FWARE_REPORTED)) {
+ tg3_flag_set(tp, NO_FWARE_REPORTED);
+
+ DBGC(tp->dev, "No firmware running\n");
+ }
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) {
+ /* The 57765 A0 needs a little more
+ * time to do some important work.
+ */
+ mdelay(10);
+ }
+
+ return 0;
+}
+
+static int tg3_nvram_lock(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, NVRAM)) {
+ int i;
+
+ if (tp->nvram_lock_cnt == 0) {
+ tw32(NVRAM_SWARB, SWARB_REQ_SET1);
+ for (i = 0; i < 8000; i++) {
+ if (tr32(NVRAM_SWARB) & SWARB_GNT1)
+ break;
+ udelay(20);
+ }
+ if (i == 8000) {
+ tw32(NVRAM_SWARB, SWARB_REQ_CLR1);
+ return -ENODEV;
+ }
+ }
+ tp->nvram_lock_cnt++;
+ }
+ return 0;
+}
+
+static void tg3_nvram_unlock(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, NVRAM)) {
+ if (tp->nvram_lock_cnt > 0)
+ tp->nvram_lock_cnt--;
+ if (tp->nvram_lock_cnt == 0)
+ tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1);
+ }
+}
+
+static int tg3_chip_reset(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 val;
+ int err;
+
+ tg3_nvram_lock(tp);
+
+
+ /* No matching tg3_nvram_unlock() after this because
+ * chip reset below will undo the nvram lock.
+ */
+ tp->nvram_lock_cnt = 0;
+
+ /* GRC_MISC_CFG core clock reset will clear the memory
+ * enable bit in PCI register 4 and the MSI enable bit
+ * on some chips, so we save relevant registers here.
+ */
+ tg3_save_pci_state(tp);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+ tg3_flag(tp, 5755_PLUS))
+ tw32(GRC_FASTBOOT_PC, 0);
+
+#if 0
+ /*
+ * We must avoid the readl() that normally takes place.
+ * It locks machines, causes machine checks, and other
+ * fun things. So, temporarily disable the 5701
+ * hardware workaround, while we do the reset.
+ */
+ write_op = tp->write32;
+ if (write_op == tg3_write_flush_reg32)
+ tp->write32 = tg3_write32;
+#endif
+
+ /* Prevent the irq handler from reading or writing PCI registers
+ * during chip reset when the memory enable bit in the PCI command
+ * register may be cleared. The chip does not generate interrupt
+ * at this time, but the irq handler may still be called due to irq
+ * sharing or irqpoll.
+ */
+ tg3_flag_set(tp, CHIP_RESETTING);
+
+ if (tp->hw_status) {
+ tp->hw_status->status = 0;
+ tp->hw_status->status_tag = 0;
+ }
+ tp->last_tag = 0;
+ tp->last_irq_tag = 0;
+
+ mb();
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
+ val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
+ tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS);
+ }
+
+ /* do the reset */
+ val = GRC_MISC_CFG_CORECLK_RESET;
+
+ if (tg3_flag(tp, PCI_EXPRESS)) {
+ /* Force PCIe 1.0a mode */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+ !tg3_flag(tp, 57765_PLUS) &&
+ tr32(TG3_PCIE_PHY_TSTCTL) ==
+ (TG3_PCIE_PHY_TSTCTL_PCIE10 | TG3_PCIE_PHY_TSTCTL_PSCRAM))
+ tw32(TG3_PCIE_PHY_TSTCTL, TG3_PCIE_PHY_TSTCTL_PSCRAM);
+
+ if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
+ tw32(GRC_MISC_CFG, (1 << 29));
+ val |= (1 << 29);
+ }
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ tw32(VCPU_STATUS, tr32(VCPU_STATUS) | VCPU_STATUS_DRV_RESET);
+ tw32(GRC_VCPU_EXT_CTRL,
+ tr32(GRC_VCPU_EXT_CTRL) & ~GRC_VCPU_EXT_CTRL_HALT_CPU);
+ }
+
+ /* Manage gphy power for all CPMU absent PCIe devices. */
+ if (tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, CPMU_PRESENT))
+ val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
+
+ tw32(GRC_MISC_CFG, val);
+
+ /* Unfortunately, we have to delay before the PCI read back.
+ * Some 575X chips even will not respond to a PCI cfg access
+ * when the reset command is given to the chip.
+ *
+ * How do these hardware designers expect things to work
+ * properly if the PCI write is posted for a long period
+ * of time? It is always necessary to have some method by
+ * which a register read back can occur to push the write
+ * out which does the reset.
+ *
+ * For most tg3 variants the trick below was working.
+ * Ho hum...
+ */
+ udelay(120);
+
+ /* Flush PCI posted writes. The normal MMIO registers
+ * are inaccessible at this time so this is the only
+ * way to make this reliably (actually, this is no longer
+ * the case, see above). I tried to use indirect
+ * register read/write but this upset some 5701 variants.
+ */
+ pci_read_config_dword(tp->pdev, PCI_COMMAND, &val);
+
+ udelay(120);
+
+ if (tg3_flag(tp, PCI_EXPRESS) && tp->pcie_cap) {
+ u16 val16;
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
+ int i;
+ u32 cfg_val;
+
+ /* Wait for link training to complete. */
+ for (i = 0; i < 5000; i++)
+ udelay(100);
+
+ pci_read_config_dword(tp->pdev, 0xc4, &cfg_val);
+ pci_write_config_dword(tp->pdev, 0xc4,
+ cfg_val | (1 << 15));
+ }
+
+ /* Clear the "no snoop" and "relaxed ordering" bits. */
+ pci_read_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_DEVCTL,
+ &val16);
+ val16 &= ~(PCI_EXP_DEVCTL_RELAX_EN |
+ PCI_EXP_DEVCTL_NOSNOOP_EN);
+ /*
+ * Older PCIe devices only support the 128 byte
+ * MPS setting. Enforce the restriction.
+ */
+ if (!tg3_flag(tp, CPMU_PRESENT))
+ val16 &= ~PCI_EXP_DEVCTL_PAYLOAD;
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_DEVCTL,
+ val16);
+
+ /* Clear error status */
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_DEVSTA,
+ PCI_EXP_DEVSTA_CED |
+ PCI_EXP_DEVSTA_NFED |
+ PCI_EXP_DEVSTA_FED |
+ PCI_EXP_DEVSTA_URD);
+ }
+
+ tg3_restore_pci_state(tp);
+
+ tg3_flag_clear(tp, CHIP_RESETTING);
+ tg3_flag_clear(tp, ERROR_PROCESSED);
+
+ val = 0;
+ if (tg3_flag(tp, 5780_CLASS))
+ val = tr32(MEMARB_MODE);
+ tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
+ tg3_stop_fw(tp);
+ tw32(0x5000, 0x400);
+ }
+
+ tw32(GRC_MODE, tp->grc_mode);
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
+ val = tr32(0xc4);
+
+ tw32(0xc4, val | (1 << 15));
+ }
+
+ if ((tp->nic_sram_data_cfg & NIC_SRAM_DATA_CFG_MINI_PCI) != 0 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+ tp->pci_clock_ctrl |= CLOCK_CTRL_CLKRUN_OENABLE;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0)
+ tp->pci_clock_ctrl |= CLOCK_CTRL_FORCE_CLKRUN;
+ tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
+ }
+
+ if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
+ tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
+ val = tp->mac_mode;
+ } else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) {
+ tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+ val = tp->mac_mode;
+ } else
+ val = 0;
+
+ tw32_f(MAC_MODE, val);
+ udelay(40);
+
+ err = tg3_poll_fw(tp);
+ if (err)
+ return err;
+
+ if (tg3_flag(tp, PCI_EXPRESS) &&
+ tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+ !tg3_flag(tp, 57765_PLUS)) {
+ val = tr32(0x7c00);
+
+ tw32(0x7c00, val | (1 << 25));
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+ val = tr32(TG3_CPMU_CLCK_ORIDE);
+ tw32(TG3_CPMU_CLCK_ORIDE, val & ~CPMU_CLCK_ORIDE_MAC_ORIDE_EN);
+ }
+
+ return 0;
+}
+
+int tg3_halt(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int err;
+
+ tg3_stop_fw(tp);
+
+ tg3_write_sig_pre_reset(tp);
+
+ tg3_abort_hw(tp);
+ err = tg3_chip_reset(tp);
+
+ __tg3_set_mac_addr(tp, 0);
+
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int tg3_nvram_read_using_eeprom(struct tg3 *tp,
+ u32 offset, u32 *val)
+{ DBGP("%s\n", __func__);
+
+ u32 tmp;
+ int i;
+
+ if (offset > EEPROM_ADDR_ADDR_MASK || (offset % 4) != 0)
+ return -EINVAL;
+
+ tmp = tr32(GRC_EEPROM_ADDR) & ~(EEPROM_ADDR_ADDR_MASK |
+ EEPROM_ADDR_DEVID_MASK |
+ EEPROM_ADDR_READ);
+ tw32(GRC_EEPROM_ADDR,
+ tmp |
+ (0 << EEPROM_ADDR_DEVID_SHIFT) |
+ ((offset << EEPROM_ADDR_ADDR_SHIFT) &
+ EEPROM_ADDR_ADDR_MASK) |
+ EEPROM_ADDR_READ | EEPROM_ADDR_START);
+
+ for (i = 0; i < 1000; i++) {
+ tmp = tr32(GRC_EEPROM_ADDR);
+
+ if (tmp & EEPROM_ADDR_COMPLETE)
+ break;
+ mdelay(1);
+ }
+ if (!(tmp & EEPROM_ADDR_COMPLETE))
+ return -EBUSY;
+
+ tmp = tr32(GRC_EEPROM_DATA);
+
+ /*
+ * The data will always be opposite the native endian
+ * format. Perform a blind byteswap to compensate.
+ */
+ *val = bswap_32(tmp);
+
+ return 0;
+}
+
+static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, NVRAM) &&
+ tg3_flag(tp, NVRAM_BUFFERED) &&
+ tg3_flag(tp, FLASH) &&
+ !tg3_flag(tp, NO_NVRAM_ADDR_TRANS) &&
+ (tp->nvram_jedecnum == JEDEC_ATMEL))
+
+ addr = ((addr / tp->nvram_pagesize) <<
+ ATMEL_AT45DB0X1B_PAGE_POS) +
+ (addr % tp->nvram_pagesize);
+
+ return addr;
+}
+
+static void tg3_enable_nvram_access(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) {
+ u32 nvaccess = tr32(NVRAM_ACCESS);
+
+ tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
+ }
+}
+
+static void tg3_disable_nvram_access(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) {
+ u32 nvaccess = tr32(NVRAM_ACCESS);
+
+ tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
+ }
+}
+
+#define NVRAM_CMD_TIMEOUT 10000
+
+static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd)
+{ DBGP("%s\n", __func__);
+
+ int i;
+
+ tw32(NVRAM_CMD, nvram_cmd);
+ for (i = 0; i < NVRAM_CMD_TIMEOUT; i++) {
+ udelay(10);
+ if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) {
+ udelay(10);
+ break;
+ }
+ }
+
+ if (i == NVRAM_CMD_TIMEOUT)
+ return -EBUSY;
+
+ return 0;
+}
+
+/* NOTE: Data read in from NVRAM is byteswapped according to
+ * the byteswapping settings for all other register accesses.
+ * tg3 devices are BE devices, so on a BE machine, the data
+ * returned will be exactly as it is seen in NVRAM. On a LE
+ * machine, the 32-bit value will be byteswapped.
+ */
+static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
+{ DBGP("%s\n", __func__);
+
+ int ret;
+
+ if (!tg3_flag(tp, NVRAM))
+ return tg3_nvram_read_using_eeprom(tp, offset, val);
+
+ offset = tg3_nvram_phys_addr(tp, offset);
+
+ if (offset > NVRAM_ADDR_MSK)
+ return -EINVAL;
+
+ ret = tg3_nvram_lock(tp);
+ if (ret)
+ return ret;
+
+ tg3_enable_nvram_access(tp);
+
+ tw32(NVRAM_ADDR, offset);
+ ret = tg3_nvram_exec_cmd(tp, NVRAM_CMD_RD | NVRAM_CMD_GO |
+ NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
+
+ if (ret == 0)
+ *val = tr32(NVRAM_RDDATA);
+
+ tg3_disable_nvram_access(tp);
+
+ tg3_nvram_unlock(tp);
+
+ return ret;
+}
+
+/* Ensures NVRAM data is in bytestream format. */
+static int tg3_nvram_read_be32(struct tg3 *tp, u32 offset, u32 *val)
+{ DBGP("%s\n", __func__);
+
+ u32 v = 0;
+ int res = tg3_nvram_read(tp, offset, &v);
+ if (!res)
+ *val = cpu_to_be32(v);
+ return res;
+}
+
+int tg3_get_device_address(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ struct net_device *dev = tp->dev;
+ u32 hi, lo, mac_offset;
+ int addr_ok = 0;
+
+ mac_offset = 0x7c;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+ tg3_flag(tp, 5780_CLASS)) {
+ if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
+ mac_offset = 0xcc;
+ if (tg3_nvram_lock(tp))
+ tw32_f(NVRAM_CMD, NVRAM_CMD_RESET);
+ else
+ tg3_nvram_unlock(tp);
+ } else if (tg3_flag(tp, 5717_PLUS)) {
+ if (PCI_FUNC(tp->pdev->busdevfn) & 1)
+ mac_offset = 0xcc;
+ if (PCI_FUNC(tp->pdev->busdevfn) > 1)
+ mac_offset += 0x18c;
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ mac_offset = 0x10;
+
+ /* First try to get it from MAC address mailbox. */
+ tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi);
+ if ((hi >> 16) == 0x484b) {
+ dev->hw_addr[0] = (hi >> 8) & 0xff;
+ dev->hw_addr[1] = (hi >> 0) & 0xff;
+
+ tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_LOW_MBOX, &lo);
+ dev->hw_addr[2] = (lo >> 24) & 0xff;
+ dev->hw_addr[3] = (lo >> 16) & 0xff;
+ dev->hw_addr[4] = (lo >> 8) & 0xff;
+ dev->hw_addr[5] = (lo >> 0) & 0xff;
+
+ /* Some old bootcode may report a 0 MAC address in SRAM */
+ addr_ok = is_valid_ether_addr(&dev->hw_addr[0]);
+ }
+ if (!addr_ok) {
+ /* Next, try NVRAM. */
+ if (!tg3_flag(tp, NO_NVRAM) &&
+ !tg3_nvram_read_be32(tp, mac_offset + 0, &hi) &&
+ !tg3_nvram_read_be32(tp, mac_offset + 4, &lo)) {
+ memcpy(&dev->hw_addr[0], ((char *)&hi) + 2, 2);
+ memcpy(&dev->hw_addr[2], (char *)&lo, sizeof(lo));
+ }
+ /* Finally just fetch it out of the MAC control regs. */
+ else {
+ hi = tr32(MAC_ADDR_0_HIGH);
+ lo = tr32(MAC_ADDR_0_LOW);
+
+ dev->hw_addr[5] = lo & 0xff;
+ dev->hw_addr[4] = (lo >> 8) & 0xff;
+ dev->hw_addr[3] = (lo >> 16) & 0xff;
+ dev->hw_addr[2] = (lo >> 24) & 0xff;
+ dev->hw_addr[1] = hi & 0xff;
+ dev->hw_addr[0] = (hi >> 8) & 0xff;
+ }
+ }
+
+ if (!is_valid_ether_addr(&dev->hw_addr[0])) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void __tg3_set_rx_mode(struct net_device *dev)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+ u32 rx_mode;
+
+ rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC |
+ RX_MODE_KEEP_VLAN_TAG);
+
+ rx_mode |= RX_MODE_KEEP_VLAN_TAG;
+
+ /* Accept all multicast. */
+ tw32(MAC_HASH_REG_0, 0xffffffff);
+ tw32(MAC_HASH_REG_1, 0xffffffff);
+ tw32(MAC_HASH_REG_2, 0xffffffff);
+ tw32(MAC_HASH_REG_3, 0xffffffff);
+
+ if (rx_mode != tp->rx_mode) {
+ tp->rx_mode = rx_mode;
+ tw32_f(MAC_RX_MODE, rx_mode);
+ udelay(10);
+ }
+}
+
+static void __tg3_set_coalesce(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+
+ tw32(HOSTCC_RXCOL_TICKS, 0);
+ tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS);
+ tw32(HOSTCC_RXMAX_FRAMES, 1);
+ /* FIXME: mix between TXMAX and RXMAX taken from legacy driver */
+ tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES);
+ tw32(HOSTCC_RXCOAL_MAXF_INT, 1);
+ tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
+
+ if (!tg3_flag(tp, 5705_PLUS)) {
+ u32 val = DEFAULT_STAT_COAL_TICKS;
+
+ tw32(HOSTCC_RXCOAL_TICK_INT, DEFAULT_RXCOAL_TICK_INT);
+ tw32(HOSTCC_TXCOAL_TICK_INT, DEFAULT_TXCOAL_TICK_INT);
+
+ if (!netdev_link_ok(tp->dev))
+ val = 0;
+
+ tw32(HOSTCC_STAT_COAL_TICKS, val);
+ }
+}
+
+static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,
+ dma_addr_t mapping, u32 maxlen_flags,
+ u32 nic_addr)
+{ DBGP("%s\n", __func__);
+
+ tg3_write_mem(tp,
+ (bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH),
+ ((u64) mapping >> 32));
+ tg3_write_mem(tp,
+ (bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW),
+ ((u64) mapping & 0xffffffff));
+ tg3_write_mem(tp,
+ (bdinfo_addr + TG3_BDINFO_MAXLEN_FLAGS),
+ maxlen_flags);
+
+ if (!tg3_flag(tp, 5705_PLUS))
+ tg3_write_mem(tp,
+ (bdinfo_addr + TG3_BDINFO_NIC_ADDR),
+ nic_addr);
+}
+
+static void tg3_rings_reset(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int i;
+ u32 txrcb, rxrcb, limit;
+
+ /* Disable all transmit rings but the first. */
+ if (!tg3_flag(tp, 5705_PLUS))
+ limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16;
+ else if (tg3_flag(tp, 5717_PLUS))
+ limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 4;
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+ limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2;
+ else
+ limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE;
+
+ for (txrcb = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE;
+ txrcb < limit; txrcb += TG3_BDINFO_SIZE)
+ tg3_write_mem(tp, txrcb + TG3_BDINFO_MAXLEN_FLAGS,
+ BDINFO_FLAGS_DISABLED);
+
+
+ /* Disable all receive return rings but the first. */
+ if (tg3_flag(tp, 5717_PLUS))
+ limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 17;
+ else if (!tg3_flag(tp, 5705_PLUS))
+ limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16;
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+ limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 4;
+ else
+ limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE;
+
+ for (rxrcb = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE;
+ rxrcb < limit; rxrcb += TG3_BDINFO_SIZE)
+ tg3_write_mem(tp, rxrcb + TG3_BDINFO_MAXLEN_FLAGS,
+ BDINFO_FLAGS_DISABLED);
+
+ /* Disable interrupts */
+ tw32_mailbox_f(tp->int_mbox, 1);
+
+ tp->tx_prod = 0;
+ tp->tx_cons = 0;
+ tw32_mailbox(tp->prodmbox, 0);
+ tw32_rx_mbox(tp->consmbox, 0);
+
+ /* Make sure the NIC-based send BD rings are disabled. */
+ if (!tg3_flag(tp, 5705_PLUS)) {
+ u32 mbox = MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW;
+ for (i = 0; i < 16; i++)
+ tw32_tx_mbox(mbox + i * 8, 0);
+ }
+
+ txrcb = NIC_SRAM_SEND_RCB;
+ rxrcb = NIC_SRAM_RCV_RET_RCB;
+
+ /* Clear status block in ram. */
+ memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+ /* Set status block DMA address */
+ tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
+ ((u64) tp->status_mapping >> 32));
+ tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
+ ((u64) tp->status_mapping & 0xffffffff));
+
+ if (tp->tx_ring) {
+ tg3_set_bdinfo(tp, txrcb, tp->tx_desc_mapping,
+ (TG3_TX_RING_SIZE <<
+ BDINFO_FLAGS_MAXLEN_SHIFT),
+ NIC_SRAM_TX_BUFFER_DESC);
+ txrcb += TG3_BDINFO_SIZE;
+ }
+
+ /* FIXME: will TG3_RX_RET_MAX_SIZE_5705 work on all cards? */
+ if (tp->rx_rcb) {
+ tg3_set_bdinfo(tp, rxrcb, tp->rx_rcb_mapping,
+ TG3_RX_RET_MAX_SIZE_5705 <<
+ BDINFO_FLAGS_MAXLEN_SHIFT, 0);
+ rxrcb += TG3_BDINFO_SIZE;
+ }
+}
+
+static void tg3_setup_rxbd_thresholds(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 val, bdcache_maxcnt;
+
+ if (!tg3_flag(tp, 5750_PLUS) ||
+ tg3_flag(tp, 5780_CLASS) ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+ bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5700;
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5755;
+ else
+ bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5906;
+
+
+ /* NOTE: legacy driver uses RX_PENDING / 8, we only use 4 descriptors
+ * for now, use / 4 so the result is > 0
+ */
+ val = TG3_DEF_RX_RING_PENDING / 4;
+ tw32(RCVBDI_STD_THRESH, val);
+
+ if (tg3_flag(tp, 57765_PLUS))
+ tw32(STD_REPLENISH_LWM, bdcache_maxcnt);
+}
+
+static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
+{ DBGP("%s\n", __func__);
+
+ u32 val, rdmac_mode;
+ int i, err, limit;
+ struct tg3_rx_prodring_set *tpr = &tp->prodring;
+
+ tg3_stop_fw(tp);
+
+ tg3_write_sig_pre_reset(tp);
+
+ if (tg3_flag(tp, INIT_COMPLETE))
+ tg3_abort_hw(tp);
+
+ if (reset_phy)
+ tg3_phy_reset(tp);
+
+ err = tg3_chip_reset(tp);
+ if (err)
+ return err;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
+ val = tr32(PCIE_PWR_MGMT_THRESH) & ~PCIE_PWR_MGMT_L1_THRESH_MSK;
+ val |= PCIE_PWR_MGMT_EXT_ASPM_TMR_EN |
+ PCIE_PWR_MGMT_L1_THRESH_4MS;
+ tw32(PCIE_PWR_MGMT_THRESH, val);
+
+ val = tr32(TG3_PCIE_EIDLE_DELAY) & ~TG3_PCIE_EIDLE_DELAY_MASK;
+ tw32(TG3_PCIE_EIDLE_DELAY, val | TG3_PCIE_EIDLE_DELAY_13_CLKS);
+
+ tw32(TG3_CORR_ERR_STAT, TG3_CORR_ERR_STAT_CLEAR);
+
+ val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
+ tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS);
+ }
+
+ if (tg3_flag(tp, L1PLLPD_EN)) {
+ u32 grc_mode = tr32(GRC_MODE);
+
+ /* Access the lower 1K of PL PCIE block registers. */
+ val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
+ tw32(GRC_MODE, val | GRC_MODE_PCIE_PL_SEL);
+
+ val = tr32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL1);
+ tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL1,
+ val | TG3_PCIE_PL_LO_PHYCTL1_L1PLLPD_EN);
+
+ tw32(GRC_MODE, grc_mode);
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) {
+ if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) {
+ u32 grc_mode = tr32(GRC_MODE);
+
+ /* Access the lower 1K of PL PCIE block registers. */
+ val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
+ tw32(GRC_MODE, val | GRC_MODE_PCIE_PL_SEL);
+
+ val = tr32(TG3_PCIE_TLDLPL_PORT +
+ TG3_PCIE_PL_LO_PHYCTL5);
+ tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL5,
+ val | TG3_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ);
+
+ tw32(GRC_MODE, grc_mode);
+ }
+
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_57765_AX) {
+ u32 grc_mode = tr32(GRC_MODE);
+
+ /* Access the lower 1K of DL PCIE block registers. */
+ val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
+ tw32(GRC_MODE, val | GRC_MODE_PCIE_DL_SEL);
+
+ val = tr32(TG3_PCIE_TLDLPL_PORT +
+ TG3_PCIE_DL_LO_FTSMAX);
+ val &= ~TG3_PCIE_DL_LO_FTSMAX_MSK;
+ tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_DL_LO_FTSMAX,
+ val | TG3_PCIE_DL_LO_FTSMAX_VAL);
+
+ tw32(GRC_MODE, grc_mode);
+ }
+
+ val = tr32(TG3_CPMU_LSPD_10MB_CLK);
+ val &= ~CPMU_LSPD_10MB_MACCLK_MASK;
+ val |= CPMU_LSPD_10MB_MACCLK_6_25;
+ tw32(TG3_CPMU_LSPD_10MB_CLK, val);
+ }
+
+ /* This works around an issue with Athlon chipsets on
+ * B3 tigon3 silicon. This bit has no effect on any
+ * other revision. But do not set this on PCI Express
+ * chips and don't even touch the clocks if the CPMU is present.
+ */
+ if (!tg3_flag(tp, CPMU_PRESENT)) {
+ if (!tg3_flag(tp, PCI_EXPRESS))
+ tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
+ tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
+ }
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
+ tg3_flag(tp, PCIX_MODE)) {
+ val = tr32(TG3PCI_PCISTATE);
+ val |= PCISTATE_RETRY_SAME_DMA;
+ tw32(TG3PCI_PCISTATE, val);
+ }
+
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_BX) {
+ /* Enable some hw fixes. */
+ val = tr32(TG3PCI_MSI_DATA);
+ val |= (1 << 26) | (1 << 28) | (1 << 29);
+ tw32(TG3PCI_MSI_DATA, val);
+ }
+
+ /* Descriptor ring init may make accesses to the
+ * NIC SRAM area to setup the TX descriptors, so we
+ * can only do this after the hardware has been
+ * successfully reset.
+ */
+ err = tg3_init_rings(tp);
+ if (err)
+ return err;
+
+ if (tg3_flag(tp, 57765_PLUS)) {
+ val = tr32(TG3PCI_DMA_RW_CTRL) &
+ ~DMA_RWCTRL_DIS_CACHE_ALIGNMENT;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0)
+ val &= ~DMA_RWCTRL_CRDRDR_RDMA_MRRS_MSK;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717)
+ val |= DMA_RWCTRL_TAGGED_STAT_WA;
+ tw32(TG3PCI_DMA_RW_CTRL, val | tp->dma_rwctrl);
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) {
+ /* This value is determined during the probe time DMA
+ * engine test, tg3_test_dma.
+ */
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+ }
+
+ tp->grc_mode &= ~(GRC_MODE_HOST_SENDBDS |
+ GRC_MODE_4X_NIC_SEND_RINGS |
+ GRC_MODE_NO_TX_PHDR_CSUM |
+ GRC_MODE_NO_RX_PHDR_CSUM);
+ tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
+ tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
+
+ /* Pseudo-header checksum is done by hardware logic and not
+ * the offload processers, so make the chip do the pseudo-
+ * header checksums on receive. For transmit it is more
+ * convenient to do the pseudo-header checksum in software
+ * as Linux does that on transmit for us in all cases.
+ */
+ tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
+
+ tw32(GRC_MODE,
+ tp->grc_mode |
+ (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP));
+
+ /* Setup the timer prescalar register. Clock is always 66Mhz. */
+ val = tr32(GRC_MISC_CFG);
+ val &= ~0xff;
+ val |= (65 << GRC_MISC_CFG_PRESCALAR_SHIFT);
+ tw32(GRC_MISC_CFG, val);
+
+ /* Initialize MBUF/DESC pool. */
+ if (tg3_flag(tp, 5750_PLUS)) {
+ /* Do nothing. */
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
+ tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
+ tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64);
+ else
+ tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96);
+ tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE);
+ tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE);
+ }
+
+ tw32(BUFMGR_MB_RDMA_LOW_WATER,
+ tp->bufmgr_config.mbuf_read_dma_low_water);
+ tw32(BUFMGR_MB_MACRX_LOW_WATER,
+ tp->bufmgr_config.mbuf_mac_rx_low_water);
+ tw32(BUFMGR_MB_HIGH_WATER,
+ tp->bufmgr_config.mbuf_high_water);
+
+ tw32(BUFMGR_DMA_LOW_WATER,
+ tp->bufmgr_config.dma_low_water);
+ tw32(BUFMGR_DMA_HIGH_WATER,
+ tp->bufmgr_config.dma_high_water);
+
+ val = BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+ val |= BUFMGR_MODE_NO_TX_UNDERRUN;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5719_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5720_A0)
+ val |= BUFMGR_MODE_MBLOW_ATTN_ENAB;
+ tw32(BUFMGR_MODE, val);
+ for (i = 0; i < 2000; i++) {
+ if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE)
+ break;
+ udelay(10);
+ }
+ if (i >= 2000) {
+ DBGC(tp->dev, "%s cannot enable BUFMGR\n", __func__);
+ return -ENODEV;
+ }
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5906_A1)
+ tw32(ISO_PKT_TX, (tr32(ISO_PKT_TX) & ~0x3) | 0x2);
+
+ tg3_setup_rxbd_thresholds(tp);
+
+ /* Initialize TG3_BDINFO's at:
+ * RCVDBDI_STD_BD: standard eth size rx ring
+ * RCVDBDI_JUMBO_BD: jumbo frame rx ring
+ * RCVDBDI_MINI_BD: small frame rx ring (??? does not work)
+ *
+ * like so:
+ * TG3_BDINFO_HOST_ADDR: high/low parts of DMA address of ring
+ * TG3_BDINFO_MAXLEN_FLAGS: (rx max buffer size << 16) |
+ * ring attribute flags
+ * TG3_BDINFO_NIC_ADDR: location of descriptors in nic SRAM
+ *
+ * Standard receive ring @ NIC_SRAM_RX_BUFFER_DESC, 512 entries.
+ * Jumbo receive ring @ NIC_SRAM_RX_JUMBO_BUFFER_DESC, 256 entries.
+ *
+ * The size of each ring is fixed in the firmware, but the location is
+ * configurable.
+ */
+ tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH,
+ ((u64) tpr->rx_std_mapping >> 32));
+ tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW,
+ ((u64) tpr->rx_std_mapping & 0xffffffff));
+ if (!tg3_flag(tp, 5717_PLUS))
+ tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR,
+ NIC_SRAM_RX_BUFFER_DESC);
+
+ /* Disable the mini ring */
+ if (!tg3_flag(tp, 5705_PLUS))
+ tw32(RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS,
+ BDINFO_FLAGS_DISABLED);
+
+ val = TG3_RX_STD_MAX_SIZE_5700 << BDINFO_FLAGS_MAXLEN_SHIFT;
+
+ tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, val);
+
+ tpr->rx_std_prod_idx = TG3_DEF_RX_RING_PENDING;
+
+ /* std prod index is updated by tg3_refill_prod_ring() */
+ tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, 0);
+ tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, 0);
+
+ tg3_rings_reset(tp);
+
+#define TG3_MAX_MTU 1522
+ /* MTU + ethernet header + FCS + optional VLAN tag */
+ tw32(MAC_RX_MTU_SIZE, TG3_MAX_MTU);
+
+ /* The slot time is changed by tg3_setup_phy if we
+ * run at gigabit with half duplex.
+ */
+ val = (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
+ (6 << TX_LENGTHS_IPG_SHIFT) |
+ (32 << TX_LENGTHS_SLOT_TIME_SHIFT);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+ val |= tr32(MAC_TX_LENGTHS) &
+ (TX_LENGTHS_JMB_FRM_LEN_MSK |
+ TX_LENGTHS_CNT_DWN_VAL_MSK);
+
+ tw32(MAC_TX_LENGTHS, val);
+
+ /* Receive rules. */
+ tw32(MAC_RCV_RULE_CFG, RCV_RULE_CFG_DEFAULT_CLASS);
+ tw32(RCVLPC_CONFIG, 0x0181);
+
+ /* Calculate RDMAC_MODE setting early, we need it to determine
+ * the RCVLPC_STATE_ENABLE mask.
+ */
+ rdmac_mode = (RDMAC_MODE_ENABLE | RDMAC_MODE_TGTABORT_ENAB |
+ RDMAC_MODE_MSTABORT_ENAB | RDMAC_MODE_PARITYERR_ENAB |
+ RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
+ RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
+ RDMAC_MODE_LNGREAD_ENAB);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+ rdmac_mode |= RDMAC_MODE_MULT_DMA_RD_DIS;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+ rdmac_mode |= RDMAC_MODE_BD_SBD_CRPT_ENAB |
+ RDMAC_MODE_MBUF_RBD_CRPT_ENAB |
+ RDMAC_MODE_MBUF_SBD_CRPT_ENAB;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+ tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) {
+ if (tg3_flag(tp, TSO_CAPABLE) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+ rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128;
+ } else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
+ !tg3_flag(tp, IS_5788)) {
+ rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
+ }
+ }
+
+ if (tg3_flag(tp, PCI_EXPRESS))
+ rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+ rdmac_mode |= tr32(RDMAC_MODE) & RDMAC_MODE_H2BNC_VLAN_DET;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+ tg3_flag(tp, 57765_PLUS)) {
+ val = tr32(TG3_RDMA_RSRVCTRL_REG);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+ val &= ~(TG3_RDMA_RSRVCTRL_TXMRGN_MASK |
+ TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK |
+ TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK);
+ val |= TG3_RDMA_RSRVCTRL_TXMRGN_320B |
+ TG3_RDMA_RSRVCTRL_FIFO_LWM_1_5K |
+ TG3_RDMA_RSRVCTRL_FIFO_HWM_1_5K;
+ }
+ tw32(TG3_RDMA_RSRVCTRL_REG,
+ val | TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX);
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+ val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
+ tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val |
+ TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K |
+ TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K);
+ }
+
+ /* Receive/send statistics. */
+ if (tg3_flag(tp, 5750_PLUS)) {
+ val = tr32(RCVLPC_STATS_ENABLE);
+ val &= ~RCVLPC_STATSENAB_DACK_FIX;
+ tw32(RCVLPC_STATS_ENABLE, val);
+ } else if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) &&
+ tg3_flag(tp, TSO_CAPABLE)) {
+ val = tr32(RCVLPC_STATS_ENABLE);
+ val &= ~RCVLPC_STATSENAB_LNGBRST_RFIX;
+ tw32(RCVLPC_STATS_ENABLE, val);
+ } else {
+ tw32(RCVLPC_STATS_ENABLE, 0xffffff);
+ }
+ tw32(RCVLPC_STATSCTRL, RCVLPC_STATSCTRL_ENABLE);
+ tw32(SNDDATAI_STATSENAB, 0xffffff);
+ tw32(SNDDATAI_STATSCTRL,
+ (SNDDATAI_SCTRL_ENABLE |
+ SNDDATAI_SCTRL_FASTUPD));
+
+ /* Setup host coalescing engine. */
+ tw32(HOSTCC_MODE, 0);
+ for (i = 0; i < 2000; i++) {
+ if (!(tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE))
+ break;
+ udelay(10);
+ }
+
+ __tg3_set_coalesce(tp);
+
+ if (!tg3_flag(tp, 5705_PLUS)) {
+ /* Status/statistics block address. See tg3_timer,
+ * the tg3_periodic_fetch_stats call there, and
+ * tg3_get_stats to see how this works for 5705/5750 chips.
+ * NOTE: stats block removed for iPXE
+ */
+ tw32(HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK);
+
+ /* Clear statistics and status block memory areas */
+ for (i = NIC_SRAM_STATS_BLK;
+ i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
+ i += sizeof(u32)) {
+ tg3_write_mem(tp, i, 0);
+ udelay(40);
+ }
+ }
+
+ tw32(HOSTCC_MODE, HOSTCC_MODE_ENABLE | tp->coalesce_mode);
+
+ tw32(RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE);
+ tw32(RCVLPC_MODE, RCVLPC_MODE_ENABLE);
+ if (!tg3_flag(tp, 5705_PLUS))
+ tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE);
+
+ if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) {
+ tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
+ /* reset to prevent losing 1st rx packet intermittently */
+ tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+ udelay(10);
+ }
+
+ if (tg3_flag(tp, ENABLE_APE))
+ tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+ else
+ tp->mac_mode = 0;
+ tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
+ MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
+ if (!tg3_flag(tp, 5705_PLUS) &&
+ !(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
+ tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+ tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
+ udelay(40);
+
+ /* tp->grc_local_ctrl is partially set up during tg3_get_invariants().
+ * If TG3_FLAG_IS_NIC is zero, we should read the
+ * register to preserve the GPIO settings for LOMs. The GPIOs,
+ * whether used as inputs or outputs, are set by boot code after
+ * reset.
+ */
+ if (!tg3_flag(tp, IS_NIC)) {
+ u32 gpio_mask;
+
+ gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 |
+ GRC_LCLCTRL_GPIO_OUTPUT1 | GRC_LCLCTRL_GPIO_OUTPUT2;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+ gpio_mask |= GRC_LCLCTRL_GPIO_OE3 |
+ GRC_LCLCTRL_GPIO_OUTPUT3;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+ gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL;
+
+ tp->grc_local_ctrl &= ~gpio_mask;
+ tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask;
+
+ /* GPIO1 must be driven high for eeprom write protect */
+ if (tg3_flag(tp, EEPROM_WRITE_PROT))
+ tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OUTPUT1);
+ }
+ tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
+ udelay(100);
+
+ if (!tg3_flag(tp, 5705_PLUS)) {
+ tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
+ udelay(40);
+ }
+
+ val = (WDMAC_MODE_ENABLE | WDMAC_MODE_TGTABORT_ENAB |
+ WDMAC_MODE_MSTABORT_ENAB | WDMAC_MODE_PARITYERR_ENAB |
+ WDMAC_MODE_ADDROFLOW_ENAB | WDMAC_MODE_FIFOOFLOW_ENAB |
+ WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB |
+ WDMAC_MODE_LNGREAD_ENAB);
+
+ /* Enable host coalescing bug fix */
+ if (tg3_flag(tp, 5755_PLUS))
+ val |= WDMAC_MODE_STATUS_TAG_FIX;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ val |= WDMAC_MODE_BURST_ALL_DATA;
+
+ tw32_f(WDMAC_MODE, val);
+ udelay(40);
+
+ if (tg3_flag(tp, PCIX_MODE)) {
+ u16 pcix_cmd;
+
+ pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+ &pcix_cmd);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
+ pcix_cmd &= ~PCI_X_CMD_MAX_READ;
+ pcix_cmd |= PCI_X_CMD_READ_2K;
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+ pcix_cmd &= ~(PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ);
+ pcix_cmd |= PCI_X_CMD_READ_2K;
+ }
+ pci_write_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+ pcix_cmd);
+ }
+
+ tw32_f(RDMAC_MODE, rdmac_mode);
+ udelay(40);
+
+ tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
+ if (!tg3_flag(tp, 5705_PLUS))
+ tw32(MBFREE_MODE, MBFREE_MODE_ENABLE);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ tw32(SNDDATAC_MODE,
+ SNDDATAC_MODE_ENABLE | SNDDATAC_MODE_CDELAY);
+ else
+ tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
+
+ tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE);
+ tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB);
+ val = RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ;
+ if (tg3_flag(tp, LRG_PROD_RING_CAP))
+ val |= RCVDBDI_MODE_LRG_RING_SZ;
+ tw32(RCVDBDI_MODE, val);
+ tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
+
+ val = SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE;
+ if (tg3_flag(tp, ENABLE_TSS))
+ val |= SNDBDI_MODE_MULTI_TXQ_EN;
+ tw32(SNDBDI_MODE, val);
+ tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE);
+
+
+ /* FIXME: 5701 firmware fix? */
+#if 0
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
+ err = tg3_load_5701_a0_firmware_fix(tp);
+ if (err)
+ return err;
+ }
+#endif
+
+ tp->tx_mode = TX_MODE_ENABLE;
+
+ if (tg3_flag(tp, 5755_PLUS) ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ tp->tx_mode |= TX_MODE_MBUF_LOCKUP_FIX;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+ val = TX_MODE_JMB_FRM_LEN | TX_MODE_CNT_DN_MODE;
+ tp->tx_mode &= ~val;
+ tp->tx_mode |= tr32(MAC_TX_MODE) & val;
+ }
+
+ tw32_f(MAC_TX_MODE, tp->tx_mode);
+ udelay(100);
+
+ tp->rx_mode = RX_MODE_ENABLE;
+
+ tw32_f(MAC_RX_MODE, tp->rx_mode);
+ udelay(10);
+
+ tw32(MAC_LED_CTRL, tp->led_ctrl);
+
+ tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+ if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
+ tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+ udelay(10);
+ }
+ tw32_f(MAC_RX_MODE, tp->rx_mode);
+ udelay(10);
+
+ if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) &&
+ !(tp->phy_flags & TG3_PHYFLG_SERDES_PREEMPHASIS)) {
+ /* Set drive transmission level to 1.2V */
+ /* only if the signal pre-emphasis bit is not set */
+ val = tr32(MAC_SERDES_CFG);
+ val &= 0xfffff000;
+ val |= 0x880;
+ tw32(MAC_SERDES_CFG, val);
+ }
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1)
+ tw32(MAC_SERDES_CFG, 0x616000);
+ }
+
+ /* Prevent chip from dropping frames when flow control
+ * is enabled.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+ val = 1;
+ else
+ val = 2;
+ tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, val);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
+ (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) {
+ /* Use hardware link auto-negotiation */
+ tg3_flag_set(tp, HW_AUTONEG);
+ }
+
+ if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+ u32 tmp;
+
+ tmp = tr32(SERDES_RX_CTRL);
+ tw32(SERDES_RX_CTRL, tmp | SERDES_RX_SIG_DETECT);
+ tp->grc_local_ctrl &= ~GRC_LCLCTRL_USE_EXT_SIG_DETECT;
+ tp->grc_local_ctrl |= GRC_LCLCTRL_USE_SIG_DETECT;
+ tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
+ }
+
+ err = tg3_setup_phy(tp, 0);
+ if (err)
+ return err;
+
+ if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
+ !(tp->phy_flags & TG3_PHYFLG_IS_FET)) {
+ u32 tmp;
+
+ /* Clear CRC stats. */
+ if (!tg3_readphy(tp, MII_TG3_TEST1, &tmp)) {
+ tg3_writephy(tp, MII_TG3_TEST1,
+ tmp | MII_TG3_TEST1_CRC_EN);
+ tg3_readphy(tp, MII_TG3_RXR_COUNTERS, &tmp);
+ }
+ }
+
+ __tg3_set_rx_mode(tp->dev);
+
+ /* Initialize receive rules. */
+ tw32(MAC_RCV_RULE_0, 0xc2000000 & RCV_RULE_DISABLE_MASK);
+ tw32(MAC_RCV_VALUE_0, 0xffffffff & RCV_RULE_DISABLE_MASK);
+ tw32(MAC_RCV_RULE_1, 0x86000004 & RCV_RULE_DISABLE_MASK);
+ tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK);
+
+ if (tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, 5780_CLASS))
+ limit = 8;
+ else
+ limit = 16;
+ if (tg3_flag(tp, ENABLE_ASF))
+ limit -= 4;
+ switch (limit) {
+ case 16:
+ tw32(MAC_RCV_RULE_15, 0); tw32(MAC_RCV_VALUE_15, 0);
+ case 15:
+ tw32(MAC_RCV_RULE_14, 0); tw32(MAC_RCV_VALUE_14, 0);
+ case 14:
+ tw32(MAC_RCV_RULE_13, 0); tw32(MAC_RCV_VALUE_13, 0);
+ case 13:
+ tw32(MAC_RCV_RULE_12, 0); tw32(MAC_RCV_VALUE_12, 0);
+ case 12:
+ tw32(MAC_RCV_RULE_11, 0); tw32(MAC_RCV_VALUE_11, 0);
+ case 11:
+ tw32(MAC_RCV_RULE_10, 0); tw32(MAC_RCV_VALUE_10, 0);
+ case 10:
+ tw32(MAC_RCV_RULE_9, 0); tw32(MAC_RCV_VALUE_9, 0);
+ case 9:
+ tw32(MAC_RCV_RULE_8, 0); tw32(MAC_RCV_VALUE_8, 0);
+ case 8:
+ tw32(MAC_RCV_RULE_7, 0); tw32(MAC_RCV_VALUE_7, 0);
+ case 7:
+ tw32(MAC_RCV_RULE_6, 0); tw32(MAC_RCV_VALUE_6, 0);
+ case 6:
+ tw32(MAC_RCV_RULE_5, 0); tw32(MAC_RCV_VALUE_5, 0);
+ case 5:
+ tw32(MAC_RCV_RULE_4, 0); tw32(MAC_RCV_VALUE_4, 0);
+ case 4:
+ /* tw32(MAC_RCV_RULE_3, 0); tw32(MAC_RCV_VALUE_3, 0); */
+ case 3:
+ /* tw32(MAC_RCV_RULE_2, 0); tw32(MAC_RCV_VALUE_2, 0); */
+ case 2:
+ case 1:
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* Called at device open time to get the chip ready for
+ * packet processing. Invoked with tp->lock held.
+ */
+int tg3_init_hw(struct tg3 *tp, int reset_phy)
+{ DBGP("%s\n", __func__);
+
+ tg3_switch_clocks(tp);
+
+ tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+
+ return tg3_reset_hw(tp, reset_phy);
+}
+
+void tg3_set_txd(struct tg3 *tp, int entry,
+ dma_addr_t mapping, int len, u32 flags)
+{ DBGP("%s\n", __func__);
+
+ struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
+
+ txd->addr_hi = ((u64) mapping >> 32);
+ txd->addr_lo = ((u64) mapping & 0xffffffff);
+ txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
+ txd->vlan_tag = 0;
+}
+
+int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, dma_addr_t buf_dma, int size, int to_device)
+{ DBGP("%s\n", __func__);
+
+ struct tg3_internal_buffer_desc test_desc;
+ u32 sram_dma_descs;
+ int ret;
+ unsigned int i;
+
+ sram_dma_descs = NIC_SRAM_DMA_DESC_POOL_BASE;
+
+ tw32(FTQ_RCVBD_COMP_FIFO_ENQDEQ, 0);
+ tw32(FTQ_RCVDATA_COMP_FIFO_ENQDEQ, 0);
+ tw32(RDMAC_STATUS, 0);
+ tw32(WDMAC_STATUS, 0);
+
+ tw32(BUFMGR_MODE, 0);
+ tw32(FTQ_RESET, 0);
+
+ test_desc.addr_hi = ((u64) buf_dma) >> 32;
+ test_desc.addr_lo = buf_dma & 0xffffffff;
+ test_desc.nic_mbuf = 0x00002100;
+ test_desc.len = size;
+
+ /*
+ * HP ZX1 was seeing test failures for 5701 cards running at 33Mhz
+ * the *second* time the tg3 driver was getting loaded after an
+ * initial scan.
+ *
+ * Broadcom tells me:
+ * ...the DMA engine is connected to the GRC block and a DMA
+ * reset may affect the GRC block in some unpredictable way...
+ * The behavior of resets to individual blocks has not been tested.
+ *
+ * Broadcom noted the GRC reset will also reset all sub-components.
+ */
+ if (to_device) {
+ test_desc.cqid_sqid = (13 << 8) | 2;
+
+ tw32_f(RDMAC_MODE, RDMAC_MODE_ENABLE);
+ udelay(40);
+ } else {
+ test_desc.cqid_sqid = (16 << 8) | 7;
+
+ tw32_f(WDMAC_MODE, WDMAC_MODE_ENABLE);
+ udelay(40);
+ }
+ test_desc.flags = 0x00000005;
+
+ for (i = 0; i < (sizeof(test_desc) / sizeof(u32)); i++) {
+ u32 val;
+
+ val = *(((u32 *)&test_desc) + i);
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR,
+ sram_dma_descs + (i * sizeof(u32)));
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+ }
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+
+ if (to_device)
+ tw32(FTQ_DMA_HIGH_READ_FIFO_ENQDEQ, sram_dma_descs);
+ else
+ tw32(FTQ_DMA_HIGH_WRITE_FIFO_ENQDEQ, sram_dma_descs);
+
+ ret = -ENODEV;
+ for (i = 0; i < 40; i++) {
+ u32 val;
+
+ if (to_device)
+ val = tr32(FTQ_RCVBD_COMP_FIFO_ENQDEQ);
+ else
+ val = tr32(FTQ_RCVDATA_COMP_FIFO_ENQDEQ);
+ if ((val & 0xffff) == sram_dma_descs) {
+ ret = 0;
+ break;
+ }
+
+ udelay(100);
+ }
+
+ return ret;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3_phy.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3_phy.c
new file mode 100644
index 00000000..f49c7f0b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/tg3/tg3_phy.c
@@ -0,0 +1,1605 @@
+
+#include <mii.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+
+#include "tg3.h"
+
+static void tg3_link_report(struct tg3 *tp);
+
+void tg3_mdio_init(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, 5717_PLUS)) {
+ u32 is_serdes;
+
+ tp->phy_addr = PCI_FUNC(tp->pdev->busdevfn) + 1;
+
+ if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0)
+ is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES;
+ else
+ is_serdes = tr32(TG3_CPMU_PHY_STRAP) &
+ TG3_CPMU_PHY_STRAP_IS_SERDES;
+ if (is_serdes)
+ tp->phy_addr += 7;
+ } else
+ tp->phy_addr = TG3_PHY_MII_ADDR;
+}
+
+static int tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
+{ DBGP("%s\n", __func__);
+
+ int i;
+ u32 val;
+
+ tw32(OTP_CTRL, cmd | OTP_CTRL_OTP_CMD_START);
+ tw32(OTP_CTRL, cmd);
+
+ /* Wait for up to 1 ms for command to execute. */
+ for (i = 0; i < 100; i++) {
+ val = tr32(OTP_STATUS);
+ if (val & OTP_STATUS_CMD_DONE)
+ break;
+ udelay(10);
+ }
+
+ return (val & OTP_STATUS_CMD_DONE) ? 0 : -EBUSY;
+}
+
+/* Read the gphy configuration from the OTP region of the chip. The gphy
+ * configuration is a 32-bit value that straddles the alignment boundary.
+ * We do two 32-bit reads and then shift and merge the results.
+ */
+u32 tg3_read_otp_phycfg(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 bhalf_otp, thalf_otp;
+
+ tw32(OTP_MODE, OTP_MODE_OTP_THRU_GRC);
+
+ if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_INIT))
+ return 0;
+
+ tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC1);
+
+ if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
+ return 0;
+
+ thalf_otp = tr32(OTP_READ_DATA);
+
+ tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC2);
+
+ if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
+ return 0;
+
+ bhalf_otp = tr32(OTP_READ_DATA);
+
+ return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16);
+}
+
+#define PHY_BUSY_LOOPS 5000
+
+int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
+{ DBGP("%s\n", __func__);
+
+ u32 frame_val;
+ unsigned int loops;
+ int ret;
+
+ if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+ tw32_f(MAC_MI_MODE,
+ (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
+ udelay(80);
+ }
+
+ *val = 0x0;
+
+ frame_val = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
+ MI_COM_PHY_ADDR_MASK);
+ frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
+ MI_COM_REG_ADDR_MASK);
+ frame_val |= (MI_COM_CMD_READ | MI_COM_START);
+
+ tw32_f(MAC_MI_COM, frame_val);
+
+ loops = PHY_BUSY_LOOPS;
+ while (loops != 0) {
+ udelay(10);
+ frame_val = tr32(MAC_MI_COM);
+
+ if ((frame_val & MI_COM_BUSY) == 0) {
+ udelay(5);
+ frame_val = tr32(MAC_MI_COM);
+ break;
+ }
+ loops -= 1;
+ }
+
+ ret = -EBUSY;
+ if (loops != 0) {
+ *val = frame_val & MI_COM_DATA_MASK;
+ ret = 0;
+ }
+
+ if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+ tw32_f(MAC_MI_MODE, tp->mi_mode);
+ udelay(80);
+ }
+
+ return ret;
+}
+
+struct subsys_tbl_ent {
+ u16 subsys_vendor, subsys_devid;
+ u32 phy_id;
+};
+
+static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
+ /* Broadcom boards. */
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6, TG3_PHY_ID_BCM5401 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95701A5, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95700T6, TG3_PHY_ID_BCM8002 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95700A9, 0 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95701T1, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95701T8, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95701A7, 0 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95701A10, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95701A12, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX1, TG3_PHY_ID_BCM5703 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX2, TG3_PHY_ID_BCM5703 },
+
+ /* 3com boards. */
+ { TG3PCI_SUBVENDOR_ID_3COM,
+ TG3PCI_SUBDEVICE_ID_3COM_3C996T, TG3_PHY_ID_BCM5401 },
+ { TG3PCI_SUBVENDOR_ID_3COM,
+ TG3PCI_SUBDEVICE_ID_3COM_3C996BT, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_3COM,
+ TG3PCI_SUBDEVICE_ID_3COM_3C996SX, 0 },
+ { TG3PCI_SUBVENDOR_ID_3COM,
+ TG3PCI_SUBDEVICE_ID_3COM_3C1000T, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_3COM,
+ TG3PCI_SUBDEVICE_ID_3COM_3C940BR01, TG3_PHY_ID_BCM5701 },
+
+ /* DELL boards. */
+ { TG3PCI_SUBVENDOR_ID_DELL,
+ TG3PCI_SUBDEVICE_ID_DELL_VIPER, TG3_PHY_ID_BCM5401 },
+ { TG3PCI_SUBVENDOR_ID_DELL,
+ TG3PCI_SUBDEVICE_ID_DELL_JAGUAR, TG3_PHY_ID_BCM5401 },
+ { TG3PCI_SUBVENDOR_ID_DELL,
+ TG3PCI_SUBDEVICE_ID_DELL_MERLOT, TG3_PHY_ID_BCM5411 },
+ { TG3PCI_SUBVENDOR_ID_DELL,
+ TG3PCI_SUBDEVICE_ID_DELL_SLIM_MERLOT, TG3_PHY_ID_BCM5411 },
+
+ /* Compaq boards. */
+ { TG3PCI_SUBVENDOR_ID_COMPAQ,
+ TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_COMPAQ,
+ TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE_2, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_COMPAQ,
+ TG3PCI_SUBDEVICE_ID_COMPAQ_CHANGELING, 0 },
+ { TG3PCI_SUBVENDOR_ID_COMPAQ,
+ TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_COMPAQ,
+ TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2, TG3_PHY_ID_BCM5701 },
+
+ /* IBM boards. */
+ { TG3PCI_SUBVENDOR_ID_IBM,
+ TG3PCI_SUBDEVICE_ID_IBM_5703SAX2, 0 }
+};
+
+static struct subsys_tbl_ent *tg3_lookup_by_subsys(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int i;
+
+ DBGC(tp->dev, "Matching with: %x:%x\n", tp->subsystem_vendor, tp->subsystem_device);
+
+ for (i = 0; i < (int) ARRAY_SIZE(subsys_id_to_phy_id); i++) {
+ if ((subsys_id_to_phy_id[i].subsys_vendor ==
+ tp->subsystem_vendor) &&
+ (subsys_id_to_phy_id[i].subsys_devid ==
+ tp->subsystem_device))
+ return &subsys_id_to_phy_id[i];
+ }
+ return NULL;
+}
+
+int tg3_writephy(struct tg3 *tp, int reg, u32 val)
+{ DBGP("%s\n", __func__);
+
+ u32 frame_val;
+ unsigned int loops;
+ int ret;
+
+ if ((tp->phy_flags & TG3_PHYFLG_IS_FET) &&
+ (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL))
+ return 0;
+
+ if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+ tw32_f(MAC_MI_MODE,
+ (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
+ udelay(80);
+ }
+
+ frame_val = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
+ MI_COM_PHY_ADDR_MASK);
+ frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
+ MI_COM_REG_ADDR_MASK);
+ frame_val |= (val & MI_COM_DATA_MASK);
+ frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);
+
+ tw32_f(MAC_MI_COM, frame_val);
+
+ loops = PHY_BUSY_LOOPS;
+ while (loops != 0) {
+ udelay(10);
+ frame_val = tr32(MAC_MI_COM);
+ if ((frame_val & MI_COM_BUSY) == 0) {
+ udelay(5);
+ frame_val = tr32(MAC_MI_COM);
+ break;
+ }
+ loops -= 1;
+ }
+
+ ret = -EBUSY;
+ if (loops != 0)
+ ret = 0;
+
+ if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+ tw32_f(MAC_MI_MODE, tp->mi_mode);
+ udelay(80);
+ }
+
+ return ret;
+}
+
+static int tg3_bmcr_reset(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 phy_control;
+ int limit, err;
+
+ /* OK, reset it, and poll the BMCR_RESET bit until it
+ * clears or we time out.
+ */
+ phy_control = BMCR_RESET;
+ err = tg3_writephy(tp, MII_BMCR, phy_control);
+ if (err != 0)
+ return -EBUSY;
+
+ limit = 5000;
+ while (limit--) {
+ err = tg3_readphy(tp, MII_BMCR, &phy_control);
+ if (err != 0)
+ return -EBUSY;
+
+ if ((phy_control & BMCR_RESET) == 0) {
+ udelay(40);
+ break;
+ }
+ udelay(10);
+ }
+ if (limit < 0)
+ return -EBUSY;
+
+ return 0;
+}
+
+static int tg3_wait_macro_done(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int limit = 100;
+
+ while (limit--) {
+ u32 tmp32;
+
+ if (!tg3_readphy(tp, MII_TG3_DSP_CONTROL, &tmp32)) {
+ if ((tmp32 & 0x1000) == 0)
+ break;
+ }
+ }
+ if (limit < 0)
+ return -EBUSY;
+
+ return 0;
+}
+
+static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp)
+{ DBGP("%s\n", __func__);
+
+ static const u32 test_pat[4][6] = {
+ { 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 },
+ { 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 },
+ { 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 },
+ { 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 }
+ };
+ int chan;
+
+ for (chan = 0; chan < 4; chan++) {
+ int i;
+
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
+ (chan * 0x2000) | 0x0200);
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002);
+
+ for (i = 0; i < 6; i++)
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT,
+ test_pat[chan][i]);
+
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202);
+ if (tg3_wait_macro_done(tp)) {
+ *resetp = 1;
+ return -EBUSY;
+ }
+
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
+ (chan * 0x2000) | 0x0200);
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0082);
+ if (tg3_wait_macro_done(tp)) {
+ *resetp = 1;
+ return -EBUSY;
+ }
+
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0802);
+ if (tg3_wait_macro_done(tp)) {
+ *resetp = 1;
+ return -EBUSY;
+ }
+
+ for (i = 0; i < 6; i += 2) {
+ u32 low, high;
+
+ if (tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low) ||
+ tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high) ||
+ tg3_wait_macro_done(tp)) {
+ *resetp = 1;
+ return -EBUSY;
+ }
+ low &= 0x7fff;
+ high &= 0x000f;
+ if (low != test_pat[chan][i] ||
+ high != test_pat[chan][i+1]) {
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b);
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001);
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005);
+
+ return -EBUSY;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int tg3_phy_reset_chanpat(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int chan;
+
+ for (chan = 0; chan < 4; chan++) {
+ int i;
+
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
+ (chan * 0x2000) | 0x0200);
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002);
+ for (i = 0; i < 6; i++)
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000);
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202);
+ if (tg3_wait_macro_done(tp))
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val)
+{ DBGP("%s\n", __func__);
+
+ int err;
+
+ err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
+ if (!err)
+ err = tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val);
+
+ return err;
+}
+
+static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set)
+{ DBGP("%s\n", __func__);
+
+ if (reg == MII_TG3_AUXCTL_SHDWSEL_MISC)
+ set |= MII_TG3_AUXCTL_MISC_WREN;
+
+ return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg);
+}
+
+#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \
+ tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
+ MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \
+ MII_TG3_AUXCTL_ACTL_TX_6DB)
+
+#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \
+ tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
+ MII_TG3_AUXCTL_ACTL_TX_6DB);
+
+static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 reg32, phy9_orig;
+ int retries, do_phy_reset, err;
+
+ retries = 10;
+ do_phy_reset = 1;
+ do {
+ if (do_phy_reset) {
+ err = tg3_bmcr_reset(tp);
+ if (err)
+ return err;
+ do_phy_reset = 0;
+ }
+
+ /* Disable transmitter and interrupt. */
+ if (tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32))
+ continue;
+
+ reg32 |= 0x3000;
+ tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
+
+ /* Set full-duplex, 1000 mbps. */
+ tg3_writephy(tp, MII_BMCR,
+ BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
+
+ /* Set to master mode. */
+ if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig))
+ continue;
+
+ tg3_writephy(tp, MII_TG3_CTRL,
+ (MII_TG3_CTRL_AS_MASTER |
+ MII_TG3_CTRL_ENABLE_AS_MASTER));
+
+ err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
+ if (err)
+ return err;
+
+ /* Block the PHY control access. */
+ tg3_phydsp_write(tp, 0x8005, 0x0800);
+
+ err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset);
+ if (!err)
+ break;
+ } while (--retries);
+
+ err = tg3_phy_reset_chanpat(tp);
+ if (err)
+ return err;
+
+ tg3_phydsp_write(tp, 0x8005, 0x0000);
+
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000);
+
+ TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+
+ tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
+
+ if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32)) {
+ reg32 &= ~0x3000;
+ tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
+ } else if (!err)
+ err = -EBUSY;
+
+ return err;
+}
+
+static void tg3_phy_apply_otp(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 otp, phy;
+
+ if (!tp->phy_otp)
+ return;
+
+ otp = tp->phy_otp;
+
+ if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp))
+ return;
+
+ phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT);
+ phy |= MII_TG3_DSP_TAP1_AGCTGT_DFLT;
+ tg3_phydsp_write(tp, MII_TG3_DSP_TAP1, phy);
+
+ phy = ((otp & TG3_OTP_HPFFLTR_MASK) >> TG3_OTP_HPFFLTR_SHIFT) |
+ ((otp & TG3_OTP_HPFOVER_MASK) >> TG3_OTP_HPFOVER_SHIFT);
+ tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH0, phy);
+
+ phy = ((otp & TG3_OTP_LPFDIS_MASK) >> TG3_OTP_LPFDIS_SHIFT);
+ phy |= MII_TG3_DSP_AADJ1CH3_ADCCKADJ;
+ tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH3, phy);
+
+ phy = ((otp & TG3_OTP_VDAC_MASK) >> TG3_OTP_VDAC_SHIFT);
+ tg3_phydsp_write(tp, MII_TG3_DSP_EXP75, phy);
+
+ phy = ((otp & TG3_OTP_10BTAMP_MASK) >> TG3_OTP_10BTAMP_SHIFT);
+ tg3_phydsp_write(tp, MII_TG3_DSP_EXP96, phy);
+
+ phy = ((otp & TG3_OTP_ROFF_MASK) >> TG3_OTP_ROFF_SHIFT) |
+ ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT);
+ tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy);
+
+ TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+}
+
+static int tg3_phy_auxctl_read(struct tg3 *tp, int reg, u32 *val)
+{ DBGP("%s\n", __func__);
+
+ int err;
+
+ err = tg3_writephy(tp, MII_TG3_AUX_CTRL,
+ (reg << MII_TG3_AUXCTL_MISC_RDSEL_SHIFT) |
+ MII_TG3_AUXCTL_SHDWSEL_MISC);
+ if (!err)
+ err = tg3_readphy(tp, MII_TG3_AUX_CTRL, val);
+
+ return err;
+}
+
+static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
+{ DBGP("%s\n", __func__);
+
+ u32 phy;
+
+ if (!tg3_flag(tp, 5705_PLUS) ||
+ (tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
+ return;
+
+ if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
+ u32 ephy;
+
+ if (!tg3_readphy(tp, MII_TG3_FET_TEST, &ephy)) {
+ u32 reg = MII_TG3_FET_SHDW_MISCCTRL;
+
+ tg3_writephy(tp, MII_TG3_FET_TEST,
+ ephy | MII_TG3_FET_SHADOW_EN);
+ if (!tg3_readphy(tp, reg, &phy)) {
+ if (enable)
+ phy |= MII_TG3_FET_SHDW_MISCCTRL_MDIX;
+ else
+ phy &= ~MII_TG3_FET_SHDW_MISCCTRL_MDIX;
+ tg3_writephy(tp, reg, phy);
+ }
+ tg3_writephy(tp, MII_TG3_FET_TEST, ephy);
+ }
+ } else {
+ int ret;
+
+ ret = tg3_phy_auxctl_read(tp,
+ MII_TG3_AUXCTL_SHDWSEL_MISC, &phy);
+ if (!ret) {
+ if (enable)
+ phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+ else
+ phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+ tg3_phy_auxctl_write(tp,
+ MII_TG3_AUXCTL_SHDWSEL_MISC, phy);
+ }
+ }
+}
+
+static void tg3_phy_set_wirespeed(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int ret;
+ u32 val;
+
+ if (tp->phy_flags & TG3_PHYFLG_NO_ETH_WIRE_SPEED)
+ return;
+
+ ret = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_MISC, &val);
+ if (!ret)
+ tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_MISC,
+ val | MII_TG3_AUXCTL_MISC_WIRESPD_EN);
+}
+
+/* This will reset the tigon3 PHY if there is no valid
+ * link unless the FORCE argument is non-zero.
+ */
+int tg3_phy_reset(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 val, cpmuctrl;
+ int err;
+
+ DBGCP(&tp->pdev->dev, "%s\n", __func__);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ val = tr32(GRC_MISC_CFG);
+ tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ);
+ udelay(40);
+ }
+ err = tg3_readphy(tp, MII_BMSR, &val);
+ err |= tg3_readphy(tp, MII_BMSR, &val);
+ if (err != 0)
+ return -EBUSY;
+
+ netdev_link_down(tp->dev);
+ tg3_link_report(tp);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+ err = tg3_phy_reset_5703_4_5(tp);
+ if (err)
+ return err;
+ goto out;
+ }
+
+ cpmuctrl = 0;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+ GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) {
+ cpmuctrl = tr32(TG3_CPMU_CTRL);
+ if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY)
+ tw32(TG3_CPMU_CTRL,
+ cpmuctrl & ~CPMU_CTRL_GPHY_10MB_RXONLY);
+ }
+
+ err = tg3_bmcr_reset(tp);
+ if (err)
+ return err;
+
+ if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) {
+ val = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz;
+ tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, val);
+
+ tw32(TG3_CPMU_CTRL, cpmuctrl);
+ }
+
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
+ GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
+ val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+ if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
+ CPMU_LSPD_1000MB_MACCLK_12_5) {
+ val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+ udelay(40);
+ tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+ }
+ }
+
+ if (tg3_flag(tp, 5717_PLUS) &&
+ (tp->phy_flags & TG3_PHYFLG_MII_SERDES))
+ return 0;
+
+ tg3_phy_apply_otp(tp);
+
+out:
+ if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) &&
+ !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+ tg3_phydsp_write(tp, 0x201f, 0x2aaa);
+ tg3_phydsp_write(tp, 0x000a, 0x0323);
+ TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+ }
+
+ if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) {
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
+ }
+
+ if (tp->phy_flags & TG3_PHYFLG_BER_BUG) {
+ if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+ tg3_phydsp_write(tp, 0x000a, 0x310b);
+ tg3_phydsp_write(tp, 0x201f, 0x9506);
+ tg3_phydsp_write(tp, 0x401f, 0x14e2);
+ TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+ }
+ } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) {
+ if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
+ if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) {
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b);
+ tg3_writephy(tp, MII_TG3_TEST1,
+ MII_TG3_TEST1_TRIM_EN | 0x4);
+ } else
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
+
+ TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+ }
+ }
+
+ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
+ /* Cannot do read-modify-write on 5401 */
+ tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ /* adjust output voltage */
+ tg3_writephy(tp, MII_TG3_FET_PTEST, 0x12);
+ }
+
+ tg3_phy_toggle_automdix(tp, 1);
+ tg3_phy_set_wirespeed(tp);
+ return 0;
+}
+
+static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask)
+{ DBGP("%s\n", __func__);
+
+ u32 adv_reg, all_mask = 0;
+
+ if (mask & ADVERTISED_10baseT_Half)
+ all_mask |= ADVERTISE_10HALF;
+ if (mask & ADVERTISED_10baseT_Full)
+ all_mask |= ADVERTISE_10FULL;
+ if (mask & ADVERTISED_100baseT_Half)
+ all_mask |= ADVERTISE_100HALF;
+ if (mask & ADVERTISED_100baseT_Full)
+ all_mask |= ADVERTISE_100FULL;
+
+ if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg))
+ return 0;
+
+ if ((adv_reg & all_mask) != all_mask)
+ return 0;
+ if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
+ u32 tg3_ctrl;
+
+ all_mask = 0;
+ if (mask & ADVERTISED_1000baseT_Half)
+ all_mask |= ADVERTISE_1000HALF;
+ if (mask & ADVERTISED_1000baseT_Full)
+ all_mask |= ADVERTISE_1000FULL;
+
+ if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl))
+ return 0;
+
+ if ((tg3_ctrl & all_mask) != all_mask)
+ return 0;
+ }
+ return 1;
+}
+
+static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl)
+{ DBGP("%s\n", __func__);
+
+ u16 miireg;
+
+ if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
+ miireg = ADVERTISE_PAUSE_CAP;
+ else if (flow_ctrl & FLOW_CTRL_TX)
+ miireg = ADVERTISE_PAUSE_ASYM;
+ else if (flow_ctrl & FLOW_CTRL_RX)
+ miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+ else
+ miireg = 0;
+
+ return miireg;
+}
+
+static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
+{ DBGP("%s\n", __func__);
+
+ int err = 0;
+ u32 val __unused, new_adv;
+
+ new_adv = ADVERTISE_CSMA;
+ if (advertise & ADVERTISED_10baseT_Half)
+ new_adv |= ADVERTISE_10HALF;
+ if (advertise & ADVERTISED_10baseT_Full)
+ new_adv |= ADVERTISE_10FULL;
+ if (advertise & ADVERTISED_100baseT_Half)
+ new_adv |= ADVERTISE_100HALF;
+ if (advertise & ADVERTISED_100baseT_Full)
+ new_adv |= ADVERTISE_100FULL;
+
+ new_adv |= tg3_advert_flowctrl_1000T(flowctrl);
+
+ err = tg3_writephy(tp, MII_ADVERTISE, new_adv);
+ if (err)
+ goto done;
+
+ if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
+ goto done;
+
+ new_adv = 0;
+ if (advertise & ADVERTISED_1000baseT_Half)
+ new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
+ if (advertise & ADVERTISED_1000baseT_Full)
+ new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
+ new_adv |= (MII_TG3_CTRL_AS_MASTER |
+ MII_TG3_CTRL_ENABLE_AS_MASTER);
+
+ err = tg3_writephy(tp, MII_TG3_CTRL, new_adv);
+ if (err)
+ goto done;
+
+ if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
+ goto done;
+
+done:
+ return err;
+}
+
+static int tg3_init_5401phy_dsp(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int err;
+
+ /* Turn off tap power management. */
+ /* Set Extended packet length bit */
+ err = tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);
+
+ err |= tg3_phydsp_write(tp, 0x0012, 0x1804);
+ err |= tg3_phydsp_write(tp, 0x0013, 0x1204);
+ err |= tg3_phydsp_write(tp, 0x8006, 0x0132);
+ err |= tg3_phydsp_write(tp, 0x8006, 0x0232);
+ err |= tg3_phydsp_write(tp, 0x201f, 0x0a20);
+
+ udelay(40);
+
+ return err;
+}
+
+#define ADVERTISED_Autoneg (1 << 6)
+#define ADVERTISED_Pause (1 << 13)
+#define ADVERTISED_TP (1 << 7)
+#define ADVERTISED_FIBRE (1 << 10)
+
+#define AUTONEG_ENABLE 0x01
+
+static void tg3_phy_init_link_config(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 adv = ADVERTISED_Autoneg |
+ ADVERTISED_Pause;
+
+
+ if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY))
+ adv |= ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full;
+ if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
+ adv |= ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_TP;
+ else
+ adv |= ADVERTISED_FIBRE;
+
+ tp->link_config.advertising = adv;
+ tp->link_config.speed = SPEED_INVALID;
+ tp->link_config.duplex = DUPLEX_INVALID;
+ tp->link_config.autoneg = AUTONEG_ENABLE;
+ tp->link_config.active_speed = SPEED_INVALID;
+ tp->link_config.active_duplex = DUPLEX_INVALID;
+ tp->link_config.orig_speed = SPEED_INVALID;
+ tp->link_config.orig_duplex = DUPLEX_INVALID;
+ tp->link_config.orig_autoneg = AUTONEG_INVALID;
+}
+
+int tg3_phy_probe(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 hw_phy_id_1, hw_phy_id_2;
+ u32 hw_phy_id, hw_phy_id_masked;
+ int err;
+
+ /* flow control autonegotiation is default behavior */
+ tg3_flag_set(tp, PAUSE_AUTONEG);
+ tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
+
+ /* Reading the PHY ID register can conflict with ASF
+ * firmware access to the PHY hardware.
+ */
+ err = 0;
+ if (tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE)) {
+ hw_phy_id = hw_phy_id_masked = TG3_PHY_ID_INVALID;
+ } else {
+ /* Now read the physical PHY_ID from the chip and verify
+ * that it is sane. If it doesn't look good, we fall back
+ * to either the hard-coded table based PHY_ID and failing
+ * that the value found in the eeprom area.
+ */
+ err |= tg3_readphy(tp, MII_PHYSID1, &hw_phy_id_1);
+ err |= tg3_readphy(tp, MII_PHYSID2, &hw_phy_id_2);
+
+ hw_phy_id = (hw_phy_id_1 & 0xffff) << 10;
+ hw_phy_id |= (hw_phy_id_2 & 0xfc00) << 16;
+ hw_phy_id |= (hw_phy_id_2 & 0x03ff) << 0;
+
+ hw_phy_id_masked = hw_phy_id & TG3_PHY_ID_MASK;
+ }
+
+ if (!err && TG3_KNOWN_PHY_ID(hw_phy_id_masked)) {
+ tp->phy_id = hw_phy_id;
+ if (hw_phy_id_masked == TG3_PHY_ID_BCM8002)
+ tp->phy_flags |= TG3_PHYFLG_PHY_SERDES;
+ else
+ tp->phy_flags &= ~TG3_PHYFLG_PHY_SERDES;
+ } else {
+ if (tp->phy_id != TG3_PHY_ID_INVALID) {
+ /* Do nothing, phy ID already set up in
+ * tg3_get_eeprom_hw_cfg().
+ */
+ } else {
+ struct subsys_tbl_ent *p;
+
+ /* No eeprom signature? Try the hardcoded
+ * subsys device table.
+ */
+ p = tg3_lookup_by_subsys(tp);
+ if (!p) {
+ DBGC(&tp->pdev->dev, "lookup by subsys failed\n");
+ return -ENODEV;
+ }
+
+ tp->phy_id = p->phy_id;
+ if (!tp->phy_id ||
+ tp->phy_id == TG3_PHY_ID_BCM8002)
+ tp->phy_flags |= TG3_PHYFLG_PHY_SERDES;
+ }
+ }
+
+ if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
+ ((tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 &&
+ tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
+ tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)))
+ tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
+
+ tg3_phy_init_link_config(tp);
+
+ if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
+ !tg3_flag(tp, ENABLE_APE) &&
+ !tg3_flag(tp, ENABLE_ASF)) {
+ u32 bmsr;
+ u32 mask;
+
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+ if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+ (bmsr & BMSR_LSTATUS))
+ goto skip_phy_reset;
+
+ err = tg3_phy_reset(tp);
+ if (err)
+ return err;
+
+ tg3_phy_set_wirespeed(tp);
+
+ mask = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full);
+ if (!tg3_copper_is_advertising_all(tp, mask)) {
+ tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
+ tp->link_config.flowctrl);
+
+ tg3_writephy(tp, MII_BMCR,
+ BMCR_ANENABLE | BMCR_ANRESTART);
+ }
+ }
+
+skip_phy_reset:
+ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
+ err = tg3_init_5401phy_dsp(tp);
+ if (err)
+ return err;
+
+ err = tg3_init_5401phy_dsp(tp);
+ }
+
+ return err;
+}
+
+void tg3_poll_link(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 mac_stat;
+
+ mac_stat = tr32(MAC_STATUS);
+
+ if (mac_stat & MAC_STATUS_LNKSTATE_CHANGED)
+ tg3_setup_phy(tp, 0);
+}
+
+static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
+{ DBGP("%s\n", __func__);
+
+ switch (val & MII_TG3_AUX_STAT_SPDMASK) {
+ case MII_TG3_AUX_STAT_10HALF:
+ *speed = SPEED_10;
+ *duplex = DUPLEX_HALF;
+ break;
+
+ case MII_TG3_AUX_STAT_10FULL:
+ *speed = SPEED_10;
+ *duplex = DUPLEX_FULL;
+ break;
+
+ case MII_TG3_AUX_STAT_100HALF:
+ *speed = SPEED_100;
+ *duplex = DUPLEX_HALF;
+ break;
+
+ case MII_TG3_AUX_STAT_100FULL:
+ *speed = SPEED_100;
+ *duplex = DUPLEX_FULL;
+ break;
+
+ case MII_TG3_AUX_STAT_1000HALF:
+ *speed = SPEED_1000;
+ *duplex = DUPLEX_HALF;
+ break;
+
+ case MII_TG3_AUX_STAT_1000FULL:
+ *speed = SPEED_1000;
+ *duplex = DUPLEX_FULL;
+ break;
+
+ default:
+ if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
+ *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 :
+ SPEED_10;
+ *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL :
+ DUPLEX_HALF;
+ break;
+ }
+ *speed = SPEED_INVALID;
+ *duplex = DUPLEX_INVALID;
+ break;
+ }
+}
+
+static int tg3_adv_1000T_flowctrl_ok(struct tg3 *tp, u32 *lcladv, u32 *rmtadv)
+{ DBGP("%s\n", __func__);
+
+ u32 curadv, reqadv;
+
+ if (tg3_readphy(tp, MII_ADVERTISE, lcladv))
+ return 1;
+
+ curadv = *lcladv & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+ reqadv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
+
+ if (tp->link_config.active_duplex == DUPLEX_FULL) {
+ if (curadv != reqadv)
+ return 0;
+
+ if (tg3_flag(tp, PAUSE_AUTONEG))
+ tg3_readphy(tp, MII_LPA, rmtadv);
+ } else {
+ /* Reprogram the advertisement register, even if it
+ * does not affect the current link. If the link
+ * gets renegotiated in the future, we can save an
+ * additional renegotiation cycle by advertising
+ * it correctly in the first place.
+ */
+ if (curadv != reqadv) {
+ *lcladv &= ~(ADVERTISE_PAUSE_CAP |
+ ADVERTISE_PAUSE_ASYM);
+ tg3_writephy(tp, MII_ADVERTISE, *lcladv | reqadv);
+ }
+ }
+
+ return 1;
+}
+
+static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv)
+{ DBGP("%s\n", __func__);
+
+ u8 cap = 0;
+
+ if (lcladv & ADVERTISE_1000XPAUSE) {
+ if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+ if (rmtadv & LPA_1000XPAUSE)
+ cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ else if (rmtadv & LPA_1000XPAUSE_ASYM)
+ cap = FLOW_CTRL_RX;
+ } else {
+ if (rmtadv & LPA_1000XPAUSE)
+ cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ }
+ } else if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+ if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM))
+ cap = FLOW_CTRL_TX;
+ }
+
+ return cap;
+}
+
+static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv)
+{ DBGP("%s\n", __func__);
+
+ u8 flowctrl = 0;
+ u32 old_rx_mode = tp->rx_mode;
+ u32 old_tx_mode = tp->tx_mode;
+
+ if (tg3_flag(tp, PAUSE_AUTONEG)) {
+ if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES)
+ flowctrl = tg3_resolve_flowctrl_1000X(lcladv, rmtadv);
+ else
+ flowctrl = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
+ } else
+ flowctrl = tp->link_config.flowctrl;
+
+ tp->link_config.active_flowctrl = flowctrl;
+
+ if (flowctrl & FLOW_CTRL_RX)
+ tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
+ else
+ tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
+
+ if (old_rx_mode != tp->rx_mode)
+ tw32_f(MAC_RX_MODE, tp->rx_mode);
+
+ if (flowctrl & FLOW_CTRL_TX)
+ tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
+ else
+ tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
+
+ if (old_tx_mode != tp->tx_mode)
+ tw32_f(MAC_TX_MODE, tp->tx_mode);
+}
+
+static void tg3_phy_copper_begin(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 new_adv;
+
+ if (tp->link_config.speed == SPEED_INVALID) {
+ if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
+ tp->link_config.advertising &=
+ ~(ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full);
+
+ tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
+ tp->link_config.flowctrl);
+ } else {
+ /* Asking for a specific link mode. */
+ if (tp->link_config.speed == SPEED_1000) {
+ if (tp->link_config.duplex == DUPLEX_FULL)
+ new_adv = ADVERTISED_1000baseT_Full;
+ else
+ new_adv = ADVERTISED_1000baseT_Half;
+ } else if (tp->link_config.speed == SPEED_100) {
+ if (tp->link_config.duplex == DUPLEX_FULL)
+ new_adv = ADVERTISED_100baseT_Full;
+ else
+ new_adv = ADVERTISED_100baseT_Half;
+ } else {
+ if (tp->link_config.duplex == DUPLEX_FULL)
+ new_adv = ADVERTISED_10baseT_Full;
+ else
+ new_adv = ADVERTISED_10baseT_Half;
+ }
+
+ tg3_phy_autoneg_cfg(tp, new_adv,
+ tp->link_config.flowctrl);
+ }
+
+ tg3_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
+}
+
+static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
+{ DBGP("%s\n", __func__);
+
+ if (tp->led_ctrl == LED_CTRL_MODE_PHY_2)
+ return 1;
+ else if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411) {
+ if (speed != SPEED_10)
+ return 1;
+ } else if (speed == SPEED_10)
+ return 1;
+
+ return 0;
+}
+
+#if 1
+
+static void tg3_ump_link_report(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 reg;
+ u32 val;
+
+ if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF))
+ return;
+
+ tg3_wait_for_event_ack(tp);
+
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE);
+
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14);
+
+ val = 0;
+ if (!tg3_readphy(tp, MII_BMCR, &reg))
+ val = reg << 16;
+ if (!tg3_readphy(tp, MII_BMSR, &reg))
+ val |= (reg & 0xffff);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val);
+
+ val = 0;
+ if (!tg3_readphy(tp, MII_ADVERTISE, &reg))
+ val = reg << 16;
+ if (!tg3_readphy(tp, MII_LPA, &reg))
+ val |= (reg & 0xffff);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val);
+
+ val = 0;
+ if (!(tp->phy_flags & TG3_PHYFLG_MII_SERDES)) {
+ if (!tg3_readphy(tp, MII_CTRL1000, &reg))
+ val = reg << 16;
+ if (!tg3_readphy(tp, MII_STAT1000, &reg))
+ val |= (reg & 0xffff);
+ }
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val);
+
+ if (!tg3_readphy(tp, MII_PHYADDR, &reg))
+ val = reg << 16;
+ else
+ val = 0;
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);
+
+ tg3_generate_fw_event(tp);
+}
+
+/* NOTE: Debugging only code */
+static void tg3_link_report(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (!netdev_link_ok(tp->dev)) {
+ DBGC(tp->dev, "Link is down\n");
+ tg3_ump_link_report(tp);
+ } else {
+ DBGC(tp->dev, "Link is up at %d Mbps, %s duplex\n",
+ (tp->link_config.active_speed == SPEED_1000 ?
+ 1000 :
+ (tp->link_config.active_speed == SPEED_100 ?
+ 100 : 10)),
+ (tp->link_config.active_duplex == DUPLEX_FULL ?
+ "full" : "half"));
+
+ DBGC(tp->dev, "Flow control is %s for TX and %s for RX\n",
+ (tp->link_config.active_flowctrl & FLOW_CTRL_TX) ?
+ "on" : "off",
+ (tp->link_config.active_flowctrl & FLOW_CTRL_RX) ?
+ "on" : "off");
+
+ if (tp->phy_flags & TG3_PHYFLG_EEE_CAP)
+ DBGC(tp->dev, "EEE is %s\n",
+ tp->setlpicnt ? "enabled" : "disabled");
+
+ tg3_ump_link_report(tp);
+ }
+}
+#endif
+
+static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
+{ DBGP("%s\n", __func__);
+
+ int current_link_up;
+ u32 bmsr, val;
+ u32 lcl_adv, rmt_adv;
+ u16 current_speed;
+ u8 current_duplex;
+ int i, err;
+
+ tw32(MAC_EVENT, 0);
+
+ tw32_f(MAC_STATUS,
+ (MAC_STATUS_SYNC_CHANGED |
+ MAC_STATUS_CFG_CHANGED |
+ MAC_STATUS_MI_COMPLETION |
+ MAC_STATUS_LNKSTATE_CHANGED));
+ udelay(40);
+
+ if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+ tw32_f(MAC_MI_MODE,
+ (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
+ udelay(80);
+ }
+
+ tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_PWRCTL, 0);
+
+ /* Some third-party PHYs need to be reset on link going
+ * down.
+ */
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
+ netdev_link_ok(tp->dev)) {
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+ if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+ !(bmsr & BMSR_LSTATUS))
+ force_reset = 1;
+ }
+ if (force_reset)
+ tg3_phy_reset(tp);
+
+ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+ if (tg3_readphy(tp, MII_BMSR, &bmsr) ||
+ !tg3_flag(tp, INIT_COMPLETE))
+ bmsr = 0;
+
+ if (!(bmsr & BMSR_LSTATUS)) {
+ err = tg3_init_5401phy_dsp(tp);
+ if (err)
+ return err;
+
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+ for (i = 0; i < 1000; i++) {
+ udelay(10);
+ if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+ (bmsr & BMSR_LSTATUS)) {
+ udelay(40);
+ break;
+ }
+ }
+
+ if ((tp->phy_id & TG3_PHY_ID_REV_MASK) ==
+ TG3_PHY_REV_BCM5401_B0 &&
+ !(bmsr & BMSR_LSTATUS) &&
+ tp->link_config.active_speed == SPEED_1000) {
+ err = tg3_phy_reset(tp);
+ if (!err)
+ err = tg3_init_5401phy_dsp(tp);
+ if (err)
+ return err;
+ }
+ }
+ } else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
+ /* 5701 {A0,B0} CRC bug workaround */
+ tg3_writephy(tp, 0x15, 0x0a75);
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
+ }
+
+ /* Clear pending interrupts... */
+ tg3_readphy(tp, MII_TG3_ISTAT, &val);
+ tg3_readphy(tp, MII_TG3_ISTAT, &val);
+
+ if (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT)
+ tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
+ else if (!(tp->phy_flags & TG3_PHYFLG_IS_FET))
+ tg3_writephy(tp, MII_TG3_IMASK, ~0);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+ if (tp->led_ctrl == LED_CTRL_MODE_PHY_1)
+ tg3_writephy(tp, MII_TG3_EXT_CTRL,
+ MII_TG3_EXT_CTRL_LNK3_LED_MODE);
+ else
+ tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
+ }
+
+ current_link_up = 0;
+ current_speed = SPEED_INVALID;
+ current_duplex = DUPLEX_INVALID;
+
+ if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) {
+ err = tg3_phy_auxctl_read(tp,
+ MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
+ &val);
+ if (!err && !(val & (1 << 10))) {
+ tg3_phy_auxctl_write(tp,
+ MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
+ val | (1 << 10));
+ goto relink;
+ }
+ }
+
+ bmsr = 0;
+ for (i = 0; i < 100; i++) {
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+ if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+ (bmsr & BMSR_LSTATUS))
+ break;
+ udelay(40);
+ }
+
+ if (bmsr & BMSR_LSTATUS) {
+ u32 aux_stat, bmcr;
+
+ tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
+ for (i = 0; i < 2000; i++) {
+ udelay(10);
+ if (!tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat) &&
+ aux_stat)
+ break;
+ }
+
+ tg3_aux_stat_to_speed_duplex(tp, aux_stat,
+ &current_speed,
+ &current_duplex);
+
+ bmcr = 0;
+ for (i = 0; i < 200; i++) {
+ tg3_readphy(tp, MII_BMCR, &bmcr);
+ if (tg3_readphy(tp, MII_BMCR, &bmcr))
+ continue;
+ if (bmcr && bmcr != 0x7fff)
+ break;
+ udelay(10);
+ }
+
+ lcl_adv = 0;
+ rmt_adv = 0;
+
+ tp->link_config.active_speed = current_speed;
+ tp->link_config.active_duplex = current_duplex;
+
+ if ((bmcr & BMCR_ANENABLE) &&
+ tg3_copper_is_advertising_all(tp,
+ tp->link_config.advertising)) {
+ if (tg3_adv_1000T_flowctrl_ok(tp, &lcl_adv,
+ &rmt_adv)) {
+ current_link_up = 1;
+ }
+ }
+
+ if (current_link_up == 1 &&
+ tp->link_config.active_duplex == DUPLEX_FULL)
+ tg3_setup_flow_control(tp, lcl_adv, rmt_adv);
+ }
+
+relink:
+ if (current_link_up == 0) {
+ tg3_phy_copper_begin(tp);
+
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+ if ((!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) ||
+ (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK))
+ current_link_up = 1;
+ }
+
+ tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
+ if (current_link_up == 1) {
+ if (tp->link_config.active_speed == SPEED_100 ||
+ tp->link_config.active_speed == SPEED_10)
+ tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
+ else
+ tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+ } else if (tp->phy_flags & TG3_PHYFLG_IS_FET)
+ tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
+ else
+ tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+
+ tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
+ if (tp->link_config.active_duplex == DUPLEX_HALF)
+ tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
+ if (current_link_up == 1 &&
+ tg3_5700_link_polarity(tp, tp->link_config.active_speed))
+ tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+ else
+ tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ }
+
+ /* ??? Without this setting Netgear GA302T PHY does not
+ * ??? send/receive packets...
+ */
+ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411 &&
+ tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
+ tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
+ tw32_f(MAC_MI_MODE, tp->mi_mode);
+ udelay(80);
+ }
+
+ tw32_f(MAC_MODE, tp->mac_mode);
+ udelay(40);
+
+ /* We always use the link change register */
+ /* NOTE: this freezes for mdc? */
+ tw32_f(MAC_EVENT, 0);
+ udelay(40);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
+ current_link_up == 1 &&
+ tp->link_config.active_speed == SPEED_1000 &&
+ (tg3_flag(tp, PCIX_MODE) || tg3_flag(tp, PCI_HIGH_SPEED))) {
+ udelay(120);
+ /* NOTE: this freezes for mdc? */
+ tw32_f(MAC_STATUS,
+ (MAC_STATUS_SYNC_CHANGED |
+ MAC_STATUS_CFG_CHANGED));
+ udelay(40);
+ tg3_write_mem(tp,
+ NIC_SRAM_FIRMWARE_MBOX,
+ NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
+ }
+
+ /* Prevent send BD corruption. */
+ if (tg3_flag(tp, CLKREQ_BUG)) {
+ u16 oldlnkctl, newlnkctl;
+
+ pci_read_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ &oldlnkctl);
+ if (tp->link_config.active_speed == SPEED_100 ||
+ tp->link_config.active_speed == SPEED_10)
+ newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN;
+ else
+ newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
+ if (newlnkctl != oldlnkctl)
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ newlnkctl);
+ }
+
+ if (current_link_up != netdev_link_ok(tp->dev)) {
+ if (current_link_up)
+ netdev_link_up(tp->dev);
+ else
+ netdev_link_down(tp->dev);
+ tg3_link_report(tp);
+ }
+
+ return 0;
+}
+
+int tg3_setup_phy(struct tg3 *tp, int force_reset)
+{ DBGP("%s\n", __func__);
+
+ u32 val;
+ int err;
+
+#if 0
+ if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)
+ err = tg3_setup_fiber_phy(tp, force_reset);
+ else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
+ err = tg3_setup_fiber_mii_phy(tp, force_reset);
+ else
+#endif
+ /* FIXME: add only copper phy variants for now */
+ err = tg3_setup_copper_phy(tp, force_reset);
+
+ val = (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
+ (6 << TX_LENGTHS_IPG_SHIFT);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+ val |= tr32(MAC_TX_LENGTHS) &
+ (TX_LENGTHS_JMB_FRM_LEN_MSK |
+ TX_LENGTHS_CNT_DWN_VAL_MSK);
+
+ if (tp->link_config.active_speed == SPEED_1000 &&
+ tp->link_config.active_duplex == DUPLEX_HALF)
+ tw32(MAC_TX_LENGTHS, val |
+ (0xff << TX_LENGTHS_SLOT_TIME_SHIFT));
+ else
+ tw32(MAC_TX_LENGTHS, val |
+ (32 << TX_LENGTHS_SLOT_TIME_SHIFT));
+
+ if (!tg3_flag(tp, 5705_PLUS)) {
+ if (netdev_link_ok(tp->dev)) {
+ tw32(HOSTCC_STAT_COAL_TICKS, DEFAULT_STAT_COAL_TICKS);
+ } else {
+ tw32(HOSTCC_STAT_COAL_TICKS, 0);
+ }
+ }
+
+ val = tr32(PCIE_PWR_MGMT_THRESH);
+ if (!netdev_link_ok(tp->dev))
+ val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK);
+ else
+ val |= PCIE_PWR_MGMT_L1_THRESH_MSK;
+ tw32(PCIE_PWR_MGMT_THRESH, val);
+
+ return err;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/tlan.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/tlan.c
new file mode 100644
index 00000000..b4d86cda
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/tlan.c
@@ -0,0 +1,1732 @@
+/**************************************************************************
+*
+* tlan.c -- Etherboot device driver for the Texas Instruments ThunderLAN
+* Written 2003-2003 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code based on:
+* lan.c: Linux ThunderLan Driver:
+*
+* by James Banks
+*
+* (C) 1997-1998 Caldera, Inc.
+* (C) 1998 James Banks
+* (C) 1999-2001 Torben Mathiasen
+* (C) 2002 Samuel Chessman
+*
+* REVISION HISTORY:
+* ================
+* v1.0 07-08-2003 timlegge Initial not quite working version
+* v1.1 07-27-2003 timlegge Sync 5.0 and 5.1 versions
+* v1.2 08-19-2003 timlegge Implement Multicast Support
+* v1.3 08-23-2003 timlegge Fix the transmit Function
+* v1.4 01-17-2004 timlegge Initial driver output cleanup
+*
+* Indent Options: indent -kr -i8
+***************************************************************************/
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "etherboot.h"
+#include "nic.h"
+#include <ipxe/pci.h>
+#include <ipxe/ethernet.h>
+#include <mii.h>
+#include "tlan.h"
+
+#define drv_version "v1.4"
+#define drv_date "01-17-2004"
+
+/* NIC specific static variables go here */
+#define HZ 100
+#define TX_TIME_OUT (6*HZ)
+
+/* Condensed operations for readability. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+static void TLan_ResetLists(struct nic *nic __unused);
+static void TLan_ResetAdapter(struct nic *nic __unused);
+static void TLan_FinishReset(struct nic *nic __unused);
+
+static void TLan_EeSendStart(u16);
+static int TLan_EeSendByte(u16, u8, int);
+static void TLan_EeReceiveByte(u16, u8 *, int);
+static int TLan_EeReadByte(u16 io_base, u8, u8 *);
+
+static void TLan_PhyDetect(struct nic *nic);
+static void TLan_PhyPowerDown(struct nic *nic);
+static void TLan_PhyPowerUp(struct nic *nic);
+
+
+static void TLan_SetMac(struct nic *nic __unused, int areg, unsigned char *mac);
+
+static void TLan_PhyReset(struct nic *nic);
+static void TLan_PhyStartLink(struct nic *nic);
+static void TLan_PhyFinishAutoNeg(struct nic *nic);
+
+#ifdef MONITOR
+static void TLan_PhyMonitor(struct nic *nic);
+#endif
+
+
+static void refill_rx(struct nic *nic __unused);
+
+static int TLan_MiiReadReg(struct nic *nic __unused, u16, u16, u16 *);
+static void TLan_MiiSendData(u16, u32, unsigned);
+static void TLan_MiiSync(u16);
+static void TLan_MiiWriteReg(struct nic *nic __unused, u16, u16, u16);
+
+
+static const char *media[] = {
+ "10BaseT-HD ", "10BaseT-FD ", "100baseTx-HD ",
+ "100baseTx-FD", "100baseT4", 0
+};
+
+/* This much match tlan_pci_tbl[]! */
+enum tlan_nics {
+ NETEL10 = 0, NETEL100 = 1, NETFLEX3I = 2, THUNDER = 3, NETFLEX3B =
+ 4, NETEL100PI = 5,
+ NETEL100D = 6, NETEL100I = 7, OC2183 = 8, OC2325 = 9, OC2326 =
+ 10, NETELLIGENT_10_100_WS_5100 = 11,
+ NETELLIGENT_10_T2 = 12
+};
+
+struct pci_id_info {
+ const char *name;
+ int nic_id;
+ struct match_info {
+ u32 pci, pci_mask, subsystem, subsystem_mask;
+ u32 revision, revision_mask; /* Only 8 bits. */
+ } id;
+ u32 flags;
+ u16 addrOfs; /* Address Offset */
+};
+
+static const struct pci_id_info tlan_pci_tbl[] = {
+ {"Compaq Netelligent 10 T PCI UTP", NETEL10,
+ {0xae340e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_ACTIVITY_LED, 0x83},
+ {"Compaq Netelligent 10/100 TX PCI UTP", NETEL100,
+ {0xae320e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_ACTIVITY_LED, 0x83},
+ {"Compaq Integrated NetFlex-3/P", NETFLEX3I,
+ {0xae350e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_NONE, 0x83},
+ {"Compaq NetFlex-3/P", THUNDER,
+ {0xf1300e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83},
+ {"Compaq NetFlex-3/P", NETFLEX3B,
+ {0xf1500e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_NONE, 0x83},
+ {"Compaq Netelligent Integrated 10/100 TX UTP", NETEL100PI,
+ {0xae430e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_ACTIVITY_LED, 0x83},
+ {"Compaq Netelligent Dual 10/100 TX PCI UTP", NETEL100D,
+ {0xae400e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_NONE, 0x83},
+ {"Compaq Netelligent 10/100 TX Embedded UTP", NETEL100I,
+ {0xb0110e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_NONE, 0x83},
+ {"Olicom OC-2183/2185", OC2183,
+ {0x0013108d, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_USE_INTERN_10, 0x83},
+ {"Olicom OC-2325", OC2325,
+ {0x0012108d, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_UNMANAGED_PHY, 0xF8},
+ {"Olicom OC-2326", OC2326,
+ {0x0014108d, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_USE_INTERN_10, 0xF8},
+ {"Compaq Netelligent 10/100 TX UTP", NETELLIGENT_10_100_WS_5100,
+ {0xb0300e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_ACTIVITY_LED, 0x83},
+ {"Compaq Netelligent 10 T/2 PCI UTP/Coax", NETELLIGENT_10_T2,
+ {0xb0120e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_NONE, 0x83},
+ {"Compaq NetFlex-3/E", 0, /* EISA card */
+ {0, 0, 0, 0, 0, 0},
+ TLAN_ADAPTER_ACTIVITY_LED | TLAN_ADAPTER_UNMANAGED_PHY |
+ TLAN_ADAPTER_BIT_RATE_PHY, 0x83},
+ {"Compaq NetFlex-3/E", 0, /* EISA card */
+ {0, 0, 0, 0, 0, 0},
+ TLAN_ADAPTER_ACTIVITY_LED, 0x83},
+ {0, 0,
+ {0, 0, 0, 0, 0, 0},
+ 0, 0},
+};
+
+struct TLanList {
+ u32 forward;
+ u16 cStat;
+ u16 frameSize;
+ struct {
+ u32 count;
+ u32 address;
+ } buffer[TLAN_BUFFERS_PER_LIST];
+};
+
+struct {
+ struct TLanList tx_ring[TLAN_NUM_TX_LISTS];
+ unsigned char txb[TLAN_MAX_FRAME_SIZE * TLAN_NUM_TX_LISTS];
+ struct TLanList rx_ring[TLAN_NUM_RX_LISTS];
+ unsigned char rxb[TLAN_MAX_FRAME_SIZE * TLAN_NUM_RX_LISTS];
+} tlan_buffers __shared;
+#define tx_ring tlan_buffers.tx_ring
+#define txb tlan_buffers.txb
+#define rx_ring tlan_buffers.rx_ring
+#define rxb tlan_buffers.rxb
+
+typedef u8 TLanBuffer[TLAN_MAX_FRAME_SIZE];
+
+static int chip_idx;
+
+/*****************************************************************
+* TLAN Private Information Structure
+*
+****************************************************************/
+static struct tlan_private {
+ unsigned short vendor_id; /* PCI Vendor code */
+ unsigned short dev_id; /* PCI Device code */
+ const char *nic_name;
+ unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indicies */
+ unsigned rx_buf_sz; /* Based on mtu + Slack */
+ struct TLanList *txList;
+ u32 txHead;
+ u32 txInProgress;
+ u32 txTail;
+ int eoc;
+ u32 phyOnline;
+ u32 aui;
+ u32 duplex;
+ u32 phy[2];
+ u32 phyNum;
+ u32 speed;
+ u8 tlanRev;
+ u8 tlanFullDuplex;
+ u8 link;
+ u8 neg_be_verbose;
+} TLanPrivateInfo;
+
+static struct tlan_private *priv;
+
+static u32 BASE;
+
+/***************************************************************
+* TLan_ResetLists
+*
+* Returns:
+* Nothing
+* Parms:
+* dev The device structure with the list
+* stuctures to be reset.
+*
+* This routine sets the variables associated with managing
+* the TLAN lists to their initial values.
+*
+**************************************************************/
+
+static void TLan_ResetLists(struct nic *nic __unused)
+{
+
+ int i;
+ struct TLanList *list;
+ priv->txHead = 0;
+ priv->txTail = 0;
+
+ for (i = 0; i < TLAN_NUM_TX_LISTS; i++) {
+ list = &tx_ring[i];
+ list->cStat = TLAN_CSTAT_UNUSED;
+ list->buffer[0].address = virt_to_bus(txb +
+ (i * TLAN_MAX_FRAME_SIZE));
+ list->buffer[2].count = 0;
+ list->buffer[2].address = 0;
+ list->buffer[9].address = 0;
+ }
+
+ priv->cur_rx = 0;
+ priv->rx_buf_sz = (TLAN_MAX_FRAME_SIZE);
+// priv->rx_head_desc = &rx_ring[0];
+
+ /* Initialize all the Rx descriptors */
+ for (i = 0; i < TLAN_NUM_RX_LISTS; i++) {
+ rx_ring[i].forward = virt_to_le32desc(&rx_ring[i + 1]);
+ rx_ring[i].cStat = TLAN_CSTAT_READY;
+ rx_ring[i].frameSize = TLAN_MAX_FRAME_SIZE;
+ rx_ring[i].buffer[0].count =
+ TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;
+ rx_ring[i].buffer[0].address =
+ virt_to_le32desc(&rxb[i * TLAN_MAX_FRAME_SIZE]);
+ rx_ring[i].buffer[1].count = 0;
+ rx_ring[i].buffer[1].address = 0;
+ }
+
+ /* Mark the last entry as wrapping the ring */
+ rx_ring[i - 1].forward = virt_to_le32desc(&rx_ring[0]);
+ priv->dirty_rx = (unsigned int) (i - TLAN_NUM_RX_LISTS);
+
+} /* TLan_ResetLists */
+
+/***************************************************************
+* TLan_Reset
+*
+* Returns:
+* 0
+* Parms:
+* dev Pointer to device structure of adapter
+* to be reset.
+*
+* This function resets the adapter and it's physical
+* device. See Chap. 3, pp. 9-10 of the "ThunderLAN
+* Programmer's Guide" for details. The routine tries to
+* implement what is detailed there, though adjustments
+* have been made.
+*
+**************************************************************/
+
+void TLan_ResetAdapter(struct nic *nic __unused)
+{
+ int i;
+ u32 addr;
+ u32 data;
+ u8 data8;
+
+ priv->tlanFullDuplex = FALSE;
+ priv->phyOnline = 0;
+/* 1. Assert reset bit. */
+
+ data = inl(BASE + TLAN_HOST_CMD);
+ data |= TLAN_HC_AD_RST;
+ outl(data, BASE + TLAN_HOST_CMD);
+
+ udelay(1000);
+
+/* 2. Turn off interrupts. ( Probably isn't necessary ) */
+
+ data = inl(BASE + TLAN_HOST_CMD);
+ data |= TLAN_HC_INT_OFF;
+ outl(data, BASE + TLAN_HOST_CMD);
+/* 3. Clear AREGs and HASHs. */
+
+ for (i = TLAN_AREG_0; i <= TLAN_HASH_2; i += 4) {
+ TLan_DioWrite32(BASE, (u16) i, 0);
+ }
+
+/* 4. Setup NetConfig register. */
+
+ data =
+ TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
+ TLan_DioWrite16(BASE, TLAN_NET_CONFIG, (u16) data);
+
+/* 5. Load Ld_Tmr and Ld_Thr in HOST_CMD. */
+
+ outl(TLAN_HC_LD_TMR | 0x3f, BASE + TLAN_HOST_CMD);
+ outl(TLAN_HC_LD_THR | 0x0, BASE + TLAN_HOST_CMD);
+
+/* 6. Unreset the MII by setting NMRST (in NetSio) to 1. */
+
+ outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR);
+ addr = BASE + TLAN_DIO_DATA + TLAN_NET_SIO;
+ TLan_SetBit(TLAN_NET_SIO_NMRST, addr);
+
+/* 7. Setup the remaining registers. */
+
+ if (priv->tlanRev >= 0x30) {
+ data8 = TLAN_ID_TX_EOC | TLAN_ID_RX_EOC;
+ TLan_DioWrite8(BASE, TLAN_INT_DIS, data8);
+ }
+ TLan_PhyDetect(nic);
+ data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN;
+
+ if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_BIT_RATE_PHY) {
+ data |= TLAN_NET_CFG_BIT;
+ if (priv->aui == 1) {
+ TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x0a);
+ } else if (priv->duplex == TLAN_DUPLEX_FULL) {
+ TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x00);
+ priv->tlanFullDuplex = TRUE;
+ } else {
+ TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x08);
+ }
+ }
+
+ if (priv->phyNum == 0) {
+ data |= TLAN_NET_CFG_PHY_EN;
+ }
+ TLan_DioWrite16(BASE, TLAN_NET_CONFIG, (u16) data);
+
+ if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY) {
+ TLan_FinishReset(nic);
+ } else {
+ TLan_PhyPowerDown(nic);
+ }
+
+} /* TLan_ResetAdapter */
+
+void TLan_FinishReset(struct nic *nic)
+{
+
+ u8 data;
+ u32 phy;
+ u8 sio;
+ u16 status;
+ u16 partner;
+ u16 tlphy_ctl;
+ u16 tlphy_par;
+ u16 tlphy_id1, tlphy_id2;
+ int i;
+
+ phy = priv->phy[priv->phyNum];
+
+ data = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP;
+ if (priv->tlanFullDuplex) {
+ data |= TLAN_NET_CMD_DUPLEX;
+ }
+ TLan_DioWrite8(BASE, TLAN_NET_CMD, data);
+ data = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5;
+ if (priv->phyNum == 0) {
+ data |= TLAN_NET_MASK_MASK7;
+ }
+ TLan_DioWrite8(BASE, TLAN_NET_MASK, data);
+ TLan_DioWrite16(BASE, TLAN_MAX_RX, ((1536) + 7) & ~7);
+ TLan_MiiReadReg(nic, phy, MII_PHYSID1, &tlphy_id1);
+ TLan_MiiReadReg(nic, phy, MII_PHYSID2, &tlphy_id2);
+
+ if ((tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY)
+ || (priv->aui)) {
+ status = BMSR_LSTATUS;
+ DBG ( "TLAN: %s: Link forced.\n", priv->nic_name );
+ } else {
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
+ udelay(1000);
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
+ if ((status & BMSR_LSTATUS) && /* We only support link info on Nat.Sem. PHY's */
+ (tlphy_id1 == NAT_SEM_ID1)
+ && (tlphy_id2 == NAT_SEM_ID2)) {
+ TLan_MiiReadReg(nic, phy, MII_LPA, &partner);
+ TLan_MiiReadReg(nic, phy, TLAN_TLPHY_PAR,
+ &tlphy_par);
+
+ DBG ( "TLAN: %s: Link active with ",
+ priv->nic_name );
+ if (!(tlphy_par & TLAN_PHY_AN_EN_STAT)) {
+ DBG ( "forced 10%sMbps %s-Duplex\n",
+ tlphy_par & TLAN_PHY_SPEED_100 ? ""
+ : "0",
+ tlphy_par & TLAN_PHY_DUPLEX_FULL ?
+ "Full" : "Half" );
+ } else {
+ DBG
+ ( "AutoNegotiation enabled, at 10%sMbps %s-Duplex\n",
+ tlphy_par & TLAN_PHY_SPEED_100 ? "" :
+ "0",
+ tlphy_par & TLAN_PHY_DUPLEX_FULL ?
+ "Full" : "Half" );
+ DBG ( "TLAN: Partner capability: " );
+ for (i = 5; i <= 10; i++)
+ if (partner & (1 << i)) {
+ DBG ( "%s", media[i - 5] );
+ }
+ DBG ( "\n" );
+ }
+
+ TLan_DioWrite8(BASE, TLAN_LED_REG, TLAN_LED_LINK);
+#ifdef MONITOR
+ /* We have link beat..for now anyway */
+ priv->link = 1;
+ /*Enabling link beat monitoring */
+ /* TLan_SetTimer( nic, (10*HZ), TLAN_TIMER_LINK_BEAT ); */
+ mdelay(10000);
+ TLan_PhyMonitor(nic);
+#endif
+ } else if (status & BMSR_LSTATUS) {
+ DBG ( "TLAN: %s: Link active\n", priv->nic_name );
+ TLan_DioWrite8(BASE, TLAN_LED_REG, TLAN_LED_LINK);
+ }
+ }
+
+ if (priv->phyNum == 0) {
+ TLan_MiiReadReg(nic, phy, TLAN_TLPHY_CTL, &tlphy_ctl);
+ tlphy_ctl |= TLAN_TC_INTEN;
+ TLan_MiiWriteReg(nic, phy, TLAN_TLPHY_CTL, tlphy_ctl);
+ sio = TLan_DioRead8(BASE, TLAN_NET_SIO);
+ sio |= TLAN_NET_SIO_MINTEN;
+ TLan_DioWrite8(BASE, TLAN_NET_SIO, sio);
+ }
+
+ if (status & BMSR_LSTATUS) {
+ TLan_SetMac(nic, 0, nic->node_addr);
+ priv->phyOnline = 1;
+ outb((TLAN_HC_INT_ON >> 8), BASE + TLAN_HOST_CMD + 1);
+ outl(virt_to_bus(&rx_ring), BASE + TLAN_CH_PARM);
+ outl(TLAN_HC_GO | TLAN_HC_RT, BASE + TLAN_HOST_CMD);
+ } else {
+ DBG
+ ( "TLAN: %s: Link inactive, will retry in 10 secs...\n",
+ priv->nic_name );
+ /* TLan_SetTimer( nic, (10*HZ), TLAN_TIMER_FINISH_RESET ); */
+ mdelay(10000);
+ TLan_FinishReset(nic);
+ return;
+
+ }
+
+} /* TLan_FinishReset */
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int tlan_poll(struct nic *nic, int retrieve)
+{
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+ u32 framesize;
+ u32 host_cmd = 0;
+ u32 ack = 1;
+ int eoc = 0;
+ int entry = priv->cur_rx % TLAN_NUM_RX_LISTS;
+ u16 tmpCStat = le32_to_cpu(rx_ring[entry].cStat);
+ u16 host_int = inw(BASE + TLAN_HOST_INT);
+
+ if ((tmpCStat & TLAN_CSTAT_FRM_CMP) && !retrieve)
+ return 1;
+
+ outw(host_int, BASE + TLAN_HOST_INT);
+
+ if (!(tmpCStat & TLAN_CSTAT_FRM_CMP))
+ return 0;
+
+ /* printf("PI-1: 0x%hX\n", host_int); */
+ if (tmpCStat & TLAN_CSTAT_EOC)
+ eoc = 1;
+
+ framesize = rx_ring[entry].frameSize;
+
+ nic->packetlen = framesize;
+
+ DBG ( ".%d.", (unsigned int) framesize );
+
+ memcpy(nic->packet, rxb +
+ (priv->cur_rx * TLAN_MAX_FRAME_SIZE), nic->packetlen);
+
+ rx_ring[entry].cStat = 0;
+
+ DBG ( "%d", entry );
+
+ entry = (entry + 1) % TLAN_NUM_RX_LISTS;
+ priv->cur_rx = entry;
+ if (eoc) {
+ if ((rx_ring[entry].cStat & TLAN_CSTAT_READY) ==
+ TLAN_CSTAT_READY) {
+ ack |= TLAN_HC_GO | TLAN_HC_RT;
+ host_cmd = TLAN_HC_ACK | ack | 0x001C0000;
+ outl(host_cmd, BASE + TLAN_HOST_CMD);
+ }
+ } else {
+ host_cmd = TLAN_HC_ACK | ack | (0x000C0000);
+ outl(host_cmd, BASE + TLAN_HOST_CMD);
+
+ DBG ( "AC: 0x%hX\n", inw(BASE + TLAN_CH_PARM) );
+ DBG ( "PI-2: 0x%hX\n", inw(BASE + TLAN_HOST_INT) );
+ }
+ refill_rx(nic);
+ return (1); /* initially as this is called to flush the input */
+}
+
+static void refill_rx(struct nic *nic __unused)
+{
+ int entry = 0;
+
+ for (;
+ (priv->cur_rx - priv->dirty_rx +
+ TLAN_NUM_RX_LISTS) % TLAN_NUM_RX_LISTS > 0;
+ priv->dirty_rx = (priv->dirty_rx + 1) % TLAN_NUM_RX_LISTS) {
+ entry = priv->dirty_rx % TLAN_NUM_TX_LISTS;
+ rx_ring[entry].frameSize = TLAN_MAX_FRAME_SIZE;
+ rx_ring[entry].cStat = TLAN_CSTAT_READY;
+ }
+
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void tlan_transmit(struct nic *nic, const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p)
+{ /* Packet */
+ u16 nstype;
+ u32 to;
+ struct TLanList *tail_list;
+ struct TLanList *head_list;
+ u8 *tail_buffer;
+ u32 ack = 0;
+ u32 host_cmd;
+ int eoc = 0;
+ u16 tmpCStat;
+ u16 host_int = inw(BASE + TLAN_HOST_INT);
+
+ int entry = 0;
+
+ DBG ( "INT0-0x%hX\n", host_int );
+
+ if (!priv->phyOnline) {
+ printf("TRANSMIT: %s PHY is not ready\n", priv->nic_name);
+ return;
+ }
+
+ tail_list = priv->txList + priv->txTail;
+
+ if (tail_list->cStat != TLAN_CSTAT_UNUSED) {
+ printf("TRANSMIT: %s is busy (Head=%p Tail=%x)\n",
+ priv->nic_name, priv->txList, (unsigned int) priv->txTail);
+ tx_ring[entry].cStat = TLAN_CSTAT_UNUSED;
+// priv->txBusyCount++;
+ return;
+ }
+
+ tail_list->forward = 0;
+
+ tail_buffer = txb + (priv->txTail * TLAN_MAX_FRAME_SIZE);
+
+ /* send the packet to destination */
+ memcpy(tail_buffer, d, ETH_ALEN);
+ memcpy(tail_buffer + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ nstype = htons((u16) t);
+ memcpy(tail_buffer + 2 * ETH_ALEN, (u8 *) & nstype, 2);
+ memcpy(tail_buffer + ETH_HLEN, p, s);
+
+ s += ETH_HLEN;
+ s &= 0x0FFF;
+ while (s < ETH_ZLEN)
+ tail_buffer[s++] = '\0';
+
+ /*=====================================================*/
+ /* Receive
+ * 0000 0000 0001 1100
+ * 0000 0000 0000 1100
+ * 0000 0000 0000 0011 = 0x0003
+ *
+ * 0000 0000 0000 0000 0000 0000 0000 0011
+ * 0000 0000 0000 1100 0000 0000 0000 0000 = 0x000C0000
+ *
+ * Transmit
+ * 0000 0000 0001 1100
+ * 0000 0000 0000 0100
+ * 0000 0000 0000 0001 = 0x0001
+ *
+ * 0000 0000 0000 0000 0000 0000 0000 0001
+ * 0000 0000 0000 0100 0000 0000 0000 0000 = 0x00040000
+ * */
+
+ /* Setup the transmit descriptor */
+ tail_list->frameSize = (u16) s;
+ tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) s;
+ tail_list->buffer[1].count = 0;
+ tail_list->buffer[1].address = 0;
+
+ tail_list->cStat = TLAN_CSTAT_READY;
+
+ DBG ( "INT1-0x%hX\n", inw(BASE + TLAN_HOST_INT) );
+
+ if (!priv->txInProgress) {
+ priv->txInProgress = 1;
+ outl(virt_to_le32desc(tail_list), BASE + TLAN_CH_PARM);
+ outl(TLAN_HC_GO, BASE + TLAN_HOST_CMD);
+ } else {
+ if (priv->txTail == 0) {
+ DBG ( "Out buffer\n" );
+ (priv->txList + (TLAN_NUM_TX_LISTS - 1))->forward =
+ virt_to_le32desc(tail_list);
+ } else {
+ DBG ( "Fix this \n" );
+ (priv->txList + (priv->txTail - 1))->forward =
+ virt_to_le32desc(tail_list);
+ }
+ }
+
+ CIRC_INC(priv->txTail, TLAN_NUM_TX_LISTS);
+
+ DBG ( "INT2-0x%hX\n", inw(BASE + TLAN_HOST_INT) );
+
+ to = currticks() + TX_TIME_OUT;
+ while ((tail_list->cStat == TLAN_CSTAT_READY) && currticks() < to);
+
+ head_list = priv->txList + priv->txHead;
+ while (((tmpCStat = head_list->cStat) & TLAN_CSTAT_FRM_CMP)
+ && (ack < 255)) {
+ ack++;
+ if(tmpCStat & TLAN_CSTAT_EOC)
+ eoc =1;
+ head_list->cStat = TLAN_CSTAT_UNUSED;
+ CIRC_INC(priv->txHead, TLAN_NUM_TX_LISTS);
+ head_list = priv->txList + priv->txHead;
+
+ }
+ if(!ack)
+ printf("Incomplete TX Frame\n");
+
+ if(eoc) {
+ head_list = priv->txList + priv->txHead;
+ if ((head_list->cStat & TLAN_CSTAT_READY) == TLAN_CSTAT_READY) {
+ outl(virt_to_le32desc(head_list), BASE + TLAN_CH_PARM);
+ ack |= TLAN_HC_GO;
+ } else {
+ priv->txInProgress = 0;
+ }
+ }
+ if(ack) {
+ host_cmd = TLAN_HC_ACK | ack;
+ outl(host_cmd, BASE + TLAN_HOST_CMD);
+ }
+
+ if(priv->tlanRev < 0x30 ) {
+ ack = 1;
+ head_list = priv->txList + priv->txHead;
+ if ((head_list->cStat & TLAN_CSTAT_READY) == TLAN_CSTAT_READY) {
+ outl(virt_to_le32desc(head_list), BASE + TLAN_CH_PARM);
+ ack |= TLAN_HC_GO;
+ } else {
+ priv->txInProgress = 0;
+ }
+ host_cmd = TLAN_HC_ACK | ack | 0x00140000;
+ outl(host_cmd, BASE + TLAN_HOST_CMD);
+
+ }
+
+ if (currticks() >= to) {
+ printf("TX Time Out");
+ }
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void tlan_disable ( struct nic *nic __unused ) {
+ /* put the card in its initial state */
+ /* This function serves 3 purposes.
+ * This disables DMA and interrupts so we don't receive
+ * unexpected packets or interrupts from the card after
+ * etherboot has finished.
+ * This frees resources so etherboot may use
+ * this driver on another interface
+ * This allows etherboot to reinitialize the interface
+ * if something is something goes wrong.
+ *
+ */
+ outl(TLAN_HC_AD_RST, BASE + TLAN_HOST_CMD);
+}
+
+/**************************************************************************
+IRQ - Enable, Disable, or Force interrupts
+***************************************************************************/
+static void tlan_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations tlan_operations = {
+ .connect = dummy_connect,
+ .poll = tlan_poll,
+ .transmit = tlan_transmit,
+ .irq = tlan_irq,
+
+};
+
+static void TLan_SetMulticastList(struct nic *nic) {
+ int i;
+ u8 tmp;
+
+ /* !IFF_PROMISC */
+ tmp = TLan_DioRead8(BASE, TLAN_NET_CMD);
+ TLan_DioWrite8(BASE, TLAN_NET_CMD, tmp & ~TLAN_NET_CMD_CAF);
+
+ /* IFF_ALLMULTI */
+ for(i = 0; i< 3; i++)
+ TLan_SetMac(nic, i + 1, NULL);
+ TLan_DioWrite32(BASE, TLAN_HASH_1, 0xFFFFFFFF);
+ TLan_DioWrite32(BASE, TLAN_HASH_2, 0xFFFFFFFF);
+
+
+}
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+
+#define board_found 1
+#define valid_link 0
+static int tlan_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ u16 data = 0;
+ int err;
+ int i;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ nic->irqno = 0;
+ nic->ioaddr = pci->ioaddr;
+
+ BASE = pci->ioaddr;
+
+ /* Set nic as PCI bus master */
+ adjust_pci_device(pci);
+
+ /* Point to private storage */
+ priv = &TLanPrivateInfo;
+
+ /* Figure out which chip we're dealing with */
+ i = 0;
+ chip_idx = -1;
+ while (tlan_pci_tbl[i].name) {
+ if ((((u32) pci->device << 16) | pci->vendor) ==
+ (tlan_pci_tbl[i].id.pci & 0xffffffff)) {
+ chip_idx = i;
+ break;
+ }
+ i++;
+ }
+
+ priv->vendor_id = pci->vendor;
+ priv->dev_id = pci->device;
+ priv->nic_name = pci->id->name;
+ priv->eoc = 0;
+
+ err = 0;
+ for (i = 0; i < 6; i++)
+ err |= TLan_EeReadByte(BASE,
+ (u8) tlan_pci_tbl[chip_idx].
+ addrOfs + i,
+ (u8 *) & nic->node_addr[i]);
+ if (err) {
+ printf ( "TLAN: %s: Error reading MAC from eeprom: %d\n",
+ pci->id->name, err);
+ } else {
+ DBG ( "%s: %s at ioaddr %#lX, ",
+ pci->id->name, eth_ntoa ( nic->node_addr ), pci->ioaddr );
+ }
+
+ priv->tlanRev = TLan_DioRead8(BASE, TLAN_DEF_REVISION);
+ printf("revision: 0x%hX\n", priv->tlanRev);
+
+ TLan_ResetLists(nic);
+ TLan_ResetAdapter(nic);
+
+ data = inl(BASE + TLAN_HOST_CMD);
+ data |= TLAN_HC_INT_OFF;
+ outw(data, BASE + TLAN_HOST_CMD);
+
+ TLan_SetMulticastList(nic);
+ udelay(100);
+ priv->txList = tx_ring;
+
+/* if (board_found && valid_link)
+ {*/
+ /* point to NIC specific routines */
+ nic->nic_op = &tlan_operations;
+ return 1;
+}
+
+
+/*****************************************************************************
+******************************************************************************
+
+ ThunderLAN Driver Eeprom routines
+
+ The Compaq Netelligent 10 and 10/100 cards use a Microchip 24C02A
+ EEPROM. These functions are based on information in Microchip's
+ data sheet. I don't know how well this functions will work with
+ other EEPROMs.
+
+******************************************************************************
+*****************************************************************************/
+
+
+/***************************************************************
+* TLan_EeSendStart
+*
+* Returns:
+* Nothing
+* Parms:
+* io_base The IO port base address for the
+* TLAN device with the EEPROM to
+* use.
+*
+* This function sends a start cycle to an EEPROM attached
+* to a TLAN chip.
+*
+**************************************************************/
+
+void TLan_EeSendStart(u16 io_base)
+{
+ u16 sio;
+
+ outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
+ sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
+
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
+ TLan_SetBit(TLAN_NET_SIO_ETXEN, sio);
+ TLan_ClearBit(TLAN_NET_SIO_EDATA, sio);
+ TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
+
+} /* TLan_EeSendStart */
+
+/***************************************************************
+* TLan_EeSendByte
+*
+* Returns:
+* If the correct ack was received, 0, otherwise 1
+* Parms: io_base The IO port base address for the
+* TLAN device with the EEPROM to
+* use.
+* data The 8 bits of information to
+* send to the EEPROM.
+* stop If TLAN_EEPROM_STOP is passed, a
+* stop cycle is sent after the
+* byte is sent after the ack is
+* read.
+*
+* This function sends a byte on the serial EEPROM line,
+* driving the clock to send each bit. The function then
+* reverses transmission direction and reads an acknowledge
+* bit.
+*
+**************************************************************/
+
+int TLan_EeSendByte(u16 io_base, u8 data, int stop)
+{
+ int err;
+ u8 place;
+ u16 sio;
+
+ outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
+ sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
+
+ /* Assume clock is low, tx is enabled; */
+ for (place = 0x80; place != 0; place >>= 1) {
+ if (place & data)
+ TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
+ else
+ TLan_ClearBit(TLAN_NET_SIO_EDATA, sio);
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
+ }
+ TLan_ClearBit(TLAN_NET_SIO_ETXEN, sio);
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ err = TLan_GetBit(TLAN_NET_SIO_EDATA, sio);
+ TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_SetBit(TLAN_NET_SIO_ETXEN, sio);
+
+ if ((!err) && stop) {
+ TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); /* STOP, raise data while clock is high */
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
+ }
+
+ return (err);
+
+} /* TLan_EeSendByte */
+
+/***************************************************************
+* TLan_EeReceiveByte
+*
+* Returns:
+* Nothing
+* Parms:
+* io_base The IO port base address for the
+* TLAN device with the EEPROM to
+* use.
+* data An address to a char to hold the
+* data sent from the EEPROM.
+* stop If TLAN_EEPROM_STOP is passed, a
+* stop cycle is sent after the
+* byte is received, and no ack is
+* sent.
+*
+* This function receives 8 bits of data from the EEPROM
+* over the serial link. It then sends and ack bit, or no
+* ack and a stop bit. This function is used to retrieve
+* data after the address of a byte in the EEPROM has been
+* sent.
+*
+**************************************************************/
+
+void TLan_EeReceiveByte(u16 io_base, u8 * data, int stop)
+{
+ u8 place;
+ u16 sio;
+
+ outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
+ sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
+ *data = 0;
+
+ /* Assume clock is low, tx is enabled; */
+ TLan_ClearBit(TLAN_NET_SIO_ETXEN, sio);
+ for (place = 0x80; place; place >>= 1) {
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ if (TLan_GetBit(TLAN_NET_SIO_EDATA, sio))
+ *data |= place;
+ TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
+ }
+
+ TLan_SetBit(TLAN_NET_SIO_ETXEN, sio);
+ if (!stop) {
+ TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); /* Ack = 0 */
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
+ } else {
+ TLan_SetBit(TLAN_NET_SIO_EDATA, sio); /* No ack = 1 (?) */
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); /* STOP, raise data while clock is high */
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
+ }
+
+} /* TLan_EeReceiveByte */
+
+/***************************************************************
+* TLan_EeReadByte
+*
+* Returns:
+* No error = 0, else, the stage at which the error
+* occurred.
+* Parms:
+* io_base The IO port base address for the
+* TLAN device with the EEPROM to
+* use.
+* ee_addr The address of the byte in the
+* EEPROM whose contents are to be
+* retrieved.
+* data An address to a char to hold the
+* data obtained from the EEPROM.
+*
+* This function reads a byte of information from an byte
+* cell in the EEPROM.
+*
+**************************************************************/
+
+int TLan_EeReadByte(u16 io_base, u8 ee_addr, u8 * data)
+{
+ int err;
+ int ret = 0;
+
+
+ TLan_EeSendStart(io_base);
+ err = TLan_EeSendByte(io_base, 0xA0, TLAN_EEPROM_ACK);
+ if (err) {
+ ret = 1;
+ goto fail;
+ }
+ err = TLan_EeSendByte(io_base, ee_addr, TLAN_EEPROM_ACK);
+ if (err) {
+ ret = 2;
+ goto fail;
+ }
+ TLan_EeSendStart(io_base);
+ err = TLan_EeSendByte(io_base, 0xA1, TLAN_EEPROM_ACK);
+ if (err) {
+ ret = 3;
+ goto fail;
+ }
+ TLan_EeReceiveByte(io_base, data, TLAN_EEPROM_STOP);
+ fail:
+
+ return ret;
+
+} /* TLan_EeReadByte */
+
+
+/*****************************************************************************
+******************************************************************************
+
+ThunderLAN Driver MII Routines
+
+These routines are based on the information in Chap. 2 of the
+"ThunderLAN Programmer's Guide", pp. 15-24.
+
+******************************************************************************
+*****************************************************************************/
+
+
+/***************************************************************
+* TLan_MiiReadReg
+*
+* Returns:
+* 0 if ack received ok
+* 1 otherwise.
+*
+* Parms:
+* dev The device structure containing
+* The io address and interrupt count
+* for this device.
+* phy The address of the PHY to be queried.
+* reg The register whose contents are to be
+* retreived.
+* val A pointer to a variable to store the
+* retrieved value.
+*
+* This function uses the TLAN's MII bus to retreive the contents
+* of a given register on a PHY. It sends the appropriate info
+* and then reads the 16-bit register value from the MII bus via
+* the TLAN SIO register.
+*
+**************************************************************/
+
+int TLan_MiiReadReg(struct nic *nic __unused, u16 phy, u16 reg, u16 * val)
+{
+ u8 nack;
+ u16 sio, tmp;
+ u32 i;
+ int err;
+ int minten;
+
+ err = FALSE;
+ outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR);
+ sio = BASE + TLAN_DIO_DATA + TLAN_NET_SIO;
+
+ TLan_MiiSync(BASE);
+
+ minten = TLan_GetBit(TLAN_NET_SIO_MINTEN, sio);
+ if (minten)
+ TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio);
+
+ TLan_MiiSendData(BASE, 0x1, 2); /* Start ( 01b ) */
+ TLan_MiiSendData(BASE, 0x2, 2); /* Read ( 10b ) */
+ TLan_MiiSendData(BASE, phy, 5); /* Device # */
+ TLan_MiiSendData(BASE, reg, 5); /* Register # */
+
+
+ TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio); /* Change direction */
+
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Clock Idle bit */
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Wait 300ns */
+
+ nack = TLan_GetBit(TLAN_NET_SIO_MDATA, sio); /* Check for ACK */
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio); /* Finish ACK */
+ if (nack) { /* No ACK, so fake it */
+ for (i = 0; i < 16; i++) {
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+ }
+ tmp = 0xffff;
+ err = TRUE;
+ } else { /* ACK, so read data */
+ for (tmp = 0, i = 0x8000; i; i >>= 1) {
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
+ if (TLan_GetBit(TLAN_NET_SIO_MDATA, sio))
+ tmp |= i;
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+ }
+ }
+
+
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Idle cycle */
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+
+ if (minten)
+ TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);
+
+ *val = tmp;
+
+ return err;
+
+} /* TLan_MiiReadReg */
+
+/***************************************************************
+* TLan_MiiSendData
+*
+* Returns:
+* Nothing
+* Parms:
+* base_port The base IO port of the adapter in
+* question.
+* dev The address of the PHY to be queried.
+* data The value to be placed on the MII bus.
+* num_bits The number of bits in data that are to
+* be placed on the MII bus.
+*
+* This function sends on sequence of bits on the MII
+* configuration bus.
+*
+**************************************************************/
+
+void TLan_MiiSendData(u16 base_port, u32 data, unsigned num_bits)
+{
+ u16 sio;
+ u32 i;
+
+ if (num_bits == 0)
+ return;
+
+ outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR);
+ sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
+ TLan_SetBit(TLAN_NET_SIO_MTXEN, sio);
+
+ for (i = (0x1 << (num_bits - 1)); i; i >>= 1) {
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
+ (void) TLan_GetBit(TLAN_NET_SIO_MCLK, sio);
+ if (data & i)
+ TLan_SetBit(TLAN_NET_SIO_MDATA, sio);
+ else
+ TLan_ClearBit(TLAN_NET_SIO_MDATA, sio);
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+ (void) TLan_GetBit(TLAN_NET_SIO_MCLK, sio);
+ }
+
+} /* TLan_MiiSendData */
+
+/***************************************************************
+* TLan_MiiSync
+*
+* Returns:
+* Nothing
+* Parms:
+* base_port The base IO port of the adapter in
+* question.
+*
+* This functions syncs all PHYs in terms of the MII configuration
+* bus.
+*
+**************************************************************/
+
+void TLan_MiiSync(u16 base_port)
+{
+ int i;
+ u16 sio;
+
+ outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR);
+ sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
+
+ TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio);
+ for (i = 0; i < 32; i++) {
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+ }
+
+} /* TLan_MiiSync */
+
+/***************************************************************
+* TLan_MiiWriteReg
+*
+* Returns:
+* Nothing
+* Parms:
+* dev The device structure for the device
+* to write to.
+* phy The address of the PHY to be written to.
+* reg The register whose contents are to be
+* written.
+* val The value to be written to the register.
+*
+* This function uses the TLAN's MII bus to write the contents of a
+* given register on a PHY. It sends the appropriate info and then
+* writes the 16-bit register value from the MII configuration bus
+* via the TLAN SIO register.
+*
+**************************************************************/
+
+void TLan_MiiWriteReg(struct nic *nic __unused, u16 phy, u16 reg, u16 val)
+{
+ u16 sio;
+ int minten;
+
+ outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR);
+ sio = BASE + TLAN_DIO_DATA + TLAN_NET_SIO;
+
+ TLan_MiiSync(BASE);
+
+ minten = TLan_GetBit(TLAN_NET_SIO_MINTEN, sio);
+ if (minten)
+ TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio);
+
+ TLan_MiiSendData(BASE, 0x1, 2); /* Start ( 01b ) */
+ TLan_MiiSendData(BASE, 0x1, 2); /* Write ( 01b ) */
+ TLan_MiiSendData(BASE, phy, 5); /* Device # */
+ TLan_MiiSendData(BASE, reg, 5); /* Register # */
+
+ TLan_MiiSendData(BASE, 0x2, 2); /* Send ACK */
+ TLan_MiiSendData(BASE, val, 16); /* Send Data */
+
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Idle cycle */
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+
+ if (minten)
+ TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);
+
+
+} /* TLan_MiiWriteReg */
+
+/***************************************************************
+* TLan_SetMac
+*
+* Returns:
+* Nothing
+* Parms:
+* dev Pointer to device structure of adapter
+* on which to change the AREG.
+* areg The AREG to set the address in (0 - 3).
+* mac A pointer to an array of chars. Each
+* element stores one byte of the address.
+* IE, it isn't in ascii.
+*
+* This function transfers a MAC address to one of the
+* TLAN AREGs (address registers). The TLAN chip locks
+* the register on writing to offset 0 and unlocks the
+* register after writing to offset 5. If NULL is passed
+* in mac, then the AREG is filled with 0's.
+*
+**************************************************************/
+
+void TLan_SetMac(struct nic *nic __unused, int areg, unsigned char *mac)
+{
+ int i;
+
+ areg *= 6;
+
+ if (mac != NULL) {
+ for (i = 0; i < 6; i++)
+ TLan_DioWrite8(BASE, TLAN_AREG_0 + areg + i,
+ mac[i]);
+ } else {
+ for (i = 0; i < 6; i++)
+ TLan_DioWrite8(BASE, TLAN_AREG_0 + areg + i, 0);
+ }
+
+} /* TLan_SetMac */
+
+/*********************************************************************
+* TLan_PhyDetect
+*
+* Returns:
+* Nothing
+* Parms:
+* dev A pointer to the device structure of the adapter
+* for which the PHY needs determined.
+*
+* So far I've found that adapters which have external PHYs
+* may also use the internal PHY for part of the functionality.
+* (eg, AUI/Thinnet). This function finds out if this TLAN
+* chip has an internal PHY, and then finds the first external
+* PHY (starting from address 0) if it exists).
+*
+********************************************************************/
+
+void TLan_PhyDetect(struct nic *nic)
+{
+ u16 control;
+ u16 hi;
+ u16 lo;
+ u32 phy;
+
+ if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY) {
+ priv->phyNum = 0xFFFF;
+ return;
+ }
+
+ TLan_MiiReadReg(nic, TLAN_PHY_MAX_ADDR, MII_PHYSID1, &hi);
+
+ if (hi != 0xFFFF) {
+ priv->phy[0] = TLAN_PHY_MAX_ADDR;
+ } else {
+ priv->phy[0] = TLAN_PHY_NONE;
+ }
+
+ priv->phy[1] = TLAN_PHY_NONE;
+ for (phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++) {
+ TLan_MiiReadReg(nic, phy, MII_BMCR, &control);
+ TLan_MiiReadReg(nic, phy, MII_PHYSID1, &hi);
+ TLan_MiiReadReg(nic, phy, MII_PHYSID2, &lo);
+ if ((control != 0xFFFF) || (hi != 0xFFFF)
+ || (lo != 0xFFFF)) {
+ printf("PHY found at %hX %hX %hX %hX\n",
+ (unsigned int) phy, control, hi, lo);
+ if ((priv->phy[1] == TLAN_PHY_NONE)
+ && (phy != TLAN_PHY_MAX_ADDR)) {
+ priv->phy[1] = phy;
+ }
+ }
+ }
+
+ if (priv->phy[1] != TLAN_PHY_NONE) {
+ priv->phyNum = 1;
+ } else if (priv->phy[0] != TLAN_PHY_NONE) {
+ priv->phyNum = 0;
+ } else {
+ printf
+ ("TLAN: Cannot initialize device, no PHY was found!\n");
+ }
+
+} /* TLan_PhyDetect */
+
+void TLan_PhyPowerDown(struct nic *nic)
+{
+
+ u16 value;
+ DBG ( "%s: Powering down PHY(s).\n", priv->nic_name );
+ value = BMCR_PDOWN | BMCR_LOOPBACK | BMCR_ISOLATE;
+ TLan_MiiSync(BASE);
+ TLan_MiiWriteReg(nic, priv->phy[priv->phyNum], MII_BMCR, value);
+ if ((priv->phyNum == 0) && (priv->phy[1] != TLAN_PHY_NONE)
+ &&
+ (!(tlan_pci_tbl[chip_idx].
+ flags & TLAN_ADAPTER_USE_INTERN_10))) {
+ TLan_MiiSync(BASE);
+ TLan_MiiWriteReg(nic, priv->phy[1], MII_BMCR, value);
+ }
+
+ /* Wait for 50 ms and powerup
+ * This is abitrary. It is intended to make sure the
+ * tranceiver settles.
+ */
+ /* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_PUP ); */
+ mdelay(50);
+ TLan_PhyPowerUp(nic);
+
+} /* TLan_PhyPowerDown */
+
+
+void TLan_PhyPowerUp(struct nic *nic)
+{
+ u16 value;
+
+ DBG ( "%s: Powering up PHY.\n", priv->nic_name );
+ TLan_MiiSync(BASE);
+ value = BMCR_LOOPBACK;
+ TLan_MiiWriteReg(nic, priv->phy[priv->phyNum], MII_BMCR, value);
+ TLan_MiiSync(BASE);
+ /* Wait for 500 ms and reset the
+ * tranceiver. The TLAN docs say both 50 ms and
+ * 500 ms, so do the longer, just in case.
+ */
+ mdelay(500);
+ TLan_PhyReset(nic);
+ /* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_RESET ); */
+
+} /* TLan_PhyPowerUp */
+
+void TLan_PhyReset(struct nic *nic)
+{
+ u16 phy;
+ u16 value;
+
+ phy = priv->phy[priv->phyNum];
+
+ DBG ( "%s: Reseting PHY.\n", priv->nic_name );
+ TLan_MiiSync(BASE);
+ value = BMCR_LOOPBACK | BMCR_RESET;
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, value);
+ TLan_MiiReadReg(nic, phy, MII_BMCR, &value);
+ while (value & BMCR_RESET) {
+ TLan_MiiReadReg(nic, phy, MII_BMCR, &value);
+ }
+
+ /* Wait for 500 ms and initialize.
+ * I don't remember why I wait this long.
+ * I've changed this to 50ms, as it seems long enough.
+ */
+ /* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_START_LINK ); */
+ mdelay(50);
+ TLan_PhyStartLink(nic);
+
+} /* TLan_PhyReset */
+
+
+void TLan_PhyStartLink(struct nic *nic)
+{
+
+ u16 ability;
+ u16 control;
+ u16 data;
+ u16 phy;
+ u16 status;
+ u16 tctl;
+
+ phy = priv->phy[priv->phyNum];
+ DBG ( "%s: Trying to activate link.\n", priv->nic_name );
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &ability);
+
+ if ((status & BMSR_ANEGCAPABLE) && (!priv->aui)) {
+ ability = status >> 11;
+ if (priv->speed == TLAN_SPEED_10 &&
+ priv->duplex == TLAN_DUPLEX_HALF) {
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x0000);
+ } else if (priv->speed == TLAN_SPEED_10 &&
+ priv->duplex == TLAN_DUPLEX_FULL) {
+ priv->tlanFullDuplex = TRUE;
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x0100);
+ } else if (priv->speed == TLAN_SPEED_100 &&
+ priv->duplex == TLAN_DUPLEX_HALF) {
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x2000);
+ } else if (priv->speed == TLAN_SPEED_100 &&
+ priv->duplex == TLAN_DUPLEX_FULL) {
+ priv->tlanFullDuplex = TRUE;
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x2100);
+ } else {
+
+ /* Set Auto-Neg advertisement */
+ TLan_MiiWriteReg(nic, phy, MII_ADVERTISE,
+ (ability << 5) | 1);
+ /* Enablee Auto-Neg */
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x1000);
+ /* Restart Auto-Neg */
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x1200);
+ /* Wait for 4 sec for autonegotiation
+ * to complete. The max spec time is less than this
+ * but the card need additional time to start AN.
+ * .5 sec should be plenty extra.
+ */
+ DBG ( "TLAN: %s: Starting autonegotiation.\n",
+ priv->nic_name );
+ mdelay(4000);
+ TLan_PhyFinishAutoNeg(nic);
+ /* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_PHY_FINISH_AN ); */
+ return;
+ }
+
+ }
+
+ if ((priv->aui) && (priv->phyNum != 0)) {
+ priv->phyNum = 0;
+ data =
+ TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN |
+ TLAN_NET_CFG_PHY_EN;
+ TLan_DioWrite16(BASE, TLAN_NET_CONFIG, data);
+ mdelay(50);
+ /* TLan_SetTimer( dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN ); */
+ TLan_PhyPowerDown(nic);
+ return;
+ } else if (priv->phyNum == 0) {
+ control = 0;
+ TLan_MiiReadReg(nic, phy, TLAN_TLPHY_CTL, &tctl);
+ if (priv->aui) {
+ tctl |= TLAN_TC_AUISEL;
+ } else {
+ tctl &= ~TLAN_TC_AUISEL;
+ if (priv->duplex == TLAN_DUPLEX_FULL) {
+ control |= BMCR_FULLDPLX;
+ priv->tlanFullDuplex = TRUE;
+ }
+ if (priv->speed == TLAN_SPEED_100) {
+ control |= BMCR_SPEED100;
+ }
+ }
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, control);
+ TLan_MiiWriteReg(nic, phy, TLAN_TLPHY_CTL, tctl);
+ }
+
+ /* Wait for 2 sec to give the tranceiver time
+ * to establish link.
+ */
+ /* TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_FINISH_RESET ); */
+ mdelay(2000);
+ TLan_FinishReset(nic);
+
+} /* TLan_PhyStartLink */
+
+void TLan_PhyFinishAutoNeg(struct nic *nic)
+{
+
+ u16 an_adv;
+ u16 an_lpa;
+ u16 data;
+ u16 mode;
+ u16 phy;
+ u16 status;
+
+ phy = priv->phy[priv->phyNum];
+
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
+ udelay(1000);
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
+
+ if (!(status & BMSR_ANEGCOMPLETE)) {
+ /* Wait for 8 sec to give the process
+ * more time. Perhaps we should fail after a while.
+ */
+ if (!priv->neg_be_verbose++) {
+ printf
+ ("TLAN: Giving autonegotiation more time.\n");
+ printf
+ ("TLAN: Please check that your adapter has\n");
+ printf
+ ("TLAN: been properly connected to a HUB or Switch.\n");
+ printf
+ ("TLAN: Trying to establish link in the background...\n");
+ }
+ mdelay(8000);
+ TLan_PhyFinishAutoNeg(nic);
+ /* TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN ); */
+ return;
+ }
+
+ DBG ( "TLAN: %s: Autonegotiation complete.\n", priv->nic_name );
+ TLan_MiiReadReg(nic, phy, MII_ADVERTISE, &an_adv);
+ TLan_MiiReadReg(nic, phy, MII_LPA, &an_lpa);
+ mode = an_adv & an_lpa & 0x03E0;
+ if (mode & 0x0100) {
+ printf("Full Duplex\n");
+ priv->tlanFullDuplex = TRUE;
+ } else if (!(mode & 0x0080) && (mode & 0x0040)) {
+ priv->tlanFullDuplex = TRUE;
+ printf("Full Duplex\n");
+ }
+
+ if ((!(mode & 0x0180))
+ && (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_USE_INTERN_10)
+ && (priv->phyNum != 0)) {
+ priv->phyNum = 0;
+ data =
+ TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN |
+ TLAN_NET_CFG_PHY_EN;
+ TLan_DioWrite16(BASE, TLAN_NET_CONFIG, data);
+ /* TLan_SetTimer( nic, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN ); */
+ mdelay(400);
+ TLan_PhyPowerDown(nic);
+ return;
+ }
+
+ if (priv->phyNum == 0) {
+ if ((priv->duplex == TLAN_DUPLEX_FULL)
+ || (an_adv & an_lpa & 0x0040)) {
+ TLan_MiiWriteReg(nic, phy, MII_BMCR,
+ BMCR_ANENABLE | BMCR_FULLDPLX);
+ DBG
+ ( "TLAN: Starting internal PHY with FULL-DUPLEX\n" );
+ } else {
+ TLan_MiiWriteReg(nic, phy, MII_BMCR,
+ BMCR_ANENABLE);
+ DBG
+ ( "TLAN: Starting internal PHY with HALF-DUPLEX\n" );
+ }
+ }
+
+ /* Wait for 100 ms. No reason in partiticular.
+ */
+ /* TLan_SetTimer( dev, (HZ/10), TLAN_TIMER_FINISH_RESET ); */
+ mdelay(100);
+ TLan_FinishReset(nic);
+
+} /* TLan_PhyFinishAutoNeg */
+
+#ifdef MONITOR
+
+/*********************************************************************
+*
+* TLan_phyMonitor
+*
+* Returns:
+* None
+*
+* Params:
+* dev The device structure of this device.
+*
+*
+* This function monitors PHY condition by reading the status
+* register via the MII bus. This can be used to give info
+* about link changes (up/down), and possible switch to alternate
+* media.
+*
+********************************************************************/
+
+void TLan_PhyMonitor(struct net_device *dev)
+{
+ TLanPrivateInfo *priv = dev->priv;
+ u16 phy;
+ u16 phy_status;
+
+ phy = priv->phy[priv->phyNum];
+
+ /* Get PHY status register */
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &phy_status);
+
+ /* Check if link has been lost */
+ if (!(phy_status & BMSR_LSTATUS)) {
+ if (priv->link) {
+ priv->link = 0;
+ printf("TLAN: %s has lost link\n", priv->nic_name);
+ priv->flags &= ~IFF_RUNNING;
+ mdelay(2000);
+ TLan_PhyMonitor(nic);
+ /* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT ); */
+ return;
+ }
+ }
+
+ /* Link restablished? */
+ if ((phy_status & BMSR_LSTATUS) && !priv->link) {
+ priv->link = 1;
+ printf("TLAN: %s has reestablished link\n",
+ priv->nic_name);
+ priv->flags |= IFF_RUNNING;
+ }
+
+ /* Setup a new monitor */
+ /* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT ); */
+ mdelay(2000);
+ TLan_PhyMonitor(nic);
+}
+
+#endif /* MONITOR */
+
+static struct pci_device_id tlan_nics[] = {
+ PCI_ROM(0x0e11, 0xae34, "netel10", "Compaq Netelligent 10 T PCI UTP", 0),
+ PCI_ROM(0x0e11, 0xae32, "netel100","Compaq Netelligent 10/100 TX PCI UTP", 0),
+ PCI_ROM(0x0e11, 0xae35, "netflex3i", "Compaq Integrated NetFlex-3/P", 0),
+ PCI_ROM(0x0e11, 0xf130, "thunder", "Compaq NetFlex-3/P", 0),
+ PCI_ROM(0x0e11, 0xf150, "netflex3b", "Compaq NetFlex-3/P", 0),
+ PCI_ROM(0x0e11, 0xae43, "netel100pi", "Compaq Netelligent Integrated 10/100 TX UTP", 0),
+ PCI_ROM(0x0e11, 0xae40, "netel100d", "Compaq Netelligent Dual 10/100 TX PCI UTP", 0),
+ PCI_ROM(0x0e11, 0xb011, "netel100i", "Compaq Netelligent 10/100 TX Embedded UTP", 0),
+ PCI_ROM(0x108d, 0x0013, "oc2183", "Olicom OC-2183/2185", 0),
+ PCI_ROM(0x108d, 0x0012, "oc2325", "Olicom OC-2325", 0),
+ PCI_ROM(0x108d, 0x0014, "oc2326", "Olicom OC-2326", 0),
+ PCI_ROM(0x0e11, 0xb030, "netelligent_10_100_ws_5100", "Compaq Netelligent 10/100 TX UTP", 0),
+ PCI_ROM(0x0e11, 0xb012, "netelligent_10_t2", "Compaq Netelligent 10 T/2 PCI UTP/Coax", 0),
+};
+
+PCI_DRIVER ( tlan_driver, tlan_nics, PCI_NO_CLASS );
+
+DRIVER ( "TLAN/PCI", nic_driver, pci_driver, tlan_driver,
+ tlan_probe, tlan_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/tlan.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/tlan.h
new file mode 100644
index 00000000..c972588b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/tlan.h
@@ -0,0 +1,500 @@
+/**************************************************************************
+*
+* tlan.c -- Etherboot device driver for the Texas Instruments ThunderLAN
+* Written 2003-2003 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code (almost all) based on:
+* tlan.c: Linux ThunderLan Driver:
+*
+* by James Banks
+*
+* (C) 1997-1998 Caldera, Inc.
+* (C) 1998 James Banks
+* (C) 1999-2001 Torben Mathiasen
+* (C) 2002 Samuel Chessman
+*
+* REVISION HISTORY:
+* ================
+* v1.0 07-08-2003 timlegge Initial not quite working version
+*
+* Indent Style: indent -kr -i8
+***************************************************************************/
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*****************************************************************
+* TLan Definitions
+*
+****************************************************************/
+
+#define FALSE 0
+#define TRUE 1
+
+#define TLAN_MIN_FRAME_SIZE 64
+#define TLAN_MAX_FRAME_SIZE 1600
+
+#define TLAN_NUM_RX_LISTS 4
+#define TLAN_NUM_TX_LISTS 2
+
+#define TLAN_IGNORE 0
+#define TLAN_RECORD 1
+/*
+#define TLAN_DBG(lvl, format, args...) if (debug&lvl) printf("TLAN: " format, ##args );
+*/
+#define TLAN_DEBUG_GNRL 0x0001
+#define TLAN_DEBUG_TX 0x0002
+#define TLAN_DEBUG_RX 0x0004
+#define TLAN_DEBUG_LIST 0x0008
+#define TLAN_DEBUG_PROBE 0x0010
+
+#define TX_TIMEOUT (10*HZ) /* We need time for auto-neg */
+#define MAX_TLAN_BOARDS 8 /* Max number of boards installed at a time */
+
+
+ /*****************************************************************
+ * Device Identification Definitions
+ *
+ ****************************************************************/
+
+#define PCI_DEVICE_ID_NETELLIGENT_10_T2 0xB012
+#define PCI_DEVICE_ID_NETELLIGENT_10_100_WS_5100 0xB030
+#ifndef PCI_DEVICE_ID_OLICOM_OC2183
+#define PCI_DEVICE_ID_OLICOM_OC2183 0x0013
+#endif
+#ifndef PCI_DEVICE_ID_OLICOM_OC2325
+#define PCI_DEVICE_ID_OLICOM_OC2325 0x0012
+#endif
+#ifndef PCI_DEVICE_ID_OLICOM_OC2326
+#define PCI_DEVICE_ID_OLICOM_OC2326 0x0014
+#endif
+
+typedef struct tlan_adapter_entry {
+ u16 vendorId;
+ u16 deviceId;
+ char *deviceLabel;
+ u32 flags;
+ u16 addrOfs;
+} TLanAdapterEntry;
+
+#define TLAN_ADAPTER_NONE 0x00000000
+#define TLAN_ADAPTER_UNMANAGED_PHY 0x00000001
+#define TLAN_ADAPTER_BIT_RATE_PHY 0x00000002
+#define TLAN_ADAPTER_USE_INTERN_10 0x00000004
+#define TLAN_ADAPTER_ACTIVITY_LED 0x00000008
+
+#define TLAN_SPEED_DEFAULT 0
+#define TLAN_SPEED_10 10
+#define TLAN_SPEED_100 100
+
+#define TLAN_DUPLEX_DEFAULT 0
+#define TLAN_DUPLEX_HALF 1
+#define TLAN_DUPLEX_FULL 2
+
+
+
+ /*****************************************************************
+ * EISA Definitions
+ *
+ ****************************************************************/
+
+#define EISA_ID 0xc80 /* EISA ID Registers */
+#define EISA_ID0 0xc80 /* EISA ID Register 0 */
+#define EISA_ID1 0xc81 /* EISA ID Register 1 */
+#define EISA_ID2 0xc82 /* EISA ID Register 2 */
+#define EISA_ID3 0xc83 /* EISA ID Register 3 */
+#define EISA_CR 0xc84 /* EISA Control Register */
+#define EISA_REG0 0xc88 /* EISA Configuration Register 0 */
+#define EISA_REG1 0xc89 /* EISA Configuration Register 1 */
+#define EISA_REG2 0xc8a /* EISA Configuration Register 2 */
+#define EISA_REG3 0xc8f /* EISA Configuration Register 3 */
+#define EISA_APROM 0xc90 /* Ethernet Address PROM */
+
+
+
+ /*****************************************************************
+ * Rx/Tx List Definitions
+ *
+ ****************************************************************/
+
+#define TLAN_BUFFERS_PER_LIST 10
+#define TLAN_LAST_BUFFER 0x80000000
+#define TLAN_CSTAT_UNUSED 0x8000
+#define TLAN_CSTAT_FRM_CMP 0x4000
+#define TLAN_CSTAT_READY 0x3000
+#define TLAN_CSTAT_EOC 0x0800
+#define TLAN_CSTAT_RX_ERROR 0x0400
+#define TLAN_CSTAT_PASS_CRC 0x0200
+#define TLAN_CSTAT_DP_PR 0x0100
+
+
+
+
+
+
+ /*****************************************************************
+ * PHY definitions
+ *
+ ****************************************************************/
+
+#define TLAN_PHY_MAX_ADDR 0x1F
+#define TLAN_PHY_NONE 0x20
+
+
+
+ /*****************************************************************
+ * TLan Driver Timer Definitions
+ *
+ ****************************************************************/
+
+#define TLAN_TIMER_LINK_BEAT 1
+#define TLAN_TIMER_ACTIVITY 2
+#define TLAN_TIMER_PHY_PDOWN 3
+#define TLAN_TIMER_PHY_PUP 4
+#define TLAN_TIMER_PHY_RESET 5
+#define TLAN_TIMER_PHY_START_LINK 6
+#define TLAN_TIMER_PHY_FINISH_AN 7
+#define TLAN_TIMER_FINISH_RESET 8
+
+#define TLAN_TIMER_ACT_DELAY (HZ/10)
+
+
+
+
+ /*****************************************************************
+ * TLan Driver Eeprom Definitions
+ *
+ ****************************************************************/
+
+#define TLAN_EEPROM_ACK 0
+#define TLAN_EEPROM_STOP 1
+
+
+
+
+ /*****************************************************************
+ * Host Register Offsets and Contents
+ *
+ ****************************************************************/
+
+#define TLAN_HOST_CMD 0x00
+#define TLAN_HC_GO 0x80000000
+#define TLAN_HC_STOP 0x40000000
+#define TLAN_HC_ACK 0x20000000
+#define TLAN_HC_CS_MASK 0x1FE00000
+#define TLAN_HC_EOC 0x00100000
+#define TLAN_HC_RT 0x00080000
+#define TLAN_HC_NES 0x00040000
+#define TLAN_HC_AD_RST 0x00008000
+#define TLAN_HC_LD_TMR 0x00004000
+#define TLAN_HC_LD_THR 0x00002000
+#define TLAN_HC_REQ_INT 0x00001000
+#define TLAN_HC_INT_OFF 0x00000800
+#define TLAN_HC_INT_ON 0x00000400
+#define TLAN_HC_AC_MASK 0x000000FF
+#define TLAN_CH_PARM 0x04
+#define TLAN_DIO_ADR 0x08
+#define TLAN_DA_ADR_INC 0x8000
+#define TLAN_DA_RAM_ADR 0x4000
+#define TLAN_HOST_INT 0x0A
+#define TLAN_HI_IV_MASK 0x1FE0
+#define TLAN_HI_IT_MASK 0x001C
+#define TLAN_DIO_DATA 0x0C
+
+
+/* ThunderLAN Internal Register DIO Offsets */
+
+#define TLAN_NET_CMD 0x00
+#define TLAN_NET_CMD_NRESET 0x80
+#define TLAN_NET_CMD_NWRAP 0x40
+#define TLAN_NET_CMD_CSF 0x20
+#define TLAN_NET_CMD_CAF 0x10
+#define TLAN_NET_CMD_NOBRX 0x08
+#define TLAN_NET_CMD_DUPLEX 0x04
+#define TLAN_NET_CMD_TRFRAM 0x02
+#define TLAN_NET_CMD_TXPACE 0x01
+#define TLAN_NET_SIO 0x01
+#define TLAN_NET_SIO_MINTEN 0x80
+#define TLAN_NET_SIO_ECLOK 0x40
+#define TLAN_NET_SIO_ETXEN 0x20
+#define TLAN_NET_SIO_EDATA 0x10
+#define TLAN_NET_SIO_NMRST 0x08
+#define TLAN_NET_SIO_MCLK 0x04
+#define TLAN_NET_SIO_MTXEN 0x02
+#define TLAN_NET_SIO_MDATA 0x01
+#define TLAN_NET_STS 0x02
+#define TLAN_NET_STS_MIRQ 0x80
+#define TLAN_NET_STS_HBEAT 0x40
+#define TLAN_NET_STS_TXSTOP 0x20
+#define TLAN_NET_STS_RXSTOP 0x10
+#define TLAN_NET_STS_RSRVD 0x0F
+#define TLAN_NET_MASK 0x03
+#define TLAN_NET_MASK_MASK7 0x80
+#define TLAN_NET_MASK_MASK6 0x40
+#define TLAN_NET_MASK_MASK5 0x20
+#define TLAN_NET_MASK_MASK4 0x10
+#define TLAN_NET_MASK_RSRVD 0x0F
+#define TLAN_NET_CONFIG 0x04
+#define TLAN_NET_CFG_RCLK 0x8000
+#define TLAN_NET_CFG_TCLK 0x4000
+#define TLAN_NET_CFG_BIT 0x2000
+#define TLAN_NET_CFG_RXCRC 0x1000
+#define TLAN_NET_CFG_PEF 0x0800
+#define TLAN_NET_CFG_1FRAG 0x0400
+#define TLAN_NET_CFG_1CHAN 0x0200
+#define TLAN_NET_CFG_MTEST 0x0100
+#define TLAN_NET_CFG_PHY_EN 0x0080
+#define TLAN_NET_CFG_MSMASK 0x007F
+#define TLAN_MAN_TEST 0x06
+#define TLAN_DEF_VENDOR_ID 0x08
+#define TLAN_DEF_DEVICE_ID 0x0A
+#define TLAN_DEF_REVISION 0x0C
+#define TLAN_DEF_SUBCLASS 0x0D
+#define TLAN_DEF_MIN_LAT 0x0E
+#define TLAN_DEF_MAX_LAT 0x0F
+#define TLAN_AREG_0 0x10
+#define TLAN_AREG_1 0x16
+#define TLAN_AREG_2 0x1C
+#define TLAN_AREG_3 0x22
+#define TLAN_HASH_1 0x28
+#define TLAN_HASH_2 0x2C
+#define TLAN_GOOD_TX_FRMS 0x30
+#define TLAN_TX_UNDERUNS 0x33
+#define TLAN_GOOD_RX_FRMS 0x34
+#define TLAN_RX_OVERRUNS 0x37
+#define TLAN_DEFERRED_TX 0x38
+#define TLAN_CRC_ERRORS 0x3A
+#define TLAN_CODE_ERRORS 0x3B
+#define TLAN_MULTICOL_FRMS 0x3C
+#define TLAN_SINGLECOL_FRMS 0x3E
+#define TLAN_EXCESSCOL_FRMS 0x40
+#define TLAN_LATE_COLS 0x41
+#define TLAN_CARRIER_LOSS 0x42
+#define TLAN_ACOMMIT 0x43
+#define TLAN_LED_REG 0x44
+#define TLAN_LED_ACT 0x10
+#define TLAN_LED_LINK 0x01
+#define TLAN_BSIZE_REG 0x45
+#define TLAN_MAX_RX 0x46
+#define TLAN_INT_DIS 0x48
+#define TLAN_ID_TX_EOC 0x04
+#define TLAN_ID_RX_EOF 0x02
+#define TLAN_ID_RX_EOC 0x01
+
+
+
+/* ThunderLAN Interrupt Codes */
+
+#define TLAN_INT_NUMBER_OF_INTS 8
+
+#define TLAN_INT_NONE 0x0000
+#define TLAN_INT_TX_EOF 0x0001
+#define TLAN_INT_STAT_OVERFLOW 0x0002
+#define TLAN_INT_RX_EOF 0x0003
+#define TLAN_INT_DUMMY 0x0004
+#define TLAN_INT_TX_EOC 0x0005
+#define TLAN_INT_STATUS_CHECK 0x0006
+#define TLAN_INT_RX_EOC 0x0007
+
+
+
+/* ThunderLAN MII Registers */
+
+/* ThunderLAN Specific MII/PHY Registers */
+
+#define TLAN_TLPHY_ID 0x10
+#define TLAN_TLPHY_CTL 0x11
+#define TLAN_TC_IGLINK 0x8000
+#define TLAN_TC_SWAPOL 0x4000
+#define TLAN_TC_AUISEL 0x2000
+#define TLAN_TC_SQEEN 0x1000
+#define TLAN_TC_MTEST 0x0800
+#define TLAN_TC_RESERVED 0x07F8
+#define TLAN_TC_NFEW 0x0004
+#define TLAN_TC_INTEN 0x0002
+#define TLAN_TC_TINT 0x0001
+#define TLAN_TLPHY_STS 0x12
+#define TLAN_TS_MINT 0x8000
+#define TLAN_TS_PHOK 0x4000
+#define TLAN_TS_POLOK 0x2000
+#define TLAN_TS_TPENERGY 0x1000
+#define TLAN_TS_RESERVED 0x0FFF
+#define TLAN_TLPHY_PAR 0x19
+#define TLAN_PHY_CIM_STAT 0x0020
+#define TLAN_PHY_SPEED_100 0x0040
+#define TLAN_PHY_DUPLEX_FULL 0x0080
+#define TLAN_PHY_AN_EN_STAT 0x0400
+
+/* National Sem. & Level1 PHY id's */
+#define NAT_SEM_ID1 0x2000
+#define NAT_SEM_ID2 0x5C01
+#define LEVEL1_ID1 0x7810
+#define LEVEL1_ID2 0x0000
+
+#define CIRC_INC( a, b ) if ( ++a >= b ) a = 0
+
+/* Routines to access internal registers. */
+
+static inline u8 TLan_DioRead8(u16 base_addr, u16 internal_addr)
+{
+ outw(internal_addr, base_addr + TLAN_DIO_ADR);
+ return (inb((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x3)));
+
+} /* TLan_DioRead8 */
+
+
+
+
+static inline u16 TLan_DioRead16(u16 base_addr, u16 internal_addr)
+{
+ outw(internal_addr, base_addr + TLAN_DIO_ADR);
+ return (inw((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x2)));
+
+} /* TLan_DioRead16 */
+
+
+
+
+static inline u32 TLan_DioRead32(u16 base_addr, u16 internal_addr)
+{
+ outw(internal_addr, base_addr + TLAN_DIO_ADR);
+ return (inl(base_addr + TLAN_DIO_DATA));
+
+} /* TLan_DioRead32 */
+
+
+
+
+static inline void TLan_DioWrite8(u16 base_addr, u16 internal_addr, u8 data)
+{
+ outw(internal_addr, base_addr + TLAN_DIO_ADR);
+ outb(data, base_addr + TLAN_DIO_DATA + (internal_addr & 0x3));
+
+}
+
+
+
+
+static inline void TLan_DioWrite16(u16 base_addr, u16 internal_addr, u16 data)
+{
+ outw(internal_addr, base_addr + TLAN_DIO_ADR);
+ outw(data, base_addr + TLAN_DIO_DATA + (internal_addr & 0x2));
+
+}
+
+
+
+
+static inline void TLan_DioWrite32(u16 base_addr, u16 internal_addr, u32 data)
+{
+ outw(internal_addr, base_addr + TLAN_DIO_ADR);
+ outl(data, base_addr + TLAN_DIO_DATA + (internal_addr & 0x2));
+
+}
+
+
+
+#if 0
+static inline void TLan_ClearBit(u8 bit, u16 port)
+{
+ outb_p(inb_p(port) & ~bit, port);
+}
+
+
+
+
+static inline int TLan_GetBit(u8 bit, u16 port)
+{
+ return ((int) (inb_p(port) & bit));
+}
+
+
+
+
+static inline void TLan_SetBit(u8 bit, u16 port)
+{
+ outb_p(inb_p(port) | bit, port);
+}
+#endif
+
+#define TLan_ClearBit( bit, port ) outb_p(inb_p(port) & ~bit, port)
+#define TLan_GetBit( bit, port ) ((int) (inb_p(port) & bit))
+#define TLan_SetBit( bit, port ) outb_p(inb_p(port) | bit, port)
+
+#ifdef I_LIKE_A_FAST_HASH_FUNCTION
+/* given 6 bytes, view them as 8 6-bit numbers and return the XOR of those */
+/* the code below is about seven times as fast as the original code */
+static inline u32 TLan_HashFunc(u8 * a)
+{
+ u8 hash;
+
+ hash = (a[0] ^ a[3]); /* & 077 */
+ hash ^= ((a[0] ^ a[3]) >> 6); /* & 003 */
+ hash ^= ((a[1] ^ a[4]) << 2); /* & 074 */
+ hash ^= ((a[1] ^ a[4]) >> 4); /* & 017 */
+ hash ^= ((a[2] ^ a[5]) << 4); /* & 060 */
+ hash ^= ((a[2] ^ a[5]) >> 2); /* & 077 */
+
+ return (hash & 077);
+}
+
+#else /* original code */
+
+static inline u32 xor(u32 a, u32 b)
+{
+ return ((a && !b) || (!a && b));
+}
+
+#define XOR8( a, b, c, d, e, f, g, h ) xor( a, xor( b, xor( c, xor( d, xor( e, xor( f, xor( g, h ) ) ) ) ) ) )
+#define DA( a, bit ) ( ( (u8) a[bit/8] ) & ( (u8) ( 1 << bit%8 ) ) )
+
+static inline u32 TLan_HashFunc(u8 * a)
+{
+ u32 hash;
+
+ hash =
+ XOR8(DA(a, 0), DA(a, 6), DA(a, 12), DA(a, 18), DA(a, 24),
+ DA(a, 30), DA(a, 36), DA(a, 42));
+ hash |=
+ XOR8(DA(a, 1), DA(a, 7), DA(a, 13), DA(a, 19), DA(a, 25),
+ DA(a, 31), DA(a, 37), DA(a, 43)) << 1;
+ hash |=
+ XOR8(DA(a, 2), DA(a, 8), DA(a, 14), DA(a, 20), DA(a, 26),
+ DA(a, 32), DA(a, 38), DA(a, 44)) << 2;
+ hash |=
+ XOR8(DA(a, 3), DA(a, 9), DA(a, 15), DA(a, 21), DA(a, 27),
+ DA(a, 33), DA(a, 39), DA(a, 45)) << 3;
+ hash |=
+ XOR8(DA(a, 4), DA(a, 10), DA(a, 16), DA(a, 22), DA(a, 28),
+ DA(a, 34), DA(a, 40), DA(a, 46)) << 4;
+ hash |=
+ XOR8(DA(a, 5), DA(a, 11), DA(a, 17), DA(a, 23), DA(a, 29),
+ DA(a, 35), DA(a, 41), DA(a, 47)) << 5;
+
+ return hash;
+
+}
+
+#endif /* I_LIKE_A_FAST_HASH_FUNCTION */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/tulip.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/tulip.c
new file mode 100644
index 00000000..7a23b7e9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/tulip.c
@@ -0,0 +1,1969 @@
+/* -*- Mode:C; c-basic-offset:4; -*- */
+
+/*
+ Tulip and clone Etherboot Driver
+
+ By Marty Connor (mdc@etherboot.org)
+ Copyright (C) 2001 Entity Cyber, Inc.
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License, incorporated herein by reference.
+
+ As of April 2001 this driver should support most tulip cards that
+ the Linux tulip driver supports because Donald Becker's Linux media
+ detection code is now included.
+
+ Based on Ken Yap's Tulip Etherboot Driver and Donald Becker's
+ Linux Tulip Driver. Supports N-Way speed auto-configuration on
+ MX98715, MX98715A and MX98725. Support inexpensive PCI 10/100 cards
+ based on the Macronix MX987x5 chip, such as the SOHOware Fast
+ model SFA110A, and the LinkSYS model LNE100TX. The NetGear
+ model FA310X, based on the LC82C168 chip is supported.
+ The TRENDnet TE100-PCIA NIC which uses a genuine Intel 21143-PD
+ chipset is supported. Also, Davicom DM9102's.
+
+ Documentation and source code used:
+ Source for Etherboot driver at
+ http://etherboot.sourceforge.net/
+ MX98715A Data Sheet and MX98715A Application Note
+ on http://www.macronix.com/ (PDF format files)
+ Source for Linux tulip driver at
+ http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
+
+ Adapted by Ken Yap from
+ FreeBSD netboot DEC 21143 driver
+ Author: David Sharp
+ date: Nov/98
+
+ Some code fragments were taken from verious places, Ken Yap's
+ etherboot, FreeBSD's if_de.c, and various Linux related files.
+ DEC's manuals for the 21143 and SROM format were very helpful.
+ The Linux de driver development page has a number of links to
+ useful related information. Have a look at:
+ ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/tulip-devel.html
+*/
+
+FILE_LICENCE ( GPL_ANY );
+
+/*********************************************************************/
+/* Revision History */
+/*********************************************************************/
+
+/*
+ 08 Feb 2005 Ramesh Chander chhabaramesh at yahoo.co.in added table entries
+ for SGThomson STE10/100A
+ 07 Sep 2003 timlegge Multicast Support Added
+ 11 Apr 2001 mdc [patch to etherboot 4.7.24]
+ Major rewrite to include Linux tulip driver media detection
+ code. This driver should support a lot more cards now.
+ 16 Jul 2000 mdc 0.75b11
+ Added support for ADMtek 0985 Centaur-P, a "Comet" tulip clone
+ which is used on the LinkSYS LNE100TX v4.x cards. We already
+ support LNE100TX v2.0 cards, which use a different controller.
+ 04 Jul 2000 jam ?
+ Added test of status after receiving a packet from the card.
+ Also uncommented the tulip_disable routine. Stray packets
+ seemed to be causing problems.
+ 27 Apr 2000 njl ?
+ 29 Feb 2000 mdc 0.75b7
+ Increased reset delay to 3 seconds because Macronix cards seem to
+ need more reset time before card comes back to a usable state.
+ 26 Feb 2000 mdc 0.75b6
+ Added a 1 second delay after initializing the transmitter because
+ some cards seem to need the time or they drop the first packet
+ transmitted.
+ 23 Feb 2000 mdc 0.75b5
+ removed udelay code and used currticks() for more reliable delay
+ code in reset pause and sanity timeouts. Added function prototypes
+ and TX debugging code.
+ 21 Feb 2000 mdc patch to Etherboot 4.4.3
+ Incorporated patches from Bob Edwards and Paul Mackerras of
+ Linuxcare's OZLabs to deal with inefficiencies in tulip_transmit
+ and udelay. We now wait for packet transmission to complete
+ (or sanity timeout).
+ 04 Feb 2000 Robert.Edwards@anu.edu.au patch to Etherboot 4.4.2
+ patch to tulip.c that implements the automatic selection of the MII
+ interface on cards using the Intel/DEC 21143 reference design, in
+ particular, the TRENDnet TE100-PCIA NIC which uses a genuine Intel
+ 21143-PD chipset.
+ 11 Jan 2000 mdc 0.75b4
+ Added support for NetGear FA310TX card based on the LC82C168
+ chip. This should also support Lite-On LC82C168 boards.
+ Added simple MII support. Re-arranged code to better modularize
+ initializations.
+ 04 Dec 1999 mdc 0.75b3
+ Added preliminary support for LNE100TX PCI cards. Should work for
+ PNIC2 cards. No MII support, but single interface (RJ45) tulip
+ cards seem to not care.
+ 03 Dec 1999 mdc 0.75b2
+ Renamed from mx987x5 to tulip, merged in original tulip init code
+ from tulip.c to support other tulip compatible cards.
+ 02 Dec 1999 mdc 0.75b1
+ Released Beta MX987x5 Driver for code review and testing to netboot
+ and thinguin mailing lists.
+*/
+
+
+/*********************************************************************/
+/* Declarations */
+/*********************************************************************/
+
+#include "etherboot.h"
+#include "nic.h"
+
+#include <ipxe/ethernet.h>
+#include <ipxe/pci.h>
+
+/* User settable parameters */
+
+#define TX_TIME_OUT 2*TICKS_PER_SEC
+
+/* helpful macros if on a big_endian machine for changing byte order.
+ not strictly needed on Intel */
+#define get_unaligned(ptr) (*(ptr))
+#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
+#define get_u16(ptr) (*(u16 *)(ptr))
+#define virt_to_le32desc(addr) virt_to_bus(addr)
+
+#define TULIP_IOTYPE PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0
+#define TULIP_SIZE 0x80
+
+/* This is a mysterious value that can be written to CSR11 in the 21040 (only)
+ to support a pre-NWay full-duplex signaling mechanism using short frames.
+ No one knows what it should be, but if left at its default value some
+ 10base2(!) packets trigger a full-duplex-request interrupt. */
+#define FULL_DUPLEX_MAGIC 0x6969
+
+static const int csr0 = 0x01A00000 | 0x8000;
+
+/* The possible media types that can be set in options[] are: */
+#define MEDIA_MASK 31
+static const char * const medianame[32] = {
+ "10baseT", "10base2", "AUI", "100baseTx",
+ "10baseT-FDX", "100baseTx-FDX", "100baseT4", "100baseFx",
+ "100baseFx-FDX", "MII 10baseT", "MII 10baseT-FDX", "MII",
+ "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FDX", "MII 100baseT4",
+ "MII 100baseFx-HDX", "MII 100baseFx-FDX", "Home-PNA 1Mbps", "Invalid-19",
+};
+
+/* This much match tulip_tbl[]! Note 21142 == 21143. */
+enum tulip_chips {
+ DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3,
+ LC82C168, MX98713, MX98715, MX98725, AX88141, AX88140, PNIC2, COMET,
+ COMPEX9881, I21145, XIRCOM, SGThomson, /*Ramesh Chander*/
+};
+
+enum pci_id_flags_bits {
+ /* Set PCI command register bits before calling probe1(). */
+ PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+ /* Read and map the single following PCI BAR. */
+ PCI_ADDR0=0<<4, PCI_ADDR1=1<<4, PCI_ADDR2=2<<4, PCI_ADDR3=3<<4,
+ PCI_ADDR_64BITS=0x100, PCI_NO_ACPI_WAKE=0x200, PCI_NO_MIN_LATENCY=0x400,
+ PCI_UNUSED_IRQ=0x800,
+};
+
+struct pci_id_info {
+ char *name;
+ struct match_info {
+ u32 pci, pci_mask, subsystem, subsystem_mask;
+ u32 revision, revision_mask; /* Only 8 bits. */
+ } id;
+ enum pci_id_flags_bits pci_flags;
+ int io_size; /* Needed for I/O region check or ioremap(). */
+ int drv_flags; /* Driver use, intended as capability flags. */
+};
+
+static const struct pci_id_info pci_id_tbl[] = {
+ { "Digital DC21040 Tulip", { 0x00021011, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 0x80, DC21040 },
+ { "Digital DC21041 Tulip", { 0x00141011, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 0x80, DC21041 },
+ { "Digital DS21140A Tulip", { 0x00091011, 0xffffffff, 0,0, 0x20,0xf0 },
+ TULIP_IOTYPE, 0x80, DC21140 },
+ { "Digital DS21140 Tulip", { 0x00091011, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 0x80, DC21140 },
+ { "Digital DS21143 Tulip", { 0x00191011, 0xffffffff, 0,0, 65,0xff },
+ TULIP_IOTYPE, TULIP_SIZE, DC21142 },
+ { "Digital DS21142 Tulip", { 0x00191011, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, TULIP_SIZE, DC21142 },
+ { "Kingston KNE110tx (PNIC)", { 0x000211AD, 0xffffffff, 0xf0022646, 0xffffffff, 0, 0 },
+ TULIP_IOTYPE, 256, LC82C168 },
+ { "Lite-On 82c168 PNIC", { 0x000211AD, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, LC82C168 },
+ { "Macronix 98713 PMAC", { 0x051210d9, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, MX98713 },
+ { "Macronix 98715 PMAC", { 0x053110d9, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, MX98715 },
+ { "Macronix 98725 PMAC", { 0x053110d9, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, MX98725 },
+ { "ASIX AX88141", { 0x1400125B, 0xffffffff, 0,0, 0x10, 0xf0 },
+ TULIP_IOTYPE, 128, AX88141 },
+ { "ASIX AX88140", { 0x1400125B, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 128, AX88140 },
+ { "Lite-On LC82C115 PNIC-II", { 0xc11511AD, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, PNIC2 },
+ { "ADMtek AN981 Comet", { 0x09811317, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, COMET },
+ { "ADMTek AN983 Comet", { 0x12161113, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, COMET },
+ { "ADMTek Comet AN983b", { 0x95111317, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, COMET },
+ { "ADMtek Centaur-P", { 0x09851317, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, COMET },
+ { "ADMtek Centaur-C", { 0x19851317, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, COMET },
+ { "Compex RL100-TX", { 0x988111F6, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 128, COMPEX9881 },
+ { "Intel 21145 Tulip", { 0x00398086, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 128, I21145 },
+ { "Xircom Tulip clone", { 0x0003115d, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 128, XIRCOM },
+ { "Davicom DM9102", { 0x91021282, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 0x80, DC21140 },
+ { "Davicom DM9100", { 0x91001282, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 0x80, DC21140 },
+ { "Macronix mxic-98715 (EN1217)", { 0x12171113, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, MX98715 },
+ { "3Com 3cSOHO100B-TX (ADMtek Centuar)", { 0x930010b7, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, TULIP_SIZE, COMET },
+ { "SG Thomson STE10/100A", { 0x2774104a, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, COMET }, /*Ramesh Chander*/
+ { 0, { 0, 0, 0, 0, 0, 0 }, 0, 0, 0 },
+};
+
+enum tbl_flag {
+ HAS_MII=1, HAS_MEDIA_TABLE=2, CSR12_IN_SROM=4, ALWAYS_CHECK_MII=8,
+ HAS_PWRDWN=0x10, MC_HASH_ONLY=0x20, /* Hash-only multicast filter. */
+ HAS_PNICNWAY=0x80, HAS_NWAY=0x40, /* Uses internal NWay xcvr. */
+ HAS_INTR_MITIGATION=0x100, IS_ASIX=0x200, HAS_8023X=0x400,
+};
+
+/* Note: this table must match enum tulip_chips above. */
+static struct tulip_chip_table {
+ char *chip_name;
+ int flags;
+} tulip_tbl[] = {
+ { "Digital DC21040 Tulip", 0},
+ { "Digital DC21041 Tulip", HAS_MEDIA_TABLE | HAS_NWAY },
+ { "Digital DS21140 Tulip", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM },
+ { "Digital DS21143 Tulip", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII
+ | HAS_PWRDWN | HAS_NWAY | HAS_INTR_MITIGATION },
+ { "Lite-On 82c168 PNIC", HAS_MII | HAS_PNICNWAY },
+ { "Macronix 98713 PMAC", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM },
+ { "Macronix 98715 PMAC", HAS_MEDIA_TABLE },
+ { "Macronix 98725 PMAC", HAS_MEDIA_TABLE },
+ { "ASIX AX88140", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM
+ | MC_HASH_ONLY | IS_ASIX },
+ { "ASIX AX88141", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY
+ | IS_ASIX },
+ { "Lite-On PNIC-II", HAS_MII | HAS_NWAY | HAS_8023X },
+ { "ADMtek Comet", HAS_MII | MC_HASH_ONLY },
+ { "Compex 9881 PMAC", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM },
+ { "Intel DS21145 Tulip", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII
+ | HAS_PWRDWN | HAS_NWAY },
+ { "Xircom tulip work-alike", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII
+ | HAS_PWRDWN | HAS_NWAY },
+ { "SGThomson STE10/100A", HAS_MII | MC_HASH_ONLY }, /*Ramesh Chander*/
+ { 0, 0 },
+};
+
+/* A full-duplex map for media types. */
+enum MediaIs {
+ MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,
+ MediaIs100=16};
+
+static const char media_cap[32] =
+{0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20, 20,31,0,0, };
+static u8 t21040_csr13[] = {2,0x0C,8,4, 4,0,0,0, 0,0,0,0, 4,0,0,0};
+
+/* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD */
+static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
+static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
+static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
+
+/* not used
+static u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, };
+*/
+static u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, };
+/* not used
+static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
+*/
+
+/* Offsets to the Command and Status Registers, "CSRs". All accesses
+ must be longword instructions and quadword aligned. */
+enum tulip_offsets {
+ CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
+ CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
+ CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x80, CSR20=0xA0
+};
+
+/* The bits in the CSR5 status registers, mostly interrupt sources. */
+enum status_bits {
+ TimerInt=0x800, TPLnkFail=0x1000, TPLnkPass=0x10,
+ NormalIntr=0x10000, AbnormalIntr=0x8000,
+ RxJabber=0x200, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40,
+ TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
+};
+
+/* The configuration bits in CSR6. */
+enum csr6_mode_bits {
+ TxOn=0x2000, RxOn=0x0002, FullDuplex=0x0200,
+ AcceptBroadcast=0x0100, AcceptAllMulticast=0x0080,
+ AcceptAllPhys=0x0040, AcceptRunt=0x0008,
+};
+
+
+enum desc_status_bits {
+ DescOwnded=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300,
+};
+
+struct medialeaf {
+ u8 type;
+ u8 media;
+ unsigned char *leafdata;
+};
+
+struct mediatable {
+ u16 defaultmedia;
+ u8 leafcount, csr12dir; /* General purpose pin directions. */
+ unsigned has_mii:1, has_nonmii:1, has_reset:6;
+ u32 csr15dir, csr15val; /* 21143 NWay setting. */
+ struct medialeaf mleaf[0];
+};
+
+struct mediainfo {
+ struct mediainfo *next;
+ int info_type;
+ int index;
+ unsigned char *info;
+};
+
+/* EEPROM Address width definitions */
+#define EEPROM_ADDRLEN 6
+#define EEPROM_SIZE 128 /* 2 << EEPROM_ADDRLEN */
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD (5 << addr_len)
+#define EE_READ_CMD (6 << addr_len)
+#define EE_ERASE_CMD (7 << addr_len)
+
+/* EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */
+#define EE_CS 0x01 /* EEPROM chip select. */
+#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
+#define EE_WRITE_0 0x01
+#define EE_WRITE_1 0x05
+#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
+#define EE_ENB (0x4800 | EE_CS)
+
+/* Delay between EEPROM clock transitions. Even at 33Mhz current PCI
+ implementations don't overrun the EEPROM clock. We add a bus
+ turn-around to insure that this remains true. */
+#define eeprom_delay() inl(ee_addr)
+
+/* Size of transmit and receive buffers */
+#define BUFLEN 1536
+
+/* Ring-wrap flag in length field, use for last ring entry.
+ 0x01000000 means chain on buffer2 address,
+ 0x02000000 means use the ring start address in CSR2/3.
+ Note: Some work-alike chips do not function correctly in chained mode.
+ The ASIX chip works only in chained mode.
+ Thus we indicate ring mode, but always write the 'next' field for
+ chained mode as well. */
+#define DESC_RING_WRAP 0x02000000
+
+/* transmit and receive descriptor format */
+struct tulip_rx_desc {
+ volatile u32 status;
+ u32 length;
+ u32 buffer1, buffer2;
+};
+
+struct tulip_tx_desc {
+ volatile u32 status;
+ u32 length;
+ u32 buffer1, buffer2;
+};
+
+/*********************************************************************/
+/* Global Storage */
+/*********************************************************************/
+
+static u32 ioaddr;
+
+struct tulip_private {
+ int cur_rx;
+ int chip_id; /* index into tulip_tbl[] */
+ int pci_id_idx; /* index into pci_id_tbl[] */
+ int revision;
+ int flags;
+ unsigned short vendor_id; /* PCI card vendor code */
+ unsigned short dev_id; /* PCI card device code */
+ unsigned char ehdr[ETH_HLEN]; /* buffer for ethernet header */
+ const char *nic_name;
+ unsigned int csr0, csr6; /* Current CSR0, CSR6 settings. */
+ unsigned int if_port;
+ unsigned int full_duplex; /* Full-duplex operation requested. */
+ unsigned int full_duplex_lock;
+ unsigned int medialock; /* Do not sense media type. */
+ unsigned int mediasense; /* Media sensing in progress. */
+ unsigned int nway, nwayset; /* 21143 internal NWay. */
+ unsigned int default_port;
+ unsigned char eeprom[EEPROM_SIZE]; /* Serial EEPROM contents. */
+ u8 media_table_storage[(sizeof(struct mediatable) + 32*sizeof(struct medialeaf))];
+ u16 sym_advertise, mii_advertise; /* NWay to-advertise. */
+ struct mediatable *mtable;
+ u16 lpar; /* 21143 Link partner ability. */
+ u16 advertising[4]; /* MII advertise, from SROM table. */
+ signed char phys[4], mii_cnt; /* MII device addresses. */
+ int cur_index; /* Current media index. */
+ int saved_if_port;
+};
+
+/* Note: transmit and receive buffers must be longword aligned and
+ longword divisable */
+
+#define TX_RING_SIZE 2
+#define RX_RING_SIZE 4
+struct {
+ struct tulip_tx_desc tx_ring[TX_RING_SIZE];
+ unsigned char txb[BUFLEN];
+ struct tulip_rx_desc rx_ring[RX_RING_SIZE];
+ unsigned char rxb[RX_RING_SIZE * BUFLEN];
+ struct tulip_private tpx;
+} tulip_bss __shared __attribute__ ((aligned(4)));
+#define tx_ring tulip_bss.tx_ring
+#define txb tulip_bss.txb
+#define rx_ring tulip_bss.rx_ring
+#define rxb tulip_bss.rxb
+
+static struct tulip_private *tp;
+
+/* Known cards that have old-style EEPROMs.
+ Writing this table is described at
+ http://cesdis.gsfc.nasa.gov/linux/drivers/tulip-drivers/tulip-media.html */
+static struct fixups {
+ char *name;
+ unsigned char addr0, addr1, addr2;
+ u16 newtable[32]; /* Max length below. */
+} eeprom_fixups[] = {
+ {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
+ 0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
+ {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
+ 0x0000, 0x009E, /* 10baseT */
+ 0x0004, 0x009E, /* 10baseT-FD */
+ 0x0903, 0x006D, /* 100baseTx */
+ 0x0905, 0x006D, /* 100baseTx-FD */ }},
+ {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f,
+ 0x0107, 0x8021, /* 100baseFx */
+ 0x0108, 0x8021, /* 100baseFx-FD */
+ 0x0100, 0x009E, /* 10baseT */
+ 0x0104, 0x009E, /* 10baseT-FD */
+ 0x0103, 0x006D, /* 100baseTx */
+ 0x0105, 0x006D, /* 100baseTx-FD */ }},
+ {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513,
+ 0x1001, 0x009E, /* 10base2, CSR12 0x10*/
+ 0x0000, 0x009E, /* 10baseT */
+ 0x0004, 0x009E, /* 10baseT-FD */
+ 0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */
+ 0x0305, 0x006D, /* 100baseTx-FD CSR12 0x03 */}},
+ {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F,
+ 0x1B01, 0x0000, /* 10base2, CSR12 0x1B */
+ 0x0B00, 0x009E, /* 10baseT, CSR12 0x0B */
+ 0x0B04, 0x009E, /* 10baseT-FD,CSR12 0x0B */
+ 0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */
+ 0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */
+ }},
+ {0, 0, 0, 0, {}}};
+
+static const char * block_name[] = {"21140 non-MII", "21140 MII PHY",
+ "21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"};
+
+
+/*********************************************************************/
+/* Function Prototypes */
+/*********************************************************************/
+static int mdio_read(struct nic *nic, int phy_id, int location);
+static void mdio_write(struct nic *nic, int phy_id, int location, int value);
+static int read_eeprom(unsigned long ioaddr, int location, int addr_len);
+static void parse_eeprom(struct nic *nic);
+static int tulip_probe(struct nic *nic,struct pci_device *pci);
+static void tulip_init_ring(struct nic *nic);
+static void tulip_reset(struct nic *nic);
+static void tulip_transmit(struct nic *nic, const char *d, unsigned int t,
+ unsigned int s, const char *p);
+static int tulip_poll(struct nic *nic, int retrieve);
+static void tulip_disable(struct nic *nic);
+static void nway_start(struct nic *nic);
+static void pnic_do_nway(struct nic *nic);
+static void select_media(struct nic *nic, int startup);
+static void init_media(struct nic *nic);
+static void start_link(struct nic *nic);
+static int tulip_check_duplex(struct nic *nic);
+
+static void tulip_wait(unsigned int nticks);
+
+
+/*********************************************************************/
+/* Utility Routines */
+/*********************************************************************/
+
+static void whereami (const char *str)
+{
+ DBGP("%s\n", str);
+ /* sleep(2); */
+}
+
+static void tulip_wait(unsigned int nticks)
+{
+ unsigned int to = currticks() + nticks;
+ while (currticks() < to)
+ /* wait */ ;
+}
+
+
+/*********************************************************************/
+/* Media Descriptor Code */
+/*********************************************************************/
+
+/* MII transceiver control section.
+ Read and write the MII registers using software-generated serial
+ MDIO protocol. See the MII specifications or DP83840A data sheet
+ for details. */
+
+/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
+ met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+ "overclocking" issues or future 66Mhz PCI. */
+#define mdio_delay() inl(mdio_addr)
+
+/* Read and write the MII registers using software-generated serial
+ MDIO protocol. It is just different enough from the EEPROM protocol
+ to not share code. The maxium data clock rate is 2.5 Mhz. */
+#define MDIO_SHIFT_CLK 0x10000
+#define MDIO_DATA_WRITE0 0x00000
+#define MDIO_DATA_WRITE1 0x20000
+#define MDIO_ENB 0x00000 /* Ignore the 0x02000 databook setting. */
+#define MDIO_ENB_IN 0x40000
+#define MDIO_DATA_READ 0x80000
+
+/* MII transceiver control section.
+ Read and write the MII registers using software-generated serial
+ MDIO protocol. See the MII specifications or DP83840A data sheet
+ for details. */
+
+int mdio_read(struct nic *nic __unused, int phy_id, int location)
+{
+ int i;
+ int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+ int retval = 0;
+ long mdio_addr = ioaddr + CSR9;
+
+ whereami("mdio_read\n");
+
+ if (tp->chip_id == LC82C168) {
+ int i = 1000;
+ outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
+ inl(ioaddr + 0xA0);
+ inl(ioaddr + 0xA0);
+ while (--i > 0)
+ if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
+ return retval & 0xffff;
+ return 0xffff;
+ }
+
+ if (tp->chip_id == COMET) {
+ if (phy_id == 1) {
+ if (location < 7)
+ return inl(ioaddr + 0xB4 + (location<<2));
+ else if (location == 17)
+ return inl(ioaddr + 0xD0);
+ else if (location >= 29 && location <= 31)
+ return inl(ioaddr + 0xD4 + ((location-29)<<2));
+ }
+ return 0xffff;
+ }
+
+ /* Establish sync by sending at least 32 logic ones. */
+ for (i = 32; i >= 0; i--) {
+ outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
+ mdio_delay();
+ outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Shift the read command bits out. */
+ for (i = 15; i >= 0; i--) {
+ int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+
+ outl(MDIO_ENB | dataval, mdio_addr);
+ mdio_delay();
+ outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Read the two transition, 16 data, and wire-idle bits. */
+ for (i = 19; i > 0; i--) {
+ outl(MDIO_ENB_IN, mdio_addr);
+ mdio_delay();
+ retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+ outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ return (retval>>1) & 0xffff;
+}
+
+void mdio_write(struct nic *nic __unused, int phy_id, int location, int value)
+{
+ int i;
+ int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
+ long mdio_addr = ioaddr + CSR9;
+
+ whereami("mdio_write\n");
+
+ if (tp->chip_id == LC82C168) {
+ int i = 1000;
+ outl(cmd, ioaddr + 0xA0);
+ do
+ if ( ! (inl(ioaddr + 0xA0) & 0x80000000))
+ break;
+ while (--i > 0);
+ return;
+ }
+
+ if (tp->chip_id == COMET) {
+ if (phy_id != 1)
+ return;
+ if (location < 7)
+ outl(value, ioaddr + 0xB4 + (location<<2));
+ else if (location == 17)
+ outl(value, ioaddr + 0xD0);
+ else if (location >= 29 && location <= 31)
+ outl(value, ioaddr + 0xD4 + ((location-29)<<2));
+ return;
+ }
+
+ /* Establish sync by sending 32 logic ones. */
+ for (i = 32; i >= 0; i--) {
+ outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
+ mdio_delay();
+ outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Shift the command bits out. */
+ for (i = 31; i >= 0; i--) {
+ int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+ outl(MDIO_ENB | dataval, mdio_addr);
+ mdio_delay();
+ outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Clear out extra bits. */
+ for (i = 2; i > 0; i--) {
+ outl(MDIO_ENB_IN, mdio_addr);
+ mdio_delay();
+ outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+}
+
+
+/*********************************************************************/
+/* EEPROM Reading Code */
+/*********************************************************************/
+/* EEPROM routines adapted from the Linux Tulip Code */
+/* Reading a serial EEPROM is a "bit" grungy, but we work our way
+ through:->.
+*/
+static int read_eeprom(unsigned long ioaddr, int location, int addr_len)
+{
+ int i;
+ unsigned short retval = 0;
+ long ee_addr = ioaddr + CSR9;
+ int read_cmd = location | EE_READ_CMD;
+
+ whereami("read_eeprom\n");
+
+ outl(EE_ENB & ~EE_CS, ee_addr);
+ outl(EE_ENB, ee_addr);
+
+ /* Shift the read command bits out. */
+ for (i = 4 + addr_len; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ outl(EE_ENB | dataval, ee_addr);
+ eeprom_delay();
+ outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay();
+ }
+ outl(EE_ENB, ee_addr);
+
+ for (i = 16; i > 0; i--) {
+ outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay();
+ retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
+ outl(EE_ENB, ee_addr);
+ eeprom_delay();
+ }
+
+ /* Terminate the EEPROM access. */
+ outl(EE_ENB & ~EE_CS, ee_addr);
+ return retval;
+}
+
+
+/*********************************************************************/
+/* EEPROM Parsing Code */
+/*********************************************************************/
+static void parse_eeprom(struct nic *nic)
+{
+ unsigned char *p, *ee_data = tp->eeprom;
+ int new_advertise = 0;
+ int i;
+
+ whereami("parse_eeprom\n");
+
+ tp->mtable = 0;
+ /* Detect an old-style (SA only) EEPROM layout:
+ memcmp(ee_data, ee_data+16, 8). */
+ for (i = 0; i < 8; i ++)
+ if (ee_data[i] != ee_data[16+i])
+ break;
+ if (i >= 8) {
+ /* Do a fix-up based on the vendor half of the station address. */
+ for (i = 0; eeprom_fixups[i].name; i++) {
+ if (nic->node_addr[0] == eeprom_fixups[i].addr0
+ && nic->node_addr[1] == eeprom_fixups[i].addr1
+ && nic->node_addr[2] == eeprom_fixups[i].addr2) {
+ if (nic->node_addr[2] == 0xE8 && ee_data[0x1a] == 0x55)
+ i++; /* An Accton EN1207, not an outlaw Maxtech. */
+ memcpy(ee_data + 26, eeprom_fixups[i].newtable,
+ sizeof(eeprom_fixups[i].newtable));
+ DBG("%s: Old format EEPROM on '%s' board.\n%s: Using substitute media control info.\n",
+ tp->nic_name, eeprom_fixups[i].name, tp->nic_name);
+ break;
+ }
+ }
+ if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
+ DBG("%s: Old style EEPROM with no media selection information.\n",
+ tp->nic_name);
+ return;
+ }
+ }
+
+ if (ee_data[19] > 1) {
+ DBG("%s: Multiport cards (%d ports) may not work correctly.\n",
+ tp->nic_name, ee_data[19]);
+ }
+
+ p = (void *)ee_data + ee_data[27];
+
+ if (ee_data[27] == 0) { /* No valid media table. */
+ DBG2("%s: No Valid Media Table. ee_data[27] = %hhX\n",
+ tp->nic_name, ee_data[27]);
+ } else if (tp->chip_id == DC21041) {
+ int media = get_u16(p);
+ int count = p[2];
+ p += 3;
+
+ DBG("%s: 21041 Media table, default media %hX (%s).\n",
+ tp->nic_name, media,
+ media & 0x0800 ? "Autosense" : medianame[media & 15]);
+ for (i = 0; i < count; i++) {
+ unsigned char media_block = *p++;
+ int media_code = media_block & MEDIA_MASK;
+ if (media_block & 0x40)
+ p += 6;
+ switch(media_code) {
+ case 0: new_advertise |= 0x0020; break;
+ case 4: new_advertise |= 0x0040; break;
+ }
+ DBG("%s: 21041 media #%d, %s.\n",
+ tp->nic_name, media_code, medianame[media_code]);
+ }
+ } else {
+ unsigned char csr12dir = 0;
+ int count;
+ struct mediatable *mtable;
+ u16 media = get_u16(p);
+
+ p += 2;
+ if (tp->flags & CSR12_IN_SROM)
+ csr12dir = *p++;
+ count = *p++;
+
+ tp->mtable = mtable = (struct mediatable *)&tp->media_table_storage[0];
+
+ mtable->defaultmedia = media;
+ mtable->leafcount = count;
+ mtable->csr12dir = csr12dir;
+ mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
+ mtable->csr15dir = mtable->csr15val = 0;
+
+ DBG("%s: EEPROM default media type %s.\n", tp->nic_name,
+ media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]);
+
+ for (i = 0; i < count; i++) {
+ struct medialeaf *leaf = &mtable->mleaf[i];
+
+ if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
+ leaf->type = 0;
+ leaf->media = p[0] & 0x3f;
+ leaf->leafdata = p;
+ if ((p[2] & 0x61) == 0x01) /* Bogus, but Znyx boards do it. */
+ mtable->has_mii = 1;
+ p += 4;
+ } else {
+ switch(leaf->type = p[1]) {
+ case 5:
+ mtable->has_reset = i;
+ leaf->media = p[2] & 0x0f;
+ break;
+ case 1: case 3:
+ mtable->has_mii = 1;
+ leaf->media = 11;
+ break;
+ case 2:
+ if ((p[2] & 0x3f) == 0) {
+ u32 base15 = (p[2] & 0x40) ? get_u16(p + 7) : 0x0008;
+ u16 *p1 = (u16 *)(p + (p[2] & 0x40 ? 9 : 3));
+ mtable->csr15dir = (get_unaligned(p1 + 0)<<16) + base15;
+ mtable->csr15val = (get_unaligned(p1 + 1)<<16) + base15;
+ }
+ /* Fall through. */
+ case 0: case 4:
+ mtable->has_nonmii = 1;
+ leaf->media = p[2] & MEDIA_MASK;
+ switch (leaf->media) {
+ case 0: new_advertise |= 0x0020; break;
+ case 4: new_advertise |= 0x0040; break;
+ case 3: new_advertise |= 0x0080; break;
+ case 5: new_advertise |= 0x0100; break;
+ case 6: new_advertise |= 0x0200; break;
+ }
+ break;
+ default:
+ leaf->media = 19;
+ }
+ leaf->leafdata = p + 2;
+ p += (p[0] & 0x3f) + 1;
+ }
+ if (leaf->media == 11) {
+ unsigned char *bp = leaf->leafdata;
+ DBG2("%s: MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %hhX %hhX.\n",
+ tp->nic_name, bp[0], bp[1], bp[2 + bp[1]*2],
+ bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);
+ }
+ DBG("%s: Index #%d - Media %s (#%d) described "
+ "by a %s (%d) block.\n",
+ tp->nic_name, i, medianame[leaf->media], leaf->media,
+ leaf->type < 6 ? block_name[leaf->type] : "UNKNOWN",
+ leaf->type);
+ }
+ if (new_advertise)
+ tp->sym_advertise = new_advertise;
+ }
+}
+
+
+/*********************************************************************/
+/* tulip_init_ring - setup the tx and rx descriptors */
+/*********************************************************************/
+static void tulip_init_ring(struct nic *nic __unused)
+{
+ int i;
+
+ whereami("tulip_init_ring\n");
+
+ tp->cur_rx = 0;
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_ring[i].status = cpu_to_le32(0x80000000);
+ rx_ring[i].length = cpu_to_le32(BUFLEN);
+ rx_ring[i].buffer1 = virt_to_le32desc(&rxb[i * BUFLEN]);
+ rx_ring[i].buffer2 = virt_to_le32desc(&rx_ring[i+1]);
+ }
+ /* Mark the last entry as wrapping the ring. */
+ rx_ring[i-1].length = cpu_to_le32(DESC_RING_WRAP | BUFLEN);
+ rx_ring[i-1].buffer2 = virt_to_le32desc(&rx_ring[0]);
+
+ /* We only use 1 transmit buffer, but we use 2 descriptors so
+ transmit engines have somewhere to point to if they feel the need */
+
+ tx_ring[0].status = 0x00000000;
+ tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]);
+ tx_ring[0].buffer2 = virt_to_le32desc(&tx_ring[1]);
+
+ /* this descriptor should never get used, since it will never be owned
+ by the machine (status will always == 0) */
+ tx_ring[1].status = 0x00000000;
+ tx_ring[1].buffer1 = virt_to_le32desc(&txb[0]);
+ tx_ring[1].buffer2 = virt_to_le32desc(&tx_ring[0]);
+
+ /* Mark the last entry as wrapping the ring, though this should never happen */
+ tx_ring[1].length = cpu_to_le32(DESC_RING_WRAP | BUFLEN);
+}
+
+
+static void set_rx_mode(struct nic *nic __unused) {
+ int csr6 = inl(ioaddr + CSR6) & ~0x00D5;
+
+ tp->csr6 &= ~0x00D5;
+
+ /* !IFF_PROMISC */
+ tp->csr6 |= AcceptAllMulticast;
+ csr6 |= AcceptAllMulticast;
+
+ outl(csr6, ioaddr + CSR6);
+
+
+
+}
+
+/*********************************************************************/
+/* eth_reset - Reset adapter */
+/*********************************************************************/
+static void tulip_reset(struct nic *nic)
+{
+ int i;
+ unsigned long to;
+
+ whereami("tulip_reset\n");
+
+ /* Stop Tx and RX */
+ outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
+
+ /* On some chip revs we must set the MII/SYM port before the reset!? */
+ if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii)) {
+ outl(0x814C0000, ioaddr + CSR6);
+ }
+
+ /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
+ outl(0x00000001, ioaddr + CSR0);
+ tulip_wait(1);
+
+ /* turn off reset and set cache align=16lword, burst=unlimit */
+ outl(tp->csr0, ioaddr + CSR0);
+
+ /* Wait the specified 50 PCI cycles after a reset */
+ tulip_wait(1);
+
+ /* set up transmit and receive descriptors */
+ tulip_init_ring(nic);
+
+ if (tp->chip_id == PNIC2) {
+ u32 addr_high = (nic->node_addr[1]<<8) + (nic->node_addr[0]<<0);
+ /* This address setting does not appear to impact chip operation?? */
+ outl((nic->node_addr[5]<<8) + nic->node_addr[4] +
+ (nic->node_addr[3]<<24) + (nic->node_addr[2]<<16),
+ ioaddr + 0xB0);
+ outl(addr_high + (addr_high<<16), ioaddr + 0xB8);
+ }
+
+ /* MC_HASH_ONLY boards don't support setup packets */
+ if (tp->flags & MC_HASH_ONLY) {
+ u32 addr_low = cpu_to_le32(get_unaligned((u32 *)nic->node_addr));
+ u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(nic->node_addr+4)));
+
+ /* clear multicast hash filters and setup MAC address filters */
+ if (tp->flags & IS_ASIX) {
+ outl(0, ioaddr + CSR13);
+ outl(addr_low, ioaddr + CSR14);
+ outl(1, ioaddr + CSR13);
+ outl(addr_high, ioaddr + CSR14);
+ outl(2, ioaddr + CSR13);
+ outl(0, ioaddr + CSR14);
+ outl(3, ioaddr + CSR13);
+ outl(0, ioaddr + CSR14);
+ } else if (tp->chip_id == COMET) {
+ outl(addr_low, ioaddr + 0xA4);
+ outl(addr_high, ioaddr + 0xA8);
+ outl(0, ioaddr + 0xAC);
+ outl(0, ioaddr + 0xB0);
+ }
+ } else {
+ /* for other boards we send a setup packet to initialize
+ the filters */
+ u32 tx_flags = 0x08000000 | 192;
+
+ /* construct perfect filter frame with mac address as first match
+ and broadcast address for all others */
+ for (i=0; i<192; i++)
+ txb[i] = 0xFF;
+ txb[0] = nic->node_addr[0];
+ txb[1] = nic->node_addr[1];
+ txb[4] = nic->node_addr[2];
+ txb[5] = nic->node_addr[3];
+ txb[8] = nic->node_addr[4];
+ txb[9] = nic->node_addr[5];
+
+ tx_ring[0].length = cpu_to_le32(tx_flags);
+ tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]);
+ tx_ring[0].status = cpu_to_le32(0x80000000);
+ }
+
+ /* Point to rx and tx descriptors */
+ outl(virt_to_le32desc(&rx_ring[0]), ioaddr + CSR3);
+ outl(virt_to_le32desc(&tx_ring[0]), ioaddr + CSR4);
+
+ init_media(nic);
+
+ /* set the chip's operating mode (but don't turn on xmit and recv yet) */
+ outl((tp->csr6 & ~0x00002002), ioaddr + CSR6);
+
+ /* send setup packet for cards that support it */
+ if (!(tp->flags & MC_HASH_ONLY)) {
+ /* enable transmit wait for completion */
+ outl(tp->csr6 | 0x00002000, ioaddr + CSR6);
+ /* immediate transmit demand */
+ outl(0, ioaddr + CSR1);
+
+ to = currticks() + TX_TIME_OUT;
+ while ((tx_ring[0].status & 0x80000000) && (currticks() < to))
+ /* wait */ ;
+
+ if (currticks() >= to) {
+ DBG ("%s: TX Setup Timeout.\n", tp->nic_name);
+ }
+ }
+
+ if (tp->chip_id == LC82C168)
+ tulip_check_duplex(nic);
+
+ set_rx_mode(nic);
+
+ /* enable transmit and receive */
+ outl(tp->csr6 | 0x00002002, ioaddr + CSR6);
+}
+
+
+/*********************************************************************/
+/* eth_transmit - Transmit a frame */
+/*********************************************************************/
+static void tulip_transmit(struct nic *nic, const char *d, unsigned int t,
+ unsigned int s, const char *p)
+{
+ u16 nstype;
+ u32 to;
+ u32 csr6 = inl(ioaddr + CSR6);
+
+ whereami("tulip_transmit\n");
+
+ /* Disable Tx */
+ outl(csr6 & ~0x00002000, ioaddr + CSR6);
+
+ memcpy(txb, d, ETH_ALEN);
+ memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ nstype = htons((u16) t);
+ memcpy(txb + 2 * ETH_ALEN, (u8 *)&nstype, 2);
+ memcpy(txb + ETH_HLEN, p, s);
+
+ s += ETH_HLEN;
+ s &= 0x0FFF;
+
+ /* pad to minimum packet size */
+ while (s < ETH_ZLEN)
+ txb[s++] = '\0';
+
+ DBG2("%s: sending %d bytes ethtype %hX\n", tp->nic_name, s, t);
+
+ /* setup the transmit descriptor */
+ /* 0x60000000 = no interrupt on completion */
+ tx_ring[0].length = cpu_to_le32(0x60000000 | s);
+ tx_ring[0].status = cpu_to_le32(0x80000000);
+
+ /* Point to transmit descriptor */
+ outl(virt_to_le32desc(&tx_ring[0]), ioaddr + CSR4);
+
+ /* Enable Tx */
+ outl(csr6 | 0x00002000, ioaddr + CSR6);
+ /* immediate transmit demand */
+ outl(0, ioaddr + CSR1);
+
+ to = currticks() + TX_TIME_OUT;
+ while ((tx_ring[0].status & 0x80000000) && (currticks() < to))
+ /* wait */ ;
+
+ if (currticks() >= to) {
+ DBG ("TX Timeout!\n");
+ }
+
+ /* Disable Tx */
+ outl(csr6 & ~0x00002000, ioaddr + CSR6);
+}
+
+/*********************************************************************/
+/* eth_poll - Wait for a frame */
+/*********************************************************************/
+static int tulip_poll(struct nic *nic, int retrieve)
+{
+
+ whereami("tulip_poll\n");
+
+ /* no packet waiting. packet still owned by NIC */
+ if (rx_ring[tp->cur_rx].status & 0x80000000)
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+ whereami("tulip_poll got one\n");
+
+ nic->packetlen = (rx_ring[tp->cur_rx].status & 0x3FFF0000) >> 16;
+
+ /* if we get a corrupted packet. throw it away and move on */
+ if (rx_ring[tp->cur_rx].status & 0x00008000) {
+ /* return the descriptor and buffer to receive ring */
+ rx_ring[tp->cur_rx].status = 0x80000000;
+ tp->cur_rx = (tp->cur_rx + 1) % RX_RING_SIZE;
+ return 0;
+ }
+
+ /* copy packet to working buffer */
+ memcpy(nic->packet, rxb + tp->cur_rx * BUFLEN, nic->packetlen);
+
+ /* return the descriptor and buffer to receive ring */
+ rx_ring[tp->cur_rx].status = 0x80000000;
+ tp->cur_rx = (tp->cur_rx + 1) % RX_RING_SIZE;
+
+ return 1;
+}
+
+/*********************************************************************/
+/* eth_disable - Disable the interface */
+/*********************************************************************/
+static void tulip_disable ( struct nic *nic ) {
+
+ whereami("tulip_disable\n");
+
+ tulip_reset(nic);
+
+ /* disable interrupts */
+ outl(0x00000000, ioaddr + CSR7);
+
+ /* Stop the chip's Tx and Rx processes. */
+ outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
+
+ /* Clear the missed-packet counter. */
+ inl(ioaddr + CSR8);
+}
+
+/*********************************************************************/
+/*IRQ - Enable, Disable, or Force interrupts */
+/*********************************************************************/
+static void tulip_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations tulip_operations = {
+ .connect = dummy_connect,
+ .poll = tulip_poll,
+ .transmit = tulip_transmit,
+ .irq = tulip_irq,
+
+};
+
+/*********************************************************************/
+/* eth_probe - Look for an adapter */
+/*********************************************************************/
+static int tulip_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ u32 i;
+ u8 chip_rev;
+ u8 ee_data[EEPROM_SIZE];
+ unsigned short sum;
+ int chip_idx;
+ static unsigned char last_phys_addr[ETH_ALEN] = {0x00, 'L', 'i', 'n', 'u', 'x'};
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ ioaddr = pci->ioaddr;
+ nic->ioaddr = pci->ioaddr & ~3;
+ nic->irqno = 0;
+
+ /* point to private storage */
+ tp = &tulip_bss.tpx;
+
+ tp->vendor_id = pci->vendor;
+ tp->dev_id = pci->device;
+ tp->nic_name = pci->id->name;
+
+ tp->if_port = 0;
+ tp->default_port = 0;
+
+ adjust_pci_device(pci);
+
+ /* disable interrupts */
+ outl(0x00000000, ioaddr + CSR7);
+
+ /* Stop the chip's Tx and Rx processes. */
+ outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
+
+ /* Clear the missed-packet counter. */
+ inl(ioaddr + CSR8);
+
+ DBG("\n"); /* so we start on a fresh line */
+ whereami("tulip_probe\n");
+
+ DBG2 ("%s: Looking for Tulip Chip: Vendor=%hX Device=%hX\n", tp->nic_name,
+ tp->vendor_id, tp->dev_id);
+
+ /* Figure out which chip we're dealing with */
+ i = 0;
+ chip_idx = -1;
+
+ while (pci_id_tbl[i].name) {
+ if ( (((u32) tp->dev_id << 16) | tp->vendor_id) ==
+ (pci_id_tbl[i].id.pci & pci_id_tbl[i].id.pci_mask) ) {
+ chip_idx = pci_id_tbl[i].drv_flags;
+ break;
+ }
+ i++;
+ }
+
+ if (chip_idx == -1) {
+ DBG ("%s: Unknown Tulip Chip: Vendor=%hX Device=%hX\n", tp->nic_name,
+ tp->vendor_id, tp->dev_id);
+ return 0;
+ }
+
+ tp->pci_id_idx = i;
+ tp->flags = tulip_tbl[chip_idx].flags;
+
+ DBG2 ("%s: tp->pci_id_idx == %d, name == %s\n", tp->nic_name,
+ tp->pci_id_idx, pci_id_tbl[tp->pci_id_idx].name);
+ DBG2 ("%s: chip_idx == %d, name == %s\n", tp->nic_name, chip_idx,
+ tulip_tbl[chip_idx].chip_name);
+
+ /* Bring the 21041/21143 out of sleep mode.
+ Caution: Snooze mode does not work with some boards! */
+ if (tp->flags & HAS_PWRDWN)
+ pci_write_config_dword(pci, 0x40, 0x00000000);
+
+ if (inl(ioaddr + CSR5) == 0xFFFFFFFF) {
+ DBG("%s: The Tulip chip at %X is not functioning.\n",
+ tp->nic_name, (unsigned int) ioaddr);
+ return 0;
+ }
+
+ pci_read_config_byte(pci, PCI_REVISION, &chip_rev);
+
+ DBG("%s: [chip: %s] rev %d at %hX\n", tp->nic_name,
+ tulip_tbl[chip_idx].chip_name, chip_rev, (unsigned int) ioaddr);
+ DBG("%s: Vendor=%hX Device=%hX", tp->nic_name, tp->vendor_id, tp->dev_id);
+
+ if (chip_idx == DC21041 && inl(ioaddr + CSR9) & 0x8000) {
+ DBG(" 21040 compatible mode.");
+ chip_idx = DC21040;
+ }
+
+ DBG("\n");
+
+ /* The SROM/EEPROM interface varies dramatically. */
+ sum = 0;
+ if (chip_idx == DC21040) {
+ outl(0, ioaddr + CSR9); /* Reset the pointer with a dummy write. */
+ for (i = 0; i < ETH_ALEN; i++) {
+ int value, boguscnt = 100000;
+ do
+ value = inl(ioaddr + CSR9);
+ while (value < 0 && --boguscnt > 0);
+ nic->node_addr[i] = value;
+ sum += value & 0xff;
+ }
+ } else if (chip_idx == LC82C168) {
+ for (i = 0; i < 3; i++) {
+ int value, boguscnt = 100000;
+ outl(0x600 | i, ioaddr + 0x98);
+ do
+ value = inl(ioaddr + CSR9);
+ while (value < 0 && --boguscnt > 0);
+ put_unaligned(le16_to_cpu(value), ((u16*)nic->node_addr) + i);
+ sum += value & 0xffff;
+ }
+ } else if (chip_idx == COMET) {
+ /* No need to read the EEPROM. */
+ put_unaligned(inl(ioaddr + 0xA4), (u32 *)nic->node_addr);
+ put_unaligned(inl(ioaddr + 0xA8), (u16 *)(nic->node_addr + 4));
+ for (i = 0; i < ETH_ALEN; i ++)
+ sum += nic->node_addr[i];
+ } else {
+ /* A serial EEPROM interface, we read now and sort it out later. */
+ int sa_offset = 0;
+ int ee_addr_size = read_eeprom(ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
+
+ for (i = 0; i < sizeof(ee_data)/2; i++)
+ ((u16 *)ee_data)[i] =
+ le16_to_cpu(read_eeprom(ioaddr, i, ee_addr_size));
+
+ /* DEC now has a specification (see Notes) but early board makers
+ just put the address in the first EEPROM locations. */
+ /* This does memcmp(eedata, eedata+16, 8) */
+ for (i = 0; i < 8; i ++)
+ if (ee_data[i] != ee_data[16+i])
+ sa_offset = 20;
+ if (ee_data[0] == 0xff && ee_data[1] == 0xff && ee_data[2] == 0) {
+ sa_offset = 2; /* Grrr, damn Matrox boards. */
+ }
+ for (i = 0; i < ETH_ALEN; i ++) {
+ nic->node_addr[i] = ee_data[i + sa_offset];
+ sum += ee_data[i + sa_offset];
+ }
+ }
+ /* Lite-On boards have the address byte-swapped. */
+ if ((nic->node_addr[0] == 0xA0 || nic->node_addr[0] == 0xC0)
+ && nic->node_addr[1] == 0x00)
+ for (i = 0; i < ETH_ALEN; i+=2) {
+ char tmp = nic->node_addr[i];
+ nic->node_addr[i] = nic->node_addr[i+1];
+ nic->node_addr[i+1] = tmp;
+ }
+
+ if (sum == 0 || sum == ETH_ALEN*0xff) {
+ DBG("%s: EEPROM not present!\n", tp->nic_name);
+ for (i = 0; i < ETH_ALEN-1; i++)
+ nic->node_addr[i] = last_phys_addr[i];
+ nic->node_addr[i] = last_phys_addr[i] + 1;
+ }
+
+ for (i = 0; i < ETH_ALEN; i++)
+ last_phys_addr[i] = nic->node_addr[i];
+
+ DBG ( "%s: %s at ioaddr %hX\n", tp->nic_name, eth_ntoa ( nic->node_addr ),
+ (unsigned int) ioaddr );
+
+ tp->chip_id = chip_idx;
+ tp->revision = chip_rev;
+ tp->csr0 = csr0;
+
+ /* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles.
+ And the ASIX must have a burst limit or horrible things happen. */
+ if (chip_idx == DC21143 && chip_rev == 65)
+ tp->csr0 &= ~0x01000000;
+ else if (tp->flags & IS_ASIX)
+ tp->csr0 |= 0x2000;
+
+ if (media_cap[tp->default_port] & MediaIsMII) {
+ static const u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60,
+ 0x80, 0x100, 0x200 };
+ tp->mii_advertise = media2advert[tp->default_port - 9];
+ tp->mii_advertise |= (tp->flags & HAS_8023X); /* Matching bits! */
+ }
+
+ /* This is logically part of the probe routine, but too complex
+ to write inline. */
+ if (tp->flags & HAS_MEDIA_TABLE) {
+ memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom));
+ parse_eeprom(nic);
+ }
+
+ start_link(nic);
+
+ /* reset the device and make ready for tx and rx of packets */
+ tulip_reset(nic);
+ nic->nic_op = &tulip_operations;
+
+ /* give the board a chance to reset before returning */
+ tulip_wait(4*TICKS_PER_SEC);
+
+ return 1;
+}
+
+static void start_link(struct nic *nic)
+{
+ int i;
+
+ whereami("start_link\n");
+
+ if ((tp->flags & ALWAYS_CHECK_MII) ||
+ (tp->mtable && tp->mtable->has_mii) ||
+ ( ! tp->mtable && (tp->flags & HAS_MII))) {
+ unsigned int phy, phy_idx;
+ if (tp->mtable && tp->mtable->has_mii) {
+ for (i = 0; i < tp->mtable->leafcount; i++)
+ if (tp->mtable->mleaf[i].media == 11) {
+ tp->cur_index = i;
+ tp->saved_if_port = tp->if_port;
+ select_media(nic, 2);
+ tp->if_port = tp->saved_if_port;
+ break;
+ }
+ }
+
+ /* Find the connected MII xcvrs. */
+ for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
+ phy++) {
+ int mii_status = mdio_read(nic, phy, 1);
+ if ((mii_status & 0x8301) == 0x8001 ||
+ ((mii_status & 0x8000) == 0 && (mii_status & 0x7800) != 0)) {
+ int mii_reg0 = mdio_read(nic, phy, 0);
+ int mii_advert = mdio_read(nic, phy, 4);
+ int to_advert;
+
+ if (tp->mii_advertise)
+ to_advert = tp->mii_advertise;
+ else if (tp->advertising[phy_idx])
+ to_advert = tp->advertising[phy_idx];
+ else /* Leave unchanged. */
+ tp->mii_advertise = to_advert = mii_advert;
+
+ tp->phys[phy_idx++] = phy;
+ DBG("%s: MII transceiver %d config %hX status %hX advertising %hX.\n",
+ tp->nic_name, phy, mii_reg0, mii_status, mii_advert);
+ /* Fixup for DLink with miswired PHY. */
+ if (mii_advert != to_advert) {
+ DBG("%s: Advertising %hX on PHY %d previously advertising %hX.\n",
+ tp->nic_name, to_advert, phy, mii_advert);
+ mdio_write(nic, phy, 4, to_advert);
+ }
+ /* Enable autonegotiation: some boards default to off. */
+ mdio_write(nic, phy, 0, mii_reg0 |
+ (tp->full_duplex ? 0x1100 : 0x1000) |
+ (media_cap[tp->default_port]&MediaIs100 ? 0x2000:0));
+ }
+ }
+ tp->mii_cnt = phy_idx;
+ if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) {
+ DBG("%s: ***WARNING***: No MII transceiver found!\n",
+ tp->nic_name);
+ tp->phys[0] = 1;
+ }
+ }
+
+ /* Reset the xcvr interface and turn on heartbeat. */
+ switch (tp->chip_id) {
+ case DC21040:
+ outl(0x00000000, ioaddr + CSR13);
+ outl(0x00000004, ioaddr + CSR13);
+ break;
+ case DC21041:
+ /* This is nway_start(). */
+ if (tp->sym_advertise == 0)
+ tp->sym_advertise = 0x0061;
+ outl(0x00000000, ioaddr + CSR13);
+ outl(0xFFFFFFFF, ioaddr + CSR14);
+ outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
+ outl(inl(ioaddr + CSR6) | 0x0200, ioaddr + CSR6);
+ outl(0x0000EF01, ioaddr + CSR13);
+ break;
+ case DC21140: default:
+ if (tp->mtable)
+ outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
+ break;
+ case DC21142:
+ case PNIC2:
+ if (tp->mii_cnt || media_cap[tp->if_port] & MediaIsMII) {
+ outl(0x82020000, ioaddr + CSR6);
+ outl(0x0000, ioaddr + CSR13);
+ outl(0x0000, ioaddr + CSR14);
+ outl(0x820E0000, ioaddr + CSR6);
+ } else
+ nway_start(nic);
+ break;
+ case LC82C168:
+ if ( ! tp->mii_cnt) {
+ tp->nway = 1;
+ tp->nwayset = 0;
+ outl(0x00420000, ioaddr + CSR6);
+ outl(0x30, ioaddr + CSR12);
+ outl(0x0001F078, ioaddr + 0xB8);
+ outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
+ }
+ break;
+ case MX98713: case COMPEX9881:
+ outl(0x00000000, ioaddr + CSR6);
+ outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */
+ outl(0x00000001, ioaddr + CSR13);
+ break;
+ case MX98715: case MX98725:
+ outl(0x01a80000, ioaddr + CSR6);
+ outl(0xFFFFFFFF, ioaddr + CSR14);
+ outl(0x00001000, ioaddr + CSR12);
+ break;
+ case COMET:
+ /* No initialization necessary. */
+ break;
+ }
+}
+
+static void nway_start(struct nic *nic __unused)
+{
+ int csr14 = ((tp->sym_advertise & 0x0780) << 9) |
+ ((tp->sym_advertise&0x0020)<<1) | 0xffbf;
+
+ whereami("nway_start\n");
+
+ tp->if_port = 0;
+ tp->nway = tp->mediasense = 1;
+ tp->nwayset = tp->lpar = 0;
+ if (tp->chip_id == PNIC2) {
+ tp->csr6 = 0x01000000 | (tp->sym_advertise & 0x0040 ? 0x0200 : 0);
+ return;
+ }
+ DBG2("%s: Restarting internal NWay autonegotiation, %X.\n",
+ tp->nic_name, csr14);
+ outl(0x0001, ioaddr + CSR13);
+ outl(csr14, ioaddr + CSR14);
+ tp->csr6 = 0x82420000 | (tp->sym_advertise & 0x0040 ? 0x0200 : 0);
+ outl(tp->csr6, ioaddr + CSR6);
+ if (tp->mtable && tp->mtable->csr15dir) {
+ outl(tp->mtable->csr15dir, ioaddr + CSR15);
+ outl(tp->mtable->csr15val, ioaddr + CSR15);
+ } else if (tp->chip_id != PNIC2)
+ outw(0x0008, ioaddr + CSR15);
+ if (tp->chip_id == DC21041) /* Trigger NWAY. */
+ outl(0xEF01, ioaddr + CSR12);
+ else
+ outl(0x1301, ioaddr + CSR12);
+}
+
+static void init_media(struct nic *nic)
+{
+ int i;
+
+ whereami("init_media\n");
+
+ tp->saved_if_port = tp->if_port;
+ if (tp->if_port == 0)
+ tp->if_port = tp->default_port;
+
+ /* Allow selecting a default media. */
+ i = 0;
+ if (tp->mtable == NULL)
+ goto media_picked;
+ if (tp->if_port) {
+ int looking_for = media_cap[tp->if_port] & MediaIsMII ? 11 :
+ (tp->if_port == 12 ? 0 : tp->if_port);
+ for (i = 0; i < tp->mtable->leafcount; i++)
+ if (tp->mtable->mleaf[i].media == looking_for) {
+ DBG("%s: Using user-specified media %s.\n",
+ tp->nic_name, medianame[tp->if_port]);
+ goto media_picked;
+ }
+ }
+ if ((tp->mtable->defaultmedia & 0x0800) == 0) {
+ int looking_for = tp->mtable->defaultmedia & 15;
+ for (i = 0; i < tp->mtable->leafcount; i++)
+ if (tp->mtable->mleaf[i].media == looking_for) {
+ DBG("%s: Using EEPROM-set media %s.\n",
+ tp->nic_name, medianame[looking_for]);
+ goto media_picked;
+ }
+ }
+ /* Start sensing first non-full-duplex media. */
+ for (i = tp->mtable->leafcount - 1;
+ (media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--)
+ ;
+ media_picked:
+
+ tp->csr6 = 0;
+ tp->cur_index = i;
+ tp->nwayset = 0;
+
+ if (tp->if_port) {
+ if (tp->chip_id == DC21143 && media_cap[tp->if_port] & MediaIsMII) {
+ /* We must reset the media CSRs when we force-select MII mode. */
+ outl(0x0000, ioaddr + CSR13);
+ outl(0x0000, ioaddr + CSR14);
+ outl(0x0008, ioaddr + CSR15);
+ }
+ select_media(nic, 1);
+ return;
+ }
+ switch(tp->chip_id) {
+ case DC21041:
+ /* tp->nway = 1;*/
+ nway_start(nic);
+ break;
+ case DC21142:
+ if (tp->mii_cnt) {
+ select_media(nic, 1);
+ DBG2("%s: Using MII transceiver %d, status %hX.\n",
+ tp->nic_name, tp->phys[0], mdio_read(nic, tp->phys[0], 1));
+ outl(0x82020000, ioaddr + CSR6);
+ tp->csr6 = 0x820E0000;
+ tp->if_port = 11;
+ outl(0x0000, ioaddr + CSR13);
+ outl(0x0000, ioaddr + CSR14);
+ } else
+ nway_start(nic);
+ break;
+ case PNIC2:
+ nway_start(nic);
+ break;
+ case LC82C168:
+ if (tp->mii_cnt) {
+ tp->if_port = 11;
+ tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0);
+ outl(0x0001, ioaddr + CSR15);
+ } else if (inl(ioaddr + CSR5) & TPLnkPass)
+ pnic_do_nway(nic);
+ else {
+ /* Start with 10mbps to do autonegotiation. */
+ outl(0x32, ioaddr + CSR12);
+ tp->csr6 = 0x00420000;
+ outl(0x0001B078, ioaddr + 0xB8);
+ outl(0x0201B078, ioaddr + 0xB8);
+ }
+ break;
+ case MX98713: case COMPEX9881:
+ tp->if_port = 0;
+ tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0);
+ outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
+ break;
+ case MX98715: case MX98725:
+ /* Provided by BOLO, Macronix - 12/10/1998. */
+ tp->if_port = 0;
+ tp->csr6 = 0x01a80200;
+ outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
+ outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);
+ break;
+ case COMET:
+ /* Enable automatic Tx underrun recovery */
+ outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88);
+ tp->if_port = 0;
+ tp->csr6 = 0x00040000;
+ break;
+ case AX88140: case AX88141:
+ tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100;
+ break;
+ default:
+ select_media(nic, 1);
+ }
+}
+
+static void pnic_do_nway(struct nic *nic __unused)
+{
+ u32 phy_reg = inl(ioaddr + 0xB8);
+ u32 new_csr6 = tp->csr6 & ~0x40C40200;
+
+ whereami("pnic_do_nway\n");
+
+ if (phy_reg & 0x78000000) { /* Ignore baseT4 */
+ if (phy_reg & 0x20000000) tp->if_port = 5;
+ else if (phy_reg & 0x40000000) tp->if_port = 3;
+ else if (phy_reg & 0x10000000) tp->if_port = 4;
+ else if (phy_reg & 0x08000000) tp->if_port = 0;
+ tp->nwayset = 1;
+ new_csr6 = (tp->if_port & 1) ? 0x01860000 : 0x00420000;
+ outl(0x32 | (tp->if_port & 1), ioaddr + CSR12);
+ if (tp->if_port & 1)
+ outl(0x1F868, ioaddr + 0xB8);
+ if (phy_reg & 0x30000000) {
+ tp->full_duplex = 1;
+ new_csr6 |= 0x00000200;
+ }
+ DBG2("%s: PNIC autonegotiated status %X, %s.\n",
+ tp->nic_name, phy_reg, medianame[tp->if_port]);
+ if (tp->csr6 != new_csr6) {
+ tp->csr6 = new_csr6;
+ outl(tp->csr6 | 0x0002, ioaddr + CSR6); /* Restart Tx */
+ outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ }
+ }
+}
+
+/* Set up the transceiver control registers for the selected media type. */
+static void select_media(struct nic *nic, int startup)
+{
+ struct mediatable *mtable = tp->mtable;
+ u32 new_csr6;
+ int i;
+
+ whereami("select_media\n");
+
+ if (mtable) {
+ struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index];
+ unsigned char *p = mleaf->leafdata;
+ switch (mleaf->type) {
+ case 0: /* 21140 non-MII xcvr. */
+ DBG2("%s: Using a 21140 non-MII transceiver"
+ " with control setting %hhX.\n",
+ tp->nic_name, p[1]);
+ tp->if_port = p[0];
+ if (startup)
+ outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
+ outl(p[1], ioaddr + CSR12);
+ new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18);
+ break;
+ case 2: case 4: {
+ u16 setup[5];
+ u32 csr13val, csr14val, csr15dir, csr15val;
+ for (i = 0; i < 5; i++)
+ setup[i] = get_u16(&p[i*2 + 1]);
+
+ tp->if_port = p[0] & 15;
+ if (media_cap[tp->if_port] & MediaAlwaysFD)
+ tp->full_duplex = 1;
+
+ if (startup && mtable->has_reset) {
+ struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
+ unsigned char *rst = rleaf->leafdata;
+ DBG2("%s: Resetting the transceiver.\n",
+ tp->nic_name);
+ for (i = 0; i < rst[0]; i++)
+ outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);
+ }
+ DBG2("%s: 21143 non-MII %s transceiver control %hX/%hX.\n",
+ tp->nic_name, medianame[tp->if_port], setup[0], setup[1]);
+ if (p[0] & 0x40) { /* SIA (CSR13-15) setup values are provided. */
+ csr13val = setup[0];
+ csr14val = setup[1];
+ csr15dir = (setup[3]<<16) | setup[2];
+ csr15val = (setup[4]<<16) | setup[2];
+ outl(0, ioaddr + CSR13);
+ outl(csr14val, ioaddr + CSR14);
+ outl(csr15dir, ioaddr + CSR15); /* Direction */
+ outl(csr15val, ioaddr + CSR15); /* Data */
+ outl(csr13val, ioaddr + CSR13);
+ } else {
+ csr13val = 1;
+ csr14val = 0x0003FF7F;
+ csr15dir = (setup[0]<<16) | 0x0008;
+ csr15val = (setup[1]<<16) | 0x0008;
+ if (tp->if_port <= 4)
+ csr14val = t21142_csr14[tp->if_port];
+ if (startup) {
+ outl(0, ioaddr + CSR13);
+ outl(csr14val, ioaddr + CSR14);
+ }
+ outl(csr15dir, ioaddr + CSR15); /* Direction */
+ outl(csr15val, ioaddr + CSR15); /* Data */
+ if (startup) outl(csr13val, ioaddr + CSR13);
+ }
+ DBG2("%s: Setting CSR15 to %X/%X.\n",
+ tp->nic_name, csr15dir, csr15val);
+ if (mleaf->type == 4)
+ new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18);
+ else
+ new_csr6 = 0x82420000;
+ break;
+ }
+ case 1: case 3: {
+ int phy_num = p[0];
+ int init_length = p[1];
+ u16 *misc_info;
+
+ tp->if_port = 11;
+ new_csr6 = 0x020E0000;
+ if (mleaf->type == 3) { /* 21142 */
+ u16 *init_sequence = (u16*)(p+2);
+ u16 *reset_sequence = &((u16*)(p+3))[init_length];
+ int reset_length = p[2 + init_length*2];
+ misc_info = reset_sequence + reset_length;
+ if (startup)
+ for (i = 0; i < reset_length; i++)
+ outl(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15);
+ for (i = 0; i < init_length; i++)
+ outl(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15);
+ } else {
+ u8 *init_sequence = p + 2;
+ u8 *reset_sequence = p + 3 + init_length;
+ int reset_length = p[2 + init_length];
+ misc_info = (u16*)(reset_sequence + reset_length);
+ if (startup) {
+ outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
+ for (i = 0; i < reset_length; i++)
+ outl(reset_sequence[i], ioaddr + CSR12);
+ }
+ for (i = 0; i < init_length; i++)
+ outl(init_sequence[i], ioaddr + CSR12);
+ }
+ tp->advertising[phy_num] = get_u16(&misc_info[1]) | 1;
+ if (startup < 2) {
+ if (tp->mii_advertise == 0)
+ tp->mii_advertise = tp->advertising[phy_num];
+ DBG2("%s: Advertising %hX on MII %d.\n",
+ tp->nic_name, tp->mii_advertise, tp->phys[phy_num]);
+ mdio_write(nic, tp->phys[phy_num], 4, tp->mii_advertise);
+ }
+ break;
+ }
+ default:
+ DBG("%s: Invalid media table selection %d.\n",
+ tp->nic_name, mleaf->type);
+ new_csr6 = 0x020E0000;
+ }
+ DBG2("%s: Using media type %s, CSR12 is %hhX.\n",
+ tp->nic_name, medianame[tp->if_port],
+ inl(ioaddr + CSR12) & 0xff);
+ } else if (tp->chip_id == DC21041) {
+ int port = tp->if_port <= 4 ? tp->if_port : 0;
+ DBG2("%s: 21041 using media %s, CSR12 is %hX.\n",
+ tp->nic_name, medianame[port == 3 ? 12: port],
+ inl(ioaddr + CSR12));
+ outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
+ outl(t21041_csr14[port], ioaddr + CSR14);
+ outl(t21041_csr15[port], ioaddr + CSR15);
+ outl(t21041_csr13[port], ioaddr + CSR13);
+ new_csr6 = 0x80020000;
+ } else if (tp->chip_id == LC82C168) {
+ if (startup && ! tp->medialock)
+ tp->if_port = tp->mii_cnt ? 11 : 0;
+ DBG2("%s: PNIC PHY status is %hX, media %s.\n",
+ tp->nic_name, inl(ioaddr + 0xB8), medianame[tp->if_port]);
+ if (tp->mii_cnt) {
+ new_csr6 = 0x810C0000;
+ outl(0x0001, ioaddr + CSR15);
+ outl(0x0201B07A, ioaddr + 0xB8);
+ } else if (startup) {
+ /* Start with 10mbps to do autonegotiation. */
+ outl(0x32, ioaddr + CSR12);
+ new_csr6 = 0x00420000;
+ outl(0x0001B078, ioaddr + 0xB8);
+ outl(0x0201B078, ioaddr + 0xB8);
+ } else if (tp->if_port == 3 || tp->if_port == 5) {
+ outl(0x33, ioaddr + CSR12);
+ new_csr6 = 0x01860000;
+ /* Trigger autonegotiation. */
+ outl(startup ? 0x0201F868 : 0x0001F868, ioaddr + 0xB8);
+ } else {
+ outl(0x32, ioaddr + CSR12);
+ new_csr6 = 0x00420000;
+ outl(0x1F078, ioaddr + 0xB8);
+ }
+ } else if (tp->chip_id == DC21040) { /* 21040 */
+ /* Turn on the xcvr interface. */
+ int csr12 = inl(ioaddr + CSR12);
+ DBG2("%s: 21040 media type is %s, CSR12 is %hhX.\n",
+ tp->nic_name, medianame[tp->if_port], csr12);
+ if (media_cap[tp->if_port] & MediaAlwaysFD)
+ tp->full_duplex = 1;
+ new_csr6 = 0x20000;
+ /* Set the full duplux match frame. */
+ outl(FULL_DUPLEX_MAGIC, ioaddr + CSR11);
+ outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
+ if (t21040_csr13[tp->if_port] & 8) {
+ outl(0x0705, ioaddr + CSR14);
+ outl(0x0006, ioaddr + CSR15);
+ } else {
+ outl(0xffff, ioaddr + CSR14);
+ outl(0x0000, ioaddr + CSR15);
+ }
+ outl(0x8f01 | t21040_csr13[tp->if_port], ioaddr + CSR13);
+ } else { /* Unknown chip type with no media table. */
+ if (tp->default_port == 0)
+ tp->if_port = tp->mii_cnt ? 11 : 3;
+ if (media_cap[tp->if_port] & MediaIsMII) {
+ new_csr6 = 0x020E0000;
+ } else if (media_cap[tp->if_port] & MediaIsFx) {
+ new_csr6 = 0x028600000;
+ } else
+ new_csr6 = 0x038600000;
+ DBG2("%s: No media description table, assuming "
+ "%s transceiver, CSR12 %hhX.\n",
+ tp->nic_name, medianame[tp->if_port],
+ inl(ioaddr + CSR12));
+ }
+
+ tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0);
+ return;
+}
+
+/*
+ Check the MII negotiated duplex and change the CSR6 setting if
+ required.
+ Return 0 if everything is OK.
+ Return < 0 if the transceiver is missing or has no link beat.
+*/
+static int tulip_check_duplex(struct nic *nic)
+{
+ unsigned int bmsr, lpa, negotiated, new_csr6;
+
+ bmsr = mdio_read(nic, tp->phys[0], 1);
+ lpa = mdio_read(nic, tp->phys[0], 5);
+
+ DBG2("%s: MII status %#x, Link partner report %#x.\n",
+ tp->nic_name, bmsr, lpa);
+
+ if (bmsr == 0xffff)
+ return -2;
+ if ((bmsr & 4) == 0) {
+ int new_bmsr = mdio_read(nic, tp->phys[0], 1);
+ if ((new_bmsr & 4) == 0) {
+ DBG2("%s: No link beat on the MII interface,"
+ " status %#x.\n", tp->nic_name,
+ new_bmsr);
+ return -1;
+ }
+ }
+ tp->full_duplex = lpa & 0x140;
+
+ new_csr6 = tp->csr6;
+ negotiated = lpa & tp->advertising[0];
+
+ if(negotiated & 0x380) new_csr6 &= ~0x400000;
+ else new_csr6 |= 0x400000;
+ if (tp->full_duplex) new_csr6 |= 0x200;
+ else new_csr6 &= ~0x200;
+
+ if (new_csr6 != tp->csr6) {
+ tp->csr6 = new_csr6;
+
+ DBG("%s: Setting %s-duplex based on MII"
+ "#%d link partner capability of %#x.\n",
+ tp->nic_name,
+ tp->full_duplex ? "full" : "half",
+ tp->phys[0], lpa);
+ return 1;
+ }
+
+ return 0;
+}
+
+static struct pci_device_id tulip_nics[] = {
+PCI_ROM(0x1011, 0x0002, "dc21040", "Digital Tulip", 0),
+PCI_ROM(0x1011, 0x0009, "ds21140", "Digital Tulip Fast", 0),
+PCI_ROM(0x1011, 0x0014, "dc21041", "Digital Tulip+", 0),
+PCI_ROM(0x1011, 0x0019, "ds21142", "Digital Tulip 21142", 0),
+PCI_ROM(0x10b7, 0x9300, "3csoho100b-tx","3ComSOHO100B-TX", 0),
+PCI_ROM(0x10b9, 0x5261, "ali1563", "ALi 1563 integrated ethernet", 0),
+PCI_ROM(0x10d9, 0x0512, "mx98713", "Macronix MX987x3", 0),
+PCI_ROM(0x10d9, 0x0531, "mx98715", "Macronix MX987x5", 0),
+PCI_ROM(0x1113, 0x1217, "mxic-98715", "Macronix MX987x5", 0),
+PCI_ROM(0x11ad, 0xc115, "lc82c115", "LinkSys LNE100TX", 0),
+PCI_ROM(0x11ad, 0x0002, "82c168", "Netgear FA310TX", 0),
+PCI_ROM(0x1282, 0x9100, "dm9100", "Davicom 9100", 0),
+PCI_ROM(0x1282, 0x9102, "dm9102", "Davicom 9102", 0),
+PCI_ROM(0x1282, 0x9009, "dm9009", "Davicom 9009", 0),
+PCI_ROM(0x1282, 0x9132, "dm9132", "Davicom 9132", 0),
+PCI_ROM(0x1317, 0x0985, "centaur-p", "ADMtek Centaur-P", 0),
+PCI_ROM(0x1317, 0x0981, "an981", "ADMtek AN981 Comet", 0), /* ADMTek Centaur-P (stmicro) */
+PCI_ROM(0x1113, 0x1216, "an983", "ADMTek AN983 Comet", 0),
+PCI_ROM(0x1317, 0x9511, "an983b", "ADMTek Comet 983b", 0),
+PCI_ROM(0x1317, 0x1985, "centaur-c", "ADMTek Centaur-C", 0),
+PCI_ROM(0x8086, 0x0039, "intel21145", "Intel Tulip", 0),
+PCI_ROM(0x125b, 0x1400, "ax88140", "ASIX AX88140", 0),
+PCI_ROM(0x11f6, 0x9881, "rl100tx", "Compex RL100-TX", 0),
+PCI_ROM(0x115d, 0x0003, "xircomtulip", "Xircom Tulip", 0),
+PCI_ROM(0x104a, 0x0981, "tulip-0981", "Tulip 0x104a 0x0981", 0),
+PCI_ROM(0x104a, 0x2774, "SGThomson-STE10100A", "Tulip 0x104a 0x2774", 0), /*Modified by Ramesh Chander*/
+PCI_ROM(0x1113, 0x9511, "tulip-9511", "Tulip 0x1113 0x9511", 0),
+PCI_ROM(0x1186, 0x1561, "tulip-1561", "Tulip 0x1186 0x1561", 0),
+PCI_ROM(0x1259, 0xa120, "tulip-a120", "Tulip 0x1259 0xa120", 0),
+PCI_ROM(0x13d1, 0xab02, "tulip-ab02", "Tulip 0x13d1 0xab02", 0),
+PCI_ROM(0x13d1, 0xab03, "tulip-ab03", "Tulip 0x13d1 0xab03", 0),
+PCI_ROM(0x13d1, 0xab08, "tulip-ab08", "Tulip 0x13d1 0xab08", 0),
+PCI_ROM(0x14f1, 0x1803, "lanfinity", "Conexant LANfinity", 0),
+PCI_ROM(0x1626, 0x8410, "tulip-8410", "Tulip 0x1626 0x8410", 0),
+PCI_ROM(0x1737, 0xab08, "tulip-1737-ab08","Tulip 0x1737 0xab08", 0),
+PCI_ROM(0x1737, 0xab09, "tulip-ab09", "Tulip 0x1737 0xab09", 0),
+};
+
+PCI_DRIVER ( tulip_driver, tulip_nics, PCI_NO_CLASS );
+
+DRIVER ( "Tulip", nic_driver, pci_driver, tulip_driver,
+ tulip_probe, tulip_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/tulip.txt b/src/VBox/Devices/PC/ipxe/src/drivers/net/tulip.txt
new file mode 100644
index 00000000..b4f6756d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/tulip.txt
@@ -0,0 +1,54 @@
+This software may be used and distributed according to the terms of
+the GNU Public License, incorporated herein by reference.
+
+This is a tulip and clone driver for Etherboot. See the revision
+history in the tulip.c file for information on changes. This version
+of the driver incorporates changes from Bob Edwards and Paul Mackerras
+who cantributed changes to support the TRENDnet TE100-PCIA NIC which
+uses a genuine Intel 21143-PD chipset. There are also various code
+cleanups to make time-based activities more reliable.
+
+Of course you have to have all the usual Etherboot environment
+(bootp/dhcp/NFS) set up, and you need a Linux kernel with v0.91g
+(7.16.99) or later of the tulip.c driver compiled in to support some
+MX98715 based cards. That file is available at:
+
+ http://cesdis.gsfc.nasa.gov/linux/drivers/test/tulip.c
+
+NOTES
+
+I've tested this driver with a SOHOware Fast 10/100 Model SDA110A,
+a Linksys LNE100TX v2.0, and a Netgear FA310TX card, and it worked at
+both 10 and 100 mbits. Other cards based on the tulip family may work as
+well.
+
+These cards are about 20$US, are supported by Linux and now Etherboot,
+and being PCI, they auto-configure IRQ and IOADDR and auto-negotiate
+10/100 half/full duplex. It seems like a pretty good value compared to
+some of the pricier cards, and can lower the cost of building/adapting
+thin client workstations substantially while giving a considerable
+performance increase.
+
+On some PCI tulip clone chipsets (MX987x5, LC82C115, LC82C168) this driver
+lets the card choose the fastest speed it can negotiate with the peer
+device. On other cards, it chooses 10mbit half-duplex.
+
+I burned an AM27C256 (32KByte) EPROM with mx987x5.lzrom and it worked.
+According to the data sheet the MX98715A supports up to 64K (27C512)
+EPROMs,
+
+I've liberally commented the code and header files in the hope that it
+will help the next person who hacks the code or needs to support some
+tulip clone card, or wishes to add functionality.
+
+Anyway, please test this if you can on your tulip based card, and let
+me (mdc@etherboot.org) and the Etherboot-Discuss list
+(etherboot-discuss@lists.sourceforge.net) know how things go. I also
+would appreciate code review by people who program. I'm a strong
+believer in "another set of eyes".
+
+Regards,
+
+Marty Connor
+mdc@etherboot.org
+http://www.etherboot.org/
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/via-rhine.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/via-rhine.c
new file mode 100644
index 00000000..03719afd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/via-rhine.c
@@ -0,0 +1,1447 @@
+/* rhine.c:Fast Ethernet driver for Linux. */
+/*
+ Adapted 09-jan-2000 by Paolo Marini (paolom@prisma-eng.it)
+
+ originally written by Donald Becker.
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License (GPL), incorporated herein by reference.
+ Drivers derived from this code also fall under the GPL and must retain
+ this authorship and copyright notice.
+
+ Under no circumstances are the authors responsible for
+ the proper functioning of this software, nor do the authors assume any
+ responsibility for damages incurred with its use.
+
+ This driver is designed for the VIA VT86C100A Rhine-II PCI Fast Ethernet
+ controller.
+
+*/
+
+static const char *version = "rhine.c v1.0.2 2004-10-29\n";
+
+/* A few user-configurable values. */
+
+// max time out delay time
+#define W_MAX_TIMEOUT 0x0FFFU
+
+/* Size of the in-memory receive ring. */
+#define RX_BUF_LEN_IDX 3 /* 0==8K, 1==16K, 2==32K, 3==64K */
+#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
+
+/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */
+#define TX_BUF_SIZE 1536
+#define RX_BUF_SIZE 1536
+
+/* PCI Tuning Parameters
+ Threshold is bytes transferred to chip before transmission starts. */
+#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */
+
+/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024. */
+#define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */
+#define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */
+#define TX_DMA_BURST 4
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT ((2000*HZ)/1000)
+
+#include "etherboot.h"
+#include "nic.h"
+#include <ipxe/pci.h>
+#include <ipxe/ethernet.h>
+
+/* define all ioaddr */
+
+#define byPAR0 ioaddr
+#define byRCR ioaddr + 6
+#define byTCR ioaddr + 7
+#define byCR0 ioaddr + 8
+#define byCR1 ioaddr + 9
+#define byISR0 ioaddr + 0x0c
+#define byISR1 ioaddr + 0x0d
+#define byIMR0 ioaddr + 0x0e
+#define byIMR1 ioaddr + 0x0f
+#define byMAR0 ioaddr + 0x10
+#define byMAR1 ioaddr + 0x11
+#define byMAR2 ioaddr + 0x12
+#define byMAR3 ioaddr + 0x13
+#define byMAR4 ioaddr + 0x14
+#define byMAR5 ioaddr + 0x15
+#define byMAR6 ioaddr + 0x16
+#define byMAR7 ioaddr + 0x17
+#define dwCurrentRxDescAddr ioaddr + 0x18
+#define dwCurrentTxDescAddr ioaddr + 0x1c
+#define dwCurrentRDSE0 ioaddr + 0x20
+#define dwCurrentRDSE1 ioaddr + 0x24
+#define dwCurrentRDSE2 ioaddr + 0x28
+#define dwCurrentRDSE3 ioaddr + 0x2c
+#define dwNextRDSE0 ioaddr + 0x30
+#define dwNextRDSE1 ioaddr + 0x34
+#define dwNextRDSE2 ioaddr + 0x38
+#define dwNextRDSE3 ioaddr + 0x3c
+#define dwCurrentTDSE0 ioaddr + 0x40
+#define dwCurrentTDSE1 ioaddr + 0x44
+#define dwCurrentTDSE2 ioaddr + 0x48
+#define dwCurrentTDSE3 ioaddr + 0x4c
+#define dwNextTDSE0 ioaddr + 0x50
+#define dwNextTDSE1 ioaddr + 0x54
+#define dwNextTDSE2 ioaddr + 0x58
+#define dwNextTDSE3 ioaddr + 0x5c
+#define dwCurrRxDMAPtr ioaddr + 0x60
+#define dwCurrTxDMAPtr ioaddr + 0x64
+#define byMPHY ioaddr + 0x6c
+#define byMIISR ioaddr + 0x6d
+#define byBCR0 ioaddr + 0x6e
+#define byBCR1 ioaddr + 0x6f
+#define byMIICR ioaddr + 0x70
+#define byMIIAD ioaddr + 0x71
+#define wMIIDATA ioaddr + 0x72
+#define byEECSR ioaddr + 0x74
+#define byTEST ioaddr + 0x75
+#define byGPIO ioaddr + 0x76
+#define byCFGA ioaddr + 0x78
+#define byCFGB ioaddr + 0x79
+#define byCFGC ioaddr + 0x7a
+#define byCFGD ioaddr + 0x7b
+#define wTallyCntMPA ioaddr + 0x7c
+#define wTallyCntCRC ioaddr + 0x7d
+#define bySTICKHW ioaddr + 0x83
+#define byWOLcrClr ioaddr + 0xA4
+#define byWOLcgClr ioaddr + 0xA7
+#define byPwrcsrClr ioaddr + 0xAC
+
+/*--------------------- Exioaddr Definitions -------------------------*/
+
+/*
+ * Bits in the RCR register
+ */
+
+#define RCR_RRFT2 0x80
+#define RCR_RRFT1 0x40
+#define RCR_RRFT0 0x20
+#define RCR_PROM 0x10
+#define RCR_AB 0x08
+#define RCR_AM 0x04
+#define RCR_AR 0x02
+#define RCR_SEP 0x01
+
+/*
+ * Bits in the TCR register
+ */
+
+#define TCR_RTSF 0x80
+#define TCR_RTFT1 0x40
+#define TCR_RTFT0 0x20
+#define TCR_OFSET 0x08
+#define TCR_LB1 0x04 /* loopback[1] */
+#define TCR_LB0 0x02 /* loopback[0] */
+
+/*
+ * Bits in the CR0 register
+ */
+
+#define CR0_RDMD 0x40 /* rx descriptor polling demand */
+#define CR0_TDMD 0x20 /* tx descriptor polling demand */
+#define CR0_TXON 0x10
+#define CR0_RXON 0x08
+#define CR0_STOP 0x04 /* stop NIC, default = 1 */
+#define CR0_STRT 0x02 /* start NIC */
+#define CR0_INIT 0x01 /* start init process */
+
+
+/*
+ * Bits in the CR1 register
+ */
+
+#define CR1_SFRST 0x80 /* software reset */
+#define CR1_RDMD1 0x40 /* RDMD1 */
+#define CR1_TDMD1 0x20 /* TDMD1 */
+#define CR1_KEYPAG 0x10 /* turn on par/key */
+#define CR1_DPOLL 0x08 /* disable rx/tx auto polling */
+#define CR1_FDX 0x04 /* full duplex mode */
+#define CR1_ETEN 0x02 /* early tx mode */
+#define CR1_EREN 0x01 /* early rx mode */
+
+/*
+ * Bits in the CR register
+ */
+
+#define CR_RDMD 0x0040 /* rx descriptor polling demand */
+#define CR_TDMD 0x0020 /* tx descriptor polling demand */
+#define CR_TXON 0x0010
+#define CR_RXON 0x0008
+#define CR_STOP 0x0004 /* stop NIC, default = 1 */
+#define CR_STRT 0x0002 /* start NIC */
+#define CR_INIT 0x0001 /* start init process */
+#define CR_SFRST 0x8000 /* software reset */
+#define CR_RDMD1 0x4000 /* RDMD1 */
+#define CR_TDMD1 0x2000 /* TDMD1 */
+#define CR_KEYPAG 0x1000 /* turn on par/key */
+#define CR_DPOLL 0x0800 /* disable rx/tx auto polling */
+#define CR_FDX 0x0400 /* full duplex mode */
+#define CR_ETEN 0x0200 /* early tx mode */
+#define CR_EREN 0x0100 /* early rx mode */
+
+/*
+ * Bits in the IMR0 register
+ */
+
+#define IMR0_CNTM 0x80
+#define IMR0_BEM 0x40
+#define IMR0_RUM 0x20
+#define IMR0_TUM 0x10
+#define IMR0_TXEM 0x08
+#define IMR0_RXEM 0x04
+#define IMR0_PTXM 0x02
+#define IMR0_PRXM 0x01
+
+/* define imrshadow */
+
+#define IMRShadow 0x5AFF
+
+/*
+ * Bits in the IMR1 register
+ */
+
+#define IMR1_INITM 0x80
+#define IMR1_SRCM 0x40
+#define IMR1_NBFM 0x10
+#define IMR1_PRAIM 0x08
+#define IMR1_RES0M 0x04
+#define IMR1_ETM 0x02
+#define IMR1_ERM 0x01
+
+/*
+ * Bits in the ISR register
+ */
+
+#define ISR_INITI 0x8000
+#define ISR_SRCI 0x4000
+#define ISR_ABTI 0x2000
+#define ISR_NORBF 0x1000
+#define ISR_PKTRA 0x0800
+#define ISR_RES0 0x0400
+#define ISR_ETI 0x0200
+#define ISR_ERI 0x0100
+#define ISR_CNT 0x0080
+#define ISR_BE 0x0040
+#define ISR_RU 0x0020
+#define ISR_TU 0x0010
+#define ISR_TXE 0x0008
+#define ISR_RXE 0x0004
+#define ISR_PTX 0x0002
+#define ISR_PRX 0x0001
+
+/*
+ * Bits in the ISR0 register
+ */
+
+#define ISR0_CNT 0x80
+#define ISR0_BE 0x40
+#define ISR0_RU 0x20
+#define ISR0_TU 0x10
+#define ISR0_TXE 0x08
+#define ISR0_RXE 0x04
+#define ISR0_PTX 0x02
+#define ISR0_PRX 0x01
+
+/*
+ * Bits in the ISR1 register
+ */
+
+#define ISR1_INITI 0x80
+#define ISR1_SRCI 0x40
+#define ISR1_NORBF 0x10
+#define ISR1_PKTRA 0x08
+#define ISR1_ETI 0x02
+#define ISR1_ERI 0x01
+
+/* ISR ABNORMAL CONDITION */
+
+#define ISR_ABNORMAL ISR_BE+ISR_RU+ISR_TU+ISR_CNT+ISR_NORBF+ISR_PKTRA
+
+/*
+ * Bits in the MIISR register
+ */
+
+#define MIISR_MIIERR 0x08
+#define MIISR_MRERR 0x04
+#define MIISR_LNKFL 0x02
+#define MIISR_SPEED 0x01
+
+/*
+ * Bits in the MIICR register
+ */
+
+#define MIICR_MAUTO 0x80
+#define MIICR_RCMD 0x40
+#define MIICR_WCMD 0x20
+#define MIICR_MDPM 0x10
+#define MIICR_MOUT 0x08
+#define MIICR_MDO 0x04
+#define MIICR_MDI 0x02
+#define MIICR_MDC 0x01
+
+/*
+ * Bits in the EECSR register
+ */
+
+#define EECSR_EEPR 0x80 /* eeprom programed status, 73h means programed */
+#define EECSR_EMBP 0x40 /* eeprom embeded programming */
+#define EECSR_AUTOLD 0x20 /* eeprom content reload */
+#define EECSR_DPM 0x10 /* eeprom direct programming */
+#define EECSR_CS 0x08 /* eeprom CS pin */
+#define EECSR_SK 0x04 /* eeprom SK pin */
+#define EECSR_DI 0x02 /* eeprom DI pin */
+#define EECSR_DO 0x01 /* eeprom DO pin */
+
+/*
+ * Bits in the BCR0 register
+ */
+
+#define BCR0_CRFT2 0x20
+#define BCR0_CRFT1 0x10
+#define BCR0_CRFT0 0x08
+#define BCR0_DMAL2 0x04
+#define BCR0_DMAL1 0x02
+#define BCR0_DMAL0 0x01
+
+/*
+ * Bits in the BCR1 register
+ */
+
+#define BCR1_CTSF 0x20
+#define BCR1_CTFT1 0x10
+#define BCR1_CTFT0 0x08
+#define BCR1_POT2 0x04
+#define BCR1_POT1 0x02
+#define BCR1_POT0 0x01
+
+/*
+ * Bits in the CFGA register
+ */
+
+#define CFGA_EELOAD 0x80 /* enable eeprom embeded and direct programming */
+#define CFGA_JUMPER 0x40
+#define CFGA_MTGPIO 0x08
+#define CFGA_T10EN 0x02
+#define CFGA_AUTO 0x01
+
+/*
+ * Bits in the CFGB register
+ */
+
+#define CFGB_PD 0x80
+#define CFGB_POLEN 0x02
+#define CFGB_LNKEN 0x01
+
+/*
+ * Bits in the CFGC register
+ */
+
+#define CFGC_M10TIO 0x80
+#define CFGC_M10POL 0x40
+#define CFGC_PHY1 0x20
+#define CFGC_PHY0 0x10
+#define CFGC_BTSEL 0x08
+#define CFGC_BPS2 0x04 /* bootrom select[2] */
+#define CFGC_BPS1 0x02 /* bootrom select[1] */
+#define CFGC_BPS0 0x01 /* bootrom select[0] */
+
+/*
+ * Bits in the CFGD register
+ */
+
+#define CFGD_GPIOEN 0x80
+#define CFGD_DIAG 0x40
+#define CFGD_MAGIC 0x10
+#define CFGD_RANDOM 0x08
+#define CFGD_CFDX 0x04
+#define CFGD_CEREN 0x02
+#define CFGD_CETEN 0x01
+
+/* Bits in RSR */
+#define RSR_RERR 0x00000001
+#define RSR_CRC 0x00000002
+#define RSR_FAE 0x00000004
+#define RSR_FOV 0x00000008
+#define RSR_LONG 0x00000010
+#define RSR_RUNT 0x00000020
+#define RSR_SERR 0x00000040
+#define RSR_BUFF 0x00000080
+#define RSR_EDP 0x00000100
+#define RSR_STP 0x00000200
+#define RSR_CHN 0x00000400
+#define RSR_PHY 0x00000800
+#define RSR_BAR 0x00001000
+#define RSR_MAR 0x00002000
+#define RSR_RXOK 0x00008000
+#define RSR_ABNORMAL RSR_RERR+RSR_LONG+RSR_RUNT
+
+/* Bits in TSR */
+#define TSR_NCR0 0x00000001
+#define TSR_NCR1 0x00000002
+#define TSR_NCR2 0x00000004
+#define TSR_NCR3 0x00000008
+#define TSR_COLS 0x00000010
+#define TSR_CDH 0x00000080
+#define TSR_ABT 0x00000100
+#define TSR_OWC 0x00000200
+#define TSR_CRS 0x00000400
+#define TSR_UDF 0x00000800
+#define TSR_TBUFF 0x00001000
+#define TSR_SERR 0x00002000
+#define TSR_JAB 0x00004000
+#define TSR_TERR 0x00008000
+#define TSR_ABNORMAL TSR_TERR+TSR_OWC+TSR_ABT+TSR_JAB+TSR_CRS
+#define TSR_OWN_BIT 0x80000000
+
+#define CB_DELAY_LOOP_WAIT 10 /* 10ms */
+/* enabled mask value of irq */
+
+#define W_IMR_MASK_VALUE 0x1BFF /* initial value of IMR */
+
+/* Ethernet address filter type */
+#define PKT_TYPE_DIRECTED 0x0001 /* obsolete, directed address is always accepted */
+#define PKT_TYPE_MULTICAST 0x0002
+#define PKT_TYPE_ALL_MULTICAST 0x0004
+#define PKT_TYPE_BROADCAST 0x0008
+#define PKT_TYPE_PROMISCUOUS 0x0020
+#define PKT_TYPE_LONG 0x2000
+#define PKT_TYPE_RUNT 0x4000
+#define PKT_TYPE_ERROR 0x8000 /* accept error packets, e.g. CRC error */
+
+/* Loopback mode */
+
+#define NIC_LB_NONE 0x00
+#define NIC_LB_INTERNAL 0x01
+#define NIC_LB_PHY 0x02 /* MII or Internal-10BaseT loopback */
+
+#define TX_RING_SIZE 2
+#define RX_RING_SIZE 2
+#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */
+
+#define PCI_REG_MODE3 0x53
+#define MODE3_MIION 0x04 /* in PCI_REG_MOD3 OF PCI space */
+
+enum rhine_revs {
+ VT86C100A = 0x00,
+ VTunknown0 = 0x20,
+ VT6102 = 0x40,
+ VT8231 = 0x50, /* Integrated MAC */
+ VT8233 = 0x60, /* Integrated MAC */
+ VT8235 = 0x74, /* Integrated MAC */
+ VT8237 = 0x78, /* Integrated MAC */
+ VTunknown1 = 0x7C,
+ VT6105 = 0x80,
+ VT6105_B0 = 0x83,
+ VT6105L = 0x8A,
+ VT6107 = 0x8C,
+ VTunknown2 = 0x8E,
+ VT6105M = 0x90,
+};
+
+/* Transmit and receive descriptors definition */
+
+struct rhine_tx_desc
+{
+ union VTC_tx_status_tag
+ {
+ struct
+ {
+ unsigned long ncro:1;
+ unsigned long ncr1:1;
+ unsigned long ncr2:1;
+ unsigned long ncr3:1;
+ unsigned long cols:1;
+ unsigned long reserve_1:2;
+ unsigned long cdh:1;
+ unsigned long abt:1;
+ unsigned long owc:1;
+ unsigned long crs:1;
+ unsigned long udf:1;
+ unsigned long tbuff:1;
+ unsigned long serr:1;
+ unsigned long jab:1;
+ unsigned long terr:1;
+ unsigned long reserve_2:15;
+ unsigned long own_bit:1;
+ }
+ bits;
+ unsigned long lw;
+ }
+ tx_status;
+
+ union VTC_tx_ctrl_tag
+ {
+ struct
+ {
+ unsigned long tx_buf_size:11;
+ unsigned long extend_tx_buf_size:4;
+ unsigned long chn:1;
+ unsigned long crc:1;
+ unsigned long reserve_1:4;
+ unsigned long stp:1;
+ unsigned long edp:1;
+ unsigned long ic:1;
+ unsigned long reserve_2:8;
+ }
+ bits;
+ unsigned long lw;
+ }
+ tx_ctrl;
+
+ unsigned long buf_addr_1:32;
+ unsigned long buf_addr_2:32;
+
+};
+
+struct rhine_rx_desc
+{
+ union VTC_rx_status_tag
+ {
+ struct
+ {
+ unsigned long rerr:1;
+ unsigned long crc_error:1;
+ unsigned long fae:1;
+ unsigned long fov:1;
+ unsigned long toolong:1;
+ unsigned long runt:1;
+ unsigned long serr:1;
+ unsigned long buff:1;
+ unsigned long edp:1;
+ unsigned long stp:1;
+ unsigned long chn:1;
+ unsigned long phy:1;
+ unsigned long bar:1;
+ unsigned long mar:1;
+ unsigned long reserve_1:1;
+ unsigned long rxok:1;
+ unsigned long frame_length:11;
+ unsigned long reverve_2:4;
+ unsigned long own_bit:1;
+ }
+ bits;
+ unsigned long lw;
+ }
+ rx_status;
+
+ union VTC_rx_ctrl_tag
+ {
+ struct
+ {
+ unsigned long rx_buf_size:11;
+ unsigned long extend_rx_buf_size:4;
+ unsigned long reserved_1:17;
+ }
+ bits;
+ unsigned long lw;
+ }
+ rx_ctrl;
+
+ unsigned long buf_addr_1:32;
+ unsigned long buf_addr_2:32;
+
+};
+
+struct {
+ char txbuf[TX_RING_SIZE * PKT_BUF_SZ + 32];
+ char rxbuf[RX_RING_SIZE * PKT_BUF_SZ + 32];
+ char txdesc[TX_RING_SIZE * sizeof (struct rhine_tx_desc) + 32];
+ char rxdesc[RX_RING_SIZE * sizeof (struct rhine_rx_desc) + 32];
+} rhine_buffers __shared;
+
+/* The I/O extent. */
+#define rhine_TOTAL_SIZE 0x80
+
+#ifdef HAVE_DEVLIST
+struct netdev_entry rhine_drv =
+ { "rhine", rhine_probe, rhine_TOTAL_SIZE, NULL };
+#endif
+
+static int rhine_debug = 1;
+
+/*
+ Theory of Operation
+
+I. Board Compatibility
+
+This driver is designed for the VIA 86c100A Rhine-II PCI Fast Ethernet
+controller.
+
+II. Board-specific settings
+
+Boards with this chip are functional only in a bus-master PCI slot.
+
+Many operational settings are loaded from the EEPROM to the Config word at
+offset 0x78. This driver assumes that they are correct.
+If this driver is compiled to use PCI memory space operations the EEPROM
+must be configured to enable memory ops.
+
+III. Driver operation
+
+IIIa. Ring buffers
+
+This driver uses two statically allocated fixed-size descriptor lists
+formed into rings by a branch from the final descriptor to the beginning of
+the list. The ring sizes are set at compile time by RX/TX_RING_SIZE.
+
+IIIb/c. Transmit/Receive Structure
+
+This driver attempts to use a zero-copy receive and transmit scheme.
+
+Alas, all data buffers are required to start on a 32 bit boundary, so
+the driver must often copy transmit packets into bounce buffers.
+
+The driver allocates full frame size skbuffs for the Rx ring buffers at
+open() time and passes the skb->data field to the chip as receive data
+buffers. When an incoming frame is less than RX_COPYBREAK bytes long,
+a fresh skbuff is allocated and the frame is copied to the new skbuff.
+When the incoming frame is larger, the skbuff is passed directly up the
+protocol stack. Buffers consumed this way are replaced by newly allocated
+skbuffs in the last phase of netdev_rx().
+
+The RX_COPYBREAK value is chosen to trade-off the memory wasted by
+using a full-sized skbuff for small frames vs. the copying costs of larger
+frames. New boards are typically used in generously configured machines
+and the underfilled buffers have negligible impact compared to the benefit of
+a single allocation size, so the default value of zero results in never
+copying packets. When copying is done, the cost is usually mitigated by using
+a combined copy/checksum routine. Copying also preloads the cache, which is
+most useful with small frames.
+
+Since the VIA chips are only able to transfer data to buffers on 32 bit
+boundaries, the IP header at offset 14 in an ethernet frame isn't
+longword aligned for further processing. Copying these unaligned buffers
+has the beneficial effect of 16-byte aligning the IP header.
+
+IIId. Synchronization
+
+The driver runs as two independent, single-threaded flows of control. One
+is the send-packet routine, which enforces single-threaded use by the
+dev->tbusy flag. The other thread is the interrupt handler, which is single
+threaded by the hardware and interrupt handling software.
+
+The send packet thread has partial control over the Tx ring and 'dev->tbusy'
+flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next
+queue slot is empty, it clears the tbusy flag when finished otherwise it sets
+the 'lp->tx_full' flag.
+
+The interrupt handler has exclusive control over the Rx ring and records stats
+from the Tx ring. After reaping the stats, it marks the Tx queue entry as
+empty by incrementing the dirty_tx mark. Iff the 'lp->tx_full' flag is set, it
+clears both the tx_full and tbusy flags.
+
+IV. Notes
+
+IVb. References
+
+Preliminary VT86C100A manual from http://www.via.com.tw/
+http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html
+http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+
+IVc. Errata
+
+The VT86C100A manual is not reliable information.
+The chip does not handle unaligned transmit or receive buffers, resulting
+in significant performance degradation for bounce buffer copies on transmit
+and unaligned IP headers on receive.
+The chip does not pad to minimum transmit length.
+
+*/
+
+/* The rest of these values should never change. */
+#define NUM_TX_DESC 2 /* Number of Tx descriptor registers. */
+
+static struct rhine_private
+{
+ char devname[8]; /* Used only for kernel debugging. */
+ const char *product_name;
+ struct rhine_rx_desc *rx_ring;
+ struct rhine_tx_desc *tx_ring;
+ char *rx_buffs[RX_RING_SIZE];
+ char *tx_buffs[TX_RING_SIZE];
+
+ /* temporary Rx buffers. */
+
+ int chip_id;
+ int chip_revision;
+ unsigned short ioaddr;
+ unsigned int cur_rx, cur_tx; /* The next free and used entries */
+ unsigned int dirty_rx, dirty_tx;
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ struct sk_buff *tx_skbuff[TX_RING_SIZE];
+ unsigned char mc_filter[8]; /* Current multicast filter. */
+ char phys[4]; /* MII device addresses. */
+ unsigned int tx_full:1; /* The Tx queue is full. */
+ unsigned int full_duplex:1; /* Full-duplex operation requested. */
+ unsigned int default_port:4; /* Last dev->if_port value. */
+ unsigned int media2:4; /* Secondary monitored media port. */
+ unsigned int medialock:1; /* Don't sense media type. */
+ unsigned int mediasense:1; /* Media sensing in progress. */
+}
+rhine;
+
+static void rhine_probe1 (struct nic *nic, struct pci_device *pci, int ioaddr,
+ int chip_id, int options);
+static int QueryAuto (int);
+static int ReadMII (int byMIIIndex, int);
+static void WriteMII (char, char, char, int);
+static void MIIDelay (void);
+static void rhine_init_ring (struct nic *dev);
+static void rhine_disable (struct nic *nic);
+static void rhine_reset (struct nic *nic);
+static int rhine_poll (struct nic *nic, int retreive);
+static void rhine_transmit (struct nic *nic, const char *d, unsigned int t,
+ unsigned int s, const char *p);
+static void reload_eeprom(int ioaddr);
+
+
+static void reload_eeprom(int ioaddr)
+{
+ int i;
+ outb(0x20, byEECSR);
+ /* Typically 2 cycles to reload. */
+ for (i = 0; i < 150; i++)
+ if (! (inb(byEECSR) & 0x20))
+ break;
+}
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void
+rhine_init_ring (struct nic *nic)
+{
+ struct rhine_private *tp = (struct rhine_private *) nic->priv_data;
+ int i;
+
+ tp->tx_full = 0;
+ tp->cur_rx = tp->cur_tx = 0;
+ tp->dirty_rx = tp->dirty_tx = 0;
+
+ for (i = 0; i < RX_RING_SIZE; i++)
+ {
+
+ tp->rx_ring[i].rx_status.bits.own_bit = 1;
+ tp->rx_ring[i].rx_ctrl.bits.rx_buf_size = 1536;
+
+ tp->rx_ring[i].buf_addr_1 = virt_to_bus (tp->rx_buffs[i]);
+ tp->rx_ring[i].buf_addr_2 = virt_to_bus (&tp->rx_ring[i + 1]);
+ /* printf("[%d]buf1=%hX,buf2=%hX",i,tp->rx_ring[i].buf_addr_1,tp->rx_ring[i].buf_addr_2); */
+ }
+ /* Mark the last entry as wrapping the ring. */
+ /* tp->rx_ring[i-1].rx_ctrl.bits.rx_buf_size =1518; */
+ tp->rx_ring[i - 1].buf_addr_2 = virt_to_bus (&tp->rx_ring[0]);
+ /*printf("[%d]buf1=%hX,buf2=%hX",i-1,tp->rx_ring[i-1].buf_addr_1,tp->rx_ring[i-1].buf_addr_2); */
+
+ /* The Tx buffer descriptor is filled in as needed, but we
+ do need to clear the ownership bit. */
+
+ for (i = 0; i < TX_RING_SIZE; i++)
+ {
+
+ tp->tx_ring[i].tx_status.lw = 0;
+ tp->tx_ring[i].tx_ctrl.lw = 0x00e08000;
+ tp->tx_ring[i].buf_addr_1 = virt_to_bus (tp->tx_buffs[i]);
+ tp->tx_ring[i].buf_addr_2 = virt_to_bus (&tp->tx_ring[i + 1]);
+ /* printf("[%d]buf1=%hX,buf2=%hX",i,tp->tx_ring[i].buf_addr_1,tp->tx_ring[i].buf_addr_2); */
+ }
+
+ tp->tx_ring[i - 1].buf_addr_2 = virt_to_bus (&tp->tx_ring[0]);
+ /* printf("[%d]buf1=%hX,buf2=%hX",i,tp->tx_ring[i-1].buf_addr_1,tp->tx_ring[i-1].buf_addr_2); */
+}
+
+int
+QueryAuto (int ioaddr)
+{
+ int byMIIIndex;
+ int MIIReturn;
+
+ int advertising,mii_reg5;
+ int negociated;
+
+ byMIIIndex = 0x04;
+ MIIReturn = ReadMII (byMIIIndex, ioaddr);
+ advertising=MIIReturn;
+
+ byMIIIndex = 0x05;
+ MIIReturn = ReadMII (byMIIIndex, ioaddr);
+ mii_reg5=MIIReturn;
+
+ negociated=mii_reg5 & advertising;
+
+ if ( (negociated & 0x100) || (negociated & 0x1C0) == 0x40 )
+ return 1;
+ else
+ return 0;
+
+}
+
+int
+ReadMII (int byMIIIndex, int ioaddr)
+{
+ int ReturnMII;
+ char byMIIAdrbak;
+ char byMIICRbak;
+ char byMIItemp;
+ unsigned long ct;
+
+ byMIIAdrbak = inb (byMIIAD);
+ byMIICRbak = inb (byMIICR);
+ outb (byMIICRbak & 0x7f, byMIICR);
+ MIIDelay ();
+
+ outb (byMIIIndex, byMIIAD);
+ MIIDelay ();
+
+ outb (inb (byMIICR) | 0x40, byMIICR);
+
+ byMIItemp = inb (byMIICR);
+ byMIItemp = byMIItemp & 0x40;
+
+ ct = currticks();
+ while (byMIItemp != 0 && ct + 2*1000 < currticks())
+ {
+ byMIItemp = inb (byMIICR);
+ byMIItemp = byMIItemp & 0x40;
+ }
+ MIIDelay ();
+
+ ReturnMII = inw (wMIIDATA);
+
+ outb (byMIIAdrbak, byMIIAD);
+ outb (byMIICRbak, byMIICR);
+ MIIDelay ();
+
+ return (ReturnMII);
+
+}
+
+void
+WriteMII (char byMIISetByte, char byMIISetBit, char byMIIOP, int ioaddr)
+{
+ int ReadMIItmp;
+ int MIIMask;
+ char byMIIAdrbak;
+ char byMIICRbak;
+ char byMIItemp;
+ unsigned long ct;
+
+
+ byMIIAdrbak = inb (byMIIAD);
+
+ byMIICRbak = inb (byMIICR);
+ outb (byMIICRbak & 0x7f, byMIICR);
+ MIIDelay ();
+ outb (byMIISetByte, byMIIAD);
+ MIIDelay ();
+
+ outb (inb (byMIICR) | 0x40, byMIICR);
+
+ byMIItemp = inb (byMIICR);
+ byMIItemp = byMIItemp & 0x40;
+
+ ct = currticks();
+ while (byMIItemp != 0 && ct + 2*1000 < currticks())
+ {
+ byMIItemp = inb (byMIICR);
+ byMIItemp = byMIItemp & 0x40;
+ }
+ MIIDelay ();
+
+ ReadMIItmp = inw (wMIIDATA);
+ MIIMask = 0x0001;
+ MIIMask = MIIMask << byMIISetBit;
+
+
+ if (byMIIOP == 0)
+ {
+ MIIMask = ~MIIMask;
+ ReadMIItmp = ReadMIItmp & MIIMask;
+ }
+ else
+ {
+ ReadMIItmp = ReadMIItmp | MIIMask;
+
+ }
+ outw (ReadMIItmp, wMIIDATA);
+ MIIDelay ();
+
+ outb (inb (byMIICR) | 0x20, byMIICR);
+ byMIItemp = inb (byMIICR);
+ byMIItemp = byMIItemp & 0x20;
+
+ ct = currticks();
+ while (byMIItemp != 0 && ct + 2*1000 < currticks())
+ {
+ byMIItemp = inb (byMIICR);
+ byMIItemp = byMIItemp & 0x20;
+ }
+ MIIDelay ();
+
+ outb (byMIIAdrbak & 0x7f, byMIIAD);
+ outb (byMIICRbak, byMIICR);
+ MIIDelay ();
+
+}
+
+void
+MIIDelay (void)
+{
+ int i;
+ for (i = 0; i < 0x7fff; i++)
+ {
+ ( void ) inb (0x61);
+ ( void ) inb (0x61);
+ ( void ) inb (0x61);
+ ( void ) inb (0x61);
+ }
+}
+
+/* Offsets to the device registers. */
+enum register_offsets {
+ StationAddr=0x00, RxConfig=0x06, TxConfig=0x07, ChipCmd=0x08,
+ IntrStatus=0x0C, IntrEnable=0x0E,
+ MulticastFilter0=0x10, MulticastFilter1=0x14,
+ RxRingPtr=0x18, TxRingPtr=0x1C, GFIFOTest=0x54,
+ MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIBusConfig=0x6E,
+ MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72, MACRegEEcsr=0x74,
+ ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B,
+ RxMissed=0x7C, RxCRCErrs=0x7E, MiscCmd=0x81,
+ StickyHW=0x83, IntrStatus2=0x84, WOLcrClr=0xA4, WOLcgClr=0xA7,
+ PwrcsrClr=0xAC,
+};
+
+/* Bits in the interrupt status/mask registers. */
+enum intr_status_bits {
+ IntrRxDone=0x0001, IntrRxErr=0x0004, IntrRxEmpty=0x0020,
+ IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0210,
+ IntrPCIErr=0x0040,
+ IntrStatsMax=0x0080, IntrRxEarly=0x0100,
+ IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000,
+ IntrTxAborted=0x2000, IntrLinkChange=0x4000,
+ IntrRxWakeUp=0x8000,
+ IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260,
+ IntrTxDescRace=0x080000, /* mapped from IntrStatus2 */
+ IntrTxErrSummary=0x082218,
+};
+#define DEFAULT_INTR (IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow | \
+ IntrRxDropped | IntrRxNoBuf)
+
+/***************************************************************************
+ IRQ - PXE IRQ Handler
+***************************************************************************/
+void rhine_irq ( struct nic *nic, irq_action_t action ) {
+ struct rhine_private *tp = (struct rhine_private *) nic->priv_data;
+ /* Enable interrupts by setting the interrupt mask. */
+ unsigned int intr_status;
+
+ switch ( action ) {
+ case DISABLE :
+ case ENABLE :
+ intr_status = inw(nic->ioaddr + IntrStatus);
+ /* On Rhine-II, Bit 3 indicates Tx descriptor write-back race. */
+
+ /* added comment by guard */
+ /* For supporting VT6107, please use revision id to recognize different chips in driver */
+ // if (tp->chip_id == 0x3065)
+ if( tp->chip_revision < 0x80 && tp->chip_revision >=0x40 )
+ intr_status |= inb(nic->ioaddr + IntrStatus2) << 16;
+ intr_status = (intr_status & ~DEFAULT_INTR);
+ if ( action == ENABLE )
+ intr_status = intr_status | DEFAULT_INTR;
+ outw(intr_status, nic->ioaddr + IntrEnable);
+ break;
+ case FORCE :
+ outw(0x0010, nic->ioaddr + 0x84);
+ break;
+ }
+}
+
+static struct nic_operations rhine_operations;
+
+static int
+rhine_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ struct rhine_private *tp = (struct rhine_private *) nic->priv_data;
+
+ if (!pci->ioaddr)
+ return 0;
+
+ rhine_probe1 (nic, pci, pci->ioaddr, pci->device, -1);
+
+ adjust_pci_device ( pci );
+
+ rhine_reset (nic);
+
+ nic->nic_op = &rhine_operations;
+
+ nic->irqno = pci->irq;
+ nic->ioaddr = tp->ioaddr;
+
+ return 1;
+}
+
+static void set_rx_mode(struct nic *nic __unused) {
+ struct rhine_private *tp = (struct rhine_private *) nic->priv_data;
+ unsigned char rx_mode;
+ int ioaddr = tp->ioaddr;
+
+ /* ! IFF_PROMISC */
+ outl(0xffffffff, byMAR0);
+ outl(0xffffffff, byMAR4);
+ rx_mode = 0x0C;
+
+ outb(0x60 /* thresh */ | rx_mode, byRCR );
+}
+
+static void
+rhine_probe1 (struct nic *nic, struct pci_device *pci, int ioaddr, int chip_id, int options)
+{
+ struct rhine_private *tp;
+ static int did_version = 0; /* Already printed version info. */
+ unsigned int i, ww;
+ unsigned int timeout;
+ int FDXFlag;
+ int byMIIvalue, LineSpeed, MIICRbak;
+ uint8_t revision_id;
+ unsigned char mode3_reg;
+
+ if (rhine_debug > 0 && did_version++ == 0)
+ printf ("%s",version);
+
+ // get revision id.
+ pci_read_config_byte(pci, PCI_REVISION, &revision_id);
+
+ /* D-Link provided reset code (with comment additions) */
+ if (revision_id >= 0x40) {
+ unsigned char byOrgValue;
+
+ if(rhine_debug > 0)
+ printf("Enabling Sticky Bit Workaround for Chip_id: 0x%hX\n"
+ , chip_id);
+ /* clear sticky bit before reset & read ethernet address */
+ byOrgValue = inb(bySTICKHW);
+ byOrgValue = byOrgValue & 0xFC;
+ outb(byOrgValue, bySTICKHW);
+
+ /* (bits written are cleared?) */
+ /* disable force PME-enable */
+ outb(0x80, byWOLcgClr);
+ /* disable power-event config bit */
+ outb(0xFF, byWOLcrClr);
+ /* clear power status (undocumented in vt6102 docs?) */
+ outb(0xFF, byPwrcsrClr);
+
+ }
+
+ /* Reset the chip to erase previous misconfiguration. */
+ outw(CR_SFRST, byCR0);
+ // if vt3043 delay after reset
+ if (revision_id <0x40) {
+ udelay(10000);
+ }
+ // polling till software reset complete
+ // W_MAX_TIMEOUT is the timeout period
+ for(ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+ if ((inw(byCR0) & CR_SFRST) == 0)
+ break;
+ }
+
+ // issue AUTOLoad in EECSR to reload eeprom
+ outb(0x20, byEECSR );
+
+ // if vt3065 delay after reset
+ if (revision_id >=0x40) {
+ // delay 8ms to let MAC stable
+ mdelay(8);
+ /*
+ * for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA
+ * turned on. it makes MAC receive magic packet
+ * automatically. So, we turn it off. (D-Link)
+ */
+ outb(inb(byCFGA) & 0xFE, byCFGA);
+ }
+
+ /* turn on bit2 in PCI configuration register 0x53 , only for 3065*/
+ if (revision_id >= 0x40) {
+ pci_read_config_byte(pci, PCI_REG_MODE3, &mode3_reg);
+ pci_write_config_byte(pci, PCI_REG_MODE3, mode3_reg|MODE3_MIION);
+ }
+
+
+ /* back off algorithm ,disable the right-most 4-bit off CFGD*/
+ outb(inb(byCFGD) & (~(CFGD_RANDOM | CFGD_CFDX | CFGD_CEREN | CFGD_CETEN)), byCFGD);
+
+ /* reload eeprom */
+ reload_eeprom(ioaddr);
+
+ /* Perhaps this should be read from the EEPROM? */
+ for (i = 0; i < ETH_ALEN; i++)
+ nic->node_addr[i] = inb (byPAR0 + i);
+
+ DBG ( "IO address %#hX Ethernet Address: %s\n", ioaddr, eth_ntoa ( nic->node_addr ) );
+
+ /* restart MII auto-negotiation */
+ WriteMII (0, 9, 1, ioaddr);
+ printf ("Analyzing Media type,this may take several seconds... ");
+ for (i = 0; i < 5; i++)
+ {
+ /* need to wait 1 millisecond - we will round it up to 50-100ms */
+ timeout = currticks() + 2;
+ for (timeout = currticks() + 2; currticks() < timeout;)
+ /* nothing */;
+ if (ReadMII (1, ioaddr) & 0x0020)
+ break;
+ }
+ printf ("OK.\n");
+
+#if 0
+ /* JJM : for Debug */
+ printf("MII : Address %hhX ",inb(ioaddr+0x6c));
+ {
+ unsigned char st1,st2,adv1,adv2,l1,l2;
+
+ st1=ReadMII(1,ioaddr)>>8;
+ st2=ReadMII(1,ioaddr)&0xFF;
+ adv1=ReadMII(4,ioaddr)>>8;
+ adv2=ReadMII(4,ioaddr)&0xFF;
+ l1=ReadMII(5,ioaddr)>>8;
+ l2=ReadMII(5,ioaddr)&0xFF;
+ printf(" status 0x%hhX%hhX, advertising 0x%hhX%hhX, link 0x%hhX%hhX\n", st1,st2,adv1,adv2,l1,l2);
+ }
+#endif
+
+
+ /* query MII to know LineSpeed,duplex mode */
+ byMIIvalue = inb (ioaddr + 0x6d);
+ LineSpeed = byMIIvalue & MIISR_SPEED;
+ if (LineSpeed != 0) //JJM
+ {
+ printf ("Linespeed=10Mbs");
+ }
+ else
+ {
+ printf ("Linespeed=100Mbs");
+ }
+
+ FDXFlag = QueryAuto (ioaddr);
+ if (FDXFlag == 1)
+ {
+ printf (" Fullduplex\n");
+ outw (CR_FDX, byCR0);
+ }
+ else
+ {
+ printf (" Halfduplex\n");
+ }
+
+
+ /* set MII 10 FULL ON, only apply in vt3043 */
+ if(chip_id == 0x3043)
+ WriteMII (0x17, 1, 1, ioaddr);
+
+ /* turn on MII link change */
+ MIICRbak = inb (byMIICR);
+ outb (MIICRbak & 0x7F, byMIICR);
+ MIIDelay ();
+ outb (0x41, byMIIAD);
+ MIIDelay ();
+
+ /* while((inb(byMIIAD)&0x20)==0) ; */
+ outb (MIICRbak | 0x80, byMIICR);
+
+ nic->priv_data = &rhine;
+ tp = &rhine;
+ tp->chip_id = chip_id;
+ tp->ioaddr = ioaddr;
+ tp->phys[0] = -1;
+ tp->chip_revision = revision_id;
+
+ /* The lower four bits are the media type. */
+ if (options > 0)
+ {
+ tp->full_duplex = (options & 16) ? 1 : 0;
+ tp->default_port = options & 15;
+ if (tp->default_port)
+ tp->medialock = 1;
+ }
+ return;
+}
+
+static void
+rhine_disable ( struct nic *nic ) {
+
+ struct rhine_private *tp = (struct rhine_private *) nic->priv_data;
+ int ioaddr = tp->ioaddr;
+
+ rhine_reset(nic);
+
+ printf ("rhine disable\n");
+ /* Switch to loopback mode to avoid hardware races. */
+ outb(0x60 | 0x01, byTCR);
+ /* Stop the chip's Tx and Rx processes. */
+ outw(CR_STOP, byCR0);
+}
+
+/**************************************************************************
+ETH_RESET - Reset adapter
+***************************************************************************/
+static void
+rhine_reset (struct nic *nic)
+{
+ struct rhine_private *tp = (struct rhine_private *) nic->priv_data;
+ int ioaddr = tp->ioaddr;
+ int i, j;
+ int FDXFlag, CRbak;
+ void *rx_ring_tmp;
+ void *tx_ring_tmp;
+ void *rx_bufs_tmp;
+ void *tx_bufs_tmp;
+ unsigned long rx_ring_tmp1;
+ unsigned long tx_ring_tmp1;
+ unsigned long rx_bufs_tmp1;
+ unsigned long tx_bufs_tmp1;
+
+ /* printf ("rhine_reset\n"); */
+ /* Soft reset the chip. */
+ /*outb(CmdReset, ioaddr + ChipCmd); */
+
+ tx_bufs_tmp = rhine_buffers.txbuf;
+ tx_ring_tmp = rhine_buffers.txdesc;
+ rx_bufs_tmp = rhine_buffers.rxbuf;
+ rx_ring_tmp = rhine_buffers.rxdesc;
+
+ /* tune RD TD 32 byte alignment */
+ rx_ring_tmp1 = virt_to_bus ( rx_ring_tmp );
+ j = (rx_ring_tmp1 + 32) & (~0x1f);
+ /* printf ("txring[%d]", j); */
+ tp->rx_ring = (struct rhine_rx_desc *) bus_to_virt (j);
+
+ tx_ring_tmp1 = virt_to_bus ( tx_ring_tmp );
+ j = (tx_ring_tmp1 + 32) & (~0x1f);
+ tp->tx_ring = (struct rhine_tx_desc *) bus_to_virt (j);
+ /* printf ("rxring[%X]", j); */
+
+
+ tx_bufs_tmp1 = virt_to_bus ( tx_bufs_tmp );
+ j = (int) (tx_bufs_tmp1 + 32) & (~0x1f);
+ tx_bufs_tmp = bus_to_virt (j);
+ /* printf ("txb[%X]", j); */
+
+ rx_bufs_tmp1 = virt_to_bus ( rx_bufs_tmp );
+ j = (int) (rx_bufs_tmp1 + 32) & (~0x1f);
+ rx_bufs_tmp = bus_to_virt (j);
+ /* printf ("rxb[%X][%X]", rx_bufs_tmp1, j); */
+
+ for (i = 0; i < RX_RING_SIZE; i++)
+ {
+ tp->rx_buffs[i] = (char *) rx_bufs_tmp;
+ /* printf("r[%X]",tp->rx_buffs[i]); */
+ rx_bufs_tmp += 1536;
+ }
+
+ for (i = 0; i < TX_RING_SIZE; i++)
+ {
+ tp->tx_buffs[i] = (char *) tx_bufs_tmp;
+ /* printf("t[%X]",tp->tx_buffs[i]); */
+ tx_bufs_tmp += 1536;
+ }
+
+ /* software reset */
+ outb (CR1_SFRST, byCR1);
+ MIIDelay ();
+
+ /* printf ("init ring"); */
+ rhine_init_ring (nic);
+ /*write TD RD Descriptor to MAC */
+ outl (virt_to_bus (tp->rx_ring), dwCurrentRxDescAddr);
+ outl (virt_to_bus (tp->tx_ring), dwCurrentTxDescAddr);
+
+ /* Setup Multicast */
+ set_rx_mode(nic);
+
+ /* set TCR RCR threshold to store and forward*/
+ outb (0x3e, byBCR0);
+ outb (0x38, byBCR1);
+ outb (0x2c, byRCR);
+ outb (0x60, byTCR);
+ /* Set Fulldupex */
+ FDXFlag = QueryAuto (ioaddr);
+ if (FDXFlag == 1)
+ {
+ outb (CFGD_CFDX, byCFGD);
+ outw (CR_FDX, byCR0);
+ }
+
+ /* KICK NIC to WORK */
+ CRbak = inw (byCR0);
+ CRbak = CRbak & 0xFFFB; /* not CR_STOP */
+ outw ((CRbak | CR_STRT | CR_TXON | CR_RXON | CR_DPOLL), byCR0);
+
+ /* disable all known interrupt */
+ outw (0, byIMR0);
+}
+/* Beware of PCI posted writes */
+#define IOSYNC do { inb(nic->ioaddr + StationAddr); } while (0)
+
+static int
+rhine_poll (struct nic *nic, int retreive)
+{
+ struct rhine_private *tp = (struct rhine_private *) nic->priv_data;
+ int rxstatus, good = 0;;
+
+ if (tp->rx_ring[tp->cur_rx].rx_status.bits.own_bit == 0)
+ {
+ unsigned int intr_status;
+ /* There is a packet ready */
+ if(!retreive)
+ return 1;
+
+ intr_status = inw(nic->ioaddr + IntrStatus);
+ /* On Rhine-II, Bit 3 indicates Tx descriptor write-back race. */
+#if 0
+ if (tp->chip_id == 0x3065)
+ intr_status |= inb(nic->ioaddr + IntrStatus2) << 16;
+#endif
+ /* Acknowledge all of the current interrupt sources ASAP. */
+ if (intr_status & IntrTxDescRace)
+ outb(0x08, nic->ioaddr + IntrStatus2);
+ outw(intr_status & 0xffff, nic->ioaddr + IntrStatus);
+ IOSYNC;
+
+ rxstatus = tp->rx_ring[tp->cur_rx].rx_status.lw;
+ if ((rxstatus & 0x0300) != 0x0300)
+ {
+ printf("rhine_poll: bad status\n");
+ }
+ else if (rxstatus & (RSR_ABNORMAL))
+ {
+ printf ("rxerr[%X]\n", rxstatus);
+ }
+ else
+ good = 1;
+
+ if (good)
+ {
+ nic->packetlen = tp->rx_ring[tp->cur_rx].rx_status.bits.frame_length;
+ memcpy (nic->packet, tp->rx_buffs[tp->cur_rx], nic->packetlen);
+ /* printf ("Packet RXed\n"); */
+ }
+ tp->rx_ring[tp->cur_rx].rx_status.bits.own_bit = 1;
+ tp->cur_rx++;
+ tp->cur_rx = tp->cur_rx % RX_RING_SIZE;
+ }
+ /* Acknowledge all of the current interrupt sources ASAP. */
+ outw(DEFAULT_INTR & ~IntrRxDone, nic->ioaddr + IntrStatus);
+
+ IOSYNC;
+
+ return good;
+}
+
+static void
+rhine_transmit (struct nic *nic,
+ const char *d, unsigned int t, unsigned int s, const char *p)
+{
+ struct rhine_private *tp = (struct rhine_private *) nic->priv_data;
+ int ioaddr = tp->ioaddr;
+ int entry;
+ unsigned char CR1bak;
+ unsigned char CR0bak;
+ unsigned int nstype;
+ unsigned long ct;
+
+
+ /*printf ("rhine_transmit\n"); */
+ /* setup ethernet header */
+
+
+ /* Calculate the next Tx descriptor entry. */
+ entry = tp->cur_tx % TX_RING_SIZE;
+
+ memcpy (tp->tx_buffs[entry], d, ETH_ALEN); /* dst */
+ memcpy (tp->tx_buffs[entry] + ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
+
+ nstype=htons(t);
+ memcpy(tp->tx_buffs[entry] + 2 * ETH_ALEN, (char*)&nstype, 2);
+
+ memcpy (tp->tx_buffs[entry] + ETH_HLEN, p, s);
+ s += ETH_HLEN;
+ while (s < ETH_ZLEN)
+ *((char *) tp->tx_buffs[entry] + (s++)) = 0;
+
+ tp->tx_ring[entry].tx_ctrl.bits.tx_buf_size = s;
+
+ tp->tx_ring[entry].tx_status.bits.own_bit = 1;
+
+
+ CR1bak = inb (byCR1);
+
+ CR1bak = CR1bak | CR1_TDMD1;
+ /*printf("tdsw=[%X]",tp->tx_ring[entry].tx_status.lw); */
+ /*printf("tdcw=[%X]",tp->tx_ring[entry].tx_ctrl.lw); */
+ /*printf("tdbuf1=[%X]",tp->tx_ring[entry].buf_addr_1); */
+ /*printf("tdbuf2=[%X]",tp->tx_ring[entry].buf_addr_2); */
+ /*printf("td1=[%X]",inl(dwCurrentTDSE0)); */
+ /*printf("td2=[%X]",inl(dwCurrentTDSE1)); */
+ /*printf("td3=[%X]",inl(dwCurrentTDSE2)); */
+ /*printf("td4=[%X]",inl(dwCurrentTDSE3)); */
+
+ outb (CR1bak, byCR1);
+ do
+ {
+ ct = currticks();
+ /* Wait until transmit is finished or timeout*/
+ while((tp->tx_ring[entry].tx_status.bits.own_bit !=0) &&
+ ct + 10*1000 < currticks())
+ ;
+
+ if(tp->tx_ring[entry].tx_status.bits.terr == 0)
+ break;
+
+ if(tp->tx_ring[entry].tx_status.bits.abt == 1)
+ {
+ // turn on TX
+ CR0bak = inb(byCR0);
+ CR0bak = CR0bak|CR_TXON;
+ outb(CR0bak,byCR0);
+ }
+ }while(0);
+ tp->cur_tx++;
+
+ /*outw(IMRShadow,byIMR0); */
+ /*dev_kfree_skb(tp->tx_skbuff[entry], FREE_WRITE); */
+ /*tp->tx_skbuff[entry] = 0; */
+}
+
+static struct nic_operations rhine_operations = {
+ .connect = dummy_connect,
+ .poll = rhine_poll,
+ .transmit = rhine_transmit,
+ .irq = rhine_irq,
+
+};
+
+static struct pci_device_id rhine_nics[] = {
+PCI_ROM(0x1106, 0x3065, "dlink-530tx", "VIA 6102", 0),
+PCI_ROM(0x1106, 0x3106, "via-rhine-6105", "VIA 6105", 0),
+PCI_ROM(0x1106, 0x3043, "dlink-530tx-old", "VIA 3043", 0), /* Rhine-I 86c100a */
+PCI_ROM(0x1106, 0x3053, "via6105m", "VIA 6105M", 0),
+PCI_ROM(0x1106, 0x6100, "via-rhine-old", "VIA 86C100A", 0), /* Rhine-II */
+};
+
+PCI_DRIVER ( rhine_driver, rhine_nics, PCI_NO_CLASS );
+
+DRIVER ( "VIA 86C100", nic_driver, pci_driver, rhine_driver,
+ rhine_probe, rhine_disable );
+
+/* EOF via-rhine.c */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/via-velocity.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/via-velocity.c
new file mode 100644
index 00000000..0bcca926
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/via-velocity.c
@@ -0,0 +1,1935 @@
+/**************************************************************************
+* via-velocity.c: Etherboot device driver for the VIA 6120 Gigabit
+* Changes for Etherboot port:
+* Copyright (c) 2006 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* This driver is based on:
+* via-velocity.c: VIA Velocity VT6120, VT6122 Ethernet driver
+* The changes are (c) Copyright 2004, Red Hat Inc.
+* <alan@redhat.com>
+* Additional fixes and clean up: Francois Romieu
+*
+* Original code:
+* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
+* All rights reserved.
+* Author: Chuang Liang-Shing, AJ Jiang
+*
+* Linux Driver Version 2.6.15.4
+*
+* REVISION HISTORY:
+* ================
+*
+* v1.0 03-06-2006 timlegge Initial port of Linux driver
+*
+* Indent Options: indent -kr -i8
+*************************************************************************/
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "etherboot.h"
+#include "nic.h"
+#include <ipxe/pci.h>
+#include <ipxe/ethernet.h>
+
+#include "via-velocity.h"
+
+typedef int pci_power_t;
+
+#define PCI_D0 ((int) 0)
+#define PCI_D1 ((int) 1)
+#define PCI_D2 ((int) 2)
+#define PCI_D3hot ((int) 3)
+#define PCI_D3cold ((int) 4)
+#define PCI_POWER_ERROR ((int) -1)
+
+
+/* Condensed operations for readability. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+//FIXME: Move to pci.c
+int pci_set_power_state(struct pci_device *dev, int state);
+
+/* FIXME: Move BASE to the private structure */
+static u32 BASE;
+
+/* NIC specific static variables go here */
+#define VELOCITY_PARAM(N,D) \
+ static const int N[MAX_UNITS]=OPTION_DEFAULT;
+/* MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UNITS) "i");\
+ MODULE_PARM_DESC(N, D); */
+
+VELOCITY_PARAM(RxDescriptors, "Number of receive descriptors");
+VELOCITY_PARAM(TxDescriptors, "Number of transmit descriptors");
+
+
+#define VLAN_ID_MIN 0
+#define VLAN_ID_MAX 4095
+#define VLAN_ID_DEF 0
+/* VID_setting[] is used for setting the VID of NIC.
+ 0: default VID.
+ 1-4094: other VIDs.
+*/
+VELOCITY_PARAM(VID_setting, "802.1Q VLAN ID");
+
+#define RX_THRESH_MIN 0
+#define RX_THRESH_MAX 3
+#define RX_THRESH_DEF 0
+/* rx_thresh[] is used for controlling the receive fifo threshold.
+ 0: indicate the rxfifo threshold is 128 bytes.
+ 1: indicate the rxfifo threshold is 512 bytes.
+ 2: indicate the rxfifo threshold is 1024 bytes.
+ 3: indicate the rxfifo threshold is store & forward.
+*/
+VELOCITY_PARAM(rx_thresh, "Receive fifo threshold");
+
+#define DMA_LENGTH_MIN 0
+#define DMA_LENGTH_MAX 7
+#define DMA_LENGTH_DEF 0
+
+/* DMA_length[] is used for controlling the DMA length
+ 0: 8 DWORDs
+ 1: 16 DWORDs
+ 2: 32 DWORDs
+ 3: 64 DWORDs
+ 4: 128 DWORDs
+ 5: 256 DWORDs
+ 6: SF(flush till emply)
+ 7: SF(flush till emply)
+*/
+VELOCITY_PARAM(DMA_length, "DMA length");
+
+#define TAGGING_DEF 0
+/* enable_tagging[] is used for enabling 802.1Q VID tagging.
+ 0: disable VID seeting(default).
+ 1: enable VID setting.
+*/
+VELOCITY_PARAM(enable_tagging, "Enable 802.1Q tagging");
+
+#define IP_ALIG_DEF 0
+/* IP_byte_align[] is used for IP header DWORD byte aligned
+ 0: indicate the IP header won't be DWORD byte aligned.(Default) .
+ 1: indicate the IP header will be DWORD byte aligned.
+ In some enviroment, the IP header should be DWORD byte aligned,
+ or the packet will be droped when we receive it. (eg: IPVS)
+*/
+VELOCITY_PARAM(IP_byte_align, "Enable IP header dword aligned");
+
+#define TX_CSUM_DEF 1
+/* txcsum_offload[] is used for setting the checksum offload ability of NIC.
+ (We only support RX checksum offload now)
+ 0: disable csum_offload[checksum offload
+ 1: enable checksum offload. (Default)
+*/
+VELOCITY_PARAM(txcsum_offload, "Enable transmit packet checksum offload");
+
+#define FLOW_CNTL_DEF 1
+#define FLOW_CNTL_MIN 1
+#define FLOW_CNTL_MAX 5
+
+/* flow_control[] is used for setting the flow control ability of NIC.
+ 1: hardware deafult - AUTO (default). Use Hardware default value in ANAR.
+ 2: enable TX flow control.
+ 3: enable RX flow control.
+ 4: enable RX/TX flow control.
+ 5: disable
+*/
+VELOCITY_PARAM(flow_control, "Enable flow control ability");
+
+#define MED_LNK_DEF 0
+#define MED_LNK_MIN 0
+#define MED_LNK_MAX 4
+/* speed_duplex[] is used for setting the speed and duplex mode of NIC.
+ 0: indicate autonegotiation for both speed and duplex mode
+ 1: indicate 100Mbps half duplex mode
+ 2: indicate 100Mbps full duplex mode
+ 3: indicate 10Mbps half duplex mode
+ 4: indicate 10Mbps full duplex mode
+
+ Note:
+ if EEPROM have been set to the force mode, this option is ignored
+ by driver.
+*/
+VELOCITY_PARAM(speed_duplex, "Setting the speed and duplex mode");
+
+#define VAL_PKT_LEN_DEF 0
+/* ValPktLen[] is used for setting the checksum offload ability of NIC.
+ 0: Receive frame with invalid layer 2 length (Default)
+ 1: Drop frame with invalid layer 2 length
+*/
+VELOCITY_PARAM(ValPktLen, "Receiving or Drop invalid 802.3 frame");
+
+#define WOL_OPT_DEF 0
+#define WOL_OPT_MIN 0
+#define WOL_OPT_MAX 7
+/* wol_opts[] is used for controlling wake on lan behavior.
+ 0: Wake up if recevied a magic packet. (Default)
+ 1: Wake up if link status is on/off.
+ 2: Wake up if recevied an arp packet.
+ 4: Wake up if recevied any unicast packet.
+ Those value can be sumed up to support more than one option.
+*/
+VELOCITY_PARAM(wol_opts, "Wake On Lan options");
+
+#define INT_WORKS_DEF 20
+#define INT_WORKS_MIN 10
+#define INT_WORKS_MAX 64
+
+VELOCITY_PARAM(int_works, "Number of packets per interrupt services");
+
+/* The descriptors for this card are required to be aligned on
+64 byte boundaries. As the align attribute does not guarantee alignment
+greater than the alignment of the start address (which for Etherboot
+is 16 bytes of alignment) it requires some extra steps. Add 64 to the
+size of the array and the init_ring adjusts the alignment */
+
+/* Define the TX Descriptor */
+static u8 tx_ring[TX_DESC_DEF * sizeof(struct tx_desc) + 64];
+
+/* Create a static buffer of size PKT_BUF_SZ for each TX Descriptor.
+All descriptors point to a part of this buffer */
+static u8 txb[(TX_DESC_DEF * PKT_BUF_SZ) + 64];
+
+/* Define the RX Descriptor */
+static u8 rx_ring[RX_DESC_DEF * sizeof(struct rx_desc) + 64];
+
+/* Create a static buffer of size PKT_BUF_SZ for each RX Descriptor
+ All descriptors point to a part of this buffer */
+static u8 rxb[(RX_DESC_DEF * PKT_BUF_SZ) + 64];
+
+static void velocity_init_info(struct pci_device *pdev,
+ struct velocity_info *vptr,
+ struct velocity_info_tbl *info);
+static int velocity_get_pci_info(struct velocity_info *,
+ struct pci_device *pdev);
+static int velocity_open(struct nic *nic, struct pci_device *pci);
+
+static int velocity_soft_reset(struct velocity_info *vptr);
+static void velocity_init_cam_filter(struct velocity_info *vptr);
+static void mii_init(struct velocity_info *vptr, u32 mii_status);
+static u32 velocity_get_opt_media_mode(struct velocity_info *vptr);
+static void velocity_print_link_status(struct velocity_info *vptr);
+static void safe_disable_mii_autopoll(struct mac_regs *regs);
+static void enable_flow_control_ability(struct velocity_info *vptr);
+static void enable_mii_autopoll(struct mac_regs *regs);
+static int velocity_mii_read(struct mac_regs *, u8 byIdx, u16 * pdata);
+static int velocity_mii_write(struct mac_regs *, u8 byMiiAddr, u16 data);
+static u32 mii_check_media_mode(struct mac_regs *regs);
+static u32 check_connection_type(struct mac_regs *regs);
+static int velocity_set_media_mode(struct velocity_info *vptr,
+ u32 mii_status);
+
+
+/*
+ * Internal board variants. At the moment we have only one
+ */
+
+static struct velocity_info_tbl chip_info_table[] = {
+ {CHIP_TYPE_VT6110,
+ "VIA Networking Velocity Family Gigabit Ethernet Adapter", 256, 1,
+ 0x00FFFFFFUL},
+ {0, NULL, 0, 0, 0}
+};
+
+/**
+ * velocity_set_int_opt - parser for integer options
+ * @opt: pointer to option value
+ * @val: value the user requested (or -1 for default)
+ * @min: lowest value allowed
+ * @max: highest value allowed
+ * @def: default value
+ * @name: property name
+ * @dev: device name
+ *
+ * Set an integer property in the module options. This function does
+ * all the verification and checking as well as reporting so that
+ * we don't duplicate code for each option.
+ */
+
+static void velocity_set_int_opt(int *opt, int val, int min, int max,
+ int def, char *name, const char *devname)
+{
+ if (val == -1) {
+ printf("%s: set value of parameter %s to %d\n",
+ devname, name, def);
+ *opt = def;
+ } else if (val < min || val > max) {
+ printf
+ ("%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n",
+ devname, name, min, max);
+ *opt = def;
+ } else {
+ printf("%s: set value of parameter %s to %d\n",
+ devname, name, val);
+ *opt = val;
+ }
+}
+
+/**
+ * velocity_set_bool_opt - parser for boolean options
+ * @opt: pointer to option value
+ * @val: value the user requested (or -1 for default)
+ * @def: default value (yes/no)
+ * @flag: numeric value to set for true.
+ * @name: property name
+ * @dev: device name
+ *
+ * Set a boolean property in the module options. This function does
+ * all the verification and checking as well as reporting so that
+ * we don't duplicate code for each option.
+ */
+
+static void velocity_set_bool_opt(u32 * opt, int val, int def, u32 flag,
+ char *name, const char *devname)
+{
+ (*opt) &= (~flag);
+ if (val == -1) {
+ printf("%s: set parameter %s to %s\n",
+ devname, name, def ? "TRUE" : "FALSE");
+ *opt |= (def ? flag : 0);
+ } else if (val < 0 || val > 1) {
+ printf
+ ("%s: the value of parameter %s is invalid, the valid range is (0-1)\n",
+ devname, name);
+ *opt |= (def ? flag : 0);
+ } else {
+ printf("%s: set parameter %s to %s\n",
+ devname, name, val ? "TRUE" : "FALSE");
+ *opt |= (val ? flag : 0);
+ }
+}
+
+/**
+ * velocity_get_options - set options on device
+ * @opts: option structure for the device
+ * @index: index of option to use in module options array
+ * @devname: device name
+ *
+ * Turn the module and command options into a single structure
+ * for the current device
+ */
+
+static void velocity_get_options(struct velocity_opt *opts, int index,
+ const char *devname)
+{
+
+ /* FIXME Do the options need to be configurable */
+ velocity_set_int_opt(&opts->rx_thresh, -1, RX_THRESH_MIN,
+ RX_THRESH_MAX, RX_THRESH_DEF, "rx_thresh",
+ devname);
+ velocity_set_int_opt(&opts->DMA_length, DMA_length[index],
+ DMA_LENGTH_MIN, DMA_LENGTH_MAX,
+ DMA_LENGTH_DEF, "DMA_length", devname);
+ velocity_set_int_opt(&opts->numrx, RxDescriptors[index],
+ RX_DESC_MIN, RX_DESC_MAX, RX_DESC_DEF,
+ "RxDescriptors", devname);
+ velocity_set_int_opt(&opts->numtx, TxDescriptors[index],
+ TX_DESC_MIN, TX_DESC_MAX, TX_DESC_DEF,
+ "TxDescriptors", devname);
+ velocity_set_int_opt(&opts->vid, VID_setting[index], VLAN_ID_MIN,
+ VLAN_ID_MAX, VLAN_ID_DEF, "VID_setting",
+ devname);
+ velocity_set_bool_opt(&opts->flags, enable_tagging[index],
+ TAGGING_DEF, VELOCITY_FLAGS_TAGGING,
+ "enable_tagging", devname);
+ velocity_set_bool_opt(&opts->flags, txcsum_offload[index],
+ TX_CSUM_DEF, VELOCITY_FLAGS_TX_CSUM,
+ "txcsum_offload", devname);
+ velocity_set_int_opt(&opts->flow_cntl, flow_control[index],
+ FLOW_CNTL_MIN, FLOW_CNTL_MAX, FLOW_CNTL_DEF,
+ "flow_control", devname);
+ velocity_set_bool_opt(&opts->flags, IP_byte_align[index],
+ IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN,
+ "IP_byte_align", devname);
+ velocity_set_bool_opt(&opts->flags, ValPktLen[index],
+ VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN,
+ "ValPktLen", devname);
+ velocity_set_int_opt((void *) &opts->spd_dpx, speed_duplex[index],
+ MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF,
+ "Media link mode", devname);
+ velocity_set_int_opt((int *) &opts->wol_opts, wol_opts[index],
+ WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF,
+ "Wake On Lan options", devname);
+ velocity_set_int_opt((int *) &opts->int_works, int_works[index],
+ INT_WORKS_MIN, INT_WORKS_MAX, INT_WORKS_DEF,
+ "Interrupt service works", devname);
+ opts->numrx = (opts->numrx & ~3);
+}
+
+/**
+ * velocity_init_cam_filter - initialise CAM
+ * @vptr: velocity to program
+ *
+ * Initialize the content addressable memory used for filters. Load
+ * appropriately according to the presence of VLAN
+ */
+
+static void velocity_init_cam_filter(struct velocity_info *vptr)
+{
+ struct mac_regs *regs = vptr->mac_regs;
+
+ /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
+ WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);
+ WORD_REG_BITS_ON(MCFG_VIDFR, &regs->MCFG);
+
+ /* Disable all CAMs */
+ memset(vptr->vCAMmask, 0, sizeof(u8) * 8);
+ memset(vptr->mCAMmask, 0, sizeof(u8) * 8);
+ mac_set_cam_mask(regs, vptr->vCAMmask, VELOCITY_VLAN_ID_CAM);
+ mac_set_cam_mask(regs, vptr->mCAMmask, VELOCITY_MULTICAST_CAM);
+
+ /* Enable first VCAM */
+ if (vptr->flags & VELOCITY_FLAGS_TAGGING) {
+ /* If Tagging option is enabled and VLAN ID is not zero, then
+ turn on MCFG_RTGOPT also */
+ if (vptr->options.vid != 0)
+ WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
+
+ mac_set_cam(regs, 0, (u8 *) & (vptr->options.vid),
+ VELOCITY_VLAN_ID_CAM);
+ vptr->vCAMmask[0] |= 1;
+ mac_set_cam_mask(regs, vptr->vCAMmask,
+ VELOCITY_VLAN_ID_CAM);
+ } else {
+ u16 temp = 0;
+ mac_set_cam(regs, 0, (u8 *) & temp, VELOCITY_VLAN_ID_CAM);
+ temp = 1;
+ mac_set_cam_mask(regs, (u8 *) & temp,
+ VELOCITY_VLAN_ID_CAM);
+ }
+}
+
+static inline void velocity_give_many_rx_descs(struct velocity_info *vptr)
+{
+ struct mac_regs *regs = vptr->mac_regs;
+ int avail, dirty, unusable;
+
+ /*
+ * RD number must be equal to 4X per hardware spec
+ * (programming guide rev 1.20, p.13)
+ */
+ if (vptr->rd_filled < 4)
+ return;
+
+ wmb();
+
+ unusable = vptr->rd_filled & 0x0003;
+ dirty = vptr->rd_dirty - unusable;
+ for (avail = vptr->rd_filled & 0xfffc; avail; avail--) {
+ dirty = (dirty > 0) ? dirty - 1 : vptr->options.numrx - 1;
+// printf("return dirty: %d\n", dirty);
+ vptr->rd_ring[dirty].rdesc0.owner = OWNED_BY_NIC;
+ }
+
+ writew(vptr->rd_filled & 0xfffc, &regs->RBRDU);
+ vptr->rd_filled = unusable;
+}
+
+static int velocity_rx_refill(struct velocity_info *vptr)
+{
+ int dirty = vptr->rd_dirty, done = 0, ret = 0;
+
+// printf("rx_refill - rd_curr = %d, dirty = %d\n", vptr->rd_curr, dirty);
+ do {
+ struct rx_desc *rd = vptr->rd_ring + dirty;
+
+ /* Fine for an all zero Rx desc at init time as well */
+ if (rd->rdesc0.owner == OWNED_BY_NIC)
+ break;
+// printf("rx_refill - after owner %d\n", dirty);
+
+ rd->inten = 1;
+ rd->pa_high = 0;
+ rd->rdesc0.len = cpu_to_le32(vptr->rx_buf_sz);;
+
+ done++;
+ dirty = (dirty < vptr->options.numrx - 1) ? dirty + 1 : 0;
+ } while (dirty != vptr->rd_curr);
+
+ if (done) {
+// printf("\nGive Back Desc\n");
+ vptr->rd_dirty = dirty;
+ vptr->rd_filled += done;
+ velocity_give_many_rx_descs(vptr);
+ }
+
+ return ret;
+}
+
+extern void hex_dump(const char *data, const unsigned int len);
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int velocity_poll(struct nic *nic, int retrieve)
+{
+ /* Work out whether or not there's an ethernet packet ready to
+ * read. Return 0 if not.
+ */
+
+ int rd_curr = vptr->rd_curr % RX_DESC_DEF;
+ struct rx_desc *rd = &(vptr->rd_ring[rd_curr]);
+
+ if (rd->rdesc0.owner == OWNED_BY_NIC)
+ return 0;
+ rmb();
+
+ if ( ! retrieve ) return 1;
+
+ /*
+ * Don't drop CE or RL error frame although RXOK is off
+ */
+ if ((rd->rdesc0.RSR & RSR_RXOK)
+ || (!(rd->rdesc0.RSR & RSR_RXOK)
+ && (rd->rdesc0.RSR & (RSR_CE | RSR_RL)))) {
+
+ nic->packetlen = rd->rdesc0.len;
+ // ptr->rxb + (rd_curr * PKT_BUF_SZ)
+ memcpy(nic->packet, bus_to_virt(rd->pa_low),
+ nic->packetlen - 4);
+
+ vptr->rd_curr++;
+ vptr->rd_curr = vptr->rd_curr % RX_DESC_DEF;
+ velocity_rx_refill(vptr);
+ return 1; /* Remove this line once this method is implemented */
+ }
+ return 0;
+}
+
+#define TX_TIMEOUT (1000);
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void velocity_transmit(struct nic *nic, const char *dest, /* Destination */
+ unsigned int type, /* Type */
+ unsigned int size, /* size */
+ const char *packet)
+{ /* Packet */
+ u16 nstype;
+ u32 to;
+ u8 *ptxb;
+ unsigned int pktlen;
+ struct tx_desc *td_ptr;
+
+ int entry = vptr->td_curr % TX_DESC_DEF;
+ td_ptr = &(vptr->td_rings[entry]);
+
+ /* point to the current txb incase multiple tx_rings are used */
+ ptxb = vptr->txb + (entry * PKT_BUF_SZ);
+ memcpy(ptxb, dest, ETH_ALEN); /* Destination */
+ memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN); /* Source */
+ nstype = htons((u16) type); /* Type */
+ memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2); /* Type */
+ memcpy(ptxb + ETH_HLEN, packet, size);
+
+ td_ptr->tdesc1.TCPLS = TCPLS_NORMAL;
+ td_ptr->tdesc1.TCR = TCR0_TIC;
+ td_ptr->td_buf[0].queue = 0;
+
+ size += ETH_HLEN;
+ while (size < ETH_ZLEN) /* pad to min length */
+ ptxb[size++] = '\0';
+
+ if (size < ETH_ZLEN) {
+// printf("Padd that packet\n");
+ pktlen = ETH_ZLEN;
+// memcpy(ptxb, skb->data, skb->len);
+ memset(ptxb + size, 0, ETH_ZLEN - size);
+
+ vptr->td_rings[entry].tdesc0.pktsize = pktlen;
+ vptr->td_rings[entry].td_buf[0].pa_low = virt_to_bus(ptxb);
+ vptr->td_rings[entry].td_buf[0].pa_high &=
+ cpu_to_le32(0xffff0000UL);
+ vptr->td_rings[entry].td_buf[0].bufsize =
+ vptr->td_rings[entry].tdesc0.pktsize;
+ vptr->td_rings[entry].tdesc1.CMDZ = 2;
+ } else {
+// printf("Correct size packet\n");
+ td_ptr->tdesc0.pktsize = size;
+ td_ptr->td_buf[0].pa_low = virt_to_bus(ptxb);
+ td_ptr->td_buf[0].pa_high = 0;
+ td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize;
+// tdinfo->nskb_dma = 1;
+ td_ptr->tdesc1.CMDZ = 2;
+ }
+
+ if (vptr->flags & VELOCITY_FLAGS_TAGGING) {
+ td_ptr->tdesc1.pqinf.VID = (vptr->options.vid & 0xfff);
+ td_ptr->tdesc1.pqinf.priority = 0;
+ td_ptr->tdesc1.pqinf.CFI = 0;
+ td_ptr->tdesc1.TCR |= TCR0_VETAG;
+ }
+
+ vptr->td_curr = (entry + 1);
+
+ {
+
+ int prev = entry - 1;
+
+ if (prev < 0)
+ prev = TX_DESC_DEF - 1;
+ td_ptr->tdesc0.owner |= OWNED_BY_NIC;
+ td_ptr = &(vptr->td_rings[prev]);
+ td_ptr->td_buf[0].queue = 1;
+ mac_tx_queue_wake(vptr->mac_regs, 0);
+
+ }
+
+ to = currticks() + TX_TIMEOUT;
+ while ((td_ptr->tdesc0.owner & OWNED_BY_NIC) && (currticks() < to)); /* wait */
+
+ if (currticks() >= to) {
+ printf("TX Time Out");
+ }
+
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void velocity_disable(struct nic *nic __unused)
+{
+ /* put the card in its initial state */
+ /* This function serves 3 purposes.
+ * This disables DMA and interrupts so we don't receive
+ * unexpected packets or interrupts from the card after
+ * etherboot has finished.
+ * This frees resources so etherboot may use
+ * this driver on another interface
+ * This allows etherboot to reinitialize the interface
+ * if something is something goes wrong.
+ */
+ struct mac_regs *regs = vptr->mac_regs;
+ mac_disable_int(regs);
+ writel(CR0_STOP, &regs->CR0Set);
+ writew(0xFFFF, &regs->TDCSRClr);
+ writeb(0xFF, &regs->RDCSRClr);
+ safe_disable_mii_autopoll(regs);
+ mac_clear_isr(regs);
+
+ /* Power down the chip */
+// pci_set_power_state(vptr->pdev, PCI_D3hot);
+
+ vptr->flags &= (~VELOCITY_FLAGS_OPENED);
+}
+
+/**************************************************************************
+IRQ - handle interrupts
+***************************************************************************/
+static void velocity_irq(struct nic *nic __unused, irq_action_t action)
+{
+ /* This routine is somewhat optional. Etherboot itself
+ * doesn't use interrupts, but they are required under some
+ * circumstances when we're acting as a PXE stack.
+ *
+ * If you don't implement this routine, the only effect will
+ * be that your driver cannot be used via Etherboot's UNDI
+ * API. This won't affect programs that use only the UDP
+ * portion of the PXE API, such as pxelinux.
+ */
+
+ switch (action) {
+ case DISABLE:
+ case ENABLE:
+ /* Set receive interrupt enabled/disabled state */
+ /*
+ outb ( action == ENABLE ? IntrMaskEnabled : IntrMaskDisabled,
+ nic->ioaddr + IntrMaskRegister );
+ */
+ break;
+ case FORCE:
+ /* Force NIC to generate a receive interrupt */
+ /*
+ outb ( ForceInterrupt, nic->ioaddr + IntrForceRegister );
+ */
+ break;
+ }
+}
+
+static struct nic_operations velocity_operations = {
+ .connect = dummy_connect,
+ .poll = velocity_poll,
+ .transmit = velocity_transmit,
+ .irq = velocity_irq,
+};
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+static int velocity_probe( struct nic *nic, struct pci_device *pci)
+{
+ int ret, i;
+ struct mac_regs *regs;
+
+ printf("via-velocity.c: Found %s Vendor=0x%hX Device=0x%hX\n",
+ pci->id->name, pci->vendor, pci->device);
+
+ /* point to private storage */
+ vptr = &vptx;
+ info = chip_info_table;
+
+ velocity_init_info(pci, vptr, info);
+
+//FIXME: pci_enable_device(pci);
+//FIXME: pci_set_power_state(pci, PCI_D0);
+
+ ret = velocity_get_pci_info(vptr, pci);
+ if (ret < 0) {
+ printf("Failed to find PCI device.\n");
+ return 0;
+ }
+
+ regs = ioremap(vptr->memaddr, vptr->io_size);
+ if (regs == NULL) {
+ printf("Unable to remap io\n");
+ return 0;
+ }
+
+ vptr->mac_regs = regs;
+
+ BASE = vptr->ioaddr;
+
+ printf("Chip ID: %hX\n", vptr->chip_id);
+
+ for (i = 0; i < 6; i++)
+ nic->node_addr[i] = readb(&regs->PAR[i]);
+
+ DBG ( "%s: %s at ioaddr %#hX\n", pci->id->name, eth_ntoa ( nic->node_addr ),
+ (unsigned int) BASE );
+
+ velocity_get_options(&vptr->options, 0, pci->id->name);
+
+ /*
+ * Mask out the options cannot be set to the chip
+ */
+ vptr->options.flags &= 0x00FFFFFFUL; //info->flags = 0x00FFFFFFUL;
+
+ /*
+ * Enable the chip specified capbilities
+ */
+
+ vptr->flags =
+ vptr->options.
+ flags | (0x00FFFFFFUL /*info->flags */ & 0xFF000000UL);
+
+ vptr->wol_opts = vptr->options.wol_opts;
+ vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED;
+
+ vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs);
+
+ if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) {
+ printf("features missing\n");
+ }
+
+ /* and leave the chip powered down */
+// FIXME: pci_set_power_state(pci, PCI_D3hot);
+
+ check_connection_type(vptr->mac_regs);
+ velocity_open(nic, pci);
+
+ /* store NIC parameters */
+ nic->nic_op = &velocity_operations;
+ return 1;
+}
+
+//#define IORESOURCE_IO 0x00000100 /* Resource type */
+
+/**
+ * velocity_init_info - init private data
+ * @pdev: PCI device
+ * @vptr: Velocity info
+ * @info: Board type
+ *
+ * Set up the initial velocity_info struct for the device that has been
+ * discovered.
+ */
+
+static void velocity_init_info(struct pci_device *pdev,
+ struct velocity_info *vptr,
+ struct velocity_info_tbl *info)
+{
+ memset(vptr, 0, sizeof(struct velocity_info));
+
+ vptr->pdev = pdev;
+ vptr->chip_id = info->chip_id;
+ vptr->io_size = info->io_size;
+ vptr->num_txq = info->txqueue;
+ vptr->multicast_limit = MCAM_SIZE;
+
+ printf
+ ("chip_id: 0x%hX, io_size: %d, num_txq %d, multicast_limit: %d\n",
+ vptr->chip_id, (unsigned int) vptr->io_size, vptr->num_txq,
+ vptr->multicast_limit);
+ printf("Name: %s\n", info->name);
+
+// spin_lock_init(&vptr->lock);
+// INIT_LIST_HEAD(&vptr->list);
+}
+
+/**
+ * velocity_get_pci_info - retrieve PCI info for device
+ * @vptr: velocity device
+ * @pdev: PCI device it matches
+ *
+ * Retrieve the PCI configuration space data that interests us from
+ * the kernel PCI layer
+ */
+
+#define IORESOURCE_IO 0x00000100 /* Resource type */
+#define IORESOURCE_PREFETCH 0x00001000 /* No side effects */
+
+#define IORESOURCE_MEM 0x00000200
+#define BAR_0 0
+#define BAR_1 1
+#define BAR_5 5
+#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
+#define PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
+#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
+#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
+#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
+//#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
+// #define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
+
+unsigned long pci_resource_flags(struct pci_device *pdev, unsigned int bar)
+{
+ uint32_t l, sz;
+ unsigned long flags = 0;
+
+ pci_read_config_dword(pdev, bar, &l);
+ pci_write_config_dword(pdev, bar, ~0);
+ pci_read_config_dword(pdev, bar, &sz);
+ pci_write_config_dword(pdev, bar, l);
+
+ if (!sz || sz == 0xffffffff)
+ printf("Weird size\n");
+ if (l == 0xffffffff)
+ l = 0;
+ if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) {
+ /* sz = pci_size(l, sz, PCI_BASE_ADDRESS_MEM_MASK);
+ if (!sz)
+ continue;
+ res->start = l & PCI_BASE_ADDRESS_MEM_MASK;
+ */ flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK;
+ printf("Memory Resource\n");
+ } else {
+ // sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff);
+ /// if (!sz)
+ /// continue;
+// res->start = l & PCI_BASE_ADDRESS_IO_MASK;
+ flags |= l & ~PCI_BASE_ADDRESS_IO_MASK;
+ printf("I/O Resource\n");
+ }
+ if (flags & PCI_BASE_ADDRESS_SPACE_IO) {
+ printf("Why is it here\n");
+ flags |= IORESOURCE_IO;
+ } else {
+ printf("here\n");
+//flags &= ~IORESOURCE_IO;
+ }
+
+
+ if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH)
+ flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
+
+
+ return flags;
+}
+static int velocity_get_pci_info(struct velocity_info *vptr,
+ struct pci_device *pdev)
+{
+ if (pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0) {
+ printf("DEBUG: pci_read_config_byte failed\n");
+ return -1;
+ }
+
+ adjust_pci_device(pdev);
+
+ vptr->ioaddr = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
+ vptr->memaddr = pci_bar_start(pdev, PCI_BASE_ADDRESS_1);
+
+ printf("Looking for I/O Resource - Found:");
+ if (!
+ (pci_resource_flags(pdev, PCI_BASE_ADDRESS_0) & IORESOURCE_IO))
+ {
+ printf
+ ("DEBUG: region #0 is not an I/O resource, aborting.\n");
+ return -1;
+ }
+
+ printf("Looking for Memory Resource - Found:");
+ if ((pci_resource_flags(pdev, PCI_BASE_ADDRESS_1) & IORESOURCE_IO)) {
+ printf("DEBUG: region #1 is an I/O resource, aborting.\n");
+ return -1;
+ }
+
+ if (pci_bar_size(pdev, PCI_BASE_ADDRESS_1) < 256) {
+ printf("DEBUG: region #1 is too small.\n");
+ return -1;
+ }
+ vptr->pdev = pdev;
+
+ return 0;
+}
+
+/**
+ * velocity_print_link_status - link status reporting
+ * @vptr: velocity to report on
+ *
+ * Turn the link status of the velocity card into a kernel log
+ * description of the new link state, detailing speed and duplex
+ * status
+ */
+
+static void velocity_print_link_status(struct velocity_info *vptr)
+{
+
+ if (vptr->mii_status & VELOCITY_LINK_FAIL) {
+ printf("failed to detect cable link\n");
+ } else if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
+ printf("Link autonegation");
+
+ if (vptr->mii_status & VELOCITY_SPEED_1000)
+ printf(" speed 1000M bps");
+ else if (vptr->mii_status & VELOCITY_SPEED_100)
+ printf(" speed 100M bps");
+ else
+ printf(" speed 10M bps");
+
+ if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
+ printf(" full duplex\n");
+ else
+ printf(" half duplex\n");
+ } else {
+ printf("Link forced");
+ switch (vptr->options.spd_dpx) {
+ case SPD_DPX_100_HALF:
+ printf(" speed 100M bps half duplex\n");
+ break;
+ case SPD_DPX_100_FULL:
+ printf(" speed 100M bps full duplex\n");
+ break;
+ case SPD_DPX_10_HALF:
+ printf(" speed 10M bps half duplex\n");
+ break;
+ case SPD_DPX_10_FULL:
+ printf(" speed 10M bps full duplex\n");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * velocity_rx_reset - handle a receive reset
+ * @vptr: velocity we are resetting
+ *
+ * Reset the ownership and status for the receive ring side.
+ * Hand all the receive queue to the NIC.
+ */
+
+static void velocity_rx_reset(struct velocity_info *vptr)
+{
+
+ struct mac_regs *regs = vptr->mac_regs;
+ int i;
+
+//ptr->rd_dirty = vptr->rd_filled = vptr->rd_curr = 0;
+
+ /*
+ * Init state, all RD entries belong to the NIC
+ */
+ for (i = 0; i < vptr->options.numrx; ++i)
+ vptr->rd_ring[i].rdesc0.owner = OWNED_BY_NIC;
+
+ writew(RX_DESC_DEF, &regs->RBRDU);
+ writel(virt_to_le32desc(vptr->rd_ring), &regs->RDBaseLo);
+ writew(0, &regs->RDIdx);
+ writew(RX_DESC_DEF - 1, &regs->RDCSize);
+}
+
+/**
+ * velocity_init_registers - initialise MAC registers
+ * @vptr: velocity to init
+ * @type: type of initialisation (hot or cold)
+ *
+ * Initialise the MAC on a reset or on first set up on the
+ * hardware.
+ */
+
+static void velocity_init_registers(struct nic *nic,
+ struct velocity_info *vptr,
+ enum velocity_init_type type)
+{
+ struct mac_regs *regs = vptr->mac_regs;
+ int i, mii_status;
+
+ mac_wol_reset(regs);
+
+ switch (type) {
+ case VELOCITY_INIT_RESET:
+ case VELOCITY_INIT_WOL:
+
+//netif_stop_queue(vptr->dev);
+
+ /*
+ * Reset RX to prevent RX pointer not on the 4X location
+ */
+ velocity_rx_reset(vptr);
+ mac_rx_queue_run(regs);
+ mac_rx_queue_wake(regs);
+
+ mii_status = velocity_get_opt_media_mode(vptr);
+
+ if (velocity_set_media_mode(vptr, mii_status) !=
+ VELOCITY_LINK_CHANGE) {
+ velocity_print_link_status(vptr);
+ if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
+ printf("Link Failed\n");
+// netif_wake_queue(vptr->dev);
+ }
+
+ enable_flow_control_ability(vptr);
+
+ mac_clear_isr(regs);
+ writel(CR0_STOP, &regs->CR0Clr);
+ //writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT),
+ writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT),
+ &regs->CR0Set);
+ break;
+
+ case VELOCITY_INIT_COLD:
+ default:
+ /*
+ * Do reset
+ */
+ velocity_soft_reset(vptr);
+ mdelay(5);
+
+ mac_eeprom_reload(regs);
+ for (i = 0; i < 6; i++) {
+ writeb(nic->node_addr[i], &(regs->PAR[i]));
+ }
+ /*
+ * clear Pre_ACPI bit.
+ */
+ BYTE_REG_BITS_OFF(CFGA_PACPI, &(regs->CFGA));
+ mac_set_rx_thresh(regs, vptr->options.rx_thresh);
+ mac_set_dma_length(regs, vptr->options.DMA_length);
+
+ writeb(WOLCFG_SAM | WOLCFG_SAB, &regs->WOLCFGSet);
+ /*
+ * Back off algorithm use original IEEE standard
+ */
+ BYTE_REG_BITS_SET(CFGB_OFSET,
+ (CFGB_CRANDOM | CFGB_CAP | CFGB_MBA |
+ CFGB_BAKOPT), &regs->CFGB);
+
+ /*
+ * Init CAM filter
+ */
+ velocity_init_cam_filter(vptr);
+
+ /*
+ * Set packet filter: Receive directed and broadcast address
+ */
+//FIXME Multicast velocity_set_multi(nic);
+
+ /*
+ * Enable MII auto-polling
+ */
+ enable_mii_autopoll(regs);
+
+ vptr->int_mask = INT_MASK_DEF;
+
+ writel(virt_to_le32desc(vptr->rd_ring), &regs->RDBaseLo);
+ writew(vptr->options.numrx - 1, &regs->RDCSize);
+ mac_rx_queue_run(regs);
+ mac_rx_queue_wake(regs);
+
+ writew(vptr->options.numtx - 1, &regs->TDCSize);
+
+// for (i = 0; i < vptr->num_txq; i++) {
+ writel(virt_to_le32desc(vptr->td_rings),
+ &(regs->TDBaseLo[0]));
+ mac_tx_queue_run(regs, 0);
+// }
+
+ init_flow_control_register(vptr);
+
+ writel(CR0_STOP, &regs->CR0Clr);
+ writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT),
+ &regs->CR0Set);
+
+ mii_status = velocity_get_opt_media_mode(vptr);
+// netif_stop_queue(vptr->dev);
+
+ mii_init(vptr, mii_status);
+
+ if (velocity_set_media_mode(vptr, mii_status) !=
+ VELOCITY_LINK_CHANGE) {
+ velocity_print_link_status(vptr);
+ if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
+ printf("Link Faaailll\n");
+// netif_wake_queue(vptr->dev);
+ }
+
+ enable_flow_control_ability(vptr);
+ mac_hw_mibs_init(regs);
+ mac_write_int_mask(vptr->int_mask, regs);
+ mac_clear_isr(regs);
+
+
+ }
+ velocity_print_link_status(vptr);
+}
+
+/**
+ * velocity_soft_reset - soft reset
+ * @vptr: velocity to reset
+ *
+ * Kick off a soft reset of the velocity adapter and then poll
+ * until the reset sequence has completed before returning.
+ */
+
+static int velocity_soft_reset(struct velocity_info *vptr)
+{
+ struct mac_regs *regs = vptr->mac_regs;
+ unsigned int i = 0;
+
+ writel(CR0_SFRST, &regs->CR0Set);
+
+ for (i = 0; i < W_MAX_TIMEOUT; i++) {
+ udelay(5);
+ if (!DWORD_REG_BITS_IS_ON(CR0_SFRST, &regs->CR0Set))
+ break;
+ }
+
+ if (i == W_MAX_TIMEOUT) {
+ writel(CR0_FORSRST, &regs->CR0Set);
+ /* FIXME: PCI POSTING */
+ /* delay 2ms */
+ mdelay(2);
+ }
+ return 0;
+}
+
+/**
+ * velocity_init_rings - set up DMA rings
+ * @vptr: Velocity to set up
+ *
+ * Allocate PCI mapped DMA rings for the receive and transmit layer
+ * to use.
+ */
+
+static int velocity_init_rings(struct velocity_info *vptr)
+{
+
+ int idx;
+
+ vptr->rd_curr = 0;
+ vptr->td_curr = 0;
+ memset(vptr->td_rings, 0, TX_DESC_DEF * sizeof(struct tx_desc));
+ memset(vptr->rd_ring, 0, RX_DESC_DEF * sizeof(struct rx_desc));
+// memset(vptr->tx_buffs, 0, TX_DESC_DEF * PKT_BUF_SZ);
+
+
+ for (idx = 0; idx < RX_DESC_DEF; idx++) {
+ vptr->rd_ring[idx].rdesc0.RSR = 0;
+ vptr->rd_ring[idx].rdesc0.len = 0;
+ vptr->rd_ring[idx].rdesc0.reserved = 0;
+ vptr->rd_ring[idx].rdesc0.owner = 0;
+ vptr->rd_ring[idx].len = cpu_to_le32(vptr->rx_buf_sz);
+ vptr->rd_ring[idx].inten = 1;
+ vptr->rd_ring[idx].pa_low =
+ virt_to_bus(vptr->rxb + (RX_DESC_DEF * idx));
+ vptr->rd_ring[idx].pa_high = 0;
+ vptr->rd_ring[idx].rdesc0.owner = OWNED_BY_NIC;
+ }
+
+/* for (i = 0; idx < TX_DESC_DEF; idx++ ) {
+ vptr->td_rings[idx].tdesc1.TCPLS = TCPLS_NORMAL;
+ vptr->td_rings[idx].tdesc1.TCR = TCR0_TIC;
+ vptr->td_rings[idx].td_buf[0].queue = 0;
+ vptr->td_rings[idx].tdesc0.owner = ~OWNED_BY_NIC;
+ vptr->td_rings[idx].tdesc0.pktsize = 0;
+ vptr->td_rings[idx].td_buf[0].pa_low = cpu_to_le32(virt_to_bus(vptr->txb + (idx * PKT_BUF_SZ)));
+ vptr->td_rings[idx].td_buf[0].pa_high = 0;
+ vptr->td_rings[idx].td_buf[0].bufsize = 0;
+ vptr->td_rings[idx].tdesc1.CMDZ = 2;
+ }
+*/
+ return 0;
+}
+
+/**
+ * velocity_open - interface activation callback
+ * @dev: network layer device to open
+ *
+ * Called when the network layer brings the interface up. Returns
+ * a negative posix error code on failure, or zero on success.
+ *
+ * All the ring allocation and set up is done on open for this
+ * adapter to minimise memory usage when inactive
+ */
+
+#define PCI_BYTE_REG_BITS_ON(x,i,p) do{\
+ u8 byReg;\
+ pci_read_config_byte((p), (i), &(byReg));\
+ (byReg) |= (x);\
+ pci_write_config_byte((p), (i), (byReg));\
+} while (0)
+
+//
+// Registers in the PCI configuration space
+//
+#define PCI_REG_COMMAND 0x04 //
+#define PCI_REG_MODE0 0x60 //
+#define PCI_REG_MODE1 0x61 //
+#define PCI_REG_MODE2 0x62 //
+#define PCI_REG_MODE3 0x63 //
+#define PCI_REG_DELAY_TIMER 0x64 //
+
+// Bits in the (MODE2, 0x62) register
+//
+#define MODE2_PCEROPT 0x80 // take PCI bus ERror as a fatal and shutdown from software control
+#define MODE2_TXQ16 0x40 // TX write-back Queue control. 0->32 entries available in Tx write-back queue, 1->16 entries
+#define MODE2_TXPOST 0x08 // (Not support in VT3119)
+#define MODE2_AUTOOPT 0x04 // (VT3119 GHCI without such behavior)
+#define MODE2_MODE10T 0x02 // used to control tx Threshold for 10M case
+#define MODE2_TCPLSOPT 0x01 // TCP large send field update disable, hardware will not update related fields, leave it to software.
+
+//
+// Bits in the MODE3 register
+//
+#define MODE3_MIION 0x04 // MII symbol codine error detect enable ??
+
+// Bits in the (COMMAND, 0x04) register
+#define COMMAND_BUSM 0x04
+#define COMMAND_WAIT 0x80
+static int velocity_open(struct nic *nic, struct pci_device *pci __unused)
+{
+ u8 diff;
+ u32 TxPhyAddr, RxPhyAddr;
+ u32 TxBufPhyAddr, RxBufPhyAddr;
+ vptr->TxDescArrays = tx_ring;
+ if (vptr->TxDescArrays == 0)
+ printf("Allot Error");
+
+ /* Tx Descriptor needs 64 bytes alignment; */
+ TxPhyAddr = virt_to_bus(vptr->TxDescArrays);
+ printf("Unaligned Address : %X\n", TxPhyAddr);
+ diff = 64 - (TxPhyAddr - ((TxPhyAddr >> 6) << 6));
+ TxPhyAddr += diff;
+ vptr->td_rings = (struct tx_desc *) (vptr->TxDescArrays + diff);
+
+ printf("Aligned Address: %lX\n", virt_to_bus(vptr->td_rings));
+ vptr->tx_buffs = txb;
+ /* Rx Buffer needs 64 bytes alignment; */
+ TxBufPhyAddr = virt_to_bus(vptr->tx_buffs);
+ diff = 64 - (TxBufPhyAddr - ((TxBufPhyAddr >> 6) << 6));
+ TxBufPhyAddr += diff;
+ vptr->txb = (unsigned char *) (vptr->tx_buffs + diff);
+
+ vptr->RxDescArrays = rx_ring;
+ /* Rx Descriptor needs 64 bytes alignment; */
+ RxPhyAddr = virt_to_bus(vptr->RxDescArrays);
+ diff = 64 - (RxPhyAddr - ((RxPhyAddr >> 6) << 6));
+ RxPhyAddr += diff;
+ vptr->rd_ring = (struct rx_desc *) (vptr->RxDescArrays + diff);
+
+ vptr->rx_buffs = rxb;
+ /* Rx Buffer needs 64 bytes alignment; */
+ RxBufPhyAddr = virt_to_bus(vptr->rx_buffs);
+ diff = 64 - (RxBufPhyAddr - ((RxBufPhyAddr >> 6) << 6));
+ RxBufPhyAddr += diff;
+ vptr->rxb = (unsigned char *) (vptr->rx_buffs + diff);
+
+ if (vptr->RxDescArrays == NULL || vptr->RxDescArrays == NULL) {
+ printf("Allocate tx_ring or rd_ring failed\n");
+ return 0;
+ }
+
+ vptr->rx_buf_sz = PKT_BUF_SZ;
+/*
+ // turn this on to avoid retry forever
+ PCI_BYTE_REG_BITS_ON(MODE2_PCEROPT, PCI_REG_MODE2, pci);
+ // for some legacy BIOS and OS don't open BusM
+ // bit in PCI configuration space. So, turn it on.
+ PCI_BYTE_REG_BITS_ON(COMMAND_BUSM, PCI_REG_COMMAND, pci);
+ // turn this on to detect MII coding error
+ PCI_BYTE_REG_BITS_ON(MODE3_MIION, PCI_REG_MODE3, pci);
+ */
+ velocity_init_rings(vptr);
+
+ /* Ensure chip is running */
+//FIXME: pci_set_power_state(vptr->pdev, PCI_D0);
+
+ velocity_init_registers(nic, vptr, VELOCITY_INIT_COLD);
+ mac_write_int_mask(0, vptr->mac_regs);
+// _int(vptr->mac_regs);
+ //mac_enable_int(vptr->mac_regs);
+
+ vptr->flags |= VELOCITY_FLAGS_OPENED;
+ return 1;
+
+}
+
+/*
+ * MII access , media link mode setting functions
+ */
+
+
+/**
+ * mii_init - set up MII
+ * @vptr: velocity adapter
+ * @mii_status: links tatus
+ *
+ * Set up the PHY for the current link state.
+ */
+
+static void mii_init(struct velocity_info *vptr, u32 mii_status __unused)
+{
+ u16 BMCR;
+
+ switch (PHYID_GET_PHY_ID(vptr->phy_id)) {
+ case PHYID_CICADA_CS8201:
+ /*
+ * Reset to hardware default
+ */
+ MII_REG_BITS_OFF((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR,
+ vptr->mac_regs);
+ /*
+ * Turn on ECHODIS bit in NWay-forced full mode and turn it
+ * off it in NWay-forced half mode for NWay-forced v.s.
+ * legacy-forced issue.
+ */
+ if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
+ MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR,
+ vptr->mac_regs);
+ else
+ MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR,
+ vptr->mac_regs);
+ /*
+ * Turn on Link/Activity LED enable bit for CIS8201
+ */
+ MII_REG_BITS_ON(PLED_LALBE, MII_REG_PLED, vptr->mac_regs);
+ break;
+ case PHYID_VT3216_32BIT:
+ case PHYID_VT3216_64BIT:
+ /*
+ * Reset to hardware default
+ */
+ MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR,
+ vptr->mac_regs);
+ /*
+ * Turn on ECHODIS bit in NWay-forced full mode and turn it
+ * off it in NWay-forced half mode for NWay-forced v.s.
+ * legacy-forced issue
+ */
+ if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
+ MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR,
+ vptr->mac_regs);
+ else
+ MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR,
+ vptr->mac_regs);
+ break;
+
+ case PHYID_MARVELL_1000:
+ case PHYID_MARVELL_1000S:
+ /*
+ * Assert CRS on Transmit
+ */
+ MII_REG_BITS_ON(PSCR_ACRSTX, MII_REG_PSCR, vptr->mac_regs);
+ /*
+ * Reset to hardware default
+ */
+ MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR,
+ vptr->mac_regs);
+ break;
+ default:
+ ;
+ }
+ velocity_mii_read(vptr->mac_regs, MII_REG_BMCR, &BMCR);
+ if (BMCR & BMCR_ISO) {
+ BMCR &= ~BMCR_ISO;
+ velocity_mii_write(vptr->mac_regs, MII_REG_BMCR, BMCR);
+ }
+}
+
+/**
+ * safe_disable_mii_autopoll - autopoll off
+ * @regs: velocity registers
+ *
+ * Turn off the autopoll and wait for it to disable on the chip
+ */
+
+static void safe_disable_mii_autopoll(struct mac_regs *regs)
+{
+ u16 ww;
+
+ /* turn off MAUTO */
+ writeb(0, &regs->MIICR);
+ for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+ udelay(1);
+ if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
+ break;
+ }
+}
+
+/**
+ * enable_mii_autopoll - turn on autopolling
+ * @regs: velocity registers
+ *
+ * Enable the MII link status autopoll feature on the Velocity
+ * hardware. Wait for it to enable.
+ */
+
+static void enable_mii_autopoll(struct mac_regs *regs)
+{
+ unsigned int ii;
+
+ writeb(0, &(regs->MIICR));
+ writeb(MIIADR_SWMPL, &regs->MIIADR);
+
+ for (ii = 0; ii < W_MAX_TIMEOUT; ii++) {
+ udelay(1);
+ if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
+ break;
+ }
+
+ writeb(MIICR_MAUTO, &regs->MIICR);
+
+ for (ii = 0; ii < W_MAX_TIMEOUT; ii++) {
+ udelay(1);
+ if (!BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
+ break;
+ }
+
+}
+
+/**
+ * velocity_mii_read - read MII data
+ * @regs: velocity registers
+ * @index: MII register index
+ * @data: buffer for received data
+ *
+ * Perform a single read of an MII 16bit register. Returns zero
+ * on success or -ETIMEDOUT if the PHY did not respond.
+ */
+
+static int velocity_mii_read(struct mac_regs *regs, u8 index, u16 * data)
+{
+ u16 ww;
+
+ /*
+ * Disable MIICR_MAUTO, so that mii addr can be set normally
+ */
+ safe_disable_mii_autopoll(regs);
+
+ writeb(index, &regs->MIIADR);
+
+ BYTE_REG_BITS_ON(MIICR_RCMD, &regs->MIICR);
+
+ for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+ if (!(readb(&regs->MIICR) & MIICR_RCMD))
+ break;
+ }
+
+ *data = readw(&regs->MIIDATA);
+
+ enable_mii_autopoll(regs);
+ if (ww == W_MAX_TIMEOUT)
+ return -1;
+ return 0;
+}
+
+/**
+ * velocity_mii_write - write MII data
+ * @regs: velocity registers
+ * @index: MII register index
+ * @data: 16bit data for the MII register
+ *
+ * Perform a single write to an MII 16bit register. Returns zero
+ * on success or -ETIMEDOUT if the PHY did not respond.
+ */
+
+static int velocity_mii_write(struct mac_regs *regs, u8 mii_addr, u16 data)
+{
+ u16 ww;
+
+ /*
+ * Disable MIICR_MAUTO, so that mii addr can be set normally
+ */
+ safe_disable_mii_autopoll(regs);
+
+ /* MII reg offset */
+ writeb(mii_addr, &regs->MIIADR);
+ /* set MII data */
+ writew(data, &regs->MIIDATA);
+
+ /* turn on MIICR_WCMD */
+ BYTE_REG_BITS_ON(MIICR_WCMD, &regs->MIICR);
+
+ /* W_MAX_TIMEOUT is the timeout period */
+ for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+ udelay(5);
+ if (!(readb(&regs->MIICR) & MIICR_WCMD))
+ break;
+ }
+ enable_mii_autopoll(regs);
+
+ if (ww == W_MAX_TIMEOUT)
+ return -1;
+ return 0;
+}
+
+/**
+ * velocity_get_opt_media_mode - get media selection
+ * @vptr: velocity adapter
+ *
+ * Get the media mode stored in EEPROM or module options and load
+ * mii_status accordingly. The requested link state information
+ * is also returned.
+ */
+
+static u32 velocity_get_opt_media_mode(struct velocity_info *vptr)
+{
+ u32 status = 0;
+
+ switch (vptr->options.spd_dpx) {
+ case SPD_DPX_AUTO:
+ status = VELOCITY_AUTONEG_ENABLE;
+ break;
+ case SPD_DPX_100_FULL:
+ status = VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL;
+ break;
+ case SPD_DPX_10_FULL:
+ status = VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL;
+ break;
+ case SPD_DPX_100_HALF:
+ status = VELOCITY_SPEED_100;
+ break;
+ case SPD_DPX_10_HALF:
+ status = VELOCITY_SPEED_10;
+ break;
+ }
+ vptr->mii_status = status;
+ return status;
+}
+
+/**
+ * mii_set_auto_on - autonegotiate on
+ * @vptr: velocity
+ *
+ * Enable autonegotation on this interface
+ */
+
+static void mii_set_auto_on(struct velocity_info *vptr)
+{
+ if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs))
+ MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR, vptr->mac_regs);
+ else
+ MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs);
+}
+
+
+/*
+static void mii_set_auto_off(struct velocity_info * vptr)
+{
+ MII_REG_BITS_OFF(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs);
+}
+*/
+
+/**
+ * set_mii_flow_control - flow control setup
+ * @vptr: velocity interface
+ *
+ * Set up the flow control on this interface according to
+ * the supplied user/eeprom options.
+ */
+
+static void set_mii_flow_control(struct velocity_info *vptr)
+{
+ /*Enable or Disable PAUSE in ANAR */
+ switch (vptr->options.flow_cntl) {
+ case FLOW_CNTL_TX:
+ MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
+ MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
+ break;
+
+ case FLOW_CNTL_RX:
+ MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
+ MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
+ break;
+
+ case FLOW_CNTL_TX_RX:
+ MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
+ MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
+ break;
+
+ case FLOW_CNTL_DISABLE:
+ MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
+ MII_REG_BITS_OFF(ANAR_ASMDIR, MII_REG_ANAR,
+ vptr->mac_regs);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * velocity_set_media_mode - set media mode
+ * @mii_status: old MII link state
+ *
+ * Check the media link state and configure the flow control
+ * PHY and also velocity hardware setup accordingly. In particular
+ * we need to set up CD polling and frame bursting.
+ */
+
+static int velocity_set_media_mode(struct velocity_info *vptr,
+ u32 mii_status)
+{
+ struct mac_regs *regs = vptr->mac_regs;
+
+ vptr->mii_status = mii_check_media_mode(vptr->mac_regs);
+
+ /* Set mii link status */
+ set_mii_flow_control(vptr);
+
+ if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201) {
+ MII_REG_BITS_ON(AUXCR_MDPPS, MII_REG_AUXCR,
+ vptr->mac_regs);
+ }
+
+ /*
+ * If connection type is AUTO
+ */
+ if (mii_status & VELOCITY_AUTONEG_ENABLE) {
+ printf("Velocity is AUTO mode\n");
+ /* clear force MAC mode bit */
+ BYTE_REG_BITS_OFF(CHIPGCR_FCMODE, &regs->CHIPGCR);
+ /* set duplex mode of MAC according to duplex mode of MII */
+ MII_REG_BITS_ON(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10,
+ MII_REG_ANAR, vptr->mac_regs);
+ MII_REG_BITS_ON(G1000CR_1000FD | G1000CR_1000,
+ MII_REG_G1000CR, vptr->mac_regs);
+ MII_REG_BITS_ON(BMCR_SPEED1G, MII_REG_BMCR,
+ vptr->mac_regs);
+
+ /* enable AUTO-NEGO mode */
+ mii_set_auto_on(vptr);
+ } else {
+ u16 ANAR;
+ u8 CHIPGCR;
+
+ /*
+ * 1. if it's 3119, disable frame bursting in halfduplex mode
+ * and enable it in fullduplex mode
+ * 2. set correct MII/GMII and half/full duplex mode in CHIPGCR
+ * 3. only enable CD heart beat counter in 10HD mode
+ */
+
+ /* set force MAC mode bit */
+ BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
+
+ CHIPGCR = readb(&regs->CHIPGCR);
+ CHIPGCR &= ~CHIPGCR_FCGMII;
+
+ if (mii_status & VELOCITY_DUPLEX_FULL) {
+ CHIPGCR |= CHIPGCR_FCFDX;
+ writeb(CHIPGCR, &regs->CHIPGCR);
+ printf
+ ("DEBUG: set Velocity to forced full mode\n");
+ if (vptr->rev_id < REV_ID_VT3216_A0)
+ BYTE_REG_BITS_OFF(TCR_TB2BDIS, &regs->TCR);
+ } else {
+ CHIPGCR &= ~CHIPGCR_FCFDX;
+ printf
+ ("DEBUG: set Velocity to forced half mode\n");
+ writeb(CHIPGCR, &regs->CHIPGCR);
+ if (vptr->rev_id < REV_ID_VT3216_A0)
+ BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
+ }
+
+ MII_REG_BITS_OFF(G1000CR_1000FD | G1000CR_1000,
+ MII_REG_G1000CR, vptr->mac_regs);
+
+ if (!(mii_status & VELOCITY_DUPLEX_FULL)
+ && (mii_status & VELOCITY_SPEED_10)) {
+ BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->TESTCFG);
+ } else {
+ BYTE_REG_BITS_ON(TESTCFG_HBDIS, &regs->TESTCFG);
+ }
+ /* MII_REG_BITS_OFF(BMCR_SPEED1G, MII_REG_BMCR, vptr->mac_regs); */
+ velocity_mii_read(vptr->mac_regs, MII_REG_ANAR, &ANAR);
+ ANAR &= (~(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10));
+ if (mii_status & VELOCITY_SPEED_100) {
+ if (mii_status & VELOCITY_DUPLEX_FULL)
+ ANAR |= ANAR_TXFD;
+ else
+ ANAR |= ANAR_TX;
+ } else {
+ if (mii_status & VELOCITY_DUPLEX_FULL)
+ ANAR |= ANAR_10FD;
+ else
+ ANAR |= ANAR_10;
+ }
+ velocity_mii_write(vptr->mac_regs, MII_REG_ANAR, ANAR);
+ /* enable AUTO-NEGO mode */
+ mii_set_auto_on(vptr);
+ /* MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs); */
+ }
+ /* vptr->mii_status=mii_check_media_mode(vptr->mac_regs); */
+ /* vptr->mii_status=check_connection_type(vptr->mac_regs); */
+ return VELOCITY_LINK_CHANGE;
+}
+
+/**
+ * mii_check_media_mode - check media state
+ * @regs: velocity registers
+ *
+ * Check the current MII status and determine the link status
+ * accordingly
+ */
+
+static u32 mii_check_media_mode(struct mac_regs *regs)
+{
+ u32 status = 0;
+ u16 ANAR;
+
+ if (!MII_REG_BITS_IS_ON(BMSR_LNK, MII_REG_BMSR, regs))
+ status |= VELOCITY_LINK_FAIL;
+
+ if (MII_REG_BITS_IS_ON(G1000CR_1000FD, MII_REG_G1000CR, regs))
+ status |= VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL;
+ else if (MII_REG_BITS_IS_ON(G1000CR_1000, MII_REG_G1000CR, regs))
+ status |= (VELOCITY_SPEED_1000);
+ else {
+ velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
+ if (ANAR & ANAR_TXFD)
+ status |=
+ (VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL);
+ else if (ANAR & ANAR_TX)
+ status |= VELOCITY_SPEED_100;
+ else if (ANAR & ANAR_10FD)
+ status |=
+ (VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL);
+ else
+ status |= (VELOCITY_SPEED_10);
+ }
+
+ if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) {
+ velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
+ if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10))
+ == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) {
+ if (MII_REG_BITS_IS_ON
+ (G1000CR_1000 | G1000CR_1000FD,
+ MII_REG_G1000CR, regs))
+ status |= VELOCITY_AUTONEG_ENABLE;
+ }
+ }
+
+ return status;
+}
+
+static u32 check_connection_type(struct mac_regs *regs)
+{
+ u32 status = 0;
+ u8 PHYSR0;
+ u16 ANAR;
+ PHYSR0 = readb(&regs->PHYSR0);
+
+ /*
+ if (!(PHYSR0 & PHYSR0_LINKGD))
+ status|=VELOCITY_LINK_FAIL;
+ */
+
+ if (PHYSR0 & PHYSR0_FDPX)
+ status |= VELOCITY_DUPLEX_FULL;
+
+ if (PHYSR0 & PHYSR0_SPDG)
+ status |= VELOCITY_SPEED_1000;
+ if (PHYSR0 & PHYSR0_SPD10)
+ status |= VELOCITY_SPEED_10;
+ else
+ status |= VELOCITY_SPEED_100;
+
+ if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) {
+ velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
+ if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10))
+ == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) {
+ if (MII_REG_BITS_IS_ON
+ (G1000CR_1000 | G1000CR_1000FD,
+ MII_REG_G1000CR, regs))
+ status |= VELOCITY_AUTONEG_ENABLE;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * enable_flow_control_ability - flow control
+ * @vptr: veloity to configure
+ *
+ * Set up flow control according to the flow control options
+ * determined by the eeprom/configuration.
+ */
+
+static void enable_flow_control_ability(struct velocity_info *vptr)
+{
+
+ struct mac_regs *regs = vptr->mac_regs;
+
+ switch (vptr->options.flow_cntl) {
+
+ case FLOW_CNTL_DEFAULT:
+ if (BYTE_REG_BITS_IS_ON(PHYSR0_RXFLC, &regs->PHYSR0))
+ writel(CR0_FDXRFCEN, &regs->CR0Set);
+ else
+ writel(CR0_FDXRFCEN, &regs->CR0Clr);
+
+ if (BYTE_REG_BITS_IS_ON(PHYSR0_TXFLC, &regs->PHYSR0))
+ writel(CR0_FDXTFCEN, &regs->CR0Set);
+ else
+ writel(CR0_FDXTFCEN, &regs->CR0Clr);
+ break;
+
+ case FLOW_CNTL_TX:
+ writel(CR0_FDXTFCEN, &regs->CR0Set);
+ writel(CR0_FDXRFCEN, &regs->CR0Clr);
+ break;
+
+ case FLOW_CNTL_RX:
+ writel(CR0_FDXRFCEN, &regs->CR0Set);
+ writel(CR0_FDXTFCEN, &regs->CR0Clr);
+ break;
+
+ case FLOW_CNTL_TX_RX:
+ writel(CR0_FDXTFCEN, &regs->CR0Set);
+ writel(CR0_FDXRFCEN, &regs->CR0Set);
+ break;
+
+ case FLOW_CNTL_DISABLE:
+ writel(CR0_FDXRFCEN, &regs->CR0Clr);
+ writel(CR0_FDXTFCEN, &regs->CR0Clr);
+ break;
+
+ default:
+ break;
+ }
+
+}
+
+/* FIXME: Move to pci.c */
+/**
+ * pci_set_power_state - Set the power state of a PCI device
+ * @dev: PCI device to be suspended
+ * @state: Power state we're entering
+ *
+ * Transition a device to a new power state, using the Power Management
+ * Capabilities in the device's config space.
+ *
+ * RETURN VALUE:
+ * -EINVAL if trying to enter a lower state than we're already in.
+ * 0 if we're already in the requested state.
+ * -EIO if device does not support PCI PM.
+ * 0 if we can successfully change the power state.
+ */
+
+int pci_set_power_state(struct pci_device *dev, int state)
+{
+ int pm;
+ u16 pmcsr;
+ int current_state = 0;
+
+ /* bound the state we're entering */
+ if (state > 3)
+ state = 3;
+
+ /* Validate current state:
+ * Can enter D0 from any state, but if we can only go deeper
+ * to sleep if we're already in a low power state
+ */
+ if (state > 0 && current_state > state)
+ return -1;
+ else if (current_state == state)
+ return 0; /* we're already there */
+
+ /* find PCI PM capability in list */
+ pm = pci_find_capability(dev, PCI_CAP_ID_PM);
+
+ /* abort if the device doesn't support PM capabilities */
+ if (!pm)
+ return -2;
+
+ /* check if this device supports the desired state */
+ if (state == 1 || state == 2) {
+ u16 pmc;
+ pci_read_config_word(dev, pm + PCI_PM_PMC, &pmc);
+ if (state == 1 && !(pmc & PCI_PM_CAP_D1))
+ return -2;
+ else if (state == 2 && !(pmc & PCI_PM_CAP_D2))
+ return -2;
+ }
+
+ /* If we're in D3, force entire word to 0.
+ * This doesn't affect PME_Status, disables PME_En, and
+ * sets PowerState to 0.
+ */
+ if (current_state >= 3)
+ pmcsr = 0;
+ else {
+ pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
+ pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+ pmcsr |= state;
+ }
+
+ /* enter specified state */
+ pci_write_config_word(dev, pm + PCI_PM_CTRL, pmcsr);
+
+ /* Mandatory power management transition delays */
+ /* see PCI PM 1.1 5.6.1 table 18 */
+ if (state == 3 || current_state == 3)
+ mdelay(10);
+ else if (state == 2 || current_state == 2)
+ udelay(200);
+ current_state = state;
+
+ return 0;
+}
+
+static struct pci_device_id velocity_nics[] = {
+ PCI_ROM(0x1106, 0x3119, "via-velocity", "VIA Networking Velocity Family Gigabit Ethernet Adapter", 0),
+};
+
+PCI_DRIVER ( velocity_driver, velocity_nics, PCI_NO_CLASS );
+
+DRIVER ( "VIA-VELOCITY/PCI", nic_driver, pci_driver, velocity_driver,
+ velocity_probe, velocity_disable );
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/via-velocity.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/via-velocity.h
new file mode 100644
index 00000000..b657224d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/via-velocity.h
@@ -0,0 +1,1932 @@
+/*
+ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
+ * All rights reserved.
+ *
+ * This software may be redistributed and/or modified under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * File: via-velocity.h
+ *
+ * Purpose: Header file to define driver's private structures.
+ *
+ * Author: Chuang Liang-Shing, AJ Jiang
+ *
+ * Date: Jan 24, 2003
+ *
+ * Changes for Etherboot Port:
+ * Copyright (c) 2006 by Timothy Legge <tlegge@rogers.com>
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef VELOCITY_H
+#define VELOCITY_H
+
+#define VELOCITY_TX_CSUM_SUPPORT
+
+#define VELOCITY_NAME "via-velocity"
+#define VELOCITY_FULL_DRV_NAM "VIA Networking Velocity Family Gigabit Ethernet Adapter Driver"
+#define VELOCITY_VERSION "1.13"
+
+#define PKT_BUF_SZ 1564
+
+#define MAX_UNITS 8
+#define OPTION_DEFAULT { [0 ... MAX_UNITS-1] = -1}
+
+#define REV_ID_VT6110 (0)
+
+#define BYTE_REG_BITS_ON(x,p) do { writeb(readb((p))|(x),(p));} while (0)
+#define WORD_REG_BITS_ON(x,p) do { writew(readw((p))|(x),(p));} while (0)
+#define DWORD_REG_BITS_ON(x,p) do { writel(readl((p))|(x),(p));} while (0)
+
+#define BYTE_REG_BITS_IS_ON(x,p) (readb((p)) & (x))
+#define WORD_REG_BITS_IS_ON(x,p) (readw((p)) & (x))
+#define DWORD_REG_BITS_IS_ON(x,p) (readl((p)) & (x))
+
+#define BYTE_REG_BITS_OFF(x,p) do { writeb(readb((p)) & (~(x)),(p));} while (0)
+#define WORD_REG_BITS_OFF(x,p) do { writew(readw((p)) & (~(x)),(p));} while (0)
+#define DWORD_REG_BITS_OFF(x,p) do { writel(readl((p)) & (~(x)),(p));} while (0)
+
+#define BYTE_REG_BITS_SET(x,m,p) do { writeb( (readb((p)) & (~(m))) |(x),(p));} while (0)
+#define WORD_REG_BITS_SET(x,m,p) do { writew( (readw((p)) & (~(m))) |(x),(p));} while (0)
+#define DWORD_REG_BITS_SET(x,m,p) do { writel( (readl((p)) & (~(m)))|(x),(p));} while (0)
+
+#define VAR_USED(p) do {(p)=(p);} while (0)
+
+/*
+ * Purpose: Structures for MAX RX/TX descriptors.
+ */
+
+
+#define B_OWNED_BY_CHIP 1
+#define B_OWNED_BY_HOST 0
+
+/*
+ * Bits in the RSR0 register
+ */
+
+#define RSR_DETAG 0x0080
+#define RSR_SNTAG 0x0040
+#define RSR_RXER 0x0020
+#define RSR_RL 0x0010
+#define RSR_CE 0x0008
+#define RSR_FAE 0x0004
+#define RSR_CRC 0x0002
+#define RSR_VIDM 0x0001
+
+/*
+ * Bits in the RSR1 register
+ */
+
+#define RSR_RXOK 0x8000 // rx OK
+#define RSR_PFT 0x4000 // Perfect filtering address match
+#define RSR_MAR 0x2000 // MAC accept multicast address packet
+#define RSR_BAR 0x1000 // MAC accept broadcast address packet
+#define RSR_PHY 0x0800 // MAC accept physical address packet
+#define RSR_VTAG 0x0400 // 802.1p/1q tagging packet indicator
+#define RSR_STP 0x0200 // start of packet
+#define RSR_EDP 0x0100 // end of packet
+
+/*
+ * Bits in the RSR1 register
+ */
+
+#define RSR1_RXOK 0x80 // rx OK
+#define RSR1_PFT 0x40 // Perfect filtering address match
+#define RSR1_MAR 0x20 // MAC accept multicast address packet
+#define RSR1_BAR 0x10 // MAC accept broadcast address packet
+#define RSR1_PHY 0x08 // MAC accept physical address packet
+#define RSR1_VTAG 0x04 // 802.1p/1q tagging packet indicator
+#define RSR1_STP 0x02 // start of packet
+#define RSR1_EDP 0x01 // end of packet
+
+/*
+ * Bits in the CSM register
+ */
+
+#define CSM_IPOK 0x40 //IP Checkusm validatiaon ok
+#define CSM_TUPOK 0x20 //TCP/UDP Checkusm validatiaon ok
+#define CSM_FRAG 0x10 //Fragment IP datagram
+#define CSM_IPKT 0x04 //Received an IP packet
+#define CSM_TCPKT 0x02 //Received a TCP packet
+#define CSM_UDPKT 0x01 //Received a UDP packet
+
+/*
+ * Bits in the TSR0 register
+ */
+
+#define TSR0_ABT 0x0080 // Tx abort because of excessive collision
+#define TSR0_OWT 0x0040 // Jumbo frame Tx abort
+#define TSR0_OWC 0x0020 // Out of window collision
+#define TSR0_COLS 0x0010 // experience collision in this transmit event
+#define TSR0_NCR3 0x0008 // collision retry counter[3]
+#define TSR0_NCR2 0x0004 // collision retry counter[2]
+#define TSR0_NCR1 0x0002 // collision retry counter[1]
+#define TSR0_NCR0 0x0001 // collision retry counter[0]
+#define TSR0_TERR 0x8000 //
+#define TSR0_FDX 0x4000 // current transaction is serviced by full duplex mode
+#define TSR0_GMII 0x2000 // current transaction is serviced by GMII mode
+#define TSR0_LNKFL 0x1000 // packet serviced during link down
+#define TSR0_SHDN 0x0400 // shutdown case
+#define TSR0_CRS 0x0200 // carrier sense lost
+#define TSR0_CDH 0x0100 // AQE test fail (CD heartbeat)
+
+/*
+ * Bits in the TSR1 register
+ */
+
+#define TSR1_TERR 0x80 //
+#define TSR1_FDX 0x40 // current transaction is serviced by full duplex mode
+#define TSR1_GMII 0x20 // current transaction is serviced by GMII mode
+#define TSR1_LNKFL 0x10 // packet serviced during link down
+#define TSR1_SHDN 0x04 // shutdown case
+#define TSR1_CRS 0x02 // carrier sense lost
+#define TSR1_CDH 0x01 // AQE test fail (CD heartbeat)
+
+//
+// Bits in the TCR0 register
+//
+#define TCR0_TIC 0x80 // assert interrupt immediately while descriptor has been send complete
+#define TCR0_PIC 0x40 // priority interrupt request, INA# is issued over adaptive interrupt scheme
+#define TCR0_VETAG 0x20 // enable VLAN tag
+#define TCR0_IPCK 0x10 // request IP checksum calculation.
+#define TCR0_UDPCK 0x08 // request UDP checksum calculation.
+#define TCR0_TCPCK 0x04 // request TCP checksum calculation.
+#define TCR0_JMBO 0x02 // indicate a jumbo packet in GMAC side
+#define TCR0_CRC 0x01 // disable CRC generation
+
+#define TCPLS_NORMAL 3
+#define TCPLS_START 2
+#define TCPLS_END 1
+#define TCPLS_MED 0
+
+
+// max transmit or receive buffer size
+#define CB_RX_BUF_SIZE 2048UL // max buffer size
+ // NOTE: must be multiple of 4
+
+#define CB_MAX_RD_NUM 512 // MAX # of RD
+#define CB_MAX_TD_NUM 256 // MAX # of TD
+
+#define CB_INIT_RD_NUM_3119 128 // init # of RD, for setup VT3119
+#define CB_INIT_TD_NUM_3119 64 // init # of TD, for setup VT3119
+
+#define CB_INIT_RD_NUM 128 // init # of RD, for setup default
+#define CB_INIT_TD_NUM 64 // init # of TD, for setup default
+
+// for 3119
+#define CB_TD_RING_NUM 4 // # of TD rings.
+#define CB_MAX_SEG_PER_PKT 7 // max data seg per packet (Tx)
+
+
+/*
+ * If collisions excess 15 times , tx will abort, and
+ * if tx fifo underflow, tx will fail
+ * we should try to resend it
+ */
+
+#define CB_MAX_TX_ABORT_RETRY 3
+
+/*
+ * Receive descriptor
+ */
+
+struct rdesc0 {
+ u16 RSR; /* Receive status */
+ u16 len:14; /* Received packet length */
+ u16 reserved:1;
+ u16 owner:1; /* Who owns this buffer ? */
+};
+
+struct rdesc1 {
+ u16 PQTAG;
+ u8 CSM;
+ u8 IPKT;
+};
+
+struct rx_desc {
+ struct rdesc0 rdesc0;
+ struct rdesc1 rdesc1;
+ u32 pa_low; /* Low 32 bit PCI address */
+ u16 pa_high; /* Next 16 bit PCI address (48 total) */
+ u16 len:15; /* Frame size */
+ u16 inten:1; /* Enable interrupt */
+} __attribute__ ((__packed__));
+
+/*
+ * Transmit descriptor
+ */
+
+struct tdesc0 {
+ u16 TSR; /* Transmit status register */
+ u16 pktsize:14; /* Size of frame */
+ u16 reserved:1;
+ u16 owner:1; /* Who owns the buffer */
+};
+
+struct pqinf { /* Priority queue info */
+ u16 VID:12;
+ u16 CFI:1;
+ u16 priority:3;
+} __attribute__ ((__packed__));
+
+struct tdesc1 {
+ struct pqinf pqinf;
+ u8 TCR;
+ u8 TCPLS:2;
+ u8 reserved:2;
+ u8 CMDZ:4;
+} __attribute__ ((__packed__));
+
+struct td_buf {
+ u32 pa_low;
+ u16 pa_high;
+ u16 bufsize:14;
+ u16 reserved:1;
+ u16 queue:1;
+} __attribute__ ((__packed__));
+
+struct tx_desc {
+ struct tdesc0 tdesc0;
+ struct tdesc1 tdesc1;
+ struct td_buf td_buf[7];
+};
+
+#ifdef LINUX
+struct velocity_rd_info {
+ struct sk_buff *skb;
+ dma_addr_t skb_dma;
+};
+
+
+/**
+ * alloc_rd_info - allocate an rd info block
+ *
+ * Alocate and initialize a receive info structure used for keeping
+ * track of kernel side information related to each receive
+ * descriptor we are using
+ */
+
+static inline struct velocity_rd_info *alloc_rd_info(void)
+{
+ struct velocity_rd_info *ptr;
+ if ((ptr =
+ kmalloc(sizeof(struct velocity_rd_info), GFP_ATOMIC)) == NULL)
+ return NULL;
+ else {
+ memset(ptr, 0, sizeof(struct velocity_rd_info));
+ return ptr;
+ }
+}
+
+/*
+ * Used to track transmit side buffers.
+ */
+
+struct velocity_td_info {
+ struct sk_buff *skb;
+ u8 *buf;
+ int nskb_dma;
+ dma_addr_t skb_dma[7];
+ dma_addr_t buf_dma;
+};
+
+#endif
+enum {
+ OWNED_BY_HOST = 0,
+ OWNED_BY_NIC = 1
+} velocity_owner;
+
+
+/*
+ * MAC registers and macros.
+ */
+
+
+#define MCAM_SIZE 64
+#define VCAM_SIZE 64
+#define TX_QUEUE_NO 4
+
+#define MAX_HW_MIB_COUNTER 32
+#define VELOCITY_MIN_MTU (1514-14)
+#define VELOCITY_MAX_MTU (9000)
+
+/*
+ * Registers in the MAC
+ */
+
+#define MAC_REG_PAR 0x00 // physical address
+#define MAC_REG_RCR 0x06
+#define MAC_REG_TCR 0x07
+#define MAC_REG_CR0_SET 0x08
+#define MAC_REG_CR1_SET 0x09
+#define MAC_REG_CR2_SET 0x0A
+#define MAC_REG_CR3_SET 0x0B
+#define MAC_REG_CR0_CLR 0x0C
+#define MAC_REG_CR1_CLR 0x0D
+#define MAC_REG_CR2_CLR 0x0E
+#define MAC_REG_CR3_CLR 0x0F
+#define MAC_REG_MAR 0x10
+#define MAC_REG_CAM 0x10
+#define MAC_REG_DEC_BASE_HI 0x18
+#define MAC_REG_DBF_BASE_HI 0x1C
+#define MAC_REG_ISR_CTL 0x20
+#define MAC_REG_ISR_HOTMR 0x20
+#define MAC_REG_ISR_TSUPTHR 0x20
+#define MAC_REG_ISR_RSUPTHR 0x20
+#define MAC_REG_ISR_CTL1 0x21
+#define MAC_REG_TXE_SR 0x22
+#define MAC_REG_RXE_SR 0x23
+#define MAC_REG_ISR 0x24
+#define MAC_REG_ISR0 0x24
+#define MAC_REG_ISR1 0x25
+#define MAC_REG_ISR2 0x26
+#define MAC_REG_ISR3 0x27
+#define MAC_REG_IMR 0x28
+#define MAC_REG_IMR0 0x28
+#define MAC_REG_IMR1 0x29
+#define MAC_REG_IMR2 0x2A
+#define MAC_REG_IMR3 0x2B
+#define MAC_REG_TDCSR_SET 0x30
+#define MAC_REG_RDCSR_SET 0x32
+#define MAC_REG_TDCSR_CLR 0x34
+#define MAC_REG_RDCSR_CLR 0x36
+#define MAC_REG_RDBASE_LO 0x38
+#define MAC_REG_RDINDX 0x3C
+#define MAC_REG_TDBASE_LO 0x40
+#define MAC_REG_RDCSIZE 0x50
+#define MAC_REG_TDCSIZE 0x52
+#define MAC_REG_TDINDX 0x54
+#define MAC_REG_TDIDX0 0x54
+#define MAC_REG_TDIDX1 0x56
+#define MAC_REG_TDIDX2 0x58
+#define MAC_REG_TDIDX3 0x5A
+#define MAC_REG_PAUSE_TIMER 0x5C
+#define MAC_REG_RBRDU 0x5E
+#define MAC_REG_FIFO_TEST0 0x60
+#define MAC_REG_FIFO_TEST1 0x64
+#define MAC_REG_CAMADDR 0x68
+#define MAC_REG_CAMCR 0x69
+#define MAC_REG_GFTEST 0x6A
+#define MAC_REG_FTSTCMD 0x6B
+#define MAC_REG_MIICFG 0x6C
+#define MAC_REG_MIISR 0x6D
+#define MAC_REG_PHYSR0 0x6E
+#define MAC_REG_PHYSR1 0x6F
+#define MAC_REG_MIICR 0x70
+#define MAC_REG_MIIADR 0x71
+#define MAC_REG_MIIDATA 0x72
+#define MAC_REG_SOFT_TIMER0 0x74
+#define MAC_REG_SOFT_TIMER1 0x76
+#define MAC_REG_CFGA 0x78
+#define MAC_REG_CFGB 0x79
+#define MAC_REG_CFGC 0x7A
+#define MAC_REG_CFGD 0x7B
+#define MAC_REG_DCFG0 0x7C
+#define MAC_REG_DCFG1 0x7D
+#define MAC_REG_MCFG0 0x7E
+#define MAC_REG_MCFG1 0x7F
+
+#define MAC_REG_TBIST 0x80
+#define MAC_REG_RBIST 0x81
+#define MAC_REG_PMCC 0x82
+#define MAC_REG_STICKHW 0x83
+#define MAC_REG_MIBCR 0x84
+#define MAC_REG_EERSV 0x85
+#define MAC_REG_REVID 0x86
+#define MAC_REG_MIBREAD 0x88
+#define MAC_REG_BPMA 0x8C
+#define MAC_REG_EEWR_DATA 0x8C
+#define MAC_REG_BPMD_WR 0x8F
+#define MAC_REG_BPCMD 0x90
+#define MAC_REG_BPMD_RD 0x91
+#define MAC_REG_EECHKSUM 0x92
+#define MAC_REG_EECSR 0x93
+#define MAC_REG_EERD_DATA 0x94
+#define MAC_REG_EADDR 0x96
+#define MAC_REG_EMBCMD 0x97
+#define MAC_REG_JMPSR0 0x98
+#define MAC_REG_JMPSR1 0x99
+#define MAC_REG_JMPSR2 0x9A
+#define MAC_REG_JMPSR3 0x9B
+#define MAC_REG_CHIPGSR 0x9C
+#define MAC_REG_TESTCFG 0x9D
+#define MAC_REG_DEBUG 0x9E
+#define MAC_REG_CHIPGCR 0x9F
+#define MAC_REG_WOLCR0_SET 0xA0
+#define MAC_REG_WOLCR1_SET 0xA1
+#define MAC_REG_PWCFG_SET 0xA2
+#define MAC_REG_WOLCFG_SET 0xA3
+#define MAC_REG_WOLCR0_CLR 0xA4
+#define MAC_REG_WOLCR1_CLR 0xA5
+#define MAC_REG_PWCFG_CLR 0xA6
+#define MAC_REG_WOLCFG_CLR 0xA7
+#define MAC_REG_WOLSR0_SET 0xA8
+#define MAC_REG_WOLSR1_SET 0xA9
+#define MAC_REG_WOLSR0_CLR 0xAC
+#define MAC_REG_WOLSR1_CLR 0xAD
+#define MAC_REG_PATRN_CRC0 0xB0
+#define MAC_REG_PATRN_CRC1 0xB2
+#define MAC_REG_PATRN_CRC2 0xB4
+#define MAC_REG_PATRN_CRC3 0xB6
+#define MAC_REG_PATRN_CRC4 0xB8
+#define MAC_REG_PATRN_CRC5 0xBA
+#define MAC_REG_PATRN_CRC6 0xBC
+#define MAC_REG_PATRN_CRC7 0xBE
+#define MAC_REG_BYTEMSK0_0 0xC0
+#define MAC_REG_BYTEMSK0_1 0xC4
+#define MAC_REG_BYTEMSK0_2 0xC8
+#define MAC_REG_BYTEMSK0_3 0xCC
+#define MAC_REG_BYTEMSK1_0 0xD0
+#define MAC_REG_BYTEMSK1_1 0xD4
+#define MAC_REG_BYTEMSK1_2 0xD8
+#define MAC_REG_BYTEMSK1_3 0xDC
+#define MAC_REG_BYTEMSK2_0 0xE0
+#define MAC_REG_BYTEMSK2_1 0xE4
+#define MAC_REG_BYTEMSK2_2 0xE8
+#define MAC_REG_BYTEMSK2_3 0xEC
+#define MAC_REG_BYTEMSK3_0 0xF0
+#define MAC_REG_BYTEMSK3_1 0xF4
+#define MAC_REG_BYTEMSK3_2 0xF8
+#define MAC_REG_BYTEMSK3_3 0xFC
+
+/*
+ * Bits in the RCR register
+ */
+
+#define RCR_AS 0x80
+#define RCR_AP 0x40
+#define RCR_AL 0x20
+#define RCR_PROM 0x10
+#define RCR_AB 0x08
+#define RCR_AM 0x04
+#define RCR_AR 0x02
+#define RCR_SEP 0x01
+
+/*
+ * Bits in the TCR register
+ */
+
+#define TCR_TB2BDIS 0x80
+#define TCR_COLTMC1 0x08
+#define TCR_COLTMC0 0x04
+#define TCR_LB1 0x02 /* loopback[1] */
+#define TCR_LB0 0x01 /* loopback[0] */
+
+/*
+ * Bits in the CR0 register
+ */
+
+#define CR0_TXON 0x00000008UL
+#define CR0_RXON 0x00000004UL
+#define CR0_STOP 0x00000002UL /* stop MAC, default = 1 */
+#define CR0_STRT 0x00000001UL /* start MAC */
+#define CR0_SFRST 0x00008000UL /* software reset */
+#define CR0_TM1EN 0x00004000UL
+#define CR0_TM0EN 0x00002000UL
+#define CR0_DPOLL 0x00000800UL /* disable rx/tx auto polling */
+#define CR0_DISAU 0x00000100UL
+#define CR0_XONEN 0x00800000UL
+#define CR0_FDXTFCEN 0x00400000UL /* full-duplex TX flow control enable */
+#define CR0_FDXRFCEN 0x00200000UL /* full-duplex RX flow control enable */
+#define CR0_HDXFCEN 0x00100000UL /* half-duplex flow control enable */
+#define CR0_XHITH1 0x00080000UL /* TX XON high threshold 1 */
+#define CR0_XHITH0 0x00040000UL /* TX XON high threshold 0 */
+#define CR0_XLTH1 0x00020000UL /* TX pause frame low threshold 1 */
+#define CR0_XLTH0 0x00010000UL /* TX pause frame low threshold 0 */
+#define CR0_GSPRST 0x80000000UL
+#define CR0_FORSRST 0x40000000UL
+#define CR0_FPHYRST 0x20000000UL
+#define CR0_DIAG 0x10000000UL
+#define CR0_INTPCTL 0x04000000UL
+#define CR0_GINTMSK1 0x02000000UL
+#define CR0_GINTMSK0 0x01000000UL
+
+/*
+ * Bits in the CR1 register
+ */
+
+#define CR1_SFRST 0x80 /* software reset */
+#define CR1_TM1EN 0x40
+#define CR1_TM0EN 0x20
+#define CR1_DPOLL 0x08 /* disable rx/tx auto polling */
+#define CR1_DISAU 0x01
+
+/*
+ * Bits in the CR2 register
+ */
+
+#define CR2_XONEN 0x80
+#define CR2_FDXTFCEN 0x40 /* full-duplex TX flow control enable */
+#define CR2_FDXRFCEN 0x20 /* full-duplex RX flow control enable */
+#define CR2_HDXFCEN 0x10 /* half-duplex flow control enable */
+#define CR2_XHITH1 0x08 /* TX XON high threshold 1 */
+#define CR2_XHITH0 0x04 /* TX XON high threshold 0 */
+#define CR2_XLTH1 0x02 /* TX pause frame low threshold 1 */
+#define CR2_XLTH0 0x01 /* TX pause frame low threshold 0 */
+
+/*
+ * Bits in the CR3 register
+ */
+
+#define CR3_GSPRST 0x80
+#define CR3_FORSRST 0x40
+#define CR3_FPHYRST 0x20
+#define CR3_DIAG 0x10
+#define CR3_INTPCTL 0x04
+#define CR3_GINTMSK1 0x02
+#define CR3_GINTMSK0 0x01
+
+#define ISRCTL_UDPINT 0x8000
+#define ISRCTL_TSUPDIS 0x4000
+#define ISRCTL_RSUPDIS 0x2000
+#define ISRCTL_PMSK1 0x1000
+#define ISRCTL_PMSK0 0x0800
+#define ISRCTL_INTPD 0x0400
+#define ISRCTL_HCRLD 0x0200
+#define ISRCTL_SCRLD 0x0100
+
+/*
+ * Bits in the ISR_CTL1 register
+ */
+
+#define ISRCTL1_UDPINT 0x80
+#define ISRCTL1_TSUPDIS 0x40
+#define ISRCTL1_RSUPDIS 0x20
+#define ISRCTL1_PMSK1 0x10
+#define ISRCTL1_PMSK0 0x08
+#define ISRCTL1_INTPD 0x04
+#define ISRCTL1_HCRLD 0x02
+#define ISRCTL1_SCRLD 0x01
+
+/*
+ * Bits in the TXE_SR register
+ */
+
+#define TXESR_TFDBS 0x08
+#define TXESR_TDWBS 0x04
+#define TXESR_TDRBS 0x02
+#define TXESR_TDSTR 0x01
+
+/*
+ * Bits in the RXE_SR register
+ */
+
+#define RXESR_RFDBS 0x08
+#define RXESR_RDWBS 0x04
+#define RXESR_RDRBS 0x02
+#define RXESR_RDSTR 0x01
+
+/*
+ * Bits in the ISR register
+ */
+
+#define ISR_ISR3 0x80000000UL
+#define ISR_ISR2 0x40000000UL
+#define ISR_ISR1 0x20000000UL
+#define ISR_ISR0 0x10000000UL
+#define ISR_TXSTLI 0x02000000UL
+#define ISR_RXSTLI 0x01000000UL
+#define ISR_HFLD 0x00800000UL
+#define ISR_UDPI 0x00400000UL
+#define ISR_MIBFI 0x00200000UL
+#define ISR_SHDNI 0x00100000UL
+#define ISR_PHYI 0x00080000UL
+#define ISR_PWEI 0x00040000UL
+#define ISR_TMR1I 0x00020000UL
+#define ISR_TMR0I 0x00010000UL
+#define ISR_SRCI 0x00008000UL
+#define ISR_LSTPEI 0x00004000UL
+#define ISR_LSTEI 0x00002000UL
+#define ISR_OVFI 0x00001000UL
+#define ISR_FLONI 0x00000800UL
+#define ISR_RACEI 0x00000400UL
+#define ISR_TXWB1I 0x00000200UL
+#define ISR_TXWB0I 0x00000100UL
+#define ISR_PTX3I 0x00000080UL
+#define ISR_PTX2I 0x00000040UL
+#define ISR_PTX1I 0x00000020UL
+#define ISR_PTX0I 0x00000010UL
+#define ISR_PTXI 0x00000008UL
+#define ISR_PRXI 0x00000004UL
+#define ISR_PPTXI 0x00000002UL
+#define ISR_PPRXI 0x00000001UL
+
+/*
+ * Bits in the IMR register
+ */
+
+#define IMR_TXSTLM 0x02000000UL
+#define IMR_UDPIM 0x00400000UL
+#define IMR_MIBFIM 0x00200000UL
+#define IMR_SHDNIM 0x00100000UL
+#define IMR_PHYIM 0x00080000UL
+#define IMR_PWEIM 0x00040000UL
+#define IMR_TMR1IM 0x00020000UL
+#define IMR_TMR0IM 0x00010000UL
+
+#define IMR_SRCIM 0x00008000UL
+#define IMR_LSTPEIM 0x00004000UL
+#define IMR_LSTEIM 0x00002000UL
+#define IMR_OVFIM 0x00001000UL
+#define IMR_FLONIM 0x00000800UL
+#define IMR_RACEIM 0x00000400UL
+#define IMR_TXWB1IM 0x00000200UL
+#define IMR_TXWB0IM 0x00000100UL
+
+#define IMR_PTX3IM 0x00000080UL
+#define IMR_PTX2IM 0x00000040UL
+#define IMR_PTX1IM 0x00000020UL
+#define IMR_PTX0IM 0x00000010UL
+#define IMR_PTXIM 0x00000008UL
+#define IMR_PRXIM 0x00000004UL
+#define IMR_PPTXIM 0x00000002UL
+#define IMR_PPRXIM 0x00000001UL
+
+/* 0x0013FB0FUL = initial value of IMR */
+
+#define INT_MASK_DEF ( IMR_PPTXIM|IMR_PPRXIM| IMR_PTXIM|IMR_PRXIM | \
+ IMR_PWEIM|IMR_TXWB0IM|IMR_TXWB1IM|IMR_FLONIM| \
+ IMR_OVFIM|IMR_LSTEIM|IMR_LSTPEIM|IMR_SRCIM|IMR_MIBFIM|\
+ IMR_SHDNIM |IMR_TMR1IM|IMR_TMR0IM|IMR_TXSTLM )
+
+/*
+ * Bits in the TDCSR0/1, RDCSR0 register
+ */
+
+#define TRDCSR_DEAD 0x0008
+#define TRDCSR_WAK 0x0004
+#define TRDCSR_ACT 0x0002
+#define TRDCSR_RUN 0x0001
+
+/*
+ * Bits in the CAMADDR register
+ */
+
+#define CAMADDR_CAMEN 0x80
+#define CAMADDR_VCAMSL 0x40
+
+/*
+ * Bits in the CAMCR register
+ */
+
+#define CAMCR_PS1 0x80
+#define CAMCR_PS0 0x40
+#define CAMCR_AITRPKT 0x20
+#define CAMCR_AITR16 0x10
+#define CAMCR_CAMRD 0x08
+#define CAMCR_CAMWR 0x04
+#define CAMCR_PS_CAM_MASK 0x40
+#define CAMCR_PS_CAM_DATA 0x80
+#define CAMCR_PS_MAR 0x00
+
+/*
+ * Bits in the MIICFG register
+ */
+
+#define MIICFG_MPO1 0x80
+#define MIICFG_MPO0 0x40
+#define MIICFG_MFDC 0x20
+
+/*
+ * Bits in the MIISR register
+ */
+
+#define MIISR_MIDLE 0x80
+
+/*
+ * Bits in the PHYSR0 register
+ */
+
+#define PHYSR0_PHYRST 0x80
+#define PHYSR0_LINKGD 0x40
+#define PHYSR0_FDPX 0x10
+#define PHYSR0_SPDG 0x08
+#define PHYSR0_SPD10 0x04
+#define PHYSR0_RXFLC 0x02
+#define PHYSR0_TXFLC 0x01
+
+/*
+ * Bits in the PHYSR1 register
+ */
+
+#define PHYSR1_PHYTBI 0x01
+
+/*
+ * Bits in the MIICR register
+ */
+
+#define MIICR_MAUTO 0x80
+#define MIICR_RCMD 0x40
+#define MIICR_WCMD 0x20
+#define MIICR_MDPM 0x10
+#define MIICR_MOUT 0x08
+#define MIICR_MDO 0x04
+#define MIICR_MDI 0x02
+#define MIICR_MDC 0x01
+
+/*
+ * Bits in the MIIADR register
+ */
+
+#define MIIADR_SWMPL 0x80
+
+/*
+ * Bits in the CFGA register
+ */
+
+#define CFGA_PMHCTG 0x08
+#define CFGA_GPIO1PD 0x04
+#define CFGA_ABSHDN 0x02
+#define CFGA_PACPI 0x01
+
+/*
+ * Bits in the CFGB register
+ */
+
+#define CFGB_GTCKOPT 0x80
+#define CFGB_MIIOPT 0x40
+#define CFGB_CRSEOPT 0x20
+#define CFGB_OFSET 0x10
+#define CFGB_CRANDOM 0x08
+#define CFGB_CAP 0x04
+#define CFGB_MBA 0x02
+#define CFGB_BAKOPT 0x01
+
+/*
+ * Bits in the CFGC register
+ */
+
+#define CFGC_EELOAD 0x80
+#define CFGC_BROPT 0x40
+#define CFGC_DLYEN 0x20
+#define CFGC_DTSEL 0x10
+#define CFGC_BTSEL 0x08
+#define CFGC_BPS2 0x04 /* bootrom select[2] */
+#define CFGC_BPS1 0x02 /* bootrom select[1] */
+#define CFGC_BPS0 0x01 /* bootrom select[0] */
+
+/*
+ * Bits in the CFGD register
+ */
+
+#define CFGD_IODIS 0x80
+#define CFGD_MSLVDACEN 0x40
+#define CFGD_CFGDACEN 0x20
+#define CFGD_PCI64EN 0x10
+#define CFGD_HTMRL4 0x08
+
+/*
+ * Bits in the DCFG1 register
+ */
+
+#define DCFG_XMWI 0x8000
+#define DCFG_XMRM 0x4000
+#define DCFG_XMRL 0x2000
+#define DCFG_PERDIS 0x1000
+#define DCFG_MRWAIT 0x0400
+#define DCFG_MWWAIT 0x0200
+#define DCFG_LATMEN 0x0100
+
+/*
+ * Bits in the MCFG0 register
+ */
+
+#define MCFG_RXARB 0x0080
+#define MCFG_RFT1 0x0020
+#define MCFG_RFT0 0x0010
+#define MCFG_LOWTHOPT 0x0008
+#define MCFG_PQEN 0x0004
+#define MCFG_RTGOPT 0x0002
+#define MCFG_VIDFR 0x0001
+
+/*
+ * Bits in the MCFG1 register
+ */
+
+#define MCFG_TXARB 0x8000
+#define MCFG_TXQBK1 0x0800
+#define MCFG_TXQBK0 0x0400
+#define MCFG_TXQNOBK 0x0200
+#define MCFG_SNAPOPT 0x0100
+
+/*
+ * Bits in the PMCC register
+ */
+
+#define PMCC_DSI 0x80
+#define PMCC_D2_DIS 0x40
+#define PMCC_D1_DIS 0x20
+#define PMCC_D3C_EN 0x10
+#define PMCC_D3H_EN 0x08
+#define PMCC_D2_EN 0x04
+#define PMCC_D1_EN 0x02
+#define PMCC_D0_EN 0x01
+
+/*
+ * Bits in STICKHW
+ */
+
+#define STICKHW_SWPTAG 0x10
+#define STICKHW_WOLSR 0x08
+#define STICKHW_WOLEN 0x04
+#define STICKHW_DS1 0x02 /* R/W by software/cfg cycle */
+#define STICKHW_DS0 0x01 /* suspend well DS write port */
+
+/*
+ * Bits in the MIBCR register
+ */
+
+#define MIBCR_MIBISTOK 0x80
+#define MIBCR_MIBISTGO 0x40
+#define MIBCR_MIBINC 0x20
+#define MIBCR_MIBHI 0x10
+#define MIBCR_MIBFRZ 0x08
+#define MIBCR_MIBFLSH 0x04
+#define MIBCR_MPTRINI 0x02
+#define MIBCR_MIBCLR 0x01
+
+/*
+ * Bits in the EERSV register
+ */
+
+#define EERSV_BOOT_RPL ((u8) 0x01) /* Boot method selection for VT6110 */
+
+#define EERSV_BOOT_MASK ((u8) 0x06)
+#define EERSV_BOOT_INT19 ((u8) 0x00)
+#define EERSV_BOOT_INT18 ((u8) 0x02)
+#define EERSV_BOOT_LOCAL ((u8) 0x04)
+#define EERSV_BOOT_BEV ((u8) 0x06)
+
+
+/*
+ * Bits in BPCMD
+ */
+
+#define BPCMD_BPDNE 0x80
+#define BPCMD_EBPWR 0x02
+#define BPCMD_EBPRD 0x01
+
+/*
+ * Bits in the EECSR register
+ */
+
+#define EECSR_EMBP 0x40 /* eeprom embeded programming */
+#define EECSR_RELOAD 0x20 /* eeprom content reload */
+#define EECSR_DPM 0x10 /* eeprom direct programming */
+#define EECSR_ECS 0x08 /* eeprom CS pin */
+#define EECSR_ECK 0x04 /* eeprom CK pin */
+#define EECSR_EDI 0x02 /* eeprom DI pin */
+#define EECSR_EDO 0x01 /* eeprom DO pin */
+
+/*
+ * Bits in the EMBCMD register
+ */
+
+#define EMBCMD_EDONE 0x80
+#define EMBCMD_EWDIS 0x08
+#define EMBCMD_EWEN 0x04
+#define EMBCMD_EWR 0x02
+#define EMBCMD_ERD 0x01
+
+/*
+ * Bits in TESTCFG register
+ */
+
+#define TESTCFG_HBDIS 0x80
+
+/*
+ * Bits in CHIPGCR register
+ */
+
+#define CHIPGCR_FCGMII 0x80
+#define CHIPGCR_FCFDX 0x40
+#define CHIPGCR_FCRESV 0x20
+#define CHIPGCR_FCMODE 0x10
+#define CHIPGCR_LPSOPT 0x08
+#define CHIPGCR_TM1US 0x04
+#define CHIPGCR_TM0US 0x02
+#define CHIPGCR_PHYINTEN 0x01
+
+/*
+ * Bits in WOLCR0
+ */
+
+#define WOLCR_MSWOLEN7 0x0080 /* enable pattern match filtering */
+#define WOLCR_MSWOLEN6 0x0040
+#define WOLCR_MSWOLEN5 0x0020
+#define WOLCR_MSWOLEN4 0x0010
+#define WOLCR_MSWOLEN3 0x0008
+#define WOLCR_MSWOLEN2 0x0004
+#define WOLCR_MSWOLEN1 0x0002
+#define WOLCR_MSWOLEN0 0x0001
+#define WOLCR_ARP_EN 0x0001
+
+/*
+ * Bits in WOLCR1
+ */
+
+#define WOLCR_LINKOFF_EN 0x0800 /* link off detected enable */
+#define WOLCR_LINKON_EN 0x0400 /* link on detected enable */
+#define WOLCR_MAGIC_EN 0x0200 /* magic packet filter enable */
+#define WOLCR_UNICAST_EN 0x0100 /* unicast filter enable */
+
+
+/*
+ * Bits in PWCFG
+ */
+
+#define PWCFG_PHYPWOPT 0x80 /* internal MII I/F timing */
+#define PWCFG_PCISTICK 0x40 /* PCI sticky R/W enable */
+#define PWCFG_WOLTYPE 0x20 /* pulse(1) or button (0) */
+#define PWCFG_LEGCY_WOL 0x10
+#define PWCFG_PMCSR_PME_SR 0x08
+#define PWCFG_PMCSR_PME_EN 0x04 /* control by PCISTICK */
+#define PWCFG_LEGACY_WOLSR 0x02 /* Legacy WOL_SR shadow */
+#define PWCFG_LEGACY_WOLEN 0x01 /* Legacy WOL_EN shadow */
+
+/*
+ * Bits in WOLCFG
+ */
+
+#define WOLCFG_PMEOVR 0x80 /* for legacy use, force PMEEN always */
+#define WOLCFG_SAM 0x20 /* accept multicast case reset, default=0 */
+#define WOLCFG_SAB 0x10 /* accept broadcast case reset, default=0 */
+#define WOLCFG_SMIIACC 0x08 /* ?? */
+#define WOLCFG_SGENWH 0x02
+#define WOLCFG_PHYINTEN 0x01 /* 0:PHYINT trigger enable, 1:use internal MII
+ to report status change */
+/*
+ * Bits in WOLSR1
+ */
+
+#define WOLSR_LINKOFF_INT 0x0800
+#define WOLSR_LINKON_INT 0x0400
+#define WOLSR_MAGIC_INT 0x0200
+#define WOLSR_UNICAST_INT 0x0100
+
+/*
+ * Ethernet address filter type
+ */
+
+#define PKT_TYPE_NONE 0x0000 /* Turn off receiver */
+#define PKT_TYPE_DIRECTED 0x0001 /* obselete, directed address is always accepted */
+#define PKT_TYPE_MULTICAST 0x0002
+#define PKT_TYPE_ALL_MULTICAST 0x0004
+#define PKT_TYPE_BROADCAST 0x0008
+#define PKT_TYPE_PROMISCUOUS 0x0020
+#define PKT_TYPE_LONG 0x2000 /* NOTE.... the definition of LONG is >2048 bytes in our chip */
+#define PKT_TYPE_RUNT 0x4000
+#define PKT_TYPE_ERROR 0x8000 /* Accept error packets, e.g. CRC error */
+
+/*
+ * Loopback mode
+ */
+
+#define MAC_LB_NONE 0x00
+#define MAC_LB_INTERNAL 0x01
+#define MAC_LB_EXTERNAL 0x02
+
+/*
+ * Enabled mask value of irq
+ */
+
+#if defined(_SIM)
+#define IMR_MASK_VALUE 0x0033FF0FUL /* initial value of IMR
+ set IMR0 to 0x0F according to spec */
+
+#else
+#define IMR_MASK_VALUE 0x0013FB0FUL /* initial value of IMR
+ ignore MIBFI,RACEI to
+ reduce intr. frequency
+ NOTE.... do not enable NoBuf int mask at driver driver
+ when (1) NoBuf -> RxThreshold = SF
+ (2) OK -> RxThreshold = original value
+ */
+#endif
+
+/*
+ * Revision id
+ */
+
+#define REV_ID_VT3119_A0 0x00
+#define REV_ID_VT3119_A1 0x01
+#define REV_ID_VT3216_A0 0x10
+
+/*
+ * Max time out delay time
+ */
+
+#define W_MAX_TIMEOUT 0x0FFFU
+
+
+/*
+ * MAC registers as a structure. Cannot be directly accessed this
+ * way but generates offsets for readl/writel() calls
+ */
+
+struct mac_regs {
+ volatile u8 PAR[6]; /* 0x00 */
+ volatile u8 RCR;
+ volatile u8 TCR;
+
+ volatile u32 CR0Set; /* 0x08 */
+ volatile u32 CR0Clr; /* 0x0C */
+
+ volatile u8 MARCAM[8]; /* 0x10 */
+
+ volatile u32 DecBaseHi; /* 0x18 */
+ volatile u16 DbfBaseHi; /* 0x1C */
+ volatile u16 reserved_1E;
+
+ volatile u16 ISRCTL; /* 0x20 */
+ volatile u8 TXESR;
+ volatile u8 RXESR;
+
+ volatile u32 ISR; /* 0x24 */
+ volatile u32 IMR;
+
+ volatile u32 TDStatusPort; /* 0x2C */
+
+ volatile u16 TDCSRSet; /* 0x30 */
+ volatile u8 RDCSRSet;
+ volatile u8 reserved_33;
+ volatile u16 TDCSRClr;
+ volatile u8 RDCSRClr;
+ volatile u8 reserved_37;
+
+ volatile u32 RDBaseLo; /* 0x38 */
+ volatile u16 RDIdx; /* 0x3C */
+ volatile u16 reserved_3E;
+
+ volatile u32 TDBaseLo[4]; /* 0x40 */
+
+ volatile u16 RDCSize; /* 0x50 */
+ volatile u16 TDCSize; /* 0x52 */
+ volatile u16 TDIdx[4]; /* 0x54 */
+ volatile u16 tx_pause_timer; /* 0x5C */
+ volatile u16 RBRDU; /* 0x5E */
+
+ volatile u32 FIFOTest0; /* 0x60 */
+ volatile u32 FIFOTest1; /* 0x64 */
+
+ volatile u8 CAMADDR; /* 0x68 */
+ volatile u8 CAMCR; /* 0x69 */
+ volatile u8 GFTEST; /* 0x6A */
+ volatile u8 FTSTCMD; /* 0x6B */
+
+ volatile u8 MIICFG; /* 0x6C */
+ volatile u8 MIISR;
+ volatile u8 PHYSR0;
+ volatile u8 PHYSR1;
+ volatile u8 MIICR;
+ volatile u8 MIIADR;
+ volatile u16 MIIDATA;
+
+ volatile u16 SoftTimer0; /* 0x74 */
+ volatile u16 SoftTimer1;
+
+ volatile u8 CFGA; /* 0x78 */
+ volatile u8 CFGB;
+ volatile u8 CFGC;
+ volatile u8 CFGD;
+
+ volatile u16 DCFG; /* 0x7C */
+ volatile u16 MCFG;
+
+ volatile u8 TBIST; /* 0x80 */
+ volatile u8 RBIST;
+ volatile u8 PMCPORT;
+ volatile u8 STICKHW;
+
+ volatile u8 MIBCR; /* 0x84 */
+ volatile u8 reserved_85;
+ volatile u8 rev_id;
+ volatile u8 PORSTS;
+
+ volatile u32 MIBData; /* 0x88 */
+
+ volatile u16 EEWrData;
+
+ volatile u8 reserved_8E;
+ volatile u8 BPMDWr;
+ volatile u8 BPCMD;
+ volatile u8 BPMDRd;
+
+ volatile u8 EECHKSUM; /* 0x92 */
+ volatile u8 EECSR;
+
+ volatile u16 EERdData; /* 0x94 */
+ volatile u8 EADDR;
+ volatile u8 EMBCMD;
+
+
+ volatile u8 JMPSR0; /* 0x98 */
+ volatile u8 JMPSR1;
+ volatile u8 JMPSR2;
+ volatile u8 JMPSR3;
+ volatile u8 CHIPGSR; /* 0x9C */
+ volatile u8 TESTCFG;
+ volatile u8 DEBUG;
+ volatile u8 CHIPGCR;
+
+ volatile u16 WOLCRSet; /* 0xA0 */
+ volatile u8 PWCFGSet;
+ volatile u8 WOLCFGSet;
+
+ volatile u16 WOLCRClr; /* 0xA4 */
+ volatile u8 PWCFGCLR;
+ volatile u8 WOLCFGClr;
+
+ volatile u16 WOLSRSet; /* 0xA8 */
+ volatile u16 reserved_AA;
+
+ volatile u16 WOLSRClr; /* 0xAC */
+ volatile u16 reserved_AE;
+
+ volatile u16 PatternCRC[8]; /* 0xB0 */
+ volatile u32 ByteMask[4][4]; /* 0xC0 */
+} __attribute__ ((__packed__));
+
+
+enum hw_mib {
+ HW_MIB_ifRxAllPkts = 0,
+ HW_MIB_ifRxOkPkts,
+ HW_MIB_ifTxOkPkts,
+ HW_MIB_ifRxErrorPkts,
+ HW_MIB_ifRxRuntOkPkt,
+ HW_MIB_ifRxRuntErrPkt,
+ HW_MIB_ifRx64Pkts,
+ HW_MIB_ifTx64Pkts,
+ HW_MIB_ifRx65To127Pkts,
+ HW_MIB_ifTx65To127Pkts,
+ HW_MIB_ifRx128To255Pkts,
+ HW_MIB_ifTx128To255Pkts,
+ HW_MIB_ifRx256To511Pkts,
+ HW_MIB_ifTx256To511Pkts,
+ HW_MIB_ifRx512To1023Pkts,
+ HW_MIB_ifTx512To1023Pkts,
+ HW_MIB_ifRx1024To1518Pkts,
+ HW_MIB_ifTx1024To1518Pkts,
+ HW_MIB_ifTxEtherCollisions,
+ HW_MIB_ifRxPktCRCE,
+ HW_MIB_ifRxJumboPkts,
+ HW_MIB_ifTxJumboPkts,
+ HW_MIB_ifRxMacControlFrames,
+ HW_MIB_ifTxMacControlFrames,
+ HW_MIB_ifRxPktFAE,
+ HW_MIB_ifRxLongOkPkt,
+ HW_MIB_ifRxLongPktErrPkt,
+ HW_MIB_ifTXSQEErrors,
+ HW_MIB_ifRxNobuf,
+ HW_MIB_ifRxSymbolErrors,
+ HW_MIB_ifInRangeLengthErrors,
+ HW_MIB_ifLateCollisions,
+ HW_MIB_SIZE
+};
+
+enum chip_type {
+ CHIP_TYPE_VT6110 = 1,
+};
+
+struct velocity_info_tbl {
+ enum chip_type chip_id;
+ char *name;
+ int io_size;
+ int txqueue;
+ u32 flags;
+};
+
+static struct velocity_info_tbl *info;
+
+#define mac_hw_mibs_init(regs) {\
+ BYTE_REG_BITS_ON(MIBCR_MIBFRZ,&((regs)->MIBCR));\
+ BYTE_REG_BITS_ON(MIBCR_MIBCLR,&((regs)->MIBCR));\
+ do {}\
+ while (BYTE_REG_BITS_IS_ON(MIBCR_MIBCLR,&((regs)->MIBCR)));\
+ BYTE_REG_BITS_OFF(MIBCR_MIBFRZ,&((regs)->MIBCR));\
+}
+
+#define mac_read_isr(regs) readl(&((regs)->ISR))
+#define mac_write_isr(regs, x) writel((x),&((regs)->ISR))
+#define mac_clear_isr(regs) writel(0xffffffffL,&((regs)->ISR))
+
+#define mac_write_int_mask(mask, regs) writel((mask),&((regs)->IMR));
+#define mac_disable_int(regs) writel(CR0_GINTMSK1,&((regs)->CR0Clr))
+#define mac_enable_int(regs) writel(CR0_GINTMSK1,&((regs)->CR0Set))
+
+#define mac_hw_mibs_read(regs, MIBs) {\
+ int i;\
+ BYTE_REG_BITS_ON(MIBCR_MPTRINI,&((regs)->MIBCR));\
+ for (i=0;i<HW_MIB_SIZE;i++) {\
+ (MIBs)[i]=readl(&((regs)->MIBData));\
+ }\
+}
+
+#define mac_set_dma_length(regs, n) {\
+ BYTE_REG_BITS_SET((n),0x07,&((regs)->DCFG));\
+}
+
+#define mac_set_rx_thresh(regs, n) {\
+ BYTE_REG_BITS_SET((n),(MCFG_RFT0|MCFG_RFT1),&((regs)->MCFG));\
+}
+
+#define mac_rx_queue_run(regs) {\
+ writeb(TRDCSR_RUN, &((regs)->RDCSRSet));\
+}
+
+#define mac_rx_queue_wake(regs) {\
+ writeb(TRDCSR_WAK, &((regs)->RDCSRSet));\
+}
+
+#define mac_tx_queue_run(regs, n) {\
+ writew(TRDCSR_RUN<<((n)*4),&((regs)->TDCSRSet));\
+}
+
+#define mac_tx_queue_wake(regs, n) {\
+ writew(TRDCSR_WAK<<(n*4),&((regs)->TDCSRSet));\
+}
+
+#define mac_eeprom_reload(regs) {\
+ int i=0;\
+ BYTE_REG_BITS_ON(EECSR_RELOAD,&((regs)->EECSR));\
+ do {\
+ udelay(10);\
+ if (i++>0x1000) {\
+ break;\
+ }\
+ }while (BYTE_REG_BITS_IS_ON(EECSR_RELOAD,&((regs)->EECSR)));\
+}
+
+enum velocity_cam_type {
+ VELOCITY_VLAN_ID_CAM = 0,
+ VELOCITY_MULTICAST_CAM
+};
+
+/**
+ * mac_get_cam_mask - Read a CAM mask
+ * @regs: register block for this velocity
+ * @mask: buffer to store mask
+ * @cam_type: CAM to fetch
+ *
+ * Fetch the mask bits of the selected CAM and store them into the
+ * provided mask buffer.
+ */
+
+static inline void mac_get_cam_mask(struct mac_regs *regs, u8 * mask,
+ enum velocity_cam_type cam_type)
+{
+ int i;
+ /* Select CAM mask */
+ BYTE_REG_BITS_SET(CAMCR_PS_CAM_MASK, CAMCR_PS1 | CAMCR_PS0,
+ &regs->CAMCR);
+
+ if (cam_type == VELOCITY_VLAN_ID_CAM)
+ writeb(CAMADDR_VCAMSL, &regs->CAMADDR);
+ else
+ writeb(0, &regs->CAMADDR);
+
+ /* read mask */
+ for (i = 0; i < 8; i++)
+ *mask++ = readb(&(regs->MARCAM[i]));
+
+ /* disable CAMEN */
+ writeb(0, &regs->CAMADDR);
+
+ /* Select mar */
+ BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0,
+ &regs->CAMCR);
+
+}
+
+/**
+ * mac_set_cam_mask - Set a CAM mask
+ * @regs: register block for this velocity
+ * @mask: CAM mask to load
+ * @cam_type: CAM to store
+ *
+ * Store a new mask into a CAM
+ */
+
+static inline void mac_set_cam_mask(struct mac_regs *regs, u8 * mask,
+ enum velocity_cam_type cam_type)
+{
+ int i;
+ /* Select CAM mask */
+ BYTE_REG_BITS_SET(CAMCR_PS_CAM_MASK, CAMCR_PS1 | CAMCR_PS0,
+ &regs->CAMCR);
+
+ if (cam_type == VELOCITY_VLAN_ID_CAM)
+ writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL, &regs->CAMADDR);
+ else
+ writeb(CAMADDR_CAMEN, &regs->CAMADDR);
+
+ for (i = 0; i < 8; i++) {
+ writeb(*mask++, &(regs->MARCAM[i]));
+ }
+ /* disable CAMEN */
+ writeb(0, &regs->CAMADDR);
+
+ /* Select mar */
+ BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0,
+ &regs->CAMCR);
+}
+
+/**
+ * mac_set_cam - set CAM data
+ * @regs: register block of this velocity
+ * @idx: Cam index
+ * @addr: 2 or 6 bytes of CAM data
+ * @cam_type: CAM to load
+ *
+ * Load an address or vlan tag into a CAM
+ */
+
+static inline void mac_set_cam(struct mac_regs *regs, int idx, u8 * addr,
+ enum velocity_cam_type cam_type)
+{
+ int i;
+
+ /* Select CAM mask */
+ BYTE_REG_BITS_SET(CAMCR_PS_CAM_DATA, CAMCR_PS1 | CAMCR_PS0,
+ &regs->CAMCR);
+
+ idx &= (64 - 1);
+
+ if (cam_type == VELOCITY_VLAN_ID_CAM)
+ writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL | idx,
+ &regs->CAMADDR);
+ else
+ writeb(CAMADDR_CAMEN | idx, &regs->CAMADDR);
+
+ if (cam_type == VELOCITY_VLAN_ID_CAM)
+ writew(*((u16 *) addr), &regs->MARCAM[0]);
+ else {
+ for (i = 0; i < 6; i++) {
+ writeb(*addr++, &(regs->MARCAM[i]));
+ }
+ }
+ BYTE_REG_BITS_ON(CAMCR_CAMWR, &regs->CAMCR);
+
+ udelay(10);
+
+ writeb(0, &regs->CAMADDR);
+
+ /* Select mar */
+ BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0,
+ &regs->CAMCR);
+}
+
+/**
+ * mac_get_cam - fetch CAM data
+ * @regs: register block of this velocity
+ * @idx: Cam index
+ * @addr: buffer to hold up to 6 bytes of CAM data
+ * @cam_type: CAM to load
+ *
+ * Load an address or vlan tag from a CAM into the buffer provided by
+ * the caller. VLAN tags are 2 bytes the address cam entries are 6.
+ */
+
+static inline void mac_get_cam(struct mac_regs *regs, int idx, u8 * addr,
+ enum velocity_cam_type cam_type)
+{
+ int i;
+
+ /* Select CAM mask */
+ BYTE_REG_BITS_SET(CAMCR_PS_CAM_DATA, CAMCR_PS1 | CAMCR_PS0,
+ &regs->CAMCR);
+
+ idx &= (64 - 1);
+
+ if (cam_type == VELOCITY_VLAN_ID_CAM)
+ writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL | idx,
+ &regs->CAMADDR);
+ else
+ writeb(CAMADDR_CAMEN | idx, &regs->CAMADDR);
+
+ BYTE_REG_BITS_ON(CAMCR_CAMRD, &regs->CAMCR);
+
+ udelay(10);
+
+ if (cam_type == VELOCITY_VLAN_ID_CAM)
+ *((u16 *) addr) = readw(&(regs->MARCAM[0]));
+ else
+ for (i = 0; i < 6; i++, addr++)
+ *((u8 *) addr) = readb(&(regs->MARCAM[i]));
+
+ writeb(0, &regs->CAMADDR);
+
+ /* Select mar */
+ BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0,
+ &regs->CAMCR);
+}
+
+/**
+ * mac_wol_reset - reset WOL after exiting low power
+ * @regs: register block of this velocity
+ *
+ * Called after we drop out of wake on lan mode in order to
+ * reset the Wake on lan features. This function doesn't restore
+ * the rest of the logic from the result of sleep/wakeup
+ */
+
+inline static void mac_wol_reset(struct mac_regs *regs)
+{
+
+ /* Turn off SWPTAG right after leaving power mode */
+ BYTE_REG_BITS_OFF(STICKHW_SWPTAG, &regs->STICKHW);
+ /* clear sticky bits */
+ BYTE_REG_BITS_OFF((STICKHW_DS1 | STICKHW_DS0), &regs->STICKHW);
+
+ BYTE_REG_BITS_OFF(CHIPGCR_FCGMII, &regs->CHIPGCR);
+ BYTE_REG_BITS_OFF(CHIPGCR_FCMODE, &regs->CHIPGCR);
+ /* disable force PME-enable */
+ writeb(WOLCFG_PMEOVR, &regs->WOLCFGClr);
+ /* disable power-event config bit */
+ writew(0xFFFF, &regs->WOLCRClr);
+ /* clear power status */
+ writew(0xFFFF, &regs->WOLSRClr);
+}
+
+
+/*
+ * Header for WOL definitions. Used to compute hashes
+ */
+
+typedef u8 MCAM_ADDR[ETH_ALEN];
+
+struct arp_packet {
+ u8 dest_mac[ETH_ALEN];
+ u8 src_mac[ETH_ALEN];
+ u16 type;
+ u16 ar_hrd;
+ u16 ar_pro;
+ u8 ar_hln;
+ u8 ar_pln;
+ u16 ar_op;
+ u8 ar_sha[ETH_ALEN];
+ u8 ar_sip[4];
+ u8 ar_tha[ETH_ALEN];
+ u8 ar_tip[4];
+} __attribute__ ((__packed__));
+
+struct _magic_packet {
+ u8 dest_mac[6];
+ u8 src_mac[6];
+ u16 type;
+ u8 MAC[16][6];
+ u8 password[6];
+} __attribute__ ((__packed__));
+
+/*
+ * Store for chip context when saving and restoring status. Not
+ * all fields are saved/restored currently.
+ */
+
+struct velocity_context {
+ u8 mac_reg[256];
+ MCAM_ADDR cam_addr[MCAM_SIZE];
+ u16 vcam[VCAM_SIZE];
+ u32 cammask[2];
+ u32 patcrc[2];
+ u32 pattern[8];
+};
+
+
+/*
+ * MII registers.
+ */
+
+
+/*
+ * Registers in the MII (offset unit is WORD)
+ */
+
+#define MII_REG_BMCR 0x00 // physical address
+#define MII_REG_BMSR 0x01 //
+#define MII_REG_PHYID1 0x02 // OUI
+#define MII_REG_PHYID2 0x03 // OUI + Module ID + REV ID
+#define MII_REG_ANAR 0x04 //
+#define MII_REG_ANLPAR 0x05 //
+#define MII_REG_G1000CR 0x09 //
+#define MII_REG_G1000SR 0x0A //
+#define MII_REG_MODCFG 0x10 //
+#define MII_REG_TCSR 0x16 //
+#define MII_REG_PLED 0x1B //
+// NS, MYSON only
+#define MII_REG_PCR 0x17 //
+// ESI only
+#define MII_REG_PCSR 0x17 //
+#define MII_REG_AUXCR 0x1C //
+
+// Marvell 88E1000/88E1000S
+#define MII_REG_PSCR 0x10 // PHY specific control register
+
+//
+// Bits in the BMCR register
+//
+#define BMCR_RESET 0x8000 //
+#define BMCR_LBK 0x4000 //
+#define BMCR_SPEED100 0x2000 //
+#define BMCR_AUTO 0x1000 //
+#define BMCR_PD 0x0800 //
+#define BMCR_ISO 0x0400 //
+#define BMCR_REAUTO 0x0200 //
+#define BMCR_FDX 0x0100 //
+#define BMCR_SPEED1G 0x0040 //
+//
+// Bits in the BMSR register
+//
+#define BMSR_AUTOCM 0x0020 //
+#define BMSR_LNK 0x0004 //
+
+//
+// Bits in the ANAR register
+//
+#define ANAR_ASMDIR 0x0800 // Asymmetric PAUSE support
+#define ANAR_PAUSE 0x0400 // Symmetric PAUSE Support
+#define ANAR_T4 0x0200 //
+#define ANAR_TXFD 0x0100 //
+#define ANAR_TX 0x0080 //
+#define ANAR_10FD 0x0040 //
+#define ANAR_10 0x0020 //
+//
+// Bits in the ANLPAR register
+//
+#define ANLPAR_ASMDIR 0x0800 // Asymmetric PAUSE support
+#define ANLPAR_PAUSE 0x0400 // Symmetric PAUSE Support
+#define ANLPAR_T4 0x0200 //
+#define ANLPAR_TXFD 0x0100 //
+#define ANLPAR_TX 0x0080 //
+#define ANLPAR_10FD 0x0040 //
+#define ANLPAR_10 0x0020 //
+
+//
+// Bits in the G1000CR register
+//
+#define G1000CR_1000FD 0x0200 // PHY is 1000-T Full-duplex capable
+#define G1000CR_1000 0x0100 // PHY is 1000-T Half-duplex capable
+
+//
+// Bits in the G1000SR register
+//
+#define G1000SR_1000FD 0x0800 // LP PHY is 1000-T Full-duplex capable
+#define G1000SR_1000 0x0400 // LP PHY is 1000-T Half-duplex capable
+
+#define TCSR_ECHODIS 0x2000 //
+#define AUXCR_MDPPS 0x0004 //
+
+// Bits in the PLED register
+#define PLED_LALBE 0x0004 //
+
+// Marvell 88E1000/88E1000S Bits in the PHY specific control register (10h)
+#define PSCR_ACRSTX 0x0800 // Assert CRS on Transmit
+
+#define PHYID_CICADA_CS8201 0x000FC410UL
+#define PHYID_VT3216_32BIT 0x000FC610UL
+#define PHYID_VT3216_64BIT 0x000FC600UL
+#define PHYID_MARVELL_1000 0x01410C50UL
+#define PHYID_MARVELL_1000S 0x01410C40UL
+
+#define PHYID_REV_ID_MASK 0x0000000FUL
+
+#define PHYID_GET_PHY_REV_ID(i) ((i) & PHYID_REV_ID_MASK)
+#define PHYID_GET_PHY_ID(i) ((i) & ~PHYID_REV_ID_MASK)
+
+#define MII_REG_BITS_ON(x,i,p) do {\
+ u16 w;\
+ velocity_mii_read((p),(i),&(w));\
+ (w)|=(x);\
+ velocity_mii_write((p),(i),(w));\
+} while (0)
+
+#define MII_REG_BITS_OFF(x,i,p) do {\
+ u16 w;\
+ velocity_mii_read((p),(i),&(w));\
+ (w)&=(~(x));\
+ velocity_mii_write((p),(i),(w));\
+} while (0)
+
+#define MII_REG_BITS_IS_ON(x,i,p) ({\
+ u16 w;\
+ velocity_mii_read((p),(i),&(w));\
+ ((int) ((w) & (x)));})
+
+#define MII_GET_PHY_ID(p) ({\
+ u32 id; \
+ u16 id2; \
+ u16 id1; \
+ velocity_mii_read((p),MII_REG_PHYID2, &id2);\
+ velocity_mii_read((p),MII_REG_PHYID1, &id1);\
+ id = ( ( (u32)id2 ) << 16 ) | id1; \
+ (id);})
+
+#ifdef LINUX
+/*
+ * Inline debug routine
+ */
+
+
+enum velocity_msg_level {
+ MSG_LEVEL_ERR = 0, //Errors that will cause abnormal operation.
+ MSG_LEVEL_NOTICE = 1, //Some errors need users to be notified.
+ MSG_LEVEL_INFO = 2, //Normal message.
+ MSG_LEVEL_VERBOSE = 3, //Will report all trival errors.
+ MSG_LEVEL_DEBUG = 4 //Only for debug purpose.
+};
+
+#ifdef VELOCITY_DEBUG
+#define ASSERT(x) { \
+ if (!(x)) { \
+ printk(KERN_ERR "assertion %s failed: file %s line %d\n", #x,\
+ __FUNCTION__, __LINE__);\
+ BUG(); \
+ }\
+}
+#define VELOCITY_DBG(p,args...) printk(p, ##args)
+#else
+#define ASSERT(x)
+#define VELOCITY_DBG(x)
+#endif
+
+#define VELOCITY_PRT(l, p, args...) do {if (l<=msglevel) printf( p ,##args);} while (0)
+
+#define VELOCITY_PRT_CAMMASK(p,t) {\
+ int i;\
+ if ((t)==VELOCITY_MULTICAST_CAM) {\
+ for (i=0;i<(MCAM_SIZE/8);i++)\
+ printk("%02X",(p)->mCAMmask[i]);\
+ }\
+ else {\
+ for (i=0;i<(VCAM_SIZE/8);i++)\
+ printk("%02X",(p)->vCAMmask[i]);\
+ }\
+ printk("\n");\
+}
+
+#endif
+
+#define VELOCITY_WOL_MAGIC 0x00000000UL
+#define VELOCITY_WOL_PHY 0x00000001UL
+#define VELOCITY_WOL_ARP 0x00000002UL
+#define VELOCITY_WOL_UCAST 0x00000004UL
+#define VELOCITY_WOL_BCAST 0x00000010UL
+#define VELOCITY_WOL_MCAST 0x00000020UL
+#define VELOCITY_WOL_MAGIC_SEC 0x00000040UL
+
+/*
+ * Flags for options
+ */
+
+#define VELOCITY_FLAGS_TAGGING 0x00000001UL
+#define VELOCITY_FLAGS_TX_CSUM 0x00000002UL
+#define VELOCITY_FLAGS_RX_CSUM 0x00000004UL
+#define VELOCITY_FLAGS_IP_ALIGN 0x00000008UL
+#define VELOCITY_FLAGS_VAL_PKT_LEN 0x00000010UL
+
+#define VELOCITY_FLAGS_FLOW_CTRL 0x01000000UL
+
+/*
+ * Flags for driver status
+ */
+
+#define VELOCITY_FLAGS_OPENED 0x00010000UL
+#define VELOCITY_FLAGS_VMNS_CONNECTED 0x00020000UL
+#define VELOCITY_FLAGS_VMNS_COMMITTED 0x00040000UL
+#define VELOCITY_FLAGS_WOL_ENABLED 0x00080000UL
+
+/*
+ * Flags for MII status
+ */
+
+#define VELOCITY_LINK_FAIL 0x00000001UL
+#define VELOCITY_SPEED_10 0x00000002UL
+#define VELOCITY_SPEED_100 0x00000004UL
+#define VELOCITY_SPEED_1000 0x00000008UL
+#define VELOCITY_DUPLEX_FULL 0x00000010UL
+#define VELOCITY_AUTONEG_ENABLE 0x00000020UL
+#define VELOCITY_FORCED_BY_EEPROM 0x00000040UL
+
+/*
+ * For velocity_set_media_duplex
+ */
+
+#define VELOCITY_LINK_CHANGE 0x00000001UL
+
+enum speed_opt {
+ SPD_DPX_AUTO = 0,
+ SPD_DPX_100_HALF = 1,
+ SPD_DPX_100_FULL = 2,
+ SPD_DPX_10_HALF = 3,
+ SPD_DPX_10_FULL = 4
+};
+
+enum velocity_init_type {
+ VELOCITY_INIT_COLD = 0,
+ VELOCITY_INIT_RESET,
+ VELOCITY_INIT_WOL
+};
+
+enum velocity_flow_cntl_type {
+ FLOW_CNTL_DEFAULT = 1,
+ FLOW_CNTL_TX,
+ FLOW_CNTL_RX,
+ FLOW_CNTL_TX_RX,
+ FLOW_CNTL_DISABLE,
+};
+
+struct velocity_opt {
+ int numrx; /* Number of RX descriptors */
+ int numtx; /* Number of TX descriptors */
+ enum speed_opt spd_dpx; /* Media link mode */
+ int vid; /* vlan id */
+ int DMA_length; /* DMA length */
+ int rx_thresh; /* RX_THRESH */
+ int flow_cntl;
+ int wol_opts; /* Wake on lan options */
+ int td_int_count;
+ int int_works;
+ int rx_bandwidth_hi;
+ int rx_bandwidth_lo;
+ int rx_bandwidth_en;
+ u32 flags;
+};
+
+#define RX_DESC_MIN 4
+#define RX_DESC_MAX 255
+#define RX_DESC_DEF RX_DESC_MIN
+
+#define TX_DESC_MIN 1
+#define TX_DESC_MAX 256
+#define TX_DESC_DEF TX_DESC_MIN
+
+static struct velocity_info {
+// struct list_head list;
+
+ struct pci_device *pdev;
+// struct net_device *dev;
+// struct net_device_stats stats;
+
+#ifdef CONFIG_PM
+ u32 pci_state[16];
+#endif
+
+// dma_addr_t rd_pool_dma;
+// dma_addr_t td_pool_dma[TX_QUEUE_NO];
+
+// dma_addr_t tx_bufs_dma;
+ u8 *tx_bufs;
+
+ u8 ip_addr[4];
+ enum chip_type chip_id;
+
+ struct mac_regs *mac_regs;
+ unsigned long memaddr;
+ unsigned long ioaddr;
+ u32 io_size;
+
+ u8 rev_id;
+
+#define AVAIL_TD(p,q) ((p)->options.numtx-((p)->td_used[(q)]))
+
+ int num_txq;
+
+ volatile int td_used[TX_QUEUE_NO];
+ int td_curr;
+ int td_tail[TX_QUEUE_NO];
+ unsigned char *TxDescArrays; /* Index of Tx Descriptor buffer */
+ unsigned char *RxDescArrays; /* Index of Rx Descriptor buffer */
+ unsigned char *tx_buffs;
+ unsigned char *rx_buffs;
+
+ unsigned char *txb;
+ unsigned char *rxb;
+ struct tx_desc *td_rings;
+ struct velocity_td_info *td_infos[TX_QUEUE_NO];
+
+ int rd_curr;
+ int rd_dirty;
+ u32 rd_filled;
+ struct rx_desc *rd_ring;
+ struct velocity_rd_info *rd_info; /* It's an array */
+
+#define GET_RD_BY_IDX(vptr, idx) (vptr->rd_ring[idx])
+ u32 mib_counter[MAX_HW_MIB_COUNTER];
+ struct velocity_opt options;
+
+ u32 int_mask;
+
+ u32 flags;
+
+ int rx_buf_sz;
+ u32 mii_status;
+ u32 phy_id;
+ int multicast_limit;
+
+ u8 vCAMmask[(VCAM_SIZE / 8)];
+ u8 mCAMmask[(MCAM_SIZE / 8)];
+
+// spinlock_t lock;
+
+ int wol_opts;
+ u8 wol_passwd[6];
+
+ struct velocity_context context;
+
+ u32 ticks;
+ u32 rx_bytes;
+
+} vptx;
+
+static struct velocity_info *vptr;
+
+#ifdef LINUX
+/**
+ * velocity_get_ip - find an IP address for the device
+ * @vptr: Velocity to query
+ *
+ * Dig out an IP address for this interface so that we can
+ * configure wakeup with WOL for ARP. If there are multiple IP
+ * addresses on this chain then we use the first - multi-IP WOL is not
+ * supported.
+ *
+ * CHECK ME: locking
+ */
+
+inline static int velocity_get_ip(struct velocity_info *vptr)
+{
+ struct in_device *in_dev = (struct in_device *) vptr->dev->ip_ptr;
+ struct in_ifaddr *ifa;
+
+ if (in_dev != NULL) {
+ ifa = (struct in_ifaddr *) in_dev->ifa_list;
+ if (ifa != NULL) {
+ memcpy(vptr->ip_addr, &ifa->ifa_address, 4);
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+/**
+ * velocity_update_hw_mibs - fetch MIB counters from chip
+ * @vptr: velocity to update
+ *
+ * The velocity hardware keeps certain counters in the hardware
+ * side. We need to read these when the user asks for statistics
+ * or when they overflow (causing an interrupt). The read of the
+ * statistic clears it, so we keep running master counters in user
+ * space.
+ */
+
+static inline void velocity_update_hw_mibs(struct velocity_info *vptr)
+{
+ u32 tmp;
+ int i;
+ BYTE_REG_BITS_ON(MIBCR_MIBFLSH, &(vptr->mac_regs->MIBCR));
+
+ while (BYTE_REG_BITS_IS_ON
+ (MIBCR_MIBFLSH, &(vptr->mac_regs->MIBCR)));
+
+ BYTE_REG_BITS_ON(MIBCR_MPTRINI, &(vptr->mac_regs->MIBCR));
+ for (i = 0; i < HW_MIB_SIZE; i++) {
+ tmp = readl(&(vptr->mac_regs->MIBData)) & 0x00FFFFFFUL;
+ vptr->mib_counter[i] += tmp;
+ }
+}
+#endif
+/**
+ * init_flow_control_register - set up flow control
+ * @vptr: velocity to configure
+ *
+ * Configure the flow control registers for this velocity device.
+ */
+
+static inline void init_flow_control_register(struct velocity_info *vptr)
+{
+ struct mac_regs *regs = vptr->mac_regs;
+
+ /* Set {XHITH1, XHITH0, XLTH1, XLTH0} in FlowCR1 to {1, 0, 1, 1}
+ depend on RD=64, and Turn on XNOEN in FlowCR1 */
+ writel((CR0_XONEN | CR0_XHITH1 | CR0_XLTH1 | CR0_XLTH0),
+ &regs->CR0Set);
+ writel((CR0_FDXTFCEN | CR0_FDXRFCEN | CR0_HDXFCEN | CR0_XHITH0),
+ &regs->CR0Clr);
+
+ /* Set TxPauseTimer to 0xFFFF */
+ writew(0xFFFF, &regs->tx_pause_timer);
+
+ /* Initialize RBRDU to Rx buffer count. */
+ writew(vptr->options.numrx, &regs->RBRDU);
+}
+
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/virtio-net.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/virtio-net.c
new file mode 100644
index 00000000..54e962d1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/virtio-net.c
@@ -0,0 +1,419 @@
+/*
+ * (c) Copyright 2010 Stefan Hajnoczi <stefanha@gmail.com>
+ *
+ * based on the Etherboot virtio-net driver
+ *
+ * (c) Copyright 2008 Bull S.A.S.
+ *
+ * Author: Laurent Vivier <Laurent.Vivier@bull.net>
+ *
+ * some parts from Linux Virtio PCI driver
+ *
+ * Copyright IBM Corp. 2007
+ * Authors: Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * some parts from Linux Virtio Ring
+ *
+ * Copyright Rusty Russell IBM Corporation 2007
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <stdlib.h>
+#include <ipxe/list.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/pci.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/virtio-ring.h>
+#include <ipxe/virtio-pci.h>
+#include "virtio-net.h"
+
+/*
+ * Virtio network device driver
+ *
+ * Specification:
+ * http://ozlabs.org/~rusty/virtio-spec/
+ *
+ * The virtio network device is supported by Linux virtualization software
+ * including QEMU/KVM and lguest. This driver supports the virtio over PCI
+ * transport; virtual machines have one virtio-net PCI adapter per NIC.
+ *
+ * Virtio-net is different from hardware NICs because virtio devices
+ * communicate with the hypervisor via virtqueues, not traditional descriptor
+ * rings. Virtqueues are unordered queues, they support add_buf() and
+ * get_buf() operations. To transmit a packet, the driver has to add the
+ * packet buffer onto the virtqueue. To receive a packet, the driver must
+ * first add an empty buffer to the virtqueue and then get the filled packet
+ * buffer on completion.
+ *
+ * Virtqueues are an abstraction that is commonly implemented using the vring
+ * descriptor ring layout. The vring is the actual shared memory structure
+ * that allows the virtual machine to communicate buffers with the hypervisor.
+ * Because the vring layout is optimized for flexibility and performance rather
+ * than space, it is heavy-weight and allocated like traditional descriptor
+ * rings in the open() function of the driver and not in probe().
+ *
+ * There is no true interrupt enable/disable. Virtqueues have callback
+ * enable/disable flags but these are only hints. The hypervisor may still
+ * raise an interrupt. Nevertheless, this driver disables callbacks in the
+ * hopes of avoiding interrupts.
+ */
+
+/* Driver types are declared here so virtio-net.h can be easily synced with its
+ * Linux source.
+ */
+
+/* Virtqueue indicies */
+enum {
+ RX_INDEX = 0,
+ TX_INDEX,
+ QUEUE_NB
+};
+
+enum {
+ /** Max number of pending rx packets */
+ NUM_RX_BUF = 8,
+
+ /** Max Ethernet frame length, including FCS and VLAN tag */
+ RX_BUF_SIZE = 1522,
+};
+
+struct virtnet_nic {
+ /** Base pio register address */
+ unsigned long ioaddr;
+
+ /** RX/TX virtqueues */
+ struct vring_virtqueue *virtqueue;
+
+ /** RX packets handed to the NIC waiting to be filled in */
+ struct list_head rx_iobufs;
+
+ /** Pending rx packet count */
+ unsigned int rx_num_iobufs;
+
+ /** Virtio net packet header, we only need one */
+ struct virtio_net_hdr empty_header;
+};
+
+/** Add an iobuf to a virtqueue
+ *
+ * @v netdev Network device
+ * @v vq_idx Virtqueue index (RX_INDEX or TX_INDEX)
+ * @v iobuf I/O buffer
+ *
+ * The virtqueue is kicked after the iobuf has been added.
+ */
+static void virtnet_enqueue_iob ( struct net_device *netdev,
+ int vq_idx, struct io_buffer *iobuf ) {
+ struct virtnet_nic *virtnet = netdev->priv;
+ struct vring_virtqueue *vq = &virtnet->virtqueue[vq_idx];
+ unsigned int out = ( vq_idx == TX_INDEX ) ? 2 : 0;
+ unsigned int in = ( vq_idx == TX_INDEX ) ? 0 : 2;
+ struct vring_list list[] = {
+ {
+ /* Share a single zeroed virtio net header between all
+ * rx and tx packets. This works because this driver
+ * does not use any advanced features so none of the
+ * header fields get used.
+ */
+ .addr = ( char* ) &virtnet->empty_header,
+ .length = sizeof ( virtnet->empty_header ),
+ },
+ {
+ .addr = ( char* ) iobuf->data,
+ .length = iob_len ( iobuf ),
+ },
+ };
+
+ DBGC ( virtnet, "VIRTIO-NET %p enqueuing iobuf %p on vq %d\n",
+ virtnet, iobuf, vq_idx );
+
+ vring_add_buf ( vq, list, out, in, iobuf, 0 );
+ vring_kick ( virtnet->ioaddr, vq, 1 );
+}
+
+/** Try to keep rx virtqueue filled with iobufs
+ *
+ * @v netdev Network device
+ */
+static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) {
+ struct virtnet_nic *virtnet = netdev->priv;
+
+ while ( virtnet->rx_num_iobufs < NUM_RX_BUF ) {
+ struct io_buffer *iobuf;
+
+ /* Try to allocate a buffer, stop for now if out of memory */
+ iobuf = alloc_iob ( RX_BUF_SIZE );
+ if ( ! iobuf )
+ break;
+
+ /* Keep track of iobuf so close() can free it */
+ list_add ( &iobuf->list, &virtnet->rx_iobufs );
+
+ /* Mark packet length until we know the actual size */
+ iob_put ( iobuf, RX_BUF_SIZE );
+
+ virtnet_enqueue_iob ( netdev, RX_INDEX, iobuf );
+ virtnet->rx_num_iobufs++;
+ }
+}
+
+/** Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int virtnet_open ( struct net_device *netdev ) {
+ struct virtnet_nic *virtnet = netdev->priv;
+ unsigned long ioaddr = virtnet->ioaddr;
+ u32 features;
+ int i;
+
+ /* Reset for sanity */
+ vp_reset ( ioaddr );
+
+ /* Allocate virtqueues */
+ virtnet->virtqueue = zalloc ( QUEUE_NB *
+ sizeof ( *virtnet->virtqueue ) );
+ if ( ! virtnet->virtqueue )
+ return -ENOMEM;
+
+ /* Initialize rx/tx virtqueues */
+ for ( i = 0; i < QUEUE_NB; i++ ) {
+ if ( vp_find_vq ( ioaddr, i, &virtnet->virtqueue[i] ) == -1 ) {
+ DBGC ( virtnet, "VIRTIO-NET %p cannot register queue %d\n",
+ virtnet, i );
+ free ( virtnet->virtqueue );
+ virtnet->virtqueue = NULL;
+ return -ENOENT;
+ }
+ }
+
+ /* Initialize rx packets */
+ INIT_LIST_HEAD ( &virtnet->rx_iobufs );
+ virtnet->rx_num_iobufs = 0;
+ virtnet_refill_rx_virtqueue ( netdev );
+
+ /* Disable interrupts before starting */
+ netdev_irq ( netdev, 0 );
+
+ /* Driver is ready */
+ features = vp_get_features ( ioaddr );
+ vp_set_features ( ioaddr, features & ( 1 << VIRTIO_NET_F_MAC ) );
+ vp_set_status ( ioaddr, VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK );
+ return 0;
+}
+
+/** Close network device
+ *
+ * @v netdev Network device
+ */
+static void virtnet_close ( struct net_device *netdev ) {
+ struct virtnet_nic *virtnet = netdev->priv;
+ struct io_buffer *iobuf;
+ struct io_buffer *next_iobuf;
+
+ vp_reset ( virtnet->ioaddr );
+
+ /* Virtqueues can be freed now that NIC is reset */
+ free ( virtnet->virtqueue );
+ virtnet->virtqueue = NULL;
+
+ /* Free rx iobufs */
+ list_for_each_entry_safe ( iobuf, next_iobuf, &virtnet->rx_iobufs, list ) {
+ free_iob ( iobuf );
+ }
+ INIT_LIST_HEAD ( &virtnet->rx_iobufs );
+ virtnet->rx_num_iobufs = 0;
+}
+
+/** Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int virtnet_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ virtnet_enqueue_iob ( netdev, TX_INDEX, iobuf );
+ return 0;
+}
+
+/** Complete packet transmission
+ *
+ * @v netdev Network device
+ */
+static void virtnet_process_tx_packets ( struct net_device *netdev ) {
+ struct virtnet_nic *virtnet = netdev->priv;
+ struct vring_virtqueue *tx_vq = &virtnet->virtqueue[TX_INDEX];
+
+ while ( vring_more_used ( tx_vq ) ) {
+ struct io_buffer *iobuf = vring_get_buf ( tx_vq, NULL );
+
+ DBGC ( virtnet, "VIRTIO-NET %p tx complete iobuf %p\n",
+ virtnet, iobuf );
+
+ netdev_tx_complete ( netdev, iobuf );
+ }
+}
+
+/** Complete packet reception
+ *
+ * @v netdev Network device
+ */
+static void virtnet_process_rx_packets ( struct net_device *netdev ) {
+ struct virtnet_nic *virtnet = netdev->priv;
+ struct vring_virtqueue *rx_vq = &virtnet->virtqueue[RX_INDEX];
+
+ while ( vring_more_used ( rx_vq ) ) {
+ unsigned int len;
+ struct io_buffer *iobuf = vring_get_buf ( rx_vq, &len );
+
+ /* Release ownership of iobuf */
+ list_del ( &iobuf->list );
+ virtnet->rx_num_iobufs--;
+
+ /* Update iobuf length */
+ iob_unput ( iobuf, RX_BUF_SIZE );
+ iob_put ( iobuf, len - sizeof ( struct virtio_net_hdr ) );
+
+ DBGC ( virtnet, "VIRTIO-NET %p rx complete iobuf %p len %zd\n",
+ virtnet, iobuf, iob_len ( iobuf ) );
+
+ /* Pass completed packet to the network stack */
+ netdev_rx ( netdev, iobuf );
+ }
+
+ virtnet_refill_rx_virtqueue ( netdev );
+}
+
+/** Poll for completed and received packets
+ *
+ * @v netdev Network device
+ */
+static void virtnet_poll ( struct net_device *netdev ) {
+ struct virtnet_nic *virtnet = netdev->priv;
+
+ /* Acknowledge interrupt. This is necessary for UNDI operation and
+ * interrupts that are raised despite VRING_AVAIL_F_NO_INTERRUPT being
+ * set (that flag is just a hint and the hypervisor not not have to
+ * honor it).
+ */
+ vp_get_isr ( virtnet->ioaddr );
+
+ virtnet_process_tx_packets ( netdev );
+ virtnet_process_rx_packets ( netdev );
+}
+
+/** Enable or disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void virtnet_irq ( struct net_device *netdev, int enable ) {
+ struct virtnet_nic *virtnet = netdev->priv;
+ int i;
+
+ for ( i = 0; i < QUEUE_NB; i++ ) {
+ if ( enable )
+ vring_enable_cb ( &virtnet->virtqueue[i] );
+ else
+ vring_disable_cb ( &virtnet->virtqueue[i] );
+ }
+}
+
+/** virtio-net device operations */
+static struct net_device_operations virtnet_operations = {
+ .open = virtnet_open,
+ .close = virtnet_close,
+ .transmit = virtnet_transmit,
+ .poll = virtnet_poll,
+ .irq = virtnet_irq,
+};
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @v id PCI ID
+ * @ret rc Return status code
+ */
+static int virtnet_probe ( struct pci_device *pci ) {
+ unsigned long ioaddr = pci->ioaddr;
+ struct net_device *netdev;
+ struct virtnet_nic *virtnet;
+ u32 features;
+ int rc;
+
+ /* Allocate and hook up net device */
+ netdev = alloc_etherdev ( sizeof ( *virtnet ) );
+ if ( ! netdev )
+ return -ENOMEM;
+ netdev_init ( netdev, &virtnet_operations );
+ virtnet = netdev->priv;
+ virtnet->ioaddr = ioaddr;
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+
+ DBGC ( virtnet, "VIRTIO-NET %p busaddr=%s ioaddr=%#lx irq=%d\n",
+ virtnet, pci->dev.name, ioaddr, pci->irq );
+
+ /* Enable PCI bus master and reset NIC */
+ adjust_pci_device ( pci );
+ vp_reset ( ioaddr );
+
+ /* Load MAC address */
+ features = vp_get_features ( ioaddr );
+ if ( features & ( 1 << VIRTIO_NET_F_MAC ) ) {
+ vp_get ( ioaddr, offsetof ( struct virtio_net_config, mac ),
+ netdev->hw_addr, ETH_ALEN );
+ DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
+ eth_ntoa ( netdev->hw_addr ) );
+ }
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register_netdev;
+
+ /* Mark link as up, control virtqueue is not used */
+ netdev_link_up ( netdev );
+
+ return 0;
+
+ unregister_netdev ( netdev );
+ err_register_netdev:
+ vp_reset ( ioaddr );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ return rc;
+}
+
+/**
+ * Remove device
+ *
+ * @v pci PCI device
+ */
+static void virtnet_remove ( struct pci_device *pci ) {
+ struct net_device *netdev = pci_get_drvdata ( pci );
+
+ unregister_netdev ( netdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+static struct pci_device_id virtnet_nics[] = {
+PCI_ROM(0x1af4, 0x1000, "virtio-net", "Virtio Network Interface", 0),
+};
+
+struct pci_driver virtnet_driver __pci_driver = {
+ .ids = virtnet_nics,
+ .id_count = ( sizeof ( virtnet_nics ) / sizeof ( virtnet_nics[0] ) ),
+ .probe = virtnet_probe,
+ .remove = virtnet_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/virtio-net.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/virtio-net.h
new file mode 100644
index 00000000..3abef28e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/virtio-net.h
@@ -0,0 +1,44 @@
+#ifndef _VIRTIO_NET_H_
+# define _VIRTIO_NET_H_
+
+/* The feature bitmap for virtio net */
+#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
+#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */
+#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
+#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */
+#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */
+#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */
+#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */
+#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */
+#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */
+#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */
+
+struct virtio_net_config
+{
+ /* The config defining mac address (if VIRTIO_NET_F_MAC) */
+ u8 mac[6];
+} __attribute__((packed));
+
+/* This is the first element of the scatter-gather list. If you don't
+ * specify GSO or CSUM features, you can simply ignore the header. */
+
+struct virtio_net_hdr
+{
+#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset
+ uint8_t flags;
+#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame
+#define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO)
+/* FIXME: Do we need this? If they said they can handle ECN, do they care? */
+#define VIRTIO_NET_HDR_GSO_TCPV4_ECN 2 // GSO frame, IPv4 TCP w/ ECN
+#define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO)
+#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP
+#define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set
+ uint8_t gso_type;
+ uint16_t hdr_len;
+ uint16_t gso_size;
+ uint16_t csum_start;
+ uint16_t csum_offset;
+};
+#endif /* _VIRTIO_NET_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/vmxnet3.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/vmxnet3.c
new file mode 100644
index 00000000..79cf1d80
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/vmxnet3.c
@@ -0,0 +1,669 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include <ipxe/io.h>
+#include <ipxe/malloc.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include "vmxnet3.h"
+
+/**
+ * @file
+ *
+ * VMware vmxnet3 virtual NIC driver
+ *
+ */
+
+/**
+ * Issue command
+ *
+ * @v vmxnet vmxnet3 NIC
+ * @v command Command to issue
+ * @ret result Command result
+ */
+static inline uint32_t vmxnet3_command ( struct vmxnet3_nic *vmxnet,
+ uint32_t command ) {
+
+ /* Issue command */
+ writel ( command, ( vmxnet->vd + VMXNET3_VD_CMD ) );
+ return readl ( vmxnet->vd + VMXNET3_VD_CMD );
+}
+
+/**
+ * Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int vmxnet3_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_tx_desc *tx_desc;
+ unsigned int desc_idx;
+ unsigned int generation;
+
+ /* Check that we have a free transmit descriptor */
+ desc_idx = ( vmxnet->count.tx_prod % VMXNET3_NUM_TX_DESC );
+ generation = ( ( vmxnet->count.tx_prod & VMXNET3_NUM_TX_DESC ) ?
+ 0 : cpu_to_le32 ( VMXNET3_TXF_GEN ) );
+ if ( vmxnet->tx_iobuf[desc_idx] ) {
+ DBGC ( vmxnet, "VMXNET3 %p out of transmit descriptors\n",
+ vmxnet );
+ return -ENOBUFS;
+ }
+
+ /* Increment producer counter */
+ vmxnet->count.tx_prod++;
+
+ /* Store I/O buffer for later completion */
+ vmxnet->tx_iobuf[desc_idx] = iobuf;
+
+ /* Populate transmit descriptor */
+ tx_desc = &vmxnet->dma->tx_desc[desc_idx];
+ tx_desc->address = cpu_to_le64 ( virt_to_bus ( iobuf->data ) );
+ tx_desc->flags[0] = ( generation | cpu_to_le32 ( iob_len ( iobuf ) ) );
+ tx_desc->flags[1] = cpu_to_le32 ( VMXNET3_TXF_CQ | VMXNET3_TXF_EOP );
+
+ /* Hand over descriptor to NIC */
+ wmb();
+ writel ( ( vmxnet->count.tx_prod % VMXNET3_NUM_TX_DESC ),
+ ( vmxnet->pt + VMXNET3_PT_TXPROD ) );
+
+ return 0;
+}
+
+/**
+ * Poll for completed transmissions
+ *
+ * @v netdev Network device
+ */
+static void vmxnet3_poll_tx ( struct net_device *netdev ) {
+ struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_tx_comp *tx_comp;
+ struct io_buffer *iobuf;
+ unsigned int comp_idx;
+ unsigned int desc_idx;
+ unsigned int generation;
+
+ while ( 1 ) {
+
+ /* Look for completed descriptors */
+ comp_idx = ( vmxnet->count.tx_cons % VMXNET3_NUM_TX_COMP );
+ generation = ( ( vmxnet->count.tx_cons & VMXNET3_NUM_TX_COMP ) ?
+ 0 : cpu_to_le32 ( VMXNET3_TXCF_GEN ) );
+ tx_comp = &vmxnet->dma->tx_comp[comp_idx];
+ if ( generation != ( tx_comp->flags &
+ cpu_to_le32 ( VMXNET3_TXCF_GEN ) ) ) {
+ break;
+ }
+
+ /* Increment consumer counter */
+ vmxnet->count.tx_cons++;
+
+ /* Locate corresponding transmit descriptor */
+ desc_idx = ( le32_to_cpu ( tx_comp->index ) %
+ VMXNET3_NUM_TX_DESC );
+ iobuf = vmxnet->tx_iobuf[desc_idx];
+ if ( ! iobuf ) {
+ DBGC ( vmxnet, "VMXNET3 %p completed on empty transmit "
+ "buffer %#x/%#x\n", vmxnet, comp_idx, desc_idx );
+ netdev_tx_err ( netdev, NULL, -ENOTTY );
+ continue;
+ }
+
+ /* Remove I/O buffer from transmit queue */
+ vmxnet->tx_iobuf[desc_idx] = NULL;
+
+ /* Report transmission completion to network layer */
+ DBGC2 ( vmxnet, "VMXNET3 %p completed TX %#x/%#x (len %#zx)\n",
+ vmxnet, comp_idx, desc_idx, iob_len ( iobuf ) );
+ netdev_tx_complete ( netdev, iobuf );
+ }
+}
+
+/**
+ * Flush any uncompleted transmit buffers
+ *
+ * @v netdev Network device
+ */
+static void vmxnet3_flush_tx ( struct net_device *netdev ) {
+ struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ unsigned int i;
+
+ for ( i = 0 ; i < VMXNET3_NUM_TX_DESC ; i++ ) {
+ if ( vmxnet->tx_iobuf[i] ) {
+ netdev_tx_complete_err ( netdev, vmxnet->tx_iobuf[i],
+ -ECANCELED );
+ vmxnet->tx_iobuf[i] = NULL;
+ }
+ }
+}
+
+/**
+ * Refill receive ring
+ *
+ * @v netdev Network device
+ */
+static void vmxnet3_refill_rx ( struct net_device *netdev ) {
+ struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_rx_desc *rx_desc;
+ struct io_buffer *iobuf;
+ unsigned int orig_rx_prod = vmxnet->count.rx_prod;
+ unsigned int desc_idx;
+ unsigned int generation;
+
+ /* Fill receive ring to specified fill level */
+ while ( vmxnet->count.rx_fill < VMXNET3_RX_FILL ) {
+
+ /* Locate receive descriptor */
+ desc_idx = ( vmxnet->count.rx_prod % VMXNET3_NUM_RX_DESC );
+ generation = ( ( vmxnet->count.rx_prod & VMXNET3_NUM_RX_DESC ) ?
+ 0 : cpu_to_le32 ( VMXNET3_RXF_GEN ) );
+ assert ( vmxnet->rx_iobuf[desc_idx] == NULL );
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( VMXNET3_MTU + NET_IP_ALIGN );
+ if ( ! iobuf ) {
+ /* Non-fatal low memory condition */
+ break;
+ }
+ iob_reserve ( iobuf, NET_IP_ALIGN );
+
+ /* Increment producer counter and fill level */
+ vmxnet->count.rx_prod++;
+ vmxnet->count.rx_fill++;
+
+ /* Store I/O buffer for later completion */
+ vmxnet->rx_iobuf[desc_idx] = iobuf;
+
+ /* Populate receive descriptor */
+ rx_desc = &vmxnet->dma->rx_desc[desc_idx];
+ rx_desc->address = cpu_to_le64 ( virt_to_bus ( iobuf->data ) );
+ rx_desc->flags = ( generation | cpu_to_le32 ( VMXNET3_MTU ) );
+
+ }
+
+ /* Hand over any new descriptors to NIC */
+ if ( vmxnet->count.rx_prod != orig_rx_prod ) {
+ wmb();
+ writel ( ( vmxnet->count.rx_prod % VMXNET3_NUM_RX_DESC ),
+ ( vmxnet->pt + VMXNET3_PT_RXPROD ) );
+ }
+}
+
+/**
+ * Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void vmxnet3_poll_rx ( struct net_device *netdev ) {
+ struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_rx_comp *rx_comp;
+ struct io_buffer *iobuf;
+ unsigned int comp_idx;
+ unsigned int desc_idx;
+ unsigned int generation;
+ size_t len;
+
+ while ( 1 ) {
+
+ /* Look for completed descriptors */
+ comp_idx = ( vmxnet->count.rx_cons % VMXNET3_NUM_RX_COMP );
+ generation = ( ( vmxnet->count.rx_cons & VMXNET3_NUM_RX_COMP ) ?
+ 0 : cpu_to_le32 ( VMXNET3_RXCF_GEN ) );
+ rx_comp = &vmxnet->dma->rx_comp[comp_idx];
+ if ( generation != ( rx_comp->flags &
+ cpu_to_le32 ( VMXNET3_RXCF_GEN ) ) ) {
+ break;
+ }
+
+ /* Increment consumer counter */
+ vmxnet->count.rx_cons++;
+
+ /* Locate corresponding receive descriptor */
+ desc_idx = ( le32_to_cpu ( rx_comp->index ) %
+ VMXNET3_NUM_RX_DESC );
+ iobuf = vmxnet->rx_iobuf[desc_idx];
+ if ( ! iobuf ) {
+ DBGC ( vmxnet, "VMXNET3 %p completed on empty receive "
+ "buffer %#x/%#x\n", vmxnet, comp_idx, desc_idx );
+ netdev_rx_err ( netdev, NULL, -ENOTTY );
+ continue;
+ }
+
+ /* Remove I/O buffer from receive queue */
+ vmxnet->rx_iobuf[desc_idx] = NULL;
+ vmxnet->count.rx_fill--;
+
+ /* Deliver packet to network layer */
+ len = ( le32_to_cpu ( rx_comp->len ) &
+ ( VMXNET3_MAX_PACKET_LEN - 1 ) );
+ DBGC2 ( vmxnet, "VMXNET3 %p completed RX %#x/%#x (len %#zx)\n",
+ vmxnet, comp_idx, desc_idx, len );
+ iob_put ( iobuf, len );
+ netdev_rx ( netdev, iobuf );
+ }
+}
+
+/**
+ * Flush any uncompleted receive buffers
+ *
+ * @v netdev Network device
+ */
+static void vmxnet3_flush_rx ( struct net_device *netdev ) {
+ struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct io_buffer *iobuf;
+ unsigned int i;
+
+ for ( i = 0 ; i < VMXNET3_NUM_RX_DESC ; i++ ) {
+ if ( ( iobuf = vmxnet->rx_iobuf[i] ) != NULL ) {
+ netdev_rx_err ( netdev, iobuf, -ECANCELED );
+ vmxnet->rx_iobuf[i] = NULL;
+ }
+ }
+}
+
+/**
+ * Check link state
+ *
+ * @v netdev Network device
+ */
+static void vmxnet3_check_link ( struct net_device *netdev ) {
+ struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ uint32_t state;
+ int link_up;
+ unsigned int link_speed;
+
+ /* Get link state */
+ state = vmxnet3_command ( vmxnet, VMXNET3_CMD_GET_LINK );
+ link_up = ( state & 1 );
+ link_speed = ( state >> 16 );
+
+ /* Report link state to network device */
+ if ( link_up ) {
+ DBGC ( vmxnet, "VMXNET3 %p link is up at %d Mbps\n",
+ vmxnet, link_speed );
+ netdev_link_up ( netdev );
+ } else {
+ DBGC ( vmxnet, "VMXNET3 %p link is down\n", vmxnet );
+ netdev_link_down ( netdev );
+ }
+}
+
+/**
+ * Poll for events
+ *
+ * @v netdev Network device
+ */
+static void vmxnet3_poll_events ( struct net_device *netdev ) {
+ struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ uint32_t events;
+
+ /* Do nothing unless there are events to process */
+ if ( ! vmxnet->dma->shared.ecr )
+ return;
+ events = le32_to_cpu ( vmxnet->dma->shared.ecr );
+
+ /* Acknowledge these events */
+ writel ( events, ( vmxnet->vd + VMXNET3_VD_ECR ) );
+
+ /* Check for link state change */
+ if ( events & VMXNET3_ECR_LINK ) {
+ vmxnet3_check_link ( netdev );
+ events &= ~VMXNET3_ECR_LINK;
+ }
+
+ /* Check for queue errors */
+ if ( events & ( VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR ) ) {
+ vmxnet3_command ( vmxnet, VMXNET3_CMD_GET_QUEUE_STATUS );
+ DBGC ( vmxnet, "VMXNET3 %p queue error status (TX %08x, RX "
+ "%08x)\n", vmxnet,
+ le32_to_cpu ( vmxnet->dma->queues.tx.status.error ),
+ le32_to_cpu ( vmxnet->dma->queues.rx.status.error ) );
+ /* Report errors to allow for visibility via "ifstat" */
+ if ( events & VMXNET3_ECR_TQERR )
+ netdev_tx_err ( netdev, NULL, -EPIPE );
+ if ( events & VMXNET3_ECR_RQERR )
+ netdev_rx_err ( netdev, NULL, -EPIPE );
+ events &= ~( VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR );
+ }
+
+ /* Check for unknown events */
+ if ( events ) {
+ DBGC ( vmxnet, "VMXNET3 %p unknown events %08x\n",
+ vmxnet, events );
+ /* Report error to allow for visibility via "ifstat" */
+ netdev_rx_err ( netdev, NULL, -ENODEV );
+ }
+}
+
+/**
+ * Poll network device
+ *
+ * @v netdev Network device
+ */
+static void vmxnet3_poll ( struct net_device *netdev ) {
+
+ vmxnet3_poll_events ( netdev );
+ vmxnet3_poll_tx ( netdev );
+ vmxnet3_poll_rx ( netdev );
+ vmxnet3_refill_rx ( netdev );
+}
+
+/**
+ * Enable/disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void vmxnet3_irq ( struct net_device *netdev, int enable ) {
+ struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+
+ DBGC ( vmxnet, "VMXNET3 %p %s IRQ not implemented\n",
+ vmxnet, ( enable ? "enable" : "disable" ) );
+}
+
+/**
+ * Set MAC address
+ *
+ * @v vmxnet vmxnet3 NIC
+ * @v ll_addr Link-layer address to set
+ */
+static void vmxnet3_set_ll_addr ( struct vmxnet3_nic *vmxnet,
+ const void *ll_addr ) {
+ struct {
+ uint32_t low;
+ uint32_t high;
+ } __attribute__ (( packed )) mac;
+
+ memset ( &mac, 0, sizeof ( mac ) );
+ memcpy ( &mac, ll_addr, ETH_ALEN );
+ writel ( cpu_to_le32 ( mac.low ), ( vmxnet->vd + VMXNET3_VD_MACL ) );
+ writel ( cpu_to_le32 ( mac.high ), ( vmxnet->vd + VMXNET3_VD_MACH ) );
+}
+
+/**
+ * Open NIC
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int vmxnet3_open ( struct net_device *netdev ) {
+ struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_shared *shared;
+ struct vmxnet3_queues *queues;
+ uint64_t shared_bus;
+ uint64_t queues_bus;
+ uint32_t status;
+ int rc;
+
+ /* Allocate DMA areas */
+ vmxnet->dma = malloc_dma ( sizeof ( *vmxnet->dma ), VMXNET3_DMA_ALIGN );
+ if ( ! vmxnet->dma ) {
+ DBGC ( vmxnet, "VMXNET3 %p could not allocate DMA area\n",
+ vmxnet );
+ rc = -ENOMEM;
+ goto err_alloc_dma;
+ }
+ memset ( vmxnet->dma, 0, sizeof ( *vmxnet->dma ) );
+
+ /* Populate queue descriptors */
+ queues = &vmxnet->dma->queues;
+ queues->tx.cfg.desc_address =
+ cpu_to_le64 ( virt_to_bus ( &vmxnet->dma->tx_desc ) );
+ queues->tx.cfg.comp_address =
+ cpu_to_le64 ( virt_to_bus ( &vmxnet->dma->tx_comp ) );
+ queues->tx.cfg.num_desc = cpu_to_le32 ( VMXNET3_NUM_TX_DESC );
+ queues->tx.cfg.num_comp = cpu_to_le32 ( VMXNET3_NUM_TX_COMP );
+ queues->rx.cfg.desc_address[0] =
+ cpu_to_le64 ( virt_to_bus ( &vmxnet->dma->rx_desc ) );
+ queues->rx.cfg.comp_address =
+ cpu_to_le64 ( virt_to_bus ( &vmxnet->dma->rx_comp ) );
+ queues->rx.cfg.num_desc[0] = cpu_to_le32 ( VMXNET3_NUM_RX_DESC );
+ queues->rx.cfg.num_comp = cpu_to_le32 ( VMXNET3_NUM_RX_COMP );
+ queues_bus = virt_to_bus ( queues );
+ DBGC ( vmxnet, "VMXNET3 %p queue descriptors at %08llx+%zx\n",
+ vmxnet, queues_bus, sizeof ( *queues ) );
+
+ /* Populate shared area */
+ shared = &vmxnet->dma->shared;
+ shared->magic = cpu_to_le32 ( VMXNET3_SHARED_MAGIC );
+ shared->misc.version = cpu_to_le32 ( VMXNET3_VERSION_MAGIC );
+ shared->misc.version_support = cpu_to_le32 ( VMXNET3_VERSION_SELECT );
+ shared->misc.upt_version_support =
+ cpu_to_le32 ( VMXNET3_UPT_VERSION_SELECT );
+ shared->misc.queue_desc_address = cpu_to_le64 ( queues_bus );
+ shared->misc.queue_desc_len = cpu_to_le32 ( sizeof ( *queues ) );
+ shared->misc.mtu = cpu_to_le32 ( VMXNET3_MTU );
+ shared->misc.num_tx_queues = 1;
+ shared->misc.num_rx_queues = 1;
+ shared->interrupt.num_intrs = 1;
+ shared->interrupt.control = cpu_to_le32 ( VMXNET3_IC_DISABLE_ALL );
+ shared->rx_filter.mode = cpu_to_le32 ( VMXNET3_RXM_UCAST |
+ VMXNET3_RXM_BCAST |
+ VMXNET3_RXM_ALL_MULTI );
+ shared_bus = virt_to_bus ( shared );
+ DBGC ( vmxnet, "VMXNET3 %p shared area at %08llx+%zx\n",
+ vmxnet, shared_bus, sizeof ( *shared ) );
+
+ /* Zero counters */
+ memset ( &vmxnet->count, 0, sizeof ( vmxnet->count ) );
+
+ /* Set MAC address */
+ vmxnet3_set_ll_addr ( vmxnet, &netdev->ll_addr );
+
+ /* Pass shared area to device */
+ writel ( ( shared_bus >> 0 ), ( vmxnet->vd + VMXNET3_VD_DSAL ) );
+ writel ( ( shared_bus >> 32 ), ( vmxnet->vd + VMXNET3_VD_DSAH ) );
+
+ /* Activate device */
+ if ( ( status = vmxnet3_command ( vmxnet,
+ VMXNET3_CMD_ACTIVATE_DEV ) ) != 0 ) {
+ DBGC ( vmxnet, "VMXNET3 %p could not activate (status %#x)\n",
+ vmxnet, status );
+ rc = -EIO;
+ goto err_activate;
+ }
+
+ /* Fill receive ring */
+ vmxnet3_refill_rx ( netdev );
+
+ return 0;
+
+ vmxnet3_command ( vmxnet, VMXNET3_CMD_QUIESCE_DEV );
+ vmxnet3_command ( vmxnet, VMXNET3_CMD_RESET_DEV );
+ err_activate:
+ vmxnet3_flush_tx ( netdev );
+ vmxnet3_flush_rx ( netdev );
+ free_dma ( vmxnet->dma, sizeof ( *vmxnet->dma ) );
+ err_alloc_dma:
+ return rc;
+}
+
+/**
+ * Close NIC
+ *
+ * @v netdev Network device
+ */
+static void vmxnet3_close ( struct net_device *netdev ) {
+ struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+
+ vmxnet3_command ( vmxnet, VMXNET3_CMD_QUIESCE_DEV );
+ vmxnet3_command ( vmxnet, VMXNET3_CMD_RESET_DEV );
+ vmxnet3_flush_tx ( netdev );
+ vmxnet3_flush_rx ( netdev );
+ free_dma ( vmxnet->dma, sizeof ( *vmxnet->dma ) );
+}
+
+/** vmxnet3 net device operations */
+static struct net_device_operations vmxnet3_operations = {
+ .open = vmxnet3_open,
+ .close = vmxnet3_close,
+ .transmit = vmxnet3_transmit,
+ .poll = vmxnet3_poll,
+ .irq = vmxnet3_irq,
+};
+
+/**
+ * Check version
+ *
+ * @v vmxnet vmxnet3 NIC
+ * @ret rc Return status code
+ */
+static int vmxnet3_check_version ( struct vmxnet3_nic *vmxnet ) {
+ uint32_t version;
+ uint32_t upt_version;
+
+ /* Read version */
+ version = readl ( vmxnet->vd + VMXNET3_VD_VRRS );
+ upt_version = readl ( vmxnet->vd + VMXNET3_VD_UVRS );
+ DBGC ( vmxnet, "VMXNET3 %p is version %d (UPT version %d)\n",
+ vmxnet, version, upt_version );
+
+ /* Inform NIC of driver version */
+ writel ( VMXNET3_VERSION_SELECT, ( vmxnet->vd + VMXNET3_VD_VRRS ) );
+ writel ( VMXNET3_UPT_VERSION_SELECT, ( vmxnet->vd + VMXNET3_VD_UVRS ) );
+
+ return 0;
+}
+
+/**
+ * Get permanent MAC address
+ *
+ * @v vmxnet vmxnet3 NIC
+ * @v hw_addr Hardware address to fill in
+ */
+static void vmxnet3_get_hw_addr ( struct vmxnet3_nic *vmxnet, void *hw_addr ) {
+ struct {
+ uint32_t low;
+ uint32_t high;
+ } __attribute__ (( packed )) mac;
+
+ mac.low = le32_to_cpu ( vmxnet3_command ( vmxnet,
+ VMXNET3_CMD_GET_PERM_MAC_LO ) );
+ mac.high = le32_to_cpu ( vmxnet3_command ( vmxnet,
+ VMXNET3_CMD_GET_PERM_MAC_HI ) );
+ memcpy ( hw_addr, &mac, ETH_ALEN );
+}
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @v id PCI ID
+ * @ret rc Return status code
+ */
+static int vmxnet3_probe ( struct pci_device *pci ) {
+ struct net_device *netdev;
+ struct vmxnet3_nic *vmxnet;
+ int rc;
+
+ /* Allocate network device */
+ netdev = alloc_etherdev ( sizeof ( *vmxnet ) );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ goto err_alloc_etherdev;
+ }
+ netdev_init ( netdev, &vmxnet3_operations );
+ vmxnet = netdev_priv ( netdev );
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+ memset ( vmxnet, 0, sizeof ( *vmxnet ) );
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* Map PCI BARs */
+ vmxnet->pt = ioremap ( pci_bar_start ( pci, VMXNET3_PT_BAR ),
+ VMXNET3_PT_LEN );
+ vmxnet->vd = ioremap ( pci_bar_start ( pci, VMXNET3_VD_BAR ),
+ VMXNET3_VD_LEN );
+
+ /* Version check */
+ if ( ( rc = vmxnet3_check_version ( vmxnet ) ) != 0 )
+ goto err_check_version;
+
+ /* Reset device */
+ if ( ( rc = vmxnet3_command ( vmxnet, VMXNET3_CMD_RESET_DEV ) ) != 0 )
+ goto err_reset;
+
+ /* Read initial MAC address */
+ vmxnet3_get_hw_addr ( vmxnet, &netdev->hw_addr );
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
+ DBGC ( vmxnet, "VMXNET3 %p could not register net device: "
+ "%s\n", vmxnet, strerror ( rc ) );
+ goto err_register_netdev;
+ }
+
+ /* Get initial link state */
+ vmxnet3_check_link ( netdev );
+
+ return 0;
+
+ unregister_netdev ( netdev );
+ err_register_netdev:
+ err_reset:
+ err_check_version:
+ iounmap ( vmxnet->vd );
+ iounmap ( vmxnet->pt );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ err_alloc_etherdev:
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void vmxnet3_remove ( struct pci_device *pci ) {
+ struct net_device *netdev = pci_get_drvdata ( pci );
+ struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+
+ unregister_netdev ( netdev );
+ iounmap ( vmxnet->vd );
+ iounmap ( vmxnet->pt );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/** vmxnet3 PCI IDs */
+static struct pci_device_id vmxnet3_nics[] = {
+ PCI_ROM ( 0x15ad, 0x07b0, "vmxnet3", "vmxnet3 virtual NIC", 0 ),
+};
+
+/** vmxnet3 PCI driver */
+struct pci_driver vmxnet3_driver __pci_driver = {
+ .ids = vmxnet3_nics,
+ .id_count = ( sizeof ( vmxnet3_nics ) / sizeof ( vmxnet3_nics[0] ) ),
+ .probe = vmxnet3_probe,
+ .remove = vmxnet3_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/vmxnet3.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/vmxnet3.h
new file mode 100644
index 00000000..22a93539
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/vmxnet3.h
@@ -0,0 +1,497 @@
+#ifndef _VMXNET3_H
+#define _VMXNET3_H
+
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * VMware vmxnet3 virtual NIC driver
+ *
+ */
+
+#include <ipxe/pci.h>
+
+/** Maximum number of TX queues */
+#define VMXNET3_MAX_TX_QUEUES 8
+
+/** Maximum number of RX queues */
+#define VMXNET3_MAX_RX_QUEUES 16
+
+/** Maximum number of interrupts */
+#define VMXNET3_MAX_INTRS 25
+
+/** Maximum packet size */
+#define VMXNET3_MAX_PACKET_LEN 0x4000
+
+/** "PT" PCI BAR address */
+#define VMXNET3_PT_BAR PCI_BASE_ADDRESS_0
+
+/** "PT" PCI BAR size */
+#define VMXNET3_PT_LEN 0x1000
+
+/** Interrupt Mask Register */
+#define VMXNET3_PT_IMR 0x0
+
+/** Transmit producer index */
+#define VMXNET3_PT_TXPROD 0x600
+
+/** Rx producer index for ring 1 */
+#define VMXNET3_PT_RXPROD 0x800
+
+/** Rx producer index for ring 2 */
+#define VMXNET3_PT_RXPROD2 0xa00
+
+/** "VD" PCI BAR address */
+#define VMXNET3_VD_BAR PCI_BASE_ADDRESS_1
+
+/** "VD" PCI BAR size */
+#define VMXNET3_VD_LEN 0x1000
+
+/** vmxnet3 Revision Report Selection */
+#define VMXNET3_VD_VRRS 0x0
+
+/** UPT Version Report Selection */
+#define VMXNET3_VD_UVRS 0x8
+
+/** Driver Shared Address Low */
+#define VMXNET3_VD_DSAL 0x10
+
+/** Driver Shared Address High */
+#define VMXNET3_VD_DSAH 0x18
+
+/** Command */
+#define VMXNET3_VD_CMD 0x20
+
+/** MAC Address Low */
+#define VMXNET3_VD_MACL 0x28
+
+/** MAC Address High */
+#define VMXNET3_VD_MACH 0x30
+
+/** Interrupt Cause Register */
+#define VMXNET3_VD_ICR 0x38
+
+/** Event Cause Register */
+#define VMXNET3_VD_ECR 0x40
+
+/** Commands */
+enum vmxnet3_command {
+ VMXNET3_CMD_FIRST_SET = 0xcafe0000,
+ VMXNET3_CMD_ACTIVATE_DEV = VMXNET3_CMD_FIRST_SET,
+ VMXNET3_CMD_QUIESCE_DEV,
+ VMXNET3_CMD_RESET_DEV,
+ VMXNET3_CMD_UPDATE_RX_MODE,
+ VMXNET3_CMD_UPDATE_MAC_FILTERS,
+ VMXNET3_CMD_UPDATE_VLAN_FILTERS,
+ VMXNET3_CMD_UPDATE_RSSIDT,
+ VMXNET3_CMD_UPDATE_IML,
+ VMXNET3_CMD_UPDATE_PMCFG,
+ VMXNET3_CMD_UPDATE_FEATURE,
+ VMXNET3_CMD_LOAD_PLUGIN,
+
+ VMXNET3_CMD_FIRST_GET = 0xf00d0000,
+ VMXNET3_CMD_GET_QUEUE_STATUS = VMXNET3_CMD_FIRST_GET,
+ VMXNET3_CMD_GET_STATS,
+ VMXNET3_CMD_GET_LINK,
+ VMXNET3_CMD_GET_PERM_MAC_LO,
+ VMXNET3_CMD_GET_PERM_MAC_HI,
+ VMXNET3_CMD_GET_DID_LO,
+ VMXNET3_CMD_GET_DID_HI,
+ VMXNET3_CMD_GET_DEV_EXTRA_INFO,
+ VMXNET3_CMD_GET_CONF_INTR
+};
+
+/** Events */
+enum vmxnet3_event {
+ VMXNET3_ECR_RQERR = 0x00000001,
+ VMXNET3_ECR_TQERR = 0x00000002,
+ VMXNET3_ECR_LINK = 0x00000004,
+ VMXNET3_ECR_DIC = 0x00000008,
+ VMXNET3_ECR_DEBUG = 0x00000010,
+};
+
+/** Miscellaneous configuration descriptor */
+struct vmxnet3_misc_config {
+ /** Driver version */
+ uint32_t version;
+ /** Guest information */
+ uint32_t guest_info;
+ /** Version supported */
+ uint32_t version_support;
+ /** UPT version supported */
+ uint32_t upt_version_support;
+ /** UPT features supported */
+ uint64_t upt_features;
+ /** Driver-private data address */
+ uint64_t driver_data_address;
+ /** Queue descriptors data address */
+ uint64_t queue_desc_address;
+ /** Driver-private data length */
+ uint32_t driver_data_len;
+ /** Queue descriptors data length */
+ uint32_t queue_desc_len;
+ /** Maximum transmission unit */
+ uint32_t mtu;
+ /** Maximum number of RX scatter-gather */
+ uint16_t max_num_rx_sg;
+ /** Number of TX queues */
+ uint8_t num_tx_queues;
+ /** Number of RX queues */
+ uint8_t num_rx_queues;
+ /** Reserved */
+ uint32_t reserved0[4];
+} __attribute__ (( packed ));
+
+/** Driver version magic */
+#define VMXNET3_VERSION_MAGIC 0x69505845
+
+/** Interrupt configuration */
+struct vmxnet3_interrupt_config {
+ uint8_t mask_mode;
+ uint8_t num_intrs;
+ uint8_t event_intr_index;
+ uint8_t moderation_level[VMXNET3_MAX_INTRS];
+ uint32_t control;
+ uint32_t reserved0[2];
+} __attribute__ (( packed ));
+
+/** Interrupt control - disable all interrupts */
+#define VMXNET3_IC_DISABLE_ALL 0x1
+
+/** Receive filter configuration */
+struct vmxnet3_rx_filter_config {
+ /** Receive filter mode */
+ uint32_t mode;
+ /** Multicast filter table length */
+ uint16_t multicast_len;
+ /** Reserved */
+ uint16_t reserved0;
+ /** Multicast filter table address */
+ uint64_t multicast_address;
+ /** VLAN filter table (one bit per possible VLAN) */
+ uint8_t vlan_filter[512];
+} __attribute__ (( packed ));
+
+/** Receive filter mode */
+enum vmxnet3_rx_filter_mode {
+ VMXNET3_RXM_UCAST = 0x01, /**< Unicast only */
+ VMXNET3_RXM_MCAST = 0x02, /**< Multicast passing the filters */
+ VMXNET3_RXM_BCAST = 0x04, /**< Broadcast only */
+ VMXNET3_RXM_ALL_MULTI = 0x08, /**< All multicast */
+ VMXNET3_RXM_PROMISC = 0x10, /**< Promiscuous */
+};
+
+/** Variable-length configuration descriptor */
+struct vmxnet3_variable_config {
+ uint32_t version;
+ uint32_t length;
+ uint64_t address;
+} __attribute__ (( packed ));
+
+/** Driver shared area */
+struct vmxnet3_shared {
+ /** Magic signature */
+ uint32_t magic;
+ /** Reserved */
+ uint32_t reserved0;
+ /** Miscellaneous configuration */
+ struct vmxnet3_misc_config misc;
+ /** Interrupt configuration */
+ struct vmxnet3_interrupt_config interrupt;
+ /** Receive filter configuration */
+ struct vmxnet3_rx_filter_config rx_filter;
+ /** RSS configuration */
+ struct vmxnet3_variable_config rss;
+ /** Pattern-matching configuration */
+ struct vmxnet3_variable_config pattern;
+ /** Plugin configuration */
+ struct vmxnet3_variable_config plugin;
+ /** Event notifications */
+ uint32_t ecr;
+ /** Reserved */
+ uint32_t reserved1[5];
+} __attribute__ (( packed ));
+
+/** Alignment of driver shared area */
+#define VMXNET3_SHARED_ALIGN 8
+
+/** Driver shared area magic */
+#define VMXNET3_SHARED_MAGIC 0xbabefee1
+
+/** Transmit descriptor */
+struct vmxnet3_tx_desc {
+ /** Address */
+ uint64_t address;
+ /** Flags */
+ uint32_t flags[2];
+} __attribute__ (( packed ));
+
+/** Transmit generation flag */
+#define VMXNET3_TXF_GEN 0x00004000UL
+
+/** Transmit end-of-packet flag */
+#define VMXNET3_TXF_EOP 0x000001000UL
+
+/** Transmit completion request flag */
+#define VMXNET3_TXF_CQ 0x000002000UL
+
+/** Transmit completion descriptor */
+struct vmxnet3_tx_comp {
+ /** Index of the end-of-packet descriptor */
+ uint32_t index;
+ /** Reserved */
+ uint32_t reserved0[2];
+ /** Flags */
+ uint32_t flags;
+} __attribute__ (( packed ));
+
+/** Transmit completion generation flag */
+#define VMXNET3_TXCF_GEN 0x80000000UL
+
+/** Transmit queue control */
+struct vmxnet3_tx_queue_control {
+ uint32_t num_deferred;
+ uint32_t threshold;
+ uint64_t reserved0;
+} __attribute__ (( packed ));
+
+/** Transmit queue configuration */
+struct vmxnet3_tx_queue_config {
+ /** Descriptor ring address */
+ uint64_t desc_address;
+ /** Data ring address */
+ uint64_t immediate_address;
+ /** Completion ring address */
+ uint64_t comp_address;
+ /** Driver-private data address */
+ uint64_t driver_data_address;
+ /** Reserved */
+ uint64_t reserved0;
+ /** Number of descriptors */
+ uint32_t num_desc;
+ /** Number of data descriptors */
+ uint32_t num_immediate;
+ /** Number of completion descriptors */
+ uint32_t num_comp;
+ /** Driver-private data length */
+ uint32_t driver_data_len;
+ /** Interrupt index */
+ uint8_t intr_index;
+ /** Reserved */
+ uint8_t reserved[7];
+} __attribute__ (( packed ));
+
+/** Transmit queue statistics */
+struct vmxnet3_tx_stats {
+ /** Reserved */
+ uint64_t reserved[10];
+} __attribute__ (( packed ));
+
+/** Receive descriptor */
+struct vmxnet3_rx_desc {
+ /** Address */
+ uint64_t address;
+ /** Flags */
+ uint32_t flags;
+ /** Reserved */
+ uint32_t reserved0;
+} __attribute__ (( packed ));
+
+/** Receive generation flag */
+#define VMXNET3_RXF_GEN 0x80000000UL
+
+/** Receive completion descriptor */
+struct vmxnet3_rx_comp {
+ /** Descriptor index */
+ uint32_t index;
+ /** RSS hash value */
+ uint32_t rss;
+ /** Length */
+ uint32_t len;
+ /** Flags */
+ uint32_t flags;
+} __attribute__ (( packed ));
+
+/** Receive completion generation flag */
+#define VMXNET3_RXCF_GEN 0x80000000UL
+
+/** Receive queue control */
+struct vmxnet3_rx_queue_control {
+ uint8_t update_prod;
+ uint8_t reserved0[7];
+ uint64_t reserved1;
+} __attribute__ (( packed ));
+
+/** Receive queue configuration */
+struct vmxnet3_rx_queue_config {
+ /** Descriptor ring addresses */
+ uint64_t desc_address[2];
+ /** Completion ring address */
+ uint64_t comp_address;
+ /** Driver-private data address */
+ uint64_t driver_data_address;
+ /** Reserved */
+ uint64_t reserved0;
+ /** Number of descriptors */
+ uint32_t num_desc[2];
+ /** Number of completion descriptors */
+ uint32_t num_comp;
+ /** Driver-private data length */
+ uint32_t driver_data_len;
+ /** Interrupt index */
+ uint8_t intr_index;
+ /** Reserved */
+ uint8_t reserved[7];
+} __attribute__ (( packed ));
+
+/** Receive queue statistics */
+struct vmxnet3_rx_stats {
+ /** Reserved */
+ uint64_t reserved[10];
+} __attribute__ (( packed ));
+
+/** Queue status */
+struct vmxnet3_queue_status {
+ uint8_t stopped;
+ uint8_t reserved0[3];
+ uint32_t error;
+} __attribute__ (( packed ));
+
+/** Transmit queue descriptor */
+struct vmxnet3_tx_queue {
+ struct vmxnet3_tx_queue_control ctrl;
+ struct vmxnet3_tx_queue_config cfg;
+ struct vmxnet3_queue_status status;
+ struct vmxnet3_tx_stats state;
+ uint8_t reserved[88];
+} __attribute__ (( packed ));
+
+/** Receive queue descriptor */
+struct vmxnet3_rx_queue {
+ struct vmxnet3_rx_queue_control ctrl;
+ struct vmxnet3_rx_queue_config cfg;
+ struct vmxnet3_queue_status status;
+ struct vmxnet3_rx_stats stats;
+ uint8_t reserved[88];
+} __attribute__ (( packed ));
+
+/**
+ * Queue descriptor set
+ *
+ * We use only a single TX and RX queue
+ */
+struct vmxnet3_queues {
+ /** Transmit queue descriptor(s) */
+ struct vmxnet3_tx_queue tx;
+ /** Receive queue descriptor(s) */
+ struct vmxnet3_rx_queue rx;
+} __attribute__ (( packed ));
+
+/** Alignment of queue descriptor set */
+#define VMXNET3_QUEUES_ALIGN 128
+
+/** Alignment of rings */
+#define VMXNET3_RING_ALIGN 512
+
+/** Number of TX descriptors */
+#define VMXNET3_NUM_TX_DESC 32
+
+/** Number of TX completion descriptors */
+#define VMXNET3_NUM_TX_COMP 32
+
+/** Number of RX descriptors */
+#define VMXNET3_NUM_RX_DESC 32
+
+/** Number of RX completion descriptors */
+#define VMXNET3_NUM_RX_COMP 32
+
+/**
+ * DMA areas
+ *
+ * These are arranged in order of decreasing alignment, to allow for a
+ * single allocation
+ */
+struct vmxnet3_dma {
+ /** TX descriptor ring */
+ struct vmxnet3_tx_desc tx_desc[VMXNET3_NUM_TX_DESC];
+ /** TX completion ring */
+ struct vmxnet3_tx_comp tx_comp[VMXNET3_NUM_TX_COMP];
+ /** RX descriptor ring */
+ struct vmxnet3_rx_desc rx_desc[VMXNET3_NUM_RX_DESC];
+ /** RX completion ring */
+ struct vmxnet3_rx_comp rx_comp[VMXNET3_NUM_RX_COMP];
+ /** Queue descriptors */
+ struct vmxnet3_queues queues;
+ /** Shared area */
+ struct vmxnet3_shared shared;
+} __attribute__ (( packed ));
+
+/** DMA area alignment */
+#define VMXNET3_DMA_ALIGN 512
+
+/** Producer and consumer counters */
+struct vmxnet3_counters {
+ /** Transmit producer counter */
+ unsigned int tx_prod;
+ /** Transmit completion consumer counter */
+ unsigned int tx_cons;
+ /** Receive producer counter */
+ unsigned int rx_prod;
+ /** Receive fill level */
+ unsigned int rx_fill;
+ /** Receive consumer counter */
+ unsigned int rx_cons;
+};
+
+/** A vmxnet3 NIC */
+struct vmxnet3_nic {
+ /** "PT" register base address */
+ void *pt;
+ /** "VD" register base address */
+ void *vd;
+
+ /** DMA area */
+ struct vmxnet3_dma *dma;
+ /** Producer and consumer counters */
+ struct vmxnet3_counters count;
+ /** Transmit I/O buffers */
+ struct io_buffer *tx_iobuf[VMXNET3_NUM_TX_DESC];
+ /** Receive I/O buffers */
+ struct io_buffer *rx_iobuf[VMXNET3_NUM_RX_DESC];
+};
+
+/** vmxnet3 version that we support */
+#define VMXNET3_VERSION_SELECT 1
+
+/** UPT version that we support */
+#define VMXNET3_UPT_VERSION_SELECT 1
+
+/** MTU size */
+#define VMXNET3_MTU ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* FCS */ )
+
+/** Receive ring maximum fill level */
+#define VMXNET3_RX_FILL 8
+
+/** Received packet alignment padding */
+#define NET_IP_ALIGN 2
+
+#endif /* _VMXNET3_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge.c
new file mode 100644
index 00000000..bf20ec43
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge.c
@@ -0,0 +1,18 @@
+/** @file Stub file for vxge driver
+ *
+ * This file drags in the rest of the driver for Neterion Inc's X3100 Series
+ * 10GbE PCIe I/O Virtualized Server Adapter, allowing the driver to be built
+ * as "vxge" even though the code is in vxge_* named files.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <ipxe/pci.h>
+
+REQUIRE_OBJECT(vxge_main);
+
+/** vxge PCI IDs for util/parserom.pl which are put into bin/NIC */
+static struct pci_device_id vxge_nics[] __unused = {
+ /* If you change this, also adjust vxge_main_nics[] in vxge_main.c */
+ PCI_ROM(0x17d5, 0x5833, "vxge-x3100", "Neterion X3100 Series", 0),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_config.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_config.c
new file mode 100644
index 00000000..ba62b508
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_config.c
@@ -0,0 +1,1868 @@
+/*
+ * vxge-config.c: iPXE driver for Neterion Inc's X3100 Series 10GbE PCIe I/O
+ * Virtualized Server Adapter.
+ *
+ * Copyright(c) 2002-2010 Neterion Inc.
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice.
+ *
+ */
+
+FILE_LICENCE(GPL2_ONLY);
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ipxe/malloc.h>
+#include <ipxe/pci.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/ethernet.h>
+#include <byteswap.h>
+
+#include "vxge_traffic.h"
+#include "vxge_config.h"
+#include "vxge_main.h"
+
+void
+vxge_hw_vpath_set_zero_rx_frm_len(struct __vxge_hw_device *hldev)
+{
+ u64 val64;
+ struct __vxge_hw_virtualpath *vpath;
+ struct vxge_hw_vpath_reg __iomem *vp_reg;
+
+ vpath = &hldev->virtual_path;
+ vp_reg = vpath->vp_reg;
+
+ val64 = readq(&vp_reg->rxmac_vcfg0);
+ val64 &= ~VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(0x3fff);
+ writeq(val64, &vp_reg->rxmac_vcfg0);
+ val64 = readq(&vp_reg->rxmac_vcfg0);
+ return;
+}
+
+enum vxge_hw_status
+vxge_hw_set_fw_api(struct __vxge_hw_device *hldev,
+ u64 vp_id,
+ u32 action,
+ u32 offset,
+ u64 data0,
+ u64 data1)
+{
+ enum vxge_hw_status status = VXGE_HW_OK;
+ u64 val64;
+ u32 fw_memo = VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO;
+
+ struct vxge_hw_vpath_reg __iomem *vp_reg;
+
+ vp_reg = (struct vxge_hw_vpath_reg __iomem *)hldev->vpath_reg[vp_id];
+
+ writeq(data0, &vp_reg->rts_access_steer_data0);
+ writeq(data1, &vp_reg->rts_access_steer_data1);
+
+ wmb();
+
+ val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(action) |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(fw_memo) |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(offset) |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE;
+
+ writeq(val64, &vp_reg->rts_access_steer_ctrl);
+
+ wmb();
+
+ status = __vxge_hw_device_register_poll(
+ &vp_reg->rts_access_steer_ctrl,
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
+ WAIT_FACTOR *
+ VXGE_HW_DEF_DEVICE_POLL_MILLIS);
+
+ if (status != VXGE_HW_OK)
+ return VXGE_HW_FAIL;
+
+ val64 = readq(&vp_reg->rts_access_steer_ctrl);
+
+ if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS)
+ status = VXGE_HW_OK;
+ else
+ status = VXGE_HW_FAIL;
+
+ return status;
+}
+
+/* Get function mode */
+enum vxge_hw_status
+vxge_hw_get_func_mode(struct __vxge_hw_device *hldev, u32 *func_mode)
+{
+ enum vxge_hw_status status = VXGE_HW_OK;
+ struct vxge_hw_vpath_reg __iomem *vp_reg;
+ u64 val64;
+ int vp_id;
+
+ /* get the first vpath number assigned to this function */
+ vp_id = hldev->first_vp_id;
+
+ vp_reg = (struct vxge_hw_vpath_reg __iomem *)hldev->vpath_reg[vp_id];
+
+ status = vxge_hw_set_fw_api(hldev, vp_id,
+ VXGE_HW_FW_API_GET_FUNC_MODE, 0, 0, 0);
+
+ if (status == VXGE_HW_OK) {
+ val64 = readq(&vp_reg->rts_access_steer_data0);
+ *func_mode = VXGE_HW_GET_FUNC_MODE_VAL(val64);
+ }
+
+ return status;
+}
+
+/*
+ * __vxge_hw_device_pci_e_init
+ * Initialize certain PCI/PCI-X configuration registers
+ * with recommended values. Save config space for future hw resets.
+ */
+void
+__vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev)
+{
+ u16 cmd = 0;
+ struct pci_device *pdev = hldev->pdev;
+
+ vxge_trace();
+
+ /* Set the PErr Repconse bit and SERR in PCI command register. */
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ cmd |= 0x140;
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+
+ return;
+}
+
+/*
+ * __vxge_hw_device_register_poll
+ * Will poll certain register for specified amount of time.
+ * Will poll until masked bit is not cleared.
+ */
+enum vxge_hw_status
+__vxge_hw_device_register_poll(void __iomem *reg, u64 mask, u32 max_millis)
+{
+ u64 val64;
+ u32 i = 0;
+ enum vxge_hw_status ret = VXGE_HW_FAIL;
+
+ udelay(10);
+
+ do {
+ val64 = readq(reg);
+ if (!(val64 & mask))
+ return VXGE_HW_OK;
+ udelay(100);
+ } while (++i <= 9);
+
+ i = 0;
+ do {
+ val64 = readq(reg);
+ if (!(val64 & mask))
+ return VXGE_HW_OK;
+ udelay(1000);
+ } while (++i <= max_millis);
+
+ return ret;
+}
+
+ /* __vxge_hw_device_vpath_reset_in_prog_check - Check if vpath reset
+ * in progress
+ * This routine checks the vpath reset in progress register is turned zero
+ */
+enum vxge_hw_status
+__vxge_hw_device_vpath_reset_in_prog_check(u64 __iomem *vpath_rst_in_prog)
+{
+ enum vxge_hw_status status;
+
+ vxge_trace();
+
+ status = __vxge_hw_device_register_poll(vpath_rst_in_prog,
+ VXGE_HW_VPATH_RST_IN_PROG_VPATH_RST_IN_PROG(0x1ffff),
+ VXGE_HW_DEF_DEVICE_POLL_MILLIS);
+ return status;
+}
+
+/*
+ * __vxge_hw_device_get_legacy_reg
+ * This routine gets the legacy register section's memory mapped address
+ * and sets the swapper.
+ */
+static struct vxge_hw_legacy_reg __iomem *
+__vxge_hw_device_get_legacy_reg(struct pci_device *pdev, void __iomem *bar0)
+{
+ enum vxge_hw_status status;
+ struct vxge_hw_legacy_reg __iomem *legacy_reg;
+ /*
+ * If the length of Bar0 is 16MB, then assume that we are configured
+ * in MF8P_VP2 mode and then add 8MB to the legacy_reg offsets
+ */
+ if (pci_bar_size(pdev, PCI_BASE_ADDRESS_0) == 0x1000000)
+ legacy_reg = (struct vxge_hw_legacy_reg __iomem *)
+ (bar0 + 0x800000);
+ else
+ legacy_reg = (struct vxge_hw_legacy_reg __iomem *)bar0;
+
+ status = __vxge_hw_legacy_swapper_set(legacy_reg);
+ if (status != VXGE_HW_OK)
+ return NULL;
+
+ return legacy_reg;
+}
+/*
+ * __vxge_hw_device_toc_get
+ * This routine sets the swapper and reads the toc pointer and returns the
+ * memory mapped address of the toc
+ */
+struct vxge_hw_toc_reg __iomem *
+__vxge_hw_device_toc_get(void __iomem *bar0,
+ struct vxge_hw_legacy_reg __iomem *legacy_reg)
+{
+ u64 val64;
+ struct vxge_hw_toc_reg __iomem *toc = NULL;
+
+ val64 = readq(&legacy_reg->toc_first_pointer);
+ toc = (struct vxge_hw_toc_reg __iomem *)(bar0+val64);
+
+ return toc;
+}
+
+/*
+ * __vxge_hw_device_reg_addr_get
+ * This routine sets the swapper and reads the toc pointer and initializes the
+ * register location pointers in the device object. It waits until the ric is
+ * completed initializing registers.
+ */
+enum vxge_hw_status
+__vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev)
+{
+ u64 val64;
+ u32 i;
+ enum vxge_hw_status status = VXGE_HW_OK;
+
+ hldev->legacy_reg = __vxge_hw_device_get_legacy_reg(hldev->pdev,
+ hldev->bar0);
+ if (hldev->legacy_reg == NULL) {
+ status = VXGE_HW_FAIL;
+ goto exit;
+ }
+
+ hldev->toc_reg = __vxge_hw_device_toc_get(hldev->bar0,
+ hldev->legacy_reg);
+ if (hldev->toc_reg == NULL) {
+ status = VXGE_HW_FAIL;
+ goto exit;
+ }
+
+ val64 = readq(&hldev->toc_reg->toc_common_pointer);
+ hldev->common_reg =
+ (struct vxge_hw_common_reg __iomem *)(hldev->bar0 + val64);
+
+ val64 = readq(&hldev->toc_reg->toc_mrpcim_pointer);
+ hldev->mrpcim_reg =
+ (struct vxge_hw_mrpcim_reg __iomem *)(hldev->bar0 + val64);
+
+ for (i = 0; i < VXGE_HW_TITAN_SRPCIM_REG_SPACES; i++) {
+ val64 = readq(&hldev->toc_reg->toc_srpcim_pointer[i]);
+ hldev->srpcim_reg[i] =
+ (struct vxge_hw_srpcim_reg __iomem *)
+ (hldev->bar0 + val64);
+ }
+
+ for (i = 0; i < VXGE_HW_TITAN_VPMGMT_REG_SPACES; i++) {
+ val64 = readq(&hldev->toc_reg->toc_vpmgmt_pointer[i]);
+ hldev->vpmgmt_reg[i] =
+ (struct vxge_hw_vpmgmt_reg __iomem *)(hldev->bar0 + val64);
+ }
+
+ for (i = 0; i < VXGE_HW_TITAN_VPATH_REG_SPACES; i++) {
+ val64 = readq(&hldev->toc_reg->toc_vpath_pointer[i]);
+ hldev->vpath_reg[i] =
+ (struct vxge_hw_vpath_reg __iomem *)
+ (hldev->bar0 + val64);
+ }
+
+ val64 = readq(&hldev->toc_reg->toc_kdfc);
+
+ switch (VXGE_HW_TOC_GET_KDFC_INITIAL_BIR(val64)) {
+ case 0:
+ hldev->kdfc = (u8 __iomem *)(hldev->bar0 +
+ VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64));
+ break;
+ default:
+ break;
+ }
+
+ status = __vxge_hw_device_vpath_reset_in_prog_check(
+ (u64 __iomem *)&hldev->common_reg->vpath_rst_in_prog);
+exit:
+ return status;
+}
+
+/*
+ * __vxge_hw_device_access_rights_get: Get Access Rights of the driver
+ * This routine returns the Access Rights of the driver
+ */
+static u32
+__vxge_hw_device_access_rights_get(u32 host_type, u32 func_id)
+{
+ u32 access_rights = VXGE_HW_DEVICE_ACCESS_RIGHT_VPATH;
+
+ switch (host_type) {
+ case VXGE_HW_NO_MR_NO_SR_NORMAL_FUNCTION:
+ if (func_id == 0) {
+ access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM |
+ VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
+ }
+ break;
+ case VXGE_HW_MR_NO_SR_VH0_BASE_FUNCTION:
+ access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM |
+ VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
+ break;
+ case VXGE_HW_NO_MR_SR_VH0_FUNCTION0:
+ access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM |
+ VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
+ break;
+ case VXGE_HW_NO_MR_SR_VH0_VIRTUAL_FUNCTION:
+ case VXGE_HW_SR_VH_VIRTUAL_FUNCTION:
+ case VXGE_HW_MR_SR_VH0_INVALID_CONFIG:
+ break;
+ case VXGE_HW_SR_VH_FUNCTION0:
+ case VXGE_HW_VH_NORMAL_FUNCTION:
+ access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
+ break;
+ }
+
+ return access_rights;
+}
+
+/*
+ * __vxge_hw_device_host_info_get
+ * This routine returns the host type assignments
+ */
+void __vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev)
+{
+ u64 val64;
+ u32 i;
+
+ val64 = readq(&hldev->common_reg->host_type_assignments);
+
+ hldev->host_type =
+ (u32)VXGE_HW_HOST_TYPE_ASSIGNMENTS_GET_HOST_TYPE_ASSIGNMENTS(val64);
+
+ hldev->vpath_assignments = readq(&hldev->common_reg->vpath_assignments);
+
+ for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
+
+ if (!(hldev->vpath_assignments & vxge_mBIT(i)))
+ continue;
+
+ hldev->func_id =
+ __vxge_hw_vpath_func_id_get(hldev->vpmgmt_reg[i]);
+
+ hldev->access_rights = __vxge_hw_device_access_rights_get(
+ hldev->host_type, hldev->func_id);
+
+ hldev->first_vp_id = i;
+ break;
+ }
+
+ return;
+}
+
+/**
+ * vxge_hw_device_hw_info_get - Get the hw information
+ * Returns the vpath mask that has the bits set for each vpath allocated
+ * for the driver, FW version information and the first mac addresse for
+ * each vpath
+ */
+enum vxge_hw_status
+vxge_hw_device_hw_info_get(struct pci_device *pdev, void __iomem *bar0,
+ struct vxge_hw_device_hw_info *hw_info)
+{
+ u32 i;
+ u64 val64;
+ struct vxge_hw_toc_reg __iomem *toc;
+ struct vxge_hw_mrpcim_reg __iomem *mrpcim_reg;
+ struct vxge_hw_common_reg __iomem *common_reg;
+ struct vxge_hw_vpath_reg __iomem *vpath_reg;
+ struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg;
+ struct vxge_hw_legacy_reg __iomem *legacy_reg;
+ enum vxge_hw_status status;
+
+ vxge_trace();
+
+ memset(hw_info, 0, sizeof(struct vxge_hw_device_hw_info));
+
+ legacy_reg = __vxge_hw_device_get_legacy_reg(pdev, bar0);
+ if (legacy_reg == NULL) {
+ status = VXGE_HW_ERR_CRITICAL;
+ goto exit;
+ }
+
+ toc = __vxge_hw_device_toc_get(bar0, legacy_reg);
+ if (toc == NULL) {
+ status = VXGE_HW_ERR_CRITICAL;
+ goto exit;
+ }
+
+ val64 = readq(&toc->toc_common_pointer);
+ common_reg = (struct vxge_hw_common_reg __iomem *)(bar0 + val64);
+
+ status = __vxge_hw_device_vpath_reset_in_prog_check(
+ (u64 __iomem *)&common_reg->vpath_rst_in_prog);
+ if (status != VXGE_HW_OK)
+ goto exit;
+
+ hw_info->vpath_mask = readq(&common_reg->vpath_assignments);
+
+ val64 = readq(&common_reg->host_type_assignments);
+
+ hw_info->host_type =
+ (u32)VXGE_HW_HOST_TYPE_ASSIGNMENTS_GET_HOST_TYPE_ASSIGNMENTS(val64);
+
+ for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
+
+ if (!((hw_info->vpath_mask) & vxge_mBIT(i)))
+ continue;
+
+ val64 = readq(&toc->toc_vpmgmt_pointer[i]);
+
+ vpmgmt_reg = (struct vxge_hw_vpmgmt_reg __iomem *)
+ (bar0 + val64);
+
+ hw_info->func_id = __vxge_hw_vpath_func_id_get(vpmgmt_reg);
+ if (__vxge_hw_device_access_rights_get(hw_info->host_type,
+ hw_info->func_id) &
+ VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM) {
+
+ val64 = readq(&toc->toc_mrpcim_pointer);
+
+ mrpcim_reg = (struct vxge_hw_mrpcim_reg __iomem *)
+ (bar0 + val64);
+
+ writeq(0, &mrpcim_reg->xgmac_gen_fw_memo_mask);
+ wmb();
+ }
+
+ val64 = readq(&toc->toc_vpath_pointer[i]);
+
+ vpath_reg = (struct vxge_hw_vpath_reg __iomem *)(bar0 + val64);
+
+ status = __vxge_hw_vpath_fw_ver_get(vpath_reg, hw_info);
+ if (status != VXGE_HW_OK)
+ goto exit;
+
+ status = __vxge_hw_vpath_card_info_get(vpath_reg, hw_info);
+ if (status != VXGE_HW_OK)
+ goto exit;
+
+ break;
+ }
+
+ for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
+
+ if (!((hw_info->vpath_mask) & vxge_mBIT(i)))
+ continue;
+
+ val64 = readq(&toc->toc_vpath_pointer[i]);
+ vpath_reg = (struct vxge_hw_vpath_reg __iomem *)(bar0 + val64);
+
+ status = __vxge_hw_vpath_addr_get(vpath_reg,
+ hw_info->mac_addrs[i],
+ hw_info->mac_addr_masks[i]);
+ if (status != VXGE_HW_OK)
+ goto exit;
+ }
+exit:
+ return status;
+}
+
+/*
+ * vxge_hw_device_initialize - Initialize Titan device.
+ * Initialize Titan device. Note that all the arguments of this public API
+ * are 'IN', including @hldev. Driver cooperates with
+ * OS to find new Titan device, locate its PCI and memory spaces.
+ *
+ * When done, the driver allocates sizeof(struct __vxge_hw_device) bytes for HW
+ * to enable the latter to perform Titan hardware initialization.
+ */
+enum vxge_hw_status
+vxge_hw_device_initialize(
+ struct __vxge_hw_device **devh,
+ void *bar0,
+ struct pci_device *pdev,
+ u8 titan1)
+{
+ struct __vxge_hw_device *hldev = NULL;
+ enum vxge_hw_status status = VXGE_HW_OK;
+
+ vxge_trace();
+
+ hldev = (struct __vxge_hw_device *)
+ zalloc(sizeof(struct __vxge_hw_device));
+ if (hldev == NULL) {
+ vxge_debug(VXGE_ERR, "hldev allocation failed\n");
+ status = VXGE_HW_ERR_OUT_OF_MEMORY;
+ goto exit;
+ }
+
+ hldev->magic = VXGE_HW_DEVICE_MAGIC;
+
+ hldev->bar0 = bar0;
+ hldev->pdev = pdev;
+ hldev->titan1 = titan1;
+
+ __vxge_hw_device_pci_e_init(hldev);
+
+ status = __vxge_hw_device_reg_addr_get(hldev);
+ if (status != VXGE_HW_OK) {
+ vxge_debug(VXGE_ERR, "%s:%d __vxge_hw_device_reg_addr_get "
+ "failed\n", __func__, __LINE__);
+ vxge_hw_device_terminate(hldev);
+ goto exit;
+ }
+
+ __vxge_hw_device_host_info_get(hldev);
+
+ *devh = hldev;
+exit:
+ return status;
+}
+
+/*
+ * vxge_hw_device_terminate - Terminate Titan device.
+ * Terminate HW device.
+ */
+void
+vxge_hw_device_terminate(struct __vxge_hw_device *hldev)
+{
+ vxge_trace();
+
+ assert(hldev->magic == VXGE_HW_DEVICE_MAGIC);
+
+ hldev->magic = VXGE_HW_DEVICE_DEAD;
+ free(hldev);
+}
+
+/*
+ *vxge_hw_ring_replenish - Initial replenish of RxDs
+ * This function replenishes the RxDs from reserve array to work array
+ */
+enum vxge_hw_status
+vxge_hw_ring_replenish(struct __vxge_hw_ring *ring)
+{
+ struct __vxge_hw_device *hldev;
+ struct vxge_hw_ring_rxd_1 *rxd;
+ enum vxge_hw_status status = VXGE_HW_OK;
+ u8 offset = 0;
+ struct __vxge_hw_ring_block *block;
+ u8 i, iob_off;
+
+ vxge_trace();
+
+ hldev = ring->vpathh->hldev;
+ /*
+ * We allocate all the dma buffers first and then share the
+ * these buffers among the all rx descriptors in the block.
+ */
+ for (i = 0; i < ARRAY_SIZE(ring->iobuf); i++) {
+ ring->iobuf[i] = alloc_iob(VXGE_LL_MAX_FRAME_SIZE(hldev->vdev));
+ if (!ring->iobuf[i]) {
+ while (i) {
+ free_iob(ring->iobuf[--i]);
+ ring->iobuf[i] = NULL;
+ }
+ status = VXGE_HW_ERR_OUT_OF_MEMORY;
+ goto iobuf_err;
+ }
+ }
+
+ for (offset = 0; offset < VXGE_HW_MAX_RXDS_PER_BLOCK_1; offset++) {
+
+ rxd = &ring->rxdl->rxd[offset];
+ if (offset == (VXGE_HW_MAX_RXDS_PER_BLOCK_1 - 1))
+ iob_off = VXGE_HW_RING_BUF_PER_BLOCK;
+ else
+ iob_off = offset % ring->buf_per_block;
+
+ rxd->control_0 = rxd->control_1 = 0;
+ vxge_hw_ring_rxd_1b_set(rxd, ring->iobuf[iob_off],
+ VXGE_LL_MAX_FRAME_SIZE(hldev->vdev));
+
+ vxge_hw_ring_rxd_post(ring, rxd);
+ }
+ /* linking the block to itself as we use only one rx block*/
+ block = ring->rxdl;
+ block->reserved_2_pNext_RxD_block = (unsigned long) block;
+ block->pNext_RxD_Blk_physical = (u64)virt_to_bus(block);
+
+ ring->rxd_offset = 0;
+iobuf_err:
+ return status;
+}
+
+/*
+ * __vxge_hw_ring_create - Create a Ring
+ * This function creates Ring and initializes it.
+ *
+ */
+enum vxge_hw_status
+__vxge_hw_ring_create(struct __vxge_hw_virtualpath *vpath,
+ struct __vxge_hw_ring *ring)
+{
+ enum vxge_hw_status status = VXGE_HW_OK;
+ struct __vxge_hw_device *hldev;
+ u32 vp_id;
+
+ vxge_trace();
+
+ hldev = vpath->hldev;
+ vp_id = vpath->vp_id;
+
+ ring->rxdl = malloc_dma(sizeof(struct __vxge_hw_ring_block),
+ sizeof(struct __vxge_hw_ring_block));
+ if (!ring->rxdl) {
+ vxge_debug(VXGE_ERR, "%s:%d malloc_dma error\n",
+ __func__, __LINE__);
+ status = VXGE_HW_ERR_OUT_OF_MEMORY;
+ goto exit;
+ }
+ ring->rxd_offset = 0;
+ ring->vpathh = vpath;
+ ring->buf_per_block = VXGE_HW_RING_BUF_PER_BLOCK;
+ ring->rx_poll_weight = VXGE_HW_RING_RX_POLL_WEIGHT;
+ ring->vp_id = vp_id;
+ ring->vp_reg = vpath->vp_reg;
+ ring->common_reg = hldev->common_reg;
+
+ ring->rxd_qword_limit = VXGE_HW_RING_RXD_QWORD_LIMIT;
+
+ status = vxge_hw_ring_replenish(ring);
+ if (status != VXGE_HW_OK) {
+ __vxge_hw_ring_delete(ring);
+ goto exit;
+ }
+exit:
+ return status;
+}
+
+/*
+ * __vxge_hw_ring_delete - Removes the ring
+ * This function freeup the memory pool and removes the ring
+ */
+enum vxge_hw_status __vxge_hw_ring_delete(struct __vxge_hw_ring *ring)
+{
+ u8 i;
+
+ vxge_trace();
+
+ for (i = 0; (i < ARRAY_SIZE(ring->iobuf)) && ring->iobuf[i]; i++) {
+ free_iob(ring->iobuf[i]);
+ ring->iobuf[i] = NULL;
+ }
+
+ if (ring->rxdl) {
+ free_dma(ring->rxdl, sizeof(struct __vxge_hw_ring_block));
+ ring->rxdl = NULL;
+ }
+ ring->rxd_offset = 0;
+
+ return VXGE_HW_OK;
+}
+
+/*
+ * _hw_legacy_swapper_set - Set the swapper bits for the legacy secion.
+ * Set the swapper bits appropriately for the legacy section.
+ */
+enum vxge_hw_status
+__vxge_hw_legacy_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg)
+{
+ u64 val64;
+ enum vxge_hw_status status = VXGE_HW_OK;
+
+ vxge_trace();
+
+ val64 = readq(&legacy_reg->toc_swapper_fb);
+
+ wmb();
+
+ switch (val64) {
+
+ case VXGE_HW_SWAPPER_INITIAL_VALUE:
+ return status;
+
+ case VXGE_HW_SWAPPER_BYTE_SWAPPED_BIT_FLIPPED:
+ writeq(VXGE_HW_SWAPPER_READ_BYTE_SWAP_ENABLE,
+ &legacy_reg->pifm_rd_swap_en);
+ writeq(VXGE_HW_SWAPPER_READ_BIT_FLAP_ENABLE,
+ &legacy_reg->pifm_rd_flip_en);
+ writeq(VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE,
+ &legacy_reg->pifm_wr_swap_en);
+ writeq(VXGE_HW_SWAPPER_WRITE_BIT_FLAP_ENABLE,
+ &legacy_reg->pifm_wr_flip_en);
+ break;
+
+ case VXGE_HW_SWAPPER_BYTE_SWAPPED:
+ writeq(VXGE_HW_SWAPPER_READ_BYTE_SWAP_ENABLE,
+ &legacy_reg->pifm_rd_swap_en);
+ writeq(VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE,
+ &legacy_reg->pifm_wr_swap_en);
+ break;
+
+ case VXGE_HW_SWAPPER_BIT_FLIPPED:
+ writeq(VXGE_HW_SWAPPER_READ_BIT_FLAP_ENABLE,
+ &legacy_reg->pifm_rd_flip_en);
+ writeq(VXGE_HW_SWAPPER_WRITE_BIT_FLAP_ENABLE,
+ &legacy_reg->pifm_wr_flip_en);
+ break;
+ }
+
+ wmb();
+
+ val64 = readq(&legacy_reg->toc_swapper_fb);
+ if (val64 != VXGE_HW_SWAPPER_INITIAL_VALUE)
+ status = VXGE_HW_ERR_SWAPPER_CTRL;
+
+ return status;
+}
+
+/*
+ * __vxge_hw_vpath_swapper_set - Set the swapper bits for the vpath.
+ * Set the swapper bits appropriately for the vpath.
+ */
+enum vxge_hw_status
+__vxge_hw_vpath_swapper_set(struct vxge_hw_vpath_reg __iomem *vpath_reg)
+{
+ vxge_trace();
+
+#if (__BYTE_ORDER != __BIG_ENDIAN)
+ u64 val64;
+
+ val64 = readq(&vpath_reg->vpath_general_cfg1);
+ wmb();
+ val64 |= VXGE_HW_VPATH_GENERAL_CFG1_CTL_BYTE_SWAPEN;
+ writeq(val64, &vpath_reg->vpath_general_cfg1);
+ wmb();
+#endif
+ return VXGE_HW_OK;
+}
+
+/*
+ * __vxge_hw_kdfc_swapper_set - Set the swapper bits for the kdfc.
+ * Set the swapper bits appropriately for the vpath.
+ */
+enum vxge_hw_status
+__vxge_hw_kdfc_swapper_set(
+ struct vxge_hw_legacy_reg __iomem *legacy_reg,
+ struct vxge_hw_vpath_reg __iomem *vpath_reg)
+{
+ u64 val64;
+
+ vxge_trace();
+
+ val64 = readq(&legacy_reg->pifm_wr_swap_en);
+
+ if (val64 == VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE) {
+ val64 = readq(&vpath_reg->kdfcctl_cfg0);
+ wmb();
+
+ val64 |= VXGE_HW_KDFCCTL_CFG0_BYTE_SWAPEN_FIFO0 |
+ VXGE_HW_KDFCCTL_CFG0_BYTE_SWAPEN_FIFO1 |
+ VXGE_HW_KDFCCTL_CFG0_BYTE_SWAPEN_FIFO2;
+
+ writeq(val64, &vpath_reg->kdfcctl_cfg0);
+ wmb();
+ }
+
+ return VXGE_HW_OK;
+}
+
+/*
+ * vxge_hw_vpath_strip_fcs_check - Check for FCS strip.
+ */
+enum vxge_hw_status
+vxge_hw_vpath_strip_fcs_check(struct __vxge_hw_device *hldev, u64 vpath_mask)
+{
+ struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg;
+ enum vxge_hw_status status = VXGE_HW_OK;
+ int i = 0, j = 0;
+
+ for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
+ if (!((vpath_mask) & vxge_mBIT(i)))
+ continue;
+ vpmgmt_reg = hldev->vpmgmt_reg[i];
+ for (j = 0; j < VXGE_HW_MAC_MAX_MAC_PORT_ID; j++) {
+ if (readq(&vpmgmt_reg->rxmac_cfg0_port_vpmgmt_clone[j])
+ & VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_STRIP_FCS)
+ return VXGE_HW_FAIL;
+ }
+ }
+ return status;
+}
+
+/*
+ * __vxge_hw_fifo_create - Create a FIFO
+ * This function creates FIFO and initializes it.
+ */
+enum vxge_hw_status
+__vxge_hw_fifo_create(struct __vxge_hw_virtualpath *vpath,
+ struct __vxge_hw_fifo *fifo)
+{
+ enum vxge_hw_status status = VXGE_HW_OK;
+
+ vxge_trace();
+
+ fifo->vpathh = vpath;
+ fifo->depth = VXGE_HW_FIFO_TXD_DEPTH;
+ fifo->hw_offset = fifo->sw_offset = 0;
+ fifo->nofl_db = vpath->nofl_db;
+ fifo->vp_id = vpath->vp_id;
+ fifo->vp_reg = vpath->vp_reg;
+ fifo->tx_intr_num = (vpath->vp_id * VXGE_HW_MAX_INTR_PER_VP)
+ + VXGE_HW_VPATH_INTR_TX;
+
+ fifo->txdl = malloc_dma(sizeof(struct vxge_hw_fifo_txd)
+ * fifo->depth, fifo->depth);
+ if (!fifo->txdl) {
+ vxge_debug(VXGE_ERR, "%s:%d malloc_dma error\n",
+ __func__, __LINE__);
+ return VXGE_HW_ERR_OUT_OF_MEMORY;
+ }
+ memset(fifo->txdl, 0, sizeof(struct vxge_hw_fifo_txd) * fifo->depth);
+ return status;
+}
+
+/*
+ * __vxge_hw_fifo_delete - Removes the FIFO
+ * This function freeup the memory pool and removes the FIFO
+ */
+enum vxge_hw_status __vxge_hw_fifo_delete(struct __vxge_hw_fifo *fifo)
+{
+ vxge_trace();
+
+ if (fifo->txdl)
+ free_dma(fifo->txdl,
+ sizeof(struct vxge_hw_fifo_txd) * fifo->depth);
+
+ fifo->txdl = NULL;
+ fifo->hw_offset = fifo->sw_offset = 0;
+
+ return VXGE_HW_OK;
+}
+
+/*
+ * __vxge_hw_vpath_pci_read - Read the content of given address
+ * in pci config space.
+ * Read from the vpath pci config space.
+ */
+enum vxge_hw_status
+__vxge_hw_vpath_pci_read(struct __vxge_hw_virtualpath *vpath,
+ u32 phy_func_0, u32 offset, u32 *val)
+{
+ u64 val64;
+ enum vxge_hw_status status = VXGE_HW_OK;
+ struct vxge_hw_vpath_reg __iomem *vp_reg = vpath->vp_reg;
+
+ val64 = VXGE_HW_PCI_CONFIG_ACCESS_CFG1_ADDRESS(offset);
+
+ if (phy_func_0)
+ val64 |= VXGE_HW_PCI_CONFIG_ACCESS_CFG1_SEL_FUNC0;
+
+ writeq(val64, &vp_reg->pci_config_access_cfg1);
+ wmb();
+ writeq(VXGE_HW_PCI_CONFIG_ACCESS_CFG2_REQ,
+ &vp_reg->pci_config_access_cfg2);
+ wmb();
+
+ status = __vxge_hw_device_register_poll(
+ &vp_reg->pci_config_access_cfg2,
+ VXGE_HW_INTR_MASK_ALL, VXGE_HW_DEF_DEVICE_POLL_MILLIS);
+
+ if (status != VXGE_HW_OK)
+ goto exit;
+
+ val64 = readq(&vp_reg->pci_config_access_status);
+
+ if (val64 & VXGE_HW_PCI_CONFIG_ACCESS_STATUS_ACCESS_ERR) {
+ status = VXGE_HW_FAIL;
+ *val = 0;
+ } else
+ *val = (u32)vxge_bVALn(val64, 32, 32);
+exit:
+ return status;
+}
+
+/*
+ * __vxge_hw_vpath_func_id_get - Get the function id of the vpath.
+ * Returns the function number of the vpath.
+ */
+u32
+__vxge_hw_vpath_func_id_get(struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg)
+{
+ u64 val64;
+
+ val64 = readq(&vpmgmt_reg->vpath_to_func_map_cfg1);
+
+ return
+ (u32)VXGE_HW_VPATH_TO_FUNC_MAP_CFG1_GET_VPATH_TO_FUNC_MAP_CFG1(val64);
+}
+
+/*
+ * __vxge_hw_read_rts_ds - Program RTS steering critieria
+ */
+static inline void
+__vxge_hw_read_rts_ds(struct vxge_hw_vpath_reg __iomem *vpath_reg,
+ u64 dta_struct_sel)
+{
+ writeq(0, &vpath_reg->rts_access_steer_ctrl);
+ wmb();
+ writeq(dta_struct_sel, &vpath_reg->rts_access_steer_data0);
+ writeq(0, &vpath_reg->rts_access_steer_data1);
+ wmb();
+ return;
+}
+
+/*
+ * __vxge_hw_vpath_card_info_get - Get the serial numbers,
+ * part number and product description.
+ */
+enum vxge_hw_status
+__vxge_hw_vpath_card_info_get(
+ struct vxge_hw_vpath_reg __iomem *vpath_reg,
+ struct vxge_hw_device_hw_info *hw_info)
+{
+ u32 i, j;
+ u64 val64;
+ u64 data1 = 0ULL;
+ u64 data2 = 0ULL;
+ enum vxge_hw_status status = VXGE_HW_OK;
+ u8 *serial_number = hw_info->serial_number;
+ u8 *part_number = hw_info->part_number;
+ u8 *product_desc = hw_info->product_desc;
+
+ __vxge_hw_read_rts_ds(vpath_reg,
+ VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_SERIAL_NUMBER);
+
+ val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY) |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0);
+
+ status = __vxge_hw_pio_mem_write64(val64,
+ &vpath_reg->rts_access_steer_ctrl,
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
+ VXGE_HW_DEF_DEVICE_POLL_MILLIS);
+
+ if (status != VXGE_HW_OK)
+ return status;
+
+ val64 = readq(&vpath_reg->rts_access_steer_ctrl);
+
+ if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
+ data1 = readq(&vpath_reg->rts_access_steer_data0);
+ ((u64 *)serial_number)[0] = be64_to_cpu(data1);
+
+ data2 = readq(&vpath_reg->rts_access_steer_data1);
+ ((u64 *)serial_number)[1] = be64_to_cpu(data2);
+ status = VXGE_HW_OK;
+ } else
+ *serial_number = 0;
+
+ __vxge_hw_read_rts_ds(vpath_reg,
+ VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PART_NUMBER);
+
+ val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY) |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0);
+
+ status = __vxge_hw_pio_mem_write64(val64,
+ &vpath_reg->rts_access_steer_ctrl,
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
+ VXGE_HW_DEF_DEVICE_POLL_MILLIS);
+
+ if (status != VXGE_HW_OK)
+ return status;
+
+ val64 = readq(&vpath_reg->rts_access_steer_ctrl);
+
+ if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
+
+ data1 = readq(&vpath_reg->rts_access_steer_data0);
+ ((u64 *)part_number)[0] = be64_to_cpu(data1);
+
+ data2 = readq(&vpath_reg->rts_access_steer_data1);
+ ((u64 *)part_number)[1] = be64_to_cpu(data2);
+
+ status = VXGE_HW_OK;
+
+ } else
+ *part_number = 0;
+
+ j = 0;
+
+ for (i = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_0;
+ i <= VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_3; i++) {
+
+ __vxge_hw_read_rts_ds(vpath_reg, i);
+
+ val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY) |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0);
+
+ status = __vxge_hw_pio_mem_write64(val64,
+ &vpath_reg->rts_access_steer_ctrl,
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
+ VXGE_HW_DEF_DEVICE_POLL_MILLIS);
+
+ if (status != VXGE_HW_OK)
+ return status;
+
+ val64 = readq(&vpath_reg->rts_access_steer_ctrl);
+
+ if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
+
+ data1 = readq(&vpath_reg->rts_access_steer_data0);
+ ((u64 *)product_desc)[j++] = be64_to_cpu(data1);
+
+ data2 = readq(&vpath_reg->rts_access_steer_data1);
+ ((u64 *)product_desc)[j++] = be64_to_cpu(data2);
+
+ status = VXGE_HW_OK;
+ } else
+ *product_desc = 0;
+ }
+
+ return status;
+}
+
+/*
+ * __vxge_hw_vpath_fw_ver_get - Get the fw version
+ * Returns FW Version
+ */
+enum vxge_hw_status
+__vxge_hw_vpath_fw_ver_get(
+ struct vxge_hw_vpath_reg __iomem *vpath_reg,
+ struct vxge_hw_device_hw_info *hw_info)
+{
+ u64 val64;
+ u64 data1 = 0ULL;
+ u64 data2 = 0ULL;
+ struct vxge_hw_device_version *fw_version = &hw_info->fw_version;
+ struct vxge_hw_device_date *fw_date = &hw_info->fw_date;
+ struct vxge_hw_device_version *flash_version = &hw_info->flash_version;
+ struct vxge_hw_device_date *flash_date = &hw_info->flash_date;
+ enum vxge_hw_status status = VXGE_HW_OK;
+
+ val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY) |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0);
+
+ status = __vxge_hw_pio_mem_write64(val64,
+ &vpath_reg->rts_access_steer_ctrl,
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
+ VXGE_HW_DEF_DEVICE_POLL_MILLIS);
+
+ if (status != VXGE_HW_OK)
+ goto exit;
+
+ val64 = readq(&vpath_reg->rts_access_steer_ctrl);
+
+ if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
+
+ data1 = readq(&vpath_reg->rts_access_steer_data0);
+ data2 = readq(&vpath_reg->rts_access_steer_data1);
+
+ fw_date->day =
+ (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_DAY(
+ data1);
+ fw_date->month =
+ (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MONTH(
+ data1);
+ fw_date->year =
+ (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_YEAR(
+ data1);
+
+ snprintf(fw_date->date, VXGE_HW_FW_STRLEN, "%d/%d/%d",
+ fw_date->month, fw_date->day, fw_date->year);
+
+ fw_version->major =
+ (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MAJOR(data1);
+ fw_version->minor =
+ (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MINOR(data1);
+ fw_version->build =
+ (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_BUILD(data1);
+
+ snprintf(fw_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d",
+ fw_version->major, fw_version->minor, fw_version->build);
+
+ flash_date->day =
+ (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_DAY(data2);
+ flash_date->month =
+ (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MONTH(data2);
+ flash_date->year =
+ (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_YEAR(data2);
+
+ snprintf(flash_date->date, VXGE_HW_FW_STRLEN, "%d/%d/%d",
+ flash_date->month, flash_date->day, flash_date->year);
+
+ flash_version->major =
+ (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MAJOR(data2);
+ flash_version->minor =
+ (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MINOR(data2);
+ flash_version->build =
+ (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_BUILD(data2);
+
+ snprintf(flash_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d",
+ flash_version->major, flash_version->minor,
+ flash_version->build);
+
+ status = VXGE_HW_OK;
+
+ } else
+ status = VXGE_HW_FAIL;
+exit:
+ return status;
+}
+
+/*
+ * __vxge_hw_vpath_addr_get - Get the hw address entry for this vpath
+ * from MAC address table.
+ */
+enum vxge_hw_status
+__vxge_hw_vpath_addr_get(
+ struct vxge_hw_vpath_reg *vpath_reg,
+ u8 (macaddr)[ETH_ALEN], u8 (macaddr_mask)[ETH_ALEN])
+{
+ u32 i;
+ u64 val64;
+ u64 data1 = 0ULL;
+ u64 data2 = 0ULL;
+ u64 action = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_FIRST_ENTRY;
+ enum vxge_hw_status status = VXGE_HW_OK;
+
+ while (1) {
+ val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(action) |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0);
+
+ status = __vxge_hw_pio_mem_write64(val64,
+ &vpath_reg->rts_access_steer_ctrl,
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
+ VXGE_HW_DEF_DEVICE_POLL_MILLIS);
+
+ if (status != VXGE_HW_OK)
+ break;
+
+ val64 = readq(&vpath_reg->rts_access_steer_ctrl);
+
+ if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
+
+ data1 = readq(&vpath_reg->rts_access_steer_data0);
+ data2 = readq(&vpath_reg->rts_access_steer_data1);
+
+ data1 =
+ VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(data1);
+ data2 =
+ VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK(
+ data2);
+
+ for (i = ETH_ALEN; i > 0; i--) {
+ macaddr[i-1] = (u8)(data1 & 0xFF);
+ data1 >>= 8;
+
+ macaddr_mask[i-1] = (u8)(data2 & 0xFF);
+ data2 >>= 8;
+ }
+ if (is_valid_ether_addr(macaddr)) {
+ status = VXGE_HW_OK;
+ break;
+ }
+ action =
+ VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_NEXT_ENTRY;
+ } else
+ status = VXGE_HW_FAIL;
+ }
+
+ return status;
+}
+
+/*
+ * __vxge_hw_vpath_mgmt_read
+ * This routine reads the vpath_mgmt registers
+ */
+static enum vxge_hw_status
+__vxge_hw_vpath_mgmt_read(
+ struct __vxge_hw_virtualpath *vpath)
+{
+ u32 i, mtu = 0, max_pyld = 0;
+ u64 val64;
+ enum vxge_hw_status status = VXGE_HW_OK;
+
+ for (i = 0; i < VXGE_HW_MAC_MAX_MAC_PORT_ID; i++) {
+
+ val64 = readq(&vpath->vpmgmt_reg->
+ rxmac_cfg0_port_vpmgmt_clone[i]);
+ max_pyld =
+ (u32)
+ VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_GET_MAX_PYLD_LEN
+ (val64);
+ if (mtu < max_pyld)
+ mtu = max_pyld;
+ }
+
+ vpath->max_mtu = mtu + VXGE_HW_MAC_HEADER_MAX_SIZE;
+
+ val64 = readq(&vpath->vpmgmt_reg->xgmac_gen_status_vpmgmt_clone);
+
+ if (val64 & VXGE_HW_XGMAC_GEN_STATUS_VPMGMT_CLONE_XMACJ_NTWK_OK)
+ VXGE_HW_DEVICE_LINK_STATE_SET(vpath->hldev, VXGE_HW_LINK_UP);
+ else
+ VXGE_HW_DEVICE_LINK_STATE_SET(vpath->hldev, VXGE_HW_LINK_DOWN);
+
+ return status;
+}
+
+/*
+ * __vxge_hw_vpath_reset_check - Check if resetting the vpath completed
+ * This routine checks the vpath_rst_in_prog register to see if
+ * adapter completed the reset process for the vpath
+ */
+enum vxge_hw_status
+__vxge_hw_vpath_reset_check(struct __vxge_hw_virtualpath *vpath)
+{
+ enum vxge_hw_status status;
+
+ vxge_trace();
+
+ status = __vxge_hw_device_register_poll(
+ &vpath->hldev->common_reg->vpath_rst_in_prog,
+ VXGE_HW_VPATH_RST_IN_PROG_VPATH_RST_IN_PROG(
+ 1 << (16 - vpath->vp_id)),
+ VXGE_HW_DEF_DEVICE_POLL_MILLIS);
+
+ return status;
+}
+
+/*
+ * __vxge_hw_vpath_reset
+ * This routine resets the vpath on the device
+ */
+enum vxge_hw_status
+__vxge_hw_vpath_reset(struct __vxge_hw_device *hldev, u32 vp_id)
+{
+ u64 val64;
+ enum vxge_hw_status status = VXGE_HW_OK;
+
+ vxge_trace();
+
+ val64 = VXGE_HW_CMN_RSTHDLR_CFG0_SW_RESET_VPATH(1 << (16 - vp_id));
+
+ __vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32),
+ &hldev->common_reg->cmn_rsthdlr_cfg0);
+
+ return status;
+}
+
+/*
+ * __vxge_hw_vpath_prc_configure
+ * This routine configures the prc registers of virtual path using the config
+ * passed
+ */
+void
+__vxge_hw_vpath_prc_configure(struct __vxge_hw_device *hldev)
+{
+ u64 val64;
+ struct __vxge_hw_virtualpath *vpath;
+ struct vxge_hw_vpath_reg __iomem *vp_reg;
+
+ vxge_trace();
+
+ vpath = &hldev->virtual_path;
+ vp_reg = vpath->vp_reg;
+
+ val64 = readq(&vp_reg->prc_cfg1);
+ val64 |= VXGE_HW_PRC_CFG1_RTI_TINT_DISABLE;
+ writeq(val64, &vp_reg->prc_cfg1);
+
+ val64 = readq(&vpath->vp_reg->prc_cfg6);
+ val64 &= ~VXGE_HW_PRC_CFG6_RXD_CRXDT(0x1ff);
+ val64 &= ~VXGE_HW_PRC_CFG6_RXD_SPAT(0x1ff);
+ val64 |= VXGE_HW_PRC_CFG6_DOORBELL_MODE_EN;
+ val64 |= VXGE_HW_PRC_CFG6_RXD_CRXDT(0x3);
+ val64 |= VXGE_HW_PRC_CFG6_RXD_SPAT(0xf);
+ writeq(val64, &vpath->vp_reg->prc_cfg6);
+
+ writeq(VXGE_HW_PRC_CFG5_RXD0_ADD(
+ (u64)virt_to_bus(vpath->ringh.rxdl) >> 3),
+ &vp_reg->prc_cfg5);
+
+ val64 = readq(&vp_reg->prc_cfg4);
+ val64 |= VXGE_HW_PRC_CFG4_IN_SVC;
+ val64 &= ~VXGE_HW_PRC_CFG4_RING_MODE(0x3);
+ val64 |= VXGE_HW_PRC_CFG4_RING_MODE(
+ VXGE_HW_PRC_CFG4_RING_MODE_ONE_BUFFER);
+ val64 |= VXGE_HW_PRC_CFG4_RTH_DISABLE;
+
+ writeq(val64, &vp_reg->prc_cfg4);
+ return;
+}
+
+/*
+ * __vxge_hw_vpath_kdfc_configure
+ * This routine configures the kdfc registers of virtual path using the
+ * config passed
+ */
+enum vxge_hw_status
+__vxge_hw_vpath_kdfc_configure(struct __vxge_hw_device *hldev, u32 vp_id)
+{
+ u64 val64;
+ u64 vpath_stride;
+ enum vxge_hw_status status = VXGE_HW_OK;
+ struct __vxge_hw_virtualpath *vpath;
+ struct vxge_hw_vpath_reg __iomem *vp_reg;
+
+ vxge_trace();
+
+ vpath = &hldev->virtual_path;
+ vp_reg = vpath->vp_reg;
+ status = __vxge_hw_kdfc_swapper_set(hldev->legacy_reg, vp_reg);
+
+ if (status != VXGE_HW_OK)
+ goto exit;
+
+ val64 = readq(&vp_reg->kdfc_drbl_triplet_total);
+
+ vpath->max_kdfc_db =
+ (u32)VXGE_HW_KDFC_DRBL_TRIPLET_TOTAL_GET_KDFC_MAX_SIZE(
+ val64+1)/2;
+
+ vpath->max_nofl_db = vpath->max_kdfc_db;
+
+ val64 = VXGE_HW_KDFC_FIFO_TRPL_PARTITION_LENGTH_0(
+ (vpath->max_nofl_db*2)-1);
+
+ writeq(val64, &vp_reg->kdfc_fifo_trpl_partition);
+
+ writeq(VXGE_HW_KDFC_FIFO_TRPL_CTRL_TRIPLET_ENABLE,
+ &vp_reg->kdfc_fifo_trpl_ctrl);
+
+ val64 = readq(&vp_reg->kdfc_trpl_fifo_0_ctrl);
+
+ val64 &= ~(VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_MODE(0x3) |
+ VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_SELECT(0xFF));
+
+ val64 |= VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_MODE(
+ VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_MODE_NON_OFFLOAD_ONLY) |
+#if (__BYTE_ORDER != __BIG_ENDIAN)
+ VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_SWAP_EN |
+#endif
+ VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_SELECT(0);
+
+ writeq(val64, &vp_reg->kdfc_trpl_fifo_0_ctrl);
+ writeq((u64)0, &vp_reg->kdfc_trpl_fifo_0_wb_address);
+ wmb();
+ vpath_stride = readq(&hldev->toc_reg->toc_kdfc_vpath_stride);
+
+ vpath->nofl_db =
+ (struct __vxge_hw_non_offload_db_wrapper __iomem *)
+ (hldev->kdfc + (vp_id *
+ VXGE_HW_TOC_KDFC_VPATH_STRIDE_GET_TOC_KDFC_VPATH_STRIDE(
+ vpath_stride)));
+exit:
+ return status;
+}
+
+/*
+ * __vxge_hw_vpath_mac_configure
+ * This routine configures the mac of virtual path using the config passed
+ */
+enum vxge_hw_status
+__vxge_hw_vpath_mac_configure(struct __vxge_hw_device *hldev)
+{
+ u64 val64;
+ enum vxge_hw_status status = VXGE_HW_OK;
+ struct __vxge_hw_virtualpath *vpath;
+ struct vxge_hw_vpath_reg __iomem *vp_reg;
+
+ vxge_trace();
+
+ vpath = &hldev->virtual_path;
+ vp_reg = vpath->vp_reg;
+
+ writeq(VXGE_HW_XMAC_VSPORT_CHOICE_VSPORT_NUMBER(
+ vpath->vsport_number), &vp_reg->xmac_vsport_choice);
+
+ val64 = readq(&vp_reg->rxmac_vcfg1);
+
+ val64 &= ~(VXGE_HW_RXMAC_VCFG1_RTS_RTH_MULTI_IT_BD_MODE(0x3) |
+ VXGE_HW_RXMAC_VCFG1_RTS_RTH_MULTI_IT_EN_MODE);
+
+ writeq(val64, &vp_reg->rxmac_vcfg1);
+ return status;
+}
+
+/*
+ * __vxge_hw_vpath_tim_configure
+ * This routine configures the tim registers of virtual path using the config
+ * passed
+ */
+enum vxge_hw_status
+__vxge_hw_vpath_tim_configure(struct __vxge_hw_device *hldev, u32 vp_id)
+{
+ u64 val64;
+ enum vxge_hw_status status = VXGE_HW_OK;
+ struct __vxge_hw_virtualpath *vpath;
+ struct vxge_hw_vpath_reg __iomem *vp_reg;
+
+ vxge_trace();
+
+ vpath = &hldev->virtual_path;
+ vp_reg = vpath->vp_reg;
+
+ writeq((u64)0, &vp_reg->tim_dest_addr);
+ writeq((u64)0, &vp_reg->tim_vpath_map);
+ writeq((u64)0, &vp_reg->tim_bitmap);
+ writeq((u64)0, &vp_reg->tim_remap);
+
+ writeq(VXGE_HW_TIM_RING_ASSN_INT_NUM(
+ (vp_id * VXGE_HW_MAX_INTR_PER_VP) +
+ VXGE_HW_VPATH_INTR_RX), &vp_reg->tim_ring_assn);
+
+ val64 = readq(&vp_reg->tim_pci_cfg);
+ val64 |= VXGE_HW_TIM_PCI_CFG_ADD_PAD;
+ writeq(val64, &vp_reg->tim_pci_cfg);
+
+ /* TX configuration */
+ val64 = VXGE_HW_TIM_CFG1_INT_NUM_BTIMER_VAL(
+ (VXGE_TTI_BTIMER_VAL * 1000) / 272);
+ val64 |= (VXGE_HW_TIM_CFG1_INT_NUM_TIMER_AC |
+ VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI |
+ VXGE_HW_TIM_CFG1_INT_NUM_TXFRM_CNT_EN);
+ val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_A(TTI_TX_URANGE_A) |
+ VXGE_HW_TIM_CFG1_INT_NUM_URNG_B(TTI_TX_URANGE_B) |
+ VXGE_HW_TIM_CFG1_INT_NUM_URNG_C(TTI_TX_URANGE_C);
+ writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
+
+ val64 = VXGE_HW_TIM_CFG2_INT_NUM_UEC_A(TTI_TX_UFC_A) |
+ VXGE_HW_TIM_CFG2_INT_NUM_UEC_B(TTI_TX_UFC_B) |
+ VXGE_HW_TIM_CFG2_INT_NUM_UEC_C(TTI_TX_UFC_C) |
+ VXGE_HW_TIM_CFG2_INT_NUM_UEC_D(TTI_TX_UFC_D);
+ writeq(val64, &vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_TX]);
+
+ val64 = VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(
+ VXGE_HW_TIM_UTIL_SEL_LEGACY_TX_NET_UTIL);
+ val64 |= VXGE_HW_TIM_CFG3_INT_NUM_LTIMER_VAL(
+ (VXGE_TTI_LTIMER_VAL * 1000) / 272);
+ writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_TX]);
+
+ /* RX configuration */
+ val64 = VXGE_HW_TIM_CFG1_INT_NUM_BTIMER_VAL(
+ (VXGE_RTI_BTIMER_VAL * 1000) / 272);
+ val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_AC;
+ val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_A(RTI_RX_URANGE_A) |
+ VXGE_HW_TIM_CFG1_INT_NUM_URNG_B(RTI_RX_URANGE_B) |
+ VXGE_HW_TIM_CFG1_INT_NUM_URNG_C(RTI_RX_URANGE_C);
+ writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_RX]);
+
+ val64 = VXGE_HW_TIM_CFG2_INT_NUM_UEC_A(RTI_RX_UFC_A) |
+ VXGE_HW_TIM_CFG2_INT_NUM_UEC_B(RTI_RX_UFC_B) |
+ VXGE_HW_TIM_CFG2_INT_NUM_UEC_C(RTI_RX_UFC_C) |
+ VXGE_HW_TIM_CFG2_INT_NUM_UEC_D(RTI_RX_UFC_D);
+ writeq(val64, &vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_RX]);
+
+ val64 = VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(
+ VXGE_HW_TIM_UTIL_SEL_LEGACY_RX_NET_UTIL);
+ val64 |= VXGE_HW_TIM_CFG3_INT_NUM_LTIMER_VAL(
+ (VXGE_RTI_LTIMER_VAL * 1000) / 272);
+ writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_RX]);
+
+ val64 = 0;
+ writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_EINTA]);
+ writeq(val64, &vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_EINTA]);
+ writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_EINTA]);
+ writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_BMAP]);
+ writeq(val64, &vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_BMAP]);
+ writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_BMAP]);
+
+ return status;
+}
+
+/*
+ * __vxge_hw_vpath_initialize
+ * This routine is the final phase of init which initializes the
+ * registers of the vpath using the configuration passed.
+ */
+enum vxge_hw_status
+__vxge_hw_vpath_initialize(struct __vxge_hw_device *hldev, u32 vp_id)
+{
+ u64 val64;
+ u32 val32;
+ int i;
+ enum vxge_hw_status status = VXGE_HW_OK;
+ struct __vxge_hw_virtualpath *vpath;
+ struct vxge_hw_vpath_reg *vp_reg;
+
+ vxge_trace();
+
+ vpath = &hldev->virtual_path;
+
+ if (!(hldev->vpath_assignments & vxge_mBIT(vp_id))) {
+ status = VXGE_HW_ERR_VPATH_NOT_AVAILABLE;
+ goto exit;
+ }
+ vp_reg = vpath->vp_reg;
+ status = __vxge_hw_legacy_swapper_set(hldev->legacy_reg);
+ if (status != VXGE_HW_OK)
+ goto exit;
+
+ status = __vxge_hw_vpath_swapper_set(vpath->vp_reg);
+
+ if (status != VXGE_HW_OK)
+ goto exit;
+ val64 = readq(&vpath->vpmgmt_reg->xmac_vsport_choices_vp);
+
+ for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
+ if (val64 & vxge_mBIT(i))
+ vpath->vsport_number = i;
+ }
+
+ status = __vxge_hw_vpath_mac_configure(hldev);
+
+ if (status != VXGE_HW_OK)
+ goto exit;
+
+ status = __vxge_hw_vpath_kdfc_configure(hldev, vp_id);
+
+ if (status != VXGE_HW_OK)
+ goto exit;
+
+ status = __vxge_hw_vpath_tim_configure(hldev, vp_id);
+
+ if (status != VXGE_HW_OK)
+ goto exit;
+
+ val64 = readq(&vp_reg->rtdma_rd_optimization_ctrl);
+
+ /* Get MRRS value from device control */
+ status = __vxge_hw_vpath_pci_read(vpath, 1, 0x78, &val32);
+
+ if (status == VXGE_HW_OK) {
+ val32 = (val32 & VXGE_HW_PCI_EXP_DEVCTL_READRQ) >> 12;
+ val64 &=
+ ~(VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_FILL_THRESH(7));
+ val64 |=
+ VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_FILL_THRESH(val32);
+
+ val64 |= VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_WAIT_FOR_SPACE;
+ }
+
+ val64 &= ~(VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_ADDR_BDRY(7));
+ val64 |=
+ VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_ADDR_BDRY(
+ VXGE_HW_MAX_PAYLOAD_SIZE_512);
+
+ val64 |= VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_ADDR_BDRY_EN;
+ writeq(val64, &vp_reg->rtdma_rd_optimization_ctrl);
+
+exit:
+ return status;
+}
+
+/*
+ * __vxge_hw_vp_initialize - Initialize Virtual Path structure
+ * This routine is the initial phase of init which resets the vpath and
+ * initializes the software support structures.
+ */
+enum vxge_hw_status
+__vxge_hw_vp_initialize(struct __vxge_hw_device *hldev, u32 vp_id,
+ struct __vxge_hw_virtualpath *vpath)
+{
+ enum vxge_hw_status status = VXGE_HW_OK;
+
+ vxge_trace();
+
+ if (!(hldev->vpath_assignments & vxge_mBIT(vp_id))) {
+ status = VXGE_HW_ERR_VPATH_NOT_AVAILABLE;
+ goto exit;
+ }
+
+ vpath->vp_id = vp_id;
+ vpath->vp_open = VXGE_HW_VP_OPEN;
+ vpath->hldev = hldev;
+ vpath->vp_reg = hldev->vpath_reg[vp_id];
+ vpath->vpmgmt_reg = hldev->vpmgmt_reg[vp_id];
+
+ __vxge_hw_vpath_reset(hldev, vp_id);
+
+ status = __vxge_hw_vpath_reset_check(vpath);
+ if (status != VXGE_HW_OK) {
+ memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath));
+ goto exit;
+ }
+
+ VXGE_HW_DEVICE_TIM_INT_MASK_SET(hldev->tim_int_mask0,
+ hldev->tim_int_mask1, vp_id);
+
+ status = __vxge_hw_vpath_initialize(hldev, vp_id);
+
+ if (status != VXGE_HW_OK) {
+ __vxge_hw_vp_terminate(hldev, vpath);
+ goto exit;
+ }
+
+ status = __vxge_hw_vpath_mgmt_read(vpath);
+exit:
+ return status;
+}
+
+/*
+ * __vxge_hw_vp_terminate - Terminate Virtual Path structure
+ * This routine closes all channels it opened and freeup memory
+ */
+void
+__vxge_hw_vp_terminate(struct __vxge_hw_device *hldev,
+ struct __vxge_hw_virtualpath *vpath)
+{
+ vxge_trace();
+
+ if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN)
+ return;
+
+ VXGE_HW_DEVICE_TIM_INT_MASK_RESET(hldev->tim_int_mask0,
+ hldev->tim_int_mask1, vpath->vp_id);
+
+ memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath));
+}
+
+/*
+ * vxge_hw_vpath_mtu_set - Set MTU.
+ * Set new MTU value. Example, to use jumbo frames:
+ * vxge_hw_vpath_mtu_set(my_device, 9600);
+ */
+enum vxge_hw_status
+vxge_hw_vpath_mtu_set(struct __vxge_hw_virtualpath *vpath, u32 new_mtu)
+{
+ u64 val64;
+ enum vxge_hw_status status = VXGE_HW_OK;
+
+ vxge_trace();
+
+ new_mtu += VXGE_HW_MAC_HEADER_MAX_SIZE;
+
+ if ((new_mtu < VXGE_HW_MIN_MTU) || (new_mtu > vpath->max_mtu))
+ status = VXGE_HW_ERR_INVALID_MTU_SIZE;
+
+ val64 = readq(&vpath->vp_reg->rxmac_vcfg0);
+
+ val64 &= ~VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(0x3fff);
+ val64 |= VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(new_mtu);
+
+ writeq(val64, &vpath->vp_reg->rxmac_vcfg0);
+
+ return status;
+}
+
+/*
+ * vxge_hw_vpath_open - Open a virtual path on a given adapter
+ * This function is used to open access to virtual path of an
+ * adapter for offload, GRO operations. This function returns
+ * synchronously.
+ */
+enum vxge_hw_status
+vxge_hw_vpath_open(struct __vxge_hw_device *hldev, struct vxge_vpath *vpath)
+{
+ struct __vxge_hw_virtualpath *vpathh;
+ enum vxge_hw_status status;
+
+ vxge_trace();
+
+ vpathh = &hldev->virtual_path;
+
+ if (vpath->vp_open == VXGE_HW_VP_OPEN) {
+ status = VXGE_HW_ERR_INVALID_STATE;
+ goto vpath_open_exit1;
+ }
+
+ status = __vxge_hw_vp_initialize(hldev, hldev->first_vp_id, vpathh);
+ if (status != VXGE_HW_OK)
+ goto vpath_open_exit1;
+
+ status = __vxge_hw_fifo_create(vpathh, &vpathh->fifoh);
+ if (status != VXGE_HW_OK)
+ goto vpath_open_exit2;
+
+ status = __vxge_hw_ring_create(vpathh, &vpathh->ringh);
+ if (status != VXGE_HW_OK)
+ goto vpath_open_exit3;
+
+ __vxge_hw_vpath_prc_configure(hldev);
+
+ return VXGE_HW_OK;
+
+vpath_open_exit3:
+ __vxge_hw_fifo_delete(&vpathh->fifoh);
+vpath_open_exit2:
+ __vxge_hw_vp_terminate(hldev, vpathh);
+vpath_open_exit1:
+ return status;
+}
+
+/*
+ * vxge_hw_vpath_rx_doorbell_init - Post the count of the refreshed region
+ * of RxD list
+ * @vp: vpath handle
+ *
+ * This function decides on the Rxd replenish count depending on the
+ * descriptor memory that has been allocated to this VPath.
+ */
+void
+vxge_hw_vpath_rx_doorbell_init(struct __vxge_hw_virtualpath *vpath)
+{
+ u64 new_count, val64;
+
+ vxge_trace();
+
+ if (vpath->hldev->titan1) {
+ new_count = readq(&vpath->vp_reg->rxdmem_size);
+ new_count &= 0x1fff;
+ } else
+ new_count = VXGE_HW_RING_RXD_QWORDS_MODE_1 * 4;
+
+ val64 = (VXGE_HW_RXDMEM_SIZE_PRC_RXDMEM_SIZE(new_count));
+
+ writeq(VXGE_HW_PRC_RXD_DOORBELL_NEW_QW_CNT(val64),
+ &vpath->vp_reg->prc_rxd_doorbell);
+}
+
+/*
+ * vxge_hw_vpath_close - Close the handle got from previous vpath (vpath) open
+ * This function is used to close access to virtual path opened
+ * earlier.
+ */
+enum vxge_hw_status vxge_hw_vpath_close(struct __vxge_hw_virtualpath *vpath)
+{
+ struct __vxge_hw_device *devh = NULL;
+ u32 vp_id = vpath->vp_id;
+ enum vxge_hw_status status = VXGE_HW_OK;
+
+ vxge_trace();
+
+ devh = vpath->hldev;
+
+ if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
+ status = VXGE_HW_ERR_VPATH_NOT_OPEN;
+ goto vpath_close_exit;
+ }
+
+ devh->vpaths_deployed &= ~vxge_mBIT(vp_id);
+
+ __vxge_hw_ring_delete(&vpath->ringh);
+
+ __vxge_hw_fifo_delete(&vpath->fifoh);
+
+ __vxge_hw_vp_terminate(devh, vpath);
+
+ vpath->vp_open = VXGE_HW_VP_NOT_OPEN;
+
+vpath_close_exit:
+ return status;
+}
+
+/*
+ * vxge_hw_vpath_reset - Resets vpath
+ * This function is used to request a reset of vpath
+ */
+enum vxge_hw_status vxge_hw_vpath_reset(struct __vxge_hw_virtualpath *vpath)
+{
+ enum vxge_hw_status status;
+ u32 vp_id;
+
+ vxge_trace();
+
+ vp_id = vpath->vp_id;
+
+ if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
+ status = VXGE_HW_ERR_VPATH_NOT_OPEN;
+ goto exit;
+ }
+
+ status = __vxge_hw_vpath_reset(vpath->hldev, vp_id);
+exit:
+ return status;
+}
+
+/*
+ * vxge_hw_vpath_recover_from_reset - Poll for reset complete and re-initialize.
+ * This function poll's for the vpath reset completion and re initializes
+ * the vpath.
+ */
+enum vxge_hw_status
+vxge_hw_vpath_recover_from_reset(struct __vxge_hw_virtualpath *vpath)
+{
+ enum vxge_hw_status status;
+ struct __vxge_hw_device *hldev;
+ u32 vp_id;
+
+ vxge_trace();
+
+ vp_id = vpath->vp_id;
+ hldev = vpath->hldev;
+
+ if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
+ status = VXGE_HW_ERR_VPATH_NOT_OPEN;
+ goto exit;
+ }
+
+ status = __vxge_hw_vpath_reset_check(vpath);
+ if (status != VXGE_HW_OK)
+ goto exit;
+
+ status = __vxge_hw_vpath_initialize(hldev, vp_id);
+ if (status != VXGE_HW_OK)
+ goto exit;
+
+ __vxge_hw_vpath_prc_configure(hldev);
+
+exit:
+ return status;
+}
+
+/*
+ * vxge_hw_vpath_enable - Enable vpath.
+ * This routine clears the vpath reset thereby enabling a vpath
+ * to start forwarding frames and generating interrupts.
+ */
+void
+vxge_hw_vpath_enable(struct __vxge_hw_virtualpath *vpath)
+{
+ struct __vxge_hw_device *hldev;
+ u64 val64;
+
+ vxge_trace();
+
+ hldev = vpath->hldev;
+
+ val64 = VXGE_HW_CMN_RSTHDLR_CFG1_CLR_VPATH_RESET(
+ 1 << (16 - vpath->vp_id));
+
+ __vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32),
+ &hldev->common_reg->cmn_rsthdlr_cfg1);
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_config.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_config.h
new file mode 100644
index 00000000..bf25134a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_config.h
@@ -0,0 +1,783 @@
+/*
+ * vxge-config.h: iPXE driver for Neterion Inc's X3100 Series 10GbE
+ * PCIe I/O Virtualized Server Adapter.
+ *
+ * Copyright(c) 2002-2010 Neterion Inc.
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice.
+ *
+ */
+
+FILE_LICENCE(GPL2_ONLY);
+
+#ifndef VXGE_CONFIG_H
+#define VXGE_CONFIG_H
+
+#include <stdint.h>
+#include <ipxe/list.h>
+#include <ipxe/pci.h>
+
+#ifndef VXGE_CACHE_LINE_SIZE
+#define VXGE_CACHE_LINE_SIZE 4096
+#endif
+
+#define WAIT_FACTOR 1
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+#define VXGE_HW_MAC_MAX_WIRE_PORTS 2
+#define VXGE_HW_MAC_MAX_AGGR_PORTS 2
+#define VXGE_HW_MAC_MAX_PORTS 3
+
+#define VXGE_HW_MIN_MTU 68
+#define VXGE_HW_MAX_MTU 9600
+#define VXGE_HW_DEFAULT_MTU 1500
+
+#ifndef __iomem
+#define __iomem
+#endif
+
+#ifndef ____cacheline_aligned
+#define ____cacheline_aligned
+#endif
+
+/**
+ * debug filtering masks
+ */
+#define VXGE_NONE 0x00
+#define VXGE_INFO 0x01
+#define VXGE_INTR 0x02
+#define VXGE_XMIT 0x04
+#define VXGE_POLL 0x08
+#define VXGE_ERR 0x10
+#define VXGE_TRACE 0x20
+#define VXGE_ALL (VXGE_INFO|VXGE_INTR|VXGE_XMIT\
+ |VXGE_POLL|VXGE_ERR|VXGE_TRACE)
+
+#define NULL_VPID 0xFFFFFFFF
+
+#define VXGE_HW_EVENT_BASE 0
+#define VXGE_LL_EVENT_BASE 100
+
+#define VXGE_HW_BASE_INF 100
+#define VXGE_HW_BASE_ERR 200
+#define VXGE_HW_BASE_BADCFG 300
+#define VXGE_HW_DEF_DEVICE_POLL_MILLIS 1000
+#define VXGE_HW_MAX_PAYLOAD_SIZE_512 2
+
+enum vxge_hw_status {
+ VXGE_HW_OK = 0,
+ VXGE_HW_FAIL = 1,
+ VXGE_HW_PENDING = 2,
+ VXGE_HW_COMPLETIONS_REMAIN = 3,
+
+ VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS = VXGE_HW_BASE_INF + 1,
+ VXGE_HW_INF_OUT_OF_DESCRIPTORS = VXGE_HW_BASE_INF + 2,
+ VXGE_HW_INF_SW_LRO_BEGIN = VXGE_HW_BASE_INF + 3,
+ VXGE_HW_INF_SW_LRO_CONT = VXGE_HW_BASE_INF + 4,
+ VXGE_HW_INF_SW_LRO_UNCAPABLE = VXGE_HW_BASE_INF + 5,
+ VXGE_HW_INF_SW_LRO_FLUSH_SESSION = VXGE_HW_BASE_INF + 6,
+ VXGE_HW_INF_SW_LRO_FLUSH_BOTH = VXGE_HW_BASE_INF + 7,
+
+ VXGE_HW_ERR_INVALID_HANDLE = VXGE_HW_BASE_ERR + 1,
+ VXGE_HW_ERR_OUT_OF_MEMORY = VXGE_HW_BASE_ERR + 2,
+ VXGE_HW_ERR_VPATH_NOT_AVAILABLE = VXGE_HW_BASE_ERR + 3,
+ VXGE_HW_ERR_VPATH_NOT_OPEN = VXGE_HW_BASE_ERR + 4,
+ VXGE_HW_ERR_WRONG_IRQ = VXGE_HW_BASE_ERR + 5,
+ VXGE_HW_ERR_SWAPPER_CTRL = VXGE_HW_BASE_ERR + 6,
+ VXGE_HW_ERR_INVALID_MTU_SIZE = VXGE_HW_BASE_ERR + 7,
+ VXGE_HW_ERR_INVALID_INDEX = VXGE_HW_BASE_ERR + 8,
+ VXGE_HW_ERR_INVALID_TYPE = VXGE_HW_BASE_ERR + 9,
+ VXGE_HW_ERR_INVALID_OFFSET = VXGE_HW_BASE_ERR + 10,
+ VXGE_HW_ERR_INVALID_DEVICE = VXGE_HW_BASE_ERR + 11,
+ VXGE_HW_ERR_VERSION_CONFLICT = VXGE_HW_BASE_ERR + 12,
+ VXGE_HW_ERR_INVALID_PCI_INFO = VXGE_HW_BASE_ERR + 13,
+ VXGE_HW_ERR_INVALID_TCODE = VXGE_HW_BASE_ERR + 14,
+ VXGE_HW_ERR_INVALID_BLOCK_SIZE = VXGE_HW_BASE_ERR + 15,
+ VXGE_HW_ERR_INVALID_STATE = VXGE_HW_BASE_ERR + 16,
+ VXGE_HW_ERR_PRIVILAGED_OPEARATION = VXGE_HW_BASE_ERR + 17,
+ VXGE_HW_ERR_INVALID_PORT = VXGE_HW_BASE_ERR + 18,
+ VXGE_HW_ERR_FIFO = VXGE_HW_BASE_ERR + 19,
+ VXGE_HW_ERR_VPATH = VXGE_HW_BASE_ERR + 20,
+ VXGE_HW_ERR_CRITICAL = VXGE_HW_BASE_ERR + 21,
+ VXGE_HW_ERR_SLOT_FREEZE = VXGE_HW_BASE_ERR + 22,
+ VXGE_HW_ERR_INVALID_MIN_BANDWIDTH = VXGE_HW_BASE_ERR + 25,
+ VXGE_HW_ERR_INVALID_MAX_BANDWIDTH = VXGE_HW_BASE_ERR + 26,
+ VXGE_HW_ERR_INVALID_TOTAL_BANDWIDTH = VXGE_HW_BASE_ERR + 27,
+ VXGE_HW_ERR_INVALID_BANDWIDTH_LIMIT = VXGE_HW_BASE_ERR + 28,
+ VXGE_HW_ERR_RESET_IN_PROGRESS = VXGE_HW_BASE_ERR + 29,
+ VXGE_HW_ERR_OUT_OF_SPACE = VXGE_HW_BASE_ERR + 30,
+ VXGE_HW_ERR_INVALID_FUNC_MODE = VXGE_HW_BASE_ERR + 31,
+ VXGE_HW_ERR_INVALID_DP_MODE = VXGE_HW_BASE_ERR + 32,
+ VXGE_HW_ERR_INVALID_FAILURE_BEHAVIOUR = VXGE_HW_BASE_ERR + 33,
+ VXGE_HW_ERR_INVALID_L2_SWITCH_STATE = VXGE_HW_BASE_ERR + 34,
+ VXGE_HW_ERR_INVALID_CATCH_BASIN_MODE = VXGE_HW_BASE_ERR + 35,
+
+ VXGE_HW_BADCFG_RING_INDICATE_MAX_PKTS = VXGE_HW_BASE_BADCFG + 1,
+ VXGE_HW_BADCFG_FIFO_BLOCKS = VXGE_HW_BASE_BADCFG + 2,
+ VXGE_HW_BADCFG_VPATH_MTU = VXGE_HW_BASE_BADCFG + 3,
+ VXGE_HW_BADCFG_VPATH_RPA_STRIP_VLAN_TAG = VXGE_HW_BASE_BADCFG + 4,
+ VXGE_HW_BADCFG_VPATH_MIN_BANDWIDTH = VXGE_HW_BASE_BADCFG + 5,
+ VXGE_HW_BADCFG_VPATH_BANDWIDTH_LIMIT = VXGE_HW_BASE_BADCFG + 6,
+ VXGE_HW_BADCFG_INTR_MODE = VXGE_HW_BASE_BADCFG + 7,
+ VXGE_HW_BADCFG_RTS_MAC_EN = VXGE_HW_BASE_BADCFG + 8,
+ VXGE_HW_BADCFG_VPATH_AGGR_ACK = VXGE_HW_BASE_BADCFG + 9,
+ VXGE_HW_BADCFG_VPATH_PRIORITY = VXGE_HW_BASE_BADCFG + 10,
+
+ VXGE_HW_EOF_TRACE_BUF = -1
+};
+
+/**
+ * enum enum vxge_hw_device_link_state - Link state enumeration.
+ * @VXGE_HW_LINK_NONE: Invalid link state.
+ * @VXGE_HW_LINK_DOWN: Link is down.
+ * @VXGE_HW_LINK_UP: Link is up.
+ *
+ */
+enum vxge_hw_device_link_state {
+ VXGE_HW_LINK_NONE,
+ VXGE_HW_LINK_DOWN,
+ VXGE_HW_LINK_UP
+};
+
+/*forward declaration*/
+struct vxge_vpath;
+struct __vxge_hw_virtualpath;
+
+/**
+ * struct vxge_hw_ring_rxd_1 - One buffer mode RxD for ring
+ *
+ * One buffer mode RxD for ring structure
+ */
+struct vxge_hw_ring_rxd_1 {
+ u64 host_control;
+ u64 control_0;
+#define VXGE_HW_RING_RXD_RTH_BUCKET_GET(ctrl0) vxge_bVALn(ctrl0, 0, 7)
+
+#define VXGE_HW_RING_RXD_LIST_OWN_ADAPTER vxge_mBIT(7)
+
+#define VXGE_HW_RING_RXD_FAST_PATH_ELIGIBLE_GET(ctrl0) vxge_bVALn(ctrl0, 8, 1)
+
+#define VXGE_HW_RING_RXD_L3_CKSUM_CORRECT_GET(ctrl0) vxge_bVALn(ctrl0, 9, 1)
+
+#define VXGE_HW_RING_RXD_L4_CKSUM_CORRECT_GET(ctrl0) vxge_bVALn(ctrl0, 10, 1)
+
+#define VXGE_HW_RING_RXD_T_CODE_GET(ctrl0) vxge_bVALn(ctrl0, 12, 4)
+#define VXGE_HW_RING_RXD_T_CODE(val) vxge_vBIT(val, 12, 4)
+
+#define VXGE_HW_RING_RXD_T_CODE_UNUSED VXGE_HW_RING_T_CODE_UNUSED
+
+#define VXGE_HW_RING_RXD_SYN_GET(ctrl0) vxge_bVALn(ctrl0, 16, 1)
+
+#define VXGE_HW_RING_RXD_IS_ICMP_GET(ctrl0) vxge_bVALn(ctrl0, 17, 1)
+
+#define VXGE_HW_RING_RXD_RTH_SPDM_HIT_GET(ctrl0) vxge_bVALn(ctrl0, 18, 1)
+
+#define VXGE_HW_RING_RXD_RTH_IT_HIT_GET(ctrl0) vxge_bVALn(ctrl0, 19, 1)
+
+#define VXGE_HW_RING_RXD_RTH_HASH_TYPE_GET(ctrl0) vxge_bVALn(ctrl0, 20, 4)
+
+#define VXGE_HW_RING_RXD_IS_VLAN_GET(ctrl0) vxge_bVALn(ctrl0, 24, 1)
+
+#define VXGE_HW_RING_RXD_ETHER_ENCAP_GET(ctrl0) vxge_bVALn(ctrl0, 25, 2)
+
+#define VXGE_HW_RING_RXD_FRAME_PROTO_GET(ctrl0) vxge_bVALn(ctrl0, 27, 5)
+
+#define VXGE_HW_RING_RXD_L3_CKSUM_GET(ctrl0) vxge_bVALn(ctrl0, 32, 16)
+
+#define VXGE_HW_RING_RXD_L4_CKSUM_GET(ctrl0) vxge_bVALn(ctrl0, 48, 16)
+
+ u64 control_1;
+
+#define VXGE_HW_RING_RXD_1_BUFFER0_SIZE_GET(ctrl1) vxge_bVALn(ctrl1, 2, 14)
+#define VXGE_HW_RING_RXD_1_BUFFER0_SIZE(val) vxge_vBIT(val, 2, 14)
+#define VXGE_HW_RING_RXD_1_BUFFER0_SIZE_MASK vxge_vBIT(0x3FFF, 2, 14)
+
+#define VXGE_HW_RING_RXD_1_RTH_HASH_VAL_GET(ctrl1) vxge_bVALn(ctrl1, 16, 32)
+
+#define VXGE_HW_RING_RXD_VLAN_TAG_GET(ctrl1) vxge_bVALn(ctrl1, 48, 16)
+
+ u64 buffer0_ptr;
+};
+
+/**
+ * struct vxge_hw_fifo_txd - Transmit Descriptor
+ *
+ * Transmit descriptor (TxD).Fifo descriptor contains configured number
+ * (list) of TxDs. * For more details please refer to Titan User Guide,
+ * Section 5.4.2 "Transmit Descriptor (TxD) Format".
+ */
+struct vxge_hw_fifo_txd {
+ u64 control_0;
+#define VXGE_HW_FIFO_TXD_LIST_OWN_ADAPTER vxge_mBIT(7)
+
+#define VXGE_HW_FIFO_TXD_T_CODE_GET(ctrl0) vxge_bVALn(ctrl0, 12, 4)
+#define VXGE_HW_FIFO_TXD_T_CODE(val) vxge_vBIT(val, 12, 4)
+#define VXGE_HW_FIFO_TXD_T_CODE_UNUSED VXGE_HW_FIFO_T_CODE_UNUSED
+
+#define VXGE_HW_FIFO_TXD_GATHER_CODE(val) vxge_vBIT(val, 22, 2)
+#define VXGE_HW_FIFO_TXD_GATHER_CODE_FIRST VXGE_HW_FIFO_GATHER_CODE_FIRST
+#define VXGE_HW_FIFO_TXD_GATHER_CODE_LAST VXGE_HW_FIFO_GATHER_CODE_LAST
+
+#define VXGE_HW_FIFO_TXD_LSO_EN vxge_mBIT(30)
+#define VXGE_HW_FIFO_TXD_LSO_MSS(val) vxge_vBIT(val, 34, 14)
+#define VXGE_HW_FIFO_TXD_BUFFER_SIZE(val) vxge_vBIT(val, 48, 16)
+
+ u64 control_1;
+#define VXGE_HW_FIFO_TXD_TX_CKO_IPV4_EN vxge_mBIT(5)
+#define VXGE_HW_FIFO_TXD_TX_CKO_TCP_EN vxge_mBIT(6)
+#define VXGE_HW_FIFO_TXD_TX_CKO_UDP_EN vxge_mBIT(7)
+#define VXGE_HW_FIFO_TXD_VLAN_ENABLE vxge_mBIT(15)
+
+#define VXGE_HW_FIFO_TXD_VLAN_TAG(val) vxge_vBIT(val, 16, 16)
+#define VXGE_HW_FIFO_TXD_NO_BW_LIMIT vxge_mBIT(43)
+
+#define VXGE_HW_FIFO_TXD_INT_NUMBER(val) vxge_vBIT(val, 34, 6)
+
+#define VXGE_HW_FIFO_TXD_INT_TYPE_PER_LIST vxge_mBIT(46)
+#define VXGE_HW_FIFO_TXD_INT_TYPE_UTILZ vxge_mBIT(47)
+
+ u64 buffer_pointer;
+
+ u64 host_control;
+};
+
+/**
+ * struct vxge_hw_device_date - Date Format
+ * @day: Day
+ * @month: Month
+ * @year: Year
+ * @date: Date in string format
+ *
+ * Structure for returning date
+ */
+
+#define VXGE_HW_FW_STRLEN 32
+struct vxge_hw_device_date {
+ u32 day;
+ u32 month;
+ u32 year;
+ char date[VXGE_HW_FW_STRLEN];
+};
+
+struct vxge_hw_device_version {
+ u32 major;
+ u32 minor;
+ u32 build;
+ char version[VXGE_HW_FW_STRLEN];
+};
+
+u64 __vxge_hw_vpath_pci_func_mode_get(
+ u32 vp_id,
+ struct vxge_hw_vpath_reg __iomem *vpath_reg);
+
+/*
+ * struct __vxge_hw_non_offload_db_wrapper - Non-offload Doorbell Wrapper
+ * @control_0: Bits 0 to 7 - Doorbell type.
+ * Bits 8 to 31 - Reserved.
+ * Bits 32 to 39 - The highest TxD in this TxDL.
+ * Bits 40 to 47 - Reserved.
+ * Bits 48 to 55 - Reserved.
+ * Bits 56 to 63 - No snoop flags.
+ * @txdl_ptr: The starting location of the TxDL in host memory.
+ *
+ * Created by the host and written to the adapter via PIO to a Kernel Doorbell
+ * FIFO. All non-offload doorbell wrapper fields must be written by the host as
+ * part of a doorbell write. Consumed by the adapter but is not written by the
+ * adapter.
+ */
+struct __vxge_hw_non_offload_db_wrapper {
+ u64 control_0;
+#define VXGE_HW_NODBW_GET_TYPE(ctrl0) vxge_bVALn(ctrl0, 0, 8)
+#define VXGE_HW_NODBW_TYPE(val) vxge_vBIT(val, 0, 8)
+#define VXGE_HW_NODBW_TYPE_NODBW 0
+
+#define VXGE_HW_NODBW_GET_LAST_TXD_NUMBER(ctrl0) vxge_bVALn(ctrl0, 32, 8)
+#define VXGE_HW_NODBW_LAST_TXD_NUMBER(val) vxge_vBIT(val, 32, 8)
+
+#define VXGE_HW_NODBW_GET_NO_SNOOP(ctrl0) vxge_bVALn(ctrl0, 56, 8)
+#define VXGE_HW_NODBW_LIST_NO_SNOOP(val) vxge_vBIT(val, 56, 8)
+#define VXGE_HW_NODBW_LIST_NO_SNOOP_TXD_READ_TXD0_WRITE 0x2
+#define VXGE_HW_NODBW_LIST_NO_SNOOP_TX_FRAME_DATA_READ 0x1
+
+ u64 txdl_ptr;
+};
+
+/*
+ * struct __vxge_hw_fifo - Fifo.
+ * @vp_id: Virtual path id
+ * @tx_intr_num: Interrupt Number associated with the TX
+ * @txdl: Start pointer of the txdl list of this fifo.
+ * iPXE does not support tx fragmentation, so we need
+ * only one txd in a list
+ * @depth: total number of lists in this fifo
+ * @hw_offset: txd index from where adapter owns the txd list
+ * @sw_offset: txd index from where driver owns the txd list
+ *
+ * @stats: Statistics of this fifo
+ *
+ */
+struct __vxge_hw_fifo {
+ struct vxge_hw_vpath_reg *vp_reg;
+ struct __vxge_hw_non_offload_db_wrapper *nofl_db;
+ u32 vp_id;
+ u32 tx_intr_num;
+
+ struct vxge_hw_fifo_txd *txdl;
+#define VXGE_HW_FIFO_TXD_DEPTH 128
+ u16 depth;
+ u16 hw_offset;
+ u16 sw_offset;
+
+ struct __vxge_hw_virtualpath *vpathh;
+};
+
+/* Structure that represents the Rx descriptor block which contains
+ * 128 Rx descriptors.
+ */
+struct __vxge_hw_ring_block {
+#define VXGE_HW_MAX_RXDS_PER_BLOCK_1 127
+ struct vxge_hw_ring_rxd_1 rxd[VXGE_HW_MAX_RXDS_PER_BLOCK_1];
+
+ u64 reserved_0;
+#define END_OF_BLOCK 0xFEFFFFFFFFFFFFFFULL
+ /* 0xFEFFFFFFFFFFFFFF to mark last Rxd in this blk */
+ u64 reserved_1;
+ /* Logical ptr to next */
+ u64 reserved_2_pNext_RxD_block;
+ /* Buff0_ptr.In a 32 bit arch the upper 32 bits should be 0 */
+ u64 pNext_RxD_Blk_physical;
+};
+
+/*
+ * struct __vxge_hw_ring - Ring channel.
+ *
+ * Note: The structure is cache line aligned to better utilize
+ * CPU cache performance.
+ */
+struct __vxge_hw_ring {
+ struct vxge_hw_vpath_reg *vp_reg;
+ struct vxge_hw_common_reg *common_reg;
+ u32 vp_id;
+#define VXGE_HW_RING_RXD_QWORDS_MODE_1 4
+ u32 doorbell_cnt;
+ u32 total_db_cnt;
+#define VXGE_HW_RING_RXD_QWORD_LIMIT 16
+ u64 rxd_qword_limit;
+
+ struct __vxge_hw_ring_block *rxdl;
+#define VXGE_HW_RING_BUF_PER_BLOCK 9
+ u16 buf_per_block;
+ u16 rxd_offset;
+
+#define VXGE_HW_RING_RX_POLL_WEIGHT 8
+ u16 rx_poll_weight;
+
+ struct io_buffer *iobuf[VXGE_HW_RING_BUF_PER_BLOCK + 1];
+ struct __vxge_hw_virtualpath *vpathh;
+};
+
+/*
+ * struct __vxge_hw_virtualpath - Virtual Path
+ *
+ * Virtual path structure to encapsulate the data related to a virtual path.
+ * Virtual paths are allocated by the HW upon getting configuration from the
+ * driver and inserted into the list of virtual paths.
+ */
+struct __vxge_hw_virtualpath {
+ u32 vp_id;
+
+ u32 vp_open;
+#define VXGE_HW_VP_NOT_OPEN 0
+#define VXGE_HW_VP_OPEN 1
+
+ struct __vxge_hw_device *hldev;
+ struct vxge_hw_vpath_reg *vp_reg;
+ struct vxge_hw_vpmgmt_reg *vpmgmt_reg;
+ struct __vxge_hw_non_offload_db_wrapper *nofl_db;
+
+ u32 max_mtu;
+ u32 vsport_number;
+ u32 max_kdfc_db;
+ u32 max_nofl_db;
+
+ struct __vxge_hw_ring ringh;
+ struct __vxge_hw_fifo fifoh;
+};
+#define VXGE_HW_INFO_LEN 64
+#define VXGE_HW_PMD_INFO_LEN 16
+#define VXGE_MAX_PRINT_BUF_SIZE 128
+/**
+ * struct vxge_hw_device_hw_info - Device information
+ * @host_type: Host Type
+ * @func_id: Function Id
+ * @vpath_mask: vpath bit mask
+ * @fw_version: Firmware version
+ * @fw_date: Firmware Date
+ * @flash_version: Firmware version
+ * @flash_date: Firmware Date
+ * @mac_addrs: Mac addresses for each vpath
+ * @mac_addr_masks: Mac address masks for each vpath
+ *
+ * Returns the vpath mask that has the bits set for each vpath allocated
+ * for the driver and the first mac address for each vpath
+ */
+struct vxge_hw_device_hw_info {
+ u32 host_type;
+#define VXGE_HW_NO_MR_NO_SR_NORMAL_FUNCTION 0
+#define VXGE_HW_MR_NO_SR_VH0_BASE_FUNCTION 1
+#define VXGE_HW_NO_MR_SR_VH0_FUNCTION0 2
+#define VXGE_HW_NO_MR_SR_VH0_VIRTUAL_FUNCTION 3
+#define VXGE_HW_MR_SR_VH0_INVALID_CONFIG 4
+#define VXGE_HW_SR_VH_FUNCTION0 5
+#define VXGE_HW_SR_VH_VIRTUAL_FUNCTION 6
+#define VXGE_HW_VH_NORMAL_FUNCTION 7
+ u64 function_mode;
+#define VXGE_HW_FUNCTION_MODE_MIN 0
+#define VXGE_HW_FUNCTION_MODE_MAX 11
+
+#define VXGE_HW_FUNCTION_MODE_SINGLE_FUNCTION 0
+#define VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION 1
+#define VXGE_HW_FUNCTION_MODE_SRIOV 2
+#define VXGE_HW_FUNCTION_MODE_MRIOV 3
+#define VXGE_HW_FUNCTION_MODE_MRIOV_8 4
+#define VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION_17 5
+#define VXGE_HW_FUNCTION_MODE_SRIOV_8 6
+#define VXGE_HW_FUNCTION_MODE_SRIOV_4 7
+#define VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION_2 8
+#define VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION_4 9
+#define VXGE_HW_FUNCTION_MODE_MRIOV_4 10
+#define VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION_DIRECT_IO 11
+
+ u32 func_id;
+ u64 vpath_mask;
+ struct vxge_hw_device_version fw_version;
+ struct vxge_hw_device_date fw_date;
+ struct vxge_hw_device_version flash_version;
+ struct vxge_hw_device_date flash_date;
+ u8 serial_number[VXGE_HW_INFO_LEN];
+ u8 part_number[VXGE_HW_INFO_LEN];
+ u8 product_desc[VXGE_HW_INFO_LEN];
+ u8 (mac_addrs)[VXGE_HW_MAX_VIRTUAL_PATHS][ETH_ALEN];
+ u8 (mac_addr_masks)[VXGE_HW_MAX_VIRTUAL_PATHS][ETH_ALEN];
+};
+
+/**
+ * struct __vxge_hw_device - Hal device object
+ * @magic: Magic Number
+ * @bar0: BAR0 virtual address.
+ * @pdev: Physical device handle
+ * @config: Confguration passed by the LL driver at initialization
+ * @link_state: Link state
+ *
+ * HW device object. Represents Titan adapter
+ */
+struct __vxge_hw_device {
+ u32 magic;
+#define VXGE_HW_DEVICE_MAGIC 0x12345678
+#define VXGE_HW_DEVICE_DEAD 0xDEADDEAD
+ void __iomem *bar0;
+ struct pci_device *pdev;
+ struct net_device *ndev;
+ struct vxgedev *vdev;
+
+ enum vxge_hw_device_link_state link_state;
+
+ u32 host_type;
+ u32 func_id;
+ u8 titan1;
+ u32 access_rights;
+#define VXGE_HW_DEVICE_ACCESS_RIGHT_VPATH 0x1
+#define VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM 0x2
+#define VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM 0x4
+ struct vxge_hw_legacy_reg *legacy_reg;
+ struct vxge_hw_toc_reg *toc_reg;
+ struct vxge_hw_common_reg *common_reg;
+ struct vxge_hw_mrpcim_reg *mrpcim_reg;
+ struct vxge_hw_srpcim_reg *srpcim_reg \
+ [VXGE_HW_TITAN_SRPCIM_REG_SPACES];
+ struct vxge_hw_vpmgmt_reg *vpmgmt_reg \
+ [VXGE_HW_TITAN_VPMGMT_REG_SPACES];
+ struct vxge_hw_vpath_reg *vpath_reg \
+ [VXGE_HW_TITAN_VPATH_REG_SPACES];
+ u8 *kdfc;
+ u8 *usdc;
+ struct __vxge_hw_virtualpath virtual_path;
+ u64 vpath_assignments;
+ u64 vpaths_deployed;
+ u32 first_vp_id;
+ u64 tim_int_mask0[4];
+ u32 tim_int_mask1[4];
+
+ struct vxge_hw_device_hw_info hw_info;
+};
+
+#define VXGE_HW_DEVICE_LINK_STATE_SET(hldev, ls) (hldev->link_state = ls)
+
+#define VXGE_HW_DEVICE_TIM_INT_MASK_SET(m0, m1, i) { \
+ if (i < 16) { \
+ m0[0] |= vxge_vBIT(0x8, (i*4), 4); \
+ m0[1] |= vxge_vBIT(0x4, (i*4), 4); \
+ } \
+ else { \
+ m1[0] = 0x80000000; \
+ m1[1] = 0x40000000; \
+ } \
+}
+
+#define VXGE_HW_DEVICE_TIM_INT_MASK_RESET(m0, m1, i) { \
+ if (i < 16) { \
+ m0[0] &= ~vxge_vBIT(0x8, (i*4), 4); \
+ m0[1] &= ~vxge_vBIT(0x4, (i*4), 4); \
+ } \
+ else { \
+ m1[0] = 0; \
+ m1[1] = 0; \
+ } \
+}
+
+/**
+ * enum enum vxge_hw_txdl_state - Descriptor (TXDL) state.
+ * @VXGE_HW_TXDL_STATE_NONE: Invalid state.
+ * @VXGE_HW_TXDL_STATE_AVAIL: Descriptor is available for reservation.
+ * @VXGE_HW_TXDL_STATE_POSTED: Descriptor is posted for processing by the
+ * device.
+ * @VXGE_HW_TXDL_STATE_FREED: Descriptor is free and can be reused for
+ * filling-in and posting later.
+ *
+ * Titan/HW descriptor states.
+ *
+ */
+enum vxge_hw_txdl_state {
+ VXGE_HW_TXDL_STATE_NONE = 0,
+ VXGE_HW_TXDL_STATE_AVAIL = 1,
+ VXGE_HW_TXDL_STATE_POSTED = 2,
+ VXGE_HW_TXDL_STATE_FREED = 3
+};
+
+
+/* fifo and ring circular buffer offset tracking apis */
+static inline void __vxge_hw_desc_offset_up(u16 upper_limit,
+ u16 *offset)
+{
+ if (++(*offset) >= upper_limit)
+ *offset = 0;
+}
+
+/* rxd offset handling apis */
+static inline void vxge_hw_ring_rxd_offset_up(u16 *offset)
+{
+ __vxge_hw_desc_offset_up(VXGE_HW_MAX_RXDS_PER_BLOCK_1,
+ offset);
+}
+/* txd offset handling apis */
+static inline void vxge_hw_fifo_txd_offset_up(u16 *offset)
+{
+ __vxge_hw_desc_offset_up(VXGE_HW_FIFO_TXD_DEPTH, offset);
+}
+
+/**
+ * vxge_hw_ring_rxd_1b_set - Prepare 1-buffer-mode descriptor.
+ * @rxdh: Descriptor handle.
+ * @dma_pointer: DMA address of a single receive buffer this descriptor
+ * should carry. Note that by the time vxge_hw_ring_rxd_1b_set is called,
+ * the receive buffer should be already mapped to the device
+ * @size: Size of the receive @dma_pointer buffer.
+ *
+ * Prepare 1-buffer-mode Rx descriptor for posting
+ * (via vxge_hw_ring_rxd_post()).
+ *
+ * This inline helper-function does not return any parameters and always
+ * succeeds.
+ *
+ */
+static inline
+void vxge_hw_ring_rxd_1b_set(struct vxge_hw_ring_rxd_1 *rxdp,
+ struct io_buffer *iob, u32 size)
+{
+ rxdp->host_control = (intptr_t)(iob);
+ rxdp->buffer0_ptr = virt_to_bus(iob->data);
+ rxdp->control_1 &= ~VXGE_HW_RING_RXD_1_BUFFER0_SIZE_MASK;
+ rxdp->control_1 |= VXGE_HW_RING_RXD_1_BUFFER0_SIZE(size);
+}
+
+enum vxge_hw_status vxge_hw_device_hw_info_get(
+ struct pci_device *pdev,
+ void __iomem *bar0,
+ struct vxge_hw_device_hw_info *hw_info);
+
+enum vxge_hw_status
+__vxge_hw_vpath_fw_ver_get(
+ struct vxge_hw_vpath_reg __iomem *vpath_reg,
+ struct vxge_hw_device_hw_info *hw_info);
+
+enum vxge_hw_status
+__vxge_hw_vpath_card_info_get(
+ struct vxge_hw_vpath_reg __iomem *vpath_reg,
+ struct vxge_hw_device_hw_info *hw_info);
+
+/**
+ * vxge_hw_device_link_state_get - Get link state.
+ * @devh: HW device handle.
+ *
+ * Get link state.
+ * Returns: link state.
+ */
+static inline
+enum vxge_hw_device_link_state vxge_hw_device_link_state_get(
+ struct __vxge_hw_device *devh)
+{
+ return devh->link_state;
+}
+
+void vxge_hw_device_terminate(struct __vxge_hw_device *devh);
+
+enum vxge_hw_status vxge_hw_device_initialize(
+ struct __vxge_hw_device **devh,
+ void *bar0,
+ struct pci_device *pdev,
+ u8 titan1);
+
+enum vxge_hw_status
+vxge_hw_vpath_open(struct __vxge_hw_device *hldev, struct vxge_vpath *vpath);
+
+enum vxge_hw_status
+__vxge_hw_device_vpath_reset_in_prog_check(u64 __iomem *vpath_rst_in_prog);
+
+enum vxge_hw_status vxge_hw_vpath_close(struct __vxge_hw_virtualpath *vpath);
+
+enum vxge_hw_status vxge_hw_vpath_reset(struct __vxge_hw_virtualpath *vpath);
+
+enum vxge_hw_status
+vxge_hw_vpath_recover_from_reset(struct __vxge_hw_virtualpath *vpath);
+
+void
+vxge_hw_vpath_enable(struct __vxge_hw_virtualpath *vpath);
+
+enum vxge_hw_status
+vxge_hw_vpath_mtu_set(struct __vxge_hw_virtualpath *vpath, u32 new_mtu);
+
+void
+vxge_hw_vpath_rx_doorbell_init(struct __vxge_hw_virtualpath *vpath);
+
+void
+__vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev);
+
+enum vxge_hw_status
+__vxge_hw_legacy_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg);
+
+enum vxge_hw_status
+__vxge_hw_vpath_swapper_set(struct vxge_hw_vpath_reg __iomem *vpath_reg);
+
+enum vxge_hw_status
+__vxge_hw_kdfc_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg,
+ struct vxge_hw_vpath_reg __iomem *vpath_reg);
+
+enum vxge_hw_status
+__vxge_hw_device_register_poll(
+ void __iomem *reg,
+ u64 mask, u32 max_millis);
+
+#ifndef readq
+static inline u64 readq(void __iomem *addr)
+{
+ u64 ret = 0;
+ ret = readl(addr + 4);
+ ret <<= 32;
+ ret |= readl(addr);
+
+ return ret;
+}
+#endif
+
+#ifndef writeq
+static inline void writeq(u64 val, void __iomem *addr)
+{
+ writel((u32) (val), addr);
+ writel((u32) (val >> 32), (addr + 4));
+}
+#endif
+
+static inline void __vxge_hw_pio_mem_write32_upper(u32 val, void __iomem *addr)
+{
+ writel(val, addr + 4);
+}
+
+static inline void __vxge_hw_pio_mem_write32_lower(u32 val, void __iomem *addr)
+{
+ writel(val, addr);
+}
+
+static inline enum vxge_hw_status
+__vxge_hw_pio_mem_write64(u64 val64, void __iomem *addr,
+ u64 mask, u32 max_millis)
+{
+ enum vxge_hw_status status = VXGE_HW_OK;
+
+ __vxge_hw_pio_mem_write32_lower((u32)vxge_bVALn(val64, 32, 32), addr);
+ wmb();
+ __vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32), addr);
+ wmb();
+
+ status = __vxge_hw_device_register_poll(addr, mask, max_millis);
+ return status;
+}
+
+void
+__vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev);
+
+enum vxge_hw_status
+__vxge_hw_device_initialize(struct __vxge_hw_device *hldev);
+
+enum vxge_hw_status
+__vxge_hw_vpath_pci_read(
+ struct __vxge_hw_virtualpath *vpath,
+ u32 phy_func_0,
+ u32 offset,
+ u32 *val);
+
+enum vxge_hw_status
+__vxge_hw_vpath_addr_get(
+ struct vxge_hw_vpath_reg __iomem *vpath_reg,
+ u8 (macaddr)[ETH_ALEN],
+ u8 (macaddr_mask)[ETH_ALEN]);
+
+u32
+__vxge_hw_vpath_func_id_get(struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg);
+
+enum vxge_hw_status
+__vxge_hw_vpath_reset_check(struct __vxge_hw_virtualpath *vpath);
+
+enum vxge_hw_status
+vxge_hw_vpath_strip_fcs_check(struct __vxge_hw_device *hldev, u64 vpath_mask);
+
+/**
+ * vxge_debug
+ * @mask: mask for the debug
+ * @fmt: printf like format string
+ */
+static const u16 debug_filter = VXGE_ERR;
+#define vxge_debug(mask, fmt...) do { \
+ if (debug_filter & mask) \
+ DBG(fmt); \
+ } while (0);
+
+#define vxge_trace() vxge_debug(VXGE_TRACE, "%s:%d\n", __func__, __LINE__);
+
+enum vxge_hw_status
+vxge_hw_get_func_mode(struct __vxge_hw_device *hldev, u32 *func_mode);
+
+enum vxge_hw_status
+vxge_hw_set_fw_api(struct __vxge_hw_device *hldev,
+ u64 vp_id, u32 action,
+ u32 offset, u64 data0, u64 data1);
+void
+vxge_hw_vpath_set_zero_rx_frm_len(struct __vxge_hw_device *hldev);
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_main.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_main.c
new file mode 100644
index 00000000..b8533d31
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_main.c
@@ -0,0 +1,718 @@
+/*
+ * vxge-main.c: iPXE driver for Neterion Inc's X3100 Series 10GbE
+ * PCIe I/O Virtualized Server Adapter.
+ *
+ * Copyright(c) 2002-2010 Neterion Inc.
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice.
+ *
+ */
+
+FILE_LICENCE(GPL2_ONLY);
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ipxe/io.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include <ipxe/malloc.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/timer.h>
+#include <nic.h>
+
+#include "vxge_main.h"
+#include "vxge_reg.h"
+
+/* function modes strings */
+static char *vxge_func_mode_names[] = {
+ "Single Function - 1 func, 17 vpath",
+ "Multi Function 8 - 8 func, 2 vpath per func",
+ "SRIOV 17 - 17 VF, 1 vpath per VF",
+ "WLPEX/SharedIO 17 - 17 VH, 1 vpath/func/hierarchy",
+ "WLPEX/SharedIO 8 - 8 VH, 2 vpath/func/hierarchy",
+ "Multi Function 17 - 17 func, 1 vpath per func",
+ "SRIOV 8 - 1 PF, 7 VF, 2 vpath per VF",
+ "SRIOV 4 - 1 PF, 3 VF, 4 vpath per VF",
+ "Multi Function 2 - 2 func, 8 vpath per func",
+ "Multi Function 4 - 4 func, 4 vpath per func",
+ "WLPEX/SharedIO 4 - 17 func, 1 vpath per func (PCIe ARI)",
+ "Multi Function 8 - For ESX DirectIO - 8 func, 2 vpath per func",
+};
+
+static inline int is_vxge_card_up(struct vxgedev *vdev)
+{
+ return test_bit(__VXGE_STATE_CARD_UP, vdev->state);
+}
+
+/*
+ * vxge_xmit_compl
+ *
+ * If an interrupt was raised to indicate DMA complete of the Tx packet,
+ * this function is called. It identifies the last TxD whose buffer was
+ * freed and frees all skbs whose data have already DMA'ed into the NICs
+ * internal memory.
+ */
+enum vxge_hw_status
+vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw,
+ struct vxge_hw_fifo_txd *txdp, enum vxge_hw_fifo_tcode tcode)
+{
+ struct net_device *netdev;
+ struct io_buffer *tx_iob = NULL;
+
+ vxge_trace();
+
+ netdev = fifo_hw->vpathh->hldev->ndev;
+
+ tx_iob = (struct io_buffer *)(intptr_t)txdp->host_control;
+
+ if (tcode == VXGE_HW_FIFO_T_CODE_OK) {
+ netdev_tx_complete(netdev, tx_iob);
+ } else {
+ netdev_tx_complete_err(netdev, tx_iob, -EINVAL);
+ vxge_debug(VXGE_ERR, "%s: transmit failed, tcode %d\n",
+ netdev->name, tcode);
+ }
+
+ memset(txdp, 0, sizeof(struct vxge_hw_fifo_txd));
+
+ return VXGE_HW_OK;
+}
+
+/* reset vpaths */
+enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev)
+{
+ enum vxge_hw_status status = VXGE_HW_OK;
+ struct __vxge_hw_virtualpath *vpath;
+
+ vxge_trace();
+
+ vpath = vdev->vpath.vpathh;
+
+ if (vpath) {
+ if ((status = vxge_hw_vpath_reset(vpath)) == VXGE_HW_OK) {
+ if (is_vxge_card_up(vdev) &&
+ (status = vxge_hw_vpath_recover_from_reset(
+ vpath)) != VXGE_HW_OK) {
+ vxge_debug(VXGE_ERR, "vxge_hw_vpath_recover_"
+ "from_reset failed\n");
+ return status;
+ } else {
+ status = __vxge_hw_vpath_reset_check(vpath);
+ if (status != VXGE_HW_OK) {
+ vxge_debug(VXGE_ERR,
+ "__vxge_hw_vpath_reset_check error\n");
+ return status;
+ }
+ }
+ } else {
+ vxge_debug(VXGE_ERR, "vxge_hw_vpath_reset failed\n");
+ return status;
+ }
+ }
+ return status;
+}
+
+/* close vpaths */
+void vxge_close_vpaths(struct vxgedev *vdev)
+{
+
+ if (vdev->vpath.vpathh && vdev->vpath.is_open)
+ vxge_hw_vpath_close(vdev->vpath.vpathh);
+
+ vdev->vpath.is_open = 0;
+ vdev->vpath.vpathh = NULL;
+}
+
+/* open vpaths */
+int vxge_open_vpaths(struct vxgedev *vdev)
+{
+ enum vxge_hw_status status;
+ struct __vxge_hw_device *hldev;
+
+ hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
+
+ vdev->vpath.vpathh = &hldev->virtual_path;
+ vdev->vpath.fifo.ndev = vdev->ndev;
+ vdev->vpath.fifo.pdev = vdev->pdev;
+ vdev->vpath.fifo.fifoh = &hldev->virtual_path.fifoh;
+ vdev->vpath.ring.ndev = vdev->ndev;
+ vdev->vpath.ring.pdev = vdev->pdev;
+ vdev->vpath.ring.ringh = &hldev->virtual_path.ringh;
+
+ status = vxge_hw_vpath_open(vdev->devh, &vdev->vpath);
+ if (status == VXGE_HW_OK) {
+ vdev->vpath.is_open = 1;
+ } else {
+ vxge_debug(VXGE_ERR,
+ "%s: vpath: %d failed to open "
+ "with status: %d\n",
+ vdev->ndev->name, vdev->vpath.device_id,
+ status);
+ vxge_close_vpaths(vdev);
+ return status;
+ }
+
+ hldev->vpaths_deployed |= vxge_mBIT(vdev->vpath.vpathh->vp_id);
+
+ return VXGE_HW_OK;
+}
+
+/** Functions that implement the iPXE driver API **/
+
+/**
+ * vxge_xmit
+ * @skb : the socket buffer containing the Tx data.
+ * @dev : device pointer.
+ *
+ * This function is the Tx entry point of the driver. Neterion NIC supports
+ * certain protocol assist features on Tx side, namely CSO, S/G, LSO.
+ */
+static int
+vxge_xmit(struct net_device *dev, struct io_buffer *iobuf)
+{
+ struct vxge_fifo *fifo = NULL;
+ struct vxgedev *vdev = NULL;
+ struct __vxge_hw_fifo *fifoh;
+ struct vxge_hw_fifo_txd *txdp;
+
+ vxge_trace();
+
+ vdev = (struct vxgedev *)netdev_priv(dev);
+
+ if (!is_vxge_card_up(vdev)) {
+ vxge_debug(VXGE_ERR,
+ "%s: vdev not initialized\n", dev->name);
+ return -EIO;
+ }
+
+ if (!netdev_link_ok(dev)) {
+ vxge_debug(VXGE_ERR,
+ "%s: Link down, transmit failed\n", dev->name);
+ return -ENETDOWN;
+ }
+
+ fifo = &vdev->vpath.fifo;
+ fifoh = fifo->fifoh;
+
+ txdp = vxge_hw_fifo_free_txdl_get(fifoh);
+ if (!txdp) {
+ vxge_debug(VXGE_ERR,
+ "%s: Out of tx descriptors\n", dev->name);
+ return -ENOBUFS;
+ }
+
+ vxge_debug(VXGE_XMIT, "%s: %s:%d fifoh offset= %d\n",
+ dev->name, __func__, __LINE__, fifoh->sw_offset);
+
+ vxge_hw_fifo_txdl_buffer_set(fifoh, txdp, iobuf);
+
+ vxge_hw_fifo_txdl_post(fifoh, txdp);
+
+ return 0;
+}
+
+/*
+ * vxge_poll
+ * @ndev: net device pointer
+ *
+ * This function acks the interrupt. It polls for rx packets
+ * and send to upper layer. It also checks for tx completion
+ * and frees iobs.
+ */
+static void vxge_poll(struct net_device *ndev)
+{
+ struct __vxge_hw_device *hldev;
+ struct vxgedev *vdev;
+
+ vxge_debug(VXGE_POLL, "%s:%d \n", __func__, __LINE__);
+
+ vdev = (struct vxgedev *)netdev_priv(ndev);
+ hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
+
+ if (!is_vxge_card_up(vdev))
+ return;
+
+ /* process alarm and acknowledge the interrupts */
+ vxge_hw_device_begin_irq(hldev);
+
+ vxge_hw_vpath_poll_tx(&hldev->virtual_path.fifoh);
+
+ vxge_hw_vpath_poll_rx(&hldev->virtual_path.ringh);
+}
+
+/*
+ * vxge_irq - enable or Disable interrupts
+ *
+ * @netdev netdevice sturcture reference
+ * @action requested interrupt action
+ */
+static void vxge_irq(struct net_device *netdev __unused, int action)
+{
+ struct __vxge_hw_device *hldev;
+ struct vxgedev *vdev;
+
+ vxge_debug(VXGE_INFO,
+ "%s:%d action(%d)\n", __func__, __LINE__, action);
+
+ vdev = (struct vxgedev *)netdev_priv(netdev);
+ hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
+
+ switch (action) {
+ case DISABLE:
+ vxge_hw_device_mask_all(hldev);
+ break;
+ default:
+ vxge_hw_device_unmask_all(hldev);
+ break;
+ }
+}
+
+/**
+ * vxge_open
+ * @dev: pointer to the device structure.
+ *
+ * This function is the open entry point of the driver. It mainly calls a
+ * function to allocate Rx buffers and inserts them into the buffer
+ * descriptors and then enables the Rx part of the NIC.
+ * Return value: '0' on success and an appropriate (-)ve integer as
+ * defined in errno.h file on failure.
+ */
+int
+vxge_open(struct net_device *dev)
+{
+ enum vxge_hw_status status;
+ struct vxgedev *vdev;
+ struct __vxge_hw_device *hldev;
+ int ret = 0;
+
+ vxge_debug(VXGE_INFO, "%s: %s:%d\n",
+ VXGE_DRIVER_NAME, __func__, __LINE__);
+
+ vdev = (struct vxgedev *)netdev_priv(dev);
+ hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
+
+ /* make sure you have link off by default every time Nic is
+ * initialized */
+ netdev_link_down(dev);
+
+ /* Open VPATHs */
+ status = vxge_open_vpaths(vdev);
+ if (status != VXGE_HW_OK) {
+ vxge_debug(VXGE_ERR, "%s: fatal: Vpath open failed\n",
+ VXGE_DRIVER_NAME);
+ ret = -EPERM;
+ goto out0;
+ }
+
+ vdev->mtu = VXGE_HW_DEFAULT_MTU;
+ /* set initial mtu before enabling the device */
+ status = vxge_hw_vpath_mtu_set(vdev->vpath.vpathh, vdev->mtu);
+ if (status != VXGE_HW_OK) {
+ vxge_debug(VXGE_ERR,
+ "%s: fatal: can not set new MTU\n", dev->name);
+ ret = -EPERM;
+ goto out2;
+ }
+ vxge_debug(VXGE_INFO,
+ "%s: MTU is %d\n", vdev->ndev->name, vdev->mtu);
+
+ set_bit(__VXGE_STATE_CARD_UP, vdev->state);
+
+ wmb();
+
+ if (vxge_hw_device_link_state_get(vdev->devh) == VXGE_HW_LINK_UP) {
+ netdev_link_up(vdev->ndev);
+ vxge_debug(VXGE_INFO, "%s: Link Up\n", vdev->ndev->name);
+ }
+
+ vxge_hw_device_intr_enable(hldev);
+
+ vxge_hw_vpath_enable(vdev->vpath.vpathh);
+ wmb();
+ vxge_hw_vpath_rx_doorbell_init(vdev->vpath.vpathh);
+
+ goto out0;
+
+out2:
+ vxge_close_vpaths(vdev);
+out0:
+ vxge_debug(VXGE_INFO, "%s: %s:%d Exiting...\n",
+ dev->name, __func__, __LINE__);
+ return ret;
+}
+
+/**
+ * vxge_close
+ * @dev: device pointer.
+ *
+ * This is the stop entry point of the driver. It needs to undo exactly
+ * whatever was done by the open entry point, thus it's usually referred to
+ * as the close function.Among other things this function mainly stops the
+ * Rx side of the NIC and frees all the Rx buffers in the Rx rings.
+ * Return value: '0' on success and an appropriate (-)ve integer as
+ * defined in errno.h file on failure.
+ */
+static void vxge_close(struct net_device *dev)
+{
+ struct vxgedev *vdev;
+ struct __vxge_hw_device *hldev;
+
+ vxge_debug(VXGE_INFO, "%s: %s:%d\n",
+ dev->name, __func__, __LINE__);
+
+ vdev = (struct vxgedev *)netdev_priv(dev);
+ hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
+
+ if (!is_vxge_card_up(vdev))
+ return;
+
+ clear_bit(__VXGE_STATE_CARD_UP, vdev->state);
+
+ vxge_hw_vpath_set_zero_rx_frm_len(hldev);
+
+ netdev_link_down(vdev->ndev);
+ vxge_debug(VXGE_INFO, "%s: Link Down\n", vdev->ndev->name);
+
+ /* Note that at this point xmit() is stopped by upper layer */
+ vxge_hw_device_intr_disable(hldev);
+
+ /* Multi function shares INTA, hence we should
+ * leave it in enabled state
+ */
+ if (is_mf(hldev->hw_info.function_mode))
+ vxge_hw_device_unmask_all(hldev);
+
+ vxge_reset_all_vpaths(vdev);
+
+ vxge_close_vpaths(vdev);
+
+ vxge_debug(VXGE_INFO,
+ "%s: %s:%d Exiting...\n", dev->name, __func__, __LINE__);
+}
+
+static struct net_device_operations vxge_operations;
+
+int vxge_device_register(struct __vxge_hw_device *hldev,
+ struct vxgedev **vdev_out)
+{
+ struct net_device *ndev;
+ struct vxgedev *vdev;
+ int ret = 0;
+
+ *vdev_out = NULL;
+
+ ndev = alloc_etherdev(sizeof(struct vxgedev));
+ if (ndev == NULL) {
+ vxge_debug(VXGE_ERR, "%s : device allocation failed\n",
+ __func__);
+ ret = -ENODEV;
+ goto _out0;
+ }
+
+ vxge_debug(VXGE_INFO, "%s:%d netdev registering\n",
+ __func__, __LINE__);
+ vdev = netdev_priv(ndev);
+ memset(vdev, 0, sizeof(struct vxgedev));
+
+ vdev->ndev = ndev;
+ vdev->devh = hldev;
+ vdev->pdev = hldev->pdev;
+
+ ndev->dev = &vdev->pdev->dev;
+ /* Associate vxge-specific network operations operations with
+ * generic network device layer */
+ netdev_init(ndev, &vxge_operations);
+
+ memcpy(ndev->hw_addr,
+ (u8 *)hldev->hw_info.mac_addrs[hldev->first_vp_id], ETH_ALEN);
+
+ if (register_netdev(ndev)) {
+ vxge_debug(VXGE_ERR, "%s : device registration failed!\n",
+ __func__);
+ ret = -ENODEV;
+ goto _out2;
+ }
+
+ /* Leave link state as off at this point, when the link change
+ * interrupt comes the state will be automatically changed to
+ * the right state.
+ */
+
+ vxge_debug(VXGE_INFO, "%s: Ethernet device registered\n",
+ VXGE_DRIVER_NAME);
+
+ *vdev_out = vdev;
+
+ return ret;
+_out2:
+ netdev_put(ndev);
+_out0:
+ return ret;
+}
+
+/*
+ * vxge_device_unregister
+ *
+ * This function will unregister and free network device
+ */
+void
+vxge_device_unregister(struct __vxge_hw_device *hldev)
+{
+ struct net_device *ndev;
+
+ ndev = hldev->ndev;
+
+ unregister_netdev(ndev);
+ netdev_nullify(ndev);
+ netdev_put(ndev);
+
+ vxge_debug(VXGE_INFO, "%s: ethernet device unregistered\n",
+ VXGE_DRIVER_NAME);
+}
+
+/**
+ * vxge_probe
+ * @pdev : structure containing the PCI related information of the device.
+ * @id: List of PCI devices supported by the driver listed in vxge_id_table.
+ * Description:
+ * This function is called when a new PCI device gets detected and initializes
+ * it.
+ * Return value:
+ * returns 0 on success and negative on failure.
+ *
+ */
+static int
+vxge_probe(struct pci_device *pdev)
+{
+ struct __vxge_hw_device *hldev;
+ enum vxge_hw_status status;
+ int ret = 0;
+ u64 vpath_mask = 0;
+ struct vxgedev *vdev;
+ int i;
+ u8 revision, titan1;
+ u32 function_mode;
+ unsigned long mmio_start, mmio_len;
+ void *bar0;
+ struct vxge_hw_device_hw_info hw_info;
+ struct vxge_hw_device_version *fw_version;
+
+ vxge_debug(VXGE_INFO, "vxge_probe for device " PCI_FMT "\n",
+ PCI_ARGS(pdev));
+
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &revision);
+ titan1 = is_titan1(pdev->device, revision);
+
+ mmio_start = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
+ mmio_len = pci_bar_size(pdev, PCI_BASE_ADDRESS_0);
+ vxge_debug(VXGE_INFO, "mmio_start: %#08lx, mmio_len: %#08lx\n",
+ mmio_start, mmio_len);
+
+ /* sets the bus master */
+ adjust_pci_device(pdev);
+
+ bar0 = ioremap(mmio_start, mmio_len);
+ if (!bar0) {
+ vxge_debug(VXGE_ERR,
+ "%s : cannot remap io memory bar0\n", __func__);
+ ret = -ENODEV;
+ goto _exit0;
+ }
+
+ status = vxge_hw_device_hw_info_get(pdev, bar0, &hw_info);
+ if (status != VXGE_HW_OK) {
+ vxge_debug(VXGE_ERR,
+ "%s: Reading of hardware info failed.\n",
+ VXGE_DRIVER_NAME);
+ ret = -EINVAL;
+ goto _exit1;
+ }
+
+ if (hw_info.func_id != 0) {
+ /* Non zero function, So do not load the driver */
+ iounmap(bar0);
+ pci_set_drvdata(pdev, NULL);
+ return -EINVAL;
+ }
+
+
+ vpath_mask = hw_info.vpath_mask;
+ if (vpath_mask == 0) {
+ vxge_debug(VXGE_ERR,
+ "%s: No vpaths available in device\n",
+ VXGE_DRIVER_NAME);
+ ret = -EINVAL;
+ goto _exit1;
+ }
+ vxge_debug(VXGE_INFO,
+ "%s:%d Vpath mask = %llx\n", __func__, __LINE__,
+ (unsigned long long)vpath_mask);
+
+ fw_version = &hw_info.fw_version;
+ /* fail the driver loading if firmware is incompatible */
+ if ((fw_version->major != VXGE_CERT_FW_VER_MAJOR) ||
+ (fw_version->minor < VXGE_CERT_FW_VER_MINOR)) {
+ printf("%s: Adapter's current firmware version: %d.%d.%d\n",
+ VXGE_DRIVER_NAME, fw_version->major,
+ fw_version->minor, fw_version->build);
+
+ printf("%s: Upgrade firmware to version %d.%d.%d\n",
+ VXGE_DRIVER_NAME, VXGE_CERT_FW_VER_MAJOR,
+ VXGE_CERT_FW_VER_MINOR, VXGE_CERT_FW_VER_BUILD);
+
+ ret = -EACCES;
+ goto _exit1;
+ }
+
+ status = vxge_hw_device_initialize(&hldev, bar0, pdev, titan1);
+ if (status != VXGE_HW_OK) {
+ vxge_debug(VXGE_ERR,
+ "Failed to initialize device (%d)\n", status);
+ ret = -EINVAL;
+ goto _exit1;
+ }
+ memcpy(&hldev->hw_info, &hw_info,
+ sizeof(struct vxge_hw_device_hw_info));
+
+ /* find the vpath id of the first available one */
+ for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++)
+ if (vpath_mask & vxge_mBIT(i)) {
+ hldev->first_vp_id = i;
+ break;
+ }
+ /* if FCS stripping is not disabled in MAC fail driver load */
+ if (vxge_hw_vpath_strip_fcs_check(hldev, vpath_mask) != VXGE_HW_OK) {
+ vxge_debug(VXGE_ERR,
+ "%s: FCS stripping is not disabled in MAC"
+ " failing driver load\n", VXGE_DRIVER_NAME);
+ ret = -EINVAL;
+ goto _exit2;
+ }
+
+ /* Read function mode */
+ status = vxge_hw_get_func_mode(hldev, &function_mode);
+ if (status != VXGE_HW_OK)
+ goto _exit2;
+
+ hldev->hw_info.function_mode = function_mode;
+
+ /* set private device info */
+ pci_set_drvdata(pdev, hldev);
+
+ if (vxge_device_register(hldev, &vdev)) {
+ ret = -EINVAL;
+ goto _exit2;
+ }
+
+ /* set private HW device info */
+ hldev->ndev = vdev->ndev;
+ hldev->vdev = vdev;
+ hldev->pdev = pdev;
+ vdev->mtu = VXGE_HW_DEFAULT_MTU;
+ vdev->bar0 = bar0;
+ vdev->titan1 = titan1;
+ /* Virtual Path count */
+ vdev->vpath.device_id = hldev->first_vp_id;
+ vdev->vpath.vdev = vdev;
+ memcpy((u8 *)vdev->vpath.macaddr,
+ (u8 *)hldev->hw_info.mac_addrs[hldev->first_vp_id],
+ ETH_ALEN);
+
+ hldev->hw_info.serial_number[VXGE_HW_INFO_LEN - 1] = '\0';
+ hldev->hw_info.product_desc[VXGE_HW_INFO_LEN - 1] = '\0';
+ hldev->hw_info.part_number[VXGE_HW_INFO_LEN - 1] = '\0';
+
+ vxge_debug(VXGE_INFO, "%s: Neterion %s Server Adapter\n",
+ VXGE_DRIVER_NAME, hldev->hw_info.product_desc);
+ vxge_debug(VXGE_INFO, "%s: SERIAL NUMBER: %s\n",
+ VXGE_DRIVER_NAME, hldev->hw_info.serial_number);
+ vxge_debug(VXGE_INFO, "%s: PART NUMBER: %s\n",
+ VXGE_DRIVER_NAME, hldev->hw_info.part_number);
+ vxge_debug(VXGE_INFO, "%s: MAC ADDR: %s\n",
+ VXGE_DRIVER_NAME, eth_ntoa(vdev->vpath.macaddr));
+ vxge_debug(VXGE_INFO,
+ "%s: Firmware version : %s Date : %s\n", VXGE_DRIVER_NAME,
+ hldev->hw_info.fw_version.version,
+ hldev->hw_info.fw_date.date);
+ vxge_debug(VXGE_INFO, "%s: %s Enabled\n",
+ VXGE_DRIVER_NAME, vxge_func_mode_names[function_mode]);
+
+ vxge_debug(VXGE_INFO, "%s: %s:%d Probe Exiting...\n",
+ VXGE_DRIVER_NAME, __func__, __LINE__);
+
+ return 0;
+
+_exit2:
+ vxge_hw_device_terminate(hldev);
+_exit1:
+ iounmap(bar0);
+_exit0:
+ pci_set_drvdata(pdev, NULL);
+ printf("%s: WARNING!! Driver loading failed!!\n",
+ VXGE_DRIVER_NAME);
+
+ return ret;
+}
+
+/**
+ * vxge_remove - Free the PCI device
+ * @pdev: structure containing the PCI related information of the device.
+ * Description: This function is called by the Pci subsystem to release a
+ * PCI device and free up all resource held up by the device.
+ */
+static void
+vxge_remove(struct pci_device *pdev)
+{
+ struct __vxge_hw_device *hldev;
+ struct vxgedev *vdev = NULL;
+ struct net_device *ndev;
+
+ vxge_debug(VXGE_INFO,
+ "%s:%d\n", __func__, __LINE__);
+ hldev = (struct __vxge_hw_device *) pci_get_drvdata(pdev);
+ if (hldev == NULL)
+ return;
+
+ ndev = hldev->ndev;
+ vdev = netdev_priv(ndev);
+
+ iounmap(vdev->bar0);
+
+ vxge_device_unregister(hldev);
+
+ vxge_debug(VXGE_INFO,
+ "%s:%d Device unregistered\n", __func__, __LINE__);
+
+ vxge_hw_device_terminate(hldev);
+ pci_set_drvdata(pdev, NULL);
+}
+
+/* vxge net device operations */
+static struct net_device_operations vxge_operations = {
+ .open = vxge_open,
+ .close = vxge_close,
+ .transmit = vxge_xmit,
+ .poll = vxge_poll,
+ .irq = vxge_irq,
+};
+
+static struct pci_device_id vxge_main_nics[] = {
+ /* If you change this, also adjust vxge_nics[] in vxge.c */
+ PCI_ID(0x17d5, 0x5833, "vxge-x3100", "Neterion X3100 Series", 0),
+};
+
+struct pci_driver vxge_driver __pci_driver = {
+ .ids = vxge_main_nics,
+ .id_count = (sizeof(vxge_main_nics) / sizeof(vxge_main_nics[0])),
+ .probe = vxge_probe,
+ .remove = vxge_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_main.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_main.h
new file mode 100644
index 00000000..550dcefd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_main.h
@@ -0,0 +1,230 @@
+/*
+ * vxge-main.h: iPXE driver for Neterion Inc's X3100 Series 10GbE
+ * PCIe I/O Virtualized Server Adapter.
+ *
+ * Copyright(c) 2002-2010 Neterion Inc.
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice.
+ *
+ */
+
+FILE_LICENCE(GPL2_ONLY);
+
+#ifndef VXGE_MAIN_H
+#define VXGE_MAIN_H
+
+#include <unistd.h>
+#include "vxge_traffic.h"
+#include "vxge_config.h"
+
+#define VXGE_DRIVER_NAME "vxge"
+#define VXGE_DRIVER_VENDOR "Neterion, Inc"
+
+#ifndef PCI_VENDOR_ID_S2IO
+#define PCI_VENDOR_ID_S2IO 0x17D5
+#endif
+
+#ifndef PCI_DEVICE_ID_TITAN_WIN
+#define PCI_DEVICE_ID_TITAN_WIN 0x5733
+#endif
+
+#ifndef PCI_DEVICE_ID_TITAN_UNI
+#define PCI_DEVICE_ID_TITAN_UNI 0x5833
+#endif
+
+#define VXGE_HW_TITAN1_PCI_REVISION 1
+#define VXGE_HW_TITAN1A_PCI_REVISION 2
+
+#define VXGE_HP_ISS_SUBSYS_VENDORID 0x103C
+#define VXGE_HP_ISS_SUBSYS_DEVICEID_1 0x323B
+#define VXGE_HP_ISS_SUBSYS_DEVICEID_2 0x323C
+
+#define VXGE_USE_DEFAULT 0xffffffff
+#define VXGE_HW_VPATH_MSIX_ACTIVE 4
+#define VXGE_ALARM_MSIX_ID 2
+#define VXGE_HW_RXSYNC_FREQ_CNT 4
+#define VXGE_LL_RX_COPY_THRESHOLD 256
+#define VXGE_DEF_FIFO_LENGTH 84
+
+#define NO_STEERING 0
+#define PORT_STEERING 0x1
+#define RTH_TCP_UDP_STEERING 0x2
+#define RTH_IPV4_STEERING 0x3
+#define RTH_IPV6_EX_STEERING 0x4
+#define RTH_BUCKET_SIZE 8
+
+#define TX_PRIORITY_STEERING 1
+#define TX_VLAN_STEERING 2
+#define TX_PORT_STEERING 3
+#define TX_MULTIQ_STEERING 4
+
+#define VXGE_HW_PROM_MODE_ENABLE 1
+#define VXGE_HW_PROM_MODE_DISABLE 0
+
+#define VXGE_HW_FW_UPGRADE_DISABLE 0
+#define VXGE_HW_FW_UPGRADE_ALL 1
+#define VXGE_HW_FW_UPGRADE_FORCE 2
+#define VXGE_HW_FUNC_MODE_DISABLE 0
+
+#define VXGE_TTI_BTIMER_VAL 250000
+#define VXGE_T1A_TTI_LTIMER_VAL 80
+#define VXGE_T1A_TTI_RTIMER_VAL 400
+
+#define VXGE_TTI_LTIMER_VAL 1000
+#define VXGE_TTI_RTIMER_VAL 0
+#define VXGE_RTI_BTIMER_VAL 250
+#define VXGE_RTI_LTIMER_VAL 100
+#define VXGE_RTI_RTIMER_VAL 0
+#define VXGE_FIFO_INDICATE_MAX_PKTS VXGE_DEF_FIFO_LENGTH
+#define VXGE_ISR_POLLING_CNT 8
+#define VXGE_MAX_CONFIG_DEV 0xFF
+#define VXGE_EXEC_MODE_DISABLE 0
+#define VXGE_EXEC_MODE_ENABLE 1
+#define VXGE_MAX_CONFIG_PORT 1
+#define VXGE_ALL_VID_DISABLE 0
+#define VXGE_ALL_VID_ENABLE 1
+#define VXGE_PAUSE_CTRL_DISABLE 0
+#define VXGE_PAUSE_CTRL_ENABLE 1
+
+#define TTI_TX_URANGE_A 5
+#define TTI_TX_URANGE_B 15
+#define TTI_TX_URANGE_C 40
+#define TTI_TX_UFC_A 5
+#define TTI_TX_UFC_B 40
+#define TTI_TX_UFC_C 60
+#define TTI_TX_UFC_D 100
+#define TTI_T1A_TX_UFC_A 30
+#define TTI_T1A_TX_UFC_B 80
+
+/* Slope - (max_mtu - min_mtu)/(max_mtu_ufc - min_mtu_ufc) */
+/* Slope - 93 */
+/* 60 - 9k Mtu, 140 - 1.5k mtu */
+#define TTI_T1A_TX_UFC_C(mtu) (60 + ((VXGE_HW_MAX_MTU - mtu)/93))
+
+/* Slope - 37 */
+/* 100 - 9k Mtu, 300 - 1.5k mtu */
+#define TTI_T1A_TX_UFC_D(mtu) (100 + ((VXGE_HW_MAX_MTU - mtu)/37))
+
+#define RTI_RX_URANGE_A 5
+#define RTI_RX_URANGE_B 15
+#define RTI_RX_URANGE_C 40
+#define RTI_T1A_RX_URANGE_A 1
+#define RTI_T1A_RX_URANGE_B 20
+#define RTI_T1A_RX_URANGE_C 50
+#define RTI_RX_UFC_A 1
+#define RTI_RX_UFC_B 5
+#define RTI_RX_UFC_C 10
+#define RTI_RX_UFC_D 15
+#define RTI_T1A_RX_UFC_B 20
+#define RTI_T1A_RX_UFC_C 50
+#define RTI_T1A_RX_UFC_D 60
+
+/*
+ * The interrupt rate is maintained at 3k per second with the moderation
+ * parameters for most traffics but not all. This is the maximum interrupt
+ * count per allowed per function with INTA or per vector in the case of in a
+ * MSI-X 10 millisecond time period. Enabled only for Titan 1A.
+ */
+#define VXGE_T1A_MAX_INTERRUPT_COUNT 100
+
+#define VXGE_ENABLE_NAPI 1
+#define VXGE_DISABLE_NAPI 0
+#define VXGE_LRO_MAX_BYTES 0x4000
+#define VXGE_T1A_LRO_MAX_BYTES 0xC000
+
+#define VXGE_HW_MIN_VPATH_TX_BW_SUPPORT 0
+#define VXGE_HW_MAX_VPATH_TX_BW_SUPPORT 7
+
+/* Milli secs timer period */
+#define VXGE_TIMER_DELAY 10000
+
+#define VXGE_TIMER_COUNT (2 * 60)
+
+#define VXGE_LL_MAX_FRAME_SIZE(dev) ((dev)->mtu + VXGE_HW_MAC_HEADER_MAX_SIZE)
+
+#define VXGE_REG_DUMP_BUFSIZE 65000
+
+#define is_mf(function_mode) \
+ ((function_mode == VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION) || \
+ (function_mode == VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION_17) || \
+ (function_mode == VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION_2) || \
+ (function_mode == VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION_4))
+
+#define is_titan1(dev_id, rev) (((dev_id == PCI_DEVICE_ID_TITAN_UNI) || \
+ (dev_id == PCI_DEVICE_ID_TITAN_WIN)) && \
+ (rev == VXGE_HW_TITAN1_PCI_REVISION))
+
+/* These flags represent the devices temporary state */
+#define __VXGE_STATE_RESET_CARD 0x01
+#define __VXGE_STATE_CARD_UP 0x02
+
+#define test_bit(bit, loc) ((bit) & (loc))
+#define set_bit(bit, loc) do { (loc) |= (bit); } while (0);
+#define clear_bit(bit, loc) do { (loc) &= ~(bit); } while (0);
+
+#define msleep(n) mdelay(n)
+
+struct vxge_fifo {
+ struct net_device *ndev;
+ struct pci_device *pdev;
+ struct __vxge_hw_fifo *fifoh;
+};
+
+struct vxge_ring {
+ struct net_device *ndev;
+ struct pci_device *pdev;
+ struct __vxge_hw_ring *ringh;
+};
+
+struct vxge_vpath {
+
+ struct vxge_fifo fifo;
+ struct vxge_ring ring;
+
+ /* Actual vpath id for this vpath in the device - 0 to 16 */
+ int device_id;
+ int is_open;
+ int vp_open;
+ u8 (macaddr)[ETH_ALEN];
+ u8 (macmask)[ETH_ALEN];
+ struct vxgedev *vdev;
+ struct __vxge_hw_virtualpath *vpathh;
+};
+
+struct vxgedev {
+ struct net_device *ndev;
+ struct pci_device *pdev;
+ struct __vxge_hw_device *devh;
+ u8 titan1;
+
+ unsigned long state;
+
+ struct vxge_vpath vpath;
+
+ void __iomem *bar0;
+ int mtu;
+
+ char fw_version[VXGE_HW_FW_STRLEN];
+};
+
+void vxge_vpath_intr_enable(struct vxgedev *vdev, int vp_id);
+
+void vxge_vpath_intr_disable(struct vxgedev *vdev, int vp_id);
+
+int vxge_reset(struct vxgedev *vdev);
+
+enum vxge_hw_status
+vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw,
+ struct vxge_hw_fifo_txd *txdp, enum vxge_hw_fifo_tcode tcode);
+
+void vxge_close_vpaths(struct vxgedev *vdev);
+
+int vxge_open_vpaths(struct vxgedev *vdev);
+
+enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev);
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_reg.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_reg.h
new file mode 100644
index 00000000..a76f24e7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_reg.h
@@ -0,0 +1,4700 @@
+/*
+ * vxge-reg.h: iPXE driver for Neterion Inc's X3100 Series 10GbE
+ * PCIe I/O Virtualized Server Adapter.
+ *
+ * Copyright(c) 2002-2010 Neterion Inc.
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice.
+ *
+ */
+
+FILE_LICENCE(GPL2_ONLY);
+
+#ifndef VXGE_REG_H
+#define VXGE_REG_H
+
+#include <stdint.h>
+/*
+ * vxge_mBIT(loc) - set bit at offset
+ */
+#define vxge_mBIT(loc) (0x8000000000000000ULL >> (loc))
+
+/*
+ * vxge_vBIT(val, loc, sz) - set bits at offset
+ */
+#define vxge_vBIT(val, loc, sz) (((u64)(val)) << (64-(loc)-(sz)))
+#define vxge_vBIT32(val, loc, sz) (((u32)(val)) << (32-(loc)-(sz)))
+
+/*
+ * vxge_bVALn(bits, loc, n) - Get the value of n bits at location
+ */
+#define vxge_bVALn(bits, loc, n) \
+ ((((u64)bits) >> (64-(loc+n))) & ((0x1ULL << n) - 1))
+
+#define VXGE_HW_TITAN_ASIC_ID_GET_INITIAL_DEVICE_ID(bits) \
+ vxge_bVALn(bits, 0, 16)
+#define VXGE_HW_TITAN_ASIC_ID_GET_INITIAL_MAJOR_REVISION(bits) \
+ vxge_bVALn(bits, 48, 8)
+#define VXGE_HW_TITAN_ASIC_ID_GET_INITIAL_MINOR_REVISION(bits) \
+ vxge_bVALn(bits, 56, 8)
+
+#define VXGE_HW_VPATH_TO_FUNC_MAP_CFG1_GET_VPATH_TO_FUNC_MAP_CFG1(bits) \
+ vxge_bVALn(bits, 3, 5)
+#define VXGE_HW_HOST_TYPE_ASSIGNMENTS_GET_HOST_TYPE_ASSIGNMENTS(bits) \
+ vxge_bVALn(bits, 5, 3)
+#define VXGE_HW_PF_SW_RESET_COMMAND 0xA5
+
+#define VXGE_HW_TITAN_PCICFGMGMT_REG_SPACES 17
+#define VXGE_HW_TITAN_SRPCIM_REG_SPACES 17
+#define VXGE_HW_TITAN_VPMGMT_REG_SPACES 17
+#define VXGE_HW_TITAN_VPATH_REG_SPACES 17
+
+
+#define VXGE_HW_PRIV_FN_ACTION 8
+#define VXGE_HW_PRIV_VP_ACTION 5
+#define VXGE_HW_PRIV_FN_MEMO 13
+#define VXGE_HW_EN_DIS_UDP_RTH 10
+#define VXGE_HW_BW_CONTROL 12
+#define VXGE_HW_RTS_ACCESS_FW_MEMO_ACTION_PRIV_NWIF 17
+
+#define VXGE_HW_FW_API_FUNC_MODE 11
+#define VXGE_HW_FW_API_GET_FUNC_MODE 29
+#define VXGE_HW_FW_API_FUNC_MODE_COMMIT 21
+#define VXGE_HW_GET_FUNC_MODE_VAL(val) (val & 0xFF)
+
+#define VXGE_HW_BYTES_PER_U64 8
+#define VXGE_HW_FW_UPGRADE_MEMO 13
+#define VXGE_HW_FW_UPGRADE_ACTION 16
+#define VXGE_HW_FW_UPGRADE_OFFSET_START 2 /* Start upgrade */
+#define VXGE_HW_FW_UPGRADE_OFFSET_SEND 3 /* Send upgrade data */
+#define VXGE_HW_FW_UPGRADE_OFFSET_COMMIT 4 /* Commit upgrade */
+#define VXGE_HW_FW_UPGRADE_OFFSET_READ 5 /* Read upgrade version */
+
+#define VXGE_HW_FW_UPGRADE_BLK_SIZE 16 /* Bytes to write */
+#define VXGE_HW_UPGRADE_GET_RET_ERR_CODE(val) (val & 0xff)
+#define VXGE_HW_UPGRADE_GET_SEC_ERR_CODE(val) ((val >> 8) & 0xff)
+
+#define VXGE_HW_ASIC_MODE_RESERVED 0
+#define VXGE_HW_ASIC_MODE_NO_IOV 1
+#define VXGE_HW_ASIC_MODE_SR_IOV 2
+#define VXGE_HW_ASIC_MODE_MR_IOV 3
+
+#define VXGE_HW_TXMAC_GEN_CFG1_TMAC_PERMA_STOP_EN vxge_mBIT(3)
+#define VXGE_HW_TXMAC_GEN_CFG1_BLOCK_BCAST_TO_WIRE vxge_mBIT(19)
+#define VXGE_HW_TXMAC_GEN_CFG1_BLOCK_BCAST_TO_SWITCH vxge_mBIT(23)
+#define VXGE_HW_TXMAC_GEN_CFG1_HOST_APPEND_FCS vxge_mBIT(31)
+
+#define VXGE_HW_VPATH_IS_FIRST_GET_VPATH_IS_FIRST(bits) vxge_bVALn(bits, 3, 1)
+
+#define VXGE_HW_TIM_VPATH_ASSIGNMENT_GET_BMAP_ROOT(bits) \
+ vxge_bVALn(bits, 0, 32)
+
+#define VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_GET_MAX_PYLD_LEN(bits) \
+ vxge_bVALn(bits, 50, 14)
+
+#define VXGE_HW_XMAC_VSPORT_CHOICES_VP_GET_VSPORT_VECTOR(bits) \
+ vxge_bVALn(bits, 0, 17)
+
+#define VXGE_HW_XMAC_VPATH_TO_VSPORT_VPMGMT_CLONE_GET_VSPORT_NUMBER(bits) \
+ vxge_bVALn(bits, 3, 5)
+
+#define VXGE_HW_KDFC_DRBL_TRIPLET_TOTAL_GET_KDFC_MAX_SIZE(bits) \
+ vxge_bVALn(bits, 17, 15)
+
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_MODE_LEGACY_MODE 0
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_MODE_NON_OFFLOAD_ONLY 1
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_MODE_MULTI_OP_MODE 2
+
+#define VXGE_HW_KDFC_TRPL_FIFO_1_CTRL_MODE_MESSAGES_ONLY 0
+#define VXGE_HW_KDFC_TRPL_FIFO_1_CTRL_MODE_MULTI_OP_MODE 1
+
+#define VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val) \
+ (val&~VXGE_HW_TOC_KDFC_INITIAL_BIR(7))
+#define VXGE_HW_TOC_GET_KDFC_INITIAL_BIR(val) \
+ vxge_bVALn(val, 61, 3)
+#define VXGE_HW_TOC_GET_USDC_INITIAL_OFFSET(val) \
+ (val&~VXGE_HW_TOC_USDC_INITIAL_BIR(7))
+#define VXGE_HW_TOC_GET_USDC_INITIAL_BIR(val) \
+ vxge_bVALn(val, 61, 3)
+
+#define VXGE_HW_TOC_KDFC_VPATH_STRIDE_GET_TOC_KDFC_VPATH_STRIDE(bits) bits
+#define VXGE_HW_TOC_KDFC_FIFO_STRIDE_GET_TOC_KDFC_FIFO_STRIDE(bits) bits
+
+#define VXGE_HW_KDFC_TRPL_FIFO_OFFSET_GET_KDFC_RCTR0(bits) \
+ vxge_bVALn(bits, 1, 15)
+#define VXGE_HW_KDFC_TRPL_FIFO_OFFSET_GET_KDFC_RCTR1(bits) \
+ vxge_bVALn(bits, 17, 15)
+#define VXGE_HW_KDFC_TRPL_FIFO_OFFSET_GET_KDFC_RCTR2(bits) \
+ vxge_bVALn(bits, 33, 15)
+
+#define VXGE_HW_KDFC_TRPL_FIFO_OFFSET_KDFC_VAPTH_NUM(val) vxge_vBIT(val, 42, 5)
+#define VXGE_HW_KDFC_TRPL_FIFO_OFFSET_KDFC_FIFO_NUM(val) vxge_vBIT(val, 47, 2)
+#define VXGE_HW_KDFC_TRPL_FIFO_OFFSET_KDFC_FIFO_OFFSET(val) \
+ vxge_vBIT(val, 49, 15)
+
+#define VXGE_HW_PRC_CFG4_RING_MODE_ONE_BUFFER 0
+#define VXGE_HW_PRC_CFG4_RING_MODE_THREE_BUFFER 1
+#define VXGE_HW_PRC_CFG4_RING_MODE_FIVE_BUFFER 2
+
+#define VXGE_HW_PRC_CFG7_SCATTER_MODE_A 0
+#define VXGE_HW_PRC_CFG7_SCATTER_MODE_B 2
+#define VXGE_HW_PRC_CFG7_SCATTER_MODE_C 1
+
+#define VXGE_HW_RTS_MGR_STEER_CTRL_WE_READ 0
+#define VXGE_HW_RTS_MGR_STEER_CTRL_WE_WRITE 1
+
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_DA 0
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_VID 1
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_ETYPE 2
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_PN 3
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_RANGE_PN 4
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_RTH_GEN_CFG 5
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT 6
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_RTH_JHASH_CFG 7
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_RTH_MASK 8
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_RTH_KEY 9
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_QOS 10
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_DS 11
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT 12
+#define VXGE_HW_RTS_MGR_STEER_CTRL_DATA_STRUCT_SEL_FW_VERSION 13
+
+#define VXGE_HW_RTS_MGR_STEER_DATA0_GET_DA_MAC_ADDR(bits) \
+ vxge_bVALn(bits, 0, 48)
+#define VXGE_HW_RTS_MGR_STEER_DATA0_DA_MAC_ADDR(val) vxge_vBIT(val, 0, 48)
+
+#define VXGE_HW_RTS_MGR_STEER_DATA1_GET_DA_MAC_ADDR_MASK(bits) \
+ vxge_bVALn(bits, 0, 48)
+#define VXGE_HW_RTS_MGR_STEER_DATA1_DA_MAC_ADDR_MASK(val) vxge_vBIT(val, 0, 48)
+#define VXGE_HW_RTS_MGR_STEER_DATA1_DA_MAC_ADDR_ADD_PRIVILEGED_MODE \
+ vxge_mBIT(54)
+#define VXGE_HW_RTS_MGR_STEER_DATA1_GET_DA_MAC_ADDR_ADD_VPATH(bits) \
+ vxge_bVALn(bits, 55, 5)
+#define VXGE_HW_RTS_MGR_STEER_DATA1_DA_MAC_ADDR_ADD_VPATH(val) \
+ vxge_vBIT(val, 55, 5)
+#define VXGE_HW_RTS_MGR_STEER_DATA1_GET_DA_MAC_ADDR_ADD_MODE(bits) \
+ vxge_bVALn(bits, 62, 2)
+#define VXGE_HW_RTS_MGR_STEER_DATA1_DA_MAC_ADDR_MODE(val) vxge_vBIT(val, 62, 2)
+
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_ADD_ENTRY 0
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_DELETE_ENTRY 1
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_FIRST_ENTRY 2
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_NEXT_ENTRY 3
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY 0
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_WRITE_ENTRY 1
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY 3
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LED_CONTROL 4
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_ALL_CLEAR 172
+
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA 0
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_VID 1
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_ETYPE 2
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_PN 3
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_GEN_CFG 5
+#define VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT 6
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_JHASH_CFG 7
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MASK 8
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_KEY 9
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_QOS 10
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DS 11
+#define VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT 12
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO 13
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(bits) \
+ vxge_bVALn(bits, 0, 48)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_DA_MAC_ADDR(val) vxge_vBIT(val, 0, 48)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_SEND_TO_NW vxge_mBIT(51)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_VLAN_ID(bits) vxge_bVALn(bits, 0, 12)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_VLAN_ID(val) vxge_vBIT(val, 0, 12)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_ETYPE(bits) vxge_bVALn(bits, 0, 11)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_ETYPE(val) vxge_vBIT(val, 0, 16)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_PN_SRC_DEST_SEL(bits) \
+ vxge_bVALn(bits, 3, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_PN_SRC_DEST_SEL vxge_mBIT(3)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_PN_TCP_UDP_SEL(bits) \
+ vxge_bVALn(bits, 7, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_PN_TCP_UDP_SEL vxge_mBIT(7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_PN_PORT_NUM(bits) \
+ vxge_bVALn(bits, 8, 16)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_PN_PORT_NUM(val) vxge_vBIT(val, 8, 16)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_GEN_RTH_EN(bits) \
+ vxge_bVALn(bits, 3, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_EN vxge_mBIT(3)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_GEN_BUCKET_SIZE(bits) \
+ vxge_bVALn(bits, 4, 4)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_BUCKET_SIZE(val) \
+ vxge_vBIT(val, 4, 4)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_GEN_ALG_SEL(bits) \
+ vxge_bVALn(bits, 10, 2)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ALG_SEL(val) \
+ vxge_vBIT(val, 10, 2)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ALG_SEL_JENKINS 0
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ALG_SEL_MS_RSS 1
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ALG_SEL_CRC32C 2
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_GEN_RTH_TCP_IPV4_EN(bits) \
+ vxge_bVALn(bits, 15, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_TCP_IPV4_EN vxge_mBIT(15)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_GEN_RTH_IPV4_EN(bits) \
+ vxge_bVALn(bits, 19, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_IPV4_EN vxge_mBIT(19)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_GEN_RTH_TCP_IPV6_EN(bits) \
+ vxge_bVALn(bits, 23, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_TCP_IPV6_EN vxge_mBIT(23)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_GEN_RTH_IPV6_EN(bits) \
+ vxge_bVALn(bits, 27, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_IPV6_EN vxge_mBIT(27)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_GEN_RTH_TCP_IPV6_EX_EN(bits) \
+ vxge_bVALn(bits, 31, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_TCP_IPV6_EX_EN vxge_mBIT(31)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_GEN_RTH_IPV6_EX_EN(bits) \
+ vxge_bVALn(bits, 35, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_IPV6_EX_EN vxge_mBIT(35)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_GEN_ACTIVE_TABLE(bits) \
+ vxge_bVALn(bits, 39, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ACTIVE_TABLE vxge_mBIT(39)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_GEN_REPL_ENTRY_EN(bits) \
+ vxge_bVALn(bits, 43, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_REPL_ENTRY_EN vxge_mBIT(43)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_SOLO_IT_ENTRY_EN(bits) \
+ vxge_bVALn(bits, 3, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_SOLO_IT_ENTRY_EN vxge_mBIT(3)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_SOLO_IT_BUCKET_DATA(bits) \
+ vxge_bVALn(bits, 9, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_SOLO_IT_BUCKET_DATA(val) \
+ vxge_vBIT(val, 9, 7)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_ITEM0_BUCKET_NUM(bits) \
+ vxge_bVALn(bits, 0, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM0_BUCKET_NUM(val) \
+ vxge_vBIT(val, 0, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_ITEM0_ENTRY_EN(bits) \
+ vxge_bVALn(bits, 8, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM0_ENTRY_EN vxge_mBIT(8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_ITEM0_BUCKET_DATA(bits) \
+ vxge_bVALn(bits, 9, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM0_BUCKET_DATA(val) \
+ vxge_vBIT(val, 9, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_ITEM1_BUCKET_NUM(bits) \
+ vxge_bVALn(bits, 16, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM1_BUCKET_NUM(val) \
+ vxge_vBIT(val, 16, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_ITEM1_ENTRY_EN(bits) \
+ vxge_bVALn(bits, 24, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM1_ENTRY_EN vxge_mBIT(24)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_ITEM1_BUCKET_DATA(bits) \
+ vxge_bVALn(bits, 25, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM1_BUCKET_DATA(val) \
+ vxge_vBIT(val, 25, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM0_BUCKET_NUM(bits) \
+ vxge_bVALn(bits, 0, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM0_BUCKET_NUM(val) \
+ vxge_vBIT(val, 0, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM0_ENTRY_EN(bits) \
+ vxge_bVALn(bits, 8, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM0_ENTRY_EN vxge_mBIT(8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM0_BUCKET_DATA(bits) \
+ vxge_bVALn(bits, 9, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM0_BUCKET_DATA(val) \
+ vxge_vBIT(val, 9, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM1_BUCKET_NUM(bits) \
+ vxge_bVALn(bits, 16, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM1_BUCKET_NUM(val) \
+ vxge_vBIT(val, 16, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM1_ENTRY_EN(bits) \
+ vxge_bVALn(bits, 24, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM1_ENTRY_EN vxge_mBIT(24)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM1_BUCKET_DATA(bits) \
+ vxge_bVALn(bits, 25, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM1_BUCKET_DATA(val) \
+ vxge_vBIT(val, 25, 7)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_JHASH_CFG_GOLDEN_RATIO(bits) \
+ vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_JHASH_CFG_GOLDEN_RATIO(val) \
+ vxge_vBIT(val, 0, 32)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_JHASH_CFG_INIT_VALUE(bits) \
+ vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_JHASH_CFG_INIT_VALUE(val) \
+ vxge_vBIT(val, 32, 32)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_MASK_IPV6_SA_MASK(bits) \
+ vxge_bVALn(bits, 0, 16)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_MASK_IPV6_SA_MASK(val) \
+ vxge_vBIT(val, 0, 16)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_MASK_IPV6_DA_MASK(bits) \
+ vxge_bVALn(bits, 16, 16)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_MASK_IPV6_DA_MASK(val) \
+ vxge_vBIT(val, 16, 16)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_MASK_IPV4_SA_MASK(bits) \
+ vxge_bVALn(bits, 32, 4)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_MASK_IPV4_SA_MASK(val) \
+ vxge_vBIT(val, 32, 4)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_MASK_IPV4_DA_MASK(bits) \
+ vxge_bVALn(bits, 36, 4)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_MASK_IPV4_DA_MASK(val) \
+ vxge_vBIT(val, 36, 4)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_MASK_L4SP_MASK(bits) \
+ vxge_bVALn(bits, 40, 2)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_MASK_L4SP_MASK(val) \
+ vxge_vBIT(val, 40, 2)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_MASK_L4DP_MASK(bits) \
+ vxge_bVALn(bits, 42, 2)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_MASK_L4DP_MASK(val) \
+ vxge_vBIT(val, 42, 2)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_KEY_KEY(bits) \
+ vxge_bVALn(bits, 0, 64)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_KEY_KEY vxge_vBIT(val, 0, 64)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_QOS_ENTRY_EN(bits) \
+ vxge_bVALn(bits, 3, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_QOS_ENTRY_EN vxge_mBIT(3)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DS_ENTRY_EN(bits) \
+ vxge_bVALn(bits, 3, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_DS_ENTRY_EN vxge_mBIT(3)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK(bits) \
+ vxge_bVALn(bits, 0, 48)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_DA_MAC_ADDR_MASK(val) \
+ vxge_vBIT(val, 0, 48)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_DA_MAC_ADDR_MODE(val) \
+ vxge_vBIT(val, 62, 2)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM4_BUCKET_NUM(bits) \
+ vxge_bVALn(bits, 0, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM4_BUCKET_NUM(val) \
+ vxge_vBIT(val, 0, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM4_ENTRY_EN(bits) \
+ vxge_bVALn(bits, 8, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM4_ENTRY_EN vxge_mBIT(8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM4_BUCKET_DATA(bits) \
+ vxge_bVALn(bits, 9, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM4_BUCKET_DATA(val) \
+ vxge_vBIT(val, 9, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM5_BUCKET_NUM(bits) \
+ vxge_bVALn(bits, 16, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM5_BUCKET_NUM(val) \
+ vxge_vBIT(val, 16, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM5_ENTRY_EN(bits) \
+ vxge_bVALn(bits, 24, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM5_ENTRY_EN vxge_mBIT(24)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM5_BUCKET_DATA(bits) \
+ vxge_bVALn(bits, 25, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM5_BUCKET_DATA(val) \
+ vxge_vBIT(val, 25, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM6_BUCKET_NUM(bits) \
+ vxge_bVALn(bits, 32, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM6_BUCKET_NUM(val) \
+ vxge_vBIT(val, 32, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM6_ENTRY_EN(bits) \
+ vxge_bVALn(bits, 40, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM6_ENTRY_EN vxge_mBIT(40)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM6_BUCKET_DATA(bits) \
+ vxge_bVALn(bits, 41, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM6_BUCKET_DATA(val) \
+ vxge_vBIT(val, 41, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM7_BUCKET_NUM(bits) \
+ vxge_bVALn(bits, 48, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM7_BUCKET_NUM(val) \
+ vxge_vBIT(val, 48, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM7_ENTRY_EN(bits) \
+ vxge_bVALn(bits, 56, 1)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM7_ENTRY_EN vxge_mBIT(56)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RTH_ITEM7_BUCKET_DATA(bits) \
+ vxge_bVALn(bits, 57, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM7_BUCKET_DATA(val) \
+ vxge_vBIT(val, 57, 7)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PART_NUMBER 0
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_SERIAL_NUMBER 1
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_VERSION 2
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PCI_MODE 3
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_0 4
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_1 5
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_2 6
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_3 7
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PORTS 8
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PORT0_PMD_TYPE 10
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PORT0_PMD_VENDOR 11
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PORT0_PMD_PARTNO 13
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PORT0_PMD_SERNO 14
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PORT1_PMD_TYPE 20
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PORT1_PMD_VENDOR 21
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PORT1_PMD_PARTNO 23
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PORT1_PMD_SERNO 24
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_LED_CONTROL_ON 1
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_LED_CONTROL_OFF 0
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_DAY(bits) \
+ vxge_bVALn(bits, 0, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_FW_VER_DAY(val) vxge_vBIT(val, 0, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MONTH(bits) \
+ vxge_bVALn(bits, 8, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_FW_VER_MONTH(val) vxge_vBIT(val, 8, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_YEAR(bits) \
+ vxge_bVALn(bits, 16, 16)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_FW_VER_YEAR(val) \
+ vxge_vBIT(val, 16, 16)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MAJOR(bits) \
+ vxge_bVALn(bits, 32, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_FW_VER_MAJOR vxge_vBIT(val, 32, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MINOR(bits) \
+ vxge_bVALn(bits, 40, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_FW_VER_MINOR vxge_vBIT(val, 40, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_BUILD(bits) \
+ vxge_bVALn(bits, 48, 16)
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_GET_ACTION(bits) \
+ vxge_bVALn(bits, 0, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_FW_VER_BUILD vxge_vBIT(val, 48, 16)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_DAY(bits) \
+ vxge_bVALn(bits, 0, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_FLASH_VER_DAY(val) vxge_vBIT(val, 0, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MONTH(bits) \
+ vxge_bVALn(bits, 8, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_FLASH_VER_MONTH(val) vxge_vBIT(val, 8, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_YEAR(bits) \
+ vxge_bVALn(bits, 16, 16)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_FLASH_VER_YEAR(val) \
+ vxge_vBIT(val, 16, 16)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MAJOR(bits) \
+ vxge_bVALn(bits, 32, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_FLASH_VER_MAJOR vxge_vBIT(val, 32, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MINOR(bits) \
+ vxge_bVALn(bits, 40, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_FLASH_VER_MINOR vxge_vBIT(val, 40, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_BUILD(bits) \
+ vxge_bVALn(bits, 48, 16)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_FLASH_VER_BUILD vxge_vBIT(val, 48, 16)
+
+/* Netork port control API related */
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_SET_NWIF_CMD(val) \
+ vxge_vBIT(val, 0, 8)
+
+/* Bandwidth & priority related MACROS */
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_API_VER(bits) \
+ vxge_bVALn(bits, 0, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_TX_PRIORITY(bits) \
+ vxge_bVALn(bits, 21, 3)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_TX_MIN_BW(bits) \
+ vxge_bVALn(bits, 24, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_TX_MAX_BW(bits) \
+ vxge_bVALn(bits, 32, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RX_PRIORITY(bits) \
+ vxge_bVALn(bits, 45, 3)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RX_MIN_BW(bits) \
+ vxge_bVALn(bits, 48, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_RX_MAX_BW(bits) \
+ vxge_bVALn(bits, 56, 8)
+
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_SET_VPATH_OR_FUNC(val) \
+ vxge_vBIT(val, 0, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_SET_TX_PRIORITY(val) \
+ vxge_vBIT(val, 21, 3)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_SET_TX_MIN_BW(val) \
+ vxge_vBIT(val, 24, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_SET_TX_MAX_BW(val) \
+ vxge_vBIT(val, 32, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_SET_RX_PRIORITY(val) \
+ vxge_vBIT(val, 45, 3)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_SET_RX_MIN_BW(val) \
+ vxge_vBIT(val, 48, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_SET_RX_MAX_BW(val) \
+ vxge_vBIT(val, 56, 8)
+
+#define VXGE_HW_SRPCIM_TO_VPATH_ALARM_REG_GET_PPIF_SRPCIM_TO_VPATH_ALARM(bits)\
+ vxge_bVALn(bits, 0, 18)
+
+#define VXGE_HW_RX_MULTI_CAST_STATS_GET_FRAME_DISCARD(bits) \
+ vxge_bVALn(bits, 48, 16)
+#define VXGE_HW_RX_FRM_TRANSFERRED_GET_RX_FRM_TRANSFERRED(bits) \
+ vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_RXD_RETURNED_GET_RXD_RETURNED(bits) vxge_bVALn(bits, 48, 16)
+#define VXGE_HW_VPATH_DEBUG_STATS0_GET_INI_NUM_MWR_SENT(bits) \
+ vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_VPATH_DEBUG_STATS1_GET_INI_NUM_MRD_SENT(bits) \
+ vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_VPATH_DEBUG_STATS2_GET_INI_NUM_CPL_RCVD(bits) \
+ vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_VPATH_DEBUG_STATS3_GET_INI_NUM_MWR_BYTE_SENT(bits) (bits)
+#define VXGE_HW_VPATH_DEBUG_STATS4_GET_INI_NUM_CPL_BYTE_RCVD(bits) (bits)
+#define VXGE_HW_VPATH_DEBUG_STATS5_GET_WRCRDTARB_XOFF(bits) \
+ vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_VPATH_DEBUG_STATS6_GET_RDCRDTARB_XOFF(bits) \
+ vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_VPATH_GENSTATS_COUNT01_GET_PPIF_VPATH_GENSTATS_COUNT1(bits) \
+ vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_VPATH_GENSTATS_COUNT01_GET_PPIF_VPATH_GENSTATS_COUNT0(bits) \
+ vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_VPATH_GENSTATS_COUNT23_GET_PPIF_VPATH_GENSTATS_COUNT3(bits) \
+ vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_VPATH_GENSTATS_COUNT23_GET_PPIF_VPATH_GENSTATS_COUNT2(bits) \
+ vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_VPATH_GENSTATS_COUNT4_GET_PPIF_VPATH_GENSTATS_COUNT4(bits) \
+ vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_VPATH_GENSTATS_COUNT5_GET_PPIF_VPATH_GENSTATS_COUNT5(bits) \
+ vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_TX_VP_RESET_DISCARDED_FRMS_GET_TX_VP_RESET_DISCARDED_FRMS(bits\
+) vxge_bVALn(bits, 48, 16)
+#define VXGE_HW_DBG_STATS_GET_RX_MPA_CRC_FAIL_FRMS(bits) vxge_bVALn(bits, 0, 16)
+#define VXGE_HW_DBG_STATS_GET_RX_MPA_MRK_FAIL_FRMS(bits) \
+ vxge_bVALn(bits, 16, 16)
+#define VXGE_HW_DBG_STATS_GET_RX_MPA_LEN_FAIL_FRMS(bits) \
+ vxge_bVALn(bits, 32, 16)
+#define VXGE_HW_DBG_STATS_GET_RX_FAU_RX_WOL_FRMS(bits) vxge_bVALn(bits, 0, 16)
+#define VXGE_HW_DBG_STATS_GET_RX_FAU_RX_VP_RESET_DISCARDED_FRMS(bits) \
+ vxge_bVALn(bits, 16, 16)
+#define VXGE_HW_DBG_STATS_GET_RX_FAU_RX_PERMITTED_FRMS(bits) \
+ vxge_bVALn(bits, 32, 16)
+
+#define VXGE_HW_MRPCIM_DEBUG_STATS0_GET_INI_WR_DROP(bits) \
+ vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_MRPCIM_DEBUG_STATS0_GET_INI_RD_DROP(bits) \
+ vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_MRPCIM_DEBUG_STATS1_GET_VPLANE_WRCRDTARB_PH_CRDT_DEPLETED(bits\
+) vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_MRPCIM_DEBUG_STATS2_GET_VPLANE_WRCRDTARB_PD_CRDT_DEPLETED(bits\
+) vxge_bVALn(bits, 32, 32)
+#define \
+VXGE_HW_MRPCIM_DEBUG_STATS3_GET_VPLANE_RDCRDTARB_NPH_CRDT_DEPLETED(bits) \
+ vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_MRPCIM_DEBUG_STATS4_GET_INI_WR_VPIN_DROP(bits) \
+ vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_MRPCIM_DEBUG_STATS4_GET_INI_RD_VPIN_DROP(bits) \
+ vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_GENSTATS_COUNT01_GET_GENSTATS_COUNT1(bits) \
+ vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_GENSTATS_COUNT01_GET_GENSTATS_COUNT0(bits) \
+ vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_GENSTATS_COUNT23_GET_GENSTATS_COUNT3(bits) \
+ vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_GENSTATS_COUNT23_GET_GENSTATS_COUNT2(bits) \
+ vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_GENSTATS_COUNT4_GET_GENSTATS_COUNT4(bits) \
+ vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_GENSTATS_COUNT5_GET_GENSTATS_COUNT5(bits) \
+ vxge_bVALn(bits, 32, 32)
+
+#define VXGE_HW_DEBUG_STATS0_GET_RSTDROP_MSG(bits) vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_DEBUG_STATS0_GET_RSTDROP_CPL(bits) vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_DEBUG_STATS1_GET_RSTDROP_CLIENT0(bits) vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_DEBUG_STATS1_GET_RSTDROP_CLIENT1(bits) vxge_bVALn(bits, 32, 32)
+#define VXGE_HW_DEBUG_STATS2_GET_RSTDROP_CLIENT2(bits) vxge_bVALn(bits, 0, 32)
+#define VXGE_HW_DEBUG_STATS3_GET_VPLANE_DEPL_PH(bits) vxge_bVALn(bits, 0, 16)
+#define VXGE_HW_DEBUG_STATS3_GET_VPLANE_DEPL_NPH(bits) vxge_bVALn(bits, 16, 16)
+#define VXGE_HW_DEBUG_STATS3_GET_VPLANE_DEPL_CPLH(bits) vxge_bVALn(bits, 32, 16)
+#define VXGE_HW_DEBUG_STATS4_GET_VPLANE_DEPL_PD(bits) vxge_bVALn(bits, 0, 16)
+#define VXGE_HW_DEBUG_STATS4_GET_VPLANE_DEPL_NPD(bits) vxge_bVALn(bits, 16, 16)
+#define VXGE_HW_DEBUG_STATS4_GET_VPLANE_DEPL_CPLD(bits) vxge_bVALn(bits, 32, 16)
+
+#define VXGE_HW_DBG_STATS_TPA_TX_PATH_GET_TX_PERMITTED_FRMS(bits) \
+ vxge_bVALn(bits, 32, 32)
+
+#define VXGE_HW_DBG_STAT_TX_ANY_FRMS_GET_PORT0_TX_ANY_FRMS(bits) \
+ vxge_bVALn(bits, 0, 8)
+#define VXGE_HW_DBG_STAT_TX_ANY_FRMS_GET_PORT1_TX_ANY_FRMS(bits) \
+ vxge_bVALn(bits, 8, 8)
+#define VXGE_HW_DBG_STAT_TX_ANY_FRMS_GET_PORT2_TX_ANY_FRMS(bits) \
+ vxge_bVALn(bits, 16, 8)
+
+#define VXGE_HW_DBG_STAT_RX_ANY_FRMS_GET_PORT0_RX_ANY_FRMS(bits) \
+ vxge_bVALn(bits, 0, 8)
+#define VXGE_HW_DBG_STAT_RX_ANY_FRMS_GET_PORT1_RX_ANY_FRMS(bits) \
+ vxge_bVALn(bits, 8, 8)
+#define VXGE_HW_DBG_STAT_RX_ANY_FRMS_GET_PORT2_RX_ANY_FRMS(bits) \
+ vxge_bVALn(bits, 16, 8)
+
+#define VXGE_HW_CONFIG_PRIV_H
+
+#define VXGE_HW_SWAPPER_INITIAL_VALUE 0x0123456789abcdefULL
+#define VXGE_HW_SWAPPER_BYTE_SWAPPED 0xefcdab8967452301ULL
+#define VXGE_HW_SWAPPER_BIT_FLIPPED 0x80c4a2e691d5b3f7ULL
+#define VXGE_HW_SWAPPER_BYTE_SWAPPED_BIT_FLIPPED 0xf7b3d591e6a2c480ULL
+
+#define VXGE_HW_SWAPPER_READ_BYTE_SWAP_ENABLE 0xFFFFFFFFFFFFFFFFULL
+#define VXGE_HW_SWAPPER_READ_BYTE_SWAP_DISABLE 0x0000000000000000ULL
+
+#define VXGE_HW_SWAPPER_READ_BIT_FLAP_ENABLE 0xFFFFFFFFFFFFFFFFULL
+#define VXGE_HW_SWAPPER_READ_BIT_FLAP_DISABLE 0x0000000000000000ULL
+
+#define VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE 0xFFFFFFFFFFFFFFFFULL
+#define VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_DISABLE 0x0000000000000000ULL
+
+#define VXGE_HW_SWAPPER_WRITE_BIT_FLAP_ENABLE 0xFFFFFFFFFFFFFFFFULL
+#define VXGE_HW_SWAPPER_WRITE_BIT_FLAP_DISABLE 0x0000000000000000ULL
+
+/*
+ * The registers are memory mapped and are native big-endian byte order. The
+ * little-endian hosts are handled by enabling hardware byte-swapping for
+ * register and dma operations.
+ */
+struct vxge_hw_legacy_reg {
+
+ u8 unused00010[0x00010];
+
+/*0x00010*/ u64 toc_swapper_fb;
+#define VXGE_HW_TOC_SWAPPER_FB_INITIAL_VAL(val) vxge_vBIT(val, 0, 64)
+/*0x00018*/ u64 pifm_rd_swap_en;
+#define VXGE_HW_PIFM_RD_SWAP_EN_PIFM_RD_SWAP_EN(val) vxge_vBIT(val, 0, 64)
+/*0x00020*/ u64 pifm_rd_flip_en;
+#define VXGE_HW_PIFM_RD_FLIP_EN_PIFM_RD_FLIP_EN(val) vxge_vBIT(val, 0, 64)
+/*0x00028*/ u64 pifm_wr_swap_en;
+#define VXGE_HW_PIFM_WR_SWAP_EN_PIFM_WR_SWAP_EN(val) vxge_vBIT(val, 0, 64)
+/*0x00030*/ u64 pifm_wr_flip_en;
+#define VXGE_HW_PIFM_WR_FLIP_EN_PIFM_WR_FLIP_EN(val) vxge_vBIT(val, 0, 64)
+/*0x00038*/ u64 toc_first_pointer;
+#define VXGE_HW_TOC_FIRST_POINTER_INITIAL_VAL(val) vxge_vBIT(val, 0, 64)
+/*0x00040*/ u64 host_access_en;
+#define VXGE_HW_HOST_ACCESS_EN_HOST_ACCESS_EN(val) vxge_vBIT(val, 0, 64)
+
+} __attribute((packed));
+
+struct vxge_hw_toc_reg {
+
+ u8 unused00050[0x00050];
+
+/*0x00050*/ u64 toc_common_pointer;
+#define VXGE_HW_TOC_COMMON_POINTER_INITIAL_VAL(val) vxge_vBIT(val, 0, 64)
+/*0x00058*/ u64 toc_memrepair_pointer;
+#define VXGE_HW_TOC_MEMREPAIR_POINTER_INITIAL_VAL(val) vxge_vBIT(val, 0, 64)
+/*0x00060*/ u64 toc_pcicfgmgmt_pointer[17];
+#define VXGE_HW_TOC_PCICFGMGMT_POINTER_INITIAL_VAL(val) vxge_vBIT(val, 0, 64)
+ u8 unused001e0[0x001e0-0x000e8];
+
+/*0x001e0*/ u64 toc_mrpcim_pointer;
+#define VXGE_HW_TOC_MRPCIM_POINTER_INITIAL_VAL(val) vxge_vBIT(val, 0, 64)
+/*0x001e8*/ u64 toc_srpcim_pointer[17];
+#define VXGE_HW_TOC_SRPCIM_POINTER_INITIAL_VAL(val) vxge_vBIT(val, 0, 64)
+ u8 unused00278[0x00278-0x00270];
+
+/*0x00278*/ u64 toc_vpmgmt_pointer[17];
+#define VXGE_HW_TOC_VPMGMT_POINTER_INITIAL_VAL(val) vxge_vBIT(val, 0, 64)
+ u8 unused00390[0x00390-0x00300];
+
+/*0x00390*/ u64 toc_vpath_pointer[17];
+#define VXGE_HW_TOC_VPATH_POINTER_INITIAL_VAL(val) vxge_vBIT(val, 0, 64)
+ u8 unused004a0[0x004a0-0x00418];
+
+/*0x004a0*/ u64 toc_kdfc;
+#define VXGE_HW_TOC_KDFC_INITIAL_OFFSET(val) vxge_vBIT(val, 0, 61)
+#define VXGE_HW_TOC_KDFC_INITIAL_BIR(val) vxge_vBIT(val, 61, 3)
+/*0x004a8*/ u64 toc_usdc;
+#define VXGE_HW_TOC_USDC_INITIAL_OFFSET(val) vxge_vBIT(val, 0, 61)
+#define VXGE_HW_TOC_USDC_INITIAL_BIR(val) vxge_vBIT(val, 61, 3)
+/*0x004b0*/ u64 toc_kdfc_vpath_stride;
+#define VXGE_HW_TOC_KDFC_VPATH_STRIDE_INITIAL_TOC_KDFC_VPATH_STRIDE(val) \
+ vxge_vBIT(val, 0, 64)
+/*0x004b8*/ u64 toc_kdfc_fifo_stride;
+#define VXGE_HW_TOC_KDFC_FIFO_STRIDE_INITIAL_TOC_KDFC_FIFO_STRIDE(val) \
+ vxge_vBIT(val, 0, 64)
+
+} __attribute((packed));
+
+struct vxge_hw_common_reg {
+
+ u8 unused00a00[0x00a00];
+
+/*0x00a00*/ u64 prc_status1;
+#define VXGE_HW_PRC_STATUS1_PRC_VP_QUIESCENT(n) vxge_mBIT(n)
+/*0x00a08*/ u64 rxdcm_reset_in_progress;
+#define VXGE_HW_RXDCM_RESET_IN_PROGRESS_PRC_VP(n) vxge_mBIT(n)
+/*0x00a10*/ u64 replicq_flush_in_progress;
+#define VXGE_HW_REPLICQ_FLUSH_IN_PROGRESS_NOA_VP(n) vxge_mBIT(n)
+/*0x00a18*/ u64 rxpe_cmds_reset_in_progress;
+#define VXGE_HW_RXPE_CMDS_RESET_IN_PROGRESS_NOA_VP(n) vxge_mBIT(n)
+/*0x00a20*/ u64 mxp_cmds_reset_in_progress;
+#define VXGE_HW_MXP_CMDS_RESET_IN_PROGRESS_NOA_VP(n) vxge_mBIT(n)
+/*0x00a28*/ u64 noffload_reset_in_progress;
+#define VXGE_HW_NOFFLOAD_RESET_IN_PROGRESS_PRC_VP(n) vxge_mBIT(n)
+/*0x00a30*/ u64 rd_req_in_progress;
+#define VXGE_HW_RD_REQ_IN_PROGRESS_VP(n) vxge_mBIT(n)
+/*0x00a38*/ u64 rd_req_outstanding;
+#define VXGE_HW_RD_REQ_OUTSTANDING_VP(n) vxge_mBIT(n)
+/*0x00a40*/ u64 kdfc_reset_in_progress;
+#define VXGE_HW_KDFC_RESET_IN_PROGRESS_NOA_VP(n) vxge_mBIT(n)
+ u8 unused00b00[0x00b00-0x00a48];
+
+/*0x00b00*/ u64 one_cfg_vp;
+#define VXGE_HW_ONE_CFG_VP_RDY(n) vxge_mBIT(n)
+/*0x00b08*/ u64 one_common;
+#define VXGE_HW_ONE_COMMON_PET_VPATH_RESET_IN_PROGRESS(n) vxge_mBIT(n)
+ u8 unused00b80[0x00b80-0x00b10];
+
+/*0x00b80*/ u64 tim_int_en;
+#define VXGE_HW_TIM_INT_EN_TIM_VP(n) vxge_mBIT(n)
+/*0x00b88*/ u64 tim_set_int_en;
+#define VXGE_HW_TIM_SET_INT_EN_VP(n) vxge_mBIT(n)
+/*0x00b90*/ u64 tim_clr_int_en;
+#define VXGE_HW_TIM_CLR_INT_EN_VP(n) vxge_mBIT(n)
+/*0x00b98*/ u64 tim_mask_int_during_reset;
+#define VXGE_HW_TIM_MASK_INT_DURING_RESET_VPATH(n) vxge_mBIT(n)
+/*0x00ba0*/ u64 tim_reset_in_progress;
+#define VXGE_HW_TIM_RESET_IN_PROGRESS_TIM_VPATH(n) vxge_mBIT(n)
+/*0x00ba8*/ u64 tim_outstanding_bmap;
+#define VXGE_HW_TIM_OUTSTANDING_BMAP_TIM_VPATH(n) vxge_mBIT(n)
+ u8 unused00c00[0x00c00-0x00bb0];
+
+/*0x00c00*/ u64 msg_reset_in_progress;
+#define VXGE_HW_MSG_RESET_IN_PROGRESS_MSG_COMPOSITE(val) vxge_vBIT(val, 0, 17)
+/*0x00c08*/ u64 msg_mxp_mr_ready;
+#define VXGE_HW_MSG_MXP_MR_READY_MP_BOOTED(n) vxge_mBIT(n)
+/*0x00c10*/ u64 msg_uxp_mr_ready;
+#define VXGE_HW_MSG_UXP_MR_READY_UP_BOOTED(n) vxge_mBIT(n)
+/*0x00c18*/ u64 msg_dmq_noni_rtl_prefetch;
+#define VXGE_HW_MSG_DMQ_NONI_RTL_PREFETCH_BYPASS_ENABLE(n) vxge_mBIT(n)
+/*0x00c20*/ u64 msg_umq_rtl_bwr;
+#define VXGE_HW_MSG_UMQ_RTL_BWR_PREFETCH_DISABLE(n) vxge_mBIT(n)
+ u8 unused00d00[0x00d00-0x00c28];
+
+/*0x00d00*/ u64 cmn_rsthdlr_cfg0;
+#define VXGE_HW_CMN_RSTHDLR_CFG0_SW_RESET_VPATH(val) vxge_vBIT(val, 0, 17)
+/*0x00d08*/ u64 cmn_rsthdlr_cfg1;
+#define VXGE_HW_CMN_RSTHDLR_CFG1_CLR_VPATH_RESET(val) vxge_vBIT(val, 0, 17)
+/*0x00d10*/ u64 cmn_rsthdlr_cfg2;
+#define VXGE_HW_CMN_RSTHDLR_CFG2_SW_RESET_FIFO0(val) vxge_vBIT(val, 0, 17)
+/*0x00d18*/ u64 cmn_rsthdlr_cfg3;
+#define VXGE_HW_CMN_RSTHDLR_CFG3_SW_RESET_FIFO1(val) vxge_vBIT(val, 0, 17)
+/*0x00d20*/ u64 cmn_rsthdlr_cfg4;
+#define VXGE_HW_CMN_RSTHDLR_CFG4_SW_RESET_FIFO2(val) vxge_vBIT(val, 0, 17)
+ u8 unused00d40[0x00d40-0x00d28];
+
+/*0x00d40*/ u64 cmn_rsthdlr_cfg8;
+#define VXGE_HW_CMN_RSTHDLR_CFG8_INCR_VPATH_INST_NUM(val) vxge_vBIT(val, 0, 17)
+/*0x00d48*/ u64 stats_cfg0;
+#define VXGE_HW_STATS_CFG0_STATS_ENABLE(val) vxge_vBIT(val, 0, 17)
+ u8 unused00da8[0x00da8-0x00d50];
+
+/*0x00da8*/ u64 clear_msix_mask_vect[4];
+#define VXGE_HW_CLEAR_MSIX_MASK_VECT_CLEAR_MSIX_MASK_VECT(val) \
+ vxge_vBIT(val, 0, 17)
+/*0x00dc8*/ u64 set_msix_mask_vect[4];
+#define VXGE_HW_SET_MSIX_MASK_VECT_SET_MSIX_MASK_VECT(val) vxge_vBIT(val, 0, 17)
+/*0x00de8*/ u64 clear_msix_mask_all_vect;
+#define VXGE_HW_CLEAR_MSIX_MASK_ALL_VECT_CLEAR_MSIX_MASK_ALL_VECT(val) \
+ vxge_vBIT(val, 0, 17)
+/*0x00df0*/ u64 set_msix_mask_all_vect;
+#define VXGE_HW_SET_MSIX_MASK_ALL_VECT_SET_MSIX_MASK_ALL_VECT(val) \
+ vxge_vBIT(val, 0, 17)
+/*0x00df8*/ u64 mask_vector[4];
+#define VXGE_HW_MASK_VECTOR_MASK_VECTOR(val) vxge_vBIT(val, 0, 17)
+/*0x00e18*/ u64 msix_pending_vector[4];
+#define VXGE_HW_MSIX_PENDING_VECTOR_MSIX_PENDING_VECTOR(val) \
+ vxge_vBIT(val, 0, 17)
+/*0x00e38*/ u64 clr_msix_one_shot_vec[4];
+#define VXGE_HW_CLR_MSIX_ONE_SHOT_VEC_CLR_MSIX_ONE_SHOT_VEC(val) \
+ vxge_vBIT(val, 0, 17)
+/*0x00e58*/ u64 titan_asic_id;
+#define VXGE_HW_TITAN_ASIC_ID_INITIAL_DEVICE_ID(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_TITAN_ASIC_ID_INITIAL_MAJOR_REVISION(val) vxge_vBIT(val, 48, 8)
+#define VXGE_HW_TITAN_ASIC_ID_INITIAL_MINOR_REVISION(val) vxge_vBIT(val, 56, 8)
+/*0x00e60*/ u64 titan_general_int_status;
+#define VXGE_HW_TITAN_GENERAL_INT_STATUS_MRPCIM_ALARM_INT vxge_mBIT(0)
+#define VXGE_HW_TITAN_GENERAL_INT_STATUS_SRPCIM_ALARM_INT vxge_mBIT(1)
+#define VXGE_HW_TITAN_GENERAL_INT_STATUS_VPATH_ALARM_INT vxge_mBIT(2)
+#define VXGE_HW_TITAN_GENERAL_INT_STATUS_VPATH_TRAFFIC_INT(val) \
+ vxge_vBIT(val, 3, 17)
+ u8 unused00e70[0x00e70-0x00e68];
+
+/*0x00e70*/ u64 titan_mask_all_int;
+#define VXGE_HW_TITAN_MASK_ALL_INT_ALARM vxge_mBIT(7)
+#define VXGE_HW_TITAN_MASK_ALL_INT_TRAFFIC vxge_mBIT(15)
+ u8 unused00e80[0x00e80-0x00e78];
+
+/*0x00e80*/ u64 tim_int_status0;
+#define VXGE_HW_TIM_INT_STATUS0_TIM_INT_STATUS0(val) vxge_vBIT(val, 0, 64)
+/*0x00e88*/ u64 tim_int_mask0;
+#define VXGE_HW_TIM_INT_MASK0_TIM_INT_MASK0(val) vxge_vBIT(val, 0, 64)
+/*0x00e90*/ u64 tim_int_status1;
+#define VXGE_HW_TIM_INT_STATUS1_TIM_INT_STATUS1(val) vxge_vBIT(val, 0, 4)
+/*0x00e98*/ u64 tim_int_mask1;
+#define VXGE_HW_TIM_INT_MASK1_TIM_INT_MASK1(val) vxge_vBIT(val, 0, 4)
+/*0x00ea0*/ u64 rti_int_status;
+#define VXGE_HW_RTI_INT_STATUS_RTI_INT_STATUS(val) vxge_vBIT(val, 0, 17)
+/*0x00ea8*/ u64 rti_int_mask;
+#define VXGE_HW_RTI_INT_MASK_RTI_INT_MASK(val) vxge_vBIT(val, 0, 17)
+/*0x00eb0*/ u64 adapter_status;
+#define VXGE_HW_ADAPTER_STATUS_RTDMA_RTDMA_READY vxge_mBIT(0)
+#define VXGE_HW_ADAPTER_STATUS_WRDMA_WRDMA_READY vxge_mBIT(1)
+#define VXGE_HW_ADAPTER_STATUS_KDFC_KDFC_READY vxge_mBIT(2)
+#define VXGE_HW_ADAPTER_STATUS_TPA_TMAC_BUF_EMPTY vxge_mBIT(3)
+#define VXGE_HW_ADAPTER_STATUS_RDCTL_PIC_QUIESCENT vxge_mBIT(4)
+#define VXGE_HW_ADAPTER_STATUS_XGMAC_NETWORK_FAULT vxge_mBIT(5)
+#define VXGE_HW_ADAPTER_STATUS_ROCRC_OFFLOAD_QUIESCENT vxge_mBIT(6)
+#define VXGE_HW_ADAPTER_STATUS_G3IF_FB_G3IF_FB_GDDR3_READY vxge_mBIT(7)
+#define VXGE_HW_ADAPTER_STATUS_G3IF_CM_G3IF_CM_GDDR3_READY vxge_mBIT(8)
+#define VXGE_HW_ADAPTER_STATUS_RIC_RIC_RUNNING vxge_mBIT(9)
+#define VXGE_HW_ADAPTER_STATUS_CMG_C_PLL_IN_LOCK vxge_mBIT(10)
+#define VXGE_HW_ADAPTER_STATUS_XGMAC_X_PLL_IN_LOCK vxge_mBIT(11)
+#define VXGE_HW_ADAPTER_STATUS_FBIF_M_PLL_IN_LOCK vxge_mBIT(12)
+#define VXGE_HW_ADAPTER_STATUS_PCC_PCC_IDLE(val) vxge_vBIT(val, 24, 8)
+#define VXGE_HW_ADAPTER_STATUS_ROCRC_RC_PRC_QUIESCENT(val) vxge_vBIT(val, 44, 8)
+/*0x00eb8*/ u64 gen_ctrl;
+#define VXGE_HW_GEN_CTRL_SPI_MRPCIM_WR_DIS vxge_mBIT(0)
+#define VXGE_HW_GEN_CTRL_SPI_MRPCIM_RD_DIS vxge_mBIT(1)
+#define VXGE_HW_GEN_CTRL_SPI_SRPCIM_WR_DIS vxge_mBIT(2)
+#define VXGE_HW_GEN_CTRL_SPI_SRPCIM_RD_DIS vxge_mBIT(3)
+#define VXGE_HW_GEN_CTRL_SPI_DEBUG_DIS vxge_mBIT(4)
+#define VXGE_HW_GEN_CTRL_SPI_APP_LTSSM_TIMER_DIS vxge_mBIT(5)
+#define VXGE_HW_GEN_CTRL_SPI_NOT_USED(val) vxge_vBIT(val, 6, 4)
+ u8 unused00ed0[0x00ed0-0x00ec0];
+
+/*0x00ed0*/ u64 adapter_ready;
+#define VXGE_HW_ADAPTER_READY_ADAPTER_READY vxge_mBIT(63)
+/*0x00ed8*/ u64 outstanding_read;
+#define VXGE_HW_OUTSTANDING_READ_OUTSTANDING_READ(val) vxge_vBIT(val, 0, 17)
+/*0x00ee0*/ u64 vpath_rst_in_prog;
+#define VXGE_HW_VPATH_RST_IN_PROG_VPATH_RST_IN_PROG(val) vxge_vBIT(val, 0, 17)
+/*0x00ee8*/ u64 vpath_reg_modified;
+#define VXGE_HW_VPATH_REG_MODIFIED_VPATH_REG_MODIFIED(val) vxge_vBIT(val, 0, 17)
+ u8 unused00fc0[0x00fc0-0x00ef0];
+
+/*0x00fc0*/ u64 cp_reset_in_progress;
+#define VXGE_HW_CP_RESET_IN_PROGRESS_CP_VPATH(n) vxge_mBIT(n)
+ u8 unused01080[0x01080-0x00fc8];
+
+/*0x01080*/ u64 xgmac_ready;
+#define VXGE_HW_XGMAC_READY_XMACJ_READY(val) vxge_vBIT(val, 0, 17)
+ u8 unused010c0[0x010c0-0x01088];
+
+/*0x010c0*/ u64 fbif_ready;
+#define VXGE_HW_FBIF_READY_FAU_READY(val) vxge_vBIT(val, 0, 17)
+ u8 unused01100[0x01100-0x010c8];
+
+/*0x01100*/ u64 vplane_assignments;
+#define VXGE_HW_VPLANE_ASSIGNMENTS_VPLANE_ASSIGNMENTS(val) vxge_vBIT(val, 3, 5)
+/*0x01108*/ u64 vpath_assignments;
+#define VXGE_HW_VPATH_ASSIGNMENTS_VPATH_ASSIGNMENTS(val) vxge_vBIT(val, 0, 17)
+/*0x01110*/ u64 resource_assignments;
+#define VXGE_HW_RESOURCE_ASSIGNMENTS_RESOURCE_ASSIGNMENTS(val) \
+ vxge_vBIT(val, 0, 17)
+/*0x01118*/ u64 host_type_assignments;
+#define VXGE_HW_HOST_TYPE_ASSIGNMENTS_HOST_TYPE_ASSIGNMENTS(val) \
+ vxge_vBIT(val, 5, 3)
+ u8 unused01128[0x01128-0x01120];
+
+/*0x01128*/ u64 max_resource_assignments;
+#define VXGE_HW_MAX_RESOURCE_ASSIGNMENTS_PCI_MAX_VPLANE(val) \
+ vxge_vBIT(val, 3, 5)
+#define VXGE_HW_MAX_RESOURCE_ASSIGNMENTS_PCI_MAX_VPATHS(val) \
+ vxge_vBIT(val, 11, 5)
+/*0x01130*/ u64 pf_vpath_assignments;
+#define VXGE_HW_PF_VPATH_ASSIGNMENTS_PF_VPATH_ASSIGNMENTS(val) \
+ vxge_vBIT(val, 0, 17)
+ u8 unused01200[0x01200-0x01138];
+
+/*0x01200*/ u64 rts_access_icmp;
+#define VXGE_HW_RTS_ACCESS_ICMP_EN(val) vxge_vBIT(val, 0, 17)
+/*0x01208*/ u64 rts_access_tcpsyn;
+#define VXGE_HW_RTS_ACCESS_TCPSYN_EN(val) vxge_vBIT(val, 0, 17)
+/*0x01210*/ u64 rts_access_zl4pyld;
+#define VXGE_HW_RTS_ACCESS_ZL4PYLD_EN(val) vxge_vBIT(val, 0, 17)
+/*0x01218*/ u64 rts_access_l4prtcl_tcp;
+#define VXGE_HW_RTS_ACCESS_L4PRTCL_TCP_EN(val) vxge_vBIT(val, 0, 17)
+/*0x01220*/ u64 rts_access_l4prtcl_udp;
+#define VXGE_HW_RTS_ACCESS_L4PRTCL_UDP_EN(val) vxge_vBIT(val, 0, 17)
+/*0x01228*/ u64 rts_access_l4prtcl_flex;
+#define VXGE_HW_RTS_ACCESS_L4PRTCL_FLEX_EN(val) vxge_vBIT(val, 0, 17)
+/*0x01230*/ u64 rts_access_ipfrag;
+#define VXGE_HW_RTS_ACCESS_IPFRAG_EN(val) vxge_vBIT(val, 0, 17)
+
+} __attribute((packed));
+
+struct vxge_hw_memrepair_reg {
+ u64 unused1;
+ u64 unused2;
+} __attribute((packed));
+
+struct vxge_hw_pcicfgmgmt_reg {
+
+/*0x00000*/ u64 resource_no;
+#define VXGE_HW_RESOURCE_NO_PFN_OR_VF BIT(3)
+/*0x00008*/ u64 bargrp_pf_or_vf_bar0_mask;
+#define VXGE_HW_BARGRP_PF_OR_VF_BAR0_MASK_BARGRP_PF_OR_VF_BAR0_MASK(val) \
+ vxge_vBIT(val, 2, 6)
+/*0x00010*/ u64 bargrp_pf_or_vf_bar1_mask;
+#define VXGE_HW_BARGRP_PF_OR_VF_BAR1_MASK_BARGRP_PF_OR_VF_BAR1_MASK(val) \
+ vxge_vBIT(val, 2, 6)
+/*0x00018*/ u64 bargrp_pf_or_vf_bar2_mask;
+#define VXGE_HW_BARGRP_PF_OR_VF_BAR2_MASK_BARGRP_PF_OR_VF_BAR2_MASK(val) \
+ vxge_vBIT(val, 2, 6)
+/*0x00020*/ u64 msixgrp_no;
+#define VXGE_HW_MSIXGRP_NO_TABLE_SIZE(val) vxge_vBIT(val, 5, 11)
+
+} __attribute((packed));
+
+struct vxge_hw_mrpcim_reg {
+/*0x00000*/ u64 g3fbct_int_status;
+#define VXGE_HW_G3FBCT_INT_STATUS_ERR_G3IF_INT vxge_mBIT(0)
+/*0x00008*/ u64 g3fbct_int_mask;
+/*0x00010*/ u64 g3fbct_err_reg;
+#define VXGE_HW_G3FBCT_ERR_REG_G3IF_SM_ERR vxge_mBIT(4)
+#define VXGE_HW_G3FBCT_ERR_REG_G3IF_GDDR3_DECC vxge_mBIT(5)
+#define VXGE_HW_G3FBCT_ERR_REG_G3IF_GDDR3_U_DECC vxge_mBIT(6)
+#define VXGE_HW_G3FBCT_ERR_REG_G3IF_CTRL_FIFO_DECC vxge_mBIT(7)
+#define VXGE_HW_G3FBCT_ERR_REG_G3IF_GDDR3_SECC vxge_mBIT(29)
+#define VXGE_HW_G3FBCT_ERR_REG_G3IF_GDDR3_U_SECC vxge_mBIT(30)
+#define VXGE_HW_G3FBCT_ERR_REG_G3IF_CTRL_FIFO_SECC vxge_mBIT(31)
+/*0x00018*/ u64 g3fbct_err_mask;
+/*0x00020*/ u64 g3fbct_err_alarm;
+
+ u8 unused00a00[0x00a00-0x00028];
+
+/*0x00a00*/ u64 wrdma_int_status;
+#define VXGE_HW_WRDMA_INT_STATUS_RC_ALARM_RC_INT vxge_mBIT(0)
+#define VXGE_HW_WRDMA_INT_STATUS_RXDRM_SM_ERR_RXDRM_INT vxge_mBIT(1)
+#define VXGE_HW_WRDMA_INT_STATUS_RXDCM_SM_ERR_RXDCM_SM_INT vxge_mBIT(2)
+#define VXGE_HW_WRDMA_INT_STATUS_RXDWM_SM_ERR_RXDWM_INT vxge_mBIT(3)
+#define VXGE_HW_WRDMA_INT_STATUS_RDA_ERR_RDA_INT vxge_mBIT(6)
+#define VXGE_HW_WRDMA_INT_STATUS_RDA_ECC_DB_RDA_ECC_DB_INT vxge_mBIT(8)
+#define VXGE_HW_WRDMA_INT_STATUS_RDA_ECC_SG_RDA_ECC_SG_INT vxge_mBIT(9)
+#define VXGE_HW_WRDMA_INT_STATUS_FRF_ALARM_FRF_INT vxge_mBIT(12)
+#define VXGE_HW_WRDMA_INT_STATUS_ROCRC_ALARM_ROCRC_INT vxge_mBIT(13)
+#define VXGE_HW_WRDMA_INT_STATUS_WDE0_ALARM_WDE0_INT vxge_mBIT(14)
+#define VXGE_HW_WRDMA_INT_STATUS_WDE1_ALARM_WDE1_INT vxge_mBIT(15)
+#define VXGE_HW_WRDMA_INT_STATUS_WDE2_ALARM_WDE2_INT vxge_mBIT(16)
+#define VXGE_HW_WRDMA_INT_STATUS_WDE3_ALARM_WDE3_INT vxge_mBIT(17)
+/*0x00a08*/ u64 wrdma_int_mask;
+/*0x00a10*/ u64 rc_alarm_reg;
+#define VXGE_HW_RC_ALARM_REG_FTC_SM_ERR vxge_mBIT(0)
+#define VXGE_HW_RC_ALARM_REG_FTC_SM_PHASE_ERR vxge_mBIT(1)
+#define VXGE_HW_RC_ALARM_REG_BTDWM_SM_ERR vxge_mBIT(2)
+#define VXGE_HW_RC_ALARM_REG_BTC_SM_ERR vxge_mBIT(3)
+#define VXGE_HW_RC_ALARM_REG_BTDCM_SM_ERR vxge_mBIT(4)
+#define VXGE_HW_RC_ALARM_REG_BTDRM_SM_ERR vxge_mBIT(5)
+#define VXGE_HW_RC_ALARM_REG_RMM_RXD_RC_ECC_DB_ERR vxge_mBIT(6)
+#define VXGE_HW_RC_ALARM_REG_RMM_RXD_RC_ECC_SG_ERR vxge_mBIT(7)
+#define VXGE_HW_RC_ALARM_REG_RHS_RXD_RHS_ECC_DB_ERR vxge_mBIT(8)
+#define VXGE_HW_RC_ALARM_REG_RHS_RXD_RHS_ECC_SG_ERR vxge_mBIT(9)
+#define VXGE_HW_RC_ALARM_REG_RMM_SM_ERR vxge_mBIT(10)
+#define VXGE_HW_RC_ALARM_REG_BTC_VPATH_MISMATCH_ERR vxge_mBIT(12)
+/*0x00a18*/ u64 rc_alarm_mask;
+/*0x00a20*/ u64 rc_alarm_alarm;
+/*0x00a28*/ u64 rxdrm_sm_err_reg;
+#define VXGE_HW_RXDRM_SM_ERR_REG_PRC_VP(n) vxge_mBIT(n)
+/*0x00a30*/ u64 rxdrm_sm_err_mask;
+/*0x00a38*/ u64 rxdrm_sm_err_alarm;
+/*0x00a40*/ u64 rxdcm_sm_err_reg;
+#define VXGE_HW_RXDCM_SM_ERR_REG_PRC_VP(n) vxge_mBIT(n)
+/*0x00a48*/ u64 rxdcm_sm_err_mask;
+/*0x00a50*/ u64 rxdcm_sm_err_alarm;
+/*0x00a58*/ u64 rxdwm_sm_err_reg;
+#define VXGE_HW_RXDWM_SM_ERR_REG_PRC_VP(n) vxge_mBIT(n)
+/*0x00a60*/ u64 rxdwm_sm_err_mask;
+/*0x00a68*/ u64 rxdwm_sm_err_alarm;
+/*0x00a70*/ u64 rda_err_reg;
+#define VXGE_HW_RDA_ERR_REG_RDA_SM0_ERR_ALARM vxge_mBIT(0)
+#define VXGE_HW_RDA_ERR_REG_RDA_MISC_ERR vxge_mBIT(1)
+#define VXGE_HW_RDA_ERR_REG_RDA_PCIX_ERR vxge_mBIT(2)
+#define VXGE_HW_RDA_ERR_REG_RDA_RXD_ECC_DB_ERR vxge_mBIT(3)
+#define VXGE_HW_RDA_ERR_REG_RDA_FRM_ECC_DB_ERR vxge_mBIT(4)
+#define VXGE_HW_RDA_ERR_REG_RDA_UQM_ECC_DB_ERR vxge_mBIT(5)
+#define VXGE_HW_RDA_ERR_REG_RDA_IMM_ECC_DB_ERR vxge_mBIT(6)
+#define VXGE_HW_RDA_ERR_REG_RDA_TIM_ECC_DB_ERR vxge_mBIT(7)
+/*0x00a78*/ u64 rda_err_mask;
+/*0x00a80*/ u64 rda_err_alarm;
+/*0x00a88*/ u64 rda_ecc_db_reg;
+#define VXGE_HW_RDA_ECC_DB_REG_RDA_RXD_ERR(n) vxge_mBIT(n)
+/*0x00a90*/ u64 rda_ecc_db_mask;
+/*0x00a98*/ u64 rda_ecc_db_alarm;
+/*0x00aa0*/ u64 rda_ecc_sg_reg;
+#define VXGE_HW_RDA_ECC_SG_REG_RDA_RXD_ERR(n) vxge_mBIT(n)
+/*0x00aa8*/ u64 rda_ecc_sg_mask;
+/*0x00ab0*/ u64 rda_ecc_sg_alarm;
+/*0x00ab8*/ u64 rqa_err_reg;
+#define VXGE_HW_RQA_ERR_REG_RQA_SM_ERR_ALARM vxge_mBIT(0)
+/*0x00ac0*/ u64 rqa_err_mask;
+/*0x00ac8*/ u64 rqa_err_alarm;
+/*0x00ad0*/ u64 frf_alarm_reg;
+#define VXGE_HW_FRF_ALARM_REG_PRC_VP_FRF_SM_ERR(n) vxge_mBIT(n)
+/*0x00ad8*/ u64 frf_alarm_mask;
+/*0x00ae0*/ u64 frf_alarm_alarm;
+/*0x00ae8*/ u64 rocrc_alarm_reg;
+#define VXGE_HW_ROCRC_ALARM_REG_QCQ_QCC_BYP_ECC_DB vxge_mBIT(0)
+#define VXGE_HW_ROCRC_ALARM_REG_QCQ_QCC_BYP_ECC_SG vxge_mBIT(1)
+#define VXGE_HW_ROCRC_ALARM_REG_NOA_NMA_SM_ERR vxge_mBIT(2)
+#define VXGE_HW_ROCRC_ALARM_REG_NOA_IMMM_ECC_DB vxge_mBIT(3)
+#define VXGE_HW_ROCRC_ALARM_REG_NOA_IMMM_ECC_SG vxge_mBIT(4)
+#define VXGE_HW_ROCRC_ALARM_REG_UDQ_UMQM_ECC_DB vxge_mBIT(5)
+#define VXGE_HW_ROCRC_ALARM_REG_UDQ_UMQM_ECC_SG vxge_mBIT(6)
+#define VXGE_HW_ROCRC_ALARM_REG_NOA_RCBM_ECC_DB vxge_mBIT(11)
+#define VXGE_HW_ROCRC_ALARM_REG_NOA_RCBM_ECC_SG vxge_mBIT(12)
+#define VXGE_HW_ROCRC_ALARM_REG_QCQ_MULTI_EGB_RSVD_ERR vxge_mBIT(13)
+#define VXGE_HW_ROCRC_ALARM_REG_QCQ_MULTI_EGB_OWN_ERR vxge_mBIT(14)
+#define VXGE_HW_ROCRC_ALARM_REG_QCQ_MULTI_BYP_OWN_ERR vxge_mBIT(15)
+#define VXGE_HW_ROCRC_ALARM_REG_QCQ_OWN_NOT_ASSIGNED_ERR vxge_mBIT(16)
+#define VXGE_HW_ROCRC_ALARM_REG_QCQ_OWN_RSVD_SYNC_ERR vxge_mBIT(17)
+#define VXGE_HW_ROCRC_ALARM_REG_QCQ_LOST_EGB_ERR vxge_mBIT(18)
+#define VXGE_HW_ROCRC_ALARM_REG_RCQ_BYPQ0_OVERFLOW vxge_mBIT(19)
+#define VXGE_HW_ROCRC_ALARM_REG_RCQ_BYPQ1_OVERFLOW vxge_mBIT(20)
+#define VXGE_HW_ROCRC_ALARM_REG_RCQ_BYPQ2_OVERFLOW vxge_mBIT(21)
+#define VXGE_HW_ROCRC_ALARM_REG_NOA_WCT_CMD_FIFO_ERR vxge_mBIT(22)
+/*0x00af0*/ u64 rocrc_alarm_mask;
+/*0x00af8*/ u64 rocrc_alarm_alarm;
+/*0x00b00*/ u64 wde0_alarm_reg;
+#define VXGE_HW_WDE0_ALARM_REG_WDE0_DCC_SM_ERR vxge_mBIT(0)
+#define VXGE_HW_WDE0_ALARM_REG_WDE0_PRM_SM_ERR vxge_mBIT(1)
+#define VXGE_HW_WDE0_ALARM_REG_WDE0_CP_SM_ERR vxge_mBIT(2)
+#define VXGE_HW_WDE0_ALARM_REG_WDE0_CP_CMD_ERR vxge_mBIT(3)
+#define VXGE_HW_WDE0_ALARM_REG_WDE0_PCR_SM_ERR vxge_mBIT(4)
+/*0x00b08*/ u64 wde0_alarm_mask;
+/*0x00b10*/ u64 wde0_alarm_alarm;
+/*0x00b18*/ u64 wde1_alarm_reg;
+#define VXGE_HW_WDE1_ALARM_REG_WDE1_DCC_SM_ERR vxge_mBIT(0)
+#define VXGE_HW_WDE1_ALARM_REG_WDE1_PRM_SM_ERR vxge_mBIT(1)
+#define VXGE_HW_WDE1_ALARM_REG_WDE1_CP_SM_ERR vxge_mBIT(2)
+#define VXGE_HW_WDE1_ALARM_REG_WDE1_CP_CMD_ERR vxge_mBIT(3)
+#define VXGE_HW_WDE1_ALARM_REG_WDE1_PCR_SM_ERR vxge_mBIT(4)
+/*0x00b20*/ u64 wde1_alarm_mask;
+/*0x00b28*/ u64 wde1_alarm_alarm;
+/*0x00b30*/ u64 wde2_alarm_reg;
+#define VXGE_HW_WDE2_ALARM_REG_WDE2_DCC_SM_ERR vxge_mBIT(0)
+#define VXGE_HW_WDE2_ALARM_REG_WDE2_PRM_SM_ERR vxge_mBIT(1)
+#define VXGE_HW_WDE2_ALARM_REG_WDE2_CP_SM_ERR vxge_mBIT(2)
+#define VXGE_HW_WDE2_ALARM_REG_WDE2_CP_CMD_ERR vxge_mBIT(3)
+#define VXGE_HW_WDE2_ALARM_REG_WDE2_PCR_SM_ERR vxge_mBIT(4)
+/*0x00b38*/ u64 wde2_alarm_mask;
+/*0x00b40*/ u64 wde2_alarm_alarm;
+/*0x00b48*/ u64 wde3_alarm_reg;
+#define VXGE_HW_WDE3_ALARM_REG_WDE3_DCC_SM_ERR vxge_mBIT(0)
+#define VXGE_HW_WDE3_ALARM_REG_WDE3_PRM_SM_ERR vxge_mBIT(1)
+#define VXGE_HW_WDE3_ALARM_REG_WDE3_CP_SM_ERR vxge_mBIT(2)
+#define VXGE_HW_WDE3_ALARM_REG_WDE3_CP_CMD_ERR vxge_mBIT(3)
+#define VXGE_HW_WDE3_ALARM_REG_WDE3_PCR_SM_ERR vxge_mBIT(4)
+/*0x00b50*/ u64 wde3_alarm_mask;
+/*0x00b58*/ u64 wde3_alarm_alarm;
+
+ u8 unused00be8[0x00be8-0x00b60];
+
+/*0x00be8*/ u64 rx_w_round_robin_0;
+#define VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_0(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_1(val) vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_2(val) vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_3(val) vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_4(val) vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_5(val) vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_6(val) vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_7(val) vxge_vBIT(val, 59, 5)
+/*0x00bf0*/ u64 rx_w_round_robin_1;
+#define VXGE_HW_RX_W_ROUND_ROBIN_1_RX_W_PRIORITY_SS_8(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_1_RX_W_PRIORITY_SS_9(val) vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_1_RX_W_PRIORITY_SS_10(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_1_RX_W_PRIORITY_SS_11(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_1_RX_W_PRIORITY_SS_12(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_1_RX_W_PRIORITY_SS_13(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_1_RX_W_PRIORITY_SS_14(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_1_RX_W_PRIORITY_SS_15(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00bf8*/ u64 rx_w_round_robin_2;
+#define VXGE_HW_RX_W_ROUND_ROBIN_2_RX_W_PRIORITY_SS_16(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_2_RX_W_PRIORITY_SS_17(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_2_RX_W_PRIORITY_SS_18(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_2_RX_W_PRIORITY_SS_19(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_2_RX_W_PRIORITY_SS_20(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_2_RX_W_PRIORITY_SS_21(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_2_RX_W_PRIORITY_SS_22(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_2_RX_W_PRIORITY_SS_23(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c00*/ u64 rx_w_round_robin_3;
+#define VXGE_HW_RX_W_ROUND_ROBIN_3_RX_W_PRIORITY_SS_24(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_3_RX_W_PRIORITY_SS_25(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_3_RX_W_PRIORITY_SS_26(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_3_RX_W_PRIORITY_SS_27(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_3_RX_W_PRIORITY_SS_28(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_3_RX_W_PRIORITY_SS_29(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_3_RX_W_PRIORITY_SS_30(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_3_RX_W_PRIORITY_SS_31(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c08*/ u64 rx_w_round_robin_4;
+#define VXGE_HW_RX_W_ROUND_ROBIN_4_RX_W_PRIORITY_SS_32(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_4_RX_W_PRIORITY_SS_33(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_4_RX_W_PRIORITY_SS_34(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_4_RX_W_PRIORITY_SS_35(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_4_RX_W_PRIORITY_SS_36(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_4_RX_W_PRIORITY_SS_37(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_4_RX_W_PRIORITY_SS_38(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_4_RX_W_PRIORITY_SS_39(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c10*/ u64 rx_w_round_robin_5;
+#define VXGE_HW_RX_W_ROUND_ROBIN_5_RX_W_PRIORITY_SS_40(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_5_RX_W_PRIORITY_SS_41(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_5_RX_W_PRIORITY_SS_42(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_5_RX_W_PRIORITY_SS_43(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_5_RX_W_PRIORITY_SS_44(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_5_RX_W_PRIORITY_SS_45(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_5_RX_W_PRIORITY_SS_46(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_5_RX_W_PRIORITY_SS_47(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c18*/ u64 rx_w_round_robin_6;
+#define VXGE_HW_RX_W_ROUND_ROBIN_6_RX_W_PRIORITY_SS_48(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_6_RX_W_PRIORITY_SS_49(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_6_RX_W_PRIORITY_SS_50(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_6_RX_W_PRIORITY_SS_51(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_6_RX_W_PRIORITY_SS_52(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_6_RX_W_PRIORITY_SS_53(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_6_RX_W_PRIORITY_SS_54(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_6_RX_W_PRIORITY_SS_55(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c20*/ u64 rx_w_round_robin_7;
+#define VXGE_HW_RX_W_ROUND_ROBIN_7_RX_W_PRIORITY_SS_56(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_7_RX_W_PRIORITY_SS_57(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_7_RX_W_PRIORITY_SS_58(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_7_RX_W_PRIORITY_SS_59(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_7_RX_W_PRIORITY_SS_60(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_7_RX_W_PRIORITY_SS_61(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_7_RX_W_PRIORITY_SS_62(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_7_RX_W_PRIORITY_SS_63(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c28*/ u64 rx_w_round_robin_8;
+#define VXGE_HW_RX_W_ROUND_ROBIN_8_RX_W_PRIORITY_SS_64(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_8_RX_W_PRIORITY_SS_65(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_8_RX_W_PRIORITY_SS_66(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_8_RX_W_PRIORITY_SS_67(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_8_RX_W_PRIORITY_SS_68(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_8_RX_W_PRIORITY_SS_69(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_8_RX_W_PRIORITY_SS_70(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_8_RX_W_PRIORITY_SS_71(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c30*/ u64 rx_w_round_robin_9;
+#define VXGE_HW_RX_W_ROUND_ROBIN_9_RX_W_PRIORITY_SS_72(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_9_RX_W_PRIORITY_SS_73(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_9_RX_W_PRIORITY_SS_74(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_9_RX_W_PRIORITY_SS_75(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_9_RX_W_PRIORITY_SS_76(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_9_RX_W_PRIORITY_SS_77(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_9_RX_W_PRIORITY_SS_78(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_9_RX_W_PRIORITY_SS_79(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c38*/ u64 rx_w_round_robin_10;
+#define VXGE_HW_RX_W_ROUND_ROBIN_10_RX_W_PRIORITY_SS_80(val) \
+ vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_10_RX_W_PRIORITY_SS_81(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_10_RX_W_PRIORITY_SS_82(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_10_RX_W_PRIORITY_SS_83(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_10_RX_W_PRIORITY_SS_84(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_10_RX_W_PRIORITY_SS_85(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_10_RX_W_PRIORITY_SS_86(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_10_RX_W_PRIORITY_SS_87(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c40*/ u64 rx_w_round_robin_11;
+#define VXGE_HW_RX_W_ROUND_ROBIN_11_RX_W_PRIORITY_SS_88(val) \
+ vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_11_RX_W_PRIORITY_SS_89(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_11_RX_W_PRIORITY_SS_90(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_11_RX_W_PRIORITY_SS_91(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_11_RX_W_PRIORITY_SS_92(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_11_RX_W_PRIORITY_SS_93(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_11_RX_W_PRIORITY_SS_94(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_11_RX_W_PRIORITY_SS_95(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c48*/ u64 rx_w_round_robin_12;
+#define VXGE_HW_RX_W_ROUND_ROBIN_12_RX_W_PRIORITY_SS_96(val) \
+ vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_12_RX_W_PRIORITY_SS_97(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_12_RX_W_PRIORITY_SS_98(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_12_RX_W_PRIORITY_SS_99(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_12_RX_W_PRIORITY_SS_100(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_12_RX_W_PRIORITY_SS_101(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_12_RX_W_PRIORITY_SS_102(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_12_RX_W_PRIORITY_SS_103(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c50*/ u64 rx_w_round_robin_13;
+#define VXGE_HW_RX_W_ROUND_ROBIN_13_RX_W_PRIORITY_SS_104(val) \
+ vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_13_RX_W_PRIORITY_SS_105(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_13_RX_W_PRIORITY_SS_106(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_13_RX_W_PRIORITY_SS_107(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_13_RX_W_PRIORITY_SS_108(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_13_RX_W_PRIORITY_SS_109(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_13_RX_W_PRIORITY_SS_110(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_13_RX_W_PRIORITY_SS_111(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c58*/ u64 rx_w_round_robin_14;
+#define VXGE_HW_RX_W_ROUND_ROBIN_14_RX_W_PRIORITY_SS_112(val) \
+ vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_14_RX_W_PRIORITY_SS_113(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_14_RX_W_PRIORITY_SS_114(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_14_RX_W_PRIORITY_SS_115(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_14_RX_W_PRIORITY_SS_116(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_14_RX_W_PRIORITY_SS_117(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_14_RX_W_PRIORITY_SS_118(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_14_RX_W_PRIORITY_SS_119(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c60*/ u64 rx_w_round_robin_15;
+#define VXGE_HW_RX_W_ROUND_ROBIN_15_RX_W_PRIORITY_SS_120(val) \
+ vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_15_RX_W_PRIORITY_SS_121(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_15_RX_W_PRIORITY_SS_122(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_15_RX_W_PRIORITY_SS_123(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_15_RX_W_PRIORITY_SS_124(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_15_RX_W_PRIORITY_SS_125(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_15_RX_W_PRIORITY_SS_126(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_15_RX_W_PRIORITY_SS_127(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c68*/ u64 rx_w_round_robin_16;
+#define VXGE_HW_RX_W_ROUND_ROBIN_16_RX_W_PRIORITY_SS_128(val) \
+ vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_16_RX_W_PRIORITY_SS_129(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_16_RX_W_PRIORITY_SS_130(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_16_RX_W_PRIORITY_SS_131(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_16_RX_W_PRIORITY_SS_132(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_16_RX_W_PRIORITY_SS_133(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_16_RX_W_PRIORITY_SS_134(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_16_RX_W_PRIORITY_SS_135(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c70*/ u64 rx_w_round_robin_17;
+#define VXGE_HW_RX_W_ROUND_ROBIN_17_RX_W_PRIORITY_SS_136(val) \
+ vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_17_RX_W_PRIORITY_SS_137(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_17_RX_W_PRIORITY_SS_138(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_17_RX_W_PRIORITY_SS_139(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_17_RX_W_PRIORITY_SS_140(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_17_RX_W_PRIORITY_SS_141(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_17_RX_W_PRIORITY_SS_142(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_17_RX_W_PRIORITY_SS_143(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c78*/ u64 rx_w_round_robin_18;
+#define VXGE_HW_RX_W_ROUND_ROBIN_18_RX_W_PRIORITY_SS_144(val) \
+ vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_18_RX_W_PRIORITY_SS_145(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_18_RX_W_PRIORITY_SS_146(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_18_RX_W_PRIORITY_SS_147(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_18_RX_W_PRIORITY_SS_148(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_18_RX_W_PRIORITY_SS_149(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_18_RX_W_PRIORITY_SS_150(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_18_RX_W_PRIORITY_SS_151(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c80*/ u64 rx_w_round_robin_19;
+#define VXGE_HW_RX_W_ROUND_ROBIN_19_RX_W_PRIORITY_SS_152(val) \
+ vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_19_RX_W_PRIORITY_SS_153(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_19_RX_W_PRIORITY_SS_154(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_19_RX_W_PRIORITY_SS_155(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_19_RX_W_PRIORITY_SS_156(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_19_RX_W_PRIORITY_SS_157(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_19_RX_W_PRIORITY_SS_158(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_19_RX_W_PRIORITY_SS_159(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c88*/ u64 rx_w_round_robin_20;
+#define VXGE_HW_RX_W_ROUND_ROBIN_20_RX_W_PRIORITY_SS_160(val) \
+ vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_20_RX_W_PRIORITY_SS_161(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_20_RX_W_PRIORITY_SS_162(val) \
+ vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_20_RX_W_PRIORITY_SS_163(val) \
+ vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_20_RX_W_PRIORITY_SS_164(val) \
+ vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_20_RX_W_PRIORITY_SS_165(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_20_RX_W_PRIORITY_SS_166(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_20_RX_W_PRIORITY_SS_167(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00c90*/ u64 rx_w_round_robin_21;
+#define VXGE_HW_RX_W_ROUND_ROBIN_21_RX_W_PRIORITY_SS_168(val) \
+ vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_21_RX_W_PRIORITY_SS_169(val) \
+ vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_W_ROUND_ROBIN_21_RX_W_PRIORITY_SS_170(val) \
+ vxge_vBIT(val, 19, 5)
+
+#define VXGE_HW_WRR_RING_SERVICE_STATES 171
+#define VXGE_HW_WRR_RING_COUNT 22
+
+/*0x00c98*/ u64 rx_queue_priority_0;
+#define VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_0(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_1(val) vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_2(val) vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_3(val) vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_4(val) vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_5(val) vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_6(val) vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_7(val) vxge_vBIT(val, 59, 5)
+/*0x00ca0*/ u64 rx_queue_priority_1;
+#define VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_8(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_9(val) vxge_vBIT(val, 11, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_10(val) vxge_vBIT(val, 19, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_11(val) vxge_vBIT(val, 27, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_12(val) vxge_vBIT(val, 35, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_13(val) vxge_vBIT(val, 43, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_14(val) vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_15(val) vxge_vBIT(val, 59, 5)
+/*0x00ca8*/ u64 rx_queue_priority_2;
+#define VXGE_HW_RX_QUEUE_PRIORITY_2_RX_Q_NUMBER_16(val) vxge_vBIT(val, 3, 5)
+ u8 unused00cc8[0x00cc8-0x00cb0];
+
+/*0x00cc8*/ u64 replication_queue_priority;
+#define VXGE_HW_REPLICATION_QUEUE_PRIORITY_REPLICATION_QUEUE_PRIORITY(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00cd0*/ u64 rx_queue_select;
+#define VXGE_HW_RX_QUEUE_SELECT_NUMBER(n) vxge_mBIT(n)
+#define VXGE_HW_RX_QUEUE_SELECT_ENABLE_CODE vxge_mBIT(15)
+#define VXGE_HW_RX_QUEUE_SELECT_ENABLE_HIERARCHICAL_PRTY vxge_mBIT(23)
+/*0x00cd8*/ u64 rqa_vpbp_ctrl;
+#define VXGE_HW_RQA_VPBP_CTRL_WR_XON_DIS vxge_mBIT(15)
+#define VXGE_HW_RQA_VPBP_CTRL_ROCRC_DIS vxge_mBIT(23)
+#define VXGE_HW_RQA_VPBP_CTRL_TXPE_DIS vxge_mBIT(31)
+/*0x00ce0*/ u64 rx_multi_cast_ctrl;
+#define VXGE_HW_RX_MULTI_CAST_CTRL_TIME_OUT_DIS vxge_mBIT(0)
+#define VXGE_HW_RX_MULTI_CAST_CTRL_FRM_DROP_DIS vxge_mBIT(1)
+#define VXGE_HW_RX_MULTI_CAST_CTRL_NO_RXD_TIME_OUT_CNT(val) \
+ vxge_vBIT(val, 2, 30)
+#define VXGE_HW_RX_MULTI_CAST_CTRL_TIME_OUT_CNT(val) vxge_vBIT(val, 32, 32)
+/*0x00ce8*/ u64 wde_prm_ctrl;
+#define VXGE_HW_WDE_PRM_CTRL_SPAV_THRESHOLD(val) vxge_vBIT(val, 2, 10)
+#define VXGE_HW_WDE_PRM_CTRL_SPLIT_THRESHOLD(val) vxge_vBIT(val, 18, 14)
+#define VXGE_HW_WDE_PRM_CTRL_SPLIT_ON_1ST_ROW vxge_mBIT(32)
+#define VXGE_HW_WDE_PRM_CTRL_SPLIT_ON_ROW_BNDRY vxge_mBIT(33)
+#define VXGE_HW_WDE_PRM_CTRL_FB_ROW_SIZE(val) vxge_vBIT(val, 46, 2)
+/*0x00cf0*/ u64 noa_ctrl;
+#define VXGE_HW_NOA_CTRL_FRM_PRTY_QUOTA(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_NOA_CTRL_NON_FRM_PRTY_QUOTA(val) vxge_vBIT(val, 11, 5)
+#define VXGE_HW_NOA_CTRL_IGNORE_KDFC_IF_STATUS vxge_mBIT(16)
+#define VXGE_HW_NOA_CTRL_MAX_JOB_CNT_FOR_WDE0(val) vxge_vBIT(val, 37, 4)
+#define VXGE_HW_NOA_CTRL_MAX_JOB_CNT_FOR_WDE1(val) vxge_vBIT(val, 45, 4)
+#define VXGE_HW_NOA_CTRL_MAX_JOB_CNT_FOR_WDE2(val) vxge_vBIT(val, 53, 4)
+#define VXGE_HW_NOA_CTRL_MAX_JOB_CNT_FOR_WDE3(val) vxge_vBIT(val, 60, 4)
+/*0x00cf8*/ u64 phase_cfg;
+#define VXGE_HW_PHASE_CFG_QCC_WR_PHASE_EN vxge_mBIT(0)
+#define VXGE_HW_PHASE_CFG_QCC_RD_PHASE_EN vxge_mBIT(3)
+#define VXGE_HW_PHASE_CFG_IMMM_WR_PHASE_EN vxge_mBIT(7)
+#define VXGE_HW_PHASE_CFG_IMMM_RD_PHASE_EN vxge_mBIT(11)
+#define VXGE_HW_PHASE_CFG_UMQM_WR_PHASE_EN vxge_mBIT(15)
+#define VXGE_HW_PHASE_CFG_UMQM_RD_PHASE_EN vxge_mBIT(19)
+#define VXGE_HW_PHASE_CFG_RCBM_WR_PHASE_EN vxge_mBIT(23)
+#define VXGE_HW_PHASE_CFG_RCBM_RD_PHASE_EN vxge_mBIT(27)
+#define VXGE_HW_PHASE_CFG_RXD_RC_WR_PHASE_EN vxge_mBIT(31)
+#define VXGE_HW_PHASE_CFG_RXD_RC_RD_PHASE_EN vxge_mBIT(35)
+#define VXGE_HW_PHASE_CFG_RXD_RHS_WR_PHASE_EN vxge_mBIT(39)
+#define VXGE_HW_PHASE_CFG_RXD_RHS_RD_PHASE_EN vxge_mBIT(43)
+/*0x00d00*/ u64 rcq_bypq_cfg;
+#define VXGE_HW_RCQ_BYPQ_CFG_OVERFLOW_THRESHOLD(val) vxge_vBIT(val, 10, 22)
+#define VXGE_HW_RCQ_BYPQ_CFG_BYP_ON_THRESHOLD(val) vxge_vBIT(val, 39, 9)
+#define VXGE_HW_RCQ_BYPQ_CFG_BYP_OFF_THRESHOLD(val) vxge_vBIT(val, 55, 9)
+ u8 unused00e00[0x00e00-0x00d08];
+
+/*0x00e00*/ u64 doorbell_int_status;
+#define VXGE_HW_DOORBELL_INT_STATUS_KDFC_ERR_REG_TXDMA_KDFC_INT vxge_mBIT(7)
+#define VXGE_HW_DOORBELL_INT_STATUS_USDC_ERR_REG_TXDMA_USDC_INT vxge_mBIT(15)
+/*0x00e08*/ u64 doorbell_int_mask;
+/*0x00e10*/ u64 kdfc_err_reg;
+#define VXGE_HW_KDFC_ERR_REG_KDFC_KDFC_ECC_SG_ERR vxge_mBIT(7)
+#define VXGE_HW_KDFC_ERR_REG_KDFC_KDFC_ECC_DB_ERR vxge_mBIT(15)
+#define VXGE_HW_KDFC_ERR_REG_KDFC_KDFC_SM_ERR_ALARM vxge_mBIT(23)
+#define VXGE_HW_KDFC_ERR_REG_KDFC_KDFC_MISC_ERR_1 vxge_mBIT(32)
+#define VXGE_HW_KDFC_ERR_REG_KDFC_KDFC_PCIX_ERR vxge_mBIT(39)
+/*0x00e18*/ u64 kdfc_err_mask;
+/*0x00e20*/ u64 kdfc_err_reg_alarm;
+#define VXGE_HW_KDFC_ERR_REG_ALARM_KDFC_KDFC_ECC_SG_ERR vxge_mBIT(7)
+#define VXGE_HW_KDFC_ERR_REG_ALARM_KDFC_KDFC_ECC_DB_ERR vxge_mBIT(15)
+#define VXGE_HW_KDFC_ERR_REG_ALARM_KDFC_KDFC_SM_ERR_ALARM vxge_mBIT(23)
+#define VXGE_HW_KDFC_ERR_REG_ALARM_KDFC_KDFC_MISC_ERR_1 vxge_mBIT(32)
+#define VXGE_HW_KDFC_ERR_REG_ALARM_KDFC_KDFC_PCIX_ERR vxge_mBIT(39)
+ u8 unused00e40[0x00e40-0x00e28];
+/*0x00e40*/ u64 kdfc_vp_partition_0;
+#define VXGE_HW_KDFC_VP_PARTITION_0_ENABLE vxge_mBIT(0)
+#define VXGE_HW_KDFC_VP_PARTITION_0_NUMBER_0(val) vxge_vBIT(val, 5, 3)
+#define VXGE_HW_KDFC_VP_PARTITION_0_LENGTH_0(val) vxge_vBIT(val, 17, 15)
+#define VXGE_HW_KDFC_VP_PARTITION_0_NUMBER_1(val) vxge_vBIT(val, 37, 3)
+#define VXGE_HW_KDFC_VP_PARTITION_0_LENGTH_1(val) vxge_vBIT(val, 49, 15)
+/*0x00e48*/ u64 kdfc_vp_partition_1;
+#define VXGE_HW_KDFC_VP_PARTITION_1_NUMBER_2(val) vxge_vBIT(val, 5, 3)
+#define VXGE_HW_KDFC_VP_PARTITION_1_LENGTH_2(val) vxge_vBIT(val, 17, 15)
+#define VXGE_HW_KDFC_VP_PARTITION_1_NUMBER_3(val) vxge_vBIT(val, 37, 3)
+#define VXGE_HW_KDFC_VP_PARTITION_1_LENGTH_3(val) vxge_vBIT(val, 49, 15)
+/*0x00e50*/ u64 kdfc_vp_partition_2;
+#define VXGE_HW_KDFC_VP_PARTITION_2_NUMBER_4(val) vxge_vBIT(val, 5, 3)
+#define VXGE_HW_KDFC_VP_PARTITION_2_LENGTH_4(val) vxge_vBIT(val, 17, 15)
+#define VXGE_HW_KDFC_VP_PARTITION_2_NUMBER_5(val) vxge_vBIT(val, 37, 3)
+#define VXGE_HW_KDFC_VP_PARTITION_2_LENGTH_5(val) vxge_vBIT(val, 49, 15)
+/*0x00e58*/ u64 kdfc_vp_partition_3;
+#define VXGE_HW_KDFC_VP_PARTITION_3_NUMBER_6(val) vxge_vBIT(val, 5, 3)
+#define VXGE_HW_KDFC_VP_PARTITION_3_LENGTH_6(val) vxge_vBIT(val, 17, 15)
+#define VXGE_HW_KDFC_VP_PARTITION_3_NUMBER_7(val) vxge_vBIT(val, 37, 3)
+#define VXGE_HW_KDFC_VP_PARTITION_3_LENGTH_7(val) vxge_vBIT(val, 49, 15)
+/*0x00e60*/ u64 kdfc_vp_partition_4;
+#define VXGE_HW_KDFC_VP_PARTITION_4_LENGTH_8(val) vxge_vBIT(val, 17, 15)
+#define VXGE_HW_KDFC_VP_PARTITION_4_LENGTH_9(val) vxge_vBIT(val, 49, 15)
+/*0x00e68*/ u64 kdfc_vp_partition_5;
+#define VXGE_HW_KDFC_VP_PARTITION_5_LENGTH_10(val) vxge_vBIT(val, 17, 15)
+#define VXGE_HW_KDFC_VP_PARTITION_5_LENGTH_11(val) vxge_vBIT(val, 49, 15)
+/*0x00e70*/ u64 kdfc_vp_partition_6;
+#define VXGE_HW_KDFC_VP_PARTITION_6_LENGTH_12(val) vxge_vBIT(val, 17, 15)
+#define VXGE_HW_KDFC_VP_PARTITION_6_LENGTH_13(val) vxge_vBIT(val, 49, 15)
+/*0x00e78*/ u64 kdfc_vp_partition_7;
+#define VXGE_HW_KDFC_VP_PARTITION_7_LENGTH_14(val) vxge_vBIT(val, 17, 15)
+#define VXGE_HW_KDFC_VP_PARTITION_7_LENGTH_15(val) vxge_vBIT(val, 49, 15)
+/*0x00e80*/ u64 kdfc_vp_partition_8;
+#define VXGE_HW_KDFC_VP_PARTITION_8_LENGTH_16(val) vxge_vBIT(val, 17, 15)
+/*0x00e88*/ u64 kdfc_w_round_robin_0;
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_0(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_1(val) vxge_vBIT(val, 11, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_2(val) vxge_vBIT(val, 19, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_3(val) vxge_vBIT(val, 27, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_4(val) vxge_vBIT(val, 35, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_5(val) vxge_vBIT(val, 43, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_6(val) vxge_vBIT(val, 51, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_7(val) vxge_vBIT(val, 59, 5)
+
+ u8 unused0f28[0x0f28-0x0e90];
+
+/*0x00f28*/ u64 kdfc_w_round_robin_20;
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_20_NUMBER_0(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_20_NUMBER_1(val) vxge_vBIT(val, 11, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_20_NUMBER_2(val) vxge_vBIT(val, 19, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_20_NUMBER_3(val) vxge_vBIT(val, 27, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_20_NUMBER_4(val) vxge_vBIT(val, 35, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_20_NUMBER_5(val) vxge_vBIT(val, 43, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_20_NUMBER_6(val) vxge_vBIT(val, 51, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_20_NUMBER_7(val) vxge_vBIT(val, 59, 5)
+
+#define VXGE_HW_WRR_FIFO_COUNT 20
+
+ u8 unused0fc8[0x0fc8-0x0f30];
+
+/*0x00fc8*/ u64 kdfc_w_round_robin_40;
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_40_NUMBER_0(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_40_NUMBER_1(val) vxge_vBIT(val, 11, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_40_NUMBER_2(val) vxge_vBIT(val, 19, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_40_NUMBER_3(val) vxge_vBIT(val, 27, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_40_NUMBER_4(val) vxge_vBIT(val, 35, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_40_NUMBER_5(val) vxge_vBIT(val, 43, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_40_NUMBER_6(val) vxge_vBIT(val, 51, 5)
+#define VXGE_HW_KDFC_W_ROUND_ROBIN_40_NUMBER_7(val) vxge_vBIT(val, 59, 5)
+
+ u8 unused1068[0x01068-0x0fd0];
+
+/*0x01068*/ u64 kdfc_entry_type_sel_0;
+#define VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_0(val) vxge_vBIT(val, 6, 2)
+#define VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_1(val) vxge_vBIT(val, 14, 2)
+#define VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_2(val) vxge_vBIT(val, 22, 2)
+#define VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_3(val) vxge_vBIT(val, 30, 2)
+#define VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_4(val) vxge_vBIT(val, 38, 2)
+#define VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_5(val) vxge_vBIT(val, 46, 2)
+#define VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_6(val) vxge_vBIT(val, 54, 2)
+#define VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_7(val) vxge_vBIT(val, 62, 2)
+/*0x01070*/ u64 kdfc_entry_type_sel_1;
+#define VXGE_HW_KDFC_ENTRY_TYPE_SEL_1_NUMBER_8(val) vxge_vBIT(val, 6, 2)
+/*0x01078*/ u64 kdfc_fifo_0_ctrl;
+#define VXGE_HW_KDFC_FIFO_0_CTRL_WRR_NUMBER(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_WEIGHTED_RR_SERVICE_STATES 176
+#define VXGE_HW_WRR_FIFO_SERVICE_STATES 153
+
+ u8 unused1100[0x01100-0x1080];
+
+/*0x01100*/ u64 kdfc_fifo_17_ctrl;
+#define VXGE_HW_KDFC_FIFO_17_CTRL_WRR_NUMBER(val) vxge_vBIT(val, 3, 5)
+
+ u8 unused1600[0x01600-0x1108];
+
+/*0x01600*/ u64 rxmac_int_status;
+#define VXGE_HW_RXMAC_INT_STATUS_RXMAC_GEN_ERR_RXMAC_GEN_INT vxge_mBIT(3)
+#define VXGE_HW_RXMAC_INT_STATUS_RXMAC_ECC_ERR_RXMAC_ECC_INT vxge_mBIT(7)
+#define VXGE_HW_RXMAC_INT_STATUS_RXMAC_VARIOUS_ERR_RXMAC_VARIOUS_INT \
+ vxge_mBIT(11)
+/*0x01608*/ u64 rxmac_int_mask;
+ u8 unused01618[0x01618-0x01610];
+
+/*0x01618*/ u64 rxmac_gen_err_reg;
+/*0x01620*/ u64 rxmac_gen_err_mask;
+/*0x01628*/ u64 rxmac_gen_err_alarm;
+/*0x01630*/ u64 rxmac_ecc_err_reg;
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RMAC_PORT0_RMAC_RTS_PART_SG_ERR(val) \
+ vxge_vBIT(val, 0, 4)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RMAC_PORT0_RMAC_RTS_PART_DB_ERR(val) \
+ vxge_vBIT(val, 4, 4)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RMAC_PORT1_RMAC_RTS_PART_SG_ERR(val) \
+ vxge_vBIT(val, 8, 4)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RMAC_PORT1_RMAC_RTS_PART_DB_ERR(val) \
+ vxge_vBIT(val, 12, 4)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RMAC_PORT2_RMAC_RTS_PART_SG_ERR(val) \
+ vxge_vBIT(val, 16, 4)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RMAC_PORT2_RMAC_RTS_PART_DB_ERR(val) \
+ vxge_vBIT(val, 20, 4)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_DA_LKP_PRT0_SG_ERR(val) \
+ vxge_vBIT(val, 24, 2)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_DA_LKP_PRT0_DB_ERR(val) \
+ vxge_vBIT(val, 26, 2)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_DA_LKP_PRT1_SG_ERR(val) \
+ vxge_vBIT(val, 28, 2)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_DA_LKP_PRT1_DB_ERR(val) \
+ vxge_vBIT(val, 30, 2)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_VID_LKP_SG_ERR vxge_mBIT(32)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_VID_LKP_DB_ERR vxge_mBIT(33)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_PN_LKP_PRT0_SG_ERR vxge_mBIT(34)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_PN_LKP_PRT0_DB_ERR vxge_mBIT(35)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_PN_LKP_PRT1_SG_ERR vxge_mBIT(36)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_PN_LKP_PRT1_DB_ERR vxge_mBIT(37)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_PN_LKP_PRT2_SG_ERR vxge_mBIT(38)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_PN_LKP_PRT2_DB_ERR vxge_mBIT(39)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_RTH_MASK_SG_ERR(val) \
+ vxge_vBIT(val, 40, 7)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_RTH_MASK_DB_ERR(val) \
+ vxge_vBIT(val, 47, 7)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_RTH_LKP_SG_ERR(val) \
+ vxge_vBIT(val, 54, 3)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_RTH_LKP_DB_ERR(val) \
+ vxge_vBIT(val, 57, 3)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_DS_LKP_SG_ERR \
+ vxge_mBIT(60)
+#define VXGE_HW_RXMAC_ECC_ERR_REG_RTSJ_RMAC_DS_LKP_DB_ERR \
+ vxge_mBIT(61)
+/*0x01638*/ u64 rxmac_ecc_err_mask;
+/*0x01640*/ u64 rxmac_ecc_err_alarm;
+/*0x01648*/ u64 rxmac_various_err_reg;
+#define VXGE_HW_RXMAC_VARIOUS_ERR_REG_RMAC_RMAC_PORT0_FSM_ERR vxge_mBIT(0)
+#define VXGE_HW_RXMAC_VARIOUS_ERR_REG_RMAC_RMAC_PORT1_FSM_ERR vxge_mBIT(1)
+#define VXGE_HW_RXMAC_VARIOUS_ERR_REG_RMAC_RMAC_PORT2_FSM_ERR vxge_mBIT(2)
+#define VXGE_HW_RXMAC_VARIOUS_ERR_REG_RMACJ_RMACJ_FSM_ERR vxge_mBIT(3)
+/*0x01650*/ u64 rxmac_various_err_mask;
+/*0x01658*/ u64 rxmac_various_err_alarm;
+/*0x01660*/ u64 rxmac_gen_cfg;
+#define VXGE_HW_RXMAC_GEN_CFG_SCALE_RMAC_UTIL vxge_mBIT(11)
+/*0x01668*/ u64 rxmac_authorize_all_addr;
+#define VXGE_HW_RXMAC_AUTHORIZE_ALL_ADDR_VP(n) vxge_mBIT(n)
+/*0x01670*/ u64 rxmac_authorize_all_vid;
+#define VXGE_HW_RXMAC_AUTHORIZE_ALL_VID_VP(n) vxge_mBIT(n)
+ u8 unused016c0[0x016c0-0x01678];
+
+/*0x016c0*/ u64 rxmac_red_rate_repl_queue;
+#define VXGE_HW_RXMAC_RED_RATE_REPL_QUEUE_CRATE_THR0(val) vxge_vBIT(val, 0, 4)
+#define VXGE_HW_RXMAC_RED_RATE_REPL_QUEUE_CRATE_THR1(val) vxge_vBIT(val, 4, 4)
+#define VXGE_HW_RXMAC_RED_RATE_REPL_QUEUE_CRATE_THR2(val) vxge_vBIT(val, 8, 4)
+#define VXGE_HW_RXMAC_RED_RATE_REPL_QUEUE_CRATE_THR3(val) vxge_vBIT(val, 12, 4)
+#define VXGE_HW_RXMAC_RED_RATE_REPL_QUEUE_FRATE_THR0(val) vxge_vBIT(val, 16, 4)
+#define VXGE_HW_RXMAC_RED_RATE_REPL_QUEUE_FRATE_THR1(val) vxge_vBIT(val, 20, 4)
+#define VXGE_HW_RXMAC_RED_RATE_REPL_QUEUE_FRATE_THR2(val) vxge_vBIT(val, 24, 4)
+#define VXGE_HW_RXMAC_RED_RATE_REPL_QUEUE_FRATE_THR3(val) vxge_vBIT(val, 28, 4)
+#define VXGE_HW_RXMAC_RED_RATE_REPL_QUEUE_TRICKLE_EN vxge_mBIT(35)
+ u8 unused016e0[0x016e0-0x016c8];
+
+/*0x016e0*/ u64 rxmac_cfg0_port[3];
+#define VXGE_HW_RXMAC_CFG0_PORT_RMAC_EN vxge_mBIT(3)
+#define VXGE_HW_RXMAC_CFG0_PORT_STRIP_FCS vxge_mBIT(7)
+#define VXGE_HW_RXMAC_CFG0_PORT_DISCARD_PFRM vxge_mBIT(11)
+#define VXGE_HW_RXMAC_CFG0_PORT_IGNORE_FCS_ERR vxge_mBIT(15)
+#define VXGE_HW_RXMAC_CFG0_PORT_IGNORE_LONG_ERR vxge_mBIT(19)
+#define VXGE_HW_RXMAC_CFG0_PORT_IGNORE_USIZED_ERR vxge_mBIT(23)
+#define VXGE_HW_RXMAC_CFG0_PORT_IGNORE_LEN_MISMATCH vxge_mBIT(27)
+#define VXGE_HW_RXMAC_CFG0_PORT_MAX_PYLD_LEN(val) vxge_vBIT(val, 50, 14)
+ u8 unused01710[0x01710-0x016f8];
+
+/*0x01710*/ u64 rxmac_cfg2_port[3];
+#define VXGE_HW_RXMAC_CFG2_PORT_PROM_EN vxge_mBIT(3)
+/*0x01728*/ u64 rxmac_pause_cfg_port[3];
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_GEN_EN vxge_mBIT(3)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_RCV_EN vxge_mBIT(7)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_ACCEL_SEND(val) vxge_vBIT(val, 9, 3)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_DUAL_THR vxge_mBIT(15)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_HIGH_PTIME(val) vxge_vBIT(val, 20, 16)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_IGNORE_PF_FCS_ERR vxge_mBIT(39)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_IGNORE_PF_LEN_ERR vxge_mBIT(43)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_LIMITER_EN vxge_mBIT(47)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_MAX_LIMIT(val) vxge_vBIT(val, 48, 8)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_PERMIT_RATEMGMT_CTRL vxge_mBIT(59)
+ u8 unused01758[0x01758-0x01740];
+
+/*0x01758*/ u64 rxmac_red_cfg0_port[3];
+#define VXGE_HW_RXMAC_RED_CFG0_PORT_RED_EN_VP(n) vxge_mBIT(n)
+/*0x01770*/ u64 rxmac_red_cfg1_port[3];
+#define VXGE_HW_RXMAC_RED_CFG1_PORT_FINE_EN vxge_mBIT(3)
+#define VXGE_HW_RXMAC_RED_CFG1_PORT_RED_EN_REPL_QUEUE vxge_mBIT(11)
+/*0x01788*/ u64 rxmac_red_cfg2_port[3];
+#define VXGE_HW_RXMAC_RED_CFG2_PORT_TRICKLE_EN_VP(n) vxge_mBIT(n)
+/*0x017a0*/ u64 rxmac_link_util_port[3];
+#define VXGE_HW_RXMAC_LINK_UTIL_PORT_RMAC_RMAC_UTILIZATION(val) \
+ vxge_vBIT(val, 1, 7)
+#define VXGE_HW_RXMAC_LINK_UTIL_PORT_RMAC_UTIL_CFG(val) vxge_vBIT(val, 8, 4)
+#define VXGE_HW_RXMAC_LINK_UTIL_PORT_RMAC_RMAC_FRAC_UTIL(val) \
+ vxge_vBIT(val, 12, 4)
+#define VXGE_HW_RXMAC_LINK_UTIL_PORT_RMAC_PKT_WEIGHT(val) vxge_vBIT(val, 16, 4)
+#define VXGE_HW_RXMAC_LINK_UTIL_PORT_RMAC_RMAC_SCALE_FACTOR vxge_mBIT(23)
+ u8 unused017d0[0x017d0-0x017b8];
+
+/*0x017d0*/ u64 rxmac_status_port[3];
+#define VXGE_HW_RXMAC_STATUS_PORT_RMAC_RX_FRM_RCVD vxge_mBIT(3)
+ u8 unused01800[0x01800-0x017e8];
+
+/*0x01800*/ u64 rxmac_rx_pa_cfg0;
+#define VXGE_HW_RXMAC_RX_PA_CFG0_IGNORE_FRAME_ERR vxge_mBIT(3)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_SUPPORT_SNAP_AB_N vxge_mBIT(7)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_SEARCH_FOR_HAO vxge_mBIT(18)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_SUPPORT_MOBILE_IPV6_HDRS vxge_mBIT(19)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_IPV6_STOP_SEARCHING vxge_mBIT(23)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_NO_PS_IF_UNKNOWN vxge_mBIT(27)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_SEARCH_FOR_ETYPE vxge_mBIT(35)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_TOSS_ANY_FRM_IF_L3_CSUM_ERR vxge_mBIT(39)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_TOSS_OFFLD_FRM_IF_L3_CSUM_ERR vxge_mBIT(43)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_TOSS_ANY_FRM_IF_L4_CSUM_ERR vxge_mBIT(47)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_TOSS_OFFLD_FRM_IF_L4_CSUM_ERR vxge_mBIT(51)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_TOSS_ANY_FRM_IF_RPA_ERR vxge_mBIT(55)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_TOSS_OFFLD_FRM_IF_RPA_ERR vxge_mBIT(59)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_JUMBO_SNAP_EN vxge_mBIT(63)
+/*0x01808*/ u64 rxmac_rx_pa_cfg1;
+#define VXGE_HW_RXMAC_RX_PA_CFG1_REPL_IPV4_TCP_INCL_PH vxge_mBIT(3)
+#define VXGE_HW_RXMAC_RX_PA_CFG1_REPL_IPV6_TCP_INCL_PH vxge_mBIT(7)
+#define VXGE_HW_RXMAC_RX_PA_CFG1_REPL_IPV4_UDP_INCL_PH vxge_mBIT(11)
+#define VXGE_HW_RXMAC_RX_PA_CFG1_REPL_IPV6_UDP_INCL_PH vxge_mBIT(15)
+#define VXGE_HW_RXMAC_RX_PA_CFG1_REPL_L4_INCL_CF vxge_mBIT(19)
+#define VXGE_HW_RXMAC_RX_PA_CFG1_REPL_STRIP_VLAN_TAG vxge_mBIT(23)
+ u8 unused01828[0x01828-0x01810];
+
+/*0x01828*/ u64 rts_mgr_cfg0;
+#define VXGE_HW_RTS_MGR_CFG0_RTS_DP_SP_PRIORITY vxge_mBIT(3)
+#define VXGE_HW_RTS_MGR_CFG0_FLEX_L4PRTCL_VALUE(val) vxge_vBIT(val, 24, 8)
+#define VXGE_HW_RTS_MGR_CFG0_ICMP_TRASH vxge_mBIT(35)
+#define VXGE_HW_RTS_MGR_CFG0_TCPSYN_TRASH vxge_mBIT(39)
+#define VXGE_HW_RTS_MGR_CFG0_ZL4PYLD_TRASH vxge_mBIT(43)
+#define VXGE_HW_RTS_MGR_CFG0_L4PRTCL_TCP_TRASH vxge_mBIT(47)
+#define VXGE_HW_RTS_MGR_CFG0_L4PRTCL_UDP_TRASH vxge_mBIT(51)
+#define VXGE_HW_RTS_MGR_CFG0_L4PRTCL_FLEX_TRASH vxge_mBIT(55)
+#define VXGE_HW_RTS_MGR_CFG0_IPFRAG_TRASH vxge_mBIT(59)
+/*0x01830*/ u64 rts_mgr_cfg1;
+#define VXGE_HW_RTS_MGR_CFG1_DA_ACTIVE_TABLE vxge_mBIT(3)
+#define VXGE_HW_RTS_MGR_CFG1_PN_ACTIVE_TABLE vxge_mBIT(7)
+/*0x01838*/ u64 rts_mgr_criteria_priority;
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_ETYPE(val) vxge_vBIT(val, 5, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_ICMP_TCPSYN(val) vxge_vBIT(val, 9, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_L4PN(val) vxge_vBIT(val, 13, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_RANGE_L4PN(val) vxge_vBIT(val, 17, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_RTH_IT(val) vxge_vBIT(val, 21, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_DS(val) vxge_vBIT(val, 25, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_QOS(val) vxge_vBIT(val, 29, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_ZL4PYLD(val) vxge_vBIT(val, 33, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_L4PRTCL(val) vxge_vBIT(val, 37, 3)
+/*0x01840*/ u64 rts_mgr_da_pause_cfg;
+#define VXGE_HW_RTS_MGR_DA_PAUSE_CFG_VPATH_VECTOR(val) vxge_vBIT(val, 0, 17)
+/*0x01848*/ u64 rts_mgr_da_slow_proto_cfg;
+#define VXGE_HW_RTS_MGR_DA_SLOW_PROTO_CFG_VPATH_VECTOR(val) \
+ vxge_vBIT(val, 0, 17)
+ u8 unused01890[0x01890-0x01850];
+/*0x01890*/ u64 rts_mgr_cbasin_cfg;
+ u8 unused01968[0x01968-0x01898];
+
+/*0x01968*/ u64 dbg_stat_rx_any_frms;
+#define VXGE_HW_DBG_STAT_RX_ANY_FRMS_PORT0_RX_ANY_FRMS(val) vxge_vBIT(val, 0, 8)
+#define VXGE_HW_DBG_STAT_RX_ANY_FRMS_PORT1_RX_ANY_FRMS(val) vxge_vBIT(val, 8, 8)
+#define VXGE_HW_DBG_STAT_RX_ANY_FRMS_PORT2_RX_ANY_FRMS(val) \
+ vxge_vBIT(val, 16, 8)
+ u8 unused01a00[0x01a00-0x01970];
+
+/*0x01a00*/ u64 rxmac_red_rate_vp[17];
+#define VXGE_HW_RXMAC_RED_RATE_VP_CRATE_THR0(val) vxge_vBIT(val, 0, 4)
+#define VXGE_HW_RXMAC_RED_RATE_VP_CRATE_THR1(val) vxge_vBIT(val, 4, 4)
+#define VXGE_HW_RXMAC_RED_RATE_VP_CRATE_THR2(val) vxge_vBIT(val, 8, 4)
+#define VXGE_HW_RXMAC_RED_RATE_VP_CRATE_THR3(val) vxge_vBIT(val, 12, 4)
+#define VXGE_HW_RXMAC_RED_RATE_VP_FRATE_THR0(val) vxge_vBIT(val, 16, 4)
+#define VXGE_HW_RXMAC_RED_RATE_VP_FRATE_THR1(val) vxge_vBIT(val, 20, 4)
+#define VXGE_HW_RXMAC_RED_RATE_VP_FRATE_THR2(val) vxge_vBIT(val, 24, 4)
+#define VXGE_HW_RXMAC_RED_RATE_VP_FRATE_THR3(val) vxge_vBIT(val, 28, 4)
+ u8 unused01e00[0x01e00-0x01a88];
+
+/*0x01e00*/ u64 xgmac_int_status;
+#define VXGE_HW_XGMAC_INT_STATUS_XMAC_GEN_ERR_XMAC_GEN_INT vxge_mBIT(3)
+#define VXGE_HW_XGMAC_INT_STATUS_XMAC_LINK_ERR_PORT0_XMAC_LINK_INT_PORT0 \
+ vxge_mBIT(7)
+#define VXGE_HW_XGMAC_INT_STATUS_XMAC_LINK_ERR_PORT1_XMAC_LINK_INT_PORT1 \
+ vxge_mBIT(11)
+#define VXGE_HW_XGMAC_INT_STATUS_XGXS_GEN_ERR_XGXS_GEN_INT vxge_mBIT(15)
+#define VXGE_HW_XGMAC_INT_STATUS_ASIC_NTWK_ERR_ASIC_NTWK_INT vxge_mBIT(19)
+#define VXGE_HW_XGMAC_INT_STATUS_ASIC_GPIO_ERR_ASIC_GPIO_INT vxge_mBIT(23)
+/*0x01e08*/ u64 xgmac_int_mask;
+/*0x01e10*/ u64 xmac_gen_err_reg;
+#define VXGE_HW_XMAC_GEN_ERR_REG_LAGC_LAG_PORT0_ACTOR_CHURN_DETECTED \
+ vxge_mBIT(7)
+#define VXGE_HW_XMAC_GEN_ERR_REG_LAGC_LAG_PORT0_PARTNER_CHURN_DETECTED \
+ vxge_mBIT(11)
+#define VXGE_HW_XMAC_GEN_ERR_REG_LAGC_LAG_PORT0_RECEIVED_LACPDU vxge_mBIT(15)
+#define VXGE_HW_XMAC_GEN_ERR_REG_LAGC_LAG_PORT1_ACTOR_CHURN_DETECTED \
+ vxge_mBIT(19)
+#define VXGE_HW_XMAC_GEN_ERR_REG_LAGC_LAG_PORT1_PARTNER_CHURN_DETECTED \
+ vxge_mBIT(23)
+#define VXGE_HW_XMAC_GEN_ERR_REG_LAGC_LAG_PORT1_RECEIVED_LACPDU vxge_mBIT(27)
+#define VXGE_HW_XMAC_GEN_ERR_REG_XLCM_LAG_FAILOVER_DETECTED vxge_mBIT(31)
+#define VXGE_HW_XMAC_GEN_ERR_REG_XSTATS_RMAC_STATS_TILE0_SG_ERR(val) \
+ vxge_vBIT(val, 40, 2)
+#define VXGE_HW_XMAC_GEN_ERR_REG_XSTATS_RMAC_STATS_TILE0_DB_ERR(val) \
+ vxge_vBIT(val, 42, 2)
+#define VXGE_HW_XMAC_GEN_ERR_REG_XSTATS_RMAC_STATS_TILE1_SG_ERR(val) \
+ vxge_vBIT(val, 44, 2)
+#define VXGE_HW_XMAC_GEN_ERR_REG_XSTATS_RMAC_STATS_TILE1_DB_ERR(val) \
+ vxge_vBIT(val, 46, 2)
+#define VXGE_HW_XMAC_GEN_ERR_REG_XSTATS_RMAC_STATS_TILE2_SG_ERR(val) \
+ vxge_vBIT(val, 48, 2)
+#define VXGE_HW_XMAC_GEN_ERR_REG_XSTATS_RMAC_STATS_TILE2_DB_ERR(val) \
+ vxge_vBIT(val, 50, 2)
+#define VXGE_HW_XMAC_GEN_ERR_REG_XSTATS_RMAC_STATS_TILE3_SG_ERR(val) \
+ vxge_vBIT(val, 52, 2)
+#define VXGE_HW_XMAC_GEN_ERR_REG_XSTATS_RMAC_STATS_TILE3_DB_ERR(val) \
+ vxge_vBIT(val, 54, 2)
+#define VXGE_HW_XMAC_GEN_ERR_REG_XSTATS_RMAC_STATS_TILE4_SG_ERR(val) \
+ vxge_vBIT(val, 56, 2)
+#define VXGE_HW_XMAC_GEN_ERR_REG_XSTATS_RMAC_STATS_TILE4_DB_ERR(val) \
+ vxge_vBIT(val, 58, 2)
+#define VXGE_HW_XMAC_GEN_ERR_REG_XMACJ_XMAC_FSM_ERR vxge_mBIT(63)
+/*0x01e18*/ u64 xmac_gen_err_mask;
+/*0x01e20*/ u64 xmac_gen_err_alarm;
+/*0x01e28*/ u64 xmac_link_err_port0_reg;
+#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_PORT_DOWN vxge_mBIT(3)
+#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_PORT_UP vxge_mBIT(7)
+#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_PORT_WENT_DOWN vxge_mBIT(11)
+#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_PORT_WENT_UP vxge_mBIT(15)
+#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_PORT_REAFFIRMED_FAULT \
+ vxge_mBIT(19)
+#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_PORT_REAFFIRMED_OK vxge_mBIT(23)
+#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_LINK_DOWN vxge_mBIT(27)
+#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_LINK_UP vxge_mBIT(31)
+#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_RATEMGMT_RATE_CHANGE vxge_mBIT(35)
+#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_RATEMGMT_LASI_INV vxge_mBIT(39)
+#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMDIO_MDIO_MGR_ACCESS_COMPLETE \
+ vxge_mBIT(47)
+/*0x01e30*/ u64 xmac_link_err_port0_mask;
+/*0x01e38*/ u64 xmac_link_err_port0_alarm;
+/*0x01e40*/ u64 xmac_link_err_port1_reg;
+/*0x01e48*/ u64 xmac_link_err_port1_mask;
+/*0x01e50*/ u64 xmac_link_err_port1_alarm;
+/*0x01e58*/ u64 xgxs_gen_err_reg;
+#define VXGE_HW_XGXS_GEN_ERR_REG_XGXS_XGXS_FSM_ERR vxge_mBIT(63)
+/*0x01e60*/ u64 xgxs_gen_err_mask;
+/*0x01e68*/ u64 xgxs_gen_err_alarm;
+/*0x01e70*/ u64 asic_ntwk_err_reg;
+#define VXGE_HW_ASIC_NTWK_ERR_REG_XMACJ_NTWK_DOWN vxge_mBIT(3)
+#define VXGE_HW_ASIC_NTWK_ERR_REG_XMACJ_NTWK_UP vxge_mBIT(7)
+#define VXGE_HW_ASIC_NTWK_ERR_REG_XMACJ_NTWK_WENT_DOWN vxge_mBIT(11)
+#define VXGE_HW_ASIC_NTWK_ERR_REG_XMACJ_NTWK_WENT_UP vxge_mBIT(15)
+#define VXGE_HW_ASIC_NTWK_ERR_REG_XMACJ_NTWK_REAFFIRMED_FAULT vxge_mBIT(19)
+#define VXGE_HW_ASIC_NTWK_ERR_REG_XMACJ_NTWK_REAFFIRMED_OK vxge_mBIT(23)
+/*0x01e78*/ u64 asic_ntwk_err_mask;
+/*0x01e80*/ u64 asic_ntwk_err_alarm;
+/*0x01e88*/ u64 asic_gpio_err_reg;
+#define VXGE_HW_ASIC_GPIO_ERR_REG_XMACJ_GPIO_INT(n) vxge_mBIT(n)
+/*0x01e90*/ u64 asic_gpio_err_mask;
+/*0x01e98*/ u64 asic_gpio_err_alarm;
+/*0x01ea0*/ u64 xgmac_gen_status;
+#define VXGE_HW_XGMAC_GEN_STATUS_XMACJ_NTWK_OK vxge_mBIT(3)
+#define VXGE_HW_XGMAC_GEN_STATUS_XMACJ_NTWK_DATA_RATE vxge_mBIT(11)
+/*0x01ea8*/ u64 xgmac_gen_fw_memo_status;
+#define VXGE_HW_XGMAC_GEN_FW_MEMO_STATUS_XMACJ_EVENTS_PENDING(val) \
+ vxge_vBIT(val, 0, 17)
+/*0x01eb0*/ u64 xgmac_gen_fw_memo_mask;
+#define VXGE_HW_XGMAC_GEN_FW_MEMO_MASK_MASK(val) vxge_vBIT(val, 0, 64)
+/*0x01eb8*/ u64 xgmac_gen_fw_vpath_to_vsport_status;
+#define VXGE_HW_XGMAC_GEN_FW_VPATH_TO_VSPORT_STATUS_XMACJ_EVENTS_PENDING(val) \
+ vxge_vBIT(val, 0, 17)
+/*0x01ec0*/ u64 xgmac_main_cfg_port[2];
+#define VXGE_HW_XGMAC_MAIN_CFG_PORT_PORT_EN vxge_mBIT(3)
+ u8 unused01f40[0x01f40-0x01ed0];
+
+/*0x01f40*/ u64 xmac_gen_cfg;
+#define VXGE_HW_XMAC_GEN_CFG_RATEMGMT_MAC_RATE_SEL(val) vxge_vBIT(val, 2, 2)
+#define VXGE_HW_XMAC_GEN_CFG_TX_HEAD_DROP_WHEN_FAULT vxge_mBIT(7)
+#define VXGE_HW_XMAC_GEN_CFG_FAULT_BEHAVIOUR vxge_mBIT(27)
+#define VXGE_HW_XMAC_GEN_CFG_PERIOD_NTWK_UP(val) vxge_vBIT(val, 28, 4)
+#define VXGE_HW_XMAC_GEN_CFG_PERIOD_NTWK_DOWN(val) vxge_vBIT(val, 32, 4)
+/*0x01f48*/ u64 xmac_timestamp;
+#define VXGE_HW_XMAC_TIMESTAMP_EN vxge_mBIT(3)
+#define VXGE_HW_XMAC_TIMESTAMP_USE_LINK_ID(val) vxge_vBIT(val, 6, 2)
+#define VXGE_HW_XMAC_TIMESTAMP_INTERVAL(val) vxge_vBIT(val, 12, 4)
+#define VXGE_HW_XMAC_TIMESTAMP_TIMER_RESTART vxge_mBIT(19)
+#define VXGE_HW_XMAC_TIMESTAMP_XMACJ_ROLLOVER_CNT(val) vxge_vBIT(val, 32, 16)
+/*0x01f50*/ u64 xmac_stats_gen_cfg;
+#define VXGE_HW_XMAC_STATS_GEN_CFG_PRTAGGR_CUM_TIMER(val) vxge_vBIT(val, 4, 4)
+#define VXGE_HW_XMAC_STATS_GEN_CFG_VPATH_CUM_TIMER(val) vxge_vBIT(val, 8, 4)
+#define VXGE_HW_XMAC_STATS_GEN_CFG_VLAN_HANDLING vxge_mBIT(15)
+/*0x01f58*/ u64 xmac_stats_sys_cmd;
+#define VXGE_HW_XMAC_STATS_SYS_CMD_OP(val) vxge_vBIT(val, 5, 3)
+#define VXGE_HW_XMAC_STATS_SYS_CMD_STROBE vxge_mBIT(15)
+#define VXGE_HW_XMAC_STATS_SYS_CMD_LOC_SEL(val) vxge_vBIT(val, 27, 5)
+#define VXGE_HW_XMAC_STATS_SYS_CMD_OFFSET_SEL(val) vxge_vBIT(val, 32, 8)
+/*0x01f60*/ u64 xmac_stats_sys_data;
+#define VXGE_HW_XMAC_STATS_SYS_DATA_XSMGR_DATA(val) vxge_vBIT(val, 0, 64)
+ u8 unused01f80[0x01f80-0x01f68];
+
+/*0x01f80*/ u64 asic_ntwk_ctrl;
+#define VXGE_HW_ASIC_NTWK_CTRL_REQ_TEST_NTWK vxge_mBIT(3)
+#define VXGE_HW_ASIC_NTWK_CTRL_PORT0_REQ_TEST_PORT vxge_mBIT(11)
+#define VXGE_HW_ASIC_NTWK_CTRL_PORT1_REQ_TEST_PORT vxge_mBIT(15)
+/*0x01f88*/ u64 asic_ntwk_cfg_show_port_info;
+#define VXGE_HW_ASIC_NTWK_CFG_SHOW_PORT_INFO_VP(n) vxge_mBIT(n)
+/*0x01f90*/ u64 asic_ntwk_cfg_port_num;
+#define VXGE_HW_ASIC_NTWK_CFG_PORT_NUM_VP(n) vxge_mBIT(n)
+/*0x01f98*/ u64 xmac_cfg_port[3];
+#define VXGE_HW_XMAC_CFG_PORT_XGMII_LOOPBACK vxge_mBIT(3)
+#define VXGE_HW_XMAC_CFG_PORT_XGMII_REVERSE_LOOPBACK vxge_mBIT(7)
+#define VXGE_HW_XMAC_CFG_PORT_XGMII_TX_BEHAV vxge_mBIT(11)
+#define VXGE_HW_XMAC_CFG_PORT_XGMII_RX_BEHAV vxge_mBIT(15)
+/*0x01fb0*/ u64 xmac_station_addr_port[2];
+#define VXGE_HW_XMAC_STATION_ADDR_PORT_MAC_ADDR(val) vxge_vBIT(val, 0, 48)
+ u8 unused02020[0x02020-0x01fc0];
+
+/*0x02020*/ u64 lag_cfg;
+#define VXGE_HW_LAG_CFG_EN vxge_mBIT(3)
+#define VXGE_HW_LAG_CFG_MODE(val) vxge_vBIT(val, 6, 2)
+#define VXGE_HW_LAG_CFG_TX_DISCARD_BEHAV vxge_mBIT(11)
+#define VXGE_HW_LAG_CFG_RX_DISCARD_BEHAV vxge_mBIT(15)
+#define VXGE_HW_LAG_CFG_PREF_INDIV_PORT_NUM vxge_mBIT(19)
+/*0x02028*/ u64 lag_status;
+#define VXGE_HW_LAG_STATUS_XLCM_WAITING_TO_FAILBACK vxge_mBIT(3)
+#define VXGE_HW_LAG_STATUS_XLCM_TIMER_VAL_COLD_FAILOVER(val) \
+ vxge_vBIT(val, 8, 8)
+/*0x02030*/ u64 lag_active_passive_cfg;
+#define VXGE_HW_LAG_ACTIVE_PASSIVE_CFG_HOT_STANDBY vxge_mBIT(3)
+#define VXGE_HW_LAG_ACTIVE_PASSIVE_CFG_LACP_DECIDES vxge_mBIT(7)
+#define VXGE_HW_LAG_ACTIVE_PASSIVE_CFG_PREF_ACTIVE_PORT_NUM vxge_mBIT(11)
+#define VXGE_HW_LAG_ACTIVE_PASSIVE_CFG_AUTO_FAILBACK vxge_mBIT(15)
+#define VXGE_HW_LAG_ACTIVE_PASSIVE_CFG_FAILBACK_EN vxge_mBIT(19)
+#define VXGE_HW_LAG_ACTIVE_PASSIVE_CFG_COLD_FAILOVER_TIMEOUT(val) \
+ vxge_vBIT(val, 32, 16)
+ u8 unused02040[0x02040-0x02038];
+
+/*0x02040*/ u64 lag_lacp_cfg;
+#define VXGE_HW_LAG_LACP_CFG_EN vxge_mBIT(3)
+#define VXGE_HW_LAG_LACP_CFG_LACP_BEGIN vxge_mBIT(7)
+#define VXGE_HW_LAG_LACP_CFG_DISCARD_LACP vxge_mBIT(11)
+#define VXGE_HW_LAG_LACP_CFG_LIBERAL_LEN_CHK vxge_mBIT(15)
+/*0x02048*/ u64 lag_timer_cfg_1;
+#define VXGE_HW_LAG_TIMER_CFG_1_FAST_PER(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_LAG_TIMER_CFG_1_SLOW_PER(val) vxge_vBIT(val, 16, 16)
+#define VXGE_HW_LAG_TIMER_CFG_1_SHORT_TIMEOUT(val) vxge_vBIT(val, 32, 16)
+#define VXGE_HW_LAG_TIMER_CFG_1_LONG_TIMEOUT(val) vxge_vBIT(val, 48, 16)
+/*0x02050*/ u64 lag_timer_cfg_2;
+#define VXGE_HW_LAG_TIMER_CFG_2_CHURN_DET(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_LAG_TIMER_CFG_2_AGGR_WAIT(val) vxge_vBIT(val, 16, 16)
+#define VXGE_HW_LAG_TIMER_CFG_2_SHORT_TIMER_SCALE(val) vxge_vBIT(val, 32, 16)
+#define VXGE_HW_LAG_TIMER_CFG_2_LONG_TIMER_SCALE(val) vxge_vBIT(val, 48, 16)
+/*0x02058*/ u64 lag_sys_id;
+#define VXGE_HW_LAG_SYS_ID_ADDR(val) vxge_vBIT(val, 0, 48)
+#define VXGE_HW_LAG_SYS_ID_USE_PORT_ADDR vxge_mBIT(51)
+#define VXGE_HW_LAG_SYS_ID_ADDR_SEL vxge_mBIT(55)
+/*0x02060*/ u64 lag_sys_cfg;
+#define VXGE_HW_LAG_SYS_CFG_SYS_PRI(val) vxge_vBIT(val, 0, 16)
+ u8 unused02070[0x02070-0x02068];
+
+/*0x02070*/ u64 lag_aggr_addr_cfg[2];
+#define VXGE_HW_LAG_AGGR_ADDR_CFG_ADDR(val) vxge_vBIT(val, 0, 48)
+#define VXGE_HW_LAG_AGGR_ADDR_CFG_USE_PORT_ADDR vxge_mBIT(51)
+#define VXGE_HW_LAG_AGGR_ADDR_CFG_ADDR_SEL vxge_mBIT(55)
+/*0x02080*/ u64 lag_aggr_id_cfg[2];
+#define VXGE_HW_LAG_AGGR_ID_CFG_ID(val) vxge_vBIT(val, 0, 16)
+/*0x02090*/ u64 lag_aggr_admin_key[2];
+#define VXGE_HW_LAG_AGGR_ADMIN_KEY_KEY(val) vxge_vBIT(val, 0, 16)
+/*0x020a0*/ u64 lag_aggr_alt_admin_key;
+#define VXGE_HW_LAG_AGGR_ALT_ADMIN_KEY_KEY(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_LAG_AGGR_ALT_ADMIN_KEY_ALT_AGGR vxge_mBIT(19)
+/*0x020a8*/ u64 lag_aggr_oper_key[2];
+#define VXGE_HW_LAG_AGGR_OPER_KEY_LAGC_KEY(val) vxge_vBIT(val, 0, 16)
+/*0x020b8*/ u64 lag_aggr_partner_sys_id[2];
+#define VXGE_HW_LAG_AGGR_PARTNER_SYS_ID_LAGC_ADDR(val) vxge_vBIT(val, 0, 48)
+/*0x020c8*/ u64 lag_aggr_partner_info[2];
+#define VXGE_HW_LAG_AGGR_PARTNER_INFO_LAGC_SYS_PRI(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_LAG_AGGR_PARTNER_INFO_LAGC_OPER_KEY(val) \
+ vxge_vBIT(val, 16, 16)
+/*0x020d8*/ u64 lag_aggr_state[2];
+#define VXGE_HW_LAG_AGGR_STATE_LAGC_TX vxge_mBIT(3)
+#define VXGE_HW_LAG_AGGR_STATE_LAGC_RX vxge_mBIT(7)
+#define VXGE_HW_LAG_AGGR_STATE_LAGC_READY vxge_mBIT(11)
+#define VXGE_HW_LAG_AGGR_STATE_LAGC_INDIVIDUAL vxge_mBIT(15)
+ u8 unused020f0[0x020f0-0x020e8];
+
+/*0x020f0*/ u64 lag_port_cfg[2];
+#define VXGE_HW_LAG_PORT_CFG_EN vxge_mBIT(3)
+#define VXGE_HW_LAG_PORT_CFG_DISCARD_SLOW_PROTO vxge_mBIT(7)
+#define VXGE_HW_LAG_PORT_CFG_HOST_CHOSEN_AGGR vxge_mBIT(11)
+#define VXGE_HW_LAG_PORT_CFG_DISCARD_UNKNOWN_SLOW_PROTO vxge_mBIT(15)
+/*0x02100*/ u64 lag_port_actor_admin_cfg[2];
+#define VXGE_HW_LAG_PORT_ACTOR_ADMIN_CFG_PORT_NUM(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_LAG_PORT_ACTOR_ADMIN_CFG_PORT_PRI(val) vxge_vBIT(val, 16, 16)
+#define VXGE_HW_LAG_PORT_ACTOR_ADMIN_CFG_KEY_10G(val) vxge_vBIT(val, 32, 16)
+#define VXGE_HW_LAG_PORT_ACTOR_ADMIN_CFG_KEY_1G(val) vxge_vBIT(val, 48, 16)
+/*0x02110*/ u64 lag_port_actor_admin_state[2];
+#define VXGE_HW_LAG_PORT_ACTOR_ADMIN_STATE_LACP_ACTIVITY vxge_mBIT(3)
+#define VXGE_HW_LAG_PORT_ACTOR_ADMIN_STATE_LACP_TIMEOUT vxge_mBIT(7)
+#define VXGE_HW_LAG_PORT_ACTOR_ADMIN_STATE_AGGREGATION vxge_mBIT(11)
+#define VXGE_HW_LAG_PORT_ACTOR_ADMIN_STATE_SYNCHRONIZATION vxge_mBIT(15)
+#define VXGE_HW_LAG_PORT_ACTOR_ADMIN_STATE_COLLECTING vxge_mBIT(19)
+#define VXGE_HW_LAG_PORT_ACTOR_ADMIN_STATE_DISTRIBUTING vxge_mBIT(23)
+#define VXGE_HW_LAG_PORT_ACTOR_ADMIN_STATE_DEFAULTED vxge_mBIT(27)
+#define VXGE_HW_LAG_PORT_ACTOR_ADMIN_STATE_EXPIRED vxge_mBIT(31)
+/*0x02120*/ u64 lag_port_partner_admin_sys_id[2];
+#define VXGE_HW_LAG_PORT_PARTNER_ADMIN_SYS_ID_ADDR(val) vxge_vBIT(val, 0, 48)
+/*0x02130*/ u64 lag_port_partner_admin_cfg[2];
+#define VXGE_HW_LAG_PORT_PARTNER_ADMIN_CFG_SYS_PRI(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_LAG_PORT_PARTNER_ADMIN_CFG_KEY(val) vxge_vBIT(val, 16, 16)
+#define VXGE_HW_LAG_PORT_PARTNER_ADMIN_CFG_PORT_NUM(val) \
+ vxge_vBIT(val, 32, 16)
+#define VXGE_HW_LAG_PORT_PARTNER_ADMIN_CFG_PORT_PRI(val) \
+ vxge_vBIT(val, 48, 16)
+/*0x02140*/ u64 lag_port_partner_admin_state[2];
+#define VXGE_HW_LAG_PORT_PARTNER_ADMIN_STATE_LACP_ACTIVITY vxge_mBIT(3)
+#define VXGE_HW_LAG_PORT_PARTNER_ADMIN_STATE_LACP_TIMEOUT vxge_mBIT(7)
+#define VXGE_HW_LAG_PORT_PARTNER_ADMIN_STATE_AGGREGATION vxge_mBIT(11)
+#define VXGE_HW_LAG_PORT_PARTNER_ADMIN_STATE_SYNCHRONIZATION vxge_mBIT(15)
+#define VXGE_HW_LAG_PORT_PARTNER_ADMIN_STATE_COLLECTING vxge_mBIT(19)
+#define VXGE_HW_LAG_PORT_PARTNER_ADMIN_STATE_DISTRIBUTING vxge_mBIT(23)
+#define VXGE_HW_LAG_PORT_PARTNER_ADMIN_STATE_DEFAULTED vxge_mBIT(27)
+#define VXGE_HW_LAG_PORT_PARTNER_ADMIN_STATE_EXPIRED vxge_mBIT(31)
+/*0x02150*/ u64 lag_port_to_aggr[2];
+#define VXGE_HW_LAG_PORT_TO_AGGR_LAGC_AGGR_ID(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_LAG_PORT_TO_AGGR_LAGC_AGGR_VLD_ID vxge_mBIT(19)
+/*0x02160*/ u64 lag_port_actor_oper_key[2];
+#define VXGE_HW_LAG_PORT_ACTOR_OPER_KEY_LAGC_KEY(val) vxge_vBIT(val, 0, 16)
+/*0x02170*/ u64 lag_port_actor_oper_state[2];
+#define VXGE_HW_LAG_PORT_ACTOR_OPER_STATE_LAGC_LACP_ACTIVITY vxge_mBIT(3)
+#define VXGE_HW_LAG_PORT_ACTOR_OPER_STATE_LAGC_LACP_TIMEOUT vxge_mBIT(7)
+#define VXGE_HW_LAG_PORT_ACTOR_OPER_STATE_LAGC_AGGREGATION vxge_mBIT(11)
+#define VXGE_HW_LAG_PORT_ACTOR_OPER_STATE_LAGC_SYNCHRONIZATION vxge_mBIT(15)
+#define VXGE_HW_LAG_PORT_ACTOR_OPER_STATE_LAGC_COLLECTING vxge_mBIT(19)
+#define VXGE_HW_LAG_PORT_ACTOR_OPER_STATE_LAGC_DISTRIBUTING vxge_mBIT(23)
+#define VXGE_HW_LAG_PORT_ACTOR_OPER_STATE_LAGC_DEFAULTED vxge_mBIT(27)
+#define VXGE_HW_LAG_PORT_ACTOR_OPER_STATE_LAGC_EXPIRED vxge_mBIT(31)
+/*0x02180*/ u64 lag_port_partner_oper_sys_id[2];
+#define VXGE_HW_LAG_PORT_PARTNER_OPER_SYS_ID_LAGC_ADDR(val) \
+ vxge_vBIT(val, 0, 48)
+/*0x02190*/ u64 lag_port_partner_oper_info[2];
+#define VXGE_HW_LAG_PORT_PARTNER_OPER_INFO_LAGC_SYS_PRI(val) \
+ vxge_vBIT(val, 0, 16)
+#define VXGE_HW_LAG_PORT_PARTNER_OPER_INFO_LAGC_KEY(val) \
+ vxge_vBIT(val, 16, 16)
+#define VXGE_HW_LAG_PORT_PARTNER_OPER_INFO_LAGC_PORT_NUM(val) \
+ vxge_vBIT(val, 32, 16)
+#define VXGE_HW_LAG_PORT_PARTNER_OPER_INFO_LAGC_PORT_PRI(val) \
+ vxge_vBIT(val, 48, 16)
+/*0x021a0*/ u64 lag_port_partner_oper_state[2];
+#define VXGE_HW_LAG_PORT_PARTNER_OPER_STATE_LAGC_LACP_ACTIVITY vxge_mBIT(3)
+#define VXGE_HW_LAG_PORT_PARTNER_OPER_STATE_LAGC_LACP_TIMEOUT vxge_mBIT(7)
+#define VXGE_HW_LAG_PORT_PARTNER_OPER_STATE_LAGC_AGGREGATION vxge_mBIT(11)
+#define VXGE_HW_LAG_PORT_PARTNER_OPER_STATE_LAGC_SYNCHRONIZATION \
+ vxge_mBIT(15)
+#define VXGE_HW_LAG_PORT_PARTNER_OPER_STATE_LAGC_COLLECTING vxge_mBIT(19)
+#define VXGE_HW_LAG_PORT_PARTNER_OPER_STATE_LAGC_DISTRIBUTING vxge_mBIT(23)
+#define VXGE_HW_LAG_PORT_PARTNER_OPER_STATE_LAGC_DEFAULTED vxge_mBIT(27)
+#define VXGE_HW_LAG_PORT_PARTNER_OPER_STATE_LAGC_EXPIRED vxge_mBIT(31)
+/*0x021b0*/ u64 lag_port_state_vars[2];
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_READY vxge_mBIT(3)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_SELECTED(val) vxge_vBIT(val, 6, 2)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_AGGR_NUM vxge_mBIT(11)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_PORT_MOVED vxge_mBIT(15)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_PORT_ENABLED vxge_mBIT(18)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_PORT_DISABLED vxge_mBIT(19)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_NTT vxge_mBIT(23)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_ACTOR_CHURN vxge_mBIT(27)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_PARTNER_CHURN vxge_mBIT(31)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_ACTOR_INFO_LEN_MISMATCH \
+ vxge_mBIT(32)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_PARTNER_INFO_LEN_MISMATCH \
+ vxge_mBIT(33)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_COLL_INFO_LEN_MISMATCH vxge_mBIT(34)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_TERM_INFO_LEN_MISMATCH vxge_mBIT(35)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_RX_FSM_STATE(val) vxge_vBIT(val, 37, 3)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_MUX_FSM_STATE(val) \
+ vxge_vBIT(val, 41, 3)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_MUX_REASON(val) vxge_vBIT(val, 44, 4)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_ACTOR_CHURN_STATE vxge_mBIT(54)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_PARTNER_CHURN_STATE vxge_mBIT(55)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_ACTOR_CHURN_COUNT(val) \
+ vxge_vBIT(val, 56, 4)
+#define VXGE_HW_LAG_PORT_STATE_VARS_LAGC_PARTNER_CHURN_COUNT(val) \
+ vxge_vBIT(val, 60, 4)
+/*0x021c0*/ u64 lag_port_timer_cntr[2];
+#define VXGE_HW_LAG_PORT_TIMER_CNTR_LAGC_CURRENT_WHILE(val) vxge_vBIT(val, 0, 8)
+#define VXGE_HW_LAG_PORT_TIMER_CNTR_LAGC_PERIODIC_WHILE(val) \
+ vxge_vBIT(val, 8, 8)
+#define VXGE_HW_LAG_PORT_TIMER_CNTR_LAGC_WAIT_WHILE(val) vxge_vBIT(val, 16, 8)
+#define VXGE_HW_LAG_PORT_TIMER_CNTR_LAGC_TX_LACP(val) vxge_vBIT(val, 24, 8)
+#define VXGE_HW_LAG_PORT_TIMER_CNTR_LAGC_ACTOR_SYNC_TRANSITION_COUNT(val) \
+ vxge_vBIT(val, 32, 8)
+#define VXGE_HW_LAG_PORT_TIMER_CNTR_LAGC_PARTNER_SYNC_TRANSITION_COUNT(val) \
+ vxge_vBIT(val, 40, 8)
+#define VXGE_HW_LAG_PORT_TIMER_CNTR_LAGC_ACTOR_CHANGE_COUNT(val) \
+ vxge_vBIT(val, 48, 8)
+#define VXGE_HW_LAG_PORT_TIMER_CNTR_LAGC_PARTNER_CHANGE_COUNT(val) \
+ vxge_vBIT(val, 56, 8)
+ u8 unused02208[0x02700-0x021d0];
+
+/*0x02700*/ u64 rtdma_int_status;
+#define VXGE_HW_RTDMA_INT_STATUS_PDA_ALARM_PDA_INT vxge_mBIT(1)
+#define VXGE_HW_RTDMA_INT_STATUS_PCC_ERROR_PCC_INT vxge_mBIT(2)
+#define VXGE_HW_RTDMA_INT_STATUS_LSO_ERROR_LSO_INT vxge_mBIT(4)
+#define VXGE_HW_RTDMA_INT_STATUS_SM_ERROR_SM_INT vxge_mBIT(5)
+/*0x02708*/ u64 rtdma_int_mask;
+/*0x02710*/ u64 pda_alarm_reg;
+#define VXGE_HW_PDA_ALARM_REG_PDA_HSC_FIFO_ERR vxge_mBIT(0)
+#define VXGE_HW_PDA_ALARM_REG_PDA_SM_ERR vxge_mBIT(1)
+/*0x02718*/ u64 pda_alarm_mask;
+/*0x02720*/ u64 pda_alarm_alarm;
+/*0x02728*/ u64 pcc_error_reg;
+#define VXGE_HW_PCC_ERROR_REG_PCC_PCC_FRM_BUF_SBE(n) vxge_mBIT(n)
+#define VXGE_HW_PCC_ERROR_REG_PCC_PCC_TXDO_SBE(n) vxge_mBIT(n)
+#define VXGE_HW_PCC_ERROR_REG_PCC_PCC_FRM_BUF_DBE(n) vxge_mBIT(n)
+#define VXGE_HW_PCC_ERROR_REG_PCC_PCC_TXDO_DBE(n) vxge_mBIT(n)
+#define VXGE_HW_PCC_ERROR_REG_PCC_PCC_FSM_ERR_ALARM(n) vxge_mBIT(n)
+#define VXGE_HW_PCC_ERROR_REG_PCC_PCC_SERR(n) vxge_mBIT(n)
+/*0x02730*/ u64 pcc_error_mask;
+/*0x02738*/ u64 pcc_error_alarm;
+/*0x02740*/ u64 lso_error_reg;
+#define VXGE_HW_LSO_ERROR_REG_PCC_LSO_ABORT(n) vxge_mBIT(n)
+#define VXGE_HW_LSO_ERROR_REG_PCC_LSO_FSM_ERR_ALARM(n) vxge_mBIT(n)
+/*0x02748*/ u64 lso_error_mask;
+/*0x02750*/ u64 lso_error_alarm;
+/*0x02758*/ u64 sm_error_reg;
+#define VXGE_HW_SM_ERROR_REG_SM_FSM_ERR_ALARM vxge_mBIT(15)
+/*0x02760*/ u64 sm_error_mask;
+/*0x02768*/ u64 sm_error_alarm;
+
+ u8 unused027a8[0x027a8-0x02770];
+
+/*0x027a8*/ u64 txd_ownership_ctrl;
+#define VXGE_HW_TXD_OWNERSHIP_CTRL_KEEP_OWNERSHIP vxge_mBIT(7)
+/*0x027b0*/ u64 pcc_cfg;
+#define VXGE_HW_PCC_CFG_PCC_ENABLE(n) vxge_mBIT(n)
+#define VXGE_HW_PCC_CFG_PCC_ECC_ENABLE_N(n) vxge_mBIT(n)
+/*0x027b8*/ u64 pcc_control;
+#define VXGE_HW_PCC_CONTROL_FE_ENABLE(val) vxge_vBIT(val, 6, 2)
+#define VXGE_HW_PCC_CONTROL_EARLY_ASSIGN_EN vxge_mBIT(15)
+#define VXGE_HW_PCC_CONTROL_UNBLOCK_DB_ERR vxge_mBIT(31)
+/*0x027c0*/ u64 pda_status1;
+#define VXGE_HW_PDA_STATUS1_PDA_WRAP_0_CTR(val) vxge_vBIT(val, 4, 4)
+#define VXGE_HW_PDA_STATUS1_PDA_WRAP_1_CTR(val) vxge_vBIT(val, 12, 4)
+#define VXGE_HW_PDA_STATUS1_PDA_WRAP_2_CTR(val) vxge_vBIT(val, 20, 4)
+#define VXGE_HW_PDA_STATUS1_PDA_WRAP_3_CTR(val) vxge_vBIT(val, 28, 4)
+#define VXGE_HW_PDA_STATUS1_PDA_WRAP_4_CTR(val) vxge_vBIT(val, 36, 4)
+#define VXGE_HW_PDA_STATUS1_PDA_WRAP_5_CTR(val) vxge_vBIT(val, 44, 4)
+#define VXGE_HW_PDA_STATUS1_PDA_WRAP_6_CTR(val) vxge_vBIT(val, 52, 4)
+#define VXGE_HW_PDA_STATUS1_PDA_WRAP_7_CTR(val) vxge_vBIT(val, 60, 4)
+/*0x027c8*/ u64 rtdma_bw_timer;
+#define VXGE_HW_RTDMA_BW_TIMER_TIMER_CTRL(val) vxge_vBIT(val, 12, 4)
+
+ u8 unused02900[0x02900-0x027d0];
+/*0x02900*/ u64 g3cmct_int_status;
+#define VXGE_HW_G3CMCT_INT_STATUS_ERR_G3IF_INT vxge_mBIT(0)
+/*0x02908*/ u64 g3cmct_int_mask;
+/*0x02910*/ u64 g3cmct_err_reg;
+#define VXGE_HW_G3CMCT_ERR_REG_G3IF_SM_ERR vxge_mBIT(4)
+#define VXGE_HW_G3CMCT_ERR_REG_G3IF_GDDR3_DECC vxge_mBIT(5)
+#define VXGE_HW_G3CMCT_ERR_REG_G3IF_GDDR3_U_DECC vxge_mBIT(6)
+#define VXGE_HW_G3CMCT_ERR_REG_G3IF_CTRL_FIFO_DECC vxge_mBIT(7)
+#define VXGE_HW_G3CMCT_ERR_REG_G3IF_GDDR3_SECC vxge_mBIT(29)
+#define VXGE_HW_G3CMCT_ERR_REG_G3IF_GDDR3_U_SECC vxge_mBIT(30)
+#define VXGE_HW_G3CMCT_ERR_REG_G3IF_CTRL_FIFO_SECC vxge_mBIT(31)
+/*0x02918*/ u64 g3cmct_err_mask;
+/*0x02920*/ u64 g3cmct_err_alarm;
+ u8 unused03000[0x03000-0x02928];
+
+/*0x03000*/ u64 mc_int_status;
+#define VXGE_HW_MC_INT_STATUS_MC_ERR_MC_INT vxge_mBIT(3)
+#define VXGE_HW_MC_INT_STATUS_GROCRC_ALARM_ROCRC_INT vxge_mBIT(7)
+#define VXGE_HW_MC_INT_STATUS_FAU_GEN_ERR_FAU_GEN_INT vxge_mBIT(11)
+#define VXGE_HW_MC_INT_STATUS_FAU_ECC_ERR_FAU_ECC_INT vxge_mBIT(15)
+/*0x03008*/ u64 mc_int_mask;
+/*0x03010*/ u64 mc_err_reg;
+#define VXGE_HW_MC_ERR_REG_MC_XFMD_MEM_ECC_SG_ERR_A vxge_mBIT(3)
+#define VXGE_HW_MC_ERR_REG_MC_XFMD_MEM_ECC_SG_ERR_B vxge_mBIT(4)
+#define VXGE_HW_MC_ERR_REG_MC_G3IF_RD_FIFO_ECC_SG_ERR vxge_mBIT(5)
+#define VXGE_HW_MC_ERR_REG_MC_MIRI_ECC_SG_ERR_0 vxge_mBIT(6)
+#define VXGE_HW_MC_ERR_REG_MC_MIRI_ECC_SG_ERR_1 vxge_mBIT(7)
+#define VXGE_HW_MC_ERR_REG_MC_XFMD_MEM_ECC_DB_ERR_A vxge_mBIT(10)
+#define VXGE_HW_MC_ERR_REG_MC_XFMD_MEM_ECC_DB_ERR_B vxge_mBIT(11)
+#define VXGE_HW_MC_ERR_REG_MC_G3IF_RD_FIFO_ECC_DB_ERR vxge_mBIT(12)
+#define VXGE_HW_MC_ERR_REG_MC_MIRI_ECC_DB_ERR_0 vxge_mBIT(13)
+#define VXGE_HW_MC_ERR_REG_MC_MIRI_ECC_DB_ERR_1 vxge_mBIT(14)
+#define VXGE_HW_MC_ERR_REG_MC_SM_ERR vxge_mBIT(15)
+/*0x03018*/ u64 mc_err_mask;
+/*0x03020*/ u64 mc_err_alarm;
+/*0x03028*/ u64 grocrc_alarm_reg;
+#define VXGE_HW_GROCRC_ALARM_REG_XFMD_WR_FIFO_ERR vxge_mBIT(3)
+#define VXGE_HW_GROCRC_ALARM_REG_WDE2MSR_RD_FIFO_ERR vxge_mBIT(7)
+/*0x03030*/ u64 grocrc_alarm_mask;
+/*0x03038*/ u64 grocrc_alarm_alarm;
+ u8 unused03100[0x03100-0x03040];
+
+/*0x03100*/ u64 rx_thresh_cfg_repl;
+#define VXGE_HW_RX_THRESH_CFG_REPL_PAUSE_LOW_THR(val) vxge_vBIT(val, 0, 8)
+#define VXGE_HW_RX_THRESH_CFG_REPL_PAUSE_HIGH_THR(val) vxge_vBIT(val, 8, 8)
+#define VXGE_HW_RX_THRESH_CFG_REPL_RED_THR_0(val) vxge_vBIT(val, 16, 8)
+#define VXGE_HW_RX_THRESH_CFG_REPL_RED_THR_1(val) vxge_vBIT(val, 24, 8)
+#define VXGE_HW_RX_THRESH_CFG_REPL_RED_THR_2(val) vxge_vBIT(val, 32, 8)
+#define VXGE_HW_RX_THRESH_CFG_REPL_RED_THR_3(val) vxge_vBIT(val, 40, 8)
+#define VXGE_HW_RX_THRESH_CFG_REPL_GLOBAL_WOL_EN vxge_mBIT(62)
+#define VXGE_HW_RX_THRESH_CFG_REPL_EXACT_VP_MATCH_REQ vxge_mBIT(63)
+ u8 unused033b8[0x033b8-0x03108];
+
+/*0x033b8*/ u64 fbmc_ecc_cfg;
+#define VXGE_HW_FBMC_ECC_CFG_ENABLE(val) vxge_vBIT(val, 3, 5)
+ u8 unused03400[0x03400-0x033c0];
+
+/*0x03400*/ u64 pcipif_int_status;
+#define VXGE_HW_PCIPIF_INT_STATUS_DBECC_ERR_DBECC_ERR_INT vxge_mBIT(3)
+#define VXGE_HW_PCIPIF_INT_STATUS_SBECC_ERR_SBECC_ERR_INT vxge_mBIT(7)
+#define VXGE_HW_PCIPIF_INT_STATUS_GENERAL_ERR_GENERAL_ERR_INT vxge_mBIT(11)
+#define VXGE_HW_PCIPIF_INT_STATUS_SRPCIM_MSG_SRPCIM_MSG_INT vxge_mBIT(15)
+#define VXGE_HW_PCIPIF_INT_STATUS_MRPCIM_SPARE_R1_MRPCIM_SPARE_R1_INT \
+ vxge_mBIT(19)
+/*0x03408*/ u64 pcipif_int_mask;
+/*0x03410*/ u64 dbecc_err_reg;
+#define VXGE_HW_DBECC_ERR_REG_PCI_RETRY_BUF_DB_ERR vxge_mBIT(3)
+#define VXGE_HW_DBECC_ERR_REG_PCI_RETRY_SOT_DB_ERR vxge_mBIT(7)
+#define VXGE_HW_DBECC_ERR_REG_PCI_P_HDR_DB_ERR vxge_mBIT(11)
+#define VXGE_HW_DBECC_ERR_REG_PCI_P_DATA_DB_ERR vxge_mBIT(15)
+#define VXGE_HW_DBECC_ERR_REG_PCI_NP_HDR_DB_ERR vxge_mBIT(19)
+#define VXGE_HW_DBECC_ERR_REG_PCI_NP_DATA_DB_ERR vxge_mBIT(23)
+/*0x03418*/ u64 dbecc_err_mask;
+/*0x03420*/ u64 dbecc_err_alarm;
+/*0x03428*/ u64 sbecc_err_reg;
+#define VXGE_HW_SBECC_ERR_REG_PCI_RETRY_BUF_SG_ERR vxge_mBIT(3)
+#define VXGE_HW_SBECC_ERR_REG_PCI_RETRY_SOT_SG_ERR vxge_mBIT(7)
+#define VXGE_HW_SBECC_ERR_REG_PCI_P_HDR_SG_ERR vxge_mBIT(11)
+#define VXGE_HW_SBECC_ERR_REG_PCI_P_DATA_SG_ERR vxge_mBIT(15)
+#define VXGE_HW_SBECC_ERR_REG_PCI_NP_HDR_SG_ERR vxge_mBIT(19)
+#define VXGE_HW_SBECC_ERR_REG_PCI_NP_DATA_SG_ERR vxge_mBIT(23)
+/*0x03430*/ u64 sbecc_err_mask;
+/*0x03438*/ u64 sbecc_err_alarm;
+/*0x03440*/ u64 general_err_reg;
+#define VXGE_HW_GENERAL_ERR_REG_PCI_DROPPED_ILLEGAL_CFG vxge_mBIT(3)
+#define VXGE_HW_GENERAL_ERR_REG_PCI_ILLEGAL_MEM_MAP_PROG vxge_mBIT(7)
+#define VXGE_HW_GENERAL_ERR_REG_PCI_LINK_RST_FSM_ERR vxge_mBIT(11)
+#define VXGE_HW_GENERAL_ERR_REG_PCI_RX_ILLEGAL_TLP_VPLANE vxge_mBIT(15)
+#define VXGE_HW_GENERAL_ERR_REG_PCI_TRAINING_RESET_DET vxge_mBIT(19)
+#define VXGE_HW_GENERAL_ERR_REG_PCI_PCI_LINK_DOWN_DET vxge_mBIT(23)
+#define VXGE_HW_GENERAL_ERR_REG_PCI_RESET_ACK_DLLP vxge_mBIT(27)
+/*0x03448*/ u64 general_err_mask;
+/*0x03450*/ u64 general_err_alarm;
+/*0x03458*/ u64 srpcim_msg_reg;
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE0_RMSG_INT \
+ vxge_mBIT(0)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE1_RMSG_INT \
+ vxge_mBIT(1)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE2_RMSG_INT \
+ vxge_mBIT(2)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE3_RMSG_INT \
+ vxge_mBIT(3)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE4_RMSG_INT \
+ vxge_mBIT(4)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE5_RMSG_INT \
+ vxge_mBIT(5)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE6_RMSG_INT \
+ vxge_mBIT(6)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE7_RMSG_INT \
+ vxge_mBIT(7)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE8_RMSG_INT \
+ vxge_mBIT(8)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE9_RMSG_INT \
+ vxge_mBIT(9)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE10_RMSG_INT \
+ vxge_mBIT(10)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE11_RMSG_INT \
+ vxge_mBIT(11)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE12_RMSG_INT \
+ vxge_mBIT(12)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE13_RMSG_INT \
+ vxge_mBIT(13)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE14_RMSG_INT \
+ vxge_mBIT(14)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE15_RMSG_INT \
+ vxge_mBIT(15)
+#define VXGE_HW_SRPCIM_MSG_REG_SWIF_SRPCIM_TO_MRPCIM_VPLANE16_RMSG_INT \
+ vxge_mBIT(16)
+/*0x03460*/ u64 srpcim_msg_mask;
+/*0x03468*/ u64 srpcim_msg_alarm;
+ u8 unused03600[0x03600-0x03470];
+
+/*0x03600*/ u64 gcmg1_int_status;
+#define VXGE_HW_GCMG1_INT_STATUS_GSSCC_ERR_GSSCC_INT vxge_mBIT(0)
+#define VXGE_HW_GCMG1_INT_STATUS_GSSC0_ERR0_GSSC0_0_INT vxge_mBIT(1)
+#define VXGE_HW_GCMG1_INT_STATUS_GSSC0_ERR1_GSSC0_1_INT vxge_mBIT(2)
+#define VXGE_HW_GCMG1_INT_STATUS_GSSC1_ERR0_GSSC1_0_INT vxge_mBIT(3)
+#define VXGE_HW_GCMG1_INT_STATUS_GSSC1_ERR1_GSSC1_1_INT vxge_mBIT(4)
+#define VXGE_HW_GCMG1_INT_STATUS_GSSC2_ERR0_GSSC2_0_INT vxge_mBIT(5)
+#define VXGE_HW_GCMG1_INT_STATUS_GSSC2_ERR1_GSSC2_1_INT vxge_mBIT(6)
+#define VXGE_HW_GCMG1_INT_STATUS_UQM_ERR_UQM_INT vxge_mBIT(7)
+#define VXGE_HW_GCMG1_INT_STATUS_GQCC_ERR_GQCC_INT vxge_mBIT(8)
+/*0x03608*/ u64 gcmg1_int_mask;
+ u8 unused03a00[0x03a00-0x03610];
+
+/*0x03a00*/ u64 pcmg1_int_status;
+#define VXGE_HW_PCMG1_INT_STATUS_PSSCC_ERR_PSSCC_INT vxge_mBIT(0)
+#define VXGE_HW_PCMG1_INT_STATUS_PQCC_ERR_PQCC_INT vxge_mBIT(1)
+#define VXGE_HW_PCMG1_INT_STATUS_PQCC_CQM_ERR_PQCC_CQM_INT vxge_mBIT(2)
+#define VXGE_HW_PCMG1_INT_STATUS_PQCC_SQM_ERR_PQCC_SQM_INT vxge_mBIT(3)
+/*0x03a08*/ u64 pcmg1_int_mask;
+ u8 unused04000[0x04000-0x03a10];
+
+/*0x04000*/ u64 one_int_status;
+#define VXGE_HW_ONE_INT_STATUS_RXPE_ERR_RXPE_INT vxge_mBIT(7)
+#define VXGE_HW_ONE_INT_STATUS_TXPE_BCC_MEM_SG_ECC_ERR_TXPE_BCC_MEM_SG_ECC_INT \
+ vxge_mBIT(13)
+#define VXGE_HW_ONE_INT_STATUS_TXPE_BCC_MEM_DB_ECC_ERR_TXPE_BCC_MEM_DB_ECC_INT \
+ vxge_mBIT(14)
+#define VXGE_HW_ONE_INT_STATUS_TXPE_ERR_TXPE_INT vxge_mBIT(15)
+#define VXGE_HW_ONE_INT_STATUS_DLM_ERR_DLM_INT vxge_mBIT(23)
+#define VXGE_HW_ONE_INT_STATUS_PE_ERR_PE_INT vxge_mBIT(31)
+#define VXGE_HW_ONE_INT_STATUS_RPE_ERR_RPE_INT vxge_mBIT(39)
+#define VXGE_HW_ONE_INT_STATUS_RPE_FSM_ERR_RPE_FSM_INT vxge_mBIT(47)
+#define VXGE_HW_ONE_INT_STATUS_OES_ERR_OES_INT vxge_mBIT(55)
+/*0x04008*/ u64 one_int_mask;
+ u8 unused04818[0x04818-0x04010];
+
+/*0x04818*/ u64 noa_wct_ctrl;
+#define VXGE_HW_NOA_WCT_CTRL_VP_INT_NUM vxge_mBIT(0)
+/*0x04820*/ u64 rc_cfg2;
+#define VXGE_HW_RC_CFG2_BUFF1_SIZE(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_RC_CFG2_BUFF2_SIZE(val) vxge_vBIT(val, 16, 16)
+#define VXGE_HW_RC_CFG2_BUFF3_SIZE(val) vxge_vBIT(val, 32, 16)
+#define VXGE_HW_RC_CFG2_BUFF4_SIZE(val) vxge_vBIT(val, 48, 16)
+/*0x04828*/ u64 rc_cfg3;
+#define VXGE_HW_RC_CFG3_BUFF5_SIZE(val) vxge_vBIT(val, 0, 16)
+/*0x04830*/ u64 rx_multi_cast_ctrl1;
+#define VXGE_HW_RX_MULTI_CAST_CTRL1_ENABLE vxge_mBIT(7)
+#define VXGE_HW_RX_MULTI_CAST_CTRL1_DELAY_COUNT(val) vxge_vBIT(val, 11, 5)
+/*0x04838*/ u64 rxdm_dbg_rd;
+#define VXGE_HW_RXDM_DBG_RD_ADDR(val) vxge_vBIT(val, 0, 12)
+#define VXGE_HW_RXDM_DBG_RD_ENABLE vxge_mBIT(31)
+/*0x04840*/ u64 rxdm_dbg_rd_data;
+#define VXGE_HW_RXDM_DBG_RD_DATA_RMC_RXDM_DBG_RD_DATA(val) vxge_vBIT(val, 0, 64)
+/*0x04848*/ u64 rqa_top_prty_for_vh[17];
+#define VXGE_HW_RQA_TOP_PRTY_FOR_VH_RQA_TOP_PRTY_FOR_VH(val) \
+ vxge_vBIT(val, 59, 5)
+ u8 unused04900[0x04900-0x048d0];
+
+/*0x04900*/ u64 tim_status;
+#define VXGE_HW_TIM_STATUS_TIM_RESET_IN_PROGRESS vxge_mBIT(0)
+/*0x04908*/ u64 tim_ecc_enable;
+#define VXGE_HW_TIM_ECC_ENABLE_VBLS_N vxge_mBIT(7)
+#define VXGE_HW_TIM_ECC_ENABLE_BMAP_N vxge_mBIT(15)
+#define VXGE_HW_TIM_ECC_ENABLE_BMAP_MSG_N vxge_mBIT(23)
+/*0x04910*/ u64 tim_bp_ctrl;
+#define VXGE_HW_TIM_BP_CTRL_RD_XON vxge_mBIT(7)
+#define VXGE_HW_TIM_BP_CTRL_WR_XON vxge_mBIT(15)
+#define VXGE_HW_TIM_BP_CTRL_ROCRC_BYP vxge_mBIT(23)
+/*0x04918*/ u64 tim_resource_assignment_vh[17];
+#define VXGE_HW_TIM_RESOURCE_ASSIGNMENT_VH_BMAP_ROOT(val) vxge_vBIT(val, 0, 32)
+/*0x049a0*/ u64 tim_bmap_mapping_vp_err[17];
+#define VXGE_HW_TIM_BMAP_MAPPING_VP_ERR_TIM_DEST_VPATH(val) vxge_vBIT(val, 3, 5)
+ u8 unused04b00[0x04b00-0x04a28];
+
+/*0x04b00*/ u64 gcmg2_int_status;
+#define VXGE_HW_GCMG2_INT_STATUS_GXTMC_ERR_GXTMC_INT vxge_mBIT(7)
+#define VXGE_HW_GCMG2_INT_STATUS_GCP_ERR_GCP_INT vxge_mBIT(15)
+#define VXGE_HW_GCMG2_INT_STATUS_CMC_ERR_CMC_INT vxge_mBIT(23)
+/*0x04b08*/ u64 gcmg2_int_mask;
+/*0x04b10*/ u64 gxtmc_err_reg;
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_MEM_DB_ERR(val) vxge_vBIT(val, 0, 4)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_MEM_SG_ERR(val) vxge_vBIT(val, 4, 4)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_CMC_RD_DATA_DB_ERR vxge_mBIT(8)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_REQ_FIFO_ERR vxge_mBIT(9)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_REQ_DATA_FIFO_ERR vxge_mBIT(10)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_WR_RSP_FIFO_ERR vxge_mBIT(11)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_RD_RSP_FIFO_ERR vxge_mBIT(12)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_CMI_WRP_FIFO_ERR vxge_mBIT(13)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_CMI_WRP_ERR vxge_mBIT(14)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_CMI_RRP_FIFO_ERR vxge_mBIT(15)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_CMI_RRP_ERR vxge_mBIT(16)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_CMI_DATA_SM_ERR vxge_mBIT(17)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_CMI_CMC0_IF_ERR vxge_mBIT(18)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_CMI_ARB_SM_ERR vxge_mBIT(19)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_CMI_CFC_SM_ERR vxge_mBIT(20)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_CMI_DFETCH_CREDIT_OVERFLOW \
+ vxge_mBIT(21)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_CMI_DFETCH_CREDIT_UNDERFLOW \
+ vxge_mBIT(22)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_CMI_DFETCH_SM_ERR vxge_mBIT(23)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_CMI_RCTRL_CREDIT_OVERFLOW \
+ vxge_mBIT(24)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_CMI_RCTRL_CREDIT_UNDERFLOW \
+ vxge_mBIT(25)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_CMI_RCTRL_SM_ERR vxge_mBIT(26)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_CMI_WCOMPL_SM_ERR vxge_mBIT(27)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_CMI_WCOMPL_TAG_ERR vxge_mBIT(28)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_CMI_WREQ_SM_ERR vxge_mBIT(29)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_BDT_CMI_WREQ_FIFO_ERR vxge_mBIT(30)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_CP2BDT_RFIFO_POP_ERR vxge_mBIT(31)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_XTMC_BDT_CMI_OP_ERR vxge_mBIT(32)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_XTMC_BDT_DFETCH_OP_ERR vxge_mBIT(33)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_XTMC_BDT_DFIFO_ERR vxge_mBIT(34)
+#define VXGE_HW_GXTMC_ERR_REG_XTMC_CMI_ARB_SM_ERR vxge_mBIT(35)
+/*0x04b18*/ u64 gxtmc_err_mask;
+/*0x04b20*/ u64 gxtmc_err_alarm;
+/*0x04b28*/ u64 cmc_err_reg;
+#define VXGE_HW_CMC_ERR_REG_CMC_CMC_SM_ERR vxge_mBIT(0)
+/*0x04b30*/ u64 cmc_err_mask;
+/*0x04b38*/ u64 cmc_err_alarm;
+/*0x04b40*/ u64 gcp_err_reg;
+#define VXGE_HW_GCP_ERR_REG_CP_H2L2CP_FIFO_ERR vxge_mBIT(0)
+#define VXGE_HW_GCP_ERR_REG_CP_STC2CP_FIFO_ERR vxge_mBIT(1)
+#define VXGE_HW_GCP_ERR_REG_CP_STE2CP_FIFO_ERR vxge_mBIT(2)
+#define VXGE_HW_GCP_ERR_REG_CP_TTE2CP_FIFO_ERR vxge_mBIT(3)
+/*0x04b48*/ u64 gcp_err_mask;
+/*0x04b50*/ u64 gcp_err_alarm;
+ u8 unused04f00[0x04f00-0x04b58];
+
+/*0x04f00*/ u64 pcmg2_int_status;
+#define VXGE_HW_PCMG2_INT_STATUS_PXTMC_ERR_PXTMC_INT vxge_mBIT(7)
+#define VXGE_HW_PCMG2_INT_STATUS_CP_EXC_CP_XT_EXC_INT vxge_mBIT(15)
+#define VXGE_HW_PCMG2_INT_STATUS_CP_ERR_CP_ERR_INT vxge_mBIT(23)
+/*0x04f08*/ u64 pcmg2_int_mask;
+/*0x04f10*/ u64 pxtmc_err_reg;
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_XT_PIF_SRAM_DB_ERR(val) vxge_vBIT(val, 0, 2)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_MPT_REQ_FIFO_ERR vxge_mBIT(2)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_MPT_PRSP_FIFO_ERR vxge_mBIT(3)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_MPT_WRSP_FIFO_ERR vxge_mBIT(4)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_UPT_REQ_FIFO_ERR vxge_mBIT(5)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_UPT_PRSP_FIFO_ERR vxge_mBIT(6)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_UPT_WRSP_FIFO_ERR vxge_mBIT(7)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CPT_REQ_FIFO_ERR vxge_mBIT(8)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CPT_PRSP_FIFO_ERR vxge_mBIT(9)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CPT_WRSP_FIFO_ERR vxge_mBIT(10)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_REQ_FIFO_ERR vxge_mBIT(11)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_REQ_DATA_FIFO_ERR vxge_mBIT(12)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_WR_RSP_FIFO_ERR vxge_mBIT(13)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_RD_RSP_FIFO_ERR vxge_mBIT(14)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_MPT_REQ_SHADOW_ERR vxge_mBIT(15)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_MPT_RSP_SHADOW_ERR vxge_mBIT(16)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_UPT_REQ_SHADOW_ERR vxge_mBIT(17)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_UPT_RSP_SHADOW_ERR vxge_mBIT(18)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CPT_REQ_SHADOW_ERR vxge_mBIT(19)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CPT_RSP_SHADOW_ERR vxge_mBIT(20)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_XIL_SHADOW_ERR vxge_mBIT(21)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_ARB_SHADOW_ERR vxge_mBIT(22)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_RAM_SHADOW_ERR vxge_mBIT(23)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CMW_SHADOW_ERR vxge_mBIT(24)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CMR_SHADOW_ERR vxge_mBIT(25)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_MPT_REQ_FSM_ERR vxge_mBIT(26)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_MPT_RSP_FSM_ERR vxge_mBIT(27)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_UPT_REQ_FSM_ERR vxge_mBIT(28)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_UPT_RSP_FSM_ERR vxge_mBIT(29)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CPT_REQ_FSM_ERR vxge_mBIT(30)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CPT_RSP_FSM_ERR vxge_mBIT(31)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_XIL_FSM_ERR vxge_mBIT(32)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_ARB_FSM_ERR vxge_mBIT(33)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CMW_FSM_ERR vxge_mBIT(34)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CMR_FSM_ERR vxge_mBIT(35)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_MXP_RD_PROT_ERR vxge_mBIT(36)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_UXP_RD_PROT_ERR vxge_mBIT(37)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CXP_RD_PROT_ERR vxge_mBIT(38)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_MXP_WR_PROT_ERR vxge_mBIT(39)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_UXP_WR_PROT_ERR vxge_mBIT(40)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CXP_WR_PROT_ERR vxge_mBIT(41)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_MXP_INV_ADDR_ERR vxge_mBIT(42)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_UXP_INV_ADDR_ERR vxge_mBIT(43)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CXP_INV_ADDR_ERR vxge_mBIT(44)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_MXP_RD_PROT_INFO_ERR vxge_mBIT(45)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_UXP_RD_PROT_INFO_ERR vxge_mBIT(46)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CXP_RD_PROT_INFO_ERR vxge_mBIT(47)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_MXP_WR_PROT_INFO_ERR vxge_mBIT(48)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_UXP_WR_PROT_INFO_ERR vxge_mBIT(49)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CXP_WR_PROT_INFO_ERR vxge_mBIT(50)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_MXP_INV_ADDR_INFO_ERR vxge_mBIT(51)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_UXP_INV_ADDR_INFO_ERR vxge_mBIT(52)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CXP_INV_ADDR_INFO_ERR vxge_mBIT(53)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_XT_PIF_SRAM_SG_ERR(val) vxge_vBIT(val, 54, 2)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CP2BDT_DFIFO_PUSH_ERR vxge_mBIT(56)
+#define VXGE_HW_PXTMC_ERR_REG_XTMC_CP2BDT_RFIFO_PUSH_ERR vxge_mBIT(57)
+/*0x04f18*/ u64 pxtmc_err_mask;
+/*0x04f20*/ u64 pxtmc_err_alarm;
+/*0x04f28*/ u64 cp_err_reg;
+#define VXGE_HW_CP_ERR_REG_CP_CP_DCACHE_SG_ERR(val) vxge_vBIT(val, 0, 8)
+#define VXGE_HW_CP_ERR_REG_CP_CP_ICACHE_SG_ERR(val) vxge_vBIT(val, 8, 2)
+#define VXGE_HW_CP_ERR_REG_CP_CP_DTAG_SG_ERR vxge_mBIT(10)
+#define VXGE_HW_CP_ERR_REG_CP_CP_ITAG_SG_ERR vxge_mBIT(11)
+#define VXGE_HW_CP_ERR_REG_CP_CP_TRACE_SG_ERR vxge_mBIT(12)
+#define VXGE_HW_CP_ERR_REG_CP_DMA2CP_SG_ERR vxge_mBIT(13)
+#define VXGE_HW_CP_ERR_REG_CP_MP2CP_SG_ERR vxge_mBIT(14)
+#define VXGE_HW_CP_ERR_REG_CP_QCC2CP_SG_ERR vxge_mBIT(15)
+#define VXGE_HW_CP_ERR_REG_CP_STC2CP_SG_ERR(val) vxge_vBIT(val, 16, 2)
+#define VXGE_HW_CP_ERR_REG_CP_CP_DCACHE_DB_ERR(val) vxge_vBIT(val, 24, 8)
+#define VXGE_HW_CP_ERR_REG_CP_CP_ICACHE_DB_ERR(val) vxge_vBIT(val, 32, 2)
+#define VXGE_HW_CP_ERR_REG_CP_CP_DTAG_DB_ERR vxge_mBIT(34)
+#define VXGE_HW_CP_ERR_REG_CP_CP_ITAG_DB_ERR vxge_mBIT(35)
+#define VXGE_HW_CP_ERR_REG_CP_CP_TRACE_DB_ERR vxge_mBIT(36)
+#define VXGE_HW_CP_ERR_REG_CP_DMA2CP_DB_ERR vxge_mBIT(37)
+#define VXGE_HW_CP_ERR_REG_CP_MP2CP_DB_ERR vxge_mBIT(38)
+#define VXGE_HW_CP_ERR_REG_CP_QCC2CP_DB_ERR vxge_mBIT(39)
+#define VXGE_HW_CP_ERR_REG_CP_STC2CP_DB_ERR(val) vxge_vBIT(val, 40, 2)
+#define VXGE_HW_CP_ERR_REG_CP_H2L2CP_FIFO_ERR vxge_mBIT(48)
+#define VXGE_HW_CP_ERR_REG_CP_STC2CP_FIFO_ERR vxge_mBIT(49)
+#define VXGE_HW_CP_ERR_REG_CP_STE2CP_FIFO_ERR vxge_mBIT(50)
+#define VXGE_HW_CP_ERR_REG_CP_TTE2CP_FIFO_ERR vxge_mBIT(51)
+#define VXGE_HW_CP_ERR_REG_CP_SWIF2CP_FIFO_ERR vxge_mBIT(52)
+#define VXGE_HW_CP_ERR_REG_CP_CP2DMA_FIFO_ERR vxge_mBIT(53)
+#define VXGE_HW_CP_ERR_REG_CP_DAM2CP_FIFO_ERR vxge_mBIT(54)
+#define VXGE_HW_CP_ERR_REG_CP_MP2CP_FIFO_ERR vxge_mBIT(55)
+#define VXGE_HW_CP_ERR_REG_CP_QCC2CP_FIFO_ERR vxge_mBIT(56)
+#define VXGE_HW_CP_ERR_REG_CP_DMA2CP_FIFO_ERR vxge_mBIT(57)
+#define VXGE_HW_CP_ERR_REG_CP_CP_WAKE_FSM_INTEGRITY_ERR vxge_mBIT(60)
+#define VXGE_HW_CP_ERR_REG_CP_CP_PMON_FSM_INTEGRITY_ERR vxge_mBIT(61)
+#define VXGE_HW_CP_ERR_REG_CP_DMA_RD_SHADOW_ERR vxge_mBIT(62)
+#define VXGE_HW_CP_ERR_REG_CP_PIFT_CREDIT_ERR vxge_mBIT(63)
+/*0x04f30*/ u64 cp_err_mask;
+/*0x04f38*/ u64 cp_err_alarm;
+ u8 unused04fe8[0x04f50-0x04f40];
+
+/*0x04f50*/ u64 cp_exc_reg;
+#define VXGE_HW_CP_EXC_REG_CP_CP_CAUSE_INFO_INT vxge_mBIT(47)
+#define VXGE_HW_CP_EXC_REG_CP_CP_CAUSE_CRIT_INT vxge_mBIT(55)
+#define VXGE_HW_CP_EXC_REG_CP_CP_SERR vxge_mBIT(63)
+/*0x04f58*/ u64 cp_exc_mask;
+/*0x04f60*/ u64 cp_exc_alarm;
+/*0x04f68*/ u64 cp_exc_cause;
+#define VXGE_HW_CP_EXC_CAUSE_CP_CP_CAUSE(val) vxge_vBIT(val, 32, 32)
+ u8 unused05200[0x05200-0x04f70];
+
+/*0x05200*/ u64 msg_int_status;
+#define VXGE_HW_MSG_INT_STATUS_TIM_ERR_TIM_INT vxge_mBIT(7)
+#define VXGE_HW_MSG_INT_STATUS_MSG_EXC_MSG_XT_EXC_INT vxge_mBIT(60)
+#define VXGE_HW_MSG_INT_STATUS_MSG_ERR3_MSG_ERR3_INT vxge_mBIT(61)
+#define VXGE_HW_MSG_INT_STATUS_MSG_ERR2_MSG_ERR2_INT vxge_mBIT(62)
+#define VXGE_HW_MSG_INT_STATUS_MSG_ERR_MSG_ERR_INT vxge_mBIT(63)
+/*0x05208*/ u64 msg_int_mask;
+/*0x05210*/ u64 tim_err_reg;
+#define VXGE_HW_TIM_ERR_REG_TIM_VBLS_SG_ERR vxge_mBIT(4)
+#define VXGE_HW_TIM_ERR_REG_TIM_BMAP_PA_SG_ERR vxge_mBIT(5)
+#define VXGE_HW_TIM_ERR_REG_TIM_BMAP_PB_SG_ERR vxge_mBIT(6)
+#define VXGE_HW_TIM_ERR_REG_TIM_BMAP_MSG_SG_ERR vxge_mBIT(7)
+#define VXGE_HW_TIM_ERR_REG_TIM_VBLS_DB_ERR vxge_mBIT(12)
+#define VXGE_HW_TIM_ERR_REG_TIM_BMAP_PA_DB_ERR vxge_mBIT(13)
+#define VXGE_HW_TIM_ERR_REG_TIM_BMAP_PB_DB_ERR vxge_mBIT(14)
+#define VXGE_HW_TIM_ERR_REG_TIM_BMAP_MSG_DB_ERR vxge_mBIT(15)
+#define VXGE_HW_TIM_ERR_REG_TIM_BMAP_MEM_CNTRL_SM_ERR vxge_mBIT(18)
+#define VXGE_HW_TIM_ERR_REG_TIM_BMAP_MSG_MEM_CNTRL_SM_ERR vxge_mBIT(19)
+#define VXGE_HW_TIM_ERR_REG_TIM_MPIF_PCIWR_ERR vxge_mBIT(20)
+#define VXGE_HW_TIM_ERR_REG_TIM_ROCRC_BMAP_UPDT_FIFO_ERR vxge_mBIT(22)
+#define VXGE_HW_TIM_ERR_REG_TIM_CREATE_BMAPMSG_FIFO_ERR vxge_mBIT(23)
+#define VXGE_HW_TIM_ERR_REG_TIM_ROCRCIF_MISMATCH vxge_mBIT(46)
+#define VXGE_HW_TIM_ERR_REG_TIM_BMAP_MAPPING_VP_ERR(n) vxge_mBIT(n)
+/*0x05218*/ u64 tim_err_mask;
+/*0x05220*/ u64 tim_err_alarm;
+/*0x05228*/ u64 msg_err_reg;
+#define VXGE_HW_MSG_ERR_REG_UP_UXP_WAKE_FSM_INTEGRITY_ERR vxge_mBIT(0)
+#define VXGE_HW_MSG_ERR_REG_MP_MXP_WAKE_FSM_INTEGRITY_ERR vxge_mBIT(1)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_DMQ_DMA_READ_CMD_FSM_INTEGRITY_ERR \
+ vxge_mBIT(2)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_DMQ_DMA_RESP_FSM_INTEGRITY_ERR \
+ vxge_mBIT(3)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_DMQ_OWN_FSM_INTEGRITY_ERR vxge_mBIT(4)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_PDA_ACC_FSM_INTEGRITY_ERR vxge_mBIT(5)
+#define VXGE_HW_MSG_ERR_REG_MP_MXP_PMON_FSM_INTEGRITY_ERR vxge_mBIT(6)
+#define VXGE_HW_MSG_ERR_REG_UP_UXP_PMON_FSM_INTEGRITY_ERR vxge_mBIT(7)
+#define VXGE_HW_MSG_ERR_REG_UP_UXP_DTAG_SG_ERR vxge_mBIT(8)
+#define VXGE_HW_MSG_ERR_REG_UP_UXP_ITAG_SG_ERR vxge_mBIT(10)
+#define VXGE_HW_MSG_ERR_REG_MP_MXP_DTAG_SG_ERR vxge_mBIT(12)
+#define VXGE_HW_MSG_ERR_REG_MP_MXP_ITAG_SG_ERR vxge_mBIT(14)
+#define VXGE_HW_MSG_ERR_REG_UP_UXP_TRACE_SG_ERR vxge_mBIT(16)
+#define VXGE_HW_MSG_ERR_REG_MP_MXP_TRACE_SG_ERR vxge_mBIT(17)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_CMG2MSG_SG_ERR vxge_mBIT(18)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_TXPE2MSG_SG_ERR vxge_mBIT(19)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_RXPE2MSG_SG_ERR vxge_mBIT(20)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_RPE2MSG_SG_ERR vxge_mBIT(21)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_UMQ_SG_ERR vxge_mBIT(26)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_BWR_PF_SG_ERR vxge_mBIT(27)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_DMQ_ECC_SG_ERR vxge_mBIT(29)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_DMA_RESP_ECC_SG_ERR vxge_mBIT(31)
+#define VXGE_HW_MSG_ERR_REG_MSG_XFMDQRY_FSM_INTEGRITY_ERR vxge_mBIT(33)
+#define VXGE_HW_MSG_ERR_REG_MSG_FRMQRY_FSM_INTEGRITY_ERR vxge_mBIT(34)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_UMQ_WRITE_FSM_INTEGRITY_ERR vxge_mBIT(35)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_UMQ_BWR_PF_FSM_INTEGRITY_ERR \
+ vxge_mBIT(36)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_REG_RESP_FIFO_ERR vxge_mBIT(38)
+#define VXGE_HW_MSG_ERR_REG_UP_UXP_DTAG_DB_ERR vxge_mBIT(39)
+#define VXGE_HW_MSG_ERR_REG_UP_UXP_ITAG_DB_ERR vxge_mBIT(41)
+#define VXGE_HW_MSG_ERR_REG_MP_MXP_DTAG_DB_ERR vxge_mBIT(43)
+#define VXGE_HW_MSG_ERR_REG_MP_MXP_ITAG_DB_ERR vxge_mBIT(45)
+#define VXGE_HW_MSG_ERR_REG_UP_UXP_TRACE_DB_ERR vxge_mBIT(47)
+#define VXGE_HW_MSG_ERR_REG_MP_MXP_TRACE_DB_ERR vxge_mBIT(48)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_CMG2MSG_DB_ERR vxge_mBIT(49)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_TXPE2MSG_DB_ERR vxge_mBIT(50)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_RXPE2MSG_DB_ERR vxge_mBIT(51)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_RPE2MSG_DB_ERR vxge_mBIT(52)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_REG_READ_FIFO_ERR vxge_mBIT(53)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_MXP2UXP_FIFO_ERR vxge_mBIT(54)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_KDFC_SIF_FIFO_ERR vxge_mBIT(55)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_CXP2SWIF_FIFO_ERR vxge_mBIT(56)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_UMQ_DB_ERR vxge_mBIT(57)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_BWR_PF_DB_ERR vxge_mBIT(58)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_BWR_SIF_FIFO_ERR vxge_mBIT(59)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_DMQ_ECC_DB_ERR vxge_mBIT(60)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_DMA_READ_FIFO_ERR vxge_mBIT(61)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_DMA_RESP_ECC_DB_ERR vxge_mBIT(62)
+#define VXGE_HW_MSG_ERR_REG_MSG_QUE_UXP2MXP_FIFO_ERR vxge_mBIT(63)
+/*0x05230*/ u64 msg_err_mask;
+/*0x05238*/ u64 msg_err_alarm;
+ u8 unused05340[0x05340-0x05240];
+
+/*0x05340*/ u64 msg_exc_reg;
+#define VXGE_HW_MSG_EXC_REG_MP_MXP_CAUSE_INFO_INT vxge_mBIT(50)
+#define VXGE_HW_MSG_EXC_REG_MP_MXP_CAUSE_CRIT_INT vxge_mBIT(51)
+#define VXGE_HW_MSG_EXC_REG_UP_UXP_CAUSE_INFO_INT vxge_mBIT(54)
+#define VXGE_HW_MSG_EXC_REG_UP_UXP_CAUSE_CRIT_INT vxge_mBIT(55)
+#define VXGE_HW_MSG_EXC_REG_MP_MXP_SERR vxge_mBIT(62)
+#define VXGE_HW_MSG_EXC_REG_UP_UXP_SERR vxge_mBIT(63)
+/*0x05348*/ u64 msg_exc_mask;
+/*0x05350*/ u64 msg_exc_alarm;
+/*0x05358*/ u64 msg_exc_cause;
+#define VXGE_HW_MSG_EXC_CAUSE_MP_MXP(val) vxge_vBIT(val, 0, 32)
+#define VXGE_HW_MSG_EXC_CAUSE_UP_UXP(val) vxge_vBIT(val, 32, 32)
+ u8 unused05368[0x05380-0x05360];
+
+/*0x05380*/ u64 msg_err2_reg;
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_CMG2MSG_DISPATCH_FSM_INTEGRITY_ERR \
+ vxge_mBIT(0)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_DMQ_DISPATCH_FSM_INTEGRITY_ERR \
+ vxge_mBIT(1)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_SWIF_DISPATCH_FSM_INTEGRITY_ERR \
+ vxge_mBIT(2)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_PIC_WRITE_FSM_INTEGRITY_ERR \
+ vxge_mBIT(3)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_SWIFREG_FSM_INTEGRITY_ERR vxge_mBIT(4)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_TIM_WRITE_FSM_INTEGRITY_ERR \
+ vxge_mBIT(5)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_UMQ_TA_FSM_INTEGRITY_ERR vxge_mBIT(6)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_TXPE_TA_FSM_INTEGRITY_ERR vxge_mBIT(7)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_RXPE_TA_FSM_INTEGRITY_ERR vxge_mBIT(8)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_SWIF_TA_FSM_INTEGRITY_ERR vxge_mBIT(9)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_DMA_TA_FSM_INTEGRITY_ERR vxge_mBIT(10)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_CP_TA_FSM_INTEGRITY_ERR vxge_mBIT(11)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA16_FSM_INTEGRITY_ERR \
+ vxge_mBIT(12)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA15_FSM_INTEGRITY_ERR \
+ vxge_mBIT(13)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA14_FSM_INTEGRITY_ERR \
+ vxge_mBIT(14)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA13_FSM_INTEGRITY_ERR \
+ vxge_mBIT(15)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA12_FSM_INTEGRITY_ERR \
+ vxge_mBIT(16)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA11_FSM_INTEGRITY_ERR \
+ vxge_mBIT(17)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA10_FSM_INTEGRITY_ERR \
+ vxge_mBIT(18)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA9_FSM_INTEGRITY_ERR \
+ vxge_mBIT(19)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA8_FSM_INTEGRITY_ERR \
+ vxge_mBIT(20)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA7_FSM_INTEGRITY_ERR \
+ vxge_mBIT(21)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA6_FSM_INTEGRITY_ERR \
+ vxge_mBIT(22)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA5_FSM_INTEGRITY_ERR \
+ vxge_mBIT(23)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA4_FSM_INTEGRITY_ERR \
+ vxge_mBIT(24)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA3_FSM_INTEGRITY_ERR \
+ vxge_mBIT(25)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA2_FSM_INTEGRITY_ERR \
+ vxge_mBIT(26)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA1_FSM_INTEGRITY_ERR \
+ vxge_mBIT(27)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_LONGTERMUMQ_TA0_FSM_INTEGRITY_ERR \
+ vxge_mBIT(28)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_FBMC_OWN_FSM_INTEGRITY_ERR vxge_mBIT(29)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_TXPE2MSG_DISPATCH_FSM_INTEGRITY_ERR \
+ vxge_mBIT(30)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_RXPE2MSG_DISPATCH_FSM_INTEGRITY_ERR \
+ vxge_mBIT(31)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_RPE2MSG_DISPATCH_FSM_INTEGRITY_ERR \
+ vxge_mBIT(32)
+#define VXGE_HW_MSG_ERR2_REG_MP_MP_PIFT_IF_CREDIT_CNT_ERR vxge_mBIT(33)
+#define VXGE_HW_MSG_ERR2_REG_UP_UP_PIFT_IF_CREDIT_CNT_ERR vxge_mBIT(34)
+#define VXGE_HW_MSG_ERR2_REG_MSG_QUE_UMQ2PIC_CMD_FIFO_ERR vxge_mBIT(62)
+#define VXGE_HW_MSG_ERR2_REG_TIM_TIM2MSG_CMD_FIFO_ERR vxge_mBIT(63)
+/*0x05388*/ u64 msg_err2_mask;
+/*0x05390*/ u64 msg_err2_alarm;
+/*0x05398*/ u64 msg_err3_reg;
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_SG_ERR0 vxge_mBIT(0)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_SG_ERR1 vxge_mBIT(1)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_SG_ERR2 vxge_mBIT(2)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_SG_ERR3 vxge_mBIT(3)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_SG_ERR4 vxge_mBIT(4)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_SG_ERR5 vxge_mBIT(5)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_SG_ERR6 vxge_mBIT(6)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_SG_ERR7 vxge_mBIT(7)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_ICACHE_SG_ERR0 vxge_mBIT(8)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_ICACHE_SG_ERR1 vxge_mBIT(9)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_SG_ERR0 vxge_mBIT(16)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_SG_ERR1 vxge_mBIT(17)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_SG_ERR2 vxge_mBIT(18)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_SG_ERR3 vxge_mBIT(19)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_SG_ERR4 vxge_mBIT(20)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_SG_ERR5 vxge_mBIT(21)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_SG_ERR6 vxge_mBIT(22)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_SG_ERR7 vxge_mBIT(23)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_ICACHE_SG_ERR0 vxge_mBIT(24)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_ICACHE_SG_ERR1 vxge_mBIT(25)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_DB_ERR0 vxge_mBIT(32)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_DB_ERR1 vxge_mBIT(33)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_DB_ERR2 vxge_mBIT(34)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_DB_ERR3 vxge_mBIT(35)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_DB_ERR4 vxge_mBIT(36)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_DB_ERR5 vxge_mBIT(37)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_DB_ERR6 vxge_mBIT(38)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_DCACHE_DB_ERR7 vxge_mBIT(39)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_ICACHE_DB_ERR0 vxge_mBIT(40)
+#define VXGE_HW_MSG_ERR3_REG_UP_UXP_ICACHE_DB_ERR1 vxge_mBIT(41)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_DB_ERR0 vxge_mBIT(48)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_DB_ERR1 vxge_mBIT(49)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_DB_ERR2 vxge_mBIT(50)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_DB_ERR3 vxge_mBIT(51)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_DB_ERR4 vxge_mBIT(52)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_DB_ERR5 vxge_mBIT(53)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_DB_ERR6 vxge_mBIT(54)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_DCACHE_DB_ERR7 vxge_mBIT(55)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_ICACHE_DB_ERR0 vxge_mBIT(56)
+#define VXGE_HW_MSG_ERR3_REG_MP_MXP_ICACHE_DB_ERR1 vxge_mBIT(57)
+/*0x053a0*/ u64 msg_err3_mask;
+/*0x053a8*/ u64 msg_err3_alarm;
+ u8 unused05600[0x05600-0x053b0];
+
+/*0x05600*/ u64 fau_gen_err_reg;
+#define VXGE_HW_FAU_GEN_ERR_REG_FMPF_PORT0_PERMANENT_STOP vxge_mBIT(3)
+#define VXGE_HW_FAU_GEN_ERR_REG_FMPF_PORT1_PERMANENT_STOP vxge_mBIT(7)
+#define VXGE_HW_FAU_GEN_ERR_REG_FMPF_PORT2_PERMANENT_STOP vxge_mBIT(11)
+#define VXGE_HW_FAU_GEN_ERR_REG_FALR_AUTO_LRO_NOTIFICATION vxge_mBIT(15)
+/*0x05608*/ u64 fau_gen_err_mask;
+/*0x05610*/ u64 fau_gen_err_alarm;
+/*0x05618*/ u64 fau_ecc_err_reg;
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_PORT0_FAU_MAC2F_N_SG_ERR vxge_mBIT(0)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_PORT0_FAU_MAC2F_N_DB_ERR vxge_mBIT(1)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_PORT0_FAU_MAC2F_W_SG_ERR(val) \
+ vxge_vBIT(val, 2, 2)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_PORT0_FAU_MAC2F_W_DB_ERR(val) \
+ vxge_vBIT(val, 4, 2)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_PORT1_FAU_MAC2F_N_SG_ERR vxge_mBIT(6)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_PORT1_FAU_MAC2F_N_DB_ERR vxge_mBIT(7)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_PORT1_FAU_MAC2F_W_SG_ERR(val) \
+ vxge_vBIT(val, 8, 2)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_PORT1_FAU_MAC2F_W_DB_ERR(val) \
+ vxge_vBIT(val, 10, 2)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_PORT2_FAU_MAC2F_N_SG_ERR vxge_mBIT(12)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_PORT2_FAU_MAC2F_N_DB_ERR vxge_mBIT(13)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_PORT2_FAU_MAC2F_W_SG_ERR(val) \
+ vxge_vBIT(val, 14, 2)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_PORT2_FAU_MAC2F_W_DB_ERR(val) \
+ vxge_vBIT(val, 16, 2)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_FAU_XFMD_INS_SG_ERR(val) \
+ vxge_vBIT(val, 18, 2)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAU_FAU_XFMD_INS_DB_ERR(val) \
+ vxge_vBIT(val, 20, 2)
+#define VXGE_HW_FAU_ECC_ERR_REG_FAUJ_FAU_FSM_ERR vxge_mBIT(31)
+/*0x05620*/ u64 fau_ecc_err_mask;
+/*0x05628*/ u64 fau_ecc_err_alarm;
+ u8 unused05658[0x05658-0x05630];
+/*0x05658*/ u64 fau_pa_cfg;
+#define VXGE_HW_FAU_PA_CFG_REPL_L4_COMP_CSUM vxge_mBIT(3)
+#define VXGE_HW_FAU_PA_CFG_REPL_L3_INCL_CF vxge_mBIT(7)
+#define VXGE_HW_FAU_PA_CFG_REPL_L3_COMP_CSUM vxge_mBIT(11)
+ u8 unused05668[0x05668-0x05660];
+
+/*0x05668*/ u64 dbg_stats_fau_rx_path;
+#define VXGE_HW_DBG_STATS_FAU_RX_PATH_RX_PERMITTED_FRMS(val) \
+ vxge_vBIT(val, 32, 32)
+ u8 unused056c0[0x056c0-0x05670];
+
+/*0x056c0*/ u64 fau_lag_cfg;
+#define VXGE_HW_FAU_LAG_CFG_COLL_ALG(val) vxge_vBIT(val, 2, 2)
+#define VXGE_HW_FAU_LAG_CFG_INCR_RX_AGGR_STATS vxge_mBIT(7)
+ u8 unused05800[0x05800-0x056c8];
+
+/*0x05800*/ u64 tpa_int_status;
+#define VXGE_HW_TPA_INT_STATUS_ORP_ERR_ORP_INT vxge_mBIT(15)
+#define VXGE_HW_TPA_INT_STATUS_PTM_ALARM_PTM_INT vxge_mBIT(23)
+#define VXGE_HW_TPA_INT_STATUS_TPA_ERROR_TPA_INT vxge_mBIT(31)
+/*0x05808*/ u64 tpa_int_mask;
+/*0x05810*/ u64 orp_err_reg;
+#define VXGE_HW_ORP_ERR_REG_ORP_FIFO_SG_ERR vxge_mBIT(3)
+#define VXGE_HW_ORP_ERR_REG_ORP_FIFO_DB_ERR vxge_mBIT(7)
+#define VXGE_HW_ORP_ERR_REG_ORP_XFMD_FIFO_UFLOW_ERR vxge_mBIT(11)
+#define VXGE_HW_ORP_ERR_REG_ORP_FRM_FIFO_UFLOW_ERR vxge_mBIT(15)
+#define VXGE_HW_ORP_ERR_REG_ORP_XFMD_RCV_FSM_ERR vxge_mBIT(19)
+#define VXGE_HW_ORP_ERR_REG_ORP_OUTREAD_FSM_ERR vxge_mBIT(23)
+#define VXGE_HW_ORP_ERR_REG_ORP_OUTQEM_FSM_ERR vxge_mBIT(27)
+#define VXGE_HW_ORP_ERR_REG_ORP_XFMD_RCV_SHADOW_ERR vxge_mBIT(31)
+#define VXGE_HW_ORP_ERR_REG_ORP_OUTREAD_SHADOW_ERR vxge_mBIT(35)
+#define VXGE_HW_ORP_ERR_REG_ORP_OUTQEM_SHADOW_ERR vxge_mBIT(39)
+#define VXGE_HW_ORP_ERR_REG_ORP_OUTFRM_SHADOW_ERR vxge_mBIT(43)
+#define VXGE_HW_ORP_ERR_REG_ORP_OPTPRS_SHADOW_ERR vxge_mBIT(47)
+/*0x05818*/ u64 orp_err_mask;
+/*0x05820*/ u64 orp_err_alarm;
+/*0x05828*/ u64 ptm_alarm_reg;
+#define VXGE_HW_PTM_ALARM_REG_PTM_RDCTRL_SYNC_ERR vxge_mBIT(3)
+#define VXGE_HW_PTM_ALARM_REG_PTM_RDCTRL_FIFO_ERR vxge_mBIT(7)
+#define VXGE_HW_PTM_ALARM_REG_XFMD_RD_FIFO_ERR vxge_mBIT(11)
+#define VXGE_HW_PTM_ALARM_REG_WDE2MSR_WR_FIFO_ERR vxge_mBIT(15)
+#define VXGE_HW_PTM_ALARM_REG_PTM_FRMM_ECC_DB_ERR(val) vxge_vBIT(val, 18, 2)
+#define VXGE_HW_PTM_ALARM_REG_PTM_FRMM_ECC_SG_ERR(val) vxge_vBIT(val, 22, 2)
+/*0x05830*/ u64 ptm_alarm_mask;
+/*0x05838*/ u64 ptm_alarm_alarm;
+/*0x05840*/ u64 tpa_error_reg;
+#define VXGE_HW_TPA_ERROR_REG_TPA_FSM_ERR_ALARM vxge_mBIT(3)
+#define VXGE_HW_TPA_ERROR_REG_TPA_TPA_DA_LKUP_PRT0_DB_ERR vxge_mBIT(7)
+#define VXGE_HW_TPA_ERROR_REG_TPA_TPA_DA_LKUP_PRT0_SG_ERR vxge_mBIT(11)
+/*0x05848*/ u64 tpa_error_mask;
+/*0x05850*/ u64 tpa_error_alarm;
+/*0x05858*/ u64 tpa_global_cfg;
+#define VXGE_HW_TPA_GLOBAL_CFG_SUPPORT_SNAP_AB_N vxge_mBIT(7)
+#define VXGE_HW_TPA_GLOBAL_CFG_ECC_ENABLE_N vxge_mBIT(35)
+ u8 unused05868[0x05870-0x05860];
+
+/*0x05870*/ u64 ptm_ecc_cfg;
+#define VXGE_HW_PTM_ECC_CFG_PTM_FRMM_ECC_EN_N vxge_mBIT(3)
+/*0x05878*/ u64 ptm_phase_cfg;
+#define VXGE_HW_PTM_PHASE_CFG_FRMM_WR_PHASE_EN vxge_mBIT(3)
+#define VXGE_HW_PTM_PHASE_CFG_FRMM_RD_PHASE_EN vxge_mBIT(7)
+ u8 unused05898[0x05898-0x05880];
+
+/*0x05898*/ u64 dbg_stats_tpa_tx_path;
+#define VXGE_HW_DBG_STATS_TPA_TX_PATH_TX_PERMITTED_FRMS(val) \
+ vxge_vBIT(val, 32, 32)
+ u8 unused05900[0x05900-0x058a0];
+
+/*0x05900*/ u64 tmac_int_status;
+#define VXGE_HW_TMAC_INT_STATUS_TXMAC_GEN_ERR_TXMAC_GEN_INT vxge_mBIT(3)
+#define VXGE_HW_TMAC_INT_STATUS_TXMAC_ECC_ERR_TXMAC_ECC_INT vxge_mBIT(7)
+/*0x05908*/ u64 tmac_int_mask;
+/*0x05910*/ u64 txmac_gen_err_reg;
+#define VXGE_HW_TXMAC_GEN_ERR_REG_TMACJ_PERMANENT_STOP vxge_mBIT(3)
+#define VXGE_HW_TXMAC_GEN_ERR_REG_TMACJ_NO_VALID_VSPORT vxge_mBIT(7)
+/*0x05918*/ u64 txmac_gen_err_mask;
+/*0x05920*/ u64 txmac_gen_err_alarm;
+/*0x05928*/ u64 txmac_ecc_err_reg;
+#define VXGE_HW_TXMAC_ECC_ERR_REG_TMACJ_TMAC_TPA2MAC_SG_ERR vxge_mBIT(3)
+#define VXGE_HW_TXMAC_ECC_ERR_REG_TMACJ_TMAC_TPA2MAC_DB_ERR vxge_mBIT(7)
+#define VXGE_HW_TXMAC_ECC_ERR_REG_TMACJ_TMAC_TPA2M_SB_SG_ERR vxge_mBIT(11)
+#define VXGE_HW_TXMAC_ECC_ERR_REG_TMACJ_TMAC_TPA2M_SB_DB_ERR vxge_mBIT(15)
+#define VXGE_HW_TXMAC_ECC_ERR_REG_TMACJ_TMAC_TPA2M_DA_SG_ERR vxge_mBIT(19)
+#define VXGE_HW_TXMAC_ECC_ERR_REG_TMACJ_TMAC_TPA2M_DA_DB_ERR vxge_mBIT(23)
+#define VXGE_HW_TXMAC_ECC_ERR_REG_TMAC_TMAC_PORT0_FSM_ERR vxge_mBIT(27)
+#define VXGE_HW_TXMAC_ECC_ERR_REG_TMAC_TMAC_PORT1_FSM_ERR vxge_mBIT(31)
+#define VXGE_HW_TXMAC_ECC_ERR_REG_TMAC_TMAC_PORT2_FSM_ERR vxge_mBIT(35)
+#define VXGE_HW_TXMAC_ECC_ERR_REG_TMACJ_TMACJ_FSM_ERR vxge_mBIT(39)
+/*0x05930*/ u64 txmac_ecc_err_mask;
+/*0x05938*/ u64 txmac_ecc_err_alarm;
+ u8 unused05978[0x05978-0x05940];
+
+/*0x05978*/ u64 dbg_stat_tx_any_frms;
+#define VXGE_HW_DBG_STAT_TX_ANY_FRMS_PORT0_TX_ANY_FRMS(val) vxge_vBIT(val, 0, 8)
+#define VXGE_HW_DBG_STAT_TX_ANY_FRMS_PORT1_TX_ANY_FRMS(val) vxge_vBIT(val, 8, 8)
+#define VXGE_HW_DBG_STAT_TX_ANY_FRMS_PORT2_TX_ANY_FRMS(val) \
+ vxge_vBIT(val, 16, 8)
+ u8 unused059a0[0x059a0-0x05980];
+
+/*0x059a0*/ u64 txmac_link_util_port[3];
+#define VXGE_HW_TXMAC_LINK_UTIL_PORT_TMAC_TMAC_UTILIZATION(val) \
+ vxge_vBIT(val, 1, 7)
+#define VXGE_HW_TXMAC_LINK_UTIL_PORT_TMAC_UTIL_CFG(val) vxge_vBIT(val, 8, 4)
+#define VXGE_HW_TXMAC_LINK_UTIL_PORT_TMAC_TMAC_FRAC_UTIL(val) \
+ vxge_vBIT(val, 12, 4)
+#define VXGE_HW_TXMAC_LINK_UTIL_PORT_TMAC_PKT_WEIGHT(val) vxge_vBIT(val, 16, 4)
+#define VXGE_HW_TXMAC_LINK_UTIL_PORT_TMAC_TMAC_SCALE_FACTOR vxge_mBIT(23)
+/*0x059b8*/ u64 txmac_cfg0_port[3];
+#define VXGE_HW_TXMAC_CFG0_PORT_TMAC_EN vxge_mBIT(3)
+#define VXGE_HW_TXMAC_CFG0_PORT_APPEND_PAD vxge_mBIT(7)
+#define VXGE_HW_TXMAC_CFG0_PORT_PAD_BYTE(val) vxge_vBIT(val, 8, 8)
+/*0x059d0*/ u64 txmac_cfg1_port[3];
+#define VXGE_HW_TXMAC_CFG1_PORT_AVG_IPG(val) vxge_vBIT(val, 40, 8)
+/*0x059e8*/ u64 txmac_status_port[3];
+#define VXGE_HW_TXMAC_STATUS_PORT_TMAC_TX_FRM_SENT vxge_mBIT(3)
+ u8 unused05a20[0x05a20-0x05a00];
+
+/*0x05a20*/ u64 lag_distrib_dest;
+#define VXGE_HW_LAG_DISTRIB_DEST_MAP_VPATH(n) vxge_mBIT(n)
+/*0x05a28*/ u64 lag_marker_cfg;
+#define VXGE_HW_LAG_MARKER_CFG_GEN_RCVR_EN vxge_mBIT(3)
+#define VXGE_HW_LAG_MARKER_CFG_RESP_EN vxge_mBIT(7)
+#define VXGE_HW_LAG_MARKER_CFG_RESP_TIMEOUT(val) vxge_vBIT(val, 16, 16)
+#define VXGE_HW_LAG_MARKER_CFG_SLOW_PROTO_MRKR_MIN_INTERVAL(val) \
+ vxge_vBIT(val, 32, 16)
+#define VXGE_HW_LAG_MARKER_CFG_THROTTLE_MRKR_RESP vxge_mBIT(51)
+/*0x05a30*/ u64 lag_tx_cfg;
+#define VXGE_HW_LAG_TX_CFG_INCR_TX_AGGR_STATS vxge_mBIT(3)
+#define VXGE_HW_LAG_TX_CFG_DISTRIB_ALG_SEL(val) vxge_vBIT(val, 6, 2)
+#define VXGE_HW_LAG_TX_CFG_DISTRIB_REMAP_IF_FAIL vxge_mBIT(11)
+#define VXGE_HW_LAG_TX_CFG_COLL_MAX_DELAY(val) vxge_vBIT(val, 16, 16)
+/*0x05a38*/ u64 lag_tx_status;
+#define VXGE_HW_LAG_TX_STATUS_TLAG_TIMER_VAL_EMPTIED_LINK(val) \
+ vxge_vBIT(val, 0, 8)
+#define VXGE_HW_LAG_TX_STATUS_TLAG_TIMER_VAL_SLOW_PROTO_MRKR(val) \
+ vxge_vBIT(val, 8, 8)
+#define VXGE_HW_LAG_TX_STATUS_TLAG_TIMER_VAL_SLOW_PROTO_MRKRRESP(val) \
+ vxge_vBIT(val, 16, 8)
+ u8 unused05d48[0x05d48-0x05a40];
+
+/*0x05d48*/ u64 srpcim_to_mrpcim_vplane_rmsg[17];
+#define \
+VXGE_HAL_SRPCIM_TO_MRPCIM_VPLANE_RMSG_SWIF_SRPCIM_TO_MRPCIM_VPLANE_RMSG(val)\
+ vxge_vBIT(val, 0, 64)
+ u8 unused06420[0x06420-0x05dd0];
+
+/*0x06420*/ u64 mrpcim_to_srpcim_vplane_wmsg[17];
+#define VXGE_HW_MRPCIM_TO_SRPCIM_VPLANE_WMSG_MRPCIM_TO_SRPCIM_VPLANE_WMSG(val) \
+ vxge_vBIT(val, 0, 64)
+/*0x064a8*/ u64 mrpcim_to_srpcim_vplane_wmsg_trig[17];
+
+/*0x06530*/ u64 debug_stats0;
+#define VXGE_HW_DEBUG_STATS0_RSTDROP_MSG(val) vxge_vBIT(val, 0, 32)
+#define VXGE_HW_DEBUG_STATS0_RSTDROP_CPL(val) vxge_vBIT(val, 32, 32)
+/*0x06538*/ u64 debug_stats1;
+#define VXGE_HW_DEBUG_STATS1_RSTDROP_CLIENT0(val) vxge_vBIT(val, 0, 32)
+#define VXGE_HW_DEBUG_STATS1_RSTDROP_CLIENT1(val) vxge_vBIT(val, 32, 32)
+/*0x06540*/ u64 debug_stats2;
+#define VXGE_HW_DEBUG_STATS2_RSTDROP_CLIENT2(val) vxge_vBIT(val, 0, 32)
+/*0x06548*/ u64 debug_stats3_vplane[17];
+#define VXGE_HW_DEBUG_STATS3_VPLANE_DEPL_PH(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_DEBUG_STATS3_VPLANE_DEPL_NPH(val) vxge_vBIT(val, 16, 16)
+#define VXGE_HW_DEBUG_STATS3_VPLANE_DEPL_CPLH(val) vxge_vBIT(val, 32, 16)
+/*0x065d0*/ u64 debug_stats4_vplane[17];
+#define VXGE_HW_DEBUG_STATS4_VPLANE_DEPL_PD(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_DEBUG_STATS4_VPLANE_DEPL_NPD(val) vxge_vBIT(val, 16, 16)
+#define VXGE_HW_DEBUG_STATS4_VPLANE_DEPL_CPLD(val) vxge_vBIT(val, 32, 16)
+
+ u8 unused07000[0x07000-0x06658];
+
+/*0x07000*/ u64 mrpcim_general_int_status;
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_PIC_INT vxge_mBIT(0)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_PCI_INT vxge_mBIT(1)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_RTDMA_INT vxge_mBIT(2)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_WRDMA_INT vxge_mBIT(3)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_G3CMCT_INT vxge_mBIT(4)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_GCMG1_INT vxge_mBIT(5)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_GCMG2_INT vxge_mBIT(6)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_GCMG3_INT vxge_mBIT(7)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_G3CMIFL_INT vxge_mBIT(8)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_G3CMIFU_INT vxge_mBIT(9)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_PCMG1_INT vxge_mBIT(10)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_PCMG2_INT vxge_mBIT(11)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_PCMG3_INT vxge_mBIT(12)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_XMAC_INT vxge_mBIT(13)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_RXMAC_INT vxge_mBIT(14)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_TMAC_INT vxge_mBIT(15)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_G3FBIF_INT vxge_mBIT(16)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_FBMC_INT vxge_mBIT(17)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_G3FBCT_INT vxge_mBIT(18)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_TPA_INT vxge_mBIT(19)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_DRBELL_INT vxge_mBIT(20)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_ONE_INT vxge_mBIT(21)
+#define VXGE_HW_MRPCIM_GENERAL_INT_STATUS_MSG_INT vxge_mBIT(22)
+/*0x07008*/ u64 mrpcim_general_int_mask;
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_PIC_INT vxge_mBIT(0)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_PCI_INT vxge_mBIT(1)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_RTDMA_INT vxge_mBIT(2)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_WRDMA_INT vxge_mBIT(3)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_G3CMCT_INT vxge_mBIT(4)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_GCMG1_INT vxge_mBIT(5)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_GCMG2_INT vxge_mBIT(6)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_GCMG3_INT vxge_mBIT(7)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_G3CMIFL_INT vxge_mBIT(8)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_G3CMIFU_INT vxge_mBIT(9)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_PCMG1_INT vxge_mBIT(10)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_PCMG2_INT vxge_mBIT(11)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_PCMG3_INT vxge_mBIT(12)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_XMAC_INT vxge_mBIT(13)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_RXMAC_INT vxge_mBIT(14)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_TMAC_INT vxge_mBIT(15)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_G3FBIF_INT vxge_mBIT(16)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_FBMC_INT vxge_mBIT(17)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_G3FBCT_INT vxge_mBIT(18)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_TPA_INT vxge_mBIT(19)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_DRBELL_INT vxge_mBIT(20)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_ONE_INT vxge_mBIT(21)
+#define VXGE_HW_MRPCIM_GENERAL_INT_MASK_MSG_INT vxge_mBIT(22)
+/*0x07010*/ u64 mrpcim_ppif_int_status;
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_INI_ERRORS_INI_INT vxge_mBIT(3)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_DMA_ERRORS_DMA_INT vxge_mBIT(7)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_TGT_ERRORS_TGT_INT vxge_mBIT(11)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_CONFIG_ERRORS_CONFIG_INT vxge_mBIT(15)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_CRDT_INT vxge_mBIT(19)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_PLL_ERRORS_PLL_INT vxge_mBIT(27)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE0_CRD_INT_VPLANE0_INT\
+ vxge_mBIT(31)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE1_CRD_INT_VPLANE1_INT\
+ vxge_mBIT(32)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE2_CRD_INT_VPLANE2_INT\
+ vxge_mBIT(33)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE3_CRD_INT_VPLANE3_INT\
+ vxge_mBIT(34)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE4_CRD_INT_VPLANE4_INT\
+ vxge_mBIT(35)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE5_CRD_INT_VPLANE5_INT\
+ vxge_mBIT(36)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE6_CRD_INT_VPLANE6_INT\
+ vxge_mBIT(37)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE7_CRD_INT_VPLANE7_INT\
+ vxge_mBIT(38)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE8_CRD_INT_VPLANE8_INT\
+ vxge_mBIT(39)
+#define VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE9_CRD_INT_VPLANE9_INT\
+ vxge_mBIT(40)
+#define \
+VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE10_CRD_INT_VPLANE10_INT \
+ vxge_mBIT(41)
+#define \
+VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE11_CRD_INT_VPLANE11_INT \
+ vxge_mBIT(42)
+#define \
+VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE12_CRD_INT_VPLANE12_INT \
+ vxge_mBIT(43)
+#define \
+VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE13_CRD_INT_VPLANE13_INT \
+ vxge_mBIT(44)
+#define \
+VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE14_CRD_INT_VPLANE14_INT \
+ vxge_mBIT(45)
+#define \
+VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE15_CRD_INT_VPLANE15_INT \
+ vxge_mBIT(46)
+#define \
+VXGE_HW_MRPCIM_PPIF_INT_STATUS_CRDT_ERRORS_VPLANE16_CRD_INT_VPLANE16_INT \
+ vxge_mBIT(47)
+#define \
+VXGE_HW_MRPCIM_PPIF_INT_STATUS_VPATH_TO_MRPCIM_ALARM_VPATH_TO_MRPCIM_ALARM_INT \
+ vxge_mBIT(55)
+/*0x07018*/ u64 mrpcim_ppif_int_mask;
+ u8 unused07028[0x07028-0x07020];
+
+/*0x07028*/ u64 ini_errors_reg;
+#define VXGE_HW_INI_ERRORS_REG_SCPL_CPL_TIMEOUT_UNUSED_TAG vxge_mBIT(3)
+#define VXGE_HW_INI_ERRORS_REG_SCPL_CPL_TIMEOUT vxge_mBIT(7)
+#define VXGE_HW_INI_ERRORS_REG_DCPL_FSM_ERR vxge_mBIT(11)
+#define VXGE_HW_INI_ERRORS_REG_DCPL_POISON vxge_mBIT(12)
+#define VXGE_HW_INI_ERRORS_REG_DCPL_UNSUPPORTED vxge_mBIT(15)
+#define VXGE_HW_INI_ERRORS_REG_DCPL_ABORT vxge_mBIT(19)
+#define VXGE_HW_INI_ERRORS_REG_INI_TLP_ABORT vxge_mBIT(23)
+#define VXGE_HW_INI_ERRORS_REG_INI_DLLP_ABORT vxge_mBIT(27)
+#define VXGE_HW_INI_ERRORS_REG_INI_ECRC_ERR vxge_mBIT(31)
+#define VXGE_HW_INI_ERRORS_REG_INI_BUF_DB_ERR vxge_mBIT(35)
+#define VXGE_HW_INI_ERRORS_REG_INI_BUF_SG_ERR vxge_mBIT(39)
+#define VXGE_HW_INI_ERRORS_REG_INI_DATA_OVERFLOW vxge_mBIT(43)
+#define VXGE_HW_INI_ERRORS_REG_INI_HDR_OVERFLOW vxge_mBIT(47)
+#define VXGE_HW_INI_ERRORS_REG_INI_MRD_SYS_DROP vxge_mBIT(51)
+#define VXGE_HW_INI_ERRORS_REG_INI_MWR_SYS_DROP vxge_mBIT(55)
+#define VXGE_HW_INI_ERRORS_REG_INI_MRD_CLIENT_DROP vxge_mBIT(59)
+#define VXGE_HW_INI_ERRORS_REG_INI_MWR_CLIENT_DROP vxge_mBIT(63)
+/*0x07030*/ u64 ini_errors_mask;
+/*0x07038*/ u64 ini_errors_alarm;
+/*0x07040*/ u64 dma_errors_reg;
+#define VXGE_HW_DMA_ERRORS_REG_RDARB_FSM_ERR vxge_mBIT(3)
+#define VXGE_HW_DMA_ERRORS_REG_WRARB_FSM_ERR vxge_mBIT(7)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_WRDMA_WR_HDR_OVERFLOW vxge_mBIT(8)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_WRDMA_WR_HDR_UNDERFLOW vxge_mBIT(9)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_WRDMA_WR_DATA_OVERFLOW vxge_mBIT(10)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_WRDMA_WR_DATA_UNDERFLOW vxge_mBIT(11)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_MSG_WR_HDR_OVERFLOW vxge_mBIT(12)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_MSG_WR_HDR_UNDERFLOW vxge_mBIT(13)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_MSG_WR_DATA_OVERFLOW vxge_mBIT(14)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_MSG_WR_DATA_UNDERFLOW vxge_mBIT(15)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_STATS_WR_HDR_OVERFLOW vxge_mBIT(16)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_STATS_WR_HDR_UNDERFLOW vxge_mBIT(17)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_STATS_WR_DATA_OVERFLOW vxge_mBIT(18)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_STATS_WR_DATA_UNDERFLOW vxge_mBIT(19)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_RTDMA_WR_HDR_OVERFLOW vxge_mBIT(20)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_RTDMA_WR_HDR_UNDERFLOW vxge_mBIT(21)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_RTDMA_WR_DATA_OVERFLOW vxge_mBIT(22)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_RTDMA_WR_DATA_UNDERFLOW vxge_mBIT(23)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_WRDMA_RD_HDR_OVERFLOW vxge_mBIT(24)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_WRDMA_RD_HDR_UNDERFLOW vxge_mBIT(25)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_RTDMA_RD_HDR_OVERFLOW vxge_mBIT(28)
+#define VXGE_HW_DMA_ERRORS_REG_DMA_RTDMA_RD_HDR_UNDERFLOW vxge_mBIT(29)
+#define VXGE_HW_DMA_ERRORS_REG_DBLGEN_FSM_ERR vxge_mBIT(32)
+#define VXGE_HW_DMA_ERRORS_REG_DBLGEN_CREDIT_FSM_ERR vxge_mBIT(33)
+#define VXGE_HW_DMA_ERRORS_REG_DBLGEN_DMA_WRR_SM_ERR vxge_mBIT(34)
+/*0x07048*/ u64 dma_errors_mask;
+/*0x07050*/ u64 dma_errors_alarm;
+/*0x07058*/ u64 tgt_errors_reg;
+#define VXGE_HW_TGT_ERRORS_REG_TGT_VENDOR_MSG vxge_mBIT(0)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_MSG_UNLOCK vxge_mBIT(1)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_ILLEGAL_TLP_BE vxge_mBIT(2)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_BOOT_WRITE vxge_mBIT(3)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_PIF_WR_CROSS_QWRANGE vxge_mBIT(4)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_PIF_READ_CROSS_QWRANGE vxge_mBIT(5)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_KDFC_READ vxge_mBIT(6)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_USDC_READ vxge_mBIT(7)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_USDC_WR_CROSS_QWRANGE vxge_mBIT(8)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_MSIX_BEYOND_RANGE vxge_mBIT(9)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_WR_TO_KDFC_POISON vxge_mBIT(10)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_WR_TO_USDC_POISON vxge_mBIT(11)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_WR_TO_PIF_POISON vxge_mBIT(12)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_WR_TO_MSIX_POISON vxge_mBIT(13)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_WR_TO_MRIOV_POISON vxge_mBIT(14)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_NOT_MEM_TLP vxge_mBIT(15)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_UNKNOWN_MEM_TLP vxge_mBIT(16)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_REQ_FSM_ERR vxge_mBIT(17)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_CPL_FSM_ERR vxge_mBIT(18)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_KDFC_PROT_ERR vxge_mBIT(19)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_SWIF_PROT_ERR vxge_mBIT(20)
+#define VXGE_HW_TGT_ERRORS_REG_TGT_MRIOV_MEM_MAP_CFG_ERR vxge_mBIT(21)
+/*0x07060*/ u64 tgt_errors_mask;
+/*0x07068*/ u64 tgt_errors_alarm;
+/*0x07070*/ u64 config_errors_reg;
+#define VXGE_HW_CONFIG_ERRORS_REG_I2C_ILLEGAL_STOP_COND vxge_mBIT(3)
+#define VXGE_HW_CONFIG_ERRORS_REG_I2C_ILLEGAL_START_COND vxge_mBIT(7)
+#define VXGE_HW_CONFIG_ERRORS_REG_I2C_EXP_RD_CNT vxge_mBIT(11)
+#define VXGE_HW_CONFIG_ERRORS_REG_I2C_EXTRA_CYCLE vxge_mBIT(15)
+#define VXGE_HW_CONFIG_ERRORS_REG_I2C_MAIN_FSM_ERR vxge_mBIT(19)
+#define VXGE_HW_CONFIG_ERRORS_REG_I2C_REQ_COLLISION vxge_mBIT(23)
+#define VXGE_HW_CONFIG_ERRORS_REG_I2C_REG_FSM_ERR vxge_mBIT(27)
+#define VXGE_HW_CONFIG_ERRORS_REG_CFGM_I2C_TIMEOUT vxge_mBIT(31)
+#define VXGE_HW_CONFIG_ERRORS_REG_RIC_I2C_TIMEOUT vxge_mBIT(35)
+#define VXGE_HW_CONFIG_ERRORS_REG_CFGM_FSM_ERR vxge_mBIT(39)
+#define VXGE_HW_CONFIG_ERRORS_REG_RIC_FSM_ERR vxge_mBIT(43)
+#define VXGE_HW_CONFIG_ERRORS_REG_PIFM_ILLEGAL_ACCESS vxge_mBIT(47)
+#define VXGE_HW_CONFIG_ERRORS_REG_PIFM_TIMEOUT vxge_mBIT(51)
+#define VXGE_HW_CONFIG_ERRORS_REG_PIFM_FSM_ERR vxge_mBIT(55)
+#define VXGE_HW_CONFIG_ERRORS_REG_PIFM_TO_FSM_ERR vxge_mBIT(59)
+#define VXGE_HW_CONFIG_ERRORS_REG_RIC_RIC_RD_TIMEOUT vxge_mBIT(63)
+/*0x07078*/ u64 config_errors_mask;
+/*0x07080*/ u64 config_errors_alarm;
+ u8 unused07090[0x07090-0x07088];
+
+/*0x07090*/ u64 crdt_errors_reg;
+#define VXGE_HW_CRDT_ERRORS_REG_WRCRDTARB_FSM_ERR vxge_mBIT(11)
+#define VXGE_HW_CRDT_ERRORS_REG_WRCRDTARB_INTCTL_ILLEGAL_CRD_DEAL \
+ vxge_mBIT(15)
+#define VXGE_HW_CRDT_ERRORS_REG_WRCRDTARB_PDA_ILLEGAL_CRD_DEAL vxge_mBIT(19)
+#define VXGE_HW_CRDT_ERRORS_REG_WRCRDTARB_PCI_MSG_ILLEGAL_CRD_DEAL \
+ vxge_mBIT(23)
+#define VXGE_HW_CRDT_ERRORS_REG_RDCRDTARB_FSM_ERR vxge_mBIT(35)
+#define VXGE_HW_CRDT_ERRORS_REG_RDCRDTARB_RDA_ILLEGAL_CRD_DEAL vxge_mBIT(39)
+#define VXGE_HW_CRDT_ERRORS_REG_RDCRDTARB_PDA_ILLEGAL_CRD_DEAL vxge_mBIT(43)
+#define VXGE_HW_CRDT_ERRORS_REG_RDCRDTARB_DBLGEN_ILLEGAL_CRD_DEAL \
+ vxge_mBIT(47)
+/*0x07098*/ u64 crdt_errors_mask;
+/*0x070a0*/ u64 crdt_errors_alarm;
+ u8 unused070b0[0x070b0-0x070a8];
+
+/*0x070b0*/ u64 mrpcim_general_errors_reg;
+#define VXGE_HW_MRPCIM_GENERAL_ERRORS_REG_STATSB_FSM_ERR vxge_mBIT(3)
+#define VXGE_HW_MRPCIM_GENERAL_ERRORS_REG_XGEN_FSM_ERR vxge_mBIT(7)
+#define VXGE_HW_MRPCIM_GENERAL_ERRORS_REG_XMEM_FSM_ERR vxge_mBIT(11)
+#define VXGE_HW_MRPCIM_GENERAL_ERRORS_REG_KDFCCTL_FSM_ERR vxge_mBIT(15)
+#define VXGE_HW_MRPCIM_GENERAL_ERRORS_REG_MRIOVCTL_FSM_ERR vxge_mBIT(19)
+#define VXGE_HW_MRPCIM_GENERAL_ERRORS_REG_SPI_FLSH_ERR vxge_mBIT(23)
+#define VXGE_HW_MRPCIM_GENERAL_ERRORS_REG_SPI_IIC_ACK_ERR vxge_mBIT(27)
+#define VXGE_HW_MRPCIM_GENERAL_ERRORS_REG_SPI_IIC_CHKSUM_ERR vxge_mBIT(31)
+#define VXGE_HW_MRPCIM_GENERAL_ERRORS_REG_INI_SERR_DET vxge_mBIT(35)
+#define VXGE_HW_MRPCIM_GENERAL_ERRORS_REG_INTCTL_MSIX_FSM_ERR vxge_mBIT(39)
+#define VXGE_HW_MRPCIM_GENERAL_ERRORS_REG_INTCTL_MSI_OVERFLOW vxge_mBIT(43)
+#define VXGE_HW_MRPCIM_GENERAL_ERRORS_REG_PPIF_PCI_NOT_FLUSH_DURING_SW_RESET \
+ vxge_mBIT(47)
+#define VXGE_HW_MRPCIM_GENERAL_ERRORS_REG_PPIF_SW_RESET_FSM_ERR vxge_mBIT(51)
+/*0x070b8*/ u64 mrpcim_general_errors_mask;
+/*0x070c0*/ u64 mrpcim_general_errors_alarm;
+ u8 unused070d0[0x070d0-0x070c8];
+
+/*0x070d0*/ u64 pll_errors_reg;
+#define VXGE_HW_PLL_ERRORS_REG_CORE_CMG_PLL_OOL vxge_mBIT(3)
+#define VXGE_HW_PLL_ERRORS_REG_CORE_FB_PLL_OOL vxge_mBIT(7)
+#define VXGE_HW_PLL_ERRORS_REG_CORE_X_PLL_OOL vxge_mBIT(11)
+/*0x070d8*/ u64 pll_errors_mask;
+/*0x070e0*/ u64 pll_errors_alarm;
+/*0x070e8*/ u64 srpcim_to_mrpcim_alarm_reg;
+#define VXGE_HW_SRPCIM_TO_MRPCIM_ALARM_REG_PPIF_SRPCIM_TO_MRPCIM_ALARM(val) \
+ vxge_vBIT(val, 0, 17)
+/*0x070f0*/ u64 srpcim_to_mrpcim_alarm_mask;
+/*0x070f8*/ u64 srpcim_to_mrpcim_alarm_alarm;
+/*0x07100*/ u64 vpath_to_mrpcim_alarm_reg;
+#define VXGE_HW_VPATH_TO_MRPCIM_ALARM_REG_PPIF_VPATH_TO_MRPCIM_ALARM(val) \
+ vxge_vBIT(val, 0, 17)
+/*0x07108*/ u64 vpath_to_mrpcim_alarm_mask;
+/*0x07110*/ u64 vpath_to_mrpcim_alarm_alarm;
+ u8 unused07128[0x07128-0x07118];
+
+/*0x07128*/ u64 crdt_errors_vplane_reg[17];
+#define VXGE_HW_CRDT_ERRORS_VPLANE_REG_WRCRDTARB_P_H_CONSUME_CRDT_ERR \
+ vxge_mBIT(3)
+#define VXGE_HW_CRDT_ERRORS_VPLANE_REG_WRCRDTARB_P_D_CONSUME_CRDT_ERR \
+ vxge_mBIT(7)
+#define VXGE_HW_CRDT_ERRORS_VPLANE_REG_WRCRDTARB_P_H_RETURN_CRDT_ERR \
+ vxge_mBIT(11)
+#define VXGE_HW_CRDT_ERRORS_VPLANE_REG_WRCRDTARB_P_D_RETURN_CRDT_ERR \
+ vxge_mBIT(15)
+#define VXGE_HW_CRDT_ERRORS_VPLANE_REG_RDCRDTARB_NP_H_CONSUME_CRDT_ERR \
+ vxge_mBIT(19)
+#define VXGE_HW_CRDT_ERRORS_VPLANE_REG_RDCRDTARB_NP_H_RETURN_CRDT_ERR \
+ vxge_mBIT(23)
+#define VXGE_HW_CRDT_ERRORS_VPLANE_REG_RDCRDTARB_TAG_CONSUME_TAG_ERR \
+ vxge_mBIT(27)
+#define VXGE_HW_CRDT_ERRORS_VPLANE_REG_RDCRDTARB_TAG_RETURN_TAG_ERR \
+ vxge_mBIT(31)
+/*0x07130*/ u64 crdt_errors_vplane_mask[17];
+/*0x07138*/ u64 crdt_errors_vplane_alarm[17];
+ u8 unused072f0[0x072f0-0x072c0];
+
+/*0x072f0*/ u64 mrpcim_rst_in_prog;
+#define VXGE_HW_MRPCIM_RST_IN_PROG_MRPCIM_RST_IN_PROG vxge_mBIT(7)
+/*0x072f8*/ u64 mrpcim_reg_modified;
+#define VXGE_HW_MRPCIM_REG_MODIFIED_MRPCIM_REG_MODIFIED vxge_mBIT(7)
+
+ u8 unused07378[0x07378-0x07300];
+
+/*0x07378*/ u64 write_arb_pending;
+#define VXGE_HW_WRITE_ARB_PENDING_WRARB_WRDMA vxge_mBIT(3)
+#define VXGE_HW_WRITE_ARB_PENDING_WRARB_RTDMA vxge_mBIT(7)
+#define VXGE_HW_WRITE_ARB_PENDING_WRARB_MSG vxge_mBIT(11)
+#define VXGE_HW_WRITE_ARB_PENDING_WRARB_STATSB vxge_mBIT(15)
+#define VXGE_HW_WRITE_ARB_PENDING_WRARB_INTCTL vxge_mBIT(19)
+/*0x07380*/ u64 read_arb_pending;
+#define VXGE_HW_READ_ARB_PENDING_RDARB_WRDMA vxge_mBIT(3)
+#define VXGE_HW_READ_ARB_PENDING_RDARB_RTDMA vxge_mBIT(7)
+#define VXGE_HW_READ_ARB_PENDING_RDARB_DBLGEN vxge_mBIT(11)
+/*0x07388*/ u64 dmaif_dmadbl_pending;
+#define VXGE_HW_DMAIF_DMADBL_PENDING_DMAIF_WRDMA_WR vxge_mBIT(0)
+#define VXGE_HW_DMAIF_DMADBL_PENDING_DMAIF_WRDMA_RD vxge_mBIT(1)
+#define VXGE_HW_DMAIF_DMADBL_PENDING_DMAIF_RTDMA_WR vxge_mBIT(2)
+#define VXGE_HW_DMAIF_DMADBL_PENDING_DMAIF_RTDMA_RD vxge_mBIT(3)
+#define VXGE_HW_DMAIF_DMADBL_PENDING_DMAIF_MSG_WR vxge_mBIT(4)
+#define VXGE_HW_DMAIF_DMADBL_PENDING_DMAIF_STATS_WR vxge_mBIT(5)
+#define VXGE_HW_DMAIF_DMADBL_PENDING_DBLGEN_IN_PROG(val) \
+ vxge_vBIT(val, 13, 51)
+/*0x07390*/ u64 wrcrdtarb_status0_vplane[17];
+#define VXGE_HW_WRCRDTARB_STATUS0_VPLANE_WRCRDTARB_ABS_AVAIL_P_H(val) \
+ vxge_vBIT(val, 0, 8)
+/*0x07418*/ u64 wrcrdtarb_status1_vplane[17];
+#define VXGE_HW_WRCRDTARB_STATUS1_VPLANE_WRCRDTARB_ABS_AVAIL_P_D(val) \
+ vxge_vBIT(val, 4, 12)
+ u8 unused07500[0x07500-0x074a0];
+
+/*0x07500*/ u64 mrpcim_general_cfg1;
+#define VXGE_HW_MRPCIM_GENERAL_CFG1_CLEAR_SERR vxge_mBIT(7)
+/*0x07508*/ u64 mrpcim_general_cfg2;
+#define VXGE_HW_MRPCIM_GENERAL_CFG2_INS_TX_WR_TD vxge_mBIT(3)
+#define VXGE_HW_MRPCIM_GENERAL_CFG2_INS_TX_RD_TD vxge_mBIT(7)
+#define VXGE_HW_MRPCIM_GENERAL_CFG2_INS_TX_CPL_TD vxge_mBIT(11)
+#define VXGE_HW_MRPCIM_GENERAL_CFG2_INI_TIMEOUT_EN_MWR vxge_mBIT(15)
+#define VXGE_HW_MRPCIM_GENERAL_CFG2_INI_TIMEOUT_EN_MRD vxge_mBIT(19)
+#define VXGE_HW_MRPCIM_GENERAL_CFG2_IGNORE_VPATH_RST_FOR_MSIX vxge_mBIT(23)
+#define VXGE_HW_MRPCIM_GENERAL_CFG2_FLASH_READ_MSB vxge_mBIT(27)
+#define VXGE_HW_MRPCIM_GENERAL_CFG2_DIS_HOST_PIPELINE_WR vxge_mBIT(31)
+#define VXGE_HW_MRPCIM_GENERAL_CFG2_MRPCIM_STATS_ENABLE vxge_mBIT(43)
+#define VXGE_HW_MRPCIM_GENERAL_CFG2_MRPCIM_STATS_MAP_TO_VPATH(val) \
+ vxge_vBIT(val, 47, 5)
+#define VXGE_HW_MRPCIM_GENERAL_CFG2_EN_BLOCK_MSIX_DUE_TO_SERR vxge_mBIT(55)
+#define VXGE_HW_MRPCIM_GENERAL_CFG2_FORCE_SENDING_INTA vxge_mBIT(59)
+#define VXGE_HW_MRPCIM_GENERAL_CFG2_DIS_SWIF_PROT_ON_RDS vxge_mBIT(63)
+/*0x07510*/ u64 mrpcim_general_cfg3;
+#define VXGE_HW_MRPCIM_GENERAL_CFG3_PROTECTION_CA_OR_UNSUPN vxge_mBIT(0)
+#define VXGE_HW_MRPCIM_GENERAL_CFG3_ILLEGAL_RD_CA_OR_UNSUPN vxge_mBIT(3)
+#define VXGE_HW_MRPCIM_GENERAL_CFG3_RD_BYTE_SWAPEN vxge_mBIT(7)
+#define VXGE_HW_MRPCIM_GENERAL_CFG3_RD_BIT_FLIPEN vxge_mBIT(11)
+#define VXGE_HW_MRPCIM_GENERAL_CFG3_WR_BYTE_SWAPEN vxge_mBIT(15)
+#define VXGE_HW_MRPCIM_GENERAL_CFG3_WR_BIT_FLIPEN vxge_mBIT(19)
+#define VXGE_HW_MRPCIM_GENERAL_CFG3_MR_MAX_MVFS(val) vxge_vBIT(val, 20, 16)
+#define VXGE_HW_MRPCIM_GENERAL_CFG3_MR_MVF_TBL_SIZE(val) \
+ vxge_vBIT(val, 36, 16)
+#define VXGE_HW_MRPCIM_GENERAL_CFG3_PF0_SW_RESET_EN vxge_mBIT(55)
+#define VXGE_HW_MRPCIM_GENERAL_CFG3_REG_MODIFIED_CFG(val) vxge_vBIT(val, 56, 2)
+#define VXGE_HW_MRPCIM_GENERAL_CFG3_CPL_ECC_ENABLE_N vxge_mBIT(59)
+#define VXGE_HW_MRPCIM_GENERAL_CFG3_BYPASS_DAISY_CHAIN vxge_mBIT(63)
+/*0x07518*/ u64 mrpcim_stats_start_host_addr;
+#define VXGE_HW_MRPCIM_STATS_START_HOST_ADDR_MRPCIM_STATS_START_HOST_ADDR(val)\
+ vxge_vBIT(val, 0, 57)
+
+ u8 unused07950[0x07950-0x07520];
+
+/*0x07950*/ u64 rdcrdtarb_cfg0;
+#define VXGE_HW_RDCRDTARB_CFG0_RDA_MAX_OUTSTANDING_RDS(val) \
+ vxge_vBIT(val, 18, 6)
+#define VXGE_HW_RDCRDTARB_CFG0_PDA_MAX_OUTSTANDING_RDS(val) \
+ vxge_vBIT(val, 26, 6)
+#define VXGE_HW_RDCRDTARB_CFG0_DBLGEN_MAX_OUTSTANDING_RDS(val) \
+ vxge_vBIT(val, 34, 6)
+#define VXGE_HW_RDCRDTARB_CFG0_WAIT_CNT(val) vxge_vBIT(val, 48, 4)
+#define VXGE_HW_RDCRDTARB_CFG0_MAX_OUTSTANDING_RDS(val) vxge_vBIT(val, 54, 6)
+#define VXGE_HW_RDCRDTARB_CFG0_EN_XON vxge_mBIT(63)
+ u8 unused07be8[0x07be8-0x07958];
+
+/*0x07be8*/ u64 bf_sw_reset;
+#define VXGE_HW_BF_SW_RESET_BF_SW_RESET(val) vxge_vBIT(val, 0, 8)
+/*0x07bf0*/ u64 sw_reset_status;
+#define VXGE_HW_SW_RESET_STATUS_RESET_CMPLT vxge_mBIT(7)
+#define VXGE_HW_SW_RESET_STATUS_INIT_CMPLT vxge_mBIT(15)
+ u8 unused07c20[0x07c20-0x07bf8];
+
+/* 0x07c20 */ u64 sw_reset_cfg1;
+#define VXGE_HW_SW_RESET_CFG1_TYPE vxge_mBIT(0)
+#define VXGE_HW_SW_RESET_CFG1_WAIT_TIME_FOR_FLUSH_PCI(val) \
+ vxge_vBIT(val, 7, 25)
+#define VXGE_HW_SW_RESET_CFG1_SOPR_ASSERT_TIME(val) vxge_vBIT(val, 32, 4)
+#define VXGE_HW_SW_RESET_CFG1_WAIT_TIME_AFTER_RESET(val) \
+ vxge_vBIT(val, 38, 25)
+ u8 unused07d30[0x07d30-0x07c28];
+
+/*0x07d30*/ u64 mrpcim_debug_stats0;
+#define VXGE_HW_MRPCIM_DEBUG_STATS0_INI_WR_DROP(val) vxge_vBIT(val, 0, 32)
+#define VXGE_HW_MRPCIM_DEBUG_STATS0_INI_RD_DROP(val) vxge_vBIT(val, 32, 32)
+/*0x07d38*/ u64 mrpcim_debug_stats1_vplane[17];
+#define VXGE_HW_MRPCIM_DEBUG_STATS1_VPLANE_WRCRDTARB_PH_CRDT_DEPLETED(val) \
+ vxge_vBIT(val, 32, 32)
+/*0x07dc0*/ u64 mrpcim_debug_stats2_vplane[17];
+#define VXGE_HW_MRPCIM_DEBUG_STATS2_VPLANE_WRCRDTARB_PD_CRDT_DEPLETED(val) \
+ vxge_vBIT(val, 32, 32)
+/*0x07e48*/ u64 mrpcim_debug_stats3_vplane[17];
+#define VXGE_HW_MRPCIM_DEBUG_STATS3_VPLANE_RDCRDTARB_NPH_CRDT_DEPLETED(val) \
+ vxge_vBIT(val, 32, 32)
+/*0x07ed0*/ u64 mrpcim_debug_stats4;
+#define VXGE_HW_MRPCIM_DEBUG_STATS4_INI_WR_VPIN_DROP(val) vxge_vBIT(val, 0, 32)
+#define VXGE_HW_MRPCIM_DEBUG_STATS4_INI_RD_VPIN_DROP(val) \
+ vxge_vBIT(val, 32, 32)
+/*0x07ed8*/ u64 genstats_count01;
+#define VXGE_HW_GENSTATS_COUNT01_GENSTATS_COUNT1(val) vxge_vBIT(val, 0, 32)
+#define VXGE_HW_GENSTATS_COUNT01_GENSTATS_COUNT0(val) vxge_vBIT(val, 32, 32)
+/*0x07ee0*/ u64 genstats_count23;
+#define VXGE_HW_GENSTATS_COUNT23_GENSTATS_COUNT3(val) vxge_vBIT(val, 0, 32)
+#define VXGE_HW_GENSTATS_COUNT23_GENSTATS_COUNT2(val) vxge_vBIT(val, 32, 32)
+/*0x07ee8*/ u64 genstats_count4;
+#define VXGE_HW_GENSTATS_COUNT4_GENSTATS_COUNT4(val) vxge_vBIT(val, 32, 32)
+/*0x07ef0*/ u64 genstats_count5;
+#define VXGE_HW_GENSTATS_COUNT5_GENSTATS_COUNT5(val) vxge_vBIT(val, 32, 32)
+
+ u8 unused07f08[0x07f08-0x07ef8];
+
+/*0x07f08*/ u64 genstats_cfg[6];
+#define VXGE_HW_GENSTATS_CFG_DTYPE_SEL(val) vxge_vBIT(val, 3, 5)
+#define VXGE_HW_GENSTATS_CFG_CLIENT_NO_SEL(val) vxge_vBIT(val, 9, 3)
+#define VXGE_HW_GENSTATS_CFG_WR_RD_CPL_SEL(val) vxge_vBIT(val, 14, 2)
+#define VXGE_HW_GENSTATS_CFG_VPATH_SEL(val) vxge_vBIT(val, 31, 17)
+/*0x07f38*/ u64 genstat_64bit_cfg;
+#define VXGE_HW_GENSTAT_64BIT_CFG_EN_FOR_GENSTATS0 vxge_mBIT(3)
+#define VXGE_HW_GENSTAT_64BIT_CFG_EN_FOR_GENSTATS2 vxge_mBIT(7)
+ u8 unused08000[0x08000-0x07f40];
+/*0x08000*/ u64 gcmg3_int_status;
+#define VXGE_HW_GCMG3_INT_STATUS_GSTC_ERR0_GSTC0_INT vxge_mBIT(0)
+#define VXGE_HW_GCMG3_INT_STATUS_GSTC_ERR1_GSTC1_INT vxge_mBIT(1)
+#define VXGE_HW_GCMG3_INT_STATUS_GH2L_ERR0_GH2L0_INT vxge_mBIT(2)
+#define VXGE_HW_GCMG3_INT_STATUS_GHSQ_ERR_GH2L1_INT vxge_mBIT(3)
+#define VXGE_HW_GCMG3_INT_STATUS_GHSQ_ERR2_GH2L2_INT vxge_mBIT(4)
+#define VXGE_HW_GCMG3_INT_STATUS_GH2L_SMERR0_GH2L3_INT vxge_mBIT(5)
+#define VXGE_HW_GCMG3_INT_STATUS_GHSQ_ERR3_GH2L4_INT vxge_mBIT(6)
+/*0x08008*/ u64 gcmg3_int_mask;
+ u8 unused09000[0x09000-0x8010];
+
+/*0x09000*/ u64 g3ifcmd_fb_int_status;
+#define VXGE_HW_G3IFCMD_FB_INT_STATUS_ERR_G3IF_INT vxge_mBIT(0)
+/*0x09008*/ u64 g3ifcmd_fb_int_mask;
+/*0x09010*/ u64 g3ifcmd_fb_err_reg;
+#define VXGE_HW_G3IFCMD_FB_ERR_REG_G3IF_CK_DLL_LOCK vxge_mBIT(6)
+#define VXGE_HW_G3IFCMD_FB_ERR_REG_G3IF_SM_ERR vxge_mBIT(7)
+#define VXGE_HW_G3IFCMD_FB_ERR_REG_G3IF_RWDQS_DLL_LOCK(val) \
+ vxge_vBIT(val, 24, 8)
+#define VXGE_HW_G3IFCMD_FB_ERR_REG_G3IF_IOCAL_FAULT vxge_mBIT(55)
+/*0x09018*/ u64 g3ifcmd_fb_err_mask;
+/*0x09020*/ u64 g3ifcmd_fb_err_alarm;
+
+ u8 unused09400[0x09400-0x09028];
+
+/*0x09400*/ u64 g3ifcmd_cmu_int_status;
+#define VXGE_HW_G3IFCMD_CMU_INT_STATUS_ERR_G3IF_INT vxge_mBIT(0)
+/*0x09408*/ u64 g3ifcmd_cmu_int_mask;
+/*0x09410*/ u64 g3ifcmd_cmu_err_reg;
+#define VXGE_HW_G3IFCMD_CMU_ERR_REG_G3IF_CK_DLL_LOCK vxge_mBIT(6)
+#define VXGE_HW_G3IFCMD_CMU_ERR_REG_G3IF_SM_ERR vxge_mBIT(7)
+#define VXGE_HW_G3IFCMD_CMU_ERR_REG_G3IF_RWDQS_DLL_LOCK(val) \
+ vxge_vBIT(val, 24, 8)
+#define VXGE_HW_G3IFCMD_CMU_ERR_REG_G3IF_IOCAL_FAULT vxge_mBIT(55)
+/*0x09418*/ u64 g3ifcmd_cmu_err_mask;
+/*0x09420*/ u64 g3ifcmd_cmu_err_alarm;
+
+ u8 unused09800[0x09800-0x09428];
+
+/*0x09800*/ u64 g3ifcmd_cml_int_status;
+#define VXGE_HW_G3IFCMD_CML_INT_STATUS_ERR_G3IF_INT vxge_mBIT(0)
+/*0x09808*/ u64 g3ifcmd_cml_int_mask;
+/*0x09810*/ u64 g3ifcmd_cml_err_reg;
+#define VXGE_HW_G3IFCMD_CML_ERR_REG_G3IF_CK_DLL_LOCK vxge_mBIT(6)
+#define VXGE_HW_G3IFCMD_CML_ERR_REG_G3IF_SM_ERR vxge_mBIT(7)
+#define VXGE_HW_G3IFCMD_CML_ERR_REG_G3IF_RWDQS_DLL_LOCK(val) \
+ vxge_vBIT(val, 24, 8)
+#define VXGE_HW_G3IFCMD_CML_ERR_REG_G3IF_IOCAL_FAULT vxge_mBIT(55)
+/*0x09818*/ u64 g3ifcmd_cml_err_mask;
+/*0x09820*/ u64 g3ifcmd_cml_err_alarm;
+ u8 unused09b00[0x09b00-0x09828];
+
+/*0x09b00*/ u64 vpath_to_vplane_map[17];
+#define VXGE_HW_VPATH_TO_VPLANE_MAP_VPATH_TO_VPLANE_MAP(val) \
+ vxge_vBIT(val, 3, 5)
+ u8 unused09c30[0x09c30-0x09b88];
+
+/*0x09c30*/ u64 xgxs_cfg_port[2];
+#define VXGE_HW_XGXS_CFG_PORT_SIG_DETECT_FORCE_LOS(val) vxge_vBIT(val, 16, 4)
+#define VXGE_HW_XGXS_CFG_PORT_SIG_DETECT_FORCE_VALID(val) vxge_vBIT(val, 20, 4)
+#define VXGE_HW_XGXS_CFG_PORT_SEL_INFO_0 vxge_mBIT(27)
+#define VXGE_HW_XGXS_CFG_PORT_SEL_INFO_1(val) vxge_vBIT(val, 29, 3)
+#define VXGE_HW_XGXS_CFG_PORT_TX_LANE0_SKEW(val) vxge_vBIT(val, 32, 4)
+#define VXGE_HW_XGXS_CFG_PORT_TX_LANE1_SKEW(val) vxge_vBIT(val, 36, 4)
+#define VXGE_HW_XGXS_CFG_PORT_TX_LANE2_SKEW(val) vxge_vBIT(val, 40, 4)
+#define VXGE_HW_XGXS_CFG_PORT_TX_LANE3_SKEW(val) vxge_vBIT(val, 44, 4)
+/*0x09c40*/ u64 xgxs_rxber_cfg_port[2];
+#define VXGE_HW_XGXS_RXBER_CFG_PORT_INTERVAL_DUR(val) vxge_vBIT(val, 0, 4)
+#define VXGE_HW_XGXS_RXBER_CFG_PORT_RXGXS_INTERVAL_CNT(val) \
+ vxge_vBIT(val, 16, 48)
+/*0x09c50*/ u64 xgxs_rxber_status_port[2];
+#define VXGE_HW_XGXS_RXBER_STATUS_PORT_RXGXS_RXGXS_LANE_A_ERR_CNT(val) \
+ vxge_vBIT(val, 0, 16)
+#define VXGE_HW_XGXS_RXBER_STATUS_PORT_RXGXS_RXGXS_LANE_B_ERR_CNT(val) \
+ vxge_vBIT(val, 16, 16)
+#define VXGE_HW_XGXS_RXBER_STATUS_PORT_RXGXS_RXGXS_LANE_C_ERR_CNT(val) \
+ vxge_vBIT(val, 32, 16)
+#define VXGE_HW_XGXS_RXBER_STATUS_PORT_RXGXS_RXGXS_LANE_D_ERR_CNT(val) \
+ vxge_vBIT(val, 48, 16)
+/*0x09c60*/ u64 xgxs_status_port[2];
+#define VXGE_HW_XGXS_STATUS_PORT_XMACJ_PCS_TX_ACTIVITY(val) vxge_vBIT(val, 0, 4)
+#define VXGE_HW_XGXS_STATUS_PORT_XMACJ_PCS_RX_ACTIVITY(val) vxge_vBIT(val, 4, 4)
+#define VXGE_HW_XGXS_STATUS_PORT_XMACJ_PCS_CTC_FIFO_ERR BIT(11)
+#define VXGE_HW_XGXS_STATUS_PORT_XMACJ_PCS_BYTE_SYNC_LOST(val) \
+ vxge_vBIT(val, 12, 4)
+#define VXGE_HW_XGXS_STATUS_PORT_XMACJ_PCS_CTC_ERR(val) vxge_vBIT(val, 16, 4)
+#define VXGE_HW_XGXS_STATUS_PORT_XMACJ_PCS_ALIGNMENT_ERR vxge_mBIT(23)
+#define VXGE_HW_XGXS_STATUS_PORT_XMACJ_PCS_DEC_ERR(val) vxge_vBIT(val, 24, 8)
+#define VXGE_HW_XGXS_STATUS_PORT_XMACJ_PCS_SKIP_INS_REQ(val) \
+ vxge_vBIT(val, 32, 4)
+#define VXGE_HW_XGXS_STATUS_PORT_XMACJ_PCS_SKIP_DEL_REQ(val) \
+ vxge_vBIT(val, 36, 4)
+/*0x09c70*/ u64 xgxs_pma_reset_port[2];
+#define VXGE_HW_XGXS_PMA_RESET_PORT_SERDES_RESET(val) vxge_vBIT(val, 0, 8)
+ u8 unused09c90[0x09c90-0x09c80];
+
+/*0x09c90*/ u64 xgxs_static_cfg_port[2];
+#define VXGE_HW_XGXS_STATIC_CFG_PORT_FW_CTRL_SERDES vxge_mBIT(3)
+ u8 unused09d40[0x09d40-0x09ca0];
+
+/*0x09d40*/ u64 xgxs_info_port[2];
+#define VXGE_HW_XGXS_INFO_PORT_XMACJ_INFO_0(val) vxge_vBIT(val, 0, 32)
+#define VXGE_HW_XGXS_INFO_PORT_XMACJ_INFO_1(val) vxge_vBIT(val, 32, 32)
+/*0x09d50*/ u64 ratemgmt_cfg_port[2];
+#define VXGE_HW_RATEMGMT_CFG_PORT_MODE(val) vxge_vBIT(val, 2, 2)
+#define VXGE_HW_RATEMGMT_CFG_PORT_RATE vxge_mBIT(7)
+#define VXGE_HW_RATEMGMT_CFG_PORT_FIXED_USE_FSM vxge_mBIT(11)
+#define VXGE_HW_RATEMGMT_CFG_PORT_ANTP_USE_FSM vxge_mBIT(15)
+#define VXGE_HW_RATEMGMT_CFG_PORT_ANBE_USE_FSM vxge_mBIT(19)
+/*0x09d60*/ u64 ratemgmt_status_port[2];
+#define VXGE_HW_RATEMGMT_STATUS_PORT_RATEMGMT_COMPLETE vxge_mBIT(3)
+#define VXGE_HW_RATEMGMT_STATUS_PORT_RATEMGMT_RATE vxge_mBIT(7)
+#define VXGE_HW_RATEMGMT_STATUS_PORT_RATEMGMT_MAC_MATCHES_PHY vxge_mBIT(11)
+ u8 unused09d80[0x09d80-0x09d70];
+
+/*0x09d80*/ u64 ratemgmt_fixed_cfg_port[2];
+#define VXGE_HW_RATEMGMT_FIXED_CFG_PORT_RESTART vxge_mBIT(7)
+/*0x09d90*/ u64 ratemgmt_antp_cfg_port[2];
+#define VXGE_HW_RATEMGMT_ANTP_CFG_PORT_RESTART vxge_mBIT(7)
+#define VXGE_HW_RATEMGMT_ANTP_CFG_PORT_USE_PREAMBLE_EXT_PHY vxge_mBIT(11)
+#define VXGE_HW_RATEMGMT_ANTP_CFG_PORT_USE_ACT_SEL vxge_mBIT(15)
+#define VXGE_HW_RATEMGMT_ANTP_CFG_PORT_T_RETRY_PHY_QUERY(val) \
+ vxge_vBIT(val, 16, 4)
+#define VXGE_HW_RATEMGMT_ANTP_CFG_PORT_T_WAIT_MDIO_RESPONSE(val) \
+ vxge_vBIT(val, 20, 4)
+#define VXGE_HW_RATEMGMT_ANTP_CFG_PORT_T_LDOWN_REAUTO_RESPONSE(val) \
+ vxge_vBIT(val, 24, 4)
+#define VXGE_HW_RATEMGMT_ANTP_CFG_PORT_ADVERTISE_10G vxge_mBIT(31)
+#define VXGE_HW_RATEMGMT_ANTP_CFG_PORT_ADVERTISE_1G vxge_mBIT(35)
+/*0x09da0*/ u64 ratemgmt_anbe_cfg_port[2];
+#define VXGE_HW_RATEMGMT_ANBE_CFG_PORT_RESTART vxge_mBIT(7)
+#define VXGE_HW_RATEMGMT_ANBE_CFG_PORT_PARALLEL_DETECT_10G_KX4_ENABLE \
+ vxge_mBIT(11)
+#define VXGE_HW_RATEMGMT_ANBE_CFG_PORT_PARALLEL_DETECT_1G_KX_ENABLE \
+ vxge_mBIT(15)
+#define VXGE_HW_RATEMGMT_ANBE_CFG_PORT_T_SYNC_10G_KX4(val) vxge_vBIT(val, 16, 4)
+#define VXGE_HW_RATEMGMT_ANBE_CFG_PORT_T_SYNC_1G_KX(val) vxge_vBIT(val, 20, 4)
+#define VXGE_HW_RATEMGMT_ANBE_CFG_PORT_T_DME_EXCHANGE(val) vxge_vBIT(val, 24, 4)
+#define VXGE_HW_RATEMGMT_ANBE_CFG_PORT_ADVERTISE_10G_KX4 vxge_mBIT(31)
+#define VXGE_HW_RATEMGMT_ANBE_CFG_PORT_ADVERTISE_1G_KX vxge_mBIT(35)
+/*0x09db0*/ u64 anbe_cfg_port[2];
+#define VXGE_HW_ANBE_CFG_PORT_RESET_CFG_REGS(val) vxge_vBIT(val, 0, 8)
+#define VXGE_HW_ANBE_CFG_PORT_ALIGN_10G_KX4_OVERRIDE(val) vxge_vBIT(val, 10, 2)
+#define VXGE_HW_ANBE_CFG_PORT_SYNC_1G_KX_OVERRIDE(val) vxge_vBIT(val, 14, 2)
+/*0x09dc0*/ u64 anbe_mgr_ctrl_port[2];
+#define VXGE_HW_ANBE_MGR_CTRL_PORT_WE vxge_mBIT(3)
+#define VXGE_HW_ANBE_MGR_CTRL_PORT_STROBE vxge_mBIT(7)
+#define VXGE_HW_ANBE_MGR_CTRL_PORT_ADDR(val) vxge_vBIT(val, 15, 9)
+#define VXGE_HW_ANBE_MGR_CTRL_PORT_DATA(val) vxge_vBIT(val, 32, 32)
+ u8 unused09de0[0x09de0-0x09dd0];
+
+/*0x09de0*/ u64 anbe_fw_mstr_port[2];
+#define VXGE_HW_ANBE_FW_MSTR_PORT_CONNECT_BEAN_TO_SERDES vxge_mBIT(3)
+#define VXGE_HW_ANBE_FW_MSTR_PORT_TX_ZEROES_TO_SERDES vxge_mBIT(7)
+/*0x09df0*/ u64 anbe_hwfsm_gen_status_port[2];
+#define VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_CHOSE_10G_KX4_USING_PD \
+ vxge_mBIT(3)
+#define VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_CHOSE_10G_KX4_USING_DME \
+ vxge_mBIT(7)
+#define VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_CHOSE_1G_KX_USING_PD \
+ vxge_mBIT(11)
+#define VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_CHOSE_1G_KX_USING_DME \
+ vxge_mBIT(15)
+#define VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_ANBEFSM_STATE(val) \
+ vxge_vBIT(val, 18, 6)
+#define VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_BEAN_NEXT_PAGE_RECEIVED \
+ vxge_mBIT(27)
+#define VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_BEAN_BASE_PAGE_RECEIVED \
+ vxge_mBIT(35)
+#define VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_BEAN_AUTONEG_COMPLETE \
+ vxge_mBIT(39)
+#define VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_UNEXPECTED_NP_BEFORE_BP \
+ vxge_mBIT(43)
+#define \
+VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_UNEXPECTED_AN_COMPLETE_BEFORE_BP \
+ vxge_mBIT(47)
+#define \
+VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_UNEXPECTED_AN_COMPLETE_BEFORE_NP \
+vxge_mBIT(51)
+#define \
+VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_UNEXPECTED_MODE_WHEN_AN_COMPLETE \
+ vxge_mBIT(55)
+#define VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_COUNT_BP(val) \
+ vxge_vBIT(val, 56, 4)
+#define VXGE_HW_ANBE_HWFSM_GEN_STATUS_PORT_RATEMGMT_COUNT_NP(val) \
+ vxge_vBIT(val, 60, 4)
+/*0x09e00*/ u64 anbe_hwfsm_bp_status_port[2];
+#define VXGE_HW_ANBE_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_FEC_ENABLE \
+ vxge_mBIT(32)
+#define VXGE_HW_ANBE_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_FEC_ABILITY \
+ vxge_mBIT(33)
+#define VXGE_HW_ANBE_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_10G_KR_CAPABLE \
+ vxge_mBIT(40)
+#define VXGE_HW_ANBE_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_10G_KX4_CAPABLE \
+ vxge_mBIT(41)
+#define VXGE_HW_ANBE_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_1G_KX_CAPABLE \
+ vxge_mBIT(42)
+#define VXGE_HW_ANBE_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_TX_NONCE(val) \
+ vxge_vBIT(val, 43, 5)
+#define VXGE_HW_ANBE_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_NP vxge_mBIT(48)
+#define VXGE_HW_ANBE_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_ACK vxge_mBIT(49)
+#define VXGE_HW_ANBE_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_REMOTE_FAULT \
+ vxge_mBIT(50)
+#define VXGE_HW_ANBE_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_ASM_DIR vxge_mBIT(51)
+#define VXGE_HW_ANBE_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_PAUSE vxge_mBIT(53)
+#define VXGE_HW_ANBE_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_ECHOED_NONCE(val) \
+ vxge_vBIT(val, 54, 5)
+#define VXGE_HW_ANBE_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_SELECTOR_FIELD(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x09e10*/ u64 anbe_hwfsm_np_status_port[2];
+#define VXGE_HW_ANBE_HWFSM_NP_STATUS_PORT_RATEMGMT_NP_BITS_47_TO_32(val) \
+ vxge_vBIT(val, 16, 16)
+#define VXGE_HW_ANBE_HWFSM_NP_STATUS_PORT_RATEMGMT_NP_BITS_31_TO_0(val) \
+ vxge_vBIT(val, 32, 32)
+ u8 unused09e30[0x09e30-0x09e20];
+
+/*0x09e30*/ u64 antp_gen_cfg_port[2];
+/*0x09e40*/ u64 antp_hwfsm_gen_status_port[2];
+#define VXGE_HW_ANTP_HWFSM_GEN_STATUS_PORT_RATEMGMT_CHOSE_10G vxge_mBIT(3)
+#define VXGE_HW_ANTP_HWFSM_GEN_STATUS_PORT_RATEMGMT_CHOSE_1G vxge_mBIT(7)
+#define VXGE_HW_ANTP_HWFSM_GEN_STATUS_PORT_RATEMGMT_ANTPFSM_STATE(val) \
+ vxge_vBIT(val, 10, 6)
+#define VXGE_HW_ANTP_HWFSM_GEN_STATUS_PORT_RATEMGMT_AUTONEG_COMPLETE \
+ vxge_mBIT(23)
+#define VXGE_HW_ANTP_HWFSM_GEN_STATUS_PORT_RATEMGMT_UNEXPECTED_NO_LP_XNP \
+ vxge_mBIT(27)
+#define VXGE_HW_ANTP_HWFSM_GEN_STATUS_PORT_RATEMGMT_GOT_LP_XNP vxge_mBIT(31)
+#define VXGE_HW_ANTP_HWFSM_GEN_STATUS_PORT_RATEMGMT_UNEXPECTED_MESSAGE_CODE \
+ vxge_mBIT(35)
+#define VXGE_HW_ANTP_HWFSM_GEN_STATUS_PORT_RATEMGMT_UNEXPECTED_NO_HCD \
+ vxge_mBIT(43)
+#define VXGE_HW_ANTP_HWFSM_GEN_STATUS_PORT_RATEMGMT_FOUND_HCD vxge_mBIT(47)
+#define VXGE_HW_ANTP_HWFSM_GEN_STATUS_PORT_RATEMGMT_UNEXPECTED_INVALID_RATE \
+ vxge_mBIT(51)
+#define VXGE_HW_ANTP_HWFSM_GEN_STATUS_PORT_RATEMGMT_VALID_RATE vxge_mBIT(55)
+#define VXGE_HW_ANTP_HWFSM_GEN_STATUS_PORT_RATEMGMT_PERSISTENT_LDOWN \
+ vxge_mBIT(59)
+/*0x09e50*/ u64 antp_hwfsm_bp_status_port[2];
+#define VXGE_HW_ANTP_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_NP vxge_mBIT(0)
+#define VXGE_HW_ANTP_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_ACK vxge_mBIT(1)
+#define VXGE_HW_ANTP_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_RF vxge_mBIT(2)
+#define VXGE_HW_ANTP_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_XNP vxge_mBIT(3)
+#define VXGE_HW_ANTP_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_ABILITY_FIELD(val) \
+ vxge_vBIT(val, 4, 7)
+#define VXGE_HW_ANTP_HWFSM_BP_STATUS_PORT_RATEMGMT_BP_SELECTOR_FIELD(val) \
+ vxge_vBIT(val, 11, 5)
+/*0x09e60*/ u64 antp_hwfsm_xnp_status_port[2];
+#define VXGE_HW_ANTP_HWFSM_XNP_STATUS_PORT_RATEMGMT_XNP_NP vxge_mBIT(0)
+#define VXGE_HW_ANTP_HWFSM_XNP_STATUS_PORT_RATEMGMT_XNP_ACK vxge_mBIT(1)
+#define VXGE_HW_ANTP_HWFSM_XNP_STATUS_PORT_RATEMGMT_XNP_MP vxge_mBIT(2)
+#define VXGE_HW_ANTP_HWFSM_XNP_STATUS_PORT_RATEMGMT_XNP_ACK2 vxge_mBIT(3)
+#define VXGE_HW_ANTP_HWFSM_XNP_STATUS_PORT_RATEMGMT_XNP_TOGGLE vxge_mBIT(4)
+#define VXGE_HW_ANTP_HWFSM_XNP_STATUS_PORT_RATEMGMT_XNP_MESSAGE_CODE(val) \
+ vxge_vBIT(val, 5, 11)
+#define VXGE_HW_ANTP_HWFSM_XNP_STATUS_PORT_RATEMGMT_XNP_UNF_CODE_FIELD1(val) \
+ vxge_vBIT(val, 16, 16)
+#define VXGE_HW_ANTP_HWFSM_XNP_STATUS_PORT_RATEMGMT_XNP_UNF_CODE_FIELD2(val) \
+ vxge_vBIT(val, 32, 16)
+/*0x09e70*/ u64 mdio_mgr_access_port[2];
+#define VXGE_HW_MDIO_MGR_ACCESS_PORT_STROBE_ONE BIT(3)
+#define VXGE_HW_MDIO_MGR_ACCESS_PORT_OP_TYPE(val) vxge_vBIT(val, 5, 3)
+#define VXGE_HW_MDIO_MGR_ACCESS_PORT_DEVAD(val) vxge_vBIT(val, 11, 5)
+#define VXGE_HW_MDIO_MGR_ACCESS_PORT_ADDR(val) vxge_vBIT(val, 16, 16)
+#define VXGE_HW_MDIO_MGR_ACCESS_PORT_DATA(val) vxge_vBIT(val, 32, 16)
+#define VXGE_HW_MDIO_MGR_ACCESS_PORT_ST_PATTERN(val) vxge_vBIT(val, 49, 2)
+#define VXGE_HW_MDIO_MGR_ACCESS_PORT_PREAMBLE vxge_mBIT(51)
+#define VXGE_HW_MDIO_MGR_ACCESS_PORT_PRTAD(val) vxge_vBIT(val, 55, 5)
+#define VXGE_HW_MDIO_MGR_ACCESS_PORT_STROBE_TWO vxge_mBIT(63)
+ u8 unused0a200[0x0a200-0x09e80];
+/*0x0a200*/ u64 xmac_vsport_choices_vh[17];
+#define VXGE_HW_XMAC_VSPORT_CHOICES_VH_VSPORT_VECTOR(val) vxge_vBIT(val, 0, 17)
+ u8 unused0a400[0x0a400-0x0a288];
+
+/*0x0a400*/ u64 rx_thresh_cfg_vp[17];
+#define VXGE_HW_RX_THRESH_CFG_VP_PAUSE_LOW_THR(val) vxge_vBIT(val, 0, 8)
+#define VXGE_HW_RX_THRESH_CFG_VP_PAUSE_HIGH_THR(val) vxge_vBIT(val, 8, 8)
+#define VXGE_HW_RX_THRESH_CFG_VP_RED_THR_0(val) vxge_vBIT(val, 16, 8)
+#define VXGE_HW_RX_THRESH_CFG_VP_RED_THR_1(val) vxge_vBIT(val, 24, 8)
+#define VXGE_HW_RX_THRESH_CFG_VP_RED_THR_2(val) vxge_vBIT(val, 32, 8)
+#define VXGE_HW_RX_THRESH_CFG_VP_RED_THR_3(val) vxge_vBIT(val, 40, 8)
+ u8 unused0ac90[0x0ac90-0x0a488];
+} __attribute((packed));
+
+/*VXGE_HW_SRPCIM_REGS_H*/
+struct vxge_hw_srpcim_reg {
+
+/*0x00000*/ u64 tim_mr2sr_resource_assignment_vh;
+#define VXGE_HW_TIM_MR2SR_RESOURCE_ASSIGNMENT_VH_BMAP_ROOT(val) \
+ vxge_vBIT(val, 0, 32)
+ u8 unused00100[0x00100-0x00008];
+
+/*0x00100*/ u64 srpcim_pcipif_int_status;
+#define VXGE_HW_SRPCIM_PCIPIF_INT_STATUS_MRPCIM_MSG_MRPCIM_MSG_INT BIT(3)
+#define VXGE_HW_SRPCIM_PCIPIF_INT_STATUS_VPATH_MSG_VPATH_MSG_INT BIT(7)
+#define VXGE_HW_SRPCIM_PCIPIF_INT_STATUS_SRPCIM_SPARE_R1_SRPCIM_SPARE_R1_INT \
+ BIT(11)
+/*0x00108*/ u64 srpcim_pcipif_int_mask;
+/*0x00110*/ u64 mrpcim_msg_reg;
+#define VXGE_HW_MRPCIM_MSG_REG_SWIF_MRPCIM_TO_SRPCIM_RMSG_INT BIT(3)
+/*0x00118*/ u64 mrpcim_msg_mask;
+/*0x00120*/ u64 mrpcim_msg_alarm;
+/*0x00128*/ u64 vpath_msg_reg;
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH0_TO_SRPCIM_RMSG_INT BIT(0)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH1_TO_SRPCIM_RMSG_INT BIT(1)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH2_TO_SRPCIM_RMSG_INT BIT(2)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH3_TO_SRPCIM_RMSG_INT BIT(3)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH4_TO_SRPCIM_RMSG_INT BIT(4)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH5_TO_SRPCIM_RMSG_INT BIT(5)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH6_TO_SRPCIM_RMSG_INT BIT(6)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH7_TO_SRPCIM_RMSG_INT BIT(7)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH8_TO_SRPCIM_RMSG_INT BIT(8)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH9_TO_SRPCIM_RMSG_INT BIT(9)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH10_TO_SRPCIM_RMSG_INT BIT(10)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH11_TO_SRPCIM_RMSG_INT BIT(11)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH12_TO_SRPCIM_RMSG_INT BIT(12)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH13_TO_SRPCIM_RMSG_INT BIT(13)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH14_TO_SRPCIM_RMSG_INT BIT(14)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH15_TO_SRPCIM_RMSG_INT BIT(15)
+#define VXGE_HW_VPATH_MSG_REG_SWIF_VPATH16_TO_SRPCIM_RMSG_INT BIT(16)
+/*0x00130*/ u64 vpath_msg_mask;
+/*0x00138*/ u64 vpath_msg_alarm;
+ u8 unused00160[0x00160-0x00140];
+
+/*0x00160*/ u64 srpcim_to_mrpcim_wmsg;
+#define VXGE_HW_SRPCIM_TO_MRPCIM_WMSG_SRPCIM_TO_MRPCIM_WMSG(val) \
+ vxge_vBIT(val, 0, 64)
+/*0x00168*/ u64 srpcim_to_mrpcim_wmsg_trig;
+#define VXGE_HW_SRPCIM_TO_MRPCIM_WMSG_TRIG_SRPCIM_TO_MRPCIM_WMSG_TRIG BIT(0)
+/*0x00170*/ u64 mrpcim_to_srpcim_rmsg;
+#define VXGE_HW_MRPCIM_TO_SRPCIM_RMSG_SWIF_MRPCIM_TO_SRPCIM_RMSG(val) \
+ vxge_vBIT(val, 0, 64)
+/*0x00178*/ u64 vpath_to_srpcim_rmsg_sel;
+#define VXGE_HW_VPATH_TO_SRPCIM_RMSG_SEL_VPATH_TO_SRPCIM_RMSG_SEL(val) \
+ vxge_vBIT(val, 0, 5)
+/*0x00180*/ u64 vpath_to_srpcim_rmsg;
+#define VXGE_HW_VPATH_TO_SRPCIM_RMSG_SWIF_VPATH_TO_SRPCIM_RMSG(val) \
+ vxge_vBIT(val, 0, 64)
+ u8 unused00200[0x00200-0x00188];
+
+/*0x00200*/ u64 srpcim_general_int_status;
+#define VXGE_HW_SRPCIM_GENERAL_INT_STATUS_PIC_INT BIT(0)
+#define VXGE_HW_SRPCIM_GENERAL_INT_STATUS_PCI_INT BIT(3)
+#define VXGE_HW_SRPCIM_GENERAL_INT_STATUS_XMAC_INT BIT(7)
+ u8 unused00210[0x00210-0x00208];
+
+/*0x00210*/ u64 srpcim_general_int_mask;
+#define VXGE_HW_SRPCIM_GENERAL_INT_MASK_PIC_INT BIT(0)
+#define VXGE_HW_SRPCIM_GENERAL_INT_MASK_PCI_INT BIT(3)
+#define VXGE_HW_SRPCIM_GENERAL_INT_MASK_XMAC_INT BIT(7)
+ u8 unused00220[0x00220-0x00218];
+
+/*0x00220*/ u64 srpcim_ppif_int_status;
+
+/*0x00228*/ u64 srpcim_ppif_int_mask;
+/*0x00230*/ u64 srpcim_gen_errors_reg;
+#define VXGE_HW_SRPCIM_GEN_ERRORS_REG_PCICONFIG_PF_STATUS_ERR BIT(3)
+#define VXGE_HW_SRPCIM_GEN_ERRORS_REG_PCICONFIG_PF_UNCOR_ERR BIT(7)
+#define VXGE_HW_SRPCIM_GEN_ERRORS_REG_PCICONFIG_PF_COR_ERR BIT(11)
+#define VXGE_HW_SRPCIM_GEN_ERRORS_REG_INTCTRL_SCHED_INT BIT(15)
+#define VXGE_HW_SRPCIM_GEN_ERRORS_REG_INI_SERR_DET BIT(19)
+#define VXGE_HW_SRPCIM_GEN_ERRORS_REG_TGT_PF_ILLEGAL_ACCESS BIT(23)
+/*0x00238*/ u64 srpcim_gen_errors_mask;
+/*0x00240*/ u64 srpcim_gen_errors_alarm;
+/*0x00248*/ u64 mrpcim_to_srpcim_alarm_reg;
+#define VXGE_HW_MRPCIM_TO_SRPCIM_ALARM_REG_PPIF_MRPCIM_TO_SRPCIM_ALARM BIT(3)
+/*0x00250*/ u64 mrpcim_to_srpcim_alarm_mask;
+/*0x00258*/ u64 mrpcim_to_srpcim_alarm_alarm;
+/*0x00260*/ u64 vpath_to_srpcim_alarm_reg;
+
+/*0x00268*/ u64 vpath_to_srpcim_alarm_mask;
+/*0x00270*/ u64 vpath_to_srpcim_alarm_alarm;
+ u8 unused00280[0x00280-0x00278];
+
+/*0x00280*/ u64 pf_sw_reset;
+#define VXGE_HW_PF_SW_RESET_PF_SW_RESET(val) vxge_vBIT(val, 0, 8)
+/*0x00288*/ u64 srpcim_general_cfg1;
+#define VXGE_HW_SRPCIM_GENERAL_CFG1_BOOT_BYTE_SWAPEN BIT(19)
+#define VXGE_HW_SRPCIM_GENERAL_CFG1_BOOT_BIT_FLIPEN BIT(23)
+#define VXGE_HW_SRPCIM_GENERAL_CFG1_MSIX_ADDR_SWAPEN BIT(27)
+#define VXGE_HW_SRPCIM_GENERAL_CFG1_MSIX_ADDR_FLIPEN BIT(31)
+#define VXGE_HW_SRPCIM_GENERAL_CFG1_MSIX_DATA_SWAPEN BIT(35)
+#define VXGE_HW_SRPCIM_GENERAL_CFG1_MSIX_DATA_FLIPEN BIT(39)
+/*0x00290*/ u64 srpcim_interrupt_cfg1;
+#define VXGE_HW_SRPCIM_INTERRUPT_CFG1_ALARM_MAP_TO_MSG(val) vxge_vBIT(val, 1, 7)
+#define VXGE_HW_SRPCIM_INTERRUPT_CFG1_TRAFFIC_CLASS(val) vxge_vBIT(val, 9, 3)
+ u8 unused002a8[0x002a8-0x00298];
+
+/*0x002a8*/ u64 srpcim_clear_msix_mask;
+#define VXGE_HW_SRPCIM_CLEAR_MSIX_MASK_SRPCIM_CLEAR_MSIX_MASK BIT(0)
+/*0x002b0*/ u64 srpcim_set_msix_mask;
+#define VXGE_HW_SRPCIM_SET_MSIX_MASK_SRPCIM_SET_MSIX_MASK BIT(0)
+/*0x002b8*/ u64 srpcim_clr_msix_one_shot;
+#define VXGE_HW_SRPCIM_CLR_MSIX_ONE_SHOT_SRPCIM_CLR_MSIX_ONE_SHOT BIT(0)
+/*0x002c0*/ u64 srpcim_rst_in_prog;
+#define VXGE_HW_SRPCIM_RST_IN_PROG_SRPCIM_RST_IN_PROG BIT(7)
+/*0x002c8*/ u64 srpcim_reg_modified;
+#define VXGE_HW_SRPCIM_REG_MODIFIED_SRPCIM_REG_MODIFIED BIT(7)
+/*0x002d0*/ u64 tgt_pf_illegal_access;
+#define VXGE_HW_TGT_PF_ILLEGAL_ACCESS_SWIF_REGION(val) vxge_vBIT(val, 1, 7)
+/*0x002d8*/ u64 srpcim_msix_status;
+#define VXGE_HW_SRPCIM_MSIX_STATUS_INTCTL_SRPCIM_MSIX_MASK BIT(3)
+#define VXGE_HW_SRPCIM_MSIX_STATUS_INTCTL_SRPCIM_MSIX_PENDING_VECTOR BIT(7)
+ u8 unused00880[0x00880-0x002e0];
+
+/*0x00880*/ u64 xgmac_sr_int_status;
+#define VXGE_HW_XGMAC_SR_INT_STATUS_ASIC_NTWK_SR_ERR_ASIC_NTWK_SR_INT BIT(3)
+/*0x00888*/ u64 xgmac_sr_int_mask;
+/*0x00890*/ u64 asic_ntwk_sr_err_reg;
+#define VXGE_HW_ASIC_NTWK_SR_ERR_REG_XMACJ_NTWK_SUSTAINED_FAULT BIT(3)
+#define VXGE_HW_ASIC_NTWK_SR_ERR_REG_XMACJ_NTWK_SUSTAINED_OK BIT(7)
+#define VXGE_HW_ASIC_NTWK_SR_ERR_REG_XMACJ_NTWK_SUSTAINED_FAULT_OCCURRED \
+ BIT(11)
+#define VXGE_HW_ASIC_NTWK_SR_ERR_REG_XMACJ_NTWK_SUSTAINED_OK_OCCURRED BIT(15)
+/*0x00898*/ u64 asic_ntwk_sr_err_mask;
+/*0x008a0*/ u64 asic_ntwk_sr_err_alarm;
+ u8 unused008c0[0x008c0-0x008a8];
+
+/*0x008c0*/ u64 xmac_vsport_choices_sr_clone;
+#define VXGE_HW_XMAC_VSPORT_CHOICES_SR_CLONE_VSPORT_VECTOR(val) \
+ vxge_vBIT(val, 0, 17)
+ u8 unused00900[0x00900-0x008c8];
+
+/*0x00900*/ u64 mr_rqa_top_prty_for_vh;
+#define VXGE_HW_MR_RQA_TOP_PRTY_FOR_VH_RQA_TOP_PRTY_FOR_VH(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00908*/ u64 umq_vh_data_list_empty;
+#define VXGE_HW_UMQ_VH_DATA_LIST_EMPTY_ROCRC_UMQ_VH_DATA_LIST_EMPTY \
+ BIT(0)
+/*0x00910*/ u64 wde_cfg;
+#define VXGE_HW_WDE_CFG_NS0_FORCE_MWB_START BIT(0)
+#define VXGE_HW_WDE_CFG_NS0_FORCE_MWB_END BIT(1)
+#define VXGE_HW_WDE_CFG_NS0_FORCE_QB_START BIT(2)
+#define VXGE_HW_WDE_CFG_NS0_FORCE_QB_END BIT(3)
+#define VXGE_HW_WDE_CFG_NS0_FORCE_MPSB_START BIT(4)
+#define VXGE_HW_WDE_CFG_NS0_FORCE_MPSB_END BIT(5)
+#define VXGE_HW_WDE_CFG_NS0_MWB_OPT_EN BIT(6)
+#define VXGE_HW_WDE_CFG_NS0_QB_OPT_EN BIT(7)
+#define VXGE_HW_WDE_CFG_NS0_MPSB_OPT_EN BIT(8)
+#define VXGE_HW_WDE_CFG_NS1_FORCE_MWB_START BIT(9)
+#define VXGE_HW_WDE_CFG_NS1_FORCE_MWB_END BIT(10)
+#define VXGE_HW_WDE_CFG_NS1_FORCE_QB_START BIT(11)
+#define VXGE_HW_WDE_CFG_NS1_FORCE_QB_END BIT(12)
+#define VXGE_HW_WDE_CFG_NS1_FORCE_MPSB_START BIT(13)
+#define VXGE_HW_WDE_CFG_NS1_FORCE_MPSB_END BIT(14)
+#define VXGE_HW_WDE_CFG_NS1_MWB_OPT_EN BIT(15)
+#define VXGE_HW_WDE_CFG_NS1_QB_OPT_EN BIT(16)
+#define VXGE_HW_WDE_CFG_NS1_MPSB_OPT_EN BIT(17)
+#define VXGE_HW_WDE_CFG_DISABLE_QPAD_FOR_UNALIGNED_ADDR BIT(19)
+#define VXGE_HW_WDE_CFG_ALIGNMENT_PREFERENCE(val) vxge_vBIT(val, 30, 2)
+#define VXGE_HW_WDE_CFG_MEM_WORD_SIZE(val) vxge_vBIT(val, 46, 2)
+
+} __attribute((packed));
+
+/*VXGE_HW_VPMGMT_REGS_H*/
+struct vxge_hw_vpmgmt_reg {
+
+ u8 unused00040[0x00040-0x00000];
+
+/*0x00040*/ u64 vpath_to_func_map_cfg1;
+#define VXGE_HW_VPATH_TO_FUNC_MAP_CFG1_VPATH_TO_FUNC_MAP_CFG1(val) \
+ vxge_vBIT(val, 3, 5)
+/*0x00048*/ u64 vpath_is_first;
+#define VXGE_HW_VPATH_IS_FIRST_VPATH_IS_FIRST vxge_mBIT(3)
+/*0x00050*/ u64 srpcim_to_vpath_wmsg;
+#define VXGE_HW_SRPCIM_TO_VPATH_WMSG_SRPCIM_TO_VPATH_WMSG(val) \
+ vxge_vBIT(val, 0, 64)
+/*0x00058*/ u64 srpcim_to_vpath_wmsg_trig;
+#define VXGE_HW_SRPCIM_TO_VPATH_WMSG_TRIG_SRPCIM_TO_VPATH_WMSG_TRIG \
+ vxge_mBIT(0)
+ u8 unused00100[0x00100-0x00060];
+
+/*0x00100*/ u64 tim_vpath_assignment;
+#define VXGE_HW_TIM_VPATH_ASSIGNMENT_BMAP_ROOT(val) vxge_vBIT(val, 0, 32)
+ u8 unused00140[0x00140-0x00108];
+
+/*0x00140*/ u64 rqa_top_prty_for_vp;
+#define VXGE_HW_RQA_TOP_PRTY_FOR_VP_RQA_TOP_PRTY_FOR_VP(val) \
+ vxge_vBIT(val, 59, 5)
+ u8 unused001c0[0x001c0-0x00148];
+
+/*0x001c0*/ u64 rxmac_rx_pa_cfg0_vpmgmt_clone;
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_IGNORE_FRAME_ERR vxge_mBIT(3)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_SUPPORT_SNAP_AB_N vxge_mBIT(7)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_SEARCH_FOR_HAO vxge_mBIT(18)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_SUPPORT_MOBILE_IPV6_HDRS \
+ vxge_mBIT(19)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_IPV6_STOP_SEARCHING \
+ vxge_mBIT(23)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_NO_PS_IF_UNKNOWN vxge_mBIT(27)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_SEARCH_FOR_ETYPE vxge_mBIT(35)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_TOSS_ANY_FRM_IF_L3_CSUM_ERR \
+ vxge_mBIT(39)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_TOSS_OFFLD_FRM_IF_L3_CSUM_ERR \
+ vxge_mBIT(43)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_TOSS_ANY_FRM_IF_L4_CSUM_ERR \
+ vxge_mBIT(47)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_TOSS_OFFLD_FRM_IF_L4_CSUM_ERR \
+ vxge_mBIT(51)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_TOSS_ANY_FRM_IF_RPA_ERR \
+ vxge_mBIT(55)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_TOSS_OFFLD_FRM_IF_RPA_ERR \
+ vxge_mBIT(59)
+#define VXGE_HW_RXMAC_RX_PA_CFG0_VPMGMT_CLONE_JUMBO_SNAP_EN vxge_mBIT(63)
+/*0x001c8*/ u64 rts_mgr_cfg0_vpmgmt_clone;
+#define VXGE_HW_RTS_MGR_CFG0_VPMGMT_CLONE_RTS_DP_SP_PRIORITY vxge_mBIT(3)
+#define VXGE_HW_RTS_MGR_CFG0_VPMGMT_CLONE_FLEX_L4PRTCL_VALUE(val) \
+ vxge_vBIT(val, 24, 8)
+#define VXGE_HW_RTS_MGR_CFG0_VPMGMT_CLONE_ICMP_TRASH vxge_mBIT(35)
+#define VXGE_HW_RTS_MGR_CFG0_VPMGMT_CLONE_TCPSYN_TRASH vxge_mBIT(39)
+#define VXGE_HW_RTS_MGR_CFG0_VPMGMT_CLONE_ZL4PYLD_TRASH vxge_mBIT(43)
+#define VXGE_HW_RTS_MGR_CFG0_VPMGMT_CLONE_L4PRTCL_TCP_TRASH vxge_mBIT(47)
+#define VXGE_HW_RTS_MGR_CFG0_VPMGMT_CLONE_L4PRTCL_UDP_TRASH vxge_mBIT(51)
+#define VXGE_HW_RTS_MGR_CFG0_VPMGMT_CLONE_L4PRTCL_FLEX_TRASH vxge_mBIT(55)
+#define VXGE_HW_RTS_MGR_CFG0_VPMGMT_CLONE_IPFRAG_TRASH vxge_mBIT(59)
+/*0x001d0*/ u64 rts_mgr_criteria_priority_vpmgmt_clone;
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_VPMGMT_CLONE_ETYPE(val) \
+ vxge_vBIT(val, 5, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_VPMGMT_CLONE_ICMP_TCPSYN(val) \
+ vxge_vBIT(val, 9, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_VPMGMT_CLONE_L4PN(val) \
+ vxge_vBIT(val, 13, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_VPMGMT_CLONE_RANGE_L4PN(val) \
+ vxge_vBIT(val, 17, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_VPMGMT_CLONE_RTH_IT(val) \
+ vxge_vBIT(val, 21, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_VPMGMT_CLONE_DS(val) \
+ vxge_vBIT(val, 25, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_VPMGMT_CLONE_QOS(val) \
+ vxge_vBIT(val, 29, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_VPMGMT_CLONE_ZL4PYLD(val) \
+ vxge_vBIT(val, 33, 3)
+#define VXGE_HW_RTS_MGR_CRITERIA_PRIORITY_VPMGMT_CLONE_L4PRTCL(val) \
+ vxge_vBIT(val, 37, 3)
+/*0x001d8*/ u64 rxmac_cfg0_port_vpmgmt_clone[3];
+#define VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_RMAC_EN vxge_mBIT(3)
+#define VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_STRIP_FCS vxge_mBIT(7)
+#define VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_DISCARD_PFRM vxge_mBIT(11)
+#define VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_IGNORE_FCS_ERR vxge_mBIT(15)
+#define VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_IGNORE_LONG_ERR vxge_mBIT(19)
+#define VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_IGNORE_USIZED_ERR vxge_mBIT(23)
+#define VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_IGNORE_LEN_MISMATCH \
+ vxge_mBIT(27)
+#define VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_MAX_PYLD_LEN(val) \
+ vxge_vBIT(val, 50, 14)
+/*0x001f0*/ u64 rxmac_pause_cfg_port_vpmgmt_clone[3];
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_VPMGMT_CLONE_GEN_EN vxge_mBIT(3)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_VPMGMT_CLONE_RCV_EN vxge_mBIT(7)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_VPMGMT_CLONE_ACCEL_SEND(val) \
+ vxge_vBIT(val, 9, 3)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_VPMGMT_CLONE_DUAL_THR vxge_mBIT(15)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_VPMGMT_CLONE_HIGH_PTIME(val) \
+ vxge_vBIT(val, 20, 16)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_VPMGMT_CLONE_IGNORE_PF_FCS_ERR \
+ vxge_mBIT(39)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_VPMGMT_CLONE_IGNORE_PF_LEN_ERR \
+ vxge_mBIT(43)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_VPMGMT_CLONE_LIMITER_EN vxge_mBIT(47)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_VPMGMT_CLONE_MAX_LIMIT(val) \
+ vxge_vBIT(val, 48, 8)
+#define VXGE_HW_RXMAC_PAUSE_CFG_PORT_VPMGMT_CLONE_PERMIT_RATEMGMT_CTRL \
+ vxge_mBIT(59)
+ u8 unused00240[0x00240-0x00208];
+
+/*0x00240*/ u64 xmac_vsport_choices_vp;
+#define VXGE_HW_XMAC_VSPORT_CHOICES_VP_VSPORT_VECTOR(val) vxge_vBIT(val, 0, 17)
+ u8 unused00260[0x00260-0x00248];
+
+/*0x00260*/ u64 xgmac_gen_status_vpmgmt_clone;
+#define VXGE_HW_XGMAC_GEN_STATUS_VPMGMT_CLONE_XMACJ_NTWK_OK vxge_mBIT(3)
+#define VXGE_HW_XGMAC_GEN_STATUS_VPMGMT_CLONE_XMACJ_NTWK_DATA_RATE \
+ vxge_mBIT(11)
+/*0x00268*/ u64 xgmac_status_port_vpmgmt_clone[2];
+#define VXGE_HW_XGMAC_STATUS_PORT_VPMGMT_CLONE_RMAC_REMOTE_FAULT \
+ vxge_mBIT(3)
+#define VXGE_HW_XGMAC_STATUS_PORT_VPMGMT_CLONE_RMAC_LOCAL_FAULT vxge_mBIT(7)
+#define VXGE_HW_XGMAC_STATUS_PORT_VPMGMT_CLONE_XMACJ_MAC_PHY_LAYER_AVAIL \
+ vxge_mBIT(11)
+#define VXGE_HW_XGMAC_STATUS_PORT_VPMGMT_CLONE_XMACJ_PORT_OK vxge_mBIT(15)
+/*0x00278*/ u64 xmac_gen_cfg_vpmgmt_clone;
+#define VXGE_HW_XMAC_GEN_CFG_VPMGMT_CLONE_RATEMGMT_MAC_RATE_SEL(val) \
+ vxge_vBIT(val, 2, 2)
+#define VXGE_HW_XMAC_GEN_CFG_VPMGMT_CLONE_TX_HEAD_DROP_WHEN_FAULT \
+ vxge_mBIT(7)
+#define VXGE_HW_XMAC_GEN_CFG_VPMGMT_CLONE_FAULT_BEHAVIOUR vxge_mBIT(27)
+#define VXGE_HW_XMAC_GEN_CFG_VPMGMT_CLONE_PERIOD_NTWK_UP(val) \
+ vxge_vBIT(val, 28, 4)
+#define VXGE_HW_XMAC_GEN_CFG_VPMGMT_CLONE_PERIOD_NTWK_DOWN(val) \
+ vxge_vBIT(val, 32, 4)
+/*0x00280*/ u64 xmac_timestamp_vpmgmt_clone;
+#define VXGE_HW_XMAC_TIMESTAMP_VPMGMT_CLONE_EN vxge_mBIT(3)
+#define VXGE_HW_XMAC_TIMESTAMP_VPMGMT_CLONE_USE_LINK_ID(val) \
+ vxge_vBIT(val, 6, 2)
+#define VXGE_HW_XMAC_TIMESTAMP_VPMGMT_CLONE_INTERVAL(val) vxge_vBIT(val, 12, 4)
+#define VXGE_HW_XMAC_TIMESTAMP_VPMGMT_CLONE_TIMER_RESTART vxge_mBIT(19)
+#define VXGE_HW_XMAC_TIMESTAMP_VPMGMT_CLONE_XMACJ_ROLLOVER_CNT(val) \
+ vxge_vBIT(val, 32, 16)
+/*0x00288*/ u64 xmac_stats_gen_cfg_vpmgmt_clone;
+#define VXGE_HW_XMAC_STATS_GEN_CFG_VPMGMT_CLONE_PRTAGGR_CUM_TIMER(val) \
+ vxge_vBIT(val, 4, 4)
+#define VXGE_HW_XMAC_STATS_GEN_CFG_VPMGMT_CLONE_VPATH_CUM_TIMER(val) \
+ vxge_vBIT(val, 8, 4)
+#define VXGE_HW_XMAC_STATS_GEN_CFG_VPMGMT_CLONE_VLAN_HANDLING vxge_mBIT(15)
+/*0x00290*/ u64 xmac_cfg_port_vpmgmt_clone[3];
+#define VXGE_HW_XMAC_CFG_PORT_VPMGMT_CLONE_XGMII_LOOPBACK vxge_mBIT(3)
+#define VXGE_HW_XMAC_CFG_PORT_VPMGMT_CLONE_XGMII_REVERSE_LOOPBACK \
+ vxge_mBIT(7)
+#define VXGE_HW_XMAC_CFG_PORT_VPMGMT_CLONE_XGMII_TX_BEHAV vxge_mBIT(11)
+#define VXGE_HW_XMAC_CFG_PORT_VPMGMT_CLONE_XGMII_RX_BEHAV vxge_mBIT(15)
+ u8 unused002c0[0x002c0-0x002a8];
+
+/*0x002c0*/ u64 txmac_gen_cfg0_vpmgmt_clone;
+#define VXGE_HW_TXMAC_GEN_CFG0_VPMGMT_CLONE_CHOSEN_TX_PORT vxge_mBIT(7)
+/*0x002c8*/ u64 txmac_cfg0_port_vpmgmt_clone[3];
+#define VXGE_HW_TXMAC_CFG0_PORT_VPMGMT_CLONE_TMAC_EN vxge_mBIT(3)
+#define VXGE_HW_TXMAC_CFG0_PORT_VPMGMT_CLONE_APPEND_PAD vxge_mBIT(7)
+#define VXGE_HW_TXMAC_CFG0_PORT_VPMGMT_CLONE_PAD_BYTE(val) vxge_vBIT(val, 8, 8)
+ u8 unused00300[0x00300-0x002e0];
+
+/*0x00300*/ u64 wol_mp_crc;
+#define VXGE_HW_WOL_MP_CRC_CRC(val) vxge_vBIT(val, 0, 32)
+#define VXGE_HW_WOL_MP_CRC_RC_EN vxge_mBIT(63)
+/*0x00308*/ u64 wol_mp_mask_a;
+#define VXGE_HW_WOL_MP_MASK_A_MASK(val) vxge_vBIT(val, 0, 64)
+/*0x00310*/ u64 wol_mp_mask_b;
+#define VXGE_HW_WOL_MP_MASK_B_MASK(val) vxge_vBIT(val, 0, 64)
+ u8 unused00360[0x00360-0x00318];
+
+/*0x00360*/ u64 fau_pa_cfg_vpmgmt_clone;
+#define VXGE_HW_FAU_PA_CFG_VPMGMT_CLONE_REPL_L4_COMP_CSUM vxge_mBIT(3)
+#define VXGE_HW_FAU_PA_CFG_VPMGMT_CLONE_REPL_L3_INCL_CF vxge_mBIT(7)
+#define VXGE_HW_FAU_PA_CFG_VPMGMT_CLONE_REPL_L3_COMP_CSUM vxge_mBIT(11)
+/*0x00368*/ u64 rx_datapath_util_vp_clone;
+#define VXGE_HW_RX_DATAPATH_UTIL_VP_CLONE_FAU_RX_UTILIZATION(val) \
+ vxge_vBIT(val, 7, 9)
+#define VXGE_HW_RX_DATAPATH_UTIL_VP_CLONE_RX_UTIL_CFG(val) \
+ vxge_vBIT(val, 16, 4)
+#define VXGE_HW_RX_DATAPATH_UTIL_VP_CLONE_FAU_RX_FRAC_UTIL(val) \
+ vxge_vBIT(val, 20, 4)
+#define VXGE_HW_RX_DATAPATH_UTIL_VP_CLONE_RX_PKT_WEIGHT(val) \
+ vxge_vBIT(val, 24, 4)
+ u8 unused00380[0x00380-0x00370];
+
+/*0x00380*/ u64 tx_datapath_util_vp_clone;
+#define VXGE_HW_TX_DATAPATH_UTIL_VP_CLONE_TPA_TX_UTILIZATION(val) \
+ vxge_vBIT(val, 7, 9)
+#define VXGE_HW_TX_DATAPATH_UTIL_VP_CLONE_TX_UTIL_CFG(val) \
+ vxge_vBIT(val, 16, 4)
+#define VXGE_HW_TX_DATAPATH_UTIL_VP_CLONE_TPA_TX_FRAC_UTIL(val) \
+ vxge_vBIT(val, 20, 4)
+#define VXGE_HW_TX_DATAPATH_UTIL_VP_CLONE_TX_PKT_WEIGHT(val) \
+ vxge_vBIT(val, 24, 4)
+
+} __attribute((packed));
+
+struct vxge_hw_vpath_reg {
+
+ u8 unused00300[0x00300];
+
+/*0x00300*/ u64 usdc_vpath;
+#define VXGE_HW_USDC_VPATH_SGRP_ASSIGN(val) vxge_vBIT(val, 0, 32)
+ u8 unused00a00[0x00a00-0x00308];
+
+/*0x00a00*/ u64 wrdma_alarm_status;
+#define VXGE_HW_WRDMA_ALARM_STATUS_PRC_ALARM_PRC_INT vxge_mBIT(1)
+/*0x00a08*/ u64 wrdma_alarm_mask;
+ u8 unused00a30[0x00a30-0x00a10];
+
+/*0x00a30*/ u64 prc_alarm_reg;
+#define VXGE_HW_PRC_ALARM_REG_PRC_RING_BUMP vxge_mBIT(0)
+#define VXGE_HW_PRC_ALARM_REG_PRC_RXDCM_SC_ERR vxge_mBIT(1)
+#define VXGE_HW_PRC_ALARM_REG_PRC_RXDCM_SC_ABORT vxge_mBIT(2)
+#define VXGE_HW_PRC_ALARM_REG_PRC_QUANTA_SIZE_ERR vxge_mBIT(3)
+/*0x00a38*/ u64 prc_alarm_mask;
+/*0x00a40*/ u64 prc_alarm_alarm;
+/*0x00a48*/ u64 prc_cfg1;
+#define VXGE_HW_PRC_CFG1_RX_TIMER_VAL(val) vxge_vBIT(val, 3, 29)
+#define VXGE_HW_PRC_CFG1_TIM_RING_BUMP_INT_ENABLE vxge_mBIT(34)
+#define VXGE_HW_PRC_CFG1_RTI_TINT_DISABLE vxge_mBIT(35)
+#define VXGE_HW_PRC_CFG1_GREEDY_RETURN vxge_mBIT(36)
+#define VXGE_HW_PRC_CFG1_QUICK_SHOT vxge_mBIT(37)
+#define VXGE_HW_PRC_CFG1_RX_TIMER_CI vxge_mBIT(39)
+#define VXGE_HW_PRC_CFG1_RESET_TIMER_ON_RXD_RET(val) vxge_vBIT(val, 40, 2)
+ u8 unused00a60[0x00a60-0x00a50];
+
+/*0x00a60*/ u64 prc_cfg4;
+#define VXGE_HW_PRC_CFG4_IN_SVC vxge_mBIT(7)
+#define VXGE_HW_PRC_CFG4_RING_MODE(val) vxge_vBIT(val, 14, 2)
+#define VXGE_HW_PRC_CFG4_RXD_NO_SNOOP vxge_mBIT(22)
+#define VXGE_HW_PRC_CFG4_FRM_NO_SNOOP vxge_mBIT(23)
+#define VXGE_HW_PRC_CFG4_RTH_DISABLE vxge_mBIT(31)
+#define VXGE_HW_PRC_CFG4_IGNORE_OWNERSHIP vxge_mBIT(32)
+#define VXGE_HW_PRC_CFG4_SIGNAL_BENIGN_OVFLW vxge_mBIT(36)
+#define VXGE_HW_PRC_CFG4_BIMODAL_INTERRUPT vxge_mBIT(37)
+#define VXGE_HW_PRC_CFG4_BACKOFF_INTERVAL(val) vxge_vBIT(val, 40, 24)
+/*0x00a68*/ u64 prc_cfg5;
+#define VXGE_HW_PRC_CFG5_RXD0_ADD(val) vxge_vBIT(val, 0, 61)
+/*0x00a70*/ u64 prc_cfg6;
+#define VXGE_HW_PRC_CFG6_FRM_PAD_EN vxge_mBIT(0)
+#define VXGE_HW_PRC_CFG6_QSIZE_ALIGNED_RXD vxge_mBIT(2)
+#define VXGE_HW_PRC_CFG6_DOORBELL_MODE_EN vxge_mBIT(5)
+#define VXGE_HW_PRC_CFG6_L3_CPC_TRSFR_CODE_EN vxge_mBIT(8)
+#define VXGE_HW_PRC_CFG6_L4_CPC_TRSFR_CODE_EN vxge_mBIT(9)
+#define VXGE_HW_PRC_CFG6_RXD_CRXDT(val) vxge_vBIT(val, 23, 9)
+#define VXGE_HW_PRC_CFG6_GET_RXD_CRXDT(val) vxge_bVALn(val, 23, 9)
+#define VXGE_HW_PRC_CFG6_RXD_SPAT(val) vxge_vBIT(val, 36, 9)
+#define VXGE_HW_PRC_CFG6_GET_RXD_SPAT(val) vxge_bVALn(val, 36, 9)
+/*0x00a78*/ u64 prc_cfg7;
+#define VXGE_HW_PRC_CFG7_SCATTER_MODE(val) vxge_vBIT(val, 6, 2)
+#define VXGE_HW_PRC_CFG7_SMART_SCAT_EN vxge_mBIT(11)
+#define VXGE_HW_PRC_CFG7_RXD_NS_CHG_EN vxge_mBIT(12)
+#define VXGE_HW_PRC_CFG7_NO_HDR_SEPARATION vxge_mBIT(14)
+#define VXGE_HW_PRC_CFG7_RXD_BUFF_SIZE_MASK(val) vxge_vBIT(val, 20, 4)
+#define VXGE_HW_PRC_CFG7_BUFF_SIZE0_MASK(val) vxge_vBIT(val, 27, 5)
+/*0x00a80*/ u64 tim_dest_addr;
+#define VXGE_HW_TIM_DEST_ADDR_TIM_DEST_ADDR(val) vxge_vBIT(val, 0, 64)
+/*0x00a88*/ u64 prc_rxd_doorbell;
+#define VXGE_HW_PRC_RXD_DOORBELL_NEW_QW_CNT(val) vxge_vBIT(val, 48, 16)
+/*0x00a90*/ u64 rqa_prty_for_vp;
+#define VXGE_HW_RQA_PRTY_FOR_VP_RQA_PRTY_FOR_VP(val) vxge_vBIT(val, 59, 5)
+/*0x00a98*/ u64 rxdmem_size;
+#define VXGE_HW_RXDMEM_SIZE_PRC_RXDMEM_SIZE(val) vxge_vBIT(val, 51, 13)
+/*0x00aa0*/ u64 frm_in_progress_cnt;
+#define VXGE_HW_FRM_IN_PROGRESS_CNT_PRC_FRM_IN_PROGRESS_CNT(val) \
+ vxge_vBIT(val, 59, 5)
+/*0x00aa8*/ u64 rx_multi_cast_stats;
+#define VXGE_HW_RX_MULTI_CAST_STATS_FRAME_DISCARD(val) vxge_vBIT(val, 48, 16)
+/*0x00ab0*/ u64 rx_frm_transferred;
+#define VXGE_HW_RX_FRM_TRANSFERRED_RX_FRM_TRANSFERRED(val) \
+ vxge_vBIT(val, 32, 32)
+/*0x00ab8*/ u64 rxd_returned;
+#define VXGE_HW_RXD_RETURNED_RXD_RETURNED(val) vxge_vBIT(val, 48, 16)
+ u8 unused00c00[0x00c00-0x00ac0];
+
+/*0x00c00*/ u64 kdfc_fifo_trpl_partition;
+#define VXGE_HW_KDFC_FIFO_TRPL_PARTITION_LENGTH_0(val) vxge_vBIT(val, 17, 15)
+#define VXGE_HW_KDFC_FIFO_TRPL_PARTITION_LENGTH_1(val) vxge_vBIT(val, 33, 15)
+#define VXGE_HW_KDFC_FIFO_TRPL_PARTITION_LENGTH_2(val) vxge_vBIT(val, 49, 15)
+/*0x00c08*/ u64 kdfc_fifo_trpl_ctrl;
+#define VXGE_HW_KDFC_FIFO_TRPL_CTRL_TRIPLET_ENABLE vxge_mBIT(7)
+/*0x00c10*/ u64 kdfc_trpl_fifo_0_ctrl;
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_MODE(val) vxge_vBIT(val, 14, 2)
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_FLIP_EN vxge_mBIT(22)
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_SWAP_EN vxge_mBIT(23)
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_INT_CTRL(val) vxge_vBIT(val, 26, 2)
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_CTRL_STRUC vxge_mBIT(28)
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_ADD_PAD vxge_mBIT(29)
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_NO_SNOOP vxge_mBIT(30)
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_RLX_ORD vxge_mBIT(31)
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_SELECT(val) vxge_vBIT(val, 32, 8)
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_INT_NO(val) vxge_vBIT(val, 41, 7)
+#define VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_BIT_MAP(val) vxge_vBIT(val, 48, 16)
+/*0x00c18*/ u64 kdfc_trpl_fifo_1_ctrl;
+#define VXGE_HW_KDFC_TRPL_FIFO_1_CTRL_MODE(val) vxge_vBIT(val, 14, 2)
+#define VXGE_HW_KDFC_TRPL_FIFO_1_CTRL_FLIP_EN vxge_mBIT(22)
+#define VXGE_HW_KDFC_TRPL_FIFO_1_CTRL_SWAP_EN vxge_mBIT(23)
+#define VXGE_HW_KDFC_TRPL_FIFO_1_CTRL_INT_CTRL(val) vxge_vBIT(val, 26, 2)
+#define VXGE_HW_KDFC_TRPL_FIFO_1_CTRL_CTRL_STRUC vxge_mBIT(28)
+#define VXGE_HW_KDFC_TRPL_FIFO_1_CTRL_ADD_PAD vxge_mBIT(29)
+#define VXGE_HW_KDFC_TRPL_FIFO_1_CTRL_NO_SNOOP vxge_mBIT(30)
+#define VXGE_HW_KDFC_TRPL_FIFO_1_CTRL_RLX_ORD vxge_mBIT(31)
+#define VXGE_HW_KDFC_TRPL_FIFO_1_CTRL_SELECT(val) vxge_vBIT(val, 32, 8)
+#define VXGE_HW_KDFC_TRPL_FIFO_1_CTRL_INT_NO(val) vxge_vBIT(val, 41, 7)
+#define VXGE_HW_KDFC_TRPL_FIFO_1_CTRL_BIT_MAP(val) vxge_vBIT(val, 48, 16)
+/*0x00c20*/ u64 kdfc_trpl_fifo_2_ctrl;
+#define VXGE_HW_KDFC_TRPL_FIFO_2_CTRL_FLIP_EN vxge_mBIT(22)
+#define VXGE_HW_KDFC_TRPL_FIFO_2_CTRL_SWAP_EN vxge_mBIT(23)
+#define VXGE_HW_KDFC_TRPL_FIFO_2_CTRL_INT_CTRL(val) vxge_vBIT(val, 26, 2)
+#define VXGE_HW_KDFC_TRPL_FIFO_2_CTRL_CTRL_STRUC vxge_mBIT(28)
+#define VXGE_HW_KDFC_TRPL_FIFO_2_CTRL_ADD_PAD vxge_mBIT(29)
+#define VXGE_HW_KDFC_TRPL_FIFO_2_CTRL_NO_SNOOP vxge_mBIT(30)
+#define VXGE_HW_KDFC_TRPL_FIFO_2_CTRL_RLX_ORD vxge_mBIT(31)
+#define VXGE_HW_KDFC_TRPL_FIFO_2_CTRL_SELECT(val) vxge_vBIT(val, 32, 8)
+#define VXGE_HW_KDFC_TRPL_FIFO_2_CTRL_INT_NO(val) vxge_vBIT(val, 41, 7)
+#define VXGE_HW_KDFC_TRPL_FIFO_2_CTRL_BIT_MAP(val) vxge_vBIT(val, 48, 16)
+/*0x00c28*/ u64 kdfc_trpl_fifo_0_wb_address;
+#define VXGE_HW_KDFC_TRPL_FIFO_0_WB_ADDRESS_ADD(val) vxge_vBIT(val, 0, 64)
+/*0x00c30*/ u64 kdfc_trpl_fifo_1_wb_address;
+#define VXGE_HW_KDFC_TRPL_FIFO_1_WB_ADDRESS_ADD(val) vxge_vBIT(val, 0, 64)
+/*0x00c38*/ u64 kdfc_trpl_fifo_2_wb_address;
+#define VXGE_HW_KDFC_TRPL_FIFO_2_WB_ADDRESS_ADD(val) vxge_vBIT(val, 0, 64)
+/*0x00c40*/ u64 kdfc_trpl_fifo_offset;
+#define VXGE_HW_KDFC_TRPL_FIFO_OFFSET_KDFC_RCTR0(val) vxge_vBIT(val, 1, 15)
+#define VXGE_HW_KDFC_TRPL_FIFO_OFFSET_KDFC_RCTR1(val) vxge_vBIT(val, 17, 15)
+#define VXGE_HW_KDFC_TRPL_FIFO_OFFSET_KDFC_RCTR2(val) vxge_vBIT(val, 33, 15)
+/*0x00c48*/ u64 kdfc_drbl_triplet_total;
+#define VXGE_HW_KDFC_DRBL_TRIPLET_TOTAL_KDFC_MAX_SIZE(val) \
+ vxge_vBIT(val, 17, 15)
+ u8 unused00c60[0x00c60-0x00c50];
+
+/*0x00c60*/ u64 usdc_drbl_ctrl;
+#define VXGE_HW_USDC_DRBL_CTRL_FLIP_EN vxge_mBIT(22)
+#define VXGE_HW_USDC_DRBL_CTRL_SWAP_EN vxge_mBIT(23)
+/*0x00c68*/ u64 usdc_vp_ready;
+#define VXGE_HW_USDC_VP_READY_USDC_HTN_READY vxge_mBIT(7)
+#define VXGE_HW_USDC_VP_READY_USDC_SRQ_READY vxge_mBIT(15)
+#define VXGE_HW_USDC_VP_READY_USDC_CQRQ_READY vxge_mBIT(23)
+/*0x00c70*/ u64 kdfc_status;
+#define VXGE_HW_KDFC_STATUS_KDFC_WRR_0_READY vxge_mBIT(0)
+#define VXGE_HW_KDFC_STATUS_KDFC_WRR_1_READY vxge_mBIT(1)
+#define VXGE_HW_KDFC_STATUS_KDFC_WRR_2_READY vxge_mBIT(2)
+ u8 unused00c80[0x00c80-0x00c78];
+
+/*0x00c80*/ u64 xmac_rpa_vcfg;
+#define VXGE_HW_XMAC_RPA_VCFG_IPV4_TCP_INCL_PH vxge_mBIT(3)
+#define VXGE_HW_XMAC_RPA_VCFG_IPV6_TCP_INCL_PH vxge_mBIT(7)
+#define VXGE_HW_XMAC_RPA_VCFG_IPV4_UDP_INCL_PH vxge_mBIT(11)
+#define VXGE_HW_XMAC_RPA_VCFG_IPV6_UDP_INCL_PH vxge_mBIT(15)
+#define VXGE_HW_XMAC_RPA_VCFG_L4_INCL_CF vxge_mBIT(19)
+#define VXGE_HW_XMAC_RPA_VCFG_STRIP_VLAN_TAG vxge_mBIT(23)
+/*0x00c88*/ u64 rxmac_vcfg0;
+#define VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(val) vxge_vBIT(val, 2, 14)
+#define VXGE_HW_RXMAC_VCFG0_RTS_USE_MIN_LEN vxge_mBIT(19)
+#define VXGE_HW_RXMAC_VCFG0_RTS_MIN_FRM_LEN(val) vxge_vBIT(val, 26, 14)
+#define VXGE_HW_RXMAC_VCFG0_UCAST_ALL_ADDR_EN vxge_mBIT(43)
+#define VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN vxge_mBIT(47)
+#define VXGE_HW_RXMAC_VCFG0_BCAST_EN vxge_mBIT(51)
+#define VXGE_HW_RXMAC_VCFG0_ALL_VID_EN vxge_mBIT(55)
+/*0x00c90*/ u64 rxmac_vcfg1;
+#define VXGE_HW_RXMAC_VCFG1_RTS_RTH_MULTI_IT_BD_MODE(val) vxge_vBIT(val, 42, 2)
+#define VXGE_HW_RXMAC_VCFG1_RTS_RTH_MULTI_IT_EN_MODE vxge_mBIT(47)
+#define VXGE_HW_RXMAC_VCFG1_CONTRIB_L2_FLOW vxge_mBIT(51)
+/*0x00c98*/ u64 rts_access_steer_ctrl;
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(val) vxge_vBIT(val, 1, 7)
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(val) vxge_vBIT(val, 8, 4)
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE vxge_mBIT(15)
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_BEHAV_TBL_SEL vxge_mBIT(23)
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_TABLE_SEL vxge_mBIT(27)
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS vxge_mBIT(0)
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(val) vxge_vBIT(val, 40, 8)
+/* To be used by the privileged driver */
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_VHN(val) vxge_vBIT(val, 48, 8)
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_VFID(val) vxge_vBIT(val, 56, 8)
+/*0x00ca0*/ u64 rts_access_steer_data0;
+#define VXGE_HW_RTS_ACCESS_STEER_DATA0_DATA(val) vxge_vBIT(val, 0, 64)
+/*0x00ca8*/ u64 rts_access_steer_data1;
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_DATA(val) vxge_vBIT(val, 0, 64)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_PRIV_MODE_EN vxge_mBIT(54)
+#define VXGE_HW_RTS_ACCESS_STEER_DATA1_PRIV_MODE_VPN(val) vxge_vBIT(val, 55, 5)
+ u8 unused00d00[0x00d00-0x00cb0];
+
+/*0x00d00*/ u64 xmac_vsport_choice;
+#define VXGE_HW_XMAC_VSPORT_CHOICE_VSPORT_NUMBER(val) vxge_vBIT(val, 3, 5)
+/*0x00d08*/ u64 xmac_stats_cfg;
+/*0x00d10*/ u64 xmac_stats_access_cmd;
+#define VXGE_HW_XMAC_STATS_ACCESS_CMD_OP(val) vxge_vBIT(val, 6, 2)
+#define VXGE_HW_XMAC_STATS_ACCESS_CMD_STROBE vxge_mBIT(15)
+#define VXGE_HW_XMAC_STATS_ACCESS_CMD_OFFSET_SEL(val) vxge_vBIT(val, 32, 8)
+/*0x00d18*/ u64 xmac_stats_access_data;
+#define VXGE_HW_XMAC_STATS_ACCESS_DATA_XSMGR_DATA(val) vxge_vBIT(val, 0, 64)
+/*0x00d20*/ u64 asic_ntwk_vp_ctrl;
+#define VXGE_HW_ASIC_NTWK_VP_CTRL_REQ_TEST_NTWK vxge_mBIT(3)
+#define VXGE_HW_ASIC_NTWK_VP_CTRL_XMACJ_SHOW_PORT_INFO vxge_mBIT(55)
+#define VXGE_HW_ASIC_NTWK_VP_CTRL_XMACJ_PORT_NUM vxge_mBIT(63)
+ u8 unused00d30[0x00d30-0x00d28];
+
+/*0x00d30*/ u64 xgmac_vp_int_status;
+#define VXGE_HW_XGMAC_VP_INT_STATUS_ASIC_NTWK_VP_ERR_ASIC_NTWK_VP_INT \
+ vxge_mBIT(3)
+/*0x00d38*/ u64 xgmac_vp_int_mask;
+/*0x00d40*/ u64 asic_ntwk_vp_err_reg;
+#define VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT vxge_mBIT(3)
+#define VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK vxge_mBIT(7)
+#define VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT_OCCURR \
+ vxge_mBIT(11)
+#define VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK_OCCURR \
+ vxge_mBIT(15)
+#define VXGE_HW_ASIC_NTWK_VP_ERR_REG_XMACJ_NTWK_REAFFIRMED_FAULT \
+ vxge_mBIT(19)
+#define VXGE_HW_ASIC_NTWK_VP_ERR_REG_XMACJ_NTWK_REAFFIRMED_OK vxge_mBIT(23)
+/*0x00d48*/ u64 asic_ntwk_vp_err_mask;
+/*0x00d50*/ u64 asic_ntwk_vp_err_alarm;
+ u8 unused00d80[0x00d80-0x00d58];
+
+/*0x00d80*/ u64 rtdma_bw_ctrl;
+#define VXGE_HW_RTDMA_BW_CTRL_BW_CTRL_EN vxge_mBIT(39)
+#define VXGE_HW_RTDMA_BW_CTRL_DESIRED_BW(val) vxge_vBIT(val, 46, 18)
+/*0x00d88*/ u64 rtdma_rd_optimization_ctrl;
+#define VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_GEN_INT_AFTER_ABORT vxge_mBIT(3)
+#define VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_PAD_MODE(val) vxge_vBIT(val, 6, 2)
+#define VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_PAD_PATTERN(val) vxge_vBIT(val, 8, 8)
+#define VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_WAIT_FOR_SPACE vxge_mBIT(19)
+#define VXGE_HW_PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */
+#define VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_FILL_THRESH(val) \
+ vxge_vBIT(val, 21, 3)
+#define VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_TXD_PYLD_WMARK_EN vxge_mBIT(28)
+#define VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_TXD_PYLD_WMARK(val) \
+ vxge_vBIT(val, 29, 3)
+#define VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_ADDR_BDRY_EN vxge_mBIT(35)
+#define VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_ADDR_BDRY(val) \
+ vxge_vBIT(val, 37, 3)
+#define VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_TXD_WAIT_FOR_SPACE vxge_mBIT(43)
+#define VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_TXD_FILL_THRESH(val) \
+ vxge_vBIT(val, 51, 5)
+#define VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_TXD_ADDR_BDRY_EN vxge_mBIT(59)
+#define VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_TXD_ADDR_BDRY(val) \
+ vxge_vBIT(val, 61, 3)
+/*0x00d90*/ u64 pda_pcc_job_monitor;
+#define VXGE_HW_PDA_PCC_JOB_MONITOR_PDA_PCC_JOB_STATUS vxge_mBIT(7)
+/*0x00d98*/ u64 tx_protocol_assist_cfg;
+#define VXGE_HW_TX_PROTOCOL_ASSIST_CFG_LSOV2_EN vxge_mBIT(6)
+#define VXGE_HW_TX_PROTOCOL_ASSIST_CFG_IPV6_KEEP_SEARCHING vxge_mBIT(7)
+ u8 unused01000[0x01000-0x00da0];
+
+/*0x01000*/ u64 tim_cfg1_int_num[4];
+#define VXGE_HW_TIM_CFG1_INT_NUM_BTIMER_VAL(val) vxge_vBIT(val, 6, 26)
+#define VXGE_HW_TIM_CFG1_INT_NUM_BITMP_EN vxge_mBIT(35)
+#define VXGE_HW_TIM_CFG1_INT_NUM_TXFRM_CNT_EN vxge_mBIT(36)
+#define VXGE_HW_TIM_CFG1_INT_NUM_TXD_CNT_EN vxge_mBIT(37)
+#define VXGE_HW_TIM_CFG1_INT_NUM_TIMER_AC vxge_mBIT(38)
+#define VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI vxge_mBIT(39)
+#define VXGE_HW_TIM_CFG1_INT_NUM_URNG_A(val) vxge_vBIT(val, 41, 7)
+#define VXGE_HW_TIM_CFG1_INT_NUM_URNG_B(val) vxge_vBIT(val, 49, 7)
+#define VXGE_HW_TIM_CFG1_INT_NUM_URNG_C(val) vxge_vBIT(val, 57, 7)
+/*0x01020*/ u64 tim_cfg2_int_num[4];
+#define VXGE_HW_TIM_CFG2_INT_NUM_UEC_A(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_TIM_CFG2_INT_NUM_UEC_B(val) vxge_vBIT(val, 16, 16)
+#define VXGE_HW_TIM_CFG2_INT_NUM_UEC_C(val) vxge_vBIT(val, 32, 16)
+#define VXGE_HW_TIM_CFG2_INT_NUM_UEC_D(val) vxge_vBIT(val, 48, 16)
+/*0x01040*/ u64 tim_cfg3_int_num[4];
+#define VXGE_HW_TIM_CFG3_INT_NUM_TIMER_RI vxge_mBIT(0)
+#define VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_EVENT_SF(val) vxge_vBIT(val, 1, 4)
+#define VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(val) vxge_vBIT(val, 6, 26)
+#define VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(val) vxge_vBIT(val, 32, 6)
+#define VXGE_HW_TIM_CFG3_INT_NUM_LTIMER_VAL(val) vxge_vBIT(val, 38, 26)
+/*0x01060*/ u64 tim_wrkld_clc;
+#define VXGE_HW_TIM_WRKLD_CLC_WRKLD_EVAL_PRD(val) vxge_vBIT(val, 0, 32)
+#define VXGE_HW_TIM_WRKLD_CLC_WRKLD_EVAL_DIV(val) vxge_vBIT(val, 35, 5)
+#define VXGE_HW_TIM_WRKLD_CLC_CNT_FRM_BYTE vxge_mBIT(40)
+#define VXGE_HW_TIM_WRKLD_CLC_CNT_RX_TX(val) vxge_vBIT(val, 41, 2)
+#define VXGE_HW_TIM_WRKLD_CLC_CNT_LNK_EN vxge_mBIT(43)
+#define VXGE_HW_TIM_WRKLD_CLC_HOST_UTIL(val) vxge_vBIT(val, 57, 7)
+/*0x01068*/ u64 tim_bitmap;
+#define VXGE_HW_TIM_BITMAP_MASK(val) vxge_vBIT(val, 0, 32)
+#define VXGE_HW_TIM_BITMAP_LLROOT_RXD_EN vxge_mBIT(32)
+#define VXGE_HW_TIM_BITMAP_LLROOT_TXD_EN vxge_mBIT(33)
+/*0x01070*/ u64 tim_ring_assn;
+#define VXGE_HW_TIM_RING_ASSN_INT_NUM(val) vxge_vBIT(val, 6, 2)
+/*0x01078*/ u64 tim_remap;
+#define VXGE_HW_TIM_REMAP_TX_EN vxge_mBIT(5)
+#define VXGE_HW_TIM_REMAP_RX_EN vxge_mBIT(6)
+#define VXGE_HW_TIM_REMAP_OFFLOAD_EN vxge_mBIT(7)
+#define VXGE_HW_TIM_REMAP_TO_VPATH_NUM(val) vxge_vBIT(val, 11, 5)
+/*0x01080*/ u64 tim_vpath_map;
+#define VXGE_HW_TIM_VPATH_MAP_BMAP_ROOT(val) vxge_vBIT(val, 0, 32)
+/*0x01088*/ u64 tim_pci_cfg;
+#define VXGE_HW_TIM_PCI_CFG_ADD_PAD vxge_mBIT(7)
+#define VXGE_HW_TIM_PCI_CFG_NO_SNOOP vxge_mBIT(15)
+#define VXGE_HW_TIM_PCI_CFG_RELAXED vxge_mBIT(23)
+#define VXGE_HW_TIM_PCI_CFG_CTL_STR vxge_mBIT(31)
+ u8 unused01100[0x01100-0x01090];
+
+/*0x01100*/ u64 sgrp_assign;
+#define VXGE_HW_SGRP_ASSIGN_SGRP_ASSIGN(val) vxge_vBIT(val, 0, 64)
+/*0x01108*/ u64 sgrp_aoa_and_result;
+#define VXGE_HW_SGRP_AOA_AND_RESULT_PET_SGRP_AOA_AND_RESULT(val) \
+ vxge_vBIT(val, 0, 64)
+/*0x01110*/ u64 rpe_pci_cfg;
+#define VXGE_HW_RPE_PCI_CFG_PAD_LRO_DATA_ENABLE vxge_mBIT(7)
+#define VXGE_HW_RPE_PCI_CFG_PAD_LRO_HDR_ENABLE vxge_mBIT(8)
+#define VXGE_HW_RPE_PCI_CFG_PAD_LRO_CQE_ENABLE vxge_mBIT(9)
+#define VXGE_HW_RPE_PCI_CFG_PAD_NONLL_CQE_ENABLE vxge_mBIT(10)
+#define VXGE_HW_RPE_PCI_CFG_PAD_BASE_LL_CQE_ENABLE vxge_mBIT(11)
+#define VXGE_HW_RPE_PCI_CFG_PAD_LL_CQE_IDATA_ENABLE vxge_mBIT(12)
+#define VXGE_HW_RPE_PCI_CFG_PAD_CQRQ_IR_ENABLE vxge_mBIT(13)
+#define VXGE_HW_RPE_PCI_CFG_PAD_CQSQ_IR_ENABLE vxge_mBIT(14)
+#define VXGE_HW_RPE_PCI_CFG_PAD_CQRR_IR_ENABLE vxge_mBIT(15)
+#define VXGE_HW_RPE_PCI_CFG_NOSNOOP_DATA vxge_mBIT(18)
+#define VXGE_HW_RPE_PCI_CFG_NOSNOOP_NONLL_CQE vxge_mBIT(19)
+#define VXGE_HW_RPE_PCI_CFG_NOSNOOP_LL_CQE vxge_mBIT(20)
+#define VXGE_HW_RPE_PCI_CFG_NOSNOOP_CQRQ_IR vxge_mBIT(21)
+#define VXGE_HW_RPE_PCI_CFG_NOSNOOP_CQSQ_IR vxge_mBIT(22)
+#define VXGE_HW_RPE_PCI_CFG_NOSNOOP_CQRR_IR vxge_mBIT(23)
+#define VXGE_HW_RPE_PCI_CFG_RELAXED_DATA vxge_mBIT(26)
+#define VXGE_HW_RPE_PCI_CFG_RELAXED_NONLL_CQE vxge_mBIT(27)
+#define VXGE_HW_RPE_PCI_CFG_RELAXED_LL_CQE vxge_mBIT(28)
+#define VXGE_HW_RPE_PCI_CFG_RELAXED_CQRQ_IR vxge_mBIT(29)
+#define VXGE_HW_RPE_PCI_CFG_RELAXED_CQSQ_IR vxge_mBIT(30)
+#define VXGE_HW_RPE_PCI_CFG_RELAXED_CQRR_IR vxge_mBIT(31)
+/*0x01118*/ u64 rpe_lro_cfg;
+#define VXGE_HW_RPE_LRO_CFG_SUPPRESS_LRO_ETH_TRLR vxge_mBIT(7)
+#define VXGE_HW_RPE_LRO_CFG_ALLOW_LRO_SNAP_SNAPJUMBO_MRG vxge_mBIT(11)
+#define VXGE_HW_RPE_LRO_CFG_ALLOW_LRO_LLC_LLCJUMBO_MRG vxge_mBIT(15)
+#define VXGE_HW_RPE_LRO_CFG_INCL_ACK_CNT_IN_CQE vxge_mBIT(23)
+/*0x01120*/ u64 pe_mr2vp_ack_blk_limit;
+#define VXGE_HW_PE_MR2VP_ACK_BLK_LIMIT_BLK_LIMIT(val) vxge_vBIT(val, 32, 32)
+/*0x01128*/ u64 pe_mr2vp_rirr_lirr_blk_limit;
+#define VXGE_HW_PE_MR2VP_RIRR_LIRR_BLK_LIMIT_RIRR_BLK_LIMIT(val) \
+ vxge_vBIT(val, 0, 32)
+#define VXGE_HW_PE_MR2VP_RIRR_LIRR_BLK_LIMIT_LIRR_BLK_LIMIT(val) \
+ vxge_vBIT(val, 32, 32)
+/*0x01130*/ u64 txpe_pci_nce_cfg;
+#define VXGE_HW_TXPE_PCI_NCE_CFG_NCE_THRESH(val) vxge_vBIT(val, 0, 32)
+#define VXGE_HW_TXPE_PCI_NCE_CFG_PAD_TOWI_ENABLE vxge_mBIT(55)
+#define VXGE_HW_TXPE_PCI_NCE_CFG_NOSNOOP_TOWI vxge_mBIT(63)
+ u8 unused01180[0x01180-0x01138];
+
+/*0x01180*/ u64 msg_qpad_en_cfg;
+#define VXGE_HW_MSG_QPAD_EN_CFG_UMQ_BWR_READ vxge_mBIT(3)
+#define VXGE_HW_MSG_QPAD_EN_CFG_DMQ_BWR_READ vxge_mBIT(7)
+#define VXGE_HW_MSG_QPAD_EN_CFG_MXP_GENDMA_READ vxge_mBIT(11)
+#define VXGE_HW_MSG_QPAD_EN_CFG_UXP_GENDMA_READ vxge_mBIT(15)
+#define VXGE_HW_MSG_QPAD_EN_CFG_UMQ_MSG_WRITE vxge_mBIT(19)
+#define VXGE_HW_MSG_QPAD_EN_CFG_UMQDMQ_IR_WRITE vxge_mBIT(23)
+#define VXGE_HW_MSG_QPAD_EN_CFG_MXP_GENDMA_WRITE vxge_mBIT(27)
+#define VXGE_HW_MSG_QPAD_EN_CFG_UXP_GENDMA_WRITE vxge_mBIT(31)
+/*0x01188*/ u64 msg_pci_cfg;
+#define VXGE_HW_MSG_PCI_CFG_GENDMA_NO_SNOOP vxge_mBIT(3)
+#define VXGE_HW_MSG_PCI_CFG_UMQDMQ_IR_NO_SNOOP vxge_mBIT(7)
+#define VXGE_HW_MSG_PCI_CFG_UMQ_NO_SNOOP vxge_mBIT(11)
+#define VXGE_HW_MSG_PCI_CFG_DMQ_NO_SNOOP vxge_mBIT(15)
+/*0x01190*/ u64 umqdmq_ir_init;
+#define VXGE_HW_UMQDMQ_IR_INIT_HOST_WRITE_ADD(val) vxge_vBIT(val, 0, 64)
+/*0x01198*/ u64 dmq_ir_int;
+#define VXGE_HW_DMQ_IR_INT_IMMED_ENABLE vxge_mBIT(6)
+#define VXGE_HW_DMQ_IR_INT_EVENT_ENABLE vxge_mBIT(7)
+#define VXGE_HW_DMQ_IR_INT_NUMBER(val) vxge_vBIT(val, 9, 7)
+#define VXGE_HW_DMQ_IR_INT_BITMAP(val) vxge_vBIT(val, 16, 16)
+/*0x011a0*/ u64 dmq_bwr_init_add;
+#define VXGE_HW_DMQ_BWR_INIT_ADD_HOST(val) vxge_vBIT(val, 0, 64)
+/*0x011a8*/ u64 dmq_bwr_init_byte;
+#define VXGE_HW_DMQ_BWR_INIT_BYTE_COUNT(val) vxge_vBIT(val, 0, 32)
+/*0x011b0*/ u64 dmq_ir;
+#define VXGE_HW_DMQ_IR_POLICY(val) vxge_vBIT(val, 0, 8)
+/*0x011b8*/ u64 umq_int;
+#define VXGE_HW_UMQ_INT_IMMED_ENABLE vxge_mBIT(6)
+#define VXGE_HW_UMQ_INT_EVENT_ENABLE vxge_mBIT(7)
+#define VXGE_HW_UMQ_INT_NUMBER(val) vxge_vBIT(val, 9, 7)
+#define VXGE_HW_UMQ_INT_BITMAP(val) vxge_vBIT(val, 16, 16)
+/*0x011c0*/ u64 umq_mr2vp_bwr_pfch_init;
+#define VXGE_HW_UMQ_MR2VP_BWR_PFCH_INIT_NUMBER(val) vxge_vBIT(val, 0, 8)
+/*0x011c8*/ u64 umq_bwr_pfch_ctrl;
+#define VXGE_HW_UMQ_BWR_PFCH_CTRL_POLL_EN vxge_mBIT(3)
+/*0x011d0*/ u64 umq_mr2vp_bwr_eol;
+#define VXGE_HW_UMQ_MR2VP_BWR_EOL_POLL_LATENCY(val) vxge_vBIT(val, 32, 32)
+/*0x011d8*/ u64 umq_bwr_init_add;
+#define VXGE_HW_UMQ_BWR_INIT_ADD_HOST(val) vxge_vBIT(val, 0, 64)
+/*0x011e0*/ u64 umq_bwr_init_byte;
+#define VXGE_HW_UMQ_BWR_INIT_BYTE_COUNT(val) vxge_vBIT(val, 0, 32)
+/*0x011e8*/ u64 gendma_int;
+/*0x011f0*/ u64 umqdmq_ir_init_notify;
+#define VXGE_HW_UMQDMQ_IR_INIT_NOTIFY_PULSE vxge_mBIT(3)
+/*0x011f8*/ u64 dmq_init_notify;
+#define VXGE_HW_DMQ_INIT_NOTIFY_PULSE vxge_mBIT(3)
+/*0x01200*/ u64 umq_init_notify;
+#define VXGE_HW_UMQ_INIT_NOTIFY_PULSE vxge_mBIT(3)
+ u8 unused01380[0x01380-0x01208];
+
+/*0x01380*/ u64 tpa_cfg;
+#define VXGE_HW_TPA_CFG_IGNORE_FRAME_ERR vxge_mBIT(3)
+#define VXGE_HW_TPA_CFG_IPV6_STOP_SEARCHING vxge_mBIT(7)
+#define VXGE_HW_TPA_CFG_L4_PSHDR_PRESENT vxge_mBIT(11)
+#define VXGE_HW_TPA_CFG_SUPPORT_MOBILE_IPV6_HDRS vxge_mBIT(15)
+ u8 unused01400[0x01400-0x01388];
+
+/*0x01400*/ u64 tx_vp_reset_discarded_frms;
+#define VXGE_HW_TX_VP_RESET_DISCARDED_FRMS_TX_VP_RESET_DISCARDED_FRMS(val) \
+ vxge_vBIT(val, 48, 16)
+ u8 unused01480[0x01480-0x01408];
+
+/*0x01480*/ u64 fau_rpa_vcfg;
+#define VXGE_HW_FAU_RPA_VCFG_L4_COMP_CSUM vxge_mBIT(7)
+#define VXGE_HW_FAU_RPA_VCFG_L3_INCL_CF vxge_mBIT(11)
+#define VXGE_HW_FAU_RPA_VCFG_L3_COMP_CSUM vxge_mBIT(15)
+ u8 unused014d0[0x014d0-0x01488];
+
+/*0x014d0*/ u64 dbg_stats_rx_mpa;
+#define VXGE_HW_DBG_STATS_RX_MPA_CRC_FAIL_FRMS(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_DBG_STATS_RX_MPA_MRK_FAIL_FRMS(val) vxge_vBIT(val, 16, 16)
+#define VXGE_HW_DBG_STATS_RX_MPA_LEN_FAIL_FRMS(val) vxge_vBIT(val, 32, 16)
+/*0x014d8*/ u64 dbg_stats_rx_fau;
+#define VXGE_HW_DBG_STATS_RX_FAU_RX_WOL_FRMS(val) vxge_vBIT(val, 0, 16)
+#define VXGE_HW_DBG_STATS_RX_FAU_RX_VP_RESET_DISCARDED_FRMS(val) \
+ vxge_vBIT(val, 16, 16)
+#define VXGE_HW_DBG_STATS_RX_FAU_RX_PERMITTED_FRMS(val) \
+ vxge_vBIT(val, 32, 32)
+ u8 unused014f0[0x014f0-0x014e0];
+
+/*0x014f0*/ u64 fbmc_vp_rdy;
+#define VXGE_HW_FBMC_VP_RDY_QUEUE_SPAV_FM vxge_mBIT(0)
+ u8 unused01e00[0x01e00-0x014f8];
+
+/*0x01e00*/ u64 vpath_pcipif_int_status;
+#define \
+VXGE_HW_VPATH_PCIPIF_INT_STATUS_SRPCIM_MSG_TO_VPATH_SRPCIM_MSG_TO_VPATH_INT \
+ vxge_mBIT(3)
+#define VXGE_HW_VPATH_PCIPIF_INT_STATUS_VPATH_SPARE_R1_VPATH_SPARE_R1_INT \
+ vxge_mBIT(7)
+/*0x01e08*/ u64 vpath_pcipif_int_mask;
+ u8 unused01e20[0x01e20-0x01e10];
+
+/*0x01e20*/ u64 srpcim_msg_to_vpath_reg;
+#define VXGE_HW_SRPCIM_MSG_TO_VPATH_REG_SWIF_SRPCIM_TO_VPATH_RMSG_INT \
+ vxge_mBIT(3)
+/*0x01e28*/ u64 srpcim_msg_to_vpath_mask;
+/*0x01e30*/ u64 srpcim_msg_to_vpath_alarm;
+ u8 unused01ea0[0x01ea0-0x01e38];
+
+/*0x01ea0*/ u64 vpath_to_srpcim_wmsg;
+#define VXGE_HW_VPATH_TO_SRPCIM_WMSG_VPATH_TO_SRPCIM_WMSG(val) \
+ vxge_vBIT(val, 0, 64)
+/*0x01ea8*/ u64 vpath_to_srpcim_wmsg_trig;
+#define VXGE_HW_VPATH_TO_SRPCIM_WMSG_TRIG_VPATH_TO_SRPCIM_WMSG_TRIG \
+ vxge_mBIT(0)
+ u8 unused02000[0x02000-0x01eb0];
+
+/*0x02000*/ u64 vpath_general_int_status;
+#define VXGE_HW_VPATH_GENERAL_INT_STATUS_PIC_INT vxge_mBIT(3)
+#define VXGE_HW_VPATH_GENERAL_INT_STATUS_PCI_INT vxge_mBIT(7)
+#define VXGE_HW_VPATH_GENERAL_INT_STATUS_WRDMA_INT vxge_mBIT(15)
+#define VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT vxge_mBIT(19)
+/*0x02008*/ u64 vpath_general_int_mask;
+#define VXGE_HW_VPATH_GENERAL_INT_MASK_PIC_INT vxge_mBIT(3)
+#define VXGE_HW_VPATH_GENERAL_INT_MASK_PCI_INT vxge_mBIT(7)
+#define VXGE_HW_VPATH_GENERAL_INT_MASK_WRDMA_INT vxge_mBIT(15)
+#define VXGE_HW_VPATH_GENERAL_INT_MASK_XMAC_INT vxge_mBIT(19)
+/*0x02010*/ u64 vpath_ppif_int_status;
+#define VXGE_HW_VPATH_PPIF_INT_STATUS_KDFCCTL_ERRORS_KDFCCTL_INT \
+ vxge_mBIT(3)
+#define VXGE_HW_VPATH_PPIF_INT_STATUS_GENERAL_ERRORS_GENERAL_INT \
+ vxge_mBIT(7)
+#define VXGE_HW_VPATH_PPIF_INT_STATUS_PCI_CONFIG_ERRORS_PCI_CONFIG_INT \
+ vxge_mBIT(11)
+#define \
+VXGE_HW_VPATH_PPIF_INT_STATUS_MRPCIM_TO_VPATH_ALARM_MRPCIM_TO_VPATH_ALARM_INT \
+ vxge_mBIT(15)
+#define \
+VXGE_HW_VPATH_PPIF_INT_STATUS_SRPCIM_TO_VPATH_ALARM_SRPCIM_TO_VPATH_ALARM_INT \
+ vxge_mBIT(19)
+/*0x02018*/ u64 vpath_ppif_int_mask;
+/*0x02020*/ u64 kdfcctl_errors_reg;
+#define VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_OVRWR vxge_mBIT(3)
+#define VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_OVRWR vxge_mBIT(7)
+#define VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_OVRWR vxge_mBIT(11)
+#define VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_POISON vxge_mBIT(15)
+#define VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_POISON vxge_mBIT(19)
+#define VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_POISON vxge_mBIT(23)
+#define VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_DMA_ERR vxge_mBIT(31)
+#define VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_DMA_ERR vxge_mBIT(35)
+#define VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_DMA_ERR vxge_mBIT(39)
+/*0x02028*/ u64 kdfcctl_errors_mask;
+/*0x02030*/ u64 kdfcctl_errors_alarm;
+ u8 unused02040[0x02040-0x02038];
+
+/*0x02040*/ u64 general_errors_reg;
+#define VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO0_OVRFLOW vxge_mBIT(3)
+#define VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO1_OVRFLOW vxge_mBIT(7)
+#define VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO2_OVRFLOW vxge_mBIT(11)
+#define VXGE_HW_GENERAL_ERRORS_REG_STATSB_PIF_CHAIN_ERR vxge_mBIT(15)
+#define VXGE_HW_GENERAL_ERRORS_REG_STATSB_DROP_TIMEOUT_REQ vxge_mBIT(19)
+#define VXGE_HW_GENERAL_ERRORS_REG_TGT_ILLEGAL_ACCESS vxge_mBIT(27)
+#define VXGE_HW_GENERAL_ERRORS_REG_INI_SERR_DET vxge_mBIT(31)
+/*0x02048*/ u64 general_errors_mask;
+/*0x02050*/ u64 general_errors_alarm;
+/*0x02058*/ u64 pci_config_errors_reg;
+#define VXGE_HW_PCI_CONFIG_ERRORS_REG_PCICONFIG_STATUS_ERR vxge_mBIT(3)
+#define VXGE_HW_PCI_CONFIG_ERRORS_REG_PCICONFIG_UNCOR_ERR vxge_mBIT(7)
+#define VXGE_HW_PCI_CONFIG_ERRORS_REG_PCICONFIG_COR_ERR vxge_mBIT(11)
+/*0x02060*/ u64 pci_config_errors_mask;
+/*0x02068*/ u64 pci_config_errors_alarm;
+/*0x02070*/ u64 mrpcim_to_vpath_alarm_reg;
+#define VXGE_HW_MRPCIM_TO_VPATH_ALARM_REG_PPIF_MRPCIM_TO_VPATH_ALARM \
+ vxge_mBIT(3)
+/*0x02078*/ u64 mrpcim_to_vpath_alarm_mask;
+/*0x02080*/ u64 mrpcim_to_vpath_alarm_alarm;
+/*0x02088*/ u64 srpcim_to_vpath_alarm_reg;
+#define VXGE_HW_SRPCIM_TO_VPATH_ALARM_REG_PPIF_SRPCIM_TO_VPATH_ALARM(val) \
+ vxge_vBIT(val, 0, 17)
+/*0x02090*/ u64 srpcim_to_vpath_alarm_mask;
+/*0x02098*/ u64 srpcim_to_vpath_alarm_alarm;
+ u8 unused02108[0x02108-0x020a0];
+
+/*0x02108*/ u64 kdfcctl_status;
+#define VXGE_HW_KDFCCTL_STATUS_KDFCCTL_FIFO0_PRES(val) vxge_vBIT(val, 0, 8)
+#define VXGE_HW_KDFCCTL_STATUS_KDFCCTL_FIFO1_PRES(val) vxge_vBIT(val, 8, 8)
+#define VXGE_HW_KDFCCTL_STATUS_KDFCCTL_FIFO2_PRES(val) vxge_vBIT(val, 16, 8)
+#define VXGE_HW_KDFCCTL_STATUS_KDFCCTL_FIFO0_OVRWR(val) vxge_vBIT(val, 24, 8)
+#define VXGE_HW_KDFCCTL_STATUS_KDFCCTL_FIFO1_OVRWR(val) vxge_vBIT(val, 32, 8)
+#define VXGE_HW_KDFCCTL_STATUS_KDFCCTL_FIFO2_OVRWR(val) vxge_vBIT(val, 40, 8)
+/*0x02110*/ u64 rsthdlr_status;
+#define VXGE_HW_RSTHDLR_STATUS_RSTHDLR_CURRENT_RESET vxge_mBIT(3)
+#define VXGE_HW_RSTHDLR_STATUS_RSTHDLR_CURRENT_VPIN(val) vxge_vBIT(val, 6, 2)
+/*0x02118*/ u64 fifo0_status;
+#define VXGE_HW_FIFO0_STATUS_DBLGEN_FIFO0_RDIDX(val) vxge_vBIT(val, 0, 12)
+/*0x02120*/ u64 fifo1_status;
+#define VXGE_HW_FIFO1_STATUS_DBLGEN_FIFO1_RDIDX(val) vxge_vBIT(val, 0, 12)
+/*0x02128*/ u64 fifo2_status;
+#define VXGE_HW_FIFO2_STATUS_DBLGEN_FIFO2_RDIDX(val) vxge_vBIT(val, 0, 12)
+ u8 unused02158[0x02158-0x02130];
+
+/*0x02158*/ u64 tgt_illegal_access;
+#define VXGE_HW_TGT_ILLEGAL_ACCESS_SWIF_REGION(val) vxge_vBIT(val, 1, 7)
+ u8 unused02200[0x02200-0x02160];
+
+/*0x02200*/ u64 vpath_general_cfg1;
+#define VXGE_HW_VPATH_GENERAL_CFG1_TC_VALUE(val) vxge_vBIT(val, 1, 3)
+#define VXGE_HW_VPATH_GENERAL_CFG1_DATA_BYTE_SWAPEN vxge_mBIT(7)
+#define VXGE_HW_VPATH_GENERAL_CFG1_DATA_FLIPEN vxge_mBIT(11)
+#define VXGE_HW_VPATH_GENERAL_CFG1_CTL_BYTE_SWAPEN vxge_mBIT(15)
+#define VXGE_HW_VPATH_GENERAL_CFG1_CTL_FLIPEN vxge_mBIT(23)
+#define VXGE_HW_VPATH_GENERAL_CFG1_MSIX_ADDR_SWAPEN vxge_mBIT(51)
+#define VXGE_HW_VPATH_GENERAL_CFG1_MSIX_ADDR_FLIPEN vxge_mBIT(55)
+#define VXGE_HW_VPATH_GENERAL_CFG1_MSIX_DATA_SWAPEN vxge_mBIT(59)
+#define VXGE_HW_VPATH_GENERAL_CFG1_MSIX_DATA_FLIPEN vxge_mBIT(63)
+/*0x02208*/ u64 vpath_general_cfg2;
+#define VXGE_HW_VPATH_GENERAL_CFG2_SIZE_QUANTUM(val) vxge_vBIT(val, 1, 3)
+/*0x02210*/ u64 vpath_general_cfg3;
+#define VXGE_HW_VPATH_GENERAL_CFG3_IGNORE_VPATH_RST_FOR_INTA vxge_mBIT(3)
+ u8 unused02220[0x02220-0x02218];
+
+/*0x02220*/ u64 kdfcctl_cfg0;
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_SWAPEN_FIFO0 vxge_mBIT(1)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_SWAPEN_FIFO1 vxge_mBIT(2)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_SWAPEN_FIFO2 vxge_mBIT(3)
+#define VXGE_HW_KDFCCTL_CFG0_BIT_FLIPEN_FIFO0 vxge_mBIT(5)
+#define VXGE_HW_KDFCCTL_CFG0_BIT_FLIPEN_FIFO1 vxge_mBIT(6)
+#define VXGE_HW_KDFCCTL_CFG0_BIT_FLIPEN_FIFO2 vxge_mBIT(7)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE0_FIFO0 vxge_mBIT(9)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE0_FIFO1 vxge_mBIT(10)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE0_FIFO2 vxge_mBIT(11)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE1_FIFO0 vxge_mBIT(13)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE1_FIFO1 vxge_mBIT(14)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE1_FIFO2 vxge_mBIT(15)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE2_FIFO0 vxge_mBIT(17)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE2_FIFO1 vxge_mBIT(18)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE2_FIFO2 vxge_mBIT(19)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE3_FIFO0 vxge_mBIT(21)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE3_FIFO1 vxge_mBIT(22)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE3_FIFO2 vxge_mBIT(23)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE4_FIFO0 vxge_mBIT(25)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE4_FIFO1 vxge_mBIT(26)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE4_FIFO2 vxge_mBIT(27)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE5_FIFO0 vxge_mBIT(29)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE5_FIFO1 vxge_mBIT(30)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE5_FIFO2 vxge_mBIT(31)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE6_FIFO0 vxge_mBIT(33)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE6_FIFO1 vxge_mBIT(34)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE6_FIFO2 vxge_mBIT(35)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE7_FIFO0 vxge_mBIT(37)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE7_FIFO1 vxge_mBIT(38)
+#define VXGE_HW_KDFCCTL_CFG0_BYTE_MASK_BYTE7_FIFO2 vxge_mBIT(39)
+
+ u8 unused02268[0x02268-0x02228];
+
+/*0x02268*/ u64 stats_cfg;
+#define VXGE_HW_STATS_CFG_START_HOST_ADDR(val) vxge_vBIT(val, 0, 57)
+/*0x02270*/ u64 interrupt_cfg0;
+#define VXGE_HW_INTERRUPT_CFG0_MSIX_FOR_RXTI(val) vxge_vBIT(val, 1, 7)
+#define VXGE_HW_INTERRUPT_CFG0_GROUP0_MSIX_FOR_TXTI(val) vxge_vBIT(val, 9, 7)
+#define VXGE_HW_INTERRUPT_CFG0_GROUP1_MSIX_FOR_TXTI(val) vxge_vBIT(val, 17, 7)
+#define VXGE_HW_INTERRUPT_CFG0_GROUP2_MSIX_FOR_TXTI(val) vxge_vBIT(val, 25, 7)
+#define VXGE_HW_INTERRUPT_CFG0_GROUP3_MSIX_FOR_TXTI(val) vxge_vBIT(val, 33, 7)
+ u8 unused02280[0x02280-0x02278];
+
+/*0x02280*/ u64 interrupt_cfg2;
+#define VXGE_HW_INTERRUPT_CFG2_ALARM_MAP_TO_MSG(val) vxge_vBIT(val, 1, 7)
+/*0x02288*/ u64 one_shot_vect0_en;
+#define VXGE_HW_ONE_SHOT_VECT0_EN_ONE_SHOT_VECT0_EN vxge_mBIT(3)
+/*0x02290*/ u64 one_shot_vect1_en;
+#define VXGE_HW_ONE_SHOT_VECT1_EN_ONE_SHOT_VECT1_EN vxge_mBIT(3)
+/*0x02298*/ u64 one_shot_vect2_en;
+#define VXGE_HW_ONE_SHOT_VECT2_EN_ONE_SHOT_VECT2_EN vxge_mBIT(3)
+/*0x022a0*/ u64 one_shot_vect3_en;
+#define VXGE_HW_ONE_SHOT_VECT3_EN_ONE_SHOT_VECT3_EN vxge_mBIT(3)
+ u8 unused022b0[0x022b0-0x022a8];
+
+/*0x022b0*/ u64 pci_config_access_cfg1;
+#define VXGE_HW_PCI_CONFIG_ACCESS_CFG1_ADDRESS(val) vxge_vBIT(val, 0, 12)
+#define VXGE_HW_PCI_CONFIG_ACCESS_CFG1_SEL_FUNC0 vxge_mBIT(15)
+/*0x022b8*/ u64 pci_config_access_cfg2;
+#define VXGE_HW_PCI_CONFIG_ACCESS_CFG2_REQ vxge_mBIT(0)
+/*0x022c0*/ u64 pci_config_access_status;
+#define VXGE_HW_PCI_CONFIG_ACCESS_STATUS_ACCESS_ERR vxge_mBIT(0)
+#define VXGE_HW_PCI_CONFIG_ACCESS_STATUS_DATA(val) vxge_vBIT(val, 32, 32)
+ u8 unused02300[0x02300-0x022c8];
+
+/*0x02300*/ u64 vpath_debug_stats0;
+#define VXGE_HW_VPATH_DEBUG_STATS0_INI_NUM_MWR_SENT(val) vxge_vBIT(val, 0, 32)
+/*0x02308*/ u64 vpath_debug_stats1;
+#define VXGE_HW_VPATH_DEBUG_STATS1_INI_NUM_MRD_SENT(val) vxge_vBIT(val, 0, 32)
+/*0x02310*/ u64 vpath_debug_stats2;
+#define VXGE_HW_VPATH_DEBUG_STATS2_INI_NUM_CPL_RCVD(val) vxge_vBIT(val, 0, 32)
+/*0x02318*/ u64 vpath_debug_stats3;
+#define VXGE_HW_VPATH_DEBUG_STATS3_INI_NUM_MWR_BYTE_SENT(val) \
+ vxge_vBIT(val, 0, 64)
+/*0x02320*/ u64 vpath_debug_stats4;
+#define VXGE_HW_VPATH_DEBUG_STATS4_INI_NUM_CPL_BYTE_RCVD(val) \
+ vxge_vBIT(val, 0, 64)
+/*0x02328*/ u64 vpath_debug_stats5;
+#define VXGE_HW_VPATH_DEBUG_STATS5_WRCRDTARB_XOFF(val) vxge_vBIT(val, 32, 32)
+/*0x02330*/ u64 vpath_debug_stats6;
+#define VXGE_HW_VPATH_DEBUG_STATS6_RDCRDTARB_XOFF(val) vxge_vBIT(val, 32, 32)
+/*0x02338*/ u64 vpath_genstats_count01;
+#define VXGE_HW_VPATH_GENSTATS_COUNT01_PPIF_VPATH_GENSTATS_COUNT1(val) \
+ vxge_vBIT(val, 0, 32)
+#define VXGE_HW_VPATH_GENSTATS_COUNT01_PPIF_VPATH_GENSTATS_COUNT0(val) \
+ vxge_vBIT(val, 32, 32)
+/*0x02340*/ u64 vpath_genstats_count23;
+#define VXGE_HW_VPATH_GENSTATS_COUNT23_PPIF_VPATH_GENSTATS_COUNT3(val) \
+ vxge_vBIT(val, 0, 32)
+#define VXGE_HW_VPATH_GENSTATS_COUNT23_PPIF_VPATH_GENSTATS_COUNT2(val) \
+ vxge_vBIT(val, 32, 32)
+/*0x02348*/ u64 vpath_genstats_count4;
+#define VXGE_HW_VPATH_GENSTATS_COUNT4_PPIF_VPATH_GENSTATS_COUNT4(val) \
+ vxge_vBIT(val, 32, 32)
+/*0x02350*/ u64 vpath_genstats_count5;
+#define VXGE_HW_VPATH_GENSTATS_COUNT5_PPIF_VPATH_GENSTATS_COUNT5(val) \
+ vxge_vBIT(val, 32, 32)
+ u8 unused02648[0x02648-0x02358];
+} __attribute((packed));
+
+#define VXGE_HW_EEPROM_SIZE (0x01 << 11)
+
+/* Capability lists */
+#define VXGE_HW_PCI_EXP_LNKCAP_LNK_SPEED 0xf /* Supported Link speeds */
+#define VXGE_HW_PCI_EXP_LNKCAP_LNK_WIDTH 0x3f0 /* Supported Link speeds. */
+#define VXGE_HW_PCI_EXP_LNKCAP_LW_RES 0x0 /* Reserved. */
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_traffic.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_traffic.c
new file mode 100644
index 00000000..0b1caf10
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_traffic.c
@@ -0,0 +1,738 @@
+/*
+ * vxge-traffic.c: iPXE driver for Neterion Inc's X3100 Series 10GbE
+ * PCIe I/O Virtualized Server Adapter.
+ *
+ * Copyright(c) 2002-2010 Neterion Inc.
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice.
+ *
+ */
+
+FILE_LICENCE(GPL2_ONLY);
+
+#include <ipxe/netdevice.h>
+#include <errno.h>
+
+#include "vxge_traffic.h"
+#include "vxge_config.h"
+#include "vxge_main.h"
+
+/*
+ * vxge_hw_vpath_intr_enable - Enable vpath interrupts.
+ * @vpath: Virtual Path handle.
+ *
+ * Enable vpath interrupts. The function is to be executed the last in
+ * vpath initialization sequence.
+ *
+ * See also: vxge_hw_vpath_intr_disable()
+ */
+enum vxge_hw_status
+vxge_hw_vpath_intr_enable(struct __vxge_hw_virtualpath *vpath)
+{
+ struct vxge_hw_vpath_reg *vp_reg;
+ enum vxge_hw_status status = VXGE_HW_OK;
+
+ if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
+ status = VXGE_HW_ERR_VPATH_NOT_OPEN;
+ goto exit;
+ }
+
+ vp_reg = vpath->vp_reg;
+
+ writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->kdfcctl_errors_reg);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->general_errors_reg);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->pci_config_errors_reg);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->mrpcim_to_vpath_alarm_reg);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->srpcim_to_vpath_alarm_reg);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->vpath_ppif_int_status);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->srpcim_msg_to_vpath_reg);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->vpath_pcipif_int_status);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->prc_alarm_reg);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->wrdma_alarm_status);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->asic_ntwk_vp_err_reg);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->xgmac_vp_int_status);
+
+ readq(&vp_reg->vpath_general_int_status);
+
+ /* Mask unwanted interrupts */
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->vpath_pcipif_int_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->srpcim_msg_to_vpath_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->srpcim_to_vpath_alarm_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->mrpcim_to_vpath_alarm_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->pci_config_errors_mask);
+
+ /* Unmask the individual interrupts */
+ writeq((u32)vxge_bVALn((VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO1_OVRFLOW|
+ VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO2_OVRFLOW|
+ VXGE_HW_GENERAL_ERRORS_REG_STATSB_DROP_TIMEOUT_REQ|
+ VXGE_HW_GENERAL_ERRORS_REG_STATSB_PIF_CHAIN_ERR), 0, 32),
+ &vp_reg->general_errors_mask);
+
+ __vxge_hw_pio_mem_write32_upper(
+ (u32)vxge_bVALn((VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_OVRWR|
+ VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_OVRWR|
+ VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_POISON|
+ VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_POISON|
+ VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_DMA_ERR|
+ VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_DMA_ERR), 0, 32),
+ &vp_reg->kdfcctl_errors_mask);
+
+ __vxge_hw_pio_mem_write32_upper(0, &vp_reg->vpath_ppif_int_mask);
+
+ __vxge_hw_pio_mem_write32_upper(
+ (u32)vxge_bVALn(VXGE_HW_PRC_ALARM_REG_PRC_RING_BUMP, 0, 32),
+ &vp_reg->prc_alarm_mask);
+
+ __vxge_hw_pio_mem_write32_upper(0, &vp_reg->wrdma_alarm_mask);
+ __vxge_hw_pio_mem_write32_upper(0, &vp_reg->xgmac_vp_int_mask);
+
+ if (vpath->hldev->first_vp_id != vpath->vp_id)
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->asic_ntwk_vp_err_mask);
+ else
+ __vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn((
+ VXGE_HW_ASIC_NTWK_VP_ERR_REG_XMACJ_NTWK_REAFFIRMED_FAULT|
+ VXGE_HW_ASIC_NTWK_VP_ERR_REG_XMACJ_NTWK_REAFFIRMED_OK),
+ 0, 32), &vp_reg->asic_ntwk_vp_err_mask);
+
+ __vxge_hw_pio_mem_write32_upper(0, &vp_reg->vpath_general_int_mask);
+exit:
+ return status;
+
+}
+
+/*
+ * vxge_hw_vpath_intr_disable - Disable vpath interrupts.
+ * @vpath: Virtual Path handle.
+ *
+ * Disable vpath interrupts. The function is to be executed the last in
+ * vpath initialization sequence.
+ *
+ * See also: vxge_hw_vpath_intr_enable()
+ */
+enum vxge_hw_status
+vxge_hw_vpath_intr_disable(struct __vxge_hw_virtualpath *vpath)
+{
+ enum vxge_hw_status status = VXGE_HW_OK;
+ struct vxge_hw_vpath_reg __iomem *vp_reg;
+
+ if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
+ status = VXGE_HW_ERR_VPATH_NOT_OPEN;
+ goto exit;
+ }
+ vp_reg = vpath->vp_reg;
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->vpath_general_int_mask);
+
+ writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->kdfcctl_errors_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->general_errors_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->pci_config_errors_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->mrpcim_to_vpath_alarm_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->srpcim_to_vpath_alarm_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->vpath_ppif_int_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->srpcim_msg_to_vpath_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->vpath_pcipif_int_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->wrdma_alarm_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->prc_alarm_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->xgmac_vp_int_mask);
+
+ __vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->asic_ntwk_vp_err_mask);
+
+exit:
+ return status;
+}
+
+/**
+ * vxge_hw_device_mask_all - Mask all device interrupts.
+ * @hldev: HW device handle.
+ *
+ * Mask all device interrupts.
+ *
+ * See also: vxge_hw_device_unmask_all()
+ */
+void vxge_hw_device_mask_all(struct __vxge_hw_device *hldev)
+{
+ u64 val64;
+
+ val64 = VXGE_HW_TITAN_MASK_ALL_INT_ALARM |
+ VXGE_HW_TITAN_MASK_ALL_INT_TRAFFIC;
+
+ __vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32),
+ &hldev->common_reg->titan_mask_all_int);
+
+ return;
+}
+
+/**
+ * vxge_hw_device_unmask_all - Unmask all device interrupts.
+ * @hldev: HW device handle.
+ *
+ * Unmask all device interrupts.
+ *
+ * See also: vxge_hw_device_mask_all()
+ */
+void vxge_hw_device_unmask_all(struct __vxge_hw_device *hldev)
+{
+ u64 val64 = VXGE_HW_TITAN_MASK_ALL_INT_TRAFFIC;
+
+ __vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32),
+ &hldev->common_reg->titan_mask_all_int);
+
+ return;
+}
+
+/**
+ * vxge_hw_device_intr_enable - Enable interrupts.
+ * @hldev: HW device handle.
+ *
+ * Enable Titan interrupts. The function is to be executed the last in
+ * Titan initialization sequence.
+ *
+ * See also: vxge_hw_device_intr_disable()
+ */
+void vxge_hw_device_intr_enable(struct __vxge_hw_device *hldev)
+{
+ u64 val64;
+ u32 val32;
+
+ vxge_hw_device_mask_all(hldev);
+
+ vxge_hw_vpath_intr_enable(&hldev->virtual_path);
+
+ val64 = hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_TX] |
+ hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_RX];
+
+ if (val64 != 0) {
+ writeq(val64, &hldev->common_reg->tim_int_status0);
+
+ writeq(~val64, &hldev->common_reg->tim_int_mask0);
+ }
+
+ val32 = hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_TX] |
+ hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_RX];
+
+ if (val32 != 0) {
+ __vxge_hw_pio_mem_write32_upper(val32,
+ &hldev->common_reg->tim_int_status1);
+
+ __vxge_hw_pio_mem_write32_upper(~val32,
+ &hldev->common_reg->tim_int_mask1);
+ }
+
+ val64 = readq(&hldev->common_reg->titan_general_int_status);
+
+ /* We have not enabled the top level interrupt yet.
+ * This will be controlled from vxge_irq() entry api.
+ */
+ return;
+}
+
+/**
+ * vxge_hw_device_intr_disable - Disable Titan interrupts.
+ * @hldev: HW device handle.
+ *
+ * Disable Titan interrupts.
+ *
+ * See also: vxge_hw_device_intr_enable()
+ */
+void vxge_hw_device_intr_disable(struct __vxge_hw_device *hldev)
+{
+ vxge_hw_device_mask_all(hldev);
+
+ /* mask all the tim interrupts */
+ writeq(VXGE_HW_INTR_MASK_ALL, &hldev->common_reg->tim_int_mask0);
+ __vxge_hw_pio_mem_write32_upper(VXGE_HW_DEFAULT_32,
+ &hldev->common_reg->tim_int_mask1);
+
+ vxge_hw_vpath_intr_disable(&hldev->virtual_path);
+
+ return;
+}
+
+/**
+ * vxge_hw_ring_rxd_post - Post descriptor on the ring.
+ * @ring: Handle to the ring object used for receive
+ * @rxdh: Descriptor obtained via vxge_hw_ring_rxd_reserve().
+ *
+ * Post descriptor on the ring.
+ * Prior to posting the descriptor should be filled in accordance with
+ * Host/Titan interface specification for a given service (LL, etc.).
+ */
+void vxge_hw_ring_rxd_post(struct __vxge_hw_ring *ring __unused,
+ struct vxge_hw_ring_rxd_1 *rxdp)
+{
+ rxdp->control_0 = VXGE_HW_RING_RXD_LIST_OWN_ADAPTER;
+}
+
+/**
+ * __vxge_hw_non_offload_db_post - Post non offload doorbell
+ *
+ * @fifo: fifohandle
+ * @txdl_ptr: The starting location of the TxDL in host memory
+ * @num_txds: The highest TxD in this TxDL (0 to 255 means 1 to 256)
+ *
+ * This function posts a non-offload doorbell to doorbell FIFO
+ *
+ */
+static void __vxge_hw_non_offload_db_post(struct __vxge_hw_fifo *fifo,
+ u64 txdl_ptr, u32 num_txds)
+{
+ writeq(VXGE_HW_NODBW_TYPE(VXGE_HW_NODBW_TYPE_NODBW) |
+ VXGE_HW_NODBW_LAST_TXD_NUMBER(num_txds),
+ &fifo->nofl_db->control_0);
+
+ wmb();
+
+ writeq(txdl_ptr, &fifo->nofl_db->txdl_ptr);
+
+ wmb();
+}
+
+/**
+ * vxge_hw_fifo_free_txdl_get: fetch next available txd in the fifo
+ *
+ * @fifo: tx channel handle
+ */
+struct vxge_hw_fifo_txd *
+ vxge_hw_fifo_free_txdl_get(struct __vxge_hw_fifo *fifo)
+{
+ struct vxge_hw_fifo_txd *txdp;
+
+ txdp = fifo->txdl + fifo->sw_offset;
+ if (txdp->control_0 & VXGE_HW_FIFO_TXD_LIST_OWN_ADAPTER) {
+ vxge_debug(VXGE_ERR, "%s:%d, error: txd(%d) owned by hw\n",
+ __func__, __LINE__, fifo->sw_offset);
+ return NULL;
+ }
+
+ return txdp;
+}
+/**
+ * vxge_hw_fifo_txdl_buffer_set - Set transmit buffer pointer in the
+ * descriptor.
+ * @fifo: Handle to the fifo object used for non offload send
+ * @txdlh: Descriptor handle.
+ * @iob: data buffer.
+ */
+void vxge_hw_fifo_txdl_buffer_set(struct __vxge_hw_fifo *fifo,
+ struct vxge_hw_fifo_txd *txdp,
+ struct io_buffer *iob)
+{
+ txdp->control_0 = VXGE_HW_FIFO_TXD_GATHER_CODE(
+ VXGE_HW_FIFO_GATHER_CODE_FIRST_LAST);
+ txdp->control_0 |= VXGE_HW_FIFO_TXD_BUFFER_SIZE(iob_len(iob));
+
+ txdp->control_1 = VXGE_HW_FIFO_TXD_INT_NUMBER(fifo->tx_intr_num);
+ txdp->control_1 |= VXGE_HW_FIFO_TXD_INT_TYPE_PER_LIST;
+
+ txdp->host_control = (intptr_t)iob;
+ txdp->buffer_pointer = virt_to_bus(iob->data);
+}
+
+/**
+ * vxge_hw_fifo_txdl_post - Post descriptor on the fifo channel.
+ * @fifo: Handle to the fifo object used for non offload send
+ * @txdp: Tx Descriptor
+ *
+ * Post descriptor on the 'fifo' type channel for transmission.
+ * Prior to posting the descriptor should be filled in accordance with
+ * Host/Titan interface specification for a given service (LL, etc.).
+ *
+ */
+void vxge_hw_fifo_txdl_post(struct __vxge_hw_fifo *fifo,
+ struct vxge_hw_fifo_txd *txdp)
+{
+ txdp->control_0 |= VXGE_HW_FIFO_TXD_LIST_OWN_ADAPTER;
+
+ __vxge_hw_non_offload_db_post(fifo, (u64) virt_to_bus(txdp), 0);
+
+ vxge_hw_fifo_txd_offset_up(&fifo->sw_offset);
+}
+
+/*
+ * __vxge_hw_vpath_alarm_process - Process Alarms.
+ * @vpath: Virtual Path.
+ * @skip_alarms: Do not clear the alarms
+ *
+ * Process vpath alarms.
+ *
+ */
+static enum vxge_hw_status __vxge_hw_vpath_alarm_process(
+ struct __vxge_hw_virtualpath *vpath)
+{
+ u64 val64;
+ u64 alarm_status;
+ enum vxge_hw_status status = VXGE_HW_OK;
+ struct __vxge_hw_device *hldev = NULL;
+ struct vxge_hw_vpath_reg *vp_reg;
+
+ hldev = vpath->hldev;
+ vp_reg = vpath->vp_reg;
+ alarm_status = readq(&vp_reg->vpath_general_int_status);
+
+ if (alarm_status == VXGE_HW_ALL_FOXES) {
+
+ vxge_debug(VXGE_ERR, "%s: %s:%d, slot freeze error\n",
+ hldev->ndev->name, __func__, __LINE__);
+ status = VXGE_HW_ERR_SLOT_FREEZE;
+ goto out;
+ }
+
+ if (alarm_status & ~(
+ VXGE_HW_VPATH_GENERAL_INT_STATUS_PIC_INT |
+ VXGE_HW_VPATH_GENERAL_INT_STATUS_PCI_INT |
+ VXGE_HW_VPATH_GENERAL_INT_STATUS_WRDMA_INT |
+ VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT)) {
+
+ vxge_debug(VXGE_ERR, "%s: %s:%d, Unknown vpath alarm\n",
+ hldev->ndev->name, __func__, __LINE__);
+ status = VXGE_HW_FAIL;
+ goto out;
+ }
+
+ if (alarm_status & VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT) {
+
+ val64 = readq(&vp_reg->xgmac_vp_int_status);
+
+ if (val64 &
+ VXGE_HW_XGMAC_VP_INT_STATUS_ASIC_NTWK_VP_ERR_ASIC_NTWK_VP_INT) {
+
+ val64 = readq(&vp_reg->asic_ntwk_vp_err_reg);
+
+ if (((val64 &
+ VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT) &&
+ (!(val64 &
+ VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK))) ||
+ ((val64 &
+ VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT_OCCURR)
+ && (!(val64 &
+ VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK_OCCURR)
+ ))) {
+ writeq(VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT,
+ &vp_reg->asic_ntwk_vp_err_mask);
+
+ netdev_link_down(hldev->ndev);
+ vxge_debug(VXGE_INTR, "%s: %s:%d link down\n",
+ hldev->ndev->name, __func__, __LINE__);
+ }
+
+ if (((val64 &
+ VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK) &&
+ (!(val64 &
+ VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT))) ||
+ ((val64 &
+ VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK_OCCURR)
+ && (!(val64 &
+ VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT_OCCURR)
+ ))) {
+ writeq(VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK,
+ &vp_reg->asic_ntwk_vp_err_mask);
+
+ netdev_link_up(hldev->ndev);
+ vxge_debug(VXGE_INTR, "%s: %s:%d link up\n",
+ hldev->ndev->name, __func__, __LINE__);
+ }
+
+ writeq(VXGE_HW_INTR_MASK_ALL,
+ &vp_reg->asic_ntwk_vp_err_reg);
+ }
+ } else {
+ vxge_debug(VXGE_INFO, "%s: %s:%d unhandled alarm %llx\n",
+ hldev->ndev->name, __func__, __LINE__,
+ alarm_status);
+ }
+out:
+ return status;
+}
+
+/**
+ * vxge_hw_device_clear_tx_rx - Acknowledge (that is, clear) the
+ * condition that has caused the Tx and RX interrupt.
+ * @hldev: HW device.
+ *
+ * Acknowledge (that is, clear) the condition that has caused
+ * the Tx and Rx interrupt.
+ * See also: vxge_hw_device_begin_irq(),
+ * vxge_hw_device_mask_tx_rx(), vxge_hw_device_unmask_tx_rx().
+ */
+void vxge_hw_device_clear_tx_rx(struct __vxge_hw_device *hldev)
+{
+
+ if ((hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_TX] != 0) ||
+ (hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_RX] != 0)) {
+ writeq((hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_TX] |
+ hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_RX]),
+ &hldev->common_reg->tim_int_status0);
+ }
+
+ if ((hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_TX] != 0) ||
+ (hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_RX] != 0)) {
+ __vxge_hw_pio_mem_write32_upper(
+ (hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_TX] |
+ hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_RX]),
+ &hldev->common_reg->tim_int_status1);
+ }
+
+ return;
+}
+
+
+/**
+ * vxge_hw_device_begin_irq - Begin IRQ processing.
+ * @hldev: HW device handle.
+ *
+ * The function performs two actions, It first checks whether (shared IRQ) the
+ * interrupt was raised by the device. Next, it masks the device interrupts.
+ *
+ * Note:
+ * vxge_hw_device_begin_irq() does not flush MMIO writes through the
+ * bridge. Therefore, two back-to-back interrupts are potentially possible.
+ *
+ * Returns: 0, if the interrupt is not "ours" (note that in this case the
+ * device remain enabled).
+ * Otherwise, vxge_hw_device_begin_irq() returns 64bit general adapter
+ * status.
+ */
+enum vxge_hw_status
+vxge_hw_device_begin_irq(struct __vxge_hw_device *hldev)
+{
+ u64 val64;
+ u64 adapter_status;
+ u64 vpath_mask;
+ enum vxge_hw_status ret = VXGE_HW_OK;
+
+ val64 = readq(&hldev->common_reg->titan_general_int_status);
+
+ if (!val64) {
+ ret = VXGE_HW_ERR_WRONG_IRQ;
+ goto exit;
+ }
+
+ if (val64 == VXGE_HW_ALL_FOXES) {
+
+ adapter_status = readq(&hldev->common_reg->adapter_status);
+
+ if (adapter_status == VXGE_HW_ALL_FOXES) {
+
+ vxge_debug(VXGE_ERR, "%s: %s:%d critical error "
+ "occurred\n", hldev->ndev->name,
+ __func__, __LINE__);
+ ret = VXGE_HW_ERR_SLOT_FREEZE;
+ goto exit;
+ }
+ }
+
+ vpath_mask = hldev->vpaths_deployed >>
+ (64 - VXGE_HW_MAX_VIRTUAL_PATHS);
+ if (val64 & VXGE_HW_TITAN_GENERAL_INT_STATUS_VPATH_TRAFFIC_INT(
+ vpath_mask))
+ vxge_hw_device_clear_tx_rx(hldev);
+
+ if (val64 & VXGE_HW_TITAN_GENERAL_INT_STATUS_VPATH_ALARM_INT)
+ ret = __vxge_hw_vpath_alarm_process(&hldev->virtual_path);
+
+exit:
+ return ret;
+}
+
+/**
+ * vxge_hw_vpath_doorbell_rx - Indicates to hw the qwords of receive
+ * descriptors posted.
+ * @ring: Handle to the ring object used for receive
+ *
+ * The function writes the number of qwords of rxds posted during replishment.
+ * Since the function is called frequently, a flush is not required to post the
+ * write transaction. At the very least, the previous write will be flushed
+ * once the subsequent write is made.
+ *
+ * Returns: None.
+ */
+void vxge_hw_vpath_doorbell_rx(struct __vxge_hw_ring *ring)
+{
+ u32 rxds_qw_per_block = VXGE_HW_MAX_RXDS_PER_BLOCK_1 *
+ VXGE_HW_RING_RXD_QWORDS_MODE_1;
+
+ ring->doorbell_cnt += VXGE_HW_RING_RXD_QWORDS_MODE_1;
+
+ ring->total_db_cnt += VXGE_HW_RING_RXD_QWORDS_MODE_1;
+
+ if (ring->total_db_cnt >= rxds_qw_per_block) {
+ /* For each block add 4 more qwords */
+ ring->doorbell_cnt += VXGE_HW_RING_RXD_QWORDS_MODE_1;
+
+ /* Reset total count */
+ ring->total_db_cnt -= rxds_qw_per_block;
+ }
+
+ if (ring->doorbell_cnt >= ring->rxd_qword_limit) {
+ wmb();
+ writeq(VXGE_HW_PRC_RXD_DOORBELL_NEW_QW_CNT(
+ ring->doorbell_cnt),
+ &ring->vp_reg->prc_rxd_doorbell);
+ ring->doorbell_cnt = 0;
+ }
+}
+
+/**
+ * vxge_hw_vpath_poll_rx - Poll Rx Virtual Path for completed
+ * descriptors and process the same.
+ * @ring: Handle to the ring object used for receive
+ *
+ * The function polls the Rx for the completed descriptors.
+ */
+#define ETH_FCS_LEN 4
+enum vxge_hw_status vxge_hw_vpath_poll_rx(struct __vxge_hw_ring *ring)
+{
+ struct __vxge_hw_device *hldev;
+ enum vxge_hw_status status = VXGE_HW_OK;
+ struct vxge_hw_ring_rxd_1 *rxd;
+ unsigned int len;
+ enum vxge_hw_ring_tcode tcode;
+ struct io_buffer *rx_iob, *iobuf = NULL;
+ u16 poll_count = 0;
+
+ hldev = ring->vpathh->hldev;
+
+ do {
+ rxd = &ring->rxdl->rxd[ring->rxd_offset];
+ tcode = VXGE_HW_RING_RXD_T_CODE_GET(rxd->control_0);
+
+ /* if tcode is VXGE_HW_RING_T_CODE_FRM_DROP, it is
+ * possible the ownership bit still set to adapter
+ */
+ if ((rxd->control_0 & VXGE_HW_RING_RXD_LIST_OWN_ADAPTER)
+ && (tcode == VXGE_HW_RING_T_CODE_OK)) {
+
+ status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
+ goto err0;
+ }
+
+ vxge_debug(VXGE_INFO, "%s: rx frame received at offset %d\n",
+ hldev->ndev->name, ring->rxd_offset);
+
+ if (tcode != VXGE_HW_RING_T_CODE_OK) {
+ netdev_rx_err(hldev->ndev, NULL, -EINVAL);
+ vxge_debug(VXGE_ERR, "%s:%d, rx error tcode %d\n",
+ __func__, __LINE__, tcode);
+ status = VXGE_HW_FAIL;
+ goto err1;
+ }
+
+ iobuf = (struct io_buffer *)(intptr_t)rxd->host_control;
+
+ len = VXGE_HW_RING_RXD_1_BUFFER0_SIZE_GET(rxd->control_1);
+ len -= ETH_FCS_LEN;
+
+ rx_iob = alloc_iob(len);
+ if (!rx_iob) {
+ netdev_rx_err(hldev->ndev, NULL, -ENOMEM);
+ vxge_debug(VXGE_ERR, "%s:%d, alloc_iob error\n",
+ __func__, __LINE__);
+ status = VXGE_HW_ERR_OUT_OF_MEMORY;
+ goto err1;
+ }
+
+ memcpy(iob_put(rx_iob, len), iobuf->data, len);
+ /* Add this packet to the receive queue. */
+ netdev_rx(hldev->ndev, rx_iob);
+
+err1:
+ /* repost the rxd */
+ rxd->control_0 = rxd->control_1 = 0;
+ vxge_hw_ring_rxd_1b_set(rxd, iobuf,
+ VXGE_LL_MAX_FRAME_SIZE(hldev->vdev));
+ vxge_hw_ring_rxd_post(ring, rxd);
+
+ /* repost the qword count for doorbell */
+ vxge_hw_vpath_doorbell_rx(ring);
+
+ /* increment the descriptor offset */
+ vxge_hw_ring_rxd_offset_up(&ring->rxd_offset);
+
+ } while (++poll_count < ring->rx_poll_weight);
+err0:
+ return status;
+}
+
+/**
+ * vxge_hw_vpath_poll_tx - Poll Tx for completed descriptors and process
+ * the same.
+ * @fifo: Handle to the fifo object used for non offload send
+ *
+ * The function polls the Tx for the completed descriptors and calls
+ * the driver via supplied completion callback.
+ */
+enum vxge_hw_status vxge_hw_vpath_poll_tx(struct __vxge_hw_fifo *fifo)
+{
+ enum vxge_hw_status status = VXGE_HW_OK;
+ struct vxge_hw_fifo_txd *txdp;
+
+ txdp = fifo->txdl + fifo->hw_offset;
+ if (!(txdp->control_0 & VXGE_HW_FIFO_TXD_LIST_OWN_ADAPTER)
+ && (txdp->host_control)) {
+
+ vxge_xmit_compl(fifo, txdp,
+ VXGE_HW_FIFO_TXD_T_CODE_GET(txdp->control_0));
+
+ vxge_hw_fifo_txd_offset_up(&fifo->hw_offset);
+ }
+
+ return status;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_traffic.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_traffic.h
new file mode 100644
index 00000000..ed72be1b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_traffic.h
@@ -0,0 +1,309 @@
+/*
+ * vxge-traffic.h: iPXE driver for Neterion Inc's X3100 Series 10GbE
+ * PCIe I/O Virtualized Server Adapter.
+ *
+ * Copyright(c) 2002-2010 Neterion Inc.
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice.
+ *
+ */
+
+FILE_LICENCE(GPL2_ONLY);
+
+#ifndef VXGE_TRAFFIC_H
+#define VXGE_TRAFFIC_H
+
+#include <stdint.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+
+#include "vxge_reg.h"
+#include "vxge_version.h"
+
+#define VXGE_HW_DTR_MAX_T_CODE 16
+#define VXGE_HW_ALL_FOXES 0xFFFFFFFFFFFFFFFFULL
+#define VXGE_HW_INTR_MASK_ALL 0xFFFFFFFFFFFFFFFFULL
+#define VXGE_HW_MAX_VIRTUAL_PATHS 17
+
+#define VXGE_HW_MAX_VIRTUAL_FUNCTIONS 8
+
+#define VXGE_HW_MAC_MAX_MAC_PORT_ID 3
+
+#define VXGE_HW_DEFAULT_32 0xffffffff
+/* frames sizes */
+#define VXGE_HW_HEADER_802_2_SIZE 3
+#define VXGE_HW_HEADER_SNAP_SIZE 5
+#define VXGE_HW_HEADER_VLAN_SIZE 4
+#define VXGE_HW_MAC_HEADER_MAX_SIZE \
+ (ETH_HLEN + \
+ VXGE_HW_HEADER_802_2_SIZE + \
+ VXGE_HW_HEADER_VLAN_SIZE + \
+ VXGE_HW_HEADER_SNAP_SIZE)
+
+/* 32bit alignments */
+
+/* A receive data corruption can occur resulting in either a single-bit or
+double-bit ECC error being flagged in the ASIC if the starting offset of a
+buffer in single buffer mode is 0x2 to 0xa. The single bit ECC error will not
+lock up the card but can hide the data corruption while the double-bit ECC
+error will lock up the card. Limiting the starting offset of the buffers to
+0x0, 0x1 or to a value greater than 0xF will workaround this issue.
+VXGE_HW_HEADER_ETHERNET_II_802_3_ALIGN of 2 causes the starting offset of
+buffer to be 0x2, 0x12 and so on, to have the start of the ip header dword
+aligned. The start of buffer of 0x2 will cause this problem to occur. To
+avoid this problem in all cases, add 0x10 to 0x2, to ensure that the start of
+buffer is outside of the problem causing offsets.
+*/
+#define VXGE_HW_HEADER_ETHERNET_II_802_3_ALIGN 0x12
+#define VXGE_HW_HEADER_802_2_SNAP_ALIGN 2
+#define VXGE_HW_HEADER_802_2_ALIGN 3
+#define VXGE_HW_HEADER_SNAP_ALIGN 1
+
+#define VXGE_HW_L3_CKSUM_OK 0xFFFF
+#define VXGE_HW_L4_CKSUM_OK 0xFFFF
+
+/* Forward declarations */
+struct __vxge_hw_device;
+struct __vxge_hw_virtualpath;
+struct __vxge_hw_fifo;
+struct __vxge_hw_ring;
+struct vxge_hw_ring_rxd_1;
+struct vxge_hw_fifo_txd;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/*VXGE_HW_STATUS_H*/
+#define VXGE_HW_EVENT_BASE 0
+#define VXGE_LL_EVENT_BASE 100
+
+/**
+ * enum vxge_hw_event- Enumerates slow-path HW events.
+ * @VXGE_HW_EVENT_UNKNOWN: Unknown (and invalid) event.
+ * @VXGE_HW_EVENT_SERR: Serious vpath hardware error event.
+ * @VXGE_HW_EVENT_ECCERR: vpath ECC error event.
+ * @VXGE_HW_EVENT_VPATH_ERR: Error local to the respective vpath
+ * @VXGE_HW_EVENT_FIFO_ERR: FIFO Doorbell fifo error.
+ * @VXGE_HW_EVENT_SRPCIM_SERR: srpcim hardware error event.
+ * @VXGE_HW_EVENT_MRPCIM_SERR: mrpcim hardware error event.
+ * @VXGE_HW_EVENT_MRPCIM_ECCERR: mrpcim ecc error event.
+ * @VXGE_HW_EVENT_RESET_START: Privileged entity is starting device reset
+ * @VXGE_HW_EVENT_RESET_COMPLETE: Device reset has been completed
+ * @VXGE_HW_EVENT_SLOT_FREEZE: Slot-freeze event. Driver tries to distinguish
+ * slot-freeze from the rest critical events (e.g. ECC) when it is
+ * impossible to PIO read "through" the bus, i.e. when getting all-foxes.
+ *
+ * enum vxge_hw_event enumerates slow-path HW eventis.
+ *
+ * See also: struct vxge_hw_uld_cbs{}, vxge_uld_link_up_f{},
+ * vxge_uld_link_down_f{}.
+ */
+enum vxge_hw_event {
+ VXGE_HW_EVENT_UNKNOWN = 0,
+ /* HW events */
+ VXGE_HW_EVENT_RESET_START = VXGE_HW_EVENT_BASE + 1,
+ VXGE_HW_EVENT_RESET_COMPLETE = VXGE_HW_EVENT_BASE + 2,
+ VXGE_HW_EVENT_LINK_DOWN = VXGE_HW_EVENT_BASE + 3,
+ VXGE_HW_EVENT_LINK_UP = VXGE_HW_EVENT_BASE + 4,
+ VXGE_HW_EVENT_ALARM_CLEARED = VXGE_HW_EVENT_BASE + 5,
+ VXGE_HW_EVENT_ECCERR = VXGE_HW_EVENT_BASE + 6,
+ VXGE_HW_EVENT_MRPCIM_ECCERR = VXGE_HW_EVENT_BASE + 7,
+ VXGE_HW_EVENT_FIFO_ERR = VXGE_HW_EVENT_BASE + 8,
+ VXGE_HW_EVENT_VPATH_ERR = VXGE_HW_EVENT_BASE + 9,
+ VXGE_HW_EVENT_CRITICAL_ERR = VXGE_HW_EVENT_BASE + 10,
+ VXGE_HW_EVENT_SERR = VXGE_HW_EVENT_BASE + 11,
+ VXGE_HW_EVENT_SRPCIM_SERR = VXGE_HW_EVENT_BASE + 12,
+ VXGE_HW_EVENT_MRPCIM_SERR = VXGE_HW_EVENT_BASE + 13,
+ VXGE_HW_EVENT_SLOT_FREEZE = VXGE_HW_EVENT_BASE + 14,
+};
+
+#define VXGE_HW_MAX_INTR_PER_VP 4
+#define VXGE_HW_VPATH_INTR_TX 0
+#define VXGE_HW_VPATH_INTR_RX 1
+#define VXGE_HW_VPATH_INTR_EINTA 2
+#define VXGE_HW_VPATH_INTR_BMAP 3
+
+#define VXGE_HW_BLOCK_SIZE 4096
+
+#define VXGE_HW_TIM_UTIL_SEL_LEGACY_TX_NET_UTIL 17
+#define VXGE_HW_TIM_UTIL_SEL_LEGACY_RX_NET_UTIL 18
+#define VXGE_HW_TIM_UTIL_SEL_LEGACY_TX_RX_AVE_NET_UTIL 19
+#define VXGE_HW_TIM_UTIL_SEL_PER_VPATH 63
+
+/**
+ * enum vxge_hw_ring_tcode - Transfer codes returned by adapter
+ * @VXGE_HW_RING_T_CODE_OK: Transfer ok.
+ * @VXGE_HW_RING_T_CODE_L3_CKSUM_MISMATCH: Layer 3 checksum presentation
+ * configuration mismatch.
+ * @VXGE_HW_RING_T_CODE_L4_CKSUM_MISMATCH: Layer 4 checksum presentation
+ * configuration mismatch.
+ * @VXGE_HW_RING_T_CODE_L3_L4_CKSUM_MISMATCH: Layer 3 and Layer 4 checksum
+ * presentation configuration mismatch.
+ * @VXGE_HW_RING_T_CODE_L3_PKT_ERR: Layer 3 error unparseable packet,
+ * such as unknown IPv6 header.
+ * @VXGE_HW_RING_T_CODE_L2_FRM_ERR: Layer 2 error frame integrity
+ * error, such as FCS or ECC).
+ * @VXGE_HW_RING_T_CODE_BUF_SIZE_ERR: Buffer size error the RxD buffer(
+ * s) were not appropriately sized and data loss occurred.
+ * @VXGE_HW_RING_T_CODE_INT_ECC_ERR: Internal ECC error RxD corrupted.
+ * @VXGE_HW_RING_T_CODE_BENIGN_OVFLOW: Benign overflow the contents of
+ * Segment1 exceeded the capacity of Buffer1 and the remainder
+ * was placed in Buffer2. Segment2 now starts in Buffer3.
+ * No data loss or errors occurred.
+ * @VXGE_HW_RING_T_CODE_ZERO_LEN_BUFF: Buffer size 0 one of the RxDs
+ * assigned buffers has a size of 0 bytes.
+ * @VXGE_HW_RING_T_CODE_FRM_DROP: Frame dropped either due to
+ * VPath Reset or because of a VPIN mismatch.
+ * @VXGE_HW_RING_T_CODE_UNUSED: Unused
+ * @VXGE_HW_RING_T_CODE_MULTI_ERR: Multiple errors more than one
+ * transfer code condition occurred.
+ *
+ * Transfer codes returned by adapter.
+ */
+enum vxge_hw_ring_tcode {
+ VXGE_HW_RING_T_CODE_OK = 0x0,
+ VXGE_HW_RING_T_CODE_L3_CKSUM_MISMATCH = 0x1,
+ VXGE_HW_RING_T_CODE_L4_CKSUM_MISMATCH = 0x2,
+ VXGE_HW_RING_T_CODE_L3_L4_CKSUM_MISMATCH = 0x3,
+ VXGE_HW_RING_T_CODE_L3_PKT_ERR = 0x5,
+ VXGE_HW_RING_T_CODE_L2_FRM_ERR = 0x6,
+ VXGE_HW_RING_T_CODE_BUF_SIZE_ERR = 0x7,
+ VXGE_HW_RING_T_CODE_INT_ECC_ERR = 0x8,
+ VXGE_HW_RING_T_CODE_BENIGN_OVFLOW = 0x9,
+ VXGE_HW_RING_T_CODE_ZERO_LEN_BUFF = 0xA,
+ VXGE_HW_RING_T_CODE_FRM_DROP = 0xC,
+ VXGE_HW_RING_T_CODE_UNUSED = 0xE,
+ VXGE_HW_RING_T_CODE_MULTI_ERR = 0xF
+};
+
+
+/**
+ * enum enum vxge_hw_fifo_gather_code - Gather codes used in fifo TxD
+ * @VXGE_HW_FIFO_GATHER_CODE_FIRST: First TxDL
+ * @VXGE_HW_FIFO_GATHER_CODE_MIDDLE: Middle TxDL
+ * @VXGE_HW_FIFO_GATHER_CODE_LAST: Last TxDL
+ * @VXGE_HW_FIFO_GATHER_CODE_FIRST_LAST: First and Last TxDL.
+ *
+ * These gather codes are used to indicate the position of a TxD in a TxD list
+ */
+enum vxge_hw_fifo_gather_code {
+ VXGE_HW_FIFO_GATHER_CODE_FIRST = 0x2,
+ VXGE_HW_FIFO_GATHER_CODE_MIDDLE = 0x0,
+ VXGE_HW_FIFO_GATHER_CODE_LAST = 0x1,
+ VXGE_HW_FIFO_GATHER_CODE_FIRST_LAST = 0x3
+};
+
+/**
+ * enum enum vxge_hw_fifo_tcode - tcodes used in fifo
+ * @VXGE_HW_FIFO_T_CODE_OK: Transfer OK
+ * @VXGE_HW_FIFO_T_CODE_PCI_READ_CORRUPT: PCI read transaction (either TxD or
+ * frame data) returned with corrupt data.
+ * @VXGE_HW_FIFO_T_CODE_PCI_READ_FAIL:PCI read transaction was returned
+ * with no data.
+ * @VXGE_HW_FIFO_T_CODE_INVALID_MSS: The host attempted to send either a
+ * frame or LSO MSS that was too long (>9800B).
+ * @VXGE_HW_FIFO_T_CODE_LSO_ERROR: Error detected during TCP/UDP Large Send
+ * Offload operation, due to improper header template,
+ * unsupported protocol, etc.
+ * @VXGE_HW_FIFO_T_CODE_UNUSED: Unused
+ * @VXGE_HW_FIFO_T_CODE_MULTI_ERROR: Set to 1 by the adapter if multiple
+ * data buffer transfer errors are encountered (see below).
+ * Otherwise it is set to 0.
+ *
+ * These tcodes are returned in various API for TxD status
+ */
+enum vxge_hw_fifo_tcode {
+ VXGE_HW_FIFO_T_CODE_OK = 0x0,
+ VXGE_HW_FIFO_T_CODE_PCI_READ_CORRUPT = 0x1,
+ VXGE_HW_FIFO_T_CODE_PCI_READ_FAIL = 0x2,
+ VXGE_HW_FIFO_T_CODE_INVALID_MSS = 0x3,
+ VXGE_HW_FIFO_T_CODE_LSO_ERROR = 0x4,
+ VXGE_HW_FIFO_T_CODE_UNUSED = 0x7,
+ VXGE_HW_FIFO_T_CODE_MULTI_ERROR = 0x8
+};
+
+enum vxge_hw_status
+vxge_hw_ring_replenish(struct __vxge_hw_ring *ring);
+
+void vxge_hw_ring_rxd_post(struct __vxge_hw_ring *ring_handle,
+ struct vxge_hw_ring_rxd_1 *rxdp);
+
+void vxge_hw_fifo_txdl_buffer_set(struct __vxge_hw_fifo *fifo,
+ struct vxge_hw_fifo_txd *txdp,
+ struct io_buffer *iob);
+
+void vxge_hw_fifo_txdl_post(struct __vxge_hw_fifo *fifo,
+ struct vxge_hw_fifo_txd *txdp);
+
+enum vxge_hw_status __vxge_hw_ring_create(
+ struct __vxge_hw_virtualpath *vpath,
+ struct __vxge_hw_ring *ring);
+
+enum vxge_hw_status __vxge_hw_ring_delete(
+ struct __vxge_hw_ring *ringh);
+
+enum vxge_hw_status __vxge_hw_fifo_create(
+ struct __vxge_hw_virtualpath *vpath,
+ struct __vxge_hw_fifo *fifo);
+
+enum vxge_hw_status
+__vxge_hw_fifo_delete(struct __vxge_hw_fifo *fifo);
+
+enum vxge_hw_status __vxge_hw_vpath_reset(
+ struct __vxge_hw_device *devh, u32 vp_id);
+
+enum vxge_hw_status
+__vxge_hw_vpath_enable(struct __vxge_hw_device *devh, u32 vp_id);
+
+void
+__vxge_hw_vpath_prc_configure(struct __vxge_hw_device *hldev);
+
+enum vxge_hw_status
+__vxge_hw_vpath_kdfc_configure(struct __vxge_hw_device *devh, u32 vp_id);
+
+enum vxge_hw_status
+__vxge_hw_vpath_mac_configure(struct __vxge_hw_device *devh);
+
+enum vxge_hw_status
+__vxge_hw_vpath_tim_configure(struct __vxge_hw_device *devh, u32 vp_id);
+
+enum vxge_hw_status
+__vxge_hw_vpath_initialize(struct __vxge_hw_device *devh, u32 vp_id);
+
+enum vxge_hw_status __vxge_hw_vp_initialize(
+ struct __vxge_hw_device *hldev, u32 vp_id,
+ struct __vxge_hw_virtualpath *vpath);
+
+void __vxge_hw_vp_terminate(struct __vxge_hw_device *hldev,
+ struct __vxge_hw_virtualpath *vpath);
+
+enum vxge_hw_status
+vxge_hw_device_begin_irq(struct __vxge_hw_device *hldev);
+
+void vxge_hw_device_intr_enable(struct __vxge_hw_device *hldev);
+
+void vxge_hw_device_intr_disable(struct __vxge_hw_device *hldev);
+
+void vxge_hw_device_mask_all(struct __vxge_hw_device *hldev);
+
+void vxge_hw_device_unmask_all(struct __vxge_hw_device *hldev);
+
+void vxge_hw_vpath_doorbell_rx(struct __vxge_hw_ring *ringh);
+
+enum vxge_hw_status vxge_hw_vpath_poll_rx(struct __vxge_hw_ring *ringh);
+
+enum vxge_hw_status vxge_hw_vpath_poll_tx(struct __vxge_hw_fifo *fifo);
+
+struct vxge_hw_fifo_txd *
+vxge_hw_fifo_free_txdl_get(struct __vxge_hw_fifo *fifo);
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_version.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_version.h
new file mode 100644
index 00000000..1475b77e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/vxge/vxge_version.h
@@ -0,0 +1,40 @@
+/*
+ * vxge-version.h: iPXE driver for Neterion Inc's X3100 Series 10GbE
+ * PCIe I/O Virtualized Server Adapter.
+ *
+ * Copyright(c) 2002-2010 Neterion Inc.
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice.
+ *
+ */
+
+FILE_LICENCE(GPL2_ONLY);
+
+#ifndef VXGE_VERSION_H
+
+#define VXGE_VERSION_H
+
+/* ipxe vxge driver version fields.
+ * Note: Each field must be a nibble size
+ */
+#define VXGE_VERSION_MAJOR 3
+#define VXGE_VERSION_MINOR 5
+#define VXGE_VERSION_FIX 0
+#define VXGE_VERSION_BUILD 1
+
+#define VXGE_FW_VER(major, minor, build) \
+ (((major) << 16) + ((minor) << 8) + (build))
+
+/* Certified FW version. */
+#define VXGE_CERT_FW_VER_MAJOR 1
+#define VXGE_CERT_FW_VER_MINOR 6
+#define VXGE_CERT_FW_VER_BUILD 0
+
+#define VXGE_CERT_FW_VER VXGE_FW_VER(VXGE_CERT_FW_VER_MAJOR, \
+ VXGE_CERT_FW_VER_MINOR, VXGE_CERT_FW_VER_BUILD)
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/w89c840.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/w89c840.c
new file mode 100644
index 00000000..82c2811c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/w89c840.c
@@ -0,0 +1,973 @@
+/*
+ * Etherboot - BOOTP/TFTP Bootstrap Program
+ *
+ * w89c840.c -- This file implements the winbond-840 driver for etherboot.
+ *
+ */
+
+/*
+ * Adapted by Igor V. Kovalenko
+ * -- <garrison@mail.ru>
+ * OR
+ * -- <iko@crec.mipt.ru>
+ * Initial adaptaion stage, including testing, completed 23 August 2000.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * date version by what
+ * Written: Aug 20 2000 V0.10 iko Initial revision.
+ * changes: Aug 22 2000 V0.90 iko Works!
+ * Aug 23 2000 V0.91 iko Cleanup, posted to etherboot
+ * maintainer.
+ * Aug 26 2000 V0.92 iko Fixed Rx ring handling.
+ * First Linux Kernel (TM)
+ * successfully loaded using
+ * this driver.
+ * Jan 07 2001 V0.93 iko Transmitter timeouts are handled
+ * using timer2 routines. Proposed
+ * by Ken Yap to eliminate CPU speed
+ * dependency.
+ * Dec 12 2003 V0.94 timlegge Fixed issues in 5.2, removed
+ * interrupt usage, enabled
+ * multicast support
+ *
+ * This is the etherboot driver for cards based on Winbond W89c840F chip.
+ *
+ * It was written from skeleton source, with Donald Becker's winbond-840.c
+ * kernel driver as a guideline. Mostly the w89c840 related definitions
+ * and the lower level routines have been cut-and-pasted into this source.
+ *
+ * Frankly speaking, about 90% of the code was obtained using cut'n'paste
+ * sequence :) while the remainder appeared while brainstorming
+ * Linux Kernel 2.4.0-testX source code. Thanks, Donald and Linus!
+ *
+ * There was a demand for using this card in a rather large
+ * remote boot environment at MSKP OVTI Lab of
+ * Moscow Institute for Physics and Technology (MIPT) -- http://www.mipt.ru/
+ * so you may count that for motivation.
+ *
+ */
+
+/*
+ * If you want to see debugging output then define W89C840_DEBUG
+ */
+
+/*
+#define W89C840_DEBUG
+*/
+
+/*
+ * Keep using IO_OPS for Etherboot driver!
+ */
+#define USE_IO_OPS
+
+#include "etherboot.h"
+#include "nic.h"
+#include <ipxe/pci.h>
+#include <ipxe/ethernet.h>
+
+static const char *w89c840_version = "driver Version 0.94 - December 12, 2003";
+
+/* Linux support functions */
+#define virt_to_le32desc(addr) virt_to_bus(addr)
+#define le32desc_to_virt(addr) bus_to_virt(addr)
+
+/*
+#define cpu_to_le32(val) (val)
+#define le32_to_cpu(val) (val)
+*/
+
+/* Operational parameters that are set at compile time. */
+
+/* Keep the ring sizes a power of two for compile efficiency.
+ The compiler will convert <unsigned>'%'<2^N> into a bit mask.
+ Making the Tx ring too large decreases the effectiveness of channel
+ bonding and packet priority.
+ There are no ill effects from too-large receive rings. */
+#define TX_RING_SIZE 2
+#define RX_RING_SIZE 2
+
+/* The presumed FIFO size for working around the Tx-FIFO-overflow bug.
+ To avoid overflowing we don't queue again until we have room for a
+ full-size packet.
+ */
+#define TX_FIFO_SIZE (2048)
+#define TX_BUG_FIFO_LIMIT (TX_FIFO_SIZE-1514-16)
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT (10*1000)
+
+#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
+
+/*
+ * Used to be this much CPU loops on Celeron@400 (?),
+ * now using real timer and TX_TIMEOUT!
+ * #define TX_LOOP_COUNT 10000000
+ */
+
+#if !defined(__OPTIMIZE__)
+#warning You must compile this file with the correct options!
+#warning See the last lines of the source file.
+#error You must compile this driver with "-O".
+#endif
+
+enum chip_capability_flags {CanHaveMII=1, HasBrokenTx=2};
+
+#ifdef USE_IO_OPS
+#define W840_FLAGS (PCI_USES_IO | PCI_ADDR0 | PCI_USES_MASTER)
+#else
+#define W840_FLAGS (PCI_USES_MEM | PCI_ADDR1 | PCI_USES_MASTER)
+#endif
+
+static u32 driver_flags = CanHaveMII | HasBrokenTx;
+
+/* This driver was written to use PCI memory space, however some x86 systems
+ work only with I/O space accesses. Pass -DUSE_IO_OPS to use PCI I/O space
+ accesses instead of memory space. */
+
+#ifdef USE_IO_OPS
+#undef readb
+#undef readw
+#undef readl
+#undef writeb
+#undef writew
+#undef writel
+#define readb inb
+#define readw inw
+#define readl inl
+#define writeb outb
+#define writew outw
+#define writel outl
+#endif
+
+/* Offsets to the Command and Status Registers, "CSRs".
+ While similar to the Tulip, these registers are longword aligned.
+ Note: It's not useful to define symbolic names for every register bit in
+ the device. The name can only partially document the semantics and make
+ the driver longer and more difficult to read.
+*/
+enum w840_offsets {
+ PCIBusCfg=0x00, TxStartDemand=0x04, RxStartDemand=0x08,
+ RxRingPtr=0x0C, TxRingPtr=0x10,
+ IntrStatus=0x14, NetworkConfig=0x18, IntrEnable=0x1C,
+ RxMissed=0x20, EECtrl=0x24, MIICtrl=0x24, BootRom=0x28, GPTimer=0x2C,
+ CurRxDescAddr=0x30, CurRxBufAddr=0x34, /* Debug use */
+ MulticastFilter0=0x38, MulticastFilter1=0x3C, StationAddr=0x40,
+ CurTxDescAddr=0x4C, CurTxBufAddr=0x50,
+};
+
+/* Bits in the interrupt status/enable registers. */
+/* The bits in the Intr Status/Enable registers, mostly interrupt sources. */
+enum intr_status_bits {
+ NormalIntr=0x10000, AbnormalIntr=0x8000,
+ IntrPCIErr=0x2000, TimerInt=0x800,
+ IntrRxDied=0x100, RxNoBuf=0x80, IntrRxDone=0x40,
+ TxFIFOUnderflow=0x20, RxErrIntr=0x10,
+ TxIdle=0x04, IntrTxStopped=0x02, IntrTxDone=0x01,
+};
+
+/* Bits in the NetworkConfig register. */
+enum rx_mode_bits {
+ AcceptErr=0x80, AcceptRunt=0x40,
+ AcceptBroadcast=0x20, AcceptMulticast=0x10,
+ AcceptAllPhys=0x08, AcceptMyPhys=0x02,
+};
+
+enum mii_reg_bits {
+ MDIO_ShiftClk=0x10000, MDIO_DataIn=0x80000, MDIO_DataOut=0x20000,
+ MDIO_EnbOutput=0x40000, MDIO_EnbIn = 0x00000,
+};
+
+/* The Tulip Rx and Tx buffer descriptors. */
+struct w840_rx_desc {
+ s32 status;
+ s32 length;
+ u32 buffer1;
+ u32 next_desc;
+};
+
+struct w840_tx_desc {
+ s32 status;
+ s32 length;
+ u32 buffer1, buffer2; /* We use only buffer 1. */
+};
+
+/* Bits in network_desc.status */
+enum desc_status_bits {
+ DescOwn=0x80000000, DescEndRing=0x02000000, DescUseLink=0x01000000,
+ DescWholePkt=0x60000000, DescStartPkt=0x20000000, DescEndPkt=0x40000000,
+ DescIntr=0x80000000,
+};
+#define PRIV_ALIGN 15 /* Required alignment mask */
+#define PRIV_ALIGN_BYTES 32
+
+static struct winbond_private
+{
+ /* Descriptor rings first for alignment. */
+ struct w840_rx_desc rx_ring[RX_RING_SIZE];
+ struct w840_tx_desc tx_ring[TX_RING_SIZE];
+ struct net_device *next_module; /* Link for devices of this type. */
+ void *priv_addr; /* Unaligned address for kfree */
+ const char *product_name;
+ /* Frequently used values: keep some adjacent for cache effect. */
+ int chip_id, drv_flags;
+ struct pci_dev *pci_dev;
+ int csr6;
+ struct w840_rx_desc *rx_head_desc;
+ unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
+ unsigned int rx_buf_sz; /* Based on MTU+slack. */
+ unsigned int cur_tx, dirty_tx;
+ int tx_q_bytes;
+ unsigned int tx_full:1; /* The Tx queue is full. */
+ /* These values are keep track of the transceiver/media in use. */
+ unsigned int full_duplex:1; /* Full-duplex operation requested. */
+ unsigned int duplex_lock:1;
+ unsigned int medialock:1; /* Do not sense media. */
+ unsigned int default_port:4; /* Last dev->if_port value. */
+ /* MII transceiver section. */
+ int mii_cnt; /* MII device addresses. */
+ u16 advertising; /* NWay media advertisement */
+ unsigned char phys[2]; /* MII device addresses. */
+} w840private __attribute__ ((aligned (PRIV_ALIGN_BYTES)));
+
+/* NIC specific static variables go here */
+
+static int ioaddr;
+static unsigned short eeprom [0x40];
+struct {
+ char rx_packet[PKT_BUF_SZ * RX_RING_SIZE];
+ char tx_packet[PKT_BUF_SZ * TX_RING_SIZE];
+} w89c840_buf __shared;
+
+static int eeprom_read(long ioaddr, int location);
+static int mdio_read(int base_address, int phy_id, int location);
+#if 0
+static void mdio_write(int base_address, int phy_id, int location, int value);
+#endif
+
+static void check_duplex(void);
+static void set_rx_mode(void);
+static void init_ring(void);
+
+#if defined(W89C840_DEBUG)
+static void decode_interrupt(u32 intr_status)
+{
+ printf("Interrupt status: ");
+
+#define TRACE_INTR(_intr_) \
+ if (intr_status & (_intr_)) { printf (" " #_intr_); }
+
+ TRACE_INTR(NormalIntr);
+ TRACE_INTR(AbnormalIntr);
+ TRACE_INTR(IntrPCIErr);
+ TRACE_INTR(TimerInt);
+ TRACE_INTR(IntrRxDied);
+ TRACE_INTR(RxNoBuf);
+ TRACE_INTR(IntrRxDone);
+ TRACE_INTR(TxFIFOUnderflow);
+ TRACE_INTR(RxErrIntr);
+ TRACE_INTR(TxIdle);
+ TRACE_INTR(IntrTxStopped);
+ TRACE_INTR(IntrTxDone);
+
+ printf("\n");
+ /*sleep(1);*/
+}
+#endif
+
+/**************************************************************************
+w89c840_reset - Reset adapter
+***************************************************************************/
+static void w89c840_reset(struct nic *nic)
+{
+ int i;
+
+ /* Reset the chip to erase previous misconfiguration.
+ No hold time required! */
+ writel(0x00000001, ioaddr + PCIBusCfg);
+
+ init_ring();
+
+ writel(virt_to_bus(w840private.rx_ring), ioaddr + RxRingPtr);
+ writel(virt_to_bus(w840private.tx_ring), ioaddr + TxRingPtr);
+
+ for (i = 0; i < ETH_ALEN; i++)
+ writeb(nic->node_addr[i], ioaddr + StationAddr + i);
+
+ /* Initialize other registers. */
+ /* Configure the PCI bus bursts and FIFO thresholds.
+ 486: Set 8 longword cache alignment, 8 longword burst.
+ 586: Set 16 longword cache alignment, no burst limit.
+ Cache alignment bits 15:14 Burst length 13:8
+ 0000 <not allowed> 0000 align to cache 0800 8 longwords
+ 4000 8 longwords 0100 1 longword 1000 16 longwords
+ 8000 16 longwords 0200 2 longwords 2000 32 longwords
+ C000 32 longwords 0400 4 longwords
+ Wait the specified 50 PCI cycles after a reset by initializing
+ Tx and Rx queues and the address filter list. */
+
+ writel(0xE010, ioaddr + PCIBusCfg);
+
+ writel(0, ioaddr + RxStartDemand);
+ w840private.csr6 = 0x20022002;
+ check_duplex();
+ set_rx_mode();
+
+ /* Do not enable the interrupts Etherboot doesn't need them */
+/*
+ writel(0x1A0F5, ioaddr + IntrStatus);
+ writel(0x1A0F5, ioaddr + IntrEnable);
+*/
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : Done reset.\n");
+#endif
+}
+
+#if 0
+static void handle_intr(u32 intr_stat)
+{
+ if ((intr_stat & (NormalIntr|AbnormalIntr)) == 0) {
+ /* we are polling, do not return now */
+ /*return 0;*/
+ } else {
+ /* Acknowledge all of the current interrupt sources ASAP. */
+ writel(intr_stat & 0x001ffff, ioaddr + IntrStatus);
+ }
+
+ if (intr_stat & AbnormalIntr) {
+ /* There was an abnormal interrupt */
+ printf("\n-=- Abnormal interrupt.\n");
+
+#if defined(W89C840_DEBUG)
+ decode_interrupt(intr_stat);
+#endif
+
+ if (intr_stat & RxNoBuf) {
+ /* There was an interrupt */
+ printf("-=- <=> No receive buffers available.\n");
+ writel(0, ioaddr + RxStartDemand);
+ }
+ }
+}
+#endif
+
+/**************************************************************************
+w89c840_poll - Wait for a frame
+***************************************************************************/
+static int w89c840_poll(struct nic *nic, int retrieve)
+{
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+ int packet_received = 0;
+
+#if defined(W89C840_DEBUG)
+ u32 intr_status = readl(ioaddr + IntrStatus);
+#endif
+
+ do {
+ /* Code from netdev_rx(dev) */
+
+ int entry = w840private.cur_rx % RX_RING_SIZE;
+
+ struct w840_rx_desc *desc = w840private.rx_head_desc;
+ s32 status = desc->status;
+
+ if (status & DescOwn) {
+ /* DescOwn bit is still set, we should wait for RX to complete */
+ packet_received = 0;
+ break;
+ }
+
+ if ( !retrieve ) {
+ packet_received = 1;
+ break;
+ }
+
+ if ((status & 0x38008300) != 0x0300) {
+ if ((status & 0x38000300) != 0x0300) {
+ /* Ingore earlier buffers. */
+ if ((status & 0xffff) != 0x7fff) {
+ printf("winbond-840 : Oversized Ethernet frame spanned "
+ "multiple buffers, entry %d status %X !\n",
+ w840private.cur_rx, (unsigned int) status);
+ }
+ } else if (status & 0x8000) {
+ /* There was a fatal error. */
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : Receive error, Rx status %X :", status);
+ if (status & 0x0890) {
+ printf(" RXLEN_ERROR");
+ }
+ if (status & 0x004C) {
+ printf(", FRAME_ERROR");
+ }
+ if (status & 0x0002) {
+ printf(", CRC_ERROR");
+ }
+ printf("\n");
+#endif
+
+ /* Simpy do a reset now... */
+ w89c840_reset(nic);
+
+ packet_received = 0;
+ break;
+ }
+ } else {
+ /* Omit the four octet CRC from the length. */
+ int pkt_len = ((status >> 16) & 0x7ff) - 4;
+
+#if defined(W89C840_DEBUG)
+ printf(" netdev_rx() normal Rx pkt ring %d length %d status %X\n", entry, pkt_len, status);
+#endif
+
+ nic->packetlen = pkt_len;
+
+ /* Check if the packet is long enough to accept without copying
+ to a minimally-sized skbuff. */
+
+ memcpy(nic->packet, le32desc_to_virt(w840private.rx_ring[entry].buffer1), pkt_len);
+ packet_received = 1;
+
+ /* Release buffer to NIC */
+ w840private.rx_ring[entry].status = DescOwn;
+
+#if defined(W89C840_DEBUG)
+ /* You will want this info for the initial debug. */
+ printf(" Rx data %hhX:%hhX:%hhX:%hhX:%hhX:"
+ "%hhX %hhX:%hhX:%hhX:%hhX:%hhX:%hhX %hhX%hhX "
+ "%hhX.%hhX.%hhX.%hhX.\n",
+ nic->packet[0], nic->packet[1], nic->packet[2], nic->packet[3],
+ nic->packet[4], nic->packet[5], nic->packet[6], nic->packet[7],
+ nic->packet[8], nic->packet[9], nic->packet[10],
+ nic->packet[11], nic->packet[12], nic->packet[13],
+ nic->packet[14], nic->packet[15], nic->packet[16],
+ nic->packet[17]);
+#endif
+
+ }
+
+ entry = (++w840private.cur_rx) % RX_RING_SIZE;
+ w840private.rx_head_desc = &w840private.rx_ring[entry];
+ } while (0);
+
+ return packet_received;
+}
+
+/**************************************************************************
+w89c840_transmit - Transmit a frame
+***************************************************************************/
+
+static void w89c840_transmit(
+ struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ /* send the packet to destination */
+ unsigned entry;
+ int transmit_status;
+ unsigned long ct;
+
+ /* Caution: the write order is important here, set the field
+ with the "ownership" bits last. */
+
+ /* Fill in our transmit buffer */
+ entry = w840private.cur_tx % TX_RING_SIZE;
+
+ memcpy (w89c840_buf.tx_packet, d, ETH_ALEN); /* dst */
+ memcpy (w89c840_buf.tx_packet + ETH_ALEN, nic->node_addr, ETH_ALEN);/*src*/
+
+ *((char *) w89c840_buf.tx_packet + 12) = t >> 8; /* type */
+ *((char *) w89c840_buf.tx_packet + 13) = t;
+
+ memcpy (w89c840_buf.tx_packet + ETH_HLEN, p, s);
+ s += ETH_HLEN;
+
+ while (s < ETH_ZLEN)
+ *((char *) w89c840_buf.tx_packet + ETH_HLEN + (s++)) = 0;
+
+ w840private.tx_ring[entry].buffer1
+ = virt_to_le32desc(w89c840_buf.tx_packet);
+
+ w840private.tx_ring[entry].length = (DescWholePkt | (u32) s);
+ if (entry >= TX_RING_SIZE-1) /* Wrap ring */
+ w840private.tx_ring[entry].length |= (DescIntr | DescEndRing);
+ w840private.tx_ring[entry].status = (DescOwn);
+ w840private.cur_tx++;
+
+ w840private.tx_q_bytes = (u16) s;
+ writel(0, ioaddr + TxStartDemand);
+
+ /* Work around horrible bug in the chip by marking the queue as full
+ when we do not have FIFO room for a maximum sized packet. */
+
+ if ((w840private.drv_flags & HasBrokenTx) && w840private.tx_q_bytes > TX_BUG_FIFO_LIMIT) {
+ /* Actually this is left to help finding error tails later in debugging...
+ * See Linux kernel driver in winbond-840.c for details.
+ */
+ w840private.tx_full = 1;
+ }
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : Transmit frame # %d size %d queued in slot %d.\n", w840private.cur_tx, s, entry);
+#endif
+
+ /* Now wait for TX to complete. */
+ transmit_status = w840private.tx_ring[entry].status;
+
+ ct = currticks();
+ {
+#if defined W89C840_DEBUG
+ u32 intr_stat = 0;
+#endif
+ while (1) {
+
+#if defined(W89C840_DEBUG)
+ decode_interrupt(intr_stat);
+#endif
+
+ while ( (transmit_status & DescOwn) && ct + TX_TIMEOUT < currticks()) {
+
+ transmit_status = w840private.tx_ring[entry].status;
+ }
+
+ break;
+ }
+ }
+
+ if ((transmit_status & DescOwn) == 0) {
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : transmission complete after wait loop iterations, status %X\n",
+ w840private.tx_ring[entry].status);
+#endif
+
+ return;
+ }
+
+ /* Transmit timed out... */
+
+ printf("winbond-840 : transmission TIMEOUT : status %X\n",
+ (unsigned int) w840private.tx_ring[entry].status);
+
+ return;
+}
+
+/**************************************************************************
+w89c840_disable - Turn off ethernet interface
+***************************************************************************/
+static void w89c840_disable ( struct nic *nic ) {
+
+ w89c840_reset(nic);
+
+ /* Don't know what to do to disable the board. Is this needed at all? */
+ /* Yes, a live NIC can corrupt the loaded memory later [Ken] */
+ /* Stop the chip's Tx and Rx processes. */
+ writel(w840private.csr6 &= ~0x20FA, ioaddr + NetworkConfig);
+}
+
+/**************************************************************************
+w89c840_irq - Enable, Disable, or Force interrupts
+***************************************************************************/
+static void w89c840_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations w89c840_operations = {
+ .connect = dummy_connect,
+ .poll = w89c840_poll,
+ .transmit = w89c840_transmit,
+ .irq = w89c840_irq,
+
+};
+
+static struct pci_device_id w89c840_nics[] = {
+PCI_ROM(0x1050, 0x0840, "winbond840", "Winbond W89C840F", 0),
+PCI_ROM(0x11f6, 0x2011, "compexrl100atx", "Compex RL100ATX", 0),
+};
+
+PCI_DRIVER ( w89c840_driver, w89c840_nics, PCI_NO_CLASS );
+
+/**************************************************************************
+w89c840_probe - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+static int w89c840_probe ( struct nic *nic, struct pci_device *p ) {
+
+
+ u16 sum = 0;
+ int i;
+ unsigned short value;
+
+ if (p->ioaddr == 0)
+ return 0;
+
+ nic->ioaddr = p->ioaddr;
+ nic->irqno = 0;
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840: PCI bus %hhX device function %hhX: I/O address: %hX\n", p->bus, p->devfn, ioaddr);
+#endif
+
+ ioaddr = ioaddr & ~3; /* Mask the bit that says "this is an io addr" */
+
+#define PCI_DEVICE_ID_WINBOND2_89C840 0x0840
+#define PCI_DEVICE_ID_COMPEX_RL100ATX 0x2011
+
+ /* From Matt Hortman <mbhortman@acpthinclient.com> */
+ if (p->vendor == PCI_VENDOR_ID_WINBOND2
+ && p->device == PCI_DEVICE_ID_WINBOND2_89C840) {
+
+ /* detected "Winbond W89c840 Fast Ethernet PCI NIC" */
+
+ } else if ( p->vendor == PCI_VENDOR_ID_COMPEX
+ && p->device == PCI_DEVICE_ID_COMPEX_RL100ATX) {
+
+ /* detected "Compex RL100ATX Fast Ethernet PCI NIC" */
+
+ } else {
+ /* Gee, guess what? They missed again. */
+ printf("device ID : %X - is not a Compex RL100ATX NIC.\n",
+ p->device);
+ return 0;
+ }
+
+ printf(" %s\n", w89c840_version);
+
+ adjust_pci_device(p);
+
+ /* Ok. Got one. Read the eeprom. */
+ for (i = 0; i < 0x40; i++) {
+ value = eeprom_read(ioaddr, i);
+ eeprom[i] = value;
+ sum += value;
+ }
+
+ for (i=0;i<ETH_ALEN;i++) {
+ nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff;
+ }
+
+ DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) );
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840: EEPROM checksum %hX, got eeprom", sum);
+#endif
+
+ /* Reset the chip to erase previous misconfiguration.
+ No hold time required! */
+ writel(0x00000001, ioaddr + PCIBusCfg);
+
+ if (driver_flags & CanHaveMII) {
+ int phy, phy_idx = 0;
+ for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
+ int mii_status = mdio_read(ioaddr, phy, 1);
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ w840private.phys[phy_idx++] = phy;
+ w840private.advertising = mdio_read(ioaddr, phy, 4);
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : MII PHY found at address %d, status "
+ "%X advertising %hX.\n", phy, mii_status, w840private.advertising);
+#endif
+
+ }
+ }
+
+ w840private.mii_cnt = phy_idx;
+
+ if (phy_idx == 0) {
+ printf("winbond-840 : MII PHY not found -- this device may not operate correctly.\n");
+ }
+ }
+
+ /* point to NIC specific routines */
+ nic->nic_op = &w89c840_operations;
+
+ w89c840_reset(nic);
+
+ return 1;
+}
+
+/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. These are
+ often serial bit streams generated by the host processor.
+ The example below is for the common 93c46 EEPROM, 64 16 bit words. */
+
+/* Delay between EEPROM clock transitions.
+ No extra delay is needed with 33Mhz PCI, but future 66Mhz access may need
+ a delay. Note that pre-2.0.34 kernels had a cache-alignment bug that
+ made udelay() unreliable.
+ The old method of using an ISA access as a delay, __SLOW_DOWN_IO__, is
+ depricated.
+*/
+#define eeprom_delay(ee_addr) readl(ee_addr)
+
+enum EEPROM_Ctrl_Bits {
+ EE_ShiftClk=0x02, EE_Write0=0x801, EE_Write1=0x805,
+ EE_ChipSelect=0x801, EE_DataIn=0x08,
+};
+
+/* The EEPROM commands include the alway-set leading bit. */
+enum EEPROM_Cmds {
+ EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6),
+};
+
+static int eeprom_read(long addr, int location)
+{
+ int i;
+ int retval = 0;
+ int ee_addr = addr + EECtrl;
+ int read_cmd = location | EE_ReadCmd;
+ writel(EE_ChipSelect, ee_addr);
+
+ /* Shift the read command bits out. */
+ for (i = 10; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
+ writel(dataval, ee_addr);
+ eeprom_delay(ee_addr);
+ writel(dataval | EE_ShiftClk, ee_addr);
+ eeprom_delay(ee_addr);
+ }
+ writel(EE_ChipSelect, ee_addr);
+
+ for (i = 16; i > 0; i--) {
+ writel(EE_ChipSelect | EE_ShiftClk, ee_addr);
+ eeprom_delay(ee_addr);
+ retval = (retval << 1) | ((readl(ee_addr) & EE_DataIn) ? 1 : 0);
+ writel(EE_ChipSelect, ee_addr);
+ eeprom_delay(ee_addr);
+ }
+
+ /* Terminate the EEPROM access. */
+ writel(0, ee_addr);
+ return retval;
+}
+
+/* MII transceiver control section.
+ Read and write the MII registers using software-generated serial
+ MDIO protocol. See the MII specifications or DP83840A data sheet
+ for details.
+
+ The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
+ met by back-to-back 33Mhz PCI cycles. */
+#define mdio_delay(mdio_addr) readl(mdio_addr)
+
+/* Set iff a MII transceiver on any interface requires mdio preamble.
+ This only set with older tranceivers, so the extra
+ code size of a per-interface flag is not worthwhile. */
+static char mii_preamble_required = 1;
+
+#define MDIO_WRITE0 (MDIO_EnbOutput)
+#define MDIO_WRITE1 (MDIO_DataOut | MDIO_EnbOutput)
+
+/* Generate the preamble required for initial synchronization and
+ a few older transceivers. */
+static void mdio_sync(long mdio_addr)
+{
+ int bits = 32;
+
+ /* Establish sync by sending at least 32 logic ones. */
+ while (--bits >= 0) {
+ writel(MDIO_WRITE1, mdio_addr);
+ mdio_delay(mdio_addr);
+ writel(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+}
+
+static int mdio_read(int base_address, int phy_id, int location)
+{
+ long mdio_addr = base_address + MIICtrl;
+ int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+ int i, retval = 0;
+
+ if (mii_preamble_required)
+ mdio_sync(mdio_addr);
+
+ /* Shift the read command bits out. */
+ for (i = 15; i >= 0; i--) {
+ int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
+
+ writel(dataval, mdio_addr);
+ mdio_delay(mdio_addr);
+ writel(dataval | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ /* Read the two transition, 16 data, and wire-idle bits. */
+ for (i = 20; i > 0; i--) {
+ writel(MDIO_EnbIn, mdio_addr);
+ mdio_delay(mdio_addr);
+ retval = (retval << 1) | ((readl(mdio_addr) & MDIO_DataIn) ? 1 : 0);
+ writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ return (retval>>1) & 0xffff;
+}
+
+#if 0
+static void mdio_write(int base_address, int phy_id, int location, int value)
+{
+ long mdio_addr = base_address + MIICtrl;
+ int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
+ int i;
+
+ if (location == 4 && phy_id == w840private.phys[0])
+ w840private.advertising = value;
+
+ if (mii_preamble_required)
+ mdio_sync(mdio_addr);
+
+ /* Shift the command bits out. */
+ for (i = 31; i >= 0; i--) {
+ int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
+
+ writel(dataval, mdio_addr);
+ mdio_delay(mdio_addr);
+ writel(dataval | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ /* Clear out extra bits. */
+ for (i = 2; i > 0; i--) {
+ writel(MDIO_EnbIn, mdio_addr);
+ mdio_delay(mdio_addr);
+ writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ return;
+}
+#endif
+
+static void check_duplex(void)
+{
+ int mii_reg5 = mdio_read(ioaddr, w840private.phys[0], 5);
+ int negotiated = mii_reg5 & w840private.advertising;
+ int duplex;
+
+ if (w840private.duplex_lock || mii_reg5 == 0xffff)
+ return;
+
+ duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
+ if (w840private.full_duplex != duplex) {
+ w840private.full_duplex = duplex;
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : Setting %s-duplex based on MII # %d negotiated capability %X\n",
+ duplex ? "full" : "half", w840private.phys[0], negotiated);
+#endif
+
+ w840private.csr6 &= ~0x200;
+ w840private.csr6 |= duplex ? 0x200 : 0;
+ }
+}
+
+static void set_rx_mode(void)
+{
+ u32 mc_filter[2]; /* Multicast hash filter */
+ u32 rx_mode;
+
+ /* Accept all multicasts from now on. */
+ memset(mc_filter, 0xff, sizeof(mc_filter));
+
+/*
+ * works OK with multicast enabled.
+ */
+
+ rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast;
+
+ writel(mc_filter[0], ioaddr + MulticastFilter0);
+ writel(mc_filter[1], ioaddr + MulticastFilter1);
+ w840private.csr6 &= ~0x00F8;
+ w840private.csr6 |= rx_mode;
+ writel(w840private.csr6, ioaddr + NetworkConfig);
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : Done setting RX mode.\n");
+#endif
+}
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void init_ring(void)
+{
+ int i;
+ char * p;
+
+ w840private.tx_full = 0;
+ w840private.tx_q_bytes = w840private.cur_rx = w840private.cur_tx = 0;
+ w840private.dirty_rx = w840private.dirty_tx = 0;
+
+ w840private.rx_buf_sz = PKT_BUF_SZ;
+ w840private.rx_head_desc = &w840private.rx_ring[0];
+
+ /* Initial all Rx descriptors. Fill in the Rx buffers. */
+
+ p = &w89c840_buf.rx_packet[0];
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ w840private.rx_ring[i].length = w840private.rx_buf_sz;
+ w840private.rx_ring[i].status = 0;
+ w840private.rx_ring[i].next_desc = virt_to_le32desc(&w840private.rx_ring[i+1]);
+
+ w840private.rx_ring[i].buffer1 = virt_to_le32desc(p + (PKT_BUF_SZ * i));
+ w840private.rx_ring[i].status = DescOwn | DescIntr;
+ }
+
+ /* Mark the last entry as wrapping the ring. */
+ w840private.rx_ring[i-1].length |= DescEndRing;
+ w840private.rx_ring[i-1].next_desc = virt_to_le32desc(&w840private.rx_ring[0]);
+
+ w840private.dirty_rx = (unsigned int)(i - RX_RING_SIZE);
+
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ w840private.tx_ring[i].status = 0;
+ }
+ return;
+}
+
+
+DRIVER ( "W89C840F", nic_driver, pci_driver, w89c840_driver,
+ w89c840_probe, w89c840_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/wd.c b/src/VBox/Devices/PC/ipxe/src/drivers/net/wd.c
new file mode 100644
index 00000000..9939aa08
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/wd.c
@@ -0,0 +1,6 @@
+/* ISA memory-mapped NS8390-based cards, including WD80x3 */
+#if 0 /* Currently broken! */
+#define INCLUDE_WD
+#define WD_DEFAULT_MEM 0xCC000
+#include "ns8390.c"
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/net/wlan_compat.h b/src/VBox/Devices/PC/ipxe/src/drivers/net/wlan_compat.h
new file mode 100644
index 00000000..9b7693bb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/net/wlan_compat.h
@@ -0,0 +1,577 @@
+/* src/include/wlan/wlan_compat.h
+*
+* Types and macros to aid in portability
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#ifndef _WLAN_COMPAT_H
+#define _WLAN_COMPAT_H
+
+/*=============================================================*/
+/*------ Establish Platform Identity --------------------------*/
+/*=============================================================*/
+/* Key macros: */
+/* WLAN_CPU_FAMILY */
+ #define WLAN_Ix86 1
+ #define WLAN_PPC 2
+ #define WLAN_Ix96 3
+ #define WLAN_ARM 4
+ #define WLAN_ALPHA 5
+ #define WLAN_MIPS 6
+ #define WLAN_HPPA 7
+/* WLAN_CPU_CORE */
+ #define WLAN_I386CORE 1
+ #define WLAN_PPCCORE 2
+ #define WLAN_I296 3
+ #define WLAN_ARMCORE 4
+ #define WLAN_ALPHACORE 5
+ #define WLAN_MIPSCORE 6
+ #define WLAN_HPPACORE 7
+/* WLAN_CPU_PART */
+ #define WLAN_I386PART 1
+ #define WLAN_MPC860 2
+ #define WLAN_MPC823 3
+ #define WLAN_I296SA 4
+ #define WLAN_PPCPART 5
+ #define WLAN_ARMPART 6
+ #define WLAN_ALPHAPART 7
+ #define WLAN_MIPSPART 8
+ #define WLAN_HPPAPART 9
+/* WLAN_SYSARCH */
+ #define WLAN_PCAT 1
+ #define WLAN_MBX 2
+ #define WLAN_RPX 3
+ #define WLAN_LWARCH 4
+ #define WLAN_PMAC 5
+ #define WLAN_SKIFF 6
+ #define WLAN_BITSY 7
+ #define WLAN_ALPHAARCH 7
+ #define WLAN_MIPSARCH 9
+ #define WLAN_HPPAARCH 10
+/* WLAN_OS */
+ #define WLAN_LINUX_KERNEL 1
+ #define WLAN_LINUX_USER 2
+/* WLAN_HOSTIF (generally set on the command line, not detected) */
+ #define WLAN_PCMCIA 1
+ #define WLAN_ISA 2
+ #define WLAN_PCI 3
+ #define WLAN_USB 4
+ #define WLAN_PLX 5
+
+/* Note: the PLX HOSTIF above refers to some vendors implementations for */
+/* PCI. It's a PLX chip that is a PCI to PCMCIA adapter, but it */
+/* isn't a real PCMCIA host interface adapter providing all the */
+/* card&socket services. */
+
+/* Lets try to figure out what we've got. Kernel mode or User mode? */
+#if defined(__KERNEL__)
+ #define WLAN_OS WLAN_LINUX_KERNEL
+#else
+ #define WLAN_OS WLAN_LINUX_USER
+#endif
+
+#ifdef __powerpc__
+#ifndef __ppc__
+#define __ppc__
+#endif
+#endif
+
+#if (defined(CONFIG_PPC) || defined(CONFIG_8xx))
+#ifndef __ppc__
+#define __ppc__
+#endif
+#endif
+
+#if defined(__KERNEL__)
+#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
+ #define WLAN_CPU_FAMILY WLAN_Ix86
+ #define WLAN_CPU_CORE WLAN_I386CORE
+ #define WLAN_CPU_PART WLAN_I386PART
+ #define WLAN_SYSARCH WLAN_PCAT
+#elif defined(__ppc__)
+ #define WLAN_CPU_FAMILY WLAN_PPC
+ #define WLAN_CPU_CORE WLAN_PPCCORE
+ #if defined(CONFIG_MBX)
+ #define WLAN_CPU_PART WLAN_MPC860
+ #define WLAN_SYSARCH WLAN_MBX
+ #elif defined(CONFIG_RPXLITE)
+ #define WLAN_CPU_PART WLAN_MPC823
+ #define WLAN_SYSARCH WLAN_RPX
+ #elif defined(CONFIG_RPXCLASSIC)
+ #define WLAN_CPU_PART WLAN_MPC860
+ #define WLAN_SYSARCH WLAN_RPX
+ #else
+ #define WLAN_CPU_PART WLAN_PPCPART
+ #define WLAN_SYSARCH WLAN_PMAC
+ #endif
+#elif defined(__arm__)
+ #define WLAN_CPU_FAMILY WLAN_ARM
+ #define WLAN_CPU_CORE WLAN_ARMCORE
+ #define WLAN_CPU_PART WLAN_ARM_PART
+ #define WLAN_SYSARCH WLAN_SKIFF
+#elif defined(__alpha__)
+ #define WLAN_CPU_FAMILY WLAN_ALPHA
+ #define WLAN_CPU_CORE WLAN_ALPHACORE
+ #define WLAN_CPU_PART WLAN_ALPHAPART
+ #define WLAN_SYSARCH WLAN_ALPHAARCH
+#elif defined(__mips__)
+ #define WLAN_CPU_FAMILY WLAN_MIPS
+ #define WLAN_CPU_CORE WLAN_MIPSCORE
+ #define WLAN_CPU_PART WLAN_MIPSPART
+ #define WLAN_SYSARCH WLAN_MIPSARCH
+#elif defined(__hppa__)
+ #define WLAN_CPU_FAMILY WLAN_HPPA
+ #define WLAN_CPU_CORE WLAN_HPPACORE
+ #define WLAN_CPU_PART WLAN_HPPAPART
+ #define WLAN_SYSARCH WLAN_HPPAARCH
+#else
+ #error "No CPU identified!"
+#endif
+#endif /* __KERNEL__ */
+
+/*
+ Some big endian machines implicitly do all I/O in little endian mode.
+
+ In particular:
+ Linux/PPC on PowerMacs (PCI)
+ Arm/Intel Xscale (PCI)
+
+ This may also affect PLX boards and other BE &| PPC platforms;
+ as new ones are discovered, add them below.
+*/
+
+#if (WLAN_HOSTIF == WLAN_PCI)
+#if ((WLAN_SYSARCH == WLAN_SKIFF) || (WLAN_SYSARCH == WLAN_PMAC))
+#define REVERSE_ENDIAN
+#endif
+#endif
+
+/*=============================================================*/
+/*------ Bit settings -----------------------------------------*/
+/*=============================================================*/
+
+#define BIT0 0x00000001
+#define BIT1 0x00000002
+#define BIT2 0x00000004
+#define BIT3 0x00000008
+#define BIT4 0x00000010
+#define BIT5 0x00000020
+#define BIT6 0x00000040
+#define BIT7 0x00000080
+#define BIT8 0x00000100
+#define BIT9 0x00000200
+#define BIT10 0x00000400
+#define BIT11 0x00000800
+#define BIT12 0x00001000
+#define BIT13 0x00002000
+#define BIT14 0x00004000
+#define BIT15 0x00008000
+#define BIT16 0x00010000
+#define BIT17 0x00020000
+#define BIT18 0x00040000
+#define BIT19 0x00080000
+#define BIT20 0x00100000
+#define BIT21 0x00200000
+#define BIT22 0x00400000
+#define BIT23 0x00800000
+#define BIT24 0x01000000
+#define BIT25 0x02000000
+#define BIT26 0x04000000
+#define BIT27 0x08000000
+#define BIT28 0x10000000
+#define BIT29 0x20000000
+#define BIT30 0x40000000
+#define BIT31 0x80000000
+
+typedef unsigned char UINT8;
+typedef unsigned short UINT16;
+typedef unsigned long UINT32;
+
+typedef signed char INT8;
+typedef signed short INT16;
+typedef signed long INT32;
+
+typedef unsigned int UINT;
+typedef signed int INT;
+
+typedef unsigned long long UINT64;
+typedef signed long long INT64;
+
+#define UINT8_MAX (0xffUL)
+#define UINT16_MAX (0xffffUL)
+#define UINT32_MAX (0xffffffffUL)
+
+#define INT8_MAX (0x7fL)
+#define INT16_MAX (0x7fffL)
+#define INT32_MAX (0x7fffffffL)
+
+/*=============================================================*/
+/*------ Compiler Portability Macros --------------------------*/
+/*=============================================================*/
+#define __WLAN_ATTRIB_PACK__ __attribute__ ((packed))
+#define __WLAN_PRAGMA_PACK1__
+#define __WLAN_PRAGMA_PACKDFLT__
+#define __WLAN_INLINE__ inline
+#define WLAN_MIN_ARRAY 0
+
+/*=============================================================*/
+/*------ OS Portability Macros --------------------------------*/
+/*=============================================================*/
+
+#ifndef WLAN_DBVAR
+#define WLAN_DBVAR wlan_debug
+#endif
+
+#if (WLAN_OS == WLAN_LINUX_KERNEL)
+ #define WLAN_LOG_ERROR0(x) printk(KERN_ERR "%s: " x , __FUNCTION__ );
+ #define WLAN_LOG_ERROR1(x,n) printk(KERN_ERR "%s: " x , __FUNCTION__ , (n));
+ #define WLAN_LOG_ERROR2(x,n1,n2) printk(KERN_ERR "%s: " x , __FUNCTION__ , (n1), (n2));
+ #define WLAN_LOG_ERROR3(x,n1,n2,n3) printk(KERN_ERR "%s: " x , __FUNCTION__, (n1), (n2), (n3));
+ #define WLAN_LOG_ERROR4(x,n1,n2,n3,n4) printk(KERN_ERR "%s: " x , __FUNCTION__, (n1), (n2), (n3), (n4));
+
+ #define WLAN_LOG_WARNING0(x) printk(KERN_WARNING "%s: " x , __FUNCTION__);
+ #define WLAN_LOG_WARNING1(x,n) printk(KERN_WARNING "%s: " x , __FUNCTION__, (n));
+ #define WLAN_LOG_WARNING2(x,n1,n2) printk(KERN_WARNING "%s: " x , __FUNCTION__, (n1), (n2));
+ #define WLAN_LOG_WARNING3(x,n1,n2,n3) printk(KERN_WARNING "%s: " x , __FUNCTION__, (n1), (n2), (n3));
+ #define WLAN_LOG_WARNING4(x,n1,n2,n3,n4) printk(KERN_WARNING "%s: " x , __FUNCTION__ , (n1), (n2), (n3), (n4));
+
+ #define WLAN_LOG_NOTICE0(x) printk(KERN_NOTICE "%s: " x , __FUNCTION__);
+ #define WLAN_LOG_NOTICE1(x,n) printk(KERN_NOTICE "%s: " x , __FUNCTION__, (n));
+ #define WLAN_LOG_NOTICE2(x,n1,n2) printk(KERN_NOTICE "%s: " x , __FUNCTION__, (n1), (n2));
+ #define WLAN_LOG_NOTICE3(x,n1,n2,n3) printk(KERN_NOTICE "%s: " x , __FUNCTION__, (n1), (n2), (n3));
+ #define WLAN_LOG_NOTICE4(x,n1,n2,n3,n4) printk(KERN_NOTICE "%s: " x , __FUNCTION__, (n1), (n2), (n3), (n4));
+
+ #define WLAN_LOG_INFO0(x) printk(KERN_INFO x);
+ #define WLAN_LOG_INFO1(x,n) printk(KERN_INFO x, (n));
+ #define WLAN_LOG_INFO2(x,n1,n2) printk(KERN_INFO x, (n1), (n2));
+ #define WLAN_LOG_INFO3(x,n1,n2,n3) printk(KERN_INFO x, (n1), (n2), (n3));
+ #define WLAN_LOG_INFO4(x,n1,n2,n3,n4) printk(KERN_INFO x, (n1), (n2), (n3), (n4));
+ #define WLAN_LOG_INFO5(x,n1,n2,n3,n4,n5) printk(KERN_INFO x, (n1), (n2), (n3), (n4), (n5));
+
+ #if defined(WLAN_INCLUDE_DEBUG)
+ #define WLAN_ASSERT(c) if ((!(c)) && WLAN_DBVAR >= 1) { \
+ WLAN_LOG_DEBUG0(1, "Assertion failure!\n"); }
+ #define WLAN_HEX_DUMP( l, x, p, n) if( WLAN_DBVAR >= (l) ){ \
+ int __i__; \
+ printk(KERN_DEBUG x ":"); \
+ for( __i__=0; __i__ < (n); __i__++) \
+ printk( " %02x", ((UINT8*)(p))[__i__]); \
+ printk("\n"); }
+
+ #define DBFENTER { if ( WLAN_DBVAR >= 4 ){ WLAN_LOG_DEBUG0(3,"Enter\n"); } }
+ #define DBFEXIT { if ( WLAN_DBVAR >= 4 ){ WLAN_LOG_DEBUG0(3,"Exit\n"); } }
+
+ #define WLAN_LOG_DEBUG0(l,x) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s: " x , __FUNCTION__ );
+ #define WLAN_LOG_DEBUG1(l,x,n) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s: " x , __FUNCTION__ , (n));
+ #define WLAN_LOG_DEBUG2(l,x,n1,n2) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s: " x , __FUNCTION__ , (n1), (n2));
+ #define WLAN_LOG_DEBUG3(l,x,n1,n2,n3) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s: " x , __FUNCTION__ , (n1), (n2), (n3));
+ #define WLAN_LOG_DEBUG4(l,x,n1,n2,n3,n4) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s: " x , __FUNCTION__ , (n1), (n2), (n3), (n4));
+ #define WLAN_LOG_DEBUG5(l,x,n1,n2,n3,n4,n5) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s: " x , __FUNCTION__ , (n1), (n2), (n3), (n4), (n5));
+ #define WLAN_LOG_DEBUG6(l,x,n1,n2,n3,n4,n5,n6) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s: " x , __FUNCTION__ , (n1), (n2), (n3), (n4), (n5), (n6));
+ #else
+ #define WLAN_ASSERT(c)
+ #define WLAN_HEX_DUMP( l, s, p, n)
+
+ #define DBFENTER
+ #define DBFEXIT
+
+ #define WLAN_LOG_DEBUG0(l, s)
+ #define WLAN_LOG_DEBUG1(l, s,n)
+ #define WLAN_LOG_DEBUG2(l, s,n1,n2)
+ #define WLAN_LOG_DEBUG3(l, s,n1,n2,n3)
+ #define WLAN_LOG_DEBUG4(l, s,n1,n2,n3,n4)
+ #define WLAN_LOG_DEBUG5(l, s,n1,n2,n3,n4,n5)
+ #endif
+#else
+ #define WLAN_LOG_ERROR0(s)
+ #define WLAN_LOG_ERROR1(s,n)
+ #define WLAN_LOG_ERROR2(s,n1,n2)
+ #define WLAN_LOG_ERROR3(s,n1,n2,n3)
+ #define WLAN_LOG_ERROR4(s,n1,n2,n3,n4)
+
+ #define WLAN_LOG_WARNING0(s)
+ #define WLAN_LOG_WARNING1(s,n)
+ #define WLAN_LOG_WARNING2(s,n1,n2)
+ #define WLAN_LOG_WARNING3(s,n1,n2,n3)
+ #define WLAN_LOG_WARNING4(s,n1,n2,n3,n4)
+
+ #define WLAN_LOG_NOTICE0(s)
+ #define WLAN_LOG_NOTICE1(s,n)
+ #define WLAN_LOG_NOTICE2(s,n1,n2)
+ #define WLAN_LOG_NOTICE3(s,n1,n2,n3)
+ #define WLAN_LOG_NOTICE4(s,n1,n2,n3,n4)
+
+ #define WLAN_ASSERT(c)
+ #define WLAN_HEX_DUMP( l, s, p, n)
+
+ #define DBFENTER
+ #define DBFEXIT
+
+ #define WLAN_LOG_INFO0(s)
+ #define WLAN_LOG_INFO1(s,n)
+ #define WLAN_LOG_INFO2(s,n1,n2)
+ #define WLAN_LOG_INFO3(s,n1,n2,n3)
+ #define WLAN_LOG_INFO4(s,n1,n2,n3,n4)
+ #define WLAN_LOG_INFO5(s,n1,n2,n3,n4,n5)
+
+ #define WLAN_LOG_DEBUG0(l, s)
+ #define WLAN_LOG_DEBUG1(l, s,n)
+ #define WLAN_LOG_DEBUG2(l, s,n1,n2)
+ #define WLAN_LOG_DEBUG3(l, s,n1,n2,n3)
+ #define WLAN_LOG_DEBUG4(l, s,n1,n2,n3,n4)
+ #define WLAN_LOG_DEBUG5(l, s,n1,n2,n3,n4,n5)
+#endif
+
+#define wlan_ms_per_tick (1000UL / (wlan_ticks_per_sec))
+#define wlan_ms_to_ticks(n) ( (n) / (wlan_ms_per_tick))
+#define wlan_tu2ticks(n) ( (n) / (wlan_ms_per_tick))
+#define WLAN_INT_DISABLE(n) { save_flags((n)); cli(); }
+#define WLAN_INT_ENABLE(n) { sti(); restore_flags((n)); }
+
+#ifdef CONFIG_MODVERSIONS
+#define MODVERSIONS 1
+#include <linux/modversions.h>
+#endif
+
+#ifdef CONFIG_SMP
+#define __SMP__ 1
+#endif
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17))
+#define CONFIG_NETLINK 1
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
+#define kfree_s(a, b) kfree((a))
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18))
+#ifndef init_waitqueue_head
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,0,16))
+#define init_waitqueue_head(p) (*(p) = NULL)
+#else
+#define init_waitqueue_head(p) init_waitqueue(p)
+#endif
+typedef struct wait_queue *wait_queue_head_t;
+typedef struct wait_queue wait_queue_t;
+#define set_current_state(b) { current->state = (b); mb(); }
+#define init_waitqueue_entry(a, b) { (a)->task = current; }
+#endif
+#endif
+
+#ifndef wait_event_interruptible_timeout
+// retval == 0; signal met; we're good.
+// retval < 0; interrupted by signal.
+// retval > 0; timed out.
+#define __wait_event_interruptible_timeout(wq, condition, timeout, ret) \
+do { \
+ int __ret = 0; \
+ if (!(condition)) { \
+ wait_queue_t __wait; \
+ unsigned long expire; \
+ init_waitqueue_entry(&__wait, current); \
+ \
+ expire = timeout + jiffies; \
+ add_wait_queue(&wq, &__wait); \
+ for (;;) { \
+ set_current_state(TASK_INTERRUPTIBLE); \
+ if (condition) \
+ break; \
+ if (jiffies > expire) { \
+ ret = jiffies - expire; \
+ break; \
+ } \
+ if (!signal_pending(current)) { \
+ schedule_timeout(timeout); \
+ continue; \
+ } \
+ ret = -ERESTARTSYS; \
+ break; \
+ } \
+ set_current_state(TASK_RUNNING); \
+ remove_wait_queue(&wq, &__wait); \
+ } \
+} while (0)
+
+#define wait_event_interruptible_timeout(wq, condition, timeout) \
+({ \
+ int __ret = 0; \
+ if (!(condition)) \
+ __wait_event_interruptible_timeout(wq, condition, \
+ timeout, __ret); \
+ __ret; \
+})
+
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,90))
+#define spin_lock(l) do { } while (0)
+#define spin_unlock(l) do { } while (0)
+#define spin_lock_irqsave(l,f) do { save_flags(f); cli(); } while (0)
+#define spin_unlock_irqrestore(l,f) do { restore_flags(f); } while (0)
+#define spin_lock_init(s) do { } while (0)
+#define spin_trylock(l) (1)
+typedef int spinlock_t;
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+#ifdef CONFIG_SMP
+#define spin_is_locked(x) (*(volatile char *)(&(x)->lock) <= 0)
+#else
+#define spin_is_locked(l) (0)
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38))
+typedef struct device netdevice_t;
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4))
+typedef struct net_device netdevice_t;
+#else
+#undef netdevice_t
+typedef struct net_device netdevice_t;
+#endif
+
+#ifdef WIRELESS_EXT
+#if (WIRELESS_EXT < 13)
+struct iw_request_info
+{
+ __u16 cmd; /* Wireless Extension command */
+ __u16 flags; /* More to come ;-) */
+};
+#endif
+#endif
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,18))
+#define MODULE_PARM(a,b) extern int __bogus_decl
+#define MODULE_AUTHOR(a) extern int __bogus_decl
+#define MODULE_DESCRIPTION(a) extern int __bogus_decl
+#define MODULE_SUPPORTED_DEVICE(a) extern int __bogus_decl
+#undef GET_USE_COUNT
+#define GET_USE_COUNT(m) mod_use_count_
+#endif
+
+#ifndef MODULE_LICENSE
+#define MODULE_LICENSE(m) extern int __bogus_decl
+#endif
+
+/* TODO: Do we care about this? */
+#ifndef MODULE_DEVICE_TABLE
+#define MODULE_DEVICE_TABLE(foo,bar)
+#endif
+
+#define wlan_minutes2ticks(a) ((a)*(wlan_ticks_per_sec * 60))
+#define wlan_seconds2ticks(a) ((a)*(wlan_ticks_per_sec))
+
+/*=============================================================*/
+/*------ Hardware Portability Macros --------------------------*/
+/*=============================================================*/
+
+#define ieee2host16(n) __le16_to_cpu(n)
+#define ieee2host32(n) __le32_to_cpu(n)
+#define host2ieee16(n) __cpu_to_le16(n)
+#define host2ieee32(n) __cpu_to_le32(n)
+
+#if (WLAN_CPU_FAMILY == WLAN_PPC)
+ #define wlan_inw(a) in_be16((unsigned short *)((a)+_IO_BASE))
+ #define wlan_inw_le16_to_cpu(a) inw((a))
+ #define wlan_outw(v,a) out_be16((unsigned short *)((a)+_IO_BASE), (v))
+ #define wlan_outw_cpu_to_le16(v,a) outw((v),(a))
+#else
+ #define wlan_inw(a) inw((a))
+ #define wlan_inw_le16_to_cpu(a) __cpu_to_le16(inw((a)))
+ #define wlan_outw(v,a) outw((v),(a))
+ #define wlan_outw_cpu_to_le16(v,a) outw(__cpu_to_le16((v)),(a))
+#endif
+
+/*=============================================================*/
+/*--- General Macros ------------------------------------------*/
+/*=============================================================*/
+
+#define wlan_max(a, b) (((a) > (b)) ? (a) : (b))
+#define wlan_min(a, b) (((a) < (b)) ? (a) : (b))
+
+#define wlan_isprint(c) (((c) > (0x19)) && ((c) < (0x7f)))
+
+#define wlan_hexchar(x) (((x) < 0x0a) ? ('0' + (x)) : ('a' + ((x) - 0x0a)))
+
+/* Create a string of printable chars from something that might not be */
+/* It's recommended that the str be 4*len + 1 bytes long */
+#define wlan_mkprintstr(buf, buflen, str, strlen) \
+{ \
+ int i = 0; \
+ int j = 0; \
+ memset(str, 0, (strlen)); \
+ for (i = 0; i < (buflen); i++) { \
+ if ( wlan_isprint((buf)[i]) ) { \
+ (str)[j] = (buf)[i]; \
+ j++; \
+ } else { \
+ (str)[j] = '\\'; \
+ (str)[j+1] = 'x'; \
+ (str)[j+2] = wlan_hexchar(((buf)[i] & 0xf0) >> 4); \
+ (str)[j+3] = wlan_hexchar(((buf)[i] & 0x0f)); \
+ j += 4; \
+ } \
+ } \
+}
+
+/*=============================================================*/
+/*--- Variables -----------------------------------------------*/
+/*=============================================================*/
+
+extern int wlan_debug;
+extern int wlan_ethconv; /* What's the default ethconv? */
+
+/*=============================================================*/
+/*--- Functions -----------------------------------------------*/
+/*=============================================================*/
+#endif /* _WLAN_COMPAT_H */
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/nvs/nvs.c b/src/VBox/Devices/PC/ipxe/src/drivers/nvs/nvs.c
new file mode 100644
index 00000000..a4a06ccf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/nvs/nvs.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/nvs.h>
+
+/** @file
+ *
+ * Non-volatile storage
+ *
+ */
+
+/**
+ * Calculate length up to next block boundary
+ *
+ * @v nvs NVS device
+ * @v address Starting address
+ * @v max_len Maximum length
+ * @ret len Length to use, stopping at block boundaries
+ */
+static size_t nvs_frag_len ( struct nvs_device *nvs, unsigned int address,
+ size_t max_len ) {
+ size_t frag_len;
+
+ /* If there are no block boundaries, return the maximum length */
+ if ( ! nvs->block_size )
+ return max_len;
+
+ /* Calculate space remaining up to next block boundary */
+ frag_len = ( ( nvs->block_size -
+ ( address & ( nvs->block_size - 1 ) ) )
+ << nvs->word_len_log2 );
+
+ /* Limit to maximum length */
+ if ( max_len < frag_len )
+ return max_len;
+
+ return frag_len;
+}
+
+/**
+ * Read from non-volatile storage device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int nvs_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len ) {
+ size_t frag_len;
+ int rc;
+
+ /* We don't even attempt to handle buffer lengths that aren't
+ * an integral number of words.
+ */
+ assert ( ( len & ( ( 1 << nvs->word_len_log2 ) - 1 ) ) == 0 );
+
+ while ( len ) {
+
+ /* Calculate length to read, stopping at block boundaries */
+ frag_len = nvs_frag_len ( nvs, address, len );
+
+ /* Read this portion of the buffer from the device */
+ if ( ( rc = nvs->read ( nvs, address, data, frag_len ) ) != 0 )
+ return rc;
+
+ /* Update parameters */
+ data += frag_len;
+ address += ( frag_len >> nvs->word_len_log2 );
+ len -= frag_len;
+ }
+
+ return 0;
+}
+
+/**
+ * Verify content of non-volatile storage device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data to compare against
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int nvs_verify ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len ) {
+ uint8_t read_data[len];
+ int rc;
+
+ /* Read data into temporary buffer */
+ if ( ( rc = nvs_read ( nvs, address, read_data, len ) ) != 0 )
+ return rc;
+
+ /* Compare data */
+ if ( memcmp ( data, read_data, len ) != 0 ) {
+ DBG ( "NVS %p verification failed at %#04x+%zd\n",
+ nvs, address, len );
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * Write to non-volatile storage device
+ *
+ * @v nvs NVS device
+ * @v address Address to which to write
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int nvs_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len ) {
+ size_t frag_len;
+ int rc;
+
+ /* We don't even attempt to handle buffer lengths that aren't
+ * an integral number of words.
+ */
+ assert ( ( len & ( ( 1 << nvs->word_len_log2 ) - 1 ) ) == 0 );
+
+ while ( len ) {
+
+ /* Calculate length to write, stopping at block boundaries */
+ frag_len = nvs_frag_len ( nvs, address, len );
+
+ /* Write this portion of the buffer to the device */
+ if ( ( rc = nvs->write ( nvs, address, data, frag_len ) ) != 0)
+ return rc;
+
+ /* Read back and verify data */
+ if ( ( rc = nvs_verify ( nvs, address, data, frag_len ) ) != 0)
+ return rc;
+
+ /* Update parameters */
+ data += frag_len;
+ address += ( frag_len >> nvs->word_len_log2 );
+ len -= frag_len;
+ }
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/nvs/nvsvpd.c b/src/VBox/Devices/PC/ipxe/src/drivers/nvs/nvsvpd.c
new file mode 100644
index 00000000..a22ec825
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/nvs/nvsvpd.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/nvs.h>
+#include <ipxe/pci.h>
+#include <ipxe/pcivpd.h>
+#include <ipxe/nvo.h>
+#include <ipxe/nvsvpd.h>
+
+/** @file
+ *
+ * Non-Volatile Storage using Vital Product Data
+ *
+ */
+
+/**
+ * Read from VPD field
+ *
+ * @v nvs NVS device
+ * @v field VPD field descriptor
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int nvs_vpd_read ( struct nvs_device *nvs, unsigned int field,
+ void *data, size_t len ) {
+ struct nvs_vpd_device *nvsvpd =
+ container_of ( nvs, struct nvs_vpd_device, nvs );
+ struct pci_device *pci = nvsvpd->vpd.pci;
+ unsigned int address;
+ size_t max_len;
+ int rc;
+
+ /* Allow reading non-existent field */
+ if ( len == 0 )
+ return 0;
+
+ /* Locate VPD field */
+ if ( ( rc = pci_vpd_find ( &nvsvpd->vpd, field, &address,
+ &max_len ) ) != 0 ) {
+ DBGC ( pci, PCI_FMT " NVS VPD could not locate field "
+ PCI_VPD_FIELD_FMT ": %s\n", PCI_ARGS ( pci ),
+ PCI_VPD_FIELD_ARGS ( field ), strerror ( rc ) );
+ return rc;
+ }
+
+ /* Sanity check */
+ if ( len > max_len ) {
+ DBGC ( pci, PCI_FMT " NVS VPD cannot read %#02zx bytes "
+ "beyond field " PCI_VPD_FIELD_FMT " at [%04x,%04zx)\n",
+ PCI_ARGS ( pci ), len, PCI_VPD_FIELD_ARGS ( field ),
+ address, ( address + max_len ) );
+ return -ENXIO;
+ }
+
+ /* Read from VPD field */
+ if ( ( rc = pci_vpd_read ( &nvsvpd->vpd, address, data, len ) ) != 0 ) {
+ DBGC ( pci, PCI_FMT " NVS VPD could not read field "
+ PCI_VPD_FIELD_FMT " at [%04x,%04zx): %s\n",
+ PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ),
+ address, ( address + len ), strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Write to VPD field
+ *
+ * @v nvs NVS device
+ * @v field VPD field descriptor
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int nvs_vpd_write ( struct nvs_device *nvs, unsigned int field,
+ const void *data, size_t len ) {
+ struct nvs_vpd_device *nvsvpd =
+ container_of ( nvs, struct nvs_vpd_device, nvs );
+ struct pci_device *pci = nvsvpd->vpd.pci;
+ unsigned int address;
+ size_t max_len;
+ int rc;
+
+ /* Locate VPD field */
+ if ( ( rc = pci_vpd_find ( &nvsvpd->vpd, field, &address,
+ &max_len ) ) != 0 ) {
+ DBGC ( pci, PCI_FMT " NVS VPD could not locate field "
+ PCI_VPD_FIELD_FMT ": %s\n", PCI_ARGS ( pci ),
+ PCI_VPD_FIELD_ARGS ( field ), strerror ( rc ) );
+ return rc;
+ }
+
+ /* Sanity check */
+ if ( len > max_len ) {
+ DBGC ( pci, PCI_FMT " NVS VPD cannot write %#02zx bytes "
+ "beyond field " PCI_VPD_FIELD_FMT " at [%04x,%04zx)\n",
+ PCI_ARGS ( pci ), len, PCI_VPD_FIELD_ARGS ( field ),
+ address, ( address + max_len ) );
+ return -ENXIO;
+ }
+
+ /* Write field */
+ if ( ( rc = pci_vpd_write ( &nvsvpd->vpd, address, data,
+ len ) ) != 0 ) {
+ DBGC ( pci, PCI_FMT " NVS VPD could not write field "
+ PCI_VPD_FIELD_FMT " at [%04x,%04zx): %s\n",
+ PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ),
+ address, ( address + len ), strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Resize VPD field
+ *
+ * @v nvs NVS device
+ * @v field VPD field descriptor
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int nvs_vpd_resize ( struct nvs_device *nvs, unsigned int field,
+ size_t len ) {
+ struct nvs_vpd_device *nvsvpd =
+ container_of ( nvs, struct nvs_vpd_device, nvs );
+ struct pci_device *pci = nvsvpd->vpd.pci;
+ unsigned int address;
+ int rc;
+
+ /* Resize field */
+ if ( ( rc = pci_vpd_resize ( &nvsvpd->vpd, field, len,
+ &address ) ) != 0 ) {
+ DBGC ( pci, PCI_FMT " NVS VPD could not resize field "
+ PCI_VPD_FIELD_FMT " to %#02zx bytes: %s\n",
+ PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ),
+ len, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Initialise NVS VPD device
+ *
+ * @v nvsvpd NVS VPD device
+ * @v pci PCI device
+ * @ret rc Return status code
+ */
+int nvs_vpd_init ( struct nvs_vpd_device *nvsvpd, struct pci_device *pci ) {
+ int rc;
+
+ /* Initialise VPD device */
+ if ( ( rc = pci_vpd_init ( &nvsvpd->vpd, pci ) ) != 0 ) {
+ DBGC ( pci, PCI_FMT " NVS could not initialise "
+ "VPD: %s\n", PCI_ARGS ( pci ), strerror ( rc ) );
+ return rc;
+ }
+
+ /* Initialise NVS device */
+ nvsvpd->nvs.read = nvs_vpd_read;
+ nvsvpd->nvs.write = nvs_vpd_write;
+
+ return 0;
+}
+
+/**
+ * Resize non-volatile option storage within NVS VPD device
+ *
+ * @v nvo Non-volatile options block
+ * @v len New length
+ * @ret rc Return status code
+ */
+static int nvs_vpd_nvo_resize ( struct nvo_block *nvo, size_t len ) {
+ int rc;
+
+ /* Resize VPD field */
+ if ( ( rc = nvs_vpd_resize ( nvo->nvs, nvo->address, len ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Initialise non-volatile option storage within NVS VPD device
+ *
+ * @v nvsvpd NVS VPD device
+ * @v field VPD field descriptor
+ * @v nvo Non-volatile options block
+ * @v refcnt Containing object reference counter, or NULL
+ */
+void nvs_vpd_nvo_init ( struct nvs_vpd_device *nvsvpd, unsigned int field,
+ struct nvo_block *nvo, struct refcnt *refcnt ) {
+ struct pci_device *pci = nvsvpd->vpd.pci;
+ unsigned int address;
+ size_t len;
+ int rc;
+
+ /* Locate VPD field, if present */
+ if ( ( rc = pci_vpd_find ( &nvsvpd->vpd, field, &address,
+ &len ) ) != 0 ) {
+ DBGC ( pci, PCI_FMT " NVS VPD field " PCI_VPD_FIELD_FMT
+ " not present; assuming empty\n",
+ PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ) );
+ len = 0;
+ }
+
+ /* Initialise non-volatile options block */
+ nvo_init ( nvo, &nvsvpd->nvs, field, len, nvs_vpd_nvo_resize, refcnt );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/nvs/spi.c b/src/VBox/Devices/PC/ipxe/src/drivers/nvs/spi.c
new file mode 100644
index 00000000..e12aeff6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/nvs/spi.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ipxe/spi.h>
+
+/** @file
+ *
+ * SPI devices
+ *
+ */
+
+/**
+ * Munge SPI device address into command
+ *
+ * @v command SPI command
+ * @v address Address
+ * @v munge_address Device requires address munging
+ * @ret command Actual SPI command to use
+ *
+ * Some devices with 9-bit addresses (e.g. AT25040A EEPROM) use bit 3
+ * of the command byte as address bit A8, rather than having a
+ * two-byte address. This function takes care of generating the
+ * appropriate command.
+ */
+static inline unsigned int spi_command ( unsigned int command,
+ unsigned int address,
+ int munge_address ) {
+ return ( command | ( ( ( address >> 8 ) & munge_address ) << 3 ) );
+}
+
+/**
+ * Wait for SPI device to complete operation
+ *
+ * @v device SPI device
+ * @ret rc Return status code
+ */
+static int spi_wait ( struct spi_device *device ) {
+ struct spi_bus *bus = device->bus;
+ uint8_t status;
+ int i;
+ int rc;
+
+ for ( i = 0 ; i < 50 ; i++ ) {
+ udelay ( 20 );
+ if ( ( rc = bus->rw ( bus, device, SPI_RDSR, -1, NULL,
+ &status, sizeof ( status ) ) ) != 0 )
+ return rc;
+ if ( ! ( status & SPI_STATUS_NRDY ) )
+ return 0;
+ }
+ DBG ( "SPI %p timed out\n", device );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Read data from SPI device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int spi_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len ) {
+ struct spi_device *device = nvs_to_spi ( nvs );
+ struct spi_bus *bus = device->bus;
+ unsigned int command = spi_command ( SPI_READ, address,
+ device->munge_address );
+ int rc;
+
+ DBG ( "SPI %p reading %zd bytes from %#04x\n", device, len, address );
+ if ( ( rc = bus->rw ( bus, device, command, address,
+ NULL, data, len ) ) != 0 ) {
+ DBG ( "SPI %p failed to read data from device\n", device );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Write data to SPI device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int spi_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len ) {
+ struct spi_device *device = nvs_to_spi ( nvs );
+ struct spi_bus *bus = device->bus;
+ unsigned int command = spi_command ( SPI_WRITE, address,
+ device->munge_address );
+ int rc;
+
+ DBG ( "SPI %p writing %zd bytes to %#04x\n", device, len, address );
+
+ if ( ( rc = bus->rw ( bus, device, SPI_WREN, -1,
+ NULL, NULL, 0 ) ) != 0 ) {
+ DBG ( "SPI %p failed to write-enable device\n", device );
+ return rc;
+ }
+
+ if ( ( rc = bus->rw ( bus, device, command, address,
+ data, NULL, len ) ) != 0 ) {
+ DBG ( "SPI %p failed to write data to device\n", device );
+ return rc;
+ }
+
+ if ( ( rc = spi_wait ( device ) ) != 0 ) {
+ DBG ( "SPI %p failed to complete write operation\n", device );
+ return rc;
+ }
+
+ return 0;
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/drivers/nvs/threewire.c b/src/VBox/Devices/PC/ipxe/src/drivers/nvs/threewire.c
new file mode 100644
index 00000000..047091fd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/drivers/nvs/threewire.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <ipxe/threewire.h>
+
+/** @file
+ *
+ * Three-wire serial devices
+ *
+ */
+
+/**
+ * Read data from three-wire device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int threewire_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len ) {
+ struct spi_device *device = nvs_to_spi ( nvs );
+ struct spi_bus *bus = device->bus;
+ int rc;
+
+ assert ( bus->mode == SPI_MODE_THREEWIRE );
+
+ DBGC ( device, "3wire %p reading %zd bytes at %04x\n",
+ device, len, address );
+
+ if ( ( rc = bus->rw ( bus, device, THREEWIRE_READ, address,
+ NULL, data, len ) ) != 0 ) {
+ DBGC ( device, "3wire %p could not read: %s\n",
+ device, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Write data to three-wire device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int threewire_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len ) {
+ struct spi_device *device = nvs_to_spi ( nvs );
+ struct spi_bus *bus = device->bus;
+ int rc;
+
+ assert ( bus->mode == SPI_MODE_THREEWIRE );
+
+ DBGC ( device, "3wire %p writing %zd bytes at %04x\n",
+ device, len, address );
+
+ /* Enable device for writing */
+ if ( ( rc = bus->rw ( bus, device, THREEWIRE_EWEN,
+ THREEWIRE_EWEN_ADDRESS, NULL, NULL, 0 ) ) != 0 ){
+ DBGC ( device, "3wire %p could not enable writing: %s\n",
+ device, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Write data */
+ if ( ( rc = bus->rw ( bus, device, THREEWIRE_WRITE, address,
+ data, NULL, len ) ) != 0 ) {
+ DBGC ( device, "3wire %p could not write: %s\n",
+ device, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Our model of an SPI bus doesn't provide a mechanism for
+ * "assert CS, wait for MISO to become high, so just wait for
+ * long enough to ensure that the write has completed.
+ */
+ mdelay ( THREEWIRE_WRITE_MDELAY );
+
+ return 0;
+}
+
+/**
+ * Autodetect device address length
+ *
+ * @v device SPI device
+ * @ret rc Return status code
+ */
+int threewire_detect_address_len ( struct spi_device *device ) {
+ struct nvs_device *nvs = &device->nvs;
+ int rc;
+
+ DBGC ( device, "3wire %p autodetecting address length\n", device );
+
+ device->address_len = SPI_AUTODETECT_ADDRESS_LEN;
+ if ( ( rc = threewire_read ( nvs, 0, NULL,
+ ( 1 << nvs->word_len_log2 ) ) ) != 0 ) {
+ DBGC ( device, "3wire %p could not autodetect address "
+ "length: %s\n", device, strerror ( rc ) );
+ return rc;
+ }
+
+ DBGC ( device, "3wire %p autodetected address length %d\n",
+ device, device->address_len );
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/autoboot_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/autoboot_cmd.c
new file mode 100644
index 00000000..0917f6fa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/autoboot_cmd.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <getopt.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/netdevice.h>
+#include <hci/ifmgmt_cmd.h>
+#include <usr/autoboot.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Booting commands
+ *
+ */
+
+/** "autoboot" command descriptor */
+static struct command_descriptor autoboot_cmd =
+ COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
+ "[<interface>...]" );
+
+/**
+ * "autoboot" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int autoboot_exec ( int argc, char **argv ) {
+ return ifcommon_exec ( argc, argv, &autoboot_cmd, netboot, 0 );
+}
+
+/** Booting commands */
+struct command autoboot_commands[] __command = {
+ {
+ .name = "autoboot",
+ .exec = autoboot_exec,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/config_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/config_cmd.c
new file mode 100644
index 00000000..e447d6af
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/config_cmd.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/settings.h>
+#include <ipxe/settings_ui.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Configuration UI commands
+ *
+ */
+
+/** "config" options */
+struct config_options {};
+
+/** "config" option list */
+static struct option_descriptor config_opts[] = {};
+
+/** "config" command descriptor */
+static struct command_descriptor config_cmd =
+ COMMAND_DESC ( struct config_options, config_opts, 0, 1, "[<scope>]" );
+
+/**
+ * Parse settings scope name
+ *
+ * @v text Text
+ * @ret value Integer value
+ * @ret rc Return status code
+ */
+static int parse_settings ( const char *text, struct settings **value ) {
+
+ /* Sanity check */
+ assert ( text != NULL );
+
+ /* Parse scope name */
+ *value = find_settings ( text );
+ if ( ! *value ) {
+ printf ( "\"%s\": no such scope\n", text );
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * "config" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int config_exec ( int argc, char **argv ) {
+ struct config_options opts;
+ struct settings *settings;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &config_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse settings option, if present */
+ if ( ( rc = parse_settings ( ( ( optind < argc ) ? argv[optind] : "" ),
+ &settings ) ) != 0 )
+ return rc;
+
+ /* Run settings UI */
+ if ( ( rc = settings_ui ( settings ) ) != 0 ) {
+ printf ( "Could not save settings: %s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/** Configuration UI commands */
+struct command config_command __command = {
+ .name = "config",
+ .exec = config_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/dhcp_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/dhcp_cmd.c
new file mode 100644
index 00000000..acf3cfda
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/dhcp_cmd.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include <getopt.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/in.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <usr/dhcpmgmt.h>
+#include <hci/ifmgmt_cmd.h>
+
+/** @file
+ *
+ * DHCP management commands
+ *
+ */
+
+/** "dhcp" command descriptor */
+static struct command_descriptor dhcp_cmd =
+ COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
+ "[<interface>...]" );
+
+/**
+ * Execute "dhcp" command for a network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int dhcp_payload ( struct net_device *netdev ) {
+ int rc;
+
+ if ( ( rc = dhcp ( netdev ) ) != 0 ) {
+ printf ( "Could not configure %s: %s\n",
+ netdev->name, strerror ( rc ) );
+
+ /* Close device on failure, to avoid memory exhaustion */
+ netdev_close ( netdev );
+
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * The "dhcp" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int dhcp_exec ( int argc, char **argv ) {
+ return ifcommon_exec ( argc, argv, &dhcp_cmd, dhcp_payload, 1 );
+}
+
+/** "pxebs" options */
+struct pxebs_options {};
+
+/** "pxebs" option list */
+static struct option_descriptor pxebs_opts[] = {};
+
+/** "pxebs" command descriptor */
+static struct command_descriptor pxebs_cmd =
+ COMMAND_DESC ( struct pxebs_options, pxebs_opts, 2, 2,
+ "<interface> <server type>" );
+
+/**
+ * The "pxebs" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int pxebs_exec ( int argc, char **argv ) {
+ struct pxebs_options opts;
+ struct net_device *netdev;
+ unsigned int pxe_type;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &pxebs_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse net device name */
+ if ( ( rc = parse_netdev ( argv[optind], &netdev ) ) != 0 )
+ return rc;
+
+ /* Parse boot server type */
+ if ( ( rc = parse_integer ( argv[ optind + 1 ], &pxe_type ) ) != 0 )
+ return rc;
+
+ /* Perform Boot Server Discovery */
+ if ( ( rc = pxebs ( netdev, pxe_type ) ) != 0 ) {
+ printf ( "Could not discover boot server on %s: %s\n",
+ netdev->name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/** DHCP management commands */
+struct command dhcp_commands[] __command = {
+ {
+ .name = "dhcp",
+ .exec = dhcp_exec,
+ },
+ {
+ .name = "pxebs",
+ .exec = pxebs_exec,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/digest_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/digest_cmd.c
new file mode 100644
index 00000000..fac49765
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/digest_cmd.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2009 Daniel Verkamp <daniel@drv.nu>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/image.h>
+#include <ipxe/crypto.h>
+#include <ipxe/md5.h>
+#include <ipxe/sha1.h>
+#include <usr/imgmgmt.h>
+
+/** @file
+ *
+ * Digest commands
+ *
+ */
+
+/** "digest" options */
+struct digest_options {};
+
+/** "digest" option list */
+static struct option_descriptor digest_opts[] = {};
+
+/** "digest" command descriptor */
+static struct command_descriptor digest_cmd =
+ COMMAND_DESC ( struct digest_options, digest_opts, 1, MAX_ARGUMENTS,
+ "<image> [<image>...]" );
+
+/**
+ * The "digest" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v digest Digest algorithm
+ * @ret rc Return status code
+ */
+static int digest_exec ( int argc, char **argv,
+ struct digest_algorithm *digest ) {
+ struct digest_options opts;
+ struct image *image;
+ uint8_t digest_ctx[digest->ctxsize];
+ uint8_t digest_out[digest->digestsize];
+ uint8_t buf[128];
+ size_t offset;
+ size_t len;
+ size_t frag_len;
+ int i;
+ unsigned j;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &digest_cmd, &opts ) ) != 0 )
+ return rc;
+
+ for ( i = optind ; i < argc ; i++ ) {
+
+ /* Acquire image */
+ if ( ( rc = imgacquire ( argv[i], &image ) ) != 0 )
+ continue;
+ offset = 0;
+ len = image->len;
+
+ /* calculate digest */
+ digest_init ( digest, digest_ctx );
+ while ( len ) {
+ frag_len = len;
+ if ( frag_len > sizeof ( buf ) )
+ frag_len = sizeof ( buf );
+ copy_from_user ( buf, image->data, offset, frag_len );
+ digest_update ( digest, digest_ctx, buf, frag_len );
+ len -= frag_len;
+ offset += frag_len;
+ }
+ digest_final ( digest, digest_ctx, digest_out );
+
+ for ( j = 0 ; j < sizeof ( digest_out ) ; j++ )
+ printf ( "%02x", digest_out[j] );
+
+ printf ( " %s\n", image->name );
+ }
+
+ return 0;
+}
+
+static int md5sum_exec ( int argc, char **argv ) {
+ return digest_exec ( argc, argv, &md5_algorithm );
+}
+
+static int sha1sum_exec ( int argc, char **argv ) {
+ return digest_exec ( argc, argv, &sha1_algorithm );
+}
+
+struct command md5sum_command __command = {
+ .name = "md5sum",
+ .exec = md5sum_exec,
+};
+
+struct command sha1sum_command __command = {
+ .name = "sha1sum",
+ .exec = sha1sum_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/fcmgmt_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/fcmgmt_cmd.c
new file mode 100644
index 00000000..a2b818ec
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/fcmgmt_cmd.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h>
+#include <strings.h>
+#include <ipxe/fc.h>
+#include <ipxe/fcels.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/tables.h>
+#include <usr/fcmgmt.h>
+
+/** @file
+ *
+ * Fibre Channel management commands
+ *
+ */
+
+/**
+ * Parse Fibre Channel port name
+ *
+ * @v text Text
+ * @ret port Fibre Channel port
+ * @ret rc Return status code
+ */
+static int parse_fc_port ( const char *text, struct fc_port **port ) {
+
+ /* Sanity check */
+ assert ( text != NULL );
+
+ /* Find Fibre Channel port */
+ *port = fc_port_find ( text );
+ if ( ! *port ) {
+ printf ( "\"%s\": no such port\n", text );
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse Fibre Channel port ID
+ *
+ * @v text Text
+ * @ret port_id Fibre Channel port ID
+ * @ret rc Return status code
+ */
+static int parse_fc_port_id ( const char *text, struct fc_port_id *port_id ) {
+ int rc;
+
+ /* Sanity check */
+ assert ( text != NULL );
+
+ /* Parse port ID */
+ if ( ( rc = fc_id_aton ( text, port_id ) ) != 0 ) {
+ printf ( "\"%s\": invalid port ID\n", text );
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse Fibre Channel ELS handler name
+ *
+ * @v text Text
+ * @ret handler Fibre Channel ELS handler
+ * @ret rc Return status code
+ */
+static int parse_fc_els_handler ( const char *text,
+ struct fc_els_handler **handler ) {
+
+ for_each_table_entry ( (*handler), FC_ELS_HANDLERS ) {
+ if ( strcasecmp ( (*handler)->name, text ) == 0 )
+ return 0;
+ }
+
+ printf ( "\"%s\": unrecognised ELS\n", text );
+ return -ENOENT;
+}
+
+/** "fcstat" options */
+struct fcstat_options {};
+
+/** "fcstat" option list */
+static struct option_descriptor fcstat_opts[] = {};
+
+/** "fcstat" command descriptor */
+static struct command_descriptor fcstat_cmd =
+ COMMAND_DESC ( struct fcstat_options, fcstat_opts, 0, 0, "" );
+
+/**
+ * The "fcstat" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int fcstat_exec ( int argc, char **argv ) {
+ struct fcstat_options opts;
+ struct fc_port *port;
+ struct fc_peer *peer;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &fcstat_cmd, &opts ) ) != 0 )
+ return rc;
+
+ list_for_each_entry ( port, &fc_ports, list )
+ fcportstat ( port );
+ list_for_each_entry ( peer, &fc_peers, list )
+ fcpeerstat ( peer );
+
+ return 0;
+}
+
+/** "fcels" options */
+struct fcels_options {
+ /** Fibre Channel port */
+ struct fc_port *port;
+ /** Fibre Channel peer port ID */
+ struct fc_port_id peer_port_id;
+};
+
+/** "fcels" option list */
+static struct option_descriptor fcels_opts[] = {
+ OPTION_DESC ( "port", 'p', required_argument,
+ struct fcels_options, port, parse_fc_port ),
+ OPTION_DESC ( "id", 'i', required_argument,
+ struct fcels_options, peer_port_id, parse_fc_port_id ),
+};
+
+/** "fcels" command descriptor */
+static struct command_descriptor fcels_cmd =
+ COMMAND_DESC ( struct fcels_options, fcels_opts, 1, 1,
+ "[--port <port>] [--id <peer port id>] <request>" );
+
+/**
+ * The "fcels" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int fcels_exec ( int argc, char **argv ) {
+ struct fcels_options opts;
+ struct fc_els_handler *handler;
+ struct fc_port_id *id;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &fcels_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse ELS handler */
+ if ( ( rc = parse_fc_els_handler ( argv[optind], &handler ) ) != 0 )
+ return rc;
+
+ /* Use first port if no port specified */
+ if ( ! opts.port ) {
+ opts.port = list_first_entry ( &fc_ports, struct fc_port,
+ list );
+ if ( ! opts.port ) {
+ printf ( "No ports\n" );
+ return -ENODEV;
+ }
+ }
+
+ /* Use link peer port ID if no peer port ID specified */
+ id = &opts.peer_port_id;
+ if ( memcmp ( id, &fc_empty_port_id, sizeof ( *id ) ) == 0 ) {
+ if ( fc_link_ok ( &opts.port->link ) &&
+ ! ( opts.port->flags & FC_PORT_HAS_FABRIC ) ) {
+ id = &opts.port->ptp_link_port_id;
+ } else {
+ id = &fc_f_port_id;
+ }
+ }
+
+ /** Issue ELS */
+ if ( ( rc = fcels ( opts.port, id, handler ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/** Fibre Channel management commands */
+struct command fcmgmt_commands[] __command = {
+ {
+ .name = "fcstat",
+ .exec = fcstat_exec,
+ },
+ {
+ .name = "fcels",
+ .exec = fcels_exec,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/gdbstub_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/gdbstub_cmd.c
new file mode 100644
index 00000000..f35f0140
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/gdbstub_cmd.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2008 Stefan Hajnoczi <stefanha@gmail.com>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+#include <getopt.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/gdbstub.h>
+
+/** @file
+ *
+ * GDB stub command
+ *
+ */
+
+/**
+ * Parse GDB transport name
+ *
+ * @v text Text
+ * @ret trans GDB transport
+ * @ret rc Return status code
+ */
+static int parse_gdb_transport ( const char *text,
+ struct gdb_transport **trans ) {
+
+ /* Sanity check */
+ assert ( text != NULL );
+
+ /* Find transport */
+ *trans = find_gdb_transport ( text );
+ if ( ! *trans ) {
+ printf ( "\"%s\": no such transport (is it compiled in?)\n",
+ text );
+ return -ENOTSUP;
+ }
+
+ return 0;
+}
+
+/** "gdbstub" options */
+struct gdbstub_options {};
+
+/** "gdbstub" option list */
+static struct option_descriptor gdbstub_opts[] = {};
+
+/** "gdbstub" command descriptor */
+static struct command_descriptor gdbstub_cmd =
+ COMMAND_DESC ( struct gdbstub_options, gdbstub_opts, 1, MAX_ARGUMENTS,
+ "<transport> [<options>...]" );
+
+/**
+ * The "gdbstub" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int gdbstub_exec ( int argc, char **argv ) {
+ struct gdbstub_options opts;
+ struct gdb_transport *trans;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &gdbstub_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse transport name */
+ if ( ( rc = parse_gdb_transport ( argv[optind++], &trans ) ) != 0 )
+ return rc;
+
+ /* Initialise transport */
+ if ( trans->init ) {
+ if ( ( rc = trans->init ( argc - optind,
+ &argv[optind] ) ) != 0 ) {
+ return rc;
+ }
+ }
+
+ /* Enter GDB stub */
+ gdbstub_start ( trans );
+
+ return 0;
+}
+
+/** GDB stub commands */
+struct command gdbstub_commands[] __command = {
+ {
+ .name = "gdbstub",
+ .exec = gdbstub_exec,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/ifmgmt_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/ifmgmt_cmd.c
new file mode 100644
index 00000000..29691d4e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/ifmgmt_cmd.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <usr/ifmgmt.h>
+#include <hci/ifmgmt_cmd.h>
+
+/** @file
+ *
+ * Network interface management commands
+ *
+ */
+
+/** "if<xxx>" command options */
+struct option_descriptor ifcommon_opts[0];
+
+/**
+ * Execute if<xxx> command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v cmd Command descriptor
+ * @v payload Command to execute
+ * @v verb Verb describing the action of the command
+ * @ret rc Return status code
+ */
+int ifcommon_exec ( int argc, char **argv,
+ struct command_descriptor *cmd,
+ int ( * payload ) ( struct net_device * ),
+ int stop_on_first_success ) {
+ struct ifcommon_options opts;
+ struct net_device *netdev;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, cmd, &opts ) ) != 0 )
+ return rc;
+
+ if ( optind != argc ) {
+ /* Treat arguments as a list of interfaces to try */
+ while ( optind != argc ) {
+ if ( ( rc = parse_netdev ( argv[optind++],
+ &netdev ) ) != 0 ) {
+ continue;
+ }
+ if ( ( ( rc = payload ( netdev ) ) == 0 ) &&
+ stop_on_first_success ) {
+ return 0;
+ }
+ }
+ } else {
+ /* Try all interfaces */
+ rc = -ENODEV;
+ for_each_netdev ( netdev ) {
+ if ( ( ( rc = payload ( netdev ) ) == 0 ) &&
+ stop_on_first_success ) {
+ return 0;
+ }
+ }
+ }
+
+ return rc;
+}
+
+/** "ifopen" command descriptor */
+static struct command_descriptor ifopen_cmd =
+ COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
+ "[<interface>...]" );
+
+/**
+ * "ifopen" payload
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int ifopen_payload ( struct net_device *netdev ) {
+ return ifopen ( netdev );
+}
+
+/**
+ * The "ifopen" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int ifopen_exec ( int argc, char **argv ) {
+ return ifcommon_exec ( argc, argv, &ifopen_cmd, ifopen_payload, 0 );
+}
+
+/** "ifclose" command descriptor */
+static struct command_descriptor ifclose_cmd =
+ COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
+ "[<interface>...]" );
+
+/**
+ * "ifclose" payload
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int ifclose_payload ( struct net_device *netdev ) {
+ ifclose ( netdev );
+ return 0;
+}
+
+/**
+ * The "ifclose" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int ifclose_exec ( int argc, char **argv ) {
+ return ifcommon_exec ( argc, argv, &ifclose_cmd, ifclose_payload, 0 );
+}
+
+/** "ifstat" command descriptor */
+static struct command_descriptor ifstat_cmd =
+ COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
+ "[<interface>...]" );
+
+/**
+ * "ifstat" payload
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int ifstat_payload ( struct net_device *netdev ) {
+ ifstat ( netdev );
+ return 0;
+}
+
+/**
+ * The "ifstat" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int ifstat_exec ( int argc, char **argv ) {
+ return ifcommon_exec ( argc, argv, &ifstat_cmd, ifstat_payload, 0 );
+}
+
+/** Interface management commands */
+struct command ifmgmt_commands[] __command = {
+ {
+ .name = "ifopen",
+ .exec = ifopen_exec,
+ },
+ {
+ .name = "ifclose",
+ .exec = ifclose_exec,
+ },
+ {
+ .name = "ifstat",
+ .exec = ifstat_exec,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/image_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/image_cmd.c
new file mode 100644
index 00000000..1ae33074
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/image_cmd.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ipxe/image.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <usr/imgmgmt.h>
+
+/** @file
+ *
+ * Image management commands
+ *
+ */
+
+/** "img{single}" options */
+struct imgsingle_options {
+ /** Image name */
+ const char *name;
+};
+
+/** "img{single}" option list */
+static struct option_descriptor imgsingle_opts[] = {
+ OPTION_DESC ( "name", 'n', required_argument,
+ struct imgsingle_options, name, parse_string ),
+};
+
+/** "img{single}" command descriptor */
+static struct command_descriptor imgsingle_cmd =
+ COMMAND_DESC ( struct imgsingle_options, imgsingle_opts,
+ 1, MAX_ARGUMENTS,
+ "[--name <name>] <uri|image> [<arguments>...]" );
+
+/** An "img{single}" family command descriptor */
+struct imgsingle_descriptor {
+ /** Command descriptor */
+ struct command_descriptor *cmd;
+ /** Function to use to acquire the image */
+ int ( * acquire ) ( const char *name, struct image **image );
+ /** Pre-action to take upon image, or NULL */
+ void ( * preaction ) ( struct image *image );
+ /** Action to take upon image, or NULL */
+ int ( * action ) ( struct image *image );
+ /** Verb to describe action */
+ const char *verb;
+};
+
+/**
+ * The "img{single}" family of commands
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v desc "img{single}" command descriptor
+ * @v action_name Action name (for error messages)
+ * @v action Action to take upon image
+ * @ret rc Return status code
+ */
+static int imgsingle_exec ( int argc, char **argv,
+ struct imgsingle_descriptor *desc ) {
+ struct imgsingle_options opts;
+ char *name_uri = NULL;
+ char *cmdline = NULL;
+ struct image *image;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, desc->cmd, &opts ) ) != 0 )
+ goto err_parse_options;
+
+ /* Parse name/URI string and command line, if present */
+ if ( optind < argc ) {
+ name_uri = argv[optind];
+ if ( argv[ optind + 1 ] != NULL ) {
+ cmdline = concat_args ( &argv[ optind + 1 ] );
+ if ( ! cmdline ) {
+ rc = -ENOMEM;
+ goto err_parse_cmdline;
+ }
+ }
+ }
+
+ /* Acquire the image */
+ if ( name_uri ) {
+ if ( ( rc = desc->acquire ( name_uri, &image ) ) != 0 )
+ goto err_acquire;
+ } else {
+ image = image_find_selected();
+ if ( ! image ) {
+ printf ( "No image selected\n" );
+ goto err_acquire;
+ }
+ }
+
+ /* Carry out command pre-action, if applicable */
+ if ( desc->preaction )
+ desc->preaction ( image );
+
+ /* Set the image name, if applicable */
+ if ( opts.name ) {
+ if ( ( rc = image_set_name ( image, opts.name ) ) != 0 ) {
+ printf ( "Could not name image: %s\n",
+ strerror ( rc ) );
+ goto err_set_name;
+ }
+ }
+
+ /* Set the command-line arguments, if applicable */
+ if ( cmdline ) {
+ if ( ( rc = image_set_cmdline ( image, cmdline ) ) != 0 ) {
+ printf ( "Could not set arguments: %s\n",
+ strerror ( rc ) );
+ goto err_set_cmdline;
+ }
+ }
+
+ /* Carry out command action, if applicable */
+ if ( desc->action ) {
+ if ( ( rc = desc->action ( image ) ) != 0 ) {
+ printf ( "Could not %s: %s\n",
+ desc->verb, strerror ( rc ) );
+ goto err_action;
+ }
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_action:
+ err_set_cmdline:
+ err_set_name:
+ err_acquire:
+ free ( cmdline );
+ err_parse_cmdline:
+ err_parse_options:
+ return rc;
+}
+
+/** "imgfetch" command descriptor */
+static struct command_descriptor imgfetch_cmd =
+ COMMAND_DESC ( struct imgsingle_options, imgsingle_opts,
+ 1, MAX_ARGUMENTS,
+ "[--name <name>] <uri> [<arguments>...]" );
+
+/** "imgfetch" family command descriptor */
+struct imgsingle_descriptor imgfetch_desc = {
+ .cmd = &imgfetch_cmd,
+ .acquire = imgdownload_string,
+};
+
+/**
+ * The "imgfetch" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int imgfetch_exec ( int argc, char **argv ) {
+ return imgsingle_exec ( argc, argv, &imgfetch_desc );
+}
+
+/** "imgselect" family command descriptor */
+struct imgsingle_descriptor imgselect_desc = {
+ .cmd = &imgsingle_cmd,
+ .acquire = imgacquire,
+ .action = image_select,
+ .verb = "select",
+};
+
+/**
+ * The "imgselect" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int imgselect_exec ( int argc, char **argv ) {
+ return imgsingle_exec ( argc, argv, &imgselect_desc );
+}
+
+/** "imgexec" command descriptor */
+static struct command_descriptor imgexec_cmd =
+ COMMAND_DESC ( struct imgsingle_options, imgsingle_opts,
+ 0, MAX_ARGUMENTS,
+ "[--name <name>] [<uri|image> [<arguments>...]]" );
+
+/** "imgexec" family command descriptor */
+struct imgsingle_descriptor imgexec_desc = {
+ .cmd = &imgexec_cmd,
+ .acquire = imgacquire,
+ .action = image_exec,
+ .verb = "boot",
+};
+
+/**
+ * The "imgexec" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int imgexec_exec ( int argc, char **argv) {
+ return imgsingle_exec ( argc, argv, &imgexec_desc );
+}
+
+/** "imgargs" family command descriptor */
+struct imgsingle_descriptor imgargs_desc = {
+ .cmd = &imgsingle_cmd,
+ .acquire = imgacquire,
+ .preaction = image_clear_cmdline,
+};
+
+/**
+ * The "imgargs" command body
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int imgargs_exec ( int argc, char **argv ) {
+ return imgsingle_exec ( argc, argv, &imgargs_desc );
+}
+
+/** "img{multi}" options */
+struct imgmulti_options {};
+
+/** "img{multi}" option list */
+static struct option_descriptor imgmulti_opts[] = {};
+
+/** "img{multi}" command descriptor */
+static struct command_descriptor imgmulti_cmd =
+ COMMAND_DESC ( struct imgmulti_options, imgmulti_opts, 0, MAX_ARGUMENTS,
+ "[<image>...]" );
+
+/**
+ * The "img{multi}" family of commands
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v payload Function to execute on each image
+ * @ret rc Return status code
+ */
+static int imgmulti_exec ( int argc, char **argv,
+ void ( * payload ) ( struct image *image ) ) {
+ struct imgmulti_options opts;
+ struct image *image;
+ struct image *tmp;
+ int i;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &imgmulti_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* If no images are explicitly specified, process all images */
+ if ( optind == argc ) {
+ for_each_image_safe ( image, tmp )
+ payload ( image );
+ return 0;
+ }
+
+ /* Otherwise, process specified images */
+ for ( i = optind ; i < argc ; i++ ) {
+ image = find_image ( argv[i] );
+ if ( ! image ) {
+ printf ( "\"%s\": no such image\n", argv[i] );
+ return -ENOENT;
+ }
+ payload ( image );
+ }
+
+ return 0;
+}
+
+/**
+ * The "imgstat" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int imgstat_exec ( int argc, char **argv ) {
+ return imgmulti_exec ( argc, argv, imgstat );
+}
+
+/**
+ * The "imgfree" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int imgfree_exec ( int argc, char **argv ) {
+ return imgmulti_exec ( argc, argv, unregister_image );
+}
+
+/** Image management commands */
+struct command image_commands[] __command = {
+ {
+ .name = "imgfetch",
+ .exec = imgfetch_exec,
+ },
+ {
+ .name = "module",
+ .exec = imgfetch_exec, /* synonym for "imgfetch" */
+ },
+ {
+ .name = "initrd",
+ .exec = imgfetch_exec, /* synonym for "imgfetch" */
+ },
+ {
+ .name = "kernel",
+ .exec = imgselect_exec, /* synonym for "imgselect" */
+ },
+ {
+ .name = "chain",
+ .exec = imgexec_exec, /* synonym for "imgexec" */
+ },
+ {
+ .name = "imgselect",
+ .exec = imgselect_exec,
+ },
+ {
+ .name = "imgload",
+ .exec = imgselect_exec, /* synonym for "imgselect" */
+ },
+ {
+ .name = "imgargs",
+ .exec = imgargs_exec,
+ },
+ {
+ .name = "imgexec",
+ .exec = imgexec_exec,
+ },
+ {
+ .name = "boot", /* synonym for "imgexec" */
+ .exec = imgexec_exec,
+ },
+ {
+ .name = "imgstat",
+ .exec = imgstat_exec,
+ },
+ {
+ .name = "imgfree",
+ .exec = imgfree_exec,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/image_trust_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/image_trust_cmd.c
new file mode 100644
index 00000000..25e77dde
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/image_trust_cmd.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <ipxe/image.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <usr/imgmgmt.h>
+#include <usr/imgtrust.h>
+
+/** @file
+ *
+ * Image trust management commands
+ *
+ */
+
+/** "imgtrust" options */
+struct imgtrust_options {
+ /** Allow trusted images */
+ int allow;
+ /** Make trust requirement permanent */
+ int permanent;
+};
+
+/** "imgtrust" option list */
+static struct option_descriptor imgtrust_opts[] = {
+ OPTION_DESC ( "allow", 'a', no_argument,
+ struct imgtrust_options, allow, parse_flag ),
+ OPTION_DESC ( "permanent", 'p', no_argument,
+ struct imgtrust_options, permanent, parse_flag ),
+};
+
+/** "imgtrust" command descriptor */
+static struct command_descriptor imgtrust_cmd =
+ COMMAND_DESC ( struct imgtrust_options, imgtrust_opts, 0, 0,
+ "[--allow] [--permanent]" );
+
+/**
+ * The "imgtrust" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int imgtrust_exec ( int argc, char **argv ) {
+ struct imgtrust_options opts;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &imgtrust_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Set trust requirement */
+ if ( ( rc = image_set_trust ( ( ! opts.allow ),
+ opts.permanent ) ) != 0 ) {
+ printf ( "Could not set image trust requirement: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/** "imgverify" options */
+struct imgverify_options {
+ /** Required signer common name */
+ const char *signer;
+ /** Keep signature after verification */
+ int keep;
+};
+
+/** "imgverify" option list */
+static struct option_descriptor imgverify_opts[] = {
+ OPTION_DESC ( "signer", 's', required_argument,
+ struct imgverify_options, signer, parse_string ),
+ OPTION_DESC ( "keep", 'k', no_argument,
+ struct imgverify_options, keep, parse_flag ),
+};
+
+/** "imgverify" command descriptor */
+static struct command_descriptor imgverify_cmd =
+ COMMAND_DESC ( struct imgverify_options, imgverify_opts, 2, 2,
+ "[--signer <signer>] [--keep] <uri|image> "
+ "<signature uri|image>" );
+
+/**
+ * The "imgverify" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int imgverify_exec ( int argc, char **argv ) {
+ struct imgverify_options opts;
+ const char *image_name_uri;
+ const char *signature_name_uri;
+ struct image *image;
+ struct image *signature;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &imgverify_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse image name/URI string */
+ image_name_uri = argv[optind];
+
+ /* Parse signature name/URI string */
+ signature_name_uri = argv[ optind + 1 ];
+
+ /* Acquire the image */
+ if ( ( rc = imgacquire ( image_name_uri, &image ) ) != 0 )
+ goto err_acquire_image;
+
+ /* Acquire the signature image */
+ if ( ( rc = imgacquire ( signature_name_uri, &signature ) ) != 0 )
+ goto err_acquire_signature;
+
+ /* Verify image */
+ if ( ( rc = imgverify ( image, signature, opts.signer ) ) != 0 ) {
+ printf ( "Could not verify: %s\n", strerror ( rc ) );
+ goto err_verify;
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_verify:
+ /* Discard signature unless --keep was specified */
+ if ( ! opts.keep )
+ unregister_image ( signature );
+ err_acquire_signature:
+ err_acquire_image:
+ return rc;
+}
+
+/** Image trust management commands */
+struct command image_trust_commands[] __command = {
+ {
+ .name = "imgtrust",
+ .exec = imgtrust_exec,
+ },
+ {
+ .name = "imgverify",
+ .exec = imgverify_exec,
+ },
+};
+
+/* Drag in objects typically required for signature verification */
+REQUIRE_OBJECT ( rsa );
+REQUIRE_OBJECT ( md5 );
+REQUIRE_OBJECT ( sha1 );
+REQUIRE_OBJECT ( sha256 );
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/iwmgmt_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/iwmgmt_cmd.c
new file mode 100644
index 00000000..00a8360d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/iwmgmt_cmd.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/netdevice.h>
+#include <ipxe/net80211.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <usr/iwmgmt.h>
+#include <hci/ifmgmt_cmd.h>
+
+/** @file
+ *
+ * Wireless interface management commands
+ *
+ */
+
+/** "iwstat" command descriptor */
+static struct command_descriptor iwstat_cmd =
+ COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
+ "[<interface>...]" );
+
+/**
+ * "iwstat" payload
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int iwstat_payload ( struct net_device *netdev ) {
+ struct net80211_device *dev = net80211_get ( netdev );
+
+ if ( dev )
+ iwstat ( dev );
+
+ return 0;
+}
+
+/**
+ * The "iwstat" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int iwstat_exec ( int argc, char **argv ) {
+ return ifcommon_exec ( argc, argv, &iwstat_cmd, iwstat_payload, 0 );
+}
+
+/** "iwlist" command descriptor */
+static struct command_descriptor iwlist_cmd =
+ COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
+ "[<interface>...]" );
+
+/**
+ * "iwlist" payload
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int iwlist_payload ( struct net_device *netdev ) {
+ struct net80211_device *dev = net80211_get ( netdev );
+
+ if ( dev )
+ return iwlist ( dev );
+
+ return 0;
+}
+
+/**
+ * The "iwlist" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int iwlist_exec ( int argc, char **argv ) {
+ return ifcommon_exec ( argc, argv, &iwlist_cmd, iwlist_payload, 0 );
+}
+
+/** Wireless interface management commands */
+struct command iwmgmt_commands[] __command = {
+ {
+ .name = "iwstat",
+ .exec = iwstat_exec,
+ },
+ {
+ .name = "iwlist",
+ .exec = iwlist_exec,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/login_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/login_cmd.c
new file mode 100644
index 00000000..3286932d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/login_cmd.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/login_ui.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Login commands
+ *
+ */
+
+/** "login" options */
+struct login_options {};
+
+/** "login" option list */
+static struct option_descriptor login_opts[] = {};
+
+/** "login" command descriptor */
+static struct command_descriptor login_cmd =
+ COMMAND_DESC ( struct login_options, login_opts, 0, 0, "" );
+
+/**
+ * "login" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int login_exec ( int argc, char **argv ) {
+ struct login_options opts;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &login_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Show login UI */
+ if ( ( rc = login_ui() ) != 0 ) {
+ printf ( "Could not set credentials: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/** Login commands */
+struct command login_command __command = {
+ .name = "login",
+ .exec = login_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/lotest_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/lotest_cmd.c
new file mode 100644
index 00000000..172be2d8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/lotest_cmd.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/if_ether.h>
+#include <usr/lotest.h>
+
+/** @file
+ *
+ * Loopback testing commands
+ *
+ */
+
+/** "lotest" options */
+struct lotest_options {
+ /** MTU */
+ unsigned int mtu;
+};
+
+/** "lotest" option list */
+static struct option_descriptor lotest_opts[] = {
+ OPTION_DESC ( "mtu", 'm', required_argument,
+ struct lotest_options, mtu, parse_integer ),
+};
+
+/** "lotest" command descriptor */
+static struct command_descriptor lotest_cmd =
+ COMMAND_DESC ( struct lotest_options, lotest_opts, 2, 2,
+ "[--mtu <mtu>] <sending interface> "
+ "<receiving interface>" );
+
+/**
+ * "lotest" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int lotest_exec ( int argc, char **argv ) {
+ struct lotest_options opts;
+ struct net_device *sender;
+ struct net_device *receiver;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &lotest_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse sending interface name */
+ if ( ( rc = parse_netdev ( argv[optind], &sender ) ) != 0 )
+ return rc;
+
+ /* Parse receiving interface name */
+ if ( ( rc = parse_netdev ( argv[ optind + 1 ], &receiver ) ) != 0 )
+ return rc;
+
+ /* Use default MTU if none specified */
+ if ( ! opts.mtu )
+ opts.mtu = ETH_MAX_MTU;
+
+ /* Perform loopback test */
+ if ( ( rc = loopback_test ( sender, receiver, opts.mtu ) ) != 0 ) {
+ printf ( "Test failed: %s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/** Loopback testing commands */
+struct command lotest_command __command = {
+ .name = "lotest",
+ .exec = lotest_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/menu_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/menu_cmd.c
new file mode 100644
index 00000000..ff3b76fa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/menu_cmd.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Menu commands
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ipxe/menu.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/settings.h>
+#include <ipxe/features.h>
+
+FEATURE ( FEATURE_MISC, "Menu", DHCP_EB_FEATURE_MENU, 1 );
+
+/** "menu" options */
+struct menu_options {
+ /** Name */
+ const char *name;
+ /** Delete */
+ int delete;
+};
+
+/** "menu" option list */
+static struct option_descriptor menu_opts[] = {
+ OPTION_DESC ( "name", 'n', required_argument,
+ struct menu_options, name, parse_string ),
+ OPTION_DESC ( "delete", 'd', no_argument,
+ struct menu_options, delete, parse_flag ),
+};
+
+/** "menu" command descriptor */
+static struct command_descriptor menu_cmd =
+ COMMAND_DESC ( struct menu_options, menu_opts, 0, MAX_ARGUMENTS,
+ "[--name <name>] [--delete] [<title>]" );
+
+/**
+ * The "menu" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int menu_exec ( int argc, char **argv ) {
+ struct menu_options opts;
+ struct menu *menu;
+ char *title;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &menu_cmd, &opts ) ) != 0 )
+ goto err_parse_options;
+
+ /* Parse title */
+ title = concat_args ( &argv[optind] );
+ if ( ! title ) {
+ rc = -ENOMEM;
+ goto err_parse_title;
+ }
+
+ /* Create menu */
+ menu = create_menu ( opts.name, title );
+ if ( ! menu ) {
+ rc = -ENOMEM;
+ goto err_create_menu;
+ }
+
+ /* Destroy menu, if applicable */
+ if ( opts.delete )
+ destroy_menu ( menu );
+
+ /* Success */
+ rc = 0;
+
+ err_create_menu:
+ free ( title );
+ err_parse_title:
+ err_parse_options:
+ return rc;
+}
+
+/** "item" options */
+struct item_options {
+ /** Menu name */
+ const char *menu;
+ /** Shortcut key */
+ unsigned int key;
+ /** Use as default */
+ int is_default;
+ /** Use as a separator */
+ int is_gap;
+};
+
+/** "item" option list */
+static struct option_descriptor item_opts[] = {
+ OPTION_DESC ( "menu", 'm', required_argument,
+ struct item_options, menu, parse_string ),
+ OPTION_DESC ( "key", 'k', required_argument,
+ struct item_options, key, parse_key ),
+ OPTION_DESC ( "default", 'd', no_argument,
+ struct item_options, is_default, parse_flag ),
+ OPTION_DESC ( "gap", 'g', no_argument,
+ struct item_options, is_gap, parse_flag ),
+};
+
+/** "item" command descriptor */
+static struct command_descriptor item_cmd =
+ COMMAND_DESC ( struct item_options, item_opts, 0, MAX_ARGUMENTS,
+ "[--menu <menu>] [--key <key>] [--default] "
+ "[<label>|--gap [<text>]]" );
+
+/**
+ * The "item" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int item_exec ( int argc, char **argv ) {
+ struct item_options opts;
+ struct menu *menu;
+ struct menu_item *item;
+ char *label = NULL;
+ char *text = NULL;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &item_cmd, &opts ) ) != 0 )
+ goto err_parse_options;
+
+ /* Parse label, if present */
+ if ( ! opts.is_gap )
+ label = argv[optind++]; /* May be NULL */
+
+ /* Parse text, if present */
+ if ( optind < argc ) {
+ text = concat_args ( &argv[optind] );
+ if ( ! text ) {
+ rc = -ENOMEM;
+ goto err_parse_text;
+ }
+ }
+
+ /* Identify menu */
+ if ( ( rc = parse_menu ( opts.menu, &menu ) ) != 0 )
+ goto err_parse_menu;
+
+ /* Add menu item */
+ item = add_menu_item ( menu, label, ( text ? text : "" ),
+ opts.key, opts.is_default );
+ if ( ! item ) {
+ rc = -ENOMEM;
+ goto err_add_menu_item;
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_add_menu_item:
+ err_parse_menu:
+ free ( text );
+ err_parse_text:
+ err_parse_options:
+ return rc;
+}
+
+/** "choose" options */
+struct choose_options {
+ /** Menu name */
+ const char *menu;
+ /** Timeout */
+ unsigned int timeout;
+ /** Default selection */
+ const char *select;
+ /** Keep menu */
+ int keep;
+};
+
+/** "choose" option list */
+static struct option_descriptor choose_opts[] = {
+ OPTION_DESC ( "menu", 'm', required_argument,
+ struct choose_options, menu, parse_string ),
+ OPTION_DESC ( "default", 'd', required_argument,
+ struct choose_options, select, parse_string ),
+ OPTION_DESC ( "timeout", 't', required_argument,
+ struct choose_options, timeout, parse_integer ),
+ OPTION_DESC ( "keep", 'k', no_argument,
+ struct choose_options, keep, parse_flag ),
+};
+
+/** "choose" command descriptor */
+static struct command_descriptor choose_cmd =
+ COMMAND_DESC ( struct choose_options, choose_opts, 1, 1,
+ "[--menu <menu>] [--default <label>] "
+ "[--timeout <timeout>] [--keep] <setting>" );
+
+/**
+ * The "choose" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int choose_exec ( int argc, char **argv ) {
+ struct choose_options opts;
+ struct menu *menu;
+ struct menu_item *item;
+ const char *setting;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &choose_cmd, &opts ) ) != 0 )
+ goto err_parse_options;
+
+ /* Parse setting name */
+ setting = argv[optind];
+
+ /* Identify menu */
+ if ( ( rc = parse_menu ( opts.menu, &menu ) ) != 0 )
+ goto err_parse_menu;
+
+ /* Show menu */
+ if ( ( rc = show_menu ( menu, opts.timeout, opts.select, &item ) ) != 0)
+ goto err_show_menu;
+
+ /* Store setting */
+ if ( ( rc = storef_named_setting ( setting, item->label ) ) != 0 ) {
+ printf ( "Could not store \"%s\": %s\n",
+ setting, strerror ( rc ) );
+ goto err_store;
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_store:
+ err_show_menu:
+ /* Destroy menu, if applicable */
+ if ( ! opts.keep )
+ destroy_menu ( menu );
+ err_parse_menu:
+ err_parse_options:
+ return rc;
+}
+
+/** Menu commands */
+struct command menu_commands[] __command = {
+ {
+ .name = "menu",
+ .exec = menu_exec,
+ },
+ {
+ .name = "item",
+ .exec = item_exec,
+ },
+ {
+ .name = "choose",
+ .exec = choose_exec,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/nvo_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/nvo_cmd.c
new file mode 100644
index 00000000..a7e0f4a0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/nvo_cmd.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ipxe/settings.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <readline/readline.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Non-volatile option commands
+ *
+ */
+
+/** "show" options */
+struct show_options {};
+
+/** "show" option list */
+static struct option_descriptor show_opts[] = {};
+
+/** "show" command descriptor */
+static struct command_descriptor show_cmd =
+ COMMAND_DESC ( struct show_options, show_opts, 1, 1, "<setting>" );
+
+/**
+ * "show" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int show_exec ( int argc, char **argv ) {
+ struct show_options opts;
+ const char *name;
+ char name_buf[32];
+ char value_buf[256];
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &show_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse setting name */
+ name = argv[optind];
+
+ /* Fetch setting */
+ if ( ( rc = fetchf_named_setting ( name, name_buf, sizeof ( name_buf ),
+ value_buf,
+ sizeof ( value_buf ) ) ) < 0 ) {
+ printf ( "Could not find \"%s\": %s\n",
+ name, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Print setting value */
+ printf ( "%s = %s\n", name_buf, value_buf );
+
+ return 0;
+}
+
+/** "set", "clear", and "read" options */
+struct set_core_options {};
+
+/** "set", "clear", and "read" option list */
+static struct option_descriptor set_core_opts[] = {};
+
+/** "set" command descriptor */
+static struct command_descriptor set_cmd =
+ COMMAND_DESC ( struct set_core_options, set_core_opts, 1, MAX_ARGUMENTS,
+ "<setting> <value>" );
+
+/** "clear" and "read" command descriptor */
+static struct command_descriptor clear_read_cmd =
+ COMMAND_DESC ( struct set_core_options, set_core_opts, 1, 1,
+ "<setting>" );
+
+/**
+ * "set", "clear", and "read" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v cmd Command descriptor
+ * @v get_value Method to obtain setting value
+ * @ret rc Return status code
+ */
+static int set_core_exec ( int argc, char **argv,
+ struct command_descriptor *cmd,
+ int ( * get_value ) ( char **args, char **value ) ) {
+ struct set_core_options opts;
+ const char *name;
+ char *value;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, cmd, &opts ) ) != 0 )
+ goto err_parse_options;
+
+ /* Parse setting name */
+ name = argv[optind];
+
+ /* Parse setting value */
+ if ( ( rc = get_value ( &argv[ optind + 1 ], &value ) ) != 0 )
+ goto err_get_value;
+
+ /* Determine total length of command line */
+ if ( ( rc = storef_named_setting ( name, value ) ) != 0 ) {
+ printf ( "Could not %s \"%s\": %s\n",
+ argv[0], name, strerror ( rc ) );
+ goto err_store;
+ }
+
+ free ( value );
+ return 0;
+
+ err_store:
+ free ( value );
+ err_get_value:
+ err_parse_options:
+ return rc;
+}
+
+/**
+ * Get setting value for "set" command
+ *
+ * @v args Remaining arguments
+ * @ret value Setting value
+ * @ret rc Return status code
+ */
+static int set_value ( char **args, char **value ) {
+
+ *value = concat_args ( args );
+ if ( ! *value )
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * "set" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int set_exec ( int argc, char **argv ) {
+ return set_core_exec ( argc, argv, &set_cmd, set_value );
+}
+
+/**
+ * Get setting value for "clear" command
+ *
+ * @v args Remaining arguments
+ * @ret value Setting value
+ * @ret rc Return status code
+ */
+static int clear_value ( char **args __unused, char **value ) {
+
+ *value = NULL;
+ return 0;
+}
+
+/**
+ * "clear" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int clear_exec ( int argc, char **argv ) {
+ return set_core_exec ( argc, argv, &clear_read_cmd, clear_value );
+}
+
+/**
+ * Get setting value for "read" command
+ *
+ * @ret value Setting value
+ * @ret rc Return status code
+ */
+static int read_value ( char **args __unused, char **value ) {
+
+ *value = readline ( NULL );
+ if ( ! *value )
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * "read" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int read_exec ( int argc, char **argv ) {
+ return set_core_exec ( argc, argv, &clear_read_cmd, read_value );
+}
+
+/** Non-volatile option commands */
+struct command nvo_commands[] __command = {
+ {
+ .name = "show",
+ .exec = show_exec,
+ },
+ {
+ .name = "set",
+ .exec = set_exec,
+ },
+ {
+ .name = "clear",
+ .exec = clear_exec,
+ },
+ {
+ .name = "read",
+ .exec = read_exec,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/route_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/route_cmd.c
new file mode 100644
index 00000000..f839d53f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/route_cmd.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <getopt.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <usr/route.h>
+
+/** @file
+ *
+ * Routing table management commands
+ *
+ */
+
+/** "route" options */
+struct route_options {};
+
+/** "route" option list */
+static struct option_descriptor route_opts[] = {};
+
+/** "route" command descriptor */
+static struct command_descriptor route_cmd =
+ COMMAND_DESC ( struct route_options, route_opts, 0, 0, "" );
+
+/**
+ * The "route" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int route_exec ( int argc, char **argv ) {
+ struct route_options opts;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &route_cmd, &opts ) ) != 0 )
+ return rc;
+
+ route();
+
+ return 0;
+}
+
+/** Routing table management commands */
+struct command route_commands[] __command = {
+ {
+ .name = "route",
+ .exec = route_exec,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/sanboot_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/sanboot_cmd.c
new file mode 100644
index 00000000..b4937104
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/sanboot_cmd.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/uri.h>
+#include <ipxe/sanboot.h>
+#include <usr/autoboot.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * SAN commands
+ *
+ */
+
+/** "sanboot" options */
+struct sanboot_options {
+ /** Drive number */
+ unsigned int drive;
+ /** Do not describe SAN device */
+ int no_describe;
+ /** Keep SAN device */
+ int keep;
+};
+
+/** "sanboot" option list */
+static struct option_descriptor sanboot_opts[] = {
+ OPTION_DESC ( "drive", 'd', required_argument,
+ struct sanboot_options, drive, parse_integer ),
+ OPTION_DESC ( "no-describe", 'n', no_argument,
+ struct sanboot_options, no_describe, parse_flag ),
+ OPTION_DESC ( "keep", 'k', no_argument,
+ struct sanboot_options, keep, parse_flag ),
+};
+
+/** "sanhook" command descriptor */
+static struct command_descriptor sanhook_cmd =
+ COMMAND_DESC ( struct sanboot_options, sanboot_opts, 1, 1,
+ "[--drive <drive>] [--no-describe] <root-path>" );
+
+/** "sanboot" command descriptor */
+static struct command_descriptor sanboot_cmd =
+ COMMAND_DESC ( struct sanboot_options, sanboot_opts, 0, 1,
+ "[--drive <drive>] [--no-describe] [--keep] "
+ "[<root-path>]" );
+
+/** "sanunhook" command descriptor */
+static struct command_descriptor sanunhook_cmd =
+ COMMAND_DESC ( struct sanboot_options, sanboot_opts, 0, 0,
+ "[--drive <drive>]" );
+
+/**
+ * The "sanboot", "sanhook" and "sanunhook" commands
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v default_flags Default set of flags for uriboot()
+ * @v no_root_path_flags Additional flags to apply if no root path is present
+ * @ret rc Return status code
+ */
+static int sanboot_core_exec ( int argc, char **argv,
+ struct command_descriptor *cmd,
+ int default_flags, int no_root_path_flags ) {
+ struct sanboot_options opts;
+ const char *root_path;
+ struct uri *uri;
+ int flags;
+ int rc;
+
+ /* Initialise options */
+ memset ( &opts, 0, sizeof ( opts ) );
+ opts.drive = san_default_drive();
+
+ /* Parse options */
+ if ( ( rc = reparse_options ( argc, argv, cmd, &opts ) ) != 0 )
+ goto err_parse_options;
+
+ /* Parse root path, if present */
+ if ( argc > optind ) {
+ root_path = argv[optind];
+ uri = parse_uri ( root_path );
+ if ( ! uri ) {
+ rc = -ENOMEM;
+ goto err_parse_uri;
+ }
+ } else {
+ root_path = NULL;
+ uri = NULL;
+ }
+
+ /* Construct flags */
+ flags = default_flags;
+ if ( opts.no_describe )
+ flags |= URIBOOT_NO_SAN_DESCRIBE;
+ if ( opts.keep )
+ flags |= URIBOOT_NO_SAN_UNHOOK;
+ if ( ! root_path )
+ flags |= no_root_path_flags;
+
+ /* Boot from root path */
+ if ( ( rc = uriboot ( NULL, uri, opts.drive, flags ) ) != 0 )
+ goto err_uriboot;
+
+ err_uriboot:
+ uri_put ( uri );
+ err_parse_uri:
+ err_parse_options:
+ return rc;
+}
+
+/**
+ * The "sanhook" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int sanhook_exec ( int argc, char **argv ) {
+ return sanboot_core_exec ( argc, argv, &sanhook_cmd,
+ ( URIBOOT_NO_SAN_BOOT |
+ URIBOOT_NO_SAN_UNHOOK ), 0 );
+}
+
+/**
+ * The "sanboot" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int sanboot_exec ( int argc, char **argv ) {
+ return sanboot_core_exec ( argc, argv, &sanboot_cmd,
+ 0, URIBOOT_NO_SAN_UNHOOK );
+}
+
+/**
+ * The "sanunhook" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int sanunhook_exec ( int argc, char **argv ) {
+ return sanboot_core_exec ( argc, argv, &sanunhook_cmd,
+ ( URIBOOT_NO_SAN_DESCRIBE |
+ URIBOOT_NO_SAN_BOOT ), 0 );
+}
+
+/** SAN commands */
+struct command sanboot_commands[] __command = {
+ {
+ .name = "sanhook",
+ .exec = sanhook_exec,
+ },
+ {
+ .name = "sanboot",
+ .exec = sanboot_exec,
+ },
+ {
+ .name = "sanunhook",
+ .exec = sanunhook_exec,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/time_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/time_cmd.c
new file mode 100644
index 00000000..6c9556ce
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/time_cmd.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 Daniel Verkamp <daniel@drv.nu>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * March-19-2009 @ 02:44: Added sleep command.
+ * Shao Miller <shao.miller@yrdsb.edu.on.ca>.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/timer.h>
+
+/** @file
+ *
+ * Time commands
+ *
+ */
+
+/** "time" options */
+struct time_options {};
+
+/** "time" option list */
+static struct option_descriptor time_opts[] = {};
+
+/** "time" command descriptor */
+static struct command_descriptor time_cmd =
+ COMMAND_DESC ( struct time_options, time_opts, 1, MAX_ARGUMENTS,
+ "<command>" );
+
+/**
+ * "time" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int time_exec ( int argc, char **argv ) {
+ struct time_options opts;
+ unsigned long start;
+ int secs;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &time_cmd, &opts ) ) != 0 )
+ return rc;
+
+ start = currticks();
+ rc = execv ( argv[1], argv + 1 );
+ secs = (currticks() - start) / ticks_per_sec();
+
+ printf ( "%s: %ds\n", argv[0], secs );
+
+ return rc;
+}
+
+/** "time" command */
+struct command time_command __command = {
+ .name = "time",
+ .exec = time_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/commands/vlan_cmd.c b/src/VBox/Devices/PC/ipxe/src/hci/commands/vlan_cmd.c
new file mode 100644
index 00000000..28638ae6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/commands/vlan_cmd.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/vlan.h>
+
+/** @file
+ *
+ * VLAN commands
+ *
+ */
+
+/** "vcreate" options */
+struct vcreate_options {
+ /** VLAN tag */
+ unsigned int tag;
+ /** VLAN default priority */
+ unsigned int priority;
+};
+
+/** "vcreate" option list */
+static struct option_descriptor vcreate_opts[] = {
+ OPTION_DESC ( "tag", 't', required_argument,
+ struct vcreate_options, tag, parse_integer ),
+ OPTION_DESC ( "priority", 'p', required_argument,
+ struct vcreate_options, priority, parse_integer ),
+};
+
+/** "vcreate" command descriptor */
+static struct command_descriptor vcreate_cmd =
+ COMMAND_DESC ( struct vcreate_options, vcreate_opts, 1, 1,
+ "--tag <tag> [--priority <priority>] "
+ "<trunk interface>" );
+
+/**
+ * "vcreate" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int vcreate_exec ( int argc, char **argv ) {
+ struct vcreate_options opts;
+ struct net_device *trunk;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &vcreate_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse trunk interface */
+ if ( ( rc = parse_netdev ( argv[optind], &trunk ) ) != 0 )
+ return rc;
+
+ /* Create VLAN device */
+ if ( ( rc = vlan_create ( trunk, opts.tag, opts.priority ) ) != 0 ) {
+ printf ( "Could not create VLAN device: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/** "vdestroy" options */
+struct vdestroy_options {};
+
+/** "vdestroy" option list */
+static struct option_descriptor vdestroy_opts[] = {};
+
+/** "vdestroy" command descriptor */
+static struct command_descriptor vdestroy_cmd =
+ COMMAND_DESC ( struct vdestroy_options, vdestroy_opts, 1, 1,
+ "<VLAN interface>" );
+
+/**
+ * "vdestroy" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int vdestroy_exec ( int argc, char **argv ) {
+ struct vdestroy_options opts;
+ struct net_device *netdev;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &vdestroy_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse trunk interface */
+ if ( ( rc = parse_netdev ( argv[optind], &netdev ) ) != 0 )
+ return rc;
+
+ /* Destroy VLAN device */
+ if ( ( rc = vlan_destroy ( netdev ) ) != 0 ) {
+ printf ( "Could not destroy VLAN device: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/** VLAN commands */
+struct command vlan_commands[] __command = {
+ {
+ .name = "vcreate",
+ .exec = vcreate_exec,
+ },
+ {
+ .name = "vdestroy",
+ .exec = vdestroy_exec,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/editstring.c b/src/VBox/Devices/PC/ipxe/src/hci/editstring.c
new file mode 100644
index 00000000..35a5b2c1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/editstring.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <assert.h>
+#include <string.h>
+#include <ipxe/keys.h>
+#include <ipxe/editstring.h>
+
+/** @file
+ *
+ * Editable strings
+ *
+ */
+
+static void insert_delete ( struct edit_string *string, size_t delete_len,
+ const char *insert_text )
+ __attribute__ (( nonnull (1) ));
+static void insert_character ( struct edit_string *string,
+ unsigned int character ) __nonnull;
+static void delete_character ( struct edit_string *string ) __nonnull;
+static void backspace ( struct edit_string *string ) __nonnull;
+static void kill_sol ( struct edit_string *string ) __nonnull;
+static void kill_eol ( struct edit_string *string ) __nonnull;
+
+/**
+ * Insert and/or delete text within an editable string
+ *
+ * @v string Editable string
+ * @v delete_len Length of text to delete from current cursor position
+ * @v insert_text Text to insert at current cursor position, or NULL
+ */
+static void insert_delete ( struct edit_string *string, size_t delete_len,
+ const char *insert_text ) {
+ size_t old_len, max_delete_len, insert_len, max_insert_len, new_len;
+
+ /* Calculate lengths */
+ old_len = strlen ( string->buf );
+ assert ( string->cursor <= old_len );
+ max_delete_len = ( old_len - string->cursor );
+ if ( delete_len > max_delete_len )
+ delete_len = max_delete_len;
+ insert_len = ( insert_text ? strlen ( insert_text ) : 0 );
+ max_insert_len = ( ( string->len - 1 ) - ( old_len - delete_len ) );
+ if ( insert_len > max_insert_len )
+ insert_len = max_insert_len;
+ new_len = ( old_len - delete_len + insert_len );
+
+ /* Fill in edit history */
+ string->mod_start = string->cursor;
+ string->mod_end = ( ( new_len > old_len ) ? new_len : old_len );
+
+ /* Move data following the cursor */
+ memmove ( ( string->buf + string->cursor + insert_len ),
+ ( string->buf + string->cursor + delete_len ),
+ ( max_delete_len + 1 - delete_len ) );
+
+ /* Copy inserted text to cursor position */
+ memcpy ( ( string->buf + string->cursor ), insert_text, insert_len );
+ string->cursor += insert_len;
+}
+
+/**
+ * Insert character at current cursor position
+ *
+ * @v string Editable string
+ * @v character Character to insert
+ */
+static void insert_character ( struct edit_string *string,
+ unsigned int character ) {
+ char insert_text[2] = { character, '\0' };
+ insert_delete ( string, 0, insert_text );
+}
+
+/**
+ * Delete character at current cursor position
+ *
+ * @v string Editable string
+ */
+static void delete_character ( struct edit_string *string ) {
+ insert_delete ( string, 1, NULL );
+}
+
+/**
+ * Delete character to left of current cursor position
+ *
+ * @v string Editable string
+ */
+static void backspace ( struct edit_string *string ) {
+ if ( string->cursor > 0 ) {
+ string->cursor--;
+ delete_character ( string );
+ }
+}
+
+/**
+ * Delete to start of line
+ *
+ * @v string Editable string
+ */
+static void kill_sol ( struct edit_string *string ) {
+ size_t old_cursor = string->cursor;
+ string->cursor = 0;
+ insert_delete ( string, old_cursor, NULL );
+}
+
+/**
+ * Delete to end of line
+ *
+ * @v string Editable string
+ */
+static void kill_eol ( struct edit_string *string ) {
+ insert_delete ( string, ~( ( size_t ) 0 ), NULL );
+}
+
+/**
+ * Replace editable string
+ *
+ * @v string Editable string
+ * @v replacement Replacement string
+ */
+void replace_string ( struct edit_string *string, const char *replacement ) {
+ string->cursor = 0;
+ insert_delete ( string, ~( ( size_t ) 0 ), replacement );
+}
+
+/**
+ * Edit editable string
+ *
+ * @v string Editable string
+ * @v key Key pressed by user
+ * @ret key Key returned to application, or zero
+ *
+ * Handles keypresses and updates the content of the editable string.
+ * Basic line editing facilities (delete/insert/cursor) are supported.
+ * If edit_string() understands and uses the keypress it will return
+ * zero, otherwise it will return the original key.
+ *
+ * This function does not update the display in any way.
+ *
+ * The string's edit history will be updated to allow the caller to
+ * efficiently bring the display into sync with the string content.
+ */
+int edit_string ( struct edit_string *string, int key ) {
+ int retval = 0;
+ size_t len = strlen ( string->buf );
+
+ /* Prepare edit history */
+ string->last_cursor = string->cursor;
+ string->mod_start = string->cursor;
+ string->mod_end = string->cursor;
+
+ /* Interpret key */
+ if ( ( key >= 0x20 ) && ( key <= 0x7e ) ) {
+ /* Printable character; insert at current position */
+ insert_character ( string, key );
+ } else switch ( key ) {
+ case KEY_BACKSPACE:
+ /* Backspace */
+ backspace ( string );
+ break;
+ case KEY_DC:
+ case CTRL_D:
+ /* Delete character */
+ delete_character ( string );
+ break;
+ case CTRL_U:
+ /* Delete to start of line */
+ kill_sol ( string );
+ break;
+ case CTRL_K:
+ /* Delete to end of line */
+ kill_eol ( string );
+ break;
+ case KEY_HOME:
+ case CTRL_A:
+ /* Start of line */
+ string->cursor = 0;
+ break;
+ case KEY_END:
+ case CTRL_E:
+ /* End of line */
+ string->cursor = len;
+ break;
+ case KEY_LEFT:
+ case CTRL_B:
+ /* Cursor left */
+ if ( string->cursor > 0 )
+ string->cursor--;
+ break;
+ case KEY_RIGHT:
+ case CTRL_F:
+ /* Cursor right */
+ if ( string->cursor < len )
+ string->cursor++;
+ break;
+ default:
+ retval = key;
+ break;
+ }
+
+ return retval;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_al.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_al.c
new file mode 100644
index 00000000..caf295e8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_al.c
@@ -0,0 +1,32 @@
+/** @file
+ *
+ * "al" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "al" keyboard mapping */
+struct key_mapping al_mapping[] __keymap = {
+ { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */
+ { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */
+ { 0x22, 0x7b }, /* '"' => '{' */
+ { 0x27, 0x5b }, /* '\'' => '[' */
+ { 0x3c, 0x3b }, /* '<' => ';' */
+ { 0x3e, 0x3a }, /* '>' => ':' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x59, 0x5a }, /* 'Y' => 'Z' */
+ { 0x5a, 0x59 }, /* 'Z' => 'Y' */
+ { 0x5c, 0x5d }, /* '\\' => ']' */
+ { 0x5d, 0x40 }, /* ']' => '@' */
+ { 0x60, 0x5c }, /* '`' => '\\' */
+ { 0x79, 0x7a }, /* 'y' => 'z' */
+ { 0x7a, 0x79 }, /* 'z' => 'y' */
+ { 0x7c, 0x7d }, /* '|' => '}' */
+ { 0x7d, 0x27 }, /* '}' => '\'' */
+ { 0x7e, 0x7c }, /* '~' => '|' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_az.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_az.c
new file mode 100644
index 00000000..27ce91e7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_az.c
@@ -0,0 +1,24 @@
+/** @file
+ *
+ * "az" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "az" keyboard mapping */
+struct key_mapping az_mapping[] __keymap = {
+ { 0x23, 0x27 }, /* '#' => '\'' */
+ { 0x24, 0x3b }, /* '$' => ';' */
+ { 0x26, 0x3f }, /* '&' => '?' */
+ { 0x2f, 0x2e }, /* '/' => '.' */
+ { 0x3a, 0x49 }, /* ':' => 'I' */
+ { 0x3f, 0x2c }, /* '?' => ',' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x5e, 0x3a }, /* '^' => ':' */
+ { 0x7c, 0x2f }, /* '|' => '/' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_bg.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_bg.c
new file mode 100644
index 00000000..62b6baea
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_bg.c
@@ -0,0 +1,15 @@
+/** @file
+ *
+ * "bg" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "bg" keyboard mapping */
+struct key_mapping bg_mapping[] __keymap = {
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_by.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_by.c
new file mode 100644
index 00000000..514d0b53
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_by.c
@@ -0,0 +1,15 @@
+/** @file
+ *
+ * "by" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "by" keyboard mapping */
+struct key_mapping by_mapping[] __keymap = {
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_cf.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_cf.c
new file mode 100644
index 00000000..d7e63b9b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_cf.c
@@ -0,0 +1,24 @@
+/** @file
+ *
+ * "cf" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "cf" keyboard mapping */
+struct key_mapping cf_mapping[] __keymap = {
+ { 0x23, 0x2f }, /* '#' => '/' */
+ { 0x3c, 0x27 }, /* '<' => '\'' */
+ { 0x3e, 0x2e }, /* '>' => '.' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x5c, 0x3c }, /* '\\' => '<' */
+ { 0x5e, 0x3f }, /* '^' => '?' */
+ { 0x60, 0x23 }, /* '`' => '#' */
+ { 0x7c, 0x3e }, /* '|' => '>' */
+ { 0x7e, 0x7c }, /* '~' => '|' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_cz.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_cz.c
new file mode 100644
index 00000000..9280f84f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_cz.c
@@ -0,0 +1,27 @@
+/** @file
+ *
+ * "cz" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "cz" keyboard mapping */
+struct key_mapping cz_mapping[] __keymap = {
+ { 0x21, 0x2b }, /* '!' => '+' */
+ { 0x2d, 0x3d }, /* '-' => '=' */
+ { 0x2f, 0x2d }, /* '/' => '-' */
+ { 0x31, 0x2b }, /* '1' => '+' */
+ { 0x3c, 0x2c }, /* '<' => ',' */
+ { 0x3e, 0x2e }, /* '>' => '.' */
+ { 0x3f, 0x2d }, /* '?' => '-' */
+ { 0x5d, 0x29 }, /* ']' => ')' */
+ { 0x5f, 0x3d }, /* '_' => '=' */
+ { 0x60, 0x3b }, /* '`' => ';' */
+ { 0x7d, 0x29 }, /* '}' => ')' */
+ { 0x7e, 0x3b }, /* '~' => ';' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_de.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_de.c
new file mode 100644
index 00000000..ffcf912f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_de.c
@@ -0,0 +1,46 @@
+/** @file
+ *
+ * "de" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "de" keyboard mapping */
+struct key_mapping de_mapping[] __keymap = {
+ { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */
+ { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */
+ { 0x22, 0x7d }, /* '"' => '}' */
+ { 0x26, 0x2f }, /* '&' => '/' */
+ { 0x27, 0x5d }, /* '\'' => ']' */
+ { 0x28, 0x29 }, /* '(' => ')' */
+ { 0x29, 0x3d }, /* ')' => '=' */
+ { 0x2a, 0x28 }, /* '*' => '(' */
+ { 0x2b, 0x60 }, /* '+' => '`' */
+ { 0x2d, 0x5c }, /* '-' => '\\' */
+ { 0x2f, 0x2d }, /* '/' => '-' */
+ { 0x3a, 0x7b }, /* ':' => '{' */
+ { 0x3b, 0x5b }, /* ';' => '[' */
+ { 0x3c, 0x3b }, /* '<' => ';' */
+ { 0x3d, 0x27 }, /* '=' => '\'' */
+ { 0x3e, 0x3a }, /* '>' => ':' */
+ { 0x3f, 0x5f }, /* '?' => '_' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x59, 0x5a }, /* 'Y' => 'Z' */
+ { 0x5a, 0x59 }, /* 'Z' => 'Y' */
+ { 0x5b, 0x40 }, /* '[' => '@' */
+ { 0x5c, 0x23 }, /* '\\' => '#' */
+ { 0x5d, 0x2b }, /* ']' => '+' */
+ { 0x5e, 0x26 }, /* '^' => '&' */
+ { 0x5f, 0x3f }, /* '_' => '?' */
+ { 0x60, 0x5e }, /* '`' => '^' */
+ { 0x79, 0x7a }, /* 'y' => 'z' */
+ { 0x7a, 0x79 }, /* 'z' => 'y' */
+ { 0x7b, 0x5c }, /* '{' => '\\' */
+ { 0x7c, 0x27 }, /* '|' => '\'' */
+ { 0x7d, 0x2a }, /* '}' => '*' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_dk.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_dk.c
new file mode 100644
index 00000000..e409018c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_dk.c
@@ -0,0 +1,31 @@
+/** @file
+ *
+ * "dk" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "dk" keyboard mapping */
+struct key_mapping dk_mapping[] __keymap = {
+ { 0x26, 0x2f }, /* '&' => '/' */
+ { 0x28, 0x29 }, /* '(' => ')' */
+ { 0x29, 0x3d }, /* ')' => '=' */
+ { 0x2a, 0x28 }, /* '*' => '(' */
+ { 0x2b, 0x60 }, /* '+' => '`' */
+ { 0x2d, 0x2b }, /* '-' => '+' */
+ { 0x2f, 0x2d }, /* '/' => '-' */
+ { 0x3c, 0x3b }, /* '<' => ';' */
+ { 0x3e, 0x3a }, /* '>' => ':' */
+ { 0x3f, 0x5f }, /* '?' => '_' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x5c, 0x27 }, /* '\\' => '\'' */
+ { 0x5e, 0x26 }, /* '^' => '&' */
+ { 0x5f, 0x3f }, /* '_' => '?' */
+ { 0x7c, 0x2a }, /* '|' => '*' */
+ { 0x7d, 0x5e }, /* '}' => '^' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_es.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_es.c
new file mode 100644
index 00000000..c1fe013a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_es.c
@@ -0,0 +1,29 @@
+/** @file
+ *
+ * "es" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "es" keyboard mapping */
+struct key_mapping es_mapping[] __keymap = {
+ { 0x26, 0x2f }, /* '&' => '/' */
+ { 0x28, 0x29 }, /* '(' => ')' */
+ { 0x29, 0x3d }, /* ')' => '=' */
+ { 0x2a, 0x28 }, /* '*' => '(' */
+ { 0x2d, 0x27 }, /* '-' => '\'' */
+ { 0x2f, 0x2d }, /* '/' => '-' */
+ { 0x3c, 0x3b }, /* '<' => ';' */
+ { 0x3e, 0x3a }, /* '>' => ':' */
+ { 0x3f, 0x5f }, /* '?' => '_' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x5d, 0x2b }, /* ']' => '+' */
+ { 0x5e, 0x26 }, /* '^' => '&' */
+ { 0x5f, 0x3f }, /* '_' => '?' */
+ { 0x7d, 0x2a }, /* '}' => '*' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_et.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_et.c
new file mode 100644
index 00000000..ad88cecc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_et.c
@@ -0,0 +1,30 @@
+/** @file
+ *
+ * "et" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "et" keyboard mapping */
+struct key_mapping et_mapping[] __keymap = {
+ { 0x26, 0x2f }, /* '&' => '/' */
+ { 0x28, 0x29 }, /* '(' => ')' */
+ { 0x29, 0x3d }, /* ')' => '=' */
+ { 0x2a, 0x28 }, /* '*' => '(' */
+ { 0x2d, 0x2b }, /* '-' => '+' */
+ { 0x2f, 0x2d }, /* '/' => '-' */
+ { 0x3c, 0x3b }, /* '<' => ';' */
+ { 0x3e, 0x3a }, /* '>' => ':' */
+ { 0x3f, 0x5f }, /* '?' => '_' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x5c, 0x27 }, /* '\\' => '\'' */
+ { 0x5e, 0x26 }, /* '^' => '&' */
+ { 0x5f, 0x3f }, /* '_' => '?' */
+ { 0x7c, 0x2a }, /* '|' => '*' */
+ { 0x7f, 0x1b }, /* 0x7f => 0x1b */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_fi.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_fi.c
new file mode 100644
index 00000000..c8f6c3a0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_fi.c
@@ -0,0 +1,38 @@
+/** @file
+ *
+ * "fi" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "fi" keyboard mapping */
+struct key_mapping fi_mapping[] __keymap = {
+ { 0x22, 0x5b }, /* '"' => '[' */
+ { 0x26, 0x2f }, /* '&' => '/' */
+ { 0x27, 0x7b }, /* '\'' => '{' */
+ { 0x28, 0x29 }, /* '(' => ')' */
+ { 0x29, 0x3d }, /* ')' => '=' */
+ { 0x2a, 0x28 }, /* '*' => '(' */
+ { 0x2b, 0x60 }, /* '+' => '`' */
+ { 0x2d, 0x2b }, /* '-' => '+' */
+ { 0x2f, 0x2d }, /* '/' => '-' */
+ { 0x3a, 0x5c }, /* ':' => '\\' */
+ { 0x3b, 0x7c }, /* ';' => '|' */
+ { 0x3c, 0x3b }, /* '<' => ';' */
+ { 0x3d, 0x27 }, /* '=' => '\'' */
+ { 0x3e, 0x3a }, /* '>' => ':' */
+ { 0x3f, 0x5f }, /* '?' => '_' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x5b, 0x7d }, /* '[' => '}' */
+ { 0x5c, 0x27 }, /* '\\' => '\'' */
+ { 0x5e, 0x26 }, /* '^' => '&' */
+ { 0x5f, 0x3f }, /* '_' => '?' */
+ { 0x7b, 0x5d }, /* '{' => ']' */
+ { 0x7c, 0x2a }, /* '|' => '*' */
+ { 0x7d, 0x5e }, /* '}' => '^' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_fr.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_fr.c
new file mode 100644
index 00000000..fd615a45
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_fr.c
@@ -0,0 +1,68 @@
+/** @file
+ *
+ * "fr" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "fr" keyboard mapping */
+struct key_mapping fr_mapping[] __keymap = {
+ { 0x01, 0x11 }, /* Ctrl-A => Ctrl-Q */
+ { 0x11, 0x01 }, /* Ctrl-Q => Ctrl-A */
+ { 0x17, 0x1a }, /* Ctrl-W => Ctrl-Z */
+ { 0x1a, 0x17 }, /* Ctrl-Z => Ctrl-W */
+ { 0x21, 0x31 }, /* '!' => '1' */
+ { 0x22, 0x25 }, /* '"' => '%' */
+ { 0x23, 0x33 }, /* '#' => '3' */
+ { 0x24, 0x34 }, /* '$' => '4' */
+ { 0x25, 0x35 }, /* '%' => '5' */
+ { 0x26, 0x37 }, /* '&' => '7' */
+ { 0x27, 0x7c }, /* '\'' => '|' */
+ { 0x28, 0x39 }, /* '(' => '9' */
+ { 0x29, 0x30 }, /* ')' => '0' */
+ { 0x2a, 0x38 }, /* '*' => '8' */
+ { 0x2c, 0x3b }, /* ',' => ';' */
+ { 0x2d, 0x29 }, /* '-' => ')' */
+ { 0x2e, 0x3a }, /* '.' => ':' */
+ { 0x2f, 0x21 }, /* '/' => '!' */
+ { 0x30, 0x40 }, /* '0' => '@' */
+ { 0x31, 0x26 }, /* '1' => '&' */
+ { 0x32, 0x7b }, /* '2' => '{' */
+ { 0x33, 0x22 }, /* '3' => '"' */
+ { 0x34, 0x27 }, /* '4' => '\'' */
+ { 0x35, 0x28 }, /* '5' => '(' */
+ { 0x36, 0x2d }, /* '6' => '-' */
+ { 0x37, 0x7d }, /* '7' => '}' */
+ { 0x38, 0x5f }, /* '8' => '_' */
+ { 0x39, 0x2f }, /* '9' => '/' */
+ { 0x3a, 0x4d }, /* ':' => 'M' */
+ { 0x3b, 0x6d }, /* ';' => 'm' */
+ { 0x3c, 0x2e }, /* '<' => '.' */
+ { 0x3e, 0x2f }, /* '>' => '/' */
+ { 0x3f, 0x5c }, /* '?' => '\\' */
+ { 0x40, 0x32 }, /* '@' => '2' */
+ { 0x41, 0x51 }, /* 'A' => 'Q' */
+ { 0x4d, 0x3f }, /* 'M' => '?' */
+ { 0x51, 0x41 }, /* 'Q' => 'A' */
+ { 0x57, 0x5a }, /* 'W' => 'Z' */
+ { 0x5a, 0x57 }, /* 'Z' => 'W' */
+ { 0x5b, 0x5e }, /* '[' => '^' */
+ { 0x5c, 0x2a }, /* '\\' => '*' */
+ { 0x5d, 0x24 }, /* ']' => '$' */
+ { 0x5e, 0x36 }, /* '^' => '6' */
+ { 0x5f, 0x5d }, /* '_' => ']' */
+ { 0x60, 0x2a }, /* '`' => '*' */
+ { 0x61, 0x71 }, /* 'a' => 'q' */
+ { 0x6d, 0x2c }, /* 'm' => ',' */
+ { 0x71, 0x61 }, /* 'q' => 'a' */
+ { 0x77, 0x7a }, /* 'w' => 'z' */
+ { 0x7a, 0x77 }, /* 'z' => 'w' */
+ { 0x7b, 0x3c }, /* '{' => '<' */
+ { 0x7c, 0x23 }, /* '|' => '#' */
+ { 0x7d, 0x3e }, /* '}' => '>' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_gr.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_gr.c
new file mode 100644
index 00000000..42b6418e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_gr.c
@@ -0,0 +1,15 @@
+/** @file
+ *
+ * "gr" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "gr" keyboard mapping */
+struct key_mapping gr_mapping[] __keymap = {
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_hu.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_hu.c
new file mode 100644
index 00000000..68eff2f4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_hu.c
@@ -0,0 +1,34 @@
+/** @file
+ *
+ * "hu" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "hu" keyboard mapping */
+struct key_mapping hu_mapping[] __keymap = {
+ { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */
+ { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */
+ { 0x21, 0x27 }, /* '!' => '\'' */
+ { 0x23, 0x2b }, /* '#' => '+' */
+ { 0x24, 0x21 }, /* '$' => '!' */
+ { 0x26, 0x3d }, /* '&' => '=' */
+ { 0x28, 0x29 }, /* '(' => ')' */
+ { 0x2a, 0x28 }, /* '*' => '(' */
+ { 0x2f, 0x2d }, /* '/' => '-' */
+ { 0x3c, 0x3f }, /* '<' => '?' */
+ { 0x3e, 0x3a }, /* '>' => ':' */
+ { 0x3f, 0x5f }, /* '?' => '_' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x59, 0x5a }, /* 'Y' => 'Z' */
+ { 0x5a, 0x59 }, /* 'Z' => 'Y' */
+ { 0x5e, 0x2f }, /* '^' => '/' */
+ { 0x60, 0x30 }, /* '`' => '0' */
+ { 0x79, 0x7a }, /* 'y' => 'z' */
+ { 0x7a, 0x79 }, /* 'z' => 'y' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_il.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_il.c
new file mode 100644
index 00000000..478330c0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_il.c
@@ -0,0 +1,15 @@
+/** @file
+ *
+ * "il" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "il" keyboard mapping */
+struct key_mapping il_mapping[] __keymap = {
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_it.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_it.c
new file mode 100644
index 00000000..5bb05471
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_it.c
@@ -0,0 +1,32 @@
+/** @file
+ *
+ * "it" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "it" keyboard mapping */
+struct key_mapping it_mapping[] __keymap = {
+ { 0x26, 0x2f }, /* '&' => '/' */
+ { 0x28, 0x29 }, /* '(' => ')' */
+ { 0x29, 0x3d }, /* ')' => '=' */
+ { 0x2a, 0x28 }, /* '*' => '(' */
+ { 0x2b, 0x5e }, /* '+' => '^' */
+ { 0x2d, 0x27 }, /* '-' => '\'' */
+ { 0x2f, 0x2d }, /* '/' => '-' */
+ { 0x3c, 0x3b }, /* '<' => ';' */
+ { 0x3e, 0x3a }, /* '>' => ':' */
+ { 0x3f, 0x5f }, /* '?' => '_' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x5d, 0x2b }, /* ']' => '+' */
+ { 0x5e, 0x26 }, /* '^' => '&' */
+ { 0x5f, 0x3f }, /* '_' => '?' */
+ { 0x60, 0x5c }, /* '`' => '\\' */
+ { 0x7d, 0x2a }, /* '}' => '*' */
+ { 0x7e, 0x7c }, /* '~' => '|' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_lt.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_lt.c
new file mode 100644
index 00000000..3e99d8c6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_lt.c
@@ -0,0 +1,15 @@
+/** @file
+ *
+ * "lt" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "lt" keyboard mapping */
+struct key_mapping lt_mapping[] __keymap = {
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_mk.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_mk.c
new file mode 100644
index 00000000..8f506077
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_mk.c
@@ -0,0 +1,15 @@
+/** @file
+ *
+ * "mk" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "mk" keyboard mapping */
+struct key_mapping mk_mapping[] __keymap = {
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_mt.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_mt.c
new file mode 100644
index 00000000..094a6fc6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_mt.c
@@ -0,0 +1,20 @@
+/** @file
+ *
+ * "mt" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "mt" keyboard mapping */
+struct key_mapping mt_mapping[] __keymap = {
+ { 0x22, 0x40 }, /* '"' => '@' */
+ { 0x23, 0x04 }, /* '#' => Ctrl-D */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x5c, 0x23 }, /* '\\' => '#' */
+ { 0x7c, 0x7e }, /* '|' => '~' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_nl.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_nl.c
new file mode 100644
index 00000000..ba051705
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_nl.c
@@ -0,0 +1,34 @@
+/** @file
+ *
+ * "nl" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "nl" keyboard mapping */
+struct key_mapping nl_mapping[] __keymap = {
+ { 0x26, 0x5f }, /* '&' => '_' */
+ { 0x28, 0x29 }, /* '(' => ')' */
+ { 0x29, 0x27 }, /* ')' => '\'' */
+ { 0x2a, 0x28 }, /* '*' => '(' */
+ { 0x2b, 0x7e }, /* '+' => '~' */
+ { 0x2d, 0x2f }, /* '-' => '/' */
+ { 0x2f, 0x2d }, /* '/' => '-' */
+ { 0x3b, 0x2b }, /* ';' => '+' */
+ { 0x3c, 0x3b }, /* '<' => ';' */
+ { 0x3e, 0x3a }, /* '>' => ':' */
+ { 0x3f, 0x3d }, /* '?' => '=' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x5c, 0x3c }, /* '\\' => '<' */
+ { 0x5d, 0x2a }, /* ']' => '*' */
+ { 0x5e, 0x26 }, /* '^' => '&' */
+ { 0x5f, 0x3f }, /* '_' => '?' */
+ { 0x60, 0x40 }, /* '`' => '@' */
+ { 0x7c, 0x3e }, /* '|' => '>' */
+ { 0x7d, 0x7c }, /* '}' => '|' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_no-latin1.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_no-latin1.c
new file mode 100644
index 00000000..8c3e81b3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_no-latin1.c
@@ -0,0 +1,34 @@
+/** @file
+ *
+ * "no-latin1" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "no-latin1" keyboard mapping */
+struct key_mapping no_latin1_mapping[] __keymap = {
+ { 0x26, 0x2f }, /* '&' => '/' */
+ { 0x28, 0x29 }, /* '(' => ')' */
+ { 0x29, 0x3d }, /* ')' => '=' */
+ { 0x2a, 0x28 }, /* '*' => '(' */
+ { 0x2b, 0x60 }, /* '+' => '`' */
+ { 0x2d, 0x2b }, /* '-' => '+' */
+ { 0x2f, 0x2d }, /* '/' => '-' */
+ { 0x3c, 0x3b }, /* '<' => ';' */
+ { 0x3d, 0x5c }, /* '=' => '\\' */
+ { 0x3e, 0x3a }, /* '>' => ':' */
+ { 0x3f, 0x5f }, /* '?' => '_' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x5c, 0x27 }, /* '\\' => '\'' */
+ { 0x5d, 0x7e }, /* ']' => '~' */
+ { 0x5e, 0x26 }, /* '^' => '&' */
+ { 0x5f, 0x3f }, /* '_' => '?' */
+ { 0x60, 0x7c }, /* '`' => '|' */
+ { 0x7c, 0x2a }, /* '|' => '*' */
+ { 0x7d, 0x5e }, /* '}' => '^' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_no.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_no.c
new file mode 100644
index 00000000..45cf9e84
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_no.c
@@ -0,0 +1,105 @@
+/** @file
+ *
+ * "no" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "no" keyboard mapping */
+struct key_mapping no_mapping[] __keymap = {
+ { 0x02, 0x18 }, /* Ctrl-B => Ctrl-X */
+ { 0x03, 0x0a }, /* Ctrl-C => Ctrl-J */
+ { 0x04, 0x05 }, /* Ctrl-D => Ctrl-E */
+ { 0x06, 0x15 }, /* Ctrl-F => Ctrl-U */
+ { 0x07, 0x09 }, /* Ctrl-G => Ctrl-I */
+ { 0x08, 0x04 }, /* Ctrl-H => Ctrl-D */
+ { 0x0a, 0x08 }, /* Ctrl-J => Ctrl-H */
+ { 0x0b, 0x14 }, /* Ctrl-K => Ctrl-T */
+ { 0x0c, 0x0e }, /* Ctrl-L => Ctrl-N */
+ { 0x0e, 0x02 }, /* Ctrl-N => Ctrl-B */
+ { 0x0f, 0x12 }, /* Ctrl-O => Ctrl-R */
+ { 0x10, 0x0c }, /* Ctrl-P => Ctrl-L */
+ { 0x12, 0x10 }, /* Ctrl-R => Ctrl-P */
+ { 0x13, 0x0f }, /* Ctrl-S => Ctrl-O */
+ { 0x14, 0x19 }, /* Ctrl-T => Ctrl-Y */
+ { 0x15, 0x07 }, /* Ctrl-U => Ctrl-G */
+ { 0x16, 0x0b }, /* Ctrl-V => Ctrl-K */
+ { 0x18, 0x11 }, /* Ctrl-X => Ctrl-Q */
+ { 0x19, 0x06 }, /* Ctrl-Y => Ctrl-F */
+ { 0x22, 0x5f }, /* '"' => '_' */
+ { 0x26, 0x2f }, /* '&' => '/' */
+ { 0x27, 0x2d }, /* '\'' => '-' */
+ { 0x28, 0x29 }, /* '(' => ')' */
+ { 0x29, 0x3d }, /* ')' => '=' */
+ { 0x2a, 0x28 }, /* '*' => '(' */
+ { 0x2b, 0x60 }, /* '+' => '`' */
+ { 0x2c, 0x77 }, /* ',' => 'w' */
+ { 0x2d, 0x2b }, /* '-' => '+' */
+ { 0x2e, 0x76 }, /* '.' => 'v' */
+ { 0x2f, 0x7a }, /* '/' => 'z' */
+ { 0x3a, 0x53 }, /* ':' => 'S' */
+ { 0x3b, 0x73 }, /* ';' => 's' */
+ { 0x3c, 0x57 }, /* '<' => 'W' */
+ { 0x3d, 0x5c }, /* '=' => '\\' */
+ { 0x3e, 0x56 }, /* '>' => 'V' */
+ { 0x3f, 0x5a }, /* '?' => 'Z' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x42, 0x58 }, /* 'B' => 'X' */
+ { 0x43, 0x4a }, /* 'C' => 'J' */
+ { 0x44, 0x45 }, /* 'D' => 'E' */
+ { 0x45, 0x3a }, /* 'E' => ':' */
+ { 0x46, 0x55 }, /* 'F' => 'U' */
+ { 0x47, 0x49 }, /* 'G' => 'I' */
+ { 0x48, 0x44 }, /* 'H' => 'D' */
+ { 0x49, 0x43 }, /* 'I' => 'C' */
+ { 0x4a, 0x48 }, /* 'J' => 'H' */
+ { 0x4b, 0x54 }, /* 'K' => 'T' */
+ { 0x4c, 0x4e }, /* 'L' => 'N' */
+ { 0x4e, 0x42 }, /* 'N' => 'B' */
+ { 0x4f, 0x52 }, /* 'O' => 'R' */
+ { 0x50, 0x4c }, /* 'P' => 'L' */
+ { 0x52, 0x50 }, /* 'R' => 'P' */
+ { 0x53, 0x4f }, /* 'S' => 'O' */
+ { 0x54, 0x59 }, /* 'T' => 'Y' */
+ { 0x55, 0x47 }, /* 'U' => 'G' */
+ { 0x56, 0x4b }, /* 'V' => 'K' */
+ { 0x57, 0x3b }, /* 'W' => ';' */
+ { 0x58, 0x51 }, /* 'X' => 'Q' */
+ { 0x59, 0x46 }, /* 'Y' => 'F' */
+ { 0x5b, 0x27 }, /* '[' => '\'' */
+ { 0x5c, 0x3c }, /* '\\' => '<' */
+ { 0x5d, 0x7e }, /* ']' => '~' */
+ { 0x5e, 0x26 }, /* '^' => '&' */
+ { 0x5f, 0x3f }, /* '_' => '?' */
+ { 0x60, 0x7c }, /* '`' => '|' */
+ { 0x62, 0x78 }, /* 'b' => 'x' */
+ { 0x63, 0x6a }, /* 'c' => 'j' */
+ { 0x64, 0x65 }, /* 'd' => 'e' */
+ { 0x65, 0x2e }, /* 'e' => '.' */
+ { 0x66, 0x75 }, /* 'f' => 'u' */
+ { 0x67, 0x69 }, /* 'g' => 'i' */
+ { 0x68, 0x64 }, /* 'h' => 'd' */
+ { 0x69, 0x63 }, /* 'i' => 'c' */
+ { 0x6a, 0x68 }, /* 'j' => 'h' */
+ { 0x6b, 0x74 }, /* 'k' => 't' */
+ { 0x6c, 0x6e }, /* 'l' => 'n' */
+ { 0x6e, 0x62 }, /* 'n' => 'b' */
+ { 0x6f, 0x72 }, /* 'o' => 'r' */
+ { 0x70, 0x6c }, /* 'p' => 'l' */
+ { 0x72, 0x70 }, /* 'r' => 'p' */
+ { 0x73, 0x6f }, /* 's' => 'o' */
+ { 0x74, 0x79 }, /* 't' => 'y' */
+ { 0x75, 0x67 }, /* 'u' => 'g' */
+ { 0x76, 0x6b }, /* 'v' => 'k' */
+ { 0x77, 0x2c }, /* 'w' => ',' */
+ { 0x78, 0x71 }, /* 'x' => 'q' */
+ { 0x79, 0x66 }, /* 'y' => 'f' */
+ { 0x7b, 0x2a }, /* '{' => '*' */
+ { 0x7c, 0x3e }, /* '|' => '>' */
+ { 0x7d, 0x5e }, /* '}' => '^' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_pl.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_pl.c
new file mode 100644
index 00000000..51822e07
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_pl.c
@@ -0,0 +1,15 @@
+/** @file
+ *
+ * "pl" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "pl" keyboard mapping */
+struct key_mapping pl_mapping[] __keymap = {
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_pt.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_pt.c
new file mode 100644
index 00000000..a8e44b6a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_pt.c
@@ -0,0 +1,29 @@
+/** @file
+ *
+ * "pt" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "pt" keyboard mapping */
+struct key_mapping pt_mapping[] __keymap = {
+ { 0x1c, 0x1d }, /* 0x1c => 0x1d */
+ { 0x1d, 0x1b }, /* 0x1d => 0x1b */
+ { 0x22, 0x5e }, /* '"' => '^' */
+ { 0x27, 0x7e }, /* '\'' => '~' */
+ { 0x2f, 0x3b }, /* '/' => ';' */
+ { 0x3f, 0x3a }, /* '?' => ':' */
+ { 0x5b, 0x27 }, /* '[' => '\'' */
+ { 0x5c, 0x5d }, /* '\\' => ']' */
+ { 0x5d, 0x5b }, /* ']' => '[' */
+ { 0x60, 0x27 }, /* '`' => '\'' */
+ { 0x7b, 0x60 }, /* '{' => '`' */
+ { 0x7c, 0x7d }, /* '|' => '}' */
+ { 0x7d, 0x7b }, /* '}' => '{' */
+ { 0x7e, 0x22 }, /* '~' => '"' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_ro.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_ro.c
new file mode 100644
index 00000000..0eef7d53
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_ro.c
@@ -0,0 +1,15 @@
+/** @file
+ *
+ * "ro" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "ro" keyboard mapping */
+struct key_mapping ro_mapping[] __keymap = {
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_ru.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_ru.c
new file mode 100644
index 00000000..422b6c69
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_ru.c
@@ -0,0 +1,15 @@
+/** @file
+ *
+ * "ru" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "ru" keyboard mapping */
+struct key_mapping ru_mapping[] __keymap = {
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_sg.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_sg.c
new file mode 100644
index 00000000..0b082092
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_sg.c
@@ -0,0 +1,41 @@
+/** @file
+ *
+ * "sg" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "sg" keyboard mapping */
+struct key_mapping sg_mapping[] __keymap = {
+ { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */
+ { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */
+ { 0x21, 0x2b }, /* '!' => '+' */
+ { 0x23, 0x2a }, /* '#' => '*' */
+ { 0x24, 0x34 }, /* '$' => '4' */
+ { 0x26, 0x2f }, /* '&' => '/' */
+ { 0x28, 0x29 }, /* '(' => ')' */
+ { 0x29, 0x3d }, /* ')' => '=' */
+ { 0x2a, 0x28 }, /* '*' => '(' */
+ { 0x2b, 0x60 }, /* '+' => '`' */
+ { 0x2d, 0x27 }, /* '-' => '\'' */
+ { 0x2f, 0x2d }, /* '/' => '-' */
+ { 0x3c, 0x3b }, /* '<' => ';' */
+ { 0x3d, 0x5e }, /* '=' => '^' */
+ { 0x3e, 0x3a }, /* '>' => ':' */
+ { 0x3f, 0x5f }, /* '?' => '_' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x59, 0x5a }, /* 'Y' => 'Z' */
+ { 0x5a, 0x59 }, /* 'Z' => 'Y' */
+ { 0x5c, 0x24 }, /* '\\' => '$' */
+ { 0x5e, 0x26 }, /* '^' => '&' */
+ { 0x5f, 0x3f }, /* '_' => '?' */
+ { 0x79, 0x7a }, /* 'y' => 'z' */
+ { 0x7a, 0x79 }, /* 'z' => 'y' */
+ { 0x7c, 0x24 }, /* '|' => '$' */
+ { 0x7d, 0x21 }, /* '}' => '!' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_sr.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_sr.c
new file mode 100644
index 00000000..0552f4d9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_sr.c
@@ -0,0 +1,35 @@
+/** @file
+ *
+ * "sr" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "sr" keyboard mapping */
+struct key_mapping sr_mapping[] __keymap = {
+ { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */
+ { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */
+ { 0x26, 0x2f }, /* '&' => '/' */
+ { 0x28, 0x29 }, /* '(' => ')' */
+ { 0x29, 0x3d }, /* ')' => '=' */
+ { 0x2a, 0x28 }, /* '*' => '(' */
+ { 0x2b, 0x2a }, /* '+' => '*' */
+ { 0x2d, 0x27 }, /* '-' => '\'' */
+ { 0x2f, 0x2d }, /* '/' => '-' */
+ { 0x3c, 0x3b }, /* '<' => ';' */
+ { 0x3d, 0x2b }, /* '=' => '+' */
+ { 0x3e, 0x3a }, /* '>' => ':' */
+ { 0x3f, 0x5f }, /* '?' => '_' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x59, 0x5a }, /* 'Y' => 'Z' */
+ { 0x5a, 0x59 }, /* 'Z' => 'Y' */
+ { 0x5e, 0x26 }, /* '^' => '&' */
+ { 0x5f, 0x3f }, /* '_' => '?' */
+ { 0x79, 0x7a }, /* 'y' => 'z' */
+ { 0x7a, 0x79 }, /* 'z' => 'y' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_th.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_th.c
new file mode 100644
index 00000000..e8b44d1e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_th.c
@@ -0,0 +1,15 @@
+/** @file
+ *
+ * "th" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "th" keyboard mapping */
+struct key_mapping th_mapping[] __keymap = {
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_ua.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_ua.c
new file mode 100644
index 00000000..1106a8b2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_ua.c
@@ -0,0 +1,15 @@
+/** @file
+ *
+ * "ua" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "ua" keyboard mapping */
+struct key_mapping ua_mapping[] __keymap = {
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_uk.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_uk.c
new file mode 100644
index 00000000..6550d8ee
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_uk.c
@@ -0,0 +1,19 @@
+/** @file
+ *
+ * "uk" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "uk" keyboard mapping */
+struct key_mapping uk_mapping[] __keymap = {
+ { 0x22, 0x40 }, /* '"' => '@' */
+ { 0x40, 0x22 }, /* '@' => '"' */
+ { 0x5c, 0x23 }, /* '\\' => '#' */
+ { 0x7c, 0x7e }, /* '|' => '~' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_us.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_us.c
new file mode 100644
index 00000000..73d01a30
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_us.c
@@ -0,0 +1,15 @@
+/** @file
+ *
+ * "us" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "us" keyboard mapping */
+struct key_mapping us_mapping[] __keymap = {
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_wo.c b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_wo.c
new file mode 100644
index 00000000..b4535761
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/keymap/keymap_wo.c
@@ -0,0 +1,55 @@
+/** @file
+ *
+ * "wo" keyboard mapping
+ *
+ * This file is automatically generated; do not edit
+ *
+ */
+
+FILE_LICENCE ( PUBLIC_DOMAIN );
+
+#include <ipxe/keymap.h>
+
+/** "wo" keyboard mapping */
+struct key_mapping wo_mapping[] __keymap = {
+ { 0x01, 0x11 }, /* Ctrl-A => Ctrl-Q */
+ { 0x11, 0x01 }, /* Ctrl-Q => Ctrl-A */
+ { 0x17, 0x1a }, /* Ctrl-W => Ctrl-Z */
+ { 0x1a, 0x17 }, /* Ctrl-Z => Ctrl-W */
+ { 0x21, 0x31 }, /* '!' => '1' */
+ { 0x23, 0x33 }, /* '#' => '3' */
+ { 0x24, 0x34 }, /* '$' => '4' */
+ { 0x25, 0x35 }, /* '%' => '5' */
+ { 0x26, 0x37 }, /* '&' => '7' */
+ { 0x28, 0x39 }, /* '(' => '9' */
+ { 0x29, 0x30 }, /* ')' => '0' */
+ { 0x2a, 0x38 }, /* '*' => '8' */
+ { 0x2c, 0x3b }, /* ',' => ';' */
+ { 0x2d, 0x29 }, /* '-' => ')' */
+ { 0x2e, 0x3a }, /* '.' => ':' */
+ { 0x2f, 0x21 }, /* '/' => '!' */
+ { 0x31, 0x26 }, /* '1' => '&' */
+ { 0x33, 0x22 }, /* '3' => '"' */
+ { 0x34, 0x27 }, /* '4' => '\'' */
+ { 0x35, 0x28 }, /* '5' => '(' */
+ { 0x36, 0x2d }, /* '6' => '-' */
+ { 0x38, 0x5f }, /* '8' => '_' */
+ { 0x3a, 0x4d }, /* ':' => 'M' */
+ { 0x3b, 0x6d }, /* ';' => 'm' */
+ { 0x3c, 0x2e }, /* '<' => '.' */
+ { 0x3e, 0x2f }, /* '>' => '/' */
+ { 0x40, 0x32 }, /* '@' => '2' */
+ { 0x41, 0x51 }, /* 'A' => 'Q' */
+ { 0x4d, 0x3f }, /* 'M' => '?' */
+ { 0x51, 0x41 }, /* 'Q' => 'A' */
+ { 0x57, 0x5a }, /* 'W' => 'Z' */
+ { 0x5a, 0x57 }, /* 'Z' => 'W' */
+ { 0x5d, 0x24 }, /* ']' => '$' */
+ { 0x5e, 0x36 }, /* '^' => '6' */
+ { 0x61, 0x71 }, /* 'a' => 'q' */
+ { 0x6d, 0x2c }, /* 'm' => ',' */
+ { 0x71, 0x61 }, /* 'q' => 'a' */
+ { 0x77, 0x7a }, /* 'w' => 'z' */
+ { 0x7a, 0x77 }, /* 'z' => 'w' */
+ { 0x7e, 0x25 }, /* '~' => '%' */
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/linux_args.c b/src/VBox/Devices/PC/ipxe/src/hci/linux_args.c
new file mode 100644
index 00000000..0bce4af9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/linux_args.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <hci/linux_args.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdio.h>
+#include <ipxe/settings.h>
+#include <ipxe/linux.h>
+#include <ipxe/malloc.h>
+#include <ipxe/init.h>
+
+/** Saved argc */
+static int saved_argc = 0;
+/** Saved argv */
+static char ** saved_argv;
+
+/**
+ * Save argc and argv for later access.
+ *
+ * To be called by linuxprefix
+ */
+__asmcall void save_args(int argc, char **argv)
+{
+ saved_argc = argc;
+ saved_argv = argv;
+}
+
+/** Supported command-line options */
+static struct option options[] = {
+ {"net", 1, 0, 'n'},
+ {"settings", 1, 0, 's'},
+ {0, 0, 0, 0}
+};
+
+/**
+ * Parse k1=v1[,k2=v2]* into linux_settings
+ */
+static int parse_kv(char *kv, struct list_head *list)
+{
+ char *token;
+ char *name;
+ char *value;
+ struct linux_setting *setting;
+
+ while ((token = strsep(&kv, ",")) != NULL) {
+ name = strsep(&token, "=");
+ if (name == NULL)
+ continue;
+ value = token;
+ if (value == NULL) {
+ DBG("Bad parameter: '%s'\n", name);
+ continue;
+ }
+
+ setting = malloc(sizeof(*setting));
+
+ if (! setting)
+ return -1;
+
+ setting->name = name;
+ setting->value = value;
+ setting->applied = 0;
+ list_add(&setting->list, list);
+ }
+
+ return 0;
+}
+
+/**
+ * Parse --net arguments
+ *
+ * Format is --net driver_name[,name=value]*
+ */
+static int parse_net_args(char *args)
+{
+ char *driver;
+ struct linux_device_request *dev_request;
+ int rc;
+
+ driver = strsep(&args, ",");
+
+ if (strlen(driver) == 0) {
+ printf("Missing driver name");
+ return -1;
+ }
+
+ dev_request = malloc(sizeof(*dev_request));
+
+ dev_request->driver = driver;
+ INIT_LIST_HEAD(&dev_request->settings);
+ list_add_tail(&dev_request->list, &linux_device_requests);
+
+ /* Parse rest of the settings */
+ rc = parse_kv(args, &dev_request->settings);
+
+ if (rc)
+ printf("Parsing net settings failed");
+
+ return rc;
+}
+
+/**
+ * Parse --settings arguments
+ *
+ * Format is --settings name=value[,name=value]*
+ */
+static int parse_settings_args(char *args)
+{
+ return parse_kv(args, &linux_global_settings);
+}
+
+
+/** Parse passed command-line arguments */
+void linux_args_parse()
+{
+ int c;
+ int rc;
+
+ reset_getopt();
+ while (1) {
+ int option_index = 0;
+
+ c = getopt_long(saved_argc, saved_argv, "", options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'n':
+ if ((rc = parse_net_args(optarg)) != 0)
+ return;
+ break;
+ case 's':
+ if ((rc = parse_settings_args(optarg)) != 0)
+ return;
+ break;
+ default:
+ return;
+ }
+ }
+
+ return;
+}
+
+/** Clean up requests and settings */
+void linux_args_cleanup(int flags __unused)
+{
+ struct linux_device_request *request;
+ struct linux_device_request *rtmp;
+ struct linux_setting *setting;
+ struct linux_setting *stmp;
+
+ /* Clean up requests and their settings */
+ list_for_each_entry_safe(request, rtmp, &linux_device_requests, list) {
+ list_for_each_entry_safe(setting, stmp, &request->settings, list) {
+ list_del(&setting->list);
+ free(setting);
+ }
+ list_del(&request->list);
+ free(request);
+ }
+
+ /* Clean up global settings */
+ list_for_each_entry_safe(setting, stmp, &linux_global_settings, list) {
+ list_del(&setting->list);
+ free(setting);
+ }
+}
+
+struct startup_fn startup_linux_args __startup_fn(STARTUP_EARLY) = {
+ .startup = linux_args_parse,
+ .shutdown = linux_args_cleanup,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/alert.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/alert.c
new file mode 100644
index 00000000..00e959a8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/alert.c
@@ -0,0 +1,18 @@
+#include <curses.h>
+#include <stdio.h>
+
+/** @file
+ *
+ * MuCurses alert functions
+ *
+ */
+
+/**
+ * Audible signal
+ *
+ * @ret rc return status code
+ */
+int beep ( void ) {
+ printf("\a");
+ return OK;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/ansi_screen.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/ansi_screen.c
new file mode 100644
index 00000000..d952e5f2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/ansi_screen.c
@@ -0,0 +1,86 @@
+#include <stdio.h>
+#include <curses.h>
+#include <ipxe/console.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+static void ansiscr_reset(struct _curses_screen *scr) __nonnull;
+static void ansiscr_movetoyx(struct _curses_screen *scr,
+ unsigned int y, unsigned int x) __nonnull;
+static void ansiscr_putc(struct _curses_screen *scr, chtype c) __nonnull;
+
+unsigned short _COLS = 80;
+unsigned short _LINES = 24;
+
+static unsigned int saved_usage;
+
+static void ansiscr_reset ( struct _curses_screen *scr ) {
+ /* Reset terminal attributes and clear screen */
+ scr->attrs = 0;
+ scr->curs_x = 0;
+ scr->curs_y = 0;
+ printf ( "\033[0m" );
+}
+
+static void ansiscr_init ( struct _curses_screen *scr ) {
+ saved_usage = console_set_usage ( CONSOLE_USAGE_TUI );
+ ansiscr_reset ( scr );
+}
+
+static void ansiscr_exit ( struct _curses_screen *scr ) {
+ ansiscr_reset ( scr );
+ console_set_usage ( saved_usage );
+}
+
+static void ansiscr_movetoyx ( struct _curses_screen *scr,
+ unsigned int y, unsigned int x ) {
+ if ( ( x != scr->curs_x ) || ( y != scr->curs_y ) ) {
+ /* ANSI escape sequence to update cursor position */
+ printf ( "\033[%d;%dH", ( y + 1 ), ( x + 1 ) );
+ scr->curs_x = x;
+ scr->curs_y = y;
+ }
+}
+
+static void ansiscr_putc ( struct _curses_screen *scr, chtype c ) {
+ unsigned int character = ( c & A_CHARTEXT );
+ attr_t attrs = ( c & ( A_ATTRIBUTES | A_COLOR ) );
+ int bold = ( attrs & A_BOLD );
+ attr_t cpair = PAIR_NUMBER ( attrs );
+ short fcol;
+ short bcol;
+
+ /* Update attributes if changed */
+ if ( attrs != scr->attrs ) {
+ scr->attrs = attrs;
+ pair_content ( cpair, &fcol, &bcol );
+ /* ANSI escape sequence to update character attributes */
+ printf ( "\033[0;%d;3%d;4%dm", ( bold ? 1 : 22 ), fcol, bcol );
+ }
+
+ /* Print the actual character */
+ putchar ( character );
+
+ /* Update expected cursor position */
+ if ( ++(scr->curs_x) == _COLS ) {
+ scr->curs_x = 0;
+ ++scr->curs_y;
+ }
+}
+
+static int ansiscr_getc ( struct _curses_screen *scr __unused ) {
+ return getchar();
+}
+
+static bool ansiscr_peek ( struct _curses_screen *scr __unused ) {
+ return iskey();
+}
+
+SCREEN _ansi_screen = {
+ .init = ansiscr_init,
+ .exit = ansiscr_exit,
+ .movetoyx = ansiscr_movetoyx,
+ .putc = ansiscr_putc,
+ .getc = ansiscr_getc,
+ .peek = ansiscr_peek,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/clear.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/clear.c
new file mode 100644
index 00000000..79b296cf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/clear.c
@@ -0,0 +1,90 @@
+#include <curses.h>
+#include "mucurses.h"
+#include "cursor.h"
+
+/** @file
+ *
+ * MuCurses clearing functions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Clear a window to the bottom from current cursor position
+ *
+ * @v *win subject window
+ * @ret rc return status code
+ */
+int wclrtobot ( WINDOW *win ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos( win, &pos );
+ do {
+ _wputc( win, ' ', WRAP );
+ } while ( win->curs_y + win->curs_x );
+ _restore_curs_pos( win, &pos );
+
+ return OK;
+}
+
+/**
+ * Clear a window to the end of the current line
+ *
+ * @v *win subject window
+ * @ret rc return status code
+ */
+int wclrtoeol ( WINDOW *win ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos( win, &pos );
+ while ( ( win->curs_y - pos.y ) == 0 ) {
+ _wputc( win, ' ', WRAP );
+ }
+ _restore_curs_pos( win, &pos );
+
+ return OK;
+}
+
+/**
+ * Delete character under the cursor in a window
+ *
+ * @v *win subject window
+ * @ret rc return status code
+ */
+int wdelch ( WINDOW *win ) {
+ _wputc( win, ' ', NOWRAP );
+ _wcursback( win );
+
+ return OK;
+}
+
+/**
+ * Delete line under a window's cursor
+ *
+ * @v *win subject window
+ * @ret rc return status code
+ */
+int wdeleteln ( WINDOW *win ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos( win, &pos );
+ /* let's just set the cursor to the beginning of the line and
+ let wclrtoeol do the work :) */
+ wmove( win, win->curs_y, 0 );
+ wclrtoeol( win );
+ _restore_curs_pos( win, &pos );
+ return OK;
+}
+
+/**
+ * Completely clear a window
+ *
+ * @v *win subject window
+ * @ret rc return status code
+ */
+int werase ( WINDOW *win ) {
+ wmove( win, 0, 0 );
+ wclrtobot( win );
+ return OK;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/colour.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/colour.c
new file mode 100644
index 00000000..c1359c86
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/colour.c
@@ -0,0 +1,66 @@
+#include <curses.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct colour_pair {
+ short fcol;
+ short bcol;
+};
+
+static struct colour_pair cpairs[COLOUR_PAIRS] = {
+ [0] = { COLOUR_WHITE, COLOUR_BLACK },
+};
+
+/**
+ * Identify the RGB components of a given colour value
+ *
+ * @v colour colour value
+ * @v *red address to store red component
+ * @v *green address to store green component
+ * @v *blue address to store blue component
+ * @ret rc return status code
+ */
+int colour_content ( short colour, short *red, short *green, short *blue ) {
+ *red = ( ( colour & COLOUR_RED ) ? 1 : 0 );
+ *green = ( ( colour & COLOUR_GREEN ) ? 1 : 0 );
+ *blue = ( ( colour & COLOUR_BLUE ) ? 1 : 0 );
+ return OK;
+}
+
+/**
+ * Initialise colour pair
+ *
+ * @v pair colour pair number
+ * @v fcol foreground colour
+ * @v bcol background colour
+ */
+int init_pair ( short pair, short fcol, short bcol ) {
+ struct colour_pair *cpair;
+
+ if ( ( pair < 1 ) || ( pair >= COLOUR_PAIRS ) )
+ return ERR;
+
+ cpair = &cpairs[pair];
+ cpair->fcol = fcol;
+ cpair->bcol = bcol;
+ return OK;
+}
+
+/**
+ * Get colours of colour pair
+ *
+ * @v pair colour pair number
+ * @ret fcol foreground colour
+ * @ret bcol background colour
+ */
+int pair_content ( short pair, short *fcol, short *bcol ) {
+ struct colour_pair *cpair;
+
+ if ( ( pair < 0 ) || ( pair >= COLOUR_PAIRS ) )
+ return ERR;
+
+ cpair = &cpairs[pair];
+ *fcol = cpair->fcol;
+ *bcol = cpair->bcol;
+ return OK;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/cursor.h b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/cursor.h
new file mode 100644
index 00000000..16b7d27c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/cursor.h
@@ -0,0 +1,37 @@
+#ifndef CURSOR_H
+#define CURSOR_H
+
+/** @file
+ *
+ * MuCurses cursor implementation specific header file
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct cursor_pos {
+ unsigned int y, x;
+};
+
+/**
+ * Restore cursor position from encoded backup variable
+ *
+ * @v *win window on which to operate
+ * @v *pos pointer to struct in which original cursor position is stored
+ */
+static inline void _restore_curs_pos ( WINDOW *win, struct cursor_pos *pos ) {
+ wmove ( win, pos->y, pos->x );
+}
+
+/**
+ * Store cursor position for later restoration
+ *
+ * @v *win window on which to operate
+ * @v *pos pointer to struct in which to store cursor position
+ */
+static inline void _store_curs_pos ( WINDOW *win, struct cursor_pos *pos ) {
+ pos->y = win->curs_y;
+ pos->x = win->curs_x;
+}
+
+#endif /* CURSOR_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/edging.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/edging.c
new file mode 100644
index 00000000..eccd3242
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/edging.c
@@ -0,0 +1,111 @@
+#include <curses.h>
+#include "mucurses.h"
+#include "cursor.h"
+
+/** @file
+ *
+ * MuCurses edging functions
+ *
+ */
+
+/**
+ * Draw borders from single-byte characters and renditions around a
+ * window
+ *
+ * @v *win window to be bordered
+ * @v verch vertical chtype
+ * @v horch horizontal chtype
+ * @ret rc return status code
+ */
+int box ( WINDOW *win, chtype verch, chtype horch ) {
+ chtype corner = '+' | win->attrs; /* default corner character */
+ return wborder( win, verch, verch, horch, horch,
+ corner, corner, corner, corner );
+}
+
+/**
+ * Draw borders from single-byte characters and renditions around a
+ * window
+ *
+ * @v *win window to be bordered
+ * @v ls left side
+ * @v rs right side
+ * @v ts top
+ * @v bs bottom
+ * @v tl top left corner
+ * @v tr top right corner
+ * @v bl bottom left corner
+ * @v br bottom right corner
+ * @ret rc return status code
+ */
+int wborder ( WINDOW *win, chtype ls, chtype rs,
+ chtype ts, chtype bs, chtype tl,
+ chtype tr, chtype bl, chtype br ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos( win, &pos );
+ wmove(win,0,0);
+
+ _wputch(win,tl,WRAP);
+ while ( ( win->width - 1 ) - win->curs_x ) {
+ _wputch(win,ts,WRAP);
+ }
+ _wputch(win,tr,WRAP);
+
+ while ( ( win->height - 1 ) - win->curs_y ) {
+ _wputch(win,ls,WRAP);
+ wmove(win,win->curs_y,(win->width)-1);
+ _wputch(win,rs,WRAP);
+ }
+
+ _wputch(win,bl,WRAP);
+ while ( ( win->width -1 ) - win->curs_x ) {
+ _wputch(win,bs,WRAP);
+ }
+ _wputch(win,br,NOWRAP); /* do not wrap last char to leave
+ cursor in last position */
+ _restore_curs_pos( win, &pos );
+
+ return OK;
+}
+
+/**
+ * Create a horizontal line in a window
+ *
+ * @v *win subject window
+ * @v ch rendition and character
+ * @v n max number of chars (wide) to render
+ * @ret rc return status code
+ */
+int whline ( WINDOW *win, chtype ch, int n ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos ( win, &pos );
+ while ( ( win->curs_x - win->width ) && n-- ) {
+ _wputch ( win, ch, NOWRAP );
+ }
+ _restore_curs_pos ( win, &pos );
+
+ return OK;
+}
+
+/**
+ * Create a vertical line in a window
+ *
+ * @v *win subject window
+ * @v ch rendition and character
+ * @v n max number of chars (high) to render
+ * @ret rc return status code
+ */
+int wvline ( WINDOW *win, chtype ch, int n ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos ( win, &pos );
+ while ( ( win->curs_y - win->height ) && n-- ) {
+ _wputch ( win, ch, NOWRAP );
+ wmove( win, ++(win->curs_y), pos.x);
+ }
+ _restore_curs_pos ( win, &pos );
+
+ return OK;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/kb.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/kb.c
new file mode 100644
index 00000000..cada7291
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/kb.c
@@ -0,0 +1,143 @@
+#include <curses.h>
+#include <stddef.h>
+#include <unistd.h>
+#include "mucurses.h"
+
+/** @file
+ *
+ * MuCurses keyboard input handling functions
+ */
+
+#define INPUT_DELAY 200 // half-blocking delay timer resolution (ms)
+#define INPUT_DELAY_TIMEOUT 1000 // half-blocking delay timeout
+
+int m_delay; /*
+ < 0 : blocking read
+ 0 : non-blocking read
+ > 0 : timed blocking read
+ */
+bool m_echo;
+bool m_cbreak;
+
+static int _wgetc ( WINDOW *win ) {
+ int timer, c;
+
+ if ( win == NULL )
+ return ERR;
+
+ timer = INPUT_DELAY_TIMEOUT;
+ while ( ! win->scr->peek( win->scr ) ) {
+ if ( m_delay == 0 ) // non-blocking read
+ return ERR;
+ if ( timer > 0 ) { // time-limited blocking read
+ if ( m_delay > 0 )
+ timer -= INPUT_DELAY;
+ mdelay( INPUT_DELAY );
+ } else { return ERR; } // non-blocking read
+ }
+
+ c = win->scr->getc( win->scr );
+
+ if ( m_echo && ( c >= 32 && c <= 126 ) ) // printable ASCII characters
+ _wputch( win, (chtype) ( c | win->attrs ), WRAP );
+
+ return c;
+}
+
+/**
+ * Pop a character from the FIFO into a window
+ *
+ * @v *win window in which to echo input
+ * @ret c char from input stream
+ */
+int wgetch ( WINDOW *win ) {
+ int c;
+
+ c = _wgetc( win );
+
+ if ( m_echo ) {
+ if ( c >= KEY_MIN ) {
+ switch(c) {
+ case KEY_LEFT :
+ case KEY_BACKSPACE :
+ _wcursback( win );
+ wdelch( win );
+ break;
+ default :
+ beep();
+ break;
+ }
+ } else {
+ _wputch( win, (chtype)( c | win->attrs ), WRAP );
+ }
+ }
+
+ return c;
+}
+
+/**
+ * Read at most n characters from the FIFO into a window
+ *
+ * @v *win window in which to echo input
+ * @v *str pointer to string in which to store result
+ * @v n maximum number of characters to read into string (inc. NUL)
+ * @ret rc return status code
+ */
+int wgetnstr ( WINDOW *win, char *str, int n ) {
+ char *_str;
+ int c;
+
+ if ( n == 0 ) {
+ str = '\0';
+ return OK;
+ }
+
+ _str = str;
+
+ while ( ( c = _wgetc( win ) ) != ERR ) {
+ /* termination enforcement - don't let us go past the
+ end of the allocated buffer... */
+ if ( n == 0 && ( c >= 32 && c <= 126 ) ) {
+ _wcursback( win );
+ wdelch( win );
+ } else {
+ if ( c >= KEY_MIN ) {
+ switch(c) {
+ case KEY_LEFT :
+ case KEY_BACKSPACE :
+ _wcursback( win );
+ wdelch( win );
+ break;
+ case KEY_ENTER :
+ *_str = '\0';
+ return OK;
+ default :
+ beep();
+ break;
+ }
+ }
+ if ( c >= 32 && c <= 126 ) {
+ *(_str++) = c; n--;
+ }
+ }
+ }
+
+ return ERR;
+}
+
+
+/**
+ *
+ */
+int echo ( void ) {
+ m_echo = TRUE;
+ return OK;
+}
+
+/**
+ *
+ */
+int noecho ( void ) {
+ m_echo = FALSE;
+ return OK;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/mucurses.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/mucurses.c
new file mode 100644
index 00000000..ab9a6535
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/mucurses.c
@@ -0,0 +1,146 @@
+#include <curses.h>
+#include "mucurses.h"
+
+/** @file
+ *
+ * MuCurses core functions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+static void _wupdcurs ( WINDOW *win ) __nonnull;
+void _wputch ( WINDOW *win, chtype ch, int wrap ) __nonnull;
+void _wputc ( WINDOW *win, char c, int wrap ) __nonnull;
+void _wcursback ( WINDOW *win ) __nonnull;
+void _wputchstr ( WINDOW *win, const chtype *chstr, int wrap, int n ) __nonnull;
+void _wputstr ( WINDOW *win, const char *str, int wrap, int n ) __nonnull;
+int wmove ( WINDOW *win, int y, int x ) __nonnull;
+
+WINDOW _stdscr = {
+ .attrs = A_DEFAULT,
+ .ori_y = 0,
+ .ori_x = 0,
+ .curs_y = 0,
+ .curs_x = 0,
+ .scr = &_ansi_screen,
+};
+
+/*
+ * Primitives
+ */
+
+/**
+ * Update cursor position
+ *
+ * @v *win window in which to update position
+ */
+static void _wupdcurs ( WINDOW *win ) {
+ win->scr->movetoyx ( win->scr, win->ori_y + win->curs_y,
+ win->ori_x + win->curs_x );
+}
+
+/**
+ * Write a single character rendition to a window
+ *
+ * @v *win window in which to write
+ * @v ch character rendition to write
+ * @v wrap wrap "switch"
+ */
+void _wputch ( WINDOW *win, chtype ch, int wrap ) {
+ /* make sure we set the screen cursor to the right position
+ first! */
+ _wupdcurs(win);
+ win->scr->putc(win->scr, ch);
+ if ( ++(win->curs_x) - win->width == 0 ) {
+ if ( wrap == WRAP ) {
+ win->curs_x = 0;
+ /* specification says we should really scroll,
+ but we have no buffer to scroll with, so we
+ can only overwrite back at the beginning of
+ the window */
+ if ( ++(win->curs_y) - win->height == 0 )
+ win->curs_y = 0;
+ } else {
+ (win->curs_x)--;
+ }
+ }
+}
+
+/**
+ * Write a single character to a window
+ *
+ * @v *win window in which to write
+ * @v c character rendition to write
+ * @v wrap wrap "switch"
+ */
+void _wputc ( WINDOW *win, char c, int wrap ) {
+ _wputch ( win, ( c | win->attrs ), wrap );
+}
+
+/**
+ * Retreat the cursor back one position (useful for a whole host of
+ * ops)
+ *
+ * @v *win window in which to retreat
+ */
+void _wcursback ( WINDOW *win ) {
+ if ( win->curs_x == 0 ) {
+ if ( win->curs_y == 0 )
+ win->curs_y = win->height - 1;
+ win->curs_x = win->width = 1;
+ } else {
+ win->curs_x--;
+ }
+
+ _wupdcurs(win);
+}
+
+/**
+ * Write a chtype string to a window
+ *
+ * @v *win window in which to write
+ * @v *chstr chtype string
+ * @v wrap wrap "switch"
+ * @v n write at most n chtypes
+ */
+void _wputchstr ( WINDOW *win, const chtype *chstr, int wrap, int n ) {
+ for ( ; *chstr && n-- ; chstr++ ) {
+ _wputch(win,*chstr,wrap);
+ }
+}
+
+/**
+ * Write a standard c-style string to a window
+ *
+ * @v *win window in which to write
+ * @v *str string
+ * @v wrap wrap "switch"
+ * @v n write at most n chars from *str
+ */
+void _wputstr ( WINDOW *win, const char *str, int wrap, int n ) {
+ for ( ; *str && n-- ; str++ ) {
+ _wputc ( win, *str, wrap );
+ }
+}
+
+/**
+ * Move a window's cursor to the specified position
+ *
+ * @v *win window to be operated on
+ * @v y Y position
+ * @v x X position
+ * @ret rc return status code
+ */
+int wmove ( WINDOW *win, int y, int x ) {
+ /* chech for out-of-bounds errors */
+ if ( ( (unsigned)y >= win->height ) ||
+ ( (unsigned)x >= win->width ) ) {
+ return ERR;
+ }
+
+ win->curs_y = y;
+ win->curs_x = x;
+ _wupdcurs(win);
+ return OK;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/mucurses.h b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/mucurses.h
new file mode 100644
index 00000000..7ac1086a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/mucurses.h
@@ -0,0 +1,23 @@
+#ifndef _MUCURSES_H
+#define _MUCURSES_H
+
+/** @file
+ *
+ * MuCurses core implementation specific header file
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#define WRAP 0
+#define NOWRAP 1
+
+extern SCREEN _ansi_screen;
+
+extern void _wputch ( WINDOW *win, chtype ch, int wrap ) __nonnull;
+extern void _wputc ( WINDOW *win, char c, int wrap ) __nonnull;
+extern void _wputchstr ( WINDOW *win, const chtype *chstr, int wrap, int n ) __nonnull;
+extern void _wputstr ( WINDOW *win, const char *str, int wrap, int n ) __nonnull;
+extern void _wcursback ( WINDOW *win ) __nonnull;
+
+#endif /* _MUCURSES_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/print.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/print.c
new file mode 100644
index 00000000..9c682588
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/print.c
@@ -0,0 +1,86 @@
+#include <curses.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <ipxe/vsprintf.h>
+#include "mucurses.h"
+
+/** @file
+ *
+ * MuCurses printing functions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Add a single-byte character and rendition to a window and advance
+ * the cursor
+ *
+ * @v *win window to be rendered in
+ * @v ch character to be added at cursor
+ * @ret rc return status code
+ */
+int waddch ( WINDOW *win, const chtype ch ) {
+ _wputch( win, ch, WRAP );
+ return OK;
+}
+
+/**
+ * Add string of single-byte characters to a window
+ *
+ * @v *win window to be rendered in
+ * @v *str standard c-style string
+ * @v n max number of chars from string to render
+ * @ret rc return status code
+ */
+int waddnstr ( WINDOW *win, const char *str, int n ) {
+ _wputstr( win, str, WRAP, n );
+ return OK;
+}
+
+struct printw_context {
+ struct printf_context ctx;
+ WINDOW *win;
+};
+
+static void _printw_handler ( struct printf_context *ctx, unsigned int c ) {
+ struct printw_context *wctx =
+ container_of ( ctx, struct printw_context, ctx );
+
+ _wputch( wctx->win, c | wctx->win->attrs, WRAP );
+}
+
+/**
+ * Print formatted output in a window
+ *
+ * @v *win subject window
+ * @v *fmt formatted string
+ * @v varglist argument list
+ * @ret rc return status code
+ */
+int vw_printw ( WINDOW *win, const char *fmt, va_list varglist ) {
+ struct printw_context wctx;
+
+ wctx.win = win;
+ wctx.ctx.handler = _printw_handler;
+ vcprintf ( &(wctx.ctx), fmt, varglist );
+ return OK;
+}
+
+/**
+ * Print formatted output to a window
+ *
+ * @v *win subject window
+ * @v *fmt formatted string
+ * @v ... string arguments
+ * @ret rc return status code
+ */
+int wprintw ( WINDOW *win, const char *fmt, ... ) {
+ va_list args;
+ int i;
+
+ va_start ( args, fmt );
+ i = vw_printw ( win, fmt, args );
+ va_end ( args );
+ return i;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/print_nadv.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/print_nadv.c
new file mode 100644
index 00000000..ee472e68
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/print_nadv.c
@@ -0,0 +1,26 @@
+#include <curses.h>
+#include "mucurses.h"
+#include "cursor.h"
+
+/** @file
+ *
+ * MuCurses printing functions (no cursor advance)
+ *
+ */
+
+/**
+ * Add string of single-byte characters and renditions to a window
+ *
+ * @v *win window to be rendered in
+ * @v *chstr pointer to first chtype in "string"
+ * @v n max number of chars from chstr to render
+ * @ret rc return status code
+ */
+int waddchnstr ( WINDOW *win, const chtype *chstr, int n ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos( win, &pos );
+ _wputchstr( win, chstr, NOWRAP, n );
+ _restore_curs_pos( win, &pos );
+ return OK;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/slk.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/slk.c
new file mode 100644
index 00000000..600658e7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/slk.c
@@ -0,0 +1,363 @@
+#include <curses.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "mucurses.h"
+#include "cursor.h"
+
+/** @file
+ *
+ * Soft label key functions
+ */
+
+#define MIN_SPACE_SIZE 2
+
+#define SLK_MAX_LABEL_LEN 8
+
+#define SLK_MAX_NUM_LABELS 12
+
+#define SLK_MAX_NUM_SPACES 2
+
+struct _softlabel {
+ // label string
+ char label[SLK_MAX_LABEL_LEN];
+ /* Format of soft label
+ 0: left justify
+ 1: centre justify
+ 2: right justify
+ */
+ unsigned int fmt;
+};
+
+struct _softlabelkeys {
+ struct _softlabel fkeys[SLK_MAX_NUM_LABELS];
+ attr_t attrs;
+ /* Soft label layout format
+ 0: 3-2-3
+ 1: 4-4
+ 2: 4-4-4
+ 3: 4-4-4 with index line
+ */
+ unsigned int fmt;
+ unsigned int max_label_len;
+ unsigned int maj_space_len;
+ unsigned int num_labels;
+ unsigned int num_spaces;
+ unsigned int spaces[SLK_MAX_NUM_SPACES];
+ struct cursor_pos saved_cursor;
+ attr_t saved_attrs;
+ short saved_pair;
+};
+
+static struct _softlabelkeys *slks;
+
+/*
+ I either need to break the primitives here, or write a collection of
+ functions specifically for SLKs that directly access the screen
+ functions - since this technically isn't part of stdscr, I think
+ this should be ok...
+ */
+
+static void _enter_slk ( void ) {
+ _store_curs_pos ( stdscr, &slks->saved_cursor );
+ wattr_get ( stdscr, &slks->saved_attrs, &slks->saved_pair, NULL );
+ LINES++;
+ wmove ( stdscr, LINES, 0 );
+ wattrset ( stdscr, slks->attrs );
+}
+
+static void _leave_slk ( void ) {
+ LINES--;
+ wattr_set ( stdscr, slks->saved_attrs, slks->saved_pair, NULL );
+ _restore_curs_pos ( stdscr, &slks->saved_cursor );
+}
+
+static void _print_label ( struct _softlabel sl ) {
+ int space_ch;
+ char str[SLK_MAX_LABEL_LEN + 1];
+
+ assert ( slks->max_label_len <= SLK_MAX_LABEL_LEN );
+ space_ch = ' ';
+
+ // protect against gaps in the soft label keys array
+ if ( sl.label == NULL ) {
+ memset( str, space_ch, (size_t)(slks->max_label_len) );
+ } else {
+ /* we need to pad the label with varying amounts of leading
+ pad depending on the format of the label */
+ if ( sl.fmt == 1 ) {
+ memset( str, space_ch,
+ (size_t)(slks->max_label_len
+ - strlen(sl.label)) / 2 );
+ }
+ if ( sl.fmt == 2 ) {
+ memset( str, space_ch,
+ (size_t)(slks->max_label_len
+ - strlen(sl.label)) );
+ }
+ strcat(str,sl.label);
+
+ // post-padding
+ memset(str+strlen(str), space_ch,
+ (size_t)(slks->max_label_len - strlen(str)) );
+ }
+
+ // print the formatted label
+ _wputstr ( stdscr, str, NOWRAP, slks->max_label_len );
+}
+
+/**
+ * Return the attribute used for the soft function keys
+ *
+ * @ret attrs the current attributes of the soft function keys
+ */
+attr_t slk_attr ( void ) {
+ return ( slks == NULL ? 0 : slks->attrs );
+}
+
+/**
+ * Turn off soft function key attributes
+ *
+ * @v attrs attribute bit mask
+ * @ret rc return status code
+ */
+int slk_attroff ( const chtype attrs ) {
+ if ( slks == NULL )
+ return ERR;
+ slks->attrs &= ~( attrs & A_ATTRIBUTES );
+ return OK;
+}
+
+/**
+ * Turn on soft function key attributes
+ *
+ * @v attrs attribute bit mask
+ * @ret rc return status code
+ */
+int slk_attron ( const chtype attrs ) {
+ if ( slks == NULL )
+ return ERR;
+ slks->attrs |= ( attrs & A_ATTRIBUTES );
+ return OK;
+}
+
+/**
+ * Set soft function key attributes
+ *
+ * @v attrs attribute bit mask
+ * @ret rc return status code
+ */
+int slk_attrset ( const chtype attrs ) {
+ if ( slks == NULL )
+ return ERR;
+ slks->attrs = ( attrs & A_ATTRIBUTES );
+ return OK;
+}
+
+/**
+ * Turn off soft function key attributes
+ *
+ * @v attrs attribute bit mask
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int slk_attr_off ( const attr_t attrs, void *opts __unused ) {
+ return slk_attroff( attrs );
+}
+
+/**
+ * Turn on soft function key attributes
+ *
+ * @v attrs attribute bit mask
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int slk_attr_on ( attr_t attrs, void *opts __unused ) {
+ return slk_attron( attrs );
+}
+
+/**
+ * Set soft function key attributes
+ *
+ * @v attrs attribute bit mask
+ * @v colour_pair_number colour pair integer
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int slk_attr_set ( const attr_t attrs, short colour_pair_number,
+ void *opts __unused ) {
+ if ( slks == NULL )
+ return ERR;
+
+ if ( ( unsigned short )colour_pair_number > COLORS )
+ return ERR;
+
+ slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) |
+ ( attrs & A_ATTRIBUTES );
+ return OK;
+}
+
+/**
+ * Clear the soft function key labels from the screen
+ *
+ * @ret rc return status code
+ */
+int slk_clear ( void ) {
+ if ( slks == NULL )
+ return ERR;
+
+ _enter_slk();
+ wclrtoeol ( stdscr );
+ _leave_slk();
+
+ return OK;
+}
+
+/**
+ * Set soft label colour pair
+ */
+int slk_colour ( short colour_pair_number ) {
+ if ( slks == NULL )
+ return ERR;
+ if ( ( unsigned short )colour_pair_number > COLORS )
+ return ERR;
+
+ slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT )
+ | ( slks->attrs & A_ATTRIBUTES );
+
+ return OK;
+}
+
+/**
+ * Initialise the soft function keys
+ *
+ * @v fmt format of keys
+ * @ret rc return status code
+ */
+int slk_init ( int fmt ) {
+ unsigned short nmaj, nmin, nblocks, available_width;
+
+ if ( (unsigned)fmt > 3 ) {
+ return ERR;
+ }
+
+ /* There seems to be no API call to free this data structure... */
+ if ( ! slks )
+ slks = calloc(1,sizeof(*slks));
+ if ( ! slks )
+ return ERR;
+
+ slks->attrs = A_DEFAULT;
+ slks->fmt = fmt;
+ switch(fmt) {
+ case 0:
+ nblocks = 8; nmaj = 2; nmin = 5;
+ slks->spaces[0] = 2; slks->spaces[1] = 4;
+ break;
+ case 1:
+ nblocks = 8; nmaj = 1; nmin = 6;
+ slks->spaces[0] = 3;
+ break;
+ case 2:
+ // same allocations as format 3
+ case 3:
+ nblocks = 12; nmaj = 2; nmin = 9;
+ slks->spaces[0] = 3; slks->spaces[1] = 7;
+ break;
+ default:
+ nblocks = 0; nmaj = 0; nmin = 0;
+ break;
+ }
+
+ // determine maximum label length and major space size
+ available_width = COLS - ( ( MIN_SPACE_SIZE * nmaj ) + nmin );
+ slks->max_label_len = available_width / nblocks;
+ slks->maj_space_len = MIN_SPACE_SIZE +
+ ( available_width % nblocks ) / nmaj;
+ slks->num_spaces = nmaj;
+ slks->num_labels = nblocks;
+
+ // strip a line from the screen
+ LINES -= 1;
+
+ return OK;
+}
+
+/**
+ * Return the label for the specified soft key
+ *
+ * @v labnum soft key identifier
+ * @ret label return label
+ */
+char* slk_label ( int labnum ) {
+ if ( slks == NULL )
+ return NULL;
+
+ return slks->fkeys[labnum].label;
+}
+
+/**
+ * Restore soft function key labels to the screen
+ *
+ * @ret rc return status code
+ */
+int slk_restore ( void ) {
+ unsigned int i, j, pos_x,
+ *next_space, *last_space;
+ chtype space_ch;
+
+ if ( slks == NULL )
+ return ERR;
+
+ pos_x = 0;
+
+ _enter_slk();
+
+ space_ch = (chtype)' ' | slks->attrs;
+ next_space = &(slks->spaces[0]);
+ last_space = &(slks->spaces[slks->num_spaces-1]);
+
+ for ( i = 0; i < slks->num_labels ; i++ ) {
+ _print_label( slks->fkeys[i] );
+ pos_x += slks->max_label_len;
+
+ if ( i == *next_space ) {
+ for ( j = 0; j < slks->maj_space_len; j++, pos_x++ )
+ _wputch ( stdscr, space_ch, NOWRAP );
+ if ( next_space < last_space )
+ next_space++;
+ } else {
+ if ( pos_x < COLS )
+ _wputch ( stdscr, space_ch, NOWRAP );
+ pos_x++;
+ }
+ }
+
+ _leave_slk();
+
+ return OK;
+}
+
+/**
+ * Configure specified soft key
+ *
+ * @v labnum soft label position to configure
+ * @v *label string to use as soft key label
+ * @v fmt justification format of label
+ * @ret rc return status code
+ */
+int slk_set ( int labnum, const char *label, int fmt ) {
+ if ( slks == NULL )
+ return ERR;
+ if ( (unsigned short)labnum >= slks->num_labels )
+ return ERR;
+ if ( (unsigned short)fmt >= 3 )
+ return ERR;
+
+ strncpy(slks->fkeys[labnum].label, label,
+ sizeof(slks->fkeys[labnum].label));
+ slks->fkeys[labnum].fmt = fmt;
+
+ return OK;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/widgets/editbox.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/widgets/editbox.c
new file mode 100644
index 00000000..5d2ba56c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/widgets/editbox.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <assert.h>
+#include <ipxe/editbox.h>
+
+/** @file
+ *
+ * Editable text box widget
+ *
+ */
+
+#define EDITBOX_MIN_CHARS 3
+
+/**
+ * Initialise text box widget
+ *
+ * @v box Editable text box widget
+ * @v buf Text buffer
+ * @v len Size of text buffer
+ * @v win Containing window
+ * @v row Row
+ * @v col Starting column
+ * @v width Width
+ * @v flags Flags
+ */
+void init_editbox ( struct edit_box *box, char *buf, size_t len,
+ WINDOW *win, unsigned int row, unsigned int col,
+ unsigned int width, unsigned int flags ) {
+ memset ( box, 0, sizeof ( *box ) );
+ init_editstring ( &box->string, buf, len );
+ box->string.cursor = strlen ( buf );
+ box->win = ( win ? win : stdscr );
+ box->row = row;
+ box->col = col;
+ box->width = width;
+ box->flags = flags;
+}
+
+/**
+ * Draw text box widget
+ *
+ * @v box Editable text box widget
+ *
+ */
+void draw_editbox ( struct edit_box *box ) {
+ size_t width = box->width;
+ char buf[ width + 1 ];
+ signed int cursor_offset, underflow, overflow, first;
+ size_t len;
+
+ /* Adjust starting offset so that cursor remains within box */
+ cursor_offset = ( box->string.cursor - box->first );
+ underflow = ( EDITBOX_MIN_CHARS - cursor_offset );
+ overflow = ( cursor_offset - ( width - 1 ) );
+ first = box->first;
+ if ( underflow > 0 ) {
+ first -= underflow;
+ if ( first < 0 )
+ first = 0;
+ } else if ( overflow > 0 ) {
+ first += overflow;
+ }
+ box->first = first;
+ cursor_offset = ( box->string.cursor - first );
+
+ /* Construct underscore-padded string portion */
+ memset ( buf, '_', width );
+ buf[width] = '\0';
+ len = ( strlen ( box->string.buf ) - first );
+ if ( len > width )
+ len = width;
+ if ( box->flags & EDITBOX_STARS ) {
+ memset ( buf, '*', len );
+ } else {
+ memcpy ( buf, ( box->string.buf + first ), len );
+ }
+
+ /* Print box content and move cursor */
+ if ( ! box->win )
+ box->win = stdscr;
+ mvwprintw ( box->win, box->row, box->col, "%s", buf );
+ wmove ( box->win, box->row, ( box->col + cursor_offset ) );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/winattrs.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/winattrs.c
new file mode 100644
index 00000000..f549d751
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/winattrs.c
@@ -0,0 +1,133 @@
+#include <curses.h>
+
+/** @file
+ *
+ * MuCurses window attribute functions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Get the background rendition attributes for a window
+ *
+ * @v *win subject window
+ * @ret ch chtype rendition representation
+ */
+inline chtype getbkgd ( WINDOW *win ) {
+ return win->attrs;
+}
+
+/**
+ * Turn off attributes in a window
+ *
+ * @v win subject window
+ * @v attrs attributes to enable
+ * @ret rc return status code
+ */
+int wattroff ( WINDOW *win, int attrs ) {
+ win->attrs &= ~attrs;
+ return OK;
+}
+
+/**
+ * Turn on attributes in a window
+ *
+ * @v win subject window
+ * @v attrs attributes to enable
+ * @ret rc return status code
+ */
+int wattron ( WINDOW *win, int attrs ) {
+ win->attrs |= attrs;
+ return OK;
+}
+
+/**
+ * Set attributes in a window
+ *
+ * @v win subject window
+ * @v attrs attributes to enable
+ * @ret rc return status code
+ */
+int wattrset ( WINDOW *win, int attrs ) {
+ win->attrs = ( attrs | ( win->attrs & A_COLOR ) );
+ return OK;
+}
+
+/**
+ * Get attributes and colour pair information
+ *
+ * @v *win window to obtain information from
+ * @v *attrs address in which to store attributes
+ * @v *pair address in which to store colour pair
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status cude
+ */
+int wattr_get ( WINDOW *win, attr_t *attrs, short *pair,
+ void *opts __unused ) {
+ *attrs = win->attrs & A_ATTRIBUTES;
+ *pair = PAIR_NUMBER ( win->attrs );
+ return OK;
+}
+
+/**
+ * Turn off attributes in a window
+ *
+ * @v *win subject window
+ * @v attrs attributes to toggle
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int wattr_off ( WINDOW *win, attr_t attrs,
+ void *opts __unused ) {
+ wattroff( win, attrs );
+ return OK;
+}
+
+/**
+ * Turn on attributes in a window
+ *
+ * @v *win subject window
+ * @v attrs attributes to toggle
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int wattr_on ( WINDOW *win, attr_t attrs,
+ void *opts __unused ) {
+ wattron( win, attrs );
+ return OK;
+}
+
+/**
+ * Set attributes and colour pair information in a window
+ *
+ * @v *win subject window
+ * @v attrs attributes to set
+ * @v cpair colour pair to set
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int wattr_set ( WINDOW *win, attr_t attrs, short cpair,
+ void *opts __unused ) {
+ wattrset( win, attrs | COLOUR_PAIR ( cpair ) );
+ return OK;
+}
+
+/**
+ * Set colour pair for a window
+ *
+ * @v *win subject window
+ * @v colour_pair_number colour pair integer
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int wcolour_set ( WINDOW *win, short colour_pair_number,
+ void *opts __unused ) {
+ if ( ( unsigned short )colour_pair_number > COLOUR_PAIRS )
+ return ERR;
+
+ win->attrs = ( ( win->attrs & A_ATTRIBUTES ) |
+ COLOUR_PAIR ( colour_pair_number ) );
+ return OK;
+}
+
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/windows.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/windows.c
new file mode 100644
index 00000000..63d0af08
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/windows.c
@@ -0,0 +1,158 @@
+#include <curses.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include "mucurses.h"
+
+/** @file
+ *
+ * MuCurses windows instance functions
+ *
+ */
+
+/**
+ * Delete a window
+ *
+ * @v *win pointer to window being deleted
+ * @ret rc return status code
+ */
+int delwin ( WINDOW *win ) {
+ if ( win == NULL )
+ return ERR;
+
+ /* I think we should blank the region covered by the window -
+ ncurses doesn't do this, but they have a buffer, so they
+ may just be deleting from an offscreen context whereas we
+ are guaranteed to be deleting something onscreen */
+ wmove( win, 0, 0 );
+ chtype killch = (chtype)' ';
+ do {
+ _wputch( win, killch, WRAP );
+ } while ( win->curs_x + win->curs_y );
+
+ free( win );
+
+ wmove ( stdscr, 0, 0 );
+
+ return OK;
+}
+
+/**
+ * Create a new derived window
+ *
+ * @v parent parent window
+ * @v nlines window height
+ * @v ncols window width
+ * @v begin_y window y origin (relative to parent)
+ * @v begin_x window x origin (relative to parent)
+ * @ret ptr return pointer to child window
+ */
+WINDOW *derwin ( WINDOW *parent, int nlines, int ncols,
+ int begin_y, int begin_x ) {
+ WINDOW *child;
+ if ( parent == NULL )
+ return NULL;
+ if ( ( child = malloc( sizeof( WINDOW ) ) ) == NULL )
+ return NULL;
+ if ( ( (unsigned)ncols > parent->width ) ||
+ ( (unsigned)nlines > parent->height ) )
+ return NULL;
+ child->ori_y = parent->ori_y + begin_y;
+ child->ori_x = parent->ori_x + begin_x;
+ child->height = nlines;
+ child->width = ncols;
+ child->parent = parent;
+ child->scr = parent->scr;
+ return child;
+}
+
+/**
+ * Create a duplicate of the specified window
+ *
+ * @v orig original window
+ * @ret ptr pointer to duplicate window
+ */
+WINDOW *dupwin ( WINDOW *orig ) {
+ WINDOW *copy;
+ if ( orig == NULL )
+ return NULL;
+ if ( ( copy = malloc( sizeof( WINDOW ) ) ) == NULL )
+ return NULL;
+ copy->scr = orig->scr;
+ copy->attrs = orig->attrs;
+ copy->ori_y = orig->ori_y;
+ copy->ori_x = orig->ori_x;
+ copy->curs_y = orig->curs_y;
+ copy->curs_x = orig->curs_x;
+ copy->height = orig->height;
+ copy->width = orig->width;
+ return copy;
+}
+
+/**
+ * Move window origin to specified coordinates
+ *
+ * @v *win window to move
+ * @v y Y position
+ * @v x X position
+ * @ret rc return status code
+ */
+int mvwin ( WINDOW *win, int y, int x ) {
+ if ( win == NULL )
+ return ERR;
+ if ( ( ( (unsigned)y + win->height ) > LINES ) ||
+ ( ( (unsigned)x + win->width ) > COLS ) )
+ return ERR;
+
+ win->ori_y = y;
+ win->ori_x = x;
+
+ return OK;
+}
+
+/**
+ * Create new WINDOW
+ *
+ * @v nlines number of lines
+ * @v ncols number of columns
+ * @v begin_y column origin
+ * @v begin_x line origin
+ * @ret *win return pointer to new window
+ */
+WINDOW *newwin ( int nlines, int ncols, int begin_y, int begin_x ) {
+ WINDOW *win;
+ if ( ( win = malloc( sizeof(WINDOW) ) ) == NULL )
+ return NULL;
+ if ( ( (unsigned)( begin_y + nlines ) > stdscr->height ) &&
+ ( (unsigned)( begin_x + ncols ) > stdscr->width ) )
+ return NULL;
+ win->ori_y = begin_y;
+ win->ori_x = begin_x;
+ win->height = nlines;
+ win->width = ncols;
+ win->scr = stdscr->scr;
+ win->parent = stdscr;
+ return win;
+}
+
+/**
+ * Create a new sub-window
+ *
+ * @v orig parent window
+ * @v nlines window height
+ * @v ncols window width
+ * @v begin_y window y origin (absolute)
+ * @v begin_x window x origin (absolute)
+ * @ret ptr return pointer to child window
+ */
+WINDOW *subwin ( WINDOW *parent, int nlines, int ncols,
+ int begin_y, int begin_x ) {
+ WINDOW *child;
+ if ( parent == NULL )
+ return NULL;
+ if ( ( child = malloc( sizeof( WINDOW ) ) ) == NULL )
+ return NULL;
+ child = newwin( nlines, ncols, begin_y, begin_x );
+ child->parent = parent;
+ child->scr = parent->scr;
+ return child;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/mucurses/wininit.c b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/wininit.c
new file mode 100644
index 00000000..782e7b5c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/mucurses/wininit.c
@@ -0,0 +1,37 @@
+#include <stddef.h>
+#include <curses.h>
+
+/** @file
+ *
+ * MuCurses initialisation functions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Initialise console environment
+ *
+ * @ret *win return pointer to stdscr
+ */
+WINDOW *initscr ( void ) {
+ /* determine console size */
+ /* initialise screen */
+ stdscr->scr->init( stdscr->scr );
+ stdscr->height = LINES;
+ stdscr->width = COLS;
+ move ( 0, 0 );
+ return stdscr;
+}
+
+/**
+ * Finalise console environment
+ *
+ */
+int endwin ( void ) {
+ attrset ( 0 );
+ color_set ( 0, NULL );
+ mvprintw ( ( LINES - 1 ), 0, "\n" );
+ stdscr->scr->exit( stdscr->scr );
+ return OK;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/readline.c b/src/VBox/Devices/PC/ipxe/src/hci/readline.c
new file mode 100644
index 00000000..32793abe
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/readline.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ipxe/console.h>
+#include <ipxe/keys.h>
+#include <ipxe/editstring.h>
+#include <readline/readline.h>
+
+/** @file
+ *
+ * Minimal readline
+ *
+ */
+
+#define READLINE_MAX 256
+
+/**
+ * Synchronise console with edited string
+ *
+ * @v string Editable string
+ */
+static void sync_console ( struct edit_string *string ) {
+ unsigned int mod_start = string->mod_start;
+ unsigned int mod_end = string->mod_end;
+ unsigned int cursor = string->last_cursor;
+ size_t len = strlen ( string->buf );
+
+ /* Expand region back to old cursor position if applicable */
+ if ( mod_start > string->last_cursor )
+ mod_start = string->last_cursor;
+
+ /* Expand region forward to new cursor position if applicable */
+ if ( mod_end < string->cursor )
+ mod_end = string->cursor;
+
+ /* Backspace to start of region */
+ while ( cursor > mod_start ) {
+ putchar ( '\b' );
+ cursor--;
+ }
+
+ /* Print modified region */
+ while ( cursor < mod_end ) {
+ putchar ( ( cursor >= len ) ? ' ' : string->buf[cursor] );
+ cursor++;
+ }
+
+ /* Backspace to new cursor position */
+ while ( cursor > string->cursor ) {
+ putchar ( '\b' );
+ cursor--;
+ }
+}
+
+/**
+ * Locate history entry
+ *
+ * @v history History buffer
+ * @v depth Depth within history buffer
+ * @ret entry History entry
+ */
+static struct readline_history_entry *
+history_entry ( struct readline_history *history, unsigned int depth ) {
+ unsigned int offset;
+
+ offset = ( ( history->next - depth ) %
+ ( sizeof ( history->entries ) /
+ sizeof ( history->entries[0] ) ) );
+ return &history->entries[offset];
+}
+
+/**
+ * Read string from history buffer
+ *
+ * @v history History buffer
+ * @v depth Depth within history buffer
+ * @ret string String
+ */
+static const char * history_fetch ( struct readline_history *history,
+ unsigned int depth ) {
+ struct readline_history_entry *entry;
+
+ /* Return the temporary copy if it exists, otherwise return
+ * the persistent copy.
+ */
+ entry = history_entry ( history, depth );
+ return ( entry->temp ? entry->temp : entry->string );
+}
+
+/**
+ * Write temporary string copy to history buffer
+ *
+ * @v history History buffer
+ * @v depth Depth within history buffer
+ * @v string String
+ */
+static void history_store ( struct readline_history *history,
+ unsigned int depth, const char *string ) {
+ struct readline_history_entry *entry;
+ char *temp;
+
+ /* Create temporary copy of string */
+ temp = strdup ( string );
+ if ( ! temp ) {
+ /* Just discard the string; there's nothing we can do */
+ DBGC ( history, "READLINE %p could not store string\n",
+ history );
+ return;
+ }
+
+ /* Store temporary copy */
+ entry = history_entry ( history, depth );
+ free ( entry->temp );
+ entry->temp = temp;
+}
+
+/**
+ * Move to new history depth
+ *
+ * @v history History buffer
+ * @v offset Offset by which to change depth
+ * @v old_string String (possibly modified) at current depth
+ * @ret new_string String at new depth, or NULL for no movement
+ */
+static const char * history_move ( struct readline_history *history,
+ int offset, const char *old_string ) {
+ unsigned int new_depth = ( history->depth + offset );
+ const char * new_string = history_fetch ( history, new_depth );
+
+ /* Depth checks */
+ if ( new_depth > READLINE_HISTORY_MAX_DEPTH )
+ return NULL;
+ if ( ! new_string )
+ return NULL;
+
+ /* Store temporary copy of old string at current depth */
+ history_store ( history, history->depth, old_string );
+
+ /* Update depth */
+ history->depth = new_depth;
+
+ /* Return new string */
+ return new_string;
+}
+
+/**
+ * Append new history entry
+ *
+ * @v history History buffer
+ * @v string String
+ */
+static void history_append ( struct readline_history *history,
+ const char *string ) {
+ struct readline_history_entry *entry;
+
+ /* Store new entry */
+ entry = history_entry ( history, 0 );
+ assert ( entry->string == NULL );
+ entry->string = strdup ( string );
+ if ( ! entry->string ) {
+ /* Just discard the string; there's nothing we can do */
+ DBGC ( history, "READLINE %p could not append string\n",
+ history );
+ return;
+ }
+
+ /* Increment history position */
+ history->next++;
+
+ /* Prepare empty "next" slot */
+ entry = history_entry ( history, 0 );
+ free ( entry->string );
+ entry->string = NULL;
+}
+
+/**
+ * Clean up history after editing
+ *
+ * @v history History buffer
+ */
+static void history_cleanup ( struct readline_history *history ) {
+ struct readline_history_entry *entry;
+ unsigned int i;
+
+ /* Discard any temporary strings */
+ for ( i = 0 ; i < ( sizeof ( history->entries ) /
+ sizeof ( history->entries[0] ) ) ; i++ ) {
+ entry = &history->entries[i];
+ free ( entry->temp );
+ entry->temp = NULL;
+ }
+
+ /* Reset depth */
+ history->depth = 0;
+
+ /* Sanity check */
+ entry = history_entry ( history, 0 );
+ assert ( entry->string == NULL );
+}
+
+/**
+ * Free history buffer
+ *
+ * @v history History buffer
+ */
+void history_free ( struct readline_history *history ) {
+ struct readline_history_entry *entry;
+ unsigned int i;
+
+ /* Discard any temporary strings */
+ for ( i = 0 ; i < ( sizeof ( history->entries ) /
+ sizeof ( history->entries[0] ) ) ; i++ ) {
+ entry = &history->entries[i];
+ assert ( entry->temp == NULL );
+ free ( entry->string );
+ }
+}
+
+/**
+ * Read line from console (with history)
+ *
+ * @v prompt Prompt string
+ * @v history History buffer, or NULL for no history
+ * @ret line Line read from console (excluding terminating newline)
+ *
+ * The returned line is allocated with malloc(); the caller must
+ * eventually call free() to release the storage.
+ */
+char * readline_history ( const char *prompt,
+ struct readline_history *history ) {
+ char buf[READLINE_MAX];
+ struct edit_string string;
+ int key;
+ int move_by;
+ const char *new_string;
+ char *line;
+
+ /* Display prompt, if applicable */
+ if ( prompt )
+ printf ( "%s", prompt );
+
+ /* Initialise editable string */
+ memset ( &string, 0, sizeof ( string ) );
+ init_editstring ( &string, buf, sizeof ( buf ) );
+ buf[0] = '\0';
+
+ while ( 1 ) {
+ /* Handle keypress */
+ key = edit_string ( &string, getkey ( 0 ) );
+ sync_console ( &string );
+ move_by = 0;
+ switch ( key ) {
+ case CR:
+ case LF:
+ line = strdup ( buf );
+ if ( ! line )
+ printf ( "\nOut of memory" );
+ goto done;
+ case CTRL_C:
+ line = NULL;
+ goto done;
+ case KEY_UP:
+ move_by = 1;
+ break;
+ case KEY_DOWN:
+ move_by = -1;
+ break;
+ default:
+ /* Do nothing */
+ break;
+ }
+
+ /* Handle history movement, if applicable */
+ if ( move_by && history ) {
+ new_string = history_move ( history, move_by, buf );
+ if ( new_string ) {
+ replace_string ( &string, new_string );
+ sync_console ( &string );
+ }
+ }
+ }
+
+ done:
+ putchar ( '\n' );
+ if ( history ) {
+ if ( line && line[0] )
+ history_append ( history, line );
+ history_cleanup ( history );
+ }
+ return line;
+}
+
+/**
+ * Read line from console
+ *
+ * @v prompt Prompt string
+ * @ret line Line read from console (excluding terminating newline)
+ *
+ * The returned line is allocated with malloc(); the caller must
+ * eventually call free() to release the storage.
+ */
+char * readline ( const char *prompt ) {
+ return readline_history ( prompt, NULL );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/shell.c b/src/VBox/Devices/PC/ipxe/src/hci/shell.c
new file mode 100644
index 00000000..e426ba94
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/shell.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <readline/readline.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/shell.h>
+
+/** @file
+ *
+ * Minimal command shell
+ *
+ */
+
+/** The shell prompt string */
+static const char shell_prompt[] = "iPXE> ";
+
+/**
+ * "help" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int help_exec ( int argc __unused, char **argv __unused ) {
+ struct command *command;
+ unsigned int hpos = 0;
+
+ printf ( "\nAvailable commands:\n\n" );
+ for_each_table_entry ( command, COMMANDS ) {
+ hpos += printf ( " %s", command->name );
+ if ( hpos > ( 16 * 4 ) ) {
+ printf ( "\n" );
+ hpos = 0;
+ } else {
+ while ( hpos % 16 ) {
+ printf ( " " );
+ hpos++;
+ }
+ }
+ }
+ printf ( "\n\nType \"<command> --help\" for further information\n\n" );
+ return 0;
+}
+
+/** "help" command */
+struct command help_command __command = {
+ .name = "help",
+ .exec = help_exec,
+};
+
+/**
+ * Start command shell
+ *
+ */
+int shell ( void ) {
+ struct readline_history history;
+ char *line;
+ int rc = 0;
+
+ /* Initialise shell history */
+ memset ( &history, 0, sizeof ( history ) );
+
+ /* Read and execute commands */
+ do {
+ line = readline_history ( shell_prompt, &history );
+ if ( line ) {
+ rc = system ( line );
+ free ( line );
+ }
+ } while ( ! shell_stopped ( SHELL_STOP_COMMAND_SEQUENCE ) );
+
+ /* Discard shell history */
+ history_free ( &history );
+
+ return rc;
+}
+
+/** "shell" options */
+struct shell_options {};
+
+/** "shell" option list */
+static struct option_descriptor shell_opts[] = {};
+
+/** "shell" command descriptor */
+static struct command_descriptor shell_cmd =
+ COMMAND_DESC ( struct shell_options, shell_opts, 0, 0, "" );
+
+/**
+ * "shell" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int shell_exec ( int argc, char **argv ) {
+ struct shell_options opts;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &shell_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Start shell */
+ if ( ( rc = shell() ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/** "shell" command */
+struct command shell_command __command = {
+ .name = "shell",
+ .exec = shell_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/strerror.c b/src/VBox/Devices/PC/ipxe/src/hci/strerror.c
new file mode 100644
index 00000000..9356e9e0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/strerror.c
@@ -0,0 +1,125 @@
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <ipxe/errortab.h>
+
+/** @file
+ *
+ * Error descriptions.
+ *
+ * The error numbers used by Etherboot are a superset of those defined
+ * by the PXE specification version 2.1. See errno.h for a listing of
+ * the error values.
+ *
+ * To save space in ROM images, error string tables are optional. Use
+ * the ERRORMSG_XXX options in config.h to select which error string
+ * tables you want to include. If an error string table is omitted,
+ * strerror() will simply return the text "Error 0x<errno>".
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Find error description
+ *
+ * @v errno Error number
+ * @ret errortab Error description, or NULL
+ */
+static struct errortab * find_error ( int errno ) {
+ struct errortab *errortab;
+
+ for_each_table_entry ( errortab, ERRORTAB ) {
+ if ( errortab->errno == errno )
+ return errortab;
+ }
+
+ return NULL;
+}
+
+/**
+ * Find closest error description
+ *
+ * @v errno Error number
+ * @ret errortab Error description, or NULL
+ *
+ *
+ */
+static struct errortab * find_closest_error ( int errno ) {
+ struct errortab *errortab;
+
+ /* First, look for an exact match */
+ if ( ( errortab = find_error ( errno ) ) != NULL )
+ return errortab;
+
+ /* Second, try masking off the iPXE-specific bit and seeing if
+ * we have an entry for the generic POSIX error message.
+ */
+ if ( ( errortab = find_error ( errno & 0x7f0000ff ) ) != NULL )
+ return errortab;
+
+ return NULL;
+}
+
+/**
+ * Retrieve string representation of error number.
+ *
+ * @v errno/rc Error number or return status code
+ * @ret strerror Pointer to error text
+ *
+ * If the error is not found in the linked-in error tables, generates
+ * a generic "Error 0x<errno>" message.
+ *
+ * The pointer returned by strerror() is valid only until the next
+ * call to strerror().
+ *
+ */
+const char * strerror ( int errno ) {
+ static char errbuf[64];
+ struct errortab *errortab;
+
+ /* Allow for strerror(rc) as well as strerror(errno) */
+ if ( errno < 0 )
+ errno = -errno;
+
+ /* Find the error description, if one exists */
+ errortab = find_closest_error ( errno );
+
+ /* Construct the error message */
+ if ( errortab ) {
+ snprintf ( errbuf, sizeof ( errbuf ),
+ "%s (http://ipxe.org/%08x)",
+ errortab->text, errno );
+ } else {
+ snprintf ( errbuf, sizeof ( errbuf ),
+ "Error %#08x (http://ipxe.org/%08x)",
+ errno, errno );
+ }
+
+ return errbuf;
+}
+
+/* Do not include ERRFILE portion in the numbers in the error table */
+#undef ERRFILE
+#define ERRFILE 0
+
+/** The most common errors */
+struct errortab common_errors[] __errortab = {
+ __einfo_errortab ( EINFO_ENOERR ),
+ __einfo_errortab ( EINFO_EACCES ),
+ __einfo_errortab ( EINFO_ECANCELED ),
+ __einfo_errortab ( EINFO_ECONNRESET ),
+ __einfo_errortab ( EINFO_EINVAL ),
+ __einfo_errortab ( EINFO_EIO ),
+ __einfo_errortab ( EINFO_ENETUNREACH ),
+ __einfo_errortab ( EINFO_ENODEV ),
+ __einfo_errortab ( EINFO_ENOENT ),
+ __einfo_errortab ( EINFO_ENOEXEC ),
+ __einfo_errortab ( EINFO_ENOMEM ),
+ __einfo_errortab ( EINFO_ENOSPC ),
+ __einfo_errortab ( EINFO_ENOTCONN ),
+ __einfo_errortab ( EINFO_ENOTSUP ),
+ __einfo_errortab ( EINFO_EPERM ),
+ __einfo_errortab ( EINFO_ERANGE ),
+ __einfo_errortab ( EINFO_ETIMEDOUT ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/tui/login_ui.c b/src/VBox/Devices/PC/ipxe/src/hci/tui/login_ui.c
new file mode 100644
index 00000000..04aabfa8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/tui/login_ui.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Login UI
+ *
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <curses.h>
+#include <ipxe/console.h>
+#include <ipxe/settings.h>
+#include <ipxe/editbox.h>
+#include <ipxe/keys.h>
+#include <ipxe/login_ui.h>
+
+/* Colour pairs */
+#define CPAIR_NORMAL 1
+#define CPAIR_LABEL 2
+#define CPAIR_EDITBOX 3
+
+/* Screen layout */
+#define USERNAME_LABEL_ROW 8
+#define USERNAME_ROW 10
+#define PASSWORD_LABEL_ROW 14
+#define PASSWORD_ROW 16
+#define LABEL_COL 36
+#define EDITBOX_COL 30
+#define EDITBOX_WIDTH 20
+
+int login_ui ( void ) {
+ char username[64];
+ char password[64];
+ struct edit_box username_box;
+ struct edit_box password_box;
+ struct edit_box *current_box = &username_box;
+ int key;
+ int rc = -EINPROGRESS;
+
+ /* Fetch current setting values */
+ fetch_string_setting ( NULL, &username_setting, username,
+ sizeof ( username ) );
+ fetch_string_setting ( NULL, &password_setting, password,
+ sizeof ( password ) );
+
+ /* Initialise UI */
+ initscr();
+ start_color();
+ init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLACK );
+ init_pair ( CPAIR_LABEL, COLOR_WHITE, COLOR_BLACK );
+ init_pair ( CPAIR_EDITBOX, COLOR_WHITE, COLOR_BLUE );
+ init_editbox ( &username_box, username, sizeof ( username ), NULL,
+ USERNAME_ROW, EDITBOX_COL, EDITBOX_WIDTH, 0 );
+ init_editbox ( &password_box, password, sizeof ( password ), NULL,
+ PASSWORD_ROW, EDITBOX_COL, EDITBOX_WIDTH,
+ EDITBOX_STARS );
+
+ /* Draw initial UI */
+ erase();
+ color_set ( CPAIR_LABEL, NULL );
+ mvprintw ( USERNAME_LABEL_ROW, LABEL_COL, "Username:" );
+ mvprintw ( PASSWORD_LABEL_ROW, LABEL_COL, "Password:" );
+ color_set ( CPAIR_EDITBOX, NULL );
+ draw_editbox ( &username_box );
+ draw_editbox ( &password_box );
+
+ /* Main loop */
+ while ( rc == -EINPROGRESS ) {
+
+ draw_editbox ( current_box );
+
+ key = getkey ( 0 );
+ switch ( key ) {
+ case KEY_DOWN:
+ current_box = &password_box;
+ break;
+ case KEY_UP:
+ current_box = &username_box;
+ break;
+ case TAB:
+ current_box = ( ( current_box == &username_box ) ?
+ &password_box : &username_box );
+ break;
+ case KEY_ENTER:
+ if ( current_box == &username_box ) {
+ current_box = &password_box;
+ } else {
+ rc = 0;
+ }
+ break;
+ case CTRL_C:
+ case ESC:
+ rc = -ECANCELED;
+ break;
+ default:
+ edit_editbox ( current_box, key );
+ break;
+ }
+ }
+
+ /* Terminate UI */
+ color_set ( CPAIR_NORMAL, NULL );
+ erase();
+ endwin();
+
+ if ( rc != 0 )
+ return rc;
+
+ /* Store settings */
+ if ( ( rc = store_setting ( NULL, &username_setting, username,
+ strlen ( username ) ) ) != 0 )
+ return rc;
+ if ( ( rc = store_setting ( NULL, &password_setting, password,
+ strlen ( password ) ) ) != 0 )
+ return rc;
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/tui/menu_ui.c b/src/VBox/Devices/PC/ipxe/src/hci/tui/menu_ui.c
new file mode 100644
index 00000000..30d93ad2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/tui/menu_ui.c
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Menu interface
+ *
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <curses.h>
+#include <ipxe/keys.h>
+#include <ipxe/timer.h>
+#include <ipxe/console.h>
+#include <ipxe/menu.h>
+
+/* Colour pairs */
+#define CPAIR_NORMAL 1
+#define CPAIR_SELECT 2
+#define CPAIR_SEPARATOR 3
+
+/* Screen layout */
+#define TITLE_ROW 1
+#define MENU_ROW 3
+#define MENU_COL 1
+#define MENU_ROWS 18
+#define MENU_COLS 78
+#define MENU_PAD 2
+
+/** A menu user interface */
+struct menu_ui {
+ /** Menu */
+ struct menu *menu;
+ /** Number of menu items */
+ int count;
+ /** Currently selected item */
+ int selected;
+ /** First visible item */
+ int first_visible;
+ /** Timeout (0=indefinite) */
+ unsigned long timeout;
+};
+
+/**
+ * Return a numbered menu item
+ *
+ * @v menu Menu
+ * @v index Index
+ * @ret item Menu item, or NULL
+ */
+static struct menu_item * menu_item ( struct menu *menu, unsigned int index ) {
+ struct menu_item *item;
+
+ list_for_each_entry ( item, &menu->items, list ) {
+ if ( index-- == 0 )
+ return item;
+ }
+
+ return NULL;
+}
+
+/**
+ * Draw a numbered menu item
+ *
+ * @v ui Menu user interface
+ * @v index Index
+ */
+static void draw_menu_item ( struct menu_ui *ui, int index ) {
+ struct menu_item *item;
+ unsigned int row_offset;
+ char buf[ MENU_COLS + 1 /* NUL */ ];
+ char timeout_buf[6]; /* "(xxx)" + NUL */
+ size_t timeout_len;
+ size_t max_len;
+ size_t len;
+
+ /* Move to start of row */
+ row_offset = ( index - ui->first_visible );
+ move ( ( MENU_ROW + row_offset ), MENU_COL );
+
+ /* Get menu item */
+ item = menu_item ( ui->menu, index );
+ if ( item ) {
+
+ /* Draw separators in a different colour */
+ if ( ! item->label )
+ color_set ( CPAIR_SEPARATOR, NULL );
+
+ /* Highlight if this is the selected item */
+ if ( index == ui->selected ) {
+ color_set ( CPAIR_SELECT, NULL );
+ attron ( A_BOLD );
+ }
+
+ /* Construct row */
+ memset ( buf, ' ', ( sizeof ( buf ) - 1 ) );
+ buf[ sizeof ( buf ) -1 ] = '\0';
+ len = strlen ( item->text );
+ max_len = ( sizeof ( buf ) - 1 /* NUL */ - ( 2 * MENU_PAD ) );
+ if ( len > max_len )
+ len = max_len;
+ memcpy ( ( buf + MENU_PAD ), item->text, len );
+
+ /* Add timeout if applicable */
+ timeout_len =
+ snprintf ( timeout_buf, sizeof ( timeout_buf ), "(%ld)",
+ ( ( ui->timeout + TICKS_PER_SEC - 1 ) /
+ TICKS_PER_SEC ) );
+ if ( ( index == ui->selected ) && ( ui->timeout != 0 ) ) {
+ memcpy ( ( buf + MENU_COLS - MENU_PAD - timeout_len ),
+ timeout_buf, timeout_len );
+ }
+
+ /* Print row */
+ printw ( "%s", buf );
+
+ /* Reset attributes */
+ color_set ( CPAIR_NORMAL, NULL );
+ attroff ( A_BOLD );
+
+ } else {
+ /* Clear row if there is no corresponding menu item */
+ clrtoeol();
+ }
+
+ /* Move cursor back to start of row */
+ move ( ( MENU_ROW + row_offset ), MENU_COL );
+}
+
+/**
+ * Draw the current block of menu items
+ *
+ * @v ui Menu user interface
+ */
+static void draw_menu_items ( struct menu_ui *ui ) {
+ unsigned int i;
+
+ /* Jump scroll to correct point in list */
+ while ( ui->first_visible < ui->selected )
+ ui->first_visible += MENU_ROWS;
+ while ( ui->first_visible > ui->selected )
+ ui->first_visible -= MENU_ROWS;
+
+ /* Draw ellipses before and/or after the list as necessary */
+ color_set ( CPAIR_SEPARATOR, NULL );
+ mvaddstr ( ( MENU_ROW - 1 ), ( MENU_COL + MENU_PAD ),
+ ( ( ui->first_visible > 0 ) ? "..." : " " ) );
+ mvaddstr ( ( MENU_ROW + MENU_ROWS ), ( MENU_COL + MENU_PAD ),
+ ( ( ( ui->first_visible + MENU_ROWS ) < ui->count ) ?
+ "..." : " " ) );
+ color_set ( CPAIR_NORMAL, NULL );
+
+ /* Draw visible items */
+ for ( i = 0 ; i < MENU_ROWS ; i++ )
+ draw_menu_item ( ui, ( ui->first_visible + i ) );
+}
+
+/**
+ * Menu main loop
+ *
+ * @v ui Menu user interface
+ * @ret selected Selected item
+ * @ret rc Return status code
+ */
+static int menu_loop ( struct menu_ui *ui, struct menu_item **selected ) {
+ struct menu_item *item;
+ unsigned long timeout;
+ unsigned int delta;
+ int current;
+ int key;
+ int i;
+ int move;
+ int chosen = 0;
+ int rc = 0;
+
+ do {
+ /* Record current selection */
+ current = ui->selected;
+
+ /* Calculate timeout as remainder of current second */
+ timeout = ( ui->timeout % TICKS_PER_SEC );
+ if ( ( timeout == 0 ) && ( ui->timeout != 0 ) )
+ timeout = TICKS_PER_SEC;
+ ui->timeout -= timeout;
+
+ /* Get key */
+ move = 0;
+ key = getkey ( timeout );
+ if ( key < 0 ) {
+ /* Choose default if we finally time out */
+ if ( ui->timeout == 0 )
+ chosen = 1;
+ } else {
+ /* Cancel any timeout */
+ ui->timeout = 0;
+
+ /* Handle key */
+ switch ( key ) {
+ case KEY_UP:
+ move = -1;
+ break;
+ case KEY_DOWN:
+ move = +1;
+ break;
+ case KEY_PPAGE:
+ move = ( ui->first_visible - ui->selected - 1 );
+ break;
+ case KEY_NPAGE:
+ move = ( ui->first_visible - ui->selected
+ + MENU_ROWS );
+ break;
+ case KEY_HOME:
+ move = -ui->count;
+ break;
+ case KEY_END:
+ move = +ui->count;
+ break;
+ case ESC:
+ case CTRL_C:
+ rc = -ECANCELED;
+ break;
+ case CR:
+ case LF:
+ chosen = 1;
+ break;
+ default:
+ i = 0;
+ list_for_each_entry ( item, &ui->menu->items,
+ list ) {
+ if ( item->shortcut == key ) {
+ ui->selected = i;
+ chosen = 1;
+ break;
+ }
+ i++;
+ }
+ break;
+ }
+ }
+
+ /* Move selection, if applicable */
+ while ( move ) {
+ ui->selected += move;
+ if ( ui->selected < 0 ) {
+ ui->selected = 0;
+ move = +1;
+ } else if ( ui->selected >= ui->count ) {
+ ui->selected = ( ui->count - 1 );
+ move = -1;
+ }
+ item = menu_item ( ui->menu, ui->selected );
+ if ( item->label )
+ break;
+ move = ( ( move > 0 ) ? +1 : -1 );
+ }
+
+ /* Redraw selection if necessary */
+ if ( ( ui->selected != current ) || ( timeout != 0 ) ) {
+ draw_menu_item ( ui, current );
+ delta = ( ui->selected - ui->first_visible );
+ if ( delta >= MENU_ROWS )
+ draw_menu_items ( ui );
+ draw_menu_item ( ui, ui->selected );
+ }
+
+ /* Refuse to choose unlabelled items (i.e. separators) */
+ item = menu_item ( ui->menu, ui->selected );
+ if ( ! item->label )
+ chosen = 0;
+
+ /* Record selection */
+ *selected = item;
+
+ } while ( ( rc == 0 ) && ! chosen );
+
+ return rc;
+}
+
+/**
+ * Show menu
+ *
+ * @v menu Menu
+ * @v wait_ms Time to wait, in milliseconds (0=indefinite)
+ * @ret selected Selected item
+ * @ret rc Return status code
+ */
+int show_menu ( struct menu *menu, unsigned int timeout_ms,
+ const char *select, struct menu_item **selected ) {
+ struct menu_item *item;
+ struct menu_ui ui;
+ int labelled_count = 0;
+ int rc;
+
+ /* Initialise UI */
+ memset ( &ui, 0, sizeof ( ui ) );
+ ui.menu = menu;
+ ui.timeout = ( ( timeout_ms * TICKS_PER_SEC ) / 1000 );
+ list_for_each_entry ( item, &menu->items, list ) {
+ if ( item->label ) {
+ if ( ! labelled_count )
+ ui.selected = ui.count;
+ labelled_count++;
+ if ( select ) {
+ if ( strcmp ( select, item->label ) == 0 )
+ ui.selected = ui.count;
+ } else {
+ if ( item->is_default )
+ ui.selected = ui.count;
+ }
+ }
+ ui.count++;
+ }
+ if ( ! labelled_count ) {
+ /* Menus with no labelled items cannot be selected
+ * from, and will seriously confuse the navigation
+ * logic. Refuse to display any such menus.
+ */
+ return -ENOENT;
+ }
+
+ /* Initialise screen */
+ initscr();
+ start_color();
+ init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLUE );
+ init_pair ( CPAIR_SELECT, COLOR_WHITE, COLOR_RED );
+ init_pair ( CPAIR_SEPARATOR, COLOR_CYAN, COLOR_BLUE );
+ color_set ( CPAIR_NORMAL, NULL );
+ erase();
+
+ /* Draw initial content */
+ attron ( A_BOLD );
+ mvprintw ( TITLE_ROW, ( ( COLS - strlen ( ui.menu->title ) ) / 2 ),
+ "%s", ui.menu->title );
+ attroff ( A_BOLD );
+ draw_menu_items ( &ui );
+ draw_menu_item ( &ui, ui.selected );
+
+ /* Enter main loop */
+ rc = menu_loop ( &ui, selected );
+ assert ( *selected );
+
+ /* Clear screen */
+ endwin();
+
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/tui/settings_ui.c b/src/VBox/Devices/PC/ipxe/src/hci/tui/settings_ui.c
new file mode 100644
index 00000000..ed076101
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/tui/settings_ui.c
@@ -0,0 +1,573 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <curses.h>
+#include <ipxe/console.h>
+#include <ipxe/settings.h>
+#include <ipxe/editbox.h>
+#include <ipxe/keys.h>
+#include <ipxe/settings_ui.h>
+
+/** @file
+ *
+ * Option configuration console
+ *
+ */
+
+/* Colour pairs */
+#define CPAIR_NORMAL 1
+#define CPAIR_SELECT 2
+#define CPAIR_EDIT 3
+#define CPAIR_ALERT 4
+#define CPAIR_URL 5
+
+/* Screen layout */
+#define TITLE_ROW 1
+#define SETTINGS_LIST_ROW 3
+#define SETTINGS_LIST_COL 1
+#define SETTINGS_LIST_ROWS 15
+#define INFO_ROW 19
+#define ALERT_ROW 22
+#define INSTRUCTION_ROW 22
+#define INSTRUCTION_PAD " "
+
+/** Layout of text within a setting widget */
+struct setting_row_text {
+ char start[0];
+ char pad1[1];
+ char name[15];
+ char pad2[1];
+ char value[60];
+ char pad3[1];
+ char nul;
+} __attribute__ (( packed ));
+
+/** A setting row widget */
+struct setting_row_widget {
+ /** Target configuration settings block
+ *
+ * Valid only for rows that lead to new settings blocks.
+ */
+ struct settings *settings;
+ /** Configuration setting
+ *
+ * Valid only for rows that represent individual settings.
+ */
+ struct setting *setting;
+ /** Screen row */
+ unsigned int row;
+ /** Screen column */
+ unsigned int col;
+ /** Edit box widget used for editing setting */
+ struct edit_box editbox;
+ /** Editing in progress flag */
+ int editing;
+ /** Setting originates from this block flag */
+ int originates_here;
+ /** Buffer for setting's value */
+ char value[256]; /* enough size for a DHCP string */
+};
+
+/** A settings widget */
+struct setting_widget {
+ /** Settings block */
+ struct settings *settings;
+ /** Number of rows */
+ unsigned int num_rows;
+ /** Current row index */
+ unsigned int current;
+ /** Index of the first visible row, for scrolling. */
+ unsigned int first_visible;
+ /** Active row */
+ struct setting_row_widget row;
+};
+
+/**
+ * Select a setting row
+ *
+ * @v widget Setting widget
+ * @v index Index of setting row
+ * @ret count Number of settings rows
+ */
+static unsigned int select_setting_row ( struct setting_widget *widget,
+ unsigned int index ) {
+ struct settings *settings;
+ struct settings *origin;
+ struct setting *setting;
+ unsigned int count = 0;
+
+ /* Initialise structure */
+ memset ( &widget->row, 0, sizeof ( widget->row ) );
+ widget->current = index;
+ widget->row.row = ( SETTINGS_LIST_ROW + index - widget->first_visible );
+ widget->row.col = SETTINGS_LIST_COL;
+
+ /* Include parent settings block, if applicable */
+ if ( widget->settings->parent && ( count++ == index ) ) {
+ widget->row.settings = widget->settings->parent;
+ snprintf ( widget->row.value, sizeof ( widget->row.value ),
+ "../" );
+ }
+
+ /* Include any child settings blocks, if applicable */
+ list_for_each_entry ( settings, &widget->settings->children, siblings ){
+ if ( count++ == index ) {
+ widget->row.settings = settings;
+ snprintf ( widget->row.value,
+ sizeof ( widget->row.value ), "%s/",
+ settings->name );
+ }
+ }
+
+ /* Include any applicable settings */
+ for_each_table_entry ( setting, SETTINGS ) {
+ if ( ! setting_applies ( widget->settings, setting ) )
+ continue;
+ if ( count++ == index ) {
+ widget->row.setting = setting;
+
+ /* Read current setting value */
+ fetchf_setting ( widget->settings, widget->row.setting,
+ widget->row.value,
+ sizeof ( widget->row.value ) );
+
+ /* Check setting's origin */
+ origin = fetch_setting_origin ( widget->settings,
+ widget->row.setting );
+ widget->row.originates_here =
+ ( origin == widget->settings );
+ }
+ }
+
+ /* Initialise edit box */
+ init_editbox ( &widget->row.editbox, widget->row.value,
+ sizeof ( widget->row.value ), NULL, widget->row.row,
+ ( widget->row.col +
+ offsetof ( struct setting_row_text, value ) ),
+ sizeof ( ( ( struct setting_row_text * ) NULL )->value ),
+ 0 );
+
+ return count;
+}
+
+static size_t string_copy ( char *dest, const char *src, size_t len ) {
+ size_t src_len;
+
+ src_len = strlen ( src );
+ if ( len > src_len )
+ len = src_len;
+ memcpy ( dest, src, len );
+ return len;
+}
+
+/**
+ * Draw setting row
+ *
+ * @v widget Setting widget
+ */
+static void draw_setting_row ( struct setting_widget *widget ) {
+ struct setting_row_text text;
+ unsigned int curs_offset;
+ char *value;
+
+ /* Fill row with spaces */
+ memset ( &text, ' ', sizeof ( text ) );
+ text.nul = '\0';
+
+ /* Construct row content */
+ if ( widget->row.settings ) {
+
+ /* Construct space-padded name */
+ curs_offset = ( offsetof ( typeof ( text ), name ) +
+ string_copy ( text.name, widget->row.value,
+ sizeof ( text.name ) ) );
+
+ } else {
+
+ /* Construct dot-padded name */
+ memset ( text.name, '.', sizeof ( text.name ) );
+ string_copy ( text.name, widget->row.setting->name,
+ sizeof ( text.name ) );
+
+ /* Construct space-padded value */
+ value = widget->row.value;
+ if ( ! *value )
+ value = "<not specified>";
+ curs_offset = ( offsetof ( typeof ( text ), value ) +
+ string_copy ( text.value, value,
+ sizeof ( text.value ) ) );
+ }
+
+ /* Print row */
+ if ( widget->row.originates_here || widget->row.settings )
+ attron ( A_BOLD );
+ mvprintw ( widget->row.row, widget->row.col, "%s", text.start );
+ attroff ( A_BOLD );
+ move ( widget->row.row, widget->row.col + curs_offset );
+}
+
+/**
+ * Edit setting widget
+ *
+ * @v widget Setting widget
+ * @v key Key pressed by user
+ * @ret key Key returned to application, or zero
+ */
+static int edit_setting ( struct setting_widget *widget, int key ) {
+ assert ( widget->row.setting != NULL );
+ widget->row.editing = 1;
+ return edit_editbox ( &widget->row.editbox, key );
+}
+
+/**
+ * Save setting widget value back to configuration settings
+ *
+ * @v widget Setting widget
+ */
+static int save_setting ( struct setting_widget *widget ) {
+ assert ( widget->row.setting != NULL );
+ return storef_setting ( widget->settings, widget->row.setting,
+ widget->row.value );
+}
+
+/**
+ * Print message centred on specified row
+ *
+ * @v row Row
+ * @v fmt printf() format string
+ * @v args printf() argument list
+ */
+static void vmsg ( unsigned int row, const char *fmt, va_list args ) {
+ char buf[COLS];
+ size_t len;
+
+ len = vsnprintf ( buf, sizeof ( buf ), fmt, args );
+ mvprintw ( row, ( ( COLS - len ) / 2 ), "%s", buf );
+}
+
+/**
+ * Print message centred on specified row
+ *
+ * @v row Row
+ * @v fmt printf() format string
+ * @v .. printf() arguments
+ */
+static void msg ( unsigned int row, const char *fmt, ... ) {
+ va_list args;
+
+ va_start ( args, fmt );
+ vmsg ( row, fmt, args );
+ va_end ( args );
+}
+
+/**
+ * Clear message on specified row
+ *
+ * @v row Row
+ */
+static void clearmsg ( unsigned int row ) {
+ move ( row, 0 );
+ clrtoeol();
+}
+
+/**
+ * Print alert message
+ *
+ * @v fmt printf() format string
+ * @v args printf() argument list
+ */
+static void valert ( const char *fmt, va_list args ) {
+ clearmsg ( ALERT_ROW );
+ color_set ( CPAIR_ALERT, NULL );
+ vmsg ( ALERT_ROW, fmt, args );
+ sleep ( 2 );
+ color_set ( CPAIR_NORMAL, NULL );
+ clearmsg ( ALERT_ROW );
+}
+
+/**
+ * Print alert message
+ *
+ * @v fmt printf() format string
+ * @v ... printf() arguments
+ */
+static void alert ( const char *fmt, ... ) {
+ va_list args;
+
+ va_start ( args, fmt );
+ valert ( fmt, args );
+ va_end ( args );
+}
+
+/**
+ * Draw title row
+ *
+ * @v widget Setting widget
+ */
+static void draw_title_row ( struct setting_widget *widget ) {
+ const char *name;
+
+ clearmsg ( TITLE_ROW );
+ name = settings_name ( widget->settings );
+ attron ( A_BOLD );
+ msg ( TITLE_ROW, "iPXE configuration settings%s%s",
+ ( name[0] ? " - " : "" ), name );
+ attroff ( A_BOLD );
+}
+
+/**
+ * Draw information row
+ *
+ * @v widget Setting widget
+ */
+static void draw_info_row ( struct setting_widget *widget ) {
+ struct settings *origin;
+ char buf[32];
+
+ /* Draw nothing unless this row represents a setting */
+ clearmsg ( INFO_ROW );
+ clearmsg ( INFO_ROW + 1 );
+ if ( ! widget->row.setting )
+ return;
+
+ /* Determine a suitable setting name */
+ origin = fetch_setting_origin ( widget->settings, widget->row.setting );
+ if ( ! origin )
+ origin = widget->settings;
+ setting_name ( origin, widget->row.setting, buf, sizeof ( buf ) );
+
+ /* Draw row */
+ attron ( A_BOLD );
+ msg ( INFO_ROW, "%s - %s", buf, widget->row.setting->description );
+ attroff ( A_BOLD );
+ color_set ( CPAIR_URL, NULL );
+ msg ( ( INFO_ROW + 1 ), "http://ipxe.org/cfg/%s",
+ widget->row.setting->name );
+ color_set ( CPAIR_NORMAL, NULL );
+}
+
+/**
+ * Draw instruction row
+ *
+ * @v widget Setting widget
+ */
+static void draw_instruction_row ( struct setting_widget *widget ) {
+
+ clearmsg ( INSTRUCTION_ROW );
+ if ( widget->row.editing ) {
+ msg ( INSTRUCTION_ROW,
+ "Enter - accept changes" INSTRUCTION_PAD
+ "Ctrl-C - discard changes" );
+ } else {
+ msg ( INSTRUCTION_ROW,
+ "%sCtrl-X - exit configuration utility",
+ ( widget->row.originates_here ?
+ "Ctrl-D - delete setting" INSTRUCTION_PAD : "" ) );
+ }
+}
+
+/**
+ * Reveal setting row
+ *
+ * @v widget Setting widget
+ * @v index Index of setting row
+ */
+static void reveal_setting_row ( struct setting_widget *widget,
+ unsigned int index ) {
+ unsigned int i;
+
+ /* Simply return if setting N is already on-screen. */
+ if ( index - widget->first_visible < SETTINGS_LIST_ROWS )
+ return;
+
+ /* Jump scroll to make the specified setting row visible. */
+ while ( widget->first_visible < index )
+ widget->first_visible += SETTINGS_LIST_ROWS;
+ while ( widget->first_visible > index )
+ widget->first_visible -= SETTINGS_LIST_ROWS;
+
+ /* Draw ellipses before and/or after the settings list to
+ * represent any invisible settings.
+ */
+ mvaddstr ( SETTINGS_LIST_ROW - 1,
+ SETTINGS_LIST_COL + 1,
+ widget->first_visible > 0 ? "..." : " " );
+ mvaddstr ( SETTINGS_LIST_ROW + SETTINGS_LIST_ROWS,
+ SETTINGS_LIST_COL + 1,
+ ( ( widget->first_visible + SETTINGS_LIST_ROWS )
+ < widget->num_rows ? "..." : " " ) );
+
+ /* Draw visible settings. */
+ for ( i = 0; i < SETTINGS_LIST_ROWS; i++ ) {
+ if ( ( widget->first_visible + i ) < widget->num_rows ) {
+ select_setting_row ( widget,
+ widget->first_visible + i );
+ draw_setting_row ( widget );
+ } else {
+ clearmsg ( SETTINGS_LIST_ROW + i );
+ }
+ }
+}
+
+/**
+ * Reveal setting row
+ *
+ * @v widget Setting widget
+ * @v settings Settings block
+ */
+static void init_widget ( struct setting_widget *widget,
+ struct settings *settings ) {
+
+ widget->settings = settings;
+ widget->num_rows = select_setting_row ( widget, 0 );
+ widget->first_visible = SETTINGS_LIST_ROWS;
+ draw_title_row ( widget );
+ reveal_setting_row ( widget, 0 );
+ select_setting_row ( widget, 0 );
+}
+
+static int main_loop ( struct settings *settings ) {
+ struct setting_widget widget;
+ int redraw = 1;
+ int move;
+ unsigned int next;
+ int key;
+ int rc;
+
+ /* Print initial screen content */
+ color_set ( CPAIR_NORMAL, NULL );
+ memset ( &widget, 0, sizeof ( widget ) );
+ init_widget ( &widget, settings );
+
+ while ( 1 ) {
+
+ /* Redraw rows if necessary */
+ if ( redraw ) {
+ draw_info_row ( &widget );
+ draw_instruction_row ( &widget );
+ color_set ( ( widget.row.editing ?
+ CPAIR_EDIT : CPAIR_SELECT ), NULL );
+ draw_setting_row ( &widget );
+ color_set ( CPAIR_NORMAL, NULL );
+ redraw = 0;
+ }
+
+ if ( widget.row.editing ) {
+
+ /* Sanity check */
+ assert ( widget.row.setting != NULL );
+
+ /* Redraw edit box */
+ color_set ( CPAIR_EDIT, NULL );
+ draw_editbox ( &widget.row.editbox );
+ color_set ( CPAIR_NORMAL, NULL );
+
+ /* Process keypress */
+ key = edit_setting ( &widget, getkey ( 0 ) );
+ switch ( key ) {
+ case CR:
+ case LF:
+ if ( ( rc = save_setting ( &widget ) ) != 0 )
+ alert ( " %s ", strerror ( rc ) );
+ /* Fall through */
+ case CTRL_C:
+ select_setting_row ( &widget, widget.current );
+ redraw = 1;
+ break;
+ default:
+ /* Do nothing */
+ break;
+ }
+
+ } else {
+
+ /* Process keypress */
+ key = getkey ( 0 );
+ move = 0;
+ switch ( key ) {
+ case KEY_DOWN:
+ if ( widget.current < ( widget.num_rows - 1 ) )
+ move = +1;
+ break;
+ case KEY_UP:
+ if ( widget.current > 0 )
+ move = -1;
+ break;
+ case CTRL_D:
+ if ( ! widget.row.setting )
+ break;
+ if ( ( rc = delete_setting ( widget.settings,
+ widget.row.setting ) ) != 0 ) {
+ alert ( " %s ", strerror ( rc ) );
+ }
+ select_setting_row ( &widget, widget.current );
+ redraw = 1;
+ break;
+ case CTRL_X:
+ return 0;
+ case CR:
+ case LF:
+ if ( widget.row.settings ) {
+ init_widget ( &widget,
+ widget.row.settings );
+ redraw = 1;
+ }
+ /* Fall through */
+ default:
+ if ( widget.row.setting ) {
+ edit_setting ( &widget, key );
+ redraw = 1;
+ }
+ break;
+ }
+ if ( move ) {
+ next = ( widget.current + move );
+ draw_setting_row ( &widget );
+ redraw = 1;
+ reveal_setting_row ( &widget, next );
+ select_setting_row ( &widget, next );
+ }
+ }
+ }
+}
+
+int settings_ui ( struct settings *settings ) {
+ int rc;
+
+ initscr();
+ start_color();
+ init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLUE );
+ init_pair ( CPAIR_SELECT, COLOR_WHITE, COLOR_RED );
+ init_pair ( CPAIR_EDIT, COLOR_BLACK, COLOR_CYAN );
+ init_pair ( CPAIR_ALERT, COLOR_WHITE, COLOR_RED );
+ init_pair ( CPAIR_URL, COLOR_CYAN, COLOR_BLUE );
+ color_set ( CPAIR_NORMAL, NULL );
+ erase();
+
+ rc = main_loop ( settings );
+
+ endwin();
+
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/hci/wireless_errors.c b/src/VBox/Devices/PC/ipxe/src/hci/wireless_errors.c
new file mode 100644
index 00000000..63c6251c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/hci/wireless_errors.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <ipxe/errortab.h>
+#include <ipxe/net80211_err.h>
+
+/* Record errors as though they come from the 802.11 stack */
+#undef ERRFILE
+#define ERRFILE ERRFILE_net80211
+
+/** All 802.11 errors
+ */
+struct errortab wireless_errors[] __errortab = {
+ __einfo_errortab ( EINFO_EINVAL_PKT_TOO_SHORT ),
+ __einfo_errortab ( EINFO_EINVAL_PKT_VERSION ),
+ __einfo_errortab ( EINFO_EINVAL_PKT_NOT_DATA ),
+ __einfo_errortab ( EINFO_EINVAL_PKT_NOT_FROMDS ),
+ __einfo_errortab ( EINFO_EINVAL_PKT_LLC_HEADER ),
+ __einfo_errortab ( EINFO_EINVAL_CRYPTO_REQUEST ),
+ __einfo_errortab ( EINFO_EINVAL_ACTIVE_SCAN ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_FAILURE ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_CAPAB_UNSUPP ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_REASSOC_INVALID ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_DENIED ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_ALGO_UNSUPP ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_SEQ_INVALID ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_CHALL_INVALID ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_TIMEOUT ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NO_ROOM ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_RATE ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_PMBL ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_PBCC ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_BAD_POWER ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_BAD_CHANNELS ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_SLOT ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_DSSS_OFDM ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_QOS_FAILURE ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_QOS_NO_ROOM ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_LINK_IS_HORRIBLE ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_ASSOC_NEED_QOS ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_REQUEST_DECLINED ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_REQUEST_INVALID ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_TS_NOT_CREATED_AGAIN ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_INVALID_IE ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_GROUP_CIPHER_INVALID ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_PAIR_CIPHER_INVALID ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_AKMP_INVALID ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_RSN_VERSION_UNSUPP ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_RSN_CAPAB_INVALID ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_CIPHER_REJECTED ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_TS_NOT_CREATED_WAIT ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_DIRECT_LINK_FORBIDDEN ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_DEST_NOT_PRESENT ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_DEST_NOT_QOS ),
+ __einfo_errortab ( EINFO_EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH ),
+ __einfo_errortab ( EINFO_ECONNRESET_UNSPECIFIED ),
+ __einfo_errortab ( EINFO_ECONNRESET_AUTH_NO_LONGER_VALID ),
+ __einfo_errortab ( EINFO_ECONNRESET_LEAVING ),
+ __einfo_errortab ( EINFO_ECONNRESET_INACTIVITY ),
+ __einfo_errortab ( EINFO_ECONNRESET_OUT_OF_RESOURCES ),
+ __einfo_errortab ( EINFO_ECONNRESET_NEED_AUTH ),
+ __einfo_errortab ( EINFO_ECONNRESET_NEED_ASSOC ),
+ __einfo_errortab ( EINFO_ECONNRESET_LEAVING_TO_ROAM ),
+ __einfo_errortab ( EINFO_ECONNRESET_REASSOC_INVALID ),
+ __einfo_errortab ( EINFO_ECONNRESET_BAD_POWER ),
+ __einfo_errortab ( EINFO_ECONNRESET_BAD_CHANNELS ),
+ __einfo_errortab ( EINFO_ECONNRESET_INVALID_IE ),
+ __einfo_errortab ( EINFO_ECONNRESET_MIC_FAILURE ),
+ __einfo_errortab ( EINFO_ECONNRESET_4WAY_TIMEOUT ),
+ __einfo_errortab ( EINFO_ECONNRESET_GROUPKEY_TIMEOUT ),
+ __einfo_errortab ( EINFO_ECONNRESET_4WAY_INVALID ),
+ __einfo_errortab ( EINFO_ECONNRESET_GROUP_CIPHER_INVALID ),
+ __einfo_errortab ( EINFO_ECONNRESET_PAIR_CIPHER_INVALID ),
+ __einfo_errortab ( EINFO_ECONNRESET_AKMP_INVALID ),
+ __einfo_errortab ( EINFO_ECONNRESET_RSN_VERSION_INVALID ),
+ __einfo_errortab ( EINFO_ECONNRESET_RSN_CAPAB_INVALID ),
+ __einfo_errortab ( EINFO_ECONNRESET_8021X_FAILURE ),
+ __einfo_errortab ( EINFO_ECONNRESET_CIPHER_REJECTED ),
+ __einfo_errortab ( EINFO_ENETRESET_QOS_UNSPECIFIED ),
+ __einfo_errortab ( EINFO_ENETRESET_QOS_OUT_OF_RESOURCES ),
+ __einfo_errortab ( EINFO_ENETRESET_LINK_IS_HORRIBLE ),
+ __einfo_errortab ( EINFO_ENETRESET_INVALID_TXOP ),
+ __einfo_errortab ( EINFO_ENETRESET_REQUESTED_LEAVING ),
+ __einfo_errortab ( EINFO_ENETRESET_REQUESTED_NO_USE ),
+ __einfo_errortab ( EINFO_ENETRESET_REQUESTED_NEED_SETUP ),
+ __einfo_errortab ( EINFO_ENETRESET_REQUESTED_TIMEOUT ),
+ __einfo_errortab ( EINFO_ENETRESET_CIPHER_UNSUPPORTED ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/image/efi_image.c b/src/VBox/Devices/PC/ipxe/src/image/efi_image.c
new file mode 100644
index 00000000..9b9e7600
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/image/efi_image.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <stdlib.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/image.h>
+#include <ipxe/init.h>
+#include <ipxe/features.h>
+#include <ipxe/uri.h>
+
+FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 );
+
+/** EFI loaded image protocol GUID */
+static EFI_GUID efi_loaded_image_protocol_guid =
+ EFI_LOADED_IMAGE_PROTOCOL_GUID;
+
+/**
+ * Create a Unicode command line for the image
+ *
+ * @v image EFI image
+ * @v devpath_out Device path to pass to image (output)
+ * @v cmdline_out Unicode command line (output)
+ * @v cmdline_len_out Length of command line in bytes (output)
+ * @ret rc Return status code
+ */
+static int efi_image_make_cmdline ( struct image *image,
+ EFI_DEVICE_PATH **devpath_out,
+ VOID **cmdline_out,
+ UINT32 *cmdline_len_out ) {
+ char *uri;
+ size_t uri_len;
+ FILEPATH_DEVICE_PATH *devpath;
+ EFI_DEVICE_PATH *endpath;
+ size_t devpath_len;
+ CHAR16 *cmdline;
+ UINT32 cmdline_len;
+ size_t args_len = 0;
+ UINT32 i;
+
+ /* Get the URI string of the image */
+ uri_len = unparse_uri ( NULL, 0, image->uri, URI_ALL ) + 1;
+
+ /* Compute final command line length */
+ if ( image->cmdline ) {
+ args_len = strlen ( image->cmdline ) + 1;
+ }
+ cmdline_len = args_len + uri_len;
+
+ /* Allocate space for the uri, final command line and device path */
+ cmdline = malloc ( cmdline_len * sizeof ( CHAR16 ) + uri_len
+ + SIZE_OF_FILEPATH_DEVICE_PATH
+ + uri_len * sizeof ( CHAR16 )
+ + sizeof ( EFI_DEVICE_PATH ) );
+ if ( ! cmdline )
+ return -ENOMEM;
+ uri = (char *) ( cmdline + cmdline_len );
+ devpath = (FILEPATH_DEVICE_PATH *) ( uri + uri_len );
+ endpath = (EFI_DEVICE_PATH *) ( (char *) devpath
+ + SIZE_OF_FILEPATH_DEVICE_PATH
+ + uri_len * sizeof ( CHAR16 ) );
+
+ /* Build the iPXE device path */
+ devpath->Header.Type = MEDIA_DEVICE_PATH;
+ devpath->Header.SubType = MEDIA_FILEPATH_DP;
+ devpath_len = SIZE_OF_FILEPATH_DEVICE_PATH
+ + uri_len * sizeof ( CHAR16 );
+ devpath->Header.Length[0] = devpath_len & 0xFF;
+ devpath->Header.Length[1] = devpath_len >> 8;
+ endpath->Type = END_DEVICE_PATH_TYPE;
+ endpath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ endpath->Length[0] = 4;
+ endpath->Length[1] = 0;
+ unparse_uri ( uri, uri_len, image->uri, URI_ALL );
+
+ /* Convert to Unicode */
+ for ( i = 0 ; i < uri_len ; i++ ) {
+ cmdline[i] = uri[i];
+ devpath->PathName[i] = uri[i];
+ }
+ if ( image->cmdline ) {
+ cmdline[uri_len - 1] = ' ';
+ }
+ for ( i = 0 ; i < args_len ; i++ ) {
+ cmdline[i + uri_len] = image->cmdline[i];
+ }
+
+ *devpath_out = &devpath->Header;
+ *cmdline_out = cmdline;
+ *cmdline_len_out = cmdline_len * sizeof ( CHAR16 );
+ return 0;
+}
+
+/**
+ * Execute EFI image
+ *
+ * @v image EFI image
+ * @ret rc Return status code
+ */
+static int efi_image_exec ( struct image *image ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ union {
+ EFI_LOADED_IMAGE_PROTOCOL *image;
+ void *interface;
+ } loaded;
+ EFI_HANDLE handle;
+ EFI_HANDLE device_handle = NULL;
+ UINTN exit_data_size;
+ CHAR16 *exit_data;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Attempt loading image */
+ if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL,
+ user_to_virt ( image->data, 0 ),
+ image->len, &handle ) ) != 0 ) {
+ /* Not an EFI image */
+ DBGC ( image, "EFIIMAGE %p could not load: %s\n",
+ image, efi_strerror ( efirc ) );
+ rc = -ENOEXEC;
+ goto err_load_image;
+ }
+
+ /* Get the loaded image protocol for the newly loaded image */
+ efirc = bs->OpenProtocol ( handle, &efi_loaded_image_protocol_guid,
+ &loaded.interface, efi_image_handle,
+ NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+ if ( efirc ) {
+ /* Should never happen */
+ rc = EFIRC_TO_RC ( efirc );
+ goto err_open_protocol;
+ }
+
+ /* Pass an iPXE download protocol to the image */
+ if ( ( rc = efi_download_install ( &device_handle ) ) != 0 ) {
+ DBGC ( image, "EFIIMAGE %p could not install iPXE download "
+ "protocol: %s\n", image, strerror ( rc ) );
+ goto err_download_install;
+ }
+ loaded.image->DeviceHandle = device_handle;
+ loaded.image->ParentHandle = efi_loaded_image;
+ if ( ( rc = efi_image_make_cmdline ( image, &loaded.image->FilePath,
+ &loaded.image->LoadOptions,
+ &loaded.image->LoadOptionsSize ) ) != 0 )
+ goto err_make_cmdline;
+
+ /* Start the image */
+ if ( ( efirc = bs->StartImage ( handle, &exit_data_size,
+ &exit_data ) ) != 0 ) {
+ DBGC ( image, "EFIIMAGE %p returned with status %s\n",
+ image, efi_strerror ( efirc ) );
+ rc = EFIRC_TO_RC ( efirc );
+ goto err_start_image;
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_start_image:
+ free ( loaded.image->LoadOptions );
+ err_make_cmdline:
+ efi_download_uninstall ( device_handle );
+ err_download_install:
+ err_open_protocol:
+ /* Unload the image. We can't leave it loaded, because we
+ * have no "unload" operation.
+ */
+ bs->UnloadImage ( handle );
+ err_load_image:
+
+ return rc;
+}
+
+/**
+ * Probe EFI image
+ *
+ * @v image EFI file
+ * @ret rc Return status code
+ */
+static int efi_image_probe ( struct image *image ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_HANDLE handle;
+ EFI_STATUS efirc;
+
+ /* Attempt loading image */
+ if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL,
+ user_to_virt ( image->data, 0 ),
+ image->len, &handle ) ) != 0 ) {
+ /* Not an EFI image */
+ DBGC ( image, "EFIIMAGE %p could not load: %s\n",
+ image, efi_strerror ( efirc ) );
+ return -ENOEXEC;
+ }
+
+ /* Unload the image. We can't leave it loaded, because we
+ * have no "unload" operation.
+ */
+ bs->UnloadImage ( handle );
+
+ return 0;
+}
+
+/** EFI image type */
+struct image_type efi_image_type __image_type ( PROBE_NORMAL ) = {
+ .name = "EFI",
+ .probe = efi_image_probe,
+ .exec = efi_image_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/image/elf.c b/src/VBox/Devices/PC/ipxe/src/image/elf.c
new file mode 100644
index 00000000..26666ec5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/image/elf.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * ELF image format
+ *
+ * A "pure" ELF image is not a bootable image. There are various
+ * bootable formats based upon ELF (e.g. Multiboot), which share
+ * common ELF-related functionality.
+ */
+
+#include <errno.h>
+#include <elf.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/segment.h>
+#include <ipxe/image.h>
+#include <ipxe/elf.h>
+
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Phdr Elf_Phdr;
+typedef Elf32_Off Elf_Off;
+#define ELFCLASS ELFCLASS32
+
+/**
+ * Load ELF segment into memory
+ *
+ * @v image ELF file
+ * @v phdr ELF program header
+ * @v ehdr ELF executable header
+ * @ret entry Entry point, if found
+ * @ret max Maximum used address
+ * @ret rc Return status code
+ */
+static int elf_load_segment ( struct image *image, Elf_Phdr *phdr,
+ Elf_Ehdr *ehdr, physaddr_t *entry,
+ physaddr_t *max ) {
+ physaddr_t dest;
+ physaddr_t end;
+ userptr_t buffer;
+ unsigned long e_offset;
+ int rc;
+
+ /* Do nothing for non-PT_LOAD segments */
+ if ( phdr->p_type != PT_LOAD )
+ return 0;
+
+ /* Check segment lies within image */
+ if ( ( phdr->p_offset + phdr->p_filesz ) > image->len ) {
+ DBGC ( image, "ELF %p segment outside image\n", image );
+ return -ENOEXEC;
+ }
+
+ /* Find start address: use physical address for preference,
+ * fall back to virtual address if no physical address
+ * supplied.
+ */
+ dest = phdr->p_paddr;
+ if ( ! dest )
+ dest = phdr->p_vaddr;
+ if ( ! dest ) {
+ DBGC ( image, "ELF %p segment loads to physical address 0\n",
+ image );
+ return -ENOEXEC;
+ }
+ buffer = phys_to_user ( dest );
+ end = ( dest + phdr->p_memsz );
+
+ DBGC ( image, "ELF %p loading segment [%x,%x) to [%x,%x,%x)\n", image,
+ phdr->p_offset, ( phdr->p_offset + phdr->p_filesz ),
+ phdr->p_paddr, ( phdr->p_paddr + phdr->p_filesz ),
+ ( phdr->p_paddr + phdr->p_memsz ) );
+
+ /* Verify and prepare segment */
+ if ( ( rc = prep_segment ( buffer, phdr->p_filesz,
+ phdr->p_memsz ) ) != 0 ) {
+ DBGC ( image, "ELF %p could not prepare segment: %s\n",
+ image, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Update maximum used address, if applicable */
+ if ( end > *max )
+ *max = end;
+
+ /* Copy image to segment */
+ memcpy_user ( buffer, 0, image->data, phdr->p_offset, phdr->p_filesz );
+
+ /* Set execution address, if it lies within this segment */
+ if ( ( e_offset = ( ehdr->e_entry - dest ) ) < phdr->p_filesz ) {
+ *entry = ehdr->e_entry;
+ DBGC ( image, "ELF %p found physical entry point at %lx\n",
+ image, *entry );
+ } else if ( ( e_offset = ( ehdr->e_entry - phdr->p_vaddr ) )
+ < phdr->p_filesz ) {
+ if ( ! *entry ) {
+ *entry = ( dest + e_offset );
+ DBGC ( image, "ELF %p found virtual entry point at %lx"
+ " (virt %lx)\n", image, *entry,
+ ( ( unsigned long ) ehdr->e_entry ) );
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Load ELF image into memory
+ *
+ * @v image ELF file
+ * @ret entry Entry point
+ * @ret max Maximum used address
+ * @ret rc Return status code
+ */
+int elf_load ( struct image *image, physaddr_t *entry, physaddr_t *max ) {
+ static const uint8_t e_ident[] = {
+ [EI_MAG0] = ELFMAG0,
+ [EI_MAG1] = ELFMAG1,
+ [EI_MAG2] = ELFMAG2,
+ [EI_MAG3] = ELFMAG3,
+ [EI_CLASS] = ELFCLASS,
+ };
+ Elf_Ehdr ehdr;
+ Elf_Phdr phdr;
+ Elf_Off phoff;
+ unsigned int phnum;
+ int rc;
+
+ /* Read ELF header */
+ copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
+ if ( memcmp ( &ehdr.e_ident[EI_MAG0], e_ident,
+ sizeof ( e_ident ) ) != 0 ) {
+ DBGC ( image, "ELF %p has invalid signature\n", image );
+ return -ENOEXEC;
+ }
+
+ /* Initialise maximum used address */
+ *max = 0;
+
+ /* Invalidate entry point */
+ *entry = 0;
+
+ /* Read ELF program headers */
+ for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ;
+ phoff += ehdr.e_phentsize, phnum-- ) {
+ if ( phoff > image->len ) {
+ DBGC ( image, "ELF %p program header %d outside "
+ "image\n", image, phnum );
+ return -ENOEXEC;
+ }
+ copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) );
+ if ( ( rc = elf_load_segment ( image, &phdr, &ehdr,
+ entry, max ) ) != 0 ) {
+ return rc;
+ }
+ }
+
+ /* Check for a valid execution address */
+ if ( ! *entry ) {
+ DBGC ( image, "ELF %p entry point %lx outside image\n",
+ image, ( ( unsigned long ) ehdr.e_entry ) );
+ return -ENOEXEC;
+ }
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/image/embedded.c b/src/VBox/Devices/PC/ipxe/src/image/embedded.c
new file mode 100644
index 00000000..6358378f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/image/embedded.c
@@ -0,0 +1,91 @@
+/** @file
+ *
+ * Embedded image support
+ *
+ * Embedded images are images built into the iPXE binary and do not require
+ * fetching over the network.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <ipxe/image.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/init.h>
+
+/* Raw image data for all embedded images */
+#undef EMBED
+#define EMBED( _index, _path, _name ) \
+ extern char embedded_image_ ## _index ## _data[]; \
+ extern char embedded_image_ ## _index ## _len[]; \
+ __asm__ ( ".section \".rodata\", \"a\", @progbits\n\t" \
+ "\nembedded_image_" #_index "_data:\n\t" \
+ ".incbin \"" _path "\"\n\t" \
+ "\nembedded_image_" #_index "_end:\n\t" \
+ ".equ embedded_image_" #_index "_len, " \
+ "( embedded_image_" #_index "_end - " \
+ " embedded_image_" #_index "_data )\n\t" \
+ ".previous\n\t" );
+EMBED_ALL
+
+/* Image structures for all embedded images */
+#undef EMBED
+#define EMBED( _index, _path, _name ) { \
+ .refcnt = REF_INIT ( ref_no_free ), \
+ .name = _name, \
+ .data = ( userptr_t ) ( embedded_image_ ## _index ## _data ), \
+ .len = ( size_t ) embedded_image_ ## _index ## _len, \
+},
+static struct image embedded_images[] = {
+ EMBED_ALL
+};
+
+/**
+ * Register all embedded images
+ */
+static void embedded_init ( void ) {
+ int i;
+ struct image *image;
+ void *data;
+ int rc;
+
+ /* Skip if we have no embedded images */
+ if ( ! sizeof ( embedded_images ) )
+ return;
+
+ /* Fix up data pointers and register images */
+ for ( i = 0 ; i < ( int ) ( sizeof ( embedded_images ) /
+ sizeof ( embedded_images[0] ) ) ; i++ ) {
+ image = &embedded_images[i];
+
+ /* virt_to_user() cannot be used in a static
+ * initialiser, so we cast the pointer to a userptr_t
+ * in the initialiser and fix it up here. (This will
+ * actually be a no-op on most platforms.)
+ */
+ data = ( ( void * ) image->data );
+ image->data = virt_to_user ( data );
+
+ DBG ( "Embedded image \"%s\": %zd bytes at %p\n",
+ image->name, image->len, data );
+
+ if ( ( rc = register_image ( image ) ) != 0 ) {
+ DBG ( "Could not register embedded image \"%s\": "
+ "%s\n", image->name, strerror ( rc ) );
+ return;
+ }
+ }
+
+ /* Select the first image */
+ image = &embedded_images[0];
+ if ( ( rc = image_select ( image ) ) != 0 ) {
+ DBG ( "Could not select embedded image \"%s\": %s\n",
+ image->name, strerror ( rc ) );
+ return;
+ }
+}
+
+/** Embedded image initialisation function */
+struct init_fn embedded_init_fn __init_fn ( INIT_LATE ) = {
+ .initialise = embedded_init,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/image/script.c b/src/VBox/Devices/PC/ipxe/src/image/script.c
new file mode 100644
index 00000000..b032d18f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/image/script.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * iPXE scripts
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/image.h>
+#include <ipxe/shell.h>
+#include <usr/prompt.h>
+#include <ipxe/script.h>
+
+/** Offset within current script
+ *
+ * This is a global in order to allow goto_exec() to update the
+ * offset.
+ */
+static size_t script_offset;
+
+/**
+ * Process script lines
+ *
+ * @v image Script
+ * @v process_line Line processor
+ * @v terminate Termination check
+ * @ret rc Return status code
+ */
+static int process_script ( struct image *image,
+ int ( * process_line ) ( const char *line ),
+ int ( * terminate ) ( int rc ) ) {
+ off_t eol;
+ size_t len;
+ char *line;
+ int rc;
+
+ script_offset = 0;
+
+ do {
+
+ /* Find length of next line, excluding any terminating '\n' */
+ eol = memchr_user ( image->data, script_offset, '\n',
+ ( image->len - script_offset ) );
+ if ( eol < 0 )
+ eol = image->len;
+ len = ( eol - script_offset );
+
+ /* Allocate buffer for line */
+ line = zalloc ( len + 1 /* NUL */ );
+ if ( ! line )
+ return -ENOMEM;
+
+ /* Copy line */
+ copy_from_user ( line, image->data, script_offset, len );
+ DBG ( "$ %s\n", line );
+
+ /* Move to next line */
+ script_offset += ( len + 1 );
+
+ /* Process and free line */
+ rc = process_line ( line );
+ free ( line );
+ if ( terminate ( rc ) )
+ return rc;
+
+ } while ( script_offset < image->len );
+
+ return rc;
+}
+
+/**
+ * Terminate script processing on shell exit or command failure
+ *
+ * @v rc Line processing status
+ * @ret terminate Terminate script processing
+ */
+static int terminate_on_exit_or_failure ( int rc ) {
+
+ return ( shell_stopped ( SHELL_STOP_COMMAND_SEQUENCE ) ||
+ ( rc != 0 ) );
+}
+
+/**
+ * Execute script line
+ *
+ * @v line Line of script
+ * @ret rc Return status code
+ */
+static int script_exec_line ( const char *line ) {
+ int rc;
+
+ /* Skip label lines */
+ if ( line[0] == ':' )
+ return 0;
+
+ /* Execute command */
+ if ( ( rc = system ( line ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Execute script
+ *
+ * @v image Script
+ * @ret rc Return status code
+ */
+static int script_exec ( struct image *image ) {
+ size_t saved_offset;
+ int rc;
+
+ /* Temporarily de-register image, so that a "boot" command
+ * doesn't throw us into an execution loop.
+ */
+ unregister_image ( image );
+
+ /* Preserve state of any currently-running script */
+ saved_offset = script_offset;
+
+ /* Process script */
+ rc = process_script ( image, script_exec_line,
+ terminate_on_exit_or_failure );
+
+ /* Restore saved state */
+ script_offset = saved_offset;
+
+ /* Re-register image (unless we have been replaced) */
+ if ( ! image->replacement )
+ register_image ( image );
+
+ return rc;
+}
+
+/**
+ * Probe script image
+ *
+ * @v image Script
+ * @ret rc Return status code
+ */
+static int script_probe ( struct image *image ) {
+ static const char ipxe_magic[] = "#!ipxe";
+ static const char gpxe_magic[] = "#!gpxe";
+ linker_assert ( sizeof ( ipxe_magic ) == sizeof ( gpxe_magic ),
+ magic_size_mismatch );
+ char test[ sizeof ( ipxe_magic ) - 1 /* NUL */
+ + 1 /* terminating space */];
+
+ /* Sanity check */
+ if ( image->len < sizeof ( test ) ) {
+ DBG ( "Too short to be a script\n" );
+ return -ENOEXEC;
+ }
+
+ /* Check for magic signature */
+ copy_from_user ( test, image->data, 0, sizeof ( test ) );
+ if ( ! ( ( ( memcmp ( test, ipxe_magic, sizeof ( test ) - 1 ) == 0 ) ||
+ ( memcmp ( test, gpxe_magic, sizeof ( test ) - 1 ) == 0 )) &&
+ isspace ( test[ sizeof ( test ) - 1 ] ) ) ) {
+ DBG ( "Invalid magic signature\n" );
+ return -ENOEXEC;
+ }
+
+ return 0;
+}
+
+/** Script image type */
+struct image_type script_image_type __image_type ( PROBE_NORMAL ) = {
+ .name = "script",
+ .probe = script_probe,
+ .exec = script_exec,
+};
+
+/** "goto" options */
+struct goto_options {};
+
+/** "goto" option list */
+static struct option_descriptor goto_opts[] = {};
+
+/** "goto" command descriptor */
+static struct command_descriptor goto_cmd =
+ COMMAND_DESC ( struct goto_options, goto_opts, 1, 1, "<label>" );
+
+/**
+ * Current "goto" label
+ *
+ * Valid only during goto_exec(). Consider this part of a closure.
+ */
+static const char *goto_label;
+
+/**
+ * Check for presence of label
+ *
+ * @v line Script line
+ * @ret rc Return status code
+ */
+static int goto_find_label ( const char *line ) {
+ size_t len = strlen ( goto_label );
+
+ if ( line[0] != ':' )
+ return -ENOENT;
+
+ if ( strncmp ( goto_label, &line[1], len ) != 0 )
+ return -ENOENT;
+
+ if ( line[ 1 + len ] && ! isspace ( line[ 1 + len ] ) )
+ return -ENOENT;
+
+ return 0;
+}
+
+/**
+ * Terminate script processing when label is found
+ *
+ * @v rc Line processing status
+ * @ret terminate Terminate script processing
+ */
+static int terminate_on_label_found ( int rc ) {
+ return ( rc == 0 );
+}
+
+/**
+ * "goto" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int goto_exec ( int argc, char **argv ) {
+ struct goto_options opts;
+ size_t saved_offset;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &goto_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Sanity check */
+ if ( ! current_image ) {
+ rc = -ENOTTY;
+ printf ( "Not in a script: %s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ /* Parse label */
+ goto_label = argv[optind];
+
+ /* Find label */
+ saved_offset = script_offset;
+ if ( ( rc = process_script ( current_image, goto_find_label,
+ terminate_on_label_found ) ) != 0 ) {
+ script_offset = saved_offset;
+ return rc;
+ }
+
+ /* Terminate processing of current command */
+ shell_stop ( SHELL_STOP_COMMAND );
+
+ return 0;
+}
+
+/** "goto" command */
+struct command goto_command __command = {
+ .name = "goto",
+ .exec = goto_exec,
+};
+
+/** "prompt" options */
+struct prompt_options {
+ /** Key to wait for */
+ unsigned int key;
+ /** Timeout */
+ unsigned int timeout;
+};
+
+/** "prompt" option list */
+static struct option_descriptor prompt_opts[] = {
+ OPTION_DESC ( "key", 'k', required_argument,
+ struct prompt_options, key, parse_key ),
+ OPTION_DESC ( "timeout", 't', required_argument,
+ struct prompt_options, timeout, parse_integer ),
+};
+
+/** "prompt" command descriptor */
+static struct command_descriptor prompt_cmd =
+ COMMAND_DESC ( struct prompt_options, prompt_opts, 0, MAX_ARGUMENTS,
+ "[--key <key>] [--timeout <timeout>] [<text>]" );
+
+/**
+ * "prompt" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int prompt_exec ( int argc, char **argv ) {
+ struct prompt_options opts;
+ char *text;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &prompt_cmd, &opts ) ) != 0 )
+ goto err_parse;
+
+ /* Parse prompt text */
+ text = concat_args ( &argv[optind] );
+ if ( ! text ) {
+ rc = -ENOMEM;
+ goto err_concat;
+ }
+
+ /* Display prompt and wait for key */
+ if ( ( rc = prompt ( text, opts.timeout, opts.key ) ) != 0 )
+ goto err_prompt;
+
+ /* Free prompt text */
+ free ( text );
+
+ return 0;
+
+ err_prompt:
+ free ( text );
+ err_concat:
+ err_parse:
+ return rc;
+}
+
+/** "prompt" command */
+struct command prompt_command __command = {
+ .name = "prompt",
+ .exec = prompt_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/image/segment.c b/src/VBox/Devices/PC/ipxe/src/image/segment.c
new file mode 100644
index 00000000..97f6a995
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/image/segment.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Executable image segments
+ *
+ */
+
+#include <errno.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/io.h>
+#include <ipxe/errortab.h>
+#include <ipxe/segment.h>
+
+/**
+ * Segment-specific error messages
+ *
+ * This error happens sufficiently often to merit a user-friendly
+ * description.
+ */
+#define ERANGE_SEGMENT __einfo_error ( EINFO_ERANGE_SEGMENT )
+#define EINFO_ERANGE_SEGMENT \
+ __einfo_uniqify ( EINFO_ERANGE, 0x01, "Requested memory not available" )
+struct errortab segment_errors[] __errortab = {
+ __einfo_errortab ( EINFO_ERANGE_SEGMENT ),
+};
+
+/**
+ * Prepare segment for loading
+ *
+ * @v segment Segment start
+ * @v filesz Size of the "allocated bytes" portion of the segment
+ * @v memsz Size of the segment
+ * @ret rc Return status code
+ */
+int prep_segment ( userptr_t segment, size_t filesz, size_t memsz ) {
+ struct memory_map memmap;
+ physaddr_t start = user_to_phys ( segment, 0 );
+ physaddr_t mid = user_to_phys ( segment, filesz );
+ physaddr_t end = user_to_phys ( segment, memsz );
+ unsigned int i;
+
+ DBG ( "Preparing segment [%lx,%lx,%lx)\n", start, mid, end );
+
+ /* Sanity check */
+ if ( filesz > memsz ) {
+ DBG ( "Insane segment [%lx,%lx,%lx)\n", start, mid, end );
+ return -EINVAL;
+ }
+
+ /* Get a fresh memory map. This allows us to automatically
+ * avoid treading on any regions that Etherboot is currently
+ * editing out of the memory map.
+ */
+ get_memmap ( &memmap );
+
+ /* Look for a suitable memory region */
+ for ( i = 0 ; i < memmap.count ; i++ ) {
+ if ( ( start >= memmap.regions[i].start ) &&
+ ( end <= memmap.regions[i].end ) ) {
+ /* Found valid region: zero bss and return */
+ memset_user ( segment, filesz, 0, ( memsz - filesz ) );
+ return 0;
+ }
+ }
+
+ /* No suitable memory region found */
+ DBG ( "Segment [%lx,%lx,%lx) does not fit into available memory\n",
+ start, mid, end );
+ return -ERANGE_SEGMENT;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/include/alloca.h b/src/VBox/Devices/PC/ipxe/src/include/alloca.h
new file mode 100644
index 00000000..08398fb3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/alloca.h
@@ -0,0 +1,25 @@
+#ifndef _ALLOCA_H
+#define _ALLOCA_H
+
+/**
+ * @file
+ *
+ * Temporary memory allocation
+ *
+ */
+
+#include <stdint.h>
+
+/**
+ * Allocate temporary memory from the stack
+ *
+ * @v size Size to allocate
+ * @ret ptr Allocated memory
+ *
+ * This memory will be freed automatically when the containing
+ * function returns. There are several caveats regarding use of
+ * alloca(); use it only if you already know what they are.
+ */
+#define alloca(size) __builtin_alloca ( size )
+
+#endif /* _ALLOCA_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/assert.h b/src/VBox/Devices/PC/ipxe/src/include/assert.h
new file mode 100644
index 00000000..655cbdc0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/assert.h
@@ -0,0 +1,70 @@
+#ifndef _ASSERT_H
+#define _ASSERT_H
+
+/** @file
+ *
+ * Assertions
+ *
+ * This file provides two assertion macros: assert() (for run-time
+ * assertions) and linker_assert() (for link-time assertions).
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef NDEBUG
+#define ASSERTING 0
+#else
+#define ASSERTING 1
+#endif
+
+extern unsigned int assertion_failures;
+
+/** printf() for assertions
+ *
+ * This function exists so that the assert() macro can expand to
+ * printf() calls without dragging the printf() prototype into scope.
+ *
+ * As far as the compiler is concerned, assert_printf() and printf() are
+ * completely unrelated calls; it's only at the assembly stage that
+ * references to the assert_printf symbol are collapsed into references
+ * to the printf symbol.
+ */
+extern int __attribute__ (( format ( printf, 1, 2 ) ))
+assert_printf ( const char *fmt, ... ) asm ( "printf" );
+
+/**
+ * Assert a condition at run-time.
+ *
+ * If the condition is not true, a debug message will be printed.
+ * Assertions only take effect in debug-enabled builds (see DBG()).
+ *
+ * @todo Make an assertion failure abort the program
+ *
+ */
+#define assert( condition ) \
+ do { \
+ if ( ASSERTING && ! (condition) ) { \
+ assertion_failures++; \
+ assert_printf ( "assert(%s) failed at %s line %d\n", \
+ #condition, __FILE__, __LINE__ ); \
+ } \
+ } while ( 0 )
+
+/**
+ * Assert a condition at link-time.
+ *
+ * If the condition is not true, the link will fail with an unresolved
+ * symbol (error_symbol).
+ *
+ * This macro is iPXE-specific. Do not use this macro in code
+ * intended to be portable.
+ *
+ */
+#define linker_assert( condition, error_symbol ) \
+ if ( ! (condition) ) { \
+ extern void error_symbol ( void ); \
+ error_symbol(); \
+ }
+
+#endif /* _ASSERT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/big_bswap.h b/src/VBox/Devices/PC/ipxe/src/include/big_bswap.h
new file mode 100644
index 00000000..3775fac1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/big_bswap.h
@@ -0,0 +1,33 @@
+#ifndef ETHERBOOT_BIG_BSWAP_H
+#define ETHERBOOT_BIG_BSWAP_H
+
+#define ntohl(x) (x)
+#define htonl(x) (x)
+#define ntohs(x) (x)
+#define htons(x) (x)
+#define cpu_to_le64(x) __bswap_64(x)
+#define cpu_to_le32(x) __bswap_32(x)
+#define cpu_to_le16(x) __bswap_16(x)
+#define cpu_to_be64(x) (x)
+#define cpu_to_be32(x) (x)
+#define cpu_to_be16(x) (x)
+#define le64_to_cpu(x) __bswap_64(x)
+#define le32_to_cpu(x) __bswap_32(x)
+#define le16_to_cpu(x) __bswap_16(x)
+#define be64_to_cpu(x) (x)
+#define be32_to_cpu(x) (x)
+#define be16_to_cpu(x) (x)
+#define cpu_to_le64s(x) __bswap_64s(x)
+#define cpu_to_le32s(x) __bswap_32s(x)
+#define cpu_to_le16s(x) __bswap_16s(x)
+#define cpu_to_be64s(x) do {} while (0)
+#define cpu_to_be32s(x) do {} while (0)
+#define cpu_to_be16s(x) do {} while (0)
+#define le64_to_cpus(x) __bswap_64s(x)
+#define le32_to_cpus(x) __bswap_32s(x)
+#define le16_to_cpus(x) __bswap_16s(x)
+#define be64_to_cpus(x) do {} while (0)
+#define be32_to_cpus(x) do {} while (0)
+#define be16_to_cpus(x) do {} while (0)
+
+#endif /* ETHERBOOT_BIG_BSWAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/bootp.h b/src/VBox/Devices/PC/ipxe/src/include/bootp.h
new file mode 100644
index 00000000..0e65477a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/bootp.h
@@ -0,0 +1,230 @@
+#ifndef _BOOTP_H
+#define _BOOTP_H
+
+#ifdef ALTERNATE_DHCP_PORTS_1067_1068
+#undef NON_STANDARD_BOOTP_SERVER
+#define NON_STANDARD_BOOTP_SERVER 1067
+#undef NON_STANDARD_BOOTP_CLIENT
+#define NON_STANDARD_BOOTP_CLIENT 1068
+#endif
+
+#ifdef NON_STANDARD_BOOTP_SERVER
+#define BOOTP_SERVER NON_STANDARD_BOOTP_SERVER
+#else
+#define BOOTP_SERVER 67
+#endif
+#ifdef NON_STANDARD_BOOTP_CLIENT
+#define BOOTP_CLIENT NON_STANDARD_BOOTP_CLIENT
+#else
+#define BOOTP_CLIENT 68
+#endif
+#define PROXYDHCP_SERVER 4011 /* For PXE */
+
+#define BOOTP_REQUEST 1
+#define BOOTP_REPLY 2
+
+#define TAG_LEN(p) (*((p)+1))
+#define RFC1533_COOKIE 99, 130, 83, 99
+#define RFC1533_PAD 0
+#define RFC1533_NETMASK 1
+#define RFC1533_TIMEOFFSET 2
+#define RFC1533_GATEWAY 3
+#define RFC1533_TIMESERVER 4
+#define RFC1533_IEN116NS 5
+#define RFC1533_DNS 6
+#define RFC1533_LOGSERVER 7
+#define RFC1533_COOKIESERVER 8
+#define RFC1533_LPRSERVER 9
+#define RFC1533_IMPRESSSERVER 10
+#define RFC1533_RESOURCESERVER 11
+#define RFC1533_HOSTNAME 12
+#define RFC1533_BOOTFILESIZE 13
+#define RFC1533_MERITDUMPFILE 14
+#define RFC1533_DOMAINNAME 15
+#define RFC1533_SWAPSERVER 16
+#define RFC1533_ROOTPATH 17
+#define RFC1533_EXTENSIONPATH 18
+#define RFC1533_IPFORWARDING 19
+#define RFC1533_IPSOURCEROUTING 20
+#define RFC1533_IPPOLICYFILTER 21
+#define RFC1533_IPMAXREASSEMBLY 22
+#define RFC1533_IPTTL 23
+#define RFC1533_IPMTU 24
+#define RFC1533_IPMTUPLATEAU 25
+#define RFC1533_INTMTU 26
+#define RFC1533_INTLOCALSUBNETS 27
+#define RFC1533_INTBROADCAST 28
+#define RFC1533_INTICMPDISCOVER 29
+#define RFC1533_INTICMPRESPOND 30
+#define RFC1533_INTROUTEDISCOVER 31
+#define RFC1533_INTROUTESOLICIT 32
+#define RFC1533_INTSTATICROUTES 33
+#define RFC1533_LLTRAILERENCAP 34
+#define RFC1533_LLARPCACHETMO 35
+#define RFC1533_LLETHERNETENCAP 36
+#define RFC1533_TCPTTL 37
+#define RFC1533_TCPKEEPALIVETMO 38
+#define RFC1533_TCPKEEPALIVEGB 39
+#define RFC1533_NISDOMAIN 40
+#define RFC1533_NISSERVER 41
+#define RFC1533_NTPSERVER 42
+#define RFC1533_VENDOR 43
+#define RFC1533_NBNS 44
+#define RFC1533_NBDD 45
+#define RFC1533_NBNT 46
+#define RFC1533_NBSCOPE 47
+#define RFC1533_XFS 48
+#define RFC1533_XDM 49
+#ifndef NO_DHCP_SUPPORT
+#define RFC2132_REQ_ADDR 50
+#define RFC2132_MSG_TYPE 53
+#define RFC2132_SRV_ID 54
+#define RFC2132_PARAM_LIST 55
+#define RFC2132_MAX_SIZE 57
+#define RFC2132_VENDOR_CLASS_ID 60
+#define RFC2132_CLIENT_ID 61
+#define RFC2132_TFTP_SERVER_NAME 66
+#define RFC2132_BOOTFILE_NAME 67
+#define RFC3004_USER_CLASS 77
+
+#ifdef PXE_DHCP_STRICT
+/*
+ * The following options are acknowledged in RFC3679 because they are
+ * widely used by PXE implementations, but have never been properly
+ * allocated. Despite other PXE options being correctly packed in a
+ * vendor encapsulated field, these are exposed. Sigh. Note that the
+ * client UUID (option 97) is also noted in the PXE spec as using
+ * option 61.
+ */
+#define RFC3679_PXE_CLIENT_ARCH 93
+#define RFC3679_PXE_CLIENT_NDI 94
+#define RFC3679_PXE_CLIENT_UUID 97
+
+/* The lengths are fixed. */
+#define RFC3679_PXE_CLIENT_ARCH_LENGTH 2
+#define RFC3679_PXE_CLIENT_NDI_LENGTH 3
+#define RFC3679_PXE_CLIENT_UUID_LENGTH 17
+
+/*
+ * Values of RFC3679_PXE_CLIENT_ARCH can apparently be one of the
+ * following, according to the PXE spec. The spec only actually
+ * described the 2nd octet, not the first. Duh... assume 0.
+ */
+#define RFC3679_PXE_CLIENT_ARCH_IAX86PC 0,0
+#define RFC3679_PXE_CLIENT_ARCH_NECPC98 0,1
+#define RFC3679_PXE_CLIENT_ARCH_IA64PC 0,2
+#define RFC3679_PXE_CLIENT_ARCH_DECALPHA 0,3
+#define RFC3679_PXE_CLIENT_ARCH_ARCX86 0,4
+#define RFC3679_PXE_CLIENT_ARCH_INTELLEAN 0,5
+
+/*
+ * Only one valid value of NDI type (must be 1) and UNDI version (must
+ * be 2.1)
+ */
+#define RFC3679_PXE_CLIENT_NDI_21 1,2,1
+
+/*
+ * UUID - type must be 1 and then 16 octets of UID, as with the client ID.
+ * The value is a default for testing only
+ */
+#define RFC3679_PXE_CLIENT_UUID_TYPE 0
+#warning "UUID is a default for testing ONLY!"
+#define RFC3679_PXE_CLIENT_UUID_DEFAULT \
+ RFC3679_PXE_CLIENT_UUID_TYPE, \
+ 0xDE,0xAD,0xBE,0xEF, \
+ 0xDE,0xAD,0xBE,0xEF, \
+ 0xDE,0xAD,0xBE,0xEF, \
+ 0xDE,0xAD,0xBE,0xEF
+/*
+ * The Vendor Class ID. Note that the Arch and UNDI version numbers
+ * are fixed and must be same as the ARCH and NDI above.
+ */
+#define RFC2132_VENDOR_CLASS_ID_PXE_LENGTH 32
+#define RFC2132_VENDOR_CLASS_ID_PXE \
+ 'P','X','E','C','l','i','e','n','t',':', \
+ 'A','r','c','h',':','0','0','0','0','0',':', \
+ 'U','N','D','I',':','0','0','2','0','0','1'
+
+/*
+ * The following vendor options are required in the PXE spec to pull
+ * options for the *next* image. The PXE spec doesn't help us with
+ * this (like explaining why).
+ */
+#define RFC1533_VENDOR_PXE_OPT128 128
+#define RFC1533_VENDOR_PXE_OPT129 129
+#define RFC1533_VENDOR_PXE_OPT130 130
+#define RFC1533_VENDOR_PXE_OPT131 131
+#define RFC1533_VENDOR_PXE_OPT132 132
+#define RFC1533_VENDOR_PXE_OPT133 133
+#define RFC1533_VENDOR_PXE_OPT134 134
+#define RFC1533_VENDOR_PXE_OPT135 135
+
+#endif /* PXE_DHCP_STRICT */
+
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPACK 5
+#endif /* NO_DHCP_SUPPORT */
+
+#define RFC1533_VENDOR_MAJOR 0
+#define RFC1533_VENDOR_MINOR 0
+
+#define RFC1533_VENDOR_MAGIC 128
+#define RFC1533_VENDOR_ADDPARM 129
+#define RFC1533_VENDOR_ETHDEV 130
+/* We should really apply for an official Etherboot encap option */
+#define RFC1533_VENDOR_ETHERBOOT_ENCAP 150
+/* I'll leave it to FREEBSD to decide if they want to renumber */
+#ifdef IMAGE_FREEBSD
+#define RFC1533_VENDOR_HOWTO 132
+#define RFC1533_VENDOR_KERNEL_ENV 133
+#endif
+#define RFC1533_VENDOR_NIC_DEV_ID 175
+#define RFC1533_VENDOR_ARCH 177
+
+#define RFC1533_END 255
+
+#define BOOTP_VENDOR_LEN 64
+#ifndef NO_DHCP_SUPPORT
+#define DHCP_OPT_LEN 312
+#endif /* NO_DHCP_SUPPORT */
+
+/* Format of a bootp packet */
+struct bootp_t {
+ uint8_t bp_op;
+ uint8_t bp_htype;
+ uint8_t bp_hlen;
+ uint8_t bp_hops;
+ uint32_t bp_xid;
+ uint16_t bp_secs;
+ uint16_t unused;
+ in_addr bp_ciaddr;
+ in_addr bp_yiaddr;
+ in_addr bp_siaddr;
+ in_addr bp_giaddr;
+ uint8_t bp_hwaddr[16];
+ uint8_t bp_sname[64];
+ char bp_file[128];
+#ifdef NO_DHCP_SUPPORT
+ uint8_t bp_vend[BOOTP_VENDOR_LEN];
+#else
+ uint8_t bp_vend[DHCP_OPT_LEN];
+#endif /* NO_DHCP_SUPPORT */
+};
+
+/* Format of a bootp IP packet */
+struct bootpip_t
+{
+ struct iphdr ip;
+ struct udphdr udp;
+ struct bootp_t bp;
+};
+
+/* Format of bootp packet with extensions */
+struct bootpd_t {
+ struct bootp_t bootp_reply;
+ uint8_t bootp_extension[MAX_BOOTP_EXTLEN];
+};
+
+#endif /* _BOOTP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/byteswap.h b/src/VBox/Devices/PC/ipxe/src/include/byteswap.h
new file mode 100644
index 00000000..466759cf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/byteswap.h
@@ -0,0 +1,59 @@
+#ifndef ETHERBOOT_BYTESWAP_H
+#define ETHERBOOT_BYTESWAP_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "endian.h"
+#include "bits/byteswap.h"
+
+#define __bswap_constant_16(x) \
+ ((uint16_t)((((uint16_t)(x) & 0x00ff) << 8) | \
+ (((uint16_t)(x) & 0xff00) >> 8)))
+
+#define __bswap_constant_32(x) \
+ ((uint32_t)((((uint32_t)(x) & 0x000000ffU) << 24) | \
+ (((uint32_t)(x) & 0x0000ff00U) << 8) | \
+ (((uint32_t)(x) & 0x00ff0000U) >> 8) | \
+ (((uint32_t)(x) & 0xff000000U) >> 24)))
+
+#define __bswap_constant_64(x) \
+ ((uint64_t)((((uint64_t)(x) & 0x00000000000000ffULL) << 56) | \
+ (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
+ (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
+ (((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \
+ (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \
+ (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
+ (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
+ (((uint64_t)(x) & 0xff00000000000000ULL) >> 56)))
+
+#define __bswap_16(x) \
+ ((uint16_t)(__builtin_constant_p(x) ? \
+ __bswap_constant_16(x) : \
+ __bswap_variable_16(x)))
+
+#define __bswap_32(x) \
+ ((uint32_t)(__builtin_constant_p(x) ? \
+ __bswap_constant_32(x) : \
+ __bswap_variable_32(x)))
+
+#define __bswap_64(x) \
+ ((uint64_t)(__builtin_constant_p(x) ? \
+ __bswap_constant_64(x) : \
+ __bswap_variable_64(x)))
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#include "little_bswap.h"
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+#include "big_bswap.h"
+#endif
+
+/* Make routines available to all */
+#define swap64(x) __bswap_64(x)
+#define swap32(x) __bswap_32(x)
+#define swap16(x) __bswap_16(x)
+#define bswap_64(x) __bswap_64(x)
+#define bswap_32(x) __bswap_32(x)
+#define bswap_16(x) __bswap_16(x)
+
+#endif /* ETHERBOOT_BYTESWAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/coff.h b/src/VBox/Devices/PC/ipxe/src/include/coff.h
new file mode 100644
index 00000000..a73fda52
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/coff.h
@@ -0,0 +1,73 @@
+#ifndef COFF_H
+#define COFF_H
+/* Based on the elf.h file
+ * Changed accordingly to support COFF file support
+ */
+
+
+/* Values for f_flags. */
+#define F_RELFLG 0x0001 /* If set, not reloc. info. Clear for executables */
+#define F_EXEC 0x0002 /* No unresolved symbols. Executable file ! */
+#define F_LNNO 0x0004 /* If set, line information numbers removed */
+#define F_LSYMS 0x0008 /* If set, local symbols removed */
+#define F_AR32WR 0x0100 /* Indicates little endian file */
+
+/* Values for e_machine (architecute). */
+#define EM_E1 0x17a /* Magic number for Hyperstone. Big endian format */
+
+/* Values for f_flags. */
+#define O_MAGIC 0x017c /* Optional's header magic number for Hyperstone */
+
+/* Values for s_flags. */
+#define S_TYPE_TEXT 0x0020 /* If set, the section contains only executable */
+#define S_TYPE_DATA 0x0040 /* If set, the section contains only initialized data */
+#define S_TYPE_BSS 0x0080 /* If set, the section is BSS no data stored */
+
+
+typedef struct
+{
+ unsigned short f_magic; /* magic number */
+ unsigned short f_nscns; /* number of sections */
+ unsigned long f_timdat; /* time & date stamp */
+ unsigned long f_symptr; /* file pointer to symtab */
+ unsigned long f_nsyms; /* number of symtab entries */
+ unsigned short f_opthdr; /* sizeof(optional hdr) */
+ unsigned short f_flags; /* flags */
+}
+COFF_filehdr;
+
+/*
+ * Optional header.
+ */
+typedef struct
+{
+ unsigned short magic; /* type of file */
+ unsigned short vstamp; /* version stamp */
+ unsigned long tsize; /* text size in bytes, padded to FW bdry*/
+ unsigned long dsize; /* initialized data " " */
+ unsigned long bsize; /* uninitialized data " " */
+ unsigned long entry; /* entry pt. */
+ unsigned long text_start; /* base of text used for this file */
+ unsigned long data_start; /* base of data used for this file */
+}
+COFF_opthdr;
+
+/*
+ * Section header.
+ */
+typedef struct
+{
+ char s_name[8]; /* section name */
+ unsigned long s_paddr; /* physical address, aliased s_nlib */
+ unsigned long s_vaddr; /* virtual address */
+ unsigned long s_size; /* section size */
+ unsigned long s_scnptr; /* file ptr to raw data for section */
+ unsigned long s_relptr; /* file ptr to relocation */
+ unsigned long s_lnnoptr; /* file ptr to line numbers */
+ unsigned short s_nreloc; /* number of relocation entries */
+ unsigned short s_nlnno; /* number of line number entries*/
+ unsigned long s_flags; /* flags */
+}
+COFF_scnhdr;
+
+#endif /* COFF_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/compiler.h b/src/VBox/Devices/PC/ipxe/src/include/compiler.h
new file mode 100644
index 00000000..ed9af237
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/compiler.h
@@ -0,0 +1,752 @@
+#ifndef COMPILER_H
+#define COMPILER_H
+
+/*
+ * Doxygen can't cope with some of the more esoteric areas of C, so we
+ * make its life simpler.
+ *
+ */
+#ifdef DOXYGEN
+#define __attribute__(x)
+#endif
+
+/** @file
+ *
+ * Global compiler definitions.
+ *
+ * This file is implicitly included by every @c .c file in Etherboot.
+ * It defines global macros such as DBG().
+ *
+ * We arrange for each object to export the symbol @c obj_OBJECT
+ * (where @c OBJECT is the object name, e.g. @c rtl8139) as a global
+ * symbol, so that the linker can drag in selected object files from
+ * the library using <tt> -u obj_OBJECT </tt>.
+ *
+ */
+
+/* Force visibility of all symbols to "hidden", i.e. inform gcc that
+ * all symbol references resolve strictly within our final binary.
+ * This avoids unnecessary PLT/GOT entries on x86_64.
+ *
+ * This is a stronger claim than specifying "-fvisibility=hidden",
+ * since it also affects symbols marked with "extern".
+ */
+#ifndef ASSEMBLY
+#if __GNUC__ >= 4
+#pragma GCC visibility push(hidden)
+#endif
+#endif /* ASSEMBLY */
+
+#undef _S1
+#undef _S2
+#undef _C1
+#undef _C2
+
+/** Concatenate non-expanded arguments */
+#define _C1( x, y ) x ## y
+/** Concatenate expanded arguments */
+#define _C2( x, y ) _C1 ( x, y )
+
+/** Stringify non-expanded argument */
+#define _S1( x ) #x
+/** Stringify expanded argument */
+#define _S2( x ) _S1 ( x )
+
+/**
+ * @defgroup symmacros Macros to provide or require explicit symbols
+ * @{
+ */
+
+/** Provide a symbol within this object file */
+#ifdef ASSEMBLY
+#define PROVIDE_SYMBOL( _sym ) \
+ .globl _sym ; \
+ .comm _sym, 0
+#else /* ASSEMBLY */
+#define PROVIDE_SYMBOL( _sym ) \
+ char _sym[0]
+#endif /* ASSEMBLY */
+
+/** Require a symbol within this object file
+ *
+ * The symbol is referenced by a relocation in a discarded section, so
+ * if it is not available at link time the link will fail.
+ */
+#ifdef ASSEMBLY
+#define REQUIRE_SYMBOL( _sym ) \
+ .section ".discard", "a", @progbits ; \
+ .extern _sym ; \
+ .long _sym ; \
+ .previous
+#else /* ASSEMBLY */
+#define REQUIRE_SYMBOL( _sym ) \
+ extern char _sym; \
+ static char * _C2 ( _C2 ( __require_, _sym ), _C2 ( _, __LINE__ ) ) \
+ __attribute__ (( section ( ".discard" ), used )) \
+ = &_sym
+#endif
+
+/** Request that a symbol be available at runtime
+ *
+ * The requested symbol is entered as undefined into the symbol table
+ * for this object, so the linker will pull in other object files as
+ * necessary to satisfy the reference. However, the undefined symbol
+ * is not referenced in any relocations, so the link can still succeed
+ * if no file contains it.
+ *
+ * A symbol passed to this macro may not be referenced anywhere
+ * else in the file. If you want to do that, see IMPORT_SYMBOL().
+ */
+#ifdef ASSEMBLY
+#define REQUEST_SYMBOL( _sym ) \
+ .equ __need_ ## _sym, _sym
+#else /* ASSEMBLY */
+#define REQUEST_SYMBOL( _sym ) \
+ __asm__ ( ".equ\t__need_" #_sym ", " #_sym )
+#endif /* ASSEMBLY */
+
+/** Set up a symbol to be usable in another file by IMPORT_SYMBOL()
+ *
+ * The symbol must already be marked as global.
+ */
+#define EXPORT_SYMBOL( _sym ) PROVIDE_SYMBOL ( __export_ ## _sym )
+
+/** Make a symbol usable to this file if available at link time
+ *
+ * If no file passed to the linker contains the symbol, it will have
+ * @c NULL value to future uses. Keep in mind that the symbol value is
+ * really the @e address of a variable or function; see the code
+ * snippet below.
+ *
+ * In C using IMPORT_SYMBOL, you must specify the declaration as the
+ * second argument, for instance
+ *
+ * @code
+ * IMPORT_SYMBOL ( my_func, int my_func ( int arg ) );
+ * IMPORT_SYMBOL ( my_var, int my_var );
+ *
+ * void use_imports ( void ) {
+ * if ( my_func && &my_var )
+ * my_var = my_func ( my_var );
+ * }
+ * @endcode
+ *
+ * GCC considers a weak declaration to override a strong one no matter
+ * which comes first, so it is safe to include a header file declaring
+ * the imported symbol normally, but providing the declaration to
+ * IMPORT_SYMBOL is still required.
+ *
+ * If no EXPORT_SYMBOL declaration exists for the imported symbol in
+ * another file, the behavior will be most likely be identical to that
+ * for an unavailable symbol.
+ */
+#ifdef ASSEMBLY
+#define IMPORT_SYMBOL( _sym ) \
+ REQUEST_SYMBOL ( __export_ ## _sym ) ; \
+ .weak _sym
+#else /* ASSEMBLY */
+#define IMPORT_SYMBOL( _sym, _decl ) \
+ REQUEST_SYMBOL ( __export_ ## _sym ) ; \
+ extern _decl __attribute__ (( weak ))
+#endif
+
+/** @} */
+
+/**
+ * @defgroup objmacros Macros to provide or require explicit objects
+ * @{
+ */
+
+#define PREFIX_OBJECT( _prefix ) _C2 ( _prefix, OBJECT )
+#define OBJECT_SYMBOL PREFIX_OBJECT ( obj_ )
+#define REQUEST_EXPANDED( _sym ) REQUEST_SYMBOL ( _sym )
+#define CONFIG_SYMBOL PREFIX_OBJECT ( obj_config_ )
+
+/** Always provide the symbol for the current object (defined by -DOBJECT) */
+PROVIDE_SYMBOL ( OBJECT_SYMBOL );
+
+/** Pull in an object-specific configuration file if available */
+REQUEST_EXPANDED ( CONFIG_SYMBOL );
+
+/** Explicitly require another object */
+#define REQUIRE_OBJECT( _obj ) REQUIRE_SYMBOL ( obj_ ## _obj )
+
+/** Pull in another object if it exists */
+#define REQUEST_OBJECT( _obj ) REQUEST_SYMBOL ( obj_ ## _obj )
+
+/** @} */
+
+/** Select file identifier for errno.h (if used) */
+#define ERRFILE PREFIX_OBJECT ( ERRFILE_ )
+
+#ifndef ASSEMBLY
+
+/** Declare a function as weak (use *before* the definition)
+ *
+ * Due to a bug in at least GCC 4.4.4 and earlier, weak symbols may be
+ * inlined if they have hidden visibility (see above for why hidden
+ * visibility is used). This results in the non-weak symbol never
+ * being used, so explicitly mark the function as noinline to prevent
+ * inlining.
+ */
+#define __weak __attribute__ (( weak, noinline ))
+
+/** Prevent a function from being optimized away without inlining
+ *
+ * Calls to functions with void return type that contain no code in their body
+ * may be removed by gcc's optimizer even when inlining is inhibited. Placing
+ * this macro in the body of the function prevents that from occurring.
+ */
+#define __keepme asm("");
+
+#endif
+
+/** @defgroup dbg Debugging infrastructure
+ * @{
+ */
+
+/** @def DBG
+ *
+ * Print a debugging message.
+ *
+ * The debug level is set at build time by specifying the @c DEBUG=
+ * parameter on the @c make command line. For example, to enable
+ * debugging for the PCI bus functions (in pci.c) in a @c .dsk image
+ * for the @c rtl8139 card, you could use the command line
+ *
+ * @code
+ *
+ * make bin/rtl8139.dsk DEBUG=pci
+ *
+ * @endcode
+ *
+ * This will enable the debugging statements (DBG()) in pci.c. If
+ * debugging is not enabled, DBG() statements will be ignored.
+ *
+ * You can enable debugging in several objects simultaneously by
+ * separating them with commas, as in
+ *
+ * @code
+ *
+ * make bin/rtl8139.dsk DEBUG=pci,buffer,heap
+ *
+ * @endcode
+ *
+ * You can increase the debugging level for an object by specifying it
+ * with @c :N, where @c N is the level, as in
+ *
+ * @code
+ *
+ * make bin/rtl8139.dsk DEBUG=pci,buffer:2,heap
+ *
+ * @endcode
+ *
+ * which would enable debugging for the PCI, buffer-handling and
+ * heap-allocation code, with the buffer-handling code at level 2.
+ *
+ */
+
+/*
+ * If debug_OBJECT is set to a true value, the macro DBG(...) will
+ * expand to printf(...) when compiling OBJECT, and the symbol
+ * DEBUG_LEVEL will be inserted into the object file.
+ *
+ */
+#define DEBUG_SYMBOL PREFIX_OBJECT ( debug_ )
+
+#if DEBUG_SYMBOL == 0
+#define NDEBUG
+#endif
+
+#ifndef ASSEMBLY
+
+/** printf() for debugging */
+extern void __attribute__ (( format ( printf, 1, 2 ) ))
+dbg_printf ( const char *fmt, ... );
+extern void dbg_autocolourise ( unsigned long id );
+extern void dbg_decolourise ( void );
+extern void dbg_hex_dump_da ( unsigned long dispaddr,
+ const void *data, unsigned long len );
+extern void dbg_md5_da ( unsigned long dispaddr,
+ const void *data, unsigned long len );
+extern void dbg_pause ( void );
+extern void dbg_more ( void );
+
+#if DEBUG_SYMBOL
+#define DBGLVL_MAX DEBUG_SYMBOL
+#else
+#define DBGLVL_MAX 0
+#endif
+
+/* Allow for selective disabling of enabled debug levels */
+#if DBGLVL_MAX
+int __debug_disable;
+#define DBGLVL ( DBGLVL_MAX & ~__debug_disable )
+#define DBG_DISABLE( level ) do { \
+ __debug_disable |= (level); \
+ } while ( 0 )
+#define DBG_ENABLE( level ) do { \
+ __debug_disable &= ~(level); \
+ } while ( 0 )
+#else
+#define DBGLVL 0
+#define DBG_DISABLE( level ) do { } while ( 0 )
+#define DBG_ENABLE( level ) do { } while ( 0 )
+#endif
+
+#define DBGLVL_LOG 1
+#define DBG_LOG ( DBGLVL & DBGLVL_LOG )
+#define DBGLVL_EXTRA 2
+#define DBG_EXTRA ( DBGLVL & DBGLVL_EXTRA )
+#define DBGLVL_PROFILE 4
+#define DBG_PROFILE ( DBGLVL & DBGLVL_PROFILE )
+#define DBGLVL_IO 8
+#define DBG_IO ( DBGLVL & DBGLVL_IO )
+
+/**
+ * Print debugging message if we are at a certain debug level
+ *
+ * @v level Debug level
+ * @v ... printf() argument list
+ */
+#define DBG_IF( level, ... ) do { \
+ if ( DBG_ ## level ) { \
+ dbg_printf ( __VA_ARGS__ ); \
+ } \
+ } while ( 0 )
+
+/**
+ * Print a hex dump if we are at a certain debug level
+ *
+ * @v level Debug level
+ * @v dispaddr Display address
+ * @v data Data to print
+ * @v len Length of data
+ */
+#define DBG_HDA_IF( level, dispaddr, data, len ) do { \
+ if ( DBG_ ## level ) { \
+ union { \
+ unsigned long ul; \
+ typeof ( dispaddr ) raw; \
+ } da; \
+ da.ul = 0; \
+ da.raw = dispaddr; \
+ dbg_hex_dump_da ( da.ul, data, len ); \
+ } \
+ } while ( 0 )
+
+/**
+ * Print a hex dump if we are at a certain debug level
+ *
+ * @v level Debug level
+ * @v data Data to print
+ * @v len Length of data
+ */
+#define DBG_HD_IF( level, data, len ) do { \
+ const void *_data = data; \
+ DBG_HDA_IF ( level, _data, _data, len ); \
+ } while ( 0 )
+
+/**
+ * Print an MD5 checksum if we are at a certain debug level
+ *
+ * @v level Debug level
+ * @v dispaddr Display address
+ * @v data Data to print
+ * @v len Length of data
+ */
+#define DBG_MD5A_IF( level, dispaddr, data, len ) do { \
+ if ( DBG_ ## level ) { \
+ union { \
+ unsigned long ul; \
+ typeof ( dispaddr ) raw; \
+ } da; \
+ da.ul = 0; \
+ da.raw = dispaddr; \
+ dbg_md5_da ( da.ul, data, len ); \
+ } \
+ } while ( 0 )
+
+/**
+ * Print an MD5 checksum if we are at a certain debug level
+ *
+ * @v level Debug level
+ * @v data Data to print
+ * @v len Length of data
+ */
+#define DBG_MD5_IF( level, data, len ) do { \
+ const void *_data = data; \
+ DBG_MD5A_IF ( level, _data, _data, len ); \
+ } while ( 0 )
+
+/**
+ * Prompt for key press if we are at a certain debug level
+ *
+ * @v level Debug level
+ */
+#define DBG_PAUSE_IF( level ) do { \
+ if ( DBG_ ## level ) { \
+ dbg_pause(); \
+ } \
+ } while ( 0 )
+
+/**
+ * Prompt for more output data if we are at a certain debug level
+ *
+ * @v level Debug level
+ */
+#define DBG_MORE_IF( level ) do { \
+ if ( DBG_ ## level ) { \
+ dbg_more(); \
+ } \
+ } while ( 0 )
+
+/**
+ * Select colour for debug messages if we are at a certain debug level
+ *
+ * @v level Debug level
+ * @v id Message stream ID
+ */
+#define DBG_AC_IF( level, id ) do { \
+ if ( DBG_ ## level ) { \
+ union { \
+ unsigned long ul; \
+ typeof ( id ) raw; \
+ } dbg_stream; \
+ dbg_stream.ul = 0; \
+ dbg_stream.raw = id; \
+ dbg_autocolourise ( dbg_stream.ul ); \
+ } \
+ } while ( 0 )
+
+/**
+ * Revert colour for debug messages if we are at a certain debug level
+ *
+ * @v level Debug level
+ */
+#define DBG_DC_IF( level ) do { \
+ if ( DBG_ ## level ) { \
+ dbg_decolourise(); \
+ } \
+ } while ( 0 )
+
+/* Autocolourising versions of the DBGxxx_IF() macros */
+
+#define DBGC_IF( level, id, ... ) do { \
+ DBG_AC_IF ( level, id ); \
+ DBG_IF ( level, __VA_ARGS__ ); \
+ DBG_DC_IF ( level ); \
+ } while ( 0 )
+
+#define DBGC_HDA_IF( level, id, ... ) do { \
+ DBG_AC_IF ( level, id ); \
+ DBG_HDA_IF ( level, __VA_ARGS__ ); \
+ DBG_DC_IF ( level ); \
+ } while ( 0 )
+
+#define DBGC_HD_IF( level, id, ... ) do { \
+ DBG_AC_IF ( level, id ); \
+ DBG_HD_IF ( level, __VA_ARGS__ ); \
+ DBG_DC_IF ( level ); \
+ } while ( 0 )
+
+#define DBGC_MD5A_IF( level, id, ... ) do { \
+ DBG_AC_IF ( level, id ); \
+ DBG_MD5A_IF ( level, __VA_ARGS__ ); \
+ DBG_DC_IF ( level ); \
+ } while ( 0 )
+
+#define DBGC_MD5_IF( level, id, ... ) do { \
+ DBG_AC_IF ( level, id ); \
+ DBG_MD5_IF ( level, __VA_ARGS__ ); \
+ DBG_DC_IF ( level ); \
+ } while ( 0 )
+
+#define DBGC_PAUSE_IF( level, id ) do { \
+ DBG_AC_IF ( level, id ); \
+ DBG_PAUSE_IF ( level ); \
+ DBG_DC_IF ( level ); \
+ } while ( 0 )
+
+#define DBGC_MORE_IF( level, id ) do { \
+ DBG_AC_IF ( level, id ); \
+ DBG_MORE_IF ( level ); \
+ DBG_DC_IF ( level ); \
+ } while ( 0 )
+
+/* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( LOG, ... )*/
+
+#define DBG( ... ) DBG_IF ( LOG, ##__VA_ARGS__ )
+#define DBG_HDA( ... ) DBG_HDA_IF ( LOG, ##__VA_ARGS__ )
+#define DBG_HD( ... ) DBG_HD_IF ( LOG, ##__VA_ARGS__ )
+#define DBG_MD5A( ... ) DBG_MD5A_IF ( LOG, ##__VA_ARGS__ )
+#define DBG_MD5( ... ) DBG_MD5_IF ( LOG, ##__VA_ARGS__ )
+#define DBG_PAUSE( ... ) DBG_PAUSE_IF ( LOG, ##__VA_ARGS__ )
+#define DBG_MORE( ... ) DBG_MORE_IF ( LOG, ##__VA_ARGS__ )
+#define DBGC( ... ) DBGC_IF ( LOG, ##__VA_ARGS__ )
+#define DBGC_HDA( ... ) DBGC_HDA_IF ( LOG, ##__VA_ARGS__ )
+#define DBGC_HD( ... ) DBGC_HD_IF ( LOG, ##__VA_ARGS__ )
+#define DBGC_MD5A( ... ) DBGC_MD5A_IF ( LOG, ##__VA_ARGS__ )
+#define DBGC_MD5( ... ) DBGC_MD5_IF ( LOG, ##__VA_ARGS__ )
+#define DBGC_PAUSE( ... ) DBGC_PAUSE_IF ( LOG, ##__VA_ARGS__ )
+#define DBGC_MORE( ... ) DBGC_MORE_IF ( LOG, ##__VA_ARGS__ )
+
+/* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( EXTRA, ... )*/
+
+#define DBG2( ... ) DBG_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBG2_HDA( ... ) DBG_HDA_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBG2_HD( ... ) DBG_HD_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBG2_MD5A( ... ) DBG_MD5A_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBG2_MD5( ... ) DBG_MD5_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBG2_PAUSE( ... ) DBG_PAUSE_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBG2_MORE( ... ) DBG_MORE_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBGC2( ... ) DBGC_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBGC2_HDA( ... ) DBGC_HDA_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBGC2_HD( ... ) DBGC_HD_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBGC2_MD5A( ... ) DBGC_MD5A_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBGC2_MD5( ... ) DBGC_MD5_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBGC2_PAUSE( ... ) DBGC_PAUSE_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBGC2_MORE( ... ) DBGC_MORE_IF ( EXTRA, ##__VA_ARGS__ )
+
+/* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( PROFILE, ... )*/
+
+#define DBGP( ... ) DBG_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGP_HDA( ... ) DBG_HDA_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGP_HD( ... ) DBG_HD_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGP_MD5A( ... ) DBG_MD5A_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGP_MD5( ... ) DBG_MD5_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGP_PAUSE( ... ) DBG_PAUSE_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGP_MORE( ... ) DBG_MORE_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGCP( ... ) DBGC_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGCP_HDA( ... ) DBGC_HDA_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGCP_HD( ... ) DBGC_HD_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGCP_MD5A( ... ) DBGC_MD5A_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGCP_MD5( ... ) DBGC_MD5_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGCP_PAUSE( ... ) DBGC_PAUSE_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGCP_MORE( ... ) DBGC_MORE_IF ( PROFILE, ##__VA_ARGS__ )
+
+/* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( IO, ... )*/
+
+#define DBGIO( ... ) DBG_IF ( IO, ##__VA_ARGS__ )
+#define DBGIO_HDA( ... ) DBG_HDA_IF ( IO, ##__VA_ARGS__ )
+#define DBGIO_HD( ... ) DBG_HD_IF ( IO, ##__VA_ARGS__ )
+#define DBGIO_MD5A( ... ) DBG_MD5A_IF ( IO, ##__VA_ARGS__ )
+#define DBGIO_MD5( ... ) DBG_MD5_IF ( IO, ##__VA_ARGS__ )
+#define DBGIO_PAUSE( ... ) DBG_PAUSE_IF ( IO, ##__VA_ARGS__ )
+#define DBGIO_MORE( ... ) DBG_MORE_IF ( IO, ##__VA_ARGS__ )
+#define DBGCIO( ... ) DBGC_IF ( IO, ##__VA_ARGS__ )
+#define DBGCIO_HDA( ... ) DBGC_HDA_IF ( IO, ##__VA_ARGS__ )
+#define DBGCIO_HD( ... ) DBGC_HD_IF ( IO, ##__VA_ARGS__ )
+#define DBGCIO_MD5A( ... ) DBGC_MD5A_IF ( IO, ##__VA_ARGS__ )
+#define DBGCIO_MD5( ... ) DBGC_MD5_IF ( IO, ##__VA_ARGS__ )
+#define DBGCIO_PAUSE( ... ) DBGC_PAUSE_IF ( IO, ##__VA_ARGS__ )
+#define DBGCIO_MORE( ... ) DBGC_MORE_IF ( IO, ##__VA_ARGS__ )
+
+#endif /* ASSEMBLY */
+/** @} */
+
+/** @defgroup attrs Miscellaneous attributes
+ * @{
+ */
+#ifndef ASSEMBLY
+
+/** Declare a variable or data structure as unused. */
+#define __unused __attribute__ (( unused ))
+
+/**
+ * Declare a function as pure - i.e. without side effects
+ */
+#define __pure __attribute__ (( pure ))
+
+/**
+ * Declare a function as const - i.e. it does not access global memory
+ * (including dereferencing pointers passed to it) at all.
+ * Must also not call any non-const functions.
+ */
+#define __const __attribute__ (( const ))
+
+/**
+ * Declare a function's pointer parameters as non-null - i.e. force
+ * compiler to check pointers at compile time and enable possible
+ * optimizations based on that fact
+ */
+#define __nonnull __attribute__ (( nonnull ))
+
+/**
+ * Declare a pointer returned by a function as a unique memory address
+ * as returned by malloc-type functions.
+ */
+#define __malloc __attribute__ (( malloc ))
+
+/**
+ * Declare a function as used.
+ *
+ * Necessary only if the function is called only from assembler code.
+ */
+#define __used __attribute__ (( used ))
+
+/** Declare a data structure to be aligned with 16-byte alignment */
+#define __aligned __attribute__ (( aligned ( 16 ) ))
+
+/** Declare a function to be always inline */
+#define __always_inline __attribute__ (( always_inline ))
+
+/* Force all inline functions to not be instrumented
+ *
+ * This is required to cope with what seems to be a long-standing gcc
+ * bug, in which -finstrument-functions will cause instances of
+ * inlined functions to be reported as further calls to the
+ * *containing* function. This makes instrumentation very difficult
+ * to use.
+ *
+ * Work around this problem by adding the no_instrument_function
+ * attribute to all inlined functions.
+ */
+#define inline inline __attribute__ (( no_instrument_function ))
+
+/**
+ * Shared data.
+ *
+ * To save space in the binary when multiple-driver images are
+ * compiled, uninitialised data areas can be shared between drivers.
+ * This will typically be used to share statically-allocated receive
+ * and transmit buffers between drivers.
+ *
+ * Use as e.g.
+ *
+ * @code
+ *
+ * struct {
+ * char rx_buf[NUM_RX_BUF][RX_BUF_SIZE];
+ * char tx_buf[TX_BUF_SIZE];
+ * } my_static_data __shared;
+ *
+ * @endcode
+ *
+ */
+#define __shared __asm__ ( "_shared_bss" ) __aligned
+
+#endif /* ASSEMBLY */
+/** @} */
+
+/**
+ * Optimisation barrier
+ */
+#ifndef ASSEMBLY
+#define barrier() __asm__ __volatile__ ( "" : : : "memory" )
+#endif /* ASSEMBLY */
+
+/**
+ * @defgroup licences Licence declarations
+ *
+ * For reasons that are partly historical, various different files
+ * within the iPXE codebase have differing licences.
+ *
+ * @{
+ */
+
+/** Declare a file as being in the public domain
+ *
+ * This licence declaration is applicable when a file states itself to
+ * be in the public domain.
+ */
+#define FILE_LICENCE_PUBLIC_DOMAIN \
+ PROVIDE_SYMBOL ( __licence_public_domain )
+
+/** Declare a file as being under version 2 (or later) of the GNU GPL
+ *
+ * This licence declaration is applicable when a file states itself to
+ * be licensed under the GNU GPL; "either version 2 of the License, or
+ * (at your option) any later version".
+ */
+#define FILE_LICENCE_GPL2_OR_LATER \
+ PROVIDE_SYMBOL ( __licence_gpl2_or_later )
+
+/** Declare a file as being under version 2 of the GNU GPL
+ *
+ * This licence declaration is applicable when a file states itself to
+ * be licensed under version 2 of the GPL, and does not include the
+ * "or, at your option, any later version" clause.
+ */
+#define FILE_LICENCE_GPL2_ONLY \
+ PROVIDE_SYMBOL ( __licence_gpl2_only )
+
+/** Declare a file as being under any version of the GNU GPL
+ *
+ * This licence declaration is applicable when a file states itself to
+ * be licensed under the GPL, but does not specify a version.
+ *
+ * According to section 9 of the GPLv2, "If the Program does not
+ * specify a version number of this License, you may choose any
+ * version ever published by the Free Software Foundation".
+ */
+#define FILE_LICENCE_GPL_ANY \
+ PROVIDE_SYMBOL ( __licence_gpl_any )
+
+/** Declare a file as being under the three-clause BSD licence
+ *
+ * This licence declaration is applicable when a file states itself to
+ * be licensed under terms allowing redistribution in source and
+ * binary forms (with or without modification) provided that:
+ *
+ * redistributions of source code retain the copyright notice,
+ * list of conditions and any attached disclaimers
+ *
+ * redistributions in binary form reproduce the copyright notice,
+ * list of conditions and any attached disclaimers in the
+ * documentation and/or other materials provided with the
+ * distribution
+ *
+ * the name of the author is not used to endorse or promote
+ * products derived from the software without specific prior
+ * written permission
+ *
+ * It is not necessary for the file to explicitly state that it is
+ * under a "BSD" licence; only that the licensing terms be
+ * functionally equivalent to the standard three-clause BSD licence.
+ */
+#define FILE_LICENCE_BSD3 \
+ PROVIDE_SYMBOL ( __licence_bsd3 )
+
+/** Declare a file as being under the two-clause BSD licence
+ *
+ * This licence declaration is applicable when a file states itself to
+ * be licensed under terms allowing redistribution in source and
+ * binary forms (with or without modification) provided that:
+ *
+ * redistributions of source code retain the copyright notice,
+ * list of conditions and any attached disclaimers
+ *
+ * redistributions in binary form reproduce the copyright notice,
+ * list of conditions and any attached disclaimers in the
+ * documentation and/or other materials provided with the
+ * distribution
+ *
+ * It is not necessary for the file to explicitly state that it is
+ * under a "BSD" licence; only that the licensing terms be
+ * functionally equivalent to the standard two-clause BSD licence.
+ */
+#define FILE_LICENCE_BSD2 \
+ PROVIDE_SYMBOL ( __licence_bsd2 )
+
+/** Declare a file as being under the one-clause MIT-style licence
+ *
+ * This licence declaration is applicable when a file states itself to
+ * be licensed under terms allowing redistribution for any purpose
+ * with or without fee, provided that the copyright notice and
+ * permission notice appear in all copies.
+ */
+#define FILE_LICENCE_MIT \
+ PROVIDE_SYMBOL ( __licence_mit )
+
+/** Declare a particular licence as applying to a file */
+#define FILE_LICENCE( _licence ) FILE_LICENCE_ ## _licence
+
+/** @} */
+
+/* This file itself is under GPLv2-or-later */
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <bits/compiler.h>
+
+#endif /* COMPILER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/cpu.h b/src/VBox/Devices/PC/ipxe/src/include/cpu.h
new file mode 100644
index 00000000..b2c428f7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/cpu.h
@@ -0,0 +1,6 @@
+#ifndef CPU_H
+#define CPU_H
+
+#include "bits/cpu.h"
+
+#endif /* CPU_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ctype.h b/src/VBox/Devices/PC/ipxe/src/include/ctype.h
new file mode 100644
index 00000000..9f5127bf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ctype.h
@@ -0,0 +1,32 @@
+#ifndef _CTYPE_H
+#define _CTYPE_H
+
+/** @file
+ *
+ * Character types
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#define isdigit(c) ((c) >= '0' && (c) <= '9')
+#define islower(c) ((c) >= 'a' && (c) <= 'z')
+#define isupper(c) ((c) >= 'A' && (c) <= 'Z')
+#define isxdigit(c) (isdigit(c) || ((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f'))
+
+static inline unsigned char tolower(unsigned char c)
+{
+ if (isupper(c))
+ c -= 'A'-'a';
+ return c;
+}
+
+static inline unsigned char toupper(unsigned char c)
+{
+ if (islower(c))
+ c -= 'a'-'A';
+ return c;
+}
+
+extern int isspace ( int c );
+
+#endif /* _CTYPE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/curses.h b/src/VBox/Devices/PC/ipxe/src/include/curses.h
new file mode 100644
index 00000000..9b2a765d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/curses.h
@@ -0,0 +1,755 @@
+#ifndef CURSES_H
+#define CURSES_H
+
+#include <stdint.h>
+#include <stdarg.h>
+
+/** @file
+ *
+ * MuCurses header file
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#undef ERR
+#define ERR (-1)
+
+#undef FALSE
+#define FALSE (0)
+
+#undef OK
+#define OK (0)
+
+#undef TRUE
+#define TRUE (1)
+
+typedef int bool;
+typedef uint32_t chtype;
+typedef uint32_t attr_t;
+
+/** Curses SCREEN object */
+typedef struct _curses_screen {
+ /** Current cursor position */
+ unsigned int curs_x, curs_y;
+ /** Current attribute */
+ attr_t attrs;
+
+ void ( *init ) ( struct _curses_screen *scr );
+ void ( *exit ) ( struct _curses_screen *scr );
+ /**
+ * Move cursor to position specified by x,y coords
+ *
+ * @v scr screen on which to operate
+ * @v y Y position
+ * @v x X position
+ */
+ void ( * movetoyx ) ( struct _curses_screen *scr,
+ unsigned int y, unsigned int x );
+ /**
+ * Write character to current cursor position
+ *
+ * @v scr screen on which to operate
+ * @v c character to be written
+ */
+ void ( * putc ) ( struct _curses_screen *scr, chtype c );
+ /**
+ * Pop a character from the keyboard input stream
+ *
+ * @v scr screen on which to operate
+ * @ret c popped character
+ */
+ int ( * getc ) ( struct _curses_screen *scr );
+ /**
+ * Checks to see whether a character is waiting in the input stream
+ *
+ * @v scr screen on which to operate
+ * @ret TRUE character waiting in stream
+ * @ret FALSE no character waiting in stream
+ */
+ bool ( *peek ) ( struct _curses_screen *scr );
+} SCREEN;
+
+/** Curses Window struct */
+typedef struct _curses_window {
+ /** screen with which window associates */
+ SCREEN *scr;
+ /** window attributes */
+ attr_t attrs;
+ /** window origin coordinates */
+ unsigned int ori_x, ori_y;
+ /** window cursor position */
+ unsigned int curs_x, curs_y;
+ /** window dimensions */
+ unsigned int width, height;
+ /** parent window */
+ struct _curses_window *parent;
+ /** windows that share the same parent as this one */
+ //struct list_head siblings;
+ /** windows der'd or sub'd from this one */
+ //struct list_head children;
+} WINDOW;
+
+extern WINDOW _stdscr;
+extern unsigned short _COLS;
+extern unsigned short _LINES;
+
+#define stdscr ( &_stdscr )
+#define COLS _COLS
+#define LINES _LINES
+
+#define MUCURSES_BITS( mask, shift ) (( mask ) << (shift))
+#define CPAIR_SHIFT 8
+#define ATTRS_SHIFT 16
+
+#define WA_DEFAULT ( 0x0000 << ATTRS_SHIFT )
+#define WA_ALTCHARSET ( 0x0001 << ATTRS_SHIFT )
+#define WA_BLINK ( 0x0002 << ATTRS_SHIFT )
+#define WA_BOLD ( 0x0004 << ATTRS_SHIFT )
+#define WA_DIM ( 0x0008 << ATTRS_SHIFT )
+#define WA_INVIS ( 0x0010 << ATTRS_SHIFT )
+#define WA_PROTECT ( 0x0020 << ATTRS_SHIFT )
+#define WA_REVERSE ( 0x0040 << ATTRS_SHIFT )
+#define WA_STANDOUT ( 0x0080 << ATTRS_SHIFT )
+#define WA_UNDERLINE ( 0x0100 << ATTRS_SHIFT )
+#define WA_HORIZONTAL ( 0x0200 << ATTRS_SHIFT )
+#define WA_VERTICAL ( 0x0400 << ATTRS_SHIFT )
+#define WA_LEFT ( 0x0800 << ATTRS_SHIFT )
+#define WA_RIGHT ( 0x1000 << ATTRS_SHIFT )
+#define WA_LOW ( 0x2000 << ATTRS_SHIFT )
+#define WA_TOP ( 0x4000 << ATTRS_SHIFT )
+
+#define A_DEFAULT WA_DEFAULT
+#define A_ALTCHARSET WA_ALTCHARSET
+#define A_BLINK WA_BLINK
+#define A_BOLD WA_BOLD
+#define A_DIM WA_DIM
+#define A_INVIS WA_INVIS
+#define A_PROTECT WA_PROTECT
+#define A_REVERSE WA_REVERSE
+#define A_STANDOUT WA_STANDOUT
+#define A_UNDERLINE WA_UNDERLINE
+
+#define A_ATTRIBUTES ( 0xffff << ATTRS_SHIFT )
+#define A_CHARTEXT ( 0xff )
+#define A_COLOUR ( 0xff << CPAIR_SHIFT )
+#define A_COLOR A_COLOUR
+
+#define COLOUR_PAIR(n) ( (n) << CPAIR_SHIFT )
+#define COLOR_PAIR(n) COLOUR_PAIR(n)
+#define PAIR_NUMBER(attrs) ( ( (attrs) & A_COLOUR ) >> CPAIR_SHIFT )
+
+#define COLOUR_PAIRS 8 /* Arbitrary limit */
+#define COLOR_PAIRS COLOUR_PAIRS
+
+#define ACS_ULCORNER '+'
+#define ACS_LLCORNER '+'
+#define ACS_URCORNER '+'
+#define ACS_LRCORNER '+'
+#define ACS_RTEE '+'
+#define ACS_LTEE '+'
+#define ACS_BTEE '+'
+#define ACS_TTEE '+'
+#define ACS_HLINE '-'
+#define ACS_VLINE '|'
+#define ACS_PLUS '+'
+#define ACS_S1 '-'
+#define ACS_S9 '_'
+#define ACS_DIAMOND '+'
+#define ACS_CKBOARD ':'
+#define ACS_DEGREE '\''
+#define ACS_PLMINUS '#'
+#define ACS_BULLET 'o'
+#define ACS_LARROW '<'
+#define ACS_RARROW '>'
+#define ACS_DARROW 'v'
+#define ACS_UARROW '^'
+#define ACS_BOARD '#'
+#define ACS_LANTERN '#'
+#define ACS_BLOCK '#'
+
+#define COLOUR_BLACK 0
+#define COLOUR_RED 1
+#define COLOUR_GREEN 2
+#define COLOUR_YELLOW 3
+#define COLOUR_BLUE 4
+#define COLOUR_MAGENTA 5
+#define COLOUR_CYAN 6
+#define COLOUR_WHITE 7
+#define COLOURS 7
+
+#define COLOUR_FG 30
+#define COLOUR_BG 40
+#define COLOR_FG COLOUR_FG
+#define COLOR_BG COLOUR_BG
+
+#define COLOR_BLACK COLOUR_BLACK
+#define COLOR_BLUE COLOUR_BLUE
+#define COLOR_GREEN COLOUR_GREEN
+#define COLOR_CYAN COLOUR_CYAN
+#define COLOR_RED COLOUR_RED
+#define COLOR_MAGENTA COLOUR_MAGENTA
+#define COLOR_YELLOW COLOUR_YELLOW
+#define COLOR_WHITE COLOUR_WHITE
+#define COLORS COLOURS
+
+/*
+ * KEY code constants are define in ipxe/keys.h
+ */
+#include <ipxe/keys.h>
+
+//extern int addch ( const chtype * );
+//extern int addchnstr ( const chtype *, int );
+//extern int addchstr ( const chtype * );
+//extern int addnstr ( const char *, int );
+//extern int addstr ( const char * );
+//extern int attroff ( int );
+//extern int attron ( int );
+//extern int attrset ( int );
+//extern int attr_get ( attr_t *, short *, void * );
+//extern int attr_off ( attr_t, void * );
+//extern int attr_on ( attr_t, void * );
+//extern int attr_set ( attr_t, short, void * );
+extern int baudrate ( void );
+extern int beep ( void );
+//extern void bkgdset ( chtype );
+/*extern int border ( chtype, chtype, chtype, chtype, chtype, chtype, chtype,
+ chtype );*/
+extern int box ( WINDOW *, chtype, chtype ) __nonnull;
+//extern bool can_change_colour ( void );
+#define can_change_color() can_change_colour()
+extern int cbreak ( void );
+//extern int clrtobot ( void );
+//extern int clrtoeol ( void );
+extern int colour_content ( short, short *, short *, short * ) __nonnull;
+#define color_content( c, r, g, b ) colour_content( (c), (r), (g), (b) )
+//extern int colour_set ( short, void * );
+#define color_set( cpno, opts ) colour_set( (cpno), (opts) )
+extern int copywin ( const WINDOW *, WINDOW *, int, int, int,
+ int, int, int, int );
+extern int curs_set ( int );
+extern int def_prog_mode ( void );
+extern int def_shell_mode ( void );
+extern int delay_output ( int );
+//extern int delch ( void );
+//extern int deleteln ( void );
+extern void delscreen ( SCREEN * );
+extern int delwin ( WINDOW * ) __nonnull;
+extern WINDOW *derwin ( WINDOW *, int, int, int, int ) __nonnull;
+//extern int doupdate ( void );
+extern WINDOW *dupwin ( WINDOW * ) __nonnull;
+extern int echo ( void );
+extern int echochar ( const chtype );
+extern int endwin ( void );
+extern char erasechar ( void );
+//extern int erase ( void );
+extern void filter ( void );
+extern int flash ( void );
+extern int flushinp ( void );
+extern __pure chtype getbkgd ( WINDOW * ) __nonnull;
+//extern int getch ( void );
+//extern int getnstr ( char *, int );
+//extern int getstr ( char * );
+extern int halfdelay ( int );
+//extern bool has_colors ( void );
+extern bool has_ic ( void );
+extern bool has_il ( void );
+//extern int hline ( chtype, int );
+extern void idcok ( WINDOW *, bool );
+extern int idlok ( WINDOW *, bool );
+//extern void immedok ( WINDOW *, bool );
+//extern chtype inch ( void );
+//extern int inchnstr ( chtype *, int );
+//extern int inchstr ( chtype * );
+extern WINDOW *initscr ( void );
+extern int init_colour ( short, short, short, short );
+#define init_color ( c, r, g, b ) init_colour ( (c), (r), (g), (b) )
+extern int init_pair ( short, short, short );
+//extern int innstr ( char *, int );
+//extern int insch ( chtype );
+//extern int insnstr ( const char *, int );
+//extern int insstr ( const char * );
+//extern int instr ( char * );
+extern int intrflush ( WINDOW *, bool );
+extern bool isendwin ( void );
+//extern bool is_linetouched ( WINDOW *, int );
+//extern bool is_wintouched ( WINDOW * );
+extern char *keyname ( int );
+extern int keypad ( WINDOW *, bool );
+extern char killchar ( void );
+extern int leaveok ( WINDOW *, bool );
+extern char *longname ( void );
+extern int meta ( WINDOW *, bool );
+//extern int move ( int, int );
+//extern int mvaddch ( int, int, const chtype );
+//extern int mvaddchnstr ( int, int, const chtype *, int );
+//extern int mvaddchstr ( int, int, const chtype * );
+//extern int mvaddnstr ( int, int, const char *, int );
+//extern int mvaddstr ( int, int, const char * );
+extern int mvcur ( int, int, int, int );
+//extern int mvdelch ( int, int );
+extern int mvderwin ( WINDOW *, int, int );
+//extern int mvgetch ( int, int );
+//extern int mvgetnstr ( int, int, char *, int );
+//extern int mvgetstr ( int, int, char * );
+//extern int mvhline ( int, int, chtype, int );
+//extern chtype mvinch ( int, int );
+//extern int mvinchnstr ( int, int, chtype *, int );
+//extern int mvinchstr ( int, int, chtype * );
+//extern int mvinnstr ( int, int, char *, int );
+//extern int mvinsch ( int, int, chtype );
+//extern int mvinsnstr ( int, int, const char *, int );
+//extern int mvinsstr ( int, int, const char * );
+//extern int mvinstr ( int, int, char * );
+//extern int mvprintw ( int, int, char *, ... );
+//extern int mvscanw ( int, int, char *, ... );
+//extern int mvvline ( int, int, chtype, int );
+//extern int mvwaddch ( WINDOW *, int, int, const chtype );
+//extern int mvwaddchnstr ( WINDOW *, int, int, const chtype *, int );
+//extern int mvwaddchstr ( WINDOW *, int, int, const chtype * );
+//extern int mvwaddnstr ( WINDOW *, int, int, const char *, int );
+//extern int mvwaddstr ( WINDOW *, int, int, const char * );
+//extern int mvwdelch ( WINDOW *, int, int );
+//extern int mvwgetch ( WINDOW *, int, int );
+//extern int mvwgetnstr ( WINDOW *, int, int, char *, int );
+//extern int mvwgetstr ( WINDOW *, int, int, char * );
+//extern int mvwhline ( WINDOW *, int, int, chtype, int );
+extern int mvwin ( WINDOW *, int, int ) __nonnull;
+//extern chtype mvwinch ( WINDOW *, int, int );
+//extern int mvwinchnstr ( WINDOW *, int, int, chtype *, int );
+//extern int mvwinchstr ( WINDOW *, int, int, chtype * );
+//extern int mvwinnstr ( WINDOW *, int, int, char *, int );
+//extern int mvwinsch ( WINDOW *, int, int, chtype );
+//extern int mvwinsnstr ( WINDOW *, int, int, const char *, int );
+//extern int mvwinsstr ( WINDOW *, int, int, const char * );
+//extern int mvwinstr ( WINDOW *, int, int, char * );
+//extern int mvwprintw ( WINDOW *, int, int, char *, ... );
+//extern int mvwscanw ( WINDOW *, int, int, char *, ... );
+//extern int mvwvline ( WINDOW *, int, int, chtype, int );
+extern int napms ( int );
+//extern WINDOW *newpad ( int, int );
+extern WINDOW *newwin ( int, int, int, int );
+extern int nl ( void );
+extern int nocbreak ( void );
+extern int nodelay ( WINDOW *, bool );
+extern int noecho ( void );
+extern int nonl ( void );
+extern void noqiflush ( void );
+extern int noraw ( void );
+extern int notimeout ( WINDOW *, bool );
+extern int overlay ( const WINDOW *, WINDOW * );
+extern int overwrite ( const WINDOW *, WINDOW * );
+extern int pair_content ( short, short *, short * ) __nonnull;
+//extern int pechochar ( WINDOW *, chtype );
+//extern int pnoutrefresh ( WINDOW *, int, int, int, int, int, int );
+//extern int prefresh ( WINDOW *, int, int, int, int, int, int );
+extern int printw ( char *, ... );
+extern int putp ( const char * );
+extern void qiflush ( void );
+extern int raw ( void );
+//extern int redrawwin ( WINDOW * );
+//extern int refresh ( void );
+extern int reset_prog_mode ( void );
+extern int reset_shell_mode ( void );
+extern int resetty ( void );
+extern int ripoffline ( int, int (*) ( WINDOW *, int) );
+extern int savetty ( void );
+//extern int scanw ( char *, ... );
+//extern int scrl ( int );
+//extern int scroll ( WINDOW * );
+//extern int scrollok ( WINDOW *, bool );
+//extern int setscrreg ( int, int );
+extern SCREEN *set_term ( SCREEN * );
+extern int setupterm ( char *, int, int * );
+extern int slk_attr_off ( const attr_t, void * );
+extern int slk_attroff ( const chtype );
+extern int slk_attr_on ( const attr_t, void * );
+extern int slk_attron ( const chtype );
+extern int slk_attr_set ( const attr_t, short, void * );
+extern int slk_attrset ( const chtype );
+extern int slk_clear ( void );
+extern int slk_colour ( short );
+#define slk_color( c ) slk_colour( (c) )
+extern int slk_init ( int );
+extern char *slk_label ( int );
+extern int slk_noutrefresh ( void );
+//extern int slk_refresh ( void );
+extern int slk_restore ( void );
+extern int slk_set ( int, const char *, int ) __nonnull;
+extern int slk_touch ( void );
+extern int standend ( void );
+extern int standout ( void );
+//extern int start_colour ( void );
+#define start_color() start_colour()
+//extern WINDOW *subpad ( WINDOW *, int, int, int, int );
+extern WINDOW *subwin ( WINDOW *, int, int, int, int ) __nonnull;
+extern int syncok ( WINDOW *, bool );
+extern chtype termattrs ( void );
+extern attr_t term_attrs ( void );
+extern char *termname ( void );
+extern int tigetflag ( char * );
+extern int tigetnum ( char * );
+extern char *tigetstr ( char * );
+extern void timeout ( int );
+//extern int touchline ( WINDOW *, int, int );
+//extern int touchwin ( WINDOW * );
+extern char *tparm ( char *, long, long, long, long, long, long, long, long,
+ long );
+extern int typeahead ( int );
+//extern int ungetch ( int );
+//extern int untouchwin ( WINDOW * );
+extern void use_env ( bool );
+extern int vid_attr ( attr_t, short, void * );
+extern int vidattr ( chtype );
+extern int vid_puts ( attr_t, short, void *, int ( *) ( int) );
+extern int vidputs ( chtype, int ( *) ( int) );
+//extern int vline ( chtype, int );
+//extern int vwprintw ( WINDOW *, const char *, va_list );
+extern int vw_printw ( WINDOW *, const char *, va_list ) __nonnull;
+//extern int vwscanw ( WINDOW *, char *, va_list );
+//extern int vw_scanw ( WINDOW *, char *, va_list );
+extern int waddch ( WINDOW *, const chtype ) __nonnull;
+extern int waddchnstr ( WINDOW *, const chtype *, int ) __nonnull;
+//extern int waddchstr ( WINDOW *, const chtype * );
+extern int waddnstr ( WINDOW *, const char *, int ) __nonnull;
+//extern int waddstr ( WINDOW *, const char * );
+extern int wattroff ( WINDOW *, int ) __nonnull;
+extern int wattron ( WINDOW *, int ) __nonnull;
+extern int wattrset ( WINDOW *, int ) __nonnull;
+extern int wattr_get ( WINDOW *, attr_t *, short *, void * )
+ __attribute__ (( nonnull (1, 2, 3)));
+extern int wattr_off ( WINDOW *, attr_t, void * )
+ __attribute__ (( nonnull (1)));
+extern int wattr_on ( WINDOW *, attr_t, void * )
+ __attribute__ (( nonnull (1)));
+extern int wattr_set ( WINDOW *, attr_t, short, void * )
+ __attribute__ (( nonnull (1)));
+//extern void wbkgdset ( WINDOW *, chtype );
+extern int wborder ( WINDOW *, chtype, chtype, chtype, chtype, chtype, chtype,
+ chtype, chtype ) __nonnull;
+extern int wclrtobot ( WINDOW * ) __nonnull;
+extern int wclrtoeol ( WINDOW * ) __nonnull;
+extern void wcursyncup ( WINDOW * );
+extern int wcolour_set ( WINDOW *, short, void * ) /*__nonnull*/;
+#define wcolor_set(w,s,v) wcolour_set((w),(s),(v))
+extern int wdelch ( WINDOW * ) __nonnull;
+extern int wdeleteln ( WINDOW * ) __nonnull;
+extern int wechochar ( WINDOW *, const chtype );
+extern int werase ( WINDOW * ) __nonnull;
+extern int wgetch ( WINDOW * );
+extern int wgetnstr ( WINDOW *, char *, int );
+//extern int wgetstr ( WINDOW *, char * );
+extern int whline ( WINDOW *, chtype, int ) __nonnull;
+//extern chtype winch ( WINDOW * );
+//extern int winchnstr ( WINDOW *, chtype *, int );
+//extern int winchstr ( WINDOW *, chtype * );
+//extern int winnstr ( WINDOW *, char *, int );
+//extern int winsch ( WINDOW *, chtype );
+//extern int winsnstr ( WINDOW *, const char *, int );
+//extern int winsstr ( WINDOW *, const char * );
+//extern int winstr ( WINDOW *, char * );
+extern int wmove ( WINDOW *, int, int );
+//extern int wnoutrefresh ( WINDOW * );
+extern int wprintw ( WINDOW *, const char *, ... ) __nonnull;
+//extern int wredrawln ( WINDOW *, int, int );
+//extern int wrefresh ( WINDOW * );
+//extern int wscanw ( WINDOW *, char *, ... );
+//extern int wscrl ( WINDOW *, int );
+//extern int wsetscrreg ( WINDOW *, int, int );
+//extern int wstandend ( WINDOW * );
+//extern int wstandout ( WINDOW * );
+extern void wsyncup ( WINDOW * );
+extern void wsyncdown ( WINDOW * );
+extern void wtimeout ( WINDOW *, int );
+//extern int wtouchln ( WINDOW *, int, int, int );
+extern int wvline ( WINDOW *, chtype, int ) __nonnull;
+
+/*
+ * There is frankly a ridiculous amount of redundancy within the
+ * curses API - ncurses decided to get around this by using #define
+ * macros, but I've decided to be type-safe and implement them all as
+ * static inlines instead...
+ */
+
+static inline int addch ( const chtype ch ) {
+ return waddch( stdscr, ch );
+}
+
+static inline int addchnstr ( const chtype *chstr, int n ) {
+ return waddchnstr ( stdscr, chstr, n );
+}
+
+static inline int addchstr ( const chtype *chstr ) {
+ return waddchnstr ( stdscr, chstr, -1 );
+}
+
+static inline int addnstr ( const char *str, int n ) {
+ return waddnstr ( stdscr, str, n );
+}
+
+static inline int addstr ( const char *str ) {
+ return waddnstr ( stdscr, str, -1 );
+}
+
+static inline int attroff ( int attrs ) {
+ return wattroff ( stdscr, attrs );
+}
+
+static inline int attron ( int attrs ) {
+ return wattron ( stdscr, attrs );
+}
+
+static inline int attrset ( int attrs ) {
+ return wattrset ( stdscr, attrs );
+}
+
+static inline int attr_get ( attr_t *attrs, short *pair, void *opts ) {
+ return wattr_get ( stdscr, attrs, pair, opts );
+}
+
+static inline int attr_off ( attr_t attrs, void *opts ) {
+ return wattr_off ( stdscr, attrs, opts );
+}
+
+static inline int attr_on ( attr_t attrs, void *opts ) {
+ return wattr_on ( stdscr, attrs, opts );
+}
+
+static inline int attr_set ( attr_t attrs, short cpair, void *opts ) {
+ return wattr_set ( stdscr, attrs, cpair, opts );
+}
+
+static inline void bkgdset ( chtype ch ) {
+ wattrset ( stdscr, ch );
+}
+
+static inline int border ( chtype ls, chtype rs, chtype ts, chtype bs,
+ chtype tl, chtype tr, chtype bl, chtype br ) {
+ return wborder ( stdscr, ls, rs, ts, bs, tl, tr, bl, br );
+}
+
+static inline bool can_change_colour ( void ) {
+ return FALSE;
+}
+
+static inline int clrtobot ( void ) {
+ return wclrtobot( stdscr );
+}
+
+static inline int clrtoeol ( void ) {
+ return wclrtoeol( stdscr );
+}
+
+static inline int colour_set ( short colour_pair_number, void *opts ) {
+ return wcolour_set ( stdscr, colour_pair_number, opts );
+}
+
+static inline int delch ( void ) {
+ return wdelch ( stdscr );
+}
+
+static inline int deleteln ( void ) {
+ return wdeleteln( stdscr );
+}
+
+static inline int erase ( void ) {
+ return werase ( stdscr );
+}
+
+static inline int getch ( void ) {
+ return wgetch ( stdscr );
+}
+
+static inline int getnstr ( char *str, int n ) {
+ return wgetnstr ( stdscr, str, n );
+}
+
+static inline int getstr ( char *str ) {
+ return wgetnstr ( stdscr, str, -1 );
+}
+
+static inline bool has_colors ( void ) {
+ return TRUE;
+}
+
+static inline int has_key ( int kc __unused ) {
+ return TRUE;
+}
+
+static inline int hline ( chtype ch, int n ) {
+ return whline ( stdscr, ch, n );
+}
+
+static inline int move ( int y, int x ) {
+ return wmove ( stdscr, y, x );
+}
+
+static inline int mvaddch ( int y, int x, const chtype ch ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? waddch( stdscr, ch ) : ERR );
+}
+
+static inline int mvaddchnstr ( int y, int x, const chtype *chstr, int n ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? waddchnstr ( stdscr, chstr, n ) : ERR );
+}
+
+static inline int mvaddchstr ( int y, int x, const chtype *chstr ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? waddchnstr ( stdscr, chstr, -1 ) : ERR );
+}
+
+static inline int mvaddnstr ( int y, int x, const char *str, int n ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? waddnstr ( stdscr, str, n ) : ERR );
+}
+
+static inline int mvaddstr ( int y, int x, const char *str ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? waddnstr ( stdscr, str, -1 ) : ERR );
+}
+
+static inline int mvdelch ( int y, int x ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? wdelch ( stdscr ) : ERR );
+}
+
+static inline int mvgetch ( int y, int x ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? wgetch ( stdscr ) : ERR );
+}
+
+static inline int mvgetnstr ( int y, int x, char *str, int n ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? wgetnstr ( stdscr, str, n ) : ERR );
+}
+
+static inline int mvgetstr ( int y, int x, char *str ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? wgetnstr ( stdscr, str, -1 ) : ERR );
+}
+
+static inline int mvhline ( int y, int x, chtype ch, int n ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? whline ( stdscr, ch, n ) : ERR );
+}
+
+// OK, so maybe a few I did with macros...
+#define mvprintw( y, x, fmt, ... ) \
+ ( wmove(stdscr,(y),(x)) == OK \
+ ? wprintw( stdscr,(fmt), ## __VA_ARGS__ ) : ERR )
+
+static inline int mvvline ( int y, int x, chtype ch, int n ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? wvline ( stdscr, ch, n ) : ERR );
+}
+
+static inline int mvwaddch ( WINDOW *win, int y, int x, const chtype ch ) {
+ return ( wmove( win, y, x ) == OK
+ ? waddch ( win, ch ) : ERR );
+}
+
+static inline int mvwaddchnstr ( WINDOW *win, int y, int x, const chtype *chstr, int n ) {
+ return ( wmove ( win, y, x ) == OK
+ ? waddchnstr ( win, chstr, n ) : ERR );
+}
+
+static inline int mvwaddchstr ( WINDOW *win, int y, int x, const chtype *chstr ) {
+ return ( wmove ( win, y, x ) == OK
+ ? waddchnstr ( win, chstr, -1 ) : ERR );
+}
+
+static inline int mvwaddnstr ( WINDOW *win, int y, int x, const char *str, int n ) {
+ return ( wmove ( win, y, x ) == OK
+ ? waddnstr ( win, str, n ) : ERR );
+}
+
+static inline int mvwaddstr ( WINDOW *win, int y, int x, const char *str ) {
+ return ( wmove ( win, y, x ) == OK
+ ? waddnstr ( win, str, -1 ) : ERR );
+}
+
+static inline int mvwdelch ( WINDOW *win, int y, int x ) {
+ return ( wmove ( win, y, x ) == OK
+ ? wdelch ( win ) : ERR );
+}
+
+static inline int mvwgetch ( WINDOW *win, int y, int x ) {
+ return ( wmove ( win, y, x ) == OK
+ ? wgetch ( win ) : ERR );
+}
+
+static inline int mvwgetnstr ( WINDOW *win, int y, int x, char *str, int n ) {
+ return ( wmove ( win, y, x ) == OK
+ ? wgetnstr ( win, str, n ) : ERR );
+}
+
+static inline int mvwgetstr ( WINDOW *win, int y, int x, char *str ) {
+ return ( wmove ( win, y, x ) == OK
+ ? wgetnstr ( win, str, -1 ) : ERR );
+}
+
+static inline int mvwhline ( WINDOW *win, int y, int x, chtype ch, int n ) {
+ return ( wmove ( win, y, x ) == OK
+ ? whline ( win, ch, n ) : ERR );
+}
+
+#define mvwprintw( win, y, x, fmt, ... ) \
+ ( wmove((win),(y),(x)) == OK \
+ ? wprintw((win),(fmt), ## __VA_ARGS__) : ERR )
+
+static inline int mvwvline ( WINDOW *win, int y, int x, chtype ch, int n ) {
+ return ( wmove ( win, y, x ) == OK
+ ? wvline ( win, ch, n ) : ERR );
+}
+
+#define printw( fmt, ... ) wprintw(stdscr,(fmt), ## __VA_ARGS__ )
+
+static inline int slk_refresh ( void ) {
+ if ( slk_clear() == OK )
+ return slk_restore();
+ else
+ return ERR;
+}
+
+#define standend() wstandend( stdscr )
+#define standout() wstandout( stdscr )
+
+static inline int start_colour ( void ) {
+ return OK;
+}
+
+static inline int vline ( chtype ch, int n ) {
+ return wvline ( stdscr, ch, n );
+}
+
+// marked for removal
+static inline int vwprintw ( WINDOW *win, const char *fmt, va_list varglist ) {
+ return vw_printw ( win, fmt, varglist );
+}
+
+static inline int waddchstr ( WINDOW *win, const chtype *chstr ) {
+ return waddchnstr ( win, chstr, -1 );
+}
+
+static inline int waddstr ( WINDOW *win, const char *str ) {
+ return waddnstr ( win, str, -1 );
+}
+
+static inline int wbkgdset ( WINDOW *win, chtype ch ) {
+ return wattrset( win, ch );
+}
+
+static inline int wgetstr ( WINDOW *win, char *str ) {
+ return wgetnstr ( win, str, -1 );
+}
+
+static inline int wstandend ( WINDOW *win ) {
+ return wattrset ( win, A_DEFAULT );
+}
+
+static inline int wstandout ( WINDOW *win ) {
+ return wattrset ( win, A_STANDOUT );
+}
+
+#endif /* CURSES_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/elf.h b/src/VBox/Devices/PC/ipxe/src/include/elf.h
new file mode 100644
index 00000000..04022b68
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/elf.h
@@ -0,0 +1,234 @@
+#ifndef ELF_H
+#define ELF_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#define EI_NIDENT 16 /* Size of e_ident array. */
+
+/* Values for e_type. */
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* Relocatable file */
+#define ET_EXEC 2 /* Executable file */
+#define ET_DYN 3 /* Shared object file */
+#define ET_CORE 4 /* Core file */
+
+/* Values for e_machine (architecute). */
+#define EM_NONE 0 /* No machine */
+#define EM_M32 1 /* AT&T WE 32100 */
+#define EM_SPARC 2 /* SUN SPARC */
+#define EM_386 3 /* Intel 80386+ */
+#define EM_68K 4 /* Motorola m68k family */
+#define EM_88K 5 /* Motorola m88k family */
+#define EM_486 6 /* Perhaps disused */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS R3000 big-endian */
+#define EM_S370 9 /* IBM System/370 */
+#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */
+
+#define EM_PARISC 15 /* HPPA */
+#define EM_VPP500 17 /* Fujitsu VPP500 */
+#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
+#define EM_960 19 /* Intel 80960 */
+#define EM_PPC 20 /* PowerPC */
+#define EM_PPC64 21 /* PowerPC 64-bit */
+#define EM_S390 22 /* IBM S390 */
+
+#define EM_V800 36 /* NEC V800 series */
+#define EM_FR20 37 /* Fujitsu FR20 */
+#define EM_RH32 38 /* TRW RH-32 */
+#define EM_RCE 39 /* Motorola RCE */
+#define EM_ARM 40 /* ARM */
+#define EM_FAKE_ALPHA 41 /* Digital Alpha */
+#define EM_SH 42 /* Hitachi SH */
+#define EM_SPARCV9 43 /* SPARC v9 64-bit */
+#define EM_TRICORE 44 /* Siemens Tricore */
+#define EM_ARC 45 /* Argonaut RISC Core */
+#define EM_H8_300 46 /* Hitachi H8/300 */
+#define EM_H8_300H 47 /* Hitachi H8/300H */
+#define EM_H8S 48 /* Hitachi H8S */
+#define EM_H8_500 49 /* Hitachi H8/500 */
+#define EM_IA_64 50 /* Intel Merced */
+#define EM_MIPS_X 51 /* Stanford MIPS-X */
+#define EM_COLDFIRE 52 /* Motorola Coldfire */
+#define EM_68HC12 53 /* Motorola M68HC12 */
+#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/
+#define EM_PCP 55 /* Siemens PCP */
+#define EM_NCPU 56 /* Sony nCPU embeeded RISC */
+#define EM_NDR1 57 /* Denso NDR1 microprocessor */
+#define EM_STARCORE 58 /* Motorola Start*Core processor */
+#define EM_ME16 59 /* Toyota ME16 processor */
+#define EM_ST100 60 /* STMicroelectronic ST100 processor */
+#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/
+#define EM_X86_64 62 /* AMD x86-64 architecture */
+#define EM_PDSP 63 /* Sony DSP Processor */
+
+#define EM_FX66 66 /* Siemens FX66 microcontroller */
+#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */
+#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */
+#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */
+#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */
+#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */
+#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */
+#define EM_SVX 73 /* Silicon Graphics SVx */
+#define EM_AT19 74 /* STMicroelectronics ST19 8 bit mc */
+#define EM_VAX 75 /* Digital VAX */
+#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
+#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */
+#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */
+#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */
+#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */
+#define EM_HUANY 81 /* Harvard University machine-independent object files */
+#define EM_PRISM 82 /* SiTera Prism */
+#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */
+#define EM_FR30 84 /* Fujitsu FR30 */
+#define EM_D10V 85 /* Mitsubishi D10V */
+#define EM_D30V 86 /* Mitsubishi D30V */
+#define EM_V850 87 /* NEC v850 */
+#define EM_M32R 88 /* Mitsubishi M32R */
+#define EM_MN10300 89 /* Matsushita MN10300 */
+#define EM_MN10200 90 /* Matsushita MN10200 */
+#define EM_PJ 91 /* picoJava */
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
+#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
+#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
+#define EM_NUM 95
+
+/* Values for p_type. */
+#define PT_NULL 0 /* Unused entry. */
+#define PT_LOAD 1 /* Loadable segment. */
+#define PT_DYNAMIC 2 /* Dynamic linking information segment. */
+#define PT_INTERP 3 /* Pathname of interpreter. */
+#define PT_NOTE 4 /* Auxiliary information. */
+#define PT_SHLIB 5 /* Reserved (not used). */
+#define PT_PHDR 6 /* Location of program header itself. */
+
+/* Values for p_flags. */
+#define PF_X 0x1 /* Executable. */
+#define PF_W 0x2 /* Writable. */
+#define PF_R 0x4 /* Readable. */
+
+
+#define ELF_PROGRAM_RETURNS_BIT 0x8000000 /* e_flags bit 31 */
+
+#define EI_MAG0 0
+#define ELFMAG0 0x7f
+
+#define EI_MAG1 1
+#define ELFMAG1 'E'
+
+#define EI_MAG2 2
+#define ELFMAG2 'L'
+
+#define EI_MAG3 3
+#define ELFMAG3 'F'
+
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+#define EI_CLASS 4 /* File class byte index */
+#define ELFCLASSNONE 0 /* Invalid class */
+#define ELFCLASS32 1 /* 32-bit objects */
+#define ELFCLASS64 2 /* 64-bit objects */
+
+#define EI_DATA 5 /* Data encodeing byte index */
+#define ELFDATANONE 0 /* Invalid data encoding */
+#define ELFDATA2LSB 1 /* 2's complement little endian */
+#define ELFDATA2MSB 2 /* 2's complement big endian */
+
+#define EI_VERSION 6 /* File version byte index */
+ /* Value must be EV_CURRENT */
+
+#define EV_NONE 0 /* Invalid ELF Version */
+#define EV_CURRENT 1 /* Current version */
+
+#define ELF32_PHDR_SIZE (8*4) /* Size of an elf program header */
+
+#ifndef ASSEMBLY
+
+#include <stdint.h>
+
+/*
+ * ELF definitions common to all 32-bit architectures.
+ */
+
+typedef uint32_t Elf32_Addr;
+typedef uint16_t Elf32_Half;
+typedef uint32_t Elf32_Off;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf32_Word;
+typedef uint32_t Elf32_Size;
+
+typedef uint64_t Elf64_Addr;
+typedef uint16_t Elf64_Half;
+typedef uint64_t Elf64_Off;
+typedef int32_t Elf64_Sword;
+typedef uint32_t Elf64_Word;
+typedef uint64_t Elf64_Size;
+
+/*
+ * ELF header.
+ */
+typedef struct {
+ unsigned char e_ident[EI_NIDENT]; /* File identification. */
+ Elf32_Half e_type; /* File type. */
+ Elf32_Half e_machine; /* Machine architecture. */
+ Elf32_Word e_version; /* ELF format version. */
+ Elf32_Addr e_entry; /* Entry point. */
+ Elf32_Off e_phoff; /* Program header file offset. */
+ Elf32_Off e_shoff; /* Section header file offset. */
+ Elf32_Word e_flags; /* Architecture-specific flags. */
+ Elf32_Half e_ehsize; /* Size of ELF header in bytes. */
+ Elf32_Half e_phentsize; /* Size of program header entry. */
+ Elf32_Half e_phnum; /* Number of program header entries. */
+ Elf32_Half e_shentsize; /* Size of section header entry. */
+ Elf32_Half e_shnum; /* Number of section header entries. */
+ Elf32_Half e_shstrndx; /* Section name strings section. */
+} Elf32_Ehdr;
+
+typedef struct {
+ unsigned char e_ident[EI_NIDENT]; /* File identification. */
+ Elf64_Half e_type; /* File type. */
+ Elf64_Half e_machine; /* Machine architecture. */
+ Elf64_Word e_version; /* ELF format version. */
+ Elf64_Addr e_entry; /* Entry point. */
+ Elf64_Off e_phoff; /* Program header file offset. */
+ Elf64_Off e_shoff; /* Section header file offset. */
+ Elf64_Word e_flags; /* Architecture-specific flags. */
+ Elf64_Half e_ehsize; /* Size of ELF header in bytes. */
+ Elf64_Half e_phentsize; /* Size of program header entry. */
+ Elf64_Half e_phnum; /* Number of program header entries. */
+ Elf64_Half e_shentsize; /* Size of section header entry. */
+ Elf64_Half e_shnum; /* Number of section header entries. */
+ Elf64_Half e_shstrndx; /* Section name strings section. */
+} Elf64_Ehdr;
+
+/*
+ * Program header.
+ */
+typedef struct {
+ Elf32_Word p_type; /* Entry type. */
+ Elf32_Off p_offset; /* File offset of contents. */
+ Elf32_Addr p_vaddr; /* Virtual address (not used). */
+ Elf32_Addr p_paddr; /* Physical address. */
+ Elf32_Size p_filesz; /* Size of contents in file. */
+ Elf32_Size p_memsz; /* Size of contents in memory. */
+ Elf32_Word p_flags; /* Access permission flags. */
+ Elf32_Size p_align; /* Alignment in memory and file. */
+} Elf32_Phdr;
+
+typedef struct {
+ Elf64_Word p_type; /* Entry type. */
+ Elf64_Word p_flags; /* Access permission flags. */
+ Elf64_Off p_offset; /* File offset of contents. */
+ Elf64_Addr p_vaddr; /* Virtual address (not used). */
+ Elf64_Addr p_paddr; /* Physical address. */
+ Elf64_Size p_filesz; /* Size of contents in file. */
+ Elf64_Size p_memsz; /* Size of contents in memory. */
+ Elf64_Size p_align; /* Alignment in memory and file. */
+} Elf64_Phdr;
+
+/* Standardized Elf image notes for booting... The name for all of these is ELFBoot */
+
+#endif /* ASSEMBLY */
+
+#endif /* ELF_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/endian.h b/src/VBox/Devices/PC/ipxe/src/include/endian.h
new file mode 100644
index 00000000..9682cf9b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/endian.h
@@ -0,0 +1,21 @@
+#ifndef ETHERBOOT_ENDIAN_H
+#define ETHERBOOT_ENDIAN_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* Definitions for byte order, according to significance of bytes,
+ from low addresses to high addresses. The value is what you get by
+ putting '4' in the most significant byte, '3' in the second most
+ significant byte, '2' in the second least significant byte, and '1'
+ in the least significant byte, and then writing down one digit for
+ each byte, starting with the byte at the lowest address at the left,
+ and proceeding to the byte with the highest address at the right. */
+
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __PDP_ENDIAN 3412
+
+#include "bits/endian.h"
+
+
+#endif /* ETHERBOOT_ENDIAN_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/errno.h b/src/VBox/Devices/PC/ipxe/src/include/errno.h
new file mode 100644
index 00000000..d576d418
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/errno.h
@@ -0,0 +1,761 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef ERRNO_H
+#define ERRNO_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Error codes
+ *
+ * Return status codes as used within iPXE are designed to allow for
+ * maximum visibility into the source of an error even in an end-user
+ * build with no debugging. They are constructed as follows:
+ *
+ * Bits 7-0 : PXE error code
+ *
+ * This is the closest equivalent PXE error code
+ * (e.g. PXENV_STATUS_OUT_OF_RESOURCES), and is the only part of the
+ * error that will be returned via the PXE API, since PXE has
+ * predefined error codes.
+ *
+ * Bits 12-8 : Per-file disambiguator
+ *
+ * When the same error number can be generated from multiple points
+ * within a file, this field can be used to identify the unique
+ * instance.
+ *
+ * Bits 23-13 : File identifier
+ *
+ * This is a unique identifier for the file generating the error
+ * (e.g. ERRFILE_tcp for tcp.c).
+ *
+ * Bits 30-24 : POSIX error code
+ *
+ * This is the closest equivalent POSIX error code (e.g. ENOMEM).
+ *
+ * Bit 31 : Reserved
+ *
+ * Errors are usually return as negative error numbers (e.g. -EINVAL);
+ * bit 31 is therefore unusable.
+ *
+ *
+ * The convention within the code is that errors are negative and
+ * expressed using the POSIX error, e.g.
+ *
+ * return -EINVAL;
+ *
+ * By various bits of preprocessor magic, the PXE error code and file
+ * identifier are already incorporated into the definition of the
+ * POSIX error macro, which keeps the code relatively clean.
+ *
+ *
+ * Functions that wish to return failures should be declared as
+ * returning an integer @c rc "Return status code". A return value of
+ * zero indicates success, a non-zero value indicates failure. The
+ * return value can be passed directly to strerror() in order to
+ * generate a human-readable error message, e.g.
+ *
+ * if ( ( rc = some_function ( ... ) ) != 0 ) {
+ * DBG ( "Whatever I was trying to do failed: %s\n", strerror ( rc ) );
+ * return rc;
+ * }
+ *
+ * As illustrated in the above example, error returns should generally
+ * be directly propagated upward to the calling function.
+ *
+ *
+ * Individual files may declare localised errors using
+ * __einfo_uniqify(). For example, iscsi.c declares a localised
+ * version of EACCES for the error of "access denied due to incorrect
+ * target username":
+ *
+ * #define EACCES_INCORRECT_TARGET_USERNAME \
+ * __einfo_error ( EINFO_EACCES_INCORRECT_TARGET_USERNAME )
+ * #define EINFO_EACCES_INCORRECT_TARGET_USERNAME \
+ * __einfo_uniqify ( EINFO_EACCESS, 0x01, "Incorrect target username" )
+ *
+ * which can then be used as:
+ *
+ * return -EACCES_INCORRECT_TARGET_USERNAME;
+ *
+ */
+
+/* Get definitions for file identifiers */
+#include <ipxe/errfile.h>
+
+/* If we do not have a valid file identifier, generate a compiler
+ * warning upon usage of any error codes. (Don't just use a #warning,
+ * because some files include errno.h but don't ever actually use any
+ * error codes.)
+ */
+#if ! ERRFILE
+extern char missing_errfile_declaration[] /*__attribute__ (( deprecated ))*/;
+#undef ERRFILE
+#define ERRFILE ( 0 * ( ( int ) missing_errfile_declaration ) )
+#endif
+
+/**
+ * Declare error information
+ *
+ * @v pxe PXE error number (0x00-0xff)
+ * @v posix POSIX error number (0x00-0x7f)
+ * @v uniq Error disambiguator (0x00-0x1f)
+ * @v desc Error description
+ * @ret einfo Error information
+ */
+#define __einfo( pxe, posix, uniq, desc ) ( pxe, posix, uniq, desc )
+
+/**
+ * Get PXE error number
+ *
+ * @v einfo Error information
+ * @ret pxe PXE error number
+ */
+#define __einfo_pxe( einfo ) __einfo_extract_pxe einfo
+#define __einfo_extract_pxe( pxe, posix, uniq, desc ) pxe
+
+/**
+ * Get POSIX error number
+ *
+ * @v einfo Error information
+ * @ret posix POSIX error number
+ */
+#define __einfo_posix( einfo ) __einfo_extract_posix einfo
+#define __einfo_extract_posix( pxe, posix, uniq, desc ) posix
+
+/**
+ * Get error disambiguator
+ *
+ * @v einfo Error information
+ * @ret uniq Error disambiguator
+ */
+#define __einfo_uniq( einfo ) __einfo_extract_uniq einfo
+#define __einfo_extract_uniq( pxe, posix, uniq, desc ) uniq
+
+/**
+ * Get error description
+ *
+ * @v einfo Error information
+ * @ret desc Error description
+ */
+#define __einfo_desc( einfo ) __einfo_extract_desc einfo
+#define __einfo_extract_desc( pxe, posix, uniq, desc ) desc
+
+/**
+ * Declare disambiguated error
+ *
+ * @v einfo_base Base error information
+ * @v uniq Error disambiguator
+ * @v desc Error description
+ * @ret einfo Error information
+ */
+#define __einfo_uniqify( einfo_base, uniq, desc ) \
+ __einfo ( __einfo_pxe ( einfo_base ), \
+ __einfo_posix ( einfo_base ), \
+ uniq, desc )
+
+/**
+ * Get error number
+ *
+ * @v einfo Error information
+ * @ret errno Error number
+ */
+#define __einfo_errno( einfo ) \
+ ( ( __einfo_posix ( einfo ) << 24 ) | ( ERRFILE ) | \
+ ( __einfo_uniq ( einfo ) << 8 ) | \
+ ( __einfo_pxe ( einfo ) << 0 ) )
+
+/**
+ * Disambiguate a base error based on non-constant information
+ *
+ * @v error_base Base error
+ * @v uniq Error disambiguator
+ * @v ... List of expected possible disambiguated errors
+ * @ret error Error
+ *
+ * EUNIQ() should be used when information from an external source is
+ * being incorporated into an error. For example, the 802.11 stack
+ * uses EUNIQ() to incorporate 802.11 status codes returned by an
+ * access point into an error.
+ *
+ * EUNIQ() should not be used for constant error disambiguators; use
+ * __einfo_uniqify() instead.
+ */
+#define EUNIQ( errno, uniq, ... ) ( { \
+ euniq_discard ( 0, ##__VA_ARGS__); \
+ ( ( int ) ( (errno) | ( (uniq) << 8 ) ) ); } )
+static inline void euniq_discard ( int dummy __unused, ... ) {}
+
+/**
+ * Declare error
+ *
+ * @v einfo Error information
+ * @ret error Error
+ */
+#define __einfo_error( einfo ) ( { \
+ __asm__ ( ".section \".einfo\", \"\", @progbits\n\t" \
+ ".align 8\n\t" \
+ "\n1:\n\t" \
+ ".long ( 4f - 1b )\n\t" \
+ ".long %c0\n\t" \
+ ".long ( 2f - 1b )\n\t" \
+ ".long ( 3f - 1b )\n\t" \
+ ".long %c1\n\t" \
+ "\n2:\t.asciz \"" __einfo_desc ( einfo ) "\"\n\t" \
+ "\n3:\t.asciz \"" __FILE__ "\"\n\t" \
+ ".align 8\n\t" \
+ "\n4:\n\t" \
+ ".previous\n\t" : : \
+ "i" ( __einfo_errno ( einfo) ), \
+ "i" ( __LINE__ ) ); \
+ __einfo_errno ( einfo ); } )
+
+/**
+ * @defgroup pxeerrors PXE error codes
+ *
+ * The names, meanings and values of these error codes are defined by
+ * the PXE specification.
+ *
+ * @{
+ */
+
+/* Generic errors */
+#define PXENV_STATUS_SUCCESS 0x0000
+#define PXENV_STATUS_FAILURE 0x0001
+#define PXENV_STATUS_BAD_FUNC 0x0002
+#define PXENV_STATUS_UNSUPPORTED 0x0003
+#define PXENV_STATUS_KEEP_UNDI 0x0004
+#define PXENV_STATUS_KEEP_ALL 0x0005
+#define PXENV_STATUS_OUT_OF_RESOURCES 0x0006
+
+/* ARP errors (0x0010 to 0x001f) */
+#define PXENV_STATUS_ARP_TIMEOUT 0x0011
+
+/* Base-Code state errors */
+#define PXENV_STATUS_UDP_CLOSED 0x0018
+#define PXENV_STATUS_UDP_OPEN 0x0019
+#define PXENV_STATUS_TFTP_CLOSED 0x001a
+#define PXENV_STATUS_TFTP_OPEN 0x001b
+
+/* BIOS/system errors (0x0020 to 0x002f) */
+#define PXENV_STATUS_MCOPY_PROBLEM 0x0020
+#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x0021
+#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x0022
+#define PXENV_STATUS_BIS_INIT_FAILURE 0x0023
+#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x0024
+#define PXENV_STATUS_BIS_GBOA_FAILURE 0x0025
+#define PXENV_STATUS_BIS_FREE_FAILURE 0x0026
+#define PXENV_STATUS_BIS_GSI_FAILURE 0x0027
+#define PXENV_STATUS_BIS_BAD_CKSUM 0x0028
+
+/* TFTP/MTFTP errors (0x0030 to 0x003f) */
+#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x0030
+#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x0032
+#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x0033
+#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x0035
+#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x0036
+#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x0038
+#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x0039
+#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x003a
+#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x003b
+#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x003c
+#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x003d
+#define PXENV_STATUS_TFTP_NO_FILESIZE 0x003e
+#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x003f
+
+/* Reserved errors 0x0040 to 0x004f) */
+
+/* DHCP/BOOTP errors (0x0050 to 0x005f) */
+#define PXENV_STATUS_DHCP_TIMEOUT 0x0051
+#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x0052
+#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x0053
+#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x0054
+
+/* Driver errors (0x0060 to 0x006f) */
+#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x0060
+#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x0061
+#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x0062
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x0063
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x0064
+#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x0065
+#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x0066
+#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x0067
+#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x0068
+#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x0069
+#define PXENV_STATUS_UNDI_INVALID_STATE 0x006a
+#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x006b
+#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x006c
+
+/* ROM and NBP bootstrap errors (0x0070 to 0x007f) */
+#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x0074
+#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x0076
+#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x0077
+#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x0078
+#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x0079
+
+/* Environment NBP errors (0x0080 to 0x008f) */
+
+/* Reserved errors (0x0090 to 0x009f) */
+
+/* Miscellaneous errors (0x00a0 to 0x00af) */
+#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0x00a0
+#define PXENV_STATUS_BINL_NO_PXE_SERVER 0x00a1
+#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0x00a2
+#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0x00a3
+
+/* BUSD errors (0x00b0 to 0x00bf) */
+#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0x00b0
+
+/* Loader errors (0x00c0 to 0x00cf) */
+#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0x00c0
+#define PXENV_STATUS_LOADER_NO_BC_ROMID 0x00c1
+#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0x00c2
+#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0x00c3
+#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0x00c4
+#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0x00c5
+#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0x00c6
+#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0x00c8
+#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0x00c9
+#define PXENV_STATUS_LOADER_UNDI_START 0x00ca
+#define PXENV_STATUS_LOADER_BC_START 0x00cb
+
+/** @} */
+
+/** Derive PXENV_STATUS code from iPXE error number */
+#define PXENV_STATUS( rc ) ( (-(rc)) & 0x00ff )
+
+/**
+ * @defgroup posixerrors POSIX error codes
+ *
+ * The names and meanings (but not the values) of these error codes
+ * are defined by POSIX.
+ *
+ * @{
+ */
+
+/** Operation completed successfully */
+#define ENOERR __einfo_error ( EINFO_ENOERR )
+#define EINFO_ENOERR __einfo ( PXENV_STATUS_SUCCESS, 0x00, 0, \
+ "Operation completed successfully" )
+
+/** Argument list too long */
+#define E2BIG __einfo_error ( EINFO_E2BIG )
+#define EINFO_E2BIG __einfo ( PXENV_STATUS_BAD_FUNC, 0x01, 0, \
+ "Argument list too long" )
+
+/** Permission denied */
+#define EACCES __einfo_error ( EINFO_EACCES )
+#define EINFO_EACCES __einfo ( PXENV_STATUS_TFTP_ACCESS_VIOLATION, 0x02, 0, \
+ "Permission denied" )
+
+/** Address already in use */
+#define EADDRINUSE __einfo_error ( EINFO_EADDRINUSE )
+#define EINFO_EADDRINUSE __einfo ( PXENV_STATUS_UDP_OPEN, 0x03, 0, \
+ "Address already in use" )
+
+/** Address not available */
+#define EADDRNOTAVAIL __einfo_error ( EINFO_EADDRNOTAVAIL )
+#define EINFO_EADDRNOTAVAIL __einfo ( PXENV_STATUS_UDP_OPEN, 0x04, 0, \
+ "Address not available" )
+
+/** Address family not supported */
+#define EAFNOSUPPORT __einfo_error ( EINFO_EAFNOSUPPORT )
+#define EINFO_EAFNOSUPPORT __einfo ( PXENV_STATUS_UNSUPPORTED, 0x05, 0, \
+ "Address family not supported" )
+
+/** Resource temporarily unavailable */
+#define EAGAIN __einfo_error ( EINFO_EAGAIN )
+#define EINFO_EAGAIN __einfo ( PXENV_STATUS_FAILURE, 0x06, 0, \
+ "Resource temporarily unavailable" )
+
+/** Connection already in progress */
+#define EALREADY __einfo_error ( EINFO_EALREADY )
+#define EINFO_EALREADY __einfo ( PXENV_STATUS_UDP_OPEN, 0x07, 0, \
+ "Connection already in progress" )
+
+/** Bad file descriptor */
+#define EBADF __einfo_error ( EINFO_EBADF )
+#define EINFO_EBADF __einfo ( PXENV_STATUS_TFTP_CLOSED, 0x08, 0, \
+ "Bad file descriptor" )
+
+/** Bad message */
+#define EBADMSG __einfo_error ( EINFO_EBADMSG )
+#define EINFO_EBADMSG __einfo ( PXENV_STATUS_FAILURE, 0x09, 0, \
+ "Bad message" )
+
+/** Device or resource busy */
+#define EBUSY __einfo_error ( EINFO_EBUSY )
+#define EINFO_EBUSY __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x0a, 0, \
+ "Device or resource busy" )
+
+/** Operation canceled */
+#define ECANCELED __einfo_error ( EINFO_ECANCELED )
+#define EINFO_ECANCELED __einfo ( PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE, \
+ 0x0b, 0, "Operation canceled" )
+
+/** No child processes */
+#define ECHILD __einfo_error ( EINFO_ECHILD )
+#define EINFO_ECHILD __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x0c, 0, \
+ "No child processes" )
+
+/** Connection aborted */
+#define ECONNABORTED __einfo_error ( EINFO_ECONNABORTED )
+#define EINFO_ECONNABORTED \
+ __einfo ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION, 0x0d, 0, \
+ "Connection aborted" )
+
+/** Connection refused */
+#define ECONNREFUSED __einfo_error ( EINFO_ECONNREFUSED )
+#define EINFO_ECONNREFUSED __einfo ( PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION, \
+ 0x0e, 0, "Connection refused" )
+
+/** Connection reset */
+#define ECONNRESET __einfo_error ( EINFO_ECONNRESET )
+#define EINFO_ECONNRESET \
+ __einfo ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION, 0x0f, 0, \
+ "Connection reset" )
+
+/** Resource deadlock avoided */
+#define EDEADLK __einfo_error ( EINFO_EDEADLK )
+#define EINFO_EDEADLK __einfo ( PXENV_STATUS_FAILURE, 0x10, 0, \
+ "Resource deadlock avoided" )
+
+/** Destination address required */
+#define EDESTADDRREQ __einfo_error ( EINFO_EDESTADDRREQ )
+#define EINFO_EDESTADDRREQ __einfo ( PXENV_STATUS_BAD_FUNC, 0x11, 0, \
+ "Destination address required" )
+
+/** Mathematics argument out of domain of function */
+#define EDOM __einfo_error ( EINFO_EDOM )
+#define EINFO_EDOM __einfo ( PXENV_STATUS_FAILURE, 0x12, 0, \
+ "Mathematics argument out of domain of function" )
+
+/** Disk quota exceeded */
+#define EDQUOT __einfo_error ( EINFO_EDQUOT )
+#define EINFO_EDQUOT __einfo ( PXENV_STATUS_FAILURE, 0x13, 0, \
+ "Disk quote exceeded" )
+
+/** File exists */
+#define EEXIST __einfo_error ( EINFO_EEXIST )
+#define EINFO_EEXIST __einfo ( PXENV_STATUS_FAILURE, 0x14, 0, \
+ "File exists" )
+
+/** Bad address */
+#define EFAULT __einfo_error ( EINFO_EFAULT )
+#define EINFO_EFAULT __einfo ( PXENV_STATUS_MCOPY_PROBLEM, 0x15, 0, \
+ "Bad address" )
+
+/** File too large */
+#define EFBIG __einfo_error ( EINFO_EFBIG )
+#define EINFO_EFBIG __einfo ( PXENV_STATUS_MCOPY_PROBLEM, 0x16, 0, \
+ "File too large" )
+
+/** Host is unreachable */
+#define EHOSTUNREACH __einfo_error ( EINFO_EHOSTUNREACH )
+#define EINFO_EHOSTUNREACH __einfo ( PXENV_STATUS_ARP_TIMEOUT, 0x17, 0, \
+ "Host is unreachable" )
+
+/** Identifier removed */
+#define EIDRM __einfo_error ( EINFO_EIDRM )
+#define EINFO_EIDRM __einfo ( PXENV_STATUS_FAILURE, 0x18, 0, \
+ "Identifier removed" )
+
+/** Illegal byte sequence */
+#define EILSEQ __einfo_error ( EINFO_EILSEQ )
+#define EINFO_EILSEQ __einfo ( PXENV_STATUS_FAILURE, 0x19, 0, \
+ "Illegal byte sequence" )
+
+/** Operation in progress */
+#define EINPROGRESS __einfo_error ( EINFO_EINPROGRESS )
+#define EINFO_EINPROGRESS __einfo ( PXENV_STATUS_FAILURE, 0x1a, 0, \
+ "Operation in progress" )
+
+/** Interrupted function call */
+#define EINTR __einfo_error ( EINFO_EINTR )
+#define EINFO_EINTR __einfo ( PXENV_STATUS_FAILURE, 0x1b, 0, \
+ "Interrupted function call" )
+
+/** Invalid argument */
+#define EINVAL __einfo_error ( EINFO_EINVAL )
+#define EINFO_EINVAL __einfo ( PXENV_STATUS_BAD_FUNC, 0x1c, 0, \
+ "Invalid argument" )
+
+/** Input/output error */
+#define EIO __einfo_error ( EINFO_EIO )
+#define EINFO_EIO __einfo ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION, \
+ 0x1d, 0, "Input/output error" )
+
+/** Socket is connected */
+#define EISCONN __einfo_error ( EINFO_EISCONN )
+#define EINFO_EISCONN __einfo ( PXENV_STATUS_UDP_OPEN, 0x1e, 0, \
+ "Socket is connected" )
+
+/** Is a directory */
+#define EISDIR __einfo_error ( EINFO_EISDIR )
+#define EINFO_EISDIR __einfo ( PXENV_STATUS_FAILURE, 0x1f, 0, \
+ "Is a directory" )
+
+/** Too many levels of symbolic links */
+#define ELOOP __einfo_error ( EINFO_ELOOP )
+#define EINFO_ELOOP __einfo ( PXENV_STATUS_FAILURE, 0x20, 0, \
+ "Too many levels of symbolic links" )
+
+/** Too many open files */
+#define EMFILE __einfo_error ( EINFO_EMFILE )
+#define EINFO_EMFILE __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x21, 0, \
+ "Too many open files" )
+
+/** Too many links */
+#define EMLINK __einfo_error ( EINFO_EMLINK )
+#define EINFO_EMLINK __einfo ( PXENV_STATUS_FAILURE, 0x22, 0, \
+ "Too many links" )
+
+/** Message too long */
+#define EMSGSIZE __einfo_error ( EINFO_EMSGSIZE )
+#define EINFO_EMSGSIZE __einfo ( PXENV_STATUS_BAD_FUNC, 0x23, 0, \
+ "Message too long" )
+
+/** Multihop attempted */
+#define EMULTIHOP __einfo_error ( EINFO_EMULTIHOP )
+#define EINFO_EMULTIHOP __einfo ( PXENV_STATUS_FAILURE, 0x24, 0, \
+ "Multihop attempted" )
+
+/** Filename too long */
+#define ENAMETOOLONG __einfo_error ( EINFO_ENAMETOOLONG )
+#define EINFO_ENAMETOOLONG __einfo ( PXENV_STATUS_FAILURE, 0x25, 0, \
+ "Filename too long" )
+
+/** Network is down */
+#define ENETDOWN __einfo_error ( EINFO_ENETDOWN )
+#define EINFO_ENETDOWN __einfo ( PXENV_STATUS_ARP_TIMEOUT, 0x26, 0, \
+ "Network is down" )
+
+/** Connection aborted by network */
+#define ENETRESET __einfo_error ( EINFO_ENETRESET )
+#define EINFO_ENETRESET __einfo ( PXENV_STATUS_FAILURE, 0x27, 0, \
+ "Connection aborted by network" )
+
+/** Network unreachable */
+#define ENETUNREACH __einfo_error ( EINFO_ENETUNREACH )
+#define EINFO_ENETUNREACH __einfo ( PXENV_STATUS_ARP_TIMEOUT, 0x28, 0, \
+ "Network unreachable" )
+
+/** Too many open files in system */
+#define ENFILE __einfo_error ( EINFO_ENFILE )
+#define EINFO_ENFILE __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x29, 0, \
+ "Too many open files in system" )
+
+/** No buffer space available */
+#define ENOBUFS __einfo_error ( EINFO_ENOBUFS )
+#define EINFO_ENOBUFS __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x2a, 0, \
+ "No buffer space available" )
+
+/** No message is available on the STREAM head read queue */
+#define ENODATA __einfo_error ( EINFO_ENODATA )
+#define EINFO_ENODATA \
+ __einfo ( PXENV_STATUS_FAILURE, 0x2b, 0, \
+ "No message is available on the STREAM head read queue" )
+
+/** No such device */
+#define ENODEV __einfo_error ( EINFO_ENODEV )
+#define EINFO_ENODEV __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x2c, 0, \
+ "No such device" )
+
+/** No such file or directory */
+#define ENOENT __einfo_error ( EINFO_ENOENT )
+#define EINFO_ENOENT __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x2d, 0, \
+ "No such file or directory" )
+
+/** Exec format error */
+#define ENOEXEC __einfo_error ( EINFO_ENOEXEC )
+#define EINFO_ENOEXEC __einfo ( PXENV_STATUS_FAILURE, 0x2e, 0, \
+ "Exec format error" )
+
+/** No locks available */
+#define ENOLCK __einfo_error ( EINFO_ENOLCK )
+#define EINFO_ENOLCK __einfo ( PXENV_STATUS_FAILURE, 0x2f, 0, \
+ "No locks available" )
+
+/** Link has been severed */
+#define ENOLINK __einfo_error ( EINFO_ENOLINK )
+#define EINFO_ENOLINK __einfo ( PXENV_STATUS_FAILURE, 0x30, 0, \
+ "Link has been severed" )
+
+/** Not enough space */
+#define ENOMEM __einfo_error ( EINFO_ENOMEM )
+#define EINFO_ENOMEM __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x31, 0, \
+ "Not enough space" )
+
+/** No message of the desired type */
+#define ENOMSG __einfo_error ( EINFO_ENOMSG )
+#define EINFO_ENOMSG __einfo ( PXENV_STATUS_FAILURE, 0x32, 0, \
+ "No message of the desired type" )
+
+/** Protocol not available */
+#define ENOPROTOOPT __einfo_error ( EINFO_ENOPROTOOPT )
+#define EINFO_ENOPROTOOPT __einfo ( PXENV_STATUS_UNSUPPORTED, 0x33, 0, \
+ "Protocol not available" )
+
+/** No space left on device */
+#define ENOSPC __einfo_error ( EINFO_ENOSPC )
+#define EINFO_ENOSPC __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x34, 0, \
+ "No space left on device" )
+
+/** No STREAM resources */
+#define ENOSR __einfo_error ( EINFO_ENOSR )
+#define EINFO_ENOSR __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x35, 0, \
+ "No STREAM resources" )
+
+/** Not a STREAM */
+#define ENOSTR __einfo_error ( EINFO_ENOSTR )
+#define EINFO_ENOSTR __einfo ( PXENV_STATUS_FAILURE, 0x36, 0, \
+ "Not a STREAM" )
+
+/** Function not implemented */
+#define ENOSYS __einfo_error ( EINFO_ENOSYS )
+#define EINFO_ENOSYS __einfo ( PXENV_STATUS_UNSUPPORTED, 0x37, 0, \
+ "Function not implemented" )
+
+/** The socket is not connected */
+#define ENOTCONN __einfo_error ( EINFO_ENOTCONN )
+#define EINFO_ENOTCONN __einfo ( PXENV_STATUS_FAILURE, 0x38, 0, \
+ "The socket is not connected" )
+
+/** Not a directory */
+#define ENOTDIR __einfo_error ( EINFO_ENOTDIR )
+#define EINFO_ENOTDIR __einfo ( PXENV_STATUS_FAILURE, 0x39, 0, \
+ "Not a directory" )
+
+/** Directory not empty */
+#define ENOTEMPTY __einfo_error ( EINFO_ENOTEMPTY )
+#define EINFO_ENOTEMPTY __einfo ( PXENV_STATUS_FAILURE, 0x3a, 0, \
+ "Directory not empty" )
+
+/** Not a socket */
+#define ENOTSOCK __einfo_error ( EINFO_ENOTSOCK )
+#define EINFO_ENOTSOCK __einfo ( PXENV_STATUS_FAILURE, 0x3b, 0, \
+ "Not a socket" )
+
+/** Operation not supported */
+#define ENOTSUP __einfo_error ( EINFO_ENOTSUP )
+#define EINFO_ENOTSUP __einfo ( PXENV_STATUS_UNSUPPORTED, 0x3c, 0, \
+ "Operation not supported" )
+
+/** Inappropriate I/O control operation */
+#define ENOTTY __einfo_error ( EINFO_ENOTTY )
+#define EINFO_ENOTTY __einfo ( PXENV_STATUS_FAILURE, 0x3d, 0, \
+ "Inappropriate I/O control operation" )
+
+/** No such device or address */
+#define ENXIO __einfo_error ( EINFO_ENXIO )
+#define EINFO_ENXIO __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x3e, 0, \
+ "No such device or address" )
+
+/** Operation not supported on socket */
+#define EOPNOTSUPP __einfo_error ( EINFO_EOPNOTSUPP )
+#define EINFO_EOPNOTSUPP __einfo ( PXENV_STATUS_UNSUPPORTED, 0x3f, 0, \
+ "Operation not supported on socket" )
+
+/** Value too large to be stored in data type */
+#define EOVERFLOW __einfo_error ( EINFO_EOVERFLOW )
+#define EINFO_EOVERFLOW __einfo ( PXENV_STATUS_FAILURE, 0x40, 0, \
+ "Value too large to be stored in data type" )
+
+/** Operation not permitted */
+#define EPERM __einfo_error ( EINFO_EPERM )
+#define EINFO_EPERM __einfo ( PXENV_STATUS_TFTP_ACCESS_VIOLATION, 0x41, 0, \
+ "Operation not permitted" )
+
+/** Broken pipe */
+#define EPIPE __einfo_error ( EINFO_EPIPE )
+#define EINFO_EPIPE __einfo ( PXENV_STATUS_FAILURE, 0x42, 0, \
+ "Broken pipe" )
+
+/** Protocol error */
+#define EPROTO __einfo_error ( EINFO_EPROTO )
+#define EINFO_EPROTO __einfo ( PXENV_STATUS_FAILURE, 0x43, 0, \
+ "Protocol error" )
+
+/** Protocol not supported */
+#define EPROTONOSUPPORT __einfo_error ( EINFO_EPROTONOSUPPORT )
+#define EINFO_EPROTONOSUPPORT __einfo ( PXENV_STATUS_UNSUPPORTED, 0x44, 0, \
+ "Protocol not supported" )
+
+/** Protocol wrong type for socket */
+#define EPROTOTYPE __einfo_error ( EINFO_EPROTOTYPE )
+#define EINFO_EPROTOTYPE __einfo ( PXENV_STATUS_FAILURE, 0x45, 0, \
+ "Protocol wrong type for socket" )
+
+/** Result too large */
+#define ERANGE __einfo_error ( EINFO_ERANGE )
+#define EINFO_ERANGE __einfo ( PXENV_STATUS_FAILURE, 0x46, 0, \
+ "Result too large" )
+
+/** Read-only file system */
+#define EROFS __einfo_error ( EINFO_EROFS )
+#define EINFO_EROFS __einfo ( PXENV_STATUS_FAILURE, 0x47, 0, \
+ "Read-only file system" )
+
+/** Invalid seek */
+#define ESPIPE __einfo_error ( EINFO_ESPIPE )
+#define EINFO_ESPIPE __einfo ( PXENV_STATUS_FAILURE, 0x48, 0, \
+ "Invalid seek" )
+
+/** No such process */
+#define ESRCH __einfo_error ( EINFO_ESRCH )
+#define EINFO_ESRCH __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x49, 0, \
+ "No such process" )
+
+/** Stale file handle */
+#define ESTALE __einfo_error ( EINFO_ESTALE )
+#define EINFO_ESTALE __einfo ( PXENV_STATUS_FAILURE, 0x4a, 0, \
+ "Stale file handle" )
+
+/** Timer expired */
+#define ETIME __einfo_error ( EINFO_ETIME )
+#define EINFO_ETIME __einfo ( PXENV_STATUS_FAILURE, 0x4b, 0, \
+ "Timer expired" )
+
+/** Connection timed out */
+#define ETIMEDOUT __einfo_error ( EINFO_ETIMEDOUT )
+#define EINFO_ETIMEDOUT __einfo ( PXENV_STATUS_TFTP_READ_TIMEOUT, 0x4c, 0, \
+ "Connection timed out" )
+
+/** Text file busy */
+#define ETXTBSY __einfo_error ( EINFO_ETXTBSY )
+#define EINFO_ETXTBSY __einfo ( PXENV_STATUS_FAILURE, 0x4d, 0, \
+ "Text file busy" )
+
+/** Operation would block */
+#define EWOULDBLOCK __einfo_error ( EINFO_EWOULDBLOCK )
+#define EINFO_EWOULDBLOCK __einfo ( PXENV_STATUS_TFTP_OPEN, 0x4e, 0, \
+ "Operation would block" )
+
+/** Improper link */
+#define EXDEV __einfo_error ( EINFO_EXDEV )
+#define EINFO_EXDEV __einfo ( PXENV_STATUS_FAILURE, 0x4f, 0, \
+ "Improper link" )
+
+/** @} */
+
+extern int errno;
+
+#endif /* ERRNO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/etherboot.h b/src/VBox/Devices/PC/ipxe/src/include/etherboot.h
new file mode 100644
index 00000000..ba79cb16
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/etherboot.h
@@ -0,0 +1,43 @@
+#ifndef ETHERBOOT_H
+#define ETHERBOOT_H
+
+/*
+ * Standard includes that we always want
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <strings.h>
+#include <ipxe/timer.h>
+#include <ipxe/if_arp.h>
+#include <ipxe/if_ether.h>
+
+typedef unsigned long Address;
+
+/*
+ * IMPORTANT!!!!!!!!!!!!!!
+ *
+ * Everything below this point is cruft left over from older versions
+ * of Etherboot. Do not add *anything* below this point. Things are
+ * gradually being moved to individual header files.
+ *
+ */
+
+/* Link configuration time in tenths of a second */
+#ifndef VALID_LINK_TIMEOUT
+#define VALID_LINK_TIMEOUT 100 /* 10.0 seconds */
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
+#endif /* ETHERBOOT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/fs.h b/src/VBox/Devices/PC/ipxe/src/include/fs.h
new file mode 100644
index 00000000..1dfe8fd9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/fs.h
@@ -0,0 +1,41 @@
+#ifndef FS_H
+#define FS_H
+
+#include <stdint.h>
+
+//typedef uint64_t sector_t;
+
+#ifdef IDE_DISK
+int ide_probe(int drive);
+int ide_read(int drive, sector_t sector, void *buffer);
+#endif
+
+#ifdef USB_DISK
+int usb_probe(int drive);
+int usb_read(int drive, sector_t sector, void *buffer);
+#endif
+
+#define DISK_IDE 1
+#define DISK_MEM 2
+#define DISK_USB 3
+
+int devopen(const char *name, int *reopen);
+int devread(unsigned long sector, unsigned long byte_offset,
+ unsigned long byte_len, void *buf);
+
+int file_open(const char *filename);
+int file_read(void *buf, unsigned long len);
+int file_seek(unsigned long offset);
+unsigned long file_size(void);
+
+#define PARTITION_UNKNOWN 0xbad6a7
+
+#ifdef ELTORITO
+int open_eltorito_image(int part, unsigned long *start, unsigned long *length);
+#else
+# define open_eltorito_image(x,y,z) PARTITION_UNKNOWN
+#endif
+
+extern int using_devsize;
+
+#endif /* FS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/getopt.h b/src/VBox/Devices/PC/ipxe/src/include/getopt.h
new file mode 100644
index 00000000..0fe43567
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/getopt.h
@@ -0,0 +1,94 @@
+#ifndef _GETOPT_H
+#define _GETOPT_H
+
+/** @file
+ *
+ * Parse command-line options
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+
+enum getopt_argument_requirement {
+ /** Option does not take an argument */
+ no_argument = 0,
+ /** Option requires an argument */
+ required_argument = 1,
+ /** Option may have an argument */
+ optional_argument = 2,
+};
+
+/** A long option, as used for getopt_long() */
+struct option {
+ /** Long name of this option */
+ const char *name;
+ /** Option takes an argument
+ *
+ * Must be one of @c no_argument, @c required_argument, or @c
+ * optional_argument.
+ */
+ int has_arg;
+ /** Location into which to store @c val, or NULL.
+ *
+ * See the description for @c val for more details.
+ */
+ int *flag;
+ /** Value to return
+ *
+ * If @c flag is NULL, then this is the value that will be
+ * returned by getopt_long() when this option is found, and
+ * should therefore be set to the equivalent short option
+ * character.
+ *
+ * If @c flag is non-NULL, then this value will be written to
+ * the location pointed to by @flag, and getopt_long() will
+ * return 0.
+ */
+ int val;
+};
+
+extern char *optarg;
+extern int optind;
+extern int nextchar;
+extern int optopt;
+
+extern int getopt_long ( int argc, char * const argv[], const char *optstring,
+ const struct option *longopts, int *longindex );
+
+/**
+ * Parse command-line options
+ *
+ * @v argv Argument count
+ * @v argv Argument list
+ * @v optstring Option specification string
+ * @ret option Option found, or -1 for no more options
+ *
+ * See getopt_long() for full details.
+ */
+static inline int getopt ( int argc, char * const argv[],
+ const char *optstring ) {
+ static const struct option no_options[] = {
+ { NULL, 0, NULL, 0 }
+ };
+ return getopt_long ( argc, argv, optstring, no_options, NULL );
+}
+
+/**
+ * Reset getopt() internal state
+ *
+ * Due to a limitation of the POSIX getopt() API, it is necessary to
+ * add a call to reset_getopt() before each set of calls to getopt()
+ * or getopt_long(). This arises because POSIX assumes that each
+ * process will parse command line arguments no more than once; this
+ * assumption is not valid within Etherboot. We work around the
+ * limitation by arranging for execv() to call reset_getopt() before
+ * executing the command.
+ */
+static inline void reset_getopt ( void ) {
+ optind = 1;
+ nextchar = 0;
+}
+
+#endif /* _GETOPT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/hci/ifmgmt_cmd.h b/src/VBox/Devices/PC/ipxe/src/include/hci/ifmgmt_cmd.h
new file mode 100644
index 00000000..a7751cb2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/hci/ifmgmt_cmd.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _IFMGMT_CMD_H
+#define _IFMGMT_CMD_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/parseopt.h>
+
+struct net_device;
+
+struct ifcommon_options {};
+
+extern struct option_descriptor ifcommon_opts[0];
+
+extern int ifcommon_exec ( int argc, char **argv,
+ struct command_descriptor *cmd,
+ int ( * payload ) ( struct net_device * ),
+ int stop_on_first_success );
+
+#endif /* _IFMGMT_CMD_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/hci/linux_args.h b/src/VBox/Devices/PC/ipxe/src/include/hci/linux_args.h
new file mode 100644
index 00000000..ae1ed052
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/hci/linux_args.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _HCI_LINUX_ARGS_H
+#define _HCI_LINUX_ARGS_H
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+/**
+ * Save argc and argv for later access.
+ *
+ * To be called by linuxprefix
+ */
+extern __asmcall void save_args(int argc, char **argv);
+
+#endif /* _HCI_LINUX_ARGS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/i82365.h b/src/VBox/Devices/PC/ipxe/src/include/i82365.h
new file mode 100644
index 00000000..a6f2b17b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/i82365.h
@@ -0,0 +1,452 @@
+/*
+ * i82365.h 1.15 1999/10/25 20:03:34
+ *
+ * The contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL").
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#ifndef _LINUX_I82365_H
+#define _LINUX_I82365_H
+
+/* register definitions for the Intel 82365SL PCMCIA controller */
+
+/* Offsets for PCIC registers */
+#define I365_IDENT 0x00 /* Identification and revision */
+#define I365_STATUS 0x01 /* Interface status */
+#define I365_POWER 0x02 /* Power and RESETDRV control */
+#define I365_INTCTL 0x03 /* Interrupt and general control */
+#define I365_CSC 0x04 /* Card status change */
+#define I365_CSCINT 0x05 /* Card status change interrupt control */
+#define I365_ADDRWIN 0x06 /* Address window enable */
+#define I365_IOCTL 0x07 /* I/O control */
+#define I365_GENCTL 0x16 /* Card detect and general control */
+#define I365_GBLCTL 0x1E /* Global control register */
+
+/* Offsets for I/O and memory window registers */
+#define I365_IO(map) (0x08+((map)<<2))
+#define I365_MEM(map) (0x10+((map)<<3))
+#define I365_W_START 0
+#define I365_W_STOP 2
+#define I365_W_OFF 4
+
+/* Flags for I365_STATUS */
+#define I365_CS_BVD1 0x01
+#define I365_CS_STSCHG 0x01
+#define I365_CS_BVD2 0x02
+#define I365_CS_SPKR 0x02
+#define I365_CS_DETECT 0x0C
+#define I365_CS_WRPROT 0x10
+#define I365_CS_READY 0x20 /* Inverted */
+#define I365_CS_POWERON 0x40
+#define I365_CS_GPI 0x80
+
+/* Flags for I365_POWER */
+#define I365_PWR_OFF 0x00 /* Turn off the socket */
+#define I365_PWR_OUT 0x80 /* Output enable */
+#define I365_PWR_NORESET 0x40 /* Disable RESETDRV on resume */
+#define I365_PWR_AUTO 0x20 /* Auto pwr switch enable */
+#define I365_VCC_MASK 0x18 /* Mask for turning off Vcc */
+/* There are different layouts for B-step and DF-step chips: the B
+ step has independent Vpp1/Vpp2 control, and the DF step has only
+ Vpp1 control, plus 3V control */
+#define I365_VCC_5V 0x10 /* Vcc = 5.0v */
+#define I365_VCC_3V 0x18 /* Vcc = 3.3v */
+#define I365_VPP2_MASK 0x0c /* Mask for turning off Vpp2 */
+#define I365_VPP2_5V 0x04 /* Vpp2 = 5.0v */
+#define I365_VPP2_12V 0x08 /* Vpp2 = 12.0v */
+#define I365_VPP1_MASK 0x03 /* Mask for turning off Vpp1 */
+#define I365_VPP1_5V 0x01 /* Vpp2 = 5.0v */
+#define I365_VPP1_12V 0x02 /* Vpp2 = 12.0v */
+
+/* Flags for I365_INTCTL */
+#define I365_RING_ENA 0x80
+#define I365_PC_RESET 0x40
+#define I365_PC_IOCARD 0x20
+#define I365_INTR_ENA 0x10
+#define I365_IRQ_MASK 0x0F
+
+/* Flags for I365_CSC and I365_CSCINT*/
+#define I365_CSC_BVD1 0x01
+#define I365_CSC_STSCHG 0x01
+#define I365_CSC_BVD2 0x02
+#define I365_CSC_READY 0x04
+#define I365_CSC_DETECT 0x08
+#define I365_CSC_ANY 0x0F
+#define I365_CSC_GPI 0x10
+
+/* Flags for I365_ADDRWIN */
+#define I365_ENA_IO(map) (0x40 << (map))
+#define I365_ENA_MEM(map) (0x01 << (map))
+
+/* Flags for I365_IOCTL */
+#define I365_IOCTL_MASK(map) (0x0F << (map<<2))
+#define I365_IOCTL_WAIT(map) (0x08 << (map<<2))
+#define I365_IOCTL_0WS(map) (0x04 << (map<<2))
+#define I365_IOCTL_IOCS16(map) (0x02 << (map<<2))
+#define I365_IOCTL_16BIT(map) (0x01 << (map<<2))
+
+/* Flags for I365_GENCTL */
+#define I365_CTL_16DELAY 0x01
+#define I365_CTL_RESET 0x02
+#define I365_CTL_GPI_ENA 0x04
+#define I365_CTL_GPI_CTL 0x08
+#define I365_CTL_RESUME 0x10
+#define I365_CTL_SW_IRQ 0x20
+
+/* Flags for I365_GBLCTL */
+#define I365_GBL_PWRDOWN 0x01
+#define I365_GBL_CSC_LEV 0x02
+#define I365_GBL_WRBACK 0x04
+#define I365_GBL_IRQ_0_LEV 0x08
+#define I365_GBL_IRQ_1_LEV 0x10
+
+/* Flags for memory window registers */
+#define I365_MEM_16BIT 0x8000 /* In memory start high byte */
+#define I365_MEM_0WS 0x4000
+#define I365_MEM_WS1 0x8000 /* In memory stop high byte */
+#define I365_MEM_WS0 0x4000
+#define I365_MEM_WRPROT 0x8000 /* In offset high byte */
+#define I365_MEM_REG 0x4000
+
+#define I365_REG(slot, reg) (((slot) << 6) + reg)
+
+#endif /* _LINUX_I82365_H */
+
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+// Beginning vg468.h (for VADEM chipset)
+
+#ifndef _LINUX_VG468_H
+#define _LINUX_VG468_H
+
+/* Special bit in I365_IDENT used for Vadem chip detection */
+#define I365_IDENT_VADEM 0x08
+
+/* Special definitions in I365_POWER */
+#define VG468_VPP2_MASK 0x0c
+#define VG468_VPP2_5V 0x04
+#define VG468_VPP2_12V 0x08
+
+/* Unique Vadem registers */
+#define VG469_VSENSE 0x1f /* Card voltage sense */
+#define VG469_VSELECT 0x2f /* Card voltage select */
+#define VG468_CTL 0x38 /* Control register */
+#define VG468_TIMER 0x39 /* Timer control */
+#define VG468_MISC 0x3a /* Miscellaneous */
+#define VG468_GPIO_CFG 0x3b /* GPIO configuration */
+#define VG469_EXT_MODE 0x3c /* Extended mode register */
+#define VG468_SELECT 0x3d /* Programmable chip select */
+#define VG468_SELECT_CFG 0x3e /* Chip select configuration */
+#define VG468_ATA 0x3f /* ATA control */
+
+/* Flags for VG469_VSENSE */
+#define VG469_VSENSE_A_VS1 0x01
+#define VG469_VSENSE_A_VS2 0x02
+#define VG469_VSENSE_B_VS1 0x04
+#define VG469_VSENSE_B_VS2 0x08
+
+/* Flags for VG469_VSELECT */
+#define VG469_VSEL_VCC 0x03
+#define VG469_VSEL_5V 0x00
+#define VG469_VSEL_3V 0x03
+#define VG469_VSEL_MAX 0x0c
+#define VG469_VSEL_EXT_STAT 0x10
+#define VG469_VSEL_EXT_BUS 0x20
+#define VG469_VSEL_MIXED 0x40
+#define VG469_VSEL_ISA 0x80
+
+/* Flags for VG468_CTL */
+#define VG468_CTL_SLOW 0x01 /* 600ns memory timing */
+#define VG468_CTL_ASYNC 0x02 /* Asynchronous bus clocking */
+#define VG468_CTL_TSSI 0x08 /* Tri-state some outputs */
+#define VG468_CTL_DELAY 0x10 /* Card detect debounce */
+#define VG468_CTL_INPACK 0x20 /* Obey INPACK signal? */
+#define VG468_CTL_POLARITY 0x40 /* VCCEN polarity */
+#define VG468_CTL_COMPAT 0x80 /* Compatibility stuff */
+
+#define VG469_CTL_WS_COMPAT 0x04 /* Wait state compatibility */
+#define VG469_CTL_STRETCH 0x10 /* LED stretch */
+
+/* Flags for VG468_TIMER */
+#define VG468_TIMER_ZEROPWR 0x10 /* Zero power control */
+#define VG468_TIMER_SIGEN 0x20 /* Power up */
+#define VG468_TIMER_STATUS 0x40 /* Activity timer status */
+#define VG468_TIMER_RES 0x80 /* Timer resolution */
+#define VG468_TIMER_MASK 0x0f /* Activity timer timeout */
+
+/* Flags for VG468_MISC */
+#define VG468_MISC_GPIO 0x04 /* General-purpose IO */
+#define VG468_MISC_DMAWSB 0x08 /* DMA wait state control */
+#define VG469_MISC_LEDENA 0x10 /* LED enable */
+#define VG468_MISC_VADEMREV 0x40 /* Vadem revision control */
+#define VG468_MISC_UNLOCK 0x80 /* Unique register lock */
+
+/* Flags for VG469_EXT_MODE_A */
+#define VG469_MODE_VPPST 0x03 /* Vpp steering control */
+#define VG469_MODE_INT_SENSE 0x04 /* Internal voltage sense */
+#define VG469_MODE_CABLE 0x08
+#define VG469_MODE_COMPAT 0x10 /* i82365sl B or DF step */
+#define VG469_MODE_TEST 0x20
+#define VG469_MODE_RIO 0x40 /* Steer RIO to INTR? */
+
+/* Flags for VG469_EXT_MODE_B */
+#define VG469_MODE_B_3V 0x01 /* 3.3v for socket B */
+
+#endif /* _LINUX_VG468_H */
+
+
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+// Beginning ricoh.h (RICOH chipsets)
+
+#ifndef _LINUX_RICOH_H
+#define _LINUX_RICOH_H
+
+
+#define RF5C_MODE_CTL 0x1f /* Mode control */
+#define RF5C_PWR_CTL 0x2f /* Mixed voltage control */
+#define RF5C_CHIP_ID 0x3a /* Chip identification */
+#define RF5C_MODE_CTL_3 0x3b /* Mode control 3 */
+
+/* I/O window address offset */
+#define RF5C_IO_OFF(w) (0x36+((w)<<1))
+
+/* Flags for RF5C_MODE_CTL */
+#define RF5C_MODE_ATA 0x01 /* ATA mode */
+#define RF5C_MODE_LED_ENA 0x02 /* IRQ 12 is LED */
+#define RF5C_MODE_CA21 0x04
+#define RF5C_MODE_CA22 0x08
+#define RF5C_MODE_CA23 0x10
+#define RF5C_MODE_CA24 0x20
+#define RF5C_MODE_CA25 0x40
+#define RF5C_MODE_3STATE_BIT7 0x80
+
+/* Flags for RF5C_PWR_CTL */
+#define RF5C_PWR_VCC_3V 0x01
+#define RF5C_PWR_IREQ_HIGH 0x02
+#define RF5C_PWR_INPACK_ENA 0x04
+#define RF5C_PWR_5V_DET 0x08
+#define RF5C_PWR_TC_SEL 0x10 /* Terminal Count: irq 11 or 15 */
+#define RF5C_PWR_DREQ_LOW 0x20
+#define RF5C_PWR_DREQ_OFF 0x00 /* DREQ steering control */
+#define RF5C_PWR_DREQ_INPACK 0x40
+#define RF5C_PWR_DREQ_SPKR 0x80
+#define RF5C_PWR_DREQ_IOIS16 0xc0
+
+/* Values for RF5C_CHIP_ID */
+#define RF5C_CHIP_RF5C296 0x32
+#define RF5C_CHIP_RF5C396 0xb2
+
+/* Flags for RF5C_MODE_CTL_3 */
+#define RF5C_MCTL3_DISABLE 0x01 /* Disable PCMCIA interface */
+#define RF5C_MCTL3_DMA_ENA 0x02
+
+/* Register definitions for Ricoh PCI-to-CardBus bridges */
+
+/* Extra bits in CB_BRIDGE_CONTROL */
+#define RL5C46X_BCR_3E0_ENA 0x0800
+#define RL5C46X_BCR_3E2_ENA 0x1000
+
+/* Bridge Configuration Register */
+#define RL5C4XX_CONFIG 0x80 /* 16 bit */
+#define RL5C4XX_CONFIG_IO_1_MODE 0x0200
+#define RL5C4XX_CONFIG_IO_0_MODE 0x0100
+#define RL5C4XX_CONFIG_PREFETCH 0x0001
+
+
+/* Misc Control Register */
+#define RL5C4XX_MISC 0x0082 /* 16 bit */
+#define RL5C4XX_MISC_HW_SUSPEND_ENA 0x0002
+#define RL5C4XX_MISC_VCCEN_POL 0x0100
+#define RL5C4XX_MISC_VPPEN_POL 0x0200
+#define RL5C46X_MISC_SUSPEND 0x0001
+#define RL5C46X_MISC_PWR_SAVE_2 0x0004
+#define RL5C46X_MISC_IFACE_BUSY 0x0008
+#define RL5C46X_MISC_B_LOCK 0x0010
+#define RL5C46X_MISC_A_LOCK 0x0020
+#define RL5C46X_MISC_PCI_LOCK 0x0040
+#define RL5C47X_MISC_IFACE_BUSY 0x0004
+#define RL5C47X_MISC_PCI_INT_MASK 0x0018
+#define RL5C47X_MISC_PCI_INT_DIS 0x0020
+#define RL5C47X_MISC_SUBSYS_WR 0x0040
+#define RL5C47X_MISC_SRIRQ_ENA 0x0080
+#define RL5C47X_MISC_5V_DISABLE 0x0400
+#define RL5C47X_MISC_LED_POL 0x0800
+
+/* 16-bit Interface Control Register */
+#define RL5C4XX_16BIT_CTL 0x0084 /* 16 bit */
+#define RL5C4XX_16CTL_IO_TIMING 0x0100
+#define RL5C4XX_16CTL_MEM_TIMING 0x0200
+#define RL5C46X_16CTL_LEVEL_1 0x0010
+#define RL5C46X_16CTL_LEVEL_2 0x0020
+
+/* 16-bit IO and memory timing registers */
+#define RL5C4XX_16BIT_IO_0 0x0088 /* 16 bit */
+#define RL5C4XX_16BIT_MEM_0 0x0088 /* 16 bit */
+#define RL5C4XX_SETUP_MASK 0x0007
+#define RL5C4XX_SETUP_SHIFT 0
+#define RL5C4XX_CMD_MASK 0x01f0
+#define RL5C4XX_CMD_SHIFT 4
+#define RL5C4XX_HOLD_MASK 0x1c00
+#define RL5C4XX_HOLD_SHIFT 10
+#define RL5C4XX_MISC_CONTROL 0x2F /* 8 bit */
+#define RL5C4XX_ZV_ENABLE 0x08
+
+#endif /* _LINUX_RICOH_H */
+
+
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+// Beginning cirrus.h (CIRRUS chipsets)
+
+#ifndef _LINUX_CIRRUS_H
+#define _LINUX_CIRRUS_H
+
+#ifndef PCI_VENDOR_ID_CIRRUS
+#define PCI_VENDOR_ID_CIRRUS 0x1013
+#endif
+#ifndef PCI_DEVICE_ID_CIRRUS_6729
+#define PCI_DEVICE_ID_CIRRUS_6729 0x1100
+#endif
+#ifndef PCI_DEVICE_ID_CIRRUS_6832
+#define PCI_DEVICE_ID_CIRRUS_6832 0x1110
+#endif
+
+#define PD67_MISC_CTL_1 0x16 /* Misc control 1 */
+#define PD67_FIFO_CTL 0x17 /* FIFO control */
+#define PD67_MISC_CTL_2 0x1E /* Misc control 2 */
+#define PD67_CHIP_INFO 0x1f /* Chip information */
+#define PD67_ATA_CTL 0x026 /* 6730: ATA control */
+#define PD67_EXT_INDEX 0x2e /* Extension index */
+#define PD67_EXT_DATA 0x2f /* Extension data */
+
+/* PD6722 extension registers -- indexed in PD67_EXT_INDEX */
+#define PD67_DATA_MASK0 0x01 /* Data mask 0 */
+#define PD67_DATA_MASK1 0x02 /* Data mask 1 */
+#define PD67_DMA_CTL 0x03 /* DMA control */
+
+/* PD6730 extension registers -- indexed in PD67_EXT_INDEX */
+#define PD67_EXT_CTL_1 0x03 /* Extension control 1 */
+#define PD67_MEM_PAGE(n) ((n)+5) /* PCI window bits 31:24 */
+#define PD67_EXTERN_DATA 0x0a
+#define PD67_MISC_CTL_3 0x25
+#define PD67_SMB_PWR_CTL 0x26
+
+/* I/O window address offset */
+#define PD67_IO_OFF(w) (0x36+((w)<<1))
+
+/* Timing register sets */
+#define PD67_TIME_SETUP(n) (0x3a + 3*(n))
+#define PD67_TIME_CMD(n) (0x3b + 3*(n))
+#define PD67_TIME_RECOV(n) (0x3c + 3*(n))
+
+/* Flags for PD67_MISC_CTL_1 */
+#define PD67_MC1_5V_DET 0x01 /* 5v detect */
+#define PD67_MC1_MEDIA_ENA 0x01 /* 6730: Multimedia enable */
+#define PD67_MC1_VCC_3V 0x02 /* 3.3v Vcc */
+#define PD67_MC1_PULSE_MGMT 0x04
+#define PD67_MC1_PULSE_IRQ 0x08
+#define PD67_MC1_SPKR_ENA 0x10
+#define PD67_MC1_INPACK_ENA 0x80
+
+/* Flags for PD67_FIFO_CTL */
+#define PD67_FIFO_EMPTY 0x80
+
+/* Flags for PD67_MISC_CTL_2 */
+#define PD67_MC2_FREQ_BYPASS 0x01
+#define PD67_MC2_DYNAMIC_MODE 0x02
+#define PD67_MC2_SUSPEND 0x04
+#define PD67_MC2_5V_CORE 0x08
+#define PD67_MC2_LED_ENA 0x10 /* IRQ 12 is LED enable */
+#define PD67_MC2_FAST_PCI 0x10 /* 6729: PCI bus > 25 MHz */
+#define PD67_MC2_3STATE_BIT7 0x20 /* Floppy change bit */
+#define PD67_MC2_DMA_MODE 0x40
+#define PD67_MC2_IRQ15_RI 0x80 /* IRQ 15 is ring enable */
+
+/* Flags for PD67_CHIP_INFO */
+#define PD67_INFO_SLOTS 0x20 /* 0 = 1 slot, 1 = 2 slots */
+#define PD67_INFO_CHIP_ID 0xc0
+#define PD67_INFO_REV 0x1c
+
+/* Fields in PD67_TIME_* registers */
+#define PD67_TIME_SCALE 0xc0
+#define PD67_TIME_SCALE_1 0x00
+#define PD67_TIME_SCALE_16 0x40
+#define PD67_TIME_SCALE_256 0x80
+#define PD67_TIME_SCALE_4096 0xc0
+#define PD67_TIME_MULT 0x3f
+
+/* Fields in PD67_DMA_CTL */
+#define PD67_DMA_MODE 0xc0
+#define PD67_DMA_OFF 0x00
+#define PD67_DMA_DREQ_INPACK 0x40
+#define PD67_DMA_DREQ_WP 0x80
+#define PD67_DMA_DREQ_BVD2 0xc0
+#define PD67_DMA_PULLUP 0x20 /* Disable socket pullups? */
+
+/* Fields in PD67_EXT_CTL_1 */
+#define PD67_EC1_VCC_PWR_LOCK 0x01
+#define PD67_EC1_AUTO_PWR_CLEAR 0x02
+#define PD67_EC1_LED_ENA 0x04
+#define PD67_EC1_INV_CARD_IRQ 0x08
+#define PD67_EC1_INV_MGMT_IRQ 0x10
+#define PD67_EC1_PULLUP_CTL 0x20
+
+/* Fields in PD67_MISC_CTL_3 */
+#define PD67_MC3_IRQ_MASK 0x03
+#define PD67_MC3_IRQ_PCPCI 0x00
+#define PD67_MC3_IRQ_EXTERN 0x01
+#define PD67_MC3_IRQ_PCIWAY 0x02
+#define PD67_MC3_IRQ_PCI 0x03
+#define PD67_MC3_PWR_MASK 0x0c
+#define PD67_MC3_PWR_SERIAL 0x00
+#define PD67_MC3_PWR_TI2202 0x08
+#define PD67_MC3_PWR_SMB 0x0c
+
+/* Register definitions for Cirrus PD6832 PCI-to-CardBus bridge */
+
+/* PD6832 extension registers -- indexed in PD67_EXT_INDEX */
+#define PD68_EXT_CTL_2 0x0b
+#define PD68_PCI_SPACE 0x22
+#define PD68_PCCARD_SPACE 0x23
+#define PD68_WINDOW_TYPE 0x24
+#define PD68_EXT_CSC 0x2e
+#define PD68_MISC_CTL_4 0x2f
+#define PD68_MISC_CTL_5 0x30
+#define PD68_MISC_CTL_6 0x31
+
+/* Extra flags in PD67_MISC_CTL_3 */
+#define PD68_MC3_HW_SUSP 0x10
+#define PD68_MC3_MM_EXPAND 0x40
+#define PD68_MC3_MM_ARM 0x80
+
+/* Bridge Control Register */
+#define PD6832_BCR_MGMT_IRQ_ENA 0x0800
+
+/* Socket Number Register */
+#define PD6832_SOCKET_NUMBER 0x004c /* 8 bit */
+
+#endif /* _LINUX_CIRRUS_H */
+
+
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/acpi.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/acpi.h
new file mode 100644
index 00000000..282b6d92
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/acpi.h
@@ -0,0 +1,63 @@
+#ifndef _IPXE_ACPI_H
+#define _IPXE_ACPI_H
+
+/** @file
+ *
+ * ACPI data structures
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/interface.h>
+
+/**
+ * An ACPI description header
+ *
+ * This is the structure common to the start of all ACPI system
+ * description tables.
+ */
+struct acpi_description_header {
+ /** ACPI signature (4 ASCII characters) */
+ uint32_t signature;
+ /** Length of table, in bytes, including header */
+ uint32_t length;
+ /** ACPI Specification minor version number */
+ uint8_t revision;
+ /** To make sum of entire table == 0 */
+ uint8_t checksum;
+ /** OEM identification */
+ char oem_id[6];
+ /** OEM table identification */
+ char oem_table_id[8];
+ /** OEM revision number */
+ uint32_t oem_revision;
+ /** ASL compiler vendor ID */
+ char asl_compiler_id[4];
+ /** ASL compiler revision number */
+ uint32_t asl_compiler_revision;
+} __attribute__ (( packed ));
+
+/**
+ * Build ACPI signature
+ *
+ * @v a First character of ACPI signature
+ * @v b Second character of ACPI signature
+ * @v c Third character of ACPI signature
+ * @v d Fourth character of ACPI signature
+ * @ret signature ACPI signature
+ */
+#define ACPI_SIGNATURE( a, b, c, d ) \
+ ( ( (a) << 0 ) | ( (b) << 8 ) | ( (c) << 16 ) | ( (d) << 24 ) )
+
+extern int acpi_describe ( struct interface *interface,
+ struct acpi_description_header *acpi, size_t len );
+#define acpi_describe_TYPE( object_type ) \
+ typeof ( int ( object_type, \
+ struct acpi_description_header *acpi, \
+ size_t len ) )
+
+extern void acpi_fix_checksum ( struct acpi_description_header *acpi );
+
+#endif /* _IPXE_ACPI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/aes.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/aes.h
new file mode 100644
index 00000000..4e44f985
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/aes.h
@@ -0,0 +1,34 @@
+#ifndef _IPXE_AES_H
+#define _IPXE_AES_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct cipher_algorithm;
+
+/** Basic AES blocksize */
+#define AES_BLOCKSIZE 16
+
+#include "crypto/axtls/crypto.h"
+
+/** AES context */
+struct aes_context {
+ /** AES context for AXTLS */
+ AES_CTX axtls_ctx;
+ /** Cipher is being used for decrypting */
+ int decrypting;
+};
+
+/** AES context size */
+#define AES_CTX_SIZE sizeof ( struct aes_context )
+
+/* AXTLS functions */
+extern void axtls_aes_encrypt ( const AES_CTX *ctx, uint32_t *data );
+extern void axtls_aes_decrypt ( const AES_CTX *ctx, uint32_t *data );
+
+extern struct cipher_algorithm aes_algorithm;
+extern struct cipher_algorithm aes_cbc_algorithm;
+
+int aes_wrap ( const void *kek, const void *src, void *dest, int nblk );
+int aes_unwrap ( const void *kek, const void *src, void *dest, int nblk );
+
+#endif /* _IPXE_AES_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ansiesc.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ansiesc.h
new file mode 100644
index 00000000..c00af258
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ansiesc.h
@@ -0,0 +1,127 @@
+#ifndef _IPXE_ANSIESC_H
+#define _IPXE_ANSIESC_H
+
+/** @file
+ *
+ * ANSI escape sequences
+ *
+ * ANSI X3.64 (aka ECMA-48 or ISO/IEC 6429, available from
+ * http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf)
+ * defines escape sequences consisting of:
+ *
+ * A Control Sequence Introducer (CSI)
+ *
+ * Zero or more Parameter Bytes (P)
+ *
+ * Zero or more Intermediate Bytes (I)
+ *
+ * A Final Byte (F)
+ *
+ * The CSI consists of ESC (0x1b) followed by "[" (0x5b). The
+ * Parameter Bytes, for a standardised (i.e. not private or
+ * experimental) sequence, consist of a list of ASCII decimal integers
+ * separated by semicolons. The Intermediate Bytes (in the range 0x20
+ * to 0x2f) and the Final Byte (in the range 0x40 to 0x4f) determine
+ * the control function.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** A handler for an escape sequence */
+struct ansiesc_handler {
+ /** The control function identifier
+ *
+ * The control function identifier consists of the
+ * Intermediate Bytes (if any) and the Final Byte. In
+ * practice, no more than one immediate byte is ever used, so
+ * the byte combination can be efficiently expressed as a
+ * single integer, in the obvious way (with the Final Byte
+ * being the least significant byte).
+ */
+ unsigned int function;
+ /** Handle escape sequence
+ *
+ * @v count Parameter count
+ * @v params Parameter list
+ *
+ * A negative parameter value indicates that the parameter was
+ * omitted and that the default value for this control
+ * function should be used.
+ *
+ * Since all parameters are optional, there is no way to
+ * distinguish between "zero parameters" and "single parameter
+ * omitted". Consequently, the parameter list will always
+ * contain at least one item.
+ */
+ void ( * handle ) ( unsigned int count, int params[] );
+};
+
+/** Maximum number of parameters within a single escape sequence */
+#define ANSIESC_MAX_PARAMS 4
+
+/**
+ * ANSI escape sequence context
+ *
+ * This provides temporary storage for processing escape sequences,
+ * and points to the list of escape sequence handlers.
+ */
+struct ansiesc_context {
+ /** Array of handlers
+ *
+ * Must be terminated by a handler with @c function set to
+ * zero.
+ */
+ struct ansiesc_handler *handlers;
+ /** Parameter count
+ *
+ * Will be zero when not currently in an escape sequence.
+ */
+ unsigned int count;
+ /** Parameter list */
+ int params[ANSIESC_MAX_PARAMS];
+ /** Control function identifier */
+ unsigned int function;
+};
+
+/** Escape character */
+#define ESC 0x1b
+
+/** Control Sequence Introducer */
+#define CSI "\033["
+
+/**
+ * @defgroup ansifuncs ANSI escape sequence function identifiers
+ * @{
+ */
+
+/** Cursor position */
+#define ANSIESC_CUP 'H'
+
+/** Erase in page */
+#define ANSIESC_ED 'J'
+
+/** Erase from cursor to end of page */
+#define ANSIESC_ED_TO_END 0
+
+/** Erase from start of page to cursor */
+#define ANSIESC_ED_FROM_START 1
+
+/** Erase whole page */
+#define ANSIESC_ED_ALL 2
+
+/** Select graphic rendition */
+#define ANSIESC_SGR 'm'
+
+/** Explicit log message priority
+ *
+ * This is an iPXE private sequence identifier. (The range 'p' to '~'
+ * is reserved for private sequences.)
+ */
+#define ANSIESC_LOG_PRIORITY 'p'
+
+/** @} */
+
+extern int ansiesc_process ( struct ansiesc_context *ctx, int c );
+
+#endif /* _IPXE_ANSIESC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/aoe.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/aoe.h
new file mode 100644
index 00000000..60f3bd95
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/aoe.h
@@ -0,0 +1,131 @@
+#ifndef _IPXE_AOE_H
+#define _IPXE_AOE_H
+
+/** @file
+ *
+ * AoE protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/list.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/retry.h>
+#include <ipxe/ata.h>
+#include <ipxe/acpi.h>
+
+/** An AoE config command */
+struct aoecfg {
+ /** AoE queue depth */
+ uint16_t bufcnt;
+ /** ATA target firmware version */
+ uint16_t fwver;
+ /** ATA target sector count */
+ uint8_t scnt;
+ /** AoE config string subcommand */
+ uint8_t aoeccmd;
+ /** AoE config string length */
+ uint16_t cfglen;
+ /** AoE config string */
+ uint8_t data[0];
+} __attribute__ (( packed ));
+
+/** An AoE ATA command */
+struct aoeata {
+ /** AoE command flags */
+ uint8_t aflags;
+ /** ATA error/feature register */
+ uint8_t err_feat;
+ /** ATA sector count register */
+ uint8_t count;
+ /** ATA command/status register */
+ uint8_t cmd_stat;
+ /** Logical block address, in little-endian order */
+ union {
+ uint64_t u64;
+ uint8_t bytes[6];
+ } lba;
+ /** Data payload */
+ uint8_t data[0];
+} __attribute__ (( packed ));
+
+#define AOE_FL_EXTENDED 0x40 /**< LBA48 extended addressing */
+#define AOE_FL_DEV_HEAD 0x10 /**< Device/head flag */
+#define AOE_FL_ASYNC 0x02 /**< Asynchronous write */
+#define AOE_FL_WRITE 0x01 /**< Write command */
+
+/** An AoE command */
+union aoecmd {
+ /** Config command */
+ struct aoecfg cfg;
+ /** ATA command */
+ struct aoeata ata;
+};
+
+/** An AoE header */
+struct aoehdr {
+ /** Protocol version number and flags */
+ uint8_t ver_flags;
+ /** Error code */
+ uint8_t error;
+ /** Major device number, in network byte order */
+ uint16_t major;
+ /** Minor device number */
+ uint8_t minor;
+ /** Command number */
+ uint8_t command;
+ /** Tag, in network byte order */
+ uint32_t tag;
+ /** Payload */
+ union aoecmd payload[0];
+} __attribute__ (( packed ));
+
+#define AOE_VERSION 0x10 /**< Version 1 */
+#define AOE_VERSION_MASK 0xf0 /**< Version part of ver_flags field */
+
+#define AOE_FL_RESPONSE 0x08 /**< Message is a response */
+#define AOE_FL_ERROR 0x04 /**< Command generated an error */
+
+#define AOE_MAJOR_BROADCAST 0xffff
+#define AOE_MINOR_BROADCAST 0xff
+
+#define AOE_CMD_ATA 0x00 /**< Issue ATA command */
+#define AOE_CMD_CONFIG 0x01 /**< Query Config Information */
+
+#define AOE_ERR_BAD_COMMAND 1 /**< Unrecognised command code */
+#define AOE_ERR_BAD_PARAMETER 2 /**< Bad argument parameter */
+#define AOE_ERR_UNAVAILABLE 3 /**< Device unavailable */
+#define AOE_ERR_CONFIG_EXISTS 4 /**< Config string present */
+#define AOE_ERR_BAD_VERSION 5 /**< Unsupported version */
+
+#define AOE_STATUS_ERR_MASK 0x0f /**< Error portion of status code */
+#define AOE_STATUS_PENDING 0x80 /**< Command pending */
+
+/** AoE tag magic marker */
+#define AOE_TAG_MAGIC 0x18ae0000
+
+/** Maximum number of sectors per packet */
+#define AOE_MAX_COUNT 2
+
+/** AoE boot firmware table signature */
+#define ABFT_SIG ACPI_SIGNATURE ( 'a', 'B', 'F', 'T' )
+
+/**
+ * AoE Boot Firmware Table (aBFT)
+ */
+struct abft_table {
+ /** ACPI header */
+ struct acpi_description_header acpi;
+ /** AoE shelf */
+ uint16_t shelf;
+ /** AoE slot */
+ uint8_t slot;
+ /** Reserved */
+ uint8_t reserved_a;
+ /** MAC address */
+ uint8_t mac[ETH_ALEN];
+} __attribute__ (( packed ));
+
+#endif /* _IPXE_AOE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/api.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/api.h
new file mode 100644
index 00000000..838b8936
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/api.h
@@ -0,0 +1,84 @@
+#ifndef _IPXE_API_H
+#define _IPXE_API_H
+
+/** @file
+ *
+ * iPXE internal APIs
+ *
+ * There are various formally-defined APIs internal to iPXE, with
+ * several differing implementations specific to particular execution
+ * environments (e.g. PC BIOS, EFI, LinuxBIOS).
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @defgroup Single-implementation APIs
+ *
+ * These are APIs for which only a single implementation may be
+ * compiled in at any given time.
+ *
+ * @{
+ */
+
+/**
+ * Calculate function implementation name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ *
+ * The subsystem prefix should be an empty string for the currently
+ * selected subsystem, and should be a subsystem-unique string for all
+ * other subsystems.
+ */
+#define SINGLE_API_NAME( _prefix, _api_func ) _prefix ## _api_func
+
+/**
+ * Calculate static inline function name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ */
+#define SINGLE_API_INLINE( _prefix, _api_func ) \
+ SINGLE_API_NAME ( _prefix, _api_func )
+
+/**
+ * Provide an API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_SINGLE_API( _prefix, _api_func, _func ) \
+ /* Ensure that _api_func exists */ \
+ typeof ( _api_func ) _api_func; \
+ /* Ensure that _func exists */ \
+ typeof ( _func ) _func; \
+ /* Ensure that _func is type-compatible with _api_func */ \
+ typeof ( _api_func ) _func; \
+ /* Ensure that _subsys_func is non-static */ \
+ extern typeof ( _api_func ) SINGLE_API_NAME ( _prefix, _api_func ); \
+ /* Provide symbol alias from _subsys_func to _func */ \
+ typeof ( _api_func ) SINGLE_API_NAME ( _prefix, _api_func ) \
+ __attribute__ (( alias ( #_func ) ));
+
+/**
+ * Provide a static inline API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ */
+#define PROVIDE_SINGLE_API_INLINE( _prefix, _api_func ) \
+ /* Ensure that _api_func exists */ \
+ typeof ( _api_func ) _api_func; \
+ /* Ensure that _subsys_func exists and is static */ \
+ static typeof ( SINGLE_API_INLINE ( _prefix, _api_func ) ) \
+ SINGLE_API_INLINE ( _prefix, _api_func ); \
+ /* Ensure that _subsys_func is type-compatible with _api_func */ \
+ typeof ( _api_func ) SINGLE_API_INLINE ( _prefix, _api_func );
+
+/** @} */
+
+#endif /* _IPXE_API_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/arc4.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/arc4.h
new file mode 100644
index 00000000..9da972b6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/arc4.h
@@ -0,0 +1,22 @@
+#ifndef _IPXE_ARC4_H
+#define _IPXE_ARC4_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct cipher_algorithm;
+
+#include <stdint.h>
+
+struct arc4_ctx {
+ int i, j;
+ u8 state[256];
+};
+
+#define ARC4_CTX_SIZE sizeof ( struct arc4_ctx )
+
+extern struct cipher_algorithm arc4_algorithm;
+
+void arc4_skip ( const void *key, size_t keylen, size_t skip,
+ const void *src, void *dst, size_t msglen );
+
+#endif /* _IPXE_ARC4_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/arp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/arp.h
new file mode 100644
index 00000000..00396d82
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/arp.h
@@ -0,0 +1,42 @@
+#ifndef _IPXE_ARP_H
+#define _IPXE_ARP_H
+
+/** @file
+ *
+ * Address Resolution Protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/tables.h>
+#include <ipxe/netdevice.h>
+
+/** A network-layer protocol that relies upon ARP */
+struct arp_net_protocol {
+ /** Network-layer protocol */
+ struct net_protocol *net_protocol;
+ /** Check existence of address
+ *
+ * @v netdev Network device
+ * @v net_addr Network-layer address
+ * @ret rc Return status code
+ */
+ int ( * check ) ( struct net_device *netdev,
+ const void *net_addr );
+};
+
+/** ARP protocol table */
+#define ARP_NET_PROTOCOLS \
+ __table ( struct arp_net_protocol, "arp_net_protocols" )
+
+/** Declare an ARP protocol */
+#define __arp_net_protocol __table_entry ( ARP_NET_PROTOCOLS, 01 )
+
+extern struct net_protocol arp_protocol __net_protocol;
+
+extern int arp_tx ( struct io_buffer *iobuf, struct net_device *netdev,
+ struct net_protocol *net_protocol, const void *net_dest,
+ const void *net_source, const void *ll_source );
+
+#endif /* _IPXE_ARP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/asn1.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/asn1.h
new file mode 100644
index 00000000..3e73b59c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/asn1.h
@@ -0,0 +1,303 @@
+#ifndef _IPXE_ASN1_H
+#define _IPXE_ASN1_H
+
+/** @file
+ *
+ * ASN.1 encoding
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <time.h>
+#include <ipxe/tables.h>
+
+/** An ASN.1 object cursor */
+struct asn1_cursor {
+ /** Start of data */
+ const void *data;
+ /** Length of data */
+ size_t len;
+};
+
+/** An ASN.1 object builder */
+struct asn1_builder {
+ /** Data
+ *
+ * This is always dynamically allocated. If @c data is NULL
+ * while @len is non-zero, this indicates that a memory
+ * allocation error has occurred during the building process.
+ */
+ void *data;
+ /** Length of data */
+ size_t len;
+};
+
+/** Maximum (viable) length of ASN.1 length
+ *
+ * While in theory unlimited, this length is sufficient to contain a
+ * size_t.
+ */
+#define ASN1_MAX_LEN_LEN ( 1 + sizeof ( size_t ) )
+
+/** An ASN.1 header */
+struct asn1_builder_header {
+ /** Type */
+ uint8_t type;
+ /** Length (encoded) */
+ uint8_t length[ASN1_MAX_LEN_LEN];
+} __attribute__ (( packed ));
+
+/** ASN.1 end */
+#define ASN1_END 0x00
+
+/** ASN.1 boolean */
+#define ASN1_BOOLEAN 0x01
+
+/** ASN.1 integer */
+#define ASN1_INTEGER 0x02
+
+/** ASN.1 bit string */
+#define ASN1_BIT_STRING 0x03
+
+/** ASN.1 octet string */
+#define ASN1_OCTET_STRING 0x04
+
+/** ASN.1 null */
+#define ASN1_NULL 0x05
+
+/** ASN.1 object identifier */
+#define ASN1_OID 0x06
+
+/** ASN.1 enumeration */
+#define ASN1_ENUMERATED 0x0a
+
+/** ASN.1 UTC time */
+#define ASN1_UTC_TIME 0x17
+
+/** ASN.1 generalized time */
+#define ASN1_GENERALIZED_TIME 0x18
+
+/** ASN.1 sequence */
+#define ASN1_SEQUENCE 0x30
+
+/** ASN.1 set */
+#define ASN1_SET 0x31
+
+/** ASN.1 implicit tag */
+#define ASN1_IMPLICIT_TAG( number) ( 0x80 | (number) )
+
+/** ASN.1 explicit tag */
+#define ASN1_EXPLICIT_TAG( number) ( 0xa0 | (number) )
+
+/** ASN.1 "any tag" magic value */
+#define ASN1_ANY -1U
+
+/** Initial OID byte */
+#define ASN1_OID_INITIAL( first, second ) ( ( (first) * 40 ) + (second) )
+
+/** Single-byte OID value
+ *
+ * Valid for values up to 127
+ */
+#define ASN1_OID_SINGLE( value ) ( (value) & 0x7f )
+
+/** Double-byte OID value
+ *
+ * Valid for values up to 16383
+ */
+#define ASN1_OID_DOUBLE( value ) \
+ ( 0x80 | ( ( (value) >> 7 ) & 0x7f ) ), ASN1_OID_SINGLE ( (value) )
+
+/** Double-byte OID value
+ *
+ * Valid for values up to 2097151
+ */
+#define ASN1_OID_TRIPLE( value ) \
+ ( 0x80 | ( ( (value) >> 14 ) & 0x7f ) ), ASN1_OID_DOUBLE ( (value) )
+
+/** ASN.1 OID for rsaEncryption (1.2.840.113549.1.1.1) */
+#define ASN1_OID_RSAENCRYPTION \
+ ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 1 )
+
+/** ASN.1 OID for md5WithRSAEncryption (1.2.840.113549.1.1.4) */
+#define ASN1_OID_MD5WITHRSAENCRYPTION \
+ ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 4 )
+
+/** ASN.1 OID for sha1WithRSAEncryption (1.2.840.113549.1.1.5) */
+#define ASN1_OID_SHA1WITHRSAENCRYPTION \
+ ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 )
+
+/** ASN.1 OID for sha256WithRSAEncryption (1.2.840.113549.1.1.11) */
+#define ASN1_OID_SHA256WITHRSAENCRYPTION \
+ ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 11 )
+
+/** ASN.1 OID for id-md5 (1.2.840.113549.2.5) */
+#define ASN1_OID_MD5 \
+ ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 2 ), \
+ ASN1_OID_SINGLE ( 5 )
+
+/** ASN.1 OID for id-sha1 (1.3.14.3.2.26) */
+#define ASN1_OID_SHA1 \
+ ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 14 ), \
+ ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 2 ), \
+ ASN1_OID_SINGLE ( 26 )
+
+/** ASN.1 OID for id-sha256 (2.16.840.1.101.3.4.2.1) */
+#define ASN1_OID_SHA256 \
+ ASN1_OID_INITIAL ( 2, 16 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 101 ), \
+ ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 4 ), \
+ ASN1_OID_SINGLE ( 2 ), ASN1_OID_SINGLE ( 1 )
+
+/** ASN.1 OID for commonName (2.5.4.3) */
+#define ASN1_OID_COMMON_NAME \
+ ASN1_OID_INITIAL ( 2, 5 ), ASN1_OID_SINGLE ( 4 ), \
+ ASN1_OID_SINGLE ( 3 )
+
+/** ASN.1 OID for id-ce-keyUsage (2.5.29.15) */
+#define ASN1_OID_KEYUSAGE \
+ ASN1_OID_INITIAL ( 2, 5 ), ASN1_OID_SINGLE ( 29 ), \
+ ASN1_OID_SINGLE ( 15 )
+
+/** ASN.1 OID for id-ce-basicConstraints (2.5.29.19) */
+#define ASN1_OID_BASICCONSTRAINTS \
+ ASN1_OID_INITIAL ( 2, 5 ), ASN1_OID_SINGLE ( 29 ), \
+ ASN1_OID_SINGLE ( 19 )
+
+/** ASN.1 OID for id-ce-extKeyUsage (2.5.29.37) */
+#define ASN1_OID_EXTKEYUSAGE \
+ ASN1_OID_INITIAL ( 2, 5 ), ASN1_OID_SINGLE ( 29 ), \
+ ASN1_OID_SINGLE ( 37 )
+
+/** ASN.1 OID for id-kp-codeSigning (1.3.6.1.5.5.7.3.3) */
+#define ASN1_OID_CODESIGNING \
+ ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ), \
+ ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \
+ ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 3 )
+
+/** ASN.1 OID for pkcs-signedData (1.2.840.113549.1.7.2) */
+#define ASN1_OID_SIGNEDDATA \
+ ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \
+ ASN1_OID_SINGLE ( 7 ), ASN1_OID_SINGLE ( 2 )
+
+/** ASN.1 OID for id-pe-authorityInfoAccess (1.3.6.1.5.5.7.1.1) */
+#define ASN1_OID_AUTHORITYINFOACCESS \
+ ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ), \
+ ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 1 )
+
+/** ASN.1 OID for id-ad-ocsp (1.3.6.1.5.5.7.48.1) */
+#define ASN1_OID_OCSP \
+ ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ), \
+ ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \
+ ASN1_OID_SINGLE ( 48 ), ASN1_OID_SINGLE ( 1 )
+
+/** ASN.1 OID for id-pkix-ocsp-basic ( 1.3.6.1.5.5.7.48.1.1) */
+#define ASN1_OID_OCSP_BASIC \
+ ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ), \
+ ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \
+ ASN1_OID_SINGLE ( 48 ), ASN1_OID_SINGLE ( 1 ), \
+ ASN1_OID_SINGLE ( 1 )
+
+/** ASN.1 OID for id-kp-OCSPSigning (1.3.6.1.5.5.7.3.9) */
+#define ASN1_OID_OCSPSIGNING \
+ ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ), \
+ ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \
+ ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 9 )
+
+/** Define an ASN.1 cursor containing an OID */
+#define ASN1_OID_CURSOR( oid_value ) { \
+ .data = oid_value, \
+ .len = sizeof ( oid_value ), \
+ }
+
+/** An ASN.1 OID-identified algorithm */
+struct asn1_algorithm {
+ /** Name */
+ const char *name;
+ /** Object identifier */
+ struct asn1_cursor oid;
+ /** Public-key algorithm (if applicable) */
+ struct pubkey_algorithm *pubkey;
+ /** Digest algorithm (if applicable) */
+ struct digest_algorithm *digest;
+};
+
+/** ASN.1 OID-identified algorithms */
+#define ASN1_ALGORITHMS __table ( struct asn1_algorithm, "asn1_algorithms" )
+
+/** Declare an ASN.1 OID-identified algorithm */
+#define __asn1_algorithm __table_entry ( ASN1_ALGORITHMS, 01 )
+
+/** An ASN.1 bit string */
+struct asn1_bit_string {
+ /** Data */
+ const void *data;
+ /** Length */
+ size_t len;
+ /** Unused bits at end of data */
+ unsigned int unused;
+} __attribute__ (( packed ));
+
+/**
+ * Extract ASN.1 type
+ *
+ * @v cursor ASN.1 object cursor
+ * @ret type Type
+ */
+static inline __attribute__ (( always_inline )) unsigned int
+asn1_type ( const struct asn1_cursor *cursor ) {
+ return ( *( ( const uint8_t * ) cursor->data ) );
+}
+
+extern void asn1_invalidate_cursor ( struct asn1_cursor *cursor );
+extern int asn1_enter ( struct asn1_cursor *cursor, unsigned int type );
+extern int asn1_skip_if_exists ( struct asn1_cursor *cursor,
+ unsigned int type );
+extern int asn1_skip ( struct asn1_cursor *cursor, unsigned int type );
+extern int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type );
+extern int asn1_enter_any ( struct asn1_cursor *cursor );
+extern int asn1_skip_any ( struct asn1_cursor *cursor );
+extern int asn1_shrink_any ( struct asn1_cursor *cursor );
+extern int asn1_boolean ( const struct asn1_cursor *cursor );
+extern int asn1_integer ( const struct asn1_cursor *cursor, int *value );
+extern int asn1_bit_string ( const struct asn1_cursor *cursor,
+ struct asn1_bit_string *bits );
+extern int asn1_integral_bit_string ( const struct asn1_cursor *cursor,
+ struct asn1_bit_string *bits );
+extern int asn1_compare ( const struct asn1_cursor *cursor1,
+ const struct asn1_cursor *cursor2 );
+extern int asn1_algorithm ( const struct asn1_cursor *cursor,
+ struct asn1_algorithm **algorithm );
+extern int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor,
+ struct asn1_algorithm **algorithm );
+extern int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
+ struct asn1_algorithm **algorithm );
+extern int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
+ struct asn1_algorithm **algorithm );
+extern int asn1_generalized_time ( const struct asn1_cursor *cursor,
+ time_t *time );
+extern int asn1_prepend_raw ( struct asn1_builder *builder, const void *data,
+ size_t len );
+extern int asn1_prepend ( struct asn1_builder *builder, unsigned int type,
+ const void *data, size_t len );
+extern int asn1_wrap ( struct asn1_builder *builder, unsigned int type );
+
+#endif /* _IPXE_ASN1_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ata.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ata.h
new file mode 100644
index 00000000..b7f02d65
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ata.h
@@ -0,0 +1,204 @@
+#ifndef _IPXE_ATA_H
+#define _IPXE_ATA_H
+
+#include <stdint.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/interface.h>
+
+/** @file
+ *
+ * ATA devices
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * An ATA Logical Block Address
+ *
+ * ATA controllers have three byte-wide registers for specifying the
+ * block address: LBA Low, LBA Mid and LBA High. This allows for a
+ * 24-bit address. Some devices support the "48-bit address feature
+ * set" (LBA48), in which case each of these byte-wide registers is
+ * actually a two-entry FIFO, and the "previous" byte pushed into the
+ * FIFO is used as the corresponding high-order byte. So, to set up
+ * the 48-bit address 0x123456abcdef, you would issue
+ *
+ * 0x56 -> LBA Low register
+ * 0xef -> LBA Low register
+ * 0x34 -> LBA Mid register
+ * 0xcd -> LBA Mid register
+ * 0x12 -> LBA High register
+ * 0xab -> LBA High register
+ *
+ * This structure encapsulates this information by providing a single
+ * 64-bit integer in native byte order, unioned with bytes named so
+ * that the sequence becomes
+ *
+ * low_prev -> LBA Low register
+ * low_cur -> LBA Low register
+ * mid_prev -> LBA Mid register
+ * mid_cur -> LBA Mid register
+ * high_prev -> LBA High register
+ * high_cur -> LBA High register
+ *
+ * Just to complicate matters further, in non-LBA48 mode it is
+ * possible to have a 28-bit address, in which case bits 27:24 must be
+ * written into the low four bits of the Device register.
+ */
+union ata_lba {
+ /** LBA as a 64-bit integer in native-endian order */
+ uint64_t native;
+ /** ATA registers */
+ struct {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ uint8_t low_cur;
+ uint8_t mid_cur;
+ uint8_t high_cur;
+ uint8_t low_prev;
+ uint8_t mid_prev;
+ uint8_t high_prev;
+ uint16_t pad;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ uint16_t pad;
+ uint8_t high_prev;
+ uint8_t mid_prev;
+ uint8_t low_prev;
+ uint8_t high_cur;
+ uint8_t mid_cur;
+ uint8_t low_cur;
+#else
+#error "I need a byte order"
+#endif
+ } bytes;
+};
+
+/** An ATA 2-byte FIFO register */
+union ata_fifo {
+ /** Value in native-endian order */
+ uint16_t native;
+ /** ATA registers */
+ struct {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ uint8_t cur;
+ uint8_t prev;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ uint8_t prev;
+ uint8_t cur;
+#else
+#error "I need a byte order"
+#endif
+ } bytes;
+};
+
+/** ATA command block */
+struct ata_cb {
+ /** Logical block address */
+ union ata_lba lba;
+ /** Sector count */
+ union ata_fifo count;
+ /** Error/feature register */
+ union ata_fifo err_feat;
+ /** Device register */
+ uint8_t device;
+ /** Command/status register */
+ uint8_t cmd_stat;
+ /** Use LBA48 extended addressing */
+ int lba48;
+};
+
+/** Obsolete bits in the ATA device register */
+#define ATA_DEV_OBSOLETE 0xa0
+
+/** LBA flag in the ATA device register */
+#define ATA_DEV_LBA 0x40
+
+/** Slave ("device 1") flag in the ATA device register */
+#define ATA_DEV_SLAVE 0x10
+
+/** Master ("device 0") flag in the ATA device register */
+#define ATA_DEV_MASTER 0x00
+
+/** Mask of non-LBA portion of device register */
+#define ATA_DEV_MASK 0xf0
+
+/** "Read sectors" command */
+#define ATA_CMD_READ 0x20
+
+/** "Read sectors (ext)" command */
+#define ATA_CMD_READ_EXT 0x24
+
+/** "Write sectors" command */
+#define ATA_CMD_WRITE 0x30
+
+/** "Write sectors (ext)" command */
+#define ATA_CMD_WRITE_EXT 0x34
+
+/** "Identify" command */
+#define ATA_CMD_IDENTIFY 0xec
+
+/** Command completed in error */
+#define ATA_STAT_ERR 0x01
+
+/**
+ * Structure returned by ATA IDENTIFY command
+ *
+ * This is a huge structure with many fields that we don't care about,
+ * so we implement only a few fields.
+ */
+struct ata_identity {
+ uint16_t ignore_a[27]; /* words 0-26 */
+ uint16_t model[20]; /* words 27-46 */
+ uint16_t ignore_b[13]; /* words 47-59 */
+ uint32_t lba_sectors; /* words 60-61 */
+ uint16_t ignore_c[21]; /* words 62-82 */
+ uint16_t supports_lba48; /* word 83 */
+ uint16_t ignore_d[16]; /* words 84-99 */
+ uint64_t lba48_sectors; /* words 100-103 */
+ uint16_t ignore_e[152]; /* words 104-255 */
+};
+
+/** Supports LBA48 flag */
+#define ATA_SUPPORTS_LBA48 ( 1 << 10 )
+
+/** ATA sector size */
+#define ATA_SECTOR_SIZE 512
+
+/** An ATA command information unit */
+struct ata_cmd {
+ /** ATA command block */
+ struct ata_cb cb;
+ /** Data-out buffer (may be NULL)
+ *
+ * If non-NULL, this buffer must be ata_command::cb::count
+ * sectors in size.
+ */
+ userptr_t data_out;
+ /** Data-out buffer length
+ *
+ * Must be zero if @c data_out is NULL
+ */
+ size_t data_out_len;
+ /** Data-in buffer (may be NULL)
+ *
+ * If non-NULL, this buffer must be ata_command::cb::count
+ * sectors in size.
+ */
+ userptr_t data_in;
+ /** Data-in buffer length
+ *
+ * Must be zero if @c data_in is NULL
+ */
+ size_t data_in_len;
+};
+
+extern int ata_command ( struct interface *control, struct interface *data,
+ struct ata_cmd *command );
+#define ata_command_TYPE( object_type ) \
+ typeof ( int ( object_type, struct interface *data, \
+ struct ata_cmd *command ) )
+
+extern int ata_open ( struct interface *block, struct interface *ata,
+ unsigned int device, unsigned int max_count );
+
+#endif /* _IPXE_ATA_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/base16.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/base16.h
new file mode 100644
index 00000000..f0c9842f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/base16.h
@@ -0,0 +1,38 @@
+#ifndef _IPXE_BASE16_H
+#define _IPXE_BASE16_H
+
+/** @file
+ *
+ * Base16 encoding
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+
+/**
+ * Calculate length of base16-encoded data
+ *
+ * @v raw_len Raw data length
+ * @ret encoded_len Encoded string length (excluding NUL)
+ */
+static inline size_t base16_encoded_len ( size_t raw_len ) {
+ return ( 2 * raw_len );
+}
+
+/**
+ * Calculate maximum length of base16-decoded string
+ *
+ * @v encoded Encoded string
+ * @v max_raw_len Maximum length of raw data
+ */
+static inline size_t base16_decoded_max_len ( const char *encoded ) {
+ return ( ( strlen ( encoded ) + 1 ) / 2 );
+}
+
+extern void base16_encode ( const uint8_t *raw, size_t len, char *encoded );
+extern int base16_decode ( const char *encoded, uint8_t *raw );
+
+#endif /* _IPXE_BASE16_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/base64.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/base64.h
new file mode 100644
index 00000000..5fe134dc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/base64.h
@@ -0,0 +1,41 @@
+#ifndef _IPXE_BASE64_H
+#define _IPXE_BASE64_H
+
+/** @file
+ *
+ * Base64 encoding
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+
+/**
+ * Calculate length of base64-encoded data
+ *
+ * @v raw_len Raw data length
+ * @ret encoded_len Encoded string length (excluding NUL)
+ */
+static inline size_t base64_encoded_len ( size_t raw_len ) {
+ return ( ( ( raw_len + 3 - 1 ) / 3 ) * 4 );
+}
+
+/**
+ * Calculate maximum length of base64-decoded string
+ *
+ * @v encoded Encoded string
+ * @v max_raw_len Maximum length of raw data
+ *
+ * Note that the exact length of the raw data cannot be known until
+ * the string is decoded.
+ */
+static inline size_t base64_decoded_max_len ( const char *encoded ) {
+ return ( ( ( strlen ( encoded ) + 4 - 1 ) / 4 ) * 3 );
+}
+
+extern void base64_encode ( const uint8_t *raw, size_t len, char *encoded );
+extern int base64_decode ( const char *encoded, uint8_t *raw );
+
+#endif /* _IPXE_BASE64_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/bigint.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/bigint.h
new file mode 100644
index 00000000..97fbce24
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/bigint.h
@@ -0,0 +1,301 @@
+#ifndef _IPXE_BIGINT_H
+#define _IPXE_BIGINT_H
+
+/** @file
+ *
+ * Big integer support
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Define a big-integer type
+ *
+ * @v size Number of elements
+ * @ret bigint_t Big integer type
+ */
+#define bigint_t( size ) \
+ struct { \
+ bigint_element_t element[ (size) ]; \
+ }
+
+/**
+ * Determine number of elements required for a big-integer type
+ *
+ * @v len Maximum length of big integer, in bytes
+ * @ret size Number of elements
+ */
+#define bigint_required_size( len ) \
+ ( ( (len) + sizeof ( bigint_element_t ) - 1 ) / \
+ sizeof ( bigint_element_t ) )
+
+/**
+ * Determine number of elements in big-integer type
+ *
+ * @v bigint Big integer
+ * @ret size Number of elements
+ */
+#define bigint_size( bigint ) \
+ ( sizeof ( *(bigint) ) / sizeof ( (bigint)->element[0] ) )
+
+/**
+ * Initialise big integer
+ *
+ * @v value Big integer to initialise
+ * @v data Raw data
+ * @v len Length of raw data
+ */
+#define bigint_init( value, data, len ) do { \
+ unsigned int size = bigint_size (value); \
+ assert ( (len) <= ( size * sizeof ( (value)->element[0] ) ) ); \
+ bigint_init_raw ( (value)->element, size, (data), (len) ); \
+ } while ( 0 )
+
+/**
+ * Finalise big integer
+ *
+ * @v value Big integer to finalise
+ * @v out Output buffer
+ * @v len Length of output buffer
+ */
+#define bigint_done( value, out, len ) do { \
+ unsigned int size = bigint_size (value); \
+ bigint_done_raw ( (value)->element, size, (out), (len) ); \
+ } while ( 0 )
+
+/**
+ * Add big integers
+ *
+ * @v addend Big integer to add
+ * @v value Big integer to be added to
+ */
+#define bigint_add( addend, value ) do { \
+ unsigned int size = bigint_size (addend); \
+ bigint_add_raw ( (addend)->element, (value)->element, size ); \
+ } while ( 0 )
+
+/**
+ * Subtract big integers
+ *
+ * @v subtrahend Big integer to subtract
+ * @v value Big integer to be subtracted from
+ */
+#define bigint_subtract( subtrahend, value ) do { \
+ unsigned int size = bigint_size (subtrahend); \
+ bigint_subtract_raw ( (subtrahend)->element, (value)->element, \
+ size ); \
+ } while ( 0 )
+
+/**
+ * Rotate big integer left
+ *
+ * @v value Big integer
+ */
+#define bigint_rol( value ) do { \
+ unsigned int size = bigint_size (value); \
+ bigint_rol_raw ( (value)->element, size ); \
+ } while ( 0 )
+
+/**
+ * Rotate big integer right
+ *
+ * @v value Big integer
+ */
+#define bigint_ror( value ) do { \
+ unsigned int size = bigint_size (value); \
+ bigint_ror_raw ( (value)->element, size ); \
+ } while ( 0 )
+
+/**
+ * Test if big integer is equal to zero
+ *
+ * @v value Big integer
+ * @v size Number of elements
+ * @ret is_zero Big integer is equal to zero
+ */
+#define bigint_is_zero( value ) ( { \
+ unsigned int size = bigint_size (value); \
+ bigint_is_zero_raw ( (value)->element, size ); } )
+
+/**
+ * Compare big integers
+ *
+ * @v value Big integer
+ * @v reference Reference big integer
+ * @ret geq Big integer is greater than or equal to the reference
+ */
+#define bigint_is_geq( value, reference ) ( { \
+ unsigned int size = bigint_size (value); \
+ bigint_is_geq_raw ( (value)->element, (reference)->element, \
+ size ); } )
+
+/**
+ * Test if bit is set in big integer
+ *
+ * @v value Big integer
+ * @v bit Bit to test
+ * @ret is_set Bit is set
+ */
+#define bigint_bit_is_set( value, bit ) ( { \
+ unsigned int size = bigint_size (value); \
+ bigint_bit_is_set_raw ( (value)->element, size, bit ); } )
+
+/**
+ * Find highest bit set in big integer
+ *
+ * @v value Big integer
+ * @ret max_bit Highest bit set + 1 (or 0 if no bits set)
+ */
+#define bigint_max_set_bit( value ) ( { \
+ unsigned int size = bigint_size (value); \
+ bigint_max_set_bit_raw ( (value)->element, size ); } )
+
+/**
+ * Grow big integer
+ *
+ * @v source Source big integer
+ * @v dest Destination big integer
+ */
+#define bigint_grow( source, dest ) do { \
+ unsigned int source_size = bigint_size (source); \
+ unsigned int dest_size = bigint_size (dest); \
+ bigint_grow_raw ( (source)->element, source_size, \
+ (dest)->element, dest_size ); \
+ } while ( 0 )
+
+/**
+ * Shrink big integer
+ *
+ * @v source Source big integer
+ * @v dest Destination big integer
+ */
+#define bigint_shrink( source, dest ) do { \
+ unsigned int source_size = bigint_size (source); \
+ unsigned int dest_size = bigint_size (dest); \
+ bigint_shrink_raw ( (source)->element, source_size, \
+ (dest)->element, dest_size ); \
+ } while ( 0 )
+
+/**
+ * Multiply big integers
+ *
+ * @v multiplicand Big integer to be multiplied
+ * @v multiplier Big integer to be multiplied
+ * @v result Big integer to hold result
+ */
+#define bigint_multiply( multiplicand, multiplier, result ) do { \
+ unsigned int size = bigint_size (multiplicand); \
+ bigint_multiply_raw ( (multiplicand)->element, \
+ (multiplier)->element, (result)->element, \
+ size ); \
+ } while ( 0 )
+
+/**
+ * Perform modular multiplication of big integers
+ *
+ * @v multiplicand Big integer to be multiplied
+ * @v multiplier Big integer to be multiplied
+ * @v modulus Big integer modulus
+ * @v result Big integer to hold result
+ * @v tmp Temporary working space
+ */
+#define bigint_mod_multiply( multiplicand, multiplier, modulus, \
+ result, tmp ) do { \
+ unsigned int size = bigint_size (multiplicand); \
+ bigint_mod_multiply_raw ( (multiplicand)->element, \
+ (multiplier)->element, \
+ (modulus)->element, \
+ (result)->element, size, tmp ); \
+ } while ( 0 )
+
+/**
+ * Calculate temporary working space required for moduluar multiplication
+ *
+ * @v modulus Big integer modulus
+ * @ret len Length of temporary working space
+ */
+#define bigint_mod_multiply_tmp_len( modulus ) ( { \
+ unsigned int size = bigint_size (modulus); \
+ sizeof ( struct { \
+ bigint_t ( size * 2 ) temp_result; \
+ bigint_t ( size * 2 ) temp_modulus; \
+ } ); } )
+
+/**
+ * Perform modular exponentiation of big integers
+ *
+ * @v base Big integer base
+ * @v modulus Big integer modulus
+ * @v exponent Big integer exponent
+ * @v result Big integer to hold result
+ * @v tmp Temporary working space
+ */
+#define bigint_mod_exp( base, modulus, exponent, result, tmp ) do { \
+ unsigned int size = bigint_size (base); \
+ unsigned int exponent_size = bigint_size (exponent); \
+ bigint_mod_exp_raw ( (base)->element, (modulus)->element, \
+ (exponent)->element, (result)->element, \
+ size, exponent_size, tmp ); \
+ } while ( 0 )
+
+/**
+ * Calculate temporary working space required for moduluar exponentiation
+ *
+ * @v modulus Big integer modulus
+ * @v exponent Big integer exponent
+ * @ret len Length of temporary working space
+ */
+#define bigint_mod_exp_tmp_len( modulus, exponent ) ( { \
+ unsigned int size = bigint_size (modulus); \
+ unsigned int exponent_size = bigint_size (exponent); \
+ size_t mod_multiply_len = \
+ bigint_mod_multiply_tmp_len (modulus); \
+ sizeof ( struct { \
+ bigint_t ( size ) temp_base; \
+ bigint_t ( exponent_size ) temp_exponent; \
+ uint8_t mod_multiply[mod_multiply_len]; \
+ } ); } )
+
+#include <bits/bigint.h>
+
+void bigint_init_raw ( bigint_element_t *value0, unsigned int size,
+ const void *data, size_t len );
+void bigint_done_raw ( const bigint_element_t *value0, unsigned int size,
+ void *out, size_t len );
+void bigint_add_raw ( const bigint_element_t *addend0,
+ bigint_element_t *value0, unsigned int size );
+void bigint_subtract_raw ( const bigint_element_t *subtrahend0,
+ bigint_element_t *value0, unsigned int size );
+void bigint_rol_raw ( bigint_element_t *value0, unsigned int size );
+void bigint_ror_raw ( bigint_element_t *value0, unsigned int size );
+int bigint_is_zero_raw ( const bigint_element_t *value0, unsigned int size );
+int bigint_is_geq_raw ( const bigint_element_t *value0,
+ const bigint_element_t *reference0,
+ unsigned int size );
+int bigint_bit_is_set_raw ( const bigint_element_t *value0, unsigned int size,
+ unsigned int bit );
+int bigint_max_set_bit_raw ( const bigint_element_t *value0,
+ unsigned int size );
+void bigint_grow_raw ( const bigint_element_t *source0,
+ unsigned int source_size, bigint_element_t *dest0,
+ unsigned int dest_size );
+void bigint_shrink_raw ( const bigint_element_t *source0,
+ unsigned int source_size, bigint_element_t *dest0,
+ unsigned int dest_size );
+void bigint_multiply_raw ( const bigint_element_t *multiplicand0,
+ const bigint_element_t *multiplier0,
+ bigint_element_t *result0,
+ unsigned int size );
+void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0,
+ const bigint_element_t *multiplier0,
+ const bigint_element_t *modulus0,
+ bigint_element_t *result0,
+ unsigned int size, void *tmp );
+void bigint_mod_exp_raw ( const bigint_element_t *base0,
+ const bigint_element_t *modulus0,
+ const bigint_element_t *exponent0,
+ bigint_element_t *result0,
+ unsigned int size, unsigned int exponent_size,
+ void *tmp );
+
+#endif /* _IPXE_BIGINT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/bitbash.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/bitbash.h
new file mode 100644
index 00000000..62b54b10
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/bitbash.h
@@ -0,0 +1,52 @@
+#ifndef _IPXE_BITBASH_H
+#define _IPXE_BITBASH_H
+
+/** @file
+ *
+ * Bit-bashing interfaces
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct bit_basher;
+
+/** Bit-bashing operations */
+struct bit_basher_operations {
+ /**
+ * Set/clear output bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @v data Value to write
+ *
+ * @c data will be 0 if a logic 0 should be written (i.e. the
+ * bit should be cleared), or -1UL if a logic 1 should be
+ * written (i.e. the bit should be set). This is done so that
+ * the method may simply binary-AND @c data with the
+ * appropriate bit mask.
+ */
+ void ( * write ) ( struct bit_basher *basher, unsigned int bit_id,
+ unsigned long data );
+ /**
+ * Read input bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @ret zero Input is a logic 0
+ * @ret non-zero Input is a logic 1
+ */
+ int ( * read ) ( struct bit_basher *basher, unsigned int bit_id );
+};
+
+/** A bit-bashing interface */
+struct bit_basher {
+ /** Bit-bashing operations */
+ struct bit_basher_operations *op;
+};
+
+extern void write_bit ( struct bit_basher *basher, unsigned int bit_id,
+ unsigned long data );
+extern int read_bit ( struct bit_basher *basher, unsigned int bit_id );
+
+#endif /* _IPXE_BITBASH_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/bitmap.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/bitmap.h
new file mode 100644
index 00000000..b18584c1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/bitmap.h
@@ -0,0 +1,85 @@
+#ifndef _IPXE_BITMAP_H
+#define _IPXE_BITMAP_H
+
+/** @file
+ *
+ * Bitmaps for multicast downloads
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/** A single block of bits within a bitmap */
+typedef unsigned long bitmap_block_t;
+
+/** Size of a block of bits (in bits) */
+#define BITMAP_BLKSIZE ( sizeof ( bitmap_block_t ) * 8 )
+
+/**
+ * Block index within bitmap
+ *
+ * @v bit Bit index
+ * @ret index Block index
+ */
+#define BITMAP_INDEX( bit ) ( (bit) / BITMAP_BLKSIZE )
+
+/**
+ * Block mask within bitmap
+ *
+ * @v bit Bit index
+ * @ret mask Block mask
+ */
+#define BITMAP_MASK( bit ) ( 1UL << ( (bit) % BITMAP_BLKSIZE ) )
+
+/** A bitmap */
+struct bitmap {
+ /** Bitmap data */
+ bitmap_block_t *blocks;
+ /** Length of the bitmap, in bits */
+ unsigned int length;
+ /** Index of first gap in the bitmap */
+ unsigned int first_gap;
+};
+
+extern int bitmap_resize ( struct bitmap *bitmap, unsigned int new_length );
+extern int bitmap_test ( struct bitmap *bitmap, unsigned int bit );
+extern void bitmap_set ( struct bitmap *bitmap, unsigned int bit );
+
+/**
+ * Free bitmap resources
+ *
+ * @v bitmap Bitmap
+ */
+static inline void bitmap_free ( struct bitmap *bitmap ) {
+ free ( bitmap->blocks );
+}
+
+/**
+ * Get first gap within bitmap
+ *
+ * @v bitmap Bitmap
+ * @ret first_gap First gap
+ *
+ * The first gap is the first unset bit within the bitmap.
+ */
+static inline unsigned int bitmap_first_gap ( struct bitmap *bitmap ) {
+ return bitmap->first_gap;
+}
+
+/**
+ * Check to see if bitmap is full
+ *
+ * @v bitmap Bitmap
+ * @ret is_full Bitmap is full
+ *
+ * The bitmap is full if it has no gaps (i.e. no unset bits).
+ */
+static inline int bitmap_full ( struct bitmap *bitmap ) {
+ return ( bitmap->first_gap == bitmap->length );
+}
+
+#endif /* _IPXE_BITMAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/bitops.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/bitops.h
new file mode 100644
index 00000000..4118ef81
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/bitops.h
@@ -0,0 +1,230 @@
+#ifndef _IPXE_BITOPS_H
+#define _IPXE_BITOPS_H
+
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Bit operations
+ *
+ */
+
+#include <stdint.h>
+#include <byteswap.h>
+
+/* Endianness selection.
+ *
+ * This is a property of the NIC, not a property of the host CPU.
+ */
+#ifdef BITOPS_LITTLE_ENDIAN
+#define cpu_to_BIT64 cpu_to_le64
+#define cpu_to_BIT32 cpu_to_le32
+#define BIT64_to_cpu le64_to_cpu
+#define BIT32_to_cpu le32_to_cpu
+#endif
+#ifdef BITOPS_BIG_ENDIAN
+#define cpu_to_BIT64 cpu_to_be64
+#define cpu_to_BIT32 cpu_to_be32
+#define BIT64_to_cpu be64_to_cpu
+#define BIT32_to_cpu be32_to_cpu
+#endif
+
+/** Datatype used to represent a bit in the pseudo-structures */
+typedef unsigned char pseudo_bit_t;
+
+/**
+ * Wrapper structure for pseudo_bit_t structures
+ *
+ * This structure provides a wrapper around pseudo_bit_t structures.
+ * It has the correct size, and also encapsulates type information
+ * about the underlying pseudo_bit_t-based structure, which allows the
+ * BIT_FILL() etc. macros to work without requiring explicit type
+ * information.
+ */
+#define PSEUDO_BIT_STRUCT( _structure ) \
+ union { \
+ uint8_t bytes[ sizeof ( _structure ) / 8 ]; \
+ uint32_t dwords[ sizeof ( _structure ) / 32 ]; \
+ uint64_t qwords[ sizeof ( _structure ) / 64 ]; \
+ _structure *dummy[0]; \
+ } __attribute__ (( packed )) u
+
+/** Get pseudo_bit_t structure type from wrapper structure pointer */
+#define PSEUDO_BIT_STRUCT_TYPE( _ptr ) \
+ typeof ( *((_ptr)->u.dummy[0]) )
+
+/** Bit offset of a field within a pseudo_bit_t structure */
+#define BIT_OFFSET( _ptr, _field ) \
+ offsetof ( PSEUDO_BIT_STRUCT_TYPE ( _ptr ), _field )
+
+/** Bit width of a field within a pseudo_bit_t structure */
+#define BIT_WIDTH( _ptr, _field ) \
+ sizeof ( ( ( PSEUDO_BIT_STRUCT_TYPE ( _ptr ) * ) NULL )->_field )
+
+/** Qword offset of a field within a pseudo_bit_t structure */
+#define QWORD_OFFSET( _ptr, _field ) \
+ ( BIT_OFFSET ( _ptr, _field ) / 64 )
+
+/** Qword bit offset of a field within a pseudo_bit_t structure */
+#define QWORD_BIT_OFFSET( _ptr, _index, _field ) \
+ ( BIT_OFFSET ( _ptr, _field ) - ( 64 * (_index) ) )
+
+/** Bit mask for a field within a pseudo_bit_t structure */
+#define BIT_MASK( _ptr, _field ) \
+ ( ( ~( ( uint64_t ) 0 ) ) >> \
+ ( 64 - BIT_WIDTH ( _ptr, _field ) ) )
+
+/*
+ * Assemble native-endian qword from named fields and values
+ *
+ */
+
+#define BIT_ASSEMBLE_1( _ptr, _index, _field, _value ) \
+ ( ( ( uint64_t) (_value) ) << \
+ QWORD_BIT_OFFSET ( _ptr, _index, _field ) )
+
+#define BIT_ASSEMBLE_2( _ptr, _index, _field, _value, ... ) \
+ ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ BIT_ASSEMBLE_1 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_ASSEMBLE_3( _ptr, _index, _field, _value, ... ) \
+ ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ BIT_ASSEMBLE_2 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_ASSEMBLE_4( _ptr, _index, _field, _value, ... ) \
+ ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ BIT_ASSEMBLE_3 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_ASSEMBLE_5( _ptr, _index, _field, _value, ... ) \
+ ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ BIT_ASSEMBLE_4 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_ASSEMBLE_6( _ptr, _index, _field, _value, ... ) \
+ ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ BIT_ASSEMBLE_5 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_ASSEMBLE_7( _ptr, _index, _field, _value, ... ) \
+ ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ BIT_ASSEMBLE_6 ( _ptr, _index, __VA_ARGS__ ) )
+
+/*
+ * Build native-endian (positive) qword bitmasks from named fields
+ *
+ */
+
+#define BIT_MASK_1( _ptr, _index, _field ) \
+ ( BIT_MASK ( _ptr, _field ) << \
+ QWORD_BIT_OFFSET ( _ptr, _index, _field ) )
+
+#define BIT_MASK_2( _ptr, _index, _field, ... ) \
+ ( BIT_MASK_1 ( _ptr, _index, _field ) | \
+ BIT_MASK_1 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_MASK_3( _ptr, _index, _field, ... ) \
+ ( BIT_MASK_1 ( _ptr, _index, _field ) | \
+ BIT_MASK_2 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_MASK_4( _ptr, _index, _field, ... ) \
+ ( BIT_MASK_1 ( _ptr, _index, _field ) | \
+ BIT_MASK_3 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_MASK_5( _ptr, _index, _field, ... ) \
+ ( BIT_MASK_1 ( _ptr, _index, _field ) | \
+ BIT_MASK_4 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_MASK_6( _ptr, _index, _field, ... ) \
+ ( BIT_MASK_1 ( _ptr, _index, _field ) | \
+ BIT_MASK_5 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_MASK_7( _ptr, _index, _field, ... ) \
+ ( BIT_MASK_1 ( _ptr, _index, _field ) | \
+ BIT_MASK_6 ( _ptr, _index, __VA_ARGS__ ) )
+
+/*
+ * Populate little-endian qwords from named fields and values
+ *
+ */
+
+#define BIT_FILL( _ptr, _index, _assembled ) do { \
+ uint64_t *__ptr = &(_ptr)->u.qwords[(_index)]; \
+ uint64_t __assembled = (_assembled); \
+ *__ptr = cpu_to_BIT64 ( __assembled ); \
+ } while ( 0 )
+
+#define BIT_FILL_1( _ptr, _field1, ... ) \
+ BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ BIT_ASSEMBLE_1 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ _field1, __VA_ARGS__ ) )
+
+#define BIT_FILL_2( _ptr, _field1, ... ) \
+ BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ BIT_ASSEMBLE_2 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ _field1, __VA_ARGS__ ) )
+
+#define BIT_FILL_3( _ptr, _field1, ... ) \
+ BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ BIT_ASSEMBLE_3 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ _field1, __VA_ARGS__ ) )
+
+#define BIT_FILL_4( _ptr, _field1, ... ) \
+ BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ BIT_ASSEMBLE_4 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ _field1, __VA_ARGS__ ) )
+
+#define BIT_FILL_5( _ptr, _field1, ... ) \
+ BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ BIT_ASSEMBLE_5 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ _field1, __VA_ARGS__ ) )
+
+#define BIT_FILL_6( _ptr, _field1, ... ) \
+ BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ BIT_ASSEMBLE_6 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ _field1, __VA_ARGS__ ) )
+
+/** Extract value of named field */
+#define BIT_GET64( _ptr, _field ) \
+ ( { \
+ unsigned int __index = QWORD_OFFSET ( _ptr, _field ); \
+ uint64_t *__ptr = &(_ptr)->u.qwords[__index]; \
+ uint64_t __value = BIT64_to_cpu ( *__ptr ); \
+ __value >>= \
+ QWORD_BIT_OFFSET ( _ptr, __index, _field ); \
+ __value &= BIT_MASK ( _ptr, _field ); \
+ __value; \
+ } )
+
+/** Extract value of named field (for fields up to the size of a long) */
+#define BIT_GET( _ptr, _field ) \
+ ( ( unsigned long ) BIT_GET64 ( _ptr, _field ) )
+
+#define BIT_SET( _ptr, _field, _value ) do { \
+ unsigned int __index = QWORD_OFFSET ( _ptr, _field ); \
+ uint64_t *__ptr = &(_ptr)->u.qwords[__index]; \
+ unsigned int __shift = \
+ QWORD_BIT_OFFSET ( _ptr, __index, _field ); \
+ uint64_t __value = (_value); \
+ *__ptr &= cpu_to_BIT64 ( ~( BIT_MASK ( _ptr, _field ) << \
+ __shift ) ); \
+ *__ptr |= cpu_to_BIT64 ( __value << __shift ); \
+ } while ( 0 )
+
+#endif /* _IPXE_BITOPS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/blockdev.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/blockdev.h
new file mode 100644
index 00000000..9f0a9f78
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/blockdev.h
@@ -0,0 +1,55 @@
+#ifndef _IPXE_BLOCKDEV_H
+#define _IPXE_BLOCKDEV_H
+
+/**
+ * @file
+ *
+ * Block devices
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/interface.h>
+
+/** Block device capacity */
+struct block_device_capacity {
+ /** Total number of blocks */
+ uint64_t blocks;
+ /** Block size */
+ size_t blksize;
+ /** Maximum number of blocks per single transfer */
+ unsigned int max_count;
+};
+
+extern int block_read ( struct interface *control, struct interface *data,
+ uint64_t lba, unsigned int count,
+ userptr_t buffer, size_t len );
+#define block_read_TYPE( object_type ) \
+ typeof ( int ( object_type, struct interface *data, \
+ uint64_t lba, unsigned int count, \
+ userptr_t buffer, size_t len ) )
+
+extern int block_write ( struct interface *control, struct interface *data,
+ uint64_t lba, unsigned int count,
+ userptr_t buffer, size_t len );
+#define block_write_TYPE( object_type ) \
+ typeof ( int ( object_type, struct interface *data, \
+ uint64_t lba, unsigned int count, \
+ userptr_t buffer, size_t len ) )
+
+extern int block_read_capacity ( struct interface *control,
+ struct interface *data );
+#define block_read_capacity_TYPE( object_type ) \
+ typeof ( int ( object_type, struct interface *data ) )
+
+extern void block_capacity ( struct interface *intf,
+ struct block_device_capacity *capacity );
+#define block_capacity_TYPE( object_type ) \
+ typeof ( void ( object_type, \
+ struct block_device_capacity *capacity ) )
+
+
+#endif /* _IPXE_BLOCKDEV_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/bofm.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/bofm.h
new file mode 100644
index 00000000..1da47f65
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/bofm.h
@@ -0,0 +1,351 @@
+#ifndef _IPXE_BOFM_H
+#define _IPXE_BOFM_H
+
+/**
+ * @file
+ *
+ * IBM BladeCenter Open Fabric Manager (BOFM)
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/list.h>
+#include <ipxe/pci.h>
+#include <config/sideband.h>
+
+/** 'IBM ' signature
+ *
+ * Present in %edi when the BIOS initialisation entry point is called,
+ * with the BOFM table pointer in %esi.
+ *
+ * Defined in section 4.1.2 of the POST/BIOS BOFM I/O Address
+ * Re-Assignment Architecture document.
+ */
+#define IBMs_SIGNATURE ( ( 'I' << 24 ) + ( 'B' << 16 ) + ( 'M' << 8 ) + ' ' )
+
+/** ' IBM' signature
+ *
+ * Returned in %edi from the BIOS initialisation entry point, with the
+ * return code in %dl.
+ *
+ * Defined in section 4.1.2 of the POST/BIOS BOFM I/O Address
+ * Re-Assignment Architecture document.
+ */
+#define sIBM_SIGNATURE ( ( ' ' << 24 ) + ( 'I' << 16 ) + ( 'B' << 8 ) + 'M' )
+
+/** @defgroup bofmrc BOFM return codes
+ *
+ * Defined in section 4.1.3 of the POST/BIOS BOFM I/O Address
+ * Re-Assignment Architecture document.
+ *
+ * @{
+ */
+
+/** Successful */
+#define BOFM_SUCCESS 0x00
+
+/** Invalid action string */
+#define BOFM_ERR_INVALID_ACTION 0x01
+
+/** Unsupported parameter structure version */
+#define BOFM_ERR_UNSUPPORTED 0x02
+
+/** Device error prohibited MAC/WWN update */
+#define BOFM_ERR_DEVICE_ERROR 0x03
+
+/** PCI reset required (may be combined with another return code) */
+#define BOFM_PCI_RESET 0x80
+
+/** @} */
+
+/** Skip option ROM initialisation
+ *
+ * A BOFM BIOS may call the initialisation entry point multiple times;
+ * only the last call should result in actual initialisation.
+ *
+ * This flag is internal to iPXE.
+ */
+#define BOFM_SKIP_INIT 0x80000000UL
+
+/** BOFM table header
+ *
+ * Defined in section 4.1 of the Open Fabric Manager Parameter
+ * Specification document.
+ */
+struct bofm_global_header {
+ /** Signature */
+ uint32_t magic;
+ /** Subsignature (action string) */
+ uint32_t action;
+ /** Data structure version */
+ uint8_t version;
+ /** Data structure level */
+ uint8_t level;
+ /** Data structure length */
+ uint16_t length;
+ /** Data structure checksum */
+ uint8_t checksum;
+ /** Data structure profile */
+ char profile[32];
+ /** Data structure global options */
+ uint32_t options;
+ /** Data structure sequence stamp */
+ uint32_t sequence;
+} __attribute__ (( packed ));
+
+/** BOFM table header signature
+ *
+ * Defined in section 4.1.2 of the POST/BIOS BOFM I/O Address
+ * Re-Assignment Architecture document.
+ */
+#define BOFM_IOAA_MAGIC ( 'I' + ( 'O' << 8 ) + ( 'A' << 16 ) + ( 'A' << 24 ) )
+
+/** @defgroup bofmaction BOFM header subsignatures (action strings)
+ *
+ * Defined in section 4.1.2 of the POST/BIOS BOFM I/O Address
+ * Re-Assignment Architecture document.
+ *
+ * @{
+ */
+
+/** Update MAC/WWN */
+#define BOFM_ACTION_UPDT ( 'U' + ( 'P' << 8 ) + ( 'D' << 16 ) + ( 'T' << 24 ) )
+
+/** Restore MAC/WWN to factory default */
+#define BOFM_ACTION_DFLT ( 'D' + ( 'F' << 8 ) + ( 'L' << 16 ) + ( 'T' << 24 ) )
+
+/** Harvest MAC/WWN */
+#define BOFM_ACTION_HVST ( 'H' + ( 'V' << 8 ) + ( 'S' << 16 ) + ( 'T' << 24 ) )
+
+/** Update MAC/WWN and initialise device */
+#define BOFM_ACTION_PARM ( 'P' + ( 'A' << 8 ) + ( 'R' << 16 ) + ( 'M' << 24 ) )
+
+/** Just initialise the device */
+#define BOFM_ACTION_NONE ( 'N' + ( 'O' << 8 ) + ( 'N' << 16 ) + ( 'E' << 24 ) )
+
+/** @} */
+
+/** BOFM section header
+ *
+ * Defined in section 4.2 of the Open Fabric Manager Parameter
+ * Specification document.
+ */
+struct bofm_section_header {
+ /** Signature */
+ uint32_t magic;
+ /** Length */
+ uint16_t length;
+} __attribute__ (( packed ));
+
+/** @defgroup bofmsections BOFM section header signatures
+ *
+ * Defined in section 4.2 of the Open Fabric Manager Parameter
+ * Specification document.
+ *
+ * @{
+ */
+
+/** EN start marker */
+#define BOFM_EN_MAGIC ( ' ' + ( ' ' << 8 ) + ( 'E' << 16 ) + ( 'N' << 24 ) )
+
+/** End marker */
+#define BOFM_DONE_MAGIC ( 'D' + ( 'O' << 8 ) + ( 'N' << 16 ) + ( 'E' << 24 ) )
+
+/** @} */
+
+/** BOFM Ethernet parameter entry
+ *
+ * Defined in section 5.1 of the Open Fabric Manager Parameter
+ * Specification document.
+ */
+struct bofm_en {
+ /** Options */
+ uint16_t options;
+ /** PCI bus:dev.fn
+ *
+ * Valid only if @c options indicates @c BOFM_EN_MAP_PFA
+ */
+ uint16_t busdevfn;
+ /** Slot or mezzanine number
+ *
+ * Valid only if @c options indicates @c BOFM_EN_MAP_SLOT_PORT
+ */
+ uint8_t slot;
+ /** Port number
+ *
+ * Valid only if @c options indicates @c BOFM_EN_MAP_SLOT_PORT
+ */
+ uint8_t port;
+ /** Multi-port index */
+ uint8_t mport;
+ /** VLAN tag for MAC address A */
+ uint16_t vlan_a;
+ /** MAC address A
+ *
+ * MAC address A is the sole MAC address, or the lower
+ * (inclusive) bound of a range of MAC addresses.
+ */
+ uint8_t mac_a[6];
+ /** VLAN tag for MAC address B */
+ uint16_t vlan_b;
+ /** MAC address B
+ *
+ * MAC address B is unset, or the upper (inclusive) bound of a
+ * range of MAC addresses
+ */
+ uint8_t mac_b[6];
+} __attribute__ (( packed ));
+
+/** @defgroup bofmenopts BOFM Ethernet parameter entry options
+ *
+ * Defined in section 5.1 of the Open Fabric Manager Parameter
+ * Specification document.
+ *
+ * @{
+ */
+
+/** Port mapping mask */
+#define BOFM_EN_MAP_MASK 0x0001
+
+/** Port mapping is by PCI bus:dev.fn */
+#define BOFM_EN_MAP_PFA 0x0000
+
+/** Port mapping is by slot/port */
+#define BOFM_EN_MAP_SLOT_PORT 0x0001
+
+/** MAC address B is present */
+#define BOFM_EN_EN_B 0x0002
+
+/** VLAN tag for MAC address B is present */
+#define BOFM_EN_VLAN_B 0x0004
+
+/** MAC address A is present */
+#define BOFM_EN_EN_A 0x0008
+
+/** VLAN tag for MAC address A is present */
+#define BOFM_EN_VLAN_A 0x0010
+
+/** Entry consumption indicator mask */
+#define BOFM_EN_CSM_MASK 0x00c0
+
+/** Entry has not been used */
+#define BOFM_EN_CSM_UNUSED 0x0000
+
+/** Entry has been used successfully */
+#define BOFM_EN_CSM_SUCCESS 0x0040
+
+/** Entry has been used but failed */
+#define BOFM_EN_CSM_FAILED 0x0080
+
+/** Consumed entry change mask */
+#define BOFM_EN_CHG_MASK 0x0100
+
+/** Consumed entry is same as previous active entry */
+#define BOFM_EN_CHG_UNCHANGED 0x0000
+
+/** Consumed entry is different than previous active entry */
+#define BOFM_EN_CHG_CHANGED 0x0100
+
+/** Ignore values - it's harvest time */
+#define BOFM_EN_USAGE_HARVEST 0x1000
+
+/** Use entry values for assignment */
+#define BOFM_EN_USAGE_ENTRY 0x0800
+
+/** Use factory default values */
+#define BOFM_EN_USAGE_DEFAULT 0x0400
+
+/** Harvest complete */
+#define BOFM_EN_HVST 0x2000
+
+/** Harvest request mask */
+#define BOFM_EN_RQ_HVST_MASK 0xc000
+
+/** Do not harvest */
+#define BOFM_EN_RQ_HVST_NONE 0x0000
+
+/** Harvest factory default values */
+#define BOFM_EN_RQ_HVST_DEFAULT 0x4000
+
+/** Harvest active values */
+#define BOFM_EN_RQ_HVST_ACTIVE 0xc000
+
+/** @} */
+
+/** BOFM magic value debug message format */
+#define BOFM_MAGIC_FMT "'%c%c%c%c'"
+
+/** BOFM magic value debug message arguments */
+#define BOFM_MAGIC_ARGS( magic ) \
+ ( ( (magic) >> 0 ) & 0xff ), ( ( (magic) >> 8 ) & 0xff ), \
+ ( ( (magic) >> 16 ) & 0xff ), ( ( (magic) >> 24 ) & 0xff )
+
+/** A BOFM device */
+struct bofm_device {
+ /** Underlying PCI device */
+ struct pci_device *pci;
+ /** BOFM device operations */
+ struct bofm_operations *op;
+ /** List of BOFM devices */
+ struct list_head list;
+};
+
+/** BOFM device operations */
+struct bofm_operations {
+ /** Harvest Ethernet MAC
+ *
+ * @v bofm BOFM device
+ * @v mport Multi-port index
+ * @v mac MAC to fill in
+ * @ret rc Return status code
+ */
+ int ( * harvest ) ( struct bofm_device *bofm, unsigned int mport,
+ uint8_t *mac );
+ /** Update Ethernet MAC
+ *
+ * @v bofm BOFM device
+ * @v mport Multi-port index
+ * @v mac New MAC
+ * @ret rc Return status code
+ */
+ int ( * update ) ( struct bofm_device *bofm, unsigned int mport,
+ const uint8_t *mac );
+};
+
+/** BOFM driver table */
+#define BOFM_DRIVERS __table ( struct pci_driver, "bofm_drivers" )
+
+/** Declare a BOFM driver
+ *
+ * In the common case of non-BOFM-enabled builds, allow any BOFM code
+ * to be garbage-collected at link time to save space.
+ */
+#ifdef CONFIG_BOFM
+#define __bofm_driver __table_entry ( BOFM_DRIVERS, 01 )
+#else
+#define __bofm_driver
+#endif
+
+/**
+ * Initialise BOFM device
+ *
+ * @v bofm BOFM device
+ * @v pci PCI device
+ * @v op BOFM device operations
+ */
+static inline __attribute__ (( always_inline )) void
+bofm_init ( struct bofm_device *bofm, struct pci_device *pci,
+ struct bofm_operations *op ) {
+ bofm->pci = pci;
+ bofm->op = op;
+}
+
+extern int bofm_register ( struct bofm_device *bofm );
+extern void bofm_unregister ( struct bofm_device *bofm );
+extern int bofm_find_driver ( struct pci_device *pci );
+extern int bofm ( userptr_t bofmtab, struct pci_device *pci );
+extern void bofm_test ( struct pci_device *pci );
+
+#endif /* _IPXE_BOFM_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/cbc.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/cbc.h
new file mode 100644
index 00000000..fae37657
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/cbc.h
@@ -0,0 +1,100 @@
+#ifndef _IPXE_CBC_H
+#define _IPXE_CBC_H
+
+/** @file
+ *
+ * Cipher-block chaining
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/crypto.h>
+
+/**
+ * Set key
+ *
+ * @v ctx Context
+ * @v key Key
+ * @v keylen Key length
+ * @v raw_cipher Underlying cipher algorithm
+ * @v cbc_ctx CBC context
+ * @ret rc Return status code
+ */
+static inline int cbc_setkey ( void *ctx, const void *key, size_t keylen,
+ struct cipher_algorithm *raw_cipher,
+ void *cbc_ctx __unused ) {
+
+ return cipher_setkey ( raw_cipher, ctx, key, keylen );
+}
+
+/**
+ * Set initialisation vector
+ *
+ * @v ctx Context
+ * @v iv Initialisation vector
+ * @v raw_cipher Underlying cipher algorithm
+ * @v cbc_ctx CBC context
+ */
+static inline void cbc_setiv ( void *ctx __unused, const void *iv,
+ struct cipher_algorithm *raw_cipher,
+ void *cbc_ctx ) {
+ memcpy ( cbc_ctx, iv, raw_cipher->blocksize );
+}
+
+extern void cbc_encrypt ( void *ctx, const void *src, void *dst,
+ size_t len, struct cipher_algorithm *raw_cipher,
+ void *cbc_ctx );
+extern void cbc_decrypt ( void *ctx, const void *src, void *dst,
+ size_t len, struct cipher_algorithm *raw_cipher,
+ void *cbc_ctx );
+
+/**
+ * Create a cipher-block chaining mode of behaviour of an existing cipher
+ *
+ * @v _cbc_name Name for the new CBC cipher
+ * @v _cbc_cipher New cipher algorithm
+ * @v _raw_cipher Underlying cipher algorithm
+ * @v _raw_context Context structure for the underlying cipher
+ * @v _blocksize Cipher block size
+ */
+#define CBC_CIPHER( _cbc_name, _cbc_cipher, _raw_cipher, _raw_context, \
+ _blocksize ) \
+struct _cbc_name ## _context { \
+ _raw_context raw_ctx; \
+ uint8_t cbc_ctx[_blocksize]; \
+}; \
+static int _cbc_name ## _setkey ( void *ctx, const void *key, \
+ size_t keylen ) { \
+ struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
+ return cbc_setkey ( &_cbc_name ## _ctx->raw_ctx, key, keylen, \
+ &_raw_cipher, &_cbc_name ## _ctx->cbc_ctx );\
+} \
+static void _cbc_name ## _setiv ( void *ctx, const void *iv ) { \
+ struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
+ cbc_setiv ( &_cbc_name ## _ctx->raw_ctx, iv, \
+ &_raw_cipher, &aes_cbc_ctx->cbc_ctx ); \
+} \
+static void _cbc_name ## _encrypt ( void *ctx, const void *src, \
+ void *dst, size_t len ) { \
+ struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
+ cbc_encrypt ( &_cbc_name ## _ctx->raw_ctx, src, dst, len, \
+ &_raw_cipher, &aes_cbc_ctx->cbc_ctx ); \
+} \
+static void _cbc_name ## _decrypt ( void *ctx, const void *src, \
+ void *dst, size_t len ) { \
+ struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
+ cbc_decrypt ( &_cbc_name ## _ctx->raw_ctx, src, dst, len, \
+ &_raw_cipher, &aes_cbc_ctx->cbc_ctx ); \
+} \
+struct cipher_algorithm _cbc_cipher = { \
+ .name = #_cbc_name, \
+ .ctxsize = sizeof ( struct _cbc_name ## _context ), \
+ .blocksize = _blocksize, \
+ .setkey = _cbc_name ## _setkey, \
+ .setiv = _cbc_name ## _setiv, \
+ .encrypt = _cbc_name ## _encrypt, \
+ .decrypt = _cbc_name ## _decrypt, \
+};
+
+#endif /* _IPXE_CBC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/chap.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/chap.h
new file mode 100644
index 00000000..fce48f3e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/chap.h
@@ -0,0 +1,53 @@
+#ifndef _IPXE_CHAP_H
+#define _IPXE_CHAP_H
+
+/** @file
+ *
+ * CHAP protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/md5.h>
+
+struct digest_algorithm;
+
+/** A CHAP response */
+struct chap_response {
+ /** Digest algorithm used for the response */
+ struct digest_algorithm *digest;
+ /** Context used by the digest algorithm */
+ uint8_t *digest_context;
+ /** CHAP response */
+ uint8_t *response;
+ /** Length of CHAP response */
+ size_t response_len;
+};
+
+extern int chap_init ( struct chap_response *chap,
+ struct digest_algorithm *digest );
+extern void chap_update ( struct chap_response *chap, const void *data,
+ size_t len );
+extern void chap_respond ( struct chap_response *chap );
+extern void chap_finish ( struct chap_response *chap );
+
+/**
+ * Add identifier data to the CHAP challenge
+ *
+ * @v chap CHAP response
+ * @v identifier CHAP identifier
+ *
+ * The CHAP identifier is the first byte of the CHAP challenge. This
+ * function is a notational convenience for calling chap_update() for
+ * the identifier byte.
+ */
+static inline void chap_set_identifier ( struct chap_response *chap,
+ unsigned int identifier ) {
+ uint8_t ident_byte = identifier;
+
+ chap_update ( chap, &ident_byte, sizeof ( ident_byte ) );
+}
+
+#endif /* _IPXE_CHAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/clientcert.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/clientcert.h
new file mode 100644
index 00000000..08f62eb7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/clientcert.h
@@ -0,0 +1,43 @@
+#ifndef _IPXE_CLIENTCERT_H
+#define _IPXE_CLIENTCERT_H
+
+/** @file
+ *
+ * Client certificate store
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/** A client certificate */
+struct client_certificate {
+ /** Data */
+ const void *data;
+ /** Length */
+ size_t len;
+};
+
+/** A client private key */
+struct client_private_key {
+ /** Data */
+ const void *data;
+ /** Length */
+ size_t len;
+};
+
+extern struct client_certificate client_certificate;
+extern struct client_private_key client_private_key;
+
+/**
+ * Check for presence of a client certificate
+ *
+ * @ret have_cert We have a client certificate and private key
+ */
+static inline int have_client_certificate ( void ) {
+ return ( ( client_certificate.len > 0 ) &&
+ ( client_private_key.len > 0 ) );
+}
+
+#endif /* _IPXE_CLIENTCERT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/cms.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/cms.h
new file mode 100644
index 00000000..eadeca4b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/cms.h
@@ -0,0 +1,75 @@
+#ifndef _IPXE_CMS_H
+#define _IPXE_CMS_H
+
+/** @file
+ *
+ * Cryptographic Message Syntax (PKCS #7)
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <time.h>
+#include <ipxe/asn1.h>
+#include <ipxe/crypto.h>
+#include <ipxe/x509.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/uaccess.h>
+
+/** CMS signer information */
+struct cms_signer_info {
+ /** List of signer information blocks */
+ struct list_head list;
+
+ /** Certificate chain */
+ struct x509_chain *chain;
+
+ /** Digest algorithm */
+ struct digest_algorithm *digest;
+ /** Public-key algorithm */
+ struct pubkey_algorithm *pubkey;
+
+ /** Signature */
+ void *signature;
+ /** Length of signature */
+ size_t signature_len;
+};
+
+/** A CMS signature */
+struct cms_signature {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** List of all certificates */
+ struct x509_chain *certificates;
+ /** List of signer information blocks */
+ struct list_head info;
+};
+
+/**
+ * Get reference to CMS signature
+ *
+ * @v sig CMS signature
+ * @ret sig CMS signature
+ */
+static inline __attribute__ (( always_inline )) struct cms_signature *
+cms_get ( struct cms_signature *sig ) {
+ ref_get ( &sig->refcnt );
+ return sig;
+}
+
+/**
+ * Drop reference to CMS signature
+ *
+ * @v sig CMS signature
+ */
+static inline __attribute__ (( always_inline )) void
+cms_put ( struct cms_signature *sig ) {
+ ref_put ( &sig->refcnt );
+}
+
+extern int cms_signature ( const void *data, size_t len,
+ struct cms_signature **sig );
+extern int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len,
+ const char *name, time_t time, struct x509_root *root );
+
+#endif /* _IPXE_CMS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/command.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/command.h
new file mode 100644
index 00000000..432da1ab
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/command.h
@@ -0,0 +1,28 @@
+#ifndef _IPXE_COMMAND_H
+#define _IPXE_COMMAND_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/tables.h>
+
+/** A command-line command */
+struct command {
+ /** Name of the command */
+ const char *name;
+ /**
+ * Function implementing the command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+ int ( * exec ) ( int argc, char **argv );
+};
+
+#define COMMANDS __table ( struct command, "commands" )
+
+#define __command __table_entry ( COMMANDS, 01 )
+
+extern char * concat_args ( char **args );
+
+#endif /* _IPXE_COMMAND_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/console.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/console.h
new file mode 100644
index 00000000..e2bf4be9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/console.h
@@ -0,0 +1,163 @@
+#ifndef _IPXE_CONSOLE_H
+#define _IPXE_CONSOLE_H
+
+#include <stdio.h>
+#include <ipxe/tables.h>
+
+/** @file
+ *
+ * User interaction.
+ *
+ * Various console devices can be selected via the build options
+ * CONSOLE_FIRMWARE, CONSOLE_SERIAL etc. The console functions
+ * putchar(), getchar() and iskey() delegate to the individual console
+ * drivers.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * A console driver
+ *
+ * Defines the functions that implement a particular console type.
+ * Must be made part of the console drivers table by using
+ * #__console_driver.
+ *
+ * @note Consoles that cannot be used before their initialisation
+ * function has completed should set #disabled=1 initially. This
+ * allows other console devices to still be used to print out early
+ * debugging messages.
+ *
+ */
+struct console_driver {
+ /** Console is disabled.
+ *
+ * The console's putchar(), getchar() and iskey() methods will
+ * not be called while #disabled==1. Typically the console's
+ * initialisation functions will set #disabled=0 upon
+ * completion.
+ *
+ */
+ int disabled;
+
+ /** Write a character to the console.
+ *
+ * @v character Character to be written
+ * @ret None -
+ * @err None -
+ *
+ */
+ void ( *putchar ) ( int character );
+
+ /** Read a character from the console.
+ *
+ * @v None -
+ * @ret character Character read
+ * @err None -
+ *
+ * If no character is available to be read, this method will
+ * block. The character read should not be echoed back to the
+ * console.
+ *
+ */
+ int ( *getchar ) ( void );
+
+ /** Check for available input.
+ *
+ * @v None -
+ * @ret True Input is available
+ * @ret False Input is not available
+ * @err None -
+ *
+ * This should return True if a subsequent call to getchar()
+ * will not block.
+ *
+ */
+ int ( *iskey ) ( void );
+
+ /** Console usage bitmask
+ *
+ * This is the bitwise OR of zero or more @c CONSOLE_USAGE_XXX
+ * values.
+ */
+ int usage;
+};
+
+/** Console driver table */
+#define CONSOLES __table ( struct console_driver, "consoles" )
+
+/**
+ * Mark a <tt> struct console_driver </tt> as being part of the
+ * console drivers table.
+ *
+ * Use as e.g.
+ *
+ * @code
+ *
+ * struct console_driver my_console __console_driver = {
+ * .putchar = my_putchar,
+ * .getchar = my_getchar,
+ * .iskey = my_iskey,
+ * };
+ *
+ * @endcode
+ *
+ */
+#define __console_driver __table_entry ( CONSOLES, 01 )
+
+/**
+ * @defgroup consoleusage Console usages
+ * @{
+ */
+
+/** Standard output */
+#define CONSOLE_USAGE_STDOUT 0x0001
+
+/** Debug messages */
+#define CONSOLE_USAGE_DEBUG 0x0002
+
+/** Text-based user interface */
+#define CONSOLE_USAGE_TUI 0x0004
+
+/** Log messages */
+#define CONSOLE_USAGE_LOG 0x0008
+
+/** All console usages */
+#define CONSOLE_USAGE_ALL ( CONSOLE_USAGE_STDOUT | CONSOLE_USAGE_DEBUG | \
+ CONSOLE_USAGE_TUI | CONSOLE_USAGE_LOG )
+
+/** @} */
+
+/**
+ * Test to see if console has an explicit usage
+ *
+ * @v console Console definition (e.g. CONSOLE_PCBIOS)
+ * @ret explicit Console has an explicit usage
+ *
+ * This relies upon the trick that the expression ( 2 * N + 1 ) will
+ * be valid even if N is defined to be empty, since it will then
+ * evaluate to give ( 2 * + 1 ) == ( 2 * +1 ) == 2.
+ */
+#define CONSOLE_EXPLICIT( console ) ( ( 2 * console + 1 ) != 2 )
+
+extern int console_usage;
+
+/**
+ * Set console usage
+ *
+ * @v usage New console usage
+ * @ret old_usage Previous console usage
+ */
+static inline __attribute__ (( always_inline )) int
+console_set_usage ( int usage ) {
+ int old_usage = console_usage;
+
+ console_usage = usage;
+ return old_usage;
+}
+
+extern int iskey ( void );
+extern int getkey ( unsigned long timeout );
+
+#endif /* _IPXE_CONSOLE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/cpio.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/cpio.h
new file mode 100644
index 00000000..27723280
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/cpio.h
@@ -0,0 +1,53 @@
+#ifndef _IPXE_CPIO_H
+#define _IPXE_CPIO_H
+
+/** @file
+ *
+ * CPIO archives
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** A CPIO archive header
+ *
+ * All field are hexadecimal ASCII numbers padded with '0' on the
+ * left to the full width of the field.
+ */
+struct cpio_header {
+ /** The string "070701" or "070702" */
+ char c_magic[6];
+ /** File inode number */
+ char c_ino[8];
+ /** File mode and permissions */
+ char c_mode[8];
+ /** File uid */
+ char c_uid[8];
+ /** File gid */
+ char c_gid[8];
+ /** Number of links */
+ char c_nlink[8];
+ /** Modification time */
+ char c_mtime[8];
+ /** Size of data field */
+ char c_filesize[8];
+ /** Major part of file device number */
+ char c_maj[8];
+ /** Minor part of file device number */
+ char c_min[8];
+ /** Major part of device node reference */
+ char c_rmaj[8];
+ /** Minor part of device node reference */
+ char c_rmin[8];
+ /** Length of filename, including final NUL */
+ char c_namesize[8];
+ /** Checksum of data field if c_magic is 070702, othersize zero */
+ char c_chksum[8];
+} __attribute__ (( packed ));
+
+/** CPIO magic */
+#define CPIO_MAGIC "070701"
+
+extern void cpio_set_field ( char *field, unsigned long value );
+
+#endif /* _IPXE_CPIO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/crc32.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/crc32.h
new file mode 100644
index 00000000..38ac1b31
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/crc32.h
@@ -0,0 +1,10 @@
+#ifndef _IPXE_CRC32_H
+#define _IPXE_CRC32_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+u32 crc32_le ( u32 seed, const void *data, size_t len );
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/crypto.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/crypto.h
new file mode 100644
index 00000000..d7d42b66
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/crypto.h
@@ -0,0 +1,252 @@
+#ifndef _IPXE_CRYPTO_H
+#define _IPXE_CRYPTO_H
+
+/** @file
+ *
+ * Cryptographic API
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stddef.h>
+
+/** A message digest algorithm */
+struct digest_algorithm {
+ /** Algorithm name */
+ const char *name;
+ /** Context size */
+ size_t ctxsize;
+ /** Block size */
+ size_t blocksize;
+ /** Digest size */
+ size_t digestsize;
+ /** Initialise digest
+ *
+ * @v ctx Context
+ */
+ void ( * init ) ( void *ctx );
+ /** Update digest with new data
+ *
+ * @v ctx Context
+ * @v src Data to digest
+ * @v len Length of data
+ *
+ * @v len is not necessarily a multiple of @c blocksize.
+ */
+ void ( * update ) ( void *ctx, const void *src, size_t len );
+ /** Finalise digest
+ *
+ * @v ctx Context
+ * @v out Buffer for digest output
+ */
+ void ( * final ) ( void *ctx, void *out );
+};
+
+/** A cipher algorithm */
+struct cipher_algorithm {
+ /** Algorithm name */
+ const char *name;
+ /** Context size */
+ size_t ctxsize;
+ /** Block size */
+ size_t blocksize;
+ /** Set key
+ *
+ * @v ctx Context
+ * @v key Key
+ * @v keylen Key length
+ * @ret rc Return status code
+ */
+ int ( * setkey ) ( void *ctx, const void *key, size_t keylen );
+ /** Set initialisation vector
+ *
+ * @v ctx Context
+ * @v iv Initialisation vector
+ */
+ void ( * setiv ) ( void *ctx, const void *iv );
+ /** Encrypt data
+ *
+ * @v ctx Context
+ * @v src Data to encrypt
+ * @v dst Buffer for encrypted data
+ * @v len Length of data
+ *
+ * @v len is guaranteed to be a multiple of @c blocksize.
+ */
+ void ( * encrypt ) ( void *ctx, const void *src, void *dst,
+ size_t len );
+ /** Decrypt data
+ *
+ * @v ctx Context
+ * @v src Data to decrypt
+ * @v dst Buffer for decrypted data
+ * @v len Length of data
+ *
+ * @v len is guaranteed to be a multiple of @c blocksize.
+ */
+ void ( * decrypt ) ( void *ctx, const void *src, void *dst,
+ size_t len );
+};
+
+/** A public key algorithm */
+struct pubkey_algorithm {
+ /** Algorithm name */
+ const char *name;
+ /** Context size */
+ size_t ctxsize;
+ /** Initialise algorithm
+ *
+ * @v ctx Context
+ * @v key Key
+ * @v key_len Length of key
+ * @ret rc Return status code
+ */
+ int ( * init ) ( void *ctx, const void *key, size_t key_len );
+ /** Calculate maximum output length
+ *
+ * @v ctx Context
+ * @ret max_len Maximum output length
+ */
+ size_t ( * max_len ) ( void *ctx );
+ /** Encrypt
+ *
+ * @v ctx Context
+ * @v plaintext Plaintext
+ * @v plaintext_len Length of plaintext
+ * @v ciphertext Ciphertext
+ * @ret ciphertext_len Length of ciphertext, or negative error
+ */
+ int ( * encrypt ) ( void *ctx, const void *data, size_t len,
+ void *out );
+ /** Decrypt
+ *
+ * @v ctx Context
+ * @v ciphertext Ciphertext
+ * @v ciphertext_len Ciphertext length
+ * @v plaintext Plaintext
+ * @ret plaintext_len Plaintext length, or negative error
+ */
+ int ( * decrypt ) ( void *ctx, const void *data, size_t len,
+ void *out );
+ /** Sign digest value
+ *
+ * @v ctx Context
+ * @v digest Digest algorithm
+ * @v value Digest value
+ * @v signature Signature
+ * @ret signature_len Signature length, or negative error
+ */
+ int ( * sign ) ( void *ctx, struct digest_algorithm *digest,
+ const void *value, void *signature );
+ /** Verify signed digest value
+ *
+ * @v ctx Context
+ * @v digest Digest algorithm
+ * @v value Digest value
+ * @v signature Signature
+ * @v signature_len Signature length
+ * @ret rc Return status code
+ */
+ int ( * verify ) ( void *ctx, struct digest_algorithm *digest,
+ const void *value, const void *signature,
+ size_t signature_len );
+ /** Finalise algorithm
+ *
+ * @v ctx Context
+ */
+ void ( * final ) ( void *ctx );
+};
+
+static inline void digest_init ( struct digest_algorithm *digest,
+ void *ctx ) {
+ digest->init ( ctx );
+}
+
+static inline void digest_update ( struct digest_algorithm *digest,
+ void *ctx, const void *data, size_t len ) {
+ digest->update ( ctx, data, len );
+}
+
+static inline void digest_final ( struct digest_algorithm *digest,
+ void *ctx, void *out ) {
+ digest->final ( ctx, out );
+}
+
+static inline int cipher_setkey ( struct cipher_algorithm *cipher,
+ void *ctx, const void *key, size_t keylen ) {
+ return cipher->setkey ( ctx, key, keylen );
+}
+
+static inline void cipher_setiv ( struct cipher_algorithm *cipher,
+ void *ctx, const void *iv ) {
+ cipher->setiv ( ctx, iv );
+}
+
+static inline void cipher_encrypt ( struct cipher_algorithm *cipher,
+ void *ctx, const void *src, void *dst,
+ size_t len ) {
+ cipher->encrypt ( ctx, src, dst, len );
+}
+#define cipher_encrypt( cipher, ctx, src, dst, len ) do { \
+ assert ( ( (len) & ( (cipher)->blocksize - 1 ) ) == 0 ); \
+ cipher_encrypt ( (cipher), (ctx), (src), (dst), (len) ); \
+ } while ( 0 )
+
+static inline void cipher_decrypt ( struct cipher_algorithm *cipher,
+ void *ctx, const void *src, void *dst,
+ size_t len ) {
+ cipher->decrypt ( ctx, src, dst, len );
+}
+#define cipher_decrypt( cipher, ctx, src, dst, len ) do { \
+ assert ( ( (len) & ( (cipher)->blocksize - 1 ) ) == 0 ); \
+ cipher_decrypt ( (cipher), (ctx), (src), (dst), (len) ); \
+ } while ( 0 )
+
+static inline int is_stream_cipher ( struct cipher_algorithm *cipher ) {
+ return ( cipher->blocksize == 1 );
+}
+
+static inline int pubkey_init ( struct pubkey_algorithm *pubkey, void *ctx,
+ const void *key, size_t key_len ) {
+ return pubkey->init ( ctx, key, key_len );
+}
+
+static inline size_t pubkey_max_len ( struct pubkey_algorithm *pubkey,
+ void *ctx ) {
+ return pubkey->max_len ( ctx );
+}
+
+static inline int pubkey_encrypt ( struct pubkey_algorithm *pubkey, void *ctx,
+ const void *data, size_t len, void *out ) {
+ return pubkey->encrypt ( ctx, data, len, out );
+}
+
+static inline int pubkey_decrypt ( struct pubkey_algorithm *pubkey, void *ctx,
+ const void *data, size_t len, void *out ) {
+ return pubkey->decrypt ( ctx, data, len, out );
+}
+
+static inline int pubkey_sign ( struct pubkey_algorithm *pubkey, void *ctx,
+ struct digest_algorithm *digest,
+ const void *value, void *signature ) {
+ return pubkey->sign ( ctx, digest, value, signature );
+}
+
+static inline int pubkey_verify ( struct pubkey_algorithm *pubkey, void *ctx,
+ struct digest_algorithm *digest,
+ const void *value, const void *signature,
+ size_t signature_len ) {
+ return pubkey->verify ( ctx, digest, value, signature, signature_len );
+}
+
+static inline void pubkey_final ( struct pubkey_algorithm *pubkey, void *ctx ) {
+ pubkey->final ( ctx );
+}
+
+extern struct digest_algorithm digest_null;
+extern struct cipher_algorithm cipher_null;
+extern struct pubkey_algorithm pubkey_null;
+
+#endif /* _IPXE_CRYPTO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/device.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/device.h
new file mode 100644
index 00000000..b712204b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/device.h
@@ -0,0 +1,148 @@
+#ifndef _IPXE_DEVICE_H
+#define _IPXE_DEVICE_H
+
+/**
+ * @file
+ *
+ * Device model
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/list.h>
+#include <ipxe/tables.h>
+#include <ipxe/io.h>
+
+#define NET_BOOT_NICS 4
+struct interface;
+
+/** A hardware device description */
+struct device_description {
+ /** Bus type
+ *
+ * This must be a BUS_TYPE_XXX constant.
+ */
+ unsigned int bus_type;
+ /** Location
+ *
+ * The interpretation of this field is bus-type-specific.
+ */
+ unsigned int location;
+ /** Vendor ID */
+ unsigned int vendor;
+ /** Device ID */
+ unsigned int device;
+ /** Device class */
+ unsigned long class;
+ /** I/O address */
+ unsigned long ioaddr;
+ /** IRQ */
+ unsigned int irq;
+};
+
+/** PCI bus type */
+#define BUS_TYPE_PCI 1
+
+/** ISAPnP bus type */
+#define BUS_TYPE_ISAPNP 2
+
+/** EISA bus type */
+#define BUS_TYPE_EISA 3
+
+/** MCA bus type */
+#define BUS_TYPE_MCA 4
+
+/** ISA bus type */
+#define BUS_TYPE_ISA 5
+
+/** A hardware device */
+struct device {
+ /** Name */
+ char name[16];
+ /** Driver name */
+ const char *driver_name;
+ /** Device description */
+ struct device_description desc;
+ /** Devices on the same bus */
+ struct list_head siblings;
+ /** Devices attached to this device */
+ struct list_head children;
+ /** Bus device */
+ struct device *parent;
+};
+
+/**
+ * A root device
+ *
+ * Root devices are system buses such as PCI, EISA, etc.
+ *
+ */
+struct root_device {
+ /** Device chain
+ *
+ * A root device has a NULL parent field.
+ */
+ struct device dev;
+ /** Root device driver */
+ struct root_driver *driver;
+};
+
+/** A root device driver */
+struct root_driver {
+ /**
+ * Add root device
+ *
+ * @v rootdev Root device
+ * @ret rc Return status code
+ *
+ * Called from probe_devices() for all root devices in the build.
+ */
+ int ( * probe ) ( struct root_device *rootdev );
+ /**
+ * Remove root device
+ *
+ * @v rootdev Root device
+ *
+ * Called from remove_device() for all successfully-probed
+ * root devices.
+ */
+ void ( * remove ) ( struct root_device *rootdev );
+};
+
+/** Root device table */
+#define ROOT_DEVICES __table ( struct root_device, "root_devices" )
+
+/** Declare a root device */
+#define __root_device __table_entry ( ROOT_DEVICES, 01 )
+
+extern int device_keep_count;
+#ifdef VBOX
+static inline uint8_t cmos2_read(uint8_t offset)
+{
+ outb(offset, 0x72);
+ return inb(0x73);
+}
+#endif
+
+/**
+ * Prevent devices from being removed on shutdown
+ *
+ */
+static inline void devices_get ( void ) {
+ device_keep_count++;
+}
+
+/**
+ * Allow devices to be removed on shutdown
+ *
+ */
+static inline void devices_put ( void ) {
+ device_keep_count--;
+}
+
+extern struct device * identify_device ( struct interface *intf );
+#define identify_device_TYPE( object_type ) \
+ typeof ( struct device * ( object_type ) )
+
+#endif /* _IPXE_DEVICE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/dhcp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/dhcp.h
new file mode 100644
index 00000000..34b4d3fd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/dhcp.h
@@ -0,0 +1,678 @@
+#ifndef _IPXE_DHCP_H
+#define _IPXE_DHCP_H
+
+/** @file
+ *
+ * Dynamic Host Configuration Protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <ipxe/in.h>
+#include <ipxe/list.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/tables.h>
+#include <ipxe/uuid.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/uaccess.h>
+
+struct interface;
+struct dhcp_options;
+struct dhcp_packet;
+
+/** BOOTP/DHCP server port */
+#define BOOTPS_PORT 67
+
+/** BOOTP/DHCP client port */
+#define BOOTPC_PORT 68
+
+/** PXE server port */
+#define PXE_PORT 4011
+
+/** Construct a tag value for an encapsulated option
+ *
+ * This tag value can be passed to Etherboot functions when searching
+ * for DHCP options in order to search for a tag within an
+ * encapsulated options block.
+ */
+#define DHCP_ENCAP_OPT( encapsulator, encapsulated ) \
+ ( ( (encapsulator) << 8 ) | (encapsulated) )
+/** Extract encapsulating option block tag from encapsulated tag value */
+#define DHCP_ENCAPSULATOR( encap_opt ) ( (encap_opt) >> 8 )
+/** Extract encapsulated option tag from encapsulated tag value */
+#define DHCP_ENCAPSULATED( encap_opt ) ( (encap_opt) & 0xff )
+/** Option is encapsulated */
+#define DHCP_IS_ENCAP_OPT( opt ) DHCP_ENCAPSULATOR( opt )
+
+/**
+ * @defgroup dhcpopts DHCP option tags
+ * @{
+ */
+
+/** Padding
+ *
+ * This tag does not have a length field; it is always only a single
+ * byte in length.
+ */
+#define DHCP_PAD 0
+
+/** Minimum normal DHCP option */
+#define DHCP_MIN_OPTION 1
+
+/** Subnet mask */
+#define DHCP_SUBNET_MASK 1
+
+/** Routers */
+#define DHCP_ROUTERS 3
+
+/** DNS servers */
+#define DHCP_DNS_SERVERS 6
+
+/** Syslog servers */
+#define DHCP_LOG_SERVERS 7
+
+/** Host name */
+#define DHCP_HOST_NAME 12
+
+/** Domain name */
+#define DHCP_DOMAIN_NAME 15
+
+/** Root path */
+#define DHCP_ROOT_PATH 17
+
+/** Vendor encapsulated options */
+#define DHCP_VENDOR_ENCAP 43
+
+/** PXE boot server discovery control */
+#define DHCP_PXE_DISCOVERY_CONTROL DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 6 )
+
+/** PXE boot server discovery control bits */
+enum dhcp_pxe_discovery_control {
+ /** Inhibit broadcast discovery */
+ PXEBS_NO_BROADCAST = 1,
+ /** Inhibit multicast discovery */
+ PXEBS_NO_MULTICAST = 2,
+ /** Accept only servers in DHCP_PXE_BOOT_SERVERS list */
+ PXEBS_NO_UNKNOWN_SERVERS = 4,
+ /** Skip discovery if filename present */
+ PXEBS_SKIP = 8,
+};
+
+/** PXE boot server multicast address */
+#define DHCP_PXE_BOOT_SERVER_MCAST DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 7 )
+
+/** PXE boot servers */
+#define DHCP_PXE_BOOT_SERVERS DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 8 )
+
+/** PXE boot server */
+struct dhcp_pxe_boot_server {
+ /** "Type" */
+ uint16_t type;
+ /** Number of IPv4 addresses */
+ uint8_t num_ip;
+ /** IPv4 addresses */
+ struct in_addr ip[0];
+} __attribute__ (( packed ));
+
+/** PXE boot menu */
+#define DHCP_PXE_BOOT_MENU DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 9 )
+
+/** PXE boot menu */
+struct dhcp_pxe_boot_menu {
+ /** "Type" */
+ uint16_t type;
+ /** Description length */
+ uint8_t desc_len;
+ /** Description */
+ char desc[0];
+} __attribute__ (( packed ));
+
+/** PXE boot menu prompt */
+#define DHCP_PXE_BOOT_MENU_PROMPT DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 10 )
+
+/** PXE boot menu prompt */
+struct dhcp_pxe_boot_menu_prompt {
+ /** Timeout
+ *
+ * A value of 0 means "time out immediately and select first
+ * boot item, without displaying the prompt". A value of 255
+ * means "display menu immediately with no timeout". Any
+ * other value means "display prompt, wait this many seconds
+ * for keypress, if key is F8, display menu, otherwise select
+ * first boot item".
+ */
+ uint8_t timeout;
+ /** Prompt to press F8 */
+ char prompt[0];
+} __attribute__ (( packed ));
+
+/** PXE boot menu item */
+#define DHCP_PXE_BOOT_MENU_ITEM DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 71 )
+
+/** PXE boot menu item */
+struct dhcp_pxe_boot_menu_item {
+ /** "Type"
+ *
+ * This field actually identifies the specific boot server (or
+ * cluster of boot servers offering identical boot files).
+ */
+ uint16_t type;
+ /** "Layer"
+ *
+ * Just don't ask.
+ */
+ uint16_t layer;
+} __attribute__ (( packed ));
+
+/** Requested IP address */
+#define DHCP_REQUESTED_ADDRESS 50
+
+/** Lease time */
+#define DHCP_LEASE_TIME 51
+
+/** Option overloading
+ *
+ * The value of this option is the bitwise-OR of zero or more
+ * DHCP_OPTION_OVERLOAD_XXX constants.
+ */
+#define DHCP_OPTION_OVERLOAD 52
+
+/** The "file" field is overloaded to contain extra DHCP options */
+#define DHCP_OPTION_OVERLOAD_FILE 1
+
+/** The "sname" field is overloaded to contain extra DHCP options */
+#define DHCP_OPTION_OVERLOAD_SNAME 2
+
+/** DHCP message type */
+#define DHCP_MESSAGE_TYPE 53
+#define DHCPNONE 0
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNAK 6
+#define DHCPRELEASE 7
+#define DHCPINFORM 8
+
+/** DHCP server identifier */
+#define DHCP_SERVER_IDENTIFIER 54
+
+/** Parameter request list */
+#define DHCP_PARAMETER_REQUEST_LIST 55
+
+/** Maximum DHCP message size */
+#define DHCP_MAX_MESSAGE_SIZE 57
+
+/** Vendor class identifier */
+#define DHCP_VENDOR_CLASS_ID 60
+
+/** Client identifier */
+#define DHCP_CLIENT_ID 61
+
+/** Client identifier */
+struct dhcp_client_id {
+ /** Link-layer protocol */
+ uint8_t ll_proto;
+ /** Link-layer address */
+ uint8_t ll_addr[MAX_LL_ADDR_LEN];
+} __attribute__ (( packed ));
+
+/** TFTP server name
+ *
+ * This option replaces the fixed "sname" field, when that field is
+ * used to contain overloaded options.
+ */
+#define DHCP_TFTP_SERVER_NAME 66
+
+/** Bootfile name
+ *
+ * This option replaces the fixed "file" field, when that field is
+ * used to contain overloaded options.
+ */
+#define DHCP_BOOTFILE_NAME 67
+
+/** User class identifier */
+#define DHCP_USER_CLASS_ID 77
+
+/** Client system architecture */
+#define DHCP_CLIENT_ARCHITECTURE 93
+
+/** DHCP client architecture */
+struct dhcp_client_architecture {
+ uint16_t arch;
+} __attribute__ (( packed ));
+
+/** DHCP client architecture values
+ *
+ * These are defined by the PXE specification and redefined by
+ * RFC4578.
+ */
+enum dhcp_client_architecture_values {
+ /** Intel x86 PC */
+ DHCP_CLIENT_ARCHITECTURE_X86 = 0x0000,
+ /** NEC/PC98 */
+ DHCP_CLIENT_ARCHITECTURE_PC98 = 0x0001,
+ /** EFI Itanium */
+ DHCP_CLIENT_ARCHITECTURE_IA64 = 0x0002,
+ /** DEC Alpha */
+ DHCP_CLIENT_ARCHITECTURE_ALPHA = 0x0003,
+ /** Arc x86 */
+ DHCP_CLIENT_ARCHITECTURE_ARCX86 = 0x0004,
+ /** Intel Lean Client */
+ DHCP_CLIENT_ARCHITECTURE_LC = 0x0005,
+ /** EFI IA32 */
+ DHCP_CLIENT_ARCHITECTURE_IA32 = 0x0006,
+ /** EFI BC */
+ DHCP_CLIENT_ARCHITECTURE_EFI = 0x0007,
+ /** EFI Xscale */
+ DHCP_CLIENT_ARCHITECTURE_XSCALE = 0x0008,
+ /** EFI x86-64 */
+ DHCP_CLIENT_ARCHITECTURE_X86_64 = 0x0009,
+};
+
+/** Client network device interface */
+#define DHCP_CLIENT_NDI 94
+
+/** UUID client identifier */
+#define DHCP_CLIENT_UUID 97
+
+/** UUID client identifier */
+struct dhcp_client_uuid {
+ /** Identifier type */
+ uint8_t type;
+ /** UUID */
+ union uuid uuid;
+} __attribute__ (( packed ));
+
+#define DHCP_CLIENT_UUID_TYPE 0
+
+/** Etherboot-specific encapsulated options
+ *
+ * This encapsulated options field is used to contain all options
+ * specific to Etherboot (i.e. not assigned by IANA or other standards
+ * bodies).
+ */
+#define DHCP_EB_ENCAP 175
+
+/** Priority of this options block
+ *
+ * This is a signed 8-bit integer field indicating the priority of
+ * this block of options. It can be used to specify the relative
+ * priority of multiple option blocks (e.g. options from non-volatile
+ * storage versus options from a DHCP server).
+ */
+#define DHCP_EB_PRIORITY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x01 )
+
+/** "Your" IP address
+ *
+ * This option is used internally to contain the value of the "yiaddr"
+ * field, in order to provide a consistent approach to storing and
+ * processing options. It should never be present in a DHCP packet.
+ */
+#define DHCP_EB_YIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x02 )
+
+/** "Server" IP address
+ *
+ * This option is used internally to contain the value of the "siaddr"
+ * field, in order to provide a consistent approach to storing and
+ * processing options. It should never be present in a DHCP packet.
+ */
+#define DHCP_EB_SIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x03 )
+
+/** Keep SAN drive registered
+ *
+ * If set to a non-zero value, iPXE will not detach any SAN drive
+ * after failing to boot from it. (This option is required in order
+ * to perform an installation direct to an iSCSI target.)
+ */
+#define DHCP_EB_KEEP_SAN DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x08 )
+
+/** Skip booting from SAN drive
+ *
+ * If set to a non-zero value, iPXE will skip booting from any SAN
+ * drive. (This option is sometimes required in conjunction with @c
+ * DHCP_EB_KEEP_SAN in order to perform an installation direct to an
+ * iSCSI target.)
+ */
+#define DHCP_EB_SKIP_SAN_BOOT DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x09 )
+
+/*
+ * Tags in the range 0x10-0x4f are reserved for feature markers
+ *
+ */
+
+/** Scriptlet
+ *
+ * If a scriptlet exists, it will be executed in place of the usual
+ * call to autoboot()
+ */
+#define DHCP_EB_SCRIPTLET DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x51 )
+
+/** Encrypted syslog server */
+#define DHCP_EB_SYSLOGS_SERVER DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x55 )
+
+/** Trusted root certficate fingerprints */
+#define DHCP_EB_TRUST DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x5a )
+
+/** Client certficate */
+#define DHCP_EB_CERT DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x5b )
+
+/** Client private key */
+#define DHCP_EB_KEY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x5c )
+
+/** Cross-signed certificate source */
+#define DHCP_EB_CROSS_CERT DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x5d )
+
+/** Skip PXE DHCP protocol extensions such as ProxyDHCP
+ *
+ * If set to a non-zero value, iPXE will not wait for ProxyDHCP offers
+ * and will ignore any PXE-specific DHCP options that it receives.
+ */
+#define DHCP_EB_NO_PXEDHCP DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xb0 )
+
+/** Network device descriptor
+ *
+ * Byte 0 is the bus type ID; remaining bytes depend on the bus type.
+ *
+ * PCI devices:
+ * Byte 0 : 1 (PCI)
+ * Byte 1 : PCI vendor ID MSB
+ * Byte 2 : PCI vendor ID LSB
+ * Byte 3 : PCI device ID MSB
+ * Byte 4 : PCI device ID LSB
+ */
+#define DHCP_EB_BUS_ID DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xb1 )
+
+/** Network device descriptor */
+struct dhcp_netdev_desc {
+ /** Bus type ID */
+ uint8_t type;
+ /** Vendor ID */
+ uint16_t vendor;
+ /** Device ID */
+ uint16_t device;
+} __attribute__ (( packed ));
+
+/** Use cached network settings
+ *
+ * Cached network settings may be available from a prior DHCP request
+ * (if running as a PXE NBP), non-volatile storage on the NIC, or
+ * settings set via the command line or an embedded image. If this
+ * flag is not set, it will be assumed that those sources are
+ * insufficient and that DHCP should still be run when autobooting.
+ */
+#define DHCP_EB_USE_CACHED DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xb2 )
+
+/** BIOS drive number
+ *
+ * This is the drive number for a drive emulated via INT 13. 0x80 is
+ * the first hard disk, 0x81 is the second hard disk, etc.
+ */
+#define DHCP_EB_BIOS_DRIVE DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbd )
+
+/** Username
+ *
+ * This will be used as the username for any required authentication.
+ * It is expected that this option's value will be held in
+ * non-volatile storage, rather than transmitted as part of a DHCP
+ * packet.
+ */
+#define DHCP_EB_USERNAME DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbe )
+
+/** Password
+ *
+ * This will be used as the password for any required authentication.
+ * It is expected that this option's value will be held in
+ * non-volatile storage, rather than transmitted as part of a DHCP
+ * packet.
+ */
+#define DHCP_EB_PASSWORD DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbf )
+
+/** Reverse username
+ *
+ * This will be used as the reverse username (i.e. the username
+ * provided by the server) for any required authentication. It is
+ * expected that this option's value will be held in non-volatile
+ * storage, rather than transmitted as part of a DHCP packet.
+ */
+#define DHCP_EB_REVERSE_USERNAME DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xc0 )
+
+/** Reverse password
+ *
+ * This will be used as the reverse password (i.e. the password
+ * provided by the server) for any required authentication. It is
+ * expected that this option's value will be held in non-volatile
+ * storage, rather than transmitted as part of a DHCP packet.
+ */
+#define DHCP_EB_REVERSE_PASSWORD DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xc1 )
+
+/** iPXE version number */
+#define DHCP_EB_VERSION DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xeb )
+
+/** iSCSI primary target IQN */
+#define DHCP_ISCSI_PRIMARY_TARGET_IQN 201
+
+/** iSCSI secondary target IQN */
+#define DHCP_ISCSI_SECONDARY_TARGET_IQN 202
+
+/** iSCSI initiator IQN */
+#define DHCP_ISCSI_INITIATOR_IQN 203
+
+/** Maximum normal DHCP option */
+#define DHCP_MAX_OPTION 254
+
+/** End of options
+ *
+ * This tag does not have a length field; it is always only a single
+ * byte in length.
+ */
+#define DHCP_END 255
+
+/** @} */
+
+/** Construct a DHCP option from a list of bytes */
+#define DHCP_OPTION( ... ) VA_ARG_COUNT ( __VA_ARGS__ ), __VA_ARGS__
+
+/** Construct a DHCP option from a list of characters */
+#define DHCP_STRING( ... ) DHCP_OPTION ( __VA_ARGS__ )
+
+/** Construct a byte-valued DHCP option */
+#define DHCP_BYTE( value ) DHCP_OPTION ( value )
+
+/** Construct a word-valued DHCP option */
+#define DHCP_WORD( value ) DHCP_OPTION ( ( ( (value) >> 8 ) & 0xff ), \
+ ( ( (value) >> 0 ) & 0xff ) )
+
+/** Construct a dword-valued DHCP option */
+#define DHCP_DWORD( value ) DHCP_OPTION ( ( ( (value) >> 24 ) & 0xff ), \
+ ( ( (value) >> 16 ) & 0xff ), \
+ ( ( (value) >> 8 ) & 0xff ), \
+ ( ( (value) >> 0 ) & 0xff ) )
+
+/** Construct a DHCP encapsulated options field */
+#define DHCP_ENCAP( ... ) DHCP_OPTION ( __VA_ARGS__, DHCP_END )
+
+/**
+ * A DHCP option
+ *
+ * DHCP options consist of a mandatory tag, a length field that is
+ * mandatory for all options except @c DHCP_PAD and @c DHCP_END, and a
+ * payload.
+ */
+struct dhcp_option {
+ /** Tag
+ *
+ * Must be a @c DHCP_XXX value.
+ */
+ uint8_t tag;
+ /** Length
+ *
+ * This is the length of the data field (i.e. excluding the
+ * tag and length fields). For the two tags @c DHCP_PAD and
+ * @c DHCP_END, the length field is implicitly zero and is
+ * also missing, i.e. these DHCP options are only a single
+ * byte in length.
+ */
+ uint8_t len;
+ /** Option data */
+ uint8_t data[0];
+} __attribute__ (( packed ));
+
+/**
+ * Length of a DHCP option header
+ *
+ * The header is the portion excluding the data, i.e. the tag and the
+ * length.
+ */
+#define DHCP_OPTION_HEADER_LEN ( offsetof ( struct dhcp_option, data ) )
+
+/** Maximum length for a single DHCP option */
+#define DHCP_MAX_LEN 0xff
+
+/**
+ * A DHCP header
+ *
+ */
+struct dhcphdr {
+ /** Operation
+ *
+ * This must be either @c BOOTP_REQUEST or @c BOOTP_REPLY.
+ */
+ uint8_t op;
+ /** Hardware address type
+ *
+ * This is an ARPHRD_XXX constant. Note that ARPHRD_XXX
+ * constants are nominally 16 bits wide; this could be
+ * considered to be a bug in the BOOTP/DHCP specification.
+ */
+ uint8_t htype;
+ /** Hardware address length */
+ uint8_t hlen;
+ /** Number of hops from server */
+ uint8_t hops;
+ /** Transaction ID */
+ uint32_t xid;
+ /** Seconds since start of acquisition */
+ uint16_t secs;
+ /** Flags */
+ uint16_t flags;
+ /** "Client" IP address
+ *
+ * This is filled in if the client already has an IP address
+ * assigned and can respond to ARP requests.
+ */
+ struct in_addr ciaddr;
+ /** "Your" IP address
+ *
+ * This is the IP address assigned by the server to the client.
+ */
+ struct in_addr yiaddr;
+ /** "Server" IP address
+ *
+ * This is the IP address of the next server to be used in the
+ * boot process.
+ */
+ struct in_addr siaddr;
+ /** "Gateway" IP address
+ *
+ * This is the IP address of the DHCP relay agent, if any.
+ */
+ struct in_addr giaddr;
+ /** Client hardware address */
+ uint8_t chaddr[16];
+ /** Server host name (null terminated)
+ *
+ * This field may be overridden and contain DHCP options
+ */
+ char sname[64];
+ /** Boot file name (null terminated)
+ *
+ * This field may be overridden and contain DHCP options
+ */
+ char file[128];
+ /** DHCP magic cookie
+ *
+ * Must have the value @c DHCP_MAGIC_COOKIE.
+ */
+ uint32_t magic;
+ /** DHCP options
+ *
+ * Variable length; extends to the end of the packet. Minimum
+ * length (for the sake of sanity) is 1, to allow for a single
+ * @c DHCP_END tag.
+ */
+ uint8_t options[0];
+};
+
+/** Opcode for a request from client to server */
+#define BOOTP_REQUEST 1
+
+/** Opcode for a reply from server to client */
+#define BOOTP_REPLY 2
+
+/** BOOTP reply must be broadcast
+ *
+ * Clients that cannot accept unicast BOOTP replies must set this
+ * flag.
+ */
+#define BOOTP_FL_BROADCAST 0x8000
+
+/** DHCP magic cookie */
+#define DHCP_MAGIC_COOKIE 0x63825363UL
+
+/** DHCP minimum packet length
+ *
+ * This is the mandated minimum packet length that a DHCP participant
+ * must be prepared to receive.
+ */
+#define DHCP_MIN_LEN 552
+
+/** Timeouts for sending DHCP packets */
+#define DHCP_MIN_TIMEOUT ( 1 * TICKS_PER_SEC )
+#define DHCP_MAX_TIMEOUT ( 10 * TICKS_PER_SEC )
+
+/** Maximum time that we will wait for ProxyDHCP responses */
+#define PROXYDHCP_MAX_TIMEOUT ( 2 * TICKS_PER_SEC )
+
+/** Maximum time that we will wait for Boot Server responses */
+#define PXEBS_MAX_TIMEOUT ( 3 * TICKS_PER_SEC )
+
+/** Settings block name used for DHCP responses */
+#define DHCP_SETTINGS_NAME "dhcp"
+
+/** Settings block name used for ProxyDHCP responses */
+#define PROXYDHCP_SETTINGS_NAME "proxydhcp"
+
+/** Setting block name used for BootServerDHCP responses */
+#define PXEBS_SETTINGS_NAME "pxebs"
+
+extern uint32_t dhcp_last_xid;
+extern unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr,
+ uint16_t *flags );
+extern int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev, uint8_t msgtype,
+ uint32_t xid, const void *options,
+ size_t options_len, void *data,
+ size_t max_len );
+extern int dhcp_create_request ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev,
+ unsigned int msgtype, uint32_t xid,
+ struct in_addr ciaddr,
+ void *data, size_t max_len );
+extern int start_dhcp ( struct interface *job, struct net_device *netdev );
+extern int start_pxebs ( struct interface *job, struct net_device *netdev,
+ unsigned int pxe_type );
+
+/* In environments that can provide cached DHCP packets, this function
+ * should look for such a packet and call store_cached_dhcpack() with
+ * it if it exists.
+ */
+extern void get_cached_dhcpack ( void );
+
+extern void store_cached_dhcpack ( userptr_t data, size_t len );
+
+#endif /* _IPXE_DHCP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/dhcpopts.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/dhcpopts.h
new file mode 100644
index 00000000..c5af5d74
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/dhcpopts.h
@@ -0,0 +1,43 @@
+#ifndef _IPXE_DHCPOPTS_H
+#define _IPXE_DHCPOPTS_H
+
+/** @file
+ *
+ * DHCP options
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/** A DHCP options block */
+struct dhcp_options {
+ /** Option block raw data */
+ void *data;
+ /** Option block used length */
+ size_t used_len;
+ /** Option block allocated length */
+ size_t alloc_len;
+ /** Reallocate option block raw data
+ *
+ * @v options DHCP option block
+ * @v len New length
+ * @ret rc Return status code
+ */
+ int ( * realloc ) ( struct dhcp_options *options, size_t len );
+};
+
+extern int dhcpopt_applies ( unsigned int tag );
+extern int dhcpopt_store ( struct dhcp_options *options, unsigned int tag,
+ const void *data, size_t len );
+extern int dhcpopt_fetch ( struct dhcp_options *options, unsigned int tag,
+ void *data, size_t len );
+extern void dhcpopt_init ( struct dhcp_options *options,
+ void *data, size_t alloc_len,
+ int ( * realloc ) ( struct dhcp_options *options,
+ size_t len ) );
+extern void dhcpopt_update_used_len ( struct dhcp_options *options );
+extern int dhcpopt_no_realloc ( struct dhcp_options *options, size_t len );
+
+#endif /* _IPXE_DHCPOPTS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/dhcppkt.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/dhcppkt.h
new file mode 100644
index 00000000..3179a6bb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/dhcppkt.h
@@ -0,0 +1,71 @@
+#ifndef _IPXE_DHCPPKT_H
+#define _IPXE_DHCPPKT_H
+
+/** @file
+ *
+ * DHCP packets
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/dhcp.h>
+#include <ipxe/dhcpopts.h>
+#include <ipxe/refcnt.h>
+
+/**
+ * A DHCP packet
+ *
+ */
+struct dhcp_packet {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** The DHCP packet contents */
+ struct dhcphdr *dhcphdr;
+ /** DHCP options */
+ struct dhcp_options options;
+ /** Settings interface */
+ struct settings settings;
+};
+
+/**
+ * Increment reference count on DHCP packet
+ *
+ * @v dhcppkt DHCP packet
+ * @ret dhcppkt DHCP packet
+ */
+static inline __attribute__ (( always_inline )) struct dhcp_packet *
+dhcppkt_get ( struct dhcp_packet *dhcppkt ) {
+ ref_get ( &dhcppkt->refcnt );
+ return dhcppkt;
+}
+
+/**
+ * Decrement reference count on DHCP packet
+ *
+ * @v dhcppkt DHCP packet
+ */
+static inline __attribute__ (( always_inline )) void
+dhcppkt_put ( struct dhcp_packet *dhcppkt ) {
+ ref_put ( &dhcppkt->refcnt );
+}
+
+/**
+ * Get used length of DHCP packet
+ *
+ * @v dhcppkt DHCP packet
+ * @ret len Used length
+ */
+static inline int dhcppkt_len ( struct dhcp_packet *dhcppkt ) {
+ return ( offsetof ( struct dhcphdr, options ) +
+ dhcppkt->options.used_len );
+}
+
+extern int dhcppkt_store ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ const void *data, size_t len );
+extern int dhcppkt_fetch ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ void *data, size_t len );
+extern void dhcppkt_init ( struct dhcp_packet *dhcppkt,
+ struct dhcphdr *data, size_t len );
+
+#endif /* _IPXE_DHCPPKT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/dns.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/dns.h
new file mode 100644
index 00000000..1c427601
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/dns.h
@@ -0,0 +1,92 @@
+#ifndef _IPXE_DNS_H
+#define _IPXE_DNS_H
+
+/** @file
+ *
+ * DNS protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/in.h>
+
+/*
+ * Constants
+ *
+ */
+
+#define DNS_TYPE_A 1
+#define DNS_TYPE_CNAME 5
+#define DNS_TYPE_ANY 255
+
+#define DNS_CLASS_IN 1
+#define DNS_CLASS_CS 2
+#define DNS_CLASS_CH 3
+#define DNS_CLASS_HS 4
+
+#define DNS_FLAG_QUERY ( 0x00 << 15 )
+#define DNS_FLAG_RESPONSE ( 0x01 << 15 )
+#define DNS_FLAG_QR(flags) ( (flags) & ( 0x01 << 15 ) )
+#define DNS_FLAG_OPCODE_QUERY ( 0x00 << 11 )
+#define DNS_FLAG_OPCODE_IQUERY ( 0x01 << 11 )
+#define DNS_FLAG_OPCODE_STATUS ( 0x02 << 11 )
+#define DNS_FLAG_OPCODE(flags) ( (flags) & ( 0x0f << 11 ) )
+#define DNS_FLAG_RD ( 0x01 << 8 )
+#define DNS_FLAG_RA ( 0x01 << 7 )
+#define DNS_FLAG_RCODE_OK ( 0x00 << 0 )
+#define DNS_FLAG_RCODE_NX ( 0x03 << 0 )
+#define DNS_FLAG_RCODE(flags) ( (flags) & ( 0x0f << 0 ) )
+
+#define DNS_PORT 53
+#define DNS_MAX_RETRIES 3
+#define DNS_MAX_CNAME_RECURSION 0x30
+
+/*
+ * DNS protocol structures
+ *
+ */
+struct dns_header {
+ uint16_t id;
+ uint16_t flags;
+ uint16_t qdcount;
+ uint16_t ancount;
+ uint16_t nscount;
+ uint16_t arcount;
+} __attribute__ (( packed ));
+
+struct dns_query_info {
+ uint16_t qtype;
+ uint16_t qclass;
+} __attribute__ (( packed ));
+
+struct dns_query {
+ struct dns_header dns;
+ char payload[ 256 + sizeof ( struct dns_query_info ) ];
+} __attribute__ (( packed ));
+
+struct dns_rr_info_common {
+ uint16_t type;
+ uint16_t class;
+ uint32_t ttl;
+ uint16_t rdlength;
+} __attribute__ (( packed ));
+
+struct dns_rr_info_a {
+ struct dns_rr_info_common common;
+ struct in_addr in_addr;
+} __attribute__ (( packed ));
+
+struct dns_rr_info_cname {
+ struct dns_rr_info_common common;
+ char cname[0];
+} __attribute__ (( packed ));
+
+union dns_rr_info {
+ struct dns_rr_info_common common;
+ struct dns_rr_info_a a;
+ struct dns_rr_info_cname cname;
+};
+
+#endif /* _IPXE_DNS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/downloader.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/downloader.h
new file mode 100644
index 00000000..a7efa3f7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/downloader.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_DOWNLOADER_H
+#define _IPXE_DOWNLOADER_H
+
+/** @file
+ *
+ * Image downloader
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct interface;
+struct image;
+
+extern int create_downloader ( struct interface *job, struct image *image,
+ int type, ... );
+
+#endif /* _IPXE_DOWNLOADER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/drbg.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/drbg.h
new file mode 100644
index 00000000..6374e778
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/drbg.h
@@ -0,0 +1,135 @@
+#ifndef _IPXE_DRBG_H
+#define _IPXE_DRBG_H
+
+/** @file
+ *
+ * DRBG mechanism
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/sha256.h>
+#include <ipxe/hmac_drbg.h>
+
+/** Choose HMAC_DRBG using SHA-256
+ *
+ * HMAC_DRBG using SHA-256 is an Approved algorithm in ANS X9.82.
+ */
+#define HMAC_DRBG_ALGORITHM HMAC_DRBG_SHA256
+
+/** Maximum security strength */
+#define DRBG_MAX_SECURITY_STRENGTH \
+ HMAC_DRBG_MAX_SECURITY_STRENGTH ( HMAC_DRBG_ALGORITHM )
+
+/** Security strength
+ *
+ * We choose to operate at a strength of 128 bits.
+ */
+#define DRBG_SECURITY_STRENGTH 128
+
+/** Minimum entropy input length */
+#define DRBG_MIN_ENTROPY_LEN_BYTES \
+ HMAC_DRBG_MIN_ENTROPY_LEN_BYTES ( DRBG_SECURITY_STRENGTH )
+
+/** Maximum entropy input length */
+#define DRBG_MAX_ENTROPY_LEN_BYTES HMAC_DRBG_MAX_ENTROPY_LEN_BYTES
+
+/** Maximum personalisation string length */
+#define DRBG_MAX_PERSONAL_LEN_BYTES HMAC_DRBG_MAX_PERSONAL_LEN_BYTES
+
+/** Maximum additional input length */
+#define DRBG_MAX_ADDITIONAL_LEN_BYTES HMAC_DRBG_MAX_ADDITIONAL_LEN_BYTES
+
+/** Maximum length of generated pseudorandom data per request */
+#define DRBG_MAX_GENERATED_LEN_BYTES HMAC_DRBG_MAX_GENERATED_LEN_BYTES
+
+/** A Deterministic Random Bit Generator */
+struct drbg_state {
+ /** Algorithm internal state */
+ struct hmac_drbg_state internal;
+ /** Reseed required flag */
+ int reseed_required;
+ /** State is valid */
+ int valid;
+};
+
+/**
+ * Instantiate DRBG algorithm
+ *
+ * @v state Algorithm state
+ * @v entropy Entropy input
+ * @v entropy_len Length of entropy input
+ * @v personal Personalisation string
+ * @v personal_len Length of personalisation string
+ *
+ * This is the Instantiate_algorithm function defined in ANS X9.82
+ * Part 3-2007 Section 9.2 (NIST SP 800-90 Section 9.1).
+ */
+static inline void drbg_instantiate_algorithm ( struct drbg_state *state,
+ const void *entropy,
+ size_t entropy_len,
+ const void *personal,
+ size_t personal_len ) {
+ hmac_drbg_instantiate ( HMAC_DRBG_HASH ( HMAC_DRBG_ALGORITHM ),
+ &state->internal, entropy, entropy_len,
+ personal, personal_len );
+}
+
+/**
+ * Reseed DRBG algorithm
+ *
+ * @v state Algorithm state
+ * @v entropy Entropy input
+ * @v entropy_len Length of entropy input
+ * @v additional Additional input
+ * @v additional_len Length of additional input
+ *
+ * This is the Reseed_algorithm function defined in ANS X9.82
+ * Part 3-2007 Section 9.3 (NIST SP 800-90 Section 9.2).
+ */
+static inline void drbg_reseed_algorithm ( struct drbg_state *state,
+ const void *entropy,
+ size_t entropy_len,
+ const void *additional,
+ size_t additional_len ) {
+ hmac_drbg_reseed ( HMAC_DRBG_HASH ( HMAC_DRBG_ALGORITHM ),
+ &state->internal, entropy, entropy_len,
+ additional, additional_len );
+}
+
+/**
+ * Generate pseudorandom bits using DRBG algorithm
+ *
+ * @v state Algorithm state
+ * @v additional Additional input
+ * @v additional_len Length of additional input
+ * @v data Output buffer
+ * @v len Length of output buffer
+ * @ret rc Return status code
+ *
+ * This is the Generate_algorithm function defined in ANS X9.82
+ * Part 3-2007 Section 9.4 (NIST SP 800-90 Section 9.3).
+ *
+ * Note that the only permitted error is "reseed required".
+ */
+static inline int drbg_generate_algorithm ( struct drbg_state *state,
+ const void *additional,
+ size_t additional_len,
+ void *data, size_t len ) {
+ return hmac_drbg_generate ( HMAC_DRBG_HASH ( HMAC_DRBG_ALGORITHM ),
+ &state->internal, additional,
+ additional_len, data, len );
+}
+
+extern int drbg_instantiate ( struct drbg_state *state, const void *personal,
+ size_t personal_len );
+extern int drbg_reseed ( struct drbg_state *state, const void *additional,
+ size_t additional_len );
+extern int drbg_generate ( struct drbg_state *state, const void *additional,
+ size_t additional_len, int prediction_resist,
+ void *data, size_t len );
+extern void drbg_uninstantiate ( struct drbg_state *state );
+
+#endif /* _IPXE_DRBG_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/eapol.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/eapol.h
new file mode 100644
index 00000000..3fad4428
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/eapol.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _IPXE_EAPOL_H
+#define _IPXE_EAPOL_H
+
+/** @file
+ *
+ * Definitions for EAPOL (Extensible Authentication Protocol over
+ * LANs) frames. Definitions for the packets usually encapsulated in
+ * them are elsewhere.
+ */
+
+#include <ipxe/tables.h>
+#include <stdint.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+
+/**
+ * @defgroup eapol_type EAPOL archetype identifiers
+ * @{
+ */
+#define EAPOL_TYPE_EAP 0 /**< EAP authentication handshake packet */
+#define EAPOL_TYPE_START 1 /**< Request by Peer to begin (no data) */
+#define EAPOL_TYPE_LOGOFF 2 /**< Request by Peer to terminate (no data) */
+#define EAPOL_TYPE_KEY 3 /**< EAPOL-Key packet */
+/** @} */
+
+/** Expected EAPOL version field value
+ *
+ * Version 2 is often seen and has no format differences from version 1;
+ * however, many older APs will completely drop version-2 packets, so
+ * we advertise ourselves as version 1.
+ */
+#define EAPOL_THIS_VERSION 1
+
+/** Length of an EAPOL frame header */
+#define EAPOL_HDR_LEN 4
+
+/** An EAPOL frame
+ *
+ * This may encapsulate an eap_pkt, an eapol_key_pkt, or a Start or
+ * Logoff request with no data attached. It is transmitted directly in
+ * an Ethernet frame, with no IP packet header.
+ */
+struct eapol_frame
+{
+ /** EAPOL version identifier, always 1 */
+ u8 version;
+
+ /** EAPOL archetype identifier indicating format of payload */
+ u8 type;
+
+ /** Length of payload, in network byte order */
+ u16 length;
+
+ /** Payload, if @a type is EAP or EAPOL-Key */
+ u8 data[0];
+} __attribute__ (( packed ));
+
+
+/** An EAPOL frame type handler
+ *
+ * Normally there will be at most two of these, one for EAP and one
+ * for EAPOL-Key frames. The EAPOL interface code handles Start and
+ * Logoff directly.
+ */
+struct eapol_handler
+{
+ /** EAPOL archetype identifier for payload this handler will handle */
+ u8 type;
+
+ /** Receive EAPOL-encapsulated packet of specified type
+ *
+ * @v iob I/O buffer containing packet payload
+ * @v netdev Network device from which packet was received
+ * @V ll_dest Destination link-layer address
+ * @v ll_source Source link-layer address
+ * @ret rc Return status code
+ *
+ * The I/O buffer will have the EAPOL header pulled off it, so
+ * @c iob->data points to the first byte of the payload.
+ *
+ * This function takes ownership of the I/O buffer passed to it.
+ */
+ int ( * rx ) ( struct io_buffer *iob, struct net_device *netdev,
+ const void *ll_dest, const void *ll_source );
+};
+
+#define EAPOL_HANDLERS __table ( struct eapol_handler, "eapol_handlers" )
+#define __eapol_handler __table_entry ( EAPOL_HANDLERS, 01 )
+
+
+extern struct net_protocol eapol_protocol __net_protocol;
+
+
+#endif /* _IPXE_EAPOL_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/edd.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/edd.h
new file mode 100644
index 00000000..0c25593d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/edd.h
@@ -0,0 +1,193 @@
+#ifndef _IPXE_EDD_H
+#define _IPXE_EDD_H
+
+/** @file
+ *
+ * Enhanced Disk Drive specification
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/interface.h>
+
+/** An EDD host bus type */
+struct edd_host_bus_type {
+ /** Type */
+ uint32_t type;
+} __attribute__ (( packed ));
+
+/** EDD bus type */
+#define EDD_BUS_TYPE_FIXED( a, b, c, d, ... ) \
+ ( ( (a) << 0 ) | ( (b) << 8 ) | ( (c) << 16 ) | ( (d) << 24 ) )
+#define EDD_BUS_TYPE( ... ) \
+ EDD_BUS_TYPE_FIXED ( __VA_ARGS__, ' ', ' ', ' ', ' ' )
+/** EDD PCI bus type */
+#define EDD_BUS_TYPE_PCI EDD_BUS_TYPE ( 'P', 'C', 'I' )
+/** EDD ISA bus type */
+#define EDD_BUS_TYPE_ISA EDD_BUS_TYPE ( 'I', 'S', 'A' )
+/** EDD PCI-X bus type */
+#define EDD_BUS_TYPE_PCIX EDD_BUS_TYPE ( 'P', 'C', 'I', 'X' )
+/** EDD Infiniband bus type */
+#define EDD_BUS_TYPE_IBND EDD_BUS_TYPE ( 'I', 'B', 'N', 'D' )
+/** EDD PCI Express bus type */
+#define EDD_BUS_TYPE_XPRS EDD_BUS_TYPE ( 'X', 'P', 'R', 'S' )
+/** EDD HyperTransport bus type */
+#define EDD_BUS_TYPE_HTPT EDD_BUS_TYPE ( 'H', 'T', 'P', 'T' )
+
+/** An EDD interface type */
+struct edd_interface_type {
+ /** Type */
+ uint64_t type;
+} __attribute__ (( packed ));
+
+/** EDD interface type */
+#define EDD_INTF_TYPE_FIXED( a, b, c, d, e, f, g, h, ... ) \
+ ( ( ( ( uint64_t ) (a) ) << 0 ) | ( ( ( uint64_t ) (b) ) << 8 ) | \
+ ( ( ( uint64_t ) (c) ) << 16 ) | ( ( ( uint64_t ) (d) ) << 24 ) | \
+ ( ( ( uint64_t ) (e) ) << 32 ) | ( ( ( uint64_t ) (f) ) << 40 ) | \
+ ( ( ( uint64_t ) (g) ) << 48 ) | ( ( ( uint64_t ) (h) ) << 56 ) )
+#define EDD_INTF_TYPE( ... ) \
+ EDD_INTF_TYPE_FIXED ( __VA_ARGS__, \
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' )
+/** EDD ATA interface type */
+#define EDD_INTF_TYPE_ATA EDD_INTF_TYPE ( 'A', 'T', 'A' )
+/** EDD ATAPI interface type */
+#define EDD_INTF_TYPE_ATAPI EDD_INTF_TYPE ( 'A', 'T', 'A', 'P', 'I' )
+/** EDD SCSI interface type */
+#define EDD_INTF_TYPE_SCSI EDD_INTF_TYPE ( 'S', 'C', 'S', 'I' )
+/** EDD USB interface type */
+#define EDD_INTF_TYPE_USB EDD_INTF_TYPE ( 'U', 'S', 'B' )
+/** EDD 1394 interface type */
+#define EDD_INTF_TYPE_1394 EDD_INTF_TYPE ( '1', '3', '9', '4' )
+/** EDD Fibre Channel interface type */
+#define EDD_INTF_TYPE_FIBRE EDD_INTF_TYPE ( 'F', 'I', 'B', 'R', 'E' )
+/** EDD I2O interface type */
+#define EDD_INTF_TYPE_I2O EDD_INTF_TYPE ( 'I', '2', 'O' )
+/** EDD RAID interface type */
+#define EDD_INTF_TYPE_RAID EDD_INTF_TYPE ( 'R', 'A', 'I', 'D' )
+/** EDD SATA interface type */
+#define EDD_INTF_TYPE_SATA EDD_INTF_TYPE ( 'S', 'A', 'T', 'A' )
+/** EDD SAS interface type */
+#define EDD_INTF_TYPE_SAS EDD_INTF_TYPE ( 'S', 'A', 'S' )
+
+/** An EDD interface path */
+union edd_interface_path {
+ /** Legacy bus type */
+ struct {
+ /** Base address */
+ uint16_t base;
+ } __attribute__ (( packed )) legacy;
+ /** PCI, PCI-X, PCI Express, or HyperTransport bus type */
+ struct {
+ /** Bus */
+ uint8_t bus;
+ /** Slot */
+ uint8_t slot;
+ /** Function */
+ uint8_t function;
+ /** Channel number */
+ uint8_t channel;
+ } __attribute__ (( packed )) pci;
+ /** Padding */
+ uint8_t pad[8];
+} __attribute__ (( packed ));
+
+/** An EDD device path */
+union edd_device_path {
+ /** ATA interface type */
+ struct {
+ /** Slave */
+ uint8_t slave;
+ } __attribute__ (( packed )) ata;
+ /** ATAPI interface type */
+ struct {
+ /** Slave */
+ uint8_t slave;
+ /** Logical Unit Number */
+ uint8_t lun;
+ } __attribute__ (( packed )) atapi;
+ /** SCSI interface type */
+ struct {
+ /** SCSI ID */
+ uint16_t id;
+ /** Logical Unit Number */
+ uint64_t lun;
+ } __attribute__ (( packed )) scsi;
+ /** USB interface type */
+ struct {
+ /** Serial number */
+ uint64_t serial;
+ } __attribute__ (( packed )) usb;
+ /** IEEE1394 interface type */
+ struct {
+ /** GUID */
+ uint64_t guid;
+ } __attribute__ (( packed )) ieee1394;
+ /** Fibre Channel interface type */
+ struct {
+ /** WWN */
+ uint64_t wwn;
+ /** Logical Unit Number */
+ uint64_t lun;
+ } __attribute__ (( packed )) fibre;
+ /** I2O interface type */
+ struct {
+ /** Identity tag */
+ uint64_t tag;
+ } __attribute__ (( packed )) i2o;
+ /** RAID interface type */
+ struct {
+ /** Array number */
+ uint32_t array;
+ } __attribute__ (( packed )) raid;
+ /** SATA interface type */
+ struct {
+ /** Port number */
+ uint8_t port;
+ /** Port multiplier number */
+ uint8_t multiplier;
+ } __attribute__ (( packed )) sata;
+ /** SAS interface type */
+ struct {
+ /** Address */
+ uint64_t address;
+ } __attribute__ (( packed )) sas;
+ /** Padding */
+ uint8_t pad[16];
+} __attribute__ (( packed ));
+
+/** EDD device path information */
+struct edd_device_path_information {
+ /** Key */
+ uint16_t key;
+ /** Length of this structure */
+ uint8_t len;
+ /** Reserved */
+ uint8_t reserved_a[3];
+ /** Host bus type */
+ struct edd_host_bus_type host_bus_type;
+ /** Interface type */
+ struct edd_interface_type interface_type;
+ /** Interface path */
+ union edd_interface_path interface_path;
+ /** Device path */
+ union edd_device_path device_path;
+ /** Reserved */
+ uint8_t reserved_b;
+ /** Checksum */
+ uint8_t checksum;
+} __attribute__ (( packed ));
+
+/** EDD device path information key */
+#define EDD_DEVICE_PATH_INFO_KEY 0xbedd
+
+extern int edd_describe ( struct interface *intf,
+ struct edd_interface_type *type,
+ union edd_device_path *path );
+#define edd_describe_TYPE( object_type ) \
+ typeof ( int ( object_type, struct edd_interface_type *type, \
+ union edd_device_path *path ) )
+
+#endif /* _IPXE_EDD_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/editbox.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/editbox.h
new file mode 100644
index 00000000..9122dbbf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/editbox.h
@@ -0,0 +1,61 @@
+#ifndef _IPXE_EDITBOX_H
+#define _IPXE_EDITBOX_H
+
+/** @file
+ *
+ * Editable text box widget
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <curses.h>
+#include <ipxe/editstring.h>
+
+/** An editable text box widget */
+struct edit_box {
+ /** Editable string */
+ struct edit_string string;
+ /** Containing window */
+ WINDOW *win;
+ /** Row */
+ unsigned int row;
+ /** Starting column */
+ unsigned int col;
+ /** Width */
+ unsigned int width;
+ /** First displayed character */
+ unsigned int first;
+ /** Flags */
+ unsigned int flags;
+};
+
+/** Editable text box widget flags */
+enum edit_box_flags {
+ /** Show stars instead of contents (for password widgets) */
+ EDITBOX_STARS = 0x0001,
+};
+
+extern void init_editbox ( struct edit_box *box, char *buf, size_t len,
+ WINDOW *win, unsigned int row, unsigned int col,
+ unsigned int width, unsigned int flags )
+ __attribute__ (( nonnull (1, 2) ));
+extern void draw_editbox ( struct edit_box *box ) __nonnull;
+static inline int edit_editbox ( struct edit_box *box, int key ) __nonnull;
+
+/**
+ * Edit text box widget
+ *
+ * @v box Editable text box widget
+ * @v key Key pressed by user
+ * @ret key Key returned to application, or zero
+ *
+ * You must call draw_editbox() to update the display after calling
+ * edit_editbox().
+ *
+ */
+static inline int edit_editbox ( struct edit_box *box, int key ) {
+ return edit_string ( &box->string, key );
+}
+
+#endif /* _IPXE_EDITBOX_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/editstring.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/editstring.h
new file mode 100644
index 00000000..2ef546a6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/editstring.h
@@ -0,0 +1,48 @@
+#ifndef _IPXE_EDITSTRING_H
+#define _IPXE_EDITSTRING_H
+
+/** @file
+ *
+ * Editable strings
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** An editable string */
+struct edit_string {
+ /** Buffer for string */
+ char *buf;
+ /** Size of buffer (including terminating NUL) */
+ size_t len;
+ /** Cursor position */
+ unsigned int cursor;
+
+ /* The following items are the edit history */
+
+ /** Last cursor position */
+ unsigned int last_cursor;
+ /** Start of modified portion of string */
+ unsigned int mod_start;
+ /** End of modified portion of string */
+ unsigned int mod_end;
+};
+
+/**
+ * Initialise editable string
+ *
+ * @v string Editable string
+ * @v buf Buffer for string
+ * @v len Length of buffer
+ */
+static inline void init_editstring ( struct edit_string *string, char *buf,
+ size_t len ) {
+ string->buf = buf;
+ string->len = len;
+}
+
+extern void replace_string ( struct edit_string *string,
+ const char *replacement ) __nonnull;
+extern int edit_string ( struct edit_string *string, int key ) __nonnull;
+
+#endif /* _IPXE_EDITSTRING_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Base.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Base.h
new file mode 100644
index 00000000..999b4147
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Base.h
@@ -0,0 +1,965 @@
+/** @file
+ Root include file for Mde Package Base type modules
+
+ This is the include file for any module of type base. Base modules only use
+ types defined via this include file and can be ported easily to any
+ environment. There are a set of base libraries in the Mde Package that can
+ be used to implement base modules.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __BASE_H__
+#define __BASE_H__
+
+FILE_LICENCE ( BSD3 );
+
+//
+// Include processor specific binding
+//
+#include <ipxe/efi/ProcessorBind.h>
+
+
+/**
+ Verifies the storage size of a given data type.
+
+ This macro generates a divide by zero error or a zero size array declaration in
+ the preprocessor if the size is incorrect. These are declared as "extern" so
+ the space for these arrays will not be in the modules.
+
+ @param TYPE The date type to determine the size of.
+ @param Size The expected size for the TYPE.
+
+**/
+#define VERIFY_SIZE_OF(TYPE, Size) extern UINT8 _VerifySizeof##TYPE[(sizeof(TYPE) == (Size)) / (sizeof(TYPE) == (Size))]
+
+//
+// Verify that ProcessorBind.h produced UEFI Data Types that are compliant with
+// Section 2.3.1 of the UEFI 2.3 Specification.
+//
+VERIFY_SIZE_OF (BOOLEAN, 1);
+VERIFY_SIZE_OF (INT8, 1);
+VERIFY_SIZE_OF (UINT8, 1);
+VERIFY_SIZE_OF (INT16, 2);
+VERIFY_SIZE_OF (UINT16, 2);
+VERIFY_SIZE_OF (INT32, 4);
+VERIFY_SIZE_OF (UINT32, 4);
+VERIFY_SIZE_OF (INT64, 8);
+VERIFY_SIZE_OF (UINT64, 8);
+VERIFY_SIZE_OF (CHAR8, 1);
+VERIFY_SIZE_OF (CHAR16, 2);
+
+//
+// The Microsoft* C compiler can removed references to unreferenced data items
+// if the /OPT:REF linker option is used. We defined a macro as this is a
+// a non standard extension
+//
+#if defined(_MSC_EXTENSIONS) && !defined (MDE_CPU_EBC)
+ ///
+ /// Remove global variable from the linked image if there are no references to
+ /// it after all compiler and linker optimizations have been performed.
+ ///
+ ///
+ #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany)
+#else
+ ///
+ /// Remove the global variable from the linked image if there are no references
+ /// to it after all compiler and linker optimizations have been performed.
+ ///
+ ///
+ #define GLOBAL_REMOVE_IF_UNREFERENCED
+#endif
+
+//
+// For symbol name in GNU assembly code, an extra "_" is necessary
+//
+#if defined(__GNUC__)
+ ///
+ /// Private worker functions for ASM_PFX()
+ ///
+ #define _CONCATENATE(a, b) __CONCATENATE(a, b)
+ #define __CONCATENATE(a, b) a ## b
+
+ ///
+ /// The __USER_LABEL_PREFIX__ macro predefined by GNUC represents the prefix
+ /// on symbols in assembly language.
+ ///
+ #define ASM_PFX(name) _CONCATENATE (__USER_LABEL_PREFIX__, name)
+#endif
+
+#if __APPLE__
+ //
+ // Apple extension that is used by the linker to optimize code size
+ // with assembly functions. Put at the end of your .S files
+ //
+ #define ASM_FUNCTION_REMOVE_IF_UNREFERENCED .subsections_via_symbols
+#else
+ #define ASM_FUNCTION_REMOVE_IF_UNREFERENCED
+#endif
+
+#ifdef __CC_ARM
+ //
+ // Older RVCT ARM compilers don't fully support #pragma pack and require __packed
+ // as a prefix for the structure.
+ //
+ #define PACKED __packed
+#else
+ #define PACKED
+#endif
+
+///
+/// 128 bit buffer containing a unique identifier value.
+/// Unless otherwise specified, aligned on a 64 bit boundary.
+///
+typedef struct {
+ UINT32 Data1;
+ UINT16 Data2;
+ UINT16 Data3;
+ UINT8 Data4[8];
+} GUID;
+
+//
+// 8-bytes unsigned value that represents a physical system address.
+//
+typedef UINT64 PHYSICAL_ADDRESS;
+
+///
+/// LIST_ENTRY structure definition.
+///
+typedef struct _LIST_ENTRY LIST_ENTRY;
+
+///
+/// _LIST_ENTRY structure definition.
+///
+struct _LIST_ENTRY {
+ LIST_ENTRY *ForwardLink;
+ LIST_ENTRY *BackLink;
+};
+
+//
+// Modifiers to abstract standard types to aid in debug of problems
+//
+
+///
+/// Datum is read-only.
+///
+#define CONST const
+
+///
+/// Datum is scoped to the current file or function.
+///
+#define STATIC static
+
+///
+/// Undeclared type.
+///
+#define VOID void
+
+//
+// Modifiers for Data Types used to self document code.
+// This concept is borrowed for UEFI specification.
+//
+
+///
+/// Datum is passed to the function.
+///
+#define IN
+
+///
+/// Datum is returned from the function.
+///
+#define OUT
+
+///
+/// Passing the datum to the function is optional, and a NULL
+/// is passed if the value is not supplied.
+///
+#define OPTIONAL
+
+//
+// UEFI specification claims 1 and 0. We are concerned about the
+// complier portability so we did it this way.
+//
+
+///
+/// Boolean true value. UEFI Specification defines this value to be 1,
+/// but this form is more portable.
+///
+#define TRUE ((BOOLEAN)(1==1))
+
+///
+/// Boolean false value. UEFI Specification defines this value to be 0,
+/// but this form is more portable.
+///
+#define FALSE ((BOOLEAN)(0==1))
+
+///
+/// NULL pointer (VOID *)
+///
+#define NULL ((VOID *) 0)
+
+
+#define BIT0 0x00000001
+#define BIT1 0x00000002
+#define BIT2 0x00000004
+#define BIT3 0x00000008
+#define BIT4 0x00000010
+#define BIT5 0x00000020
+#define BIT6 0x00000040
+#define BIT7 0x00000080
+#define BIT8 0x00000100
+#define BIT9 0x00000200
+#define BIT10 0x00000400
+#define BIT11 0x00000800
+#define BIT12 0x00001000
+#define BIT13 0x00002000
+#define BIT14 0x00004000
+#define BIT15 0x00008000
+#define BIT16 0x00010000
+#define BIT17 0x00020000
+#define BIT18 0x00040000
+#define BIT19 0x00080000
+#define BIT20 0x00100000
+#define BIT21 0x00200000
+#define BIT22 0x00400000
+#define BIT23 0x00800000
+#define BIT24 0x01000000
+#define BIT25 0x02000000
+#define BIT26 0x04000000
+#define BIT27 0x08000000
+#define BIT28 0x10000000
+#define BIT29 0x20000000
+#define BIT30 0x40000000
+#define BIT31 0x80000000
+#define BIT32 0x0000000100000000ULL
+#define BIT33 0x0000000200000000ULL
+#define BIT34 0x0000000400000000ULL
+#define BIT35 0x0000000800000000ULL
+#define BIT36 0x0000001000000000ULL
+#define BIT37 0x0000002000000000ULL
+#define BIT38 0x0000004000000000ULL
+#define BIT39 0x0000008000000000ULL
+#define BIT40 0x0000010000000000ULL
+#define BIT41 0x0000020000000000ULL
+#define BIT42 0x0000040000000000ULL
+#define BIT43 0x0000080000000000ULL
+#define BIT44 0x0000100000000000ULL
+#define BIT45 0x0000200000000000ULL
+#define BIT46 0x0000400000000000ULL
+#define BIT47 0x0000800000000000ULL
+#define BIT48 0x0001000000000000ULL
+#define BIT49 0x0002000000000000ULL
+#define BIT50 0x0004000000000000ULL
+#define BIT51 0x0008000000000000ULL
+#define BIT52 0x0010000000000000ULL
+#define BIT53 0x0020000000000000ULL
+#define BIT54 0x0040000000000000ULL
+#define BIT55 0x0080000000000000ULL
+#define BIT56 0x0100000000000000ULL
+#define BIT57 0x0200000000000000ULL
+#define BIT58 0x0400000000000000ULL
+#define BIT59 0x0800000000000000ULL
+#define BIT60 0x1000000000000000ULL
+#define BIT61 0x2000000000000000ULL
+#define BIT62 0x4000000000000000ULL
+#define BIT63 0x8000000000000000ULL
+
+#define SIZE_1KB 0x00000400
+#define SIZE_2KB 0x00000800
+#define SIZE_4KB 0x00001000
+#define SIZE_8KB 0x00002000
+#define SIZE_16KB 0x00004000
+#define SIZE_32KB 0x00008000
+#define SIZE_64KB 0x00010000
+#define SIZE_128KB 0x00020000
+#define SIZE_256KB 0x00040000
+#define SIZE_512KB 0x00080000
+#define SIZE_1MB 0x00100000
+#define SIZE_2MB 0x00200000
+#define SIZE_4MB 0x00400000
+#define SIZE_8MB 0x00800000
+#define SIZE_16MB 0x01000000
+#define SIZE_32MB 0x02000000
+#define SIZE_64MB 0x04000000
+#define SIZE_128MB 0x08000000
+#define SIZE_256MB 0x10000000
+#define SIZE_512MB 0x20000000
+#define SIZE_1GB 0x40000000
+#define SIZE_2GB 0x80000000
+#define SIZE_4GB 0x0000000100000000ULL
+#define SIZE_8GB 0x0000000200000000ULL
+#define SIZE_16GB 0x0000000400000000ULL
+#define SIZE_32GB 0x0000000800000000ULL
+#define SIZE_64GB 0x0000001000000000ULL
+#define SIZE_128GB 0x0000002000000000ULL
+#define SIZE_256GB 0x0000004000000000ULL
+#define SIZE_512GB 0x0000008000000000ULL
+#define SIZE_1TB 0x0000010000000000ULL
+#define SIZE_2TB 0x0000020000000000ULL
+#define SIZE_4TB 0x0000040000000000ULL
+#define SIZE_8TB 0x0000080000000000ULL
+#define SIZE_16TB 0x0000100000000000ULL
+#define SIZE_32TB 0x0000200000000000ULL
+#define SIZE_64TB 0x0000400000000000ULL
+#define SIZE_128TB 0x0000800000000000ULL
+#define SIZE_256TB 0x0001000000000000ULL
+#define SIZE_512TB 0x0002000000000000ULL
+#define SIZE_1PB 0x0004000000000000ULL
+#define SIZE_2PB 0x0008000000000000ULL
+#define SIZE_4PB 0x0010000000000000ULL
+#define SIZE_8PB 0x0020000000000000ULL
+#define SIZE_16PB 0x0040000000000000ULL
+#define SIZE_32PB 0x0080000000000000ULL
+#define SIZE_64PB 0x0100000000000000ULL
+#define SIZE_128PB 0x0200000000000000ULL
+#define SIZE_256PB 0x0400000000000000ULL
+#define SIZE_512PB 0x0800000000000000ULL
+#define SIZE_1EB 0x1000000000000000ULL
+#define SIZE_2EB 0x2000000000000000ULL
+#define SIZE_4EB 0x4000000000000000ULL
+#define SIZE_8EB 0x8000000000000000ULL
+
+#define BASE_1KB 0x00000400
+#define BASE_2KB 0x00000800
+#define BASE_4KB 0x00001000
+#define BASE_8KB 0x00002000
+#define BASE_16KB 0x00004000
+#define BASE_32KB 0x00008000
+#define BASE_64KB 0x00010000
+#define BASE_128KB 0x00020000
+#define BASE_256KB 0x00040000
+#define BASE_512KB 0x00080000
+#define BASE_1MB 0x00100000
+#define BASE_2MB 0x00200000
+#define BASE_4MB 0x00400000
+#define BASE_8MB 0x00800000
+#define BASE_16MB 0x01000000
+#define BASE_32MB 0x02000000
+#define BASE_64MB 0x04000000
+#define BASE_128MB 0x08000000
+#define BASE_256MB 0x10000000
+#define BASE_512MB 0x20000000
+#define BASE_1GB 0x40000000
+#define BASE_2GB 0x80000000
+#define BASE_4GB 0x0000000100000000ULL
+#define BASE_8GB 0x0000000200000000ULL
+#define BASE_16GB 0x0000000400000000ULL
+#define BASE_32GB 0x0000000800000000ULL
+#define BASE_64GB 0x0000001000000000ULL
+#define BASE_128GB 0x0000002000000000ULL
+#define BASE_256GB 0x0000004000000000ULL
+#define BASE_512GB 0x0000008000000000ULL
+#define BASE_1TB 0x0000010000000000ULL
+#define BASE_2TB 0x0000020000000000ULL
+#define BASE_4TB 0x0000040000000000ULL
+#define BASE_8TB 0x0000080000000000ULL
+#define BASE_16TB 0x0000100000000000ULL
+#define BASE_32TB 0x0000200000000000ULL
+#define BASE_64TB 0x0000400000000000ULL
+#define BASE_128TB 0x0000800000000000ULL
+#define BASE_256TB 0x0001000000000000ULL
+#define BASE_512TB 0x0002000000000000ULL
+#define BASE_1PB 0x0004000000000000ULL
+#define BASE_2PB 0x0008000000000000ULL
+#define BASE_4PB 0x0010000000000000ULL
+#define BASE_8PB 0x0020000000000000ULL
+#define BASE_16PB 0x0040000000000000ULL
+#define BASE_32PB 0x0080000000000000ULL
+#define BASE_64PB 0x0100000000000000ULL
+#define BASE_128PB 0x0200000000000000ULL
+#define BASE_256PB 0x0400000000000000ULL
+#define BASE_512PB 0x0800000000000000ULL
+#define BASE_1EB 0x1000000000000000ULL
+#define BASE_2EB 0x2000000000000000ULL
+#define BASE_4EB 0x4000000000000000ULL
+#define BASE_8EB 0x8000000000000000ULL
+
+//
+// Support for variable length argument lists using the ANSI standard.
+//
+// Since we are using the ANSI standard we used the standard naming and
+// did not follow the coding convention
+//
+// VA_LIST - typedef for argument list.
+// VA_START (VA_LIST Marker, argument before the ...) - Init Marker for use.
+// VA_END (VA_LIST Marker) - Clear Marker
+// VA_ARG (VA_LIST Marker, var arg size) - Use Marker to get an argument from
+// the ... list. You must know the size and pass it in this macro.
+//
+// example:
+//
+// UINTN
+// ExampleVarArg (
+// IN UINTN NumberOfArgs,
+// ...
+// )
+// {
+// VA_LIST Marker;
+// UINTN Index;
+// UINTN Result;
+//
+// //
+// // Initialize the Marker
+// //
+// VA_START (Marker, NumberOfArgs);
+// for (Index = 0, Result = 0; Index < NumberOfArgs; Index++) {
+// //
+// // The ... list is a series of UINTN values, so average them up.
+// //
+// Result += VA_ARG (Marker, UINTN);
+// }
+//
+// VA_END (Marker);
+// return Result
+// }
+//
+
+/**
+ Return the size of argument that has been aligned to sizeof (UINTN).
+
+ @param n The parameter size to be aligned.
+
+ @return The aligned size.
+**/
+#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1))
+
+#if defined(__CC_ARM)
+//
+// RVCT ARM variable argument list support.
+//
+
+///
+/// Variable used to traverse the list of arguments. This type can vary by
+/// implementation and could be an array or structure.
+///
+#ifdef __APCS_ADSABI
+ typedef int *va_list[1];
+ #define VA_LIST va_list
+#else
+ typedef struct __va_list { void *__ap; } va_list;
+ #define VA_LIST va_list
+#endif
+
+#define VA_START(Marker, Parameter) __va_start(Marker, Parameter)
+
+#define VA_ARG(Marker, TYPE) __va_arg(Marker, TYPE)
+
+#define VA_END(Marker) ((void)0)
+
+#elif defined(__GNUC__) && !defined(NO_BUILTIN_VA_FUNCS)
+//
+// Use GCC built-in macros for variable argument lists.
+//
+
+///
+/// Variable used to traverse the list of arguments. This type can vary by
+/// implementation and could be an array or structure.
+///
+typedef __builtin_va_list VA_LIST;
+
+#define VA_START(Marker, Parameter) __builtin_va_start (Marker, Parameter)
+
+#define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
+
+#define VA_END(Marker) __builtin_va_end (Marker)
+
+#else
+///
+/// Variable used to traverse the list of arguments. This type can vary by
+/// implementation and could be an array or structure.
+///
+typedef CHAR8 *VA_LIST;
+
+/**
+ Retrieves a pointer to the beginning of a variable argument list, based on
+ the name of the parameter that immediately precedes the variable argument list.
+
+ This function initializes Marker to point to the beginning of the variable
+ argument list that immediately follows Parameter. The method for computing the
+ pointer to the next argument in the argument list is CPU-specific following the
+ EFIAPI ABI.
+
+ @param Marker The VA_LIST used to traverse the list of arguments.
+ @param Parameter The name of the parameter that immediately precedes
+ the variable argument list.
+
+ @return A pointer to the beginning of a variable argument list.
+
+**/
+#define VA_START(Marker, Parameter) (Marker = (VA_LIST) ((UINTN) & (Parameter) + _INT_SIZE_OF (Parameter)))
+
+/**
+ Returns an argument of a specified type from a variable argument list and updates
+ the pointer to the variable argument list to point to the next argument.
+
+ This function returns an argument of the type specified by TYPE from the beginning
+ of the variable argument list specified by Marker. Marker is then updated to point
+ to the next argument in the variable argument list. The method for computing the
+ pointer to the next argument in the argument list is CPU-specific following the EFIAPI ABI.
+
+ @param Marker VA_LIST used to traverse the list of arguments.
+ @param TYPE The type of argument to retrieve from the beginning
+ of the variable argument list.
+
+ @return An argument of the type specified by TYPE.
+
+**/
+#define VA_ARG(Marker, TYPE) (*(TYPE *) ((Marker += _INT_SIZE_OF (TYPE)) - _INT_SIZE_OF (TYPE)))
+
+/**
+ Terminates the use of a variable argument list.
+
+ This function initializes Marker so it can no longer be used with VA_ARG().
+ After this macro is used, the only way to access the variable argument list is
+ by using VA_START() again.
+
+ @param Marker VA_LIST used to traverse the list of arguments.
+
+**/
+#define VA_END(Marker) (Marker = (VA_LIST) 0)
+
+#endif
+
+///
+/// Pointer to the start of a variable argument list stored in a memory buffer. Same as UINT8 *.
+///
+typedef UINTN *BASE_LIST;
+
+/**
+ Returns the size of a data type in sizeof(UINTN) units rounded up to the nearest UINTN boundary.
+
+ @param TYPE The date type to determine the size of.
+
+ @return The size of TYPE in sizeof (UINTN) units rounded up to the nearest UINTN boundary.
+**/
+#define _BASE_INT_SIZE_OF(TYPE) ((sizeof (TYPE) + sizeof (UINTN) - 1) / sizeof (UINTN))
+
+/**
+ Returns an argument of a specified type from a variable argument list and updates
+ the pointer to the variable argument list to point to the next argument.
+
+ This function returns an argument of the type specified by TYPE from the beginning
+ of the variable argument list specified by Marker. Marker is then updated to point
+ to the next argument in the variable argument list. The method for computing the
+ pointer to the next argument in the argument list is CPU specific following the EFIAPI ABI.
+
+ @param Marker The pointer to the beginning of a variable argument list.
+ @param TYPE The type of argument to retrieve from the beginning
+ of the variable argument list.
+
+ @return An argument of the type specified by TYPE.
+
+**/
+#define BASE_ARG(Marker, TYPE) (*(TYPE *) ((Marker += _BASE_INT_SIZE_OF (TYPE)) - _BASE_INT_SIZE_OF (TYPE)))
+
+/**
+ The macro that returns the byte offset of a field in a data structure.
+
+ This function returns the offset, in bytes, of field specified by Field from the
+ beginning of the data structure specified by TYPE. If TYPE does not contain Field,
+ the module will not compile.
+
+ @param TYPE The name of the data structure that contains the field specified by Field.
+ @param Field The name of the field in the data structure.
+
+ @return Offset, in bytes, of field.
+
+**/
+#ifdef __GNUC__
+#if __GNUC__ >= 4
+#define OFFSET_OF(TYPE, Field) ((UINTN) __builtin_offsetof(TYPE, Field))
+#endif
+#endif
+
+#ifndef OFFSET_OF
+#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field))
+#endif
+
+/**
+ Macro that returns a pointer to the data structure that contains a specified field of
+ that data structure. This is a lightweight method to hide information by placing a
+ public data structure inside a larger private data structure and using a pointer to
+ the public data structure to retrieve a pointer to the private data structure.
+
+ This function computes the offset, in bytes, of field specified by Field from the beginning
+ of the data structure specified by TYPE. This offset is subtracted from Record, and is
+ used to return a pointer to a data structure of the type specified by TYPE. If the data type
+ specified by TYPE does not contain the field specified by Field, then the module will not compile.
+
+ @param Record Pointer to the field specified by Field within a data structure of type TYPE.
+ @param TYPE The name of the data structure type to return. This data structure must
+ contain the field specified by Field.
+ @param Field The name of the field in the data structure specified by TYPE to which Record points.
+
+ @return A pointer to the structure from one of it's elements.
+
+**/
+#define BASE_CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
+
+/**
+ Rounds a value up to the next boundary using a specified alignment.
+
+ This function rounds Value up to the next boundary using the specified Alignment.
+ This aligned value is returned.
+
+ @param Value The value to round up.
+ @param Alignment The alignment boundary used to return the aligned value.
+
+ @return A value up to the next boundary.
+
+**/
+#define ALIGN_VALUE(Value, Alignment) ((Value) + (((Alignment) - (Value)) & ((Alignment) - 1)))
+
+/**
+ Adjust a pointer by adding the minimum offset required for it to be aligned on
+ a specified alignment boundary.
+
+ This function rounds the pointer specified by Pointer to the next alignment boundary
+ specified by Alignment. The pointer to the aligned address is returned.
+
+ @param Pointer The pointer to round up.
+ @param Alignment The alignment boundary to use to return an aligned pointer.
+
+ @return Pointer to the aligned address.
+
+**/
+#define ALIGN_POINTER(Pointer, Alignment) ((VOID *) (ALIGN_VALUE ((UINTN)(Pointer), (Alignment))))
+
+/**
+ Rounds a value up to the next natural boundary for the current CPU.
+ This is 4-bytes for 32-bit CPUs and 8-bytes for 64-bit CPUs.
+
+ This function rounds the value specified by Value up to the next natural boundary for the
+ current CPU. This rounded value is returned.
+
+ @param Value The value to round up.
+
+ @return Rounded value specified by Value.
+
+**/
+#define ALIGN_VARIABLE(Value) ALIGN_VALUE ((Value), sizeof (UINTN))
+
+
+/**
+ Return the maximum of two operands.
+
+ This macro returns the maximum of two operand specified by a and b.
+ Both a and b must be the same numerical types, signed or unsigned.
+
+ @param a The first operand with any numerical type.
+ @param b The second operand. Can be any numerical type as long as is
+ the same type as a.
+
+ @return Maximum of two operands.
+
+**/
+#define MAX(a, b) \
+ (((a) > (b)) ? (a) : (b))
+
+/**
+ Return the minimum of two operands.
+
+ This macro returns the minimal of two operand specified by a and b.
+ Both a and b must be the same numerical types, signed or unsigned.
+
+ @param a The first operand with any numerical type.
+ @param b The second operand. It should be the same any numerical type with a.
+
+ @return Minimum of two operands.
+
+**/
+
+#define MIN(a, b) \
+ (((a) < (b)) ? (a) : (b))
+
+//
+// Status codes common to all execution phases
+//
+typedef UINTN RETURN_STATUS;
+
+/**
+ Produces a RETURN_STATUS code with the highest bit set.
+
+ @param StatusCode The status code value to convert into a warning code.
+ StatusCode must be in the range 0x00000000..0x7FFFFFFF.
+
+ @return The value specified by StatusCode with the highest bit set.
+
+**/
+#define ENCODE_ERROR(StatusCode) ((RETURN_STATUS)(MAX_BIT | (StatusCode)))
+
+/**
+ Produces a RETURN_STATUS code with the highest bit clear.
+
+ @param StatusCode The status code value to convert into a warning code.
+ StatusCode must be in the range 0x00000000..0x7FFFFFFF.
+
+ @return The value specified by StatusCode with the highest bit clear.
+
+**/
+#define ENCODE_WARNING(StatusCode) ((RETURN_STATUS)(StatusCode))
+
+/**
+ Returns TRUE if a specified RETURN_STATUS code is an error code.
+
+ This function returns TRUE if StatusCode has the high bit set. Otherwise, FALSE is returned.
+
+ @param StatusCode The status code value to evaluate.
+
+ @retval TRUE The high bit of StatusCode is set.
+ @retval FALSE The high bit of StatusCode is clear.
+
+**/
+#define RETURN_ERROR(StatusCode) (((INTN)(RETURN_STATUS)(StatusCode)) < 0)
+
+///
+/// The operation completed successfully.
+///
+#define RETURN_SUCCESS 0
+
+///
+/// The image failed to load.
+///
+#define RETURN_LOAD_ERROR ENCODE_ERROR (1)
+
+///
+/// The parameter was incorrect.
+///
+#define RETURN_INVALID_PARAMETER ENCODE_ERROR (2)
+
+///
+/// The operation is not supported.
+///
+#define RETURN_UNSUPPORTED ENCODE_ERROR (3)
+
+///
+/// The buffer was not the proper size for the request.
+///
+#define RETURN_BAD_BUFFER_SIZE ENCODE_ERROR (4)
+
+///
+/// The buffer was not large enough to hold the requested data.
+/// The required buffer size is returned in the appropriate
+/// parameter when this error occurs.
+///
+#define RETURN_BUFFER_TOO_SMALL ENCODE_ERROR (5)
+
+///
+/// There is no data pending upon return.
+///
+#define RETURN_NOT_READY ENCODE_ERROR (6)
+
+///
+/// The physical device reported an error while attempting the
+/// operation.
+///
+#define RETURN_DEVICE_ERROR ENCODE_ERROR (7)
+
+///
+/// The device can not be written to.
+///
+#define RETURN_WRITE_PROTECTED ENCODE_ERROR (8)
+
+///
+/// The resource has run out.
+///
+#define RETURN_OUT_OF_RESOURCES ENCODE_ERROR (9)
+
+///
+/// An inconsistency was detected on the file system causing the
+/// operation to fail.
+///
+#define RETURN_VOLUME_CORRUPTED ENCODE_ERROR (10)
+
+///
+/// There is no more space on the file system.
+///
+#define RETURN_VOLUME_FULL ENCODE_ERROR (11)
+
+///
+/// The device does not contain any medium to perform the
+/// operation.
+///
+#define RETURN_NO_MEDIA ENCODE_ERROR (12)
+
+///
+/// The medium in the device has changed since the last
+/// access.
+///
+#define RETURN_MEDIA_CHANGED ENCODE_ERROR (13)
+
+///
+/// The item was not found.
+///
+#define RETURN_NOT_FOUND ENCODE_ERROR (14)
+
+///
+/// Access was denied.
+///
+#define RETURN_ACCESS_DENIED ENCODE_ERROR (15)
+
+///
+/// The server was not found or did not respond to the request.
+///
+#define RETURN_NO_RESPONSE ENCODE_ERROR (16)
+
+///
+/// A mapping to the device does not exist.
+///
+#define RETURN_NO_MAPPING ENCODE_ERROR (17)
+
+///
+/// A timeout time expired.
+///
+#define RETURN_TIMEOUT ENCODE_ERROR (18)
+
+///
+/// The protocol has not been started.
+///
+#define RETURN_NOT_STARTED ENCODE_ERROR (19)
+
+///
+/// The protocol has already been started.
+///
+#define RETURN_ALREADY_STARTED ENCODE_ERROR (20)
+
+///
+/// The operation was aborted.
+///
+#define RETURN_ABORTED ENCODE_ERROR (21)
+
+///
+/// An ICMP error occurred during the network operation.
+///
+#define RETURN_ICMP_ERROR ENCODE_ERROR (22)
+
+///
+/// A TFTP error occurred during the network operation.
+///
+#define RETURN_TFTP_ERROR ENCODE_ERROR (23)
+
+///
+/// A protocol error occurred during the network operation.
+///
+#define RETURN_PROTOCOL_ERROR ENCODE_ERROR (24)
+
+///
+/// A function encountered an internal version that was
+/// incompatible with a version requested by the caller.
+///
+#define RETURN_INCOMPATIBLE_VERSION ENCODE_ERROR (25)
+
+///
+/// The function was not performed due to a security violation.
+///
+#define RETURN_SECURITY_VIOLATION ENCODE_ERROR (26)
+
+///
+/// A CRC error was detected.
+///
+#define RETURN_CRC_ERROR ENCODE_ERROR (27)
+
+///
+/// The beginning or end of media was reached.
+///
+#define RETURN_END_OF_MEDIA ENCODE_ERROR (28)
+
+///
+/// The end of the file was reached.
+///
+#define RETURN_END_OF_FILE ENCODE_ERROR (31)
+
+///
+/// The language specified was invalid.
+///
+#define RETURN_INVALID_LANGUAGE ENCODE_ERROR (32)
+
+
+///
+/// The string contained one or more characters that
+/// the device could not render and were skipped.
+///
+#define RETURN_WARN_UNKNOWN_GLYPH ENCODE_WARNING (1)
+
+///
+/// The handle was closed, but the file was not deleted.
+///
+#define RETURN_WARN_DELETE_FAILURE ENCODE_WARNING (2)
+
+///
+/// The handle was closed, but the data to the file was not
+/// flushed properly.
+///
+#define RETURN_WARN_WRITE_FAILURE ENCODE_WARNING (3)
+
+///
+/// The resulting buffer was too small, and the data was
+/// truncated to the buffer size.
+///
+#define RETURN_WARN_BUFFER_TOO_SMALL ENCODE_WARNING (4)
+
+/**
+ Returns a 16-bit signature built from 2 ASCII characters.
+
+ This macro returns a 16-bit value built from the two ASCII characters specified
+ by A and B.
+
+ @param A The first ASCII character.
+ @param B The second ASCII character.
+
+ @return A 16-bit value built from the two ASCII characters specified by A and B.
+
+**/
+#define SIGNATURE_16(A, B) ((A) | (B << 8))
+
+/**
+ Returns a 32-bit signature built from 4 ASCII characters.
+
+ This macro returns a 32-bit value built from the four ASCII characters specified
+ by A, B, C, and D.
+
+ @param A The first ASCII character.
+ @param B The second ASCII character.
+ @param C The third ASCII character.
+ @param D The fourth ASCII character.
+
+ @return A 32-bit value built from the two ASCII characters specified by A, B,
+ C and D.
+
+**/
+#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16))
+
+/**
+ Returns a 64-bit signature built from 8 ASCII characters.
+
+ This macro returns a 64-bit value built from the eight ASCII characters specified
+ by A, B, C, D, E, F, G,and H.
+
+ @param A The first ASCII character.
+ @param B The second ASCII character.
+ @param C The third ASCII character.
+ @param D The fourth ASCII character.
+ @param E The fifth ASCII character.
+ @param F The sixth ASCII character.
+ @param G The seventh ASCII character.
+ @param H The eighth ASCII character.
+
+ @return A 64-bit value built from the two ASCII characters specified by A, B,
+ C, D, E, F, G and H.
+
+**/
+#define SIGNATURE_64(A, B, C, D, E, F, G, H) \
+ (SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32))
+
+#endif
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/HiiFormMapMethodGuid.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/HiiFormMapMethodGuid.h
new file mode 100644
index 00000000..c8f37213
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/HiiFormMapMethodGuid.h
@@ -0,0 +1,27 @@
+/** @file
+ Guid used to identify HII FormMap configuration method.
+
+ Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ GUID defined in UEFI 2.2 spec.
+**/
+
+#ifndef __EFI_HII_FORMMAP_GUID_H__
+#define __EFI_HII_FORMMAP_GUID_H__
+
+FILE_LICENCE ( BSD3 );
+
+#define EFI_HII_STANDARD_FORM_GUID \
+ { 0x3bd2f4ec, 0xe524, 0x46e4, { 0xa9, 0xd8, 0x51, 0x1, 0x17, 0x42, 0x55, 0x62 } }
+
+extern EFI_GUID gEfiHiiStandardFormGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/HiiPlatformSetupFormset.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/HiiPlatformSetupFormset.h
new file mode 100644
index 00000000..fa817363
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/HiiPlatformSetupFormset.h
@@ -0,0 +1,37 @@
+/** @file
+ GUID indicates that the form set contains forms designed to be used
+ for platform configuration and this form set will be displayed.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ GUID defined in UEFI 2.1.
+
+**/
+
+#ifndef __HII_PLATFORM_SETUP_FORMSET_GUID_H__
+#define __HII_PLATFORM_SETUP_FORMSET_GUID_H__
+
+FILE_LICENCE ( BSD3 );
+
+#define EFI_HII_PLATFORM_SETUP_FORMSET_GUID \
+ { 0x93039971, 0x8545, 0x4b04, { 0xb4, 0x5e, 0x32, 0xeb, 0x83, 0x26, 0x4, 0xe } }
+
+#define EFI_HII_DRIVER_HEALTH_FORMSET_GUID \
+ { 0xf22fc20c, 0x8cf4, 0x45eb, { 0x8e, 0x6, 0xad, 0x4e, 0x50, 0xb9, 0x5d, 0xd3 } }
+
+#define EFI_HII_USER_CREDENTIAL_FORMSET_GUID \
+ { 0x337f4407, 0x5aee, 0x4b83, { 0xb2, 0xa7, 0x4e, 0xad, 0xca, 0x30, 0x88, 0xcd } }
+
+extern EFI_GUID gEfiHiiPlatformSetupFormsetGuid;
+extern EFI_GUID gEfiHiiDriverHealthFormsetGuid;
+extern EFI_GUID gEfiHiiUserCredentialFormsetGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/MdeModuleHii.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/MdeModuleHii.h
new file mode 100644
index 00000000..15edf9cb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/MdeModuleHii.h
@@ -0,0 +1,222 @@
+/** @file
+ EDKII extented HII IFR guid opcodes.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __MDEMODULE_HII_H__
+#define __MDEMODULE_HII_H__
+
+FILE_LICENCE ( BSD3 );
+
+#define NARROW_CHAR 0xFFF0
+#define WIDE_CHAR 0xFFF1
+#define NON_BREAKING_CHAR 0xFFF2
+
+///
+/// State defined for password statemachine .
+///
+#define BROWSER_STATE_VALIDATE_PASSWORD 0
+#define BROWSER_STATE_SET_PASSWORD 1
+
+///
+/// GUIDed opcodes defined for EDKII implementation.
+///
+#define EFI_IFR_TIANO_GUID \
+ { 0xf0b1735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38, 0xaf, 0x48, 0xce} }
+
+#pragma pack(1)
+
+///
+/// EDKII implementation extension opcodes, new extension can be added here later.
+///
+#define EFI_IFR_EXTEND_OP_LABEL 0x0
+#define EFI_IFR_EXTEND_OP_BANNER 0x1
+#define EFI_IFR_EXTEND_OP_TIMEOUT 0x2
+#define EFI_IFR_EXTEND_OP_CLASS 0x3
+#define EFI_IFR_EXTEND_OP_SUBCLASS 0x4
+
+///
+/// Label opcode.
+///
+typedef struct _EFI_IFR_GUID_LABEL {
+ EFI_IFR_OP_HEADER Header;
+ ///
+ /// EFI_IFR_TIANO_GUID.
+ ///
+ EFI_GUID Guid;
+ ///
+ /// EFI_IFR_EXTEND_OP_LABEL.
+ ///
+ UINT8 ExtendOpCode;
+ ///
+ /// Label Number.
+ ///
+ UINT16 Number;
+} EFI_IFR_GUID_LABEL;
+
+#define EFI_IFR_BANNER_ALIGN_LEFT 0
+#define EFI_IFR_BANNER_ALIGN_CENTER 1
+#define EFI_IFR_BANNER_ALIGN_RIGHT 2
+
+///
+/// Banner opcode.
+///
+typedef struct _EFI_IFR_GUID_BANNER {
+ EFI_IFR_OP_HEADER Header;
+ ///
+ /// EFI_IFR_TIANO_GUID.
+ ///
+ EFI_GUID Guid;
+ ///
+ /// EFI_IFR_EXTEND_OP_BANNER
+ ///
+ UINT8 ExtendOpCode;
+ EFI_STRING_ID Title; ///< The string token for the banner title.
+ UINT16 LineNumber; ///< 1-based line number.
+ UINT8 Alignment; ///< left, center, or right-aligned.
+} EFI_IFR_GUID_BANNER;
+
+///
+/// Timeout opcode.
+///
+typedef struct _EFI_IFR_GUID_TIMEOUT {
+ EFI_IFR_OP_HEADER Header;
+ ///
+ /// EFI_IFR_TIANO_GUID.
+ ///
+ EFI_GUID Guid;
+ ///
+ /// EFI_IFR_EXTEND_OP_TIMEOUT.
+ ///
+ UINT8 ExtendOpCode;
+ UINT16 TimeOut; ///< TimeOut Value.
+} EFI_IFR_GUID_TIMEOUT;
+
+#define EFI_NON_DEVICE_CLASS 0x00
+#define EFI_DISK_DEVICE_CLASS 0x01
+#define EFI_VIDEO_DEVICE_CLASS 0x02
+#define EFI_NETWORK_DEVICE_CLASS 0x04
+#define EFI_INPUT_DEVICE_CLASS 0x08
+#define EFI_ON_BOARD_DEVICE_CLASS 0x10
+#define EFI_OTHER_DEVICE_CLASS 0x20
+
+///
+/// Device Class opcode.
+///
+typedef struct _EFI_IFR_GUID_CLASS {
+ EFI_IFR_OP_HEADER Header;
+ ///
+ /// EFI_IFR_TIANO_GUID.
+ ///
+ EFI_GUID Guid;
+ ///
+ /// EFI_IFR_EXTEND_OP_CLASS.
+ ///
+ UINT8 ExtendOpCode;
+ UINT16 Class; ///< Device Class from the above.
+} EFI_IFR_GUID_CLASS;
+
+#define EFI_SETUP_APPLICATION_SUBCLASS 0x00
+#define EFI_GENERAL_APPLICATION_SUBCLASS 0x01
+#define EFI_FRONT_PAGE_SUBCLASS 0x02
+#define EFI_SINGLE_USE_SUBCLASS 0x03
+
+///
+/// SubClass opcode
+///
+typedef struct _EFI_IFR_GUID_SUBCLASS {
+ EFI_IFR_OP_HEADER Header;
+ ///
+ /// EFI_IFR_TIANO_GUID.
+ ///
+ EFI_GUID Guid;
+ ///
+ /// EFI_IFR_EXTEND_OP_SUBCLASS.
+ ///
+ UINT8 ExtendOpCode;
+ UINT16 SubClass; ///< Sub Class type from the above.
+} EFI_IFR_GUID_SUBCLASS;
+
+///
+/// GUIDed opcodes support for framework vfr.
+///
+#define EFI_IFR_FRAMEWORK_GUID \
+ { 0x31ca5d1a, 0xd511, 0x4931, { 0xb7, 0x82, 0xae, 0x6b, 0x2b, 0x17, 0x8c, 0xd7 } }
+
+///
+/// Two extended opcodes are added, and new extensions can be added here later.
+/// One is for framework OneOf question Option Key value;
+/// another is for framework vareqval.
+///
+#define EFI_IFR_EXTEND_OP_OPTIONKEY 0x0
+#define EFI_IFR_EXTEND_OP_VAREQNAME 0x1
+
+///
+/// Store the framework vfr option key value.
+///
+typedef struct _EFI_IFR_GUID_OPTIONKEY {
+ EFI_IFR_OP_HEADER Header;
+ ///
+ /// EFI_IFR_FRAMEWORK_GUID.
+ ///
+ EFI_GUID Guid;
+ ///
+ /// EFI_IFR_EXTEND_OP_OPTIONKEY.
+ ///
+ UINT8 ExtendOpCode;
+ ///
+ /// OneOf Questiond ID binded by OneOf Option.
+ ///
+ EFI_QUESTION_ID QuestionId;
+ ///
+ /// The OneOf Option Value.
+ ///
+ EFI_IFR_TYPE_VALUE OptionValue;
+ ///
+ /// The Framework OneOf Option Key Value.
+ ///
+ UINT16 KeyValue;
+} EFI_IFR_GUID_OPTIONKEY;
+
+///
+/// Store the framework vfr vareqval name number.
+///
+typedef struct _EFI_IFR_GUID_VAREQNAME {
+ EFI_IFR_OP_HEADER Header;
+ ///
+ /// EFI_IFR_FRAMEWORK_GUID.
+ ///
+ EFI_GUID Guid;
+ ///
+ /// EFI_IFR_EXTEND_OP_VAREQNAME.
+ ///
+ UINT8 ExtendOpCode;
+ ///
+ /// Question ID of the Numeric Opcode created.
+ ///
+ EFI_QUESTION_ID QuestionId;
+ ///
+ /// For vareqval (0x100), NameId is 0x100.
+ /// This value will convert to a Unicode String following this rule;
+ /// sprintf(StringBuffer, "%d", NameId) .
+ /// The Unicode String will be used as a EFI Variable Name.
+ ///
+ UINT16 NameId;
+} EFI_IFR_GUID_VAREQNAME;
+
+#pragma pack()
+
+extern EFI_GUID gEfiIfrTianoGuid;
+extern EFI_GUID gEfiIfrFrameworkGuid;
+
+#endif
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/PcAnsi.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/PcAnsi.h
new file mode 100644
index 00000000..8b3e63f3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/PcAnsi.h
@@ -0,0 +1,60 @@
+/** @file
+ Terminal Device Path Vendor Guid.
+
+ Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ GUIDs defined in UEFI 2.0 spec.
+
+**/
+
+#ifndef __PC_ANSI_H__
+#define __PC_ANSI_H__
+
+FILE_LICENCE ( BSD3 );
+
+#define EFI_PC_ANSI_GUID \
+ { \
+ 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+ }
+
+#define EFI_VT_100_GUID \
+ { \
+ 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+ }
+
+#define EFI_VT_100_PLUS_GUID \
+ { \
+ 0x7baec70b, 0x57e0, 0x4c76, {0x8e, 0x87, 0x2f, 0x9e, 0x28, 0x08, 0x83, 0x43 } \
+ }
+
+#define EFI_VT_UTF8_GUID \
+ { \
+ 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88 } \
+ }
+
+#define DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL \
+ { \
+ 0x37499a9d, 0x542f, 0x4c89, {0xa0, 0x26, 0x35, 0xda, 0x14, 0x20, 0x94, 0xe4 } \
+ }
+
+#define EFI_SAS_DEVICE_PATH_GUID \
+ { \
+ 0xd487ddb4, 0x008b, 0x11d9, {0xaf, 0xdc, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d } \
+ }
+
+extern EFI_GUID gEfiPcAnsiGuid;
+extern EFI_GUID gEfiVT100Guid;
+extern EFI_GUID gEfiVT100PlusGuid;
+extern EFI_GUID gEfiVTUTF8Guid;
+extern EFI_GUID gEfiUartDevicePathGuid;
+extern EFI_GUID gEfiSasDevicePathGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/SmBios.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/SmBios.h
new file mode 100644
index 00000000..cc4a1f94
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/SmBios.h
@@ -0,0 +1,34 @@
+/** @file
+ GUIDs used to locate the SMBIOS tables in the UEFI 2.0 system table.
+
+ This GUID in the system table is the only legal way to search for and
+ locate the SMBIOS tables. Do not search the 0xF0000 segment to find SMBIOS
+ tables.
+
+ Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ GUIDs defined in UEFI 2.0 spec.
+
+**/
+
+#ifndef __SMBIOS_GUID_H__
+#define __SMBIOS_GUID_H__
+
+FILE_LICENCE ( BSD3 );
+
+#define SMBIOS_TABLE_GUID \
+ { \
+ 0xeb9d2d31, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+ }
+
+extern EFI_GUID gEfiSmbiosTableGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/WinCertificate.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/WinCertificate.h
new file mode 100644
index 00000000..75fc642f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Guid/WinCertificate.h
@@ -0,0 +1,130 @@
+/** @file
+ GUID for UEFI WIN_CERTIFICATE structure.
+
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ GUID defined in UEFI 2.0 spec.
+**/
+
+#ifndef __EFI_WIN_CERTIFICATE_H__
+#define __EFI_WIN_CERTIFICATE_H__
+
+FILE_LICENCE ( BSD3 );
+
+//
+// _WIN_CERTIFICATE.wCertificateType
+//
+#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
+#define WIN_CERT_TYPE_EFI_PKCS115 0x0EF0
+#define WIN_CERT_TYPE_EFI_GUID 0x0EF1
+
+///
+/// The WIN_CERTIFICATE structure is part of the PE/COFF specification.
+///
+typedef struct {
+ ///
+ /// The length of the entire certificate,
+ /// including the length of the header, in bytes.
+ ///
+ UINT32 dwLength;
+ ///
+ /// The revision level of the WIN_CERTIFICATE
+ /// structure. The current revision level is 0x0200.
+ ///
+ UINT16 wRevision;
+ ///
+ /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI
+ /// certificate types. The UEFI specification reserves the range of
+ /// certificate type values from 0x0EF0 to 0x0EFF.
+ ///
+ UINT16 wCertificateType;
+ ///
+ /// The following is the actual certificate. The format of
+ /// the certificate depends on wCertificateType.
+ ///
+ /// UINT8 bCertificate[ANYSIZE_ARRAY];
+ ///
+} WIN_CERTIFICATE;
+
+///
+/// WIN_CERTIFICATE_UEFI_GUID.CertType
+///
+#define EFI_CERT_TYPE_RSA2048_SHA256_GUID \
+ {0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf } }
+
+///
+/// WIN_CERTIFICATE_UEFI_GUID.CertData
+///
+typedef struct {
+ EFI_GUID HashType;
+ UINT8 PublicKey[256];
+ UINT8 Signature[256];
+} EFI_CERT_BLOCK_RSA_2048_SHA256;
+
+
+///
+/// Certificate which encapsulates a GUID-specific digital signature
+///
+typedef struct {
+ ///
+ /// This is the standard WIN_CERTIFICATE header, where
+ /// wCertificateType is set to WIN_CERT_TYPE_UEFI_GUID.
+ ///
+ WIN_CERTIFICATE Hdr;
+ ///
+ /// This is the unique id which determines the
+ /// format of the CertData. .
+ ///
+ EFI_GUID CertType;
+ ///
+ /// The following is the certificate data. The format of
+ /// the data is determined by the CertType.
+ /// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID,
+ /// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure.
+ ///
+ UINT8 CertData[1];
+} WIN_CERTIFICATE_UEFI_GUID;
+
+
+///
+/// Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital signature.
+///
+/// The WIN_CERTIFICATE_UEFI_PKCS1_15 structure is derived from
+/// WIN_CERTIFICATE and encapsulate the information needed to
+/// implement the RSASSA-PKCS1-v1_5 digital signature algorithm as
+/// specified in RFC2437.
+///
+typedef struct {
+ ///
+ /// This is the standard WIN_CERTIFICATE header, where
+ /// wCertificateType is set to WIN_CERT_TYPE_UEFI_PKCS1_15.
+ ///
+ WIN_CERTIFICATE Hdr;
+ ///
+ /// This is the hashing algorithm which was performed on the
+ /// UEFI executable when creating the digital signature.
+ ///
+ EFI_GUID HashAlgorithm;
+ ///
+ /// The following is the actual digital signature. The
+ /// size of the signature is the same size as the key
+ /// (1024-bit key is 128 bytes) and can be determined by
+ /// subtracting the length of the other parts of this header
+ /// from the total length of the certificate as found in
+ /// Hdr.dwLength.
+ ///
+ /// UINT8 Signature[];
+ ///
+} WIN_CERTIFICATE_EFI_PKCS1_15;
+
+extern EFI_GUID gEfiCertTypeRsa2048Sha256Guid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Ia32/ProcessorBind.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Ia32/ProcessorBind.h
new file mode 100644
index 00000000..20cf407b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Ia32/ProcessorBind.h
@@ -0,0 +1,280 @@
+/** @file
+ Processor or Compiler specific defines and types for IA-32 architecture.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PROCESSOR_BIND_H__
+#define __PROCESSOR_BIND_H__
+
+FILE_LICENCE ( BSD3 );
+
+///
+/// Define the processor type so other code can make processor based choices.
+///
+#define MDE_CPU_IA32
+
+//
+// Make sure we are using the correct packing rules per EFI specification
+//
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#if defined(__INTEL_COMPILER)
+//
+// Disable ICC's remark #869: "Parameter" was never referenced warning.
+// This is legal ANSI C code so we disable the remark that is turned on with -Wall
+//
+#pragma warning ( disable : 869 )
+
+//
+// Disable ICC's remark #1418: external function definition with no prior declaration.
+// This is legal ANSI C code so we disable the remark that is turned on with /W4
+//
+#pragma warning ( disable : 1418 )
+
+//
+// Disable ICC's remark #1419: external declaration in primary source file
+// This is legal ANSI C code so we disable the remark that is turned on with /W4
+//
+#pragma warning ( disable : 1419 )
+
+//
+// Disable ICC's remark #593: "Variable" was set but never used.
+// This is legal ANSI C code so we disable the remark that is turned on with /W4
+//
+#pragma warning ( disable : 593 )
+
+#endif
+
+
+#if defined(_MSC_EXTENSIONS)
+
+//
+// Disable warning that make it impossible to compile at /W4
+// This only works for Microsoft* tools
+//
+
+//
+// Disabling bitfield type checking warnings.
+//
+#pragma warning ( disable : 4214 )
+
+//
+// Disabling the unreferenced formal parameter warnings.
+//
+#pragma warning ( disable : 4100 )
+
+//
+// Disable slightly different base types warning as CHAR8 * can not be set
+// to a constant string.
+//
+#pragma warning ( disable : 4057 )
+
+//
+// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning
+//
+#pragma warning ( disable : 4127 )
+
+//
+// This warning is caused by functions defined but not used. For precompiled header only.
+//
+#pragma warning ( disable : 4505 )
+
+//
+// This warning is caused by empty (after preprocessing) source file. For precompiled header only.
+//
+#pragma warning ( disable : 4206 )
+
+#endif
+
+
+#if defined(_MSC_EXTENSIONS)
+
+ //
+ // use Microsoft C complier dependent integer width types
+ //
+
+ ///
+ /// 8-byte unsigned value.
+ ///
+ typedef unsigned __int64 UINT64;
+ ///
+ /// 8-byte signed value.
+ ///
+ typedef __int64 INT64;
+ ///
+ /// 4-byte unsigned value.
+ ///
+ typedef unsigned __int32 UINT32;
+ ///
+ /// 4-byte signed value.
+ ///
+ typedef __int32 INT32;
+ ///
+ /// 2-byte unsigned value.
+ ///
+ typedef unsigned short UINT16;
+ ///
+ /// 2-byte Character. Unless otherwise specified all strings are stored in the
+ /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
+ ///
+ typedef unsigned short CHAR16;
+ ///
+ /// 2-byte signed value.
+ ///
+ typedef short INT16;
+ ///
+ /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
+ /// values are undefined.
+ ///
+ typedef unsigned char BOOLEAN;
+ ///
+ /// 1-byte unsigned value.
+ ///
+ typedef unsigned char UINT8;
+ ///
+ /// 1-byte Character.
+ ///
+ typedef char CHAR8;
+ ///
+ /// 1-byte signed value.
+ ///
+ typedef char INT8;
+#else
+ ///
+ /// 8-byte unsigned value.
+ ///
+ typedef unsigned long long UINT64;
+ ///
+ /// 8-byte signed value.
+ ///
+ typedef long long INT64;
+ ///
+ /// 4-byte unsigned value.
+ ///
+ typedef unsigned int UINT32;
+ ///
+ /// 4-byte signed value.
+ ///
+ typedef int INT32;
+ ///
+ /// 2-byte unsigned value.
+ ///
+ typedef unsigned short UINT16;
+ ///
+ /// 2-byte Character. Unless otherwise specified all strings are stored in the
+ /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
+ ///
+ typedef unsigned short CHAR16;
+ ///
+ /// 2-byte signed value.
+ ///
+ typedef short INT16;
+ ///
+ /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
+ /// values are undefined.
+ ///
+ typedef unsigned char BOOLEAN;
+ ///
+ /// 1-byte unsigned value.
+ ///
+ typedef unsigned char UINT8;
+ ///
+ /// 1-byte Character
+ ///
+ typedef char CHAR8;
+ ///
+ /// 1-byte signed value
+ ///
+ typedef char INT8;
+#endif
+
+///
+/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions;
+/// 8 bytes on supported 64-bit processor instructions.)
+///
+typedef UINT32 UINTN;
+///
+/// Signed value of native width. (4 bytes on supported 32-bit processor instructions;
+/// 8 bytes on supported 64-bit processor instructions.)
+///
+typedef INT32 INTN;
+
+//
+// Processor specific defines
+//
+
+///
+/// A value of native width with the highest bit set.
+///
+#define MAX_BIT 0x80000000
+///
+/// A value of native width with the two highest bits set.
+///
+#define MAX_2_BITS 0xC0000000
+
+///
+/// Maximum legal IA-32 address.
+///
+#define MAX_ADDRESS 0xFFFFFFFF
+
+///
+/// The stack alignment required for IA-32.
+///
+#define CPU_STACK_ALIGNMENT sizeof(UINTN)
+
+//
+// Modifier to ensure that all protocol member functions and EFI intrinsics
+// use the correct C calling convention. All protocol member functions and
+// EFI intrinsics are required to modify their member functions with EFIAPI.
+//
+#ifdef EFIAPI
+ ///
+ /// If EFIAPI is already defined, then we use that definition.
+ ///
+#elif defined(_MSC_EXTENSIONS)
+ ///
+ /// Microsoft* compiler specific method for EFIAPI calling convention.
+ ///
+ #define EFIAPI __cdecl
+#else
+ #if defined(__GNUC__)
+ ///
+ /// GCC specific method for EFIAPI calling convention.
+ ///
+ #define EFIAPI __attribute__((cdecl))
+ #endif
+#endif
+
+#if defined(__GNUC__)
+ ///
+ /// For GNU assembly code, .global or .globl can declare global symbols.
+ /// Define this macro to unify the usage.
+ ///
+ #define ASM_GLOBAL .globl
+#endif
+
+/**
+ Return the pointer to the first instruction of a function given a function pointer.
+ On IA-32 CPU architectures, these two pointer values are the same,
+ so the implementation of this macro is very simple.
+
+ @param FunctionPointer A pointer to a function.
+
+ @return The pointer to the first instruction of a function given a function pointer.
+
+**/
+#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer)
+
+#endif
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/IndustryStandard/Pci22.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/IndustryStandard/Pci22.h
new file mode 100644
index 00000000..b57059a9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/IndustryStandard/Pci22.h
@@ -0,0 +1,817 @@
+/** @file
+ Support for PCI 2.2 standard.
+
+ This file includes the definitions in the following specifications,
+ PCI Local Bus Specification, 2.2
+ PCI-to-PCI Bridge Architecture Specification, Revision 1.2
+ PC Card Standard, 8.0
+
+ Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCI22_H_
+#define _PCI22_H_
+
+FILE_LICENCE ( BSD3 );
+
+#define PCI_MAX_BUS 255
+#define PCI_MAX_DEVICE 31
+#define PCI_MAX_FUNC 7
+
+#pragma pack(1)
+
+///
+/// Common header region in PCI Configuration Space
+/// Section 6.1, PCI Local Bus Specification, 2.2
+///
+typedef struct {
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ UINT16 Command;
+ UINT16 Status;
+ UINT8 RevisionID;
+ UINT8 ClassCode[3];
+ UINT8 CacheLineSize;
+ UINT8 LatencyTimer;
+ UINT8 HeaderType;
+ UINT8 BIST;
+} PCI_DEVICE_INDEPENDENT_REGION;
+
+///
+/// PCI Device header region in PCI Configuration Space
+/// Section 6.1, PCI Local Bus Specification, 2.2
+///
+typedef struct {
+ UINT32 Bar[6];
+ UINT32 CISPtr;
+ UINT16 SubsystemVendorID;
+ UINT16 SubsystemID;
+ UINT32 ExpansionRomBar;
+ UINT8 CapabilityPtr;
+ UINT8 Reserved1[3];
+ UINT32 Reserved2;
+ UINT8 InterruptLine;
+ UINT8 InterruptPin;
+ UINT8 MinGnt;
+ UINT8 MaxLat;
+} PCI_DEVICE_HEADER_TYPE_REGION;
+
+///
+/// PCI Device Configuration Space
+/// Section 6.1, PCI Local Bus Specification, 2.2
+///
+typedef struct {
+ PCI_DEVICE_INDEPENDENT_REGION Hdr;
+ PCI_DEVICE_HEADER_TYPE_REGION Device;
+} PCI_TYPE00;
+
+///
+/// PCI-PCI Bridge header region in PCI Configuration Space
+/// Section 3.2, PCI-PCI Bridge Architecture, Version 1.2
+///
+typedef struct {
+ UINT32 Bar[2];
+ UINT8 PrimaryBus;
+ UINT8 SecondaryBus;
+ UINT8 SubordinateBus;
+ UINT8 SecondaryLatencyTimer;
+ UINT8 IoBase;
+ UINT8 IoLimit;
+ UINT16 SecondaryStatus;
+ UINT16 MemoryBase;
+ UINT16 MemoryLimit;
+ UINT16 PrefetchableMemoryBase;
+ UINT16 PrefetchableMemoryLimit;
+ UINT32 PrefetchableBaseUpper32;
+ UINT32 PrefetchableLimitUpper32;
+ UINT16 IoBaseUpper16;
+ UINT16 IoLimitUpper16;
+ UINT8 CapabilityPtr;
+ UINT8 Reserved[3];
+ UINT32 ExpansionRomBAR;
+ UINT8 InterruptLine;
+ UINT8 InterruptPin;
+ UINT16 BridgeControl;
+} PCI_BRIDGE_CONTROL_REGISTER;
+
+///
+/// PCI-to-PCI Bridge Configuration Space
+/// Section 3.2, PCI-PCI Bridge Architecture, Version 1.2
+///
+typedef struct {
+ PCI_DEVICE_INDEPENDENT_REGION Hdr;
+ PCI_BRIDGE_CONTROL_REGISTER Bridge;
+} PCI_TYPE01;
+
+typedef union {
+ PCI_TYPE00 Device;
+ PCI_TYPE01 Bridge;
+} PCI_TYPE_GENERIC;
+
+///
+/// CardBus Conroller Configuration Space,
+/// Section 4.5.1, PC Card Standard. 8.0
+///
+typedef struct {
+ UINT32 CardBusSocketReg; ///< Cardus Socket/ExCA Base
+ UINT8 Cap_Ptr;
+ UINT8 Reserved;
+ UINT16 SecondaryStatus; ///< Secondary Status
+ UINT8 PciBusNumber; ///< PCI Bus Number
+ UINT8 CardBusBusNumber; ///< CardBus Bus Number
+ UINT8 SubordinateBusNumber; ///< Subordinate Bus Number
+ UINT8 CardBusLatencyTimer; ///< CardBus Latency Timer
+ UINT32 MemoryBase0; ///< Memory Base Register 0
+ UINT32 MemoryLimit0; ///< Memory Limit Register 0
+ UINT32 MemoryBase1;
+ UINT32 MemoryLimit1;
+ UINT32 IoBase0;
+ UINT32 IoLimit0; ///< I/O Base Register 0
+ UINT32 IoBase1; ///< I/O Limit Register 0
+ UINT32 IoLimit1;
+ UINT8 InterruptLine; ///< Interrupt Line
+ UINT8 InterruptPin; ///< Interrupt Pin
+ UINT16 BridgeControl; ///< Bridge Control
+} PCI_CARDBUS_CONTROL_REGISTER;
+
+//
+// Definitions of PCI class bytes and manipulation macros.
+//
+#define PCI_CLASS_OLD 0x00
+#define PCI_CLASS_OLD_OTHER 0x00
+#define PCI_CLASS_OLD_VGA 0x01
+
+#define PCI_CLASS_MASS_STORAGE 0x01
+#define PCI_CLASS_MASS_STORAGE_SCSI 0x00
+#define PCI_CLASS_MASS_STORAGE_IDE 0x01
+#define PCI_CLASS_MASS_STORAGE_FLOPPY 0x02
+#define PCI_CLASS_MASS_STORAGE_IPI 0x03
+#define PCI_CLASS_MASS_STORAGE_RAID 0x04
+#define PCI_CLASS_MASS_STORAGE_OTHER 0x80
+
+#define PCI_CLASS_NETWORK 0x02
+#define PCI_CLASS_NETWORK_ETHERNET 0x00
+#define PCI_CLASS_NETWORK_TOKENRING 0x01
+#define PCI_CLASS_NETWORK_FDDI 0x02
+#define PCI_CLASS_NETWORK_ATM 0x03
+#define PCI_CLASS_NETWORK_ISDN 0x04
+#define PCI_CLASS_NETWORK_OTHER 0x80
+
+#define PCI_CLASS_DISPLAY 0x03
+#define PCI_CLASS_DISPLAY_VGA 0x00
+#define PCI_IF_VGA_VGA 0x00
+#define PCI_IF_VGA_8514 0x01
+#define PCI_CLASS_DISPLAY_XGA 0x01
+#define PCI_CLASS_DISPLAY_3D 0x02
+#define PCI_CLASS_DISPLAY_OTHER 0x80
+
+#define PCI_CLASS_MEDIA 0x04
+#define PCI_CLASS_MEDIA_VIDEO 0x00
+#define PCI_CLASS_MEDIA_AUDIO 0x01
+#define PCI_CLASS_MEDIA_TELEPHONE 0x02
+#define PCI_CLASS_MEDIA_OTHER 0x80
+
+#define PCI_CLASS_MEMORY_CONTROLLER 0x05
+#define PCI_CLASS_MEMORY_RAM 0x00
+#define PCI_CLASS_MEMORY_FLASH 0x01
+#define PCI_CLASS_MEMORY_OTHER 0x80
+
+#define PCI_CLASS_BRIDGE 0x06
+#define PCI_CLASS_BRIDGE_HOST 0x00
+#define PCI_CLASS_BRIDGE_ISA 0x01
+#define PCI_CLASS_BRIDGE_EISA 0x02
+#define PCI_CLASS_BRIDGE_MCA 0x03
+#define PCI_CLASS_BRIDGE_P2P 0x04
+#define PCI_IF_BRIDGE_P2P 0x00
+#define PCI_IF_BRIDGE_P2P_SUBTRACTIVE 0x01
+#define PCI_CLASS_BRIDGE_PCMCIA 0x05
+#define PCI_CLASS_BRIDGE_NUBUS 0x06
+#define PCI_CLASS_BRIDGE_CARDBUS 0x07
+#define PCI_CLASS_BRIDGE_RACEWAY 0x08
+#define PCI_CLASS_BRIDGE_OTHER 0x80
+#define PCI_CLASS_BRIDGE_ISA_PDECODE 0x80
+
+#define PCI_CLASS_SCC 0x07 ///< Simple communications controllers
+#define PCI_SUBCLASS_SERIAL 0x00
+#define PCI_IF_GENERIC_XT 0x00
+#define PCI_IF_16450 0x01
+#define PCI_IF_16550 0x02
+#define PCI_IF_16650 0x03
+#define PCI_IF_16750 0x04
+#define PCI_IF_16850 0x05
+#define PCI_IF_16950 0x06
+#define PCI_SUBCLASS_PARALLEL 0x01
+#define PCI_IF_PARALLEL_PORT 0x00
+#define PCI_IF_BI_DIR_PARALLEL_PORT 0x01
+#define PCI_IF_ECP_PARALLEL_PORT 0x02
+#define PCI_IF_1284_CONTROLLER 0x03
+#define PCI_IF_1284_DEVICE 0xFE
+#define PCI_SUBCLASS_MULTIPORT_SERIAL 0x02
+#define PCI_SUBCLASS_MODEM 0x03
+#define PCI_IF_GENERIC_MODEM 0x00
+#define PCI_IF_16450_MODEM 0x01
+#define PCI_IF_16550_MODEM 0x02
+#define PCI_IF_16650_MODEM 0x03
+#define PCI_IF_16750_MODEM 0x04
+#define PCI_SUBCLASS_SCC_OTHER 0x80
+
+#define PCI_CLASS_SYSTEM_PERIPHERAL 0x08
+#define PCI_SUBCLASS_PIC 0x00
+#define PCI_IF_8259_PIC 0x00
+#define PCI_IF_ISA_PIC 0x01
+#define PCI_IF_EISA_PIC 0x02
+#define PCI_IF_APIC_CONTROLLER 0x10 ///< I/O APIC interrupt controller , 32 bye none-prefectable memory.
+#define PCI_IF_APIC_CONTROLLER2 0x20
+#define PCI_SUBCLASS_DMA 0x01
+#define PCI_IF_8237_DMA 0x00
+#define PCI_IF_ISA_DMA 0x01
+#define PCI_IF_EISA_DMA 0x02
+#define PCI_SUBCLASS_TIMER 0x02
+#define PCI_IF_8254_TIMER 0x00
+#define PCI_IF_ISA_TIMER 0x01
+#define PCI_IF_EISA_TIMER 0x02
+#define PCI_SUBCLASS_RTC 0x03
+#define PCI_IF_GENERIC_RTC 0x00
+#define PCI_IF_ISA_RTC 0x00
+#define PCI_SUBCLASS_PNP_CONTROLLER 0x04 ///< HotPlug Controller
+#define PCI_SUBCLASS_PERIPHERAL_OTHER 0x80
+
+#define PCI_CLASS_INPUT_DEVICE 0x09
+#define PCI_SUBCLASS_KEYBOARD 0x00
+#define PCI_SUBCLASS_PEN 0x01
+#define PCI_SUBCLASS_MOUSE_CONTROLLER 0x02
+#define PCI_SUBCLASS_SCAN_CONTROLLER 0x03
+#define PCI_SUBCLASS_GAMEPORT 0x04
+#define PCI_IF_GAMEPORT 0x00
+#define PCI_IF_GAMEPORT1 0x01
+#define PCI_SUBCLASS_INPUT_OTHER 0x80
+
+#define PCI_CLASS_DOCKING_STATION 0x0A
+
+#define PCI_CLASS_PROCESSOR 0x0B
+#define PCI_SUBCLASS_PROC_386 0x00
+#define PCI_SUBCLASS_PROC_486 0x01
+#define PCI_SUBCLASS_PROC_PENTIUM 0x02
+#define PCI_SUBCLASS_PROC_ALPHA 0x10
+#define PCI_SUBCLASS_PROC_POWERPC 0x20
+#define PCI_SUBCLASS_PROC_MIPS 0x30
+#define PCI_SUBCLASS_PROC_CO_PORC 0x40 ///< Co-Processor
+
+#define PCI_CLASS_SERIAL 0x0C
+#define PCI_CLASS_SERIAL_FIREWIRE 0x00
+#define PCI_IF_1394 0x00
+#define PCI_IF_1394_OPEN_HCI 0x10
+#define PCI_CLASS_SERIAL_ACCESS_BUS 0x01
+#define PCI_CLASS_SERIAL_SSA 0x02
+#define PCI_CLASS_SERIAL_USB 0x03
+#define PCI_IF_UHCI 0x00
+#define PCI_IF_OHCI 0x10
+#define PCI_IF_USB_OTHER 0x80
+#define PCI_IF_USB_DEVICE 0xFE
+#define PCI_CLASS_SERIAL_FIBRECHANNEL 0x04
+#define PCI_CLASS_SERIAL_SMB 0x05
+
+#define PCI_CLASS_WIRELESS 0x0D
+#define PCI_SUBCLASS_IRDA 0x00
+#define PCI_SUBCLASS_IR 0x01
+#define PCI_SUBCLASS_RF 0x02
+#define PCI_SUBCLASS_WIRELESS_OTHER 0x80
+
+#define PCI_CLASS_INTELLIGENT_IO 0x0E
+
+#define PCI_CLASS_SATELLITE 0x0F
+#define PCI_SUBCLASS_TV 0x01
+#define PCI_SUBCLASS_AUDIO 0x02
+#define PCI_SUBCLASS_VOICE 0x03
+#define PCI_SUBCLASS_DATA 0x04
+
+#define PCI_SECURITY_CONTROLLER 0x10 ///< Encryption and decryption controller
+#define PCI_SUBCLASS_NET_COMPUT 0x00
+#define PCI_SUBCLASS_ENTERTAINMENT 0x10
+#define PCI_SUBCLASS_SECURITY_OTHER 0x80
+
+#define PCI_CLASS_DPIO 0x11
+#define PCI_SUBCLASS_DPIO 0x00
+#define PCI_SUBCLASS_DPIO_OTHER 0x80
+
+/**
+ Macro that checks whether the Base Class code of device matched.
+
+ @param _p Specified device.
+ @param c Base Class code needs matching.
+
+ @retval TRUE Base Class code matches the specified device.
+ @retval FALSE Base Class code doesn't match the specified device.
+
+**/
+#define IS_CLASS1(_p, c) ((_p)->Hdr.ClassCode[2] == (c))
+/**
+ Macro that checks whether the Base Class code and Sub-Class code of device matched.
+
+ @param _p Specified device.
+ @param c Base Class code needs matching.
+ @param s Sub-Class code needs matching.
+
+ @retval TRUE Base Class code and Sub-Class code match the specified device.
+ @retval FALSE Base Class code and Sub-Class code don't match the specified device.
+
+**/
+#define IS_CLASS2(_p, c, s) (IS_CLASS1 (_p, c) && ((_p)->Hdr.ClassCode[1] == (s)))
+/**
+ Macro that checks whether the Base Class code, Sub-Class code and Interface code of device matched.
+
+ @param _p Specified device.
+ @param c Base Class code needs matching.
+ @param s Sub-Class code needs matching.
+ @param p Interface code needs matching.
+
+ @retval TRUE Base Class code, Sub-Class code and Interface code match the specified device.
+ @retval FALSE Base Class code, Sub-Class code and Interface code don't match the specified device.
+
+**/
+#define IS_CLASS3(_p, c, s, p) (IS_CLASS2 (_p, c, s) && ((_p)->Hdr.ClassCode[0] == (p)))
+
+/**
+ Macro that checks whether device is a display controller.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is a display controller.
+ @retval FALSE Device is not a display controller.
+
+**/
+#define IS_PCI_DISPLAY(_p) IS_CLASS1 (_p, PCI_CLASS_DISPLAY)
+/**
+ Macro that checks whether device is a VGA-compatible controller.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is a VGA-compatible controller.
+ @retval FALSE Device is not a VGA-compatible controller.
+
+**/
+#define IS_PCI_VGA(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, PCI_IF_VGA_VGA)
+/**
+ Macro that checks whether device is an 8514-compatible controller.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is an 8514-compatible controller.
+ @retval FALSE Device is not an 8514-compatible controller.
+
+**/
+#define IS_PCI_8514(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, PCI_IF_VGA_8514)
+/**
+ Macro that checks whether device is built before the Class Code field was defined.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is an old device.
+ @retval FALSE Device is not an old device.
+
+**/
+#define IS_PCI_OLD(_p) IS_CLASS1 (_p, PCI_CLASS_OLD)
+/**
+ Macro that checks whether device is a VGA-compatible device built before the Class Code field was defined.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is an old VGA-compatible device.
+ @retval FALSE Device is not an old VGA-compatible device.
+
+**/
+#define IS_PCI_OLD_VGA(_p) IS_CLASS2 (_p, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA)
+/**
+ Macro that checks whether device is an IDE controller.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is an IDE controller.
+ @retval FALSE Device is not an IDE controller.
+
+**/
+#define IS_PCI_IDE(_p) IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_IDE)
+/**
+ Macro that checks whether device is a SCSI bus controller.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is a SCSI bus controller.
+ @retval FALSE Device is not a SCSI bus controller.
+
+**/
+#define IS_PCI_SCSI(_p) IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_SCSI)
+/**
+ Macro that checks whether device is a RAID controller.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is a RAID controller.
+ @retval FALSE Device is not a RAID controller.
+
+**/
+#define IS_PCI_RAID(_p) IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_RAID)
+/**
+ Macro that checks whether device is an ISA bridge.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is an ISA bridge.
+ @retval FALSE Device is not an ISA bridge.
+
+**/
+#define IS_PCI_LPC(_p) IS_CLASS2 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA)
+/**
+ Macro that checks whether device is a PCI-to-PCI bridge.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is a PCI-to-PCI bridge.
+ @retval FALSE Device is not a PCI-to-PCI bridge.
+
+**/
+#define IS_PCI_P2P(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, PCI_IF_BRIDGE_P2P)
+/**
+ Macro that checks whether device is a Subtractive Decode PCI-to-PCI bridge.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is a Subtractive Decode PCI-to-PCI bridge.
+ @retval FALSE Device is not a Subtractive Decode PCI-to-PCI bridge.
+
+**/
+#define IS_PCI_P2P_SUB(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, PCI_IF_BRIDGE_P2P_SUBTRACTIVE)
+/**
+ Macro that checks whether device is a 16550-compatible serial controller.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is a 16550-compatible serial controller.
+ @retval FALSE Device is not a 16550-compatible serial controller.
+
+**/
+#define IS_PCI_16550_SERIAL(_p) IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)
+/**
+ Macro that checks whether device is a Universal Serial Bus controller.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is a Universal Serial Bus controller.
+ @retval FALSE Device is not a Universal Serial Bus controller.
+
+**/
+#define IS_PCI_USB(_p) IS_CLASS2 (_p, PCI_CLASS_SERIAL, PCI_CLASS_SERIAL_USB)
+
+//
+// the definition of Header Type
+//
+#define HEADER_TYPE_DEVICE 0x00
+#define HEADER_TYPE_PCI_TO_PCI_BRIDGE 0x01
+#define HEADER_TYPE_CARDBUS_BRIDGE 0x02
+#define HEADER_TYPE_MULTI_FUNCTION 0x80
+//
+// Mask of Header type
+//
+#define HEADER_LAYOUT_CODE 0x7f
+/**
+ Macro that checks whether device is a PCI-PCI bridge.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is a PCI-PCI bridge.
+ @retval FALSE Device is not a PCI-PCI bridge.
+
+**/
+#define IS_PCI_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_PCI_TO_PCI_BRIDGE))
+/**
+ Macro that checks whether device is a CardBus bridge.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is a CardBus bridge.
+ @retval FALSE Device is not a CardBus bridge.
+
+**/
+#define IS_CARDBUS_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE))
+/**
+ Macro that checks whether device is a multiple functions device.
+
+ @param _p Specified device.
+
+ @retval TRUE Device is a multiple functions device.
+ @retval FALSE Device is not a multiple functions device.
+
+**/
+#define IS_PCI_MULTI_FUNC(_p) ((_p)->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)
+
+///
+/// Rom Base Address in Bridge, defined in PCI-to-PCI Bridge Architecure Specification,
+///
+#define PCI_BRIDGE_ROMBAR 0x38
+
+#define PCI_MAX_BAR 0x0006
+#define PCI_MAX_CONFIG_OFFSET 0x0100
+
+#define PCI_VENDOR_ID_OFFSET 0x00
+#define PCI_DEVICE_ID_OFFSET 0x02
+#define PCI_COMMAND_OFFSET 0x04
+#define PCI_PRIMARY_STATUS_OFFSET 0x06
+#define PCI_REVISION_ID_OFFSET 0x08
+#define PCI_CLASSCODE_OFFSET 0x09
+#define PCI_CACHELINE_SIZE_OFFSET 0x0C
+#define PCI_LATENCY_TIMER_OFFSET 0x0D
+#define PCI_HEADER_TYPE_OFFSET 0x0E
+#define PCI_BIST_OFFSET 0x0F
+#define PCI_BASE_ADDRESSREG_OFFSET 0x10
+#define PCI_CARDBUS_CIS_OFFSET 0x28
+#define PCI_SVID_OFFSET 0x2C ///< SubSystem Vendor id
+#define PCI_SUBSYSTEM_VENDOR_ID_OFFSET 0x2C
+#define PCI_SID_OFFSET 0x2E ///< SubSystem ID
+#define PCI_SUBSYSTEM_ID_OFFSET 0x2E
+#define PCI_EXPANSION_ROM_BASE 0x30
+#define PCI_CAPBILITY_POINTER_OFFSET 0x34
+#define PCI_INT_LINE_OFFSET 0x3C ///< Interrupt Line Register
+#define PCI_INT_PIN_OFFSET 0x3D ///< Interrupt Pin Register
+#define PCI_MAXGNT_OFFSET 0x3E ///< Max Grant Register
+#define PCI_MAXLAT_OFFSET 0x3F ///< Max Latency Register
+
+//
+// defined in PCI-to-PCI Bridge Architecture Specification
+//
+#define PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET 0x18
+#define PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET 0x19
+#define PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET 0x1a
+#define PCI_BRIDGE_STATUS_REGISTER_OFFSET 0x1E
+#define PCI_BRIDGE_CONTROL_REGISTER_OFFSET 0x3E
+
+///
+/// Interrupt Line "Unknown" or "No connection" value defined for x86 based system
+///
+#define PCI_INT_LINE_UNKNOWN 0xFF
+
+///
+/// PCI Access Data Format
+///
+typedef union {
+ struct {
+ UINT32 Reg : 8;
+ UINT32 Func : 3;
+ UINT32 Dev : 5;
+ UINT32 Bus : 8;
+ UINT32 Reserved : 7;
+ UINT32 Enable : 1;
+ } Bits;
+ UINT32 Uint32;
+} PCI_CONFIG_ACCESS_CF8;
+
+#pragma pack()
+
+#define EFI_PCI_COMMAND_IO_SPACE BIT0 ///< 0x0001
+#define EFI_PCI_COMMAND_MEMORY_SPACE BIT1 ///< 0x0002
+#define EFI_PCI_COMMAND_BUS_MASTER BIT2 ///< 0x0004
+#define EFI_PCI_COMMAND_SPECIAL_CYCLE BIT3 ///< 0x0008
+#define EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE BIT4 ///< 0x0010
+#define EFI_PCI_COMMAND_VGA_PALETTE_SNOOP BIT5 ///< 0x0020
+#define EFI_PCI_COMMAND_PARITY_ERROR_RESPOND BIT6 ///< 0x0040
+#define EFI_PCI_COMMAND_STEPPING_CONTROL BIT7 ///< 0x0080
+#define EFI_PCI_COMMAND_SERR BIT8 ///< 0x0100
+#define EFI_PCI_COMMAND_FAST_BACK_TO_BACK BIT9 ///< 0x0200
+
+//
+// defined in PCI-to-PCI Bridge Architecture Specification
+//
+#define EFI_PCI_BRIDGE_CONTROL_PARITY_ERROR_RESPONSE BIT0 ///< 0x0001
+#define EFI_PCI_BRIDGE_CONTROL_SERR BIT1 ///< 0x0002
+#define EFI_PCI_BRIDGE_CONTROL_ISA BIT2 ///< 0x0004
+#define EFI_PCI_BRIDGE_CONTROL_VGA BIT3 ///< 0x0008
+#define EFI_PCI_BRIDGE_CONTROL_VGA_16 BIT4 ///< 0x0010
+#define EFI_PCI_BRIDGE_CONTROL_MASTER_ABORT BIT5 ///< 0x0020
+#define EFI_PCI_BRIDGE_CONTROL_RESET_SECONDARY_BUS BIT6 ///< 0x0040
+#define EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK BIT7 ///< 0x0080
+#define EFI_PCI_BRIDGE_CONTROL_PRIMARY_DISCARD_TIMER BIT8 ///< 0x0100
+#define EFI_PCI_BRIDGE_CONTROL_SECONDARY_DISCARD_TIMER BIT9 ///< 0x0200
+#define EFI_PCI_BRIDGE_CONTROL_TIMER_STATUS BIT10 ///< 0x0400
+#define EFI_PCI_BRIDGE_CONTROL_DISCARD_TIMER_SERR BIT11 ///< 0x0800
+
+//
+// Following are the PCI-CARDBUS bridge control bit, defined in PC Card Standard
+//
+#define EFI_PCI_BRIDGE_CONTROL_IREQINT_ENABLE BIT7 ///< 0x0080
+#define EFI_PCI_BRIDGE_CONTROL_RANGE0_MEMORY_TYPE BIT8 ///< 0x0100
+#define EFI_PCI_BRIDGE_CONTROL_RANGE1_MEMORY_TYPE BIT9 ///< 0x0200
+#define EFI_PCI_BRIDGE_CONTROL_WRITE_POSTING_ENABLE BIT10 ///< 0x0400
+
+//
+// Following are the PCI status control bit
+//
+#define EFI_PCI_STATUS_CAPABILITY BIT4 ///< 0x0010
+#define EFI_PCI_STATUS_66MZ_CAPABLE BIT5 ///< 0x0020
+#define EFI_PCI_FAST_BACK_TO_BACK_CAPABLE BIT7 ///< 0x0080
+#define EFI_PCI_MASTER_DATA_PARITY_ERROR BIT8 ///< 0x0100
+
+///
+/// defined in PC Card Standard
+///
+#define EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR 0x14
+
+#pragma pack(1)
+//
+// PCI Capability List IDs and records
+//
+#define EFI_PCI_CAPABILITY_ID_PMI 0x01
+#define EFI_PCI_CAPABILITY_ID_AGP 0x02
+#define EFI_PCI_CAPABILITY_ID_VPD 0x03
+#define EFI_PCI_CAPABILITY_ID_SLOTID 0x04
+#define EFI_PCI_CAPABILITY_ID_MSI 0x05
+#define EFI_PCI_CAPABILITY_ID_HOTPLUG 0x06
+
+///
+/// Capabilities List Header
+/// Section 6.7, PCI Local Bus Specification, 2.2
+///
+typedef struct {
+ UINT8 CapabilityID;
+ UINT8 NextItemPtr;
+} EFI_PCI_CAPABILITY_HDR;
+
+///
+/// Power Management Register Block Definition
+/// Section 3.2, PCI Power Management Interface Specifiction, Revision 1.2
+///
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 PMC;
+ UINT16 PMCSR;
+ UINT8 BridgeExtention;
+ UINT8 Data;
+} EFI_PCI_CAPABILITY_PMI;
+
+///
+/// A.G.P Capability
+/// Section 6.1.4, Accelerated Graphics Port Interface Specification, Revision 1.0
+///
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT8 Rev;
+ UINT8 Reserved;
+ UINT32 Status;
+ UINT32 Command;
+} EFI_PCI_CAPABILITY_AGP;
+
+///
+/// VPD Capability Structure
+/// Appendix I, PCI Local Bus Specification, 2.2
+///
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 AddrReg;
+ UINT32 DataReg;
+} EFI_PCI_CAPABILITY_VPD;
+
+///
+/// Slot Numbering Capabilities Register
+/// Section 3.2.6, PCI-to-PCI Bridge Architeture Specification, Revision 1.2
+///
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT8 ExpnsSlotReg;
+ UINT8 ChassisNo;
+} EFI_PCI_CAPABILITY_SLOTID;
+
+///
+/// Message Capability Structure for 32-bit Message Address
+/// Section 6.8.1, PCI Local Bus Specification, 2.2
+///
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 MsgCtrlReg;
+ UINT32 MsgAddrReg;
+ UINT16 MsgDataReg;
+} EFI_PCI_CAPABILITY_MSI32;
+
+///
+/// Message Capability Structure for 64-bit Message Address
+/// Section 6.8.1, PCI Local Bus Specification, 2.2
+///
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 MsgCtrlReg;
+ UINT32 MsgAddrRegLsdw;
+ UINT32 MsgAddrRegMsdw;
+ UINT16 MsgDataReg;
+} EFI_PCI_CAPABILITY_MSI64;
+
+///
+/// Capability EFI_PCI_CAPABILITY_ID_HOTPLUG,
+/// CompactPCI Hot Swap Specification PICMG 2.1, R1.0
+///
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ ///
+ /// not finished - fields need to go here
+ ///
+} EFI_PCI_CAPABILITY_HOTPLUG;
+
+#define DEVICE_ID_NOCARE 0xFFFF
+
+#define PCI_ACPI_UNUSED 0
+#define PCI_BAR_NOCHANGE 0
+#define PCI_BAR_OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL
+#define PCI_BAR_EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL
+#define PCI_BAR_SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL
+#define PCI_BAR_DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL
+
+#define PCI_BAR_IDX0 0x00
+#define PCI_BAR_IDX1 0x01
+#define PCI_BAR_IDX2 0x02
+#define PCI_BAR_IDX3 0x03
+#define PCI_BAR_IDX4 0x04
+#define PCI_BAR_IDX5 0x05
+#define PCI_BAR_ALL 0xFF
+
+///
+/// EFI PCI Option ROM definitions
+///
+#define EFI_ROOT_BRIDGE_LIST 'eprb'
+#define EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE 0x0EF1 ///< defined in UEFI Spec.
+
+#define PCI_EXPANSION_ROM_HEADER_SIGNATURE 0xaa55
+#define PCI_DATA_STRUCTURE_SIGNATURE SIGNATURE_32 ('P', 'C', 'I', 'R')
+#define PCI_CODE_TYPE_PCAT_IMAGE 0x00
+#define EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED 0x0001 ///< defined in UEFI spec.
+
+///
+/// Standard PCI Expansion ROM Header
+/// Section 13.4.2, Unified Extensible Firmware Interface Specification, Version 2.1
+///
+typedef struct {
+ UINT16 Signature; ///< 0xaa55
+ UINT8 Reserved[0x16];
+ UINT16 PcirOffset;
+} PCI_EXPANSION_ROM_HEADER;
+
+///
+/// Legacy ROM Header Extensions
+/// Section 6.3.3.1, PCI Local Bus Specification, 2.2
+///
+typedef struct {
+ UINT16 Signature; ///< 0xaa55
+ UINT8 Size512;
+ UINT8 InitEntryPoint[3];
+ UINT8 Reserved[0x12];
+ UINT16 PcirOffset;
+} EFI_LEGACY_EXPANSION_ROM_HEADER;
+
+///
+/// PCI Data Structure Format
+/// Section 6.3.1.2, PCI Local Bus Specification, 2.2
+///
+typedef struct {
+ UINT32 Signature; ///< "PCIR"
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ UINT16 Reserved0;
+ UINT16 Length;
+ UINT8 Revision;
+ UINT8 ClassCode[3];
+ UINT16 ImageLength;
+ UINT16 CodeRevision;
+ UINT8 CodeType;
+ UINT8 Indicator;
+ UINT16 Reserved1;
+} PCI_DATA_STRUCTURE;
+
+///
+/// EFI PCI Expansion ROM Header
+/// Section 13.4.2, Unified Extensible Firmware Interface Specification, Version 2.1
+///
+typedef struct {
+ UINT16 Signature; ///< 0xaa55
+ UINT16 InitializationSize;
+ UINT32 EfiSignature; ///< 0x0EF1
+ UINT16 EfiSubsystem;
+ UINT16 EfiMachineType;
+ UINT16 CompressionType;
+ UINT8 Reserved[8];
+ UINT16 EfiImageHeaderOffset;
+ UINT16 PcirOffset;
+} EFI_PCI_EXPANSION_ROM_HEADER;
+
+typedef union {
+ UINT8 *Raw;
+ PCI_EXPANSION_ROM_HEADER *Generic;
+ EFI_PCI_EXPANSION_ROM_HEADER *Efi;
+ EFI_LEGACY_EXPANSION_ROM_HEADER *PcAt;
+} EFI_PCI_ROM_HEADER;
+
+#pragma pack()
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/IndustryStandard/PeImage.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/IndustryStandard/PeImage.h
new file mode 100644
index 00000000..fb4c2aaa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/IndustryStandard/PeImage.h
@@ -0,0 +1,757 @@
+/** @file
+ EFI image format for PE32, PE32+ and TE. Please note some data structures are
+ different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and
+ EFI_IMAGE_NT_HEADERS64 is for PE32+.
+
+ This file is coded to the Visual Studio, Microsoft Portable Executable and
+ Common Object File Format Specification, Revision 8.0 - May 16, 2006.
+ This file also includes some definitions in PI Specification, Revision 1.0.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PE_IMAGE_H__
+#define __PE_IMAGE_H__
+
+FILE_LICENCE ( BSD3 );
+
+//
+// PE32+ Subsystem type for EFI images
+//
+#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10
+#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
+#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 ///< defined PI Specification, 1.0
+
+
+//
+// PE32+ Machine type for EFI images
+//
+#define IMAGE_FILE_MACHINE_I386 0x014c
+#define IMAGE_FILE_MACHINE_IA64 0x0200
+#define IMAGE_FILE_MACHINE_EBC 0x0EBC
+#define IMAGE_FILE_MACHINE_X64 0x8664
+#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x01c2
+
+//
+// EXE file formats
+//
+#define EFI_IMAGE_DOS_SIGNATURE SIGNATURE_16('M', 'Z')
+#define EFI_IMAGE_OS2_SIGNATURE SIGNATURE_16('N', 'E')
+#define EFI_IMAGE_OS2_SIGNATURE_LE SIGNATURE_16('L', 'E')
+#define EFI_IMAGE_NT_SIGNATURE SIGNATURE_32('P', 'E', '\0', '\0')
+
+///
+/// PE images can start with an optional DOS header, so if an image is run
+/// under DOS it can print an error message.
+///
+typedef struct {
+ UINT16 e_magic; ///< Magic number.
+ UINT16 e_cblp; ///< Bytes on last page of file.
+ UINT16 e_cp; ///< Pages in file.
+ UINT16 e_crlc; ///< Relocations.
+ UINT16 e_cparhdr; ///< Size of header in paragraphs.
+ UINT16 e_minalloc; ///< Minimum extra paragraphs needed.
+ UINT16 e_maxalloc; ///< Maximum extra paragraphs needed.
+ UINT16 e_ss; ///< Initial (relative) SS value.
+ UINT16 e_sp; ///< Initial SP value.
+ UINT16 e_csum; ///< Checksum.
+ UINT16 e_ip; ///< Initial IP value.
+ UINT16 e_cs; ///< Initial (relative) CS value.
+ UINT16 e_lfarlc; ///< File address of relocation table.
+ UINT16 e_ovno; ///< Overlay number.
+ UINT16 e_res[4]; ///< Reserved words.
+ UINT16 e_oemid; ///< OEM identifier (for e_oeminfo).
+ UINT16 e_oeminfo; ///< OEM information; e_oemid specific.
+ UINT16 e_res2[10]; ///< Reserved words.
+ UINT32 e_lfanew; ///< File address of new exe header.
+} EFI_IMAGE_DOS_HEADER;
+
+///
+/// COFF File Header (Object and Image).
+///
+typedef struct {
+ UINT16 Machine;
+ UINT16 NumberOfSections;
+ UINT32 TimeDateStamp;
+ UINT32 PointerToSymbolTable;
+ UINT32 NumberOfSymbols;
+ UINT16 SizeOfOptionalHeader;
+ UINT16 Characteristics;
+} EFI_IMAGE_FILE_HEADER;
+
+///
+/// Size of EFI_IMAGE_FILE_HEADER.
+///
+#define EFI_IMAGE_SIZEOF_FILE_HEADER 20
+
+//
+// Characteristics
+//
+#define EFI_IMAGE_FILE_RELOCS_STRIPPED BIT0 ///< 0x0001 Relocation info stripped from file.
+#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE BIT1 ///< 0x0002 File is executable (i.e. no unresolved externel references).
+#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED BIT2 ///< 0x0004 Line nunbers stripped from file.
+#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED BIT3 ///< 0x0008 Local symbols stripped from file.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_LO BIT7 ///< 0x0080 Bytes of machine word are reversed.
+#define EFI_IMAGE_FILE_32BIT_MACHINE BIT8 ///< 0x0100 32 bit word machine.
+#define EFI_IMAGE_FILE_DEBUG_STRIPPED BIT9 ///< 0x0200 Debugging info stripped from file in .DBG file.
+#define EFI_IMAGE_FILE_SYSTEM BIT12 ///< 0x1000 System File.
+#define EFI_IMAGE_FILE_DLL BIT13 ///< 0x2000 File is a DLL.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_HI BIT15 ///< 0x8000 Bytes of machine word are reversed.
+
+///
+/// Header Data Directories.
+///
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 Size;
+} EFI_IMAGE_DATA_DIRECTORY;
+
+//
+// Directory Entries
+//
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0
+#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1
+#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
+#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4
+#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5
+#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6
+#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
+#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
+#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9
+#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
+
+#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
+
+///
+/// @attention
+/// EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC means PE32 and
+/// EFI_IMAGE_OPTIONAL_HEADER32 must be used. The data structures only vary
+/// after NT additional fields.
+///
+#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
+
+///
+/// Optional Header Standard Fields for PE32.
+///
+typedef struct {
+ ///
+ /// Standard fields.
+ ///
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ UINT32 BaseOfData; ///< PE32 contains this additional field, which is absent in PE32+.
+ ///
+ /// Optional Header Windows-Specific Fields.
+ ///
+ UINT32 ImageBase;
+ UINT32 SectionAlignment;
+ UINT32 FileAlignment;
+ UINT16 MajorOperatingSystemVersion;
+ UINT16 MinorOperatingSystemVersion;
+ UINT16 MajorImageVersion;
+ UINT16 MinorImageVersion;
+ UINT16 MajorSubsystemVersion;
+ UINT16 MinorSubsystemVersion;
+ UINT32 Win32VersionValue;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfHeaders;
+ UINT32 CheckSum;
+ UINT16 Subsystem;
+ UINT16 DllCharacteristics;
+ UINT32 SizeOfStackReserve;
+ UINT32 SizeOfStackCommit;
+ UINT32 SizeOfHeapReserve;
+ UINT32 SizeOfHeapCommit;
+ UINT32 LoaderFlags;
+ UINT32 NumberOfRvaAndSizes;
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER32;
+
+///
+/// @attention
+/// EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC means PE32+ and
+/// EFI_IMAGE_OPTIONAL_HEADER64 must be used. The data structures only vary
+/// after NT additional fields.
+///
+#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
+
+///
+/// Optional Header Standard Fields for PE32+.
+///
+typedef struct {
+ ///
+ /// Standard fields.
+ ///
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ ///
+ /// Optional Header Windows-Specific Fields.
+ ///
+ UINT64 ImageBase;
+ UINT32 SectionAlignment;
+ UINT32 FileAlignment;
+ UINT16 MajorOperatingSystemVersion;
+ UINT16 MinorOperatingSystemVersion;
+ UINT16 MajorImageVersion;
+ UINT16 MinorImageVersion;
+ UINT16 MajorSubsystemVersion;
+ UINT16 MinorSubsystemVersion;
+ UINT32 Win32VersionValue;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfHeaders;
+ UINT32 CheckSum;
+ UINT16 Subsystem;
+ UINT16 DllCharacteristics;
+ UINT64 SizeOfStackReserve;
+ UINT64 SizeOfStackCommit;
+ UINT64 SizeOfHeapReserve;
+ UINT64 SizeOfHeapCommit;
+ UINT32 LoaderFlags;
+ UINT32 NumberOfRvaAndSizes;
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER64;
+
+
+///
+/// @attention
+/// EFI_IMAGE_NT_HEADERS32 is for use ONLY by tools.
+///
+typedef struct {
+ UINT32 Signature;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS32;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32)
+
+///
+/// @attention
+/// EFI_IMAGE_HEADERS64 is for use ONLY by tools.
+///
+typedef struct {
+ UINT32 Signature;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS64;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64)
+
+//
+// Other Windows Subsystem Values
+//
+#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0
+#define EFI_IMAGE_SUBSYSTEM_NATIVE 1
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3
+#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5
+#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7
+
+///
+/// Length of ShortName.
+///
+#define EFI_IMAGE_SIZEOF_SHORT_NAME 8
+
+///
+/// Section Table. This table immediately follows the optional header.
+///
+typedef struct {
+ UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
+ union {
+ UINT32 PhysicalAddress;
+ UINT32 VirtualSize;
+ } Misc;
+ UINT32 VirtualAddress;
+ UINT32 SizeOfRawData;
+ UINT32 PointerToRawData;
+ UINT32 PointerToRelocations;
+ UINT32 PointerToLinenumbers;
+ UINT16 NumberOfRelocations;
+ UINT16 NumberOfLinenumbers;
+ UINT32 Characteristics;
+} EFI_IMAGE_SECTION_HEADER;
+
+///
+/// Size of EFI_IMAGE_SECTION_HEADER.
+///
+#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40
+
+//
+// Section Flags Values
+//
+#define EFI_IMAGE_SCN_TYPE_NO_PAD BIT3 ///< 0x00000008 ///< Reserved.
+#define EFI_IMAGE_SCN_CNT_CODE BIT5 ///< 0x00000020
+#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA BIT6 ///< 0x00000040
+#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA BIT7 ///< 0x00000080
+
+#define EFI_IMAGE_SCN_LNK_OTHER BIT8 ///< 0x00000100 ///< Reserved.
+#define EFI_IMAGE_SCN_LNK_INFO BIT9 ///< 0x00000200 ///< Section contains comments or some other type of information.
+#define EFI_IMAGE_SCN_LNK_REMOVE BIT11 ///< 0x00000800 ///< Section contents will not become part of image.
+#define EFI_IMAGE_SCN_LNK_COMDAT BIT12 ///< 0x00001000
+
+#define EFI_IMAGE_SCN_ALIGN_1BYTES BIT20 ///< 0x00100000
+#define EFI_IMAGE_SCN_ALIGN_2BYTES BIT21 ///< 0x00200000
+#define EFI_IMAGE_SCN_ALIGN_4BYTES (BIT20|BIT21) ///< 0x00300000
+#define EFI_IMAGE_SCN_ALIGN_8BYTES BIT22 ///< 0x00400000
+#define EFI_IMAGE_SCN_ALIGN_16BYTES (BIT20|BIT22) ///< 0x00500000
+#define EFI_IMAGE_SCN_ALIGN_32BYTES (BIT21|BIT22) ///< 0x00600000
+#define EFI_IMAGE_SCN_ALIGN_64BYTES (BIT20|BIT21|BIT22) ///< 0x00700000
+
+#define EFI_IMAGE_SCN_MEM_DISCARDABLE BIT25 ///< 0x02000000
+#define EFI_IMAGE_SCN_MEM_NOT_CACHED BIT26 ///< 0x04000000
+#define EFI_IMAGE_SCN_MEM_NOT_PAGED BIT27 ///< 0x08000000
+#define EFI_IMAGE_SCN_MEM_SHARED BIT28 ///< 0x10000000
+#define EFI_IMAGE_SCN_MEM_EXECUTE BIT29 ///< 0x20000000
+#define EFI_IMAGE_SCN_MEM_READ BIT30 ///< 0x40000000
+#define EFI_IMAGE_SCN_MEM_WRITE BIT31 ///< 0x80000000
+
+///
+/// Size of a Symbol Table Record.
+///
+#define EFI_IMAGE_SIZEOF_SYMBOL 18
+
+//
+// Symbols have a section number of the section in which they are
+// defined. Otherwise, section numbers have the following meanings:
+//
+#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 ///< Symbol is undefined or is common.
+#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 ///< Symbol is an absolute value.
+#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 ///< Symbol is a special debug item.
+
+//
+// Symbol Type (fundamental) values.
+//
+#define EFI_IMAGE_SYM_TYPE_NULL 0 ///< no type.
+#define EFI_IMAGE_SYM_TYPE_VOID 1 ///< no valid type.
+#define EFI_IMAGE_SYM_TYPE_CHAR 2 ///< type character.
+#define EFI_IMAGE_SYM_TYPE_SHORT 3 ///< type short integer.
+#define EFI_IMAGE_SYM_TYPE_INT 4
+#define EFI_IMAGE_SYM_TYPE_LONG 5
+#define EFI_IMAGE_SYM_TYPE_FLOAT 6
+#define EFI_IMAGE_SYM_TYPE_DOUBLE 7
+#define EFI_IMAGE_SYM_TYPE_STRUCT 8
+#define EFI_IMAGE_SYM_TYPE_UNION 9
+#define EFI_IMAGE_SYM_TYPE_ENUM 10 ///< enumeration.
+#define EFI_IMAGE_SYM_TYPE_MOE 11 ///< member of enumeration.
+#define EFI_IMAGE_SYM_TYPE_BYTE 12
+#define EFI_IMAGE_SYM_TYPE_WORD 13
+#define EFI_IMAGE_SYM_TYPE_UINT 14
+#define EFI_IMAGE_SYM_TYPE_DWORD 15
+
+//
+// Symbol Type (derived) values.
+//
+#define EFI_IMAGE_SYM_DTYPE_NULL 0 ///< no derived type.
+#define EFI_IMAGE_SYM_DTYPE_POINTER 1
+#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2
+#define EFI_IMAGE_SYM_DTYPE_ARRAY 3
+
+//
+// Storage classes.
+//
+#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION ((UINT8) -1)
+#define EFI_IMAGE_SYM_CLASS_NULL 0
+#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2
+#define EFI_IMAGE_SYM_CLASS_STATIC 3
+#define EFI_IMAGE_SYM_CLASS_REGISTER 4
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5
+#define EFI_IMAGE_SYM_CLASS_LABEL 6
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
+#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9
+#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
+#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12
+#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
+#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
+#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17
+#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18
+#define EFI_IMAGE_SYM_CLASS_BLOCK 100
+#define EFI_IMAGE_SYM_CLASS_FUNCTION 101
+#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102
+#define EFI_IMAGE_SYM_CLASS_FILE 103
+#define EFI_IMAGE_SYM_CLASS_SECTION 104
+#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
+
+//
+// type packing constants
+//
+#define EFI_IMAGE_N_BTMASK 017
+#define EFI_IMAGE_N_TMASK 060
+#define EFI_IMAGE_N_TMASK1 0300
+#define EFI_IMAGE_N_TMASK2 0360
+#define EFI_IMAGE_N_BTSHFT 4
+#define EFI_IMAGE_N_TSHIFT 2
+
+//
+// Communal selection types.
+//
+#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1
+#define EFI_IMAGE_COMDAT_SELECT_ANY 2
+#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3
+#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4
+#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5
+
+//
+// the following values only be referred in PeCoff, not defined in PECOFF.
+//
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
+
+///
+/// Relocation format.
+///
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 SymbolTableIndex;
+ UINT16 Type;
+} EFI_IMAGE_RELOCATION;
+
+///
+/// Size of EFI_IMAGE_RELOCATION
+///
+#define EFI_IMAGE_SIZEOF_RELOCATION 10
+
+//
+// I386 relocation types.
+//
+#define EFI_IMAGE_REL_I386_ABSOLUTE 0x0000 ///< Reference is absolute, no relocation is necessary.
+#define EFI_IMAGE_REL_I386_DIR16 0x0001 ///< Direct 16-bit reference to the symbols virtual address.
+#define EFI_IMAGE_REL_I386_REL16 0x0002 ///< PC-relative 16-bit reference to the symbols virtual address.
+#define EFI_IMAGE_REL_I386_DIR32 0x0006 ///< Direct 32-bit reference to the symbols virtual address.
+#define EFI_IMAGE_REL_I386_DIR32NB 0x0007 ///< Direct 32-bit reference to the symbols virtual address, base not included.
+#define EFI_IMAGE_REL_I386_SEG12 0x0009 ///< Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address.
+#define EFI_IMAGE_REL_I386_SECTION 0x000A
+#define EFI_IMAGE_REL_I386_SECREL 0x000B
+#define EFI_IMAGE_REL_I386_REL32 0x0014 ///< PC-relative 32-bit reference to the symbols virtual address.
+
+//
+// x64 processor relocation types.
+//
+#define IMAGE_REL_AMD64_ABSOLUTE 0x0000
+#define IMAGE_REL_AMD64_ADDR64 0x0001
+#define IMAGE_REL_AMD64_ADDR32 0x0002
+#define IMAGE_REL_AMD64_ADDR32NB 0x0003
+#define IMAGE_REL_AMD64_REL32 0x0004
+#define IMAGE_REL_AMD64_REL32_1 0x0005
+#define IMAGE_REL_AMD64_REL32_2 0x0006
+#define IMAGE_REL_AMD64_REL32_3 0x0007
+#define IMAGE_REL_AMD64_REL32_4 0x0008
+#define IMAGE_REL_AMD64_REL32_5 0x0009
+#define IMAGE_REL_AMD64_SECTION 0x000A
+#define IMAGE_REL_AMD64_SECREL 0x000B
+#define IMAGE_REL_AMD64_SECREL7 0x000C
+#define IMAGE_REL_AMD64_TOKEN 0x000D
+#define IMAGE_REL_AMD64_SREL32 0x000E
+#define IMAGE_REL_AMD64_PAIR 0x000F
+#define IMAGE_REL_AMD64_SSPAN32 0x0010
+
+///
+/// Based relocation format.
+///
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 SizeOfBlock;
+} EFI_IMAGE_BASE_RELOCATION;
+
+///
+/// Size of EFI_IMAGE_BASE_RELOCATION.
+///
+#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8
+
+//
+// Based relocation types.
+//
+#define EFI_IMAGE_REL_BASED_ABSOLUTE 0
+#define EFI_IMAGE_REL_BASED_HIGH 1
+#define EFI_IMAGE_REL_BASED_LOW 2
+#define EFI_IMAGE_REL_BASED_HIGHLOW 3
+#define EFI_IMAGE_REL_BASED_HIGHADJ 4
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5
+#define EFI_IMAGE_REL_BASED_ARM_MOV32A 5
+#define EFI_IMAGE_REL_BASED_ARM_MOV32T 7
+#define EFI_IMAGE_REL_BASED_IA64_IMM64 9
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR16 9
+#define EFI_IMAGE_REL_BASED_DIR64 10
+
+///
+/// Line number format.
+///
+typedef struct {
+ union {
+ UINT32 SymbolTableIndex; ///< Symbol table index of function name if Linenumber is 0.
+ UINT32 VirtualAddress; ///< Virtual address of line number.
+ } Type;
+ UINT16 Linenumber; ///< Line number.
+} EFI_IMAGE_LINENUMBER;
+
+///
+/// Size of EFI_IMAGE_LINENUMBER.
+///
+#define EFI_IMAGE_SIZEOF_LINENUMBER 6
+
+//
+// Archive format.
+//
+#define EFI_IMAGE_ARCHIVE_START_SIZE 8
+#define EFI_IMAGE_ARCHIVE_START "!<arch>\n"
+#define EFI_IMAGE_ARCHIVE_END "`\n"
+#define EFI_IMAGE_ARCHIVE_PAD "\n"
+#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ "
+#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// "
+
+///
+/// Archive Member Headers
+///
+typedef struct {
+ UINT8 Name[16]; ///< File member name - `/' terminated.
+ UINT8 Date[12]; ///< File member date - decimal.
+ UINT8 UserID[6]; ///< File member user id - decimal.
+ UINT8 GroupID[6]; ///< File member group id - decimal.
+ UINT8 Mode[8]; ///< File member mode - octal.
+ UINT8 Size[10]; ///< File member size - decimal.
+ UINT8 EndHeader[2]; ///< String to end header. (0x60 0x0A).
+} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;
+
+///
+/// Size of EFI_IMAGE_ARCHIVE_MEMBER_HEADER.
+///
+#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
+
+
+//
+// DLL Support
+//
+
+///
+/// Export Directory Table.
+///
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 Name;
+ UINT32 Base;
+ UINT32 NumberOfFunctions;
+ UINT32 NumberOfNames;
+ UINT32 AddressOfFunctions;
+ UINT32 AddressOfNames;
+ UINT32 AddressOfNameOrdinals;
+} EFI_IMAGE_EXPORT_DIRECTORY;
+
+///
+/// Hint/Name Table.
+///
+typedef struct {
+ UINT16 Hint;
+ UINT8 Name[1];
+} EFI_IMAGE_IMPORT_BY_NAME;
+
+///
+/// Import Address Table RVA (Thunk Table).
+///
+typedef struct {
+ union {
+ UINT32 Function;
+ UINT32 Ordinal;
+ EFI_IMAGE_IMPORT_BY_NAME *AddressOfData;
+ } u1;
+} EFI_IMAGE_THUNK_DATA;
+
+#define EFI_IMAGE_ORDINAL_FLAG BIT31 ///< Flag for PE32.
+#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)
+#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
+
+///
+/// Import Directory Table
+///
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT32 ForwarderChain;
+ UINT32 Name;
+ EFI_IMAGE_THUNK_DATA *FirstThunk;
+} EFI_IMAGE_IMPORT_DESCRIPTOR;
+
+
+///
+/// Debug Directory Format.
+///
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 Type;
+ UINT32 SizeOfData;
+ UINT32 RVA; ///< The address of the debug data when loaded, relative to the image base.
+ UINT32 FileOffset; ///< The file pointer to the debug data.
+} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;
+
+#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 ///< The Visual C++ debug information.
+
+///
+/// Debug Data Structure defined in Microsoft C++.
+///
+#define CODEVIEW_SIGNATURE_NB10 SIGNATURE_32('N', 'B', '1', '0')
+typedef struct {
+ UINT32 Signature; ///< "NB10"
+ UINT32 Unknown;
+ UINT32 Unknown2;
+ UINT32 Unknown3;
+ //
+ // Filename of .PDB goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;
+
+///
+/// Debug Data Structure defined in Microsoft C++.
+///
+#define CODEVIEW_SIGNATURE_RSDS SIGNATURE_32('R', 'S', 'D', 'S')
+typedef struct {
+ UINT32 Signature; ///< "RSDS".
+ UINT32 Unknown;
+ UINT32 Unknown2;
+ UINT32 Unknown3;
+ UINT32 Unknown4;
+ UINT32 Unknown5;
+ //
+ // Filename of .PDB goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;
+
+
+///
+/// Debug Data Structure defined by Apple Mach-O to Coff utility.
+///
+#define CODEVIEW_SIGNATURE_MTOC SIGNATURE_32('M', 'T', 'O', 'C')
+typedef struct {
+ UINT32 Signature; ///< "MTOC".
+ GUID MachOUuid;
+ //
+ // Filename of .DLL (Mach-O with debug info) goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY;
+
+///
+/// Resource format.
+///
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT16 NumberOfNamedEntries;
+ UINT16 NumberOfIdEntries;
+ //
+ // Array of EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY entries goes here.
+ //
+} EFI_IMAGE_RESOURCE_DIRECTORY;
+
+///
+/// Resource directory entry format.
+///
+typedef struct {
+ union {
+ struct {
+ UINT32 NameOffset:31;
+ UINT32 NameIsString:1;
+ } s;
+ UINT32 Id;
+ } u1;
+ union {
+ UINT32 OffsetToData;
+ struct {
+ UINT32 OffsetToDirectory:31;
+ UINT32 DataIsDirectory:1;
+ } s;
+ } u2;
+} EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY;
+
+///
+/// Resource directory entry for string.
+///
+typedef struct {
+ UINT16 Length;
+ CHAR16 String[1];
+} EFI_IMAGE_RESOURCE_DIRECTORY_STRING;
+
+///
+/// Resource directory entry for data array.
+///
+typedef struct {
+ UINT32 OffsetToData;
+ UINT32 Size;
+ UINT32 CodePage;
+ UINT32 Reserved;
+} EFI_IMAGE_RESOURCE_DATA_ENTRY;
+
+///
+/// Header format for TE images, defined in the PI Specification, 1.0.
+///
+typedef struct {
+ UINT16 Signature; ///< The signature for TE format = "VZ".
+ UINT16 Machine; ///< From the original file header.
+ UINT8 NumberOfSections; ///< From the original file header.
+ UINT8 Subsystem; ///< From original optional header.
+ UINT16 StrippedSize; ///< Number of bytes we removed from the header.
+ UINT32 AddressOfEntryPoint; ///< Offset to entry point -- from original optional header.
+ UINT32 BaseOfCode; ///< From original image -- required for ITP debug.
+ UINT64 ImageBase; ///< From original file header.
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; ///< Only base relocation and debug directory.
+} EFI_TE_IMAGE_HEADER;
+
+
+#define EFI_TE_IMAGE_HEADER_SIGNATURE SIGNATURE_16('V', 'Z')
+
+//
+// Data directory indexes in our TE image header
+//
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1
+
+
+///
+/// Union of PE32, PE32+, and TE headers.
+///
+typedef union {
+ EFI_IMAGE_NT_HEADERS32 Pe32;
+ EFI_IMAGE_NT_HEADERS64 Pe32Plus;
+ EFI_TE_IMAGE_HEADER Te;
+} EFI_IMAGE_OPTIONAL_HEADER_UNION;
+
+typedef union {
+ EFI_IMAGE_NT_HEADERS32 *Pe32;
+ EFI_IMAGE_NT_HEADERS64 *Pe32Plus;
+ EFI_TE_IMAGE_HEADER *Te;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *Union;
+} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/LICENCE b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/LICENCE
new file mode 100644
index 00000000..6c28e6f9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/LICENCE
@@ -0,0 +1,40 @@
+The EFI headers contained herein are copied from the EFI Development
+Kit, available from http://www.tianocore.org and published under the
+following licence:
+
+ BSD License from Intel
+ Copyright (c) 2004, Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+This licence applies only to files that are part of the EFI
+Development Kit. Other files may contain their own licence terms, or
+may fall under the standard iPXE GPL licence.
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiBootMode.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiBootMode.h
new file mode 100644
index 00000000..30fd4437
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiBootMode.h
@@ -0,0 +1,43 @@
+/** @file
+ Present the boot mode values in PI.
+
+ Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ PI Version 1.0
+
+**/
+
+#ifndef __PI_BOOT_MODE_H__
+#define __PI_BOOT_MODE_H__
+
+FILE_LICENCE ( BSD3 );
+
+///
+/// EFI boot mode
+///
+typedef UINT32 EFI_BOOT_MODE;
+
+//
+// 0x21 - 0xf..f are reserved.
+//
+#define BOOT_WITH_FULL_CONFIGURATION 0x00
+#define BOOT_WITH_MINIMAL_CONFIGURATION 0x01
+#define BOOT_ASSUMING_NO_CONFIGURATION_CHANGES 0x02
+#define BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS 0x03
+#define BOOT_WITH_DEFAULT_SETTINGS 0x04
+#define BOOT_ON_S4_RESUME 0x05
+#define BOOT_ON_S5_RESUME 0x06
+#define BOOT_ON_S2_RESUME 0x10
+#define BOOT_ON_S3_RESUME 0x11
+#define BOOT_ON_FLASH_UPDATE 0x12
+#define BOOT_IN_RECOVERY_MODE 0x20
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiDependency.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiDependency.h
new file mode 100644
index 00000000..b1fa399b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiDependency.h
@@ -0,0 +1,49 @@
+/** @file
+ Present the dependency expression values in PI.
+
+ Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ PI Version 1.0
+
+**/
+#ifndef __PI_DEPENDENCY_H__
+#define __PI_DEPENDENCY_H__
+
+FILE_LICENCE ( BSD3 );
+
+///
+/// If present, this must be the first and only opcode,
+/// EFI_DEP_BEFORE may be used by DXE and SMM drivers.
+///
+#define EFI_DEP_BEFORE 0x00
+
+///
+/// If present, this must be the first and only opcode,
+/// EFI_DEP_AFTER may be used by DXE and SMM drivers.
+///
+#define EFI_DEP_AFTER 0x01
+
+#define EFI_DEP_PUSH 0x02
+#define EFI_DEP_AND 0x03
+#define EFI_DEP_OR 0x04
+#define EFI_DEP_NOT 0x05
+#define EFI_DEP_TRUE 0x06
+#define EFI_DEP_FALSE 0x07
+#define EFI_DEP_END 0x08
+
+
+///
+/// If present, this must be the first opcode,
+/// EFI_DEP_SOR is only used by DXE driver.
+///
+#define EFI_DEP_SOR 0x09
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiDxeCis.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiDxeCis.h
new file mode 100644
index 00000000..6c4f44b9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiDxeCis.h
@@ -0,0 +1,715 @@
+/** @file
+ Include file matches things in PI.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ PI Version 1.0
+
+**/
+
+#ifndef __PI_DXECIS_H__
+#define __PI_DXECIS_H__
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/Uefi/UefiMultiPhase.h>
+#include <ipxe/efi/Pi/PiMultiPhase.h>
+
+///
+/// Global Coherencey Domain types - Memory type.
+///
+typedef enum {
+ ///
+ /// A memory region that is visible to the boot processor. However, there are no system
+ /// components that are currently decoding this memory region.
+ ///
+ EfiGcdMemoryTypeNonExistent,
+ ///
+ /// A memory region that is visible to the boot processor. This memory region is being
+ /// decoded by a system component, but the memory region is not considered to be either
+ /// system memory or memory-mapped I/O.
+ ///
+ EfiGcdMemoryTypeReserved,
+ ///
+ /// A memory region that is visible to the boot processor. A memory controller is
+ /// currently decoding this memory region and the memory controller is producing a
+ /// tested system memory region that is available to the memory services.
+ ///
+ EfiGcdMemoryTypeSystemMemory,
+ ///
+ /// A memory region that is visible to the boot processor. This memory region is
+ /// currently being decoded by a component as memory-mapped I/O that can be used to
+ /// access I/O devices in the platform.
+ ///
+ EfiGcdMemoryTypeMemoryMappedIo,
+ EfiGcdMemoryTypeMaximum
+} EFI_GCD_MEMORY_TYPE;
+
+///
+/// Global Coherencey Domain types - IO type.
+///
+typedef enum {
+ ///
+ /// An I/O region that is visible to the boot processor. However, there are no system
+ /// components that are currently decoding this I/O region.
+ ///
+ EfiGcdIoTypeNonExistent,
+ ///
+ /// An I/O region that is visible to the boot processor. This I/O region is currently being
+ /// decoded by a system component, but the I/O region cannot be used to access I/O devices.
+ ///
+ EfiGcdIoTypeReserved,
+ ///
+ /// An I/O region that is visible to the boot processor. This I/O region is currently being
+ /// decoded by a system component that is producing I/O ports that can be used to access I/O devices.
+ ///
+ EfiGcdIoTypeIo,
+ EfiGcdIoTypeMaximum
+} EFI_GCD_IO_TYPE;
+
+///
+/// The type of allocation to perform.
+///
+typedef enum {
+ ///
+ /// The GCD memory space map is searched from the lowest address up to the highest address
+ /// looking for unallocated memory ranges.
+ ///
+ EfiGcdAllocateAnySearchBottomUp,
+ ///
+ /// The GCD memory space map is searched from the lowest address up
+ /// to the specified MaxAddress looking for unallocated memory ranges.
+ ///
+ EfiGcdAllocateMaxAddressSearchBottomUp,
+ ///
+ /// The GCD memory space map is checked to see if the memory range starting
+ /// at the specified Address is available.
+ ///
+ EfiGcdAllocateAddress,
+ ///
+ /// The GCD memory space map is searched from the highest address down to the lowest address
+ /// looking for unallocated memory ranges.
+ ///
+ EfiGcdAllocateAnySearchTopDown,
+ ///
+ /// The GCD memory space map is searched from the specified MaxAddress
+ /// down to the lowest address looking for unallocated memory ranges.
+ ///
+ EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdMaxAllocateType
+} EFI_GCD_ALLOCATE_TYPE;
+
+///
+/// EFI_GCD_MEMORY_SPACE_DESCRIPTOR.
+///
+typedef struct {
+ ///
+ /// The physical address of the first byte in the memory region. Type
+ /// EFI_PHYSICAL_ADDRESS is defined in the AllocatePages() function
+ /// description in the UEFI 2.0 specification.
+ ///
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+
+ ///
+ /// The number of bytes in the memory region.
+ ///
+ UINT64 Length;
+
+ ///
+ /// The bit mask of attributes that the memory region is capable of supporting. The bit
+ /// mask of available attributes is defined in the GetMemoryMap() function description
+ /// in the UEFI 2.0 specification.
+ ///
+ UINT64 Capabilities;
+ ///
+ /// The bit mask of attributes that the memory region is currently using. The bit mask of
+ /// available attributes is defined in GetMemoryMap().
+ ///
+ UINT64 Attributes;
+ ///
+ /// Type of the memory region. Type EFI_GCD_MEMORY_TYPE is defined in the
+ /// AddMemorySpace() function description.
+ ///
+ EFI_GCD_MEMORY_TYPE GcdMemoryType;
+
+ ///
+ /// The image handle of the agent that allocated the memory resource described by
+ /// PhysicalStart and NumberOfBytes. If this field is NULL, then the memory
+ /// resource is not currently allocated. Type EFI_HANDLE is defined in
+ /// InstallProtocolInterface() in the UEFI 2.0 specification.
+ ///
+ EFI_HANDLE ImageHandle;
+
+ ///
+ /// The device handle for which the memory resource has been allocated. If
+ /// ImageHandle is NULL, then the memory resource is not currently allocated. If this
+ /// field is NULL, then the memory resource is not associated with a device that is
+ /// described by a device handle. Type EFI_HANDLE is defined in
+ /// InstallProtocolInterface() in the UEFI 2.0 specification.
+ ///
+ EFI_HANDLE DeviceHandle;
+} EFI_GCD_MEMORY_SPACE_DESCRIPTOR;
+
+///
+/// EFI_GCD_IO_SPACE_DESCRIPTOR.
+///
+typedef struct {
+ ///
+ /// Physical address of the first byte in the I/O region. Type
+ /// EFI_PHYSICAL_ADDRESS is defined in the AllocatePages() function
+ /// description in the UEFI 2.0 specification.
+ ///
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+
+ ///
+ /// Number of bytes in the I/O region.
+ ///
+ UINT64 Length;
+
+ ///
+ /// Type of the I/O region. Type EFI_GCD_IO_TYPE is defined in the
+ /// AddIoSpace() function description.
+ ///
+ EFI_GCD_IO_TYPE GcdIoType;
+
+ ///
+ /// The image handle of the agent that allocated the I/O resource described by
+ /// PhysicalStart and NumberOfBytes. If this field is NULL, then the I/O
+ /// resource is not currently allocated. Type EFI_HANDLE is defined in
+ /// InstallProtocolInterface() in the UEFI 2.0 specification.
+ ///
+ EFI_HANDLE ImageHandle;
+
+ ///
+ /// The device handle for which the I/O resource has been allocated. If ImageHandle
+ /// is NULL, then the I/O resource is not currently allocated. If this field is NULL, then
+ /// the I/O resource is not associated with a device that is described by a device handle.
+ /// Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI
+ /// 2.0 specification.
+ ///
+ EFI_HANDLE DeviceHandle;
+} EFI_GCD_IO_SPACE_DESCRIPTOR;
+
+
+/**
+ Adds reserved memory, system memory, or memory-mapped I/O resources to the
+ global coherency domain of the processor.
+
+ @param GcdMemoryType The type of memory resource being added.
+ @param BaseAddress The physical address that is the start address
+ of the memory resource being added.
+ @param Length The size, in bytes, of the memory resource that
+ is being added.
+ @param Capabilities The bit mask of attributes that the memory
+ resource region supports.
+
+ @retval EFI_SUCCESS The memory resource was added to the global
+ coherency domain of the processor.
+ @retval EFI_INVALID_PARAMETER GcdMemoryType is invalid.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to add
+ the memory resource to the global coherency
+ domain of the processor.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes
+ of the memory resource range specified by
+ BaseAddress and Length.
+ @retval EFI_ACCESS_DENIED One or more bytes of the memory resource range
+ specified by BaseAddress and Length conflicts
+ with a memory resource range that was previously
+ added to the global coherency domain of the processor.
+ @retval EFI_ACCESS_DENIED One or more bytes of the memory resource range
+ specified by BaseAddress and Length was allocated
+ in a prior call to AllocateMemorySpace().
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ADD_MEMORY_SPACE)(
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Capabilities
+ );
+
+/**
+ Allocates nonexistent memory, reserved memory, system memory, or memorymapped
+ I/O resources from the global coherency domain of the processor.
+
+ @param GcdAllocateType The type of allocation to perform.
+ @param GcdMemoryType The type of memory resource being allocated.
+ @param Alignment The log base 2 of the boundary that BaseAddress must
+ be aligned on output. Align with 2^Alignment.
+ @param Length The size in bytes of the memory resource range that
+ is being allocated.
+ @param BaseAddress A pointer to a physical address to allocate.
+ @param Imagehandle The image handle of the agent that is allocating
+ the memory resource.
+ @param DeviceHandle The device handle for which the memory resource
+ is being allocated.
+
+ @retval EFI_INVALID_PARAMETER GcdAllocateType is invalid.
+ @retval EFI_INVALID_PARAMETER GcdMemoryType is invalid.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ @retval EFI_INVALID_PARAMETER BaseAddress is NULL.
+ @retval EFI_INVALID_PARAMETER ImageHandle is NULL.
+ @retval EFI_NOT_FOUND The memory resource request could not be satisfied.
+ No descriptor contains the desired space.
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to allocate the memory
+ resource from the global coherency domain of the processor.
+ @retval EFI_SUCCESS The memory resource was allocated from the global coherency
+ domain of the processor.
+
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ALLOCATE_MEMORY_SPACE)(
+ IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle OPTIONAL
+ );
+
+/**
+ Frees nonexistent memory, reserved memory, system memory, or memory-mapped
+ I/O resources from the global coherency domain of the processor.
+
+ @param BaseAddress The physical address that is the start address of the memory resource being freed.
+ @param Length The size in bytes of the memory resource range that is being freed.
+
+ @retval EFI_SUCCESS The memory resource was freed from the global coherency domain of
+ the processor.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
+ resource range specified by BaseAddress and Length.
+ @retval EFI_NOT_FOUND The memory resource range specified by BaseAddress and
+ Length was not allocated with previous calls to AllocateMemorySpace().
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to free the memory resource
+ from the global coherency domain of the processor.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FREE_MEMORY_SPACE)(
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ );
+
+/**
+ Removes reserved memory, system memory, or memory-mapped I/O resources from
+ the global coherency domain of the processor.
+
+ @param BaseAddress The physical address that is the start address of the memory resource being removed.
+ @param Length The size in bytes of the memory resource that is being removed.
+
+ @retval EFI_SUCCESS The memory resource was removed from the global coherency
+ domain of the processor.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
+ resource range specified by BaseAddress and Length.
+ @retval EFI_NOT_FOUND One or more bytes of the memory resource range specified by
+ BaseAddress and Length was not added with previous calls to
+ AddMemorySpace().
+ @retval EFI_ACCESS_DEFINED One or more bytes of the memory resource range specified by
+ BaseAddress and Length has been allocated with AllocateMemorySpace().
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to remove the memory
+ resource from the global coherency domain of the processor.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REMOVE_MEMORY_SPACE)(
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ );
+
+/**
+ Retrieves the descriptor for a memory region containing a specified address.
+
+ @param BaseAddress The physical address that is the start address of a memory region.
+ @param Descriptor A pointer to a caller allocated descriptor.
+
+ @retval EFI_SUCCESS The descriptor for the memory resource region containing
+ BaseAddress was returned in Descriptor.
+ @retval EFI_INVALID_PARAMETER Descriptor is NULL.
+ @retval EFI_NOT_FOUND A memory resource range containing BaseAddress was not found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_MEMORY_SPACE_DESCRIPTOR)(
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor
+ );
+
+/**
+ Modifies the attributes for a memory region in the global coherency domain of the
+ processor.
+
+ @param BaseAddress The physical address that is the start address of a memory region.
+ @param Length The size in bytes of the memory region.
+ @param Attributes The bit mask of attributes to set for the memory region.
+
+ @retval EFI_SUCCESS The attributes were set for the memory region.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
+ resource range specified by BaseAddress and Length.
+ @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource
+ range specified by BaseAddress and Length.
+ @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by
+ BaseAddress and Length cannot be modified.
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
+ the memory resource range.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_MEMORY_SPACE_ATTRIBUTES)(
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ );
+
+/**
+ Returns a map of the memory resources in the global coherency domain of the
+ processor.
+
+ @param NumberOfDescriptors A pointer to number of descriptors returned in the MemorySpaceMap buffer.
+ @param MemorySpaceMap A pointer to the array of EFI_GCD_MEMORY_SPACE_DESCRIPTORs.
+
+ @retval EFI_SUCCESS The memory space map was returned in the MemorySpaceMap
+ buffer, and the number of descriptors in MemorySpaceMap was
+ returned in NumberOfDescriptors.
+ @retval EFI_INVALID_PARAMETER NumberOfDescriptors is NULL.
+ @retval EFI_INVALID_PARAMETER MemorySpaceMap is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate MemorySpaceMap.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_MEMORY_SPACE_MAP)(
+ OUT UINTN *NumberOfDescriptors,
+ OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap
+ );
+
+/**
+ Adds reserved I/O or I/O resources to the global coherency domain of the processor.
+
+ @param GcdIoType The type of I/O resource being added.
+ @param BaseAddress The physical address that is the start address of the I/O resource being added.
+ @param Length The size in bytes of the I/O resource that is being added.
+
+ @retval EFI_SUCCESS The I/O resource was added to the global coherency domain of
+ the processor.
+ @retval EFI_INVALID_PARAMETER GcdIoType is invalid.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to add the I/O resource to
+ the global coherency domain of the processor.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the I/O
+ resource range specified by BaseAddress and Length.
+ @retval EFI_ACCESS_DENIED One or more bytes of the I/O resource range specified by
+ BaseAddress and Length conflicts with an I/O resource
+ range that was previously added to the global coherency domain
+ of the processor.
+ @retval EFI_ACCESS_DENIED One or more bytes of the I/O resource range specified by
+ BaseAddress and Length was allocated in a prior call to
+ AllocateIoSpace().
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ADD_IO_SPACE)(
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ );
+
+/**
+ Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
+ domain of the processor.
+
+ @param GcdAllocateType The type of allocation to perform.
+ @param GcdIoType The type of I/O resource being allocated.
+ @param Alignment The log base 2 of the boundary that BaseAddress must be aligned on output.
+ @param Length The size in bytes of the I/O resource range that is being allocated.
+ @param BaseAddress A pointer to a physical address.
+ @param Imagehandle The image handle of the agent that is allocating the I/O resource.
+ @param DeviceHandle The device handle for which the I/O resource is being allocated.
+
+ @retval EFI_SUCCESS The I/O resource was allocated from the global coherency domain
+ of the processor.
+ @retval EFI_INVALID_PARAMETER GcdAllocateType is invalid.
+ @retval EFI_INVALID_PARAMETER GcdIoType is invalid.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ @retval EFI_INVALID_PARAMETER BaseAddress is NULL.
+ @retval EFI_INVALID_PARAMETER ImageHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to allocate the I/O
+ resource from the global coherency domain of the processor.
+ @retval EFI_NOT_FOUND The I/O resource request could not be satisfied.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ALLOCATE_IO_SPACE)(
+ IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle OPTIONAL
+ );
+
+/**
+ Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
+ domain of the processor.
+
+ @param BaseAddress The physical address that is the start address of the I/O resource being freed.
+ @param Length The size in bytes of the I/O resource range that is being freed.
+
+ @retval EFI_SUCCESS The I/O resource was freed from the global coherency domain of the
+ processor.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the I/O resource
+ range specified by BaseAddress and Length.
+ @retval EFI_NOT_FOUND The I/O resource range specified by BaseAddress and Length
+ was not allocated with previous calls to AllocateIoSpace().
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to free the I/O resource from
+ the global coherency domain of the processor.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FREE_IO_SPACE)(
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ );
+
+/**
+ Removes reserved I/O or I/O resources from the global coherency domain of the
+ processor.
+
+ @param BaseAddress A pointer to a physical address that is the start address of the I/O resource being
+ removed.
+ @param Length The size in bytes of the I/O resource that is being removed.
+
+ @retval EFI_SUCCESS The I/O resource was removed from the global coherency domain
+ of the processor.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the I/O
+ resource range specified by BaseAddress and Length.
+ @retval EFI_NOT_FOUND One or more bytes of the I/O resource range specified by
+ BaseAddress and Length was not added with previous
+ calls to AddIoSpace().
+ @retval EFI_ACCESS_DENIED One or more bytes of the I/O resource range specified by
+ BaseAddress and Length has been allocated with
+ AllocateIoSpace().
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to remove the I/O
+ resource from the global coherency domain of the processor.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REMOVE_IO_SPACE)(
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ );
+
+/**
+ Retrieves the descriptor for an I/O region containing a specified address.
+
+ @param BaseAddress The physical address that is the start address of an I/O region.
+ @param Descriptor A pointer to a caller allocated descriptor.
+
+ @retval EFI_SUCCESS The descriptor for the I/O resource region containing
+ BaseAddress was returned in Descriptor.
+ @retval EFI_INVALID_PARAMETER Descriptor is NULL.
+ @retval EFI_NOT_FOUND An I/O resource range containing BaseAddress was not found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_IO_SPACE_DESCRIPTOR)(
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor
+ );
+
+/**
+ Returns a map of the I/O resources in the global coherency domain of the processor.
+
+ @param NumberOfDescriptors A pointer to number of descriptors returned in the IoSpaceMap buffer.
+ @param MemorySpaceMap A pointer to the array of EFI_GCD_IO_SPACE_DESCRIPTORs.
+
+ @retval EFI_SUCCESS The I/O space map was returned in the IoSpaceMap buffer, and
+ the number of descriptors in IoSpaceMap was returned in
+ NumberOfDescriptors.
+ @retval EFI_INVALID_PARAMETER NumberOfDescriptors is NULL.
+ @retval EFI_INVALID_PARAMETER IoSpaceMap is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate IoSpaceMap.
+
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_IO_SPACE_MAP)(
+ OUT UINTN *NumberOfDescriptors,
+ OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap
+ );
+
+
+
+/**
+ Loads and executed DXE drivers from firmware volumes.
+
+ The Dispatch() function searches for DXE drivers in firmware volumes that have been
+ installed since the last time the Dispatch() service was called. It then evaluates
+ the dependency expressions of all the DXE drivers and loads and executes those DXE
+ drivers whose dependency expression evaluate to TRUE. This service must interact with
+ the Security Architectural Protocol to authenticate DXE drivers before they are executed.
+ This process is continued until no more DXE drivers can be executed.
+
+ @retval EFI_SUCCESS One or more DXE driver were dispatched.
+ @retval EFI_NOT_FOUND No DXE drivers were dispatched.
+ @retval EFI_ALREADY_STARTED An attempt is being made to start the DXE Dispatcher recursively.
+ Thus, no action was taken.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DISPATCH)(
+ VOID
+ );
+
+/**
+ Clears the Schedule on Request (SOR) flag for a component that is stored in a firmware volume.
+
+ @param FirmwareVolumeHandle The handle of the firmware volume that contains the file specified by FileName.
+ @param FileName A pointer to the name of the file in a firmware volume.
+
+ @retval EFI_SUCCESS The DXE driver was found and its SOR bit was cleared.
+ @retval EFI_NOT_FOUND The DXE driver does not exist, or the DXE driver exists and its SOR
+ bit is not set.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SCHEDULE)(
+ IN EFI_HANDLE FirmwareVolumeHandle,
+ IN CONST EFI_GUID *FileName
+ );
+
+/**
+ Promotes a file stored in a firmware volume from the untrusted to the trusted state.
+
+ @param FirmwareVolumeHandle The handle of the firmware volume that contains the file specified by FileName.
+ @param DriverName A pointer to the name of the file in a firmware volume.
+
+ @return Status of promoting FFS from untrusted to trusted
+ state.
+ @retval EFI_NOT_FOUND The file was not found in the untrusted state.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TRUST)(
+ IN EFI_HANDLE FirmwareVolumeHandle,
+ IN CONST EFI_GUID *FileName
+ );
+
+/**
+ Creates a firmware volume handle for a firmware volume that is present in system memory.
+
+ @param FirmwareVolumeHeader A pointer to the header of the firmware volume.
+ @param Size The size, in bytes, of the firmware volume.
+ @param FirmwareVolumeHandle On output, a pointer to the created handle.
+
+ @retval EFI_SUCCESS The EFI_FIRMWARE_VOLUME_PROTOCOL and
+ EFI_DEVICE_PATH_PROTOCOL were installed onto
+ FirmwareVolumeHandle for the firmware volume described
+ by FirmwareVolumeHeader and Size.
+ @retval EFI_VOLUME_CORRUPTED The firmware volume described by FirmwareVolumeHeader
+ and Size is corrupted.
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources available to produce the
+ EFI_FIRMWARE_VOLUME_PROTOCOL and EFI_DEVICE_PATH_PROTOCOL
+ for the firmware volume described by FirmwareVolumeHeader and Size.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PROCESS_FIRMWARE_VOLUME)(
+ IN CONST VOID *FirmwareVolumeHeader,
+ IN UINTN Size,
+ OUT EFI_HANDLE *FirmwareVolumeHandle
+ );
+
+//
+// DXE Services Table
+//
+#define DXE_SERVICES_SIGNATURE 0x565245535f455844ULL
+#define DXE_SERVICES_REVISION ((1<<16) | (00))
+
+typedef struct {
+ ///
+ /// The table header for the DXE Services Table.
+ /// This header contains the DXE_SERVICES_SIGNATURE and DXE_SERVICES_REVISION values.
+ ///
+ EFI_TABLE_HEADER Hdr;
+
+ //
+ // Global Coherency Domain Services
+ //
+ EFI_ADD_MEMORY_SPACE AddMemorySpace;
+ EFI_ALLOCATE_MEMORY_SPACE AllocateMemorySpace;
+ EFI_FREE_MEMORY_SPACE FreeMemorySpace;
+ EFI_REMOVE_MEMORY_SPACE RemoveMemorySpace;
+ EFI_GET_MEMORY_SPACE_DESCRIPTOR GetMemorySpaceDescriptor;
+ EFI_SET_MEMORY_SPACE_ATTRIBUTES SetMemorySpaceAttributes;
+ EFI_GET_MEMORY_SPACE_MAP GetMemorySpaceMap;
+ EFI_ADD_IO_SPACE AddIoSpace;
+ EFI_ALLOCATE_IO_SPACE AllocateIoSpace;
+ EFI_FREE_IO_SPACE FreeIoSpace;
+ EFI_REMOVE_IO_SPACE RemoveIoSpace;
+ EFI_GET_IO_SPACE_DESCRIPTOR GetIoSpaceDescriptor;
+ EFI_GET_IO_SPACE_MAP GetIoSpaceMap;
+
+ //
+ // Dispatcher Services
+ //
+ EFI_DISPATCH Dispatch;
+ EFI_SCHEDULE Schedule;
+ EFI_TRUST Trust;
+ //
+ // Service to process a single firmware volume found in a capsule
+ //
+ EFI_PROCESS_FIRMWARE_VOLUME ProcessFirmwareVolume;
+} DXE_SERVICES;
+
+typedef DXE_SERVICES EFI_DXE_SERVICES;
+
+
+/**
+ The function prototype for invoking a function on an Application Processor.
+
+ This definition is used by the UEFI MP Serices Protocol, and the
+ PI SMM System Table.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+typedef
+VOID
+(EFIAPI *EFI_AP_PROCEDURE)(
+ IN OUT VOID *Buffer
+ );
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiFirmwareFile.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiFirmwareFile.h
new file mode 100644
index 00000000..6909018b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiFirmwareFile.h
@@ -0,0 +1,482 @@
+/** @file
+ The firmware file related definitions in PI.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ PI Version 1.2.
+
+**/
+
+
+#ifndef __PI_FIRMWARE_FILE_H__
+#define __PI_FIRMWARE_FILE_H__
+
+FILE_LICENCE ( BSD3 );
+
+#pragma pack(1)
+///
+/// Used to verify the integrity of the file.
+///
+typedef union {
+ struct {
+ ///
+ /// The IntegrityCheck.Checksum.Header field is an 8-bit checksum of the file
+ /// header. The State and IntegrityCheck.Checksum.File fields are assumed
+ /// to be zero and the checksum is calculated such that the entire header sums to zero.
+ ///
+ UINT8 Header;
+ ///
+ /// If the FFS_ATTRIB_CHECKSUM (see definition below) bit of the Attributes
+ /// field is set to one, the IntegrityCheck.Checksum.File field is an 8-bit
+ /// checksum of the entire file The State field and the file tail are assumed to be zero
+ /// and the checksum is calculated such that the entire file sums to zero.
+ /// If the FFS_ATTRIB_CHECKSUM bit of the Attributes field is cleared to zero,
+ /// the IntegrityCheck.Checksum.File field must be initialized with a value of
+ /// 0xAA. The IntegrityCheck.Checksum.File field is valid any time the
+ /// EFI_FILE_DATA_VALID bit is set in the State field.
+ ///
+ UINT8 File;
+ } Checksum;
+ ///
+ /// This is the full 16 bits of the IntegrityCheck field.
+ ///
+ UINT16 Checksum16;
+} EFI_FFS_INTEGRITY_CHECK;
+
+///
+/// FFS_FIXED_CHECKSUM is the checksum value used when the
+/// FFS_ATTRIB_CHECKSUM attribute bit is clear.
+///
+#define FFS_FIXED_CHECKSUM 0xAA
+
+typedef UINT8 EFI_FV_FILETYPE;
+typedef UINT8 EFI_FFS_FILE_ATTRIBUTES;
+typedef UINT8 EFI_FFS_FILE_STATE;
+
+///
+/// File Types Definitions
+///
+#define EFI_FV_FILETYPE_ALL 0x00
+#define EFI_FV_FILETYPE_RAW 0x01
+#define EFI_FV_FILETYPE_FREEFORM 0x02
+#define EFI_FV_FILETYPE_SECURITY_CORE 0x03
+#define EFI_FV_FILETYPE_PEI_CORE 0x04
+#define EFI_FV_FILETYPE_DXE_CORE 0x05
+#define EFI_FV_FILETYPE_PEIM 0x06
+#define EFI_FV_FILETYPE_DRIVER 0x07
+#define EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER 0x08
+#define EFI_FV_FILETYPE_APPLICATION 0x09
+#define EFI_FV_FILETYPE_SMM 0x0A
+#define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B
+#define EFI_FV_FILETYPE_COMBINED_SMM_DXE 0x0C
+#define EFI_FV_FILETYPE_SMM_CORE 0x0D
+#define EFI_FV_FILETYPE_OEM_MIN 0xc0
+#define EFI_FV_FILETYPE_OEM_MAX 0xdf
+#define EFI_FV_FILETYPE_DEBUG_MIN 0xe0
+#define EFI_FV_FILETYPE_DEBUG_MAX 0xef
+#define EFI_FV_FILETYPE_FFS_MIN 0xf0
+#define EFI_FV_FILETYPE_FFS_MAX 0xff
+#define EFI_FV_FILETYPE_FFS_PAD 0xf0
+///
+/// FFS File Attributes.
+///
+#define FFS_ATTRIB_LARGE_FILE 0x01
+#define FFS_ATTRIB_FIXED 0x04
+#define FFS_ATTRIB_DATA_ALIGNMENT 0x38
+#define FFS_ATTRIB_CHECKSUM 0x40
+
+///
+/// FFS File State Bits.
+///
+#define EFI_FILE_HEADER_CONSTRUCTION 0x01
+#define EFI_FILE_HEADER_VALID 0x02
+#define EFI_FILE_DATA_VALID 0x04
+#define EFI_FILE_MARKED_FOR_UPDATE 0x08
+#define EFI_FILE_DELETED 0x10
+#define EFI_FILE_HEADER_INVALID 0x20
+
+
+///
+/// Each file begins with the header that describe the
+/// contents and state of the files.
+///
+typedef struct {
+ ///
+ /// This GUID is the file name. It is used to uniquely identify the file.
+ ///
+ EFI_GUID Name;
+ ///
+ /// Used to verify the integrity of the file.
+ ///
+ EFI_FFS_INTEGRITY_CHECK IntegrityCheck;
+ ///
+ /// Identifies the type of file.
+ ///
+ EFI_FV_FILETYPE Type;
+ ///
+ /// Declares various file attribute bits.
+ ///
+ EFI_FFS_FILE_ATTRIBUTES Attributes;
+ ///
+ /// The length of the file in bytes, including the FFS header.
+ ///
+ UINT8 Size[3];
+ ///
+ /// Used to track the state of the file throughout the life of the file from creation to deletion.
+ ///
+ EFI_FFS_FILE_STATE State;
+} EFI_FFS_FILE_HEADER;
+
+typedef struct {
+ ///
+ /// This GUID is the file name. It is used to uniquely identify the file. There may be only
+ /// one instance of a file with the file name GUID of Name in any given firmware
+ /// volume, except if the file type is EFI_FV_FILETYPE_FFS_PAD.
+ ///
+ EFI_GUID Name;
+
+ ///
+ /// Used to verify the integrity of the file.
+ ///
+ EFI_FFS_INTEGRITY_CHECK IntegrityCheck;
+
+ ///
+ /// Identifies the type of file.
+ ///
+ EFI_FV_FILETYPE Type;
+
+ ///
+ /// Declares various file attribute bits.
+ ///
+ EFI_FFS_FILE_ATTRIBUTES Attributes;
+
+ ///
+ /// The length of the file in bytes, including the FFS header.
+ /// The length of the file data is either (Size - sizeof(EFI_FFS_FILE_HEADER)). This calculation means a
+ /// zero-length file has a Size of 24 bytes, which is sizeof(EFI_FFS_FILE_HEADER).
+ /// Size is not required to be a multiple of 8 bytes. Given a file F, the next file header is
+ /// located at the next 8-byte aligned firmware volume offset following the last byte of the file F.
+ ///
+ UINT8 Size[3];
+
+ ///
+ /// Used to track the state of the file throughout the life of the file from creation to deletion.
+ ///
+ EFI_FFS_FILE_STATE State;
+
+ ///
+ /// If FFS_ATTRIB_LARGE_FILE is set in Attributes, then ExtendedSize exists and Size must be set to zero.
+ /// If FFS_ATTRIB_LARGE_FILE is not set then EFI_FFS_FILE_HEADER is used.
+ ///
+ EFI_FFS_FILE_STATE ExtendedSize;
+} EFI_FFS_FILE_HEADER2;
+
+typedef UINT8 EFI_SECTION_TYPE;
+
+///
+/// Pseudo type. It is used as a wild card when retrieving sections.
+/// The section type EFI_SECTION_ALL matches all section types.
+///
+#define EFI_SECTION_ALL 0x00
+
+///
+/// Encapsulation section Type values.
+///
+#define EFI_SECTION_COMPRESSION 0x01
+
+#define EFI_SECTION_GUID_DEFINED 0x02
+
+#define EFI_SECTION_DISPOSABLE 0x03
+
+///
+/// Leaf section Type values.
+///
+#define EFI_SECTION_PE32 0x10
+#define EFI_SECTION_PIC 0x11
+#define EFI_SECTION_TE 0x12
+#define EFI_SECTION_DXE_DEPEX 0x13
+#define EFI_SECTION_VERSION 0x14
+#define EFI_SECTION_USER_INTERFACE 0x15
+#define EFI_SECTION_COMPATIBILITY16 0x16
+#define EFI_SECTION_FIRMWARE_VOLUME_IMAGE 0x17
+#define EFI_SECTION_FREEFORM_SUBTYPE_GUID 0x18
+#define EFI_SECTION_RAW 0x19
+#define EFI_SECTION_PEI_DEPEX 0x1B
+#define EFI_SECTION_SMM_DEPEX 0x1C
+
+///
+/// Common section header.
+///
+typedef struct {
+ ///
+ /// A 24-bit unsigned integer that contains the total size of the section in bytes,
+ /// including the EFI_COMMON_SECTION_HEADER.
+ ///
+ UINT8 Size[3];
+ EFI_SECTION_TYPE Type;
+ ///
+ /// Declares the section type.
+ ///
+} EFI_COMMON_SECTION_HEADER;
+
+typedef struct {
+ ///
+ /// A 24-bit unsigned integer that contains the total size of the section in bytes,
+ /// including the EFI_COMMON_SECTION_HEADER.
+ ///
+ UINT8 Size[3];
+
+ EFI_SECTION_TYPE Type;
+
+ ///
+ /// If Size is 0xFFFFFF, then ExtendedSize contains the size of the section. If
+ /// Size is not equal to 0xFFFFFF, then this field does not exist.
+ ///
+ UINT32 ExtendedSize;
+} EFI_COMMON_SECTION_HEADER2;
+
+///
+/// Leaf section type that contains an
+/// IA-32 16-bit executable image.
+///
+typedef EFI_COMMON_SECTION_HEADER EFI_COMPATIBILITY16_SECTION;
+typedef EFI_COMMON_SECTION_HEADER2 EFI_COMPATIBILITY16_SECTION2;
+
+///
+/// CompressionType of EFI_COMPRESSION_SECTION.
+///
+#define EFI_NOT_COMPRESSED 0x00
+#define EFI_STANDARD_COMPRESSION 0x01
+///
+/// An encapsulation section type in which the
+/// section data is compressed.
+///
+typedef struct {
+ ///
+ /// Usual common section header. CommonHeader.Type = EFI_SECTION_COMPRESSION.
+ ///
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+ ///
+ /// The UINT32 that indicates the size of the section data after decompression.
+ ///
+ UINT32 UncompressedLength;
+ ///
+ /// Indicates which compression algorithm is used.
+ ///
+ UINT8 CompressionType;
+} EFI_COMPRESSION_SECTION;
+
+typedef struct {
+ ///
+ /// Usual common section header. CommonHeader.Type = EFI_SECTION_COMPRESSION.
+ ///
+ EFI_COMMON_SECTION_HEADER2 CommonHeader;
+ ///
+ /// UINT32 that indicates the size of the section data after decompression.
+ ///
+ UINT32 UncompressedLength;
+ ///
+ /// Indicates which compression algorithm is used.
+ ///
+ UINT8 CompressionType;
+} EFI_COMPRESSION_SECTION2;
+
+///
+/// An encapsulation section type in which the section data is disposable.
+/// A disposable section is an encapsulation section in which the section data may be disposed of during
+/// the process of creating or updating a firmware image without significant impact on the usefulness of
+/// the file. The Type field in the section header is set to EFI_SECTION_DISPOSABLE. This
+/// allows optional or descriptive data to be included with the firmware file which can be removed in
+/// order to conserve space. The contents of this section are implementation specific, but might contain
+/// debug data or detailed integration instructions.
+///
+typedef EFI_COMMON_SECTION_HEADER EFI_DISPOSABLE_SECTION;
+typedef EFI_COMMON_SECTION_HEADER2 EFI_DISPOSABLE_SECTION2;
+
+///
+/// The leaf section which could be used to determine the dispatch order of DXEs.
+///
+typedef EFI_COMMON_SECTION_HEADER EFI_DXE_DEPEX_SECTION;
+typedef EFI_COMMON_SECTION_HEADER2 EFI_DXE_DEPEX_SECTION2;
+
+///
+/// The leaf section which contains a PI FV.
+///
+typedef EFI_COMMON_SECTION_HEADER EFI_FIRMWARE_VOLUME_IMAGE_SECTION;
+typedef EFI_COMMON_SECTION_HEADER2 EFI_FIRMWARE_VOLUME_IMAGE_SECTION2;
+
+///
+/// The leaf section which contains a single GUID.
+///
+typedef struct {
+ ///
+ /// Common section header. CommonHeader.Type = EFI_SECTION_FREEFORM_SUBTYPE_GUID.
+ ///
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+ ///
+ /// This GUID is defined by the creator of the file. It is a vendor-defined file type.
+ ///
+ EFI_GUID SubTypeGuid;
+} EFI_FREEFORM_SUBTYPE_GUID_SECTION;
+
+typedef struct {
+ ///
+ /// The common section header. CommonHeader.Type = EFI_SECTION_FREEFORM_SUBTYPE_GUID.
+ ///
+ EFI_COMMON_SECTION_HEADER2 CommonHeader;
+ ///
+ /// This GUID is defined by the creator of the file. It is a vendor-defined file type.
+ ///
+ EFI_GUID SubTypeGuid;
+} EFI_FREEFORM_SUBTYPE_GUID_SECTION2;
+
+///
+/// Attributes of EFI_GUID_DEFINED_SECTION.
+///
+#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01
+#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02
+///
+/// The leaf section which is encapsulation defined by specific GUID.
+///
+typedef struct {
+ ///
+ /// The common section header. CommonHeader.Type = EFI_SECTION_GUID_DEFINED.
+ ///
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+ ///
+ /// The GUID that defines the format of the data that follows. It is a vendor-defined section type.
+ ///
+ EFI_GUID SectionDefinitionGuid;
+ ///
+ /// Contains the offset in bytes from the beginning of the common header to the first byte of the data.
+ ///
+ UINT16 DataOffset;
+ ///
+ /// The bit field that declares some specific characteristics of the section contents.
+ ///
+ UINT16 Attributes;
+} EFI_GUID_DEFINED_SECTION;
+
+typedef struct {
+ ///
+ /// The common section header. CommonHeader.Type = EFI_SECTION_GUID_DEFINED.
+ ///
+ EFI_COMMON_SECTION_HEADER2 CommonHeader;
+ ///
+ /// The GUID that defines the format of the data that follows. It is a vendor-defined section type.
+ ///
+ EFI_GUID SectionDefinitionGuid;
+ ///
+ /// Contains the offset in bytes from the beginning of the common header to the first byte of the data.
+ ///
+ UINT16 DataOffset;
+ ///
+ /// The bit field that declares some specific characteristics of the section contents.
+ ///
+ UINT16 Attributes;
+} EFI_GUID_DEFINED_SECTION2;
+
+///
+/// The leaf section which contains PE32+ image.
+///
+typedef EFI_COMMON_SECTION_HEADER EFI_PE32_SECTION;
+typedef EFI_COMMON_SECTION_HEADER2 EFI_PE32_SECTION2;
+
+///
+/// The leaf section used to determine the dispatch order of PEIMs.
+///
+typedef EFI_COMMON_SECTION_HEADER EFI_PEI_DEPEX_SECTION;
+typedef EFI_COMMON_SECTION_HEADER2 EFI_PEI_DEPEX_SECTION2;
+
+///
+/// A leaf section type that contains a position-independent-code (PIC) image.
+/// A PIC image section is a leaf section that contains a position-independent-code (PIC) image.
+/// In addition to normal PE32+ images that contain relocation information, PEIM executables may be
+/// PIC and are referred to as PIC images. A PIC image is the same as a PE32+ image except that all
+/// relocation information has been stripped from the image and the image can be moved and will
+/// execute correctly without performing any relocation or other fix-ups. EFI_PIC_SECTION2 must
+/// be used if the section is 16MB or larger.
+///
+typedef EFI_COMMON_SECTION_HEADER EFI_PIC_SECTION;
+typedef EFI_COMMON_SECTION_HEADER2 EFI_PIC_SECTION2;
+
+///
+/// The leaf section which constains the position-independent-code image.
+///
+typedef EFI_COMMON_SECTION_HEADER EFI_TE_SECTION;
+typedef EFI_COMMON_SECTION_HEADER2 EFI_TE_SECTION2;
+
+///
+/// The leaf section which contains an array of zero or more bytes.
+///
+typedef EFI_COMMON_SECTION_HEADER EFI_RAW_SECTION;
+typedef EFI_COMMON_SECTION_HEADER2 EFI_RAW_SECTION2;
+
+///
+/// The SMM dependency expression section is a leaf section that contains a dependency expression that
+/// is used to determine the dispatch order for SMM drivers. Before the SMRAM invocation of the
+/// SMM driver's entry point, this dependency expression must evaluate to TRUE. See the Platform
+/// Initialization Specification, Volume 2, for details regarding the format of the dependency expression.
+/// The dependency expression may refer to protocols installed in either the UEFI or the SMM protocol
+/// database. EFI_SMM_DEPEX_SECTION2 must be used if the section is 16MB or larger.
+///
+typedef EFI_COMMON_SECTION_HEADER EFI_SMM_DEPEX_SECTION;
+typedef EFI_COMMON_SECTION_HEADER2 EFI_SMM_DEPEX_SECTION2;
+
+///
+/// The leaf section which contains a unicode string that
+/// is human readable file name.
+///
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+
+ ///
+ /// Array of unicode string.
+ ///
+ CHAR16 FileNameString[1];
+} EFI_USER_INTERFACE_SECTION;
+
+typedef struct {
+ EFI_COMMON_SECTION_HEADER2 CommonHeader;
+ CHAR16 FileNameString[1];
+} EFI_USER_INTERFACE_SECTION2;
+
+///
+/// The leaf section which contains a numeric build number and
+/// an optional unicode string that represents the file revision.
+///
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+ UINT16 BuildNumber;
+
+ ///
+ /// Array of unicode string.
+ ///
+ CHAR16 VersionString[1];
+} EFI_VERSION_SECTION;
+
+typedef struct {
+ EFI_COMMON_SECTION_HEADER2 CommonHeader;
+ ///
+ /// A UINT16 that represents a particular build. Subsequent builds have monotonically
+ /// increasing build numbers relative to earlier builds.
+ ///
+ UINT16 BuildNumber;
+ CHAR16 VersionString[1];
+} EFI_VERSION_SECTION2;
+
+#define SECTION_SIZE(SectionHeaderPtr) \
+ ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) SectionHeaderPtr)->Size) & 0x00ffffff))
+
+#pragma pack()
+
+#endif
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiFirmwareVolume.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiFirmwareVolume.h
new file mode 100644
index 00000000..813fab22
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiFirmwareVolume.h
@@ -0,0 +1,233 @@
+/** @file
+ The firmware volume related definitions in PI.
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ PI Version 1.2B
+
+**/
+
+#ifndef __PI_FIRMWAREVOLUME_H__
+#define __PI_FIRMWAREVOLUME_H__
+
+FILE_LICENCE ( BSD3 );
+
+///
+/// EFI_FV_FILE_ATTRIBUTES
+///
+typedef UINT32 EFI_FV_FILE_ATTRIBUTES;
+
+//
+// Value of EFI_FV_FILE_ATTRIBUTES.
+//
+#define EFI_FV_FILE_ATTRIB_ALIGNMENT 0x0000001F
+#define EFI_FV_FILE_ATTRIB_FIXED 0x00000100
+#define EFI_FV_FILE_ATTRIB_MEMORY_MAPPED 0x00000200
+
+///
+/// type of EFI FVB attribute
+///
+typedef UINT32 EFI_FVB_ATTRIBUTES_2;
+
+//
+// Attributes bit definitions
+//
+#define EFI_FVB2_READ_DISABLED_CAP 0x00000001
+#define EFI_FVB2_READ_ENABLED_CAP 0x00000002
+#define EFI_FVB2_READ_STATUS 0x00000004
+#define EFI_FVB2_WRITE_DISABLED_CAP 0x00000008
+#define EFI_FVB2_WRITE_ENABLED_CAP 0x00000010
+#define EFI_FVB2_WRITE_STATUS 0x00000020
+#define EFI_FVB2_LOCK_CAP 0x00000040
+#define EFI_FVB2_LOCK_STATUS 0x00000080
+#define EFI_FVB2_STICKY_WRITE 0x00000200
+#define EFI_FVB2_MEMORY_MAPPED 0x00000400
+#define EFI_FVB2_ERASE_POLARITY 0x00000800
+#define EFI_FVB2_READ_LOCK_CAP 0x00001000
+#define EFI_FVB2_READ_LOCK_STATUS 0x00002000
+#define EFI_FVB2_WRITE_LOCK_CAP 0x00004000
+#define EFI_FVB2_WRITE_LOCK_STATUS 0x00008000
+#define EFI_FVB2_ALIGNMENT 0x001F0000
+#define EFI_FVB2_ALIGNMENT_1 0x00000000
+#define EFI_FVB2_ALIGNMENT_2 0x00010000
+#define EFI_FVB2_ALIGNMENT_4 0x00020000
+#define EFI_FVB2_ALIGNMENT_8 0x00030000
+#define EFI_FVB2_ALIGNMENT_16 0x00040000
+#define EFI_FVB2_ALIGNMENT_32 0x00050000
+#define EFI_FVB2_ALIGNMENT_64 0x00060000
+#define EFI_FVB2_ALIGNMENT_128 0x00070000
+#define EFI_FVB2_ALIGNMENT_256 0x00080000
+#define EFI_FVB2_ALIGNMENT_512 0x00090000
+#define EFI_FVB2_ALIGNMENT_1K 0x000A0000
+#define EFI_FVB2_ALIGNMENT_2K 0x000B0000
+#define EFI_FVB2_ALIGNMENT_4K 0x000C0000
+#define EFI_FVB2_ALIGNMENT_8K 0x000D0000
+#define EFI_FVB2_ALIGNMENT_16K 0x000E0000
+#define EFI_FVB2_ALIGNMENT_32K 0x000F0000
+#define EFI_FVB2_ALIGNMENT_64K 0x00100000
+#define EFI_FVB2_ALIGNMENT_128K 0x00110000
+#define EFI_FVB2_ALIGNMENT_256K 0x00120000
+#define EFI_FVB2_ALIGNMNET_512K 0x00130000
+#define EFI_FVB2_ALIGNMENT_1M 0x00140000
+#define EFI_FVB2_ALIGNMENT_2M 0x00150000
+#define EFI_FVB2_ALIGNMENT_4M 0x00160000
+#define EFI_FVB2_ALIGNMENT_8M 0x00170000
+#define EFI_FVB2_ALIGNMENT_16M 0x00180000
+#define EFI_FVB2_ALIGNMENT_32M 0x00190000
+#define EFI_FVB2_ALIGNMENT_64M 0x001A0000
+#define EFI_FVB2_ALIGNMENT_128M 0x001B0000
+#define EFI_FVB2_ALIGNMENT_256M 0x001C0000
+#define EFI_FVB2_ALIGNMENT_512M 0x001D0000
+#define EFI_FVB2_ALIGNMENT_1G 0x001E0000
+#define EFI_FVB2_ALIGNMENT_2G 0x001F0000
+
+
+typedef struct {
+ ///
+ /// The number of sequential blocks which are of the same size.
+ ///
+ UINT32 NumBlocks;
+ ///
+ /// The size of the blocks.
+ ///
+ UINT32 Length;
+} EFI_FV_BLOCK_MAP_ENTRY;
+
+///
+/// Describes the features and layout of the firmware volume.
+///
+typedef struct {
+ ///
+ /// The first 16 bytes are reserved to allow for the reset vector of
+ /// processors whose reset vector is at address 0.
+ ///
+ UINT8 ZeroVector[16];
+ ///
+ /// Declares the file system with which the firmware volume is formatted.
+ ///
+ EFI_GUID FileSystemGuid;
+ ///
+ /// Length in bytes of the complete firmware volume, including the header.
+ ///
+ UINT64 FvLength;
+ ///
+ /// Set to EFI_FVH_SIGNATURE
+ ///
+ UINT32 Signature;
+ ///
+ /// Declares capabilities and power-on defaults for the firmware volume.
+ ///
+ EFI_FVB_ATTRIBUTES_2 Attributes;
+ ///
+ /// Length in bytes of the complete firmware volume header.
+ ///
+ UINT16 HeaderLength;
+ ///
+ /// A 16-bit checksum of the firmware volume header. A valid header sums to zero.
+ ///
+ UINT16 Checksum;
+ ///
+ /// Offset, relative to the start of the header, of the extended header
+ /// (EFI_FIRMWARE_VOLUME_EXT_HEADER) or zero if there is no extended header.
+ ///
+ UINT16 ExtHeaderOffset;
+ ///
+ /// This field must always be set to zero.
+ ///
+ UINT8 Reserved[1];
+ ///
+ /// Set to 2. Future versions of this specification may define new header fields and will
+ /// increment the Revision field accordingly.
+ ///
+ UINT8 Revision;
+ ///
+ /// An array of run-length encoded FvBlockMapEntry structures. The array is
+ /// terminated with an entry of {0,0}.
+ ///
+ EFI_FV_BLOCK_MAP_ENTRY BlockMap[1];
+} EFI_FIRMWARE_VOLUME_HEADER;
+
+#define EFI_FVH_SIGNATURE SIGNATURE_32 ('_', 'F', 'V', 'H')
+
+///
+/// Firmware Volume Header Revision definition
+///
+#define EFI_FVH_REVISION 0x02
+
+///
+/// Extension header pointed by ExtHeaderOffset of volume header.
+///
+typedef struct {
+ ///
+ /// Firmware volume name.
+ ///
+ EFI_GUID FvName;
+ ///
+ /// Size of the rest of the extension header, including this structure.
+ ///
+ UINT32 ExtHeaderSize;
+} EFI_FIRMWARE_VOLUME_EXT_HEADER;
+
+///
+/// Entry struture for describing FV extension header
+///
+typedef struct {
+ ///
+ /// Size of this header extension.
+ ///
+ UINT16 ExtEntrySize;
+ ///
+ /// Type of the header.
+ ///
+ UINT16 ExtEntryType;
+} EFI_FIRMWARE_VOLUME_EXT_ENTRY;
+
+#define EFI_FV_EXT_TYPE_OEM_TYPE 0x01
+///
+/// This extension header provides a mapping between a GUID and an OEM file type.
+///
+typedef struct {
+ ///
+ /// Standard extension entry, with the type EFI_FV_EXT_TYPE_OEM_TYPE.
+ ///
+ EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr;
+ ///
+ /// A bit mask, one bit for each file type between 0xC0 (bit 0) and 0xDF (bit 31). If a bit
+ /// is '1', then the GUID entry exists in Types. If a bit is '0' then no GUID entry exists in Types.
+ ///
+ UINT32 TypeMask;
+ ///
+ /// An array of GUIDs, each GUID representing an OEM file type.
+ ///
+ EFI_GUID Types[1];
+} EFI_FIRMWARE_VOLUME_EXT_ENTRY_OEM_TYPE;
+
+#define EFI_FV_EXT_TYPE_GUID_TYPE 0x0002
+
+///
+/// This extension header provides a mapping between a GUID and an OEM file type.
+///
+typedef struct {
+ ///
+ /// Standard extension entry, with the type EFI_FV_EXT_TYPE_OEM_TYPE.
+ ///
+ EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr;
+ ///
+ /// Vendor-specific GUID.
+ ///
+ EFI_GUID FormatType;
+ ///
+ /// An arry of bytes of length Length.
+ ///
+ UINT8 Data[1];
+} EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiHob.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiHob.h
new file mode 100644
index 00000000..cd196cb3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiHob.h
@@ -0,0 +1,451 @@
+/** @file
+ HOB related definitions in PI.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ PI Version 1.0
+
+**/
+
+#ifndef __PI_HOB_H__
+#define __PI_HOB_H__
+
+FILE_LICENCE ( BSD3 );
+
+//
+// HobType of EFI_HOB_GENERIC_HEADER.
+//
+#define EFI_HOB_TYPE_HANDOFF 0x0001
+#define EFI_HOB_TYPE_MEMORY_ALLOCATION 0x0002
+#define EFI_HOB_TYPE_RESOURCE_DESCRIPTOR 0x0003
+#define EFI_HOB_TYPE_GUID_EXTENSION 0x0004
+#define EFI_HOB_TYPE_FV 0x0005
+#define EFI_HOB_TYPE_CPU 0x0006
+#define EFI_HOB_TYPE_MEMORY_POOL 0x0007
+#define EFI_HOB_TYPE_FV2 0x0009
+#define EFI_HOB_TYPE_LOAD_PEIM_UNUSED 0x000A
+#define EFI_HOB_TYPE_UEFI_CAPSULE 0x000B
+#define EFI_HOB_TYPE_UNUSED 0xFFFE
+#define EFI_HOB_TYPE_END_OF_HOB_LIST 0xFFFF
+
+///
+/// Describes the format and size of the data inside the HOB.
+/// All HOBs must contain this generic HOB header.
+///
+typedef struct {
+ ///
+ /// Identifies the HOB data structure type.
+ ///
+ UINT16 HobType;
+ ///
+ /// The length in bytes of the HOB.
+ ///
+ UINT16 HobLength;
+ ///
+ /// This field must always be set to zero.
+ ///
+ UINT32 Reserved;
+} EFI_HOB_GENERIC_HEADER;
+
+
+///
+/// Value of version in EFI_HOB_HANDOFF_INFO_TABLE.
+///
+#define EFI_HOB_HANDOFF_TABLE_VERSION 0x0009
+
+///
+/// Contains general state information used by the HOB producer phase.
+/// This HOB must be the first one in the HOB list.
+///
+typedef struct {
+ ///
+ /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_HANDOFF.
+ ///
+ EFI_HOB_GENERIC_HEADER Header;
+ ///
+ /// The version number pertaining to the PHIT HOB definition.
+ /// This value is four bytes in length to provide an 8-byte aligned entry
+ /// when it is combined with the 4-byte BootMode.
+ ///
+ UINT32 Version;
+ ///
+ /// The system boot mode as determined during the HOB producer phase.
+ ///
+ EFI_BOOT_MODE BootMode;
+ ///
+ /// The highest address location of memory that is allocated for use by the HOB producer
+ /// phase. This address must be 4-KB aligned to meet page restrictions of UEFI.
+ ///
+ EFI_PHYSICAL_ADDRESS EfiMemoryTop;
+ ///
+ /// The lowest address location of memory that is allocated for use by the HOB producer phase.
+ ///
+ EFI_PHYSICAL_ADDRESS EfiMemoryBottom;
+ ///
+ /// The highest address location of free memory that is currently available
+ /// for use by the HOB producer phase.
+ ///
+ EFI_PHYSICAL_ADDRESS EfiFreeMemoryTop;
+ ///
+ /// The lowest address location of free memory that is available for use by the HOB producer phase.
+ ///
+ EFI_PHYSICAL_ADDRESS EfiFreeMemoryBottom;
+ ///
+ /// The end of the HOB list.
+ ///
+ EFI_PHYSICAL_ADDRESS EfiEndOfHobList;
+} EFI_HOB_HANDOFF_INFO_TABLE;
+
+///
+/// EFI_HOB_MEMORY_ALLOCATION_HEADER describes the
+/// various attributes of the logical memory allocation. The type field will be used for
+/// subsequent inclusion in the UEFI memory map.
+///
+typedef struct {
+ ///
+ /// A GUID that defines the memory allocation region's type and purpose, as well as
+ /// other fields within the memory allocation HOB. This GUID is used to define the
+ /// additional data within the HOB that may be present for the memory allocation HOB.
+ /// Type EFI_GUID is defined in InstallProtocolInterface() in the UEFI 2.0
+ /// specification.
+ ///
+ EFI_GUID Name;
+
+ ///
+ /// The base address of memory allocated by this HOB. Type
+ /// EFI_PHYSICAL_ADDRESS is defined in AllocatePages() in the UEFI 2.0
+ /// specification.
+ ///
+ EFI_PHYSICAL_ADDRESS MemoryBaseAddress;
+
+ ///
+ /// The length in bytes of memory allocated by this HOB.
+ ///
+ UINT64 MemoryLength;
+
+ ///
+ /// Defines the type of memory allocated by this HOB. The memory type definition
+ /// follows the EFI_MEMORY_TYPE definition. Type EFI_MEMORY_TYPE is defined
+ /// in AllocatePages() in the UEFI 2.0 specification.
+ ///
+ EFI_MEMORY_TYPE MemoryType;
+
+ ///
+ /// Padding for Itanium processor family
+ ///
+ UINT8 Reserved[4];
+} EFI_HOB_MEMORY_ALLOCATION_HEADER;
+
+///
+/// Describes all memory ranges used during the HOB producer
+/// phase that exist outside the HOB list. This HOB type
+/// describes how memory is used, not the physical attributes of memory.
+///
+typedef struct {
+ ///
+ /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION.
+ ///
+ EFI_HOB_GENERIC_HEADER Header;
+ ///
+ /// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the
+ /// various attributes of the logical memory allocation.
+ ///
+ EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor;
+ //
+ // Additional data pertaining to the "Name" Guid memory
+ // may go here.
+ //
+} EFI_HOB_MEMORY_ALLOCATION;
+
+
+///
+/// Describes the memory stack that is produced by the HOB producer
+/// phase and upon which all post-memory-installed executable
+/// content in the HOB producer phase is executing.
+///
+typedef struct {
+ ///
+ /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION.
+ ///
+ EFI_HOB_GENERIC_HEADER Header;
+ ///
+ /// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the
+ /// various attributes of the logical memory allocation.
+ ///
+ EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor;
+} EFI_HOB_MEMORY_ALLOCATION_STACK;
+
+///
+/// Defines the location of the boot-strap
+/// processor (BSP) BSPStore ("Backing Store Pointer Store").
+/// This HOB is valid for the Itanium processor family only
+/// register overflow store.
+///
+typedef struct {
+ ///
+ /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION.
+ ///
+ EFI_HOB_GENERIC_HEADER Header;
+ ///
+ /// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the
+ /// various attributes of the logical memory allocation.
+ ///
+ EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor;
+} EFI_HOB_MEMORY_ALLOCATION_BSP_STORE;
+
+///
+/// Defines the location and entry point of the HOB consumer phase.
+///
+typedef struct {
+ ///
+ /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION.
+ ///
+ EFI_HOB_GENERIC_HEADER Header;
+ ///
+ /// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the
+ /// various attributes of the logical memory allocation.
+ ///
+ EFI_HOB_MEMORY_ALLOCATION_HEADER MemoryAllocationHeader;
+ ///
+ /// The GUID specifying the values of the firmware file system name
+ /// that contains the HOB consumer phase component.
+ ///
+ EFI_GUID ModuleName;
+ ///
+ /// The address of the memory-mapped firmware volume
+ /// that contains the HOB consumer phase firmware file.
+ ///
+ EFI_PHYSICAL_ADDRESS EntryPoint;
+} EFI_HOB_MEMORY_ALLOCATION_MODULE;
+
+///
+/// The resource type.
+///
+typedef UINT32 EFI_RESOURCE_TYPE;
+
+//
+// Value of ResourceType in EFI_HOB_RESOURCE_DESCRIPTOR.
+//
+#define EFI_RESOURCE_SYSTEM_MEMORY 0x00000000
+#define EFI_RESOURCE_MEMORY_MAPPED_IO 0x00000001
+#define EFI_RESOURCE_IO 0x00000002
+#define EFI_RESOURCE_FIRMWARE_DEVICE 0x00000003
+#define EFI_RESOURCE_MEMORY_MAPPED_IO_PORT 0x00000004
+#define EFI_RESOURCE_MEMORY_RESERVED 0x00000005
+#define EFI_RESOURCE_IO_RESERVED 0x00000006
+#define EFI_RESOURCE_MAX_MEMORY_TYPE 0x00000007
+
+///
+/// A type of recount attribute type.
+///
+typedef UINT32 EFI_RESOURCE_ATTRIBUTE_TYPE;
+
+//
+// These types can be ORed together as needed.
+//
+// The first three enumerations describe settings
+//
+#define EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001
+#define EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002
+#define EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004
+//
+// The rest of the settings describe capabilities
+//
+#define EFI_RESOURCE_ATTRIBUTE_SINGLE_BIT_ECC 0x00000008
+#define EFI_RESOURCE_ATTRIBUTE_MULTIPLE_BIT_ECC 0x00000010
+#define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_1 0x00000020
+#define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_2 0x00000040
+#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080
+#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED 0x00000100
+#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED 0x00000200
+#define EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE 0x00000400
+#define EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE 0x00000800
+#define EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE 0x00001000
+#define EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 0x00002000
+#define EFI_RESOURCE_ATTRIBUTE_16_BIT_IO 0x00004000
+#define EFI_RESOURCE_ATTRIBUTE_32_BIT_IO 0x00008000
+#define EFI_RESOURCE_ATTRIBUTE_64_BIT_IO 0x00010000
+#define EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED 0x00020000
+
+///
+/// Describes the resource properties of all fixed,
+/// nonrelocatable resource ranges found on the processor
+/// host bus during the HOB producer phase.
+///
+typedef struct {
+ ///
+ /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_RESOURCE_DESCRIPTOR.
+ ///
+ EFI_HOB_GENERIC_HEADER Header;
+ ///
+ /// A GUID representing the owner of the resource. This GUID is used by HOB
+ /// consumer phase components to correlate device ownership of a resource.
+ ///
+ EFI_GUID Owner;
+ ///
+ /// The resource type enumeration as defined by EFI_RESOURCE_TYPE.
+ ///
+ EFI_RESOURCE_TYPE ResourceType;
+ ///
+ /// Resource attributes as defined by EFI_RESOURCE_ATTRIBUTE_TYPE.
+ ///
+ EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute;
+ ///
+ /// The physical start address of the resource region.
+ ///
+ EFI_PHYSICAL_ADDRESS PhysicalStart;
+ ///
+ /// The number of bytes of the resource region.
+ ///
+ UINT64 ResourceLength;
+} EFI_HOB_RESOURCE_DESCRIPTOR;
+
+///
+/// Allows writers of executable content in the HOB producer phase to
+/// maintain and manage HOBs with specific GUID.
+///
+typedef struct {
+ ///
+ /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_GUID_EXTENSION.
+ ///
+ EFI_HOB_GENERIC_HEADER Header;
+ ///
+ /// A GUID that defines the contents of this HOB.
+ ///
+ EFI_GUID Name;
+ //
+ // Guid specific data goes here
+ //
+} EFI_HOB_GUID_TYPE;
+
+///
+/// Details the location of firmware volumes that contain firmware files.
+///
+typedef struct {
+ ///
+ /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_FV.
+ ///
+ EFI_HOB_GENERIC_HEADER Header;
+ ///
+ /// The physical memory-mapped base address of the firmware volume.
+ ///
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ ///
+ /// The length in bytes of the firmware volume.
+ ///
+ UINT64 Length;
+} EFI_HOB_FIRMWARE_VOLUME;
+
+///
+/// Details the location of a firmware volume that was extracted
+/// from a file within another firmware volume.
+///
+typedef struct {
+ ///
+ /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_FV2.
+ ///
+ EFI_HOB_GENERIC_HEADER Header;
+ ///
+ /// The physical memory-mapped base address of the firmware volume.
+ ///
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ ///
+ /// The length in bytes of the firmware volume.
+ ///
+ UINT64 Length;
+ ///
+ /// The name of the firmware volume.
+ ///
+ EFI_GUID FvName;
+ ///
+ /// The name of the firmware file that contained this firmware volume.
+ ///
+ EFI_GUID FileName;
+} EFI_HOB_FIRMWARE_VOLUME2;
+
+
+///
+/// Describes processor information, such as address space and I/O space capabilities.
+///
+typedef struct {
+ ///
+ /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_CPU.
+ ///
+ EFI_HOB_GENERIC_HEADER Header;
+ ///
+ /// Identifies the maximum physical memory addressability of the processor.
+ ///
+ UINT8 SizeOfMemorySpace;
+ ///
+ /// Identifies the maximum physical I/O addressability of the processor.
+ ///
+ UINT8 SizeOfIoSpace;
+ ///
+ /// This field will always be set to zero.
+ ///
+ UINT8 Reserved[6];
+} EFI_HOB_CPU;
+
+
+///
+/// Describes pool memory allocations.
+///
+typedef struct {
+ ///
+ /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_POOL.
+ ///
+ EFI_HOB_GENERIC_HEADER Header;
+} EFI_HOB_MEMORY_POOL;
+
+///
+/// Each UEFI capsule HOB details the location of a UEFI capsule. It includes a base address and length
+/// which is based upon memory blocks with a EFI_CAPSULE_HEADER and the associated
+/// CapsuleImageSize-based payloads. These HOB's shall be created by the PEI PI firmware
+/// sometime after the UEFI UpdateCapsule service invocation with the
+/// CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag set in the EFI_CAPSULE_HEADER.
+///
+typedef struct {
+ ///
+ /// The HOB generic header where Header.HobType = EFI_HOB_TYPE_UEFI_CAPSULE.
+ ///
+ EFI_HOB_GENERIC_HEADER Header;
+
+ ///
+ /// The physical memory-mapped base address of an UEFI capsule. This value is set to
+ /// point to the base of the contiguous memory of the UEFI capsule.
+ /// The length of the contiguous memory in bytes.
+ ///
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+} EFI_HOB_UEFI_CAPSULE;
+
+///
+/// Union of all the possible HOB Types.
+///
+typedef union {
+ EFI_HOB_GENERIC_HEADER *Header;
+ EFI_HOB_HANDOFF_INFO_TABLE *HandoffInformationTable;
+ EFI_HOB_MEMORY_ALLOCATION *MemoryAllocation;
+ EFI_HOB_MEMORY_ALLOCATION_BSP_STORE *MemoryAllocationBspStore;
+ EFI_HOB_MEMORY_ALLOCATION_STACK *MemoryAllocationStack;
+ EFI_HOB_MEMORY_ALLOCATION_MODULE *MemoryAllocationModule;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor;
+ EFI_HOB_GUID_TYPE *Guid;
+ EFI_HOB_FIRMWARE_VOLUME *FirmwareVolume;
+ EFI_HOB_FIRMWARE_VOLUME2 *FirmwareVolume2;
+ EFI_HOB_CPU *Cpu;
+ EFI_HOB_MEMORY_POOL *Pool;
+ EFI_HOB_UEFI_CAPSULE *Capsule;
+ UINT8 *Raw;
+} EFI_PEI_HOB_POINTERS;
+
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiMultiPhase.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiMultiPhase.h
new file mode 100644
index 00000000..d5d7aaa4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiMultiPhase.h
@@ -0,0 +1,138 @@
+/** @file
+ Include file matches things in PI for multiple module types.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ These elements are defined in UEFI Platform Initialization Specification 1.2.
+
+**/
+
+#ifndef __PI_MULTIPHASE_H__
+#define __PI_MULTIPHASE_H__
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/Pi/PiFirmwareVolume.h>
+#include <ipxe/efi/Pi/PiFirmwareFile.h>
+#include <ipxe/efi/Pi/PiBootMode.h>
+#include <ipxe/efi/Pi/PiHob.h>
+#include <ipxe/efi/Pi/PiDependency.h>
+#include <ipxe/efi/Pi/PiStatusCode.h>
+#include <ipxe/efi/Pi/PiS3BootScript.h>
+
+/**
+ Produces an error code in the range reserved for use by the Platform Initialization
+ Architecture Specification.
+
+ The supported 32-bit range is 0xA0000000-0xBFFFFFFF
+ The supported 64-bit range is 0xA000000000000000-0xBFFFFFFFFFFFFFFF
+
+ @param StatusCode The status code value to convert into a warning code.
+ StatusCode must be in the range 0x00000000..0x1FFFFFFF.
+
+ @return The value specified by StatusCode in the PI reserved range.
+
+**/
+#define DXE_ERROR(StatusCode) (MAX_BIT | (MAX_BIT >> 2) | StatusCode)
+
+///
+/// If this value is returned by an EFI image, then the image should be unloaded.
+///
+#define EFI_REQUEST_UNLOAD_IMAGE DXE_ERROR (1)
+
+///
+/// If this value is returned by an API, it means the capability is not yet
+/// installed/available/ready to use.
+///
+#define EFI_NOT_AVAILABLE_YET DXE_ERROR (2)
+
+///
+/// Success and warning codes reserved for use by PI.
+/// Supported 32-bit range is 0x20000000-0x3fffffff.
+/// Supported 64-bit range is 0x2000000000000000-0x3fffffffffffffff.
+///
+#define PI_ENCODE_WARNING(a) ((MAX_BIT >> 2) | (a))
+
+///
+/// Error codes reserved for use by PI.
+/// Supported 32-bit range is 0xa0000000-0xbfffffff.
+/// Supported 64-bit range is 0xa000000000000000-0xbfffffffffffffff.
+///
+#define PI_ENCODE_ERROR(a) (MAX_BIT | (MAX_BIT >> 2) | (a))
+
+///
+/// Return status codes defined in SMM CIS.
+///
+#define EFI_INTERRUPT_PENDING PI_ENCODE_ERROR (0)
+
+#define EFI_WARN_INTERRUPT_SOURCE_PENDING PI_ENCODE_WARNING (0)
+#define EFI_WARN_INTERRUPT_SOURCE_QUIESCED PI_ENCODE_WARNING (1)
+
+///
+/// Bitmask of values for Authentication Status.
+/// Authentication Status is returned from EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL
+/// and the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
+///
+/// xx00 Image was not signed.
+/// xxx1 Platform security policy override. Assumes the same meaning as 0010 (the image was signed, the
+/// signature was tested, and the signature passed authentication test).
+/// 0010 Image was signed, the signature was tested, and the signature passed authentication test.
+/// 0110 Image was signed and the signature was not tested.
+/// 1010 Image was signed, the signature was tested, and the signature failed the authentication test.
+///
+///@{
+#define EFI_AUTH_STATUS_PLATFORM_OVERRIDE 0x01
+#define EFI_AUTH_STATUS_IMAGE_SIGNED 0x02
+#define EFI_AUTH_STATUS_NOT_TESTED 0x04
+#define EFI_AUTH_STATUS_TEST_FAILED 0x08
+#define EFI_AUTH_STATUS_ALL 0x0f
+///@}
+
+///
+/// SMRAM states and capabilities
+///
+#define EFI_SMRAM_OPEN 0x00000001
+#define EFI_SMRAM_CLOSED 0x00000002
+#define EFI_SMRAM_LOCKED 0x00000004
+#define EFI_CACHEABLE 0x00000008
+#define EFI_ALLOCATED 0x00000010
+#define EFI_NEEDS_TESTING 0x00000020
+#define EFI_NEEDS_ECC_INITIALIZATION 0x00000040
+
+///
+/// Structure describing a SMRAM region and its accessibility attributes.
+///
+typedef struct {
+ ///
+ /// Designates the physical address of the SMRAM in memory. This view of memory is
+ /// the same as seen by I/O-based agents, for example, but it may not be the address seen
+ /// by the processors.
+ ///
+ EFI_PHYSICAL_ADDRESS PhysicalStart;
+ ///
+ /// Designates the address of the SMRAM, as seen by software executing on the
+ /// processors. This address may or may not match PhysicalStart.
+ ///
+ EFI_PHYSICAL_ADDRESS CpuStart;
+ ///
+ /// Describes the number of bytes in the SMRAM region.
+ ///
+ UINT64 PhysicalSize;
+ ///
+ /// Describes the accessibility attributes of the SMRAM. These attributes include the
+ /// hardware state (e.g., Open/Closed/Locked), capability (e.g., cacheable), logical
+ /// allocation (e.g., allocated), and pre-use initialization (e.g., needs testing/ECC
+ /// initialization).
+ ///
+ UINT64 RegionState;
+} EFI_SMRAM_DESCRIPTOR;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiS3BootScript.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiS3BootScript.h
new file mode 100644
index 00000000..01cae154
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiS3BootScript.h
@@ -0,0 +1,61 @@
+/** @file
+ This file contains the boot script defintions that are shared between the
+ Boot Script Executor PPI and the Boot Script Save Protocol.
+
+ Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PI_S3_BOOT_SCRIPT_H_
+#define _PI_S3_BOOT_SCRIPT_H_
+
+FILE_LICENCE ( BSD3 );
+
+//*******************************************
+// EFI Boot Script Opcode definitions
+//*******************************************
+#define EFI_BOOT_SCRIPT_IO_WRITE_OPCODE 0x00
+#define EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE 0x01
+#define EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE 0x02
+#define EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE 0x03
+#define EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE 0x04
+#define EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE 0x05
+#define EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE 0x06
+#define EFI_BOOT_SCRIPT_STALL_OPCODE 0x07
+#define EFI_BOOT_SCRIPT_DISPATCH_OPCODE 0x08
+#define EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE 0x09
+#define EFI_BOOT_SCRIPT_INFORMATION_OPCODE 0x0A
+#define EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE 0x0B
+#define EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE 0x0C
+#define EFI_BOOT_SCRIPT_IO_POLL_OPCODE 0x0D
+#define EFI_BOOT_SCRIPT_MEM_POLL_OPCODE 0x0E
+#define EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE 0x0F
+#define EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE 0x10
+
+//*******************************************
+// EFI_BOOT_SCRIPT_WIDTH
+//*******************************************
+typedef enum {
+ EfiBootScriptWidthUint8,
+ EfiBootScriptWidthUint16,
+ EfiBootScriptWidthUint32,
+ EfiBootScriptWidthUint64,
+ EfiBootScriptWidthFifoUint8,
+ EfiBootScriptWidthFifoUint16,
+ EfiBootScriptWidthFifoUint32,
+ EfiBootScriptWidthFifoUint64,
+ EfiBootScriptWidthFillUint8,
+ EfiBootScriptWidthFillUint16,
+ EfiBootScriptWidthFillUint32,
+ EfiBootScriptWidthFillUint64,
+ EfiBootScriptWidthMaximum
+} EFI_BOOT_SCRIPT_WIDTH;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiStatusCode.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiStatusCode.h
new file mode 100644
index 00000000..6133f00c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Pi/PiStatusCode.h
@@ -0,0 +1,1130 @@
+/** @file
+ StatusCode related definitions in PI.
+
+Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ These status codes are defined in UEFI Platform Initialization Specification 1.2,
+ Volume 3: Shared Architectural Elements.
+
+**/
+
+#ifndef __PI_STATUS_CODE_H__
+#define __PI_STATUS_CODE_H__
+
+FILE_LICENCE ( BSD3 );
+
+//
+// Required for IA32 and IPF defines for CPU exception types
+//
+#include <ipxe/efi/Protocol/DebugSupport.h>
+
+///
+/// Status Code Type Definition.
+///
+typedef UINT32 EFI_STATUS_CODE_TYPE;
+
+///
+/// A Status Code Type is made up of the code type and severity.
+/// All values masked by EFI_STATUS_CODE_RESERVED_MASK are
+/// reserved for use by this specification.
+///
+///@{
+#define EFI_STATUS_CODE_TYPE_MASK 0x000000FF
+#define EFI_STATUS_CODE_SEVERITY_MASK 0xFF000000
+#define EFI_STATUS_CODE_RESERVED_MASK 0x00FFFF00
+///@}
+
+///
+/// Definition of code types. All other values masked by
+/// EFI_STATUS_CODE_TYPE_MASK are reserved for use by
+/// this specification.
+///
+///@{
+#define EFI_PROGRESS_CODE 0x00000001
+#define EFI_ERROR_CODE 0x00000002
+#define EFI_DEBUG_CODE 0x00000003
+///@}
+
+///
+/// Definitions of severities, all other values masked by
+/// EFI_STATUS_CODE_SEVERITY_MASK are reserved for use by
+/// this specification.
+/// Uncontained errors are major errors that could not contained
+/// to the specific component that is reporting the error.
+/// For example, if a memory error was not detected early enough,
+/// the bad data could be consumed by other drivers.
+///
+///@{
+#define EFI_ERROR_MINOR 0x40000000
+#define EFI_ERROR_MAJOR 0x80000000
+#define EFI_ERROR_UNRECOVERED 0x90000000
+#define EFI_ERROR_UNCONTAINED 0xa0000000
+///@}
+
+///
+/// Status Code Value Definition.
+///
+typedef UINT32 EFI_STATUS_CODE_VALUE;
+
+///
+/// A Status Code Value is made up of the class, subclass, and
+/// an operation.
+///
+///@{
+#define EFI_STATUS_CODE_CLASS_MASK 0xFF000000
+#define EFI_STATUS_CODE_SUBCLASS_MASK 0x00FF0000
+#define EFI_STATUS_CODE_OPERATION_MASK 0x0000FFFF
+///@}
+
+///
+/// Definition of Status Code extended data header.
+/// The data will follow HeaderSize bytes from the beginning of
+/// the structure and is Size bytes long.
+///
+typedef struct {
+ ///
+ /// The size of the structure. This is specified to enable future expansion.
+ ///
+ UINT16 HeaderSize;
+ ///
+ /// The size of the data in bytes. This does not include the size of the header structure.
+ ///
+ UINT16 Size;
+ ///
+ /// The GUID defining the type of the data.
+ ///
+ EFI_GUID Type;
+} EFI_STATUS_CODE_DATA;
+
+///
+/// General partitioning scheme for Progress and Error Codes are:
+/// - 0x0000-0x0FFF Shared by all sub-classes in a given class.
+/// - 0x1000-0x7FFF Subclass Specific.
+/// - 0x8000-0xFFFF OEM specific.
+///@{
+#define EFI_SUBCLASS_SPECIFIC 0x1000
+#define EFI_OEM_SPECIFIC 0x8000
+///@}
+
+///
+/// Debug Code definitions for all classes and subclass.
+/// Only one debug code is defined at this point and should
+/// be used for anything that is sent to the debug stream.
+///
+///@{
+#define EFI_DC_UNSPECIFIED 0x0
+///@}
+
+///
+/// Class definitions.
+/// Values of 4-127 are reserved for future use by this specification.
+/// Values in the range 127-255 are reserved for OEM use.
+///
+///@{
+#define EFI_COMPUTING_UNIT 0x00000000
+#define EFI_PERIPHERAL 0x01000000
+#define EFI_IO_BUS 0x02000000
+#define EFI_SOFTWARE 0x03000000
+///@}
+
+///
+/// Computing Unit Subclass definitions.
+/// Values of 8-127 are reserved for future use by this specification.
+/// Values of 128-255 are reserved for OEM use.
+///
+///@{
+#define EFI_COMPUTING_UNIT_UNSPECIFIED (EFI_COMPUTING_UNIT | 0x00000000)
+#define EFI_COMPUTING_UNIT_HOST_PROCESSOR (EFI_COMPUTING_UNIT | 0x00010000)
+#define EFI_COMPUTING_UNIT_FIRMWARE_PROCESSOR (EFI_COMPUTING_UNIT | 0x00020000)
+#define EFI_COMPUTING_UNIT_IO_PROCESSOR (EFI_COMPUTING_UNIT | 0x00030000)
+#define EFI_COMPUTING_UNIT_CACHE (EFI_COMPUTING_UNIT | 0x00040000)
+#define EFI_COMPUTING_UNIT_MEMORY (EFI_COMPUTING_UNIT | 0x00050000)
+#define EFI_COMPUTING_UNIT_CHIPSET (EFI_COMPUTING_UNIT | 0x00060000)
+///@}
+
+///
+/// Computing Unit Class Progress Code definitions.
+/// These are shared by all subclasses.
+///
+///@{
+#define EFI_CU_PC_INIT_BEGIN 0x00000000
+#define EFI_CU_PC_INIT_END 0x00000001
+///@}
+
+//
+// Computing Unit Unspecified Subclass Progress Code definitions.
+//
+
+///
+/// Computing Unit Host Processor Subclass Progress Code definitions.
+///@{
+#define EFI_CU_HP_PC_POWER_ON_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_CU_HP_PC_CACHE_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_CU_HP_PC_RAM_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_CU_HP_PC_MEMORY_CONTROLLER_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+#define EFI_CU_HP_PC_IO_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000004)
+#define EFI_CU_HP_PC_BSP_SELECT (EFI_SUBCLASS_SPECIFIC | 0x00000005)
+#define EFI_CU_HP_PC_BSP_RESELECT (EFI_SUBCLASS_SPECIFIC | 0x00000006)
+#define EFI_CU_HP_PC_AP_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000007)
+#define EFI_CU_HP_PC_SMM_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000008)
+///@}
+
+//
+// Computing Unit Firmware Processor Subclass Progress Code definitions.
+//
+
+//
+// Computing Unit IO Processor Subclass Progress Code definitions.
+//
+
+///
+/// Computing Unit Cache Subclass Progress Code definitions.
+///
+///@{
+#define EFI_CU_CACHE_PC_PRESENCE_DETECT (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_CU_CACHE_PC_CONFIGURATION (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+///@}
+
+///
+/// Computing Unit Memory Subclass Progress Code definitions.
+///
+///@{
+#define EFI_CU_MEMORY_PC_SPD_READ (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_CU_MEMORY_PC_PRESENCE_DETECT (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_CU_MEMORY_PC_TIMING (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_CU_MEMORY_PC_CONFIGURING (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+#define EFI_CU_MEMORY_PC_OPTIMIZING (EFI_SUBCLASS_SPECIFIC | 0x00000004)
+#define EFI_CU_MEMORY_PC_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000005)
+#define EFI_CU_MEMORY_PC_TEST (EFI_SUBCLASS_SPECIFIC | 0x00000006)
+///@}
+
+//
+// Computing Unit Chipset Subclass Progress Code definitions.
+//
+
+///
+/// South Bridge initialization prior to memory detection.
+///
+#define EFI_CHIPSET_PC_PEI_CAR_SB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000000)
+
+///
+/// North Bridge initialization prior to memory detection.
+///
+#define EFI_CHIPSET_PC_PEI_CAR_NB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000001)
+
+///
+/// South Bridge initialization after memory detection.
+///
+#define EFI_CHIPSET_PC_PEI_MEM_SB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000002)
+
+///
+/// North Bridge initialization after memory detection.
+///
+#define EFI_CHIPSET_PC_PEI_MEM_NB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000003)
+
+///
+/// PCI Host Bridge DXE initialization.
+///
+#define EFI_CHIPSET_PC_DXE_HB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000004)
+
+///
+/// North Bridge DXE initialization.
+///
+#define EFI_CHIPSET_PC_DXE_NB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000005)
+
+///
+/// North Bridge specific SMM initialization in DXE.
+///
+#define EFI_CHIPSET_PC_DXE_NB_SMM_INIT (EFI_SUBCLASS_SPECIFIC|0x00000006)
+
+///
+/// Initialization of the South Bridge specific UEFI Runtime Services.
+///
+#define EFI_CHIPSET_PC_DXE_SB_RT_INIT (EFI_SUBCLASS_SPECIFIC|0x00000007)
+
+///
+/// South Bridge DXE initialization
+///
+#define EFI_CHIPSET_PC_DXE_SB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000008)
+
+///
+/// South Bridge specific SMM initialization in DXE.
+///
+#define EFI_CHIPSET_PC_DXE_SB_SMM_INIT (EFI_SUBCLASS_SPECIFIC|0x00000009)
+
+///
+/// Initialization of the South Bridge devices.
+///
+#define EFI_CHIPSET_PC_DXE_SB_DEVICES_INIT (EFI_SUBCLASS_SPECIFIC|0x0000000a)
+
+///
+/// Computing Unit Class Error Code definitions.
+/// These are shared by all subclasses.
+///
+///@{
+#define EFI_CU_EC_NON_SPECIFIC 0x00000000
+#define EFI_CU_EC_DISABLED 0x00000001
+#define EFI_CU_EC_NOT_SUPPORTED 0x00000002
+#define EFI_CU_EC_NOT_DETECTED 0x00000003
+#define EFI_CU_EC_NOT_CONFIGURED 0x00000004
+///@}
+
+//
+// Computing Unit Unspecified Subclass Error Code definitions.
+//
+
+///
+/// Computing Unit Host Processor Subclass Error Code definitions.
+///
+///@{
+#define EFI_CU_HP_EC_INVALID_TYPE (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_CU_HP_EC_INVALID_SPEED (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_CU_HP_EC_MISMATCH (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_CU_HP_EC_TIMER_EXPIRED (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+#define EFI_CU_HP_EC_SELF_TEST (EFI_SUBCLASS_SPECIFIC | 0x00000004)
+#define EFI_CU_HP_EC_INTERNAL (EFI_SUBCLASS_SPECIFIC | 0x00000005)
+#define EFI_CU_HP_EC_THERMAL (EFI_SUBCLASS_SPECIFIC | 0x00000006)
+#define EFI_CU_HP_EC_LOW_VOLTAGE (EFI_SUBCLASS_SPECIFIC | 0x00000007)
+#define EFI_CU_HP_EC_HIGH_VOLTAGE (EFI_SUBCLASS_SPECIFIC | 0x00000008)
+#define EFI_CU_HP_EC_CACHE (EFI_SUBCLASS_SPECIFIC | 0x00000009)
+#define EFI_CU_HP_EC_MICROCODE_UPDATE (EFI_SUBCLASS_SPECIFIC | 0x0000000A)
+#define EFI_CU_HP_EC_CORRECTABLE (EFI_SUBCLASS_SPECIFIC | 0x0000000B)
+#define EFI_CU_HP_EC_UNCORRECTABLE (EFI_SUBCLASS_SPECIFIC | 0x0000000C)
+#define EFI_CU_HP_EC_NO_MICROCODE_UPDATE (EFI_SUBCLASS_SPECIFIC | 0x0000000D)
+///@}
+
+///
+/// Computing Unit Firmware Processor Subclass Error Code definitions.
+///
+///@{
+#define EFI_CU_FP_EC_HARD_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_CU_FP_EC_SOFT_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_CU_FP_EC_COMM_ERROR (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+///@}
+
+//
+// Computing Unit IO Processor Subclass Error Code definitions.
+//
+
+///
+/// Computing Unit Cache Subclass Error Code definitions.
+///
+///@{
+#define EFI_CU_CACHE_EC_INVALID_TYPE (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_CU_CACHE_EC_INVALID_SPEED (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_CU_CACHE_EC_INVALID_SIZE (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_CU_CACHE_EC_MISMATCH (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+///@}
+
+///
+/// Computing Unit Memory Subclass Error Code definitions.
+///
+///@{
+#define EFI_CU_MEMORY_EC_INVALID_TYPE (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_CU_MEMORY_EC_INVALID_SPEED (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_CU_MEMORY_EC_CORRECTABLE (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_CU_MEMORY_EC_UNCORRECTABLE (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+#define EFI_CU_MEMORY_EC_SPD_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000004)
+#define EFI_CU_MEMORY_EC_INVALID_SIZE (EFI_SUBCLASS_SPECIFIC | 0x00000005)
+#define EFI_CU_MEMORY_EC_MISMATCH (EFI_SUBCLASS_SPECIFIC | 0x00000006)
+#define EFI_CU_MEMORY_EC_S3_RESUME_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000007)
+#define EFI_CU_MEMORY_EC_UPDATE_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000008)
+#define EFI_CU_MEMORY_EC_NONE_DETECTED (EFI_SUBCLASS_SPECIFIC | 0x00000009)
+#define EFI_CU_MEMORY_EC_NONE_USEFUL (EFI_SUBCLASS_SPECIFIC | 0x0000000A)
+///@}
+
+///
+/// Computing Unit Chipset Subclass Error Code definitions.
+///
+///@{
+#define EFI_CHIPSET_EC_BAD_BATTERY (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_CHIPSET_EC_DXE_NB_ERROR (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_CHIPSET_EC_DXE_SB_ERROR (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+///@}
+
+///
+/// Peripheral Subclass definitions.
+/// Values of 12-127 are reserved for future use by this specification.
+/// Values of 128-255 are reserved for OEM use.
+///
+///@{
+#define EFI_PERIPHERAL_UNSPECIFIED (EFI_PERIPHERAL | 0x00000000)
+#define EFI_PERIPHERAL_KEYBOARD (EFI_PERIPHERAL | 0x00010000)
+#define EFI_PERIPHERAL_MOUSE (EFI_PERIPHERAL | 0x00020000)
+#define EFI_PERIPHERAL_LOCAL_CONSOLE (EFI_PERIPHERAL | 0x00030000)
+#define EFI_PERIPHERAL_REMOTE_CONSOLE (EFI_PERIPHERAL | 0x00040000)
+#define EFI_PERIPHERAL_SERIAL_PORT (EFI_PERIPHERAL | 0x00050000)
+#define EFI_PERIPHERAL_PARALLEL_PORT (EFI_PERIPHERAL | 0x00060000)
+#define EFI_PERIPHERAL_FIXED_MEDIA (EFI_PERIPHERAL | 0x00070000)
+#define EFI_PERIPHERAL_REMOVABLE_MEDIA (EFI_PERIPHERAL | 0x00080000)
+#define EFI_PERIPHERAL_AUDIO_INPUT (EFI_PERIPHERAL | 0x00090000)
+#define EFI_PERIPHERAL_AUDIO_OUTPUT (EFI_PERIPHERAL | 0x000A0000)
+#define EFI_PERIPHERAL_LCD_DEVICE (EFI_PERIPHERAL | 0x000B0000)
+#define EFI_PERIPHERAL_NETWORK (EFI_PERIPHERAL | 0x000C0000)
+///@}
+
+///
+/// Peripheral Class Progress Code definitions.
+/// These are shared by all subclasses.
+///
+///@{
+#define EFI_P_PC_INIT 0x00000000
+#define EFI_P_PC_RESET 0x00000001
+#define EFI_P_PC_DISABLE 0x00000002
+#define EFI_P_PC_PRESENCE_DETECT 0x00000003
+#define EFI_P_PC_ENABLE 0x00000004
+#define EFI_P_PC_RECONFIG 0x00000005
+#define EFI_P_PC_DETECTED 0x00000006
+///@}
+
+//
+// Peripheral Class Unspecified Subclass Progress Code definitions.
+//
+
+///
+/// Peripheral Class Keyboard Subclass Progress Code definitions.
+///
+///@{
+#define EFI_P_KEYBOARD_PC_CLEAR_BUFFER (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_P_KEYBOARD_PC_SELF_TEST (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+///@}
+
+///
+/// Peripheral Class Mouse Subclass Progress Code definitions.
+///
+///@{
+#define EFI_P_MOUSE_PC_SELF_TEST (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+///@}
+
+//
+// Peripheral Class Local Console Subclass Progress Code definitions.
+//
+
+//
+// Peripheral Class Remote Console Subclass Progress Code definitions.
+//
+
+///
+/// Peripheral Class Serial Port Subclass Progress Code definitions.
+///
+///@{
+#define EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+///@}
+
+//
+// Peripheral Class Parallel Port Subclass Progress Code definitions.
+//
+
+//
+// Peripheral Class Fixed Media Subclass Progress Code definitions.
+//
+
+//
+// Peripheral Class Removable Media Subclass Progress Code definitions.
+//
+
+//
+// Peripheral Class Audio Input Subclass Progress Code definitions.
+//
+
+//
+// Peripheral Class Audio Output Subclass Progress Code definitions.
+//
+
+//
+// Peripheral Class LCD Device Subclass Progress Code definitions.
+//
+
+//
+// Peripheral Class Network Subclass Progress Code definitions.
+//
+
+///
+/// Peripheral Class Error Code definitions.
+/// These are shared by all subclasses.
+///
+///@{
+#define EFI_P_EC_NON_SPECIFIC 0x00000000
+#define EFI_P_EC_DISABLED 0x00000001
+#define EFI_P_EC_NOT_SUPPORTED 0x00000002
+#define EFI_P_EC_NOT_DETECTED 0x00000003
+#define EFI_P_EC_NOT_CONFIGURED 0x00000004
+#define EFI_P_EC_INTERFACE_ERROR 0x00000005
+#define EFI_P_EC_CONTROLLER_ERROR 0x00000006
+#define EFI_P_EC_INPUT_ERROR 0x00000007
+#define EFI_P_EC_OUTPUT_ERROR 0x00000008
+#define EFI_P_EC_RESOURCE_CONFLICT 0x00000009
+///@}
+
+//
+// Peripheral Class Unspecified Subclass Error Code definitions.
+//
+
+///
+/// Peripheral Class Keyboard Subclass Error Code definitions.
+///
+///@{
+#define EFI_P_KEYBOARD_EC_LOCKED (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_P_KEYBOARD_EC_STUCK_KEY (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+///@}
+
+///
+/// Peripheral Class Mouse Subclass Error Code definitions.
+///
+///@{
+#define EFI_P_MOUSE_EC_LOCKED (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+///@}
+
+//
+// Peripheral Class Local Console Subclass Error Code definitions.
+//
+
+//
+// Peripheral Class Remote Console Subclass Error Code definitions.
+//
+
+//
+// Peripheral Class Serial Port Subclass Error Code definitions.
+//
+
+//
+// Peripheral Class Parallel Port Subclass Error Code definitions.
+//
+
+//
+// Peripheral Class Fixed Media Subclass Error Code definitions.
+//
+
+//
+// Peripheral Class Removable Media Subclass Error Code definitions.
+//
+
+//
+// Peripheral Class Audio Input Subclass Error Code definitions.
+//
+
+//
+// Peripheral Class Audio Output Subclass Error Code definitions.
+//
+
+//
+// Peripheral Class LCD Device Subclass Error Code definitions.
+//
+
+//
+// Peripheral Class Network Subclass Error Code definitions.
+//
+
+///
+/// IO Bus Subclass definitions.
+/// Values of 14-127 are reserved for future use by this specification.
+/// Values of 128-255 are reserved for OEM use.
+///
+///@{
+#define EFI_IO_BUS_UNSPECIFIED (EFI_IO_BUS | 0x00000000)
+#define EFI_IO_BUS_PCI (EFI_IO_BUS | 0x00010000)
+#define EFI_IO_BUS_USB (EFI_IO_BUS | 0x00020000)
+#define EFI_IO_BUS_IBA (EFI_IO_BUS | 0x00030000)
+#define EFI_IO_BUS_AGP (EFI_IO_BUS | 0x00040000)
+#define EFI_IO_BUS_PC_CARD (EFI_IO_BUS | 0x00050000)
+#define EFI_IO_BUS_LPC (EFI_IO_BUS | 0x00060000)
+#define EFI_IO_BUS_SCSI (EFI_IO_BUS | 0x00070000)
+#define EFI_IO_BUS_ATA_ATAPI (EFI_IO_BUS | 0x00080000)
+#define EFI_IO_BUS_FC (EFI_IO_BUS | 0x00090000)
+#define EFI_IO_BUS_IP_NETWORK (EFI_IO_BUS | 0x000A0000)
+#define EFI_IO_BUS_SMBUS (EFI_IO_BUS | 0x000B0000)
+#define EFI_IO_BUS_I2C (EFI_IO_BUS | 0x000C0000)
+///@}
+
+///
+/// IO Bus Class Progress Code definitions.
+/// These are shared by all subclasses.
+///
+///@{
+#define EFI_IOB_PC_INIT 0x00000000
+#define EFI_IOB_PC_RESET 0x00000001
+#define EFI_IOB_PC_DISABLE 0x00000002
+#define EFI_IOB_PC_DETECT 0x00000003
+#define EFI_IOB_PC_ENABLE 0x00000004
+#define EFI_IOB_PC_RECONFIG 0x00000005
+#define EFI_IOB_PC_HOTPLUG 0x00000006
+///@}
+
+//
+// IO Bus Class Unspecified Subclass Progress Code definitions.
+//
+
+///
+/// IO Bus Class PCI Subclass Progress Code definitions.
+///
+///@{
+#define EFI_IOB_PCI_BUS_ENUM (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_IOB_PCI_RES_ALLOC (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_IOB_PCI_HPC_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+///@}
+
+//
+// IO Bus Class USB Subclass Progress Code definitions.
+//
+
+//
+// IO Bus Class IBA Subclass Progress Code definitions.
+//
+
+//
+// IO Bus Class AGP Subclass Progress Code definitions.
+//
+
+//
+// IO Bus Class PC Card Subclass Progress Code definitions.
+//
+
+//
+// IO Bus Class LPC Subclass Progress Code definitions.
+//
+
+//
+// IO Bus Class SCSI Subclass Progress Code definitions.
+//
+
+//
+// IO Bus Class ATA/ATAPI Subclass Progress Code definitions.
+//
+
+//
+// IO Bus Class FC Subclass Progress Code definitions.
+//
+
+//
+// IO Bus Class IP Network Subclass Progress Code definitions.
+//
+
+//
+// IO Bus Class SMBUS Subclass Progress Code definitions.
+//
+
+//
+// IO Bus Class I2C Subclass Progress Code definitions.
+//
+
+///
+/// IO Bus Class Error Code definitions.
+/// These are shared by all subclasses.
+///
+///@{
+#define EFI_IOB_EC_NON_SPECIFIC 0x00000000
+#define EFI_IOB_EC_DISABLED 0x00000001
+#define EFI_IOB_EC_NOT_SUPPORTED 0x00000002
+#define EFI_IOB_EC_NOT_DETECTED 0x00000003
+#define EFI_IOB_EC_NOT_CONFIGURED 0x00000004
+#define EFI_IOB_EC_INTERFACE_ERROR 0x00000005
+#define EFI_IOB_EC_CONTROLLER_ERROR 0x00000006
+#define EFI_IOB_EC_READ_ERROR 0x00000007
+#define EFI_IOB_EC_WRITE_ERROR 0x00000008
+#define EFI_IOB_EC_RESOURCE_CONFLICT 0x00000009
+///@}
+
+//
+// IO Bus Class Unspecified Subclass Error Code definitions.
+//
+
+///
+/// IO Bus Class PCI Subclass Error Code definitions.
+///
+///@{
+#define EFI_IOB_PCI_EC_PERR (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_IOB_PCI_EC_SERR (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+///@}
+
+//
+// IO Bus Class USB Subclass Error Code definitions.
+//
+
+//
+// IO Bus Class IBA Subclass Error Code definitions.
+//
+
+//
+// IO Bus Class AGP Subclass Error Code definitions.
+//
+
+//
+// IO Bus Class PC Card Subclass Error Code definitions.
+//
+
+//
+// IO Bus Class LPC Subclass Error Code definitions.
+//
+
+//
+// IO Bus Class SCSI Subclass Error Code definitions.
+//
+
+//
+// IO Bus Class ATA/ATAPI Subclass Error Code definitions.
+//
+
+//
+// IO Bus Class FC Subclass Error Code definitions.
+//
+
+//
+// IO Bus Class IP Network Subclass Error Code definitions.
+//
+
+//
+// IO Bus Class SMBUS Subclass Error Code definitions.
+//
+
+//
+// IO Bus Class I2C Subclass Error Code definitions.
+//
+
+///
+/// Software Subclass definitions.
+/// Values of 14-127 are reserved for future use by this specification.
+/// Values of 128-255 are reserved for OEM use.
+///
+///@{
+#define EFI_SOFTWARE_UNSPECIFIED (EFI_SOFTWARE | 0x00000000)
+#define EFI_SOFTWARE_SEC (EFI_SOFTWARE | 0x00010000)
+#define EFI_SOFTWARE_PEI_CORE (EFI_SOFTWARE | 0x00020000)
+#define EFI_SOFTWARE_PEI_MODULE (EFI_SOFTWARE | 0x00030000)
+#define EFI_SOFTWARE_DXE_CORE (EFI_SOFTWARE | 0x00040000)
+#define EFI_SOFTWARE_DXE_BS_DRIVER (EFI_SOFTWARE | 0x00050000)
+#define EFI_SOFTWARE_DXE_RT_DRIVER (EFI_SOFTWARE | 0x00060000)
+#define EFI_SOFTWARE_SMM_DRIVER (EFI_SOFTWARE | 0x00070000)
+#define EFI_SOFTWARE_EFI_APPLICATION (EFI_SOFTWARE | 0x00080000)
+#define EFI_SOFTWARE_EFI_OS_LOADER (EFI_SOFTWARE | 0x00090000)
+#define EFI_SOFTWARE_RT (EFI_SOFTWARE | 0x000A0000)
+#define EFI_SOFTWARE_AL (EFI_SOFTWARE | 0x000B0000)
+#define EFI_SOFTWARE_EBC_EXCEPTION (EFI_SOFTWARE | 0x000C0000)
+#define EFI_SOFTWARE_IA32_EXCEPTION (EFI_SOFTWARE | 0x000D0000)
+#define EFI_SOFTWARE_IPF_EXCEPTION (EFI_SOFTWARE | 0x000E0000)
+#define EFI_SOFTWARE_PEI_SERVICE (EFI_SOFTWARE | 0x000F0000)
+#define EFI_SOFTWARE_EFI_BOOT_SERVICE (EFI_SOFTWARE | 0x00100000)
+#define EFI_SOFTWARE_EFI_RUNTIME_SERVICE (EFI_SOFTWARE | 0x00110000)
+#define EFI_SOFTWARE_EFI_DXE_SERVICE (EFI_SOFTWARE | 0x00120000)
+///@}
+
+///
+/// Software Class Progress Code definitions.
+/// These are shared by all subclasses.
+///
+///@{
+#define EFI_SW_PC_INIT 0x00000000
+#define EFI_SW_PC_LOAD 0x00000001
+#define EFI_SW_PC_INIT_BEGIN 0x00000002
+#define EFI_SW_PC_INIT_END 0x00000003
+#define EFI_SW_PC_AUTHENTICATE_BEGIN 0x00000004
+#define EFI_SW_PC_AUTHENTICATE_END 0x00000005
+#define EFI_SW_PC_INPUT_WAIT 0x00000006
+#define EFI_SW_PC_USER_SETUP 0x00000007
+///@}
+
+//
+// Software Class Unspecified Subclass Progress Code definitions.
+//
+
+///
+/// Software Class SEC Subclass Progress Code definitions.
+///
+///@{
+#define EFI_SW_SEC_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_SEC_PC_HANDOFF_TO_NEXT (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+///@}
+
+///
+/// Software Class PEI Core Subclass Progress Code definitions.
+///
+///@{
+#define EFI_SW_PEI_CORE_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_SW_PEI_CORE_PC_RETURN_TO_LAST (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+///@}
+
+///
+/// Software Class PEI Module Subclass Progress Code definitions.
+/// Note: EFI_SW_PEI_PC_RECOVERY_BEGIN is different from PI 1.2 Specification.
+///
+///@{
+#define EFI_SW_PEI_PC_RECOVERY_BEGIN (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_PEI_PC_CAPSULE_LOAD (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_SW_PEI_PC_CAPSULE_START (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_SW_PEI_PC_RECOVERY_USER (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+#define EFI_SW_PEI_PC_RECOVERY_AUTO (EFI_SUBCLASS_SPECIFIC | 0x00000004)
+#define EFI_SW_PEI_PC_S3_BOOT_SCRIPT (EFI_SUBCLASS_SPECIFIC | 0x00000005)
+#define EFI_SW_PEI_PC_OS_WAKE (EFI_SUBCLASS_SPECIFIC | 0x00000006)
+///@}
+
+///
+/// Software Class DXE Core Subclass Progress Code definitions.
+///
+///@{
+#define EFI_SW_DXE_CORE_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_SW_DXE_CORE_PC_RETURN_TO_LAST (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_SW_DXE_CORE_PC_START_DRIVER (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+#define EFI_SW_DXE_CORE_PC_ARCH_READY (EFI_SUBCLASS_SPECIFIC | 0x00000004)
+///@}
+
+///
+/// Software Class DXE BS Driver Subclass Progress Code definitions.
+///
+///@{
+#define EFI_SW_DXE_BS_PC_LEGACY_OPROM_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_SW_DXE_BS_PC_LEGACY_BOOT_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_SW_DXE_BS_PC_EXIT_BOOT_SERVICES_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+#define EFI_SW_DXE_BS_PC_VIRTUAL_ADDRESS_CHANGE_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000004)
+///@}
+
+//
+// Software Class SMM Driver Subclass Progress Code definitions.
+//
+
+//
+// Software Class EFI Application Subclass Progress Code definitions.
+//
+
+//
+// Software Class EFI OS Loader Subclass Progress Code definitions.
+//
+
+///
+/// Software Class EFI RT Subclass Progress Code definitions.
+///
+///@{
+#define EFI_SW_RT_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_RT_PC_HANDOFF_TO_NEXT (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_SW_RT_PC_RETURN_TO_LAST (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+///@}
+
+//
+// Software Class EBC Exception Subclass Progress Code definitions.
+//
+
+//
+// Software Class IA32 Exception Subclass Progress Code definitions.
+//
+
+//
+// Software Class X64 Exception Subclass Progress Code definitions.
+//
+
+//
+// Software Class IPF Exception Subclass Progress Code definitions.
+//
+
+///
+/// Software Class PEI Services Subclass Progress Code definitions.
+///
+///@{
+#define EFI_SW_PS_PC_INSTALL_PPI (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_PS_PC_REINSTALL_PPI (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_SW_PS_PC_LOCATE_PPI (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_SW_PS_PC_NOTIFY_PPI (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+#define EFI_SW_PS_PC_GET_BOOT_MODE (EFI_SUBCLASS_SPECIFIC | 0x00000004)
+#define EFI_SW_PS_PC_SET_BOOT_MODE (EFI_SUBCLASS_SPECIFIC | 0x00000005)
+#define EFI_SW_PS_PC_GET_HOB_LIST (EFI_SUBCLASS_SPECIFIC | 0x00000006)
+#define EFI_SW_PS_PC_CREATE_HOB (EFI_SUBCLASS_SPECIFIC | 0x00000007)
+#define EFI_SW_PS_PC_FFS_FIND_NEXT_VOLUME (EFI_SUBCLASS_SPECIFIC | 0x00000008)
+#define EFI_SW_PS_PC_FFS_FIND_NEXT_FILE (EFI_SUBCLASS_SPECIFIC | 0x00000009)
+#define EFI_SW_PS_PC_FFS_FIND_SECTION_DATA (EFI_SUBCLASS_SPECIFIC | 0x0000000A)
+#define EFI_SW_PS_PC_INSTALL_PEI_MEMORY (EFI_SUBCLASS_SPECIFIC | 0x0000000B)
+#define EFI_SW_PS_PC_ALLOCATE_PAGES (EFI_SUBCLASS_SPECIFIC | 0x0000000C)
+#define EFI_SW_PS_PC_ALLOCATE_POOL (EFI_SUBCLASS_SPECIFIC | 0x0000000D)
+#define EFI_SW_PS_PC_COPY_MEM (EFI_SUBCLASS_SPECIFIC | 0x0000000E)
+#define EFI_SW_PS_PC_SET_MEM (EFI_SUBCLASS_SPECIFIC | 0x0000000F)
+#define EFI_SW_PS_PC_RESET_SYSTEM (EFI_SUBCLASS_SPECIFIC | 0x00000010)
+#define EFI_SW_PS_PC_FFS_FIND_FILE_BY_NAME (EFI_SUBCLASS_SPECIFIC | 0x00000013)
+#define EFI_SW_PS_PC_FFS_GET_FILE_INFO (EFI_SUBCLASS_SPECIFIC | 0x00000014)
+#define EFI_SW_PS_PC_FFS_GET_VOLUME_INFO (EFI_SUBCLASS_SPECIFIC | 0x00000015)
+#define EFI_SW_PS_PC_FFS_REGISTER_FOR_SHADOW (EFI_SUBCLASS_SPECIFIC | 0x00000016)
+///@}
+
+///
+/// Software Class EFI Boot Services Subclass Progress Code definitions.
+///
+///@{
+#define EFI_SW_BS_PC_RAISE_TPL (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_BS_PC_RESTORE_TPL (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_SW_BS_PC_ALLOCATE_PAGES (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_SW_BS_PC_FREE_PAGES (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+#define EFI_SW_BS_PC_GET_MEMORY_MAP (EFI_SUBCLASS_SPECIFIC | 0x00000004)
+#define EFI_SW_BS_PC_ALLOCATE_POOL (EFI_SUBCLASS_SPECIFIC | 0x00000005)
+#define EFI_SW_BS_PC_FREE_POOL (EFI_SUBCLASS_SPECIFIC | 0x00000006)
+#define EFI_SW_BS_PC_CREATE_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000007)
+#define EFI_SW_BS_PC_SET_TIMER (EFI_SUBCLASS_SPECIFIC | 0x00000008)
+#define EFI_SW_BS_PC_WAIT_FOR_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000009)
+#define EFI_SW_BS_PC_SIGNAL_EVENT (EFI_SUBCLASS_SPECIFIC | 0x0000000A)
+#define EFI_SW_BS_PC_CLOSE_EVENT (EFI_SUBCLASS_SPECIFIC | 0x0000000B)
+#define EFI_SW_BS_PC_CHECK_EVENT (EFI_SUBCLASS_SPECIFIC | 0x0000000C)
+#define EFI_SW_BS_PC_INSTALL_PROTOCOL_INTERFACE (EFI_SUBCLASS_SPECIFIC | 0x0000000D)
+#define EFI_SW_BS_PC_REINSTALL_PROTOCOL_INTERFACE (EFI_SUBCLASS_SPECIFIC | 0x0000000E)
+#define EFI_SW_BS_PC_UNINSTALL_PROTOCOL_INTERFACE (EFI_SUBCLASS_SPECIFIC | 0x0000000F)
+#define EFI_SW_BS_PC_HANDLE_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x00000010)
+#define EFI_SW_BS_PC_PC_HANDLE_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x00000011)
+#define EFI_SW_BS_PC_REGISTER_PROTOCOL_NOTIFY (EFI_SUBCLASS_SPECIFIC | 0x00000012)
+#define EFI_SW_BS_PC_LOCATE_HANDLE (EFI_SUBCLASS_SPECIFIC | 0x00000013)
+#define EFI_SW_BS_PC_INSTALL_CONFIGURATION_TABLE (EFI_SUBCLASS_SPECIFIC | 0x00000014)
+#define EFI_SW_BS_PC_LOAD_IMAGE (EFI_SUBCLASS_SPECIFIC | 0x00000015)
+#define EFI_SW_BS_PC_START_IMAGE (EFI_SUBCLASS_SPECIFIC | 0x00000016)
+#define EFI_SW_BS_PC_EXIT (EFI_SUBCLASS_SPECIFIC | 0x00000017)
+#define EFI_SW_BS_PC_UNLOAD_IMAGE (EFI_SUBCLASS_SPECIFIC | 0x00000018)
+#define EFI_SW_BS_PC_EXIT_BOOT_SERVICES (EFI_SUBCLASS_SPECIFIC | 0x00000019)
+#define EFI_SW_BS_PC_GET_NEXT_MONOTONIC_COUNT (EFI_SUBCLASS_SPECIFIC | 0x0000001A)
+#define EFI_SW_BS_PC_STALL (EFI_SUBCLASS_SPECIFIC | 0x0000001B)
+#define EFI_SW_BS_PC_SET_WATCHDOG_TIMER (EFI_SUBCLASS_SPECIFIC | 0x0000001C)
+#define EFI_SW_BS_PC_CONNECT_CONTROLLER (EFI_SUBCLASS_SPECIFIC | 0x0000001D)
+#define EFI_SW_BS_PC_DISCONNECT_CONTROLLER (EFI_SUBCLASS_SPECIFIC | 0x0000001E)
+#define EFI_SW_BS_PC_OPEN_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x0000001F)
+#define EFI_SW_BS_PC_CLOSE_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x00000020)
+#define EFI_SW_BS_PC_OPEN_PROTOCOL_INFORMATION (EFI_SUBCLASS_SPECIFIC | 0x00000021)
+#define EFI_SW_BS_PC_PROTOCOLS_PER_HANDLE (EFI_SUBCLASS_SPECIFIC | 0x00000022)
+#define EFI_SW_BS_PC_LOCATE_HANDLE_BUFFER (EFI_SUBCLASS_SPECIFIC | 0x00000023)
+#define EFI_SW_BS_PC_LOCATE_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x00000024)
+#define EFI_SW_BS_PC_INSTALL_MULTIPLE_INTERFACES (EFI_SUBCLASS_SPECIFIC | 0x00000025)
+#define EFI_SW_BS_PC_UNINSTALL_MULTIPLE_INTERFACES (EFI_SUBCLASS_SPECIFIC | 0x00000026)
+#define EFI_SW_BS_PC_CALCULATE_CRC_32 (EFI_SUBCLASS_SPECIFIC | 0x00000027)
+#define EFI_SW_BS_PC_COPY_MEM (EFI_SUBCLASS_SPECIFIC | 0x00000028)
+#define EFI_SW_BS_PC_SET_MEM (EFI_SUBCLASS_SPECIFIC | 0x00000029)
+#define EFI_SW_BS_PC_CREATE_EVENT_EX (EFI_SUBCLASS_SPECIFIC | 0x0000002A)
+///@}
+
+///
+/// Software Class EFI Runtime Services Subclass Progress Code definitions.
+///
+///@{
+#define EFI_SW_RS_PC_GET_TIME (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_RS_PC_SET_TIME (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_SW_RS_PC_GET_WAKEUP_TIME (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_SW_RS_PC_SET_WAKEUP_TIME (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+#define EFI_SW_RS_PC_SET_VIRTUAL_ADDRESS_MAP (EFI_SUBCLASS_SPECIFIC | 0x00000004)
+#define EFI_SW_RS_PC_CONVERT_POINTER (EFI_SUBCLASS_SPECIFIC | 0x00000005)
+#define EFI_SW_RS_PC_GET_VARIABLE (EFI_SUBCLASS_SPECIFIC | 0x00000006)
+#define EFI_SW_RS_PC_GET_NEXT_VARIABLE_NAME (EFI_SUBCLASS_SPECIFIC | 0x00000007)
+#define EFI_SW_RS_PC_SET_VARIABLE (EFI_SUBCLASS_SPECIFIC | 0x00000008)
+#define EFI_SW_RS_PC_GET_NEXT_HIGH_MONOTONIC_COUNT (EFI_SUBCLASS_SPECIFIC | 0x00000009)
+#define EFI_SW_RS_PC_RESET_SYSTEM (EFI_SUBCLASS_SPECIFIC | 0x0000000A)
+#define EFI_SW_RS_PC_UPDATE_CAPSULE (EFI_SUBCLASS_SPECIFIC | 0x0000000B)
+#define EFI_SW_RS_PC_QUERY_CAPSULE_CAPABILITIES (EFI_SUBCLASS_SPECIFIC | 0x0000000C)
+#define EFI_SW_RS_PC_QUERY_VARIABLE_INFO (EFI_SUBCLASS_SPECIFIC | 0x0000000D)
+///@}
+
+///
+/// Software Class EFI DXE Services Subclass Progress Code definitions
+///
+///@{
+#define EFI_SW_DS_PC_ADD_MEMORY_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_DS_PC_ALLOCATE_MEMORY_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_SW_DS_PC_FREE_MEMORY_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_SW_DS_PC_REMOVE_MEMORY_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+#define EFI_SW_DS_PC_GET_MEMORY_SPACE_DESCRIPTOR (EFI_SUBCLASS_SPECIFIC | 0x00000004)
+#define EFI_SW_DS_PC_SET_MEMORY_SPACE_ATTRIBUTES (EFI_SUBCLASS_SPECIFIC | 0x00000005)
+#define EFI_SW_DS_PC_GET_MEMORY_SPACE_MAP (EFI_SUBCLASS_SPECIFIC | 0x00000006)
+#define EFI_SW_DS_PC_ADD_IO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000007)
+#define EFI_SW_DS_PC_ALLOCATE_IO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000008)
+#define EFI_SW_DS_PC_FREE_IO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000009)
+#define EFI_SW_DS_PC_REMOVE_IO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x0000000A)
+#define EFI_SW_DS_PC_GET_IO_SPACE_DESCRIPTOR (EFI_SUBCLASS_SPECIFIC | 0x0000000B)
+#define EFI_SW_DS_PC_GET_IO_SPACE_MAP (EFI_SUBCLASS_SPECIFIC | 0x0000000C)
+#define EFI_SW_DS_PC_DISPATCH (EFI_SUBCLASS_SPECIFIC | 0x0000000D)
+#define EFI_SW_DS_PC_SCHEDULE (EFI_SUBCLASS_SPECIFIC | 0x0000000E)
+#define EFI_SW_DS_PC_TRUST (EFI_SUBCLASS_SPECIFIC | 0x0000000F)
+#define EFI_SW_DS_PC_PROCESS_FIRMWARE_VOLUME (EFI_SUBCLASS_SPECIFIC | 0x00000010)
+///@}
+
+///
+/// Software Class Error Code definitions.
+/// These are shared by all subclasses.
+///
+///@{
+#define EFI_SW_EC_NON_SPECIFIC 0x00000000
+#define EFI_SW_EC_LOAD_ERROR 0x00000001
+#define EFI_SW_EC_INVALID_PARAMETER 0x00000002
+#define EFI_SW_EC_UNSUPPORTED 0x00000003
+#define EFI_SW_EC_INVALID_BUFFER 0x00000004
+#define EFI_SW_EC_OUT_OF_RESOURCES 0x00000005
+#define EFI_SW_EC_ABORTED 0x00000006
+#define EFI_SW_EC_ILLEGAL_SOFTWARE_STATE 0x00000007
+#define EFI_SW_EC_ILLEGAL_HARDWARE_STATE 0x00000008
+#define EFI_SW_EC_START_ERROR 0x00000009
+#define EFI_SW_EC_BAD_DATE_TIME 0x0000000A
+#define EFI_SW_EC_CFG_INVALID 0x0000000B
+#define EFI_SW_EC_CFG_CLR_REQUEST 0x0000000C
+#define EFI_SW_EC_CFG_DEFAULT 0x0000000D
+#define EFI_SW_EC_PWD_INVALID 0x0000000E
+#define EFI_SW_EC_PWD_CLR_REQUEST 0x0000000F
+#define EFI_SW_EC_PWD_CLEARED 0x00000010
+#define EFI_SW_EC_EVENT_LOG_FULL 0x00000011
+///@}
+
+//
+// Software Class Unspecified Subclass Error Code definitions.
+//
+
+//
+// Software Class SEC Subclass Error Code definitions.
+//
+
+///
+/// Software Class PEI Core Subclass Error Code definitions.
+///
+///@{
+#define EFI_SW_PEI_CORE_EC_DXE_CORRUPT (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_PEI_CORE_EC_DXEIPL_NOT_FOUND (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_SW_PEI_CORE_EC_MEMORY_NOT_INSTALLED (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+///@}
+
+///
+/// Software Class PEI Module Subclass Error Code definitions.
+/// Note: EFI_SW_PEI_EC_INVALID_CAPSULE_DESCRIPTOR is different from PI 1.2 Specification.
+///
+///@{
+#define EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_PEI_EC_INVALID_CAPSULE_DESCRIPTOR (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_SW_PEI_EC_S3_RESUME_PPI_NOT_FOUND (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_SW_PEI_EC_S3_BOOT_SCRIPT_ERROR (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+#define EFI_SW_PEI_EC_S3_OS_WAKE_ERROR (EFI_SUBCLASS_SPECIFIC | 0x00000004)
+#define EFI_SW_PEI_EC_S3_RESUME_FAILED (EFI_SUBCLASS_SPECIFIC | 0x00000005)
+#define EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND (EFI_SUBCLASS_SPECIFIC | 0x00000006)
+#define EFI_SW_PEI_EC_RECOVERY_FAILED (EFI_SUBCLASS_SPECIFIC | 0x00000007)
+///@}
+
+///
+/// Software Class DXE Foundation Subclass Error Code definitions.
+///
+///@{
+#define EFI_SW_DXE_CORE_EC_NO_ARCH (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+///@}
+
+
+///
+/// Software Class DXE Boot Service Driver Subclass Error Code definitions.
+///
+///@{
+#define EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_DXE_BS_EC_INVALID_PASSWORD (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+#define EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR (EFI_SUBCLASS_SPECIFIC | 0x00000002)
+#define EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED (EFI_SUBCLASS_SPECIFIC | 0x00000003)
+#define EFI_SW_DXE_BS_EC_INVALID_IDE_PASSWORD (EFI_SUBCLASS_SPECIFIC | 0x00000004)
+///@}
+
+//
+// Software Class DXE Runtime Service Driver Subclass Error Code definitions.
+//
+
+//
+// Software Class SMM Driver Subclass Error Code definitions.
+//
+
+//
+// Software Class EFI Application Subclass Error Code definitions.
+//
+
+//
+// Software Class EFI OS Loader Subclass Error Code definitions.
+//
+
+//
+// Software Class EFI RT Subclass Error Code definitions.
+//
+
+//
+// Software Class EFI AL Subclass Error Code definitions.
+//
+
+///
+/// Software Class EBC Exception Subclass Error Code definitions.
+/// These exceptions are derived from the debug protocol definitions in the EFI
+/// specification.
+///
+///@{
+#define EFI_SW_EC_EBC_UNDEFINED 0x00000000
+#define EFI_SW_EC_EBC_DIVIDE_ERROR EXCEPT_EBC_DIVIDE_ERROR
+#define EFI_SW_EC_EBC_DEBUG EXCEPT_EBC_DEBUG
+#define EFI_SW_EC_EBC_BREAKPOINT EXCEPT_EBC_BREAKPOINT
+#define EFI_SW_EC_EBC_OVERFLOW EXCEPT_EBC_OVERFLOW
+#define EFI_SW_EC_EBC_INVALID_OPCODE EXCEPT_EBC_INVALID_OPCODE
+#define EFI_SW_EC_EBC_STACK_FAULT EXCEPT_EBC_STACK_FAULT
+#define EFI_SW_EC_EBC_ALIGNMENT_CHECK EXCEPT_EBC_ALIGNMENT_CHECK
+#define EFI_SW_EC_EBC_INSTRUCTION_ENCODING EXCEPT_EBC_INSTRUCTION_ENCODING
+#define EFI_SW_EC_EBC_BAD_BREAK EXCEPT_EBC_BAD_BREAK
+#define EFI_SW_EC_EBC_STEP EXCEPT_EBC_STEP
+///@}
+
+///
+/// Software Class IA32 Exception Subclass Error Code definitions.
+/// These exceptions are derived from the debug protocol definitions in the EFI
+/// specification.
+///
+///@{
+#define EFI_SW_EC_IA32_DIVIDE_ERROR EXCEPT_IA32_DIVIDE_ERROR
+#define EFI_SW_EC_IA32_DEBUG EXCEPT_IA32_DEBUG
+#define EFI_SW_EC_IA32_NMI EXCEPT_IA32_NMI
+#define EFI_SW_EC_IA32_BREAKPOINT EXCEPT_IA32_BREAKPOINT
+#define EFI_SW_EC_IA32_OVERFLOW EXCEPT_IA32_OVERFLOW
+#define EFI_SW_EC_IA32_BOUND EXCEPT_IA32_BOUND
+#define EFI_SW_EC_IA32_INVALID_OPCODE EXCEPT_IA32_INVALID_OPCODE
+#define EFI_SW_EC_IA32_DOUBLE_FAULT EXCEPT_IA32_DOUBLE_FAULT
+#define EFI_SW_EC_IA32_INVALID_TSS EXCEPT_IA32_INVALID_TSS
+#define EFI_SW_EC_IA32_SEG_NOT_PRESENT EXCEPT_IA32_SEG_NOT_PRESENT
+#define EFI_SW_EC_IA32_STACK_FAULT EXCEPT_IA32_STACK_FAULT
+#define EFI_SW_EC_IA32_GP_FAULT EXCEPT_IA32_GP_FAULT
+#define EFI_SW_EC_IA32_PAGE_FAULT EXCEPT_IA32_PAGE_FAULT
+#define EFI_SW_EC_IA32_FP_ERROR EXCEPT_IA32_FP_ERROR
+#define EFI_SW_EC_IA32_ALIGNMENT_CHECK EXCEPT_IA32_ALIGNMENT_CHECK
+#define EFI_SW_EC_IA32_MACHINE_CHECK EXCEPT_IA32_MACHINE_CHECK
+#define EFI_SW_EC_IA32_SIMD EXCEPT_IA32_SIMD
+///@}
+
+///
+/// Software Class IPF Exception Subclass Error Code definitions.
+/// These exceptions are derived from the debug protocol definitions in the EFI
+/// specification.
+///
+///@{
+#define EFI_SW_EC_IPF_ALT_DTLB EXCEPT_IPF_ALT_DTLB
+#define EFI_SW_EC_IPF_DNESTED_TLB EXCEPT_IPF_DNESTED_TLB
+#define EFI_SW_EC_IPF_BREAKPOINT EXCEPT_IPF_BREAKPOINT
+#define EFI_SW_EC_IPF_EXTERNAL_INTERRUPT EXCEPT_IPF_EXTERNAL_INTERRUPT
+#define EFI_SW_EC_IPF_GEN_EXCEPT EXCEPT_IPF_GEN_EXCEPT
+#define EFI_SW_EC_IPF_NAT_CONSUMPTION EXCEPT_IPF_NAT_CONSUMPTION
+#define EFI_SW_EC_IPF_DEBUG_EXCEPT EXCEPT_IPF_DEBUG_EXCEPT
+#define EFI_SW_EC_IPF_UNALIGNED_ACCESS EXCEPT_IPF_UNALIGNED_ACCESS
+#define EFI_SW_EC_IPF_FP_FAULT EXCEPT_IPF_FP_FAULT
+#define EFI_SW_EC_IPF_FP_TRAP EXCEPT_IPF_FP_TRAP
+#define EFI_SW_EC_IPF_TAKEN_BRANCH EXCEPT_IPF_TAKEN_BRANCH
+#define EFI_SW_EC_IPF_SINGLE_STEP EXCEPT_IPF_SINGLE_STEP
+///@}
+
+///
+/// Software Class PEI Service Subclass Error Code definitions.
+///
+///@{
+#define EFI_SW_PS_EC_RESET_NOT_AVAILABLE (EFI_SUBCLASS_SPECIFIC | 0x00000000)
+#define EFI_SW_PS_EC_MEMORY_INSTALLED_TWICE (EFI_SUBCLASS_SPECIFIC | 0x00000001)
+///@}
+
+//
+// Software Class EFI Boot Service Subclass Error Code definitions.
+//
+
+//
+// Software Class EFI Runtime Service Subclass Error Code definitions.
+//
+
+//
+// Software Class EFI DXE Service Subclass Error Code definitions.
+//
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/PiDxe.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/PiDxe.h
new file mode 100644
index 00000000..94433680
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/PiDxe.h
@@ -0,0 +1,27 @@
+/** @file
+
+ Root include file for Mde Package DXE_CORE, DXE, RUNTIME, SMM, SAL type modules.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PI_DXE_H__
+#define __PI_DXE_H__
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/Uefi/UefiBaseType.h>
+#include <ipxe/efi/Uefi/UefiSpec.h>
+
+#include <ipxe/efi/Pi/PiDxeCis.h>
+
+#endif
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/ProcessorBind.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/ProcessorBind.h
new file mode 100644
index 00000000..535cd4ce
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/ProcessorBind.h
@@ -0,0 +1,19 @@
+#ifndef _IPXE_EFI_PROCESSOR_BIND_H
+#define _IPXE_EFI_PROCESSOR_BIND_H
+
+/*
+ * EFI header files rely on having the CPU architecture directory
+ * present in the search path in order to pick up ProcessorBind.h. We
+ * use this header file as a quick indirection layer.
+ * - mcb30
+ */
+
+#if __i386__
+#include <ipxe/efi/Ia32/ProcessorBind.h>
+#endif
+
+#if __x86_64__
+#include <ipxe/efi/X64/ProcessorBind.h>
+#endif
+
+#endif /* _IPXE_EFI_PROCESSOR_BIND_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/ComponentName2.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/ComponentName2.h
new file mode 100644
index 00000000..978ede5a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/ComponentName2.h
@@ -0,0 +1,175 @@
+/** @file
+ UEFI Component Name 2 Protocol as defined in the UEFI 2.1 specification.
+ This protocol is used to retrieve user readable names of drivers
+ and controllers managed by UEFI Drivers.
+
+ Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_COMPONENT_NAME2_H__
+#define __EFI_COMPONENT_NAME2_H__
+
+FILE_LICENCE ( BSD3 );
+
+///
+/// Global ID for the Component Name Protocol
+///
+#define EFI_COMPONENT_NAME2_PROTOCOL_GUID \
+ {0x6a7a5cff, 0xe8d9, 0x4f70, { 0xba, 0xda, 0x75, 0xab, 0x30, 0x25, 0xce, 0x14 } }
+
+typedef struct _EFI_COMPONENT_NAME2_PROTOCOL EFI_COMPONENT_NAME2_PROTOCOL;
+
+
+/**
+ Retrieves a string that is the user readable name of
+ the EFI Driver.
+
+ @param This A pointer to the
+ EFI_COMPONENT_NAME2_PROTOCOL instance.
+
+ @param Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller
+ is requesting, and it must match one of the
+ languages specified in SupportedLanguages.
+ The number of languages supported by a
+ driver is up to the driver writer. Language
+ is specified in RFC 4646 language code
+ format.
+
+ @param DriverName A pointer to the string to return.
+ This string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The string for the
+ Driver specified by This and the
+ language specified by Language
+ was returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This
+ does not support the language
+ specified by Language.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_COMPONENT_NAME2_GET_DRIVER_NAME)(
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+
+/**
+ Retrieves a string that is the user readable name of
+ the controller that is being managed by an EFI Driver.
+
+ @param This A pointer to the
+ EFI_COMPONENT_NAME2_PROTOCOL instance.
+
+ @param ControllerHandle The handle of a controller that the
+ driver specified by This is managing.
+ This handle specifies the controller
+ whose name is to be returned.
+
+ @param ChildHandle The handle of the child controller to
+ retrieve the name of. This is an
+ optional parameter that may be NULL.
+ It will be NULL for device drivers.
+ It will also be NULL for bus
+ drivers that wish to retrieve the
+ name of the bus controller. It will
+ not be NULL for a bus driver that
+ wishes to retrieve the name of a
+ child controller.
+
+ @param Language A pointer to a Null-terminated ASCII
+ string array indicating the language.
+ This is the language of the driver
+ name that the caller is requesting,
+ and it must match one of the
+ languages specified in
+ SupportedLanguages. The number of
+ languages supported by a driver is up
+ to the driver writer. Language is
+ specified in RFC 4646 language code
+ format.
+
+ @param ControllerName A pointer to the string to return.
+ This string is the name of the controller
+ specified by ControllerHandle and ChildHandle
+ in the language specified by Language
+ from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The string for the user
+ readable name in the language
+ specified by Language for the
+ driver specified by This was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it
+ is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is
+ not currently managing the
+ controller specified by
+ ControllerHandle and
+ ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This
+ does not support the language
+ specified by Language.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)(
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+///
+/// This protocol is used to retrieve user readable names of drivers
+/// and controllers managed by UEFI Drivers.
+///
+struct _EFI_COMPONENT_NAME2_PROTOCOL {
+ EFI_COMPONENT_NAME2_GET_DRIVER_NAME GetDriverName;
+ EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME GetControllerName;
+
+ ///
+ /// A Null-terminated ASCII string array that contains one or more
+ /// supported language codes. This is the list of language codes that
+ /// this protocol supports. The number of languages supported by a
+ /// driver is up to the driver writer. SupportedLanguages is
+ /// specified in RFC 4646 format.
+ ///
+ CHAR8 *SupportedLanguages;
+};
+
+extern EFI_GUID gEfiComponentName2ProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/Cpu.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/Cpu.h
new file mode 100644
index 00000000..ebcaf5f1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/Cpu.h
@@ -0,0 +1,300 @@
+/** @file
+ CPU Architectural Protocol as defined in PI spec Volume 2 DXE
+
+ This code abstracts the DXE core from processor implementation details.
+
+ Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __ARCH_PROTOCOL_CPU_H__
+#define __ARCH_PROTOCOL_CPU_H__
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/Protocol/DebugSupport.h>
+
+#define EFI_CPU_ARCH_PROTOCOL_GUID \
+ { 0x26baccb1, 0x6f42, 0x11d4, {0xbc, 0xe7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } }
+
+typedef struct _EFI_CPU_ARCH_PROTOCOL EFI_CPU_ARCH_PROTOCOL;
+
+///
+/// The type of flush operation
+///
+typedef enum {
+ EfiCpuFlushTypeWriteBackInvalidate,
+ EfiCpuFlushTypeWriteBack,
+ EfiCpuFlushTypeInvalidate,
+ EfiCpuMaxFlushType
+} EFI_CPU_FLUSH_TYPE;
+
+///
+/// The type of processor INIT.
+///
+typedef enum {
+ EfiCpuInit,
+ EfiCpuMaxInitType
+} EFI_CPU_INIT_TYPE;
+
+/**
+ EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
+
+ @param InterruptType Defines the type of interrupt or exception that
+ occurred on the processor.This parameter is processor architecture specific.
+ @param SystemContext A pointer to the processor context when
+ the interrupt occurred on the processor.
+
+ @return None
+
+**/
+typedef
+VOID
+(EFIAPI *EFI_CPU_INTERRUPT_HANDLER)(
+ IN CONST EFI_EXCEPTION_TYPE InterruptType,
+ IN CONST EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+/**
+ This function flushes the range of addresses from Start to Start+Length
+ from the processor's data cache. If Start is not aligned to a cache line
+ boundary, then the bytes before Start to the preceding cache line boundary
+ are also flushed. If Start+Length is not aligned to a cache line boundary,
+ then the bytes past Start+Length to the end of the next cache line boundary
+ are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
+ supported. If the data cache is fully coherent with all DMA operations, then
+ this function can just return EFI_SUCCESS. If the processor does not support
+ flushing a range of the data cache, then the entire data cache can be flushed.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param Start The beginning physical address to flush from the processor's data
+ cache.
+ @param Length The number of bytes to flush from the processor's data cache. This
+ function may flush more bytes than Length specifies depending upon
+ the granularity of the flush operation that the processor supports.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
+ the processor's data cache.
+ @retval EFI_UNSUPPORTEDT The processor does not support the cache flush type specified
+ by FlushType.
+ @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
+ from the processor's data cache.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_FLUSH_DATA_CACHE)(
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ );
+
+
+/**
+ This function enables interrupt processing by the processor.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Interrupts are enabled on the processor.
+ @retval EFI_DEVICE_ERROR Interrupts could not be enabled on the processor.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_ENABLE_INTERRUPT)(
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+
+/**
+ This function disables interrupt processing by the processor.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Interrupts are disabled on the processor.
+ @retval EFI_DEVICE_ERROR Interrupts could not be disabled on the processor.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_DISABLE_INTERRUPT)(
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+
+/**
+ This function retrieves the processor's current interrupt state a returns it in
+ State. If interrupts are currently enabled, then TRUE is returned. If interrupts
+ are currently disabled, then FALSE is returned.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param State A pointer to the processor's current interrupt state. Set to TRUE if
+ interrupts are enabled and FALSE if interrupts are disabled.
+
+ @retval EFI_SUCCESS The processor's current interrupt state was returned in State.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_GET_INTERRUPT_STATE)(
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ );
+
+
+/**
+ This function generates an INIT on the processor. If this function succeeds, then the
+ processor will be reset, and control will not be returned to the caller. If InitType is
+ not supported by this processor, or the processor cannot programmatically generate an
+ INIT without help from external hardware, then EFI_UNSUPPORTED is returned. If an error
+ occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param InitType The type of processor INIT to perform.
+
+ @retval EFI_SUCCESS The processor INIT was performed. This return code should never be seen.
+ @retval EFI_UNSUPPORTED The processor INIT operation specified by InitType is not supported
+ by this processor.
+ @retval EFI_DEVICE_ERROR The processor INIT failed.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_INIT)(
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ );
+
+
+/**
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
+ are enabled and FALSE if interrupts are disabled.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_REGISTER_INTERRUPT_HANDLER)(
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+
+/**
+ This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
+ must be between 0 and NumberOfTimers-1.
+ @param TimerValue Pointer to the returned timer value.
+ @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
+ of TimerValue. If TimerValue does not increment at a predictable rate, then 0 is
+ returned. This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
+ @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
+ @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
+ @retval EFI_UNSUPPORTED The processor does not have any readable timers.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_GET_TIMER_VALUE)(
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ );
+
+
+/**
+ This function modifies the attributes for the memory region specified by BaseAddress and
+ Length from their current attributes to the attributes specified by Attributes.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param BaseAddress The physical address that is the start address of a memory region.
+ @param Length The size in bytes of the memory region.
+ @param Attributes The bit mask of attributes to set for the memory region.
+
+ @retval EFI_SUCCESS The attributes were set for the memory region.
+ @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
+ BaseAddress and Length cannot be modified.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
+ the memory resource range.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
+ resource range specified by BaseAddress and Length.
+ The bit mask of attributes is not support for the memory resource
+ range specified by BaseAddress and Length.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_SET_MEMORY_ATTRIBUTES)(
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ );
+
+
+///
+/// The EFI_CPU_ARCH_PROTOCOL is used to abstract processor-specific functions from the DXE
+/// Foundation. This includes flushing caches, enabling and disabling interrupts, hooking interrupt
+/// vectors and exception vectors, reading internal processor timers, resetting the processor, and
+/// determining the processor frequency.
+///
+struct _EFI_CPU_ARCH_PROTOCOL {
+ EFI_CPU_FLUSH_DATA_CACHE FlushDataCache;
+ EFI_CPU_ENABLE_INTERRUPT EnableInterrupt;
+ EFI_CPU_DISABLE_INTERRUPT DisableInterrupt;
+ EFI_CPU_GET_INTERRUPT_STATE GetInterruptState;
+ EFI_CPU_INIT Init;
+ EFI_CPU_REGISTER_INTERRUPT_HANDLER RegisterInterruptHandler;
+ EFI_CPU_GET_TIMER_VALUE GetTimerValue;
+ EFI_CPU_SET_MEMORY_ATTRIBUTES SetMemoryAttributes;
+ ///
+ /// The number of timers that are available in a processor. The value in this
+ /// field is a constant that must not be modified after the CPU Architectural
+ /// Protocol is installed. All consumers must treat this as a read-only field.
+ ///
+ UINT32 NumberOfTimers;
+ ///
+ /// The size, in bytes, of the alignment required for DMA buffer allocations.
+ /// This is typically the size of the largest data cache line in the platform.
+ /// The value in this field is a constant that must not be modified after the
+ /// CPU Architectural Protocol is installed. All consumers must treat this as
+ /// a read-only field.
+ ///
+ UINT32 DmaBufferAlignment;
+};
+
+extern EFI_GUID gEfiCpuArchProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/CpuIo.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/CpuIo.h
new file mode 100644
index 00000000..39b82b3b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/CpuIo.h
@@ -0,0 +1,48 @@
+/** @file
+ This code abstracts the CPU IO Protocol which installed by some platform or chipset-specific
+ PEIM that abstracts the processor-visible I/O operations.
+
+ Note: This is a runtime protocol and can be used by runtime drivers after ExitBootServices().
+ It is different from the PI 1.2 CPU I/O 2 Protocol, which is a boot services only protocol
+ and may not be used by runtime drivers after ExitBootServices().
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ CPU IO Protocol is defined in Framework of EFI CPU IO Protocol Spec
+ Version 0.9.
+
+**/
+
+#ifndef _CPUIO_H_
+#define _CPUIO_H_
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/Protocol/CpuIo2.h>
+
+#define EFI_CPU_IO_PROTOCOL_GUID \
+ { \
+ 0xB0732526, 0x38C8, 0x4b40, {0x88, 0x77, 0x61, 0xC7, 0xB0, 0x6A, 0xAC, 0x45 } \
+ }
+
+//
+// Framework CPU IO protocol structure is the same as CPU IO 2 protocol defined in PI 1.2 spec.
+// However, there is a significant different between the Framework CPU I/O
+// Protocol and the PI 1.2 CPU I/O 2 Protocol. The Framework one is a runtime
+// protocol, which means it can be used by runtime drivers after ExitBootServices().
+// The PI one is not runtime safe, so it is a boot services only protocol and may
+// not be used by runtime drivers after ExitBootServices().
+//
+typedef EFI_CPU_IO2_PROTOCOL EFI_CPU_IO_PROTOCOL;
+
+extern EFI_GUID gEfiCpuIoProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/CpuIo2.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/CpuIo2.h
new file mode 100644
index 00000000..aef8157d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/CpuIo2.h
@@ -0,0 +1,144 @@
+/** @file
+ This files describes the CPU I/O 2 Protocol.
+
+ This protocol provides an I/O abstraction for a system processor. This protocol
+ is used by a PCI root bridge I/O driver to perform memory-mapped I/O and I/O transactions.
+ The I/O or memory primitives can be used by the consumer of the protocol to materialize
+ bus-specific configuration cycles, such as the transitional configuration address and data
+ ports for PCI. Only drivers that require direct access to the entire system should use this
+ protocol.
+
+ Note: This is a boot-services only protocol and it may not be used by runtime drivers after
+ ExitBootServices(). It is different from the Framework CPU I/O Protocol, which is a runtime
+ protocol and can be used by runtime drivers after ExitBootServices().
+
+ Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ This Protocol is defined in UEFI Platform Initialization Specification 1.2
+ Volume 5: Standards
+
+**/
+
+#ifndef __CPU_IO2_H__
+#define __CPU_IO2_H__
+
+FILE_LICENCE ( BSD3 );
+
+#define EFI_CPU_IO2_PROTOCOL_GUID \
+ { \
+ 0xad61f191, 0xae5f, 0x4c0e, {0xb9, 0xfa, 0xe8, 0x69, 0xd2, 0x88, 0xc6, 0x4f} \
+ }
+
+typedef struct _EFI_CPU_IO2_PROTOCOL EFI_CPU_IO2_PROTOCOL;
+
+///
+/// Enumeration that defines the width of the I/O operation.
+///
+typedef enum {
+ EfiCpuIoWidthUint8,
+ EfiCpuIoWidthUint16,
+ EfiCpuIoWidthUint32,
+ EfiCpuIoWidthUint64,
+ EfiCpuIoWidthFifoUint8,
+ EfiCpuIoWidthFifoUint16,
+ EfiCpuIoWidthFifoUint32,
+ EfiCpuIoWidthFifoUint64,
+ EfiCpuIoWidthFillUint8,
+ EfiCpuIoWidthFillUint16,
+ EfiCpuIoWidthFillUint32,
+ EfiCpuIoWidthFillUint64,
+ EfiCpuIoWidthMaximum
+} EFI_CPU_IO_PROTOCOL_WIDTH;
+
+/**
+ Enables a driver to access registers in the PI CPU I/O space.
+
+ The Io.Read() and Io.Write() functions enable a driver to access PCI controller
+ registers in the PI CPU I/O space.
+
+ The I/O operations are carried out exactly as requested. The caller is responsible
+ for satisfying any alignment and I/O width restrictions that a PI System on a
+ platform might require. For example on some platforms, width requests of
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
+ be handled by the driver.
+
+ If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
+ or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
+ each of the Count operations that is performed.
+
+ If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
+ EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times on the same Address.
+
+ If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
+ EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
+ incremented for each of the Count operations that is performed. The read or
+ write operation is performed Count times from the first element of Buffer.
+
+ @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number
+ of bytes moved is Width size * Count, starting at Address.
+ @param[in, out] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the PI system.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_IO_PROTOCOL_IO_MEM)(
+ IN EFI_CPU_IO2_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+///
+/// Service for read and write accesses.
+///
+typedef struct {
+ ///
+ /// This service provides the various modalities of memory and I/O read.
+ ///
+ EFI_CPU_IO_PROTOCOL_IO_MEM Read;
+ ///
+ /// This service provides the various modalities of memory and I/O write.
+ ///
+ EFI_CPU_IO_PROTOCOL_IO_MEM Write;
+} EFI_CPU_IO_PROTOCOL_ACCESS;
+
+///
+/// Provides the basic memory and I/O interfaces that are used to abstract
+/// accesses to devices in a system.
+///
+struct _EFI_CPU_IO2_PROTOCOL {
+ ///
+ /// Enables a driver to access memory-mapped registers in the EFI system memory space.
+ ///
+ EFI_CPU_IO_PROTOCOL_ACCESS Mem;
+ ///
+ /// Enables a driver to access registers in the EFI CPU I/O space.
+ ///
+ EFI_CPU_IO_PROTOCOL_ACCESS Io;
+};
+
+extern EFI_GUID gEfiCpuIo2ProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/DebugSupport.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/DebugSupport.h
new file mode 100644
index 00000000..ea5cec57
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/DebugSupport.h
@@ -0,0 +1,685 @@
+/** @file
+ DebugSupport protocol and supporting definitions as defined in the UEFI2.0
+ specification.
+
+ The DebugSupport protocol is used by source level debuggers to abstract the
+ processor and handle context save and restore operations.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __DEBUG_SUPPORT_H__
+#define __DEBUG_SUPPORT_H__
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/IndustryStandard/PeImage.h>
+
+typedef struct _EFI_DEBUG_SUPPORT_PROTOCOL EFI_DEBUG_SUPPORT_PROTOCOL;
+
+///
+/// Debug Support protocol {2755590C-6F3C-42FA-9EA4-A3BA543CDA25}.
+///
+#define EFI_DEBUG_SUPPORT_PROTOCOL_GUID \
+ { \
+ 0x2755590C, 0x6F3C, 0x42FA, {0x9E, 0xA4, 0xA3, 0xBA, 0x54, 0x3C, 0xDA, 0x25 } \
+ }
+
+///
+/// Processor exception to be hooked.
+/// All exception types for IA32, X64, Itanium and EBC processors are defined.
+///
+typedef INTN EFI_EXCEPTION_TYPE;
+
+///
+/// IA-32 processor exception types.
+///
+#define EXCEPT_IA32_DIVIDE_ERROR 0
+#define EXCEPT_IA32_DEBUG 1
+#define EXCEPT_IA32_NMI 2
+#define EXCEPT_IA32_BREAKPOINT 3
+#define EXCEPT_IA32_OVERFLOW 4
+#define EXCEPT_IA32_BOUND 5
+#define EXCEPT_IA32_INVALID_OPCODE 6
+#define EXCEPT_IA32_DOUBLE_FAULT 8
+#define EXCEPT_IA32_INVALID_TSS 10
+#define EXCEPT_IA32_SEG_NOT_PRESENT 11
+#define EXCEPT_IA32_STACK_FAULT 12
+#define EXCEPT_IA32_GP_FAULT 13
+#define EXCEPT_IA32_PAGE_FAULT 14
+#define EXCEPT_IA32_FP_ERROR 16
+#define EXCEPT_IA32_ALIGNMENT_CHECK 17
+#define EXCEPT_IA32_MACHINE_CHECK 18
+#define EXCEPT_IA32_SIMD 19
+
+///
+/// FXSAVE_STATE.
+/// FP / MMX / XMM registers (see fxrstor instruction definition).
+///
+typedef struct {
+ UINT16 Fcw;
+ UINT16 Fsw;
+ UINT16 Ftw;
+ UINT16 Opcode;
+ UINT32 Eip;
+ UINT16 Cs;
+ UINT16 Reserved1;
+ UINT32 DataOffset;
+ UINT16 Ds;
+ UINT8 Reserved2[10];
+ UINT8 St0Mm0[10], Reserved3[6];
+ UINT8 St1Mm1[10], Reserved4[6];
+ UINT8 St2Mm2[10], Reserved5[6];
+ UINT8 St3Mm3[10], Reserved6[6];
+ UINT8 St4Mm4[10], Reserved7[6];
+ UINT8 St5Mm5[10], Reserved8[6];
+ UINT8 St6Mm6[10], Reserved9[6];
+ UINT8 St7Mm7[10], Reserved10[6];
+ UINT8 Xmm0[16];
+ UINT8 Xmm1[16];
+ UINT8 Xmm2[16];
+ UINT8 Xmm3[16];
+ UINT8 Xmm4[16];
+ UINT8 Xmm5[16];
+ UINT8 Xmm6[16];
+ UINT8 Xmm7[16];
+ UINT8 Reserved11[14 * 16];
+} EFI_FX_SAVE_STATE_IA32;
+
+///
+/// IA-32 processor context definition.
+///
+typedef struct {
+ UINT32 ExceptionData;
+ EFI_FX_SAVE_STATE_IA32 FxSaveState;
+ UINT32 Dr0;
+ UINT32 Dr1;
+ UINT32 Dr2;
+ UINT32 Dr3;
+ UINT32 Dr6;
+ UINT32 Dr7;
+ UINT32 Cr0;
+ UINT32 Cr1; /* Reserved */
+ UINT32 Cr2;
+ UINT32 Cr3;
+ UINT32 Cr4;
+ UINT32 Eflags;
+ UINT32 Ldtr;
+ UINT32 Tr;
+ UINT32 Gdtr[2];
+ UINT32 Idtr[2];
+ UINT32 Eip;
+ UINT32 Gs;
+ UINT32 Fs;
+ UINT32 Es;
+ UINT32 Ds;
+ UINT32 Cs;
+ UINT32 Ss;
+ UINT32 Edi;
+ UINT32 Esi;
+ UINT32 Ebp;
+ UINT32 Esp;
+ UINT32 Ebx;
+ UINT32 Edx;
+ UINT32 Ecx;
+ UINT32 Eax;
+} EFI_SYSTEM_CONTEXT_IA32;
+
+///
+/// x64 processor exception types.
+///
+#define EXCEPT_X64_DIVIDE_ERROR 0
+#define EXCEPT_X64_DEBUG 1
+#define EXCEPT_X64_NMI 2
+#define EXCEPT_X64_BREAKPOINT 3
+#define EXCEPT_X64_OVERFLOW 4
+#define EXCEPT_X64_BOUND 5
+#define EXCEPT_X64_INVALID_OPCODE 6
+#define EXCEPT_X64_DOUBLE_FAULT 8
+#define EXCEPT_X64_INVALID_TSS 10
+#define EXCEPT_X64_SEG_NOT_PRESENT 11
+#define EXCEPT_X64_STACK_FAULT 12
+#define EXCEPT_X64_GP_FAULT 13
+#define EXCEPT_X64_PAGE_FAULT 14
+#define EXCEPT_X64_FP_ERROR 16
+#define EXCEPT_X64_ALIGNMENT_CHECK 17
+#define EXCEPT_X64_MACHINE_CHECK 18
+#define EXCEPT_X64_SIMD 19
+
+///
+/// FXSAVE_STATE.
+/// FP / MMX / XMM registers (see fxrstor instruction definition).
+///
+typedef struct {
+ UINT16 Fcw;
+ UINT16 Fsw;
+ UINT16 Ftw;
+ UINT16 Opcode;
+ UINT64 Rip;
+ UINT64 DataOffset;
+ UINT8 Reserved1[8];
+ UINT8 St0Mm0[10], Reserved2[6];
+ UINT8 St1Mm1[10], Reserved3[6];
+ UINT8 St2Mm2[10], Reserved4[6];
+ UINT8 St3Mm3[10], Reserved5[6];
+ UINT8 St4Mm4[10], Reserved6[6];
+ UINT8 St5Mm5[10], Reserved7[6];
+ UINT8 St6Mm6[10], Reserved8[6];
+ UINT8 St7Mm7[10], Reserved9[6];
+ UINT8 Xmm0[16];
+ UINT8 Xmm1[16];
+ UINT8 Xmm2[16];
+ UINT8 Xmm3[16];
+ UINT8 Xmm4[16];
+ UINT8 Xmm5[16];
+ UINT8 Xmm6[16];
+ UINT8 Xmm7[16];
+ //
+ // NOTE: UEFI 2.0 spec definition as follows.
+ //
+ UINT8 Reserved11[14 * 16];
+} EFI_FX_SAVE_STATE_X64;
+
+///
+/// x64 processor context definition.
+///
+typedef struct {
+ UINT64 ExceptionData;
+ EFI_FX_SAVE_STATE_X64 FxSaveState;
+ UINT64 Dr0;
+ UINT64 Dr1;
+ UINT64 Dr2;
+ UINT64 Dr3;
+ UINT64 Dr6;
+ UINT64 Dr7;
+ UINT64 Cr0;
+ UINT64 Cr1; /* Reserved */
+ UINT64 Cr2;
+ UINT64 Cr3;
+ UINT64 Cr4;
+ UINT64 Cr8;
+ UINT64 Rflags;
+ UINT64 Ldtr;
+ UINT64 Tr;
+ UINT64 Gdtr[2];
+ UINT64 Idtr[2];
+ UINT64 Rip;
+ UINT64 Gs;
+ UINT64 Fs;
+ UINT64 Es;
+ UINT64 Ds;
+ UINT64 Cs;
+ UINT64 Ss;
+ UINT64 Rdi;
+ UINT64 Rsi;
+ UINT64 Rbp;
+ UINT64 Rsp;
+ UINT64 Rbx;
+ UINT64 Rdx;
+ UINT64 Rcx;
+ UINT64 Rax;
+ UINT64 R8;
+ UINT64 R9;
+ UINT64 R10;
+ UINT64 R11;
+ UINT64 R12;
+ UINT64 R13;
+ UINT64 R14;
+ UINT64 R15;
+} EFI_SYSTEM_CONTEXT_X64;
+
+///
+/// Itanium Processor Family Exception types.
+///
+#define EXCEPT_IPF_VHTP_TRANSLATION 0
+#define EXCEPT_IPF_INSTRUCTION_TLB 1
+#define EXCEPT_IPF_DATA_TLB 2
+#define EXCEPT_IPF_ALT_INSTRUCTION_TLB 3
+#define EXCEPT_IPF_ALT_DATA_TLB 4
+#define EXCEPT_IPF_DATA_NESTED_TLB 5
+#define EXCEPT_IPF_INSTRUCTION_KEY_MISSED 6
+#define EXCEPT_IPF_DATA_KEY_MISSED 7
+#define EXCEPT_IPF_DIRTY_BIT 8
+#define EXCEPT_IPF_INSTRUCTION_ACCESS_BIT 9
+#define EXCEPT_IPF_DATA_ACCESS_BIT 10
+#define EXCEPT_IPF_BREAKPOINT 11
+#define EXCEPT_IPF_EXTERNAL_INTERRUPT 12
+//
+// 13 - 19 reserved
+//
+#define EXCEPT_IPF_PAGE_NOT_PRESENT 20
+#define EXCEPT_IPF_KEY_PERMISSION 21
+#define EXCEPT_IPF_INSTRUCTION_ACCESS_RIGHTS 22
+#define EXCEPT_IPF_DATA_ACCESS_RIGHTS 23
+#define EXCEPT_IPF_GENERAL_EXCEPTION 24
+#define EXCEPT_IPF_DISABLED_FP_REGISTER 25
+#define EXCEPT_IPF_NAT_CONSUMPTION 26
+#define EXCEPT_IPF_SPECULATION 27
+//
+// 28 reserved
+//
+#define EXCEPT_IPF_DEBUG 29
+#define EXCEPT_IPF_UNALIGNED_REFERENCE 30
+#define EXCEPT_IPF_UNSUPPORTED_DATA_REFERENCE 31
+#define EXCEPT_IPF_FP_FAULT 32
+#define EXCEPT_IPF_FP_TRAP 33
+#define EXCEPT_IPF_LOWER_PRIVILEGE_TRANSFER_TRAP 34
+#define EXCEPT_IPF_TAKEN_BRANCH 35
+#define EXCEPT_IPF_SINGLE_STEP 36
+//
+// 37 - 44 reserved
+//
+#define EXCEPT_IPF_IA32_EXCEPTION 45
+#define EXCEPT_IPF_IA32_INTERCEPT 46
+#define EXCEPT_IPF_IA32_INTERRUPT 47
+
+///
+/// IPF processor context definition.
+///
+typedef struct {
+ //
+ // The first reserved field is necessary to preserve alignment for the correct
+ // bits in UNAT and to insure F2 is 16 byte aligned.
+ //
+ UINT64 Reserved;
+ UINT64 R1;
+ UINT64 R2;
+ UINT64 R3;
+ UINT64 R4;
+ UINT64 R5;
+ UINT64 R6;
+ UINT64 R7;
+ UINT64 R8;
+ UINT64 R9;
+ UINT64 R10;
+ UINT64 R11;
+ UINT64 R12;
+ UINT64 R13;
+ UINT64 R14;
+ UINT64 R15;
+ UINT64 R16;
+ UINT64 R17;
+ UINT64 R18;
+ UINT64 R19;
+ UINT64 R20;
+ UINT64 R21;
+ UINT64 R22;
+ UINT64 R23;
+ UINT64 R24;
+ UINT64 R25;
+ UINT64 R26;
+ UINT64 R27;
+ UINT64 R28;
+ UINT64 R29;
+ UINT64 R30;
+ UINT64 R31;
+
+ UINT64 F2[2];
+ UINT64 F3[2];
+ UINT64 F4[2];
+ UINT64 F5[2];
+ UINT64 F6[2];
+ UINT64 F7[2];
+ UINT64 F8[2];
+ UINT64 F9[2];
+ UINT64 F10[2];
+ UINT64 F11[2];
+ UINT64 F12[2];
+ UINT64 F13[2];
+ UINT64 F14[2];
+ UINT64 F15[2];
+ UINT64 F16[2];
+ UINT64 F17[2];
+ UINT64 F18[2];
+ UINT64 F19[2];
+ UINT64 F20[2];
+ UINT64 F21[2];
+ UINT64 F22[2];
+ UINT64 F23[2];
+ UINT64 F24[2];
+ UINT64 F25[2];
+ UINT64 F26[2];
+ UINT64 F27[2];
+ UINT64 F28[2];
+ UINT64 F29[2];
+ UINT64 F30[2];
+ UINT64 F31[2];
+
+ UINT64 Pr;
+
+ UINT64 B0;
+ UINT64 B1;
+ UINT64 B2;
+ UINT64 B3;
+ UINT64 B4;
+ UINT64 B5;
+ UINT64 B6;
+ UINT64 B7;
+
+ //
+ // application registers
+ //
+ UINT64 ArRsc;
+ UINT64 ArBsp;
+ UINT64 ArBspstore;
+ UINT64 ArRnat;
+
+ UINT64 ArFcr;
+
+ UINT64 ArEflag;
+ UINT64 ArCsd;
+ UINT64 ArSsd;
+ UINT64 ArCflg;
+ UINT64 ArFsr;
+ UINT64 ArFir;
+ UINT64 ArFdr;
+
+ UINT64 ArCcv;
+
+ UINT64 ArUnat;
+
+ UINT64 ArFpsr;
+
+ UINT64 ArPfs;
+ UINT64 ArLc;
+ UINT64 ArEc;
+
+ //
+ // control registers
+ //
+ UINT64 CrDcr;
+ UINT64 CrItm;
+ UINT64 CrIva;
+ UINT64 CrPta;
+ UINT64 CrIpsr;
+ UINT64 CrIsr;
+ UINT64 CrIip;
+ UINT64 CrIfa;
+ UINT64 CrItir;
+ UINT64 CrIipa;
+ UINT64 CrIfs;
+ UINT64 CrIim;
+ UINT64 CrIha;
+
+ //
+ // debug registers
+ //
+ UINT64 Dbr0;
+ UINT64 Dbr1;
+ UINT64 Dbr2;
+ UINT64 Dbr3;
+ UINT64 Dbr4;
+ UINT64 Dbr5;
+ UINT64 Dbr6;
+ UINT64 Dbr7;
+
+ UINT64 Ibr0;
+ UINT64 Ibr1;
+ UINT64 Ibr2;
+ UINT64 Ibr3;
+ UINT64 Ibr4;
+ UINT64 Ibr5;
+ UINT64 Ibr6;
+ UINT64 Ibr7;
+
+ //
+ // virtual registers - nat bits for R1-R31
+ //
+ UINT64 IntNat;
+
+} EFI_SYSTEM_CONTEXT_IPF;
+
+///
+/// EBC processor exception types.
+///
+#define EXCEPT_EBC_UNDEFINED 0
+#define EXCEPT_EBC_DIVIDE_ERROR 1
+#define EXCEPT_EBC_DEBUG 2
+#define EXCEPT_EBC_BREAKPOINT 3
+#define EXCEPT_EBC_OVERFLOW 4
+#define EXCEPT_EBC_INVALID_OPCODE 5 ///< Opcode out of range.
+#define EXCEPT_EBC_STACK_FAULT 6
+#define EXCEPT_EBC_ALIGNMENT_CHECK 7
+#define EXCEPT_EBC_INSTRUCTION_ENCODING 8 ///< Malformed instruction.
+#define EXCEPT_EBC_BAD_BREAK 9 ///< BREAK 0 or undefined BREAK.
+#define EXCEPT_EBC_STEP 10 ///< To support debug stepping.
+///
+/// For coding convenience, define the maximum valid EBC exception.
+///
+#define MAX_EBC_EXCEPTION EXCEPT_EBC_STEP
+
+///
+/// EBC processor context definition.
+///
+typedef struct {
+ UINT64 R0;
+ UINT64 R1;
+ UINT64 R2;
+ UINT64 R3;
+ UINT64 R4;
+ UINT64 R5;
+ UINT64 R6;
+ UINT64 R7;
+ UINT64 Flags;
+ UINT64 ControlFlags;
+ UINT64 Ip;
+} EFI_SYSTEM_CONTEXT_EBC;
+
+
+
+///
+/// ARM processor exception types.
+///
+#define EXCEPT_ARM_RESET 0
+#define EXCEPT_ARM_UNDEFINED_INSTRUCTION 1
+#define EXCEPT_ARM_SOFTWARE_INTERRUPT 2
+#define EXCEPT_ARM_PREFETCH_ABORT 3
+#define EXCEPT_ARM_DATA_ABORT 4
+#define EXCEPT_ARM_RESERVED 5
+#define EXCEPT_ARM_IRQ 6
+#define EXCEPT_ARM_FIQ 7
+
+///
+/// For coding convenience, define the maximum valid ARM exception.
+///
+#define MAX_ARM_EXCEPTION EXCEPT_ARM_FIQ
+
+///
+/// ARM processor context definition.
+///
+typedef struct {
+ UINT32 R0;
+ UINT32 R1;
+ UINT32 R2;
+ UINT32 R3;
+ UINT32 R4;
+ UINT32 R5;
+ UINT32 R6;
+ UINT32 R7;
+ UINT32 R8;
+ UINT32 R9;
+ UINT32 R10;
+ UINT32 R11;
+ UINT32 R12;
+ UINT32 SP;
+ UINT32 LR;
+ UINT32 PC;
+ UINT32 CPSR;
+ UINT32 DFSR;
+ UINT32 DFAR;
+ UINT32 IFSR;
+ UINT32 IFAR;
+} EFI_SYSTEM_CONTEXT_ARM;
+
+///
+/// Universal EFI_SYSTEM_CONTEXT definition.
+///
+typedef union {
+ EFI_SYSTEM_CONTEXT_EBC *SystemContextEbc;
+ EFI_SYSTEM_CONTEXT_IA32 *SystemContextIa32;
+ EFI_SYSTEM_CONTEXT_X64 *SystemContextX64;
+ EFI_SYSTEM_CONTEXT_IPF *SystemContextIpf;
+ EFI_SYSTEM_CONTEXT_ARM *SystemContextArm;
+} EFI_SYSTEM_CONTEXT;
+
+//
+// DebugSupport callback function prototypes
+//
+
+/**
+ Registers and enables an exception callback function for the specified exception.
+
+ @param ExceptionType Exception types in EBC, IA-32, x64, or IPF.
+ @param SystemContext Exception content.
+
+**/
+typedef
+VOID
+(EFIAPI *EFI_EXCEPTION_CALLBACK)(
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+/**
+ Registers and enables the on-target debug agent's periodic entry point.
+
+ @param SystemContext Exception content.
+
+**/
+typedef
+VOID
+(EFIAPI *EFI_PERIODIC_CALLBACK)(
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+///
+/// Machine type definition
+///
+typedef enum {
+ IsaIa32 = IMAGE_FILE_MACHINE_I386, ///< 0x014C
+ IsaX64 = IMAGE_FILE_MACHINE_X64, ///< 0x8664
+ IsaIpf = IMAGE_FILE_MACHINE_IA64, ///< 0x0200
+ IsaEbc = IMAGE_FILE_MACHINE_EBC, ///< 0x0EBC
+ IsaArm = IMAGE_FILE_MACHINE_ARMTHUMB_MIXED ///< 0x01c2
+} EFI_INSTRUCTION_SET_ARCHITECTURE;
+
+
+//
+// DebugSupport member function definitions
+//
+
+/**
+ Returns the maximum value that may be used for the ProcessorIndex parameter in
+ RegisterPeriodicCallback() and RegisterExceptionCallback().
+
+ @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
+ @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the maximum supported
+ processor index is returned.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_MAXIMUM_PROCESSOR_INDEX)(
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ OUT UINTN *MaxProcessorIndex
+ );
+
+/**
+ Registers a function to be called back periodically in interrupt context.
+
+ @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
+ @param ProcessorIndex Specifies which processor the callback function applies to.
+ @param PeriodicCallback A pointer to a function of type PERIODIC_CALLBACK that is the main
+ periodic entry point of the debug agent.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback
+ function was previously registered.
+ @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback
+ function.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REGISTER_PERIODIC_CALLBACK)(
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ IN UINTN ProcessorIndex,
+ IN EFI_PERIODIC_CALLBACK PeriodicCallback
+ );
+
+/**
+ Registers a function to be called when a given processor exception occurs.
+
+ @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
+ @param ProcessorIndex Specifies which processor the callback function applies to.
+ @param ExceptionCallback A pointer to a function of type EXCEPTION_CALLBACK that is called
+ when the processor exception specified by ExceptionType occurs.
+ @param ExceptionType Specifies which processor exception to hook.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback
+ function was previously registered.
+ @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback
+ function.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REGISTER_EXCEPTION_CALLBACK)(
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ IN UINTN ProcessorIndex,
+ IN EFI_EXCEPTION_CALLBACK ExceptionCallback,
+ IN EFI_EXCEPTION_TYPE ExceptionType
+ );
+
+/**
+ Invalidates processor instruction cache for a memory range. Subsequent execution in this range
+ causes a fresh memory fetch to retrieve code to be executed.
+
+ @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
+ @param ProcessorIndex Specifies which processor's instruction cache is to be invalidated.
+ @param Start Specifies the physical base of the memory range to be invalidated.
+ @param Length Specifies the minimum number of bytes in the processor's instruction
+ cache to invalidate.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_INVALIDATE_INSTRUCTION_CACHE)(
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ IN UINTN ProcessorIndex,
+ IN VOID *Start,
+ IN UINT64 Length
+ );
+
+///
+/// This protocol provides the services to allow the debug agent to register
+/// callback functions that are called either periodically or when specific
+/// processor exceptions occur.
+///
+struct _EFI_DEBUG_SUPPORT_PROTOCOL {
+ ///
+ /// Declares the processor architecture for this instance of the EFI Debug Support protocol.
+ ///
+ EFI_INSTRUCTION_SET_ARCHITECTURE Isa;
+ EFI_GET_MAXIMUM_PROCESSOR_INDEX GetMaximumProcessorIndex;
+ EFI_REGISTER_PERIODIC_CALLBACK RegisterPeriodicCallback;
+ EFI_REGISTER_EXCEPTION_CALLBACK RegisterExceptionCallback;
+ EFI_INVALIDATE_INSTRUCTION_CACHE InvalidateInstructionCache;
+};
+
+extern EFI_GUID gEfiDebugSupportProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/DevicePath.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/DevicePath.h
new file mode 100644
index 00000000..5c678708
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/DevicePath.h
@@ -0,0 +1,1074 @@
+/** @file
+ The device path protocol as defined in UEFI 2.0.
+
+ The device path represents a programmatic path to a device,
+ from a software point of view. The path must persist from boot to boot, so
+ it can not contain things like PCI bus numbers that change from boot to boot.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_DEVICE_PATH_PROTOCOL_H__
+#define __EFI_DEVICE_PATH_PROTOCOL_H__
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/Guid/PcAnsi.h>
+
+///
+/// Device Path protocol.
+///
+#define EFI_DEVICE_PATH_PROTOCOL_GUID \
+ { \
+ 0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+ }
+
+///
+/// Device Path guid definition for backward-compatible with EFI1.1.
+///
+#define DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL_GUID
+
+#pragma pack(1)
+
+/**
+ This protocol can be used on any device handle to obtain generic path/location
+ information concerning the physical device or logical device. If the handle does
+ not logically map to a physical device, the handle may not necessarily support
+ the device path protocol. The device path describes the location of the device
+ the handle is for. The size of the Device Path can be determined from the structures
+ that make up the Device Path.
+**/
+typedef struct {
+ UINT8 Type; ///< 0x01 Hardware Device Path.
+ ///< 0x02 ACPI Device Path.
+ ///< 0x03 Messaging Device Path.
+ ///< 0x04 Media Device Path.
+ ///< 0x05 BIOS Boot Specification Device Path.
+ ///< 0x7F End of Hardware Device Path.
+
+ UINT8 SubType; ///< Varies by Type
+ ///< 0xFF End Entire Device Path, or
+ ///< 0x01 End This Instance of a Device Path and start a new
+ ///< Device Path.
+
+ UINT8 Length[2]; ///< Specific Device Path data. Type and Sub-Type define
+ ///< type of data. Size of data is included in Length.
+
+} EFI_DEVICE_PATH_PROTOCOL;
+
+///
+/// Device Path protocol definition for backward-compatible with EFI1.1.
+///
+typedef EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH;
+
+///
+/// Hardware Device Paths.
+///
+#define HARDWARE_DEVICE_PATH 0x01
+
+///
+/// PCI Device Path SubType.
+///
+#define HW_PCI_DP 0x01
+
+///
+/// PCI Device Path.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// PCI Function Number.
+ ///
+ UINT8 Function;
+ ///
+ /// PCI Device Number.
+ ///
+ UINT8 Device;
+} PCI_DEVICE_PATH;
+
+///
+/// PCCARD Device Path SubType.
+///
+#define HW_PCCARD_DP 0x02
+
+///
+/// PCCARD Device Path.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Function Number (0 = First Function).
+ ///
+ UINT8 FunctionNumber;
+} PCCARD_DEVICE_PATH;
+
+///
+/// Memory Mapped Device Path SubType.
+///
+#define HW_MEMMAP_DP 0x03
+
+///
+/// Memory Mapped Device Path.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// EFI_MEMORY_TYPE
+ ///
+ UINT32 MemoryType;
+ ///
+ /// Starting Memory Address.
+ ///
+ EFI_PHYSICAL_ADDRESS StartingAddress;
+ ///
+ /// Ending Memory Address.
+ ///
+ EFI_PHYSICAL_ADDRESS EndingAddress;
+} MEMMAP_DEVICE_PATH;
+
+///
+/// Hardware Vendor Device Path SubType.
+///
+#define HW_VENDOR_DP 0x04
+
+///
+/// The Vendor Device Path allows the creation of vendor-defined Device Paths. A vendor must
+/// allocate a Vendor GUID for a Device Path. The Vendor GUID can then be used to define the
+/// contents on the n bytes that follow in the Vendor Device Path node.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Vendor-assigned GUID that defines the data that follows.
+ ///
+ EFI_GUID Guid;
+ ///
+ /// Vendor-defined variable size data.
+ ///
+} VENDOR_DEVICE_PATH;
+
+///
+/// Controller Device Path SubType.
+///
+#define HW_CONTROLLER_DP 0x05
+
+///
+/// Controller Device Path.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Controller number.
+ ///
+ UINT32 ControllerNumber;
+} CONTROLLER_DEVICE_PATH;
+
+///
+/// ACPI Device Paths.
+///
+#define ACPI_DEVICE_PATH 0x02
+
+///
+/// ACPI Device Path SubType.
+///
+#define ACPI_DP 0x01
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Device's PnP hardware ID stored in a numeric 32-bit
+ /// compressed EISA-type ID. This value must match the
+ /// corresponding _HID in the ACPI name space.
+ ///
+ UINT32 HID;
+ ///
+ /// Unique ID that is required by ACPI if two devices have the
+ /// same _HID. This value must also match the corresponding
+ /// _UID/_HID pair in the ACPI name space. Only the 32-bit
+ /// numeric value type of _UID is supported. Thus, strings must
+ /// not be used for the _UID in the ACPI name space.
+ ///
+ UINT32 UID;
+} ACPI_HID_DEVICE_PATH;
+
+///
+/// Expanded ACPI Device Path SubType.
+///
+#define ACPI_EXTENDED_DP 0x02
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Device's PnP hardware ID stored in a numeric 32-bit
+ /// compressed EISA-type ID. This value must match the
+ /// corresponding _HID in the ACPI name space.
+ ///
+ UINT32 HID;
+ ///
+ /// Unique ID that is required by ACPI if two devices have the
+ /// same _HID. This value must also match the corresponding
+ /// _UID/_HID pair in the ACPI name space.
+ ///
+ UINT32 UID;
+ ///
+ /// Device's compatible PnP hardware ID stored in a numeric
+ /// 32-bit compressed EISA-type ID. This value must match at
+ /// least one of the compatible device IDs returned by the
+ /// corresponding _CID in the ACPI name space.
+ ///
+ UINT32 CID;
+ ///
+ /// Optional variable length _HIDSTR.
+ /// Optional variable length _UIDSTR.
+ /// Optional variable length _CIDSTR.
+ ///
+} ACPI_EXTENDED_HID_DEVICE_PATH;
+
+//
+// EISA ID Macro
+// EISA ID Definition 32-bits
+// bits[15:0] - three character compressed ASCII EISA ID.
+// bits[31:16] - binary number
+// Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z'
+//
+#define PNP_EISA_ID_CONST 0x41d0
+#define EISA_ID(_Name, _Num) ((UINT32)((_Name) | (_Num) << 16))
+#define EISA_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId)))
+#define EFI_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId)))
+
+#define PNP_EISA_ID_MASK 0xffff
+#define EISA_ID_TO_NUM(_Id) ((_Id) >> 16)
+
+///
+/// ACPI _ADR Device Path SubType.
+///
+#define ACPI_ADR_DP 0x03
+
+///
+/// The _ADR device path is used to contain video output device attributes to support the Graphics
+/// Output Protocol. The device path can contain multiple _ADR entries if multiple video output
+/// devices are displaying the same output.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// _ADR value. For video output devices the value of this
+ /// field comes from Table B-2 of the ACPI 3.0 specification. At
+ /// least one _ADR value is required.
+ ///
+ UINT32 ADR;
+ //
+ // This device path may optionally contain more than one _ADR entry.
+ //
+} ACPI_ADR_DEVICE_PATH;
+
+#define ACPI_ADR_DISPLAY_TYPE_OTHER 0
+#define ACPI_ADR_DISPLAY_TYPE_VGA 1
+#define ACPI_ADR_DISPLAY_TYPE_TV 2
+#define ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL 3
+#define ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL 4
+
+#define ACPI_DISPLAY_ADR(_DeviceIdScheme, _HeadId, _NonVgaOutput, _BiosCanDetect, _VendorInfo, _Type, _Port, _Index) \
+ ((UINT32)( (((_DeviceIdScheme) & 0x1) << 31) | \
+ (((_HeadId) & 0x7) << 18) | \
+ (((_NonVgaOutput) & 0x1) << 17) | \
+ (((_BiosCanDetect) & 0x1) << 16) | \
+ (((_VendorInfo) & 0xf) << 12) | \
+ (((_Type) & 0xf) << 8) | \
+ (((_Port) & 0xf) << 4) | \
+ ((_Index) & 0xf) ))
+
+///
+/// Messaging Device Paths.
+/// This Device Path is used to describe the connection of devices outside the resource domain of the
+/// system. This Device Path can describe physical messaging information like SCSI ID, or abstract
+/// information like networking protocol IP addresses.
+///
+#define MESSAGING_DEVICE_PATH 0x03
+
+///
+/// ATAPI Device Path SubType
+///
+#define MSG_ATAPI_DP 0x01
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Set to zero for primary, or one for secondary.
+ ///
+ UINT8 PrimarySecondary;
+ ///
+ /// Set to zero for master, or one for slave mode.
+ ///
+ UINT8 SlaveMaster;
+ ///
+ /// Logical Unit Number.
+ ///
+ UINT16 Lun;
+} ATAPI_DEVICE_PATH;
+
+///
+/// SCSI Device Path SubType.
+///
+#define MSG_SCSI_DP 0x02
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Target ID on the SCSI bus (PUN).
+ ///
+ UINT16 Pun;
+ ///
+ /// Logical Unit Number (LUN).
+ ///
+ UINT16 Lun;
+} SCSI_DEVICE_PATH;
+
+///
+/// Fibre Channel SubType.
+///
+#define MSG_FIBRECHANNEL_DP 0x03
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Reserved for the future.
+ ///
+ UINT32 Reserved;
+ ///
+ /// Fibre Channel World Wide Number.
+ ///
+ UINT64 WWN;
+ ///
+ /// Fibre Channel Logical Unit Number.
+ ///
+ UINT64 Lun;
+} FIBRECHANNEL_DEVICE_PATH;
+
+///
+/// 1394 Device Path SubType
+///
+#define MSG_1394_DP 0x04
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Reserved for the future.
+ ///
+ UINT32 Reserved;
+ ///
+ /// 1394 Global Unique ID (GUID).
+ ///
+ UINT64 Guid;
+} F1394_DEVICE_PATH;
+
+///
+/// USB Device Path SubType.
+///
+#define MSG_USB_DP 0x05
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// USB Parent Port Number.
+ ///
+ UINT8 ParentPortNumber;
+ ///
+ /// USB Interface Number.
+ ///
+ UINT8 InterfaceNumber;
+} USB_DEVICE_PATH;
+
+///
+/// USB Class Device Path SubType.
+///
+#define MSG_USB_CLASS_DP 0x0f
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Vendor ID assigned by USB-IF. A value of 0xFFFF will
+ /// match any Vendor ID.
+ ///
+ UINT16 VendorId;
+ ///
+ /// Product ID assigned by USB-IF. A value of 0xFFFF will
+ /// match any Product ID.
+ ///
+ UINT16 ProductId;
+ ///
+ /// The class code assigned by the USB-IF. A value of 0xFF
+ /// will match any class code.
+ ///
+ UINT8 DeviceClass;
+ ///
+ /// The subclass code assigned by the USB-IF. A value of
+ /// 0xFF will match any subclass code.
+ ///
+ UINT8 DeviceSubClass;
+ ///
+ /// The protocol code assigned by the USB-IF. A value of
+ /// 0xFF will match any protocol code.
+ ///
+ UINT8 DeviceProtocol;
+} USB_CLASS_DEVICE_PATH;
+
+///
+/// USB WWID Device Path SubType.
+///
+#define MSG_USB_WWID_DP 0x10
+
+///
+/// This device path describes a USB device using its serial number.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// USB interface number.
+ ///
+ UINT16 InterfaceNumber;
+ ///
+ /// USB vendor id of the device.
+ ///
+ UINT16 VendorId;
+ ///
+ /// USB product id of the device.
+ ///
+ UINT16 ProductId;
+ ///
+ /// Last 64-or-fewer UTF-16 characters of the USB
+ /// serial number. The length of the string is
+ /// determined by the Length field less the offset of the
+ /// Serial Number field (10)
+ ///
+ /// CHAR16 SerialNumber[...];
+} USB_WWID_DEVICE_PATH;
+
+///
+/// Device Logical Unit SubType.
+///
+#define MSG_DEVICE_LOGICAL_UNIT_DP 0x11
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Logical Unit Number for the interface.
+ ///
+ UINT8 Lun;
+} DEVICE_LOGICAL_UNIT_DEVICE_PATH;
+
+///
+/// SATA Device Path SubType.
+///
+#define MSG_SATA_DP 0x12
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// The HBA port number that facilitates the connection to the
+ /// device or a port multiplier. The value 0xFFFF is reserved.
+ ///
+ UINT16 HBAPortNumber;
+ ///
+ /// The Port multiplier port number that facilitates the connection
+ /// to the device. Bit 15 should be set if the device is directly
+ /// connected to the HBA.
+ ///
+ UINT16 PortMultiplierPortNumber;
+ ///
+ /// Logical Unit Number.
+ ///
+ UINT16 Lun;
+} SATA_DEVICE_PATH;
+
+///
+/// Flag for if the device is directly connected to the HBA.
+///
+#define SATA_HBA_DIRECT_CONNECT_FLAG 0x8000
+
+///
+/// I2O Device Path SubType.
+///
+#define MSG_I2O_DP 0x06
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Target ID (TID) for a device.
+ ///
+ UINT32 Tid;
+} I2O_DEVICE_PATH;
+
+///
+/// MAC Address Device Path SubType.
+///
+#define MSG_MAC_ADDR_DP 0x0b
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// The MAC address for a network interface padded with 0s.
+ ///
+ EFI_MAC_ADDRESS MacAddress;
+ ///
+ /// Network interface type(i.e. 802.3, FDDI).
+ ///
+ UINT8 IfType;
+} MAC_ADDR_DEVICE_PATH;
+
+///
+/// IPv4 Device Path SubType
+///
+#define MSG_IPv4_DP 0x0c
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// The local IPv4 address.
+ ///
+ EFI_IPv4_ADDRESS LocalIpAddress;
+ ///
+ /// The remote IPv4 address.
+ ///
+ EFI_IPv4_ADDRESS RemoteIpAddress;
+ ///
+ /// The local port number.
+ ///
+ UINT16 LocalPort;
+ ///
+ /// The remote port number.
+ ///
+ UINT16 RemotePort;
+ ///
+ /// The network protocol(i.e. UDP, TCP).
+ ///
+ UINT16 Protocol;
+ ///
+ /// 0x00 - The Source IP Address was assigned though DHCP.
+ /// 0x01 - The Source IP Address is statically bound.
+ ///
+ BOOLEAN StaticIpAddress;
+} IPv4_DEVICE_PATH;
+
+///
+/// IPv6 Device Path SubType.
+///
+#define MSG_IPv6_DP 0x0d
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// The local IPv6 address.
+ ///
+ EFI_IPv6_ADDRESS LocalIpAddress;
+ ///
+ /// The remote IPv6 address.
+ ///
+ EFI_IPv6_ADDRESS RemoteIpAddress;
+ ///
+ /// The local port number.
+ ///
+ UINT16 LocalPort;
+ ///
+ /// The remote port number.
+ ///
+ UINT16 RemotePort;
+ ///
+ /// The network protocol(i.e. UDP, TCP).
+ ///
+ UINT16 Protocol;
+ ///
+ /// 0x00 - The Source IP Address was assigned though DHCP.
+ /// 0x01 - The Source IP Address is statically bound.
+ ///
+ BOOLEAN StaticIpAddress;
+} IPv6_DEVICE_PATH;
+
+///
+/// InfiniBand Device Path SubType.
+///
+#define MSG_INFINIBAND_DP 0x09
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Flags to help identify/manage InfiniBand device path elements:
+ /// Bit 0 - IOC/Service (0b = IOC, 1b = Service).
+ /// Bit 1 - Extend Boot Environment.
+ /// Bit 2 - Console Protocol.
+ /// Bit 3 - Storage Protocol.
+ /// Bit 4 - Network Protocol.
+ /// All other bits are reserved.
+ ///
+ UINT32 ResourceFlags;
+ ///
+ /// 128-bit Global Identifier for remote fabric port.
+ ///
+ UINT8 PortGid[16];
+ ///
+ /// 64-bit unique identifier to remote IOC or server process.
+ /// Interpretation of field specified by Resource Flags (bit 0).
+ ///
+ UINT64 ServiceId;
+ ///
+ /// 64-bit persistent ID of remote IOC port.
+ ///
+ UINT64 TargetPortId;
+ ///
+ /// 64-bit persistent ID of remote device.
+ ///
+ UINT64 DeviceId;
+} INFINIBAND_DEVICE_PATH;
+
+#define INFINIBAND_RESOURCE_FLAG_IOC_SERVICE 0x01
+#define INFINIBAND_RESOURCE_FLAG_EXTENDED_BOOT_ENVIRONMENT 0x02
+#define INFINIBAND_RESOURCE_FLAG_CONSOLE_PROTOCOL 0x04
+#define INFINIBAND_RESOURCE_FLAG_STORAGE_PROTOCOL 0x08
+#define INFINIBAND_RESOURCE_FLAG_NETWORK_PROTOCOL 0x10
+
+///
+/// UART Device Path SubType.
+///
+#define MSG_UART_DP 0x0e
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Reserved.
+ ///
+ UINT32 Reserved;
+ ///
+ /// The baud rate setting for the UART style device. A value of 0
+ /// means that the device's default baud rate will be used.
+ ///
+ UINT64 BaudRate;
+ ///
+ /// The number of data bits for the UART style device. A value
+ /// of 0 means that the device's default number of data bits will be used.
+ ///
+ UINT8 DataBits;
+ ///
+ /// The parity setting for the UART style device.
+ /// Parity 0x00 - Default Parity.
+ /// Parity 0x01 - No Parity.
+ /// Parity 0x02 - Even Parity.
+ /// Parity 0x03 - Odd Parity.
+ /// Parity 0x04 - Mark Parity.
+ /// Parity 0x05 - Space Parity.
+ ///
+ UINT8 Parity;
+ ///
+ /// The number of stop bits for the UART style device.
+ /// Stop Bits 0x00 - Default Stop Bits.
+ /// Stop Bits 0x01 - 1 Stop Bit.
+ /// Stop Bits 0x02 - 1.5 Stop Bits.
+ /// Stop Bits 0x03 - 2 Stop Bits.
+ ///
+ UINT8 StopBits;
+} UART_DEVICE_PATH;
+
+//
+// Use VENDOR_DEVICE_PATH struct
+//
+#define MSG_VENDOR_DP 0x0a
+typedef VENDOR_DEVICE_PATH VENDOR_DEFINED_DEVICE_PATH;
+
+#define DEVICE_PATH_MESSAGING_PC_ANSI EFI_PC_ANSI_GUID
+#define DEVICE_PATH_MESSAGING_VT_100 EFI_VT_100_GUID
+#define DEVICE_PATH_MESSAGING_VT_100_PLUS EFI_VT_100_PLUS_GUID
+#define DEVICE_PATH_MESSAGING_VT_UTF8 EFI_VT_UTF8_GUID
+
+///
+/// A new device path node is defined to declare flow control characteristics.
+/// UART Flow Control Messaging Device Path
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL GUID.
+ ///
+ EFI_GUID Guid;
+ ///
+ /// Bitmap of supported flow control types.
+ /// Bit 0 set indicates hardware flow control.
+ /// Bit 1 set indicates Xon/Xoff flow control.
+ /// All other bits are reserved and are clear.
+ ///
+ UINT32 FlowControlMap;
+} UART_FLOW_CONTROL_DEVICE_PATH;
+
+#define UART_FLOW_CONTROL_HARDWARE 0x00000001
+#define UART_FLOW_CONTROL_XON_XOFF 0x00000010
+
+#define DEVICE_PATH_MESSAGING_SAS EFI_SAS_DEVICE_PATH_GUID
+///
+/// Serial Attached SCSI (SAS) devices.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// DEVICE_PATH_MESSAGING_SAS GUID.
+ ///
+ EFI_GUID Guid;
+ ///
+ /// Reserved for future use.
+ ///
+ UINT32 Reserved;
+ ///
+ /// SAS Address for Serial Attached SCSI Target.
+ ///
+ UINT64 SasAddress;
+ ///
+ /// SAS Logical Unit Number.
+ ///
+ UINT64 Lun;
+ ///
+ /// More Information about the device and its interconnect.
+ ///
+ UINT16 DeviceTopology;
+ ///
+ /// Relative Target Port (RTP).
+ ///
+ UINT16 RelativeTargetPort;
+} SAS_DEVICE_PATH;
+
+///
+/// iSCSI Device Path SubType
+///
+#define MSG_ISCSI_DP 0x13
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Network Protocol (0 = TCP, 1+ = reserved).
+ ///
+ UINT16 NetworkProtocol;
+ ///
+ /// iSCSI Login Options.
+ ///
+ UINT16 LoginOption;
+ ///
+ /// iSCSI Logical Unit Number.
+ ///
+ UINT64 Lun;
+ ///
+ /// iSCSI Target Portal group tag the initiator intends
+ /// to establish a session with.
+ ///
+ UINT16 TargetPortalGroupTag;
+ ///
+ /// iSCSI NodeTarget Name. The length of the name
+ /// is determined by subtracting the offset of this field from Length.
+ ///
+ /// CHAR8 iSCSI Target Name.
+} ISCSI_DEVICE_PATH;
+
+#define ISCSI_LOGIN_OPTION_NO_HEADER_DIGEST 0x0000
+#define ISCSI_LOGIN_OPTION_HEADER_DIGEST_USING_CRC32C 0x0002
+#define ISCSI_LOGIN_OPTION_NO_DATA_DIGEST 0x0000
+#define ISCSI_LOGIN_OPTION_DATA_DIGEST_USING_CRC32C 0x0008
+#define ISCSI_LOGIN_OPTION_AUTHMETHOD_CHAP 0x0000
+#define ISCSI_LOGIN_OPTION_AUTHMETHOD_NON 0x1000
+#define ISCSI_LOGIN_OPTION_CHAP_BI 0x0000
+#define ISCSI_LOGIN_OPTION_CHAP_UNI 0x2000
+
+///
+/// VLAN Device Path SubType.
+///
+#define MSG_VLAN_DP 0x14
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// VLAN identifier (0-4094).
+ ///
+ UINT16 VlanId;
+} VLAN_DEVICE_PATH;
+
+//
+// Media Device Path
+//
+#define MEDIA_DEVICE_PATH 0x04
+
+///
+/// Hard Drive Media Device Path SubType.
+///
+#define MEDIA_HARDDRIVE_DP 0x01
+
+///
+/// The Hard Drive Media Device Path is used to represent a partition on a hard drive.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Describes the entry in a partition table, starting with entry 1.
+ /// Partition number zero represents the entire device. Valid
+ /// partition numbers for a MBR partition are [1, 4]. Valid
+ /// partition numbers for a GPT partition are [1, NumberOfPartitionEntries].
+ ///
+ UINT32 PartitionNumber;
+ ///
+ /// Starting LBA of the partition on the hard drive.
+ ///
+ UINT64 PartitionStart;
+ ///
+ /// Size of the partition in units of Logical Blocks.
+ ///
+ UINT64 PartitionSize;
+ ///
+ /// Signature unique to this partition:
+ /// If SignatureType is 0, this field has to be initialized with 16 zeros.
+ /// If SignatureType is 1, the MBR signature is stored in the first 4 bytes of this field.
+ /// The other 12 bytes are initialized with zeros.
+ /// If SignatureType is 2, this field contains a 16 byte signature.
+ ///
+ UINT8 Signature[16];
+ ///
+ /// Partition Format: (Unused values reserved).
+ /// 0x01 - PC-AT compatible legacy MBR.
+ /// 0x02 - GUID Partition Table.
+ ///
+ UINT8 MBRType;
+ ///
+ /// Type of Disk Signature: (Unused values reserved).
+ /// 0x00 - No Disk Signature.
+ /// 0x01 - 32-bit signature from address 0x1b8 of the type 0x01 MBR.
+ /// 0x02 - GUID signature.
+ ///
+ UINT8 SignatureType;
+} HARDDRIVE_DEVICE_PATH;
+
+#define MBR_TYPE_PCAT 0x01
+#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
+
+#define NO_DISK_SIGNATURE 0x00
+#define SIGNATURE_TYPE_MBR 0x01
+#define SIGNATURE_TYPE_GUID 0x02
+
+///
+/// CD-ROM Media Device Path SubType.
+///
+#define MEDIA_CDROM_DP 0x02
+
+///
+/// The CD-ROM Media Device Path is used to define a system partition that exists on a CD-ROM.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Boot Entry number from the Boot Catalog. The Initial/Default entry is defined as zero.
+ ///
+ UINT32 BootEntry;
+ ///
+ /// Starting RBA of the partition on the medium. CD-ROMs use Relative logical Block Addressing.
+ ///
+ UINT64 PartitionStart;
+ ///
+ /// Size of the partition in units of Blocks, also called Sectors.
+ ///
+ UINT64 PartitionSize;
+} CDROM_DEVICE_PATH;
+
+//
+// Use VENDOR_DEVICE_PATH struct
+//
+#define MEDIA_VENDOR_DP 0x03 ///< Media vendor device path subtype.
+
+///
+/// File Path Media Device Path SubType
+///
+#define MEDIA_FILEPATH_DP 0x04
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// A NULL-terminated Path string including directory and file names.
+ ///
+ CHAR16 PathName[1];
+} FILEPATH_DEVICE_PATH;
+
+#define SIZE_OF_FILEPATH_DEVICE_PATH OFFSET_OF(FILEPATH_DEVICE_PATH,PathName)
+
+///
+/// Media Protocol Device Path SubType.
+///
+#define MEDIA_PROTOCOL_DP 0x05
+
+///
+/// The Media Protocol Device Path is used to denote the protocol that is being
+/// used in a device path at the location of the path specified.
+/// Many protocols are inherent to the style of device path.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// The ID of the protocol.
+ ///
+ EFI_GUID Protocol;
+} MEDIA_PROTOCOL_DEVICE_PATH;
+
+///
+/// PIWG Firmware Volume Device Path SubType.
+///
+#define MEDIA_PIWG_FW_FILE_DP 0x06
+
+///
+/// This device path is used by systems implementing the UEFI PI Specification 1.0 to describe a firmware file.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Firmware file name
+ ///
+ EFI_GUID FvFileName;
+} MEDIA_FW_VOL_FILEPATH_DEVICE_PATH;
+
+///
+/// PIWG Firmware Volume Device Path SubType.
+///
+#define MEDIA_PIWG_FW_VOL_DP 0x07
+
+///
+/// This device path is used by systems implementing the UEFI PI Specification 1.0 to describe a firmware volume.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Firmware volume name.
+ ///
+ EFI_GUID FvName;
+} MEDIA_FW_VOL_DEVICE_PATH;
+
+///
+/// Media relative offset range device path.
+///
+#define MEDIA_RELATIVE_OFFSET_RANGE_DP 0x08
+
+///
+/// Used to describe the offset range of media relative.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ UINT32 Reserved;
+ UINT64 StartingOffset;
+ UINT64 EndingOffset;
+} MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH;
+
+///
+/// BIOS Boot Specification Device Path.
+///
+#define BBS_DEVICE_PATH 0x05
+
+///
+/// BIOS Boot Specification Device Path SubType.
+///
+#define BBS_BBS_DP 0x01
+
+///
+/// This Device Path is used to describe the booting of non-EFI-aware operating systems.
+///
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Device Type as defined by the BIOS Boot Specification.
+ ///
+ UINT16 DeviceType;
+ ///
+ /// Status Flags as defined by the BIOS Boot Specification.
+ ///
+ UINT16 StatusFlag;
+ ///
+ /// ASCIIZ string that describes the boot device to a user.
+ ///
+ CHAR8 String[1];
+} BBS_BBS_DEVICE_PATH;
+
+//
+// DeviceType definitions - from BBS specification
+//
+#define BBS_TYPE_FLOPPY 0x01
+#define BBS_TYPE_HARDDRIVE 0x02
+#define BBS_TYPE_CDROM 0x03
+#define BBS_TYPE_PCMCIA 0x04
+#define BBS_TYPE_USB 0x05
+#define BBS_TYPE_EMBEDDED_NETWORK 0x06
+#define BBS_TYPE_BEV 0x80
+#define BBS_TYPE_UNKNOWN 0xFF
+
+
+///
+/// Union of all possible Device Paths and pointers to Device Paths.
+///
+typedef union {
+ EFI_DEVICE_PATH_PROTOCOL DevPath;
+ PCI_DEVICE_PATH Pci;
+ PCCARD_DEVICE_PATH PcCard;
+ MEMMAP_DEVICE_PATH MemMap;
+ VENDOR_DEVICE_PATH Vendor;
+
+ CONTROLLER_DEVICE_PATH Controller;
+ ACPI_HID_DEVICE_PATH Acpi;
+
+ ATAPI_DEVICE_PATH Atapi;
+ SCSI_DEVICE_PATH Scsi;
+ ISCSI_DEVICE_PATH Iscsi;
+ FIBRECHANNEL_DEVICE_PATH FibreChannel;
+
+ F1394_DEVICE_PATH F1394;
+ USB_DEVICE_PATH Usb;
+ SATA_DEVICE_PATH Sata;
+ USB_CLASS_DEVICE_PATH UsbClass;
+ I2O_DEVICE_PATH I2O;
+ MAC_ADDR_DEVICE_PATH MacAddr;
+ IPv4_DEVICE_PATH Ipv4;
+ IPv6_DEVICE_PATH Ipv6;
+ INFINIBAND_DEVICE_PATH InfiniBand;
+ UART_DEVICE_PATH Uart;
+
+ HARDDRIVE_DEVICE_PATH HardDrive;
+ CDROM_DEVICE_PATH CD;
+
+ FILEPATH_DEVICE_PATH FilePath;
+ MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol;
+ MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH Offset;
+
+ BBS_BBS_DEVICE_PATH Bbs;
+} EFI_DEV_PATH;
+
+
+
+typedef union {
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ PCI_DEVICE_PATH *Pci;
+ PCCARD_DEVICE_PATH *PcCard;
+ MEMMAP_DEVICE_PATH *MemMap;
+ VENDOR_DEVICE_PATH *Vendor;
+
+ CONTROLLER_DEVICE_PATH *Controller;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ ACPI_EXTENDED_HID_DEVICE_PATH *ExtendedAcpi;
+
+ ATAPI_DEVICE_PATH *Atapi;
+ SCSI_DEVICE_PATH *Scsi;
+ FIBRECHANNEL_DEVICE_PATH *FibreChannel;
+
+ F1394_DEVICE_PATH *F1394;
+ USB_DEVICE_PATH *Usb;
+ SATA_DEVICE_PATH *Sata;
+ USB_CLASS_DEVICE_PATH *UsbClass;
+ I2O_DEVICE_PATH *I2O;
+ MAC_ADDR_DEVICE_PATH *MacAddr;
+ IPv4_DEVICE_PATH *Ipv4;
+ IPv6_DEVICE_PATH *Ipv6;
+ INFINIBAND_DEVICE_PATH *InfiniBand;
+ UART_DEVICE_PATH *Uart;
+
+ HARDDRIVE_DEVICE_PATH *HardDrive;
+ CDROM_DEVICE_PATH *CD;
+
+ FILEPATH_DEVICE_PATH *FilePath;
+ MEDIA_PROTOCOL_DEVICE_PATH *MediaProtocol;
+ MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset;
+
+ BBS_BBS_DEVICE_PATH *Bbs;
+ UINT8 *Raw;
+} EFI_DEV_PATH_PTR;
+
+#pragma pack()
+
+#define END_DEVICE_PATH_TYPE 0x7f
+#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xFF
+#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01
+
+extern EFI_GUID gEfiDevicePathProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/DriverBinding.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/DriverBinding.h
new file mode 100644
index 00000000..1f464a73
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/DriverBinding.h
@@ -0,0 +1,203 @@
+/** @file
+ UEFI DriverBinding Protocol is defined in UEFI specification.
+
+ This protocol is produced by every driver that follows the UEFI Driver Model,
+ and it is the central component that allows drivers and controllers to be managed.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_DRIVER_BINDING_H__
+#define __EFI_DRIVER_BINDING_H__
+
+FILE_LICENCE ( BSD3 );
+
+///
+/// The global ID for the ControllerHandle Driver Protocol.
+///
+#define EFI_DRIVER_BINDING_PROTOCOL_GUID \
+ { \
+ 0x18a031ab, 0xb443, 0x4d1a, {0xa5, 0xc0, 0xc, 0x9, 0x26, 0x1e, 0x9f, 0x71 } \
+ }
+
+typedef struct _EFI_DRIVER_BINDING_PROTOCOL EFI_DRIVER_BINDING_PROTOCOL;
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DRIVER_BINDING_SUPPORTED)(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DRIVER_BINDING_START)(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DRIVER_BINDING_STOP)(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ );
+
+///
+/// This protocol provides the services required to determine if a driver supports a given controller.
+/// If a controller is supported, then it also provides routines to start and stop the controller.
+///
+struct _EFI_DRIVER_BINDING_PROTOCOL {
+ EFI_DRIVER_BINDING_SUPPORTED Supported;
+ EFI_DRIVER_BINDING_START Start;
+ EFI_DRIVER_BINDING_STOP Stop;
+
+ ///
+ /// The version number of the UEFI driver that produced the
+ /// EFI_DRIVER_BINDING_PROTOCOL. This field is used by
+ /// the EFI boot service ConnectController() to determine
+ /// the order that driver's Supported() service will be used when
+ /// a controller needs to be started. EFI Driver Binding Protocol
+ /// instances with higher Version values will be used before ones
+ /// with lower Version values. The Version values of 0x0-
+ /// 0x0f and 0xfffffff0-0xffffffff are reserved for
+ /// platform/OEM specific drivers. The Version values of 0x10-
+ /// 0xffffffef are reserved for IHV-developed drivers.
+ ///
+ UINT32 Version;
+
+ ///
+ /// The image handle of the UEFI driver that produced this instance
+ /// of the EFI_DRIVER_BINDING_PROTOCOL.
+ ///
+ EFI_HANDLE ImageHandle;
+
+ ///
+ /// The handle on which this instance of the
+ /// EFI_DRIVER_BINDING_PROTOCOL is installed. In most
+ /// cases, this is the same handle as ImageHandle. However, for
+ /// UEFI drivers that produce more than one instance of the
+ /// EFI_DRIVER_BINDING_PROTOCOL, this value may not be
+ /// the same as ImageHandle.
+ ///
+ EFI_HANDLE DriverBindingHandle;
+};
+
+extern EFI_GUID gEfiDriverBindingProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/FormBrowser2.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/FormBrowser2.h
new file mode 100644
index 00000000..7e98430f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/FormBrowser2.h
@@ -0,0 +1,177 @@
+/** @file
+ This protocol is defined in UEFI spec.
+
+ The EFI_FORM_BROWSER2_PROTOCOL is the interface to call for drivers to
+ leverage the EFI configuration driver interface.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_FORM_BROWSER2_H__
+#define __EFI_FORM_BROWSER2_H__
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/Guid/HiiPlatformSetupFormset.h>
+
+#define EFI_FORM_BROWSER2_PROTOCOL_GUID \
+ {0xb9d4c360, 0xbcfb, 0x4f9b, {0x92, 0x98, 0x53, 0xc1, 0x36, 0x98, 0x22, 0x58 }}
+
+
+typedef struct _EFI_FORM_BROWSER2_PROTOCOL EFI_FORM_BROWSER2_PROTOCOL;
+
+
+
+/**
+
+ @param LeftColumn The value that designates the text column
+ where the browser window will begin from
+ the left-hand side of the screen
+
+ @param RightColumn The value that designates the text
+ column where the browser window will end
+ on the right-hand side of the screen.
+
+ @param TopRow The value that designates the text row from the
+ top of the screen where the browser window
+ will start.
+
+ @param BottomRow The value that designates the text row from the
+ bottom of the screen where the browser
+ window will end.
+**/
+typedef struct {
+ UINTN LeftColumn;
+ UINTN RightColumn;
+ UINTN TopRow;
+ UINTN BottomRow;
+} EFI_SCREEN_DESCRIPTOR;
+
+typedef UINTN EFI_BROWSER_ACTION_REQUEST;
+
+#define EFI_BROWSER_ACTION_REQUEST_NONE 0
+#define EFI_BROWSER_ACTION_REQUEST_RESET 1
+#define EFI_BROWSER_ACTION_REQUEST_SUBMIT 2
+#define EFI_BROWSER_ACTION_REQUEST_EXIT 3
+
+
+/**
+ Initialize the browser to display the specified configuration forms.
+
+ This function is the primary interface to the internal forms-based browser.
+ The forms browser will display forms associated with the specified Handles.
+ The browser will select all forms in packages which have the specified Type
+ and (for EFI_HII_PACKAGE_TYPE_GUID) the specified PackageGuid.
+
+ @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL instance
+
+ @param Handles A pointer to an array of Handles. This value should correspond
+ to the value of the HII form package that is required to be displayed.
+
+ @param HandleCount The number of Handles specified in Handle.
+
+ @param FormSetGuid This field points to the EFI_GUID which must match the Guid field or one of the
+ elements of the ClassId field in the EFI_IFR_FORM_SET op-code. If
+ FormsetGuid is NULL, then this function will display the form set class
+ EFI_HII_PLATFORM_SETUP_FORMSET_GUID.
+
+ @param FormId This field specifies the identifier of the form within the form set to render as the first
+ displayable page. If this field has a value of 0x0000, then the Forms Browser will
+ render the first enabled form in the form set.
+
+ @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
+ characters.
+
+ @param ActionRequest Points to the action recommended by the form.
+
+ @retval EFI_SUCCESS The function completed successfully
+
+ @retval EFI_NOT_FOUND The variable was not found.
+
+ @retval EFI_INVALID_PARAMETER One of the parameters has an
+ invalid value.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SEND_FORM2)(
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
+ IN EFI_HII_HANDLE *Handle,
+ IN UINTN HandleCount,
+ IN EFI_GUID *FormSetGuid, OPTIONAL
+ IN EFI_FORM_ID FormId, OPTIONAL
+ IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL
+);
+
+
+/**
+ This function is called by a callback handler to retrieve uncommitted state data from the browser.
+
+ This routine is called by a routine which was called by the
+ browser. This routine called this service in the browser to
+ retrieve or set certain uncommitted state information.
+
+ @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL instance.
+
+ @param ResultsDataSize A pointer to the size of the buffer
+ associated with ResultsData. On input, the size in
+ bytes of ResultsData. On output, the size of data
+ returned in ResultsData.
+
+ @param ResultsData A string returned from an IFR browser or
+ equivalent. The results string will have
+ no routing information in them.
+
+ @param RetrieveData A BOOLEAN field which allows an agent to
+ retrieve (if RetrieveData = TRUE) data
+ from the uncommitted browser state
+ information or set (if RetrieveData =
+ FALSE) data in the uncommitted browser
+ state information.
+
+ @param VariableGuid An optional field to indicate the target
+ variable GUID name to use.
+
+ @param VariableName An optional field to indicate the target
+ human-readable variable name.
+
+ @retval EFI_SUCCESS The results have been distributed or are
+ awaiting distribution.
+
+ @retval EFI_OUT_OF_RESOURCES The ResultsDataSize specified
+ was too small to contain the
+ results data.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_BROWSER_CALLBACK2)(
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
+ IN OUT UINTN *ResultsDataSize,
+ IN OUT EFI_STRING ResultsData,
+ IN CONST BOOLEAN RetrieveData,
+ IN CONST EFI_GUID *VariableGuid, OPTIONAL
+ IN CONST CHAR16 *VariableName OPTIONAL
+);
+
+///
+/// This interface will allow the caller to direct the configuration
+/// driver to use either the HII database or use the passed-in packet of data.
+///
+struct _EFI_FORM_BROWSER2_PROTOCOL {
+ EFI_SEND_FORM2 SendForm;
+ EFI_BROWSER_CALLBACK2 BrowserCallback;
+} ;
+
+extern EFI_GUID gEfiFormBrowser2ProtocolGuid;
+
+#endif
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/HiiConfigAccess.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/HiiConfigAccess.h
new file mode 100644
index 00000000..2bef5cbc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/HiiConfigAccess.h
@@ -0,0 +1,221 @@
+/** @file
+
+ The EFI HII results processing protocol invokes this type of protocol
+ when it needs to forward results to a driver's configuration handler.
+ This protocol is published by drivers providing and requesting
+ configuration data from HII. It may only be invoked by HII.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __EFI_HII_CONFIG_ACCESS_H__
+#define __EFI_HII_CONFIG_ACCESS_H__
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/Protocol/FormBrowser2.h>
+
+#define EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID \
+ { 0x330d4706, 0xf2a0, 0x4e4f, { 0xa3, 0x69, 0xb6, 0x6f, 0xa8, 0xd5, 0x43, 0x85 } }
+
+typedef struct _EFI_HII_CONFIG_ACCESS_PROTOCOL EFI_HII_CONFIG_ACCESS_PROTOCOL;
+
+typedef UINTN EFI_BROWSER_ACTION;
+
+#define EFI_BROWSER_ACTION_CHANGING 0
+#define EFI_BROWSER_ACTION_CHANGED 1
+#define EFI_BROWSER_ACTION_RETRIEVE 2
+#define EFI_BROWSER_ACTION_FORM_OPEN 3
+#define EFI_BROWSER_ACTION_FORM_CLOSE 4
+
+/**
+
+ This function allows the caller to request the current
+ configuration for one or more named elements. The resulting
+ string is in <ConfigAltResp> format. Any and all alternative
+ configuration strings shall also be appended to the end of the
+ current configuration string. If they are, they must appear
+ after the current configuration. They must contain the same
+ routing (GUID, NAME, PATH) as the current configuration string.
+ They must have an additional description indicating the type of
+ alternative configuration the string represents,
+ "ALTCFG=<StringToken>". That <StringToken> (when
+ converted from Hex UNICODE to binary) is a reference to a
+ string in the associated string pack.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+ @param Request A null-terminated Unicode string in
+ <ConfigRequest> format. Note that this
+ includes the routing information as well as
+ the configurable name / value pairs. It is
+ invalid for this string to be in
+ <MultiConfigRequest> format.
+ If a NULL is passed in for the Request field,
+ all of the settings being abstracted by this function
+ will be returned in the Results field. In addition,
+ if a ConfigHdr is passed in with no request elements,
+ all of the settings being abstracted for that particular
+ ConfigHdr reference will be returned in the Results Field.
+
+ @param Progress On return, points to a character in the
+ Request string. Points to the string's null
+ terminator if request was successful. Points
+ to the most recent "&" before the first
+ failing name / value pair (or the beginning
+ of the string if the failure is in the first
+ name / value pair) if the request was not
+ successful.
+
+ @param Results A null-terminated Unicode string in
+ <MultiConfigAltResp> format which has all values
+ filled in for the names in the Request string.
+ String to be allocated by the called function.
+
+ @retval EFI_SUCCESS The Results string is filled with the
+ values corresponding to all requested
+ names.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
+ parts of the results that must be
+ stored awaiting possible future
+ protocols.
+
+ @retval EFI_NOT_FOUND Routing data doesn't match any
+ known driver. Progress set to the
+ first character in the routing header.
+ Note: There is no requirement that the
+ driver validate the routing data. It
+ must skip the <ConfigHdr> in order to
+ process the names.
+
+ @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
+ to most recent "&" before the
+ error or the beginning of the
+ string.
+
+ @retval EFI_INVALID_PARAMETER Unknown name. Progress points
+ to the & before the name in
+ question.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI * EFI_HII_ACCESS_EXTRACT_CONFIG)(
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+);
+
+
+/**
+
+ This function applies changes in a driver's configuration.
+ Input is a Configuration, which has the routing data for this
+ driver followed by name / value configuration pairs. The driver
+ must apply those pairs to its configurable storage. If the
+ driver's configuration is stored in a linear block of data
+ and the driver's name / value pairs are in <BlockConfig>
+ format, it may use the ConfigToBlock helper function (above) to
+ simplify the job.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+ @param Configuration A null-terminated Unicode string in
+ <ConfigString> format.
+
+ @param Progress A pointer to a string filled in with the
+ offset of the most recent '&' before the
+ first failing name / value pair (or the
+ beginn ing of the string if the failure
+ is in the first name / value pair) or
+ the terminating NULL if all was
+ successful.
+
+ @retval EFI_SUCCESS The results have been distributed or are
+ awaiting distribution.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
+ parts of the results that must be
+ stored awaiting possible future
+ protocols.
+
+ @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
+ Results parameter would result
+ in this type of error.
+
+ @retval EFI_NOT_FOUND Target for the specified routing data
+ was not found
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI * EFI_HII_ACCESS_ROUTE_CONFIG)(
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+);
+
+/**
+
+ This function is called to provide results data to the driver.
+ This data consists of a unique key that is used to identify
+ which data is either being passed back or being asked for.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Action Specifies the type of action taken by the browser.
+ @param QuestionId A unique value which is sent to the original
+ exporting driver so that it can identify the type
+ of data to expect. The format of the data tends to
+ vary based on the opcode that generated the callback.
+ @param Type The type of value for the question.
+ @param Value A pointer to the data being sent to the original
+ exporting driver.
+ @param ActionRequest On return, points to the action requested by the
+ callback function.
+
+ @retval EFI_SUCCESS The callback successfully handled the action.
+ @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
+ variable and its data.
+ @retval EFI_DEVICE_ERROR The variable could not be saved.
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the
+ callback.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_ACCESS_FORM_CALLBACK)(
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN OUT EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+ ;
+
+///
+/// This protocol provides a callable interface between the HII and
+/// drivers. Only drivers which provide IFR data to HII are required
+/// to publish this protocol.
+///
+struct _EFI_HII_CONFIG_ACCESS_PROTOCOL {
+ EFI_HII_ACCESS_EXTRACT_CONFIG ExtractConfig;
+ EFI_HII_ACCESS_ROUTE_CONFIG RouteConfig;
+ EFI_HII_ACCESS_FORM_CALLBACK Callback;
+} ;
+
+extern EFI_GUID gEfiHiiConfigAccessProtocolGuid;
+
+#endif
+
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/HiiDatabase.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/HiiDatabase.h
new file mode 100644
index 00000000..411ca2c0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/HiiDatabase.h
@@ -0,0 +1,519 @@
+/** @file
+ The file provides Database manager for HII-related data
+ structures.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __HII_DATABASE_H__
+#define __HII_DATABASE_H__
+
+FILE_LICENCE ( BSD3 );
+
+#define EFI_HII_DATABASE_PROTOCOL_GUID \
+ { 0xef9fc172, 0xa1b2, 0x4693, { 0xb3, 0x27, 0x6d, 0x32, 0xfc, 0x41, 0x60, 0x42 } }
+
+
+typedef struct _EFI_HII_DATABASE_PROTOCOL EFI_HII_DATABASE_PROTOCOL;
+
+
+///
+/// EFI_HII_DATABASE_NOTIFY_TYPE.
+///
+typedef UINTN EFI_HII_DATABASE_NOTIFY_TYPE;
+
+#define EFI_HII_DATABASE_NOTIFY_NEW_PACK 0x00000001
+#define EFI_HII_DATABASE_NOTIFY_REMOVE_PACK 0x00000002
+#define EFI_HII_DATABASE_NOTIFY_EXPORT_PACK 0x00000004
+#define EFI_HII_DATABASE_NOTIFY_ADD_PACK 0x00000008
+/**
+
+ Functions which are registered to receive notification of
+ database events have this prototype. The actual event is encoded
+ in NotifyType. The following table describes how PackageType,
+ PackageGuid, Handle, and Package are used for each of the
+ notification types.
+
+ @param PackageType Package type of the notification.
+
+ @param PackageGuid If PackageType is
+ EFI_HII_PACKAGE_TYPE_GUID, then this is
+ the pointer to the GUID from the Guid
+ field of EFI_HII_PACKAGE_GUID_HEADER.
+ Otherwise, it must be NULL.
+
+ @param Package Points to the package referred to by the notification.
+
+ @param Handle The handle of the package
+ list which contains the specified package.
+
+ @param NotifyType The type of change concerning the
+ database. See
+ EFI_HII_DATABASE_NOTIFY_TYPE.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_DATABASE_NOTIFY)(
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN CONST EFI_HII_PACKAGE_HEADER *Package,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
+);
+
+/**
+
+ This function adds the packages in the package list to the
+ database and returns a handle. If there is a
+ EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then
+ this function will create a package of type
+ EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list. For
+ each package in the package list, registered functions with the
+ notification type NEW_PACK and having the same package type will
+ be called. For each call to NewPackageList(), there should be a
+ corresponding call to
+ EFI_HII_DATABASE_PROTOCOL.RemovePackageList().
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
+
+ @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER structure.
+
+ @param DriverHandle Associate the package list with this EFI handle.
+ If a NULL is specified, this data will not be associate
+ with any drivers and cannot have a callback induced.
+
+ @param Handle A pointer to the EFI_HII_HANDLE instance.
+
+ @retval EFI_SUCCESS The package list associated with the
+ Handle was added to the HII database.
+
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary
+ resources for the new database
+ contents.
+
+ @retval EFI_INVALID_PARAMETER PackageList is NULL, or Handle is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_DATABASE_NEW_PACK)(
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
+ IN EFI_HANDLE DriverHandle, OPTIONAL
+ OUT EFI_HII_HANDLE *Handle
+);
+
+
+/**
+
+ This function removes the package list that is associated with a
+ handle Handle from the HII database. Before removing the
+ package, any registered functions with the notification type
+ REMOVE_PACK and the same package type will be called. For each
+ call to EFI_HII_DATABASE_PROTOCOL.NewPackageList(), there should
+ be a corresponding call to RemovePackageList.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
+
+ @param Handle The handle that was registered to the data
+ that is requested for removal.
+
+ @retval EFI_SUCCESS The data associated with the Handle was
+ removed from the HII database.
+ @retval EFI_NOT_FOUND The specified Handle is not in database.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_DATABASE_REMOVE_PACK)(
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle
+);
+
+
+/**
+
+ This function updates the existing package list (which has the
+ specified Handle) in the HII databases, using the new package
+ list specified by PackageList. The update process has the
+ following steps: Collect all the package types in the package
+ list specified by PackageList. A package type consists of the
+ Type field of EFI_HII_PACKAGE_HEADER and, if the Type is
+ EFI_HII_PACKAGE_TYPE_GUID, the Guid field, as defined in
+ EFI_HII_PACKAGE_GUID_HEADER. Iterate through the packages within
+ the existing package list in the HII database specified by
+ Handle. If a package's type matches one of the collected types collected
+ in step 1, then perform the following steps:
+ - Call any functions registered with the notification type
+ REMOVE_PACK.
+ - Remove the package from the package list and the HII
+ database.
+ Add all of the packages within the new package list specified
+ by PackageList, using the following steps:
+ - Add the package to the package list and the HII database.
+ - Call any functions registered with the notification type
+ ADD_PACK.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
+
+ @param Handle The handle that was registered to the data
+ that is requested for removal.
+
+ @param PackageList A pointer to an EFI_HII_PACKAGE_LIST
+ package.
+
+ @retval EFI_SUCCESS The HII database was successfully updated.
+
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate enough memory
+ for the updated database.
+
+ @retval EFI_INVALID_PARAMETER PackageList was NULL.
+ @retval EFI_NOT_FOUND The specified Handle is not in database.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_DATABASE_UPDATE_PACK)(
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList
+);
+
+
+/**
+
+ This function returns a list of the package handles of the
+ specified type that are currently active in the database. The
+ pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package
+ handles to be listed.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
+
+ @param PackageType Specifies the package type of the packages
+ to list or EFI_HII_PACKAGE_TYPE_ALL for
+ all packages to be listed.
+
+ @param PackageGuid If PackageType is
+ EFI_HII_PACKAGE_TYPE_GUID, then this is
+ the pointer to the GUID which must match
+ the Guid field of
+ EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it
+ must be NULL.
+
+ @param HandleBufferLength On input, a pointer to the length
+ of the handle buffer. On output,
+ the length of the handle buffer
+ that is required for the handles found.
+
+ @param Handle An array of EFI_HII_HANDLE instances returned.
+
+ @retval EFI_SUCCESS The matching handles are outputed successfully.
+ HandleBufferLength is updated with the actual length.
+ @retval EFI_BUFFER_TOO_SMALL The HandleBufferLength parameter
+ indicates that Handle is too
+ small to support the number of
+ handles. HandleBufferLength is
+ updated with a value that will
+ enable the data to fit.
+ @retval EFI_NOT_FOUND No matching handle could be found in database.
+ @retval EFI_INVALID_PARAMETER Handle or HandleBufferLength was NULL.
+ @retval EFI_INVALID_PARAMETER PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but
+ PackageGuid is not NULL, PackageType is a EFI_HII_
+ PACKAGE_TYPE_GUID but PackageGuid is NULL.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_DATABASE_LIST_PACKS)(
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN OUT UINTN *HandleBufferLength,
+ OUT EFI_HII_HANDLE *Handle
+);
+
+/**
+
+ This function will export one or all package lists in the
+ database to a buffer. For each package list exported, this
+ function will call functions registered with EXPORT_PACK and
+ then copy the package list to the buffer. The registered
+ functions may call EFI_HII_DATABASE_PROTOCOL.UpdatePackageList()
+ to modify the package list before it is copied to the buffer. If
+ the specified BufferSize is too small, then the status
+ EFI_OUT_OF_RESOURCES will be returned and the actual package
+ size will be returned in BufferSize.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
+
+
+ @param Handle An EFI_HII_HANDLE that corresponds to the
+ desired package list in the HII database to
+ export or NULL to indicate all package lists
+ should be exported.
+
+ @param BufferSize On input, a pointer to the length of the
+ buffer. On output, the length of the
+ buffer that is required for the exported
+ data.
+
+ @param Buffer A pointer to a buffer that will contain the
+ results of the export function.
+
+
+ @retval EFI_SUCCESS Package exported.
+
+ @retval EFI_OUT_OF_RESOURCES BufferSize is too small to hold the package.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_DATABASE_EXPORT_PACKS)(
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
+);
+
+
+/**
+
+
+ This function registers a function which will be called when
+ specified actions related to packages of the specified type
+ occur in the HII database. By registering a function, other
+ HII-related drivers are notified when specific package types
+ are added, removed or updated in the HII database. Each driver
+ or application which registers a notification should use
+ EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before
+ exiting.
+
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
+
+ @param PackageType The package type. See
+ EFI_HII_PACKAGE_TYPE_x in EFI_HII_PACKAGE_HEADER.
+
+ @param PackageGuid If PackageType is
+ EFI_HII_PACKAGE_TYPE_GUID, then this is
+ the pointer to the GUID which must match
+ the Guid field of
+ EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it
+ must be NULL.
+
+ @param PackageNotifyFn Points to the function to be called
+ when the event specified by
+ NotificationType occurs. See
+ EFI_HII_DATABASE_NOTIFY.
+
+ @param NotifyType Describes the types of notification which
+ this function will be receiving. See
+ EFI_HII_DATABASE_NOTIFY_TYPE for a
+ list of types.
+
+ @param NotifyHandle Points to the unique handle assigned to
+ the registered notification. Can be used
+ in EFI_HII_DATABASE_PROTOCOL.UnregisterPack
+ to stop notifications.
+
+
+ @retval EFI_SUCCESS Notification registered successfully.
+
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary
+ data structures.
+
+ @retval EFI_INVALID_PARAMETER PackageGuid is not NULL when
+ PackageType is not
+ EFI_HII_PACKAGE_TYPE_GUID.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_DATABASE_REGISTER_NOTIFY)(
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN EFI_HII_DATABASE_NOTIFY PackageNotifyFn,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ OUT EFI_HANDLE *NotifyHandle
+);
+
+
+/**
+
+ Removes the specified HII database package-related notification.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
+
+ @param NotificationHandle The handle of the notification
+ function being unregistered.
+
+ @retval EFI_SUCCESS Successsfully unregistered the notification.
+
+ @retval EFI_NOT_FOUND The incoming notification handle does not exist
+ in the current hii database.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_DATABASE_UNREGISTER_NOTIFY)(
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+);
+
+
+/**
+
+ This routine retrieves an array of GUID values for each keyboard
+ layout that was previously registered in the system.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param KeyGuidBufferLength On input, a pointer to the length
+ of the keyboard GUID buffer. On
+ output, the length of the handle
+ buffer that is required for the
+ handles found.
+
+ @param KeyGuidBuffer An array of keyboard layout GUID
+ instances returned.
+
+ @retval EFI_SUCCESS KeyGuidBuffer was updated successfully.
+
+ @retval EFI_BUFFER_TOO_SMALL The KeyGuidBufferLength
+ parameter indicates that
+ KeyGuidBuffer is too small to
+ support the number of GUIDs.
+ KeyGuidBufferLength is updated
+ with a value that will enable
+ the data to fit.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_FIND_KEYBOARD_LAYOUTS)(
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN OUT UINT16 *KeyGuidBufferLength,
+ OUT EFI_GUID *KeyGuidBuffer
+);
+
+
+/**
+
+ This routine retrieves the requested keyboard layout. The layout
+ is a physical description of the keys on a keyboard, and the
+ character(s) that are associated with a particular set of key
+ strokes.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param KeyGuid A pointer to the unique ID associated with a
+ given keyboard layout. If KeyGuid is NULL then
+ the current layout will be retrieved.
+
+ @param KeyboardLayoutLength On input, a pointer to the length of the
+ KeyboardLayout buffer. On output, the length of
+ the data placed into KeyboardLayout.
+
+ @param KeyboardLayout A pointer to a buffer containing the
+ retrieved keyboard layout.
+
+ @retval EFI_SUCCESS The keyboard layout was retrieved
+ successfully.
+
+ @retval EFI_NOT_FOUND The requested keyboard layout was not found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_GET_KEYBOARD_LAYOUT)(
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN CONST EFI_GUID *KeyGuid,
+ IN OUT UINT16 *KeyboardLayoutLength,
+ OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout
+);
+
+/**
+
+ This routine sets the default keyboard layout to the one
+ referenced by KeyGuid. When this routine is called, an event
+ will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
+ group type. This is so that agents which are sensitive to the
+ current keyboard layout being changed can be notified of this
+ change.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param KeyGuid A pointer to the unique ID associated with a
+ given keyboard layout.
+
+ @retval EFI_SUCCESS The current keyboard layout was successfully set.
+
+ @retval EFI_NOT_FOUND The referenced keyboard layout was not
+ found, so action was taken.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_SET_KEYBOARD_LAYOUT)(
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN CONST EFI_GUID *KeyGuid
+);
+
+/**
+
+ Return the EFI handle associated with a package list.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param PackageListHandle An EFI_HII_HANDLE that corresponds
+ to the desired package list in the
+ HIIdatabase.
+
+ @param DriverHandle On return, contains the EFI_HANDLE which
+ was registered with the package list in
+ NewPackageList().
+
+ @retval EFI_SUCCESS The DriverHandle was returned successfully.
+
+ @retval EFI_INVALID_PARAMETER The PackageListHandle was not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_DATABASE_GET_PACK_HANDLE)(
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageListHandle,
+ OUT EFI_HANDLE *DriverHandle
+);
+
+///
+/// Database manager for HII-related data structures.
+///
+struct _EFI_HII_DATABASE_PROTOCOL {
+ EFI_HII_DATABASE_NEW_PACK NewPackageList;
+ EFI_HII_DATABASE_REMOVE_PACK RemovePackageList;
+ EFI_HII_DATABASE_UPDATE_PACK UpdatePackageList;
+ EFI_HII_DATABASE_LIST_PACKS ListPackageLists;
+ EFI_HII_DATABASE_EXPORT_PACKS ExportPackageLists;
+ EFI_HII_DATABASE_REGISTER_NOTIFY RegisterPackageNotify;
+ EFI_HII_DATABASE_UNREGISTER_NOTIFY UnregisterPackageNotify;
+ EFI_HII_FIND_KEYBOARD_LAYOUTS FindKeyboardLayouts;
+ EFI_HII_GET_KEYBOARD_LAYOUT GetKeyboardLayout;
+ EFI_HII_SET_KEYBOARD_LAYOUT SetKeyboardLayout;
+ EFI_HII_DATABASE_GET_PACK_HANDLE GetPackageListHandle;
+};
+
+extern EFI_GUID gEfiHiiDatabaseProtocolGuid;
+
+#endif
+
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/LoadedImage.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/LoadedImage.h
new file mode 100644
index 00000000..cbe4103c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/LoadedImage.h
@@ -0,0 +1,90 @@
+/** @file
+ UEFI 2.0 Loaded image protocol definition.
+
+ Every EFI driver and application is passed an image handle when it is loaded.
+ This image handle will contain a Loaded Image Protocol.
+
+ Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __LOADED_IMAGE_PROTOCOL_H__
+#define __LOADED_IMAGE_PROTOCOL_H__
+
+FILE_LICENCE ( BSD3 );
+
+#define EFI_LOADED_IMAGE_PROTOCOL_GUID \
+ { \
+ 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \
+ }
+
+#define EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID \
+ { \
+ 0xbc62157e, 0x3e33, 0x4fec, {0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf } \
+ }
+
+///
+/// Protocol GUID defined in EFI1.1.
+///
+#define LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE_PROTOCOL_GUID
+
+///
+/// EFI_SYSTEM_TABLE & EFI_IMAGE_UNLOAD are defined in EfiApi.h
+///
+#define EFI_LOADED_IMAGE_PROTOCOL_REVISION 0x1000
+
+///
+/// Revision defined in EFI1.1.
+///
+#define EFI_LOADED_IMAGE_INFORMATION_REVISION EFI_LOADED_IMAGE_PROTOCOL_REVISION
+
+///
+/// Can be used on any image handle to obtain information about the loaded image.
+///
+typedef struct {
+ UINT32 Revision; ///< Defines the revision of the EFI_LOADED_IMAGE_PROTOCOL structure.
+ ///< All future revisions will be backward compatible to the current revision.
+ EFI_HANDLE ParentHandle; ///< Parent image's image handle. NULL if the image is loaded directly from
+ ///< the firmware's boot manager.
+ EFI_SYSTEM_TABLE *SystemTable; ///< the image's EFI system table pointer.
+
+ //
+ // Source location of image
+ //
+ EFI_HANDLE DeviceHandle; ///< The device handle that the EFI Image was loaded from.
+ EFI_DEVICE_PATH_PROTOCOL *FilePath; ///< A pointer to the file path portion specific to DeviceHandle
+ ///< that the EFI Image was loaded from.
+ VOID *Reserved; ///< Reserved. DO NOT USE.
+
+ //
+ // Images load options
+ //
+ UINT32 LoadOptionsSize;///< The size in bytes of LoadOptions.
+ VOID *LoadOptions; ///< A pointer to the image's binary load options.
+
+ //
+ // Location of where image was loaded
+ //
+ VOID *ImageBase; ///< The base address at which the image was loaded.
+ UINT64 ImageSize; ///< The size in bytes of the loaded image.
+ EFI_MEMORY_TYPE ImageCodeType; ///< The memory type that the code sections were loaded as.
+ EFI_MEMORY_TYPE ImageDataType; ///< The memory type that the data sections were loaded as.
+ EFI_IMAGE_UNLOAD Unload;
+} EFI_LOADED_IMAGE_PROTOCOL;
+
+//
+// For backward-compatible with EFI1.1.
+//
+typedef EFI_LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE;
+
+extern EFI_GUID gEfiLoadedImageProtocolGuid;
+extern EFI_GUID gEfiLoadedImageDevicePathProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/NetworkInterfaceIdentifier.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/NetworkInterfaceIdentifier.h
new file mode 100644
index 00000000..ac86e972
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/NetworkInterfaceIdentifier.h
@@ -0,0 +1,93 @@
+/** @file
+ EFI Network Interface Identifier Protocol.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ This Protocol is introduced in EFI Specification 1.10.
+
+**/
+
+#ifndef __EFI_NETWORK_INTERFACE_IDENTIFER_H__
+#define __EFI_NETWORK_INTERFACE_IDENTIFER_H__
+
+FILE_LICENCE ( BSD3 );
+
+//
+// GUID retired from UEFI Specification 2.1b
+//
+#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID \
+ { \
+ 0xE18541CD, 0xF755, 0x4f73, {0x92, 0x8D, 0x64, 0x3C, 0x8A, 0x79, 0xB2, 0x29 } \
+ }
+
+//
+// GUID intruduced in UEFI Specification 2.1b
+//
+#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID_31 \
+ { \
+ 0x1ACED566, 0x76ED, 0x4218, {0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 } \
+ }
+
+#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION 0x00010000
+
+///
+/// Revision defined in EFI1.1.
+///
+#define EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE_REVISION EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION
+
+///
+/// Forward reference for pure ANSI compatability.
+///
+typedef struct _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL;
+
+///
+/// Protocol defined in EFI1.1.
+///
+typedef EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE;
+
+///
+/// An optional protocol that is used to describe details about the software
+/// layer that is used to produce the Simple Network Protocol.
+///
+struct _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL {
+ UINT64 Revision; ///< The revision of the EFI_NETWORK_INTERFACE_IDENTIFIER protocol.
+ UINT64 Id; ///< The address of the first byte of the identifying structure for this network
+ ///< interface. This is only valid when the network interface is started
+ ///< (see Start()). When the network interface is not started, this field is set to zero.
+ UINT64 ImageAddr; ///< The address of the first byte of the identifying structure for this
+ ///< network interface. This is set to zero if there is no structure.
+ UINT32 ImageSize; ///< The size of unrelocated network interface image.
+ CHAR8 StringId[4];///< A four-character ASCII string that is sent in the class identifier field of
+ ///< option 60 in DHCP. For a Type of EfiNetworkInterfaceUndi, this field is UNDI.
+ UINT8 Type; ///< Network interface type. This will be set to one of the values
+ ///< in EFI_NETWORK_INTERFACE_TYPE.
+ UINT8 MajorVer; ///< Major version number.
+ UINT8 MinorVer; ///< Minor version number.
+ BOOLEAN Ipv6Supported; ///< TRUE if the network interface supports IPv6; otherwise FALSE.
+ UINT8 IfNum; ///< The network interface number that is being identified by this Network
+ ///< Interface Identifier Protocol. This field must be less than or equal
+ ///< to the IFcnt field in the !PXE structure.
+
+};
+
+///
+///*******************************************************
+/// EFI_NETWORK_INTERFACE_TYPE
+///*******************************************************
+///
+typedef enum {
+ EfiNetworkInterfaceUndi = 1
+} EFI_NETWORK_INTERFACE_TYPE;
+
+extern EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid;
+extern EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid_31;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/PciIo.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/PciIo.h
new file mode 100644
index 00000000..97f65e1f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/PciIo.h
@@ -0,0 +1,560 @@
+/** @file
+ EFI PCI I/O Protocol provides the basic Memory, I/O, PCI configuration,
+ and DMA interfaces that a driver uses to access its PCI controller.
+
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PCI_IO_H__
+#define __PCI_IO_H__
+
+FILE_LICENCE ( BSD3 );
+
+///
+/// Global ID for the PCI I/O Protocol
+///
+#define EFI_PCI_IO_PROTOCOL_GUID \
+ { \
+ 0x4cf5b200, 0x68b8, 0x4ca5, {0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a } \
+ }
+
+typedef struct _EFI_PCI_IO_PROTOCOL EFI_PCI_IO_PROTOCOL;
+
+///
+/// *******************************************************
+/// EFI_PCI_IO_PROTOCOL_WIDTH
+/// *******************************************************
+///
+typedef enum {
+ EfiPciIoWidthUint8 = 0,
+ EfiPciIoWidthUint16,
+ EfiPciIoWidthUint32,
+ EfiPciIoWidthUint64,
+ EfiPciIoWidthFifoUint8,
+ EfiPciIoWidthFifoUint16,
+ EfiPciIoWidthFifoUint32,
+ EfiPciIoWidthFifoUint64,
+ EfiPciIoWidthFillUint8,
+ EfiPciIoWidthFillUint16,
+ EfiPciIoWidthFillUint32,
+ EfiPciIoWidthFillUint64,
+ EfiPciIoWidthMaximum
+} EFI_PCI_IO_PROTOCOL_WIDTH;
+
+//
+// Complete PCI address generater
+//
+#define EFI_PCI_IO_PASS_THROUGH_BAR 0xff ///< Special BAR that passes a memory or I/O cycle through unchanged
+#define EFI_PCI_IO_ATTRIBUTE_MASK 0x077f ///< All the following I/O and Memory cycles
+#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001 ///< I/O cycles 0x0000-0x00FF (10 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002 ///< I/O cycles 0x0100-0x03FF or greater (10 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004 ///< I/O cycles 0x3C6, 0x3C8, 0x3C9 (10 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008 ///< MEM cycles 0xA0000-0xBFFFF (24 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010 ///< I/O cycles 0x3B0-0x3BB and 0x3C0-0x3DF (10 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020 ///< I/O cycles 0x1F0-0x1F7, 0x3F6, 0x3F7 (10 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040 ///< I/O cycles 0x170-0x177, 0x376, 0x377 (10 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080 ///< Map a memory range so writes are combined
+#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100 ///< Enable the I/O decode bit in the PCI Config Header
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200 ///< Enable the Memory decode bit in the PCI Config Header
+#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400 ///< Enable the DMA bit in the PCI Config Header
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800 ///< Map a memory range so all r/w accesses are cached
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000 ///< Disable a memory range
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000 ///< Clear for an add-in PCI Device
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000 ///< Clear for a physical PCI Option ROM accessed through ROM BAR
+#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000 ///< Clear for PCI controllers that can not genrate a DAC
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000 ///< I/O cycles 0x0100-0x03FF or greater (16 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 ///< I/O cycles 0x3C6, 0x3C8, 0x3C9 (16 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000 ///< I/O cycles 0x3B0-0x3BB and 0x3C0-0x3DF (16 bit decode)
+
+#define EFI_PCI_DEVICE_ENABLE (EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER)
+#define EFI_VGA_DEVICE_ENABLE (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_IO)
+
+///
+/// *******************************************************
+/// EFI_PCI_IO_PROTOCOL_OPERATION
+/// *******************************************************
+///
+typedef enum {
+ ///
+ /// A read operation from system memory by a bus master.
+ ///
+ EfiPciIoOperationBusMasterRead,
+ ///
+ /// A write operation from system memory by a bus master.
+ ///
+ EfiPciIoOperationBusMasterWrite,
+ ///
+ /// Provides both read and write access to system memory by both the processor and a
+ /// bus master. The buffer is coherent from both the processor's and the bus master's point of view.
+ ///
+ EfiPciIoOperationBusMasterCommonBuffer,
+ EfiPciIoOperationMaximum
+} EFI_PCI_IO_PROTOCOL_OPERATION;
+
+///
+/// *******************************************************
+/// EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION
+/// *******************************************************
+///
+typedef enum {
+ ///
+ /// Retrieve the PCI controller's current attributes, and return them in Result.
+ ///
+ EfiPciIoAttributeOperationGet,
+ ///
+ /// Set the PCI controller's current attributes to Attributes.
+ ///
+ EfiPciIoAttributeOperationSet,
+ ///
+ /// Enable the attributes specified by the bits that are set in Attributes for this PCI controller.
+ ///
+ EfiPciIoAttributeOperationEnable,
+ ///
+ /// Disable the attributes specified by the bits that are set in Attributes for this PCI controller.
+ ///
+ EfiPciIoAttributeOperationDisable,
+ ///
+ /// Retrieve the PCI controller's supported attributes, and return them in Result.
+ ///
+ EfiPciIoAttributeOperationSupported,
+ EfiPciIoAttributeOperationMaximum
+} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION;
+
+/**
+ Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
+ satisfied or after a defined duration.
+
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ @param Width Signifies the width of the memory or I/O operations.
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the
+ base address for the memory operation to perform.
+ @param Offset The offset within the selected BAR to start the memory operation.
+ @param Mask Mask used for the polling criteria.
+ @param Value The comparison value used for the polling exit criteria.
+ @param Delay The number of 100 ns units to poll.
+ @param Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
+ @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of this PCI controller.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_POLL_IO_MEM)(
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+/**
+ Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
+
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ @param Width Signifies the width of the memory or I/O operations.
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the
+ base address for the memory or I/O operation to perform.
+ @param Offset The offset within the selected BAR to start the memory or I/O operation.
+ @param Count The number of memory or I/O operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
+ valid for the PCI BAR specified by BarIndex.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_IO_MEM)(
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+typedef struct {
+ ///
+ /// Read PCI controller registers in the PCI memory or I/O space.
+ ///
+ EFI_PCI_IO_PROTOCOL_IO_MEM Read;
+ ///
+ /// Write PCI controller registers in the PCI memory or I/O space.
+ ///
+ EFI_PCI_IO_PROTOCOL_IO_MEM Write;
+} EFI_PCI_IO_PROTOCOL_ACCESS;
+
+/**
+ Enable a PCI driver to access PCI controller registers in PCI configuration space.
+
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ @param Width Signifies the width of the memory operations.
+ @param Offset The offset within the PCI configuration space for the PCI controller.
+ @param Count The number of PCI configuration operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
+ valid for the PCI configuration header of the PCI controller.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_CONFIG)(
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+typedef struct {
+ ///
+ /// Read PCI controller registers in PCI configuration space.
+ ///
+ EFI_PCI_IO_PROTOCOL_CONFIG Read;
+ ///
+ /// Write PCI controller registers in PCI configuration space.
+ ///
+ EFI_PCI_IO_PROTOCOL_CONFIG Write;
+} EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS;
+
+/**
+ Enables a PCI driver to copy one region of PCI memory space to another region of PCI
+ memory space.
+
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ @param Width Signifies the width of the memory operations.
+ @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the
+ base address for the memory operation to perform.
+ @param DestOffset The destination offset within the BAR specified by DestBarIndex to
+ start the memory writes for the copy operation.
+ @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the
+ base address for the memory operation to perform.
+ @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start
+ the memory reads for the copy operation.
+ @param Count The number of memory operations to perform. Bytes moved is Width
+ size * Count, starting at DestOffset and SrcOffset.
+
+ @retval EFI_SUCCESS The data was copied from one memory region to another memory region.
+ @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI controller.
+ @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI controller.
+ @retval EFI_UNSUPPORTED The address range specified by DestOffset, Width, and Count
+ is not valid for the PCI BAR specified by DestBarIndex.
+ @retval EFI_UNSUPPORTED The address range specified by SrcOffset, Width, and Count is
+ not valid for the PCI BAR specified by SrcBarIndex.
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_COPY_MEM)(
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 DestBarIndex,
+ IN UINT64 DestOffset,
+ IN UINT8 SrcBarIndex,
+ IN UINT64 SrcOffset,
+ IN UINTN Count
+ );
+
+/**
+ Provides the PCI controller-specific addresses needed to access system memory.
+
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ @param Operation Indicates if the bus master is going to read or write to system memory.
+ @param HostAddress The system memory address to map to the PCI controller.
+ @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
+ that were mapped.
+ @param DeviceAddress The resulting map address for the bus master PCI controller to use to
+ access the hosts HostAddress.
+ @param Mapping A resulting value to pass to Unmap().
+
+ @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_MAP)(
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+/**
+ Completes the Map() operation and releases any corresponding resources.
+
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ @param Mapping The mapping value returned from Map().
+
+ @retval EFI_SUCCESS The range was unmapped.
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_UNMAP)(
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+/**
+ Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer
+ mapping.
+
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ @param Type This parameter is not used and must be ignored.
+ @param MemoryType The type of memory to allocate, EfiBootServicesData or
+ EfiRuntimeServicesData.
+ @param Pages The number of pages to allocate.
+ @param HostAddress A pointer to store the base system memory address of the
+ allocated range.
+ @param Attributes The requested bit mask of attributes for the allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
+ MEMORY_WRITE_COMBINE and MEMORY_CACHED.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER)(
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ );
+
+/**
+ Frees memory that was allocated with AllocateBuffer().
+
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ @param Pages The number of pages to free.
+ @param HostAddress The base system memory address of the allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were freed.
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+ was not allocated with AllocateBuffer().
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_FREE_BUFFER)(
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ );
+
+/**
+ Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host
+ bridge to system memory.
+ @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI
+ host bridge due to a hardware error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_FLUSH)(
+ IN EFI_PCI_IO_PROTOCOL *This
+ );
+
+/**
+ Retrieves this PCI controller's current PCI bus number, device number, and function number.
+
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ @param SegmentNumber The PCI controller's current PCI segment number.
+ @param BusNumber The PCI controller's current PCI bus number.
+ @param DeviceNumber The PCI controller's current PCI device number.
+ @param FunctionNumber The PCI controller's current PCI function number.
+
+ @retval EFI_SUCCESS The PCI controller location was returned.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_GET_LOCATION)(
+ IN EFI_PCI_IO_PROTOCOL *This,
+ OUT UINTN *SegmentNumber,
+ OUT UINTN *BusNumber,
+ OUT UINTN *DeviceNumber,
+ OUT UINTN *FunctionNumber
+ );
+
+/**
+ Performs an operation on the attributes that this PCI controller supports. The operations include
+ getting the set of supported attributes, retrieving the current attributes, setting the current
+ attributes, enabling attributes, and disabling attributes.
+
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ @param Operation The operation to perform on the attributes for this PCI controller.
+ @param Attributes The mask of attributes that are used for Set, Enable, and Disable
+ operations.
+ @param Result A pointer to the result mask of attributes that are returned for the Get
+ and Supported operations.
+
+ @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_UNSUPPORTED one or more of the bits set in
+ Attributes are not supported by this PCI controller or one of
+ its parent bridges when Operation is Set, Enable or Disable.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_ATTRIBUTES)(
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes,
+ OUT UINT64 *Result OPTIONAL
+ );
+
+/**
+ Gets the attributes that this PCI controller supports setting on a BAR using
+ SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.
+
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the
+ base address for resource range. The legal range for this field is 0..5.
+ @param Supports A pointer to the mask of attributes that this PCI controller supports
+ setting for this BAR with SetBarAttributes().
+ @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current
+ configuration of this BAR of the PCI controller.
+
+ @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI
+ controller supports are returned in Supports. If Resources
+ is not NULL, then the ACPI 2.0 resource descriptors that the PCI
+ controller is currently using are returned in Resources.
+ @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate
+ Resources.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES)(
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT8 BarIndex,
+ OUT UINT64 *Supports, OPTIONAL
+ OUT VOID **Resources OPTIONAL
+ );
+
+/**
+ Sets the attributes for a range of a BAR on a PCI controller.
+
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ @param Attributes The mask of attributes to set for the resource range specified by
+ BarIndex, Offset, and Length.
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the
+ base address for resource range. The legal range for this field is 0..5.
+ @param Offset A pointer to the BAR relative base address of the resource range to be
+ modified by the attributes specified by Attributes.
+ @param Length A pointer to the length of the resource range to be modified by the
+ attributes specified by Attributes.
+
+ @retval EFI_SUCCESS The set of attributes specified by Attributes for the resource
+ range specified by BarIndex, Offset, and Length were
+ set on the PCI controller, and the actual resource range is returned
+ in Offset and Length.
+ @retval EFI_INVALID_PARAMETER Offset or Length is NULL.
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the attributes on the
+ resource range specified by BarIndex, Offset, and
+ Length.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES)(
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN UINT8 BarIndex,
+ IN OUT UINT64 *Offset,
+ IN OUT UINT64 *Length
+ );
+
+///
+/// The EFI_PCI_IO_PROTOCOL provides the basic Memory, I/O, PCI configuration,
+/// and DMA interfaces used to abstract accesses to PCI controllers.
+/// There is one EFI_PCI_IO_PROTOCOL instance for each PCI controller on a PCI bus.
+/// A device driver that wishes to manage a PCI controller in a system will have to
+/// retrieve the EFI_PCI_IO_PROTOCOL instance that is associated with the PCI controller.
+///
+struct _EFI_PCI_IO_PROTOCOL {
+ EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollMem;
+ EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollIo;
+ EFI_PCI_IO_PROTOCOL_ACCESS Mem;
+ EFI_PCI_IO_PROTOCOL_ACCESS Io;
+ EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS Pci;
+ EFI_PCI_IO_PROTOCOL_COPY_MEM CopyMem;
+ EFI_PCI_IO_PROTOCOL_MAP Map;
+ EFI_PCI_IO_PROTOCOL_UNMAP Unmap;
+ EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer;
+ EFI_PCI_IO_PROTOCOL_FREE_BUFFER FreeBuffer;
+ EFI_PCI_IO_PROTOCOL_FLUSH Flush;
+ EFI_PCI_IO_PROTOCOL_GET_LOCATION GetLocation;
+ EFI_PCI_IO_PROTOCOL_ATTRIBUTES Attributes;
+ EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES GetBarAttributes;
+ EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES SetBarAttributes;
+
+ ///
+ /// The size, in bytes, of the ROM image.
+ ///
+ UINT64 RomSize;
+
+ ///
+ /// A pointer to the in memory copy of the ROM image. The PCI Bus Driver is responsible
+ /// for allocating memory for the ROM image, and copying the contents of the ROM to memory.
+ /// The contents of this buffer are either from the PCI option ROM that can be accessed
+ /// through the ROM BAR of the PCI controller, or it is from a platform-specific location.
+ /// The Attributes() function can be used to determine from which of these two sources
+ /// the RomImage buffer was initialized.
+ ///
+ VOID *RomImage;
+};
+
+extern EFI_GUID gEfiPciIoProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/PciRootBridgeIo.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/PciRootBridgeIo.h
new file mode 100644
index 00000000..e8feea0c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/PciRootBridgeIo.h
@@ -0,0 +1,438 @@
+/** @file
+ PCI Root Bridge I/O protocol as defined in the UEFI 2.0 specification.
+
+ PCI Root Bridge I/O protocol is used by PCI Bus Driver to perform PCI Memory, PCI I/O,
+ and PCI Configuration cycles on a PCI Root Bridge. It also provides services to perform
+ defferent types of bus mastering DMA.
+
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PCI_ROOT_BRIDGE_IO_H__
+#define __PCI_ROOT_BRIDGE_IO_H__
+
+FILE_LICENCE ( BSD3 );
+
+#define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \
+ { \
+ 0x2f707ebb, 0x4a1a, 0x11d4, {0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+ }
+
+typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL;
+
+///
+/// *******************************************************
+/// EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
+/// *******************************************************
+///
+typedef enum {
+ EfiPciWidthUint8,
+ EfiPciWidthUint16,
+ EfiPciWidthUint32,
+ EfiPciWidthUint64,
+ EfiPciWidthFifoUint8,
+ EfiPciWidthFifoUint16,
+ EfiPciWidthFifoUint32,
+ EfiPciWidthFifoUint64,
+ EfiPciWidthFillUint8,
+ EfiPciWidthFillUint16,
+ EfiPciWidthFillUint32,
+ EfiPciWidthFillUint64,
+ EfiPciWidthMaximum
+} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH;
+
+///
+/// *******************************************************
+/// EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION
+/// *******************************************************
+///
+typedef enum {
+ ///
+ /// A read operation from system memory by a bus master that is not capable of producing
+ /// PCI dual address cycles.
+ ///
+ EfiPciOperationBusMasterRead,
+ ///
+ /// A write operation from system memory by a bus master that is not capable of producing
+ /// PCI dual address cycles.
+ ///
+ EfiPciOperationBusMasterWrite,
+ ///
+ /// Provides both read and write access to system memory by both the processor and a bus
+ /// master that is not capable of producing PCI dual address cycles.
+ ///
+ EfiPciOperationBusMasterCommonBuffer,
+ ///
+ /// A read operation from system memory by a bus master that is capable of producing PCI
+ /// dual address cycles.
+ ///
+ EfiPciOperationBusMasterRead64,
+ ///
+ /// A write operation to system memory by a bus master that is capable of producing PCI
+ /// dual address cycles.
+ ///
+ EfiPciOperationBusMasterWrite64,
+ ///
+ /// Provides both read and write access to system memory by both the processor and a bus
+ /// master that is capable of producing PCI dual address cycles.
+ ///
+ EfiPciOperationBusMasterCommonBuffer64,
+ EfiPciOperationMaximum
+} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION;
+
+#define EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001
+#define EFI_PCI_ATTRIBUTE_ISA_IO 0x0002
+#define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO 0x0004
+#define EFI_PCI_ATTRIBUTE_VGA_MEMORY 0x0008
+#define EFI_PCI_ATTRIBUTE_VGA_IO 0x0010
+#define EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO 0x0020
+#define EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO 0x0040
+#define EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080
+#define EFI_PCI_ATTRIBUTE_MEMORY_CACHED 0x0800
+#define EFI_PCI_ATTRIBUTE_MEMORY_DISABLE 0x1000
+#define EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000
+#define EFI_PCI_ATTRIBUTE_ISA_IO_16 0x10000
+#define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000
+#define EFI_PCI_ATTRIBUTE_VGA_IO_16 0x40000
+
+#define EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER (EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED | EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE)
+
+#define EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER (~EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER)
+
+#define EFI_PCI_ADDRESS(bus, dev, func, reg) \
+ ((UINT64) ((((UINTN) bus) << 24) + (((UINTN) dev) << 16) + (((UINTN) func) << 8) + ((UINTN) reg)))
+
+typedef struct {
+ UINT8 Register;
+ UINT8 Function;
+ UINT8 Device;
+ UINT8 Bus;
+ UINT32 ExtendedRegister;
+} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS;
+
+/**
+ Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
+ satisfied or after a defined duration.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory or I/O operations.
+ @param Address The base address of the memory or I/O operations.
+ @param Mask Mask used for the polling criteria.
+ @param Value The comparison value used for the polling exit criteria.
+ @param Delay The number of 100 ns units to poll.
+ @param Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM)(
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM)(
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+typedef struct {
+ ///
+ /// Read PCI controller registers in the PCI root bridge memory space.
+ ///
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Read;
+ ///
+ /// Write PCI controller registers in the PCI root bridge memory space.
+ ///
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Write;
+} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS;
+
+/**
+ Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
+ root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ @param Width Signifies the width of the memory operations.
+ @param DestAddress The destination address of the memory operation.
+ @param SrcAddress The source address of the memory operation.
+ @param Count The number of memory operations to perform.
+
+ @retval EFI_SUCCESS The data was copied from one memory region to another memory region.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM)(
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ );
+
+/**
+ Provides the PCI controller-specific addresses required to access system memory from a
+ DMA bus master.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Operation Indicates if the bus master is going to read or write to system memory.
+ @param HostAddress The system memory address to map to the PCI controller.
+ @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
+ that were mapped.
+ @param DeviceAddress The resulting map address for the bus master PCI controller to use to
+ access the hosts HostAddress.
+ @param Mapping A resulting value to pass to Unmap().
+
+ @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP)(
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+/**
+ Completes the Map() operation and releases any corresponding resources.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Mapping The mapping value returned from Map().
+
+ @retval EFI_SUCCESS The range was unmapped.
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP)(
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+/**
+ Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
+ EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Type This parameter is not used and must be ignored.
+ @param MemoryType The type of memory to allocate, EfiBootServicesData or
+ EfiRuntimeServicesData.
+ @param Pages The number of pages to allocate.
+ @param HostAddress A pointer to store the base system memory address of the
+ allocated range.
+ @param Attributes The requested bit mask of attributes for the allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
+ MEMORY_WRITE_COMBINE and MEMORY_CACHED.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER)(
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ IN OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ );
+
+/**
+ Frees memory that was allocated with AllocateBuffer().
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Pages The number of pages to free.
+ @param HostAddress The base system memory address of the allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were freed.
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+ was not allocated with AllocateBuffer().
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER)(
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ );
+
+/**
+ Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host
+ bridge to system memory.
+ @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI
+ host bridge due to a hardware error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH)(
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ );
+
+/**
+ Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
+ attributes that a PCI root bridge is currently using.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Supports A pointer to the mask of attributes that this PCI root bridge supports
+ setting with SetAttributes().
+ @param Attributes A pointer to the mask of attributes that this PCI root bridge is currently
+ using.
+
+ @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI root
+ bridge supports is returned in Supports. If Attributes is
+ not NULL, then the attributes that the PCI root bridge is currently
+ using is returned in Attributes.
+ @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES)(
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supports,
+ OUT UINT64 *Attributes
+ );
+
+/**
+ Sets attributes for a resource range on a PCI root bridge.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Attributes The mask of attributes to set.
+ @param ResourceBase A pointer to the base address of the resource range to be modified by the
+ attributes specified by Attributes.
+ @param ResourceLength A pointer to the length of the resource range to be modified by the
+ attributes specified by Attributes.
+
+ @retval EFI_SUCCESS The set of attributes specified by Attributes for the resource
+ range specified by ResourceBase and ResourceLength
+ were set on the PCI root bridge, and the actual resource range is
+ returned in ResuourceBase and ResourceLength.
+ @retval EFI_UNSUPPORTED A bit is set in Attributes that is not supported by the PCI Root
+ Bridge.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the attributes on the
+ resource range specified by BaseAddress and Length.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES)(
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ );
+
+/**
+ Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
+ resource descriptors.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current
+ configuration of this PCI root bridge.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in
+ Resources.
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be
+ retrieved.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION)(
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ );
+
+///
+/// Provides the basic Memory, I/O, PCI configuration, and DMA interfaces that are
+/// used to abstract accesses to PCI controllers behind a PCI Root Bridge Controller.
+///
+struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL {
+ ///
+ /// The EFI_HANDLE of the PCI Host Bridge of which this PCI Root Bridge is a member.
+ ///
+ EFI_HANDLE ParentHandle;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollMem;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollIo;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Mem;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Io;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Pci;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM CopyMem;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP Map;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP Unmap;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER FreeBuffer;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH Flush;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES GetAttributes;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES SetAttributes;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION Configuration;
+
+ ///
+ /// The segment number that this PCI root bridge resides.
+ ///
+ UINT32 SegmentNumber;
+};
+
+extern EFI_GUID gEfiPciRootBridgeIoProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/SimpleNetwork.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/SimpleNetwork.h
new file mode 100644
index 00000000..2b521a9d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/SimpleNetwork.h
@@ -0,0 +1,664 @@
+/** @file
+ The EFI_SIMPLE_NETWORK_PROTOCOL provides services to initialize a network interface,
+ transmit packets, receive packets, and close a network interface.
+
+ Basic network device abstraction.
+
+ Rx - Received
+ Tx - Transmit
+ MCast - MultiCast
+ ...
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ This Protocol is introduced in EFI Specification 1.10.
+
+**/
+
+#ifndef __SIMPLE_NETWORK_H__
+#define __SIMPLE_NETWORK_H__
+
+FILE_LICENCE ( BSD3 );
+
+#define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \
+ { \
+ 0xA19832B9, 0xAC25, 0x11D3, {0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } \
+ }
+
+typedef struct _EFI_SIMPLE_NETWORK_PROTOCOL EFI_SIMPLE_NETWORK_PROTOCOL;
+
+
+///
+/// Protocol defined in EFI1.1.
+///
+typedef EFI_SIMPLE_NETWORK_PROTOCOL EFI_SIMPLE_NETWORK;
+
+///
+/// Simple Network Protocol data structures.
+///
+typedef struct {
+ ///
+ /// Total number of frames received. Includes frames with errors and
+ /// dropped frames.
+ ///
+ UINT64 RxTotalFrames;
+
+ ///
+ /// Number of valid frames received and copied into receive buffers.
+ ///
+ UINT64 RxGoodFrames;
+
+ ///
+ /// Number of frames below the minimum length for the media.
+ /// This would be <64 for ethernet.
+ ///
+ UINT64 RxUndersizeFrames;
+
+ ///
+ /// Number of frames longer than the maxminum length for the
+ /// media. This would be >1500 for ethernet.
+ ///
+ UINT64 RxOversizeFrames;
+
+ ///
+ /// Valid frames that were dropped because receive buffers were full.
+ ///
+ UINT64 RxDroppedFrames;
+
+ ///
+ /// Number of valid unicast frames received and not dropped.
+ ///
+ UINT64 RxUnicastFrames;
+
+ ///
+ /// Number of valid broadcast frames received and not dropped.
+ ///
+ UINT64 RxBroadcastFrames;
+
+ ///
+ /// Number of valid mutlicast frames received and not dropped.
+ ///
+ UINT64 RxMulticastFrames;
+
+ ///
+ /// Number of frames w/ CRC or alignment errors.
+ ///
+ UINT64 RxCrcErrorFrames;
+
+ ///
+ /// Total number of bytes received. Includes frames with errors
+ /// and dropped frames.
+ //
+ UINT64 RxTotalBytes;
+
+ ///
+ /// Transmit statistics.
+ ///
+ UINT64 TxTotalFrames;
+ UINT64 TxGoodFrames;
+ UINT64 TxUndersizeFrames;
+ UINT64 TxOversizeFrames;
+ UINT64 TxDroppedFrames;
+ UINT64 TxUnicastFrames;
+ UINT64 TxBroadcastFrames;
+ UINT64 TxMulticastFrames;
+ UINT64 TxCrcErrorFrames;
+ UINT64 TxTotalBytes;
+
+ ///
+ /// Number of collisions detection on this subnet.
+ ///
+ UINT64 Collisions;
+
+ ///
+ /// Number of frames destined for unsupported protocol.
+ ///
+ UINT64 UnsupportedProtocol;
+
+} EFI_NETWORK_STATISTICS;
+
+///
+/// The state of the network interface.
+/// When an EFI_SIMPLE_NETWORK_PROTOCOL driver initializes a
+/// network interface, the network interface is left in the EfiSimpleNetworkStopped state.
+///
+typedef enum {
+ EfiSimpleNetworkStopped,
+ EfiSimpleNetworkStarted,
+ EfiSimpleNetworkInitialized,
+ EfiSimpleNetworkMaxState
+} EFI_SIMPLE_NETWORK_STATE;
+
+#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01
+#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02
+#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04
+#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08
+#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10
+
+#define EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT 0x01
+#define EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT 0x02
+#define EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT 0x04
+#define EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT 0x08
+
+#define MAX_MCAST_FILTER_CNT 16
+typedef struct {
+ ///
+ /// Reports the current state of the network interface.
+ ///
+ UINT32 State;
+ ///
+ /// The size, in bytes, of the network interface's HW address.
+ ///
+ UINT32 HwAddressSize;
+ ///
+ /// The size, in bytes, of the network interface's media header.
+ ///
+ UINT32 MediaHeaderSize;
+ ///
+ /// The maximum size, in bytes, of the packets supported by the network interface.
+ ///
+ UINT32 MaxPacketSize;
+ ///
+ /// The size, in bytes, of the NVRAM device attached to the network interface.
+ ///
+ UINT32 NvRamSize;
+ ///
+ /// The size that must be used for all NVRAM reads and writes. The
+ /// start address for NVRAM read and write operations and the total
+ /// length of those operations, must be a multiple of this value. The
+ /// legal values for this field are 0, 1, 2, 4, and 8.
+ ///
+ UINT32 NvRamAccessSize;
+ ///
+ /// The multicast receive filter settings supported by the network interface.
+ ///
+ UINT32 ReceiveFilterMask;
+ ///
+ /// The current multicast receive filter settings.
+ ///
+ UINT32 ReceiveFilterSetting;
+ ///
+ /// The maximum number of multicast address receive filters supported by the driver.
+ ///
+ UINT32 MaxMCastFilterCount;
+ ///
+ /// The current number of multicast address receive filters.
+ ///
+ UINT32 MCastFilterCount;
+ ///
+ /// Array containing the addresses of the current multicast address receive filters.
+ ///
+ EFI_MAC_ADDRESS MCastFilter[MAX_MCAST_FILTER_CNT];
+ ///
+ /// The current HW MAC address for the network interface.
+ ///
+ EFI_MAC_ADDRESS CurrentAddress;
+ ///
+ /// The current HW MAC address for broadcast packets.
+ ///
+ EFI_MAC_ADDRESS BroadcastAddress;
+ ///
+ /// The permanent HW MAC address for the network interface.
+ ///
+ EFI_MAC_ADDRESS PermanentAddress;
+ ///
+ /// The interface type of the network interface.
+ ///
+ UINT8 IfType;
+ ///
+ /// TRUE if the HW MAC address can be changed.
+ ///
+ BOOLEAN MacAddressChangeable;
+ ///
+ /// TRUE if the network interface can transmit more than one packet at a time.
+ ///
+ BOOLEAN MultipleTxSupported;
+ ///
+ /// TRUE if the presence of media can be determined; otherwise FALSE.
+ ///
+ BOOLEAN MediaPresentSupported;
+ ///
+ /// TRUE if media are connected to the network interface; otherwise FALSE.
+ ///
+ BOOLEAN MediaPresent;
+} EFI_SIMPLE_NETWORK_MODE;
+
+//
+// Protocol Member Functions
+//
+/**
+ Changes the state of a network interface from "stopped" to "started".
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The network interface was started.
+ @retval EFI_ALREADY_STARTED The network interface is already in the started state.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_NETWORK_START)(
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ );
+
+/**
+ Changes the state of a network interface from "started" to "stopped".
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The network interface was stopped.
+ @retval EFI_ALREADY_STARTED The network interface is already in the stopped state.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_NETWORK_STOP)(
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ );
+
+/**
+ Resets a network adapter and allocates the transmit and receive buffers
+ required by the network interface; optionally, also requests allocation
+ of additional transmit and receive buffers.
+
+ @param This The protocol instance pointer.
+ @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space
+ that the driver should allocate for the network interface.
+ Some network interfaces will not be able to use the extra
+ buffer, and the caller will not know if it is actually
+ being used.
+ @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space
+ that the driver should allocate for the network interface.
+ Some network interfaces will not be able to use the extra
+ buffer, and the caller will not know if it is actually
+ being used.
+
+ @retval EFI_SUCCESS The network interface was initialized.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and
+ receive buffers.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_NETWORK_INITIALIZE)(
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN UINTN ExtraRxBufferSize OPTIONAL,
+ IN UINTN ExtraTxBufferSize OPTIONAL
+ );
+
+/**
+ Resets a network adapter and re-initializes it with the parameters that were
+ provided in the previous call to Initialize().
+
+ @param This The protocol instance pointer.
+ @param ExtendedVerification Indicates that the driver may perform a more
+ exhaustive verification operation of the device
+ during reset.
+
+ @retval EFI_SUCCESS The network interface was reset.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_NETWORK_RESET)(
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Resets a network adapter and leaves it in a state that is safe for
+ another driver to initialize.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The network interface was shutdown.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_NETWORK_SHUTDOWN)(
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ );
+
+/**
+ Manages the multicast receive filters of a network interface.
+
+ @param This The protocol instance pointer.
+ @param Enable A bit mask of receive filters to enable on the network interface.
+ @param Disable A bit mask of receive filters to disable on the network interface.
+ @param ResetMCastFilter Set to TRUE to reset the contents of the multicast receive
+ filters on the network interface to their default values.
+ @param McastFilterCnt Number of multicast HW MAC addresses in the new
+ MCastFilter list. This value must be less than or equal to
+ the MCastFilterCnt field of EFI_SIMPLE_NETWORK_MODE. This
+ field is optional if ResetMCastFilter is TRUE.
+ @param MCastFilter A pointer to a list of new multicast receive filter HW MAC
+ addresses. This list will replace any existing multicast
+ HW MAC address list. This field is optional if
+ ResetMCastFilter is TRUE.
+
+ @retval EFI_SUCCESS The multicast receive filter list was updated.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_NETWORK_RECEIVE_FILTERS)(
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN UINT32 Enable,
+ IN UINT32 Disable,
+ IN BOOLEAN ResetMCastFilter,
+ IN UINTN MCastFilterCnt OPTIONAL,
+ IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL
+ );
+
+/**
+ Modifies or resets the current station address, if supported.
+
+ @param This The protocol instance pointer.
+ @param Reset Flag used to reset the station address to the network interfaces
+ permanent address.
+ @param New The new station address to be used for the network interface.
+
+ @retval EFI_SUCCESS The network interfaces station address was updated.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_NETWORK_STATION_ADDRESS)(
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN Reset,
+ IN EFI_MAC_ADDRESS *New OPTIONAL
+ );
+
+/**
+ Resets or collects the statistics on a network interface.
+
+ @param This Protocol instance pointer.
+ @param Reset Set to TRUE to reset the statistics for the network interface.
+ @param StatisticsSize On input the size, in bytes, of StatisticsTable. On
+ output the size, in bytes, of the resulting table of
+ statistics.
+ @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
+ contains the statistics.
+
+ @retval EFI_SUCCESS The statistics were collected from the network interface.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer
+ size needed to hold the statistics is returned in
+ StatisticsSize.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_NETWORK_STATISTICS)(
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN Reset,
+ IN OUT UINTN *StatisticsSize OPTIONAL,
+ OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL
+ );
+
+/**
+ Converts a multicast IP address to a multicast HW MAC address.
+
+ @param This The protocol instance pointer.
+ @param IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC 2460]. Set
+ to FALSE if the multicast IP address is IPv4 [RFC 791].
+ @param IP The multicast IP address that is to be converted to a multicast
+ HW MAC address.
+ @param MAC The multicast HW MAC address that is to be generated from IP.
+
+ @retval EFI_SUCCESS The multicast IP address was mapped to the multicast
+ HW MAC address.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer
+ size needed to hold the statistics is returned in
+ StatisticsSize.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC)(
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN IPv6,
+ IN EFI_IP_ADDRESS *IP,
+ OUT EFI_MAC_ADDRESS *MAC
+ );
+
+/**
+ Performs read and write operations on the NVRAM device attached to a
+ network interface.
+
+ @param This The protocol instance pointer.
+ @param ReadWrite TRUE for read operations, FALSE for write operations.
+ @param Offset Byte offset in the NVRAM device at which to start the read or
+ write operation. This must be a multiple of NvRamAccessSize and
+ less than NvRamSize.
+ @param BufferSize The number of bytes to read or write from the NVRAM device.
+ This must also be a multiple of NvramAccessSize.
+ @param Buffer A pointer to the data buffer.
+
+ @retval EFI_SUCCESS The NVRAM access was performed.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_NETWORK_NVDATA)(
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN ReadWrite,
+ IN UINTN Offset,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Reads the current interrupt status and recycled transmit buffer status from
+ a network interface.
+
+ @param This The protocol instance pointer.
+ @param InterruptStatus A pointer to the bit mask of the currently active interrupts
+ If this is NULL, the interrupt status will not be read from
+ the device. If this is not NULL, the interrupt status will
+ be read from the device. When the interrupt status is read,
+ it will also be cleared. Clearing the transmit interrupt
+ does not empty the recycled transmit buffer array.
+ @param TxBuf Recycled transmit buffer address. The network interface will
+ not transmit if its internal recycled transmit buffer array
+ is full. Reading the transmit buffer does not clear the
+ transmit interrupt. If this is NULL, then the transmit buffer
+ status will not be read. If there are no transmit buffers to
+ recycle and TxBuf is not NULL, * TxBuf will be set to NULL.
+
+ @retval EFI_SUCCESS The status of the network interface was retrieved.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_NETWORK_GET_STATUS)(
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ OUT UINT32 *InterruptStatus OPTIONAL,
+ OUT VOID **TxBuf OPTIONAL
+ );
+
+/**
+ Places a packet in the transmit queue of a network interface.
+
+ @param This The protocol instance pointer.
+ @param HeaderSize The size, in bytes, of the media header to be filled in by
+ the Transmit() function. If HeaderSize is non-zero, then it
+ must be equal to This->Mode->MediaHeaderSize and the DestAddr
+ and Protocol parameters must not be NULL.
+ @param BufferSize The size, in bytes, of the entire packet (media header and
+ data) to be transmitted through the network interface.
+ @param Buffer A pointer to the packet (media header followed by data) to be
+ transmitted. This parameter cannot be NULL. If HeaderSize is zero,
+ then the media header in Buffer must already be filled in by the
+ caller. If HeaderSize is non-zero, then the media header will be
+ filled in by the Transmit() function.
+ @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter
+ is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then
+ This->Mode->CurrentAddress is used for the source HW MAC address.
+ @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this
+ parameter is ignored.
+ @param Protocol The type of header to build. If HeaderSize is zero, then this
+ parameter is ignored. See RFC 1700, section "Ether Types", for
+ examples.
+
+ @retval EFI_SUCCESS The packet was placed on the transmit queue.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_NETWORK_TRANSMIT)(
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN UINTN HeaderSize,
+ IN UINTN BufferSize,
+ IN VOID *Buffer,
+ IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
+ IN EFI_MAC_ADDRESS *DestAddr OPTIONAL,
+ IN UINT16 *Protocol OPTIONAL
+ );
+
+/**
+ Receives a packet from a network interface.
+
+ @param This The protocol instance pointer.
+ @param HeaderSize The size, in bytes, of the media header received on the network
+ interface. If this parameter is NULL, then the media header size
+ will not be returned.
+ @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in
+ bytes, of the packet that was received on the network interface.
+ @param Buffer A pointer to the data buffer to receive both the media header and
+ the data.
+ @param SrcAddr The source HW MAC address. If this parameter is NULL, the
+ HW MAC source address will not be extracted from the media
+ header.
+ @param DestAddr The destination HW MAC address. If this parameter is NULL,
+ the HW MAC destination address will not be extracted from the
+ media header.
+ @param Protocol The media header type. If this parameter is NULL, then the
+ protocol will not be extracted from the media header. See
+ RFC 1700 section "Ether Types" for examples.
+
+ @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has
+ been updated to the number of bytes received.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit
+ request.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIMPLE_NETWORK_RECEIVE)(
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ OUT UINTN *HeaderSize OPTIONAL,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer,
+ OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
+ OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL,
+ OUT UINT16 *Protocol OPTIONAL
+ );
+
+#define EFI_SIMPLE_NETWORK_PROTOCOL_REVISION 0x00010000
+
+//
+// Revision defined in EFI1.1
+//
+#define EFI_SIMPLE_NETWORK_INTERFACE_REVISION EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
+
+///
+/// The EFI_SIMPLE_NETWORK_PROTOCOL protocol is used to initialize access
+/// to a network adapter. Once the network adapter initializes,
+/// the EFI_SIMPLE_NETWORK_PROTOCOL protocol provides services that
+/// allow packets to be transmitted and received.
+///
+struct _EFI_SIMPLE_NETWORK_PROTOCOL {
+ ///
+ /// Revision of the EFI_SIMPLE_NETWORK_PROTOCOL. All future revisions must
+ /// be backwards compatible. If a future version is not backwards compatible
+ /// it is not the same GUID.
+ ///
+ UINT64 Revision;
+ EFI_SIMPLE_NETWORK_START Start;
+ EFI_SIMPLE_NETWORK_STOP Stop;
+ EFI_SIMPLE_NETWORK_INITIALIZE Initialize;
+ EFI_SIMPLE_NETWORK_RESET Reset;
+ EFI_SIMPLE_NETWORK_SHUTDOWN Shutdown;
+ EFI_SIMPLE_NETWORK_RECEIVE_FILTERS ReceiveFilters;
+ EFI_SIMPLE_NETWORK_STATION_ADDRESS StationAddress;
+ EFI_SIMPLE_NETWORK_STATISTICS Statistics;
+ EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC MCastIpToMac;
+ EFI_SIMPLE_NETWORK_NVDATA NvData;
+ EFI_SIMPLE_NETWORK_GET_STATUS GetStatus;
+ EFI_SIMPLE_NETWORK_TRANSMIT Transmit;
+ EFI_SIMPLE_NETWORK_RECEIVE Receive;
+ ///
+ /// Event used with WaitForEvent() to wait for a packet to be received.
+ ///
+ EFI_EVENT WaitForPacket;
+ ///
+ /// Pointer to the EFI_SIMPLE_NETWORK_MODE data for the device.
+ ///
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+};
+
+extern EFI_GUID gEfiSimpleNetworkProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/SimpleTextIn.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/SimpleTextIn.h
new file mode 100644
index 00000000..a89a9b4f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/SimpleTextIn.h
@@ -0,0 +1,138 @@
+/** @file
+ Simple Text Input protocol from the UEFI 2.0 specification.
+
+ Abstraction of a very simple input device like a keyboard or serial
+ terminal.
+
+ Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __SIMPLE_TEXT_IN_PROTOCOL_H__
+#define __SIMPLE_TEXT_IN_PROTOCOL_H__
+
+FILE_LICENCE ( BSD3 );
+
+#define EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID \
+ { \
+ 0x387477c1, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+ }
+
+typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
+
+///
+/// Protocol GUID name defined in EFI1.1.
+///
+#define SIMPLE_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID
+
+///
+/// Protocol name in EFI1.1 for backward-compatible.
+///
+typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL SIMPLE_INPUT_INTERFACE;
+
+///
+/// The keystroke information for the key that was pressed.
+///
+typedef struct {
+ UINT16 ScanCode;
+ CHAR16 UnicodeChar;
+} EFI_INPUT_KEY;
+
+//
+// Required unicode control chars
+//
+#define CHAR_NULL 0x0000
+#define CHAR_BACKSPACE 0x0008
+#define CHAR_TAB 0x0009
+#define CHAR_LINEFEED 0x000A
+#define CHAR_CARRIAGE_RETURN 0x000D
+
+//
+// EFI Scan codes
+//
+#define SCAN_NULL 0x0000
+#define SCAN_UP 0x0001
+#define SCAN_DOWN 0x0002
+#define SCAN_RIGHT 0x0003
+#define SCAN_LEFT 0x0004
+#define SCAN_HOME 0x0005
+#define SCAN_END 0x0006
+#define SCAN_INSERT 0x0007
+#define SCAN_DELETE 0x0008
+#define SCAN_PAGE_UP 0x0009
+#define SCAN_PAGE_DOWN 0x000A
+#define SCAN_F1 0x000B
+#define SCAN_F2 0x000C
+#define SCAN_F3 0x000D
+#define SCAN_F4 0x000E
+#define SCAN_F5 0x000F
+#define SCAN_F6 0x0010
+#define SCAN_F7 0x0011
+#define SCAN_F8 0x0012
+#define SCAN_F9 0x0013
+#define SCAN_F10 0x0014
+#define SCAN_F11 0x0015
+#define SCAN_F12 0x0016
+#define SCAN_ESC 0x0017
+
+/**
+ Reset the input device and optionally run diagnostics
+
+ @param This Protocol instance pointer.
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_INPUT_RESET)(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Reads the next keystroke from the input device. The WaitForKey Event can
+ be used to test for existence of a keystroke via WaitForEvent () call.
+
+ @param This Protocol instance pointer.
+ @param Key A pointer to a buffer that is filled in with the keystroke
+ information for the key that was pressed.
+
+ @retval EFI_SUCCESS The keystroke information was returned.
+ @retval EFI_NOT_READY There was no keystroke data available.
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
+ hardware errors.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_INPUT_READ_KEY)(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+ );
+
+///
+/// The EFI_SIMPLE_TEXT_INPUT_PROTOCOL is used on the ConsoleIn device.
+/// It is the minimum required protocol for ConsoleIn.
+///
+struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
+ EFI_INPUT_RESET Reset;
+ EFI_INPUT_READ_KEY ReadKeyStroke;
+ ///
+ /// Event to use with WaitForEvent() to wait for a key to be available
+ ///
+ EFI_EVENT WaitForKey;
+};
+
+extern EFI_GUID gEfiSimpleTextInProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/SimpleTextOut.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/SimpleTextOut.h
new file mode 100644
index 00000000..a79cf431
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Protocol/SimpleTextOut.h
@@ -0,0 +1,406 @@
+/** @file
+ Simple Text Out protocol from the UEFI 2.0 specification.
+
+ Abstraction of a very simple text based output device like VGA text mode or
+ a serial terminal. The Simple Text Out protocol instance can represent
+ a single hardware device or a virtual device that is an aggregation
+ of multiple physical devices.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __SIMPLE_TEXT_OUT_H__
+#define __SIMPLE_TEXT_OUT_H__
+
+FILE_LICENCE ( BSD3 );
+
+#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \
+ { \
+ 0x387477c2, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+ }
+
+///
+/// Protocol GUID defined in EFI1.1.
+///
+#define SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID
+
+typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
+
+///
+/// Backward-compatible with EFI1.1.
+///
+typedef EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SIMPLE_TEXT_OUTPUT_INTERFACE;
+
+//
+// Define's for required EFI Unicode Box Draw characters
+//
+#define BOXDRAW_HORIZONTAL 0x2500
+#define BOXDRAW_VERTICAL 0x2502
+#define BOXDRAW_DOWN_RIGHT 0x250c
+#define BOXDRAW_DOWN_LEFT 0x2510
+#define BOXDRAW_UP_RIGHT 0x2514
+#define BOXDRAW_UP_LEFT 0x2518
+#define BOXDRAW_VERTICAL_RIGHT 0x251c
+#define BOXDRAW_VERTICAL_LEFT 0x2524
+#define BOXDRAW_DOWN_HORIZONTAL 0x252c
+#define BOXDRAW_UP_HORIZONTAL 0x2534
+#define BOXDRAW_VERTICAL_HORIZONTAL 0x253c
+#define BOXDRAW_DOUBLE_HORIZONTAL 0x2550
+#define BOXDRAW_DOUBLE_VERTICAL 0x2551
+#define BOXDRAW_DOWN_RIGHT_DOUBLE 0x2552
+#define BOXDRAW_DOWN_DOUBLE_RIGHT 0x2553
+#define BOXDRAW_DOUBLE_DOWN_RIGHT 0x2554
+#define BOXDRAW_DOWN_LEFT_DOUBLE 0x2555
+#define BOXDRAW_DOWN_DOUBLE_LEFT 0x2556
+#define BOXDRAW_DOUBLE_DOWN_LEFT 0x2557
+#define BOXDRAW_UP_RIGHT_DOUBLE 0x2558
+#define BOXDRAW_UP_DOUBLE_RIGHT 0x2559
+#define BOXDRAW_DOUBLE_UP_RIGHT 0x255a
+#define BOXDRAW_UP_LEFT_DOUBLE 0x255b
+#define BOXDRAW_UP_DOUBLE_LEFT 0x255c
+#define BOXDRAW_DOUBLE_UP_LEFT 0x255d
+#define BOXDRAW_VERTICAL_RIGHT_DOUBLE 0x255e
+#define BOXDRAW_VERTICAL_DOUBLE_RIGHT 0x255f
+#define BOXDRAW_DOUBLE_VERTICAL_RIGHT 0x2560
+#define BOXDRAW_VERTICAL_LEFT_DOUBLE 0x2561
+#define BOXDRAW_VERTICAL_DOUBLE_LEFT 0x2562
+#define BOXDRAW_DOUBLE_VERTICAL_LEFT 0x2563
+#define BOXDRAW_DOWN_HORIZONTAL_DOUBLE 0x2564
+#define BOXDRAW_DOWN_DOUBLE_HORIZONTAL 0x2565
+#define BOXDRAW_DOUBLE_DOWN_HORIZONTAL 0x2566
+#define BOXDRAW_UP_HORIZONTAL_DOUBLE 0x2567
+#define BOXDRAW_UP_DOUBLE_HORIZONTAL 0x2568
+#define BOXDRAW_DOUBLE_UP_HORIZONTAL 0x2569
+#define BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE 0x256a
+#define BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL 0x256b
+#define BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL 0x256c
+
+//
+// EFI Required Block Elements Code Chart
+//
+#define BLOCKELEMENT_FULL_BLOCK 0x2588
+#define BLOCKELEMENT_LIGHT_SHADE 0x2591
+
+//
+// EFI Required Geometric Shapes Code Chart
+//
+#define GEOMETRICSHAPE_UP_TRIANGLE 0x25b2
+#define GEOMETRICSHAPE_RIGHT_TRIANGLE 0x25ba
+#define GEOMETRICSHAPE_DOWN_TRIANGLE 0x25bc
+#define GEOMETRICSHAPE_LEFT_TRIANGLE 0x25c4
+
+//
+// EFI Required Arrow shapes
+//
+#define ARROW_LEFT 0x2190
+#define ARROW_UP 0x2191
+#define ARROW_RIGHT 0x2192
+#define ARROW_DOWN 0x2193
+
+//
+// EFI Console Colours
+//
+#define EFI_BLACK 0x00
+#define EFI_BLUE 0x01
+#define EFI_GREEN 0x02
+#define EFI_CYAN (EFI_BLUE | EFI_GREEN)
+#define EFI_RED 0x04
+#define EFI_MAGENTA (EFI_BLUE | EFI_RED)
+#define EFI_BROWN (EFI_GREEN | EFI_RED)
+#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED)
+#define EFI_BRIGHT 0x08
+#define EFI_DARKGRAY (EFI_BRIGHT)
+#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT)
+#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT)
+#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT)
+#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT)
+#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT)
+#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT)
+#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT)
+
+#define EFI_TEXT_ATTR(f, b) ((f) | ((b) << 4))
+
+#define EFI_BACKGROUND_BLACK 0x00
+#define EFI_BACKGROUND_BLUE 0x10
+#define EFI_BACKGROUND_GREEN 0x20
+#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN)
+#define EFI_BACKGROUND_RED 0x40
+#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED)
+#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
+#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
+
+//
+// We currently define attributes from 0 - 7F for color manipulations
+// To internally handle the local display characteristics for a particular character,
+// Bit 7 signifies the local glyph representation for a character. If turned on, glyphs will be
+// pulled from the wide glyph database and will display locally as a wide character (16 X 19 versus 8 X 19)
+// If bit 7 is off, the narrow glyph database will be used. This does NOT affect information that is sent to
+// non-local displays, such as serial or LAN consoles.
+//
+#define EFI_WIDE_ATTRIBUTE 0x80
+
+/**
+ Reset the text output device hardware and optionaly run diagnostics
+
+ @param This The protocol instance pointer.
+ @param ExtendedVerification Driver may perform more exhaustive verfication
+ operation of the device during reset.
+
+ @retval EFI_SUCCESS The text output device was reset.
+ @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
+ could not be reset.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_RESET)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Write a string to the output device.
+
+ @param This The protocol instance pointer.
+ @param String The NULL-terminated string to be displayed on the output
+ device(s). All output devices must also support the Unicode
+ drawing character codes defined in this file.
+
+ @retval EFI_SUCCESS The string was output to the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
+ the text.
+ @retval EFI_UNSUPPORTED The output device's mode is not currently in a
+ defined text mode.
+ @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
+ characters in the string could not be
+ rendered and were skipped.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_STRING)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+ );
+
+/**
+ Verifies that all characters in a string can be output to the
+ target device.
+
+ @param This The protocol instance pointer.
+ @param String The NULL-terminated string to be examined for the output
+ device(s).
+
+ @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
+ @retval EFI_UNSUPPORTED Some of the characters in the string cannot be
+ rendered by one or more of the output devices mapped
+ by the EFI handle.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_TEST_STRING)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+ );
+
+/**
+ Returns information for an available text mode that the output device(s)
+ supports.
+
+ @param This The protocol instance pointer.
+ @param ModeNumber The mode number to return information on.
+ @param Columns Returns the geometry of the text output device for the
+ requested ModeNumber.
+ @param Rows Returns the geometry of the text output device for the
+ requested ModeNumber.
+
+ @retval EFI_SUCCESS The requested mode information was returned.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
+ @retval EFI_UNSUPPORTED The mode number was not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_QUERY_MODE)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber,
+ OUT UINTN *Columns,
+ OUT UINTN *Rows
+ );
+
+/**
+ Sets the output device(s) to a specified mode.
+
+ @param This The protocol instance pointer.
+ @param ModeNumber The mode number to set.
+
+ @retval EFI_SUCCESS The requested text mode was set.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
+ @retval EFI_UNSUPPORTED The mode number was not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_SET_MODE)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber
+ );
+
+/**
+ Sets the background and foreground colors for the OutputString () and
+ ClearScreen () functions.
+
+ @param This The protocol instance pointer.
+ @param Attribute The attribute to set. Bits 0..3 are the foreground color, and
+ bits 4..6 are the background color. All other bits are undefined
+ and must be zero. The valid Attributes are defined in this file.
+
+ @retval EFI_SUCCESS The attribute was set.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
+ @retval EFI_UNSUPPORTED The attribute requested is not defined.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_SET_ATTRIBUTE)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Attribute
+ );
+
+/**
+ Clears the output device(s) display to the currently selected background
+ color.
+
+ @param This The protocol instance pointer.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
+ @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_CLEAR_SCREEN)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
+ );
+
+/**
+ Sets the current coordinates of the cursor position
+
+ @param This The protocol instance pointer.
+ @param Column The position to set the cursor to. Must be greater than or
+ equal to zero and less than the number of columns and rows
+ by QueryMode ().
+ @param Row The position to set the cursor to. Must be greater than or
+ equal to zero and less than the number of columns and rows
+ by QueryMode ().
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
+ @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
+ cursor position is invalid for the current mode.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_SET_CURSOR_POSITION)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Column,
+ IN UINTN Row
+ );
+
+/**
+ Makes the cursor visible or invisible
+
+ @param This The protocol instance pointer.
+ @param Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
+ set to be invisible.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the
+ request, or the device does not support changing
+ the cursor mode.
+ @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TEXT_ENABLE_CURSOR)(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN Visible
+ );
+
+/**
+ @par Data Structure Description:
+ Mode Structure pointed to by Simple Text Out protocol.
+**/
+typedef struct {
+ ///
+ /// The number of modes supported by QueryMode () and SetMode ().
+ ///
+ INT32 MaxMode;
+
+ //
+ // current settings
+ //
+
+ ///
+ /// The text mode of the output device(s).
+ ///
+ INT32 Mode;
+ ///
+ /// The current character output attribute.
+ ///
+ INT32 Attribute;
+ ///
+ /// The cursor's column.
+ ///
+ INT32 CursorColumn;
+ ///
+ /// The cursor's row.
+ ///
+ INT32 CursorRow;
+ ///
+ /// The cursor is currently visbile or not.
+ ///
+ BOOLEAN CursorVisible;
+} EFI_SIMPLE_TEXT_OUTPUT_MODE;
+
+///
+/// The SIMPLE_TEXT_OUTPUT protocol is used to control text-based output devices.
+/// It is the minimum required protocol for any handle supplied as the ConsoleOut
+/// or StandardError device. In addition, the minimum supported text mode of such
+/// devices is at least 80 x 25 characters.
+///
+struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
+ EFI_TEXT_RESET Reset;
+
+ EFI_TEXT_STRING OutputString;
+ EFI_TEXT_TEST_STRING TestString;
+
+ EFI_TEXT_QUERY_MODE QueryMode;
+ EFI_TEXT_SET_MODE SetMode;
+ EFI_TEXT_SET_ATTRIBUTE SetAttribute;
+
+ EFI_TEXT_CLEAR_SCREEN ClearScreen;
+ EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition;
+ EFI_TEXT_ENABLE_CURSOR EnableCursor;
+
+ ///
+ /// Pointer to SIMPLE_TEXT_OUTPUT_MODE data.
+ ///
+ EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
+};
+
+extern EFI_GUID gEfiSimpleTextOutProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi.h
new file mode 100644
index 00000000..a5a25a9c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi.h
@@ -0,0 +1,29 @@
+/** @file
+
+ Root include file for Mde Package UEFI, UEFI_APPLICATION type modules.
+
+ This is the include file for any module of type UEFI and UEFI_APPLICATION. Uefi modules only use
+ types defined via this include file and can be ported easily to any
+ environment.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PI_UEFI_H__
+#define __PI_UEFI_H__
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/Uefi/UefiBaseType.h>
+#include <ipxe/efi/Uefi/UefiSpec.h>
+
+#endif
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiBaseType.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiBaseType.h
new file mode 100644
index 00000000..2c63aa6f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiBaseType.h
@@ -0,0 +1,287 @@
+/** @file
+ Defines data types and constants introduced in UEFI.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __UEFI_BASETYPE_H__
+#define __UEFI_BASETYPE_H__
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/Base.h>
+
+//
+// Basic data type definitions introduced in UEFI.
+//
+
+///
+/// 128-bit buffer containing a unique identifier value.
+///
+typedef GUID EFI_GUID;
+///
+/// Function return status for EFI API.
+///
+typedef RETURN_STATUS EFI_STATUS;
+///
+/// A collection of related interfaces.
+///
+typedef VOID *EFI_HANDLE;
+///
+/// Handle to an event structure.
+///
+typedef VOID *EFI_EVENT;
+///
+/// Task priority level.
+///
+typedef UINTN EFI_TPL;
+///
+/// Logical block address.
+///
+typedef UINT64 EFI_LBA;
+
+///
+/// 64-bit physical memory address.
+///
+typedef UINT64 EFI_PHYSICAL_ADDRESS;
+
+///
+/// 64-bit virtual memory address.
+///
+typedef UINT64 EFI_VIRTUAL_ADDRESS;
+
+///
+/// EFI Time Abstraction:
+/// Year: 1900 - 9999
+/// Month: 1 - 12
+/// Day: 1 - 31
+/// Hour: 0 - 23
+/// Minute: 0 - 59
+/// Second: 0 - 59
+/// Nanosecond: 0 - 999,999,999
+/// TimeZone: -1440 to 1440 or 2047
+///
+typedef struct {
+ UINT16 Year;
+ UINT8 Month;
+ UINT8 Day;
+ UINT8 Hour;
+ UINT8 Minute;
+ UINT8 Second;
+ UINT8 Pad1;
+ UINT32 Nanosecond;
+ INT16 TimeZone;
+ UINT8 Daylight;
+ UINT8 Pad2;
+} EFI_TIME;
+
+
+///
+/// 4-byte buffer. An IPv4 internet protocol address.
+///
+typedef struct {
+ UINT8 Addr[4];
+} EFI_IPv4_ADDRESS;
+
+///
+/// 16-byte buffer. An IPv6 internet protocol address.
+///
+typedef struct {
+ UINT8 Addr[16];
+} EFI_IPv6_ADDRESS;
+
+///
+/// 32-byte buffer containing a network Media Access Control address.
+///
+typedef struct {
+ UINT8 Addr[32];
+} EFI_MAC_ADDRESS;
+
+///
+/// 16-byte buffer aligned on a 4-byte boundary.
+/// An IPv4 or IPv6 internet protocol address.
+///
+typedef union {
+ UINT32 Addr[4];
+ EFI_IPv4_ADDRESS v4;
+ EFI_IPv6_ADDRESS v6;
+} EFI_IP_ADDRESS;
+
+
+///
+/// Enumeration of EFI_STATUS.
+///@{
+#define EFI_SUCCESS RETURN_SUCCESS
+#define EFI_LOAD_ERROR RETURN_LOAD_ERROR
+#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER
+#define EFI_UNSUPPORTED RETURN_UNSUPPORTED
+#define EFI_BAD_BUFFER_SIZE RETURN_BAD_BUFFER_SIZE
+#define EFI_BUFFER_TOO_SMALL RETURN_BUFFER_TOO_SMALL
+#define EFI_NOT_READY RETURN_NOT_READY
+#define EFI_DEVICE_ERROR RETURN_DEVICE_ERROR
+#define EFI_WRITE_PROTECTED RETURN_WRITE_PROTECTED
+#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES
+#define EFI_VOLUME_CORRUPTED RETURN_VOLUME_CORRUPTED
+#define EFI_VOLUME_FULL RETURN_VOLUME_FULL
+#define EFI_NO_MEDIA RETURN_NO_MEDIA
+#define EFI_MEDIA_CHANGED RETURN_MEDIA_CHANGED
+#define EFI_NOT_FOUND RETURN_NOT_FOUND
+#define EFI_ACCESS_DENIED RETURN_ACCESS_DENIED
+#define EFI_NO_RESPONSE RETURN_NO_RESPONSE
+#define EFI_NO_MAPPING RETURN_NO_MAPPING
+#define EFI_TIMEOUT RETURN_TIMEOUT
+#define EFI_NOT_STARTED RETURN_NOT_STARTED
+#define EFI_ALREADY_STARTED RETURN_ALREADY_STARTED
+#define EFI_ABORTED RETURN_ABORTED
+#define EFI_ICMP_ERROR RETURN_ICMP_ERROR
+#define EFI_TFTP_ERROR RETURN_TFTP_ERROR
+#define EFI_PROTOCOL_ERROR RETURN_PROTOCOL_ERROR
+#define EFI_INCOMPATIBLE_VERSION RETURN_INCOMPATIBLE_VERSION
+#define EFI_SECURITY_VIOLATION RETURN_SECURITY_VIOLATION
+#define EFI_CRC_ERROR RETURN_CRC_ERROR
+#define EFI_END_OF_MEDIA RETURN_END_OF_MEDIA
+#define EFI_END_OF_FILE RETURN_END_OF_FILE
+#define EFI_INVALID_LANGUAGE RETURN_INVALID_LANGUAGE
+
+#define EFI_WARN_UNKNOWN_GLYPH RETURN_WARN_UNKNOWN_GLYPH
+#define EFI_WARN_DELETE_FAILURE RETURN_WARN_DELETE_FAILURE
+#define EFI_WARN_WRITE_FAILURE RETURN_WARN_WRITE_FAILURE
+#define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL
+///@}
+
+///
+/// Define macro to encode the status code.
+///
+#define EFIERR(_a) ENCODE_ERROR(_a)
+
+#define EFI_ERROR(A) RETURN_ERROR(A)
+
+///
+/// ICMP error definitions
+///@{
+#define EFI_NETWORK_UNREACHABLE EFIERR(100)
+#define EFI_HOST_UNREACHABLE EFIERR(101)
+#define EFI_PROTOCOL_UNREACHABLE EFIERR(102)
+#define EFI_PORT_UNREACHABLE EFIERR(103)
+///@}
+
+///
+/// Tcp connection status definitions
+///@{
+#define EFI_CONNECTION_FIN EFIERR(104)
+#define EFI_CONNECTION_RESET EFIERR(105)
+#define EFI_CONNECTION_REFUSED EFIERR(106)
+///@}
+
+//
+// The EFI memory allocation functions work in units of EFI_PAGEs that are
+// 4KB. This should in no way be confused with the page size of the processor.
+// An EFI_PAGE is just the quanta of memory in EFI.
+//
+#define EFI_PAGE_SIZE SIZE_4KB
+#define EFI_PAGE_MASK 0xFFF
+#define EFI_PAGE_SHIFT 12
+
+/**
+ Macro that converts a size, in bytes, to a number of EFI_PAGESs.
+
+ @param Size A size in bytes. This parameter is assumed to be type UINTN.
+ Passing in a parameter that is larger than UINTN may produce
+ unexpected results.
+
+ @return The number of EFI_PAGESs associated with the number of bytes specified
+ by Size.
+
+**/
+#define EFI_SIZE_TO_PAGES(Size) (((Size) >> EFI_PAGE_SHIFT) + (((Size) & EFI_PAGE_MASK) ? 1 : 0))
+
+/**
+ Macro that converts a number of EFI_PAGEs to a size in bytes.
+
+ @param Pages The number of EFI_PAGES. This parameter is assumed to be
+ type UINTN. Passing in a parameter that is larger than
+ UINTN may produce unexpected results.
+
+ @return The number of bytes associated with the number of EFI_PAGEs specified
+ by Pages.
+
+**/
+#define EFI_PAGES_TO_SIZE(Pages) ((Pages) << EFI_PAGE_SHIFT)
+
+///
+/// PE32+ Machine type for IA32 UEFI images.
+///
+#define EFI_IMAGE_MACHINE_IA32 0x014C
+
+///
+/// PE32+ Machine type for IA64 UEFI images.
+///
+#define EFI_IMAGE_MACHINE_IA64 0x0200
+
+///
+/// PE32+ Machine type for EBC UEFI images.
+///
+#define EFI_IMAGE_MACHINE_EBC 0x0EBC
+
+///
+/// PE32+ Machine type for X64 UEFI images.
+///
+#define EFI_IMAGE_MACHINE_X64 0x8664
+
+///
+/// PE32+ Machine type for ARM mixed ARM and Thumb/Thumb2 images.
+///
+#define EFI_IMAGE_MACHINE_ARMTHUMB_MIXED 0x01C2
+
+
+#if defined (MDE_CPU_IA32)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_X64)
+
+#elif defined (MDE_CPU_IPF)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_IA64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE)
+
+#elif defined (MDE_CPU_X64)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_IA32)
+
+#elif defined (MDE_CPU_ARM)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED)
+
+#elif defined (MDE_CPU_EBC)
+
+///
+/// This is just to make sure you can cross compile with the EBC compiler.
+/// It does not make sense to have a PE loader coded in EBC.
+///
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_EBC)
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE)
+
+#else
+#error Unknown Processor Type
+#endif
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiGpt.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiGpt.h
new file mode 100644
index 00000000..26af39f5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiGpt.h
@@ -0,0 +1,142 @@
+/** @file
+ EFI Guid Partition Table Format Definition.
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __UEFI_GPT_H__
+#define __UEFI_GPT_H__
+
+FILE_LICENCE ( BSD3 );
+
+///
+/// The primary GUID Partition Table Header must be
+/// located in LBA 1 (i.e., the second logical block).
+///
+#define PRIMARY_PART_HEADER_LBA 1
+///
+/// EFI Partition Table Signature: "EFI PART".
+///
+#define EFI_PTAB_HEADER_ID SIGNATURE_64 ('E','F','I',' ','P','A','R','T')
+
+#pragma pack(1)
+
+///
+/// GPT Partition Table Header.
+///
+typedef struct {
+ ///
+ /// The table header for the GPT partition Table.
+ /// This header contains EFI_PTAB_HEADER_ID.
+ ///
+ EFI_TABLE_HEADER Header;
+ ///
+ /// The LBA that contains this data structure.
+ ///
+ EFI_LBA MyLBA;
+ ///
+ /// LBA address of the alternate GUID Partition Table Header.
+ ///
+ EFI_LBA AlternateLBA;
+ ///
+ /// The first usable logical block that may be used
+ /// by a partition described by a GUID Partition Entry.
+ ///
+ EFI_LBA FirstUsableLBA;
+ ///
+ /// The last usable logical block that may be used
+ /// by a partition described by a GUID Partition Entry.
+ ///
+ EFI_LBA LastUsableLBA;
+ ///
+ /// GUID that can be used to uniquely identify the disk.
+ ///
+ EFI_GUID DiskGUID;
+ ///
+ /// The starting LBA of the GUID Partition Entry array.
+ ///
+ EFI_LBA PartitionEntryLBA;
+ ///
+ /// The number of Partition Entries in the GUID Partition Entry array.
+ ///
+ UINT32 NumberOfPartitionEntries;
+ ///
+ /// The size, in bytes, of each the GUID Partition
+ /// Entry structures in the GUID Partition Entry
+ /// array. Must be a multiple of 8.
+ ///
+ UINT32 SizeOfPartitionEntry;
+ ///
+ /// The CRC32 of the GUID Partition Entry array.
+ /// Starts at PartitionEntryLBA and is
+ /// computed over a byte length of
+ /// NumberOfPartitionEntries * SizeOfPartitionEntry.
+ ///
+ UINT32 PartitionEntryArrayCRC32;
+} EFI_PARTITION_TABLE_HEADER;
+
+///
+/// GPT Partition Entry.
+///
+typedef struct {
+ ///
+ /// Unique ID that defines the purpose and type of this Partition. A value of
+ /// zero defines that this partition entry is not being used.
+ ///
+ EFI_GUID PartitionTypeGUID;
+ ///
+ /// GUID that is unique for every partition entry. Every partition ever
+ /// created will have a unique GUID.
+ /// This GUID must be assigned when the GUID Partition Entry is created.
+ ///
+ EFI_GUID UniquePartitionGUID;
+ ///
+ /// Starting LBA of the partition defined by this entry
+ ///
+ EFI_LBA StartingLBA;
+ ///
+ /// Ending LBA of the partition defined by this entry.
+ ///
+ EFI_LBA EndingLBA;
+ ///
+ /// Attribute bits, all bits reserved by UEFI
+ /// Bit 0: If this bit is set, the partition is required for the platform to function. The owner/creator of the
+ /// partition indicates that deletion or modification of the contents can result in loss of platform
+ /// features or failure for the platform to boot or operate. The system cannot function normally if
+ /// this partition is removed, and it should be considered part of the hardware of the system.
+ /// Actions such as running diagnostics, system recovery, or even OS install or boot, could
+ /// potentially stop working if this partition is removed. Unless OS software or firmware
+ /// recognizes this partition, it should never be removed or modified as the UEFI firmware or
+ /// platform hardware may become non-functional.
+ /// Bit 1: If this bit is set, then firmware must not produce an EFI_BLOCK_IO_PROTOCOL device for
+ /// this partition. By not producing an EFI_BLOCK_IO_PROTOCOL partition, file system
+ /// mappings will not be created for this partition in UEFI.
+ /// Bit 2: This bit is set aside to let systems with traditional PC-AT BIOS firmware implementations
+ /// inform certain limited, special-purpose software running on these systems that a GPT
+ /// partition may be bootable. The UEFI boot manager must ignore this bit when selecting
+ /// a UEFI-compliant application, e.g., an OS loader.
+ /// Bits 3-47: Undefined and must be zero. Reserved for expansion by future versions of the UEFI
+ /// specification.
+ /// Bits 48-63: Reserved for GUID specific use. The use of these bits will vary depending on the
+ /// PartitionTypeGUID. Only the owner of the PartitionTypeGUID is allowed
+ /// to modify these bits. They must be preserved if Bits 0-47 are modified..
+ ///
+ UINT64 Attributes;
+ ///
+ /// Null-terminated name of the partition.
+ ///
+ CHAR16 PartitionName[36];
+} EFI_PARTITION_ENTRY;
+
+#pragma pack()
+#endif
+
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h
new file mode 100644
index 00000000..6b6d1e06
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h
@@ -0,0 +1,2068 @@
+/** @file
+ This file defines the encoding for the VFR (Visual Form Representation) language.
+ IFR is primarily consumed by the EFI presentation engine, and produced by EFI
+ internal application and drivers as well as all add-in card option-ROM drivers
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ These definitions are from UEFI 2.1 and 2.2.
+
+**/
+
+#ifndef __UEFI_INTERNAL_FORMREPRESENTATION_H__
+#define __UEFI_INTERNAL_FORMREPRESENTATION_H__
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/Guid/HiiFormMapMethodGuid.h>
+
+///
+/// The following types are currently defined:
+///
+typedef VOID* EFI_HII_HANDLE;
+typedef CHAR16* EFI_STRING;
+typedef UINT16 EFI_IMAGE_ID;
+typedef UINT16 EFI_QUESTION_ID;
+typedef UINT16 EFI_STRING_ID;
+typedef UINT16 EFI_FORM_ID;
+typedef UINT16 EFI_VARSTORE_ID;
+typedef UINT16 EFI_ANIMATION_ID;
+
+typedef UINT16 EFI_DEFAULT_ID;
+
+typedef UINT32 EFI_HII_FONT_STYLE;
+
+
+
+#pragma pack(1)
+
+//
+// Definitions for Package Lists and Package Headers
+// Section 27.3.1
+//
+
+///
+/// The header found at the start of each package list.
+///
+typedef struct {
+ EFI_GUID PackageListGuid;
+ UINT32 PackageLength;
+} EFI_HII_PACKAGE_LIST_HEADER;
+
+///
+/// The header found at the start of each package.
+///
+typedef struct {
+ UINT32 Length:24;
+ UINT32 Type:8;
+ // UINT8 Data[...];
+} EFI_HII_PACKAGE_HEADER;
+
+//
+// Value of HII package type
+//
+#define EFI_HII_PACKAGE_TYPE_ALL 0x00
+#define EFI_HII_PACKAGE_TYPE_GUID 0x01
+#define EFI_HII_PACKAGE_FORMS 0x02
+#define EFI_HII_PACKAGE_STRINGS 0x04
+#define EFI_HII_PACKAGE_FONTS 0x05
+#define EFI_HII_PACKAGE_IMAGES 0x06
+#define EFI_HII_PACKAGE_SIMPLE_FONTS 0x07
+#define EFI_HII_PACKAGE_DEVICE_PATH 0x08
+#define EFI_HII_PACKAGE_KEYBOARD_LAYOUT 0x09
+#define EFI_HII_PACKAGE_ANIMATIONS 0x0A
+#define EFI_HII_PACKAGE_END 0xDF
+#define EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN 0xE0
+#define EFI_HII_PACKAGE_TYPE_SYSTEM_END 0xFF
+
+//
+// Definitions for Simplified Font Package
+//
+
+///
+/// Contents of EFI_NARROW_GLYPH.Attributes.
+///@{
+#define EFI_GLYPH_NON_SPACING 0x01
+#define EFI_GLYPH_WIDE 0x02
+#define EFI_GLYPH_HEIGHT 19
+#define EFI_GLYPH_WIDTH 8
+///@}
+
+///
+/// The EFI_NARROW_GLYPH has a preferred dimension (w x h) of 8 x 19 pixels.
+///
+typedef struct {
+ ///
+ /// The Unicode representation of the glyph. The term weight is the
+ /// technical term for a character code.
+ ///
+ CHAR16 UnicodeWeight;
+ ///
+ /// The data element containing the glyph definitions.
+ ///
+ UINT8 Attributes;
+ ///
+ /// The column major glyph representation of the character. Bits
+ /// with values of one indicate that the corresponding pixel is to be
+ /// on when normally displayed; those with zero are off.
+ ///
+ UINT8 GlyphCol1[EFI_GLYPH_HEIGHT];
+} EFI_NARROW_GLYPH;
+
+///
+/// The EFI_WIDE_GLYPH has a preferred dimension (w x h) of 16 x 19 pixels, which is large enough
+/// to accommodate logographic characters.
+///
+typedef struct {
+ ///
+ /// The Unicode representation of the glyph. The term weight is the
+ /// technical term for a character code.
+ ///
+ CHAR16 UnicodeWeight;
+ ///
+ /// The data element containing the glyph definitions.
+ ///
+ UINT8 Attributes;
+ ///
+ /// The column major glyph representation of the character. Bits
+ /// with values of one indicate that the corresponding pixel is to be
+ /// on when normally displayed; those with zero are off.
+ ///
+ UINT8 GlyphCol1[EFI_GLYPH_HEIGHT];
+ ///
+ /// The column major glyph representation of the character. Bits
+ /// with values of one indicate that the corresponding pixel is to be
+ /// on when normally displayed; those with zero are off.
+ ///
+ UINT8 GlyphCol2[EFI_GLYPH_HEIGHT];
+ ///
+ /// Ensures that sizeof (EFI_WIDE_GLYPH) is twice the
+ /// sizeof (EFI_NARROW_GLYPH). The contents of Pad must
+ /// be zero.
+ ///
+ UINT8 Pad[3];
+} EFI_WIDE_GLYPH;
+
+///
+/// A simplified font package consists of a font header
+/// followed by a series of glyph structures.
+///
+typedef struct _EFI_HII_SIMPLE_FONT_PACKAGE_HDR {
+ EFI_HII_PACKAGE_HEADER Header;
+ UINT16 NumberOfNarrowGlyphs;
+ UINT16 NumberOfWideGlyphs;
+ // EFI_NARROW_GLYPH NarrowGlyphs[];
+ // EFI_WIDE_GLYPH WideGlyphs[];
+} EFI_HII_SIMPLE_FONT_PACKAGE_HDR;
+
+//
+// Definitions for Font Package
+// Section 27.3.3
+//
+
+//
+// Value for font style
+//
+#define EFI_HII_FONT_STYLE_NORMAL 0x00000000
+#define EFI_HII_FONT_STYLE_BOLD 0x00000001
+#define EFI_HII_FONT_STYLE_ITALIC 0x00000002
+#define EFI_HII_FONT_STYLE_EMBOSS 0x00010000
+#define EFI_HII_FONT_STYLE_OUTLINE 0x00020000
+#define EFI_HII_FONT_STYLE_SHADOW 0x00040000
+#define EFI_HII_FONT_STYLE_UNDERLINE 0x00080000
+#define EFI_HII_FONT_STYLE_DBL_UNDER 0x00100000
+
+typedef struct _EFI_HII_GLYPH_INFO {
+ UINT16 Width;
+ UINT16 Height;
+ INT16 OffsetX;
+ INT16 OffsetY;
+ INT16 AdvanceX;
+} EFI_HII_GLYPH_INFO;
+
+///
+/// The fixed header consists of a standard record header,
+/// then the character values in this section, the flags
+/// (including the encoding method) and the offsets of the glyph
+/// information, the glyph bitmaps and the character map.
+///
+typedef struct _EFI_HII_FONT_PACKAGE_HDR {
+ EFI_HII_PACKAGE_HEADER Header;
+ UINT32 HdrSize;
+ UINT32 GlyphBlockOffset;
+ EFI_HII_GLYPH_INFO Cell;
+ EFI_HII_FONT_STYLE FontStyle;
+ CHAR16 FontFamily[1];
+} EFI_HII_FONT_PACKAGE_HDR;
+
+//
+// Value of different glyph info block types
+//
+#define EFI_HII_GIBT_END 0x00
+#define EFI_HII_GIBT_GLYPH 0x10
+#define EFI_HII_GIBT_GLYPHS 0x11
+#define EFI_HII_GIBT_GLYPH_DEFAULT 0x12
+#define EFI_HII_GIBT_GLYPHS_DEFAULT 0x13
+#define EFI_HII_GIBT_DUPLICATE 0x20
+#define EFI_HII_GIBT_SKIP2 0x21
+#define EFI_HII_GIBT_SKIP1 0x22
+#define EFI_HII_GIBT_DEFAULTS 0x23
+#define EFI_HII_GIBT_EXT1 0x30
+#define EFI_HII_GIBT_EXT2 0x31
+#define EFI_HII_GIBT_EXT4 0x32
+
+typedef struct _EFI_HII_GLYPH_BLOCK {
+ UINT8 BlockType;
+} EFI_HII_GLYPH_BLOCK;
+
+//
+// Definition of different glyph info block types
+//
+
+typedef struct _EFI_HII_GIBT_DEFAULTS_BLOCK {
+ EFI_HII_GLYPH_BLOCK Header;
+ EFI_HII_GLYPH_INFO Cell;
+} EFI_HII_GIBT_DEFAULTS_BLOCK;
+
+typedef struct _EFI_HII_GIBT_DUPLICATE_BLOCK {
+ EFI_HII_GLYPH_BLOCK Header;
+ CHAR16 CharValue;
+} EFI_HII_GIBT_DUPLICATE_BLOCK;
+
+typedef struct _EFI_GLYPH_GIBT_END_BLOCK {
+ EFI_HII_GLYPH_BLOCK Header;
+} EFI_GLYPH_GIBT_END_BLOCK;
+
+typedef struct _EFI_HII_GIBT_EXT1_BLOCK {
+ EFI_HII_GLYPH_BLOCK Header;
+ UINT8 BlockType2;
+ UINT8 Length;
+} EFI_HII_GIBT_EXT1_BLOCK;
+
+typedef struct _EFI_HII_GIBT_EXT2_BLOCK {
+ EFI_HII_GLYPH_BLOCK Header;
+ UINT8 BlockType2;
+ UINT16 Length;
+} EFI_HII_GIBT_EXT2_BLOCK;
+
+typedef struct _EFI_HII_GIBT_EXT4_BLOCK {
+ EFI_HII_GLYPH_BLOCK Header;
+ UINT8 BlockType2;
+ UINT32 Length;
+} EFI_HII_GIBT_EXT4_BLOCK;
+
+typedef struct _EFI_HII_GIBT_GLYPH_BLOCK {
+ EFI_HII_GLYPH_BLOCK Header;
+ EFI_HII_GLYPH_INFO Cell;
+ UINT8 BitmapData[1];
+} EFI_HII_GIBT_GLYPH_BLOCK;
+
+typedef struct _EFI_HII_GIBT_GLYPHS_BLOCK {
+ EFI_HII_GLYPH_BLOCK Header;
+ EFI_HII_GLYPH_INFO Cell;
+ UINT16 Count;
+ UINT8 BitmapData[1];
+} EFI_HII_GIBT_GLYPHS_BLOCK;
+
+typedef struct _EFI_HII_GIBT_GLYPH_DEFAULT_BLOCK {
+ EFI_HII_GLYPH_BLOCK Header;
+ UINT8 BitmapData[1];
+} EFI_HII_GIBT_GLYPH_DEFAULT_BLOCK;
+
+typedef struct _EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK {
+ EFI_HII_GLYPH_BLOCK Header;
+ UINT16 Count;
+ UINT8 BitmapData[1];
+} EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK;
+
+typedef struct _EFI_HII_GIBT_SKIP1_BLOCK {
+ EFI_HII_GLYPH_BLOCK Header;
+ UINT8 SkipCount;
+} EFI_HII_GIBT_SKIP1_BLOCK;
+
+typedef struct _EFI_HII_GIBT_SKIP2_BLOCK {
+ EFI_HII_GLYPH_BLOCK Header;
+ UINT16 SkipCount;
+} EFI_HII_GIBT_SKIP2_BLOCK;
+
+//
+// Definitions for Device Path Package
+// Section 27.3.4
+//
+
+///
+/// The device path package is used to carry a device path
+/// associated with the package list.
+///
+typedef struct _EFI_HII_DEVICE_PATH_PACKAGE_HDR {
+ EFI_HII_PACKAGE_HEADER Header;
+ // EFI_DEVICE_PATH_PROTOCOL DevicePath[];
+} EFI_HII_DEVICE_PATH_PACKAGE_HDR;
+
+//
+// Definitions for GUID Package
+// Section 27.3.5
+//
+
+///
+/// The GUID package is used to carry data where the format is defined by a GUID.
+///
+typedef struct _EFI_HII_GUID_PACKAGE_HDR {
+ EFI_HII_PACKAGE_HEADER Header;
+ EFI_GUID Guid;
+ // Data per GUID definition may follow
+} EFI_HII_GUID_PACKAGE_HDR;
+
+//
+// Definitions for String Package
+// Section 27.3.6
+//
+
+#define UEFI_CONFIG_LANG "x-UEFI"
+#define UEFI_CONFIG_LANG_2 "x-i-UEFI"
+
+///
+/// The fixed header consists of a standard record header and then the string identifiers
+/// contained in this section and the offsets of the string and language information.
+///
+typedef struct _EFI_HII_STRING_PACKAGE_HDR {
+ EFI_HII_PACKAGE_HEADER Header;
+ UINT32 HdrSize;
+ UINT32 StringInfoOffset;
+ CHAR16 LanguageWindow[16];
+ EFI_STRING_ID LanguageName;
+ CHAR8 Language[1];
+} EFI_HII_STRING_PACKAGE_HDR;
+
+typedef struct {
+ UINT8 BlockType;
+} EFI_HII_STRING_BLOCK;
+
+//
+// Value of different string information block types
+//
+#define EFI_HII_SIBT_END 0x00
+#define EFI_HII_SIBT_STRING_SCSU 0x10
+#define EFI_HII_SIBT_STRING_SCSU_FONT 0x11
+#define EFI_HII_SIBT_STRINGS_SCSU 0x12
+#define EFI_HII_SIBT_STRINGS_SCSU_FONT 0x13
+#define EFI_HII_SIBT_STRING_UCS2 0x14
+#define EFI_HII_SIBT_STRING_UCS2_FONT 0x15
+#define EFI_HII_SIBT_STRINGS_UCS2 0x16
+#define EFI_HII_SIBT_STRINGS_UCS2_FONT 0x17
+#define EFI_HII_SIBT_DUPLICATE 0x20
+#define EFI_HII_SIBT_SKIP2 0x21
+#define EFI_HII_SIBT_SKIP1 0x22
+#define EFI_HII_SIBT_EXT1 0x30
+#define EFI_HII_SIBT_EXT2 0x31
+#define EFI_HII_SIBT_EXT4 0x32
+#define EFI_HII_SIBT_FONT 0x40
+
+//
+// Definition of different string information block types
+//
+
+typedef struct _EFI_HII_SIBT_DUPLICATE_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ EFI_STRING_ID StringId;
+} EFI_HII_SIBT_DUPLICATE_BLOCK;
+
+typedef struct _EFI_HII_SIBT_END_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+} EFI_HII_SIBT_END_BLOCK;
+
+typedef struct _EFI_HII_SIBT_EXT1_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ UINT8 BlockType2;
+ UINT8 Length;
+} EFI_HII_SIBT_EXT1_BLOCK;
+
+typedef struct _EFI_HII_SIBT_EXT2_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ UINT8 BlockType2;
+ UINT16 Length;
+} EFI_HII_SIBT_EXT2_BLOCK;
+
+typedef struct _EFI_HII_SIBT_EXT4_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ UINT8 BlockType2;
+ UINT32 Length;
+} EFI_HII_SIBT_EXT4_BLOCK;
+
+typedef struct _EFI_HII_SIBT_FONT_BLOCK {
+ EFI_HII_SIBT_EXT2_BLOCK Header;
+ UINT8 FontId;
+ UINT16 FontSize;
+ EFI_HII_FONT_STYLE FontStyle;
+ CHAR16 FontName[1];
+} EFI_HII_SIBT_FONT_BLOCK;
+
+typedef struct _EFI_HII_SIBT_SKIP1_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ UINT8 SkipCount;
+} EFI_HII_SIBT_SKIP1_BLOCK;
+
+typedef struct _EFI_HII_SIBT_SKIP2_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ UINT16 SkipCount;
+} EFI_HII_SIBT_SKIP2_BLOCK;
+
+typedef struct _EFI_HII_SIBT_STRING_SCSU_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ UINT8 StringText[1];
+} EFI_HII_SIBT_STRING_SCSU_BLOCK;
+
+typedef struct _EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ UINT8 FontIdentifier;
+ UINT8 StringText[1];
+} EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK;
+
+typedef struct _EFI_HII_SIBT_STRINGS_SCSU_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ UINT16 StringCount;
+ UINT8 StringText[1];
+} EFI_HII_SIBT_STRINGS_SCSU_BLOCK;
+
+typedef struct _EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ UINT8 FontIdentifier;
+ UINT16 StringCount;
+ UINT8 StringText[1];
+} EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK;
+
+typedef struct _EFI_HII_SIBT_STRING_UCS2_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ CHAR16 StringText[1];
+} EFI_HII_SIBT_STRING_UCS2_BLOCK;
+
+typedef struct _EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ UINT8 FontIdentifier;
+ CHAR16 StringText[1];
+} EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK;
+
+typedef struct _EFI_HII_SIBT_STRINGS_UCS2_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ UINT16 StringCount;
+ CHAR16 StringText[1];
+} EFI_HII_SIBT_STRINGS_UCS2_BLOCK;
+
+typedef struct _EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK {
+ EFI_HII_STRING_BLOCK Header;
+ UINT8 FontIdentifier;
+ UINT16 StringCount;
+ CHAR16 StringText[1];
+} EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK;
+
+//
+// Definitions for Image Package
+// Section 27.3.7
+//
+
+typedef struct _EFI_HII_IMAGE_PACKAGE_HDR {
+ EFI_HII_PACKAGE_HEADER Header;
+ UINT32 ImageInfoOffset;
+ UINT32 PaletteInfoOffset;
+} EFI_HII_IMAGE_PACKAGE_HDR;
+
+typedef struct _EFI_HII_IMAGE_BLOCK {
+ UINT8 BlockType;
+} EFI_HII_IMAGE_BLOCK;
+
+//
+// Value of different image information block types
+//
+#define EFI_HII_IIBT_END 0x00
+#define EFI_HII_IIBT_IMAGE_1BIT 0x10
+#define EFI_HII_IIBT_IMAGE_1BIT_TRANS 0x11
+#define EFI_HII_IIBT_IMAGE_4BIT 0x12
+#define EFI_HII_IIBT_IMAGE_4BIT_TRANS 0x13
+#define EFI_HII_IIBT_IMAGE_8BIT 0x14
+#define EFI_HII_IIBT_IMAGE_8BIT_TRANS 0x15
+#define EFI_HII_IIBT_IMAGE_24BIT 0x16
+#define EFI_HII_IIBT_IMAGE_24BIT_TRANS 0x17
+#define EFI_HII_IIBT_IMAGE_JPEG 0x18
+#define EFI_HII_IIBT_DUPLICATE 0x20
+#define EFI_HII_IIBT_SKIP2 0x21
+#define EFI_HII_IIBT_SKIP1 0x22
+#define EFI_HII_IIBT_EXT1 0x30
+#define EFI_HII_IIBT_EXT2 0x31
+#define EFI_HII_IIBT_EXT4 0x32
+
+//
+// Definition of different image information block types
+//
+
+typedef struct _EFI_HII_IIBT_END_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+} EFI_HII_IIBT_END_BLOCK;
+
+typedef struct _EFI_HII_IIBT_EXT1_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ UINT8 BlockType2;
+ UINT8 Length;
+} EFI_HII_IIBT_EXT1_BLOCK;
+
+typedef struct _EFI_HII_IIBT_EXT2_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ UINT8 BlockType2;
+ UINT16 Length;
+} EFI_HII_IIBT_EXT2_BLOCK;
+
+typedef struct _EFI_HII_IIBT_EXT4_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ UINT8 BlockType2;
+ UINT32 Length;
+} EFI_HII_IIBT_EXT4_BLOCK;
+
+typedef struct _EFI_HII_IIBT_IMAGE_1BIT_BASE {
+ UINT16 Width;
+ UINT16 Height;
+ UINT8 Data[1];
+} EFI_HII_IIBT_IMAGE_1BIT_BASE;
+
+typedef struct _EFI_HII_IIBT_IMAGE_1BIT_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ UINT8 PaletteIndex;
+ EFI_HII_IIBT_IMAGE_1BIT_BASE Bitmap;
+} EFI_HII_IIBT_IMAGE_1BIT_BLOCK;
+
+typedef struct _EFI_HII_IIBT_IMAGE_1BIT_TRANS_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ UINT8 PaletteIndex;
+ EFI_HII_IIBT_IMAGE_1BIT_BASE Bitmap;
+} EFI_HII_IIBT_IMAGE_1BIT_TRANS_BLOCK;
+
+typedef struct _EFI_HII_RGB_PIXEL {
+ UINT8 b;
+ UINT8 g;
+ UINT8 r;
+} EFI_HII_RGB_PIXEL;
+
+typedef struct _EFI_HII_IIBT_IMAGE_24BIT_BASE {
+ UINT16 Width;
+ UINT16 Height;
+ EFI_HII_RGB_PIXEL Bitmap[1];
+} EFI_HII_IIBT_IMAGE_24BIT_BASE;
+
+typedef struct _EFI_HII_IIBT_IMAGE_24BIT_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ EFI_HII_IIBT_IMAGE_24BIT_BASE Bitmap;
+} EFI_HII_IIBT_IMAGE_24BIT_BLOCK;
+
+typedef struct _EFI_HII_IIBT_IMAGE_24BIT_TRANS_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ EFI_HII_IIBT_IMAGE_24BIT_BASE Bitmap;
+} EFI_HII_IIBT_IMAGE_24BIT_TRANS_BLOCK;
+
+typedef struct _EFI_HII_IIBT_IMAGE_4BIT_BASE {
+ UINT16 Width;
+ UINT16 Height;
+ UINT8 Data[1];
+} EFI_HII_IIBT_IMAGE_4BIT_BASE;
+
+typedef struct _EFI_HII_IIBT_IMAGE_4BIT_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ UINT8 PaletteIndex;
+ EFI_HII_IIBT_IMAGE_4BIT_BASE Bitmap;
+} EFI_HII_IIBT_IMAGE_4BIT_BLOCK;
+
+typedef struct _EFI_HII_IIBT_IMAGE_4BIT_TRANS_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ UINT8 PaletteIndex;
+ EFI_HII_IIBT_IMAGE_4BIT_BASE Bitmap;
+} EFI_HII_IIBT_IMAGE_4BIT_TRANS_BLOCK;
+
+typedef struct _EFI_HII_IIBT_IMAGE_8BIT_BASE {
+ UINT16 Width;
+ UINT16 Height;
+ UINT8 Data[1];
+} EFI_HII_IIBT_IMAGE_8BIT_BASE;
+
+typedef struct _EFI_HII_IIBT_IMAGE_8BIT_PALETTE_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ UINT8 PaletteIndex;
+ EFI_HII_IIBT_IMAGE_8BIT_BASE Bitmap;
+} EFI_HII_IIBT_IMAGE_8BIT_BLOCK;
+
+typedef struct _EFI_HII_IIBT_IMAGE_8BIT_TRANS_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ UINT8 PaletteIndex;
+ EFI_HII_IIBT_IMAGE_8BIT_BASE Bitmap;
+} EFI_HII_IIBT_IMAGE_8BIT_TRAN_BLOCK;
+
+typedef struct _EFI_HII_IIBT_DUPLICATE_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ EFI_IMAGE_ID ImageId;
+} EFI_HII_IIBT_DUPLICATE_BLOCK;
+
+typedef struct _EFI_HII_IIBT_JPEG_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ UINT32 Size;
+ UINT8 Data[1];
+} EFI_HII_IIBT_JPEG_BLOCK;
+
+typedef struct _EFI_HII_IIBT_SKIP1_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ UINT8 SkipCount;
+} EFI_HII_IIBT_SKIP1_BLOCK;
+
+typedef struct _EFI_HII_IIBT_SKIP2_BLOCK {
+ EFI_HII_IMAGE_BLOCK Header;
+ UINT16 SkipCount;
+} EFI_HII_IIBT_SKIP2_BLOCK;
+
+//
+// Definitions for Palette Information
+//
+
+typedef struct _EFI_HII_IMAGE_PALETTE_INFO_HEADER {
+ UINT16 PaletteCount;
+} EFI_HII_IMAGE_PALETTE_INFO_HEADER;
+
+typedef struct _EFI_HII_IMAGE_PALETTE_INFO {
+ UINT16 PaletteSize;
+ EFI_HII_RGB_PIXEL PaletteValue[1];
+} EFI_HII_IMAGE_PALETTE_INFO;
+
+//
+// Definitions for Forms Package
+// Section 27.3.8
+//
+
+///
+/// The Form package is used to carry form-based encoding data.
+///
+typedef struct _EFI_HII_FORM_PACKAGE_HDR {
+ EFI_HII_PACKAGE_HEADER Header;
+ // EFI_IFR_OP_HEADER OpCodeHeader;
+ // More op-codes follow
+} EFI_HII_FORM_PACKAGE_HDR;
+
+typedef struct {
+ UINT8 Hour;
+ UINT8 Minute;
+ UINT8 Second;
+} EFI_HII_TIME;
+
+typedef struct {
+ UINT16 Year;
+ UINT8 Month;
+ UINT8 Day;
+} EFI_HII_DATE;
+
+typedef union {
+ UINT8 u8;
+ UINT16 u16;
+ UINT32 u32;
+ UINT64 u64;
+ BOOLEAN b;
+ EFI_HII_TIME time;
+ EFI_HII_DATE date;
+ EFI_STRING_ID string; ///< EFI_IFR_TYPE_STRING, EFI_IFR_TYPE_ACTION
+ // UINT8 buffer[]; ///< EFI_IFR_TYPE_ORDERED_LIST
+} EFI_IFR_TYPE_VALUE;
+
+//
+// IFR Opcodes
+//
+#define EFI_IFR_FORM_OP 0x01
+#define EFI_IFR_SUBTITLE_OP 0x02
+#define EFI_IFR_TEXT_OP 0x03
+#define EFI_IFR_IMAGE_OP 0x04
+#define EFI_IFR_ONE_OF_OP 0x05
+#define EFI_IFR_CHECKBOX_OP 0x06
+#define EFI_IFR_NUMERIC_OP 0x07
+#define EFI_IFR_PASSWORD_OP 0x08
+#define EFI_IFR_ONE_OF_OPTION_OP 0x09
+#define EFI_IFR_SUPPRESS_IF_OP 0x0A
+#define EFI_IFR_LOCKED_OP 0x0B
+#define EFI_IFR_ACTION_OP 0x0C
+#define EFI_IFR_RESET_BUTTON_OP 0x0D
+#define EFI_IFR_FORM_SET_OP 0x0E
+#define EFI_IFR_REF_OP 0x0F
+#define EFI_IFR_NO_SUBMIT_IF_OP 0x10
+#define EFI_IFR_INCONSISTENT_IF_OP 0x11
+#define EFI_IFR_EQ_ID_VAL_OP 0x12
+#define EFI_IFR_EQ_ID_ID_OP 0x13
+#define EFI_IFR_EQ_ID_LIST_OP 0x14
+#define EFI_IFR_AND_OP 0x15
+#define EFI_IFR_OR_OP 0x16
+#define EFI_IFR_NOT_OP 0x17
+#define EFI_IFR_RULE_OP 0x18
+#define EFI_IFR_GRAY_OUT_IF_OP 0x19
+#define EFI_IFR_DATE_OP 0x1A
+#define EFI_IFR_TIME_OP 0x1B
+#define EFI_IFR_STRING_OP 0x1C
+#define EFI_IFR_REFRESH_OP 0x1D
+#define EFI_IFR_DISABLE_IF_OP 0x1E
+#define EFI_IFR_ANIMATION_OP 0x1F
+#define EFI_IFR_TO_LOWER_OP 0x20
+#define EFI_IFR_TO_UPPER_OP 0x21
+#define EFI_IFR_MAP_OP 0x22
+#define EFI_IFR_ORDERED_LIST_OP 0x23
+#define EFI_IFR_VARSTORE_OP 0x24
+#define EFI_IFR_VARSTORE_NAME_VALUE_OP 0x25
+#define EFI_IFR_VARSTORE_EFI_OP 0x26
+#define EFI_IFR_VARSTORE_DEVICE_OP 0x27
+#define EFI_IFR_VERSION_OP 0x28
+#define EFI_IFR_END_OP 0x29
+#define EFI_IFR_MATCH_OP 0x2A
+#define EFI_IFR_GET_OP 0x2B
+#define EFI_IFR_SET_OP 0x2C
+#define EFI_IFR_READ_OP 0x2D
+#define EFI_IFR_WRITE_OP 0x2E
+#define EFI_IFR_EQUAL_OP 0x2F
+#define EFI_IFR_NOT_EQUAL_OP 0x30
+#define EFI_IFR_GREATER_THAN_OP 0x31
+#define EFI_IFR_GREATER_EQUAL_OP 0x32
+#define EFI_IFR_LESS_THAN_OP 0x33
+#define EFI_IFR_LESS_EQUAL_OP 0x34
+#define EFI_IFR_BITWISE_AND_OP 0x35
+#define EFI_IFR_BITWISE_OR_OP 0x36
+#define EFI_IFR_BITWISE_NOT_OP 0x37
+#define EFI_IFR_SHIFT_LEFT_OP 0x38
+#define EFI_IFR_SHIFT_RIGHT_OP 0x39
+#define EFI_IFR_ADD_OP 0x3A
+#define EFI_IFR_SUBTRACT_OP 0x3B
+#define EFI_IFR_MULTIPLY_OP 0x3C
+#define EFI_IFR_DIVIDE_OP 0x3D
+#define EFI_IFR_MODULO_OP 0x3E
+#define EFI_IFR_RULE_REF_OP 0x3F
+#define EFI_IFR_QUESTION_REF1_OP 0x40
+#define EFI_IFR_QUESTION_REF2_OP 0x41
+#define EFI_IFR_UINT8_OP 0x42
+#define EFI_IFR_UINT16_OP 0x43
+#define EFI_IFR_UINT32_OP 0x44
+#define EFI_IFR_UINT64_OP 0x45
+#define EFI_IFR_TRUE_OP 0x46
+#define EFI_IFR_FALSE_OP 0x47
+#define EFI_IFR_TO_UINT_OP 0x48
+#define EFI_IFR_TO_STRING_OP 0x49
+#define EFI_IFR_TO_BOOLEAN_OP 0x4A
+#define EFI_IFR_MID_OP 0x4B
+#define EFI_IFR_FIND_OP 0x4C
+#define EFI_IFR_TOKEN_OP 0x4D
+#define EFI_IFR_STRING_REF1_OP 0x4E
+#define EFI_IFR_STRING_REF2_OP 0x4F
+#define EFI_IFR_CONDITIONAL_OP 0x50
+#define EFI_IFR_QUESTION_REF3_OP 0x51
+#define EFI_IFR_ZERO_OP 0x52
+#define EFI_IFR_ONE_OP 0x53
+#define EFI_IFR_ONES_OP 0x54
+#define EFI_IFR_UNDEFINED_OP 0x55
+#define EFI_IFR_LENGTH_OP 0x56
+#define EFI_IFR_DUP_OP 0x57
+#define EFI_IFR_THIS_OP 0x58
+#define EFI_IFR_SPAN_OP 0x59
+#define EFI_IFR_VALUE_OP 0x5A
+#define EFI_IFR_DEFAULT_OP 0x5B
+#define EFI_IFR_DEFAULTSTORE_OP 0x5C
+#define EFI_IFR_FORM_MAP_OP 0x5D
+#define EFI_IFR_CATENATE_OP 0x5E
+#define EFI_IFR_GUID_OP 0x5F
+#define EFI_IFR_SECURITY_OP 0x60
+
+//
+// Definitions of IFR Standard Headers
+// Section 27.3.8.2
+//
+
+typedef struct _EFI_IFR_OP_HEADER {
+ UINT8 OpCode;
+ UINT8 Length:7;
+ UINT8 Scope:1;
+} EFI_IFR_OP_HEADER;
+
+typedef struct _EFI_IFR_STATEMENT_HEADER {
+ EFI_STRING_ID Prompt;
+ EFI_STRING_ID Help;
+} EFI_IFR_STATEMENT_HEADER;
+
+typedef struct _EFI_IFR_QUESTION_HEADER {
+ EFI_IFR_STATEMENT_HEADER Header;
+ EFI_QUESTION_ID QuestionId;
+ EFI_VARSTORE_ID VarStoreId;
+ union {
+ EFI_STRING_ID VarName;
+ UINT16 VarOffset;
+ } VarStoreInfo;
+ UINT8 Flags;
+} EFI_IFR_QUESTION_HEADER;
+
+//
+// Flag values of EFI_IFR_QUESTION_HEADER
+//
+#define EFI_IFR_FLAG_READ_ONLY 0x01
+#define EFI_IFR_FLAG_CALLBACK 0x04
+#define EFI_IFR_FLAG_RESET_REQUIRED 0x10
+#define EFI_IFR_FLAG_OPTIONS_ONLY 0x80
+
+//
+// Definition for Opcode Reference
+// Section 27.3.8.3
+//
+typedef struct _EFI_IFR_DEFAULTSTORE {
+ EFI_IFR_OP_HEADER Header;
+ EFI_STRING_ID DefaultName;
+ UINT16 DefaultId;
+} EFI_IFR_DEFAULTSTORE;
+
+//
+// Default Identifier of default store
+//
+#define EFI_HII_DEFAULT_CLASS_STANDARD 0x0000
+#define EFI_HII_DEFAULT_CLASS_MANUFACTURING 0x0001
+#define EFI_HII_DEFAULT_CLASS_SAFE 0x0002
+#define EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN 0x4000
+#define EFI_HII_DEFAULT_CLASS_PLATFORM_END 0x7fff
+#define EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN 0x8000
+#define EFI_HII_DEFAULT_CLASS_HARDWARE_END 0xbfff
+#define EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN 0xc000
+#define EFI_HII_DEFAULT_CLASS_FIRMWARE_END 0xffff
+
+typedef struct _EFI_IFR_VARSTORE {
+ EFI_IFR_OP_HEADER Header;
+ EFI_GUID Guid;
+ EFI_VARSTORE_ID VarStoreId;
+ UINT16 Size;
+ UINT8 Name[1];
+} EFI_IFR_VARSTORE;
+
+typedef struct _EFI_IFR_VARSTORE_EFI {
+ EFI_IFR_OP_HEADER Header;
+ EFI_VARSTORE_ID VarStoreId;
+ EFI_GUID Guid;
+ UINT32 Attributes;
+} EFI_IFR_VARSTORE_EFI;
+
+typedef struct _EFI_IFR_VARSTORE_NAME_VALUE {
+ EFI_IFR_OP_HEADER Header;
+ EFI_VARSTORE_ID VarStoreId;
+ EFI_GUID Guid;
+} EFI_IFR_VARSTORE_NAME_VALUE;
+
+typedef struct _EFI_IFR_FORM_SET {
+ EFI_IFR_OP_HEADER Header;
+ EFI_GUID Guid;
+ EFI_STRING_ID FormSetTitle;
+ EFI_STRING_ID Help;
+ UINT8 Flags;
+ // EFI_GUID ClassGuid[];
+} EFI_IFR_FORM_SET;
+
+typedef struct _EFI_IFR_END {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_END;
+
+typedef struct _EFI_IFR_FORM {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 FormId;
+ EFI_STRING_ID FormTitle;
+} EFI_IFR_FORM;
+
+typedef struct _EFI_IFR_IMAGE {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IMAGE_ID Id;
+} EFI_IFR_IMAGE;
+
+typedef struct _EFI_IFR_LOCKED {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_LOCKED;
+
+typedef struct _EFI_IFR_RULE {
+ EFI_IFR_OP_HEADER Header;
+ UINT8 RuleId;
+} EFI_IFR_RULE;
+
+typedef struct _EFI_IFR_DEFAULT {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 DefaultId;
+ UINT8 Type;
+ EFI_IFR_TYPE_VALUE Value;
+} EFI_IFR_DEFAULT;
+
+typedef struct _EFI_IFR_VALUE {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_VALUE;
+
+typedef struct _EFI_IFR_SUBTITLE {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_STATEMENT_HEADER Statement;
+ UINT8 Flags;
+} EFI_IFR_SUBTITLE;
+
+#define EFI_IFR_FLAGS_HORIZONTAL 0x01
+
+typedef struct _EFI_IFR_CHECKBOX {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+ UINT8 Flags;
+} EFI_IFR_CHECKBOX;
+
+#define EFI_IFR_CHECKBOX_DEFAULT 0x01
+#define EFI_IFR_CHECKBOX_DEFAULT_MFG 0x02
+
+typedef struct _EFI_IFR_TEXT {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_STATEMENT_HEADER Statement;
+ EFI_STRING_ID TextTwo;
+} EFI_IFR_TEXT;
+
+typedef struct _EFI_IFR_REF {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+ EFI_FORM_ID FormId;
+} EFI_IFR_REF;
+
+typedef struct _EFI_IFR_REF2 {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+ EFI_FORM_ID FormId;
+ EFI_QUESTION_ID QuestionId;
+} EFI_IFR_REF2;
+
+typedef struct _EFI_IFR_REF3 {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+ EFI_FORM_ID FormId;
+ EFI_QUESTION_ID QuestionId;
+ EFI_GUID FormSetId;
+} EFI_IFR_REF3;
+
+typedef struct _EFI_IFR_REF4 {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+ EFI_FORM_ID FormId;
+ EFI_QUESTION_ID QuestionId;
+ EFI_GUID FormSetId;
+ EFI_STRING_ID DevicePath;
+} EFI_IFR_REF4;
+
+typedef struct _EFI_IFR_RESET_BUTTON {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_STATEMENT_HEADER Statement;
+ EFI_DEFAULT_ID DefaultId;
+} EFI_IFR_RESET_BUTTON;
+
+typedef struct _EFI_IFR_ACTION {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+ EFI_STRING_ID QuestionConfig;
+} EFI_IFR_ACTION;
+
+typedef struct _EFI_IFR_ACTION_1 {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+} EFI_IFR_ACTION_1;
+
+typedef struct _EFI_IFR_DATE {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+ UINT8 Flags;
+} EFI_IFR_DATE;
+
+//
+// Flags that describe the behavior of the question.
+//
+#define EFI_QF_DATE_YEAR_SUPPRESS 0x01
+#define EFI_QF_DATE_MONTH_SUPPRESS 0x02
+#define EFI_QF_DATE_DAY_SUPPRESS 0x04
+
+#define EFI_QF_DATE_STORAGE 0x30
+#define QF_DATE_STORAGE_NORMAL 0x00
+#define QF_DATE_STORAGE_TIME 0x10
+#define QF_DATE_STORAGE_WAKEUP 0x20
+
+typedef union {
+ struct {
+ UINT8 MinValue;
+ UINT8 MaxValue;
+ UINT8 Step;
+ } u8;
+ struct {
+ UINT16 MinValue;
+ UINT16 MaxValue;
+ UINT16 Step;
+ } u16;
+ struct {
+ UINT32 MinValue;
+ UINT32 MaxValue;
+ UINT32 Step;
+ } u32;
+ struct {
+ UINT64 MinValue;
+ UINT64 MaxValue;
+ UINT64 Step;
+ } u64;
+} MINMAXSTEP_DATA;
+
+typedef struct _EFI_IFR_NUMERIC {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+ UINT8 Flags;
+ MINMAXSTEP_DATA data;
+} EFI_IFR_NUMERIC;
+
+//
+// Flags related to the numeric question
+//
+#define EFI_IFR_NUMERIC_SIZE 0x03
+#define EFI_IFR_NUMERIC_SIZE_1 0x00
+#define EFI_IFR_NUMERIC_SIZE_2 0x01
+#define EFI_IFR_NUMERIC_SIZE_4 0x02
+#define EFI_IFR_NUMERIC_SIZE_8 0x03
+
+#define EFI_IFR_DISPLAY 0x30
+#define EFI_IFR_DISPLAY_INT_DEC 0x00
+#define EFI_IFR_DISPLAY_UINT_DEC 0x10
+#define EFI_IFR_DISPLAY_UINT_HEX 0x20
+
+typedef struct _EFI_IFR_ONE_OF {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+ UINT8 Flags;
+ MINMAXSTEP_DATA data;
+} EFI_IFR_ONE_OF;
+
+typedef struct _EFI_IFR_STRING {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+ UINT8 MinSize;
+ UINT8 MaxSize;
+ UINT8 Flags;
+} EFI_IFR_STRING;
+
+#define EFI_IFR_STRING_MULTI_LINE 0x01
+
+typedef struct _EFI_IFR_PASSWORD {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+ UINT16 MinSize;
+ UINT16 MaxSize;
+} EFI_IFR_PASSWORD;
+
+typedef struct _EFI_IFR_ORDERED_LIST {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+ UINT8 MaxContainers;
+ UINT8 Flags;
+} EFI_IFR_ORDERED_LIST;
+
+#define EFI_IFR_UNIQUE_SET 0x01
+#define EFI_IFR_NO_EMPTY_SET 0x02
+
+typedef struct _EFI_IFR_TIME {
+ EFI_IFR_OP_HEADER Header;
+ EFI_IFR_QUESTION_HEADER Question;
+ UINT8 Flags;
+} EFI_IFR_TIME;
+
+//
+// A bit-mask that determines which unique settings are active for this opcode.
+//
+#define QF_TIME_HOUR_SUPPRESS 0x01
+#define QF_TIME_MINUTE_SUPPRESS 0x02
+#define QF_TIME_SECOND_SUPPRESS 0x04
+
+#define QF_TIME_STORAGE 0x30
+#define QF_TIME_STORAGE_NORMAL 0x00
+#define QF_TIME_STORAGE_TIME 0x10
+#define QF_TIME_STORAGE_WAKEUP 0x20
+
+typedef struct _EFI_IFR_DISABLE_IF {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_DISABLE_IF;
+
+typedef struct _EFI_IFR_SUPPRESS_IF {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_SUPPRESS_IF;
+
+typedef struct _EFI_IFR_GRAY_OUT_IF {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_GRAY_OUT_IF;
+
+typedef struct _EFI_IFR_INCONSISTENT_IF {
+ EFI_IFR_OP_HEADER Header;
+ EFI_STRING_ID Error;
+} EFI_IFR_INCONSISTENT_IF;
+
+typedef struct _EFI_IFR_NO_SUBMIT_IF {
+ EFI_IFR_OP_HEADER Header;
+ EFI_STRING_ID Error;
+} EFI_IFR_NO_SUBMIT_IF;
+
+typedef struct _EFI_IFR_REFRESH {
+ EFI_IFR_OP_HEADER Header;
+ UINT8 RefreshInterval;
+} EFI_IFR_REFRESH;
+
+typedef struct _EFI_IFR_VARSTORE_DEVICE {
+ EFI_IFR_OP_HEADER Header;
+ EFI_STRING_ID DevicePath;
+} EFI_IFR_VARSTORE_DEVICE;
+
+typedef struct _EFI_IFR_ONE_OF_OPTION {
+ EFI_IFR_OP_HEADER Header;
+ EFI_STRING_ID Option;
+ UINT8 Flags;
+ UINT8 Type;
+ EFI_IFR_TYPE_VALUE Value;
+} EFI_IFR_ONE_OF_OPTION;
+
+//
+// Types of the option's value.
+//
+#define EFI_IFR_TYPE_NUM_SIZE_8 0x00
+#define EFI_IFR_TYPE_NUM_SIZE_16 0x01
+#define EFI_IFR_TYPE_NUM_SIZE_32 0x02
+#define EFI_IFR_TYPE_NUM_SIZE_64 0x03
+#define EFI_IFR_TYPE_BOOLEAN 0x04
+#define EFI_IFR_TYPE_TIME 0x05
+#define EFI_IFR_TYPE_DATE 0x06
+#define EFI_IFR_TYPE_STRING 0x07
+#define EFI_IFR_TYPE_OTHER 0x08
+#define EFI_IFR_TYPE_UNDEFINED 0x09
+#define EFI_IFR_TYPE_ACTION 0x0A
+#define EFI_IFR_TYPE_BUFFER 0x0B
+
+#define EFI_IFR_OPTION_DEFAULT 0x10
+#define EFI_IFR_OPTION_DEFAULT_MFG 0x20
+
+typedef struct _EFI_IFR_GUID {
+ EFI_IFR_OP_HEADER Header;
+ EFI_GUID Guid;
+ //Optional Data Follows
+} EFI_IFR_GUID;
+
+typedef struct _EFI_IFR_DUP {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_DUP;
+
+typedef struct _EFI_IFR_EQ_ID_ID {
+ EFI_IFR_OP_HEADER Header;
+ EFI_QUESTION_ID QuestionId1;
+ EFI_QUESTION_ID QuestionId2;
+} EFI_IFR_EQ_ID_ID;
+
+typedef struct _EFI_IFR_EQ_ID_VAL {
+ EFI_IFR_OP_HEADER Header;
+ EFI_QUESTION_ID QuestionId;
+ UINT16 Value;
+} EFI_IFR_EQ_ID_VAL;
+
+typedef struct _EFI_IFR_EQ_ID_VAL_LIST {
+ EFI_IFR_OP_HEADER Header;
+ EFI_QUESTION_ID QuestionId;
+ UINT16 ListLength;
+ UINT16 ValueList[1];
+} EFI_IFR_EQ_ID_VAL_LIST;
+
+typedef struct _EFI_IFR_UINT8 {
+ EFI_IFR_OP_HEADER Header;
+ UINT8 Value;
+} EFI_IFR_UINT8;
+
+typedef struct _EFI_IFR_UINT16 {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 Value;
+} EFI_IFR_UINT16;
+
+typedef struct _EFI_IFR_UINT32 {
+ EFI_IFR_OP_HEADER Header;
+ UINT32 Value;
+} EFI_IFR_UINT32;
+
+typedef struct _EFI_IFR_UINT64 {
+ EFI_IFR_OP_HEADER Header;
+ UINT64 Value;
+} EFI_IFR_UINT64;
+
+typedef struct _EFI_IFR_QUESTION_REF1 {
+ EFI_IFR_OP_HEADER Header;
+ EFI_QUESTION_ID QuestionId;
+} EFI_IFR_QUESTION_REF1;
+
+typedef struct _EFI_IFR_QUESTION_REF2 {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_QUESTION_REF2;
+
+typedef struct _EFI_IFR_QUESTION_REF3 {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_QUESTION_REF3;
+
+typedef struct _EFI_IFR_QUESTION_REF3_2 {
+ EFI_IFR_OP_HEADER Header;
+ EFI_STRING_ID DevicePath;
+} EFI_IFR_QUESTION_REF3_2;
+
+typedef struct _EFI_IFR_QUESTION_REF3_3 {
+ EFI_IFR_OP_HEADER Header;
+ EFI_STRING_ID DevicePath;
+ EFI_GUID Guid;
+} EFI_IFR_QUESTION_REF3_3;
+
+typedef struct _EFI_IFR_RULE_REF {
+ EFI_IFR_OP_HEADER Header;
+ UINT8 RuleId;
+} EFI_IFR_RULE_REF;
+
+typedef struct _EFI_IFR_STRING_REF1 {
+ EFI_IFR_OP_HEADER Header;
+ EFI_STRING_ID StringId;
+} EFI_IFR_STRING_REF1;
+
+typedef struct _EFI_IFR_STRING_REF2 {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_STRING_REF2;
+
+typedef struct _EFI_IFR_THIS {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_THIS;
+
+typedef struct _EFI_IFR_TRUE {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_TRUE;
+
+typedef struct _EFI_IFR_FALSE {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_FALSE;
+
+typedef struct _EFI_IFR_ONE {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_ONE;
+
+typedef struct _EFI_IFR_ONES {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_ONES;
+
+typedef struct _EFI_IFR_ZERO {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_ZERO;
+
+typedef struct _EFI_IFR_UNDEFINED {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_UNDEFINED;
+
+typedef struct _EFI_IFR_VERSION {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_VERSION;
+
+typedef struct _EFI_IFR_LENGTH {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_LENGTH;
+
+typedef struct _EFI_IFR_NOT {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_NOT;
+
+typedef struct _EFI_IFR_BITWISE_NOT {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_BITWISE_NOT;
+
+typedef struct _EFI_IFR_TO_BOOLEAN {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_TO_BOOLEAN;
+
+///
+/// For EFI_IFR_TO_STRING, when converting from
+/// unsigned integers, these flags control the format:
+/// 0 = unsigned decimal.
+/// 1 = signed decimal.
+/// 2 = hexadecimal (lower-case alpha).
+/// 3 = hexadecimal (upper-case alpha).
+///@{
+#define EFI_IFR_STRING_UNSIGNED_DEC 0
+#define EFI_IFR_STRING_SIGNED_DEC 1
+#define EFI_IFR_STRING_LOWERCASE_HEX 2
+#define EFI_IFR_STRING_UPPERCASE_HEX 3
+///@}
+
+///
+/// When converting from a buffer, these flags control the format:
+/// 0 = ASCII.
+/// 8 = Unicode.
+///@{
+#define EFI_IFR_STRING_ASCII 0
+#define EFI_IFR_STRING_UNICODE 8
+///@}
+
+typedef struct _EFI_IFR_TO_STRING {
+ EFI_IFR_OP_HEADER Header;
+ UINT8 Format;
+} EFI_IFR_TO_STRING;
+
+typedef struct _EFI_IFR_TO_UINT {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_TO_UINT;
+
+typedef struct _EFI_IFR_TO_UPPER {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_TO_UPPER;
+
+typedef struct _EFI_IFR_TO_LOWER {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_TO_LOWER;
+
+typedef struct _EFI_IFR_ADD {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_ADD;
+
+typedef struct _EFI_IFR_AND {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_AND;
+
+typedef struct _EFI_IFR_BITWISE_AND {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_BITWISE_AND;
+
+typedef struct _EFI_IFR_BITWISE_OR {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_BITWISE_OR;
+
+typedef struct _EFI_IFR_CATENATE {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_CATENATE;
+
+typedef struct _EFI_IFR_DIVIDE {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_DIVIDE;
+
+typedef struct _EFI_IFR_EQUAL {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_EQUAL;
+
+typedef struct _EFI_IFR_GREATER_EQUAL {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_GREATER_EQUAL;
+
+typedef struct _EFI_IFR_GREATER_THAN {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_GREATER_THAN;
+
+typedef struct _EFI_IFR_LESS_EQUAL {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_LESS_EQUAL;
+
+typedef struct _EFI_IFR_LESS_THAN {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_LESS_THAN;
+
+typedef struct _EFI_IFR_MATCH {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_MATCH;
+
+typedef struct _EFI_IFR_MULTIPLY {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_MULTIPLY;
+
+typedef struct _EFI_IFR_MODULO {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_MODULO;
+
+typedef struct _EFI_IFR_NOT_EQUAL {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_NOT_EQUAL;
+
+typedef struct _EFI_IFR_OR {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_OR;
+
+typedef struct _EFI_IFR_SHIFT_LEFT {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_SHIFT_LEFT;
+
+typedef struct _EFI_IFR_SHIFT_RIGHT {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_SHIFT_RIGHT;
+
+typedef struct _EFI_IFR_SUBTRACT {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_SUBTRACT;
+
+typedef struct _EFI_IFR_CONDITIONAL {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_CONDITIONAL;
+
+//
+// Flags governing the matching criteria of EFI_IFR_FIND
+//
+#define EFI_IFR_FF_CASE_SENSITIVE 0x00
+#define EFI_IFR_FF_CASE_INSENSITIVE 0x01
+
+typedef struct _EFI_IFR_FIND {
+ EFI_IFR_OP_HEADER Header;
+ UINT8 Format;
+} EFI_IFR_FIND;
+
+typedef struct _EFI_IFR_MID {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_MID;
+
+typedef struct _EFI_IFR_TOKEN {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_TOKEN;
+
+//
+// Flags specifying whether to find the first matching string
+// or the first non-matching string.
+//
+#define EFI_IFR_FLAGS_FIRST_MATCHING 0x00
+#define EFI_IFR_FLAGS_FIRST_NON_MATCHING 0x01
+
+typedef struct _EFI_IFR_SPAN {
+ EFI_IFR_OP_HEADER Header;
+ UINT8 Flags;
+} EFI_IFR_SPAN;
+
+typedef struct _EFI_IFR_SECURITY {
+ ///
+ /// Standard opcode header, where Header.Op = EFI_IFR_SECURITY_OP.
+ ///
+ EFI_IFR_OP_HEADER Header;
+ ///
+ /// Security permission level.
+ ///
+ EFI_GUID Permissions;
+} EFI_IFR_SECURITY;
+
+typedef struct _EFI_IFR_FORM_MAP_METHOD {
+ ///
+ /// The string identifier which provides the human-readable name of
+ /// the configuration method for this standards map form.
+ ///
+ EFI_STRING_ID MethodTitle;
+ ///
+ /// Identifier which uniquely specifies the configuration methods
+ /// associated with this standards map form.
+ ///
+ EFI_GUID MethodIdentifier;
+} EFI_IFR_FORM_MAP_METHOD;
+
+typedef struct _EFI_IFR_FORM_MAP {
+ ///
+ /// The sequence that defines the type of opcode as well as the length
+ /// of the opcode being defined. Header.OpCode = EFI_IFR_FORM_MAP_OP.
+ ///
+ EFI_IFR_OP_HEADER Header;
+ ///
+ /// The unique identifier for this particular form.
+ ///
+ EFI_FORM_ID FormId;
+ ///
+ /// One or more configuration method's name and unique identifier.
+ ///
+ // EFI_IFR_FORM_MAP_METHOD Methods[];
+} EFI_IFR_FORM_MAP;
+
+typedef struct _EFI_IFR_SET {
+ ///
+ /// The sequence that defines the type of opcode as well as the length
+ /// of the opcode being defined. Header.OpCode = EFI_IFR_SET_OP.
+ ///
+ EFI_IFR_OP_HEADER Header;
+ ///
+ /// Specifies the identifier of a previously declared variable store to
+ /// use when storing the question's value.
+ ///
+ EFI_VARSTORE_ID VarStoreId;
+ union {
+ ///
+ /// A 16-bit Buffer Storage offset.
+ ///
+ EFI_STRING_ID VarName;
+ ///
+ /// A Name Value or EFI Variable name (VarName).
+ ///
+ UINT16 VarOffset;
+ } VarStoreInfo;
+ ///
+ /// Specifies the type used for storage.
+ ///
+ UINT8 VarStoreType;
+} EFI_IFR_SET;
+
+typedef struct _EFI_IFR_GET {
+ ///
+ /// The sequence that defines the type of opcode as well as the length
+ /// of the opcode being defined. Header.OpCode = EFI_IFR_GET_OP.
+ ///
+ EFI_IFR_OP_HEADER Header;
+ ///
+ /// Specifies the identifier of a previously declared variable store to
+ /// use when retrieving the value.
+ ///
+ EFI_VARSTORE_ID VarStoreId;
+ union {
+ ///
+ /// A 16-bit Buffer Storage offset.
+ ///
+ EFI_STRING_ID VarName;
+ ///
+ /// A Name Value or EFI Variable name (VarName).
+ ///
+ UINT16 VarOffset;
+ } VarStoreInfo;
+ ///
+ /// Specifies the type used for storage.
+ ///
+ UINT8 VarStoreType;
+} EFI_IFR_GET;
+
+typedef struct _EFI_IFR_READ {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_READ;
+
+typedef struct _EFI_IFR_WRITE {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_WRITE;
+
+typedef struct _EFI_IFR_MAP {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_MAP;
+//
+// Definitions for Keyboard Package
+// Releated definitions are in Section of EFI_HII_DATABASE_PROTOCOL
+//
+
+///
+/// Each enumeration values maps a physical key on a keyboard.
+///
+typedef enum {
+ EfiKeyLCtrl,
+ EfiKeyA0,
+ EfiKeyLAlt,
+ EfiKeySpaceBar,
+ EfiKeyA2,
+ EfiKeyA3,
+ EfiKeyA4,
+ EfiKeyRCtrl,
+ EfiKeyLeftArrow,
+ EfiKeyDownArrow,
+ EfiKeyRightArrow,
+ EfiKeyZero,
+ EfiKeyPeriod,
+ EfiKeyEnter,
+ EfiKeyLShift,
+ EfiKeyB0,
+ EfiKeyB1,
+ EfiKeyB2,
+ EfiKeyB3,
+ EfiKeyB4,
+ EfiKeyB5,
+ EfiKeyB6,
+ EfiKeyB7,
+ EfiKeyB8,
+ EfiKeyB9,
+ EfiKeyB10,
+ EfiKeyRShift,
+ EfiKeyUpArrow,
+ EfiKeyOne,
+ EfiKeyTwo,
+ EfiKeyThree,
+ EfiKeyCapsLock,
+ EfiKeyC1,
+ EfiKeyC2,
+ EfiKeyC3,
+ EfiKeyC4,
+ EfiKeyC5,
+ EfiKeyC6,
+ EfiKeyC7,
+ EfiKeyC8,
+ EfiKeyC9,
+ EfiKeyC10,
+ EfiKeyC11,
+ EfiKeyC12,
+ EfiKeyFour,
+ EfiKeyFive,
+ EfiKeySix,
+ EfiKeyPlus,
+ EfiKeyTab,
+ EfiKeyD1,
+ EfiKeyD2,
+ EfiKeyD3,
+ EfiKeyD4,
+ EfiKeyD5,
+ EfiKeyD6,
+ EfiKeyD7,
+ EfiKeyD8,
+ EfiKeyD9,
+ EfiKeyD10,
+ EfiKeyD11,
+ EfiKeyD12,
+ EfiKeyD13,
+ EfiKeyDel,
+ EfiKeyEnd,
+ EfiKeyPgDn,
+ EfiKeySeven,
+ EfiKeyEight,
+ EfiKeyNine,
+ EfiKeyE0,
+ EfiKeyE1,
+ EfiKeyE2,
+ EfiKeyE3,
+ EfiKeyE4,
+ EfiKeyE5,
+ EfiKeyE6,
+ EfiKeyE7,
+ EfiKeyE8,
+ EfiKeyE9,
+ EfiKeyE10,
+ EfiKeyE11,
+ EfiKeyE12,
+ EfiKeyBackSpace,
+ EfiKeyIns,
+ EfiKeyHome,
+ EfiKeyPgUp,
+ EfiKeyNLck,
+ EfiKeySlash,
+ EfiKeyAsterisk,
+ EfiKeyMinus,
+ EfiKeyEsc,
+ EfiKeyF1,
+ EfiKeyF2,
+ EfiKeyF3,
+ EfiKeyF4,
+ EfiKeyF5,
+ EfiKeyF6,
+ EfiKeyF7,
+ EfiKeyF8,
+ EfiKeyF9,
+ EfiKeyF10,
+ EfiKeyF11,
+ EfiKeyF12,
+ EfiKeyPrint,
+ EfiKeySLck,
+ EfiKeyPause
+} EFI_KEY;
+
+typedef struct {
+ ///
+ /// Used to describe a physical key on a keyboard.
+ ///
+ EFI_KEY Key;
+ ///
+ /// Unicode character code for the Key.
+ ///
+ CHAR16 Unicode;
+ ///
+ /// Unicode character code for the key with the shift key being held down.
+ ///
+ CHAR16 ShiftedUnicode;
+ ///
+ /// Unicode character code for the key with the Alt-GR being held down.
+ ///
+ CHAR16 AltGrUnicode;
+ ///
+ /// Unicode character code for the key with the Alt-GR and shift keys being held down.
+ ///
+ CHAR16 ShiftedAltGrUnicode;
+ ///
+ /// Modifier keys are defined to allow for special functionality that is not necessarily
+ /// accomplished by a printable character. Many of these modifier keys are flags to toggle
+ /// certain state bits on and off inside of a keyboard driver.
+ ///
+ UINT16 Modifier;
+ UINT16 AffectedAttribute;
+} EFI_KEY_DESCRIPTOR;
+
+///
+/// A key which is affected by all the standard shift modifiers.
+/// Most keys would be expected to have this bit active.
+///
+#define EFI_AFFECTED_BY_STANDARD_SHIFT 0x0001
+
+///
+/// This key is affected by the caps lock so that if a keyboard driver
+/// would need to disambiguate between a key which had a "1" defined
+/// versus an "a" character. Having this bit turned on would tell
+/// the keyboard driver to use the appropriate shifted state or not.
+///
+#define EFI_AFFECTED_BY_CAPS_LOCK 0x0002
+
+///
+/// Similar to the case of CAPS lock, if this bit is active, the key
+/// is affected by the num lock being turned on.
+///
+#define EFI_AFFECTED_BY_NUM_LOCK 0x0004
+
+typedef struct {
+ UINT16 LayoutLength;
+ EFI_GUID Guid;
+ UINT32 LayoutDescriptorStringOffset;
+ UINT8 DescriptorCount;
+ // EFI_KEY_DESCRIPTOR Descriptors[];
+} EFI_HII_KEYBOARD_LAYOUT;
+
+typedef struct {
+ EFI_HII_PACKAGE_HEADER Header;
+ UINT16 LayoutCount;
+ // EFI_HII_KEYBOARD_LAYOUT Layout[];
+} EFI_HII_KEYBOARD_PACKAGE_HDR;
+
+//
+// Modifier values
+//
+#define EFI_NULL_MODIFIER 0x0000
+#define EFI_LEFT_CONTROL_MODIFIER 0x0001
+#define EFI_RIGHT_CONTROL_MODIFIER 0x0002
+#define EFI_LEFT_ALT_MODIFIER 0x0003
+#define EFI_RIGHT_ALT_MODIFIER 0x0004
+#define EFI_ALT_GR_MODIFIER 0x0005
+#define EFI_INSERT_MODIFIER 0x0006
+#define EFI_DELETE_MODIFIER 0x0007
+#define EFI_PAGE_DOWN_MODIFIER 0x0008
+#define EFI_PAGE_UP_MODIFIER 0x0009
+#define EFI_HOME_MODIFIER 0x000A
+#define EFI_END_MODIFIER 0x000B
+#define EFI_LEFT_SHIFT_MODIFIER 0x000C
+#define EFI_RIGHT_SHIFT_MODIFIER 0x000D
+#define EFI_CAPS_LOCK_MODIFIER 0x000E
+#define EFI_NUM_LOCK_MODIFIER 0x000F
+#define EFI_LEFT_ARROW_MODIFIER 0x0010
+#define EFI_RIGHT_ARROW_MODIFIER 0x0011
+#define EFI_DOWN_ARROW_MODIFIER 0x0012
+#define EFI_UP_ARROW_MODIFIER 0x0013
+#define EFI_NS_KEY_MODIFIER 0x0014
+#define EFI_NS_KEY_DEPENDENCY_MODIFIER 0x0015
+#define EFI_FUNCTION_KEY_ONE_MODIFIER 0x0016
+#define EFI_FUNCTION_KEY_TWO_MODIFIER 0x0017
+#define EFI_FUNCTION_KEY_THREE_MODIFIER 0x0018
+#define EFI_FUNCTION_KEY_FOUR_MODIFIER 0x0019
+#define EFI_FUNCTION_KEY_FIVE_MODIFIER 0x001A
+#define EFI_FUNCTION_KEY_SIX_MODIFIER 0x001B
+#define EFI_FUNCTION_KEY_SEVEN_MODIFIER 0x001C
+#define EFI_FUNCTION_KEY_EIGHT_MODIFIER 0x001D
+#define EFI_FUNCTION_KEY_NINE_MODIFIER 0x001E
+#define EFI_FUNCTION_KEY_TEN_MODIFIER 0x001F
+#define EFI_FUNCTION_KEY_ELEVEN_MODIFIER 0x0020
+#define EFI_FUNCTION_KEY_TWELVE_MODIFIER 0x0021
+
+//
+// Keys that have multiple control functions based on modifier
+// settings are handled in the keyboard driver implementation.
+// For instance, PRINT_KEY might have a modifier held down and
+// is still a nonprinting character, but might have an alternate
+// control function like SYSREQUEST
+//
+#define EFI_PRINT_MODIFIER 0x0022
+#define EFI_SYS_REQUEST_MODIFIER 0x0023
+#define EFI_SCROLL_LOCK_MODIFIER 0x0024
+#define EFI_PAUSE_MODIFIER 0x0025
+#define EFI_BREAK_MODIFIER 0x0026
+
+#define EFI_LEFT_LOGO_MODIFIER 0x0027
+#define EFI_RIGHT_LOGO_MODIFIER 0x0028
+#define EFI_MENU_MODIFIER 0x0029
+
+///
+/// Animation IFR opcode
+///
+typedef struct _EFI_IFR_ANIMATION {
+ ///
+ /// Standard opcode header, where Header.OpCode is
+ /// EFI_IFR_ANIMATION_OP.
+ ///
+ EFI_IFR_OP_HEADER Header;
+ ///
+ /// Animation identifier in the HII database.
+ ///
+ EFI_ANIMATION_ID Id;
+} EFI_IFR_ANIMATION;
+
+///
+/// HII animation package header.
+///
+typedef struct _EFI_HII_ANIMATION_PACKAGE_HDR {
+ ///
+ /// Standard package header, where Header.Type = EFI_HII_PACKAGE_ANIMATIONS.
+ ///
+ EFI_HII_PACKAGE_HEADER Header;
+ ///
+ /// Offset, relative to this header, of the animation information. If
+ /// this is zero, then there are no animation sequences in the package.
+ ///
+ UINT32 AnimationInfoOffset;
+} EFI_HII_ANIMATION_PACKAGE_HDR;
+
+///
+/// Animation information is encoded as a series of blocks,
+/// with each block prefixed by a single byte header EFI_HII_ANIMATION_BLOCK.
+///
+typedef struct _EFI_HII_ANIMATION_BLOCK {
+ UINT8 BlockType;
+ //UINT8 BlockBody[];
+} EFI_HII_ANIMATION_BLOCK;
+
+///
+/// Animation block types.
+///
+#define EFI_HII_AIBT_END 0x00
+#define EFI_HII_AIBT_OVERLAY_IMAGES 0x10
+#define EFI_HII_AIBT_CLEAR_IMAGES 0x11
+#define EFI_HII_AIBT_RESTORE_SCRN 0x12
+#define EFI_HII_AIBT_OVERLAY_IMAGES_LOOP 0x18
+#define EFI_HII_AIBT_CLEAR_IMAGES_LOOP 0x19
+#define EFI_HII_AIBT_RESTORE_SCRN_LOOP 0x1A
+#define EFI_HII_AIBT_DUPLICATE 0x20
+#define EFI_HII_AIBT_SKIP2 0x21
+#define EFI_HII_AIBT_SKIP1 0x22
+#define EFI_HII_AIBT_EXT1 0x30
+#define EFI_HII_AIBT_EXT2 0x31
+#define EFI_HII_AIBT_EXT4 0x32
+
+///
+/// Extended block headers used for variable sized animation records
+/// which need an explicit length.
+///
+
+typedef struct _EFI_HII_AIBT_EXT1_BLOCK {
+ ///
+ /// Standard animation header, where Header.BlockType = EFI_HII_AIBT_EXT1.
+ ///
+ EFI_HII_ANIMATION_BLOCK Header;
+ ///
+ /// The block type.
+ ///
+ UINT8 BlockType2;
+ ///
+ /// Size of the animation block, in bytes, including the animation block header.
+ ///
+ UINT8 Length;
+} EFI_HII_AIBT_EXT1_BLOCK;
+
+typedef struct _EFI_HII_AIBT_EXT2_BLOCK {
+ ///
+ /// Standard animation header, where Header.BlockType = EFI_HII_AIBT_EXT2.
+ ///
+ EFI_HII_ANIMATION_BLOCK Header;
+ ///
+ /// The block type
+ ///
+ UINT8 BlockType2;
+ ///
+ /// Size of the animation block, in bytes, including the animation block header.
+ ///
+ UINT16 Length;
+} EFI_HII_AIBT_EXT2_BLOCK;
+
+typedef struct _EFI_HII_AIBT_EXT4_BLOCK {
+ ///
+ /// Standard animation header, where Header.BlockType = EFI_HII_AIBT_EXT4.
+ ///
+ EFI_HII_ANIMATION_BLOCK Header;
+ ///
+ /// The block type
+ ///
+ UINT8 BlockType2;
+ ///
+ /// Size of the animation block, in bytes, including the animation block header.
+ ///
+ UINT32 Length;
+} EFI_HII_AIBT_EXT4_BLOCK;
+
+typedef struct _EFI_HII_ANIMATION_CELL {
+ ///
+ /// The X offset from the upper left hand corner of the logical
+ /// window to position the indexed image.
+ ///
+ UINT16 OffsetX;
+ ///
+ /// The Y offset from the upper left hand corner of the logical
+ /// window to position the indexed image.
+ ///
+ UINT16 OffsetY;
+ ///
+ /// The image to display at the specified offset from the upper left
+ /// hand corner of the logical window.
+ ///
+ EFI_IMAGE_ID ImageId;
+ ///
+ /// The number of milliseconds to delay after displaying the indexed
+ /// image and before continuing on to the next linked image. If value
+ /// is zero, no delay.
+ ///
+ UINT16 Delay;
+} EFI_HII_ANIMATION_CELL;
+
+///
+/// An animation block to describe an animation sequence that does not cycle, and
+/// where one image is simply displayed over the previous image.
+///
+typedef struct _EFI_HII_AIBT_OVERLAY_IMAGES_BLOCK {
+ ///
+ /// This is image that is to be reference by the image protocols, if the
+ /// animation function is not supported or disabled. This image can
+ /// be one particular image from the animation sequence (if any one
+ /// of the animation frames has a complete image) or an alternate
+ /// image that can be displayed alone. If the value is zero, no image
+ /// is displayed.
+ ///
+ EFI_IMAGE_ID DftImageId;
+ ///
+ /// The overall width of the set of images (logical window width).
+ ///
+ UINT16 Width;
+ ///
+ /// The overall height of the set of images (logical window height).
+ ///
+ UINT16 Height;
+ ///
+ /// The number of EFI_HII_ANIMATION_CELL contained in the
+ /// animation sequence.
+ ///
+ UINT16 CellCount;
+ ///
+ /// An array of CellCount animation cells.
+ ///
+ EFI_HII_ANIMATION_CELL AnimationCell[1];
+} EFI_HII_AIBT_OVERLAY_IMAGES_BLOCK;
+
+///
+/// An animation block to describe an animation sequence that does not cycle,
+/// and where the logical window is cleared to the specified color before
+/// the next image is displayed.
+///
+typedef struct _EFI_HII_AIBT_CLEAR_IMAGES_BLOCK {
+ ///
+ /// This is image that is to be reference by the image protocols, if the
+ /// animation function is not supported or disabled. This image can
+ /// be one particular image from the animation sequence (if any one
+ /// of the animation frames has a complete image) or an alternate
+ /// image that can be displayed alone. If the value is zero, no image
+ /// is displayed.
+ ///
+ EFI_IMAGE_ID DftImageId;
+ ///
+ /// The overall width of the set of images (logical window width).
+ ///
+ UINT16 Width;
+ ///
+ /// The overall height of the set of images (logical window height).
+ ///
+ UINT16 Height;
+ ///
+ /// The number of EFI_HII_ANIMATION_CELL contained in the
+ /// animation sequence.
+ ///
+ UINT16 CellCount;
+ ///
+ /// The color to clear the logical window to before displaying the
+ /// indexed image.
+ ///
+ EFI_HII_RGB_PIXEL BackgndColor;
+ ///
+ /// An array of CellCount animation cells.
+ ///
+ EFI_HII_ANIMATION_CELL AnimationCell[1];
+} EFI_HII_AIBT_CLEAR_IMAGES_BLOCK;
+
+///
+/// An animation block to describe an animation sequence that does not cycle,
+/// and where the screen is restored to the original state before the next
+/// image is displayed.
+///
+typedef struct _EFI_HII_AIBT_RESTORE_SCRN_BLOCK {
+ ///
+ /// This is image that is to be reference by the image protocols, if the
+ /// animation function is not supported or disabled. This image can
+ /// be one particular image from the animation sequence (if any one
+ /// of the animation frames has a complete image) or an alternate
+ /// image that can be displayed alone. If the value is zero, no image
+ /// is displayed.
+ ///
+ EFI_IMAGE_ID DftImageId;
+ ///
+ /// The overall width of the set of images (logical window width).
+ ///
+ UINT16 Width;
+ ///
+ /// The overall height of the set of images (logical window height).
+ ///
+ UINT16 Height;
+ ///
+ /// The number of EFI_HII_ANIMATION_CELL contained in the
+ /// animation sequence.
+ ///
+ UINT16 CellCount;
+ ///
+ /// An array of CellCount animation cells.
+ ///
+ EFI_HII_ANIMATION_CELL AnimationCell[1];
+} EFI_HII_AIBT_RESTORE_SCRN_BLOCK;
+
+///
+/// An animation block to describe an animation sequence that continuously cycles,
+/// and where one image is simply displayed over the previous image.
+///
+typedef EFI_HII_AIBT_OVERLAY_IMAGES_BLOCK EFI_HII_AIBT_OVERLAY_IMAGES_LOOP_BLOCK;
+
+///
+/// An animation block to describe an animation sequence that continuously cycles,
+/// and where the logical window is cleared to the specified color before
+/// the next image is displayed.
+///
+typedef EFI_HII_AIBT_CLEAR_IMAGES_BLOCK EFI_HII_AIBT_CLEAR_IMAGES_LOOP_BLOCK;
+
+///
+/// An animation block to describe an animation sequence that continuously cycles,
+/// and where the screen is restored to the original state before
+/// the next image is displayed.
+///
+typedef EFI_HII_AIBT_RESTORE_SCRN_BLOCK EFI_HII_AIBT_RESTORE_SCRN_LOOP_BLOCK;
+
+///
+/// Assigns a new character value to a previously defined animation sequence.
+///
+typedef struct _EFI_HII_AIBT_DUPLICATE_BLOCK {
+ ///
+ /// The previously defined animation ID with the exact same
+ /// animation information.
+ ///
+ EFI_ANIMATION_ID AnimationId;
+} EFI_HII_AIBT_DUPLICATE_BLOCK;
+
+///
+/// Skips animation IDs.
+///
+typedef struct _EFI_HII_AIBT_SKIP1_BLOCK {
+ ///
+ /// The unsigned 8-bit value to add to AnimationIdCurrent.
+ ///
+ UINT8 SkipCount;
+} EFI_HII_AIBT_SKIP1_BLOCK;
+
+///
+/// Skips animation IDs.
+///
+typedef struct _EFI_HII_AIBT_SKIP2_BLOCK {
+ ///
+ /// The unsigned 16-bit value to add to AnimationIdCurrent.
+ ///
+ UINT16 SkipCount;
+} EFI_HII_AIBT_SKIP2_BLOCK;
+
+#pragma pack()
+
+
+
+///
+/// References to string tokens must use this macro to enable scanning for
+/// token usages.
+///
+///
+/// STRING_TOKEN is not defined in UEFI specification. But it is placed
+/// here for the easy access by C files and VFR source files.
+///
+#define STRING_TOKEN(t) t
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiMultiPhase.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiMultiPhase.h
new file mode 100644
index 00000000..1d05ca55
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiMultiPhase.h
@@ -0,0 +1,171 @@
+/** @file
+ This includes some definitions introduced in UEFI that will be used in both PEI and DXE phases.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __UEFI_MULTIPHASE_H__
+#define __UEFI_MULTIPHASE_H__
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/Guid/WinCertificate.h>
+///
+/// Enumeration of memory types introduced in UEFI.
+///
+typedef enum {
+ ///
+ /// Not used.
+ ///
+ EfiReservedMemoryType,
+ ///
+ /// The code portions of a loaded application.
+ /// (Note that UEFI OS loaders are UEFI applications.)
+ ///
+ EfiLoaderCode,
+ ///
+ /// The data portions of a loaded application and the default data allocation
+ /// type used by an application to allocate pool memory.
+ ///
+ EfiLoaderData,
+ ///
+ /// The code portions of a loaded Boot Services Driver.
+ ///
+ EfiBootServicesCode,
+ ///
+ /// The data portions of a loaded Boot Serves Driver, and the default data
+ /// allocation type used by a Boot Services Driver to allocate pool memory.
+ ///
+ EfiBootServicesData,
+ ///
+ /// The code portions of a loaded Runtime Services Driver.
+ ///
+ EfiRuntimeServicesCode,
+ ///
+ /// The data portions of a loaded Runtime Services Driver and the default
+ /// data allocation type used by a Runtime Services Driver to allocate pool memory.
+ ///
+ EfiRuntimeServicesData,
+ ///
+ /// Free (unallocated) memory.
+ ///
+ EfiConventionalMemory,
+ ///
+ /// Memory in which errors have been detected.
+ ///
+ EfiUnusableMemory,
+ ///
+ /// Memory that holds the ACPI tables.
+ ///
+ EfiACPIReclaimMemory,
+ ///
+ /// Address space reserved for use by the firmware.
+ ///
+ EfiACPIMemoryNVS,
+ ///
+ /// Used by system firmware to request that a memory-mapped IO region
+ /// be mapped by the OS to a virtual address so it can be accessed by EFI runtime services.
+ ///
+ EfiMemoryMappedIO,
+ ///
+ /// System memory-mapped IO region that is used to translate memory
+ /// cycles to IO cycles by the processor.
+ ///
+ EfiMemoryMappedIOPortSpace,
+ ///
+ /// Address space reserved by the firmware for code that is part of the processor.
+ ///
+ EfiPalCode,
+ EfiMaxMemoryType
+} EFI_MEMORY_TYPE;
+
+///
+/// Data structure that precedes all of the standard EFI table types.
+///
+typedef struct {
+ ///
+ /// A 64-bit signature that identifies the type of table that follows.
+ /// Unique signatures have been generated for the EFI System Table,
+ /// the EFI Boot Services Table, and the EFI Runtime Services Table.
+ ///
+ UINT64 Signature;
+ ///
+ /// The revision of the EFI Specification to which this table
+ /// conforms. The upper 16 bits of this field contain the major
+ /// revision value, and the lower 16 bits contain the minor revision
+ /// value. The minor revision values are limited to the range of 00..99.
+ ///
+ UINT32 Revision;
+ ///
+ /// The size, in bytes, of the entire table including the EFI_TABLE_HEADER.
+ ///
+ UINT32 HeaderSize;
+ ///
+ /// The 32-bit CRC for the entire table. This value is computed by
+ /// setting this field to 0, and computing the 32-bit CRC for HeaderSize bytes.
+ ///
+ UINT32 CRC32;
+ ///
+ /// Reserved field that must be set to 0.
+ ///
+ UINT32 Reserved;
+} EFI_TABLE_HEADER;
+
+///
+/// Attributes of variable.
+///
+#define EFI_VARIABLE_NON_VOLATILE 0x00000001
+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
+#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008
+
+///
+/// This attribute is identified by the mnemonic 'HR'
+/// elsewhere in this specification.
+///
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010
+
+///
+/// AuthInfo is a WIN_CERTIFICATE using the wCertificateType
+/// WIN_CERTIFICATE_UEFI_GUID and the CertType
+/// EFI_CERT_TYPE_RSA2048_SHA256. If the attribute specifies
+/// authenticated access, then the Data buffer should begin with an
+/// authentication descriptor prior to the data payload and DataSize
+/// should reflect the data.and descriptor size. The caller
+/// shall digest the Monotonic Count value and the associated data
+/// for the variable update using the SHA-256 1-way hash algorithm.
+/// The ensuing the 32-byte digest will be signed using the private
+/// key associated w/ the public/private 2048-bit RSA key-pair. The
+/// WIN_CERTIFICATE shall be used to describe the signature of the
+/// Variable data *Data. In addition, the signature will also
+/// include the MonotonicCount value to guard against replay attacks.
+///
+typedef struct {
+ ///
+ /// Included in the signature of
+ /// AuthInfo.Used to ensure freshness/no
+ /// replay. Incremented during each
+ /// "Write" access.
+ ///
+ UINT64 MonotonicCount;
+ ///
+ /// Provides the authorization for the variable
+ /// access. It is a signature across the
+ /// variable data and the Monotonic Count
+ /// value. Caller uses Private key that is
+ /// associated with a public key that has been
+ /// provisioned via the key exchange.
+ ///
+ WIN_CERTIFICATE_UEFI_GUID AuthInfo;
+} EFI_VARIABLE_AUTHENTICATION;
+
+#endif
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiPxe.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiPxe.h
new file mode 100644
index 00000000..0b8da5fa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiPxe.h
@@ -0,0 +1,1772 @@
+/** @file
+ This header file contains all of the PXE type definitions,
+ structure prototypes, global variables and constants that
+ are needed for porting PXE to EFI.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ 32/64-bit PXE specification:
+ alpha-4, 99-Dec-17.
+
+**/
+
+#ifndef __EFI_PXE_H__
+#define __EFI_PXE_H__
+
+FILE_LICENCE ( BSD3 );
+
+#pragma pack(1)
+
+#define PXE_BUSTYPE(a, b, c, d) \
+ ( \
+ (((PXE_UINT32) (d) & 0xFF) << 24) | (((PXE_UINT32) (c) & 0xFF) << 16) | (((PXE_UINT32) (b) & 0xFF) << 8) | \
+ ((PXE_UINT32) (a) & 0xFF) \
+ )
+
+///
+/// UNDI ROM ID and devive ID signature.
+///
+#define PXE_BUSTYPE_PXE PXE_BUSTYPE ('!', 'P', 'X', 'E')
+
+///
+/// BUS ROM ID signatures.
+///
+#define PXE_BUSTYPE_PCI PXE_BUSTYPE ('P', 'C', 'I', 'R')
+#define PXE_BUSTYPE_PC_CARD PXE_BUSTYPE ('P', 'C', 'C', 'R')
+#define PXE_BUSTYPE_USB PXE_BUSTYPE ('U', 'S', 'B', 'R')
+#define PXE_BUSTYPE_1394 PXE_BUSTYPE ('1', '3', '9', '4')
+
+#define PXE_SWAP_UINT16(n) ((((PXE_UINT16) (n) & 0x00FF) << 8) | (((PXE_UINT16) (n) & 0xFF00) >> 8))
+
+#define PXE_SWAP_UINT32(n) \
+ ((((PXE_UINT32)(n) & 0x000000FF) << 24) | \
+ (((PXE_UINT32)(n) & 0x0000FF00) << 8) | \
+ (((PXE_UINT32)(n) & 0x00FF0000) >> 8) | \
+ (((PXE_UINT32)(n) & 0xFF000000) >> 24))
+
+#define PXE_SWAP_UINT64(n) \
+ ((((PXE_UINT64)(n) & 0x00000000000000FFULL) << 56) | \
+ (((PXE_UINT64)(n) & 0x000000000000FF00ULL) << 40) | \
+ (((PXE_UINT64)(n) & 0x0000000000FF0000ULL) << 24) | \
+ (((PXE_UINT64)(n) & 0x00000000FF000000ULL) << 8) | \
+ (((PXE_UINT64)(n) & 0x000000FF00000000ULL) >> 8) | \
+ (((PXE_UINT64)(n) & 0x0000FF0000000000ULL) >> 24) | \
+ (((PXE_UINT64)(n) & 0x00FF000000000000ULL) >> 40) | \
+ (((PXE_UINT64)(n) & 0xFF00000000000000ULL) >> 56))
+
+
+#define PXE_CPBSIZE_NOT_USED 0 ///< zero
+#define PXE_DBSIZE_NOT_USED 0 ///< zero
+#define PXE_CPBADDR_NOT_USED (PXE_UINT64) 0 ///< zero
+#define PXE_DBADDR_NOT_USED (PXE_UINT64) 0 ///< zero
+#define PXE_CONST CONST
+
+#define PXE_VOLATILE volatile
+
+typedef VOID PXE_VOID;
+typedef UINT8 PXE_UINT8;
+typedef UINT16 PXE_UINT16;
+typedef UINT32 PXE_UINT32;
+typedef UINTN PXE_UINTN;
+
+///
+/// Typedef unsigned long PXE_UINT64.
+///
+typedef UINT64 PXE_UINT64;
+
+typedef PXE_UINT8 PXE_BOOL;
+#define PXE_FALSE 0 ///< zero
+#define PXE_TRUE (!PXE_FALSE)
+
+typedef PXE_UINT16 PXE_OPCODE;
+
+///
+/// Return UNDI operational state.
+///
+#define PXE_OPCODE_GET_STATE 0x0000
+
+///
+/// Change UNDI operational state from Stopped to Started.
+///
+#define PXE_OPCODE_START 0x0001
+
+///
+/// Change UNDI operational state from Started to Stopped.
+///
+#define PXE_OPCODE_STOP 0x0002
+
+///
+/// Get UNDI initialization information.
+///
+#define PXE_OPCODE_GET_INIT_INFO 0x0003
+
+///
+/// Get NIC configuration information.
+///
+#define PXE_OPCODE_GET_CONFIG_INFO 0x0004
+
+///
+/// Changed UNDI operational state from Started to Initialized.
+///
+#define PXE_OPCODE_INITIALIZE 0x0005
+
+///
+/// Re-initialize the NIC H/W.
+///
+#define PXE_OPCODE_RESET 0x0006
+
+///
+/// Change the UNDI operational state from Initialized to Started.
+///
+#define PXE_OPCODE_SHUTDOWN 0x0007
+
+///
+/// Read & change state of external interrupt enables.
+///
+#define PXE_OPCODE_INTERRUPT_ENABLES 0x0008
+
+///
+/// Read & change state of packet receive filters.
+///
+#define PXE_OPCODE_RECEIVE_FILTERS 0x0009
+
+///
+/// Read & change station MAC address.
+///
+#define PXE_OPCODE_STATION_ADDRESS 0x000A
+
+///
+/// Read traffic statistics.
+///
+#define PXE_OPCODE_STATISTICS 0x000B
+
+///
+/// Convert multicast IP address to multicast MAC address.
+///
+#define PXE_OPCODE_MCAST_IP_TO_MAC 0x000C
+
+///
+/// Read or change non-volatile storage on the NIC.
+///
+#define PXE_OPCODE_NVDATA 0x000D
+
+///
+/// Get & clear interrupt status.
+///
+#define PXE_OPCODE_GET_STATUS 0x000E
+
+///
+/// Fill media header in packet for transmit.
+///
+#define PXE_OPCODE_FILL_HEADER 0x000F
+
+///
+/// Transmit packet(s).
+///
+#define PXE_OPCODE_TRANSMIT 0x0010
+
+///
+/// Receive packet.
+///
+#define PXE_OPCODE_RECEIVE 0x0011
+
+///
+/// Last valid PXE UNDI OpCode number.
+///
+#define PXE_OPCODE_LAST_VALID 0x0011
+
+typedef PXE_UINT16 PXE_OPFLAGS;
+
+#define PXE_OPFLAGS_NOT_USED 0x0000
+
+//
+// //////////////////////////////////////
+// UNDI Get State
+//
+// No OpFlags
+
+////////////////////////////////////////
+// UNDI Start
+//
+// No OpFlags
+
+////////////////////////////////////////
+// UNDI Stop
+//
+// No OpFlags
+
+////////////////////////////////////////
+// UNDI Get Init Info
+//
+// No Opflags
+
+////////////////////////////////////////
+// UNDI Get Config Info
+//
+// No Opflags
+
+///
+/// UNDI Initialize
+///
+#define PXE_OPFLAGS_INITIALIZE_CABLE_DETECT_MASK 0x0001
+#define PXE_OPFLAGS_INITIALIZE_DETECT_CABLE 0x0000
+#define PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE 0x0001
+
+///
+///
+/// UNDI Reset
+///
+#define PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS 0x0001
+#define PXE_OPFLAGS_RESET_DISABLE_FILTERS 0x0002
+
+///
+/// UNDI Shutdown.
+///
+/// No OpFlags.
+
+///
+/// UNDI Interrupt Enables.
+///
+///
+/// Select whether to enable or disable external interrupt signals.
+/// Setting both enable and disable will return PXE_STATCODE_INVALID_OPFLAGS.
+///
+#define PXE_OPFLAGS_INTERRUPT_OPMASK 0xC000
+#define PXE_OPFLAGS_INTERRUPT_ENABLE 0x8000
+#define PXE_OPFLAGS_INTERRUPT_DISABLE 0x4000
+#define PXE_OPFLAGS_INTERRUPT_READ 0x0000
+
+///
+/// Enable receive interrupts. An external interrupt will be generated
+/// after a complete non-error packet has been received.
+///
+#define PXE_OPFLAGS_INTERRUPT_RECEIVE 0x0001
+
+///
+/// Enable transmit interrupts. An external interrupt will be generated
+/// after a complete non-error packet has been transmitted.
+///
+#define PXE_OPFLAGS_INTERRUPT_TRANSMIT 0x0002
+
+///
+/// Enable command interrupts. An external interrupt will be generated
+/// when command execution stops.
+///
+#define PXE_OPFLAGS_INTERRUPT_COMMAND 0x0004
+
+///
+/// Generate software interrupt. Setting this bit generates an external
+/// interrupt, if it is supported by the hardware.
+///
+#define PXE_OPFLAGS_INTERRUPT_SOFTWARE 0x0008
+
+///
+/// UNDI Receive Filters.
+///
+///
+/// Select whether to enable or disable receive filters.
+/// Setting both enable and disable will return PXE_STATCODE_INVALID_OPCODE.
+///
+#define PXE_OPFLAGS_RECEIVE_FILTER_OPMASK 0xC000
+#define PXE_OPFLAGS_RECEIVE_FILTER_ENABLE 0x8000
+#define PXE_OPFLAGS_RECEIVE_FILTER_DISABLE 0x4000
+#define PXE_OPFLAGS_RECEIVE_FILTER_READ 0x0000
+
+///
+/// To reset the contents of the multicast MAC address filter list,
+/// set this OpFlag:
+///
+#define PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST 0x2000
+
+///
+/// Enable unicast packet receiving. Packets sent to the current station
+/// MAC address will be received.
+///
+#define PXE_OPFLAGS_RECEIVE_FILTER_UNICAST 0x0001
+
+///
+/// Enable broadcast packet receiving. Packets sent to the broadcast
+/// MAC address will be received.
+///
+#define PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST 0x0002
+
+///
+/// Enable filtered multicast packet receiving. Packets sent to any
+/// of the multicast MAC addresses in the multicast MAC address filter
+/// list will be received. If the filter list is empty, no multicast
+///
+#define PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST 0x0004
+
+///
+/// Enable promiscuous packet receiving. All packets will be received.
+///
+#define PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS 0x0008
+
+///
+/// Enable promiscuous multicast packet receiving. All multicast
+/// packets will be received.
+///
+#define PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST 0x0010
+
+///
+/// UNDI Station Address.
+///
+#define PXE_OPFLAGS_STATION_ADDRESS_READ 0x0000
+#define PXE_OPFLAGS_STATION_ADDRESS_WRITE 0x0000
+#define PXE_OPFLAGS_STATION_ADDRESS_RESET 0x0001
+
+///
+/// UNDI Statistics.
+///
+#define PXE_OPFLAGS_STATISTICS_READ 0x0000
+#define PXE_OPFLAGS_STATISTICS_RESET 0x0001
+
+///
+/// UNDI MCast IP to MAC.
+///
+///
+/// Identify the type of IP address in the CPB.
+///
+#define PXE_OPFLAGS_MCAST_IP_TO_MAC_OPMASK 0x0003
+#define PXE_OPFLAGS_MCAST_IPV4_TO_MAC 0x0000
+#define PXE_OPFLAGS_MCAST_IPV6_TO_MAC 0x0001
+
+///
+/// UNDI NvData.
+///
+///
+/// Select the type of non-volatile data operation.
+///
+#define PXE_OPFLAGS_NVDATA_OPMASK 0x0001
+#define PXE_OPFLAGS_NVDATA_READ 0x0000
+#define PXE_OPFLAGS_NVDATA_WRITE 0x0001
+
+///
+/// UNDI Get Status.
+///
+///
+/// Return current interrupt status. This will also clear any interrupts
+/// that are currently set. This can be used in a polling routine. The
+/// interrupt flags are still set and cleared even when the interrupts
+/// are disabled.
+///
+#define PXE_OPFLAGS_GET_INTERRUPT_STATUS 0x0001
+
+///
+/// Return list of transmitted buffers for recycling. Transmit buffers
+/// must not be changed or unallocated until they have recycled. After
+/// issuing a transmit command, wait for a transmit complete interrupt.
+/// When a transmit complete interrupt is received, read the transmitted
+/// buffers. Do not plan on getting one buffer per interrupt. Some
+/// NICs and UNDIs may transmit multiple buffers per interrupt.
+///
+#define PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS 0x0002
+
+///
+/// Return current media status.
+///
+#define PXE_OPFLAGS_GET_MEDIA_STATUS 0x0004
+
+///
+/// UNDI Fill Header.
+///
+#define PXE_OPFLAGS_FILL_HEADER_OPMASK 0x0001
+#define PXE_OPFLAGS_FILL_HEADER_FRAGMENTED 0x0001
+#define PXE_OPFLAGS_FILL_HEADER_WHOLE 0x0000
+
+///
+/// UNDI Transmit.
+///
+///
+/// S/W UNDI only. Return after the packet has been transmitted. A
+/// transmit complete interrupt will still be generated and the transmit
+/// buffer will have to be recycled.
+///
+#define PXE_OPFLAGS_SWUNDI_TRANSMIT_OPMASK 0x0001
+#define PXE_OPFLAGS_TRANSMIT_BLOCK 0x0001
+#define PXE_OPFLAGS_TRANSMIT_DONT_BLOCK 0x0000
+
+#define PXE_OPFLAGS_TRANSMIT_OPMASK 0x0002
+#define PXE_OPFLAGS_TRANSMIT_FRAGMENTED 0x0002
+#define PXE_OPFLAGS_TRANSMIT_WHOLE 0x0000
+
+///
+/// UNDI Receive.
+///
+/// No OpFlags.
+///
+
+///
+/// PXE STATFLAGS.
+///
+typedef PXE_UINT16 PXE_STATFLAGS;
+
+#define PXE_STATFLAGS_INITIALIZE 0x0000
+
+///
+/// Common StatFlags that can be returned by all commands.
+///
+///
+/// The COMMAND_COMPLETE and COMMAND_FAILED status flags must be
+/// implemented by all UNDIs. COMMAND_QUEUED is only needed by UNDIs
+/// that support command queuing.
+///
+#define PXE_STATFLAGS_STATUS_MASK 0xC000
+#define PXE_STATFLAGS_COMMAND_COMPLETE 0xC000
+#define PXE_STATFLAGS_COMMAND_FAILED 0x8000
+#define PXE_STATFLAGS_COMMAND_QUEUED 0x4000
+
+///
+/// UNDI Get State.
+///
+#define PXE_STATFLAGS_GET_STATE_MASK 0x0003
+#define PXE_STATFLAGS_GET_STATE_INITIALIZED 0x0002
+#define PXE_STATFLAGS_GET_STATE_STARTED 0x0001
+#define PXE_STATFLAGS_GET_STATE_STOPPED 0x0000
+
+///
+/// UNDI Start.
+///
+/// No additional StatFlags.
+///
+
+///
+/// UNDI Get Init Info.
+///
+#define PXE_STATFLAGS_CABLE_DETECT_MASK 0x0001
+#define PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED 0x0000
+#define PXE_STATFLAGS_CABLE_DETECT_SUPPORTED 0x0001
+
+#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK 0x0002
+#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED 0x0000
+#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED 0x0002
+
+///
+/// UNDI Initialize.
+///
+#define PXE_STATFLAGS_INITIALIZED_NO_MEDIA 0x0001
+
+///
+/// UNDI Reset.
+///
+#define PXE_STATFLAGS_RESET_NO_MEDIA 0x0001
+
+///
+/// UNDI Shutdown.
+///
+/// No additional StatFlags.
+
+///
+/// UNDI Interrupt Enables.
+///
+///
+/// If set, receive interrupts are enabled.
+///
+#define PXE_STATFLAGS_INTERRUPT_RECEIVE 0x0001
+
+///
+/// If set, transmit interrupts are enabled.
+///
+#define PXE_STATFLAGS_INTERRUPT_TRANSMIT 0x0002
+
+///
+/// If set, command interrupts are enabled.
+///
+#define PXE_STATFLAGS_INTERRUPT_COMMAND 0x0004
+
+///
+/// UNDI Receive Filters.
+///
+
+///
+/// If set, unicast packets will be received.
+///
+#define PXE_STATFLAGS_RECEIVE_FILTER_UNICAST 0x0001
+
+///
+/// If set, broadcast packets will be received.
+///
+#define PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST 0x0002
+
+///
+/// If set, multicast packets that match up with the multicast address
+/// filter list will be received.
+///
+#define PXE_STATFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST 0x0004
+
+///
+/// If set, all packets will be received.
+///
+#define PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS 0x0008
+
+///
+/// If set, all multicast packets will be received.
+///
+#define PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST 0x0010
+
+///
+/// UNDI Station Address.
+///
+/// No additional StatFlags.
+///
+
+///
+/// UNDI Statistics.
+///
+/// No additional StatFlags.
+///
+
+///
+//// UNDI MCast IP to MAC.
+////
+//// No additional StatFlags.
+
+///
+/// UNDI NvData.
+///
+/// No additional StatFlags.
+///
+
+///
+/// UNDI Get Status.
+///
+
+///
+/// Use to determine if an interrupt has occurred.
+///
+#define PXE_STATFLAGS_GET_STATUS_INTERRUPT_MASK 0x000F
+#define PXE_STATFLAGS_GET_STATUS_NO_INTERRUPTS 0x0000
+
+///
+/// If set, at least one receive interrupt occurred.
+///
+#define PXE_STATFLAGS_GET_STATUS_RECEIVE 0x0001
+
+///
+/// If set, at least one transmit interrupt occurred.
+///
+#define PXE_STATFLAGS_GET_STATUS_TRANSMIT 0x0002
+
+///
+/// If set, at least one command interrupt occurred.
+///
+#define PXE_STATFLAGS_GET_STATUS_COMMAND 0x0004
+
+///
+/// If set, at least one software interrupt occurred.
+///
+#define PXE_STATFLAGS_GET_STATUS_SOFTWARE 0x0008
+
+///
+/// This flag is set if the transmitted buffer queue is empty. This flag
+/// will be set if all transmitted buffer addresses get written into the DB.
+///
+#define PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY 0x0010
+
+///
+/// This flag is set if no transmitted buffer addresses were written
+/// into the DB. (This could be because DBsize was too small.)
+///
+#define PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN 0x0020
+
+///
+/// This flag is set if there is no media detected.
+///
+#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA 0x0040
+
+///
+/// UNDI Fill Header.
+///
+/// No additional StatFlags.
+///
+
+///
+/// UNDI Transmit.
+///
+/// No additional StatFlags.
+
+///
+/// UNDI Receive
+///.
+
+///
+/// No additional StatFlags.
+///
+typedef PXE_UINT16 PXE_STATCODE;
+
+#define PXE_STATCODE_INITIALIZE 0x0000
+
+///
+/// Common StatCodes returned by all UNDI commands, UNDI protocol functions
+/// and BC protocol functions.
+///
+#define PXE_STATCODE_SUCCESS 0x0000
+
+#define PXE_STATCODE_INVALID_CDB 0x0001
+#define PXE_STATCODE_INVALID_CPB 0x0002
+#define PXE_STATCODE_BUSY 0x0003
+#define PXE_STATCODE_QUEUE_FULL 0x0004
+#define PXE_STATCODE_ALREADY_STARTED 0x0005
+#define PXE_STATCODE_NOT_STARTED 0x0006
+#define PXE_STATCODE_NOT_SHUTDOWN 0x0007
+#define PXE_STATCODE_ALREADY_INITIALIZED 0x0008
+#define PXE_STATCODE_NOT_INITIALIZED 0x0009
+#define PXE_STATCODE_DEVICE_FAILURE 0x000A
+#define PXE_STATCODE_NVDATA_FAILURE 0x000B
+#define PXE_STATCODE_UNSUPPORTED 0x000C
+#define PXE_STATCODE_BUFFER_FULL 0x000D
+#define PXE_STATCODE_INVALID_PARAMETER 0x000E
+#define PXE_STATCODE_INVALID_UNDI 0x000F
+#define PXE_STATCODE_IPV4_NOT_SUPPORTED 0x0010
+#define PXE_STATCODE_IPV6_NOT_SUPPORTED 0x0011
+#define PXE_STATCODE_NOT_ENOUGH_MEMORY 0x0012
+#define PXE_STATCODE_NO_DATA 0x0013
+
+typedef PXE_UINT16 PXE_IFNUM;
+
+///
+/// This interface number must be passed to the S/W UNDI Start command.
+///
+#define PXE_IFNUM_START 0x0000
+
+///
+/// This interface number is returned by the S/W UNDI Get State and
+/// Start commands if information in the CDB, CPB or DB is invalid.
+///
+#define PXE_IFNUM_INVALID 0x0000
+
+typedef PXE_UINT16 PXE_CONTROL;
+
+///
+/// Setting this flag directs the UNDI to queue this command for later
+/// execution if the UNDI is busy and it supports command queuing.
+/// If queuing is not supported, a PXE_STATCODE_INVALID_CONTROL error
+/// is returned. If the queue is full, a PXE_STATCODE_CDB_QUEUE_FULL
+/// error is returned.
+///
+#define PXE_CONTROL_QUEUE_IF_BUSY 0x0002
+
+///
+/// These two bit values are used to determine if there are more UNDI
+/// CDB structures following this one. If the link bit is set, there
+/// must be a CDB structure following this one. Execution will start
+/// on the next CDB structure as soon as this one completes successfully.
+/// If an error is generated by this command, execution will stop.
+///
+#define PXE_CONTROL_LINK 0x0001
+#define PXE_CONTROL_LAST_CDB_IN_LIST 0x0000
+
+typedef PXE_UINT8 PXE_FRAME_TYPE;
+
+#define PXE_FRAME_TYPE_NONE 0x00
+#define PXE_FRAME_TYPE_UNICAST 0x01
+#define PXE_FRAME_TYPE_BROADCAST 0x02
+#define PXE_FRAME_TYPE_FILTERED_MULTICAST 0x03
+#define PXE_FRAME_TYPE_PROMISCUOUS 0x04
+#define PXE_FRAME_TYPE_PROMISCUOUS_MULTICAST 0x05
+
+#define PXE_FRAME_TYPE_MULTICAST PXE_FRAME_TYPE_FILTERED_MULTICAST
+
+typedef PXE_UINT32 PXE_IPV4;
+
+typedef PXE_UINT32 PXE_IPV6[4];
+#define PXE_MAC_LENGTH 32
+
+typedef PXE_UINT8 PXE_MAC_ADDR[PXE_MAC_LENGTH];
+
+typedef PXE_UINT8 PXE_IFTYPE;
+typedef UINT16 PXE_MEDIA_PROTOCOL;
+
+///
+/// This information is from the ARP section of RFC 1700.
+///
+/// 1 Ethernet (10Mb) [JBP]
+/// 2 Experimental Ethernet (3Mb) [JBP]
+/// 3 Amateur Radio AX.25 [PXK]
+/// 4 Proteon ProNET Token Ring [JBP]
+/// 5 Chaos [GXP]
+/// 6 IEEE 802 Networks [JBP]
+/// 7 ARCNET [JBP]
+/// 8 Hyperchannel [JBP]
+/// 9 Lanstar [TU]
+/// 10 Autonet Short Address [MXB1]
+/// 11 LocalTalk [JKR1]
+/// 12 LocalNet (IBM* PCNet or SYTEK* LocalNET) [JXM]
+/// 13 Ultra link [RXD2]
+/// 14 SMDS [GXC1]
+/// 15 Frame Relay [AGM]
+/// 16 Asynchronous Transmission Mode (ATM) [JXB2]
+/// 17 HDLC [JBP]
+/// 18 Fibre Channel [Yakov Rekhter]
+/// 19 Asynchronous Transmission Mode (ATM) [Mark Laubach]
+/// 20 Serial Line [JBP]
+/// 21 Asynchronous Transmission Mode (ATM) [MXB1]
+///
+/// * Other names and brands may be claimed as the property of others.
+///
+#define PXE_IFTYPE_ETHERNET 0x01
+#define PXE_IFTYPE_TOKENRING 0x04
+#define PXE_IFTYPE_FIBRE_CHANNEL 0x12
+
+typedef struct s_pxe_hw_undi {
+ PXE_UINT32 Signature; ///< PXE_ROMID_SIGNATURE.
+ PXE_UINT8 Len; ///< sizeof(PXE_HW_UNDI).
+ PXE_UINT8 Fudge; ///< makes 8-bit cksum equal zero.
+ PXE_UINT8 Rev; ///< PXE_ROMID_REV.
+ PXE_UINT8 IFcnt; ///< physical connector count.
+ PXE_UINT8 MajorVer; ///< PXE_ROMID_MAJORVER.
+ PXE_UINT8 MinorVer; ///< PXE_ROMID_MINORVER.
+ PXE_UINT16 reserved; ///< zero, not used.
+ PXE_UINT32 Implementation; ///< implementation flags.
+ ///< reserved ///< vendor use.
+ ///< UINT32 Status; ///< status port.
+ ///< UINT32 Command; ///< command port.
+ ///< UINT64 CDBaddr; ///< CDB address port.
+ ///<
+} PXE_HW_UNDI;
+
+///
+/// Status port bit definitions.
+///
+
+///
+/// UNDI operation state.
+///
+#define PXE_HWSTAT_STATE_MASK 0xC0000000
+#define PXE_HWSTAT_BUSY 0xC0000000
+#define PXE_HWSTAT_INITIALIZED 0x80000000
+#define PXE_HWSTAT_STARTED 0x40000000
+#define PXE_HWSTAT_STOPPED 0x00000000
+
+///
+/// If set, last command failed.
+///
+#define PXE_HWSTAT_COMMAND_FAILED 0x20000000
+
+///
+/// If set, identifies enabled receive filters.
+///
+#define PXE_HWSTAT_PROMISCUOUS_MULTICAST_RX_ENABLED 0x00001000
+#define PXE_HWSTAT_PROMISCUOUS_RX_ENABLED 0x00000800
+#define PXE_HWSTAT_BROADCAST_RX_ENABLED 0x00000400
+#define PXE_HWSTAT_MULTICAST_RX_ENABLED 0x00000200
+#define PXE_HWSTAT_UNICAST_RX_ENABLED 0x00000100
+
+///
+/// If set, identifies enabled external interrupts.
+///
+#define PXE_HWSTAT_SOFTWARE_INT_ENABLED 0x00000080
+#define PXE_HWSTAT_TX_COMPLETE_INT_ENABLED 0x00000040
+#define PXE_HWSTAT_PACKET_RX_INT_ENABLED 0x00000020
+#define PXE_HWSTAT_CMD_COMPLETE_INT_ENABLED 0x00000010
+
+///
+/// If set, identifies pending interrupts.
+///
+#define PXE_HWSTAT_SOFTWARE_INT_PENDING 0x00000008
+#define PXE_HWSTAT_TX_COMPLETE_INT_PENDING 0x00000004
+#define PXE_HWSTAT_PACKET_RX_INT_PENDING 0x00000002
+#define PXE_HWSTAT_CMD_COMPLETE_INT_PENDING 0x00000001
+
+///
+/// Command port definitions.
+///
+
+///
+/// If set, CDB identified in CDBaddr port is given to UNDI.
+/// If not set, other bits in this word will be processed.
+///
+#define PXE_HWCMD_ISSUE_COMMAND 0x80000000
+#define PXE_HWCMD_INTS_AND_FILTS 0x00000000
+
+///
+/// Use these to enable/disable receive filters.
+///
+#define PXE_HWCMD_PROMISCUOUS_MULTICAST_RX_ENABLE 0x00001000
+#define PXE_HWCMD_PROMISCUOUS_RX_ENABLE 0x00000800
+#define PXE_HWCMD_BROADCAST_RX_ENABLE 0x00000400
+#define PXE_HWCMD_MULTICAST_RX_ENABLE 0x00000200
+#define PXE_HWCMD_UNICAST_RX_ENABLE 0x00000100
+
+///
+/// Use these to enable/disable external interrupts.
+///
+#define PXE_HWCMD_SOFTWARE_INT_ENABLE 0x00000080
+#define PXE_HWCMD_TX_COMPLETE_INT_ENABLE 0x00000040
+#define PXE_HWCMD_PACKET_RX_INT_ENABLE 0x00000020
+#define PXE_HWCMD_CMD_COMPLETE_INT_ENABLE 0x00000010
+
+///
+/// Use these to clear pending external interrupts.
+///
+#define PXE_HWCMD_CLEAR_SOFTWARE_INT 0x00000008
+#define PXE_HWCMD_CLEAR_TX_COMPLETE_INT 0x00000004
+#define PXE_HWCMD_CLEAR_PACKET_RX_INT 0x00000002
+#define PXE_HWCMD_CLEAR_CMD_COMPLETE_INT 0x00000001
+
+typedef struct s_pxe_sw_undi {
+ PXE_UINT32 Signature; ///< PXE_ROMID_SIGNATURE.
+ PXE_UINT8 Len; ///< sizeof(PXE_SW_UNDI).
+ PXE_UINT8 Fudge; ///< makes 8-bit cksum zero.
+ PXE_UINT8 Rev; ///< PXE_ROMID_REV.
+ PXE_UINT8 IFcnt; ///< physical connector count.
+ PXE_UINT8 MajorVer; ///< PXE_ROMID_MAJORVER.
+ PXE_UINT8 MinorVer; ///< PXE_ROMID_MINORVER.
+ PXE_UINT16 reserved1; ///< zero, not used.
+ PXE_UINT32 Implementation; ///< Implementation flags.
+ PXE_UINT64 EntryPoint; ///< API entry point.
+ PXE_UINT8 reserved2[3]; ///< zero, not used.
+ PXE_UINT8 BusCnt; ///< number of bustypes supported.
+ PXE_UINT32 BusType[1]; ///< list of supported bustypes.
+} PXE_SW_UNDI;
+
+typedef union u_pxe_undi {
+ PXE_HW_UNDI hw;
+ PXE_SW_UNDI sw;
+} PXE_UNDI;
+
+///
+/// Signature of !PXE structure.
+///
+#define PXE_ROMID_SIGNATURE PXE_BUSTYPE ('!', 'P', 'X', 'E')
+
+///
+/// !PXE structure format revision
+///.
+#define PXE_ROMID_REV 0x02
+
+///
+/// UNDI command interface revision. These are the values that get sent
+/// in option 94 (Client Network Interface Identifier) in the DHCP Discover
+/// and PXE Boot Server Request packets.
+///
+#define PXE_ROMID_MAJORVER 0x03
+#define PXE_ROMID_MINORVER 0x01
+
+///
+/// Implementation flags.
+///
+#define PXE_ROMID_IMP_HW_UNDI 0x80000000
+#define PXE_ROMID_IMP_SW_VIRT_ADDR 0x40000000
+#define PXE_ROMID_IMP_64BIT_DEVICE 0x00010000
+#define PXE_ROMID_IMP_FRAG_SUPPORTED 0x00008000
+#define PXE_ROMID_IMP_CMD_LINK_SUPPORTED 0x00004000
+#define PXE_ROMID_IMP_CMD_QUEUE_SUPPORTED 0x00002000
+#define PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED 0x00001000
+#define PXE_ROMID_IMP_NVDATA_SUPPORT_MASK 0x00000C00
+#define PXE_ROMID_IMP_NVDATA_BULK_WRITABLE 0x00000C00
+#define PXE_ROMID_IMP_NVDATA_SPARSE_WRITABLE 0x00000800
+#define PXE_ROMID_IMP_NVDATA_READ_ONLY 0x00000400
+#define PXE_ROMID_IMP_NVDATA_NOT_AVAILABLE 0x00000000
+#define PXE_ROMID_IMP_STATISTICS_SUPPORTED 0x00000200
+#define PXE_ROMID_IMP_STATION_ADDR_SETTABLE 0x00000100
+#define PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED 0x00000080
+#define PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED 0x00000040
+#define PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED 0x00000020
+#define PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED 0x00000010
+#define PXE_ROMID_IMP_SOFTWARE_INT_SUPPORTED 0x00000008
+#define PXE_ROMID_IMP_TX_COMPLETE_INT_SUPPORTED 0x00000004
+#define PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED 0x00000002
+#define PXE_ROMID_IMP_CMD_COMPLETE_INT_SUPPORTED 0x00000001
+
+typedef struct s_pxe_cdb {
+ PXE_OPCODE OpCode;
+ PXE_OPFLAGS OpFlags;
+ PXE_UINT16 CPBsize;
+ PXE_UINT16 DBsize;
+ PXE_UINT64 CPBaddr;
+ PXE_UINT64 DBaddr;
+ PXE_STATCODE StatCode;
+ PXE_STATFLAGS StatFlags;
+ PXE_UINT16 IFnum;
+ PXE_CONTROL Control;
+} PXE_CDB;
+
+typedef union u_pxe_ip_addr {
+ PXE_IPV6 IPv6;
+ PXE_IPV4 IPv4;
+} PXE_IP_ADDR;
+
+typedef union pxe_device {
+ ///
+ /// PCI and PC Card NICs are both identified using bus, device
+ /// and function numbers. For PC Card, this may require PC
+ /// Card services to be loaded in the BIOS or preboot
+ /// environment.
+ ///
+ struct {
+ ///
+ /// See S/W UNDI ROMID structure definition for PCI and
+ /// PCC BusType definitions.
+ ///
+ PXE_UINT32 BusType;
+
+ ///
+ /// Bus, device & function numbers that locate this device.
+ ///
+ PXE_UINT16 Bus;
+ PXE_UINT8 Device;
+ PXE_UINT8 Function;
+ }
+ PCI, PCC;
+
+} PXE_DEVICE;
+
+///
+/// cpb and db definitions
+///
+#define MAX_PCI_CONFIG_LEN 64 ///< # of dwords.
+#define MAX_EEPROM_LEN 128 ///< # of dwords.
+#define MAX_XMIT_BUFFERS 32 ///< recycling Q length for xmit_done.
+#define MAX_MCAST_ADDRESS_CNT 8
+
+typedef struct s_pxe_cpb_start_30 {
+ ///
+ /// PXE_VOID Delay(UINTN microseconds);
+ ///
+ /// UNDI will never request a delay smaller than 10 microseconds
+ /// and will always request delays in increments of 10 microseconds.
+ /// The Delay() CallBack routine must delay between n and n + 10
+ /// microseconds before returning control to the UNDI.
+ ///
+ /// This field cannot be set to zero.
+ ///
+ UINT64 Delay;
+
+ ///
+ /// PXE_VOID Block(UINT32 enable);
+ ///
+ /// UNDI may need to block multi-threaded/multi-processor access to
+ /// critical code sections when programming or accessing the network
+ /// device. To this end, a blocking service is needed by the UNDI.
+ /// When UNDI needs a block, it will call Block() passing a non-zero
+ /// value. When UNDI no longer needs a block, it will call Block()
+ /// with a zero value. When called, if the Block() is already enabled,
+ /// do not return control to the UNDI until the previous Block() is
+ /// disabled.
+ ///
+ /// This field cannot be set to zero.
+ ///
+ UINT64 Block;
+
+ ///
+ /// PXE_VOID Virt2Phys(UINT64 virtual, UINT64 physical_ptr);
+ ///
+ /// UNDI will pass the virtual address of a buffer and the virtual
+ /// address of a 64-bit physical buffer. Convert the virtual address
+ /// to a physical address and write the result to the physical address
+ /// buffer. If virtual and physical addresses are the same, just
+ /// copy the virtual address to the physical address buffer.
+ ///
+ /// This field can be set to zero if virtual and physical addresses
+ /// are equal.
+ ///
+ UINT64 Virt2Phys;
+ ///
+ /// PXE_VOID Mem_IO(UINT8 read_write, UINT8 len, UINT64 port,
+ /// UINT64 buf_addr);
+ ///
+ /// UNDI will read or write the device io space using this call back
+ /// function. It passes the number of bytes as the len parameter and it
+ /// will be either 1,2,4 or 8.
+ ///
+ /// This field can not be set to zero.
+ ///
+ UINT64 Mem_IO;
+} PXE_CPB_START_30;
+
+typedef struct s_pxe_cpb_start_31 {
+ ///
+ /// PXE_VOID Delay(UINT64 UnqId, UINTN microseconds);
+ ///
+ /// UNDI will never request a delay smaller than 10 microseconds
+ /// and will always request delays in increments of 10 microseconds.
+ /// The Delay() CallBack routine must delay between n and n + 10
+ /// microseconds before returning control to the UNDI.
+ ///
+ /// This field cannot be set to zero.
+ ///
+ UINT64 Delay;
+
+ ///
+ /// PXE_VOID Block(UINT64 unq_id, UINT32 enable);
+ ///
+ /// UNDI may need to block multi-threaded/multi-processor access to
+ /// critical code sections when programming or accessing the network
+ /// device. To this end, a blocking service is needed by the UNDI.
+ /// When UNDI needs a block, it will call Block() passing a non-zero
+ /// value. When UNDI no longer needs a block, it will call Block()
+ /// with a zero value. When called, if the Block() is already enabled,
+ /// do not return control to the UNDI until the previous Block() is
+ /// disabled.
+ ///
+ /// This field cannot be set to zero.
+ ///
+ UINT64 Block;
+
+ ///
+ /// PXE_VOID Virt2Phys(UINT64 UnqId, UINT64 virtual, UINT64 physical_ptr);
+ ///
+ /// UNDI will pass the virtual address of a buffer and the virtual
+ /// address of a 64-bit physical buffer. Convert the virtual address
+ /// to a physical address and write the result to the physical address
+ /// buffer. If virtual and physical addresses are the same, just
+ /// copy the virtual address to the physical address buffer.
+ ///
+ /// This field can be set to zero if virtual and physical addresses
+ /// are equal.
+ ///
+ UINT64 Virt2Phys;
+ ///
+ /// PXE_VOID Mem_IO(UINT64 UnqId, UINT8 read_write, UINT8 len, UINT64 port,
+ /// UINT64 buf_addr);
+ ///
+ /// UNDI will read or write the device io space using this call back
+ /// function. It passes the number of bytes as the len parameter and it
+ /// will be either 1,2,4 or 8.
+ ///
+ /// This field can not be set to zero.
+ ///
+ UINT64 Mem_IO;
+ ///
+ /// PXE_VOID Map_Mem(UINT64 unq_id, UINT64 virtual_addr, UINT32 size,
+ /// UINT32 Direction, UINT64 mapped_addr);
+ ///
+ /// UNDI will pass the virtual address of a buffer, direction of the data
+ /// flow from/to the mapped buffer (the constants are defined below)
+ /// and a place holder (pointer) for the mapped address.
+ /// This call will Map the given address to a physical DMA address and write
+ /// the result to the mapped_addr pointer. If there is no need to
+ /// map the given address to a lower address (i.e. the given address is
+ /// associated with a physical address that is already compatible to be
+ /// used with the DMA, it converts the given virtual address to it's
+ /// physical address and write that in the mapped address pointer.
+ ///
+ /// This field can be set to zero if there is no mapping service available.
+ ///
+ UINT64 Map_Mem;
+
+ ///
+ /// PXE_VOID UnMap_Mem(UINT64 unq_id, UINT64 virtual_addr, UINT32 size,
+ /// UINT32 Direction, UINT64 mapped_addr);
+ ///
+ /// UNDI will pass the virtual and mapped addresses of a buffer.
+ /// This call will un map the given address.
+ ///
+ /// This field can be set to zero if there is no unmapping service available.
+ ///
+ UINT64 UnMap_Mem;
+
+ ///
+ /// PXE_VOID Sync_Mem(UINT64 unq_id, UINT64 virtual,
+ /// UINT32 size, UINT32 Direction, UINT64 mapped_addr);
+ ///
+ /// UNDI will pass the virtual and mapped addresses of a buffer.
+ /// This call will synchronize the contents of both the virtual and mapped.
+ /// buffers for the given Direction.
+ ///
+ /// This field can be set to zero if there is no service available.
+ ///
+ UINT64 Sync_Mem;
+
+ ///
+ /// protocol driver can provide anything for this Unique_ID, UNDI remembers
+ /// that as just a 64bit value assocaited to the interface specified by
+ /// the ifnum and gives it back as a parameter to all the call-back routines
+ /// when calling for that interface!
+ ///
+ UINT64 Unique_ID;
+} PXE_CPB_START_31;
+
+#define TO_AND_FROM_DEVICE 0
+#define FROM_DEVICE 1
+#define TO_DEVICE 2
+
+#define PXE_DELAY_MILLISECOND 1000
+#define PXE_DELAY_SECOND 1000000
+#define PXE_IO_READ 0
+#define PXE_IO_WRITE 1
+#define PXE_MEM_READ 2
+#define PXE_MEM_WRITE 4
+
+typedef struct s_pxe_db_get_init_info {
+ ///
+ /// Minimum length of locked memory buffer that must be given to
+ /// the Initialize command. Giving UNDI more memory will generally
+ /// give better performance.
+ ///
+ /// If MemoryRequired is zero, the UNDI does not need and will not
+ /// use system memory to receive and transmit packets.
+ ///
+ PXE_UINT32 MemoryRequired;
+
+ ///
+ /// Maximum frame data length for Tx/Rx excluding the media header.
+ ///
+ PXE_UINT32 FrameDataLen;
+
+ ///
+ /// Supported link speeds are in units of mega bits. Common ethernet
+ /// values are 10, 100 and 1000. Unused LinkSpeeds[] entries are zero
+ /// filled.
+ ///
+ PXE_UINT32 LinkSpeeds[4];
+
+ ///
+ /// Number of non-volatile storage items.
+ ///
+ PXE_UINT32 NvCount;
+
+ ///
+ /// Width of non-volatile storage item in bytes. 0, 1, 2 or 4
+ ///
+ PXE_UINT16 NvWidth;
+
+ ///
+ /// Media header length. This is the typical media header length for
+ /// this UNDI. This information is needed when allocating receive
+ /// and transmit buffers.
+ ///
+ PXE_UINT16 MediaHeaderLen;
+
+ ///
+ /// Number of bytes in the NIC hardware (MAC) address.
+ ///
+ PXE_UINT16 HWaddrLen;
+
+ ///
+ /// Maximum number of multicast MAC addresses in the multicast
+ /// MAC address filter list.
+ ///
+ PXE_UINT16 MCastFilterCnt;
+
+ ///
+ /// Default number and size of transmit and receive buffers that will
+ /// be allocated by the UNDI. If MemoryRequired is non-zero, this
+ /// allocation will come out of the memory buffer given to the Initialize
+ /// command. If MemoryRequired is zero, this allocation will come out of
+ /// memory on the NIC.
+ ///
+ PXE_UINT16 TxBufCnt;
+ PXE_UINT16 TxBufSize;
+ PXE_UINT16 RxBufCnt;
+ PXE_UINT16 RxBufSize;
+
+ ///
+ /// Hardware interface types defined in the Assigned Numbers RFC
+ /// and used in DHCP and ARP packets.
+ /// See the PXE_IFTYPE typedef and PXE_IFTYPE_xxx macros.
+ ///
+ PXE_UINT8 IFtype;
+
+ ///
+ /// Supported duplex. See PXE_DUPLEX_xxxxx #defines below.
+ ///
+ PXE_UINT8 SupportedDuplexModes;
+
+ ///
+ /// Supported loopback options. See PXE_LOOPBACK_xxxxx #defines below.
+ ///
+ PXE_UINT8 SupportedLoopBackModes;
+} PXE_DB_GET_INIT_INFO;
+
+#define PXE_MAX_TXRX_UNIT_ETHER 1500
+
+#define PXE_HWADDR_LEN_ETHER 0x0006
+#define PXE_MAC_HEADER_LEN_ETHER 0x000E
+
+#define PXE_DUPLEX_ENABLE_FULL_SUPPORTED 1
+#define PXE_DUPLEX_FORCE_FULL_SUPPORTED 2
+
+#define PXE_LOOPBACK_INTERNAL_SUPPORTED 1
+#define PXE_LOOPBACK_EXTERNAL_SUPPORTED 2
+
+typedef struct s_pxe_pci_config_info {
+ ///
+ /// This is the flag field for the PXE_DB_GET_CONFIG_INFO union.
+ /// For PCI bus devices, this field is set to PXE_BUSTYPE_PCI.
+ ///
+ UINT32 BusType;
+
+ ///
+ /// This identifies the PCI network device that this UNDI interface.
+ /// is bound to.
+ ///
+ UINT16 Bus;
+ UINT8 Device;
+ UINT8 Function;
+
+ ///
+ /// This is a copy of the PCI configuration space for this
+ /// network device.
+ ///
+ union {
+ UINT8 Byte[256];
+ UINT16 Word[128];
+ UINT32 Dword[64];
+ } Config;
+} PXE_PCI_CONFIG_INFO;
+
+typedef struct s_pxe_pcc_config_info {
+ ///
+ /// This is the flag field for the PXE_DB_GET_CONFIG_INFO union.
+ /// For PCC bus devices, this field is set to PXE_BUSTYPE_PCC.
+ ///
+ PXE_UINT32 BusType;
+
+ ///
+ /// This identifies the PCC network device that this UNDI interface
+ /// is bound to.
+ ///
+ PXE_UINT16 Bus;
+ PXE_UINT8 Device;
+ PXE_UINT8 Function;
+
+ ///
+ /// This is a copy of the PCC configuration space for this
+ /// network device.
+ ///
+ union {
+ PXE_UINT8 Byte[256];
+ PXE_UINT16 Word[128];
+ PXE_UINT32 Dword[64];
+ } Config;
+} PXE_PCC_CONFIG_INFO;
+
+typedef union u_pxe_db_get_config_info {
+ PXE_PCI_CONFIG_INFO pci;
+ PXE_PCC_CONFIG_INFO pcc;
+} PXE_DB_GET_CONFIG_INFO;
+
+typedef struct s_pxe_cpb_initialize {
+ ///
+ /// Address of first (lowest) byte of the memory buffer. This buffer must
+ /// be in contiguous physical memory and cannot be swapped out. The UNDI
+ /// will be using this for transmit and receive buffering.
+ ///
+ PXE_UINT64 MemoryAddr;
+
+ ///
+ /// MemoryLength must be greater than or equal to MemoryRequired
+ /// returned by the Get Init Info command.
+ ///
+ PXE_UINT32 MemoryLength;
+
+ ///
+ /// Desired link speed in Mbit/sec. Common ethernet values are 10, 100
+ /// and 1000. Setting a value of zero will auto-detect and/or use the
+ /// default link speed (operation depends on UNDI/NIC functionality).
+ ///
+ PXE_UINT32 LinkSpeed;
+
+ ///
+ /// Suggested number and size of receive and transmit buffers to
+ /// allocate. If MemoryAddr and MemoryLength are non-zero, this
+ /// allocation comes out of the supplied memory buffer. If MemoryAddr
+ /// and MemoryLength are zero, this allocation comes out of memory
+ /// on the NIC.
+ ///
+ /// If these fields are set to zero, the UNDI will allocate buffer
+ /// counts and sizes as it sees fit.
+ ///
+ PXE_UINT16 TxBufCnt;
+ PXE_UINT16 TxBufSize;
+ PXE_UINT16 RxBufCnt;
+ PXE_UINT16 RxBufSize;
+
+ ///
+ /// The following configuration parameters are optional and must be zero
+ /// to use the default values.
+ ///
+ PXE_UINT8 DuplexMode;
+
+ PXE_UINT8 LoopBackMode;
+} PXE_CPB_INITIALIZE;
+
+#define PXE_DUPLEX_DEFAULT 0x00
+#define PXE_FORCE_FULL_DUPLEX 0x01
+#define PXE_ENABLE_FULL_DUPLEX 0x02
+#define PXE_FORCE_HALF_DUPLEX 0x04
+#define PXE_DISABLE_FULL_DUPLEX 0x08
+
+#define LOOPBACK_NORMAL 0
+#define LOOPBACK_INTERNAL 1
+#define LOOPBACK_EXTERNAL 2
+
+typedef struct s_pxe_db_initialize {
+ ///
+ /// Actual amount of memory used from the supplied memory buffer. This
+ /// may be less that the amount of memory suppllied and may be zero if
+ /// the UNDI and network device do not use external memory buffers.
+ ///
+ /// Memory used by the UNDI and network device is allocated from the
+ /// lowest memory buffer address.
+ ///
+ PXE_UINT32 MemoryUsed;
+
+ ///
+ /// Actual number and size of receive and transmit buffers that were
+ /// allocated.
+ ///
+ PXE_UINT16 TxBufCnt;
+ PXE_UINT16 TxBufSize;
+ PXE_UINT16 RxBufCnt;
+ PXE_UINT16 RxBufSize;
+} PXE_DB_INITIALIZE;
+
+typedef struct s_pxe_cpb_receive_filters {
+ ///
+ /// List of multicast MAC addresses. This list, if present, will
+ /// replace the existing multicast MAC address filter list.
+ ///
+ PXE_MAC_ADDR MCastList[MAX_MCAST_ADDRESS_CNT];
+} PXE_CPB_RECEIVE_FILTERS;
+
+typedef struct s_pxe_db_receive_filters {
+ ///
+ /// Filtered multicast MAC address list.
+ ///
+ PXE_MAC_ADDR MCastList[MAX_MCAST_ADDRESS_CNT];
+} PXE_DB_RECEIVE_FILTERS;
+
+typedef struct s_pxe_cpb_station_address {
+ ///
+ /// If supplied and supported, the current station MAC address
+ /// will be changed.
+ ///
+ PXE_MAC_ADDR StationAddr;
+} PXE_CPB_STATION_ADDRESS;
+
+typedef struct s_pxe_dpb_station_address {
+ ///
+ /// Current station MAC address.
+ ///
+ PXE_MAC_ADDR StationAddr;
+
+ ///
+ /// Station broadcast MAC address.
+ ///
+ PXE_MAC_ADDR BroadcastAddr;
+
+ ///
+ /// Permanent station MAC address.
+ ///
+ PXE_MAC_ADDR PermanentAddr;
+} PXE_DB_STATION_ADDRESS;
+
+typedef struct s_pxe_db_statistics {
+ ///
+ /// Bit field identifying what statistic data is collected by the
+ /// UNDI/NIC.
+ /// If bit 0x00 is set, Data[0x00] is collected.
+ /// If bit 0x01 is set, Data[0x01] is collected.
+ /// If bit 0x20 is set, Data[0x20] is collected.
+ /// If bit 0x21 is set, Data[0x21] is collected.
+ /// Etc.
+ ///
+ PXE_UINT64 Supported;
+
+ ///
+ /// Statistic data.
+ ///
+ PXE_UINT64 Data[64];
+} PXE_DB_STATISTICS;
+
+///
+/// Total number of frames received. Includes frames with errors and
+/// dropped frames.
+///
+#define PXE_STATISTICS_RX_TOTAL_FRAMES 0x00
+
+///
+/// Number of valid frames received and copied into receive buffers.
+///
+#define PXE_STATISTICS_RX_GOOD_FRAMES 0x01
+
+///
+/// Number of frames below the minimum length for the media.
+/// This would be <64 for ethernet.
+///
+#define PXE_STATISTICS_RX_UNDERSIZE_FRAMES 0x02
+
+///
+/// Number of frames longer than the maxminum length for the
+/// media. This would be >1500 for ethernet.
+///
+#define PXE_STATISTICS_RX_OVERSIZE_FRAMES 0x03
+
+///
+/// Valid frames that were dropped because receive buffers were full.
+///
+#define PXE_STATISTICS_RX_DROPPED_FRAMES 0x04
+
+///
+/// Number of valid unicast frames received and not dropped.
+///
+#define PXE_STATISTICS_RX_UNICAST_FRAMES 0x05
+
+///
+/// Number of valid broadcast frames received and not dropped.
+///
+#define PXE_STATISTICS_RX_BROADCAST_FRAMES 0x06
+
+///
+/// Number of valid mutlicast frames received and not dropped.
+///
+#define PXE_STATISTICS_RX_MULTICAST_FRAMES 0x07
+
+///
+/// Number of frames w/ CRC or alignment errors.
+///
+#define PXE_STATISTICS_RX_CRC_ERROR_FRAMES 0x08
+
+///
+/// Total number of bytes received. Includes frames with errors
+/// and dropped frames.
+///
+#define PXE_STATISTICS_RX_TOTAL_BYTES 0x09
+
+///
+/// Transmit statistics.
+///
+#define PXE_STATISTICS_TX_TOTAL_FRAMES 0x0A
+#define PXE_STATISTICS_TX_GOOD_FRAMES 0x0B
+#define PXE_STATISTICS_TX_UNDERSIZE_FRAMES 0x0C
+#define PXE_STATISTICS_TX_OVERSIZE_FRAMES 0x0D
+#define PXE_STATISTICS_TX_DROPPED_FRAMES 0x0E
+#define PXE_STATISTICS_TX_UNICAST_FRAMES 0x0F
+#define PXE_STATISTICS_TX_BROADCAST_FRAMES 0x10
+#define PXE_STATISTICS_TX_MULTICAST_FRAMES 0x11
+#define PXE_STATISTICS_TX_CRC_ERROR_FRAMES 0x12
+#define PXE_STATISTICS_TX_TOTAL_BYTES 0x13
+
+///
+/// Number of collisions detection on this subnet.
+///
+#define PXE_STATISTICS_COLLISIONS 0x14
+
+///
+/// Number of frames destined for unsupported protocol.
+///
+#define PXE_STATISTICS_UNSUPPORTED_PROTOCOL 0x15
+
+typedef struct s_pxe_cpb_mcast_ip_to_mac {
+ ///
+ /// Multicast IP address to be converted to multicast MAC address.
+ ///
+ PXE_IP_ADDR IP;
+} PXE_CPB_MCAST_IP_TO_MAC;
+
+typedef struct s_pxe_db_mcast_ip_to_mac {
+ ///
+ /// Multicast MAC address.
+ ///
+ PXE_MAC_ADDR MAC;
+} PXE_DB_MCAST_IP_TO_MAC;
+
+typedef struct s_pxe_cpb_nvdata_sparse {
+ ///
+ /// NvData item list. Only items in this list will be updated.
+ ///
+ struct {
+ ///
+ /// Non-volatile storage address to be changed.
+ ///
+ PXE_UINT32 Addr;
+
+ ///
+ /// Data item to write into above storage address.
+ ///
+ union {
+ PXE_UINT8 Byte;
+ PXE_UINT16 Word;
+ PXE_UINT32 Dword;
+ } Data;
+ } Item[MAX_EEPROM_LEN];
+} PXE_CPB_NVDATA_SPARSE;
+
+///
+/// When using bulk update, the size of the CPB structure must be
+/// the same size as the non-volatile NIC storage.
+///
+typedef union u_pxe_cpb_nvdata_bulk {
+ ///
+ /// Array of byte-wide data items.
+ ///
+ PXE_UINT8 Byte[MAX_EEPROM_LEN << 2];
+
+ ///
+ /// Array of word-wide data items.
+ ///
+ PXE_UINT16 Word[MAX_EEPROM_LEN << 1];
+
+ ///
+ /// Array of dword-wide data items.
+ ///
+ PXE_UINT32 Dword[MAX_EEPROM_LEN];
+} PXE_CPB_NVDATA_BULK;
+
+typedef struct s_pxe_db_nvdata {
+ ///
+ /// Arrays of data items from non-volatile storage.
+ ///
+ union {
+ ///
+ /// Array of byte-wide data items.
+ ///
+ PXE_UINT8 Byte[MAX_EEPROM_LEN << 2];
+
+ ///
+ /// Array of word-wide data items.
+ ///
+ PXE_UINT16 Word[MAX_EEPROM_LEN << 1];
+
+ ///
+ /// Array of dword-wide data items.
+ ///
+ PXE_UINT32 Dword[MAX_EEPROM_LEN];
+ } Data;
+} PXE_DB_NVDATA;
+
+typedef struct s_pxe_db_get_status {
+ ///
+ /// Length of next receive frame (header + data). If this is zero,
+ /// there is no next receive frame available.
+ ///
+ PXE_UINT32 RxFrameLen;
+
+ ///
+ /// Reserved, set to zero.
+ ///
+ PXE_UINT32 reserved;
+
+ ///
+ /// Addresses of transmitted buffers that need to be recycled.
+ ///
+ PXE_UINT64 TxBuffer[MAX_XMIT_BUFFERS];
+} PXE_DB_GET_STATUS;
+
+typedef struct s_pxe_cpb_fill_header {
+ ///
+ /// Source and destination MAC addresses. These will be copied into
+ /// the media header without doing byte swapping.
+ ///
+ PXE_MAC_ADDR SrcAddr;
+ PXE_MAC_ADDR DestAddr;
+
+ ///
+ /// Address of first byte of media header. The first byte of packet data
+ /// follows the last byte of the media header.
+ ///
+ PXE_UINT64 MediaHeader;
+
+ ///
+ /// Length of packet data in bytes (not including the media header).
+ ///
+ PXE_UINT32 PacketLen;
+
+ ///
+ /// Protocol type. This will be copied into the media header without
+ /// doing byte swapping. Protocol type numbers can be obtained from
+ /// the Assigned Numbers RFC 1700.
+ ///
+ PXE_UINT16 Protocol;
+
+ ///
+ /// Length of the media header in bytes.
+ ///
+ PXE_UINT16 MediaHeaderLen;
+} PXE_CPB_FILL_HEADER;
+
+#define PXE_PROTOCOL_ETHERNET_IP 0x0800
+#define PXE_PROTOCOL_ETHERNET_ARP 0x0806
+#define MAX_XMIT_FRAGMENTS 16
+
+typedef struct s_pxe_cpb_fill_header_fragmented {
+ ///
+ /// Source and destination MAC addresses. These will be copied into
+ /// the media header without doing byte swapping.
+ ///
+ PXE_MAC_ADDR SrcAddr;
+ PXE_MAC_ADDR DestAddr;
+
+ ///
+ /// Length of packet data in bytes (not including the media header).
+ ///
+ PXE_UINT32 PacketLen;
+
+ ///
+ /// Protocol type. This will be copied into the media header without
+ /// doing byte swapping. Protocol type numbers can be obtained from
+ /// the Assigned Numbers RFC 1700.
+ ///
+ PXE_MEDIA_PROTOCOL Protocol;
+
+ ///
+ /// Length of the media header in bytes.
+ ///
+ PXE_UINT16 MediaHeaderLen;
+
+ ///
+ /// Number of packet fragment descriptors.
+ ///
+ PXE_UINT16 FragCnt;
+
+ ///
+ /// Reserved, must be set to zero.
+ ///
+ PXE_UINT16 reserved;
+
+ ///
+ /// Array of packet fragment descriptors. The first byte of the media
+ /// header is the first byte of the first fragment.
+ ///
+ struct {
+ ///
+ /// Address of this packet fragment.
+ ///
+ PXE_UINT64 FragAddr;
+
+ ///
+ /// Length of this packet fragment.
+ ///
+ PXE_UINT32 FragLen;
+
+ ///
+ /// Reserved, must be set to zero.
+ ///
+ PXE_UINT32 reserved;
+ } FragDesc[MAX_XMIT_FRAGMENTS];
+}
+PXE_CPB_FILL_HEADER_FRAGMENTED;
+
+typedef struct s_pxe_cpb_transmit {
+ ///
+ /// Address of first byte of frame buffer. This is also the first byte
+ /// of the media header.
+ ///
+ PXE_UINT64 FrameAddr;
+
+ ///
+ /// Length of the data portion of the frame buffer in bytes. Do not
+ /// include the length of the media header.
+ ///
+ PXE_UINT32 DataLen;
+
+ ///
+ /// Length of the media header in bytes.
+ ///
+ PXE_UINT16 MediaheaderLen;
+
+ ///
+ /// Reserved, must be zero.
+ ///
+ PXE_UINT16 reserved;
+} PXE_CPB_TRANSMIT;
+
+typedef struct s_pxe_cpb_transmit_fragments {
+ ///
+ /// Length of packet data in bytes (not including the media header).
+ ///
+ PXE_UINT32 FrameLen;
+
+ ///
+ /// Length of the media header in bytes.
+ ///
+ PXE_UINT16 MediaheaderLen;
+
+ ///
+ /// Number of packet fragment descriptors.
+ ///
+ PXE_UINT16 FragCnt;
+
+ ///
+ /// Array of frame fragment descriptors. The first byte of the first
+ /// fragment is also the first byte of the media header.
+ ///
+ struct {
+ ///
+ /// Address of this frame fragment.
+ ///
+ PXE_UINT64 FragAddr;
+
+ ///
+ /// Length of this frame fragment.
+ ///
+ PXE_UINT32 FragLen;
+
+ ///
+ /// Reserved, must be set to zero.
+ ///
+ PXE_UINT32 reserved;
+ } FragDesc[MAX_XMIT_FRAGMENTS];
+}
+PXE_CPB_TRANSMIT_FRAGMENTS;
+
+typedef struct s_pxe_cpb_receive {
+ ///
+ /// Address of first byte of receive buffer. This is also the first byte
+ /// of the frame header.
+ ///
+ PXE_UINT64 BufferAddr;
+
+ ///
+ /// Length of receive buffer. This must be large enough to hold the
+ /// received frame (media header + data). If the length of smaller than
+ /// the received frame, data will be lost.
+ ///
+ PXE_UINT32 BufferLen;
+
+ ///
+ /// Reserved, must be set to zero.
+ ///
+ PXE_UINT32 reserved;
+} PXE_CPB_RECEIVE;
+
+typedef struct s_pxe_db_receive {
+ ///
+ /// Source and destination MAC addresses from media header.
+ ///
+ PXE_MAC_ADDR SrcAddr;
+ PXE_MAC_ADDR DestAddr;
+
+ ///
+ /// Length of received frame. May be larger than receive buffer size.
+ /// The receive buffer will not be overwritten. This is how to tell
+ /// if data was lost because the receive buffer was too small.
+ ///
+ PXE_UINT32 FrameLen;
+
+ ///
+ /// Protocol type from media header.
+ ///
+ PXE_MEDIA_PROTOCOL Protocol;
+
+ ///
+ /// Length of media header in received frame.
+ ///
+ PXE_UINT16 MediaHeaderLen;
+
+ ///
+ /// Type of receive frame.
+ ///
+ PXE_FRAME_TYPE Type;
+
+ ///
+ /// Reserved, must be zero.
+ ///
+ PXE_UINT8 reserved[7];
+
+} PXE_DB_RECEIVE;
+
+#pragma pack()
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiSpec.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiSpec.h
new file mode 100644
index 00000000..1f125d4f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/Uefi/UefiSpec.h
@@ -0,0 +1,2099 @@
+/** @file
+ Include file that supports UEFI.
+
+ This include file must contain things defined in the UEFI 2.3 specification.
+ If a code construct is defined in the UEFI 2.3 specification it must be included
+ by this include file.
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __UEFI_SPEC_H__
+#define __UEFI_SPEC_H__
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/Uefi/UefiMultiPhase.h>
+
+#include <ipxe/efi/Protocol/DevicePath.h>
+#include <ipxe/efi/Protocol/SimpleTextIn.h>
+#include <ipxe/efi/Protocol/SimpleTextOut.h>
+
+///
+/// Enumeration of EFI memory allocation types.
+///
+typedef enum {
+ ///
+ /// Allocate any available range of pages that satisfies the request.
+ ///
+ AllocateAnyPages,
+ ///
+ /// Allocate any available range of pages whose uppermost address is less than
+ /// or equal to a specified maximum address.
+ ///
+ AllocateMaxAddress,
+ ///
+ /// Allocate pages at a specified address.
+ ///
+ AllocateAddress,
+ ///
+ /// Maximum enumeration value that may be used for bounds checking.
+ ///
+ MaxAllocateType
+} EFI_ALLOCATE_TYPE;
+
+//
+// Bit definitions for EFI_TIME.Daylight
+//
+#define EFI_TIME_ADJUST_DAYLIGHT 0x01
+#define EFI_TIME_IN_DAYLIGHT 0x02
+
+///
+/// Value definition for EFI_TIME.TimeZone.
+///
+#define EFI_UNSPECIFIED_TIMEZONE 0x07FF
+
+//
+// Memory cacheability attributes
+//
+#define EFI_MEMORY_UC 0x0000000000000001ULL
+#define EFI_MEMORY_WC 0x0000000000000002ULL
+#define EFI_MEMORY_WT 0x0000000000000004ULL
+#define EFI_MEMORY_WB 0x0000000000000008ULL
+#define EFI_MEMORY_UCE 0x0000000000000010ULL
+//
+// Physical memory protection attributes
+//
+#define EFI_MEMORY_WP 0x0000000000001000ULL
+#define EFI_MEMORY_RP 0x0000000000002000ULL
+#define EFI_MEMORY_XP 0x0000000000004000ULL
+//
+// Runtime memory attribute
+//
+#define EFI_MEMORY_RUNTIME 0x8000000000000000ULL
+
+///
+/// Memory descriptor version number.
+///
+#define EFI_MEMORY_DESCRIPTOR_VERSION 1
+
+///
+/// Definition of an EFI memory descriptor.
+///
+typedef struct {
+ ///
+ /// Type of the memory region. See EFI_MEMORY_TYPE.
+ ///
+ UINT32 Type;
+ ///
+ /// Physical address of the first byte of the memory region. Must aligned
+ /// on a 4 KB boundary.
+ ///
+ EFI_PHYSICAL_ADDRESS PhysicalStart;
+ ///
+ /// Virtual address of the first byte of the memory region. Must aligned
+ /// on a 4 KB boundary.
+ ///
+ EFI_VIRTUAL_ADDRESS VirtualStart;
+ ///
+ /// Number of 4KB pages in the memory region.
+ ///
+ UINT64 NumberOfPages;
+ ///
+ /// Attributes of the memory region that describe the bit mask of capabilities
+ /// for that memory region, and not necessarily the current settings for that
+ /// memory region.
+ ///
+ UINT64 Attribute;
+} EFI_MEMORY_DESCRIPTOR;
+
+/**
+ Allocates memory pages from the system.
+
+ @param Type The type of allocation to perform.
+ @param MemoryType The type of memory to allocate.
+ @param Pages The number of contiguous 4 KB pages to allocate.
+ @param Memory The pointer to a physical address. On input, the way in which the address is
+ used depends on the value of Type.
+
+ @retval EFI_SUCCESS The requested pages were allocated.
+ @retval EFI_INVALID_PARAMETER 1) Type is not AllocateAnyPages or
+ AllocateMaxAddress or AllocateAddress.
+ 2) MemoryType is in the range
+ EfiMaxMemoryType..0x7FFFFFFF.
+ @retval EFI_OUT_OF_RESOURCES The pages could not be allocated.
+ @retval EFI_NOT_FOUND The requested pages could not be found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ALLOCATE_PAGES)(
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Memory
+ );
+
+/**
+ Frees memory pages.
+
+ @param Memory The base physical address of the pages to be freed.
+ @param Pages The number of contiguous 4 KB pages to free.
+
+ @retval EFI_SUCCESS The requested pages were freed.
+ @retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pages is invalid.
+ @retval EFI_NOT_FOUND The requested memory pages were not allocated with
+ AllocatePages().
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FREE_PAGES)(
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN Pages
+ );
+
+/**
+ Returns the current memory map.
+
+ @param MemoryMapSize A pointer to the size, in bytes, of the MemoryMap buffer.
+ On input, this is the size of the buffer allocated by the caller.
+ On output, it is the size of the buffer returned by the firmware if
+ the buffer was large enough, or the size of the buffer needed to contain
+ the map if the buffer was too small.
+ @param MemoryMap A pointer to the buffer in which firmware places the current memory
+ map.
+ @param MapKey A pointer to the location in which firmware returns the key for the
+ current memory map.
+ @param DescriptorSize A pointer to the location in which firmware returns the size, in bytes, of
+ an individual EFI_MEMORY_DESCRIPTOR.
+ @param DescriptorVersion A pointer to the location in which firmware returns the version number
+ associated with the EFI_MEMORY_DESCRIPTOR.
+
+ @retval EFI_SUCCESS The memory map was returned in the MemoryMap buffer.
+ @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current buffer size
+ needed to hold the memory map is returned in MemoryMapSize.
+ @retval EFI_INVALID_PARAMETER 1) MemoryMapSize is NULL.
+ 2) The MemoryMap buffer is not too small and MemoryMap is
+ NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_MEMORY_MAP)(
+ IN OUT UINTN *MemoryMapSize,
+ IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ OUT UINTN *MapKey,
+ OUT UINTN *DescriptorSize,
+ OUT UINT32 *DescriptorVersion
+ );
+
+/**
+ Allocates pool memory.
+
+ @param PoolType The type of pool to allocate.
+ @param Size The number of bytes to allocate from the pool.
+ @param Buffer A pointer to a pointer to the allocated buffer if the call succeeds;
+ undefined otherwise.
+
+ @retval EFI_SUCCESS The requested number of bytes was allocated.
+ @retval EFI_OUT_OF_RESOURCES The pool requested could not be allocated.
+ @retval EFI_INVALID_PARAMETER PoolType was invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ALLOCATE_POOL)(
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size,
+ OUT VOID **Buffer
+ );
+
+/**
+ Returns pool memory to the system.
+
+ @param Buffer The pointer to the buffer to free.
+
+ @retval EFI_SUCCESS The memory was returned to the system.
+ @retval EFI_INVALID_PARAMETER Buffer was invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_FREE_POOL)(
+ IN VOID *Buffer
+ );
+
+/**
+ Changes the runtime addressing mode of EFI firmware from physical to virtual.
+
+ @param MemoryMapSize The size in bytes of VirtualMap.
+ @param DescriptorSize The size in bytes of an entry in the VirtualMap.
+ @param DescriptorVersion The version of the structure entries in VirtualMap.
+ @param VirtualMap An array of memory descriptors which contain new virtual
+ address mapping information for all runtime ranges.
+
+ @retval EFI_SUCCESS The virtual address map has been applied.
+ @retval EFI_UNSUPPORTED EFI firmware is not at runtime, or the EFI firmware is already in
+ virtual address mapped mode.
+ @retval EFI_INVALID_PARAMETER DescriptorSize or DescriptorVersion is invalid.
+ @retval EFI_NO_MAPPING A virtual address was not supplied for a range in the memory
+ map that requires a mapping.
+ @retval EFI_NOT_FOUND A virtual address was supplied for an address that is not found
+ in the memory map.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_VIRTUAL_ADDRESS_MAP)(
+ IN UINTN MemoryMapSize,
+ IN UINTN DescriptorSize,
+ IN UINT32 DescriptorVersion,
+ IN EFI_MEMORY_DESCRIPTOR *VirtualMap
+ );
+
+/**
+ Connects one or more drivers to a controller.
+
+ @param ControllerHandle The handle of the controller to which driver(s) are to be connected.
+ @param DriverImageHandle A pointer to an ordered list handles that support the
+ EFI_DRIVER_BINDING_PROTOCOL.
+ @param RemainingDevicePath A pointer to the device path that specifies a child of the
+ controller specified by ControllerHandle.
+ @param Recursive If TRUE, then ConnectController() is called recursively
+ until the entire tree of controllers below the controller specified
+ by ControllerHandle have been created. If FALSE, then
+ the tree of controllers is only expanded one level.
+
+ @retval EFI_SUCCESS 1) One or more drivers were connected to ControllerHandle.
+ 2) No drivers were connected to ControllerHandle, but
+ RemainingDevicePath is not NULL, and it is an End Device
+ Path Node.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+ @retval EFI_NOT_FOUND 1) There are no EFI_DRIVER_BINDING_PROTOCOL instances
+ present in the system.
+ 2) No drivers were connected to ControllerHandle.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CONNECT_CONTROLLER)(
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE *DriverImageHandle, OPTIONAL
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, OPTIONAL
+ IN BOOLEAN Recursive
+ );
+
+/**
+ Disconnects one or more drivers from a controller.
+
+ @param ControllerHandle The handle of the controller from which driver(s) are to be disconnected.
+ @param DriverImageHandle The driver to disconnect from ControllerHandle.
+ If DriverImageHandle is NULL, then all the drivers currently managing
+ ControllerHandle are disconnected from ControllerHandle.
+ @param ChildHandle The handle of the child to destroy.
+ If ChildHandle is NULL, then all the children of ControllerHandle are
+ destroyed before the drivers are disconnected from ControllerHandle.
+
+ @retval EFI_SUCCESS 1) One or more drivers were disconnected from the controller.
+ 2) On entry, no drivers are managing ControllerHandle.
+ 3) DriverImageHandle is not NULL, and on entry
+ DriverImageHandle is not managing ControllerHandle.
+ @retval EFI_INVALID_PARAMETER 1) ControllerHandle is not a valid EFI_HANDLE.
+ 2) DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE.
+ 3) ChildHandle is not NULL, and it is not a valid EFI_HANDLE.
+ 4) DriverImageHandle does not support the EFI_DRIVER_BINDING_PROTOCOL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to disconnect any drivers from
+ ControllerHandle.
+ @retval EFI_DEVICE_ERROR The controller could not be disconnected because of a device error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DISCONNECT_CONTROLLER)(
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE DriverImageHandle, OPTIONAL
+ IN EFI_HANDLE ChildHandle OPTIONAL
+ );
+
+
+
+//
+// ConvertPointer DebugDisposition type.
+//
+#define EFI_OPTIONAL_PTR 0x00000001
+
+/**
+ Determines the new virtual address that is to be used on subsequent memory accesses.
+
+ @param DebugDisposition Supplies type information for the pointer being converted.
+ @param Address A pointer to a pointer that is to be fixed to be the value needed
+ for the new virtual address mappings being applied.
+
+ @retval EFI_SUCCESS The pointer pointed to by Address was modified.
+ @retval EFI_INVALID_PARAMETER 1) Address is NULL.
+ 2) *Address is NULL and DebugDisposition does
+ not have the EFI_OPTIONAL_PTR bit set.
+ @retval EFI_NOT_FOUND The pointer pointed to by Address was not found to be part
+ of the current memory map. This is normally fatal.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CONVERT_POINTER)(
+ IN UINTN DebugDisposition,
+ IN OUT VOID **Address
+ );
+
+
+//
+// These types can be ORed together as needed - for example,
+// EVT_TIMER might be Ored with EVT_NOTIFY_WAIT or
+// EVT_NOTIFY_SIGNAL.
+//
+#define EVT_TIMER 0x80000000
+#define EVT_RUNTIME 0x40000000
+#define EVT_NOTIFY_WAIT 0x00000100
+#define EVT_NOTIFY_SIGNAL 0x00000200
+
+#define EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201
+#define EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202
+
+//
+// The event's NotifyContext pointer points to a runtime memory
+// address.
+// The event is deprecated in UEFI2.0 and later specifications.
+//
+#define EVT_RUNTIME_CONTEXT 0x20000000
+
+
+/**
+ Invoke a notification event
+
+ @param Event Event whose notification function is being invoked.
+ @param Context The pointer to the notification function's context,
+ which is implementation-dependent.
+
+**/
+typedef
+VOID
+(EFIAPI *EFI_EVENT_NOTIFY)(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Creates an event.
+
+ @param Type The type of event to create and its mode and attributes.
+ @param NotifyTpl The task priority level of event notifications, if needed.
+ @param NotifyFunction The pointer to the event's notification function, if any.
+ @param NotifyContext The pointer to the notification function's context; corresponds to parameter
+ Context in the notification function.
+ @param Event The pointer to the newly created event if the call succeeds; undefined
+ otherwise.
+
+ @retval EFI_SUCCESS The event structure was created.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The event could not be allocated.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CREATE_EVENT)(
+ IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ OUT EFI_EVENT *Event
+ );
+
+/**
+ Creates an event in a group.
+
+ @param Type The type of event to create and its mode and attributes.
+ @param NotifyTpl The task priority level of event notifications,if needed.
+ @param NotifyFunction The pointer to the event's notification function, if any.
+ @param NotifyContext The pointer to the notification function's context; corresponds to parameter
+ Context in the notification function.
+ @param EventGroup The pointer to the unique identifier of the group to which this event belongs.
+ If this is NULL, then the function behaves as if the parameters were passed
+ to CreateEvent.
+ @param Event The pointer to the newly created event if the call succeeds; undefined
+ otherwise.
+
+ @retval EFI_SUCCESS The event structure was created.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The event could not be allocated.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CREATE_EVENT_EX)(
+ IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,
+ IN CONST VOID *NotifyContext OPTIONAL,
+ IN CONST EFI_GUID *EventGroup OPTIONAL,
+ OUT EFI_EVENT *Event
+ );
+
+///
+/// Timer delay types
+///
+typedef enum {
+ ///
+ /// An event's timer settings is to be cancelled and not trigger time is to be set/
+ ///
+ TimerCancel,
+ ///
+ /// An event is to be signalled periodically at a specified interval from the current time.
+ ///
+ TimerPeriodic,
+ ///
+ /// An event is to be signalled once at a specified interval from the current time.
+ ///
+ TimerRelative
+} EFI_TIMER_DELAY;
+
+/**
+ Sets the type of timer and the trigger time for a timer event.
+
+ @param Event The timer event that is to be signaled at the specified time.
+ @param Type The type of time that is specified in TriggerTime.
+ @param TriggerTime The number of 100ns units until the timer expires.
+ A TriggerTime of 0 is legal.
+ If Type is TimerRelative and TriggerTime is 0, then the timer
+ event will be signaled on the next timer tick.
+ If Type is TimerPeriodic and TriggerTime is 0, then the timer
+ event will be signaled on every timer tick.
+
+ @retval EFI_SUCCESS The event has been set to be signaled at the requested time.
+ @retval EFI_INVALID_PARAMETER Event or Type is not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_TIMER)(
+ IN EFI_EVENT Event,
+ IN EFI_TIMER_DELAY Type,
+ IN UINT64 TriggerTime
+ );
+
+/**
+ Signals an event.
+
+ @param Event The event to signal.
+
+ @retval EFI_SUCCESS The event has been signaled.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SIGNAL_EVENT)(
+ IN EFI_EVENT Event
+ );
+
+/**
+ Stops execution until an event is signaled.
+
+ @param NumberOfEvents The number of events in the Event array.
+ @param Event An array of EFI_EVENT.
+ @param Index The pointer to the index of the event which satisfied the wait condition.
+
+ @retval EFI_SUCCESS The event indicated by Index was signaled.
+ @retval EFI_INVALID_PARAMETER 1) NumberOfEvents is 0.
+ 2) The event indicated by Index is of type
+ EVT_NOTIFY_SIGNAL.
+ @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_WAIT_FOR_EVENT)(
+ IN UINTN NumberOfEvents,
+ IN EFI_EVENT *Event,
+ OUT UINTN *Index
+ );
+
+/**
+ Closes an event.
+
+ @param Event The event to close.
+
+ @retval EFI_SUCCESS The event has been closed.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CLOSE_EVENT)(
+ IN EFI_EVENT Event
+ );
+
+/**
+ Checks whether an event is in the signaled state.
+
+ @param Event The event to check.
+
+ @retval EFI_SUCCESS The event is in the signaled state.
+ @retval EFI_NOT_READY The event is not in the signaled state.
+ @retval EFI_INVALID_PARAMETER Event is of type EVT_NOTIFY_SIGNAL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CHECK_EVENT)(
+ IN EFI_EVENT Event
+ );
+
+
+//
+// Task priority level
+//
+#define TPL_APPLICATION 4
+#define TPL_CALLBACK 8
+#define TPL_NOTIFY 16
+#define TPL_HIGH_LEVEL 31
+
+
+/**
+ Raises a task's priority level and returns its previous level.
+
+ @param NewTpl The new task priority level.
+
+ @return Previous task priority level
+
+**/
+typedef
+EFI_TPL
+(EFIAPI *EFI_RAISE_TPL)(
+ IN EFI_TPL NewTpl
+ );
+
+/**
+ Restores a task's priority level to its previous value.
+
+ @param OldTpl The previous task priority level to restore.
+
+**/
+typedef
+VOID
+(EFIAPI *EFI_RESTORE_TPL)(
+ IN EFI_TPL OldTpl
+ );
+
+/**
+ Returns the value of a variable.
+
+ @param VariableName A Null-terminated string that is the name of the vendor's
+ variable.
+ @param VendorGuid A unique identifier for the vendor.
+ @param Attributes If not NULL, a pointer to the memory location to return the
+ attributes bitmask for the variable.
+ @param DataSize On input, the size in bytes of the return Data buffer.
+ On output the size of data returned in Data.
+ @param Data The buffer to return the contents of the variable.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND The variable was not found.
+ @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result.
+ @retval EFI_INVALID_PARAMETER VariableName is NULL.
+ @retval EFI_INVALID_PARAMETER VendorGuid is NULL.
+ @retval EFI_INVALID_PARAMETER DataSize is NULL.
+ @retval EFI_INVALID_PARAMETER The DataSize is not too small and Data is NULL.
+ @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
+ @retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_VARIABLE)(
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ OUT UINT32 *Attributes, OPTIONAL
+ IN OUT UINTN *DataSize,
+ OUT VOID *Data
+ );
+
+/**
+ Enumerates the current variable names.
+
+ @param VariableNameSize The size of the VariableName buffer.
+ @param VariableName On input, supplies the last VariableName that was returned
+ by GetNextVariableName(). On output, returns the Nullterminated
+ string of the current variable.
+ @param VendorGuid On input, supplies the last VendorGuid that was returned by
+ GetNextVariableName(). On output, returns the
+ VendorGuid of the current variable.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND The next variable was not found.
+ @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the result.
+ @retval EFI_INVALID_PARAMETER VariableNameSize is NULL.
+ @retval EFI_INVALID_PARAMETER VariableName is NULL.
+ @retval EFI_INVALID_PARAMETER VendorGuid is NULL.
+ @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_NEXT_VARIABLE_NAME)(
+ IN OUT UINTN *VariableNameSize,
+ IN OUT CHAR16 *VariableName,
+ IN OUT EFI_GUID *VendorGuid
+ );
+
+/**
+ Sets the value of a variable.
+
+ @param VariableName A Null-terminated string that is the name of the vendor's variable.
+ Each VariableName is unique for each VendorGuid. VariableName must
+ contain 1 or more characters. If VariableName is an empty string,
+ then EFI_INVALID_PARAMETER is returned.
+ @param VendorGuid A unique identifier for the vendor.
+ @param Attributes Attributes bitmask to set for the variable.
+ @param DataSize The size in bytes of the Data buffer. A size of zero causes the
+ variable to be deleted.
+ @param Data The contents for the variable.
+
+ @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
+ defined by the Attributes.
+ @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied, or the
+ DataSize exceeds the maximum allowed.
+ @retval EFI_INVALID_PARAMETER VariableName is an empty string.
+ @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
+ @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
+ @retval EFI_WRITE_PROTECTED The variable in question is read-only.
+ @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted.
+ @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
+ set but the AuthInfo does NOT pass the validation check carried out
+ by the firmware.
+ @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_VARIABLE)(
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ );
+
+
+///
+/// This provides the capabilities of the
+/// real time clock device as exposed through the EFI interfaces.
+///
+typedef struct {
+ ///
+ /// Provides the reporting resolution of the real-time clock device in
+ /// counts per second. For a normal PC-AT CMOS RTC device, this
+ /// value would be 1 Hz, or 1, to indicate that the device only reports
+ /// the time to the resolution of 1 second.
+ ///
+ UINT32 Resolution;
+ ///
+ /// Provides the timekeeping accuracy of the real-time clock in an
+ /// error rate of 1E-6 parts per million. For a clock with an accuracy
+ /// of 50 parts per million, the value in this field would be
+ /// 50,000,000.
+ ///
+ UINT32 Accuracy;
+ ///
+ /// A TRUE indicates that a time set operation clears the device's
+ /// time below the Resolution reporting level. A FALSE
+ /// indicates that the state below the Resolution level of the
+ /// device is not cleared when the time is set. Normal PC-AT CMOS
+ /// RTC devices set this value to FALSE.
+ ///
+ BOOLEAN SetsToZero;
+} EFI_TIME_CAPABILITIES;
+
+/**
+ Returns the current time and date information, and the time-keeping capabilities
+ of the hardware platform.
+
+ @param Time A pointer to storage to receive a snapshot of the current time.
+ @param Capabilities An optional pointer to a buffer to receive the real time clock
+ device's capabilities.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Time is NULL.
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_TIME)(
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL
+ );
+
+/**
+ Sets the current local time and date information.
+
+ @param Time A pointer to the current time.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_TIME)(
+ IN EFI_TIME *Time
+ );
+
+/**
+ Returns the current wakeup alarm clock setting.
+
+ @param Enabled Indicates if the alarm is currently enabled or disabled.
+ @param Pending Indicates if the alarm signal is pending and requires acknowledgement.
+ @param Time The current alarm setting.
+
+ @retval EFI_SUCCESS The alarm settings were returned.
+ @retval EFI_INVALID_PARAMETER Enabled is NULL.
+ @retval EFI_INVALID_PARAMETER Pending is NULL.
+ @retval EFI_INVALID_PARAMETER Time is NULL.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_WAKEUP_TIME)(
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time
+ );
+
+/**
+ Sets the system wakeup alarm clock time.
+
+ @param Enabled Enable or disable the wakeup alarm.
+ @param Time If Enable is TRUE, the time to set the wakeup alarm for.
+ If Enable is FALSE, then this parameter is optional, and may be NULL.
+
+ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If
+ Enable is FALSE, then the wakeup alarm was disabled.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_WAKEUP_TIME)(
+ IN BOOLEAN Enable,
+ IN EFI_TIME *Time OPTIONAL
+ );
+
+/**
+ Loads an EFI image into memory.
+
+ @param BootPolicy If TRUE, indicates that the request originates from the boot
+ manager, and that the boot manager is attempting to load
+ FilePath as a boot selection. Ignored if SourceBuffer is
+ not NULL.
+ @param ParentImageHandle The caller's image handle.
+ @param DevicePath The DeviceHandle specific file path from which the image is
+ loaded.
+ @param SourceBuffer If not NULL, a pointer to the memory location containing a copy
+ of the image to be loaded.
+ @param SourceSize The size in bytes of SourceBuffer. Ignored if SourceBuffer is NULL.
+ @param ImageHandle The pointer to the returned image handle that is created when the
+ image is successfully loaded.
+
+ @retval EFI_SUCCESS Image was loaded into memory correctly.
+ @retval EFI_NOT_FOUND Both SourceBuffer and DevicePath are NULL.
+ @retval EFI_INVALID_PARAMETER One or more parametes are invalid.
+ @retval EFI_UNSUPPORTED The image type is not supported.
+ @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient resources.
+ @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
+ understood.
+ @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
+ @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
+ image from being loaded. NULL is returned in *ImageHandle.
+ @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
+ valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
+ platform policy specifies that the image should not be started.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IMAGE_LOAD)(
+ IN BOOLEAN BootPolicy,
+ IN EFI_HANDLE ParentImageHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ OUT EFI_HANDLE *ImageHandle
+ );
+
+/**
+ Transfers control to a loaded image's entry point.
+
+ @param ImageHandle Handle of image to be started.
+ @param ExitDataSize The pointer to the size, in bytes, of ExitData.
+ @param ExitData The pointer to a pointer to a data buffer that includes a Null-terminated
+ string, optionally followed by additional binary data.
+
+ @retval EFI_INVALID_PARAMETER ImageHandle is either an invalid image handle or the image
+ has already been initialized with StartImage.
+ @return Exit code from image
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IMAGE_START)(
+ IN EFI_HANDLE ImageHandle,
+ OUT UINTN *ExitDataSize,
+ OUT CHAR16 **ExitData OPTIONAL
+ );
+
+/**
+ Terminates a loaded EFI image and returns control to boot services.
+
+ @param ImageHandle Handle that identifies the image. This parameter is passed to the
+ image on entry.
+ @param ExitStatus The image's exit code.
+ @param ExitDataSize The size, in bytes, of ExitData. Ignored if ExitStatus is EFI_SUCCESS.
+ @param ExitData The pointer to a data buffer that includes a Null-terminated string,
+ optionally followed by additional binary data. The string is a
+ description that the caller may use to further indicate the reason
+ for the image's exit. ExitData is only valid if ExitStatus
+ is something other than EFI_SUCCESS. The ExitData buffer
+ must be allocated by calling AllocatePool().
+
+ @retval EFI_SUCCESS The image specified by ImageHandle was unloaded.
+ @retval EFI_INVALID_PARAMETER The image specified by ImageHandle has been loaded and
+ started with LoadImage() and StartImage(), but the
+ image is not the currently executing image.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_EXIT)(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_STATUS ExitStatus,
+ IN UINTN ExitDataSize,
+ IN CHAR16 *ExitData OPTIONAL
+ );
+
+/**
+ Unloads an image.
+
+ @param ImageHandle Handle that identifies the image to be unloaded.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+ @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IMAGE_UNLOAD)(
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ Terminates all boot services.
+
+ @param ImageHandle Handle that identifies the exiting image.
+ @param MapKey Key to the latest memory map.
+
+ @retval EFI_SUCCESS Boot services have been terminated.
+ @retval EFI_INVALID_PARAMETER MapKey is incorrect.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_EXIT_BOOT_SERVICES)(
+ IN EFI_HANDLE ImageHandle,
+ IN UINTN MapKey
+ );
+
+/**
+ Induces a fine-grained stall.
+
+ @param Microseconds The number of microseconds to stall execution.
+
+ @retval EFI_SUCCESS Execution was stalled at least the requested number of
+ Microseconds.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_STALL)(
+ IN UINTN Microseconds
+ );
+
+/**
+ Sets the system's watchdog timer.
+
+ @param Timeout The number of seconds to set the watchdog timer to.
+ @param WatchdogCode The numeric code to log on a watchdog timer timeout event.
+ @param DataSize The size, in bytes, of WatchdogData.
+ @param WatchdogData A data buffer that includes a Null-terminated string, optionally
+ followed by additional binary data.
+
+ @retval EFI_SUCCESS The timeout has been set.
+ @retval EFI_INVALID_PARAMETER The supplied WatchdogCode is invalid.
+ @retval EFI_UNSUPPORTED The system does not have a watchdog timer.
+ @retval EFI_DEVICE_ERROR The watchdog timer could not be programmed due to a hardware
+ error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_WATCHDOG_TIMER)(
+ IN UINTN Timeout,
+ IN UINT64 WatchdogCode,
+ IN UINTN DataSize,
+ IN CHAR16 *WatchdogData OPTIONAL
+ );
+
+///
+/// Enumeration of reset types.
+///
+typedef enum {
+ ///
+ /// Used to induce a system-wide reset. This sets all circuitry within the
+ /// system to its initial state. This type of reset is asynchronous to system
+ /// operation and operates withgout regard to cycle boundaries. EfiColdReset
+ /// is tantamount to a system power cycle.
+ ///
+ EfiResetCold,
+ ///
+ /// Used to induce a system-wide initialization. The processors are set to their
+ /// initial state, and pending cycles are not corrupted. If the system does
+ /// not support this reset type, then an EfiResetCold must be performed.
+ ///
+ EfiResetWarm,
+ ///
+ /// Used to induce an entry into a power state equivalent to the ACPI G2/S5 or G3
+ /// state. If the system does not support this reset type, then when the system
+ /// is rebooted, it should exhibit the EfiResetCold attributes.
+ ///
+ EfiResetShutdown
+} EFI_RESET_TYPE;
+
+/**
+ Resets the entire platform.
+
+ @param ResetType The type of reset to perform.
+ @param ResetStatus The status code for the reset.
+ @param DataSize The size, in bytes, of WatchdogData.
+ @param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or
+ EfiResetShutdown the data buffer starts with a Null-terminated
+ string, optionally followed by additional binary data.
+
+**/
+typedef
+VOID
+(EFIAPI *EFI_RESET_SYSTEM)(
+ IN EFI_RESET_TYPE ResetType,
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ );
+
+/**
+ Returns a monotonically increasing count for the platform.
+
+ @param Count The pointer to returned value.
+
+ @retval EFI_SUCCESS The next monotonic count was returned.
+ @retval EFI_INVALID_PARAMETER Count is NULL.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_NEXT_MONOTONIC_COUNT)(
+ OUT UINT64 *Count
+ );
+
+/**
+ Returns the next high 32 bits of the platform's monotonic counter.
+
+ @param HighCount The pointer to returned value.
+
+ @retval EFI_SUCCESS The next high monotonic count was returned.
+ @retval EFI_INVALID_PARAMETER HighCount is NULL.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_NEXT_HIGH_MONO_COUNT)(
+ OUT UINT32 *HighCount
+ );
+
+/**
+ Computes and returns a 32-bit CRC for a data buffer.
+
+ @param Data A pointer to the buffer on which the 32-bit CRC is to be computed.
+ @param DataSize The number of bytes in the buffer Data.
+ @param Crc32 The 32-bit CRC that was computed for the data buffer specified by Data
+ and DataSize.
+
+ @retval EFI_SUCCESS The 32-bit CRC was computed for the data buffer and returned in
+ Crc32.
+ @retval EFI_INVALID_PARAMETER Data is NULL.
+ @retval EFI_INVALID_PARAMETER Crc32 is NULL.
+ @retval EFI_INVALID_PARAMETER DataSize is 0.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CALCULATE_CRC32)(
+ IN VOID *Data,
+ IN UINTN DataSize,
+ OUT UINT32 *Crc32
+ );
+
+/**
+ Copies the contents of one buffer to another buffer.
+
+ @param Destination The pointer to the destination buffer of the memory copy.
+ @param Source The pointer to the source buffer of the memory copy.
+ @param Length Number of bytes to copy from Source to Destination.
+
+**/
+typedef
+VOID
+(EFIAPI *EFI_COPY_MEM)(
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ );
+
+/**
+ The SetMem() function fills a buffer with a specified value.
+
+ @param Buffer The pointer to the buffer to fill.
+ @param Size Number of bytes in Buffer to fill.
+ @param Value Value to fill Buffer with.
+
+**/
+typedef
+VOID
+(EFIAPI *EFI_SET_MEM)(
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN UINT8 Value
+ );
+
+///
+/// Enumeration of EFI Interface Types
+///
+typedef enum {
+ ///
+ /// Indicates that the supplied protocol interface is supplied in native form.
+ ///
+ EFI_NATIVE_INTERFACE
+} EFI_INTERFACE_TYPE;
+
+/**
+ Installs a protocol interface on a device handle. If the handle does not exist, it is created and added
+ to the list of handles in the system. InstallMultipleProtocolInterfaces() performs
+ more error checking than InstallProtocolInterface(), so it is recommended that
+ InstallMultipleProtocolInterfaces() be used in place of
+ InstallProtocolInterface()
+
+ @param Handle A pointer to the EFI_HANDLE on which the interface is to be installed.
+ @param Protocol The numeric ID of the protocol interface.
+ @param InterfaceType Indicates whether Interface is supplied in native form.
+ @param Interface A pointer to the protocol interface.
+
+ @retval EFI_SUCCESS The protocol interface was installed.
+ @retval EFI_OUT_OF_RESOURCES Space for a new handle could not be allocated.
+ @retval EFI_INVALID_PARAMETER Handle is NULL.
+ @retval EFI_INVALID_PARAMETER Protocol is NULL.
+ @retval EFI_INVALID_PARAMETER InterfaceType is not EFI_NATIVE_INTERFACE.
+ @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_INSTALL_PROTOCOL_INTERFACE)(
+ IN OUT EFI_HANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface
+ );
+
+/**
+ Installs one or more protocol interfaces into the boot services environment.
+
+ @param Handle The handle to install the new protocol interfaces on, or NULL if a new
+ handle is to be allocated.
+ @param ... A variable argument list containing pairs of protocol GUIDs and protocol
+ interfaces.
+
+ @retval EFI_SUCCESS All the protocol interface was installed.
+ @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.
+ @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in
+ the handle database.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES)(
+ IN OUT EFI_HANDLE *Handle,
+ ...
+ );
+
+/**
+ Reinstalls a protocol interface on a device handle.
+
+ @param Handle Handle on which the interface is to be reinstalled.
+ @param Protocol The numeric ID of the interface.
+ @param OldInterface A pointer to the old interface. NULL can be used if a structure is not
+ associated with Protocol.
+ @param NewInterface A pointer to the new interface.
+
+ @retval EFI_SUCCESS The protocol interface was reinstalled.
+ @retval EFI_NOT_FOUND The OldInterface on the handle was not found.
+ @retval EFI_ACCESS_DENIED The protocol interface could not be reinstalled,
+ because OldInterface is still being used by a
+ driver that will not release it.
+ @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Protocol is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REINSTALL_PROTOCOL_INTERFACE)(
+ IN EFI_HANDLE Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *OldInterface,
+ IN VOID *NewInterface
+ );
+
+/**
+ Removes a protocol interface from a device handle. It is recommended that
+ UninstallMultipleProtocolInterfaces() be used in place of
+ UninstallProtocolInterface().
+
+ @param Handle The handle on which the interface was installed.
+ @param Protocol The numeric ID of the interface.
+ @param Interface A pointer to the interface.
+
+ @retval EFI_SUCCESS The interface was removed.
+ @retval EFI_NOT_FOUND The interface was not found.
+ @retval EFI_ACCESS_DENIED The interface was not removed because the interface
+ is still being used by a driver.
+ @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Protocol is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UNINSTALL_PROTOCOL_INTERFACE)(
+ IN EFI_HANDLE Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ );
+
+/**
+ Removes one or more protocol interfaces into the boot services environment.
+
+ @param Handle The handle to remove the protocol interfaces from.
+ @param ... A variable argument list containing pairs of protocol GUIDs and
+ protocol interfaces.
+
+ @retval EFI_SUCCESS All the protocol interfaces were removed.
+ @retval EFI_INVALID_PARAMETER One of the protocol interfaces was not previously installed on Handle.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES)(
+ IN EFI_HANDLE Handle,
+ ...
+ );
+
+/**
+ Queries a handle to determine if it supports a specified protocol.
+
+ @param Handle The handle being queried.
+ @param Protocol The published unique identifier of the protocol.
+ @param Interface Supplies the address where a pointer to the corresponding Protocol
+ Interface is returned.
+
+ @retval EFI_SUCCESS The interface information for the specified protocol was returned.
+ @retval EFI_UNSUPPORTED The device does not support the specified protocol.
+ @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Protocol is NULL.
+ @retval EFI_INVALID_PARAMETER Interface is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HANDLE_PROTOCOL)(
+ IN EFI_HANDLE Handle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface
+ );
+
+#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001
+#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002
+#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004
+#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008
+#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010
+#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020
+
+/**
+ Queries a handle to determine if it supports a specified protocol. If the protocol is supported by the
+ handle, it opens the protocol on behalf of the calling agent.
+
+ @param Handle The handle for the protocol interface that is being opened.
+ @param Protocol The published unique identifier of the protocol.
+ @param Interface Supplies the address where a pointer to the corresponding Protocol
+ Interface is returned.
+ @param AgentHandle The handle of the agent that is opening the protocol interface
+ specified by Protocol and Interface.
+ @param ControllerHandle If the agent that is opening a protocol is a driver that follows the
+ UEFI Driver Model, then this parameter is the controller handle
+ that requires the protocol interface. If the agent does not follow
+ the UEFI Driver Model, then this parameter is optional and may
+ be NULL.
+ @param Attributes The open mode of the protocol interface specified by Handle
+ and Protocol.
+
+ @retval EFI_SUCCESS An item was added to the open list for the protocol interface, and the
+ protocol interface was returned in Interface.
+ @retval EFI_UNSUPPORTED Handle does not support Protocol.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_ACCESS_DENIED Required attributes can't be supported in current environment.
+ @retval EFI_ALREADY_STARTED Item on the open list already has requierd attributes whose agent
+ handle is the same as AgentHandle.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_OPEN_PROTOCOL)(
+ IN EFI_HANDLE Handle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface, OPTIONAL
+ IN EFI_HANDLE AgentHandle,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINT32 Attributes
+ );
+
+
+/**
+ Closes a protocol on a handle that was opened using OpenProtocol().
+
+ @param Handle The handle for the protocol interface that was previously opened
+ with OpenProtocol(), and is now being closed.
+ @param Protocol The published unique identifier of the protocol.
+ @param AgentHandle The handle of the agent that is closing the protocol interface.
+ @param ControllerHandle If the agent that opened a protocol is a driver that follows the
+ UEFI Driver Model, then this parameter is the controller handle
+ that required the protocol interface.
+
+ @retval EFI_SUCCESS The protocol instance was closed.
+ @retval EFI_INVALID_PARAMETER 1) Handle is not a valid EFI_HANDLE.
+ 2) AgentHandle is not a valid EFI_HANDLE.
+ 3) ControllerHandle is not NULL and ControllerHandle is not a valid EFI_HANDLE.
+ 4) Protocol is NULL.
+ @retval EFI_NOT_FOUND 1) Handle does not support the protocol specified by Protocol.
+ 2) The protocol interface specified by Handle and Protocol is not
+ currently open by AgentHandle and ControllerHandle.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CLOSE_PROTOCOL)(
+ IN EFI_HANDLE Handle,
+ IN EFI_GUID *Protocol,
+ IN EFI_HANDLE AgentHandle,
+ IN EFI_HANDLE ControllerHandle
+ );
+
+///
+/// EFI Oprn Protocol Information Entry
+///
+typedef struct {
+ EFI_HANDLE AgentHandle;
+ EFI_HANDLE ControllerHandle;
+ UINT32 Attributes;
+ UINT32 OpenCount;
+} EFI_OPEN_PROTOCOL_INFORMATION_ENTRY;
+
+/**
+ Retrieves the list of agents that currently have a protocol interface opened.
+
+ @param Handle The handle for the protocol interface that is being queried.
+ @param Protocol The published unique identifier of the protocol.
+ @param EntryBuffer A pointer to a buffer of open protocol information in the form of
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
+ @param EntryCount A pointer to the number of entries in EntryBuffer.
+
+ @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer, and the
+ number of entries was returned EntryCount.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.
+ @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_OPEN_PROTOCOL_INFORMATION)(
+ IN EFI_HANDLE Handle,
+ IN EFI_GUID *Protocol,
+ OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
+ OUT UINTN *EntryCount
+ );
+
+/**
+ Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
+ from pool.
+
+ @param Handle The handle from which to retrieve the list of protocol interface
+ GUIDs.
+ @param ProtocolBuffer A pointer to the list of protocol interface GUID pointers that are
+ installed on Handle.
+ @param ProtocolBufferCount A pointer to the number of GUID pointers present in
+ ProtocolBuffer.
+
+ @retval EFI_SUCCESS The list of protocol interface GUIDs installed on Handle was returned in
+ ProtocolBuffer. The number of protocol interface GUIDs was
+ returned in ProtocolBufferCount.
+ @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the results.
+ @retval EFI_INVALID_PARAMETER Handle is NULL.
+ @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
+ @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PROTOCOLS_PER_HANDLE)(
+ IN EFI_HANDLE Handle,
+ OUT EFI_GUID ***ProtocolBuffer,
+ OUT UINTN *ProtocolBufferCount
+ );
+
+/**
+ Creates an event that is to be signaled whenever an interface is installed for a specified protocol.
+
+ @param Protocol The numeric ID of the protocol for which the event is to be registered.
+ @param Event Event that is to be signaled whenever a protocol interface is registered
+ for Protocol.
+ @param Registration A pointer to a memory location to receive the registration value.
+
+ @retval EFI_SUCCESS The notification event has been registered.
+ @retval EFI_OUT_OF_RESOURCES Space for the notification event could not be allocated.
+ @retval EFI_INVALID_PARAMETER Protocol is NULL.
+ @retval EFI_INVALID_PARAMETER Event is NULL.
+ @retval EFI_INVALID_PARAMETER Registration is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REGISTER_PROTOCOL_NOTIFY)(
+ IN EFI_GUID *Protocol,
+ IN EFI_EVENT Event,
+ OUT VOID **Registration
+ );
+
+///
+/// Enumeration of EFI Locate Search Types
+///
+typedef enum {
+ ///
+ /// Retrieve all the handles in the handle database.
+ ///
+ AllHandles,
+ ///
+ /// Retrieve the next handle fron a RegisterProtocolNotify() event.
+ ///
+ ByRegisterNotify,
+ ///
+ /// Retrieve the set of handles from the handle database that support a
+ /// specified protocol.
+ ///
+ ByProtocol
+} EFI_LOCATE_SEARCH_TYPE;
+
+/**
+ Returns an array of handles that support a specified protocol.
+
+ @param SearchType Specifies which handle(s) are to be returned.
+ @param Protocol Specifies the protocol to search by.
+ @param SearchKey Specifies the search key.
+ @param BufferSize On input, the size in bytes of Buffer. On output, the size in bytes of
+ the array returned in Buffer (if the buffer was large enough) or the
+ size, in bytes, of the buffer needed to obtain the array (if the buffer was
+ not large enough).
+ @param Buffer The buffer in which the array is returned.
+
+ @retval EFI_SUCCESS The array of handles was returned.
+ @retval EFI_NOT_FOUND No handles match the search.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small for the result.
+ @retval EFI_INVALID_PARAMETER SearchType is not a member of EFI_LOCATE_SEARCH_TYPE.
+ @retval EFI_INVALID_PARAMETER SearchType is ByRegisterNotify and SearchKey is NULL.
+ @retval EFI_INVALID_PARAMETER SearchType is ByProtocol and Protocol is NULL.
+ @retval EFI_INVALID_PARAMETER One or more matches are found and BufferSize is NULL.
+ @retval EFI_INVALID_PARAMETER BufferSize is large enough for the result and Buffer is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LOCATE_HANDLE)(
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,
+ IN EFI_GUID *Protocol, OPTIONAL
+ IN VOID *SearchKey, OPTIONAL
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HANDLE *Buffer
+ );
+
+/**
+ Locates the handle to a device on the device path that supports the specified protocol.
+
+ @param Protocol Specifies the protocol to search for.
+ @param DevicePath On input, a pointer to a pointer to the device path. On output, the device
+ path pointer is modified to point to the remaining part of the device
+ path.
+ @param Device A pointer to the returned device handle.
+
+ @retval EFI_SUCCESS The resulting handle was returned.
+ @retval EFI_NOT_FOUND No handles match the search.
+ @retval EFI_INVALID_PARAMETER Protocol is NULL.
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL.
+ @retval EFI_INVALID_PARAMETER A handle matched the search and Device is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LOCATE_DEVICE_PATH)(
+ IN EFI_GUID *Protocol,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
+ OUT EFI_HANDLE *Device
+ );
+
+/**
+ Adds, updates, or removes a configuration table entry from the EFI System Table.
+
+ @param Guid A pointer to the GUID for the entry to add, update, or remove.
+ @param Table A pointer to the configuration table for the entry to add, update, or
+ remove. May be NULL.
+
+ @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed.
+ @retval EFI_NOT_FOUND An attempt was made to delete a nonexistent entry.
+ @retval EFI_INVALID_PARAMETER Guid is not valid.
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_INSTALL_CONFIGURATION_TABLE)(
+ IN EFI_GUID *Guid,
+ IN VOID *Table
+ );
+
+/**
+ Returns an array of handles that support the requested protocol in a buffer allocated from pool.
+
+ @param SearchType Specifies which handle(s) are to be returned.
+ @param Protocol Provides the protocol to search by.
+ This parameter is only valid for a SearchType of ByProtocol.
+ @param SearchKey Supplies the search key depending on the SearchType.
+ @param NoHandles The number of handles returned in Buffer.
+ @param Buffer A pointer to the buffer to return the requested array of handles that
+ support Protocol.
+
+ @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
+ handles in Buffer was returned in NoHandles.
+ @retval EFI_NOT_FOUND No handles match the search.
+ @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
+ @retval EFI_INVALID_PARAMETER NoHandles is NULL.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LOCATE_HANDLE_BUFFER)(
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,
+ IN EFI_GUID *Protocol, OPTIONAL
+ IN VOID *SearchKey, OPTIONAL
+ IN OUT UINTN *NoHandles,
+ OUT EFI_HANDLE **Buffer
+ );
+
+/**
+ Returns the first protocol instance that matches the given protocol.
+
+ @param Protocol Provides the protocol to search for.
+ @param Registration Optional registration key returned from
+ RegisterProtocolNotify().
+ @param Interface On return, a pointer to the first interface that matches Protocol and
+ Registration.
+
+ @retval EFI_SUCCESS A protocol instance matching Protocol was found and returned in
+ Interface.
+ @retval EFI_NOT_FOUND No protocol instances were found that match Protocol and
+ Registration.
+ @retval EFI_INVALID_PARAMETER Interface is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LOCATE_PROTOCOL)(
+ IN EFI_GUID *Protocol,
+ IN VOID *Registration, OPTIONAL
+ OUT VOID **Interface
+ );
+
+///
+/// EFI Capsule Block Descriptor
+///
+typedef struct {
+ ///
+ /// Length in bytes of the data pointed to by DataBlock/ContinuationPointer.
+ ///
+ UINT64 Length;
+ union {
+ ///
+ /// Physical address of the data block. This member of the union is
+ /// used if Length is not equal to zero.
+ ///
+ EFI_PHYSICAL_ADDRESS DataBlock;
+ ///
+ /// Physical address of another block of
+ /// EFI_CAPSULE_BLOCK_DESCRIPTOR structures. This
+ /// member of the union is used if Length is equal to zero. If
+ /// ContinuationPointer is zero this entry represents the end of the list.
+ ///
+ EFI_PHYSICAL_ADDRESS ContinuationPointer;
+ } Union;
+} EFI_CAPSULE_BLOCK_DESCRIPTOR;
+
+///
+/// EFI Capsule Header.
+///
+typedef struct {
+ ///
+ /// A GUID that defines the contents of a capsule.
+ ///
+ EFI_GUID CapsuleGuid;
+ ///
+ /// The size of the capsule header. This may be larger than the size of
+ /// the EFI_CAPSULE_HEADER since CapsuleGuid may imply
+ /// extended header entries
+ ///
+ UINT32 HeaderSize;
+ ///
+ /// Bit-mapped list describing the capsule attributes. The Flag values
+ /// of 0x0000 - 0xFFFF are defined by CapsuleGuid. Flag values
+ /// of 0x10000 - 0xFFFFFFFF are defined by this specification
+ ///
+ UINT32 Flags;
+ ///
+ /// Size in bytes of the capsule.
+ ///
+ UINT32 CapsuleImageSize;
+} EFI_CAPSULE_HEADER;
+
+///
+/// The EFI System Table entry must point to an array of capsules
+/// that contain the same CapsuleGuid value. The array must be
+/// prefixed by a UINT32 that represents the size of the array of capsules.
+///
+typedef struct {
+ ///
+ /// the size of the array of capsules.
+ ///
+ UINT32 CapsuleArrayNumber;
+ ///
+ /// Point to an array of capsules that contain the same CapsuleGuid value.
+ ///
+ VOID* CapsulePtr[1];
+} EFI_CAPSULE_TABLE;
+
+#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000
+#define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000
+#define CAPSULE_FLAGS_INITIATE_RESET 0x00040000
+
+/**
+ Passes capsules to the firmware with both virtual and physical mapping. Depending on the intended
+ consumption, the firmware may process the capsule immediately. If the payload should persist
+ across a system reset, the reset value returned from EFI_QueryCapsuleCapabilities must
+ be passed into ResetSystem() and will cause the capsule to be processed by the firmware as
+ part of the reset process.
+
+ @param CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules
+ being passed into update capsule.
+ @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER in
+ CaspuleHeaderArray.
+ @param ScatterGatherList Physical pointer to a set of
+ EFI_CAPSULE_BLOCK_DESCRIPTOR that describes the
+ location in physical memory of a set of capsules.
+
+ @retval EFI_SUCCESS Valid capsule was passed. If
+ CAPSULE_FLAGS_PERSIT_ACROSS_RESET is not set, the
+ capsule has been successfully processed by the firmware.
+ @retval EFI_INVALID_PARAMETER CapsuleSize is NULL, or an incompatible set of flags were
+ set in the capsule header.
+ @retval EFI_INVALID_PARAMETER CapsuleCount is 0.
+ @retval EFI_DEVICE_ERROR The capsule update was started, but failed due to a device error.
+ @retval EFI_UNSUPPORTED The capsule type is not supported on this platform.
+ @retval EFI_OUT_OF_RESOURCES There were insufficient resources to process the capsule.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UPDATE_CAPSULE)(
+ IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,
+ IN UINTN CapsuleCount,
+ IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL
+ );
+
+/**
+ Returns if the capsule can be supported via UpdateCapsule().
+
+ @param CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules
+ being passed into update capsule.
+ @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER in
+ CaspuleHeaderArray.
+ @param MaxiumCapsuleSize On output the maximum size that UpdateCapsule() can
+ support as an argument to UpdateCapsule() via
+ CapsuleHeaderArray and ScatterGatherList.
+ @param ResetType Returns the type of reset required for the capsule update.
+
+ @retval EFI_SUCCESS Valid answer returned.
+ @retval EFI_UNSUPPORTED The capsule type is not supported on this platform, and
+ MaximumCapsuleSize and ResetType are undefined.
+ @retval EFI_INVALID_PARAMETER MaximumCapsuleSize is NULL.
+ @retval EFI_OUT_OF_RESOURCES There were insufficient resources to process the query request.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_QUERY_CAPSULE_CAPABILITIES)(
+ IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,
+ IN UINTN CapsuleCount,
+ OUT UINT64 *MaximumCapsuleSize,
+ OUT EFI_RESET_TYPE *ResetType
+ );
+
+/**
+ Returns information about the EFI variables.
+
+ @param Attributes Attributes bitmask to specify the type of variables on
+ which to return information.
+ @param MaximumVariableStorageSize On output the maximum size of the storage space
+ available for the EFI variables associated with the
+ attributes specified.
+ @param RemainingVariableStorageSize Returns the remaining size of the storage space
+ available for the EFI variables associated with the
+ attributes specified.
+ @param MaximumVariableSize Returns the maximum size of the individual EFI
+ variables associated with the attributes specified.
+
+ @retval EFI_SUCCESS Valid answer returned.
+ @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied
+ @retval EFI_UNSUPPORTED The attribute is not supported on this platform, and the
+ MaximumVariableStorageSize,
+ RemainingVariableStorageSize, MaximumVariableSize
+ are undefined.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_QUERY_VARIABLE_INFO)(
+ IN UINT32 Attributes,
+ OUT UINT64 *MaximumVariableStorageSize,
+ OUT UINT64 *RemainingVariableStorageSize,
+ OUT UINT64 *MaximumVariableSize
+ );
+
+
+//
+// EFI Runtime Services Table
+//
+#define EFI_SYSTEM_TABLE_SIGNATURE SIGNATURE_64 ('I','B','I',' ','S','Y','S','T')
+#define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30))
+#define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20))
+#define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10))
+#define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | (00))
+#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10))
+#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02))
+#define EFI_SYSTEM_TABLE_REVISION EFI_2_30_SYSTEM_TABLE_REVISION
+
+#define EFI_RUNTIME_SERVICES_SIGNATURE SIGNATURE_64 ('R','U','N','T','S','E','R','V')
+#define EFI_RUNTIME_SERVICES_REVISION EFI_2_30_SYSTEM_TABLE_REVISION
+
+///
+/// EFI Runtime Services Table.
+///
+typedef struct {
+ ///
+ /// The table header for the EFI Runtime Services Table.
+ ///
+ EFI_TABLE_HEADER Hdr;
+
+ //
+ // Time Services
+ //
+ EFI_GET_TIME GetTime;
+ EFI_SET_TIME SetTime;
+ EFI_GET_WAKEUP_TIME GetWakeupTime;
+ EFI_SET_WAKEUP_TIME SetWakeupTime;
+
+ //
+ // Virtual Memory Services
+ //
+ EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap;
+ EFI_CONVERT_POINTER ConvertPointer;
+
+ //
+ // Variable Services
+ //
+ EFI_GET_VARIABLE GetVariable;
+ EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName;
+ EFI_SET_VARIABLE SetVariable;
+
+ //
+ // Miscellaneous Services
+ //
+ EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount;
+ EFI_RESET_SYSTEM ResetSystem;
+
+ //
+ // UEFI 2.0 Capsule Services
+ //
+ EFI_UPDATE_CAPSULE UpdateCapsule;
+ EFI_QUERY_CAPSULE_CAPABILITIES QueryCapsuleCapabilities;
+
+ //
+ // Miscellaneous UEFI 2.0 Service
+ //
+ EFI_QUERY_VARIABLE_INFO QueryVariableInfo;
+} EFI_RUNTIME_SERVICES;
+
+
+#define EFI_BOOT_SERVICES_SIGNATURE SIGNATURE_64 ('B','O','O','T','S','E','R','V')
+#define EFI_BOOT_SERVICES_REVISION EFI_2_30_SYSTEM_TABLE_REVISION
+
+///
+/// EFI Boot Services Table.
+///
+typedef struct {
+ ///
+ /// The table header for the EFI Boot Services Table.
+ ///
+ EFI_TABLE_HEADER Hdr;
+
+ //
+ // Task Priority Services
+ //
+ EFI_RAISE_TPL RaiseTPL;
+ EFI_RESTORE_TPL RestoreTPL;
+
+ //
+ // Memory Services
+ //
+ EFI_ALLOCATE_PAGES AllocatePages;
+ EFI_FREE_PAGES FreePages;
+ EFI_GET_MEMORY_MAP GetMemoryMap;
+ EFI_ALLOCATE_POOL AllocatePool;
+ EFI_FREE_POOL FreePool;
+
+ //
+ // Event & Timer Services
+ //
+ EFI_CREATE_EVENT CreateEvent;
+ EFI_SET_TIMER SetTimer;
+ EFI_WAIT_FOR_EVENT WaitForEvent;
+ EFI_SIGNAL_EVENT SignalEvent;
+ EFI_CLOSE_EVENT CloseEvent;
+ EFI_CHECK_EVENT CheckEvent;
+
+ //
+ // Protocol Handler Services
+ //
+ EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface;
+ EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface;
+ EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface;
+ EFI_HANDLE_PROTOCOL HandleProtocol;
+ VOID *Reserved;
+ EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify;
+ EFI_LOCATE_HANDLE LocateHandle;
+ EFI_LOCATE_DEVICE_PATH LocateDevicePath;
+ EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable;
+
+ //
+ // Image Services
+ //
+ EFI_IMAGE_LOAD LoadImage;
+ EFI_IMAGE_START StartImage;
+ EFI_EXIT Exit;
+ EFI_IMAGE_UNLOAD UnloadImage;
+ EFI_EXIT_BOOT_SERVICES ExitBootServices;
+
+ //
+ // Miscellaneous Services
+ //
+ EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount;
+ EFI_STALL Stall;
+ EFI_SET_WATCHDOG_TIMER SetWatchdogTimer;
+
+ //
+ // DriverSupport Services
+ //
+ EFI_CONNECT_CONTROLLER ConnectController;
+ EFI_DISCONNECT_CONTROLLER DisconnectController;
+
+ //
+ // Open and Close Protocol Services
+ //
+ EFI_OPEN_PROTOCOL OpenProtocol;
+ EFI_CLOSE_PROTOCOL CloseProtocol;
+ EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation;
+
+ //
+ // Library Services
+ //
+ EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle;
+ EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer;
+ EFI_LOCATE_PROTOCOL LocateProtocol;
+ EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces;
+ EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces;
+
+ //
+ // 32-bit CRC Services
+ //
+ EFI_CALCULATE_CRC32 CalculateCrc32;
+
+ //
+ // Miscellaneous Services
+ //
+ EFI_COPY_MEM CopyMem;
+ EFI_SET_MEM SetMem;
+ EFI_CREATE_EVENT_EX CreateEventEx;
+} EFI_BOOT_SERVICES;
+
+///
+/// Contains a set of GUID/pointer pairs comprised of the ConfigurationTable field in the
+/// EFI System Table.
+///
+typedef struct {
+ ///
+ /// The 128-bit GUID value that uniquely identifies the system configuration table.
+ ///
+ EFI_GUID VendorGuid;
+ ///
+ /// A pointer to the table associated with VendorGuid.
+ ///
+ VOID *VendorTable;
+} EFI_CONFIGURATION_TABLE;
+
+///
+/// EFI System Table
+///
+typedef struct {
+ ///
+ /// The table header for the EFI System Table.
+ ///
+ EFI_TABLE_HEADER Hdr;
+ ///
+ /// A pointer to a null terminated string that identifies the vendor
+ /// that produces the system firmware for the platform.
+ ///
+ CHAR16 *FirmwareVendor;
+ ///
+ /// A firmware vendor specific value that identifies the revision
+ /// of the system firmware for the platform.
+ ///
+ UINT32 FirmwareRevision;
+ ///
+ /// The handle for the active console input device. This handle must support
+ /// EFI_SIMPLE_TEXT_INPUT_PROTOCOL and EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
+ ///
+ EFI_HANDLE ConsoleInHandle;
+ ///
+ /// A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL interface that is
+ /// associated with ConsoleInHandle.
+ ///
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
+ ///
+ /// The handle for the active console output device.
+ ///
+ EFI_HANDLE ConsoleOutHandle;
+ ///
+ /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface
+ /// that is associated with ConsoleOutHandle.
+ ///
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
+ ///
+ /// The handle for the active standard error console device.
+ /// This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.
+ ///
+ EFI_HANDLE StandardErrorHandle;
+ ///
+ /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface
+ /// that is associated with StandardErrorHandle.
+ ///
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr;
+ ///
+ /// A pointer to the EFI Runtime Services Table.
+ ///
+ EFI_RUNTIME_SERVICES *RuntimeServices;
+ ///
+ /// A pointer to the EFI Boot Services Table.
+ ///
+ EFI_BOOT_SERVICES *BootServices;
+ ///
+ /// The number of system configuration tables in the buffer ConfigurationTable.
+ ///
+ UINTN NumberOfTableEntries;
+ ///
+ /// A pointer to the system configuration tables.
+ /// The number of entries in the table is NumberOfTableEntries.
+ ///
+ EFI_CONFIGURATION_TABLE *ConfigurationTable;
+} EFI_SYSTEM_TABLE;
+
+/**
+ This is the declaration of an EFI image entry point. This entry point is
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+ both device drivers and bus drivers.
+
+ @param ImageHandle The firmware allocated handle for the UEFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IMAGE_ENTRY_POINT)(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+//
+// EFI Load Options Attributes
+//
+#define LOAD_OPTION_ACTIVE 0x00000001
+#define LOAD_OPTION_FORCE_RECONNECT 0x00000002
+#define LOAD_OPTION_HIDDEN 0x00000008
+#define LOAD_OPTION_CATEGORY 0x00001F00
+
+#define LOAD_OPTION_CATEGORY_BOOT 0x00000000
+#define LOAD_OPTION_CATEGORY_APP 0x00000100
+
+#define EFI_BOOT_OPTION_SUPPORT_KEY 0x00000001
+#define EFI_BOOT_OPTION_SUPPORT_APP 0x00000002
+#define EFI_BOOT_OPTION_SUPPORT_COUNT 0x00000300
+
+///
+/// EFI Boot Key Data
+///
+typedef union {
+ struct {
+ ///
+ /// Indicates the revision of the EFI_KEY_OPTION structure. This revision level should be 0.
+ ///
+ UINT32 Revision : 8;
+ ///
+ /// Either the left or right Shift keys must be pressed (1) or must not be pressed (0).
+ ///
+ UINT32 ShiftPressed : 1;
+ ///
+ /// Either the left or right Control keys must be pressed (1) or must not be pressed (0).
+ ///
+ UINT32 ControlPressed : 1;
+ ///
+ /// Either the left or right Alt keys must be pressed (1) or must not be pressed (0).
+ ///
+ UINT32 AltPressed : 1;
+ ///
+ /// Either the left or right Logo keys must be pressed (1) or must not be pressed (0).
+ ///
+ UINT32 LogoPressed : 1;
+ ///
+ /// The Menu key must be pressed (1) or must not be pressed (0).
+ ///
+ UINT32 MenuPressed : 1;
+ ///
+ /// The SysReq key must be pressed (1) or must not be pressed (0).
+ ///
+ UINT32 SysReqPressed : 1;
+ UINT32 Reserved : 16;
+ ///
+ /// Specifies the actual number of entries in EFI_KEY_OPTION.Keys, from 0-3. If
+ /// zero, then only the shift state is considered. If more than one, then the boot option will
+ /// only be launched if all of the specified keys are pressed with the same shift state.
+ ///
+ UINT32 InputKeyCount : 2;
+ } Options;
+ UINT32 PackedValue;
+} EFI_BOOT_KEY_DATA;
+
+///
+/// EFI Key Option.
+///
+typedef struct {
+ ///
+ /// Specifies options about how the key will be processed.
+ ///
+ EFI_BOOT_KEY_DATA KeyData;
+ ///
+ /// The CRC-32 which should match the CRC-32 of the entire EFI_LOAD_OPTION to
+ /// which BootOption refers. If the CRC-32s do not match this value, then this key
+ /// option is ignored.
+ ///
+ UINT32 BootOptionCrc;
+ ///
+ /// The Boot#### option which will be invoked if this key is pressed and the boot option
+ /// is active (LOAD_OPTION_ACTIVE is set).
+ ///
+ UINT16 BootOption;
+ ///
+ /// The key codes to compare against those returned by the
+ /// EFI_SIMPLE_TEXT_INPUT and EFI_SIMPLE_TEXT_INPUT_EX protocols.
+ /// The number of key codes (0-3) is specified by the EFI_KEY_CODE_COUNT field in KeyOptions.
+ ///
+ //EFI_INPUT_KEY Keys[];
+} EFI_KEY_OPTION;
+
+//
+// EFI File location to boot from on removable media devices
+//
+#define EFI_REMOVABLE_MEDIA_FILE_NAME_IA32 L"\\EFI\\BOOT\\BOOTIA32.EFI"
+#define EFI_REMOVABLE_MEDIA_FILE_NAME_IA64 L"\\EFI\\BOOT\\BOOTIA64.EFI"
+#define EFI_REMOVABLE_MEDIA_FILE_NAME_X64 L"\\EFI\\BOOT\\BOOTX64.EFI"
+#define EFI_REMOVABLE_MEDIA_FILE_NAME_ARM L"\\EFI\\BOOT\\BOOTARM.EFI"
+
+#if defined (MDE_CPU_IA32)
+ #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_IA32
+#elif defined (MDE_CPU_IPF)
+ #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_IA64
+#elif defined (MDE_CPU_X64)
+ #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_X64
+#elif defined (MDE_CPU_EBC)
+#elif defined (MDE_CPU_ARM)
+ #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_ARM
+#else
+ #error Unknown Processor Type
+#endif
+
+#include <ipxe/efi/Uefi/UefiPxe.h>
+#include <ipxe/efi/Uefi/UefiGpt.h>
+#include <ipxe/efi/Uefi/UefiInternalFormRepresentation.h>
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/X64/ProcessorBind.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/X64/ProcessorBind.h
new file mode 100644
index 00000000..0b1a3e11
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/X64/ProcessorBind.h
@@ -0,0 +1,290 @@
+/** @file
+ Processor or Compiler specific defines and types x64 (Intel 64, AMD64).
+
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PROCESSOR_BIND_H__
+#define __PROCESSOR_BIND_H__
+
+FILE_LICENCE ( BSD3 );
+
+///
+/// Define the processor type so other code can make processor based choices
+///
+#define MDE_CPU_X64
+
+//
+// Make sure we are using the correct packing rules per EFI specification
+//
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+
+#if defined(__INTEL_COMPILER)
+//
+// Disable ICC's remark #869: "Parameter" was never referenced warning.
+// This is legal ANSI C code so we disable the remark that is turned on with -Wall
+//
+#pragma warning ( disable : 869 )
+
+//
+// Disable ICC's remark #1418: external function definition with no prior declaration.
+// This is legal ANSI C code so we disable the remark that is turned on with /W4
+//
+#pragma warning ( disable : 1418 )
+
+//
+// Disable ICC's remark #1419: external declaration in primary source file
+// This is legal ANSI C code so we disable the remark that is turned on with /W4
+//
+#pragma warning ( disable : 1419 )
+
+//
+// Disable ICC's remark #593: "Variable" was set but never used.
+// This is legal ANSI C code so we disable the remark that is turned on with /W4
+//
+#pragma warning ( disable : 593 )
+
+#endif
+
+
+#if defined(_MSC_EXTENSIONS)
+
+//
+// Disable warning that make it impossible to compile at /W4
+// This only works for Microsoft* tools
+//
+
+//
+// Disabling bitfield type checking warnings.
+//
+#pragma warning ( disable : 4214 )
+
+//
+// Disabling the unreferenced formal parameter warnings.
+//
+#pragma warning ( disable : 4100 )
+
+//
+// Disable slightly different base types warning as CHAR8 * can not be set
+// to a constant string.
+//
+#pragma warning ( disable : 4057 )
+
+//
+// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning
+//
+#pragma warning ( disable : 4127 )
+
+//
+// This warning is caused by functions defined but not used. For precompiled header only.
+//
+#pragma warning ( disable : 4505 )
+
+//
+// This warning is caused by empty (after preprocessing) source file. For precompiled header only.
+//
+#pragma warning ( disable : 4206 )
+
+#endif
+
+
+#if defined(_MSC_EXTENSIONS)
+ //
+ // use Microsoft C complier dependent integer width types
+ //
+
+ ///
+ /// 8-byte unsigned value
+ ///
+ typedef unsigned __int64 UINT64;
+ ///
+ /// 8-byte signed value
+ ///
+ typedef __int64 INT64;
+ ///
+ /// 4-byte unsigned value
+ ///
+ typedef unsigned __int32 UINT32;
+ ///
+ /// 4-byte signed value
+ ///
+ typedef __int32 INT32;
+ ///
+ /// 2-byte unsigned value
+ ///
+ typedef unsigned short UINT16;
+ ///
+ /// 2-byte Character. Unless otherwise specified all strings are stored in the
+ /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
+ ///
+ typedef unsigned short CHAR16;
+ ///
+ /// 2-byte signed value
+ ///
+ typedef short INT16;
+ ///
+ /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
+ /// values are undefined.
+ ///
+ typedef unsigned char BOOLEAN;
+ ///
+ /// 1-byte unsigned value
+ ///
+ typedef unsigned char UINT8;
+ ///
+ /// 1-byte Character
+ ///
+ typedef char CHAR8;
+ ///
+ /// 1-byte signed value
+ ///
+ typedef char INT8;
+#else
+ ///
+ /// 8-byte unsigned value
+ ///
+ typedef unsigned long long UINT64;
+ ///
+ /// 8-byte signed value
+ ///
+ typedef long long INT64;
+ ///
+ /// 4-byte unsigned value
+ ///
+ typedef unsigned int UINT32;
+ ///
+ /// 4-byte signed value
+ ///
+ typedef int INT32;
+ ///
+ /// 2-byte unsigned value
+ ///
+ typedef unsigned short UINT16;
+ ///
+ /// 2-byte Character. Unless otherwise specified all strings are stored in the
+ /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
+ ///
+ typedef unsigned short CHAR16;
+ ///
+ /// 2-byte signed value
+ ///
+ typedef short INT16;
+ ///
+ /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
+ /// values are undefined.
+ ///
+ typedef unsigned char BOOLEAN;
+ ///
+ /// 1-byte unsigned value
+ ///
+ typedef unsigned char UINT8;
+ ///
+ /// 1-byte Character
+ ///
+ typedef char CHAR8;
+ ///
+ /// 1-byte signed value
+ ///
+ typedef char INT8;
+#endif
+
+///
+/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions,
+/// 8 bytes on supported 64-bit processor instructions)
+///
+typedef UINT64 UINTN;
+///
+/// Signed value of native width. (4 bytes on supported 32-bit processor instructions,
+/// 8 bytes on supported 64-bit processor instructions)
+///
+typedef INT64 INTN;
+
+
+//
+// Processor specific defines
+//
+
+///
+/// A value of native width with the highest bit set.
+///
+#define MAX_BIT 0x8000000000000000ULL
+///
+/// A value of native width with the two highest bits set.
+///
+#define MAX_2_BITS 0xC000000000000000ULL
+
+///
+/// Maximum legal x64 address
+///
+#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL
+
+///
+/// The stack alignment required for x64
+///
+#define CPU_STACK_ALIGNMENT 16
+
+//
+// Modifier to ensure that all protocol member functions and EFI intrinsics
+// use the correct C calling convention. All protocol member functions and
+// EFI intrinsics are required to modify their member functions with EFIAPI.
+//
+#ifdef EFIAPI
+ ///
+ /// If EFIAPI is already defined, then we use that definition.
+ ///
+#elif defined(_MSC_EXTENSIONS)
+ ///
+ /// Microsoft* compiler specific method for EFIAPI calling convension
+ ///
+ #define EFIAPI __cdecl
+#elif defined(__GNUC__)
+ ///
+ /// Define the standard calling convention reguardless of optimization level.
+ /// The GCC support assumes a GCC compiler that supports the EFI ABI. The EFI
+ /// ABI is much closer to the x64 Microsoft* ABI than standard x64 (x86-64)
+ /// GCC ABI. Thus a standard x64 (x86-64) GCC compiler can not be used for
+ /// x64. Warning the assembly code in the MDE x64 does not follow the correct
+ /// ABI for the standard x64 (x86-64) GCC.
+ ///
+ #define EFIAPI
+#else
+ ///
+ /// The default for a non Microsoft* or GCC compiler is to assume the EFI ABI
+ /// is the standard.
+ ///
+ #define EFIAPI
+#endif
+
+#if defined(__GNUC__)
+ ///
+ /// For GNU assembly code, .global or .globl can declare global symbols.
+ /// Define this macro to unify the usage.
+ ///
+ #define ASM_GLOBAL .globl
+#endif
+
+/**
+ Return the pointer to the first instruction of a function given a function pointer.
+ On x64 CPU architectures, these two pointer values are the same,
+ so the implementation of this macro is very simple.
+
+ @param FunctionPointer A pointer to a function.
+
+ @return The pointer to the first instruction of a function given a function pointer.
+
+**/
+#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer)
+
+#endif
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi.h
new file mode 100644
index 00000000..b5ce7df9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi.h
@@ -0,0 +1,148 @@
+#ifndef _IPXE_EFI_H
+#define _IPXE_EFI_H
+
+/** @file
+ *
+ * EFI API
+ *
+ * The intention is to include near-verbatim copies of the EFI headers
+ * required by iPXE. This is achieved using the import.pl script in
+ * this directory. Run the import script to update the local copies
+ * of the headers:
+ *
+ * ./import.pl /path/to/edk2/edk2
+ *
+ * where /path/to/edk2/edk2 is the path to your local checkout of the
+ * EFI Development Kit.
+ *
+ * Note that import.pl will modify any #include lines in each imported
+ * header to reflect its new location within the iPXE tree. It will
+ * also tidy up the file by removing carriage return characters and
+ * trailing whitespace.
+ */
+
+/* EFI headers rudely redefine NULL */
+#undef NULL
+
+/* EFI headers expect ICC to define __GNUC__ */
+#if defined ( __ICC ) && ! defined ( __GNUC__ )
+#define __GNUC__ 1
+#endif
+
+/* EFI headers think your compiler uses the MS ABI by default on X64 */
+#if __x86_64__
+#define EFIAPI __attribute__((ms_abi))
+#endif
+
+/* EFI headers assume regparm(0) on i386, but that is not the case for iPXE */
+#if __i386__
+#define EFIAPI __attribute__((cdecl,regparm(0)))
+#endif
+
+/* Include the top-level EFI header files */
+#include <ipxe/efi/Uefi.h>
+#include <ipxe/efi/PiDxe.h>
+#include <ipxe/efi/Protocol/LoadedImage.h>
+
+/* Reset any trailing #pragma pack directives */
+#pragma pack(1)
+#pragma pack()
+
+#include <ipxe/tables.h>
+#include <ipxe/uuid.h>
+
+/** An EFI protocol used by iPXE */
+struct efi_protocol {
+ /** GUID */
+ union {
+ /** EFI protocol GUID */
+ EFI_GUID guid;
+ /** UUID structure understood by iPXE */
+ union uuid uuid;
+ } u;
+ /** Variable containing pointer to protocol structure */
+ void **protocol;
+};
+
+/** EFI protocol table */
+#define EFI_PROTOCOLS __table ( struct efi_protocol, "efi_protocols" )
+
+/** Declare an EFI protocol used by iPXE */
+#define __efi_protocol __table_entry ( EFI_PROTOCOLS, 01 )
+
+/** Declare an EFI protocol to be required by iPXE
+ *
+ * @v _protocol EFI protocol name
+ * @v _ptr Pointer to protocol instance
+ */
+#define EFI_REQUIRE_PROTOCOL( _protocol, _ptr ) \
+ struct efi_protocol __ ## _protocol __efi_protocol = { \
+ .u.guid = _protocol ## _GUID, \
+ .protocol = ( ( void ** ) ( void * ) \
+ ( ( (_ptr) == ( ( _protocol ** ) (_ptr) ) ) ? \
+ (_ptr) : (_ptr) ) ), \
+ }
+
+/** An EFI configuration table used by iPXE */
+struct efi_config_table {
+ /** GUID */
+ union {
+ /** EFI configuration table GUID */
+ EFI_GUID guid;
+ /** UUID structure understood by iPXE */
+ union uuid uuid;
+ } u;
+ /** Variable containing pointer to configuration table */
+ void **table;
+ /** Table is required for operation */
+ int required;
+};
+
+/** EFI configuration table table */
+#define EFI_CONFIG_TABLES \
+ __table ( struct efi_config_table, "efi_config_tables" )
+
+/** Declare an EFI configuration table used by iPXE */
+#define __efi_config_table __table_entry ( EFI_CONFIG_TABLES, 01 )
+
+/** Declare an EFI configuration table to be used by iPXE
+ *
+ * @v _table EFI configuration table name
+ * @v _ptr Pointer to configuration table
+ * @v _required Table is required for operation
+ */
+#define EFI_USE_TABLE( _table, _ptr, _required ) \
+ struct efi_config_table __ ## _table __efi_config_table = { \
+ .u.guid = _table ## _GUID, \
+ .table = ( ( void ** ) ( void * ) (_ptr) ), \
+ .required = (_required), \
+ }
+
+/** Convert a iPXE status code to an EFI status code
+ *
+ * FIXME: actually perform some kind of conversion. iPXE error codes
+ * will be detected as EFI error codes; both have the top bit set, and
+ * the success return code is zero for both. Anything that just
+ * reports a numerical error will be OK, anything attempting to
+ * interpret the value or to display a text equivalent will be
+ * screwed.
+ */
+#define RC_TO_EFIRC( rc ) (rc)
+
+/** Convert an EFI status code to a iPXE status code
+ *
+ * FIXME: as above
+ */
+#define EFIRC_TO_RC( efirc ) (efirc)
+
+extern EFI_HANDLE efi_image_handle;
+extern EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image;
+extern EFI_SYSTEM_TABLE *efi_systab;
+
+extern const char * efi_strerror ( EFI_STATUS efirc );
+extern EFI_STATUS efi_init ( EFI_HANDLE image_handle,
+ EFI_SYSTEM_TABLE *systab );
+extern int efi_download_install ( EFI_HANDLE *device_handle );
+extern void efi_download_uninstall ( EFI_HANDLE device_handle );
+
+#endif /* _IPXE_EFI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_driver.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_driver.h
new file mode 100644
index 00000000..e5872ced
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_driver.h
@@ -0,0 +1,49 @@
+#ifndef _IPXE_EFI_DRIVER_H
+#define _IPXE_EFI_DRIVER_H
+
+/** @file
+ *
+ * EFI driver interface
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/Protocol/DriverBinding.h>
+#include <ipxe/efi/Protocol/ComponentName2.h>
+#include <ipxe/efi/Protocol/DevicePath.h>
+
+/** An EFI driver */
+struct efi_driver {
+ /** Name */
+ const char *name;
+ /** EFI name */
+ CHAR16 wname[32];
+ /** EFI driver binding protocol */
+ EFI_DRIVER_BINDING_PROTOCOL driver;
+ /** EFI component name protocol */
+ EFI_COMPONENT_NAME2_PROTOCOL wtf;
+};
+
+/** Initialise an EFI driver
+ *
+ * @v name Driver name
+ * @v supported Device supported method
+ * @v start Device start method
+ * @v stop Device stop method
+ */
+#define EFI_DRIVER_INIT( _name, _supported, _start, _stop ) { \
+ .name = _name, \
+ .driver = { \
+ .Supported = _supported, \
+ .Start = _start, \
+ .Stop = _stop, \
+ .Version = 0x10, \
+ } }
+
+extern EFI_DEVICE_PATH_PROTOCOL *
+efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path );
+
+extern EFI_STATUS efi_driver_install ( struct efi_driver *efidrv );
+
+#endif /* _IPXE_EFI_DRIVER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_hii.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_hii.h
new file mode 100644
index 00000000..1a98750f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_hii.h
@@ -0,0 +1,140 @@
+#ifndef _IPXE_EFI_HII_H
+#define _IPXE_EFI_HII_H
+
+/** @file
+ *
+ * EFI human interface infrastructure
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/efi/Uefi/UefiInternalFormRepresentation.h>
+#include <ipxe/efi/Guid/MdeModuleHii.h>
+
+/**
+ * Define an EFI IFR form set type
+ *
+ * @v num_class_guids Number of class GUIDs
+ * @ret type Form set type
+ */
+#define EFI_IFR_FORM_SET_TYPE( num_class_guids ) \
+ struct { \
+ EFI_IFR_FORM_SET FormSet; \
+ EFI_GUID ClassGuid[num_class_guids]; \
+ } __attribute__ (( packed ))
+
+/**
+ * Define an EFI IFR form set
+ *
+ * @v guid GUID
+ * @v title Title string
+ * @v help Help string
+ * @v type Form set type (as returned by EFI_IFR_FORM_SET_TYPE())
+ * @ret ifr Form set
+ *
+ * This definition opens a new scope, which must be closed by an
+ * EFI_IFR_END().
+ */
+#define EFI_IFR_FORM_SET( guid, title, help, type, ... ) { \
+ .FormSet = { \
+ .Header = { \
+ .OpCode = EFI_IFR_FORM_SET_OP, \
+ .Length = sizeof ( type ), \
+ .Scope = 1, \
+ }, \
+ .Guid = guid, \
+ .FormSetTitle = title, \
+ .Help = help, \
+ .Flags = ( sizeof ( ( ( type * ) NULL )->ClassGuid ) / \
+ sizeof ( ( ( type * ) NULL )->ClassGuid[0] ) ), \
+ }, \
+ .ClassGuid = { \
+ __VA_ARGS__ \
+ }, \
+ }
+
+/**
+ * Define an EFI IFR GUID class
+ *
+ * @v class Class
+ * @ret ifr GUID class
+ */
+#define EFI_IFR_GUID_CLASS( class ) { \
+ .Header = { \
+ .OpCode = EFI_IFR_GUID_OP, \
+ .Length = sizeof ( EFI_IFR_GUID_CLASS ), \
+ }, \
+ .Guid = EFI_IFR_TIANO_GUID, \
+ .ExtendOpCode = EFI_IFR_EXTEND_OP_CLASS, \
+ .Class = class, \
+ }
+
+/**
+ * Define an EFI IFR GUID subclass
+ *
+ * @v subclass Subclass
+ * @ret ifr GUID subclass
+ */
+#define EFI_IFR_GUID_SUBCLASS( subclass ) { \
+ .Header = { \
+ .OpCode = EFI_IFR_GUID_OP, \
+ .Length = sizeof ( EFI_IFR_GUID_SUBCLASS ), \
+ }, \
+ .Guid = EFI_IFR_TIANO_GUID, \
+ .ExtendOpCode = EFI_IFR_EXTEND_OP_SUBCLASS, \
+ .SubClass = subclass, \
+ }
+
+/**
+ * Define an EFI IFR form
+ *
+ * @v formid Form ID
+ * @v title Title string
+ * @ret ifr Form
+ *
+ * This definition opens a new scope, which must be closed by an
+ * EFI_IFR_END().
+ */
+#define EFI_IFR_FORM( formid, title ) { \
+ .Header = { \
+ .OpCode = EFI_IFR_FORM_OP, \
+ .Length = sizeof ( EFI_IFR_FORM ), \
+ .Scope = 1, \
+ }, \
+ .FormId = formid, \
+ .FormTitle = title, \
+ }
+
+/**
+ * Define an EFI IFR text widget
+ *
+ * @v prompt Prompt string
+ * @v help Help string
+ * @v text Text string
+ * @ret ifr Text widget
+ */
+#define EFI_IFR_TEXT( prompt, help, text ) { \
+ .Header = { \
+ .OpCode = EFI_IFR_TEXT_OP, \
+ .Length = sizeof ( EFI_IFR_TEXT ), \
+ }, \
+ .Statement = { \
+ .Prompt = prompt, \
+ .Help = help, \
+ }, \
+ .TextTwo = text, \
+ }
+
+/**
+ * Define an EFI IFR end marker
+ *
+ * @ret ifr End marker
+ */
+#define EFI_IFR_END() { \
+ .Header = { \
+ .OpCode = EFI_IFR_END_OP, \
+ .Length = sizeof ( EFI_IFR_END ), \
+ }, \
+ }
+
+#endif /* _IPXE_EFI_HII_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_io.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_io.h
new file mode 100644
index 00000000..2ed96e10
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_io.h
@@ -0,0 +1,180 @@
+#ifndef _IPXE_EFI_IO_H
+#define _IPXE_EFI_IO_H
+
+/** @file
+ *
+ * iPXE I/O API for EFI
+ *
+ * EFI runs with flat physical addressing, so the various mappings
+ * between virtual addresses, I/O addresses and bus addresses are all
+ * no-ops. I/O is handled using the EFI_CPU_IO_PROTOCOL.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef IOAPI_EFI
+#define IOAPI_PREFIX_efi
+#else
+#define IOAPI_PREFIX_efi __efi_
+#endif
+
+extern unsigned long long efi_ioread ( volatile void *io_addr,
+ size_t size );
+extern void efi_iowrite ( unsigned long long data, volatile void *io_addr,
+ size_t size );
+extern void efi_ioreads ( volatile void *io_addr, void *data,
+ size_t size, unsigned int count );
+extern void efi_iowrites ( volatile void *io_addr, const void *data,
+ size_t size, unsigned int count );
+
+/*
+ * Physical<->Bus and Bus<->I/O address mappings
+ *
+ * EFI runs with flat physical addressing, so these are all no-ops.
+ *
+ */
+
+static inline __always_inline unsigned long
+IOAPI_INLINE ( efi, phys_to_bus ) ( unsigned long phys_addr ) {
+ return phys_addr;
+}
+
+static inline __always_inline unsigned long
+IOAPI_INLINE ( efi, bus_to_phys ) ( unsigned long bus_addr ) {
+ return bus_addr;
+}
+
+static inline __always_inline void *
+IOAPI_INLINE ( efi, ioremap ) ( unsigned long bus_addr, size_t len __unused ) {
+ return ( ( void * ) bus_addr );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, iounmap ) ( volatile const void *io_addr __unused ) {
+ /* Nothing to do */
+}
+
+static inline __always_inline unsigned long
+IOAPI_INLINE ( efi, io_to_bus ) ( volatile const void *io_addr ) {
+ return ( ( unsigned long ) io_addr );
+}
+
+/*
+ * I/O functions
+ *
+ */
+
+static inline __always_inline uint8_t
+IOAPI_INLINE ( efi, readb ) ( volatile uint8_t *io_addr ) {
+ return efi_ioread ( io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline uint16_t
+IOAPI_INLINE ( efi, readw ) ( volatile uint16_t *io_addr ) {
+ return efi_ioread ( io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline uint32_t
+IOAPI_INLINE ( efi, readl ) ( volatile uint32_t *io_addr ) {
+ return efi_ioread ( io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline uint64_t
+IOAPI_INLINE ( efi, readq ) ( volatile uint64_t *io_addr ) {
+ return efi_ioread ( io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, writeb ) ( uint8_t data, volatile uint8_t *io_addr ) {
+ efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, writew ) ( uint16_t data, volatile uint16_t *io_addr ) {
+ efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, writel ) ( uint32_t data, volatile uint32_t *io_addr ) {
+ efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, writeq ) ( uint64_t data, volatile uint64_t *io_addr ) {
+ efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline uint8_t
+IOAPI_INLINE ( efi, inb ) ( volatile uint8_t *io_addr ) {
+ return efi_ioread ( io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline uint16_t
+IOAPI_INLINE ( efi, inw ) ( volatile uint16_t *io_addr ) {
+ return efi_ioread ( io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline uint32_t
+IOAPI_INLINE ( efi, inl ) ( volatile uint32_t *io_addr ) {
+ return efi_ioread ( io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, outb ) ( uint8_t data, volatile uint8_t *io_addr ) {
+ efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, outw ) ( uint16_t data, volatile uint16_t *io_addr ) {
+ efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, outl ) ( uint32_t data, volatile uint32_t *io_addr ) {
+ efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, insb ) ( volatile uint8_t *io_addr, uint8_t *data,
+ unsigned int count ) {
+ efi_ioreads ( io_addr, data, sizeof ( *io_addr ), count );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, insw ) ( volatile uint16_t *io_addr, uint16_t *data,
+ unsigned int count ) {
+ efi_ioreads ( io_addr, data, sizeof ( *io_addr ), count );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, insl ) ( volatile uint32_t *io_addr, uint32_t *data,
+ unsigned int count ) {
+ efi_ioreads ( io_addr, data, sizeof ( *io_addr ), count );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, outsb ) ( volatile uint8_t *io_addr, const uint8_t *data,
+ unsigned int count ) {
+ efi_iowrites ( io_addr, data, sizeof ( *io_addr ), count );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, outsw ) ( volatile uint16_t *io_addr, const uint16_t *data,
+ unsigned int count ) {
+ efi_iowrites ( io_addr, data, sizeof ( *io_addr ), count );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, outsl ) ( volatile uint32_t *io_addr, const uint32_t *data,
+ unsigned int count ) {
+ efi_iowrites ( io_addr, data, sizeof ( *io_addr ), count );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( efi, mb ) ( void ) {
+ /* Do nothing; EFI readl()/writel() calls already act as
+ * memory barriers.
+ */
+}
+
+#endif /* _IPXE_EFI_IO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_pci.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_pci.h
new file mode 100644
index 00000000..24890eb4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_pci.h
@@ -0,0 +1,46 @@
+#ifndef _IPXE_EFI_PCI_H
+#define _IPXE_EFI_PCI_H
+
+/** @file
+ *
+ * EFI driver interface
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/Protocol/PciIo.h>
+#include <ipxe/efi/Protocol/DevicePath.h>
+
+struct efi_driver;
+struct device;
+
+/** An EFI PCI device */
+struct efi_pci_device {
+ /** List of EFI PCI devices */
+ struct list_head list;
+ /** iPXE PCI device */
+ struct pci_device pci;
+ /** Underlying EFI device */
+ EFI_HANDLE device;
+ /** PCI I/O protocol */
+ EFI_PCI_IO_PROTOCOL *pci_io;
+ /** Device path */
+ EFI_DEVICE_PATH_PROTOCOL *path;
+ /** EFI driver */
+ struct efi_driver *efidrv;
+};
+
+extern struct efi_pci_device * efipci_create ( struct efi_driver *efidrv,
+ EFI_HANDLE device );
+extern EFI_STATUS efipci_enable ( struct efi_pci_device *efipci );
+extern struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device );
+extern struct efi_pci_device * efipci_find ( struct device *dev );
+extern EFI_STATUS efipci_child_add ( struct efi_pci_device *efipci,
+ EFI_HANDLE device );
+extern void efipci_child_del ( struct efi_pci_device *efipci,
+ EFI_HANDLE device );
+extern void efipci_destroy ( struct efi_driver *efidrv,
+ struct efi_pci_device *efipci );
+
+#endif /* _IPXE_EFI_PCI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_pci_api.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_pci_api.h
new file mode 100644
index 00000000..1bc43e30
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_pci_api.h
@@ -0,0 +1,148 @@
+#ifndef _IPXE_EFI_PCI_API_H
+#define _IPXE_EFI_PCI_API_H
+
+/** @file
+ *
+ * iPXE PCI I/O API for EFI
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef PCIAPI_EFI
+#define PCIAPI_PREFIX_efi
+#else
+#define PCIAPI_PREFIX_efi __efi_
+#endif
+
+/* EFI PCI width codes defined by EFI spec */
+#define EFIPCI_WIDTH_BYTE 0
+#define EFIPCI_WIDTH_WORD 1
+#define EFIPCI_WIDTH_DWORD 2
+
+#define EFIPCI_LOCATION( _offset, _width ) \
+ ( (_offset) | ( (_width) << 16 ) )
+#define EFIPCI_OFFSET( _location ) ( (_location) & 0xffff )
+#define EFIPCI_WIDTH( _location ) ( (_location) >> 16 )
+
+struct pci_device;
+
+extern int efipci_read ( struct pci_device *pci, unsigned long location,
+ void *value );
+extern int efipci_write ( struct pci_device *pci, unsigned long location,
+ unsigned long value );
+
+/**
+ * Determine number of PCI buses within system
+ *
+ * @ret num_bus Number of buses
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( efi, pci_num_bus ) ( void ) {
+ /* EFI does not want us to scan the PCI bus ourselves */
+ return 0;
+}
+
+/**
+ * Read byte from PCI configuration space via EFI
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( efi, pci_read_config_byte ) ( struct pci_device *pci,
+ unsigned int where,
+ uint8_t *value ) {
+ return efipci_read ( pci,
+ EFIPCI_LOCATION ( where, EFIPCI_WIDTH_BYTE ),
+ value );
+}
+
+/**
+ * Read word from PCI configuration space via EFI
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( efi, pci_read_config_word ) ( struct pci_device *pci,
+ unsigned int where,
+ uint16_t *value ) {
+ return efipci_read ( pci,
+ EFIPCI_LOCATION ( where, EFIPCI_WIDTH_WORD ),
+ value );
+}
+
+/**
+ * Read dword from PCI configuration space via EFI
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( efi, pci_read_config_dword ) ( struct pci_device *pci,
+ unsigned int where,
+ uint32_t *value ) {
+ return efipci_read ( pci,
+ EFIPCI_LOCATION ( where, EFIPCI_WIDTH_DWORD ),
+ value );
+}
+
+/**
+ * Write byte to PCI configuration space via EFI
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( efi, pci_write_config_byte ) ( struct pci_device *pci,
+ unsigned int where,
+ uint8_t value ) {
+ return efipci_write ( pci,
+ EFIPCI_LOCATION ( where, EFIPCI_WIDTH_BYTE ),
+ value );
+}
+
+/**
+ * Write word to PCI configuration space via EFI
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( efi, pci_write_config_word ) ( struct pci_device *pci,
+ unsigned int where,
+ uint16_t value ) {
+ return efipci_write ( pci,
+ EFIPCI_LOCATION ( where, EFIPCI_WIDTH_WORD ),
+ value );
+}
+
+/**
+ * Write dword to PCI configuration space via EFI
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( efi, pci_write_config_dword ) ( struct pci_device *pci,
+ unsigned int where,
+ uint32_t value ) {
+ return efipci_write ( pci,
+ EFIPCI_LOCATION ( where, EFIPCI_WIDTH_DWORD ),
+ value );
+}
+
+#endif /* _IPXE_EFI_PCI_API_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_smbios.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_smbios.h
new file mode 100644
index 00000000..7642e5bc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_smbios.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_EFI_SMBIOS_H
+#define _IPXE_EFI_SMBIOS_H
+
+/** @file
+ *
+ * iPXE SMBIOS API for EFI
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef SMBIOS_EFI
+#define SMBIOS_PREFIX_efi
+#else
+#define SMBIOS_PREFIX_efi __efi_
+#endif
+
+#endif /* _IPXE_EFI_SMBIOS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_strings.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_strings.h
new file mode 100644
index 00000000..023ccda0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_strings.h
@@ -0,0 +1,23 @@
+#ifndef _IPXE_EFI_STRINGS_H
+#define _IPXE_EFI_STRINGS_H
+
+/** @file
+ *
+ * EFI strings
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdarg.h>
+
+extern int efi_vsnprintf ( wchar_t *wbuf, size_t wsize, const char *fmt,
+ va_list args );
+extern int efi_snprintf ( wchar_t *wbuf, size_t wsize, const char *fmt, ... );
+extern int efi_vssnprintf ( wchar_t *wbuf, ssize_t swsize, const char *fmt,
+ va_list args );
+extern int efi_ssnprintf ( wchar_t *wbuf, ssize_t swsize,
+ const char *fmt, ... );
+
+#endif /* _IPXE_EFI_STRINGS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_timer.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_timer.h
new file mode 100644
index 00000000..b10543d6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_timer.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_EFI_TIMER_H
+#define _IPXE_EFI_TIMER_H
+
+/** @file
+ *
+ * iPXE timer API for EFI
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef TIMER_EFI
+#define TIMER_PREFIX_efi
+#else
+#define TIMER_PREFIX_efi __efi_
+#endif
+
+#endif /* _IPXE_EFI_TIMER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_uaccess.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_uaccess.h
new file mode 100644
index 00000000..dc226a3e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_uaccess.h
@@ -0,0 +1,90 @@
+#ifndef _IPXE_EFI_UACCESS_H
+#define _IPXE_EFI_UACCESS_H
+
+/** @file
+ *
+ * iPXE user access API for EFI
+ *
+ * EFI runs with flat physical addressing, so the various mappings
+ * between virtual addresses, I/O addresses and bus addresses are all
+ * no-ops.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef UACCESS_EFI
+#define UACCESS_PREFIX_efi
+#else
+#define UACCESS_PREFIX_efi __efi_
+#endif
+
+/**
+ * Convert physical address to user pointer
+ *
+ * @v phys_addr Physical address
+ * @ret userptr User pointer
+ */
+static inline __always_inline userptr_t
+UACCESS_INLINE ( efi, phys_to_user ) ( unsigned long phys_addr ) {
+ return phys_addr;
+}
+
+/**
+ * Convert user buffer to physical address
+ *
+ * @v userptr User pointer
+ * @v offset Offset from user pointer
+ * @ret phys_addr Physical address
+ */
+static inline __always_inline unsigned long
+UACCESS_INLINE ( efi, user_to_phys ) ( userptr_t userptr, off_t offset ) {
+ return ( userptr + offset );
+}
+
+static inline __always_inline userptr_t
+UACCESS_INLINE ( efi, virt_to_user ) ( volatile const void *addr ) {
+ return trivial_virt_to_user ( addr );
+}
+
+static inline __always_inline void *
+UACCESS_INLINE ( efi, user_to_virt ) ( userptr_t userptr, off_t offset ) {
+ return trivial_user_to_virt ( userptr, offset );
+}
+
+static inline __always_inline userptr_t
+UACCESS_INLINE ( efi, userptr_add ) ( userptr_t userptr, off_t offset ) {
+ return trivial_userptr_add ( userptr, offset );
+}
+
+static inline __always_inline void
+UACCESS_INLINE ( efi, memcpy_user ) ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off,
+ size_t len ) {
+ trivial_memcpy_user ( dest, dest_off, src, src_off, len );
+}
+
+static inline __always_inline void
+UACCESS_INLINE ( efi, memmove_user ) ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off,
+ size_t len ) {
+ trivial_memmove_user ( dest, dest_off, src, src_off, len );
+}
+
+static inline __always_inline void
+UACCESS_INLINE ( efi, memset_user ) ( userptr_t buffer, off_t offset,
+ int c, size_t len ) {
+ trivial_memset_user ( buffer, offset, c, len );
+}
+
+static inline __always_inline size_t
+UACCESS_INLINE ( efi, strlen_user ) ( userptr_t buffer, off_t offset ) {
+ return trivial_strlen_user ( buffer, offset );
+}
+
+static inline __always_inline off_t
+UACCESS_INLINE ( efi, memchr_user ) ( userptr_t buffer, off_t offset,
+ int c, size_t len ) {
+ return trivial_memchr_user ( buffer, offset, c, len );
+}
+
+#endif /* _IPXE_EFI_UACCESS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_umalloc.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_umalloc.h
new file mode 100644
index 00000000..911e69a9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/efi_umalloc.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_EFI_UMALLOC_H
+#define _IPXE_EFI_UMALLOC_H
+
+/** @file
+ *
+ * iPXE user memory allocation API for EFI
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef UMALLOC_EFI
+#define UMALLOC_PREFIX_efi
+#else
+#define UMALLOC_PREFIX_efi __efi_
+#endif
+
+#endif /* _IPXE_EFI_UMALLOC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/import.pl b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/import.pl
new file mode 100755
index 00000000..2b5d3e93
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/import.pl
@@ -0,0 +1,135 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+import.pl
+
+=head1 SYNOPSIS
+
+import.pl [options] /path/to/edk2/edk2
+
+Options:
+
+ -h,--help Display brief help message
+ -v,--verbose Increase verbosity
+ -q,--quiet Decrease verbosity
+
+=cut
+
+use File::Spec::Functions qw ( :ALL );
+use File::Find;
+use File::Path;
+use Getopt::Long;
+use Pod::Usage;
+use FindBin;
+use strict;
+use warnings;
+
+my $verbosity = 0;
+
+sub try_import_file {
+ my $ipxedir = shift;
+ my $edktop = shift;
+ my $edkdirs = shift;
+ my $filename = shift;
+
+ # Skip everything except headers
+ return unless $filename =~ /\.h$/;
+
+ # Skip files that are iPXE native headers
+ my $outfile = catfile ( $ipxedir, $filename );
+ if ( -s $outfile ) {
+ open my $outfh, "<$outfile" or die "Could not open $outfile: $!\n";
+ my $line = <$outfh>;
+ close $outfh;
+ chomp $line;
+ return if $line =~ /^\#ifndef\s+_IPXE_\S+_H$/;
+ }
+
+ # Search for importable header
+ foreach my $edkdir ( @$edkdirs ) {
+ my $infile = catfile ( $edktop, $edkdir, $filename );
+ if ( -e $infile ) {
+ # We have found a matching source file - import it
+ print "$filename <- ".catfile ( $edkdir, $filename )."\n"
+ if $verbosity >= 1;
+ open my $infh, "<$infile" or die "Could not open $infile: $!\n";
+ ( undef, my $outdir, undef ) = splitpath ( $outfile );
+ mkpath ( $outdir );
+ open my $outfh, ">$outfile" or die "Could not open $outfile: $!\n";
+ my @dependencies = ();
+ my $licence;
+ my $guard;
+ while ( <$infh> ) {
+ # Strip CR and trailing whitespace
+ s/\r//g;
+ s/\s*$//g;
+ chomp;
+ # Update include lines, and record included files
+ if ( s/^\#include\s+[<\"](\S+)[>\"]/\#include <ipxe\/efi\/$1>/ ) {
+ push @dependencies, $1;
+ }
+ # Check for BSD licence statement
+ if ( /^\s*THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE/ ) {
+ die "Licence detected after header guard\n" if $guard;
+ $licence = "BSD3";
+ }
+ # Write out line
+ print $outfh "$_\n";
+ # Apply FILE_LICENCE() immediately after include guard
+ if ( /^\#define\s+_?_\S+_H_?_$/ ) {
+ die "Duplicate header guard detected in $infile\n" if $guard;
+ $guard = 1;
+ print $outfh "\nFILE_LICENCE ( $licence );\n" if $licence;
+ }
+ }
+ close $outfh;
+ close $infh;
+ # Warn if no licence was detected
+ warn "Cannot detect licence in $infile\n" unless $licence;
+ warn "Cannot detect header guard in $infile\n" unless $guard;
+ # Recurse to handle any included files that we don't already have
+ foreach my $dependency ( @dependencies ) {
+ if ( ! -e catfile ( $ipxedir, $dependency ) ) {
+ print "...following dependency on $dependency\n" if $verbosity >= 1;
+ try_import_file ( $ipxedir, $edktop, $edkdirs, $dependency );
+ }
+ }
+ return;
+ }
+ }
+ die "$filename has no equivalent in $edktop\n";
+}
+
+# Parse command-line options
+Getopt::Long::Configure ( 'bundling', 'auto_abbrev' );
+GetOptions (
+ 'verbose|v+' => sub { $verbosity++; },
+ 'quiet|q+' => sub { $verbosity--; },
+ 'help|h' => sub { pod2usage ( 1 ); },
+) or die "Could not parse command-line options\n";
+pod2usage ( 1 ) unless @ARGV == 1;
+my $edktop = shift;
+
+# Identify edk import directories
+my $edkdirs = [ "MdePkg/Include", "IntelFrameworkPkg/Include",
+ "MdeModulePkg/Include" ];
+foreach my $edkdir ( @$edkdirs ) {
+ die "Directory \"$edktop\" does not appear to contain the EFI EDK2 "
+ ."(missing \"$edkdir\")\n" unless -d catdir ( $edktop, $edkdir );
+}
+
+# Identify iPXE EFI includes directory
+my $ipxedir = $FindBin::Bin;
+die "Directory \"$ipxedir\" does not appear to contain the iPXE EFI includes\n"
+ unless -e catfile ( $ipxedir, "../../../include/ipxe/efi" );
+
+if ( $verbosity >= 1 ) {
+ print "Importing EFI headers into $ipxedir\nfrom ";
+ print join ( "\n and ", map { catdir ( $edktop, $_ ) } @$edkdirs )."\n";
+}
+
+# Import headers
+find ( { wanted => sub {
+ try_import_file ( $ipxedir, $edktop, $edkdirs, abs2rel ( $_, $ipxedir ) );
+}, no_chdir => 1 }, $ipxedir );
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/ipxe_download.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/ipxe_download.h
new file mode 100644
index 00000000..282d1eed
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/efi/ipxe_download.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010 VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef IPXE_DOWNLOAD_H
+#define IPXE_DOWNLOAD_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * iPXE Download Protocol
+ *
+ * EFI applications started by iPXE may use this interface to download files.
+ */
+
+typedef struct _IPXE_DOWNLOAD_PROTOCOL IPXE_DOWNLOAD_PROTOCOL;
+
+/** Token to represent a currently downloading file */
+typedef VOID *IPXE_DOWNLOAD_FILE;
+
+/**
+ * Callback function that is invoked when data arrives for a particular file.
+ *
+ * Not all protocols will deliver data in order. Clients should not rely on the
+ * order of data delivery matching the order in the file.
+ *
+ * Some protocols are capable of determining the file size near the beginning
+ * of data transfer. To allow the client to allocate memory more efficiently,
+ * iPXE may give a hint about the file size by calling the Data callback with
+ * a zero BufferLength and the file size in FileOffset. Clients should be
+ * prepared to deal with more or less data than the hint actually arriving.
+ *
+ * @v Context Context provided to the Start function
+ * @v Buffer New data
+ * @v BufferLength Length of new data in bytes
+ * @v FileOffset Offset of new data in the file
+ * @ret Status EFI_SUCCESS to continue the download,
+ * or any error code to abort.
+ */
+typedef
+EFI_STATUS
+(EFIAPI *IPXE_DOWNLOAD_DATA_CALLBACK)(
+ IN VOID *Context,
+ IN VOID *Buffer,
+ IN UINTN BufferLength,
+ IN UINTN FileOffset
+ );
+
+/**
+ * Callback function that is invoked when the file is finished downloading, or
+ * when a connection unexpectedly closes or times out.
+ *
+ * The finish callback is also called when a download is aborted by the Abort
+ * function (below).
+ *
+ * @v Context Context provided to the Start function
+ * @v Status Reason for termination: EFI_SUCCESS when the entire
+ * file was transferred successfully, or an error
+ * otherwise
+ */
+typedef
+void
+(EFIAPI *IPXE_DOWNLOAD_FINISH_CALLBACK)(
+ IN VOID *Context,
+ IN EFI_STATUS Status
+ );
+
+/**
+ * Start downloading a file, and register callback functions to handle the
+ * download.
+ *
+ * @v This iPXE Download Protocol instance
+ * @v Url URL to download from
+ * @v DataCallback Callback that will be invoked when data arrives
+ * @v FinishCallback Callback that will be invoked when the download ends
+ * @v Context Context passed to the Data and Finish callbacks
+ * @v File Token that can be used to abort the download
+ * @ret Status EFI status code
+ */
+typedef
+EFI_STATUS
+(EFIAPI *IPXE_DOWNLOAD_START)(
+ IN IPXE_DOWNLOAD_PROTOCOL *This,
+ IN CHAR8 *Url,
+ IN IPXE_DOWNLOAD_DATA_CALLBACK DataCallback,
+ IN IPXE_DOWNLOAD_FINISH_CALLBACK FinishCallback,
+ IN VOID *Context,
+ OUT IPXE_DOWNLOAD_FILE *File
+ );
+
+/**
+ * Forcibly abort downloading a file that is currently in progress.
+ *
+ * It is not safe to call this function after the Finish callback has executed.
+ *
+ * @v This iPXE Download Protocol instance
+ * @v File Token obtained from Start
+ * @v Status Reason for aborting the download
+ * @ret Status EFI status code
+ */
+typedef
+EFI_STATUS
+(EFIAPI *IPXE_DOWNLOAD_ABORT)(
+ IN IPXE_DOWNLOAD_PROTOCOL *This,
+ IN IPXE_DOWNLOAD_FILE File,
+ IN EFI_STATUS Status
+ );
+
+/**
+ * Poll for more data from iPXE. This function will invoke the registered
+ * callbacks if data is available or if downloads complete.
+ *
+ * @v This iPXE Download Protocol instance
+ * @ret Status EFI status code
+ */
+typedef
+EFI_STATUS
+(EFIAPI *IPXE_DOWNLOAD_POLL)(
+ IN IPXE_DOWNLOAD_PROTOCOL *This
+ );
+
+/**
+ * The iPXE Download Protocol.
+ *
+ * iPXE will attach a iPXE Download Protocol to the DeviceHandle in the Loaded
+ * Image Protocol of all child EFI applications.
+ */
+struct _IPXE_DOWNLOAD_PROTOCOL {
+ IPXE_DOWNLOAD_START Start;
+ IPXE_DOWNLOAD_ABORT Abort;
+ IPXE_DOWNLOAD_POLL Poll;
+};
+
+#define IPXE_DOWNLOAD_PROTOCOL_GUID \
+ { \
+ 0x3eaeaebd, 0xdecf, 0x493b, { 0x9b, 0xd1, 0xcd, 0xb2, 0xde, 0xca, 0xe7, 0x19 } \
+ }
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/eisa.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/eisa.h
new file mode 100644
index 00000000..22a1ed94
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/eisa.h
@@ -0,0 +1,128 @@
+#ifndef EISA_H
+#define EISA_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/isa_ids.h>
+#include <ipxe/device.h>
+#include <ipxe/tables.h>
+
+/*
+ * EISA constants
+ *
+ */
+
+#define EISA_MIN_SLOT (0x1)
+#define EISA_MAX_SLOT (0xf) /* Must be 2^n - 1 */
+#define EISA_SLOT_BASE( n ) ( 0x1000 * (n) )
+
+#define EISA_VENDOR_ID ( 0xc80 )
+#define EISA_PROD_ID ( 0xc82 )
+#define EISA_GLOBAL_CONFIG ( 0xc84 )
+
+#define EISA_CMD_RESET ( 1 << 2 )
+#define EISA_CMD_ENABLE ( 1 << 0 )
+
+/** An EISA device ID list entry */
+struct eisa_device_id {
+ /** Name */
+ const char *name;
+ /** Manufacturer ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+};
+
+/** An EISA device */
+struct eisa_device {
+ /** Generic device */
+ struct device dev;
+ /** Slot number */
+ unsigned int slot;
+ /** I/O address */
+ uint16_t ioaddr;
+ /** Manufacturer ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+ /** Driver for this device */
+ struct eisa_driver *driver;
+ /** Driver-private data
+ *
+ * Use eisa_set_drvdata() and eisa_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+};
+
+/** An EISA driver */
+struct eisa_driver {
+ /** EISA ID table */
+ struct eisa_device_id *ids;
+ /** Number of entries in EISA ID table */
+ unsigned int id_count;
+ /**
+ * Probe device
+ *
+ * @v eisa EISA device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct eisa_device *eisa,
+ const struct eisa_device_id *id );
+ /**
+ * Remove device
+ *
+ * @v eisa EISA device
+ */
+ void ( * remove ) ( struct eisa_device *eisa );
+};
+
+/** EISA driver table */
+#define EISA_DRIVERS __table ( struct eisa_driver, "eisa_drivers" )
+
+/** Declare an EISA driver */
+#define __eisa_driver __table_entry ( EISA_DRIVERS, 01 )
+
+extern void eisa_device_enabled ( struct eisa_device *eisa, int enabled );
+
+/**
+ * Enable EISA device
+ *
+ * @v eisa EISA device
+ */
+static inline void enable_eisa_device ( struct eisa_device *eisa ) {
+ eisa_device_enabled ( eisa, 1 );
+}
+
+/**
+ * Disable EISA device
+ *
+ * @v eisa EISA device
+ */
+static inline void disable_eisa_device ( struct eisa_device *eisa ) {
+ eisa_device_enabled ( eisa, 0 );
+}
+
+/**
+ * Set EISA driver-private data
+ *
+ * @v eisa EISA device
+ * @v priv Private data
+ */
+static inline void eisa_set_drvdata ( struct eisa_device *eisa, void *priv ) {
+ eisa->priv = priv;
+}
+
+/**
+ * Get EISA driver-private data
+ *
+ * @v eisa EISA device
+ * @ret priv Private data
+ */
+static inline void * eisa_get_drvdata ( struct eisa_device *eisa ) {
+ return eisa->priv;
+}
+
+#endif /* EISA_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/elf.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/elf.h
new file mode 100644
index 00000000..ec675c04
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/elf.h
@@ -0,0 +1,17 @@
+#ifndef _IPXE_ELF_H
+#define _IPXE_ELF_H
+
+/**
+ * @file
+ *
+ * ELF image format
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <elf.h>
+
+extern int elf_load ( struct image *image, physaddr_t *entry, physaddr_t *max );
+
+#endif /* _IPXE_ELF_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/entropy.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/entropy.h
new file mode 100644
index 00000000..adf325e7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/entropy.h
@@ -0,0 +1,224 @@
+#ifndef _IPXE_ENTROPY_H
+#define _IPXE_ENTROPY_H
+
+/** @file
+ *
+ * Entropy source
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <ipxe/api.h>
+#include <ipxe/hash_df.h>
+#include <ipxe/sha256.h>
+#include <config/entropy.h>
+
+/**
+ * Calculate static inline entropy API function name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ */
+#define ENTROPY_INLINE( _subsys, _api_func ) \
+ SINGLE_API_INLINE ( ENTROPY_PREFIX_ ## _subsys, _api_func )
+
+/**
+ * Provide a entropy API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_ENTROPY( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( ENTROPY_PREFIX_ ## _subsys, _api_func, _func )
+
+/**
+ * Provide a static inline entropy API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ */
+#define PROVIDE_ENTROPY_INLINE( _subsys, _api_func ) \
+ PROVIDE_SINGLE_API_INLINE ( ENTROPY_PREFIX_ ## _subsys, _api_func )
+
+/** A noise sample */
+typedef uint8_t noise_sample_t;
+
+/** An entropy sample */
+typedef uint8_t entropy_sample_t;
+
+/* Include all architecture-independent entropy API headers */
+#include <ipxe/null_entropy.h>
+#include <ipxe/linux/linux_entropy.h>
+
+/* Include all architecture-dependent entropy API headers */
+#include <bits/entropy.h>
+
+/**
+ * Enable entropy gathering
+ *
+ * @ret rc Return status code
+ */
+int entropy_enable ( void );
+
+/**
+ * Disable entropy gathering
+ *
+ */
+void entropy_disable ( void );
+
+/**
+ * min-entropy per sample
+ *
+ * @ret min_entropy min-entropy of each sample
+ *
+ * min-entropy is defined in ANS X9.82 Part 1-2006 Section 8.3 and in
+ * NIST SP 800-90 Appendix C.3 as
+ *
+ * H_min = -log2 ( p_max )
+ *
+ * where p_max is the probability of the most likely sample value.
+ *
+ * This must be a compile-time constant.
+ */
+double min_entropy_per_sample ( void );
+
+/**
+ * Get noise sample
+ *
+ * @ret noise Noise sample
+ * @ret rc Return status code
+ *
+ * This is the GetNoise function defined in ANS X9.82 Part 2
+ * (October 2011 Draft) Section 6.5.2.
+ */
+int get_noise ( noise_sample_t *noise );
+
+extern int get_entropy_input_tmp ( unsigned int num_samples,
+ uint8_t *tmp, size_t tmp_len );
+
+/** Use SHA-256 as the underlying hash algorithm for Hash_df
+ *
+ * Hash_df using SHA-256 is an Approved algorithm in ANS X9.82.
+ */
+#define entropy_hash_df_algorithm sha256_algorithm
+
+/** Underlying hash algorithm output length (in bytes) */
+#define ENTROPY_HASH_DF_OUTLEN_BYTES SHA256_DIGEST_SIZE
+
+/**
+ * Obtain entropy input
+ *
+ * @v min_entropy_bits Minimum amount of entropy, in bits
+ * @v data Data buffer
+ * @v min_len Minimum length of entropy input, in bytes
+ * @v max_len Maximum length of entropy input, in bytes
+ * @ret len Length of entropy input, in bytes, or negative error
+ *
+ * This is the implementation of the Get_entropy_input function (using
+ * an entropy source as the source of entropy input and condensing
+ * each entropy source output after each GetEntropy call) as defined
+ * in ANS X9.82 Part 4 (April 2011 Draft) Section 13.3.4.2.
+ *
+ * To minimise code size, the number of samples required is calculated
+ * at compilation time.
+ */
+static inline __attribute__ (( always_inline )) int
+get_entropy_input ( unsigned int min_entropy_bits, void *data, size_t min_len,
+ size_t max_len ) {
+ size_t tmp_len = ( ( ( min_entropy_bits * 2 ) + 7 ) / 8 );
+ uint8_t tmp_buf[ tmp_len ];
+ uint8_t *tmp = ( ( tmp_len > max_len ) ? tmp_buf : data );
+ double min_samples;
+ unsigned int num_samples;
+ unsigned int n;
+ int rc;
+
+ /* Sanity checks */
+ linker_assert ( ( min_entropy_per_sample() <=
+ ( 8 * sizeof ( noise_sample_t ) ) ),
+ min_entropy_per_sample_is_impossibly_high );
+ linker_assert ( ( min_entropy_bits <= ( 8 * max_len ) ),
+ entropy_buffer_too_small );
+
+ /* Round up minimum entropy to an integral number of bytes */
+ min_entropy_bits = ( ( min_entropy_bits + 7 ) & ~7 );
+
+ /* Calculate number of samples required to contain sufficient entropy */
+ min_samples = ( ( min_entropy_bits * 1.0 ) / min_entropy_per_sample() );
+
+ /* Round up to a whole number of samples. We don't have the
+ * ceil() function available, so do the rounding by hand.
+ */
+ num_samples = min_samples;
+ if ( num_samples < min_samples )
+ num_samples++;
+ linker_assert ( ( num_samples >= min_samples ), rounding_error );
+
+ /* Floating-point operations are not allowed in iPXE since we
+ * never set up a suitable environment. Abort the build
+ * unless the calculated number of samples is a compile-time
+ * constant.
+ */
+ linker_assert ( __builtin_constant_p ( num_samples ),
+ num_samples_not_constant );
+
+ /* (Unnumbered). The output length of the hash function shall
+ * meet or exceed the security strength indicated by the
+ * min_entropy parameter.
+ */
+ linker_assert ( ( ( 8 * ENTROPY_HASH_DF_OUTLEN_BYTES ) >=
+ min_entropy_bits ), hash_df_algorithm_too_weak );
+
+ /* 1. If ( min_length > max_length ), then return ( FAILURE, Null ) */
+ linker_assert ( ( min_len <= max_len ), min_len_greater_than_max_len );
+
+ /* 2. n = 2 * min_entropy */
+ n = ( 2 * min_entropy_bits );
+
+ /* 3. entropy_total = 0
+ * 4. tmp = a fixed n-bit value, such as 0^n
+ * 5. While ( entropy_total < min_entropy )
+ * 5.1. ( status, entropy_bitstring, assessed_entropy )
+ * = GetEntropy()
+ * 5.2. If status indicates an error, return ( status, Null )
+ * 5.3. nonce = MakeNextNonce()
+ * 5.4. tmp = tmp XOR df ( ( nonce || entropy_bitstring ), n )
+ * 5.5. entropy_total = entropy_total + assessed_entropy
+ *
+ * (The implementation of these steps is inside the function
+ * get_entropy_input_tmp().)
+ */
+ linker_assert ( __builtin_constant_p ( tmp_len ),
+ tmp_len_not_constant );
+ linker_assert ( ( n == ( 8 * tmp_len ) ), tmp_len_mismatch );
+ if ( ( rc = get_entropy_input_tmp ( num_samples, tmp, tmp_len ) ) != 0 )
+ return rc;
+
+ /* 6. If ( n < min_length ), then tmp = tmp || 0^(min_length-n)
+ * 7. If ( n > max_length ), then tmp = df ( tmp, max_length )
+ * 8. Return ( SUCCESS, tmp )
+ */
+ if ( tmp_len < min_len ) {
+ /* (Data is already in-place.) */
+ linker_assert ( ( data == tmp ), data_not_inplace );
+ memset ( ( data + tmp_len ), 0, ( min_len - tmp_len ) );
+ return min_len;
+ } else if ( tmp_len > max_len ) {
+ linker_assert ( ( tmp == tmp_buf ), data_inplace );
+ hash_df ( &entropy_hash_df_algorithm, tmp, tmp_len,
+ data, max_len );
+ return max_len;
+ } else {
+ /* (Data is already in-place.) */
+ linker_assert ( ( data == tmp ), data_not_inplace );
+ return tmp_len;
+ }
+}
+
+#endif /* _IPXE_ENTROPY_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/errfile.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/errfile.h
new file mode 100644
index 00000000..108efc7a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/errfile.h
@@ -0,0 +1,267 @@
+#ifndef _IPXE_ERRFILE_H
+#define _IPXE_ERRFILE_H
+
+/** @file
+ *
+ * Error file identifiers
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <bits/errfile.h>
+
+/**
+ * @defgroup errfilecat Error file identifier categories
+ *
+ * @{
+ */
+
+#define ERRFILE_CORE 0x00002000 /**< Core code */
+#define ERRFILE_DRIVER 0x00004000 /**< Driver code */
+#define ERRFILE_NET 0x00006000 /**< Networking code */
+#define ERRFILE_IMAGE 0x00008000 /**< Image code */
+#define ERRFILE_OTHER 0x0000e000 /**< Any other code */
+
+/** @} */
+
+/** Flag for architecture-dependent error files */
+#define ERRFILE_ARCH 0x00800000
+
+/**
+ * @defgroup errfile Error file identifiers
+ *
+ * These values are automatically incorporated into the definitions
+ * for error numbers such as EINVAL.
+ *
+ * @{
+ */
+
+#define ERRFILE_asprintf ( ERRFILE_CORE | 0x00000000 )
+#define ERRFILE_downloader ( ERRFILE_CORE | 0x00010000 )
+#define ERRFILE_exec ( ERRFILE_CORE | 0x00020000 )
+#define ERRFILE_hw ( ERRFILE_CORE | 0x00030000 )
+#define ERRFILE_iobuf ( ERRFILE_CORE | 0x00040000 )
+#define ERRFILE_job ( ERRFILE_CORE | 0x00050000 )
+#define ERRFILE_linebuf ( ERRFILE_CORE | 0x00060000 )
+#define ERRFILE_monojob ( ERRFILE_CORE | 0x00070000 )
+#define ERRFILE_nvo ( ERRFILE_CORE | 0x00080000 )
+#define ERRFILE_open ( ERRFILE_CORE | 0x00090000 )
+#define ERRFILE_posix_io ( ERRFILE_CORE | 0x000a0000 )
+#define ERRFILE_resolv ( ERRFILE_CORE | 0x000b0000 )
+#define ERRFILE_settings ( ERRFILE_CORE | 0x000c0000 )
+#define ERRFILE_vsprintf ( ERRFILE_CORE | 0x000d0000 )
+#define ERRFILE_xfer ( ERRFILE_CORE | 0x000e0000 )
+#define ERRFILE_bitmap ( ERRFILE_CORE | 0x000f0000 )
+#define ERRFILE_base64 ( ERRFILE_CORE | 0x00100000 )
+#define ERRFILE_base16 ( ERRFILE_CORE | 0x00110000 )
+#define ERRFILE_blockdev ( ERRFILE_CORE | 0x00120000 )
+#define ERRFILE_acpi ( ERRFILE_CORE | 0x00130000 )
+#define ERRFILE_null_sanboot ( ERRFILE_CORE | 0x00140000 )
+#define ERRFILE_edd ( ERRFILE_CORE | 0x00150000 )
+#define ERRFILE_parseopt ( ERRFILE_CORE | 0x00160000 )
+#define ERRFILE_test ( ERRFILE_CORE | 0x00170000 )
+#define ERRFILE_xferbuf ( ERRFILE_CORE | 0x00180000 )
+
+#define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 )
+#define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 )
+#define ERRFILE_isapnp ( ERRFILE_DRIVER | 0x00020000 )
+#define ERRFILE_mca ( ERRFILE_DRIVER | 0x00030000 )
+#define ERRFILE_pci ( ERRFILE_DRIVER | 0x00040000 )
+#define ERRFILE_linux ( ERRFILE_DRIVER | 0x00050000 )
+#define ERRFILE_pcivpd ( ERRFILE_DRIVER | 0x00060000 )
+
+#define ERRFILE_nvs ( ERRFILE_DRIVER | 0x00100000 )
+#define ERRFILE_spi ( ERRFILE_DRIVER | 0x00110000 )
+#define ERRFILE_i2c_bit ( ERRFILE_DRIVER | 0x00120000 )
+#define ERRFILE_spi_bit ( ERRFILE_DRIVER | 0x00130000 )
+#define ERRFILE_nvsvpd ( ERRFILE_DRIVER | 0x00140000 )
+
+#define ERRFILE_3c509 ( ERRFILE_DRIVER | 0x00200000 )
+#define ERRFILE_bnx2 ( ERRFILE_DRIVER | 0x00210000 )
+#define ERRFILE_cs89x0 ( ERRFILE_DRIVER | 0x00220000 )
+#define ERRFILE_eepro ( ERRFILE_DRIVER | 0x00230000 )
+#define ERRFILE_etherfabric ( ERRFILE_DRIVER | 0x00240000 )
+#define ERRFILE_legacy ( ERRFILE_DRIVER | 0x00250000 )
+#define ERRFILE_natsemi ( ERRFILE_DRIVER | 0x00260000 )
+#define ERRFILE_pnic ( ERRFILE_DRIVER | 0x00270000 )
+#define ERRFILE_prism2_pci ( ERRFILE_DRIVER | 0x00280000 )
+#define ERRFILE_prism2_plx ( ERRFILE_DRIVER | 0x00290000 )
+#define ERRFILE_rtl8139 ( ERRFILE_DRIVER | 0x002a0000 )
+#define ERRFILE_smc9000 ( ERRFILE_DRIVER | 0x002b0000 )
+#define ERRFILE_tg3 ( ERRFILE_DRIVER | 0x002c0000 )
+#define ERRFILE_3c509_eisa ( ERRFILE_DRIVER | 0x002d0000 )
+#define ERRFILE_3c515 ( ERRFILE_DRIVER | 0x002e0000 )
+#define ERRFILE_3c529 ( ERRFILE_DRIVER | 0x002f0000 )
+#define ERRFILE_3c595 ( ERRFILE_DRIVER | 0x00300000 )
+#define ERRFILE_3c5x9 ( ERRFILE_DRIVER | 0x00310000 )
+#define ERRFILE_3c90x ( ERRFILE_DRIVER | 0x00320000 )
+#define ERRFILE_amd8111e ( ERRFILE_DRIVER | 0x00330000 )
+#define ERRFILE_davicom ( ERRFILE_DRIVER | 0x00340000 )
+#define ERRFILE_depca ( ERRFILE_DRIVER | 0x00350000 )
+#define ERRFILE_dmfe ( ERRFILE_DRIVER | 0x00360000 )
+#define ERRFILE_eepro100 ( ERRFILE_DRIVER | 0x00380000 )
+#define ERRFILE_epic100 ( ERRFILE_DRIVER | 0x00390000 )
+#define ERRFILE_forcedeth ( ERRFILE_DRIVER | 0x003a0000 )
+#define ERRFILE_mtd80x ( ERRFILE_DRIVER | 0x003b0000 )
+#define ERRFILE_ns83820 ( ERRFILE_DRIVER | 0x003c0000 )
+#define ERRFILE_ns8390 ( ERRFILE_DRIVER | 0x003d0000 )
+#define ERRFILE_pcnet32 ( ERRFILE_DRIVER | 0x003e0000 )
+#define ERRFILE_r8169 ( ERRFILE_DRIVER | 0x003f0000 )
+#define ERRFILE_sis900 ( ERRFILE_DRIVER | 0x00400000 )
+#define ERRFILE_sundance ( ERRFILE_DRIVER | 0x00410000 )
+#define ERRFILE_tlan ( ERRFILE_DRIVER | 0x00420000 )
+#define ERRFILE_tulip ( ERRFILE_DRIVER | 0x00430000 )
+#define ERRFILE_via_rhine ( ERRFILE_DRIVER | 0x00440000 )
+#define ERRFILE_via_velocity ( ERRFILE_DRIVER | 0x00450000 )
+#define ERRFILE_w89c840 ( ERRFILE_DRIVER | 0x00460000 )
+#define ERRFILE_ipoib ( ERRFILE_DRIVER | 0x00470000 )
+#define ERRFILE_e1000_main ( ERRFILE_DRIVER | 0x00480000 )
+#define ERRFILE_e1000e_main ( ERRFILE_DRIVER | 0x00490000 )
+#define ERRFILE_mtnic ( ERRFILE_DRIVER | 0x004a0000 )
+#define ERRFILE_phantom ( ERRFILE_DRIVER | 0x004b0000 )
+#define ERRFILE_ne2k_isa ( ERRFILE_DRIVER | 0x004c0000 )
+#define ERRFILE_b44 ( ERRFILE_DRIVER | 0x004d0000 )
+#define ERRFILE_rtl818x ( ERRFILE_DRIVER | 0x004e0000 )
+#define ERRFILE_sky2 ( ERRFILE_DRIVER | 0x004f0000 )
+#define ERRFILE_ath5k ( ERRFILE_DRIVER | 0x00500000 )
+#define ERRFILE_atl1e ( ERRFILE_DRIVER | 0x00510000 )
+#define ERRFILE_sis190 ( ERRFILE_DRIVER | 0x00520000 )
+#define ERRFILE_myri10ge ( ERRFILE_DRIVER | 0x00530000 )
+#define ERRFILE_skge ( ERRFILE_DRIVER | 0x00540000 )
+#define ERRFILE_vxge_main ( ERRFILE_DRIVER | 0x00550000 )
+#define ERRFILE_vxge_config ( ERRFILE_DRIVER | 0x00560000 )
+#define ERRFILE_vxge_traffic ( ERRFILE_DRIVER | 0x00570000 )
+#define ERRFILE_igb_main ( ERRFILE_DRIVER | 0x00580000 )
+#define ERRFILE_snpnet ( ERRFILE_DRIVER | 0x00590000 )
+#define ERRFILE_snponly ( ERRFILE_DRIVER | 0x005a0000 )
+#define ERRFILE_jme ( ERRFILE_DRIVER | 0x005b0000 )
+#define ERRFILE_virtio_net ( ERRFILE_DRIVER | 0x005c0000 )
+#define ERRFILE_tap ( ERRFILE_DRIVER | 0x005d0000 )
+#define ERRFILE_igbvf_main ( ERRFILE_DRIVER | 0x005e0000 )
+#define ERRFILE_ath9k ( ERRFILE_DRIVER | 0x005f0000 )
+#define ERRFILE_ath ( ERRFILE_DRIVER | 0x00600000 )
+#define ERRFILE_vmxnet3 ( ERRFILE_DRIVER | 0x00610000 )
+#define ERRFILE_mii ( ERRFILE_DRIVER | 0x00620000 )
+#define ERRFILE_realtek ( ERRFILE_DRIVER | 0x00630000 )
+#define ERRFILE_skeleton ( ERRFILE_DRIVER | 0x00640000 )
+#define ERRFILE_intel ( ERRFILE_DRIVER | 0x00650000 )
+#define ERRFILE_myson ( ERRFILE_DRIVER | 0x00660000 )
+
+#define ERRFILE_scsi ( ERRFILE_DRIVER | 0x00700000 )
+#define ERRFILE_arbel ( ERRFILE_DRIVER | 0x00710000 )
+#define ERRFILE_hermon ( ERRFILE_DRIVER | 0x00720000 )
+#define ERRFILE_linda ( ERRFILE_DRIVER | 0x00730000 )
+#define ERRFILE_ata ( ERRFILE_DRIVER | 0x00740000 )
+#define ERRFILE_srp ( ERRFILE_DRIVER | 0x00750000 )
+#define ERRFILE_qib7322 ( ERRFILE_DRIVER | 0x00760000 )
+
+#define ERRFILE_aoe ( ERRFILE_NET | 0x00000000 )
+#define ERRFILE_arp ( ERRFILE_NET | 0x00010000 )
+#define ERRFILE_dhcpopts ( ERRFILE_NET | 0x00020000 )
+#define ERRFILE_ethernet ( ERRFILE_NET | 0x00030000 )
+#define ERRFILE_icmpv6 ( ERRFILE_NET | 0x00040000 )
+#define ERRFILE_ipv4 ( ERRFILE_NET | 0x00050000 )
+#define ERRFILE_ipv6 ( ERRFILE_NET | 0x00060000 )
+#define ERRFILE_ndp ( ERRFILE_NET | 0x00070000 )
+#define ERRFILE_netdevice ( ERRFILE_NET | 0x00080000 )
+#define ERRFILE_nullnet ( ERRFILE_NET | 0x00090000 )
+#define ERRFILE_tcp ( ERRFILE_NET | 0x000a0000 )
+#define ERRFILE_ftp ( ERRFILE_NET | 0x000b0000 )
+#define ERRFILE_httpcore ( ERRFILE_NET | 0x000c0000 )
+#define ERRFILE_iscsi ( ERRFILE_NET | 0x000d0000 )
+#define ERRFILE_tcpip ( ERRFILE_NET | 0x000e0000 )
+#define ERRFILE_udp ( ERRFILE_NET | 0x000f0000 )
+#define ERRFILE_dhcp ( ERRFILE_NET | 0x00100000 )
+#define ERRFILE_dns ( ERRFILE_NET | 0x00110000 )
+#define ERRFILE_tftp ( ERRFILE_NET | 0x00120000 )
+#define ERRFILE_infiniband ( ERRFILE_NET | 0x00130000 )
+#define ERRFILE_netdev_settings ( ERRFILE_NET | 0x00140000 )
+#define ERRFILE_dhcppkt ( ERRFILE_NET | 0x00150000 )
+#define ERRFILE_slam ( ERRFILE_NET | 0x00160000 )
+#define ERRFILE_ib_sma ( ERRFILE_NET | 0x00170000 )
+#define ERRFILE_ib_packet ( ERRFILE_NET | 0x00180000 )
+#define ERRFILE_icmp ( ERRFILE_NET | 0x00190000 )
+#define ERRFILE_ib_qset ( ERRFILE_NET | 0x001a0000 )
+#define ERRFILE_ib_gma ( ERRFILE_NET | 0x001b0000 )
+#define ERRFILE_ib_pathrec ( ERRFILE_NET | 0x001c0000 )
+#define ERRFILE_ib_mcast ( ERRFILE_NET | 0x001d0000 )
+#define ERRFILE_ib_cm ( ERRFILE_NET | 0x001e0000 )
+#define ERRFILE_net80211 ( ERRFILE_NET | 0x001f0000 )
+#define ERRFILE_ib_mi ( ERRFILE_NET | 0x00200000 )
+#define ERRFILE_ib_cmrc ( ERRFILE_NET | 0x00210000 )
+#define ERRFILE_ib_srp ( ERRFILE_NET | 0x00220000 )
+#define ERRFILE_sec80211 ( ERRFILE_NET | 0x00230000 )
+#define ERRFILE_wep ( ERRFILE_NET | 0x00240000 )
+#define ERRFILE_eapol ( ERRFILE_NET | 0x00250000 )
+#define ERRFILE_wpa ( ERRFILE_NET | 0x00260000 )
+#define ERRFILE_wpa_psk ( ERRFILE_NET | 0x00270000 )
+#define ERRFILE_wpa_tkip ( ERRFILE_NET | 0x00280000 )
+#define ERRFILE_wpa_ccmp ( ERRFILE_NET | 0x00290000 )
+#define ERRFILE_eth_slow ( ERRFILE_NET | 0x002a0000 )
+#define ERRFILE_fc ( ERRFILE_NET | 0x002b0000 )
+#define ERRFILE_fcels ( ERRFILE_NET | 0x002c0000 )
+#define ERRFILE_fcp ( ERRFILE_NET | 0x002d0000 )
+#define ERRFILE_fcoe ( ERRFILE_NET | 0x002e0000 )
+#define ERRFILE_fcns ( ERRFILE_NET | 0x002f0000 )
+#define ERRFILE_vlan ( ERRFILE_NET | 0x00300000 )
+
+#define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 )
+#define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 )
+#define ERRFILE_script ( ERRFILE_IMAGE | 0x00020000 )
+#define ERRFILE_segment ( ERRFILE_IMAGE | 0x00030000 )
+#define ERRFILE_efi_image ( ERRFILE_IMAGE | 0x00040000 )
+#define ERRFILE_embedded ( ERRFILE_IMAGE | 0x00050000 )
+
+#define ERRFILE_asn1 ( ERRFILE_OTHER | 0x00000000 )
+#define ERRFILE_chap ( ERRFILE_OTHER | 0x00010000 )
+#define ERRFILE_aoeboot ( ERRFILE_OTHER | 0x00020000 )
+#define ERRFILE_autoboot ( ERRFILE_OTHER | 0x00030000 )
+#define ERRFILE_dhcpmgmt ( ERRFILE_OTHER | 0x00040000 )
+#define ERRFILE_imgmgmt ( ERRFILE_OTHER | 0x00050000 )
+#define ERRFILE_pxe_tftp ( ERRFILE_OTHER | 0x00060000 )
+#define ERRFILE_pxe_udp ( ERRFILE_OTHER | 0x00070000 )
+#define ERRFILE_axtls_aes ( ERRFILE_OTHER | 0x00080000 )
+#define ERRFILE_cipher ( ERRFILE_OTHER | 0x00090000 )
+#define ERRFILE_image_cmd ( ERRFILE_OTHER | 0x000a0000 )
+#define ERRFILE_uri_test ( ERRFILE_OTHER | 0x000b0000 )
+#define ERRFILE_ibft ( ERRFILE_OTHER | 0x000c0000 )
+#define ERRFILE_tls ( ERRFILE_OTHER | 0x000d0000 )
+#define ERRFILE_ifmgmt ( ERRFILE_OTHER | 0x000e0000 )
+#define ERRFILE_iscsiboot ( ERRFILE_OTHER | 0x000f0000 )
+#define ERRFILE_efi_pci ( ERRFILE_OTHER | 0x00100000 )
+#define ERRFILE_efi_snp ( ERRFILE_OTHER | 0x00110000 )
+#define ERRFILE_smbios ( ERRFILE_OTHER | 0x00120000 )
+#define ERRFILE_smbios_settings ( ERRFILE_OTHER | 0x00130000 )
+#define ERRFILE_efi_smbios ( ERRFILE_OTHER | 0x00140000 )
+#define ERRFILE_pxemenu ( ERRFILE_OTHER | 0x00150000 )
+#define ERRFILE_x509 ( ERRFILE_OTHER | 0x00160000 )
+#define ERRFILE_login_ui ( ERRFILE_OTHER | 0x00170000 )
+#define ERRFILE_ib_srpboot ( ERRFILE_OTHER | 0x00180000 )
+#define ERRFILE_iwmgmt ( ERRFILE_OTHER | 0x00190000 )
+#define ERRFILE_linux_smbios ( ERRFILE_OTHER | 0x001a0000 )
+#define ERRFILE_lotest ( ERRFILE_OTHER | 0x001b0000 )
+#define ERRFILE_config_cmd ( ERRFILE_OTHER | 0x001c0000 )
+#define ERRFILE_ifmgmt_cmd ( ERRFILE_OTHER | 0x001d0000 )
+#define ERRFILE_fcmgmt_cmd ( ERRFILE_OTHER | 0x001e0000 )
+#define ERRFILE_gdbstub_cmd ( ERRFILE_OTHER | 0x001f0000 )
+#define ERRFILE_sanboot_cmd ( ERRFILE_OTHER | 0x00200000 )
+#define ERRFILE_bofm ( ERRFILE_OTHER | 0x00210000 )
+#define ERRFILE_prompt ( ERRFILE_OTHER | 0x00220000 )
+#define ERRFILE_nvo_cmd ( ERRFILE_OTHER | 0x00230000 )
+#define ERRFILE_hmac_drbg ( ERRFILE_OTHER | 0x00240000 )
+#define ERRFILE_drbg ( ERRFILE_OTHER | 0x00250000 )
+#define ERRFILE_entropy ( ERRFILE_OTHER | 0x00260000 )
+#define ERRFILE_rsa ( ERRFILE_OTHER | 0x00270000 )
+#define ERRFILE_linux_entropy ( ERRFILE_OTHER | 0x00280000 )
+#define ERRFILE_x509_test ( ERRFILE_OTHER | 0x00290000 )
+#define ERRFILE_cms ( ERRFILE_OTHER | 0x002a0000 )
+#define ERRFILE_imgtrust ( ERRFILE_OTHER | 0x002b0000 )
+#define ERRFILE_menu_ui ( ERRFILE_OTHER | 0x002c0000 )
+#define ERRFILE_menu_cmd ( ERRFILE_OTHER | 0x002d0000 )
+#define ERRFILE_validator ( ERRFILE_OTHER | 0x002e0000 )
+#define ERRFILE_ocsp ( ERRFILE_OTHER | 0x002f0000 )
+
+/** @} */
+
+#endif /* _IPXE_ERRFILE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/errortab.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/errortab.h
new file mode 100644
index 00000000..a2f6a70f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/errortab.h
@@ -0,0 +1,28 @@
+#ifndef _IPXE_ERRORTAB_H
+#define _IPXE_ERRORTAB_H
+
+/** @file
+ *
+ * Error message tables
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/tables.h>
+
+struct errortab {
+ int errno;
+ const char *text;
+};
+
+#define ERRORTAB __table ( struct errortab, "errortab" )
+
+#define __errortab __table_entry ( ERRORTAB, 01 )
+
+#define __einfo_errortab( einfo ) { \
+ .errno = __einfo_errno ( einfo ), \
+ .text = __einfo_desc ( einfo ), \
+ }
+
+#endif /* _IPXE_ERRORTAB_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/eth_slow.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/eth_slow.h
new file mode 100644
index 00000000..00509197
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/eth_slow.h
@@ -0,0 +1,255 @@
+#ifndef _IPXE_ETH_SLOW_H
+#define _IPXE_ETH_SLOW_H
+
+/** @file
+ *
+ * Ethernet slow protocols
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** Slow protocols header */
+struct eth_slow_header {
+ /** Slow protocols subtype */
+ uint8_t subtype;
+ /** Subtype version number */
+ uint8_t version;
+} __attribute__ (( packed ));
+
+/** LACP subtype */
+#define ETH_SLOW_SUBTYPE_LACP 1
+
+/** LACP version number */
+#define ETH_SLOW_LACP_VERSION 1
+
+/** Marker subtype */
+#define ETH_SLOW_SUBTYPE_MARKER 2
+
+/** Marker version number */
+#define ETH_SLOW_MARKER_VERSION 1
+
+/** TLV (type, length, value) header */
+struct eth_slow_tlv_header {
+ /** Type
+ *
+ * This is an ETH_SLOW_TLV_XXX constant.
+ */
+ uint8_t type;
+ /** Length
+ *
+ * The length includes the TLV header (except for a TLV
+ * terminator, which has a length of zero).
+ */
+ uint8_t length;
+} __attribute__ (( packed ));
+
+/** Terminator type */
+#define ETH_SLOW_TLV_TERMINATOR 0
+
+/** Terminator length */
+#define ETH_SLOW_TLV_TERMINATOR_LEN 0
+
+/** LACP actor type */
+#define ETH_SLOW_TLV_LACP_ACTOR 1
+
+/** LACP actor length */
+#define ETH_SLOW_TLV_LACP_ACTOR_LEN \
+ ( sizeof ( struct eth_slow_lacp_entity_tlv ) )
+
+/** LACP partner type */
+#define ETH_SLOW_TLV_LACP_PARTNER 2
+
+/** LACP partner length */
+#define ETH_SLOW_TLV_LACP_PARTNER_LEN \
+ ( sizeof ( struct eth_slow_lacp_entity_tlv ) )
+
+/** LACP collector type */
+#define ETH_SLOW_TLV_LACP_COLLECTOR 3
+
+/** LACP collector length */
+#define ETH_SLOW_TLV_LACP_COLLECTOR_LEN \
+ ( sizeof ( struct eth_slow_lacp_collector_tlv ) )
+
+/** Marker request type */
+#define ETH_SLOW_TLV_MARKER_REQUEST 1
+
+/** Marker request length */
+#define ETH_SLOW_TLV_MARKER_REQUEST_LEN \
+ ( sizeof ( struct eth_slow_marker_tlv ) )
+
+/** Marker response type */
+#define ETH_SLOW_TLV_MARKER_RESPONSE 2
+
+/** Marker response length */
+#define ETH_SLOW_TLV_MARKER_RESPONSE_LEN \
+ ( sizeof ( struct eth_slow_marker_tlv ) )
+
+/** Terminator TLV */
+struct eth_slow_terminator_tlv {
+ /** TLV header */
+ struct eth_slow_tlv_header tlv;
+} __attribute__ (( packed ));
+
+/** LACP entity (actor or partner) TLV */
+struct eth_slow_lacp_entity_tlv {
+ /** TLV header */
+ struct eth_slow_tlv_header tlv;
+ /** System priority
+ *
+ * Used to determine the order in which ports are selected for
+ * aggregation.
+ */
+ uint16_t system_priority;
+ /** System identifier
+ *
+ * Used to uniquely identify the system (i.e. the entity with
+ * potentially multiple ports).
+ */
+ uint8_t system[ETH_ALEN];
+ /** Key
+ *
+ * Used to uniquely identify a group of aggregatable ports
+ * within a system.
+ */
+ uint16_t key;
+ /** Port priority
+ *
+ * Used to determine the order in which ports are selected for
+ * aggregation.
+ */
+ uint16_t port_priority;
+ /** Port identifier
+ *
+ * Used to uniquely identify a port within a system.
+ */
+ uint16_t port;
+ /** State
+ *
+ * This is the bitwise OR of zero or more LACP_STATE_XXX
+ * constants.
+ */
+ uint8_t state;
+ /** Reserved */
+ uint8_t reserved[3];
+} __attribute__ (( packed ));
+
+/** Maximum system priority */
+#define LACP_SYSTEM_PRIORITY_MAX 0xffff
+
+/** Maximum port priority */
+#define LACP_PORT_PRIORITY_MAX 0xff
+
+/** LACP entity is active
+ *
+ * Represented by the state character "A"/"a"
+ */
+#define LACP_STATE_ACTIVE 0x01
+
+/** LACP timeout is short
+ *
+ * Short timeout is one second, long timeout is 30s
+ *
+ * Represented by the state character "F"/"f"
+ */
+#define LACP_STATE_FAST 0x02
+
+/** LACP link is aggregateable
+ *
+ * Represented by the state characters "G"/"g"
+ */
+#define LACP_STATE_AGGREGATABLE 0x04
+
+/** LACP link is in synchronisation
+ *
+ * Represented by the state characters "S"/"s"
+ */
+#define LACP_STATE_IN_SYNC 0x08
+
+/** LACP link is collecting (receiving)
+ *
+ * Represented by the state characters "C"/"c"
+ */
+#define LACP_STATE_COLLECTING 0x10
+
+/** LACP link is distributing (transmitting)
+ *
+ * Represented by the state characters "D"/"d"
+ */
+#define LACP_STATE_DISTRIBUTING 0x20
+
+/** LACP entity is using defaulted partner information
+ *
+ * Represented by the state characters "L"/"l"
+ */
+#define LACP_STATE_DEFAULTED 0x40
+
+/** LACP entity receive state machine is in EXPIRED
+ *
+ * Represented by the state characters "X"/"x"
+ */
+#define LACP_STATE_EXPIRED 0x80
+
+/** LACP collector TLV */
+struct eth_slow_lacp_collector_tlv {
+ /** TLV header */
+ struct eth_slow_tlv_header tlv;
+ /** Maximum delay (in 10us increments) */
+ uint16_t max_delay;
+ /** Reserved */
+ uint8_t reserved[12];
+} __attribute__ (( packed ));
+
+/** Marker TLV */
+struct eth_slow_marker_tlv {
+ /** TLV header */
+ struct eth_slow_tlv_header tlv;
+ /** Requester port */
+ uint16_t port;
+ /** Requester system */
+ uint8_t system[ETH_ALEN];
+ /** Requester transaction ID */
+ uint32_t xact;
+ /** Padding */
+ uint16_t pad;
+} __attribute__ (( packed ));
+
+/** LACP packet */
+struct eth_slow_lacp {
+ /** Slow protocols header */
+ struct eth_slow_header header;
+ /** Actor information */
+ struct eth_slow_lacp_entity_tlv actor;
+ /** Partner information */
+ struct eth_slow_lacp_entity_tlv partner;
+ /** Collector information */
+ struct eth_slow_lacp_collector_tlv collector;
+ /** Terminator */
+ struct eth_slow_terminator_tlv terminator;
+ /** Reserved */
+ uint8_t reserved[50];
+} __attribute__ (( packed ));
+
+/** Marker packet */
+struct eth_slow_marker {
+ /** Slow protocols header */
+ struct eth_slow_header header;
+ /** Marker information */
+ struct eth_slow_marker_tlv marker;
+ /** Terminator */
+ struct eth_slow_terminator_tlv terminator;
+ /** Reserved */
+ uint8_t reserved[90];
+} __attribute__ (( packed ));
+
+/** Slow protocols packet */
+union eth_slow_packet {
+ /** Slow protocols header */
+ struct eth_slow_header header;
+ /** LACP packet */
+ struct eth_slow_lacp lacp;
+ /** Marker packet */
+ struct eth_slow_marker marker;
+} __attribute__ (( packed ));
+
+#endif /* _IPXE_ETH_SLOW_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ethernet.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ethernet.h
new file mode 100644
index 00000000..3d2d462e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ethernet.h
@@ -0,0 +1,95 @@
+#ifndef _IPXE_ETHERNET_H
+#define _IPXE_ETHERNET_H
+
+/** @file
+ *
+ * Ethernet protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/iobuf.h>
+
+/**
+ * Check if Ethernet address is all zeroes
+ *
+ * @v addr Ethernet address
+ * @ret is_zero Address is all zeroes
+ */
+static inline int is_zero_ether_addr ( const void *addr ) {
+ const uint8_t *addr_bytes = addr;
+
+ return ( ! ( addr_bytes[0] | addr_bytes[1] | addr_bytes[2] |
+ addr_bytes[3] | addr_bytes[4] | addr_bytes[5] ) );
+}
+
+/**
+ * Check if Ethernet address is a multicast address
+ *
+ * @v addr Ethernet address
+ * @ret is_mcast Address is a multicast address
+ *
+ * Note that the broadcast address is also a multicast address.
+ */
+static inline int is_multicast_ether_addr ( const void *addr ) {
+ const uint8_t *addr_bytes = addr;
+
+ return ( addr_bytes[0] & 0x01 );
+}
+
+/**
+ * Check if Ethernet address is locally assigned
+ *
+ * @v addr Ethernet address
+ * @ret is_local Address is locally assigned
+ */
+static inline int is_local_ether_addr ( const void *addr ) {
+ const uint8_t *addr_bytes = addr;
+
+ return ( addr_bytes[0] & 0x02 );
+}
+
+/**
+ * Check if Ethernet address is the broadcast address
+ *
+ * @v addr Ethernet address
+ * @ret is_bcast Address is the broadcast address
+ */
+static inline int is_broadcast_ether_addr ( const void *addr ) {
+ const uint8_t *addr_bytes = addr;
+
+ return ( ( addr_bytes[0] & addr_bytes[1] & addr_bytes[2] &
+ addr_bytes[3] & addr_bytes[4] & addr_bytes[5] ) == 0xff );
+}
+
+/**
+ * Check if Ethernet address is valid
+ *
+ * @v addr Ethernet address
+ * @ret is_valid Address is valid
+ *
+ * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is
+ * not a multicast address, and is not ff:ff:ff:ff:ff:ff.
+ */
+static inline int is_valid_ether_addr ( const void *addr ) {
+ return ( ( ! is_multicast_ether_addr ( addr ) ) &&
+ ( ! is_zero_ether_addr ( addr ) ) );
+}
+
+extern int eth_push ( struct net_device *netdev, struct io_buffer *iobuf,
+ const void *ll_dest, const void *ll_source,
+ uint16_t net_proto );
+extern int eth_pull ( struct net_device *netdev, struct io_buffer *iobuf,
+ const void **ll_dest, const void **ll_source,
+ uint16_t *net_proto, unsigned int *flags );
+extern void eth_init_addr ( const void *hw_addr, void *ll_addr );
+extern const char * eth_ntoa ( const void *ll_addr );
+extern int eth_mc_hash ( unsigned int af, const void *net_addr,
+ void *ll_addr );
+extern int eth_eth_addr ( const void *ll_addr, void *eth_addr );
+extern struct net_device * alloc_etherdev ( size_t priv_size );
+
+#endif /* _IPXE_ETHERNET_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/fakedhcp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fakedhcp.h
new file mode 100644
index 00000000..ea06b06d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fakedhcp.h
@@ -0,0 +1,23 @@
+#ifndef _IPXE_FAKEDHCP_H
+#define _IPXE_FAKEDHCP_H
+
+/** @file
+ *
+ * Fake DHCP packets
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+struct net_device;
+
+extern int create_fakedhcpdiscover ( struct net_device *netdev,
+ void *data, size_t max_len );
+extern int create_fakedhcpack ( struct net_device *netdev,
+ void *data, size_t max_len );
+extern int create_fakepxebsack ( struct net_device *netdev,
+ void *data, size_t max_len );
+
+#endif /* _IPXE_FAKEDHCP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/fc.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fc.h
new file mode 100644
index 00000000..6689f394
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fc.h
@@ -0,0 +1,538 @@
+#ifndef _IPXE_FC_H
+#define _IPXE_FC_H
+
+/**
+ * @file
+ *
+ * Fibre Channel
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/list.h>
+#include <ipxe/tables.h>
+#include <ipxe/interface.h>
+#include <ipxe/retry.h>
+#include <ipxe/socket.h>
+
+/******************************************************************************
+ *
+ * Fibre Channel Names and identifiers
+ *
+ ******************************************************************************
+ */
+
+/** A Fibre Channel name */
+struct fc_name {
+ uint8_t bytes[8];
+} __attribute__ (( packed ));
+
+/** Length of Fibre Channel name text */
+#define FC_NAME_STRLEN 23 /* "xx:xx:xx:xx:xx:xx:xx:xx" */
+
+/** A Fibre Channel port identifier */
+struct fc_port_id {
+ uint8_t bytes[3];
+} __attribute__ (( packed ));
+
+/** Length of Fibre Channel port identifier next */
+#define FC_PORT_ID_STRLEN 9 /* "xx.xx.xx" */
+
+/**
+ * Fibre Channel socket address
+ */
+struct sockaddr_fc {
+ /** Socket address family (part of struct @c sockaddr)
+ *
+ * Always set to @c AF_FC for Fibre Channel addresses
+ */
+ sa_family_t sfc_family;
+ /** Port ID */
+ struct fc_port_id sfc_port_id;
+ /** Padding
+ *
+ * This ensures that a struct @c sockaddr_tcpip is large
+ * enough to hold a socket address for any TCP/IP address
+ * family.
+ */
+ char pad[ sizeof ( struct sockaddr ) - sizeof ( sa_family_t )
+ - sizeof ( struct fc_port_id ) ];
+} __attribute__ (( may_alias ));
+
+extern struct fc_port_id fc_empty_port_id;
+extern struct fc_port_id fc_f_port_id;
+extern struct fc_port_id fc_gs_port_id;
+extern struct fc_port_id fc_ptp_low_port_id;
+extern struct fc_port_id fc_ptp_high_port_id;
+
+extern const char * fc_id_ntoa ( const struct fc_port_id *id );
+extern int fc_id_aton ( const char *id_text, struct fc_port_id *id );
+extern const char * fc_ntoa ( const struct fc_name *wwn );
+extern int fc_aton ( const char *wwn_text, struct fc_name *wwn );
+extern struct sockaddr * fc_fill_sockaddr ( struct sockaddr_fc *sa_fc,
+ struct fc_port_id *id );
+
+/******************************************************************************
+ *
+ * Fibre Channel link state
+ *
+ ******************************************************************************
+ */
+
+/** Delay between failed link-up attempts */
+#define FC_LINK_RETRY_DELAY ( 2 * TICKS_PER_SEC )
+
+/** A Fibre Channel link state nonitor */
+struct fc_link_state {
+ /** Retry timer */
+ struct retry_timer timer;
+ /** Link state */
+ int rc;
+ /** Examine link state
+ *
+ * @v link Fibre Channel link state monitor
+ */
+ void ( * examine ) ( struct fc_link_state *link );
+};
+
+/**
+ * Check Fibre Channel link state
+ *
+ * @v link Fibre Channel link state monitor
+ * @ret link_up Link is up
+ */
+static inline __attribute__ (( always_inline )) int
+fc_link_ok ( struct fc_link_state *link ) {
+ return ( link->rc == 0 );
+}
+
+/******************************************************************************
+ *
+ * Fibre Channel packet formats and exchanges
+ *
+ ******************************************************************************
+ */
+
+/** A Fibre Channel Frame Header */
+struct fc_frame_header {
+ /** Routing control
+ *
+ * This is the bitwise OR of one @c fc_r_ctl_routing value and
+ * one @c fc_r_ctl_info value.
+ */
+ uint8_t r_ctl;
+ /** Destination ID */
+ struct fc_port_id d_id;
+ /** Class-specific control / Priority */
+ uint8_t cs_ctl_prio;
+ /** Source ID */
+ struct fc_port_id s_id;
+ /** Data structure type */
+ uint8_t type;
+ /** Frame control - exchange and sequence */
+ uint8_t f_ctl_es;
+ /** Frame control - acknowledgements */
+ uint8_t f_ctl_ack;
+ /** Frame control - miscellaneous */
+ uint8_t f_ctl_misc;
+ /** Sequence ID */
+ uint8_t seq_id;
+ /** Data field control */
+ uint8_t df_ctl;
+ /** Sequence count */
+ uint16_t seq_cnt;
+ /** Originator exchange ID */
+ uint16_t ox_id;
+ /** Responder exchange ID */
+ uint16_t rx_id;
+ /** Parameter
+ *
+ * Contains the relative offset when @c FC_F_CTL_MISC_REL_OFF
+ * is set.
+ */
+ uint32_t parameter;
+} __attribute__ (( packed ));
+
+/** Fibre Channel Routing Control Routing */
+enum fc_r_ctl_routing {
+ FC_R_CTL_DATA = 0x00, /**< Device Data */
+ FC_R_CTL_ELS = 0x20, /**< Extended Link Services */
+ FC_R_CTL_FC4_LINK = 0x30, /**< FC-4 Link Data */
+ FC_R_CTL_VIDEO = 0x40, /**< Video Data */
+ FC_R_CTL_EH = 0x50, /**< Extended Headers */
+ FC_R_CTL_BLS = 0x80, /**< Basic Link Services */
+ FC_R_CTL_LINK_CTRL = 0xc0, /**< Link Control */
+ FC_R_CTL_EXT_ROUTE = 0xf0, /**< Extended Routing */
+};
+
+/** Fibre Channel Routing Control Routing mask */
+#define FC_R_CTL_ROUTING_MASK 0xf0
+
+/** Fibre Channel Routing Control Information */
+enum fc_r_ctl_info {
+ FC_R_CTL_UNCAT = 0x00, /**< Uncategorized */
+ FC_R_CTL_SOL_DATA = 0x01, /**< Solicited Data */
+ FC_R_CTL_UNSOL_CTRL = 0x02, /**< Unsolicited Control */
+ FC_R_CTL_SOL_CTRL = 0x03, /**< Solicited Control */
+ FC_R_CTL_UNSOL_DATA = 0x04, /**< Unsolicited Data */
+ FC_R_CTL_DATA_DESC = 0x05, /**< Data Descriptor */
+ FC_R_CTL_UNSOL_CMD = 0x06, /**< Unsolicited Command */
+ FC_R_CTL_CMD_STAT = 0x07, /**< Command Status */
+};
+
+/** Fibre Channel Routing Control Information mask */
+#define FC_R_CTL_INFO_MASK 0x07
+
+/** Fibre Channel Data Structure Type */
+enum fc_type {
+ FC_TYPE_BLS = 0x00, /**< Basic Link Service */
+ FC_TYPE_ELS = 0x01, /**< Extended Link Service */
+ FC_TYPE_FCP = 0x08, /**< Fibre Channel Protocol */
+ FC_TYPE_CT = 0x20, /**< Common Transport */
+};
+
+/** Fibre Channel Frame Control - Exchange and Sequence */
+enum fc_f_ctl_es {
+ FC_F_CTL_ES_RESPONDER = 0x80, /**< Responder of Exchange */
+ FC_F_CTL_ES_RECIPIENT = 0x40, /**< Sequence Recipient */
+ FC_F_CTL_ES_FIRST = 0x20, /**< First Sequence of Exchange */
+ FC_F_CTL_ES_LAST = 0x10, /**< Last Sequence of Exchange */
+ FC_F_CTL_ES_END = 0x08, /**< Last Data Frame of Sequence */
+ FC_F_CTL_ES_TRANSFER = 0x01, /**< Transfer Sequence Initiative */
+};
+
+/** Fibre Channel Frame Control - Miscellaneous */
+enum fc_f_ctl_misc {
+ FC_F_CTL_MISC_REL_OFF = 0x08, /**< Relative Offset Present */
+};
+
+/** Responder exchange identifier used before first response */
+#define FC_RX_ID_UNKNOWN 0xffff
+
+struct fc_port;
+
+extern int fc_xchg_originate ( struct interface *parent, struct fc_port *port,
+ struct fc_port_id *peer_port_id,
+ unsigned int type );
+
+/** A Fibre Channel responder */
+struct fc_responder {
+ /** Type */
+ unsigned int type;
+ /** Respond to exchange
+ *
+ * @v xchg Exchange interface
+ * @v port Fibre Channel port
+ * @v port_id Local port ID
+ * @v peer_port_id Peer port ID
+ * @ret rc Return status code
+ */
+ int ( * respond ) ( struct interface *xchg, struct fc_port *port,
+ struct fc_port_id *port_id,
+ struct fc_port_id *peer_port_id );
+};
+
+/** Fibre Channel responder table */
+#define FC_RESPONDERS __table ( struct fc_responder, "fc_responders" )
+
+/** Declare a Fibre Channel responder */
+#define __fc_responder __table_entry ( FC_RESPONDERS, 01 )
+
+/******************************************************************************
+ *
+ * Fibre Channel ports
+ *
+ ******************************************************************************
+ */
+
+/** A Fibre Channel port */
+struct fc_port {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** List of all ports */
+ struct list_head list;
+ /** Name of this port */
+ char name[8];
+
+ /** Transport interface */
+ struct interface transport;
+ /** Node name */
+ struct fc_name node_wwn;
+ /** Port name */
+ struct fc_name port_wwn;
+ /** Local port ID */
+ struct fc_port_id port_id;
+ /** Flags */
+ unsigned int flags;
+
+ /** Link state monitor */
+ struct fc_link_state link;
+ /** FLOGI interface */
+ struct interface flogi;
+ /** Link node name */
+ struct fc_name link_node_wwn;
+ /** Link port name */
+ struct fc_name link_port_wwn;
+ /** Link port ID (for point-to-point links only) */
+ struct fc_port_id ptp_link_port_id;
+
+ /** Name server PLOGI interface */
+ struct interface ns_plogi;
+
+ /** List of active exchanges */
+ struct list_head xchgs;
+};
+
+/** Fibre Channel port flags */
+enum fc_port_flags {
+ /** Port is attached to a fabric */
+ FC_PORT_HAS_FABRIC = 0x0001,
+ /** Port is logged in to a name server */
+ FC_PORT_HAS_NS = 0x0002,
+};
+
+/**
+ * Get reference to Fibre Channel port
+ *
+ * @v port Fibre Channel port
+ * @ret port Fibre Channel port
+ */
+static inline __attribute__ (( always_inline )) struct fc_port *
+fc_port_get ( struct fc_port *port ) {
+ ref_get ( &port->refcnt );
+ return port;
+}
+
+/**
+ * Drop reference to Fibre Channel port
+ *
+ * @v port Fibre Channel port
+ */
+static inline __attribute__ (( always_inline )) void
+fc_port_put ( struct fc_port *port ) {
+ ref_put ( &port->refcnt );
+}
+
+extern struct list_head fc_ports;
+
+extern int fc_port_login ( struct fc_port *port, struct fc_port_id *port_id,
+ const struct fc_name *link_node_wwn,
+ const struct fc_name *link_port_wwn,
+ int has_fabric );
+extern void fc_port_logout ( struct fc_port *port, int rc );
+extern int fc_port_open ( struct interface *transport,
+ const struct fc_name *node_wwn,
+ const struct fc_name *port_wwn,
+ const char *name );
+extern struct fc_port * fc_port_find ( const char *name );
+
+/******************************************************************************
+ *
+ * Fibre Channel peers
+ *
+ ******************************************************************************
+ */
+
+/** A Fibre Channel peer */
+struct fc_peer {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** List of all peers */
+ struct list_head list;
+
+ /** Port name */
+ struct fc_name port_wwn;
+
+ /** Link state monitor */
+ struct fc_link_state link;
+ /** PLOGI interface */
+ struct interface plogi;
+ /** Fibre Channel port, if known */
+ struct fc_port *port;
+ /** Peer port ID, if known */
+ struct fc_port_id port_id;
+
+ /** List of upper-layer protocols */
+ struct list_head ulps;
+ /** Active usage count
+ *
+ * A peer (and attached ULPs) may be created in response to
+ * unsolicited login requests received via the fabric. We
+ * track our own active usage count independently of the
+ * existence of the peer, so that if the peer becomes logged
+ * out (e.g. due to a link failure) then we know whether or
+ * not we should attempt to relogin.
+ */
+ unsigned int usage;
+};
+
+/**
+ * Get reference to Fibre Channel peer
+ *
+ * @v peer Fibre Channel peer
+ * @ret peer Fibre Channel peer
+ */
+static inline __attribute__ (( always_inline )) struct fc_peer *
+fc_peer_get ( struct fc_peer *peer ) {
+ ref_get ( &peer->refcnt );
+ return peer;
+}
+
+/**
+ * Drop reference to Fibre Channel peer
+ *
+ * @v peer Fibre Channel peer
+ */
+static inline __attribute__ (( always_inline )) void
+fc_peer_put ( struct fc_peer *peer ) {
+ ref_put ( &peer->refcnt );
+}
+
+extern struct list_head fc_peers;
+
+extern struct fc_peer * fc_peer_get_wwn ( const struct fc_name *port_wwn );
+extern struct fc_peer *
+fc_peer_get_port_id ( struct fc_port *port,
+ const struct fc_port_id *peer_port_id );
+extern int fc_peer_login ( struct fc_peer *peer,
+ struct fc_port *port,
+ struct fc_port_id *port_id );
+extern void fc_peer_logout ( struct fc_peer *peer, int rc );
+
+/******************************************************************************
+ *
+ * Fibre Channel upper-layer protocols
+ *
+ ******************************************************************************
+ */
+
+/** A Fibre Channel upper-layer protocol */
+struct fc_ulp {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Fibre Channel peer */
+ struct fc_peer *peer;
+ /** List of upper-layer protocols */
+ struct list_head list;
+
+ /** Type */
+ unsigned int type;
+ /** Flags */
+ unsigned int flags;
+
+ /** Link state monitor */
+ struct fc_link_state link;
+ /** PRLI interface */
+ struct interface prli;
+ /** Service parameters, if any */
+ void *param;
+ /** Service parameter length */
+ size_t param_len;
+
+ /** Active users of this upper-layer protocol
+ *
+ * As with peers, an upper-layer protocol may be created in
+ * response to an unsolicited login request received via the
+ * fabric. This list records the number of active users of
+ * the ULP; the number of entries in the list is equivalent to
+ * the peer usage count.
+ */
+ struct list_head users;
+};
+
+/** Fibre Channel upper-layer protocol flags */
+enum fc_ulp_flags {
+ /** A login originated by us has succeeded */
+ FC_ULP_ORIGINATED_LOGIN_OK = 0x0001,
+};
+
+/** A Fibre Channel upper-layer protocol user */
+struct fc_ulp_user {
+ /** Fibre Channel upper layer protocol */
+ struct fc_ulp *ulp;
+ /** List of users */
+ struct list_head list;
+ /** Containing object reference count, or NULL */
+ struct refcnt *refcnt;
+ /** Examine link state
+ *
+ * @v user Fibre Channel upper-layer-protocol user
+ */
+ void ( * examine ) ( struct fc_ulp_user *user );
+};
+
+/**
+ * Get reference to Fibre Channel upper-layer protocol
+ *
+ * @v ulp Fibre Channel upper-layer protocol
+ * @ret ulp Fibre Channel upper-layer protocol
+ */
+static inline __attribute__ (( always_inline )) struct fc_ulp *
+fc_ulp_get ( struct fc_ulp *ulp ) {
+ ref_get ( &ulp->refcnt );
+ return ulp;
+}
+
+/**
+ * Drop reference to Fibre Channel upper-layer protocol
+ *
+ * @v ulp Fibre Channel upper-layer protocol
+ */
+static inline __attribute__ (( always_inline )) void
+fc_ulp_put ( struct fc_ulp *ulp ) {
+ ref_put ( &ulp->refcnt );
+}
+
+/**
+ * Get reference to Fibre Channel upper-layer protocol user
+ *
+ * @v user Fibre Channel upper-layer protocol user
+ * @ret user Fibre Channel upper-layer protocol user
+ */
+static inline __attribute__ (( always_inline )) struct fc_ulp_user *
+fc_ulp_user_get ( struct fc_ulp_user *user ) {
+ ref_get ( user->refcnt );
+ return user;
+}
+
+/**
+ * Drop reference to Fibre Channel upper-layer protocol user
+ *
+ * @v user Fibre Channel upper-layer protocol user
+ */
+static inline __attribute__ (( always_inline )) void
+fc_ulp_user_put ( struct fc_ulp_user *user ) {
+ ref_put ( user->refcnt );
+}
+
+/**
+ * Initialise Fibre Channel upper-layer protocol user
+ *
+ * @v user Fibre Channel upper-layer protocol user
+ * @v examine Examine link state method
+ * @v refcnt Containing object reference count, or NULL
+ */
+static inline __attribute__ (( always_inline )) void
+fc_ulp_user_init ( struct fc_ulp_user *user,
+ void ( * examine ) ( struct fc_ulp_user *user ),
+ struct refcnt *refcnt ) {
+ user->examine = examine;
+ user->refcnt = refcnt;
+}
+
+extern struct fc_ulp * fc_ulp_get_wwn_type ( const struct fc_name *port_wwn,
+ unsigned int type );
+extern struct fc_ulp *
+fc_ulp_get_port_id_type ( struct fc_port *port,
+ const struct fc_port_id *peer_port_id,
+ unsigned int type );
+extern void fc_ulp_attach ( struct fc_ulp *ulp, struct fc_ulp_user *user );
+extern void fc_ulp_detach ( struct fc_ulp_user *user );
+extern int fc_ulp_login ( struct fc_ulp *ulp, const void *param,
+ size_t param_len, int originated );
+extern void fc_ulp_logout ( struct fc_ulp *ulp, int rc );
+
+#endif /* _IPXE_FC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/fcels.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fcels.h
new file mode 100644
index 00000000..45fa69a4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fcels.h
@@ -0,0 +1,445 @@
+#ifndef _IPXE_FCELS_H
+#define _IPXE_FCELS_H
+
+/**
+ * @file
+ *
+ * Fibre Channel Extended Link Services
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/fc.h>
+#include <ipxe/tables.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/list.h>
+#include <ipxe/process.h>
+#include <ipxe/interface.h>
+
+/** Fibre Channel ELS frame common parameters */
+struct fc_els_frame_common {
+ /** ELS command code */
+ uint8_t command;
+ /** Reserved */
+ uint8_t reserved[3];
+} __attribute__ (( packed ));
+
+/** Fibre Channel ELS command codes */
+enum fc_els_command_code {
+ FC_ELS_LS_RJT = 0x01, /**< Link Service Reject */
+ FC_ELS_LS_ACC = 0x02, /**< Link Service Accept */
+ FC_ELS_PLOGI = 0x03, /**< Port Login */
+ FC_ELS_FLOGI = 0x04, /**< Fabric Login */
+ FC_ELS_LOGO = 0x05, /**< Logout */
+ FC_ELS_RTV = 0x0e, /**< Read Timeout Value */
+ FC_ELS_ECHO = 0x10, /**< Echo */
+ FC_ELS_PRLI = 0x20, /**< Process Login */
+ FC_ELS_PRLO = 0x21, /**< Process Logout */
+};
+
+/** A Fibre Channel LS_RJT frame */
+struct fc_ls_rjt_frame {
+ /** ELS command code */
+ uint8_t command;
+ /** Reserved */
+ uint8_t reserved[4];
+ /** Reason code */
+ uint8_t reason;
+ /** Reason code explanation */
+ uint8_t explanation;
+ /** Vendor unique */
+ uint8_t vendor;
+} __attribute__ (( packed ));
+
+/** Fibre Channel ELS rejection reason codes */
+enum fc_els_reject_reason {
+ /** Invalid ELS command code */
+ FC_ELS_RJT_INVALID_COMMAND = 0x01,
+ /** Logical error */
+ FC_ELS_RJT_ILLOGICAL = 0x03,
+ /** Logical busy */
+ FC_ELS_RJT_BUSY = 0x05,
+ /** Protocol error */
+ FC_ELS_RJT_PROTOCOL = 0x07,
+ /** Unable to perform command request */
+ FC_ELS_RJT_UNABLE = 0x09,
+ /** Command not supported */
+ FC_ELS_RJT_UNSUPPORTED = 0x0b,
+ /** Command already in progress */
+ FC_ELS_RJT_IN_PROGRESS = 0x0e,
+};
+
+/** Fibre Channel "common" service parameters */
+struct fc_login_common {
+ /** Login version */
+ uint16_t version;
+ /** Buffer-to-buffer credit */
+ uint16_t credit;
+ /** Flags */
+ uint16_t flags;
+ /** Receive size */
+ uint16_t mtu;
+ /** "Common"?! */
+ union {
+ struct {
+ /** Maximum number of concurrent sequences */
+ uint16_t max_seq;
+ /** Relative offset by info category */
+ uint16_t rel_offs;
+ } plogi;
+ struct {
+ /** Resource allocation timeout value */
+ uint32_t r_a_tov;
+ } flogi;
+ } u;
+ /** Error detection timeout value */
+ uint32_t e_d_tov;
+} __attribute__ (( packed ));
+
+/** Fibre Channel default login version */
+#define FC_LOGIN_VERSION 0x2020
+
+/** Fibre Channel default buffer-to-buffer credit */
+#define FC_LOGIN_DEFAULT_B2B 10
+
+/** Continuously increasing relative offset */
+#define FC_LOGIN_CONTINUOUS_OFFSET 0x8000
+
+/** Clean address */
+#define FC_LOGIN_CLEAN 0x8000
+
+/** Multiple N_Port_ID support */
+#define FC_LOGIN_MULTI_N 0x8000
+
+/** Random relative offset */
+#define FC_LOGIN_RANDOM_OFFSET 0x4000
+
+/** Virtual fabrics */
+#define FC_LOGIN_VIRTUAL 0x4000
+
+/** Vendor version level */
+#define FC_LOGIN_VENDOR 0x2000
+
+/** Multiple N_Port_ID support */
+#define FC_LOGIN_MULTI_F 0x2000
+
+/** Forwarder port */
+#define FC_LOGIN_F_PORT 0x1000
+
+/** Alternative credit management */
+#define FC_LOGIN_ALT_CREDIT 0x0800
+
+/** Name server session started */
+#define FC_LOGIN_NSS_STARTED 0x0800
+
+/** Begin name server session */
+#define FC_LOGIN_NSS_BEGIN 0x0400
+
+/** 1ns error detection timer resolution */
+#define FC_LOGIN_HIRES_E_D_TOV 0x0400
+
+/** Broadcast supported */
+#define FC_LOGIN_BROADCAST 0x0100
+
+/** Query buffer conditions */
+#define FC_LOGIN_QUERY_BUF 0x0040
+
+/** Security */
+#define FC_LOGIN_SECURITY 0x0020
+
+/** Clock sync primitive capable */
+#define FC_LOGIN_CLOCK_SYNC 0x0010
+
+/** Short R_T timeout */
+#define FC_LOGIN_SHORT_R_T_TOV 0x0008
+
+/** Dynamic half duplex */
+#define FC_LOGIN_DHD 0x0004
+
+/** Continuously increasing sequence count */
+#define FC_LOGIN_CONTINUOUS_SEQ 0x0002
+
+/** Payload */
+#define FC_LOGIN_PAYLOAD 0x0001
+
+/** Fibre Channel default MTU */
+#define FC_LOGIN_DEFAULT_MTU 1452
+
+/** Default maximum number of concurrent sequences */
+#define FC_LOGIN_DEFAULT_MAX_SEQ 255
+
+/** Default relative offset by info category */
+#define FC_LOGIN_DEFAULT_REL_OFFS 0x1f
+
+/** Default E_D timeout value */
+#define FC_LOGIN_DEFAULT_E_D_TOV 2000
+
+/** Fibre Channel class-specific login parameters */
+struct fc_login_class {
+ /** Flags */
+ uint16_t flags;
+ /** Initiator flags */
+ uint16_t init_flags;
+ /** Recipient flags */
+ uint16_t recip_flags;
+ /** Receive data field size */
+ uint16_t mtu;
+ /** Maximum number of concurrent sequences */
+ uint16_t max_seq;
+ /** End-to-end credit */
+ uint16_t credit;
+ /** Reserved */
+ uint8_t reserved0;
+ /** Maximum number of open sequences per exchange */
+ uint8_t max_seq_per_xchg;
+ /** Reserved */
+ uint8_t reserved1[2];
+} __attribute__ (( packed ));
+
+/** Class valid */
+#define FC_LOGIN_CLASS_VALID 0x8000
+
+/** Sequential delivery requested */
+#define FC_LOGIN_CLASS_SEQUENTIAL 0x0800
+
+/** A Fibre Channel FLOGI/PLOGI frame */
+struct fc_login_frame {
+ /** ELS command code */
+ uint8_t command;
+ /** Reserved */
+ uint8_t reserved[3];
+ /** Common service parameters */
+ struct fc_login_common common;
+ /** Port name */
+ struct fc_name port_wwn;
+ /** Node name */
+ struct fc_name node_wwn;
+ /** Class 1 service parameters */
+ struct fc_login_class class1;
+ /** Class 2 service parameters */
+ struct fc_login_class class2;
+ /** Class 3 service parameters */
+ struct fc_login_class class3;
+ /** Class 4 service parameters */
+ struct fc_login_class class4;
+ /** Vendor version level */
+ uint8_t vendor_version[16];
+} __attribute__ (( packed ));
+
+/** A Fibre Channel LOGO request frame */
+struct fc_logout_request_frame {
+ /** ELS command code */
+ uint8_t command;
+ /** Reserved */
+ uint8_t reserved[4];
+ /** Port ID */
+ struct fc_port_id port_id;
+ /** Port name */
+ struct fc_name port_wwn;
+} __attribute__ (( packed ));
+
+/** A Fibre Channel LOGO response frame */
+struct fc_logout_response_frame {
+ /** ELS command code */
+ uint8_t command;
+ /** Reserved */
+ uint8_t reserved[3];
+} __attribute__ (( packed ));
+
+/** A Fibre Channel PRLI service parameter page */
+struct fc_prli_page {
+ /** Type code */
+ uint8_t type;
+ /** Type code extension */
+ uint8_t type_ext;
+ /** Flags and response code */
+ uint16_t flags;
+ /** Reserved */
+ uint32_t reserved[2];
+} __attribute__ (( packed ));
+
+/** Establish image pair */
+#define FC_PRLI_ESTABLISH 0x2000
+
+/** Response code mask */
+#define FC_PRLI_RESPONSE_MASK 0x0f00
+
+/** Request was executed successfully */
+#define FC_PRLI_RESPONSE_SUCCESS 0x0100
+
+/** A Fibre Channel PRLI frame */
+struct fc_prli_frame {
+ /** ELS command code */
+ uint8_t command;
+ /** Page length */
+ uint8_t page_len;
+ /** Payload length */
+ uint16_t len;
+ /** Service parameter page */
+ struct fc_prli_page page;
+} __attribute__ (( packed ));
+
+/** A Fibre Channel RTV request frame */
+struct fc_rtv_request_frame {
+ /** ELS command code */
+ uint8_t command;
+ /** Reserved */
+ uint8_t reserved[3];
+} __attribute__ (( packed ));
+
+/** A Fibre Channel RTV response frame */
+struct fc_rtv_response_frame {
+ /** ELS command code */
+ uint8_t command;
+ /** Reserved */
+ uint8_t reserved0[3];
+ /** Resource allocation timeout value */
+ uint32_t r_a_tov;
+ /** Error detection timeout value */
+ uint32_t e_d_tov;
+ /** Timeout qualifier */
+ uint16_t flags;
+ /** Reserved */
+ uint16_t reserved1;
+} __attribute__ (( packed ));
+
+/** 1ns error detection timer resolution */
+#define FC_RTV_HIRES_E_D_TOV 0x0400
+
+/** Short R_T timeout */
+#define FC_RTV_SHORT_R_T_TOV 0x0008
+
+/** A Fibre Channel ECHO frame */
+struct fc_echo_frame_header {
+ /** ELS command code */
+ uint8_t command;
+ /** Reserved */
+ uint8_t reserved[3];
+} __attribute__ (( packed ));
+
+/** A Fibre Channel extended link services transaction */
+struct fc_els {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Job control interface */
+ struct interface job;
+ /** Fibre Channel exchange */
+ struct interface xchg;
+ /** Request sending process */
+ struct process process;
+
+ /** Fibre Channel port */
+ struct fc_port *port;
+ /** Local port ID */
+ struct fc_port_id port_id;
+ /** Peer port ID */
+ struct fc_port_id peer_port_id;
+ /** ELS handler, if known */
+ struct fc_els_handler *handler;
+ /** Flags */
+ unsigned int flags;
+};
+
+/** Fibre Channel extended link services transaction flags */
+enum fc_els_flags {
+ /** ELS transaction is a request */
+ FC_ELS_REQUEST = 0x0001,
+};
+
+/** A Fibre Channel extended link services handler */
+struct fc_els_handler {
+ /** Name */
+ const char *name;
+ /** Transmit ELS frame
+ *
+ * @v els Fibre Channel ELS transaction
+ * @ret rc Return status code
+ */
+ int ( * tx ) ( struct fc_els *els );
+ /** Receive ELS frame
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+ int ( * rx ) ( struct fc_els *els, void *data, size_t len );
+ /** Detect ELS frame
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+ int ( * detect ) ( struct fc_els *els, const void *data, size_t len );
+};
+
+/** Fibre Channel ELS handler table */
+#define FC_ELS_HANDLERS __table ( struct fc_els_handler, "fc_els_handlers" )
+
+/** Declare a Fibre Channel ELS handler */
+#define __fc_els_handler __table_entry ( FC_ELS_HANDLERS, 01 )
+
+/** A Fibre Channel ELS PRLI descriptor */
+struct fc_els_prli_descriptor {
+ /** Upper-layer protocol type */
+ unsigned int type;
+ /** Service parameter length */
+ size_t param_len;
+ /** Fibre Channel ELS handler */
+ struct fc_els_handler *handler;
+};
+
+/** Fibre Channel ELS PRLI descriptor table */
+#define FC_ELS_PRLI_DESCRIPTORS \
+ __table ( struct fc_els_prli_descriptor, "fc_els_prli_descriptors" )
+
+/** Declare a Fibre Channel ELS PRLI descriptor */
+#define __fc_els_prli_descriptor __table_entry ( FC_ELS_PRLI_DESCRIPTORS, 01 )
+
+/**
+ * Check if Fibre Channel ELS transaction is a request
+ *
+ * @v els Fibre Channel ELS transaction
+ * @ret is_request ELS transaction is a request
+ */
+static inline int fc_els_is_request ( struct fc_els *els ) {
+ return ( els->flags & FC_ELS_REQUEST );
+}
+
+/**
+ * Calculate ELS command to transmit
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v request_command Command for requests
+ * @v command Command to transmit
+ */
+static inline unsigned int fc_els_tx_command ( struct fc_els *els,
+ unsigned int request_command ) {
+ return ( fc_els_is_request ( els ) ? request_command : FC_ELS_LS_ACC );
+}
+
+extern int fc_els_tx ( struct fc_els *els, const void *data, size_t len );
+extern int fc_els_request ( struct interface *job, struct fc_port *port,
+ struct fc_port_id *peer_port_id,
+ struct fc_els_handler *handler );
+extern int fc_els_flogi ( struct interface *parent, struct fc_port *port );
+extern int fc_els_plogi ( struct interface *parent, struct fc_port *port,
+ struct fc_port_id *peer_port_id );
+extern int fc_els_logo ( struct interface *parent, struct fc_port *port,
+ struct fc_port_id *peer_port_id );
+extern int fc_els_prli ( struct interface *parent, struct fc_port *port,
+ struct fc_port_id *peer_port_id, unsigned int type );
+extern int fc_els_prli_tx ( struct fc_els *els,
+ struct fc_els_prli_descriptor *descriptor,
+ void *param );
+extern int fc_els_prli_rx ( struct fc_els *els,
+ struct fc_els_prli_descriptor *descriptor,
+ void *data, size_t len );
+extern int fc_els_prli_detect ( struct fc_els *els __unused,
+ struct fc_els_prli_descriptor *descriptor,
+ const void *data, size_t len );
+
+#endif /* _IPXE_FCELS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/fcns.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fcns.h
new file mode 100644
index 00000000..e25d9b9d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fcns.h
@@ -0,0 +1,217 @@
+#ifndef _IPXE_FCNS_H
+#define _IPXE_FCNS_H
+
+/**
+ * @file
+ *
+ * Fibre Channel name server lookups
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/fc.h>
+
+/** A Fibre Channel Common Transport header */
+struct fc_ct_header {
+ /** Revision */
+ uint8_t revision;
+ /** Original requestor ID */
+ struct fc_port_id in_id;
+ /** Generic service type */
+ uint8_t type;
+ /** Generic service subtype */
+ uint8_t subtype;
+ /** Options */
+ uint8_t options;
+ /** Reserved */
+ uint8_t reserved;
+ /** Command/response code */
+ uint16_t code;
+ /** Maximum/residual size */
+ uint16_t size;
+ /** Fragment ID */
+ uint8_t fragment;
+ /** Reason code */
+ uint8_t reason;
+ /** Reason code explanation */
+ uint8_t explanation;
+ /** Vendor specific */
+ uint8_t vendor;
+} __attribute__ (( packed ));
+
+/** Fibre Channel Common Transport revision */
+#define FC_CT_REVISION 1
+
+/** Fibre Channel generic service type */
+enum fc_gs_type {
+ /** Directory service */
+ FC_GS_TYPE_DS = 0xfc,
+};
+
+/** Fibre Channel generic service response codes */
+enum fc_gs_response_code {
+ /** Accepted */
+ FC_GS_ACCEPT = 0x8002,
+ /** Rejected */
+ FC_GS_REJECT = 0x8001,
+};
+
+/** Fibre Channel generic service rejection reason codes */
+enum fc_gs_reason_code {
+ /** Invalid command code */
+ FC_GS_BAD_COMMAND = 0x01,
+ /** Invalid version level */
+ FC_GS_BAD_VERSION = 0x02,
+ /** Logical error */
+ FC_GS_ERROR = 0x03,
+ /** Invalid CT_IU size */
+ FC_GS_BAD_SIZE = 0x04,
+ /** Logical busy */
+ FC_GS_BUSY = 0x05,
+ /** Protocol error */
+ FC_GS_EPROTO = 0x07,
+ /** Unable to perform command request */
+ FC_GS_UNABLE = 0x09,
+ /** Command not supported */
+ FC_GS_ENOTSUP = 0x0b,
+ /** Server not available */
+ FC_GS_UNAVAILABLE = 0x0d,
+ /** Session could not be established */
+ FC_GS_SESSION = 0x0e,
+};
+
+/** Fibre Channel directory service subtype */
+enum fc_ds_subtype {
+ /** Name server */
+ FC_DS_SUBTYPE_NAME = 0x02,
+};
+
+/** Fibre Channel name server commands */
+enum fc_ns_command_nibble {
+ /** Get */
+ FC_NS_GET = 0x1,
+ /** Register */
+ FC_NS_REGISTER = 0x2,
+ /** De-register */
+ FC_NS_DEREGISTER = 0x3,
+};
+
+/** Fibre Channel name server objects */
+enum fc_ns_object_nibble {
+ /** Port ID */
+ FC_NS_PORT_ID = 0x1,
+ /** Port name */
+ FC_NS_PORT_NAME = 0x2,
+ /** Node name */
+ FC_NS_NODE_NAME = 0x3,
+ /** FC-4 types */
+ FC_NS_FC4_TYPES = 0x7,
+ /** Symbolic port name */
+ FC_NS_SYM_PORT_NAME = 0x8,
+ /** Symbolic node name */
+ FC_NS_SYM_NODE_NAME = 0x9,
+ /** FC-4 features */
+ FC_NS_FC4_FEATURES = 0xf,
+};
+
+/** Construct Fibre Channel name server command code
+ *
+ * @v command Name server command
+ * @v key Name server key
+ * @v value Name server value
+ * @ret code Name server command code
+ */
+#define FC_NS_CODE( command, key, value ) \
+ ( ( (command) << 8 ) | ( (key) << 4 ) | ( (value) << 0 ) )
+
+/** Construct Fibre Channel name server "get" command code
+ *
+ * @v key Name server key
+ * @v value Name server value to get
+ * @ret code Name server command code
+ */
+#define FC_NS_GET( key, value ) FC_NS_CODE ( FC_NS_GET, key, value )
+
+/** Construct Fibre Channel name server "register" command code
+ *
+ * @v key Name server key
+ * @v value Name server value to register
+ * @ret code Name server command code
+ */
+#define FC_NS_REGISTER( key, value ) FC_NS_CODE ( FC_NS_REGISTER, key, value )
+
+/** Extract Fibre Channel name server command
+ *
+ * @v code Name server command code
+ * @ret command Name server command
+ */
+#define FC_NS_COMMAND( code ) ( ( (code) >> 8 ) & 0xf )
+
+/** Extract Fibre Channel name server key
+ *
+ * @v code Name server command code
+ * @ret key Name server key
+ */
+#define FC_NS_KEY( code ) ( ( (code) >> 4 ) & 0xf )
+
+/** Extract Fibre Channel name server value
+ *
+ * @v code Name server command code
+ * @ret value NAme server value
+ */
+#define FC_NS_VALUE( code ) ( ( (code) >> 0 ) & 0xf )
+
+/** A Fibre Channel name server port ID */
+struct fc_ns_port_id {
+ /** Reserved */
+ uint8_t reserved;
+ /** Port ID */
+ struct fc_port_id port_id;
+} __attribute__ (( packed ));
+
+/** A Fibre Channel name server GID_PN request */
+struct fc_ns_gid_pn_request {
+ /** Common Transport header */
+ struct fc_ct_header ct;
+ /** Port name */
+ struct fc_name port_wwn;
+} __attribute__ (( packed ));
+
+/** A Fibre Channel name server request */
+union fc_ns_request {
+ /** Get ID by port name */
+ struct fc_ns_gid_pn_request gid_pn;
+};
+
+/** A Fibre Channel name server rejection response */
+struct fc_ns_reject_response {
+ /** Common Transport header */
+ struct fc_ct_header ct;
+} __attribute__ (( packed ));
+
+/** A Fibre Channel name server GID_PN response */
+struct fc_ns_gid_pn_response {
+ /** Common Transport header */
+ struct fc_ct_header ct;
+ /** Port ID */
+ struct fc_ns_port_id port_id;
+} __attribute__ (( packed ));
+
+/** A Fibre Channel name server response */
+union fc_ns_response {
+ /** Common Transport header */
+ struct fc_ct_header ct;
+ /** Rejection */
+ struct fc_ns_reject_response reject;
+ /** Get ID by port name */
+ struct fc_ns_gid_pn_response gid_pn;
+};
+
+extern int fc_ns_query ( struct fc_peer *peer, struct fc_port *port,
+ int ( * done ) ( struct fc_peer *peer,
+ struct fc_port *port,
+ struct fc_port_id *peer_port_id ) );
+
+#endif /* _IPXE_FCNS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/fcoe.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fcoe.h
new file mode 100644
index 00000000..6ba5b406
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fcoe.h
@@ -0,0 +1,92 @@
+#ifndef _IPXE_FCOE_H
+#define _IPXE_FCOE_H
+
+/**
+ * @file
+ *
+ * Fibre Channel over Ethernet
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/fc.h>
+#include <ipxe/if_ether.h>
+
+/** An FCoE name */
+union fcoe_name {
+ /** Fibre Channel name */
+ struct fc_name fc;
+ /** FCoE name */
+ struct {
+ /** Naming authority */
+ uint16_t authority;
+ /** MAC address */
+ uint8_t mac[ETH_ALEN];
+ } __attribute__ (( packed )) fcoe;
+};
+
+/** IEEE 48-bit address */
+#define FCOE_AUTHORITY_IEEE 0x1000
+
+/** IEEE extended */
+#define FCOE_AUTHORITY_IEEE_EXTENDED 0x2000
+
+/** An FCoE MAC address prefix (FC-MAP) */
+struct fcoe_map {
+ uint8_t bytes[3];
+} __attribute__ (( packed ));
+
+/** An FCoE (fabric-assigned) MAC address */
+struct fcoe_mac {
+ /** MAC address prefix */
+ struct fcoe_map map;
+ /** Port ID */
+ struct fc_port_id port_id;
+} __attribute__ (( packed ));
+
+/** An FCoE header */
+struct fcoe_header {
+ /** FCoE frame version */
+ uint8_t version;
+ /** Reserved */
+ uint8_t reserved[12];
+ /** Start of Frame marker */
+ uint8_t sof;
+} __attribute__ (( packed ));
+
+/** FCoE frame version */
+#define FCOE_FRAME_VER 0x00
+
+/** Start of Frame marker values */
+enum fcoe_sof {
+ FCOE_SOF_F = 0x28, /**< Start of Frame Class F */
+ FCOE_SOF_I2 = 0x2d, /**< Start of Frame Initiate Class 2 */
+ FCOE_SOF_N2 = 0x35, /**< Start of Frame Normal Class 2 */
+ FCOE_SOF_I3 = 0x2e, /**< Start of Frame Initiate Class 3 */
+ FCOE_SOF_N3 = 0x36, /**< Start of Frame Normal Class 3 */
+};
+
+/** An FCoE footer */
+struct fcoe_footer {
+ /** CRC */
+ uint32_t crc;
+ /** End of frame marker */
+ uint8_t eof;
+ /** Reserved */
+ uint8_t reserved[3];
+} __attribute__ (( packed ));
+
+/** End of Frame marker value */
+enum fcoe_eof {
+ FCOE_EOF_N = 0x41, /**< End of Frame Normal */
+ FCOE_EOF_T = 0x42, /**< End of Frame Terminate */
+ FCOE_EOF_NI = 0x49, /**< End of Frame Invalid */
+ FCOE_EOF_A = 0x50, /**< End of Frame Abort */
+};
+
+/** FCoE VLAN priority */
+#define FCOE_VLAN_PRIORITY 3
+
+#endif /* _IPXE_FCOE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/fcp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fcp.h
new file mode 100644
index 00000000..f6922bc7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fcp.h
@@ -0,0 +1,166 @@
+#ifndef _IPXE_FCP_H
+#define _IPXE_FCP_H
+
+/**
+ * @file
+ *
+ * Fibre Channel Protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/fc.h>
+#include <ipxe/fcels.h>
+#include <ipxe/scsi.h>
+
+/** An FCP command IU */
+struct fcp_cmnd {
+ /** SCSI LUN */
+ struct scsi_lun lun;
+ /** Command reference number */
+ uint8_t ref;
+ /** Priority and task attributes */
+ uint8_t priority;
+ /** Task management flags */
+ uint8_t flags;
+ /** Direction */
+ uint8_t dirn;
+ /** SCSI CDB */
+ union scsi_cdb cdb;
+ /** Data length */
+ uint32_t len;
+} __attribute__ (( packed ));
+
+/** Command includes data-out */
+#define FCP_CMND_WRDATA 0x01
+
+/** Command includes data-in */
+#define FCP_CMND_RDDATA 0x02
+
+/** FCP tag magic marker */
+#define FCP_TAG_MAGIC 0x18ae0000
+
+/** An FCP transfer ready IU */
+struct fcp_xfer_rdy {
+ /** Relative offset of data */
+ uint32_t offset;
+ /** Burst length */
+ uint32_t len;
+ /** Reserved */
+ uint32_t reserved;
+} __attribute__ (( packed ));
+
+/** An FCP response IU */
+struct fcp_rsp {
+ /** Reserved */
+ uint8_t reserved[8];
+ /** Retry delay timer */
+ uint16_t retry_delay;
+ /** Flags */
+ uint8_t flags;
+ /** SCSI status code */
+ uint8_t status;
+ /** Residual data count */
+ uint32_t residual;
+ /** Sense data length */
+ uint32_t sense_len;
+ /** Response data length */
+ uint32_t response_len;
+} __attribute__ (( packed ));
+
+/** Response length field is valid */
+#define FCP_RSP_RESPONSE_LEN_VALID 0x01
+
+/** Sense length field is valid */
+#define FCP_RSP_SENSE_LEN_VALID 0x02
+
+/** Residual represents overrun */
+#define FCP_RSP_RESIDUAL_OVERRUN 0x04
+
+/** Residual represents underrun */
+#define FCP_RSP_RESIDUAL_UNDERRUN 0x08
+
+/**
+ * Get response data portion of FCP response
+ *
+ * @v rsp FCP response
+ * @ret response_data Response data, or NULL if not present
+ */
+static inline void * fcp_rsp_response_data ( struct fcp_rsp *rsp ) {
+ return ( ( rsp->flags & FCP_RSP_RESPONSE_LEN_VALID ) ?
+ ( ( ( void * ) rsp ) + sizeof ( *rsp ) ) : NULL );
+}
+
+/**
+ * Get length of response data portion of FCP response
+ *
+ * @v rsp FCP response
+ * @ret response_data_len Response data length
+ */
+static inline size_t fcp_rsp_response_data_len ( struct fcp_rsp *rsp ) {
+ return ( ( rsp->flags & FCP_RSP_RESPONSE_LEN_VALID ) ?
+ ntohl ( rsp->response_len ) : 0 );
+}
+
+/**
+ * Get sense data portion of FCP response
+ *
+ * @v rsp FCP response
+ * @ret sense_data Sense data, or NULL if not present
+ */
+static inline void * fcp_rsp_sense_data ( struct fcp_rsp *rsp ) {
+ return ( ( rsp->flags & FCP_RSP_SENSE_LEN_VALID ) ?
+ ( ( ( void * ) rsp ) + sizeof ( *rsp ) +
+ fcp_rsp_response_data_len ( rsp ) ) : NULL );
+}
+
+/**
+ * Get length of sense data portion of FCP response
+ *
+ * @v rsp FCP response
+ * @ret sense_data_len Sense data length
+ */
+static inline size_t fcp_rsp_sense_data_len ( struct fcp_rsp *rsp ) {
+ return ( ( rsp->flags & FCP_RSP_SENSE_LEN_VALID ) ?
+ ntohl ( rsp->sense_len ) : 0 );
+}
+
+/** An FCP PRLI service parameter page */
+struct fcp_prli_service_parameters {
+ /** Flags */
+ uint32_t flags;
+} __attribute__ (( packed ));
+
+/** Write FCP_XFER_RDY disabled */
+#define FCP_PRLI_NO_WRITE_RDY 0x0001
+
+/** Read FCP_XFER_RDY disabled */
+#define FCP_PRLI_NO_READ_RDY 0x0002
+
+/** Has target functionality */
+#define FCP_PRLI_TARGET 0x0010
+
+/** Has initiator functionality */
+#define FCP_PRLI_INITIATOR 0x0020
+
+/** Data overlay allowed */
+#define FCP_PRLI_OVERLAY 0x0040
+
+/** Confirm completion allowed */
+#define FCP_PRLI_CONF 0x0080
+
+/** Retransmission supported */
+#define FCP_PRLI_RETRY 0x0100
+
+/** Task retry identification */
+#define FCP_PRLI_TASK_RETRY 0x0200
+
+/** REC ELS supported */
+#define FCP_PRLI_REC 0x0400
+
+/** Enhanced discovery supported */
+#define FCP_PRLI_ENH_DISC 0x0800
+
+#endif /* _IPXE_FCP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/features.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/features.h
new file mode 100644
index 00000000..498ec944
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/features.h
@@ -0,0 +1,106 @@
+#ifndef _IPXE_FEATURES_H
+#define _IPXE_FEATURES_H
+
+#include <stdint.h>
+#include <ipxe/tables.h>
+#include <ipxe/dhcp.h>
+
+/** @file
+ *
+ * Feature list
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @defgroup featurecat Feature categories
+ * @{
+ */
+
+#define FEATURE_PROTOCOL 01 /**< Network protocols */
+#define FEATURE_IMAGE 02 /**< Image formats */
+#define FEATURE_MISC 03 /**< Miscellaneous */
+
+/** @} */
+
+/**
+ * @defgroup dhcpfeatures DHCP feature option tags
+ *
+ * DHCP feature option tags are Etherboot encapsulated options in the
+ * range 0x10-0x7f.
+ *
+ * @{
+ */
+
+#define DHCP_EB_FEATURE_PXE_EXT 0x10 /**< PXE API extensions */
+#define DHCP_EB_FEATURE_ISCSI 0x11 /**< iSCSI protocol */
+#define DHCP_EB_FEATURE_AOE 0x12 /**< AoE protocol */
+#define DHCP_EB_FEATURE_HTTP 0x13 /**< HTTP protocol */
+#define DHCP_EB_FEATURE_HTTPS 0x14 /**< HTTPS protocol */
+#define DHCP_EB_FEATURE_TFTP 0x15 /**< TFTP protocol */
+#define DHCP_EB_FEATURE_FTP 0x16 /**< FTP protocol */
+#define DHCP_EB_FEATURE_DNS 0x17 /**< DNS protocol */
+#define DHCP_EB_FEATURE_BZIMAGE 0x18 /**< bzImage format */
+#define DHCP_EB_FEATURE_MULTIBOOT 0x19 /**< Multiboot format */
+#define DHCP_EB_FEATURE_SLAM 0x1a /**< SLAM protocol */
+#define DHCP_EB_FEATURE_SRP 0x1b /**< SRP protocol */
+#define DHCP_EB_FEATURE_NBI 0x20 /**< NBI format */
+#define DHCP_EB_FEATURE_PXE 0x21 /**< PXE format */
+#define DHCP_EB_FEATURE_ELF 0x22 /**< ELF format */
+#define DHCP_EB_FEATURE_COMBOOT 0x23 /**< COMBOOT format */
+#define DHCP_EB_FEATURE_EFI 0x24 /**< EFI format */
+#define DHCP_EB_FEATURE_FCOE 0x25 /**< FCoE protocol */
+#define DHCP_EB_FEATURE_VLAN 0x26 /**< VLAN support */
+#define DHCP_EB_FEATURE_MENU 0x27 /**< Menu support */
+
+/** @} */
+
+/** DHCP feature table */
+#define DHCP_FEATURES __table ( uint8_t, "dhcp_features" )
+
+/** Declare a feature code for DHCP */
+#define __dhcp_feature __table_entry ( DHCP_FEATURES, 01 )
+
+/** Construct a DHCP feature table entry */
+#define DHCP_FEATURE( feature_opt, ... ) \
+ _DHCP_FEATURE ( OBJECT, feature_opt, __VA_ARGS__ )
+#define _DHCP_FEATURE( _name, feature_opt, ... ) \
+ __DHCP_FEATURE ( _name, feature_opt, __VA_ARGS__ )
+#define __DHCP_FEATURE( _name, feature_opt, ... ) \
+ uint8_t __dhcp_feature_ ## _name [] __dhcp_feature = { \
+ feature_opt, DHCP_OPTION ( __VA_ARGS__ ) \
+ };
+
+/** A named feature */
+struct feature {
+ /** Feature name */
+ char *name;
+};
+
+/** Named feature table */
+#define FEATURES __table ( struct feature, "features" )
+
+/** Declare a named feature */
+#define __feature_name( category ) __table_entry ( FEATURES, category )
+
+/** Construct a named feature */
+#define FEATURE_NAME( category, text ) \
+ _FEATURE_NAME ( category, OBJECT, text )
+#define _FEATURE_NAME( category, _name, text ) \
+ __FEATURE_NAME ( category, _name, text )
+#define __FEATURE_NAME( category, _name, text ) \
+ struct feature __feature_ ## _name __feature_name ( category ) = { \
+ .name = text, \
+ };
+
+/** Declare a feature */
+#define FEATURE( category, text, feature_opt, version ) \
+ FEATURE_NAME ( category, text ); \
+ DHCP_FEATURE ( feature_opt, version );
+
+/** Declare the version number feature */
+#define FEATURE_VERSION( ... ) \
+ DHCP_FEATURE ( DHCP_ENCAPSULATED ( DHCP_EB_VERSION ), __VA_ARGS__ )
+
+#endif /* _IPXE_FEATURES_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/fip.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fip.h
new file mode 100644
index 00000000..b81e8604
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/fip.h
@@ -0,0 +1,450 @@
+#ifndef _IPXE_FIP_H
+#define _IPXE_FIP_H
+
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdint.h>
+#include <ipxe/fc.h>
+#include <ipxe/fcels.h>
+#include <ipxe/fcoe.h>
+
+/** A FIP frame header */
+struct fip_header {
+ /** Frame version */
+ uint8_t version;
+ /** Reserved */
+ uint8_t reserved_a;
+ /** Protocol code */
+ uint16_t code;
+ /** Reserved */
+ uint8_t reserved_b;
+ /** Subcode */
+ uint8_t subcode;
+ /** Descriptor list length in 32-bit words */
+ uint16_t len;
+ /** Flags */
+ uint16_t flags;
+} __attribute__ (( packed ));
+
+/** FIP frame version */
+#define FIP_VERSION 0x10
+
+/** FIP protocol code */
+enum fip_code {
+ FIP_CODE_DISCOVERY = 0x0001, /**< Discovery */
+ FIP_CODE_ELS = 0x0002, /**< Extended link services */
+ FIP_CODE_MAINTAIN = 0x0003, /**< Maintain virtual links */
+ FIP_CODE_VLAN = 0x0004, /**< VLAN */
+};
+
+/** FIP protocol subcode for discovery */
+enum fip_discovery_subcode {
+ FIP_DISCOVERY_SOLICIT = 0x01, /**< Discovery solicitation */
+ FIP_DISCOVERY_ADVERTISE = 0x02, /**< Discovery advertisement */
+};
+
+/** FIP protocol subcode for extended link services */
+enum fip_els_subcode {
+ FIP_ELS_REQUEST = 0x01, /**< ELS request */
+ FIP_ELS_RESPONSE = 0x02, /**< ELS response */
+};
+
+/** FIP protocol subcode for keep alive / clear links */
+enum fip_vitality_subcode {
+ FIP_MAINTAIN_KEEP_ALIVE = 0x01, /**< Keep alive */
+ FIP_MAINTAIN_CLEAR_LINKS = 0x02,/**< Clear virtual links */
+};
+
+/** FIP protocol subcode for VLAN */
+enum fip_vlan_subcode {
+ FIP_VLAN_REQUEST = 0x01, /**< VLAN request */
+ FIP_VLAN_NOTIFY = 0x02, /**< VLAN notification */
+};
+
+/** FIP flags */
+enum fip_flags {
+ FIP_FP = 0x8000, /**< Fabric-provided MAC address */
+ FIP_SP = 0x4000, /**< Server-provided MAC address */
+ FIP_A = 0x0004, /**< Available for login */
+ FIP_S = 0x0002, /**< Solicited */
+ FIP_F = 0x0001, /**< Forwarder */
+};
+
+/** FIP descriptor common fields */
+struct fip_common {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Reserved */
+ uint8_t reserved[2];
+} __attribute__ (( packed ));
+
+/** FIP descriptor types */
+enum fip_type {
+ FIP_RESERVED = 0x00, /**< Reserved */
+ FIP_PRIORITY = 0x01, /**< Priority */
+ FIP_MAC_ADDRESS = 0x02, /**< MAC address */
+ FIP_FC_MAP = 0x03, /**< FC-MAP */
+ FIP_NAME_ID = 0x04, /**< Name identifier */
+ FIP_FABRIC = 0x05, /**< Fabric */
+ FIP_MAX_FCOE_SIZE = 0x06, /**< Max FCoE size */
+ FIP_FLOGI = 0x07, /**< FLOGI */
+ FIP_NPIV_FDISC = 0x08, /**< NPIV FDISC */
+ FIP_LOGO = 0x09, /**< LOGO */
+ FIP_ELP = 0x0a, /**< ELP */
+ FIP_VX_PORT_ID = 0x0b, /**< Vx port identification */
+ FIP_FKA_ADV_P = 0x0c, /**< FKA ADV period */
+ FIP_VENDOR_ID = 0x0d, /**< Vendor ID */
+ FIP_VLAN = 0x0e, /**< VLAN */
+ FIP_NUM_DESCRIPTOR_TYPES
+};
+
+/** FIP descriptor type is critical */
+#define FIP_IS_CRITICAL( type ) ( (type) <= 0x7f )
+
+/** A FIP priority descriptor */
+struct fip_priority {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Reserved */
+ uint8_t reserved;
+ /** Priority
+ *
+ * A higher value indicates a lower priority.
+ */
+ uint8_t priority;
+} __attribute__ (( packed ));
+
+/** Default FIP priority */
+#define FIP_DEFAULT_PRIORITY 128
+
+/** Lowest FIP priority */
+#define FIP_LOWEST_PRIORITY 255
+
+/** A FIP MAC address descriptor */
+struct fip_mac_address {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** MAC address */
+ uint8_t mac[ETH_ALEN];
+} __attribute__ (( packed ));
+
+/** A FIP FC-MAP descriptor */
+struct fip_fc_map {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Reserved */
+ uint8_t reserved[3];
+ /** FC-MAP */
+ struct fcoe_map map;
+} __attribute__ (( packed ));
+
+/** A FIP name identifier descriptor */
+struct fip_name_id {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Reserved */
+ uint8_t reserved[2];
+ /** Name identifier */
+ struct fc_name name;
+} __attribute__ (( packed ));
+
+/** A FIP fabric descriptor */
+struct fip_fabric {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Virtual Fabric ID, if any */
+ uint16_t vf_id;
+ /** Reserved */
+ uint8_t reserved;
+ /** FC-MAP */
+ struct fcoe_map map;
+ /** Fabric name */
+ struct fc_name name;
+} __attribute__ (( packed ));
+
+/** A FIP max FCoE size descriptor */
+struct fip_max_fcoe_size {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Maximum FCoE size */
+ uint16_t mtu;
+} __attribute__ (( packed ));
+
+/** A FIP descriptor containing an encapsulated ELS frame */
+struct fip_els {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Reserved */
+ uint8_t reserved[2];
+ /** Fibre Channel frame header */
+ struct fc_frame_header fc;
+ /** ELS frame */
+ struct fc_els_frame_common els;
+} __attribute__ (( packed ));
+
+/** A FIP descriptor containing an encapsulated login frame */
+struct fip_login {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Reserved */
+ uint8_t reserved[2];
+ /** Fibre Channel frame header */
+ struct fc_frame_header fc;
+ /** ELS frame */
+ struct fc_login_frame els;
+} __attribute__ (( packed ));
+
+/** A FIP descriptor containing an encapsulated LOGO request frame */
+struct fip_logo_request {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Reserved */
+ uint8_t reserved[2];
+ /** Fibre Channel frame header */
+ struct fc_frame_header fc;
+ /** ELS frame */
+ struct fc_logout_request_frame els;
+} __attribute__ (( packed ));
+
+/** A FIP descriptor containing an encapsulated LOGO response frame */
+struct fip_logo_response {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Reserved */
+ uint8_t reserved[2];
+ /** Fibre Channel frame header */
+ struct fc_frame_header fc;
+ /** ELS frame */
+ struct fc_logout_response_frame els;
+} __attribute__ (( packed ));
+
+/** A FIP descriptor containing an encapsulated ELP frame */
+struct fip_elp {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Reserved */
+ uint8_t reserved[2];
+ /** Fibre Channel frame header */
+ struct fc_frame_header fc;
+ /** ELS frame */
+ struct fc_els_frame_common els;
+ /** Uninteresting content */
+ uint32_t dull[25];
+} __attribute__ (( packed ));
+
+/** A FIP descriptor containing an encapsulated LS_RJT frame */
+struct fip_ls_rjt {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Reserved */
+ uint8_t reserved[2];
+ /** Fibre Channel frame header */
+ struct fc_frame_header fc;
+ /** ELS frame */
+ struct fc_ls_rjt_frame els;
+} __attribute__ (( packed ));
+
+/** A FIP Vx port identification descriptor */
+struct fip_vx_port_id {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** MAC address */
+ uint8_t mac[ETH_ALEN];
+ /** Reserved */
+ uint8_t reserved;
+ /** Address identifier */
+ struct fc_port_id id;
+ /** Port name */
+ struct fc_name name;
+} __attribute__ (( packed ));
+
+/** A FIP FKA ADV period descriptor */
+struct fip_fka_adv_p {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Reserved */
+ uint8_t reserved;
+ /** Flags */
+ uint8_t flags;
+ /** Keep alive advertisement period in milliseconds */
+ uint32_t period;
+} __attribute__ (( packed ));
+
+/** FIP FKA ADV period flags */
+enum fip_fka_adv_p_flags {
+ FIP_NO_KEEPALIVE = 0x01, /**< Do not send keepalives */
+};
+
+/** A FIP vendor ID descriptor */
+struct fip_vendor_id {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** Reserved */
+ uint8_t reserved[2];
+ /** Vendor ID */
+ uint8_t vendor[8];
+} __attribute__ (( packed ));
+
+/** A FIP VLAN descriptor */
+struct fip_vlan {
+ /** Type */
+ uint8_t type;
+ /** Length in 32-bit words */
+ uint8_t len;
+ /** VLAN ID */
+ uint16_t vlan;
+} __attribute__ (( packed ));
+
+/** A FIP descriptor */
+union fip_descriptor {
+ /** Common fields */
+ struct fip_common common;
+ /** Priority descriptor */
+ struct fip_priority priority;
+ /** MAC address descriptor */
+ struct fip_mac_address mac_address;
+ /** FC-MAP descriptor */
+ struct fip_fc_map fc_map;
+ /** Name identifier descriptor */
+ struct fip_name_id name_id;
+ /** Fabric descriptor */
+ struct fip_fabric fabric;
+ /** Max FCoE size descriptor */
+ struct fip_max_fcoe_size max_fcoe_size;
+ /** FLOGI descriptor */
+ struct fip_els flogi;
+ /** FLOGI request descriptor */
+ struct fip_login flogi_request;
+ /** FLOGI LS_ACC descriptor */
+ struct fip_login flogi_ls_acc;
+ /** FLOGI LS_RJT descriptor */
+ struct fip_ls_rjt flogi_ls_rjt;
+ /** NPIV FDISC descriptor */
+ struct fip_els npiv_fdisc;
+ /** NPIV FDISC request descriptor */
+ struct fip_login npiv_fdisc_request;
+ /** NPIV FDISC LS_ACC descriptor */
+ struct fip_login npiv_fdisc_ls_acc;
+ /** NPIV FDISC LS_RJT descriptor */
+ struct fip_ls_rjt npiv_fdisc_ls_rjt;
+ /** LOGO descriptor */
+ struct fip_els logo;
+ /** LOGO request descriptor */
+ struct fip_logo_request logo_request;
+ /** LOGO LS_ACC descriptor */
+ struct fip_logo_response logo_ls_acc;
+ /** LOGO LS_RJT descriptor */
+ struct fip_ls_rjt logo_ls_rjt;
+ /** ELS descriptor */
+ struct fip_els elp;
+ /** ELP request descriptor */
+ struct fip_elp elp_request;
+ /** ELP LS_ACC descriptor */
+ struct fip_elp elp_ls_acc;
+ /** ELP LS_RJT descriptor */
+ struct fip_ls_rjt elp_ls_rjt;
+ /** Vx port identification descriptor */
+ struct fip_vx_port_id vx_port_id;
+ /** FKA ADV period descriptor */
+ struct fip_fka_adv_p fka_adv_p;
+ /** Vendor ID descriptor */
+ struct fip_vendor_id vendor_id;
+ /** VLAN descriptor */
+ struct fip_vlan vlan;
+} __attribute__ (( packed ));
+
+/** A FIP descriptor set */
+struct fip_descriptors {
+ /** Descriptors, indexed by type */
+ union fip_descriptor *desc[FIP_NUM_DESCRIPTOR_TYPES];
+};
+
+/**
+ * Define a function to extract a specific FIP descriptor type from a list
+ *
+ * @v type Descriptor type
+ * @v name Descriptor name
+ * @v finder Descriptor finder
+ */
+#define FIP_DESCRIPTOR( type, name ) \
+ static inline __attribute__ (( always_inline )) \
+ typeof ( ( ( union fip_descriptor * ) NULL )->name ) * \
+ fip_ ## name ( struct fip_descriptors *descs ) { \
+ return &(descs->desc[type]->name); \
+ }
+FIP_DESCRIPTOR ( FIP_PRIORITY, priority );
+FIP_DESCRIPTOR ( FIP_MAC_ADDRESS, mac_address );
+FIP_DESCRIPTOR ( FIP_FC_MAP, fc_map );
+FIP_DESCRIPTOR ( FIP_NAME_ID, name_id );
+FIP_DESCRIPTOR ( FIP_FABRIC, fabric );
+FIP_DESCRIPTOR ( FIP_MAX_FCOE_SIZE, max_fcoe_size );
+FIP_DESCRIPTOR ( FIP_FLOGI, flogi );
+FIP_DESCRIPTOR ( FIP_FLOGI, flogi_request );
+FIP_DESCRIPTOR ( FIP_FLOGI, flogi_ls_acc );
+FIP_DESCRIPTOR ( FIP_FLOGI, flogi_ls_rjt );
+FIP_DESCRIPTOR ( FIP_NPIV_FDISC, npiv_fdisc );
+FIP_DESCRIPTOR ( FIP_NPIV_FDISC, npiv_fdisc_request );
+FIP_DESCRIPTOR ( FIP_NPIV_FDISC, npiv_fdisc_ls_acc );
+FIP_DESCRIPTOR ( FIP_NPIV_FDISC, npiv_fdisc_ls_rjt );
+FIP_DESCRIPTOR ( FIP_LOGO, logo );
+FIP_DESCRIPTOR ( FIP_LOGO, logo_request );
+FIP_DESCRIPTOR ( FIP_LOGO, logo_ls_acc );
+FIP_DESCRIPTOR ( FIP_LOGO, logo_ls_rjt );
+FIP_DESCRIPTOR ( FIP_ELP, elp );
+FIP_DESCRIPTOR ( FIP_ELP, elp_request );
+FIP_DESCRIPTOR ( FIP_ELP, elp_ls_acc );
+FIP_DESCRIPTOR ( FIP_ELP, elp_ls_rjt );
+FIP_DESCRIPTOR ( FIP_VX_PORT_ID, vx_port_id );
+FIP_DESCRIPTOR ( FIP_FKA_ADV_P, fka_adv_p );
+FIP_DESCRIPTOR ( FIP_VENDOR_ID, vendor_id );
+FIP_DESCRIPTOR ( FIP_VLAN, vlan );
+
+#endif /* _IPXE_FIP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ftp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ftp.h
new file mode 100644
index 00000000..cbab12d2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ftp.h
@@ -0,0 +1,15 @@
+#ifndef _IPXE_FTP_H
+#define _IPXE_FTP_H
+
+/** @file
+ *
+ * File transfer protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** FTP default port */
+#define FTP_PORT 21
+
+#endif /* _IPXE_FTP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/gdbserial.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/gdbserial.h
new file mode 100644
index 00000000..a3b56173
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/gdbserial.h
@@ -0,0 +1,21 @@
+#ifndef _IPXE_GDBSERIAL_H
+#define _IPXE_GDBSERIAL_H
+
+/** @file
+ *
+ * GDB remote debugging over serial
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct gdb_transport;
+
+/**
+ * Set up the serial transport
+ *
+ * @ret transport suitable for starting the GDB stub or NULL on error
+ */
+struct gdb_transport *gdbserial_configure ( void );
+
+#endif /* _IPXE_GDBSERIAL_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/gdbstub.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/gdbstub.h
new file mode 100644
index 00000000..31960674
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/gdbstub.h
@@ -0,0 +1,77 @@
+#ifndef _IPXE_GDBSTUB_H
+#define _IPXE_GDBSTUB_H
+
+/** @file
+ *
+ * GDB remote debugging
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/tables.h>
+#include <gdbmach.h>
+
+/**
+ * A transport mechanism for the GDB protocol
+ *
+ */
+struct gdb_transport {
+ /** Transport name */
+ const char *name;
+ /**
+ * Set up the transport given a list of arguments
+ *
+ * @v argc Number of arguments
+ * @v argv Argument list
+ * @ret Return status code
+ *
+ * Note that arguments start at argv[0].
+ */
+ int ( * init ) ( int argc, char **argv );
+ /**
+ * Perform a blocking read
+ *
+ * @v buf Buffer
+ * @v len Size of buffer
+ * @ret Number of bytes read into buffer
+ */
+ size_t ( * recv ) ( char *buf, size_t len );
+ /**
+ * Write, may block
+ *
+ * @v buf Buffer
+ * @v len Size of buffer
+ */
+ void ( * send ) ( const char *buf, size_t len );
+};
+
+#define GDB_TRANSPORTS __table ( struct gdb_transport, "gdb_transports" )
+
+#define __gdb_transport __table_entry ( GDB_TRANSPORTS, 01 )
+
+/**
+ * Look up GDB transport by name
+ *
+ * @v name Name of transport
+ * @ret GDB transport or NULL
+ */
+extern struct gdb_transport *find_gdb_transport ( const char *name );
+
+/**
+ * Break into the debugger using the given transport
+ *
+ * @v trans GDB transport
+ */
+extern void gdbstub_start ( struct gdb_transport *trans );
+
+/**
+ * Interrupt handler
+ *
+ * @signo POSIX signal number
+ * @regs CPU register snapshot
+ **/
+extern void gdbstub_handler ( int signo, gdbreg_t *regs );
+
+#endif /* _IPXE_GDBSTUB_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/gdbudp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/gdbudp.h
new file mode 100644
index 00000000..db7a451c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/gdbudp.h
@@ -0,0 +1,24 @@
+#ifndef _IPXE_GDBUDP_H
+#define _IPXE_GDBUDP_H
+
+/** @file
+ *
+ * GDB remote debugging over UDP
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct sockaddr_in;
+struct gdb_transport;
+
+/**
+ * Set up the UDP transport with network address
+ *
+ * @name network device name
+ * @addr IP address and UDP listen port, may be NULL and fields may be zero
+ * @ret transport suitable for starting the GDB stub or NULL on error
+ */
+struct gdb_transport *gdbudp_configure ( const char *name, struct sockaddr_in *addr );
+
+#endif /* _IPXE_GDBUDP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/hash_df.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/hash_df.h
new file mode 100644
index 00000000..607a4a61
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/hash_df.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_HASH_DF_H
+#define _IPXE_HASH_DF_H
+
+/** @file
+ *
+ * Hash-based derivation function (Hash_df)
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/crypto.h>
+
+extern void hash_df ( struct digest_algorithm *hash, const void *input,
+ size_t input_len, void *output, size_t output_len );
+
+#endif /* _IPXE_HASH_DF_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/hidemem.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/hidemem.h
new file mode 100644
index 00000000..ddc9cd8b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/hidemem.h
@@ -0,0 +1,17 @@
+#ifndef _IPXE_HIDEMEM_H
+#define _IPXE_HIDEMEM_H
+
+/**
+ * @file
+ *
+ * Hidden memory regions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+extern void hide_umalloc ( physaddr_t start, physaddr_t end );
+
+#endif /* _IPXE_HIDEMEM_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/hmac.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/hmac.h
new file mode 100644
index 00000000..d5ec0868
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/hmac.h
@@ -0,0 +1,32 @@
+#ifndef _IPXE_HMAC_H
+#define _IPXE_HMAC_H
+
+/** @file
+ *
+ * Keyed-Hashing for Message Authentication
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/crypto.h>
+
+/**
+ * Update HMAC
+ *
+ * @v digest Digest algorithm to use
+ * @v digest_ctx Digest context
+ * @v data Data
+ * @v len Length of data
+ */
+static inline void hmac_update ( struct digest_algorithm *digest,
+ void *digest_ctx, const void *data,
+ size_t len ) {
+ digest_update ( digest, digest_ctx, data, len );
+}
+
+extern void hmac_init ( struct digest_algorithm *digest, void *digest_ctx,
+ void *key, size_t *key_len );
+extern void hmac_final ( struct digest_algorithm *digest, void *digest_ctx,
+ void *key, size_t *key_len, void *hmac );
+
+#endif /* _IPXE_HMAC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/hmac_drbg.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/hmac_drbg.h
new file mode 100644
index 00000000..8dfd2924
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/hmac_drbg.h
@@ -0,0 +1,253 @@
+#ifndef _IPXE_HMAC_DRBG_H
+#define _IPXE_HMAC_DRBG_H
+
+/** @file
+ *
+ * HMAC_DRBG algorithm
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/crypto.h>
+
+/** Declare an HMAC_DRBG algorithm
+ *
+ * @v hash Underlying hash algorithm
+ * @v max_security_strength Maxmimum security strength
+ * @v out_len_bits Output block length, in bits
+ * @ret hmac_drbg HMAC_DRBG algorithm
+ */
+#define HMAC_DRBG( hash, max_security_strength, out_len_bits ) \
+ ( hash, max_security_strength, out_len_bits )
+
+/** HMAC_DRBG using SHA-1
+ *
+ * The maximum security strength of HMAC_DRBG using SHA-1 is 128 bits
+ * according to the list of maximum security strengths documented in
+ * NIST SP 800-57 Part 1 Section 5.6.1 Table 3.
+ *
+ * The output block length of HMAC_DRBG using SHA-1 is 160 bits
+ * according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 2 (NIST SP
+ * 800-90 Section 10.1 Table 2).
+ */
+#define HMAC_DRBG_SHA1 HMAC_DRBG ( &sha1_algorithm, 128, 160 )
+
+/** HMAC_DRBG using SHA-224
+ *
+ * The maximum security strength of HMAC_DRBG using SHA-224 is 192
+ * bits according to the list of maximum security strengths documented
+ * in NIST SP 800-57 Part 1 Section 5.6.1 Table 3.
+ *
+ * The output block length of HMAC_DRBG using SHA-224 is 224 bits
+ * according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 2 (NIST SP
+ * 800-90 Section 10.1 Table 2).
+ */
+#define HMAC_DRBG_SHA224 HMAC_DRBG ( &sha224_algorithm, 192, 224 )
+
+/** HMAC_DRBG using SHA-256
+ *
+ * The maximum security strength of HMAC_DRBG using SHA-256 is 256
+ * bits according to the list of maximum security strengths documented
+ * in NIST SP 800-57 Part 1 Section 5.6.1 Table 3.
+ *
+ * The output block length of HMAC_DRBG using SHA-256 is 256 bits
+ * according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 2 (NIST SP
+ * 800-90 Section 10.1 Table 2).
+ */
+#define HMAC_DRBG_SHA256 HMAC_DRBG ( &sha256_algorithm, 256, 256 )
+
+/** HMAC_DRBG using SHA-384
+ *
+ * The maximum security strength of HMAC_DRBG using SHA-384 is 256
+ * bits according to the list of maximum security strengths documented
+ * in NIST SP 800-57 Part 1 Section 5.6.1 Table 3.
+ *
+ * The output block length of HMAC_DRBG using SHA-384 is 384 bits
+ * according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 2 (NIST SP
+ * 800-90 Section 10.1 Table 2).
+ */
+#define HMAC_DRBG_SHA384 HMAC_DRBG ( &sha384_algorithm, 256, 384 )
+
+/** HMAC_DRBG using SHA-512
+ *
+ * The maximum security strength of HMAC_DRBG using SHA-512 is 256
+ * bits according to the list of maximum security strengths documented
+ * in NIST SP 800-57 Part 1 Section 5.6.1 Table 3.
+ *
+ * The output block length of HMAC_DRBG using SHA-512 is 512 bits
+ * according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 2 (NIST SP
+ * 800-90 Section 10.1 Table 2).
+ */
+#define HMAC_DRBG_SHA512 HMAC_DRBG ( &sha512_algorithm, 256, 512 )
+
+/** Underlying hash algorithm
+ *
+ * @v hmac_drbg HMAC_DRBG algorithm
+ * @ret hash Underlying hash algorithm
+ */
+#define HMAC_DRBG_HASH( hmac_drbg ) \
+ HMAC_DRBG_EXTRACT_HASH hmac_drbg
+#define HMAC_DRBG_EXTRACT_HASH( hash, max_security_strength, out_len_bits ) \
+ hash
+
+/** Maximum security strength
+ *
+ * @v hmac_drbg HMAC_DRBG algorithm
+ * @ret max_security_strength Maxmimum security strength
+ */
+#define HMAC_DRBG_MAX_SECURITY_STRENGTH( hmac_drbg ) \
+ HMAC_DRBG_EXTRACT_MAX_SECURITY_STRENGTH hmac_drbg
+#define HMAC_DRBG_EXTRACT_MAX_SECURITY_STRENGTH( hash, max_security_strength, \
+ out_len_bits ) \
+ max_security_strength
+
+/** Output block length, in bits
+ *
+ * @v hmac_drbg HMAC_DRBG algorithm
+ * @ret out_len_bits Output block length, in bits
+ */
+#define HMAC_DRBG_OUTLEN_BITS( hmac_drbg ) \
+ HMAC_DRBG_EXTRACT_OUTLEN_BITS hmac_drbg
+#define HMAC_DRBG_EXTRACT_OUTLEN_BITS( hash, max_security_strength, \
+ out_len_bits ) \
+ out_len_bits
+
+/** Output block length, in bytes
+ *
+ * @v hmac_drbg HMAC_DRBG algorithm
+ * @ret out_len_bytes Output block length, in bytes
+ */
+#define HMAC_DRBG_OUTLEN_BYTES( hmac_drbg ) \
+ ( HMAC_DRBG_OUTLEN_BITS ( hmac_drbg ) / 8 )
+
+/** Maximum output block length, in bytes
+ *
+ * The maximum output block length for HMAC_DRBG is 512 bits for
+ * SHA-512 according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 2
+ * (NIST SP 800-90 Section 10.1 Table 2).
+ */
+#define HMAC_DRBG_MAX_OUTLEN_BYTES HMAC_DRBG_OUTLEN_BYTES ( HMAC_DRBG_SHA512 )
+
+/** Required minimum entropy for instantiate and reseed
+ *
+ * @v security_strength Security strength
+ * @ret min_entropy Required minimum entropy
+ *
+ * The minimum required entropy for HMAC_DRBG is equal to the security
+ * strength according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 2
+ * (NIST SP 800-90 Section 10.1 Table 2).
+ */
+#define HMAC_DRBG_MIN_ENTROPY( security_strength ) (security_strength)
+
+/** Minimum entropy input length
+ *
+ * @v security_strength Security strength
+ * @ret min_entropy_len_bytes Required minimum entropy length (in bytes)
+ *
+ * The minimum entropy input length for HMAC_DRBG is equal to the
+ * security strength according to ANS X9.82 Part 3-2007 Section 10.2.1
+ * Table 2 (NIST SP 800-90 Section 10.1 Table 2).
+ */
+#define HMAC_DRBG_MIN_ENTROPY_LEN_BYTES( security_strength ) \
+ ( (security_strength) / 8 )
+
+/** Maximum entropy input length
+ *
+ * The maximum entropy input length for HMAC_DRBG is 2^35 bits
+ * according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 2 (NIST SP
+ * 800-90 Section 10.1 Table 2).
+ *
+ * We choose to allow up to 32 bytes.
+ */
+#define HMAC_DRBG_MAX_ENTROPY_LEN_BYTES 32
+
+/** Maximum personalisation string length
+ *
+ * The maximum permitted personalisation string length for HMAC_DRBG
+ * is 2^35 bits according to ANS X9.82 Part 3-2007 Section 10.2.1
+ * Table 1 (NIST SP 800-90 Section 10.1 Table 2).
+ *
+ * We choose to allow up to 2^32-1 bytes (i.e. 2^35-8 bits).
+ */
+#define HMAC_DRBG_MAX_PERSONAL_LEN_BYTES 0xffffffffUL
+
+/** Maximum additional input length
+ *
+ * The maximum permitted additional input length for HMAC_DRBG is 2^35
+ * bits according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 1
+ * (NIST SP 800-90 Section 10.1 Table 2).
+ *
+ * We choose to allow up to 2^32-1 bytes (i.e. 2^35-8 bits).
+ */
+#define HMAC_DRBG_MAX_ADDITIONAL_LEN_BYTES 0xffffffffUL
+
+/** Maximum length of generated pseudorandom data per request
+ *
+ * The maximum number of bits per request for HMAC_DRBG is 2^19 bits
+ * according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 1 (NIST SP
+ * 800-90 Section 10.1 Table 2).
+ *
+ * We choose to allow up to 2^16-1 bytes (i.e. 2^19-8 bits).
+ */
+#define HMAC_DRBG_MAX_GENERATED_LEN_BYTES 0x0000ffffUL
+
+/** Reseed interval
+ *
+ * The maximum permitted reseed interval for HMAC_DRBG is 2^48
+ * according to ANS X9.82 Part 3-2007 Section 10.2.1 Table 2 (NIST SP
+ * 800-90 Section 10.1 Table 2). However, the sample implementation
+ * given in ANS X9.82 Part 3-2007 Annex E.2.1 (NIST SP 800-90 Appendix
+ * F.2) shows a reseed interval of 10000.
+ *
+ * We choose a very conservative reseed interval.
+ */
+#define HMAC_DRBG_RESEED_INTERVAL 1024
+
+/**
+ * HMAC_DRBG internal state
+ *
+ * This structure is defined by ANS X9.82 Part 3-2007 Section
+ * 10.2.2.2.1 (NIST SP 800-90 Section 10.1.2.1).
+ *
+ * The "administrative information" portions (security_strength and
+ * prediction_resistance) are design-time constants and so are not
+ * present as fields in this structure.
+ */
+struct hmac_drbg_state {
+ /** Current value
+ *
+ * "The value V of outlen bits, which is updated each time
+ * another outlen bits of output are produced"
+ */
+ uint8_t value[HMAC_DRBG_MAX_OUTLEN_BYTES];
+ /** Current key
+ *
+ * "The outlen-bit Key, which is updated at least once each
+ * time that the DRBG mechanism generates pseudorandom bits."
+ */
+ uint8_t key[HMAC_DRBG_MAX_OUTLEN_BYTES];
+ /** Reseed counter
+ *
+ * "A counter (reseed_counter) that indicates the number of
+ * requests for pseudorandom bits since instantiation or
+ * reseeding"
+ */
+ unsigned int reseed_counter;
+};
+
+extern void hmac_drbg_instantiate ( struct digest_algorithm *hash,
+ struct hmac_drbg_state *state,
+ const void *entropy, size_t entropy_len,
+ const void *personal, size_t personal_len );
+extern void hmac_drbg_reseed ( struct digest_algorithm *hash,
+ struct hmac_drbg_state *state,
+ const void *entropy, size_t entropy_len,
+ const void *additional, size_t additional_len );
+extern int hmac_drbg_generate ( struct digest_algorithm *hash,
+ struct hmac_drbg_state *state,
+ const void *additional, size_t additional_len,
+ void *data, size_t len );
+
+#endif /* _IPXE_HMAC_DRBG_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/http.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/http.h
new file mode 100644
index 00000000..cf8c0c7f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/http.h
@@ -0,0 +1,24 @@
+#ifndef _IPXE_HTTP_H
+#define _IPXE_HTTP_H
+
+/** @file
+ *
+ * Hyper Text Transport Protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** HTTP default port */
+#define HTTP_PORT 80
+
+/** HTTPS default port */
+#define HTTPS_PORT 443
+
+extern int http_open_filter ( struct interface *xfer, struct uri *uri,
+ unsigned int default_port,
+ int ( * filter ) ( struct interface *,
+ const char *,
+ struct interface ** ) );
+
+#endif /* _IPXE_HTTP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/i2c.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/i2c.h
new file mode 100644
index 00000000..c1f5a9bb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/i2c.h
@@ -0,0 +1,171 @@
+#ifndef _IPXE_I2C_H
+#define _IPXE_I2C_H
+
+/** @file
+ *
+ * I2C interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/bitbash.h>
+
+/** An I2C device
+ *
+ * An I2C device represents a specific slave device on an I2C bus. It
+ * is accessed via an I2C interface.
+ */
+struct i2c_device {
+ /** Address of this device
+ *
+ * The actual address sent on the bus will look like
+ *
+ * <start> <device address> <word address overflow> <r/w>
+ *
+ * The "word address overflow" is any excess bits from the
+ * word address, i.e. any portion that does not fit within the
+ * defined word address length.
+ */
+ unsigned int dev_addr;
+ /** Device address length, in bytes
+ *
+ * This is the number of bytes that comprise the device
+ * address, defined to be the portion that terminates with the
+ * read/write bit.
+ */
+ unsigned int dev_addr_len;
+ /** Word adddress length, in bytes
+ *
+ * This is the number of bytes that comprise the word address,
+ * defined to be the portion that starts after the read/write
+ * bit and ends before the first data byte.
+ *
+ * For some devices, this length will be zero (i.e. the word
+ * address is contained entirely within the "word address
+ * overflow").
+ */
+ unsigned int word_addr_len;
+};
+
+/** An I2C interface
+ *
+ * An I2C interface provides access to an I2C bus, via which I2C
+ * devices may be reached.
+ */
+struct i2c_interface {
+ /**
+ * Read data from I2C device
+ *
+ * @v i2c I2C interface
+ * @v i2cdev I2C device
+ * @v offset Starting offset within the device
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+ int ( * read ) ( struct i2c_interface *i2c, struct i2c_device *i2cdev,
+ unsigned int offset, uint8_t *data,
+ unsigned int len );
+ /**
+ * Write data to I2C device
+ *
+ * @v i2c I2C interface
+ * @v i2cdev I2C device
+ * @v offset Starting offset within the device
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+ int ( * write ) ( struct i2c_interface *i2c, struct i2c_device *i2cdev,
+ unsigned int offset, const uint8_t *data,
+ unsigned int len );
+};
+
+/** A bit-bashing I2C interface
+ *
+ * This provides a standardised way to construct I2C buses via a
+ * bit-bashing interface.
+ */
+struct i2c_bit_basher {
+ /** I2C interface */
+ struct i2c_interface i2c;
+ /** Bit-bashing interface */
+ struct bit_basher basher;
+};
+
+/** Ten-bit address marker
+ *
+ * This value is ORed with the I2C device address to indicate a
+ * ten-bit address format on the bus.
+ */
+#define I2C_TENBIT_ADDRESS 0x7800
+
+/** An I2C write command */
+#define I2C_WRITE 0
+
+/** An I2C read command */
+#define I2C_READ 1
+
+/** Bit indices used for I2C bit-bashing interface */
+enum {
+ /** Serial clock */
+ I2C_BIT_SCL = 0,
+ /** Serial data */
+ I2C_BIT_SDA,
+};
+
+/** Delay required for bit-bashing operation */
+#define I2C_UDELAY 5
+
+/** Maximum number of cycles to use when attempting a bus reset */
+#define I2C_RESET_MAX_CYCLES 32
+
+/**
+ * Check presence of I2C device
+ *
+ * @v i2c I2C interface
+ * @v i2cdev I2C device
+ * @ret rc Return status code
+ *
+ * Checks for the presence of the device on the I2C bus by attempting
+ * a zero-length write.
+ */
+static inline int i2c_check_presence ( struct i2c_interface *i2c,
+ struct i2c_device *i2cdev ) {
+ return i2c->write ( i2c, i2cdev, 0, NULL, 0 );
+}
+
+extern int init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit,
+ struct bit_basher_operations *bash_op );
+
+/**
+ * Initialise generic I2C EEPROM device
+ *
+ * @v i2cdev I2C device
+ */
+static inline __always_inline void
+init_i2c_eeprom ( struct i2c_device *i2cdev, unsigned int dev_addr ) {
+ i2cdev->dev_addr = dev_addr;
+ i2cdev->dev_addr_len = 1;
+ i2cdev->word_addr_len = 1;
+}
+
+/**
+ * Initialise Atmel AT24C11
+ *
+ * @v i2cdev I2C device
+ */
+static inline __always_inline void
+init_at24c11 ( struct i2c_device *i2cdev ) {
+ /* This chip has no device address; it must be the only chip
+ * on the bus. The word address is contained entirely within
+ * the device address field.
+ */
+ i2cdev->dev_addr = 0;
+ i2cdev->dev_addr_len = 1;
+ i2cdev->word_addr_len = 0;
+}
+
+#endif /* _IPXE_I2C_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_cm.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_cm.h
new file mode 100644
index 00000000..7d08cd9b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_cm.h
@@ -0,0 +1,72 @@
+#ifndef _IPXE_IB_CM_H
+#define _IPXE_IB_CM_H
+
+/** @file
+ *
+ * Infiniband communication management
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/infiniband.h>
+#include <ipxe/retry.h>
+
+struct ib_mad_transaction;
+struct ib_connection;
+
+/** Infiniband connection operations */
+struct ib_connection_operations {
+ /** Handle change of connection status
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v conn Connection
+ * @v rc Connection status code
+ * @v private_data Private data, if available
+ * @v private_data_len Length of private data
+ */
+ void ( * changed ) ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_connection *conn, int rc,
+ void *private_data, size_t private_data_len );
+};
+
+/** An Infiniband connection */
+struct ib_connection {
+ /** Infiniband device */
+ struct ib_device *ibdev;
+ /** Queue pair */
+ struct ib_queue_pair *qp;
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Remote communication ID */
+ uint32_t remote_id;
+ /** Target service ID */
+ union ib_guid service_id;
+ /** Connection operations */
+ struct ib_connection_operations *op;
+
+ /** List of connections */
+ struct list_head list;
+
+ /** Path to target */
+ struct ib_path *path;
+ /** Connection request management transaction */
+ struct ib_mad_transaction *madx;
+
+ /** Length of connection request private data */
+ size_t private_data_len;
+ /** Connection request private data */
+ uint8_t private_data[0];
+};
+
+extern struct ib_connection *
+ib_create_conn ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ union ib_gid *dgid, union ib_guid *service_id,
+ void *req_private_data, size_t req_private_data_len,
+ struct ib_connection_operations *op );
+extern void ib_destroy_conn ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_connection *conn );
+
+#endif /* _IPXE_IB_CM_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_cmrc.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_cmrc.h
new file mode 100644
index 00000000..47ad27fa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_cmrc.h
@@ -0,0 +1,20 @@
+#ifndef _IPXE_IB_CMRC_H
+#define _IPXE_IB_CMRC_H
+
+/** @file
+ *
+ * Infiniband Communication-managed Reliable Connections
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <ipxe/infiniband.h>
+#include <ipxe/xfer.h>
+
+extern int ib_cmrc_open ( struct interface *xfer,
+ struct ib_device *ibdev,
+ union ib_gid *dgid,
+ union ib_guid *service_id );
+
+#endif /* _IPXE_IB_CMRC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_mad.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_mad.h
new file mode 100644
index 00000000..b8694833
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_mad.h
@@ -0,0 +1,591 @@
+#ifndef _IPXE_IB_MAD_H
+#define _IPXE_IB_MAD_H
+
+/** @file
+ *
+ * Infiniband management datagrams
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/ib_packet.h>
+
+/*****************************************************************************
+ *
+ * Subnet management MADs
+ *
+ *****************************************************************************
+ */
+
+/** A subnet management header
+ *
+ * Defined in sections 14.2.1.1 and 14.2.1.2 of the IBA.
+ */
+struct ib_smp_hdr {
+ uint64_t mkey;
+ uint16_t slid;
+ uint16_t dlid;
+ uint8_t reserved[28];
+} __attribute__ (( packed ));
+
+/** Subnet management class version */
+#define IB_SMP_CLASS_VERSION 1
+
+/** Subnet management direction bit
+ *
+ * This bit resides in the "status" field in the MAD header.
+ */
+#define IB_SMP_STATUS_D_INBOUND 0x8000
+
+/* Subnet management attributes */
+#define IB_SMP_ATTR_NOTICE 0x0002
+#define IB_SMP_ATTR_NODE_DESC 0x0010
+#define IB_SMP_ATTR_NODE_INFO 0x0011
+#define IB_SMP_ATTR_SWITCH_INFO 0x0012
+#define IB_SMP_ATTR_GUID_INFO 0x0014
+#define IB_SMP_ATTR_PORT_INFO 0x0015
+#define IB_SMP_ATTR_PKEY_TABLE 0x0016
+#define IB_SMP_ATTR_SL_TO_VL_TABLE 0x0017
+#define IB_SMP_ATTR_VL_ARB_TABLE 0x0018
+#define IB_SMP_ATTR_LINEAR_FORWARD_TABLE 0x0019
+#define IB_SMP_ATTR_RANDOM_FORWARD_TABLE 0x001A
+#define IB_SMP_ATTR_MCAST_FORWARD_TABLE 0x001B
+#define IB_SMP_ATTR_SM_INFO 0x0020
+#define IB_SMP_ATTR_VENDOR_DIAG 0x0030
+#define IB_SMP_ATTR_LED_INFO 0x0031
+#define IB_SMP_ATTR_VENDOR_MASK 0xFF00
+
+/**
+ * A Node Description attribute
+ *
+ * Defined in section 14.2.5.2 of the IBA
+ */
+struct ib_node_desc {
+ char node_string[64];
+} __attribute__ (( packed ));
+
+/** A Node Information attribute
+ *
+ * Defined in section 14.2.5.3 of the IBA.
+ */
+struct ib_node_info {
+ uint8_t base_version;
+ uint8_t class_version;
+ uint8_t node_type;
+ uint8_t num_ports;
+ union ib_guid sys_guid;
+ union ib_guid node_guid;
+ union ib_guid port_guid;
+ uint16_t partition_cap;
+ uint16_t device_id;
+ uint32_t revision;
+ uint8_t local_port_num;
+ uint8_t vendor_id[3];
+} __attribute__ ((packed));
+
+#define IB_NODE_TYPE_HCA 0x01
+#define IB_NODE_TYPE_SWITCH 0x02
+#define IB_NODE_TYPE_ROUTER 0x03
+
+/** A GUID Information attribute
+ *
+ * Defined in section 14.2.5.5 of the IBA.
+ */
+struct ib_guid_info {
+ uint8_t guid[8][8];
+} __attribute__ (( packed ));
+
+/** A Port Information attribute
+ *
+ * Defined in section 14.2.5.6 of the IBA.
+ */
+struct ib_port_info {
+ uint64_t mkey;
+ uint8_t gid_prefix[8];
+ uint16_t lid;
+ uint16_t mastersm_lid;
+ uint32_t cap_mask;
+ uint16_t diag_code;
+ uint16_t mkey_lease_period;
+ uint8_t local_port_num;
+ uint8_t link_width_enabled;
+ uint8_t link_width_supported;
+ uint8_t link_width_active;
+ uint8_t link_speed_supported__port_state;
+ uint8_t port_phys_state__link_down_def_state;
+ uint8_t mkey_prot_bits__lmc;
+ uint8_t link_speed_active__link_speed_enabled;
+ uint8_t neighbour_mtu__mastersm_sl;
+ uint8_t vl_cap__init_type;
+ uint8_t vl_high_limit;
+ uint8_t vl_arbitration_high_cap;
+ uint8_t vl_arbitration_low_cap;
+ uint8_t init_type_reply__mtu_cap;
+ uint8_t vl_stall_count__hoq_life;
+ uint8_t operational_vls__enforcement;
+ uint16_t mkey_violations;
+ uint16_t pkey_violations;
+ uint16_t qkey_violations;
+ uint8_t guid_cap;
+ uint8_t client_reregister__subnet_timeout;
+ uint8_t resp_time_value;
+ uint8_t local_phy_errors__overrun_errors;
+ uint16_t max_credit_hint;
+ uint32_t link_round_trip_latency;
+} __attribute__ (( packed ));
+
+#define IB_LINK_WIDTH_1X 0x01
+#define IB_LINK_WIDTH_4X 0x02
+#define IB_LINK_WIDTH_8X 0x04
+#define IB_LINK_WIDTH_12X 0x08
+
+#define IB_LINK_SPEED_SDR 0x01
+#define IB_LINK_SPEED_DDR 0x02
+#define IB_LINK_SPEED_QDR 0x04
+
+#define IB_PORT_STATE_DOWN 0x01
+#define IB_PORT_STATE_INIT 0x02
+#define IB_PORT_STATE_ARMED 0x03
+#define IB_PORT_STATE_ACTIVE 0x04
+
+#define IB_PORT_PHYS_STATE_SLEEP 0x01
+#define IB_PORT_PHYS_STATE_POLLING 0x02
+
+#define IB_MTU_256 0x01
+#define IB_MTU_512 0x02
+#define IB_MTU_1024 0x03
+#define IB_MTU_2048 0x04
+#define IB_MTU_4096 0x05
+
+#define IB_VL_0 0x01
+#define IB_VL_0_1 0x02
+#define IB_VL_0_3 0x03
+#define IB_VL_0_7 0x04
+#define IB_VL_0_14 0x05
+
+/** A Partition Key Table attribute
+ *
+ * Defined in section 14.2.5.7 of the IBA.
+ */
+struct ib_pkey_table {
+ uint16_t pkey[32];
+} __attribute__ (( packed ));
+
+/** A subnet management attribute */
+union ib_smp_data {
+ struct ib_node_desc node_desc;
+ struct ib_node_info node_info;
+ struct ib_guid_info guid_info;
+ struct ib_port_info port_info;
+ struct ib_pkey_table pkey_table;
+ uint8_t bytes[64];
+} __attribute__ (( packed ));
+
+/** A subnet management directed route path */
+struct ib_smp_dr_path {
+ uint8_t hops[64];
+} __attribute__ (( packed ));
+
+/** Subnet management MAD class-specific data */
+struct ib_smp_class_specific {
+ uint8_t hop_pointer;
+ uint8_t hop_count;
+} __attribute__ (( packed ));
+
+/*****************************************************************************
+ *
+ * Subnet administration MADs
+ *
+ *****************************************************************************
+ */
+
+#define IB_SA_CLASS_VERSION 2
+
+#define IB_SA_METHOD_DELETE_RESP 0x95
+
+struct ib_rmpp_hdr {
+ uint32_t raw[3];
+} __attribute__ (( packed ));
+
+struct ib_sa_hdr {
+ uint32_t sm_key[2];
+ uint16_t reserved;
+ uint16_t attrib_offset;
+ uint32_t comp_mask[2];
+} __attribute__ (( packed ));
+
+#define IB_SA_ATTR_MC_MEMBER_REC 0x38
+#define IB_SA_ATTR_PATH_REC 0x35
+
+struct ib_path_record {
+ uint32_t reserved0[2];
+ union ib_gid dgid;
+ union ib_gid sgid;
+ uint16_t dlid;
+ uint16_t slid;
+ uint32_t hop_limit__flow_label__raw_traffic;
+ uint32_t pkey__numb_path__reversible__tclass;
+ uint8_t reserved1;
+ uint8_t reserved__sl;
+ uint8_t mtu_selector__mtu;
+ uint8_t rate_selector__rate;
+ uint32_t preference__packet_lifetime__packet_lifetime_selector;
+ uint32_t reserved2[35];
+} __attribute__ (( packed ));
+
+#define IB_SA_PATH_REC_DGID (1<<2)
+#define IB_SA_PATH_REC_SGID (1<<3)
+
+struct ib_mc_member_record {
+ union ib_gid mgid;
+ union ib_gid port_gid;
+ uint32_t qkey;
+ uint16_t mlid;
+ uint8_t mtu_selector__mtu;
+ uint8_t tclass;
+ uint16_t pkey;
+ uint8_t rate_selector__rate;
+ uint8_t packet_lifetime_selector__packet_lifetime;
+ uint32_t sl__flow_label__hop_limit;
+ uint8_t scope__join_state;
+ uint8_t proxy_join__reserved;
+ uint16_t reserved0;
+ uint32_t reserved1[37];
+} __attribute__ (( packed ));
+
+#define IB_SA_MCMEMBER_REC_MGID (1<<0)
+#define IB_SA_MCMEMBER_REC_PORT_GID (1<<1)
+#define IB_SA_MCMEMBER_REC_QKEY (1<<2)
+#define IB_SA_MCMEMBER_REC_MLID (1<<3)
+#define IB_SA_MCMEMBER_REC_MTU_SELECTOR (1<<4)
+#define IB_SA_MCMEMBER_REC_MTU (1<<5)
+#define IB_SA_MCMEMBER_REC_TRAFFIC_CLASS (1<<6)
+#define IB_SA_MCMEMBER_REC_PKEY (1<<7)
+#define IB_SA_MCMEMBER_REC_RATE_SELECTOR (1<<8)
+#define IB_SA_MCMEMBER_REC_RATE (1<<9)
+#define IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME_SELECTOR (1<<10)
+#define IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME (1<<11)
+#define IB_SA_MCMEMBER_REC_SL (1<<12)
+#define IB_SA_MCMEMBER_REC_FLOW_LABEL (1<<13)
+#define IB_SA_MCMEMBER_REC_HOP_LIMIT (1<<14)
+#define IB_SA_MCMEMBER_REC_SCOPE (1<<15)
+#define IB_SA_MCMEMBER_REC_JOIN_STATE (1<<16)
+#define IB_SA_MCMEMBER_REC_PROXY_JOIN (1<<17)
+
+union ib_sa_data {
+ struct ib_path_record path_record;
+ struct ib_mc_member_record mc_member_record;
+} __attribute__ (( packed ));
+
+/*****************************************************************************
+ *
+ * Communication management MADs
+ *
+ *****************************************************************************
+ */
+
+/** Communication management class version */
+#define IB_CM_CLASS_VERSION 2
+
+/* Communication management attributes */
+#define IB_CM_ATTR_CLASS_PORT_INFO 0x0001
+#define IB_CM_ATTR_CONNECT_REQUEST 0x0010
+#define IB_CM_ATTR_MSG_RCPT_ACK 0x0011
+#define IB_CM_ATTR_CONNECT_REJECT 0x0012
+#define IB_CM_ATTR_CONNECT_REPLY 0x0013
+#define IB_CM_ATTR_READY_TO_USE 0x0014
+#define IB_CM_ATTR_DISCONNECT_REQUEST 0x0015
+#define IB_CM_ATTR_DISCONNECT_REPLY 0x0016
+#define IB_CM_ATTR_SERVICE_ID_RES_REQ 0x0016
+#define IB_CM_ATTR_SERVICE_ID_RES_REQ_RESP 0x0018
+#define IB_CM_ATTR_LOAD_ALTERNATE_PATH 0x0019
+#define IB_CM_ATTR_ALTERNATE_PATH_RESPONSE 0x001a
+
+/** Communication management common fields */
+struct ib_cm_common {
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Remote communication ID */
+ uint32_t remote_id;
+ /** Reserved */
+ uint8_t reserved[224];
+} __attribute__ (( packed ));
+
+/** A communication management path */
+struct ib_cm_path {
+ /** Local port LID */
+ uint16_t local_lid;
+ /** Remote port LID */
+ uint16_t remote_lid;
+ /** Local port GID */
+ union ib_gid local_gid;
+ /** Remote port GID */
+ union ib_gid remote_gid;
+ /** Flow label and rate */
+ uint32_t flow_label__rate;
+ /** Traffic class */
+ uint8_t tc;
+ /** Hop limit */
+ uint8_t hop_limit;
+ /** SL and subnet local*/
+ uint8_t sl__subnet_local;
+ /** Local ACK timeout */
+ uint8_t local_ack_timeout;
+} __attribute__ (( packed ));
+
+/** A communication management connection request
+ *
+ * Defined in section 12.6.5 of the IBA.
+ */
+struct ib_cm_connect_request {
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Reserved */
+ uint32_t reserved0[1];
+ /** Service ID */
+ union ib_guid service_id;
+ /** Local CA GUID */
+ union ib_guid local_ca;
+ /** Reserved */
+ uint32_t reserved1[1];
+ /** Local queue key */
+ uint32_t local_qkey;
+ /** Local QPN and responder resources*/
+ uint32_t local_qpn__responder_resources;
+ /** Local EECN and initiator depth */
+ uint32_t local_eecn__initiator_depth;
+ /** Remote EECN, remote CM response timeout, transport service
+ * type, EE flow control
+ */
+ uint32_t remote_eecn__remote_timeout__service_type__ee_flow_ctrl;
+ /** Starting PSN, local CM response timeout and retry count */
+ uint32_t starting_psn__local_timeout__retry_count;
+ /** Partition key */
+ uint16_t pkey;
+ /** Path packet payload MTU, RDC exists, RNR retry count */
+ uint8_t payload_mtu__rdc_exists__rnr_retry;
+ /** Max CM retries and SRQ */
+ uint8_t max_cm_retries__srq;
+ /** Primary path */
+ struct ib_cm_path primary;
+ /** Alternate path */
+ struct ib_cm_path alternate;
+ /** Private data */
+ uint8_t private_data[92];
+} __attribute__ (( packed ));
+
+/** CM transport types */
+#define IB_CM_TRANSPORT_RC 0
+#define IB_CM_TRANSPORT_UC 1
+#define IB_CM_TRANSPORT_RD 2
+
+/** A communication management connection rejection
+ *
+ * Defined in section 12.6.7 of the IBA.
+ */
+struct ib_cm_connect_reject {
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Remote communication ID */
+ uint32_t remote_id;
+ /** Message rejected */
+ uint8_t message;
+ /** Reject information length */
+ uint8_t info_len;
+ /** Rejection reason */
+ uint16_t reason;
+ /** Additional rejection information */
+ uint8_t info[72];
+ /** Private data */
+ uint8_t private_data[148];
+} __attribute__ (( packed ));
+
+/** CM rejection reasons */
+#define IB_CM_REJECT_BAD_SERVICE_ID 8
+#define IB_CM_REJECT_STALE_CONN 10
+#define IB_CM_REJECT_CONSUMER 28
+
+/** A communication management connection reply
+ *
+ * Defined in section 12.6.8 of the IBA.
+ */
+struct ib_cm_connect_reply {
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Remote communication ID */
+ uint32_t remote_id;
+ /** Local queue key */
+ uint32_t local_qkey;
+ /** Local QPN */
+ uint32_t local_qpn;
+ /** Local EECN */
+ uint32_t local_eecn;
+ /** Starting PSN */
+ uint32_t starting_psn;
+ /** Responder resources */
+ uint8_t responder_resources;
+ /** Initiator depth */
+ uint8_t initiator_depth;
+ /** Target ACK delay, failover accepted, and end-to-end flow control */
+ uint8_t target_ack_delay__failover_accepted__ee_flow_ctrl;
+ /** RNR retry count, SRQ */
+ uint8_t rnr_retry__srq;
+ /** Local CA GUID */
+ union ib_guid local_ca;
+ /** Private data */
+ uint8_t private_data[196];
+} __attribute__ (( packed ));
+
+/** A communication management ready to use reply
+ *
+ * Defined in section 12.6.9 of the IBA.
+ */
+struct ib_cm_ready_to_use {
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Remote communication ID */
+ uint32_t remote_id;
+ /** Private data */
+ uint8_t private_data[224];
+} __attribute__ (( packed ));
+
+/** A communication management disconnection request
+ *
+ * Defined in section 12.6.10 of the IBA.
+ */
+struct ib_cm_disconnect_request {
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Remote communication ID */
+ uint32_t remote_id;
+ /** Remote QPN/EECN */
+ uint32_t remote_qpn_eecn;
+ /** Private data */
+ uint8_t private_data[220];
+} __attribute__ (( packed ));
+
+/** A communication management disconnection reply
+ *
+ * Defined in section 12.6.11 of the IBA.
+ */
+struct ib_cm_disconnect_reply {
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Remote communication ID */
+ uint32_t remote_id;
+ /** Private data */
+ uint8_t private_data[224];
+} __attribute__ (( packed ));
+
+/** A communication management attribute */
+union ib_cm_data {
+ struct ib_cm_common common;
+ struct ib_cm_connect_request connect_request;
+ struct ib_cm_connect_reject connect_reject;
+ struct ib_cm_connect_reply connect_reply;
+ struct ib_cm_ready_to_use ready_to_use;
+ struct ib_cm_disconnect_request disconnect_request;
+ struct ib_cm_disconnect_reply disconnect_reply;
+ uint8_t bytes[232];
+} __attribute__ (( packed ));
+
+/*****************************************************************************
+ *
+ * MADs
+ *
+ *****************************************************************************
+ */
+
+/** Management datagram class_specific data */
+union ib_mad_class_specific {
+ uint16_t raw;
+ struct ib_smp_class_specific smp;
+} __attribute__ (( packed ));
+
+/** A management datagram common header
+ *
+ * Defined in section 13.4.2 of the IBA.
+ */
+struct ib_mad_hdr {
+ uint8_t base_version;
+ uint8_t mgmt_class;
+ uint8_t class_version;
+ uint8_t method;
+ uint16_t status;
+ union ib_mad_class_specific class_specific;
+ uint32_t tid[2];
+ uint16_t attr_id;
+ uint8_t reserved[2];
+ uint32_t attr_mod;
+} __attribute__ (( packed ));
+
+/* Management base version */
+#define IB_MGMT_BASE_VERSION 1
+
+/* Management classes */
+#define IB_MGMT_CLASS_SUBN_LID_ROUTED 0x01
+#define IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE 0x81
+#define IB_MGMT_CLASS_SUBN_ADM 0x03
+#define IB_MGMT_CLASS_PERF_MGMT 0x04
+#define IB_MGMT_CLASS_BM 0x05
+#define IB_MGMT_CLASS_DEVICE_MGMT 0x06
+#define IB_MGMT_CLASS_CM 0x07
+#define IB_MGMT_CLASS_SNMP 0x08
+#define IB_MGMT_CLASS_VENDOR_RANGE2_START 0x30
+#define IB_MGMT_CLASS_VENDOR_RANGE2_END 0x4f
+
+#define IB_MGMT_CLASS_MASK 0x7f
+
+/* Management methods */
+#define IB_MGMT_METHOD_GET 0x01
+#define IB_MGMT_METHOD_SET 0x02
+#define IB_MGMT_METHOD_GET_RESP 0x81
+#define IB_MGMT_METHOD_SEND 0x03
+#define IB_MGMT_METHOD_TRAP 0x05
+#define IB_MGMT_METHOD_REPORT 0x06
+#define IB_MGMT_METHOD_REPORT_RESP 0x86
+#define IB_MGMT_METHOD_TRAP_REPRESS 0x07
+#define IB_MGMT_METHOD_DELETE 0x15
+
+/* Status codes */
+#define IB_MGMT_STATUS_OK 0x0000
+#define IB_MGMT_STATUS_BAD_VERSION 0x0001
+#define IB_MGMT_STATUS_UNSUPPORTED_METHOD 0x0002
+#define IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR 0x0003
+#define IB_MGMT_STATUS_INVALID_VALUE 0x0004
+
+/** A subnet management MAD */
+struct ib_mad_smp {
+ struct ib_mad_hdr mad_hdr;
+ struct ib_smp_hdr smp_hdr;
+ union ib_smp_data smp_data;
+ struct ib_smp_dr_path initial_path;
+ struct ib_smp_dr_path return_path;
+} __attribute__ (( packed ));
+
+/** A subnet administration MAD */
+struct ib_mad_sa {
+ struct ib_mad_hdr mad_hdr;
+ struct ib_rmpp_hdr rmpp_hdr;
+ struct ib_sa_hdr sa_hdr;
+ union ib_sa_data sa_data;
+} __attribute__ (( packed ));
+
+/** A communication management MAD */
+struct ib_mad_cm {
+ struct ib_mad_hdr mad_hdr;
+ union ib_cm_data cm_data;
+} __attribute__ (( packed ));
+
+/** A management datagram */
+union ib_mad {
+ struct ib_mad_hdr hdr;
+ struct ib_mad_smp smp;
+ struct ib_mad_sa sa;
+ struct ib_mad_cm cm;
+ uint8_t bytes[256];
+} __attribute__ (( packed ));
+
+#endif /* _IPXE_IB_MAD_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_mcast.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_mcast.h
new file mode 100644
index 00000000..a5c22a03
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_mcast.h
@@ -0,0 +1,48 @@
+#ifndef _IPXE_IB_MCAST_H
+#define _IPXE_IB_MCAST_H
+
+/** @file
+ *
+ * Infiniband multicast groups
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/infiniband.h>
+
+struct ib_mad_transaction;
+
+/** An Infiniband multicast group membership */
+struct ib_mc_membership {
+ /** Queue pair */
+ struct ib_queue_pair *qp;
+ /** Multicast GID */
+ union ib_gid gid;
+ /** Multicast group join transaction */
+ struct ib_mad_transaction *madx;
+ /** Handle join success/failure
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v membership Multicast group membership
+ * @v rc Status code
+ * @v mad Response MAD (or NULL on error)
+ */
+ void ( * complete ) ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_mc_membership *membership, int rc,
+ union ib_mad *mad );
+};
+
+extern int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_mc_membership *membership,
+ union ib_gid *gid,
+ void ( * joined ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_mc_membership *memb,
+ int rc, union ib_mad *mad ) );
+
+extern void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_mc_membership *membership );
+
+#endif /* _IPXE_IB_MCAST_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_mi.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_mi.h
new file mode 100644
index 00000000..5c5415b7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_mi.h
@@ -0,0 +1,135 @@
+#ifndef _IPXE_IB_MI_H
+#define _IPXE_IB_MI_H
+
+/** @file
+ *
+ * Infiniband management interfaces
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/list.h>
+#include <ipxe/retry.h>
+#include <ipxe/tables.h>
+#include <ipxe/infiniband.h>
+
+struct ib_mad_interface;
+struct ib_mad_transaction;
+
+/** An Infiniband management agent */
+struct ib_mad_agent {
+ /** Management class */
+ uint8_t mgmt_class;
+ /** Class version */
+ uint8_t class_version;
+ /** Attribute (in network byte order) */
+ uint16_t attr_id;
+ /** Handle MAD
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ * @ret rc Return status code
+ */
+ void ( * handle ) ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av );
+};
+
+/** Infiniband management agents */
+#define IB_MAD_AGENTS __table ( struct ib_mad_agent, "ib_mad_agents" )
+
+/** Declare an Infiniband management agent */
+#define __ib_mad_agent __table_entry ( IB_MAD_AGENTS, 01 )
+
+/** Infiniband management transaction operations */
+struct ib_mad_transaction_operations {
+ /** Handle transaction completion
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v madx Management transaction
+ * @v rc Status code
+ * @v mad Received MAD (or NULL on error)
+ * @v av Source address vector (or NULL on error)
+ *
+ * The completion handler should in most cases call
+ * ib_destroy_madx() to free up the completed transaction.
+ */
+ void ( * complete ) ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ struct ib_mad_transaction *madx,
+ int rc, union ib_mad *mad,
+ struct ib_address_vector *av );
+};
+
+/** An Infiniband management transaction */
+struct ib_mad_transaction {
+ /** Associated management interface */
+ struct ib_mad_interface *mi;
+ /** List of transactions */
+ struct list_head list;
+ /** Retry timer */
+ struct retry_timer timer;
+ /** Destination address vector */
+ struct ib_address_vector av;
+ /** MAD being sent */
+ union ib_mad mad;
+ /** Transaction operations */
+ struct ib_mad_transaction_operations *op;
+ /** Owner private data */
+ void *owner_priv;
+};
+
+/** An Infiniband management interface */
+struct ib_mad_interface {
+ /** Infiniband device */
+ struct ib_device *ibdev;
+ /** Completion queue */
+ struct ib_completion_queue *cq;
+ /** Queue pair */
+ struct ib_queue_pair *qp;
+ /** List of management transactions */
+ struct list_head madx;
+};
+
+/**
+ * Set Infiniband management transaction owner-private data
+ *
+ * @v madx Management transaction
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_madx_set_ownerdata ( struct ib_mad_transaction *madx, void *priv ) {
+ madx->owner_priv = priv;
+}
+
+/**
+ * Get Infiniband management transaction owner-private data
+ *
+ * @v madx Management transaction
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_madx_get_ownerdata ( struct ib_mad_transaction *madx ) {
+ return madx->owner_priv;
+}
+
+extern int ib_mi_send ( struct ib_device *ibdev, struct ib_mad_interface *mi,
+ union ib_mad *mad, struct ib_address_vector *av );
+extern struct ib_mad_transaction *
+ib_create_madx ( struct ib_device *ibdev, struct ib_mad_interface *mi,
+ union ib_mad *mad, struct ib_address_vector *av,
+ struct ib_mad_transaction_operations *op );
+extern void ib_destroy_madx ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ struct ib_mad_transaction *madx );
+extern struct ib_mad_interface * ib_create_mi ( struct ib_device *ibdev,
+ enum ib_queue_pair_type type );
+extern void ib_destroy_mi ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi );
+
+#endif /* _IPXE_IB_MI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_packet.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_packet.h
new file mode 100644
index 00000000..4bd33576
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_packet.h
@@ -0,0 +1,160 @@
+#ifndef _IPXE_IB_PACKET_H
+#define _IPXE_IB_PACKET_H
+
+/** @file
+ *
+ * Infiniband packet format
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct ib_device;
+struct ib_queue_pair;
+struct ib_address_vector;
+struct io_buffer;
+
+/** An Infiniband Globally Unique Identifier */
+union ib_guid {
+ uint8_t bytes[8];
+ uint16_t words[4];
+ uint32_t dwords[2];
+};
+
+/** Infiniband Globally Unique Identifier debug message format */
+#define IB_GUID_FMT "%08x:%08x"
+
+/** Infiniband Globally Unique Identifier debug message arguments */
+#define IB_GUID_ARGS( guid ) \
+ ntohl ( (guid)->dwords[0] ), ntohl ( (guid)->dwords[1] )
+
+/** An Infiniband Global Identifier */
+union ib_gid {
+ uint8_t bytes[16];
+ uint16_t words[8];
+ uint32_t dwords[4];
+ struct {
+ union ib_guid prefix;
+ union ib_guid guid;
+ } s;
+};
+
+/** Infiniband Global Identifier debug message format */
+#define IB_GID_FMT IB_GUID_FMT ":" IB_GUID_FMT
+
+/** Infiniband Global Identifier debug message arguments */
+#define IB_GID_ARGS( gid ) \
+ IB_GUID_ARGS ( &(gid)->s.prefix ), IB_GUID_ARGS ( &(gid)->s.guid )
+
+/** An Infiniband Local Route Header */
+struct ib_local_route_header {
+ /** Virtual lane and link version */
+ uint8_t vl__lver;
+ /** Service level and next link header */
+ uint8_t sl__lnh;
+ /** Destination LID */
+ uint16_t dlid;
+ /** Packet length */
+ uint16_t length;
+ /** Source LID */
+ uint16_t slid;
+} __attribute__ (( packed ));
+
+/** Infiniband virtual lanes */
+enum ib_vl {
+ IB_VL_DEFAULT = 0,
+ IB_VL_SMP = 15,
+};
+
+/** An Infiniband Link Next Header value */
+enum ib_lnh {
+ IB_LNH_RAW = 0,
+ IB_LNH_IPv6 = 1,
+ IB_LNH_BTH = 2,
+ IB_LNH_GRH = 3
+};
+
+/** Default Infiniband LID */
+#define IB_LID_NONE 0xffff
+
+/** Test for multicast LID */
+#define IB_LID_MULTICAST( lid ) ( ( (lid) >= 0xc000 ) && ( (lid) <= 0xfffe ) )
+
+/** An Infiniband Global Route Header */
+struct ib_global_route_header {
+ /** IP version, traffic class, and flow label
+ *
+ * 4 bits : Version of the GRH
+ * 8 bits : Traffic class
+ * 20 bits : Flow label
+ */
+ uint32_t ipver__tclass__flowlabel;
+ /** Payload length */
+ uint16_t paylen;
+ /** Next header */
+ uint8_t nxthdr;
+ /** Hop limit */
+ uint8_t hoplmt;
+ /** Source GID */
+ union ib_gid sgid;
+ /** Destiniation GID */
+ union ib_gid dgid;
+} __attribute__ (( packed ));
+
+#define IB_GRH_IPVER_IPv6 0x06
+#define IB_GRH_NXTHDR_IBA 0x1b
+
+/** An Infiniband Base Transport Header */
+struct ib_base_transport_header {
+ /** Opcode */
+ uint8_t opcode;
+ /** Transport header version, pad count, migration and solicitation */
+ uint8_t se__m__padcnt__tver;
+ /** Partition key */
+ uint16_t pkey;
+ /** Destination queue pair */
+ uint32_t dest_qp;
+ /** Packet sequence number and acknowledge request */
+ uint32_t ack__psn;
+} __attribute__ (( packed ));
+
+/** An Infiniband BTH opcode */
+enum ib_bth_opcode {
+ BTH_OPCODE_UD_SEND = 0x64,
+};
+
+/** An Infiniband Datagram Extended Transport Header */
+struct ib_datagram_extended_transport_header {
+ /** Queue key */
+ uint32_t qkey;
+ /** Source queue pair */
+ uint32_t src_qp;
+} __attribute__ (( packed ));
+
+/** All known IB header formats */
+union ib_headers {
+ struct ib_local_route_header lrh;
+ struct {
+ struct ib_local_route_header lrh;
+ struct ib_global_route_header grh;
+ struct ib_base_transport_header bth;
+ struct ib_datagram_extended_transport_header deth;
+ } __attribute__ (( packed )) lrh__grh__bth__deth;
+ struct {
+ struct ib_local_route_header lrh;
+ struct ib_base_transport_header bth;
+ struct ib_datagram_extended_transport_header deth;
+ } __attribute__ (( packed )) lrh__bth__deth;
+} __attribute__ (( packed ));
+
+/** Maximum size required for IB headers */
+#define IB_MAX_HEADER_SIZE sizeof ( union ib_headers )
+
+extern int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf,
+ struct ib_queue_pair *qp, size_t payload_len,
+ const struct ib_address_vector *av );
+extern int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf,
+ struct ib_queue_pair **qp, size_t *payload_len,
+ struct ib_address_vector *av );
+
+#endif /* _IPXE_IB_PACKET_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_pathrec.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_pathrec.h
new file mode 100644
index 00000000..1fe67f87
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_pathrec.h
@@ -0,0 +1,76 @@
+#ifndef _IPXE_IB_PATHREC_H
+#define _IPXE_IB_PATHREC_H
+
+/** @file
+ *
+ * Infiniband path records
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/infiniband.h>
+
+struct ib_mad_transaction;
+struct ib_path;
+
+/** Infiniband path operations */
+struct ib_path_operations {
+ /** Handle path transaction completion
+ *
+ * @v ibdev Infiniband device
+ * @v path Path
+ * @v rc Status code
+ * @v av Address vector, or NULL on error
+ */
+ void ( * complete ) ( struct ib_device *ibdev,
+ struct ib_path *path, int rc,
+ struct ib_address_vector *av );
+};
+
+/** An Infiniband path */
+struct ib_path {
+ /** Infiniband device */
+ struct ib_device *ibdev;
+ /** Address vector */
+ struct ib_address_vector av;
+ /** Management transaction */
+ struct ib_mad_transaction *madx;
+ /** Path operations */
+ struct ib_path_operations *op;
+ /** Owner private data */
+ void *owner_priv;
+};
+
+/**
+ * Set Infiniband path owner-private data
+ *
+ * @v path Path
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_path_set_ownerdata ( struct ib_path *path, void *priv ) {
+ path->owner_priv = priv;
+}
+
+/**
+ * Get Infiniband path owner-private data
+ *
+ * @v path Path
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_path_get_ownerdata ( struct ib_path *path ) {
+ return path->owner_priv;
+}
+
+extern struct ib_path *
+ib_create_path ( struct ib_device *ibdev, struct ib_address_vector *av,
+ struct ib_path_operations *op );
+extern void ib_destroy_path ( struct ib_device *ibdev,
+ struct ib_path *path );
+
+extern int ib_resolve_path ( struct ib_device *ibdev,
+ struct ib_address_vector *av );
+
+#endif /* _IPXE_IB_PATHREC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_sma.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_sma.h
new file mode 100644
index 00000000..fa355c65
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_sma.h
@@ -0,0 +1,20 @@
+#ifndef _IPXE_IB_SMA_H
+#define _IPXE_IB_SMA_H
+
+/** @file
+ *
+ * Infiniband subnet management agent
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct ib_device;
+struct ib_mad_interface;
+
+extern int ib_create_sma ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi );
+extern void ib_destroy_sma ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi );
+
+#endif /* _IPXE_IB_SMA_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_smc.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_smc.h
new file mode 100644
index 00000000..259d2cde
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_smc.h
@@ -0,0 +1,20 @@
+#ifndef _IPXE_IB_SMC_H
+#define _IPXE_IB_SMC_H
+
+/** @file
+ *
+ * Infiniband Subnet Management Client
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/infiniband.h>
+
+typedef int ( * ib_local_mad_t ) ( struct ib_device *ibdev,
+ union ib_mad *mad );
+
+extern int ib_smc_init ( struct ib_device *ibdev, ib_local_mad_t local_mad );
+extern int ib_smc_update ( struct ib_device *ibdev, ib_local_mad_t local_mad );
+
+#endif /* _IPXE_IB_SMC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_srp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_srp.h
new file mode 100644
index 00000000..ad407b0c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ib_srp.h
@@ -0,0 +1,58 @@
+#ifndef _IPXE_IB_SRP_H
+#define _IPXE_IB_SRP_H
+
+/** @file
+ *
+ * SCSI RDMA Protocol over Infiniband
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdint.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/srp.h>
+
+/** SRP initiator port identifier for Infiniband */
+union ib_srp_initiator_port_id {
+ /** SRP version of port identifier */
+ union srp_port_id srp;
+ /** Infiniband version of port identifier */
+ struct {
+ /** Identifier extension */
+ union ib_guid id_ext;
+ /** IB channel adapter GUID */
+ union ib_guid hca_guid;
+ } __attribute__ (( packed )) ib;
+};
+
+/** SRP target port identifier for Infiniband */
+union ib_srp_target_port_id {
+ /** SRP version of port identifier */
+ union srp_port_id srp;
+ /** Infiniband version of port identifier */
+ struct {
+ /** Identifier extension */
+ union ib_guid id_ext;
+ /** I/O controller GUID */
+ union ib_guid ioc_guid;
+ } __attribute__ (( packed )) ib;
+};
+
+/**
+ * sBFT Infiniband subtable
+ */
+struct sbft_ib_subtable {
+ /** Source GID */
+ union ib_gid sgid;
+ /** Destination GID */
+ union ib_gid dgid;
+ /** Service ID */
+ union ib_guid service_id;
+ /** Partition key */
+ uint16_t pkey;
+ /** Reserved */
+ uint8_t reserved[6];
+} __attribute__ (( packed ));
+
+#endif /* _IPXE_IB_SRP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ibft.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ibft.h
new file mode 100644
index 00000000..73372122
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ibft.h
@@ -0,0 +1,271 @@
+#ifndef _IPXE_IBFT_H
+#define _IPXE_IBFT_H
+
+/*
+ * Copyright Fen Systems Ltd. 2007. Portions of this code are derived
+ * from IBM Corporation Sample Programs. Copyright IBM Corporation
+ * 2004, 2007. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+/** @file
+ *
+ * iSCSI boot firmware table
+ *
+ * The information in this file is derived from the document "iSCSI
+ * Boot Firmware Table (iBFT)" as published by IBM at
+ *
+ * ftp://ftp.software.ibm.com/systems/support/system_x_pdf/ibm_iscsi_boot_firmware_table_v1.02.pdf
+ *
+ */
+
+#include <stdint.h>
+#include <ipxe/acpi.h>
+#include <ipxe/scsi.h>
+#include <ipxe/in.h>
+
+/** iSCSI Boot Firmware Table signature */
+#define IBFT_SIG ACPI_SIGNATURE ( 'i', 'B', 'F', 'T' )
+
+/** An offset from the start of the iBFT */
+typedef uint16_t ibft_off_t;
+
+/** Length of a string within the iBFT (excluding terminating NUL) */
+typedef uint16_t ibft_size_t;
+
+/** A string within the iBFT */
+struct ibft_string {
+ /** Length of string */
+ ibft_size_t len;
+ /** Offset to string */
+ ibft_off_t offset;
+} __attribute__ (( packed ));
+
+/** An IP address within the iBFT */
+struct ibft_ipaddr {
+ /** Reserved; must be zero */
+ uint16_t zeroes[5];
+ /** Must be 0xffff if IPv4 address is present, otherwise zero */
+ uint16_t ones;
+ /** The IPv4 address, or zero if not present */
+ struct in_addr in;
+} __attribute__ (( packed ));
+
+/**
+ * iBFT structure header
+ *
+ * This structure is common to several sections within the iBFT.
+ */
+struct ibft_header {
+ /** Structure ID
+ *
+ * This is an IBFT_STRUCTURE_ID_XXX constant
+ */
+ uint8_t structure_id;
+ /** Version (always 1) */
+ uint8_t version;
+ /** Length, including this header */
+ uint16_t length;
+ /** Index
+ *
+ * This is the number of the NIC or Target, when applicable.
+ */
+ uint8_t index;
+ /** Flags */
+ uint8_t flags;
+} __attribute__ (( packed ));
+
+/**
+ * iBFT Control structure
+ *
+ */
+struct ibft_control {
+ /** Common header */
+ struct ibft_header header;
+ /** Extensions */
+ uint16_t extensions;
+ /** Offset to Initiator structure */
+ ibft_off_t initiator;
+ /** Offset to NIC structure for NIC 0 */
+ ibft_off_t nic_0;
+ /** Offset to Target structure for target 0 */
+ ibft_off_t target_0;
+ /** Offset to NIC structure for NIC 1 */
+ ibft_off_t nic_1;
+ /** Offset to Target structure for target 1 */
+ ibft_off_t target_1;
+} __attribute__ (( packed ));
+
+/** Structure ID for Control section */
+#define IBFT_STRUCTURE_ID_CONTROL 0x01
+
+/** Attempt login only to specified target
+ *
+ * If this flag is not set, all targets will be logged in to.
+ */
+#define IBFT_FL_CONTROL_SINGLE_LOGIN_ONLY 0x01
+
+/**
+ * iBFT Initiator structure
+ *
+ */
+struct ibft_initiator {
+ /** Common header */
+ struct ibft_header header;
+ /** iSNS server */
+ struct ibft_ipaddr isns_server;
+ /** SLP server */
+ struct ibft_ipaddr slp_server;
+ /** Primary and secondary Radius servers */
+ struct ibft_ipaddr radius[2];
+ /** Initiator name */
+ struct ibft_string initiator_name;
+} __attribute__ (( packed ));
+
+/** Structure ID for Initiator section */
+#define IBFT_STRUCTURE_ID_INITIATOR 0x02
+
+/** Initiator block valid */
+#define IBFT_FL_INITIATOR_BLOCK_VALID 0x01
+
+/** Initiator firmware boot selected */
+#define IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED 0x02
+
+/**
+ * iBFT NIC structure
+ *
+ */
+struct ibft_nic {
+ /** Common header */
+ struct ibft_header header;
+ /** IP address */
+ struct ibft_ipaddr ip_address;
+ /** Subnet mask
+ *
+ * This is the length of the subnet mask in bits (e.g. /24).
+ */
+ uint8_t subnet_mask_prefix;
+ /** Origin */
+ uint8_t origin;
+ /** Default gateway */
+ struct ibft_ipaddr gateway;
+ /** Primary and secondary DNS servers */
+ struct ibft_ipaddr dns[2];
+ /** DHCP server */
+ struct ibft_ipaddr dhcp;
+ /** VLAN tag */
+ uint16_t vlan;
+ /** MAC address */
+ uint8_t mac_address[6];
+ /** PCI bus:dev:fn */
+ uint16_t pci_bus_dev_func;
+ /** Hostname */
+ struct ibft_string hostname;
+} __attribute__ (( packed ));
+
+/** Structure ID for NIC section */
+#define IBFT_STRUCTURE_ID_NIC 0x03
+
+/** NIC block valid */
+#define IBFT_FL_NIC_BLOCK_VALID 0x01
+
+/** NIC firmware boot selected */
+#define IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED 0x02
+
+/** NIC global / link local */
+#define IBFT_FL_NIC_GLOBAL 0x04
+
+/**
+ * iBFT Target structure
+ *
+ */
+struct ibft_target {
+ /** Common header */
+ struct ibft_header header;
+ /** IP address */
+ struct ibft_ipaddr ip_address;
+ /** TCP port */
+ uint16_t socket;
+ /** Boot LUN */
+ struct scsi_lun boot_lun;
+ /** CHAP type
+ *
+ * This is an IBFT_CHAP_XXX constant.
+ */
+ uint8_t chap_type;
+ /** NIC association */
+ uint8_t nic_association;
+ /** Target name */
+ struct ibft_string target_name;
+ /** CHAP name */
+ struct ibft_string chap_name;
+ /** CHAP secret */
+ struct ibft_string chap_secret;
+ /** Reverse CHAP name */
+ struct ibft_string reverse_chap_name;
+ /** Reverse CHAP secret */
+ struct ibft_string reverse_chap_secret;
+} __attribute__ (( packed ));
+
+/** Structure ID for Target section */
+#define IBFT_STRUCTURE_ID_TARGET 0x04
+
+/** Target block valid */
+#define IBFT_FL_TARGET_BLOCK_VALID 0x01
+
+/** Target firmware boot selected */
+#define IBFT_FL_TARGET_FIRMWARE_BOOT_SELECTED 0x02
+
+/** Target use Radius CHAP */
+#define IBFT_FL_TARGET_USE_CHAP 0x04
+
+/** Target use Radius rCHAP */
+#define IBFT_FL_TARGET_USE_RCHAP 0x08
+
+/* Values for chap_type */
+#define IBFT_CHAP_NONE 0 /**< No CHAP authentication */
+#define IBFT_CHAP_ONE_WAY 1 /**< One-way CHAP */
+#define IBFT_CHAP_MUTUAL 2 /**< Mutual CHAP */
+
+/**
+ * iSCSI Boot Firmware Table (iBFT)
+ */
+struct ibft_table {
+ /** ACPI header */
+ struct acpi_description_header acpi;
+ /** Reserved */
+ uint8_t reserved[12];
+ /** Control structure */
+ struct ibft_control control;
+} __attribute__ (( packed ));
+
+struct iscsi_session;
+struct net_device;
+
+extern int ibft_describe ( struct iscsi_session *iscsi,
+ struct acpi_description_header *acpi,
+ size_t len );
+
+#endif /* _IPXE_IBFT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/icmp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/icmp.h
new file mode 100644
index 00000000..e402ce40
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/icmp.h
@@ -0,0 +1,25 @@
+#ifndef _IPXE_ICMP_H
+#define _IPXE_ICMP_H
+
+/** @file
+ *
+ * ICMP protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** An ICMP header */
+struct icmp_header {
+ /** Type */
+ uint8_t type;
+ /** Code */
+ uint8_t code;
+ /** Checksum */
+ uint16_t chksum;
+} __attribute__ (( packed ));
+
+#define ICMP_ECHO_RESPONSE 0
+#define ICMP_ECHO_REQUEST 8
+
+#endif /* _IPXE_ICMP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/icmp6.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/icmp6.h
new file mode 100644
index 00000000..1d433408
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/icmp6.h
@@ -0,0 +1,59 @@
+#ifndef _IPXE_ICMP6_H
+#define _IPXE_ICMP6_H
+
+/** @file
+ *
+ * ICMP6 protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/ip6.h>
+#include <ipxe/ndp.h>
+
+#define ICMP6_NSOLICIT 135
+#define ICMP6_NADVERT 136
+
+extern struct tcpip_protocol icmp6_protocol __tcpip_protocol;
+
+struct icmp6_header {
+ uint8_t type;
+ uint8_t code;
+ uint16_t csum;
+ /* Message body */
+};
+
+struct neighbour_solicit {
+ uint8_t type;
+ uint8_t code;
+ uint16_t csum;
+ uint32_t reserved;
+ struct in6_addr target;
+ /* "Compulsory" options */
+ uint8_t opt_type;
+ uint8_t opt_len;
+ /* FIXME: hack alert */
+ uint8_t opt_ll_addr[6];
+};
+
+struct neighbour_advert {
+ uint8_t type;
+ uint8_t code;
+ uint16_t csum;
+ uint8_t flags;
+ uint8_t reserved;
+ struct in6_addr target;
+ uint8_t opt_type;
+ uint8_t opt_len;
+ /* FIXME: hack alert */
+ uint8_t opt_ll_addr[6];
+};
+
+#define ICMP6_FLAGS_ROUTER 0x80
+#define ICMP6_FLAGS_SOLICITED 0x40
+#define ICMP6_FLAGS_OVERRIDE 0x20
+
+int icmp6_send_solicit ( struct net_device *netdev, struct in6_addr *src, struct in6_addr *dest );
+
+#endif /* _IPXE_ICMP6_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ieee80211.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ieee80211.h
new file mode 100644
index 00000000..4e44f434
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ieee80211.h
@@ -0,0 +1,1161 @@
+#ifndef _IPXE_IEEE80211_H
+#define _IPXE_IEEE80211_H
+
+#include <stddef.h>
+#include <ipxe/if_ether.h> /* for ETH_ALEN */
+#include <endian.h>
+
+/** @file
+ * Constants and data structures defined in IEEE 802.11, subsetted
+ * according to what iPXE knows how to use.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+/* ---------- Maximum lengths of things ---------- */
+
+/**
+ * @defgroup ieee80211_maxlen Maximum lengths in the 802.11 protocol
+ * @{
+ */
+
+/** Maximum length of frame payload
+ *
+ * This does not include cryptographic overhead, which can be up to 20
+ * bytes, but it DOES include the 802.2 LLC/SNAP headers that are used
+ * on data frames (but not management frames).
+ */
+#define IEEE80211_MAX_DATA_LEN 2304
+
+/** Length of LLC/SNAP headers on data frames */
+#define IEEE80211_LLC_HEADER_LEN 8
+
+/** Maximum cryptographic overhead before encrypted data */
+#define IEEE80211_MAX_CRYPTO_HEADER 8
+
+/** Maximum cryptographic overhead after encrypted data
+ *
+ * This does not count the MIC in TKIP frames, since that is
+ * considered to be part of the MSDU and thus contributes to the size
+ * of the data field.
+ *
+ * It @e does count the MIC in CCMP frames, which is considered part
+ * of the MPDU (outside the data field).
+ */
+#define IEEE80211_MAX_CRYPTO_TRAILER 8
+
+/** Total maximum cryptographic overhead */
+#define IEEE80211_MAX_CRYPTO_OVERHEAD 16
+
+/** Bytes of network-layer data that can go into a regular data frame */
+#define IEEE80211_MAX_FRAME_DATA 2296
+
+/** Frame header length for frames we might work with
+ *
+ * QoS adds a two-byte field on top of this, and APs communicating
+ * with each other in Wireless Distribution System (WDS) mode add an
+ * extra 6-byte MAC address field, but we do not work with such
+ * frames.
+ */
+#define IEEE80211_TYP_FRAME_HEADER_LEN 24
+
+/** Theoretical maximum frame header length
+ *
+ * This includes the QoS and WDS Addr4 fields that we should never
+ * see.
+ */
+#define IEEE80211_MAX_FRAME_HEADER_LEN 32
+
+/** Maximum combined frame length
+ *
+ * The biggest frame will include 32 frame header bytes, 16 bytes of
+ * crypto overhead, and 2304 data bytes.
+ */
+#define IEEE80211_MAX_FRAME_LEN 2352
+
+/** Maximum length of an ESSID */
+#define IEEE80211_MAX_SSID_LEN 32
+
+/** @} */
+
+
+/* ---------- Frame Control defines ---------- */
+
+/**
+ * @defgroup ieee80211_fc 802.11 Frame Control field bits
+ * @{
+ */
+
+/** 802.11 Frame Control field, Version bitmask */
+#define IEEE80211_FC_VERSION 0x0003
+
+/** Expected value of Version bits in Frame Control */
+#define IEEE80211_THIS_VERSION 0x0000
+
+
+/** 802.11 Frame Control field, Frame Type bitmask */
+#define IEEE80211_FC_TYPE 0x000C
+
+/** Type value for management (layer-2) frames */
+#define IEEE80211_TYPE_MGMT 0x0000
+
+/** Type value for control (layer-1, hardware-managed) frames */
+#define IEEE80211_TYPE_CTRL 0x0004
+
+/** Type value for data frames */
+#define IEEE80211_TYPE_DATA 0x0008
+
+
+/** 802.11 Frame Control field, Frame Subtype bitmask */
+#define IEEE80211_FC_SUBTYPE 0x00F0
+
+/** Subtype value for association-request management frames
+ *
+ * Association request frames are sent after authentication from the
+ * client to the Access Point to establish the client as part of the
+ * Access Point's network.
+ */
+#define IEEE80211_STYPE_ASSOC_REQ 0x0000
+
+/** Subtype value for association-response management frames
+ *
+ * Association response frames are sent by the Access Point to confirm
+ * or deny the association requested in an association request frame.
+ */
+#define IEEE80211_STYPE_ASSOC_RESP 0x0010
+
+/** Subtype value for reassociation-request management frames
+ *
+ * Reassociation request frames are sent by clients wishing to change
+ * from one Access Point to another while roaming within the same
+ * extended network (same ESSID).
+ */
+#define IEEE80211_STYPE_REASSOC_REQ 0x0020
+
+/** Subtype value for reassociation-response management frames
+ *
+ * Reassociation response frames are sent by the Access Point to
+ * confirm or deny the swap requested in a reassociation request
+ * frame.
+ */
+#define IEEE80211_STYPE_REASSOC_RESP 0x0030
+
+/** Subtype value for probe-request management frames
+ *
+ * Probe request frames are sent by clients to request that all Access
+ * Points on the sending channel, or all belonging to a particular
+ * ESSID, identify themselves by BSSID, supported transfer rates, RF
+ * configuration, and other capabilities.
+ */
+#define IEEE80211_STYPE_PROBE_REQ 0x0040
+
+/** Subtype value for probe-response management frames
+ *
+ * Probe response frames are sent by Access Points in response to
+ * probe request frames, providing the requested information.
+ */
+#define IEEE80211_STYPE_PROBE_RESP 0x0050
+
+/** Subtype value for beacon management frames
+ *
+ * Beacon frames are sent by Access Points at regular intervals,
+ * usually ten per second, on the channel on which they communicate.
+ * They can be used to probe passively for access points on a channel
+ * where local regulatory restrictions prohibit active scanning, or
+ * due to their regularity as a mechanism to determine the fraction of
+ * packets that are being dropped.
+ */
+#define IEEE80211_STYPE_BEACON 0x0080
+
+/** Subtype value for disassociation management frames
+ *
+ * Disassociation frames are sent by either a client or an Access
+ * Point to unequivocally terminate the association between the two.
+ * They may be sent by clients upon leaving the network, or by an
+ * Access Point upon reconfiguration, among other reasons; they are
+ * usually more "polite" than deauthentication frames.
+ */
+#define IEEE80211_STYPE_DISASSOC 0x00A0
+
+/** Subtype value for authentication management frames
+ *
+ * Authentication frames are exchanged between a client and an Access
+ * Point before association may be performed. Confusingly, in the most
+ * common authentication method (Open System) no security tokens are
+ * exchanged at all. Modern 802.11 security handshaking takes place
+ * after association.
+ */
+#define IEEE80211_STYPE_AUTH 0x00B0
+
+/** Subtype value for deauthentication management frames
+ *
+ * Deauthentication frames are sent by either a client or an Access
+ * Point to terminate the authentication (and therefore also the
+ * association) between the two. They are generally more forceful than
+ * disassociation frames, sent for such reasons as a failure to
+ * set up security properly after associating.
+ */
+#define IEEE80211_STYPE_DEAUTH 0x00C0
+
+/** Subtype value for action management frames
+ *
+ * Action frames are used to implement spectrum management and QoS
+ * features that iPXE currently does not support.
+ */
+#define IEEE80211_STYPE_ACTION 0x00D0
+
+
+/** Subtype value for RTS (request to send) control frames */
+#define IEEE80211_STYPE_RTS 0x00B0
+
+/** Subtype value for CTS (clear to send) control frames */
+#define IEEE80211_STYPE_CTS 0x00C0
+
+/** Subtype value for ACK (acknowledgement) control frames */
+#define IEEE80211_STYPE_ACK 0x00D0
+
+
+/** Subtype value for ordinary data frames, with no QoS or CF add-ons */
+#define IEEE80211_STYPE_DATA 0x0000
+
+/** Subtype value for data frames containing no data */
+#define IEEE80211_STYPE_NODATA 0x0040
+
+
+/** 802.11 Frame Control field: To Data System flag
+ *
+ * This is set on data frames sent to an Access Point.
+ */
+#define IEEE80211_FC_TODS 0x0100
+
+/** 802.11 Frame Control field: From Data System flag
+ *
+ * This is set on data frames sent from an Access Point. If both TODS
+ * and FROMDS are set, the frame header is a 4-address format used for
+ * inter-Access Point communication.
+ */
+#define IEEE80211_FC_FROMDS 0x0200
+
+/** 802.11 Frame Control field: More Fragments flag */
+#define IEEE80211_FC_MORE_FRAG 0x0400
+
+/** 802.11 Frame Control field: Retransmission flag */
+#define IEEE80211_FC_RETRY 0x0800
+
+/** 802.11 Frame Control field: Power Managed flag
+ *
+ * This is set on any frame sent by a low-power station that will go
+ * into a power-saving mode immediately after this frame. Access
+ * Points are not allowed to act as low-power stations.
+ */
+#define IEEE80211_FC_PWR_MGMT 0x1000
+
+/** 802.11 Frame Control field: More Data flag
+ *
+ * This is set on any frame sent by a station that has more data
+ * queued to be sent than is in the frame.
+ */
+#define IEEE80211_FC_MORE_DATA 0x2000
+
+/** 802.11 Frame Control field: Protected flag
+ *
+ * This is set on frames in which data is encrypted (by any method).
+ */
+#define IEEE80211_FC_PROTECTED 0x4000
+
+/** 802.11 Frame Control field: Ordered flag [?] */
+#define IEEE80211_FC_ORDER 0x8000
+
+/** @} */
+
+
+/* ---------- Sequence Control defines ---------- */
+
+/**
+ * @defgroup ieee80211_seq 802.11 Sequence Control field handling
+ * @{
+ */
+
+/** Extract sequence number from 802.11 Sequence Control field */
+#define IEEE80211_SEQNR( seq ) ( ( seq ) >> 4 )
+
+/** Extract fragment number from 802.11 Sequence Control field */
+#define IEEE80211_FRAG( seq ) ( ( seq ) & 0x000F )
+
+/** Make 802.11 Sequence Control field from sequence and fragment numbers */
+#define IEEE80211_MAKESEQ( seqnr, frag ) \
+ ( ( ( ( seqnr ) & 0xFFF ) << 4 ) | ( ( frag ) & 0xF ) )
+
+/** @} */
+
+
+/* ---------- Frame header formats ---------- */
+
+/**
+ * @defgroup ieee80211_hdr 802.11 frame header formats
+ * @{
+ */
+
+/** An 802.11 data or management frame without QoS or WDS header fields */
+struct ieee80211_frame
+{
+ u16 fc; /**< 802.11 Frame Control field */
+ u16 duration; /**< Microseconds to reserve link */
+ u8 addr1[ETH_ALEN]; /**< Address 1 (immediate receiver) */
+ u8 addr2[ETH_ALEN]; /**< Address 2 (immediate sender) */
+ u8 addr3[ETH_ALEN]; /**< Address 3 (often "forward to") */
+ u16 seq; /**< 802.11 Sequence Control field */
+ u8 data[0]; /**< Beginning of frame data */
+} __attribute__((packed));
+
+/** The 802.2 LLC/SNAP header sent before actual data in a data frame
+ *
+ * This header is not acknowledged in the 802.11 standard at all; it
+ * is treated just like data for MAC-layer purposes, including
+ * fragmentation and encryption. It is actually two headers
+ * concatenated: a three-byte 802.2 LLC header indicating Subnetwork
+ * Accesss Protocol (SNAP) in both source and destination Service
+ * Access Point (SAP) fields, and a five-byte SNAP header indicating a
+ * zero OUI and two-byte Ethernet protocol type field.
+ *
+ * Thus, an eight-byte header in which six of the bytes are redundant.
+ * Lovely, isn't it?
+ */
+struct ieee80211_llc_snap_header
+{
+ /* LLC part: */
+ u8 dsap; /**< Destination SAP ID */
+ u8 ssap; /**< Source SAP ID */
+ u8 ctrl; /**< Control information */
+
+ /* SNAP part: */
+ u8 oui[3]; /**< Organization code, usually 0 */
+ u16 ethertype; /**< Ethernet Type field */
+} __attribute__((packed));
+
+/** Value for DSAP field in 802.2 LLC header for 802.11 frames: SNAP */
+#define IEEE80211_LLC_DSAP 0xAA
+
+/** Value for SSAP field in 802.2 LLC header for 802.11 frames: SNAP */
+#define IEEE80211_LLC_SSAP 0xAA
+
+/** Value for control field in 802.2 LLC header for 802.11 frames
+ *
+ * "Unnumbered Information".
+ */
+#define IEEE80211_LLC_CTRL 0x03
+
+
+/** 16-byte RTS frame format, with abbreviated header */
+struct ieee80211_rts
+{
+ u16 fc; /**< 802.11 Frame Control field */
+ u16 duration; /**< Microseconds to reserve link */
+ u8 addr1[ETH_ALEN]; /**< Address 1 (immediate receiver) */
+ u8 addr2[ETH_ALEN]; /**< Address 2 (immediate sender) */
+} __attribute__((packed));
+
+/** Length of 802.11 RTS control frame */
+#define IEEE80211_RTS_LEN 16
+
+/** 10-byte CTS or ACK frame format, with abbreviated header */
+struct ieee80211_cts_or_ack
+{
+ u16 fc; /**< 802.11 Frame Control field */
+ u16 duration; /**< Microseconds to reserve link */
+ u8 addr1[ETH_ALEN]; /**< Address 1 (immediate receiver) */
+} __attribute__((packed));
+
+#define ieee80211_cts ieee80211_cts_or_ack
+#define ieee80211_ack ieee80211_cts_or_ack
+
+/** Length of 802.11 CTS control frame */
+#define IEEE80211_CTS_LEN 10
+
+/** Length of 802.11 ACK control frame */
+#define IEEE80211_ACK_LEN 10
+
+/** @} */
+
+
+/* ---------- Capability bits, status and reason codes ---------- */
+
+/**
+ * @defgroup ieee80211_capab 802.11 management frame capability field bits
+ * @{
+ */
+
+/** Set if using an Access Point (managed mode) */
+#define IEEE80211_CAPAB_MANAGED 0x0001
+
+/** Set if operating in IBSS (no-AP, "Ad-Hoc") mode */
+#define IEEE80211_CAPAB_ADHOC 0x0002
+
+/** Set if we support Contention-Free Period operation */
+#define IEEE80211_CAPAB_CFPOLL 0x0004
+
+/** Set if we wish to be polled for Contention-Free operation */
+#define IEEE80211_CAPAB_CFPR 0x0008
+
+/** Set if the network is encrypted (by any method) */
+#define IEEE80211_CAPAB_PRIVACY 0x0010
+
+/** Set if PHY supports short preambles on 802.11b */
+#define IEEE80211_CAPAB_SHORT_PMBL 0x0020
+
+/** Set if PHY supports PBCC modulation */
+#define IEEE80211_CAPAB_PBCC 0x0040
+
+/** Set if we support Channel Agility */
+#define IEEE80211_CAPAB_CHAN_AGILITY 0x0080
+
+/** Set if we support spectrum management (DFS and TPC) on the 5GHz band */
+#define IEEE80211_CAPAB_SPECTRUM_MGMT 0x0100
+
+/** Set if we support Quality of Service enhancements */
+#define IEEE80211_CAPAB_QOS 0x0200
+
+/** Set if PHY supports short slot time on 802.11g */
+#define IEEE80211_CAPAB_SHORT_SLOT 0x0400
+
+/** Set if PHY supports APSD option */
+#define IEEE80211_CAPAB_APSD 0x0800
+
+/** Set if PHY supports DSSS/OFDM modulation (one way of 802.11 b/g mixing) */
+#define IEEE80211_CAPAB_DSSS_OFDM 0x2000
+
+/** Set if we support delayed block ACK */
+#define IEEE80211_CAPAB_DELAYED_BACK 0x4000
+
+/** Set if we support immediate block ACK */
+#define IEEE80211_CAPAB_IMMED_BACK 0x8000
+
+/** @} */
+
+
+/**
+ * @defgroup ieee80211_status 802.11 status codes
+ *
+ * These are returned to indicate an immediate denial of
+ * authentication or association. In iPXE, the lower 5 bits of the
+ * status code are encoded into the file-unique portion of an error
+ * code, the ERRFILE portion is always @c ERRFILE_net80211, and the
+ * POSIX error code is @c ECONNREFUSED for status 0-31 or @c
+ * EHOSTUNREACH for status 32-63.
+ *
+ * For a complete table with non-abbreviated error messages, see IEEE
+ * Std 802.11-2007, Table 7-23, p.94.
+ *
+ * @{
+ */
+
+#define IEEE80211_STATUS_SUCCESS 0
+#define IEEE80211_STATUS_FAILURE 1
+#define IEEE80211_STATUS_CAPAB_UNSUPP 10
+#define IEEE80211_STATUS_REASSOC_INVALID 11
+#define IEEE80211_STATUS_ASSOC_DENIED 12
+#define IEEE80211_STATUS_AUTH_ALGO_UNSUPP 13
+#define IEEE80211_STATUS_AUTH_SEQ_INVALID 14
+#define IEEE80211_STATUS_AUTH_CHALL_INVALID 15
+#define IEEE80211_STATUS_AUTH_TIMEOUT 16
+#define IEEE80211_STATUS_ASSOC_NO_ROOM 17
+#define IEEE80211_STATUS_ASSOC_NEED_RATE 18
+#define IEEE80211_STATUS_ASSOC_NEED_SHORT_PMBL 19
+#define IEEE80211_STATUS_ASSOC_NEED_PBCC 20
+#define IEEE80211_STATUS_ASSOC_NEED_CHAN_AGILITY 21
+#define IEEE80211_STATUS_ASSOC_NEED_SPECTRUM_MGMT 22
+#define IEEE80211_STATUS_ASSOC_BAD_POWER 23
+#define IEEE80211_STATUS_ASSOC_BAD_CHANNELS 24
+#define IEEE80211_STATUS_ASSOC_NEED_SHORT_SLOT 25
+#define IEEE80211_STATUS_ASSOC_NEED_DSSS_OFDM 26
+#define IEEE80211_STATUS_QOS_FAILURE 32
+#define IEEE80211_STATUS_QOS_NO_ROOM 33
+#define IEEE80211_STATUS_LINK_IS_HORRIBLE 34
+#define IEEE80211_STATUS_ASSOC_NEED_QOS 35
+#define IEEE80211_STATUS_REQUEST_DECLINED 37
+#define IEEE80211_STATUS_REQUEST_INVALID 38
+#define IEEE80211_STATUS_TS_NOT_CREATED_AGAIN 39
+#define IEEE80211_STATUS_INVALID_IE 40
+#define IEEE80211_STATUS_GROUP_CIPHER_INVALID 41
+#define IEEE80211_STATUS_PAIR_CIPHER_INVALID 42
+#define IEEE80211_STATUS_AKMP_INVALID 43
+#define IEEE80211_STATUS_RSN_VERSION_UNSUPP 44
+#define IEEE80211_STATUS_RSN_CAPAB_INVALID 45
+#define IEEE80211_STATUS_CIPHER_REJECTED 46
+#define IEEE80211_STATUS_TS_NOT_CREATED_WAIT 47
+#define IEEE80211_STATUS_DIRECT_LINK_FORBIDDEN 48
+#define IEEE80211_STATUS_DEST_NOT_PRESENT 49
+#define IEEE80211_STATUS_DEST_NOT_QOS 50
+#define IEEE80211_STATUS_ASSOC_LISTEN_TOO_HIGH 51
+
+/** @} */
+
+
+
+/**
+ * @defgroup ieee80211_reason 802.11 reason codes
+ *
+ * These are returned to indicate the reason for a deauthentication or
+ * disassociation sent (usually) after authentication or association
+ * had succeeded. In iPXE, the lower 5 bits of the reason code are
+ * encoded into the file-unique portion of an error code, the ERRFILE
+ * portion is always @c ERRFILE_net80211, and the POSIX error code is
+ * @c ECONNRESET for reason 0-31 or @c ENETRESET for reason 32-63.
+ *
+ * For a complete table with non-abbreviated error messages, see IEEE
+ * Std 802.11-2007, Table 7-22, p.92.
+ *
+ * @{
+ */
+
+#define IEEE80211_REASON_NONE 0
+#define IEEE80211_REASON_UNSPECIFIED 1
+#define IEEE80211_REASON_AUTH_NO_LONGER_VALID 2
+#define IEEE80211_REASON_LEAVING 3
+#define IEEE80211_REASON_INACTIVITY 4
+#define IEEE80211_REASON_OUT_OF_RESOURCES 5
+#define IEEE80211_REASON_NEED_AUTH 6
+#define IEEE80211_REASON_NEED_ASSOC 7
+#define IEEE80211_REASON_LEAVING_TO_ROAM 8
+#define IEEE80211_REASON_REASSOC_INVALID 9
+#define IEEE80211_REASON_BAD_POWER 10
+#define IEEE80211_REASON_BAD_CHANNELS 11
+#define IEEE80211_REASON_INVALID_IE 13
+#define IEEE80211_REASON_MIC_FAILURE 14
+#define IEEE80211_REASON_4WAY_TIMEOUT 15
+#define IEEE80211_REASON_GROUPKEY_TIMEOUT 16
+#define IEEE80211_REASON_4WAY_INVALID 17
+#define IEEE80211_REASON_GROUP_CIPHER_INVALID 18
+#define IEEE80211_REASON_PAIR_CIPHER_INVALID 19
+#define IEEE80211_REASON_AKMP_INVALID 20
+#define IEEE80211_REASON_RSN_VERSION_INVALID 21
+#define IEEE80211_REASON_RSN_CAPAB_INVALID 22
+#define IEEE80211_REASON_8021X_FAILURE 23
+#define IEEE80211_REASON_CIPHER_REJECTED 24
+#define IEEE80211_REASON_QOS_UNSPECIFIED 32
+#define IEEE80211_REASON_QOS_OUT_OF_RESOURCES 33
+#define IEEE80211_REASON_LINK_IS_HORRIBLE 34
+#define IEEE80211_REASON_INVALID_TXOP 35
+#define IEEE80211_REASON_REQUESTED_LEAVING 36
+#define IEEE80211_REASON_REQUESTED_NO_USE 37
+#define IEEE80211_REASON_REQUESTED_NEED_SETUP 38
+#define IEEE80211_REASON_REQUESTED_TIMEOUT 39
+#define IEEE80211_REASON_CIPHER_UNSUPPORTED 45
+
+/** @} */
+
+/* ---------- Information element declarations ---------- */
+
+/**
+ * @defgroup ieee80211_ie 802.11 information elements
+ *
+ * Many management frames include a section that amounts to a
+ * concatenation of these information elements, so that the sender can
+ * choose which information to send and the receiver can ignore the
+ * parts it doesn't understand. Each IE contains a two-byte header,
+ * one byte ID and one byte length, followed by IE-specific data. The
+ * length does not include the two-byte header. Information elements
+ * are required to be sorted by ID, but iPXE does not require that in
+ * those it receives.
+ *
+ * This group also includes a few inline functions to simplify common
+ * tasks in IE processing.
+ *
+ * @{
+ */
+
+/** Generic 802.11 information element header */
+struct ieee80211_ie_header {
+ u8 id; /**< Information element ID */
+ u8 len; /**< Information element length */
+} __attribute__ ((packed));
+
+
+/** 802.11 SSID information element */
+struct ieee80211_ie_ssid {
+ u8 id; /**< SSID ID: 0 */
+ u8 len; /**< SSID length */
+ char ssid[0]; /**< SSID data, not NUL-terminated */
+} __attribute__ ((packed));
+
+/** Information element ID for SSID information element */
+#define IEEE80211_IE_SSID 0
+
+
+/** 802.11 rates information element
+ *
+ * The first 8 rates go in an IE of type RATES (1), and any more rates
+ * go in one of type EXT_RATES (50). Each rate is a byte with the low
+ * 7 bits equal to the rate in units of 500 kbps, and the high bit set
+ * if and only if the rate is "basic" (must be supported by all
+ * connected stations).
+ */
+struct ieee80211_ie_rates {
+ u8 id; /**< Rates ID: 1 or 50 */
+ u8 len; /**< Number of rates */
+ u8 rates[0]; /**< Rates data, one rate per byte */
+} __attribute__ ((packed));
+
+/** Information element ID for rates information element */
+#define IEEE80211_IE_RATES 1
+
+/** Information element ID for extended rates information element */
+#define IEEE80211_IE_EXT_RATES 50
+
+
+/** 802.11 Direct Spectrum parameter information element
+ *
+ * This just contains the channel number. It has the fancy name
+ * because IEEE 802.11 also defines a frequency-hopping PHY that
+ * changes channels at regular intervals following a predetermined
+ * pattern; in practice nobody uses the FH PHY.
+ */
+struct ieee80211_ie_ds_param {
+ u8 id; /**< DS parameter ID: 3 */
+ u8 len; /**< DS parameter length: 1 */
+ u8 current_channel; /**< Current channel number, 1-14 */
+} __attribute__ ((packed));
+
+/** Information element ID for Direct Spectrum parameter information element */
+#define IEEE80211_IE_DS_PARAM 3
+
+
+/** 802.11 Country information element regulatory extension triplet */
+struct ieee80211_ie_country_ext_triplet {
+ u8 reg_ext_id; /**< Regulatory extension ID */
+ u8 reg_class_id; /**< Regulatory class ID */
+ u8 coverage_class; /**< Coverage class */
+} __attribute__ ((packed));
+
+/** 802.11 Country information element regulatory band triplet */
+struct ieee80211_ie_country_band_triplet {
+ u8 first_channel; /**< Channel number for first channel in band */
+ u8 nr_channels; /**< Number of contiguous channels in band */
+ u8 max_txpower; /**< Maximum TX power in dBm */
+} __attribute__ ((packed));
+
+/** 802.11 Country information element regulatory triplet
+ *
+ * It is a band triplet if the first byte is 200 or less, and a
+ * regulatory extension triplet otherwise.
+ */
+union ieee80211_ie_country_triplet {
+ /** Differentiator between band and ext triplets */
+ u8 first;
+
+ /** Information about a band of channels */
+ struct ieee80211_ie_country_band_triplet band;
+
+ /** Regulatory extension information */
+ struct ieee80211_ie_country_ext_triplet ext;
+};
+
+/** 802.11 Country information element
+ *
+ * This contains some data about RF regulations.
+ */
+struct ieee80211_ie_country {
+ u8 id; /**< Country information ID: 7 */
+ u8 len; /**< Country information length: varies */
+ char name[2]; /**< ISO Alpha2 country code */
+ char in_out; /**< 'I' for indoor, 'O' for outdoor */
+
+ /** List of regulatory triplets */
+ union ieee80211_ie_country_triplet triplet[0];
+} __attribute__ ((packed));
+
+/** Information element ID for Country information element */
+#define IEEE80211_IE_COUNTRY 7
+
+
+/** 802.11 Request information element
+ *
+ * This contains a list of information element types we would like to
+ * be included in probe response frames.
+ */
+struct ieee80211_ie_request {
+ u8 id; /**< Request ID: 10 */
+ u8 len; /**< Number of IEs requested */
+ u8 request[0]; /**< List of IEs requested */
+} __attribute__ ((packed));
+
+/** Information element ID for Request information element */
+#define IEEE80211_IE_REQUEST 10
+
+
+/** 802.11 Challenge Text information element
+ *
+ * This is used in authentication frames under Shared Key
+ * authentication.
+ */
+struct ieee80211_ie_challenge_text {
+ u8 id; /**< Challenge Text ID: 16 */
+ u8 len; /**< Challenge Text length: usually 128 */
+ u8 challenge_text[0]; /**< Challenge Text data */
+} __attribute__ ((packed));
+
+/** Information element ID for Challenge Text information element */
+#define IEEE80211_IE_CHALLENGE_TEXT 16
+
+
+/** 802.11 Power Constraint information element
+ *
+ * This is used to specify an additional power limitation on top of
+ * the Country requirements.
+ */
+struct ieee80211_ie_power_constraint {
+ u8 id; /**< Power Constraint ID: 52 */
+ u8 len; /**< Power Constraint length: 1 */
+ u8 power_constraint; /**< Decrease in allowed TX power, dBm */
+} __attribute__ ((packed));
+
+/** Information element ID for Power Constraint information element */
+#define IEEE80211_IE_POWER_CONSTRAINT 52
+
+
+/** 802.11 Power Capability information element
+ *
+ * This is used in association request frames to indicate the extremes
+ * of our TX power abilities. It is required only if we indicate
+ * support for spectrum management.
+ */
+struct ieee80211_ie_power_capab {
+ u8 id; /**< Power Capability ID: 33 */
+ u8 len; /**< Power Capability length: 2 */
+ u8 min_txpower; /**< Minimum possible TX power, dBm */
+ u8 max_txpower; /**< Maximum possible TX power, dBm */
+} __attribute__ ((packed));
+
+/** Information element ID for Power Capability information element */
+#define IEEE80211_IE_POWER_CAPAB 33
+
+
+/** 802.11 Channels information element channel band tuple */
+struct ieee80211_ie_channels_channel_band {
+ u8 first_channel; /**< Channel number of first channel in band */
+ u8 nr_channels; /**< Number of channels in band */
+} __attribute__ ((packed));
+
+/** 802.11 Channels information element
+ *
+ * This is used in association frames to indicate the channels we can
+ * use. It is required only if we indicate support for spectrum
+ * management.
+ */
+struct ieee80211_ie_channels {
+ u8 id; /**< Channels ID: 36 */
+ u8 len; /**< Channels length: 2 */
+
+ /** List of (start, length) channel bands we can use */
+ struct ieee80211_ie_channels_channel_band channels[0];
+} __attribute__ ((packed));
+
+/** Information element ID for Channels information element */
+#define IEEE80211_IE_CHANNELS 36
+
+
+/** 802.11 ERP Information information element
+ *
+ * This is used to communicate some PHY-level flags.
+ */
+struct ieee80211_ie_erp_info {
+ u8 id; /**< ERP Information ID: 42 */
+ u8 len; /**< ERP Information length: 1 */
+ u8 erp_info; /**< ERP flags */
+} __attribute__ ((packed));
+
+/** Information element ID for ERP Information information element */
+#define IEEE80211_IE_ERP_INFO 42
+
+/** ERP information element: Flag set if 802.11b stations are present */
+#define IEEE80211_ERP_NONERP_PRESENT 0x01
+
+/** ERP information element: Flag set if CTS protection must be used */
+#define IEEE80211_ERP_USE_PROTECTION 0x02
+
+/** ERP information element: Flag set if long preambles must be used */
+#define IEEE80211_ERP_BARKER_LONG 0x04
+
+
+/** 802.11 Robust Security Network ("WPA") information element
+ *
+ * Showing once again a striking clarity of design, the IEEE folks put
+ * dynamically-sized data in the middle of this structure. As such,
+ * the below structure definition only works for IEs we create
+ * ourselves, which always have one pairwise cipher and one AKM;
+ * received IEs should be parsed piecemeal.
+ *
+ * Also inspired was IEEE's choice of 16-bit fields to count the
+ * number of 4-byte elements in a structure with a maximum length of
+ * 255 bytes.
+ *
+ * Many fields reference a cipher or authentication-type ID; this is a
+ * three-byte OUI followed by one byte identifying the cipher with
+ * respect to that OUI. For all standard ciphers the OUI is 00:0F:AC,
+ * except in old-style WPA IEs encapsulated in vendor-specific IEs,
+ * where it's 00:50:F2.
+ */
+struct ieee80211_ie_rsn {
+ /** Information element ID */
+ u8 id;
+
+ /** Information element length */
+ u8 len;
+
+ /** RSN information element version */
+ u16 version;
+
+ /** Cipher ID for the cipher used in multicast/broadcast frames */
+ u32 group_cipher;
+
+ /** Number of unicast ciphers supported */
+ u16 pairwise_count;
+
+ /** List of cipher IDs for supported unicast frame ciphers */
+ u32 pairwise_cipher[1];
+
+ /** Number of authentication types supported */
+ u16 akm_count;
+
+ /** List of authentication type IDs for supported types */
+ u32 akm_list[1];
+
+ /** Security capabilities field (RSN only) */
+ u16 rsn_capab;
+
+ /** Number of PMKIDs included (present only in association frames) */
+ u16 pmkid_count;
+
+ /** List of PMKIDs included, each a 16-byte SHA1 hash */
+ u8 pmkid_list[0];
+} __attribute__((packed));
+
+/** Information element ID for Robust Security Network information element */
+#define IEEE80211_IE_RSN 48
+
+/** Calculate necessary size of RSN information element
+ *
+ * @v npair Number of pairwise ciphers supported
+ * @v nauth Number of authentication types supported
+ * @v npmkid Number of PMKIDs to include
+ * @v is_rsn If TRUE, calculate RSN IE size; if FALSE, calculate WPA IE size
+ * @ret size Necessary size of IE, including header bytes
+ */
+static inline size_t ieee80211_rsn_size ( int npair, int nauth, int npmkid,
+ int rsn_ie ) {
+ return 16 + 4 * ( npair + nauth ) + 16 * npmkid - 4 * ! rsn_ie;
+}
+
+/** Make OUI plus type byte into 32-bit integer for easy comparison */
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define _MKOUI( a, b, c, t ) \
+ ( ( ( a ) << 24 ) | ( ( b ) << 16 ) | ( ( c ) << 8 ) | ( d ) )
+#define OUI_ORG_MASK 0xFFFFFF00
+#define OUI_TYPE_MASK 0x000000FF
+#else
+#define _MKOUI( a, b, c, t ) \
+ ( ( ( t ) << 24 ) | ( ( c ) << 16 ) | ( ( b ) << 8 ) | ( a ) )
+#define OUI_ORG_MASK 0x00FFFFFF
+#define OUI_TYPE_MASK 0xFF000000
+#endif
+
+/** Organization part for OUIs in standard RSN IE */
+#define IEEE80211_RSN_OUI _MKOUI ( 0x00, 0x0F, 0xAC, 0 )
+
+/** Organization part for OUIs in old WPA IE */
+#define IEEE80211_WPA_OUI _MKOUI ( 0x00, 0x50, 0xF2, 0 )
+
+/** Old vendor-type WPA IE OUI type + subtype */
+#define IEEE80211_WPA_OUI_VEN _MKOUI ( 0x00, 0x50, 0xF2, 0x01 )
+
+
+/** 802.11 RSN IE: expected version number */
+#define IEEE80211_RSN_VERSION 1
+
+/** 802.11 RSN IE: cipher type for 40-bit WEP */
+#define IEEE80211_RSN_CTYPE_WEP40 _MKOUI ( 0, 0, 0, 0x01 )
+
+/** 802.11 RSN IE: cipher type for 104-bit WEP */
+#define IEEE80211_RSN_CTYPE_WEP104 _MKOUI ( 0, 0, 0, 0x05 )
+
+/** 802.11 RSN IE: cipher type for TKIP ("WPA") */
+#define IEEE80211_RSN_CTYPE_TKIP _MKOUI ( 0, 0, 0, 0x02 )
+
+/** 802.11 RSN IE: cipher type for CCMP ("WPA2") */
+#define IEEE80211_RSN_CTYPE_CCMP _MKOUI ( 0, 0, 0, 0x04 )
+
+/** 802.11 RSN IE: cipher type for "use group"
+ *
+ * This can only appear as a pairwise cipher, and means unicast frames
+ * should be encrypted in the same way as broadcast/multicast frames.
+ */
+#define IEEE80211_RSN_CTYPE_USEGROUP _MKOUI ( 0, 0, 0, 0x00 )
+
+/** 802.11 RSN IE: auth method type for using an 802.1X server */
+#define IEEE80211_RSN_ATYPE_8021X _MKOUI ( 0, 0, 0, 0x01 )
+
+/** 802.11 RSN IE: auth method type for using a pre-shared key */
+#define IEEE80211_RSN_ATYPE_PSK _MKOUI ( 0, 0, 0, 0x02 )
+
+/** 802.11 RSN IE capabilities: AP supports pre-authentication */
+#define IEEE80211_RSN_CAPAB_PREAUTH 0x001
+
+/** 802.11 RSN IE capabilities: Node has conflict between TKIP and WEP
+ *
+ * This is a legacy issue; APs always set it to 0, and iPXE sets it to
+ * 0.
+ */
+#define IEEE80211_RSN_CAPAB_NO_PAIRWISE 0x002
+
+/** 802.11 RSN IE capabilities: Number of PTKSA replay counters
+ *
+ * A value of 0 means one replay counter, 1 means two, 2 means four,
+ * and 3 means sixteen.
+ */
+#define IEEE80211_RSN_CAPAB_PTKSA_REPLAY 0x00C
+
+/** 802.11 RSN IE capabilities: Number of GTKSA replay counters
+ *
+ * A value of 0 means one replay counter, 1 means two, 2 means four,
+ * and 3 means sixteen.
+ */
+#define IEEE80211_RSN_CAPAB_GTKSA_REPLAY 0x030
+
+/** 802.11 RSN IE capabilities: PeerKey Handshaking is suported */
+#define IEEE80211_RSN_CAPAB_PEERKEY 0x200
+
+
+/** 802.11 RSN IE capabilities: One replay counter
+ *
+ * This should be AND'ed with @c IEEE80211_RSN_CAPAB_PTKSA_REPLAY or
+ * @c IEEE80211_RSN_CAPAB_GTKSA_REPLAY (or both) to produce a value
+ * which can be OR'ed into the capabilities field.
+ */
+#define IEEE80211_RSN_1_CTR 0x000
+
+/** 802.11 RSN IE capabilities: Two replay counters */
+#define IEEE80211_RSN_2_CTR 0x014
+
+/** 802.11 RSN IE capabilities: Four replay counters */
+#define IEEE80211_RSN_4_CTR 0x028
+
+/** 802.11 RSN IE capabilities: 16 replay counters */
+#define IEEE80211_RSN_16_CTR 0x03C
+
+
+/** 802.11 Vendor Specific information element
+ *
+ * One often sees the RSN IE masquerading as vendor-specific on
+ * devices that were produced prior to 802.11i (the WPA amendment)
+ * being finalized.
+ */
+struct ieee80211_ie_vendor {
+ u8 id; /**< Vendor-specific ID: 221 */
+ u8 len; /**< Vendor-specific length: variable */
+ u32 oui; /**< OUI and vendor-specific type byte */
+ u8 data[0]; /**< Vendor-specific data */
+} __attribute__ ((packed));
+
+/** Information element ID for Vendor Specific information element */
+#define IEEE80211_IE_VENDOR 221
+
+
+
+
+/** Any 802.11 information element
+ *
+ * This is formatted for ease of use, so IEs with complex structures
+ * get referenced in full, while those with only one byte of data or a
+ * simple array are pulled in to avoid a layer of indirection like
+ * ie->channels.channels[0].
+ */
+union ieee80211_ie
+{
+ /** Generic and simple information element info */
+ struct {
+ u8 id; /**< Information element ID */
+ u8 len; /**< Information element data length */
+ union {
+ char ssid[0]; /**< SSID text */
+ u8 rates[0]; /**< Rates data */
+ u8 request[0]; /**< Request list */
+ u8 challenge_text[0]; /**< Challenge text data */
+ u8 power_constraint; /**< Power constraint, dBm */
+ u8 erp_info; /**< ERP information flags */
+ /** List of channels */
+ struct ieee80211_ie_channels_channel_band channels[0];
+ };
+ };
+
+ /** DS parameter set */
+ struct ieee80211_ie_ds_param ds_param;
+
+ /** Country information */
+ struct ieee80211_ie_country country;
+
+ /** Power capability */
+ struct ieee80211_ie_power_capab power_capab;
+
+ /** Security information */
+ struct ieee80211_ie_rsn rsn;
+
+ /** Vendor-specific */
+ struct ieee80211_ie_vendor vendor;
+};
+
+/** Check that 802.11 information element is bounded by buffer
+ *
+ * @v ie Information element
+ * @v end End of buffer in which information element is stored
+ * @ret ok TRUE if the IE is completely contained within the buffer
+ */
+static inline int ieee80211_ie_bound ( union ieee80211_ie *ie, void *end )
+{
+ void *iep = ie;
+ return ( iep + 2 <= end && iep + 2 + ie->len <= end );
+}
+
+/** Advance to next 802.11 information element
+ *
+ * @v ie Current information element pointer
+ * @v end Pointer to first byte not in information element space
+ * @ret next Pointer to next information element, or NULL if no more
+ *
+ * When processing received IEs, @a end should be set to the I/O
+ * buffer tail pointer; when marshalling IEs for sending, @a end
+ * should be NULL.
+ */
+static inline union ieee80211_ie * ieee80211_next_ie ( union ieee80211_ie *ie,
+ void *end )
+{
+ void *next_ie_byte = ( void * ) ie + ie->len + 2;
+ union ieee80211_ie *next_ie = next_ie_byte;
+
+ if ( ! end )
+ return next_ie;
+
+ if ( ieee80211_ie_bound ( next_ie, end ) )
+ return next_ie;
+
+ return NULL;
+}
+
+/** @} */
+
+
+/* ---------- Management frame data formats ---------- */
+
+/**
+ * @defgroup ieee80211_mgmt_data Management frame data payloads
+ * @{
+ */
+
+/** Beacon or probe response frame data */
+struct ieee80211_beacon_or_probe_resp
+{
+ /** 802.11 TSFT value at frame send */
+ u64 timestamp;
+
+ /** Interval at which beacons are sent, in units of 1024 us */
+ u16 beacon_interval;
+
+ /** Capability flags */
+ u16 capability;
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+#define ieee80211_beacon ieee80211_beacon_or_probe_resp
+#define ieee80211_probe_resp ieee80211_beacon_or_probe_resp
+
+/** Disassociation or deauthentication frame data */
+struct ieee80211_disassoc_or_deauth
+{
+ /** Reason code */
+ u16 reason;
+} __attribute__((packed));
+
+#define ieee80211_disassoc ieee80211_disassoc_or_deauth
+#define ieee80211_deauth ieee80211_disassoc_or_deauth
+
+/** Association request frame data */
+struct ieee80211_assoc_req
+{
+ /** Capability flags */
+ u16 capability;
+
+ /** Interval at which we wake up, in units of the beacon interval */
+ u16 listen_interval;
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+/** Association or reassociation response frame data */
+struct ieee80211_assoc_or_reassoc_resp
+{
+ /** Capability flags */
+ u16 capability;
+
+ /** Status code */
+ u16 status;
+
+ /** Association ID */
+ u16 aid;
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+#define ieee80211_assoc_resp ieee80211_assoc_or_reassoc_resp
+#define ieee80211_reassoc_resp ieee80211_assoc_or_reassoc_resp
+
+/** Reassociation request frame data */
+struct ieee80211_reassoc_req
+{
+ /** Capability flags */
+ u16 capability;
+
+ /** Interval at which we wake up, in units of the beacon interval */
+ u16 listen_interval;
+
+ /** MAC address of current Access Point */
+ u8 current_addr[ETH_ALEN];
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+/** Probe request frame data */
+struct ieee80211_probe_req
+{
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+/** Authentication frame data */
+struct ieee80211_auth
+{
+ /** Authentication algorithm (Open System or Shared Key) */
+ u16 algorithm;
+
+ /** Sequence number of this frame; first from client to AP is 1 */
+ u16 tx_seq;
+
+ /** Status code */
+ u16 status;
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+/** Open System authentication algorithm */
+#define IEEE80211_AUTH_OPEN_SYSTEM 0
+
+/** Shared Key authentication algorithm */
+#define IEEE80211_AUTH_SHARED_KEY 1
+
+/** @} */
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/if_arp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/if_arp.h
new file mode 100644
index 00000000..fd36e9c6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/if_arp.h
@@ -0,0 +1,102 @@
+#ifndef _IPXE_IF_ARP_H
+#define _IPXE_IF_ARP_H
+
+/** @file
+ *
+ * Address Resolution Protocol constants and types
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/* ARP protocol HARDWARE identifiers. */
+#define ARPHRD_NETROM 0 /**< from KA9Q: NET/ROM pseudo */
+#define ARPHRD_ETHER 1 /**< Ethernet 10Mbps */
+#define ARPHRD_EETHER 2 /**< Experimental Ethernet */
+#define ARPHRD_AX25 3 /**< AX.25 Level 2 */
+#define ARPHRD_PRONET 4 /**< PROnet token ring */
+#define ARPHRD_CHAOS 5 /**< Chaosnet */
+#define ARPHRD_IEEE802 6 /**< IEEE 802.2 Ethernet/TR/TB */
+#define ARPHRD_ARCNET 7 /**< ARCnet */
+#define ARPHRD_APPLETLK 8 /**< APPLEtalk */
+#define ARPHRD_DLCI 15 /**< Frame Relay DLCI */
+#define ARPHRD_ATM 19 /**< ATM */
+#define ARPHRD_METRICOM 23 /**< Metricom STRIP (new IANA id) */
+#define ARPHRD_IEEE1394 24 /**< IEEE 1394 IPv4 - RFC 2734 */
+#define ARPHRD_EUI64 27 /**< EUI-64 */
+#define ARPHRD_INFINIBAND 32 /**< InfiniBand */
+
+/* ARP protocol opcodes. */
+#define ARPOP_REQUEST 1 /**< ARP request */
+#define ARPOP_REPLY 2 /**< ARP reply */
+#define ARPOP_RREQUEST 3 /**< RARP request */
+#define ARPOP_RREPLY 4 /**< RARP reply */
+#define ARPOP_InREQUEST 8 /**< InARP request */
+#define ARPOP_InREPLY 9 /**< InARP reply */
+#define ARPOP_NAK 10 /**< (ATM)ARP NAK */
+
+/**
+ * An ARP header
+ *
+ * This contains only the fixed-size portions of an ARP header; for
+ * other fields use the arp_{sender,target}_{ha,pa} family of
+ * functions.
+ */
+struct arphdr {
+ /** Link-layer protocol
+ *
+ * This is an ARPHRD_XXX constant
+ */
+ uint16_t ar_hrd;
+ /** Network-layer protocol
+ *
+ * This is, for Ethernet, an ETH_P_XXX constant.
+ */
+ uint16_t ar_pro;
+ /** Link-layer address length */
+ uint8_t ar_hln;
+ /** Network-layer address length */
+ uint8_t ar_pln;
+ /** ARP opcode */
+ uint16_t ar_op;
+} __attribute__ (( packed ));
+
+/** ARP packet sender hardware address
+ *
+ * @v arphdr ARP header
+ * @ret ar_sha Sender hardware address
+ */
+static inline void * arp_sender_ha ( struct arphdr *arphdr ) {
+ return ( ( ( void * ) arphdr ) + sizeof ( *arphdr ) );
+}
+
+/** ARP packet sender protocol address
+ *
+ * @v arphdr ARP header
+ * @ret ar_spa Sender protocol address
+ */
+static inline void * arp_sender_pa ( struct arphdr *arphdr ) {
+ return ( arp_sender_ha ( arphdr ) + arphdr->ar_hln );
+}
+
+/** ARP packet target hardware address
+ *
+ * @v arphdr ARP header
+ * @ret ar_tha Target hardware address
+ */
+static inline void * arp_target_ha ( struct arphdr *arphdr ) {
+ return ( arp_sender_pa ( arphdr ) + arphdr->ar_pln );
+}
+
+/** ARP packet target protocol address
+ *
+ * @v arphdr ARP header
+ * @ret ar_tpa Target protocol address
+ */
+static inline void * arp_target_pa ( struct arphdr *arphdr ) {
+ return ( arp_target_ha ( arphdr ) + arphdr->ar_hln );
+}
+
+#endif /* _IPXE_IF_ARP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/if_ether.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/if_ether.h
new file mode 100644
index 00000000..a7e23734
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/if_ether.h
@@ -0,0 +1,39 @@
+#ifndef _IPXE_IF_ETHER_H
+#define _IPXE_IF_ETHER_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+#define ETH_ALEN 6 /* Size of Ethernet address */
+#define ETH_HLEN 14 /* Size of ethernet header */
+#define ETH_ZLEN 60 /* Minimum packet */
+#define ETH_FRAME_LEN 1514 /* Maximum packet */
+#define ETH_DATA_ALIGN 2 /* Amount needed to align the data after an ethernet header */
+#ifndef ETH_MAX_MTU
+#define ETH_MAX_MTU (ETH_FRAME_LEN-ETH_HLEN)
+#endif
+
+#define ETH_P_RAW 0x0000 /* Raw packet */
+#define ETH_P_IP 0x0800 /* Internet Protocl Packet */
+#define ETH_P_ARP 0x0806 /* Address Resolution Protocol */
+#define ETH_P_RARP 0x8035 /* Reverse Address resolution Protocol */
+#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */
+#define ETH_P_IPV6 0x86DD /* IPv6 over blueblook */
+#define ETH_P_SLOW 0x8809 /* Ethernet slow protocols */
+#define ETH_P_EAPOL 0x888E /* 802.1X EAP over LANs */
+#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */
+#define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */
+#define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */
+
+/** An Ethernet link-layer header */
+struct ethhdr {
+ /** Destination MAC address */
+ uint8_t h_dest[ETH_ALEN];
+ /** Source MAC address */
+ uint8_t h_source[ETH_ALEN];
+ /** Protocol ID */
+ uint16_t h_protocol;
+} __attribute__ ((packed));
+
+#endif /* _IPXE_IF_ETHER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/image.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/image.h
new file mode 100644
index 00000000..ac97137b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/image.h
@@ -0,0 +1,207 @@
+#ifndef _IPXE_IMAGE_H
+#define _IPXE_IMAGE_H
+
+/**
+ * @file
+ *
+ * Executable images
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/tables.h>
+#include <ipxe/list.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/refcnt.h>
+
+struct uri;
+struct image_type;
+
+/** An executable image */
+struct image {
+ /** Reference count */
+ struct refcnt refcnt;
+
+ /** List of registered images */
+ struct list_head list;
+
+ /** URI of image */
+ struct uri *uri;
+ /** Name */
+ char *name;
+ /** Flags */
+ unsigned int flags;
+
+ /** Command line to pass to image */
+ char *cmdline;
+ /** Raw file image */
+ userptr_t data;
+ /** Length of raw file image */
+ size_t len;
+
+ /** Image type, if known */
+ struct image_type *type;
+
+ /** Replacement image
+ *
+ * An image wishing to replace itself with another image (in a
+ * style similar to a Unix exec() call) should return from its
+ * exec() method with the replacement image set to point to
+ * the new image.
+ *
+ * If an image unregisters itself as a result of being
+ * executed, it must make sure that its replacement image (if
+ * any) is registered, otherwise the replacement is likely to
+ * be freed before it can be executed.
+ */
+ struct image *replacement;
+};
+
+/** Image is registered */
+#define IMAGE_REGISTERED 0x00001
+
+/** Image is selected for execution */
+#define IMAGE_SELECTED 0x0002
+
+/** Image is trusted */
+#define IMAGE_TRUSTED 0x0004
+
+/** An executable image type */
+struct image_type {
+ /** Name of this image type */
+ char *name;
+ /** Probe image
+ *
+ * @v image Executable image
+ * @ret rc Return status code
+ *
+ * Return success if the image is of this image type.
+ */
+ int ( * probe ) ( struct image *image );
+ /**
+ * Execute image
+ *
+ * @v image Executable image
+ * @ret rc Return status code
+ */
+ int ( * exec ) ( struct image *image );
+};
+
+/**
+ * Multiboot image probe priority
+ *
+ * Multiboot images are also valid executables in another format
+ * (e.g. ELF), so we must perform the multiboot probe first.
+ */
+#define PROBE_MULTIBOOT 01
+
+/**
+ * Normal image probe priority
+ */
+#define PROBE_NORMAL 02
+
+/**
+ * PXE image probe priority
+ *
+ * PXE images have no signature checks, so will claim all image files.
+ * They must therefore be tried last in the probe order list.
+ */
+#define PROBE_PXE 03
+
+/** Executable image type table */
+#define IMAGE_TYPES __table ( struct image_type, "image_types" )
+
+/** An executable image type */
+#define __image_type( probe_order ) __table_entry ( IMAGE_TYPES, probe_order )
+
+extern struct list_head images;
+extern struct image *current_image;
+
+/** Iterate over all registered images */
+#define for_each_image( image ) \
+ list_for_each_entry ( (image), &images, list )
+
+/** Iterate over all registered images, safe against deletion */
+#define for_each_image_safe( image, tmp ) \
+ list_for_each_entry_safe ( (image), (tmp), &images, list )
+
+/**
+ * Test for existence of images
+ *
+ * @ret existence Some images exist
+ */
+static inline int have_images ( void ) {
+ return ( ! list_empty ( &images ) );
+}
+
+/**
+ * Retrieve first image
+ *
+ * @ret image Image, or NULL
+ */
+static inline struct image * first_image ( void ) {
+ return list_first_entry ( &images, struct image, list );
+}
+
+extern struct image * alloc_image ( struct uri *uri );
+extern int image_set_name ( struct image *image, const char *name );
+extern int image_set_cmdline ( struct image *image, const char *cmdline );
+extern int register_image ( struct image *image );
+extern void unregister_image ( struct image *image );
+struct image * find_image ( const char *name );
+extern int image_probe ( struct image *image );
+extern int image_exec ( struct image *image );
+extern int image_replace ( struct image *replacement );
+extern int image_select ( struct image *image );
+extern struct image * image_find_selected ( void );
+extern int image_set_trust ( int require_trusted, int permanent );
+
+/**
+ * Increment reference count on an image
+ *
+ * @v image Image
+ * @ret image Image
+ */
+static inline struct image * image_get ( struct image *image ) {
+ ref_get ( &image->refcnt );
+ return image;
+}
+
+/**
+ * Decrement reference count on an image
+ *
+ * @v image Image
+ */
+static inline void image_put ( struct image *image ) {
+ ref_put ( &image->refcnt );
+}
+
+/**
+ * Clear image command line
+ *
+ * @v image Image
+ */
+static inline void image_clear_cmdline ( struct image *image ) {
+ image_set_cmdline ( image, NULL );
+}
+
+/**
+ * Set image as trusted
+ *
+ * @v image Image
+ */
+static inline void image_trust ( struct image *image ) {
+ image->flags |= IMAGE_TRUSTED;
+}
+
+/**
+ * Set image as untrusted
+ *
+ * @v image Image
+ */
+static inline void image_untrust ( struct image *image ) {
+ image->flags &= ~IMAGE_TRUSTED;
+}
+
+#endif /* _IPXE_IMAGE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/in.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/in.h
new file mode 100644
index 00000000..20f1ce26
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/in.h
@@ -0,0 +1,104 @@
+#ifndef _IPXE_IN_H
+#define _IPXE_IN_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/socket.h>
+
+/* Protocol numbers */
+
+#define IP_ICMP 1
+#define IP_TCP 6
+#define IP_UDP 17
+#define IP_ICMP6 58
+
+/* IP address constants */
+
+#define INADDR_NONE 0xffffffff
+
+#define INADDR_BROADCAST 0xffffffff
+
+#define IN_CLASSA(addr) ( ( (addr) & 0x80000000 ) == 0x00000000 )
+#define IN_CLASSA_NET 0xff000000
+#define IN_CLASSB(addr) ( ( (addr) & 0xc0000000 ) == 0x80000000 )
+#define IN_CLASSB_NET 0xffff0000
+#define IN_CLASSC(addr) ( ( (addr) & 0xe0000000 ) == 0xc0000000 )
+#define IN_CLASSC_NET 0xffffff00
+#define IN_MULTICAST(addr) ( ( (addr) & 0xf0000000 ) == 0xe0000000 )
+
+/**
+ * IP address structure
+ */
+struct in_addr {
+ uint32_t s_addr;
+};
+
+typedef struct in_addr in_addr;
+
+/**
+ * IP6 address structure
+ */
+struct in6_addr {
+ union {
+ uint8_t u6_addr8[16];
+ uint16_t u6_addr16[8];
+ uint32_t u6_addr32[4];
+ } in6_u;
+#define s6_addr in6_u.u6_addr8
+#define s6_addr16 in6_u.u6_addr16
+#define s6_addr32 in6_u.u6_addr32
+};
+
+/**
+ * IPv4 socket address
+ */
+struct sockaddr_in {
+ /** Socket address family (part of struct @c sockaddr)
+ *
+ * Always set to @c AF_INET for IPv4 addresses
+ */
+ sa_family_t sin_family;
+ /** TCP/IP port (part of struct @c sockaddr_tcpip) */
+ uint16_t sin_port;
+ /** IPv4 address */
+ struct in_addr sin_addr;
+ /** Padding
+ *
+ * This ensures that a struct @c sockaddr_tcpip is large
+ * enough to hold a socket address for any TCP/IP address
+ * family.
+ */
+ char pad[ sizeof ( struct sockaddr ) - sizeof ( sa_family_t )
+ - sizeof ( uint16_t )
+ - sizeof ( struct in_addr ) ];
+} __attribute__ (( may_alias ));
+
+/**
+ * IPv6 socket address
+ */
+struct sockaddr_in6 {
+ /** Socket address family (part of struct @c sockaddr)
+ *
+ * Always set to @c AF_INET6 for IPv6 addresses
+ */
+ sa_family_t sin_family;
+ /** TCP/IP port (part of struct @c sockaddr_tcpip) */
+ uint16_t sin_port;
+ uint32_t sin6_flowinfo; /* Flow number */
+ struct in6_addr sin6_addr; /* 128-bit destination address */
+ uint32_t sin6_scope_id; /* Scope ID */
+} __attribute__ (( may_alias ));
+
+extern int inet_aton ( const char *cp, struct in_addr *inp );
+extern char * inet_ntoa ( struct in_addr in );
+
+/* Adding the following for IP6 support
+ *
+
+extern int inet6_aton ( const char *cp, struct in6_addr *inp );
+extern char * inet6_ntoa ( struct in_addr in );
+
+ */
+
+#endif /* _IPXE_IN_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/infiniband.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/infiniband.h
new file mode 100644
index 00000000..f97a5d4f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/infiniband.h
@@ -0,0 +1,705 @@
+#ifndef _IPXE_INFINIBAND_H
+#define _IPXE_INFINIBAND_H
+
+/** @file
+ *
+ * Infiniband protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/device.h>
+#include <ipxe/tables.h>
+#include <ipxe/ib_packet.h>
+#include <ipxe/ib_mad.h>
+
+/** Subnet management interface QPN */
+#define IB_QPN_SMI 0
+
+/** Subnet management interface queue key */
+#define IB_QKEY_SMI 0
+
+/** General service interface QPN */
+#define IB_QPN_GSI 1
+
+/** General service interface queue key */
+#define IB_QKEY_GSI 0x80010000UL
+
+/** Broadcast QPN */
+#define IB_QPN_BROADCAST 0xffffffUL
+
+/** QPN mask */
+#define IB_QPN_MASK 0xffffffUL
+
+/** Default Infiniband partition key */
+#define IB_PKEY_DEFAULT 0xffff
+
+/** Infiniband partition key full membership flag */
+#define IB_PKEY_FULL 0x8000
+
+/**
+ * Maximum payload size
+ *
+ * This is currently hard-coded in various places (drivers, subnet
+ * management agent, etc.) to 2048.
+ */
+#define IB_MAX_PAYLOAD_SIZE 2048
+
+struct ib_device;
+struct ib_queue_pair;
+struct ib_address_vector;
+struct ib_completion_queue;
+struct ib_mad_interface;
+
+/** Infiniband transmission rates */
+enum ib_rate {
+ IB_RATE_2_5 = 2,
+ IB_RATE_10 = 3,
+ IB_RATE_30 = 4,
+ IB_RATE_5 = 5,
+ IB_RATE_20 = 6,
+ IB_RATE_40 = 7,
+ IB_RATE_60 = 8,
+ IB_RATE_80 = 9,
+ IB_RATE_120 = 10,
+};
+
+/** An Infiniband Address Vector */
+struct ib_address_vector {
+ /** Queue Pair Number */
+ unsigned long qpn;
+ /** Queue key
+ *
+ * Not specified for received packets.
+ */
+ unsigned long qkey;
+ /** Local ID */
+ unsigned int lid;
+ /** Rate
+ *
+ * Not specified for received packets.
+ */
+ enum ib_rate rate;
+ /** Service level */
+ unsigned int sl;
+ /** GID is present */
+ unsigned int gid_present;
+ /** GID, if present */
+ union ib_gid gid;
+ /** VLAN is present */
+ unsigned int vlan_present;
+ /** VLAN, if present */
+ unsigned int vlan;
+};
+
+/** An Infiniband Work Queue */
+struct ib_work_queue {
+ /** Containing queue pair */
+ struct ib_queue_pair *qp;
+ /** "Is a send queue" flag */
+ int is_send;
+ /** Associated completion queue */
+ struct ib_completion_queue *cq;
+ /** List of work queues on this completion queue */
+ struct list_head list;
+ /** Packet sequence number */
+ uint32_t psn;
+ /** Number of work queue entries */
+ unsigned int num_wqes;
+ /** Number of occupied work queue entries */
+ unsigned int fill;
+ /** Next work queue entry index
+ *
+ * This is the index of the next entry to be filled (i.e. the
+ * first empty entry). This value is not bounded by num_wqes;
+ * users must logical-AND with (num_wqes-1) to generate an
+ * array index.
+ */
+ unsigned long next_idx;
+ /** I/O buffers assigned to work queue */
+ struct io_buffer **iobufs;
+ /** Driver private data */
+ void *drv_priv;
+};
+
+/** An Infiniband multicast GID */
+struct ib_multicast_gid {
+ /** List of multicast GIDs on this QP */
+ struct list_head list;
+ /** Multicast GID */
+ union ib_gid gid;
+};
+
+/** An Infiniband queue pair type */
+enum ib_queue_pair_type {
+ IB_QPT_SMI,
+ IB_QPT_GSI,
+ IB_QPT_UD,
+ IB_QPT_RC,
+ IB_QPT_ETH,
+};
+
+/** An Infiniband Queue Pair */
+struct ib_queue_pair {
+ /** Containing Infiniband device */
+ struct ib_device *ibdev;
+ /** List of queue pairs on this Infiniband device */
+ struct list_head list;
+ /** Queue pair number */
+ unsigned long qpn;
+ /** Externally-visible queue pair number
+ *
+ * This may differ from the real queue pair number (e.g. when
+ * the HCA cannot use the management QPNs 0 and 1 as hardware
+ * QPNs and needs to remap them).
+ */
+ unsigned long ext_qpn;
+ /** Queue pair type */
+ enum ib_queue_pair_type type;
+ /** Queue key */
+ unsigned long qkey;
+ /** Send queue */
+ struct ib_work_queue send;
+ /** Receive queue */
+ struct ib_work_queue recv;
+ /** List of multicast GIDs */
+ struct list_head mgids;
+ /** Address vector */
+ struct ib_address_vector av;
+ /** Driver private data */
+ void *drv_priv;
+ /** Queue owner private data */
+ void *owner_priv;
+};
+
+/** Infiniband completion queue operations */
+struct ib_completion_queue_operations {
+ /**
+ * Complete Send WQE
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+ void ( * complete_send ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf, int rc );
+ /**
+ * Complete Receive WQE
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector, or NULL
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+ void ( * complete_recv ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc );
+};
+
+/** An Infiniband Completion Queue */
+struct ib_completion_queue {
+ /** Containing Infiniband device */
+ struct ib_device *ibdev;
+ /** List of completion queues on this Infiniband device */
+ struct list_head list;
+ /** Completion queue number */
+ unsigned long cqn;
+ /** Number of completion queue entries */
+ unsigned int num_cqes;
+ /** Next completion queue entry index
+ *
+ * This is the index of the next entry to be filled (i.e. the
+ * first empty entry). This value is not bounded by num_wqes;
+ * users must logical-AND with (num_wqes-1) to generate an
+ * array index.
+ */
+ unsigned long next_idx;
+ /** List of work queues completing to this queue */
+ struct list_head work_queues;
+ /** Completion queue operations */
+ struct ib_completion_queue_operations *op;
+ /** Driver private data */
+ void *drv_priv;
+};
+
+/**
+ * Infiniband device operations
+ *
+ * These represent a subset of the Infiniband Verbs.
+ */
+struct ib_device_operations {
+ /** Create completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ * @ret rc Return status code
+ */
+ int ( * create_cq ) ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq );
+ /** Destroy completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+ void ( * destroy_cq ) ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq );
+ /** Create queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+ int ( * create_qp ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp );
+ /** Modify queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+ int ( * modify_qp ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp );
+ /** Destroy queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+ void ( * destroy_qp ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp );
+ /** Post send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * If this method returns success, the I/O buffer remains
+ * owned by the queue pair. If this method returns failure,
+ * the I/O buffer is immediately released; the failure is
+ * interpreted as "failure to enqueue buffer".
+ */
+ int ( * post_send ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf );
+ /** Post receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * If this method returns success, the I/O buffer remains
+ * owned by the queue pair. If this method returns failure,
+ * the I/O buffer is immediately released; the failure is
+ * interpreted as "failure to enqueue buffer".
+ */
+ int ( * post_recv ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf );
+ /** Poll completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ *
+ * The relevant completion handler (specified at completion
+ * queue creation time) takes ownership of the I/O buffer.
+ */
+ void ( * poll_cq ) ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq );
+ /**
+ * Poll event queue
+ *
+ * @v ibdev Infiniband device
+ */
+ void ( * poll_eq ) ( struct ib_device *ibdev );
+ /**
+ * Open port
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+ int ( * open ) ( struct ib_device *ibdev );
+ /**
+ * Close port
+ *
+ * @v ibdev Infiniband device
+ */
+ void ( * close ) ( struct ib_device *ibdev );
+ /** Attach to multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ * @ret rc Return status code
+ */
+ int ( * mcast_attach ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ union ib_gid *gid );
+ /** Detach from multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ */
+ void ( * mcast_detach ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ union ib_gid *gid );
+ /** Set port information
+ *
+ * @v ibdev Infiniband device
+ * @v mad Set port information MAD
+ *
+ * This method is required only by adapters that do not have
+ * an embedded SMA.
+ */
+ int ( * set_port_info ) ( struct ib_device *ibdev, union ib_mad *mad );
+ /** Set partition key table
+ *
+ * @v ibdev Infiniband device
+ * @v mad Set partition key table MAD
+ *
+ * This method is required only by adapters that do not have
+ * an embedded SMA.
+ */
+ int ( * set_pkey_table ) ( struct ib_device *ibdev,
+ union ib_mad *mad );
+};
+
+/** An Infiniband device */
+struct ib_device {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** List of Infiniband devices */
+ struct list_head list;
+ /** List of open Infiniband devices */
+ struct list_head open_list;
+ /** Underlying device */
+ struct device *dev;
+ /** List of completion queues */
+ struct list_head cqs;
+ /** List of queue pairs */
+ struct list_head qps;
+ /** Infiniband operations */
+ struct ib_device_operations *op;
+ /** Port number */
+ unsigned int port;
+ /** Port open request counter */
+ unsigned int open_count;
+
+ /** Port state */
+ uint8_t port_state;
+ /** Link width supported */
+ uint8_t link_width_supported;
+ /** Link width enabled */
+ uint8_t link_width_enabled;
+ /** Link width active */
+ uint8_t link_width_active;
+ /** Link speed supported */
+ uint8_t link_speed_supported;
+ /** Link speed enabled */
+ uint8_t link_speed_enabled;
+ /** Link speed active */
+ uint8_t link_speed_active;
+ /** Node GUID */
+ union ib_guid node_guid;
+ /** Port GID (comprising GID prefix and port GUID) */
+ union ib_gid gid;
+ /** Port LID */
+ uint16_t lid;
+ /** Subnet manager LID */
+ uint16_t sm_lid;
+ /** Subnet manager SL */
+ uint8_t sm_sl;
+ /** Partition key */
+ uint16_t pkey;
+
+ /** RDMA key
+ *
+ * This is a single key allowing unrestricted access to
+ * memory.
+ */
+ uint32_t rdma_key;
+
+ /** Subnet management interface */
+ struct ib_mad_interface *smi;
+ /** General services interface */
+ struct ib_mad_interface *gsi;
+
+ /** Driver private data */
+ void *drv_priv;
+ /** Owner private data */
+ void *owner_priv;
+};
+
+/** An Infiniband upper-layer driver */
+struct ib_driver {
+ /** Name */
+ const char *name;
+ /** Probe device
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct ib_device *ibdev );
+ /** Notify of device or link state change
+ *
+ * @v ibdev Infiniband device
+ */
+ void ( * notify ) ( struct ib_device *ibdev );
+ /** Remove device
+ *
+ * @v ibdev Infiniband device
+ */
+ void ( * remove ) ( struct ib_device *ibdev );
+};
+
+/** Infiniband driver table */
+#define IB_DRIVERS __table ( struct ib_driver, "ib_drivers" )
+
+/** Declare an Infiniband driver */
+#define __ib_driver __table_entry ( IB_DRIVERS, 01 )
+
+extern struct ib_completion_queue *
+ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
+ struct ib_completion_queue_operations *op );
+extern void ib_destroy_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq );
+extern void ib_poll_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq );
+extern struct ib_queue_pair *
+ib_create_qp ( struct ib_device *ibdev, enum ib_queue_pair_type type,
+ unsigned int num_send_wqes, struct ib_completion_queue *send_cq,
+ unsigned int num_recv_wqes,
+ struct ib_completion_queue *recv_cq );
+extern int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp );
+extern void ib_destroy_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp );
+extern struct ib_queue_pair * ib_find_qp_qpn ( struct ib_device *ibdev,
+ unsigned long qpn );
+extern struct ib_queue_pair * ib_find_qp_mgid ( struct ib_device *ibdev,
+ union ib_gid *gid );
+extern struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
+ unsigned long qpn, int is_send );
+extern int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf );
+extern int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct io_buffer *iobuf );
+extern void ib_complete_send ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf, int rc );
+extern void ib_complete_recv ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc );
+extern void ib_refill_recv ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp );
+extern int ib_open ( struct ib_device *ibdev );
+extern void ib_close ( struct ib_device *ibdev );
+extern int ib_link_rc ( struct ib_device *ibdev );
+extern int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ union ib_gid *gid );
+extern void ib_mcast_detach ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp, union ib_gid *gid );
+extern int ib_count_ports ( struct ib_device *ibdev );
+extern int ib_set_port_info ( struct ib_device *ibdev, union ib_mad *mad );
+extern int ib_set_pkey_table ( struct ib_device *ibdev, union ib_mad *mad );
+extern struct ib_device * alloc_ibdev ( size_t priv_size );
+extern int register_ibdev ( struct ib_device *ibdev );
+extern void unregister_ibdev ( struct ib_device *ibdev );
+extern struct ib_device * find_ibdev ( union ib_gid *gid );
+extern struct ib_device * last_opened_ibdev ( void );
+extern void ib_link_state_changed ( struct ib_device *ibdev );
+extern void ib_poll_eq ( struct ib_device *ibdev );
+extern struct list_head ib_devices;
+
+/** Iterate over all network devices */
+#define for_each_ibdev( ibdev ) \
+ list_for_each_entry ( (ibdev), &ib_devices, list )
+
+/**
+ * Check link state of Infiniband device
+ *
+ * @v ibdev Infiniband device
+ * @ret link_up Link is up
+ */
+static inline __always_inline int
+ib_link_ok ( struct ib_device *ibdev ) {
+ return ( ibdev->port_state == IB_PORT_STATE_ACTIVE );
+}
+
+/**
+ * Check whether or not Infiniband device is open
+ *
+ * @v ibdev Infiniband device
+ * @v is_open Infiniband device is open
+ */
+static inline __attribute__ (( always_inline )) int
+ib_is_open ( struct ib_device *ibdev ) {
+ return ( ibdev->open_count > 0 );
+}
+
+/**
+ * Get reference to Infiniband device
+ *
+ * @v ibdev Infiniband device
+ * @ret ibdev Infiniband device
+ */
+static inline __always_inline struct ib_device *
+ibdev_get ( struct ib_device *ibdev ) {
+ ref_get ( &ibdev->refcnt );
+ return ibdev;
+}
+
+/**
+ * Drop reference to Infiniband device
+ *
+ * @v ibdev Infiniband device
+ */
+static inline __always_inline void
+ibdev_put ( struct ib_device *ibdev ) {
+ ref_put ( &ibdev->refcnt );
+}
+
+/**
+ * Set Infiniband work queue driver-private data
+ *
+ * @v wq Work queue
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_wq_set_drvdata ( struct ib_work_queue *wq, void *priv ) {
+ wq->drv_priv = priv;
+}
+
+/**
+ * Get Infiniband work queue driver-private data
+ *
+ * @v wq Work queue
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_wq_get_drvdata ( struct ib_work_queue *wq ) {
+ return wq->drv_priv;
+}
+
+/**
+ * Set Infiniband queue pair driver-private data
+ *
+ * @v qp Queue pair
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_qp_set_drvdata ( struct ib_queue_pair *qp, void *priv ) {
+ qp->drv_priv = priv;
+}
+
+/**
+ * Get Infiniband queue pair driver-private data
+ *
+ * @v qp Queue pair
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_qp_get_drvdata ( struct ib_queue_pair *qp ) {
+ return qp->drv_priv;
+}
+
+/**
+ * Set Infiniband queue pair owner-private data
+ *
+ * @v qp Queue pair
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_qp_set_ownerdata ( struct ib_queue_pair *qp, void *priv ) {
+ qp->owner_priv = priv;
+}
+
+/**
+ * Get Infiniband queue pair owner-private data
+ *
+ * @v qp Queue pair
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_qp_get_ownerdata ( struct ib_queue_pair *qp ) {
+ return qp->owner_priv;
+}
+
+/**
+ * Set Infiniband completion queue driver-private data
+ *
+ * @v cq Completion queue
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_cq_set_drvdata ( struct ib_completion_queue *cq, void *priv ) {
+ cq->drv_priv = priv;
+}
+
+/**
+ * Get Infiniband completion queue driver-private data
+ *
+ * @v cq Completion queue
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_cq_get_drvdata ( struct ib_completion_queue *cq ) {
+ return cq->drv_priv;
+}
+
+/**
+ * Set Infiniband device driver-private data
+ *
+ * @v ibdev Infiniband device
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_set_drvdata ( struct ib_device *ibdev, void *priv ) {
+ ibdev->drv_priv = priv;
+}
+
+/**
+ * Get Infiniband device driver-private data
+ *
+ * @v ibdev Infiniband device
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_get_drvdata ( struct ib_device *ibdev ) {
+ return ibdev->drv_priv;
+}
+
+/**
+ * Set Infiniband device owner-private data
+ *
+ * @v ibdev Infiniband device
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_set_ownerdata ( struct ib_device *ibdev, void *priv ) {
+ ibdev->owner_priv = priv;
+}
+
+/**
+ * Get Infiniband device owner-private data
+ *
+ * @v ibdev Infiniband device
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_get_ownerdata ( struct ib_device *ibdev ) {
+ return ibdev->owner_priv;
+}
+
+#endif /* _IPXE_INFINIBAND_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/init.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/init.h
new file mode 100644
index 00000000..19c5925b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/init.h
@@ -0,0 +1,88 @@
+#ifndef _IPXE_INIT_H
+#define _IPXE_INIT_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/tables.h>
+
+/**
+ * An initialisation function
+ *
+ * Initialisation functions are called exactly once, as part of the
+ * call to initialise().
+ */
+struct init_fn {
+ void ( * initialise ) ( void );
+};
+
+/** Initialisation function table */
+#define INIT_FNS __table ( struct init_fn, "init_fns" )
+
+/** Declare an initialisation functon */
+#define __init_fn( init_order ) __table_entry ( INIT_FNS, init_order )
+
+/** @defgroup initfn_order Initialisation function ordering
+ * @{
+ */
+
+#define INIT_EARLY 01 /**< Early initialisation */
+#define INIT_SERIAL 02 /**< Serial driver initialisation */
+#define INIT_CONSOLE 03 /**< Console initialisation */
+#define INIT_NORMAL 04 /**< Normal initialisation */
+#define INIT_LATE 05 /**< Late initialisation */
+
+/** @} */
+
+/**
+ * A startup/shutdown function
+ *
+ * Startup and shutdown functions may be called multiple times, as
+ * part of the calls to startup() and shutdown().
+ */
+struct startup_fn {
+ void ( * startup ) ( void );
+ void ( * shutdown ) ( int booting );
+};
+
+/** Startup/shutdown function table */
+#define STARTUP_FNS __table ( struct startup_fn, "startup_fns" )
+
+/** Declare a startup/shutdown function */
+#define __startup_fn( startup_order ) \
+ __table_entry ( STARTUP_FNS, startup_order )
+
+/** @defgroup startfn_order Startup/shutdown function ordering
+ *
+ * Shutdown functions are called in the reverse order to startup
+ * functions.
+ *
+ * @{
+ */
+
+#define STARTUP_EARLY 01 /**< Early startup */
+#define STARTUP_NORMAL 02 /**< Normal startup */
+#define STARTUP_LATE 03 /**< Late startup */
+
+/** @} */
+
+extern void initialise ( void );
+extern void startup ( void );
+extern void shutdown ( int booting );
+
+/**
+ * Shut down system for OS boot
+ *
+ */
+static inline void shutdown_boot ( void ) {
+ shutdown ( 1 );
+}
+
+/**
+ * Shut down system for exit back to firmware
+ *
+ */
+static inline void shutdown_exit ( void ) {
+ shutdown ( 0 );
+}
+
+#endif /* _IPXE_INIT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/interface.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/interface.h
new file mode 100644
index 00000000..a474aaad
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/interface.h
@@ -0,0 +1,234 @@
+#ifndef _IPXE_INTERFACE_H
+#define _IPXE_INTERFACE_H
+
+/** @file
+ *
+ * Object interfaces
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <ipxe/refcnt.h>
+
+/** An object interface operation */
+struct interface_operation {
+ /** Operation type */
+ void *type;
+ /** Implementing method */
+ void *func;
+};
+
+/**
+ * Define an object interface operation
+ *
+ * @v op_type Operation type
+ * @v object_type Implementing method's expected object type
+ * @v op_func Implementing method
+ * @ret op Object interface operation
+ */
+#define INTF_OP( op_type, object_type, op_func ) { \
+ .type = op_type, \
+ .func = ( ( ( ( typeof ( op_func ) * ) NULL ) == \
+ ( ( op_type ## _TYPE ( object_type ) * ) NULL ) ) \
+ ? op_func : op_func ), \
+ }
+
+/** An object interface descriptor */
+struct interface_descriptor {
+ /** Offset of interface within containing object */
+ size_t offset;
+ /** Number of interface operations */
+ unsigned int num_op;
+ /** Object interface operations */
+ struct interface_operation *op;
+ /** Offset to pass-through interface, if present */
+ ssize_t passthru_offset;
+};
+
+#define intf_offset( object_type, intf ) \
+ ( ( ( ( typeof ( ( ( object_type * ) NULL )->intf ) * ) NULL ) \
+ == ( ( struct interface * ) NULL ) ) \
+ ? offsetof ( object_type, intf ) \
+ : offsetof ( object_type, intf ) )
+
+/**
+ * Define an object interface descriptor
+ *
+ * @v object_type Containing object data type
+ * @v intf Interface name (i.e. field within object data type)
+ * @v operations Object interface operations array
+ * @ret desc Object interface descriptor
+ */
+#define INTF_DESC( object_type, intf, operations ) { \
+ .offset = intf_offset ( object_type, intf ), \
+ .op = operations, \
+ .num_op = ( sizeof ( operations ) / \
+ sizeof ( operations[0] ) ), \
+ .passthru_offset = 0, \
+ }
+
+/**
+ * Define an object interface descriptor with pass-through interface
+ *
+ * @v object_type Containing object data type
+ * @v intf Interface name (i.e. field within object data type)
+ * @v operations Object interface operations array
+ * @v passthru Pass-through interface name
+ * @ret desc Object interface descriptor
+ */
+#define INTF_DESC_PASSTHRU( object_type, intf, operations, passthru ) { \
+ .offset = offsetof ( object_type, intf ), \
+ .op = operations, \
+ .num_op = ( sizeof ( operations ) / \
+ sizeof ( operations[0] ) ), \
+ .passthru_offset = ( intf_offset ( object_type, passthru ) - \
+ intf_offset ( object_type, intf ) ), \
+ }
+
+/**
+ * Define an object interface descriptor for a pure-interface object
+ *
+ * @v operations Object interface operations array
+ * @ret desc Object interface descriptor
+ *
+ * A pure-interface object is an object that consists solely of a
+ * single interface.
+ */
+#define INTF_DESC_PURE( operations ) { \
+ .offset = 0, \
+ .op = operations, \
+ .num_op = ( sizeof ( operations ) / \
+ sizeof ( operations[0] ) ), \
+ .passthru_offset = 0, \
+ }
+
+/** An object interface */
+struct interface {
+ /** Destination object interface
+ *
+ * When the containing object invokes an operation on this
+ * interface, it will be executed by the destination object.
+ *
+ * This pointer may never be NULL. When the interface is
+ * unplugged, it should point to the null interface.
+ */
+ struct interface *dest;
+ /** Reference counter
+ *
+ * If this interface is not part of a reference-counted
+ * object, this field may be NULL.
+ */
+ struct refcnt *refcnt;
+ /** Interface descriptor */
+ struct interface_descriptor *desc;
+};
+
+extern void intf_plug ( struct interface *intf, struct interface *dest );
+extern void intf_plug_plug ( struct interface *a, struct interface *b );
+extern void intf_unplug ( struct interface *intf );
+extern void intf_nullify ( struct interface *intf );
+extern struct interface * intf_get ( struct interface *intf );
+extern void intf_put ( struct interface *intf );
+extern void * __attribute__ (( pure )) intf_object ( struct interface *intf );
+extern void * intf_get_dest_op_no_passthru_untyped ( struct interface *intf,
+ void *type,
+ struct interface **dest );
+extern void * intf_get_dest_op_untyped ( struct interface *intf, void *type,
+ struct interface **dest );
+
+extern void intf_close ( struct interface *intf, int rc );
+#define intf_close_TYPE( object_type ) \
+ typeof ( void ( object_type, int rc ) )
+
+extern void intf_shutdown ( struct interface *intf, int rc );
+extern void intf_restart ( struct interface *intf, int rc );
+
+extern struct interface_descriptor null_intf_desc;
+extern struct interface null_intf;
+
+/**
+ * Initialise an object interface
+ *
+ * @v intf Object interface
+ * @v desc Object interface descriptor
+ * @v refcnt Containing object reference counter, or NULL
+ */
+static inline void intf_init ( struct interface *intf,
+ struct interface_descriptor *desc,
+ struct refcnt *refcnt ) {
+ intf->dest = &null_intf;
+ intf->refcnt = refcnt;
+ intf->desc = desc;
+}
+
+/**
+ * Initialise a static object interface
+ *
+ * @v descriptor Object interface descriptor
+ */
+#define INTF_INIT( descriptor ) { \
+ .dest = &null_intf, \
+ .refcnt = NULL, \
+ .desc = &(descriptor), \
+ }
+
+/**
+ * Get object interface destination and operation method (without pass-through)
+ *
+ * @v intf Object interface
+ * @v type Operation type
+ * @ret dest Destination interface
+ * @ret func Implementing method, or NULL
+ */
+#define intf_get_dest_op_no_passthru( intf, type, dest ) \
+ ( ( type ## _TYPE ( void * ) * ) \
+ intf_get_dest_op_no_passthru_untyped ( intf, type, dest ) )
+
+/**
+ * Get object interface destination and operation method
+ *
+ * @v intf Object interface
+ * @v type Operation type
+ * @ret dest Destination interface
+ * @ret func Implementing method, or NULL
+ */
+#define intf_get_dest_op( intf, type, dest ) \
+ ( ( type ## _TYPE ( void * ) * ) \
+ intf_get_dest_op_untyped ( intf, type, dest ) )
+
+/**
+ * Find debugging colourisation for an object interface
+ *
+ * @v intf Object interface
+ * @ret col Debugging colourisation
+ *
+ * Use as the first argument to DBGC() or equivalent macro.
+ */
+#define INTF_COL( intf ) intf_object ( intf )
+
+/** printf() format string for INTF_DBG() */
+#define INTF_FMT "%p+%zx"
+
+/**
+ * printf() arguments for representing an object interface
+ *
+ * @v intf Object interface
+ * @ret args printf() argument list corresponding to INTF_FMT
+ */
+#define INTF_DBG( intf ) intf_object ( intf ), (intf)->desc->offset
+
+/** printf() format string for INTF_INTF_DBG() */
+#define INTF_INTF_FMT INTF_FMT "->" INTF_FMT
+
+/**
+ * printf() arguments for representing an object interface pair
+ *
+ * @v intf Object interface
+ * @v dest Destination object interface
+ * @ret args printf() argument list corresponding to INTF_INTF_FMT
+ */
+#define INTF_INTF_DBG( intf, dest ) INTF_DBG ( intf ), INTF_DBG ( dest )
+
+#endif /* _IPXE_INTERFACE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/io.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/io.h
new file mode 100644
index 00000000..b4d88fe8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/io.h
@@ -0,0 +1,532 @@
+#ifndef _IPXE_IO_H
+#define _IPXE_IO_H
+
+/** @file
+ *
+ * iPXE I/O API
+ *
+ * The I/O API provides methods for reading from and writing to
+ * memory-mapped and I/O-mapped devices.
+ *
+ * The standard methods (readl()/writel() etc.) do not strictly check
+ * the type of the address parameter; this is because traditional
+ * usage does not necessarily provide the correct pointer type. For
+ * example, code written for ISA devices at fixed I/O addresses (such
+ * as the keyboard controller) tend to use plain integer constants for
+ * the address parameter.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/api.h>
+#include <config/ioapi.h>
+#include <ipxe/uaccess.h>
+
+/**
+ * Calculate static inline I/O API function name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ */
+#define IOAPI_INLINE( _subsys, _api_func ) \
+ SINGLE_API_INLINE ( IOAPI_PREFIX_ ## _subsys, _api_func )
+
+/**
+ * Provide an I/O API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_IOAPI( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( IOAPI_PREFIX_ ## _subsys, _api_func, _func )
+
+/**
+ * Provide a static inline I/O API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ */
+#define PROVIDE_IOAPI_INLINE( _subsys, _api_func ) \
+ PROVIDE_SINGLE_API_INLINE ( IOAPI_PREFIX_ ## _subsys, _api_func )
+
+/* Include all architecture-independent I/O API headers */
+#include <ipxe/efi/efi_io.h>
+
+/* Include all architecture-dependent I/O API headers */
+#include <bits/io.h>
+
+/**
+ * Wrap an I/O read
+ *
+ * @v _func I/O API function
+ * @v _type Data type
+ * @v io_addr I/O address
+ * @v _prefix Prefix for address in debug message
+ * @v _ndigits Number of hex digits for this data type
+ */
+#define IOAPI_READ( _func, _type, io_addr, _prefix, _ndigits ) ( { \
+ volatile _type *_io_addr = \
+ ( ( volatile _type * ) ( intptr_t ) (io_addr) ); \
+ _type _data = _func ( _io_addr ); \
+ DBGIO ( "[" _prefix " %08lx] => %0" #_ndigits "llx\n", \
+ io_to_bus ( _io_addr ), ( unsigned long long ) _data ); \
+ _data; } )
+
+/**
+ * Wrap an I/O write
+ *
+ * @v _func I/O API function
+ * @v _type Data type
+ * @v data Value to write
+ * @v io_addr I/O address
+ * @v _prefix Prefix for address in debug message
+ * @v _ndigits Number of hex digits for this data type
+ */
+#define IOAPI_WRITE( _func, _type, data, io_addr, _prefix, _ndigits ) do { \
+ volatile _type *_io_addr = \
+ ( ( volatile _type * ) ( intptr_t ) (io_addr) ); \
+ _type _data = (data); \
+ DBGIO ( "[" _prefix " %08lx] <= %0" #_ndigits "llx\n", \
+ io_to_bus ( _io_addr ), ( unsigned long long ) _data ); \
+ _func ( _data, _io_addr ); \
+ } while ( 0 )
+
+/**
+ * Wrap an I/O string read
+ *
+ * @v _func I/O API function
+ * @v _type Data type
+ * @v io_addr I/O address
+ * @v data Data buffer
+ * @v count Number of elements to read
+ * @v _prefix Prefix for address in debug message
+ * @v _ndigits Number of hex digits for this data type
+ */
+#define IOAPI_READS( _func, _type, io_addr, data, count, _prefix, _ndigits ) \
+ do { \
+ volatile _type *_io_addr = \
+ ( ( volatile _type * ) ( intptr_t ) (io_addr) ); \
+ void *_data_void = (data); /* Check data is a pointer */ \
+ _type * _data = ( ( _type * ) _data_void ); \
+ const _type * _dbg_data = _data; \
+ unsigned int _count = (count); \
+ unsigned int _dbg_count = _count; \
+ _func ( _io_addr, _data, _count ); \
+ DBGIO ( "[" _prefix " %08lx] =>", io_to_bus ( _io_addr ) ); \
+ while ( _dbg_count-- ) { \
+ DBGIO ( " %0" #_ndigits "llx", \
+ ( ( unsigned long long ) *(_dbg_data++) ) ); \
+ } \
+ DBGIO ( "\n" ); \
+ } while ( 0 )
+
+/**
+ * Wrap an I/O string write
+ *
+ * @v _func I/O API function
+ * @v _type Data type
+ * @v io_addr I/O address
+ * @v data Data buffer
+ * @v count Number of elements to write
+ * @v _prefix Prefix for address in debug message
+ * @v _ndigits Number of hex digits for this data type
+ */
+#define IOAPI_WRITES( _func, _type, io_addr, data, count, _prefix, _ndigits ) \
+ do { \
+ volatile _type *_io_addr = \
+ ( ( volatile _type * ) ( intptr_t ) (io_addr) ); \
+ const void *_data_void = (data); /* Check data is a pointer */ \
+ const _type * _data = ( ( const _type * ) _data_void ); \
+ const _type * _dbg_data = _data; \
+ unsigned int _count = (count); \
+ unsigned int _dbg_count = _count; \
+ DBGIO ( "[" _prefix " %08lx] <=", io_to_bus ( _io_addr ) ); \
+ while ( _dbg_count-- ) { \
+ DBGIO ( " %0" #_ndigits "llx", \
+ ( ( unsigned long long ) *(_dbg_data++) ) ); \
+ } \
+ DBGIO ( "\n" ); \
+ _func ( _io_addr, _data, _count ); \
+ } while ( 0 )
+
+/**
+ * Convert physical address to a bus address
+ *
+ * @v phys_addr Physical address
+ * @ret bus_addr Bus address
+ */
+unsigned long phys_to_bus ( unsigned long phys_addr );
+
+/**
+ * Convert bus address to a physical address
+ *
+ * @v bus_addr Bus address
+ * @ret phys_addr Physical address
+ */
+unsigned long bus_to_phys ( unsigned long bus_addr );
+
+/**
+ * Convert virtual address to a bus address
+ *
+ * @v addr Virtual address
+ * @ret bus_addr Bus address
+ */
+static inline __always_inline unsigned long
+virt_to_bus ( volatile const void *addr ) {
+ return phys_to_bus ( virt_to_phys ( addr ) );
+}
+
+/**
+ * Convert bus address to a virtual address
+ *
+ * @v bus_addr Bus address
+ * @ret addr Virtual address
+ *
+ * This operation is not available under all memory models.
+ */
+static inline __always_inline void * bus_to_virt ( unsigned long bus_addr ) {
+ return phys_to_virt ( bus_to_phys ( bus_addr ) );
+}
+
+/**
+ * Map bus address as an I/O address
+ *
+ * @v bus_addr Bus address
+ * @v len Length of region
+ * @ret io_addr I/O address
+ */
+void * ioremap ( unsigned long bus_addr, size_t len );
+
+/**
+ * Unmap I/O address
+ *
+ * @v io_addr I/O address
+ */
+void iounmap ( volatile const void *io_addr );
+
+/**
+ * Convert I/O address to bus address (for debug only)
+ *
+ * @v io_addr I/O address
+ * @ret bus_addr Bus address
+ */
+unsigned long io_to_bus ( volatile const void *io_addr );
+
+/**
+ * Read byte from memory-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ */
+uint8_t readb ( volatile uint8_t *io_addr );
+#define readb( io_addr ) IOAPI_READ ( readb, uint8_t, io_addr, "MEM", 2 )
+
+/**
+ * Read 16-bit word from memory-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ */
+uint16_t readw ( volatile uint16_t *io_addr );
+#define readw( io_addr ) IOAPI_READ ( readw, uint16_t, io_addr, "MEM", 4 )
+
+/**
+ * Read 32-bit dword from memory-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ */
+uint32_t readl ( volatile uint32_t *io_addr );
+#define readl( io_addr ) IOAPI_READ ( readl, uint32_t, io_addr, "MEM", 8 )
+
+/**
+ * Read 64-bit qword from memory-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ */
+uint64_t readq ( volatile uint64_t *io_addr );
+#define readq( io_addr ) IOAPI_READ ( readq, uint64_t, io_addr, "MEM", 16 )
+
+/**
+ * Write byte to memory-mapped device
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ */
+void writeb ( uint8_t data, volatile uint8_t *io_addr );
+#define writeb( data, io_addr ) \
+ IOAPI_WRITE ( writeb, uint8_t, data, io_addr, "MEM", 2 )
+
+/**
+ * Write 16-bit word to memory-mapped device
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ */
+void writew ( uint16_t data, volatile uint16_t *io_addr );
+#define writew( data, io_addr ) \
+ IOAPI_WRITE ( writew, uint16_t, data, io_addr, "MEM", 4 )
+
+/**
+ * Write 32-bit dword to memory-mapped device
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ */
+void writel ( uint32_t data, volatile uint32_t *io_addr );
+#define writel( data, io_addr ) \
+ IOAPI_WRITE ( writel, uint32_t, data, io_addr, "MEM", 8 )
+
+/**
+ * Write 64-bit qword to memory-mapped device
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ */
+void writeq ( uint64_t data, volatile uint64_t *io_addr );
+#define writeq( data, io_addr ) \
+ IOAPI_WRITE ( writeq, uint64_t, data, io_addr, "MEM", 16 )
+
+/**
+ * Read byte from I/O-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ */
+uint8_t inb ( volatile uint8_t *io_addr );
+#define inb( io_addr ) IOAPI_READ ( inb, uint8_t, io_addr, "IO", 2 )
+
+/**
+ * Read 16-bit word from I/O-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ */
+uint16_t inw ( volatile uint16_t *io_addr );
+#define inw( io_addr ) IOAPI_READ ( inw, uint16_t, io_addr, "IO", 4 )
+
+/**
+ * Read 32-bit dword from I/O-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ */
+uint32_t inl ( volatile uint32_t *io_addr );
+#define inl( io_addr ) IOAPI_READ ( inl, uint32_t, io_addr, "IO", 8 )
+
+/**
+ * Write byte to I/O-mapped device
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ */
+void outb ( uint8_t data, volatile uint8_t *io_addr );
+#define outb( data, io_addr ) \
+ IOAPI_WRITE ( outb, uint8_t, data, io_addr, "IO", 2 )
+
+/**
+ * Write 16-bit word to I/O-mapped device
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ */
+void outw ( uint16_t data, volatile uint16_t *io_addr );
+#define outw( data, io_addr ) \
+ IOAPI_WRITE ( outw, uint16_t, data, io_addr, "IO", 4 )
+
+/**
+ * Write 32-bit dword to I/O-mapped device
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ */
+void outl ( uint32_t data, volatile uint32_t *io_addr );
+#define outl( data, io_addr ) \
+ IOAPI_WRITE ( outl, uint32_t, data, io_addr, "IO", 8 )
+
+/**
+ * Read bytes from I/O-mapped device
+ *
+ * @v io_addr I/O address
+ * @v data Data buffer
+ * @v count Number of bytes to read
+ */
+void insb ( volatile uint8_t *io_addr, uint8_t *data, unsigned int count );
+#define insb( io_addr, data, count ) \
+ IOAPI_READS ( insb, uint8_t, io_addr, data, count, "IO", 2 )
+
+/**
+ * Read 16-bit words from I/O-mapped device
+ *
+ * @v io_addr I/O address
+ * @v data Data buffer
+ * @v count Number of words to read
+ */
+void insw ( volatile uint16_t *io_addr, uint16_t *data, unsigned int count );
+#define insw( io_addr, data, count ) \
+ IOAPI_READS ( insw, uint16_t, io_addr, data, count, "IO", 4 )
+
+/**
+ * Read 32-bit words from I/O-mapped device
+ *
+ * @v io_addr I/O address
+ * @v data Data buffer
+ * @v count Number of words to read
+ */
+void insl ( volatile uint32_t *io_addr, uint32_t *data, unsigned int count );
+#define insl( io_addr, data, count ) \
+ IOAPI_READS ( insl, uint32_t, io_addr, data, count, "IO", 8 )
+
+/**
+ * Write bytes to I/O-mapped device
+ *
+ * @v io_addr I/O address
+ * @v data Data buffer
+ * @v count Number of bytes to write
+ */
+void outsb ( volatile uint8_t *io_addr, const uint8_t *data,
+ unsigned int count );
+#define outsb( io_addr, data, count ) \
+ IOAPI_WRITES ( outsb, uint8_t, io_addr, data, count, "IO", 2 )
+
+/**
+ * Write 16-bit words to I/O-mapped device
+ *
+ * @v io_addr I/O address
+ * @v data Data buffer
+ * @v count Number of words to write
+ */
+void outsw ( volatile uint16_t *io_addr, const uint16_t *data,
+ unsigned int count );
+#define outsw( io_addr, data, count ) \
+ IOAPI_WRITES ( outsw, uint16_t, io_addr, data, count, "IO", 4 )
+
+/**
+ * Write 32-bit words to I/O-mapped device
+ *
+ * @v io_addr I/O address
+ * @v data Data buffer
+ * @v count Number of words to write
+ */
+void outsl ( volatile uint32_t *io_addr, const uint32_t *data,
+ unsigned int count );
+#define outsl( io_addr, data, count ) \
+ IOAPI_WRITES ( outsl, uint32_t, io_addr, data, count, "IO", 8 )
+
+/**
+ * Slow down I/O
+ *
+ */
+void iodelay ( void );
+
+/**
+ * Read value from I/O-mapped device, slowly
+ *
+ * @v _func Function to use to read value
+ * @v data Value to write
+ * @v io_addr I/O address
+ */
+#define INX_P( _func, _type, io_addr ) ( { \
+ _type _data = _func ( (io_addr) ); \
+ iodelay(); \
+ _data; } )
+
+/**
+ * Read byte from I/O-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ */
+#define inb_p( io_addr ) INX_P ( inb, uint8_t, io_addr )
+
+/**
+ * Read 16-bit word from I/O-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ */
+#define inw_p( io_addr ) INX_P ( inw, uint16_t, io_addr )
+
+/**
+ * Read 32-bit dword from I/O-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ */
+#define inl_p( io_addr ) INX_P ( inl, uint32_t, io_addr )
+
+/**
+ * Write value to I/O-mapped device, slowly
+ *
+ * @v _func Function to use to write value
+ * @v data Value to write
+ * @v io_addr I/O address
+ */
+#define OUTX_P( _func, data, io_addr ) do { \
+ _func ( (data), (io_addr) ); \
+ iodelay(); \
+ } while ( 0 )
+
+/**
+ * Write byte to I/O-mapped device, slowly
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ */
+#define outb_p( data, io_addr ) OUTX_P ( outb, data, io_addr )
+
+/**
+ * Write 16-bit word to I/O-mapped device, slowly
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ */
+#define outw_p( data, io_addr ) OUTX_P ( outw, data, io_addr )
+
+/**
+ * Write 32-bit dword to I/O-mapped device, slowly
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ */
+#define outl_p( data, io_addr ) OUTX_P ( outl, data, io_addr )
+
+/**
+ * Memory barrier
+ *
+ */
+void mb ( void );
+#define rmb() mb()
+#define wmb() mb()
+
+/** A usable memory region */
+struct memory_region {
+ /** Physical start address */
+ uint64_t start;
+ /** Physical end address */
+ uint64_t end;
+};
+
+/** Maximum number of memory regions we expect to encounter */
+#define MAX_MEMORY_REGIONS 8
+
+/** A memory map */
+struct memory_map {
+ /** Memory regions */
+ struct memory_region regions[MAX_MEMORY_REGIONS];
+ /** Number of used regions */
+ unsigned int count;
+};
+
+/**
+ * Get memory map
+ *
+ * @v memmap Memory map to fill in
+ */
+void get_memmap ( struct memory_map *memmap );
+
+#endif /* _IPXE_IO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/iobuf.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/iobuf.h
new file mode 100644
index 00000000..82c8b889
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/iobuf.h
@@ -0,0 +1,229 @@
+#ifndef _IPXE_IOBUF_H
+#define _IPXE_IOBUF_H
+
+/** @file
+ *
+ * I/O buffers
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <assert.h>
+#include <ipxe/list.h>
+
+/**
+ * I/O buffer alignment
+ *
+ * I/O buffers allocated via alloc_iob() are guaranteed to be
+ * physically aligned to this boundary. Some cards cannot DMA across
+ * a 4kB boundary. With a standard Ethernet MTU, aligning to a 2kB
+ * boundary is sufficient to guarantee no 4kB boundary crossings. For
+ * a jumbo Ethernet MTU, a packet may be larger than 4kB anyway.
+ */
+#define IOB_ALIGN 2048
+
+/**
+ * Minimum I/O buffer length
+ *
+ * alloc_iob() will round up the allocated length to this size if
+ * necessary. This is used on behalf of hardware that is not capable
+ * of auto-padding.
+ */
+#define IOB_ZLEN 64
+
+/**
+ * A persistent I/O buffer
+ *
+ * This data structure encapsulates a long-lived I/O buffer. The
+ * buffer may be passed between multiple owners, queued for possible
+ * retransmission, etc.
+ */
+struct io_buffer {
+ /** List of which this buffer is a member
+ *
+ * The list must belong to the current owner of the buffer.
+ * Different owners may maintain different lists (e.g. a
+ * retransmission list for TCP).
+ */
+ struct list_head list;
+
+ /** Start of the buffer */
+ void *head;
+ /** Start of data */
+ void *data;
+ /** End of data */
+ void *tail;
+ /** End of the buffer */
+ void *end;
+};
+
+/**
+ * Reserve space at start of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to reserve
+ * @ret data Pointer to new start of buffer
+ */
+static inline void * iob_reserve ( struct io_buffer *iobuf, size_t len ) {
+ iobuf->data += len;
+ iobuf->tail += len;
+ return iobuf->data;
+}
+#define iob_reserve( iobuf, len ) ( { \
+ void *__result; \
+ __result = iob_reserve ( (iobuf), (len) ); \
+ assert ( (iobuf)->tail <= (iobuf)->end ); \
+ __result; } )
+
+/**
+ * Add data to start of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to add
+ * @ret data Pointer to new start of buffer
+ */
+static inline void * iob_push ( struct io_buffer *iobuf, size_t len ) {
+ iobuf->data -= len;
+ return iobuf->data;
+}
+#define iob_push( iobuf, len ) ( { \
+ void *__result; \
+ __result = iob_push ( (iobuf), (len) ); \
+ assert ( (iobuf)->data >= (iobuf)->head ); \
+ __result; } )
+
+/**
+ * Remove data from start of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to remove
+ * @ret data Pointer to new start of buffer
+ */
+static inline void * iob_pull ( struct io_buffer *iobuf, size_t len ) {
+ iobuf->data += len;
+ assert ( iobuf->data <= iobuf->tail );
+ return iobuf->data;
+}
+#define iob_pull( iobuf, len ) ( { \
+ void *__result; \
+ __result = iob_pull ( (iobuf), (len) ); \
+ assert ( (iobuf)->data <= (iobuf)->tail ); \
+ __result; } )
+
+/**
+ * Add data to end of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to add
+ * @ret data Pointer to newly added space
+ */
+static inline void * iob_put ( struct io_buffer *iobuf, size_t len ) {
+ void *old_tail = iobuf->tail;
+ iobuf->tail += len;
+ return old_tail;
+}
+#define iob_put( iobuf, len ) ( { \
+ void *__result; \
+ __result = iob_put ( (iobuf), (len) ); \
+ assert ( (iobuf)->tail <= (iobuf)->end ); \
+ __result; } )
+
+/**
+ * Remove data from end of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to remove
+ */
+static inline void iob_unput ( struct io_buffer *iobuf, size_t len ) {
+ iobuf->tail -= len;
+}
+#define iob_unput( iobuf, len ) do { \
+ iob_unput ( (iobuf), (len) ); \
+ assert ( (iobuf)->tail >= (iobuf)->data ); \
+ } while ( 0 )
+
+/**
+ * Empty an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ */
+static inline void iob_empty ( struct io_buffer *iobuf ) {
+ iobuf->tail = iobuf->data;
+}
+
+/**
+ * Calculate length of data in an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @ret len Length of data in buffer
+ */
+static inline size_t iob_len ( struct io_buffer *iobuf ) {
+ return ( iobuf->tail - iobuf->data );
+}
+
+/**
+ * Calculate available space at start of an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @ret len Length of data available at start of buffer
+ */
+static inline size_t iob_headroom ( struct io_buffer *iobuf ) {
+ return ( iobuf->data - iobuf->head );
+}
+
+/**
+ * Calculate available space at end of an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @ret len Length of data available at end of buffer
+ */
+static inline size_t iob_tailroom ( struct io_buffer *iobuf ) {
+ return ( iobuf->end - iobuf->tail );
+}
+
+/**
+ * Create a temporary I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v data Data buffer
+ * @v len Length of data
+ * @v max_len Length of buffer
+ *
+ * It is sometimes useful to use the iob_xxx() methods on temporary
+ * data buffers.
+ */
+static inline void iob_populate ( struct io_buffer *iobuf,
+ void *data, size_t len, size_t max_len ) {
+ iobuf->head = iobuf->data = data;
+ iobuf->tail = ( data + len );
+ iobuf->end = ( data + max_len );
+}
+
+/**
+ * Disown an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ *
+ * There are many functions that take ownership of the I/O buffer they
+ * are passed as a parameter. The caller should not retain a pointer
+ * to the I/O buffer. Use iob_disown() to automatically nullify the
+ * caller's pointer, e.g.:
+ *
+ * xfer_deliver_iob ( xfer, iob_disown ( iobuf ) );
+ *
+ * This will ensure that iobuf is set to NULL for any code after the
+ * call to xfer_deliver_iob().
+ */
+#define iob_disown( iobuf ) ( { \
+ struct io_buffer *__iobuf = (iobuf); \
+ (iobuf) = NULL; \
+ __iobuf; } )
+
+extern struct io_buffer * __malloc alloc_iob ( size_t len );
+extern void free_iob ( struct io_buffer *iobuf );
+extern void iob_pad ( struct io_buffer *iobuf, size_t min_len );
+extern int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len );
+
+#endif /* _IPXE_IOBUF_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ip.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ip.h
new file mode 100644
index 00000000..4366d9ab
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ip.h
@@ -0,0 +1,89 @@
+#ifndef _IPXE_IP_H
+#define _IPXE_IP_H
+
+/** @file
+ *
+ * IP protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/in.h>
+#include <ipxe/list.h>
+#include <ipxe/retry.h>
+#include <ipxe/netdevice.h>
+
+struct io_buffer;
+
+/* IP constants */
+
+#define IP_VER 0x40U
+#define IP_MASK_VER 0xf0U
+#define IP_MASK_HLEN 0x0fU
+#define IP_MASK_OFFSET 0x1fffU
+#define IP_MASK_DONOTFRAG 0x4000U
+#define IP_MASK_MOREFRAGS 0x2000U
+#define IP_PSHLEN 12
+
+/* IP header defaults */
+#define IP_TOS 0
+#define IP_TTL 64
+
+/** An IPv4 packet header */
+struct iphdr {
+ uint8_t verhdrlen;
+ uint8_t service;
+ uint16_t len;
+ uint16_t ident;
+ uint16_t frags;
+ uint8_t ttl;
+ uint8_t protocol;
+ uint16_t chksum;
+ struct in_addr src;
+ struct in_addr dest;
+} __attribute__ (( packed ));
+
+/** An IPv4 pseudo header */
+struct ipv4_pseudo_header {
+ struct in_addr src;
+ struct in_addr dest;
+ uint8_t zero_padding;
+ uint8_t protocol;
+ uint16_t len;
+};
+
+/** An IPv4 address/routing table entry */
+struct ipv4_miniroute {
+ /** List of miniroutes */
+ struct list_head list;
+
+ /** Network device */
+ struct net_device *netdev;
+
+ /** IPv4 address */
+ struct in_addr address;
+ /** Subnet mask */
+ struct in_addr netmask;
+ /** Gateway address */
+ struct in_addr gateway;
+};
+
+/* IPv4 fragment reassembly buffer */
+struct ipv4_fragment {
+ /* List of fragment reassembly buffers */
+ struct list_head list;
+ /** Reassembled packet */
+ struct io_buffer *iobuf;
+ /** Current offset */
+ size_t offset;
+ /** Reassembly timer */
+ struct retry_timer timer;
+};
+
+extern struct list_head ipv4_miniroutes;
+
+extern struct net_protocol ipv4_protocol __net_protocol;
+
+#endif /* _IPXE_IP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ip6.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ip6.h
new file mode 100644
index 00000000..e9584bd6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ip6.h
@@ -0,0 +1,80 @@
+#ifndef _IPXE_IP6_H
+#define _IPXE_IP6_H
+
+/** @file
+ *
+ * IP6 protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/in.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/tcpip.h>
+
+/* IP6 constants */
+
+#define IP6_VERSION 0x6
+#define IP6_HOP_LIMIT 255
+
+/**
+ * I/O buffer contents
+ * This is duplicated in tcp.h and here. Ideally it should go into iobuf.h
+ */
+#define MAX_HDR_LEN 100
+#define MAX_IOB_LEN 1500
+#define MIN_IOB_LEN MAX_HDR_LEN + 100 /* To account for padding by LL */
+
+#define IP6_EQUAL( in6_addr1, in6_addr2 ) \
+ ( memcmp ( ( char* ) &( in6_addr1 ), ( char* ) &( in6_addr2 ),\
+ sizeof ( struct in6_addr ) ) == 0 )
+
+#define IS_UNSPECIFIED( addr ) \
+ ( ( (addr).in6_u.u6_addr32[0] == 0x00000000 ) && \
+ ( (addr).in6_u.u6_addr32[1] == 0x00000000 ) && \
+ ( (addr).in6_u.u6_addr32[2] == 0x00000000 ) && \
+ ( (addr).in6_u.u6_addr32[3] == 0x00000000 ) )
+/* IP6 header */
+struct ip6_header {
+ uint32_t ver_traffic_class_flow_label;
+ uint16_t payload_len;
+ uint8_t nxt_hdr;
+ uint8_t hop_limit;
+ struct in6_addr src;
+ struct in6_addr dest;
+};
+
+/* IP6 pseudo header */
+struct ipv6_pseudo_header {
+ struct in6_addr src;
+ struct in6_addr dest;
+ uint8_t zero_padding;
+ uint8_t nxt_hdr;
+ uint16_t len;
+};
+
+/* Next header numbers */
+#define IP6_HOPBYHOP 0x00
+#define IP6_ROUTING 0x43
+#define IP6_FRAGMENT 0x44
+#define IP6_AUTHENTICATION 0x51
+#define IP6_DEST_OPTS 0x60
+#define IP6_ESP 0x50
+#define IP6_ICMP6 0x58
+#define IP6_NO_HEADER 0x59
+
+struct io_buffer;
+
+extern struct net_protocol ipv6_protocol __net_protocol;
+extern struct tcpip_net_protocol ipv6_tcpip_protocol __tcpip_net_protocol;
+extern char * inet6_ntoa ( struct in6_addr in6 );
+
+extern int add_ipv6_address ( struct net_device *netdev,
+ struct in6_addr prefix, int prefix_len,
+ struct in6_addr address,
+ struct in6_addr gateway );
+extern void del_ipv6_address ( struct net_device *netdev );
+
+#endif /* _IPXE_IP6_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ipoib.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ipoib.h
new file mode 100644
index 00000000..e8f12dc5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ipoib.h
@@ -0,0 +1,58 @@
+#ifndef _IPXE_IPOIB_H
+#define _IPXE_IPOIB_H
+
+/** @file
+ *
+ * IP over Infiniband
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/infiniband.h>
+
+/** IPoIB MAC address length */
+#define IPOIB_ALEN 20
+
+/** An IPoIB MAC address */
+struct ipoib_mac {
+ /** Queue pair number
+ *
+ * MSB indicates support for IPoIB "connected mode". Lower 24
+ * bits are the QPN.
+ */
+ uint32_t flags__qpn;
+ /** Port GID */
+ union ib_gid gid;
+} __attribute__ (( packed ));
+
+/** IPoIB link-layer header length */
+#define IPOIB_HLEN 4
+
+/** IPoIB link-layer header */
+struct ipoib_hdr {
+ /** Network-layer protocol */
+ uint16_t proto;
+ /** Reserved, must be zero */
+ union {
+ /** Reserved, must be zero */
+ uint16_t reserved;
+ /** Peer addresses
+ *
+ * We use these fields internally to represent the
+ * peer addresses using a lookup key. There simply
+ * isn't enough room in the IPoIB header to store
+ * literal source or destination MAC addresses.
+ */
+ struct {
+ /** Destination address key */
+ uint8_t dest;
+ /** Source address key */
+ uint8_t src;
+ } __attribute__ (( packed )) peer;
+ } __attribute__ (( packed )) u;
+} __attribute__ (( packed ));
+
+extern const char * ipoib_ntoa ( const void *ll_addr );
+extern struct net_device * alloc_ipoibdev ( size_t priv_size );
+
+#endif /* _IPXE_IPOIB_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/isa.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/isa.h
new file mode 100644
index 00000000..4e69fc6f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/isa.h
@@ -0,0 +1,95 @@
+#ifndef ISA_H
+#define ISA_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/isa_ids.h>
+#include <ipxe/device.h>
+#include <ipxe/tables.h>
+
+/** An ISA device */
+struct isa_device {
+ /** Generic device */
+ struct device dev;
+ /** I/O address */
+ uint16_t ioaddr;
+ /** Driver for this device */
+ struct isa_driver *driver;
+ /** Driver-private data
+ *
+ * Use isa_set_drvdata() and isa_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+};
+
+/*
+ * An individual ISA device, identified by probe address
+ *
+ */
+typedef uint16_t isa_probe_addr_t;
+
+/** An ISA driver */
+struct isa_driver {
+ /** Name */
+ const char *name;
+ /** Probe address list */
+ isa_probe_addr_t *probe_addrs;
+ /** Number of entries in probe address list */
+ unsigned int addr_count;
+ /** Manufacturer ID to be assumed for this device */
+ uint16_t vendor_id;
+ /** Product ID to be assumed for this device */
+ uint16_t prod_id;
+ /**
+ * Probe device
+ *
+ * @v isa ISA device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct isa_device *isa );
+ /**
+ * Remove device
+ *
+ * @v isa ISA device
+ */
+ void ( * remove ) ( struct isa_device *isa );
+};
+
+/** ISA driver table */
+#define ISA_DRIVERS __table ( struct isa_driver, "isa_drivers" )
+
+/** Declare an ISA driver */
+#define __isa_driver __table_entry ( ISA_DRIVERS, 01 )
+
+/**
+ * Set ISA driver-private data
+ *
+ * @v isa ISA device
+ * @v priv Private data
+ */
+static inline void isa_set_drvdata ( struct isa_device *isa, void *priv ) {
+ isa->priv = priv;
+}
+
+/**
+ * Get ISA driver-private data
+ *
+ * @v isa ISA device
+ * @ret priv Private data
+ */
+static inline void * isa_get_drvdata ( struct isa_device *isa ) {
+ return isa->priv;
+}
+
+/*
+ * ISA_ROM is parsed by parserom.pl to generate Makefile rules and
+ * files for rom-o-matic.
+ *
+ */
+#define ISA_ROM( IMAGE, DESCRIPTION )
+
+#endif /* ISA_H */
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/isa_ids.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/isa_ids.h
new file mode 100644
index 00000000..1faf1148
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/isa_ids.h
@@ -0,0 +1,51 @@
+#ifndef ISA_IDS_H
+#define ISA_IDS_H
+
+/*
+ * This file defines IDs as used by ISAPnP and EISA devices. These
+ * IDs have the format:
+ *
+ * vendor byte 0 bit 7 must be zero
+ * bits 6-2 first vendor char in compressed ASCII
+ * bits 1-0 second vendor char in compressed ASCII (bits 4-3)
+ * byte 1 bits 7-5 second vendor char in compressed ASCII (bits 2-0)
+ * bits 4-0 third vendor char in compressed ASCII
+ * product byte 0 bits 7-4 first hex digit of product number
+ * bits 3-0 second hex digit of product number
+ * byte 1 bits 7-4 third hex digit of product number
+ * bits 3-0 hex digit of revision level
+ *
+ * ISA IDs are always expressed in little-endian order, even though
+ * the underlying "meaning" is big-endian.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <byteswap.h>
+
+/*
+ * Construct a vendor ID from three ASCII characters
+ *
+ */
+#define ISA_VENDOR( a, b, c ) \
+ bswap_16 ( ( ( ( (a) - 'A' + 1 ) & 0x1f ) << 10 ) | \
+ ( ( ( (b) - 'A' + 1 ) & 0x1f ) << 5 ) | \
+ ( ( ( (c) - 'A' + 1 ) & 0x1f ) << 0 ) )
+
+#define ISAPNP_VENDOR( a, b, c ) ISA_VENDOR ( a, b, c )
+#define EISA_VENDOR( a, b, c ) ISA_VENDOR ( a, b, c )
+
+#define GENERIC_ISAPNP_VENDOR ISAPNP_VENDOR ( 'P','N','P' )
+
+/*
+ * Extract product ID and revision from combined product field
+ *
+ */
+#define ISA_PROD_ID_MASK ( 0xf0ff )
+#define ISA_PROD_ID(product) ( (product) & ISA_PROD_ID_MASK )
+#define ISA_PROD_REV(product) ( ( (product) & ~ISA_PROD_ID_MASK ) >> 8 )
+
+/* Functions in isa_ids.c */
+extern char * isa_id_string ( unsigned int vendor, unsigned int product );
+
+#endif /* ISA_IDS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/isapnp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/isapnp.h
new file mode 100644
index 00000000..a1959e1b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/isapnp.h
@@ -0,0 +1,285 @@
+/**************************************************************************
+*
+* isapnp.h -- Etherboot isapnp support for the 3Com 3c515
+* Written 2002-2003 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code:
+* Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk)
+*
+*
+*
+* REVISION HISTORY:
+* ================
+* Version 0.1 April 26, 2002 TJL
+* Version 0.2 01/08/2003 TJL Renamed from 3c515_isapnp.h
+*
+*
+* Generalised into an ISAPnP bus that can be used by more than just
+* the 3c515 by Michael Brown <mbrown@fensystems.co.uk>
+*
+***************************************************************************/
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef ISAPNP_H
+#define ISAPNP_H
+
+#include <stdint.h>
+#include <ipxe/isa_ids.h>
+#include <ipxe/device.h>
+#include <ipxe/tables.h>
+
+/*
+ * ISAPnP constants
+ *
+ */
+
+/* Port addresses */
+#define ISAPNP_ADDRESS 0x279
+#define ISAPNP_WRITE_DATA 0xa79
+#define ISAPNP_READ_PORT_MIN 0x203
+#define ISAPNP_READ_PORT_START 0x213 /* ISAPnP spec says 0x203, but
+ * Linux ISAPnP starts at
+ * 0x213 with no explanatory
+ * comment. 0x203 probably
+ * clashes with something. */
+#define ISAPNP_READ_PORT_MAX 0x3ff
+#define ISAPNP_READ_PORT_STEP 0x10 /* Can be any multiple of 4
+ * according to the spec, but
+ * since ISA I/O addresses are
+ * allocated in blocks of 16,
+ * it makes no sense to use
+ * any value less than 16.
+ */
+
+/* Card select numbers */
+#define ISAPNP_CSN_MIN 0x01
+#define ISAPNP_CSN_MAX 0x0f
+
+/* Registers */
+#define ISAPNP_READPORT 0x00
+#define ISAPNP_SERIALISOLATION 0x01
+#define ISAPNP_CONFIGCONTROL 0x02
+#define ISAPNP_WAKE 0x03
+#define ISAPNP_RESOURCEDATA 0x04
+#define ISAPNP_STATUS 0x05
+#define ISAPNP_CARDSELECTNUMBER 0x06
+#define ISAPNP_LOGICALDEVICENUMBER 0x07
+#define ISAPNP_ACTIVATE 0x30
+#define ISAPNP_IORANGECHECK 0x31
+#define ISAPNP_IOBASE(n) ( 0x60 + ( (n) * 2 ) )
+#define ISAPNP_IRQNO(n) ( 0x70 + ( (n) * 2 ) )
+#define ISAPNP_IRQTYPE(n) ( 0x71 + ( (n) * 2 ) )
+
+/* Bits in the CONFIGCONTROL register */
+#define ISAPNP_CONFIG_RESET ( 1 << 0 )
+#define ISAPNP_CONFIG_WAIT_FOR_KEY ( 1 << 1 )
+#define ISAPNP_CONFIG_RESET_CSN ( 1 << 2 )
+#define ISAPNP_CONFIG_RESET_DRV ( ISAPNP_CONFIG_RESET | \
+ ISAPNP_CONFIG_WAIT_FOR_KEY | \
+ ISAPNP_CONFIG_RESET_CSN )
+
+/* The LFSR used for the initiation key and for checksumming */
+#define ISAPNP_LFSR_SEED 0x6a
+
+/* Small tags */
+#define ISAPNP_IS_SMALL_TAG(tag) ( ! ( (tag) & 0x80 ) )
+#define ISAPNP_SMALL_TAG_NAME(tag) ( ( (tag) >> 3 ) & 0xf )
+#define ISAPNP_SMALL_TAG_LEN(tag) ( ( (tag) & 0x7 ) )
+#define ISAPNP_TAG_PNPVERNO 0x01
+#define ISAPNP_TAG_LOGDEVID 0x02
+#define ISAPNP_TAG_COMPATDEVID 0x03
+#define ISAPNP_TAG_IRQ 0x04
+#define ISAPNP_TAG_DMA 0x05
+#define ISAPNP_TAG_STARTDEP 0x06
+#define ISAPNP_TAG_ENDDEP 0x07
+#define ISAPNP_TAG_IOPORT 0x08
+#define ISAPNP_TAG_FIXEDIO 0x09
+#define ISAPNP_TAG_RSVDSHORTA 0x0A
+#define ISAPNP_TAG_RSVDSHORTB 0x0B
+#define ISAPNP_TAG_RSVDSHORTC 0x0C
+#define ISAPNP_TAG_RSVDSHORTD 0x0D
+#define ISAPNP_TAG_VENDORSHORT 0x0E
+#define ISAPNP_TAG_END 0x0F
+/* Large tags */
+#define ISAPNP_IS_LARGE_TAG(tag) ( ( (tag) & 0x80 ) )
+#define ISAPNP_LARGE_TAG_NAME(tag) (tag)
+#define ISAPNP_TAG_MEMRANGE 0x81
+#define ISAPNP_TAG_ANSISTR 0x82
+#define ISAPNP_TAG_UNICODESTR 0x83
+#define ISAPNP_TAG_VENDORLONG 0x84
+#define ISAPNP_TAG_MEM32RANGE 0x85
+#define ISAPNP_TAG_FIXEDMEM32RANGE 0x86
+#define ISAPNP_TAG_RSVDLONG0 0xF0
+#define ISAPNP_TAG_RSVDLONG1 0xF1
+#define ISAPNP_TAG_RSVDLONG2 0xF2
+#define ISAPNP_TAG_RSVDLONG3 0xF3
+#define ISAPNP_TAG_RSVDLONG4 0xF4
+#define ISAPNP_TAG_RSVDLONG5 0xF5
+#define ISAPNP_TAG_RSVDLONG6 0xF6
+#define ISAPNP_TAG_RSVDLONG7 0xF7
+#define ISAPNP_TAG_RSVDLONG8 0xF8
+#define ISAPNP_TAG_RSVDLONG9 0xF9
+#define ISAPNP_TAG_RSVDLONGA 0xFA
+#define ISAPNP_TAG_RSVDLONGB 0xFB
+#define ISAPNP_TAG_RSVDLONGC 0xFC
+#define ISAPNP_TAG_RSVDLONGD 0xFD
+#define ISAPNP_TAG_RSVDLONGE 0xFE
+#define ISAPNP_TAG_RSVDLONGF 0xFF
+#define ISAPNP_TAG_PSEUDO_NEWBOARD 0x100
+
+/** An ISAPnP serial identifier */
+struct isapnp_identifier {
+ /** Vendor ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+ /** Serial number */
+ uint32_t serial;
+ /** Checksum */
+ uint8_t checksum;
+} __attribute__ (( packed ));
+
+/** An ISAPnP logical device ID structure */
+struct isapnp_logdevid {
+ /** Vendor ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+ /** Flags */
+ uint16_t flags;
+} __attribute__ (( packed ));
+
+/** An ISAPnP device ID list entry */
+struct isapnp_device_id {
+ /** Name */
+ const char *name;
+ /** Vendor ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+};
+
+/** An ISAPnP device */
+struct isapnp_device {
+ /** Generic device */
+ struct device dev;
+ /** Vendor ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+ /** I/O address */
+ uint16_t ioaddr;
+ /** Interrupt number */
+ uint8_t irqno;
+ /** Card Select Number */
+ uint8_t csn;
+ /** Logical Device ID */
+ uint8_t logdev;
+ /** Driver for this device */
+ struct isapnp_driver *driver;
+ /** Driver-private data
+ *
+ * Use isapnp_set_drvdata() and isapnp_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+};
+
+/** An ISAPnP driver */
+struct isapnp_driver {
+ /** ISAPnP ID table */
+ struct isapnp_device_id *ids;
+ /** Number of entries in ISAPnP ID table */
+ unsigned int id_count;
+ /**
+ * Probe device
+ *
+ * @v isapnp ISAPnP device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct isapnp_device *isapnp,
+ const struct isapnp_device_id *id );
+ /**
+ * Remove device
+ *
+ * @v isapnp ISAPnP device
+ */
+ void ( * remove ) ( struct isapnp_device *isapnp );
+};
+
+/** ISAPnP driver table */
+#define ISAPNP_DRIVERS __table ( struct isapnp_driver, "isapnp_drivers" )
+
+/** Declare an ISAPnP driver */
+#define __isapnp_driver __table_entry ( ISAPNP_DRIVERS, 01 )
+
+extern uint16_t isapnp_read_port;
+
+extern void isapnp_device_activation ( struct isapnp_device *isapnp,
+ int activation );
+
+/**
+ * Activate ISAPnP device
+ *
+ * @v isapnp ISAPnP device
+ */
+static inline void activate_isapnp_device ( struct isapnp_device *isapnp ) {
+ isapnp_device_activation ( isapnp, 1 );
+}
+
+/**
+ * Deactivate ISAPnP device
+ *
+ * @v isapnp ISAPnP device
+ */
+static inline void deactivate_isapnp_device ( struct isapnp_device *isapnp ) {
+ isapnp_device_activation ( isapnp, 0 );
+}
+
+/**
+ * Set ISAPnP driver-private data
+ *
+ * @v isapnp ISAPnP device
+ * @v priv Private data
+ */
+static inline void isapnp_set_drvdata ( struct isapnp_device *isapnp,
+ void *priv ) {
+ isapnp->priv = priv;
+}
+
+/**
+ * Get ISAPnP driver-private data
+ *
+ * @v isapnp ISAPnP device
+ * @ret priv Private data
+ */
+static inline void * isapnp_get_drvdata ( struct isapnp_device *isapnp ) {
+ return isapnp->priv;
+}
+
+#endif /* ISAPNP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/iscsi.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/iscsi.h
new file mode 100644
index 00000000..b4de793a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/iscsi.h
@@ -0,0 +1,700 @@
+#ifndef _IPXE_ISCSI_H
+#define _IPXE_ISCSI_H
+
+/** @file
+ *
+ * iSCSI protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/socket.h>
+#include <ipxe/scsi.h>
+#include <ipxe/chap.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/xfer.h>
+#include <ipxe/process.h>
+
+/** Default iSCSI port */
+#define ISCSI_PORT 3260
+
+/**
+ * iSCSI segment lengths
+ *
+ * iSCSI uses an icky structure with one one-byte field (a dword
+ * count) and one three-byte field (a byte count). This structure,
+ * and the accompanying macros, relieve some of the pain.
+ */
+union iscsi_segment_lengths {
+ struct {
+ /** The AHS length (measured in dwords) */
+ uint8_t ahs_len;
+ /** The data length (measured in bytes), in network
+ * byte order
+ */
+ uint8_t data_len[3];
+ } bytes;
+ /** Ths data length (measured in bytes), in network byte
+ * order, with ahs_len as the first byte.
+ */
+ uint32_t ahs_and_data_len;
+};
+
+/** The length of the additional header segment, in dwords */
+#define ISCSI_AHS_LEN( segment_lengths ) \
+ ( (segment_lengths).bytes.ahs_len )
+
+/** The length of the data segment, in bytes, excluding any padding */
+#define ISCSI_DATA_LEN( segment_lengths ) \
+ ( ntohl ( (segment_lengths).ahs_and_data_len ) & 0xffffff )
+
+/** The padding of the data segment, in bytes */
+#define ISCSI_DATA_PAD_LEN( segment_lengths ) \
+ ( ( 0 - (segment_lengths).bytes.data_len[2] ) & 0x03 )
+
+/** Set additional header and data segment lengths */
+#define ISCSI_SET_LENGTHS( segment_lengths, ahs_len, data_len ) do { \
+ (segment_lengths).ahs_and_data_len = \
+ htonl ( data_len | ( ahs_len << 24 ) ); \
+ } while ( 0 )
+
+/**
+ * iSCSI basic header segment common fields
+ *
+ */
+struct iscsi_bhs_common {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Fields specific to the PDU type */
+ uint8_t other_a[2];
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Fields specific to the PDU type */
+ uint8_t other_b[8];
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Fields specific to the PDU type */
+ uint8_t other_c[28];
+};
+
+/** Opcode mask */
+#define ISCSI_OPCODE_MASK 0x3f
+
+/** Immediate delivery */
+#define ISCSI_FLAG_IMMEDIATE 0x40
+
+/** Final PDU of a sequence */
+#define ISCSI_FLAG_FINAL 0x80
+
+/** iSCSI tag magic marker */
+#define ISCSI_TAG_MAGIC 0x18ae0000
+
+/** iSCSI reserved tag value */
+#define ISCSI_TAG_RESERVED 0xffffffff
+
+/**
+ * iSCSI basic header segment common request fields
+ *
+ */
+struct iscsi_bhs_common_response {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Fields specific to the PDU type */
+ uint8_t other_a[2];
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Fields specific to the PDU type */
+ uint8_t other_b[8];
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Fields specific to the PDU type */
+ uint8_t other_c[4];
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Fields specific to the PDU type */
+ uint8_t other_d[16];
+};
+
+/**
+ * iSCSI login request basic header segment
+ *
+ */
+struct iscsi_bhs_login_request {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Maximum supported version number */
+ uint8_t version_max;
+ /** Minimum supported version number */
+ uint8_t version_min;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Initiator session ID (IANA format) enterprise number and flags */
+ uint32_t isid_iana_en;
+ /** Initiator session ID (IANA format) qualifier */
+ uint16_t isid_iana_qual;
+ /** Target session identifying handle */
+ uint16_t tsih;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Connection ID */
+ uint16_t cid;
+ /** Reserved */
+ uint16_t reserved_a;
+ /** Command sequence number */
+ uint32_t cmdsn;
+ /** Expected status sequence number */
+ uint32_t expstatsn;
+ /** Reserved */
+ uint8_t reserved_b[16];
+};
+
+/** Login request opcode */
+#define ISCSI_OPCODE_LOGIN_REQUEST 0x03
+
+/** Willingness to transition to next stage */
+#define ISCSI_LOGIN_FLAG_TRANSITION 0x80
+
+/** Key=value pairs continued in subsequent request */
+#define ISCSI_LOGIN_FLAG_CONTINUE 0x40
+
+/* Current stage values and mask */
+#define ISCSI_LOGIN_CSG_MASK 0x0c
+#define ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION 0x00
+#define ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION 0x04
+#define ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE 0x0c
+
+/* Next stage values and mask */
+#define ISCSI_LOGIN_NSG_MASK 0x03
+#define ISCSI_LOGIN_NSG_SECURITY_NEGOTIATION 0x00
+#define ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION 0x01
+#define ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE 0x03
+
+/** ISID IANA format marker */
+#define ISCSI_ISID_IANA 0x40000000
+
+/** Fen Systems Ltd. IANA enterprise number
+ *
+ * Permission is hereby granted to use Fen Systems Ltd.'s IANA
+ * enterprise number with this iSCSI implementation.
+ */
+#define IANA_EN_FEN_SYSTEMS 10019
+
+/**
+ * iSCSI login response basic header segment
+ *
+ */
+struct iscsi_bhs_login_response {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Maximum supported version number */
+ uint8_t version_max;
+ /** Minimum supported version number */
+ uint8_t version_min;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Initiator session ID (IANA format) enterprise number and flags */
+ uint32_t isid_iana_en;
+ /** Initiator session ID (IANA format) qualifier */
+ uint16_t isid_iana_qual;
+ /** Target session identifying handle */
+ uint16_t tsih;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Reserved */
+ uint32_t reserved_a;
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Maximum command sequence number */
+ uint32_t maxcmdsn;
+ /** Status class */
+ uint8_t status_class;
+ /** Status detail */
+ uint8_t status_detail;
+ /** Reserved */
+ uint8_t reserved_b[10];
+};
+
+/** Login response opcode */
+#define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
+
+/* Login response status codes */
+#define ISCSI_STATUS_SUCCESS 0x00
+#define ISCSI_STATUS_REDIRECT 0x01
+#define ISCSI_STATUS_INITIATOR_ERROR 0x02
+#define ISCSI_STATUS_INITIATOR_ERROR_AUTHENTICATION 0x01
+#define ISCSI_STATUS_INITIATOR_ERROR_AUTHORISATION 0x02
+#define ISCSI_STATUS_INITIATOR_ERROR_NOT_FOUND 0x03
+#define ISCSI_STATUS_INITIATOR_ERROR_REMOVED 0x04
+#define ISCSI_STATUS_TARGET_ERROR 0x03
+#define ISCSI_STATUS_TARGET_ERROR_UNAVAILABLE 0x01
+#define ISCSI_STATUS_TARGET_ERROR_NO_RESOURCES 0x02
+
+/**
+ * iSCSI SCSI command basic header segment
+ *
+ */
+struct iscsi_bhs_scsi_command {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Reserved */
+ uint16_t reserved_a;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** SCSI Logical Unit Number */
+ struct scsi_lun lun;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Expected data transfer length */
+ uint32_t exp_len;
+ /** Command sequence number */
+ uint32_t cmdsn;
+ /** Expected status sequence number */
+ uint32_t expstatsn;
+ /** SCSI Command Descriptor Block (CDB) */
+ union scsi_cdb cdb;
+};
+
+/** SCSI command opcode */
+#define ISCSI_OPCODE_SCSI_COMMAND 0x01
+
+/** Command will read data */
+#define ISCSI_COMMAND_FLAG_READ 0x40
+
+/** Command will write data */
+#define ISCSI_COMMAND_FLAG_WRITE 0x20
+
+/* Task attributes */
+#define ISCSI_COMMAND_ATTR_UNTAGGED 0x00
+#define ISCSI_COMMAND_ATTR_SIMPLE 0x01
+#define ISCSI_COMMAND_ATTR_ORDERED 0x02
+#define ISCSI_COMMAND_ATTR_HEAD_OF_QUEUE 0x03
+#define ISCSI_COMMAND_ATTR_ACA 0x04
+
+/**
+ * iSCSI SCSI response basic header segment
+ *
+ */
+struct iscsi_bhs_scsi_response {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Response code */
+ uint8_t response;
+ /** SCSI status code */
+ uint8_t status;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Reserved */
+ uint8_t reserved_a[8];
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** SNACK tag */
+ uint32_t snack;
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Maximum command sequence number */
+ uint32_t maxcmdsn;
+ /** Expected data sequence number */
+ uint32_t expdatasn;
+ /** Bidirectional read residual count */
+ uint32_t bidi_residual_count;
+ /** Residual count */
+ uint32_t residual_count;
+};
+
+/** SCSI response opcode */
+#define ISCSI_OPCODE_SCSI_RESPONSE 0x21
+
+/** SCSI command completed at target */
+#define ISCSI_RESPONSE_COMMAND_COMPLETE 0x00
+
+/** SCSI target failure */
+#define ISCSI_RESPONSE_TARGET_FAILURE 0x01
+
+/** Data overflow occurred */
+#define ISCSI_RESPONSE_FLAG_OVERFLOW 0x20
+
+/** Data underflow occurred */
+#define ISCSI_RESPONSE_FLAG_UNDERFLOW 0x40
+
+/**
+ * iSCSI data-in basic header segment
+ *
+ */
+struct iscsi_bhs_data_in {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved_a;
+ /** SCSI status code */
+ uint8_t status;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Logical Unit Number */
+ struct scsi_lun lun;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Target Transfer Tag */
+ uint32_t ttt;
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Maximum command sequence number */
+ uint32_t maxcmdsn;
+ /** Data sequence number */
+ uint32_t datasn;
+ /** Buffer offset */
+ uint32_t offset;
+ /** Residual count */
+ uint32_t residual_count;
+};
+
+/** Data-in opcode */
+#define ISCSI_OPCODE_DATA_IN 0x25
+
+/** Data requires acknowledgement */
+#define ISCSI_DATA_FLAG_ACKNOWLEDGE 0x40
+
+/** Data overflow occurred */
+#define ISCSI_DATA_FLAG_OVERFLOW 0x04
+
+/** Data underflow occurred */
+#define ISCSI_DATA_FLAG_UNDERFLOW 0x02
+
+/** SCSI status code and overflow/underflow flags are valid */
+#define ISCSI_DATA_FLAG_STATUS 0x01
+
+/**
+ * iSCSI data-out basic header segment
+ *
+ */
+struct iscsi_bhs_data_out {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Reserved */
+ uint16_t reserved_a;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Logical Unit Number */
+ struct scsi_lun lun;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Target Transfer Tag */
+ uint32_t ttt;
+ /** Reserved */
+ uint32_t reserved_b;
+ /** Expected status sequence number */
+ uint32_t expstatsn;
+ /** Reserved */
+ uint32_t reserved_c;
+ /** Data sequence number */
+ uint32_t datasn;
+ /** Buffer offset */
+ uint32_t offset;
+ /** Reserved */
+ uint32_t reserved_d;
+};
+
+/** Data-out opcode */
+#define ISCSI_OPCODE_DATA_OUT 0x05
+
+/**
+ * iSCSI request to transfer basic header segment
+ *
+ */
+struct iscsi_bhs_r2t {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Reserved */
+ uint16_t reserved_a;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Logical Unit Number */
+ struct scsi_lun lun;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Target Transfer Tag */
+ uint32_t ttt;
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Maximum command sequence number */
+ uint32_t maxcmdsn;
+ /** R2T sequence number */
+ uint32_t r2tsn;
+ /** Buffer offset */
+ uint32_t offset;
+ /** Desired data transfer length */
+ uint32_t len;
+};
+
+/** R2T opcode */
+#define ISCSI_OPCODE_R2T 0x31
+
+/**
+ * iSCSI NOP-In basic header segment
+ *
+ */
+struct iscsi_nop_in {
+ /** Opcode */
+ uint8_t opcode;
+ /** Reserved */
+ uint8_t reserved_a[3];
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Logical Unit Number */
+ struct scsi_lun lun;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Target Transfer Tag */
+ uint32_t ttt;
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Maximum command sequence number */
+ uint32_t maxcmdsn;
+ /** Reserved */
+ uint8_t reserved_b[12];
+};
+
+/** NOP-In opcode */
+#define ISCSI_OPCODE_NOP_IN 0x20
+
+/**
+ * An iSCSI basic header segment
+ */
+union iscsi_bhs {
+ struct iscsi_bhs_common common;
+ struct iscsi_bhs_common_response common_response;
+ struct iscsi_bhs_login_request login_request;
+ struct iscsi_bhs_login_response login_response;
+ struct iscsi_bhs_scsi_command scsi_command;
+ struct iscsi_bhs_scsi_response scsi_response;
+ struct iscsi_bhs_data_in data_in;
+ struct iscsi_bhs_data_out data_out;
+ struct iscsi_bhs_r2t r2t;
+ struct iscsi_nop_in nop_in;
+ unsigned char bytes[ sizeof ( struct iscsi_bhs_common ) ];
+};
+
+/** State of an iSCSI TX engine */
+enum iscsi_tx_state {
+ /** Nothing to send */
+ ISCSI_TX_IDLE = 0,
+ /** Sending the basic header segment */
+ ISCSI_TX_BHS,
+ /** Sending the additional header segment */
+ ISCSI_TX_AHS,
+ /** Sending the data segment */
+ ISCSI_TX_DATA,
+};
+
+/** State of an iSCSI RX engine */
+enum iscsi_rx_state {
+ /** Receiving the basic header segment */
+ ISCSI_RX_BHS = 0,
+ /** Receiving the additional header segment */
+ ISCSI_RX_AHS,
+ /** Receiving the data segment */
+ ISCSI_RX_DATA,
+ /** Receiving the data segment padding */
+ ISCSI_RX_DATA_PADDING,
+};
+
+/** An iSCSI session */
+struct iscsi_session {
+ /** Reference counter */
+ struct refcnt refcnt;
+
+ /** SCSI command-issuing interface */
+ struct interface control;
+ /** SCSI command interface */
+ struct interface data;
+ /** Transport-layer socket */
+ struct interface socket;
+
+ /** Initiator IQN */
+ char *initiator_iqn;
+ /** Target address */
+ char *target_address;
+ /** Target port */
+ unsigned int target_port;
+ /** Target IQN */
+ char *target_iqn;
+
+ /** Session status
+ *
+ * This is the bitwise-OR of zero or more ISCSI_STATUS_XXX
+ * constants.
+ */
+ int status;
+
+ /** Initiator username (if any) */
+ char *initiator_username;
+ /** Initiator password (if any) */
+ char *initiator_password;
+ /** Target username (if any) */
+ char *target_username;
+ /** Target password (if any) */
+ char *target_password;
+ /** CHAP challenge (for target auth only)
+ *
+ * This is a block of random data; the first byte is used as
+ * the CHAP identifier (CHAP_I) and the remainder as the CHAP
+ * challenge (CHAP_C).
+ */
+ unsigned char chap_challenge[17];
+ /** CHAP response (used for both initiator and target auth) */
+ struct chap_response chap;
+
+ /** Initiator session ID (IANA format) qualifier
+ *
+ * This is part of the ISID. It is generated randomly
+ * whenever a new connection is opened.
+ */
+ uint16_t isid_iana_qual;
+ /** Initiator task tag
+ *
+ * This is the tag of the current command. It is incremented
+ * whenever a new command is started.
+ */
+ uint32_t itt;
+ /** Target transfer tag
+ *
+ * This is the tag attached to a sequence of data-out PDUs in
+ * response to an R2T.
+ */
+ uint32_t ttt;
+ /** Transfer offset
+ *
+ * This is the offset for an in-progress sequence of data-out
+ * PDUs in response to an R2T.
+ */
+ uint32_t transfer_offset;
+ /** Transfer length
+ *
+ * This is the length for an in-progress sequence of data-out
+ * PDUs in response to an R2T.
+ */
+ uint32_t transfer_len;
+ /** Command sequence number
+ *
+ * This is the sequence number of the current command, used to
+ * fill out the CmdSN field in iSCSI request PDUs. It is
+ * updated with the value of the ExpCmdSN field whenever we
+ * receive an iSCSI response PDU containing such a field.
+ */
+ uint32_t cmdsn;
+ /** Status sequence number
+ *
+ * This is the most recent status sequence number present in
+ * the StatSN field of an iSCSI response PDU containing such a
+ * field. Whenever we send an iSCSI request PDU, we fill out
+ * the ExpStatSN field with this value plus one.
+ */
+ uint32_t statsn;
+
+ /** Basic header segment for current TX PDU */
+ union iscsi_bhs tx_bhs;
+ /** State of the TX engine */
+ enum iscsi_tx_state tx_state;
+ /** TX process */
+ struct process process;
+
+ /** Basic header segment for current RX PDU */
+ union iscsi_bhs rx_bhs;
+ /** State of the RX engine */
+ enum iscsi_rx_state rx_state;
+ /** Byte offset within the current RX state */
+ size_t rx_offset;
+ /** Length of the current RX state */
+ size_t rx_len;
+ /** Buffer for received data (not always used) */
+ void *rx_buffer;
+
+ /** Current SCSI command, if any */
+ struct scsi_cmd *command;
+
+ /** Target socket address (for boot firmware table) */
+ struct sockaddr target_sockaddr;
+ /** SCSI LUN (for boot firmware table) */
+ struct scsi_lun lun;
+};
+
+/** iSCSI session is currently in the security negotiation phase */
+#define ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE \
+ ( ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION | \
+ ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION )
+
+/** iSCSI session is currently in the operational parameter
+ * negotiation phase
+ */
+#define ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE \
+ ( ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION | \
+ ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE )
+
+/** iSCSI session is currently in the full feature phase */
+#define ISCSI_STATUS_FULL_FEATURE_PHASE ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE
+
+/** Mask for all iSCSI session phases */
+#define ISCSI_STATUS_PHASE_MASK ( ISCSI_LOGIN_CSG_MASK | ISCSI_LOGIN_NSG_MASK )
+
+/** iSCSI session needs to send the initial security negotiation strings */
+#define ISCSI_STATUS_STRINGS_SECURITY 0x0100
+
+/** iSCSI session needs to send the CHAP_A string */
+#define ISCSI_STATUS_STRINGS_CHAP_ALGORITHM 0x0200
+
+/** iSCSI session needs to send the CHAP response */
+#define ISCSI_STATUS_STRINGS_CHAP_RESPONSE 0x0400
+
+/** iSCSI session needs to send the mutual CHAP challenge */
+#define ISCSI_STATUS_STRINGS_CHAP_CHALLENGE 0x0800
+
+/** iSCSI session needs to send the operational negotiation strings */
+#define ISCSI_STATUS_STRINGS_OPERATIONAL 0x1000
+
+/** Mask for all iSCSI "needs to send" flags */
+#define ISCSI_STATUS_STRINGS_MASK 0xff00
+
+/** Target has requested forward (initiator) authentication */
+#define ISCSI_STATUS_AUTH_FORWARD_REQUIRED 0x00010000
+
+/** Initiator requires target (reverse) authentication */
+#define ISCSI_STATUS_AUTH_REVERSE_REQUIRED 0x00020000
+
+/** Target authenticated itself correctly */
+#define ISCSI_STATUS_AUTH_REVERSE_OK 0x00040000
+
+/** Default initiator IQN prefix */
+#define ISCSI_DEFAULT_IQN_PREFIX "iqn.2010-04.org.ipxe"
+
+#endif /* _IPXE_ISCSI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/job.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/job.h
new file mode 100644
index 00000000..c2232fc1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/job.h
@@ -0,0 +1,38 @@
+#ifndef _IPXE_JOB_H
+#define _IPXE_JOB_H
+
+/** @file
+ *
+ * Job control interfaces
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/interface.h>
+
+/** Job progress */
+struct job_progress {
+ /** Amount of operation completed so far
+ *
+ * The units for this quantity are arbitrary. @c completed
+ * divded by @total should give something which approximately
+ * represents the progress through the operation. For a
+ * download operation, using byte counts would make sense.
+ */
+ unsigned long completed;
+ /** Total operation size
+ *
+ * See @c completed. A zero value means "total size unknown"
+ * and is explcitly permitted; users should take this into
+ * account before calculating @c completed/total.
+ */
+ unsigned long total;
+};
+
+extern void job_progress ( struct interface *intf,
+ struct job_progress *progress );
+#define job_progress_TYPE( object_type ) \
+ typeof ( void ( object_type, struct job_progress *progress ) )
+
+#endif /* _IPXE_JOB_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/keymap.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/keymap.h
new file mode 100644
index 00000000..9ac42a6b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/keymap.h
@@ -0,0 +1,30 @@
+#ifndef _IPXE_KEYMAP_H
+#define _IPXE_KEYMAP_H
+
+/**
+ * @file
+ *
+ * Keyboard mappings
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/tables.h>
+
+/** A keyboard mapping */
+struct key_mapping {
+ /** Character read from keyboard */
+ uint8_t from;
+ /** Character to be used instead */
+ uint8_t to;
+} __attribute__ (( packed ));
+
+/** Keyboard mapping table */
+#define KEYMAP __table ( struct key_mapping, "keymap" )
+
+/** Define a keyboard mapping */
+#define __keymap __table_entry ( KEYMAP, 01 )
+
+#endif /* _IPXE_KEYMAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/keys.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/keys.h
new file mode 100644
index 00000000..8b13550b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/keys.h
@@ -0,0 +1,88 @@
+#ifndef _IPXE_KEYS_H
+#define _IPXE_KEYS_H
+
+/** @file
+ *
+ * Key definitions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * Symbolic names for some standard ASCII characters
+ *
+ */
+
+#define NUL 0x00
+#define CTRL_A 0x01
+#define CTRL_B 0x02
+#define CTRL_C 0x03
+#define CTRL_D 0x04
+#define CTRL_E 0x05
+#define CTRL_F 0x06
+#define CTRL_G 0x07
+#define CTRL_H 0x08
+#define CTRL_I 0x09
+#define CTRL_J 0x0a
+#define CTRL_K 0x0b
+#define CTRL_L 0x0c
+#define CTRL_M 0x0d
+#define CTRL_N 0x0e
+#define CTRL_O 0x0f
+#define CTRL_P 0x10
+#define CTRL_Q 0x11
+#define CTRL_R 0x12
+#define CTRL_S 0x13
+#define CTRL_T 0x14
+#define CTRL_U 0x15
+#define CTRL_V 0x16
+#define CTRL_W 0x17
+#define CTRL_X 0x18
+#define CTRL_Y 0x19
+#define CTRL_Z 0x1a
+
+#define BACKSPACE CTRL_H
+#define TAB CTRL_I
+#define LF CTRL_J
+#define CR CTRL_M
+#define ESC 0x1b
+
+/*
+ * Special keys outside the normal ASCII range
+ *
+ *
+ * The names are chosen to match those used by curses. The values are
+ * chosen to facilitate easy conversion from a received ANSI escape
+ * sequence to a KEY_XXX constant.
+ */
+
+#define KEY_ANSI( n, terminator ) ( 0x100 * ( (n) + 1 ) + (terminator) )
+
+#define KEY_MIN 0x101
+#define KEY_UP KEY_ANSI ( 0, 'A' ) /**< Up arrow */
+#define KEY_DOWN KEY_ANSI ( 0, 'B' ) /**< Down arrow */
+#define KEY_RIGHT KEY_ANSI ( 0, 'C' ) /**< Right arrow */
+#define KEY_LEFT KEY_ANSI ( 0, 'D' ) /**< Left arrow */
+#define KEY_END KEY_ANSI ( 0, 'F' ) /**< End */
+#define KEY_HOME KEY_ANSI ( 0, 'H' ) /**< Home */
+#define KEY_IC KEY_ANSI ( 2, '~' ) /**< Insert */
+#define KEY_DC KEY_ANSI ( 3, '~' ) /**< Delete */
+#define KEY_PPAGE KEY_ANSI ( 5, '~' ) /**< Page up */
+#define KEY_NPAGE KEY_ANSI ( 6, '~' ) /**< Page down */
+#define KEY_F5 KEY_ANSI ( 15, '~' ) /**< F5 */
+#define KEY_F6 KEY_ANSI ( 17, '~' ) /**< F6 */
+#define KEY_F7 KEY_ANSI ( 18, '~' ) /**< F7 */
+#define KEY_F8 KEY_ANSI ( 19, '~' ) /**< F8 (for PXE) */
+#define KEY_F9 KEY_ANSI ( 20, '~' ) /**< F9 */
+#define KEY_F10 KEY_ANSI ( 21, '~' ) /**< F10 */
+#define KEY_F11 KEY_ANSI ( 23, '~' ) /**< F11 */
+#define KEY_F12 KEY_ANSI ( 24, '~' ) /**< F12 */
+
+/* Not in the [KEY_MIN,KEY_MAX] range; terminals seem to send these as
+ * normal ASCII values.
+ */
+#define KEY_BACKSPACE BACKSPACE
+#define KEY_ENTER LF
+
+#endif /* _IPXE_KEYS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/linebuf.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linebuf.h
new file mode 100644
index 00000000..706ef255
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linebuf.h
@@ -0,0 +1,30 @@
+#ifndef _IPXE_LINEBUF_H
+#define _IPXE_LINEBUF_H
+
+/** @file
+ *
+ * Line buffering
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stddef.h>
+
+/** A line buffer */
+struct line_buffer {
+ /** Current string in the buffer */
+ char *data;
+ /** Length of current string, excluding the terminating NUL */
+ size_t len;
+ /** String is ready to read */
+ int ready;
+};
+
+extern char * buffered_line ( struct line_buffer *linebuf );
+extern ssize_t line_buffer ( struct line_buffer *linebuf,
+ const char *data, size_t len );
+extern void empty_line_buffer ( struct line_buffer *linebuf );
+
+#endif /* _IPXE_LINEBUF_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/lineconsole.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/lineconsole.h
new file mode 100644
index 00000000..925c0acc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/lineconsole.h
@@ -0,0 +1,36 @@
+#ifndef _IPXE_LINECONSOLE_H
+#define _IPXE_LINECONSOLE_H
+
+/** @file
+ *
+ * Line-based console
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/ansiesc.h>
+
+/** A line-based console */
+struct line_console {
+ /** Data buffer
+ *
+ * Must initially be filled with NULs
+ */
+ char *buffer;
+ /** Current index within buffer */
+ size_t index;
+ /** Length of buffer
+ *
+ * The final character of the buffer will only ever be used as
+ * a potential terminating NUL.
+ */
+ size_t len;
+ /** ANSI escape sequence context */
+ struct ansiesc_context ctx;
+};
+
+extern size_t line_putchar ( struct line_console *line, int character );
+
+#endif /* _IPXE_LINECONSOLE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux.h
new file mode 100644
index 00000000..dac508ea
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _IPXE_LINUX_H
+#define _IPXE_LINUX_H
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+/** @file
+ *
+ * Linux devices, drivers and device requests.
+ */
+
+#include <ipxe/list.h>
+#include <ipxe/device.h>
+#include <ipxe/settings.h>
+
+/** A linux device */
+struct linux_device {
+ /** Generic device */
+ struct device dev;
+ /** Driver that's handling the device */
+ struct linux_driver *driver;
+ /** Private data used by drivers */
+ void *priv;
+};
+
+struct linux_device_request;
+
+/** A linux driver */
+struct linux_driver {
+ /** Name */
+ char *name;
+ /** Probe function */
+ int (*probe)(struct linux_device *device, struct linux_device_request *request);
+ /** Remove function */
+ void (*remove)(struct linux_device *device);
+ /** Can the driver probe any more devices? */
+ int can_probe;
+};
+
+/** Linux driver table */
+#define LINUX_DRIVERS __table(struct linux_driver, "linux_drivers")
+
+/** Declare a Linux driver */
+#define __linux_driver __table_entry(LINUX_DRIVERS, 01)
+
+/**
+ * Set linux device driver-private data
+ *
+ * @v device Linux device
+ * @v priv Private data
+ */
+static inline void linux_set_drvdata(struct linux_device * device, void *priv)
+{
+ device->priv = priv;
+}
+
+/**
+ * Get linux device driver-private data
+ *
+ * @v device Linux device
+ * @ret priv Private data
+ */
+static inline void *linux_get_drvdata(struct linux_device *device)
+{
+ return device->priv;
+}
+
+/**
+ * A device request.
+ *
+ * To be created and filled by the UI code.
+ */
+struct linux_device_request {
+ /** Driver name. Compared to the linux drivers' names */
+ char *driver;
+ /** List node */
+ struct list_head list;
+ /** List of settings */
+ struct list_head settings;
+};
+
+/** A device request setting */
+struct linux_setting {
+ /** Name */
+ char *name;
+ /** Value */
+ char *value;
+ /** Was the setting already applied? */
+ int applied;
+ /** List node */
+ struct list_head list;
+};
+
+/**
+ * List of requested devices.
+ *
+ * Filled by the UI code. Linux root_driver walks over this list looking for an
+ * appropriate driver to handle each request by matching the driver's name.
+ */
+extern struct list_head linux_device_requests;
+
+/**
+ * List of global settings to apply.
+ *
+ * Filled by the UI code. Linux root_driver applies these settings.
+ */
+extern struct list_head linux_global_settings;
+
+/**
+ * Look for the last occurrence of a setting with the specified name
+ *
+ * @v name Name of the setting to look for
+ * @v settings List of the settings to look through
+ */
+struct linux_setting *linux_find_setting(char *name, struct list_head *settings);
+
+/**
+ * Apply a list of linux settings to a settings block
+ *
+ * @v new_settings List of linux_setting's to apply
+ * @v settings_block Settings block to apply the settings to
+ * @ret rc 0 on success
+ */
+extern void linux_apply_settings(struct list_head *new_settings, struct settings *settings_block);
+
+
+#endif /* _IPXE_LINUX_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_entropy.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_entropy.h
new file mode 100644
index 00000000..bd89bd52
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_entropy.h
@@ -0,0 +1,32 @@
+#ifndef _IPXE_LINUX_ENTROPY_H
+#define _IPXE_LINUX_ENTROPY_H
+
+/** @file
+ *
+ * iPXE entropy API for linux
+ *
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#ifdef ENTROPY_LINUX
+#define ENTROPY_PREFIX_linux
+#else
+#define ENTROPY_PREFIX_linux __linux_
+#endif
+
+/**
+ * min-entropy per sample
+ *
+ * @ret min_entropy min-entropy of each sample
+ */
+static inline __always_inline double
+ENTROPY_INLINE ( linux, min_entropy_per_sample ) ( void ) {
+
+ /* We read single bytes from /dev/random and assume that each
+ * contains full entropy.
+ */
+ return 8;
+}
+
+#endif /* _IPXE_LINUX_ENTROPY_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_nap.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_nap.h
new file mode 100644
index 00000000..5bac7242
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_nap.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_LINUX_NAP_H
+#define _IPXE_LINUX_NAP_H
+
+/** @file
+ *
+ * Linux CPU sleeping
+ *
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#ifdef NAP_LINUX
+#define NAP_PREFIX_linux
+#else
+#define NAP_PREFIX_linux __linux_
+#endif
+
+#endif /* _IPXE_LINUX_NAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_smbios.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_smbios.h
new file mode 100644
index 00000000..6d51e13b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_smbios.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_LINUX_SMBIOS_H
+#define _IPXE_LINUX_SMBIOS_H
+
+/** @file
+ *
+ * iPXE SMBIOS API for linux
+ *
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#ifdef SMBIOS_LINUX
+#define SMBIOS_PREFIX_linux
+#else
+#define SMBIOS_PREFIX_linux __linux_
+#endif
+
+#endif /* _IPXE_LINUX_SMBIOS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_time.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_time.h
new file mode 100644
index 00000000..93a25773
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_time.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_LINUX_TIME_H
+#define _IPXE_LINUX_TIME_H
+
+/** @file
+ *
+ * Linux time source
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef TIME_LINUX
+#define TIME_PREFIX_linux
+#else
+#define TIME_PREFIX_linux __linux_
+#endif
+
+#endif /* _IPXE_LINUX_TIME_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_timer.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_timer.h
new file mode 100644
index 00000000..37950741
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_timer.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_LINUX_TIMER_H
+#define _IPXE_LINUX_TIMER_H
+
+/** @file
+ *
+ * iPXE timer API for Linux
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef TIMER_LINUX
+#define TIMER_PREFIX_linux
+#else
+#define TIMER_PREFIX_linux __linux_
+#endif
+
+#endif /* _IPXE_LINUX_TIMER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_uaccess.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_uaccess.h
new file mode 100644
index 00000000..1b496117
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_uaccess.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _IPXE_LINUX_UACCESS_H
+#define _IPXE_LINUX_UACCESS_H
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+/** @file
+ *
+ * iPXE user access API for linux
+ *
+ * In linux userspace virtual == user == phys addresses.
+ * Physical addresses also being the same is wrong, but there is no general way
+ * of converting userspace addresses to physical as what appears to be
+ * contiguous in userspace is physically fragmented.
+ * Currently only the DMA memory is special-cased, but its conversion to bus
+ * addresses is done in phys_to_bus.
+ * This is known to break virtio as it is passing phys addresses to the virtual
+ * device.
+ */
+
+#ifdef UACCESS_LINUX
+#define UACCESS_PREFIX_linux
+#else
+#define UACCESS_PREFIX_linux __linux_
+#endif
+
+static inline __always_inline userptr_t
+UACCESS_INLINE(linux, phys_to_user)(unsigned long phys_addr)
+{
+ return phys_addr;
+}
+
+static inline __always_inline unsigned long
+UACCESS_INLINE(linux, user_to_phys)(userptr_t userptr, off_t offset)
+{
+ return userptr + offset;
+}
+
+static inline __always_inline userptr_t
+UACCESS_INLINE(linux, virt_to_user)(volatile const void *addr)
+{
+ return trivial_virt_to_user(addr);
+}
+
+static inline __always_inline void *
+UACCESS_INLINE(linux, user_to_virt)(userptr_t userptr, off_t offset)
+{
+ return trivial_user_to_virt(userptr, offset);
+}
+
+static inline __always_inline userptr_t
+UACCESS_INLINE(linux, userptr_add)(userptr_t userptr, off_t offset)
+{
+ return trivial_userptr_add(userptr, offset);
+}
+
+static inline __always_inline void
+UACCESS_INLINE(linux, memcpy_user)(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
+{
+ trivial_memcpy_user(dest, dest_off, src, src_off, len);
+}
+
+static inline __always_inline void
+UACCESS_INLINE(linux, memmove_user)(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
+{
+ trivial_memmove_user(dest, dest_off, src, src_off, len);
+}
+
+static inline __always_inline void
+UACCESS_INLINE(linux, memset_user)(userptr_t buffer, off_t offset, int c, size_t len)
+{
+ trivial_memset_user(buffer, offset, c, len);
+}
+
+static inline __always_inline size_t
+UACCESS_INLINE(linux, strlen_user)(userptr_t buffer, off_t offset)
+{
+ return trivial_strlen_user(buffer, offset);
+}
+
+static inline __always_inline off_t
+UACCESS_INLINE(linux, memchr_user)(userptr_t buffer, off_t offset, int c, size_t len)
+{
+ return trivial_memchr_user(buffer, offset, c, len);
+}
+
+#endif /* _IPXE_LINUX_UACCESS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_umalloc.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_umalloc.h
new file mode 100644
index 00000000..4de55ecf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux/linux_umalloc.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_LINUX_UMALLOC_H
+#define _IPXE_LINUX_UMALLOC_H
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+/** @file
+ *
+ * iPXE user memory allocation API for linux
+ *
+ */
+
+#ifdef UMALLOC_LINUX
+#define UMALLOC_PREFIX_linux
+#else
+#define UMALLOC_PREFIX_linux __linux_
+#endif
+
+#endif /* _IPXE_LINUX_UMALLOC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux_compat.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux_compat.h
new file mode 100644
index 00000000..6f6ed97d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/linux_compat.h
@@ -0,0 +1,27 @@
+#ifndef _IPXE_LINUX_COMPAT_H
+#define _IPXE_LINUX_COMPAT_H
+
+/** @file
+ *
+ * Linux code compatibility
+ *
+ * This file exists to ease the building of Linux source code within
+ * iPXE. This is intended to facilitate quick testing; it is not
+ * intended to be a substitute for proper porting.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <errno.h>
+#include <stdio.h>
+#include <byteswap.h>
+#include <ipxe/bitops.h>
+
+#define __init
+#define __exit
+#define __initdata
+#define __exitdata
+#define printk printf
+
+#endif /* _IPXE_LINUX_COMPAT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/list.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/list.h
new file mode 100644
index 00000000..b14a83d7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/list.h
@@ -0,0 +1,463 @@
+#ifndef _IPXE_LIST_H
+#define _IPXE_LIST_H
+
+/** @file
+ *
+ * Linked lists
+ *
+ * This linked list handling code is based on the Linux kernel's
+ * list.h.
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include <stddef.h>
+#include <assert.h>
+
+/** A doubly-linked list entry (or list head) */
+struct list_head {
+ /** Next list entry */
+ struct list_head *next;
+ /** Previous list entry */
+ struct list_head *prev;
+};
+
+/**
+ * Initialise a static list head
+ *
+ * @v list List head
+ */
+#define LIST_HEAD_INIT( list ) { &(list), &(list) }
+
+/**
+ * Declare a static list head
+ *
+ * @v list List head
+ */
+#define LIST_HEAD( list ) \
+ struct list_head list = LIST_HEAD_INIT ( list )
+
+/**
+ * Initialise a list head
+ *
+ * @v list List head
+ */
+#define INIT_LIST_HEAD( list ) do { \
+ (list)->next = (list); \
+ (list)->prev = (list); \
+ } while ( 0 )
+
+/**
+ * Check a list entry or list head is valid
+ *
+ * @v list List entry or head
+ */
+#define list_check( list ) ( { \
+ assert ( (list) != NULL ); \
+ assert ( (list)->prev != NULL ); \
+ assert ( (list)->next != NULL ); \
+ assert ( (list)->next->prev == (list) ); \
+ assert ( (list)->prev->next == (list) ); \
+ } )
+
+/**
+ * Insert a list entry between two known consecutive entries
+ *
+ * @v new New list entry
+ * @v prev Previous list entry
+ * @v next Next list entry
+ */
+static inline void __list_add ( struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next ) {
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * Add a new entry to the head of a list
+ *
+ * @v new New entry to be added
+ * @v head List head, or entry after which to add the new entry
+ */
+static inline void list_add ( struct list_head *new, struct list_head *head ) {
+ __list_add ( new, head, head->next );
+}
+#define list_add( new, head ) do { \
+ list_check ( (head) ); \
+ list_add ( (new), (head) ); \
+ } while ( 0 )
+
+/**
+ * Add a new entry to the tail of a list
+ *
+ * @v new New entry to be added
+ * @v head List head, or entry before which to add the new entry
+ */
+static inline void list_add_tail ( struct list_head *new,
+ struct list_head *head ) {
+ __list_add ( new, head->prev, head );
+}
+#define list_add_tail( new, head ) do { \
+ list_check ( (head) ); \
+ list_add_tail ( (new), (head) ); \
+ } while ( 0 )
+
+/**
+ * Delete a list entry between two known consecutive entries
+ *
+ * @v prev Previous list entry
+ * @v next Next list entry
+ */
+static inline void __list_del ( struct list_head *prev,
+ struct list_head *next ) {
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * Delete an entry from a list
+ *
+ * @v list List entry
+ *
+ * Note that list_empty() on entry does not return true after this;
+ * the entry is in an undefined state.
+ */
+static inline void list_del ( struct list_head *list ) {
+ __list_del ( list->prev, list->next );
+}
+#define list_del( list ) do { \
+ list_check ( (list) ); \
+ list_del ( (list) ); \
+ } while ( 0 )
+
+/**
+ * Test whether a list is empty
+ *
+ * @v list List head
+ */
+static inline int list_empty ( const struct list_head *list ) {
+ return ( list->next == list );
+}
+#define list_empty( list ) ( { \
+ list_check ( (list) ); \
+ list_empty ( (list) ); } )
+
+/**
+ * Test whether a list has just one entry
+ *
+ * @v list List to test
+ */
+static inline int list_is_singular ( const struct list_head *list ) {
+ return ( ( ! list_empty ( list ) ) && ( list->next == list->prev ) );
+}
+#define list_is_singular( list ) ( { \
+ list_check ( (list) ); \
+ list_is_singular ( (list) ); } )
+
+/**
+ * Test whether an entry is the last entry in list
+ *
+ * @v list List entry to test
+ * @v head List head
+ */
+static inline int list_is_last ( const struct list_head *list,
+ const struct list_head *head ) {
+ return ( list->next == head );
+}
+#define list_is_last( list, head ) ( { \
+ list_check ( (list) ); \
+ list_check ( (head) ); \
+ list_is_last ( (list), (head) ); } )
+
+/**
+ * Cut a list into two
+ *
+ * @v new A new list to contain all removed entries
+ * @v list An existing list
+ * @v entry An entry within the existing list
+ *
+ * All entries from @c list up to and including @c entry are moved to
+ * @c new, which should be an empty list. @c entry may be equal to @c
+ * list, in which case no entries are moved.
+ */
+static inline void list_cut_position ( struct list_head *new,
+ struct list_head *list,
+ struct list_head *entry ) {
+ struct list_head *first = entry->next;
+
+ if ( list != entry ) {
+ new->next = list->next;
+ new->next->prev = new;
+ new->prev = entry;
+ new->prev->next = new;
+ list->next = first;
+ list->next->prev = list;
+ }
+}
+#define list_cut_position( new, list, entry ) do { \
+ list_check ( (new) ); \
+ assert ( list_empty ( (new) ) ); \
+ list_check ( (list) ); \
+ list_check ( (entry) ); \
+ list_cut_position ( (new), (list), (entry) ); \
+ } while ( 0 )
+
+/**
+ * Move all entries from one list into another list
+ *
+ * @v list List of entries to add
+ * @v entry Entry after which to add the new entries
+ *
+ * All entries from @c list are inserted after @c entry. Note that @c
+ * list is left in an undefined state; use @c list_splice_init() if
+ * you want @c list to become an empty list.
+ */
+static inline void list_splice ( const struct list_head *list,
+ struct list_head *entry ) {
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+
+ if ( ! list_empty ( list ) ) {
+ last->next = entry->next;
+ last->next->prev = last;
+ first->prev = entry;
+ first->prev->next = first;
+ }
+}
+#define list_splice( list, entry ) do { \
+ list_check ( (list) ); \
+ list_check ( (entry) ); \
+ list_splice ( (list), (entry) ); \
+ } while ( 0 )
+
+/**
+ * Move all entries from one list into another list
+ *
+ * @v list List of entries to add
+ * @v entry Entry before which to add the new entries
+ *
+ * All entries from @c list are inserted before @c entry. Note that @c
+ * list is left in an undefined state; use @c list_splice_tail_init() if
+ * you want @c list to become an empty list.
+ */
+static inline void list_splice_tail ( const struct list_head *list,
+ struct list_head *entry ) {
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+
+ if ( ! list_empty ( list ) ) {
+ first->prev = entry->prev;
+ first->prev->next = first;
+ last->next = entry;
+ last->next->prev = last;
+ }
+}
+#define list_splice_tail( list, entry ) do { \
+ list_check ( (list) ); \
+ list_check ( (entry) ); \
+ list_splice_tail ( (list), (entry) ); \
+ } while ( 0 )
+
+/**
+ * Move all entries from one list into another list and reinitialise empty list
+ *
+ * @v list List of entries to add
+ * @v entry Entry after which to add the new entries
+ *
+ * All entries from @c list are inserted after @c entry.
+ */
+static inline void list_splice_init ( struct list_head *list,
+ struct list_head *entry ) {
+ list_splice ( list, entry );
+ INIT_LIST_HEAD ( list );
+}
+#define list_splice_init( list, entry ) do { \
+ list_check ( (list) ); \
+ list_check ( (entry) ); \
+ list_splice_init ( (list), (entry) ); \
+ } while ( 0 )
+
+/**
+ * Move all entries from one list into another list and reinitialise empty list
+ *
+ * @v list List of entries to add
+ * @v entry Entry before which to add the new entries
+ *
+ * All entries from @c list are inserted before @c entry.
+ */
+static inline void list_splice_tail_init ( struct list_head *list,
+ struct list_head *entry ) {
+ list_splice_tail ( list, entry );
+ INIT_LIST_HEAD ( list );
+}
+#define list_splice_tail_init( list, entry ) do { \
+ list_check ( (list) ); \
+ list_check ( (entry) ); \
+ list_splice_tail_init ( (list), (entry) ); \
+ } while ( 0 )
+
+/**
+ * Get the container of a list entry
+ *
+ * @v list List entry
+ * @v type Containing type
+ * @v member Name of list field within containing type
+ * @ret container Containing object
+ */
+#define list_entry( list, type, member ) ( { \
+ list_check ( (list) ); \
+ container_of ( list, type, member ); } )
+
+/**
+ * Get the container of the first entry in a list
+ *
+ * @v list List head
+ * @v type Containing type
+ * @v member Name of list field within containing type
+ * @ret first First list entry, or NULL
+ */
+#define list_first_entry( list, type, member ) \
+ ( list_empty ( (list) ) ? \
+ ( type * ) NULL : \
+ list_entry ( (list)->next, type, member ) )
+
+/**
+ * Get the container of the last entry in a list
+ *
+ * @v list List head
+ * @v type Containing type
+ * @v member Name of list field within containing type
+ * @ret first First list entry, or NULL
+ */
+#define list_last_entry( list, type, member ) \
+ ( list_empty ( (list) ) ? \
+ ( type * ) NULL : \
+ list_entry ( (list)->prev, type, member ) )
+
+/**
+ * Iterate over a list
+ *
+ * @v pos Iterator
+ * @v head List head
+ */
+#define list_for_each( pos, head ) \
+ for ( list_check ( (head) ), \
+ pos = (head)->next; \
+ pos != (head); \
+ pos = (pos)->next )
+
+/**
+ * Iterate over entries in a list
+ *
+ * @v pos Iterator
+ * @v head List head
+ * @v member Name of list field within iterator's type
+ */
+#define list_for_each_entry( pos, head, member ) \
+ for ( list_check ( (head) ), \
+ pos = list_entry ( (head)->next, typeof ( *pos ), member ); \
+ &pos->member != (head); \
+ pos = list_entry ( pos->member.next, typeof ( *pos ), member ) )
+
+/**
+ * Iterate over entries in a list in reverse order
+ *
+ * @v pos Iterator
+ * @v head List head
+ * @v member Name of list field within iterator's type
+ */
+#define list_for_each_entry_reverse( pos, head, member ) \
+ for ( list_check ( (head) ), \
+ pos = list_entry ( (head)->prev, typeof ( *pos ), member ); \
+ &pos->member != (head); \
+ pos = list_entry ( pos->member.prev, typeof ( *pos ), member ) )
+
+/**
+ * Iterate over entries in a list, safe against deletion of the current entry
+ *
+ * @v pos Iterator
+ * @v tmp Temporary value (of same type as iterator)
+ * @v head List head
+ * @v member Name of list field within iterator's type
+ */
+#define list_for_each_entry_safe( pos, tmp, head, member ) \
+ for ( list_check ( (head) ), \
+ pos = list_entry ( (head)->next, typeof ( *pos ), member ), \
+ tmp = list_entry ( pos->member.next, typeof ( *tmp ), member ); \
+ &pos->member != (head); \
+ pos = tmp, \
+ tmp = list_entry ( tmp->member.next, typeof ( *tmp ), member ) )
+
+/**
+ * Iterate over entries in a list, starting after current position
+ *
+ * @v pos Iterator
+ * @v head List head
+ * @v member Name of list field within iterator's type
+ */
+#define list_for_each_entry_continue( pos, head, member ) \
+ for ( list_check ( (head) ), \
+ pos = list_entry ( pos->member.next, typeof ( *pos ), member ); \
+ &pos->member != (head); \
+ pos = list_entry ( pos->member.next, typeof ( *pos ), member ) )
+
+/**
+ * Iterate over entries in a list in reverse, starting after current position
+ *
+ * @v pos Iterator
+ * @v head List head
+ * @v member Name of list field within iterator's type
+ */
+#define list_for_each_entry_continue_reverse( pos, head, member ) \
+ for ( list_check ( (head) ), \
+ pos = list_entry ( pos->member.prev, typeof ( *pos ), member ); \
+ &pos->member != (head); \
+ pos = list_entry ( pos->member.prev, typeof ( *pos ), member ) )
+
+/**
+ * Test if list contains a specified entry
+ *
+ * @v entry Entry
+ * @v head List head
+ * @ret present List contains specified entry
+ */
+static inline int list_contains ( struct list_head *entry,
+ struct list_head *head ) {
+ struct list_head *tmp;
+
+ list_for_each ( tmp, head ) {
+ if ( tmp == entry )
+ return 1;
+ }
+ return 0;
+}
+#define list_contains( entry, head ) ( { \
+ list_check ( (head) ); \
+ list_check ( (entry) ); \
+ list_contains ( (entry), (head) ); } )
+
+/**
+ * Test if list contains a specified entry
+ *
+ * @v entry Entry
+ * @v head List head
+ * @ret present List contains specified entry
+ */
+#define list_contains_entry( entry, head, member ) \
+ list_contains ( &(entry)->member, (head) )
+
+/**
+ * Check list contains a specified entry
+ *
+ * @v entry Entry
+ * @v head List head
+ * @v member Name of list field within iterator's type
+ */
+#define list_check_contains_entry( entry, head, member ) do { \
+ assert ( list_contains_entry ( (entry), (head), member ) ); \
+ } while ( 0 )
+
+#endif /* _IPXE_LIST_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/login_ui.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/login_ui.h
new file mode 100644
index 00000000..01e5479f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/login_ui.h
@@ -0,0 +1,14 @@
+#ifndef _IPXE_LOGIN_UI_H
+#define _IPXE_LOGIN_UI_H
+
+/** @file
+ *
+ * Login UI
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern int login_ui ( void );
+
+#endif /* _IPXE_LOGIN_UI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/malloc.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/malloc.h
new file mode 100644
index 00000000..c435a7dd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/malloc.h
@@ -0,0 +1,81 @@
+#ifndef _IPXE_MALLOC_H
+#define _IPXE_MALLOC_H
+
+#include <stdint.h>
+
+/** @file
+ *
+ * Dynamic memory allocation
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * Prototypes for the standard functions (malloc() et al) are in
+ * stdlib.h. Include <ipxe/malloc.h> only if you need the
+ * non-standard functions, such as malloc_dma().
+ *
+ */
+#include <stdlib.h>
+#include <ipxe/tables.h>
+#include <valgrind/memcheck.h>
+
+extern size_t freemem;
+
+extern void * __malloc alloc_memblock ( size_t size, size_t align );
+extern void free_memblock ( void *ptr, size_t size );
+extern void mpopulate ( void *start, size_t len );
+extern void mdumpfree ( void );
+
+/**
+ * Allocate memory for DMA
+ *
+ * @v size Requested size
+ * @v align Physical alignment
+ * @ret ptr Memory, or NULL
+ *
+ * Allocates physically-aligned memory for DMA.
+ *
+ * @c align must be a power of two. @c size may not be zero.
+ */
+static inline void * __malloc malloc_dma ( size_t size, size_t phys_align ) {
+ void * ptr = alloc_memblock ( size, phys_align );
+ if ( ptr && size )
+ VALGRIND_MALLOCLIKE_BLOCK ( ptr, size, 0, 0 );
+ return ptr;
+}
+
+/**
+ * Free memory allocated with malloc_dma()
+ *
+ * @v ptr Memory allocated by malloc_dma(), or NULL
+ * @v size Size of memory, as passed to malloc_dma()
+ *
+ * Memory allocated with malloc_dma() can only be freed with
+ * free_dma(); it cannot be freed with the standard free().
+ *
+ * If @c ptr is NULL, no action is taken.
+ */
+static inline void free_dma ( void *ptr, size_t size ) {
+ free_memblock ( ptr, size );
+ VALGRIND_FREELIKE_BLOCK ( ptr, 0 );
+}
+
+/** A cache discarder */
+struct cache_discarder {
+ /**
+ * Discard some cached data
+ *
+ * @ret discarded Number of cached items discarded
+ */
+ unsigned int ( * discard ) ( void );
+};
+
+/** Cache discarder table */
+#define CACHE_DISCARDERS __table ( struct cache_discarder, "cache_discarders" )
+
+/** Declare a cache discarder */
+#define __cache_discarder __table_entry ( CACHE_DISCARDERS, 01 )
+
+#endif /* _IPXE_MALLOC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/mca.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/mca.h
new file mode 100644
index 00000000..d86dab19
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/mca.h
@@ -0,0 +1,106 @@
+/*
+ * MCA bus driver code
+ *
+ * Abstracted from 3c509.c.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef MCA_H
+#define MCA_H
+
+#include <ipxe/isa_ids.h>
+#include <ipxe/device.h>
+#include <ipxe/tables.h>
+
+/*
+ * MCA constants
+ *
+ */
+#define MCA_MOTHERBOARD_SETUP_REG 0x94
+#define MCA_ADAPTER_SETUP_REG 0x96
+#define MCA_MAX_SLOT_NR 0x07 /* Must be 2^n - 1 */
+#define MCA_POS_REG(n) (0x100+(n))
+
+/* Is there a standard that would define this? */
+#define GENERIC_MCA_VENDOR ISA_VENDOR ( 'M', 'C', 'A' )
+
+/** An MCA device ID list entry */
+struct mca_device_id {
+ /** Name */
+ const char *name;
+ /** Device ID */
+ uint16_t id;
+};
+
+/** An MCA device */
+struct mca_device {
+ /** Generic device */
+ struct device dev;
+ /** Slot number */
+ unsigned int slot;
+ /** POS register values */
+ unsigned char pos[8];
+ /** Driver for this device */
+ struct mca_driver *driver;
+ /** Driver-private data
+ *
+ * Use mca_set_drvdata() and mca_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+};
+
+#define MCA_ID(mca) ( ( (mca)->pos[1] << 8 ) + (mca)->pos[0] )
+
+/** An MCA driver */
+struct mca_driver {
+ /** MCA ID table */
+ struct mca_device_id *ids;
+ /** Number of entries in MCA ID table */
+ unsigned int id_count;
+ /**
+ * Probe device
+ *
+ * @v mca MCA device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct mca_device *mca,
+ const struct mca_device_id *id );
+ /**
+ * Remove device
+ *
+ * @v mca MCA device
+ */
+ void ( * remove ) ( struct mca_device *mca );
+};
+
+/** MCA driver table */
+#define MCA_DRIVERS __table ( struct mca_driver, "mca_drivers" )
+
+/** Declare an MCA driver */
+#define __mca_driver __table_entry ( MCA_DRIVERS, 01 )
+
+/**
+ * Set MCA driver-private data
+ *
+ * @v mca MCA device
+ * @v priv Private data
+ */
+static inline void mca_set_drvdata ( struct mca_device *mca, void *priv ) {
+ mca->priv = priv;
+}
+
+/**
+ * Get MCA driver-private data
+ *
+ * @v mca MCA device
+ * @ret priv Private data
+ */
+static inline void * mca_get_drvdata ( struct mca_device *mca ) {
+ return mca->priv;
+}
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/md5.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/md5.h
new file mode 100644
index 00000000..860bc476
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/md5.h
@@ -0,0 +1,73 @@
+#ifndef _IPXE_MD5_H
+#define _IPXE_MD5_H
+
+/** @file
+ *
+ * MD5 algorithm
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/crypto.h>
+
+/** An MD5 digest */
+struct md5_digest {
+ /** Hash output */
+ uint32_t h[4];
+};
+
+/** An MD5 data block */
+union md5_block {
+ /** Raw bytes */
+ uint8_t byte[64];
+ /** Raw dwords */
+ uint32_t dword[16];
+ /** Final block structure */
+ struct {
+ /** Padding */
+ uint8_t pad[56];
+ /** Length in bits */
+ uint64_t len;
+ } final;
+};
+
+/** MD5 digest and data block
+ *
+ * The order of fields within this structure is designed to minimise
+ * code size.
+ */
+struct md5_digest_data {
+ /** Digest of data already processed */
+ struct md5_digest digest;
+ /** Accumulated data */
+ union md5_block data;
+} __attribute__ (( packed ));
+
+/** MD5 digest and data block */
+union md5_digest_data_dwords {
+ /** Digest and data block */
+ struct md5_digest_data dd;
+ /** Raw dwords */
+ uint32_t dword[ sizeof ( struct md5_digest_data ) /
+ sizeof ( uint32_t ) ];
+};
+
+/** An MD5 context */
+struct md5_context {
+ /** Amount of accumulated data */
+ size_t len;
+ /** Digest and accumulated data */
+ union md5_digest_data_dwords ddd;
+} __attribute__ (( packed ));
+
+/** MD5 context size */
+#define MD5_CTX_SIZE sizeof ( struct md5_context )
+
+/** MD5 digest size */
+#define MD5_DIGEST_SIZE sizeof ( struct md5_digest )
+
+extern struct digest_algorithm md5_algorithm;
+
+#endif /* _IPXE_MD5_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/menu.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/menu.h
new file mode 100644
index 00000000..993b027e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/menu.h
@@ -0,0 +1,49 @@
+#ifndef _IPXE_MENU_H
+#define _IPXE_MENU_H
+
+/** @file
+ *
+ * Menu selection
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/list.h>
+
+/** A menu */
+struct menu {
+ /** List of menus */
+ struct list_head list;
+ /** Name */
+ const char *name;
+ /** Title */
+ const char *title;
+ /** Menu items */
+ struct list_head items;
+};
+
+/** A menu item */
+struct menu_item {
+ /** List of menu items */
+ struct list_head list;
+ /** Label */
+ const char *label;
+ /** Text */
+ const char *text;
+ /** Shortcut key */
+ int shortcut;
+ /** Is default item */
+ int is_default;
+};
+
+extern struct menu * create_menu ( const char *name, const char *title );
+extern struct menu_item * add_menu_item ( struct menu *menu, const char *label,
+ const char *text, int shortcut,
+ int is_default );
+extern void destroy_menu ( struct menu *menu );
+extern struct menu * find_menu ( const char *name );
+extern int show_menu ( struct menu *menu, unsigned int timeout_ms,
+ const char *select, struct menu_item **selected );
+
+#endif /* _IPXE_MENU_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/mii.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/mii.h
new file mode 100644
index 00000000..a33a31d9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/mii.h
@@ -0,0 +1,86 @@
+#ifndef _IPXE_MII_H
+#define _IPXE_MII_H
+
+/** @file
+ *
+ * Media Independent Interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <mii.h>
+#include <ipxe/netdevice.h>
+
+struct mii_interface;
+
+/** MII interface operations */
+struct mii_operations {
+ /**
+ * Read from MII register
+ *
+ * @v mii MII interface
+ * @v reg Register address
+ * @ret data Data read, or negative error
+ */
+ int ( * read ) ( struct mii_interface *mii, unsigned int reg );
+ /**
+ * Write to MII register
+ *
+ * @v mii MII interface
+ * @v reg Register address
+ * @v data Data to write
+ * @ret rc Return status code
+ */
+ int ( * write ) ( struct mii_interface *mii, unsigned int reg,
+ unsigned int data );
+};
+
+/** An MII interface */
+struct mii_interface {
+ /** Interface operations */
+ struct mii_operations *op;
+};
+
+/**
+ * Initialise MII interface
+ *
+ * @v mii MII interface
+ * @v op MII interface operations
+ */
+static inline __attribute__ (( always_inline )) void
+mii_init ( struct mii_interface *mii, struct mii_operations *op ) {
+ mii->op = op;
+}
+
+/**
+ * Read from MII register
+ *
+ * @v mii MII interface
+ * @v reg Register address
+ * @ret data Data read, or negative error
+ */
+static inline __attribute__ (( always_inline )) int
+mii_read ( struct mii_interface *mii, unsigned int reg ) {
+ return mii->op->read ( mii, reg );
+}
+
+/**
+ * Write to MII register
+ *
+ * @v mii MII interface
+ * @v reg Register address
+ * @v data Data to write
+ * @ret rc Return status code
+ */
+static inline __attribute__ (( always_inline )) int
+mii_write ( struct mii_interface *mii, unsigned int reg, unsigned int data ) {
+ return mii->op->write ( mii, reg, data );
+}
+
+/** Maximum time to wait for a reset, in milliseconds */
+#define MII_RESET_MAX_WAIT_MS 500
+
+extern int mii_reset ( struct mii_interface *mii );
+
+#endif /* _IPXE_MII_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/monojob.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/monojob.h
new file mode 100644
index 00000000..3d8b31c0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/monojob.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_MONOJOB_H
+#define _IPXE_MONOJOB_H
+
+/** @file
+ *
+ * Single foreground job
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct interface;
+
+extern struct interface monojob;
+
+extern int monojob_wait ( const char *string );
+
+#endif /* _IPXE_MONOJOB_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/nap.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/nap.h
new file mode 100644
index 00000000..afc88791
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/nap.h
@@ -0,0 +1,57 @@
+#ifndef _IPXE_NAP_H
+#define _IPXE_NAP_H
+
+/** @file
+ *
+ * CPU sleeping
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/api.h>
+#include <config/nap.h>
+
+/**
+ * Calculate static inline CPU sleeping API function name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ */
+#define NAP_INLINE( _subsys, _api_func ) \
+ SINGLE_API_INLINE ( NAP_PREFIX_ ## _subsys, _api_func )
+
+/**
+ * Provide an CPU sleeping API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_NAP( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( NAP_PREFIX_ ## _subsys, _api_func, _func )
+
+/**
+ * Provide a static inline CPU sleeping API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ */
+#define PROVIDE_NAP_INLINE( _subsys, _api_func ) \
+ PROVIDE_SINGLE_API_INLINE ( NAP_PREFIX_ ## _subsys, _api_func )
+
+/* Include all architecture-independent I/O API headers */
+#include <ipxe/null_nap.h>
+#include <ipxe/linux/linux_nap.h>
+
+/* Include all architecture-dependent I/O API headers */
+#include <bits/nap.h>
+
+/**
+ * Sleep until next CPU interrupt
+ *
+ */
+void cpu_nap ( void );
+
+#endif /* _IPXE_NAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ndp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ndp.h
new file mode 100644
index 00000000..42bb2fe0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ndp.h
@@ -0,0 +1,21 @@
+#include <stdint.h>
+#include <byteswap.h>
+#include <string.h>
+#include <ipxe/icmp6.h>
+#include <ipxe/ip6.h>
+#include <ipxe/in.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/tcpip.h>
+
+#define NDP_STATE_INVALID 0
+#define NDP_STATE_INCOMPLETE 1
+#define NDP_STATE_REACHABLE 2
+#define NDP_STATE_DELAY 3
+#define NDP_STATE_PROBE 4
+#define NDP_STATE_STALE 5
+
+int ndp_resolve ( struct net_device *netdev, struct in6_addr *src,
+ struct in6_addr *dest, void *dest_ll_addr );
+int ndp_process_advert ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest );
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/net80211.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/net80211.h
new file mode 100644
index 00000000..771872c8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/net80211.h
@@ -0,0 +1,1207 @@
+#ifndef _IPXE_NET80211_H
+#define _IPXE_NET80211_H
+
+#include <ipxe/process.h>
+#include <ipxe/ieee80211.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/rc80211.h>
+
+/** @file
+ *
+ * The iPXE 802.11 MAC layer.
+ */
+
+/*
+ * Major things NOT YET supported:
+ * - any type of security
+ * - 802.11n
+ *
+ * Major things that probably will NEVER be supported, barring a
+ * compelling use case and/or corporate sponsorship:
+ * - QoS
+ * - 802.1X authentication ("WPA Enterprise")
+ * - Contention-free periods
+ * - "ad-hoc" networks (IBSS), monitor mode, host AP mode
+ * - hidden networks on the 5GHz band due to regulatory issues
+ * - spectrum management on the 5GHz band (TPC and DFS), as required
+ * in some non-US regulatory domains
+ * - Clause 14 PHYs (Frequency-Hopping Spread Spectrum on 2.4GHz)
+ * and Clause 16 PHYs (infrared) - I'm not aware of any real-world
+ * use of these.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* All 802.11 devices are handled using a generic "802.11 device"
+ net_device, with a link in its `priv' field to a net80211_device
+ which we use to handle 802.11-specific details. */
+
+
+/** @defgroup net80211_band RF bands on which an 802.11 device can transmit */
+/** @{ */
+
+/** The 2.4 GHz ISM band, unlicensed in most countries */
+#define NET80211_BAND_2GHZ 0
+/** The band from 4.9 GHz to 5.7 GHz, which tends to be more restricted */
+#define NET80211_BAND_5GHZ 1
+/** Number of RF bands */
+#define NET80211_NR_BANDS 2
+
+/** Bitmask for the 2GHz band */
+#define NET80211_BAND_BIT_2GHZ (1 << 0)
+/** Bitmask for the 5GHz band */
+#define NET80211_BAND_BIT_5GHZ (1 << 1)
+
+/** @} */
+
+
+/** @defgroup net80211_mode 802.11 operation modes supported by hardware */
+/** @{ */
+
+/** 802.11a: 54 Mbps operation using OFDM signaling on the 5GHz band */
+#define NET80211_MODE_A (1 << 0)
+
+/** 802.11b: 1-11 Mbps operation using DSSS/CCK signaling on the 2.4GHz band */
+#define NET80211_MODE_B (1 << 1)
+
+/** 802.11g: 54 Mbps operation using ERP/OFDM signaling on the 2.4GHz band */
+#define NET80211_MODE_G (1 << 2)
+
+/** 802.11n: High-rate operation using MIMO technology on 2.4GHz or 5GHz */
+#define NET80211_MODE_N (1 << 3)
+
+/** @} */
+
+
+/** @defgroup net80211_cfg Constants for the net80211 config callback */
+/** @{ */
+
+/** Channel choice (@c dev->channel) or regulatory parameters have changed */
+#define NET80211_CFG_CHANNEL (1 << 0)
+
+/** Requested transmission rate (@c dev->rate) has changed */
+#define NET80211_CFG_RATE (1 << 1)
+
+/** Association has been established with a new BSS (@c dev->bssid) */
+#define NET80211_CFG_ASSOC (1 << 2)
+
+/** Low-level link parameters (short preamble, protection, etc) have changed */
+#define NET80211_CFG_PHY_PARAMS (1 << 3)
+
+/** @} */
+
+
+/** An 802.11 security handshaking protocol */
+enum net80211_security_proto {
+ /** No security handshaking
+ *
+ * This might be used with an open network or with WEP, as
+ * WEP does not have a cryptographic handshaking phase.
+ */
+ NET80211_SECPROT_NONE = 0,
+
+ /** Pre-shared key handshaking
+ *
+ * This implements the "WPA Personal" handshake. 802.1X
+ * authentication is not performed -- the user supplies a
+ * pre-shared key directly -- but there is a 4-way handshake
+ * between client and AP to verify that both have the same key
+ * without revealing the contents of that key.
+ */
+ NET80211_SECPROT_PSK = 1,
+
+ /** Full EAP 802.1X handshaking
+ *
+ * This implements the "WPA Enterprise" handshake, connecting
+ * to an 802.1X authentication server to provide credentials
+ * and receive a pairwise master key (PMK), which is then used
+ * in the same 4-way handshake as the PSK method.
+ */
+ NET80211_SECPROT_EAP = 2,
+
+ /** Dummy value used when the handshaking type can't be detected */
+ NET80211_SECPROT_UNKNOWN = 3,
+};
+
+
+/** An 802.11 data encryption algorithm */
+enum net80211_crypto_alg {
+ /** No security, an "Open" network */
+ NET80211_CRYPT_NONE = 0,
+
+ /** Network protected with WEP (awful RC4-based system)
+ *
+ * WEP uses a naive application of RC4, with a monotonically
+ * increasing initialization vector that is prepended to the
+ * key to initialize the RC4 keystream. It is highly insecure
+ * and can be completely cracked or subverted using automated,
+ * robust, freely available tools (aircrack-ng) in minutes.
+ *
+ * 40-bit and 104-bit WEP are differentiated only by the size
+ * of the key. They may be advertised as 64-bit and 128-bit,
+ * counting the non-random IV as part of the key bits.
+ */
+ NET80211_CRYPT_WEP = 1,
+
+ /** Network protected with TKIP (better RC4-based system)
+ *
+ * Usually known by its trade name of WPA (Wi-Fi Protected
+ * Access), TKIP implements a message integrity code (MIC)
+ * called Michael, a timestamp counter for replay prevention,
+ * and a key mixing function that together remove almost all
+ * the security problems with WEP. Countermeasures are
+ * implemented to prevent high data-rate attacks.
+ *
+ * There exists one known attack on TKIP, that allows one to
+ * send between 7 and 15 arbitrary short data packets on a
+ * QoS-enabled network given about an hour of data
+ * gathering. Since iPXE does not support QoS for 802.11
+ * networks, this is not a threat to us. The only other method
+ * is a brute-force passphrase attack.
+ */
+ NET80211_CRYPT_TKIP = 2,
+
+ /** Network protected with CCMP (AES-based system)
+ *
+ * Often called WPA2 in commerce, or RSNA (Robust Security
+ * Network Architecture) in the 802.11 standard, CCMP is
+ * highly secure and does not have any known attack vectors.
+ * Since it is based on a block cipher, the statistical
+ * correlation and "chopchop" attacks used with great success
+ * against WEP and minor success against TKIP fail.
+ */
+ NET80211_CRYPT_CCMP = 3,
+
+ /** Dummy value used when the cryptosystem can't be detected */
+ NET80211_CRYPT_UNKNOWN = 4,
+};
+
+
+/** @defgroup net80211_state Bits for the 802.11 association state field */
+/** @{ */
+
+/** An error code indicating the failure mode, or 0 if successful */
+#define NET80211_STATUS_MASK 0x7F
+
+/** Whether the error code provided is a "reason" code, not a "status" code */
+#define NET80211_IS_REASON 0x80
+
+/** Whether we have found the network we will be associating with */
+#define NET80211_PROBED (1 << 8)
+
+/** Whether we have successfully authenticated with the network
+ *
+ * This usually has nothing to do with actual security; it is a
+ * holdover from older 802.11 implementation ideas.
+ */
+#define NET80211_AUTHENTICATED (1 << 9)
+
+/** Whether we have successfully associated with the network */
+#define NET80211_ASSOCIATED (1 << 10)
+
+/** Whether we have completed security handshaking with the network
+ *
+ * Once this is set, we can send data packets. For that reason this
+ * bit is set even in cases where no security handshaking is
+ * required.
+ */
+#define NET80211_CRYPTO_SYNCED (1 << 11)
+
+/** Whether the auto-association task is running */
+#define NET80211_WORKING (1 << 12)
+
+/** Whether the auto-association task is waiting for a reply from the AP */
+#define NET80211_WAITING (1 << 13)
+
+/** Whether the auto-association task should be suppressed
+ *
+ * This is set by the `iwlist' command so that it can open the device
+ * without starting another probe process that will interfere with its
+ * own.
+ */
+#define NET80211_NO_ASSOC (1 << 14)
+
+/** Whether this association was performed using a broadcast SSID
+ *
+ * If the user opened this device without netX/ssid set, the device's
+ * SSID will be set to that of the network it chooses to associate
+ * with, but the netX/ssid setting will remain blank. If we don't
+ * remember that we started from no specified SSID, it will appear
+ * every time settings are updated (e.g. after DHCP) that we need to
+ * reassociate due to the difference between the set SSID and our own.
+ */
+#define NET80211_AUTO_SSID (1 << 15)
+
+
+/** @} */
+
+
+/** @defgroup net80211_phy 802.11 physical layer flags */
+/** @{ */
+
+/** Whether to use RTS/CTS or CTS-to-self protection for transmissions
+ *
+ * Since the RTS or CTS is transmitted using 802.11b signaling, and
+ * includes a field indicating the amount of time that will be used by
+ * transmission of the following packet, this serves as an effective
+ * protection mechanism to avoid 802.11b clients interfering with
+ * 802.11g clients on mixed networks.
+ */
+#define NET80211_PHY_USE_PROTECTION (1 << 1)
+
+/** Whether to use 802.11b short preamble operation
+ *
+ * Short-preamble operation can moderately increase throughput on
+ * 802.11b networks operating between 2Mbps and 11Mbps. It is
+ * irrelevant for 802.11g data rates, since they use a different
+ * modulation scheme.
+ */
+#define NET80211_PHY_USE_SHORT_PREAMBLE (1 << 2)
+
+/** Whether to use 802.11g short slot operation
+ *
+ * This affects a low-level timing parameter of 802.11g transmissions.
+ */
+#define NET80211_PHY_USE_SHORT_SLOT (1 << 3)
+
+/** @} */
+
+
+/** The maximum number of TX rates we allow to be configured simultaneously */
+#define NET80211_MAX_RATES 16
+
+/** The maximum number of channels we allow to be configured simultaneously */
+#define NET80211_MAX_CHANNELS 40
+
+/** Seconds we'll wait to get all fragments of a packet */
+#define NET80211_FRAG_TIMEOUT 2
+
+/** The number of fragments we can receive at once
+ *
+ * The 802.11 standard requires that this be at least 3.
+ */
+#define NET80211_NR_CONCURRENT_FRAGS 3
+
+/** Maximum TX power to allow (dBm), if we don't get a regulatory hint */
+#define NET80211_REG_TXPOWER 20
+
+
+struct net80211_device;
+
+/** Operations that must be implemented by an 802.11 driver */
+struct net80211_device_operations {
+ /** Open 802.11 device
+ *
+ * @v dev 802.11 device
+ * @ret rc Return status code
+ *
+ * This method should allocate RX I/O buffers and enable the
+ * hardware to start transmitting and receiving packets on the
+ * channels its net80211_register() call indicated it could
+ * handle. It does not need to tune the antenna to receive
+ * packets on any particular channel.
+ */
+ int ( * open ) ( struct net80211_device *dev );
+
+ /** Close 802.11 network device
+ *
+ * @v dev 802.11 device
+ *
+ * This method should stop the flow of packets, and call
+ * net80211_tx_complete() for any packets remaining in the
+ * device's TX queue.
+ */
+ void ( * close ) ( struct net80211_device *dev );
+
+ /** Transmit packet on 802.11 network device
+ *
+ * @v dev 802.11 device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * This method should cause the hardware to initiate
+ * transmission of the I/O buffer, using the channel and rate
+ * most recently indicated by an appropriate call to the
+ * @c config callback. The 802.11 layer guarantees that said
+ * channel and rate will be the same as those currently
+ * reflected in the fields of @a dev.
+ *
+ * If this method returns success, the I/O buffer remains
+ * owned by the network layer's TX queue, and the driver must
+ * eventually call net80211_tx_complete() to free the buffer
+ * whether transmission succeeded or not. If this method
+ * returns failure, it will be interpreted as "failure to
+ * enqueue buffer" and the I/O buffer will be immediately
+ * released.
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ int ( * transmit ) ( struct net80211_device *dev,
+ struct io_buffer *iobuf );
+
+ /** Poll for completed and received packets
+ *
+ * @v dev 802.11 device
+ *
+ * This method should cause the hardware to check for
+ * completed transmissions and received packets. Any received
+ * packets should be delivered via net80211_rx(), and
+ * completed transmissions should be indicated using
+ * net80211_tx_complete().
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ void ( * poll ) ( struct net80211_device *dev );
+
+ /** Enable or disable interrupts
+ *
+ * @v dev 802.11 device
+ * @v enable If TRUE, interrupts should be enabled
+ */
+ void ( * irq ) ( struct net80211_device *dev, int enable );
+
+ /** Update hardware state to match 802.11 layer state
+ *
+ * @v dev 802.11 device
+ * @v changed Set of flags indicating what may have changed
+ * @ret rc Return status code
+ *
+ * This method should cause the hardware state to be
+ * reinitialized from the state indicated in fields of
+ * net80211_device, in the areas indicated by bits set in
+ * @a changed. If the hardware is unable to do so, this method
+ * may return an appropriate error indication.
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ int ( * config ) ( struct net80211_device *dev, int changed );
+};
+
+/** An 802.11 RF channel. */
+struct net80211_channel
+{
+ /** The band with which this channel is associated */
+ u8 band;
+
+ /** A channel number interpreted according to the band
+ *
+ * The 2.4GHz band uses channel numbers from 1-13 at 5MHz
+ * intervals such that channel 1 is 2407 MHz; channel 14,
+ * legal for use only in Japan, is defined separately as 2484
+ * MHz. Adjacent channels will overlap, since 802.11
+ * transmissions use a 20 MHz (4-channel) bandwidth. Most
+ * commonly, channels 1, 6, and 11 are used.
+ *
+ * The 5GHz band uses channel numbers derived directly from
+ * the frequency; channel 0 is 5000 MHz, and channels are
+ * always spaced 5 MHz apart. Channel numbers over 180 are
+ * relative to 4GHz instead of 5GHz, but these are rarely
+ * seen. Most channels are not legal for use.
+ */
+ u8 channel_nr;
+
+ /** The center frequency for this channel
+ *
+ * Currently a bandwidth of 20 MHz is assumed.
+ */
+ u16 center_freq;
+
+ /** Hardware channel value */
+ u16 hw_value;
+
+ /** Maximum allowable transmit power, in dBm
+ *
+ * This should be interpreted as EIRP, the power supplied to
+ * an ideal isotropic antenna in order to achieve the same
+ * average signal intensity as the real hardware at a
+ * particular distance.
+ *
+ * Currently no provision is made for directional antennas.
+ */
+ u8 maxpower;
+};
+
+/** Information on the capabilities of an 802.11 hardware device
+ *
+ * In its probe callback, an 802.11 driver must read hardware
+ * registers to determine the appropriate contents of this structure,
+ * fill it, and pass it to net80211_register() so that the 802.11
+ * layer knows how to treat the hardware and what to advertise as
+ * supported to access points.
+ */
+struct net80211_hw_info
+{
+ /** Default hardware MAC address.
+ *
+ * The user may change this by setting the @c netX/mac setting
+ * before the driver's open function is called; in that case
+ * the driver must set the hardware MAC address to the address
+ * contained in the wrapping net_device's ll_addr field, or if
+ * that is impossible, set that ll_addr field back to the
+ * unchangeable hardware MAC address.
+ */
+ u8 hwaddr[ETH_ALEN];
+
+ /** A bitwise OR of the 802.11x modes supported by this device */
+ int modes;
+
+ /** A bitwise OR of the bands on which this device can communicate */
+ int bands;
+
+ /** A set of flags indicating peculiarities of this device. */
+ enum {
+ /** Received frames include a frame check sequence. */
+ NET80211_HW_RX_HAS_FCS = (1 << 1),
+
+ /** Hardware doesn't support 2.4GHz short preambles
+ *
+ * This is only relevant for 802.11b operation above
+ * 2Mbps. All 802.11g devices support short preambles.
+ */
+ NET80211_HW_NO_SHORT_PREAMBLE = (1 << 2),
+
+ /** Hardware doesn't support 802.11g short slot operation */
+ NET80211_HW_NO_SHORT_SLOT = (1 << 3),
+ } flags;
+
+ /** Signal strength information that can be provided by the device
+ *
+ * Signal strength is passed to net80211_rx(), primarily to
+ * allow determination of the closest access point for a
+ * multi-AP network. The units are provided for completeness
+ * of status displays.
+ */
+ enum {
+ /** No signal strength information supported */
+ NET80211_SIGNAL_NONE = 0,
+ /** Signal strength in arbitrary units */
+ NET80211_SIGNAL_ARBITRARY,
+ /** Signal strength in decibels relative to arbitrary base */
+ NET80211_SIGNAL_DB,
+ /** Signal strength in decibels relative to 1mW */
+ NET80211_SIGNAL_DBM,
+ } signal_type;
+
+ /** Maximum signal in arbitrary cases
+ *
+ * If signal_type is NET80211_SIGNAL_ARBITRARY or
+ * NET80211_SIGNAL_DB, the driver should report it on a scale
+ * from 0 to signal_max.
+ */
+ unsigned signal_max;
+
+ /** List of RF channels supported by the card */
+ struct net80211_channel channels[NET80211_MAX_CHANNELS];
+
+ /** Number of supported channels */
+ int nr_channels;
+
+ /** List of transmission rates supported by the card, indexed by band
+ *
+ * Rates should be in 100kbps increments (e.g. 11 Mbps would
+ * be represented as the number 110).
+ */
+ u16 rates[NET80211_NR_BANDS][NET80211_MAX_RATES];
+
+ /** Number of supported rates, indexed by band */
+ int nr_rates[NET80211_NR_BANDS];
+
+ /** Estimate of the time required to change channels, in microseconds
+ *
+ * If this is not known, a guess on the order of a few
+ * milliseconds (value of 1000-5000) is reasonable.
+ */
+ unsigned channel_change_time;
+};
+
+/** Structure tracking received fragments for a packet
+ *
+ * We set up a fragment cache entry when we receive a packet marked as
+ * fragment 0 with the "more fragments" bit set in its frame control
+ * header. We are required by the 802.11 standard to track 3
+ * fragmented packets arriving simultaneously; if we receive more we
+ * may drop some. Upon receipt of a new fragment-0 packet, if no entry
+ * is available or expired, we take over the most @e recent entry for
+ * the new packet, since we don't want to starve old entries from ever
+ * finishing at all. If we get a fragment after the zeroth with no
+ * cache entry for its packet, we drop it.
+ */
+struct net80211_frag_cache
+{
+ /** Whether this cache entry is in use */
+ u8 in_use;
+
+ /** Sequence number of this MSDU (packet) */
+ u16 seqnr;
+
+ /** Timestamp from point at which first fragment was collected */
+ u32 start_ticks;
+
+ /** Buffers for each fragment */
+ struct io_buffer *iob[16];
+};
+
+
+/** Interface to an 802.11 security handshaking protocol
+ *
+ * Security handshaking protocols handle parsing a user-specified key
+ * into a suitable input to the encryption algorithm, and for WPA and
+ * better systems, manage performing whatever authentication with the
+ * network is necessary.
+ *
+ * At all times when any method in this structure is called with a
+ * net80211_device argument @a dev, a dynamically allocated copy of
+ * the handshaker structure itself with space for the requested amount
+ * of private data may be accessed as @c dev->handshaker. The
+ * structure will not be modified, and will only be freed during
+ * reassociation and device closing after the @a stop method has been
+ * called.
+ */
+struct net80211_handshaker
+{
+ /** The security handshaking protocol implemented */
+ enum net80211_security_proto protocol;
+
+ /** Initialize security handshaking protocol
+ *
+ * @v dev 802.11 device
+ * @ret rc Return status code
+ *
+ * This method is expected to access @c netX/key or other
+ * applicable settings to determine the parameters for
+ * handshaking. If no handshaking is required, it should call
+ * sec80211_install() with the cryptosystem and key that are
+ * to be used, and @c start and @c step should be set to @c
+ * NULL.
+ *
+ * This is always called just before association is performed,
+ * but after its parameters have been set; in particular, you
+ * may rely on the contents of the @a essid field in @a dev.
+ */
+ int ( * init ) ( struct net80211_device *dev );
+
+ /** Start handshaking
+ *
+ * @v dev 802.11 device
+ * @ret rc Return status code
+ *
+ * This method is expected to set up internal state so that
+ * packets sent immediately after association, before @a step
+ * can be called, will be handled appropriately.
+ *
+ * This is always called just before association is attempted.
+ */
+ int ( * start ) ( struct net80211_device *dev );
+
+ /** Process handshaking state
+ *
+ * @v dev 802.11 device
+ * @ret rc Return status code, or positive if done
+ *
+ * This method is expected to perform as much progress on the
+ * protocol it implements as is possible without blocking. It
+ * should return 0 if it wishes to be called again, a negative
+ * return status code on error, or a positive value if
+ * handshaking is complete. In the case of a positive return,
+ * net80211_crypto_install() must have been called.
+ *
+ * If handshaking may require further action (e.g. an AP that
+ * might decide to rekey), handlers must be installed by this
+ * function that will act without further calls to @a step.
+ */
+ int ( * step ) ( struct net80211_device *dev );
+
+ /** Change cryptographic key based on setting
+ *
+ * @v dev 802.11 device
+ * @ret rc Return status code
+ *
+ * This method is called whenever the @c netX/key setting
+ * @e may have been changed. It is expected to determine
+ * whether it did in fact change, and if so, to install the
+ * new key using net80211_crypto_install(). If it is not
+ * possible to do this immediately, this method should return
+ * an error; in that case the 802.11 stack will reassociate,
+ * following the usual init/start/step sequence.
+ *
+ * This method is only relevant when it is possible to
+ * associate successfully with an incorrect key. When it is
+ * not, a failed association will be retried until the user
+ * changes the key setting, and a successful association will
+ * not be dropped due to such a change. When association with
+ * an incorrect key is impossible, this function should return
+ * 0 after performing no action.
+ */
+ int ( * change_key ) ( struct net80211_device *dev );
+
+ /** Stop security handshaking handlers
+ *
+ * @v dev 802.11 device
+ *
+ * This method is called just before freeing a security
+ * handshaker; it could, for example, delete a process that @a
+ * start had created to manage the security of the connection.
+ * If not needed it may be set to NULL.
+ */
+ void ( * stop ) ( struct net80211_device *dev );
+
+ /** Amount of private data requested
+ *
+ * Before @c init is called for the first time, this structure's
+ * @c priv pointer will point to this many bytes of allocated
+ * data, where the allocation will be performed separately for
+ * each net80211_device.
+ */
+ int priv_len;
+
+ /** Whether @a start has been called
+ *
+ * Reset to 0 after @a stop is called.
+ */
+ int started;
+
+ /** Pointer to private data
+ *
+ * In initializing this structure statically for a linker
+ * table, set this to NULL.
+ */
+ void *priv;
+};
+
+#define NET80211_HANDSHAKERS __table ( struct net80211_handshaker, \
+ "net80211_handshakers" )
+#define __net80211_handshaker __table_entry ( NET80211_HANDSHAKERS, 01 )
+
+
+/** Interface to an 802.11 cryptosystem
+ *
+ * Cryptosystems define a net80211_crypto structure statically, using
+ * a iPXE linker table to make it available to the 802.11 layer. When
+ * the cryptosystem needs to be used, the 802.11 code will allocate a
+ * copy of the static definition plus whatever space the algorithm has
+ * requested for private state, and point net80211_device::crypto or
+ * net80211_device::gcrypto at it.
+ */
+struct net80211_crypto
+{
+ /** The cryptographic algorithm implemented */
+ enum net80211_crypto_alg algorithm;
+
+ /** Initialize cryptosystem using a given key
+ *
+ * @v crypto 802.11 cryptosystem
+ * @v key Pointer to key bytes
+ * @v keylen Number of key bytes
+ * @v rsc Initial receive sequence counter, if applicable
+ * @ret rc Return status code
+ *
+ * This method is passed the communication key provided by the
+ * security handshake handler, which will already be in the
+ * low-level form required. It may not store a pointer to the
+ * key after returning; it must copy it to its private storage.
+ */
+ int ( * init ) ( struct net80211_crypto *crypto, const void *key,
+ int keylen, const void *rsc );
+
+ /** Encrypt a frame using the cryptosystem
+ *
+ * @v crypto 802.11 cryptosystem
+ * @v iob I/O buffer
+ * @ret eiob Newly allocated I/O buffer with encrypted packet
+ *
+ * This method is called to encrypt a single frame. It is
+ * guaranteed that initialize() will have completed
+ * successfully before this method is called.
+ *
+ * The frame passed already has an 802.11 header prepended,
+ * but the PROTECTED bit in the frame control field will not
+ * be set; this method is responsible for setting it. The
+ * returned I/O buffer should contain a complete copy of @a
+ * iob, including the 802.11 header, but with the PROTECTED
+ * bit set, the data encrypted, and whatever encryption
+ * headers/trailers are necessary added.
+ *
+ * This method should never free the passed I/O buffer.
+ *
+ * Return NULL if the packet could not be encrypted, due to
+ * memory limitations or otherwise.
+ */
+ struct io_buffer * ( * encrypt ) ( struct net80211_crypto *crypto,
+ struct io_buffer *iob );
+
+ /** Decrypt a frame using the cryptosystem
+ *
+ * @v crypto 802.11 cryptosystem
+ * @v eiob Encrypted I/O buffer
+ * @ret iob Newly allocated I/O buffer with decrypted packet
+ *
+ * This method is called to decrypt a single frame. It is
+ * guaranteed that initialize() will have completed
+ * successfully before this method is called.
+ *
+ * Decryption follows the reverse of the pattern used for
+ * encryption: this method must copy the 802.11 header into
+ * the returned packet, decrypt the data stream, remove any
+ * encryption header or trailer, and clear the PROTECTED bit
+ * in the frame control header.
+ *
+ * This method should never free the passed I/O buffer.
+ *
+ * Return NULL if memory was not available for decryption, if
+ * a consistency or integrity check on the decrypted frame
+ * failed, or if the decrypted frame should not be processed
+ * by the network stack for any other reason.
+ */
+ struct io_buffer * ( * decrypt ) ( struct net80211_crypto *crypto,
+ struct io_buffer *iob );
+
+ /** Length of private data requested to be allocated */
+ int priv_len;
+
+ /** Private data for the algorithm to store key and state info */
+ void *priv;
+};
+
+#define NET80211_CRYPTOS __table ( struct net80211_crypto, "net80211_cryptos" )
+#define __net80211_crypto __table_entry ( NET80211_CRYPTOS, 01 )
+
+
+struct net80211_probe_ctx;
+struct net80211_assoc_ctx;
+
+
+/** Structure encapsulating the complete state of an 802.11 device
+ *
+ * An 802.11 device is always wrapped by a network device, and this
+ * network device is always pointed to by the @a netdev field. In
+ * general, operations should never be performed by 802.11 code using
+ * netdev functions directly. It is usually the case that the 802.11
+ * layer might need to do some processing or bookkeeping on top of
+ * what the netdevice code will do.
+ */
+struct net80211_device
+{
+ /** The net_device that wraps us. */
+ struct net_device *netdev;
+
+ /** List of 802.11 devices. */
+ struct list_head list;
+
+ /** 802.11 device operations */
+ struct net80211_device_operations *op;
+
+ /** Driver private data */
+ void *priv;
+
+ /** Information about the hardware, provided to net80211_register() */
+ struct net80211_hw_info *hw;
+
+ /* ---------- Channel and rate fields ---------- */
+
+ /** A list of all possible channels we might use */
+ struct net80211_channel channels[NET80211_MAX_CHANNELS];
+
+ /** The number of channels in the channels array */
+ u8 nr_channels;
+
+ /** The channel currently in use, as an index into the channels array */
+ u8 channel;
+
+ /** A list of all possible TX rates we might use
+ *
+ * Rates are in units of 100 kbps.
+ */
+ u16 rates[NET80211_MAX_RATES];
+
+ /** The number of transmission rates in the rates array */
+ u8 nr_rates;
+
+ /** The rate currently in use, as an index into the rates array */
+ u8 rate;
+
+ /** The rate to use for RTS/CTS transmissions
+ *
+ * This is always the fastest basic rate that is not faster
+ * than the data rate in use. Also an index into the rates array.
+ */
+ u8 rtscts_rate;
+
+ /** Bitmask of basic rates
+ *
+ * If bit N is set in this value, with the LSB considered to
+ * be bit 0, then rate N in the rates array is a "basic" rate.
+ *
+ * We don't decide which rates are "basic"; our AP does, and
+ * we respect its wishes. We need to be able to identify basic
+ * rates in order to calculate the duration of a CTS packet
+ * used for 802.11 g/b interoperability.
+ */
+ u32 basic_rates;
+
+ /* ---------- Association fields ---------- */
+
+ /** The asynchronous association process.
+ *
+ * When an 802.11 netdev is opened, or when the user changes
+ * the SSID setting on an open 802.11 device, an
+ * autoassociation task is started by net80211_autoassocate()
+ * to associate with the new best network. The association is
+ * asynchronous, but no packets can be transmitted until it is
+ * complete. If it is successful, the wrapping net_device is
+ * set as "link up". If it fails, @c assoc_rc will be set with
+ * an error indication.
+ */
+ struct process proc_assoc;
+
+ /** Network with which we are associating
+ *
+ * This will be NULL when we are not actively in the process
+ * of associating with a network we have already successfully
+ * probed for.
+ */
+ struct net80211_wlan *associating;
+
+ /** Context for the association process
+ *
+ * This is a probe_ctx if the @c PROBED flag is not set in @c
+ * state, and an assoc_ctx otherwise.
+ */
+ union {
+ struct net80211_probe_ctx *probe;
+ struct net80211_assoc_ctx *assoc;
+ } ctx;
+
+ /** Security handshaker being used */
+ struct net80211_handshaker *handshaker;
+
+ /** State of our association to the network
+ *
+ * Since the association process happens asynchronously, it's
+ * necessary to have some channel of communication so the
+ * driver can say "I got an association reply and we're OK" or
+ * similar. This variable provides that link. It is a bitmask
+ * of any of NET80211_PROBED, NET80211_AUTHENTICATED,
+ * NET80211_ASSOCIATED, NET80211_CRYPTO_SYNCED to indicate how
+ * far along in associating we are; NET80211_WORKING if the
+ * association task is running; and NET80211_WAITING if a
+ * packet has been sent that we're waiting for a reply to. We
+ * can only be crypto-synced if we're associated, we can
+ * only be associated if we're authenticated, we can only be
+ * authenticated if we've probed.
+ *
+ * If an association process fails (that is, we receive a
+ * packet with an error indication), the error code is copied
+ * into bits 6-0 of this variable and bit 7 is set to specify
+ * what type of error code it is. An AP can provide either a
+ * "status code" (0-51 are defined) explaining why it refused
+ * an association immediately, or a "reason code" (0-45 are
+ * defined) explaining why it canceled an association after it
+ * had originally OK'ed it. Status and reason codes serve
+ * similar functions, but they use separate error message
+ * tables. A iPXE-formatted return status code (negative) is
+ * placed in @c assoc_rc.
+ *
+ * If the failure to associate is indicated by a status code,
+ * the NET80211_IS_REASON bit will be clear; if it is
+ * indicated by a reason code, the bit will be set. If we were
+ * successful, both zero status and zero reason mean success,
+ * so there is no ambiguity.
+ *
+ * To prevent association when opening the device, user code
+ * can set the NET80211_NO_ASSOC bit. The final bit in this
+ * variable, NET80211_AUTO_SSID, is used to remember whether
+ * we picked our SSID through automated probing as opposed to
+ * user specification; the distinction becomes relevant in the
+ * settings applicator.
+ */
+ u16 state;
+
+ /** Return status code associated with @c state */
+ int assoc_rc;
+
+ /** RSN or WPA information element to include with association
+ *
+ * If set to @c NULL, none will be included. It is expected
+ * that this will be set by the @a init function of a security
+ * handshaker if it is needed.
+ */
+ union ieee80211_ie *rsn_ie;
+
+ /* ---------- Parameters of currently associated network ---------- */
+
+ /** 802.11 cryptosystem for our current network
+ *
+ * For an open network, this will be set to NULL.
+ */
+ struct net80211_crypto *crypto;
+
+ /** 802.11 cryptosystem for multicast and broadcast frames
+ *
+ * If this is NULL, the cryptosystem used for receiving
+ * unicast frames will also be used for receiving multicast
+ * and broadcast frames. Transmitted multicast and broadcast
+ * frames are always sent unicast to the AP, who multicasts
+ * them on our behalf; thus they always use the unicast
+ * cryptosystem.
+ */
+ struct net80211_crypto *gcrypto;
+
+ /** MAC address of the access point most recently associated */
+ u8 bssid[ETH_ALEN];
+
+ /** SSID of the access point we are or will be associated with
+ *
+ * Although the SSID field in 802.11 packets is generally not
+ * NUL-terminated, here and in net80211_wlan we add a NUL for
+ * convenience.
+ */
+ char essid[IEEE80211_MAX_SSID_LEN+1];
+
+ /** Association ID given to us by the AP */
+ u16 aid;
+
+ /** TSFT value for last beacon received, microseconds */
+ u64 last_beacon_timestamp;
+
+ /** Time between AP sending beacons, microseconds */
+ u32 tx_beacon_interval;
+
+ /** Smoothed average time between beacons, microseconds */
+ u32 rx_beacon_interval;
+
+ /* ---------- Physical layer information ---------- */
+
+ /** Physical layer options
+ *
+ * These control the use of CTS protection, short preambles,
+ * and short-slot operation.
+ */
+ int phy_flags;
+
+ /** Signal strength of last received packet */
+ int last_signal;
+
+ /** Rate control state */
+ struct rc80211_ctx *rctl;
+
+ /* ---------- Packet handling state ---------- */
+
+ /** Fragment reassembly state */
+ struct net80211_frag_cache frags[NET80211_NR_CONCURRENT_FRAGS];
+
+ /** The sequence number of the last packet we sent */
+ u16 last_tx_seqnr;
+
+ /** Packet duplication elimination state
+ *
+ * We are only required to handle immediate duplicates for
+ * each direct sender, and since we can only have one direct
+ * sender (the AP), we need only keep the sequence control
+ * field from the most recent packet we've received. Thus,
+ * this field stores the last sequence control field we've
+ * received for a packet from the AP.
+ */
+ u16 last_rx_seq;
+
+ /** RX management packet queue
+ *
+ * Sometimes we want to keep probe, beacon, and action packets
+ * that we receive, such as when we're scanning for networks.
+ * Ordinarily we drop them because they are sent at a large
+ * volume (ten beacons per second per AP, broadcast) and we
+ * have no need of them except when we're scanning.
+ *
+ * When keep_mgmt is TRUE, received probe, beacon, and action
+ * management packets will be stored in this queue.
+ */
+ struct list_head mgmt_queue;
+
+ /** RX management packet info queue
+ *
+ * We need to keep track of the signal strength for management
+ * packets we're keeping, because that provides the only way
+ * to distinguish between multiple APs for the same network.
+ * Since we can't extend io_buffer to store signal, this field
+ * heads a linked list of "RX packet info" structures that
+ * contain that signal strength field. Its entries always
+ * parallel the entries in mgmt_queue, because the two queues
+ * are always added to or removed from in parallel.
+ */
+ struct list_head mgmt_info_queue;
+
+ /** Whether to store management packets
+ *
+ * Received beacon, probe, and action packets will be added to
+ * mgmt_queue (and their signal strengths added to
+ * mgmt_info_queue) only when this variable is TRUE. It should
+ * be set by net80211_keep_mgmt() (which returns the old
+ * value) only when calling code is prepared to poll the
+ * management queue frequently, because packets will otherwise
+ * pile up and exhaust memory.
+ */
+ int keep_mgmt;
+};
+
+/** Structure representing a probed network.
+ *
+ * This is returned from the net80211_probe_finish functions and
+ * passed to the low-level association functions. At least essid,
+ * bssid, channel, beacon, and security must be filled in if you want
+ * to build this structure manually.
+ */
+struct net80211_wlan
+{
+ /** The human-readable ESSID (network name)
+ *
+ * Although the 802.11 SSID field is generally not
+ * NUL-terminated, the iPXE code adds an extra NUL (and
+ * expects one in this structure) for convenience.
+ */
+ char essid[IEEE80211_MAX_SSID_LEN+1];
+
+ /** MAC address of the strongest-signal access point for this ESSID */
+ u8 bssid[ETH_ALEN];
+
+ /** Signal strength of beacon frame from that access point */
+ int signal;
+
+ /** The channel on which that access point communicates
+ *
+ * This is a raw channel number (net80211_channel::channel_nr),
+ * so that it will not be affected by reconfiguration of the
+ * device channels array.
+ */
+ int channel;
+
+ /** The complete beacon or probe-response frame received */
+ struct io_buffer *beacon;
+
+ /** Security handshaking method used on the network */
+ enum net80211_security_proto handshaking;
+
+ /** Cryptographic algorithm used on the network */
+ enum net80211_crypto_alg crypto;
+
+ /** Link to allow chaining multiple structures into a list to
+ be returned from net80211_probe_finish_all(). */
+ struct list_head list;
+};
+
+
+/** 802.11 encryption key setting */
+extern struct setting net80211_key_setting __setting ( SETTING_NETDEV_EXTRA );
+
+
+/**
+ * @defgroup net80211_probe 802.11 network location API
+ * @{
+ */
+int net80211_prepare_probe ( struct net80211_device *dev, int band,
+ int active );
+struct net80211_probe_ctx * net80211_probe_start ( struct net80211_device *dev,
+ const char *essid,
+ int active );
+int net80211_probe_step ( struct net80211_probe_ctx *ctx );
+struct net80211_wlan *
+net80211_probe_finish_best ( struct net80211_probe_ctx *ctx );
+struct list_head *net80211_probe_finish_all ( struct net80211_probe_ctx *ctx );
+
+void net80211_free_wlan ( struct net80211_wlan *wlan );
+void net80211_free_wlanlist ( struct list_head *list );
+/** @} */
+
+
+/**
+ * @defgroup net80211_mgmt 802.11 network management API
+ * @{
+ */
+struct net80211_device * net80211_get ( struct net_device *netdev );
+void net80211_autoassociate ( struct net80211_device *dev );
+
+int net80211_change_channel ( struct net80211_device *dev, int channel );
+void net80211_set_rate_idx ( struct net80211_device *dev, int rate );
+
+int net80211_keep_mgmt ( struct net80211_device *dev, int enable );
+struct io_buffer * net80211_mgmt_dequeue ( struct net80211_device *dev,
+ int *signal );
+int net80211_tx_mgmt ( struct net80211_device *dev, u16 fc,
+ u8 bssid[ETH_ALEN], struct io_buffer *iob );
+/** @} */
+
+
+/**
+ * @defgroup net80211_assoc 802.11 network association API
+ * @{
+ */
+int net80211_prepare_assoc ( struct net80211_device *dev,
+ struct net80211_wlan *wlan );
+int net80211_send_auth ( struct net80211_device *dev,
+ struct net80211_wlan *wlan, int method );
+int net80211_send_assoc ( struct net80211_device *dev,
+ struct net80211_wlan *wlan );
+void net80211_deauthenticate ( struct net80211_device *dev, int rc );
+/** @} */
+
+
+/**
+ * @defgroup net80211_driver 802.11 driver interface API
+ * @{
+ */
+struct net80211_device *net80211_alloc ( size_t priv_size );
+int net80211_register ( struct net80211_device *dev,
+ struct net80211_device_operations *ops,
+ struct net80211_hw_info *hw );
+u16 net80211_duration ( struct net80211_device *dev, int bytes, u16 rate );
+void net80211_rx ( struct net80211_device *dev, struct io_buffer *iob,
+ int signal, u16 rate );
+void net80211_rx_err ( struct net80211_device *dev,
+ struct io_buffer *iob, int rc );
+void net80211_tx_complete ( struct net80211_device *dev,
+ struct io_buffer *iob, int retries, int rc );
+void net80211_unregister ( struct net80211_device *dev );
+void net80211_free ( struct net80211_device *dev );
+/** @} */
+
+/**
+ * Calculate duration field for a CTS control frame
+ *
+ * @v dev 802.11 device
+ * @v size Size of the packet being cleared to send
+ *
+ * A CTS control frame's duration field captures the frame being
+ * protected and its 10-byte ACK.
+ */
+static inline u16 net80211_cts_duration ( struct net80211_device *dev,
+ int size )
+{
+ return ( net80211_duration ( dev, 10,
+ dev->rates[dev->rtscts_rate] ) +
+ net80211_duration ( dev, size, dev->rates[dev->rate] ) );
+}
+
+/** 802.11 device setting tag magic */
+#define NET80211_SETTING_TAG_MAGIC 0x8211
+
+/**
+ * Construct 802.11 setting tag
+ *
+ * @v id Unique identifier
+ * @ret tag Setting tag
+ */
+#define NET80211_SETTING_TAG( id ) \
+ NETDEV_SETTING_TAG ( ( NET80211_SETTING_TAG_MAGIC << 8 ) | (id) )
+
+/** SSID setting tag */
+#define NET80211_SETTING_TAG_SSID NET80211_SETTING_TAG ( 0x01 )
+
+/** Active scanning setting tag */
+#define NET80211_SETTING_TAG_ACTIVE_SCAN NET80211_SETTING_TAG ( 0x02 )
+
+/** Wireless key setting tag */
+#define NET80211_SETTING_TAG_KEY NET80211_SETTING_TAG ( 0x03 )
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/net80211_err.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/net80211_err.h
new file mode 100644
index 00000000..2175b143
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/net80211_err.h
@@ -0,0 +1,633 @@
+#ifndef _IPXE_NET80211_ERR_H
+#define _IPXE_NET80211_ERR_H
+
+#include <errno.h>
+#include <ipxe/ieee80211.h>
+
+/*
+ * The iPXE 802.11 MAC layer.
+ *
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * The iPXE 802.11 MAC layer errors.
+ */
+
+/* Disambiguate the EINVAL's a bit */
+#define EINVAL_PKT_TOO_SHORT __einfo_error ( EINFO_EINVAL_PKT_TOO_SHORT )
+#define EINFO_EINVAL_PKT_TOO_SHORT __einfo_uniqify \
+ ( EINFO_EINVAL, 0x01, "Packet too short" )
+#define EINVAL_PKT_VERSION __einfo_error ( EINFO_EINVAL_PKT_VERSION )
+#define EINFO_EINVAL_PKT_VERSION __einfo_uniqify \
+ ( EINFO_EINVAL, 0x02, "Packet 802.11 version not supported" )
+#define EINVAL_PKT_NOT_DATA __einfo_error ( EINFO_EINVAL_PKT_NOT_DATA )
+#define EINFO_EINVAL_PKT_NOT_DATA __einfo_uniqify \
+ ( EINFO_EINVAL, 0x03, "Packet not a data packet" )
+#define EINVAL_PKT_NOT_FROMDS __einfo_error ( EINFO_EINVAL_PKT_NOT_FROMDS )
+#define EINFO_EINVAL_PKT_NOT_FROMDS __einfo_uniqify \
+ ( EINFO_EINVAL, 0x04, "Packet not from an Access Point" )
+#define EINVAL_PKT_LLC_HEADER __einfo_error ( EINFO_EINVAL_PKT_LLC_HEADER )
+#define EINFO_EINVAL_PKT_LLC_HEADER __einfo_uniqify \
+ ( EINFO_EINVAL, 0x05, "Packet has invalid LLC header" )
+#define EINVAL_CRYPTO_REQUEST __einfo_error ( EINFO_EINVAL_CRYPTO_REQUEST )
+#define EINFO_EINVAL_CRYPTO_REQUEST __einfo_uniqify \
+ ( EINFO_EINVAL, 0x06, "Packet decryption error" )
+#define EINVAL_ACTIVE_SCAN __einfo_error ( EINFO_EINVAL_ACTIVE_SCAN )
+#define EINFO_EINVAL_ACTIVE_SCAN __einfo_uniqify \
+ ( EINFO_EINVAL, 0x07, "Invalid active scan requested" )
+
+/*
+ * 802.11 error codes: The AP can give us a status code explaining why
+ * authentication failed, or a reason code explaining why we were
+ * deauthenticated/disassociated. These codes range from 0-63 (the
+ * field is 16 bits wide, but only up to 45 or so are defined yet; we
+ * allow up to 63 for extensibility). This is encoded into an error
+ * code as such:
+ *
+ * status & 0x1f goes here --vv--
+ * Status code 0-31: ECONNREFUSED | EUNIQ_(status & 0x1f) (0e1a6038)
+ * Status code 32-63: EHOSTUNREACH | EUNIQ_(status & 0x1f) (171a6011)
+ * Reason code 0-31: ECONNRESET | EUNIQ_(reason & 0x1f) (0f1a6039)
+ * Reason code 32-63: ENETRESET | EUNIQ_(reason & 0x1f) (271a6001)
+ *
+ * The POSIX error codes more or less convey the appropriate message
+ * (status codes occur when we can't associate at all, reason codes
+ * when we lose association unexpectedly) and let us extract the
+ * complete 802.11 error code from the rc value.
+ *
+ * The error messages follow the 802.11 standard as much as is
+ * feasible, but most have been abbreviated to fit the 50-character
+ * limit imposed by strerror().
+ */
+
+/* 802.11 status codes (IEEE Std 802.11-2007, Table 7-23) */
+
+#define ECONNREFUSED_FAILURE __einfo_error \
+ ( EINFO_ECONNREFUSED_FAILURE )
+#define EINFO_ECONNREFUSED_FAILURE __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_FAILURE & 0x1f ), \
+ "Unspecified failure" )
+
+#define ECONNREFUSED_CAPAB_UNSUPP __einfo_error \
+ ( EINFO_ECONNREFUSED_CAPAB_UNSUPP )
+#define EINFO_ECONNREFUSED_CAPAB_UNSUPP __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_CAPAB_UNSUPP & 0x1f ), \
+ "Cannot support all requested capabilities" )
+
+#define ECONNREFUSED_REASSOC_INVALID __einfo_error \
+ ( EINFO_ECONNREFUSED_REASSOC_INVALID )
+#define EINFO_ECONNREFUSED_REASSOC_INVALID __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_REASSOC_INVALID & 0x1f ), \
+ "Reassociation denied due to lack of association" )
+
+#define ECONNREFUSED_ASSOC_DENIED __einfo_error \
+ ( EINFO_ECONNREFUSED_ASSOC_DENIED )
+#define EINFO_ECONNREFUSED_ASSOC_DENIED __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_ASSOC_DENIED & 0x1f ), \
+ "Association denied for another reason" )
+
+#define ECONNREFUSED_AUTH_ALGO_UNSUPP __einfo_error \
+ ( EINFO_ECONNREFUSED_AUTH_ALGO_UNSUPP )
+#define EINFO_ECONNREFUSED_AUTH_ALGO_UNSUPP __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_AUTH_ALGO_UNSUPP & 0x1f ), \
+ "Authentication algorithm unsupported" )
+
+#define ECONNREFUSED_AUTH_SEQ_INVALID __einfo_error \
+ ( EINFO_ECONNREFUSED_AUTH_SEQ_INVALID )
+#define EINFO_ECONNREFUSED_AUTH_SEQ_INVALID __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_AUTH_SEQ_INVALID & 0x1f ), \
+ "Authentication sequence number unexpected" )
+
+#define ECONNREFUSED_AUTH_CHALL_INVALID __einfo_error \
+ ( EINFO_ECONNREFUSED_AUTH_CHALL_INVALID )
+#define EINFO_ECONNREFUSED_AUTH_CHALL_INVALID __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_AUTH_CHALL_INVALID & 0x1f ), \
+ "Authentication rejected due to challenge failure" )
+
+#define ECONNREFUSED_AUTH_TIMEOUT __einfo_error \
+ ( EINFO_ECONNREFUSED_AUTH_TIMEOUT )
+#define EINFO_ECONNREFUSED_AUTH_TIMEOUT __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_AUTH_TIMEOUT & 0x1f ), \
+ "Authentication rejected due to timeout" )
+
+#define ECONNREFUSED_ASSOC_NO_ROOM __einfo_error \
+ ( EINFO_ECONNREFUSED_ASSOC_NO_ROOM )
+#define EINFO_ECONNREFUSED_ASSOC_NO_ROOM __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_ASSOC_NO_ROOM & 0x1f ), \
+ "Association denied because AP is out of resources" )
+
+#define ECONNREFUSED_ASSOC_NEED_RATE __einfo_error \
+ ( EINFO_ECONNREFUSED_ASSOC_NEED_RATE )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_RATE __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_ASSOC_NEED_RATE & 0x1f ), \
+ "Association denied; basic rate support required" )
+
+#define ECONNREFUSED_ASSOC_NEED_SHORT_PMBL __einfo_error \
+ ( EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_PMBL )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_PMBL __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_ASSOC_NEED_SHORT_PMBL & 0x1f ), \
+ "Association denied; short preamble support req'd" )
+
+#define ECONNREFUSED_ASSOC_NEED_PBCC __einfo_error \
+ ( EINFO_ECONNREFUSED_ASSOC_NEED_PBCC )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_PBCC __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_ASSOC_NEED_PBCC & 0x1f ), \
+ "Association denied; PBCC modulation support req'd" )
+
+#define ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY __einfo_error \
+ ( EINFO_ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_ASSOC_NEED_CHAN_AGILITY & 0x1f ), \
+ "Association denied; Channel Agility support req'd" )
+
+#define ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT __einfo_error \
+ ( EINFO_ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_ASSOC_NEED_SPECTRUM_MGMT & 0x1f ), \
+ "Association denied; Spectrum Management required" )
+
+#define ECONNREFUSED_ASSOC_BAD_POWER __einfo_error \
+ ( EINFO_ECONNREFUSED_ASSOC_BAD_POWER )
+#define EINFO_ECONNREFUSED_ASSOC_BAD_POWER __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_ASSOC_BAD_POWER & 0x1f ), \
+ "Association denied; Power Capability unacceptable" )
+
+#define ECONNREFUSED_ASSOC_BAD_CHANNELS __einfo_error \
+ ( EINFO_ECONNREFUSED_ASSOC_BAD_CHANNELS )
+#define EINFO_ECONNREFUSED_ASSOC_BAD_CHANNELS __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_ASSOC_BAD_CHANNELS & 0x1f ), \
+ "Association denied; Supported Channels unacceptable" )
+
+#define ECONNREFUSED_ASSOC_NEED_SHORT_SLOT __einfo_error \
+ ( EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_SLOT )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_SLOT __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_ASSOC_NEED_SHORT_SLOT & 0x1f ), \
+ "Association denied; Short Slot Tume support req'd" )
+
+#define ECONNREFUSED_ASSOC_NEED_DSSS_OFDM __einfo_error \
+ ( EINFO_ECONNREFUSED_ASSOC_NEED_DSSS_OFDM )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_DSSS_OFDM __einfo_uniqify \
+ ( EINFO_ECONNREFUSED, \
+ ( IEEE80211_STATUS_ASSOC_NEED_DSSS_OFDM & 0x1f ), \
+ "Association denied; DSSS-OFDM support required" )
+
+#define EHOSTUNREACH_QOS_FAILURE __einfo_error \
+ ( EINFO_EHOSTUNREACH_QOS_FAILURE )
+#define EINFO_EHOSTUNREACH_QOS_FAILURE __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_QOS_FAILURE & 0x1f ), \
+ "Unspecified, QoS-related failure" )
+
+#define EHOSTUNREACH_QOS_NO_ROOM __einfo_error \
+ ( EINFO_EHOSTUNREACH_QOS_NO_ROOM )
+#define EINFO_EHOSTUNREACH_QOS_NO_ROOM __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_QOS_NO_ROOM & 0x1f ), \
+ "Association denied; QoS AP out of QoS resources" )
+
+#define EHOSTUNREACH_LINK_IS_HORRIBLE __einfo_error \
+ ( EINFO_EHOSTUNREACH_LINK_IS_HORRIBLE )
+#define EINFO_EHOSTUNREACH_LINK_IS_HORRIBLE __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_LINK_IS_HORRIBLE & 0x1f ), \
+ "Association denied due to excessively poor link" )
+
+#define EHOSTUNREACH_ASSOC_NEED_QOS __einfo_error \
+ ( EINFO_EHOSTUNREACH_ASSOC_NEED_QOS )
+#define EINFO_EHOSTUNREACH_ASSOC_NEED_QOS __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_ASSOC_NEED_QOS & 0x1f ), \
+ "Association denied; QoS support required" )
+
+#define EHOSTUNREACH_REQUEST_DECLINED __einfo_error \
+ ( EINFO_EHOSTUNREACH_REQUEST_DECLINED )
+#define EINFO_EHOSTUNREACH_REQUEST_DECLINED __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_REQUEST_DECLINED & 0x1f ), \
+ "The request has been declined" )
+
+#define EHOSTUNREACH_REQUEST_INVALID __einfo_error \
+ ( EINFO_EHOSTUNREACH_REQUEST_INVALID )
+#define EINFO_EHOSTUNREACH_REQUEST_INVALID __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_REQUEST_INVALID & 0x1f ), \
+ "Request unsuccessful due to invalid parameters" )
+
+#define EHOSTUNREACH_TS_NOT_CREATED_AGAIN __einfo_error \
+ ( EINFO_EHOSTUNREACH_TS_NOT_CREATED_AGAIN )
+#define EINFO_EHOSTUNREACH_TS_NOT_CREATED_AGAIN __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_TS_NOT_CREATED_AGAIN & 0x1f ), \
+ "TS not created due to bad specification" )
+
+#define EHOSTUNREACH_INVALID_IE __einfo_error \
+ ( EINFO_EHOSTUNREACH_INVALID_IE )
+#define EINFO_EHOSTUNREACH_INVALID_IE __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_INVALID_IE & 0x1f ), \
+ "Invalid information element" )
+
+#define EHOSTUNREACH_GROUP_CIPHER_INVALID __einfo_error \
+ ( EINFO_EHOSTUNREACH_GROUP_CIPHER_INVALID )
+#define EINFO_EHOSTUNREACH_GROUP_CIPHER_INVALID __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_GROUP_CIPHER_INVALID & 0x1f ), \
+ "Invalid group cipher" )
+
+#define EHOSTUNREACH_PAIR_CIPHER_INVALID __einfo_error \
+ ( EINFO_EHOSTUNREACH_PAIR_CIPHER_INVALID )
+#define EINFO_EHOSTUNREACH_PAIR_CIPHER_INVALID __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_PAIR_CIPHER_INVALID & 0x1f ), \
+ "Invalid pairwise cipher" )
+
+#define EHOSTUNREACH_AKMP_INVALID __einfo_error \
+ ( EINFO_EHOSTUNREACH_AKMP_INVALID )
+#define EINFO_EHOSTUNREACH_AKMP_INVALID __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_AKMP_INVALID & 0x1f ), \
+ "Invalid AKMP" )
+
+#define EHOSTUNREACH_RSN_VERSION_UNSUPP __einfo_error \
+ ( EINFO_EHOSTUNREACH_RSN_VERSION_UNSUPP )
+#define EINFO_EHOSTUNREACH_RSN_VERSION_UNSUPP __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_RSN_VERSION_UNSUPP & 0x1f ), \
+ "Unsupported RSN information element version" )
+
+#define EHOSTUNREACH_RSN_CAPAB_INVALID __einfo_error \
+ ( EINFO_EHOSTUNREACH_RSN_CAPAB_INVALID )
+#define EINFO_EHOSTUNREACH_RSN_CAPAB_INVALID __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_RSN_CAPAB_INVALID & 0x1f ), \
+ "Invalid RSN information element capabilities" )
+
+#define EHOSTUNREACH_CIPHER_REJECTED __einfo_error \
+ ( EINFO_EHOSTUNREACH_CIPHER_REJECTED )
+#define EINFO_EHOSTUNREACH_CIPHER_REJECTED __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_CIPHER_REJECTED & 0x1f ), \
+ "Cipher suite rejected because of security policy" )
+
+#define EHOSTUNREACH_TS_NOT_CREATED_WAIT __einfo_error \
+ ( EINFO_EHOSTUNREACH_TS_NOT_CREATED_WAIT )
+#define EINFO_EHOSTUNREACH_TS_NOT_CREATED_WAIT __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_TS_NOT_CREATED_WAIT & 0x1f ), \
+ "TS not created due to insufficient delay" )
+
+#define EHOSTUNREACH_DIRECT_LINK_FORBIDDEN __einfo_error \
+ ( EINFO_EHOSTUNREACH_DIRECT_LINK_FORBIDDEN )
+#define EINFO_EHOSTUNREACH_DIRECT_LINK_FORBIDDEN __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_DIRECT_LINK_FORBIDDEN & 0x1f ), \
+ "Direct link is not allowed in the BSS by policy" )
+
+#define EHOSTUNREACH_DEST_NOT_PRESENT __einfo_error \
+ ( EINFO_EHOSTUNREACH_DEST_NOT_PRESENT )
+#define EINFO_EHOSTUNREACH_DEST_NOT_PRESENT __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_DEST_NOT_PRESENT & 0x1f ), \
+ "The Destination STA is not present within the BSS" )
+
+#define EHOSTUNREACH_DEST_NOT_QOS __einfo_error \
+ ( EINFO_EHOSTUNREACH_DEST_NOT_QOS )
+#define EINFO_EHOSTUNREACH_DEST_NOT_QOS __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_DEST_NOT_QOS & 0x1f ), \
+ "The Destination STA is not a QoS STA" )
+
+#define EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH __einfo_error \
+ ( EINFO_EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH )
+#define EINFO_EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH __einfo_uniqify \
+ ( EINFO_EHOSTUNREACH, \
+ ( IEEE80211_STATUS_ASSOC_LISTEN_TOO_HIGH & 0x1f ), \
+ "Association denied; Listen Interval is too large" )
+
+/* 802.11 reason codes (IEEE Std 802.11-2007, Table 7-22) */
+
+#define ECONNRESET_UNSPECIFIED __einfo_error \
+ ( EINFO_ECONNRESET_UNSPECIFIED )
+#define EINFO_ECONNRESET_UNSPECIFIED __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_UNSPECIFIED & 0x1f ), \
+ "Unspecified reason" )
+
+#define ECONNRESET_AUTH_NO_LONGER_VALID __einfo_error \
+ ( EINFO_ECONNRESET_AUTH_NO_LONGER_VALID )
+#define EINFO_ECONNRESET_AUTH_NO_LONGER_VALID __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_AUTH_NO_LONGER_VALID & 0x1f ), \
+ "Previous authentication no longer valid" )
+
+#define ECONNRESET_LEAVING __einfo_error \
+ ( EINFO_ECONNRESET_LEAVING )
+#define EINFO_ECONNRESET_LEAVING __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_LEAVING & 0x1f ), \
+ "Deauthenticated due to leaving network" )
+
+#define ECONNRESET_INACTIVITY __einfo_error \
+ ( EINFO_ECONNRESET_INACTIVITY )
+#define EINFO_ECONNRESET_INACTIVITY __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_INACTIVITY & 0x1f ), \
+ "Disassociated due to inactivity" )
+
+#define ECONNRESET_OUT_OF_RESOURCES __einfo_error \
+ ( EINFO_ECONNRESET_OUT_OF_RESOURCES )
+#define EINFO_ECONNRESET_OUT_OF_RESOURCES __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_OUT_OF_RESOURCES & 0x1f ), \
+ "Disassociated because AP is out of resources" )
+
+#define ECONNRESET_NEED_AUTH __einfo_error \
+ ( EINFO_ECONNRESET_NEED_AUTH )
+#define EINFO_ECONNRESET_NEED_AUTH __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_NEED_AUTH & 0x1f ), \
+ "Class 2 frame received from nonauthenticated STA" )
+
+#define ECONNRESET_NEED_ASSOC __einfo_error \
+ ( EINFO_ECONNRESET_NEED_ASSOC )
+#define EINFO_ECONNRESET_NEED_ASSOC __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_NEED_ASSOC & 0x1f ), \
+ "Class 3 frame received from nonassociated STA" )
+
+#define ECONNRESET_LEAVING_TO_ROAM __einfo_error \
+ ( EINFO_ECONNRESET_LEAVING_TO_ROAM )
+#define EINFO_ECONNRESET_LEAVING_TO_ROAM __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_LEAVING_TO_ROAM & 0x1f ), \
+ "Disassociated due to roaming" )
+
+#define ECONNRESET_REASSOC_INVALID __einfo_error \
+ ( EINFO_ECONNRESET_REASSOC_INVALID )
+#define EINFO_ECONNRESET_REASSOC_INVALID __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_REASSOC_INVALID & 0x1f ), \
+ "STA requesting (re)association not authenticated" )
+
+#define ECONNRESET_BAD_POWER __einfo_error \
+ ( EINFO_ECONNRESET_BAD_POWER )
+#define EINFO_ECONNRESET_BAD_POWER __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_BAD_POWER & 0x1f ), \
+ "Disassociated; Power Capability unacceptable" )
+
+#define ECONNRESET_BAD_CHANNELS __einfo_error \
+ ( EINFO_ECONNRESET_BAD_CHANNELS )
+#define EINFO_ECONNRESET_BAD_CHANNELS __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_BAD_CHANNELS & 0x1f ), \
+ "Disassociated; Supported Channels unacceptable" )
+
+#define ECONNRESET_INVALID_IE __einfo_error \
+ ( EINFO_ECONNRESET_INVALID_IE )
+#define EINFO_ECONNRESET_INVALID_IE __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_INVALID_IE & 0x1f ), \
+ "Invalid information element" )
+
+#define ECONNRESET_MIC_FAILURE __einfo_error \
+ ( EINFO_ECONNRESET_MIC_FAILURE )
+#define EINFO_ECONNRESET_MIC_FAILURE __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_MIC_FAILURE & 0x1f ), \
+ "Message integrity code (MIC) failure" )
+
+#define ECONNRESET_4WAY_TIMEOUT __einfo_error \
+ ( EINFO_ECONNRESET_4WAY_TIMEOUT )
+#define EINFO_ECONNRESET_4WAY_TIMEOUT __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_4WAY_TIMEOUT & 0x1f ), \
+ "4-Way Handshake timeout" )
+
+#define ECONNRESET_GROUPKEY_TIMEOUT __einfo_error \
+ ( EINFO_ECONNRESET_GROUPKEY_TIMEOUT )
+#define EINFO_ECONNRESET_GROUPKEY_TIMEOUT __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_GROUPKEY_TIMEOUT & 0x1f ), \
+ "Group Key Handshake timeout" )
+
+#define ECONNRESET_4WAY_INVALID __einfo_error \
+ ( EINFO_ECONNRESET_4WAY_INVALID )
+#define EINFO_ECONNRESET_4WAY_INVALID __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_4WAY_INVALID & 0x1f ), \
+ "4-Way Handshake information element changed unduly" )
+
+#define ECONNRESET_GROUP_CIPHER_INVALID __einfo_error \
+ ( EINFO_ECONNRESET_GROUP_CIPHER_INVALID )
+#define EINFO_ECONNRESET_GROUP_CIPHER_INVALID __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_GROUP_CIPHER_INVALID & 0x1f ), \
+ "Invalid group cipher" )
+
+#define ECONNRESET_PAIR_CIPHER_INVALID __einfo_error \
+ ( EINFO_ECONNRESET_PAIR_CIPHER_INVALID )
+#define EINFO_ECONNRESET_PAIR_CIPHER_INVALID __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_PAIR_CIPHER_INVALID & 0x1f ), \
+ "Invalid pairwise cipher" )
+
+#define ECONNRESET_AKMP_INVALID __einfo_error \
+ ( EINFO_ECONNRESET_AKMP_INVALID )
+#define EINFO_ECONNRESET_AKMP_INVALID __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_AKMP_INVALID & 0x1f ), \
+ "Invalid AKMP" )
+
+#define ECONNRESET_RSN_VERSION_INVALID __einfo_error \
+ ( EINFO_ECONNRESET_RSN_VERSION_INVALID )
+#define EINFO_ECONNRESET_RSN_VERSION_INVALID __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_RSN_VERSION_INVALID & 0x1f ), \
+ "Unsupported RSN information element version" )
+
+#define ECONNRESET_RSN_CAPAB_INVALID __einfo_error \
+ ( EINFO_ECONNRESET_RSN_CAPAB_INVALID )
+#define EINFO_ECONNRESET_RSN_CAPAB_INVALID __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_RSN_CAPAB_INVALID & 0x1f ), \
+ "Invalid RSN information element capabilities" )
+
+#define ECONNRESET_8021X_FAILURE __einfo_error \
+ ( EINFO_ECONNRESET_8021X_FAILURE )
+#define EINFO_ECONNRESET_8021X_FAILURE __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_8021X_FAILURE & 0x1f ), \
+ "IEEE 802.1X authentication failed" )
+
+#define ECONNRESET_CIPHER_REJECTED __einfo_error \
+ ( EINFO_ECONNRESET_CIPHER_REJECTED )
+#define EINFO_ECONNRESET_CIPHER_REJECTED __einfo_uniqify \
+ ( EINFO_ECONNRESET, \
+ ( IEEE80211_REASON_CIPHER_REJECTED & 0x1f ), \
+ "Cipher suite rejected because of security policy" )
+
+#define ENETRESET_QOS_UNSPECIFIED __einfo_error \
+ ( EINFO_ENETRESET_QOS_UNSPECIFIED )
+#define EINFO_ENETRESET_QOS_UNSPECIFIED __einfo_uniqify \
+ ( EINFO_ENETRESET, \
+ ( IEEE80211_REASON_QOS_UNSPECIFIED & 0x1f ), \
+ "Disassociated for unspecified, QoS-related reason" )
+
+#define ENETRESET_QOS_OUT_OF_RESOURCES __einfo_error \
+ ( EINFO_ENETRESET_QOS_OUT_OF_RESOURCES )
+#define EINFO_ENETRESET_QOS_OUT_OF_RESOURCES __einfo_uniqify \
+ ( EINFO_ENETRESET, \
+ ( IEEE80211_REASON_QOS_OUT_OF_RESOURCES & 0x1f ), \
+ "Disassociated; QoS AP is out of QoS resources" )
+
+#define ENETRESET_LINK_IS_HORRIBLE __einfo_error \
+ ( EINFO_ENETRESET_LINK_IS_HORRIBLE )
+#define EINFO_ENETRESET_LINK_IS_HORRIBLE __einfo_uniqify \
+ ( EINFO_ENETRESET, \
+ ( IEEE80211_REASON_LINK_IS_HORRIBLE & 0x1f ), \
+ "Disassociated due to excessively poor link" )
+
+#define ENETRESET_INVALID_TXOP __einfo_error \
+ ( EINFO_ENETRESET_INVALID_TXOP )
+#define EINFO_ENETRESET_INVALID_TXOP __einfo_uniqify \
+ ( EINFO_ENETRESET, \
+ ( IEEE80211_REASON_INVALID_TXOP & 0x1f ), \
+ "Disassociated due to TXOP limit violation" )
+
+#define ENETRESET_REQUESTED_LEAVING __einfo_error \
+ ( EINFO_ENETRESET_REQUESTED_LEAVING )
+#define EINFO_ENETRESET_REQUESTED_LEAVING __einfo_uniqify \
+ ( EINFO_ENETRESET, \
+ ( IEEE80211_REASON_REQUESTED_LEAVING & 0x1f ), \
+ "Requested; STA is leaving the BSS (or resetting)" )
+
+#define ENETRESET_REQUESTED_NO_USE __einfo_error \
+ ( EINFO_ENETRESET_REQUESTED_NO_USE )
+#define EINFO_ENETRESET_REQUESTED_NO_USE __einfo_uniqify \
+ ( EINFO_ENETRESET, \
+ ( IEEE80211_REASON_REQUESTED_NO_USE & 0x1f ), \
+ "Requested; does not want to use the mechanism" )
+
+#define ENETRESET_REQUESTED_NEED_SETUP __einfo_error \
+ ( EINFO_ENETRESET_REQUESTED_NEED_SETUP )
+#define EINFO_ENETRESET_REQUESTED_NEED_SETUP __einfo_uniqify \
+ ( EINFO_ENETRESET, \
+ ( IEEE80211_REASON_REQUESTED_NEED_SETUP & 0x1f ), \
+ "Requested; setup is required" )
+
+#define ENETRESET_REQUESTED_TIMEOUT __einfo_error \
+ ( EINFO_ENETRESET_REQUESTED_TIMEOUT )
+#define EINFO_ENETRESET_REQUESTED_TIMEOUT __einfo_uniqify \
+ ( EINFO_ENETRESET, \
+ ( IEEE80211_REASON_REQUESTED_TIMEOUT & 0x1f ), \
+ "Requested from peer STA due to timeout" )
+
+#define ENETRESET_CIPHER_UNSUPPORTED __einfo_error \
+ ( EINFO_ENETRESET_CIPHER_UNSUPPORTED )
+#define EINFO_ENETRESET_CIPHER_UNSUPPORTED __einfo_uniqify \
+ ( EINFO_ENETRESET, \
+ ( IEEE80211_REASON_CIPHER_UNSUPPORTED & 0x1f ), \
+ "Peer STA does not support requested cipher suite" )
+
+/** Make return status code from 802.11 status code */
+#define E80211_STATUS( stat ) \
+ EUNIQ ( ( ( stat & 0x20 ) ? EHOSTUNREACH : ECONNREFUSED ), \
+ ( stat &0x1f ), \
+ ECONNREFUSED_FAILURE, \
+ ECONNREFUSED_CAPAB_UNSUPP, \
+ ECONNREFUSED_REASSOC_INVALID, \
+ ECONNREFUSED_ASSOC_DENIED, \
+ ECONNREFUSED_AUTH_ALGO_UNSUPP, \
+ ECONNREFUSED_AUTH_SEQ_INVALID, \
+ ECONNREFUSED_AUTH_CHALL_INVALID, \
+ ECONNREFUSED_AUTH_TIMEOUT, \
+ ECONNREFUSED_ASSOC_NO_ROOM, \
+ ECONNREFUSED_ASSOC_NEED_RATE, \
+ ECONNREFUSED_ASSOC_NEED_SHORT_PMBL, \
+ ECONNREFUSED_ASSOC_NEED_PBCC, \
+ ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY, \
+ ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT, \
+ ECONNREFUSED_ASSOC_BAD_POWER, \
+ ECONNREFUSED_ASSOC_BAD_CHANNELS, \
+ ECONNREFUSED_ASSOC_NEED_SHORT_SLOT, \
+ ECONNREFUSED_ASSOC_NEED_DSSS_OFDM, \
+ EHOSTUNREACH_QOS_FAILURE, \
+ EHOSTUNREACH_QOS_NO_ROOM, \
+ EHOSTUNREACH_LINK_IS_HORRIBLE, \
+ EHOSTUNREACH_ASSOC_NEED_QOS, \
+ EHOSTUNREACH_REQUEST_DECLINED, \
+ EHOSTUNREACH_REQUEST_INVALID, \
+ EHOSTUNREACH_TS_NOT_CREATED_AGAIN, \
+ EHOSTUNREACH_INVALID_IE, \
+ EHOSTUNREACH_GROUP_CIPHER_INVALID, \
+ EHOSTUNREACH_PAIR_CIPHER_INVALID, \
+ EHOSTUNREACH_AKMP_INVALID, \
+ EHOSTUNREACH_RSN_VERSION_UNSUPP, \
+ EHOSTUNREACH_RSN_CAPAB_INVALID, \
+ EHOSTUNREACH_CIPHER_REJECTED, \
+ EHOSTUNREACH_TS_NOT_CREATED_WAIT, \
+ EHOSTUNREACH_DIRECT_LINK_FORBIDDEN, \
+ EHOSTUNREACH_DEST_NOT_PRESENT, \
+ EHOSTUNREACH_DEST_NOT_QOS, \
+ EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH )
+
+/** Make return status code from 802.11 reason code */
+#define E80211_REASON( reas ) \
+ EUNIQ ( ( ( reas & 0x20 ) ? ENETRESET : ECONNRESET ), \
+ ( reas & 0x1f ), \
+ ECONNRESET_UNSPECIFIED, \
+ ECONNRESET_AUTH_NO_LONGER_VALID, \
+ ECONNRESET_LEAVING, \
+ ECONNRESET_INACTIVITY, \
+ ECONNRESET_OUT_OF_RESOURCES, \
+ ECONNRESET_NEED_AUTH, \
+ ECONNRESET_NEED_ASSOC, \
+ ECONNRESET_LEAVING_TO_ROAM, \
+ ECONNRESET_REASSOC_INVALID, \
+ ECONNRESET_BAD_POWER, \
+ ECONNRESET_BAD_CHANNELS, \
+ ECONNRESET_INVALID_IE, \
+ ECONNRESET_MIC_FAILURE, \
+ ECONNRESET_4WAY_TIMEOUT, \
+ ECONNRESET_GROUPKEY_TIMEOUT, \
+ ECONNRESET_4WAY_INVALID, \
+ ECONNRESET_GROUP_CIPHER_INVALID, \
+ ECONNRESET_PAIR_CIPHER_INVALID, \
+ ECONNRESET_AKMP_INVALID, \
+ ECONNRESET_RSN_VERSION_INVALID, \
+ ECONNRESET_RSN_CAPAB_INVALID, \
+ ECONNRESET_8021X_FAILURE, \
+ ECONNRESET_CIPHER_REJECTED, \
+ ENETRESET_QOS_UNSPECIFIED, \
+ ENETRESET_QOS_OUT_OF_RESOURCES, \
+ ENETRESET_LINK_IS_HORRIBLE, \
+ ENETRESET_INVALID_TXOP, \
+ ENETRESET_REQUESTED_LEAVING, \
+ ENETRESET_REQUESTED_NO_USE, \
+ ENETRESET_REQUESTED_NEED_SETUP, \
+ ENETRESET_REQUESTED_TIMEOUT, \
+ ENETRESET_CIPHER_UNSUPPORTED )
+
+#endif /* _IPXE_NET80211_ERR_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/netdevice.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/netdevice.h
new file mode 100644
index 00000000..3633a165
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/netdevice.h
@@ -0,0 +1,681 @@
+#ifndef _IPXE_NETDEVICE_H
+#define _IPXE_NETDEVICE_H
+
+/** @file
+ *
+ * Network device management
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/list.h>
+#include <ipxe/tables.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/settings.h>
+
+struct io_buffer;
+struct net_device;
+struct net_protocol;
+struct ll_protocol;
+struct device;
+
+/** Maximum length of a hardware address
+ *
+ * The longest currently-supported link-layer address is for IPoIB.
+ */
+#define MAX_HW_ADDR_LEN 8
+
+/** Maximum length of a link-layer address
+ *
+ * The longest currently-supported link-layer address is for IPoIB.
+ */
+#define MAX_LL_ADDR_LEN 20
+
+/** Maximum length of a link-layer header
+ *
+ * The longest currently-supported link-layer header is for 802.11: a
+ * 24-byte frame header plus an 8-byte 802.3 LLC/SNAP header, plus a
+ * possible 4-byte VLAN header. (The IPoIB link-layer pseudo-header
+ * doesn't actually include link-layer addresses; see ipoib.c for
+ * details.)
+ */
+#define MAX_LL_HEADER_LEN 36
+
+/** Maximum length of a network-layer address */
+#define MAX_NET_ADDR_LEN 4
+
+/** Maximum length of a network-layer header
+ *
+ * The longest currently-supported network-layer header is for IPv6 at
+ * 40 bytes.
+ */
+#define MAX_NET_HEADER_LEN 40
+
+/** Maximum combined length of a link-layer and network-layer header */
+#define MAX_LL_NET_HEADER_LEN ( MAX_LL_HEADER_LEN + MAX_NET_HEADER_LEN )
+
+/**
+ * A network-layer protocol
+ *
+ */
+struct net_protocol {
+ /** Protocol name */
+ const char *name;
+ /**
+ * Process received packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer source address
+ * @v flags Packet flags
+ * @ret rc Return status code
+ *
+ * This method takes ownership of the I/O buffer.
+ */
+ int ( * rx ) ( struct io_buffer *iobuf, struct net_device *netdev,
+ const void *ll_dest, const void *ll_source,
+ unsigned int flags );
+ /**
+ * Transcribe network-layer address
+ *
+ * @v net_addr Network-layer address
+ * @ret string Human-readable transcription of address
+ *
+ * This method should convert the network-layer address into a
+ * human-readable format (e.g. dotted quad notation for IPv4).
+ *
+ * The buffer used to hold the transcription is statically
+ * allocated.
+ */
+ const char * ( *ntoa ) ( const void * net_addr );
+ /** Network-layer protocol
+ *
+ * This is an ETH_P_XXX constant, in network-byte order
+ */
+ uint16_t net_proto;
+ /** Network-layer address length */
+ uint8_t net_addr_len;
+};
+
+/** Packet is a multicast (including broadcast) packet */
+#define LL_MULTICAST 0x0001
+
+/** Packet is a broadcast packet */
+#define LL_BROADCAST 0x0002
+
+/**
+ * A link-layer protocol
+ *
+ */
+struct ll_protocol {
+ /** Protocol name */
+ const char *name;
+ /**
+ * Add link-layer header
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Source link-layer address
+ * @v net_proto Network-layer protocol, in network-byte order
+ * @ret rc Return status code
+ */
+ int ( * push ) ( struct net_device *netdev, struct io_buffer *iobuf,
+ const void *ll_dest, const void *ll_source,
+ uint16_t net_proto );
+ /**
+ * Remove link-layer header
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret ll_dest Link-layer destination address
+ * @ret ll_source Source link-layer address
+ * @ret net_proto Network-layer protocol, in network-byte order
+ * @ret flags Packet flags
+ * @ret rc Return status code
+ */
+ int ( * pull ) ( struct net_device *netdev, struct io_buffer *iobuf,
+ const void **ll_dest, const void **ll_source,
+ uint16_t *net_proto, unsigned int *flags );
+ /**
+ * Initialise link-layer address
+ *
+ * @v hw_addr Hardware address
+ * @v ll_addr Link-layer address to fill in
+ */
+ void ( * init_addr ) ( const void *hw_addr, void *ll_addr );
+ /**
+ * Transcribe link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @ret string Human-readable transcription of address
+ *
+ * This method should convert the link-layer address into a
+ * human-readable format.
+ *
+ * The buffer used to hold the transcription is statically
+ * allocated.
+ */
+ const char * ( * ntoa ) ( const void *ll_addr );
+ /**
+ * Hash multicast address
+ *
+ * @v af Address family
+ * @v net_addr Network-layer address
+ * @v ll_addr Link-layer address to fill in
+ * @ret rc Return status code
+ */
+ int ( * mc_hash ) ( unsigned int af, const void *net_addr,
+ void *ll_addr );
+ /**
+ * Generate Ethernet-compatible compressed link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @v eth_addr Ethernet-compatible address to fill in
+ */
+ int ( * eth_addr ) ( const void *ll_addr, void *eth_addr );
+ /** Link-layer protocol
+ *
+ * This is an ARPHRD_XXX constant, in network byte order.
+ */
+ uint16_t ll_proto;
+ /** Hardware address length */
+ uint8_t hw_addr_len;
+ /** Link-layer address length */
+ uint8_t ll_addr_len;
+ /** Link-layer header length */
+ uint8_t ll_header_len;
+};
+
+/** Network device operations */
+struct net_device_operations {
+ /** Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ *
+ * This method should allocate RX I/O buffers and enable
+ * the hardware to start transmitting and receiving packets.
+ */
+ int ( * open ) ( struct net_device *netdev );
+ /** Close network device
+ *
+ * @v netdev Network device
+ *
+ * This method should stop the flow of packets, and free up
+ * any packets that are currently in the device's TX queue.
+ */
+ void ( * close ) ( struct net_device *netdev );
+ /** Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * This method should cause the hardware to initiate
+ * transmission of the I/O buffer.
+ *
+ * If this method returns success, the I/O buffer remains
+ * owned by the net device's TX queue, and the net device must
+ * eventually call netdev_tx_complete() to free the buffer.
+ * If this method returns failure, the I/O buffer is
+ * immediately released; the failure is interpreted as
+ * "failure to enqueue buffer".
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ int ( * transmit ) ( struct net_device *netdev,
+ struct io_buffer *iobuf );
+ /** Poll for completed and received packets
+ *
+ * @v netdev Network device
+ *
+ * This method should cause the hardware to check for
+ * completed transmissions and received packets. Any received
+ * packets should be delivered via netdev_rx().
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ void ( * poll ) ( struct net_device *netdev );
+ /** Enable or disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ *
+ * This method may be NULL to indicate that interrupts are not
+ * supported.
+ */
+ void ( * irq ) ( struct net_device *netdev, int enable );
+};
+
+/** Network device error */
+struct net_device_error {
+ /** Error status code */
+ int rc;
+ /** Error count */
+ unsigned int count;
+};
+
+/** Maximum number of unique errors that we will keep track of */
+#define NETDEV_MAX_UNIQUE_ERRORS 4
+
+/** Network device statistics */
+struct net_device_stats {
+ /** Count of successful completions */
+ unsigned int good;
+ /** Count of error completions */
+ unsigned int bad;
+ /** Error breakdowns */
+ struct net_device_error errors[NETDEV_MAX_UNIQUE_ERRORS];
+};
+
+/**
+ * A network device
+ *
+ * This structure represents a piece of networking hardware. It has
+ * properties such as a link-layer address and methods for
+ * transmitting and receiving raw packets.
+ *
+ * Note that this structure must represent a generic network device,
+ * not just an Ethernet device.
+ */
+struct net_device {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** List of network devices */
+ struct list_head list;
+ /** List of open network devices */
+ struct list_head open_list;
+ /** Name of this network device */
+ char name[12];
+ /** Underlying hardware device */
+ struct device *dev;
+
+ /** Network device operations */
+ struct net_device_operations *op;
+
+ /** Link-layer protocol */
+ struct ll_protocol *ll_protocol;
+ /** Hardware address
+ *
+ * This is an address which is an intrinsic property of the
+ * hardware, e.g. an address held in EEPROM.
+ *
+ * Note that the hardware address may not be the same length
+ * as the link-layer address.
+ */
+ uint8_t hw_addr[MAX_HW_ADDR_LEN];
+ /** Link-layer address
+ *
+ * This is the current link-layer address assigned to the
+ * device. It can be changed at runtime.
+ */
+ uint8_t ll_addr[MAX_LL_ADDR_LEN];
+ /** Link-layer broadcast address */
+ const uint8_t *ll_broadcast;
+
+ /** Current device state
+ *
+ * This is the bitwise-OR of zero or more NETDEV_XXX constants.
+ */
+ unsigned int state;
+ /** Link status code
+ *
+ * Zero indicates that the link is up; any other value
+ * indicates the error preventing link-up.
+ */
+ int link_rc;
+ /** Maximum packet length
+ *
+ * This length includes any link-layer headers.
+ */
+ size_t max_pkt_len;
+ /** TX packet queue */
+ struct list_head tx_queue;
+ /** RX packet queue */
+ struct list_head rx_queue;
+ /** TX statistics */
+ struct net_device_stats tx_stats;
+ /** RX statistics */
+ struct net_device_stats rx_stats;
+
+ /** Configuration settings applicable to this device */
+ struct generic_settings settings;
+
+ /** Driver private data */
+ void *priv;
+};
+
+/** Network device is open */
+#define NETDEV_OPEN 0x0001
+
+/** Network device interrupts are enabled */
+#define NETDEV_IRQ_ENABLED 0x0002
+
+/** Network device receive queue processing is frozen */
+#define NETDEV_RX_FROZEN 0x0004
+
+/** Link-layer protocol table */
+#define LL_PROTOCOLS __table ( struct ll_protocol, "ll_protocols" )
+
+/** Declare a link-layer protocol */
+#define __ll_protocol __table_entry ( LL_PROTOCOLS, 01 )
+
+/** Network-layer protocol table */
+#define NET_PROTOCOLS __table ( struct net_protocol, "net_protocols" )
+
+/** Declare a network-layer protocol */
+#define __net_protocol __table_entry ( NET_PROTOCOLS, 01 )
+
+/** A network upper-layer driver */
+struct net_driver {
+ /** Name */
+ const char *name;
+ /** Probe device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct net_device *netdev );
+ /** Notify of device or link state change
+ *
+ * @v netdev Network device
+ */
+ void ( * notify ) ( struct net_device *netdev );
+ /** Remove device
+ *
+ * @v netdev Network device
+ */
+ void ( * remove ) ( struct net_device *netdev );
+};
+
+/** Network driver table */
+#define NET_DRIVERS __table ( struct net_driver, "net_drivers" )
+
+/** Declare a network driver */
+#define __net_driver __table_entry ( NET_DRIVERS, 01 )
+
+/** Network device setting tag magic
+ *
+ * All DHCP option settings are deemed to be valid as network device
+ * settings. There are also some extra non-DHCP settings (such as
+ * "mac"), which are marked as being valid network device settings by
+ * using a magic tag value.
+ */
+#define NETDEV_SETTING_TAG_MAGIC 0xeb
+
+/**
+ * Construct network device setting tag
+ *
+ * @v id Unique identifier
+ * @ret tag Setting tag
+ */
+#define NETDEV_SETTING_TAG( id ) ( ( NETDEV_SETTING_TAG_MAGIC << 24 ) | (id) )
+
+/**
+ * Check if tag is a network device setting tag
+ *
+ * @v tag Setting tag
+ * @ret is_ours Tag is a network device setting tag
+ */
+#define IS_NETDEV_SETTING_TAG( tag ) \
+ ( ( (tag) >> 24 ) == NETDEV_SETTING_TAG_MAGIC )
+
+/** MAC address setting tag */
+#define NETDEV_SETTING_TAG_MAC NETDEV_SETTING_TAG ( 0x01 )
+
+/** Bus ID setting tag */
+#define NETDEV_SETTING_TAG_BUS_ID NETDEV_SETTING_TAG ( 0x02 )
+
+extern struct list_head net_devices;
+extern struct net_device_operations null_netdev_operations;
+extern struct settings_operations netdev_settings_operations;
+
+/**
+ * Initialise a network device
+ *
+ * @v netdev Network device
+ * @v op Network device operations
+ */
+static inline void netdev_init ( struct net_device *netdev,
+ struct net_device_operations *op ) {
+ netdev->op = op;
+}
+
+/**
+ * Stop using a network device
+ *
+ * @v netdev Network device
+ *
+ * Drivers should call this method immediately before the final call
+ * to netdev_put().
+ */
+static inline void netdev_nullify ( struct net_device *netdev ) {
+ netdev->op = &null_netdev_operations;
+}
+
+/**
+ * Get printable network device link-layer address
+ *
+ * @v netdev Network device
+ * @ret name Link-layer address
+ */
+static inline const char * netdev_addr ( struct net_device *netdev ) {
+ return netdev->ll_protocol->ntoa ( netdev->ll_addr );
+}
+
+/** Iterate over all network devices */
+#define for_each_netdev( netdev ) \
+ list_for_each_entry ( (netdev), &net_devices, list )
+
+/** There exist some network devices
+ *
+ * @ret existence Existence of network devices
+ */
+static inline int have_netdevs ( void ) {
+ return ( ! list_empty ( &net_devices ) );
+}
+
+/**
+ * Get reference to network device
+ *
+ * @v netdev Network device
+ * @ret netdev Network device
+ */
+static inline __attribute__ (( always_inline )) struct net_device *
+netdev_get ( struct net_device *netdev ) {
+ ref_get ( &netdev->refcnt );
+ return netdev;
+}
+
+/**
+ * Drop reference to network device
+ *
+ * @v netdev Network device
+ */
+static inline __attribute__ (( always_inline )) void
+netdev_put ( struct net_device *netdev ) {
+ ref_put ( &netdev->refcnt );
+}
+
+/**
+ * Get driver private area for this network device
+ *
+ * @v netdev Network device
+ * @ret priv Driver private area for this network device
+ */
+static inline __attribute__ (( always_inline )) void *
+netdev_priv ( struct net_device *netdev ) {
+ return netdev->priv;
+}
+
+/**
+ * Get per-netdevice configuration settings block
+ *
+ * @v netdev Network device
+ * @ret settings Settings block
+ */
+static inline __attribute__ (( always_inline )) struct settings *
+netdev_settings ( struct net_device *netdev ) {
+ return &netdev->settings.settings;
+}
+
+/**
+ * Initialise a per-netdevice configuration settings block
+ *
+ * @v generics Generic settings block
+ * @v refcnt Containing object reference counter, or NULL
+ * @v name Settings block name
+ */
+static inline __attribute__ (( always_inline )) void
+netdev_settings_init ( struct net_device *netdev ) {
+ generic_settings_init ( &netdev->settings, &netdev->refcnt );
+ netdev->settings.settings.op = &netdev_settings_operations;
+}
+
+/**
+ * Check link state of network device
+ *
+ * @v netdev Network device
+ * @ret link_up Link is up
+ */
+static inline __attribute__ (( always_inline )) int
+netdev_link_ok ( struct net_device *netdev ) {
+ return ( netdev->link_rc == 0 );
+}
+
+/**
+ * Check whether or not network device is open
+ *
+ * @v netdev Network device
+ * @ret is_open Network device is open
+ */
+static inline __attribute__ (( always_inline )) int
+netdev_is_open ( struct net_device *netdev ) {
+ return ( netdev->state & NETDEV_OPEN );
+}
+
+/**
+ * Check whether or not network device supports interrupts
+ *
+ * @v netdev Network device
+ * @ret irq_supported Network device supports interrupts
+ */
+static inline __attribute__ (( always_inline )) int
+netdev_irq_supported ( struct net_device *netdev ) {
+ return ( netdev->op->irq != NULL );
+}
+
+/**
+ * Check whether or not network device interrupts are currently enabled
+ *
+ * @v netdev Network device
+ * @ret irq_enabled Network device interrupts are enabled
+ */
+static inline __attribute__ (( always_inline )) int
+netdev_irq_enabled ( struct net_device *netdev ) {
+ return ( netdev->state & NETDEV_IRQ_ENABLED );
+}
+
+/**
+ * Check whether or not network device receive queue processing is frozen
+ *
+ * @v netdev Network device
+ * @ret rx_frozen Network device receive queue processing is frozen
+ */
+static inline __attribute__ (( always_inline )) int
+netdev_rx_frozen ( struct net_device *netdev ) {
+ return ( netdev->state & NETDEV_RX_FROZEN );
+}
+
+extern void netdev_link_err ( struct net_device *netdev, int rc );
+extern void netdev_link_down ( struct net_device *netdev );
+extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
+extern void netdev_tx_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc );
+extern void netdev_tx_complete_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc );
+extern void netdev_tx_complete_next_err ( struct net_device *netdev, int rc );
+extern void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf );
+extern void netdev_rx_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc );
+extern void netdev_poll ( struct net_device *netdev );
+extern struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev );
+extern struct net_device * alloc_netdev ( size_t priv_size );
+extern int register_netdev ( struct net_device *netdev );
+extern int netdev_open ( struct net_device *netdev );
+extern void netdev_close ( struct net_device *netdev );
+extern void unregister_netdev ( struct net_device *netdev );
+extern void netdev_irq ( struct net_device *netdev, int enable );
+extern struct net_device * find_netdev ( const char *name );
+extern struct net_device * find_netdev_by_location ( unsigned int bus_type,
+ unsigned int location );
+extern struct net_device * last_opened_netdev ( void );
+extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
+ struct net_protocol *net_protocol, const void *ll_dest,
+ const void *ll_source );
+extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
+ uint16_t net_proto, const void *ll_dest,
+ const void *ll_source, unsigned int flags );
+extern void net_poll ( void );
+
+/**
+ * Complete network transmission
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ *
+ * The packet must currently be in the network device's TX queue.
+ */
+static inline void netdev_tx_complete ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ netdev_tx_complete_err ( netdev, iobuf, 0 );
+}
+
+/**
+ * Complete network transmission
+ *
+ * @v netdev Network device
+ *
+ * Completes the oldest outstanding packet in the TX queue.
+ */
+static inline void netdev_tx_complete_next ( struct net_device *netdev ) {
+ netdev_tx_complete_next_err ( netdev, 0 );
+}
+
+/**
+ * Mark network device as having link up
+ *
+ * @v netdev Network device
+ */
+static inline __attribute__ (( always_inline )) void
+netdev_link_up ( struct net_device *netdev ) {
+ netdev_link_err ( netdev, 0 );
+}
+
+/**
+ * Freeze network device receive queue processing
+ *
+ * @v netdev Network device
+ */
+static inline __attribute__ (( always_inline )) void
+netdev_rx_freeze ( struct net_device *netdev ) {
+ netdev->state |= NETDEV_RX_FROZEN;
+}
+
+/**
+ * Unfreeze network device receive queue processing
+ *
+ * @v netdev Network device
+ */
+static inline __attribute__ (( always_inline )) void
+netdev_rx_unfreeze ( struct net_device *netdev ) {
+ netdev->state &= ~NETDEV_RX_FROZEN;
+}
+
+#endif /* _IPXE_NETDEVICE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/null_entropy.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/null_entropy.h
new file mode 100644
index 00000000..646d1a17
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/null_entropy.h
@@ -0,0 +1,52 @@
+#ifndef _IPXE_NULL_ENTROPY_H
+#define _IPXE_NULL_ENTROPY_H
+
+/** @file
+ *
+ * Nonexistent entropy source
+ *
+ * This source provides no entropy and must NOT be used in a
+ * security-sensitive environment.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+#ifdef ENTROPY_NULL
+#define ENTROPY_PREFIX_null
+#else
+#define ENTROPY_PREFIX_null __null_
+#endif
+
+static inline __always_inline int
+ENTROPY_INLINE ( null, entropy_enable ) ( void ) {
+ /* Do nothing */
+ return 0;
+}
+
+static inline __always_inline void
+ENTROPY_INLINE ( null, entropy_disable ) ( void ) {
+ /* Do nothing */
+}
+
+static inline __always_inline double
+ENTROPY_INLINE ( null, min_entropy_per_sample ) ( void ) {
+ /* Actual amount of min-entropy is zero. To avoid
+ * division-by-zero errors and to allow compilation of
+ * entropy-consuming code, pretend to have 1 bit of entropy in
+ * each sample.
+ */
+ return 1.0;
+}
+
+static inline __always_inline int
+ENTROPY_INLINE ( null, get_noise ) ( noise_sample_t *noise ) {
+
+ /* All sample values are constant */
+ *noise = 0x01;
+
+ return 0;
+}
+
+#endif /* _IPXE_NULL_ENTROPY_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/null_nap.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/null_nap.h
new file mode 100644
index 00000000..0c0704bc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/null_nap.h
@@ -0,0 +1,23 @@
+#ifndef _IPXE_NULL_NAP_H
+#define _IPXE_NULL_NAP_H
+
+/** @file
+ *
+ * Null CPU sleeping
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef NAP_NULL
+#define NAP_PREFIX_null
+#else
+#define NAP_PREFIX_null __null_
+#endif
+
+static inline __always_inline void
+NAP_INLINE ( null, cpu_nap ) ( void ) {
+ /* Do nothing */
+}
+
+#endif /* _IPXE_NULL_NAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/null_sanboot.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/null_sanboot.h
new file mode 100644
index 00000000..2b3a2c74
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/null_sanboot.h
@@ -0,0 +1,23 @@
+#ifndef _IPXE_NULL_SANBOOT_H
+#define _IPXE_NULL_SANBOOT_H
+
+/** @file
+ *
+ * Standard do-nothing sanboot interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef SANBOOT_NULL
+#define SANBOOT_PREFIX_null
+#else
+#define SANBOOT_PREFIX_null __null_
+#endif
+
+static inline __always_inline unsigned int
+SANBOOT_INLINE ( null, san_default_drive ) ( void ) {
+ return 0;
+}
+
+#endif /* _IPXE_NULL_SANBOOT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/null_time.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/null_time.h
new file mode 100644
index 00000000..2b72cdf5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/null_time.h
@@ -0,0 +1,23 @@
+#ifndef _IPXE_NULL_TIME_H
+#define _IPXE_NULL_TIME_H
+
+/** @file
+ *
+ * Nonexistent time source
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef TIME_NULL
+#define TIME_PREFIX_null
+#else
+#define TIME_PREFIX_null __null_
+#endif
+
+static inline __always_inline time_t
+TIME_INLINE ( null, time_now ) ( void ) {
+ return 0;
+}
+
+#endif /* _IPXE_NULL_TIME_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/nvo.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/nvo.h
new file mode 100644
index 00000000..995afd74
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/nvo.h
@@ -0,0 +1,52 @@
+#ifndef _IPXE_NVO_H
+#define _IPXE_NVO_H
+
+/** @file
+ *
+ * Non-volatile stored options
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/dhcpopts.h>
+#include <ipxe/settings.h>
+
+struct nvs_device;
+struct refcnt;
+
+/**
+ * A block of non-volatile stored options
+ */
+struct nvo_block {
+ /** Settings block */
+ struct settings settings;
+ /** Underlying non-volatile storage device */
+ struct nvs_device *nvs;
+ /** Address within NVS device */
+ unsigned int address;
+ /** Length of options data */
+ size_t len;
+ /** Option-containing data */
+ void *data;
+ /**
+ * Resize non-volatile stored option block
+ *
+ * @v nvo Non-volatile options block
+ * @v len New size
+ * @ret rc Return status code
+ */
+ int ( * resize ) ( struct nvo_block *nvo, size_t len );
+ /** DHCP options block */
+ struct dhcp_options dhcpopts;
+};
+
+extern void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
+ size_t address, size_t len,
+ int ( * resize ) ( struct nvo_block *nvo, size_t len ),
+ struct refcnt *refcnt );
+extern int register_nvo ( struct nvo_block *nvo, struct settings *parent );
+extern void unregister_nvo ( struct nvo_block *nvo );
+
+#endif /* _IPXE_NVO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/nvs.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/nvs.h
new file mode 100644
index 00000000..4733123c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/nvs.h
@@ -0,0 +1,68 @@
+#ifndef _IPXE_NVS_H
+#define _IPXE_NVS_H
+
+/** @file
+ *
+ * Non-volatile storage
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/** A non-volatile storage device */
+struct nvs_device {
+ /** Word length
+ *
+ * This is expressed as the base-2 logarithm of the word
+ * length in bytes. A value of 0 therefore translates as
+ * 8-bit words, and a value of 1 translates as 16-bit words.
+ */
+ unsigned int word_len_log2;
+ /** Device size (in words) */
+ unsigned int size;
+ /** Data block size (in words)
+ *
+ * This is the block size used by the device. It must be a
+ * power of two. Data reads and writes must not cross a block
+ * boundary.
+ *
+ * Many devices allow reads to cross a block boundary, and
+ * restrict only writes. For the sake of simplicity, we
+ * assume that the same restriction applies to both reads and
+ * writes.
+ */
+ unsigned int block_size;
+ /** Read data from device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ *
+ * Reads may not cross a block boundary.
+ */
+ int ( * read ) ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len );
+ /** Write data to device
+ *
+ * @v nvs NVS device
+ * @v address Address to which to write
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ *
+ * Writes may not cross a block boundary.
+ */
+ int ( * write ) ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len );
+};
+
+extern int nvs_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len );
+extern int nvs_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len );
+
+#endif /* _IPXE_NVS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/nvsvpd.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/nvsvpd.h
new file mode 100644
index 00000000..3450e5c7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/nvsvpd.h
@@ -0,0 +1,33 @@
+#ifndef _IPXE_NVSVPD_H
+#define _IPXE_NVSVPD_H
+
+/**
+ * @file
+ *
+ * Non-Volatile Storage using Vital Product Data
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/nvs.h>
+#include <ipxe/pcivpd.h>
+
+struct nvo_block;
+struct refcnt;
+
+/** An NVS VPD device */
+struct nvs_vpd_device {
+ /** NVS device */
+ struct nvs_device nvs;
+ /** PCI VPD device */
+ struct pci_vpd vpd;
+};
+
+extern int nvs_vpd_init ( struct nvs_vpd_device *nvsvpd,
+ struct pci_device *pci );
+extern void nvs_vpd_nvo_init ( struct nvs_vpd_device *nvsvpd,
+ unsigned int field, struct nvo_block *nvo,
+ struct refcnt *refcnt );
+
+#endif /* IPXE_NVSVPD_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/ocsp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ocsp.h
new file mode 100644
index 00000000..e8414923
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/ocsp.h
@@ -0,0 +1,108 @@
+#ifndef _IPXE_OCSP_H
+#define _IPXE_OCSP_H
+
+/** @file
+ *
+ * Online Certificate Status Protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdarg.h>
+#include <time.h>
+#include <ipxe/asn1.h>
+#include <ipxe/x509.h>
+#include <ipxe/refcnt.h>
+
+/** OCSP algorithm identifier */
+#define OCSP_ALGORITHM_IDENTIFIER( ... ) \
+ ASN1_OID, VA_ARG_COUNT ( __VA_ARGS__ ), __VA_ARGS__, \
+ ASN1_NULL, 0x00
+
+/* OCSP response statuses */
+#define OCSP_STATUS_SUCCESSFUL 0x00
+#define OCSP_STATUS_MALFORMED_REQUEST 0x01
+#define OCSP_STATUS_INTERNAL_ERROR 0x02
+#define OCSP_STATUS_TRY_LATER 0x03
+#define OCSP_STATUS_SIG_REQUIRED 0x05
+#define OCSP_STATUS_UNAUTHORIZED 0x06
+
+/** Margin of error allowed in OCSP response times
+ *
+ * We allow a generous margin of error: 12 hours to allow for the
+ * local time zone being non-GMT, plus 30 minutes to allow for general
+ * clock drift.
+ */
+#define OCSP_ERROR_MARGIN_TIME ( ( 12 * 60 + 30 ) * 60 )
+
+/** An OCSP request */
+struct ocsp_request {
+ /** Request builder */
+ struct asn1_builder builder;
+ /** Certificate ID */
+ struct asn1_cursor cert_id;
+};
+
+/** An OCSP response */
+struct ocsp_response {
+ /** Raw response */
+ void *data;
+ /** Raw tbsResponseData */
+ struct asn1_cursor tbs;
+ /** Time at which status is known to be correct */
+ time_t this_update;
+ /** Time at which newer status information will be available */
+ time_t next_update;
+ /** Signature algorithm */
+ struct asn1_algorithm *algorithm;
+ /** Signature value */
+ struct asn1_bit_string signature;
+ /** Signing certificate */
+ struct x509_certificate *signer;
+};
+
+/** An OCSP check */
+struct ocsp_check {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Certificate being checked */
+ struct x509_certificate *cert;
+ /** Issuing certificate */
+ struct x509_certificate *issuer;
+ /** Request */
+ struct ocsp_request request;
+ /** Response */
+ struct ocsp_response response;
+};
+
+/**
+ * Get reference to OCSP check
+ *
+ * @v ocsp OCSP check
+ * @ret ocsp OCSP check
+ */
+static inline __attribute__ (( always_inline )) struct ocsp_check *
+ocsp_get ( struct ocsp_check *ocsp ) {
+ ref_get ( &ocsp->refcnt );
+ return ocsp;
+}
+
+/**
+ * Drop reference to OCSP check
+ *
+ * @v ocsp OCSP check
+ */
+static inline __attribute__ (( always_inline )) void
+ocsp_put ( struct ocsp_check *ocsp ) {
+ ref_put ( &ocsp->refcnt );
+}
+
+extern int ocsp_check ( struct x509_certificate *cert,
+ struct x509_certificate *issuer,
+ struct ocsp_check **ocsp );
+extern int ocsp_response ( struct ocsp_check *ocsp, const void *data,
+ size_t len );
+extern int ocsp_validate ( struct ocsp_check *check, time_t time );
+
+#endif /* _IPXE_OCSP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/open.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/open.h
new file mode 100644
index 00000000..a522f0cd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/open.h
@@ -0,0 +1,106 @@
+#ifndef _IPXE_OPEN_H
+#define _IPXE_OPEN_H
+
+/** @file
+ *
+ * Data transfer interface opening
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdarg.h>
+#include <ipxe/tables.h>
+#include <ipxe/socket.h>
+
+struct uri;
+struct interface;
+
+/** Location types */
+enum {
+ /** Location is a URI
+ *
+ * Parameter list for open() is:
+ *
+ * struct uri *uri;
+ */
+ LOCATION_URI = 1,
+ /** Location is a URI string
+ *
+ * Parameter list for open() is:
+ *
+ * const char *uri_string;
+ */
+ LOCATION_URI_STRING,
+ /** Location is a socket
+ *
+ * Parameter list for open() is:
+ *
+ * int semantics;
+ * struct sockaddr *peer;
+ * struct sockaddr *local;
+ */
+ LOCATION_SOCKET,
+};
+
+/** A URI opener */
+struct uri_opener {
+ /** URI protocol name
+ *
+ * This is the "scheme" portion of the URI, e.g. "http" or
+ * "file".
+ */
+ const char *scheme;
+ /** Open URI
+ *
+ * @v intf Object interface
+ * @v uri URI
+ * @ret rc Return status code
+ */
+ int ( * open ) ( struct interface *intf, struct uri *uri );
+};
+
+/** URI opener table */
+#define URI_OPENERS __table ( struct uri_opener, "uri_openers" )
+
+/** Register a URI opener */
+#define __uri_opener __table_entry ( URI_OPENERS, 01 )
+
+/** A socket opener */
+struct socket_opener {
+ /** Communication semantics (e.g. SOCK_STREAM) */
+ int semantics;
+ /** Address family (e.g. AF_INET) */
+ int family;
+ /** Open socket
+ *
+ * @v intf Object interface
+ * @v peer Peer socket address
+ * @v local Local socket address, or NULL
+ * @ret rc Return status code
+ */
+ int ( * open ) ( struct interface *intf, struct sockaddr *peer,
+ struct sockaddr *local );
+};
+
+/** Socket opener table */
+#define SOCKET_OPENERS __table ( struct socket_opener, "socket_openers" )
+
+/** Register a socket opener */
+#define __socket_opener __table_entry ( SOCKET_OPENERS, 01 )
+
+extern struct uri_opener * xfer_uri_opener ( const char *scheme );
+extern int xfer_open_uri ( struct interface *intf, struct uri *uri );
+extern int xfer_open_uri_string ( struct interface *intf,
+ const char *uri_string );
+extern int xfer_open_named_socket ( struct interface *intf, int semantics,
+ struct sockaddr *peer, const char *name,
+ struct sockaddr *local );
+extern int xfer_open_socket ( struct interface *intf, int semantics,
+ struct sockaddr *peer, struct sockaddr *local );
+extern int xfer_vopen ( struct interface *intf, int type, va_list args );
+extern int xfer_open ( struct interface *intf, int type, ... );
+extern int xfer_vreopen ( struct interface *intf, int type,
+ va_list args );
+
+#endif /* _IPXE_OPEN_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/parseopt.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/parseopt.h
new file mode 100644
index 00000000..b492a51e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/parseopt.h
@@ -0,0 +1,129 @@
+#ifndef _IPXE_PARSEOPT_H
+#define _IPXE_PARSEOPT_H
+
+/** @file
+ *
+ * Command line option parsing
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stddef.h>
+
+struct net_device;
+struct menu;
+
+/** A command-line option descriptor */
+struct option_descriptor {
+ /** Long option name, if any */
+ const char *longopt;
+ /** Short option name */
+ char shortopt;
+ /** Argument requirement (as for @c struct @c option) */
+ uint8_t has_arg;
+ /** Offset of field within options structure */
+ uint16_t offset;
+ /** Parse option
+ *
+ * @v text Option text
+ * @v value Option value to fill in
+ * @ret rc Return status code
+ */
+ int ( * parse ) ( const char *text, void *value );
+};
+
+/**
+ * Construct option parser
+ *
+ * @v _struct Options structure type
+ * @v _field Field within options structure
+ * @v _parse Field type-specific option parser
+ * @ret _parse Generic option parser
+ */
+#define OPTION_PARSER( _struct, _field, _parse ) \
+ ( ( int ( * ) ( const char *text, void *value ) ) \
+ ( ( ( ( typeof ( _parse ) * ) NULL ) == \
+ ( ( int ( * ) ( const char *text, \
+ typeof ( ( ( _struct * ) NULL )->_field ) * ) ) \
+ NULL ) ) ? _parse : _parse ) )
+
+/**
+ * Construct option descriptor
+ *
+ * @v _longopt Long option name, if any
+ * @v _shortopt Short option name, if any
+ * @v _has_arg Argument requirement
+ * @v _struct Options structure type
+ * @v _field Field within options structure
+ * @v _parse Field type-specific option parser
+ * @ret _option Option descriptor
+ */
+#define OPTION_DESC( _longopt, _shortopt, _has_arg, _struct, _field, _parse ) \
+ { \
+ .longopt = _longopt, \
+ .shortopt = _shortopt, \
+ .has_arg = _has_arg, \
+ .offset = offsetof ( _struct, _field ), \
+ .parse = OPTION_PARSER ( _struct, _field, _parse ), \
+ }
+
+/** A command descriptor */
+struct command_descriptor {
+ /** Option descriptors */
+ struct option_descriptor *options;
+ /** Number of option descriptors */
+ uint8_t num_options;
+ /** Length of option structure */
+ uint8_t len;
+ /** Minimum number of non-option arguments */
+ uint8_t min_args;
+ /** Maximum number of non-option arguments */
+ uint8_t max_args;
+ /** Command usage
+ *
+ * This excludes the literal "Usage:" and the command name,
+ * which will be prepended automatically.
+ */
+ const char *usage;
+};
+
+/** No maximum number of arguments */
+#define MAX_ARGUMENTS 0xff
+
+/**
+ * Construct command descriptor
+ *
+ * @v _struct Options structure type
+ * @v _options Option descriptor array
+ * @v _check_args Remaining argument checker
+ * @v _usage Command usage
+ * @ret _command Command descriptor
+ */
+#define COMMAND_DESC( _struct, _options, _min_args, _max_args, _usage ) \
+ { \
+ .options = ( ( ( ( typeof ( _options[0] ) * ) NULL ) == \
+ ( ( struct option_descriptor * ) NULL ) ) ? \
+ _options : _options ), \
+ .num_options = ( sizeof ( _options ) / \
+ sizeof ( _options[0] ) ), \
+ .len = sizeof ( _struct ), \
+ .min_args = _min_args, \
+ .max_args = _max_args, \
+ .usage = _usage, \
+ }
+
+extern int parse_string ( const char *text, const char **value );
+extern int parse_integer ( const char *text, unsigned int *value );
+extern int parse_netdev ( const char *text, struct net_device **netdev );
+extern int parse_menu ( const char *text, struct menu **menu );
+extern int parse_flag ( const char *text __unused, int *flag );
+extern int parse_key ( const char *text, unsigned int *key );
+extern void print_usage ( struct command_descriptor *cmd, char **argv );
+extern int reparse_options ( int argc, char **argv,
+ struct command_descriptor *cmd, void *opts );
+extern int parse_options ( int argc, char **argv,
+ struct command_descriptor *cmd, void *opts );
+
+#endif /* _IPXE_PARSEOPT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/pci.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/pci.h
new file mode 100644
index 00000000..2e8192d9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/pci.h
@@ -0,0 +1,448 @@
+#ifndef _IPXE_PCI_H
+#define _IPXE_PCI_H
+
+/*
+ * Support for NE2000 PCI clones added David Monro June 1997
+ * Generalised for other PCI NICs by Ken Yap July 1997
+ * PCI support rewritten by Michael Brown 2006
+ *
+ * Most of this is taken from /usr/src/linux/include/linux/pci.h.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include <stdint.h>
+#include <ipxe/device.h>
+#include <ipxe/tables.h>
+#include <ipxe/pci_io.h>
+#include "pci_ids.h"
+
+/*
+ * PCI constants
+ *
+ */
+
+#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
+#define PCI_COMMAND_MEM 0x2 /* Enable response in mem space */
+#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
+
+#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
+#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
+
+#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
+#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
+#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
+#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
+#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
+#define PCI_COMMAND_SERR 0x100 /* Enable SERR */
+#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
+#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
+
+
+#define PCI_VENDOR_ID 0x00 /* 16 bits */
+#define PCI_DEVICE_ID 0x02 /* 16 bits */
+#define PCI_COMMAND 0x04 /* 16 bits */
+
+#define PCI_STATUS 0x06 /* 16 bits */
+#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
+#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
+#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */
+#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
+#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
+#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
+#define PCI_STATUS_DEVSEL_FAST 0x000
+#define PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define PCI_STATUS_DEVSEL_SLOW 0x400
+#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
+
+#define PCI_REVISION 0x08 /* 8 bits */
+#define PCI_REVISION_ID 0x08 /* 8 bits */
+#define PCI_CLASS_REVISION 0x08 /* 32 bits */
+#define PCI_CLASS_CODE 0x0b /* 8 bits */
+#define PCI_SUBCLASS_CODE 0x0a /* 8 bits */
+#define PCI_HEADER_TYPE 0x0e /* 8 bits */
+#define PCI_HEADER_TYPE_NORMAL 0
+#define PCI_HEADER_TYPE_BRIDGE 1
+#define PCI_HEADER_TYPE_CARDBUS 2
+
+
+/* Header type 0 (normal devices) */
+#define PCI_CARDBUS_CIS 0x28
+#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
+#define PCI_SUBSYSTEM_ID 0x2e
+
+#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
+#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits */
+#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits */
+#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */
+#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */
+#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */
+
+#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
+#define PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+
+#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
+#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
+#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
+#define PCI_BASE_ADDRESS_MEM_MASK (~0x0f)
+#define PCI_BASE_ADDRESS_IO_MASK (~0x03)
+#define PCI_ROM_ADDRESS 0x30 /* 32 bits */
+#define PCI_ROM_ADDRESS_ENABLE 0x01 /* Write 1 to enable ROM,
+ bits 31..11 are address,
+ 10..2 are reserved */
+
+#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
+
+#define PCI_INTERRUPT_LINE 0x3c /* IRQ number (0-15) */
+#define PCI_INTERRUPT_PIN 0x3d /* IRQ pin on PCI bus (A-D) */
+
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
+#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
+#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */
+#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */
+#define PCI_IO_LIMIT 0x1d
+#define PCI_IO_RANGE_TYPE_MASK 0x0f /* I/O bridging type */
+#define PCI_IO_RANGE_TYPE_16 0x00
+#define PCI_IO_RANGE_TYPE_32 0x01
+#define PCI_IO_RANGE_MASK ~0x0f
+#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE 0x20 /* Memory range behind */
+#define PCI_MEMORY_LIMIT 0x22
+#define PCI_MEMORY_RANGE_TYPE_MASK 0x0f
+#define PCI_MEMORY_RANGE_MASK ~0x0f
+#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT 0x26
+#define PCI_PREF_RANGE_TYPE_MASK 0x0f
+#define PCI_PREF_RANGE_TYPE_32 0x00
+#define PCI_PREF_RANGE_TYPE_64 0x01
+#define PCI_PREF_RANGE_MASK ~0x0f
+#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32 0x2c
+#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16 0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
+#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL 0x3e
+#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */
+#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
+#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */
+#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
+#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
+#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
+#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
+
+#define PCI_CB_CAPABILITY_LIST 0x14
+
+/* Capability lists */
+
+#define PCI_CAP_LIST_ID 0 /* Capability ID */
+#define PCI_CAP_ID_PM 0x01 /* Power Management */
+#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */
+#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */
+#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */
+#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
+#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
+#define PCI_CAP_ID_VNDR 0x09 /* Vendor specific */
+#define PCI_CAP_ID_EXP 0x10 /* PCI Express */
+#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
+#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */
+#define PCI_CAP_SIZEOF 4
+
+/* Power Management Registers */
+
+#define PCI_PM_PMC 2 /* PM Capabilities Register */
+#define PCI_PM_CAP_VER_MASK 0x0007 /* Version */
+#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */
+#define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */
+#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */
+#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */
+#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */
+#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */
+#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */
+#define PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */
+#define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */
+#define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */
+#define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */
+#define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */
+#define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */
+#define PCI_PM_CTRL 4 /* PM control and status register */
+#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */
+#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */
+#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */
+#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */
+#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */
+#define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */
+#define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */
+#define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */
+#define PCI_PM_DATA_REGISTER 7 /* (??) */
+#define PCI_PM_SIZEOF 8
+
+/* AGP registers */
+
+#define PCI_AGP_VERSION 2 /* BCD version number */
+#define PCI_AGP_RFU 3 /* Rest of capability flags */
+#define PCI_AGP_STATUS 4 /* Status register */
+#define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */
+#define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */
+#define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing supported */
+#define PCI_AGP_STATUS_FW 0x0010 /* FW transfers supported */
+#define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported */
+#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported */
+#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported */
+#define PCI_AGP_COMMAND 8 /* Control register */
+#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */
+#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */
+#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */
+#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow processing of 64-bit addresses */
+#define PCI_AGP_COMMAND_FW 0x0010 /* Force FW transfers */
+#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate */
+#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 2x rate */
+#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 1x rate */
+#define PCI_AGP_SIZEOF 12
+
+/* Slot Identification */
+
+#define PCI_SID_ESR 2 /* Expansion Slot Register */
+#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */
+#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */
+#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */
+
+/* Message Signalled Interrupts registers */
+
+#define PCI_MSI_FLAGS 2 /* Various flags */
+#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */
+#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */
+#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */
+#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */
+#define PCI_MSI_RFU 3 /* Rest of capability flags */
+#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
+#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
+#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
+#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
+
+/* Advanced Error Reporting */
+
+#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */
+#define PCI_ERR_UNC_TRAIN 0x00000001 /* Training */
+#define PCI_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */
+#define PCI_ERR_UNC_POISON_TLP 0x00001000 /* Poisoned TLP */
+#define PCI_ERR_UNC_FCP 0x00002000 /* Flow Control Protocol */
+#define PCI_ERR_UNC_COMP_TIME 0x00004000 /* Completion Timeout */
+#define PCI_ERR_UNC_COMP_ABORT 0x00008000 /* Completer Abort */
+#define PCI_ERR_UNC_UNX_COMP 0x00010000 /* Unexpected Completion */
+#define PCI_ERR_UNC_RX_OVER 0x00020000 /* Receiver Overflow */
+#define PCI_ERR_UNC_MALF_TLP 0x00040000 /* Malformed TLP */
+#define PCI_ERR_UNC_ECRC 0x00080000 /* ECRC Error Status */
+#define PCI_ERR_UNC_UNSUP 0x00100000 /* Unsupported Request */
+#define PCI_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */
+ /* Same bits as above */
+#define PCI_ERR_UNCOR_SEVER 12 /* Uncorrectable Error Severity */
+ /* Same bits as above */
+#define PCI_ERR_COR_STATUS 16 /* Correctable Error Status */
+#define PCI_ERR_COR_RCVR 0x00000001 /* Receiver Error Status */
+#define PCI_ERR_COR_BAD_TLP 0x00000040 /* Bad TLP Status */
+#define PCI_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */
+#define PCI_ERR_COR_REP_ROLL 0x00000100 /* REPLAY_NUM Rollover */
+#define PCI_ERR_COR_REP_TIMER 0x00001000 /* Replay Timer Timeout */
+#define PCI_ERR_COR_MASK 20 /* Correctable Error Mask */
+ /* Same bits as above */
+
+/** A PCI device ID list entry */
+struct pci_device_id {
+ /** Name */
+ const char *name;
+ /** PCI vendor ID */
+ uint16_t vendor;
+ /** PCI device ID */
+ uint16_t device;
+ /** Arbitrary driver data */
+ unsigned long driver_data;
+};
+
+/** Match-anything ID */
+#define PCI_ANY_ID 0xffff
+
+/** A PCI device */
+struct pci_device {
+ /** Generic device */
+ struct device dev;
+ /** Memory base
+ *
+ * This is the physical address of the first valid memory BAR.
+ */
+ unsigned long membase;
+ /**
+ * I/O address
+ *
+ * This is the physical address of the first valid I/O BAR.
+ */
+ unsigned long ioaddr;
+ /** Vendor ID */
+ uint16_t vendor;
+ /** Device ID */
+ uint16_t device;
+ /** Device class */
+ uint32_t class;
+ /** Interrupt number */
+ uint8_t irq;
+ /** Bus, device, and function (bus:dev.fn) number */
+ uint16_t busdevfn;
+ /** Driver for this device */
+ struct pci_driver *driver;
+ /** Driver-private data
+ *
+ * Use pci_set_drvdata() and pci_get_drvdata() to access this
+ * field.
+ */
+ void *priv;
+ /** Driver device ID */
+ struct pci_device_id *id;
+};
+
+/** A PCI driver */
+struct pci_driver {
+ /** PCI ID table */
+ struct pci_device_id *ids;
+ /** Number of entries in PCI ID table */
+ unsigned int id_count;
+ /**
+ * Probe device
+ *
+ * @v pci PCI device
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct pci_device *pci );
+ /**
+ * Remove device
+ *
+ * @v pci PCI device
+ */
+ void ( * remove ) ( struct pci_device *pci );
+};
+
+/** PCI driver table */
+#define PCI_DRIVERS __table ( struct pci_driver, "pci_drivers" )
+
+/** Declare a PCI driver */
+#define __pci_driver __table_entry ( PCI_DRIVERS, 01 )
+
+/** Declare a fallback PCI driver */
+#define __pci_driver_fallback __table_entry ( PCI_DRIVERS, 02 )
+
+#define PCI_BUS( busdevfn ) ( ( (busdevfn) >> 8 ) & 0xff )
+#define PCI_SLOT( busdevfn ) ( ( (busdevfn) >> 3 ) & 0x1f )
+#define PCI_FUNC( busdevfn ) ( ( (busdevfn) >> 0 ) & 0x07 )
+#define PCI_BUSDEVFN( bus, slot, func ) \
+ ( ( (bus) << 8 ) | ( (slot) << 3 ) | ( (func) << 0 ) )
+
+#define PCI_BASE_CLASS( class ) ( (class) >> 16 )
+#define PCI_SUB_CLASS( class ) ( ( (class) >> 8 ) & 0xff )
+#define PCI_PROG_INTF( class ) ( (class) & 0xff )
+
+/*
+ * PCI_ROM is used to build up entries in a struct pci_id array. It
+ * is also parsed by parserom.pl to generate Makefile rules and files
+ * for rom-o-matic.
+ *
+ * PCI_ID can be used to generate entries without creating a
+ * corresponding ROM in the build process.
+ */
+#define PCI_ID( _vendor, _device, _name, _description, _data ) { \
+ .vendor = _vendor, \
+ .device = _device, \
+ .name = _name, \
+ .driver_data = _data \
+}
+#define PCI_ROM( _vendor, _device, _name, _description, _data ) \
+ PCI_ID( _vendor, _device, _name, _description, _data )
+
+/** PCI device debug message format */
+#define PCI_FMT "PCI %02x:%02x.%x"
+
+/** PCI device debug message arguments */
+#define PCI_ARGS( pci ) \
+ PCI_BUS ( (pci)->busdevfn ), PCI_SLOT ( (pci)->busdevfn ), \
+ PCI_FUNC ( (pci)->busdevfn )
+
+extern void adjust_pci_device ( struct pci_device *pci );
+extern unsigned long pci_bar_start ( struct pci_device *pci,
+ unsigned int reg );
+extern int pci_read_config ( struct pci_device *pci );
+extern int pci_find_driver ( struct pci_device *pci );
+extern int pci_probe ( struct pci_device *pci );
+extern void pci_remove ( struct pci_device *pci );
+extern int pci_find_capability ( struct pci_device *pci, int capability );
+extern unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg );
+
+/**
+ * Initialise PCI device
+ *
+ * @v pci PCI device
+ * @v busdevfn PCI bus:dev.fn address
+ */
+static inline void pci_init ( struct pci_device *pci, unsigned int busdevfn ) {
+ pci->busdevfn = busdevfn;
+}
+
+/**
+ * Set PCI driver
+ *
+ * @v pci PCI device
+ * @v driver PCI driver
+ * @v id PCI device ID
+ */
+static inline void pci_set_driver ( struct pci_device *pci,
+ struct pci_driver *driver,
+ struct pci_device_id *id ) {
+ pci->driver = driver;
+ pci->id = id;
+ pci->dev.driver_name = id->name;
+}
+
+/**
+ * Set PCI driver-private data
+ *
+ * @v pci PCI device
+ * @v priv Private data
+ */
+static inline void pci_set_drvdata ( struct pci_device *pci, void *priv ) {
+ pci->priv = priv;
+}
+
+/**
+ * Get PCI driver-private data
+ *
+ * @v pci PCI device
+ * @ret priv Private data
+ */
+static inline void * pci_get_drvdata ( struct pci_device *pci ) {
+ return pci->priv;
+}
+
+#endif /* _IPXE_PCI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/pci_ids.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/pci_ids.h
new file mode 100644
index 00000000..25c7782b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/pci_ids.h
@@ -0,0 +1,351 @@
+#ifndef _IPXE_PCI_IDS_H
+#define _IPXE_PCI_IDS_H
+
+/*
+ * PCI Class, Vendor and Device IDs
+ *
+ * Please keep sorted.
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/* Device classes and subclasses */
+
+#define PCI_CLASS_NOT_DEFINED 0x0000
+#define PCI_CLASS_NOT_DEFINED_VGA 0x0001
+
+#define PCI_BASE_CLASS_STORAGE 0x01
+#define PCI_CLASS_STORAGE_SCSI 0x0100
+#define PCI_CLASS_STORAGE_IDE 0x0101
+#define PCI_CLASS_STORAGE_FLOPPY 0x0102
+#define PCI_CLASS_STORAGE_IPI 0x0103
+#define PCI_CLASS_STORAGE_RAID 0x0104
+#define PCI_CLASS_STORAGE_OTHER 0x0180
+
+#define PCI_BASE_CLASS_NETWORK 0x02
+#define PCI_CLASS_NETWORK_ETHERNET 0x0200
+#define PCI_CLASS_NETWORK_TOKEN_RING 0x0201
+#define PCI_CLASS_NETWORK_FDDI 0x0202
+#define PCI_CLASS_NETWORK_ATM 0x0203
+#define PCI_CLASS_NETWORK_OTHER 0x0280
+
+#define PCI_BASE_CLASS_DISPLAY 0x03
+#define PCI_CLASS_DISPLAY_VGA 0x0300
+#define PCI_CLASS_DISPLAY_XGA 0x0301
+#define PCI_CLASS_DISPLAY_3D 0x0302
+#define PCI_CLASS_DISPLAY_OTHER 0x0380
+
+#define PCI_BASE_CLASS_MULTIMEDIA 0x04
+#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400
+#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401
+#define PCI_CLASS_MULTIMEDIA_PHONE 0x0402
+#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480
+
+#define PCI_BASE_CLASS_MEMORY 0x05
+#define PCI_CLASS_MEMORY_RAM 0x0500
+#define PCI_CLASS_MEMORY_FLASH 0x0501
+#define PCI_CLASS_MEMORY_OTHER 0x0580
+
+#define PCI_BASE_CLASS_BRIDGE 0x06
+#define PCI_CLASS_BRIDGE_HOST 0x0600
+#define PCI_CLASS_BRIDGE_ISA 0x0601
+#define PCI_CLASS_BRIDGE_EISA 0x0602
+#define PCI_CLASS_BRIDGE_MC 0x0603
+#define PCI_CLASS_BRIDGE_PCI 0x0604
+#define PCI_CLASS_BRIDGE_PCMCIA 0x0605
+#define PCI_CLASS_BRIDGE_NUBUS 0x0606
+#define PCI_CLASS_BRIDGE_CARDBUS 0x0607
+#define PCI_CLASS_BRIDGE_RACEWAY 0x0608
+#define PCI_CLASS_BRIDGE_OTHER 0x0680
+
+#define PCI_BASE_CLASS_COMMUNICATION 0x07
+#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700
+#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
+#define PCI_CLASS_COMMUNICATION_MULTISERIAL 0x0702
+#define PCI_CLASS_COMMUNICATION_MODEM 0x0703
+#define PCI_CLASS_COMMUNICATION_OTHER 0x0780
+
+#define PCI_BASE_CLASS_SYSTEM 0x08
+#define PCI_CLASS_SYSTEM_PIC 0x0800
+#define PCI_CLASS_SYSTEM_DMA 0x0801
+#define PCI_CLASS_SYSTEM_TIMER 0x0802
+#define PCI_CLASS_SYSTEM_RTC 0x0803
+#define PCI_CLASS_SYSTEM_PCI_HOTPLUG 0x0804
+#define PCI_CLASS_SYSTEM_OTHER 0x0880
+
+#define PCI_BASE_CLASS_INPUT 0x09
+#define PCI_CLASS_INPUT_KEYBOARD 0x0900
+#define PCI_CLASS_INPUT_PEN 0x0901
+#define PCI_CLASS_INPUT_MOUSE 0x0902
+#define PCI_CLASS_INPUT_SCANNER 0x0903
+#define PCI_CLASS_INPUT_GAMEPORT 0x0904
+#define PCI_CLASS_INPUT_OTHER 0x0980
+
+#define PCI_BASE_CLASS_DOCKING 0x0a
+#define PCI_CLASS_DOCKING_GENERIC 0x0a00
+#define PCI_CLASS_DOCKING_OTHER 0x0a80
+
+#define PCI_BASE_CLASS_PROCESSOR 0x0b
+#define PCI_CLASS_PROCESSOR_386 0x0b00
+#define PCI_CLASS_PROCESSOR_486 0x0b01
+#define PCI_CLASS_PROCESSOR_PENTIUM 0x0b02
+#define PCI_CLASS_PROCESSOR_ALPHA 0x0b10
+#define PCI_CLASS_PROCESSOR_POWERPC 0x0b20
+#define PCI_CLASS_PROCESSOR_MIPS 0x0b30
+#define PCI_CLASS_PROCESSOR_CO 0x0b40
+
+#define PCI_BASE_CLASS_SERIAL 0x0c
+#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00
+#define PCI_CLASS_SERIAL_ACCESS 0x0c01
+#define PCI_CLASS_SERIAL_SSA 0x0c02
+#define PCI_CLASS_SERIAL_USB 0x0c03
+#define PCI_CLASS_SERIAL_FIBER 0x0c04
+#define PCI_CLASS_SERIAL_SMBUS 0x0c05
+
+#define PCI_BASE_CLASS_INTELLIGENT 0x0e
+#define PCI_CLASS_INTELLIGENT_I2O 0x0e00
+
+#define PCI_BASE_CLASS_SATELLITE 0x0f
+#define PCI_CLASS_SATELLITE_TV 0x0f00
+#define PCI_CLASS_SATELLITE_AUDIO 0x0f01
+#define PCI_CLASS_SATELLITE_VOICE 0x0f03
+#define PCI_CLASS_SATELLITE_DATA 0x0f04
+
+#define PCI_BASE_CLASS_CRYPT 0x10
+#define PCI_CLASS_CRYPT_NETWORK 0x1000
+#define PCI_CLASS_CRYPT_ENTERTAINMENT 0x1001
+#define PCI_CLASS_CRYPT_OTHER 0x1080
+
+#define PCI_BASE_CLASS_SIGNAL_PROCESSING 0x11
+#define PCI_CLASS_SP_DPIO 0x1100
+#define PCI_CLASS_SP_OTHER 0x1180
+
+#define PCI_CLASS_OTHERS 0xff
+
+/* Vendors */
+
+#define PCI_VENDOR_ID_DYNALINK 0x0675
+#define PCI_VENDOR_ID_BERKOM 0x0871
+#define PCI_VENDOR_ID_COMPAQ 0x0e11
+#define PCI_VENDOR_ID_NCR 0x1000
+#define PCI_VENDOR_ID_LSI_LOGIC 0x1000
+#define PCI_VENDOR_ID_ATI 0x1002
+#define PCI_VENDOR_ID_VLSI 0x1004
+#define PCI_VENDOR_ID_ADL 0x1005
+#define PCI_VENDOR_ID_NS 0x100b
+#define PCI_VENDOR_ID_TSENG 0x100c
+#define PCI_VENDOR_ID_WEITEK 0x100e
+#define PCI_VENDOR_ID_DEC 0x1011
+#define PCI_VENDOR_ID_CIRRUS 0x1013
+#define PCI_VENDOR_ID_IBM 0x1014
+#define PCI_VENDOR_ID_COMPEX2 0x101a
+/* pci.ids says "AT&T GIS (NCR)" */
+#define PCI_VENDOR_ID_WD 0x101c
+#define PCI_VENDOR_ID_AMI 0x101e
+#define PCI_VENDOR_ID_AMD 0x1022
+#define PCI_VENDOR_ID_TRIDENT 0x1023
+#define PCI_VENDOR_ID_AI 0x1025
+#define PCI_VENDOR_ID_DELL 0x1028
+#define PCI_VENDOR_ID_MATROX 0x102B
+#define PCI_VENDOR_ID_CT 0x102c
+#define PCI_VENDOR_ID_MIRO 0x1031
+#define PCI_VENDOR_ID_NEC 0x1033
+#define PCI_VENDOR_ID_FD 0x1036
+#define PCI_VENDOR_ID_SIS 0x1039
+#define PCI_VENDOR_ID_SI 0x1039
+#define PCI_VENDOR_ID_HP 0x103c
+#define PCI_VENDOR_ID_PCTECH 0x1042
+#define PCI_VENDOR_ID_ASUSTEK 0x1043
+#define PCI_VENDOR_ID_DPT 0x1044
+#define PCI_VENDOR_ID_OPTI 0x1045
+#define PCI_VENDOR_ID_ELSA 0x1048
+#define PCI_VENDOR_ID_ELSA 0x1048
+#define PCI_VENDOR_ID_SGS 0x104a
+#define PCI_VENDOR_ID_BUSLOGIC 0x104B
+#define PCI_VENDOR_ID_TI 0x104c
+#define PCI_VENDOR_ID_SONY 0x104d
+#define PCI_VENDOR_ID_OAK 0x104e
+/* Winbond have two vendor IDs! See 0x10ad as well */
+#define PCI_VENDOR_ID_WINBOND2 0x1050
+#define PCI_VENDOR_ID_ANIGMA 0x1051
+#define PCI_VENDOR_ID_EFAR 0x1055
+#define PCI_VENDOR_ID_MOTOROLA 0x1057
+#define PCI_VENDOR_ID_MOTOROLA_OOPS 0x1507
+#define PCI_VENDOR_ID_PROMISE 0x105a
+#define PCI_VENDOR_ID_N9 0x105d
+#define PCI_VENDOR_ID_UMC 0x1060
+#define PCI_VENDOR_ID_X 0x1061
+#define PCI_VENDOR_ID_MYLEX 0x1069
+#define PCI_VENDOR_ID_PICOP 0x1066
+#define PCI_VENDOR_ID_APPLE 0x106b
+#define PCI_VENDOR_ID_YAMAHA 0x1073
+#define PCI_VENDOR_ID_NEXGEN 0x1074
+#define PCI_VENDOR_ID_QLOGIC 0x1077
+#define PCI_VENDOR_ID_CYRIX 0x1078
+#define PCI_VENDOR_ID_LEADTEK 0x107d
+#define PCI_VENDOR_ID_INTERPHASE 0x107e
+#define PCI_VENDOR_ID_CONTAQ 0x1080
+#define PCI_VENDOR_ID_FOREX 0x1083
+#define PCI_VENDOR_ID_OLICOM 0x108d
+#define PCI_VENDOR_ID_SUN 0x108e
+#define PCI_VENDOR_ID_CMD 0x1095
+#define PCI_VENDOR_ID_VISION 0x1098
+#define PCI_VENDOR_ID_BROOKTREE 0x109e
+#define PCI_VENDOR_ID_SIERRA 0x10a8
+#define PCI_VENDOR_ID_SGI 0x10a9
+#define PCI_VENDOR_ID_ACC 0x10aa
+#define PCI_VENDOR_ID_WINBOND 0x10ad
+#define PCI_VENDOR_ID_DATABOOK 0x10b3
+#define PCI_VENDOR_ID_PLX 0x10b5
+#define PCI_VENDOR_ID_MADGE 0x10b6
+#define PCI_VENDOR_ID_3COM 0x10b7
+#define PCI_VENDOR_ID_SMC 0x10b8
+#define PCI_VENDOR_ID_SUNDANCE 0x13F0
+#define PCI_VENDOR_ID_AL 0x10b9
+#define PCI_VENDOR_ID_MITSUBISHI 0x10ba
+#define PCI_VENDOR_ID_SURECOM 0x10bd
+#define PCI_VENDOR_ID_NEOMAGIC 0x10c8
+#define PCI_VENDOR_ID_ASP 0x10cd
+#define PCI_VENDOR_ID_MACRONIX 0x10d9
+#define PCI_VENDOR_ID_TCONRAD 0x10da
+#define PCI_VENDOR_ID_CERN 0x10dc
+#define PCI_VENDOR_ID_NVIDIA 0x10de
+#define PCI_VENDOR_ID_IMS 0x10e0
+#define PCI_VENDOR_ID_TEKRAM2 0x10e1
+#define PCI_VENDOR_ID_TUNDRA 0x10e3
+#define PCI_VENDOR_ID_AMCC 0x10e8
+#define PCI_VENDOR_ID_INTERG 0x10ea
+#define PCI_VENDOR_ID_REALTEK 0x10ec
+#define PCI_VENDOR_ID_XILINX 0x10ee
+#define PCI_VENDOR_ID_TRUEVISION 0x10fa
+#define PCI_VENDOR_ID_INIT 0x1101
+#define PCI_VENDOR_ID_CREATIVE 0x1102
+/* duplicate: ECTIVA */
+#define PCI_VENDOR_ID_ECTIVA 0x1102
+/* duplicate: CREATIVE */
+#define PCI_VENDOR_ID_TTI 0x1103
+#define PCI_VENDOR_ID_VIA 0x1106
+#define PCI_VENDOR_ID_VIATEC 0x1106
+#define PCI_VENDOR_ID_SIEMENS 0x110A
+#define PCI_VENDOR_ID_SMC2 0x1113
+#define PCI_VENDOR_ID_VORTEX 0x1119
+#define PCI_VENDOR_ID_EF 0x111a
+#define PCI_VENDOR_ID_IDT 0x111d
+#define PCI_VENDOR_ID_FORE 0x1127
+#define PCI_VENDOR_ID_IMAGINGTECH 0x112f
+#define PCI_VENDOR_ID_PHILIPS 0x1131
+#define PCI_VENDOR_ID_EICON 0x1133
+#define PCI_VENDOR_ID_CYCLONE 0x113c
+#define PCI_VENDOR_ID_ALLIANCE 0x1142
+#define PCI_VENDOR_ID_SYSKONNECT 0x1148
+#define PCI_VENDOR_ID_VMIC 0x114a
+#define PCI_VENDOR_ID_DIGI 0x114f
+#define PCI_VENDOR_ID_MUTECH 0x1159
+#define PCI_VENDOR_ID_XIRCOM 0x115d
+#define PCI_VENDOR_ID_RENDITION 0x1163
+#define PCI_VENDOR_ID_SERVERWORKS 0x1166
+#define PCI_VENDOR_ID_SBE 0x1176
+#define PCI_VENDOR_ID_TOSHIBA 0x1179
+#define PCI_VENDOR_ID_RICOH 0x1180
+#define PCI_VENDOR_ID_DLINK 0x1186
+#define PCI_VENDOR_ID_ARTOP 0x1191
+#define PCI_VENDOR_ID_ZEITNET 0x1193
+#define PCI_VENDOR_ID_OMEGA 0x119b
+#define PCI_VENDOR_ID_FUJITSU_ME 0x119e
+#define PCI_SUBVENDOR_ID_KEYSPAN 0x11a9
+#define PCI_VENDOR_ID_GALILEO 0x11ab
+#define PCI_VENDOR_ID_LINKSYS 0x11ad
+#define PCI_VENDOR_ID_LITEON 0x11ad
+#define PCI_VENDOR_ID_V3 0x11b0
+#define PCI_VENDOR_ID_NP 0x11bc
+#define PCI_VENDOR_ID_ATT 0x11c1
+#define PCI_VENDOR_ID_SPECIALIX 0x11cb
+#define PCI_VENDOR_ID_AURAVISION 0x11d1
+#define PCI_VENDOR_ID_ANALOG_DEVICES 0x11d4
+#define PCI_VENDOR_ID_IKON 0x11d5
+#define PCI_VENDOR_ID_ZORAN 0x11de
+#define PCI_VENDOR_ID_KINETIC 0x11f4
+#define PCI_VENDOR_ID_COMPEX 0x11f6
+#define PCI_VENDOR_ID_RP 0x11fe
+#define PCI_VENDOR_ID_CYCLADES 0x120e
+#define PCI_VENDOR_ID_ESSENTIAL 0x120f
+#define PCI_VENDOR_ID_O2 0x1217
+#define PCI_VENDOR_ID_3DFX 0x121a
+#define PCI_VENDOR_ID_SIGMADES 0x1236
+#define PCI_VENDOR_ID_CCUBE 0x123f
+#define PCI_VENDOR_ID_AVM 0x1244
+#define PCI_VENDOR_ID_DIPIX 0x1246
+#define PCI_VENDOR_ID_STALLION 0x124d
+#define PCI_VENDOR_ID_OPTIBASE 0x1255
+#define PCI_VENDOR_ID_ESS 0x125d
+#define PCI_VENDOR_ID_HARRIS 0x1260
+#define PCI_VENDOR_ID_SATSAGEM 0x1267
+#define PCI_VENDOR_ID_HUGHES 0x1273
+#define PCI_VENDOR_ID_ENSONIQ 0x1274
+#define PCI_VENDOR_ID_ROCKWELL 0x127A
+#define PCI_VENDOR_ID_DAVICOM 0x1282
+#define PCI_VENDOR_ID_ITE 0x1283
+/* formerly Platform Tech */
+#define PCI_VENDOR_ID_ESS_OLD 0x1285
+#define PCI_VENDOR_ID_ALTEON 0x12ae
+#define PCI_VENDOR_ID_USR 0x12B9
+#define PCI_VENDOR_ID_HOLTEK 0x12c3
+#define PCI_SUBVENDOR_ID_CONNECT_TECH 0x12c4
+#define PCI_VENDOR_ID_PICTUREL 0x12c5
+#define PCI_VENDOR_ID_NVIDIA_SGS 0x12d2
+#define PCI_SUBVENDOR_ID_CHASE_PCIFAST 0x12E0
+#define PCI_SUBVENDOR_ID_CHASE_PCIRAS 0x124D
+#define PCI_VENDOR_ID_AUREAL 0x12eb
+#define PCI_VENDOR_ID_CBOARDS 0x1307
+#define PCI_VENDOR_ID_SIIG 0x131f
+#define PCI_VENDOR_ID_ADMTEK 0x1317
+#define PCI_VENDOR_ID_DOMEX 0x134a
+#define PCI_VENDOR_ID_QUATECH 0x135C
+#define PCI_VENDOR_ID_SEALEVEL 0x135e
+#define PCI_VENDOR_ID_HYPERCOPE 0x1365
+#define PCI_VENDOR_ID_KAWASAKI 0x136b
+#define PCI_VENDOR_ID_LMC 0x1376
+#define PCI_VENDOR_ID_NETGEAR 0x1385
+#define PCI_VENDOR_ID_APPLICOM 0x1389
+#define PCI_VENDOR_ID_MOXA 0x1393
+#define PCI_VENDOR_ID_CCD 0x1397
+#define PCI_VENDOR_ID_MICROGATE 0x13c0
+#define PCI_VENDOR_ID_3WARE 0x13C1
+#define PCI_VENDOR_ID_ABOCOM 0x13D1
+#define PCI_VENDOR_ID_CMEDIA 0x13f6
+#define PCI_VENDOR_ID_LAVA 0x1407
+#define PCI_VENDOR_ID_TIMEDIA 0x1409
+#define PCI_VENDOR_ID_OXSEMI 0x1415
+#define PCI_VENDOR_ID_AIRONET 0x14b9
+#define PCI_VENDOR_ID_MYRICOM 0x14c1
+#define PCI_VENDOR_ID_TITAN 0x14D2
+#define PCI_VENDOR_ID_PANACOM 0x14d4
+#define PCI_VENDOR_ID_BROADCOM 0x14e4
+#define PCI_VENDOR_ID_SYBA 0x1592
+#define PCI_VENDOR_ID_MORETON 0x15aa
+#define PCI_VENDOR_ID_ZOLTRIX 0x15b0
+#define PCI_VENDOR_ID_PDC 0x15e9
+#define PCI_VENDOR_ID_FSC 0x1734
+#define PCI_VENDOR_ID_SYMPHONY 0x1c1c
+#define PCI_VENDOR_ID_TEKRAM 0x1de1
+#define PCI_VENDOR_ID_3DLABS 0x3d3d
+#define PCI_VENDOR_ID_AVANCE 0x4005
+#define PCI_VENDOR_ID_AKS 0x416c
+#define PCI_VENDOR_ID_NETVIN 0x4a14
+#define PCI_VENDOR_ID_S3 0x5333
+#define PCI_VENDOR_ID_DCI 0x6666
+#define PCI_VENDOR_ID_GENROCO 0x5555
+#define PCI_VENDOR_ID_INTEL 0x8086
+#define PCI_VENDOR_ID_COMPUTONE 0x8e0e
+#define PCI_SUBVENDOR_ID_COMPUTONE 0x8e0e
+#define PCI_VENDOR_ID_KTI 0x8e2e
+#define PCI_VENDOR_ID_ADAPTEC 0x9004
+#define PCI_VENDOR_ID_ADAPTEC2 0x9005
+#define PCI_VENDOR_ID_ATRONICS 0x907f
+#define PCI_VENDOR_ID_HOLTEK2 0x9412
+#define PCI_VENDOR_ID_NETMOS 0x9710
+#define PCI_SUBVENDOR_ID_EXSYS 0xd84d
+#define PCI_VENDOR_ID_TIGERJET 0xe159
+#define PCI_VENDOR_ID_ARK 0xedd8
+
+#endif /* _IPXE_PCI_IDS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/pci_io.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/pci_io.h
new file mode 100644
index 00000000..7368cf48
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/pci_io.h
@@ -0,0 +1,124 @@
+#ifndef _IPXE_PCI_IO_H
+#define _IPXE_PCI_IO_H
+
+/** @file
+ *
+ * PCI I/O API
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/api.h>
+#include <config/ioapi.h>
+
+/**
+ * Calculate static inline PCI I/O API function name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ */
+#define PCIAPI_INLINE( _subsys, _api_func ) \
+ SINGLE_API_INLINE ( PCIAPI_PREFIX_ ## _subsys, _api_func )
+
+/**
+ * Provide a PCI I/O API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_PCIAPI( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( PCIAPI_PREFIX_ ## _subsys, _api_func, _func )
+
+/**
+ * Provide a static inline PCI I/O API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ */
+#define PROVIDE_PCIAPI_INLINE( _subsys, _api_func ) \
+ PROVIDE_SINGLE_API_INLINE ( PCIAPI_PREFIX_ ## _subsys, _api_func )
+
+/* Include all architecture-independent I/O API headers */
+#include <ipxe/efi/efi_pci_api.h>
+
+/* Include all architecture-dependent I/O API headers */
+#include <bits/pci_io.h>
+
+/**
+ * Determine number of PCI buses within system
+ *
+ * @ret num_bus Number of buses
+ */
+int pci_num_bus ( void );
+
+/**
+ * Read byte from PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+int pci_read_config_byte ( struct pci_device *pci, unsigned int where,
+ uint8_t *value );
+
+/**
+ * Read 16-bit word from PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+int pci_read_config_word ( struct pci_device *pci, unsigned int where,
+ uint16_t *value );
+
+/**
+ * Read 32-bit dword from PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+int pci_read_config_dword ( struct pci_device *pci, unsigned int where,
+ uint32_t *value );
+
+/**
+ * Write byte to PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+int pci_write_config_byte ( struct pci_device *pci, unsigned int where,
+ uint8_t value );
+
+/**
+ * Write 16-bit word to PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+int pci_write_config_word ( struct pci_device *pci, unsigned int where,
+ uint16_t value );
+
+/**
+ * Write 32-bit dword to PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+int pci_write_config_dword ( struct pci_device *pci, unsigned int where,
+ uint32_t value );
+
+#endif /* _IPXE_PCI_IO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/pcibackup.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/pcibackup.h
new file mode 100644
index 00000000..b9f55cf7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/pcibackup.h
@@ -0,0 +1,33 @@
+#ifndef _IPXE_PCIBACKUP_H
+#define _IPXE_PCIBACKUP_H
+
+/** @file
+ *
+ * PCI configuration space backup and restoration
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/** A PCI configuration space backup */
+struct pci_config_backup {
+ uint32_t dwords[64];
+};
+
+/** PCI configuration space backup exclusion list end marker */
+#define PCI_CONFIG_BACKUP_EXCLUDE_END 0xff
+
+/** Define a PCI configuration space backup exclusion list */
+#define PCI_CONFIG_BACKUP_EXCLUDE(...) \
+ { __VA_ARGS__, PCI_CONFIG_BACKUP_EXCLUDE_END }
+
+extern void pci_backup ( struct pci_device *pci,
+ struct pci_config_backup *backup,
+ const uint8_t *exclude );
+extern void pci_restore ( struct pci_device *pci,
+ struct pci_config_backup *backup,
+ const uint8_t *exclude );
+
+#endif /* _IPXE_PCIBACKUP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/pcivpd.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/pcivpd.h
new file mode 100644
index 00000000..0abf8a95
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/pcivpd.h
@@ -0,0 +1,181 @@
+#ifndef _IPXE_PCIVPD_H
+#define _IPXE_PCIVPD_H
+
+/**
+ * @file
+ *
+ * PCI Vital Product Data
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <byteswap.h>
+#include <ipxe/isapnp.h>
+#include <ipxe/pci.h>
+
+/** PCI VPD address register */
+#define PCI_VPD_ADDRESS 0x02
+
+/** PCI VPD write flag */
+#define PCI_VPD_FLAG 0x8000
+
+/** PCI VPD data register */
+#define PCI_VPD_DATA 0x04
+
+/** A PCI VPD field */
+struct pci_vpd_field {
+ /** Keyword */
+ uint16_t keyword;
+ /** Length */
+ uint8_t len;
+} __attribute__ (( packed ));
+
+/** Maximum PCI VPD field length */
+#define PCI_VPD_MAX_LEN 0xff
+
+/** Construct PCI VPD field descriptor
+ *
+ * @v tag ISAPnP tag
+ * @v keyword1 First character of keyword
+ * @v keyword2 Second character of keyword
+ * @ret field VPD field descriptor
+ */
+#define PCI_VPD_FIELD( tag, keyword1, keyword2 ) \
+ ( ( (tag) << 16 ) | ( (keyword2) << 8 ) | ( (keyword1) << 0 ) )
+
+/** Construct PCI VPD whole-tag field descriptor
+ *
+ * @v tag ISAPnP tag
+ * @ret field VPD field descriptor
+ */
+#define PCI_VPD_WHOLE_TAG_FIELD( tag ) PCI_VPD_FIELD ( (tag), '\0', '\0' )
+
+/** Extract PCI VPD ISAPnP tag
+ *
+ * @v field VPD field descriptor
+ * @ret tag ISAPnP tag
+ */
+#define PCI_VPD_TAG( field ) ( (field) >> 16 )
+
+/** Extract PCI VPD keyword
+ *
+ * @v field VPD field descriptor
+ * @ret keyword Keyword
+ */
+#define PCI_VPD_KEYWORD( field ) ( cpu_to_le16 ( (field) & 0xffff ) )
+
+/** PCI VPD field debug message format */
+#define PCI_VPD_FIELD_FMT "%c%c"
+
+/** PCI VPD field debug message arguments */
+#define PCI_VPD_FIELD_ARGS( field ) \
+ ( (field) >> 0 ), ( (field) >> 8 )
+
+/** PCI VPD Read-Only field tag */
+#define PCI_VPD_TAG_RO 0x90
+
+/** PCI VPD Read-Write field tag */
+#define PCI_VPD_TAG_RW 0x91
+
+/** PCI VPD Card Name field descriptor */
+#define PCI_VPD_FIELD_NAME PCI_VPD_WHOLE_TAG_FIELD ( ISAPNP_TAG_ANSISTR )
+
+/** PCI VPD Part Number field descriptor */
+#define PCI_VPD_FIELD_PN PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'P', 'N' )
+
+/** PCI VPD Engineering Change Level field descriptor */
+#define PCI_VPD_FIELD_EC PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'E', 'C' )
+
+/** PCI VPD Fabric Geography field descriptor */
+#define PCI_VPD_FIELD_FG PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'F', 'G' )
+
+/** PCI VPD Location field descriptor */
+#define PCI_VPD_FIELD_LC PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'L', 'C' )
+
+/** PCI VPD Manufacturer ID field descriptor */
+#define PCI_VPD_FIELD_MN PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'M', 'N' )
+
+/** PCI VPD PCI Geography field descriptor */
+#define PCI_VPD_FIELD_PG PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'P', 'G' )
+
+/** PCI VPD Serial Number field descriptor */
+#define PCI_VPD_FIELD_SN PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'S', 'N' )
+
+/** PCI VPD Extended Capability field descriptor */
+#define PCI_VPD_FIELD_CP PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'C', 'P' )
+
+/** PCI VPD Checksum and Reserved field descriptor */
+#define PCI_VPD_FIELD_RV PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'R', 'V' )
+
+/** PCI VPD Asset Tag field descriptor */
+#define PCI_VPD_FIELD_YA PCI_VPD_FIELD ( PCI_VPD_TAG_RW, 'Y', 'A' )
+
+/** PCI VPD Remaining Read/Write Area field descriptor */
+#define PCI_VPD_FIELD_RW PCI_VPD_FIELD ( PCI_VPD_TAG_RW, 'R', 'W' )
+
+/** Maximum wait for PCI VPD (in ms) */
+#define PCI_VPD_MAX_WAIT_MS 100
+
+/** PCI VPD cache */
+struct pci_vpd_cache {
+ /** Address */
+ int address;
+ /** Data */
+ uint32_t data;
+};
+
+/** PCI VPD */
+struct pci_vpd {
+ /** PCI device */
+ struct pci_device *pci;
+ /** VPD capability offset */
+ int cap;
+ /** Read cache */
+ struct pci_vpd_cache cache;
+};
+
+/**
+ * Check for presence of PCI VPD
+ *
+ * @v vpd PCI VPD
+ * @ret is_present VPD is present
+ */
+static inline __attribute__ (( always_inline )) int
+pci_vpd_is_present ( struct pci_vpd *vpd ) {
+ return ( vpd->cap != 0 );
+}
+
+/**
+ * Check if PCI VPD read cache is valid
+ *
+ * @v vpd PCI VPD
+ * @ret is_valid Read cache is valid
+ */
+static inline __attribute__ (( always_inline )) int
+pci_vpd_cache_is_valid ( struct pci_vpd *vpd ) {
+ return ( vpd->cache.address >= 0 );
+}
+
+/**
+ * Invalidate PCI VPD read cache
+ *
+ * @v vpd PCI VPD
+ */
+static inline __attribute__ (( always_inline )) void
+pci_vpd_invalidate_cache ( struct pci_vpd *vpd ) {
+ vpd->cache.address = -1;
+}
+
+extern int pci_vpd_init ( struct pci_vpd *vpd, struct pci_device *pci );
+extern int pci_vpd_read ( struct pci_vpd *vpd, unsigned int address,
+ void *buf, size_t len );
+extern int pci_vpd_write ( struct pci_vpd *vpd, unsigned int address,
+ const void *buf, size_t len );
+extern int pci_vpd_find ( struct pci_vpd *vpd, unsigned int field,
+ unsigned int *address, size_t *len );
+extern int pci_vpd_resize ( struct pci_vpd *vpd, unsigned int field,
+ size_t len, unsigned int *address );
+
+#endif /* _IPXE_PCIVPD_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/posix_io.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/posix_io.h
new file mode 100644
index 00000000..11f3bb5c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/posix_io.h
@@ -0,0 +1,87 @@
+#ifndef _IPXE_POSIX_IO_H
+#define _IPXE_POSIX_IO_H
+
+/** @file
+ *
+ * POSIX-like I/O
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/uaccess.h>
+
+/** Minimum file descriptor that will ever be allocated */
+#define POSIX_FD_MIN ( 1 )
+
+/** Maximum file descriptor that will ever be allocated */
+#define POSIX_FD_MAX ( 31 )
+
+/** File descriptor set as used for select() */
+typedef uint32_t fd_set;
+
+extern int open ( const char *uri_string );
+extern ssize_t read_user ( int fd, userptr_t buffer,
+ off_t offset, size_t len );
+extern int select ( fd_set *readfds, int wait );
+extern ssize_t fsize ( int fd );
+extern int close ( int fd );
+
+/**
+ * Zero a file descriptor set
+ *
+ * @v set File descriptor set
+ */
+static inline __attribute__ (( always_inline )) void
+FD_ZERO ( fd_set *set ) {
+ *set = 0;
+}
+
+/**
+ * Set a bit within a file descriptor set
+ *
+ * @v fd File descriptor
+ * @v set File descriptor set
+ */
+static inline __attribute__ (( always_inline )) void
+FD_SET ( int fd, fd_set *set ) {
+ *set |= ( 1 << fd );
+}
+
+/**
+ * Clear a bit within a file descriptor set
+ *
+ * @v fd File descriptor
+ * @v set File descriptor set
+ */
+static inline __attribute__ (( always_inline )) void
+FD_CLR ( int fd, fd_set *set ) {
+ *set &= ~( 1 << fd );
+}
+
+/**
+ * Test a bit within a file descriptor set
+ *
+ * @v fd File descriptor
+ * @v set File descriptor set
+ * @ret is_set Corresponding bit is set
+ */
+static inline __attribute__ (( always_inline )) int
+FD_ISSET ( int fd, fd_set *set ) {
+ return ( *set & ( 1 << fd ) );
+}
+
+/**
+ * Read data from file
+ *
+ * @v fd File descriptor
+ * @v buf Data buffer
+ * @v len Maximum length to read
+ * @ret len Actual length read, or negative error number
+ */
+static inline ssize_t read ( int fd, void *buf, size_t len ) {
+ return read_user ( fd, virt_to_user ( buf ), 0, len );
+}
+
+#endif /* _IPXE_POSIX_IO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/process.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/process.h
new file mode 100644
index 00000000..9b757981
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/process.h
@@ -0,0 +1,205 @@
+#ifndef _IPXE_PROCESS_H
+#define _IPXE_PROCESS_H
+
+/** @file
+ *
+ * Processes
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/list.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/tables.h>
+
+/** A process */
+struct process {
+ /** List of processes */
+ struct list_head list;
+ /** Process descriptor */
+ struct process_descriptor *desc;
+ /** Reference counter
+ *
+ * If this process is not part of a reference-counted object,
+ * this field may be NULL.
+ */
+ struct refcnt *refcnt;
+};
+
+/** A process descriptor */
+struct process_descriptor {
+ /** Offset of process within containing object */
+ size_t offset;
+ /**
+ * Single-step the process
+ *
+ * This method should execute a single step of the process.
+ * Returning from this method is isomorphic to yielding the
+ * CPU to another process.
+ */
+ void ( * step ) ( void *object );
+ /** Automatically reschedule the process */
+ int reschedule;
+};
+
+/**
+ * Define a process step() method
+ *
+ * @v object_type Implementing method's expected object type
+ * @v step Implementing method
+ * @ret step Process step method
+ */
+#define PROC_STEP( object_type, step ) \
+ ( ( ( ( typeof ( step ) * ) NULL ) == \
+ ( ( void ( * ) ( object_type *object ) ) NULL ) ) ? \
+ ( void ( * ) ( void *object ) ) step : \
+ ( void ( * ) ( void *object ) ) step )
+
+/**
+ * Calculate offset of process within containing object
+ *
+ * @v object_type Containing object data type
+ * @v name Process name (i.e. field within object data type)
+ * @ret offset Offset of process within containing object
+ */
+#define process_offset( object_type, name ) \
+ ( ( ( ( typeof ( ( ( object_type * ) NULL )->name ) * ) NULL ) \
+ == ( ( struct process * ) NULL ) ) \
+ ? offsetof ( object_type, name ) \
+ : offsetof ( object_type, name ) )
+
+/**
+ * Define a process descriptor
+ *
+ * @v object_type Containing object data type
+ * @v process Process name (i.e. field within object data type)
+ * @v step Process' step() method
+ * @ret desc Object interface descriptor
+ */
+#define PROC_DESC( object_type, process, _step ) { \
+ .offset = process_offset ( object_type, process ), \
+ .step = PROC_STEP ( object_type, _step ), \
+ .reschedule = 1, \
+ }
+
+/**
+ * Define a process descriptor for a process that runs only once
+ *
+ * @v object_type Containing object data type
+ * @v process Process name (i.e. field within object data type)
+ * @v step Process' step() method
+ * @ret desc Object interface descriptor
+ */
+#define PROC_DESC_ONCE( object_type, process, _step ) { \
+ .offset = process_offset ( object_type, process ), \
+ .step = PROC_STEP ( object_type, _step ), \
+ .reschedule = 0, \
+ }
+
+/**
+ * Define a process descriptor for a pure process
+ *
+ * A pure process is a process that does not have a containing object.
+ *
+ * @v step Process' step() method
+ * @ret desc Object interface descriptor
+ */
+#define PROC_DESC_PURE( _step ) { \
+ .offset = 0, \
+ .step = PROC_STEP ( struct process, _step ), \
+ .reschedule = 1, \
+ }
+
+extern void * __attribute__ (( pure ))
+process_object ( struct process *process );
+extern void process_add ( struct process *process );
+extern void process_del ( struct process *process );
+extern void step ( void );
+
+/**
+ * Initialise process without adding to process list
+ *
+ * @v process Process
+ * @v desc Process descriptor
+ * @v refcnt Containing object reference count, or NULL
+ */
+static inline __attribute__ (( always_inline )) void
+process_init_stopped ( struct process *process,
+ struct process_descriptor *desc,
+ struct refcnt *refcnt ) {
+ INIT_LIST_HEAD ( &process->list );
+ process->desc = desc;
+ process->refcnt = refcnt;
+}
+
+/**
+ * Initialise process and add to process list
+ *
+ * @v process Process
+ * @v desc Process descriptor
+ * @v refcnt Containing object reference count, or NULL
+ */
+static inline __attribute__ (( always_inline )) void
+process_init ( struct process *process,
+ struct process_descriptor *desc,
+ struct refcnt *refcnt ) {
+ process_init_stopped ( process, desc, refcnt );
+ process_add ( process );
+}
+
+/**
+ * Check if process is running
+ *
+ * @v process Process
+ * @ret running Process is running
+ */
+static inline __attribute__ (( always_inline )) int
+process_running ( struct process *process ) {
+ return ( ! list_empty ( &process->list ) );
+}
+
+/** Permanent process table */
+#define PERMANENT_PROCESSES __table ( struct process, "processes" )
+
+/**
+ * Declare a permanent process
+ *
+ * Permanent processes will be automatically added to the process list
+ * at initialisation time.
+ */
+#define __permanent_process __table_entry ( PERMANENT_PROCESSES, 01 )
+
+/** Define a permanent process
+ *
+ */
+#define PERMANENT_PROCESS( name, step ) \
+struct process_descriptor name ## _desc = PROC_DESC_PURE ( step ); \
+struct process name __permanent_process = { \
+ .list = LIST_HEAD_INIT ( name.list ), \
+ .desc = & name ## _desc, \
+ .refcnt = NULL, \
+};
+
+/**
+ * Find debugging colourisation for a process
+ *
+ * @v process Process
+ * @ret col Debugging colourisation
+ *
+ * Use as the first argument to DBGC() or equivalent macro.
+ */
+#define PROC_COL( process ) process_object ( process )
+
+/** printf() format string for PROC_DBG() */
+#define PROC_FMT "%p+%zx"
+
+/**
+ * printf() arguments for representing a process
+ *
+ * @v process Process
+ * @ret args printf() argument list corresponding to PROC_FMT
+ */
+#define PROC_DBG( process ) process_object ( process ), (process)->desc->offset
+
+#endif /* _IPXE_PROCESS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/profile.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/profile.h
new file mode 100644
index 00000000..60dd53a3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/profile.h
@@ -0,0 +1,80 @@
+#ifndef _IPXE_PROFILE_H
+#define _IPXE_PROFILE_H
+
+/** @file
+ *
+ * Profiling
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/**
+ * A data structure for storing profiling information
+ */
+union profiler {
+ /** Timestamp (in CPU-specific "ticks") */
+ uint64_t timestamp;
+ /** Registers returned by rdtsc.
+ *
+ * This part should really be architecture-specific code.
+ */
+ struct {
+ uint32_t eax;
+ uint32_t edx;
+ } rdtsc;
+};
+
+/**
+ * Static per-object profiler, for use with simple_profile()
+ */
+static union profiler simple_profiler;
+
+/**
+ * Perform profiling
+ *
+ * @v profiler Profiler data structure
+ * @ret delta Elapsed ticks since last call to profile().
+ *
+ * Call profile() both before and after the code you wish to measure.
+ * The "after" call will return the measurement. For example:
+ *
+ * @code
+ *
+ * profile ( &profiler );
+ * ... do something here ...
+ * printf ( "It took %ld ticks to execute\n", profile ( &profiler ) );
+ *
+ * @endcode
+ */
+static inline __attribute__ (( always_inline )) unsigned long
+profile ( union profiler *profiler ) {
+ uint64_t last_timestamp = profiler->timestamp;
+
+ __asm__ __volatile__ ( "rdtsc" :
+ "=a" ( profiler->rdtsc.eax ),
+ "=d" ( profiler->rdtsc.edx ) );
+ return ( profiler->timestamp - last_timestamp );
+}
+
+/**
+ * Perform profiling
+ *
+ * @ret delta Elapsed ticks since last call to profile().
+ *
+ * When you only need one profiler, you can avoid the hassle of
+ * creating your own @c profiler data structure by using
+ * simple_profile() instead.
+ *
+ * simple_profile() is equivalent to profile(&simple_profiler), where
+ * @c simple_profiler is a @c profiler data structure that is static
+ * to each object which includes @c profile.h.
+ */
+static inline __attribute__ (( always_inline )) unsigned long
+simple_profile ( void ) {
+ return profile ( &simple_profiler );
+}
+
+#endif /* _IPXE_PROFILE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/random_nz.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/random_nz.h
new file mode 100644
index 00000000..6bb80d2a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/random_nz.h
@@ -0,0 +1,16 @@
+#ifndef _IPXE_RANDOM_NZ_H
+#define _IPXE_RANDOM_NZ_H
+
+/** @file
+ *
+ * HMAC_DRBG algorithm
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+extern int get_random_nz ( void *data, size_t len );
+
+#endif /* _IPXE_RANDOM_NZ_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/rarp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/rarp.h
new file mode 100644
index 00000000..f84301a4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/rarp.h
@@ -0,0 +1,16 @@
+#ifndef _IPXE_RARP_H
+#define _IPXE_RARP_H
+
+/** @file
+ *
+ * Reverse Address Resolution Protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/netdevice.h>
+
+extern struct net_protocol rarp_protocol __net_protocol;
+
+#endif /* _IPXE_RARP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/rbg.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/rbg.h
new file mode 100644
index 00000000..9689142f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/rbg.h
@@ -0,0 +1,43 @@
+#ifndef _IPXE_RBG_H
+#define _IPXE_RBG_H
+
+/** @file
+ *
+ * RBG mechanism
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/drbg.h>
+
+/** An RBG */
+struct random_bit_generator {
+ /** DRBG state */
+ struct drbg_state state;
+};
+
+extern struct random_bit_generator rbg;
+
+/**
+ * Generate bits using RBG
+ *
+ * @v additional Additional input
+ * @v additional_len Length of additional input
+ * @v prediction_resist Prediction resistance is required
+ * @v data Output buffer
+ * @v len Length of output buffer
+ * @ret rc Return status code
+ *
+ * This is the RBG_Generate function defined in ANS X9.82 Part 4
+ * (April 2011 Draft) Section 9.1.2.2.
+ */
+static inline int rbg_generate ( const void *additional, size_t additional_len,
+ int prediction_resist, void *data,
+ size_t len ) {
+ return drbg_generate ( &rbg.state, additional, additional_len,
+ prediction_resist, data, len );
+}
+
+#endif /* _IPXE_RBG_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/rc80211.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/rc80211.h
new file mode 100644
index 00000000..eac6bc9c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/rc80211.h
@@ -0,0 +1,19 @@
+#ifndef _IPXE_RC80211_H
+#define _IPXE_RC80211_H
+
+/** @file
+ *
+ * Rate-control algorithm prototype for 802.11.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct net80211_device;
+struct rc80211_ctx;
+
+struct rc80211_ctx * rc80211_init ( struct net80211_device *dev );
+void rc80211_update_tx ( struct net80211_device *dev, int retries, int rc );
+void rc80211_update_rx ( struct net80211_device *dev, int retry, u16 rate );
+void rc80211_free ( struct rc80211_ctx *ctx );
+
+#endif /* _IPXE_RC80211_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/refcnt.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/refcnt.h
new file mode 100644
index 00000000..0e8b8658
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/refcnt.h
@@ -0,0 +1,114 @@
+#ifndef _IPXE_REFCNT_H
+#define _IPXE_REFCNT_H
+
+/** @file
+ *
+ * Reference counting
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <assert.h>
+
+/**
+ * A reference counter
+ *
+ * This data structure is designed to be embedded within a
+ * reference-counted object.
+ *
+ * Reference-counted objects are freed when their reference count
+ * drops below zero. This means that a freshly allocated-and-zeroed
+ * reference-counted object will be freed on the first call to
+ * ref_put().
+ */
+struct refcnt {
+ /** Current reference count
+ *
+ * When this count is decremented below zero, the free()
+ * method will be called.
+ */
+ int count;
+ /** Free containing object
+ *
+ * This method is called when the reference count is
+ * decremented below zero.
+ *
+ * If this method is left NULL, the standard library free()
+ * function will be called. The upshot of this is that you
+ * may omit the free() method if the @c refcnt object is the
+ * first element of your reference-counted struct.
+ */
+ void ( * free ) ( struct refcnt *refcnt );
+};
+
+/**
+ * Initialise a reference counter
+ *
+ * @v refcnt Reference counter
+ * @v free Freeing function
+ */
+static inline __attribute__ (( always_inline )) void
+ref_init ( struct refcnt *refcnt,
+ void ( * free ) ( struct refcnt *refcnt ) ) {
+ refcnt->free = free;
+}
+
+/**
+ * Initialise a reference counter
+ *
+ * @v refcnt Reference counter
+ * @v free Free containing object
+ */
+#define ref_init( refcnt, free ) do { \
+ if ( __builtin_constant_p ( (free) ) && ( (free) == NULL ) ) { \
+ /* Skip common case of no initialisation required */ \
+ } else { \
+ ref_init ( (refcnt), (free) ); \
+ } \
+ } while ( 0 )
+
+/**
+ * Initialise a static reference counter
+ *
+ * @v free_fn Free containing object
+ */
+#define REF_INIT( free_fn ) { \
+ .free = free_fn, \
+ }
+
+extern void ref_increment ( struct refcnt *refcnt );
+extern void ref_decrement ( struct refcnt *refcnt );
+
+/**
+ * Get additional reference to object
+ *
+ * @v refcnt Reference counter, or NULL
+ * @ret refcnt Reference counter
+ *
+ * If @c refcnt is NULL, no action is taken.
+ */
+#define ref_get( refcnt ) ( { \
+ if ( refcnt ) \
+ assert ( (refcnt)->count >= 0 ); \
+ ref_increment ( refcnt ); \
+ (refcnt); } )
+
+/**
+ * Drop reference to object
+ *
+ * @v refcnt Reference counter, or NULL
+ * @ret refcnt Reference counter
+ *
+ * If @c refcnt is NULL, no action is taken.
+ */
+#define ref_put( refcnt ) do { \
+ if ( refcnt ) \
+ assert ( (refcnt)->count >= 0 ); \
+ ref_decrement ( refcnt ); \
+ } while ( 0 )
+
+extern void ref_no_free ( struct refcnt *refcnt );
+
+#endif /* _IPXE_REFCNT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/resolv.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/resolv.h
new file mode 100644
index 00000000..d9868a5d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/resolv.h
@@ -0,0 +1,51 @@
+#ifndef _IPXE_RESOLV_H
+#define _IPXE_RESOLV_H
+
+/** @file
+ *
+ * Name resolution
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/interface.h>
+#include <ipxe/tables.h>
+
+struct sockaddr;
+
+/** A name resolver */
+struct resolver {
+ /** Name of this resolver (e.g. "DNS") */
+ const char *name;
+ /** Start name resolution
+ *
+ * @v resolv Name resolution interface
+ * @v name Name to resolve
+ * @v sa Socket address to complete
+ * @ret rc Return status code
+ */
+ int ( * resolv ) ( struct interface *resolv, const char *name,
+ struct sockaddr *sa );
+};
+
+/** Numeric resolver priority */
+#define RESOLV_NUMERIC 01
+
+/** Normal resolver priority */
+#define RESOLV_NORMAL 02
+
+/** Resolvers table */
+#define RESOLVERS __table ( struct resolver, "resolvers" )
+
+/** Register as a name resolver */
+#define __resolver( resolv_order ) __table_entry ( RESOLVERS, resolv_order )
+
+extern void resolv_done ( struct interface *intf, struct sockaddr *sa );
+#define resolv_done_TYPE( object_type ) \
+ typeof ( void ( object_type, struct sockaddr *sa ) )
+
+extern int resolv ( struct interface *resolv, const char *name,
+ struct sockaddr *sa );
+
+#endif /* _IPXE_RESOLV_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/retry.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/retry.h
new file mode 100644
index 00000000..87f69a5d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/retry.h
@@ -0,0 +1,111 @@
+#ifndef _IPXE_RETRY_H
+#define _IPXE_RETRY_H
+
+/** @file
+ *
+ * Retry timers
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/list.h>
+
+/** Default timeout value */
+#define DEFAULT_MIN_TIMEOUT ( TICKS_PER_SEC / 4 )
+
+/** Limit after which the timeout will be deemed permanent */
+#define DEFAULT_MAX_TIMEOUT ( 10 * TICKS_PER_SEC )
+
+/** A retry timer */
+struct retry_timer {
+ /** List of active timers */
+ struct list_head list;
+ /** Timer is currently running */
+ unsigned int running;
+ /** Timeout value (in ticks) */
+ unsigned long timeout;
+ /** Minimum timeout value (in ticks)
+ *
+ * A value of zero means "use default timeout."
+ */
+ unsigned long min_timeout;
+ /** Maximum timeout value before failure (in ticks)
+ *
+ * A value of zero means "use default timeout."
+ */
+ unsigned long max_timeout;
+ /** Start time (in ticks) */
+ unsigned long start;
+ /** Retry count */
+ unsigned int count;
+ /** Timer expired callback
+ *
+ * @v timer Retry timer
+ * @v fail Failure indicator
+ *
+ * The timer will already be stopped when this method is
+ * called. The failure indicator will be True if the retry
+ * timeout has already exceeded @c MAX_TIMEOUT.
+ */
+ void ( * expired ) ( struct retry_timer *timer, int over );
+ /** Reference counter
+ *
+ * If this interface is not part of a reference-counted
+ * object, this field may be NULL.
+ */
+ struct refcnt *refcnt;
+};
+
+/**
+ * Initialise a timer
+ *
+ * @v timer Retry timer
+ * @v expired Timer expired callback
+ * @v refcnt Reference counter, or NULL
+ */
+static inline __attribute__ (( always_inline )) void
+timer_init ( struct retry_timer *timer,
+ void ( * expired ) ( struct retry_timer *timer, int over ),
+ struct refcnt *refcnt ) {
+ timer->expired = expired;
+ timer->refcnt = refcnt;
+}
+
+/**
+ * Initialise a static timer
+ *
+ * @v expired_fn Timer expired callback
+ */
+#define TIMER_INIT( expired_fn ) { \
+ .expired = (expired_fn), \
+ }
+
+extern void start_timer ( struct retry_timer *timer );
+extern void start_timer_fixed ( struct retry_timer *timer,
+ unsigned long timeout );
+extern void stop_timer ( struct retry_timer *timer );
+
+/**
+ * Start timer with no delay
+ *
+ * @v timer Retry timer
+ *
+ * This starts the timer running with a zero timeout value.
+ */
+static inline void start_timer_nodelay ( struct retry_timer *timer ) {
+ start_timer_fixed ( timer, 0 );
+}
+
+/**
+ * Test to see if timer is currently running
+ *
+ * @v timer Retry timer
+ * @ret running Non-zero if timer is running
+ */
+static inline __attribute__ (( always_inline )) unsigned long
+timer_running ( struct retry_timer *timer ) {
+ return ( timer->running );
+}
+
+#endif /* _IPXE_RETRY_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/rootcert.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/rootcert.h
new file mode 100644
index 00000000..6525df87
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/rootcert.h
@@ -0,0 +1,16 @@
+#ifndef _IPXE_ROOTCERT_H
+#define _IPXE_ROOTCERT_H
+
+/** @file
+ *
+ * Root certificate store
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/x509.h>
+
+extern struct x509_root root_certificates;
+
+#endif /* _IPXE_ROOTCERT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/rotate.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/rotate.h
new file mode 100644
index 00000000..ba271ca7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/rotate.h
@@ -0,0 +1,33 @@
+#ifndef _IPXE_ROTATE_H
+#define _IPXE_ROTATE_H
+
+/** @file
+ *
+ * Bit operations
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+static inline __attribute__ (( always_inline )) uint32_t
+rol32 ( uint32_t data, unsigned int rotation ) {
+ return ( ( data << rotation ) | ( data >> ( 32 - rotation ) ) );
+}
+
+static inline __attribute__ (( always_inline )) uint32_t
+ror32 ( uint32_t data, unsigned int rotation ) {
+ return ( ( data >> rotation ) | ( data << ( 32 - rotation ) ) );
+}
+
+static inline __attribute__ (( always_inline )) uint64_t
+rol64 ( uint64_t data, unsigned int rotation ) {
+ return ( ( data << rotation ) | ( data >> ( 64 - rotation ) ) );
+}
+
+static inline __attribute__ (( always_inline )) uint64_t
+ror64 ( uint64_t data, unsigned int rotation ) {
+ return ( ( data >> rotation ) | ( data << ( 64 - rotation ) ) );
+}
+
+#endif /* _IPXE_ROTATE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/rsa.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/rsa.h
new file mode 100644
index 00000000..1a5ad8ba
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/rsa.h
@@ -0,0 +1,81 @@
+#ifndef _IPXE_RSA_H
+#define _IPXE_RSA_H
+
+/** @file
+ *
+ * RSA public-key cryptography
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/crypto.h>
+#include <ipxe/bigint.h>
+#include <ipxe/asn1.h>
+#include <ipxe/tables.h>
+
+/** RSA digestAlgorithm sequence contents */
+#define RSA_DIGESTALGORITHM_CONTENTS( ... ) \
+ ASN1_OID, VA_ARG_COUNT ( __VA_ARGS__ ), __VA_ARGS__, \
+ ASN1_NULL, 0x00
+
+/** RSA digestAlgorithm sequence */
+#define RSA_DIGESTALGORITHM( ... ) \
+ ASN1_SEQUENCE, \
+ VA_ARG_COUNT ( RSA_DIGESTALGORITHM_CONTENTS ( __VA_ARGS__ ) ), \
+ RSA_DIGESTALGORITHM_CONTENTS ( __VA_ARGS__ )
+
+/** RSA digest prefix */
+#define RSA_DIGEST_PREFIX( digest_size ) \
+ ASN1_OCTET_STRING, digest_size
+
+/** RSA digestInfo prefix */
+#define RSA_DIGESTINFO_PREFIX( digest_size, ... ) \
+ ASN1_SEQUENCE, \
+ ( VA_ARG_COUNT ( RSA_DIGESTALGORITHM ( __VA_ARGS__ ) ) + \
+ VA_ARG_COUNT ( RSA_DIGEST_PREFIX ( digest_size ) ) + \
+ digest_size ), \
+ RSA_DIGESTALGORITHM ( __VA_ARGS__ ), \
+ RSA_DIGEST_PREFIX ( digest_size )
+
+/** An RSA digestInfo prefix */
+struct rsa_digestinfo_prefix {
+ /** Digest algorithm */
+ struct digest_algorithm *digest;
+ /** Prefix */
+ const void *data;
+ /** Length of prefix */
+ size_t len;
+};
+
+/** RSA digestInfo prefix table */
+#define RSA_DIGESTINFO_PREFIXES \
+ __table ( struct rsa_digestinfo_prefix, "rsa_digestinfo_prefixes" )
+
+/** Declare an RSA digestInfo prefix */
+#define __rsa_digestinfo_prefix __table_entry ( RSA_DIGESTINFO_PREFIXES, 01 )
+
+/** An RSA context */
+struct rsa_context {
+ /** Allocated memory */
+ void *dynamic;
+ /** Modulus */
+ bigint_element_t *modulus0;
+ /** Modulus size */
+ unsigned int size;
+ /** Modulus length */
+ size_t max_len;
+ /** Exponent */
+ bigint_element_t *exponent0;
+ /** Exponent size */
+ unsigned int exponent_size;
+ /** Input buffer */
+ bigint_element_t *input0;
+ /** Output buffer */
+ bigint_element_t *output0;
+ /** Temporary working space for modular exponentiation */
+ void *tmp;
+};
+
+extern struct pubkey_algorithm rsa_algorithm;
+
+#endif /* _IPXE_RSA_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/sanboot.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/sanboot.h
new file mode 100644
index 00000000..14c8a5da
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/sanboot.h
@@ -0,0 +1,100 @@
+#ifndef _IPXE_SANBOOT_H
+#define _IPXE_SANBOOT_H
+
+/** @file
+ *
+ * iPXE sanboot API
+ *
+ * The sanboot API provides methods for hooking, unhooking,
+ * describing, and booting from SAN devices.
+ *
+ * The standard methods (readl()/writel() etc.) do not strictly check
+ * the type of the address parameter; this is because traditional
+ * usage does not necessarily provide the correct pointer type. For
+ * example, code written for ISA devices at fixed I/O addresses (such
+ * as the keyboard controller) tend to use plain integer constants for
+ * the address parameter.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/api.h>
+#include <config/sanboot.h>
+
+struct uri;
+
+/**
+ * Calculate static inline sanboot API function name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ */
+#define SANBOOT_INLINE( _subsys, _api_func ) \
+ SINGLE_API_INLINE ( SANBOOT_PREFIX_ ## _subsys, _api_func )
+
+/**
+ * Provide a sanboot API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_SANBOOT( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( SANBOOT_PREFIX_ ## _subsys, _api_func, _func )
+
+/**
+ * Provide a static inline sanboot API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ */
+#define PROVIDE_SANBOOT_INLINE( _subsys, _api_func ) \
+ PROVIDE_SINGLE_API_INLINE ( SANBOOT_PREFIX_ ## _subsys, _api_func )
+
+/* Include all architecture-independent sanboot API headers */
+#include <ipxe/null_sanboot.h>
+
+/* Include all architecture-dependent sanboot API headers */
+#include <bits/sanboot.h>
+
+/**
+ * Get default SAN drive number
+ *
+ * @ret drive Default drive number
+ */
+unsigned int san_default_drive ( void );
+
+/**
+ * Hook SAN device
+ *
+ * @v uri URI
+ * @v drive Drive number
+ * @ret rc Return status code
+ */
+int san_hook ( struct uri *uri, unsigned int drive );
+
+/**
+ * Unhook SAN device
+ *
+ * @v drive Drive number
+ */
+void san_unhook ( unsigned int drive );
+
+/**
+ * Attempt to boot from a SAN device
+ *
+ * @v drive Drive number
+ * @ret rc Return status code
+ */
+int san_boot ( unsigned int drive );
+
+/**
+ * Describe SAN device for SAN-booted operating system
+ *
+ * @v drive Drive number
+ * @ret rc Return status code
+ */
+int san_describe ( unsigned int drive );
+
+#endif /* _IPXE_SANBOOT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/script.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/script.h
new file mode 100644
index 00000000..33420dae
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/script.h
@@ -0,0 +1,16 @@
+#ifndef _IPXE_SCRIPT_H
+#define _IPXE_SCRIPT_H
+
+/** @file
+ *
+ * iPXE scripts
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/image.h>
+
+extern struct image_type script_image_type __image_type ( PROBE_NORMAL );
+
+#endif /* _IPXE_SCRIPT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/scsi.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/scsi.h
new file mode 100644
index 00000000..6dfb7f1e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/scsi.h
@@ -0,0 +1,310 @@
+#ifndef _IPXE_SCSI_H
+#define _IPXE_SCSI_H
+
+#include <stdint.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/interface.h>
+
+/** @file
+ *
+ * SCSI devices
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** Maximum block for READ/WRITE (10) commands */
+#define SCSI_MAX_BLOCK_10 0xffffffffULL
+
+/**
+ * @defgroup scsiops SCSI operation codes
+ * @{
+ */
+
+#define SCSI_OPCODE_READ_10 0x28 /**< READ (10) */
+#define SCSI_OPCODE_READ_16 0x88 /**< READ (16) */
+#define SCSI_OPCODE_WRITE_10 0x2a /**< WRITE (10) */
+#define SCSI_OPCODE_WRITE_16 0x8a /**< WRITE (16) */
+#define SCSI_OPCODE_READ_CAPACITY_10 0x25 /**< READ CAPACITY (10) */
+#define SCSI_OPCODE_SERVICE_ACTION_IN 0x9e /**< SERVICE ACTION IN */
+#define SCSI_SERVICE_ACTION_READ_CAPACITY_16 0x10 /**< READ CAPACITY (16) */
+#define SCSI_OPCODE_TEST_UNIT_READY 0x00 /**< TEST UNIT READY */
+
+/** @} */
+
+/**
+ * @defgroup scsiflags SCSI flags
+ * @{
+ */
+
+#define SCSI_FL_FUA_NV 0x02 /**< Force unit access to NVS */
+#define SCSI_FL_FUA 0x08 /**< Force unit access */
+#define SCSI_FL_DPO 0x10 /**< Disable cache page out */
+
+/** @} */
+
+/**
+ * @defgroup scsicdbs SCSI command data blocks
+ * @{
+ */
+
+/** A SCSI "READ (10)" CDB */
+struct scsi_cdb_read_10 {
+ /** Opcode (0x28) */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Start address
+ *
+ * This is a logical block number, in big-endian order.
+ */
+ uint32_t lba;
+ /** Group number */
+ uint8_t group;
+ /** Transfer length
+ *
+ * This is a logical block count, in big-endian order.
+ */
+ uint16_t len;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** A SCSI "READ (16)" CDB */
+struct scsi_cdb_read_16 {
+ /** Opcode (0x88) */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Start address
+ *
+ * This is a logical block number, in big-endian order.
+ */
+ uint64_t lba;
+ /** Transfer length
+ *
+ * This is a logical block count, in big-endian order.
+ */
+ uint32_t len;
+ /** Group number */
+ uint8_t group;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** A SCSI "WRITE (10)" CDB */
+struct scsi_cdb_write_10 {
+ /** Opcode (0x2a) */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Start address
+ *
+ * This is a logical block number, in big-endian order.
+ */
+ uint32_t lba;
+ /** Group number */
+ uint8_t group;
+ /** Transfer length
+ *
+ * This is a logical block count, in big-endian order.
+ */
+ uint16_t len;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** A SCSI "WRITE (16)" CDB */
+struct scsi_cdb_write_16 {
+ /** Opcode (0x8a) */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Start address
+ *
+ * This is a logical block number, in big-endian order.
+ */
+ uint64_t lba;
+ /** Transfer length
+ *
+ * This is a logical block count, in big-endian order.
+ */
+ uint32_t len;
+ /** Group number */
+ uint8_t group;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** A SCSI "READ CAPACITY (10)" CDB */
+struct scsi_cdb_read_capacity_10 {
+ /** Opcode (0x25) */
+ uint8_t opcode;
+ /** Reserved */
+ uint8_t reserved_a;
+ /** Logical block address
+ *
+ * Applicable only if the PMI bit is set.
+ */
+ uint32_t lba;
+ /** Reserved */
+ uint8_t reserved_b[3];
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** SCSI "READ CAPACITY (10)" parameter data */
+struct scsi_capacity_10 {
+ /** Maximum logical block number */
+ uint32_t lba;
+ /** Block length in bytes */
+ uint32_t blksize;
+} __attribute__ (( packed ));
+
+/** A SCSI "READ CAPACITY (16)" CDB */
+struct scsi_cdb_read_capacity_16 {
+ /** Opcode (0x9e) */
+ uint8_t opcode;
+ /** Service action */
+ uint8_t service_action;
+ /** Logical block address
+ *
+ * Applicable only if the PMI bit is set.
+ */
+ uint64_t lba;
+ /** Transfer length
+ *
+ * This is the size of the data-in buffer, in bytes.
+ */
+ uint32_t len;
+ /** Reserved */
+ uint8_t reserved;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** SCSI "READ CAPACITY (16)" parameter data */
+struct scsi_capacity_16 {
+ /** Maximum logical block number */
+ uint64_t lba;
+ /** Block length in bytes */
+ uint32_t blksize;
+ /** Reserved */
+ uint8_t reserved[20];
+} __attribute__ (( packed ));
+
+/** A SCSI "TEST UNIT READY" CDB */
+struct scsi_cdb_test_unit_ready {
+ /** Opcode (0x00) */
+ uint8_t opcode;
+ /** Reserved */
+ uint8_t reserved[4];
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** A SCSI Command Data Block */
+union scsi_cdb {
+ struct scsi_cdb_read_10 read10;
+ struct scsi_cdb_read_16 read16;
+ struct scsi_cdb_write_10 write10;
+ struct scsi_cdb_write_16 write16;
+ struct scsi_cdb_read_capacity_10 readcap10;
+ struct scsi_cdb_read_capacity_16 readcap16;
+ struct scsi_cdb_test_unit_ready testready;
+ unsigned char bytes[16];
+};
+
+/** printf() format for dumping a scsi_cdb */
+#define SCSI_CDB_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" \
+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
+
+/** printf() parameters for dumping a scsi_cdb */
+#define SCSI_CDB_DATA(cdb) \
+ (cdb).bytes[0], (cdb).bytes[1], (cdb).bytes[2], (cdb).bytes[3], \
+ (cdb).bytes[4], (cdb).bytes[5], (cdb).bytes[6], (cdb).bytes[7], \
+ (cdb).bytes[8], (cdb).bytes[9], (cdb).bytes[10], (cdb).bytes[11], \
+ (cdb).bytes[12], (cdb).bytes[13], (cdb).bytes[14], (cdb).bytes[15]
+
+/** @} */
+
+/** A SCSI LUN
+ *
+ * This is a four-level LUN as specified by SAM-2, in big-endian
+ * order.
+ */
+struct scsi_lun {
+ uint16_t u16[4];
+} __attribute__ (( packed ));
+
+/** printf() format for dumping a scsi_lun */
+#define SCSI_LUN_FORMAT "%04x-%04x-%04x-%04x"
+
+/** printf() parameters for dumping a scsi_lun */
+#define SCSI_LUN_DATA(lun) \
+ ntohs ( (lun).u16[0] ), ntohs ( (lun).u16[1] ), \
+ ntohs ( (lun).u16[2] ), ntohs ( (lun).u16[3] )
+
+/** A SCSI command information unit */
+struct scsi_cmd {
+ /** LUN */
+ struct scsi_lun lun;
+ /** CDB for this command */
+ union scsi_cdb cdb;
+ /** Data-out buffer (may be NULL) */
+ userptr_t data_out;
+ /** Data-out buffer length
+ *
+ * Must be zero if @c data_out is NULL
+ */
+ size_t data_out_len;
+ /** Data-in buffer (may be NULL) */
+ userptr_t data_in;
+ /** Data-in buffer length
+ *
+ * Must be zero if @c data_in is NULL
+ */
+ size_t data_in_len;
+};
+
+/** SCSI sense data */
+struct scsi_sns {
+ /** Response code */
+ uint8_t code;
+ /** Reserved */
+ uint8_t reserved;
+ /** Sense key */
+ uint8_t key;
+ /** Information */
+ uint32_t info;
+};
+
+/** SCSI sense key mask */
+#define SCSI_SENSE_KEY_MASK 0x0f
+
+/** A SCSI response information unit */
+struct scsi_rsp {
+ /** SCSI status code */
+ uint8_t status;
+ /** Data overrun (or negative underrun) */
+ ssize_t overrun;
+ /** Autosense data (if any) */
+ struct scsi_sns sense;
+};
+
+extern int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun );
+
+extern int scsi_command ( struct interface *control, struct interface *data,
+ struct scsi_cmd *command );
+#define scsi_command_TYPE( object_type ) \
+ typeof ( int ( object_type, struct interface *data, \
+ struct scsi_cmd *command ) )
+
+extern void scsi_response ( struct interface *intf, struct scsi_rsp *response );
+#define scsi_response_TYPE( object_type ) \
+ typeof ( void ( object_type, struct scsi_rsp *response ) )
+
+extern int scsi_open ( struct interface *block, struct interface *scsi,
+ struct scsi_lun *lun );
+
+#endif /* _IPXE_SCSI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/sec80211.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/sec80211.h
new file mode 100644
index 00000000..59ca3eb8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/sec80211.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _IPXE_SEC80211_H
+#define _IPXE_SEC80211_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/net80211.h>
+#include <errno.h>
+
+/** @file
+ *
+ * Definitions for general secured-network routines.
+ */
+
+int sec80211_detect ( struct io_buffer *iob,
+ enum net80211_security_proto *secprot,
+ enum net80211_crypto_alg *crypt );
+
+int sec80211_detect_ie ( int is_rsn, u8 *start, u8 *end,
+ enum net80211_security_proto *secprot,
+ enum net80211_crypto_alg *crypt );
+u8 * sec80211_find_rsn ( union ieee80211_ie *ie, void *ie_end,
+ int *is_rsn, u8 **end );
+
+int sec80211_install ( struct net80211_crypto **which,
+ enum net80211_crypto_alg crypt,
+ const void *key, int len, const void *rsc );
+
+u32 sec80211_rsn_get_crypto_desc ( enum net80211_crypto_alg crypt, int rsnie );
+u32 sec80211_rsn_get_akm_desc ( enum net80211_security_proto secprot,
+ int rsnie );
+enum net80211_crypto_alg sec80211_rsn_get_net80211_crypt ( u32 desc );
+
+#endif /* _IPXE_SEC80211_H */
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/segment.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/segment.h
new file mode 100644
index 00000000..37bed0e1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/segment.h
@@ -0,0 +1,17 @@
+#ifndef _IPXE_SEGMENT_H
+#define _IPXE_SEGMENT_H
+
+/**
+ * @file
+ *
+ * Executable image segments
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/uaccess.h>
+
+extern int prep_segment ( userptr_t segment, size_t filesz, size_t memsz );
+
+#endif /* _IPXE_SEGMENT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/serial.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/serial.h
new file mode 100644
index 00000000..c16e56ae
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/serial.h
@@ -0,0 +1,16 @@
+#ifndef _IPXE_SERIAL_H
+#define _IPXE_SERIAL_H
+
+/** @file
+ *
+ * Serial driver functions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern void serial_putc ( int ch );
+extern int serial_getc ( void );
+extern int serial_ischar ( void );
+
+#endif /* _IPXE_SERIAL_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/settings.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/settings.h
new file mode 100644
index 00000000..d0a142fa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/settings.h
@@ -0,0 +1,383 @@
+#ifndef _IPXE_SETTINGS_H
+#define _IPXE_SETTINGS_H
+
+/** @file
+ *
+ * Configuration settings
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/tables.h>
+#include <ipxe/list.h>
+#include <ipxe/refcnt.h>
+
+struct settings;
+struct in_addr;
+union uuid;
+
+/** A setting */
+struct setting {
+ /** Name
+ *
+ * This is the human-readable name for the setting.
+ */
+ const char *name;
+ /** Description */
+ const char *description;
+ /** Setting type
+ *
+ * This identifies the type of setting (e.g. string, IPv4
+ * address, etc.).
+ */
+ struct setting_type *type;
+ /** Setting tag, if applicable
+ *
+ * The setting tag is a numerical description of the setting
+ * (such as a DHCP option number, or an SMBIOS structure and
+ * field number).
+ *
+ * Users can construct tags for settings that are not
+ * explicitly known to iPXE using the generic syntax for
+ * numerical settings. For example, the setting name "60"
+ * will be interpreted as referring to DHCP option 60 (the
+ * vendor class identifier).
+ *
+ * This creates a potential for namespace collisions, since
+ * the interpretation of the numerical description will vary
+ * according to the settings block. When a user attempts to
+ * fetch a generic numerical setting, we need to ensure that
+ * only the intended settings block interprets the numerical
+ * description. (For example, we do not want to attempt to
+ * retrieve the subnet mask from SMBIOS, or the system UUID
+ * from DHCP.)
+ *
+ * This potential problem is resolved by allowing the setting
+ * tag to include a "magic" value indicating the
+ * interpretation to be placed upon the numerical description.
+ */
+ unsigned int tag;
+};
+
+/** Configuration setting table */
+#define SETTINGS __table ( struct setting, "settings" )
+
+/** Declare a configuration setting */
+#define __setting( setting_order ) __table_entry ( SETTINGS, setting_order )
+
+/** @defgroup setting_order Setting ordering
+ * @{
+ */
+
+#define SETTING_NETDEV 01 /**< Network device settings */
+#define SETTING_NETDEV_EXTRA 02 /**< Network device additional settings */
+#define SETTING_IPv4 03 /**< IPv4 settings */
+#define SETTING_IPv4_EXTRA 04 /**< IPv4 additional settings */
+#define SETTING_BOOT 05 /**< Generic boot settings */
+#define SETTING_BOOT_EXTRA 06 /**< Generic boot additional settings */
+#define SETTING_SANBOOT 07 /**< SAN boot settings */
+#define SETTING_SANBOOT_EXTRA 08 /**< SAN boot additional settings */
+#define SETTING_HOST 09 /**< Host identity settings */
+#define SETTING_HOST_EXTRA 10 /**< Host identity additional settings */
+#define SETTING_AUTH 11 /**< Authentication settings */
+#define SETTING_AUTH_EXTRA 12 /**< Authentication additional settings */
+#define SETTING_CRYPTO 13 /**< Cryptography settings */
+#define SETTING_MISC 14 /**< Miscellaneous settings */
+
+/** @} */
+
+/** Settings block operations */
+struct settings_operations {
+ /** Check applicability of setting
+ *
+ * @v settings Settings block
+ * @v setting Setting
+ * @ret applies Setting applies within this settings block
+ */
+ int ( * applies ) ( struct settings *settings,
+ struct setting *setting );
+ /** Store value of setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+ int ( * store ) ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len );
+ /** Fetch value of setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ *
+ * The actual length of the setting will be returned even if
+ * the buffer was too small.
+ */
+ int ( * fetch ) ( struct settings *settings, struct setting *setting,
+ void *data, size_t len );
+ /** Clear settings block
+ *
+ * @v settings Settings block
+ */
+ void ( * clear ) ( struct settings *settings );
+};
+
+/** A settings block */
+struct settings {
+ /** Reference counter */
+ struct refcnt *refcnt;
+ /** Name */
+ const char *name;
+ /** Tag magic
+ *
+ * This value will be ORed in to any numerical tags
+ * constructed by parse_setting_name().
+ */
+ unsigned int tag_magic;
+ /** Parent settings block */
+ struct settings *parent;
+ /** Sibling settings blocks */
+ struct list_head siblings;
+ /** Child settings blocks */
+ struct list_head children;
+ /** Settings block operations */
+ struct settings_operations *op;
+};
+
+/**
+ * A setting type
+ *
+ * This represents a type of setting (e.g. string, IPv4 address,
+ * etc.).
+ */
+struct setting_type {
+ /** Name
+ *
+ * This is the name exposed to the user (e.g. "string").
+ */
+ const char *name;
+ /** Parse formatted setting value
+ *
+ * @v value Formatted setting value
+ * @v buf Buffer to contain raw value
+ * @v len Length of buffer
+ * @ret len Length of raw value, or negative error
+ */
+ int ( * parse ) ( const char *value, void *buf, size_t len );
+ /** Format setting value
+ *
+ * @v raw Raw setting value
+ * @v raw_len Length of raw setting value
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+ int ( * format ) ( const void *raw, size_t raw_len, char *buf,
+ size_t len );
+};
+
+/** Configuration setting type table */
+#define SETTING_TYPES __table ( struct setting_type, "setting_types" )
+
+/** Declare a configuration setting type */
+#define __setting_type __table_entry ( SETTING_TYPES, 01 )
+
+/**
+ * A settings applicator
+ *
+ */
+struct settings_applicator {
+ /** Apply updated settings
+ *
+ * @ret rc Return status code
+ */
+ int ( * apply ) ( void );
+};
+
+/** Settings applicator table */
+#define SETTINGS_APPLICATORS \
+ __table ( struct settings_applicator, "settings_applicators" )
+
+/** Declare a settings applicator */
+#define __settings_applicator __table_entry ( SETTINGS_APPLICATORS, 01 )
+
+/**
+ * A generic settings block
+ *
+ */
+struct generic_settings {
+ /** Settings block */
+ struct settings settings;
+ /** List of generic settings */
+ struct list_head list;
+};
+
+extern struct settings_operations generic_settings_operations;
+extern int generic_settings_store ( struct settings *settings,
+ struct setting *setting,
+ const void *data, size_t len );
+extern int generic_settings_fetch ( struct settings *settings,
+ struct setting *setting,
+ void *data, size_t len );
+extern void generic_settings_clear ( struct settings *settings );
+
+extern int register_settings ( struct settings *settings,
+ struct settings *parent, const char *name );
+extern void unregister_settings ( struct settings *settings );
+
+extern int setting_applies ( struct settings *settings,
+ struct setting *setting );
+extern int store_setting ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len );
+extern int fetch_setting ( struct settings *settings, struct setting *setting,
+ void *data, size_t len );
+extern struct settings * fetch_setting_origin ( struct settings *settings,
+ struct setting *setting );
+extern int fetch_setting_len ( struct settings *settings,
+ struct setting *setting );
+extern int fetch_setting_copy ( struct settings *settings,
+ struct setting *setting, void **data );
+extern int fetch_string_setting ( struct settings *settings,
+ struct setting *setting,
+ char *data, size_t len );
+extern int fetch_string_setting_copy ( struct settings *settings,
+ struct setting *setting,
+ char **data );
+extern int fetch_ipv4_array_setting ( struct settings *settings,
+ struct setting *setting,
+ struct in_addr *inp,
+ unsigned int count );
+extern int fetch_ipv4_setting ( struct settings *settings,
+ struct setting *setting, struct in_addr *inp );
+extern int fetch_int_setting ( struct settings *settings,
+ struct setting *setting, long *value );
+extern int fetch_uint_setting ( struct settings *settings,
+ struct setting *setting,
+ unsigned long *value );
+extern long fetch_intz_setting ( struct settings *settings,
+ struct setting *setting );
+extern unsigned long fetch_uintz_setting ( struct settings *settings,
+ struct setting *setting );
+extern int fetch_uuid_setting ( struct settings *settings,
+ struct setting *setting, union uuid *uuid );
+extern void clear_settings ( struct settings *settings );
+extern int setting_cmp ( struct setting *a, struct setting *b );
+
+extern const char * settings_name ( struct settings *settings );
+extern struct settings * find_settings ( const char *name );
+extern struct setting * find_setting ( const char *name );
+
+extern int setting_name ( struct settings *settings, struct setting *setting,
+ char *buf, size_t len );
+extern int fetchf_setting ( struct settings *settings, struct setting *setting,
+ char *buf, size_t len );
+extern int storef_setting ( struct settings *settings,
+ struct setting *setting,
+ const char *value );
+extern int storef_named_setting ( const char *name, const char *value );
+extern int fetchf_named_setting ( const char *name, char *name_buf,
+ size_t name_len, char *value_buf,
+ size_t value_len );
+extern char * expand_settings ( const char *string );
+
+extern struct setting_type setting_type_string __setting_type;
+extern struct setting_type setting_type_uristring __setting_type;
+extern struct setting_type setting_type_ipv4 __setting_type;
+extern struct setting_type setting_type_int8 __setting_type;
+extern struct setting_type setting_type_int16 __setting_type;
+extern struct setting_type setting_type_int32 __setting_type;
+extern struct setting_type setting_type_uint8 __setting_type;
+extern struct setting_type setting_type_uint16 __setting_type;
+extern struct setting_type setting_type_uint32 __setting_type;
+extern struct setting_type setting_type_hex __setting_type;
+extern struct setting_type setting_type_hexhyp __setting_type;
+extern struct setting_type setting_type_uuid __setting_type;
+
+extern struct setting ip_setting __setting ( SETTING_IPv4 );
+extern struct setting netmask_setting __setting ( SETTING_IPv4 );
+extern struct setting gateway_setting __setting ( SETTING_IPv4 );
+extern struct setting dns_setting __setting ( SETTING_IPv4_EXTRA );
+extern struct setting hostname_setting __setting ( SETTING_HOST );
+extern struct setting filename_setting __setting ( SETTING_BOOT );
+extern struct setting root_path_setting __setting ( SETTING_SANBOOT );
+extern struct setting username_setting __setting ( SETTING_AUTH );
+extern struct setting password_setting __setting ( SETTING_AUTH );
+extern struct setting priority_setting __setting ( SETTING_MISC );
+extern struct setting uuid_setting __setting ( SETTING_HOST );
+extern struct setting next_server_setting __setting ( SETTING_BOOT );
+extern struct setting mac_setting __setting ( SETTING_NETDEV );
+extern struct setting busid_setting __setting ( SETTING_NETDEV );
+
+/**
+ * Initialise a settings block
+ *
+ * @v settings Settings block
+ * @v op Settings block operations
+ * @v refcnt Containing object reference counter, or NULL
+ * @v tag_magic Tag magic
+ */
+static inline void settings_init ( struct settings *settings,
+ struct settings_operations *op,
+ struct refcnt *refcnt,
+ unsigned int tag_magic ) {
+ INIT_LIST_HEAD ( &settings->siblings );
+ INIT_LIST_HEAD ( &settings->children );
+ settings->op = op;
+ settings->refcnt = refcnt;
+ settings->tag_magic = tag_magic;
+}
+
+/**
+ * Initialise a settings block
+ *
+ * @v generics Generic settings block
+ * @v refcnt Containing object reference counter, or NULL
+ */
+static inline void generic_settings_init ( struct generic_settings *generics,
+ struct refcnt *refcnt ) {
+ settings_init ( &generics->settings, &generic_settings_operations,
+ refcnt, 0 );
+ INIT_LIST_HEAD ( &generics->list );
+}
+
+/**
+ * Delete setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to delete
+ * @ret rc Return status code
+ */
+static inline int delete_setting ( struct settings *settings,
+ struct setting *setting ) {
+ return store_setting ( settings, setting, NULL, 0 );
+}
+
+/**
+ * Delete named setting
+ *
+ * @v name Name of setting
+ * @ret rc Return status code
+ */
+static inline int delete_named_setting ( const char *name ) {
+ return storef_named_setting ( name, NULL );
+}
+
+/**
+ * Check existence of setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @ret exists Setting exists
+ */
+static inline int setting_exists ( struct settings *settings,
+ struct setting *setting ) {
+ return ( fetch_setting_len ( settings, setting ) >= 0 );
+}
+
+#endif /* _IPXE_SETTINGS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/settings_ui.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/settings_ui.h
new file mode 100644
index 00000000..5f7be30c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/settings_ui.h
@@ -0,0 +1,16 @@
+#ifndef _IPXE_SETTINGS_UI_H
+#define _IPXE_SETTINGS_UI_H
+
+/** @file
+ *
+ * Option configuration console
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct settings;
+
+extern int settings_ui ( struct settings *settings ) __nonnull;
+
+#endif /* _IPXE_SETTINGS_UI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/sha1.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/sha1.h
new file mode 100644
index 00000000..a97035ec
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/sha1.h
@@ -0,0 +1,80 @@
+#ifndef _IPXE_SHA1_H
+#define _IPXE_SHA1_H
+
+/** @file
+ *
+ * SHA-1 algorithm
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/crypto.h>
+
+/** An SHA-1 digest */
+struct sha1_digest {
+ /** Hash output */
+ uint32_t h[5];
+};
+
+/** An SHA-1 data block */
+union sha1_block {
+ /** Raw bytes */
+ uint8_t byte[64];
+ /** Raw dwords */
+ uint32_t dword[16];
+ /** Final block structure */
+ struct {
+ /** Padding */
+ uint8_t pad[56];
+ /** Length in bits */
+ uint64_t len;
+ } final;
+};
+
+/** SHA-1 digest and data block
+ *
+ * The order of fields within this structure is designed to minimise
+ * code size.
+ */
+struct sha1_digest_data {
+ /** Digest of data already processed */
+ struct sha1_digest digest;
+ /** Accumulated data */
+ union sha1_block data;
+} __attribute__ (( packed ));
+
+/** SHA-1 digest and data block */
+union sha1_digest_data_dwords {
+ /** Digest and data block */
+ struct sha1_digest_data dd;
+ /** Raw dwords */
+ uint32_t dword[ sizeof ( struct sha1_digest_data ) /
+ sizeof ( uint32_t ) ];
+};
+
+/** An SHA-1 context */
+struct sha1_context {
+ /** Amount of accumulated data */
+ size_t len;
+ /** Digest and accumulated data */
+ union sha1_digest_data_dwords ddd;
+} __attribute__ (( packed ));
+
+/** SHA-1 context size */
+#define SHA1_CTX_SIZE sizeof ( struct sha1_context )
+
+/** SHA-1 digest size */
+#define SHA1_DIGEST_SIZE sizeof ( struct sha1_digest )
+
+extern struct digest_algorithm sha1_algorithm;
+
+extern void prf_sha1 ( const void *key, size_t key_len, const char *label,
+ const void *data, size_t data_len, void *prf,
+ size_t prf_len );
+extern void pbkdf2_sha1 ( const void *passphrase, size_t pass_len,
+ const void *salt, size_t salt_len,
+ int iterations, void *key, size_t key_len );
+
+#endif /* _IPXE_SHA1_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/sha256.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/sha256.h
new file mode 100644
index 00000000..9aa9f3e5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/sha256.h
@@ -0,0 +1,73 @@
+#ifndef _IPXE_SHA256_H
+#define _IPXE_SHA256_H
+
+/** @file
+ *
+ * SHA-256 algorithm
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/crypto.h>
+
+/** An SHA-256 digest */
+struct sha256_digest {
+ /** Hash output */
+ uint32_t h[8];
+};
+
+/** An SHA-256 data block */
+union sha256_block {
+ /** Raw bytes */
+ uint8_t byte[64];
+ /** Raw dwords */
+ uint32_t dword[16];
+ /** Final block structure */
+ struct {
+ /** Padding */
+ uint8_t pad[56];
+ /** Length in bits */
+ uint64_t len;
+ } final;
+};
+
+/** SHA-256 digest and data block
+ *
+ * The order of fields within this structure is designed to minimise
+ * code size.
+ */
+struct sha256_digest_data {
+ /** Digest of data already processed */
+ struct sha256_digest digest;
+ /** Accumulated data */
+ union sha256_block data;
+} __attribute__ (( packed ));
+
+/** SHA-256 digest and data block */
+union sha256_digest_data_dwords {
+ /** Digest and data block */
+ struct sha256_digest_data dd;
+ /** Raw dwords */
+ uint32_t dword[ sizeof ( struct sha256_digest_data ) /
+ sizeof ( uint32_t ) ];
+};
+
+/** An SHA-256 context */
+struct sha256_context {
+ /** Amount of accumulated data */
+ size_t len;
+ /** Digest and accumulated data */
+ union sha256_digest_data_dwords ddd;
+} __attribute__ (( packed ));
+
+/** SHA-256 context size */
+#define SHA256_CTX_SIZE sizeof ( struct sha256_context )
+
+/** SHA-256 digest size */
+#define SHA256_DIGEST_SIZE sizeof ( struct sha256_digest )
+
+extern struct digest_algorithm sha256_algorithm;
+
+#endif /* _IPXE_SHA256_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/shell.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/shell.h
new file mode 100644
index 00000000..faa32f42
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/shell.h
@@ -0,0 +1,36 @@
+#ifndef _IPXE_SHELL_H
+#define _IPXE_SHELL_H
+
+/** @file
+ *
+ * Minimal command shell
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** Shell stop states */
+enum shell_stop_state {
+ /** Continue processing */
+ SHELL_CONTINUE = 0,
+ /**
+ * Stop processing current command line
+ *
+ * This is the stop state entered by commands that change the flow
+ * of execution, such as "goto".
+ */
+ SHELL_STOP_COMMAND = 1,
+ /**
+ * Stop processing commands
+ *
+ * This is the stop state entered by commands that terminate
+ * the flow of execution, such as "exit".
+ */
+ SHELL_STOP_COMMAND_SEQUENCE = 2,
+};
+
+extern void shell_stop ( int stop );
+extern int shell_stopped ( int stop );
+extern int shell ( void );
+
+#endif /* _IPXE_SHELL_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/smbios.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/smbios.h
new file mode 100644
index 00000000..fcf149ea
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/smbios.h
@@ -0,0 +1,162 @@
+#ifndef _IPXE_SMBIOS_H
+#define _IPXE_SMBIOS_H
+
+/** @file
+ *
+ * System Management BIOS
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/api.h>
+#include <config/general.h>
+#include <ipxe/uaccess.h>
+
+/**
+ * Provide an SMBIOS API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_SMBIOS( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( SMBIOS_PREFIX_ ## _subsys, _api_func, _func )
+
+/* Include all architecture-independent SMBIOS API headers */
+#include <ipxe/efi/efi_smbios.h>
+#include <ipxe/linux/linux_smbios.h>
+
+/* Include all architecture-dependent SMBIOS API headers */
+#include <bits/smbios.h>
+
+/** Signature for SMBIOS entry point */
+#define SMBIOS_SIGNATURE \
+ ( ( '_' << 0 ) + ( 'S' << 8 ) + ( 'M' << 16 ) + ( '_' << 24 ) )
+
+/**
+ * SMBIOS entry point
+ *
+ * This is the single table which describes the list of SMBIOS
+ * structures. It is located by scanning through the BIOS segment.
+ */
+struct smbios_entry {
+ /** Signature
+ *
+ * Must be equal to SMBIOS_SIGNATURE
+ */
+ uint32_t signature;
+ /** Checksum */
+ uint8_t checksum;
+ /** Length */
+ uint8_t len;
+ /** Major version */
+ uint8_t major;
+ /** Minor version */
+ uint8_t minor;
+ /** Maximum structure size */
+ uint16_t max;
+ /** Entry point revision */
+ uint8_t revision;
+ /** Formatted area */
+ uint8_t formatted[5];
+ /** DMI Signature */
+ uint8_t dmi_signature[5];
+ /** DMI checksum */
+ uint8_t dmi_checksum;
+ /** Structure table length */
+ uint16_t smbios_len;
+ /** Structure table address */
+ uint32_t smbios_address;
+ /** Number of SMBIOS structures */
+ uint16_t smbios_count;
+ /** BCD revision */
+ uint8_t bcd_revision;
+} __attribute__ (( packed ));
+
+/** An SMBIOS structure header */
+struct smbios_header {
+ /** Type */
+ uint8_t type;
+ /** Length */
+ uint8_t len;
+ /** Handle */
+ uint16_t handle;
+} __attribute__ (( packed ));
+
+/** SMBIOS structure descriptor */
+struct smbios_structure {
+ /** Copy of SMBIOS structure header */
+ struct smbios_header header;
+ /** Offset of structure within SMBIOS */
+ size_t offset;
+ /** Length of strings section */
+ size_t strings_len;
+};
+
+/** SMBIOS system information structure */
+struct smbios_system_information {
+ /** SMBIOS structure header */
+ struct smbios_header header;
+ /** Manufacturer string */
+ uint8_t manufacturer;
+ /** Product string */
+ uint8_t product;
+ /** Version string */
+ uint8_t version;
+ /** Serial number string */
+ uint8_t serial;
+ /** UUID */
+ uint8_t uuid[16];
+ /** Wake-up type */
+ uint8_t wakeup;
+} __attribute__ (( packed ));
+
+/** SMBIOS system information structure type */
+#define SMBIOS_TYPE_SYSTEM_INFORMATION 1
+
+/** SMBIOS enclosure information structure */
+struct smbios_enclosure_information {
+ /** SMBIOS structure header */
+ struct smbios_header header;
+ /** Manufacturer string */
+ uint8_t manufacturer;
+ /** Type string */
+ uint8_t type;
+ /** Version string */
+ uint8_t version;
+ /** Serial number string */
+ uint8_t serial;
+ /** Asset tag */
+ uint8_t asset_tag;
+} __attribute__ (( packed ));
+
+/** SMBIOS enclosure information structure type */
+#define SMBIOS_TYPE_ENCLOSURE_INFORMATION 3
+
+/**
+ * SMBIOS entry point descriptor
+ *
+ * This contains the information from the SMBIOS entry point that we
+ * care about.
+ */
+struct smbios {
+ /** Start of SMBIOS structures */
+ userptr_t address;
+ /** Length of SMBIOS structures */
+ size_t len;
+ /** Number of SMBIOS structures */
+ unsigned int count;
+};
+
+extern int find_smbios ( struct smbios *smbios );
+extern int find_smbios_structure ( unsigned int type,
+ struct smbios_structure *structure );
+extern int read_smbios_structure ( struct smbios_structure *structure,
+ void *data, size_t len );
+extern int read_smbios_string ( struct smbios_structure *structure,
+ unsigned int index,
+ void *data, size_t len );
+
+#endif /* _IPXE_SMBIOS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/socket.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/socket.h
new file mode 100644
index 00000000..320dae4f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/socket.h
@@ -0,0 +1,102 @@
+#ifndef _IPXE_SOCKET_H
+#define _IPXE_SOCKET_H
+
+/** @file
+ *
+ * Socket addresses
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/**
+ * @defgroup commtypes Communication semantics
+ *
+ * @{
+ */
+
+/** Connection-based, reliable streams */
+extern int tcp_sock_stream;
+#define TCP_SOCK_STREAM 0x1
+#define SOCK_STREAM tcp_sock_stream
+
+/** Connectionless, unreliable streams */
+extern int udp_sock_dgram;
+#define UDP_SOCK_DGRAM 0x2
+#define SOCK_DGRAM udp_sock_dgram
+
+/** @} */
+
+/**
+ * Name communication semantics
+ *
+ * @v semantics Communication semantics (e.g. SOCK_STREAM)
+ * @ret name Name of communication semantics
+ */
+static inline __attribute__ (( always_inline )) const char *
+socket_semantics_name ( int semantics ) {
+ /* Cannot use a switch() because of the {TCP_UDP}_SOCK_XXX hack */
+ if ( semantics == SOCK_STREAM ) {
+ return "SOCK_STREAM";
+ } else if ( semantics == SOCK_DGRAM ) {
+ return "SOCK_DGRAM";
+ } else {
+ return "SOCK_UNKNOWN";
+ }
+}
+
+/**
+ * @defgroup addrfam Address families
+ *
+ * @{
+ */
+#define AF_INET 1 /**< IPv4 Internet addresses */
+#define AF_INET6 2 /**< IPv6 Internet addresses */
+#define AF_FC 3 /**< Fibre Channel addresses */
+/** @} */
+
+/**
+ * Name address family
+ *
+ * @v family Address family (e.g. AF_INET)
+ * @ret name Name of address family
+ */
+static inline __attribute__ (( always_inline )) const char *
+socket_family_name ( int family ) {
+ switch ( family ) {
+ case AF_INET: return "AF_INET";
+ case AF_INET6: return "AF_INET6";
+ default: return "AF_UNKNOWN";
+ }
+}
+
+/** A socket address family */
+typedef uint16_t sa_family_t;
+
+/** Length of a @c struct @c sockaddr */
+#define SA_LEN 32
+
+/**
+ * Generalized socket address structure
+ *
+ * This contains the fields common to socket addresses for all address
+ * families.
+ */
+struct sockaddr {
+ /** Socket address family
+ *
+ * This is an AF_XXX constant.
+ */
+ sa_family_t sa_family;
+ /** Padding
+ *
+ * This ensures that a struct @c sockaddr_tcpip is large
+ * enough to hold a socket address for any TCP/IP address
+ * family.
+ */
+ char pad[ SA_LEN - sizeof ( sa_family_t ) ];
+} __attribute__ (( may_alias ));
+
+#endif /* _IPXE_SOCKET_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/spi.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/spi.h
new file mode 100644
index 00000000..d92d1aec
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/spi.h
@@ -0,0 +1,258 @@
+#ifndef _IPXE_SPI_H
+#define _IPXE_SPI_H
+
+/** @file
+ *
+ * SPI interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/nvs.h>
+
+/**
+ * @defgroup spicmds SPI commands
+ * @{
+ */
+
+/** Write status register */
+#define SPI_WRSR 0x01
+
+/** Write data to memory array */
+#define SPI_WRITE 0x02
+
+/** Read data from memory array */
+#define SPI_READ 0x03
+
+/** Reset write enable latch */
+#define SPI_WRDI 0x04
+
+/** Read status register */
+#define SPI_RDSR 0x05
+
+/** Set write enable latch */
+#define SPI_WREN 0x06
+
+/**
+ * @defgroup atmelcmds Atmel-specific SPI commands
+ * @{
+ */
+
+/** Erase one sector in memory array (Not supported on all devices) */
+#define ATMEL_SECTOR_ERASE 0x52
+
+/** Erase all sections in memory array (Not supported on all devices) */
+#define ATMEL_CHIP_ERASE 0x62
+
+/** Read manufacturer and product ID (Not supported on all devices) */
+#define ATMEL_RDID 0x15
+
+/** @} */
+
+/** @} */
+
+/**
+ * @defgroup spistatus SPI status register bits (not present on all devices)
+ * @{
+ */
+
+/** Write-protect pin enabled */
+#define SPI_STATUS_WPEN 0x80
+
+/** Block protection bit 2 */
+#define SPI_STATUS_BP2 0x10
+
+/** Block protection bit 1 */
+#define SPI_STATUS_BP1 0x08
+
+/** Block protection bit 0 */
+#define SPI_STATUS_BP0 0x04
+
+/** State of the write enable latch */
+#define SPI_STATUS_WEN 0x02
+
+/** Device busy flag */
+#define SPI_STATUS_NRDY 0x01
+
+/** @} */
+
+/**
+ * An SPI device
+ *
+ * This data structure represents a physical SPI device attached to an
+ * SPI bus.
+ */
+struct spi_device {
+ /** NVS device */
+ struct nvs_device nvs;
+ /** SPI bus to which device is attached */
+ struct spi_bus *bus;
+ /** Slave number */
+ unsigned int slave;
+ /** Command length, in bits */
+ unsigned int command_len;
+ /** Address length, in bits */
+ unsigned int address_len;
+ /** Address is munged
+ *
+ * Some devices with 9-bit addresses (e.g. AT25040A EEPROM)
+ * use bit 3 of the command byte as address bit A8, rather
+ * than having a two-byte address. If this flag is set, then
+ * commands should be munged in this way.
+ */
+ unsigned int munge_address : 1;
+};
+
+/**
+ * SPI magic autodetection address length
+ *
+ * Set @c spi_device::address_len to @c SPI_AUTODETECT_ADDRESS_LEN if
+ * the address length should be autodetected.
+ */
+#define SPI_AUTODETECT_ADDRESS_LEN 0
+
+static inline __attribute__ (( always_inline )) struct spi_device *
+nvs_to_spi ( struct nvs_device *nvs ) {
+ return container_of ( nvs, struct spi_device, nvs );
+}
+
+/**
+ * An SPI bus
+ *
+ * This data structure represents an SPI bus controller capable of
+ * issuing commands to attached SPI devices.
+ */
+struct spi_bus {
+ /** SPI interface mode
+ *
+ * This is the bitwise OR of zero or more of @c SPI_MODE_CPHA
+ * and @c SPI_MODE_CPOL. It is also the number conventionally
+ * used to describe the SPI interface mode. For example, SPI
+ * mode 1 is the mode in which CPOL=0 and CPHA=1, which
+ * therefore corresponds to a mode value of (0|SPI_MODE_CPHA)
+ * which, happily, equals 1.
+ */
+ unsigned int mode;
+ /**
+ * Read/write data via SPI bus
+ *
+ * @v bus SPI bus
+ * @v device SPI device
+ * @v command Command
+ * @v address Address to read/write (<0 for no address)
+ * @v data_out TX data buffer (or NULL)
+ * @v data_in RX data buffer (or NULL)
+ * @v len Length of data buffer(s)
+ *
+ * This issues the specified command and optional address to
+ * the SPI device, then reads and/or writes data to/from the
+ * data buffers.
+ */
+ int ( * rw ) ( struct spi_bus *bus, struct spi_device *device,
+ unsigned int command, int address,
+ const void *data_out, void *data_in, size_t len );
+};
+
+/** Clock phase (CPHA) mode bit
+ *
+ * Phase 0 is sample on rising edge, shift data on falling edge.
+ *
+ * Phase 1 is shift data on rising edge, sample data on falling edge.
+ */
+#define SPI_MODE_CPHA 0x01
+
+/** Clock polarity (CPOL) mode bit
+ *
+ * This bit reflects the idle state of the clock line (SCLK).
+ */
+#define SPI_MODE_CPOL 0x02
+
+/** Slave select polarity mode bit
+ *
+ * This bit reflects that active state of the slave select lines. It
+ * is not part of the normal SPI mode number (which covers only @c
+ * SPI_MODE_CPOL and @c SPI_MODE_CPHA), but is included here for
+ * convenience.
+ */
+#define SPI_MODE_SSPOL 0x10
+
+/** Microwire-compatible mode
+ *
+ * This is SPI mode 1 (i.e. CPOL=0, CPHA=1), and is compatible with
+ * the original Microwire protocol.
+ */
+#define SPI_MODE_MICROWIRE 1
+
+/** Microwire/Plus-compatible mode
+ *
+ * This is SPI mode 0 (i.e. CPOL=0, CPHA=0), and is compatible with
+ * the Microwire/Plus protocol
+ */
+#define SPI_MODE_MICROWIRE_PLUS 0
+
+/** Threewire-compatible mode
+ *
+ * This mode is compatible with Atmel's series of "three-wire"
+ * interfaces.
+ */
+#define SPI_MODE_THREEWIRE ( SPI_MODE_MICROWIRE_PLUS | SPI_MODE_SSPOL )
+
+extern int spi_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len );
+extern int spi_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len );
+
+/**
+ * @defgroup spidevs SPI device types
+ * @{
+ */
+
+static inline __attribute__ (( always_inline )) void
+init_spi ( struct spi_device *device ) {
+ device->nvs.word_len_log2 = 0;
+ device->command_len = 8,
+ device->nvs.read = spi_read;
+ device->nvs.write = spi_write;
+}
+
+/** Atmel AT25F1024 serial flash */
+static inline __attribute__ (( always_inline )) void
+init_at25f1024 ( struct spi_device *device ) {
+ device->address_len = 24;
+ device->nvs.size = ( 128 * 1024 );
+ device->nvs.block_size = 256;
+ init_spi ( device );
+}
+
+/** Atmel 25040 serial EEPROM */
+static inline __attribute__ (( always_inline )) void
+init_at25040 ( struct spi_device *device ) {
+ device->address_len = 8;
+ device->munge_address = 1;
+ device->nvs.size = 512;
+ device->nvs.block_size = 8;
+ init_spi ( device );
+}
+
+/** ST M25P32 serial flash */
+static inline __attribute__ (( always_inline )) void
+init_m25p32 ( struct spi_device *device ) {
+ device->address_len = 24;
+ device->nvs.size = ( 4 * 1024 * 1024 );
+ device->nvs.block_size = 256;
+ init_spi ( device );
+}
+
+/** Microchip 25XX640 serial EEPROM */
+static inline __attribute__ (( always_inline )) void
+init_mc25xx640 ( struct spi_device *device ) {
+ device->address_len = 16;
+ device->nvs.size = ( 8 * 1024 );
+ device->nvs.block_size = 32;
+ init_spi ( device );
+}
+
+/** @} */
+
+#endif /* _IPXE_SPI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/spi_bit.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/spi_bit.h
new file mode 100644
index 00000000..9cfa7b82
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/spi_bit.h
@@ -0,0 +1,63 @@
+#ifndef _IPXE_SPI_BIT_H
+#define _IPXE_SPI_BIT_H
+
+/** @file
+ *
+ * SPI bit-bashing interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/spi.h>
+#include <ipxe/bitbash.h>
+
+/** A bit-bashing SPI bus */
+struct spi_bit_basher {
+ /** SPI bus */
+ struct spi_bus bus;
+ /** Bit-bashing interface */
+ struct bit_basher basher;
+ /** Endianness of data
+ *
+ * SPI commands and addresses are always big-endian (i.e. MSB
+ * transmitted first on the wire), but some cards
+ * (e.g. natsemi) choose to regard the data stored in the
+ * EEPROM as little-endian (i.e. LSB transmitted first on the
+ * wire).
+ */
+ int endianness;
+};
+
+/** Bit indices used for SPI bit-bashing interface */
+enum {
+ /** Serial clock */
+ SPI_BIT_SCLK = 0,
+ /** Master Out Slave In */
+ SPI_BIT_MOSI,
+ /** Master In Slave Out */
+ SPI_BIT_MISO,
+ /** Slave 0 select */
+ SPI_BIT_SS0,
+};
+
+/**
+ * Determine bit index for a particular slave
+ *
+ * @v slave Slave number
+ * @ret index Bit index (i.e. SPI_BIT_SSN, where N=slave)
+ */
+#define SPI_BIT_SS( slave ) ( SPI_BIT_SS0 + (slave) )
+
+/** Delay between SCLK transitions */
+#define SPI_BIT_UDELAY 1
+
+/** SPI bit basher treats data as big-endian */
+#define SPI_BIT_BIG_ENDIAN 0
+
+/** SPI bit basher treats data as little-endian */
+#define SPI_BIT_LITTLE_ENDIAN 1
+
+extern void init_spi_bit_basher ( struct spi_bit_basher *spibit );
+
+#endif /* _IPXE_SPI_BIT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/srp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/srp.h
new file mode 100644
index 00000000..8d7f799c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/srp.h
@@ -0,0 +1,833 @@
+#ifndef _IPXE_SRP_H
+#define _IPXE_SRP_H
+
+/** @file
+ *
+ * SCSI RDMA Protocol
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdint.h>
+#include <byteswap.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/scsi.h>
+#include <ipxe/acpi.h>
+
+/*****************************************************************************
+ *
+ * Common fields
+ *
+ *****************************************************************************
+ */
+
+/** An SRP information unit tag */
+union srp_tag {
+ uint8_t bytes[8];
+ uint32_t dwords[2];
+} __attribute__ (( packed ));
+
+/** SRP tag magic marker */
+#define SRP_TAG_MAGIC 0x69505845
+
+/** An SRP port ID */
+union srp_port_id {
+ uint8_t bytes[16];
+ uint32_t dwords[4];
+} __attribute__ (( packed ));
+
+/** SRP information unit common fields */
+struct srp_common {
+ /** Information unit type */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[7];
+ /** Tag */
+ union srp_tag tag;
+} __attribute__ (( packed ));
+
+/*****************************************************************************
+ *
+ * Login request
+ *
+ *****************************************************************************
+ */
+
+/** An SRP login request information unit */
+struct srp_login_req {
+ /** Information unit type
+ *
+ * This must be @c SRP_LOGIN_REQ
+ */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[7];
+ /** Tag */
+ union srp_tag tag;
+ /** Requested maximum initiator to target IU length */
+ uint32_t max_i_t_iu_len;
+ /** Reserved */
+ uint8_t reserved1[4];
+ /** Required buffer formats
+ *
+ * This is the bitwise OR of one or more @c
+ * SRP_LOGIN_REQ_FMT_XXX constants.
+ */
+ uint16_t required_buffer_formats;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more @c
+ * SRP_LOGIN_REQ_FLAG_XXX and @c SRP_LOGIN_REQ_MCA_XXX
+ * constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved2[5];
+ /** Initiator port identifier */
+ union srp_port_id initiator;
+ /** Target port identifier */
+ union srp_port_id target;
+} __attribute__ (( packed ));
+
+/** Type of an SRP login request */
+#define SRP_LOGIN_REQ 0x00
+
+/** Require indirect data buffer descriptor format */
+#define SRP_LOGIN_REQ_FMT_IDBD 0x04
+
+/** Require direct data buffer descriptor format */
+#define SRP_LOGIN_REQ_FMT_DDBD 0x02
+
+/** Use solicited notification for asynchronous events */
+#define SRP_LOGIN_REQ_FLAG_AESOLNT 0x40
+
+/** Use solicited notification for credit request */
+#define SRP_LOGIN_REQ_FLAG_CRSOLNT 0x20
+
+/** Use solicited notification for logouts */
+#define SRP_LOGIN_REQ_FLAG_LOSOLNT 0x10
+
+/** Multi-channel action mask */
+#define SRP_LOGIN_REQ_MCA_MASK 0x03
+
+/** Single RDMA channel operation */
+#define SRP_LOGIN_REQ_MCA_SINGLE_CHANNEL 0x00
+
+/** Multiple independent RDMA channel operation */
+#define SRP_LOGIN_REQ_MCA_MULTIPLE_CHANNELS 0x01
+
+/*****************************************************************************
+ *
+ * Login response
+ *
+ *****************************************************************************
+ */
+
+/** An SRP login response */
+struct srp_login_rsp {
+ /** Information unit type
+ *
+ * This must be @c SRP_LOGIN_RSP
+ */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[3];
+ /** Request limit delta */
+ uint32_t request_limit_delta;
+ /** Tag */
+ union srp_tag tag;
+ /** Maximum initiator to target IU length */
+ uint32_t max_i_t_iu_len;
+ /** Maximum target to initiator IU length */
+ uint32_t max_t_i_iu_len;
+ /** Supported buffer formats
+ *
+ * This is the bitwise OR of one or more @c
+ * SRP_LOGIN_RSP_FMT_XXX constants.
+ */
+ uint16_t supported_buffer_formats;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more @c
+ * SRP_LOGIN_RSP_FLAG_XXX and @c SRP_LOGIN_RSP_MCR_XXX
+ * constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved1[25];
+} __attribute__ (( packed ));
+
+/** Type of an SRP login response */
+#define SRP_LOGIN_RSP 0xc0
+
+/** Indirect data buffer descriptor format supported */
+#define SRP_LOGIN_RSP_FMT_IDBD 0x04
+
+/** Direct data buffer descriptor format supported */
+#define SRP_LOGIN_RSP_FMT_DDBD 0x02
+
+/** Solicited notification is supported */
+#define SRP_LOGIN_RSP_FLAG_SOLNTSUP 0x10
+
+/** Multi-channel result mask */
+#define SRP_LOGIN_RSP_MCR_MASK 0x03
+
+/** No existing RDMA channels were associated with the same I_T nexus */
+#define SRP_LOGIN_RSP_MCR_NO_EXISTING_CHANNELS 0x00
+
+/** One or more existing RDMA channels were terminated */
+#define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_TERMINATED 0x01
+
+/** One or more existing RDMA channels continue to operate independently */
+#define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_CONTINUE 0x02
+
+/*****************************************************************************
+ *
+ * Login rejection
+ *
+ *****************************************************************************
+ */
+
+/** An SRP login rejection */
+struct srp_login_rej {
+ /** Information unit type
+ *
+ * This must be @c SRP_LOGIN_REJ
+ */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[3];
+ /** Reason
+ *
+ * This is a @c SRP_LOGIN_REJ_REASON_XXX constant.
+ */
+ uint32_t reason;
+ /** Tag */
+ union srp_tag tag;
+ /** Reserved */
+ uint8_t reserved1[8];
+ /** Supported buffer formats
+ *
+ * This is the bitwise OR of one or more @c
+ * SRP_LOGIN_REJ_FMT_XXX constants.
+ */
+ uint16_t supported_buffer_formats;
+ /** Reserved */
+ uint8_t reserved2[6];
+} __attribute__ (( packed ));
+
+/** Type of an SRP login rejection */
+#define SRP_LOGIN_REJ 0xc2
+
+/** Unable to establish RDMA channel, no reason specified */
+#define SRP_LOGIN_REJ_REASON_UNKNOWN 0x00010000UL
+
+/** Insufficient RDMA channel resources */
+#define SRP_LOGIN_REJ_REASON_INSUFFICIENT_RESOURCES 0x00010001UL
+
+/** Requested maximum initiator to target IU length value too large */
+#define SRP_LOGIN_REJ_REASON_BAD_MAX_I_T_IU_LEN 0x00010002UL
+
+/** Unable to associate RDMA channel with specified I_T nexus */
+#define SRP_LOGIN_REJ_REASON_CANNOT_ASSOCIATE 0x00010003UL
+
+/** One or more requested data buffer descriptor formats are not supported */
+#define SRP_LOGIN_REJ_REASON_UNSUPPORTED_BUFFER_FORMAT 0x00010004UL
+
+/** SRP target port does not support multiple RDMA channels per I_T nexus */
+#define SRP_LOGIN_REJ_REASON_NO_MULTIPLE_CHANNELS 0x00010005UL
+
+/** RDMA channel limit reached for this initiator */
+#define SRP_LOGIN_REJ_REASON_NO_MORE_CHANNELS 0x00010006UL
+
+/** SRP login rejection reason is defined */
+#define SRP_LOGIN_REJ_REASON_DEFINED( reason ) \
+ ( ( (reason) & 0xfffffff0UL ) == 0x00010000UL )
+
+/** Indirect data buffer descriptor format supported */
+#define SRP_LOGIN_REJ_FMT_IDBD 0x04
+
+/** Direct data buffer descriptor format supported */
+#define SRP_LOGIN_REJ_FMT_DDBD 0x02
+
+/*****************************************************************************
+ *
+ * Initiator logout
+ *
+ *****************************************************************************
+ */
+
+/** An SRP initiator logout request */
+struct srp_i_logout {
+ /** Information unit type
+ *
+ * This must be @c SRP_I_LOGOUT
+ */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[7];
+ /** Tag */
+ union srp_tag tag;
+} __attribute__ (( packed ));
+
+/** Type of an SRP initiator logout request */
+#define SRP_I_LOGOUT 0x03
+
+/*****************************************************************************
+ *
+ * Target logout
+ *
+ *****************************************************************************
+ */
+
+/** An SRP target logout request */
+struct srp_t_logout {
+ /** Information unit type
+ *
+ * This must be @c SRP_T_LOGOUT
+ */
+ uint8_t type;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more @c
+ * SRP_T_LOGOUT_FLAG_XXX constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved0[2];
+ /** Reason
+ *
+ * This is a @c SRP_T_LOGOUT_REASON_XXX constant.
+ */
+ uint32_t reason;
+ /** Tag */
+ union srp_tag tag;
+} __attribute__ (( packed ));
+
+/** Type of an SRP target logout request */
+#define SRP_T_LOGOUT 0x80
+
+/** The initiator specified solicited notification of logouts */
+#define SRP_T_LOGOUT_FLAG_SOLNT 0x01
+
+/** No reason specified */
+#define SRP_T_LOGOUT_REASON_UNKNOWN 0x00000000UL
+
+/** Inactive RDMA channel (reclaiming resources) */
+#define SRP_T_LOGOUT_REASON_INACTIVE 0x00000001UL
+
+/** Invalid information unit type code received by SRP target port */
+#define SRP_T_LOGOUT_REASON_INVALID_TYPE 0x00000002UL
+
+/** SRP initiator port sent response with no corresponding request */
+#define SRP_T_LOGOUT_REASON_SPURIOUS_RESPONSE 0x00000003UL
+
+/** RDMA channel disconnected due to multi-channel action code in new login */
+#define SRP_T_LOGOUT_REASON_MCA 0x00000004UL
+
+/** Unsuppported format code value specified in data-out buffer descriptor */
+#define SRP_T_LOGOUT_UNSUPPORTED_DATA_OUT_FORMAT 0x00000005UL
+
+/** Unsuppported format code value specified in data-in buffer descriptor */
+#define SRP_T_LOGOUT_UNSUPPORTED_DATA_IN_FORMAT 0x00000006UL
+
+/** Invalid length for IU type */
+#define SRP_T_LOGOUT_INVALID_IU_LEN 0x00000008UL
+
+/*****************************************************************************
+ *
+ * Task management
+ *
+ *****************************************************************************
+ */
+
+/** An SRP task management request */
+struct srp_tsk_mgmt {
+ /** Information unit type
+ *
+ * This must be @c SRP_TSK_MGMT
+ */
+ uint8_t type;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more
+ * @c SRP_TSK_MGMT_FLAG_XXX constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved0[6];
+ /** Tag */
+ union srp_tag tag;
+ /** Reserved */
+ uint8_t reserved1[4];
+ /** Logical unit number */
+ struct scsi_lun lun;
+ /** Reserved */
+ uint8_t reserved2[2];
+ /** Task management function
+ *
+ * This is a @c SRP_TASK_MGMT_FUNC_XXX constant
+ */
+ uint8_t function;
+ /** Reserved */
+ uint8_t reserved3[1];
+ /** Tag of task to be managed */
+ union srp_tag managed_tag;
+ /** Reserved */
+ uint8_t reserved4[8];
+} __attribute__ (( packed ));
+
+/** Type of an SRP task management request */
+#define SRP_TSK_MGMT 0x01
+
+/** Use solicited notification for unsuccessful completions */
+#define SRP_TSK_MGMT_FLAG_UCSOLNT 0x04
+
+/** Use solicited notification for successful completions */
+#define SRP_TSK_MGMT_FLAG_SCSOLNT 0x02
+
+/** The task manager shall perform an ABORT TASK function */
+#define SRP_TSK_MGMT_FUNC_ABORT_TASK 0x01
+
+/** The task manager shall perform an ABORT TASK SET function */
+#define SRP_TSK_MGMT_FUNC_ABORT_TASK_SET 0x02
+
+/** The task manager shall perform a CLEAR TASK SET function */
+#define SRP_TSK_MGMT_FUNC_CLEAR_TASK_SET 0x04
+
+/** The task manager shall perform a LOGICAL UNIT RESET function */
+#define SRP_TSK_MGMT_FUNC_LOGICAL_UNIT_RESET 0x08
+
+/** The task manager shall perform a CLEAR ACA function */
+#define SRP_TSK_MGMT_FUNC_CLEAR_ACA 0x40
+
+/*****************************************************************************
+ *
+ * SCSI command
+ *
+ *****************************************************************************
+ */
+
+/** An SRP SCSI command */
+struct srp_cmd {
+ /** Information unit type
+ *
+ * This must be @c SRP_CMD
+ */
+ uint8_t type;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more @c SRP_CMD_FLAG_XXX
+ * constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved0[3];
+ /** Data buffer descriptor formats
+ *
+ * This is the bitwise OR of one @c SRP_CMD_DO_FMT_XXX and one @c
+ * SRP_CMD_DI_FMT_XXX constant.
+ */
+ uint8_t data_buffer_formats;
+ /** Data-out buffer descriptor count */
+ uint8_t data_out_buffer_count;
+ /** Data-in buffer descriptor count */
+ uint8_t data_in_buffer_count;
+ /** Tag */
+ union srp_tag tag;
+ /** Reserved */
+ uint8_t reserved1[4];
+ /** Logical unit number */
+ struct scsi_lun lun;
+ /** Reserved */
+ uint8_t reserved2[1];
+ /** Task attribute
+ *
+ * This is a @c SRP_CMD_TASK_ATTR_XXX constant.
+ */
+ uint8_t task_attr;
+ /** Reserved */
+ uint8_t reserved3[1];
+ /** Additional CDB length */
+ uint8_t additional_cdb_len;
+ /** Command data block */
+ union scsi_cdb cdb;
+} __attribute__ (( packed ));
+
+/** Type of an SRP SCSI command */
+#define SRP_CMD 0x02
+
+/** Use solicited notification for unsuccessful completions */
+#define SRP_CMD_FLAG_UCSOLNT 0x04
+
+/** Use solicited notification for successful completions */
+#define SRP_CMD_FLAG_SCSOLNT 0x02
+
+/** Data-out buffer format mask */
+#define SRP_CMD_DO_FMT_MASK 0xf0
+
+/** Direct data-out buffer format */
+#define SRP_CMD_DO_FMT_DIRECT 0x10
+
+/** Indirect data-out buffer format */
+#define SRP_CMD_DO_FMT_INDIRECT 0x20
+
+/** Data-in buffer format mask */
+#define SRP_CMD_DI_FMT_MASK 0x0f
+
+/** Direct data-in buffer format */
+#define SRP_CMD_DI_FMT_DIRECT 0x01
+
+/** Indirect data-in buffer format */
+#define SRP_CMD_DI_FMT_INDIRECT 0x02
+
+/** Use the rules for a simple task attribute */
+#define SRP_CMD_TASK_ATTR_SIMPLE 0x00
+
+/** Use the rules for a head of queue task attribute */
+#define SRP_CMD_TASK_ATTR_QUEUE_HEAD 0x01
+
+/** Use the rules for an ordered task attribute */
+#define SRP_CMD_TASK_ATTR_ORDERED 0x02
+
+/** Use the rules for an automatic contingent allegiance task attribute */
+#define SRP_CMD_TASK_ATTR_AUTOMATIC_CONTINGENT_ALLEGIANCE 0x08
+
+/** An SRP memory descriptor */
+struct srp_memory_descriptor {
+ /** Virtual address */
+ uint64_t address;
+ /** Memory handle */
+ uint32_t handle;
+ /** Data length */
+ uint32_t len;
+} __attribute__ (( packed ));
+
+/*****************************************************************************
+ *
+ * SCSI response
+ *
+ *****************************************************************************
+ */
+
+/** An SRP SCSI response */
+struct srp_rsp {
+ /** Information unit type
+ *
+ * This must be @c SRP_RSP
+ */
+ uint8_t type;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more @c SRP_RSP_FLAG_XXX
+ * constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved0[2];
+ /** Request limit delta */
+ uint32_t request_limit_delta;
+ /** Tag */
+ union srp_tag tag;
+ /** Reserved */
+ uint8_t reserved1[2];
+ /** Valid fields
+ *
+ * This is the bitwise OR of zero or more @c SRP_RSP_VALID_XXX
+ * constants.
+ */
+ uint8_t valid;
+ /** Status
+ *
+ * This is the SCSI status code.
+ */
+ uint8_t status;
+ /** Data-out residual count */
+ uint32_t data_out_residual_count;
+ /** Data-in residual count */
+ uint32_t data_in_residual_count;
+ /** Sense data list length */
+ uint32_t sense_data_len;
+ /** Response data list length */
+ uint32_t response_data_len;
+} __attribute__ (( packed ));
+
+/** Type of an SRP SCSI response */
+#define SRP_RSP 0xc1
+
+/** The initiator specified solicited notification of this response */
+#define SRP_RSP_FLAG_SOLNT 0x01
+
+/** Data-in residual count field is valid and represents an underflow */
+#define SRP_RSP_VALID_DIUNDER 0x20
+
+/** Data-in residual count field is valid and represents an overflow */
+#define SRP_RSP_VALID_DIOVER 0x10
+
+/** Data-out residual count field is valid and represents an underflow */
+#define SRP_RSP_VALID_DOUNDER 0x08
+
+/** Data-out residual count field is valid and represents an overflow */
+#define SRP_RSP_VALID_DOOVER 0x04
+
+/** Sense data list length field is valid */
+#define SRP_RSP_VALID_SNSVALID 0x02
+
+/** Response data list length field is valid */
+#define SRP_RSP_VALID_RSPVALID 0x01
+
+/**
+ * Get response data portion of SCSI response
+ *
+ * @v rsp SCSI response
+ * @ret response_data Response data, or NULL if not present
+ */
+static inline const void * srp_rsp_response_data ( const struct srp_rsp *rsp ) {
+ return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
+ ( ( ( const void * ) rsp ) + sizeof ( *rsp ) ) : NULL );
+}
+
+/**
+ * Get length of response data portion of SCSI response
+ *
+ * @v rsp SCSI response
+ * @ret response_data_len Response data length
+ */
+static inline size_t srp_rsp_response_data_len ( const struct srp_rsp *rsp ) {
+ return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
+ ntohl ( rsp->response_data_len ) : 0 );
+}
+
+/**
+ * Get sense data portion of SCSI response
+ *
+ * @v rsp SCSI response
+ * @ret sense_data Sense data, or NULL if not present
+ */
+static inline const void * srp_rsp_sense_data ( const struct srp_rsp *rsp ) {
+ return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
+ ( ( ( const void * ) rsp ) + sizeof ( *rsp ) +
+ srp_rsp_response_data_len ( rsp ) ) : NULL );
+}
+
+/**
+ * Get length of sense data portion of SCSI response
+ *
+ * @v rsp SCSI response
+ * @ret sense_data_len Sense data length
+ */
+static inline size_t srp_rsp_sense_data_len ( const struct srp_rsp *rsp ) {
+ return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
+ ntohl ( rsp->sense_data_len ) : 0 );
+}
+
+/*****************************************************************************
+ *
+ * Credit request
+ *
+ *****************************************************************************
+ */
+
+/** An SRP credit request */
+struct srp_cred_req {
+ /** Information unit type
+ *
+ * This must be @c SRP_CRED_REQ
+ */
+ uint8_t type;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more
+ * @c SRP_CRED_REQ_FLAG_XXX constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved0[2];
+ /** Request limit delta */
+ uint32_t request_limit_delta;
+ /** Tag */
+ union srp_tag tag;
+} __attribute__ (( packed ));
+
+/** Type of an SRP credit request */
+#define SRP_CRED_REQ 0x81
+
+/** The initiator specified solicited notification of credit requests */
+#define SRP_CRED_REQ_FLAG_SOLNT 0x01
+
+/*****************************************************************************
+ *
+ * Credit response
+ *
+ *****************************************************************************
+ */
+
+/** An SRP credit response */
+struct srp_cred_rsp {
+ /** Information unit type
+ *
+ * This must be @c SRP_CRED_RSP
+ */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[7];
+ /** Tag */
+ union srp_tag tag;
+} __attribute__ (( packed ));
+
+/** Type of an SRP credit response */
+#define SRP_CRED_RSP 0x41
+
+/*****************************************************************************
+ *
+ * Asynchronous event request
+ *
+ *****************************************************************************
+ */
+
+/** An SRP asynchronous event request */
+struct srp_aer_req {
+ /** Information unit type
+ *
+ * This must be @c SRP_AER_REQ
+ */
+ uint8_t type;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more @c
+ * SRP_AER_REQ_FLAG_XXX constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved0[2];
+ /** Request limit delta */
+ uint32_t request_limit_delta;
+ /** Tag */
+ union srp_tag tag;
+ /** Reserved */
+ uint8_t reserved1[4];
+ /** Logical unit number */
+ struct scsi_lun lun;
+ /** Sense data list length */
+ uint32_t sense_data_len;
+ /** Reserved */
+ uint8_t reserved2[4];
+} __attribute__ (( packed ));
+
+/** Type of an SRP asynchronous event request */
+#define SRP_AER_REQ 0x82
+
+/** The initiator specified solicited notification of asynchronous events */
+#define SRP_AER_REQ_FLAG_SOLNT 0x01
+
+/**
+ * Get sense data portion of asynchronous event request
+ *
+ * @v aer_req SRP asynchronous event request
+ * @ret sense_data Sense data
+ */
+static inline __always_inline void *
+srp_aer_req_sense_data ( struct srp_aer_req *aer_req ) {
+ return ( ( ( void * ) aer_req ) + sizeof ( *aer_req ) );
+}
+
+/**
+ * Get length of sense data portion of asynchronous event request
+ *
+ * @v aer_req SRP asynchronous event request
+ * @ret sense_data_len Sense data length
+ */
+static inline __always_inline size_t
+srp_aer_req_sense_data_len ( struct srp_aer_req *aer_req ) {
+ return ( ntohl ( aer_req->sense_data_len ) );
+}
+
+/*****************************************************************************
+ *
+ * Asynchronous event response
+ *
+ *****************************************************************************
+ */
+
+/** An SRP asynchronous event response */
+struct srp_aer_rsp {
+ /** Information unit type
+ *
+ * This must be @c SRP_AER_RSP
+ */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[7];
+ /** Tag */
+ union srp_tag tag;
+} __attribute__ (( packed ));
+
+/** Type of an SRP asynchronous event response */
+#define SRP_AER_RSP 0x42
+
+/*****************************************************************************
+ *
+ * SRP boot firmware table
+ *
+ * The working draft specification for the SRP boot firmware table can
+ * be found at
+ *
+ * http://ipxe.org/wiki/srp/sbft
+ *
+ *****************************************************************************
+ */
+
+/** SRP Boot Firmware Table signature */
+#define SBFT_SIG ACPI_SIGNATURE ( 's', 'B', 'F', 'T' )
+
+/** An offset from the start of the sBFT */
+typedef uint16_t sbft_off_t;
+
+/**
+ * SRP Boot Firmware Table
+ */
+struct sbft_table {
+ /** ACPI header */
+ struct acpi_description_header acpi;
+ /** Offset to SCSI subtable */
+ sbft_off_t scsi_offset;
+ /** Offset to SRP subtable */
+ sbft_off_t srp_offset;
+ /** Offset to IB subtable, if present */
+ sbft_off_t ib_offset;
+ /** Reserved */
+ uint8_t reserved[6];
+} __attribute__ (( packed ));
+
+/**
+ * sBFT SCSI subtable
+ */
+struct sbft_scsi_subtable {
+ /** LUN */
+ struct scsi_lun lun;
+} __attribute__ (( packed ));
+
+/**
+ * sBFT SRP subtable
+ */
+struct sbft_srp_subtable {
+ /** Initiator port identifier */
+ union srp_port_id initiator;
+ /** Target port identifier */
+ union srp_port_id target;
+} __attribute__ (( packed ));
+
+/*****************************************************************************
+ *
+ * SRP devices
+ *
+ *****************************************************************************
+ */
+
+extern int srp_open ( struct interface *block, struct interface *socket,
+ union srp_port_id *initiator, union srp_port_id *target,
+ uint32_t memory_handle, struct scsi_lun *lun );
+
+#endif /* _IPXE_SRP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/syslog.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/syslog.h
new file mode 100644
index 00000000..035ca670
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/syslog.h
@@ -0,0 +1,38 @@
+#ifndef _IPXE_SYSLOG_H
+#define _IPXE_SYSLOG_H
+
+/** @file
+ *
+ * Syslog protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <syslog.h>
+
+/** Syslog server port */
+#define SYSLOG_PORT 514
+
+/** Syslog line buffer size
+ *
+ * This is a policy decision
+ */
+#define SYSLOG_BUFSIZE 128
+
+/** Syslog default facility
+ *
+ * This is a policy decision
+ */
+#define SYSLOG_DEFAULT_FACILITY 0 /* kernel */
+
+/** Syslog default severity
+ *
+ * This is a policy decision
+ */
+#define SYSLOG_DEFAULT_SEVERITY LOG_INFO
+
+/** Syslog priority */
+#define SYSLOG_PRIORITY( facility, severity ) ( 8 * (facility) + (severity) )
+
+#endif /* _IPXE_SYSLOG_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/tables.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/tables.h
new file mode 100644
index 00000000..e35ce822
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/tables.h
@@ -0,0 +1,518 @@
+#ifndef _IPXE_TABLES_H
+#define _IPXE_TABLES_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @page ifdef_harmful #ifdef considered harmful
+ *
+ * Overuse of @c #ifdef has long been a problem in Etherboot.
+ * Etherboot provides a rich array of features, but all these features
+ * take up valuable space in a ROM image. The traditional solution to
+ * this problem has been for each feature to have its own @c #ifdef
+ * option, allowing the feature to be compiled in only if desired.
+ *
+ * The problem with this is that it becomes impossible to compile, let
+ * alone test, all possible versions of Etherboot. Code that is not
+ * typically used tends to suffer from bit-rot over time. It becomes
+ * extremely difficult to predict which combinations of compile-time
+ * options will result in code that can even compile and link
+ * correctly.
+ *
+ * To solve this problem, we have adopted a new approach from
+ * Etherboot 5.5 onwards. @c #ifdef is now "considered harmful", and
+ * its use should be minimised. Separate features should be
+ * implemented in separate @c .c files, and should \b always be
+ * compiled (i.e. they should \b not be guarded with a @c #ifdef @c
+ * MY_PET_FEATURE statement). By making (almost) all code always
+ * compile, we avoid the problem of bit-rot in rarely-used code.
+ *
+ * The file config.h, in combination with the @c make command line,
+ * specifies the objects that will be included in any particular build
+ * of Etherboot. For example, suppose that config.h includes the line
+ *
+ * @code
+ *
+ * #define CONSOLE_SERIAL
+ * #define DOWNLOAD_PROTO_TFTP
+ *
+ * @endcode
+ *
+ * When a particular Etherboot image (e.g. @c bin/rtl8139.zdsk) is
+ * built, the options specified in config.h are used to drag in the
+ * relevant objects at link-time. For the above example, serial.o and
+ * tftp.o would be linked in.
+ *
+ * There remains one problem to solve: how do these objects get used?
+ * Traditionally, we had code such as
+ *
+ * @code
+ *
+ * #ifdef CONSOLE_SERIAL
+ * serial_init();
+ * #endif
+ *
+ * @endcode
+ *
+ * in main.c, but this reintroduces @c #ifdef and so is a Bad Idea.
+ * We cannot simply remove the @c #ifdef and make it
+ *
+ * @code
+ *
+ * serial_init();
+ *
+ * @endcode
+ *
+ * because then serial.o would end up always being linked in.
+ *
+ * The solution is to use @link tables.h linker tables @endlink.
+ *
+ */
+
+/** @file
+ *
+ * Linker tables
+ *
+ * Read @ref ifdef_harmful first for some background on the motivation
+ * for using linker tables.
+ *
+ * This file provides macros for dealing with linker-generated tables
+ * of fixed-size symbols. We make fairly extensive use of these in
+ * order to avoid @c #ifdef spaghetti and/or linker symbol pollution.
+ * For example, instead of having code such as
+ *
+ * @code
+ *
+ * #ifdef CONSOLE_SERIAL
+ * serial_init();
+ * #endif
+ *
+ * @endcode
+ *
+ * we make serial.c generate an entry in the initialisation function
+ * table, and then have a function call_init_fns() that simply calls
+ * all functions present in this table. If and only if serial.o gets
+ * linked in, then its initialisation function will be called. We
+ * avoid linker symbol pollution (i.e. always dragging in serial.o
+ * just because of a call to serial_init()) and we also avoid @c
+ * #ifdef spaghetti (having to conditionalise every reference to
+ * functions in serial.c).
+ *
+ * The linker script takes care of assembling the tables for us. All
+ * our table sections have names of the format @c .tbl.NAME.NN where
+ * @c NAME designates the data structure stored in the table (e.g. @c
+ * init_fns) and @c NN is a two-digit decimal number used to impose an
+ * ordering upon the tables if required. @c NN=00 is reserved for the
+ * symbol indicating "table start", and @c NN=99 is reserved for the
+ * symbol indicating "table end".
+ *
+ * As an example, suppose that we want to create a "frobnicator"
+ * feature framework, and allow for several independent modules to
+ * provide frobnicating services. Then we would create a frob.h
+ * header file containing e.g.
+ *
+ * @code
+ *
+ * struct frobnicator {
+ * const char *name; // Name of the frobnicator
+ * void ( *frob ) ( void ); // The frobnicating function itself
+ * };
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * #define __frobnicator __table_entry ( FROBNICATORS, 01 )
+ *
+ * @endcode
+ *
+ * Any module providing frobnicating services would look something
+ * like
+ *
+ * @code
+ *
+ * #include "frob.h"
+ *
+ * static void my_frob ( void ) {
+ * // Do my frobnicating
+ * ...
+ * }
+ *
+ * struct frob my_frobnicator __frobnicator = {
+ * .name = "my_frob",
+ * .frob = my_frob,
+ * };
+ *
+ * @endcode
+ *
+ * The central frobnicator code (frob.c) would use the frobnicating
+ * modules as follows
+ *
+ * @code
+ *
+ * #include "frob.h"
+ *
+ * // Call all linked-in frobnicators
+ * void frob_all ( void ) {
+ * struct frob *frob;
+ *
+ * for_each_table ( frob, FROBNICATORS ) {
+ * printf ( "Calling frobnicator \"%s\"\n", frob->name );
+ * frob->frob ();
+ * }
+ * }
+ *
+ * @endcode
+ *
+ * See init.h and init.c for a real-life example.
+ *
+ */
+
+#ifdef DOXYGEN
+#define __attribute__( x )
+#endif
+
+/**
+ * Declare a linker table
+ *
+ * @v type Data type
+ * @v name Table name
+ * @ret table Linker table
+ */
+#define __table( type, name ) ( type, name )
+
+/**
+ * Get linker table data type
+ *
+ * @v table Linker table
+ * @ret type Data type
+ */
+#define __table_type( table ) __table_extract_type table
+#define __table_extract_type( type, name ) type
+
+/**
+ * Get linker table name
+ *
+ * @v table Linker table
+ * @ret name Table name
+ */
+#define __table_name( table ) __table_extract_name table
+#define __table_extract_name( type, name ) name
+
+/**
+ * Get linker table section name
+ *
+ * @v table Linker table
+ * @v idx Sub-table index
+ * @ret section Section name
+ */
+#define __table_section( table, idx ) \
+ ".tbl." __table_name ( table ) "." __table_str ( idx )
+#define __table_str( x ) #x
+
+/**
+ * Get linker table alignment
+ *
+ * @v table Linker table
+ * @ret align Alignment
+ */
+#define __table_alignment( table ) __alignof__ ( __table_type ( table ) )
+
+/**
+ * Declare a linker table entry
+ *
+ * @v table Linker table
+ * @v idx Sub-table index
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * #define __frobnicator __table_entry ( FROBNICATORS, 01 )
+ *
+ * struct frobnicator my_frob __frobnicator = {
+ * ...
+ * };
+ *
+ * @endcode
+ */
+#define __table_entry( table, idx ) \
+ __attribute__ (( __section__ ( __table_section ( table, idx ) ),\
+ __aligned__ ( __table_alignment ( table ) ) ))
+
+/**
+ * Get start of linker table entries
+ *
+ * @v table Linker table
+ * @v idx Sub-table index
+ * @ret entries Start of entries
+ */
+#define __table_entries( table, idx ) ( { \
+ static __table_type ( table ) __table_entries[0] \
+ __table_entry ( table, idx ) \
+ __attribute__ (( unused )); \
+ __table_entries; } )
+
+/**
+ * Get start of linker table
+ *
+ * @v table Linker table
+ * @ret start Start of linker table
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * struct frobnicator *frobs = table_start ( FROBNICATORS );
+ *
+ * @endcode
+ */
+#define table_start( table ) __table_entries ( table, 00 )
+
+/**
+ * Get end of linker table
+ *
+ * @v table Linker table
+ * @ret end End of linker table
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * struct frobnicator *frobs_end = table_end ( FROBNICATORS );
+ *
+ * @endcode
+ */
+#define table_end( table ) __table_entries ( table, 99 )
+
+/**
+ * Get number of entries in linker table
+ *
+ * @v table Linker table
+ * @ret num_entries Number of entries in linker table
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * unsigned int num_frobs = table_num_entries ( FROBNICATORS );
+ *
+ * @endcode
+ *
+ */
+#define table_num_entries( table ) \
+ ( ( unsigned int ) ( table_end ( table ) - \
+ table_start ( table ) ) )
+
+/**
+ * Get index of entry within linker table
+ *
+ * @v table Linker table
+ * @v entry Table entry
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * #define __frobnicator __table_entry ( FROBNICATORS, 01 )
+ *
+ * struct frobnicator my_frob __frobnicator = {
+ * ...
+ * };
+ *
+ * unsigned int my_frob_idx = table_index ( FROBNICATORS, &my_frob );
+ *
+ * @endcode
+ */
+#define table_index( table, entry ) \
+ ( ( unsigned int ) ( (entry) - table_start ( table ) ) )
+
+/**
+ * Iterate through all entries within a linker table
+ *
+ * @v pointer Entry pointer
+ * @v table Linker table
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * struct frobnicator *frob;
+ *
+ * for_each_table_entry ( frob, FROBNICATORS ) {
+ * ...
+ * }
+ *
+ * @endcode
+ *
+ */
+#define for_each_table_entry( pointer, table ) \
+ for ( pointer = table_start ( table ) ; \
+ pointer < table_end ( table ) ; \
+ pointer++ )
+
+/**
+ * Iterate through all remaining entries within a linker table
+ *
+ * @v pointer Entry pointer, preset to most recent entry
+ * @v table Linker table
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ * #define __frobnicator __table_entry ( FROBNICATORS, 01 )
+ *
+ * struct frob my_frobnicator __frobnicator;
+ * struct frobnicator *frob;
+ *
+ * frob = &my_frobnicator;
+ * for_each_table_entry_continue ( frob, FROBNICATORS ) {
+ * ...
+ * }
+ *
+ * @endcode
+ *
+ */
+#define for_each_table_entry_continue( pointer, table ) \
+ for ( pointer++ ; \
+ pointer < table_end ( table ) ; \
+ pointer++ )
+
+/**
+ * Iterate through all entries within a linker table in reverse order
+ *
+ * @v pointer Entry pointer
+ * @v table Linker table
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * struct frobnicator *frob;
+ *
+ * for_each_table_entry_reverse ( frob, FROBNICATORS ) {
+ * ...
+ * }
+ *
+ * @endcode
+ *
+ */
+#define for_each_table_entry_reverse( pointer, table ) \
+ for ( pointer = ( table_end ( table ) - 1 ) ; \
+ pointer >= table_start ( table ) ; \
+ pointer-- )
+
+/**
+ * Iterate through all remaining entries within a linker table in reverse order
+ *
+ * @v pointer Entry pointer, preset to most recent entry
+ * @v table Linker table
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ * #define __frobnicator __table_entry ( FROBNICATORS, 01 )
+ *
+ * struct frob my_frobnicator __frobnicator;
+ * struct frobnicator *frob;
+ *
+ * frob = &my_frobnicator;
+ * for_each_table_entry_continue_reverse ( frob, FROBNICATORS ) {
+ * ...
+ * }
+ *
+ * @endcode
+ *
+ */
+#define for_each_table_entry_continue_reverse( pointer, table ) \
+ for ( pointer-- ; \
+ pointer >= table_start ( table ) ; \
+ pointer-- )
+
+/******************************************************************************
+ *
+ * Intel's C compiler chokes on several of the constructs used in this
+ * file. The workarounds are ugly, so we use them only for an icc
+ * build.
+ *
+ */
+#define ICC_ALIGN_HACK_FACTOR 128
+#ifdef __ICC
+
+/*
+ * icc miscompiles zero-length arrays by inserting padding to a length
+ * of two array elements. We therefore have to generate the
+ * __table_entries() symbols by hand in asm.
+ *
+ */
+#undef __table_entries
+#define __table_entries( table, idx ) ( { \
+ extern __table_type ( table ) \
+ __table_temp_sym ( idx, __LINE__ ) [] \
+ __table_entry ( table, idx ) \
+ asm ( __table_entries_sym ( table, idx ) ); \
+ __asm__ ( ".ifndef %c0\n\t" \
+ ".section " __table_section ( table, idx ) "\n\t" \
+ ".align %c1\n\t" \
+ "\n%c0:\n\t" \
+ ".previous\n\t" \
+ ".endif\n\t" \
+ : : "i" ( __table_temp_sym ( idx, __LINE__ ) ), \
+ "i" ( __table_alignment ( table ) ) ); \
+ __table_temp_sym ( idx, __LINE__ ); } )
+#define __table_entries_sym( table, idx ) \
+ "__tbl_" __table_name ( table ) "_" #idx
+#define __table_temp_sym( a, b ) \
+ ___table_temp_sym( __table_, a, _, b )
+#define ___table_temp_sym( a, b, c, d ) a ## b ## c ## d
+
+/*
+ * icc ignores __attribute__ (( aligned (x) )) when it is used to
+ * decrease the compiler's default choice of alignment (which may be
+ * higher than the alignment actually required by the structure). We
+ * work around this by forcing the alignment to a large multiple of
+ * the required value (so that we are never attempting to decrease the
+ * default alignment) and then postprocessing the object file to
+ * reduce the alignment back down to the "real" value.
+ *
+ */
+#undef __table_alignment
+#define __table_alignment( table ) \
+ ( ICC_ALIGN_HACK_FACTOR * __alignof__ ( __table_type ( table ) ) )
+
+/*
+ * Because of the alignment hack, we must ensure that the compiler
+ * never tries to place multiple objects within the same section,
+ * otherwise the assembler will insert padding to the (incorrect)
+ * alignment boundary. Do this by appending the line number to table
+ * section names.
+ *
+ * Note that we don't need to worry about padding between array
+ * elements, since the alignment is declared on the variable (i.e. the
+ * whole array) rather than on the type (i.e. on all individual array
+ * elements).
+ */
+#undef __table_section
+#define __table_section( table, idx ) \
+ ".tbl." __table_name ( table ) "." __table_str ( idx ) \
+ "." __table_xstr ( __LINE__ )
+#define __table_xstr( x ) __table_str ( x )
+
+#endif /* __ICC */
+
+#endif /* _IPXE_TABLES_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/tcp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/tcp.h
new file mode 100644
index 00000000..7084af60
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/tcp.h
@@ -0,0 +1,352 @@
+#ifndef _IPXE_TCP_H
+#define _IPXE_TCP_H
+
+/** @file
+ *
+ * TCP protocol
+ *
+ * This file defines the iPXE TCP API.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/tcpip.h>
+
+/**
+ * A TCP header
+ */
+struct tcp_header {
+ uint16_t src; /* Source port */
+ uint16_t dest; /* Destination port */
+ uint32_t seq; /* Sequence number */
+ uint32_t ack; /* Acknowledgement number */
+ uint8_t hlen; /* Header length (4), Reserved (4) */
+ uint8_t flags; /* Reserved (2), Flags (6) */
+ uint16_t win; /* Advertised window */
+ uint16_t csum; /* Checksum */
+ uint16_t urg; /* Urgent pointer */
+};
+
+/** @defgroup tcpopts TCP options
+ * @{
+ */
+
+/** End of TCP options list */
+#define TCP_OPTION_END 0
+
+/** TCP option pad */
+#define TCP_OPTION_NOP 1
+
+/** Generic TCP option */
+struct tcp_option {
+ uint8_t kind;
+ uint8_t length;
+} __attribute__ (( packed ));
+
+/** TCP MSS option */
+struct tcp_mss_option {
+ uint8_t kind;
+ uint8_t length;
+ uint16_t mss;
+} __attribute__ (( packed ));
+
+/** Code for the TCP MSS option */
+#define TCP_OPTION_MSS 2
+
+/** TCP timestamp option */
+struct tcp_timestamp_option {
+ uint8_t kind;
+ uint8_t length;
+ uint32_t tsval;
+ uint32_t tsecr;
+} __attribute__ (( packed ));
+
+/** Padded TCP timestamp option (used for sending) */
+struct tcp_timestamp_padded_option {
+ uint8_t nop[2];
+ struct tcp_timestamp_option tsopt;
+} __attribute__ (( packed ));
+
+/** Code for the TCP timestamp option */
+#define TCP_OPTION_TS 8
+
+/** Parsed TCP options */
+struct tcp_options {
+ /** MSS option, if present */
+ const struct tcp_mss_option *mssopt;
+ /** Timestampe option, if present */
+ const struct tcp_timestamp_option *tsopt;
+};
+
+/** @} */
+
+/*
+ * TCP flags
+ */
+#define TCP_CWR 0x80
+#define TCP_ECE 0x40
+#define TCP_URG 0x20
+#define TCP_ACK 0x10
+#define TCP_PSH 0x08
+#define TCP_RST 0x04
+#define TCP_SYN 0x02
+#define TCP_FIN 0x01
+
+/**
+* @defgroup tcpstates TCP states
+*
+* The TCP state is defined by a combination of the flags that have
+* been sent to the peer, the flags that have been acknowledged by the
+* peer, and the flags that have been received from the peer.
+*
+* @{
+*/
+
+/** TCP flags that have been sent in outgoing packets */
+#define TCP_STATE_SENT(flags) ( (flags) << 0 )
+#define TCP_FLAGS_SENT(state) ( ( (state) >> 0 ) & 0xff )
+
+/** TCP flags that have been acknowledged by the peer
+ *
+ * Note that this applies only to SYN and FIN.
+ */
+#define TCP_STATE_ACKED(flags) ( (flags) << 8 )
+#define TCP_FLAGS_ACKED(state) ( ( (state) >> 8 ) & 0xff )
+
+/** TCP flags that have been received from the peer
+ *
+ * Note that this applies only to SYN and FIN, and that once SYN has
+ * been received, we should always be sending ACK.
+ */
+#define TCP_STATE_RCVD(flags) ( (flags) << 16 )
+#define TCP_FLAGS_RCVD(state) ( ( (state) >> 16 ) & 0xff )
+
+/** TCP flags that are currently being sent in outgoing packets */
+#define TCP_FLAGS_SENDING(state) \
+ ( TCP_FLAGS_SENT ( state ) & ~TCP_FLAGS_ACKED ( state ) )
+
+/** CLOSED
+ *
+ * The connection has not yet been used for anything.
+ */
+#define TCP_CLOSED TCP_RST
+
+/** LISTEN
+ *
+ * Not currently used as a state; we have no support for listening
+ * connections. Given a unique value to avoid compiler warnings.
+ */
+#define TCP_LISTEN 0
+
+/** SYN_SENT
+ *
+ * SYN has been sent, nothing has yet been received or acknowledged.
+ */
+#define TCP_SYN_SENT ( TCP_STATE_SENT ( TCP_SYN ) )
+
+/** SYN_RCVD
+ *
+ * SYN has been sent but not acknowledged, SYN has been received.
+ */
+#define TCP_SYN_RCVD ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) )
+
+/** ESTABLISHED
+ *
+ * SYN has been sent and acknowledged, SYN has been received.
+ */
+#define TCP_ESTABLISHED ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) | \
+ TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) )
+
+/** FIN_WAIT_1
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been sent but not acknowledged, FIN has not been received.
+ *
+ * RFC 793 shows that we can enter FIN_WAIT_1 without have had SYN
+ * acknowledged, i.e. if the application closes the connection after
+ * sending and receiving SYN, but before having had SYN acknowledged.
+ * However, we have to *pretend* that SYN has been acknowledged
+ * anyway, otherwise we end up sending SYN and FIN in the same
+ * sequence number slot. Therefore, when we transition from SYN_RCVD
+ * to FIN_WAIT_1, we have to remember to set TCP_STATE_ACKED(TCP_SYN)
+ * and increment our sequence number.
+ */
+#define TCP_FIN_WAIT_1 ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
+ TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) )
+
+/** FIN_WAIT_2
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been sent and acknowledged, FIN ha not been received.
+ */
+#define TCP_FIN_WAIT_2 ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
+ TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) )
+
+/** CLOSING / LAST_ACK
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been sent but not acknowledged, FIN has been received.
+ *
+ * This state actually encompasses both CLOSING and LAST_ACK; they are
+ * identical with the definition of state that we use. I don't
+ * *believe* that they need to be distinguished.
+ */
+#define TCP_CLOSING_OR_LAST_ACK \
+ ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
+ TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
+
+/** TIME_WAIT
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been sent and acknowledged, FIN has been received.
+ */
+#define TCP_TIME_WAIT ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
+ TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \
+ TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
+
+/** CLOSE_WAIT
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been received.
+ */
+#define TCP_CLOSE_WAIT ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) | \
+ TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
+
+/** Can send data in current state
+ *
+ * We can send data if and only if we have had our SYN acked and we
+ * have not yet sent our FIN.
+ */
+#define TCP_CAN_SEND_DATA(state) \
+ ( ( (state) & ( TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_SENT ( TCP_FIN ) ) ) \
+ == TCP_STATE_ACKED ( TCP_SYN ) )
+
+/** Have ever been fully established
+ *
+ * We have been fully established if we have both received a SYN and
+ * had our own SYN acked.
+ */
+#define TCP_HAS_BEEN_ESTABLISHED(state) \
+ ( ( (state) & ( TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) ) ) \
+ == ( TCP_STATE_ACKED ( TCP_SYN ) | TCP_STATE_RCVD ( TCP_SYN ) ) )
+
+/** Have closed gracefully
+ *
+ * We have closed gracefully if we have both received a FIN and had
+ * our own FIN acked.
+ */
+#define TCP_CLOSED_GRACEFULLY(state) \
+ ( ( (state) & ( TCP_STATE_ACKED ( TCP_FIN ) | \
+ TCP_STATE_RCVD ( TCP_FIN ) ) ) \
+ == ( TCP_STATE_ACKED ( TCP_FIN ) | TCP_STATE_RCVD ( TCP_FIN ) ) )
+
+/** @} */
+
+/** Mask for TCP header length field */
+#define TCP_MASK_HLEN 0xf0
+
+/** Smallest port number on which a TCP connection can listen */
+#define TCP_MIN_PORT 1
+
+/**
+ * Maxmimum advertised TCP window size
+ *
+ * We estimate the TCP window size as the amount of free memory we
+ * have. This is not strictly accurate (since it ignores any space
+ * already allocated as RX buffers), but it will do for now.
+ *
+ * Since we don't store out-of-order received packets, the
+ * retransmission penalty is that the whole window contents must be
+ * resent. This suggests keeping the window size small, but bear in
+ * mind that the maximum bandwidth on any link is limited to
+ *
+ * max_bandwidth = ( tcp_window / round_trip_time )
+ *
+ * With a 48kB window, which probably accurately reflects our amount
+ * of free memory, and a WAN RTT of say 200ms, this gives a maximum
+ * bandwidth of 240kB/s. This is sufficiently close to realistic that
+ * we will need to be careful that our advertised window doesn't end
+ * up limiting WAN download speeds.
+ *
+ * Finally, since the window goes into a 16-bit field and we cannot
+ * actually use 65536, we use a window size of (65536-4) to ensure
+ * that payloads remain dword-aligned.
+ */
+//#define TCP_MAX_WINDOW_SIZE ( 65536 - 4 )
+#define TCP_MAX_WINDOW_SIZE 8192
+
+/**
+ * Path MTU
+ *
+ * We really ought to implement Path MTU discovery. Until we do,
+ * anything with a path MTU greater than this may fail.
+ */
+#define TCP_PATH_MTU 1460
+
+/**
+ * Advertised TCP MSS
+ *
+ * We currently hardcode this to a reasonable value and hope that the
+ * sender uses path MTU discovery. The alternative is breaking the
+ * abstraction layer so that we can find out the MTU from the IP layer
+ * (which would have to find out from the net device layer).
+ */
+#define TCP_MSS 1460
+
+/** TCP maximum segment lifetime
+ *
+ * Currently set to 2 minutes, as per RFC 793.
+ */
+#define TCP_MSL ( 2 * 60 * TICKS_PER_SEC )
+
+/**
+ * TCP maximum header length
+ *
+ */
+#define TCP_MAX_HEADER_LEN \
+ ( MAX_LL_NET_HEADER_LEN + \
+ sizeof ( struct tcp_header ) + \
+ sizeof ( struct tcp_mss_option ) + \
+ sizeof ( struct tcp_timestamp_padded_option ) )
+
+/**
+ * Compare TCP sequence numbers
+ *
+ * @v seq1 Sequence number 1
+ * @v seq2 Sequence number 2
+ * @ret diff Sequence difference
+ *
+ * Analogous to memcmp(), returns an integer less than, equal to, or
+ * greater than zero if @c seq1 is found, respectively, to be before,
+ * equal to, or after @c seq2.
+ */
+static inline __attribute__ (( always_inline )) int32_t
+tcp_cmp ( uint32_t seq1, uint32_t seq2 ) {
+ return ( ( int32_t ) ( seq1 - seq2 ) );
+}
+
+/**
+ * Check if TCP sequence number lies within window
+ *
+ * @v seq Sequence number
+ * @v start Start of window
+ * @v len Length of window
+ * @ret in_window Sequence number is within window
+ */
+static inline int tcp_in_window ( uint32_t seq, uint32_t start,
+ uint32_t len ) {
+ return ( ( seq - start ) < len );
+}
+
+extern struct tcpip_protocol tcp_protocol __tcpip_protocol;
+
+#endif /* _IPXE_TCP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/tcpip.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/tcpip.h
new file mode 100644
index 00000000..cdf554ea
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/tcpip.h
@@ -0,0 +1,128 @@
+#ifndef _IPXE_TCPIP_H
+#define _IPXE_TCPIP_H
+
+/** @file
+ *
+ * Transport-network layer interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/socket.h>
+#include <ipxe/in.h>
+#include <ipxe/tables.h>
+
+struct io_buffer;
+struct net_device;
+
+/** Empty checksum value
+ *
+ * This is the TCP/IP checksum over a zero-length block of data.
+ */
+#define TCPIP_EMPTY_CSUM 0xffff
+
+/**
+ * TCP/IP socket address
+ *
+ * This contains the fields common to socket addresses for all TCP/IP
+ * address families.
+ */
+struct sockaddr_tcpip {
+ /** Socket address family (part of struct @c sockaddr) */
+ sa_family_t st_family;
+ /** TCP/IP port */
+ uint16_t st_port;
+ /** Padding
+ *
+ * This ensures that a struct @c sockaddr_tcpip is large
+ * enough to hold a socket address for any TCP/IP address
+ * family.
+ */
+ char pad[ sizeof ( struct sockaddr ) -
+ ( sizeof ( sa_family_t ) + sizeof ( uint16_t ) ) ];
+} __attribute__ (( may_alias ));
+
+/**
+ * A transport-layer protocol of the TCP/IP stack (eg. UDP, TCP, etc)
+ */
+struct tcpip_protocol {
+ /** Protocol name */
+ const char *name;
+ /**
+ * Process received packet
+ *
+ * @v iobuf I/O buffer
+ * @v st_src Partially-filled source address
+ * @v st_dest Partially-filled destination address
+ * @v pshdr_csum Pseudo-header checksum
+ * @ret rc Return status code
+ *
+ * This method takes ownership of the I/O buffer.
+ */
+ int ( * rx ) ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum );
+ /**
+ * Transport-layer protocol number
+ *
+ * This is a constant of the type IP_XXX
+ */
+ uint8_t tcpip_proto;
+};
+
+/**
+ * A network-layer protocol of the TCP/IP stack (eg. IPV4, IPv6, etc)
+ */
+struct tcpip_net_protocol {
+ /** Protocol name */
+ const char *name;
+ /** Network address family */
+ sa_family_t sa_family;
+ /**
+ * Transmit packet
+ *
+ * @v iobuf I/O buffer
+ * @v tcpip_protocol Transport-layer protocol
+ * @v st_src Source address, or NULL to use default
+ * @v st_dest Destination address
+ * @v netdev Network device (or NULL to route automatically)
+ * @v trans_csum Transport-layer checksum to complete, or NULL
+ * @ret rc Return status code
+ *
+ * This function takes ownership of the I/O buffer.
+ */
+ int ( * tx ) ( struct io_buffer *iobuf,
+ struct tcpip_protocol *tcpip_protocol,
+ struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest,
+ struct net_device *netdev,
+ uint16_t *trans_csum );
+};
+
+/** TCP/IP transport-layer protocol table */
+#define TCPIP_PROTOCOLS __table ( struct tcpip_protocol, "tcpip_protocols" )
+
+/** Declare a TCP/IP transport-layer protocol */
+#define __tcpip_protocol __table_entry ( TCPIP_PROTOCOLS, 01 )
+
+/** TCP/IP network-layer protocol table */
+#define TCPIP_NET_PROTOCOLS \
+ __table ( struct tcpip_net_protocol, "tcpip_net_protocols" )
+
+/** Declare a TCP/IP network-layer protocol */
+#define __tcpip_net_protocol __table_entry ( TCPIP_NET_PROTOCOLS, 01 )
+
+extern int tcpip_rx ( struct io_buffer *iobuf, uint8_t tcpip_proto,
+ struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum );
+extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip,
+ struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest,
+ struct net_device *netdev,
+ uint16_t *trans_csum );
+extern uint16_t tcpip_continue_chksum ( uint16_t partial,
+ const void *data, size_t len );
+extern uint16_t tcpip_chksum ( const void *data, size_t len );
+
+#endif /* _IPXE_TCPIP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/test.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/test.h
new file mode 100644
index 00000000..8c361d28
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/test.h
@@ -0,0 +1,45 @@
+#ifndef _IPXE_TEST_H
+#define _IPXE_TEST_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Self-test infrastructure
+ *
+ */
+
+#include <ipxe/tables.h>
+
+/** A self-test set */
+struct self_test {
+ /** Test set name */
+ const char *name;
+ /** Run self-tests */
+ void ( * exec ) ( void );
+ /** Number of tests run */
+ unsigned int total;
+ /** Number of test failures */
+ unsigned int failures;
+ /** Number of assertion failures */
+ unsigned int assertion_failures;
+};
+
+/** Self-test table */
+#define SELF_TESTS __table ( struct self_test, "self_tests" )
+
+/** Declare a self-test */
+#define __self_test __table_entry ( SELF_TESTS, 01 )
+
+extern void test_ok ( int success, const char *file, unsigned int line );
+
+/**
+ * Report test result
+ *
+ * @v success Test succeeded
+ */
+#define ok( success ) do { \
+ test_ok ( (success), __FILE__, __LINE__ ); \
+ } while ( 0 )
+
+#endif /* _IPXE_TEST_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/tftp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/tftp.h
new file mode 100644
index 00000000..38be0d4d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/tftp.h
@@ -0,0 +1,85 @@
+#ifndef _IPXE_TFTP_H
+#define _IPXE_TFTP_H
+
+/** @file
+ *
+ * TFTP protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+#define TFTP_PORT 69 /**< Default TFTP server port */
+#define TFTP_DEFAULT_BLKSIZE 512 /**< Default TFTP data block size */
+#define TFTP_MAX_BLKSIZE 1432
+
+#define TFTP_RRQ 1 /**< Read request opcode */
+#define TFTP_WRQ 2 /**< Write request opcode */
+#define TFTP_DATA 3 /**< Data block opcode */
+#define TFTP_ACK 4 /**< Data block acknowledgement opcode */
+#define TFTP_ERROR 5 /**< Error opcode */
+#define TFTP_OACK 6 /**< Options acknowledgement opcode */
+
+#define TFTP_ERR_FILE_NOT_FOUND 1 /**< File not found */
+#define TFTP_ERR_ACCESS_DENIED 2 /**< Access violation */
+#define TFTP_ERR_DISK_FULL 3 /**< Disk full or allocation exceeded */
+#define TFTP_ERR_ILLEGAL_OP 4 /**< Illegal TFTP operation */
+#define TFTP_ERR_UNKNOWN_TID 5 /**< Unknown transfer ID */
+#define TFTP_ERR_FILE_EXISTS 6 /**< File already exists */
+#define TFTP_ERR_UNKNOWN_USER 7 /**< No such user */
+#define TFTP_ERR_BAD_OPTS 8 /**< Option negotiation failed */
+
+#define MTFTP_PORT 1759 /**< Default MTFTP server port */
+
+/** A TFTP read request (RRQ) packet */
+struct tftp_rrq {
+ uint16_t opcode;
+ char data[0];
+} __attribute__ (( packed ));
+
+/** A TFTP data (DATA) packet */
+struct tftp_data {
+ uint16_t opcode;
+ uint16_t block;
+ uint8_t data[0];
+} __attribute__ (( packed ));
+
+/** A TFTP acknowledgement (ACK) packet */
+struct tftp_ack {
+ uint16_t opcode;
+ uint16_t block;
+} __attribute__ (( packed ));
+
+/** A TFTP error (ERROR) packet */
+struct tftp_error {
+ uint16_t opcode;
+ uint16_t errcode;
+ char errmsg[0];
+} __attribute__ (( packed ));
+
+/** A TFTP options acknowledgement (OACK) packet */
+struct tftp_oack {
+ uint16_t opcode;
+ char data[0];
+} __attribute__ (( packed ));
+
+/** The common header of all TFTP packets */
+struct tftp_common {
+ uint16_t opcode;
+} __attribute__ (( packed ));
+
+/** A union encapsulating all TFTP packet types */
+union tftp_any {
+ struct tftp_common common;
+ struct tftp_rrq rrq;
+ struct tftp_data data;
+ struct tftp_ack ack;
+ struct tftp_error error;
+ struct tftp_oack oack;
+};
+
+extern void tftp_set_request_blksize ( unsigned int blksize );
+
+#endif /* _IPXE_TFTP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/threewire.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/threewire.h
new file mode 100644
index 00000000..b5513ecd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/threewire.h
@@ -0,0 +1,118 @@
+#ifndef _IPXE_THREEWIRE_H
+#define _IPXE_THREEWIRE_H
+
+/** @file
+ *
+ * Three-wire serial interface
+ *
+ * The Atmel three-wire interface is a subset of the (newer) SPI
+ * interface, and is implemented here as a layer on top of the SPI
+ * support.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/spi.h>
+#include <limits.h>
+
+/**
+ * @defgroup tcmds Three-wire commands
+ * @{
+ */
+
+/** Read data from memory array */
+#define THREEWIRE_READ 0x6
+
+/** Write data to memory array */
+#define THREEWIRE_WRITE 0x5
+
+/** Write enable */
+#define THREEWIRE_EWEN 0x4
+
+/** Address to be used for write enable command */
+#define THREEWIRE_EWEN_ADDRESS INT_MAX
+
+/** Time to wait for write cycles to complete
+ *
+ * This is sufficient for AT93C46/AT93C56 devices, but may need to be
+ * increased in future when other devices are added.
+ */
+#define THREEWIRE_WRITE_MDELAY 10
+
+/** @} */
+
+extern int threewire_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len );
+extern int threewire_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len );
+extern int threewire_detect_address_len ( struct spi_device *device );
+
+/**
+ * @defgroup tdevs Three-wire device types
+ * @{
+ */
+
+static inline __attribute__ (( always_inline )) void
+init_at93cx6 ( struct spi_device *device, unsigned int organisation ) {
+ device->nvs.word_len_log2 = ( ( organisation == 8 ) ? 0 : 1 );
+ device->nvs.block_size = 1;
+ device->command_len = 3,
+ device->nvs.read = threewire_read;
+ device->nvs.write = threewire_write;
+}
+
+/**
+ * Initialise Atmel AT93C06 serial EEPROM
+ *
+ * @v device SPI device
+ * @v organisation Word organisation (8 or 16)
+ */
+static inline __attribute__ (( always_inline )) void
+init_at93c06 ( struct spi_device *device, unsigned int organisation ) {
+ device->nvs.size = ( 256 / organisation );
+ device->address_len = ( ( organisation == 8 ) ? 7 : 6 );
+ init_at93cx6 ( device, organisation );
+}
+
+/**
+ * Initialise Atmel AT93C46 serial EEPROM
+ *
+ * @v device SPI device
+ * @v organisation Word organisation (8 or 16)
+ */
+static inline __attribute__ (( always_inline )) void
+init_at93c46 ( struct spi_device *device, unsigned int organisation ) {
+ device->nvs.size = ( 1024 / organisation );
+ device->address_len = ( ( organisation == 8 ) ? 7 : 6 );
+ init_at93cx6 ( device, organisation );
+}
+
+/**
+ * Initialise Atmel AT93C56 serial EEPROM
+ *
+ * @v device SPI device
+ * @v organisation Word organisation (8 or 16)
+ */
+static inline __attribute__ (( always_inline )) void
+init_at93c56 ( struct spi_device *device, unsigned int organisation ) {
+ device->nvs.size = ( 2048 / organisation );
+ device->address_len = ( ( organisation == 8 ) ? 9 : 8 );
+ init_at93cx6 ( device, organisation );
+}
+
+/**
+ * Initialise Atmel AT93C66 serial EEPROM
+ *
+ * @v device SPI device
+ * @v organisation Word organisation (8 or 16)
+ */
+static inline __attribute__ (( always_inline )) void
+init_at93c66 ( struct spi_device *device, unsigned int organisation ) {
+ device->nvs.size = ( 4096 / organisation );
+ device->address_len = ( ( organisation == 8 ) ? 9 : 8 );
+ init_at93cx6 ( device, organisation );
+}
+
+/** @} */
+
+#endif /* _IPXE_THREEWIRE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/time.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/time.h
new file mode 100644
index 00000000..673fe098
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/time.h
@@ -0,0 +1,59 @@
+#ifndef _IPXE_TIME_H
+#define _IPXE_TIME_H
+
+/** @file
+ *
+ * Time source
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <sys/time.h>
+#include <ipxe/api.h>
+#include <config/time.h>
+
+/**
+ * Calculate static inline time API function name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ */
+#define TIME_INLINE( _subsys, _api_func ) \
+ SINGLE_API_INLINE ( TIME_PREFIX_ ## _subsys, _api_func )
+
+/**
+ * Provide a time API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_TIME( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( TIME_PREFIX_ ## _subsys, _api_func, _func )
+
+/**
+ * Provide a static inline time API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ */
+#define PROVIDE_TIME_INLINE( _subsys, _api_func ) \
+ PROVIDE_SINGLE_API_INLINE ( TIME_PREFIX_ ## _subsys, _api_func )
+
+/* Include all architecture-independent time API headers */
+#include <ipxe/null_time.h>
+#include <ipxe/linux/linux_time.h>
+
+/* Include all architecture-dependent time API headers */
+#include <bits/time.h>
+
+/**
+ * Get current time in seconds
+ *
+ * @ret time Time, in seconds
+ */
+time_t time_now ( void );
+
+#endif /* _IPXE_TIME_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/timer.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/timer.h
new file mode 100644
index 00000000..d0309655
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/timer.h
@@ -0,0 +1,77 @@
+#ifndef _IPXE_TIMER_H
+#define _IPXE_TIMER_H
+
+/** @file
+ *
+ * iPXE timer API
+ *
+ * The timer API provides udelay() for fixed delays, and currticks()
+ * for a monotonically increasing tick counter.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/api.h>
+#include <config/timer.h>
+
+/**
+ * Calculate static inline timer API function name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ */
+#define TIMER_INLINE( _subsys, _api_func ) \
+ SINGLE_API_INLINE ( TIMER_PREFIX_ ## _subsys, _api_func )
+
+/**
+ * Provide a timer API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_TIMER( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( TIMER_PREFIX_ ## _subsys, _api_func, _func )
+
+/**
+ * Provide a static inline timer API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ */
+#define PROVIDE_TIMER_INLINE( _subsys, _api_func ) \
+ PROVIDE_SINGLE_API_INLINE ( TIMER_PREFIX_ ## _subsys, _api_func )
+
+/* Include all architecture-independent I/O API headers */
+#include <ipxe/efi/efi_timer.h>
+#include <ipxe/linux/linux_timer.h>
+
+/* Include all architecture-dependent I/O API headers */
+#include <bits/timer.h>
+
+/**
+ * Delay for a fixed number of microseconds
+ *
+ * @v usecs Number of microseconds for which to delay
+ */
+void udelay ( unsigned long usecs );
+
+/**
+ * Get current system time in ticks
+ *
+ * @ret ticks Current time, in ticks
+ */
+unsigned long currticks ( void );
+
+/**
+ * Get number of ticks per second
+ *
+ * @ret ticks_per_sec Number of ticks per second
+ */
+unsigned long ticks_per_sec ( void );
+
+/** Number of ticks per second */
+#define TICKS_PER_SEC ( ticks_per_sec() )
+
+#endif /* _IPXE_TIMER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/tls.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/tls.h
new file mode 100644
index 00000000..7de1f19e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/tls.h
@@ -0,0 +1,270 @@
+#ifndef _IPXE_TLS_H
+#define _IPXE_TLS_H
+
+/**
+ * @file
+ *
+ * Transport Layer Security Protocol
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/interface.h>
+#include <ipxe/process.h>
+#include <ipxe/crypto.h>
+#include <ipxe/md5.h>
+#include <ipxe/sha1.h>
+#include <ipxe/sha256.h>
+#include <ipxe/x509.h>
+
+/** A TLS header */
+struct tls_header {
+ /** Content type
+ *
+ * This is a TLS_TYPE_XXX constant
+ */
+ uint8_t type;
+ /** Protocol version
+ *
+ * This is a TLS_VERSION_XXX constant
+ */
+ uint16_t version;
+ /** Length of payload */
+ uint16_t length;
+} __attribute__ (( packed ));
+
+/** TLS version 1.0 */
+#define TLS_VERSION_TLS_1_0 0x0301
+
+/** TLS version 1.1 */
+#define TLS_VERSION_TLS_1_1 0x0302
+
+/** TLS version 1.2 */
+#define TLS_VERSION_TLS_1_2 0x0303
+
+/** Change cipher content type */
+#define TLS_TYPE_CHANGE_CIPHER 20
+
+/** Alert content type */
+#define TLS_TYPE_ALERT 21
+
+/** Handshake content type */
+#define TLS_TYPE_HANDSHAKE 22
+
+/** Application data content type */
+#define TLS_TYPE_DATA 23
+
+/* Handshake message types */
+#define TLS_HELLO_REQUEST 0
+#define TLS_CLIENT_HELLO 1
+#define TLS_SERVER_HELLO 2
+#define TLS_CERTIFICATE 11
+#define TLS_SERVER_KEY_EXCHANGE 12
+#define TLS_CERTIFICATE_REQUEST 13
+#define TLS_SERVER_HELLO_DONE 14
+#define TLS_CERTIFICATE_VERIFY 15
+#define TLS_CLIENT_KEY_EXCHANGE 16
+#define TLS_FINISHED 20
+
+/* TLS alert levels */
+#define TLS_ALERT_WARNING 1
+#define TLS_ALERT_FATAL 2
+
+/* TLS cipher specifications */
+#define TLS_RSA_WITH_NULL_MD5 0x0001
+#define TLS_RSA_WITH_NULL_SHA 0x0002
+#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002f
+#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035
+#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003c
+#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003d
+
+/* TLS hash algorithm identifiers */
+#define TLS_MD5_ALGORITHM 1
+#define TLS_SHA1_ALGORITHM 2
+#define TLS_SHA256_ALGORITHM 4
+
+/* TLS signature algorithm identifiers */
+#define TLS_RSA_ALGORITHM 1
+
+/* TLS extension types */
+#define TLS_SERVER_NAME 0
+#define TLS_SERVER_NAME_HOST_NAME 0
+
+/** TLS RX state machine state */
+enum tls_rx_state {
+ TLS_RX_HEADER = 0,
+ TLS_RX_DATA,
+};
+
+/** TLS TX pending flags */
+enum tls_tx_pending {
+ TLS_TX_CLIENT_HELLO = 0x0001,
+ TLS_TX_CERTIFICATE = 0x0002,
+ TLS_TX_CLIENT_KEY_EXCHANGE = 0x0004,
+ TLS_TX_CERTIFICATE_VERIFY = 0x0008,
+ TLS_TX_CHANGE_CIPHER = 0x0010,
+ TLS_TX_FINISHED = 0x0020,
+};
+
+/** A TLS cipher suite */
+struct tls_cipher_suite {
+ /** Public-key encryption algorithm */
+ struct pubkey_algorithm *pubkey;
+ /** Bulk encryption cipher algorithm */
+ struct cipher_algorithm *cipher;
+ /** MAC digest algorithm */
+ struct digest_algorithm *digest;
+ /** Key length */
+ uint16_t key_len;
+ /** Numeric code (in network-endian order) */
+ uint16_t code;
+};
+
+/** A TLS cipher specification */
+struct tls_cipherspec {
+ /** Cipher suite */
+ struct tls_cipher_suite *suite;
+ /** Dynamically-allocated storage */
+ void *dynamic;
+ /** Public key encryption context */
+ void *pubkey_ctx;
+ /** Bulk encryption cipher context */
+ void *cipher_ctx;
+ /** Next bulk encryption cipher context (TX only) */
+ void *cipher_next_ctx;
+ /** MAC secret */
+ void *mac_secret;
+};
+
+/** A TLS signature and hash algorithm identifier */
+struct tls_signature_hash_id {
+ /** Hash algorithm */
+ uint8_t hash;
+ /** Signature algorithm */
+ uint8_t signature;
+} __attribute__ (( packed ));
+
+/** A TLS signature algorithm */
+struct tls_signature_hash_algorithm {
+ /** Digest algorithm */
+ struct digest_algorithm *digest;
+ /** Public-key algorithm */
+ struct pubkey_algorithm *pubkey;
+ /** Numeric code */
+ struct tls_signature_hash_id code;
+};
+
+/** TLS pre-master secret */
+struct tls_pre_master_secret {
+ /** TLS version */
+ uint16_t version;
+ /** Random data */
+ uint8_t random[46];
+} __attribute__ (( packed ));
+
+/** TLS client random data */
+struct tls_client_random {
+ /** GMT Unix time */
+ uint32_t gmt_unix_time;
+ /** Random data */
+ uint8_t random[28];
+} __attribute__ (( packed ));
+
+/** An MD5+SHA1 context */
+struct md5_sha1_context {
+ /** MD5 context */
+ uint8_t md5[MD5_CTX_SIZE];
+ /** SHA-1 context */
+ uint8_t sha1[SHA1_CTX_SIZE];
+} __attribute__ (( packed ));
+
+/** MD5+SHA1 context size */
+#define MD5_SHA1_CTX_SIZE sizeof ( struct md5_sha1_context )
+
+/** An MD5+SHA1 digest */
+struct md5_sha1_digest {
+ /** MD5 digest */
+ uint8_t md5[MD5_DIGEST_SIZE];
+ /** SHA-1 digest */
+ uint8_t sha1[SHA1_DIGEST_SIZE];
+} __attribute__ (( packed ));
+
+/** MD5+SHA1 digest size */
+#define MD5_SHA1_DIGEST_SIZE sizeof ( struct md5_sha1_digest )
+
+/** A TLS session */
+struct tls_session {
+ /** Reference counter */
+ struct refcnt refcnt;
+
+ /** Server name */
+ const char *name;
+ /** Plaintext stream */
+ struct interface plainstream;
+ /** Ciphertext stream */
+ struct interface cipherstream;
+
+ /** Protocol version */
+ uint16_t version;
+ /** Current TX cipher specification */
+ struct tls_cipherspec tx_cipherspec;
+ /** Next TX cipher specification */
+ struct tls_cipherspec tx_cipherspec_pending;
+ /** Current RX cipher specification */
+ struct tls_cipherspec rx_cipherspec;
+ /** Next RX cipher specification */
+ struct tls_cipherspec rx_cipherspec_pending;
+ /** Premaster secret */
+ struct tls_pre_master_secret pre_master_secret;
+ /** Master secret */
+ uint8_t master_secret[48];
+ /** Server random bytes */
+ uint8_t server_random[32];
+ /** Client random bytes */
+ struct tls_client_random client_random;
+ /** MD5+SHA1 context for handshake verification */
+ uint8_t handshake_md5_sha1_ctx[MD5_SHA1_CTX_SIZE];
+ /** SHA256 context for handshake verification */
+ uint8_t handshake_sha256_ctx[SHA256_CTX_SIZE];
+ /** Digest algorithm used for handshake verification */
+ struct digest_algorithm *handshake_digest;
+ /** Digest algorithm context used for handshake verification */
+ uint8_t *handshake_ctx;
+ /** Public-key algorithm used for Certificate Verify (if sent) */
+ struct pubkey_algorithm *verify_pubkey;
+
+ /** Server certificate chain */
+ struct x509_chain *chain;
+ /** Certificate validator */
+ struct interface validator;
+
+ /** Client has finished security negotiation */
+ unsigned int client_finished;
+ /** Server has finished security negotiation */
+ unsigned int server_finished;
+
+ /** TX sequence number */
+ uint64_t tx_seq;
+ /** TX pending transmissions */
+ unsigned int tx_pending;
+ /** TX process */
+ struct process process;
+
+ /** RX sequence number */
+ uint64_t rx_seq;
+ /** RX state */
+ enum tls_rx_state rx_state;
+ /** Offset within current RX state */
+ size_t rx_rcvd;
+ /** Current received record header */
+ struct tls_header rx_header;
+ /** Current received raw data buffer */
+ void *rx_data;
+};
+
+extern int add_tls ( struct interface *xfer, const char *name,
+ struct interface **next );
+
+#endif /* _IPXE_TLS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/uaccess.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/uaccess.h
new file mode 100644
index 00000000..b574c318
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/uaccess.h
@@ -0,0 +1,345 @@
+#ifndef _IPXE_UACCESS_H
+#define _IPXE_UACCESS_H
+
+/**
+ * @file
+ *
+ * Access to external ("user") memory
+ *
+ * iPXE often needs to transfer data between internal and external
+ * buffers. On i386, the external buffers may require access via a
+ * different segment, and the buffer address cannot be encoded into a
+ * simple void * pointer. The @c userptr_t type encapsulates the
+ * information needed to identify an external buffer, and the
+ * copy_to_user() and copy_from_user() functions provide methods for
+ * transferring data between internal and external buffers.
+ *
+ * Note that userptr_t is an opaque type; in particular, performing
+ * arithmetic upon a userptr_t is not allowed.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <ipxe/api.h>
+#include <config/ioapi.h>
+
+/**
+ * A pointer to a user buffer
+ *
+ */
+typedef unsigned long userptr_t;
+
+/** Equivalent of NULL for user pointers */
+#define UNULL ( ( userptr_t ) 0 )
+
+/**
+ * @defgroup uaccess_trivial Trivial user access API implementations
+ *
+ * User access API implementations that can be used by environments in
+ * which virtual addresses allow access to all of memory.
+ *
+ * @{
+ *
+ */
+
+/**
+ * Convert virtual address to user pointer
+ *
+ * @v addr Virtual address
+ * @ret userptr User pointer
+ */
+static inline __always_inline userptr_t
+trivial_virt_to_user ( volatile const void *addr ) {
+ return ( ( userptr_t ) addr );
+}
+
+/**
+ * Convert user pointer to virtual address
+ *
+ * @v userptr User pointer
+ * @v offset Offset from user pointer
+ * @ret addr Virtual address
+ *
+ * This operation is not available under all memory models.
+ */
+static inline __always_inline void *
+trivial_user_to_virt ( userptr_t userptr, off_t offset ) {
+ return ( ( void * ) userptr + offset );
+}
+
+/**
+ * Add offset to user pointer
+ *
+ * @v userptr User pointer
+ * @v offset Offset
+ * @ret userptr New pointer value
+ */
+static inline __always_inline userptr_t
+trivial_userptr_add ( userptr_t userptr, off_t offset ) {
+ return ( userptr + offset );
+}
+
+/**
+ * Copy data between user buffers
+ *
+ * @v dest Destination
+ * @v dest_off Destination offset
+ * @v src Source
+ * @v src_off Source offset
+ * @v len Length
+ */
+static inline __always_inline void
+trivial_memcpy_user ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off, size_t len ) {
+ memcpy ( ( ( void * ) dest + dest_off ),
+ ( ( void * ) src + src_off ), len );
+}
+
+/**
+ * Copy data between user buffers, allowing for overlap
+ *
+ * @v dest Destination
+ * @v dest_off Destination offset
+ * @v src Source
+ * @v src_off Source offset
+ * @v len Length
+ */
+static inline __always_inline void
+trivial_memmove_user ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off, size_t len ) {
+ memmove ( ( ( void * ) dest + dest_off ),
+ ( ( void * ) src + src_off ), len );
+}
+
+/**
+ * Fill user buffer with a constant byte
+ *
+ * @v buffer User buffer
+ * @v offset Offset within buffer
+ * @v c Constant byte with which to fill
+ * @v len Length
+ */
+static inline __always_inline void
+trivial_memset_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
+ memset ( ( ( void * ) buffer + offset ), c, len );
+}
+
+/**
+ * Find length of NUL-terminated string in user buffer
+ *
+ * @v buffer User buffer
+ * @v offset Offset within buffer
+ * @ret len Length of string (excluding NUL)
+ */
+static inline __always_inline size_t
+trivial_strlen_user ( userptr_t buffer, off_t offset ) {
+ return strlen ( ( void * ) buffer + offset );
+}
+
+/**
+ * Find character in user buffer
+ *
+ * @v buffer User buffer
+ * @v offset Starting offset within buffer
+ * @v c Character to search for
+ * @v len Length of user buffer
+ * @ret offset Offset of character, or <0 if not found
+ */
+static inline __always_inline off_t
+trivial_memchr_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
+ void *found;
+
+ found = memchr ( ( ( void * ) buffer + offset ), c, len );
+ return ( found ? ( found - ( void * ) buffer ) : -1 );
+}
+
+/** @} */
+
+/**
+ * Calculate static inline user access API function name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ */
+#define UACCESS_INLINE( _subsys, _api_func ) \
+ SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
+
+/**
+ * Provide an user access API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_UACCESS( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( UACCESS_PREFIX_ ## _subsys, _api_func, _func )
+
+/**
+ * Provide a static inline user access API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ */
+#define PROVIDE_UACCESS_INLINE( _subsys, _api_func ) \
+ PROVIDE_SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
+
+/* Include all architecture-independent user access API headers */
+#include <ipxe/efi/efi_uaccess.h>
+#include <ipxe/linux/linux_uaccess.h>
+
+/* Include all architecture-dependent user access API headers */
+#include <bits/uaccess.h>
+
+/**
+ * Convert physical address to user pointer
+ *
+ * @v phys_addr Physical address
+ * @ret userptr User pointer
+ */
+userptr_t phys_to_user ( unsigned long phys_addr );
+
+/**
+ * Convert user pointer to physical address
+ *
+ * @v userptr User pointer
+ * @v offset Offset from user pointer
+ * @ret phys_addr Physical address
+ */
+unsigned long user_to_phys ( userptr_t userptr, off_t offset );
+
+/**
+ * Convert virtual address to user pointer
+ *
+ * @v addr Virtual address
+ * @ret userptr User pointer
+ */
+userptr_t virt_to_user ( volatile const void *addr );
+
+/**
+ * Convert user pointer to virtual address
+ *
+ * @v userptr User pointer
+ * @v offset Offset from user pointer
+ * @ret addr Virtual address
+ *
+ * This operation is not available under all memory models.
+ */
+void * user_to_virt ( userptr_t userptr, off_t offset );
+
+/**
+ * Add offset to user pointer
+ *
+ * @v userptr User pointer
+ * @v offset Offset
+ * @ret userptr New pointer value
+ */
+userptr_t userptr_add ( userptr_t userptr, off_t offset );
+
+/**
+ * Convert virtual address to a physical address
+ *
+ * @v addr Virtual address
+ * @ret phys_addr Physical address
+ */
+static inline __always_inline unsigned long
+virt_to_phys ( volatile const void *addr ) {
+ return user_to_phys ( virt_to_user ( addr ), 0 );
+}
+
+/**
+ * Convert physical address to a virtual address
+ *
+ * @v addr Virtual address
+ * @ret phys_addr Physical address
+ *
+ * This operation is not available under all memory models.
+ */
+static inline __always_inline void * phys_to_virt ( unsigned long phys_addr ) {
+ return user_to_virt ( phys_to_user ( phys_addr ), 0 );
+}
+
+/**
+ * Copy data between user buffers
+ *
+ * @v dest Destination
+ * @v dest_off Destination offset
+ * @v src Source
+ * @v src_off Source offset
+ * @v len Length
+ */
+void memcpy_user ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off, size_t len );
+
+/**
+ * Copy data to user buffer
+ *
+ * @v dest Destination
+ * @v dest_off Destination offset
+ * @v src Source
+ * @v len Length
+ */
+static inline __always_inline void
+copy_to_user ( userptr_t dest, off_t dest_off, const void *src, size_t len ) {
+ memcpy_user ( dest, dest_off, virt_to_user ( src ), 0, len );
+}
+
+/**
+ * Copy data from user buffer
+ *
+ * @v dest Destination
+ * @v src Source
+ * @v src_off Source offset
+ * @v len Length
+ */
+static inline __always_inline void
+copy_from_user ( void *dest, userptr_t src, off_t src_off, size_t len ) {
+ memcpy_user ( virt_to_user ( dest ), 0, src, src_off, len );
+}
+
+/**
+ * Copy data between user buffers, allowing for overlap
+ *
+ * @v dest Destination
+ * @v dest_off Destination offset
+ * @v src Source
+ * @v src_off Source offset
+ * @v len Length
+ */
+void memmove_user ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off, size_t len );
+
+/**
+ * Fill user buffer with a constant byte
+ *
+ * @v userptr User buffer
+ * @v offset Offset within buffer
+ * @v c Constant byte with which to fill
+ * @v len Length
+ */
+void memset_user ( userptr_t userptr, off_t offset, int c, size_t len );
+
+/**
+ * Find length of NUL-terminated string in user buffer
+ *
+ * @v userptr User buffer
+ * @v offset Offset within buffer
+ * @ret len Length of string (excluding NUL)
+ */
+size_t strlen_user ( userptr_t userptr, off_t offset );
+
+/**
+ * Find character in user buffer
+ *
+ * @v userptr User buffer
+ * @v offset Starting offset within buffer
+ * @v c Character to search for
+ * @v len Length of user buffer
+ * @ret offset Offset of character, or <0 if not found
+ */
+off_t memchr_user ( userptr_t userptr, off_t offset, int c, size_t len );
+
+#endif /* _IPXE_UACCESS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/udp.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/udp.h
new file mode 100644
index 00000000..5717ef21
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/udp.h
@@ -0,0 +1,45 @@
+#ifndef _IPXE_UDP_H
+#define _IPXE_UDP_H
+
+/** @file
+ *
+ * UDP protocol
+ *
+ * This file defines the iPXE UDP API.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/if_ether.h>
+
+struct interface;
+struct sockaddr;
+
+/**
+ * UDP constants
+ */
+
+/**
+ * A UDP header
+ */
+struct udp_header {
+ /** Source port */
+ uint16_t src;
+ /** Destination port */
+ uint16_t dest;
+ /** Length */
+ uint16_t len;
+ /** Checksum */
+ uint16_t chksum;
+};
+
+extern int udp_open_promisc ( struct interface *xfer );
+extern int udp_open ( struct interface *xfer, struct sockaddr *peer,
+ struct sockaddr *local );
+
+#endif /* _IPXE_UDP_H */
+
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/umalloc.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/umalloc.h
new file mode 100644
index 00000000..4b25e182
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/umalloc.h
@@ -0,0 +1,69 @@
+#ifndef _IPXE_UMALLOC_H
+#define _IPXE_UMALLOC_H
+
+/**
+ * @file
+ *
+ * User memory allocation
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/api.h>
+#include <config/umalloc.h>
+#include <ipxe/uaccess.h>
+
+/**
+ * Provide a user memory allocation API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_UMALLOC( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( UMALLOC_PREFIX_ ## _subsys, _api_func, _func )
+
+/* Include all architecture-independent I/O API headers */
+#include <ipxe/efi/efi_umalloc.h>
+#include <ipxe/linux/linux_umalloc.h>
+
+/* Include all architecture-dependent I/O API headers */
+#include <bits/umalloc.h>
+
+/**
+ * Reallocate external memory
+ *
+ * @v userptr Memory previously allocated by umalloc(), or UNULL
+ * @v new_size Requested size
+ * @ret userptr Allocated memory, or UNULL
+ *
+ * Calling realloc() with a new size of zero is a valid way to free a
+ * memory block.
+ */
+userptr_t urealloc ( userptr_t userptr, size_t new_size );
+
+/**
+ * Allocate external memory
+ *
+ * @v size Requested size
+ * @ret userptr Memory, or UNULL
+ *
+ * Memory is guaranteed to be aligned to a page boundary.
+ */
+static inline __always_inline userptr_t umalloc ( size_t size ) {
+ return urealloc ( UNULL, size );
+}
+
+/**
+ * Free external memory
+ *
+ * @v userptr Memory allocated by umalloc(), or UNULL
+ *
+ * If @c ptr is UNULL, no action is taken.
+ */
+static inline __always_inline void ufree ( userptr_t userptr ) {
+ urealloc ( userptr, 0 );
+}
+
+#endif /* _IPXE_UMALLOC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/uri.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/uri.h
new file mode 100644
index 00000000..b7b8b441
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/uri.h
@@ -0,0 +1,192 @@
+#ifndef _IPXE_URI_H
+#define _IPXE_URI_H
+
+/** @file
+ *
+ * Uniform Resource Identifiers
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <ipxe/refcnt.h>
+
+/** A Uniform Resource Identifier
+ *
+ * Terminology for this data structure is as per uri(7), except that
+ * "path" is defined to include the leading '/' for an absolute path.
+ *
+ * Note that all fields within a URI are optional and may be NULL.
+ *
+ * The pointers to the various fields are packed together so they can
+ * be accessed in array fashion in some places in uri.c where doing so
+ * saves significant code size.
+ *
+ * Some examples are probably helpful:
+ *
+ * http://www.ipxe.org/wiki :
+ *
+ * scheme = "http", host = "www.ipxe.org", path = "/wiki"
+ *
+ * /var/lib/tftpboot :
+ *
+ * path = "/var/lib/tftpboot"
+ *
+ * mailto:bob@nowhere.com :
+ *
+ * scheme = "mailto", opaque = "bob@nowhere.com"
+ *
+ * ftp://joe:secret@insecure.org:8081/hidden/path/to?what=is#this
+ *
+ * scheme = "ftp", user = "joe", password = "secret",
+ * host = "insecure.org", port = "8081", path = "/hidden/path/to",
+ * query = "what=is", fragment = "this"
+ */
+struct uri {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Scheme */
+ const char *scheme;
+ /** Opaque part */
+ const char *opaque;
+ /** User name */
+ const char *user;
+ /** Password */
+ const char *password;
+ /** Host name */
+ const char *host;
+ /** Port number */
+ const char *port;
+ /** Path */
+ const char *path;
+ /** Query */
+ const char *query;
+ /** Fragment */
+ const char *fragment;
+} __attribute__ (( packed ));
+
+/** A field in a URI
+ *
+ * The order of the indices in this enumeration must match the order
+ * of the fields in the URI structure.
+ */
+enum {
+ URI_SCHEME = 0, URI_SCHEME_BIT = ( 1 << URI_SCHEME ),
+ URI_OPAQUE = 1, URI_OPAQUE_BIT = ( 1 << URI_OPAQUE ),
+ URI_USER = 2, URI_USER_BIT = ( 1 << URI_USER ),
+ URI_PASSWORD = 3, URI_PASSWORD_BIT = ( 1 << URI_PASSWORD ),
+ URI_HOST = 4, URI_HOST_BIT = ( 1 << URI_HOST ),
+ URI_PORT = 5, URI_PORT_BIT = ( 1 << URI_PORT ),
+ URI_PATH = 6, URI_PATH_BIT = ( 1 << URI_PATH ),
+ URI_QUERY = 7, URI_QUERY_BIT = ( 1 << URI_QUERY ),
+ URI_FRAGMENT = 8, URI_FRAGMENT_BIT = ( 1 << URI_FRAGMENT ),
+
+ URI_FIRST_FIELD = URI_SCHEME,
+ URI_LAST_FIELD = URI_FRAGMENT,
+};
+
+/** Extract field from URI */
+#define uri_get_field( uri, field ) (&uri->scheme)[field]
+
+/** All URI fields */
+#define URI_ALL ( URI_SCHEME_BIT | URI_OPAQUE_BIT | URI_USER_BIT | \
+ URI_PASSWORD_BIT | URI_HOST_BIT | URI_PORT_BIT | \
+ URI_PATH_BIT | URI_QUERY_BIT | URI_FRAGMENT_BIT )
+
+/** URI fields that should be decoded on storage */
+#define URI_ENCODED ( URI_USER_BIT | URI_PASSWORD_BIT | URI_HOST_BIT | \
+ URI_PATH_BIT | URI_QUERY_BIT | URI_FRAGMENT_BIT )
+
+/**
+ * URI is an absolute URI
+ *
+ * @v uri URI
+ * @ret is_absolute URI is absolute
+ *
+ * An absolute URI begins with a scheme, e.g. "http:" or "mailto:".
+ * Note that this is a separate concept from a URI with an absolute
+ * path.
+ */
+static inline int uri_is_absolute ( struct uri *uri ) {
+ return ( uri->scheme != NULL );
+}
+
+/**
+ * URI has a path
+ *
+ * @v uri URI
+ * @ret has_path URI has a path
+ */
+static inline int uri_has_path ( struct uri *uri ) {
+ return ( uri->path && ( uri->path[0] != '\0' ) );
+}
+
+/**
+ * URI has an absolute path
+ *
+ * @v uri URI
+ * @ret has_absolute_path URI has an absolute path
+ *
+ * An absolute path begins with a '/'. Note that this is a separate
+ * concept from an absolute URI. Note also that a URI may not have a
+ * path at all.
+ */
+static inline int uri_has_absolute_path ( struct uri *uri ) {
+ return ( uri->path && ( uri->path[0] == '/' ) );
+}
+
+/**
+ * URI has a relative path
+ *
+ * @v uri URI
+ * @ret has_relative_path URI has a relative path
+ *
+ * A relative path begins with something other than a '/'. Note that
+ * this is a separate concept from a relative URI. Note also that a
+ * URI may not have a path at all.
+ */
+static inline int uri_has_relative_path ( struct uri *uri ) {
+ return ( uri->path && ( uri->path[0] != '/' ) );
+}
+
+/**
+ * Increment URI reference count
+ *
+ * @v uri URI, or NULL
+ * @ret uri URI as passed in
+ */
+static inline __attribute__ (( always_inline )) struct uri *
+uri_get ( struct uri *uri ) {
+ ref_get ( &uri->refcnt );
+ return uri;
+}
+
+/**
+ * Decrement URI reference count
+ *
+ * @v uri URI, or NULL
+ */
+static inline __attribute__ (( always_inline )) void
+uri_put ( struct uri *uri ) {
+ ref_put ( &uri->refcnt );
+}
+
+extern struct uri *cwuri;
+
+extern struct uri * parse_uri ( const char *uri_string );
+extern unsigned int uri_port ( struct uri *uri, unsigned int default_port );
+extern int unparse_uri ( char *buf, size_t size, struct uri *uri,
+ unsigned int fields );
+extern struct uri * uri_dup ( struct uri *uri );
+extern char * resolve_path ( const char *base_path,
+ const char *relative_path );
+extern struct uri * resolve_uri ( struct uri *base_uri,
+ struct uri *relative_uri );
+extern void churi ( struct uri *uri );
+extern size_t uri_encode ( const char *raw_string, char *buf, ssize_t len,
+ int field );
+extern size_t uri_decode ( const char *encoded_string, char *buf, ssize_t len );
+
+#endif /* _IPXE_URI_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/uuid.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/uuid.h
new file mode 100644
index 00000000..5de56b94
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/uuid.h
@@ -0,0 +1,33 @@
+#ifndef _IPXE_UUID_H
+#define _IPXE_UUID_H
+
+/** @file
+ *
+ * Universally unique IDs
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/** A universally unique ID */
+union uuid {
+ /** Canonical form (00000000-0000-0000-0000-000000000000) */
+ struct {
+ /** 8 hex digits, big-endian */
+ uint32_t a;
+ /** 2 hex digits, big-endian */
+ uint16_t b;
+ /** 2 hex digits, big-endian */
+ uint16_t c;
+ /** 2 hex digits, big-endian */
+ uint16_t d;
+ /** 12 hex digits, big-endian */
+ uint8_t e[6];
+ } canonical;
+ uint8_t raw[16];
+};
+
+extern char * uuid_ntoa ( const union uuid *uuid );
+
+#endif /* _IPXE_UUID_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/validator.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/validator.h
new file mode 100644
index 00000000..23bdab42
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/validator.h
@@ -0,0 +1,17 @@
+#ifndef _IPXE_VALIDATOR_H
+#define _IPXE_VALIDATOR_H
+
+/** @file
+ *
+ * Certificate validator
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/interface.h>
+#include <ipxe/x509.h>
+
+extern int create_validator ( struct interface *job, struct x509_chain *chain );
+
+#endif /* _IPXE_VALIDATOR_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/virtio-pci.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/virtio-pci.h
new file mode 100644
index 00000000..a09c4631
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/virtio-pci.h
@@ -0,0 +1,101 @@
+#ifndef _VIRTIO_PCI_H_
+# define _VIRTIO_PCI_H_
+
+/* A 32-bit r/o bitmask of the features supported by the host */
+#define VIRTIO_PCI_HOST_FEATURES 0
+
+/* A 32-bit r/w bitmask of features activated by the guest */
+#define VIRTIO_PCI_GUEST_FEATURES 4
+
+/* A 32-bit r/w PFN for the currently selected queue */
+#define VIRTIO_PCI_QUEUE_PFN 8
+
+/* A 16-bit r/o queue size for the currently selected queue */
+#define VIRTIO_PCI_QUEUE_NUM 12
+
+/* A 16-bit r/w queue selector */
+#define VIRTIO_PCI_QUEUE_SEL 14
+
+/* A 16-bit r/w queue notifier */
+#define VIRTIO_PCI_QUEUE_NOTIFY 16
+
+/* An 8-bit device status register. */
+#define VIRTIO_PCI_STATUS 18
+
+/* An 8-bit r/o interrupt status register. Reading the value will return the
+ * current contents of the ISR and will also clear it. This is effectively
+ * a read-and-acknowledge. */
+#define VIRTIO_PCI_ISR 19
+
+/* The bit of the ISR which indicates a device configuration change. */
+#define VIRTIO_PCI_ISR_CONFIG 0x2
+
+/* The remaining space is defined by each driver as the per-driver
+ * configuration space */
+#define VIRTIO_PCI_CONFIG 20
+
+/* Virtio ABI version, this must match exactly */
+#define VIRTIO_PCI_ABI_VERSION 0
+
+static inline u32 vp_get_features(unsigned int ioaddr)
+{
+ return inl(ioaddr + VIRTIO_PCI_HOST_FEATURES);
+}
+
+static inline void vp_set_features(unsigned int ioaddr, u32 features)
+{
+ outl(features, ioaddr + VIRTIO_PCI_GUEST_FEATURES);
+}
+
+static inline void vp_get(unsigned int ioaddr, unsigned offset,
+ void *buf, unsigned len)
+{
+ u8 *ptr = buf;
+ unsigned i;
+
+ for (i = 0; i < len; i++)
+ ptr[i] = inb(ioaddr + VIRTIO_PCI_CONFIG + offset + i);
+}
+
+static inline u8 vp_get_status(unsigned int ioaddr)
+{
+ return inb(ioaddr + VIRTIO_PCI_STATUS);
+}
+
+static inline void vp_set_status(unsigned int ioaddr, u8 status)
+{
+ if (status == 0) /* reset */
+ return;
+ outb(status, ioaddr + VIRTIO_PCI_STATUS);
+}
+
+static inline u8 vp_get_isr(unsigned int ioaddr)
+{
+ return inb(ioaddr + VIRTIO_PCI_ISR);
+}
+
+static inline void vp_reset(unsigned int ioaddr)
+{
+ outb(0, ioaddr + VIRTIO_PCI_STATUS);
+ (void)inb(ioaddr + VIRTIO_PCI_ISR);
+}
+
+static inline void vp_notify(unsigned int ioaddr, int queue_index)
+{
+ outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
+}
+
+static inline void vp_del_vq(unsigned int ioaddr, int queue_index)
+{
+ /* select the queue */
+
+ outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
+
+ /* deactivate the queue */
+
+ outl(0, ioaddr + VIRTIO_PCI_QUEUE_PFN);
+}
+
+int vp_find_vq(unsigned int ioaddr, int queue_index,
+ struct vring_virtqueue *vq);
+#endif /* _VIRTIO_PCI_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/virtio-ring.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/virtio-ring.h
new file mode 100644
index 00000000..0afe8bab
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/virtio-ring.h
@@ -0,0 +1,142 @@
+#ifndef _VIRTIO_RING_H_
+# define _VIRTIO_RING_H_
+#define PAGE_SHIFT (12)
+#define PAGE_SIZE (1<<PAGE_SHIFT)
+#define PAGE_MASK (PAGE_SIZE-1)
+
+/* Status byte for guest to report progress, and synchronize features. */
+/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
+#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
+/* We have found a driver for the device. */
+#define VIRTIO_CONFIG_S_DRIVER 2
+/* Driver has used its parts of the config, and is happy */
+#define VIRTIO_CONFIG_S_DRIVER_OK 4
+/* We've given up on this device. */
+#define VIRTIO_CONFIG_S_FAILED 0x80
+
+#define MAX_QUEUE_NUM (256)
+
+#define VRING_DESC_F_NEXT 1
+#define VRING_DESC_F_WRITE 2
+
+#define VRING_AVAIL_F_NO_INTERRUPT 1
+
+#define VRING_USED_F_NO_NOTIFY 1
+
+struct vring_desc
+{
+ u64 addr;
+ u32 len;
+ u16 flags;
+ u16 next;
+};
+
+struct vring_avail
+{
+ u16 flags;
+ u16 idx;
+ u16 ring[0];
+};
+
+struct vring_used_elem
+{
+ u32 id;
+ u32 len;
+};
+
+struct vring_used
+{
+ u16 flags;
+ u16 idx;
+ struct vring_used_elem ring[];
+};
+
+struct vring {
+ unsigned int num;
+ struct vring_desc *desc;
+ struct vring_avail *avail;
+ struct vring_used *used;
+};
+
+#define vring_size(num) \
+ (((((sizeof(struct vring_desc) * num) + \
+ (sizeof(struct vring_avail) + sizeof(u16) * num)) \
+ + PAGE_MASK) & ~PAGE_MASK) + \
+ (sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num))
+
+typedef unsigned char virtio_queue_t[PAGE_MASK + vring_size(MAX_QUEUE_NUM)];
+
+struct vring_virtqueue {
+ virtio_queue_t queue;
+ struct vring vring;
+ u16 free_head;
+ u16 last_used_idx;
+ void *vdata[MAX_QUEUE_NUM];
+ /* PCI */
+ int queue_index;
+};
+
+struct vring_list {
+ char *addr;
+ unsigned int length;
+};
+
+static inline void vring_init(struct vring *vr,
+ unsigned int num, unsigned char *queue)
+{
+ unsigned int i;
+ unsigned long pa;
+
+ vr->num = num;
+
+ /* physical address of desc must be page aligned */
+
+ pa = virt_to_phys(queue);
+ pa = (pa + PAGE_MASK) & ~PAGE_MASK;
+ vr->desc = phys_to_virt(pa);
+
+ vr->avail = (struct vring_avail *)&vr->desc[num];
+
+ /* physical address of used must be page aligned */
+
+ pa = virt_to_phys(&vr->avail->ring[num]);
+ pa = (pa + PAGE_MASK) & ~PAGE_MASK;
+ vr->used = phys_to_virt(pa);
+
+ for (i = 0; i < num - 1; i++)
+ vr->desc[i].next = i + 1;
+ vr->desc[i].next = 0;
+}
+
+static inline void vring_enable_cb(struct vring_virtqueue *vq)
+{
+ vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
+}
+
+static inline void vring_disable_cb(struct vring_virtqueue *vq)
+{
+ vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
+}
+
+
+/*
+ * vring_more_used
+ *
+ * is there some used buffers ?
+ *
+ */
+
+static inline int vring_more_used(struct vring_virtqueue *vq)
+{
+ wmb();
+ return vq->last_used_idx != vq->vring.used->idx;
+}
+
+void vring_detach(struct vring_virtqueue *vq, unsigned int head);
+void *vring_get_buf(struct vring_virtqueue *vq, unsigned int *len);
+void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[],
+ unsigned int out, unsigned int in,
+ void *index, int num_added);
+void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added);
+
+#endif /* _VIRTIO_RING_H_ */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/vlan.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/vlan.h
new file mode 100644
index 00000000..d9f4484e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/vlan.h
@@ -0,0 +1,69 @@
+#ifndef _IPXE_VLAN_H
+#define _IPXE_VLAN_H
+
+/**
+ * @file
+ *
+ * Virtual LANs
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** A VLAN header */
+struct vlan_header {
+ /** Tag control information */
+ uint16_t tci;
+ /** Encapsulated protocol */
+ uint16_t net_proto;
+} __attribute__ (( packed ));
+
+/**
+ * Extract VLAN tag from tag control information
+ *
+ * @v tci Tag control information
+ * @ret tag VLAN tag
+ */
+#define VLAN_TAG( tci ) ( (tci) & 0x0fff )
+
+/**
+ * Extract VLAN priority from tag control information
+ *
+ * @v tci Tag control information
+ * @ret priority Priority
+ */
+#define VLAN_PRIORITY( tci ) ( (tci) >> 13 )
+
+/**
+ * Construct VLAN tag control information
+ *
+ * @v tag VLAN tag
+ * @v priority Priority
+ * @ret tci Tag control information
+ */
+#define VLAN_TCI( tag, priority ) ( ( (priority) << 13 ) | (tag) )
+
+/**
+ * Check VLAN tag is valid
+ *
+ * @v tag VLAN tag
+ * @ret is_valid VLAN tag is valid
+ */
+#define VLAN_TAG_IS_VALID( tag ) ( (tag) < 0xfff )
+
+/**
+ * Check VLAN priority is valid
+ *
+ * @v priority VLAN priority
+ * @ret is_valid VLAN priority is valid
+ */
+#define VLAN_PRIORITY_IS_VALID( priority ) ( (priority) <= 7 )
+
+extern struct net_device * vlan_find ( struct net_device *trunk,
+ unsigned int tag );
+extern int vlan_can_be_trunk ( struct net_device *trunk );
+extern int vlan_create ( struct net_device *trunk, unsigned int tag,
+ unsigned int priority );
+extern int vlan_destroy ( struct net_device *netdev );
+
+#endif /* _IPXE_VLAN_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/vsprintf.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/vsprintf.h
new file mode 100644
index 00000000..c48c97a8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/vsprintf.h
@@ -0,0 +1,74 @@
+#ifndef _IPXE_VSPRINTF_H
+#define _IPXE_VSPRINTF_H
+
+/** @file
+ *
+ * printf() and friends
+ *
+ * Etherboot's printf() functions understand the following subset of
+ * the standard C printf()'s format specifiers:
+ *
+ * - Flag characters
+ * - '#' - Alternate form (i.e. "0x" prefix)
+ * - '0' - Zero-pad
+ * - Field widths
+ * - Length modifiers
+ * - 'hh' - Signed / unsigned char
+ * - 'h' - Signed / unsigned short
+ * - 'l' - Signed / unsigned long
+ * - 'll' - Signed / unsigned long long
+ * - 'z' - Signed / unsigned size_t
+ * - Conversion specifiers
+ * - 'd' - Signed decimal
+ * - 'x','X' - Unsigned hexadecimal
+ * - 'c' - Character
+ * - 's' - String
+ * - 'p' - Pointer
+ *
+ * Hexadecimal numbers are always zero-padded to the specified field
+ * width (if any); decimal numbers are always space-padded. Decimal
+ * long longs are not supported.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+/**
+ * A printf context
+ *
+ * Contexts are used in order to be able to share code between
+ * vprintf() and vsnprintf(), without requiring the allocation of a
+ * buffer for vprintf().
+ */
+struct printf_context {
+ /**
+ * Character handler
+ *
+ * @v ctx Context
+ * @v c Character
+ *
+ * This method is called for each character written to the
+ * formatted string.
+ */
+ void ( * handler ) ( struct printf_context *ctx, unsigned int c );
+ /** Length of formatted string
+ *
+ * When handler() is called, @len will be set to the number of
+ * characters written so far (i.e. zero for the first call to
+ * handler()).
+ */
+ size_t len;
+};
+
+extern size_t vcprintf ( struct printf_context *ctx, const char *fmt,
+ va_list args );
+extern int vssnprintf ( char *buf, ssize_t ssize, const char *fmt,
+ va_list args );
+extern int __attribute__ (( format ( printf, 3, 4 ) ))
+ssnprintf ( char *buf, ssize_t ssize, const char *fmt, ... );
+
+#endif /* _IPXE_VSPRINTF_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/wpa.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/wpa.h
new file mode 100644
index 00000000..29342282
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/wpa.h
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _IPXE_WPA_H
+#define _IPXE_WPA_H
+
+#include <ipxe/ieee80211.h>
+#include <ipxe/list.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Common definitions for all types of WPA-protected networks.
+ */
+
+
+/** EAPOL-Key type field for modern 802.11i/RSN WPA packets */
+#define EAPOL_KEY_TYPE_RSN 2
+
+/** Old EAPOL-Key type field used by WPA1 hardware before 802.11i ratified */
+#define EAPOL_KEY_TYPE_WPA 254
+
+
+/**
+ * @defgroup eapol_key_info EAPOL-Key Info field bits
+ * @{
+ */
+
+/** Key descriptor version, indicating WPA or WPA2 */
+#define EAPOL_KEY_INFO_VERSION 0x0007
+
+/** Key type bit, indicating pairwise or group */
+#define EAPOL_KEY_INFO_TYPE 0x0008
+
+/** Key install bit; set on message 3 except when legacy hacks are used */
+#define EAPOL_KEY_INFO_INSTALL 0x0040
+
+/** Key ACK bit; set when a response is required, on all messages except #4 */
+#define EAPOL_KEY_INFO_KEY_ACK 0x0080
+
+/** Key MIC bit; set when the MIC field is valid, on messages 3 and 4 */
+#define EAPOL_KEY_INFO_KEY_MIC 0x0100
+
+/** Secure bit; set when both sides have both keys, on messages 3 and 4 */
+#define EAPOL_KEY_INFO_SECURE 0x0200
+
+/** Error bit; set on a MIC failure for TKIP */
+#define EAPOL_KEY_INFO_ERROR 0x0400
+
+/** Request bit; set when authentication is initiated by the Peer (unusual) */
+#define EAPOL_KEY_INFO_REQUEST 0x0800
+
+/** Key Encrypted bit; set when the Key Data field is encrypted */
+#define EAPOL_KEY_INFO_KEY_ENC 0x1000
+
+/** SMC Message bit; set when this frame is part of an IBSS SMK handshake */
+#define EAPOL_KEY_INFO_SMC_MESS 0x2000
+
+
+/** Key descriptor version field value for WPA (TKIP) */
+#define EAPOL_KEY_VERSION_WPA 1
+
+/** Key descriptor version field value for WPA2 (CCMP) */
+#define EAPOL_KEY_VERSION_WPA2 2
+
+/** Key type field value for a PTK (pairwise) key handshake */
+#define EAPOL_KEY_TYPE_PTK 0x0008
+
+/** Key type field value for a GTK (group) key handshake */
+#define EAPOL_KEY_TYPE_GTK 0x0000
+
+/** @} */
+
+
+
+/** An EAPOL-Key packet.
+ *
+ * These are used for the WPA 4-Way Handshake, whether or not prior
+ * authentication has been performed using EAP.
+ *
+ * On LANs, an eapol_key_pkt is always encapsulated in the data field
+ * of an eapol_frame, with the frame's type code set to EAPOL_TYPE_KEY.
+ *
+ * Unlike 802.11 frame headers, the fields in this structure are
+ * stored in big-endian!
+ */
+struct eapol_key_pkt
+{
+ /** One of the EAPOL_KEY_TYPE_* defines. */
+ u8 type;
+
+ /** Bitfield of key characteristics, network byte order */
+ u16 info;
+
+ /** Length of encryption key to be used, network byte order
+ *
+ * This is 16 for CCMP, 32 for TKIP, and 5 or 13 for WEP.
+ */
+ u16 keysize;
+
+ /** Monotonically increasing value for EAPOL-Key conversations
+ *
+ * In another classic demonstration of overengineering, this
+ * 8-byte value will rarely be anything above 1. It's stored
+ * in network byte order.
+ */
+ u64 replay;
+
+ /** Nonce value
+ *
+ * This is the authenticator's ANonce in frame 1, the peer's
+ * SNonce in frame 2, and 0 in frames 3 and 4.
+ */
+ u8 nonce[32];
+
+ /** Initialization vector
+ *
+ * This contains the IV used with the Key Encryption Key, or 0
+ * if the key is unencrypted or encrypted using an algorithm
+ * that does not require an IV.
+ */
+ u8 iv[16];
+
+ /** Receive sequence counter for GTK
+ *
+ * This is used to synchronize the client's replay counter for
+ * ordinary data packets. The first six bytes contain PN0
+ * through PN5 for CCMP mode, or TSC0 through TSC5 for TKIP
+ * mode. The last two bytes are zero.
+ */
+ u8 rsc[8];
+
+ /** Reserved bytes */
+ u8 _reserved[8];
+
+ /** Message integrity code over the entire EAPOL frame
+ *
+ * This is calculated using HMAC-MD5 when the key descriptor
+ * version field in @a info is 1, and HMAC-SHA1 ignoring the
+ * last 4 bytes of the hash when the version field in @a info
+ * is 2.
+ */
+ u8 mic[16];
+
+ /** Length of the @a data field in bytes, network byte order */
+ u16 datalen;
+
+ /** Key data
+ *
+ * This is formatted as a series of 802.11 information
+ * elements, with cryptographic data encapsulated using a
+ * "vendor-specific IE" code and an IEEE-specified OUI.
+ */
+ u8 data[0];
+} __attribute__ (( packed ));
+
+
+/** WPA handshaking state */
+enum wpa_state {
+ /** Waiting for PMK to be set */
+ WPA_WAITING = 0,
+
+ /** Ready for 4-Way Handshake */
+ WPA_READY,
+
+ /** Performing 4-Way Handshake */
+ WPA_WORKING,
+
+ /** 4-Way Handshake succeeded */
+ WPA_SUCCESS,
+
+ /** 4-Way Handshake failed */
+ WPA_FAILURE,
+};
+
+/** Bitfield indicating a selection of WPA transient keys */
+enum wpa_keymask {
+ /** Pairwise transient key */
+ WPA_PTK = 1,
+
+ /** Group transient key */
+ WPA_GTK = 2,
+};
+
+
+/** Length of a nonce */
+#define WPA_NONCE_LEN 32
+
+/** Length of a TKIP main key */
+#define WPA_TKIP_KEY_LEN 16
+
+/** Length of a TKIP MIC key */
+#define WPA_TKIP_MIC_KEY_LEN 8
+
+/** Length of a CCMP key */
+#define WPA_CCMP_KEY_LEN 16
+
+/** Length of an EAPOL Key Confirmation Key */
+#define WPA_KCK_LEN 16
+
+/** Length of an EAPOL Key Encryption Key */
+#define WPA_KEK_LEN 16
+
+/** Usual length of a Pairwise Master Key */
+#define WPA_PMK_LEN 32
+
+/** Length of a PMKID */
+#define WPA_PMKID_LEN 16
+
+
+/** Structure of the Temporal Key for TKIP encryption */
+struct tkip_tk
+{
+ /** Main key: input to TKIP Phase 1 and Phase 2 key mixing functions */
+ u8 key[WPA_TKIP_KEY_LEN];
+
+ /** Michael MIC keys */
+ struct {
+ /** MIC key for packets from the AP */
+ u8 rx[WPA_TKIP_MIC_KEY_LEN];
+
+ /** MIC key for packets to the AP */
+ u8 tx[WPA_TKIP_MIC_KEY_LEN];
+ } __attribute__ (( packed )) mic;
+} __attribute__ (( packed ));
+
+/** Structure of a generic Temporal Key */
+union wpa_tk
+{
+ /** CCMP key */
+ u8 ccmp[WPA_CCMP_KEY_LEN];
+
+ /** TKIP keys */
+ struct tkip_tk tkip;
+};
+
+/** Structure of the Pairwise Transient Key */
+struct wpa_ptk
+{
+ /** EAPOL-Key Key Confirmation Key (KCK) */
+ u8 kck[WPA_KCK_LEN];
+
+ /** EAPOL-Key Key Encryption Key (KEK) */
+ u8 kek[WPA_KEK_LEN];
+
+ /** Temporal key */
+ union wpa_tk tk;
+} __attribute__ (( packed ));
+
+/** Structure of the Group Transient Key */
+struct wpa_gtk
+{
+ /** Temporal key */
+ union wpa_tk tk;
+} __attribute__ (( packed ));
+
+
+/** Common context for WPA security handshaking
+ *
+ * Any implementor of a particular handshaking type (e.g. PSK or EAP)
+ * must include this structure at the very beginning of their private
+ * data context structure, to allow the EAPOL-Key handling code to
+ * work. When the preliminary authentication is done, it is necessary
+ * to call wpa_start(), passing the PMK (derived from PSK or EAP MSK)
+ * as an argument. The handshaker can use its @a step function to
+ * monitor @a state in this wpa_ctx structure for success or
+ * failure. On success, the keys will be available in @a ptk and @a
+ * gtk according to the state of the @a valid bitmask.
+ *
+ * After an initial success, the parent handshaker does not need to
+ * concern itself with rekeying; the WPA common code takes care of
+ * that.
+ */
+struct wpa_common_ctx
+{
+ /** 802.11 device we are authenticating for */
+ struct net80211_device *dev;
+
+ /** The Pairwise Master Key to use in handshaking
+ *
+ * This is set either by running the PBKDF2 algorithm on a
+ * passphrase with the SSID as salt to generate a pre-shared
+ * key, or by copying the first 32 bytes of the EAP Master
+ * Session Key in 802.1X-served authentication.
+ */
+ u8 pmk[WPA_PMK_LEN];
+
+ /** Length of the Pairwise Master Key
+ *
+ * This is always 32 except with one EAP method which only
+ * gives 16 bytes.
+ */
+ int pmk_len;
+
+ /** State of EAPOL-Key handshaking */
+ enum wpa_state state;
+
+ /** Replay counter for this association
+ *
+ * This stores the replay counter value for the most recent
+ * packet we've accepted. It is initially initialised to ~0 to
+ * show we'll accept anything.
+ */
+ u64 replay;
+
+ /** Mask of valid keys after authentication success
+ *
+ * If the PTK is not valid, the GTK should be used for both
+ * unicast and multicast decryption; if the GTK is not valid,
+ * multicast packets cannot be decrypted.
+ */
+ enum wpa_keymask valid;
+
+ /** The cipher to use for unicast RX and all TX */
+ enum net80211_crypto_alg crypt;
+
+ /** The cipher to use for broadcast and multicast RX */
+ enum net80211_crypto_alg gcrypt;
+
+ /** The Pairwise Transient Key derived from the handshake */
+ struct wpa_ptk ptk;
+
+ /** The Group Transient Key derived from the handshake */
+ struct wpa_gtk gtk;
+
+ /** Authenticator-provided nonce */
+ u8 Anonce[WPA_NONCE_LEN];
+
+ /** Supplicant-generated nonce (that's us) */
+ u8 Snonce[WPA_NONCE_LEN];
+
+ /** Whether we should refrain from generating another SNonce */
+ int have_Snonce;
+
+ /** Data in WPA or RSN IE from AP's beacon frame */
+ void *ap_rsn_ie;
+
+ /** Length of @a ap_rsn_ie */
+ int ap_rsn_ie_len;
+
+ /** Whether @a ap_rsn_ie is an RSN IE (as opposed to old WPA) */
+ int ap_rsn_is_rsn;
+
+ /** List entry */
+ struct list_head list;
+};
+
+
+/** WPA handshake key integrity and encryption handler
+ *
+ * Note that due to the structure of the 4-Way Handshake we never
+ * actually need to encrypt key data, only decrypt it.
+ */
+struct wpa_kie {
+ /** Value of version bits in EAPOL-Key info field for which to use
+ *
+ * This should be one of the @c EAPOL_KEY_VERSION_* constants.
+ */
+ int version;
+
+ /** Calculate MIC over message
+ *
+ * @v kck Key Confirmation Key, 16 bytes
+ * @v msg Message to calculate MIC over
+ * @v len Number of bytes to calculate MIC over
+ * @ret mic Calculated MIC, 16 bytes long
+ *
+ * The @a mic return may point within @a msg, so it must not
+ * be filled until the calculation has been performed.
+ */
+ void ( * mic ) ( const void *kck, const void *msg, size_t len,
+ void *mic );
+
+ /** Decrypt key data
+ *
+ * @v kek Key Encryption Key, 16 bytes
+ * @v iv Initialisation vector for encryption, 16 bytes
+ * @v msg Message to decrypt (Key Data field)
+ * @v len Length of message
+ * @ret msg Decrypted message in place of original
+ * @ret len Updated to reflect encrypted length
+ * @ret rc Return status code
+ *
+ * The decrypted message is written over the encrypted one.
+ */
+ int ( * decrypt ) ( const void *kek, const void *iv, void *msg,
+ u16 *len );
+};
+
+#define WPA_KIES __table ( struct wpa_kie, "wpa_kies" )
+#define __wpa_kie __table_entry ( WPA_KIES, 01 )
+
+
+
+/**
+ * @defgroup wpa_kde Key descriptor element types
+ * @{
+ */
+
+/** Payload structure of the GTK-encapsulating KDE
+ *
+ * This does not include the IE type, length, or OUI bytes, which are
+ * generic to all KDEs.
+ */
+struct wpa_kde_gtk_encap
+{
+ /** Key ID and TX bit */
+ u8 id;
+
+ /** Reserved byte */
+ u8 _rsvd;
+
+ /** Encapsulated group transient key */
+ struct wpa_gtk gtk;
+} __attribute__ (( packed ));
+
+/** Mask for Key ID in wpa_kde_gtk::id field */
+#define WPA_GTK_KID 0x03
+
+/** Mask for Tx bit in wpa_kde_gtk::id field */
+#define WPA_GTK_TXBIT 0x04
+
+
+/** KDE type for an encapsulated Group Transient Key (requires encryption) */
+#define WPA_KDE_GTK _MKOUI ( 0x00, 0x0F, 0xAC, 0x01 )
+
+/** KDE type for a MAC address */
+#define WPA_KDE_MAC _MKOUI ( 0x00, 0x0F, 0xAC, 0x03 )
+
+/** KDE type for a PMKID */
+#define WPA_KDE_PMKID _MKOUI ( 0x00, 0x0F, 0xAC, 0x04 )
+
+/** KDE type for a nonce */
+#define WPA_KDE_NONCE _MKOUI ( 0x00, 0x0F, 0xAC, 0x06 )
+
+/** KDE type for a lifetime value */
+#define WPA_KDE_LIFETIME _MKOUI ( 0x00, 0x0F, 0xAC, 0x07 )
+
+
+/** Any key descriptor element type
+ *
+ * KDEs follow the 802.11 information element format of a type byte
+ * (in this case "vendor-specific", with the requisite OUI+subtype
+ * after length) and a length byte whose value does not include the
+ * length of the type and length bytes.
+ */
+struct wpa_kde
+{
+ /** Information element type: always 0xDD (IEEE80211_IE_VENDOR) */
+ u8 ie_type;
+
+ /** Length, not including ie_type and length fields */
+ u8 len;
+
+ /** OUI + type byte */
+ u32 oui_type;
+
+ /** Payload data */
+ union {
+ /** For GTK-type KDEs, encapsulated GTK */
+ struct wpa_kde_gtk_encap gtk_encap;
+
+ /** For MAC-type KDEs, the MAC address */
+ u8 mac[ETH_ALEN];
+
+ /** For PMKID-type KDEs, the PMKID */
+ u8 pmkid[WPA_PMKID_LEN];
+
+ /** For Nonce-type KDEs, the nonce */
+ u8 nonce[WPA_NONCE_LEN];
+
+ /** For Lifetime-type KDEs, the lifetime in seconds
+ *
+ * This is in network byte order!
+ */
+ u32 lifetime;
+ };
+} __attribute__ (( packed ));
+
+/** @} */
+
+int wpa_make_rsn_ie ( struct net80211_device *dev, union ieee80211_ie **ie );
+int wpa_start ( struct net80211_device *dev, struct wpa_common_ctx *ctx,
+ const void *pmk, size_t pmk_len );
+void wpa_stop ( struct net80211_device *dev );
+
+#endif /* _IPXE_WPA_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/x509.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/x509.h
new file mode 100644
index 00000000..a5626c8a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/x509.h
@@ -0,0 +1,373 @@
+#ifndef _IPXE_X509_H
+#define _IPXE_X509_H
+
+/** @file
+ *
+ * X.509 certificates
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stddef.h>
+#include <time.h>
+#include <ipxe/asn1.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/list.h>
+
+/** An X.509 serial number */
+struct x509_serial {
+ /** Raw serial number */
+ struct asn1_cursor raw;
+};
+
+/** An X.509 issuer */
+struct x509_issuer {
+ /** Raw issuer */
+ struct asn1_cursor raw;
+};
+
+/** An X.509 time */
+struct x509_time {
+ /** Seconds since the Epoch */
+ time_t time;
+};
+
+/** An X.509 certificate validity period */
+struct x509_validity {
+ /** Not valid before */
+ struct x509_time not_before;
+ /** Not valid after */
+ struct x509_time not_after;
+};
+
+/** An X.509 certificate public key */
+struct x509_public_key {
+ /** Raw public key information */
+ struct asn1_cursor raw;
+ /** Public key algorithm */
+ struct asn1_algorithm *algorithm;
+ /** Raw public key bit string */
+ struct asn1_bit_string raw_bits;
+};
+
+/** An X.509 certificate subject */
+struct x509_subject {
+ /** Raw subject */
+ struct asn1_cursor raw;
+ /** Common name */
+ char *name;
+ /** Public key information */
+ struct x509_public_key public_key;
+};
+
+/** An X.509 certificate signature */
+struct x509_signature {
+ /** Signature algorithm */
+ struct asn1_algorithm *algorithm;
+ /** Signature value */
+ struct asn1_bit_string value;
+};
+
+/** An X.509 certificate basic constraints set */
+struct x509_basic_constraints {
+ /** Subject is a CA */
+ int ca;
+ /** Path length */
+ unsigned int path_len;
+};
+
+/** Unlimited path length
+ *
+ * We use -2U, since this quantity represents one *fewer* than the
+ * maximum number of remaining certificates in a chain.
+ */
+#define X509_PATH_LEN_UNLIMITED -2U
+
+/** An X.509 certificate key usage */
+struct x509_key_usage {
+ /** Key usage extension is present */
+ int present;
+ /** Usage bits */
+ unsigned int bits;
+};
+
+/** X.509 certificate key usage bits */
+enum x509_key_usage_bits {
+ X509_DIGITAL_SIGNATURE = 0x0080,
+ X509_NON_REPUDIATION = 0x0040,
+ X509_KEY_ENCIPHERMENT = 0x0020,
+ X509_DATA_ENCIPHERMENT = 0x0010,
+ X509_KEY_AGREEMENT = 0x0008,
+ X509_KEY_CERT_SIGN = 0x0004,
+ X509_CRL_SIGN = 0x0002,
+ X509_ENCIPHER_ONLY = 0x0001,
+ X509_DECIPHER_ONLY = 0x8000,
+};
+
+/** An X.509 certificate extended key usage */
+struct x509_extended_key_usage {
+ /** Usage bits */
+ unsigned int bits;
+};
+
+/** X.509 certificate extended key usage bits
+ *
+ * Extended key usages are identified by OID; these bits are purely an
+ * internal definition.
+ */
+enum x509_extended_key_usage_bits {
+ X509_CODE_SIGNING = 0x0001,
+ X509_OCSP_SIGNING = 0x0002,
+};
+
+/** X.509 certificate OCSP responder */
+struct x509_ocsp_responder {
+ /** URI */
+ char *uri;
+ /** OCSP status is good */
+ int good;
+};
+
+/** X.509 certificate authority information access */
+struct x509_authority_info_access {
+ /** OCSP responder */
+ struct x509_ocsp_responder ocsp;
+};
+
+/** An X.509 certificate extensions set */
+struct x509_extensions {
+ /** Basic constraints */
+ struct x509_basic_constraints basic;
+ /** Key usage */
+ struct x509_key_usage usage;
+ /** Extended key usage */
+ struct x509_extended_key_usage ext_usage;
+ /** Authority information access */
+ struct x509_authority_info_access auth_info;
+};
+
+/** An X.509 certificate */
+struct x509_certificate {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** List of certificates in cache */
+ struct list_head list;
+
+ /** Certificate has been validated */
+ int valid;
+ /** Maximum number of subsequent certificates in chain */
+ unsigned int path_remaining;
+
+ /** Raw certificate */
+ struct asn1_cursor raw;
+ /** Version */
+ unsigned int version;
+ /** Serial number */
+ struct x509_serial serial;
+ /** Raw tbsCertificate */
+ struct asn1_cursor tbs;
+ /** Signature algorithm */
+ struct asn1_algorithm *signature_algorithm;
+ /** Issuer */
+ struct x509_issuer issuer;
+ /** Validity */
+ struct x509_validity validity;
+ /** Subject */
+ struct x509_subject subject;
+ /** Signature */
+ struct x509_signature signature;
+ /** Extensions */
+ struct x509_extensions extensions;
+};
+
+/**
+ * Get reference to X.509 certificate
+ *
+ * @v cert X.509 certificate
+ * @ret cert X.509 certificate
+ */
+static inline __attribute__ (( always_inline )) struct x509_certificate *
+x509_get ( struct x509_certificate *cert ) {
+ ref_get ( &cert->refcnt );
+ return cert;
+}
+
+/**
+ * Drop reference to X.509 certificate
+ *
+ * @v cert X.509 certificate
+ */
+static inline __attribute__ (( always_inline )) void
+x509_put ( struct x509_certificate *cert ) {
+ ref_put ( &cert->refcnt );
+}
+
+/** A link in an X.509 certificate chain */
+struct x509_link {
+ /** List of links */
+ struct list_head list;
+ /** Certificate */
+ struct x509_certificate *cert;
+};
+
+/** An X.509 certificate chain */
+struct x509_chain {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** List of links */
+ struct list_head links;
+};
+
+/**
+ * Get reference to X.509 certificate chain
+ *
+ * @v chain X.509 certificate chain
+ * @ret chain X.509 certificate chain
+ */
+static inline __attribute__ (( always_inline )) struct x509_chain *
+x509_chain_get ( struct x509_chain *chain ) {
+ ref_get ( &chain->refcnt );
+ return chain;
+}
+
+/**
+ * Drop reference to X.509 certificate chain
+ *
+ * @v chain X.509 certificate chain
+ */
+static inline __attribute__ (( always_inline )) void
+x509_chain_put ( struct x509_chain *chain ) {
+ ref_put ( &chain->refcnt );
+}
+
+/**
+ * Get first certificate in X.509 certificate chain
+ *
+ * @v chain X.509 certificate chain
+ * @ret cert X.509 certificate, or NULL
+ */
+static inline __attribute__ (( always_inline )) struct x509_certificate *
+x509_first ( struct x509_chain *chain ) {
+ struct x509_link *link;
+
+ link = list_first_entry ( &chain->links, struct x509_link, list );
+ return ( link ? link->cert : NULL );
+}
+
+/**
+ * Get last certificate in X.509 certificate chain
+ *
+ * @v chain X.509 certificate chain
+ * @ret cert X.509 certificate, or NULL
+ */
+static inline __attribute__ (( always_inline )) struct x509_certificate *
+x509_last ( struct x509_chain *chain ) {
+ struct x509_link *link;
+
+ link = list_last_entry ( &chain->links, struct x509_link, list );
+ return ( link ? link->cert : NULL );
+}
+
+/** An X.509 extension */
+struct x509_extension {
+ /** Name */
+ const char *name;
+ /** Object identifier */
+ struct asn1_cursor oid;
+ /** Parse extension
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+ int ( * parse ) ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw );
+};
+
+/** An X.509 key purpose */
+struct x509_key_purpose {
+ /** Name */
+ const char *name;
+ /** Object identifier */
+ struct asn1_cursor oid;
+ /** Extended key usage bits */
+ unsigned int bits;
+};
+
+/** An X.509 access method */
+struct x509_access_method {
+ /** Name */
+ const char *name;
+ /** Object identifier */
+ struct asn1_cursor oid;
+ /** Parse access method
+ *
+ * @v cert X.509 certificate
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+ int ( * parse ) ( struct x509_certificate *cert,
+ const struct asn1_cursor *raw );
+};
+
+/** An X.509 root certificate store */
+struct x509_root {
+ /** Fingerprint digest algorithm */
+ struct digest_algorithm *digest;
+ /** Number of certificates */
+ unsigned int count;
+ /** Certificate fingerprints */
+ const void *fingerprints;
+};
+
+extern int x509_certificate ( const void *data, size_t len,
+ struct x509_certificate **cert );
+extern int x509_validate ( struct x509_certificate *cert,
+ struct x509_certificate *issuer,
+ time_t time, struct x509_root *root );
+
+extern struct x509_chain * x509_alloc_chain ( void );
+extern int x509_append ( struct x509_chain *chain,
+ struct x509_certificate *cert );
+extern int x509_append_raw ( struct x509_chain *chain, const void *data,
+ size_t len );
+extern int x509_auto_append ( struct x509_chain *chain,
+ struct x509_chain *certs );
+extern int x509_validate_chain ( struct x509_chain *chain, time_t time,
+ struct x509_root *root );
+
+/* Functions exposed only for unit testing */
+extern int x509_check_issuer ( struct x509_certificate *cert,
+ struct x509_certificate *issuer );
+extern void x509_fingerprint ( struct x509_certificate *cert,
+ struct digest_algorithm *digest,
+ void *fingerprint );
+extern int x509_check_root ( struct x509_certificate *cert,
+ struct x509_root *root );
+extern int x509_check_time ( struct x509_certificate *cert, time_t time );
+
+/**
+ * Invalidate X.509 certificate
+ *
+ * @v cert X.509 certificate
+ */
+static inline void x509_invalidate ( struct x509_certificate *cert ) {
+ cert->valid = 0;
+ cert->path_remaining = 0;
+}
+
+/**
+ * Invalidate X.509 certificate chain
+ *
+ * @v chain X.509 certificate chain
+ */
+static inline void x509_invalidate_chain ( struct x509_chain *chain ) {
+ struct x509_link *link;
+
+ list_for_each_entry ( link, &chain->links, list )
+ x509_invalidate ( link->cert );
+}
+
+#endif /* _IPXE_X509_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/xfer.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/xfer.h
new file mode 100644
index 00000000..1167e5cb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/xfer.h
@@ -0,0 +1,107 @@
+#ifndef _IPXE_XFER_H
+#define _IPXE_XFER_H
+
+/** @file
+ *
+ * Data transfer interfaces
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <ipxe/interface.h>
+
+struct xfer_metadata;
+struct io_buffer;
+struct sockaddr;
+struct net_device;
+
+/** Data transfer metadata */
+struct xfer_metadata {
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more @c XFER_FL_XXX
+ * constants.
+ */
+ unsigned int flags;
+ /** Offset of data within stream
+ *
+ * This is an absolute offset if the @c XFER_FL_ABS_OFFSET
+ * flag is set, otherwise a relative offset. (A freshly
+ * zeroed @c xfer_metadata structure therefore represents a
+ * relative offset of zero, i.e. no offset from the current
+ * position.)
+ */
+ off_t offset;
+ /** Source socket address, or NULL */
+ struct sockaddr *src;
+ /** Destination socket address, or NULL */
+ struct sockaddr *dest;
+ /** Network device, or NULL */
+ struct net_device *netdev;
+};
+
+/** Offset is absolute */
+#define XFER_FL_ABS_OFFSET 0x0001
+
+/** Sender is relinquishing use of half-duplex channel */
+#define XFER_FL_OVER 0x0002
+
+/** This is the final data transfer */
+#define XFER_FL_OUT 0x0004
+
+/** Data content represents a command or status message
+ *
+ * The flag @c XFER_FL_RESPONSE is used to distinguish between a
+ * command message and a status message.
+ */
+#define XFER_FL_CMD_STAT 0x0008
+
+/** Data content is a response */
+#define XFER_FL_RESPONSE 0x0010
+
+/* Data transfer interface operations */
+
+extern int xfer_vredirect ( struct interface *intf, int type,
+ va_list args );
+#define xfer_vredirect_TYPE( object_type ) \
+ typeof ( int ( object_type, int type, va_list args ) )
+
+extern size_t xfer_window ( struct interface *intf );
+#define xfer_window_TYPE( object_type ) \
+ typeof ( size_t ( object_type ) )
+
+extern void xfer_window_changed ( struct interface *intf );
+#define xfer_window_changed_TYPE( object_type ) \
+ typeof ( void ( object_type ) )
+
+extern struct io_buffer * xfer_alloc_iob ( struct interface *intf,
+ size_t len );
+#define xfer_alloc_iob_TYPE( object_type ) \
+ typeof ( struct io_buffer * ( object_type, size_t len ) )
+
+extern int xfer_deliver ( struct interface *intf,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta );
+#define xfer_deliver_TYPE( object_type ) \
+ typeof ( int ( object_type, struct io_buffer *iobuf, \
+ struct xfer_metadata *meta ) )
+
+/* Data transfer interface helper functions */
+
+extern int xfer_redirect ( struct interface *xfer, int type, ... );
+extern int xfer_deliver_iob ( struct interface *intf,
+ struct io_buffer *iobuf );
+extern int xfer_deliver_raw_meta ( struct interface *intf, const void *data,
+ size_t len, struct xfer_metadata *meta );
+extern int xfer_deliver_raw ( struct interface *intf,
+ const void *data, size_t len );
+extern int xfer_vprintf ( struct interface *intf,
+ const char *format, va_list args );
+extern int __attribute__ (( format ( printf, 2, 3 ) ))
+xfer_printf ( struct interface *intf, const char *format, ... );
+extern int xfer_seek ( struct interface *intf, off_t offset );
+
+#endif /* _IPXE_XFER_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/ipxe/xferbuf.h b/src/VBox/Devices/PC/ipxe/src/include/ipxe/xferbuf.h
new file mode 100644
index 00000000..2ca871e5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/ipxe/xferbuf.h
@@ -0,0 +1,31 @@
+#ifndef _IPXE_XFERBUF_H
+#define _IPXE_XFERBUF_H
+
+/** @file
+ *
+ * Data transfer buffer
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+
+/** A data transfer buffer */
+struct xfer_buffer {
+ /** Data */
+ void *data;
+ /** Size of data */
+ size_t len;
+ /** Current offset within data */
+ size_t pos;
+};
+
+extern void xferbuf_done ( struct xfer_buffer *xferbuf );
+extern int xferbuf_deliver ( struct xfer_buffer *xferbuf,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta );
+
+#endif /* _IPXE_XFERBUF_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/libgen.h b/src/VBox/Devices/PC/ipxe/src/include/libgen.h
new file mode 100644
index 00000000..7e94881a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/libgen.h
@@ -0,0 +1,9 @@
+#ifndef _LIBGEN_H
+#define _LIBGEN_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern char * basename ( char *path );
+extern char * dirname ( char *path );
+
+#endif /* _LIBGEN_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/linux_api.h b/src/VBox/Devices/PC/ipxe/src/include/linux_api.h
new file mode 100644
index 00000000..94dc991f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/linux_api.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _LINUX_API_H
+#define _LINUX_API_H
+
+/** * @file
+ *
+ * Linux API prototypes.
+ * Most of the functions map directly to linux syscalls and are the equivalent
+ * of POSIX functions with the linux_ prefix removed.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <bits/linux_api.h>
+#include <bits/linux_api_platform.h>
+
+#include <stdint.h>
+
+#define __KERNEL_STRICT_NAMES
+#include <linux/types.h>
+#include <linux/posix_types.h>
+typedef __kernel_pid_t pid_t;
+typedef __kernel_suseconds_t suseconds_t;
+typedef __kernel_loff_t loff_t;
+#include <linux/time.h>
+#include <linux/mman.h>
+#include <linux/fcntl.h>
+#include <linux/ioctl.h>
+#include <linux/poll.h>
+typedef unsigned long nfds_t;
+typedef uint32_t useconds_t;
+#define MAP_FAILED ( ( void * ) -1 )
+
+extern long linux_syscall ( int number, ... );
+
+extern int linux_open ( const char *pathname, int flags );
+extern int linux_close ( int fd );
+extern __kernel_ssize_t linux_read ( int fd, void *buf, __kernel_size_t count );
+extern __kernel_ssize_t linux_write ( int fd, const void *buf,
+ __kernel_size_t count );
+extern int linux_fcntl ( int fd, int cmd, ... );
+extern int linux_ioctl ( int fd, int request, ... );
+extern int linux_poll ( struct pollfd *fds, nfds_t nfds, int timeout );
+extern int linux_nanosleep ( const struct timespec *req, struct timespec *rem );
+extern int linux_usleep ( useconds_t usec );
+extern int linux_gettimeofday ( struct timeval *tv, struct timezone *tz );
+extern void * linux_mmap ( void *addr, __kernel_size_t length, int prot,
+ int flags, int fd, off_t offset );
+extern void * linux_mremap ( void *old_address, __kernel_size_t old_size,
+ __kernel_size_t new_size, int flags );
+extern int linux_munmap ( void *addr, __kernel_size_t length );
+
+extern const char * linux_strerror ( int errnum );
+
+#endif /* _LINUX_API_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/little_bswap.h b/src/VBox/Devices/PC/ipxe/src/include/little_bswap.h
new file mode 100644
index 00000000..a5dc9c87
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/little_bswap.h
@@ -0,0 +1,35 @@
+#ifndef ETHERBOOT_LITTLE_BSWAP_H
+#define ETHERBOOT_LITTLE_BSWAP_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#define ntohl(x) __bswap_32(x)
+#define htonl(x) __bswap_32(x)
+#define ntohs(x) __bswap_16(x)
+#define htons(x) __bswap_16(x)
+#define cpu_to_le64(x) (x)
+#define cpu_to_le32(x) (x)
+#define cpu_to_le16(x) (x)
+#define cpu_to_be64(x) __bswap_64(x)
+#define cpu_to_be32(x) __bswap_32(x)
+#define cpu_to_be16(x) __bswap_16(x)
+#define le64_to_cpu(x) (x)
+#define le32_to_cpu(x) (x)
+#define le16_to_cpu(x) (x)
+#define be64_to_cpu(x) __bswap_64(x)
+#define be32_to_cpu(x) __bswap_32(x)
+#define be16_to_cpu(x) __bswap_16(x)
+#define cpu_to_le64s(x) do {} while (0)
+#define cpu_to_le32s(x) do {} while (0)
+#define cpu_to_le16s(x) do {} while (0)
+#define cpu_to_be64s(x) __bswap_64s(x)
+#define cpu_to_be32s(x) __bswap_32s(x)
+#define cpu_to_be16s(x) __bswap_16s(x)
+#define le64_to_cpus(x) do {} while (0)
+#define le32_to_cpus(x) do {} while (0)
+#define le16_to_cpus(x) do {} while (0)
+#define be64_to_cpus(x) __bswap_64s(x)
+#define be32_to_cpus(x) __bswap_32s(x)
+#define be16_to_cpus(x) __bswap_16s(x)
+
+#endif /* ETHERBOOT_LITTLE_BSWAP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/mii.h b/src/VBox/Devices/PC/ipxe/src/include/mii.h
new file mode 100644
index 00000000..e2afef85
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/mii.h
@@ -0,0 +1,157 @@
+#ifndef _MII_H_
+#define _MII_H_
+
+/** @file
+ *
+ * Media Independent Interface constants
+ *
+ * Extracted from Linux's include/linux/mii.h
+ *
+ * Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com)
+ *
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/* Generic MII registers. */
+#define MII_BMCR 0x00 /* Basic mode control register */
+#define MII_BMSR 0x01 /* Basic mode status register */
+#define MII_PHYSID1 0x02 /* PHYS ID 1 */
+#define MII_PHYSID2 0x03 /* PHYS ID 2 */
+#define MII_ADVERTISE 0x04 /* Advertisement control reg */
+#define MII_LPA 0x05 /* Link partner ability reg */
+#define MII_EXPANSION 0x06 /* Expansion register */
+#define MII_CTRL1000 0x09 /* 1000BASE-T control */
+#define MII_STAT1000 0x0a /* 1000BASE-T status */
+#define MII_ESTATUS 0x0f /* Extended Status */
+#define MII_DCOUNTER 0x12 /* Disconnect counter */
+#define MII_FCSCOUNTER 0x13 /* False carrier counter */
+#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
+#define MII_RERRCOUNTER 0x15 /* Receive error counter */
+#define MII_SREVISION 0x16 /* Silicon revision */
+#define MII_RESV1 0x17 /* Reserved... */
+#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
+#define MII_PHYADDR 0x19 /* PHY address */
+#define MII_RESV2 0x1a /* Reserved... */
+#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
+#define MII_NCONFIG 0x1c /* Network interface config */
+
+/* Basic mode control register. */
+#define BMCR_RESV 0x003f /* Unused... */
+#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
+#define BMCR_CTST 0x0080 /* Collision test */
+#define BMCR_FULLDPLX 0x0100 /* Full duplex */
+#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
+#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
+#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
+#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
+#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
+#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
+#define BMCR_RESET 0x8000 /* Reset the DP83840 */
+
+/* Basic mode status register. */
+#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
+#define BMSR_JCD 0x0002 /* Jabber detected */
+#define BMSR_LSTATUS 0x0004 /* Link status */
+#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
+#define BMSR_RFAULT 0x0010 /* Remote fault detected */
+#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
+#define BMSR_RESV 0x00c0 /* Unused... */
+#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
+#define BMSR_100HALF2 0x0200 /* Can do 100BASE-T2 HDX */
+#define BMSR_100FULL2 0x0400 /* Can do 100BASE-T2 FDX */
+#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
+#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
+#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
+#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
+#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
+
+/* Advertisement control register. */
+#define ADVERTISE_SLCT 0x001f /* Selector bits */
+#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
+#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
+#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
+#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
+#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
+#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
+#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
+#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
+#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
+#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
+#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
+#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
+#define ADVERTISE_RESV 0x1000 /* Unused... */
+#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
+#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
+#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
+
+#define ADVERTISE_FULL ( ADVERTISE_100FULL | ADVERTISE_10FULL | \
+ ADVERTISE_CSMA)
+#define ADVERTISE_ALL ( ADVERTISE_10HALF | ADVERTISE_10FULL | \
+ ADVERTISE_100HALF | ADVERTISE_100FULL )
+
+/* Link partner ability register. */
+#define LPA_SLCT 0x001f /* Same as advertise selector */
+#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
+#define LPA_1000XFULL 0x0020 /* Can do 1000BASE-X full-duplex */
+#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
+#define LPA_1000XHALF 0x0040 /* Can do 1000BASE-X half-duplex */
+#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
+#define LPA_1000XPAUSE 0x0080 /* Can do 1000BASE-X pause */
+#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
+#define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/
+#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
+#define LPA_PAUSE_CAP 0x0400 /* Can pause */
+#define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */
+#define LPA_RESV 0x1000 /* Unused... */
+#define LPA_RFAULT 0x2000 /* Link partner faulted */
+#define LPA_LPACK 0x4000 /* Link partner acked us */
+#define LPA_NPAGE 0x8000 /* Next page bit */
+
+#define LPA_DUPLEX ( LPA_10FULL | LPA_100FULL )
+#define LPA_100 ( LPA_100FULL | LPA_100HALF | LPA_100BASE4 )
+
+/* Expansion register for auto-negotiation. */
+#define EXPANSION_NWAY 0x0001 /* Can do N-way auto-nego */
+#define EXPANSION_LCWP 0x0002 /* Got new RX page code word */
+#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */
+#define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */
+#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */
+#define EXPANSION_RESV 0xffe0 /* Unused... */
+
+#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */
+#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */
+
+/* N-way test register. */
+#define NWAYTEST_RESV1 0x00ff /* Unused... */
+#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
+#define NWAYTEST_RESV2 0xfe00 /* Unused... */
+
+/* 1000BASE-T Control register */
+#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */
+#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */
+
+/* 1000BASE-T Status register */
+#define LPA_1000LOCALRXOK 0x2000 /* Partner local receiver status */
+#define LPA_1000REMRXOK 0x1000 /* Partner remote receiver status */
+#define LPA_1000FULL 0x0800 /* Partner 1000BASE-T full duplex */
+#define LPA_1000HALF 0x0400 /* Partner 1000BASE-T half duplex */
+
+#include <ipxe/netdevice.h>
+
+struct mii_if_info {
+ int phy_id;
+ int advertising;
+ int phy_id_mask;
+ int reg_num_mask;
+
+ unsigned int full_duplex : 1; /* is full duplex? */
+ unsigned int force_media : 1; /* is autoneg. disabled? */
+ unsigned int supports_gmii : 1; /* are GMII registers supported? */
+
+ struct net_device *dev;
+ int (*mdio_read) (struct net_device *dev, int phy_id, int location);
+ void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
+};
+
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/nic.h b/src/VBox/Devices/PC/ipxe/src/include/nic.h
new file mode 100644
index 00000000..22f2c4da
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/nic.h
@@ -0,0 +1,280 @@
+ /*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef NIC_H
+#define NIC_H
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include <ipxe/isapnp.h>
+#include <ipxe/isa.h>
+#include <ipxe/eisa.h>
+#include <ipxe/mca.h>
+#include <ipxe/io.h>
+
+typedef enum {
+ DISABLE = 0,
+ ENABLE,
+ FORCE
+} irq_action_t;
+
+typedef enum duplex {
+ HALF_DUPLEX = 1,
+ FULL_DUPLEX
+} duplex_t;
+
+/*
+ * Structure returned from eth_probe and passed to other driver
+ * functions.
+ */
+struct nic {
+ struct nic_operations *nic_op;
+ int flags; /* driver specific flags */
+ unsigned char *node_addr;
+ unsigned char *packet;
+ unsigned int packetlen;
+ unsigned int ioaddr;
+ unsigned char irqno;
+ unsigned int mbps;
+ duplex_t duplex;
+ void *priv_data; /* driver private data */
+};
+
+struct nic_operations {
+ int ( *connect ) ( struct nic * );
+ int ( *poll ) ( struct nic *, int retrieve );
+ void ( *transmit ) ( struct nic *, const char *,
+ unsigned int, unsigned int, const char * );
+ void ( *irq ) ( struct nic *, irq_action_t );
+};
+
+extern struct nic nic;
+
+static inline int eth_poll ( int retrieve ) {
+ return nic.nic_op->poll ( &nic, retrieve );
+}
+
+static inline void eth_transmit ( const char *dest, unsigned int type,
+ unsigned int size, const void *packet ) {
+ nic.nic_op->transmit ( &nic, dest, type, size, packet );
+}
+
+/*
+ * Function prototypes
+ *
+ */
+extern int dummy_connect ( struct nic *nic );
+extern void dummy_irq ( struct nic *nic, irq_action_t irq_action );
+extern int legacy_probe ( void *hwdev,
+ void ( * set_drvdata ) ( void *hwdev, void *priv ),
+ struct device *dev,
+ int ( * probe ) ( struct nic *nic, void *hwdev ),
+ void ( * disable ) ( struct nic *nic, void *hwdev ));
+void legacy_remove ( void *hwdev,
+ void * ( * get_drvdata ) ( void *hwdev ),
+ void ( * disable ) ( struct nic *nic, void *hwdev ) );
+
+#define PCI_DRIVER(_name,_ids,_class) \
+ static inline int \
+ _name ## _pci_legacy_probe ( struct pci_device *pci ); \
+ static inline void \
+ _name ## _pci_legacy_remove ( struct pci_device *pci ); \
+ struct pci_driver _name __pci_driver = { \
+ .ids = _ids, \
+ .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
+ .probe = _name ## _pci_legacy_probe, \
+ .remove = _name ## _pci_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( pci );
+
+static inline void legacy_pci_set_drvdata ( void *hwdev, void *priv ) {
+ pci_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_pci_get_drvdata ( void *hwdev ) {
+ return pci_get_drvdata ( hwdev );
+}
+
+#define ISAPNP_DRIVER(_name,_ids) \
+ static inline int \
+ _name ## _isapnp_legacy_probe ( struct isapnp_device *isapnp, \
+ const struct isapnp_device_id *id ); \
+ static inline void \
+ _name ## _isapnp_legacy_remove ( struct isapnp_device *isapnp ); \
+ struct isapnp_driver _name __isapnp_driver = { \
+ .ids = _ids, \
+ .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
+ .probe = _name ## _isapnp_legacy_probe, \
+ .remove = _name ## _isapnp_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( isapnp );
+
+static inline void legacy_isapnp_set_drvdata ( void *hwdev, void *priv ) {
+ isapnp_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_isapnp_get_drvdata ( void *hwdev ) {
+ return isapnp_get_drvdata ( hwdev );
+}
+
+#define EISA_DRIVER(_name,_ids) \
+ static inline int \
+ _name ## _eisa_legacy_probe ( struct eisa_device *eisa, \
+ const struct eisa_device_id *id ); \
+ static inline void \
+ _name ## _eisa_legacy_remove ( struct eisa_device *eisa ); \
+ struct eisa_driver _name __eisa_driver = { \
+ .ids = _ids, \
+ .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
+ .probe = _name ## _eisa_legacy_probe, \
+ .remove = _name ## _eisa_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( eisa );
+
+static inline void legacy_eisa_set_drvdata ( void *hwdev, void *priv ) {
+ eisa_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_eisa_get_drvdata ( void *hwdev ) {
+ return eisa_get_drvdata ( hwdev );
+}
+
+#define MCA_DRIVER(_name,_ids) \
+ static inline int \
+ _name ## _mca_legacy_probe ( struct mca_device *mca, \
+ const struct mca_device_id *id ); \
+ static inline void \
+ _name ## _mca_legacy_remove ( struct mca_device *mca ); \
+ struct mca_driver _name __mca_driver = { \
+ .ids = _ids, \
+ .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
+ .probe = _name ## _mca_legacy_probe, \
+ .remove = _name ## _mca_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( mca );
+
+static inline void legacy_mca_set_drvdata ( void *hwdev, void *priv ) {
+ mca_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_mca_get_drvdata ( void *hwdev ) {
+ return mca_get_drvdata ( hwdev );
+}
+
+#define ISA_DRIVER(_name,_probe_addrs,_probe_addr,_vendor_id,_prod_id) \
+ static inline int \
+ _name ## _isa_legacy_probe ( struct isa_device *isa ); \
+ static inline int \
+ _name ## _isa_legacy_probe_at_addr ( struct isa_device *isa ) { \
+ if ( ! _probe_addr ( isa->ioaddr ) ) \
+ return -ENODEV; \
+ return _name ## _isa_legacy_probe ( isa ); \
+ } \
+ static inline void \
+ _name ## _isa_legacy_remove ( struct isa_device *isa ); \
+ static const char _name ## _text[]; \
+ struct isa_driver _name __isa_driver = { \
+ .name = _name ## _text, \
+ .probe_addrs = _probe_addrs, \
+ .addr_count = ( sizeof ( _probe_addrs ) / \
+ sizeof ( _probe_addrs[0] ) ), \
+ .vendor_id = _vendor_id, \
+ .prod_id = _prod_id, \
+ .probe = _name ## _isa_legacy_probe_at_addr, \
+ .remove = _name ## _isa_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( isa );
+
+static inline void legacy_isa_set_drvdata ( void *hwdev, void *priv ) {
+ isa_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_isa_get_drvdata ( void *hwdev ) {
+ return isa_get_drvdata ( hwdev );
+}
+
+#undef DRIVER
+#define DRIVER(_name_text,_unused2,_unused3,_name,_probe,_disable) \
+ static const char _name ## _text[] = _name_text; \
+ static inline int \
+ _name ## _probe ( struct nic *nic, void *hwdev ) { \
+ return _probe ( nic, hwdev ); \
+ } \
+ static inline void \
+ _name ## _disable ( struct nic *nic, void *hwdev ) { \
+ void ( * _unsafe_disable ) () = _disable; \
+ _unsafe_disable ( nic, hwdev ); \
+ } \
+ static inline int \
+ _name ## _pci_legacy_probe ( struct pci_device *pci ) { \
+ return legacy_probe ( pci, legacy_pci_set_drvdata, \
+ &pci->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _pci_legacy_remove ( struct pci_device *pci ) { \
+ return legacy_remove ( pci, legacy_pci_get_drvdata, \
+ _name ## _disable ); \
+ } \
+ static inline int \
+ _name ## _isapnp_legacy_probe ( struct isapnp_device *isapnp, \
+ const struct isapnp_device_id *id __unused ) { \
+ return legacy_probe ( isapnp, legacy_isapnp_set_drvdata, \
+ &isapnp->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _isapnp_legacy_remove ( struct isapnp_device *isapnp ) { \
+ return legacy_remove ( isapnp, legacy_isapnp_get_drvdata, \
+ _name ## _disable ); \
+ } \
+ static inline int \
+ _name ## _eisa_legacy_probe ( struct eisa_device *eisa, \
+ const struct eisa_device_id *id __unused ) { \
+ return legacy_probe ( eisa, legacy_eisa_set_drvdata, \
+ &eisa->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _eisa_legacy_remove ( struct eisa_device *eisa ) { \
+ return legacy_remove ( eisa, legacy_eisa_get_drvdata, \
+ _name ## _disable ); \
+ } \
+ static inline int \
+ _name ## _mca_legacy_probe ( struct mca_device *mca, \
+ const struct mca_device_id *id __unused ) { \
+ return legacy_probe ( mca, legacy_mca_set_drvdata, \
+ &mca->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _mca_legacy_remove ( struct mca_device *mca ) { \
+ return legacy_remove ( mca, legacy_mca_get_drvdata, \
+ _name ## _disable ); \
+ } \
+ static inline int \
+ _name ## _isa_legacy_probe ( struct isa_device *isa ) { \
+ return legacy_probe ( isa, legacy_isa_set_drvdata, \
+ &isa->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _isa_legacy_remove ( struct isa_device *isa ) { \
+ return legacy_remove ( isa, legacy_isa_get_drvdata, \
+ _name ## _disable ); \
+ }
+
+#endif /* NIC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/old_tcp.h b/src/VBox/Devices/PC/ipxe/src/include/old_tcp.h
new file mode 100644
index 00000000..93e1485e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/old_tcp.h
@@ -0,0 +1,37 @@
+#ifndef _TCP_H
+#define _TCP_H
+
+#define TCP_INITIAL_TIMEOUT (3*TICKS_PER_SEC)
+#define TCP_MAX_TIMEOUT (60*TICKS_PER_SEC)
+#define TCP_MIN_TIMEOUT (TICKS_PER_SEC)
+#define TCP_MAX_RETRY 10
+#define TCP_MAX_HEADER ((int)sizeof(struct iphdr)+64)
+#define TCP_MIN_WINDOW (1500-TCP_MAX_HEADER)
+#define TCP_MAX_WINDOW (65535-TCP_MAX_HEADER)
+
+#define FIN 1
+#define SYN 2
+#define RST 4
+#define PSH 8
+#define ACK 16
+#define URG 32
+
+
+struct tcphdr {
+ uint16_t src;
+ uint16_t dst;
+ int32_t seq;
+ int32_t ack;
+ uint16_t ctrl;
+ uint16_t window;
+ uint16_t chksum;
+ uint16_t urgent;
+};
+
+extern int tcp_transaction ( unsigned long destip, unsigned int destsock,
+ void *ptr,
+ int (*send)(int len, void *buf, void *ptr),
+ int (*recv)(int len, const void *buf, void *ptr));
+
+
+#endif /* _TCP_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/pc_kbd.h b/src/VBox/Devices/PC/ipxe/src/include/pc_kbd.h
new file mode 100644
index 00000000..c125efa0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/pc_kbd.h
@@ -0,0 +1,7 @@
+#ifndef _PC_KBD_H
+#define _PC_KBD_H
+
+int kbd_ischar(void);
+
+int kbd_getc(void);
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/pcmcia-opts.h b/src/VBox/Devices/PC/ipxe/src/include/pcmcia-opts.h
new file mode 100644
index 00000000..70dc0921
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/pcmcia-opts.h
@@ -0,0 +1,23 @@
+// pcmcia-opts.h
+// special options file for development time. Later this could end in Config(?)
+#ifndef __pcmciaopts
+#define __pcmciaopts
+
+ #define _yes_ 1
+ #define _no_ 0
+
+ #define SUPPORT_I82365 (_yes_)
+// #define SUPPORT_YENTA (_no_)
+// #define SUPPORT_SOME_DRIVER (_no_)
+
+ #define PCMCIA_SHUTDOWN (_yes_)
+ #define MAP_ATTRMEM_TO 0xd0000
+ #define MAP_ATTRMEM_LEN 0x02000
+
+ #define PDEBUG 3
+ // The higher the more output you get, 0..3
+ // Not fully implemented though, but for the future...
+
+ #undef _yes_
+ #undef _no_
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/include/pcmcia.h b/src/VBox/Devices/PC/ipxe/src/include/pcmcia.h
new file mode 100644
index 00000000..d528bea5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/pcmcia.h
@@ -0,0 +1,156 @@
+// pcmcia.h - Header file for PCMCIA support
+
+#ifndef PCMCIA_H
+#define PCMCIA_H
+
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+
+typedef u_short ioaddr_t;
+extern int sockets;
+
+#define MAXPCCSOCKS 8
+#define MAXPCCCONFIGS 8
+
+typedef enum ebpdriver_t { I82365, SOMEDRIVER } ebpdriver_t;
+typedef enum interface_func_t { INIT, SHUTDOWN, MAPATTRMEM, UNMAPATTRMEM, SELECTCONFIG } interface_func_t;
+typedef enum ebpstatus_t { EMPTY, HASCARD, INITIALIZED, SUSPENDED, OTHERDEVICE, UNKNOWN } ebpstatus_t;
+
+struct driver_interact_t {
+ ebpdriver_t id;
+ int (*f)(interface_func_t,int,int,int,int);
+ char *name;
+};
+struct pccsock_t {
+ ebpdriver_t device;
+ int drivernum;
+ ebpstatus_t status;
+ // Internal usage of the drivers:
+ int internalid;
+ int flags;
+ int ioaddr;
+ int type;
+ int configoffset;
+ int possibleconfignum;
+ int stringoffset;
+ u_int stringlength;
+ int rmask0;
+};
+
+extern struct pccsock_t pccsock[MAXPCCSOCKS];
+extern u_int pccsocks;
+
+struct pcc_config_t {
+ u_char index;
+ u_char irq;
+ int iowin;
+ int iolen;
+};
+
+
+int i82365_interfacer(interface_func_t,int,int,int,void *);
+void sleepticks(int);
+
+#define EINVAL 22
+
+
+//*********************************************************** cc.h:
+/* Definitions for card status flags for GetStatus */
+#define SS_WRPROT 0x0001
+#define SS_CARDLOCK 0x0002
+#define SS_EJECTION 0x0004
+#define SS_INSERTION 0x0008
+#define SS_BATDEAD 0x0010
+#define SS_BATWARN 0x0020
+#define SS_READY 0x0040
+#define SS_DETECT 0x0080
+#define SS_POWERON 0x0100
+#define SS_GPI 0x0200
+#define SS_STSCHG 0x0400
+#define SS_CARDBUS 0x0800
+#define SS_3VCARD 0x1000
+#define SS_XVCARD 0x2000
+#define SS_PENDING 0x4000
+
+/* cc.h: for InquireSocket */
+typedef struct socket_cap_t {
+ u_int features;
+ u_int irq_mask;
+ u_int map_size;
+ ioaddr_t io_offset;
+ u_char pci_irq;
+ //struct pci_dev *cb_dev;
+ //struct bus_operations *bus;
+ void *cb_dev;
+ void *bus;
+} socket_cap_t;
+/* InquireSocket capabilities */
+#define SS_CAP_PAGE_REGS 0x0001
+#define SS_CAP_VIRTUAL_BUS 0x0002
+#define SS_CAP_MEM_ALIGN 0x0004
+#define SS_CAP_STATIC_MAP 0x0008
+#define SS_CAP_PCCARD 0x4000
+#define SS_CAP_CARDBUS 0x8000
+
+/* for GetSocket, SetSocket */
+typedef struct socket_state_t {
+ u_int flags;
+ u_int csc_mask;
+ u_char Vcc, Vpp;
+ u_char io_irq;
+} socket_state_t;
+
+extern socket_state_t dead_socket;
+
+/* Socket configuration flags */
+#define SS_PWR_AUTO 0x0010
+#define SS_IOCARD 0x0020
+#define SS_RESET 0x0040
+#define SS_DMA_MODE 0x0080
+#define SS_SPKR_ENA 0x0100
+#define SS_OUTPUT_ENA 0x0200
+#define SS_DEBOUNCED 0x0400 /* Tell driver that the debounce delay has ended */
+#define SS_ZVCARD 0x0800
+
+/* Flags for I/O port and memory windows */
+#define MAP_ACTIVE 0x01
+#define MAP_16BIT 0x02
+#define MAP_AUTOSZ 0x04
+#define MAP_0WS 0x08
+#define MAP_WRPROT 0x10
+#define MAP_ATTRIB 0x20
+#define MAP_USE_WAIT 0x40
+#define MAP_PREFETCH 0x80
+
+/* Use this just for bridge windows */
+#define MAP_IOSPACE 0x20
+
+typedef struct pccard_io_map {
+ u_char map;
+ u_char flags;
+ u_short speed;
+ ioaddr_t start, stop;
+} pccard_io_map;
+
+
+typedef struct pccard_mem_map {
+ u_char map;
+ u_char flags;
+ u_short speed;
+ u_long sys_start, sys_stop;
+ u_int card_start;
+} pccard_mem_map;
+
+typedef struct cb_bridge_map {
+ u_char map;
+ u_char flags;
+ u_int start, stop;
+} cb_bridge_map;
+// need the global function pointer struct? *TODO*
+//************************************* end cc.h
+
+
+
+#endif /* PCMCIA_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/readline/readline.h b/src/VBox/Devices/PC/ipxe/src/include/readline/readline.h
new file mode 100644
index 00000000..42dfd8c4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/readline/readline.h
@@ -0,0 +1,57 @@
+#ifndef _READLINE_H
+#define _READLINE_H
+
+/** @file
+ *
+ * Minmal readline
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** A readline history entry */
+struct readline_history_entry {
+ /** Persistent copy of string */
+ char *string;
+ /** Temporary copy of string
+ *
+ * The temporary copy exists only during the call to
+ * readline().
+ */
+ char *temp;
+};
+
+/** Maximum depth of a readline history buffer
+ *
+ * Must be one less than a power of two.
+ */
+#define READLINE_HISTORY_MAX_DEPTH ( ( 1 << 3 ) - 1 )
+
+/** A readline history buffer */
+struct readline_history {
+ /** History entries
+ *
+ * This is a circular buffer, with entries in chronological
+ * order. The "next" entry is always empty except during a
+ * call to readline().
+ */
+ struct readline_history_entry entries[READLINE_HISTORY_MAX_DEPTH + 1];
+ /** Position of next entry within buffer
+ *
+ * This is incremented monotonically each time an entry is
+ * added to the buffer.
+ */
+ unsigned int next;
+ /** Current depth within history buffer
+ *
+ * This is valid only during the call to readline()
+ */
+ unsigned int depth;
+};
+
+extern void history_free ( struct readline_history *history );
+extern char * __malloc readline_history ( const char *prompt,
+ struct readline_history *history );
+extern char * __malloc readline ( const char *prompt );
+
+#endif /* _READLINE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/stdarg.h b/src/VBox/Devices/PC/ipxe/src/include/stdarg.h
new file mode 100644
index 00000000..f317238a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/stdarg.h
@@ -0,0 +1,38 @@
+#ifndef _STDARG_H
+#define _STDARG_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+typedef __builtin_va_list va_list;
+#define va_start( ap, last ) __builtin_va_start ( ap, last )
+#define va_arg( ap, type ) __builtin_va_arg ( ap, type )
+#define va_end( ap ) __builtin_va_end ( ap )
+#define va_copy( dest, src ) __builtin_va_copy ( dest, src )
+
+/**
+ * Count number of arguments to a variadic macro
+ *
+ * This rather neat, non-iterative solution is courtesy of Laurent
+ * Deniau.
+ *
+ */
+#define _VA_ARG_COUNT( _1, _2, _3, _4, _5, _6, _7, _8, \
+ _9, _10, _11, _12, _13, _14, _15, _16, \
+ _17, _18, _19, _20, _21, _22, _23, _24, \
+ _25, _26, _27, _28, _29, _30, _31, _32, \
+ _33, _34, _35, _36, _37, _38, _39, _40, \
+ _41, _42, _43, _44, _45, _46, _47, _48, \
+ _49, _50, _51, _52, _53, _54, _55, _56, \
+ _57, _58, _59, _60, _61, _62, _63, N, ... ) N
+#define VA_ARG_COUNT( ... ) \
+ _VA_ARG_COUNT ( __VA_ARGS__, \
+ 63, 62, 61, 60, 59, 58, 57, 56, \
+ 55, 54, 53, 52, 51, 50, 49, 48, \
+ 47, 46, 45, 44, 43, 42, 41, 40, \
+ 39, 38, 37, 36, 35, 34, 33, 32, \
+ 31, 30, 29, 28, 27, 26, 25, 24, \
+ 23, 22, 21, 20, 19, 18, 17, 16, \
+ 15, 14, 13, 12, 11, 10, 9, 8, \
+ 7, 6, 5, 4, 3, 2, 1, 0 )
+
+#endif /* _STDARG_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/stddef.h b/src/VBox/Devices/PC/ipxe/src/include/stddef.h
new file mode 100644
index 00000000..c91a103f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/stddef.h
@@ -0,0 +1,30 @@
+#ifndef STDDEF_H
+#define STDDEF_H
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/* for size_t */
+#include <stdint.h>
+
+#undef NULL
+#define NULL ((void *)0)
+
+#undef offsetof
+#if ( defined ( __GNUC__ ) && ( __GNUC__ > 3 ) )
+#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
+#else
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#undef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+/* __WCHAR_TYPE__ is defined by gcc and will change if -fshort-wchar is used */
+#ifndef __WCHAR_TYPE__
+#define __WCHAR_TYPE__ long int
+#endif
+typedef __WCHAR_TYPE__ wchar_t;
+
+#endif /* STDDEF_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/stdint.h b/src/VBox/Devices/PC/ipxe/src/include/stdint.h
new file mode 100644
index 00000000..8cc9b84a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/stdint.h
@@ -0,0 +1,36 @@
+#ifndef _STDINT_H
+#define _STDINT_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * This is a standard predefined macro on all gcc's I've seen. It's
+ * important that we define size_t in the same way as the compiler,
+ * because that's what it's expecting when it checks %zd/%zx printf
+ * format specifiers.
+ */
+#ifndef __SIZE_TYPE__
+#define __SIZE_TYPE__ unsigned long /* safe choice on most systems */
+#endif
+
+#include <bits/stdint.h>
+
+typedef int8_t s8;
+typedef uint8_t u8;
+typedef int16_t s16;
+typedef uint16_t u16;
+typedef int32_t s32;
+typedef uint32_t u32;
+typedef int64_t s64;
+typedef uint64_t u64;
+
+typedef int8_t int8;
+typedef uint8_t uint8;
+typedef int16_t int16;
+typedef uint16_t uint16;
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int64_t int64;
+typedef uint64_t uint64;
+
+#endif /* _STDINT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/stdio.h b/src/VBox/Devices/PC/ipxe/src/include/stdio.h
new file mode 100644
index 00000000..91840af5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/stdio.h
@@ -0,0 +1,51 @@
+#ifndef _STDIO_H
+#define _STDIO_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdarg.h>
+
+extern void putchar ( int character );
+
+extern int getchar ( void );
+
+extern int __attribute__ (( format ( printf, 1, 2 ) ))
+printf ( const char *fmt, ... );
+
+extern int __attribute__ (( format ( printf, 3, 4 ) ))
+snprintf ( char *buf, size_t size, const char *fmt, ... );
+
+extern int __attribute__ (( format ( printf, 2, 3 ) ))
+asprintf ( char **strp, const char *fmt, ... );
+
+extern int vprintf ( const char *fmt, va_list args );
+
+extern int vsnprintf ( char *buf, size_t size, const char *fmt, va_list args );
+
+extern int vasprintf ( char **strp, const char *fmt, va_list args );
+
+/**
+ * Write a formatted string to a buffer
+ *
+ * @v buf Buffer into which to write the string
+ * @v fmt Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+#define sprintf( buf, fmt, ... ) \
+ snprintf ( (buf), ~( ( size_t ) 0 ), (fmt), ## __VA_ARGS__ )
+
+/**
+ * Write a formatted string to a buffer
+ *
+ * @v buf Buffer into which to write the string
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+static inline int vsprintf ( char *buf, const char *fmt, va_list args ) {
+ return vsnprintf ( buf, ~( ( size_t ) 0 ), fmt, args );
+}
+
+#endif /* _STDIO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/stdlib.h b/src/VBox/Devices/PC/ipxe/src/include/stdlib.h
new file mode 100644
index 00000000..3d30858f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/stdlib.h
@@ -0,0 +1,111 @@
+#ifndef STDLIB_H
+#define STDLIB_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <assert.h>
+
+/*****************************************************************************
+ *
+ * Numeric parsing
+ *
+ ****************************************************************************
+ */
+
+static inline int strtoul_base ( const char **pp, int base )
+{
+ const char *p = *pp;
+
+ if ( base == 0 ) {
+ base = 10;
+ if ( *p == '0' ) {
+ p++;
+ base = 8;
+ if ( ( *p | 0x20 ) == 'x' ) {
+ p++;
+ base = 16;
+ }
+ }
+ }
+
+ *pp = p;
+
+ return base;
+}
+
+static inline unsigned int strtoul_charval ( unsigned int charval )
+{
+ if ( charval >= 'a' ) {
+ charval = ( charval - 'a' + 10 );
+ } else if ( charval >= 'A' ) {
+ charval = ( charval - 'A' + 10 );
+ } else if ( charval <= '9' ) {
+ charval = ( charval - '0' );
+ }
+
+ return charval;
+}
+
+extern unsigned long strtoul ( const char *p, char **endp, int base );
+extern unsigned long long strtoull ( const char *p, char **endp, int base );
+
+
+/*****************************************************************************
+ *
+ * Memory allocation
+ *
+ ****************************************************************************
+ */
+
+extern void * __malloc malloc ( size_t size );
+extern void * realloc ( void *old_ptr, size_t new_size );
+extern void free ( void *ptr );
+extern void * __malloc zalloc ( size_t len );
+
+/**
+ * Allocate cleared memory
+ *
+ * @v nmemb Number of members
+ * @v size Size of each member
+ * @ret ptr Allocated memory
+ *
+ * Allocate memory as per malloc(), and zero it.
+ *
+ * This is implemented as a static inline, with the body of the
+ * function in zalloc(), since in most cases @c nmemb will be 1 and
+ * doing the multiply is just wasteful.
+ */
+static inline void * __malloc calloc ( size_t nmemb, size_t size ) {
+ return zalloc ( nmemb * size );
+}
+
+/*****************************************************************************
+ *
+ * Random number generation
+ *
+ ****************************************************************************
+ */
+
+extern long int random ( void );
+extern void srandom ( unsigned int seed );
+
+static inline int rand ( void ) {
+ return random();
+}
+
+static inline void srand ( unsigned int seed ) {
+ srandom ( seed );
+}
+
+/*****************************************************************************
+ *
+ * Miscellaneous
+ *
+ ****************************************************************************
+ */
+
+extern int system ( const char *command );
+extern __asmcall int main ( void );
+
+#endif /* STDLIB_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/string.h b/src/VBox/Devices/PC/ipxe/src/include/string.h
new file mode 100644
index 00000000..2fd6acf1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/string.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * string handling functions
+ * based on linux/include/linux/ctype.h
+ * and linux/include/linux/string.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#ifndef ETHERBOOT_STRING_H
+#define ETHERBOOT_STRING_H
+
+#include <stddef.h>
+#include <bits/string.h>
+
+int __pure strnicmp(const char *s1, const char *s2, size_t len) __nonnull;
+char * strcpy(char * dest,const char *src) __nonnull;
+char * strncpy(char * dest,const char *src,size_t count) __nonnull;
+char * strcat(char * dest, const char * src) __nonnull;
+char * strncat(char *dest, const char *src, size_t count) __nonnull;
+int __pure strcmp(const char * cs,const char * ct) __nonnull;
+int __pure strncmp(const char * cs,const char * ct,
+ size_t count) __nonnull;
+char * __pure strchr(const char * s, int c) __nonnull;
+char * __pure strrchr(const char * s, int c) __nonnull;
+size_t __pure strlen(const char * s) __nonnull;
+size_t __pure strnlen(const char * s, size_t count) __nonnull;
+size_t __pure strspn(const char *s, const char *accept) __nonnull;
+size_t __pure strcspn(const char *s, const char *reject) __nonnull;
+char * __pure strpbrk(const char * cs,const char * ct) __nonnull;
+char * strtok(char * s,const char * ct) __nonnull;
+char * strsep(char **s, const char *ct) __nonnull;
+void * memset(void * s,int c,size_t count) __nonnull;
+void * memmove(void * dest,const void *src,size_t count) __nonnull;
+int __pure memcmp(const void * cs,const void * ct,
+ size_t count) __nonnull;
+void * __pure memscan(const void * addr, int c, size_t size) __nonnull;
+char * __pure strstr(const char * s1,const char * s2) __nonnull;
+void * __pure memchr(const void *s, int c, size_t n) __nonnull;
+char * __malloc strdup(const char *s) __nonnull;
+char * __malloc strndup(const char *s, size_t n) __nonnull;
+
+extern const char * __pure strerror ( int errno );
+
+#endif /* ETHERBOOT_STRING */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/strings.h b/src/VBox/Devices/PC/ipxe/src/include/strings.h
new file mode 100644
index 00000000..c7063d68
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/strings.h
@@ -0,0 +1,65 @@
+#ifndef _STRINGS_H
+#define _STRINGS_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <limits.h>
+#include <string.h>
+
+static inline __attribute__ (( always_inline )) int
+__constant_flsl ( unsigned long x ) {
+ int r = 0;
+
+#if ULONG_MAX > 0xffffffff
+ if ( x & 0xffffffff00000000UL ) {
+ x >>= 32;
+ r += 32;
+ }
+#endif
+ if ( x & 0xffff0000UL ) {
+ x >>= 16;
+ r += 16;
+ }
+ if ( x & 0xff00 ) {
+ x >>= 8;
+ r += 8;
+ }
+ if ( x & 0xf0 ) {
+ x >>= 4;
+ r += 4;
+ }
+ if ( x & 0xc ) {
+ x >>= 2;
+ r += 2;
+ }
+ if ( x & 0x2 ) {
+ x >>= 1;
+ r += 1;
+ }
+ if ( x & 0x1 ) {
+ r += 1;
+ }
+ return r;
+}
+
+/* We don't actually have these functions yet */
+extern int __flsl ( long x );
+
+#define flsl( x ) \
+ ( __builtin_constant_p ( x ) ? __constant_flsl ( x ) : __flsl ( x ) )
+
+#define fls( x ) flsl ( x )
+
+extern int strcasecmp ( const char *s1, const char *s2 );
+
+static inline __attribute__ (( always_inline )) void
+bcopy ( const void *src, void *dest, size_t n ) {
+ memmove ( dest, src, n );
+}
+
+static inline __attribute__ (( always_inline )) void
+bzero ( void *s, size_t n ) {
+ memset ( s, 0, n );
+}
+
+#endif /* _STRINGS_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/sys/time.h b/src/VBox/Devices/PC/ipxe/src/include/sys/time.h
new file mode 100644
index 00000000..6c9b7421
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/sys/time.h
@@ -0,0 +1,18 @@
+#ifndef _SYS_TIME_H
+#define _SYS_TIME_H
+
+/** @file
+ *
+ * Date and time
+ */
+
+#include <stdint.h>
+
+/** Seconds since the Epoch
+ *
+ * We use a 64-bit type to avoid Y2K38 issues, since we may have to
+ * handle distant future dates (e.g. X.509 certificate expiry dates).
+ */
+typedef int64_t time_t;
+
+#endif /* _SYS_TIME_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/sys_info.h b/src/VBox/Devices/PC/ipxe/src/include/sys_info.h
new file mode 100644
index 00000000..7127c643
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/sys_info.h
@@ -0,0 +1,33 @@
+#ifndef SYS_INFO_H
+#define SYS_INFO_H
+
+/* Information collected from firmware/bootloader */
+
+struct sys_info {
+ /* Values passed by bootloader */
+ unsigned long boot_type;
+ unsigned long boot_data;
+ unsigned long boot_arg;
+
+ char *firmware; /* "PCBIOS", "LinuxBIOS", etc. */
+ char *command_line; /* command line given to us */
+#if 0
+//By LYH
+//Will use meminfo in Etherboot
+ /* memory map */
+ int n_memranges;
+ struct memrange {
+ unsigned long long base;
+ unsigned long long size;
+ } *memrange;
+#endif
+};
+
+void collect_sys_info(struct sys_info *info);
+void collect_elfboot_info(struct sys_info *info);
+void collect_linuxbios_info(struct sys_info *info);
+
+/* Our name and version. I want to see single instance of these in the image */
+extern const char *program_name, *program_version;
+
+#endif /* SYS_INFO_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/syslog.h b/src/VBox/Devices/PC/ipxe/src/include/syslog.h
new file mode 100644
index 00000000..93f32f86
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/syslog.h
@@ -0,0 +1,100 @@
+#ifndef _SYSLOG_H
+#define _SYSLOG_H
+
+/** @file
+ *
+ * System logger
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdarg.h>
+#include <ipxe/ansiesc.h>
+#include <config/console.h>
+
+/**
+ * @defgroup syslogpri Syslog priorities
+ *
+ * These values are chosen to match those used in the syslog network
+ * protocol (RFC 5424).
+ *
+ * @{
+ */
+
+/** Emergency: system is unusable */
+#define LOG_EMERG 0
+
+/** Alert: action must be taken immediately */
+#define LOG_ALERT 1
+
+/** Critical: critical conditions */
+#define LOG_CRIT 2
+
+/** Error: error conditions */
+#define LOG_ERR 3
+
+/** Warning: warning conditions */
+#define LOG_WARNING 4
+
+/** Notice: normal but significant conditions */
+#define LOG_NOTICE 5
+
+/** Informational: informational messages */
+#define LOG_INFO 6
+
+/** Debug: debug-level messages */
+#define LOG_DEBUG 7
+
+/** @} */
+
+/** Do not log any messages */
+#define LOG_NONE -1
+
+/** Log all messages */
+#define LOG_ALL LOG_DEBUG
+
+extern void log_vprintf ( const char *fmt, va_list args );
+
+extern void __attribute__ (( format ( printf, 1, 2 ) ))
+log_printf ( const char *fmt, ... );
+
+/** ANSI private escape sequence to set syslog priority
+ *
+ * @v priority Priority
+ */
+#define SYSLOG_SET_PRIORITY( priority ) \
+ "\033[" #priority "p"
+
+/** ANSI private escape sequence to clear syslog priority */
+#define SYSLOG_CLEAR_PRIORITY "\033[p"
+
+/**
+ * Write message to system log
+ *
+ * @v priority Message priority
+ * @v fmt Format string
+ * @v ... Arguments
+ */
+#define vsyslog( priority, fmt, args ) do { \
+ if ( (priority) <= LOG_LEVEL ) { \
+ log_vprintf ( SYSLOG_SET_PRIORITY ( priority ) fmt \
+ SYSLOG_CLEAR_PRIORITY, (args) ); \
+ } \
+ } while ( 0 )
+
+/**
+ * Write message to system log
+ *
+ * @v priority Message priority
+ * @v fmt Format string
+ * @v ... Arguments
+ */
+#define syslog( priority, fmt, ... ) do { \
+ if ( (priority) <= LOG_LEVEL ) { \
+ log_printf ( SYSLOG_SET_PRIORITY ( priority ) fmt \
+ SYSLOG_CLEAR_PRIORITY, ##__VA_ARGS__ ); \
+ } \
+ } while ( 0 )
+
+#endif /* _SYSLOG_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/time.h b/src/VBox/Devices/PC/ipxe/src/include/time.h
new file mode 100644
index 00000000..bc73af4c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/time.h
@@ -0,0 +1,51 @@
+#ifndef _TIME_H
+#define _TIME_H
+
+/** @file
+ *
+ * Date and time
+ */
+
+#include <sys/time.h>
+#include <ipxe/time.h>
+
+/** Broken-down time */
+struct tm {
+ /** Seconds [0,60] */
+ int tm_sec;
+ /** Minutes [0,59] */
+ int tm_min;
+ /** Hour [0,23] */
+ int tm_hour;
+ /** Day of month [1,31] */
+ int tm_mday;
+ /** Month of year [0,11] */
+ int tm_mon;
+ /** Years since 1900 */
+ int tm_year;
+ /** Day of week [0,6] (Sunday=0) */
+ int tm_wday;
+ /** Day of year [0,365] */
+ int tm_yday;
+ /** Daylight savings flag */
+ int tm_isdst;
+};
+
+/**
+ * Get current time in seconds since the Epoch
+ *
+ * @v t Time to fill in, or NULL
+ * @ret time Current time
+ */
+static inline time_t time ( time_t *t ) {
+ time_t now;
+
+ now = time_now();
+ if ( t )
+ *t = now;
+ return now;
+}
+
+extern time_t mktime ( struct tm *tm );
+
+#endif /* _TIME_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/unistd.h b/src/VBox/Devices/PC/ipxe/src/include/unistd.h
new file mode 100644
index 00000000..3a50a252
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/unistd.h
@@ -0,0 +1,43 @@
+#ifndef _UNISTD_H
+#define _UNISTD_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdarg.h>
+
+extern int execv ( const char *command, char * const argv[] );
+
+/**
+ * Execute command
+ *
+ * @v command Command name
+ * @v arg ... Argument list (starting with argv[0])
+ * @ret rc Command exit status
+ *
+ * This is a front end to execv().
+ */
+#define execl( command, arg, ... ) ( { \
+ char * const argv[] = { (arg), ## __VA_ARGS__ }; \
+ int rc = execv ( (command), argv ); \
+ rc; \
+ } )
+
+/* Pick up udelay() */
+#include <ipxe/timer.h>
+
+/*
+ * sleep() prototype is defined by POSIX.1. usleep() prototype is
+ * defined by 4.3BSD. udelay() and mdelay() prototypes are chosen to
+ * be reasonably sensible.
+ *
+ */
+
+extern unsigned int sleep ( unsigned int seconds );
+extern void mdelay ( unsigned long msecs );
+
+static inline __always_inline void usleep ( unsigned long usecs ) {
+ udelay ( usecs );
+}
+
+#endif /* _UNISTD_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/usr/autoboot.h b/src/VBox/Devices/PC/ipxe/src/include/usr/autoboot.h
new file mode 100644
index 00000000..25b9f073
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/usr/autoboot.h
@@ -0,0 +1,37 @@
+#ifndef _USR_AUTOBOOT_H
+#define _USR_AUTOBOOT_H
+
+/** @file
+ *
+ * Automatic booting
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/in.h>
+struct net_device;
+struct uri;
+struct settings;
+
+/** uriboot() flags */
+enum uriboot_flags {
+ URIBOOT_NO_SAN_DESCRIBE = 0x0001,
+ URIBOOT_NO_SAN_BOOT = 0x0002,
+ URIBOOT_NO_SAN_UNHOOK = 0x0004,
+};
+
+#define URIBOOT_NO_SAN ( URIBOOT_NO_SAN_DESCRIBE | \
+ URIBOOT_NO_SAN_BOOT | \
+ URIBOOT_NO_SAN_UNHOOK )
+
+extern int uriboot ( struct uri *filename, struct uri *root_path, int drive,
+ unsigned int flags );
+extern struct uri *
+fetch_next_server_and_filename ( struct settings *settings );
+extern int netboot ( struct net_device *netdev );
+extern int autoboot ( void );
+
+extern int pxe_menu_boot ( struct net_device *netdev );
+
+#endif /* _USR_AUTOBOOT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/usr/dhcpmgmt.h b/src/VBox/Devices/PC/ipxe/src/include/usr/dhcpmgmt.h
new file mode 100644
index 00000000..2394dac4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/usr/dhcpmgmt.h
@@ -0,0 +1,17 @@
+#ifndef _USR_DHCPMGMT_H
+#define _USR_DHCPMGMT_H
+
+/** @file
+ *
+ * DHCP management
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct net_device;
+
+extern int dhcp ( struct net_device *netdev );
+extern int pxebs ( struct net_device *netdev, unsigned int pxe_type );
+
+#endif /* _USR_DHCPMGMT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/usr/fcmgmt.h b/src/VBox/Devices/PC/ipxe/src/include/usr/fcmgmt.h
new file mode 100644
index 00000000..9441cefb
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/usr/fcmgmt.h
@@ -0,0 +1,21 @@
+#ifndef _USR_FCMGMT_H
+#define _USR_FCMGMT_H
+
+/** @file
+ *
+ * Fibre Channel management
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct fc_port;
+struct fc_peer;
+struct fc_els_handler;
+
+extern void fcportstat ( struct fc_port *port );
+extern void fcpeerstat ( struct fc_peer *peer );
+extern int fcels ( struct fc_port *port, struct fc_port_id *peer_port_id,
+ struct fc_els_handler *handler );
+
+#endif /* _USR_FCMGMT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/usr/ifmgmt.h b/src/VBox/Devices/PC/ipxe/src/include/usr/ifmgmt.h
new file mode 100644
index 00000000..f762c7ba
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/usr/ifmgmt.h
@@ -0,0 +1,19 @@
+#ifndef _USR_IFMGMT_H
+#define _USR_IFMGMT_H
+
+/** @file
+ *
+ * Network interface management
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct net_device;
+
+extern int ifopen ( struct net_device *netdev );
+extern void ifclose ( struct net_device *netdev );
+extern void ifstat ( struct net_device *netdev );
+extern int iflinkwait ( struct net_device *netdev, unsigned int max_wait_ms );
+
+#endif /* _USR_IFMGMT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/usr/imgmgmt.h b/src/VBox/Devices/PC/ipxe/src/include/usr/imgmgmt.h
new file mode 100644
index 00000000..8db5c978
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/usr/imgmgmt.h
@@ -0,0 +1,19 @@
+#ifndef _USR_IMGMGMT_H
+#define _USR_IMGMGMT_H
+
+/** @file
+ *
+ * Image management
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/image.h>
+
+extern int imgdownload ( struct uri *uri, struct image **image );
+extern int imgdownload_string ( const char *uri_string, struct image **image );
+extern int imgacquire ( const char *name, struct image **image );
+extern void imgstat ( struct image *image );
+
+#endif /* _USR_IMGMGMT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/usr/imgtrust.h b/src/VBox/Devices/PC/ipxe/src/include/usr/imgtrust.h
new file mode 100644
index 00000000..f47105af
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/usr/imgtrust.h
@@ -0,0 +1,17 @@
+#ifndef _USR_IMGTRUST_H
+#define _USR_IMGTRUST_H
+
+/** @file
+ *
+ * Image trust management
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/image.h>
+
+extern int imgverify ( struct image *image, struct image *signature,
+ const char *name );
+
+#endif /* _USR_IMGTRUST_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/usr/iwmgmt.h b/src/VBox/Devices/PC/ipxe/src/include/usr/iwmgmt.h
new file mode 100644
index 00000000..c1bdc37a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/usr/iwmgmt.h
@@ -0,0 +1,17 @@
+#ifndef _USR_IWMGMT_H
+#define _USR_IWMGMT_H
+
+/** @file
+ *
+ * Wireless network interface management
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct net80211_device;
+
+extern void iwstat ( struct net80211_device *dev );
+extern int iwlist ( struct net80211_device *dev );
+
+#endif /* _USR_IWMGMT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/usr/lotest.h b/src/VBox/Devices/PC/ipxe/src/include/usr/lotest.h
new file mode 100644
index 00000000..aa4bbac4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/usr/lotest.h
@@ -0,0 +1,15 @@
+#ifndef _USR_LOTEST_H
+#define _USR_LOTEST_H
+
+/** @file
+ *
+ * Loopback testing
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern int loopback_test ( struct net_device *sender,
+ struct net_device *receiver, size_t mtu );
+
+#endif /* _USR_LOTEST_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/usr/prompt.h b/src/VBox/Devices/PC/ipxe/src/include/usr/prompt.h
new file mode 100644
index 00000000..fc1946c7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/usr/prompt.h
@@ -0,0 +1,14 @@
+#ifndef _USR_PROMPT_H
+#define _USR_PROMPT_H
+
+/** @file
+ *
+ * Prompt for keypress
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern int prompt ( const char *text, unsigned int wait_ms, int key );
+
+#endif /* _USR_PROMPT_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/include/usr/route.h b/src/VBox/Devices/PC/ipxe/src/include/usr/route.h
new file mode 100644
index 00000000..855fa7ba
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/include/usr/route.h
@@ -0,0 +1,14 @@
+#ifndef _USR_ROUTE_H
+#define _USR_ROUTE_H
+
+/** @file
+ *
+ * Routing table management
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern void route ( void );
+
+#endif /* _USR_ROUTE_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/bofm/bofm.c b/src/VBox/Devices/PC/ipxe/src/interface/bofm/bofm.c
new file mode 100644
index 00000000..63b25a55
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/bofm/bofm.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/list.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/bofm.h>
+
+/** @file
+ *
+ * IBM BladeCenter Open Fabric Manager (BOFM)
+ *
+ */
+
+/** List of BOFM devices */
+static LIST_HEAD ( bofmdevs );
+
+/**
+ * Register BOFM device
+ *
+ * @v bofm BOFM device
+ * @ret rc Return status code
+ */
+int bofm_register ( struct bofm_device *bofm ) {
+
+ list_add ( &bofm->list, &bofmdevs );
+ DBG ( "BOFM: " PCI_FMT " registered using driver \"%s\"\n",
+ PCI_ARGS ( bofm->pci ), bofm->pci->id->name );
+ return 0;
+}
+
+/**
+ * Unregister BOFM device
+ *
+ * @v bofm BOFM device
+ */
+void bofm_unregister ( struct bofm_device *bofm ) {
+
+ list_del ( &bofm->list );
+ DBG ( "BOFM: " PCI_FMT " unregistered\n", PCI_ARGS ( bofm->pci ) );
+}
+
+/**
+ * Find BOFM device matching PCI bus:dev.fn address
+ *
+ * @v busdevfn PCI bus:dev.fn address
+ * @ret bofm BOFM device, or NULL
+ */
+static struct bofm_device * bofm_find_busdevfn ( unsigned int busdevfn ) {
+ struct bofm_device *bofm;
+
+ list_for_each_entry ( bofm, &bofmdevs, list ) {
+ if ( bofm->pci->busdevfn == busdevfn )
+ return bofm;
+ }
+ return NULL;
+}
+
+/**
+ * Find BOFM driver for PCI device
+ *
+ * @v pci PCI device
+ * @ret rc Return status code
+ */
+int bofm_find_driver ( struct pci_device *pci ) {
+ struct pci_driver *driver;
+ struct pci_device_id *id;
+ unsigned int i;
+
+ for_each_table_entry ( driver, BOFM_DRIVERS ) {
+ for ( i = 0 ; i < driver->id_count ; i++ ) {
+ id = &driver->ids[i];
+ if ( ( id->vendor == pci->vendor ) &&
+ ( id->device == pci->device ) ) {
+ pci_set_driver ( pci, driver, id );
+ return 0;
+ }
+ }
+ }
+ return -ENOENT;
+}
+
+/**
+ * Probe PCI device for BOFM driver
+ *
+ * @v pci PCI device
+ * @ret rc Return status code
+ */
+static int bofm_probe ( struct pci_device *pci ) {
+ int rc;
+
+ /* Probe device */
+ if ( ( rc = pci_probe ( pci ) ) != 0 ) {
+ DBG ( "BOFM: " PCI_FMT " could not load driver: %s\n",
+ PCI_ARGS ( pci ), strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void bofm_remove ( struct pci_device *pci ) {
+
+ /* Note that the IBM BIOS may re-read the expansion ROM after
+ * the BOFM initialisation call. The BOFM driver must ensure
+ * that the card is left in a state in which expansion ROM
+ * reads will succeed. (For example, if a card contains an
+ * embedded CPU that may issue reads to the same underlying
+ * flash device, and these reads are not locked against reads
+ * via the expansion ROM BAR, then the CPU must be stopped.)
+ *
+ * If this is not done, then occasional corrupted reads from
+ * the expansion ROM will be seen, and the BIOS may complain
+ * about a ROM checksum error.
+ */
+ pci_remove ( pci );
+ DBG ( "BOFM: " PCI_FMT " removed\n", PCI_ARGS ( pci ) );
+}
+
+/**
+ * Locate BOFM table section
+ *
+ * @v bofmtab BOFM table
+ * @v len Length of BOFM table
+ * @v magic Section magic
+ * @v bofmsec BOFM section header to fill in
+ * @ret offset Offset to section, or 0 if not found
+ */
+static size_t bofm_locate_section ( userptr_t bofmtab, size_t len,
+ uint32_t magic,
+ struct bofm_section_header *bofmsec ) {
+ size_t offset = sizeof ( struct bofm_global_header );
+
+ while ( offset < len ) {
+ copy_from_user ( bofmsec, bofmtab, offset,
+ sizeof ( *bofmsec ) );
+ if ( bofmsec->magic == magic )
+ return offset;
+ if ( bofmsec->magic == BOFM_DONE_MAGIC )
+ break;
+ offset += ( sizeof ( *bofmsec ) + bofmsec->length );
+ }
+ return 0;
+}
+
+/**
+ * Process BOFM Ethernet parameter entry
+ *
+ * @v bofm BOFM device
+ * @v en EN parameter entry
+ * @ret rc Return status code
+ */
+static int bofm_en ( struct bofm_device *bofm, struct bofm_en *en ) {
+ uint8_t mac[6];
+ int rc;
+
+ /* Retrieve current MAC address */
+ if ( ( rc = bofm->op->harvest ( bofm, en->mport, mac ) ) != 0 ) {
+ DBG ( "BOFM: " PCI_FMT " mport %d could not harvest: %s\n",
+ PCI_ARGS ( bofm->pci ), en->mport, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Harvest MAC address if necessary */
+ if ( en->options & BOFM_EN_RQ_HVST_MASK ) {
+ DBG ( "BOFM: " PCI_FMT " mport %d harvested MAC %s\n",
+ PCI_ARGS ( bofm->pci ), en->mport, eth_ntoa ( mac ) );
+ memcpy ( en->mac_a, mac, sizeof ( en->mac_a ) );
+ en->options |= ( BOFM_EN_EN_A | BOFM_EN_HVST );
+ }
+
+ /* Mark as changed if necessary */
+ if ( ( en->options & BOFM_EN_EN_A ) &&
+ ( memcmp ( en->mac_a, mac, sizeof ( en->mac_a ) ) != 0 ) ) {
+ DBG ( "BOFM: " PCI_FMT " mport %d MAC %s",
+ PCI_ARGS ( bofm->pci ), en->mport, eth_ntoa ( mac ) );
+ DBG ( " changed to %s\n", eth_ntoa ( en->mac_a ) );
+ en->options |= BOFM_EN_CHG_CHANGED;
+ }
+
+ /* Apply MAC address if necessary */
+ if ( ( en->options & BOFM_EN_EN_A ) &&
+ ( en->options & BOFM_EN_USAGE_ENTRY ) &&
+ ( ! ( en->options & BOFM_EN_USAGE_HARVEST ) ) ) {
+ DBG ( "BOFM: " PCI_FMT " mport %d applied MAC %s\n",
+ PCI_ARGS ( bofm->pci ), en->mport,
+ eth_ntoa ( en->mac_a ) );
+ memcpy ( mac, en->mac_a, sizeof ( mac ) );
+ }
+
+ /* Store MAC address */
+ if ( ( rc = bofm->op->update ( bofm, en->mport, mac ) ) != 0 ) {
+ DBG ( "BOFM: " PCI_FMT " mport %d could not update: %s\n",
+ PCI_ARGS ( bofm->pci ), en->mport, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Process BOFM table
+ *
+ * @v bofmtab BOFM table
+ * @v pci PCI device
+ * @ret bofmrc BOFM return status
+ */
+int bofm ( userptr_t bofmtab, struct pci_device *pci ) {
+ struct bofm_global_header bofmhdr;
+ struct bofm_section_header bofmsec;
+ struct bofm_en en;
+ struct bofm_device *bofm;
+ size_t en_region_offset;
+ size_t en_offset;
+ int skip;
+ int rc;
+ int bofmrc;
+
+ /* Read BOFM structure */
+ copy_from_user ( &bofmhdr, bofmtab, 0, sizeof ( bofmhdr ) );
+ if ( bofmhdr.magic != BOFM_IOAA_MAGIC ) {
+ DBG ( "BOFM: invalid table signature " BOFM_MAGIC_FMT "\n",
+ BOFM_MAGIC_ARGS ( bofmhdr.magic ) );
+ bofmrc = BOFM_ERR_INVALID_ACTION;
+ goto err_bad_signature;
+ }
+ DBG ( "BOFM: " BOFM_MAGIC_FMT " (profile \"%s\")\n",
+ BOFM_MAGIC_ARGS ( bofmhdr.action ), bofmhdr.profile );
+
+ /* Determine whether or not we should skip normal POST
+ * initialisation.
+ */
+ switch ( bofmhdr.action ) {
+ case BOFM_ACTION_UPDT:
+ case BOFM_ACTION_DFLT:
+ case BOFM_ACTION_HVST:
+ skip = BOFM_SKIP_INIT;
+ break;
+ case BOFM_ACTION_PARM:
+ case BOFM_ACTION_NONE:
+ skip = 0;
+ break;
+ default:
+ DBG ( "BOFM: invalid action " BOFM_MAGIC_FMT "\n",
+ BOFM_MAGIC_ARGS ( bofmhdr.action ) );
+ bofmrc = BOFM_ERR_INVALID_ACTION;
+ goto err_bad_action;
+ }
+
+ /* Find BOFM driver */
+ if ( ( rc = bofm_find_driver ( pci ) ) != 0 ) {
+ DBG ( "BOFM: " PCI_FMT " has no driver\n", PCI_ARGS ( pci ) );
+ bofmrc = BOFM_ERR_DEVICE_ERROR;
+ goto err_find_driver;
+ }
+
+ /* Probe driver for PCI device */
+ if ( ( rc = bofm_probe ( pci ) ) != 0 ) {
+ bofmrc = BOFM_ERR_DEVICE_ERROR;
+ goto err_probe;
+ }
+
+ /* Locate EN section, if present */
+ en_region_offset = bofm_locate_section ( bofmtab, bofmhdr.length,
+ BOFM_EN_MAGIC, &bofmsec );
+ if ( ! en_region_offset ) {
+ DBG ( "BOFM: No EN section found\n" );
+ bofmrc = ( BOFM_SUCCESS | skip );
+ goto err_no_en_section;
+ }
+
+ /* Iterate through EN entries */
+ for ( en_offset = ( en_region_offset + sizeof ( bofmsec ) ) ;
+ en_offset < ( en_region_offset + sizeof ( bofmsec ) +
+ bofmsec.length ) ; en_offset += sizeof ( en ) ) {
+ copy_from_user ( &en, bofmtab, en_offset, sizeof ( en ) );
+ DBG2 ( "BOFM: EN entry found:\n" );
+ DBG2_HDA ( en_offset, &en, sizeof ( en ) );
+ if ( ( en.options & BOFM_EN_MAP_MASK ) != BOFM_EN_MAP_PFA ) {
+ DBG ( "BOFM: slot %d port %d has no PCI mapping\n",
+ en.slot, ( en.port + 1 ) );
+ continue;
+ }
+ DBG ( "BOFM: slot %d port %d%s is " PCI_FMT " mport %d\n",
+ en.slot, ( en.port + 1 ),
+ ( ( en.slot || en.port ) ? "" : "(?)" ),
+ PCI_BUS ( en.busdevfn ), PCI_SLOT ( en.busdevfn ),
+ PCI_FUNC ( en.busdevfn ), en.mport );
+ bofm = bofm_find_busdevfn ( en.busdevfn );
+ if ( ! bofm ) {
+ DBG ( "BOFM: " PCI_FMT " mport %d ignored\n",
+ PCI_BUS ( en.busdevfn ), PCI_SLOT ( en.busdevfn ),
+ PCI_FUNC ( en.busdevfn ), en.mport );
+ continue;
+ }
+ if ( ( rc = bofm_en ( bofm, &en ) ) == 0 ) {
+ en.options |= BOFM_EN_CSM_SUCCESS;
+ } else {
+ en.options |= BOFM_EN_CSM_FAILED;
+ }
+ DBG2 ( "BOFM: EN entry after processing:\n" );
+ DBG2_HDA ( en_offset, &en, sizeof ( en ) );
+ copy_to_user ( bofmtab, en_offset, &en, sizeof ( en ) );
+ }
+
+ bofmrc = ( BOFM_SUCCESS | skip );
+
+ err_no_en_section:
+ bofm_remove ( pci );
+ err_probe:
+ err_find_driver:
+ err_bad_action:
+ err_bad_signature:
+ return bofmrc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_bofm.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_bofm.c
new file mode 100644
index 00000000..bf38d88b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_bofm.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <ipxe/bofm.h>
+#include <ipxe/init.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_pci.h>
+#include <ipxe/efi/efi_driver.h>
+
+/** @file
+ *
+ * IBM BladeCenter Open Fabric Manager (BOFM) EFI interface
+ *
+ */
+
+/***************************************************************************
+ *
+ * EFI BOFM definitions
+ *
+ ***************************************************************************
+ *
+ * Taken from the BOFM UEFI Vendor Specification document
+ *
+ */
+
+#define IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL_GUID \
+ { 0x03207ce2, 0xd9c7, 0x11dc, \
+ { 0xa9, 0x4d, 0x00, 0x19, 0x7d, 0x89, 0x02, 0x38 } }
+
+#define IBM_BOFM_DRIVER_CONFIGURATION2_PROTOCOL_GUID \
+ { 0xe82a9763, 0x0584, 0x4e41, \
+ { 0xbb, 0x39, 0xe0, 0xcd, 0xb8, 0xc1, 0xf0, 0xfc } }
+
+typedef struct {
+ UINT8 Id;
+ UINT8 ResultByte;
+} __attribute__ (( packed )) BOFM_EPID_Results_t;
+
+typedef struct {
+ UINT8 Version;
+ UINT8 Level;
+ UINT16 Length;
+ UINT8 Checksum;
+ UINT8 Profile[32];
+ UINT8 GlobalOption0;
+ UINT8 GlobalOption1;
+ UINT8 GlobalOption2;
+ UINT8 GlobalOption3;
+ UINT32 SequenceStamp;
+ UINT8 Regions[911]; // For use by BOFM Driver
+ UINT32 Reserved1;
+} __attribute__ (( packed )) BOFM_Parameters_t;
+
+typedef struct {
+ UINT32 Reserved1;
+ UINT8 Version;
+ UINT8 Level;
+ UINT8 Checksum;
+ UINT32 SequenceStamp;
+ UINT8 SUIDResults;
+ UINT8 EntryResults[32];
+ UINT8 Reserved2;
+ UINT8 Reserved3;
+ UINT8 FCTgtResults[2];
+ UINT8 SASTgtResults[2];
+ BOFM_EPID_Results_t EPIDResults[2];
+ UINT8 Results4[10];
+} __attribute__ (( packed )) BOFM_Results_t;
+
+typedef struct {
+ UINT32 Signature;
+ UINT32 SubSignature;
+ BOFM_Parameters_t Parameters;
+ BOFM_Results_t Results;
+} __attribute__ (( packed )) BOFM_DataStructure_t;
+
+#define IBM_BOFM_TABLE BOFM_DataStructure_t
+
+typedef struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL
+ IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL;
+
+typedef struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2
+ IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2;
+
+typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT ) (
+ IN IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *This,
+ EFI_HANDLE ControllerHandle,
+ UINT8 SupporttedOptions,
+ UINT8 iSCSI_Parameter_Version,
+ UINT8 BOFM_Parameter_Version
+);
+
+typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_STATUS ) (
+ IN IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *This,
+ EFI_HANDLE ControllerHandle,
+ BOOLEAN ResetRequired,
+ UINT8 BOFMReturnCode
+);
+
+typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_STATUS2 ) (
+ IN IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 *This,
+ EFI_HANDLE ControllerHandle,
+ BOOLEAN ResetRequired,
+ UINT8 BOFMReturnCode
+);
+
+struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL {
+ IBM_BOFM_TABLE BofmTable;
+ IBM_BOFM_DRIVER_CONFIGURATION_STATUS SetStatus;
+ IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT RegisterSupport;
+};
+
+struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 {
+ UINT32 Signature;
+ UINT32 Reserved1;
+ UINT64 Reserved2;
+ IBM_BOFM_DRIVER_CONFIGURATION_STATUS2 SetStatus;
+ IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT RegisterSupport;
+ IBM_BOFM_TABLE BofmTable;
+};
+
+/***************************************************************************
+ *
+ * EFI BOFM interface
+ *
+ ***************************************************************************
+ */
+
+/** BOFM1 protocol GUID */
+static EFI_GUID bofm1_protocol_guid =
+ IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL_GUID;
+
+/** BOFM2 protocol GUID */
+static EFI_GUID bofm2_protocol_guid =
+ IBM_BOFM_DRIVER_CONFIGURATION2_PROTOCOL_GUID;
+
+/**
+ * Check if device is supported
+ *
+ * @v driver EFI driver
+ * @v device EFI device
+ * @v child Path to child device, if any
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
+ EFI_HANDLE device,
+ EFI_DEVICE_PATH_PROTOCOL *child ) {
+ struct efi_driver *efidrv =
+ container_of ( driver, struct efi_driver, driver );
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ union {
+ IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
+ void *interface;
+ } bofm1;
+ struct efi_pci_device *efipci;
+ EFI_STATUS efirc;
+ int rc;
+
+ DBGCP ( efidrv, "EFIBOFM DRIVER_SUPPORTED %p (%p)\n", device, child );
+
+ /* Create corresponding PCI device, if any */
+ efipci = efipci_create ( efidrv, device );
+ if ( ! efipci ) {
+ efirc = EFI_UNSUPPORTED;
+ goto err_not_pci;
+ }
+
+ /* Look for a BOFM driver */
+ if ( ( rc = bofm_find_driver ( &efipci->pci ) ) != 0 ) {
+ DBGCP ( efidrv, "EFIBOFM " PCI_FMT " has no driver\n",
+ PCI_ARGS ( &efipci->pci ) );
+ efirc = EFI_UNSUPPORTED;
+ goto err_no_driver;
+ }
+
+ /* Locate BOFM protocol */
+ if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
+ &bofm1.interface ) ) != 0 ) {
+ DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM "
+ "protocol\n", PCI_ARGS ( &efipci->pci ) );
+ efirc = EFI_UNSUPPORTED;
+ goto err_not_bofm;
+ }
+
+ /* Register support for this device */
+ if ( ( efirc = bofm1.bofm1->RegisterSupport ( bofm1.bofm1, device,
+ 0x04 /* Can change MAC */,
+ 0x00 /* No iSCSI */,
+ 0x02 /* Version */ ))!=0){
+ DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not register "
+ "support: %s\n", PCI_ARGS ( &efipci->pci ),
+ efi_strerror ( efirc ) );
+ goto err_cannot_register;
+ }
+
+ DBGC ( efidrv, "EFIBOFM " PCI_FMT " is supported by driver \"%s\"\n",
+ PCI_ARGS ( &efipci->pci ), efipci->pci.id->name );
+
+ /* Destroy temporary PCI device */
+ efipci_destroy ( efidrv, efipci );
+
+ return 0;
+
+ err_cannot_register:
+ err_not_bofm:
+ err_no_driver:
+ efipci_destroy ( efidrv, efipci );
+ err_not_pci:
+ return efirc;
+}
+
+/**
+ * Attach driver to device
+ *
+ * @v driver EFI driver
+ * @v device EFI device
+ * @v child Path to child device, if any
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
+ EFI_HANDLE device,
+ EFI_DEVICE_PATH_PROTOCOL *child ) {
+ struct efi_driver *efidrv =
+ container_of ( driver, struct efi_driver, driver );
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ union {
+ IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
+ void *interface;
+ } bofm1;
+ union {
+ IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 *bofm2;
+ void *interface;
+ } bofm2;
+ struct efi_pci_device *efipci;
+ IBM_BOFM_TABLE *bofmtab;
+ IBM_BOFM_TABLE *bofmtab2;
+ EFI_STATUS efirc;
+ int bofmrc;
+
+ DBGCP ( efidrv, "EFIBOFM DRIVER_START %p (%p)\n", device, child );
+
+ /* Create corresponding PCI device */
+ efipci = efipci_create ( efidrv, device );
+ if ( ! efipci ) {
+ efirc = EFI_OUT_OF_RESOURCES;
+ goto err_create;
+ }
+
+ /* Enable PCI device */
+ if ( ( efirc = efipci_enable ( efipci ) ) != 0 )
+ goto err_enable;
+
+ /* Locate BOFM protocol */
+ if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
+ &bofm1.interface ) ) != 0 ) {
+ DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM "
+ "protocol\n", PCI_ARGS ( &efipci->pci ) );
+ goto err_locate_bofm;
+ }
+ bofmtab = &bofm1.bofm1->BofmTable;
+ DBGC ( efidrv, "EFIBOFM " PCI_FMT " found version 1 BOFM table at "
+ "%p+%04x\n", PCI_ARGS ( &efipci->pci ), bofmtab,
+ bofmtab->Parameters.Length );
+
+ /* Locate BOFM2 protocol, if available */
+ if ( ( efirc = bs->LocateProtocol ( &bofm2_protocol_guid, NULL,
+ &bofm2.interface ) ) == 0 ) {
+ bofmtab2 = &bofm2.bofm2->BofmTable;
+ DBGC ( efidrv, "EFIBOFM " PCI_FMT " found version 2 BOFM table "
+ "at %p+%04x\n", PCI_ARGS ( &efipci->pci ), bofmtab2,
+ bofmtab2->Parameters.Length );
+ assert ( bofm2.bofm2->RegisterSupport ==
+ bofm1.bofm1->RegisterSupport );
+ } else {
+ DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM2 "
+ "protocol\n", PCI_ARGS ( &efipci->pci ) );
+ /* Not a fatal error; may be a BOFM1-only system */
+ bofmtab2 = NULL;
+ }
+
+ /* Process BOFM table */
+ DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 1 before processing:\n",
+ PCI_ARGS ( &efipci->pci ) );
+ DBGC2_HD ( efidrv, bofmtab, bofmtab->Parameters.Length );
+ if ( bofmtab2 ) {
+ DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 2 before "
+ "processing:\n", PCI_ARGS ( &efipci->pci ) );
+ DBGC2_HD ( efidrv, bofmtab2, bofmtab2->Parameters.Length );
+ }
+ bofmrc = bofm ( virt_to_user ( bofmtab2 ? bofmtab2 : bofmtab ),
+ &efipci->pci );
+ DBGC ( efidrv, "EFIBOFM " PCI_FMT " status %08x\n",
+ PCI_ARGS ( &efipci->pci ), bofmrc );
+ DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 1 after processing:\n",
+ PCI_ARGS ( &efipci->pci ) );
+ DBGC2_HD ( efidrv, bofmtab, bofmtab->Parameters.Length );
+ if ( bofmtab2 ) {
+ DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 2 after "
+ "processing:\n", PCI_ARGS ( &efipci->pci ) );
+ DBGC2_HD ( efidrv, bofmtab2, bofmtab2->Parameters.Length );
+ }
+
+ /* Return BOFM status */
+ if ( bofmtab2 ) {
+ if ( ( efirc = bofm2.bofm2->SetStatus ( bofm2.bofm2, device,
+ FALSE, bofmrc ) ) != 0){
+ DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not set "
+ "BOFM2 status: %s\n", PCI_ARGS ( &efipci->pci ),
+ efi_strerror ( efirc ) );
+ goto err_set_status;
+ }
+ } else {
+ if ( ( efirc = bofm1.bofm1->SetStatus ( bofm1.bofm1, device,
+ FALSE, bofmrc ) ) != 0){
+ DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not set "
+ "BOFM status: %s\n", PCI_ARGS ( &efipci->pci ),
+ efi_strerror ( efirc ) );
+ goto err_set_status;
+ }
+ }
+
+ /* Destroy the PCI device anyway; we have no further use for it */
+ efipci_destroy ( efidrv, efipci );
+
+ /* BOFM (ab)uses the "start" method to mean "process and exit" */
+ return EFI_NOT_READY;
+
+ err_set_status:
+ err_locate_bofm:
+ err_enable:
+ efipci_destroy ( efidrv, efipci );
+ err_create:
+ return efirc;
+}
+
+/**
+ * Detach driver from device
+ *
+ * @v driver EFI driver
+ * @v device EFI device
+ * @v num_children Number of child devices
+ * @v children List of child devices
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI efi_bofm_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver,
+ EFI_HANDLE device, UINTN num_children,
+ EFI_HANDLE *children ) {
+ struct efi_driver *efidrv =
+ container_of ( driver, struct efi_driver, driver );
+
+ DBGCP ( efidrv, "EFIBOFM DRIVER_STOP %p (%ld %p)\n",
+ device, ( ( unsigned long ) num_children ), children );
+
+ return 0;
+}
+
+/** EFI BOFM driver */
+static struct efi_driver efi_bofm_driver =
+ EFI_DRIVER_INIT ( "BOFM",
+ efi_bofm_supported, efi_bofm_start, efi_bofm_stop );
+
+/**
+ * Install EFI BOFM driver
+ *
+ */
+static void efi_bofm_driver_init ( void ) {
+ struct efi_driver *efidrv = &efi_bofm_driver;
+ EFI_STATUS efirc;
+
+ /* Install driver */
+ if ( ( efirc = efi_driver_install ( efidrv ) ) != 0 ) {
+ DBGC ( efidrv, "EFIBOFM could not install driver: %s\n",
+ efi_strerror ( efirc ) );
+ return;
+ }
+
+ DBGC ( efidrv, "EFIBOFM driver installed\n" );
+}
+
+/** EFI BOFM startup function */
+struct startup_fn startup_bofm __startup_fn ( STARTUP_EARLY ) = {
+ .startup = efi_bofm_driver_init,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_console.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_console.c
new file mode 100644
index 00000000..6b612438
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_console.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <assert.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/ansiesc.h>
+#include <ipxe/console.h>
+#include <config/console.h>
+
+#define ATTR_BOLD 0x08
+
+#define ATTR_FCOL_MASK 0x07
+#define ATTR_FCOL_BLACK 0x00
+#define ATTR_FCOL_BLUE 0x01
+#define ATTR_FCOL_GREEN 0x02
+#define ATTR_FCOL_CYAN 0x03
+#define ATTR_FCOL_RED 0x04
+#define ATTR_FCOL_MAGENTA 0x05
+#define ATTR_FCOL_YELLOW 0x06
+#define ATTR_FCOL_WHITE 0x07
+
+#define ATTR_BCOL_MASK 0x70
+#define ATTR_BCOL_BLACK 0x00
+#define ATTR_BCOL_BLUE 0x10
+#define ATTR_BCOL_GREEN 0x20
+#define ATTR_BCOL_CYAN 0x30
+#define ATTR_BCOL_RED 0x40
+#define ATTR_BCOL_MAGENTA 0x50
+#define ATTR_BCOL_YELLOW 0x60
+#define ATTR_BCOL_WHITE 0x70
+
+#define ATTR_DEFAULT ATTR_FCOL_WHITE
+
+/* Set default console usage if applicable */
+#if ! ( defined ( CONSOLE_EFI ) && CONSOLE_EXPLICIT ( CONSOLE_EFI ) )
+#undef CONSOLE_EFI
+#define CONSOLE_EFI ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
+#endif
+
+/** Current character attribute */
+static unsigned int efi_attr = ATTR_DEFAULT;
+
+/**
+ * Handle ANSI CUP (cursor position)
+ *
+ * @v count Parameter count
+ * @v params[0] Row (1 is top)
+ * @v params[1] Column (1 is left)
+ */
+static void efi_handle_cup ( unsigned int count __unused, int params[] ) {
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut;
+ int cx = ( params[1] - 1 );
+ int cy = ( params[0] - 1 );
+
+ if ( cx < 0 )
+ cx = 0;
+ if ( cy < 0 )
+ cy = 0;
+
+ conout->SetCursorPosition ( conout, cx, cy );
+}
+
+/**
+ * Handle ANSI ED (erase in page)
+ *
+ * @v count Parameter count
+ * @v params[0] Region to erase
+ */
+static void efi_handle_ed ( unsigned int count __unused,
+ int params[] __unused ) {
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut;
+
+ /* We assume that we always clear the whole screen */
+ assert ( params[0] == ANSIESC_ED_ALL );
+
+ conout->ClearScreen ( conout );
+}
+
+/**
+ * Handle ANSI SGR (set graphics rendition)
+ *
+ * @v count Parameter count
+ * @v params List of graphic rendition aspects
+ */
+static void efi_handle_sgr ( unsigned int count, int params[] ) {
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut;
+ static const uint8_t efi_attr_fcols[10] = {
+ ATTR_FCOL_BLACK, ATTR_FCOL_RED, ATTR_FCOL_GREEN,
+ ATTR_FCOL_YELLOW, ATTR_FCOL_BLUE, ATTR_FCOL_MAGENTA,
+ ATTR_FCOL_CYAN, ATTR_FCOL_WHITE,
+ ATTR_FCOL_WHITE, ATTR_FCOL_WHITE /* defaults */
+ };
+ static const uint8_t efi_attr_bcols[10] = {
+ ATTR_BCOL_BLACK, ATTR_BCOL_RED, ATTR_BCOL_GREEN,
+ ATTR_BCOL_YELLOW, ATTR_BCOL_BLUE, ATTR_BCOL_MAGENTA,
+ ATTR_BCOL_CYAN, ATTR_BCOL_WHITE,
+ ATTR_BCOL_BLACK, ATTR_BCOL_BLACK /* defaults */
+ };
+ unsigned int i;
+ int aspect;
+
+ for ( i = 0 ; i < count ; i++ ) {
+ aspect = params[i];
+ if ( aspect == 0 ) {
+ efi_attr = ATTR_DEFAULT;
+ } else if ( aspect == 1 ) {
+ efi_attr |= ATTR_BOLD;
+ } else if ( aspect == 22 ) {
+ efi_attr &= ~ATTR_BOLD;
+ } else if ( ( aspect >= 30 ) && ( aspect <= 39 ) ) {
+ efi_attr &= ~ATTR_FCOL_MASK;
+ efi_attr |= efi_attr_fcols[ aspect - 30 ];
+ } else if ( ( aspect >= 40 ) && ( aspect <= 49 ) ) {
+ efi_attr &= ~ATTR_BCOL_MASK;
+ efi_attr |= efi_attr_bcols[ aspect - 40 ];
+ }
+ }
+
+ conout->SetAttribute ( conout, efi_attr );
+}
+
+/** EFI console ANSI escape sequence handlers */
+static struct ansiesc_handler efi_ansiesc_handlers[] = {
+ { ANSIESC_CUP, efi_handle_cup },
+ { ANSIESC_ED, efi_handle_ed },
+ { ANSIESC_SGR, efi_handle_sgr },
+ { 0, NULL }
+};
+
+/** EFI console ANSI escape sequence context */
+static struct ansiesc_context efi_ansiesc_ctx = {
+ .handlers = efi_ansiesc_handlers,
+};
+
+/**
+ * Print a character to EFI console
+ *
+ * @v character Character to be printed
+ */
+static void efi_putchar ( int character ) {
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut;
+ wchar_t wstr[] = { character, 0 };
+
+ /* Intercept ANSI escape sequences */
+ character = ansiesc_process ( &efi_ansiesc_ctx, character );
+ if ( character < 0 )
+ return;
+
+ conout->OutputString ( conout, wstr );
+}
+
+/**
+ * Pointer to current ANSI output sequence
+ *
+ * While we are in the middle of returning an ANSI sequence for a
+ * special key, this will point to the next character to return. When
+ * not in the middle of such a sequence, this will point to a NUL
+ * (note: not "will be NULL").
+ */
+static const char *ansi_input = "";
+
+/** Mapping from EFI scan codes to ANSI escape sequences */
+static const char *ansi_sequences[] = {
+ [SCAN_UP] = "[A",
+ [SCAN_DOWN] = "[B",
+ [SCAN_RIGHT] = "[C",
+ [SCAN_LEFT] = "[D",
+ [SCAN_HOME] = "[H",
+ [SCAN_END] = "[F",
+ [SCAN_INSERT] = "[2~",
+ /* EFI translates an incoming backspace via the serial console
+ * into a SCAN_DELETE. There's not much we can do about this.
+ */
+ [SCAN_DELETE] = "[3~",
+ [SCAN_PAGE_UP] = "[5~",
+ [SCAN_PAGE_DOWN] = "[6~",
+ /* EFI translates some (but not all) incoming escape sequences
+ * via the serial console into equivalent scancodes. When it
+ * doesn't recognise a sequence, it helpfully(!) translates
+ * the initial ESC and passes the remainder through verbatim.
+ * Treating SCAN_ESC as equivalent to an empty escape sequence
+ * works around this bug.
+ */
+ [SCAN_ESC] = "",
+};
+
+/**
+ * Get ANSI escape sequence corresponding to EFI scancode
+ *
+ * @v scancode EFI scancode
+ * @ret ansi_seq ANSI escape sequence, if any, otherwise NULL
+ */
+static const char * scancode_to_ansi_seq ( unsigned int scancode ) {
+ if ( scancode < ( sizeof ( ansi_sequences ) /
+ sizeof ( ansi_sequences[0] ) ) ) {
+ return ansi_sequences[scancode];
+ }
+ return NULL;
+}
+
+/**
+ * Get character from EFI console
+ *
+ * @ret character Character read from console
+ */
+static int efi_getchar ( void ) {
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *conin = efi_systab->ConIn;
+ const char *ansi_seq;
+ EFI_INPUT_KEY key;
+ EFI_STATUS efirc;
+
+ /* If we are mid-sequence, pass out the next byte */
+ if ( *ansi_input )
+ return *(ansi_input++);
+
+ /* Read key from real EFI console */
+ if ( ( efirc = conin->ReadKeyStroke ( conin, &key ) ) != 0 ) {
+ DBG ( "EFI could not read keystroke: %s\n",
+ efi_strerror ( efirc ) );
+ return 0;
+ }
+ DBG2 ( "EFI read key stroke with unicode %04x scancode %04x\n",
+ key.UnicodeChar, key.ScanCode );
+
+ /* If key has a Unicode representation, return it */
+ if ( key.UnicodeChar )
+ return key.UnicodeChar;
+
+ /* Otherwise, check for a special key that we know about */
+ if ( ( ansi_seq = scancode_to_ansi_seq ( key.ScanCode ) ) ) {
+ /* Start of escape sequence: return ESC (0x1b) */
+ ansi_input = ansi_seq;
+ return 0x1b;
+ }
+
+ return 0;
+}
+
+/**
+ * Check for character ready to read from EFI console
+ *
+ * @ret True Character available to read
+ * @ret False No character available to read
+ */
+static int efi_iskey ( void ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *conin = efi_systab->ConIn;
+ EFI_STATUS efirc;
+
+ /* If we are mid-sequence, we are always ready */
+ if ( *ansi_input )
+ return 1;
+
+ /* Check to see if the WaitForKey event has fired */
+ if ( ( efirc = bs->CheckEvent ( conin->WaitForKey ) ) == 0 )
+ return 1;
+
+ return 0;
+}
+
+struct console_driver efi_console __console_driver = {
+ .putchar = efi_putchar,
+ .getchar = efi_getchar,
+ .iskey = efi_iskey,
+ .usage = CONSOLE_EFI,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_download.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_download.c
new file mode 100644
index 00000000..250946e2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_download.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2010 VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <string.h>
+#include <ipxe/open.h>
+#include <ipxe/process.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/ipxe_download.h>
+
+/** iPXE download protocol GUID */
+static EFI_GUID ipxe_download_protocol_guid
+ = IPXE_DOWNLOAD_PROTOCOL_GUID;
+
+/** A single in-progress file */
+struct efi_download_file {
+ /** Data transfer interface that provides downloaded data */
+ struct interface xfer;
+
+ /** Current file position */
+ size_t pos;
+
+ /** Data callback */
+ IPXE_DOWNLOAD_DATA_CALLBACK data_callback;
+
+ /** Finish callback */
+ IPXE_DOWNLOAD_FINISH_CALLBACK finish_callback;
+
+ /** Callback context */
+ void *context;
+};
+
+/* xfer interface */
+
+/**
+ * Transfer finished or was aborted
+ *
+ * @v file Data transfer file
+ * @v rc Reason for close
+ */
+static void efi_download_close ( struct efi_download_file *file, int rc ) {
+
+ file->finish_callback ( file->context, RC_TO_EFIRC ( rc ) );
+
+ intf_shutdown ( &file->xfer, rc );
+}
+
+/**
+ * Process received data
+ *
+ * @v file Data transfer file
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int efi_download_deliver_iob ( struct efi_download_file *file,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ EFI_STATUS efirc;
+ size_t len = iob_len ( iobuf );
+
+ /* Calculate new buffer position */
+ if ( meta->flags & XFER_FL_ABS_OFFSET )
+ file->pos = 0;
+ file->pos += meta->offset;
+
+ /* Call out to the data handler */
+ efirc = file->data_callback ( file->context, iobuf->data,
+ len, file->pos );
+
+ /* Update current buffer position */
+ file->pos += len;
+
+ free_iob ( iobuf );
+ return EFIRC_TO_RC ( efirc );
+}
+
+/** Data transfer interface operations */
+static struct interface_operation efi_xfer_operations[] = {
+ INTF_OP ( xfer_deliver, struct efi_download_file *, efi_download_deliver_iob ),
+ INTF_OP ( intf_close, struct efi_download_file *, efi_download_close ),
+};
+
+/** EFI download data transfer interface descriptor */
+static struct interface_descriptor efi_download_file_xfer_desc =
+ INTF_DESC ( struct efi_download_file, xfer, efi_xfer_operations );
+
+/**
+ * Start downloading a file, and register callback functions to handle the
+ * download.
+ *
+ * @v This iPXE Download Protocol instance
+ * @v Url URL to download from
+ * @v DataCallback Callback that will be invoked when data arrives
+ * @v FinishCallback Callback that will be invoked when the download ends
+ * @v Context Context passed to the Data and Finish callbacks
+ * @v File Token that can be used to abort the download
+ * @ret Status EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_download_start ( IPXE_DOWNLOAD_PROTOCOL *This __unused,
+ CHAR8 *Url,
+ IPXE_DOWNLOAD_DATA_CALLBACK DataCallback,
+ IPXE_DOWNLOAD_FINISH_CALLBACK FinishCallback,
+ VOID *Context,
+ IPXE_DOWNLOAD_FILE *File ) {
+ struct efi_download_file *file;
+ int rc;
+
+ file = malloc ( sizeof ( struct efi_download_file ) );
+ if ( file == NULL ) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ intf_init ( &file->xfer, &efi_download_file_xfer_desc, NULL );
+ rc = xfer_open ( &file->xfer, LOCATION_URI_STRING, Url );
+ if ( rc ) {
+ free ( file );
+ return RC_TO_EFIRC ( rc );
+ }
+
+ file->pos = 0;
+ file->data_callback = DataCallback;
+ file->finish_callback = FinishCallback;
+ file->context = Context;
+ *File = file;
+ return EFI_SUCCESS;
+}
+
+/**
+ * Forcibly abort downloading a file that is currently in progress.
+ *
+ * It is not safe to call this function after the Finish callback has executed.
+ *
+ * @v This iPXE Download Protocol instance
+ * @v File Token obtained from Start
+ * @v Status Reason for aborting the download
+ * @ret Status EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_download_abort ( IPXE_DOWNLOAD_PROTOCOL *This __unused,
+ IPXE_DOWNLOAD_FILE File,
+ EFI_STATUS Status ) {
+ struct efi_download_file *file = File;
+
+ efi_download_close ( file, EFIRC_TO_RC ( Status ) );
+ return EFI_SUCCESS;
+}
+
+/**
+ * Poll for more data from iPXE. This function will invoke the registered
+ * callbacks if data is available or if downloads complete.
+ *
+ * @v This iPXE Download Protocol instance
+ * @ret Status EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_download_poll ( IPXE_DOWNLOAD_PROTOCOL *This __unused ) {
+ step();
+ return EFI_SUCCESS;
+}
+
+/** Publicly exposed iPXE download protocol */
+static IPXE_DOWNLOAD_PROTOCOL ipxe_download_protocol_interface = {
+ .Start = efi_download_start,
+ .Abort = efi_download_abort,
+ .Poll = efi_download_poll
+};
+
+/**
+ * Create a new device handle with a iPXE download protocol attached to it.
+ *
+ * @v device_handle Newly created device handle (output)
+ * @ret rc Return status code
+ */
+int efi_download_install ( EFI_HANDLE *device_handle ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_STATUS efirc;
+ EFI_HANDLE handle = NULL;
+ if (efi_loaded_image->DeviceHandle) { /* TODO: ensure handle is the NIC (maybe efi_image has a better way to indicate the handle doing SNP?) */
+ handle = efi_loaded_image->DeviceHandle;
+ }
+
+ DBG ( "Installing ipxe protocol interface (%p)... ",
+ &ipxe_download_protocol_interface );
+ efirc = bs->InstallMultipleProtocolInterfaces (
+ &handle,
+ &ipxe_download_protocol_guid,
+ &ipxe_download_protocol_interface,
+ NULL );
+ if ( efirc ) {
+ DBG ( "failed (%s)\n", efi_strerror ( efirc ) );
+ return EFIRC_TO_RC ( efirc );
+ }
+
+ DBG ( "success (%p)\n", handle );
+ *device_handle = handle;
+ return 0;
+}
+
+/**
+ * Remove the iPXE download protocol from the given handle, and if nothing
+ * else is attached, destroy the handle.
+ *
+ * @v device_handle EFI device handle to remove from
+ */
+void efi_download_uninstall ( EFI_HANDLE device_handle ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+
+ bs->UninstallMultipleProtocolInterfaces (
+ device_handle,
+ ipxe_download_protocol_guid,
+ ipxe_download_protocol_interface );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_driver.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_driver.c
new file mode 100644
index 00000000..4aa976f9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_driver.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdio.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/Protocol/DriverBinding.h>
+#include <ipxe/efi/Protocol/ComponentName2.h>
+#include <ipxe/efi/efi_strings.h>
+#include <ipxe/efi/efi_driver.h>
+#include <config/general.h>
+
+/** @file
+ *
+ * EFI driver interface
+ *
+ */
+
+/** EFI driver binding protocol GUID */
+static EFI_GUID efi_driver_binding_protocol_guid
+ = EFI_DRIVER_BINDING_PROTOCOL_GUID;
+
+/** EFI component name protocol GUID */
+static EFI_GUID efi_component_name2_protocol_guid
+ = EFI_COMPONENT_NAME2_PROTOCOL_GUID;
+
+/**
+ * Find end of device path
+ *
+ * @v path Path to device
+ * @ret path_end End of device path
+ */
+EFI_DEVICE_PATH_PROTOCOL * efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ) {
+
+ while ( path->Type != END_DEVICE_PATH_TYPE ) {
+ path = ( ( ( void * ) path ) +
+ /* There's this amazing new-fangled thing known as
+ * a UINT16, but who wants to use one of those? */
+ ( ( path->Length[1] << 8 ) | path->Length[0] ) );
+ }
+
+ return path;
+}
+
+/**
+ * Look up driver name
+ *
+ * @v wtf Component name protocol
+ * @v language Language to use
+ * @v driver_name Driver name to fill in
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_driver_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf,
+ CHAR8 *language __unused, CHAR16 **driver_name ) {
+ struct efi_driver *efidrv =
+ container_of ( wtf, struct efi_driver, wtf );
+
+ *driver_name = efidrv->wname;
+ return 0;
+}
+
+/**
+ * Look up controller name
+ *
+ * @v wtf Component name protocol
+ * @v device Device
+ * @v child Child device, or NULL
+ * @v language Language to use
+ * @v driver_name Device name to fill in
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_driver_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
+ EFI_HANDLE device __unused,
+ EFI_HANDLE child __unused,
+ CHAR8 *language __unused,
+ CHAR16 **controller_name __unused ) {
+
+ /* Just let EFI use the default Device Path Name */
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * Install EFI driver
+ *
+ * @v efidrv EFI driver
+ * @ret efirc EFI status code
+ */
+EFI_STATUS efi_driver_install ( struct efi_driver *efidrv ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_DRIVER_BINDING_PROTOCOL *driver = &efidrv->driver;
+ EFI_COMPONENT_NAME2_PROTOCOL *wtf = &efidrv->wtf;
+ EFI_STATUS efirc;
+
+ /* Configure driver binding protocol */
+ driver->ImageHandle = efi_image_handle;
+
+ /* Configure component name protocol */
+ wtf->GetDriverName = efi_driver_get_driver_name;
+ wtf->GetControllerName = efi_driver_get_controller_name;
+ wtf->SupportedLanguages = "en";
+
+ /* Fill in driver name */
+ efi_snprintf ( efidrv->wname,
+ ( sizeof ( efidrv->wname ) /
+ sizeof ( efidrv->wname[0] ) ),
+ PRODUCT_SHORT_NAME " - %s", efidrv->name );
+
+ /* Install driver */
+ if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
+ &driver->DriverBindingHandle,
+ &efi_driver_binding_protocol_guid, driver,
+ &efi_component_name2_protocol_guid, wtf,
+ NULL ) ) != 0 ) {
+ DBGC ( efidrv, "EFIDRV %s could not install protocol: %s\n",
+ efidrv->name, efi_strerror ( efirc ) );
+ return efirc;
+ }
+
+ DBGC ( efidrv, "EFIDRV %s installed\n", efidrv->name );
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_init.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_init.c
new file mode 100644
index 00000000..6c7b4955
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_init.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/Protocol/LoadedImage.h>
+#include <ipxe/uuid.h>
+#include <ipxe/init.h>
+
+/** Image handle passed to entry point */
+EFI_HANDLE efi_image_handle;
+
+/** Loaded image protocol for this image */
+EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image;
+
+/** System table passed to entry point */
+EFI_SYSTEM_TABLE *efi_systab;
+
+/** EFI loaded image protocol GUID */
+static EFI_GUID efi_loaded_image_protocol_guid
+ = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+
+/** Event used to signal shutdown */
+static EFI_EVENT efi_shutdown_event;
+
+/**
+ * Shut down in preparation for booting an OS.
+ *
+ * This hook gets called at ExitBootServices time in order to make
+ * sure that everything is properly shut down before the OS takes
+ * over.
+ */
+static EFIAPI void efi_shutdown_hook ( EFI_EVENT event __unused,
+ void *context __unused ) {
+ shutdown_boot();
+}
+
+/**
+ * Look up EFI configuration table
+ *
+ * @v guid Configuration table GUID
+ * @ret table Configuration table, or NULL
+ */
+static void * efi_find_table ( EFI_GUID *guid ) {
+ unsigned int i;
+
+ for ( i = 0 ; i < efi_systab->NumberOfTableEntries ; i++ ) {
+ if ( memcmp ( &efi_systab->ConfigurationTable[i].VendorGuid,
+ guid, sizeof ( *guid ) ) == 0 )
+ return efi_systab->ConfigurationTable[i].VendorTable;
+ }
+
+ return NULL;
+}
+
+/**
+ * Initialise EFI environment
+ *
+ * @v image_handle Image handle
+ * @v systab System table
+ * @ret efirc EFI return status code
+ */
+EFI_STATUS efi_init ( EFI_HANDLE image_handle,
+ EFI_SYSTEM_TABLE *systab ) {
+ EFI_BOOT_SERVICES *bs;
+ struct efi_protocol *prot;
+ struct efi_config_table *tab;
+ EFI_STATUS efirc;
+ void *loaded_image;
+
+ /* Store image handle and system table pointer for future use */
+ efi_image_handle = image_handle;
+ efi_systab = systab;
+
+ /* Sanity checks */
+ if ( ! systab )
+ return EFI_NOT_AVAILABLE_YET;
+ if ( ! systab->ConOut )
+ return EFI_NOT_AVAILABLE_YET;
+ if ( ! systab->BootServices ) {
+ DBGC ( systab, "EFI provided no BootServices entry point\n" );
+ return EFI_NOT_AVAILABLE_YET;
+ }
+ if ( ! systab->RuntimeServices ) {
+ DBGC ( systab, "EFI provided no RuntimeServices entry "
+ "point\n" );
+ return EFI_NOT_AVAILABLE_YET;
+ }
+ DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab );
+
+ bs = systab->BootServices;
+ efirc = bs->OpenProtocol ( image_handle,
+ &efi_loaded_image_protocol_guid,
+ &loaded_image, image_handle, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+ if ( efirc ) {
+ DBGC ( systab, "Could not get loaded image protocol" );
+ return efirc;
+ }
+
+ efi_loaded_image = loaded_image;
+ DBG ( "Image base address = %p\n", efi_loaded_image->ImageBase );
+
+ /* Look up used protocols */
+ for_each_table_entry ( prot, EFI_PROTOCOLS ) {
+ if ( ( efirc = bs->LocateProtocol ( &prot->u.guid, NULL,
+ prot->protocol ) ) == 0 ) {
+ DBGC ( systab, "EFI protocol %s is at %p\n",
+ uuid_ntoa ( &prot->u.uuid ), *(prot->protocol));
+ } else {
+ DBGC ( systab, "EFI does not provide protocol %s\n",
+ uuid_ntoa ( &prot->u.uuid ) );
+ /* All protocols are required */
+ return efirc;
+ }
+ }
+
+ /* Look up used configuration tables */
+ for_each_table_entry ( tab, EFI_CONFIG_TABLES ) {
+ if ( ( *(tab->table) = efi_find_table ( &tab->u.guid ) ) ) {
+ DBGC ( systab, "EFI configuration table %s is at %p\n",
+ uuid_ntoa ( &tab->u.uuid ), *(tab->table) );
+ } else {
+ DBGC ( systab, "EFI does not provide configuration "
+ "table %s\n", uuid_ntoa ( &tab->u.uuid ) );
+ if ( tab->required )
+ return EFI_NOT_AVAILABLE_YET;
+ }
+ }
+
+ /* EFI is perfectly capable of gracefully shutting down any
+ * loaded devices if it decides to fall back to a legacy boot.
+ * For no particularly comprehensible reason, it doesn't
+ * bother doing so when ExitBootServices() is called.
+ */
+ if ( ( efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES,
+ TPL_CALLBACK, efi_shutdown_hook,
+ NULL, &efi_shutdown_event ) ) != 0 ) {
+ DBGC ( systab, "EFI could not create ExitBootServices event: "
+ "%s\n", efi_strerror ( efirc ) );
+ return efirc;
+ }
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_io.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_io.c
new file mode 100644
index 00000000..9a9aad31
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_io.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <assert.h>
+#include <ipxe/io.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/Protocol/CpuIo.h>
+#include <ipxe/efi/efi_io.h>
+
+/** @file
+ *
+ * iPXE I/O API for EFI
+ *
+ */
+
+/** CPU I/O protocol */
+static EFI_CPU_IO_PROTOCOL *cpu_io;
+EFI_REQUIRE_PROTOCOL ( EFI_CPU_IO_PROTOCOL, &cpu_io );
+
+/** Maximum address that can be used for port I/O */
+#define MAX_PORT_ADDRESS 0xffff
+
+/**
+ * Determine whether or not address is a port I/O address
+ *
+ * @v io_addr I/O address
+ * @v is_port I/O address is a port I/O address
+ */
+#define IS_PORT_ADDRESS(io_addr) \
+ ( ( ( intptr_t ) (io_addr) ) <= MAX_PORT_ADDRESS )
+
+/**
+ * Determine EFI CPU I/O width code
+ *
+ * @v size Size of value
+ * @ret width EFI width code
+ *
+ * Someone at Intel clearly gets paid by the number of lines of code
+ * they write. No-one should ever be able to make I/O this
+ * convoluted. The EFI_CPU_IO_PROTOCOL_WIDTH enum is my favourite
+ * idiocy.
+ */
+static EFI_CPU_IO_PROTOCOL_WIDTH efi_width ( size_t size ) {
+ switch ( size ) {
+ case 1 : return EfiCpuIoWidthFifoUint8;
+ case 2 : return EfiCpuIoWidthFifoUint16;
+ case 4 : return EfiCpuIoWidthFifoUint32;
+ case 8 : return EfiCpuIoWidthFifoUint64;
+ default :
+ assert ( 0 );
+ /* I wonder what this will actually do... */
+ return EfiCpuIoWidthMaximum;
+ }
+}
+
+/**
+ * Read from device
+ *
+ * @v io_addr I/O address
+ * @v size Size of value
+ * @ret data Value read
+ */
+unsigned long long efi_ioread ( volatile void *io_addr, size_t size ) {
+ EFI_CPU_IO_PROTOCOL_IO_MEM read;
+ unsigned long long data = 0;
+ EFI_STATUS efirc;
+
+ read = ( IS_PORT_ADDRESS ( io_addr ) ?
+ cpu_io->Io.Read : cpu_io->Mem.Read );
+
+ if ( ( efirc = read ( cpu_io, efi_width ( size ),
+ ( intptr_t ) io_addr, 1,
+ ( void * ) &data ) ) != 0 ) {
+ DBG ( "EFI I/O read at %p failed: %s\n",
+ io_addr, efi_strerror ( efirc ) );
+ return -1ULL;
+ }
+
+ return data;
+}
+
+/**
+ * Write to device
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ * @v size Size of value
+ */
+void efi_iowrite ( unsigned long long data, volatile void *io_addr,
+ size_t size ) {
+ EFI_CPU_IO_PROTOCOL_IO_MEM write;
+ EFI_STATUS efirc;
+
+ write = ( IS_PORT_ADDRESS ( io_addr ) ?
+ cpu_io->Io.Write : cpu_io->Mem.Write );
+
+ if ( ( efirc = write ( cpu_io, efi_width ( size ),
+ ( intptr_t ) io_addr, 1,
+ ( void * ) &data ) ) != 0 ) {
+ DBG ( "EFI I/O write at %p failed: %s\n",
+ io_addr, efi_strerror ( efirc ) );
+ }
+}
+
+/**
+ * String read from device
+ *
+ * @v io_addr I/O address
+ * @v data Data buffer
+ * @v size Size of values
+ * @v count Number of values to read
+ */
+void efi_ioreads ( volatile void *io_addr, void *data,
+ size_t size, unsigned int count ) {
+ EFI_CPU_IO_PROTOCOL_IO_MEM read;
+ EFI_STATUS efirc;
+
+ read = ( IS_PORT_ADDRESS ( io_addr ) ?
+ cpu_io->Io.Read : cpu_io->Mem.Read );
+
+ if ( ( efirc = read ( cpu_io, efi_width ( size ),
+ ( intptr_t ) io_addr, count,
+ ( void * ) data ) ) != 0 ) {
+ DBG ( "EFI I/O string read at %p failed: %s\n",
+ io_addr, efi_strerror ( efirc ) );
+ }
+}
+
+/**
+ * String write to device
+ *
+ * @v io_addr I/O address
+ * @v data Data buffer
+ * @v size Size of values
+ * @v count Number of values to write
+ */
+void efi_iowrites ( volatile void *io_addr, const void *data,
+ size_t size, unsigned int count ) {
+ EFI_CPU_IO_PROTOCOL_IO_MEM write;
+ EFI_STATUS efirc;
+
+ write = ( IS_PORT_ADDRESS ( io_addr ) ?
+ cpu_io->Io.Write : cpu_io->Mem.Write );
+
+ if ( ( efirc = write ( cpu_io, efi_width ( size ),
+ ( intptr_t ) io_addr, count,
+ ( void * ) data ) ) != 0 ) {
+ DBG ( "EFI I/O write at %p failed: %s\n",
+ io_addr, efi_strerror ( efirc ) );
+ }
+}
+
+/**
+ * Wait for I/O-mapped operation to complete
+ *
+ */
+static void efi_iodelay ( void ) {
+ /* Write to non-existent port. Probably x86-only. */
+ outb ( 0, 0x80 );
+}
+
+/**
+ * Get memory map
+ *
+ * Can't be done on EFI so return an empty map
+ *
+ * @v memmap Memory map to fill in
+ */
+static void efi_get_memmap ( struct memory_map *memmap ) {
+ memmap->count = 0;
+}
+
+PROVIDE_IOAPI_INLINE ( efi, phys_to_bus );
+PROVIDE_IOAPI_INLINE ( efi, bus_to_phys );
+PROVIDE_IOAPI_INLINE ( efi, ioremap );
+PROVIDE_IOAPI_INLINE ( efi, iounmap );
+PROVIDE_IOAPI_INLINE ( efi, io_to_bus );
+PROVIDE_IOAPI_INLINE ( efi, readb );
+PROVIDE_IOAPI_INLINE ( efi, readw );
+PROVIDE_IOAPI_INLINE ( efi, readl );
+PROVIDE_IOAPI_INLINE ( efi, readq );
+PROVIDE_IOAPI_INLINE ( efi, writeb );
+PROVIDE_IOAPI_INLINE ( efi, writew );
+PROVIDE_IOAPI_INLINE ( efi, writel );
+PROVIDE_IOAPI_INLINE ( efi, writeq );
+PROVIDE_IOAPI_INLINE ( efi, inb );
+PROVIDE_IOAPI_INLINE ( efi, inw );
+PROVIDE_IOAPI_INLINE ( efi, inl );
+PROVIDE_IOAPI_INLINE ( efi, outb );
+PROVIDE_IOAPI_INLINE ( efi, outw );
+PROVIDE_IOAPI_INLINE ( efi, outl );
+PROVIDE_IOAPI_INLINE ( efi, insb );
+PROVIDE_IOAPI_INLINE ( efi, insw );
+PROVIDE_IOAPI_INLINE ( efi, insl );
+PROVIDE_IOAPI_INLINE ( efi, outsb );
+PROVIDE_IOAPI_INLINE ( efi, outsw );
+PROVIDE_IOAPI_INLINE ( efi, outsl );
+PROVIDE_IOAPI ( efi, iodelay, efi_iodelay );
+PROVIDE_IOAPI_INLINE ( efi, mb );
+PROVIDE_IOAPI ( efi, get_memmap, efi_get_memmap );
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_pci.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_pci.c
new file mode 100644
index 00000000..fa71e7d8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_pci.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <errno.h>
+#include <ipxe/pci.h>
+#include <ipxe/init.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_pci.h>
+#include <ipxe/efi/efi_driver.h>
+#include <ipxe/efi/Protocol/PciIo.h>
+#include <ipxe/efi/Protocol/PciRootBridgeIo.h>
+
+/** @file
+ *
+ * iPXE PCI I/O API for EFI
+ *
+ */
+
+/******************************************************************************
+ *
+ * iPXE PCI API
+ *
+ ******************************************************************************
+ */
+
+/** PCI root bridge I/O protocol */
+static EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *efipci;
+EFI_REQUIRE_PROTOCOL ( EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL, &efipci );
+
+static unsigned long efipci_address ( struct pci_device *pci,
+ unsigned long location ) {
+ return EFI_PCI_ADDRESS ( PCI_BUS ( pci->busdevfn ),
+ PCI_SLOT ( pci->busdevfn ),
+ PCI_FUNC ( pci->busdevfn ),
+ EFIPCI_OFFSET ( location ) );
+}
+
+int efipci_read ( struct pci_device *pci, unsigned long location,
+ void *value ) {
+ EFI_STATUS efirc;
+
+ if ( ( efirc = efipci->Pci.Read ( efipci, EFIPCI_WIDTH ( location ),
+ efipci_address ( pci, location ), 1,
+ value ) ) != 0 ) {
+ DBG ( "EFIPCI config read from " PCI_FMT " offset %02lx "
+ "failed: %s\n", PCI_ARGS ( pci ),
+ EFIPCI_OFFSET ( location ), efi_strerror ( efirc ) );
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int efipci_write ( struct pci_device *pci, unsigned long location,
+ unsigned long value ) {
+ EFI_STATUS efirc;
+
+ if ( ( efirc = efipci->Pci.Write ( efipci, EFIPCI_WIDTH ( location ),
+ efipci_address ( pci, location ), 1,
+ &value ) ) != 0 ) {
+ DBG ( "EFIPCI config write to " PCI_FMT " offset %02lx "
+ "failed: %s\n", PCI_ARGS ( pci ),
+ EFIPCI_OFFSET ( location ), efi_strerror ( efirc ) );
+ return -EIO;
+ }
+
+ return 0;
+}
+
+PROVIDE_PCIAPI_INLINE ( efi, pci_num_bus );
+PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_byte );
+PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_word );
+PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_dword );
+PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_byte );
+PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_word );
+PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_dword );
+
+/******************************************************************************
+ *
+ * EFI PCI device instantiation
+ *
+ ******************************************************************************
+ */
+
+/** EFI PCI I/O protocol GUID */
+static EFI_GUID efi_pci_io_protocol_guid
+ = EFI_PCI_IO_PROTOCOL_GUID;
+
+/** EFI device path protocol GUID */
+static EFI_GUID efi_device_path_protocol_guid
+ = EFI_DEVICE_PATH_PROTOCOL_GUID;
+
+/** EFI PCI devices */
+static LIST_HEAD ( efi_pci_devices );
+
+/**
+ * Create EFI PCI device
+ *
+ * @v efidrv EFI driver
+ * @v device EFI device
+ * @ret efipci EFI PCI device, or NULL
+ */
+struct efi_pci_device * efipci_create ( struct efi_driver *efidrv,
+ EFI_HANDLE device ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ struct efi_pci_device *efipci;
+ union {
+ EFI_PCI_IO_PROTOCOL *pci_io;
+ void *interface;
+ } pci_io;
+ union {
+ EFI_DEVICE_PATH_PROTOCOL *path;
+ void *interface;
+ } path;
+ UINTN pci_segment, pci_bus, pci_dev, pci_fn;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Allocate PCI device */
+ efipci = zalloc ( sizeof ( *efipci ) );
+ if ( ! efipci )
+ goto err_zalloc;
+ efipci->device = device;
+ efipci->efidrv = efidrv;
+
+ /* See if device is a PCI device */
+ if ( ( efirc = bs->OpenProtocol ( device,
+ &efi_pci_io_protocol_guid,
+ &pci_io.interface,
+ efidrv->driver.DriverBindingHandle,
+ device,
+ EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
+ DBGCP ( efipci, "EFIPCI device %p is not a PCI device\n",
+ device );
+ goto err_open_protocol;
+ }
+ efipci->pci_io = pci_io.pci_io;
+
+ /* Get PCI bus:dev.fn address */
+ if ( ( efirc = pci_io.pci_io->GetLocation ( pci_io.pci_io,
+ &pci_segment,
+ &pci_bus, &pci_dev,
+ &pci_fn ) ) != 0 ) {
+ DBGC ( efipci, "EFIPCI device %p could not get PCI "
+ "location: %s\n", device, efi_strerror ( efirc ) );
+ goto err_get_location;
+ }
+ DBGC2 ( efipci, "EFIPCI device %p is PCI %04lx:%02lx:%02lx.%lx\n",
+ device, ( ( unsigned long ) pci_segment ),
+ ( ( unsigned long ) pci_bus ), ( ( unsigned long ) pci_dev ),
+ ( ( unsigned long ) pci_fn ) );
+
+ /* Populate PCI device */
+ pci_init ( &efipci->pci, PCI_BUSDEVFN ( pci_bus, pci_dev, pci_fn ) );
+ if ( ( rc = pci_read_config ( &efipci->pci ) ) != 0 ) {
+ DBGC ( efipci, "EFIPCI " PCI_FMT " cannot read PCI "
+ "configuration: %s\n",
+ PCI_ARGS ( &efipci->pci ), strerror ( rc ) );
+ goto err_pci_read_config;
+ }
+
+ /* Retrieve device path */
+ if ( ( efirc = bs->OpenProtocol ( device,
+ &efi_device_path_protocol_guid,
+ &path.interface,
+ efidrv->driver.DriverBindingHandle,
+ device,
+ EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
+ DBGC ( efipci, "EFIPCI " PCI_FMT " has no device path\n",
+ PCI_ARGS ( &efipci->pci ) );
+ goto err_no_device_path;
+ }
+ efipci->path = path.path;
+
+ /* Add to list of PCI devices */
+ list_add ( &efipci->list, &efi_pci_devices );
+
+ return efipci;
+
+ bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
+ efidrv->driver.DriverBindingHandle, device );
+ err_no_device_path:
+ err_pci_read_config:
+ err_get_location:
+ bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
+ efidrv->driver.DriverBindingHandle, device );
+ err_open_protocol:
+ free ( efipci );
+ err_zalloc:
+ return NULL;
+}
+
+/**
+ * Enable EFI PCI device
+ *
+ * @v efipci EFI PCI device
+ * @ret efirc EFI status code
+ */
+EFI_STATUS efipci_enable ( struct efi_pci_device *efipci ) {
+ EFI_PCI_IO_PROTOCOL *pci_io = efipci->pci_io;
+ EFI_STATUS efirc;
+
+ /* Enable device */
+ if ( ( efirc = pci_io->Attributes ( pci_io,
+ EfiPciIoAttributeOperationSet,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL ) ) != 0 ) {
+ DBGC ( efipci, "EFIPCI " PCI_FMT " could not be enabled: %s\n",
+ PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) );
+ return efirc;
+ }
+
+ return 0;
+}
+
+/**
+ * Find EFI PCI device by EFI device
+ *
+ * @v device EFI device
+ * @ret efipci EFI PCI device, or NULL
+ */
+struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device ) {
+ struct efi_pci_device *efipci;
+
+ list_for_each_entry ( efipci, &efi_pci_devices, list ) {
+ if ( efipci->device == device )
+ return efipci;
+ }
+ return NULL;
+}
+
+/**
+ * Find EFI PCI device by iPXE device
+ *
+ * @v dev Device
+ * @ret efipci EFI PCI device, or NULL
+ */
+struct efi_pci_device * efipci_find ( struct device *dev ) {
+ struct efi_pci_device *efipci;
+
+ list_for_each_entry ( efipci, &efi_pci_devices, list ) {
+ if ( &efipci->pci.dev == dev )
+ return efipci;
+ }
+ return NULL;
+}
+
+/**
+ * Add EFI device as child of EFI PCI device
+ *
+ * @v efipci EFI PCI device
+ * @v device EFI child device
+ * @ret efirc EFI status code
+ */
+EFI_STATUS efipci_child_add ( struct efi_pci_device *efipci,
+ EFI_HANDLE device ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ struct efi_driver *efidrv = efipci->efidrv;
+ union {
+ EFI_PCI_IO_PROTOCOL *pci_io;
+ void *interface;
+ } pci_io;
+ EFI_STATUS efirc;
+
+ /* Re-open the PCI_IO_PROTOCOL */
+ if ( ( efirc = bs->OpenProtocol ( efipci->device,
+ &efi_pci_io_protocol_guid,
+ &pci_io.interface,
+ efidrv->driver.DriverBindingHandle,
+ device,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ ) ) != 0 ) {
+ DBGC ( efipci, "EFIPCI " PCI_FMT " could not add child: %s\n",
+ PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) );
+ return efirc;
+ }
+
+ return 0;
+}
+
+/**
+ * Remove EFI device as child of PCI device
+ *
+ * @v efipci EFI PCI device
+ * @v device EFI child device
+ * @ret efirc EFI status code
+ */
+void efipci_child_del ( struct efi_pci_device *efipci, EFI_HANDLE device ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ struct efi_driver *efidrv = efipci->efidrv;
+
+ bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid,
+ efidrv->driver.DriverBindingHandle, device );
+}
+
+/**
+ * Destroy EFI PCI device
+ *
+ * @v efidrv EFI driver
+ * @v efipci EFI PCI device
+ */
+void efipci_destroy ( struct efi_driver *efidrv,
+ struct efi_pci_device *efipci ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+
+ list_del ( &efipci->list );
+ bs->CloseProtocol ( efipci->device, &efi_device_path_protocol_guid,
+ efidrv->driver.DriverBindingHandle,
+ efipci->device );
+ bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid,
+ efidrv->driver.DriverBindingHandle,
+ efipci->device );
+ free ( efipci );
+}
+
+/******************************************************************************
+ *
+ * EFI PCI driver
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Check to see if driver supports a device
+ *
+ * @v driver EFI driver
+ * @v device EFI device
+ * @v child Path to child device, if any
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efipci_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
+ EFI_DEVICE_PATH_PROTOCOL *child ) {
+ struct efi_driver *efidrv =
+ container_of ( driver, struct efi_driver, driver );
+ struct efi_pci_device *efipci;
+ EFI_STATUS efirc;
+ int rc;
+
+ DBGCP ( efidrv, "EFIPCI DRIVER_SUPPORTED %p (%p)\n", device, child );
+
+ /* Create temporary corresponding PCI device, if any */
+ efipci = efipci_create ( efidrv, device );
+ if ( ! efipci ) {
+ /* Non-PCI devices are simply unsupported */
+ efirc = EFI_UNSUPPORTED;
+ goto err_not_pci;
+ }
+
+ /* Look for a driver */
+ if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) {
+ DBGCP ( efipci, "EFIPCI " PCI_FMT " has no driver\n",
+ PCI_ARGS ( &efipci->pci ) );
+ efirc = EFI_UNSUPPORTED;
+ goto err_no_driver;
+ }
+
+ DBGC ( efipci, "EFIPCI " PCI_FMT " is supported by driver \"%s\"\n",
+ PCI_ARGS ( &efipci->pci ), efipci->pci.id->name );
+
+ /* Destroy temporary PCI device */
+ efipci_destroy ( efidrv, efipci );
+
+ return 0;
+
+ err_no_driver:
+ efipci_destroy ( efidrv, efipci );
+ err_not_pci:
+ return efirc;
+}
+
+/**
+ * Attach driver to device
+ *
+ * @v driver EFI driver
+ * @v device EFI device
+ * @v child Path to child device, if any
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
+ EFI_DEVICE_PATH_PROTOCOL *child ) {
+ struct efi_driver *efidrv =
+ container_of ( driver, struct efi_driver, driver );
+ struct efi_pci_device *efipci;
+ EFI_STATUS efirc;
+ int rc;
+
+ DBGC ( efidrv, "EFIPCI DRIVER_START %p (%p)\n", device, child );
+
+ /* Create corresponding PCI device */
+ efipci = efipci_create ( efidrv, device );
+ if ( ! efipci ) {
+ efirc = EFI_OUT_OF_RESOURCES;
+ goto err_create;
+ }
+
+ /* Find driver */
+ if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) {
+ DBGC ( efipci, "EFIPCI " PCI_FMT " has no driver\n",
+ PCI_ARGS ( &efipci->pci ) );
+ efirc = RC_TO_EFIRC ( rc );
+ goto err_find_driver;
+ }
+
+ /* Enable PCI device */
+ if ( ( efirc = efipci_enable ( efipci ) ) != 0 )
+ goto err_enable;
+
+ /* Probe driver */
+ if ( ( rc = pci_probe ( &efipci->pci ) ) != 0 ) {
+ DBGC ( efipci, "EFIPCI " PCI_FMT " could not probe driver "
+ "\"%s\": %s\n", PCI_ARGS ( &efipci->pci ),
+ efipci->pci.id->name, strerror ( rc ) );
+ efirc = RC_TO_EFIRC ( rc );
+ goto err_probe;
+ }
+
+ return 0;
+
+ pci_remove ( &efipci->pci );
+ err_probe:
+ err_enable:
+ err_find_driver:
+ efipci_destroy ( efidrv, efipci );
+ err_create:
+ return efirc;
+}
+
+/**
+ * Detach driver from device
+ *
+ * @v driver EFI driver
+ * @v device EFI device
+ * @v pci PCI device
+ * @v num_children Number of child devices
+ * @v children List of child devices
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efipci_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
+ UINTN num_children, EFI_HANDLE *children ) {
+ struct efi_driver *efidrv =
+ container_of ( driver, struct efi_driver, driver );
+ struct efi_pci_device *efipci;
+
+ DBGC ( efidrv, "EFIPCI DRIVER_STOP %p (%ld %p)\n",
+ device, ( ( unsigned long ) num_children ), children );
+
+ /* Find PCI device */
+ efipci = efipci_find_efi ( device );
+ if ( ! efipci ) {
+ DBGC ( efidrv, "EFIPCI device %p not started!\n", device );
+ return EFI_INVALID_PARAMETER;
+ }
+
+ /* Remove device */
+ pci_remove ( &efipci->pci );
+
+ /* Delete EFI PCI device */
+ efipci_destroy ( efidrv, efipci );
+
+ return 0;
+}
+
+/** EFI PCI driver */
+static struct efi_driver efipci_driver =
+ EFI_DRIVER_INIT ( "PCI", efipci_supported, efipci_start, efipci_stop );
+
+/**
+ * Install EFI PCI driver
+ *
+ */
+static void efipci_driver_startup ( void ) {
+ struct efi_driver *efidrv = &efipci_driver;
+ EFI_STATUS efirc;
+
+ /* Install driver */
+ if ( ( efirc = efi_driver_install ( efidrv ) ) != 0 ) {
+ DBGC ( efidrv, "EFIPCI could not install driver: %s\n",
+ efi_strerror ( efirc ) );
+ return;
+ }
+
+ DBGC ( efidrv, "EFIPCI driver installed\n" );
+}
+
+/**
+ * Shut down EFI PCI driver
+ *
+ * @v booting System is shutting down for OS boot
+ */
+static void efipci_driver_shutdown ( int booting __unused ) {
+ struct efi_driver *efidrv = &efipci_driver;
+ struct efi_pci_device *efipci;
+ struct efi_pci_device *tmp;
+
+ /* Shut down any remaining devices */
+ list_for_each_entry_safe ( efipci, tmp, &efi_pci_devices, list ) {
+ DBGC ( efipci, "EFIPCI " PCI_FMT " still active at shutdown; "
+ "forcing close\n", PCI_ARGS ( &efipci->pci ) );
+ pci_remove ( &efipci->pci );
+ efipci_destroy ( efidrv, efipci );
+ }
+}
+
+/** EFI PCI startup function */
+struct startup_fn startup_pci __startup_fn ( STARTUP_NORMAL ) = {
+ .startup = efipci_driver_startup,
+ .shutdown = efipci_driver_shutdown,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_smbios.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_smbios.c
new file mode 100644
index 00000000..4b58d846
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_smbios.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <ipxe/smbios.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/Guid/SmBios.h>
+
+/** @file
+ *
+ * iPXE SMBIOS API for EFI
+ *
+ */
+
+/** SMBIOS configuration table */
+static struct smbios_entry *smbios_entry;
+EFI_USE_TABLE ( SMBIOS_TABLE, &smbios_entry, 0 );
+
+/**
+ * Find SMBIOS
+ *
+ * @v smbios SMBIOS entry point descriptor structure to fill in
+ * @ret rc Return status code
+ */
+static int efi_find_smbios ( struct smbios *smbios ) {
+
+ if ( ! smbios_entry ) {
+ DBG ( "No SMBIOS table provided\n" );
+ return -ENODEV;
+ }
+
+ if ( smbios_entry->signature != SMBIOS_SIGNATURE ) {
+ DBG ( "Invalid SMBIOS signature\n" );
+ return -ENODEV;
+ }
+
+ smbios->address = phys_to_user ( smbios_entry->smbios_address );
+ smbios->len = smbios_entry->smbios_len;
+ smbios->count = smbios_entry->smbios_count;
+ DBG ( "Found SMBIOS v%d.%d entry point at %p (%x+%zx)\n",
+ smbios_entry->major, smbios_entry->minor, smbios_entry,
+ smbios_entry->smbios_address, smbios->len );
+
+ return 0;
+}
+
+PROVIDE_SMBIOS ( efi, find_smbios, efi_find_smbios );
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_snp.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_snp.c
new file mode 100644
index 00000000..4df221c5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_snp.c
@@ -0,0 +1,1342 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/in.h>
+#include <ipxe/pci.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_pci.h>
+#include <ipxe/efi/efi_driver.h>
+#include <ipxe/efi/efi_strings.h>
+#include <ipxe/efi/efi_hii.h>
+#include <ipxe/efi/Protocol/SimpleNetwork.h>
+#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
+#include <ipxe/efi/Protocol/DevicePath.h>
+#include <ipxe/efi/Protocol/HiiConfigAccess.h>
+#include <ipxe/efi/Protocol/HiiDatabase.h>
+#include <config/general.h>
+
+/** @file
+ *
+ * iPXE EFI SNP interface
+ *
+ */
+
+/** An SNP device */
+struct efi_snp_device {
+ /** List of SNP devices */
+ struct list_head list;
+ /** The underlying iPXE network device */
+ struct net_device *netdev;
+ /** The underlying EFI PCI device */
+ struct efi_pci_device *efipci;
+ /** EFI device handle */
+ EFI_HANDLE handle;
+ /** The SNP structure itself */
+ EFI_SIMPLE_NETWORK_PROTOCOL snp;
+ /** The SNP "mode" (parameters) */
+ EFI_SIMPLE_NETWORK_MODE mode;
+ /** Outstanding TX packet count (via "interrupt status")
+ *
+ * Used in order to generate TX completions.
+ */
+ unsigned int tx_count_interrupts;
+ /** Outstanding TX packet count (via "recycled tx buffers")
+ *
+ * Used in order to generate TX completions.
+ */
+ unsigned int tx_count_txbufs;
+ /** Outstanding RX packet count (via "interrupt status") */
+ unsigned int rx_count_interrupts;
+ /** Outstanding RX packet count (via WaitForPacket event) */
+ unsigned int rx_count_events;
+ /** The network interface identifier */
+ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii;
+ /** HII configuration access protocol */
+ EFI_HII_CONFIG_ACCESS_PROTOCOL hii;
+ /** HII package list */
+ EFI_HII_PACKAGE_LIST_HEADER *package_list;
+ /** HII handle */
+ EFI_HII_HANDLE hii_handle;
+ /** Device name */
+ wchar_t name[ sizeof ( ( ( struct net_device * ) NULL )->name ) ];
+ /** The device path
+ *
+ * This field is variable in size and must appear at the end
+ * of the structure.
+ */
+ EFI_DEVICE_PATH_PROTOCOL path;
+};
+
+/** EFI simple network protocol GUID */
+static EFI_GUID efi_simple_network_protocol_guid
+ = EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
+
+/** EFI device path protocol GUID */
+static EFI_GUID efi_device_path_protocol_guid
+ = EFI_DEVICE_PATH_PROTOCOL_GUID;
+
+/** EFI network interface identifier GUID */
+static EFI_GUID efi_nii_protocol_guid
+ = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID;
+
+/** EFI network interface identifier GUID (extra special version) */
+static EFI_GUID efi_nii31_protocol_guid = {
+ /* At some point, it seems that someone decided to change the
+ * GUID. Current EFI builds ignore the older GUID, older EFI
+ * builds ignore the newer GUID, so we have to expose both.
+ */
+ 0x1ACED566, 0x76ED, 0x4218,
+ { 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 }
+};
+
+/** List of SNP devices */
+static LIST_HEAD ( efi_snp_devices );
+
+/**
+ * Set EFI SNP mode based on iPXE net device parameters
+ *
+ * @v snp SNP interface
+ */
+static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) {
+ struct net_device *netdev = snpdev->netdev;
+ EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+ unsigned int ll_addr_len = ll_protocol->ll_addr_len;
+
+ mode->HwAddressSize = ll_addr_len;
+ mode->MediaHeaderSize = ll_protocol->ll_header_len;
+ mode->MaxPacketSize = netdev->max_pkt_len;
+ mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST );
+ assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) );
+ memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len );
+ memcpy ( &mode->BroadcastAddress, netdev->ll_broadcast, ll_addr_len );
+ ll_protocol->init_addr ( netdev->hw_addr, &mode->PermanentAddress );
+ mode->IfType = ntohs ( ll_protocol->ll_proto );
+ mode->MacAddressChangeable = TRUE;
+ mode->MediaPresentSupported = TRUE;
+ mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
+}
+
+/**
+ * Poll net device and count received packets
+ *
+ * @v snpdev SNP device
+ */
+static void efi_snp_poll ( struct efi_snp_device *snpdev ) {
+ struct io_buffer *iobuf;
+ unsigned int before = 0;
+ unsigned int after = 0;
+ unsigned int arrived;
+
+ /* We have to report packet arrivals, and this is the easiest
+ * way to fake it.
+ */
+ list_for_each_entry ( iobuf, &snpdev->netdev->rx_queue, list )
+ before++;
+ netdev_poll ( snpdev->netdev );
+ list_for_each_entry ( iobuf, &snpdev->netdev->rx_queue, list )
+ after++;
+ arrived = ( after - before );
+
+ snpdev->rx_count_interrupts += arrived;
+ snpdev->rx_count_events += arrived;
+}
+
+/**
+ * Change SNP state from "stopped" to "started"
+ *
+ * @v snp SNP interface
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
+ struct efi_snp_device *snpdev =
+ container_of ( snp, struct efi_snp_device, snp );
+
+ DBGC2 ( snpdev, "SNPDEV %p START\n", snpdev );
+
+ snpdev->mode.State = EfiSimpleNetworkStarted;
+ return 0;
+}
+
+/**
+ * Change SNP state from "started" to "stopped"
+ *
+ * @v snp SNP interface
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
+ struct efi_snp_device *snpdev =
+ container_of ( snp, struct efi_snp_device, snp );
+
+ DBGC2 ( snpdev, "SNPDEV %p STOP\n", snpdev );
+
+ snpdev->mode.State = EfiSimpleNetworkStopped;
+ return 0;
+}
+
+/**
+ * Open the network device
+ *
+ * @v snp SNP interface
+ * @v extra_rx_bufsize Extra RX buffer size, in bytes
+ * @v extra_tx_bufsize Extra TX buffer size, in bytes
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
+ UINTN extra_rx_bufsize, UINTN extra_tx_bufsize ) {
+ struct efi_snp_device *snpdev =
+ container_of ( snp, struct efi_snp_device, snp );
+ int rc;
+
+ DBGC2 ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n",
+ snpdev, ( ( unsigned long ) extra_rx_bufsize ),
+ ( ( unsigned long ) extra_tx_bufsize ) );
+
+ if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
+ DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n",
+ snpdev, snpdev->netdev->name, strerror ( rc ) );
+ return RC_TO_EFIRC ( rc );
+ }
+
+ snpdev->mode.State = EfiSimpleNetworkInitialized;
+ return 0;
+}
+
+/**
+ * Reset the network device
+ *
+ * @v snp SNP interface
+ * @v ext_verify Extended verification required
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
+ struct efi_snp_device *snpdev =
+ container_of ( snp, struct efi_snp_device, snp );
+ int rc;
+
+ DBGC2 ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
+ snpdev, ( ext_verify ? "with" : "without" ) );
+
+ netdev_close ( snpdev->netdev );
+ snpdev->mode.State = EfiSimpleNetworkStarted;
+
+ if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
+ DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n",
+ snpdev, snpdev->netdev->name, strerror ( rc ) );
+ return RC_TO_EFIRC ( rc );
+ }
+
+ snpdev->mode.State = EfiSimpleNetworkInitialized;
+ return 0;
+}
+
+/**
+ * Shut down the network device
+ *
+ * @v snp SNP interface
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
+ struct efi_snp_device *snpdev =
+ container_of ( snp, struct efi_snp_device, snp );
+
+ DBGC2 ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
+
+ netdev_close ( snpdev->netdev );
+ snpdev->mode.State = EfiSimpleNetworkStarted;
+ return 0;
+}
+
+/**
+ * Manage receive filters
+ *
+ * @v snp SNP interface
+ * @v enable Receive filters to enable
+ * @v disable Receive filters to disable
+ * @v mcast_reset Reset multicast filters
+ * @v mcast_count Number of multicast filters
+ * @v mcast Multicast filters
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable,
+ UINT32 disable, BOOLEAN mcast_reset,
+ UINTN mcast_count, EFI_MAC_ADDRESS *mcast ) {
+ struct efi_snp_device *snpdev =
+ container_of ( snp, struct efi_snp_device, snp );
+ unsigned int i;
+
+ DBGC2 ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n",
+ snpdev, enable, disable, ( mcast_reset ? " reset" : "" ),
+ ( ( unsigned long ) mcast_count ) );
+ for ( i = 0 ; i < mcast_count ; i++ ) {
+ DBGC2_HDA ( snpdev, i, &mcast[i],
+ snpdev->netdev->ll_protocol->ll_addr_len );
+ }
+
+ /* Lie through our teeth, otherwise MNP refuses to accept us */
+ return 0;
+}
+
+/**
+ * Set station address
+ *
+ * @v snp SNP interface
+ * @v reset Reset to permanent address
+ * @v new New station address
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_station_address ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
+ EFI_MAC_ADDRESS *new ) {
+ struct efi_snp_device *snpdev =
+ container_of ( snp, struct efi_snp_device, snp );
+ struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
+
+ DBGC2 ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev,
+ ( reset ? "reset" : ll_protocol->ntoa ( new ) ) );
+
+ /* Set the MAC address */
+ if ( reset )
+ new = &snpdev->mode.PermanentAddress;
+ memcpy ( snpdev->netdev->ll_addr, new, ll_protocol->ll_addr_len );
+
+ /* MAC address changes take effect only on netdev_open() */
+ if ( netdev_is_open ( snpdev->netdev ) ) {
+ DBGC ( snpdev, "SNPDEV %p MAC address changed while net "
+ "devive open\n", snpdev );
+ }
+
+ return 0;
+}
+
+/**
+ * Get (or reset) statistics
+ *
+ * @v snp SNP interface
+ * @v reset Reset statistics
+ * @v stats_len Size of statistics table
+ * @v stats Statistics table
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
+ UINTN *stats_len, EFI_NETWORK_STATISTICS *stats ) {
+ struct efi_snp_device *snpdev =
+ container_of ( snp, struct efi_snp_device, snp );
+ EFI_NETWORK_STATISTICS stats_buf;
+
+ DBGC2 ( snpdev, "SNPDEV %p STATISTICS%s", snpdev,
+ ( reset ? " reset" : "" ) );
+
+ /* Gather statistics */
+ memset ( &stats_buf, 0, sizeof ( stats_buf ) );
+ stats_buf.TxGoodFrames = snpdev->netdev->tx_stats.good;
+ stats_buf.TxDroppedFrames = snpdev->netdev->tx_stats.bad;
+ stats_buf.TxTotalFrames = ( snpdev->netdev->tx_stats.good +
+ snpdev->netdev->tx_stats.bad );
+ stats_buf.RxGoodFrames = snpdev->netdev->rx_stats.good;
+ stats_buf.RxDroppedFrames = snpdev->netdev->rx_stats.bad;
+ stats_buf.RxTotalFrames = ( snpdev->netdev->rx_stats.good +
+ snpdev->netdev->rx_stats.bad );
+ if ( *stats_len > sizeof ( stats_buf ) )
+ *stats_len = sizeof ( stats_buf );
+ if ( stats )
+ memcpy ( stats, &stats_buf, *stats_len );
+
+ /* Reset statistics if requested to do so */
+ if ( reset ) {
+ memset ( &snpdev->netdev->tx_stats, 0,
+ sizeof ( snpdev->netdev->tx_stats ) );
+ memset ( &snpdev->netdev->rx_stats, 0,
+ sizeof ( snpdev->netdev->rx_stats ) );
+ }
+
+ return 0;
+}
+
+/**
+ * Convert multicast IP address to MAC address
+ *
+ * @v snp SNP interface
+ * @v ipv6 Address is IPv6
+ * @v ip IP address
+ * @v mac MAC address
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6,
+ EFI_IP_ADDRESS *ip, EFI_MAC_ADDRESS *mac ) {
+ struct efi_snp_device *snpdev =
+ container_of ( snp, struct efi_snp_device, snp );
+ struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
+ const char *ip_str;
+ int rc;
+
+ ip_str = ( ipv6 ? "(IPv6)" /* FIXME when we have inet6_ntoa() */ :
+ inet_ntoa ( *( ( struct in_addr * ) ip ) ) );
+ DBGC2 ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );
+
+ /* Try to hash the address */
+ if ( ( rc = ll_protocol->mc_hash ( ( ipv6 ? AF_INET6 : AF_INET ),
+ ip, mac ) ) != 0 ) {
+ DBGC ( snpdev, "SNPDEV %p could not hash %s: %s\n",
+ snpdev, ip_str, strerror ( rc ) );
+ return RC_TO_EFIRC ( rc );
+ }
+
+ return 0;
+}
+
+/**
+ * Read or write non-volatile storage
+ *
+ * @v snp SNP interface
+ * @v read Operation is a read
+ * @v offset Starting offset within NVRAM
+ * @v len Length of data buffer
+ * @v data Data buffer
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read,
+ UINTN offset, UINTN len, VOID *data ) {
+ struct efi_snp_device *snpdev =
+ container_of ( snp, struct efi_snp_device, snp );
+
+ DBGC2 ( snpdev, "SNPDEV %p NVDATA %s %lx+%lx\n", snpdev,
+ ( read ? "read" : "write" ), ( ( unsigned long ) offset ),
+ ( ( unsigned long ) len ) );
+ if ( ! read )
+ DBGC2_HDA ( snpdev, offset, data, len );
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * Read interrupt status and TX recycled buffer status
+ *
+ * @v snp SNP interface
+ * @v interrupts Interrupt status, or NULL
+ * @v txbufs Recycled transmit buffer address, or NULL
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
+ UINT32 *interrupts, VOID **txbufs ) {
+ struct efi_snp_device *snpdev =
+ container_of ( snp, struct efi_snp_device, snp );
+
+ DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev );
+
+ /* Poll the network device */
+ efi_snp_poll ( snpdev );
+
+ /* Interrupt status. In practice, this seems to be used only
+ * to detect TX completions.
+ */
+ if ( interrupts ) {
+ *interrupts = 0;
+ /* Report TX completions once queue is empty; this
+ * avoids having to add hooks in the net device layer.
+ */
+ if ( snpdev->tx_count_interrupts &&
+ list_empty ( &snpdev->netdev->tx_queue ) ) {
+ *interrupts |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
+ snpdev->tx_count_interrupts--;
+ }
+ /* Report RX */
+ if ( snpdev->rx_count_interrupts ) {
+ *interrupts |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
+ snpdev->rx_count_interrupts--;
+ }
+ DBGC2 ( snpdev, " INTS:%02x", *interrupts );
+ }
+
+ /* TX completions. It would be possible to design a more
+ * idiotic scheme for this, but it would be a challenge.
+ * According to the UEFI header file, txbufs will be filled in
+ * with a list of "recycled transmit buffers" (i.e. completed
+ * TX buffers). Observant readers may care to note that
+ * *txbufs is a void pointer. Precisely how a list of
+ * completed transmit buffers is meant to be represented as an
+ * array of voids is left as an exercise for the reader.
+ *
+ * The only users of this interface (MnpDxe/MnpIo.c and
+ * PxeBcDxe/Bc.c within the EFI dev kit) both just poll until
+ * seeing a non-NULL result return in txbufs. This is valid
+ * provided that they do not ever attempt to transmit more
+ * than one packet concurrently (and that TX never times out).
+ */
+ if ( txbufs ) {
+ if ( snpdev->tx_count_txbufs &&
+ list_empty ( &snpdev->netdev->tx_queue ) ) {
+ *txbufs = "Which idiot designed this API?";
+ snpdev->tx_count_txbufs--;
+ } else {
+ *txbufs = NULL;
+ }
+ DBGC2 ( snpdev, " TX:%s", ( *txbufs ? "some" : "none" ) );
+ }
+
+ DBGC2 ( snpdev, "\n" );
+ return 0;
+}
+
+/**
+ * Start packet transmission
+ *
+ * @v snp SNP interface
+ * @v ll_header_len Link-layer header length, if to be filled in
+ * @v len Length of data buffer
+ * @v data Data buffer
+ * @v ll_src Link-layer source address, if specified
+ * @v ll_dest Link-layer destination address, if specified
+ * @v net_proto Network-layer protocol (in host order)
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
+ UINTN ll_header_len, UINTN len, VOID *data,
+ EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
+ UINT16 *net_proto ) {
+ struct efi_snp_device *snpdev =
+ container_of ( snp, struct efi_snp_device, snp );
+ struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
+ struct io_buffer *iobuf;
+ size_t ll_headroom;
+ int rc;
+ EFI_STATUS efirc;
+
+ DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data,
+ ( ( unsigned long ) len ) );
+ if ( ll_header_len ) {
+ if ( ll_src ) {
+ DBGC2 ( snpdev, " src %s",
+ ll_protocol->ntoa ( ll_src ) );
+ }
+ if ( ll_dest ) {
+ DBGC2 ( snpdev, " dest %s",
+ ll_protocol->ntoa ( ll_dest ) );
+ }
+ if ( net_proto ) {
+ DBGC2 ( snpdev, " proto %04x", *net_proto );
+ }
+ }
+ DBGC2 ( snpdev, "\n" );
+
+ /* Sanity checks */
+ if ( ll_header_len ) {
+ if ( ll_header_len != ll_protocol->ll_header_len ) {
+ DBGC ( snpdev, "SNPDEV %p TX invalid header length "
+ "%ld\n", snpdev,
+ ( ( unsigned long ) ll_header_len ) );
+ efirc = EFI_INVALID_PARAMETER;
+ goto err_sanity;
+ }
+ if ( len < ll_header_len ) {
+ DBGC ( snpdev, "SNPDEV %p invalid packet length %ld\n",
+ snpdev, ( ( unsigned long ) len ) );
+ efirc = EFI_BUFFER_TOO_SMALL;
+ goto err_sanity;
+ }
+ if ( ! ll_dest ) {
+ DBGC ( snpdev, "SNPDEV %p TX missing destination "
+ "address\n", snpdev );
+ efirc = EFI_INVALID_PARAMETER;
+ goto err_sanity;
+ }
+ if ( ! net_proto ) {
+ DBGC ( snpdev, "SNPDEV %p TX missing network "
+ "protocol\n", snpdev );
+ efirc = EFI_INVALID_PARAMETER;
+ goto err_sanity;
+ }
+ if ( ! ll_src )
+ ll_src = &snpdev->mode.CurrentAddress;
+ }
+
+ /* Allocate buffer */
+ ll_headroom = ( MAX_LL_HEADER_LEN - ll_header_len );
+ iobuf = alloc_iob ( ll_headroom + len );
+ if ( ! iobuf ) {
+ DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte "
+ "buffer\n", snpdev, ( ( unsigned long ) len ) );
+ efirc = EFI_DEVICE_ERROR;
+ goto err_alloc_iob;
+ }
+ iob_reserve ( iobuf, ll_headroom );
+ memcpy ( iob_put ( iobuf, len ), data, len );
+
+ /* Create link-layer header, if specified */
+ if ( ll_header_len ) {
+ iob_pull ( iobuf, ll_header_len );
+ if ( ( rc = ll_protocol->push ( snpdev->netdev,
+ iobuf, ll_dest, ll_src,
+ htons ( *net_proto ) )) != 0 ){
+ DBGC ( snpdev, "SNPDEV %p TX could not construct "
+ "header: %s\n", snpdev, strerror ( rc ) );
+ efirc = RC_TO_EFIRC ( rc );
+ goto err_ll_push;
+ }
+ }
+
+ /* Transmit packet */
+ if ( ( rc = netdev_tx ( snpdev->netdev, iob_disown ( iobuf ) ) ) != 0){
+ DBGC ( snpdev, "SNPDEV %p TX could not transmit: %s\n",
+ snpdev, strerror ( rc ) );
+ efirc = RC_TO_EFIRC ( rc );
+ goto err_tx;
+ }
+
+ /* Record transmission as outstanding */
+ snpdev->tx_count_interrupts++;
+ snpdev->tx_count_txbufs++;
+
+ return 0;
+
+ err_tx:
+ err_ll_push:
+ free_iob ( iobuf );
+ err_alloc_iob:
+ err_sanity:
+ return efirc;
+}
+
+/**
+ * Receive packet
+ *
+ * @v snp SNP interface
+ * @v ll_header_len Link-layer header length, if to be filled in
+ * @v len Length of data buffer
+ * @v data Data buffer
+ * @v ll_src Link-layer source address, if specified
+ * @v ll_dest Link-layer destination address, if specified
+ * @v net_proto Network-layer protocol (in host order)
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
+ UINTN *ll_header_len, UINTN *len, VOID *data,
+ EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
+ UINT16 *net_proto ) {
+ struct efi_snp_device *snpdev =
+ container_of ( snp, struct efi_snp_device, snp );
+ struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
+ struct io_buffer *iobuf;
+ const void *iob_ll_dest;
+ const void *iob_ll_src;
+ uint16_t iob_net_proto;
+ unsigned int iob_flags;
+ int rc;
+ EFI_STATUS efirc;
+
+ DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data,
+ ( ( unsigned long ) *len ) );
+
+ /* Poll the network device */
+ efi_snp_poll ( snpdev );
+
+ /* Dequeue a packet, if one is available */
+ iobuf = netdev_rx_dequeue ( snpdev->netdev );
+ if ( ! iobuf ) {
+ DBGC2 ( snpdev, "\n" );
+ efirc = EFI_NOT_READY;
+ goto out_no_packet;
+ }
+ DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) );
+
+ /* Return packet to caller */
+ memcpy ( data, iobuf->data, iob_len ( iobuf ) );
+ *len = iob_len ( iobuf );
+
+ /* Attempt to decode link-layer header */
+ if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest,
+ &iob_ll_src, &iob_net_proto,
+ &iob_flags ) ) != 0 ) {
+ DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n",
+ snpdev, strerror ( rc ) );
+ efirc = RC_TO_EFIRC ( rc );
+ goto out_bad_ll_header;
+ }
+
+ /* Return link-layer header parameters to caller, if required */
+ if ( ll_header_len )
+ *ll_header_len = ll_protocol->ll_header_len;
+ if ( ll_src )
+ memcpy ( ll_src, iob_ll_src, ll_protocol->ll_addr_len );
+ if ( ll_dest )
+ memcpy ( ll_dest, iob_ll_dest, ll_protocol->ll_addr_len );
+ if ( net_proto )
+ *net_proto = ntohs ( iob_net_proto );
+
+ efirc = 0;
+
+ out_bad_ll_header:
+ free_iob ( iobuf );
+out_no_packet:
+ return efirc;
+}
+
+/**
+ * Poll event
+ *
+ * @v event Event
+ * @v context Event context
+ */
+static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event,
+ VOID *context ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ struct efi_snp_device *snpdev = context;
+
+ DBGCP ( snpdev, "SNPDEV %p WAIT_FOR_PACKET\n", snpdev );
+
+ /* Do nothing unless the net device is open */
+ if ( ! netdev_is_open ( snpdev->netdev ) )
+ return;
+
+ /* Poll the network device */
+ efi_snp_poll ( snpdev );
+
+ /* Fire event if packets have been received */
+ if ( snpdev->rx_count_events != 0 ) {
+ DBGC2 ( snpdev, "SNPDEV %p firing WaitForPacket event\n",
+ snpdev );
+ bs->SignalEvent ( event );
+ snpdev->rx_count_events--;
+ }
+}
+
+/** SNP interface */
+static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = {
+ .Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION,
+ .Start = efi_snp_start,
+ .Stop = efi_snp_stop,
+ .Initialize = efi_snp_initialize,
+ .Reset = efi_snp_reset,
+ .Shutdown = efi_snp_shutdown,
+ .ReceiveFilters = efi_snp_receive_filters,
+ .StationAddress = efi_snp_station_address,
+ .Statistics = efi_snp_statistics,
+ .MCastIpToMac = efi_snp_mcast_ip_to_mac,
+ .NvData = efi_snp_nvdata,
+ .GetStatus = efi_snp_get_status,
+ .Transmit = efi_snp_transmit,
+ .Receive = efi_snp_receive,
+};
+
+/******************************************************************************
+ *
+ * Human Interface Infrastructure
+ *
+ ******************************************************************************
+ */
+
+/** EFI configuration access protocol GUID */
+static EFI_GUID efi_hii_config_access_protocol_guid
+ = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID;
+
+/** EFI HII database protocol */
+static EFI_HII_DATABASE_PROTOCOL *efihii;
+EFI_REQUIRE_PROTOCOL ( EFI_HII_DATABASE_PROTOCOL, &efihii );
+
+/** Local base GUID used for our EFI SNP formset */
+#define EFI_SNP_FORMSET_GUID_BASE \
+ { 0xc4f84019, 0x6dfd, 0x4a27, \
+ { 0x9b, 0x94, 0xb7, 0x2e, 0x1f, 0xbc, 0xad, 0xca } }
+
+/** Form identifiers used for our EFI SNP HII */
+enum efi_snp_hii_form_id {
+ EFI_SNP_FORM = 0x0001, /**< The only form */
+};
+
+/** String identifiers used for our EFI SNP HII */
+enum efi_snp_hii_string_id {
+ /* Language name */
+ EFI_SNP_LANGUAGE_NAME = 0x0001,
+ /* Formset */
+ EFI_SNP_FORMSET_TITLE, EFI_SNP_FORMSET_HELP,
+ /* Product name */
+ EFI_SNP_PRODUCT_PROMPT, EFI_SNP_PRODUCT_HELP, EFI_SNP_PRODUCT_TEXT,
+ /* Version */
+ EFI_SNP_VERSION_PROMPT, EFI_SNP_VERSION_HELP, EFI_SNP_VERSION_TEXT,
+ /* Driver */
+ EFI_SNP_DRIVER_PROMPT, EFI_SNP_DRIVER_HELP, EFI_SNP_DRIVER_TEXT,
+ /* Device */
+ EFI_SNP_DEVICE_PROMPT, EFI_SNP_DEVICE_HELP, EFI_SNP_DEVICE_TEXT,
+ /* End of list */
+ EFI_SNP_MAX_STRING_ID
+};
+
+/** EFI SNP formset */
+struct efi_snp_formset {
+ EFI_HII_PACKAGE_HEADER Header;
+ EFI_IFR_FORM_SET_TYPE(1) FormSet;
+ EFI_IFR_GUID_CLASS Class;
+ EFI_IFR_GUID_SUBCLASS SubClass;
+ EFI_IFR_FORM Form;
+ EFI_IFR_TEXT ProductText;
+ EFI_IFR_TEXT VersionText;
+ EFI_IFR_TEXT DriverText;
+ EFI_IFR_TEXT DeviceText;
+ EFI_IFR_END EndForm;
+ EFI_IFR_END EndFormSet;
+} __attribute__ (( packed )) efi_snp_formset = {
+ .Header = {
+ .Length = sizeof ( efi_snp_formset ),
+ .Type = EFI_HII_PACKAGE_FORMS,
+ },
+ .FormSet = EFI_IFR_FORM_SET ( EFI_SNP_FORMSET_GUID_BASE,
+ EFI_SNP_FORMSET_TITLE,
+ EFI_SNP_FORMSET_HELP,
+ typeof ( efi_snp_formset.FormSet ),
+ EFI_HII_PLATFORM_SETUP_FORMSET_GUID ),
+ .Class = EFI_IFR_GUID_CLASS ( EFI_NETWORK_DEVICE_CLASS ),
+ .SubClass = EFI_IFR_GUID_SUBCLASS ( 0x03 ),
+ .Form = EFI_IFR_FORM ( EFI_SNP_FORM, EFI_SNP_FORMSET_TITLE ),
+ .ProductText = EFI_IFR_TEXT ( EFI_SNP_PRODUCT_PROMPT,
+ EFI_SNP_PRODUCT_HELP,
+ EFI_SNP_PRODUCT_TEXT ),
+ .VersionText = EFI_IFR_TEXT ( EFI_SNP_VERSION_PROMPT,
+ EFI_SNP_VERSION_HELP,
+ EFI_SNP_VERSION_TEXT ),
+ .DriverText = EFI_IFR_TEXT ( EFI_SNP_DRIVER_PROMPT,
+ EFI_SNP_DRIVER_HELP,
+ EFI_SNP_DRIVER_TEXT ),
+ .DeviceText = EFI_IFR_TEXT ( EFI_SNP_DEVICE_PROMPT,
+ EFI_SNP_DEVICE_HELP,
+ EFI_SNP_DEVICE_TEXT ),
+ .EndForm = EFI_IFR_END(),
+ .EndFormSet = EFI_IFR_END(),
+};
+
+/**
+ * Generate EFI SNP string
+ *
+ * @v wbuf Buffer
+ * @v swlen Size of buffer (in wide characters)
+ * @v snpdev SNP device
+ * @ret wlen Length of string (in wide characters)
+ */
+static int efi_snp_string ( wchar_t *wbuf, ssize_t swlen,
+ enum efi_snp_hii_string_id id,
+ struct efi_snp_device *snpdev ) {
+ struct net_device *netdev = snpdev->netdev;
+ struct device *dev = netdev->dev;
+
+ switch ( id ) {
+ case EFI_SNP_LANGUAGE_NAME:
+ return efi_ssnprintf ( wbuf, swlen, "English" );
+ case EFI_SNP_FORMSET_TITLE:
+ return efi_ssnprintf ( wbuf, swlen, "%s (%s)",
+ ( PRODUCT_NAME[0] ?
+ PRODUCT_NAME : PRODUCT_SHORT_NAME ),
+ netdev_addr ( netdev ) );
+ case EFI_SNP_FORMSET_HELP:
+ return efi_ssnprintf ( wbuf, swlen,
+ "Configure " PRODUCT_SHORT_NAME );
+ case EFI_SNP_PRODUCT_PROMPT:
+ return efi_ssnprintf ( wbuf, swlen, "Name" );
+ case EFI_SNP_PRODUCT_HELP:
+ return efi_ssnprintf ( wbuf, swlen, "Firmware product name" );
+ case EFI_SNP_PRODUCT_TEXT:
+ return efi_ssnprintf ( wbuf, swlen, "%s",
+ ( PRODUCT_NAME[0] ?
+ PRODUCT_NAME : PRODUCT_SHORT_NAME ) );
+ case EFI_SNP_VERSION_PROMPT:
+ return efi_ssnprintf ( wbuf, swlen, "Version" );
+ case EFI_SNP_VERSION_HELP:
+ return efi_ssnprintf ( wbuf, swlen, "Firmware version" );
+ case EFI_SNP_VERSION_TEXT:
+ return efi_ssnprintf ( wbuf, swlen, VERSION );
+ case EFI_SNP_DRIVER_PROMPT:
+ return efi_ssnprintf ( wbuf, swlen, "Driver" );
+ case EFI_SNP_DRIVER_HELP:
+ return efi_ssnprintf ( wbuf, swlen, "Firmware driver" );
+ case EFI_SNP_DRIVER_TEXT:
+ return efi_ssnprintf ( wbuf, swlen, "%s", dev->driver_name );
+ case EFI_SNP_DEVICE_PROMPT:
+ return efi_ssnprintf ( wbuf, swlen, "Device" );
+ case EFI_SNP_DEVICE_HELP:
+ return efi_ssnprintf ( wbuf, swlen, "Hardware device" );
+ case EFI_SNP_DEVICE_TEXT:
+ return efi_ssnprintf ( wbuf, swlen, "%s", dev->name );
+ default:
+ assert ( 0 );
+ return 0;
+ }
+}
+
+/**
+ * Generate EFI SNP string package
+ *
+ * @v strings String package header buffer
+ * @v max_len Buffer length
+ * @v snpdev SNP device
+ * @ret len Length of string package
+ */
+static int efi_snp_strings ( EFI_HII_STRING_PACKAGE_HDR *strings,
+ size_t max_len, struct efi_snp_device *snpdev ) {
+ static const char language[] = "en-us";
+ void *buf = strings;
+ ssize_t remaining = max_len;
+ size_t hdrsize;
+ EFI_HII_SIBT_STRING_UCS2_BLOCK *string;
+ ssize_t wremaining;
+ size_t string_wlen;
+ unsigned int id;
+ EFI_HII_STRING_BLOCK *end;
+ size_t len;
+
+ /* Calculate header size */
+ hdrsize = ( offsetof ( typeof ( *strings ), Language ) +
+ sizeof ( language ) );
+ buf += hdrsize;
+ remaining -= hdrsize;
+
+ /* Fill in strings */
+ for ( id = 1 ; id < EFI_SNP_MAX_STRING_ID ; id++ ) {
+ string = buf;
+ if ( remaining >= ( ( ssize_t ) sizeof ( string->Header ) ) )
+ string->Header.BlockType = EFI_HII_SIBT_STRING_UCS2;
+ buf += offsetof ( typeof ( *string ), StringText );
+ remaining -= offsetof ( typeof ( *string ), StringText );
+ wremaining = ( remaining /
+ ( ( ssize_t ) sizeof ( string->StringText[0] )));
+ assert ( ! ( ( remaining <= 0 ) && ( wremaining > 0 ) ) );
+ string_wlen = efi_snp_string ( string->StringText, wremaining,
+ id, snpdev );
+ buf += ( ( string_wlen + 1 /* wNUL */ ) *
+ sizeof ( string->StringText[0] ) );
+ remaining -= ( ( string_wlen + 1 /* wNUL */ ) *
+ sizeof ( string->StringText[0] ) );
+ }
+
+ /* Fill in end marker */
+ end = buf;
+ if ( remaining >= ( ( ssize_t ) sizeof ( *end ) ) )
+ end->BlockType = EFI_HII_SIBT_END;
+ buf += sizeof ( *end );
+ remaining -= sizeof ( *end );
+
+ /* Calculate overall length */
+ len = ( max_len - remaining );
+
+ /* Fill in string package header */
+ if ( strings ) {
+ memset ( strings, 0, sizeof ( *strings ) );
+ strings->Header.Length = len;
+ strings->Header.Type = EFI_HII_PACKAGE_STRINGS;
+ strings->HdrSize = hdrsize;
+ strings->StringInfoOffset = hdrsize;
+ strings->LanguageName = EFI_SNP_LANGUAGE_NAME;
+ memcpy ( strings->Language, language, sizeof ( language ) );
+ }
+
+ return len;
+}
+
+/**
+ * Generate EFI SNP package list
+ *
+ * @v snpdev SNP device
+ * @ret package_list Package list, or NULL on error
+ *
+ * The package list is allocated using malloc(), and must eventually
+ * be freed by the caller.
+ */
+static EFI_HII_PACKAGE_LIST_HEADER *
+efi_snp_package_list ( struct efi_snp_device *snpdev ) {
+ size_t strings_len = efi_snp_strings ( NULL, 0, snpdev );
+ struct {
+ EFI_HII_PACKAGE_LIST_HEADER header;
+ struct efi_snp_formset formset;
+ union {
+ EFI_HII_STRING_PACKAGE_HDR strings;
+ uint8_t pad[strings_len];
+ } __attribute__ (( packed )) strings;
+ EFI_HII_PACKAGE_HEADER end;
+ } __attribute__ (( packed )) *package_list;
+
+ /* Allocate package list */
+ package_list = zalloc ( sizeof ( *package_list ) );
+ if ( ! package_list )
+ return NULL;
+
+ /* Create a unique GUID for this package list and formset */
+ efi_snp_formset.FormSet.FormSet.Guid.Data1++;
+
+ /* Populate package list */
+ memcpy ( &package_list->header.PackageListGuid,
+ &efi_snp_formset.FormSet.FormSet.Guid,
+ sizeof ( package_list->header.PackageListGuid ) );
+ package_list->header.PackageLength = sizeof ( *package_list );
+ memcpy ( &package_list->formset, &efi_snp_formset,
+ sizeof ( package_list->formset ) );
+ efi_snp_strings ( &package_list->strings.strings,
+ sizeof ( package_list->strings ), snpdev );
+ package_list->end.Length = sizeof ( package_list->end );
+ package_list->end.Type = EFI_HII_PACKAGE_END;
+
+ return &package_list->header;
+}
+
+/**
+ * Fetch configuration
+ *
+ * @v hii HII configuration access protocol
+ * @v request Configuration to fetch
+ * @ret progress Progress made through configuration to fetch
+ * @ret results Query results
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
+ EFI_STRING request, EFI_STRING *progress,
+ EFI_STRING *results __unused ) {
+ struct efi_snp_device *snpdev =
+ container_of ( hii, struct efi_snp_device, hii );
+
+ DBGC ( snpdev, "SNPDEV %p ExtractConfig\n", snpdev );
+
+ *progress = request;
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ * Store configuration
+ *
+ * @v hii HII configuration access protocol
+ * @v config Configuration to store
+ * @ret progress Progress made through configuration to store
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
+ EFI_STRING config, EFI_STRING *progress ) {
+ struct efi_snp_device *snpdev =
+ container_of ( hii, struct efi_snp_device, hii );
+
+ DBGC ( snpdev, "SNPDEV %p RouteConfig\n", snpdev );
+
+ *progress = config;
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ * Handle form actions
+ *
+ * @v hii HII configuration access protocol
+ * @v action Form browser action
+ * @v question_id Question ID
+ * @v type Type of value
+ * @v value Value
+ * @ret action_request Action requested by driver
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_hii_callback ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
+ EFI_BROWSER_ACTION action __unused,
+ EFI_QUESTION_ID question_id __unused,
+ UINT8 type __unused, EFI_IFR_TYPE_VALUE *value __unused,
+ EFI_BROWSER_ACTION_REQUEST *action_request __unused ) {
+ struct efi_snp_device *snpdev =
+ container_of ( hii, struct efi_snp_device, hii );
+
+ DBGC ( snpdev, "SNPDEV %p Callback\n", snpdev );
+ return EFI_UNSUPPORTED;
+}
+
+/** HII configuration access protocol */
+static EFI_HII_CONFIG_ACCESS_PROTOCOL efi_snp_device_hii = {
+ .ExtractConfig = efi_snp_hii_extract_config,
+ .RouteConfig = efi_snp_hii_route_config,
+ .Callback = efi_snp_hii_callback,
+};
+
+/******************************************************************************
+ *
+ * iPXE network driver
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Locate SNP device corresponding to network device
+ *
+ * @v netdev Network device
+ * @ret snp SNP device, or NULL if not found
+ */
+static struct efi_snp_device * efi_snp_demux ( struct net_device *netdev ) {
+ struct efi_snp_device *snpdev;
+
+ list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
+ if ( snpdev->netdev == netdev )
+ return snpdev;
+ }
+ return NULL;
+}
+
+/**
+ * Create SNP device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int efi_snp_probe ( struct net_device *netdev ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ struct efi_pci_device *efipci;
+ struct efi_snp_device *snpdev;
+ EFI_DEVICE_PATH_PROTOCOL *path_end;
+ MAC_ADDR_DEVICE_PATH *macpath;
+ size_t path_prefix_len = 0;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Find EFI PCI device */
+ efipci = efipci_find ( netdev->dev );
+ if ( ! efipci ) {
+ DBG ( "SNP skipping non-PCI device %s\n", netdev->name );
+ rc = 0;
+ goto err_no_pci;
+ }
+
+ /* Calculate device path prefix length */
+ path_end = efi_devpath_end ( efipci->path );
+ path_prefix_len = ( ( ( void * ) path_end ) -
+ ( ( void * ) efipci->path ) );
+
+ /* Allocate the SNP device */
+ snpdev = zalloc ( sizeof ( *snpdev ) + path_prefix_len +
+ sizeof ( *macpath ) );
+ if ( ! snpdev ) {
+ rc = -ENOMEM;
+ goto err_alloc_snp;
+ }
+ snpdev->netdev = netdev_get ( netdev );
+ snpdev->efipci = efipci;
+
+ /* Sanity check */
+ if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) {
+ DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
+ "length %d for %s\n", snpdev,
+ netdev->ll_protocol->ll_addr_len, netdev->name );
+ rc = -ENOTSUP;
+ goto err_ll_addr_len;
+ }
+
+ /* Populate the SNP structure */
+ memcpy ( &snpdev->snp, &efi_snp_device_snp, sizeof ( snpdev->snp ) );
+ snpdev->snp.Mode = &snpdev->mode;
+ if ( ( efirc = bs->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY,
+ efi_snp_wait_for_packet, snpdev,
+ &snpdev->snp.WaitForPacket ) ) != 0 ){
+ DBGC ( snpdev, "SNPDEV %p could not create event: %s\n",
+ snpdev, efi_strerror ( efirc ) );
+ rc = EFIRC_TO_RC ( efirc );
+ goto err_create_event;
+ }
+
+ /* Populate the SNP mode structure */
+ snpdev->mode.State = EfiSimpleNetworkStopped;
+ efi_snp_set_mode ( snpdev );
+
+ /* Populate the NII structure */
+ snpdev->nii.Revision =
+ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
+ strncpy ( snpdev->nii.StringId, "iPXE",
+ sizeof ( snpdev->nii.StringId ) );
+
+ /* Populate the HII configuration access structure */
+ memcpy ( &snpdev->hii, &efi_snp_device_hii, sizeof ( snpdev->hii ) );
+
+ /* Populate the device name */
+ efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) /
+ sizeof ( snpdev->name[0] ) ),
+ "%s", netdev->name );
+
+ /* Populate the device path */
+ memcpy ( &snpdev->path, efipci->path, path_prefix_len );
+ macpath = ( ( ( void * ) &snpdev->path ) + path_prefix_len );
+ path_end = ( ( void * ) ( macpath + 1 ) );
+ memset ( macpath, 0, sizeof ( *macpath ) );
+ macpath->Header.Type = MESSAGING_DEVICE_PATH;
+ macpath->Header.SubType = MSG_MAC_ADDR_DP;
+ macpath->Header.Length[0] = sizeof ( *macpath );
+ memcpy ( &macpath->MacAddress, netdev->ll_addr,
+ sizeof ( macpath->MacAddress ) );
+ macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto );
+ memset ( path_end, 0, sizeof ( *path_end ) );
+ path_end->Type = END_DEVICE_PATH_TYPE;
+ path_end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ path_end->Length[0] = sizeof ( *path_end );
+
+ /* Install the SNP */
+ if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
+ &snpdev->handle,
+ &efi_simple_network_protocol_guid, &snpdev->snp,
+ &efi_device_path_protocol_guid, &snpdev->path,
+ &efi_nii_protocol_guid, &snpdev->nii,
+ &efi_nii31_protocol_guid, &snpdev->nii,
+ &efi_hii_config_access_protocol_guid, &snpdev->hii,
+ NULL ) ) != 0 ) {
+ DBGC ( snpdev, "SNPDEV %p could not install protocols: "
+ "%s\n", snpdev, efi_strerror ( efirc ) );
+ rc = EFIRC_TO_RC ( efirc );
+ goto err_install_protocol_interface;
+ }
+
+ /* Add as child of PCI device */
+ if ( ( efirc = efipci_child_add ( efipci, snpdev->handle ) ) != 0 ) {
+ DBGC ( snpdev, "SNPDEV %p could not become child of " PCI_FMT
+ ": %s\n", snpdev, PCI_ARGS ( &efipci->pci ),
+ efi_strerror ( efirc ) );
+ rc = EFIRC_TO_RC ( efirc );
+ goto err_efipci_child_add;
+ }
+
+ /* Create HII package list */
+ snpdev->package_list = efi_snp_package_list ( snpdev );
+ if ( ! snpdev->package_list ) {
+ DBGC ( snpdev, "SNPDEV %p could not create HII package list\n",
+ snpdev );
+ rc = -ENOMEM;
+ goto err_create_hii;
+ }
+
+ /* Add HII packages */
+ if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list,
+ snpdev->handle,
+ &snpdev->hii_handle ) ) != 0 ) {
+ DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n",
+ snpdev, efi_strerror ( efirc ) );
+ rc = EFIRC_TO_RC ( efirc );
+ goto err_register_hii;
+ }
+
+ /* Add to list of SNP devices */
+ list_add ( &snpdev->list, &efi_snp_devices );
+
+ DBGC ( snpdev, "SNPDEV %p installed for %s as device %p\n",
+ snpdev, netdev->name, snpdev->handle );
+ return 0;
+
+ efihii->RemovePackageList ( efihii, snpdev->hii_handle );
+ err_register_hii:
+ free ( snpdev->package_list );
+ err_create_hii:
+ efipci_child_del ( efipci, snpdev->handle );
+ err_efipci_child_add:
+ bs->UninstallMultipleProtocolInterfaces (
+ snpdev->handle,
+ &efi_simple_network_protocol_guid, &snpdev->snp,
+ &efi_device_path_protocol_guid, &snpdev->path,
+ &efi_nii_protocol_guid, &snpdev->nii,
+ &efi_nii31_protocol_guid, &snpdev->nii,
+ &efi_hii_config_access_protocol_guid, &snpdev->hii,
+ NULL );
+ err_install_protocol_interface:
+ bs->CloseEvent ( snpdev->snp.WaitForPacket );
+ err_create_event:
+ err_ll_addr_len:
+ netdev_put ( netdev );
+ free ( snpdev );
+ err_alloc_snp:
+ err_no_pci:
+ return rc;
+}
+
+/**
+ * Handle SNP device or link state change
+ *
+ * @v netdev Network device
+ */
+static void efi_snp_notify ( struct net_device *netdev ) {
+ struct efi_snp_device *snpdev;
+
+ /* Locate SNP device */
+ snpdev = efi_snp_demux ( netdev );
+ if ( ! snpdev ) {
+ DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
+ return;
+ }
+
+ /* Update link state */
+ snpdev->mode.MediaPresent =
+ ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
+ DBGC ( snpdev, "SNPDEV %p link is %s\n", snpdev,
+ ( snpdev->mode.MediaPresent ? "up" : "down" ) );
+}
+
+/**
+ * Destroy SNP device
+ *
+ * @v netdev Network device
+ */
+static void efi_snp_remove ( struct net_device *netdev ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ struct efi_snp_device *snpdev;
+
+ /* Locate SNP device */
+ snpdev = efi_snp_demux ( netdev );
+ if ( ! snpdev ) {
+ DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
+ return;
+ }
+
+ /* Uninstall the SNP */
+ efihii->RemovePackageList ( efihii, snpdev->hii_handle );
+ free ( snpdev->package_list );
+ efipci_child_del ( snpdev->efipci, snpdev->handle );
+ list_del ( &snpdev->list );
+ bs->UninstallMultipleProtocolInterfaces (
+ snpdev->handle,
+ &efi_simple_network_protocol_guid, &snpdev->snp,
+ &efi_device_path_protocol_guid, &snpdev->path,
+ &efi_nii_protocol_guid, &snpdev->nii,
+ &efi_nii31_protocol_guid, &snpdev->nii,
+ &efi_hii_config_access_protocol_guid, &snpdev->hii,
+ NULL );
+ bs->CloseEvent ( snpdev->snp.WaitForPacket );
+ netdev_put ( snpdev->netdev );
+ free ( snpdev );
+}
+
+/** SNP driver */
+struct net_driver efi_snp_driver __net_driver = {
+ .name = "SNP",
+ .probe = efi_snp_probe,
+ .notify = efi_snp_notify,
+ .remove = efi_snp_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_strerror.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_strerror.c
new file mode 100644
index 00000000..430758f8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_strerror.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <ipxe/efi/efi.h>
+
+/** @file
+ *
+ * iPXE error message formatting for EFI
+ *
+ */
+
+/**
+ * Format EFI status code
+ *
+ * @v efirc EFI status code
+ * @v efi_strerror EFI status code string
+ */
+const char * efi_strerror ( EFI_STATUS efirc ) {
+ static char errbuf[32];
+
+ if ( ! efirc )
+ return "No error";
+
+ snprintf ( errbuf, sizeof ( errbuf ), "Error %lld",
+ ( unsigned long long ) ( efirc ^ MAX_BIT ) );
+ return errbuf;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_strings.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_strings.c
new file mode 100644
index 00000000..0fbc4538
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_strings.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <ipxe/vsprintf.h>
+#include <ipxe/efi/efi_strings.h>
+
+/** Context used by efi_vsnprintf() and friends */
+struct efi_sputc_context {
+ /** printf context */
+ struct printf_context ctx;
+ /** Buffer for formatted string (used by efi_printf_sputc()) */
+ wchar_t *buf;
+ /** Buffer length (used by efi_printf_sputc())
+ *
+ * Note that this is a number of wide characters, not a number
+ * of bytes.
+ */
+ size_t max_wlen;
+};
+
+/**
+ * Write wide character to buffer
+ *
+ * @v ctx Context
+ * @v c Character
+ */
+static void efi_printf_sputc ( struct printf_context *ctx, unsigned int c ) {
+ struct efi_sputc_context * sctx =
+ container_of ( ctx, struct efi_sputc_context, ctx );
+
+ if ( ctx->len < sctx->max_wlen )
+ sctx->buf[ctx->len] = c;
+}
+
+/**
+ * Write a formatted string to a wide-character buffer
+ *
+ * @v wbuf Buffer into which to write the string
+ * @v wsize Size of buffer (in wide characters)
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret wlen Length of formatted string (in wide characters)
+ *
+ * If the buffer is too small to contain the string, the returned
+ * length is the length that would have been written had enough space
+ * been available.
+ */
+int efi_vsnprintf ( wchar_t *wbuf, size_t wsize, const char *fmt,
+ va_list args ) {
+ struct efi_sputc_context sctx;
+ size_t wlen;
+ size_t wend;
+
+ /* Hand off to vcprintf */
+ sctx.ctx.handler = efi_printf_sputc;
+ sctx.buf = wbuf;
+ sctx.max_wlen = wsize;
+ wlen = vcprintf ( &sctx.ctx, fmt, args );
+
+ /* Add trailing NUL */
+ if ( wsize ) {
+ wend = wsize - 1;
+ if ( wlen < wend )
+ wend = wlen;
+ wbuf[wend] = '\0';
+ }
+
+ return wlen;
+}
+
+/**
+ * Write a formatted string to a buffer
+ *
+ * @v wbuf Buffer into which to write the string
+ * @v wsize Size of buffer (in wide characters)
+ * @v fmt Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret wlen Length of formatted string (in wide characters)
+ */
+int efi_snprintf ( wchar_t *wbuf, size_t wsize, const char *fmt, ... ) {
+ va_list args;
+ int i;
+
+ va_start ( args, fmt );
+ i = efi_vsnprintf ( wbuf, wsize, fmt, args );
+ va_end ( args );
+ return i;
+}
+
+/**
+ * Version of efi_vsnprintf() that accepts a signed buffer size
+ *
+ * @v wbuf Buffer into which to write the string
+ * @v swsize Size of buffer (in wide characters)
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret wlen Length of formatted string (in wide characters)
+ */
+int efi_vssnprintf ( wchar_t *wbuf, ssize_t swsize, const char *fmt,
+ va_list args ) {
+
+ /* Treat negative buffer size as zero buffer size */
+ if ( swsize < 0 )
+ swsize = 0;
+
+ /* Hand off to vsnprintf */
+ return efi_vsnprintf ( wbuf, swsize, fmt, args );
+}
+
+/**
+ * Version of efi_vsnprintf() that accepts a signed buffer size
+ *
+ * @v wbuf Buffer into which to write the string
+ * @v swsize Size of buffer (in wide characters)
+ * @v fmt Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret wlen Length of formatted string (in wide characters)
+ */
+int efi_ssnprintf ( wchar_t *wbuf, ssize_t swsize, const char *fmt, ... ) {
+ va_list args;
+ int len;
+
+ /* Hand off to vssnprintf */
+ va_start ( args, fmt );
+ len = efi_vssnprintf ( wbuf, swsize, fmt, args );
+ va_end ( args );
+ return len;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_timer.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_timer.c
new file mode 100644
index 00000000..1f8ad150
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_timer.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <limits.h>
+#include <assert.h>
+#include <unistd.h>
+#include <ipxe/timer.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/Protocol/Cpu.h>
+
+/** @file
+ *
+ * iPXE timer API for EFI
+ *
+ */
+
+/** Scale factor to apply to CPU timer 0
+ *
+ * The timer is scaled down in order to ensure that reasonable values
+ * for "number of ticks" don't exceed the size of an unsigned long.
+ */
+#define EFI_TIMER0_SHIFT 12
+
+/** Calibration time */
+#define EFI_CALIBRATE_DELAY_MS 1
+
+/** CPU protocol */
+static EFI_CPU_ARCH_PROTOCOL *cpu_arch;
+EFI_REQUIRE_PROTOCOL ( EFI_CPU_ARCH_PROTOCOL, &cpu_arch );
+
+/**
+ * Delay for a fixed number of microseconds
+ *
+ * @v usecs Number of microseconds for which to delay
+ */
+static void efi_udelay ( unsigned long usecs ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_STATUS efirc;
+
+ if ( ( efirc = bs->Stall ( usecs ) ) != 0 ) {
+ DBG ( "EFI could not delay for %ldus: %s\n",
+ usecs, efi_strerror ( efirc ) );
+ /* Probably screwed */
+ }
+}
+
+/**
+ * Get current system time in ticks
+ *
+ * @ret ticks Current time, in ticks
+ */
+static unsigned long efi_currticks ( void ) {
+ UINT64 time;
+ EFI_STATUS efirc;
+
+ /* Read CPU timer 0 (TSC) */
+ if ( ( efirc = cpu_arch->GetTimerValue ( cpu_arch, 0, &time,
+ NULL ) ) != 0 ) {
+ DBG ( "EFI could not read CPU timer: %s\n",
+ efi_strerror ( efirc ) );
+ /* Probably screwed */
+ return -1UL;
+ }
+
+ return ( time >> EFI_TIMER0_SHIFT );
+}
+
+/**
+ * Get number of ticks per second
+ *
+ * @ret ticks_per_sec Number of ticks per second
+ */
+static unsigned long efi_ticks_per_sec ( void ) {
+ static unsigned long ticks_per_sec = 0;
+
+ /* Calibrate timer, if necessary. EFI does nominally provide
+ * the timer speed via the (optional) TimerPeriod parameter to
+ * the GetTimerValue() call, but it gets the speed slightly
+ * wrong. By up to three orders of magnitude. Not helpful.
+ */
+ if ( ! ticks_per_sec ) {
+ unsigned long start;
+ unsigned long elapsed;
+
+ DBG ( "Calibrating EFI timer with a %d ms delay\n",
+ EFI_CALIBRATE_DELAY_MS );
+ start = currticks();
+ mdelay ( EFI_CALIBRATE_DELAY_MS );
+ elapsed = ( currticks() - start );
+ ticks_per_sec = ( elapsed * ( 1000 / EFI_CALIBRATE_DELAY_MS ));
+ DBG ( "EFI CPU timer calibrated at %ld ticks in %d ms (%ld "
+ "ticks/sec)\n", elapsed, EFI_CALIBRATE_DELAY_MS,
+ ticks_per_sec );
+ }
+
+ return ticks_per_sec;
+}
+
+PROVIDE_TIMER ( efi, udelay, efi_udelay );
+PROVIDE_TIMER ( efi, currticks, efi_currticks );
+PROVIDE_TIMER ( efi, ticks_per_sec, efi_ticks_per_sec );
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_uaccess.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_uaccess.c
new file mode 100644
index 00000000..d80ca7a7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_uaccess.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/uaccess.h>
+#include <ipxe/efi/efi.h>
+
+/** @file
+ *
+ * iPXE user access API for EFI
+ *
+ */
+
+PROVIDE_UACCESS_INLINE ( efi, phys_to_user );
+PROVIDE_UACCESS_INLINE ( efi, user_to_phys );
+PROVIDE_UACCESS_INLINE ( efi, virt_to_user );
+PROVIDE_UACCESS_INLINE ( efi, user_to_virt );
+PROVIDE_UACCESS_INLINE ( efi, userptr_add );
+PROVIDE_UACCESS_INLINE ( efi, memcpy_user );
+PROVIDE_UACCESS_INLINE ( efi, memmove_user );
+PROVIDE_UACCESS_INLINE ( efi, memset_user );
+PROVIDE_UACCESS_INLINE ( efi, strlen_user );
+PROVIDE_UACCESS_INLINE ( efi, memchr_user );
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_umalloc.c b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_umalloc.c
new file mode 100644
index 00000000..d1d689ea
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/efi/efi_umalloc.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <assert.h>
+#include <ipxe/umalloc.h>
+#include <ipxe/efi/efi.h>
+
+/** @file
+ *
+ * iPXE user memory allocation API for EFI
+ *
+ */
+
+/** Equivalent of NOWHERE for user pointers */
+#define UNOWHERE ( ~UNULL )
+
+/**
+ * Reallocate external memory
+ *
+ * @v old_ptr Memory previously allocated by umalloc(), or UNULL
+ * @v new_size Requested size
+ * @ret new_ptr Allocated memory, or UNULL
+ *
+ * Calling realloc() with a new size of zero is a valid way to free a
+ * memory block.
+ */
+static userptr_t efi_urealloc ( userptr_t old_ptr, size_t new_size ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_PHYSICAL_ADDRESS phys_addr;
+ unsigned int new_pages, old_pages;
+ userptr_t new_ptr = UNOWHERE;
+ size_t old_size;
+ EFI_STATUS efirc;
+
+ /* Allocate new memory if necessary. If allocation fails,
+ * return without touching the old block.
+ */
+ if ( new_size ) {
+ new_pages = ( EFI_SIZE_TO_PAGES ( new_size ) + 1 );
+ if ( ( efirc = bs->AllocatePages ( AllocateAnyPages,
+ EfiBootServicesData,
+ new_pages,
+ &phys_addr ) ) != 0 ) {
+ DBG ( "EFI could not allocate %d pages: %s\n",
+ new_pages, efi_strerror ( efirc ) );
+ return UNULL;
+ }
+ assert ( phys_addr != 0 );
+ new_ptr = phys_to_user ( phys_addr + EFI_PAGE_SIZE );
+ copy_to_user ( new_ptr, -EFI_PAGE_SIZE,
+ &new_size, sizeof ( new_size ) );
+ DBG ( "EFI allocated %d pages at %llx\n",
+ new_pages, phys_addr );
+ }
+
+ /* Copy across relevant part of the old data region (if any),
+ * then free it. Note that at this point either (a) new_ptr
+ * is valid, or (b) new_size is 0; either way, the memcpy() is
+ * valid.
+ */
+ if ( old_ptr && ( old_ptr != UNOWHERE ) ) {
+ copy_from_user ( &old_size, old_ptr, -EFI_PAGE_SIZE,
+ sizeof ( old_size ) );
+ memcpy_user ( new_ptr, 0, old_ptr, 0,
+ ( (old_size < new_size) ? old_size : new_size ));
+ old_pages = ( EFI_SIZE_TO_PAGES ( old_size ) + 1 );
+ phys_addr = user_to_phys ( old_ptr, -EFI_PAGE_SIZE );
+ if ( ( efirc = bs->FreePages ( phys_addr, old_pages ) ) != 0 ){
+ DBG ( "EFI could not free %d pages at %llx: %s\n",
+ old_pages, phys_addr, efi_strerror ( efirc ) );
+ /* Not fatal; we have leaked memory but successfully
+ * allocated (if asked to do so).
+ */
+ }
+ DBG ( "EFI freed %d pages at %llx\n", old_pages, phys_addr );
+ }
+
+ return new_ptr;
+}
+
+PROVIDE_UMALLOC ( efi, urealloc, efi_urealloc );
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_console.c b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_console.c
new file mode 100644
index 00000000..5105eaa9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_console.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+/** @file
+ *
+ * Linux console implementation.
+ *
+ */
+
+#include <ipxe/console.h>
+
+#include <ipxe/init.h>
+#include <ipxe/keys.h>
+#include <linux_api.h>
+
+#include <linux/termios.h>
+#include <asm/errno.h>
+
+#include <config/console.h>
+
+/* Set default console usage if applicable */
+#if ! ( defined ( CONSOLE_LINUX ) && CONSOLE_EXPLICIT ( CONSOLE_LINUX ) )
+#undef CONSOLE_LINUX
+#define CONSOLE_LINUX ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
+#endif
+
+static void linux_console_putchar(int c)
+{
+ /* write to stdout */
+ if (linux_write(1, &c, 1) != 1)
+ DBG("linux_console write failed (%s)\n", linux_strerror(linux_errno));
+}
+
+static int linux_console_getchar()
+{
+ char c;
+
+ /* read from stdin */
+ if (linux_read(0, &c, 1) < 0) {
+ DBG("linux_console read failed (%s)\n", linux_strerror(linux_errno));
+ return 0;
+ }
+ /* backspace seems to be returned as ascii del, map it here */
+ if (c == 0x7f)
+ return KEY_BACKSPACE;
+ else
+ return c;
+}
+
+static int linux_console_iskey()
+{
+ struct pollfd pfd;
+ pfd.fd = 0;
+ pfd.events = POLLIN;
+
+ /* poll for data to be read on stdin */
+ if (linux_poll(&pfd, 1, 0) == -1) {
+ DBG("linux_console poll failed (%s)\n", linux_strerror(linux_errno));
+ return 0;
+ }
+
+ if (pfd.revents & POLLIN)
+ return 1;
+ else
+ return 0;
+}
+
+struct console_driver linux_console __console_driver = {
+ .disabled = 0,
+ .putchar = linux_console_putchar,
+ .getchar = linux_console_getchar,
+ .iskey = linux_console_iskey,
+ .usage = CONSOLE_LINUX,
+};
+
+static int linux_tcgetattr(int fd, struct termios *termios_p)
+{
+ return linux_ioctl(fd, TCGETS, termios_p);
+}
+
+static int linux_tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
+{
+ unsigned long int cmd;
+
+ switch (optional_actions)
+ {
+ case TCSANOW:
+ cmd = TCSETS;
+ break;
+ case TCSADRAIN:
+ cmd = TCSETSW;
+ break;
+ case TCSAFLUSH:
+ cmd = TCSETSF;
+ break;
+ default:
+ linux_errno = EINVAL;
+ return -1;
+ }
+
+ return linux_ioctl(fd, cmd, termios_p);
+}
+
+/** Saved termios attributes */
+static struct termios saved_termios;
+
+/** Setup the terminal for our use */
+static void linux_console_startup(void)
+{
+ struct termios t;
+
+ if (linux_tcgetattr(0, &t)) {
+ DBG("linux_console tcgetattr failed (%s)", linux_strerror(linux_errno));
+ return;
+ }
+
+ saved_termios = t;
+
+ /* Disable canonical mode and echo. Let readline handle that */
+ t.c_lflag &= ~(ECHO | ICANON);
+ /* stop ^C from sending a signal */
+ t.c_cc[VINTR] = 0;
+
+ if (linux_tcsetattr(0, TCSAFLUSH, &t))
+ DBG("linux_console tcsetattr failed (%s)", linux_strerror(linux_errno));
+}
+
+/** Restores original terminal attributes on shutdown */
+static void linux_console_shutdown(int flags __unused)
+{
+ if (linux_tcsetattr(0, TCSAFLUSH, &saved_termios))
+ DBG("linux_console tcsetattr failed (%s)", linux_strerror(linux_errno));
+}
+
+struct startup_fn linux_console_startup_fn __startup_fn(STARTUP_EARLY) = {
+ .startup = linux_console_startup,
+ .shutdown = linux_console_shutdown,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_entropy.c b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_entropy.c
new file mode 100644
index 00000000..d82aabaa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_entropy.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Linux entropy source
+ *
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <linux_api.h>
+#include <ipxe/entropy.h>
+
+/** Entropy source filename */
+static const char entropy_filename[] = "/dev/random";
+
+/** Entropy source file handle */
+static int entropy_fd;
+
+/**
+ * Enable entropy gathering
+ *
+ * @ret rc Return status code
+ */
+static int linux_entropy_enable ( void ) {
+
+ /* Open entropy source */
+ entropy_fd = linux_open ( entropy_filename, O_RDONLY );
+ if ( entropy_fd < 0 ) {
+ DBGC ( &entropy_fd, "ENTROPY could not open %s: %s\n",
+ entropy_filename, linux_strerror ( linux_errno ) );
+ return entropy_fd;
+ }
+
+ return 0;
+}
+
+/**
+ * Disable entropy gathering
+ *
+ */
+static void linux_entropy_disable ( void ) {
+
+ /* Close entropy source */
+ linux_close ( entropy_fd );
+}
+
+/**
+ * Get noise sample
+ *
+ * @ret noise Noise sample
+ * @ret rc Return status code
+ */
+static int linux_get_noise ( noise_sample_t *noise ) {
+ uint8_t byte;
+ ssize_t len;
+
+ /* Read a single byte from entropy source */
+ len = linux_read ( entropy_fd, &byte, sizeof ( byte ) );
+ if ( len < 0 ) {
+ DBGC ( &entropy_fd, "ENTROPY could not read from %s: %s\n",
+ entropy_filename, linux_strerror ( linux_errno ) );
+ return len;
+ }
+ if ( len == 0 ) {
+ DBGC ( &entropy_fd, "ENTROPY EOF on reading from %s: %s\n",
+ entropy_filename, linux_strerror ( linux_errno ) );
+ return -EPIPE;
+ }
+ *noise = byte;
+
+ return 0;
+}
+
+PROVIDE_ENTROPY_INLINE ( linux, min_entropy_per_sample );
+PROVIDE_ENTROPY ( linux, entropy_enable, linux_entropy_enable );
+PROVIDE_ENTROPY ( linux, entropy_disable, linux_entropy_disable );
+PROVIDE_ENTROPY ( linux, get_noise, linux_get_noise );
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_nap.c b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_nap.c
new file mode 100644
index 00000000..98642bad
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_nap.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <ipxe/nap.h>
+
+#include <linux_api.h>
+
+/** @file
+ *
+ * iPXE CPU sleeping API for linux
+ *
+ */
+
+/**
+ * Sleep until next CPU interrupt
+ *
+ */
+static void linux_cpu_nap(void)
+{
+ linux_usleep(0);
+}
+
+PROVIDE_NAP(linux, cpu_nap, linux_cpu_nap);
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_smbios.c b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_smbios.c
new file mode 100644
index 00000000..f99120bf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_smbios.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <errno.h>
+#include <ipxe/smbios.h>
+
+/**
+ * Find SMBIOS
+ *
+ * Not implemented currently.
+ *
+ * @v smbios SMBIOS entry point descriptor structure to fill in
+ * @ret rc Return status code
+ */
+static int linux_find_smbios(struct smbios *smbios __unused)
+{
+ return -ENODEV;
+}
+
+PROVIDE_SMBIOS(linux, find_smbios, linux_find_smbios);
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_time.c b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_time.c
new file mode 100644
index 00000000..b41d8a6e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_time.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Linux time source
+ *
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <linux_api.h>
+#include <ipxe/time.h>
+
+/**
+ * Get current time in seconds
+ *
+ * @ret time Time, in seconds
+ */
+static time_t linux_now ( void ) {
+ struct timeval now;
+
+ linux_gettimeofday ( &now, NULL );
+ return now.tv_sec;
+}
+
+PROVIDE_TIME ( linux, time_now, linux_now );
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_timer.c b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_timer.c
new file mode 100644
index 00000000..6b4643a6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_timer.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <ipxe/timer.h>
+
+#include <linux_api.h>
+
+/** @file
+ *
+ * iPXE timer API for linux
+ *
+ */
+
+/**
+ * Delay for a fixed number of microseconds
+ *
+ * @v usecs Number of microseconds for which to delay
+ */
+static void linux_udelay(unsigned long usecs)
+{
+ linux_usleep(usecs);
+}
+
+/**
+ * Get number of ticks per second
+ *
+ * @ret ticks_per_sec Number of ticks per second
+ */
+static unsigned long linux_ticks_per_sec(void)
+{
+ return 1000;
+}
+
+/**
+ * Get current system time in ticks
+ *
+ * linux doesn't provide an easy access to jiffies so implement it by measuring
+ * the time since the first call to this function.
+ *
+ * @ret ticks Current time, in ticks
+ */
+static unsigned long linux_currticks(void)
+{
+ static struct timeval start;
+ static int initialized = 0;
+
+ if (! initialized) {
+ linux_gettimeofday(&start, NULL);
+ initialized = 1;
+ }
+
+ struct timeval now;
+ linux_gettimeofday(&now, NULL);
+
+ unsigned long ticks = (now.tv_sec - start.tv_sec) * linux_ticks_per_sec();
+ ticks += (now.tv_usec - start.tv_usec) / (long)(1000000 / linux_ticks_per_sec());
+
+ return ticks;
+}
+
+PROVIDE_TIMER(linux, udelay, linux_udelay);
+PROVIDE_TIMER(linux, currticks, linux_currticks);
+PROVIDE_TIMER(linux, ticks_per_sec, linux_ticks_per_sec);
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_uaccess.c b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_uaccess.c
new file mode 100644
index 00000000..d4e52d09
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_uaccess.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <ipxe/uaccess.h>
+
+/** @file
+ *
+ * iPXE user access API for linux
+ *
+ */
+
+PROVIDE_UACCESS_INLINE(linux, phys_to_user);
+PROVIDE_UACCESS_INLINE(linux, user_to_phys);
+PROVIDE_UACCESS_INLINE(linux, virt_to_user);
+PROVIDE_UACCESS_INLINE(linux, user_to_virt);
+PROVIDE_UACCESS_INLINE(linux, userptr_add);
+PROVIDE_UACCESS_INLINE(linux, memcpy_user);
+PROVIDE_UACCESS_INLINE(linux, memmove_user);
+PROVIDE_UACCESS_INLINE(linux, memset_user);
+PROVIDE_UACCESS_INLINE(linux, strlen_user);
+PROVIDE_UACCESS_INLINE(linux, memchr_user);
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_umalloc.c b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_umalloc.c
new file mode 100644
index 00000000..aa0052c5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/linux/linux_umalloc.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <valgrind/memcheck.h>
+
+/** @file
+ *
+ * iPXE user memory allocation API for linux
+ *
+ */
+
+#include <assert.h>
+#include <ipxe/umalloc.h>
+
+#include <linux_api.h>
+
+/** Special address returned for empty allocations */
+#define NOWHERE ((void *)-1)
+
+/** Poison to make the metadata more unique */
+#define POISON 0xa5a5a5a5
+#define min(a,b) (((a)<(b))?(a):(b))
+
+/** Metadata stored at the beginning of all allocations */
+struct metadata
+{
+ unsigned poison;
+ size_t size;
+};
+
+#define SIZE_MD (sizeof(struct metadata))
+
+/** Simple realloc which passes most of the work to mmap(), mremap() and munmap() */
+static void * linux_realloc(void *ptr, size_t size)
+{
+ struct metadata md = {0, 0};
+ struct metadata * mdptr = NULL;
+
+ DBG2("linux_realloc(%p, %zd)\n", ptr, size);
+
+ /* Check whether we have a valid pointer */
+ if (ptr != NULL && ptr != NOWHERE) {
+ mdptr = ptr - SIZE_MD;
+ VALGRIND_MAKE_MEM_DEFINED(mdptr, SIZE_MD);
+ md = *mdptr;
+ VALGRIND_MAKE_MEM_NOACCESS(mdptr, SIZE_MD);
+
+ /* Check for poison in the metadata */
+ if (md.poison != POISON) {
+ DBG("linux_realloc bad poison: 0x%x (expected 0x%x)\n", md.poison, POISON);
+ return NULL;
+ }
+ } else {
+ /* Handle NOWHERE as NULL */
+ ptr = NULL;
+ }
+
+ /*
+ * At this point, ptr is either NULL or pointing to a region allocated by us.
+ * In the latter case mdptr is pointing to a valid metadata, otherwise it is NULL.
+ */
+
+ /* Handle deallocation or allocation of size 0 */
+ if (size == 0) {
+ if (mdptr) {
+ if (linux_munmap(mdptr, md.size))
+ DBG("linux_realloc munmap failed: %s\n", linux_strerror(linux_errno));
+ VALGRIND_FREELIKE_BLOCK(ptr, sizeof(*mdptr));
+ }
+ return NOWHERE;
+ }
+
+ if (ptr) {
+ char *vbits = NULL;
+
+ if (RUNNING_ON_VALGRIND > 0)
+ vbits = linux_realloc(NULL, min(size, md.size));
+
+/* prevent an unused variable warning when building w/o valgrind support */
+#ifndef NVALGRIND
+ VALGRIND_GET_VBITS(ptr, vbits, min(size, md.size));
+#endif
+
+ VALGRIND_FREELIKE_BLOCK(ptr, SIZE_MD);
+
+ mdptr = linux_mremap(mdptr, md.size + SIZE_MD, size + SIZE_MD, MREMAP_MAYMOVE);
+ if (mdptr == MAP_FAILED) {
+ DBG("linux_realloc mremap failed: %s\n", linux_strerror(linux_errno));
+ return NULL;
+ }
+ ptr = ((void *)mdptr) + SIZE_MD;
+
+ VALGRIND_MALLOCLIKE_BLOCK(ptr, size, SIZE_MD, 0);
+/* prevent an unused variable warning when building w/o valgrind support */
+#ifndef NVALGRIND
+ VALGRIND_SET_VBITS(ptr, vbits, min(size, md.size));
+#endif
+
+ if (RUNNING_ON_VALGRIND > 0)
+ linux_realloc(vbits, 0);
+ } else {
+ mdptr = linux_mmap(NULL, size + SIZE_MD, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (mdptr == MAP_FAILED) {
+ DBG("linux_realloc mmap failed: %s\n", linux_strerror(linux_errno));
+ return NULL;
+ }
+ ptr = ((void *)mdptr) + SIZE_MD;
+ VALGRIND_MALLOCLIKE_BLOCK(ptr, size, SIZE_MD, 0);
+ }
+
+ /* Update the metadata */
+ VALGRIND_MAKE_MEM_DEFINED(mdptr, SIZE_MD);
+ mdptr->poison = POISON;
+ mdptr->size = size;
+ VALGRIND_MAKE_MEM_NOACCESS(mdptr, SIZE_MD);
+ // VALGRIND_MALLOCLIKE_BLOCK ignores redzones currently, make our own
+ VALGRIND_MAKE_MEM_NOACCESS(ptr + size, SIZE_MD);
+
+ return ptr;
+}
+
+/**
+ * Reallocate external memory
+ *
+ * @v old_ptr Memory previously allocated by umalloc(), or UNULL
+ * @v new_size Requested size
+ * @ret new_ptr Allocated memory, or UNULL
+ *
+ * Calling realloc() with a new size of zero is a valid way to free a
+ * memory block.
+ */
+static userptr_t linux_urealloc(userptr_t old_ptr, size_t new_size)
+{
+ return (userptr_t)linux_realloc((void *)old_ptr, new_size);
+}
+
+PROVIDE_UMALLOC(linux, urealloc, linux_urealloc);
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/smbios/smbios.c b/src/VBox/Devices/PC/ipxe/src/interface/smbios/smbios.c
new file mode 100644
index 00000000..b60e10f7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/smbios/smbios.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/smbios.h>
+
+/** @file
+ *
+ * System Management BIOS
+ *
+ */
+
+/** SMBIOS entry point descriptor */
+static struct smbios smbios = {
+ .address = UNULL,
+};
+
+/**
+ * Find SMBIOS strings terminator
+ *
+ * @v offset Offset to start of strings
+ * @ret offset Offset to strings terminator, or 0 if not found
+ */
+static size_t find_strings_terminator ( size_t offset ) {
+ size_t max_offset = ( smbios.len - 2 );
+ uint16_t nulnul;
+
+ for ( ; offset <= max_offset ; offset++ ) {
+ copy_from_user ( &nulnul, smbios.address, offset, 2 );
+ if ( nulnul == 0 )
+ return ( offset + 1 );
+ }
+ return 0;
+}
+
+/**
+ * Find specific structure type within SMBIOS
+ *
+ * @v type Structure type to search for
+ * @v structure SMBIOS structure descriptor to fill in
+ * @ret rc Return status code
+ */
+int find_smbios_structure ( unsigned int type,
+ struct smbios_structure *structure ) {
+ unsigned int count = 0;
+ size_t offset = 0;
+ size_t strings_offset;
+ size_t terminator_offset;
+ int rc;
+
+ /* Find SMBIOS */
+ if ( ( smbios.address == UNULL ) &&
+ ( ( rc = find_smbios ( &smbios ) ) != 0 ) )
+ return rc;
+ assert ( smbios.address != UNULL );
+
+ /* Scan through list of structures */
+ while ( ( ( offset + sizeof ( structure->header ) ) < smbios.len )
+ && ( count < smbios.count ) ) {
+
+ /* Read next SMBIOS structure header */
+ copy_from_user ( &structure->header, smbios.address, offset,
+ sizeof ( structure->header ) );
+
+ /* Determine start and extent of strings block */
+ strings_offset = ( offset + structure->header.len );
+ if ( strings_offset > smbios.len ) {
+ DBG ( "SMBIOS structure at offset %zx with length "
+ "%x extends beyond SMBIOS\n", offset,
+ structure->header.len );
+ return -ENOENT;
+ }
+ terminator_offset = find_strings_terminator ( strings_offset );
+ if ( ! terminator_offset ) {
+ DBG ( "SMBIOS structure at offset %zx has "
+ "unterminated strings section\n", offset );
+ return -ENOENT;
+ }
+ structure->strings_len = ( terminator_offset - strings_offset);
+
+ DBG ( "SMBIOS structure at offset %zx has type %d, length %x, "
+ "strings length %zx\n", offset, structure->header.type,
+ structure->header.len, structure->strings_len );
+
+ /* If this is the structure we want, return */
+ if ( structure->header.type == type ) {
+ structure->offset = offset;
+ return 0;
+ }
+
+ /* Move to next SMBIOS structure */
+ offset = ( terminator_offset + 1 );
+ count++;
+ }
+
+ DBG ( "SMBIOS structure type %d not found\n", type );
+ return -ENOENT;
+}
+
+/**
+ * Copy SMBIOS structure
+ *
+ * @v structure SMBIOS structure descriptor
+ * @v data Buffer to hold SMBIOS structure
+ * @v len Length of buffer
+ * @ret rc Return status code
+ */
+int read_smbios_structure ( struct smbios_structure *structure,
+ void *data, size_t len ) {
+
+ assert ( smbios.address != UNULL );
+
+ if ( len > structure->header.len )
+ len = structure->header.len;
+ copy_from_user ( data, smbios.address, structure->offset, len );
+ return 0;
+}
+
+/**
+ * Find indexed string within SMBIOS structure
+ *
+ * @v structure SMBIOS structure descriptor
+ * @v index String index
+ * @v data Buffer for string
+ * @v len Length of string buffer
+ * @ret rc Length of string, or negative error
+ */
+int read_smbios_string ( struct smbios_structure *structure,
+ unsigned int index, void *data, size_t len ) {
+ size_t strings_start = ( structure->offset + structure->header.len );
+ size_t strings_end = ( strings_start + structure->strings_len );
+ size_t offset;
+ size_t string_len;
+
+ assert ( smbios.address != UNULL );
+
+ /* String numbers start at 1 (0 is used to indicate "no string") */
+ if ( ! index )
+ return -ENOENT;
+
+ for ( offset = strings_start ; offset < strings_end ;
+ offset += ( string_len + 1 ) ) {
+ /* Get string length. This is known safe, since the
+ * smbios_strings struct is constructed so as to
+ * always end on a string boundary.
+ */
+ string_len = strlen_user ( smbios.address, offset );
+ if ( --index == 0 ) {
+ /* Copy string, truncating as necessary. */
+ if ( len > string_len )
+ len = string_len;
+ copy_from_user ( data, smbios.address, offset, len );
+ return string_len;
+ }
+ }
+
+ DBG ( "SMBIOS string index %d not found\n", index );
+ return -ENOENT;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/interface/smbios/smbios_settings.c b/src/VBox/Devices/PC/ipxe/src/interface/smbios/smbios_settings.c
new file mode 100644
index 00000000..92dc4127
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/interface/smbios/smbios_settings.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/settings.h>
+#include <ipxe/init.h>
+#include <ipxe/uuid.h>
+#include <ipxe/smbios.h>
+
+/** SMBIOS settings tag magic number */
+#define SMBIOS_TAG_MAGIC 0x5B /* "SmBios" */
+
+/**
+ * Construct SMBIOS empty tag
+ *
+ * @ret tag SMBIOS setting tag
+ */
+#define SMBIOS_EMPTY_TAG ( SMBIOS_TAG_MAGIC << 24 )
+
+/**
+ * Construct SMBIOS raw-data tag
+ *
+ * @v _type SMBIOS structure type number
+ * @v _structure SMBIOS structure data type
+ * @v _field Field within SMBIOS structure data type
+ * @ret tag SMBIOS setting tag
+ */
+#define SMBIOS_RAW_TAG( _type, _structure, _field ) \
+ ( ( SMBIOS_TAG_MAGIC << 24 ) | \
+ ( (_type) << 16 ) | \
+ ( offsetof ( _structure, _field ) << 8 ) | \
+ ( sizeof ( ( ( _structure * ) 0 )->_field ) ) )
+
+/**
+ * Construct SMBIOS string tag
+ *
+ * @v _type SMBIOS structure type number
+ * @v _structure SMBIOS structure data type
+ * @v _field Field within SMBIOS structure data type
+ * @ret tag SMBIOS setting tag
+ */
+#define SMBIOS_STRING_TAG( _type, _structure, _field ) \
+ ( ( SMBIOS_TAG_MAGIC << 24 ) | \
+ ( (_type) << 16 ) | \
+ ( offsetof ( _structure, _field ) << 8 ) )
+
+/**
+ * Check applicability of SMBIOS setting
+ *
+ * @v settings Settings block
+ * @v setting Setting
+ * @ret applies Setting applies within this settings block
+ */
+static int smbios_applies ( struct settings *settings __unused,
+ struct setting *setting ) {
+ unsigned int tag_magic;
+
+ /* Check tag magic */
+ tag_magic = ( setting->tag >> 24 );
+ return ( tag_magic == SMBIOS_TAG_MAGIC );
+}
+
+/**
+ * Fetch value of SMBIOS setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+static int smbios_fetch ( struct settings *settings __unused,
+ struct setting *setting,
+ void *data, size_t len ) {
+ struct smbios_structure structure;
+ unsigned int tag_magic;
+ unsigned int tag_type;
+ unsigned int tag_offset;
+ unsigned int tag_len;
+ int rc;
+
+ /* Split tag into type, offset and length */
+ tag_magic = ( setting->tag >> 24 );
+ tag_type = ( ( setting->tag >> 16 ) & 0xff );
+ tag_offset = ( ( setting->tag >> 8 ) & 0xff );
+ tag_len = ( setting->tag & 0xff );
+ assert ( tag_magic == SMBIOS_TAG_MAGIC );
+
+ /* Find SMBIOS structure */
+ if ( ( rc = find_smbios_structure ( tag_type, &structure ) ) != 0 )
+ return rc;
+
+ {
+ uint8_t buf[structure.header.len];
+
+ /* Read SMBIOS structure */
+ if ( ( rc = read_smbios_structure ( &structure, buf,
+ sizeof ( buf ) ) ) != 0 )
+ return rc;
+
+ if ( tag_len == 0 ) {
+ /* String */
+ return read_smbios_string ( &structure,
+ buf[tag_offset],
+ data, len );
+ } else {
+ /* Raw data */
+ if ( len > tag_len )
+ len = tag_len;
+ memcpy ( data, &buf[tag_offset], len );
+ return tag_len;
+ }
+ }
+}
+
+/** SMBIOS settings operations */
+static struct settings_operations smbios_settings_operations = {
+ .applies = smbios_applies,
+ .fetch = smbios_fetch,
+};
+
+/** SMBIOS settings */
+static struct settings smbios_settings = {
+ .refcnt = NULL,
+ .tag_magic = SMBIOS_EMPTY_TAG,
+ .siblings = LIST_HEAD_INIT ( smbios_settings.siblings ),
+ .children = LIST_HEAD_INIT ( smbios_settings.children ),
+ .op = &smbios_settings_operations,
+};
+
+/** Initialise SMBIOS settings */
+static void smbios_init ( void ) {
+ int rc;
+
+ if ( ( rc = register_settings ( &smbios_settings, NULL,
+ "smbios" ) ) != 0 ) {
+ DBG ( "SMBIOS could not register settings: %s\n",
+ strerror ( rc ) );
+ return;
+ }
+}
+
+/** SMBIOS settings initialiser */
+struct init_fn smbios_init_fn __init_fn ( INIT_NORMAL ) = {
+ .initialise = smbios_init,
+};
+
+/** UUID setting obtained via SMBIOS */
+struct setting uuid_setting __setting ( SETTING_HOST ) = {
+ .name = "uuid",
+ .description = "UUID",
+ .tag = SMBIOS_RAW_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION,
+ struct smbios_system_information, uuid ),
+ .type = &setting_type_uuid,
+};
+
+/** Other SMBIOS named settings */
+struct setting smbios_named_settings[] __setting ( SETTING_HOST_EXTRA ) = {
+ {
+ .name = "manufacturer",
+ .description = "Manufacturer",
+ .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION,
+ struct smbios_system_information,
+ manufacturer ),
+ .type = &setting_type_string,
+ },
+ {
+ .name = "product",
+ .description = "Product name",
+ .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION,
+ struct smbios_system_information,
+ product ),
+ .type = &setting_type_string,
+ },
+ {
+ .name = "serial",
+ .description = "Serial number",
+ .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION,
+ struct smbios_system_information,
+ serial ),
+ .type = &setting_type_string,
+ },
+ {
+ .name = "asset",
+ .description = "Asset tag",
+ .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_ENCLOSURE_INFORMATION,
+ struct smbios_enclosure_information,
+ asset_tag ),
+ .type = &setting_type_string,
+ },
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/libgcc/__divdi3.c b/src/VBox/Devices/PC/ipxe/src/libgcc/__divdi3.c
new file mode 100644
index 00000000..7097b11e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/libgcc/__divdi3.c
@@ -0,0 +1,26 @@
+/*
+ * arch/i386/libgcc/__divdi3.c
+ */
+
+#include "libgcc.h"
+
+__libgcc int64_t __divdi3(int64_t num, int64_t den)
+{
+ int minus = 0;
+ int64_t v;
+
+ if ( num < 0 ) {
+ num = -num;
+ minus = 1;
+ }
+ if ( den < 0 ) {
+ den = -den;
+ minus ^= 1;
+ }
+
+ v = __udivmoddi4(num, den, NULL);
+ if ( minus )
+ v = -v;
+
+ return v;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/libgcc/__moddi3.c b/src/VBox/Devices/PC/ipxe/src/libgcc/__moddi3.c
new file mode 100644
index 00000000..d671bbc4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/libgcc/__moddi3.c
@@ -0,0 +1,26 @@
+/*
+ * arch/i386/libgcc/__moddi3.c
+ */
+
+#include "libgcc.h"
+
+__libgcc int64_t __moddi3(int64_t num, int64_t den)
+{
+ int minus = 0;
+ int64_t v;
+
+ if ( num < 0 ) {
+ num = -num;
+ minus = 1;
+ }
+ if ( den < 0 ) {
+ den = -den;
+ minus ^= 1;
+ }
+
+ (void) __udivmoddi4(num, den, (uint64_t *)&v);
+ if ( minus )
+ v = -v;
+
+ return v;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/libgcc/__udivdi3.c b/src/VBox/Devices/PC/ipxe/src/libgcc/__udivdi3.c
new file mode 100644
index 00000000..f5a14de2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/libgcc/__udivdi3.c
@@ -0,0 +1,10 @@
+/*
+ * arch/i386/libgcc/__divdi3.c
+ */
+
+#include "libgcc.h"
+
+__libgcc uint64_t __udivdi3(uint64_t num, uint64_t den)
+{
+ return __udivmoddi4(num, den, NULL);
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/libgcc/__udivmoddi4.c b/src/VBox/Devices/PC/ipxe/src/libgcc/__udivmoddi4.c
new file mode 100644
index 00000000..21e0d51f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/libgcc/__udivmoddi4.c
@@ -0,0 +1,32 @@
+#include "libgcc.h"
+
+__libgcc uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem_p)
+{
+ uint64_t quot = 0, qbit = 1;
+
+ if ( den == 0 ) {
+ return 1/((unsigned)den); /* Intentional divide by zero, without
+ triggering a compiler warning which
+ would abort the build */
+ }
+
+ /* Left-justify denominator and count shift */
+ while ( (int64_t)den >= 0 ) {
+ den <<= 1;
+ qbit <<= 1;
+ }
+
+ while ( qbit ) {
+ if ( den <= num ) {
+ num -= den;
+ quot += qbit;
+ }
+ den >>= 1;
+ qbit >>= 1;
+ }
+
+ if ( rem_p )
+ *rem_p = num;
+
+ return quot;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/libgcc/__umoddi3.c b/src/VBox/Devices/PC/ipxe/src/libgcc/__umoddi3.c
new file mode 100644
index 00000000..fb4da991
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/libgcc/__umoddi3.c
@@ -0,0 +1,13 @@
+/*
+ * arch/i386/libgcc/__umoddi3.c
+ */
+
+#include "libgcc.h"
+
+__libgcc uint64_t __umoddi3(uint64_t num, uint64_t den)
+{
+ uint64_t v;
+
+ (void) __udivmoddi4(num, den, &v);
+ return v;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/libgcc/icc.c b/src/VBox/Devices/PC/ipxe/src/libgcc/icc.c
new file mode 100644
index 00000000..2f7f605c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/libgcc/icc.c
@@ -0,0 +1,8 @@
+/*
+ * Intel's compiler creates an implicit call to this function at the
+ * start of main().
+ *
+ */
+void __libgcc __intel_new_proc_init ( void ) {
+ /* Do nothing */
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/libgcc/libgcc.h b/src/VBox/Devices/PC/ipxe/src/libgcc/libgcc.h
new file mode 100644
index 00000000..d3e9bdd7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/libgcc/libgcc.h
@@ -0,0 +1,14 @@
+#ifndef _LIBGCC_H
+#define _LIBGCC_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+extern __libgcc uint64_t __udivmoddi4 ( uint64_t num, uint64_t den,
+ uint64_t *rem );
+extern __libgcc uint64_t __udivdi3 (uint64_t num, uint64_t den );
+extern __libgcc uint64_t __umoddi3 ( uint64_t num, uint64_t den );
+extern __libgcc int64_t __divdi3 ( int64_t num, int64_t den );
+extern __libgcc int64_t __moddi3 ( int64_t num, int64_t den );
+
+#endif /* _LIBGCC_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/libgcc/memcpy.c b/src/VBox/Devices/PC/ipxe/src/libgcc/memcpy.c
new file mode 100644
index 00000000..e98b7838
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/libgcc/memcpy.c
@@ -0,0 +1,18 @@
+/** @file
+ *
+ * gcc sometimes likes to insert implicit calls to memcpy().
+ * Unfortunately, there doesn't seem to be any way to prevent it from
+ * doing this, or to force it to use the optimised memcpy() as seen by
+ * C code; it insists on inserting a symbol reference to "memcpy". We
+ * therefore include wrapper functions just to keep gcc happy.
+ *
+ */
+
+#include <string.h>
+
+void * gcc_implicit_memcpy ( void *dest, const void *src,
+ size_t len ) asm ( "memcpy" );
+
+void * gcc_implicit_memcpy ( void *dest, const void *src, size_t len ) {
+ return memcpy ( dest, src, len );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/80211/net80211.c b/src/VBox/Devices/PC/ipxe/src/net/80211/net80211.c
new file mode 100644
index 00000000..c00363cd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/80211/net80211.c
@@ -0,0 +1,2829 @@
+/*
+ * The iPXE 802.11 MAC layer.
+ *
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <byteswap.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ipxe/settings.h>
+#include <ipxe/if_arp.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/ieee80211.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/net80211.h>
+#include <ipxe/sec80211.h>
+#include <ipxe/timer.h>
+#include <ipxe/nap.h>
+#include <ipxe/errortab.h>
+#include <ipxe/net80211_err.h>
+
+/** @file
+ *
+ * 802.11 device management
+ */
+
+/** List of 802.11 devices */
+static struct list_head net80211_devices = LIST_HEAD_INIT ( net80211_devices );
+
+/** Set of device operations that does nothing */
+static struct net80211_device_operations net80211_null_ops;
+
+/** Information associated with a received management packet
+ *
+ * This is used to keep beacon signal strengths in a parallel queue to
+ * the beacons themselves.
+ */
+struct net80211_rx_info {
+ int signal;
+ struct list_head list;
+};
+
+/** Context for a probe operation */
+struct net80211_probe_ctx {
+ /** 802.11 device to probe on */
+ struct net80211_device *dev;
+
+ /** Value of keep_mgmt before probe was started */
+ int old_keep_mgmt;
+
+ /** If scanning actively, pointer to probe packet to send */
+ struct io_buffer *probe;
+
+ /** If non-"", the ESSID to limit ourselves to */
+ const char *essid;
+
+ /** Time probe was started */
+ u32 ticks_start;
+
+ /** Time last useful beacon was received */
+ u32 ticks_beacon;
+
+ /** Time channel was last changed */
+ u32 ticks_channel;
+
+ /** Time to stay on each channel */
+ u32 hop_time;
+
+ /** Channels to hop by when changing channel */
+ int hop_step;
+
+ /** List of best beacons for each network found so far */
+ struct list_head *beacons;
+};
+
+/** Context for the association task */
+struct net80211_assoc_ctx {
+ /** Next authentication method to try using */
+ int method;
+
+ /** Time (in ticks) of the last sent association-related packet */
+ int last_packet;
+
+ /** Number of times we have tried sending it */
+ int times_tried;
+};
+
+/**
+ * Detect secure 802.11 network when security support is not available
+ *
+ * @return -ENOTSUP, always.
+ */
+__weak int sec80211_detect ( struct io_buffer *iob __unused,
+ enum net80211_security_proto *secprot __unused,
+ enum net80211_crypto_alg *crypt __unused ) {
+ return -ENOTSUP;
+}
+
+/**
+ * @defgroup net80211_netdev Network device interface functions
+ * @{
+ */
+static int net80211_netdev_open ( struct net_device *netdev );
+static void net80211_netdev_close ( struct net_device *netdev );
+static int net80211_netdev_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf );
+static void net80211_netdev_poll ( struct net_device *netdev );
+static void net80211_netdev_irq ( struct net_device *netdev, int enable );
+/** @} */
+
+/**
+ * @defgroup net80211_linklayer 802.11 link-layer protocol functions
+ * @{
+ */
+static int net80211_ll_push ( struct net_device *netdev,
+ struct io_buffer *iobuf, const void *ll_dest,
+ const void *ll_source, uint16_t net_proto );
+static int net80211_ll_pull ( struct net_device *netdev,
+ struct io_buffer *iobuf, const void **ll_dest,
+ const void **ll_source, uint16_t * net_proto,
+ unsigned int *flags );
+/** @} */
+
+/**
+ * @defgroup net80211_help 802.11 helper functions
+ * @{
+ */
+static void net80211_add_channels ( struct net80211_device *dev, int start,
+ int len, int txpower );
+static void net80211_filter_hw_channels ( struct net80211_device *dev );
+static void net80211_set_rtscts_rate ( struct net80211_device *dev );
+static int net80211_process_capab ( struct net80211_device *dev,
+ u16 capab );
+static int net80211_process_ie ( struct net80211_device *dev,
+ union ieee80211_ie *ie, void *ie_end );
+static union ieee80211_ie *
+net80211_marshal_request_info ( struct net80211_device *dev,
+ union ieee80211_ie *ie );
+/** @} */
+
+/**
+ * @defgroup net80211_assoc_ll 802.11 association handling functions
+ * @{
+ */
+static void net80211_step_associate ( struct net80211_device *dev );
+static void net80211_handle_auth ( struct net80211_device *dev,
+ struct io_buffer *iob );
+static void net80211_handle_assoc_reply ( struct net80211_device *dev,
+ struct io_buffer *iob );
+static int net80211_send_disassoc ( struct net80211_device *dev, int reason,
+ int deauth );
+static void net80211_handle_mgmt ( struct net80211_device *dev,
+ struct io_buffer *iob, int signal );
+/** @} */
+
+/**
+ * @defgroup net80211_frag 802.11 fragment handling functions
+ * @{
+ */
+static void net80211_free_frags ( struct net80211_device *dev, int fcid );
+static struct io_buffer *net80211_accum_frags ( struct net80211_device *dev,
+ int fcid, int nfrags, int size );
+static void net80211_rx_frag ( struct net80211_device *dev,
+ struct io_buffer *iob, int signal );
+/** @} */
+
+/**
+ * @defgroup net80211_settings 802.11 settings handlers
+ * @{
+ */
+static int net80211_check_settings_update ( void );
+
+/** 802.11 settings applicator
+ *
+ * When the SSID is changed, this will cause any open devices to
+ * re-associate; when the encryption key is changed, we similarly
+ * update their state.
+ */
+struct settings_applicator net80211_applicator __settings_applicator = {
+ .apply = net80211_check_settings_update,
+};
+
+/** The network name to associate with
+ *
+ * If this is blank, we scan for all networks and use the one with the
+ * greatest signal strength.
+ */
+struct setting net80211_ssid_setting __setting ( SETTING_NETDEV_EXTRA ) = {
+ .name = "ssid",
+ .description = "Wireless SSID",
+ .type = &setting_type_string,
+ .tag = NET80211_SETTING_TAG_SSID,
+};
+
+/** Whether to use active scanning
+ *
+ * In order to associate with a hidden SSID, it's necessary to use an
+ * active scan (send probe packets). If this setting is nonzero, an
+ * active scan on the 2.4GHz band will be used to associate.
+ */
+struct setting net80211_active_setting __setting ( SETTING_NETDEV_EXTRA ) = {
+ .name = "active-scan",
+ .description = "Actively scan for wireless networks",
+ .type = &setting_type_int8,
+ .tag = NET80211_SETTING_TAG_ACTIVE_SCAN,
+};
+
+/** The cryptographic key to use
+ *
+ * For hex WEP keys, as is common, this must be entered using the
+ * normal iPXE method for entering hex settings; an ASCII string of
+ * hex characters will not behave as expected.
+ */
+struct setting net80211_key_setting __setting ( SETTING_NETDEV_EXTRA ) = {
+ .name = "key",
+ .description = "Wireless encryption key",
+ .type = &setting_type_string,
+ .tag = NET80211_SETTING_TAG_KEY,
+};
+
+/** @} */
+
+
+/* ---------- net_device wrapper ---------- */
+
+/**
+ * Open 802.11 device and start association
+ *
+ * @v netdev Wrapping network device
+ * @ret rc Return status code
+ *
+ * This sets up a default conservative set of channels for probing,
+ * and starts the auto-association task unless the @c
+ * NET80211_NO_ASSOC flag is set in the wrapped 802.11 device's @c
+ * state field.
+ */
+static int net80211_netdev_open ( struct net_device *netdev )
+{
+ struct net80211_device *dev = netdev->priv;
+ int rc = 0;
+
+ if ( dev->op == &net80211_null_ops )
+ return -EFAULT;
+
+ if ( dev->op->open )
+ rc = dev->op->open ( dev );
+
+ if ( rc < 0 )
+ return rc;
+
+ if ( ! ( dev->state & NET80211_NO_ASSOC ) )
+ net80211_autoassociate ( dev );
+
+ return 0;
+}
+
+/**
+ * Close 802.11 device
+ *
+ * @v netdev Wrapping network device.
+ *
+ * If the association task is running, this will stop it.
+ */
+static void net80211_netdev_close ( struct net_device *netdev )
+{
+ struct net80211_device *dev = netdev->priv;
+
+ if ( dev->state & NET80211_WORKING )
+ process_del ( &dev->proc_assoc );
+
+ /* Send disassociation frame to AP, to be polite */
+ if ( dev->state & NET80211_ASSOCIATED )
+ net80211_send_disassoc ( dev, IEEE80211_REASON_LEAVING, 0 );
+
+ if ( dev->handshaker && dev->handshaker->stop &&
+ dev->handshaker->started )
+ dev->handshaker->stop ( dev );
+
+ free ( dev->crypto );
+ free ( dev->handshaker );
+ dev->crypto = NULL;
+ dev->handshaker = NULL;
+
+ netdev_link_down ( netdev );
+ dev->state = 0;
+
+ if ( dev->op->close )
+ dev->op->close ( dev );
+}
+
+/**
+ * Transmit packet on 802.11 device
+ *
+ * @v netdev Wrapping network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * If encryption is enabled for the currently associated network, the
+ * packet will be encrypted prior to transmission.
+ */
+static int net80211_netdev_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf )
+{
+ struct net80211_device *dev = netdev->priv;
+ struct ieee80211_frame *hdr = iobuf->data;
+ int rc = -ENOSYS;
+
+ if ( dev->crypto && ! ( hdr->fc & IEEE80211_FC_PROTECTED ) &&
+ ( ( hdr->fc & IEEE80211_FC_TYPE ) == IEEE80211_TYPE_DATA ) ) {
+ struct io_buffer *niob = dev->crypto->encrypt ( dev->crypto,
+ iobuf );
+ if ( ! niob )
+ return -ENOMEM; /* only reason encryption could fail */
+
+ /* Free the non-encrypted iob */
+ netdev_tx_complete ( netdev, iobuf );
+
+ /* Transmit the encrypted iob; the Protected flag is
+ set, so we won't recurse into here again */
+ netdev_tx ( netdev, niob );
+
+ /* Don't transmit the freed packet */
+ return 0;
+ }
+
+ if ( dev->op->transmit )
+ rc = dev->op->transmit ( dev, iobuf );
+
+ return rc;
+}
+
+/**
+ * Poll 802.11 device for received packets and completed transmissions
+ *
+ * @v netdev Wrapping network device
+ */
+static void net80211_netdev_poll ( struct net_device *netdev )
+{
+ struct net80211_device *dev = netdev->priv;
+
+ if ( dev->op->poll )
+ dev->op->poll ( dev );
+}
+
+/**
+ * Enable or disable interrupts for 802.11 device
+ *
+ * @v netdev Wrapping network device
+ * @v enable Whether to enable interrupts
+ */
+static void net80211_netdev_irq ( struct net_device *netdev, int enable )
+{
+ struct net80211_device *dev = netdev->priv;
+
+ if ( dev->op->irq )
+ dev->op->irq ( dev, enable );
+}
+
+/** Network device operations for a wrapped 802.11 device */
+static struct net_device_operations net80211_netdev_ops = {
+ .open = net80211_netdev_open,
+ .close = net80211_netdev_close,
+ .transmit = net80211_netdev_transmit,
+ .poll = net80211_netdev_poll,
+ .irq = net80211_netdev_irq,
+};
+
+
+/* ---------- 802.11 link-layer protocol ---------- */
+
+/** 802.11 broadcast MAC address */
+static u8 net80211_ll_broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+/**
+ * Determine whether a transmission rate uses ERP/OFDM
+ *
+ * @v rate Rate in 100 kbps units
+ * @ret is_erp TRUE if the rate is an ERP/OFDM rate
+ *
+ * 802.11b supports rates of 1.0, 2.0, 5.5, and 11.0 Mbps; any other
+ * rate than these on the 2.4GHz spectrum is an ERP (802.11g) rate.
+ */
+static inline int net80211_rate_is_erp ( u16 rate )
+{
+ if ( rate == 10 || rate == 20 || rate == 55 || rate == 110 )
+ return 0;
+ return 1;
+}
+
+
+/**
+ * Calculate one frame's contribution to 802.11 duration field
+ *
+ * @v dev 802.11 device
+ * @v bytes Amount of data to calculate duration for
+ * @ret dur Duration field in microseconds
+ *
+ * To avoid multiple stations attempting to transmit at once, 802.11
+ * provides that every packet shall include a duration field
+ * specifying a length of time for which the wireless medium will be
+ * reserved after it is transmitted. The duration is measured in
+ * microseconds and is calculated with respect to the current
+ * physical-layer parameters of the 802.11 device.
+ *
+ * For an unfragmented data or management frame, or the last fragment
+ * of a fragmented frame, the duration captures only the 10 data bytes
+ * of one ACK; call once with bytes = 10.
+ *
+ * For a fragment of a data or management rame that will be followed
+ * by more fragments, the duration captures an ACK, the following
+ * fragment, and its ACK; add the results of three calls, two with
+ * bytes = 10 and one with bytes set to the next fragment's size.
+ *
+ * For an RTS control frame, the duration captures the responding CTS,
+ * the frame being sent, and its ACK; add the results of three calls,
+ * two with bytes = 10 and one with bytes set to the next frame's size
+ * (assuming unfragmented).
+ *
+ * For a CTS-to-self control frame, the duration captures the frame
+ * being protected and its ACK; add the results of two calls, one with
+ * bytes = 10 and one with bytes set to the next frame's size.
+ *
+ * No other frame types are currently supported by iPXE.
+ */
+u16 net80211_duration ( struct net80211_device *dev, int bytes, u16 rate )
+{
+ struct net80211_channel *chan = &dev->channels[dev->channel];
+ u32 kbps = rate * 100;
+
+ if ( chan->band == NET80211_BAND_5GHZ || net80211_rate_is_erp ( rate ) ) {
+ /* OFDM encoding (802.11a/g) */
+ int bits_per_symbol = ( kbps * 4 ) / 1000; /* 4us/symbol */
+ int bits = 22 + ( bytes << 3 ); /* 22-bit PLCP */
+ int symbols = ( bits + bits_per_symbol - 1 ) / bits_per_symbol;
+
+ return 16 + 20 + ( symbols * 4 ); /* 16us SIFS, 20us preamble */
+ } else {
+ /* CCK encoding (802.11b) */
+ int phy_time = 144 + 48; /* preamble + PLCP */
+ int bits = bytes << 3;
+ int data_time = ( bits * 1000 + kbps - 1 ) / kbps;
+
+ if ( dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE )
+ phy_time >>= 1;
+
+ return 10 + phy_time + data_time; /* 10us SIFS */
+ }
+}
+
+/**
+ * Add 802.11 link-layer header
+ *
+ * @v netdev Wrapping network device
+ * @v iobuf I/O buffer
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer source address
+ * @v net_proto Network-layer protocol, in network byte order
+ * @ret rc Return status code
+ *
+ * This adds both the 802.11 frame header and the 802.2 LLC/SNAP
+ * header used on data packets.
+ *
+ * We also check here for state of the link that would make it invalid
+ * to send a data packet; every data packet must pass through here,
+ * and no non-data packet (e.g. management frame) should.
+ */
+static int net80211_ll_push ( struct net_device *netdev,
+ struct io_buffer *iobuf, const void *ll_dest,
+ const void *ll_source, uint16_t net_proto )
+{
+ struct net80211_device *dev = netdev->priv;
+ struct ieee80211_frame *hdr = iob_push ( iobuf,
+ IEEE80211_LLC_HEADER_LEN +
+ IEEE80211_TYP_FRAME_HEADER_LEN );
+ struct ieee80211_llc_snap_header *lhdr =
+ ( void * ) hdr + IEEE80211_TYP_FRAME_HEADER_LEN;
+
+ /* We can't send data packets if we're not associated. */
+ if ( ! ( dev->state & NET80211_ASSOCIATED ) ) {
+ if ( dev->assoc_rc )
+ return dev->assoc_rc;
+ return -ENETUNREACH;
+ }
+
+ hdr->fc = IEEE80211_THIS_VERSION | IEEE80211_TYPE_DATA |
+ IEEE80211_STYPE_DATA | IEEE80211_FC_TODS;
+
+ /* We don't send fragmented frames, so duration is the time
+ for an SIFS + 10-byte ACK. */
+ hdr->duration = net80211_duration ( dev, 10, dev->rates[dev->rate] );
+
+ memcpy ( hdr->addr1, dev->bssid, ETH_ALEN );
+ memcpy ( hdr->addr2, ll_source, ETH_ALEN );
+ memcpy ( hdr->addr3, ll_dest, ETH_ALEN );
+
+ hdr->seq = IEEE80211_MAKESEQ ( ++dev->last_tx_seqnr, 0 );
+
+ lhdr->dsap = IEEE80211_LLC_DSAP;
+ lhdr->ssap = IEEE80211_LLC_SSAP;
+ lhdr->ctrl = IEEE80211_LLC_CTRL;
+ memset ( lhdr->oui, 0x00, 3 );
+ lhdr->ethertype = net_proto;
+
+ return 0;
+}
+
+/**
+ * Remove 802.11 link-layer header
+ *
+ * @v netdev Wrapping network device
+ * @v iobuf I/O buffer
+ * @ret ll_dest Link-layer destination address
+ * @ret ll_source Link-layer source
+ * @ret net_proto Network-layer protocol, in network byte order
+ * @ret flags Packet flags
+ * @ret rc Return status code
+ *
+ * This expects and removes both the 802.11 frame header and the 802.2
+ * LLC/SNAP header that are used on data packets.
+ */
+static int net80211_ll_pull ( struct net_device *netdev __unused,
+ struct io_buffer *iobuf,
+ const void **ll_dest, const void **ll_source,
+ uint16_t * net_proto, unsigned int *flags )
+{
+ struct ieee80211_frame *hdr = iobuf->data;
+ struct ieee80211_llc_snap_header *lhdr =
+ ( void * ) hdr + IEEE80211_TYP_FRAME_HEADER_LEN;
+
+ /* Bunch of sanity checks */
+ if ( iob_len ( iobuf ) < IEEE80211_TYP_FRAME_HEADER_LEN +
+ IEEE80211_LLC_HEADER_LEN ) {
+ DBGC ( netdev->priv, "802.11 %p packet too short (%zd bytes)\n",
+ netdev->priv, iob_len ( iobuf ) );
+ return -EINVAL_PKT_TOO_SHORT;
+ }
+
+ if ( ( hdr->fc & IEEE80211_FC_VERSION ) != IEEE80211_THIS_VERSION ) {
+ DBGC ( netdev->priv, "802.11 %p packet invalid version %04x\n",
+ netdev->priv, hdr->fc & IEEE80211_FC_VERSION );
+ return -EINVAL_PKT_VERSION;
+ }
+
+ if ( ( hdr->fc & IEEE80211_FC_TYPE ) != IEEE80211_TYPE_DATA ||
+ ( hdr->fc & IEEE80211_FC_SUBTYPE ) != IEEE80211_STYPE_DATA ) {
+ DBGC ( netdev->priv, "802.11 %p packet not data/data (fc=%04x)\n",
+ netdev->priv, hdr->fc );
+ return -EINVAL_PKT_NOT_DATA;
+ }
+
+ if ( ( hdr->fc & ( IEEE80211_FC_TODS | IEEE80211_FC_FROMDS ) ) !=
+ IEEE80211_FC_FROMDS ) {
+ DBGC ( netdev->priv, "802.11 %p packet not from DS (fc=%04x)\n",
+ netdev->priv, hdr->fc );
+ return -EINVAL_PKT_NOT_FROMDS;
+ }
+
+ if ( lhdr->dsap != IEEE80211_LLC_DSAP || lhdr->ssap != IEEE80211_LLC_SSAP ||
+ lhdr->ctrl != IEEE80211_LLC_CTRL || lhdr->oui[0] || lhdr->oui[1] ||
+ lhdr->oui[2] ) {
+ DBGC ( netdev->priv, "802.11 %p LLC header is not plain EtherType "
+ "encapsulator: %02x->%02x [%02x] %02x:%02x:%02x %04x\n",
+ netdev->priv, lhdr->dsap, lhdr->ssap, lhdr->ctrl,
+ lhdr->oui[0], lhdr->oui[1], lhdr->oui[2], lhdr->ethertype );
+ return -EINVAL_PKT_LLC_HEADER;
+ }
+
+ iob_pull ( iobuf, sizeof ( *hdr ) + sizeof ( *lhdr ) );
+
+ *ll_dest = hdr->addr1;
+ *ll_source = hdr->addr3;
+ *net_proto = lhdr->ethertype;
+ *flags = ( ( is_multicast_ether_addr ( hdr->addr1 ) ?
+ LL_MULTICAST : 0 ) |
+ ( is_broadcast_ether_addr ( hdr->addr1 ) ?
+ LL_BROADCAST : 0 ) );
+ return 0;
+}
+
+/** 802.11 link-layer protocol */
+static struct ll_protocol net80211_ll_protocol __ll_protocol = {
+ .name = "802.11",
+ .push = net80211_ll_push,
+ .pull = net80211_ll_pull,
+ .init_addr = eth_init_addr,
+ .ntoa = eth_ntoa,
+ .mc_hash = eth_mc_hash,
+ .eth_addr = eth_eth_addr,
+ .ll_proto = htons ( ARPHRD_ETHER ), /* "encapsulated Ethernet" */
+ .hw_addr_len = ETH_ALEN,
+ .ll_addr_len = ETH_ALEN,
+ .ll_header_len = IEEE80211_TYP_FRAME_HEADER_LEN +
+ IEEE80211_LLC_HEADER_LEN,
+};
+
+
+/* ---------- 802.11 network management API ---------- */
+
+/**
+ * Get 802.11 device from wrapping network device
+ *
+ * @v netdev Wrapping network device
+ * @ret dev 802.11 device wrapped by network device, or NULL
+ *
+ * Returns NULL if the network device does not wrap an 802.11 device.
+ */
+struct net80211_device * net80211_get ( struct net_device *netdev )
+{
+ struct net80211_device *dev;
+
+ list_for_each_entry ( dev, &net80211_devices, list ) {
+ if ( netdev->priv == dev )
+ return netdev->priv;
+ }
+
+ return NULL;
+}
+
+/**
+ * Set state of 802.11 device keeping management frames
+ *
+ * @v dev 802.11 device
+ * @v enable Whether to keep management frames
+ * @ret oldenab Whether management frames were enabled before this call
+ *
+ * If enable is TRUE, beacon, probe, and action frames will be kept
+ * and may be retrieved by calling net80211_mgmt_dequeue().
+ */
+int net80211_keep_mgmt ( struct net80211_device *dev, int enable )
+{
+ int oldenab = dev->keep_mgmt;
+
+ dev->keep_mgmt = enable;
+ return oldenab;
+}
+
+/**
+ * Get 802.11 management frame
+ *
+ * @v dev 802.11 device
+ * @ret signal Signal strength of returned management frame
+ * @ret iob I/O buffer, or NULL if no management frame is queued
+ *
+ * Frames will only be returned by this function if
+ * net80211_keep_mgmt() has been previously called with enable set to
+ * TRUE.
+ *
+ * The calling function takes ownership of the returned I/O buffer.
+ */
+struct io_buffer * net80211_mgmt_dequeue ( struct net80211_device *dev,
+ int *signal )
+{
+ struct io_buffer *iobuf;
+ struct net80211_rx_info *rxi;
+
+ list_for_each_entry ( rxi, &dev->mgmt_info_queue, list ) {
+ list_del ( &rxi->list );
+ if ( signal )
+ *signal = rxi->signal;
+ free ( rxi );
+
+ assert ( ! list_empty ( &dev->mgmt_queue ) );
+ iobuf = list_first_entry ( &dev->mgmt_queue, struct io_buffer,
+ list );
+ list_del ( &iobuf->list );
+ return iobuf;
+ }
+
+ return NULL;
+}
+
+/**
+ * Transmit 802.11 management frame
+ *
+ * @v dev 802.11 device
+ * @v fc Frame Control flags for management frame
+ * @v dest Destination access point
+ * @v iob I/O buffer
+ * @ret rc Return status code
+ *
+ * The @a fc argument must contain at least an IEEE 802.11 management
+ * subtype number (e.g. IEEE80211_STYPE_PROBE_REQ). If it contains
+ * IEEE80211_FC_PROTECTED, the frame will be encrypted prior to
+ * transmission.
+ *
+ * It is required that @a iob have at least 24 bytes of headroom
+ * reserved before its data start.
+ */
+int net80211_tx_mgmt ( struct net80211_device *dev, u16 fc, u8 dest[6],
+ struct io_buffer *iob )
+{
+ struct ieee80211_frame *hdr = iob_push ( iob,
+ IEEE80211_TYP_FRAME_HEADER_LEN );
+
+ hdr->fc = IEEE80211_THIS_VERSION | IEEE80211_TYPE_MGMT |
+ ( fc & ~IEEE80211_FC_PROTECTED );
+ hdr->duration = net80211_duration ( dev, 10, dev->rates[dev->rate] );
+ hdr->seq = IEEE80211_MAKESEQ ( ++dev->last_tx_seqnr, 0 );
+
+ memcpy ( hdr->addr1, dest, ETH_ALEN ); /* DA = RA */
+ memcpy ( hdr->addr2, dev->netdev->ll_addr, ETH_ALEN ); /* SA = TA */
+ memcpy ( hdr->addr3, dest, ETH_ALEN ); /* BSSID */
+
+ if ( fc & IEEE80211_FC_PROTECTED ) {
+ if ( ! dev->crypto )
+ return -EINVAL_CRYPTO_REQUEST;
+
+ struct io_buffer *eiob = dev->crypto->encrypt ( dev->crypto,
+ iob );
+ free_iob ( iob );
+ iob = eiob;
+ }
+
+ return netdev_tx ( dev->netdev, iob );
+}
+
+
+/* ---------- Driver API ---------- */
+
+/** 802.11 association process descriptor */
+static struct process_descriptor net80211_process_desc =
+ PROC_DESC ( struct net80211_device, proc_assoc,
+ net80211_step_associate );
+
+/**
+ * Allocate 802.11 device
+ *
+ * @v priv_size Size of driver-private allocation area
+ * @ret dev Newly allocated 802.11 device
+ *
+ * This function allocates a net_device with space in its private area
+ * for both the net80211_device it will wrap and the driver-private
+ * data space requested. It initializes the link-layer-specific parts
+ * of the net_device, and links the net80211_device to the net_device
+ * appropriately.
+ */
+struct net80211_device * net80211_alloc ( size_t priv_size )
+{
+ struct net80211_device *dev;
+ struct net_device *netdev =
+ alloc_netdev ( sizeof ( *dev ) + priv_size );
+
+ if ( ! netdev )
+ return NULL;
+
+ netdev->ll_protocol = &net80211_ll_protocol;
+ netdev->ll_broadcast = net80211_ll_broadcast;
+ netdev->max_pkt_len = IEEE80211_MAX_DATA_LEN;
+ netdev_init ( netdev, &net80211_netdev_ops );
+
+ dev = netdev->priv;
+ dev->netdev = netdev;
+ dev->priv = ( u8 * ) dev + sizeof ( *dev );
+ dev->op = &net80211_null_ops;
+
+ process_init_stopped ( &dev->proc_assoc, &net80211_process_desc,
+ &netdev->refcnt );
+ INIT_LIST_HEAD ( &dev->mgmt_queue );
+ INIT_LIST_HEAD ( &dev->mgmt_info_queue );
+
+ return dev;
+}
+
+/**
+ * Register 802.11 device with network stack
+ *
+ * @v dev 802.11 device
+ * @v ops 802.11 device operations
+ * @v hw 802.11 hardware information
+ *
+ * This also registers the wrapping net_device with the higher network
+ * layers.
+ */
+int net80211_register ( struct net80211_device *dev,
+ struct net80211_device_operations *ops,
+ struct net80211_hw_info *hw )
+{
+ dev->op = ops;
+ dev->hw = malloc ( sizeof ( *hw ) );
+ if ( ! dev->hw )
+ return -ENOMEM;
+
+ memcpy ( dev->hw, hw, sizeof ( *hw ) );
+ memcpy ( dev->netdev->hw_addr, hw->hwaddr, ETH_ALEN );
+
+ /* Set some sensible channel defaults for driver's open() function */
+ memcpy ( dev->channels, dev->hw->channels,
+ NET80211_MAX_CHANNELS * sizeof ( dev->channels[0] ) );
+ dev->channel = 0;
+
+ list_add_tail ( &dev->list, &net80211_devices );
+ return register_netdev ( dev->netdev );
+}
+
+/**
+ * Unregister 802.11 device from network stack
+ *
+ * @v dev 802.11 device
+ *
+ * After this call, the device operations are cleared so that they
+ * will not be called.
+ */
+void net80211_unregister ( struct net80211_device *dev )
+{
+ unregister_netdev ( dev->netdev );
+ list_del ( &dev->list );
+ dev->op = &net80211_null_ops;
+}
+
+/**
+ * Free 802.11 device
+ *
+ * @v dev 802.11 device
+ *
+ * The device should be unregistered before this function is called.
+ */
+void net80211_free ( struct net80211_device *dev )
+{
+ free ( dev->hw );
+ rc80211_free ( dev->rctl );
+ netdev_nullify ( dev->netdev );
+ netdev_put ( dev->netdev );
+}
+
+
+/* ---------- 802.11 network management workhorse code ---------- */
+
+/**
+ * Set state of 802.11 device
+ *
+ * @v dev 802.11 device
+ * @v clear Bitmask of flags to clear
+ * @v set Bitmask of flags to set
+ * @v status Status or reason code for most recent operation
+ *
+ * If @a status represents a reason code, it should be OR'ed with
+ * NET80211_IS_REASON.
+ *
+ * Clearing authentication also clears association; clearing
+ * association also clears security handshaking state. Clearing
+ * association removes the link-up flag from the wrapping net_device,
+ * but setting it does not automatically set the flag; that is left to
+ * the judgment of higher-level code.
+ */
+static inline void net80211_set_state ( struct net80211_device *dev,
+ short clear, short set,
+ u16 status )
+{
+ /* The conditions in this function are deliberately formulated
+ to be decidable at compile-time in most cases. Since clear
+ and set are generally passed as constants, the body of this
+ function can be reduced down to a few statements by the
+ compiler. */
+
+ const int statmsk = NET80211_STATUS_MASK | NET80211_IS_REASON;
+
+ if ( clear & NET80211_PROBED )
+ clear |= NET80211_AUTHENTICATED;
+
+ if ( clear & NET80211_AUTHENTICATED )
+ clear |= NET80211_ASSOCIATED;
+
+ if ( clear & NET80211_ASSOCIATED )
+ clear |= NET80211_CRYPTO_SYNCED;
+
+ dev->state = ( dev->state & ~clear ) | set;
+ dev->state = ( dev->state & ~statmsk ) | ( status & statmsk );
+
+ if ( clear & NET80211_ASSOCIATED )
+ netdev_link_down ( dev->netdev );
+
+ if ( ( clear | set ) & NET80211_ASSOCIATED )
+ dev->op->config ( dev, NET80211_CFG_ASSOC );
+
+ if ( status != 0 ) {
+ if ( status & NET80211_IS_REASON )
+ dev->assoc_rc = -E80211_REASON ( status );
+ else
+ dev->assoc_rc = -E80211_STATUS ( status );
+ netdev_link_err ( dev->netdev, dev->assoc_rc );
+ }
+}
+
+/**
+ * Add channels to 802.11 device
+ *
+ * @v dev 802.11 device
+ * @v start First channel number to add
+ * @v len Number of channels to add
+ * @v txpower TX power (dBm) to allow on added channels
+ *
+ * To replace the current list of channels instead of adding to it,
+ * set the nr_channels field of the 802.11 device to 0 before calling
+ * this function.
+ */
+static void net80211_add_channels ( struct net80211_device *dev, int start,
+ int len, int txpower )
+{
+ int i, chan = start;
+
+ for ( i = dev->nr_channels; len-- && i < NET80211_MAX_CHANNELS; i++ ) {
+ dev->channels[i].channel_nr = chan;
+ dev->channels[i].maxpower = txpower;
+ dev->channels[i].hw_value = 0;
+
+ if ( chan >= 1 && chan <= 14 ) {
+ dev->channels[i].band = NET80211_BAND_2GHZ;
+ if ( chan == 14 )
+ dev->channels[i].center_freq = 2484;
+ else
+ dev->channels[i].center_freq = 2407 + 5 * chan;
+ chan++;
+ } else {
+ dev->channels[i].band = NET80211_BAND_5GHZ;
+ dev->channels[i].center_freq = 5000 + 5 * chan;
+ chan += 4;
+ }
+ }
+
+ dev->nr_channels = i;
+}
+
+/**
+ * Filter 802.11 device channels for hardware capabilities
+ *
+ * @v dev 802.11 device
+ *
+ * Hardware may support fewer channels than regulatory restrictions
+ * allow; this function filters out channels in dev->channels that are
+ * not supported by the hardware list in dev->hwinfo. It also copies
+ * over the net80211_channel::hw_value and limits maximum TX power
+ * appropriately.
+ *
+ * Channels are matched based on center frequency, ignoring band and
+ * channel number.
+ *
+ * If the driver specifies no supported channels, the effect will be
+ * as though all were supported.
+ */
+static void net80211_filter_hw_channels ( struct net80211_device *dev )
+{
+ int delta = 0, i = 0;
+ int old_freq = dev->channels[dev->channel].center_freq;
+ struct net80211_channel *chan, *hwchan;
+
+ if ( ! dev->hw->nr_channels )
+ return;
+
+ dev->channel = 0;
+ for ( chan = dev->channels; chan < dev->channels + dev->nr_channels;
+ chan++, i++ ) {
+ int ok = 0;
+ for ( hwchan = dev->hw->channels;
+ hwchan < dev->hw->channels + dev->hw->nr_channels;
+ hwchan++ ) {
+ if ( hwchan->center_freq == chan->center_freq ) {
+ ok = 1;
+ break;
+ }
+ }
+
+ if ( ! ok )
+ delta++;
+ else {
+ chan->hw_value = hwchan->hw_value;
+ if ( hwchan->maxpower != 0 &&
+ chan->maxpower > hwchan->maxpower )
+ chan->maxpower = hwchan->maxpower;
+ if ( old_freq == chan->center_freq )
+ dev->channel = i - delta;
+ if ( delta )
+ chan[-delta] = *chan;
+ }
+ }
+
+ dev->nr_channels -= delta;
+
+ if ( dev->channels[dev->channel].center_freq != old_freq )
+ dev->op->config ( dev, NET80211_CFG_CHANNEL );
+}
+
+/**
+ * Update 802.11 device state to reflect received capabilities field
+ *
+ * @v dev 802.11 device
+ * @v capab Capabilities field in beacon, probe, or association frame
+ * @ret rc Return status code
+ */
+static int net80211_process_capab ( struct net80211_device *dev,
+ u16 capab )
+{
+ u16 old_phy = dev->phy_flags;
+
+ if ( ( capab & ( IEEE80211_CAPAB_MANAGED | IEEE80211_CAPAB_ADHOC ) ) !=
+ IEEE80211_CAPAB_MANAGED ) {
+ DBGC ( dev, "802.11 %p cannot handle IBSS network\n", dev );
+ return -ENOSYS;
+ }
+
+ dev->phy_flags &= ~( NET80211_PHY_USE_SHORT_PREAMBLE |
+ NET80211_PHY_USE_SHORT_SLOT );
+
+ if ( capab & IEEE80211_CAPAB_SHORT_PMBL )
+ dev->phy_flags |= NET80211_PHY_USE_SHORT_PREAMBLE;
+
+ if ( capab & IEEE80211_CAPAB_SHORT_SLOT )
+ dev->phy_flags |= NET80211_PHY_USE_SHORT_SLOT;
+
+ if ( old_phy != dev->phy_flags )
+ dev->op->config ( dev, NET80211_CFG_PHY_PARAMS );
+
+ return 0;
+}
+
+/**
+ * Update 802.11 device state to reflect received information elements
+ *
+ * @v dev 802.11 device
+ * @v ie Pointer to first information element
+ * @v ie_end Pointer to tail of packet I/O buffer
+ * @ret rc Return status code
+ */
+static int net80211_process_ie ( struct net80211_device *dev,
+ union ieee80211_ie *ie, void *ie_end )
+{
+ u16 old_rate = dev->rates[dev->rate];
+ u16 old_phy = dev->phy_flags;
+ int have_rates = 0, i;
+ int ds_channel = 0;
+ int changed = 0;
+ int band = dev->channels[dev->channel].band;
+
+ if ( ! ieee80211_ie_bound ( ie, ie_end ) )
+ return 0;
+
+ for ( ; ie; ie = ieee80211_next_ie ( ie, ie_end ) ) {
+ switch ( ie->id ) {
+ case IEEE80211_IE_SSID:
+ if ( ie->len <= 32 ) {
+ memcpy ( dev->essid, ie->ssid, ie->len );
+ dev->essid[ie->len] = 0;
+ }
+ break;
+
+ case IEEE80211_IE_RATES:
+ case IEEE80211_IE_EXT_RATES:
+ if ( ! have_rates ) {
+ dev->nr_rates = 0;
+ dev->basic_rates = 0;
+ have_rates = 1;
+ }
+ for ( i = 0; i < ie->len &&
+ dev->nr_rates < NET80211_MAX_RATES; i++ ) {
+ u8 rid = ie->rates[i];
+ u16 rate = ( rid & 0x7f ) * 5;
+
+ if ( rid & 0x80 )
+ dev->basic_rates |=
+ ( 1 << dev->nr_rates );
+
+ dev->rates[dev->nr_rates++] = rate;
+ }
+
+ break;
+
+ case IEEE80211_IE_DS_PARAM:
+ if ( dev->channel < dev->nr_channels && ds_channel ==
+ dev->channels[dev->channel].channel_nr )
+ break;
+ ds_channel = ie->ds_param.current_channel;
+ net80211_change_channel ( dev, ds_channel );
+ break;
+
+ case IEEE80211_IE_COUNTRY:
+ dev->nr_channels = 0;
+
+ DBGC ( dev, "802.11 %p setting country regulations "
+ "for %c%c\n", dev, ie->country.name[0],
+ ie->country.name[1] );
+ for ( i = 0; i < ( ie->len - 3 ) / 3; i++ ) {
+ union ieee80211_ie_country_triplet *t =
+ &ie->country.triplet[i];
+ if ( t->first > 200 ) {
+ DBGC ( dev, "802.11 %p ignoring regulatory "
+ "extension information\n", dev );
+ } else {
+ net80211_add_channels ( dev,
+ t->band.first_channel,
+ t->band.nr_channels,
+ t->band.max_txpower );
+ }
+ }
+ net80211_filter_hw_channels ( dev );
+ break;
+
+ case IEEE80211_IE_ERP_INFO:
+ dev->phy_flags &= ~( NET80211_PHY_USE_PROTECTION |
+ NET80211_PHY_USE_SHORT_PREAMBLE );
+ if ( ie->erp_info & IEEE80211_ERP_USE_PROTECTION )
+ dev->phy_flags |= NET80211_PHY_USE_PROTECTION;
+ if ( ! ( ie->erp_info & IEEE80211_ERP_BARKER_LONG ) )
+ dev->phy_flags |= NET80211_PHY_USE_SHORT_PREAMBLE;
+ break;
+ }
+ }
+
+ if ( have_rates ) {
+ /* Allow only those rates that are also supported by
+ the hardware. */
+ int delta = 0, j;
+
+ dev->rate = 0;
+ for ( i = 0; i < dev->nr_rates; i++ ) {
+ int ok = 0;
+ for ( j = 0; j < dev->hw->nr_rates[band]; j++ ) {
+ if ( dev->hw->rates[band][j] == dev->rates[i] ){
+ ok = 1;
+ break;
+ }
+ }
+
+ if ( ! ok )
+ delta++;
+ else {
+ dev->rates[i - delta] = dev->rates[i];
+ if ( old_rate == dev->rates[i] )
+ dev->rate = i - delta;
+ }
+ }
+
+ dev->nr_rates -= delta;
+
+ /* Sort available rates - sorted subclumps tend to already
+ exist, so insertion sort works well. */
+ for ( i = 1; i < dev->nr_rates; i++ ) {
+ u16 rate = dev->rates[i];
+ u32 tmp, br, mask;
+
+ for ( j = i - 1; j >= 0 && dev->rates[j] >= rate; j-- )
+ dev->rates[j + 1] = dev->rates[j];
+ dev->rates[j + 1] = rate;
+
+ /* Adjust basic_rates to match by rotating the
+ bits from bit j+1 to bit i left one position. */
+ mask = ( ( 1 << i ) - 1 ) & ~( ( 1 << ( j + 1 ) ) - 1 );
+ br = dev->basic_rates;
+ tmp = br & ( 1 << i );
+ br = ( br & ~( mask | tmp ) ) | ( ( br & mask ) << 1 );
+ br |= ( tmp >> ( i - j - 1 ) );
+ dev->basic_rates = br;
+ }
+
+ net80211_set_rtscts_rate ( dev );
+
+ if ( dev->rates[dev->rate] != old_rate )
+ changed |= NET80211_CFG_RATE;
+ }
+
+ if ( dev->hw->flags & NET80211_HW_NO_SHORT_PREAMBLE )
+ dev->phy_flags &= ~NET80211_PHY_USE_SHORT_PREAMBLE;
+ if ( dev->hw->flags & NET80211_HW_NO_SHORT_SLOT )
+ dev->phy_flags &= ~NET80211_PHY_USE_SHORT_SLOT;
+
+ if ( old_phy != dev->phy_flags )
+ changed |= NET80211_CFG_PHY_PARAMS;
+
+ if ( changed )
+ dev->op->config ( dev, changed );
+
+ return 0;
+}
+
+/**
+ * Create information elements for outgoing probe or association packet
+ *
+ * @v dev 802.11 device
+ * @v ie Pointer to start of information element area
+ * @ret next_ie Pointer to first byte after added information elements
+ */
+static union ieee80211_ie *
+net80211_marshal_request_info ( struct net80211_device *dev,
+ union ieee80211_ie *ie )
+{
+ int i;
+
+ ie->id = IEEE80211_IE_SSID;
+ ie->len = strlen ( dev->essid );
+ memcpy ( ie->ssid, dev->essid, ie->len );
+
+ ie = ieee80211_next_ie ( ie, NULL );
+
+ ie->id = IEEE80211_IE_RATES;
+ ie->len = dev->nr_rates;
+ if ( ie->len > 8 )
+ ie->len = 8;
+
+ for ( i = 0; i < ie->len; i++ ) {
+ ie->rates[i] = dev->rates[i] / 5;
+ if ( dev->basic_rates & ( 1 << i ) )
+ ie->rates[i] |= 0x80;
+ }
+
+ ie = ieee80211_next_ie ( ie, NULL );
+
+ if ( dev->rsn_ie && dev->rsn_ie->id == IEEE80211_IE_RSN ) {
+ memcpy ( ie, dev->rsn_ie, dev->rsn_ie->len + 2 );
+ ie = ieee80211_next_ie ( ie, NULL );
+ }
+
+ if ( dev->nr_rates > 8 ) {
+ /* 802.11 requires we use an Extended Basic Rates IE
+ for the rates beyond the eighth. */
+
+ ie->id = IEEE80211_IE_EXT_RATES;
+ ie->len = dev->nr_rates - 8;
+
+ for ( ; i < dev->nr_rates; i++ ) {
+ ie->rates[i - 8] = dev->rates[i] / 5;
+ if ( dev->basic_rates & ( 1 << i ) )
+ ie->rates[i - 8] |= 0x80;
+ }
+
+ ie = ieee80211_next_ie ( ie, NULL );
+ }
+
+ if ( dev->rsn_ie && dev->rsn_ie->id == IEEE80211_IE_VENDOR ) {
+ memcpy ( ie, dev->rsn_ie, dev->rsn_ie->len + 2 );
+ ie = ieee80211_next_ie ( ie, NULL );
+ }
+
+ return ie;
+}
+
+/** Seconds to wait after finding a network, to possibly find better APs for it
+ *
+ * This is used when a specific SSID to scan for is specified.
+ */
+#define NET80211_PROBE_GATHER 1
+
+/** Seconds to wait after finding a network, to possibly find other networks
+ *
+ * This is used when an empty SSID is specified, to scan for all
+ * networks.
+ */
+#define NET80211_PROBE_GATHER_ALL 2
+
+/** Seconds to allow a probe to take if no network has been found */
+#define NET80211_PROBE_TIMEOUT 6
+
+/**
+ * Begin probe of 802.11 networks
+ *
+ * @v dev 802.11 device
+ * @v essid SSID to probe for, or "" to accept any (may not be NULL)
+ * @v active Whether to use active scanning
+ * @ret ctx Probe context
+ *
+ * Active scanning may only be used on channels 1-11 in the 2.4GHz
+ * band, due to iPXE's lack of a complete regulatory database. If
+ * active scanning is used, probe packets will be sent on each
+ * channel; this can allow association with hidden-SSID networks if
+ * the SSID is properly specified.
+ *
+ * A @c NULL return indicates an out-of-memory condition.
+ *
+ * The returned context must be periodically passed to
+ * net80211_probe_step() until that function returns zero.
+ */
+struct net80211_probe_ctx * net80211_probe_start ( struct net80211_device *dev,
+ const char *essid,
+ int active )
+{
+ struct net80211_probe_ctx *ctx = zalloc ( sizeof ( *ctx ) );
+
+ if ( ! ctx )
+ return NULL;
+
+ assert ( netdev_is_open ( dev->netdev ) );
+
+ ctx->dev = dev;
+ ctx->old_keep_mgmt = net80211_keep_mgmt ( dev, 1 );
+ ctx->essid = essid;
+ if ( dev->essid != ctx->essid )
+ strcpy ( dev->essid, ctx->essid );
+
+ if ( active ) {
+ struct ieee80211_probe_req *probe_req;
+ union ieee80211_ie *ie;
+
+ ctx->probe = alloc_iob ( 128 );
+ iob_reserve ( ctx->probe, IEEE80211_TYP_FRAME_HEADER_LEN );
+ probe_req = ctx->probe->data;
+
+ ie = net80211_marshal_request_info ( dev,
+ probe_req->info_element );
+
+ iob_put ( ctx->probe, ( void * ) ie - ctx->probe->data );
+ }
+
+ ctx->ticks_start = currticks();
+ ctx->ticks_beacon = 0;
+ ctx->ticks_channel = currticks();
+ ctx->hop_time = ticks_per_sec() / ( active ? 2 : 6 );
+
+ /*
+ * Channels on 2.4GHz overlap, and the most commonly used
+ * are 1, 6, and 11. We'll get a result faster if we check
+ * every 5 channels, but in order to hit all of them the
+ * number of channels must be relatively prime to 5. If it's
+ * not, tweak the hop.
+ */
+ ctx->hop_step = 5;
+ while ( dev->nr_channels % ctx->hop_step == 0 && ctx->hop_step > 1 )
+ ctx->hop_step--;
+
+ ctx->beacons = malloc ( sizeof ( *ctx->beacons ) );
+ INIT_LIST_HEAD ( ctx->beacons );
+
+ dev->channel = 0;
+ dev->op->config ( dev, NET80211_CFG_CHANNEL );
+
+ return ctx;
+}
+
+/**
+ * Continue probe of 802.11 networks
+ *
+ * @v ctx Probe context returned by net80211_probe_start()
+ * @ret rc Probe status
+ *
+ * The return code will be 0 if the probe is still going on (and this
+ * function should be called again), a positive number if the probe
+ * completed successfully, or a negative error code if the probe
+ * failed for that reason.
+ *
+ * Whether the probe succeeded or failed, you must call
+ * net80211_probe_finish_all() or net80211_probe_finish_best()
+ * (depending on whether you want information on all networks or just
+ * the best-signal one) in order to release the probe context. A
+ * failed probe may still have acquired some valid data.
+ */
+int net80211_probe_step ( struct net80211_probe_ctx *ctx )
+{
+ struct net80211_device *dev = ctx->dev;
+ u32 start_timeout = NET80211_PROBE_TIMEOUT * ticks_per_sec();
+ u32 gather_timeout = ticks_per_sec();
+ u32 now = currticks();
+ struct io_buffer *iob;
+ int signal;
+ int rc;
+ char ssid[IEEE80211_MAX_SSID_LEN + 1];
+
+ gather_timeout *= ( ctx->essid[0] ? NET80211_PROBE_GATHER :
+ NET80211_PROBE_GATHER_ALL );
+
+ /* Time out if necessary */
+ if ( now >= ctx->ticks_start + start_timeout )
+ return list_empty ( ctx->beacons ) ? -ETIMEDOUT : +1;
+
+ if ( ctx->ticks_beacon > 0 && now >= ctx->ticks_start + gather_timeout )
+ return +1;
+
+ /* Change channels if necessary */
+ if ( now >= ctx->ticks_channel + ctx->hop_time ) {
+ dev->channel = ( dev->channel + ctx->hop_step )
+ % dev->nr_channels;
+ dev->op->config ( dev, NET80211_CFG_CHANNEL );
+ udelay ( dev->hw->channel_change_time );
+
+ ctx->ticks_channel = now;
+
+ if ( ctx->probe ) {
+ struct io_buffer *siob = ctx->probe; /* to send */
+
+ /* make a copy for future use */
+ iob = alloc_iob ( siob->tail - siob->head );
+ iob_reserve ( iob, iob_headroom ( siob ) );
+ memcpy ( iob_put ( iob, iob_len ( siob ) ),
+ siob->data, iob_len ( siob ) );
+
+ ctx->probe = iob;
+ rc = net80211_tx_mgmt ( dev, IEEE80211_STYPE_PROBE_REQ,
+ net80211_ll_broadcast,
+ iob_disown ( siob ) );
+ if ( rc ) {
+ DBGC ( dev, "802.11 %p send probe failed: "
+ "%s\n", dev, strerror ( rc ) );
+ return rc;
+ }
+ }
+ }
+
+ /* Check for new management packets */
+ while ( ( iob = net80211_mgmt_dequeue ( dev, &signal ) ) != NULL ) {
+ struct ieee80211_frame *hdr;
+ struct ieee80211_beacon *beacon;
+ union ieee80211_ie *ie;
+ struct net80211_wlan *wlan;
+ u16 type;
+
+ hdr = iob->data;
+ type = hdr->fc & IEEE80211_FC_SUBTYPE;
+ beacon = ( struct ieee80211_beacon * ) hdr->data;
+
+ if ( type != IEEE80211_STYPE_BEACON &&
+ type != IEEE80211_STYPE_PROBE_RESP ) {
+ DBGC2 ( dev, "802.11 %p probe: non-beacon\n", dev );
+ goto drop;
+ }
+
+ if ( ( void * ) beacon->info_element >= iob->tail ) {
+ DBGC ( dev, "802.11 %p probe: beacon with no IEs\n",
+ dev );
+ goto drop;
+ }
+
+ ie = beacon->info_element;
+
+ if ( ! ieee80211_ie_bound ( ie, iob->tail ) )
+ ie = NULL;
+
+ while ( ie && ie->id != IEEE80211_IE_SSID )
+ ie = ieee80211_next_ie ( ie, iob->tail );
+
+ if ( ! ie ) {
+ DBGC ( dev, "802.11 %p probe: beacon with no SSID\n",
+ dev );
+ goto drop;
+ }
+
+ memcpy ( ssid, ie->ssid, ie->len );
+ ssid[ie->len] = 0;
+
+ if ( ctx->essid[0] && strcmp ( ctx->essid, ssid ) != 0 ) {
+ DBGC2 ( dev, "802.11 %p probe: beacon with wrong SSID "
+ "(%s)\n", dev, ssid );
+ goto drop;
+ }
+
+ /* See if we've got an entry for this network */
+ list_for_each_entry ( wlan, ctx->beacons, list ) {
+ if ( strcmp ( wlan->essid, ssid ) != 0 )
+ continue;
+
+ if ( signal < wlan->signal ) {
+ DBGC2 ( dev, "802.11 %p probe: beacon for %s "
+ "(%s) with weaker signal %d\n", dev,
+ ssid, eth_ntoa ( hdr->addr3 ), signal );
+ goto drop;
+ }
+
+ goto fill;
+ }
+
+ /* No entry yet - make one */
+ wlan = zalloc ( sizeof ( *wlan ) );
+ strcpy ( wlan->essid, ssid );
+ list_add_tail ( &wlan->list, ctx->beacons );
+
+ /* Whether we're using an old entry or a new one, fill
+ it with new data. */
+ fill:
+ memcpy ( wlan->bssid, hdr->addr3, ETH_ALEN );
+ wlan->signal = signal;
+ wlan->channel = dev->channels[dev->channel].channel_nr;
+
+ /* Copy this I/O buffer into a new wlan->beacon; the
+ * iob we've got probably came from the device driver
+ * and may have the full 2.4k allocation, which we
+ * don't want to keep around wasting memory.
+ */
+ free_iob ( wlan->beacon );
+ wlan->beacon = alloc_iob ( iob_len ( iob ) );
+ memcpy ( iob_put ( wlan->beacon, iob_len ( iob ) ),
+ iob->data, iob_len ( iob ) );
+
+ if ( ( rc = sec80211_detect ( wlan->beacon, &wlan->handshaking,
+ &wlan->crypto ) ) == -ENOTSUP ) {
+ struct ieee80211_beacon *beacon =
+ ( struct ieee80211_beacon * ) hdr->data;
+
+ if ( beacon->capability & IEEE80211_CAPAB_PRIVACY ) {
+ DBG ( "802.11 %p probe: secured network %s but "
+ "encryption support not compiled in\n",
+ dev, wlan->essid );
+ wlan->handshaking = NET80211_SECPROT_UNKNOWN;
+ wlan->crypto = NET80211_CRYPT_UNKNOWN;
+ } else {
+ wlan->handshaking = NET80211_SECPROT_NONE;
+ wlan->crypto = NET80211_CRYPT_NONE;
+ }
+ } else if ( rc != 0 ) {
+ DBGC ( dev, "802.11 %p probe warning: network "
+ "%s with unidentifiable security "
+ "settings: %s\n", dev, wlan->essid,
+ strerror ( rc ) );
+ }
+
+ ctx->ticks_beacon = now;
+
+ DBGC2 ( dev, "802.11 %p probe: good beacon for %s (%s)\n",
+ dev, wlan->essid, eth_ntoa ( wlan->bssid ) );
+
+ drop:
+ free_iob ( iob );
+ }
+
+ return 0;
+}
+
+
+/**
+ * Finish probe of 802.11 networks, returning best-signal network found
+ *
+ * @v ctx Probe context
+ * @ret wlan Best-signal network found, or @c NULL if none were found
+ *
+ * If net80211_probe_start() was called with a particular SSID
+ * parameter as filter, only a network with that SSID (matching
+ * case-sensitively) can be returned from this function.
+ */
+struct net80211_wlan *
+net80211_probe_finish_best ( struct net80211_probe_ctx *ctx )
+{
+ struct net80211_wlan *best = NULL, *wlan;
+
+ if ( ! ctx )
+ return NULL;
+
+ list_for_each_entry ( wlan, ctx->beacons, list ) {
+ if ( ! best || best->signal < wlan->signal )
+ best = wlan;
+ }
+
+ if ( best )
+ list_del ( &best->list );
+ else
+ DBGC ( ctx->dev, "802.11 %p probe: found nothing for '%s'\n",
+ ctx->dev, ctx->essid );
+
+ net80211_free_wlanlist ( ctx->beacons );
+
+ net80211_keep_mgmt ( ctx->dev, ctx->old_keep_mgmt );
+
+ if ( ctx->probe )
+ free_iob ( ctx->probe );
+
+ free ( ctx );
+
+ return best;
+}
+
+
+/**
+ * Finish probe of 802.11 networks, returning all networks found
+ *
+ * @v ctx Probe context
+ * @ret list List of net80211_wlan detailing networks found
+ *
+ * If net80211_probe_start() was called with a particular SSID
+ * parameter as filter, this will always return either an empty or a
+ * one-element list.
+ */
+struct list_head *net80211_probe_finish_all ( struct net80211_probe_ctx *ctx )
+{
+ struct list_head *beacons = ctx->beacons;
+
+ if ( ! ctx )
+ return NULL;
+
+ net80211_keep_mgmt ( ctx->dev, ctx->old_keep_mgmt );
+
+ if ( ctx->probe )
+ free_iob ( ctx->probe );
+
+ free ( ctx );
+
+ return beacons;
+}
+
+
+/**
+ * Free WLAN structure
+ *
+ * @v wlan WLAN structure to free
+ */
+void net80211_free_wlan ( struct net80211_wlan *wlan )
+{
+ if ( wlan ) {
+ free_iob ( wlan->beacon );
+ free ( wlan );
+ }
+}
+
+
+/**
+ * Free list of WLAN structures
+ *
+ * @v list List of WLAN structures to free
+ */
+void net80211_free_wlanlist ( struct list_head *list )
+{
+ struct net80211_wlan *wlan, *tmp;
+
+ if ( ! list )
+ return;
+
+ list_for_each_entry_safe ( wlan, tmp, list, list ) {
+ list_del ( &wlan->list );
+ net80211_free_wlan ( wlan );
+ }
+
+ free ( list );
+}
+
+
+/** Number of ticks to wait for replies to association management frames */
+#define ASSOC_TIMEOUT TICKS_PER_SEC
+
+/** Number of times to try sending a particular association management frame */
+#define ASSOC_RETRIES 2
+
+/**
+ * Step 802.11 association process
+ *
+ * @v dev 802.11 device
+ */
+static void net80211_step_associate ( struct net80211_device *dev )
+{
+ int rc = 0;
+ int status = dev->state & NET80211_STATUS_MASK;
+
+ /*
+ * We use a sort of state machine implemented using bits in
+ * the dev->state variable. At each call, we take the
+ * logically first step that has not yet succeeded; either it
+ * has not been tried yet, it's being retried, or it failed.
+ * If it failed, we return an error indication; otherwise we
+ * perform the step. If it succeeds, RX handling code will set
+ * the appropriate status bit for us.
+ *
+ * Probe works a bit differently, since we have to step it
+ * on every call instead of waiting for a packet to arrive
+ * that will set the completion bit for us.
+ */
+
+ /* If we're waiting for a reply, check for timeout condition */
+ if ( dev->state & NET80211_WAITING ) {
+ /* Sanity check */
+ if ( ! dev->associating )
+ return;
+
+ if ( currticks() - dev->ctx.assoc->last_packet > ASSOC_TIMEOUT ) {
+ /* Timed out - fail if too many retries, or retry */
+ dev->ctx.assoc->times_tried++;
+ if ( ++dev->ctx.assoc->times_tried > ASSOC_RETRIES ) {
+ rc = -ETIMEDOUT;
+ goto fail;
+ }
+ } else {
+ /* Didn't time out - let it keep going */
+ return;
+ }
+ } else {
+ if ( dev->state & NET80211_PROBED )
+ dev->ctx.assoc->times_tried = 0;
+ }
+
+ if ( ! ( dev->state & NET80211_PROBED ) ) {
+ /* state: probe */
+
+ if ( ! dev->ctx.probe ) {
+ /* start probe */
+ int active = fetch_intz_setting ( NULL,
+ &net80211_active_setting );
+ int band = dev->hw->bands;
+
+ if ( active )
+ band &= ~NET80211_BAND_BIT_5GHZ;
+
+ rc = net80211_prepare_probe ( dev, band, active );
+ if ( rc )
+ goto fail;
+
+ dev->ctx.probe = net80211_probe_start ( dev, dev->essid,
+ active );
+ if ( ! dev->ctx.probe ) {
+ dev->assoc_rc = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ rc = net80211_probe_step ( dev->ctx.probe );
+ if ( ! rc ) {
+ return; /* still going */
+ }
+
+ dev->associating = net80211_probe_finish_best ( dev->ctx.probe );
+ dev->ctx.probe = NULL;
+ if ( ! dev->associating ) {
+ if ( rc > 0 ) /* "successful" probe found nothing */
+ rc = -ETIMEDOUT;
+ goto fail;
+ }
+
+ /* If we probed using a broadcast SSID, record that
+ fact for the settings applicator before we clobber
+ it with the specific SSID we've chosen. */
+ if ( ! dev->essid[0] )
+ dev->state |= NET80211_AUTO_SSID;
+
+ DBGC ( dev, "802.11 %p found network %s (%s)\n", dev,
+ dev->associating->essid,
+ eth_ntoa ( dev->associating->bssid ) );
+
+ dev->ctx.assoc = zalloc ( sizeof ( *dev->ctx.assoc ) );
+ if ( ! dev->ctx.assoc ) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ dev->state |= NET80211_PROBED;
+ dev->ctx.assoc->method = IEEE80211_AUTH_OPEN_SYSTEM;
+
+ return;
+ }
+
+ /* Record time of sending the packet we're about to send, for timeout */
+ dev->ctx.assoc->last_packet = currticks();
+
+ if ( ! ( dev->state & NET80211_AUTHENTICATED ) ) {
+ /* state: prepare and authenticate */
+
+ if ( status != IEEE80211_STATUS_SUCCESS ) {
+ /* we tried authenticating already, but failed */
+ int method = dev->ctx.assoc->method;
+
+ if ( method == IEEE80211_AUTH_OPEN_SYSTEM &&
+ ( status == IEEE80211_STATUS_AUTH_CHALL_INVALID ||
+ status == IEEE80211_STATUS_AUTH_ALGO_UNSUPP ) ) {
+ /* Maybe this network uses Shared Key? */
+ dev->ctx.assoc->method =
+ IEEE80211_AUTH_SHARED_KEY;
+ } else {
+ goto fail;
+ }
+ }
+
+ DBGC ( dev, "802.11 %p authenticating with method %d\n", dev,
+ dev->ctx.assoc->method );
+
+ rc = net80211_prepare_assoc ( dev, dev->associating );
+ if ( rc )
+ goto fail;
+
+ rc = net80211_send_auth ( dev, dev->associating,
+ dev->ctx.assoc->method );
+ if ( rc )
+ goto fail;
+
+ return;
+ }
+
+ if ( ! ( dev->state & NET80211_ASSOCIATED ) ) {
+ /* state: associate */
+
+ if ( status != IEEE80211_STATUS_SUCCESS )
+ goto fail;
+
+ DBGC ( dev, "802.11 %p associating\n", dev );
+
+ if ( dev->handshaker && dev->handshaker->start &&
+ ! dev->handshaker->started ) {
+ rc = dev->handshaker->start ( dev );
+ if ( rc < 0 )
+ goto fail;
+ dev->handshaker->started = 1;
+ }
+
+ rc = net80211_send_assoc ( dev, dev->associating );
+ if ( rc )
+ goto fail;
+
+ return;
+ }
+
+ if ( ! ( dev->state & NET80211_CRYPTO_SYNCED ) ) {
+ /* state: crypto sync */
+ DBGC ( dev, "802.11 %p security handshaking\n", dev );
+
+ if ( ! dev->handshaker || ! dev->handshaker->step ) {
+ dev->state |= NET80211_CRYPTO_SYNCED;
+ return;
+ }
+
+ rc = dev->handshaker->step ( dev );
+
+ if ( rc < 0 ) {
+ /* Only record the returned error if we're
+ still marked as associated, because an
+ asynchronous error will have already been
+ reported to net80211_deauthenticate() and
+ assoc_rc thereby set. */
+ if ( dev->state & NET80211_ASSOCIATED )
+ dev->assoc_rc = rc;
+ rc = 0;
+ goto fail;
+ }
+
+ if ( rc > 0 ) {
+ dev->assoc_rc = 0;
+ dev->state |= NET80211_CRYPTO_SYNCED;
+ }
+ return;
+ }
+
+ /* state: done! */
+ netdev_link_up ( dev->netdev );
+ dev->assoc_rc = 0;
+ dev->state &= ~NET80211_WORKING;
+
+ free ( dev->ctx.assoc );
+ dev->ctx.assoc = NULL;
+
+ net80211_free_wlan ( dev->associating );
+ dev->associating = NULL;
+
+ dev->rctl = rc80211_init ( dev );
+
+ process_del ( &dev->proc_assoc );
+
+ DBGC ( dev, "802.11 %p associated with %s (%s)\n", dev,
+ dev->essid, eth_ntoa ( dev->bssid ) );
+
+ return;
+
+ fail:
+ dev->state &= ~( NET80211_WORKING | NET80211_WAITING );
+ if ( rc )
+ dev->assoc_rc = rc;
+
+ netdev_link_err ( dev->netdev, dev->assoc_rc );
+
+ /* We never reach here from the middle of a probe, so we don't
+ need to worry about freeing dev->ctx.probe. */
+
+ if ( dev->state & NET80211_PROBED ) {
+ free ( dev->ctx.assoc );
+ dev->ctx.assoc = NULL;
+ }
+
+ net80211_free_wlan ( dev->associating );
+ dev->associating = NULL;
+
+ process_del ( &dev->proc_assoc );
+
+ DBGC ( dev, "802.11 %p association failed (state=%04x): "
+ "%s\n", dev, dev->state, strerror ( dev->assoc_rc ) );
+
+ /* Try it again: */
+ net80211_autoassociate ( dev );
+}
+
+/**
+ * Check for 802.11 SSID or key updates
+ *
+ * This acts as a settings applicator; if the user changes netX/ssid,
+ * and netX is currently open, the association task will be invoked
+ * again. If the user changes the encryption key, the current security
+ * handshaker will be asked to update its state to match; if that is
+ * impossible without reassociation, we reassociate.
+ */
+static int net80211_check_settings_update ( void )
+{
+ struct net80211_device *dev;
+ char ssid[IEEE80211_MAX_SSID_LEN + 1];
+ int key_reassoc;
+
+ list_for_each_entry ( dev, &net80211_devices, list ) {
+ if ( ! netdev_is_open ( dev->netdev ) )
+ continue;
+
+ key_reassoc = 0;
+ if ( dev->handshaker && dev->handshaker->change_key &&
+ dev->handshaker->change_key ( dev ) < 0 )
+ key_reassoc = 1;
+
+ fetch_string_setting ( netdev_settings ( dev->netdev ),
+ &net80211_ssid_setting, ssid,
+ IEEE80211_MAX_SSID_LEN + 1 );
+
+ if ( key_reassoc ||
+ ( ! ( ! ssid[0] && ( dev->state & NET80211_AUTO_SSID ) ) &&
+ strcmp ( ssid, dev->essid ) != 0 ) ) {
+ DBGC ( dev, "802.11 %p updating association: "
+ "%s -> %s\n", dev, dev->essid, ssid );
+ net80211_autoassociate ( dev );
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Start 802.11 association process
+ *
+ * @v dev 802.11 device
+ *
+ * If the association process is running, it will be restarted.
+ */
+void net80211_autoassociate ( struct net80211_device *dev )
+{
+ if ( ! ( dev->state & NET80211_WORKING ) ) {
+ DBGC2 ( dev, "802.11 %p spawning association process\n", dev );
+ process_add ( &dev->proc_assoc );
+ } else {
+ DBGC2 ( dev, "802.11 %p restarting association\n", dev );
+ }
+
+ /* Clean up everything an earlier association process might
+ have been in the middle of using */
+ if ( dev->associating )
+ net80211_free_wlan ( dev->associating );
+
+ if ( ! ( dev->state & NET80211_PROBED ) )
+ net80211_free_wlan (
+ net80211_probe_finish_best ( dev->ctx.probe ) );
+ else
+ free ( dev->ctx.assoc );
+
+ /* Reset to a clean state */
+ fetch_string_setting ( netdev_settings ( dev->netdev ),
+ &net80211_ssid_setting, dev->essid,
+ IEEE80211_MAX_SSID_LEN + 1 );
+ dev->ctx.probe = NULL;
+ dev->associating = NULL;
+ dev->assoc_rc = 0;
+ net80211_set_state ( dev, NET80211_PROBED, NET80211_WORKING, 0 );
+}
+
+/**
+ * Pick TX rate for RTS/CTS packets based on data rate
+ *
+ * @v dev 802.11 device
+ *
+ * The RTS/CTS rate is the fastest TX rate marked as "basic" that is
+ * not faster than the data rate.
+ */
+static void net80211_set_rtscts_rate ( struct net80211_device *dev )
+{
+ u16 datarate = dev->rates[dev->rate];
+ u16 rtsrate = 0;
+ int rts_idx = -1;
+ int i;
+
+ for ( i = 0; i < dev->nr_rates; i++ ) {
+ u16 rate = dev->rates[i];
+
+ if ( ! ( dev->basic_rates & ( 1 << i ) ) || rate > datarate )
+ continue;
+
+ if ( rate > rtsrate ) {
+ rtsrate = rate;
+ rts_idx = i;
+ }
+ }
+
+ /* If this is in initialization, we might not have any basic
+ rates; just use the first data rate in that case. */
+ if ( rts_idx < 0 )
+ rts_idx = 0;
+
+ dev->rtscts_rate = rts_idx;
+}
+
+/**
+ * Set data transmission rate for 802.11 device
+ *
+ * @v dev 802.11 device
+ * @v rate Rate to set, as index into @c dev->rates array
+ */
+void net80211_set_rate_idx ( struct net80211_device *dev, int rate )
+{
+ assert ( netdev_is_open ( dev->netdev ) );
+
+ if ( rate >= 0 && rate < dev->nr_rates && rate != dev->rate ) {
+ DBGC2 ( dev, "802.11 %p changing rate from %d->%d Mbps\n",
+ dev, dev->rates[dev->rate] / 10,
+ dev->rates[rate] / 10 );
+
+ dev->rate = rate;
+ net80211_set_rtscts_rate ( dev );
+ dev->op->config ( dev, NET80211_CFG_RATE );
+ }
+}
+
+/**
+ * Configure 802.11 device to transmit on a certain channel
+ *
+ * @v dev 802.11 device
+ * @v channel Channel number (1-11 for 2.4GHz) to transmit on
+ */
+int net80211_change_channel ( struct net80211_device *dev, int channel )
+{
+ int i, oldchan = dev->channel;
+
+ assert ( netdev_is_open ( dev->netdev ) );
+
+ for ( i = 0; i < dev->nr_channels; i++ ) {
+ if ( dev->channels[i].channel_nr == channel ) {
+ dev->channel = i;
+ break;
+ }
+ }
+
+ if ( i == dev->nr_channels )
+ return -ENOENT;
+
+ if ( i != oldchan )
+ return dev->op->config ( dev, NET80211_CFG_CHANNEL );
+
+ return 0;
+}
+
+/**
+ * Prepare 802.11 device channel and rate set for scanning
+ *
+ * @v dev 802.11 device
+ * @v band RF band(s) on which to prepare for scanning
+ * @v active Whether the scanning will be active
+ * @ret rc Return status code
+ */
+int net80211_prepare_probe ( struct net80211_device *dev, int band,
+ int active )
+{
+ assert ( netdev_is_open ( dev->netdev ) );
+
+ if ( active && ( band & NET80211_BAND_BIT_5GHZ ) ) {
+ DBGC ( dev, "802.11 %p cannot perform active scanning on "
+ "5GHz band\n", dev );
+ return -EINVAL_ACTIVE_SCAN;
+ }
+
+ if ( band == 0 ) {
+ /* This can happen for a 5GHz-only card with 5GHz
+ scanning masked out by an active request. */
+ DBGC ( dev, "802.11 %p asked to prepare for scanning nothing\n",
+ dev );
+ return -EINVAL_ACTIVE_SCAN;
+ }
+
+ dev->nr_channels = 0;
+
+ if ( active )
+ net80211_add_channels ( dev, 1, 11, NET80211_REG_TXPOWER );
+ else {
+ if ( band & NET80211_BAND_BIT_2GHZ )
+ net80211_add_channels ( dev, 1, 14,
+ NET80211_REG_TXPOWER );
+ if ( band & NET80211_BAND_BIT_5GHZ )
+ net80211_add_channels ( dev, 36, 8,
+ NET80211_REG_TXPOWER );
+ }
+
+ net80211_filter_hw_channels ( dev );
+
+ /* Use channel 1 for now */
+ dev->channel = 0;
+ dev->op->config ( dev, NET80211_CFG_CHANNEL );
+
+ /* Always do active probes at lowest (presumably first) speed */
+ dev->rate = 0;
+ dev->nr_rates = 1;
+ dev->rates[0] = dev->hw->rates[dev->channels[0].band][0];
+ dev->op->config ( dev, NET80211_CFG_RATE );
+
+ return 0;
+}
+
+/**
+ * Prepare 802.11 device channel and rate set for communication
+ *
+ * @v dev 802.11 device
+ * @v wlan WLAN to prepare for communication with
+ * @ret rc Return status code
+ */
+int net80211_prepare_assoc ( struct net80211_device *dev,
+ struct net80211_wlan *wlan )
+{
+ struct ieee80211_frame *hdr = wlan->beacon->data;
+ struct ieee80211_beacon *beacon =
+ ( struct ieee80211_beacon * ) hdr->data;
+ struct net80211_handshaker *handshaker;
+ int rc;
+
+ assert ( netdev_is_open ( dev->netdev ) );
+
+ net80211_set_state ( dev, NET80211_ASSOCIATED, 0, 0 );
+ memcpy ( dev->bssid, wlan->bssid, ETH_ALEN );
+ strcpy ( dev->essid, wlan->essid );
+
+ free ( dev->rsn_ie );
+ dev->rsn_ie = NULL;
+
+ dev->last_beacon_timestamp = beacon->timestamp;
+ dev->tx_beacon_interval = 1024 * beacon->beacon_interval;
+
+ /* Barring an IE that tells us the channel outright, assume
+ the channel we heard this AP best on is the channel it's
+ communicating on. */
+ net80211_change_channel ( dev, wlan->channel );
+
+ rc = net80211_process_capab ( dev, beacon->capability );
+ if ( rc )
+ return rc;
+
+ rc = net80211_process_ie ( dev, beacon->info_element,
+ wlan->beacon->tail );
+ if ( rc )
+ return rc;
+
+ /* Associate at the lowest rate so we know it'll get through */
+ dev->rate = 0;
+ dev->op->config ( dev, NET80211_CFG_RATE );
+
+ /* Free old handshaker and crypto, if they exist */
+ if ( dev->handshaker && dev->handshaker->stop &&
+ dev->handshaker->started )
+ dev->handshaker->stop ( dev );
+ free ( dev->handshaker );
+ dev->handshaker = NULL;
+ free ( dev->crypto );
+ free ( dev->gcrypto );
+ dev->crypto = dev->gcrypto = NULL;
+
+ /* Find new security handshaker to use */
+ for_each_table_entry ( handshaker, NET80211_HANDSHAKERS ) {
+ if ( handshaker->protocol == wlan->handshaking ) {
+ dev->handshaker = zalloc ( sizeof ( *handshaker ) +
+ handshaker->priv_len );
+ if ( ! dev->handshaker )
+ return -ENOMEM;
+
+ memcpy ( dev->handshaker, handshaker,
+ sizeof ( *handshaker ) );
+ dev->handshaker->priv = ( ( void * ) dev->handshaker +
+ sizeof ( *handshaker ) );
+ break;
+ }
+ }
+
+ if ( ( wlan->handshaking != NET80211_SECPROT_NONE ) &&
+ ! dev->handshaker ) {
+ DBGC ( dev, "802.11 %p no support for handshaking scheme %d\n",
+ dev, wlan->handshaking );
+ return -( ENOTSUP | ( wlan->handshaking << 8 ) );
+ }
+
+ /* Initialize security handshaker */
+ if ( dev->handshaker ) {
+ rc = dev->handshaker->init ( dev );
+ if ( rc < 0 )
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Send 802.11 initial authentication frame
+ *
+ * @v dev 802.11 device
+ * @v wlan WLAN to authenticate with
+ * @v method Authentication method
+ * @ret rc Return status code
+ *
+ * @a method may be 0 for Open System authentication or 1 for Shared
+ * Key authentication. Open System provides no security in association
+ * whatsoever, relying on encryption for confidentiality, but Shared
+ * Key actively introduces security problems and is very rarely used.
+ */
+int net80211_send_auth ( struct net80211_device *dev,
+ struct net80211_wlan *wlan, int method )
+{
+ struct io_buffer *iob = alloc_iob ( 64 );
+ struct ieee80211_auth *auth;
+
+ net80211_set_state ( dev, 0, NET80211_WAITING, 0 );
+ iob_reserve ( iob, IEEE80211_TYP_FRAME_HEADER_LEN );
+ auth = iob_put ( iob, sizeof ( *auth ) );
+ auth->algorithm = method;
+ auth->tx_seq = 1;
+ auth->status = 0;
+
+ return net80211_tx_mgmt ( dev, IEEE80211_STYPE_AUTH, wlan->bssid, iob );
+}
+
+/**
+ * Handle receipt of 802.11 authentication frame
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer
+ *
+ * If the authentication method being used is Shared Key, and the
+ * frame that was received included challenge text, the frame is
+ * encrypted using the cryptosystem currently in effect and sent back
+ * to the AP to complete the authentication.
+ */
+static void net80211_handle_auth ( struct net80211_device *dev,
+ struct io_buffer *iob )
+{
+ struct ieee80211_frame *hdr = iob->data;
+ struct ieee80211_auth *auth =
+ ( struct ieee80211_auth * ) hdr->data;
+
+ if ( auth->tx_seq & 1 ) {
+ DBGC ( dev, "802.11 %p authentication received improperly "
+ "directed frame (seq. %d)\n", dev, auth->tx_seq );
+ net80211_set_state ( dev, NET80211_WAITING, 0,
+ IEEE80211_STATUS_FAILURE );
+ return;
+ }
+
+ if ( auth->status != IEEE80211_STATUS_SUCCESS ) {
+ DBGC ( dev, "802.11 %p authentication failed: status %d\n",
+ dev, auth->status );
+ net80211_set_state ( dev, NET80211_WAITING, 0,
+ auth->status );
+ return;
+ }
+
+ if ( auth->algorithm == IEEE80211_AUTH_SHARED_KEY && ! dev->crypto ) {
+ DBGC ( dev, "802.11 %p can't perform shared-key authentication "
+ "without a cryptosystem\n", dev );
+ net80211_set_state ( dev, NET80211_WAITING, 0,
+ IEEE80211_STATUS_FAILURE );
+ return;
+ }
+
+ if ( auth->algorithm == IEEE80211_AUTH_SHARED_KEY &&
+ auth->tx_seq == 2 ) {
+ /* Since the iob we got is going to be freed as soon
+ as we return, we can do some in-place
+ modification. */
+ auth->tx_seq = 3;
+ auth->status = 0;
+
+ memcpy ( hdr->addr2, hdr->addr1, ETH_ALEN );
+ memcpy ( hdr->addr1, hdr->addr3, ETH_ALEN );
+
+ netdev_tx ( dev->netdev,
+ dev->crypto->encrypt ( dev->crypto, iob ) );
+ return;
+ }
+
+ net80211_set_state ( dev, NET80211_WAITING, NET80211_AUTHENTICATED,
+ IEEE80211_STATUS_SUCCESS );
+
+ return;
+}
+
+/**
+ * Send 802.11 association frame
+ *
+ * @v dev 802.11 device
+ * @v wlan WLAN to associate with
+ * @ret rc Return status code
+ */
+int net80211_send_assoc ( struct net80211_device *dev,
+ struct net80211_wlan *wlan )
+{
+ struct io_buffer *iob = alloc_iob ( 128 );
+ struct ieee80211_assoc_req *assoc;
+ union ieee80211_ie *ie;
+
+ net80211_set_state ( dev, 0, NET80211_WAITING, 0 );
+
+ iob_reserve ( iob, IEEE80211_TYP_FRAME_HEADER_LEN );
+ assoc = iob->data;
+
+ assoc->capability = IEEE80211_CAPAB_MANAGED;
+ if ( ! ( dev->hw->flags & NET80211_HW_NO_SHORT_PREAMBLE ) )
+ assoc->capability |= IEEE80211_CAPAB_SHORT_PMBL;
+ if ( ! ( dev->hw->flags & NET80211_HW_NO_SHORT_SLOT ) )
+ assoc->capability |= IEEE80211_CAPAB_SHORT_SLOT;
+ if ( wlan->crypto )
+ assoc->capability |= IEEE80211_CAPAB_PRIVACY;
+
+ assoc->listen_interval = 1;
+
+ ie = net80211_marshal_request_info ( dev, assoc->info_element );
+
+ DBGP ( "802.11 %p about to send association request:\n", dev );
+ DBGP_HD ( iob->data, ( void * ) ie - iob->data );
+
+ iob_put ( iob, ( void * ) ie - iob->data );
+
+ return net80211_tx_mgmt ( dev, IEEE80211_STYPE_ASSOC_REQ,
+ wlan->bssid, iob );
+}
+
+/**
+ * Handle receipt of 802.11 association reply frame
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer
+ */
+static void net80211_handle_assoc_reply ( struct net80211_device *dev,
+ struct io_buffer *iob )
+{
+ struct ieee80211_frame *hdr = iob->data;
+ struct ieee80211_assoc_resp *assoc =
+ ( struct ieee80211_assoc_resp * ) hdr->data;
+
+ net80211_process_capab ( dev, assoc->capability );
+ net80211_process_ie ( dev, assoc->info_element, iob->tail );
+
+ if ( assoc->status != IEEE80211_STATUS_SUCCESS ) {
+ DBGC ( dev, "802.11 %p association failed: status %d\n",
+ dev, assoc->status );
+ net80211_set_state ( dev, NET80211_WAITING, 0,
+ assoc->status );
+ return;
+ }
+
+ /* ESSID was filled before the association request was sent */
+ memcpy ( dev->bssid, hdr->addr3, ETH_ALEN );
+ dev->aid = assoc->aid;
+
+ net80211_set_state ( dev, NET80211_WAITING, NET80211_ASSOCIATED,
+ IEEE80211_STATUS_SUCCESS );
+}
+
+
+/**
+ * Send 802.11 disassociation frame
+ *
+ * @v dev 802.11 device
+ * @v reason Reason for disassociation
+ * @v deauth If TRUE, send deauthentication instead of disassociation
+ * @ret rc Return status code
+ */
+static int net80211_send_disassoc ( struct net80211_device *dev, int reason,
+ int deauth )
+{
+ struct io_buffer *iob = alloc_iob ( 64 );
+ struct ieee80211_disassoc *disassoc;
+
+ if ( ! ( dev->state & NET80211_ASSOCIATED ) )
+ return -EINVAL;
+
+ net80211_set_state ( dev, NET80211_ASSOCIATED, 0, 0 );
+ iob_reserve ( iob, IEEE80211_TYP_FRAME_HEADER_LEN );
+ disassoc = iob_put ( iob, sizeof ( *disassoc ) );
+ disassoc->reason = reason;
+
+ return net80211_tx_mgmt ( dev, deauth ? IEEE80211_STYPE_DEAUTH :
+ IEEE80211_STYPE_DISASSOC, dev->bssid, iob );
+}
+
+
+/**
+ * Deauthenticate from current network and try again
+ *
+ * @v dev 802.11 device
+ * @v rc Return status code indicating reason
+ *
+ * The deauthentication will be sent using an 802.11 "unspecified
+ * reason", as is common, but @a rc will be set as a link-up
+ * error to aid the user in debugging.
+ */
+void net80211_deauthenticate ( struct net80211_device *dev, int rc )
+{
+ net80211_send_disassoc ( dev, IEEE80211_REASON_UNSPECIFIED, 1 );
+ dev->assoc_rc = rc;
+ netdev_link_err ( dev->netdev, rc );
+
+ net80211_autoassociate ( dev );
+}
+
+
+/** Smoothing factor (1-7) for link quality calculation */
+#define LQ_SMOOTH 7
+
+/**
+ * Update link quality information based on received beacon
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer containing beacon
+ * @ret rc Return status code
+ */
+static void net80211_update_link_quality ( struct net80211_device *dev,
+ struct io_buffer *iob )
+{
+ struct ieee80211_frame *hdr = iob->data;
+ struct ieee80211_beacon *beacon;
+ u32 dt, rxi;
+
+ if ( ! ( dev->state & NET80211_ASSOCIATED ) )
+ return;
+
+ beacon = ( struct ieee80211_beacon * ) hdr->data;
+ dt = ( u32 ) ( beacon->timestamp - dev->last_beacon_timestamp );
+ rxi = dev->rx_beacon_interval;
+
+ rxi = ( LQ_SMOOTH * rxi ) + ( ( 8 - LQ_SMOOTH ) * dt );
+ dev->rx_beacon_interval = rxi >> 3;
+
+ dev->last_beacon_timestamp = beacon->timestamp;
+}
+
+
+/**
+ * Handle receipt of 802.11 management frame
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer
+ * @v signal Signal strength of received frame
+ */
+static void net80211_handle_mgmt ( struct net80211_device *dev,
+ struct io_buffer *iob, int signal )
+{
+ struct ieee80211_frame *hdr = iob->data;
+ struct ieee80211_disassoc *disassoc;
+ u16 stype = hdr->fc & IEEE80211_FC_SUBTYPE;
+ int keep = 0;
+ int is_deauth = ( stype == IEEE80211_STYPE_DEAUTH );
+
+ if ( ( hdr->fc & IEEE80211_FC_TYPE ) != IEEE80211_TYPE_MGMT ) {
+ free_iob ( iob );
+ return; /* only handle management frames */
+ }
+
+ switch ( stype ) {
+ /* We reconnect on deauthentication and disassociation. */
+ case IEEE80211_STYPE_DEAUTH:
+ case IEEE80211_STYPE_DISASSOC:
+ disassoc = ( struct ieee80211_disassoc * ) hdr->data;
+ net80211_set_state ( dev, is_deauth ? NET80211_AUTHENTICATED :
+ NET80211_ASSOCIATED, 0,
+ NET80211_IS_REASON | disassoc->reason );
+ DBGC ( dev, "802.11 %p %s: reason %d\n",
+ dev, is_deauth ? "deauthenticated" : "disassociated",
+ disassoc->reason );
+
+ /* Try to reassociate, in case it's transient. */
+ net80211_autoassociate ( dev );
+
+ break;
+
+ /* We handle authentication and association. */
+ case IEEE80211_STYPE_AUTH:
+ if ( ! ( dev->state & NET80211_AUTHENTICATED ) )
+ net80211_handle_auth ( dev, iob );
+ break;
+
+ case IEEE80211_STYPE_ASSOC_RESP:
+ case IEEE80211_STYPE_REASSOC_RESP:
+ if ( ! ( dev->state & NET80211_ASSOCIATED ) )
+ net80211_handle_assoc_reply ( dev, iob );
+ break;
+
+ /* We pass probes and beacons onto network scanning
+ code. Pass actions for future extensibility. */
+ case IEEE80211_STYPE_BEACON:
+ net80211_update_link_quality ( dev, iob );
+ /* fall through */
+ case IEEE80211_STYPE_PROBE_RESP:
+ case IEEE80211_STYPE_ACTION:
+ if ( dev->keep_mgmt ) {
+ struct net80211_rx_info *rxinf;
+ rxinf = zalloc ( sizeof ( *rxinf ) );
+ if ( ! rxinf ) {
+ DBGC ( dev, "802.11 %p out of memory\n", dev );
+ break;
+ }
+ rxinf->signal = signal;
+ list_add_tail ( &iob->list, &dev->mgmt_queue );
+ list_add_tail ( &rxinf->list, &dev->mgmt_info_queue );
+ keep = 1;
+ }
+ break;
+
+ case IEEE80211_STYPE_PROBE_REQ:
+ /* Some nodes send these broadcast. Ignore them. */
+ break;
+
+ case IEEE80211_STYPE_ASSOC_REQ:
+ case IEEE80211_STYPE_REASSOC_REQ:
+ /* We should never receive these, only send them. */
+ DBGC ( dev, "802.11 %p received strange management request "
+ "(%04x)\n", dev, stype );
+ break;
+
+ default:
+ DBGC ( dev, "802.11 %p received unimplemented management "
+ "packet (%04x)\n", dev, stype );
+ break;
+ }
+
+ if ( ! keep )
+ free_iob ( iob );
+}
+
+/* ---------- Packet handling functions ---------- */
+
+/**
+ * Free buffers used by 802.11 fragment cache entry
+ *
+ * @v dev 802.11 device
+ * @v fcid Fragment cache entry index
+ *
+ * After this function, the referenced entry will be marked unused.
+ */
+static void net80211_free_frags ( struct net80211_device *dev, int fcid )
+{
+ int j;
+ struct net80211_frag_cache *frag = &dev->frags[fcid];
+
+ for ( j = 0; j < 16; j++ ) {
+ if ( frag->iob[j] ) {
+ free_iob ( frag->iob[j] );
+ frag->iob[j] = NULL;
+ }
+ }
+
+ frag->seqnr = 0;
+ frag->start_ticks = 0;
+ frag->in_use = 0;
+}
+
+/**
+ * Accumulate 802.11 fragments into one I/O buffer
+ *
+ * @v dev 802.11 device
+ * @v fcid Fragment cache entry index
+ * @v nfrags Number of fragments received
+ * @v size Sum of sizes of all fragments, including headers
+ * @ret iob I/O buffer containing reassembled packet
+ *
+ * This function does not free the fragment buffers.
+ */
+static struct io_buffer *net80211_accum_frags ( struct net80211_device *dev,
+ int fcid, int nfrags, int size )
+{
+ struct net80211_frag_cache *frag = &dev->frags[fcid];
+ int hdrsize = IEEE80211_TYP_FRAME_HEADER_LEN;
+ int nsize = size - hdrsize * ( nfrags - 1 );
+ int i;
+
+ struct io_buffer *niob = alloc_iob ( nsize );
+ struct ieee80211_frame *hdr;
+
+ /* Add the header from the first one... */
+ memcpy ( iob_put ( niob, hdrsize ), frag->iob[0]->data, hdrsize );
+
+ /* ... and all the data from all of them. */
+ for ( i = 0; i < nfrags; i++ ) {
+ int len = iob_len ( frag->iob[i] ) - hdrsize;
+ memcpy ( iob_put ( niob, len ),
+ frag->iob[i]->data + hdrsize, len );
+ }
+
+ /* Turn off the fragment bit. */
+ hdr = niob->data;
+ hdr->fc &= ~IEEE80211_FC_MORE_FRAG;
+
+ return niob;
+}
+
+/**
+ * Handle receipt of 802.11 fragment
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer containing fragment
+ * @v signal Signal strength with which fragment was received
+ */
+static void net80211_rx_frag ( struct net80211_device *dev,
+ struct io_buffer *iob, int signal )
+{
+ struct ieee80211_frame *hdr = iob->data;
+ int fragnr = IEEE80211_FRAG ( hdr->seq );
+
+ if ( fragnr == 0 && ( hdr->fc & IEEE80211_FC_MORE_FRAG ) ) {
+ /* start a frag cache entry */
+ int i, newest = -1;
+ u32 curr_ticks = currticks(), newest_ticks = 0;
+ u32 timeout = ticks_per_sec() * NET80211_FRAG_TIMEOUT;
+
+ for ( i = 0; i < NET80211_NR_CONCURRENT_FRAGS; i++ ) {
+ if ( dev->frags[i].in_use == 0 )
+ break;
+
+ if ( dev->frags[i].start_ticks + timeout >=
+ curr_ticks ) {
+ net80211_free_frags ( dev, i );
+ break;
+ }
+
+ if ( dev->frags[i].start_ticks > newest_ticks ) {
+ newest = i;
+ newest_ticks = dev->frags[i].start_ticks;
+ }
+ }
+
+ /* If we're being sent more concurrent fragmented
+ packets than we can handle, drop the newest so the
+ older ones have time to complete. */
+ if ( i == NET80211_NR_CONCURRENT_FRAGS ) {
+ i = newest;
+ net80211_free_frags ( dev, i );
+ }
+
+ dev->frags[i].in_use = 1;
+ dev->frags[i].seqnr = IEEE80211_SEQNR ( hdr->seq );
+ dev->frags[i].start_ticks = currticks();
+ dev->frags[i].iob[0] = iob;
+ return;
+ } else {
+ int i;
+ for ( i = 0; i < NET80211_NR_CONCURRENT_FRAGS; i++ ) {
+ if ( dev->frags[i].in_use && dev->frags[i].seqnr ==
+ IEEE80211_SEQNR ( hdr->seq ) )
+ break;
+ }
+ if ( i == NET80211_NR_CONCURRENT_FRAGS ) {
+ /* Drop non-first not-in-cache fragments */
+ DBGC ( dev, "802.11 %p dropped fragment fc=%04x "
+ "seq=%04x\n", dev, hdr->fc, hdr->seq );
+ free_iob ( iob );
+ return;
+ }
+
+ dev->frags[i].iob[fragnr] = iob;
+
+ if ( ! ( hdr->fc & IEEE80211_FC_MORE_FRAG ) ) {
+ int j, size = 0;
+ for ( j = 0; j < fragnr; j++ ) {
+ size += iob_len ( dev->frags[i].iob[j] );
+ if ( dev->frags[i].iob[j] == NULL )
+ break;
+ }
+ if ( j == fragnr ) {
+ /* We've got everything */
+ struct io_buffer *niob =
+ net80211_accum_frags ( dev, i, fragnr,
+ size );
+ net80211_free_frags ( dev, i );
+ net80211_rx ( dev, niob, signal, 0 );
+ } else {
+ DBGC ( dev, "802.11 %p dropping fragmented "
+ "packet due to out-of-order arrival, "
+ "fc=%04x seq=%04x\n", dev, hdr->fc,
+ hdr->seq );
+ net80211_free_frags ( dev, i );
+ }
+ }
+ }
+}
+
+/**
+ * Handle receipt of 802.11 frame
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer
+ * @v signal Received signal strength
+ * @v rate Bitrate at which frame was received, in 100 kbps units
+ *
+ * If the rate or signal is unknown, 0 should be passed.
+ */
+void net80211_rx ( struct net80211_device *dev, struct io_buffer *iob,
+ int signal, u16 rate )
+{
+ struct ieee80211_frame *hdr = iob->data;
+ u16 type = hdr->fc & IEEE80211_FC_TYPE;
+ if ( ( hdr->fc & IEEE80211_FC_VERSION ) != IEEE80211_THIS_VERSION )
+ goto drop; /* drop invalid-version packets */
+
+ if ( type == IEEE80211_TYPE_CTRL )
+ goto drop; /* we don't handle control packets,
+ the hardware does */
+
+ if ( dev->last_rx_seq == hdr->seq )
+ goto drop; /* avoid duplicate packet */
+ dev->last_rx_seq = hdr->seq;
+
+ if ( dev->hw->flags & NET80211_HW_RX_HAS_FCS ) {
+ /* discard the FCS */
+ iob_unput ( iob, 4 );
+ }
+
+ /* Only decrypt packets from our BSSID, to avoid spurious errors */
+ if ( ( hdr->fc & IEEE80211_FC_PROTECTED ) &&
+ ! memcmp ( hdr->addr2, dev->bssid, ETH_ALEN ) ) {
+ /* Decrypt packet; record and drop if it fails */
+ struct io_buffer *niob;
+ struct net80211_crypto *crypto = dev->crypto;
+
+ if ( ! dev->crypto ) {
+ DBGC ( dev, "802.11 %p cannot decrypt packet "
+ "without a cryptosystem\n", dev );
+ goto drop_crypt;
+ }
+
+ if ( ( hdr->addr1[0] & 1 ) && dev->gcrypto ) {
+ /* Use group decryption if needed */
+ crypto = dev->gcrypto;
+ }
+
+ niob = crypto->decrypt ( crypto, iob );
+ if ( ! niob ) {
+ DBGC ( dev, "802.11 %p decryption error\n", dev );
+ goto drop_crypt;
+ }
+ free_iob ( iob );
+ iob = niob;
+ hdr = iob->data;
+ }
+
+ dev->last_signal = signal;
+
+ /* Fragments go into the frag cache or get dropped. */
+ if ( IEEE80211_FRAG ( hdr->seq ) != 0
+ || ( hdr->fc & IEEE80211_FC_MORE_FRAG ) ) {
+ net80211_rx_frag ( dev, iob, signal );
+ return;
+ }
+
+ /* Management frames get handled, enqueued, or dropped. */
+ if ( type == IEEE80211_TYPE_MGMT ) {
+ net80211_handle_mgmt ( dev, iob, signal );
+ return;
+ }
+
+ /* Data frames get dropped or sent to the net_device. */
+ if ( ( hdr->fc & IEEE80211_FC_SUBTYPE ) != IEEE80211_STYPE_DATA )
+ goto drop; /* drop QoS, CFP, or null data packets */
+
+ /* Update rate-control algorithm */
+ if ( dev->rctl )
+ rc80211_update_rx ( dev, hdr->fc & IEEE80211_FC_RETRY, rate );
+
+ /* Pass packet onward */
+ if ( dev->state & NET80211_ASSOCIATED ) {
+ netdev_rx ( dev->netdev, iob );
+ return;
+ }
+
+ /* No association? Drop it. */
+ goto drop;
+
+ drop_crypt:
+ netdev_rx_err ( dev->netdev, NULL, EINVAL_CRYPTO_REQUEST );
+ drop:
+ DBGC2 ( dev, "802.11 %p dropped packet fc=%04x seq=%04x\n", dev,
+ hdr->fc, hdr->seq );
+ free_iob ( iob );
+ return;
+}
+
+/** Indicate an error in receiving a packet
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer with received packet, or NULL
+ * @v rc Error code
+ *
+ * This logs the error with the wrapping net_device, and frees iob if
+ * it is passed.
+ */
+void net80211_rx_err ( struct net80211_device *dev,
+ struct io_buffer *iob, int rc )
+{
+ netdev_rx_err ( dev->netdev, iob, rc );
+}
+
+/** Indicate the completed transmission of a packet
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer of transmitted packet
+ * @v retries Number of times this packet was retransmitted
+ * @v rc Error code, or 0 for success
+ *
+ * This logs an error with the wrapping net_device if one occurred,
+ * and removes and frees the I/O buffer from its TX queue. The
+ * provided retry information is used to tune our transmission rate.
+ *
+ * If the packet did not need to be retransmitted because it was
+ * properly ACKed the first time, @a retries should be 0.
+ */
+void net80211_tx_complete ( struct net80211_device *dev,
+ struct io_buffer *iob, int retries, int rc )
+{
+ /* Update rate-control algorithm */
+ if ( dev->rctl )
+ rc80211_update_tx ( dev, retries, rc );
+
+ /* Pass completion onward */
+ netdev_tx_complete_err ( dev->netdev, iob, rc );
+}
+
+/** Common 802.11 errors */
+struct errortab common_wireless_errors[] __errortab = {
+ __einfo_errortab ( EINFO_EINVAL_CRYPTO_REQUEST ),
+ __einfo_errortab ( EINFO_ECONNRESET_UNSPECIFIED ),
+ __einfo_errortab ( EINFO_ECONNRESET_INACTIVITY ),
+ __einfo_errortab ( EINFO_ECONNRESET_4WAY_TIMEOUT ),
+ __einfo_errortab ( EINFO_ECONNRESET_8021X_FAILURE ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_FAILURE ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_DENIED ),
+ __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_ALGO_UNSUPP ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/80211/rc80211.c b/src/VBox/Devices/PC/ipxe/src/net/80211/rc80211.c
new file mode 100644
index 00000000..56bbc8a0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/80211/rc80211.c
@@ -0,0 +1,371 @@
+/*
+ * Simple 802.11 rate-control algorithm for iPXE.
+ *
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <ipxe/net80211.h>
+
+/**
+ * @file
+ *
+ * Simple 802.11 rate-control algorithm
+ */
+
+/** @page rc80211 Rate control philosophy
+ *
+ * We want to maximize our transmission speed, to the extent that we
+ * can do that without dropping undue numbers of packets. We also
+ * don't want to take up very much code space, so our algorithm has to
+ * be pretty simple
+ *
+ * When we receive a packet, we know what rate it was transmitted at,
+ * and whether it had to be retransmitted to get to us.
+ *
+ * When we send a packet, we hear back how many times it had to be
+ * retried to get through, and whether it got through at all.
+ *
+ * Indications of TX success are more reliable than RX success, but RX
+ * information helps us know where to start.
+ *
+ * To handle all of this, we keep for each rate and each direction (TX
+ * and RX separately) some state information for the most recent
+ * packets on that rate and the number of packets for which we have
+ * information. The state is a 32-bit unsigned integer in which two
+ * bits represent a packet: 11 if it went through well, 10 if it went
+ * through with one retry, 01 if it went through with more than one
+ * retry, or 00 if it didn't go through at all. We define the
+ * "goodness" for a particular (rate, direction) combination as the
+ * sum of all the 2-bit fields, times 33, divided by the number of
+ * 2-bit fields containing valid information (16 except when we're
+ * starting out). The number produced is between 0 and 99; we use -1
+ * for rates with less than 4 RX packets or 1 TX, as an indicator that
+ * we do not have enough information to rely on them.
+ *
+ * In deciding which rates are best, we find the weighted average of
+ * TX and RX goodness, where the weighting is by number of packets
+ * with data and TX packets are worth 4 times as much as RX packets.
+ * The weighted average is called "net goodness" and is also a number
+ * between 0 and 99. If 3 consecutive packets fail transmission
+ * outright, we automatically ratchet down the rate; otherwise, we
+ * switch to the best rate whenever the current rate's goodness falls
+ * below some threshold, and try increasing our rate when the goodness
+ * is very high.
+ *
+ * This system is optimized for iPXE's style of usage. Because normal
+ * operation always involves receiving something, we'll make our way
+ * to the best rate pretty quickly. We tend to follow the lead of the
+ * sending AP in choosing rates, but we won't use rates for long that
+ * don't work well for us in transmission. We assume iPXE won't be
+ * running for long enough that rate patterns will change much, so we
+ * don't have to keep time counters or the like. And if this doesn't
+ * work well in practice there are many ways it could be tweaked.
+ *
+ * To avoid staying at 1Mbps for a long time, we don't track any
+ * transmitted packets until we've set our rate based on received
+ * packets.
+ */
+
+/** Two-bit packet status indicator for a packet with no retries */
+#define RC_PKT_OK 0x3
+
+/** Two-bit packet status indicator for a packet with one retry */
+#define RC_PKT_RETRIED_ONCE 0x2
+
+/** Two-bit packet status indicator for a TX packet with multiple retries
+ *
+ * It is not possible to tell whether an RX packet had one or multiple
+ * retries; we rely instead on the fact that failed RX packets won't
+ * get to us at all, so if we receive a lot of RX packets on a certain
+ * rate it must be pretty good.
+ */
+#define RC_PKT_RETRIED_MULTI 0x1
+
+/** Two-bit packet status indicator for a TX packet that was never ACKed
+ *
+ * It is not possible to tell whether an RX packet was setn if it
+ * didn't get through to us, but if we don't see one we won't increase
+ * the goodness for its rate. This asymmetry is part of why TX packets
+ * are weighted much more heavily than RX.
+ */
+#define RC_PKT_FAILED 0x0
+
+/** Number of times to weight TX packets more heavily than RX packets */
+#define RC_TX_FACTOR 4
+
+/** Number of consecutive failed TX packets that cause an automatic rate drop */
+#define RC_TX_EMERG_FAIL 3
+
+/** Minimum net goodness below which we will search for a better rate */
+#define RC_GOODNESS_MIN 85
+
+/** Maximum net goodness above which we will try to increase our rate */
+#define RC_GOODNESS_MAX 95
+
+/** Minimum (num RX + @c RC_TX_FACTOR * num TX) to use a certain rate */
+#define RC_UNCERTAINTY_THRESH 4
+
+/** TX direction */
+#define TX 0
+
+/** RX direction */
+#define RX 1
+
+/** A rate control context */
+struct rc80211_ctx
+{
+ /** Goodness state for each rate, TX and RX */
+ u32 goodness[2][NET80211_MAX_RATES];
+
+ /** Number of packets recorded for each rate */
+ u8 count[2][NET80211_MAX_RATES];
+
+ /** Indication of whether we've set the device rate yet */
+ int started;
+
+ /** Counter of all packets sent and received */
+ int packets;
+};
+
+/**
+ * Initialize rate-control algorithm
+ *
+ * @v dev 802.11 device
+ * @ret ctx Rate-control context, to be stored in @c dev->rctl
+ */
+struct rc80211_ctx * rc80211_init ( struct net80211_device *dev __unused )
+{
+ struct rc80211_ctx *ret = zalloc ( sizeof ( *ret ) );
+ return ret;
+}
+
+/**
+ * Calculate net goodness for a certain rate
+ *
+ * @v ctx Rate-control context
+ * @v rate_idx Index of rate to calculate net goodness for
+ */
+static int rc80211_calc_net_goodness ( struct rc80211_ctx *ctx,
+ int rate_idx )
+{
+ int sum[2], num[2], dir, pkt;
+
+ for ( dir = 0; dir < 2; dir++ ) {
+ u32 good = ctx->goodness[dir][rate_idx];
+
+ num[dir] = ctx->count[dir][rate_idx];
+ sum[dir] = 0;
+
+ for ( pkt = 0; pkt < num[dir]; pkt++ )
+ sum[dir] += ( good >> ( 2 * pkt ) ) & 0x3;
+ }
+
+ if ( ( num[TX] * RC_TX_FACTOR + num[RX] ) < RC_UNCERTAINTY_THRESH )
+ return -1;
+
+ return ( 33 * ( sum[TX] * RC_TX_FACTOR + sum[RX] ) /
+ ( num[TX] * RC_TX_FACTOR + num[RX] ) );
+}
+
+/**
+ * Determine the best rate to switch to and return it
+ *
+ * @v dev 802.11 device
+ * @ret rate_idx Index of the best rate to switch to
+ */
+static int rc80211_pick_best ( struct net80211_device *dev )
+{
+ struct rc80211_ctx *ctx = dev->rctl;
+ int best_net_good = 0, best_rate = -1, i;
+
+ for ( i = 0; i < dev->nr_rates; i++ ) {
+ int net_good = rc80211_calc_net_goodness ( ctx, i );
+
+ if ( net_good > best_net_good ||
+ ( best_net_good > RC_GOODNESS_MIN &&
+ net_good > RC_GOODNESS_MIN ) ) {
+ best_net_good = net_good;
+ best_rate = i;
+ }
+ }
+
+ if ( best_rate >= 0 ) {
+ int old_good = rc80211_calc_net_goodness ( ctx, dev->rate );
+ if ( old_good != best_net_good )
+ DBGC ( ctx, "802.11 RC %p switching from goodness "
+ "%d to %d\n", ctx, old_good, best_net_good );
+
+ ctx->started = 1;
+ return best_rate;
+ }
+
+ return dev->rate;
+}
+
+/**
+ * Set 802.11 device rate
+ *
+ * @v dev 802.11 device
+ * @v rate_idx Index of rate to switch to
+ *
+ * This is a thin wrapper around net80211_set_rate_idx to insert a
+ * debugging message where appropriate.
+ */
+static inline void rc80211_set_rate ( struct net80211_device *dev,
+ int rate_idx )
+{
+ DBGC ( dev->rctl, "802.11 RC %p changing rate %d->%d Mbps\n", dev->rctl,
+ dev->rates[dev->rate] / 10, dev->rates[rate_idx] / 10 );
+
+ net80211_set_rate_idx ( dev, rate_idx );
+}
+
+/**
+ * Check rate-control state and change rate if necessary
+ *
+ * @v dev 802.11 device
+ */
+static void rc80211_maybe_set_new ( struct net80211_device *dev )
+{
+ struct rc80211_ctx *ctx = dev->rctl;
+ int net_good;
+
+ net_good = rc80211_calc_net_goodness ( ctx, dev->rate );
+
+ if ( ! ctx->started ) {
+ rc80211_set_rate ( dev, rc80211_pick_best ( dev ) );
+ return;
+ }
+
+ if ( net_good < 0 ) /* insufficient data */
+ return;
+
+ if ( net_good > RC_GOODNESS_MAX && dev->rate + 1 < dev->nr_rates ) {
+ int higher = rc80211_calc_net_goodness ( ctx, dev->rate + 1 );
+ if ( higher > net_good || higher < 0 )
+ rc80211_set_rate ( dev, dev->rate + 1 );
+ else
+ rc80211_set_rate ( dev, rc80211_pick_best ( dev ) );
+ }
+
+ if ( net_good < RC_GOODNESS_MIN ) {
+ rc80211_set_rate ( dev, rc80211_pick_best ( dev ) );
+ }
+}
+
+/**
+ * Update rate-control state
+ *
+ * @v dev 802.11 device
+ * @v direction One of the direction constants TX or RX
+ * @v rate_idx Index of rate at which packet was sent or received
+ * @v retries Number of times packet was retried before success
+ * @v failed If nonzero, the packet failed to get through
+ */
+static void rc80211_update ( struct net80211_device *dev, int direction,
+ int rate_idx, int retries, int failed )
+{
+ struct rc80211_ctx *ctx = dev->rctl;
+ u32 goodness = ctx->goodness[direction][rate_idx];
+
+ if ( ctx->count[direction][rate_idx] < 16 )
+ ctx->count[direction][rate_idx]++;
+
+ goodness <<= 2;
+ if ( failed )
+ goodness |= RC_PKT_FAILED;
+ else if ( retries > 1 )
+ goodness |= RC_PKT_RETRIED_MULTI;
+ else if ( retries )
+ goodness |= RC_PKT_RETRIED_ONCE;
+ else
+ goodness |= RC_PKT_OK;
+
+ ctx->goodness[direction][rate_idx] = goodness;
+
+ ctx->packets++;
+
+ rc80211_maybe_set_new ( dev );
+}
+
+/**
+ * Update rate-control state for transmitted packet
+ *
+ * @v dev 802.11 device
+ * @v retries Number of times packet was transmitted before success
+ * @v rc Return status code for transmission
+ */
+void rc80211_update_tx ( struct net80211_device *dev, int retries, int rc )
+{
+ struct rc80211_ctx *ctx = dev->rctl;
+
+ if ( ! ctx->started )
+ return;
+
+ rc80211_update ( dev, TX, dev->rate, retries, rc );
+
+ /* Check if the last RC_TX_EMERG_FAIL packets have all failed */
+ if ( ! ( ctx->goodness[TX][dev->rate] &
+ ( ( 1 << ( 2 * RC_TX_EMERG_FAIL ) ) - 1 ) ) ) {
+ if ( dev->rate == 0 )
+ DBGC ( dev->rctl, "802.11 RC %p saw %d consecutive "
+ "failed TX, but cannot lower rate any further\n",
+ dev->rctl, RC_TX_EMERG_FAIL );
+ else {
+ DBGC ( dev->rctl, "802.11 RC %p lowering rate (%d->%d "
+ "Mbps) due to %d consecutive TX failures\n",
+ dev->rctl, dev->rates[dev->rate] / 10,
+ dev->rates[dev->rate - 1] / 10,
+ RC_TX_EMERG_FAIL );
+
+ rc80211_set_rate ( dev, dev->rate - 1 );
+ }
+ }
+}
+
+/**
+ * Update rate-control state for received packet
+ *
+ * @v dev 802.11 device
+ * @v retry Whether the received packet had been retransmitted
+ * @v rate Rate at which packet was received, in 100 kbps units
+ */
+void rc80211_update_rx ( struct net80211_device *dev, int retry, u16 rate )
+{
+ int ridx;
+
+ for ( ridx = 0; ridx < dev->nr_rates && dev->rates[ridx] != rate;
+ ridx++ )
+ ;
+ if ( ridx >= dev->nr_rates )
+ return; /* couldn't find the rate */
+
+ rc80211_update ( dev, RX, ridx, retry, 0 );
+}
+
+/**
+ * Free rate-control context
+ *
+ * @v ctx Rate-control context
+ */
+void rc80211_free ( struct rc80211_ctx *ctx )
+{
+ free ( ctx );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/80211/sec80211.c b/src/VBox/Devices/PC/ipxe/src/net/80211/sec80211.c
new file mode 100644
index 00000000..82b1ce94
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/80211/sec80211.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/ieee80211.h>
+#include <ipxe/net80211.h>
+#include <ipxe/sec80211.h>
+
+/** @file
+ *
+ * General secured-network routines required whenever any secure
+ * network support at all is compiled in. This involves things like
+ * installing keys, determining the type of security used by a probed
+ * network, and some small helper functions that take advantage of
+ * static data in this file.
+ */
+
+/* Unsupported cryptosystem error numbers */
+#define ENOTSUP_WEP __einfo_error ( EINFO_ENOTSUP_WEP )
+#define EINFO_ENOTSUP_WEP __einfo_uniqify ( EINFO_ENOTSUP, \
+ ( 0x10 | NET80211_CRYPT_WEP ), "WEP not supported" )
+#define ENOTSUP_TKIP __einfo_error ( EINFO_ENOTSUP_TKIP )
+#define EINFO_ENOTSUP_TKIP __einfo_uniqify ( EINFO_ENOTSUP, \
+ ( 0x10 | NET80211_CRYPT_TKIP ), "TKIP not supported" )
+#define ENOTSUP_CCMP __einfo_error ( EINFO_ENOTSUP_CCMP )
+#define EINFO_ENOTSUP_CCMP __einfo_uniqify ( EINFO_ENOTSUP, \
+ ( 0x10 | NET80211_CRYPT_CCMP ), "CCMP not supported" )
+#define ENOTSUP_CRYPT( crypt ) \
+ EUNIQ ( ENOTSUP, ( 0x10 | (crypt) ), \
+ ENOTSUP_WEP, ENOTSUP_TKIP, ENOTSUP_CCMP )
+
+/** Mapping from net80211 crypto/secprot types to RSN OUI descriptors */
+struct descriptor_map {
+ /** Value of net80211_crypto_alg or net80211_security_proto */
+ u32 net80211_type;
+
+ /** OUI+type in appropriate byte order, masked to exclude vendor */
+ u32 oui_type;
+};
+
+/** Magic number in @a oui_type showing end of list */
+#define END_MAGIC 0xFFFFFFFF
+
+/** Mapping between net80211 cryptosystems and 802.11i cipher IDs */
+static struct descriptor_map rsn_cipher_map[] = {
+ { .net80211_type = NET80211_CRYPT_WEP,
+ .oui_type = IEEE80211_RSN_CTYPE_WEP40 },
+
+ { .net80211_type = NET80211_CRYPT_WEP,
+ .oui_type = IEEE80211_RSN_CTYPE_WEP104 },
+
+ { .net80211_type = NET80211_CRYPT_TKIP,
+ .oui_type = IEEE80211_RSN_CTYPE_TKIP },
+
+ { .net80211_type = NET80211_CRYPT_CCMP,
+ .oui_type = IEEE80211_RSN_CTYPE_CCMP },
+
+ { .net80211_type = NET80211_CRYPT_UNKNOWN,
+ .oui_type = END_MAGIC },
+};
+
+/** Mapping between net80211 handshakers and 802.11i AKM IDs */
+static struct descriptor_map rsn_akm_map[] = {
+ { .net80211_type = NET80211_SECPROT_EAP,
+ .oui_type = IEEE80211_RSN_ATYPE_8021X },
+
+ { .net80211_type = NET80211_SECPROT_PSK,
+ .oui_type = IEEE80211_RSN_ATYPE_PSK },
+
+ { .net80211_type = NET80211_SECPROT_UNKNOWN,
+ .oui_type = END_MAGIC },
+};
+
+
+/**
+ * Install 802.11 cryptosystem
+ *
+ * @v which Pointer to the cryptosystem structure to install in
+ * @v crypt Cryptosystem ID number
+ * @v key Encryption key to use
+ * @v len Length of encryption key
+ * @v rsc Initial receive sequence counter, if applicable
+ * @ret rc Return status code
+ *
+ * The encryption key will not be accessed via the provided pointer
+ * after this function returns, so you may keep it on the stack.
+ *
+ * @a which must point to either @c dev->crypto (for the normal case
+ * of installing a unicast cryptosystem) or @c dev->gcrypto (to
+ * install a cryptosystem that will be used only for decrypting
+ * group-source frames).
+ */
+int sec80211_install ( struct net80211_crypto **which,
+ enum net80211_crypto_alg crypt,
+ const void *key, int len, const void *rsc )
+{
+ struct net80211_crypto *crypto = *which;
+ struct net80211_crypto *tbl_crypto;
+
+ /* Remove old crypto if it exists */
+ free ( *which );
+ *which = NULL;
+
+ if ( crypt == NET80211_CRYPT_NONE ) {
+ DBG ( "802.11-Sec not installing null cryptography\n" );
+ return 0;
+ }
+
+ /* Find cryptosystem to use */
+ for_each_table_entry ( tbl_crypto, NET80211_CRYPTOS ) {
+ if ( tbl_crypto->algorithm == crypt ) {
+ crypto = zalloc ( sizeof ( *crypto ) +
+ tbl_crypto->priv_len );
+ if ( ! crypto ) {
+ DBG ( "802.11-Sec out of memory\n" );
+ return -ENOMEM;
+ }
+
+ memcpy ( crypto, tbl_crypto, sizeof ( *crypto ) );
+ crypto->priv = ( ( void * ) crypto +
+ sizeof ( *crypto ) );
+ break;
+ }
+ }
+
+ if ( ! crypto ) {
+ DBG ( "802.11-Sec no support for cryptosystem %d\n", crypt );
+ return -ENOTSUP_CRYPT ( crypt );
+ }
+
+ *which = crypto;
+
+ DBG ( "802.11-Sec installing cryptosystem %d as %p with key of "
+ "length %d\n", crypt, crypto, len );
+
+ return crypto->init ( crypto, key, len, rsc );
+}
+
+
+/**
+ * Determine net80211 crypto or handshaking type value to return for RSN info
+ *
+ * @v rsnp Pointer to next descriptor count field in RSN IE
+ * @v rsn_end Pointer to end of RSN IE
+ * @v map Descriptor map to use
+ * @v tbl_start Start of linker table to examine for iPXE support
+ * @v tbl_end End of linker table to examine for iPXE support
+ * @ret rsnp Updated to point to first byte after descriptors
+ * @ret map_ent Descriptor map entry of translation to use
+ *
+ * The entries in the linker table must be either net80211_crypto or
+ * net80211_handshaker structures, and @a tbl_stride must be set to
+ * sizeof() the appropriate one.
+ *
+ * This function expects @a rsnp to point at a two-byte descriptor
+ * count followed by a list of four-byte cipher or AKM descriptors; it
+ * will return @c NULL if the input packet is malformed, and otherwise
+ * set @a rsnp to the first byte it has not looked at. It will return
+ * the first cipher in the list that is supported by the current build
+ * of iPXE, or the first of all if none are supported.
+ *
+ * We play rather fast and loose with type checking, because this
+ * function is only called from two well-defined places in the
+ * RSN-checking code. Don't try to use it for anything else.
+ */
+static struct descriptor_map * rsn_pick_desc ( u8 **rsnp, u8 *rsn_end,
+ struct descriptor_map *map,
+ void *tbl_start, void *tbl_end )
+{
+ int ndesc;
+ int ok = 0;
+ struct descriptor_map *map_ent, *map_ret = NULL;
+ u8 *rsn = *rsnp;
+ void *tblp;
+ size_t tbl_stride = ( map == rsn_cipher_map ?
+ sizeof ( struct net80211_crypto ) :
+ sizeof ( struct net80211_handshaker ) );
+
+ if ( map != rsn_cipher_map && map != rsn_akm_map )
+ return NULL;
+
+ /* Determine which types we support */
+ for ( tblp = tbl_start; tblp < tbl_end; tblp += tbl_stride ) {
+ struct net80211_crypto *crypto = tblp;
+ struct net80211_handshaker *hs = tblp;
+
+ if ( map == rsn_cipher_map )
+ ok |= ( 1 << crypto->algorithm );
+ else
+ ok |= ( 1 << hs->protocol );
+ }
+
+ /* RSN sanity checks */
+ if ( rsn + 2 > rsn_end ) {
+ DBG ( "RSN detect: malformed descriptor count\n" );
+ return NULL;
+ }
+
+ ndesc = *( u16 * ) rsn;
+ rsn += 2;
+
+ if ( ! ndesc ) {
+ DBG ( "RSN detect: no descriptors\n" );
+ return NULL;
+ }
+
+ /* Determine which net80211 crypto types are listed */
+ while ( ndesc-- ) {
+ u32 desc;
+
+ if ( rsn + 4 > rsn_end ) {
+ DBG ( "RSN detect: malformed descriptor (%d left)\n",
+ ndesc );
+ return NULL;
+ }
+
+ desc = *( u32 * ) rsn;
+ rsn += 4;
+
+ for ( map_ent = map; map_ent->oui_type != END_MAGIC; map_ent++ )
+ if ( map_ent->oui_type == ( desc & OUI_TYPE_MASK ) )
+ break;
+
+ /* Use first cipher as a fallback */
+ if ( ! map_ret )
+ map_ret = map_ent;
+
+ /* Once we find one we support, use it */
+ if ( ok & ( 1 << map_ent->net80211_type ) ) {
+ map_ret = map_ent;
+ break;
+ }
+ }
+
+ if ( ndesc > 0 )
+ rsn += 4 * ndesc;
+
+ *rsnp = rsn;
+ return map_ret;
+}
+
+
+/**
+ * Find the RSN or WPA information element in the provided beacon frame
+ *
+ * @v ie Pointer to first information element to check
+ * @v ie_end Pointer to end of information element space
+ * @ret is_rsn TRUE if returned IE is RSN, FALSE if it's WPA
+ * @ret end Pointer to byte immediately after last byte of data
+ * @ret data Pointer to first byte of data (the `version' field)
+ *
+ * If both an RSN and a WPA information element are found, this
+ * function will return the first one seen, which by ordering rules
+ * should always prefer the newer RSN IE.
+ *
+ * If no RSN or WPA infomration element is found, returns @c NULL and
+ * leaves @a is_rsn and @a end in an undefined state.
+ *
+ * This function will not return a pointer to an information element
+ * that states it extends past the tail of the io_buffer, or whose @a
+ * version field is incorrect.
+ */
+u8 * sec80211_find_rsn ( union ieee80211_ie *ie, void *ie_end,
+ int *is_rsn, u8 **end )
+{
+ u8 *rsn = NULL;
+
+ if ( ! ieee80211_ie_bound ( ie, ie_end ) )
+ return NULL;
+
+ while ( ie ) {
+ if ( ie->id == IEEE80211_IE_VENDOR &&
+ ie->vendor.oui == IEEE80211_WPA_OUI_VEN ) {
+ DBG ( "RSN detect: old-style WPA IE found\n" );
+ rsn = &ie->vendor.data[0];
+ *end = rsn + ie->len - 4;
+ *is_rsn = 0;
+ } else if ( ie->id == IEEE80211_IE_RSN ) {
+ DBG ( "RSN detect: 802.11i RSN IE found\n" );
+ rsn = ( u8 * ) &ie->rsn.version;
+ *end = rsn + ie->len;
+ *is_rsn = 1;
+ }
+
+ if ( rsn && ( *end > ( u8 * ) ie_end || rsn >= *end ||
+ *( u16 * ) rsn != IEEE80211_RSN_VERSION ) ) {
+ DBG ( "RSN detect: malformed RSN IE or unknown "
+ "version, keep trying\n" );
+ rsn = NULL;
+ }
+
+ if ( rsn )
+ break;
+
+ ie = ieee80211_next_ie ( ie, ie_end );
+ }
+
+ if ( ! ie ) {
+ DBG ( "RSN detect: no RSN IE found\n" );
+ return NULL;
+ }
+
+ return rsn;
+}
+
+
+/**
+ * Detect crypto and AKM types from RSN information element
+ *
+ * @v is_rsn If TRUE, IE is a new-style RSN information element
+ * @v start Pointer to first byte of @a version field
+ * @v end Pointer to first byte not in the RSN IE
+ * @ret secprot Security handshaking protocol used by network
+ * @ret crypt Cryptosystem used by network
+ * @ret rc Return status code
+ *
+ * If the IE cannot be parsed, returns an error indication and leaves
+ * @a secprot and @a crypt unchanged.
+ */
+int sec80211_detect_ie ( int is_rsn, u8 *start, u8 *end,
+ enum net80211_security_proto *secprot,
+ enum net80211_crypto_alg *crypt )
+{
+ enum net80211_security_proto sp;
+ enum net80211_crypto_alg cr;
+ struct descriptor_map *map;
+ u8 *rsn = start;
+
+ /* Set some defaults */
+ cr = ( is_rsn ? NET80211_CRYPT_CCMP : NET80211_CRYPT_TKIP );
+ sp = NET80211_SECPROT_EAP;
+
+ rsn += 2; /* version - already checked */
+ rsn += 4; /* group cipher - we don't use it here */
+
+ if ( rsn >= end )
+ goto done;
+
+ /* Pick crypto algorithm */
+ map = rsn_pick_desc ( &rsn, end, rsn_cipher_map,
+ table_start ( NET80211_CRYPTOS ),
+ table_end ( NET80211_CRYPTOS ) );
+ if ( ! map )
+ goto invalid_rsn;
+
+ cr = map->net80211_type;
+
+ if ( rsn >= end )
+ goto done;
+
+ /* Pick handshaking algorithm */
+ map = rsn_pick_desc ( &rsn, end, rsn_akm_map,
+ table_start ( NET80211_HANDSHAKERS ),
+ table_end ( NET80211_HANDSHAKERS ) );
+ if ( ! map )
+ goto invalid_rsn;
+
+ sp = map->net80211_type;
+
+ done:
+ DBG ( "RSN detect: OK, crypto type %d, secprot type %d\n", cr, sp );
+ *secprot = sp;
+ *crypt = cr;
+ return 0;
+
+ invalid_rsn:
+ DBG ( "RSN detect: invalid RSN IE\n" );
+ return -EINVAL;
+}
+
+
+/**
+ * Detect the cryptosystem and handshaking protocol used by an 802.11 network
+ *
+ * @v iob I/O buffer containing beacon frame
+ * @ret secprot Security handshaking protocol used by network
+ * @ret crypt Cryptosystem used by network
+ * @ret rc Return status code
+ *
+ * This function uses weak linkage, as it must be called from generic
+ * contexts but should only be linked in if some encryption is
+ * supported; you must test its address against @c NULL before calling
+ * it. If it does not exist, any network with the PRIVACY bit set in
+ * beacon->capab should be considered unknown.
+ */
+int sec80211_detect ( struct io_buffer *iob,
+ enum net80211_security_proto *secprot,
+ enum net80211_crypto_alg *crypt )
+{
+ struct ieee80211_frame *hdr = iob->data;
+ struct ieee80211_beacon *beacon =
+ ( struct ieee80211_beacon * ) hdr->data;
+ u8 *rsn, *rsn_end;
+ int is_rsn, rc;
+
+ *crypt = NET80211_CRYPT_UNKNOWN;
+ *secprot = NET80211_SECPROT_UNKNOWN;
+
+ /* Find RSN or WPA IE */
+ if ( ! ( rsn = sec80211_find_rsn ( beacon->info_element, iob->tail,
+ &is_rsn, &rsn_end ) ) ) {
+ /* No security IE at all; either WEP or no security. */
+ *secprot = NET80211_SECPROT_NONE;
+
+ if ( beacon->capability & IEEE80211_CAPAB_PRIVACY )
+ *crypt = NET80211_CRYPT_WEP;
+ else
+ *crypt = NET80211_CRYPT_NONE;
+
+ return 0;
+ }
+
+ /* Determine type of security */
+ if ( ( rc = sec80211_detect_ie ( is_rsn, rsn, rsn_end, secprot,
+ crypt ) ) == 0 )
+ return 0;
+
+ /* If we get here, the RSN IE was invalid */
+
+ *crypt = NET80211_CRYPT_UNKNOWN;
+ *secprot = NET80211_SECPROT_UNKNOWN;
+ DBG ( "Failed to handle RSN IE:\n" );
+ DBG_HD ( rsn, rsn_end - rsn );
+ return rc;
+}
+
+
+/**
+ * Determine RSN descriptor for specified net80211 ID
+ *
+ * @v id net80211 ID value
+ * @v rsnie Whether to return a new-format (RSN IE) descriptor
+ * @v map Map to use in translation
+ * @ret desc RSN descriptor, or 0 on error
+ *
+ * If @a rsnie is false, returns an old-format (WPA vendor IE)
+ * descriptor.
+ */
+static u32 rsn_get_desc ( unsigned id, int rsnie, struct descriptor_map *map )
+{
+ u32 vendor = ( rsnie ? IEEE80211_RSN_OUI : IEEE80211_WPA_OUI );
+
+ for ( ; map->oui_type != END_MAGIC; map++ ) {
+ if ( map->net80211_type == id )
+ return map->oui_type | vendor;
+ }
+
+ return 0;
+}
+
+/**
+ * Determine RSN descriptor for specified net80211 cryptosystem number
+ *
+ * @v crypt Cryptosystem number
+ * @v rsnie Whether to return a new-format (RSN IE) descriptor
+ * @ret desc RSN descriptor
+ *
+ * If @a rsnie is false, returns an old-format (WPA vendor IE)
+ * descriptor.
+ */
+u32 sec80211_rsn_get_crypto_desc ( enum net80211_crypto_alg crypt, int rsnie )
+{
+ return rsn_get_desc ( crypt, rsnie, rsn_cipher_map );
+}
+
+/**
+ * Determine RSN descriptor for specified net80211 handshaker number
+ *
+ * @v secprot Handshaker number
+ * @v rsnie Whether to return a new-format (RSN IE) descriptor
+ * @ret desc RSN descriptor
+ *
+ * If @a rsnie is false, returns an old-format (WPA vendor IE)
+ * descriptor.
+ */
+u32 sec80211_rsn_get_akm_desc ( enum net80211_security_proto secprot,
+ int rsnie )
+{
+ return rsn_get_desc ( secprot, rsnie, rsn_akm_map );
+}
+
+/**
+ * Determine net80211 cryptosystem number from RSN descriptor
+ *
+ * @v desc RSN descriptor
+ * @ret crypt net80211 cryptosystem enumeration value
+ */
+enum net80211_crypto_alg sec80211_rsn_get_net80211_crypt ( u32 desc )
+{
+ struct descriptor_map *map = rsn_cipher_map;
+
+ for ( ; map->oui_type != END_MAGIC; map++ ) {
+ if ( map->oui_type == ( desc & OUI_TYPE_MASK ) )
+ break;
+ }
+
+ return map->net80211_type;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/80211/wep.c b/src/VBox/Devices/PC/ipxe/src/net/80211/wep.c
new file mode 100644
index 00000000..3b104552
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/80211/wep.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/net80211.h>
+#include <ipxe/sec80211.h>
+#include <ipxe/crypto.h>
+#include <ipxe/arc4.h>
+#include <ipxe/crc32.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/** @file
+ *
+ * The WEP wireless encryption method (insecure!)
+ *
+ * The data field in a WEP-encrypted packet contains a 3-byte
+ * initialisation vector, one-byte Key ID field (only the bottom two
+ * bits are ever used), encrypted data, and a 4-byte encrypted CRC of
+ * the plaintext data, called the ICV. To decrypt it, the IV is
+ * prepended to the shared key and the data stream (including ICV) is
+ * run through the ARC4 stream cipher; if the ICV matches a CRC32
+ * calculated on the plaintext, the packet is valid.
+ *
+ * For efficiency and code-size reasons, this file assumes it is
+ * running on a little-endian machine.
+ */
+
+/** Length of WEP initialisation vector */
+#define WEP_IV_LEN 3
+
+/** Length of WEP key ID byte */
+#define WEP_KID_LEN 1
+
+/** Length of WEP ICV checksum */
+#define WEP_ICV_LEN 4
+
+/** Maximum length of WEP key */
+#define WEP_MAX_KEY 16
+
+/** Amount of data placed before the encrypted bytes */
+#define WEP_HEADER_LEN 4
+
+/** Amount of data placed after the encrypted bytes */
+#define WEP_TRAILER_LEN 4
+
+/** Total WEP overhead bytes */
+#define WEP_OVERHEAD 8
+
+/** Context for WEP encryption and decryption */
+struct wep_ctx
+{
+ /** Encoded WEP key
+ *
+ * The actual key bytes are stored beginning at offset 3, to
+ * leave room for easily inserting the IV before a particular
+ * operation.
+ */
+ u8 key[WEP_IV_LEN + WEP_MAX_KEY];
+
+ /** Length of WEP key (not including IV bytes) */
+ int keylen;
+
+ /** ARC4 context */
+ struct arc4_ctx arc4;
+};
+
+/**
+ * Initialize WEP algorithm
+ *
+ * @v crypto 802.11 cryptographic algorithm
+ * @v key WEP key to use
+ * @v keylen Length of WEP key
+ * @v rsc Initial receive sequence counter (unused)
+ * @ret rc Return status code
+ *
+ * Standard key lengths are 5 and 13 bytes; 16-byte keys are
+ * occasionally supported as an extension to the standard.
+ */
+static int wep_init ( struct net80211_crypto *crypto, const void *key,
+ int keylen, const void *rsc __unused )
+{
+ struct wep_ctx *ctx = crypto->priv;
+
+ ctx->keylen = ( keylen > WEP_MAX_KEY ? WEP_MAX_KEY : keylen );
+ memcpy ( ctx->key + WEP_IV_LEN, key, ctx->keylen );
+
+ return 0;
+}
+
+/**
+ * Encrypt packet using WEP
+ *
+ * @v crypto 802.11 cryptographic algorithm
+ * @v iob I/O buffer of plaintext packet
+ * @ret eiob Newly allocated I/O buffer for encrypted packet, or NULL
+ *
+ * If memory allocation fails, @c NULL is returned.
+ */
+static struct io_buffer * wep_encrypt ( struct net80211_crypto *crypto,
+ struct io_buffer *iob )
+{
+ struct wep_ctx *ctx = crypto->priv;
+ struct io_buffer *eiob;
+ struct ieee80211_frame *hdr;
+ const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
+ int datalen = iob_len ( iob ) - hdrlen;
+ int newlen = hdrlen + datalen + WEP_OVERHEAD;
+ u32 iv, icv;
+
+ eiob = alloc_iob ( newlen );
+ if ( ! eiob )
+ return NULL;
+
+ memcpy ( iob_put ( eiob, hdrlen ), iob->data, hdrlen );
+ hdr = eiob->data;
+ hdr->fc |= IEEE80211_FC_PROTECTED;
+
+ /* Calculate IV, put it in the header (with key ID byte = 0), and
+ set it up at the start of the encryption key. */
+ iv = random() & 0xffffff; /* IV in bottom 3 bytes, top byte = KID = 0 */
+ memcpy ( iob_put ( eiob, WEP_HEADER_LEN ), &iv, WEP_HEADER_LEN );
+ memcpy ( ctx->key, &iv, WEP_IV_LEN );
+
+ /* Encrypt the data using RC4 */
+ cipher_setkey ( &arc4_algorithm, &ctx->arc4, ctx->key,
+ ctx->keylen + WEP_IV_LEN );
+ cipher_encrypt ( &arc4_algorithm, &ctx->arc4, iob->data + hdrlen,
+ iob_put ( eiob, datalen ), datalen );
+
+ /* Add ICV */
+ icv = ~crc32_le ( ~0, iob->data + hdrlen, datalen );
+ cipher_encrypt ( &arc4_algorithm, &ctx->arc4, &icv,
+ iob_put ( eiob, WEP_ICV_LEN ), WEP_ICV_LEN );
+
+ return eiob;
+}
+
+/**
+ * Decrypt packet using WEP
+ *
+ * @v crypto 802.11 cryptographic algorithm
+ * @v eiob I/O buffer of encrypted packet
+ * @ret iob Newly allocated I/O buffer for plaintext packet, or NULL
+ *
+ * If a consistency check for the decryption fails (usually indicating
+ * an invalid key), @c NULL is returned.
+ */
+static struct io_buffer * wep_decrypt ( struct net80211_crypto *crypto,
+ struct io_buffer *eiob )
+{
+ struct wep_ctx *ctx = crypto->priv;
+ struct io_buffer *iob;
+ struct ieee80211_frame *hdr;
+ const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
+ int datalen = iob_len ( eiob ) - hdrlen - WEP_OVERHEAD;
+ int newlen = hdrlen + datalen;
+ u32 iv, icv, crc;
+
+ iob = alloc_iob ( newlen );
+ if ( ! iob )
+ return NULL;
+
+ memcpy ( iob_put ( iob, hdrlen ), eiob->data, hdrlen );
+ hdr = iob->data;
+ hdr->fc &= ~IEEE80211_FC_PROTECTED;
+
+ /* Strip off IV and use it to initialize cryptosystem */
+ memcpy ( &iv, eiob->data + hdrlen, 4 );
+ iv &= 0xffffff; /* ignore key ID byte */
+ memcpy ( ctx->key, &iv, WEP_IV_LEN );
+
+ /* Decrypt the data using RC4 */
+ cipher_setkey ( &arc4_algorithm, &ctx->arc4, ctx->key,
+ ctx->keylen + WEP_IV_LEN );
+ cipher_decrypt ( &arc4_algorithm, &ctx->arc4, eiob->data + hdrlen +
+ WEP_HEADER_LEN, iob_put ( iob, datalen ), datalen );
+
+ /* Strip off ICV and verify it */
+ cipher_decrypt ( &arc4_algorithm, &ctx->arc4, eiob->data + hdrlen +
+ WEP_HEADER_LEN + datalen, &icv, WEP_ICV_LEN );
+ crc = ~crc32_le ( ~0, iob->data + hdrlen, datalen );
+ if ( crc != icv ) {
+ DBGC ( crypto, "WEP %p CRC mismatch: expect %08x, get %08x\n",
+ crypto, icv, crc );
+ free_iob ( iob );
+ return NULL;
+ }
+ return iob;
+}
+
+/** WEP cryptosystem for 802.11 */
+struct net80211_crypto wep_crypto __net80211_crypto = {
+ .algorithm = NET80211_CRYPT_WEP,
+ .init = wep_init,
+ .encrypt = wep_encrypt,
+ .decrypt = wep_decrypt,
+ .priv_len = sizeof ( struct wep_ctx ),
+};
+
+/**
+ * Initialize trivial 802.11 security handshaker
+ *
+ * @v dev 802.11 device
+ * @v ctx Security handshaker
+ *
+ * This simply fetches a WEP key from netX/key, and if it exists,
+ * installs WEP cryptography on the 802.11 device. No real handshaking
+ * is performed.
+ */
+static int trivial_init ( struct net80211_device *dev )
+{
+ u8 key[WEP_MAX_KEY]; /* support up to 128-bit keys */
+ int len;
+ int rc;
+
+ if ( dev->associating &&
+ dev->associating->crypto == NET80211_CRYPT_NONE )
+ return 0; /* no crypto? OK. */
+
+ len = fetch_setting ( netdev_settings ( dev->netdev ),
+ &net80211_key_setting, key, WEP_MAX_KEY );
+
+ if ( len <= 0 ) {
+ DBGC ( dev, "802.11 %p cannot do WEP without a key\n", dev );
+ return -EACCES;
+ }
+
+ /* Full 128-bit keys are a nonstandard extension, but they're
+ utterly trivial to support, so we do. */
+ if ( len != 5 && len != 13 && len != 16 ) {
+ DBGC ( dev, "802.11 %p invalid WEP key length %d\n",
+ dev, len );
+ return -EINVAL;
+ }
+
+ DBGC ( dev, "802.11 %p installing %d-bit WEP\n", dev, len * 8 );
+
+ rc = sec80211_install ( &dev->crypto, NET80211_CRYPT_WEP, key, len,
+ NULL );
+ if ( rc < 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Check for key change on trivial 802.11 security handshaker
+ *
+ * @v dev 802.11 device
+ * @v ctx Security handshaker
+ */
+static int trivial_change_key ( struct net80211_device *dev )
+{
+ u8 key[WEP_MAX_KEY];
+ int len;
+ int change = 0;
+
+ /* If going from WEP to clear, or something else to WEP, reassociate. */
+ if ( ! dev->crypto || ( dev->crypto->init != wep_init ) )
+ change ^= 1;
+
+ len = fetch_setting ( netdev_settings ( dev->netdev ),
+ &net80211_key_setting, key, WEP_MAX_KEY );
+ if ( len <= 0 )
+ change ^= 1;
+
+ /* Changing crypto type => return nonzero to reassociate. */
+ if ( change )
+ return -EINVAL;
+
+ /* Going from no crypto to still no crypto => nothing to do. */
+ if ( len <= 0 )
+ return 0;
+
+ /* Otherwise, reinitialise WEP with new key. */
+ return wep_init ( dev->crypto, key, len, NULL );
+}
+
+/** Trivial 802.11 security handshaker */
+struct net80211_handshaker trivial_handshaker __net80211_handshaker = {
+ .protocol = NET80211_SECPROT_NONE,
+ .init = trivial_init,
+ .change_key = trivial_change_key,
+ .priv_len = 0,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/80211/wpa.c b/src/VBox/Devices/PC/ipxe/src/net/80211/wpa.c
new file mode 100644
index 00000000..45def8c1
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/80211/wpa.c
@@ -0,0 +1,914 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/net80211.h>
+#include <ipxe/sec80211.h>
+#include <ipxe/wpa.h>
+#include <ipxe/eapol.h>
+#include <ipxe/crypto.h>
+#include <ipxe/arc4.h>
+#include <ipxe/crc32.h>
+#include <ipxe/sha1.h>
+#include <ipxe/hmac.h>
+#include <ipxe/list.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/rbg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <byteswap.h>
+
+/** @file
+ *
+ * Handler for the aspects of WPA handshaking that are independent of
+ * 802.1X/PSK or TKIP/CCMP; this mostly involves the 4-Way Handshake.
+ */
+
+/** List of WPA contexts in active use. */
+struct list_head wpa_contexts = LIST_HEAD_INIT ( wpa_contexts );
+
+
+/**
+ * Return an error code and deauthenticate
+ *
+ * @v ctx WPA common context
+ * @v rc Return status code
+ * @ret rc The passed return status code
+ */
+static int wpa_fail ( struct wpa_common_ctx *ctx, int rc )
+{
+ net80211_deauthenticate ( ctx->dev, rc );
+ return rc;
+}
+
+
+/**
+ * Find a cryptosystem handler structure from a crypto ID
+ *
+ * @v crypt Cryptosystem ID
+ * @ret crypto Cryptosystem handler structure
+ *
+ * If support for @a crypt is not compiled in to iPXE, or if @a crypt
+ * is NET80211_CRYPT_UNKNOWN, returns @c NULL.
+ */
+static struct net80211_crypto *
+wpa_find_cryptosystem ( enum net80211_crypto_alg crypt )
+{
+ struct net80211_crypto *crypto;
+
+ for_each_table_entry ( crypto, NET80211_CRYPTOS ) {
+ if ( crypto->algorithm == crypt )
+ return crypto;
+ }
+
+ return NULL;
+}
+
+
+/**
+ * Find WPA key integrity and encryption handler from key version field
+ *
+ * @v ver Version bits of EAPOL-Key info field
+ * @ret kie Key integrity and encryption handler
+ */
+struct wpa_kie * wpa_find_kie ( int version )
+{
+ struct wpa_kie *kie;
+
+ for_each_table_entry ( kie, WPA_KIES ) {
+ if ( kie->version == version )
+ return kie;
+ }
+
+ return NULL;
+}
+
+
+/**
+ * Construct RSN or WPA information element
+ *
+ * @v dev 802.11 device
+ * @ret ie_ret RSN or WPA information element
+ * @ret rc Return status code
+ *
+ * This function allocates, fills, and returns a RSN or WPA
+ * information element suitable for including in an association
+ * request frame to the network identified by @c dev->associating.
+ * If it is impossible to construct an information element consistent
+ * with iPXE's capabilities that is compatible with that network, or
+ * if none should be sent because that network's beacon included no
+ * security information, returns an error indication and leaves
+ * @a ie_ret unchanged.
+ *
+ * The returned IE will be of the same type (RSN or WPA) as was
+ * included in the beacon for the network it is destined for.
+ */
+int wpa_make_rsn_ie ( struct net80211_device *dev, union ieee80211_ie **ie_ret )
+{
+ u8 *rsn, *rsn_end;
+ int is_rsn;
+ u32 group_cipher;
+ enum net80211_crypto_alg gcrypt;
+ int ie_len;
+ u8 *iep;
+ struct ieee80211_ie_rsn *ie;
+ struct ieee80211_frame *hdr;
+ struct ieee80211_beacon *beacon;
+
+ if ( ! dev->associating ) {
+ DBG ( "WPA: Can't make RSN IE for a non-associating device\n" );
+ return -EINVAL;
+ }
+
+ hdr = dev->associating->beacon->data;
+ beacon = ( struct ieee80211_beacon * ) hdr->data;
+ rsn = sec80211_find_rsn ( beacon->info_element,
+ dev->associating->beacon->tail, &is_rsn,
+ &rsn_end );
+ if ( ! rsn ) {
+ DBG ( "WPA: Can't make RSN IE when we didn't get one\n" );
+ return -EINVAL;
+ }
+
+ rsn += 2; /* skip version */
+ group_cipher = *( u32 * ) rsn;
+ gcrypt = sec80211_rsn_get_net80211_crypt ( group_cipher );
+
+ if ( ! wpa_find_cryptosystem ( gcrypt ) ||
+ ! wpa_find_cryptosystem ( dev->associating->crypto ) ) {
+ DBG ( "WPA: No support for (GC:%d, PC:%d)\n",
+ gcrypt, dev->associating->crypto );
+ return -ENOTSUP;
+ }
+
+ /* Everything looks good - make our IE. */
+
+ /* WPA IEs need 4 more bytes for the OUI+type */
+ ie_len = ieee80211_rsn_size ( 1, 1, 0, is_rsn ) + ( 4 * ! is_rsn );
+ iep = malloc ( ie_len );
+ if ( ! iep )
+ return -ENOMEM;
+
+ *ie_ret = ( union ieee80211_ie * ) iep;
+
+ /* Store ID and length bytes. */
+ *iep++ = ( is_rsn ? IEEE80211_IE_RSN : IEEE80211_IE_VENDOR );
+ *iep++ = ie_len - 2;
+
+ /* Store OUI+type for WPA IEs. */
+ if ( ! is_rsn ) {
+ *( u32 * ) iep = IEEE80211_WPA_OUI_VEN;
+ iep += 4;
+ }
+
+ /* If this is a WPA IE, the id and len bytes in the
+ ieee80211_ie_rsn structure will not be valid, but by doing
+ the cast we can fill all the other fields much more
+ readily. */
+
+ ie = ( struct ieee80211_ie_rsn * ) ( iep - 2 );
+ ie->version = IEEE80211_RSN_VERSION;
+ ie->group_cipher = group_cipher;
+ ie->pairwise_count = 1;
+ ie->pairwise_cipher[0] =
+ sec80211_rsn_get_crypto_desc ( dev->associating->crypto,
+ is_rsn );
+ ie->akm_count = 1;
+ ie->akm_list[0] =
+ sec80211_rsn_get_akm_desc ( dev->associating->handshaking,
+ is_rsn );
+ if ( is_rsn ) {
+ ie->rsn_capab = 0;
+ ie->pmkid_count = 0;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Set up generic WPA support to handle 4-Way Handshake
+ *
+ * @v dev 802.11 device
+ * @v ctx WPA common context
+ * @v pmk Pairwise Master Key to use for session
+ * @v pmk_len Length of PMK, almost always 32
+ * @ret rc Return status code
+ */
+int wpa_start ( struct net80211_device *dev, struct wpa_common_ctx *ctx,
+ const void *pmk, size_t pmk_len )
+{
+ struct io_buffer *iob;
+ struct ieee80211_frame *hdr;
+ struct ieee80211_beacon *beacon;
+ u8 *ap_rsn_ie = NULL, *ap_rsn_ie_end;
+
+ if ( ! dev->rsn_ie || ! dev->associating )
+ return -EINVAL;
+
+ ctx->dev = dev;
+ memcpy ( ctx->pmk, pmk, ctx->pmk_len = pmk_len );
+ ctx->state = WPA_READY;
+ ctx->replay = ~0ULL;
+
+ iob = dev->associating->beacon;
+ hdr = iob->data;
+ beacon = ( struct ieee80211_beacon * ) hdr->data;
+ ap_rsn_ie = sec80211_find_rsn ( beacon->info_element, iob->tail,
+ &ctx->ap_rsn_is_rsn, &ap_rsn_ie_end );
+ if ( ap_rsn_ie ) {
+ ctx->ap_rsn_ie = malloc ( ap_rsn_ie_end - ap_rsn_ie );
+ if ( ! ctx->ap_rsn_ie )
+ return -ENOMEM;
+ memcpy ( ctx->ap_rsn_ie, ap_rsn_ie, ap_rsn_ie_end - ap_rsn_ie );
+ ctx->ap_rsn_ie_len = ap_rsn_ie_end - ap_rsn_ie;
+ } else {
+ return -ENOENT;
+ }
+
+ ctx->crypt = dev->associating->crypto;
+ ctx->gcrypt = NET80211_CRYPT_UNKNOWN;
+
+ list_add_tail ( &ctx->list, &wpa_contexts );
+ return 0;
+}
+
+
+/**
+ * Disable handling of received WPA handshake frames
+ *
+ * @v dev 802.11 device
+ */
+void wpa_stop ( struct net80211_device *dev )
+{
+ struct wpa_common_ctx *ctx, *tmp;
+
+ list_for_each_entry_safe ( ctx, tmp, &wpa_contexts, list ) {
+ if ( ctx->dev == dev ) {
+ free ( ctx->ap_rsn_ie );
+ ctx->ap_rsn_ie = NULL;
+ list_del ( &ctx->list );
+ }
+ }
+}
+
+
+/**
+ * Derive pairwise transient key
+ *
+ * @v ctx WPA common context
+ */
+static void wpa_derive_ptk ( struct wpa_common_ctx *ctx )
+{
+ struct {
+ u8 mac1[ETH_ALEN];
+ u8 mac2[ETH_ALEN];
+ u8 nonce1[WPA_NONCE_LEN];
+ u8 nonce2[WPA_NONCE_LEN];
+ } __attribute__ (( packed )) ptk_data;
+
+ /* The addresses and nonces are stored in numerical order (!) */
+
+ if ( memcmp ( ctx->dev->netdev->ll_addr, ctx->dev->bssid,
+ ETH_ALEN ) < 0 ) {
+ memcpy ( ptk_data.mac1, ctx->dev->netdev->ll_addr, ETH_ALEN );
+ memcpy ( ptk_data.mac2, ctx->dev->bssid, ETH_ALEN );
+ } else {
+ memcpy ( ptk_data.mac1, ctx->dev->bssid, ETH_ALEN );
+ memcpy ( ptk_data.mac2, ctx->dev->netdev->ll_addr, ETH_ALEN );
+ }
+
+ if ( memcmp ( ctx->Anonce, ctx->Snonce, WPA_NONCE_LEN ) < 0 ) {
+ memcpy ( ptk_data.nonce1, ctx->Anonce, WPA_NONCE_LEN );
+ memcpy ( ptk_data.nonce2, ctx->Snonce, WPA_NONCE_LEN );
+ } else {
+ memcpy ( ptk_data.nonce1, ctx->Snonce, WPA_NONCE_LEN );
+ memcpy ( ptk_data.nonce2, ctx->Anonce, WPA_NONCE_LEN );
+ }
+
+ DBGC2 ( ctx, "WPA %p A1 %s, A2 %s\n", ctx, eth_ntoa ( ptk_data.mac1 ),
+ eth_ntoa ( ptk_data.mac2 ) );
+ DBGC2 ( ctx, "WPA %p Nonce1, Nonce2:\n", ctx );
+ DBGC2_HD ( ctx, ptk_data.nonce1, WPA_NONCE_LEN );
+ DBGC2_HD ( ctx, ptk_data.nonce2, WPA_NONCE_LEN );
+
+ prf_sha1 ( ctx->pmk, ctx->pmk_len,
+ "Pairwise key expansion",
+ &ptk_data, sizeof ( ptk_data ),
+ &ctx->ptk, sizeof ( ctx->ptk ) );
+
+ DBGC2 ( ctx, "WPA %p PTK:\n", ctx );
+ DBGC2_HD ( ctx, &ctx->ptk, sizeof ( ctx->ptk ) );
+}
+
+
+/**
+ * Install pairwise transient key
+ *
+ * @v ctx WPA common context
+ * @v len Key length (16 for CCMP, 32 for TKIP)
+ * @ret rc Return status code
+ */
+static inline int wpa_install_ptk ( struct wpa_common_ctx *ctx, int len )
+{
+ DBGC ( ctx, "WPA %p: installing %d-byte pairwise transient key\n",
+ ctx, len );
+ DBGC2_HD ( ctx, &ctx->ptk.tk, len );
+
+ return sec80211_install ( &ctx->dev->crypto, ctx->crypt,
+ &ctx->ptk.tk, len, NULL );
+}
+
+/**
+ * Install group transient key
+ *
+ * @v ctx WPA common context
+ * @v len Key length (16 for CCMP, 32 for TKIP)
+ * @v rsc Receive sequence counter field in EAPOL-Key packet
+ * @ret rc Return status code
+ */
+static inline int wpa_install_gtk ( struct wpa_common_ctx *ctx, int len,
+ const void *rsc )
+{
+ DBGC ( ctx, "WPA %p: installing %d-byte group transient key\n",
+ ctx, len );
+ DBGC2_HD ( ctx, &ctx->gtk.tk, len );
+
+ return sec80211_install ( &ctx->dev->gcrypto, ctx->gcrypt,
+ &ctx->gtk.tk, len, rsc );
+}
+
+/**
+ * Search for group transient key, and install it if found
+ *
+ * @v ctx WPA common context
+ * @v ie Pointer to first IE in key data field
+ * @v ie_end Pointer to first byte not in key data field
+ * @v rsc Receive sequence counter field in EAPOL-Key packet
+ * @ret rc Return status code
+ */
+static int wpa_maybe_install_gtk ( struct wpa_common_ctx *ctx,
+ union ieee80211_ie *ie, void *ie_end,
+ const void *rsc )
+{
+ struct wpa_kde *kde;
+
+ if ( ! ieee80211_ie_bound ( ie, ie_end ) )
+ return -ENOENT;
+
+ while ( ie ) {
+ if ( ie->id == IEEE80211_IE_VENDOR &&
+ ie->vendor.oui == WPA_KDE_GTK )
+ break;
+
+ ie = ieee80211_next_ie ( ie, ie_end );
+ }
+
+ if ( ! ie )
+ return -ENOENT;
+
+ if ( ie->len - 6u > sizeof ( ctx->gtk.tk ) ) {
+ DBGC ( ctx, "WPA %p: GTK KDE is too long (%d bytes, max %zd)\n",
+ ctx, ie->len - 4, sizeof ( ctx->gtk.tk ) );
+ return -EINVAL;
+ }
+
+ /* XXX We ignore key ID for now. */
+ kde = ( struct wpa_kde * ) ie;
+ memcpy ( &ctx->gtk.tk, &kde->gtk_encap.gtk, kde->len - 6 );
+
+ return wpa_install_gtk ( ctx, kde->len - 6, rsc );
+}
+
+
+/**
+ * Allocate I/O buffer for construction of outgoing EAPOL-Key frame
+ *
+ * @v kdlen Maximum number of bytes in the Key Data field
+ * @ret iob Newly allocated I/O buffer
+ *
+ * The returned buffer will have space reserved for the link-layer and
+ * EAPOL headers, and will have @c iob->tail pointing to the start of
+ * the Key Data field. Thus, it is necessary to use iob_put() in
+ * filling the Key Data.
+ */
+static struct io_buffer * wpa_alloc_frame ( int kdlen )
+{
+ struct io_buffer *ret = alloc_iob ( sizeof ( struct eapol_key_pkt ) +
+ kdlen + EAPOL_HDR_LEN +
+ MAX_LL_HEADER_LEN );
+ if ( ! ret )
+ return NULL;
+
+ iob_reserve ( ret, MAX_LL_HEADER_LEN + EAPOL_HDR_LEN );
+ memset ( iob_put ( ret, sizeof ( struct eapol_key_pkt ) ), 0,
+ sizeof ( struct eapol_key_pkt ) );
+
+ return ret;
+}
+
+
+/**
+ * Send EAPOL-Key packet
+ *
+ * @v iob I/O buffer, with sufficient headroom for headers
+ * @v dev 802.11 device
+ * @v kie Key integrity and encryption handler
+ * @v is_rsn If TRUE, handshake uses new RSN format
+ * @ret rc Return status code
+ *
+ * If a KIE is specified, the MIC will be filled in before transmission.
+ */
+static int wpa_send_eapol ( struct io_buffer *iob, struct wpa_common_ctx *ctx,
+ struct wpa_kie *kie )
+{
+ struct eapol_key_pkt *pkt = iob->data;
+ struct eapol_frame *eapol = iob_push ( iob, EAPOL_HDR_LEN );
+
+ pkt->info = htons ( pkt->info );
+ pkt->keysize = htons ( pkt->keysize );
+ pkt->datalen = htons ( pkt->datalen );
+ pkt->replay = cpu_to_be64 ( pkt->replay );
+ eapol->version = EAPOL_THIS_VERSION;
+ eapol->type = EAPOL_TYPE_KEY;
+ eapol->length = htons ( iob->tail - iob->data - sizeof ( *eapol ) );
+
+ memset ( pkt->mic, 0, sizeof ( pkt->mic ) );
+ if ( kie )
+ kie->mic ( &ctx->ptk.kck, eapol, EAPOL_HDR_LEN +
+ sizeof ( *pkt ) + ntohs ( pkt->datalen ),
+ pkt->mic );
+
+ return net_tx ( iob, ctx->dev->netdev, &eapol_protocol,
+ ctx->dev->bssid, ctx->dev->netdev->ll_addr );
+}
+
+
+/**
+ * Send second frame in 4-Way Handshake
+ *
+ * @v ctx WPA common context
+ * @v pkt First frame, to which this is a reply
+ * @v is_rsn If TRUE, handshake uses new RSN format
+ * @v kie Key integrity and encryption handler
+ * @ret rc Return status code
+ */
+static int wpa_send_2_of_4 ( struct wpa_common_ctx *ctx,
+ struct eapol_key_pkt *pkt, int is_rsn,
+ struct wpa_kie *kie )
+{
+ struct io_buffer *iob = wpa_alloc_frame ( ctx->dev->rsn_ie->len + 2 );
+ struct eapol_key_pkt *npkt;
+
+ if ( ! iob )
+ return -ENOMEM;
+
+ npkt = iob->data;
+ memcpy ( npkt, pkt, sizeof ( *pkt ) );
+ npkt->info &= ~EAPOL_KEY_INFO_KEY_ACK;
+ npkt->info |= EAPOL_KEY_INFO_KEY_MIC;
+ if ( is_rsn )
+ npkt->keysize = 0;
+ memcpy ( npkt->nonce, ctx->Snonce, sizeof ( npkt->nonce ) );
+ npkt->datalen = ctx->dev->rsn_ie->len + 2;
+ memcpy ( iob_put ( iob, npkt->datalen ), ctx->dev->rsn_ie,
+ npkt->datalen );
+
+ DBGC ( ctx, "WPA %p: sending 2/4\n", ctx );
+
+ return wpa_send_eapol ( iob, ctx, kie );
+}
+
+
+/**
+ * Handle receipt of first frame in 4-Way Handshake
+ *
+ * @v ctx WPA common context
+ * @v pkt EAPOL-Key packet
+ * @v is_rsn If TRUE, frame uses new RSN format
+ * @v kie Key integrity and encryption handler
+ * @ret rc Return status code
+ */
+static int wpa_handle_1_of_4 ( struct wpa_common_ctx *ctx,
+ struct eapol_key_pkt *pkt, int is_rsn,
+ struct wpa_kie *kie )
+{
+ if ( ctx->state == WPA_WAITING )
+ return -EINVAL;
+
+ ctx->state = WPA_WORKING;
+ memcpy ( ctx->Anonce, pkt->nonce, sizeof ( ctx->Anonce ) );
+ if ( ! ctx->have_Snonce ) {
+ rbg_generate ( NULL, 0, 0, ctx->Snonce,
+ sizeof ( ctx->Snonce ) );
+ ctx->have_Snonce = 1;
+ }
+
+ DBGC ( ctx, "WPA %p: received 1/4, looks OK\n", ctx );
+
+ wpa_derive_ptk ( ctx );
+
+ return wpa_send_2_of_4 ( ctx, pkt, is_rsn, kie );
+}
+
+
+/**
+ * Send fourth frame in 4-Way Handshake, or second in Group Key Handshake
+ *
+ * @v ctx WPA common context
+ * @v pkt EAPOL-Key packet for frame to which we're replying
+ * @v is_rsn If TRUE, frame uses new RSN format
+ * @v kie Key integrity and encryption handler
+ * @ret rc Return status code
+ */
+static int wpa_send_final ( struct wpa_common_ctx *ctx,
+ struct eapol_key_pkt *pkt, int is_rsn,
+ struct wpa_kie *kie )
+{
+ struct io_buffer *iob = wpa_alloc_frame ( 0 );
+ struct eapol_key_pkt *npkt;
+
+ if ( ! iob )
+ return -ENOMEM;
+
+ npkt = iob->data;
+ memcpy ( npkt, pkt, sizeof ( *pkt ) );
+ npkt->info &= ~( EAPOL_KEY_INFO_KEY_ACK | EAPOL_KEY_INFO_INSTALL |
+ EAPOL_KEY_INFO_KEY_ENC );
+ if ( is_rsn )
+ npkt->keysize = 0;
+ memset ( npkt->nonce, 0, sizeof ( npkt->nonce ) );
+ memset ( npkt->iv, 0, sizeof ( npkt->iv ) );
+ npkt->datalen = 0;
+
+ if ( npkt->info & EAPOL_KEY_INFO_TYPE )
+ DBGC ( ctx, "WPA %p: sending 4/4\n", ctx );
+ else
+ DBGC ( ctx, "WPA %p: sending 2/2\n", ctx );
+
+ return wpa_send_eapol ( iob, ctx, kie );
+
+}
+
+
+/**
+ * Handle receipt of third frame in 4-Way Handshake
+ *
+ * @v ctx WPA common context
+ * @v pkt EAPOL-Key packet
+ * @v is_rsn If TRUE, frame uses new RSN format
+ * @v kie Key integrity and encryption handler
+ * @ret rc Return status code
+ */
+static int wpa_handle_3_of_4 ( struct wpa_common_ctx *ctx,
+ struct eapol_key_pkt *pkt, int is_rsn,
+ struct wpa_kie *kie )
+{
+ int rc;
+ u8 *this_rsn, *this_rsn_end;
+ u8 *new_rsn, *new_rsn_end;
+ int this_is_rsn, new_is_rsn;
+
+ if ( ctx->state == WPA_WAITING )
+ return -EINVAL;
+
+ ctx->state = WPA_WORKING;
+
+ /* Check nonce */
+ if ( memcmp ( ctx->Anonce, pkt->nonce, WPA_NONCE_LEN ) != 0 ) {
+ DBGC ( ctx, "WPA %p ALERT: nonce mismatch in 3/4\n", ctx );
+ return wpa_fail ( ctx, -EACCES );
+ }
+
+ /* Check RSN IE */
+ this_rsn = sec80211_find_rsn ( ( union ieee80211_ie * ) pkt->data,
+ pkt->data + pkt->datalen,
+ &this_is_rsn, &this_rsn_end );
+ if ( this_rsn )
+ new_rsn = sec80211_find_rsn ( ( union ieee80211_ie * )
+ this_rsn_end,
+ pkt->data + pkt->datalen,
+ &new_is_rsn, &new_rsn_end );
+ else
+ new_rsn = NULL;
+
+ if ( ! ctx->ap_rsn_ie || ! this_rsn ||
+ ctx->ap_rsn_ie_len != ( this_rsn_end - this_rsn ) ||
+ ctx->ap_rsn_is_rsn != this_is_rsn ||
+ memcmp ( ctx->ap_rsn_ie, this_rsn, ctx->ap_rsn_ie_len ) != 0 ) {
+ DBGC ( ctx, "WPA %p ALERT: RSN mismatch in 3/4\n", ctx );
+ DBGC2 ( ctx, "WPA %p RSNs (in 3/4, in beacon):\n", ctx );
+ DBGC2_HD ( ctx, this_rsn, this_rsn_end - this_rsn );
+ DBGC2_HD ( ctx, ctx->ap_rsn_ie, ctx->ap_rsn_ie_len );
+ return wpa_fail ( ctx, -EACCES );
+ }
+
+ /* Don't switch if they just supplied both styles of IE
+ simultaneously; we need two RSN IEs or two WPA IEs to
+ switch ciphers. They'll be immediately consecutive because
+ of ordering guarantees. */
+ if ( new_rsn && this_is_rsn == new_is_rsn ) {
+ struct net80211_wlan *assoc = ctx->dev->associating;
+ DBGC ( ctx, "WPA %p: accommodating bait-and-switch tactics\n",
+ ctx );
+ DBGC2 ( ctx, "WPA %p RSNs (in 3/4+beacon, new in 3/4):\n",
+ ctx );
+ DBGC2_HD ( ctx, this_rsn, this_rsn_end - this_rsn );
+ DBGC2_HD ( ctx, new_rsn, new_rsn_end - new_rsn );
+
+ if ( ( rc = sec80211_detect_ie ( new_is_rsn, new_rsn,
+ new_rsn_end,
+ &assoc->handshaking,
+ &assoc->crypto ) ) != 0 )
+ DBGC ( ctx, "WPA %p: bait-and-switch invalid, staying "
+ "with original request\n", ctx );
+ } else {
+ new_rsn = this_rsn;
+ new_is_rsn = this_is_rsn;
+ new_rsn_end = this_rsn_end;
+ }
+
+ /* Grab group cryptosystem ID */
+ ctx->gcrypt = sec80211_rsn_get_net80211_crypt ( *( u32 * )
+ ( new_rsn + 2 ) );
+
+ /* Check for a GTK, if info field is encrypted */
+ if ( pkt->info & EAPOL_KEY_INFO_KEY_ENC ) {
+ rc = wpa_maybe_install_gtk ( ctx,
+ ( union ieee80211_ie * ) pkt->data,
+ pkt->data + pkt->datalen,
+ pkt->rsc );
+ if ( rc < 0 ) {
+ DBGC ( ctx, "WPA %p did not install GTK in 3/4: %s\n",
+ ctx, strerror ( rc ) );
+ if ( rc != -ENOENT )
+ return wpa_fail ( ctx, rc );
+ }
+ }
+
+ DBGC ( ctx, "WPA %p: received 3/4, looks OK\n", ctx );
+
+ /* Send final message */
+ rc = wpa_send_final ( ctx, pkt, is_rsn, kie );
+ if ( rc < 0 )
+ return wpa_fail ( ctx, rc );
+
+ /* Install PTK */
+ rc = wpa_install_ptk ( ctx, pkt->keysize );
+ if ( rc < 0 ) {
+ DBGC ( ctx, "WPA %p failed to install PTK: %s\n", ctx,
+ strerror ( rc ) );
+ return wpa_fail ( ctx, rc );
+ }
+
+ /* Mark us as needing a new Snonce if we rekey */
+ ctx->have_Snonce = 0;
+
+ /* Done! */
+ ctx->state = WPA_SUCCESS;
+ return 0;
+}
+
+
+/**
+ * Handle receipt of first frame in Group Key Handshake
+ *
+ * @v ctx WPA common context
+ * @v pkt EAPOL-Key packet
+ * @v is_rsn If TRUE, frame uses new RSN format
+ * @v kie Key integrity and encryption handler
+ * @ret rc Return status code
+ */
+static int wpa_handle_1_of_2 ( struct wpa_common_ctx *ctx,
+ struct eapol_key_pkt *pkt, int is_rsn,
+ struct wpa_kie *kie )
+{
+ int rc;
+
+ /*
+ * WPA and RSN do this completely differently.
+ *
+ * The idea of encoding the GTK (or PMKID, or various other
+ * things) into a KDE that looks like an information element
+ * is an RSN innovation; old WPA code never encapsulates
+ * things like that. If it looks like an info element, it
+ * really is (for the WPA IE check in frames 2/4 and 3/4). The
+ * "key data encrypted" bit in the info field is also specific
+ * to RSN.
+ *
+ * So from an old WPA host, 3/4 does not contain an
+ * encapsulated GTK. The first frame of the GK handshake
+ * contains it, encrypted, but without a KDE wrapper, and with
+ * the key ID field (which iPXE doesn't use) shoved away in
+ * the reserved bits in the info field, and the TxRx bit
+ * stealing the Install bit's spot.
+ */
+
+ if ( is_rsn && ( pkt->info & EAPOL_KEY_INFO_KEY_ENC ) ) {
+ rc = wpa_maybe_install_gtk ( ctx,
+ ( union ieee80211_ie * ) pkt->data,
+ pkt->data + pkt->datalen,
+ pkt->rsc );
+ if ( rc < 0 ) {
+ DBGC ( ctx, "WPA %p: failed to install GTK in 1/2: "
+ "%s\n", ctx, strerror ( rc ) );
+ return wpa_fail ( ctx, rc );
+ }
+ } else {
+ rc = kie->decrypt ( &ctx->ptk.kek, pkt->iv, pkt->data,
+ &pkt->datalen );
+ if ( rc < 0 ) {
+ DBGC ( ctx, "WPA %p: failed to decrypt GTK: %s\n",
+ ctx, strerror ( rc ) );
+ return rc; /* non-fatal */
+ }
+ if ( pkt->datalen > sizeof ( ctx->gtk.tk ) ) {
+ DBGC ( ctx, "WPA %p: too much GTK data (%d > %zd)\n",
+ ctx, pkt->datalen, sizeof ( ctx->gtk.tk ) );
+ return wpa_fail ( ctx, -EINVAL );
+ }
+
+ memcpy ( &ctx->gtk.tk, pkt->data, pkt->datalen );
+ wpa_install_gtk ( ctx, pkt->datalen, pkt->rsc );
+ }
+
+ DBGC ( ctx, "WPA %p: received 1/2, looks OK\n", ctx );
+
+ return wpa_send_final ( ctx, pkt, is_rsn, kie );
+}
+
+
+/**
+ * Handle receipt of EAPOL-Key frame for WPA
+ *
+ * @v iob I/O buffer
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Source link-layer address
+ */
+static int eapol_key_rx ( struct io_buffer *iob, struct net_device *netdev,
+ const void *ll_dest __unused,
+ const void *ll_source )
+{
+ struct net80211_device *dev = net80211_get ( netdev );
+ struct eapol_key_pkt *pkt = iob->data;
+ int is_rsn, found_ctx;
+ struct wpa_common_ctx *ctx;
+ int rc = 0;
+ struct wpa_kie *kie;
+ u8 their_mic[16], our_mic[16];
+
+ if ( pkt->type != EAPOL_KEY_TYPE_WPA &&
+ pkt->type != EAPOL_KEY_TYPE_RSN ) {
+ DBG ( "EAPOL-Key: packet not of 802.11 type\n" );
+ rc = -EINVAL;
+ goto drop;
+ }
+
+ is_rsn = ( pkt->type == EAPOL_KEY_TYPE_RSN );
+
+ if ( ! dev ) {
+ DBG ( "EAPOL-Key: packet not from 802.11\n" );
+ rc = -EINVAL;
+ goto drop;
+ }
+
+ if ( memcmp ( dev->bssid, ll_source, ETH_ALEN ) != 0 ) {
+ DBG ( "EAPOL-Key: packet not from associated AP\n" );
+ rc = -EINVAL;
+ goto drop;
+ }
+
+ if ( ! ( ntohs ( pkt->info ) & EAPOL_KEY_INFO_KEY_ACK ) ) {
+ DBG ( "EAPOL-Key: packet sent in wrong direction\n" );
+ rc = -EINVAL;
+ goto drop;
+ }
+
+ found_ctx = 0;
+ list_for_each_entry ( ctx, &wpa_contexts, list ) {
+ if ( ctx->dev == dev ) {
+ found_ctx = 1;
+ break;
+ }
+ }
+
+ if ( ! found_ctx ) {
+ DBG ( "EAPOL-Key: no WPA context to handle packet for %p\n",
+ dev );
+ rc = -ENOENT;
+ goto drop;
+ }
+
+ if ( ( void * ) ( pkt + 1 ) + ntohs ( pkt->datalen ) > iob->tail ) {
+ DBGC ( ctx, "WPA %p: packet truncated (has %zd extra bytes, "
+ "states %d)\n", ctx, iob->tail - ( void * ) ( pkt + 1 ),
+ ntohs ( pkt->datalen ) );
+ rc = -EINVAL;
+ goto drop;
+ }
+
+ /* Get a handle on key integrity/encryption handler */
+ kie = wpa_find_kie ( ntohs ( pkt->info ) & EAPOL_KEY_INFO_VERSION );
+ if ( ! kie ) {
+ DBGC ( ctx, "WPA %p: no support for packet version %d\n", ctx,
+ ntohs ( pkt->info ) & EAPOL_KEY_INFO_VERSION );
+ rc = wpa_fail ( ctx, -ENOTSUP );
+ goto drop;
+ }
+
+ /* Check MIC */
+ if ( ntohs ( pkt->info ) & EAPOL_KEY_INFO_KEY_MIC ) {
+ memcpy ( their_mic, pkt->mic, sizeof ( pkt->mic ) );
+ memset ( pkt->mic, 0, sizeof ( pkt->mic ) );
+ kie->mic ( &ctx->ptk.kck, ( void * ) pkt - EAPOL_HDR_LEN,
+ EAPOL_HDR_LEN + sizeof ( *pkt ) +
+ ntohs ( pkt->datalen ), our_mic );
+ DBGC2 ( ctx, "WPA %p MIC comparison (theirs, ours):\n", ctx );
+ DBGC2_HD ( ctx, their_mic, 16 );
+ DBGC2_HD ( ctx, our_mic, 16 );
+ if ( memcmp ( their_mic, our_mic, sizeof ( pkt->mic ) ) != 0 ) {
+ DBGC ( ctx, "WPA %p: EAPOL MIC failure\n", ctx );
+ goto drop;
+ }
+ }
+
+ /* Fix byte order to local */
+ pkt->info = ntohs ( pkt->info );
+ pkt->keysize = ntohs ( pkt->keysize );
+ pkt->datalen = ntohs ( pkt->datalen );
+ pkt->replay = be64_to_cpu ( pkt->replay );
+
+ /* Check replay counter */
+ if ( ctx->replay != ~0ULL && ctx->replay >= pkt->replay ) {
+ DBGC ( ctx, "WPA %p ALERT: Replay detected! "
+ "(%08x:%08x >= %08x:%08x)\n", ctx,
+ ( u32 ) ( ctx->replay >> 32 ), ( u32 ) ctx->replay,
+ ( u32 ) ( pkt->replay >> 32 ), ( u32 ) pkt->replay );
+ rc = 0; /* ignore without error */
+ goto drop;
+ }
+ ctx->replay = pkt->replay;
+
+ /* Decrypt key data */
+ if ( pkt->info & EAPOL_KEY_INFO_KEY_ENC ) {
+ rc = kie->decrypt ( &ctx->ptk.kek, pkt->iv, pkt->data,
+ &pkt->datalen );
+ if ( rc < 0 ) {
+ DBGC ( ctx, "WPA %p: failed to decrypt packet: %s\n",
+ ctx, strerror ( rc ) );
+ goto drop;
+ }
+ }
+
+ /* Hand it off to appropriate handler */
+ switch ( pkt->info & ( EAPOL_KEY_INFO_TYPE |
+ EAPOL_KEY_INFO_KEY_MIC ) ) {
+ case EAPOL_KEY_TYPE_PTK:
+ rc = wpa_handle_1_of_4 ( ctx, pkt, is_rsn, kie );
+ break;
+
+ case EAPOL_KEY_TYPE_PTK | EAPOL_KEY_INFO_KEY_MIC:
+ rc = wpa_handle_3_of_4 ( ctx, pkt, is_rsn, kie );
+ break;
+
+ case EAPOL_KEY_TYPE_GTK | EAPOL_KEY_INFO_KEY_MIC:
+ rc = wpa_handle_1_of_2 ( ctx, pkt, is_rsn, kie );
+ break;
+
+ default:
+ DBGC ( ctx, "WPA %p: Invalid combination of key flags %04x\n",
+ ctx, pkt->info );
+ rc = -EINVAL;
+ break;
+ }
+
+ drop:
+ free_iob ( iob );
+ return rc;
+}
+
+struct eapol_handler eapol_key_handler __eapol_handler = {
+ .type = EAPOL_TYPE_KEY,
+ .rx = eapol_key_rx,
+};
+
+/* WPA always needs EAPOL in order to be useful */
+REQUIRE_OBJECT ( eapol );
diff --git a/src/VBox/Devices/PC/ipxe/src/net/80211/wpa_ccmp.c b/src/VBox/Devices/PC/ipxe/src/net/80211/wpa_ccmp.c
new file mode 100644
index 00000000..38fd199f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/80211/wpa_ccmp.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <ipxe/net80211.h>
+#include <ipxe/crypto.h>
+#include <ipxe/hmac.h>
+#include <ipxe/sha1.h>
+#include <ipxe/aes.h>
+#include <ipxe/wpa.h>
+#include <byteswap.h>
+#include <errno.h>
+
+/** @file
+ *
+ * Backend for WPA using the CCMP encryption method
+ */
+
+/** Context for CCMP encryption and decryption */
+struct ccmp_ctx
+{
+ /** AES context - only ever used for encryption */
+ u8 aes_ctx[AES_CTX_SIZE];
+
+ /** Most recently sent packet number */
+ u64 tx_seq;
+
+ /** Most recently received packet number */
+ u64 rx_seq;
+};
+
+/** Header structure at the beginning of CCMP frame data */
+struct ccmp_head
+{
+ u8 pn_lo[2]; /**< Bytes 0 and 1 of packet number */
+ u8 _rsvd; /**< Reserved byte */
+ u8 kid; /**< Key ID and ExtIV byte */
+ u8 pn_hi[4]; /**< Bytes 2-5 (2 first) of packet number */
+} __attribute__ (( packed ));
+
+
+/** CCMP header overhead */
+#define CCMP_HEAD_LEN 8
+
+/** CCMP MIC trailer overhead */
+#define CCMP_MIC_LEN 8
+
+/** CCMP nonce length */
+#define CCMP_NONCE_LEN 13
+
+/** CCMP nonce structure */
+struct ccmp_nonce
+{
+ u8 prio; /**< Packet priority, 0 for non-QoS */
+ u8 a2[ETH_ALEN]; /**< Address 2 from packet header (sender) */
+ u8 pn[6]; /**< Packet number */
+} __attribute__ (( packed ));
+
+/** CCMP additional authentication data length (for non-QoS, non-WDS frames) */
+#define CCMP_AAD_LEN 22
+
+/** CCMP additional authentication data structure */
+struct ccmp_aad
+{
+ u16 fc; /**< Frame Control field */
+ u8 a1[6]; /**< Address 1 */
+ u8 a2[6]; /**< Address 2 */
+ u8 a3[6]; /**< Address 3 */
+ u16 seq; /**< Sequence Control field */
+ /* Address 4 and QoS Control are included if present */
+} __attribute__ (( packed ));
+
+/** Mask for Frame Control field in AAD */
+#define CCMP_AAD_FC_MASK 0xC38F
+
+/** Mask for Sequence Control field in AAD */
+#define CCMP_AAD_SEQ_MASK 0x000F
+
+
+/**
+ * Convert 6-byte LSB packet number to 64-bit integer
+ *
+ * @v pn Pointer to 6-byte packet number
+ * @ret v 64-bit integer value of @a pn
+ */
+static u64 pn_to_u64 ( const u8 *pn )
+{
+ int i;
+ u64 ret = 0;
+
+ for ( i = 5; i >= 0; i-- ) {
+ ret <<= 8;
+ ret |= pn[i];
+ }
+
+ return ret;
+}
+
+/**
+ * Convert 64-bit integer to 6-byte packet number
+ *
+ * @v v 64-bit integer
+ * @v msb If TRUE, reverse the output PN to be in MSB order
+ * @ret pn 6-byte packet number
+ *
+ * The PN is stored in LSB order in the packet header and in MSB order
+ * in the nonce. WHYYYYY?
+ */
+static void u64_to_pn ( u64 v, u8 *pn, int msb )
+{
+ int i;
+ u8 *pnp = pn + ( msb ? 5 : 0 );
+ int delta = ( msb ? -1 : +1 );
+
+ for ( i = 0; i < 6; i++ ) {
+ *pnp = v & 0xFF;
+ pnp += delta;
+ v >>= 8;
+ }
+}
+
+/** Value for @a msb argument of u64_to_pn() for MSB output */
+#define PN_MSB 1
+
+/** Value for @a msb argument of u64_to_pn() for LSB output */
+#define PN_LSB 0
+
+
+
+/**
+ * Initialise CCMP state and install key
+ *
+ * @v crypto CCMP cryptosystem structure
+ * @v key Pointer to 16-byte temporal key to install
+ * @v keylen Length of key (16 bytes)
+ * @v rsc Initial receive sequence counter
+ */
+static int ccmp_init ( struct net80211_crypto *crypto, const void *key,
+ int keylen, const void *rsc )
+{
+ struct ccmp_ctx *ctx = crypto->priv;
+
+ if ( keylen != 16 )
+ return -EINVAL;
+
+ if ( rsc )
+ ctx->rx_seq = pn_to_u64 ( rsc );
+
+ cipher_setkey ( &aes_algorithm, ctx->aes_ctx, key, keylen );
+
+ return 0;
+}
+
+
+/**
+ * Encrypt or decrypt data stream using AES in Counter mode
+ *
+ * @v ctx CCMP cryptosystem context
+ * @v nonce Nonce value, 13 bytes
+ * @v srcv Data to encrypt or decrypt
+ * @v len Number of bytes pointed to by @a src
+ * @v msrcv MIC value to encrypt or decrypt (may be NULL)
+ * @ret destv Encrypted or decrypted data
+ * @ret mdestv Encrypted or decrypted MIC value
+ *
+ * This assumes CCMP parameters of L=2 and M=8. The algorithm is
+ * defined in RFC 3610.
+ */
+static void ccmp_ctr_xor ( struct ccmp_ctx *ctx, const void *nonce,
+ const void *srcv, void *destv, int len,
+ const void *msrcv, void *mdestv )
+{
+ u8 A[16], S[16];
+ u16 ctr;
+ int i;
+ const u8 *src = srcv, *msrc = msrcv;
+ u8 *dest = destv, *mdest = mdestv;
+
+ A[0] = 0x01; /* flags, L' = L - 1 = 1, other bits rsvd */
+ memcpy ( A + 1, nonce, CCMP_NONCE_LEN );
+
+ if ( msrcv ) {
+ A[14] = A[15] = 0;
+
+ cipher_encrypt ( &aes_algorithm, ctx->aes_ctx, A, S, 16 );
+
+ for ( i = 0; i < 8; i++ ) {
+ *mdest++ = *msrc++ ^ S[i];
+ }
+ }
+
+ for ( ctr = 1 ;; ctr++ ) {
+ A[14] = ctr >> 8;
+ A[15] = ctr & 0xFF;
+
+ cipher_encrypt ( &aes_algorithm, ctx->aes_ctx, A, S, 16 );
+
+ for ( i = 0; i < len && i < 16; i++ )
+ *dest++ = *src++ ^ S[i];
+
+ if ( len <= 16 )
+ break; /* we're done */
+
+ len -= 16;
+ }
+}
+
+
+/**
+ * Advance one block in CBC-MAC calculation
+ *
+ * @v aes_ctx AES encryption context with key set
+ * @v B Cleartext block to incorporate (16 bytes)
+ * @v X Previous ciphertext block (16 bytes)
+ * @ret B Clobbered
+ * @ret X New ciphertext block (16 bytes)
+ *
+ * This function does X := E[key] ( X ^ B ).
+ */
+static void ccmp_feed_cbc_mac ( void *aes_ctx, u8 *B, u8 *X )
+{
+ int i;
+ for ( i = 0; i < 16; i++ )
+ B[i] ^= X[i];
+ cipher_encrypt ( &aes_algorithm, aes_ctx, B, X, 16 );
+}
+
+
+/**
+ * Calculate MIC on plaintext data using CBC-MAC
+ *
+ * @v ctx CCMP cryptosystem context
+ * @v nonce Nonce value, 13 bytes
+ * @v data Data to calculate MIC over
+ * @v datalen Length of @a data
+ * @v aad Additional authentication data, for MIC but not encryption
+ * @ret mic MIC value (unencrypted), 8 bytes
+ *
+ * @a aadlen is assumed to be 22 bytes long, as it always is for
+ * 802.11 use when transmitting non-QoS, not-between-APs frames (the
+ * only type we deal with).
+ */
+static void ccmp_cbc_mac ( struct ccmp_ctx *ctx, const void *nonce,
+ const void *data, u16 datalen,
+ const void *aad, void *mic )
+{
+ u8 X[16], B[16];
+
+ /* Zeroth block: flags, nonce, length */
+
+ /* Rsv AAD - M'- - L'-
+ * 0 1 0 1 1 0 0 1 for an 8-byte MAC and 2-byte message length
+ */
+ B[0] = 0x59;
+ memcpy ( B + 1, nonce, CCMP_NONCE_LEN );
+ B[14] = datalen >> 8;
+ B[15] = datalen & 0xFF;
+
+ cipher_encrypt ( &aes_algorithm, ctx->aes_ctx, B, X, 16 );
+
+ /* First block: AAD length field and 14 bytes of AAD */
+ B[0] = 0;
+ B[1] = CCMP_AAD_LEN;
+ memcpy ( B + 2, aad, 14 );
+
+ ccmp_feed_cbc_mac ( ctx->aes_ctx, B, X );
+
+ /* Second block: Remaining 8 bytes of AAD, 8 bytes zero pad */
+ memcpy ( B, aad + 14, 8 );
+ memset ( B + 8, 0, 8 );
+
+ ccmp_feed_cbc_mac ( ctx->aes_ctx, B, X );
+
+ /* Message blocks */
+ while ( datalen ) {
+ if ( datalen >= 16 ) {
+ memcpy ( B, data, 16 );
+ datalen -= 16;
+ } else {
+ memcpy ( B, data, datalen );
+ memset ( B + datalen, 0, 16 - datalen );
+ datalen = 0;
+ }
+
+ ccmp_feed_cbc_mac ( ctx->aes_ctx, B, X );
+
+ data += 16;
+ }
+
+ /* Get MIC from final value of X */
+ memcpy ( mic, X, 8 );
+}
+
+
+/**
+ * Encapsulate and encrypt a packet using CCMP
+ *
+ * @v crypto CCMP cryptosystem
+ * @v iob I/O buffer containing cleartext packet
+ * @ret eiob I/O buffer containing encrypted packet
+ */
+struct io_buffer * ccmp_encrypt ( struct net80211_crypto *crypto,
+ struct io_buffer *iob )
+{
+ struct ccmp_ctx *ctx = crypto->priv;
+ struct ieee80211_frame *hdr = iob->data;
+ struct io_buffer *eiob;
+ const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
+ int datalen = iob_len ( iob ) - hdrlen;
+ struct ccmp_head head;
+ struct ccmp_nonce nonce;
+ struct ccmp_aad aad;
+ u8 mic[8], tx_pn[6];
+ void *edata, *emic;
+
+ ctx->tx_seq++;
+ u64_to_pn ( ctx->tx_seq, tx_pn, PN_LSB );
+
+ /* Allocate memory */
+ eiob = alloc_iob ( iob_len ( iob ) + CCMP_HEAD_LEN + CCMP_MIC_LEN );
+ if ( ! eiob )
+ return NULL;
+
+ /* Copy frame header */
+ memcpy ( iob_put ( eiob, hdrlen ), iob->data, hdrlen );
+ hdr = eiob->data;
+ hdr->fc |= IEEE80211_FC_PROTECTED;
+
+ /* Fill in packet number and extended IV */
+ memcpy ( head.pn_lo, tx_pn, 2 );
+ memcpy ( head.pn_hi, tx_pn + 2, 4 );
+ head.kid = 0x20; /* have Extended IV, key ID 0 */
+ head._rsvd = 0;
+ memcpy ( iob_put ( eiob, sizeof ( head ) ), &head, sizeof ( head ) );
+
+ /* Form nonce */
+ nonce.prio = 0;
+ memcpy ( nonce.a2, hdr->addr2, ETH_ALEN );
+ u64_to_pn ( ctx->tx_seq, nonce.pn, PN_MSB );
+
+ /* Form additional authentication data */
+ aad.fc = hdr->fc & CCMP_AAD_FC_MASK;
+ memcpy ( aad.a1, hdr->addr1, 3 * ETH_ALEN ); /* all 3 at once */
+ aad.seq = hdr->seq & CCMP_AAD_SEQ_MASK;
+
+ /* Calculate MIC over the data */
+ ccmp_cbc_mac ( ctx, &nonce, iob->data + hdrlen, datalen, &aad, mic );
+
+ /* Copy and encrypt data and MIC */
+ edata = iob_put ( eiob, datalen );
+ emic = iob_put ( eiob, CCMP_MIC_LEN );
+ ccmp_ctr_xor ( ctx, &nonce,
+ iob->data + hdrlen, edata, datalen,
+ mic, emic );
+
+ /* Done! */
+ DBGC2 ( ctx, "WPA-CCMP %p: encrypted packet %p -> %p\n", ctx,
+ iob, eiob );
+
+ return eiob;
+}
+
+/**
+ * Decrypt a packet using CCMP
+ *
+ * @v crypto CCMP cryptosystem
+ * @v eiob I/O buffer containing encrypted packet
+ * @ret iob I/O buffer containing cleartext packet
+ */
+static struct io_buffer * ccmp_decrypt ( struct net80211_crypto *crypto,
+ struct io_buffer *eiob )
+{
+ struct ccmp_ctx *ctx = crypto->priv;
+ struct ieee80211_frame *hdr;
+ struct io_buffer *iob;
+ const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
+ int datalen = iob_len ( eiob ) - hdrlen - CCMP_HEAD_LEN - CCMP_MIC_LEN;
+ struct ccmp_head *head;
+ struct ccmp_nonce nonce;
+ struct ccmp_aad aad;
+ u8 rx_pn[6], their_mic[8], our_mic[8];
+
+ iob = alloc_iob ( hdrlen + datalen );
+ if ( ! iob )
+ return NULL;
+
+ /* Copy frame header */
+ memcpy ( iob_put ( iob, hdrlen ), eiob->data, hdrlen );
+ hdr = iob->data;
+ hdr->fc &= ~IEEE80211_FC_PROTECTED;
+
+ /* Check and update RX packet number */
+ head = eiob->data + hdrlen;
+ memcpy ( rx_pn, head->pn_lo, 2 );
+ memcpy ( rx_pn + 2, head->pn_hi, 4 );
+
+ if ( pn_to_u64 ( rx_pn ) <= ctx->rx_seq ) {
+ DBGC ( ctx, "WPA-CCMP %p: packet received out of order "
+ "(%012llx <= %012llx)\n", ctx, pn_to_u64 ( rx_pn ),
+ ctx->rx_seq );
+ free_iob ( iob );
+ return NULL;
+ }
+
+ ctx->rx_seq = pn_to_u64 ( rx_pn );
+ DBGC2 ( ctx, "WPA-CCMP %p: RX packet number %012llx\n", ctx, ctx->rx_seq );
+
+ /* Form nonce */
+ nonce.prio = 0;
+ memcpy ( nonce.a2, hdr->addr2, ETH_ALEN );
+ u64_to_pn ( ctx->rx_seq, nonce.pn, PN_MSB );
+
+ /* Form additional authentication data */
+ aad.fc = ( hdr->fc & CCMP_AAD_FC_MASK ) | IEEE80211_FC_PROTECTED;
+ memcpy ( aad.a1, hdr->addr1, 3 * ETH_ALEN ); /* all 3 at once */
+ aad.seq = hdr->seq & CCMP_AAD_SEQ_MASK;
+
+ /* Copy-decrypt data and MIC */
+ ccmp_ctr_xor ( ctx, &nonce, eiob->data + hdrlen + sizeof ( *head ),
+ iob_put ( iob, datalen ), datalen,
+ eiob->tail - CCMP_MIC_LEN, their_mic );
+
+ /* Check MIC */
+ ccmp_cbc_mac ( ctx, &nonce, iob->data + hdrlen, datalen, &aad,
+ our_mic );
+
+ if ( memcmp ( their_mic, our_mic, CCMP_MIC_LEN ) != 0 ) {
+ DBGC2 ( ctx, "WPA-CCMP %p: MIC failure\n", ctx );
+ free_iob ( iob );
+ return NULL;
+ }
+
+ DBGC2 ( ctx, "WPA-CCMP %p: decrypted packet %p -> %p\n", ctx,
+ eiob, iob );
+
+ return iob;
+}
+
+
+/** CCMP cryptosystem */
+struct net80211_crypto ccmp_crypto __net80211_crypto = {
+ .algorithm = NET80211_CRYPT_CCMP,
+ .init = ccmp_init,
+ .encrypt = ccmp_encrypt,
+ .decrypt = ccmp_decrypt,
+ .priv_len = sizeof ( struct ccmp_ctx ),
+};
+
+
+
+
+/**
+ * Calculate HMAC-SHA1 MIC for EAPOL-Key frame
+ *
+ * @v kck Key Confirmation Key, 16 bytes
+ * @v msg Message to calculate MIC over
+ * @v len Number of bytes to calculate MIC over
+ * @ret mic Calculated MIC, 16 bytes long
+ */
+static void ccmp_kie_mic ( const void *kck, const void *msg, size_t len,
+ void *mic )
+{
+ u8 sha1_ctx[SHA1_CTX_SIZE];
+ u8 kckb[16];
+ u8 hash[SHA1_SIZE];
+ size_t kck_len = 16;
+
+ memcpy ( kckb, kck, kck_len );
+
+ hmac_init ( &sha1_algorithm, sha1_ctx, kckb, &kck_len );
+ hmac_update ( &sha1_algorithm, sha1_ctx, msg, len );
+ hmac_final ( &sha1_algorithm, sha1_ctx, kckb, &kck_len, hash );
+
+ memcpy ( mic, hash, 16 );
+}
+
+/**
+ * Decrypt key data in EAPOL-Key frame
+ *
+ * @v kek Key Encryption Key, 16 bytes
+ * @v iv Initialisation vector, 16 bytes (unused)
+ * @v msg Message to decrypt
+ * @v len Length of message
+ * @ret msg Decrypted message in place of original
+ * @ret len Adjusted downward for 8 bytes of overhead
+ * @ret rc Return status code
+ *
+ * The returned message may still contain padding of 0xDD followed by
+ * zero or more 0x00 octets. It is impossible to remove the padding
+ * without parsing the IEs in the packet (another design decision that
+ * tends to make one question the 802.11i committee's intelligence...)
+ */
+static int ccmp_kie_decrypt ( const void *kek, const void *iv __unused,
+ void *msg, u16 *len )
+{
+ if ( *len % 8 != 0 )
+ return -EINVAL;
+
+ if ( aes_unwrap ( kek, msg, msg, *len / 8 - 1 ) != 0 )
+ return -EINVAL;
+
+ *len -= 8;
+
+ return 0;
+}
+
+/** CCMP-style key integrity and encryption handler */
+struct wpa_kie ccmp_kie __wpa_kie = {
+ .version = EAPOL_KEY_VERSION_WPA2,
+ .mic = ccmp_kie_mic,
+ .decrypt = ccmp_kie_decrypt,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/80211/wpa_psk.c b/src/VBox/Devices/PC/ipxe/src/net/80211/wpa_psk.c
new file mode 100644
index 00000000..c88f556e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/80211/wpa_psk.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <ipxe/net80211.h>
+#include <ipxe/sha1.h>
+#include <ipxe/wpa.h>
+#include <errno.h>
+
+/** @file
+ *
+ * Frontend for WPA using a pre-shared key.
+ */
+
+/**
+ * Initialise WPA-PSK state
+ *
+ * @v dev 802.11 device
+ * @ret rc Return status code
+ */
+static int wpa_psk_init ( struct net80211_device *dev )
+{
+ return wpa_make_rsn_ie ( dev, &dev->rsn_ie );
+}
+
+/**
+ * Start WPA-PSK authentication
+ *
+ * @v dev 802.11 device
+ * @ret rc Return status code
+ */
+static int wpa_psk_start ( struct net80211_device *dev )
+{
+ char passphrase[64+1];
+ u8 pmk[WPA_PMK_LEN];
+ int len;
+ struct wpa_common_ctx *ctx = dev->handshaker->priv;
+
+ len = fetch_string_setting ( netdev_settings ( dev->netdev ),
+ &net80211_key_setting, passphrase,
+ 64 + 1 );
+
+ if ( len <= 0 ) {
+ DBGC ( ctx, "WPA-PSK %p: no passphrase provided!\n", ctx );
+ net80211_deauthenticate ( dev, -EACCES );
+ return -EACCES;
+ }
+
+ pbkdf2_sha1 ( passphrase, len, dev->essid, strlen ( dev->essid ),
+ 4096, pmk, WPA_PMK_LEN );
+
+ DBGC ( ctx, "WPA-PSK %p: derived PMK from passphrase `%s':\n", ctx,
+ passphrase );
+ DBGC_HD ( ctx, pmk, WPA_PMK_LEN );
+
+ return wpa_start ( dev, ctx, pmk, WPA_PMK_LEN );
+}
+
+/**
+ * Step WPA-PSK authentication
+ *
+ * @v dev 802.11 device
+ * @ret rc Return status code
+ */
+static int wpa_psk_step ( struct net80211_device *dev )
+{
+ struct wpa_common_ctx *ctx = dev->handshaker->priv;
+
+ switch ( ctx->state ) {
+ case WPA_SUCCESS:
+ return 1;
+ case WPA_FAILURE:
+ return -EACCES;
+ default:
+ return 0;
+ }
+}
+
+/**
+ * Do-nothing function; you can't change a WPA key post-authentication
+ *
+ * @v dev 802.11 device
+ * @ret rc Return status code
+ */
+static int wpa_psk_no_change_key ( struct net80211_device *dev __unused )
+{
+ return 0;
+}
+
+/**
+ * Disable handling of received WPA authentication frames
+ *
+ * @v dev 802.11 device
+ */
+static void wpa_psk_stop ( struct net80211_device *dev )
+{
+ wpa_stop ( dev );
+}
+
+/** WPA-PSK security handshaker */
+struct net80211_handshaker wpa_psk_handshaker __net80211_handshaker = {
+ .protocol = NET80211_SECPROT_PSK,
+ .init = wpa_psk_init,
+ .start = wpa_psk_start,
+ .step = wpa_psk_step,
+ .change_key = wpa_psk_no_change_key,
+ .stop = wpa_psk_stop,
+ .priv_len = sizeof ( struct wpa_common_ctx ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/80211/wpa_tkip.c b/src/VBox/Devices/PC/ipxe/src/net/80211/wpa_tkip.c
new file mode 100644
index 00000000..871666ee
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/80211/wpa_tkip.c
@@ -0,0 +1,587 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <ipxe/net80211.h>
+#include <ipxe/crypto.h>
+#include <ipxe/hmac.h>
+#include <ipxe/sha1.h>
+#include <ipxe/md5.h>
+#include <ipxe/crc32.h>
+#include <ipxe/arc4.h>
+#include <ipxe/wpa.h>
+#include <byteswap.h>
+#include <errno.h>
+
+/** @file
+ *
+ * Backend for WPA using the TKIP encryption standard.
+ */
+
+/** Context for one direction of TKIP, either encryption or decryption */
+struct tkip_dir_ctx
+{
+ /** High 32 bits of last sequence counter value used */
+ u32 tsc_hi;
+
+ /** Low 32 bits of last sequence counter value used */
+ u16 tsc_lo;
+
+ /** MAC address used to derive TTAK */
+ u8 mac[ETH_ALEN];
+
+ /** If TRUE, TTAK is valid */
+ u16 ttak_ok;
+
+ /** TKIP-mixed transmit address and key, depends on tsc_hi and MAC */
+ u16 ttak[5];
+};
+
+/** Context for TKIP encryption and decryption */
+struct tkip_ctx
+{
+ /** Temporal key to use */
+ struct tkip_tk tk;
+
+ /** State for encryption */
+ struct tkip_dir_ctx enc;
+
+ /** State for decryption */
+ struct tkip_dir_ctx dec;
+};
+
+/** Header structure at the beginning of TKIP frame data */
+struct tkip_head
+{
+ u8 tsc1; /**< High byte of low 16 bits of TSC */
+ u8 seed1; /**< Second byte of WEP seed */
+ u8 tsc0; /**< Low byte of TSC */
+ u8 kid; /**< Key ID and ExtIV byte */
+ u32 tsc_hi; /**< High 32 bits of TSC, as an ExtIV */
+} __attribute__ (( packed ));
+
+
+/** TKIP header overhead (IV + KID + ExtIV) */
+#define TKIP_HEAD_LEN 8
+
+/** TKIP trailer overhead (MIC + ICV) [assumes unfragmented] */
+#define TKIP_FOOT_LEN 12
+
+/** TKIP MIC length */
+#define TKIP_MIC_LEN 8
+
+/** TKIP ICV length */
+#define TKIP_ICV_LEN 4
+
+
+/** TKIP S-box */
+static const u16 Sbox[256] = {
+ 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
+ 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
+ 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
+ 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
+ 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
+ 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
+ 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
+ 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
+ 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
+ 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
+ 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
+ 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
+ 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
+ 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
+ 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
+ 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
+ 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
+ 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
+ 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
+ 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
+ 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
+ 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
+ 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
+ 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
+ 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
+ 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
+ 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
+ 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
+ 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
+ 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
+ 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
+ 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
+};
+
+/**
+ * Perform S-box mapping on a 16-bit value
+ *
+ * @v v Value to perform S-box mapping on
+ * @ret Sv S-box mapped value
+ */
+static inline u16 S ( u16 v )
+{
+ return Sbox[v & 0xFF] ^ swap16 ( Sbox[v >> 8] );
+}
+
+/**
+ * Rotate 16-bit value right
+ *
+ * @v v Value to rotate
+ * @v bits Number of bits to rotate by
+ * @ret rotv Rotated value
+ */
+static inline u16 ror16 ( u16 v, int bits )
+{
+ return ( v >> bits ) | ( v << ( 16 - bits ) );
+}
+
+/**
+ * Rotate 32-bit value right
+ *
+ * @v v Value to rotate
+ * @v bits Number of bits to rotate by
+ * @ret rotv Rotated value
+ */
+static inline u32 ror32 ( u32 v, int bits )
+{
+ return ( v >> bits ) | ( v << ( 32 - bits ) );
+}
+
+/**
+ * Rotate 32-bit value left
+ *
+ * @v v Value to rotate
+ * @v bits Number of bits to rotate by
+ * @ret rotv Rotated value
+ */
+static inline u32 rol32 ( u32 v, int bits )
+{
+ return ( v << bits ) | ( v >> ( 32 - bits ) );
+}
+
+
+/**
+ * Initialise TKIP state and install key
+ *
+ * @v crypto TKIP cryptosystem structure
+ * @v key Pointer to tkip_tk to install
+ * @v keylen Length of key (32 bytes)
+ * @v rsc Initial receive sequence counter
+ */
+static int tkip_init ( struct net80211_crypto *crypto, const void *key,
+ int keylen, const void *rsc )
+{
+ struct tkip_ctx *ctx = crypto->priv;
+ const u8 *rscb = rsc;
+
+ if ( keylen != sizeof ( ctx->tk ) )
+ return -EINVAL;
+
+ if ( rscb ) {
+ ctx->dec.tsc_lo = ( rscb[1] << 8 ) | rscb[0];
+ ctx->dec.tsc_hi = ( ( rscb[5] << 24 ) | ( rscb[4] << 16 ) |
+ ( rscb[3] << 8 ) | rscb[2] );
+ }
+
+ memcpy ( &ctx->tk, key, sizeof ( ctx->tk ) );
+
+ return 0;
+}
+
+/**
+ * Perform TKIP key mixing, phase 1
+ *
+ * @v dctx TKIP directional context
+ * @v tk TKIP temporal key
+ * @v mac MAC address of transmitter
+ *
+ * This recomputes the TTAK in @a dctx if necessary, and sets
+ * @c dctx->ttak_ok.
+ */
+static void tkip_mix_1 ( struct tkip_dir_ctx *dctx, struct tkip_tk *tk, u8 *mac )
+{
+ int i, j;
+
+ if ( dctx->ttak_ok && ! memcmp ( mac, dctx->mac, ETH_ALEN ) )
+ return;
+
+ memcpy ( dctx->mac, mac, ETH_ALEN );
+
+ dctx->ttak[0] = dctx->tsc_hi & 0xFFFF;
+ dctx->ttak[1] = dctx->tsc_hi >> 16;
+ dctx->ttak[2] = ( mac[1] << 8 ) | mac[0];
+ dctx->ttak[3] = ( mac[3] << 8 ) | mac[2];
+ dctx->ttak[4] = ( mac[5] << 8 ) | mac[4];
+
+ for ( i = 0; i < 8; i++ ) {
+ j = 2 * ( i & 1 );
+
+ dctx->ttak[0] += S ( dctx->ttak[4] ^ ( ( tk->key[1 + j] << 8 ) |
+ tk->key[0 + j] ) );
+ dctx->ttak[1] += S ( dctx->ttak[0] ^ ( ( tk->key[5 + j] << 8 ) |
+ tk->key[4 + j] ) );
+ dctx->ttak[2] += S ( dctx->ttak[1] ^ ( ( tk->key[9 + j] << 8 ) |
+ tk->key[8 + j] ) );
+ dctx->ttak[3] += S ( dctx->ttak[2] ^ ( ( tk->key[13+ j] << 8 ) |
+ tk->key[12+ j] ) );
+ dctx->ttak[4] += S ( dctx->ttak[3] ^ ( ( tk->key[1 + j] << 8 ) |
+ tk->key[0 + j] ) ) + i;
+ }
+
+ dctx->ttak_ok = 1;
+}
+
+/**
+ * Perform TKIP key mixing, phase 2
+ *
+ * @v dctx TKIP directional context
+ * @v tk TKIP temporal key
+ * @ret key ARC4 key, 16 bytes long
+ */
+static void tkip_mix_2 ( struct tkip_dir_ctx *dctx, struct tkip_tk *tk,
+ void *key )
+{
+ u8 *kb = key;
+ u16 ppk[6];
+ int i;
+
+ memcpy ( ppk, dctx->ttak, sizeof ( dctx->ttak ) );
+ ppk[5] = dctx->ttak[4] + dctx->tsc_lo;
+
+ ppk[0] += S ( ppk[5] ^ ( ( tk->key[1] << 8 ) | tk->key[0] ) );
+ ppk[1] += S ( ppk[0] ^ ( ( tk->key[3] << 8 ) | tk->key[2] ) );
+ ppk[2] += S ( ppk[1] ^ ( ( tk->key[5] << 8 ) | tk->key[4] ) );
+ ppk[3] += S ( ppk[2] ^ ( ( tk->key[7] << 8 ) | tk->key[6] ) );
+ ppk[4] += S ( ppk[3] ^ ( ( tk->key[9] << 8 ) | tk->key[8] ) );
+ ppk[5] += S ( ppk[4] ^ ( ( tk->key[11] << 8 ) | tk->key[10] ) );
+
+ ppk[0] += ror16 ( ppk[5] ^ ( ( tk->key[13] << 8 ) | tk->key[12] ), 1 );
+ ppk[1] += ror16 ( ppk[0] ^ ( ( tk->key[15] << 8 ) | tk->key[14] ), 1 );
+ ppk[2] += ror16 ( ppk[1], 1 );
+ ppk[3] += ror16 ( ppk[2], 1 );
+ ppk[4] += ror16 ( ppk[3], 1 );
+ ppk[5] += ror16 ( ppk[4], 1 );
+
+ kb[0] = dctx->tsc_lo >> 8;
+ kb[1] = ( ( dctx->tsc_lo >> 8 ) | 0x20 ) & 0x7F;
+ kb[2] = dctx->tsc_lo & 0xFF;
+ kb[3] = ( ( ppk[5] ^ ( ( tk->key[1] << 8 ) | tk->key[0] ) ) >> 1 )
+ & 0xFF;
+
+ for ( i = 0; i < 6; i++ ) {
+ kb[4 + 2*i] = ppk[i] & 0xFF;
+ kb[5 + 2*i] = ppk[i] >> 8;
+ }
+}
+
+/**
+ * Update Michael message integrity code based on next 32-bit word of data
+ *
+ * @v V Michael code state (two 32-bit words)
+ * @v word Next 32-bit word of data
+ */
+static void tkip_feed_michael ( u32 *V, u32 word )
+{
+ V[0] ^= word;
+ V[1] ^= rol32 ( V[0], 17 );
+ V[0] += V[1];
+ V[1] ^= ( ( V[0] & 0xFF00FF00 ) >> 8 ) | ( ( V[0] & 0x00FF00FF ) << 8 );
+ V[0] += V[1];
+ V[1] ^= rol32 ( V[0], 3 );
+ V[0] += V[1];
+ V[1] ^= ror32 ( V[0], 2 );
+ V[0] += V[1];
+}
+
+/**
+ * Calculate Michael message integrity code
+ *
+ * @v key MIC key to use (8 bytes)
+ * @v da Destination link-layer address
+ * @v sa Source link-layer address
+ * @v data Start of data to calculate over
+ * @v len Length of header + data
+ * @ret mic Calculated Michael MIC (8 bytes)
+ */
+static void tkip_michael ( const void *key, const void *da, const void *sa,
+ const void *data, size_t len, void *mic )
+{
+ u32 V[2]; /* V[0] = "l", V[1] = "r" in 802.11 */
+ union {
+ u8 byte[12];
+ u32 word[3];
+ } cap;
+ const u8 *ptr = data;
+ const u8 *end = ptr + len;
+ int i;
+
+ memcpy ( V, key, sizeof ( V ) );
+ V[0] = le32_to_cpu ( V[0] );
+ V[1] = le32_to_cpu ( V[1] );
+
+ /* Feed in header (we assume non-QoS, so Priority = 0) */
+ memcpy ( &cap.byte[0], da, ETH_ALEN );
+ memcpy ( &cap.byte[6], sa, ETH_ALEN );
+ tkip_feed_michael ( V, le32_to_cpu ( cap.word[0] ) );
+ tkip_feed_michael ( V, le32_to_cpu ( cap.word[1] ) );
+ tkip_feed_michael ( V, le32_to_cpu ( cap.word[2] ) );
+ tkip_feed_michael ( V, 0 );
+
+ /* Feed in data */
+ while ( ptr + 4 <= end ) {
+ tkip_feed_michael ( V, le32_to_cpu ( *( u32 * ) ptr ) );
+ ptr += 4;
+ }
+
+ /* Add unaligned part and padding */
+ for ( i = 0; ptr < end; i++ )
+ cap.byte[i] = *ptr++;
+ cap.byte[i++] = 0x5a;
+ for ( ; i < 8; i++ )
+ cap.byte[i] = 0;
+
+ /* Feed in padding */
+ tkip_feed_michael ( V, le32_to_cpu ( cap.word[0] ) );
+ tkip_feed_michael ( V, le32_to_cpu ( cap.word[1] ) );
+
+ /* Output MIC */
+ V[0] = cpu_to_le32 ( V[0] );
+ V[1] = cpu_to_le32 ( V[1] );
+ memcpy ( mic, V, sizeof ( V ) );
+}
+
+/**
+ * Encrypt a packet using TKIP
+ *
+ * @v crypto TKIP cryptosystem
+ * @v iob I/O buffer containing cleartext packet
+ * @ret eiob I/O buffer containing encrypted packet
+ */
+static struct io_buffer * tkip_encrypt ( struct net80211_crypto *crypto,
+ struct io_buffer *iob )
+{
+ struct tkip_ctx *ctx = crypto->priv;
+ struct ieee80211_frame *hdr = iob->data;
+ struct io_buffer *eiob;
+ struct arc4_ctx arc4;
+ u8 key[16];
+ struct tkip_head head;
+ u8 mic[8];
+ u32 icv;
+ const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
+ int datalen = iob_len ( iob ) - hdrlen;
+
+ ctx->enc.tsc_lo++;
+ if ( ctx->enc.tsc_lo == 0 ) {
+ ctx->enc.tsc_hi++;
+ ctx->enc.ttak_ok = 0;
+ }
+
+ tkip_mix_1 ( &ctx->enc, &ctx->tk, hdr->addr2 );
+ tkip_mix_2 ( &ctx->enc, &ctx->tk, key );
+
+ eiob = alloc_iob ( iob_len ( iob ) + TKIP_HEAD_LEN + TKIP_FOOT_LEN );
+ if ( ! eiob )
+ return NULL;
+
+ /* Copy frame header */
+ memcpy ( iob_put ( eiob, hdrlen ), iob->data, hdrlen );
+ hdr = eiob->data;
+ hdr->fc |= IEEE80211_FC_PROTECTED;
+
+ /* Fill in IV and key ID byte, and extended IV */
+ memcpy ( &head, key, 3 );
+ head.kid = 0x20; /* have Extended IV, key ID 0 */
+ head.tsc_hi = cpu_to_le32 ( ctx->enc.tsc_hi );
+ memcpy ( iob_put ( eiob, sizeof ( head ) ), &head, sizeof ( head ) );
+
+ /* Copy and encrypt the data */
+ cipher_setkey ( &arc4_algorithm, &arc4, key, 16 );
+ cipher_encrypt ( &arc4_algorithm, &arc4, iob->data + hdrlen,
+ iob_put ( eiob, datalen ), datalen );
+
+ /* Add MIC */
+ hdr = iob->data;
+ tkip_michael ( &ctx->tk.mic.tx, hdr->addr3, hdr->addr2,
+ iob->data + hdrlen, datalen, mic );
+ cipher_encrypt ( &arc4_algorithm, &arc4, mic,
+ iob_put ( eiob, sizeof ( mic ) ), sizeof ( mic ) );
+
+ /* Add ICV */
+ icv = crc32_le ( ~0, iob->data + hdrlen, datalen );
+ icv = crc32_le ( icv, mic, sizeof ( mic ) );
+ icv = cpu_to_le32 ( ~icv );
+ cipher_encrypt ( &arc4_algorithm, &arc4, &icv,
+ iob_put ( eiob, TKIP_ICV_LEN ), TKIP_ICV_LEN );
+
+ DBGC2 ( ctx, "WPA-TKIP %p: encrypted packet %p -> %p\n", ctx,
+ iob, eiob );
+
+ return eiob;
+}
+
+/**
+ * Decrypt a packet using TKIP
+ *
+ * @v crypto TKIP cryptosystem
+ * @v eiob I/O buffer containing encrypted packet
+ * @ret iob I/O buffer containing cleartext packet
+ */
+static struct io_buffer * tkip_decrypt ( struct net80211_crypto *crypto,
+ struct io_buffer *eiob )
+{
+ struct tkip_ctx *ctx = crypto->priv;
+ struct ieee80211_frame *hdr;
+ struct io_buffer *iob;
+ const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
+ int datalen = iob_len ( eiob ) - hdrlen - TKIP_HEAD_LEN - TKIP_FOOT_LEN;
+ struct tkip_head *head;
+ struct arc4_ctx arc4;
+ u16 rx_tsc_lo;
+ u8 key[16];
+ u8 mic[8];
+ u32 icv, crc;
+
+ iob = alloc_iob ( hdrlen + datalen + TKIP_FOOT_LEN );
+ if ( ! iob )
+ return NULL;
+
+ /* Copy frame header */
+ memcpy ( iob_put ( iob, hdrlen ), eiob->data, hdrlen );
+ hdr = iob->data;
+ hdr->fc &= ~IEEE80211_FC_PROTECTED;
+
+ /* Check and update TSC */
+ head = eiob->data + hdrlen;
+ rx_tsc_lo = ( head->tsc1 << 8 ) | head->tsc0;
+
+ if ( head->tsc_hi < ctx->dec.tsc_hi ||
+ ( head->tsc_hi == ctx->dec.tsc_hi &&
+ rx_tsc_lo <= ctx->dec.tsc_lo ) ) {
+ DBGC ( ctx, "WPA-TKIP %p: packet received out of order "
+ "(%08x:%04x <= %08x:%04x)\n", ctx, head->tsc_hi,
+ rx_tsc_lo, ctx->dec.tsc_hi, ctx->dec.tsc_lo );
+ free_iob ( iob );
+ return NULL;
+ }
+ ctx->dec.tsc_lo = rx_tsc_lo;
+ if ( ctx->dec.tsc_hi != head->tsc_hi ) {
+ ctx->dec.ttak_ok = 0;
+ ctx->dec.tsc_hi = head->tsc_hi;
+ }
+
+ /* Calculate key */
+ tkip_mix_1 ( &ctx->dec, &ctx->tk, hdr->addr2 );
+ tkip_mix_2 ( &ctx->dec, &ctx->tk, key );
+
+ /* Copy-decrypt data, MIC, ICV */
+ cipher_setkey ( &arc4_algorithm, &arc4, key, 16 );
+ cipher_decrypt ( &arc4_algorithm, &arc4,
+ eiob->data + hdrlen + TKIP_HEAD_LEN,
+ iob_put ( iob, datalen ), datalen + TKIP_FOOT_LEN );
+
+ /* Check ICV */
+ icv = le32_to_cpu ( *( u32 * ) ( iob->tail + TKIP_MIC_LEN ) );
+ crc = ~crc32_le ( ~0, iob->data + hdrlen, datalen + TKIP_MIC_LEN );
+ if ( crc != icv ) {
+ DBGC ( ctx, "WPA-TKIP %p CRC mismatch: expect %08x, get %08x\n",
+ ctx, icv, crc );
+ free_iob ( iob );
+ return NULL;
+ }
+
+ /* Check MIC */
+ tkip_michael ( &ctx->tk.mic.rx, hdr->addr1, hdr->addr3,
+ iob->data + hdrlen, datalen, mic );
+ if ( memcmp ( mic, iob->tail, TKIP_MIC_LEN ) != 0 ) {
+ DBGC ( ctx, "WPA-TKIP %p ALERT! MIC failure\n", ctx );
+ /* XXX we should do the countermeasures here */
+ free_iob ( iob );
+ return NULL;
+ }
+
+ DBGC2 ( ctx, "WPA-TKIP %p: decrypted packet %p -> %p\n", ctx,
+ eiob, iob );
+
+ return iob;
+}
+
+/** TKIP cryptosystem */
+struct net80211_crypto tkip_crypto __net80211_crypto = {
+ .algorithm = NET80211_CRYPT_TKIP,
+ .init = tkip_init,
+ .encrypt = tkip_encrypt,
+ .decrypt = tkip_decrypt,
+ .priv_len = sizeof ( struct tkip_ctx ),
+};
+
+
+
+
+/**
+ * Calculate HMAC-MD5 MIC for EAPOL-Key frame
+ *
+ * @v kck Key Confirmation Key, 16 bytes
+ * @v msg Message to calculate MIC over
+ * @v len Number of bytes to calculate MIC over
+ * @ret mic Calculated MIC, 16 bytes long
+ */
+static void tkip_kie_mic ( const void *kck, const void *msg, size_t len,
+ void *mic )
+{
+ uint8_t ctx[MD5_CTX_SIZE];
+ u8 kckb[16];
+ size_t kck_len = 16;
+
+ memcpy ( kckb, kck, kck_len );
+
+ hmac_init ( &md5_algorithm, ctx, kckb, &kck_len );
+ hmac_update ( &md5_algorithm, ctx, msg, len );
+ hmac_final ( &md5_algorithm, ctx, kckb, &kck_len, mic );
+}
+
+/**
+ * Decrypt key data in EAPOL-Key frame
+ *
+ * @v kek Key Encryption Key, 16 bytes
+ * @v iv Initialisation vector, 16 bytes
+ * @v msg Message to decrypt
+ * @v len Length of message
+ * @ret msg Decrypted message in place of original
+ * @ret len Unchanged
+ * @ret rc Always 0 for success
+ */
+static int tkip_kie_decrypt ( const void *kek, const void *iv,
+ void *msg, u16 *len )
+{
+ u8 key[32];
+ memcpy ( key, iv, 16 );
+ memcpy ( key + 16, kek, 16 );
+
+ arc4_skip ( key, 32, 256, msg, msg, *len );
+
+ return 0;
+}
+
+
+/** TKIP-style key integrity and encryption handler */
+struct wpa_kie tkip_kie __wpa_kie = {
+ .version = EAPOL_KEY_VERSION_WPA,
+ .mic = tkip_kie_mic,
+ .decrypt = tkip_kie_decrypt,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/aoe.c b/src/VBox/Devices/PC/ipxe/src/net/aoe.c
new file mode 100644
index 00000000..1016b250
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/aoe.c
@@ -0,0 +1,1056 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/list.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/features.h>
+#include <ipxe/interface.h>
+#include <ipxe/xfer.h>
+#include <ipxe/uri.h>
+#include <ipxe/open.h>
+#include <ipxe/ata.h>
+#include <ipxe/device.h>
+#include <ipxe/aoe.h>
+
+/** @file
+ *
+ * AoE protocol
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "AoE", DHCP_EB_FEATURE_AOE, 1 );
+
+struct net_protocol aoe_protocol __net_protocol;
+
+/******************************************************************************
+ *
+ * AoE devices and commands
+ *
+ ******************************************************************************
+ */
+
+/** List of all AoE devices */
+static LIST_HEAD ( aoe_devices );
+
+/** List of active AoE commands */
+static LIST_HEAD ( aoe_commands );
+
+/** An AoE device */
+struct aoe_device {
+ /** Reference counter */
+ struct refcnt refcnt;
+
+ /** Network device */
+ struct net_device *netdev;
+ /** ATA command issuing interface */
+ struct interface ata;
+
+ /** Major number */
+ uint16_t major;
+ /** Minor number */
+ uint8_t minor;
+ /** Target MAC address */
+ uint8_t target[MAX_LL_ADDR_LEN];
+
+ /** Saved timeout value */
+ unsigned long timeout;
+
+ /** Configuration command interface */
+ struct interface config;
+ /** Device is configued */
+ int configured;
+};
+
+/** An AoE command */
+struct aoe_command {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** AOE device */
+ struct aoe_device *aoedev;
+ /** List of active commands */
+ struct list_head list;
+
+ /** ATA command interface */
+ struct interface ata;
+
+ /** ATA command */
+ struct ata_cmd command;
+ /** Command type */
+ struct aoe_command_type *type;
+ /** Command tag */
+ uint32_t tag;
+
+ /** Retransmission timer */
+ struct retry_timer timer;
+};
+
+/** An AoE command type */
+struct aoe_command_type {
+ /**
+ * Calculate length of AoE command IU
+ *
+ * @v aoecmd AoE command
+ * @ret len Length of command IU
+ */
+ size_t ( * cmd_len ) ( struct aoe_command *aoecmd );
+ /**
+ * Build AoE command IU
+ *
+ * @v aoecmd AoE command
+ * @v data Command IU
+ * @v len Length of command IU
+ */
+ void ( * cmd ) ( struct aoe_command *aoecmd, void *data, size_t len );
+ /**
+ * Handle AoE response IU
+ *
+ * @v aoecmd AoE command
+ * @v data Response IU
+ * @v len Length of response IU
+ * @v ll_source Link-layer source address
+ * @ret rc Return status code
+ */
+ int ( * rsp ) ( struct aoe_command *aoecmd, const void *data,
+ size_t len, const void *ll_source );
+};
+
+/**
+ * Get reference to AoE device
+ *
+ * @v aoedev AoE device
+ * @ret aoedev AoE device
+ */
+static inline __attribute__ (( always_inline )) struct aoe_device *
+aoedev_get ( struct aoe_device *aoedev ) {
+ ref_get ( &aoedev->refcnt );
+ return aoedev;
+}
+
+/**
+ * Drop reference to AoE device
+ *
+ * @v aoedev AoE device
+ */
+static inline __attribute__ (( always_inline )) void
+aoedev_put ( struct aoe_device *aoedev ) {
+ ref_put ( &aoedev->refcnt );
+}
+
+/**
+ * Get reference to AoE command
+ *
+ * @v aoecmd AoE command
+ * @ret aoecmd AoE command
+ */
+static inline __attribute__ (( always_inline )) struct aoe_command *
+aoecmd_get ( struct aoe_command *aoecmd ) {
+ ref_get ( &aoecmd->refcnt );
+ return aoecmd;
+}
+
+/**
+ * Drop reference to AoE command
+ *
+ * @v aoecmd AoE command
+ */
+static inline __attribute__ (( always_inline )) void
+aoecmd_put ( struct aoe_command *aoecmd ) {
+ ref_put ( &aoecmd->refcnt );
+}
+
+/**
+ * Name AoE device
+ *
+ * @v aoedev AoE device
+ * @ret name AoE device name
+ */
+static const char * aoedev_name ( struct aoe_device *aoedev ) {
+ static char buf[16];
+
+ snprintf ( buf, sizeof ( buf ), "%s/e%d.%d", aoedev->netdev->name,
+ aoedev->major, aoedev->minor );
+ return buf;
+}
+
+/**
+ * Free AoE command
+ *
+ * @v refcnt Reference counter
+ */
+static void aoecmd_free ( struct refcnt *refcnt ) {
+ struct aoe_command *aoecmd =
+ container_of ( refcnt, struct aoe_command, refcnt );
+
+ assert ( ! timer_running ( &aoecmd->timer ) );
+ assert ( list_empty ( &aoecmd->list ) );
+
+ aoedev_put ( aoecmd->aoedev );
+ free ( aoecmd );
+}
+
+/**
+ * Close AoE command
+ *
+ * @v aoecmd AoE command
+ * @v rc Reason for close
+ */
+static void aoecmd_close ( struct aoe_command *aoecmd, int rc ) {
+ struct aoe_device *aoedev = aoecmd->aoedev;
+
+ /* Stop timer */
+ stop_timer ( &aoecmd->timer );
+
+ /* Preserve the timeout value for subsequent commands */
+ aoedev->timeout = aoecmd->timer.timeout;
+
+ /* Remove from list of commands */
+ if ( ! list_empty ( &aoecmd->list ) ) {
+ list_del ( &aoecmd->list );
+ INIT_LIST_HEAD ( &aoecmd->list );
+ aoecmd_put ( aoecmd );
+ }
+
+ /* Shut down interfaces */
+ intf_shutdown ( &aoecmd->ata, rc );
+}
+
+/**
+ * Transmit AoE command request
+ *
+ * @v aoecmd AoE command
+ * @ret rc Return status code
+ */
+static int aoecmd_tx ( struct aoe_command *aoecmd ) {
+ struct aoe_device *aoedev = aoecmd->aoedev;
+ struct net_device *netdev = aoedev->netdev;
+ struct io_buffer *iobuf;
+ struct aoehdr *aoehdr;
+ size_t cmd_len;
+ int rc;
+
+ /* Sanity check */
+ assert ( netdev != NULL );
+
+ /* If we are transmitting anything that requires a response,
+ * start the retransmission timer. Do this before attempting
+ * to allocate the I/O buffer, in case allocation itself
+ * fails.
+ */
+ start_timer ( &aoecmd->timer );
+
+ /* Create outgoing I/O buffer */
+ cmd_len = aoecmd->type->cmd_len ( aoecmd );
+ iobuf = alloc_iob ( MAX_LL_HEADER_LEN + cmd_len );
+ if ( ! iobuf )
+ return -ENOMEM;
+ iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
+ aoehdr = iob_put ( iobuf, cmd_len );
+
+ /* Fill AoE header */
+ memset ( aoehdr, 0, sizeof ( *aoehdr ) );
+ aoehdr->ver_flags = AOE_VERSION;
+ aoehdr->major = htons ( aoedev->major );
+ aoehdr->minor = aoedev->minor;
+ aoehdr->tag = htonl ( aoecmd->tag );
+ aoecmd->type->cmd ( aoecmd, iobuf->data, iob_len ( iobuf ) );
+
+ /* Send packet */
+ if ( ( rc = net_tx ( iobuf, netdev, &aoe_protocol, aoedev->target,
+ netdev->ll_addr ) ) != 0 ) {
+ DBGC ( aoedev, "AoE %s/%08x could not transmit: %s\n",
+ aoedev_name ( aoedev ), aoecmd->tag,
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Receive AoE command response
+ *
+ * @v aoecmd AoE command
+ * @v iobuf I/O buffer
+ * @v ll_source Link-layer source address
+ * @ret rc Return status code
+ */
+static int aoecmd_rx ( struct aoe_command *aoecmd, struct io_buffer *iobuf,
+ const void *ll_source ) {
+ struct aoe_device *aoedev = aoecmd->aoedev;
+ struct aoehdr *aoehdr = iobuf->data;
+ int rc;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *aoehdr ) ) {
+ DBGC ( aoedev, "AoE %s/%08x received underlength response "
+ "(%zd bytes)\n", aoedev_name ( aoedev ),
+ aoecmd->tag, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto done;
+ }
+ if ( ( ntohs ( aoehdr->major ) != aoedev->major ) ||
+ ( aoehdr->minor != aoedev->minor ) ) {
+ DBGC ( aoedev, "AoE %s/%08x received response for incorrect "
+ "device e%d.%d\n", aoedev_name ( aoedev ), aoecmd->tag,
+ ntohs ( aoehdr->major ), aoehdr->minor );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Catch command failures */
+ if ( aoehdr->ver_flags & AOE_FL_ERROR ) {
+ DBGC ( aoedev, "AoE %s/%08x terminated in error\n",
+ aoedev_name ( aoedev ), aoecmd->tag );
+ aoecmd_close ( aoecmd, -EIO );
+ rc = -EIO;
+ goto done;
+ }
+
+ /* Hand off to command completion handler */
+ if ( ( rc = aoecmd->type->rsp ( aoecmd, iobuf->data, iob_len ( iobuf ),
+ ll_source ) ) != 0 )
+ goto done;
+
+ done:
+ /* Free I/O buffer */
+ free_iob ( iobuf );
+
+ /* Terminate command */
+ aoecmd_close ( aoecmd, rc );
+
+ return rc;
+}
+
+/**
+ * Handle AoE retry timer expiry
+ *
+ * @v timer AoE retry timer
+ * @v fail Failure indicator
+ */
+static void aoecmd_expired ( struct retry_timer *timer, int fail ) {
+ struct aoe_command *aoecmd =
+ container_of ( timer, struct aoe_command, timer );
+
+ if ( fail ) {
+ aoecmd_close ( aoecmd, -ETIMEDOUT );
+ } else {
+ aoecmd_tx ( aoecmd );
+ }
+}
+
+/**
+ * Calculate length of AoE ATA command IU
+ *
+ * @v aoecmd AoE command
+ * @ret len Length of command IU
+ */
+static size_t aoecmd_ata_cmd_len ( struct aoe_command *aoecmd ) {
+ struct ata_cmd *command = &aoecmd->command;
+
+ return ( sizeof ( struct aoehdr ) + sizeof ( struct aoeata ) +
+ command->data_out_len );
+}
+
+/**
+ * Build AoE ATA command IU
+ *
+ * @v aoecmd AoE command
+ * @v data Command IU
+ * @v len Length of command IU
+ */
+static void aoecmd_ata_cmd ( struct aoe_command *aoecmd,
+ void *data, size_t len ) {
+ struct aoe_device *aoedev = aoecmd->aoedev;
+ struct ata_cmd *command = &aoecmd->command;
+ struct aoehdr *aoehdr = data;
+ struct aoeata *aoeata = &aoehdr->payload[0].ata;
+
+ /* Sanity check */
+ linker_assert ( AOE_FL_DEV_HEAD == ATA_DEV_SLAVE, __fix_ata_h__ );
+ assert ( len == ( sizeof ( *aoehdr ) + sizeof ( *aoeata ) +
+ command->data_out_len ) );
+
+ /* Build IU */
+ aoehdr->command = AOE_CMD_ATA;
+ memset ( aoeata, 0, sizeof ( *aoeata ) );
+ aoeata->aflags = ( ( command->cb.lba48 ? AOE_FL_EXTENDED : 0 ) |
+ ( command->cb.device & ATA_DEV_SLAVE ) |
+ ( command->data_out_len ? AOE_FL_WRITE : 0 ) );
+ aoeata->err_feat = command->cb.err_feat.bytes.cur;
+ aoeata->count = command->cb.count.native;
+ aoeata->cmd_stat = command->cb.cmd_stat;
+ aoeata->lba.u64 = cpu_to_le64 ( command->cb.lba.native );
+ if ( ! command->cb.lba48 )
+ aoeata->lba.bytes[3] |=
+ ( command->cb.device & ATA_DEV_MASK );
+ copy_from_user ( aoeata->data, command->data_out, 0,
+ command->data_out_len );
+
+ DBGC2 ( aoedev, "AoE %s/%08x ATA cmd %02x:%02x:%02x:%02x:%08llx",
+ aoedev_name ( aoedev ), aoecmd->tag, aoeata->aflags,
+ aoeata->err_feat, aoeata->count, aoeata->cmd_stat,
+ aoeata->lba.u64 );
+ if ( command->data_out_len )
+ DBGC2 ( aoedev, " out %04zx", command->data_out_len );
+ if ( command->data_in_len )
+ DBGC2 ( aoedev, " in %04zx", command->data_in_len );
+ DBGC2 ( aoedev, "\n" );
+}
+
+/**
+ * Handle AoE ATA response IU
+ *
+ * @v aoecmd AoE command
+ * @v data Response IU
+ * @v len Length of response IU
+ * @v ll_source Link-layer source address
+ * @ret rc Return status code
+ */
+static int aoecmd_ata_rsp ( struct aoe_command *aoecmd, const void *data,
+ size_t len, const void *ll_source __unused ) {
+ struct aoe_device *aoedev = aoecmd->aoedev;
+ struct ata_cmd *command = &aoecmd->command;
+ const struct aoehdr *aoehdr = data;
+ const struct aoeata *aoeata = &aoehdr->payload[0].ata;
+ size_t data_len;
+
+ /* Sanity check */
+ if ( len < ( sizeof ( *aoehdr ) + sizeof ( *aoeata ) ) ) {
+ DBGC ( aoedev, "AoE %s/%08x received underlength ATA response "
+ "(%zd bytes)\n", aoedev_name ( aoedev ),
+ aoecmd->tag, len );
+ return -EINVAL;
+ }
+ data_len = ( len - ( sizeof ( *aoehdr ) + sizeof ( *aoeata ) ) );
+ DBGC2 ( aoedev, "AoE %s/%08x ATA rsp %02x in %04zx\n",
+ aoedev_name ( aoedev ), aoecmd->tag, aoeata->cmd_stat,
+ data_len );
+
+ /* Check for command failure */
+ if ( aoeata->cmd_stat & ATA_STAT_ERR ) {
+ DBGC ( aoedev, "AoE %s/%08x status %02x\n",
+ aoedev_name ( aoedev ), aoecmd->tag, aoeata->cmd_stat );
+ return -EIO;
+ }
+
+ /* Check data-in length is sufficient. (There may be trailing
+ * garbage due to Ethernet minimum-frame-size padding.)
+ */
+ if ( data_len < command->data_in_len ) {
+ DBGC ( aoedev, "AoE %s/%08x data-in underrun (received %zd, "
+ "expected %zd)\n", aoedev_name ( aoedev ), aoecmd->tag,
+ data_len, command->data_in_len );
+ return -ERANGE;
+ }
+
+ /* Copy out data payload */
+ copy_to_user ( command->data_in, 0, aoeata->data,
+ command->data_in_len );
+
+ return 0;
+}
+
+/** AoE ATA command */
+static struct aoe_command_type aoecmd_ata = {
+ .cmd_len = aoecmd_ata_cmd_len,
+ .cmd = aoecmd_ata_cmd,
+ .rsp = aoecmd_ata_rsp,
+};
+
+/**
+ * Calculate length of AoE configuration command IU
+ *
+ * @v aoecmd AoE command
+ * @ret len Length of command IU
+ */
+static size_t aoecmd_cfg_cmd_len ( struct aoe_command *aoecmd __unused ) {
+ return ( sizeof ( struct aoehdr ) + sizeof ( struct aoecfg ) );
+}
+
+/**
+ * Build AoE configuration command IU
+ *
+ * @v aoecmd AoE command
+ * @v data Command IU
+ * @v len Length of command IU
+ */
+static void aoecmd_cfg_cmd ( struct aoe_command *aoecmd,
+ void *data, size_t len ) {
+ struct aoe_device *aoedev = aoecmd->aoedev;
+ struct aoehdr *aoehdr = data;
+ struct aoecfg *aoecfg = &aoehdr->payload[0].cfg;
+
+ /* Sanity check */
+ assert ( len == ( sizeof ( *aoehdr ) + sizeof ( *aoecfg ) ) );
+
+ /* Build IU */
+ aoehdr->command = AOE_CMD_CONFIG;
+ memset ( aoecfg, 0, sizeof ( *aoecfg ) );
+
+ DBGC ( aoedev, "AoE %s/%08x CONFIG cmd\n",
+ aoedev_name ( aoedev ), aoecmd->tag );
+}
+
+/**
+ * Handle AoE configuration response IU
+ *
+ * @v aoecmd AoE command
+ * @v data Response IU
+ * @v len Length of response IU
+ * @v ll_source Link-layer source address
+ * @ret rc Return status code
+ */
+static int aoecmd_cfg_rsp ( struct aoe_command *aoecmd, const void *data,
+ size_t len, const void *ll_source ) {
+ struct aoe_device *aoedev = aoecmd->aoedev;
+ struct ll_protocol *ll_protocol = aoedev->netdev->ll_protocol;
+ const struct aoehdr *aoehdr = data;
+ const struct aoecfg *aoecfg = &aoehdr->payload[0].cfg;
+
+ /* Sanity check */
+ if ( len < ( sizeof ( *aoehdr ) + sizeof ( *aoecfg ) ) ) {
+ DBGC ( aoedev, "AoE %s/%08x received underlength "
+ "configuration response (%zd bytes)\n",
+ aoedev_name ( aoedev ), aoecmd->tag, len );
+ return -EINVAL;
+ }
+ DBGC ( aoedev, "AoE %s/%08x CONFIG rsp buf %04x fw %04x scnt %02x\n",
+ aoedev_name ( aoedev ), aoecmd->tag, ntohs ( aoecfg->bufcnt ),
+ aoecfg->fwver, aoecfg->scnt );
+
+ /* Record target MAC address */
+ memcpy ( aoedev->target, ll_source, ll_protocol->ll_addr_len );
+ DBGC ( aoedev, "AoE %s has MAC address %s\n",
+ aoedev_name ( aoedev ), ll_protocol->ntoa ( aoedev->target ) );
+
+ return 0;
+}
+
+/** AoE configuration command */
+static struct aoe_command_type aoecmd_cfg = {
+ .cmd_len = aoecmd_cfg_cmd_len,
+ .cmd = aoecmd_cfg_cmd,
+ .rsp = aoecmd_cfg_rsp,
+};
+
+/** AoE command ATA interface operations */
+static struct interface_operation aoecmd_ata_op[] = {
+ INTF_OP ( intf_close, struct aoe_command *, aoecmd_close ),
+};
+
+/** AoE command ATA interface descriptor */
+static struct interface_descriptor aoecmd_ata_desc =
+ INTF_DESC ( struct aoe_command, ata, aoecmd_ata_op );
+
+/**
+ * Identify AoE command by tag
+ *
+ * @v tag Command tag
+ * @ret aoecmd AoE command, or NULL
+ */
+static struct aoe_command * aoecmd_find_tag ( uint32_t tag ) {
+ struct aoe_command *aoecmd;
+
+ list_for_each_entry ( aoecmd, &aoe_commands, list ) {
+ if ( aoecmd->tag == tag )
+ return aoecmd;
+ }
+ return NULL;
+}
+
+/**
+ * Choose an AoE command tag
+ *
+ * @ret tag New tag, or negative error
+ */
+static int aoecmd_new_tag ( void ) {
+ static uint16_t tag_idx;
+ unsigned int i;
+
+ for ( i = 0 ; i < 65536 ; i++ ) {
+ tag_idx++;
+ if ( aoecmd_find_tag ( tag_idx ) == NULL )
+ return ( AOE_TAG_MAGIC | tag_idx );
+ }
+ return -EADDRINUSE;
+}
+
+/**
+ * Create AoE command
+ *
+ * @v aoedev AoE device
+ * @v type AoE command type
+ * @ret aoecmd AoE command
+ */
+static struct aoe_command * aoecmd_create ( struct aoe_device *aoedev,
+ struct aoe_command_type *type ) {
+ struct aoe_command *aoecmd;
+ int tag;
+
+ /* Allocate command tag */
+ tag = aoecmd_new_tag();
+ if ( tag < 0 )
+ return NULL;
+
+ /* Allocate and initialise structure */
+ aoecmd = zalloc ( sizeof ( *aoecmd ) );
+ if ( ! aoecmd )
+ return NULL;
+ ref_init ( &aoecmd->refcnt, aoecmd_free );
+ list_add ( &aoecmd->list, &aoe_commands );
+ intf_init ( &aoecmd->ata, &aoecmd_ata_desc, &aoecmd->refcnt );
+ timer_init ( &aoecmd->timer, aoecmd_expired, &aoecmd->refcnt );
+ aoecmd->aoedev = aoedev_get ( aoedev );
+ aoecmd->type = type;
+ aoecmd->tag = tag;
+
+ /* Preserve timeout from last completed command */
+ aoecmd->timer.timeout = aoedev->timeout;
+
+ /* Return already mortalised. (Reference is held by command list.) */
+ return aoecmd;
+}
+
+/**
+ * Issue AoE ATA command
+ *
+ * @v aoedev AoE device
+ * @v parent Parent interface
+ * @v command ATA command
+ * @ret tag Command tag, or negative error
+ */
+static int aoedev_ata_command ( struct aoe_device *aoedev,
+ struct interface *parent,
+ struct ata_cmd *command ) {
+ struct net_device *netdev = aoedev->netdev;
+ struct aoe_command *aoecmd;
+
+ /* Fail immediately if net device is closed */
+ if ( ! netdev_is_open ( netdev ) ) {
+ DBGC ( aoedev, "AoE %s cannot issue command while net device "
+ "is closed\n", aoedev_name ( aoedev ) );
+ return -EWOULDBLOCK;
+ }
+
+ /* Create command */
+ aoecmd = aoecmd_create ( aoedev, &aoecmd_ata );
+ if ( ! aoecmd )
+ return -ENOMEM;
+ memcpy ( &aoecmd->command, command, sizeof ( aoecmd->command ) );
+
+ /* Attempt to send command. Allow failures to be handled by
+ * the retry timer.
+ */
+ aoecmd_tx ( aoecmd );
+
+ /* Attach to parent interface, leave reference with command
+ * list, and return.
+ */
+ intf_plug_plug ( &aoecmd->ata, parent );
+ return aoecmd->tag;
+}
+
+/**
+ * Issue AoE configuration command
+ *
+ * @v aoedev AoE device
+ * @v parent Parent interface
+ * @ret tag Command tag, or negative error
+ */
+static int aoedev_cfg_command ( struct aoe_device *aoedev,
+ struct interface *parent ) {
+ struct aoe_command *aoecmd;
+
+ /* Create command */
+ aoecmd = aoecmd_create ( aoedev, &aoecmd_cfg );
+ if ( ! aoecmd )
+ return -ENOMEM;
+
+ /* Attempt to send command. Allow failures to be handled by
+ * the retry timer.
+ */
+ aoecmd_tx ( aoecmd );
+
+ /* Attach to parent interface, leave reference with command
+ * list, and return.
+ */
+ intf_plug_plug ( &aoecmd->ata, parent );
+ return aoecmd->tag;
+}
+
+/**
+ * Free AoE device
+ *
+ * @v refcnt Reference count
+ */
+static void aoedev_free ( struct refcnt *refcnt ) {
+ struct aoe_device *aoedev =
+ container_of ( refcnt, struct aoe_device, refcnt );
+
+ netdev_put ( aoedev->netdev );
+ free ( aoedev );
+}
+
+/**
+ * Close AoE device
+ *
+ * @v aoedev AoE device
+ * @v rc Reason for close
+ */
+static void aoedev_close ( struct aoe_device *aoedev, int rc ) {
+ struct aoe_command *aoecmd;
+ struct aoe_command *tmp;
+
+ /* Shut down interfaces */
+ intf_shutdown ( &aoedev->ata, rc );
+ intf_shutdown ( &aoedev->config, rc );
+
+ /* Shut down any active commands */
+ list_for_each_entry_safe ( aoecmd, tmp, &aoe_commands, list ) {
+ if ( aoecmd->aoedev != aoedev )
+ continue;
+ aoecmd_get ( aoecmd );
+ aoecmd_close ( aoecmd, rc );
+ aoecmd_put ( aoecmd );
+ }
+}
+
+/**
+ * Check AoE device flow-control window
+ *
+ * @v aoedev AoE device
+ * @ret len Length of window
+ */
+static size_t aoedev_window ( struct aoe_device *aoedev ) {
+ return ( aoedev->configured ? ~( ( size_t ) 0 ) : 0 );
+}
+
+/**
+ * Handle AoE device configuration completion
+ *
+ * @v aoedev AoE device
+ * @v rc Reason for completion
+ */
+static void aoedev_config_done ( struct aoe_device *aoedev, int rc ) {
+
+ /* Shut down interface */
+ intf_shutdown ( &aoedev->config, rc );
+
+ /* Close device on failure */
+ if ( rc != 0 ) {
+ aoedev_close ( aoedev, rc );
+ return;
+ }
+
+ /* Mark device as configured */
+ aoedev->configured = 1;
+ xfer_window_changed ( &aoedev->ata );
+}
+
+/**
+ * Identify device underlying AoE device
+ *
+ * @v aoedev AoE device
+ * @ret device Underlying device
+ */
+static struct device * aoedev_identify_device ( struct aoe_device *aoedev ) {
+ return aoedev->netdev->dev;
+}
+
+/**
+ * Describe AoE device in an ACPI table
+ *
+ * @v aoedev AoE device
+ * @v acpi ACPI table
+ * @v len Length of ACPI table
+ * @ret rc Return status code
+ */
+static int aoedev_describe ( struct aoe_device *aoedev,
+ struct acpi_description_header *acpi,
+ size_t len ) {
+ struct abft_table *abft =
+ container_of ( acpi, struct abft_table, acpi );
+
+ /* Sanity check */
+ if ( len < sizeof ( *abft ) )
+ return -ENOBUFS;
+
+ /* Populate table */
+ abft->acpi.signature = cpu_to_le32 ( ABFT_SIG );
+ abft->acpi.length = cpu_to_le32 ( sizeof ( *abft ) );
+ abft->acpi.revision = 1;
+ abft->shelf = cpu_to_le16 ( aoedev->major );
+ abft->slot = aoedev->minor;
+ memcpy ( abft->mac, aoedev->netdev->ll_addr, sizeof ( abft->mac ) );
+
+ return 0;
+}
+
+/** AoE device ATA interface operations */
+static struct interface_operation aoedev_ata_op[] = {
+ INTF_OP ( ata_command, struct aoe_device *, aoedev_ata_command ),
+ INTF_OP ( xfer_window, struct aoe_device *, aoedev_window ),
+ INTF_OP ( intf_close, struct aoe_device *, aoedev_close ),
+ INTF_OP ( acpi_describe, struct aoe_device *, aoedev_describe ),
+ INTF_OP ( identify_device, struct aoe_device *,
+ aoedev_identify_device ),
+};
+
+/** AoE device ATA interface descriptor */
+static struct interface_descriptor aoedev_ata_desc =
+ INTF_DESC ( struct aoe_device, ata, aoedev_ata_op );
+
+/** AoE device configuration interface operations */
+static struct interface_operation aoedev_config_op[] = {
+ INTF_OP ( intf_close, struct aoe_device *, aoedev_config_done ),
+};
+
+/** AoE device configuration interface descriptor */
+static struct interface_descriptor aoedev_config_desc =
+ INTF_DESC ( struct aoe_device, config, aoedev_config_op );
+
+/**
+ * Open AoE device
+ *
+ * @v parent Parent interface
+ * @v netdev Network device
+ * @v major Device major number
+ * @v minor Device minor number
+ * @ret rc Return status code
+ */
+static int aoedev_open ( struct interface *parent, struct net_device *netdev,
+ unsigned int major, unsigned int minor ) {
+ struct aoe_device *aoedev;
+ int rc;
+
+ /* Allocate and initialise structure */
+ aoedev = zalloc ( sizeof ( *aoedev ) );
+ if ( ! aoedev ) {
+ rc = -ENOMEM;
+ goto err_zalloc;
+ }
+ ref_init ( &aoedev->refcnt, aoedev_free );
+ intf_init ( &aoedev->ata, &aoedev_ata_desc, &aoedev->refcnt );
+ intf_init ( &aoedev->config, &aoedev_config_desc, &aoedev->refcnt );
+ aoedev->netdev = netdev_get ( netdev );
+ aoedev->major = major;
+ aoedev->minor = minor;
+ memcpy ( aoedev->target, netdev->ll_broadcast,
+ netdev->ll_protocol->ll_addr_len );
+
+ /* Initiate configuration */
+ if ( ( rc = aoedev_cfg_command ( aoedev, &aoedev->config ) ) < 0 ) {
+ DBGC ( aoedev, "AoE %s could not initiate configuration: %s\n",
+ aoedev_name ( aoedev ), strerror ( rc ) );
+ goto err_config;
+ }
+
+ /* Attach ATA device to parent interface */
+ if ( ( rc = ata_open ( parent, &aoedev->ata, ATA_DEV_MASTER,
+ AOE_MAX_COUNT ) ) != 0 ) {
+ DBGC ( aoedev, "AoE %s could not create ATA device: %s\n",
+ aoedev_name ( aoedev ), strerror ( rc ) );
+ goto err_ata_open;
+ }
+
+ /* Mortalise self and return */
+ ref_put ( &aoedev->refcnt );
+ return 0;
+
+ err_ata_open:
+ err_config:
+ aoedev_close ( aoedev, rc );
+ ref_put ( &aoedev->refcnt );
+ err_zalloc:
+ return rc;
+}
+
+/******************************************************************************
+ *
+ * AoE network protocol
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Process incoming AoE packets
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer source address
+ * @v flags Packet flags
+ * @ret rc Return status code
+ */
+static int aoe_rx ( struct io_buffer *iobuf,
+ struct net_device *netdev __unused,
+ const void *ll_dest __unused,
+ const void *ll_source,
+ unsigned int flags __unused ) {
+ struct aoehdr *aoehdr = iobuf->data;
+ struct aoe_command *aoecmd;
+ int rc;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *aoehdr ) ) {
+ DBG ( "AoE received underlength packet (%zd bytes)\n",
+ iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto err_sanity;
+ }
+ if ( ( aoehdr->ver_flags & AOE_VERSION_MASK ) != AOE_VERSION ) {
+ DBG ( "AoE received packet for unsupported protocol version "
+ "%02x\n", ( aoehdr->ver_flags & AOE_VERSION_MASK ) );
+ rc = -EPROTONOSUPPORT;
+ goto err_sanity;
+ }
+ if ( ! ( aoehdr->ver_flags & AOE_FL_RESPONSE ) ) {
+ DBG ( "AoE received request packet\n" );
+ rc = -EOPNOTSUPP;
+ goto err_sanity;
+ }
+
+ /* Demultiplex amongst active AoE commands */
+ aoecmd = aoecmd_find_tag ( ntohl ( aoehdr->tag ) );
+ if ( ! aoecmd ) {
+ DBG ( "AoE received packet for unused tag %08x\n",
+ ntohl ( aoehdr->tag ) );
+ rc = -ENOENT;
+ goto err_demux;
+ }
+
+ /* Pass received frame to command */
+ aoecmd_get ( aoecmd );
+ if ( ( rc = aoecmd_rx ( aoecmd, iob_disown ( iobuf ),
+ ll_source ) ) != 0 )
+ goto err_rx;
+
+ err_rx:
+ aoecmd_put ( aoecmd );
+ err_demux:
+ err_sanity:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** AoE protocol */
+struct net_protocol aoe_protocol __net_protocol = {
+ .name = "AoE",
+ .net_proto = htons ( ETH_P_AOE ),
+ .rx = aoe_rx,
+};
+
+/******************************************************************************
+ *
+ * AoE URIs
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Parse AoE URI
+ *
+ * @v uri URI
+ * @ret major Major device number
+ * @ret minor Minor device number
+ * @ret rc Return status code
+ *
+ * An AoE URI has the form "aoe:e<major>.<minor>".
+ */
+static int aoe_parse_uri ( struct uri *uri, unsigned int *major,
+ unsigned int *minor ) {
+ const char *ptr;
+ char *end;
+
+ /* Check for URI with opaque portion */
+ if ( ! uri->opaque )
+ return -EINVAL;
+ ptr = uri->opaque;
+
+ /* Check for initial 'e' */
+ if ( *ptr != 'e' )
+ return -EINVAL;
+ ptr++;
+
+ /* Parse major device number */
+ *major = strtoul ( ptr, &end, 10 );
+ if ( *end != '.' )
+ return -EINVAL;
+ ptr = ( end + 1 );
+
+ /* Parse minor device number */
+ *minor = strtoul ( ptr, &end, 10 );
+ if ( *end )
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * Open AoE URI
+ *
+ * @v parent Parent interface
+ * @v uri URI
+ * @ret rc Return status code
+ */
+static int aoe_open ( struct interface *parent, struct uri *uri ) {
+ struct net_device *netdev;
+ unsigned int major;
+ unsigned int minor;
+ int rc;
+
+ /* Identify network device. This is something of a hack, but
+ * the AoE URI scheme that has been in use for some time now
+ * provides no way to specify a particular device.
+ */
+ netdev = last_opened_netdev();
+ if ( ! netdev ) {
+ DBG ( "AoE cannot identify network device\n" );
+ return -ENODEV;
+ }
+
+ /* Parse URI */
+ if ( ( rc = aoe_parse_uri ( uri, &major, &minor ) ) != 0 ) {
+ DBG ( "AoE cannot parse URI\n" );
+ return rc;
+ }
+
+ /* Open AoE device */
+ if ( ( rc = aoedev_open ( parent, netdev, major, minor ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/** AoE URI opener */
+struct uri_opener aoe_uri_opener __uri_opener = {
+ .scheme = "aoe",
+ .open = aoe_open,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/arp.c b/src/VBox/Devices/PC/ipxe/src/net/arp.c
new file mode 100644
index 00000000..4283b669
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/arp.c
@@ -0,0 +1,504 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/if_arp.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/list.h>
+#include <ipxe/retry.h>
+#include <ipxe/timer.h>
+#include <ipxe/malloc.h>
+#include <ipxe/arp.h>
+
+/** @file
+ *
+ * Address Resolution Protocol
+ *
+ * This file implements the address resolution protocol as defined in
+ * RFC826. The implementation is media-independent and
+ * protocol-independent; it is not limited to Ethernet or to IPv4.
+ *
+ */
+
+/** ARP minimum timeout */
+#define ARP_MIN_TIMEOUT ( TICKS_PER_SEC / 8 )
+
+/** ARP maximum timeout */
+#define ARP_MAX_TIMEOUT ( TICKS_PER_SEC * 3 )
+
+/** An ARP cache entry */
+struct arp_entry {
+ /** List of ARP cache entries */
+ struct list_head list;
+ /** Network device */
+ struct net_device *netdev;
+ /** Network-layer protocol */
+ struct net_protocol *net_protocol;
+ /** Network-layer destination address */
+ uint8_t net_dest[MAX_NET_ADDR_LEN];
+ /** Network-layer source address */
+ uint8_t net_source[MAX_NET_ADDR_LEN];
+ /** Link-layer destination address */
+ uint8_t ll_dest[MAX_LL_ADDR_LEN];
+ /** Retransmission timer */
+ struct retry_timer timer;
+ /** Pending I/O buffers */
+ struct list_head tx_queue;
+};
+
+/** The ARP cache */
+static LIST_HEAD ( arp_entries );
+
+struct net_protocol arp_protocol __net_protocol;
+
+static void arp_expired ( struct retry_timer *timer, int over );
+
+/**
+ * Create ARP cache entry
+ *
+ * @v netdev Network device
+ * @v net_protocol Network-layer protocol
+ * @v net_dest Destination network-layer address
+ * @v net_source Source network-layer address
+ * @ret arp ARP cache entry, or NULL if allocation failed
+ */
+static struct arp_entry * arp_create ( struct net_device *netdev,
+ struct net_protocol *net_protocol,
+ const void *net_dest,
+ const void *net_source ) {
+ struct arp_entry *arp;
+
+ /* Allocate entry and add to cache */
+ arp = zalloc ( sizeof ( *arp ) );
+ if ( ! arp )
+ return NULL;
+
+ /* Initialise entry and add to cache */
+ arp->netdev = netdev_get ( netdev );
+ arp->net_protocol = net_protocol;
+ memcpy ( arp->net_dest, net_dest,
+ net_protocol->net_addr_len );
+ memcpy ( arp->net_source, net_source,
+ net_protocol->net_addr_len );
+ timer_init ( &arp->timer, arp_expired, NULL );
+ arp->timer.min_timeout = ARP_MIN_TIMEOUT;
+ arp->timer.max_timeout = ARP_MAX_TIMEOUT;
+ INIT_LIST_HEAD ( &arp->tx_queue );
+ list_add ( &arp->list, &arp_entries );
+
+ /* Start timer running to trigger initial transmission */
+ start_timer_nodelay ( &arp->timer );
+
+ DBGC ( arp, "ARP %p %s %s %s created\n", arp, netdev->name,
+ net_protocol->name, net_protocol->ntoa ( net_dest ) );
+ return arp;
+}
+
+/**
+ * Find entry in the ARP cache
+ *
+ * @v netdev Network device
+ * @v net_protocol Network-layer protocol
+ * @v net_dest Destination network-layer address
+ * @ret arp ARP cache entry, or NULL if not found
+ */
+static struct arp_entry * arp_find ( struct net_device *netdev,
+ struct net_protocol *net_protocol,
+ const void *net_dest ) {
+ struct arp_entry *arp;
+
+ list_for_each_entry ( arp, &arp_entries, list ) {
+ if ( ( arp->netdev == netdev ) &&
+ ( arp->net_protocol == net_protocol ) &&
+ ( memcmp ( arp->net_dest, net_dest,
+ net_protocol->net_addr_len ) == 0 ) ) {
+
+ /* Move to start of cache */
+ list_del ( &arp->list );
+ list_add ( &arp->list, &arp_entries );
+
+ return arp;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Destroy ARP cache entry
+ *
+ * @v arp ARP cache entry
+ * @v rc Reason for destruction
+ */
+static void arp_destroy ( struct arp_entry *arp, int rc ) {
+ struct net_device *netdev = arp->netdev;
+ struct net_protocol *net_protocol = arp->net_protocol;
+ struct io_buffer *iobuf;
+ struct io_buffer *tmp;
+
+ /* Stop timer */
+ stop_timer ( &arp->timer );
+
+ /* Discard any outstanding I/O buffers */
+ list_for_each_entry_safe ( iobuf, tmp, &arp->tx_queue, list ) {
+ DBGC2 ( arp, "ARP %p %s %s %s discarding deferred packet: "
+ "%s\n", arp, netdev->name, net_protocol->name,
+ net_protocol->ntoa ( arp->net_dest ), strerror ( rc ) );
+ list_del ( &iobuf->list );
+ netdev_tx_err ( arp->netdev, iobuf, rc );
+ }
+
+ DBGC ( arp, "ARP %p %s %s %s destroyed: %s\n", arp, netdev->name,
+ net_protocol->name, net_protocol->ntoa ( arp->net_dest ),
+ strerror ( rc ) );
+
+ /* Drop reference to network device, remove from cache and free */
+ netdev_put ( arp->netdev );
+ list_del ( &arp->list );
+ free ( arp );
+}
+
+/**
+ * Test if ARP cache entry has a valid link-layer address
+ *
+ * @v arp ARP cache entry
+ * @ret resolved ARP cache entry is resolved
+ */
+static inline int arp_resolved ( struct arp_entry *arp ) {
+ return ( ! timer_running ( &arp->timer ) );
+}
+
+/**
+ * Transmit packet, determining link-layer address via ARP
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v net_protocol Network-layer protocol
+ * @v net_dest Destination network-layer address
+ * @v net_source Source network-layer address
+ * @v ll_source Source link-layer address
+ * @ret rc Return status code
+ */
+int arp_tx ( struct io_buffer *iobuf, struct net_device *netdev,
+ struct net_protocol *net_protocol, const void *net_dest,
+ const void *net_source, const void *ll_source ) {
+ struct arp_entry *arp;
+
+ /* Find or create ARP cache entry */
+ arp = arp_find ( netdev, net_protocol, net_dest );
+ if ( ! arp ) {
+ arp = arp_create ( netdev, net_protocol, net_dest,
+ net_source );
+ if ( ! arp )
+ return -ENOMEM;
+ }
+
+ /* If a link-layer address is available then transmit
+ * immediately, otherwise queue for later transmission.
+ */
+ if ( arp_resolved ( arp ) ) {
+ return net_tx ( iobuf, netdev, net_protocol, arp->ll_dest,
+ ll_source );
+ } else {
+ DBGC2 ( arp, "ARP %p %s %s %s deferring packet\n",
+ arp, netdev->name, net_protocol->name,
+ net_protocol->ntoa ( net_dest ) );
+ list_add_tail ( &iobuf->list, &arp->tx_queue );
+ return -EAGAIN;
+ }
+}
+
+/**
+ * Update ARP cache entry
+ *
+ * @v arp ARP cache entry
+ * @v ll_dest Destination link-layer address
+ */
+static void arp_update ( struct arp_entry *arp, const void *ll_dest ) {
+ struct net_device *netdev = arp->netdev;
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+ struct net_protocol *net_protocol = arp->net_protocol;
+ struct io_buffer *iobuf;
+ struct io_buffer *tmp;
+ int rc;
+
+ DBGC ( arp, "ARP %p %s %s %s updated => %s\n", arp, netdev->name,
+ net_protocol->name, net_protocol->ntoa ( arp->net_dest ),
+ ll_protocol->ntoa ( ll_dest ) );
+
+ /* Fill in link-layer address */
+ memcpy ( arp->ll_dest, ll_dest, ll_protocol->ll_addr_len );
+
+ /* Stop retransmission timer */
+ stop_timer ( &arp->timer );
+
+ /* Transmit any packets in queue */
+ list_for_each_entry_safe ( iobuf, tmp, &arp->tx_queue, list ) {
+ DBGC2 ( arp, "ARP %p %s %s %s transmitting deferred packet\n",
+ arp, netdev->name, net_protocol->name,
+ net_protocol->ntoa ( arp->net_dest ) );
+ list_del ( &iobuf->list );
+ if ( ( rc = net_tx ( iobuf, netdev, net_protocol, ll_dest,
+ netdev->ll_addr ) ) != 0 ) {
+ DBGC ( arp, "ARP %p could not transmit deferred "
+ "packet: %s\n", arp, strerror ( rc ) );
+ /* Ignore error and continue */
+ }
+ }
+}
+
+/**
+ * Handle ARP timer expiry
+ *
+ * @v timer Retry timer
+ * @v fail Failure indicator
+ */
+static void arp_expired ( struct retry_timer *timer, int fail ) {
+ struct arp_entry *arp = container_of ( timer, struct arp_entry, timer );
+ struct net_device *netdev = arp->netdev;
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+ struct net_protocol *net_protocol = arp->net_protocol;
+ struct io_buffer *iobuf;
+ struct arphdr *arphdr;
+ int rc;
+
+ /* If we have failed, destroy the cache entry */
+ if ( fail ) {
+ arp_destroy ( arp, -ETIMEDOUT );
+ return;
+ }
+
+ /* Restart the timer */
+ start_timer ( &arp->timer );
+
+ /* Allocate ARP packet */
+ iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *arphdr ) +
+ ( 2 * ( MAX_LL_ADDR_LEN + MAX_NET_ADDR_LEN ) ) );
+ if ( ! iobuf ) {
+ /* Leave timer running and try again later */
+ return;
+ }
+ iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
+
+ /* Build up ARP request */
+ arphdr = iob_put ( iobuf, sizeof ( *arphdr ) );
+ arphdr->ar_hrd = ll_protocol->ll_proto;
+ arphdr->ar_hln = ll_protocol->ll_addr_len;
+ arphdr->ar_pro = net_protocol->net_proto;
+ arphdr->ar_pln = net_protocol->net_addr_len;
+ arphdr->ar_op = htons ( ARPOP_REQUEST );
+ memcpy ( iob_put ( iobuf, ll_protocol->ll_addr_len ),
+ netdev->ll_addr, ll_protocol->ll_addr_len );
+ memcpy ( iob_put ( iobuf, net_protocol->net_addr_len ),
+ arp->net_source, net_protocol->net_addr_len );
+ memset ( iob_put ( iobuf, ll_protocol->ll_addr_len ),
+ 0, ll_protocol->ll_addr_len );
+ memcpy ( iob_put ( iobuf, net_protocol->net_addr_len ),
+ arp->net_dest, net_protocol->net_addr_len );
+
+ /* Transmit ARP request */
+ if ( ( rc = net_tx ( iobuf, netdev, &arp_protocol,
+ netdev->ll_broadcast, netdev->ll_addr ) ) != 0 ) {
+ DBGC ( arp, "ARP %p could not transmit request: %s\n",
+ arp, strerror ( rc ) );
+ return;
+ }
+}
+
+/**
+ * Identify ARP protocol
+ *
+ * @v net_proto Network-layer protocol, in network-endian order
+ * @ret arp_net_protocol ARP protocol, or NULL
+ *
+ */
+static struct arp_net_protocol * arp_find_protocol ( uint16_t net_proto ) {
+ struct arp_net_protocol *arp_net_protocol;
+
+ for_each_table_entry ( arp_net_protocol, ARP_NET_PROTOCOLS ) {
+ if ( arp_net_protocol->net_protocol->net_proto == net_proto ) {
+ return arp_net_protocol;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Process incoming ARP packets
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_source Link-layer source address
+ * @v flags Packet flags
+ * @ret rc Return status code
+ */
+static int arp_rx ( struct io_buffer *iobuf, struct net_device *netdev,
+ const void *ll_dest __unused,
+ const void *ll_source __unused,
+ unsigned int flags __unused ) {
+ struct arphdr *arphdr = iobuf->data;
+ struct arp_net_protocol *arp_net_protocol;
+ struct net_protocol *net_protocol;
+ struct ll_protocol *ll_protocol;
+ struct arp_entry *arp;
+ int rc;
+
+ /* Identify network-layer and link-layer protocols */
+ arp_net_protocol = arp_find_protocol ( arphdr->ar_pro );
+ if ( ! arp_net_protocol ) {
+ rc = -EPROTONOSUPPORT;
+ goto done;
+ }
+ net_protocol = arp_net_protocol->net_protocol;
+ ll_protocol = netdev->ll_protocol;
+
+ /* Sanity checks */
+ if ( ( arphdr->ar_hrd != ll_protocol->ll_proto ) ||
+ ( arphdr->ar_hln != ll_protocol->ll_addr_len ) ||
+ ( arphdr->ar_pln != net_protocol->net_addr_len ) ) {
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* See if we have an entry for this sender, and update it if so */
+ arp = arp_find ( netdev, net_protocol, arp_sender_pa ( arphdr ) );
+ if ( arp ) {
+ arp_update ( arp, arp_sender_ha ( arphdr ) );
+ }
+
+ /* If it's not a request, there's nothing more to do */
+ if ( arphdr->ar_op != htons ( ARPOP_REQUEST ) ) {
+ rc = 0;
+ goto done;
+ }
+
+ /* See if we own the target protocol address */
+ if ( arp_net_protocol->check ( netdev, arp_target_pa ( arphdr ) ) != 0){
+ rc = 0;
+ goto done;
+ }
+
+ /* Change request to a reply */
+ DBGC ( netdev, "ARP reply %s %s %s => %s %s\n",
+ netdev->name, net_protocol->name,
+ net_protocol->ntoa ( arp_target_pa ( arphdr ) ),
+ ll_protocol->name, ll_protocol->ntoa ( netdev->ll_addr ) );
+ arphdr->ar_op = htons ( ARPOP_REPLY );
+ memswap ( arp_sender_ha ( arphdr ), arp_target_ha ( arphdr ),
+ arphdr->ar_hln + arphdr->ar_pln );
+ memcpy ( arp_sender_ha ( arphdr ), netdev->ll_addr, arphdr->ar_hln );
+
+ /* Send reply */
+ if ( ( rc = net_tx ( iob_disown ( iobuf ), netdev, &arp_protocol,
+ arp_target_ha ( arphdr ),
+ netdev->ll_addr ) ) != 0 ) {
+ DBGC ( netdev, "ARP could not transmit reply via %s: %s\n",
+ netdev->name, strerror ( rc ) );
+ goto done;
+ }
+
+ /* Success */
+ rc = 0;
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Transcribe ARP address
+ *
+ * @v net_addr ARP address
+ * @ret string "<ARP>"
+ *
+ * This operation is meaningless for the ARP protocol.
+ */
+static const char * arp_ntoa ( const void *net_addr __unused ) {
+ return "<ARP>";
+}
+
+/** ARP protocol */
+struct net_protocol arp_protocol __net_protocol = {
+ .name = "ARP",
+ .net_proto = htons ( ETH_P_ARP ),
+ .rx = arp_rx,
+ .ntoa = arp_ntoa,
+};
+
+/**
+ * Update ARP cache on network device creation
+ *
+ * @v netdev Network device
+ */
+static int arp_probe ( struct net_device *netdev __unused ) {
+ /* Nothing to do */
+ return 0;
+}
+
+/**
+ * Update ARP cache on network device state change or removal
+ *
+ * @v netdev Network device
+ */
+static void arp_flush ( struct net_device *netdev ) {
+ struct arp_entry *arp;
+ struct arp_entry *tmp;
+
+ /* Remove all ARP cache entries when a network device is closed */
+ if ( ! netdev_is_open ( netdev ) ) {
+ list_for_each_entry_safe ( arp, tmp, &arp_entries, list )
+ arp_destroy ( arp, -ENODEV );
+ }
+}
+
+/** ARP driver (for net device notifications) */
+struct net_driver arp_net_driver __net_driver = {
+ .name = "ARP",
+ .probe = arp_probe,
+ .notify = arp_flush,
+ .remove = arp_flush,
+};
+
+/**
+ * Discard some cached ARP entries
+ *
+ * @ret discarded Number of cached items discarded
+ */
+static unsigned int arp_discard ( void ) {
+ struct arp_entry *arp;
+
+ /* Drop oldest cache entry, if any */
+ list_for_each_entry_reverse ( arp, &arp_entries, list ) {
+ arp_destroy ( arp, -ENOBUFS );
+ return 1;
+ }
+
+ return 0;
+}
+
+/** ARP cache discarder */
+struct cache_discarder arp_cache_discarder __cache_discarder = {
+ .discard = arp_discard,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/cachedhcp.c b/src/VBox/Devices/PC/ipxe/src/net/cachedhcp.c
new file mode 100644
index 00000000..36f480a9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/cachedhcp.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/dhcppkt.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/uaccess.h>
+
+/** @file
+ *
+ * Cached DHCP packet handling
+ *
+ */
+
+/**
+ * Store cached DHCPACK packet
+ *
+ * @v data User pointer to cached DHCP packet data
+ * @v len Length of cached DHCP packet data
+ * @ret rc Return status code
+ *
+ * This function should be called by the architecture-specific
+ * get_cached_dhcpack() handler.
+ */
+void store_cached_dhcpack ( userptr_t data, size_t len ) {
+ struct dhcp_packet *dhcppkt;
+ struct dhcphdr *dhcphdr;
+ struct settings *parent;
+ int rc;
+
+ /* Create DHCP packet */
+ dhcppkt = zalloc ( sizeof ( *dhcppkt ) + len );
+ if ( ! dhcppkt )
+ return;
+
+ /* Fill in data for DHCP packet */
+ dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( * dhcppkt ) );
+ copy_from_user ( dhcphdr, data, 0, len );
+ dhcppkt_init ( dhcppkt, dhcphdr, len );
+ DBG_HD ( dhcppkt->options.data, dhcppkt->options.used_len );
+
+ /* Register settings on the last opened network device.
+ * This will have the effect of registering cached settings
+ * with a network device when "dhcp netX" is performed for that
+ * device, which is usually what we want.
+ */
+ parent = netdev_settings ( last_opened_netdev() );
+ if ( ( rc = register_settings ( &dhcppkt->settings, parent,
+ DHCP_SETTINGS_NAME ) ) != 0 )
+ DBG ( "DHCP could not register cached settings: %s\n",
+ strerror ( rc ) );
+
+ dhcppkt_put ( dhcppkt );
+
+ DBG ( "DHCP registered cached settings\n" );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/dhcpopts.c b/src/VBox/Devices/PC/ipxe/src/net/dhcpopts.c
new file mode 100644
index 00000000..249fde15
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/dhcpopts.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/dhcpopts.h>
+
+/** @file
+ *
+ * DHCP options
+ *
+ */
+
+/**
+ * Obtain printable version of a DHCP option tag
+ *
+ * @v tag DHCP option tag
+ * @ret name String representation of the tag
+ *
+ */
+static inline char * dhcp_tag_name ( unsigned int tag ) {
+ static char name[8];
+
+ if ( DHCP_IS_ENCAP_OPT ( tag ) ) {
+ snprintf ( name, sizeof ( name ), "%d.%d",
+ DHCP_ENCAPSULATOR ( tag ),
+ DHCP_ENCAPSULATED ( tag ) );
+ } else {
+ snprintf ( name, sizeof ( name ), "%d", tag );
+ }
+ return name;
+}
+
+/**
+ * Get pointer to DHCP option
+ *
+ * @v options DHCP options block
+ * @v offset Offset within options block
+ * @ret option DHCP option
+ */
+static inline __attribute__ (( always_inline )) struct dhcp_option *
+dhcp_option ( struct dhcp_options *options, unsigned int offset ) {
+ return ( ( struct dhcp_option * ) ( options->data + offset ) );
+}
+
+/**
+ * Get offset of a DHCP option
+ *
+ * @v options DHCP options block
+ * @v option DHCP option
+ * @ret offset Offset within options block
+ */
+static inline __attribute__ (( always_inline )) int
+dhcp_option_offset ( struct dhcp_options *options,
+ struct dhcp_option *option ) {
+ return ( ( ( void * ) option ) - options->data );
+}
+
+/**
+ * Calculate length of any DHCP option
+ *
+ * @v option DHCP option
+ * @ret len Length (including tag and length field)
+ */
+static unsigned int dhcp_option_len ( struct dhcp_option *option ) {
+ if ( ( option->tag == DHCP_END ) || ( option->tag == DHCP_PAD ) ) {
+ return 1;
+ } else {
+ return ( option->len + DHCP_OPTION_HEADER_LEN );
+ }
+}
+
+/**
+ * Find DHCP option within DHCP options block, and its encapsulator (if any)
+ *
+ * @v options DHCP options block
+ * @v tag DHCP option tag to search for
+ * @ret encap_offset Offset of encapsulating DHCP option
+ * @ret offset Offset of DHCP option, or negative error
+ *
+ * Searches for the DHCP option matching the specified tag within the
+ * DHCP option block. Encapsulated options may be searched for by
+ * using DHCP_ENCAP_OPT() to construct the tag value.
+ *
+ * If the option is encapsulated, and @c encap_offset is non-NULL, it
+ * will be filled in with the offset of the encapsulating option.
+ *
+ * This routine is designed to be paranoid. It does not assume that
+ * the option data is well-formatted, and so must guard against flaws
+ * such as options missing a @c DHCP_END terminator, or options whose
+ * length would take them beyond the end of the data block.
+ */
+static int find_dhcp_option_with_encap ( struct dhcp_options *options,
+ unsigned int tag,
+ int *encap_offset ) {
+ unsigned int original_tag __attribute__ (( unused )) = tag;
+ struct dhcp_option *option;
+ int offset = 0;
+ ssize_t remaining = options->used_len;
+ unsigned int option_len;
+
+ /* Sanity check */
+ if ( tag == DHCP_PAD )
+ return -ENOENT;
+
+ /* Search for option */
+ while ( remaining ) {
+ /* Calculate length of this option. Abort processing
+ * if the length is malformed (i.e. takes us beyond
+ * the end of the data block).
+ */
+ option = dhcp_option ( options, offset );
+ option_len = dhcp_option_len ( option );
+ remaining -= option_len;
+ if ( remaining < 0 )
+ break;
+ /* Check for explicit end marker */
+ if ( option->tag == DHCP_END ) {
+ if ( tag == DHCP_END )
+ /* Special case where the caller is interested
+ * in whether we have this marker or not.
+ */
+ return offset;
+ else
+ break;
+ }
+ /* Check for matching tag */
+ if ( option->tag == tag ) {
+ DBGC ( options, "DHCPOPT %p found %s (length %d)\n",
+ options, dhcp_tag_name ( original_tag ),
+ option_len );
+ return offset;
+ }
+ /* Check for start of matching encapsulation block */
+ if ( DHCP_IS_ENCAP_OPT ( tag ) &&
+ ( option->tag == DHCP_ENCAPSULATOR ( tag ) ) ) {
+ if ( encap_offset )
+ *encap_offset = offset;
+ /* Continue search within encapsulated option block */
+ tag = DHCP_ENCAPSULATED ( tag );
+ remaining = option_len;
+ offset += DHCP_OPTION_HEADER_LEN;
+ continue;
+ }
+ offset += option_len;
+ }
+
+ return -ENOENT;
+}
+
+/**
+ * Refuse to reallocate DHCP option block
+ *
+ * @v options DHCP option block
+ * @v len New length
+ * @ret rc Return status code
+ */
+int dhcpopt_no_realloc ( struct dhcp_options *options, size_t len ) {
+ return ( ( len <= options->alloc_len ) ? 0 : -ENOSPC );
+}
+
+/**
+ * Resize a DHCP option
+ *
+ * @v options DHCP option block
+ * @v offset Offset of option to resize
+ * @v encap_offset Offset of encapsulating offset (or -ve for none)
+ * @v old_len Old length (including header)
+ * @v new_len New length (including header)
+ * @ret rc Return status code
+ */
+static int resize_dhcp_option ( struct dhcp_options *options,
+ int offset, int encap_offset,
+ size_t old_len, size_t new_len ) {
+ struct dhcp_option *encapsulator;
+ struct dhcp_option *option;
+ ssize_t delta = ( new_len - old_len );
+ size_t old_alloc_len;
+ size_t new_used_len;
+ size_t new_encapsulator_len;
+ void *source;
+ void *dest;
+ void *end;
+ int rc;
+
+ /* Check for sufficient space */
+ if ( new_len > DHCP_MAX_LEN ) {
+ DBGC ( options, "DHCPOPT %p overlength option\n", options );
+ return -ENOSPC;
+ }
+ new_used_len = ( options->used_len + delta );
+
+ /* Expand options block, if necessary */
+ if ( new_used_len > options->alloc_len ) {
+ /* Reallocate options block */
+ old_alloc_len = options->alloc_len;
+ if ( ( rc = options->realloc ( options, new_used_len ) ) != 0 ){
+ DBGC ( options, "DHCPOPT %p could not reallocate to "
+ "%zd bytes\n", options, new_used_len );
+ return rc;
+ }
+ /* Clear newly allocated space */
+ memset ( ( options->data + old_alloc_len ), 0,
+ ( options->alloc_len - old_alloc_len ) );
+ }
+
+ /* Update encapsulator, if applicable */
+ if ( encap_offset >= 0 ) {
+ encapsulator = dhcp_option ( options, encap_offset );
+ new_encapsulator_len = ( encapsulator->len + delta );
+ if ( new_encapsulator_len > DHCP_MAX_LEN ) {
+ DBGC ( options, "DHCPOPT %p overlength encapsulator\n",
+ options );
+ return -ENOSPC;
+ }
+ encapsulator->len = new_encapsulator_len;
+ }
+
+ /* Update used length */
+ options->used_len = new_used_len;
+
+ /* Move remainder of option data */
+ option = dhcp_option ( options, offset );
+ source = ( ( ( void * ) option ) + old_len );
+ dest = ( ( ( void * ) option ) + new_len );
+ end = ( options->data + options->alloc_len );
+ memmove ( dest, source, ( end - dest ) );
+
+ /* Shrink options block, if applicable */
+ if ( new_used_len < options->alloc_len ) {
+ if ( ( rc = options->realloc ( options, new_used_len ) ) != 0 ){
+ DBGC ( options, "DHCPOPT %p could not reallocate to "
+ "%zd bytes\n", options, new_used_len );
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Set value of DHCP option
+ *
+ * @v options DHCP option block
+ * @v tag DHCP option tag
+ * @v data New value for DHCP option
+ * @v len Length of value, in bytes
+ * @ret offset Offset of DHCP option, or negative error
+ *
+ * Sets the value of a DHCP option within the options block. The
+ * option may or may not already exist. Encapsulators will be created
+ * (and deleted) as necessary.
+ *
+ * This call may fail due to insufficient space in the options block.
+ * If it does fail, and the option existed previously, the option will
+ * be left with its original value.
+ */
+static int set_dhcp_option ( struct dhcp_options *options, unsigned int tag,
+ const void *data, size_t len ) {
+ static const uint8_t empty_encap[] = { DHCP_END };
+ int offset;
+ int encap_offset = -1;
+ int creation_offset;
+ struct dhcp_option *option;
+ unsigned int encap_tag = DHCP_ENCAPSULATOR ( tag );
+ size_t old_len = 0;
+ size_t new_len = ( len ? ( len + DHCP_OPTION_HEADER_LEN ) : 0 );
+ int rc;
+
+ /* Sanity check */
+ if ( tag == DHCP_PAD )
+ return -ENOTTY;
+
+ creation_offset = find_dhcp_option_with_encap ( options, DHCP_END,
+ NULL );
+ if ( creation_offset < 0 )
+ creation_offset = options->used_len;
+ /* Find old instance of this option, if any */
+ offset = find_dhcp_option_with_encap ( options, tag, &encap_offset );
+ if ( offset >= 0 ) {
+ old_len = dhcp_option_len ( dhcp_option ( options, offset ) );
+ DBGC ( options, "DHCPOPT %p resizing %s from %zd to %zd\n",
+ options, dhcp_tag_name ( tag ), old_len, new_len );
+ } else {
+ DBGC ( options, "DHCPOPT %p creating %s (length %zd)\n",
+ options, dhcp_tag_name ( tag ), new_len );
+ }
+
+ /* Ensure that encapsulator exists, if required */
+ if ( encap_tag ) {
+ if ( encap_offset < 0 ) {
+ encap_offset =
+ set_dhcp_option ( options, encap_tag,
+ empty_encap,
+ sizeof ( empty_encap ) );
+ }
+ if ( encap_offset < 0 )
+ return encap_offset;
+ creation_offset = ( encap_offset + DHCP_OPTION_HEADER_LEN );
+ }
+
+ /* Create new option if necessary */
+ if ( offset < 0 )
+ offset = creation_offset;
+
+ /* Resize option to fit new data */
+ if ( ( rc = resize_dhcp_option ( options, offset, encap_offset,
+ old_len, new_len ) ) != 0 )
+ return rc;
+
+ /* Copy new data into option, if applicable */
+ if ( len ) {
+ option = dhcp_option ( options, offset );
+ option->tag = tag;
+ option->len = len;
+ memcpy ( &option->data, data, len );
+ }
+
+ /* Delete encapsulator if there's nothing else left in it */
+ if ( encap_offset >= 0 ) {
+ option = dhcp_option ( options, encap_offset );
+ if ( option->len <= 1 )
+ set_dhcp_option ( options, encap_tag, NULL, 0 );
+ }
+
+ return offset;
+}
+
+/**
+ * Check applicability of DHCP option setting
+ *
+ * @v tag Setting tag number
+ * @ret applies Setting applies to this option block
+ */
+int dhcpopt_applies ( unsigned int tag ) {
+
+ return ( tag && ( tag <= DHCP_ENCAP_OPT ( DHCP_MAX_OPTION,
+ DHCP_MAX_OPTION ) ) );
+}
+
+/**
+ * Store value of DHCP option setting
+ *
+ * @v options DHCP option block
+ * @v tag Setting tag number
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+int dhcpopt_store ( struct dhcp_options *options, unsigned int tag,
+ const void *data, size_t len ) {
+ int offset;
+
+ offset = set_dhcp_option ( options, tag, data, len );
+ if ( offset < 0 )
+ return offset;
+ return 0;
+}
+
+/**
+ * Fetch value of DHCP option setting
+ *
+ * @v options DHCP option block
+ * @v tag Setting tag number
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+int dhcpopt_fetch ( struct dhcp_options *options, unsigned int tag,
+ void *data, size_t len ) {
+ int offset;
+ struct dhcp_option *option;
+ size_t option_len;
+
+ offset = find_dhcp_option_with_encap ( options, tag, NULL );
+ if ( offset < 0 )
+ return offset;
+
+ option = dhcp_option ( options, offset );
+ option_len = option->len;
+ if ( len > option_len )
+ len = option_len;
+ memcpy ( data, option->data, len );
+
+ return option_len;
+}
+
+/**
+ * Recalculate length of DHCP options block
+ *
+ * @v options Uninitialised DHCP option block
+ *
+ * The "used length" field will be updated based on scanning through
+ * the block to find the end of the options.
+ */
+void dhcpopt_update_used_len ( struct dhcp_options *options ) {
+ struct dhcp_option *option;
+ int offset = 0;
+ ssize_t remaining = options->alloc_len;
+ unsigned int option_len;
+
+ /* Find last non-pad option */
+ options->used_len = 0;
+ while ( remaining ) {
+ option = dhcp_option ( options, offset );
+ option_len = dhcp_option_len ( option );
+ remaining -= option_len;
+ if ( remaining < 0 )
+ break;
+ offset += option_len;
+ if ( option->tag != DHCP_PAD )
+ options->used_len = offset;
+ }
+}
+
+/**
+ * Initialise prepopulated block of DHCP options
+ *
+ * @v options Uninitialised DHCP option block
+ * @v data Memory for DHCP option data
+ * @v alloc_len Length of memory for DHCP option data
+ * @v realloc DHCP option block reallocator
+ *
+ * The memory content must already be filled with valid DHCP options.
+ * A zeroed block counts as a block of valid DHCP options.
+ */
+void dhcpopt_init ( struct dhcp_options *options, void *data, size_t alloc_len,
+ int ( * realloc ) ( struct dhcp_options *options,
+ size_t len ) ) {
+
+ /* Fill in fields */
+ options->data = data;
+ options->alloc_len = alloc_len;
+ options->realloc = realloc;
+
+ /* Update length */
+ dhcpopt_update_used_len ( options );
+
+ DBGC ( options, "DHCPOPT %p created (data %p lengths %#zx,%#zx)\n",
+ options, options->data, options->used_len, options->alloc_len );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/dhcppkt.c b/src/VBox/Devices/PC/ipxe/src/net/dhcppkt.c
new file mode 100644
index 00000000..0a0e458f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/dhcppkt.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/dhcpopts.h>
+#include <ipxe/dhcppkt.h>
+
+/** @file
+ *
+ * DHCP packets
+ *
+ */
+
+/****************************************************************************
+ *
+ * DHCP packet raw interface
+ *
+ */
+
+/**
+ * Calculate used length of an IPv4 field within a DHCP packet
+ *
+ * @v data Field data
+ * @v len Length of field
+ * @ret used Used length of field
+ */
+static size_t used_len_ipv4 ( const void *data, size_t len __unused ) {
+ const struct in_addr *in = data;
+
+ return ( in->s_addr ? sizeof ( *in ) : 0 );
+}
+
+/**
+ * Calculate used length of a string field within a DHCP packet
+ *
+ * @v data Field data
+ * @v len Length of field
+ * @ret used Used length of field
+ */
+static size_t used_len_string ( const void *data, size_t len ) {
+ return strnlen ( data, len );
+}
+
+/** A dedicated field within a DHCP packet */
+struct dhcp_packet_field {
+ /** Settings tag number */
+ unsigned int tag;
+ /** Offset within DHCP packet */
+ uint16_t offset;
+ /** Length of field */
+ uint16_t len;
+ /** Calculate used length of field
+ *
+ * @v data Field data
+ * @v len Length of field
+ * @ret used Used length of field
+ */
+ size_t ( * used_len ) ( const void *data, size_t len );
+};
+
+/** Declare a dedicated field within a DHCP packet
+ *
+ * @v _tag Settings tag number
+ * @v _field Field name
+ * @v _used_len Function to calculate used length of field
+ */
+#define DHCP_PACKET_FIELD( _tag, _field, _used_len ) { \
+ .tag = (_tag), \
+ .offset = offsetof ( struct dhcphdr, _field ), \
+ .len = sizeof ( ( ( struct dhcphdr * ) 0 )->_field ), \
+ .used_len = _used_len, \
+ }
+
+/** Dedicated fields within a DHCP packet */
+static struct dhcp_packet_field dhcp_packet_fields[] = {
+ DHCP_PACKET_FIELD ( DHCP_EB_YIADDR, yiaddr, used_len_ipv4 ),
+ DHCP_PACKET_FIELD ( DHCP_EB_SIADDR, siaddr, used_len_ipv4 ),
+ DHCP_PACKET_FIELD ( DHCP_TFTP_SERVER_NAME, sname, used_len_string ),
+ DHCP_PACKET_FIELD ( DHCP_BOOTFILE_NAME, file, used_len_string ),
+};
+
+/**
+ * Get address of a DHCP packet field
+ *
+ * @v dhcphdr DHCP packet header
+ * @v field DHCP packet field
+ * @ret data Packet field data
+ */
+static inline void * dhcp_packet_field ( struct dhcphdr *dhcphdr,
+ struct dhcp_packet_field *field ) {
+ return ( ( ( void * ) dhcphdr ) + field->offset );
+}
+
+/**
+ * Find DHCP packet field corresponding to settings tag number
+ *
+ * @v tag Settings tag number
+ * @ret field DHCP packet field, or NULL
+ */
+static struct dhcp_packet_field *
+find_dhcp_packet_field ( unsigned int tag ) {
+ struct dhcp_packet_field *field;
+ unsigned int i;
+
+ for ( i = 0 ; i < ( sizeof ( dhcp_packet_fields ) /
+ sizeof ( dhcp_packet_fields[0] ) ) ; i++ ) {
+ field = &dhcp_packet_fields[i];
+ if ( field->tag == tag )
+ return field;
+ }
+ return NULL;
+}
+
+/**
+ * Check applicability of DHCP setting
+ *
+ * @v dhcppkt DHCP packet
+ * @v tag Setting tag number
+ * @ret applies Setting applies within this settings block
+ */
+static int dhcppkt_applies ( struct dhcp_packet *dhcppkt __unused,
+ unsigned int tag ) {
+
+ return dhcpopt_applies ( tag );
+}
+
+/**
+ * Store value of DHCP packet setting
+ *
+ * @v dhcppkt DHCP packet
+ * @v tag Setting tag number
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+int dhcppkt_store ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ const void *data, size_t len ) {
+ struct dhcp_packet_field *field;
+ void *field_data;
+
+ /* If this is a special field, fill it in */
+ if ( ( field = find_dhcp_packet_field ( tag ) ) != NULL ) {
+ if ( len > field->len )
+ return -ENOSPC;
+ field_data = dhcp_packet_field ( dhcppkt->dhcphdr, field );
+ memset ( field_data, 0, field->len );
+ memcpy ( dhcp_packet_field ( dhcppkt->dhcphdr, field ),
+ data, len );
+ /* Erase any equivalent option from the options block */
+ dhcpopt_store ( &dhcppkt->options, tag, NULL, 0 );
+ return 0;
+ }
+
+ /* Otherwise, use the generic options block */
+ return dhcpopt_store ( &dhcppkt->options, tag, data, len );
+}
+
+/**
+ * Fetch value of DHCP packet setting
+ *
+ * @v dhcppkt DHCP packet
+ * @v tag Setting tag number
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+int dhcppkt_fetch ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ void *data, size_t len ) {
+ struct dhcp_packet_field *field;
+ void *field_data;
+ size_t field_len = 0;
+
+ /* Identify special field, if any */
+ if ( ( field = find_dhcp_packet_field ( tag ) ) != NULL ) {
+ field_data = dhcp_packet_field ( dhcppkt->dhcphdr, field );
+ field_len = field->used_len ( field_data, field->len );
+ }
+
+ /* Return special field, if it exists and is populated */
+ if ( field_len ) {
+ if ( len > field_len )
+ len = field_len;
+ memcpy ( data, field_data, len );
+ return field_len;
+ }
+
+ /* Otherwise, use the generic options block */
+ return dhcpopt_fetch ( &dhcppkt->options, tag, data, len );
+}
+
+/****************************************************************************
+ *
+ * DHCP packet settings interface
+ *
+ */
+
+/**
+ * Check applicability of DHCP setting
+ *
+ * @v settings Settings block
+ * @v setting Setting
+ * @ret applies Setting applies within this settings block
+ */
+static int dhcppkt_settings_applies ( struct settings *settings,
+ struct setting *setting ) {
+ struct dhcp_packet *dhcppkt =
+ container_of ( settings, struct dhcp_packet, settings );
+
+ return dhcppkt_applies ( dhcppkt, setting->tag );
+}
+
+/**
+ * Store value of DHCP setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+static int dhcppkt_settings_store ( struct settings *settings,
+ struct setting *setting,
+ const void *data, size_t len ) {
+ struct dhcp_packet *dhcppkt =
+ container_of ( settings, struct dhcp_packet, settings );
+
+ return dhcppkt_store ( dhcppkt, setting->tag, data, len );
+}
+
+/**
+ * Fetch value of DHCP setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+static int dhcppkt_settings_fetch ( struct settings *settings,
+ struct setting *setting,
+ void *data, size_t len ) {
+ struct dhcp_packet *dhcppkt =
+ container_of ( settings, struct dhcp_packet, settings );
+
+ return dhcppkt_fetch ( dhcppkt, setting->tag, data, len );
+}
+
+/** DHCP settings operations */
+static struct settings_operations dhcppkt_settings_operations = {
+ .applies = dhcppkt_settings_applies,
+ .store = dhcppkt_settings_store,
+ .fetch = dhcppkt_settings_fetch,
+};
+
+/****************************************************************************
+ *
+ * Constructor
+ *
+ */
+
+/**
+ * Initialise DHCP packet
+ *
+ * @v dhcppkt DHCP packet structure to fill in
+ * @v data DHCP packet raw data
+ * @v max_len Length of raw data buffer
+ *
+ * Initialise a DHCP packet structure from a data buffer containing a
+ * DHCP packet.
+ */
+void dhcppkt_init ( struct dhcp_packet *dhcppkt, struct dhcphdr *data,
+ size_t len ) {
+ ref_init ( &dhcppkt->refcnt, NULL );
+ dhcppkt->dhcphdr = data;
+ dhcpopt_init ( &dhcppkt->options, &dhcppkt->dhcphdr->options,
+ ( len - offsetof ( struct dhcphdr, options ) ),
+ dhcpopt_no_realloc );
+ settings_init ( &dhcppkt->settings,
+ &dhcppkt_settings_operations, &dhcppkt->refcnt, 0 );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/eapol.c b/src/VBox/Devices/PC/ipxe/src/net/eapol.c
new file mode 100644
index 00000000..dd042083
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/eapol.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * 802.1X Extensible Authentication Protocol over LANs demultiplexer
+ *
+ */
+
+#include <ipxe/netdevice.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/eapol.h>
+#include <errno.h>
+#include <byteswap.h>
+
+/**
+ * Receive EAPOL network-layer packet
+ *
+ * @v iob I/O buffer
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer source address
+ * @v flags Packet flags
+ *
+ * This function takes ownership of the I/O buffer passed to it.
+ */
+static int eapol_rx ( struct io_buffer *iob, struct net_device *netdev,
+ const void *ll_dest, const void *ll_source,
+ unsigned int flags __unused ) {
+ struct eapol_frame *eapol = iob->data;
+ struct eapol_handler *handler;
+
+ if ( iob_len ( iob ) < EAPOL_HDR_LEN ) {
+ free_iob ( iob );
+ return -EINVAL;
+ }
+
+ for_each_table_entry ( handler, EAPOL_HANDLERS ) {
+ if ( handler->type == eapol->type ) {
+ iob_pull ( iob, EAPOL_HDR_LEN );
+ return handler->rx ( iob, netdev, ll_dest, ll_source );
+ }
+ }
+
+ free_iob ( iob );
+ return -( ENOTSUP | ( ( eapol->type & 0x1f ) << 8 ) );
+}
+
+/**
+ * Transcribe EAPOL network-layer address
+ *
+ * @v net_addr Network-layer address
+ * @ret str String representation of network-layer address
+ *
+ * EAPOL doesn't have network-layer addresses, so we just return the
+ * string @c "<EAPOL>".
+ */
+static const char * eapol_ntoa ( const void *net_addr __unused )
+{
+ return "<EAPOL>";
+}
+
+/** EAPOL network protocol */
+struct net_protocol eapol_protocol __net_protocol = {
+ .name = "EAPOL",
+ .rx = eapol_rx,
+ .ntoa = eapol_ntoa,
+ .net_proto = htons ( ETH_P_EAPOL ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/eth_slow.c b/src/VBox/Devices/PC/ipxe/src/net/eth_slow.c
new file mode 100644
index 00000000..593e45bc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/eth_slow.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/eth_slow.h>
+
+/** @file
+ *
+ * Ethernet slow protocols
+ *
+ * We implement a very simple passive LACP entity, that pretends that
+ * each port is the only port on an individual system. We avoid the
+ * need for timeout logic (and retaining local state about our
+ * partner) by requesting the same timeout period (1s or 30s) as our
+ * partner requests, and then simply responding to every packet the
+ * partner sends us.
+ */
+
+struct net_protocol eth_slow_protocol __net_protocol;
+
+/** Slow protocols multicast address */
+static const uint8_t eth_slow_address[ETH_ALEN] =
+ { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 };
+
+/**
+ * Name LACP TLV type
+ *
+ * @v type LACP TLV type
+ * @ret name Name of LACP TLV type
+ */
+static inline __attribute__ (( always_inline )) const char *
+eth_slow_lacp_tlv_name ( uint8_t type ) {
+ switch ( type ) {
+ case ETH_SLOW_TLV_TERMINATOR: return "terminator";
+ case ETH_SLOW_TLV_LACP_ACTOR: return "actor";
+ case ETH_SLOW_TLV_LACP_PARTNER: return "partner";
+ case ETH_SLOW_TLV_LACP_COLLECTOR: return "collector";
+ default: return "<invalid>";
+ }
+}
+
+/**
+ * Name marker TLV type
+ *
+ * @v type Marker TLV type
+ * @ret name Name of marker TLV type
+ */
+static inline __attribute__ (( always_inline )) const char *
+eth_slow_marker_tlv_name ( uint8_t type ) {
+ switch ( type ) {
+ case ETH_SLOW_TLV_TERMINATOR: return "terminator";
+ case ETH_SLOW_TLV_MARKER_REQUEST: return "request";
+ case ETH_SLOW_TLV_MARKER_RESPONSE: return "response";
+ default: return "<invalid>";
+ }
+}
+
+/**
+ * Name LACP state
+ *
+ * @v state LACP state
+ * @ret name LACP state name
+ */
+static const char * eth_slow_lacp_state_name ( uint8_t state ) {
+ static char state_chars[] = "AFGSRTLX";
+ unsigned int i;
+
+ for ( i = 0 ; i < 8 ; i++ ) {
+ state_chars[i] |= 0x20;
+ if ( state & ( 1 << i ) )
+ state_chars[i] &= ~0x20;
+ }
+ return state_chars;
+}
+
+/**
+ * Dump LACP packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v label "RX" or "TX"
+ */
+static void eth_slow_lacp_dump ( struct io_buffer *iobuf,
+ struct net_device *netdev,
+ const char *label ) {
+ union eth_slow_packet *eth_slow = iobuf->data;
+ struct eth_slow_lacp *lacp = &eth_slow->lacp;
+
+ DBGC ( netdev,
+ "SLOW %s %s LACP actor (%04x,%s,%04x,%02x,%04x) [%s]\n",
+ netdev->name, label, ntohs ( lacp->actor.system_priority ),
+ eth_ntoa ( lacp->actor.system ),
+ ntohs ( lacp->actor.key ),
+ ntohs ( lacp->actor.port_priority ),
+ ntohs ( lacp->actor.port ),
+ eth_slow_lacp_state_name ( lacp->actor.state ) );
+ DBGC ( netdev,
+ "SLOW %s %s LACP partner (%04x,%s,%04x,%02x,%04x) [%s]\n",
+ netdev->name, label, ntohs ( lacp->partner.system_priority ),
+ eth_ntoa ( lacp->partner.system ),
+ ntohs ( lacp->partner.key ),
+ ntohs ( lacp->partner.port_priority ),
+ ntohs ( lacp->partner.port ),
+ eth_slow_lacp_state_name ( lacp->partner.state ) );
+ DBGC ( netdev, "SLOW %s %s LACP collector %04x (%d us)\n",
+ netdev->name, label, ntohs ( lacp->collector.max_delay ),
+ ( ntohs ( lacp->collector.max_delay ) * 10 ) );
+ DBGC2_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
+}
+
+/**
+ * Process incoming LACP packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int eth_slow_lacp_rx ( struct io_buffer *iobuf,
+ struct net_device *netdev ) {
+ union eth_slow_packet *eth_slow = iobuf->data;
+ struct eth_slow_lacp *lacp = &eth_slow->lacp;
+
+ eth_slow_lacp_dump ( iobuf, netdev, "RX" );
+
+ /* Build response */
+ memset ( lacp->reserved, 0, sizeof ( lacp->reserved ) );
+ memset ( &lacp->terminator, 0, sizeof ( lacp->terminator ) );
+ memset ( &lacp->collector, 0, sizeof ( lacp->collector ) );
+ lacp->collector.tlv.type = ETH_SLOW_TLV_LACP_COLLECTOR;
+ lacp->collector.tlv.length = ETH_SLOW_TLV_LACP_COLLECTOR_LEN;
+ memcpy ( &lacp->partner, &lacp->actor, sizeof ( lacp->partner ) );
+ lacp->partner.tlv.type = ETH_SLOW_TLV_LACP_PARTNER;
+ lacp->partner.tlv.length = ETH_SLOW_TLV_LACP_PARTNER_LEN;
+ memset ( &lacp->partner.reserved, 0,
+ sizeof ( lacp->partner.reserved ) );
+ memset ( &lacp->actor, 0, sizeof ( lacp->actor ) );
+ lacp->actor.tlv.type = ETH_SLOW_TLV_LACP_ACTOR;
+ lacp->actor.tlv.length = ETH_SLOW_TLV_LACP_ACTOR_LEN;
+ lacp->actor.system_priority = htons ( LACP_SYSTEM_PRIORITY_MAX );
+ memcpy ( lacp->actor.system, netdev->ll_addr,
+ sizeof ( lacp->actor.system ) );
+ lacp->actor.key = htons ( 1 );
+ lacp->actor.port_priority = htons ( LACP_PORT_PRIORITY_MAX );
+ lacp->actor.port = htons ( 1 );
+ lacp->actor.state = ( LACP_STATE_IN_SYNC |
+ LACP_STATE_COLLECTING |
+ LACP_STATE_DISTRIBUTING |
+ ( lacp->partner.state & LACP_STATE_FAST ) );
+ lacp->header.version = ETH_SLOW_LACP_VERSION;
+
+ /* Send response */
+ eth_slow_lacp_dump ( iobuf, netdev, "TX" );
+ return net_tx ( iobuf, netdev, &eth_slow_protocol, eth_slow_address,
+ netdev->ll_addr );
+}
+
+/**
+ * Dump marker packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v label "RX" or "TX"
+ */
+static void eth_slow_marker_dump ( struct io_buffer *iobuf,
+ struct net_device *netdev,
+ const char *label ) {
+ union eth_slow_packet *eth_slow = iobuf->data;
+ struct eth_slow_marker *marker = &eth_slow->marker;
+
+ DBGC ( netdev, "SLOW %s %s marker %s port %04x system %s xact %08x\n",
+ netdev->name, label,
+ eth_slow_marker_tlv_name ( marker->marker.tlv.type ),
+ ntohs ( marker->marker.port ),
+ eth_ntoa ( marker->marker.system ),
+ ntohl ( marker->marker.xact ) );
+ DBGC2_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
+}
+
+/**
+ * Process incoming marker packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int eth_slow_marker_rx ( struct io_buffer *iobuf,
+ struct net_device *netdev ) {
+ union eth_slow_packet *eth_slow = iobuf->data;
+ struct eth_slow_marker *marker = &eth_slow->marker;
+
+ eth_slow_marker_dump ( iobuf, netdev, "RX" );
+
+ if ( marker->marker.tlv.type == ETH_SLOW_TLV_MARKER_REQUEST ) {
+ /* Send marker response */
+ marker->marker.tlv.type = ETH_SLOW_TLV_MARKER_RESPONSE;
+ eth_slow_marker_dump ( iobuf, netdev, "TX" );
+ return net_tx ( iobuf, netdev, &eth_slow_protocol,
+ eth_slow_address, netdev->ll_addr );
+ } else {
+ /* Discard all other marker packets */
+ free_iob ( iobuf );
+ return -EINVAL;
+ }
+}
+
+/**
+ * Process incoming slow packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer source address
+ * @v flags Packet flags
+ * @ret rc Return status code
+ */
+static int eth_slow_rx ( struct io_buffer *iobuf,
+ struct net_device *netdev,
+ const void *ll_dest __unused,
+ const void *ll_source __unused,
+ unsigned int flags __unused ) {
+ union eth_slow_packet *eth_slow = iobuf->data;
+
+ /* Sanity checks */
+ if ( iob_len ( iobuf ) < sizeof ( *eth_slow ) ) {
+ free_iob ( iobuf );
+ return -EINVAL;
+ }
+
+ /* Handle according to subtype */
+ switch ( eth_slow->header.subtype ) {
+ case ETH_SLOW_SUBTYPE_LACP:
+ return eth_slow_lacp_rx ( iobuf, netdev );
+ case ETH_SLOW_SUBTYPE_MARKER:
+ return eth_slow_marker_rx ( iobuf, netdev );
+ default:
+ DBGC ( netdev, "SLOW %s RX unknown subtype %02x\n",
+ netdev->name, eth_slow->header.subtype );
+ free_iob ( iobuf );
+ return -EINVAL;
+ }
+}
+
+/** Slow protocol */
+struct net_protocol eth_slow_protocol __net_protocol = {
+ .name = "Slow",
+ .net_proto = htons ( ETH_P_SLOW ),
+ .rx = eth_slow_rx,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/ethernet.c b/src/VBox/Devices/PC/ipxe/src/net/ethernet.c
new file mode 100644
index 00000000..a842bc11
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/ethernet.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/if_arp.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/in.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/ethernet.h>
+
+/** @file
+ *
+ * Ethernet protocol
+ *
+ */
+
+/** Ethernet broadcast MAC address */
+static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+/**
+ * Add Ethernet link-layer header
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Source link-layer address
+ * @v net_proto Network-layer protocol, in network-byte order
+ * @ret rc Return status code
+ */
+int eth_push ( struct net_device *netdev __unused, struct io_buffer *iobuf,
+ const void *ll_dest, const void *ll_source,
+ uint16_t net_proto ) {
+ struct ethhdr *ethhdr = iob_push ( iobuf, sizeof ( *ethhdr ) );
+
+ /* Build Ethernet header */
+ memcpy ( ethhdr->h_dest, ll_dest, ETH_ALEN );
+ memcpy ( ethhdr->h_source, ll_source, ETH_ALEN );
+ ethhdr->h_protocol = net_proto;
+
+ return 0;
+}
+
+/**
+ * Remove Ethernet link-layer header
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret ll_dest Link-layer destination address
+ * @ret ll_source Source link-layer address
+ * @ret net_proto Network-layer protocol, in network-byte order
+ * @ret flags Packet flags
+ * @ret rc Return status code
+ */
+int eth_pull ( struct net_device *netdev __unused, struct io_buffer *iobuf,
+ const void **ll_dest, const void **ll_source,
+ uint16_t *net_proto, unsigned int *flags ) {
+ struct ethhdr *ethhdr = iobuf->data;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *ethhdr ) ) {
+ DBG ( "Ethernet packet too short (%zd bytes)\n",
+ iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+
+ /* Strip off Ethernet header */
+ iob_pull ( iobuf, sizeof ( *ethhdr ) );
+
+ /* Fill in required fields */
+ *ll_dest = ethhdr->h_dest;
+ *ll_source = ethhdr->h_source;
+ *net_proto = ethhdr->h_protocol;
+ *flags = ( ( is_multicast_ether_addr ( ethhdr->h_dest ) ?
+ LL_MULTICAST : 0 ) |
+ ( is_broadcast_ether_addr ( ethhdr->h_dest ) ?
+ LL_BROADCAST : 0 ) );
+
+ return 0;
+}
+
+/**
+ * Initialise Ethernet address
+ *
+ * @v hw_addr Hardware address
+ * @v ll_addr Link-layer address
+ */
+void eth_init_addr ( const void *hw_addr, void *ll_addr ) {
+ memcpy ( ll_addr, hw_addr, ETH_ALEN );
+}
+
+/**
+ * Transcribe Ethernet address
+ *
+ * @v ll_addr Link-layer address
+ * @ret string Link-layer address in human-readable format
+ */
+const char * eth_ntoa ( const void *ll_addr ) {
+ static char buf[18]; /* "00:00:00:00:00:00" */
+ const uint8_t *eth_addr = ll_addr;
+
+ sprintf ( buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+ eth_addr[0], eth_addr[1], eth_addr[2],
+ eth_addr[3], eth_addr[4], eth_addr[5] );
+ return buf;
+}
+
+/**
+ * Hash multicast address
+ *
+ * @v af Address family
+ * @v net_addr Network-layer address
+ * @v ll_addr Link-layer address to fill in
+ * @ret rc Return status code
+ */
+int eth_mc_hash ( unsigned int af, const void *net_addr, void *ll_addr ) {
+ const uint8_t *net_addr_bytes = net_addr;
+ uint8_t *ll_addr_bytes = ll_addr;
+
+ switch ( af ) {
+ case AF_INET:
+ ll_addr_bytes[0] = 0x01;
+ ll_addr_bytes[1] = 0x00;
+ ll_addr_bytes[2] = 0x5e;
+ ll_addr_bytes[3] = net_addr_bytes[1] & 0x7f;
+ ll_addr_bytes[4] = net_addr_bytes[2];
+ ll_addr_bytes[5] = net_addr_bytes[3];
+ return 0;
+ default:
+ return -ENOTSUP;
+ }
+}
+
+/**
+ * Generate Ethernet-compatible compressed link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @v eth_addr Ethernet-compatible address to fill in
+ */
+int eth_eth_addr ( const void *ll_addr, void *eth_addr ) {
+ memcpy ( eth_addr, ll_addr, ETH_ALEN );
+ return 0;
+}
+
+/** Ethernet protocol */
+struct ll_protocol ethernet_protocol __ll_protocol = {
+ .name = "Ethernet",
+ .ll_proto = htons ( ARPHRD_ETHER ),
+ .hw_addr_len = ETH_ALEN,
+ .ll_addr_len = ETH_ALEN,
+ .ll_header_len = ETH_HLEN,
+ .push = eth_push,
+ .pull = eth_pull,
+ .init_addr = eth_init_addr,
+ .ntoa = eth_ntoa,
+ .mc_hash = eth_mc_hash,
+ .eth_addr = eth_eth_addr,
+};
+
+/**
+ * Allocate Ethernet device
+ *
+ * @v priv_size Size of driver private data
+ * @ret netdev Network device, or NULL
+ */
+struct net_device * alloc_etherdev ( size_t priv_size ) {
+ struct net_device *netdev;
+
+ netdev = alloc_netdev ( priv_size );
+ if ( netdev ) {
+ netdev->ll_protocol = &ethernet_protocol;
+ netdev->ll_broadcast = eth_broadcast;
+ netdev->max_pkt_len = ETH_FRAME_LEN;
+ }
+ return netdev;
+}
+
+/* Drag in Ethernet slow protocols */
+REQUIRE_OBJECT ( eth_slow );
diff --git a/src/VBox/Devices/PC/ipxe/src/net/fakedhcp.c b/src/VBox/Devices/PC/ipxe/src/net/fakedhcp.c
new file mode 100644
index 00000000..b182ab6f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/fakedhcp.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <ipxe/settings.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/dhcppkt.h>
+#include <ipxe/fakedhcp.h>
+
+/** @file
+ *
+ * Fake DHCP packets
+ *
+ */
+
+/**
+ * Copy settings to DHCP packet
+ *
+ * @v dest Destination DHCP packet
+ * @v source Source settings block
+ * @v encapsulator Encapsulating setting tag number, or zero
+ * @ret rc Return status code
+ */
+static int copy_encap_settings ( struct dhcp_packet *dest,
+ struct settings *source,
+ unsigned int encapsulator ) {
+ struct setting setting = { .name = "" };
+ unsigned int subtag;
+ unsigned int tag;
+ int len;
+ int check_len;
+ int rc;
+
+ for ( subtag = DHCP_MIN_OPTION; subtag <= DHCP_MAX_OPTION; subtag++ ) {
+ tag = DHCP_ENCAP_OPT ( encapsulator, subtag );
+ switch ( tag ) {
+ case DHCP_EB_ENCAP:
+ case DHCP_VENDOR_ENCAP:
+ /* Process encapsulated settings */
+ if ( ( rc = copy_encap_settings ( dest, source,
+ tag ) ) != 0 )
+ return rc;
+ break;
+ default:
+ /* Copy setting, if present */
+ setting.tag = tag;
+ len = fetch_setting_len ( source, &setting );
+ if ( len < 0 )
+ break;
+ {
+ char buf[len];
+
+ check_len = fetch_setting ( source, &setting,
+ buf, sizeof (buf));
+ assert ( check_len == len );
+ if ( ( rc = dhcppkt_store ( dest, tag, buf,
+ sizeof(buf) )) !=0)
+ return rc;
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Copy settings to DHCP packet
+ *
+ * @v dest Destination DHCP packet
+ * @v source Source settings block
+ * @ret rc Return status code
+ */
+static int copy_settings ( struct dhcp_packet *dest,
+ struct settings *source ) {
+ return copy_encap_settings ( dest, source, 0 );
+}
+
+/**
+ * Create fake DHCPDISCOVER packet
+ *
+ * @v netdev Network device
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ *
+ * Used by external code.
+ */
+int create_fakedhcpdiscover ( struct net_device *netdev,
+ void *data, size_t max_len ) {
+ struct dhcp_packet dhcppkt;
+ struct in_addr ciaddr = { 0 };
+ int rc;
+
+ if ( ( rc = dhcp_create_request ( &dhcppkt, netdev, DHCPDISCOVER,
+ dhcp_last_xid, ciaddr, data,
+ max_len ) ) != 0 ) {
+ DBG ( "Could not create DHCPDISCOVER: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Create fake DHCPACK packet
+ *
+ * @v netdev Network device
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ *
+ * Used by external code.
+ */
+int create_fakedhcpack ( struct net_device *netdev,
+ void *data, size_t max_len ) {
+ struct dhcp_packet dhcppkt;
+ int rc;
+
+ /* Create base DHCPACK packet */
+ if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK,
+ dhcp_last_xid, NULL, 0,
+ data, max_len ) ) != 0 ) {
+ DBG ( "Could not create DHCPACK: %s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ /* Merge in globally-scoped settings, then netdev-specific
+ * settings. Do it in this order so that netdev-specific
+ * settings take precedence regardless of stated priorities.
+ */
+ if ( ( rc = copy_settings ( &dhcppkt, NULL ) ) != 0 ) {
+ DBG ( "Could not set DHCPACK global settings: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+ if ( ( rc = copy_settings ( &dhcppkt,
+ netdev_settings ( netdev ) ) ) != 0 ) {
+ DBG ( "Could not set DHCPACK netdev settings: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Create fake PXE Boot Server ACK packet
+ *
+ * @v netdev Network device
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ *
+ * Used by external code.
+ */
+int create_fakepxebsack ( struct net_device *netdev,
+ void *data, size_t max_len ) {
+ struct dhcp_packet dhcppkt;
+ struct settings *proxy_settings;
+ struct settings *pxebs_settings;
+ int rc;
+
+ /* Identify available settings */
+ proxy_settings = find_settings ( PROXYDHCP_SETTINGS_NAME );
+ pxebs_settings = find_settings ( PXEBS_SETTINGS_NAME );
+ if ( ( ! proxy_settings ) && ( ! pxebs_settings ) ) {
+ /* No PXE boot server; return the regular DHCPACK */
+ return create_fakedhcpack ( netdev, data, max_len );
+ }
+
+ /* Create base DHCPACK packet */
+ if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK,
+ dhcp_last_xid, NULL, 0,
+ data, max_len ) ) != 0 ) {
+ DBG ( "Could not create PXE BS ACK: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Merge in ProxyDHCP options */
+ if ( proxy_settings &&
+ ( ( rc = copy_settings ( &dhcppkt, proxy_settings ) ) != 0 ) ) {
+ DBG ( "Could not copy ProxyDHCP settings: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Merge in BootServerDHCP options, if present */
+ if ( pxebs_settings &&
+ ( ( rc = copy_settings ( &dhcppkt, pxebs_settings ) ) != 0 ) ) {
+ DBG ( "Could not copy PXE BS settings: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/fc.c b/src/VBox/Devices/PC/ipxe/src/net/fc.c
new file mode 100644
index 00000000..f76cfe92
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/fc.c
@@ -0,0 +1,1936 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/list.h>
+#include <ipxe/tables.h>
+#include <ipxe/timer.h>
+#include <ipxe/retry.h>
+#include <ipxe/interface.h>
+#include <ipxe/xfer.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/fc.h>
+#include <ipxe/fcels.h>
+#include <ipxe/fcns.h>
+
+/** @file
+ *
+ * Fibre Channel
+ *
+ */
+
+/** List of Fibre Channel ports */
+LIST_HEAD ( fc_ports );
+
+/** List of Fibre Channel peers */
+LIST_HEAD ( fc_peers );
+
+/******************************************************************************
+ *
+ * Well-known addresses
+ *
+ ******************************************************************************
+ */
+
+/** Unassigned port ID */
+struct fc_port_id fc_empty_port_id = { .bytes = { 0x00, 0x00, 0x00 } };
+
+/** F_Port contoller port ID */
+struct fc_port_id fc_f_port_id = { .bytes = { 0xff, 0xff, 0xfe } };
+
+/** Generic services port ID */
+struct fc_port_id fc_gs_port_id = { .bytes = { 0xff, 0xff, 0xfc } };
+
+/** Point-to-point low port ID */
+struct fc_port_id fc_ptp_low_port_id = { .bytes = { 0x01, 0x01, 0x01 } };
+
+/** Point-to-point high port ID */
+struct fc_port_id fc_ptp_high_port_id = { .bytes = { 0x01, 0x01, 0x02 } };
+
+/******************************************************************************
+ *
+ * Utility functions
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Format Fibre Channel port ID
+ *
+ * @v id Fibre Channel port ID
+ * @ret id_text Port ID text
+ */
+const char * fc_id_ntoa ( const struct fc_port_id *id ) {
+ static char id_text[ FC_PORT_ID_STRLEN + 1 /* NUL */ ];
+
+ snprintf ( id_text, sizeof ( id_text ), "%02x.%02x.%02x",
+ id->bytes[0], id->bytes[1], id->bytes[2] );
+ return id_text;
+}
+
+/**
+ * Parse Fibre Channel port ID
+ *
+ * @v id_text Port ID text
+ * @ret id Fibre Channel port ID
+ * @ret rc Return status code
+ */
+int fc_id_aton ( const char *id_text, struct fc_port_id *id ) {
+ char *ptr = ( ( char * ) id_text );
+ unsigned int i = 0;
+
+ while ( 1 ) {
+ id->bytes[i++] = strtoul ( ptr, &ptr, 16 );
+ if ( i == sizeof ( id->bytes ) )
+ return ( ( *ptr == '\0' ) ? 0 : -EINVAL );
+ if ( *ptr != '.' )
+ return -EINVAL;
+ ptr++;
+ }
+}
+
+/**
+ * Format Fibre Channel WWN
+ *
+ * @v wwn Fibre Channel WWN
+ * @ret wwn_text WWN text
+ */
+const char * fc_ntoa ( const struct fc_name *wwn ) {
+ static char wwn_text[ FC_NAME_STRLEN + 1 /* NUL */ ];
+
+ snprintf ( wwn_text, sizeof ( wwn_text ),
+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+ wwn->bytes[0], wwn->bytes[1], wwn->bytes[2], wwn->bytes[3],
+ wwn->bytes[4], wwn->bytes[5], wwn->bytes[6], wwn->bytes[7] );
+ return wwn_text;
+}
+
+/**
+ * Parse Fibre Channel WWN
+ *
+ * @v wwn_text WWN text
+ * @ret wwn Fibre Channel WWN
+ * @ret rc Return status code
+ */
+int fc_aton ( const char *wwn_text, struct fc_name *wwn ) {
+ char *ptr = ( ( char * ) wwn_text );
+ unsigned int i = 0;
+
+ while ( 1 ) {
+ wwn->bytes[i++] = strtoul ( ptr, &ptr, 16 );
+ if ( i == sizeof ( wwn->bytes ) )
+ return ( ( *ptr == '\0' ) ? 0 : -EINVAL );
+ if ( *ptr != ':' )
+ return -EINVAL;
+ ptr++;
+ }
+}
+
+/**
+ * Fill Fibre Channel socket address
+ *
+ * @v sa_fc Fibre Channel socket address to fill in
+ * @v id Fibre Channel port ID
+ * @ret sa Socket address
+ */
+struct sockaddr * fc_fill_sockaddr ( struct sockaddr_fc *sa_fc,
+ struct fc_port_id *id ) {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_fc fc;
+ } *u = container_of ( sa_fc, typeof ( *u ), fc );
+
+ memset ( sa_fc, 0, sizeof ( *sa_fc ) );
+ sa_fc->sfc_family = AF_FC;
+ memcpy ( &sa_fc->sfc_port_id, id, sizeof ( sa_fc->sfc_port_id ) );
+ return &u->sa;
+}
+
+/******************************************************************************
+ *
+ * Fibre Channel link state
+ *
+ ******************************************************************************
+ */
+
+/** Default link status code */
+#define EUNKNOWN_LINK_STATUS __einfo_error ( EINFO_EUNKNOWN_LINK_STATUS )
+#define EINFO_EUNKNOWN_LINK_STATUS \
+ __einfo_uniqify ( EINFO_EINPROGRESS, 0x01, "Unknown" )
+
+/**
+ * Mark Fibre Channel link as up
+ *
+ * @v link Fibre Channel link state monitor
+ */
+static void fc_link_up ( struct fc_link_state *link ) {
+
+ /* Stop retry timer */
+ stop_timer ( &link->timer );
+
+ /* Record link state */
+ link->rc = 0;
+}
+
+/**
+ * Mark Fibre Channel link as down
+ *
+ * @v link Fibre Channel link state monitor
+ * @v rc Link state
+ */
+static void fc_link_err ( struct fc_link_state *link, int rc ) {
+
+ /* Record link state */
+ if ( rc == 0 )
+ rc = -EUNKNOWN_LINK_STATUS;
+ link->rc = rc;
+
+ /* Schedule another link examination */
+ start_timer_fixed ( &link->timer, FC_LINK_RETRY_DELAY );
+}
+
+/**
+ * Examine Fibre Channel link state
+ *
+ * @v link Fibre Channel link state monitor
+ */
+static void fc_link_examine ( struct fc_link_state *link ) {
+
+ link->examine ( link );
+}
+
+/**
+ * Handle Fibre Channel link retry timer expiry
+ */
+static void fc_link_expired ( struct retry_timer *timer, int over __unused ) {
+ struct fc_link_state *link =
+ container_of ( timer, struct fc_link_state, timer );
+
+ /* Schedule another link examination */
+ start_timer_fixed ( &link->timer, FC_LINK_RETRY_DELAY );
+
+ /* Examine link */
+ fc_link_examine ( link );
+}
+
+/**
+ * Initialise Fibre Channel link state monitor
+ *
+ * @v link Fibre Channel link state monitor
+ * @v examine Examine link state method
+ * @v refcnt Reference counter
+ */
+static void fc_link_init ( struct fc_link_state *link,
+ void ( * examine ) ( struct fc_link_state *link ),
+ struct refcnt *refcnt ) {
+
+ link->rc = -EUNKNOWN_LINK_STATUS;
+ timer_init ( &link->timer, fc_link_expired, refcnt );
+ link->examine = examine;
+}
+
+/**
+ * Start monitoring Fibre Channel link state
+ *
+ * @v link Fibre Channel link state monitor
+ */
+static void fc_link_start ( struct fc_link_state *link ) {
+ start_timer_nodelay ( &link->timer );
+}
+
+/**
+ * Stop monitoring Fibre Channel link state
+ *
+ * @v link Fibre Channel link state monitor
+ */
+static void fc_link_stop ( struct fc_link_state *link ) {
+ stop_timer ( &link->timer );
+}
+
+/******************************************************************************
+ *
+ * Fibre Channel exchanges
+ *
+ ******************************************************************************
+ */
+
+/** A Fibre Channel exchange */
+struct fc_exchange {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Fibre Channel port */
+ struct fc_port *port;
+ /** List of active exchanges within this port */
+ struct list_head list;
+
+ /** Peer port ID */
+ struct fc_port_id peer_port_id;
+ /** Data structure type */
+ unsigned int type;
+ /** Flags */
+ unsigned int flags;
+ /** Local exchange ID */
+ uint16_t xchg_id;
+ /** Peer exchange ID */
+ uint16_t peer_xchg_id;
+ /** Active sequence ID */
+ uint8_t seq_id;
+ /** Active sequence count */
+ uint16_t seq_cnt;
+
+ /** Timeout timer */
+ struct retry_timer timer;
+
+ /** Upper-layer protocol interface */
+ struct interface ulp;
+};
+
+/** Fibre Channel exchange flags */
+enum fc_exchange_flags {
+ /** We are the exchange originator */
+ FC_XCHG_ORIGINATOR = 0x0001,
+ /** We have the sequence initiative */
+ FC_XCHG_SEQ_INITIATIVE = 0x0002,
+ /** This is the first sequence of the exchange */
+ FC_XCHG_SEQ_FIRST = 0x0004,
+};
+
+/** Fibre Channel timeout */
+#define FC_TIMEOUT ( 1 * TICKS_PER_SEC )
+
+/**
+ * Create local Fibre Channel exchange identifier
+ *
+ * @ret xchg_id Local exchange ID
+ */
+static unsigned int fc_new_xchg_id ( void ) {
+ static uint16_t next_id = 0x0000;
+
+ /* We must avoid using FC_RX_ID_UNKNOWN (0xffff) */
+ next_id += 2;
+ return next_id;
+}
+
+/**
+ * Create local Fibre Channel sequence identifier
+ *
+ * @ret seq_id Local sequence identifier
+ */
+static unsigned int fc_new_seq_id ( void ) {
+ static uint8_t seq_id = 0x00;
+
+ return (++seq_id);
+}
+
+/**
+ * Free Fibre Channel exchange
+ *
+ * @v refcnt Reference count
+ */
+static void fc_xchg_free ( struct refcnt *refcnt ) {
+ struct fc_exchange *xchg =
+ container_of ( refcnt, struct fc_exchange, refcnt );
+
+ assert ( ! timer_running ( &xchg->timer ) );
+ assert ( list_empty ( &xchg->list ) );
+
+ fc_port_put ( xchg->port );
+ free ( xchg );
+}
+
+/**
+ * Close Fibre Channel exchange
+ *
+ * @v xchg Fibre Channel exchange
+ * @v rc Reason for close
+ */
+static void fc_xchg_close ( struct fc_exchange *xchg, int rc ) {
+ struct fc_port *port = xchg->port;
+
+ if ( rc != 0 ) {
+ DBGC2 ( port, "FCXCHG %s/%04x closed: %s\n",
+ port->name, xchg->xchg_id, strerror ( rc ) );
+ }
+
+ /* Stop timer */
+ stop_timer ( &xchg->timer );
+
+ /* If list still holds a reference, remove from list of open
+ * exchanges and drop list's reference.
+ */
+ if ( ! list_empty ( &xchg->list ) ) {
+ list_del ( &xchg->list );
+ INIT_LIST_HEAD ( &xchg->list );
+ ref_put ( &xchg->refcnt );
+ }
+
+ /* Shutdown interfaces */
+ intf_shutdown ( &xchg->ulp, rc );
+}
+
+/**
+ * Handle exchange timeout
+ *
+ * @v timer Timeout timer
+ * @v over Failure indicator
+ */
+static void fc_xchg_expired ( struct retry_timer *timer, int over __unused ) {
+ struct fc_exchange *xchg =
+ container_of ( timer, struct fc_exchange, timer );
+ struct fc_port *port = xchg->port;
+
+ DBGC ( port, "FCXCHG %s/%04x timed out\n", port->name, xchg->xchg_id );
+
+ /* Terminate the exchange */
+ fc_xchg_close ( xchg, -ETIMEDOUT );
+}
+
+/**
+ * Check Fibre Channel exchange window
+ *
+ * @v xchg Fibre Channel exchange
+ * @ret len Length opf window
+ */
+static size_t fc_xchg_window ( struct fc_exchange *xchg __unused ) {
+
+ /* We don't currently store the path MTU */
+ return FC_LOGIN_DEFAULT_MTU;
+}
+
+/**
+ * Allocate Fibre Channel I/O buffer
+ *
+ * @v xchg Fibre Channel exchange
+ * @v len Payload length
+ * @ret iobuf I/O buffer, or NULL
+ */
+static struct io_buffer * fc_xchg_alloc_iob ( struct fc_exchange *xchg,
+ size_t len ) {
+ struct fc_port *port = xchg->port;
+ struct io_buffer *iobuf;
+
+ iobuf = xfer_alloc_iob ( &port->transport,
+ ( sizeof ( struct fc_frame_header ) + len ) );
+ if ( iobuf ) {
+ iob_reserve ( iobuf, sizeof ( struct fc_frame_header ) );
+ }
+ return iobuf;
+}
+
+/**
+ * Transmit data as part of a Fibre Channel exchange
+ *
+ * @v xchg Fibre Channel exchange
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int fc_xchg_tx ( struct fc_exchange *xchg, struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct fc_port *port = xchg->port;
+ struct sockaddr_fc *dest = ( ( struct sockaddr_fc * ) meta->dest );
+ struct fc_frame_header *fchdr;
+ unsigned int r_ctl;
+ unsigned int f_ctl_es;
+ int rc;
+
+ /* Sanity checks */
+ if ( ! ( xchg->flags & FC_XCHG_SEQ_INITIATIVE ) ) {
+ DBGC ( port, "FCXCHG %s/%04x cannot transmit while not "
+ "holding sequence initiative\n",
+ port->name, xchg->xchg_id );
+ rc = -EBUSY;
+ goto done;
+ }
+
+ /* Calculate routing control */
+ switch ( xchg->type ) {
+ case FC_TYPE_ELS:
+ r_ctl = FC_R_CTL_ELS;
+ if ( meta->flags & XFER_FL_RESPONSE ) {
+ r_ctl |= FC_R_CTL_SOL_CTRL;
+ } else {
+ r_ctl |= FC_R_CTL_UNSOL_CTRL;
+ }
+ break;
+ case FC_TYPE_CT:
+ r_ctl = FC_R_CTL_DATA;
+ if ( meta->flags & XFER_FL_RESPONSE ) {
+ r_ctl |= FC_R_CTL_SOL_CTRL;
+ } else {
+ r_ctl |= FC_R_CTL_UNSOL_CTRL;
+ }
+ break;
+ default:
+ r_ctl = FC_R_CTL_DATA;
+ switch ( meta->flags &
+ ( XFER_FL_CMD_STAT | XFER_FL_RESPONSE ) ) {
+ case ( XFER_FL_CMD_STAT | XFER_FL_RESPONSE ):
+ r_ctl |= FC_R_CTL_CMD_STAT;
+ break;
+ case ( XFER_FL_CMD_STAT ):
+ r_ctl |= FC_R_CTL_UNSOL_CMD;
+ break;
+ case ( XFER_FL_RESPONSE ):
+ r_ctl |= FC_R_CTL_SOL_DATA;
+ break;
+ default:
+ r_ctl |= FC_R_CTL_UNSOL_DATA;
+ break;
+ }
+ break;
+ }
+
+ /* Calculate exchange and sequence control */
+ f_ctl_es = 0;
+ if ( ! ( xchg->flags & FC_XCHG_ORIGINATOR ) )
+ f_ctl_es |= FC_F_CTL_ES_RESPONDER;
+ if ( xchg->flags & FC_XCHG_SEQ_FIRST )
+ f_ctl_es |= FC_F_CTL_ES_FIRST;
+ if ( meta->flags & XFER_FL_OUT )
+ f_ctl_es |= ( FC_F_CTL_ES_END | FC_F_CTL_ES_LAST );
+ if ( meta->flags & XFER_FL_OVER )
+ f_ctl_es |= ( FC_F_CTL_ES_END | FC_F_CTL_ES_TRANSFER );
+
+ /* Create frame header */
+ fchdr = iob_push ( iobuf, sizeof ( *fchdr ) );
+ memset ( fchdr, 0, sizeof ( *fchdr ) );
+ fchdr->r_ctl = r_ctl;
+ memcpy ( &fchdr->d_id,
+ ( dest ? &dest->sfc_port_id : &xchg->peer_port_id ),
+ sizeof ( fchdr->d_id ) );
+ memcpy ( &fchdr->s_id, &port->port_id, sizeof ( fchdr->s_id ) );
+ fchdr->type = xchg->type;
+ fchdr->f_ctl_es = f_ctl_es;
+ fchdr->seq_id = xchg->seq_id;
+ fchdr->seq_cnt = htons ( xchg->seq_cnt++ );
+ fchdr->ox_id = htons ( ( xchg->flags & FC_XCHG_ORIGINATOR ) ?
+ xchg->xchg_id : xchg->peer_xchg_id );
+ fchdr->rx_id = htons ( ( xchg->flags & FC_XCHG_ORIGINATOR ) ?
+ xchg->peer_xchg_id : xchg->xchg_id );
+ if ( meta->flags & XFER_FL_ABS_OFFSET ) {
+ fchdr->f_ctl_misc |= FC_F_CTL_MISC_REL_OFF;
+ fchdr->parameter = htonl ( meta->offset );
+ }
+
+ /* Relinquish sequence initiative if applicable */
+ if ( meta->flags & XFER_FL_OVER ) {
+ xchg->flags &= ~( FC_XCHG_SEQ_INITIATIVE | FC_XCHG_SEQ_FIRST );
+ xchg->seq_cnt = 0;
+ }
+
+ /* Reset timeout */
+ start_timer_fixed ( &xchg->timer, FC_TIMEOUT );
+
+ /* Deliver frame */
+ if ( ( rc = xfer_deliver_iob ( &port->transport,
+ iob_disown ( iobuf ) ) ) != 0 ) {
+ DBGC ( port, "FCXCHG %s/%04x cannot transmit: %s\n",
+ port->name, xchg->xchg_id, strerror ( rc ) );
+ goto done;
+ }
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** Mapping from Fibre Channel routing control information to xfer metadata */
+static const uint8_t fc_r_ctl_info_meta_flags[ FC_R_CTL_INFO_MASK + 1 ] = {
+ [FC_R_CTL_UNCAT] = ( 0 ),
+ [FC_R_CTL_SOL_DATA] = ( XFER_FL_RESPONSE ),
+ [FC_R_CTL_UNSOL_CTRL] = ( XFER_FL_CMD_STAT ),
+ [FC_R_CTL_SOL_CTRL] = ( XFER_FL_CMD_STAT ),
+ [FC_R_CTL_UNSOL_DATA] = ( 0 ),
+ [FC_R_CTL_DATA_DESC] = ( XFER_FL_CMD_STAT ),
+ [FC_R_CTL_UNSOL_CMD] = ( XFER_FL_CMD_STAT ),
+ [FC_R_CTL_CMD_STAT] = ( XFER_FL_CMD_STAT | XFER_FL_RESPONSE ),
+};
+
+/**
+ * Receive data as part of a Fibre Channel exchange
+ *
+ * @v xchg Fibre Channel exchange
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int fc_xchg_rx ( struct fc_exchange *xchg, struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ struct fc_port *port = xchg->port;
+ struct fc_frame_header *fchdr = iobuf->data;
+ struct xfer_metadata fc_meta;
+ struct sockaddr_fc src;
+ struct sockaddr_fc dest;
+ int rc;
+
+ /* Record peer exchange ID */
+ xchg->peer_xchg_id =
+ ntohs ( ( fchdr->f_ctl_es & FC_F_CTL_ES_RESPONDER ) ?
+ fchdr->rx_id : fchdr->ox_id );
+
+ /* Sequence checks */
+ if ( xchg->flags & FC_XCHG_SEQ_INITIATIVE ) {
+ DBGC ( port, "FCXCHG %s/%04x received frame while holding "
+ "sequence initiative\n", port->name, xchg->xchg_id );
+ rc = -EBUSY;
+ goto done;
+ }
+ if ( ntohs ( fchdr->seq_cnt ) != xchg->seq_cnt ) {
+ DBGC ( port, "FCXCHG %s/%04x received out-of-order frame %d "
+ "(expected %d)\n", port->name, xchg->xchg_id,
+ ntohs ( fchdr->seq_cnt ), xchg->seq_cnt );
+ rc = -EPIPE;
+ goto done;
+ }
+ if ( xchg->seq_cnt == 0 )
+ xchg->seq_id = fchdr->seq_id;
+ xchg->seq_cnt++;
+ if ( fchdr->seq_id != xchg->seq_id ) {
+ DBGC ( port, "FCXCHG %s/%04x received frame for incorrect "
+ "sequence %02x (expected %02x)\n", port->name,
+ xchg->xchg_id, fchdr->seq_id, xchg->seq_id );
+ rc = -EPIPE;
+ goto done;
+ }
+
+ /* Check for end of sequence and transfer of sequence initiative */
+ if ( fchdr->f_ctl_es & FC_F_CTL_ES_END ) {
+ xchg->seq_cnt = 0;
+ if ( fchdr->f_ctl_es & FC_F_CTL_ES_TRANSFER ) {
+ xchg->flags |= FC_XCHG_SEQ_INITIATIVE;
+ xchg->seq_id = fc_new_seq_id();
+ }
+ }
+
+ /* Construct metadata */
+ memset ( &fc_meta, 0, sizeof ( fc_meta ) );
+ fc_meta.flags =
+ fc_r_ctl_info_meta_flags[ fchdr->r_ctl & FC_R_CTL_INFO_MASK ];
+ if ( fchdr->f_ctl_es & FC_F_CTL_ES_TRANSFER ) {
+ fc_meta.flags |= XFER_FL_OVER;
+ }
+ if ( ( fchdr->f_ctl_es & FC_F_CTL_ES_LAST ) &&
+ ( fchdr->f_ctl_es & FC_F_CTL_ES_END ) ) {
+ fc_meta.flags |= XFER_FL_OUT;
+ }
+ if ( fchdr->f_ctl_misc & FC_F_CTL_MISC_REL_OFF ) {
+ fc_meta.flags |= XFER_FL_ABS_OFFSET;
+ fc_meta.offset = ntohl ( fchdr->parameter );
+ }
+ fc_meta.src = fc_fill_sockaddr ( &src, &fchdr->s_id );
+ fc_meta.dest = fc_fill_sockaddr ( &dest, &fchdr->d_id );
+
+ /* Reset timeout */
+ start_timer_fixed ( &xchg->timer, FC_TIMEOUT );
+
+ /* Deliver via exchange's ULP interface */
+ iob_pull ( iobuf, sizeof ( *fchdr ) );
+ if ( ( rc = xfer_deliver ( &xchg->ulp, iob_disown ( iobuf ),
+ &fc_meta ) ) != 0 ) {
+ DBGC ( port, "FCXCHG %s/%04x cannot deliver frame: %s\n",
+ port->name, xchg->xchg_id, strerror ( rc ) );
+ goto done;
+ }
+
+ /* Close exchange if applicable */
+ if ( ( fchdr->f_ctl_es & FC_F_CTL_ES_LAST ) &&
+ ( fchdr->f_ctl_es & FC_F_CTL_ES_END ) ) {
+ fc_xchg_close ( xchg, 0 );
+ }
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** Fibre Channel exchange ULP interface operations */
+static struct interface_operation fc_xchg_ulp_op[] = {
+ INTF_OP ( xfer_deliver, struct fc_exchange *, fc_xchg_tx ),
+ INTF_OP ( xfer_alloc_iob, struct fc_exchange *, fc_xchg_alloc_iob ),
+ INTF_OP ( xfer_window, struct fc_exchange *, fc_xchg_window ),
+ INTF_OP ( intf_close, struct fc_exchange *, fc_xchg_close ),
+};
+
+/** Fibre Channel exchange ULP interface descriptor */
+static struct interface_descriptor fc_xchg_ulp_desc =
+ INTF_DESC ( struct fc_exchange, ulp, fc_xchg_ulp_op );
+
+/**
+ * Create new Fibre Channel exchange
+ *
+ * @v port Fibre Channel port
+ * @v peer_port_id Peer port ID
+ * @ret xchg Exchange, or NULL
+ */
+static struct fc_exchange * fc_xchg_create ( struct fc_port *port,
+ struct fc_port_id *peer_port_id,
+ unsigned int type ) {
+ struct fc_exchange *xchg;
+
+ /* Allocate and initialise structure */
+ xchg = zalloc ( sizeof ( *xchg ) );
+ if ( ! xchg )
+ return NULL;
+ ref_init ( &xchg->refcnt, fc_xchg_free );
+ intf_init ( &xchg->ulp, &fc_xchg_ulp_desc, &xchg->refcnt );
+ timer_init ( &xchg->timer, fc_xchg_expired, &xchg->refcnt );
+ xchg->port = fc_port_get ( port );
+ memcpy ( &xchg->peer_port_id, peer_port_id,
+ sizeof ( xchg->peer_port_id ) );
+ xchg->type = type;
+ xchg->xchg_id = fc_new_xchg_id();
+ xchg->peer_xchg_id = FC_RX_ID_UNKNOWN;
+ xchg->seq_id = fc_new_seq_id();
+
+ /* Transfer reference to list of exchanges and return */
+ list_add ( &xchg->list, &port->xchgs );
+ return xchg;
+}
+
+/**
+ * Originate a new Fibre Channel exchange
+ *
+ * @v parent Interface to which to attach
+ * @v port Fibre Channel port
+ * @v peer_port_id Peer port ID
+ * @ret xchg_id Exchange ID, or negative error
+ */
+int fc_xchg_originate ( struct interface *parent, struct fc_port *port,
+ struct fc_port_id *peer_port_id, unsigned int type ) {
+ struct fc_exchange *xchg;
+
+ /* Allocate and initialise structure */
+ xchg = fc_xchg_create ( port, peer_port_id, type );
+ if ( ! xchg )
+ return -ENOMEM;
+ xchg->flags = ( FC_XCHG_ORIGINATOR | FC_XCHG_SEQ_INITIATIVE |
+ FC_XCHG_SEQ_FIRST );
+
+ DBGC2 ( port, "FCXCHG %s/%04x originating to %s (type %02x)\n",
+ port->name, xchg->xchg_id, fc_id_ntoa ( &xchg->peer_port_id ),
+ xchg->type );
+
+ /* Attach to parent interface and return */
+ intf_plug_plug ( &xchg->ulp, parent );
+ return xchg->xchg_id;
+}
+
+/**
+ * Open a new responder Fibre Channel exchange
+ *
+ * @v port Fibre Channel port
+ * @v fchdr Fibre Channel frame header
+ * @ret xchg Fibre Channel exchange, or NULL
+ */
+static struct fc_exchange * fc_xchg_respond ( struct fc_port *port,
+ struct fc_frame_header *fchdr ) {
+ struct fc_exchange *xchg;
+ struct fc_responder *responder;
+ unsigned int type = fchdr->type;
+ int rc;
+
+ /* Allocate and initialise structure */
+ xchg = fc_xchg_create ( port, &fchdr->s_id, type );
+ if ( ! xchg )
+ return NULL;
+ xchg->seq_id = fchdr->seq_id;
+
+ DBGC2 ( port, "FCXCHG %s/%04x responding to %s xchg %04x (type "
+ "%02x)\n", port->name, xchg->xchg_id,
+ fc_id_ntoa ( &xchg->peer_port_id ),
+ ntohs ( fchdr->ox_id ), xchg->type );
+
+ /* Find a responder, if any */
+ for_each_table_entry ( responder, FC_RESPONDERS ) {
+ if ( responder->type == type ) {
+ if ( ( rc = responder->respond ( &xchg->ulp, port,
+ &fchdr->d_id,
+ &fchdr->s_id ) ) !=0 ){
+ DBGC ( port, "FCXCHG %s/%04x could not "
+ "respond: %s\n", port->name,
+ xchg->xchg_id, strerror ( rc ) );
+ }
+ }
+ break;
+ }
+
+ /* We may or may not have a ULP attached at this point, but
+ * the exchange does exist.
+ */
+ return xchg;
+}
+
+/******************************************************************************
+ *
+ * Fibre Channel ports
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Close Fibre Channel port
+ *
+ * @v port Fibre Channel port
+ * @v rc Reason for close
+ */
+static void fc_port_close ( struct fc_port *port, int rc ) {
+ struct fc_exchange *xchg;
+ struct fc_exchange *tmp;
+
+ DBGC ( port, "FCPORT %s closed\n", port->name );
+
+ /* Log out port, if necessary */
+ if ( fc_link_ok ( &port->link ) )
+ fc_port_logout ( port, rc );
+
+ /* Stop link monitor */
+ fc_link_stop ( &port->link );
+
+ /* Shut down interfaces */
+ intf_shutdown ( &port->transport, rc );
+ intf_shutdown ( &port->flogi, rc );
+ intf_shutdown ( &port->ns_plogi, rc );
+
+ /* Shut down any remaining exchanges */
+ list_for_each_entry_safe ( xchg, tmp, &port->xchgs, list )
+ fc_xchg_close ( xchg, rc );
+
+ /* Remove from list of ports */
+ list_del ( &port->list );
+ INIT_LIST_HEAD ( &port->list );
+}
+
+/**
+ * Identify Fibre Channel exchange by local exchange ID
+ *
+ * @v port Fibre Channel port
+ * @v xchg_id Local exchange ID
+ * @ret xchg Fibre Channel exchange, or NULL
+ */
+static struct fc_exchange * fc_port_demux ( struct fc_port *port,
+ unsigned int xchg_id ) {
+ struct fc_exchange *xchg;
+
+ list_for_each_entry ( xchg, &port->xchgs, list ) {
+ if ( xchg->xchg_id == xchg_id )
+ return xchg;
+ }
+ return NULL;
+}
+
+/**
+ * Handle received frame from Fibre Channel port
+ *
+ * @v port Fibre Channel port
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int fc_port_deliver ( struct fc_port *port, struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct fc_frame_header *fchdr = iobuf->data;
+ unsigned int xchg_id;
+ struct fc_exchange *xchg;
+ int rc;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *fchdr ) ) {
+ DBGC ( port, "FCPORT %s received underlength frame (%zd "
+ "bytes)\n", port->name, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto err_sanity;
+ }
+
+ /* Verify local port ID */
+ if ( ( memcmp ( &fchdr->d_id, &port->port_id,
+ sizeof ( fchdr->d_id ) ) != 0 ) &&
+ ( memcmp ( &fchdr->d_id, &fc_f_port_id,
+ sizeof ( fchdr->d_id ) ) != 0 ) &&
+ ( memcmp ( &port->port_id, &fc_empty_port_id,
+ sizeof ( port->port_id ) ) != 0 ) ) {
+ DBGC ( port, "FCPORT %s received frame for incorrect port ID "
+ "%s\n", port->name, fc_id_ntoa ( &fchdr->d_id ) );
+ rc = -ENOTCONN;
+ goto err_port_id;
+ }
+
+ /* Demultiplex amongst active exchanges */
+ xchg_id = ntohs ( ( fchdr->f_ctl_es & FC_F_CTL_ES_RESPONDER ) ?
+ fchdr->ox_id : fchdr->rx_id );
+ xchg = fc_port_demux ( port, xchg_id );
+
+ /* If we have no active exchange and this frame starts a new
+ * exchange, try to create a new responder exchange
+ */
+ if ( ( fchdr->f_ctl_es & FC_F_CTL_ES_FIRST ) &&
+ ( fchdr->seq_cnt == 0 ) ) {
+
+ /* Create new exchange */
+ xchg = fc_xchg_respond ( port, fchdr );
+ if ( ! xchg ) {
+ DBGC ( port, "FCPORT %s cannot create new exchange\n",
+ port->name );
+ rc = -ENOMEM;
+ goto err_respond;
+ }
+ }
+
+ /* Fail if no exchange exists */
+ if ( ! xchg ) {
+ DBGC ( port, "FCPORT %s xchg %04x unknown\n",
+ port->name, xchg_id );
+ rc = -ENOTCONN;
+ goto err_no_xchg;
+ }
+
+ /* Pass received frame to exchange */
+ ref_get ( &xchg->refcnt );
+ if ( ( rc = fc_xchg_rx ( xchg, iob_disown ( iobuf ), meta ) ) != 0 )
+ goto err_xchg_rx;
+
+ err_xchg_rx:
+ ref_put ( &xchg->refcnt );
+ err_no_xchg:
+ err_respond:
+ err_port_id:
+ err_sanity:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Log in Fibre Channel port
+ *
+ * @v port Fibre Channel port
+ * @v port_id Local port ID
+ * @v link_node_wwn Link node name
+ * @v link_port_wwn Link port name
+ * @v has_fabric Link is to a fabric
+ * @ret rc Return status code
+ */
+int fc_port_login ( struct fc_port *port, struct fc_port_id *port_id,
+ const struct fc_name *link_node_wwn,
+ const struct fc_name *link_port_wwn, int has_fabric ) {
+ struct fc_peer *peer;
+ struct fc_peer *tmp;
+ int rc;
+
+ /* Perform implicit logout if logged in and details differ */
+ if ( fc_link_ok ( &port->link ) &&
+ ( ( ( !! ( port->flags & FC_PORT_HAS_FABRIC ) ) !=
+ ( !! has_fabric ) ) ||
+ ( memcmp ( &port->link_node_wwn, link_node_wwn,
+ sizeof ( port->link_node_wwn ) ) != 0 ) ||
+ ( memcmp ( &port->link_port_wwn, link_port_wwn,
+ sizeof ( port->link_port_wwn ) ) != 0 ) ||
+ ( has_fabric &&
+ ( memcmp ( &port->port_id, port_id,
+ sizeof ( port->port_id ) ) != 0 ) ) ) ) {
+ fc_port_logout ( port, 0 );
+ }
+
+ /* Log in, if applicable */
+ if ( ! fc_link_ok ( &port->link ) ) {
+
+ /* Record link port name */
+ memcpy ( &port->link_node_wwn, link_node_wwn,
+ sizeof ( port->link_node_wwn ) );
+ memcpy ( &port->link_port_wwn, link_port_wwn,
+ sizeof ( port->link_port_wwn ) );
+ DBGC ( port, "FCPORT %s logged in to %s",
+ port->name, fc_ntoa ( &port->link_node_wwn ) );
+ DBGC ( port, " port %s\n", fc_ntoa ( &port->link_port_wwn ) );
+
+ /* Calculate local (and possibly remote) port IDs */
+ if ( has_fabric ) {
+ port->flags |= FC_PORT_HAS_FABRIC;
+ memcpy ( &port->port_id, port_id,
+ sizeof ( port->port_id ) );
+ } else {
+ port->flags &= ~FC_PORT_HAS_FABRIC;
+ if ( memcmp ( &port->port_wwn, link_port_wwn,
+ sizeof ( port->port_wwn ) ) > 0 ) {
+ memcpy ( &port->port_id, &fc_ptp_high_port_id,
+ sizeof ( port->port_id ) );
+ memcpy ( &port->ptp_link_port_id,
+ &fc_ptp_low_port_id,
+ sizeof ( port->ptp_link_port_id ) );
+ } else {
+ memcpy ( &port->port_id, &fc_ptp_low_port_id,
+ sizeof ( port->port_id ) );
+ memcpy ( &port->ptp_link_port_id,
+ &fc_ptp_high_port_id,
+ sizeof ( port->ptp_link_port_id ) );
+ }
+ }
+ DBGC ( port, "FCPORT %s logged in via a %s, with local ID "
+ "%s\n", port->name,
+ ( ( port->flags & FC_PORT_HAS_FABRIC ) ?
+ "fabric" : "point-to-point link" ),
+ fc_id_ntoa ( &port->port_id ) );
+ }
+
+ /* Log in to name server, if attached to a fabric */
+ if ( has_fabric && ! ( port->flags & FC_PORT_HAS_NS ) ) {
+
+ DBGC ( port, "FCPORT %s attempting login to name server\n",
+ port->name );
+
+ intf_restart ( &port->ns_plogi, -ECANCELED );
+ if ( ( rc = fc_els_plogi ( &port->ns_plogi, port,
+ &fc_gs_port_id ) ) != 0 ) {
+ DBGC ( port, "FCPORT %s could not initiate name "
+ "server PLOGI: %s\n",
+ port->name, strerror ( rc ) );
+ fc_port_logout ( port, rc );
+ return rc;
+ }
+ }
+
+ /* Record login */
+ fc_link_up ( &port->link );
+
+ /* Notify peers of link state change */
+ list_for_each_entry_safe ( peer, tmp, &fc_peers, list ) {
+ fc_peer_get ( peer );
+ fc_link_examine ( &peer->link );
+ fc_peer_put ( peer );
+ }
+
+ return 0;
+}
+
+/**
+ * Log out Fibre Channel port
+ *
+ * @v port Fibre Channel port
+ * @v rc Reason for logout
+ */
+void fc_port_logout ( struct fc_port *port, int rc ) {
+ struct fc_peer *peer;
+ struct fc_peer *tmp;
+
+ DBGC ( port, "FCPORT %s logged out: %s\n",
+ port->name, strerror ( rc ) );
+
+ /* Erase port details */
+ memset ( &port->port_id, 0, sizeof ( port->port_id ) );
+ port->flags = 0;
+
+ /* Record logout */
+ fc_link_err ( &port->link, rc );
+
+ /* Notify peers of link state change */
+ list_for_each_entry_safe ( peer, tmp, &fc_peers, list ) {
+ fc_peer_get ( peer );
+ fc_link_examine ( &peer->link );
+ fc_peer_put ( peer );
+ }
+}
+
+/**
+ * Handle FLOGI completion
+ *
+ * @v port Fibre Channel port
+ * @v rc Reason for completion
+ */
+static void fc_port_flogi_done ( struct fc_port *port, int rc ) {
+
+ intf_restart ( &port->flogi, rc );
+
+ if ( rc != 0 )
+ fc_port_logout ( port, rc );
+}
+
+/**
+ * Handle name server PLOGI completion
+ *
+ * @v port Fibre Channel port
+ * @v rc Reason for completion
+ */
+static void fc_port_ns_plogi_done ( struct fc_port *port, int rc ) {
+
+ intf_restart ( &port->ns_plogi, rc );
+
+ if ( rc == 0 ) {
+ port->flags |= FC_PORT_HAS_NS;
+ DBGC ( port, "FCPORT %s logged in to name server\n",
+ port->name );
+ } else {
+ DBGC ( port, "FCPORT %s could not log in to name server: %s\n",
+ port->name, strerror ( rc ) );
+ /* Absence of a name server is not a fatal error */
+ }
+}
+
+/**
+ * Examine Fibre Channel port link state
+ *
+ * @ link Fibre Channel link state monitor
+ */
+static void fc_port_examine ( struct fc_link_state *link ) {
+ struct fc_port *port = container_of ( link, struct fc_port, link );
+ int rc;
+
+ /* Do nothing if already logged in */
+ if ( fc_link_ok ( &port->link ) )
+ return;
+
+ DBGC ( port, "FCPORT %s attempting login\n", port->name );
+
+ /* Try to create FLOGI ELS */
+ intf_restart ( &port->flogi, -ECANCELED );
+ if ( ( rc = fc_els_flogi ( &port->flogi, port ) ) != 0 ) {
+ DBGC ( port, "FCPORT %s could not initiate FLOGI: %s\n",
+ port->name, strerror ( rc ) );
+ fc_port_logout ( port, rc );
+ return;
+ }
+}
+
+/**
+ * Handle change of flow control window
+ *
+ * @v port Fibre Channel port
+ */
+static void fc_port_window_changed ( struct fc_port *port ) {
+ size_t window;
+
+ /* Check if transport layer is ready */
+ window = xfer_window ( &port->transport );
+ if ( window > 0 ) {
+
+ /* Transport layer is ready. Start login if the link
+ * is not already up.
+ */
+ if ( ! fc_link_ok ( &port->link ) )
+ fc_link_start ( &port->link );
+
+ } else {
+
+ /* Transport layer is not ready. Log out port and
+ * wait for transport layer before attempting log in
+ * again.
+ */
+ fc_port_logout ( port, -ENOTCONN );
+ fc_link_stop ( &port->link );
+ }
+}
+
+/** Fibre Channel port transport interface operations */
+static struct interface_operation fc_port_transport_op[] = {
+ INTF_OP ( xfer_deliver, struct fc_port *, fc_port_deliver ),
+ INTF_OP ( xfer_window_changed, struct fc_port *,
+ fc_port_window_changed ),
+ INTF_OP ( intf_close, struct fc_port *, fc_port_close ),
+};
+
+/** Fibre Channel port transport interface descriptor */
+static struct interface_descriptor fc_port_transport_desc =
+ INTF_DESC ( struct fc_port, transport, fc_port_transport_op );
+
+/** Fibre Channel port FLOGI interface operations */
+static struct interface_operation fc_port_flogi_op[] = {
+ INTF_OP ( intf_close, struct fc_port *, fc_port_flogi_done ),
+};
+
+/** Fibre Channel port FLOGI interface descriptor */
+static struct interface_descriptor fc_port_flogi_desc =
+ INTF_DESC ( struct fc_port, flogi, fc_port_flogi_op );
+
+/** Fibre Channel port name server PLOGI interface operations */
+static struct interface_operation fc_port_ns_plogi_op[] = {
+ INTF_OP ( intf_close, struct fc_port *, fc_port_ns_plogi_done ),
+};
+
+/** Fibre Channel port name server PLOGI interface descriptor */
+static struct interface_descriptor fc_port_ns_plogi_desc =
+ INTF_DESC ( struct fc_port, ns_plogi, fc_port_ns_plogi_op );
+
+/**
+ * Create Fibre Channel port
+ *
+ * @v transport Transport interface
+ * @v node Fibre Channel node name
+ * @v port Fibre Channel port name
+ * @v name Symbolic port name
+ * @ret rc Return status code
+ */
+int fc_port_open ( struct interface *transport, const struct fc_name *node_wwn,
+ const struct fc_name *port_wwn, const char *name ) {
+ struct fc_port *port;
+
+ /* Allocate and initialise structure */
+ port = zalloc ( sizeof ( *port ) );
+ if ( ! port )
+ return -ENOMEM;
+ ref_init ( &port->refcnt, NULL );
+ intf_init ( &port->transport, &fc_port_transport_desc, &port->refcnt );
+ fc_link_init ( &port->link, fc_port_examine, &port->refcnt );
+ intf_init ( &port->flogi, &fc_port_flogi_desc, &port->refcnt );
+ intf_init ( &port->ns_plogi, &fc_port_ns_plogi_desc, &port->refcnt );
+ list_add_tail ( &port->list, &fc_ports );
+ INIT_LIST_HEAD ( &port->xchgs );
+ memcpy ( &port->node_wwn, node_wwn, sizeof ( port->node_wwn ) );
+ memcpy ( &port->port_wwn, port_wwn, sizeof ( port->port_wwn ) );
+ snprintf ( port->name, sizeof ( port->name ), "%s", name );
+
+ DBGC ( port, "FCPORT %s opened as %s",
+ port->name, fc_ntoa ( &port->node_wwn ) );
+ DBGC ( port, " port %s\n", fc_ntoa ( &port->port_wwn ) );
+
+ /* Attach to transport layer, mortalise self, and return */
+ intf_plug_plug ( &port->transport, transport );
+ ref_put ( &port->refcnt );
+ return 0;
+}
+
+/**
+ * Find Fibre Channel port by name
+ *
+ * @v name Fibre Channel port name
+ * @ret port Fibre Channel port, or NULL
+ */
+struct fc_port * fc_port_find ( const char *name ) {
+ struct fc_port *port;
+
+ list_for_each_entry ( port, &fc_ports, list ) {
+ if ( strcmp ( name, port->name ) == 0 )
+ return port;
+ }
+ return NULL;
+}
+
+/******************************************************************************
+ *
+ * Fibre Channel peers
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Close Fibre Channel peer
+ *
+ * @v peer Fibre Channel peer
+ * @v rc Reason for close
+ */
+static void fc_peer_close ( struct fc_peer *peer, int rc ) {
+
+ DBGC ( peer, "FCPEER %s closed: %s\n",
+ fc_ntoa ( &peer->port_wwn ) , strerror ( rc ) );
+
+ /* Sanity check */
+ assert ( list_empty ( &peer->ulps ) );
+
+ /* Stop link timer */
+ fc_link_stop ( &peer->link );
+
+ /* Shut down interfaces */
+ intf_shutdown ( &peer->plogi, rc );
+
+ /* Remove from list of peers */
+ list_del ( &peer->list );
+ INIT_LIST_HEAD ( &peer->list );
+}
+
+/**
+ * Increment Fibre Channel peer active usage count
+ *
+ * @v peer Fibre Channel peer
+ */
+static void fc_peer_increment ( struct fc_peer *peer ) {
+
+ /* Increment our usage count */
+ peer->usage++;
+}
+
+/**
+ * Decrement Fibre Channel peer active usage count
+ *
+ * @v peer Fibre Channel peer
+ */
+static void fc_peer_decrement ( struct fc_peer *peer ) {
+
+ /* Sanity check */
+ assert ( peer->usage > 0 );
+
+ /* Decrement our usage count and log out if we reach zero */
+ if ( --(peer->usage) == 0 )
+ fc_peer_logout ( peer, 0 );
+}
+
+/**
+ * Log in Fibre Channel peer
+ *
+ * @v peer Fibre Channel peer
+ * @v port Fibre Channel port
+ * @v port_id Port ID
+ * @ret rc Return status code
+ */
+int fc_peer_login ( struct fc_peer *peer, struct fc_port *port,
+ struct fc_port_id *port_id ) {
+ struct fc_ulp *ulp;
+ struct fc_ulp *tmp;
+
+ /* Perform implicit logout if logged in and details differ */
+ if ( fc_link_ok ( &peer->link ) &&
+ ( ( peer->port != port ) ||
+ ( memcmp ( &peer->port_id, port_id,
+ sizeof ( peer->port_id ) ) !=0 ) ) ) {
+ fc_peer_logout ( peer, 0 );
+ }
+
+ /* Log in, if applicable */
+ if ( ! fc_link_ok ( &peer->link ) ) {
+
+ /* Record peer details */
+ assert ( peer->port == NULL );
+ peer->port = fc_port_get ( port );
+ memcpy ( &peer->port_id, port_id, sizeof ( peer->port_id ) );
+ DBGC ( peer, "FCPEER %s logged in via %s as %s\n",
+ fc_ntoa ( &peer->port_wwn ), peer->port->name,
+ fc_id_ntoa ( &peer->port_id ) );
+
+ /* Add login reference */
+ fc_peer_get ( peer );
+ }
+
+ /* Record login */
+ fc_link_up ( &peer->link );
+
+ /* Notify ULPs of link state change */
+ list_for_each_entry_safe ( ulp, tmp, &peer->ulps, list ) {
+ fc_ulp_get ( ulp );
+ fc_link_examine ( &ulp->link );
+ fc_ulp_put ( ulp );
+ }
+
+ return 0;
+}
+
+/**
+ * Log out Fibre Channel peer
+ *
+ * @v peer Fibre Channel peer
+ * @v rc Reason for logout
+ */
+void fc_peer_logout ( struct fc_peer *peer, int rc ) {
+ struct fc_ulp *ulp;
+ struct fc_ulp *tmp;
+
+ DBGC ( peer, "FCPEER %s logged out: %s\n",
+ fc_ntoa ( &peer->port_wwn ), strerror ( rc ) );
+
+ /* Drop login reference, if applicable */
+ if ( fc_link_ok ( &peer->link ) )
+ fc_peer_put ( peer );
+
+ /* Erase peer details */
+ fc_port_put ( peer->port );
+ peer->port = NULL;
+
+ /* Record logout */
+ fc_link_err ( &peer->link, rc );
+
+ /* Notify ULPs of link state change */
+ list_for_each_entry_safe ( ulp, tmp, &peer->ulps, list ) {
+ fc_ulp_get ( ulp );
+ fc_link_examine ( &ulp->link );
+ fc_ulp_put ( ulp );
+ }
+
+ /* Close peer if there are no active users */
+ if ( peer->usage == 0 )
+ fc_peer_close ( peer, rc );
+}
+
+/**
+ * Handle PLOGI completion
+ *
+ * @v peer Fibre Channel peer
+ * @v rc Reason for completion
+ */
+static void fc_peer_plogi_done ( struct fc_peer *peer, int rc ) {
+
+ intf_restart ( &peer->plogi, rc );
+
+ if ( rc != 0 )
+ fc_peer_logout ( peer, rc );
+}
+
+/**
+ * Initiate PLOGI
+ *
+ * @v peer Fibre Channel peer
+ * @v port Fibre Channel port
+ * @v peer_port_id Peer port ID
+ * @ret rc Return status code
+ */
+static int fc_peer_plogi ( struct fc_peer *peer, struct fc_port *port,
+ struct fc_port_id *peer_port_id ) {
+ int rc;
+
+ /* Try to create PLOGI ELS */
+ intf_restart ( &peer->plogi, -ECANCELED );
+ if ( ( rc = fc_els_plogi ( &peer->plogi, port, peer_port_id ) ) != 0 ) {
+ DBGC ( peer, "FCPEER %s could not initiate PLOGI: %s\n",
+ fc_ntoa ( &peer->port_wwn ), strerror ( rc ) );
+ fc_peer_logout ( peer, rc );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Examine Fibre Channel peer link state
+ *
+ * @ link Fibre Channel link state monitor
+ */
+static void fc_peer_examine ( struct fc_link_state *link ) {
+ struct fc_peer *peer = container_of ( link, struct fc_peer, link );
+ struct fc_port *port;
+ int rc;
+
+ /* Check to see if underlying port link has gone down */
+ if ( peer->port && ( ! fc_link_ok ( &peer->port->link ) ) ) {
+ fc_peer_logout ( peer, -ENOTCONN );
+ return;
+ }
+
+ /* Do nothing if already logged in */
+ if ( fc_link_ok ( &peer->link ) )
+ return;
+
+ DBGC ( peer, "FCPEER %s attempting login\n",
+ fc_ntoa ( &peer->port_wwn ) );
+
+ /* Sanity check */
+ assert ( peer->port == NULL );
+
+ /* First, look for a port with the peer attached via a
+ * point-to-point link.
+ */
+ list_for_each_entry ( port, &fc_ports, list ) {
+ if ( fc_link_ok ( &port->link ) &&
+ ( ! ( port->flags & FC_PORT_HAS_FABRIC ) ) &&
+ ( memcmp ( &peer->port_wwn, &port->link_port_wwn,
+ sizeof ( peer->port_wwn ) ) == 0 ) ) {
+ /* Use this peer port ID, and stop looking */
+ fc_peer_plogi ( peer, port, &port->ptp_link_port_id );
+ return;
+ }
+ }
+
+ /* If the peer is not directly attached, try initiating a name
+ * server lookup on any suitable ports.
+ */
+ list_for_each_entry ( port, &fc_ports, list ) {
+ if ( fc_link_ok ( &port->link ) &&
+ ( port->flags & FC_PORT_HAS_FABRIC ) &&
+ ( port->flags & FC_PORT_HAS_NS ) ) {
+ if ( ( rc = fc_ns_query ( peer, port,
+ fc_peer_plogi ) ) != 0 ) {
+ DBGC ( peer, "FCPEER %s could not attempt "
+ "name server lookup on %s: %s\n",
+ fc_ntoa ( &peer->port_wwn ), port->name,
+ strerror ( rc ) );
+ /* Non-fatal */
+ }
+ }
+ }
+}
+
+/** Fibre Channel peer PLOGI interface operations */
+static struct interface_operation fc_peer_plogi_op[] = {
+ INTF_OP ( intf_close, struct fc_peer *, fc_peer_plogi_done ),
+};
+
+/** Fibre Channel peer PLOGI interface descriptor */
+static struct interface_descriptor fc_peer_plogi_desc =
+ INTF_DESC ( struct fc_peer, plogi, fc_peer_plogi_op );
+
+/**
+ * Create Fibre Channel peer
+ *
+ * @v port_wwn Node name
+ * @ret peer Fibre Channel peer, or NULL
+ */
+static struct fc_peer * fc_peer_create ( const struct fc_name *port_wwn ) {
+ struct fc_peer *peer;
+
+ /* Allocate and initialise structure */
+ peer = zalloc ( sizeof ( *peer ) );
+ if ( ! peer )
+ return NULL;
+ ref_init ( &peer->refcnt, NULL );
+ fc_link_init ( &peer->link, fc_peer_examine, &peer->refcnt );
+ intf_init ( &peer->plogi, &fc_peer_plogi_desc, &peer->refcnt );
+ list_add_tail ( &peer->list, &fc_peers );
+ memcpy ( &peer->port_wwn, port_wwn, sizeof ( peer->port_wwn ) );
+ INIT_LIST_HEAD ( &peer->ulps );
+
+ /* Start link monitor */
+ fc_link_start ( &peer->link );
+
+ DBGC ( peer, "FCPEER %s created\n", fc_ntoa ( &peer->port_wwn ) );
+ return peer;
+}
+
+/**
+ * Get Fibre Channel peer by node name
+ *
+ * @v port_wwn Node name
+ * @ret peer Fibre Channel peer, or NULL
+ */
+struct fc_peer * fc_peer_get_wwn ( const struct fc_name *port_wwn ) {
+ struct fc_peer *peer;
+
+ /* Look for an existing peer */
+ list_for_each_entry ( peer, &fc_peers, list ) {
+ if ( memcmp ( &peer->port_wwn, port_wwn,
+ sizeof ( peer->port_wwn ) ) == 0 )
+ return fc_peer_get ( peer );
+ }
+
+ /* Create a new peer */
+ peer = fc_peer_create ( port_wwn );
+ if ( ! peer )
+ return NULL;
+
+ return peer;
+}
+
+/**
+ * Get Fibre Channel peer by port ID
+ *
+ * @v port Fibre Channel port
+ * @v peer_port_id Peer port ID
+ * @ret peer Fibre Channel peer, or NULL
+ */
+struct fc_peer * fc_peer_get_port_id ( struct fc_port *port,
+ const struct fc_port_id *peer_port_id ){
+ struct fc_peer *peer;
+
+ /* Look for an existing peer */
+ list_for_each_entry ( peer, &fc_peers, list ) {
+ if ( ( peer->port == port ) &&
+ ( memcmp ( &peer->port_id, peer_port_id,
+ sizeof ( peer->port_id ) ) == 0 ) )
+ return fc_peer_get ( peer );
+ }
+
+ /* Cannot create a new peer, since we have no port name to use */
+ return NULL;
+}
+
+/******************************************************************************
+ *
+ * Fibre Channel upper-layer protocols
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Free Fibre Channel upper-layer protocol
+ *
+ * @v refcnt Reference count
+ */
+static void fc_ulp_free ( struct refcnt *refcnt ) {
+ struct fc_ulp *ulp = container_of ( refcnt, struct fc_ulp, refcnt );
+
+ fc_peer_put ( ulp->peer );
+ free ( ulp );
+}
+
+/**
+ * Close Fibre Channel upper-layer protocol
+ *
+ * @v ulp Fibre Channel upper-layer protocol
+ * @v rc Reason for close
+ */
+static void fc_ulp_close ( struct fc_ulp *ulp, int rc ) {
+
+ DBGC ( ulp, "FCULP %s/%02x closed: %s\n",
+ fc_ntoa ( &ulp->peer->port_wwn ), ulp->type, strerror ( rc ) );
+
+ /* Sanity check */
+ assert ( list_empty ( &ulp->users ) );
+
+ /* Stop link monitor */
+ fc_link_stop ( &ulp->link );
+
+ /* Shut down interfaces */
+ intf_shutdown ( &ulp->prli, rc );
+
+ /* Remove from list of ULPs */
+ list_del ( &ulp->list );
+ INIT_LIST_HEAD ( &ulp->list );
+}
+
+/**
+ * Attach Fibre Channel upper-layer protocol user
+ *
+ * @v ulp Fibre Channel upper-layer protocol
+ * @v user Fibre Channel upper-layer protocol user
+ */
+void fc_ulp_attach ( struct fc_ulp *ulp, struct fc_ulp_user *user ) {
+
+ /* Sanity check */
+ assert ( user->ulp == NULL );
+
+ /* Increment peer's usage count */
+ fc_peer_increment ( ulp->peer );
+
+ /* Attach user */
+ user->ulp = fc_ulp_get ( ulp );
+ list_add ( &user->list, &ulp->users );
+}
+
+/**
+ * Detach Fibre Channel upper-layer protocol user
+ *
+ * @v user Fibre Channel upper-layer protocol user
+ */
+void fc_ulp_detach ( struct fc_ulp_user *user ) {
+ struct fc_ulp *ulp = user->ulp;
+
+ /* Do nothing if not attached */
+ if ( ! ulp )
+ return;
+
+ /* Sanity checks */
+ list_check_contains_entry ( user, &ulp->users, list );
+
+ /* Detach user and log out if no users remain */
+ list_del ( &user->list );
+ if ( list_empty ( &ulp->users ) )
+ fc_ulp_logout ( ulp, 0 );
+
+ /* Decrement our peer's usage count */
+ fc_peer_decrement ( ulp->peer );
+
+ /* Drop reference */
+ user->ulp = NULL;
+ fc_ulp_put ( ulp );
+}
+
+/**
+ * Log in Fibre Channel upper-layer protocol
+ *
+ * @v ulp Fibre Channel upper-layer protocol
+ * @v param Service parameters
+ * @v param_len Length of service parameters
+ * @v originated Login was originated by us
+ * @ret rc Return status code
+ */
+int fc_ulp_login ( struct fc_ulp *ulp, const void *param, size_t param_len,
+ int originated ) {
+ struct fc_ulp_user *user;
+ struct fc_ulp_user *tmp;
+
+ /* Perform implicit logout if logged in and service parameters differ */
+ if ( fc_link_ok ( &ulp->link ) &&
+ ( ( ulp->param_len != param_len ) ||
+ ( memcmp ( ulp->param, param, ulp->param_len ) != 0 ) ) ) {
+ fc_ulp_logout ( ulp, 0 );
+ }
+
+ /* Work around a bug in some versions of the Linux Fibre
+ * Channel stack, which fail to fully initialise image pairs
+ * established via a PRLI originated by the Linux stack
+ * itself.
+ */
+ if ( originated )
+ ulp->flags |= FC_ULP_ORIGINATED_LOGIN_OK;
+ if ( ! ( ulp->flags & FC_ULP_ORIGINATED_LOGIN_OK ) ) {
+ DBGC ( ulp, "FCULP %s/%02x sending extra PRLI to work around "
+ "Linux bug\n",
+ fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
+ fc_link_stop ( &ulp->link );
+ fc_link_start ( &ulp->link );
+ return 0;
+ }
+
+ /* Log in, if applicable */
+ if ( ! fc_link_ok ( &ulp->link ) ) {
+
+ /* Record service parameters */
+ assert ( ulp->param == NULL );
+ assert ( ulp->param_len == 0 );
+ ulp->param = malloc ( param_len );
+ if ( ! ulp->param ) {
+ DBGC ( ulp, "FCULP %s/%02x could not record "
+ "parameters\n",
+ fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
+ return -ENOMEM;
+ }
+ memcpy ( ulp->param, param, param_len );
+ ulp->param_len = param_len;
+ DBGC ( ulp, "FCULP %s/%02x logged in with parameters:\n",
+ fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
+ DBGC_HDA ( ulp, 0, ulp->param, ulp->param_len );
+
+ /* Add login reference */
+ fc_ulp_get ( ulp );
+ }
+
+ /* Record login */
+ fc_link_up ( &ulp->link );
+
+ /* Notify users of link state change */
+ list_for_each_entry_safe ( user, tmp, &ulp->users, list ) {
+ fc_ulp_user_get ( user );
+ user->examine ( user );
+ fc_ulp_user_put ( user );
+ }
+
+ return 0;
+}
+
+/**
+ * Log out Fibre Channel upper-layer protocol
+ *
+ * @v ulp Fibre Channel upper-layer protocol
+ * @v rc Reason for logout
+ */
+void fc_ulp_logout ( struct fc_ulp *ulp, int rc ) {
+ struct fc_ulp_user *user;
+ struct fc_ulp_user *tmp;
+
+ DBGC ( ulp, "FCULP %s/%02x logged out: %s\n",
+ fc_ntoa ( &ulp->peer->port_wwn ), ulp->type, strerror ( rc ) );
+
+ /* Drop login reference, if applicable */
+ if ( fc_link_ok ( &ulp->link ) )
+ fc_ulp_put ( ulp );
+
+ /* Discard service parameters */
+ free ( ulp->param );
+ ulp->param = NULL;
+ ulp->param_len = 0;
+ ulp->flags = 0;
+
+ /* Record logout */
+ fc_link_err ( &ulp->link, rc );
+
+ /* Notify users of link state change */
+ list_for_each_entry_safe ( user, tmp, &ulp->users, list ) {
+ fc_ulp_user_get ( user );
+ user->examine ( user );
+ fc_ulp_user_put ( user );
+ }
+
+ /* Close ULP if there are no clients attached */
+ if ( list_empty ( &ulp->users ) )
+ fc_ulp_close ( ulp, rc );
+}
+
+/**
+ * Handle PRLI completion
+ *
+ * @v ulp Fibre Channel upper-layer protocol
+ * @v rc Reason for completion
+ */
+static void fc_ulp_prli_done ( struct fc_ulp *ulp, int rc ) {
+
+ intf_restart ( &ulp->prli, rc );
+
+ if ( rc != 0 )
+ fc_ulp_logout ( ulp, rc );
+}
+
+/**
+ * Examine Fibre Channel upper-layer protocol link state
+ *
+ * @ link Fibre Channel link state monitor
+ */
+static void fc_ulp_examine ( struct fc_link_state *link ) {
+ struct fc_ulp *ulp = container_of ( link, struct fc_ulp, link );
+ int rc;
+
+ /* Check to see if underlying peer link has gone down */
+ if ( ! fc_link_ok ( &ulp->peer->link ) ) {
+ fc_ulp_logout ( ulp, -ENOTCONN );
+ return;
+ }
+
+ /* Do nothing if already logged in */
+ if ( fc_link_ok ( &ulp->link ) &&
+ ( ulp->flags & FC_ULP_ORIGINATED_LOGIN_OK ) )
+ return;
+
+ DBGC ( ulp, "FCULP %s/%02x attempting login\n",
+ fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
+
+ /* Try to create PRLI ELS */
+ intf_restart ( &ulp->prli, -ECANCELED );
+ if ( ( rc = fc_els_prli ( &ulp->prli, ulp->peer->port,
+ &ulp->peer->port_id, ulp->type ) ) != 0 ) {
+ DBGC ( ulp, "FCULP %s/%02x could not initiate PRLI: %s\n",
+ fc_ntoa ( &ulp->peer->port_wwn ), ulp->type,
+ strerror ( rc ) );
+ fc_ulp_logout ( ulp, rc );
+ return;
+ }
+}
+
+/** Fibre Channel upper-layer protocol PRLI interface operations */
+static struct interface_operation fc_ulp_prli_op[] = {
+ INTF_OP ( intf_close, struct fc_ulp *, fc_ulp_prli_done ),
+};
+
+/** Fibre Channel upper-layer protocol PRLI interface descriptor */
+static struct interface_descriptor fc_ulp_prli_desc =
+ INTF_DESC ( struct fc_ulp, prli, fc_ulp_prli_op );
+
+/**
+ * Create Fibre Channel upper-layer protocl
+ *
+ * @v peer Fibre Channel peer
+ * @v type Type
+ * @ret ulp Fibre Channel upper-layer protocol, or NULL
+ */
+static struct fc_ulp * fc_ulp_create ( struct fc_peer *peer,
+ unsigned int type ) {
+ struct fc_ulp *ulp;
+
+ /* Allocate and initialise structure */
+ ulp = zalloc ( sizeof ( *ulp ) );
+ if ( ! ulp )
+ return NULL;
+ ref_init ( &ulp->refcnt, fc_ulp_free );
+ fc_link_init ( &ulp->link, fc_ulp_examine, &ulp->refcnt );
+ intf_init ( &ulp->prli, &fc_ulp_prli_desc, &ulp->refcnt );
+ ulp->peer = fc_peer_get ( peer );
+ list_add_tail ( &ulp->list, &peer->ulps );
+ ulp->type = type;
+ INIT_LIST_HEAD ( &ulp->users );
+
+ /* Start link state monitor */
+ fc_link_start ( &ulp->link );
+
+ DBGC ( ulp, "FCULP %s/%02x created\n",
+ fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
+ return ulp;
+}
+
+/**
+ * Get Fibre Channel upper-layer protocol by peer and type
+ *
+ * @v peer Fibre Channel peer
+ * @v type Type
+ * @ret ulp Fibre Channel upper-layer protocol, or NULL
+ */
+static struct fc_ulp * fc_ulp_get_type ( struct fc_peer *peer,
+ unsigned int type ) {
+ struct fc_ulp *ulp;
+
+ /* Look for an existing ULP */
+ list_for_each_entry ( ulp, &peer->ulps, list ) {
+ if ( ulp->type == type )
+ return fc_ulp_get ( ulp );
+ }
+
+ /* Create a new ULP */
+ ulp = fc_ulp_create ( peer, type );
+ if ( ! ulp )
+ return NULL;
+
+ return ulp;
+}
+
+/**
+ * Get Fibre Channel upper-layer protocol by port name and type
+ *
+ * @v port_wwn Port name
+ * @v type Type
+ * @ret ulp Fibre Channel upper-layer protocol, or NULL
+ */
+struct fc_ulp * fc_ulp_get_wwn_type ( const struct fc_name *port_wwn,
+ unsigned int type ) {
+ struct fc_ulp *ulp;
+ struct fc_peer *peer;
+
+ /* Get peer */
+ peer = fc_peer_get_wwn ( port_wwn );
+ if ( ! peer )
+ goto err_peer_get_wwn;
+
+ /* Get ULP */
+ ulp = fc_ulp_get_type ( peer, type );
+ if ( ! ulp )
+ goto err_ulp_get_type;
+
+ /* Drop temporary reference to peer */
+ fc_peer_put ( peer );
+
+ return ulp;
+
+ fc_ulp_put ( ulp );
+ err_ulp_get_type:
+ fc_peer_put ( peer );
+ err_peer_get_wwn:
+ return NULL;
+}
+
+/**
+ * Get Fibre Channel upper-layer protocol by port ID and type
+ *
+ * @v port Fibre Channel port
+ * @v peer_port_id Peer port ID
+ * @v type Type
+ * @ret ulp Fibre Channel upper-layer protocol, or NULL
+ */
+struct fc_ulp * fc_ulp_get_port_id_type ( struct fc_port *port,
+ const struct fc_port_id *peer_port_id,
+ unsigned int type ) {
+ struct fc_ulp *ulp;
+ struct fc_peer *peer;
+
+ /* Get peer */
+ peer = fc_peer_get_port_id ( port, peer_port_id );
+ if ( ! peer )
+ goto err_peer_get_wwn;
+
+ /* Get ULP */
+ ulp = fc_ulp_get_type ( peer, type );
+ if ( ! ulp )
+ goto err_ulp_get_type;
+
+ /* Drop temporary reference to peer */
+ fc_peer_put ( peer );
+
+ return ulp;
+
+ fc_ulp_put ( ulp );
+ err_ulp_get_type:
+ fc_peer_put ( peer );
+ err_peer_get_wwn:
+ return NULL;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/fcels.c b/src/VBox/Devices/PC/ipxe/src/net/fcels.c
new file mode 100644
index 00000000..2106cbd5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/fcels.c
@@ -0,0 +1,1338 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/interface.h>
+#include <ipxe/xfer.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/process.h>
+#include <ipxe/fc.h>
+#include <ipxe/fcels.h>
+
+/** @file
+ *
+ * Fibre Channel Extended Link Services
+ *
+ */
+
+/** Fibre Channel ELS transaction debug message format */
+#define FCELS_FMT "FCELS %s %s %s %s"
+
+/** Fibre Channel ELS transaction debug message arguments */
+#define FCELS_ARGS( els ) \
+ (els)->port->name, \
+ ( (els)->handler ? (els)->handler->name : "unknown ELS" ), \
+ ( fc_els_is_request ( els ) ? "to" : "from" ), \
+ fc_id_ntoa ( &(els)->peer_port_id )
+
+struct fc_els_handler fc_els_unknown_handler __fc_els_handler;
+
+/**
+ * Free Fibre Channel ELS transaction
+ *
+ * @v refcnt Reference count
+ */
+static void fc_els_free ( struct refcnt *refcnt ) {
+ struct fc_els *els = container_of ( refcnt, struct fc_els, refcnt );
+
+ assert ( ! process_running ( &els->process ) );
+ fc_port_put ( els->port );
+ free ( els );
+}
+
+/**
+ * Close Fibre Channel ELS transaction
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v rc Reason for close
+ */
+static void fc_els_close ( struct fc_els *els, int rc ) {
+
+ if ( rc != 0 ) {
+ DBGC ( els, FCELS_FMT " complete (%s)\n",
+ FCELS_ARGS ( els ), strerror ( rc ) );
+ }
+
+ /* Stop process */
+ process_del ( &els->process );
+
+ /* Shut down interfaces */
+ intf_shutdown ( &els->xchg, rc );
+ intf_shutdown ( &els->job, rc );
+}
+
+/**
+ * Detect Fibre Channel ELS frame handler
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v command ELS command code
+ * @ret handler ELS handler, or NULL
+ */
+static struct fc_els_handler * fc_els_detect ( struct fc_els *els,
+ const void *data,
+ size_t len ) {
+ const struct fc_els_frame_common *frame = data;
+ struct fc_els_handler *handler;
+ int rc;
+
+ /* Sanity check */
+ if ( len < sizeof ( *frame ) )
+ return NULL;
+
+ /* Try each handler in turn */
+ for_each_table_entry ( handler, FC_ELS_HANDLERS ) {
+ if ( ( rc = handler->detect ( els, data, len ) ) == 0 )
+ return handler;
+ }
+
+ return NULL;
+}
+
+/**
+ * Transmit Fibre Channel ELS frame
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data Data to transmit
+ * @v len Length of data
+ * @ret rc Return status code
+ */
+int fc_els_tx ( struct fc_els *els, const void *data, size_t len ) {
+ struct xfer_metadata meta;
+ struct sockaddr_fc dest;
+ int rc;
+
+ DBGC2 ( els, FCELS_FMT " transmitting:\n", FCELS_ARGS ( els ) );
+ DBGC2_HDA ( els, 0, data, len );
+
+ /* Construct metadata */
+ memset ( &meta, 0, sizeof ( meta ) );
+ meta.flags = ( fc_els_is_request ( els ) ?
+ XFER_FL_OVER : ( XFER_FL_RESPONSE | XFER_FL_OUT ) );
+ meta.dest = fc_fill_sockaddr ( &dest, &els->peer_port_id );
+
+ /* Transmit frame */
+ if ( ( rc = xfer_deliver_raw_meta ( &els->xchg, data, len,
+ &meta ) ) != 0 ) {
+ DBGC ( els, FCELS_FMT " could not deliver frame: %s\n",
+ FCELS_ARGS ( els ), strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Receive Fibre Channel ELS frame
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int fc_els_rx ( struct fc_els *els,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct fc_els_frame_common *frame = iobuf->data;
+ struct sockaddr_fc *src = ( ( struct sockaddr_fc * ) meta->src );
+ struct sockaddr_fc *dest = ( ( struct sockaddr_fc * ) meta->dest );
+ size_t len = iob_len ( iobuf );
+ int rc;
+
+ /* Sanity check */
+ if ( len < sizeof ( *frame ) ) {
+ DBGC ( els, FCELS_FMT " received underlength frame:\n",
+ FCELS_ARGS ( els ) );
+ DBGC_HDA ( els, 0, frame, len );
+ rc = -EINVAL;
+ goto done;
+ }
+ if ( ! src ) {
+ DBGC ( els, FCELS_FMT " received frame missing source "
+ "address:\n", FCELS_ARGS ( els ) );
+ rc = -EINVAL;
+ goto done;
+ }
+ if ( ! dest ) {
+ DBGC ( els, FCELS_FMT " received frame missing destination "
+ "address:\n", FCELS_ARGS ( els ) );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Check for rejection responses */
+ if ( fc_els_is_request ( els ) &&
+ ( frame->command != FC_ELS_LS_ACC ) ) {
+ DBGC ( els, FCELS_FMT " rejected:\n", FCELS_ARGS ( els ) );
+ DBGC_HDA ( els, 0, frame, len );
+ rc = -EACCES;
+ goto done;
+ }
+
+ /* Update port IDs */
+ memcpy ( &els->port_id, &dest->sfc_port_id, sizeof ( els->port_id ) );
+ memcpy ( &els->peer_port_id, &src->sfc_port_id,
+ sizeof ( els->peer_port_id ) );
+
+ /* Determine handler, if necessary */
+ if ( ! els->handler )
+ els->handler = fc_els_detect ( els, frame, len );
+ if ( ! els->handler )
+ els->handler = &fc_els_unknown_handler;
+
+ DBGC2 ( els, FCELS_FMT " received:\n", FCELS_ARGS ( els ) );
+ DBGC2_HDA ( els, 0, frame, len );
+
+ /* Handle received frame */
+ if ( ( rc = els->handler->rx ( els, frame, len ) ) != 0 ) {
+ DBGC ( els, FCELS_FMT " could not handle received frame: "
+ "%s\n", FCELS_ARGS ( els ), strerror ( rc ) );
+ DBGC_HDA ( els, 0, frame, len );
+ goto done;
+ }
+
+ done:
+ /* Free I/O buffer */
+ free_iob ( iobuf );
+
+ /* Close transaction */
+ fc_els_close ( els, rc );
+
+ return rc;
+}
+
+/** Fibre Channel ELS exchange interface operations */
+static struct interface_operation fc_els_xchg_op[] = {
+ INTF_OP ( xfer_deliver, struct fc_els *, fc_els_rx ),
+ INTF_OP ( intf_close, struct fc_els *, fc_els_close ),
+};
+
+/** Fibre Channel ELS exchange interface descriptor */
+static struct interface_descriptor fc_els_xchg_desc =
+ INTF_DESC ( struct fc_els, xchg, fc_els_xchg_op );
+
+/** Fibre Channel ELS job control interface operations */
+static struct interface_operation fc_els_job_op[] = {
+ INTF_OP ( intf_close, struct fc_els *, fc_els_close ),
+};
+
+/** Fibre Channel ELS job control interface descriptor */
+static struct interface_descriptor fc_els_job_desc =
+ INTF_DESC ( struct fc_els, job, fc_els_job_op );
+
+/**
+ * Fibre Channel ELS process
+ *
+ * @v els Fibre Channel ELS transaction
+ */
+static void fc_els_step ( struct fc_els *els ) {
+ int xchg_id;
+ int rc;
+
+ /* Sanity check */
+ assert ( fc_els_is_request ( els ) );
+
+ /* Create exchange */
+ if ( ( xchg_id = fc_xchg_originate ( &els->xchg, els->port,
+ &els->peer_port_id,
+ FC_TYPE_ELS ) ) < 0 ) {
+ rc = xchg_id;
+ DBGC ( els, FCELS_FMT " could not create exchange: %s\n",
+ FCELS_ARGS ( els ), strerror ( rc ) );
+ fc_els_close ( els, rc );
+ return;
+ }
+
+ /* Transmit request */
+ if ( ( rc = els->handler->tx ( els ) ) != 0 ) {
+ DBGC ( els, FCELS_FMT " could not transmit request: %s\n",
+ FCELS_ARGS ( els ), strerror ( rc ) );
+ fc_els_close ( els, rc );
+ return;
+ }
+}
+
+/** Fibre Channel ELS process descriptor */
+static struct process_descriptor fc_els_process_desc =
+ PROC_DESC_ONCE ( struct fc_els, process, fc_els_step );
+
+/**
+ * Create ELS transaction
+ *
+ * @v port Fibre Channel port
+ * @v port_id Local port ID
+ * @v peer_port_id Peer port ID
+ * @ret els Fibre Channel ELS transaction, or NULL
+ */
+static struct fc_els * fc_els_create ( struct fc_port *port,
+ struct fc_port_id *port_id,
+ struct fc_port_id *peer_port_id ) {
+ struct fc_els *els;
+
+ /* Allocate and initialise structure */
+ els = zalloc ( sizeof ( *els ) );
+ if ( ! els )
+ return NULL;
+ ref_init ( &els->refcnt, fc_els_free );
+ intf_init ( &els->job, &fc_els_job_desc, &els->refcnt );
+ intf_init ( &els->xchg, &fc_els_xchg_desc, &els->refcnt );
+ process_init_stopped ( &els->process, &fc_els_process_desc,
+ &els->refcnt );
+ els->port = fc_port_get ( port );
+ memcpy ( &els->port_id, port_id, sizeof ( els->port_id ) );
+ memcpy ( &els->peer_port_id, peer_port_id,
+ sizeof ( els->peer_port_id ) );
+ return els;
+}
+
+/**
+ * Create ELS request
+ *
+ * @v job Parent job-control interface
+ * @v port Fibre Channel port
+ * @v peer_port_id Peer port ID
+ * @v handler ELS handler
+ * @ret rc Return status code
+ */
+int fc_els_request ( struct interface *job, struct fc_port *port,
+ struct fc_port_id *peer_port_id,
+ struct fc_els_handler *handler ) {
+ struct fc_els *els;
+
+ /* Allocate and initialise structure */
+ els = fc_els_create ( port, &port->port_id, peer_port_id );
+ if ( ! els )
+ return -ENOMEM;
+ els->handler = handler;
+ els->flags = FC_ELS_REQUEST;
+ process_add ( &els->process );
+
+ /* Attach to parent job interface, mortalise self, and return */
+ intf_plug_plug ( &els->job, job );
+ ref_put ( &els->refcnt );
+ return 0;
+}
+
+/**
+ * Create ELS response
+ *
+ * @v xchg Exchange interface
+ * @v port Fibre Channel port
+ * @v port_id Local port ID
+ * @v peer_port_id Peer port ID
+ * @ret rc Return status code
+ */
+static int fc_els_respond ( struct interface *xchg, struct fc_port *port,
+ struct fc_port_id *port_id,
+ struct fc_port_id *peer_port_id ) {
+ struct fc_els *els;
+
+ /* Allocate and initialise structure */
+ els = fc_els_create ( port, port_id, peer_port_id );
+ if ( ! els )
+ return -ENOMEM;
+
+ /* Attach to exchange interface, mortalise self, and return */
+ intf_plug_plug ( &els->xchg, xchg );
+ ref_put ( &els->refcnt );
+ return 0;
+}
+
+/** Fibre Channel ELS responder */
+struct fc_responder fc_els_responder __fc_responder = {
+ .type = FC_TYPE_ELS,
+ .respond = fc_els_respond,
+};
+
+/******************************************************************************
+ *
+ * Unknown ELS handler
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Transmit unknown ELS request
+ *
+ * @v els Fibre Channel ELS transaction
+ * @ret rc Return status code
+ */
+static int fc_els_unknown_tx ( struct fc_els *els __unused ) {
+ return -ENOTSUP;
+}
+
+/**
+ * Transmit unknown ELS response
+ *
+ * @v els Fibre Channel ELS transaction
+ * @ret rc Return status code
+ */
+static int fc_els_unknown_tx_response ( struct fc_els *els ) {
+ struct fc_ls_rjt_frame ls_rjt;
+
+ /* Construct LS_RJT */
+ memset ( &ls_rjt, 0, sizeof ( ls_rjt ) );
+ ls_rjt.command = FC_ELS_LS_RJT;
+ ls_rjt.reason = FC_ELS_RJT_UNSUPPORTED;
+
+ /* Transmit LS_RJT */
+ return fc_els_tx ( els, &ls_rjt, sizeof ( ls_rjt ) );
+}
+
+/**
+ * Receive unknown ELS
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_unknown_rx ( struct fc_els *els, void *data, size_t len ) {
+ int rc;
+
+ DBGC ( els, FCELS_FMT ":\n", FCELS_ARGS ( els ) );
+ DBGC_HDA ( els, 0, data, len );
+
+ /* Transmit response, if applicable */
+ if ( ! fc_els_is_request ( els ) ) {
+ if ( ( rc = fc_els_unknown_tx_response ( els ) ) != 0 )
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Detect unknown ELS
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_unknown_detect ( struct fc_els *els __unused,
+ const void *data __unused,
+ size_t len __unused ) {
+ return -ENOTSUP;
+}
+
+/** Unknown ELS handler */
+struct fc_els_handler fc_els_unknown_handler __fc_els_handler = {
+ .name = "UNKNOWN",
+ .tx = fc_els_unknown_tx,
+ .rx = fc_els_unknown_rx,
+ .detect = fc_els_unknown_detect,
+};
+
+/******************************************************************************
+ *
+ * FLOGI
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Transmit FLOGI
+ *
+ * @v els Fibre Channel ELS transaction
+ * @ret rc Return status code
+ */
+static int fc_els_flogi_tx ( struct fc_els *els ) {
+ struct fc_login_frame flogi;
+
+ /* Construct FLOGI */
+ memset ( &flogi, 0, sizeof ( flogi ) );
+ flogi.command = fc_els_tx_command ( els, FC_ELS_FLOGI );
+ flogi.common.version = htons ( FC_LOGIN_VERSION );
+ flogi.common.credit = htons ( FC_LOGIN_DEFAULT_B2B );
+ flogi.common.flags = htons ( FC_LOGIN_CONTINUOUS_OFFSET );
+ flogi.common.mtu = htons ( FC_LOGIN_DEFAULT_MTU );
+ memcpy ( &flogi.port_wwn, &els->port->port_wwn,
+ sizeof ( flogi.port_wwn ) );
+ memcpy ( &flogi.node_wwn, &els->port->node_wwn,
+ sizeof ( flogi.node_wwn ) );
+ flogi.class3.flags = htons ( FC_LOGIN_CLASS_VALID |
+ FC_LOGIN_CLASS_SEQUENTIAL );
+
+ /* Transmit FLOGI */
+ return fc_els_tx ( els, &flogi, sizeof ( flogi ) );
+}
+
+/**
+ * Receive FLOGI
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_flogi_rx ( struct fc_els *els, void *data, size_t len ) {
+ struct fc_login_frame *flogi = data;
+ int has_fabric;
+ int rc;
+
+ /* Sanity check */
+ if ( len < sizeof ( *flogi ) ) {
+ DBGC ( els, FCELS_FMT " received underlength frame:\n",
+ FCELS_ARGS ( els ) );
+ DBGC_HDA ( els, 0, data, len );
+ return -EINVAL;
+ }
+
+ /* Extract parameters */
+ has_fabric = ( flogi->common.flags & htons ( FC_LOGIN_F_PORT ) );
+ DBGC ( els, FCELS_FMT " has node %s\n", FCELS_ARGS ( els ),
+ fc_ntoa ( &flogi->node_wwn ) );
+ DBGC ( els, FCELS_FMT " has port %s\n", FCELS_ARGS ( els ),
+ fc_ntoa ( &flogi->port_wwn ) );
+ if ( has_fabric ) {
+ DBGC ( els, FCELS_FMT " has fabric with", FCELS_ARGS ( els ) );
+ DBGC ( els, " local ID %s\n", fc_id_ntoa ( &els->port_id ) );
+ } else {
+ DBGC ( els, FCELS_FMT " has point-to-point link\n",
+ FCELS_ARGS ( els ) );
+ }
+
+ /* Log in port */
+ if ( ( rc = fc_port_login ( els->port, &els->port_id, &flogi->node_wwn,
+ &flogi->port_wwn, has_fabric ) ) != 0 ) {
+ DBGC ( els, FCELS_FMT " could not log in port: %s\n",
+ FCELS_ARGS ( els ), strerror ( rc ) );
+ return rc;
+ }
+
+ /* Send any responses to the newly-assigned peer port ID, if
+ * applicable.
+ */
+ if ( ! has_fabric ) {
+ memcpy ( &els->peer_port_id, &els->port->ptp_link_port_id,
+ sizeof ( els->peer_port_id ) );
+ }
+
+ /* Transmit response, if applicable */
+ if ( ! fc_els_is_request ( els ) ) {
+ if ( ( rc = fc_els_flogi_tx ( els ) ) != 0 )
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Detect FLOGI
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_flogi_detect ( struct fc_els *els __unused, const void *data,
+ size_t len __unused ) {
+ const struct fc_login_frame *flogi = data;
+
+ /* Check for FLOGI */
+ if ( flogi->command != FC_ELS_FLOGI )
+ return -EINVAL;
+
+ return 0;
+}
+
+/** FLOGI ELS handler */
+struct fc_els_handler fc_els_flogi_handler __fc_els_handler = {
+ .name = "FLOGI",
+ .tx = fc_els_flogi_tx,
+ .rx = fc_els_flogi_rx,
+ .detect = fc_els_flogi_detect,
+};
+
+/**
+ * Create FLOGI request
+ *
+ * @v parent Parent interface
+ * @v port Fibre Channel port
+ * @ret rc Return status code
+ */
+int fc_els_flogi ( struct interface *parent, struct fc_port *port ) {
+
+ return fc_els_request ( parent, port, &fc_f_port_id,
+ &fc_els_flogi_handler );
+}
+
+/******************************************************************************
+ *
+ * PLOGI
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Transmit PLOGI
+ *
+ * @v els Fibre Channel ELS transaction
+ * @ret rc Return status code
+ */
+static int fc_els_plogi_tx ( struct fc_els *els ) {
+ struct fc_login_frame plogi;
+
+ /* Construct PLOGI */
+ memset ( &plogi, 0, sizeof ( plogi ) );
+ plogi.command = fc_els_tx_command ( els, FC_ELS_PLOGI );
+ plogi.common.version = htons ( FC_LOGIN_VERSION );
+ plogi.common.credit = htons ( FC_LOGIN_DEFAULT_B2B );
+ plogi.common.flags = htons ( FC_LOGIN_CONTINUOUS_OFFSET );
+ plogi.common.mtu = htons ( FC_LOGIN_DEFAULT_MTU );
+ plogi.common.u.plogi.max_seq = htons ( FC_LOGIN_DEFAULT_MAX_SEQ );
+ plogi.common.u.plogi.rel_offs = htons ( FC_LOGIN_DEFAULT_REL_OFFS );
+ plogi.common.e_d_tov = htonl ( FC_LOGIN_DEFAULT_E_D_TOV );
+ memcpy ( &plogi.port_wwn, &els->port->port_wwn,
+ sizeof ( plogi.port_wwn ) );
+ memcpy ( &plogi.node_wwn, &els->port->node_wwn,
+ sizeof ( plogi.node_wwn ) );
+ plogi.class3.flags = htons ( FC_LOGIN_CLASS_VALID |
+ FC_LOGIN_CLASS_SEQUENTIAL );
+ plogi.class3.mtu = htons ( FC_LOGIN_DEFAULT_MTU );
+ plogi.class3.max_seq = htons ( FC_LOGIN_DEFAULT_MAX_SEQ );
+ plogi.class3.max_seq_per_xchg = 1;
+
+ /* Transmit PLOGI */
+ return fc_els_tx ( els, &plogi, sizeof ( plogi ) );
+}
+
+/**
+ * Receive PLOGI
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_plogi_rx ( struct fc_els *els, void *data, size_t len ) {
+ struct fc_login_frame *plogi = data;
+ struct fc_peer *peer;
+ int rc;
+
+ /* Sanity checks */
+ if ( len < sizeof ( *plogi ) ) {
+ DBGC ( els, FCELS_FMT " received underlength frame:\n",
+ FCELS_ARGS ( els ) );
+ DBGC_HDA ( els, 0, data, len );
+ rc = -EINVAL;
+ goto err_sanity;
+ }
+ if ( ! fc_link_ok ( &els->port->link ) ) {
+ DBGC ( els, FCELS_FMT " received while port link is down\n",
+ FCELS_ARGS ( els ) );
+ rc = -EINVAL;
+ goto err_sanity;
+ }
+
+ /* Extract parameters */
+ DBGC ( els, FCELS_FMT " has node %s\n", FCELS_ARGS ( els ),
+ fc_ntoa ( &plogi->node_wwn ) );
+ DBGC ( els, FCELS_FMT " has port %s as %s\n",
+ FCELS_ARGS ( els ), fc_ntoa ( &plogi->port_wwn ),
+ fc_id_ntoa ( &els->peer_port_id ) );
+
+ /* Get peer */
+ peer = fc_peer_get_wwn ( &plogi->port_wwn );
+ if ( ! peer ) {
+ DBGC ( els, FCELS_FMT " could not create peer\n",
+ FCELS_ARGS ( els ) );
+ rc = -ENOMEM;
+ goto err_peer_get_wwn;
+ }
+
+ /* Record login */
+ if ( ( rc = fc_peer_login ( peer, els->port,
+ &els->peer_port_id ) ) != 0 ) {
+ DBGC ( els, FCELS_FMT " could not log in peer: %s\n",
+ FCELS_ARGS ( els ), strerror ( rc ) );
+ goto err_login;
+ }
+
+ /* Transmit response, if applicable */
+ if ( ! fc_els_is_request ( els ) ) {
+ if ( ( rc = fc_els_plogi_tx ( els ) ) != 0 )
+ goto err_plogi_tx;
+ }
+
+ /* Drop temporary reference to peer */
+ fc_peer_put ( peer );
+
+ return 0;
+
+ err_plogi_tx:
+ err_login:
+ fc_peer_put ( peer );
+ err_peer_get_wwn:
+ err_sanity:
+ return rc;
+}
+
+/**
+ * Detect PLOGI
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_plogi_detect ( struct fc_els *els __unused, const void *data,
+ size_t len __unused ) {
+ const struct fc_login_frame *plogi = data;
+
+ /* Check for PLOGI */
+ if ( plogi->command != FC_ELS_PLOGI )
+ return -EINVAL;
+
+ return 0;
+}
+
+/** PLOGI ELS handler */
+struct fc_els_handler fc_els_plogi_handler __fc_els_handler = {
+ .name = "PLOGI",
+ .tx = fc_els_plogi_tx,
+ .rx = fc_els_plogi_rx,
+ .detect = fc_els_plogi_detect,
+};
+
+/**
+ * Create PLOGI request
+ *
+ * @v parent Parent interface
+ * @v port Fibre Channel port
+ * @v peer_port_id Peer port ID
+ * @ret rc Return status code
+ */
+int fc_els_plogi ( struct interface *parent, struct fc_port *port,
+ struct fc_port_id *peer_port_id ) {
+
+ return fc_els_request ( parent, port, peer_port_id,
+ &fc_els_plogi_handler );
+}
+
+/******************************************************************************
+ *
+ * LOGO
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Transmit LOGO request
+ *
+ * @v els Fibre Channel ELS transaction
+ * @ret rc Return status code
+ */
+static int fc_els_logo_tx ( struct fc_els *els ) {
+ struct fc_logout_request_frame logo;
+
+ /* Construct LOGO */
+ memset ( &logo, 0, sizeof ( logo ) );
+ logo.command = FC_ELS_LOGO;
+ memcpy ( &logo.port_id, &els->port->port_id, sizeof ( logo.port_id ) );
+ memcpy ( &logo.port_wwn, &els->port->port_wwn,
+ sizeof ( logo.port_wwn ) );
+
+ /* Transmit LOGO */
+ return fc_els_tx ( els, &logo, sizeof ( logo ) );
+}
+
+/**
+ * Transmit LOGO response
+ *
+ * @v els Fibre Channel ELS transaction
+ * @ret rc Return status code
+ */
+static int fc_els_logo_tx_response ( struct fc_els *els ) {
+ struct fc_logout_response_frame logo;
+
+ /* Construct LOGO */
+ memset ( &logo, 0, sizeof ( logo ) );
+ logo.command = FC_ELS_LS_ACC;
+
+ /* Transmit LOGO */
+ return fc_els_tx ( els, &logo, sizeof ( logo ) );
+}
+
+/**
+ * Log out individual peer or whole port as applicable
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v port_id Peer port ID
+ */
+static void fc_els_logo_logout ( struct fc_els *els,
+ struct fc_port_id *peer_port_id ) {
+ struct fc_peer *peer;
+
+ if ( ( memcmp ( peer_port_id, &fc_f_port_id,
+ sizeof ( *peer_port_id ) ) == 0 ) ||
+ ( memcmp ( peer_port_id, &els->port->port_id,
+ sizeof ( *peer_port_id ) ) == 0 ) ) {
+ fc_port_logout ( els->port, 0 );
+ } else {
+ peer = fc_peer_get_port_id ( els->port, peer_port_id );
+ if ( peer ) {
+ fc_peer_logout ( peer, 0 );
+ fc_peer_put ( peer );
+ }
+ }
+}
+
+/**
+ * Receive LOGO request
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_logo_rx_request ( struct fc_els *els, void *data,
+ size_t len ) {
+ struct fc_logout_request_frame *logo = data;
+ int rc;
+
+ /* Sanity check */
+ if ( len < sizeof ( *logo ) ) {
+ DBGC ( els, FCELS_FMT " received underlength frame:\n",
+ FCELS_ARGS ( els ) );
+ DBGC_HDA ( els, 0, data, len );
+ return -EINVAL;
+ }
+
+ DBGC ( els, FCELS_FMT " has port %s as %s\n", FCELS_ARGS ( els ),
+ fc_ntoa ( &logo->port_wwn ), fc_id_ntoa ( &logo->port_id ) );
+
+ /* Log out individual peer or whole port as applicable */
+ fc_els_logo_logout ( els, &logo->port_id );
+
+ /* Transmit repsonse */
+ if ( ( rc = fc_els_logo_tx_response ( els ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Receive LOGO response
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_logo_rx_response ( struct fc_els *els, void *data __unused,
+ size_t len __unused ) {
+
+ /* Log out individual peer or whole port as applicable */
+ fc_els_logo_logout ( els, &els->peer_port_id );
+
+ return 0;
+}
+
+/**
+ * Receive LOGO
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_logo_rx ( struct fc_els *els, void *data, size_t len ) {
+
+ if ( fc_els_is_request ( els ) ) {
+ return fc_els_logo_rx_response ( els, data, len );
+ } else {
+ return fc_els_logo_rx_request ( els, data, len );
+ }
+}
+
+/**
+ * Detect LOGO
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_logo_detect ( struct fc_els *els __unused, const void *data,
+ size_t len __unused ) {
+ const struct fc_logout_request_frame *logo = data;
+
+ /* Check for LOGO */
+ if ( logo->command != FC_ELS_LOGO )
+ return -EINVAL;
+
+ return 0;
+}
+
+/** LOGO ELS handler */
+struct fc_els_handler fc_els_logo_handler __fc_els_handler = {
+ .name = "LOGO",
+ .tx = fc_els_logo_tx,
+ .rx = fc_els_logo_rx,
+ .detect = fc_els_logo_detect,
+};
+
+/**
+ * Create LOGO request
+ *
+ * @v parent Parent interface
+ * @v port Fibre Channel port
+ * @v peer_port_id Peer port ID
+ * @ret rc Return status code
+ */
+int fc_els_logo ( struct interface *parent, struct fc_port *port,
+ struct fc_port_id *peer_port_id ) {
+
+ return fc_els_request ( parent, port, peer_port_id,
+ &fc_els_logo_handler );
+}
+
+/******************************************************************************
+ *
+ * PRLI
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Find PRLI descriptor
+ *
+ * @v type Upper-layer protocol type
+ * @ret descriptor PRLI descriptor, or NULL
+ */
+static struct fc_els_prli_descriptor *
+fc_els_prli_descriptor ( unsigned int type ) {
+ struct fc_els_prli_descriptor *descriptor;
+
+ for_each_table_entry ( descriptor, FC_ELS_PRLI_DESCRIPTORS ) {
+ if ( descriptor->type == type )
+ return descriptor;
+ }
+ return NULL;
+}
+
+/**
+ * Transmit PRLI
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v descriptor ELS PRLI descriptor
+ * @v param Service parameters
+ * @ret rc Return status code
+ */
+int fc_els_prli_tx ( struct fc_els *els,
+ struct fc_els_prli_descriptor *descriptor, void *param ) {
+ struct {
+ struct fc_prli_frame frame;
+ uint8_t param[descriptor->param_len];
+ } __attribute__ (( packed )) prli;
+ struct fc_ulp *ulp;
+ int rc;
+
+ /* Get ULP */
+ ulp = fc_ulp_get_port_id_type ( els->port, &els->peer_port_id,
+ descriptor->type );
+ if ( ! ulp ) {
+ rc = -ENOMEM;
+ goto err_get_port_id_type;
+ }
+
+ /* Build frame for transmission */
+ memset ( &prli, 0, sizeof ( prli ) );
+ prli.frame.command = fc_els_tx_command ( els, FC_ELS_PRLI );
+ prli.frame.page_len =
+ ( sizeof ( prli.frame.page ) + sizeof ( prli.param ) );
+ prli.frame.len = htons ( sizeof ( prli ) );
+ prli.frame.page.type = descriptor->type;
+ if ( fc_els_is_request ( els ) ) {
+ prli.frame.page.flags |= htons ( FC_PRLI_ESTABLISH );
+ } else if ( fc_link_ok ( &ulp->link ) ) {
+ prli.frame.page.flags |= htons ( FC_PRLI_ESTABLISH |
+ FC_PRLI_RESPONSE_SUCCESS );
+ }
+ memcpy ( &prli.param, param, sizeof ( prli.param ) );
+
+ /* Transmit frame */
+ if ( ( rc = fc_els_tx ( els, &prli, sizeof ( prli ) ) ) != 0 )
+ goto err_tx;
+
+ /* Drop temporary reference to ULP */
+ fc_ulp_put ( ulp );
+
+ return 0;
+
+ err_tx:
+ fc_ulp_put ( ulp );
+ err_get_port_id_type:
+ return rc;
+}
+
+/**
+ * Receive PRLI
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v descriptor ELS PRLI descriptor
+ * @v frame ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+int fc_els_prli_rx ( struct fc_els *els,
+ struct fc_els_prli_descriptor *descriptor,
+ void *data, size_t len ) {
+ struct {
+ struct fc_prli_frame frame;
+ uint8_t param[descriptor->param_len];
+ } __attribute__ (( packed )) *prli = data;
+ struct fc_ulp *ulp;
+ int rc;
+
+ /* Sanity check */
+ if ( len < sizeof ( *prli ) ) {
+ DBGC ( els, FCELS_FMT " received underlength frame:\n",
+ FCELS_ARGS ( els ) );
+ DBGC_HDA ( els, 0, data, len );
+ rc = -EINVAL;
+ goto err_sanity;
+ }
+
+ DBGC ( els, FCELS_FMT " has parameters:\n", FCELS_ARGS ( els ) );
+ DBGC_HDA ( els, 0, prli->param, sizeof ( prli->param ) );
+
+ /* Get ULP */
+ ulp = fc_ulp_get_port_id_type ( els->port, &els->peer_port_id,
+ descriptor->type );
+ if ( ! ulp ) {
+ rc = -ENOMEM;
+ goto err_get_port_id_type;
+ }
+
+ /* Sanity check */
+ if ( ! fc_link_ok ( &ulp->peer->link ) ) {
+ DBGC ( els, FCELS_FMT " received while peer link is down\n",
+ FCELS_ARGS ( els ) );
+ rc = -EINVAL;
+ goto err_link;
+ }
+
+ /* Log in ULP, if applicable */
+ if ( prli->frame.page.flags & htons ( FC_PRLI_ESTABLISH ) ) {
+ if ( ( rc = fc_ulp_login ( ulp, prli->param,
+ sizeof ( prli->param ),
+ fc_els_is_request ( els ) ) ) != 0 ){
+ DBGC ( els, FCELS_FMT " could not log in ULP: %s\n",
+ FCELS_ARGS ( els ), strerror ( rc ) );
+ goto err_login;
+ }
+ } else {
+ if ( fc_els_is_request ( els ) ) {
+ fc_ulp_logout ( ulp, -EACCES );
+ } else {
+ /* This is just an information-gathering PRLI; do not
+ * log in or out
+ */
+ }
+ }
+
+ /* Transmit response, if applicable */
+ if ( ! fc_els_is_request ( els ) ) {
+ if ( ( rc = els->handler->tx ( els ) ) != 0 )
+ goto err_tx;
+ }
+
+ /* Drop temporary reference to ULP */
+ fc_ulp_put ( ulp );
+
+ return 0;
+
+ err_tx:
+ err_login:
+ err_link:
+ fc_ulp_put ( ulp );
+ err_get_port_id_type:
+ err_sanity:
+ return rc;
+}
+
+/**
+ * Detect PRLI
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v descriptor ELS PRLI descriptor
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+int fc_els_prli_detect ( struct fc_els *els __unused,
+ struct fc_els_prli_descriptor *descriptor,
+ const void *data, size_t len ) {
+ const struct {
+ struct fc_prli_frame frame;
+ uint8_t param[descriptor->param_len];
+ } __attribute__ (( packed )) *prli = data;
+
+ /* Check for PRLI */
+ if ( prli->frame.command != FC_ELS_PRLI )
+ return -EINVAL;
+
+ /* Check for sufficient length to contain service parameter page */
+ if ( len < sizeof ( *prli ) )
+ return -EINVAL;
+
+ /* Check for upper-layer protocol type */
+ if ( prli->frame.page.type != descriptor->type )
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * Create PRLI request
+ *
+ * @v parent Parent interface
+ * @v port Fibre Channel port
+ * @v peer_port_id Peer port ID
+ * @v type Upper-layer protocol type
+ * @ret rc Return status code
+ */
+int fc_els_prli ( struct interface *parent, struct fc_port *port,
+ struct fc_port_id *peer_port_id, unsigned int type ) {
+ struct fc_els_prli_descriptor *descriptor;
+
+ /* Find a PRLI descriptor */
+ descriptor = fc_els_prli_descriptor ( type );
+ if ( ! descriptor )
+ return -ENOTSUP;
+
+ return fc_els_request ( parent, port, peer_port_id,
+ descriptor->handler );
+}
+
+/******************************************************************************
+ *
+ * RTV
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Transmit RTV response
+ *
+ * @v els Fibre Channel ELS transaction
+ * @ret rc Return status code
+ */
+static int fc_els_rtv_tx_response ( struct fc_els *els ) {
+ struct fc_rtv_response_frame rtv;
+
+ /* Construct RTV */
+ memset ( &rtv, 0, sizeof ( rtv ) );
+ rtv.command = FC_ELS_LS_ACC;
+ rtv.e_d_tov = htonl ( FC_LOGIN_DEFAULT_E_D_TOV );
+
+ /* Transmit RTV */
+ return fc_els_tx ( els, &rtv, sizeof ( rtv ) );
+}
+
+/**
+ * Receive RTV
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_rtv_rx ( struct fc_els *els, void *data __unused,
+ size_t len __unused ) {
+ int rc;
+
+ DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );
+
+ /* Transmit response */
+ if ( ! fc_els_is_request ( els ) ) {
+ if ( ( rc = fc_els_rtv_tx_response ( els ) ) != 0 )
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Detect RTV
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_rtv_detect ( struct fc_els *els __unused, const void *data,
+ size_t len __unused ) {
+ const struct fc_rtv_request_frame *rtv = data;
+
+ /* Check for RTV */
+ if ( rtv->command != FC_ELS_RTV )
+ return -EINVAL;
+
+ return 0;
+}
+
+/** RTV ELS handler */
+struct fc_els_handler fc_els_rtv_handler __fc_els_handler = {
+ .name = "RTV",
+ .tx = fc_els_unknown_tx,
+ .rx = fc_els_rtv_rx,
+ .detect = fc_els_rtv_detect,
+};
+
+/******************************************************************************
+ *
+ * ECHO
+ *
+ ******************************************************************************
+ */
+
+/** ECHO request data */
+struct fc_echo_request_frame {
+ /** ECHO frame header */
+ struct fc_echo_frame_header echo;
+ /** Magic marker */
+ uint32_t magic;
+} __attribute__ (( packed ));
+
+/** ECHO magic marker */
+#define FC_ECHO_MAGIC 0x69505845
+
+/**
+ * Transmit ECHO
+ *
+ * @v els Fibre Channel ELS transaction
+ * @ret rc Return status code
+ */
+static int fc_els_echo_tx ( struct fc_els *els ) {
+ struct fc_echo_request_frame echo;
+
+ /* Construct ECHO */
+ memset ( &echo, 0, sizeof ( echo ) );
+ echo.echo.command = FC_ELS_ECHO;
+ echo.magic = htonl ( FC_ECHO_MAGIC );
+
+ /* Transmit ECHO */
+ return fc_els_tx ( els, &echo, sizeof ( echo ) );
+}
+
+/**
+ * Receive ECHO request
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_echo_rx_request ( struct fc_els *els, void *data,
+ size_t len ) {
+ struct {
+ struct fc_echo_frame_header echo;
+ char payload[ len - sizeof ( struct fc_echo_frame_header ) ];
+ } *echo = data;
+ int rc;
+
+ DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );
+
+ /* Transmit response */
+ echo->echo.command = FC_ELS_LS_ACC;
+ if ( ( rc = fc_els_tx ( els, echo, sizeof ( *echo ) ) ) != 0 )
+ return rc;
+
+ /* Nothing to do */
+ return 0;
+}
+
+/**
+ * Receive ECHO response
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_echo_rx_response ( struct fc_els *els, void *data,
+ size_t len ) {
+ struct fc_echo_request_frame *echo = data;
+
+ DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );
+
+ /* Check response is correct */
+ if ( ( len != sizeof ( *echo ) ) ||
+ ( echo->magic != htonl ( FC_ECHO_MAGIC ) ) ) {
+ DBGC ( els, FCELS_FMT " received bad echo response\n",
+ FCELS_ARGS ( els ) );
+ DBGC_HDA ( els, 0, data, len );
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * Receive ECHO
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_echo_rx ( struct fc_els *els, void *data, size_t len ) {
+
+ if ( fc_els_is_request ( els ) ) {
+ return fc_els_echo_rx_response ( els, data, len );
+ } else {
+ return fc_els_echo_rx_request ( els, data, len );
+ }
+}
+
+/**
+ * Detect ECHO
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fc_els_echo_detect ( struct fc_els *els __unused, const void *data,
+ size_t len __unused ) {
+ const struct fc_echo_frame_header *echo = data;
+
+ /* Check for ECHO */
+ if ( echo->command != FC_ELS_ECHO )
+ return -EINVAL;
+
+ return 0;
+}
+
+/** ECHO ELS handler */
+struct fc_els_handler fc_els_echo_handler __fc_els_handler = {
+ .name = "ECHO",
+ .tx = fc_els_echo_tx,
+ .rx = fc_els_echo_rx,
+ .detect = fc_els_echo_detect,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/fcns.c b/src/VBox/Devices/PC/ipxe/src/net/fcns.c
new file mode 100644
index 00000000..55bd29e5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/fcns.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/interface.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/process.h>
+#include <ipxe/xfer.h>
+#include <ipxe/fc.h>
+#include <ipxe/fcns.h>
+
+/** @file
+ *
+ * Fibre Channel name server lookups
+ *
+ */
+
+/** A Fibre Channel name server query */
+struct fc_ns_query {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Fibre Channel exchange */
+ struct interface xchg;
+
+ /** Fibre Channel peer */
+ struct fc_peer *peer;
+ /** Fibre Channel port */
+ struct fc_port *port;
+
+ /** Process */
+ struct process process;
+ /** Success handler
+ *
+ * @v peer Fibre Channel peer
+ * @v port Fibre Channel port
+ * @v peer_port_id Peer port ID
+ * @ret rc Return status code
+ */
+ int ( * done ) ( struct fc_peer *peer, struct fc_port *port,
+ struct fc_port_id *peer_port_id );
+};
+
+/**
+ * Free name server query
+ *
+ * @v refcnt Reference count
+ */
+static void fc_ns_query_free ( struct refcnt *refcnt ) {
+ struct fc_ns_query *query =
+ container_of ( refcnt, struct fc_ns_query, refcnt );
+
+ fc_peer_put ( query->peer );
+ fc_port_put ( query->port );
+ free ( query );
+}
+
+/**
+ * Close name server query
+ *
+ * @v query Name server query
+ * @v rc Reason for close
+ */
+static void fc_ns_query_close ( struct fc_ns_query *query, int rc ) {
+
+ /* Stop process */
+ process_del ( &query->process );
+
+ /* Shut down interfaces */
+ intf_shutdown ( &query->xchg, rc );
+}
+
+/**
+ * Receive name server query response
+ *
+ * @v query Name server query
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int fc_ns_query_deliver ( struct fc_ns_query *query,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ union fc_ns_response *resp = iobuf->data;
+ struct fc_port_id *peer_port_id;
+ int rc;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( resp->ct ) ) {
+ DBGC ( query, "FCNS %p received underlength response (%zd "
+ "bytes)\n", query, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Handle response */
+ switch ( ntohs ( resp->ct.code ) ) {
+ case FC_GS_ACCEPT:
+ if ( iob_len ( iobuf ) < sizeof ( resp->gid_pn ) ) {
+ DBGC ( query, "FCNS %p received underlength accept "
+ "response (%zd bytes)\n",
+ query, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto done;
+ }
+ peer_port_id = &resp->gid_pn.port_id.port_id;
+ DBGC ( query, "FCNS %p resolved %s to %s via %s\n",
+ query, fc_ntoa ( &query->peer->port_wwn ),
+ fc_id_ntoa ( peer_port_id ), query->port->name );
+ if ( ( rc = query->done ( query->peer, query->port,
+ peer_port_id ) ) != 0 )
+ goto done;
+ break;
+ case FC_GS_REJECT:
+ DBGC ( query, "FCNS %p rejected (reason %02x explanation "
+ "%02x)\n", query, resp->reject.ct.reason,
+ resp->reject.ct.explanation );
+ break;
+ default:
+ DBGC ( query, "FCNS %p received invalid response code %04x\n",
+ query, ntohs ( resp->ct.code ) );
+ rc = -ENOTSUP;
+ goto done;
+ }
+
+ rc = 0;
+ done:
+ free_iob ( iobuf );
+ fc_ns_query_close ( query, rc );
+ return rc;
+}
+
+/**
+ * Name server query process
+ *
+ * @v query Name server query
+ */
+static void fc_ns_query_step ( struct fc_ns_query *query ) {
+ struct xfer_metadata meta;
+ struct fc_ns_gid_pn_request gid_pn;
+ int xchg_id;
+ int rc;
+
+ /* Create exchange */
+ if ( ( xchg_id = fc_xchg_originate ( &query->xchg, query->port,
+ &fc_gs_port_id,
+ FC_TYPE_CT ) ) < 0 ) {
+ rc = xchg_id;
+ DBGC ( query, "FCNS %p could not create exchange: %s\n",
+ query, strerror ( rc ) );
+ fc_ns_query_close ( query, rc );
+ return;
+ }
+
+ /* Construct query request */
+ memset ( &gid_pn, 0, sizeof ( gid_pn ) );
+ gid_pn.ct.revision = FC_CT_REVISION;
+ gid_pn.ct.type = FC_GS_TYPE_DS;
+ gid_pn.ct.subtype = FC_DS_SUBTYPE_NAME;
+ gid_pn.ct.code = htons ( FC_NS_GET ( FC_NS_PORT_NAME, FC_NS_PORT_ID ));
+ memcpy ( &gid_pn.port_wwn, &query->peer->port_wwn,
+ sizeof ( gid_pn.port_wwn ) );
+ memset ( &meta, 0, sizeof ( meta ) );
+ meta.flags = XFER_FL_OVER;
+
+ /* Send query */
+ if ( ( rc = xfer_deliver_raw_meta ( &query->xchg, &gid_pn,
+ sizeof ( gid_pn ), &meta ) ) != 0){
+ DBGC ( query, "FCNS %p could not deliver query: %s\n",
+ query, strerror ( rc ) );
+ fc_ns_query_close ( query, rc );
+ return;
+ }
+}
+
+/** Name server exchange interface operations */
+static struct interface_operation fc_ns_query_xchg_op[] = {
+ INTF_OP ( xfer_deliver, struct fc_ns_query *, fc_ns_query_deliver ),
+ INTF_OP ( intf_close, struct fc_ns_query *, fc_ns_query_close ),
+};
+
+/** Name server exchange interface descriptor */
+static struct interface_descriptor fc_ns_query_xchg_desc =
+ INTF_DESC ( struct fc_ns_query, xchg, fc_ns_query_xchg_op );
+
+/** Name server process descriptor */
+static struct process_descriptor fc_ns_query_process_desc =
+ PROC_DESC_ONCE ( struct fc_ns_query, process, fc_ns_query_step );
+
+/**
+ * Issue Fibre Channel name server query
+ *
+ * @v peer Fibre Channel peer
+ * @v port Fibre Channel port
+ * @ret rc Return status code
+ */
+int fc_ns_query ( struct fc_peer *peer, struct fc_port *port,
+ int ( * done ) ( struct fc_peer *peer, struct fc_port *port,
+ struct fc_port_id *peer_port_id ) ) {
+ struct fc_ns_query *query;
+
+ /* Allocate and initialise structure */
+ query = zalloc ( sizeof ( *query ) );
+ if ( ! query )
+ return -ENOMEM;
+ ref_init ( &query->refcnt, fc_ns_query_free );
+ intf_init ( &query->xchg, &fc_ns_query_xchg_desc, &query->refcnt );
+ process_init ( &query->process, &fc_ns_query_process_desc,
+ &query->refcnt );
+ query->peer = fc_peer_get ( peer );
+ query->port = fc_port_get ( port );
+ query->done = done;
+
+ DBGC ( query, "FCNS %p querying %s via %s\n",
+ query, fc_ntoa ( &query->peer->port_wwn ), port->name );
+
+ /* Mortalise self and return */
+ ref_put ( &query->refcnt );
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/fcoe.c b/src/VBox/Devices/PC/ipxe/src/net/fcoe.c
new file mode 100644
index 00000000..c54d1b47
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/fcoe.c
@@ -0,0 +1,1228 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/if_arp.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/interface.h>
+#include <ipxe/xfer.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/vlan.h>
+#include <ipxe/features.h>
+#include <ipxe/errortab.h>
+#include <ipxe/device.h>
+#include <ipxe/crc32.h>
+#include <ipxe/retry.h>
+#include <ipxe/timer.h>
+#include <ipxe/fc.h>
+#include <ipxe/fip.h>
+#include <ipxe/fcoe.h>
+
+/** @file
+ *
+ * FCoE protocol
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "FCoE", DHCP_EB_FEATURE_FCOE, 1 );
+
+/* Disambiguate the various error causes */
+#define EINVAL_UNDERLENGTH __einfo_error ( EINFO_EINVAL_UNDERLENGTH )
+#define EINFO_EINVAL_UNDERLENGTH \
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, "Underlength packet" )
+#define EINVAL_SOF __einfo_error ( EINFO_EINVAL_SOF )
+#define EINFO_EINVAL_SOF \
+ __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid SoF delimiter" )
+#define EINVAL_CRC __einfo_error ( EINFO_EINVAL_CRC )
+#define EINFO_EINVAL_CRC \
+ __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid CRC (not stripped?)" )
+#define EINVAL_EOF __einfo_error ( EINFO_EINVAL_EOF )
+#define EINFO_EINVAL_EOF \
+ __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid EoF delimiter" )
+
+/** An FCoE port */
+struct fcoe_port {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** List of FCoE ports */
+ struct list_head list;
+ /** Transport interface */
+ struct interface transport;
+ /** Network device */
+ struct net_device *netdev;
+
+ /** Node WWN */
+ union fcoe_name node_wwn;
+ /** Port WWN */
+ union fcoe_name port_wwn;
+
+ /** FIP retransmission timer */
+ struct retry_timer timer;
+ /** FIP timeout counter */
+ unsigned int timeouts;
+ /** Flags */
+ unsigned int flags;
+ /** FCoE forwarder priority */
+ unsigned int priority;
+ /** Keepalive delay (in ms) */
+ unsigned int keepalive;
+ /** FCoE forwarder MAC address */
+ uint8_t fcf_mac[ETH_ALEN];
+ /** Local MAC address */
+ uint8_t local_mac[ETH_ALEN];
+};
+
+/** FCoE flags */
+enum fcoe_flags {
+ /** Underlying network device is available */
+ FCOE_HAVE_NETWORK = 0x0001,
+ /** We have selected an FCoE forwarder to use */
+ FCOE_HAVE_FCF = 0x0002,
+ /** We have a FIP-capable FCoE forwarder available to be used */
+ FCOE_HAVE_FIP_FCF = 0x0004,
+ /** FCoE forwarder supports server-provided MAC addresses */
+ FCOE_FCF_ALLOWS_SPMA = 0x0008,
+ /** An alternative VLAN has been found */
+ FCOE_VLAN_FOUND = 0x0010,
+ /** VLAN discovery has timed out */
+ FCOE_VLAN_TIMED_OUT = 0x0020,
+};
+
+struct net_protocol fcoe_protocol __net_protocol;
+struct net_protocol fip_protocol __net_protocol;
+
+/** FCoE All-FCoE-MACs address */
+static uint8_t all_fcoe_macs[ETH_ALEN] =
+ { 0x01, 0x10, 0x18, 0x01, 0x00, 0x00 };
+
+/** FCoE All-ENode-MACs address */
+static uint8_t all_enode_macs[ETH_ALEN] =
+ { 0x01, 0x10, 0x18, 0x01, 0x00, 0x01 };
+
+/** FCoE All-FCF-MACs address */
+static uint8_t all_fcf_macs[ETH_ALEN] =
+ { 0x01, 0x10, 0x18, 0x01, 0x00, 0x02 };
+
+/** Default FCoE forwarded MAC address */
+static uint8_t default_fcf_mac[ETH_ALEN] =
+ { 0x0e, 0xfc, 0x00, 0xff, 0xff, 0xfe };
+
+/** Maximum number of VLAN requests before giving up on VLAN discovery */
+#define FCOE_MAX_VLAN_REQUESTS 2
+
+/** Delay between retrying VLAN requests */
+#define FCOE_VLAN_RETRY_DELAY ( TICKS_PER_SEC )
+
+/** Delay between retrying polling VLAN requests */
+#define FCOE_VLAN_POLL_DELAY ( 30 * TICKS_PER_SEC )
+
+/** Maximum number of FIP solicitations before giving up on FIP */
+#define FCOE_MAX_FIP_SOLICITATIONS 2
+
+/** Delay between retrying FIP solicitations */
+#define FCOE_FIP_RETRY_DELAY ( TICKS_PER_SEC )
+
+/** Maximum number of missing discovery advertisements */
+#define FCOE_MAX_FIP_MISSING_KEEPALIVES 4
+
+/** List of FCoE ports */
+static LIST_HEAD ( fcoe_ports );
+
+/******************************************************************************
+ *
+ * FCoE protocol
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Identify FCoE port by network device
+ *
+ * @v netdev Network device
+ * @ret fcoe FCoE port, or NULL
+ */
+static struct fcoe_port * fcoe_demux ( struct net_device *netdev ) {
+ struct fcoe_port *fcoe;
+
+ list_for_each_entry ( fcoe, &fcoe_ports, list ) {
+ if ( fcoe->netdev == netdev )
+ return fcoe;
+ }
+ return NULL;
+}
+
+/**
+ * Reset FCoE port
+ *
+ * @v fcoe FCoE port
+ */
+static void fcoe_reset ( struct fcoe_port *fcoe ) {
+
+ /* Detach FC port, if any */
+ intf_restart ( &fcoe->transport, -ECANCELED );
+
+ /* Reset any FIP state */
+ stop_timer ( &fcoe->timer );
+ fcoe->timeouts = 0;
+ fcoe->flags = 0;
+ fcoe->priority = ( FIP_LOWEST_PRIORITY + 1 );
+ fcoe->keepalive = 0;
+ memcpy ( fcoe->fcf_mac, default_fcf_mac,
+ sizeof ( fcoe->fcf_mac ) );
+ memcpy ( fcoe->local_mac, fcoe->netdev->ll_addr,
+ sizeof ( fcoe->local_mac ) );
+
+ /* Start FIP solicitation if network is available */
+ if ( netdev_is_open ( fcoe->netdev ) &&
+ netdev_link_ok ( fcoe->netdev ) ) {
+ fcoe->flags |= FCOE_HAVE_NETWORK;
+ start_timer_nodelay ( &fcoe->timer );
+ DBGC ( fcoe, "FCoE %s starting %s\n", fcoe->netdev->name,
+ ( vlan_can_be_trunk ( fcoe->netdev ) ?
+ "VLAN discovery" : "FIP solicitation" ) );
+ }
+
+ /* Send notification of window change */
+ xfer_window_changed ( &fcoe->transport );
+}
+
+/**
+ * Transmit FCoE packet
+ *
+ * @v fcoe FCoE port
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int fcoe_deliver ( struct fcoe_port *fcoe,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ struct fc_frame_header *fchdr = iobuf->data;
+ struct fc_els_frame_common *els = ( iobuf->data + sizeof ( *fchdr ) );
+ struct fcoe_header *fcoehdr;
+ struct fcoe_footer *fcoeftr;
+ struct fip_header *fiphdr;
+ struct fip_login *fipflogi;
+ struct fip_mac_address *fipmac;
+ uint32_t crc;
+ struct net_protocol *net_protocol;
+ void *ll_source;
+ int rc;
+
+ /* Send as FIP or FCoE as appropriate */
+ if ( ( fchdr->r_ctl == ( FC_R_CTL_ELS | FC_R_CTL_UNSOL_CTRL ) ) &&
+ ( els->command == FC_ELS_FLOGI ) &&
+ ( fcoe->flags & FCOE_HAVE_FIP_FCF ) ) {
+
+ /* Create FIP FLOGI descriptor */
+ fipflogi = iob_push ( iobuf,
+ offsetof ( typeof ( *fipflogi ), fc ) );
+ memset ( fipflogi, 0, offsetof ( typeof ( *fipflogi ), fc ) );
+ fipflogi->type = FIP_FLOGI;
+ fipflogi->len = ( iob_len ( iobuf ) / 4 );
+
+ /* Create FIP MAC address descriptor */
+ fipmac = iob_put ( iobuf, sizeof ( *fipmac ) );
+ memset ( fipmac, 0, sizeof ( *fipmac ) );
+ fipmac->type = FIP_MAC_ADDRESS;
+ fipmac->len = ( sizeof ( *fipmac ) / 4 );
+ if ( fcoe->flags & FCOE_FCF_ALLOWS_SPMA ) {
+ memcpy ( fipmac->mac, fcoe->netdev->ll_addr,
+ sizeof ( fipmac->mac ) );
+ }
+
+ /* Create FIP header */
+ fiphdr = iob_push ( iobuf, sizeof ( *fiphdr ) );
+ memset ( fiphdr, 0, sizeof ( *fiphdr ) );
+ fiphdr->version = FIP_VERSION;
+ fiphdr->code = htons ( FIP_CODE_ELS );
+ fiphdr->subcode = FIP_ELS_REQUEST;
+ fiphdr->len =
+ htons ( ( iob_len ( iobuf ) - sizeof ( *fiphdr ) ) / 4);
+ fiphdr->flags = ( ( fcoe->flags & FCOE_FCF_ALLOWS_SPMA ) ?
+ htons ( FIP_SP ) : htons ( FIP_FP ) );
+
+ /* Send as FIP packet from netdev's own MAC address */
+ net_protocol = &fip_protocol;
+ ll_source = fcoe->netdev->ll_addr;
+
+ } else {
+
+ /* Calculate CRC */
+ crc = crc32_le ( ~((uint32_t)0), iobuf->data,
+ iob_len ( iobuf ) );
+
+ /* Create FCoE header */
+ fcoehdr = iob_push ( iobuf, sizeof ( *fcoehdr ) );
+ memset ( fcoehdr, 0, sizeof ( *fcoehdr ) );
+ fcoehdr->sof = ( ( fchdr->seq_cnt == ntohs ( 0 ) ) ?
+ FCOE_SOF_I3 : FCOE_SOF_N3 );
+
+ /* Create FCoE footer */
+ fcoeftr = iob_put ( iobuf, sizeof ( *fcoeftr ) );
+ memset ( fcoeftr, 0, sizeof ( *fcoeftr ) );
+ fcoeftr->crc = cpu_to_le32 ( crc ^ ~((uint32_t)0) );
+ fcoeftr->eof = ( ( fchdr->f_ctl_es & FC_F_CTL_ES_END ) ?
+ FCOE_EOF_T : FCOE_EOF_N );
+
+ /* Send as FCoE packet from FCoE MAC address */
+ net_protocol = &fcoe_protocol;
+ ll_source = fcoe->local_mac;
+ }
+
+ /* Transmit packet */
+ if ( ( rc = net_tx ( iob_disown ( iobuf ), fcoe->netdev, net_protocol,
+ fcoe->fcf_mac, ll_source ) ) != 0 ) {
+ DBGC ( fcoe, "FCoE %s could not transmit: %s\n",
+ fcoe->netdev->name, strerror ( rc ) );
+ goto done;
+ }
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Allocate FCoE I/O buffer
+ *
+ * @v len Payload length
+ * @ret iobuf I/O buffer, or NULL
+ */
+static struct io_buffer * fcoe_alloc_iob ( struct fcoe_port *fcoe __unused,
+ size_t len ) {
+ struct io_buffer *iobuf;
+
+ iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( struct fcoe_header ) +
+ len + sizeof ( struct fcoe_footer ) );
+ if ( iobuf ) {
+ iob_reserve ( iobuf, ( MAX_LL_HEADER_LEN +
+ sizeof ( struct fcoe_header ) ) );
+ }
+ return iobuf;
+}
+
+/**
+ * Process incoming FCoE packets
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer source address
+ * @v flags Packet flags
+ * @ret rc Return status code
+ */
+static int fcoe_rx ( struct io_buffer *iobuf, struct net_device *netdev,
+ const void *ll_dest, const void *ll_source,
+ unsigned int flags __unused ) {
+ struct fcoe_header *fcoehdr;
+ struct fcoe_footer *fcoeftr;
+ struct fcoe_port *fcoe;
+ int rc;
+
+ /* Identify FCoE port */
+ if ( ( fcoe = fcoe_demux ( netdev ) ) == NULL ) {
+ DBG ( "FCoE received frame for net device %s missing FCoE "
+ "port\n", netdev->name );
+ rc = -ENOTCONN;
+ goto done;
+ }
+
+ /* Discard packets not destined for us */
+ if ( ( memcmp ( fcoe->local_mac, ll_dest,
+ sizeof ( fcoe->local_mac ) ) != 0 ) &&
+ ( memcmp ( default_fcf_mac, ll_dest,
+ sizeof ( default_fcf_mac ) ) != 0 ) ) {
+ DBGC2 ( fcoe, "FCoE %s ignoring packet for %s\n",
+ fcoe->netdev->name, eth_ntoa ( ll_dest ) );
+ rc = -ENOTCONN;
+ goto done;
+ }
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < ( sizeof ( *fcoehdr ) + sizeof ( *fcoeftr ) )){
+ DBGC ( fcoe, "FCoE %s received under-length frame (%zd "
+ "bytes)\n", fcoe->netdev->name, iob_len ( iobuf ) );
+ rc = -EINVAL_UNDERLENGTH;
+ goto done;
+ }
+
+ /* Strip header and footer */
+ fcoehdr = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *fcoehdr ) );
+ fcoeftr = ( iobuf->data + iob_len ( iobuf ) - sizeof ( *fcoeftr ) );
+ iob_unput ( iobuf, sizeof ( *fcoeftr ) );
+
+ /* Validity checks */
+ if ( fcoehdr->version != FCOE_FRAME_VER ) {
+ DBGC ( fcoe, "FCoE %s received unsupported frame version "
+ "%02x\n", fcoe->netdev->name, fcoehdr->version );
+ rc = -EPROTONOSUPPORT;
+ goto done;
+ }
+ if ( ! ( ( fcoehdr->sof == FCOE_SOF_I3 ) ||
+ ( fcoehdr->sof == FCOE_SOF_N3 ) ) ) {
+ DBGC ( fcoe, "FCoE %s received unsupported start-of-frame "
+ "delimiter %02x\n", fcoe->netdev->name, fcoehdr->sof );
+ rc = -EINVAL_SOF;
+ goto done;
+ }
+ if ( ( le32_to_cpu ( fcoeftr->crc ) ^ ~((uint32_t)0) ) !=
+ crc32_le ( ~((uint32_t)0), iobuf->data, iob_len ( iobuf ) ) ) {
+ DBGC ( fcoe, "FCoE %s received invalid CRC\n",
+ fcoe->netdev->name );
+ rc = -EINVAL_CRC;
+ goto done;
+ }
+ if ( ! ( ( fcoeftr->eof == FCOE_EOF_N ) ||
+ ( fcoeftr->eof == FCOE_EOF_T ) ) ) {
+ DBGC ( fcoe, "FCoE %s received unsupported end-of-frame "
+ "delimiter %02x\n", fcoe->netdev->name, fcoeftr->eof );
+ rc = -EINVAL_EOF;
+ goto done;
+ }
+
+ /* Record FCF address if applicable */
+ if ( ( fcoe->flags & FCOE_HAVE_FCF ) &&
+ ( ! ( fcoe->flags & FCOE_HAVE_FIP_FCF ) ) ) {
+ memcpy ( &fcoe->fcf_mac, ll_source, sizeof ( fcoe->fcf_mac ) );
+ }
+
+ /* Hand off via transport interface */
+ if ( ( rc = xfer_deliver_iob ( &fcoe->transport,
+ iob_disown ( iobuf ) ) ) != 0 ) {
+ DBGC ( fcoe, "FCoE %s could not deliver frame: %s\n",
+ fcoe->netdev->name, strerror ( rc ) );
+ goto done;
+ }
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Check FCoE flow control window
+ *
+ * @v fcoe FCoE port
+ * @ret len Length of window
+ */
+static size_t fcoe_window ( struct fcoe_port *fcoe ) {
+ return ( ( fcoe->flags & FCOE_HAVE_FCF ) ? ~( ( size_t ) 0 ) : 0 );
+}
+
+/**
+ * Close FCoE port
+ *
+ * @v fcoe FCoE port
+ * @v rc Reason for close
+ */
+static void fcoe_close ( struct fcoe_port *fcoe, int rc ) {
+
+ stop_timer ( &fcoe->timer );
+ intf_shutdown ( &fcoe->transport, rc );
+ netdev_put ( fcoe->netdev );
+ list_del ( &fcoe->list );
+ ref_put ( &fcoe->refcnt );
+}
+
+/**
+ * Identify device underlying FCoE port
+ *
+ * @v fcoe FCoE port
+ * @ret device Underlying device
+ */
+static struct device * fcoe_identify_device ( struct fcoe_port *fcoe ) {
+ return fcoe->netdev->dev;
+}
+
+/** FCoE transport interface operations */
+static struct interface_operation fcoe_transport_op[] = {
+ INTF_OP ( xfer_deliver, struct fcoe_port *, fcoe_deliver ),
+ INTF_OP ( xfer_alloc_iob, struct fcoe_port *, fcoe_alloc_iob ),
+ INTF_OP ( xfer_window, struct fcoe_port *, fcoe_window ),
+ INTF_OP ( intf_close, struct fcoe_port *, fcoe_close ),
+ INTF_OP ( identify_device, struct fcoe_port *,
+ fcoe_identify_device ),
+};
+
+/** FCoE transport interface descriptor */
+static struct interface_descriptor fcoe_transport_desc =
+ INTF_DESC ( struct fcoe_port, transport, fcoe_transport_op );
+
+/******************************************************************************
+ *
+ * FIP protocol
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Parse FIP packet into descriptor set
+ *
+ * @v fcoe FCoE port
+ * @v fiphdr FIP header
+ * @v len Length of FIP packet
+ * @v descs Descriptor set to fill in
+ * @ret rc Return status code
+ */
+static int fcoe_fip_parse ( struct fcoe_port *fcoe, struct fip_header *fiphdr,
+ size_t len, struct fip_descriptors *descs ) {
+ union fip_descriptor *desc;
+ size_t descs_len;
+ size_t desc_len;
+ size_t desc_offset;
+ unsigned int desc_type;
+
+ /* Check FIP version */
+ if ( fiphdr->version != FIP_VERSION ) {
+ DBGC ( fcoe, "FCoE %s received unsupported FIP version %02x\n",
+ fcoe->netdev->name, fiphdr->version );
+ return -EINVAL;
+ }
+
+ /* Check length */
+ descs_len = ( ntohs ( fiphdr->len ) * 4 );
+ if ( ( sizeof ( *fiphdr ) + descs_len ) > len ) {
+ DBGC ( fcoe, "FCoE %s received bad descriptor list length\n",
+ fcoe->netdev->name );
+ return -EINVAL;
+ }
+
+ /* Parse descriptor list */
+ memset ( descs, 0, sizeof ( *descs ) );
+ for ( desc_offset = 0 ;
+ desc_offset <= ( descs_len - sizeof ( desc->common ) ) ;
+ desc_offset += desc_len ) {
+
+ /* Find descriptor and validate length */
+ desc = ( ( ( void * ) ( fiphdr + 1 ) ) + desc_offset );
+ desc_type = desc->common.type;
+ desc_len = ( desc->common.len * 4 );
+ if ( desc_len == 0 ) {
+ DBGC ( fcoe, "FCoE %s received zero-length "
+ "descriptor\n", fcoe->netdev->name );
+ return -EINVAL;
+ }
+ if ( ( desc_offset + desc_len ) > descs_len ) {
+ DBGC ( fcoe, "FCoE %s descriptor overrun\n",
+ fcoe->netdev->name );
+ return -EINVAL;
+ }
+
+ /* Handle descriptors that we understand */
+ if ( ( desc_type > FIP_RESERVED ) &&
+ ( desc_type < FIP_NUM_DESCRIPTOR_TYPES ) ) {
+ /* Use only the first instance of a descriptor */
+ if ( descs->desc[desc_type] == NULL )
+ descs->desc[desc_type] = desc;
+ continue;
+ }
+
+ /* Abort if we cannot understand a critical descriptor */
+ if ( FIP_IS_CRITICAL ( desc_type ) ) {
+ DBGC ( fcoe, "FCoE %s cannot understand critical "
+ "descriptor type %02x\n",
+ fcoe->netdev->name, desc_type );
+ return -ENOTSUP;
+ }
+
+ /* Ignore non-critical descriptors that we cannot understand */
+ }
+
+ return 0;
+}
+
+/**
+ * Send FIP VLAN request
+ *
+ * @v fcoe FCoE port
+ * @ret rc Return status code
+ */
+static int fcoe_fip_tx_vlan ( struct fcoe_port *fcoe ) {
+ struct io_buffer *iobuf;
+ struct {
+ struct fip_header hdr;
+ struct fip_mac_address mac_address;
+ } __attribute__ (( packed )) *request;
+ int rc;
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *request ) );
+ if ( ! iobuf )
+ return -ENOMEM;
+ iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
+
+ /* Construct VLAN request */
+ request = iob_put ( iobuf, sizeof ( *request ) );
+ memset ( request, 0, sizeof ( *request ) );
+ request->hdr.version = FIP_VERSION;
+ request->hdr.code = htons ( FIP_CODE_VLAN );
+ request->hdr.subcode = FIP_VLAN_REQUEST;
+ request->hdr.len = htons ( ( sizeof ( *request ) -
+ sizeof ( request->hdr ) ) / 4 );
+ request->mac_address.type = FIP_MAC_ADDRESS;
+ request->mac_address.len =
+ ( sizeof ( request->mac_address ) / 4 );
+ memcpy ( request->mac_address.mac, fcoe->netdev->ll_addr,
+ sizeof ( request->mac_address.mac ) );
+
+ /* Send VLAN request */
+ if ( ( rc = net_tx ( iob_disown ( iobuf ), fcoe->netdev,
+ &fip_protocol, all_fcf_macs,
+ fcoe->netdev->ll_addr ) ) != 0 ) {
+ DBGC ( fcoe, "FCoE %s could not send VLAN request: "
+ "%s\n", fcoe->netdev->name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle received FIP VLAN notification
+ *
+ * @v fcoe FCoE port
+ * @v descs Descriptor list
+ * @v flags Flags
+ * @ret rc Return status code
+ */
+static int fcoe_fip_rx_vlan ( struct fcoe_port *fcoe,
+ struct fip_descriptors *descs,
+ unsigned int flags __unused ) {
+ struct fip_mac_address *mac_address = fip_mac_address ( descs );
+ struct fip_vlan *vlan = fip_vlan ( descs );
+ unsigned int tag;
+ int rc;
+
+ /* Sanity checks */
+ if ( ! mac_address ) {
+ DBGC ( fcoe, "FCoE %s received VLAN notification missing MAC "
+ "address\n", fcoe->netdev->name );
+ return -EINVAL;
+ }
+ if ( ! vlan ) {
+ DBGC ( fcoe, "FCoE %s received VLAN notification missing VLAN "
+ "tag\n", fcoe->netdev->name );
+ return -EINVAL;
+ }
+
+ /* Create VLAN */
+ tag = ntohs ( vlan->vlan );
+ DBGC ( fcoe, "FCoE %s creating VLAN %d for FCF %s\n",
+ fcoe->netdev->name, tag, eth_ntoa ( mac_address->mac ) );
+ if ( ( rc = vlan_create ( fcoe->netdev, tag,
+ FCOE_VLAN_PRIORITY ) ) != 0 ) {
+ DBGC ( fcoe, "FCoE %s could not create VLAN %d: %s\n",
+ fcoe->netdev->name, tag, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Record that a VLAN was found. This FCoE port will play no
+ * further active role; the real FCoE traffic will use the
+ * port automatically created for the new VLAN device.
+ */
+ fcoe->flags |= FCOE_VLAN_FOUND;
+
+ return 0;
+}
+
+/**
+ * Send FIP discovery solicitation
+ *
+ * @v fcoe FCoE port
+ * @ret rc Return status code
+ */
+static int fcoe_fip_tx_solicitation ( struct fcoe_port *fcoe ) {
+ struct io_buffer *iobuf;
+ struct {
+ struct fip_header hdr;
+ struct fip_mac_address mac_address;
+ struct fip_name_id name_id;
+ struct fip_max_fcoe_size max_fcoe_size;
+ } __attribute__ (( packed )) *solicitation;
+ int rc;
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *solicitation ) );
+ if ( ! iobuf )
+ return -ENOMEM;
+ iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
+
+ /* Construct discovery solicitation */
+ solicitation = iob_put ( iobuf, sizeof ( *solicitation ) );
+ memset ( solicitation, 0, sizeof ( *solicitation ) );
+ solicitation->hdr.version = FIP_VERSION;
+ solicitation->hdr.code = htons ( FIP_CODE_DISCOVERY );
+ solicitation->hdr.subcode = FIP_DISCOVERY_SOLICIT;
+ solicitation->hdr.len = htons ( ( sizeof ( *solicitation ) -
+ sizeof ( solicitation->hdr ) ) / 4 );
+ solicitation->hdr.flags = htons ( FIP_FP | FIP_SP );
+ solicitation->mac_address.type = FIP_MAC_ADDRESS;
+ solicitation->mac_address.len =
+ ( sizeof ( solicitation->mac_address ) / 4 );
+ memcpy ( solicitation->mac_address.mac, fcoe->netdev->ll_addr,
+ sizeof ( solicitation->mac_address.mac ) );
+ solicitation->name_id.type = FIP_NAME_ID;
+ solicitation->name_id.len = ( sizeof ( solicitation->name_id ) / 4 );
+ memcpy ( &solicitation->name_id.name, &fcoe->node_wwn.fc,
+ sizeof ( solicitation->name_id.name ) );
+ solicitation->max_fcoe_size.type = FIP_MAX_FCOE_SIZE;
+ solicitation->max_fcoe_size.len =
+ ( sizeof ( solicitation->max_fcoe_size ) / 4 );
+ solicitation->max_fcoe_size.mtu =
+ htons ( ETH_MAX_MTU - sizeof ( struct fcoe_header ) -
+ sizeof ( struct fcoe_footer ) );
+
+ /* Send discovery solicitation */
+ if ( ( rc = net_tx ( iob_disown ( iobuf ), fcoe->netdev,
+ &fip_protocol, all_fcf_macs,
+ fcoe->netdev->ll_addr ) ) != 0 ) {
+ DBGC ( fcoe, "FCoE %s could not send discovery solicitation: "
+ "%s\n", fcoe->netdev->name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle received FIP discovery advertisement
+ *
+ * @v fcoe FCoE port
+ * @v descs Descriptor list
+ * @v flags Flags
+ * @ret rc Return status code
+ */
+static int fcoe_fip_rx_advertisement ( struct fcoe_port *fcoe,
+ struct fip_descriptors *descs,
+ unsigned int flags ) {
+ struct fip_priority *priority = fip_priority ( descs );
+ struct fip_mac_address *mac_address = fip_mac_address ( descs );
+ struct fip_fka_adv_p *fka_adv_p = fip_fka_adv_p ( descs );
+
+ /* Sanity checks */
+ if ( ! priority ) {
+ DBGC ( fcoe, "FCoE %s received advertisement missing "
+ "priority\n", fcoe->netdev->name );
+ return -EINVAL;
+ }
+ if ( ! mac_address ) {
+ DBGC ( fcoe, "FCoE %s received advertisement missing MAC "
+ "address\n", fcoe->netdev->name );
+ return -EINVAL;
+ }
+ if ( ! fka_adv_p ) {
+ DBGC ( fcoe, "FCoE %s received advertisement missing FKA ADV "
+ "period\n", fcoe->netdev->name );
+ return -EINVAL;
+ }
+
+ if ( ! ( fcoe->flags & FCOE_HAVE_FCF ) ) {
+
+ /* We are soliciting for an FCF. Store the highest
+ * (i.e. lowest-valued) priority solicited
+ * advertisement that we receive.
+ */
+ if ( ( ( flags & ( FIP_A | FIP_S | FIP_F ) ) ==
+ ( FIP_A | FIP_S | FIP_F ) ) &&
+ ( priority->priority < fcoe->priority ) ) {
+
+ fcoe->flags |= FCOE_HAVE_FIP_FCF;
+ fcoe->priority = priority->priority;
+ if ( fka_adv_p->flags & FIP_NO_KEEPALIVE ) {
+ fcoe->keepalive = 0;
+ } else {
+ fcoe->keepalive = ntohl ( fka_adv_p->period );
+ }
+ fcoe->flags &= ~FCOE_FCF_ALLOWS_SPMA;
+ if ( flags & FIP_SP )
+ fcoe->flags |= FCOE_FCF_ALLOWS_SPMA;
+ memcpy ( fcoe->fcf_mac, mac_address->mac,
+ sizeof ( fcoe->fcf_mac ) );
+ DBGC ( fcoe, "FCoE %s selected FCF %s (pri %d",
+ fcoe->netdev->name, eth_ntoa ( fcoe->fcf_mac ),
+ fcoe->priority );
+ if ( fcoe->keepalive ) {
+ DBGC ( fcoe, ", FKA ADV %dms",
+ fcoe->keepalive );
+ }
+ DBGC ( fcoe, ", %cPMA)\n",
+ ( ( fcoe->flags & FCOE_FCF_ALLOWS_SPMA ) ?
+ 'S' : 'F' ) );
+ }
+
+ } else if ( fcoe->flags & FCOE_HAVE_FIP_FCF ) {
+
+ /* We are checking that the FCF remains alive. Reset
+ * the timeout counter if this is an advertisement
+ * from our forwarder.
+ */
+ if ( memcmp ( fcoe->fcf_mac, mac_address->mac,
+ sizeof ( fcoe->fcf_mac ) ) == 0 ) {
+ fcoe->timeouts = 0;
+ }
+
+ } else {
+
+ /* We are operating in non-FIP mode and have received
+ * a FIP advertisement. Reset the link in order to
+ * attempt FIP.
+ */
+ fcoe_reset ( fcoe );
+
+ }
+
+ return 0;
+}
+
+/**
+ * Handle received FIP ELS response
+ *
+ * @v fcoe FCoE port
+ * @v descs Descriptor list
+ * @v flags Flags
+ * @ret rc Return status code
+ */
+static int fcoe_fip_rx_els_response ( struct fcoe_port *fcoe,
+ struct fip_descriptors *descs,
+ unsigned int flags __unused ) {
+ struct fip_els *flogi = fip_flogi ( descs );
+ struct fip_mac_address *mac_address = fip_mac_address ( descs );
+ void *frame;
+ size_t frame_len;
+ int rc;
+
+ /* Sanity checks */
+ if ( ! flogi ) {
+ DBGC ( fcoe, "FCoE %s received ELS response missing FLOGI\n",
+ fcoe->netdev->name );
+ return -EINVAL;
+ }
+ if ( ! mac_address ) {
+ DBGC ( fcoe, "FCoE %s received ELS response missing MAC "
+ "address\n", fcoe->netdev->name );
+ return -EINVAL;
+ }
+
+ /* Record local MAC address */
+ memcpy ( fcoe->local_mac, mac_address->mac, sizeof ( fcoe->local_mac ));
+ DBGC ( fcoe, "FCoE %s using local MAC %s\n",
+ fcoe->netdev->name, eth_ntoa ( fcoe->local_mac ) );
+
+ /* Hand off via transport interface */
+ frame = &flogi->fc;
+ frame_len = ( ( flogi->len * 4 ) - offsetof ( typeof ( *flogi ), fc ) );
+ if ( ( rc = xfer_deliver_raw ( &fcoe->transport, frame,
+ frame_len ) ) != 0 ) {
+ DBGC ( fcoe, "FCoE %s could not deliver FIP FLOGI frame: %s\n",
+ fcoe->netdev->name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Send FIP keepalive
+ *
+ * @v fcoe FCoE port
+ * @ret rc Return status code
+ */
+static int fcoe_fip_tx_keepalive ( struct fcoe_port *fcoe ) {
+ struct io_buffer *iobuf;
+ struct {
+ struct fip_header hdr;
+ struct fip_mac_address mac_address;
+ } __attribute__ (( packed )) *keepalive;
+ int rc;
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *keepalive ) );
+ if ( ! iobuf )
+ return -ENOMEM;
+ iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
+
+ /* Construct keepalive */
+ keepalive = iob_put ( iobuf, sizeof ( *keepalive ) );
+ memset ( keepalive, 0, sizeof ( *keepalive ) );
+ keepalive->hdr.version = FIP_VERSION;
+ keepalive->hdr.code = htons ( FIP_CODE_MAINTAIN );
+ keepalive->hdr.subcode = FIP_MAINTAIN_KEEP_ALIVE;
+ keepalive->hdr.len = htons ( ( sizeof ( *keepalive ) -
+ sizeof ( keepalive->hdr ) ) / 4 );
+ keepalive->mac_address.type = FIP_MAC_ADDRESS;
+ keepalive->mac_address.len =
+ ( sizeof ( keepalive->mac_address ) / 4 );
+ memcpy ( keepalive->mac_address.mac, fcoe->netdev->ll_addr,
+ sizeof ( keepalive->mac_address.mac ) );
+
+ /* Send keepalive */
+ if ( ( rc = net_tx ( iob_disown ( iobuf ), fcoe->netdev,
+ &fip_protocol, fcoe->fcf_mac,
+ fcoe->netdev->ll_addr ) ) != 0 ) {
+ DBGC ( fcoe, "FCoE %s could not send keepalive: %s\n",
+ fcoe->netdev->name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/** A FIP handler */
+struct fip_handler {
+ /** Protocol code */
+ uint16_t code;
+ /** Protocol subcode */
+ uint8_t subcode;
+ /**
+ * Receive FIP packet
+ *
+ * @v fcoe FCoE port
+ * @v descs Descriptor list
+ * @v flags Flags
+ * @ret rc Return status code
+ */
+ int ( * rx ) ( struct fcoe_port *fcoe, struct fip_descriptors *descs,
+ unsigned int flags );
+};
+
+/** FIP handlers */
+static struct fip_handler fip_handlers[] = {
+ { FIP_CODE_VLAN, FIP_VLAN_NOTIFY,
+ fcoe_fip_rx_vlan },
+ { FIP_CODE_DISCOVERY, FIP_DISCOVERY_ADVERTISE,
+ fcoe_fip_rx_advertisement },
+ { FIP_CODE_ELS, FIP_ELS_RESPONSE,
+ fcoe_fip_rx_els_response },
+};
+
+/**
+ * Process incoming FIP packets
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer source address
+ * @v flags Packet flags
+ * @ret rc Return status code
+ */
+static int fcoe_fip_rx ( struct io_buffer *iobuf,
+ struct net_device *netdev,
+ const void *ll_dest,
+ const void *ll_source __unused,
+ unsigned int flags __unused ) {
+ struct fip_header *fiphdr = iobuf->data;
+ struct fip_descriptors descs;
+ struct fip_handler *handler;
+ struct fcoe_port *fcoe;
+ unsigned int i;
+ int rc;
+
+ /* Identify FCoE port */
+ if ( ( fcoe = fcoe_demux ( netdev ) ) == NULL ) {
+ DBG ( "FCoE received FIP frame for net device %s missing FCoE "
+ "port\n", netdev->name );
+ rc = -ENOTCONN;
+ goto done;
+ }
+
+ /* Discard packets not destined for us */
+ if ( ( memcmp ( fcoe->netdev->ll_addr, ll_dest, ETH_ALEN ) != 0 ) &&
+ ( memcmp ( all_fcoe_macs, ll_dest,
+ sizeof ( all_fcoe_macs ) ) != 0 ) &&
+ ( memcmp ( all_enode_macs, ll_dest,
+ sizeof ( all_enode_macs ) ) != 0 ) ) {
+ DBGC2 ( fcoe, "FCoE %s ignoring FIP packet for %s\n",
+ fcoe->netdev->name, eth_ntoa ( ll_dest ) );
+ rc = -ENOTCONN;
+ goto done;
+ }
+
+ /* Parse FIP packet */
+ if ( ( rc = fcoe_fip_parse ( fcoe, fiphdr, iob_len ( iobuf ),
+ &descs ) ) != 0 )
+ goto done;
+
+ /* Find a suitable handler */
+ for ( i = 0 ; i < ( sizeof ( fip_handlers ) /
+ sizeof ( fip_handlers[0] ) ) ; i++ ) {
+ handler = &fip_handlers[i];
+ if ( ( handler->code == ntohs ( fiphdr->code ) ) &&
+ ( handler->subcode == fiphdr->subcode ) ) {
+ rc = handler->rx ( fcoe, &descs,
+ ntohs ( fiphdr->flags ) );
+ goto done;
+ }
+ }
+ DBGC ( fcoe, "FCoE %s received unsupported FIP code %04x.%02x\n",
+ fcoe->netdev->name, ntohs ( fiphdr->code ), fiphdr->subcode );
+ rc = -ENOTSUP;
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/******************************************************************************
+ *
+ * FCoE ports
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Handle FCoE timer expiry
+ *
+ * @v timer FIP timer
+ * @v over Timer expired
+ */
+static void fcoe_expired ( struct retry_timer *timer, int over __unused ) {
+ struct fcoe_port *fcoe =
+ container_of ( timer, struct fcoe_port, timer );
+ int rc;
+
+ /* Sanity check */
+ assert ( fcoe->flags & FCOE_HAVE_NETWORK );
+
+ /* Increment the timeout counter */
+ fcoe->timeouts++;
+
+ if ( vlan_can_be_trunk ( fcoe->netdev ) &
+ ! ( fcoe->flags & FCOE_VLAN_TIMED_OUT ) ) {
+
+ /* If we have already found a VLAN, send infrequent
+ * VLAN requests, in case VLAN information changes.
+ */
+ if ( fcoe->flags & FCOE_VLAN_FOUND ) {
+ fcoe->flags &= ~FCOE_VLAN_FOUND;
+ fcoe->timeouts = 0;
+ start_timer_fixed ( &fcoe->timer,
+ FCOE_VLAN_POLL_DELAY );
+ fcoe_fip_tx_vlan ( fcoe );
+ return;
+ }
+
+ /* If we have not yet found a VLAN, and we have not
+ * yet timed out and given up on finding one, then
+ * send a VLAN request and wait.
+ */
+ if ( fcoe->timeouts <= FCOE_MAX_VLAN_REQUESTS ) {
+ start_timer_fixed ( &fcoe->timer,
+ FCOE_VLAN_RETRY_DELAY );
+ fcoe_fip_tx_vlan ( fcoe );
+ return;
+ }
+
+ /* We have timed out waiting for a VLAN; proceed to
+ * FIP discovery.
+ */
+ fcoe->flags |= FCOE_VLAN_TIMED_OUT;
+ fcoe->timeouts = 0;
+ DBGC ( fcoe, "FCoE %s giving up on VLAN discovery\n",
+ fcoe->netdev->name );
+ start_timer_nodelay ( &fcoe->timer );
+
+ } else if ( ! ( fcoe->flags & FCOE_HAVE_FCF ) ) {
+
+ /* If we have not yet found a FIP-capable forwarder,
+ * and we have not yet timed out and given up on
+ * finding one, then send a FIP solicitation and wait.
+ */
+ start_timer_fixed ( &fcoe->timer, FCOE_FIP_RETRY_DELAY );
+ if ( ( ! ( fcoe->flags & FCOE_HAVE_FIP_FCF ) ) &&
+ ( fcoe->timeouts <= FCOE_MAX_FIP_SOLICITATIONS ) ) {
+ fcoe_fip_tx_solicitation ( fcoe );
+ return;
+ }
+
+ /* Attach Fibre Channel port */
+ if ( ( rc = fc_port_open ( &fcoe->transport, &fcoe->node_wwn.fc,
+ &fcoe->port_wwn.fc,
+ fcoe->netdev->name ) ) != 0 ) {
+ DBGC ( fcoe, "FCoE %s could not create FC port: %s\n",
+ fcoe->netdev->name, strerror ( rc ) );
+ /* We will try again on the next timer expiry */
+ return;
+ }
+ stop_timer ( &fcoe->timer );
+
+ /* Either we have found a FIP-capable forwarder, or we
+ * have timed out and will fall back to pre-FIP mode.
+ */
+ fcoe->flags |= FCOE_HAVE_FCF;
+ fcoe->timeouts = 0;
+ DBGC ( fcoe, "FCoE %s using %sFIP FCF %s\n", fcoe->netdev->name,
+ ( ( fcoe->flags & FCOE_HAVE_FIP_FCF ) ? "" : "non-" ),
+ eth_ntoa ( fcoe->fcf_mac ) );
+
+ /* Start sending keepalives if applicable */
+ if ( fcoe->keepalive )
+ start_timer_nodelay ( &fcoe->timer );
+
+ /* Send notification of window change */
+ xfer_window_changed ( &fcoe->transport );
+
+ } else {
+
+ /* Send keepalive */
+ start_timer_fixed ( &fcoe->timer,
+ ( ( fcoe->keepalive * TICKS_PER_SEC ) / 1000 ) );
+ fcoe_fip_tx_keepalive ( fcoe );
+
+ /* Abandon FCF if we have not seen its advertisements */
+ if ( fcoe->timeouts > FCOE_MAX_FIP_MISSING_KEEPALIVES ) {
+ DBGC ( fcoe, "FCoE %s abandoning FCF %s\n",
+ fcoe->netdev->name, eth_ntoa ( fcoe->fcf_mac ));
+ fcoe_reset ( fcoe );
+ }
+ }
+}
+
+/**
+ * Create FCoE port
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int fcoe_probe ( struct net_device *netdev ) {
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+ struct fcoe_port *fcoe;
+ int rc;
+
+ /* Sanity check */
+ if ( ll_protocol->ll_proto != htons ( ARPHRD_ETHER ) ) {
+ /* Not an error; simply skip this net device */
+ DBG ( "FCoE skipping non-Ethernet device %s\n", netdev->name );
+ rc = 0;
+ goto err_non_ethernet;
+ }
+
+ /* Allocate and initialise structure */
+ fcoe = zalloc ( sizeof ( *fcoe ) );
+ if ( ! fcoe ) {
+ rc = -ENOMEM;
+ goto err_zalloc;
+ }
+ ref_init ( &fcoe->refcnt, NULL );
+ intf_init ( &fcoe->transport, &fcoe_transport_desc, &fcoe->refcnt );
+ timer_init ( &fcoe->timer, fcoe_expired, &fcoe->refcnt );
+ fcoe->netdev = netdev_get ( netdev );
+
+ /* Construct node and port names */
+ fcoe->node_wwn.fcoe.authority = htons ( FCOE_AUTHORITY_IEEE );
+ memcpy ( &fcoe->node_wwn.fcoe.mac, netdev->ll_addr,
+ sizeof ( fcoe->node_wwn.fcoe.mac ) );
+ fcoe->port_wwn.fcoe.authority = htons ( FCOE_AUTHORITY_IEEE_EXTENDED );
+ memcpy ( &fcoe->port_wwn.fcoe.mac, netdev->ll_addr,
+ sizeof ( fcoe->port_wwn.fcoe.mac ) );
+
+ DBGC ( fcoe, "FCoE %s is %s", fcoe->netdev->name,
+ fc_ntoa ( &fcoe->node_wwn.fc ) );
+ DBGC ( fcoe, " port %s\n", fc_ntoa ( &fcoe->port_wwn.fc ) );
+
+ /* Transfer reference to port list */
+ list_add ( &fcoe->list, &fcoe_ports );
+ return 0;
+
+ netdev_put ( fcoe->netdev );
+ err_zalloc:
+ err_non_ethernet:
+ return rc;
+}
+
+/**
+ * Handle FCoE port device or link state change
+ *
+ * @v netdev Network device
+ */
+static void fcoe_notify ( struct net_device *netdev ) {
+ struct fcoe_port *fcoe;
+
+ /* Sanity check */
+ if ( ( fcoe = fcoe_demux ( netdev ) ) == NULL ) {
+ DBG ( "FCoE notification for net device %s missing FCoE "
+ "port\n", netdev->name );
+ return;
+ }
+
+ /* Reset the FCoE link if necessary */
+ if ( ! ( netdev_is_open ( netdev ) &&
+ netdev_link_ok ( netdev ) &&
+ ( fcoe->flags & FCOE_HAVE_NETWORK ) ) ) {
+ fcoe_reset ( fcoe );
+ }
+}
+
+/**
+ * Destroy FCoE port
+ *
+ * @v netdev Network device
+ */
+static void fcoe_remove ( struct net_device *netdev ) {
+ struct fcoe_port *fcoe;
+
+ /* Sanity check */
+ if ( ( fcoe = fcoe_demux ( netdev ) ) == NULL ) {
+ DBG ( "FCoE removal of net device %s missing FCoE port\n",
+ netdev->name );
+ return;
+ }
+
+ /* Close FCoE device */
+ fcoe_close ( fcoe, 0 );
+}
+
+/** FCoE driver */
+struct net_driver fcoe_driver __net_driver = {
+ .name = "FCoE",
+ .probe = fcoe_probe,
+ .notify = fcoe_notify,
+ .remove = fcoe_remove,
+};
+
+/** FCoE protocol */
+struct net_protocol fcoe_protocol __net_protocol = {
+ .name = "FCoE",
+ .net_proto = htons ( ETH_P_FCOE ),
+ .rx = fcoe_rx,
+};
+
+/** FIP protocol */
+struct net_protocol fip_protocol __net_protocol = {
+ .name = "FIP",
+ .net_proto = htons ( ETH_P_FIP ),
+ .rx = fcoe_fip_rx,
+};
+
+/** Human-readable message for CRC errors
+ *
+ * It seems as though several drivers neglect to strip the Ethernet
+ * CRC, which will cause the FCoE footer to be misplaced and result
+ * (coincidentally) in an "invalid CRC" error from FCoE.
+ */
+struct errortab fcoe_errors[] __errortab = {
+ __einfo_errortab ( EINFO_EINVAL_CRC ),
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/fcp.c b/src/VBox/Devices/PC/ipxe/src/net/fcp.c
new file mode 100644
index 00000000..bd1a0900
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/fcp.c
@@ -0,0 +1,1092 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/list.h>
+#include <ipxe/interface.h>
+#include <ipxe/xfer.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/open.h>
+#include <ipxe/process.h>
+#include <ipxe/uri.h>
+#include <ipxe/acpi.h>
+#include <ipxe/scsi.h>
+#include <ipxe/device.h>
+#include <ipxe/edd.h>
+#include <ipxe/fc.h>
+#include <ipxe/fcels.h>
+#include <ipxe/fcp.h>
+
+/** @file
+ *
+ * Fibre Channel Protocol
+ *
+ */
+
+/* Disambiguate the various error causes */
+#define ERANGE_READ_DATA_ORDERING \
+ __einfo_error ( EINFO_ERANGE_READ_DATA_ORDERING )
+#define EINFO_ERANGE_READ_DATA_ORDERING \
+ __einfo_uniqify ( EINFO_ERANGE, 0x01, "Read data out of order" )
+#define ERANGE_READ_DATA_OVERRUN \
+ __einfo_error ( EINFO_ERANGE_READ_DATA_OVERRUN )
+#define EINFO_ERANGE_READ_DATA_OVERRUN \
+ __einfo_uniqify ( EINFO_ERANGE, 0x02, "Read data overrun" )
+#define ERANGE_WRITE_DATA_STUCK \
+ __einfo_error ( EINFO_ERANGE_WRITE_DATA_STUCK )
+#define EINFO_ERANGE_WRITE_DATA_STUCK \
+ __einfo_uniqify ( EINFO_ERANGE, 0x03, "Write data stuck" )
+#define ERANGE_WRITE_DATA_OVERRUN \
+ __einfo_error ( EINFO_ERANGE_WRITE_DATA_OVERRUN )
+#define EINFO_ERANGE_WRITE_DATA_OVERRUN \
+ __einfo_uniqify ( EINFO_ERANGE, 0x04, "Write data overrun" )
+#define ERANGE_DATA_UNDERRUN \
+ __einfo_error ( EINFO_ERANGE_DATA_UNDERRUN )
+#define EINFO_ERANGE_DATA_UNDERRUN \
+ __einfo_uniqify ( EINFO_ERANGE, 0x05, "Data underrun" )
+
+/******************************************************************************
+ *
+ * PRLI
+ *
+ ******************************************************************************
+ */
+
+struct fc_els_prli_descriptor fcp_prli_descriptor __fc_els_prli_descriptor;
+
+/**
+ * Transmit FCP PRLI
+ *
+ * @v els Fibre Channel ELS transaction
+ * @ret rc Return status code
+ */
+static int fcp_prli_tx ( struct fc_els *els ) {
+ struct fcp_prli_service_parameters param;
+
+ /* Build service parameter page */
+ memset ( &param, 0, sizeof ( param ) );
+ param.flags = htonl ( FCP_PRLI_NO_READ_RDY | FCP_PRLI_INITIATOR );
+
+ return fc_els_prli_tx ( els, &fcp_prli_descriptor, &param );
+}
+
+/**
+ * Receive FCP PRLI
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v frame ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fcp_prli_rx ( struct fc_els *els, void *data, size_t len ) {
+ return fc_els_prli_rx ( els, &fcp_prli_descriptor, data, len );
+}
+
+/**
+ * Detect FCP PRLI
+ *
+ * @v els Fibre Channel ELS transaction
+ * @v data ELS frame
+ * @v len Length of ELS frame
+ * @ret rc Return status code
+ */
+static int fcp_prli_detect ( struct fc_els *els, const void *data,
+ size_t len ) {
+ return fc_els_prli_detect ( els, &fcp_prli_descriptor, data, len );
+}
+
+/** FCP PRLI ELS handler */
+struct fc_els_handler fcp_prli_handler __fc_els_handler = {
+ .name = "PRLI-FCP",
+ .tx = fcp_prli_tx,
+ .rx = fcp_prli_rx,
+ .detect = fcp_prli_detect,
+};
+
+/** FCP PRLI descriptor */
+struct fc_els_prli_descriptor fcp_prli_descriptor __fc_els_prli_descriptor = {
+ .type = FC_TYPE_FCP,
+ .param_len = sizeof ( struct fcp_prli_service_parameters ),
+ .handler = &fcp_prli_handler,
+};
+
+/******************************************************************************
+ *
+ * FCP devices and commands
+ *
+ ******************************************************************************
+ */
+
+/** An FCP device */
+struct fcp_device {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Fibre Channel upper-layer protocol user */
+ struct fc_ulp_user user;
+ /** SCSI command issuing interface */
+ struct interface scsi;
+ /** List of active commands */
+ struct list_head fcpcmds;
+
+ /** Fibre Channel WWN (for boot firmware table) */
+ struct fc_name wwn;
+ /** SCSI LUN (for boot firmware table) */
+ struct scsi_lun lun;
+};
+
+/** An FCP command */
+struct fcp_command {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** FCP SCSI device */
+ struct fcp_device *fcpdev;
+ /** List of active commands */
+ struct list_head list;
+ /** SCSI command interface */
+ struct interface scsi;
+ /** Fibre Channel exchange interface */
+ struct interface xchg;
+ /** Send process */
+ struct process process;
+ /** Send current IU
+ *
+ * @v fcpcmd FCP command
+ * @ret rc Return status code
+ */
+ int ( * send ) ( struct fcp_command *fcpcmd );
+ /** SCSI command */
+ struct scsi_cmd command;
+ /** Data offset within command */
+ size_t offset;
+ /** Length of data remaining to be sent within this IU */
+ size_t remaining;
+ /** Exchange ID */
+ uint16_t xchg_id;
+};
+
+/**
+ * Get reference to FCP device
+ *
+ * @v fcpdev FCP device
+ * @ret fcpdev FCP device
+ */
+static inline __attribute__ (( always_inline )) struct fcp_device *
+fcpdev_get ( struct fcp_device *fcpdev ) {
+ ref_get ( &fcpdev->refcnt );
+ return fcpdev;
+}
+
+/**
+ * Drop reference to FCP device
+ *
+ * @v fcpdev FCP device
+ */
+static inline __attribute__ (( always_inline )) void
+fcpdev_put ( struct fcp_device *fcpdev ) {
+ ref_put ( &fcpdev->refcnt );
+}
+
+/**
+ * Get reference to FCP command
+ *
+ * @v fcpcmd FCP command
+ * @ret fcpcmd FCP command
+ */
+static inline __attribute__ (( always_inline )) struct fcp_command *
+fcpcmd_get ( struct fcp_command *fcpcmd ) {
+ ref_get ( &fcpcmd->refcnt );
+ return fcpcmd;
+}
+
+/**
+ * Drop reference to FCP command
+ *
+ * @v fcpcmd FCP command
+ */
+static inline __attribute__ (( always_inline )) void
+fcpcmd_put ( struct fcp_command *fcpcmd ) {
+ ref_put ( &fcpcmd->refcnt );
+}
+
+/**
+ * Start FCP command sending
+ *
+ * @v fcpcmd FCP command
+ * @v send Send method
+ */
+static inline __attribute__ (( always_inline )) void
+fcpcmd_start_send ( struct fcp_command *fcpcmd,
+ int ( * send ) ( struct fcp_command *fcpcmd ) ) {
+ fcpcmd->send = send;
+ process_add ( &fcpcmd->process );
+}
+
+/**
+ * Stop FCP command sending
+ *
+ * @v fcpcmd FCP command
+ */
+static inline __attribute__ (( always_inline )) void
+fcpcmd_stop_send ( struct fcp_command *fcpcmd ) {
+ process_del ( &fcpcmd->process );
+}
+
+/**
+ * Free FCP command
+ *
+ * @v refcnt Reference count
+ */
+static void fcpcmd_free ( struct refcnt *refcnt ) {
+ struct fcp_command *fcpcmd =
+ container_of ( refcnt, struct fcp_command, refcnt );
+
+ /* Remove from list of commands */
+ list_del ( &fcpcmd->list );
+ fcpdev_put ( fcpcmd->fcpdev );
+
+ /* Free command */
+ free ( fcpcmd );
+}
+
+/**
+ * Close FCP command
+ *
+ * @v fcpcmd FCP command
+ * @v rc Reason for close
+ */
+static void fcpcmd_close ( struct fcp_command *fcpcmd, int rc ) {
+ struct fcp_device *fcpdev = fcpcmd->fcpdev;
+
+ if ( rc != 0 ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x closed: %s\n",
+ fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
+ }
+
+ /* Stop sending */
+ fcpcmd_stop_send ( fcpcmd );
+
+ /* Shut down interfaces */
+ intf_shutdown ( &fcpcmd->scsi, rc );
+ intf_shutdown ( &fcpcmd->xchg, rc );
+}
+
+/**
+ * Close FCP command in error
+ *
+ * @v fcpcmd FCP command
+ * @v rc Reason for close
+ */
+static void fcpcmd_close_err ( struct fcp_command *fcpcmd, int rc ) {
+ if ( rc == 0 )
+ rc = -EPIPE;
+ fcpcmd_close ( fcpcmd, rc );
+}
+
+/**
+ * Send FCP command IU
+ *
+ * @v fcpcmd FCP command
+ * @ret rc Return status code
+ */
+static int fcpcmd_send_cmnd ( struct fcp_command *fcpcmd ) {
+ struct fcp_device *fcpdev = fcpcmd->fcpdev;
+ struct scsi_cmd *command = &fcpcmd->command;
+ struct io_buffer *iobuf;
+ struct fcp_cmnd *cmnd;
+ struct xfer_metadata meta;
+ int rc;
+
+ /* Sanity check */
+ if ( command->data_in_len && command->data_out_len ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x cannot handle bidirectional "
+ "command\n", fcpdev, fcpcmd->xchg_id );
+ return -ENOTSUP;
+ }
+
+ /* Allocate I/O buffer */
+ iobuf = xfer_alloc_iob ( &fcpcmd->xchg, sizeof ( *cmnd ) );
+ if ( ! iobuf ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x cannot allocate command IU\n",
+ fcpdev, fcpcmd->xchg_id );
+ return -ENOMEM;
+ }
+
+ /* Construct command IU frame */
+ cmnd = iob_put ( iobuf, sizeof ( *cmnd ) );
+ memset ( cmnd, 0, sizeof ( *cmnd ) );
+ memcpy ( &cmnd->lun, &command->lun, sizeof ( cmnd->lun ) );
+ assert ( ! ( command->data_in_len && command->data_out_len ) );
+ if ( command->data_in_len )
+ cmnd->dirn |= FCP_CMND_RDDATA;
+ if ( command->data_out_len )
+ cmnd->dirn |= FCP_CMND_WRDATA;
+ memcpy ( &cmnd->cdb, &fcpcmd->command.cdb, sizeof ( cmnd->cdb ) );
+ cmnd->len = htonl ( command->data_in_len + command->data_out_len );
+ memset ( &meta, 0, sizeof ( meta ) );
+ meta.flags = ( XFER_FL_CMD_STAT | XFER_FL_OVER );
+ DBGC2 ( fcpdev, "FCP %p xchg %04x CMND " SCSI_CDB_FORMAT " %04x\n",
+ fcpdev, fcpcmd->xchg_id, SCSI_CDB_DATA ( cmnd->cdb ),
+ ntohl ( cmnd->len ) );
+
+ /* No further data to send within this IU */
+ fcpcmd_stop_send ( fcpcmd );
+
+ /* Send command IU frame */
+ if ( ( rc = xfer_deliver ( &fcpcmd->xchg, iob_disown ( iobuf ),
+ &meta ) ) != 0 ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x cannot deliver command IU: "
+ "%s\n", fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle FCP read data IU
+ *
+ * @v fcpcmd FCP command
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int fcpcmd_recv_rddata ( struct fcp_command *fcpcmd,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct fcp_device *fcpdev = fcpcmd->fcpdev;
+ struct scsi_cmd *command = &fcpcmd->command;
+ size_t offset = meta->offset;
+ size_t len = iob_len ( iobuf );
+ int rc;
+
+ /* Sanity checks */
+ if ( ! ( meta->flags & XFER_FL_ABS_OFFSET ) ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x read data missing offset\n",
+ fcpdev, fcpcmd->xchg_id );
+ rc = -ERANGE_READ_DATA_ORDERING;
+ goto done;
+ }
+ if ( offset != fcpcmd->offset ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x read data out of order "
+ "(expected %zd, received %zd)\n",
+ fcpdev, fcpcmd->xchg_id, fcpcmd->offset, offset );
+ rc = -ERANGE_READ_DATA_ORDERING;
+ goto done;
+ }
+ if ( ( offset + len ) > command->data_in_len ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x read data overrun (max %zd, "
+ "received %zd)\n", fcpdev, fcpcmd->xchg_id,
+ command->data_in_len, ( offset + len ) );
+ rc = -ERANGE_READ_DATA_OVERRUN;
+ goto done;
+ }
+ DBGC2 ( fcpdev, "FCP %p xchg %04x RDDATA [%08zx,%08zx)\n",
+ fcpdev, fcpcmd->xchg_id, offset, ( offset + len ) );
+
+ /* Copy to user buffer */
+ copy_to_user ( command->data_in, offset, iobuf->data, len );
+ fcpcmd->offset += len;
+ assert ( fcpcmd->offset <= command->data_in_len );
+
+ rc = 0;
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Send FCP write data IU
+ *
+ * @v fcpcmd FCP command
+ * @ret rc Return status code
+ */
+static int fcpcmd_send_wrdata ( struct fcp_command *fcpcmd ) {
+ struct fcp_device *fcpdev = fcpcmd->fcpdev;
+ struct scsi_cmd *command = &fcpcmd->command;
+ struct io_buffer *iobuf;
+ struct xfer_metadata meta;
+ size_t len;
+ int rc;
+
+ /* Calculate length to be sent */
+ len = xfer_window ( &fcpcmd->xchg );
+ if ( len > fcpcmd->remaining )
+ len = fcpcmd->remaining;
+
+ /* Sanity checks */
+ if ( len == 0 ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x write data stuck\n",
+ fcpdev, fcpcmd->xchg_id );
+ return -ERANGE_WRITE_DATA_STUCK;
+ }
+ if ( ( fcpcmd->offset + len ) > command->data_out_len ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x write data overrun (max %zd, "
+ "requested %zd)\n", fcpdev, fcpcmd->xchg_id,
+ command->data_out_len, ( fcpcmd->offset + len ) );
+ return -ERANGE_WRITE_DATA_OVERRUN;
+ }
+
+ /* Allocate I/O buffer */
+ iobuf = xfer_alloc_iob ( &fcpcmd->xchg, len );
+ if ( ! iobuf ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x cannot allocate write data "
+ "IU for %zd bytes\n", fcpdev, fcpcmd->xchg_id, len );
+ return -ENOMEM;
+ }
+
+ /* Construct data IU frame */
+ copy_from_user ( iob_put ( iobuf, len ), command->data_out,
+ fcpcmd->offset, len );
+ memset ( &meta, 0, sizeof ( meta ) );
+ meta.flags = ( XFER_FL_RESPONSE | XFER_FL_ABS_OFFSET );
+ meta.offset = fcpcmd->offset;
+ DBGC2 ( fcpdev, "FCP %p xchg %04x WRDATA [%08zx,%04zx)\n",
+ fcpdev, fcpcmd->xchg_id, fcpcmd->offset,
+ ( fcpcmd->offset + iob_len ( iobuf ) ) );
+
+ /* Calculate amount of data remaining to be sent within this IU */
+ assert ( len <= fcpcmd->remaining );
+ fcpcmd->offset += len;
+ fcpcmd->remaining -= len;
+ assert ( fcpcmd->offset <= command->data_out_len );
+ if ( fcpcmd->remaining == 0 ) {
+ fcpcmd_stop_send ( fcpcmd );
+ meta.flags |= XFER_FL_OVER;
+ }
+
+ /* Send data IU frame */
+ if ( ( rc = xfer_deliver ( &fcpcmd->xchg, iob_disown ( iobuf ),
+ &meta ) ) != 0 ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x cannot deliver write data "
+ "IU: %s\n", fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle FCP transfer ready IU
+ *
+ * @v fcpcmd FCP command
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int fcpcmd_recv_xfer_rdy ( struct fcp_command *fcpcmd,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ struct fcp_device *fcpdev = fcpcmd->fcpdev;
+ struct fcp_xfer_rdy *xfer_rdy = iobuf->data;
+ int rc;
+
+ /* Sanity checks */
+ if ( iob_len ( iobuf ) != sizeof ( *xfer_rdy ) ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x received invalid transfer "
+ "ready IU:\n", fcpdev, fcpcmd->xchg_id );
+ DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
+ rc = -EPROTO;
+ goto done;
+ }
+ if ( ntohl ( xfer_rdy->offset ) != fcpcmd->offset ) {
+ /* We do not advertise out-of-order delivery */
+ DBGC ( fcpdev, "FCP %p xchg %04x cannot support out-of-order "
+ "delivery (expected %zd, requested %d)\n",
+ fcpdev, fcpcmd->xchg_id, fcpcmd->offset,
+ ntohl ( xfer_rdy->offset ) );
+ rc = -EPROTO;
+ goto done;
+ }
+ DBGC2 ( fcpdev, "FCP %p xchg %04x XFER_RDY [%08x,%08x)\n",
+ fcpdev, fcpcmd->xchg_id, ntohl ( xfer_rdy->offset ),
+ ( ntohl ( xfer_rdy->offset ) + ntohl ( xfer_rdy->len ) ) );
+
+ /* Start sending requested data */
+ fcpcmd->remaining = ntohl ( xfer_rdy->len );
+ fcpcmd_start_send ( fcpcmd, fcpcmd_send_wrdata );
+
+ rc = 0;
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Handle FCP response IU
+ *
+ * @v fcpcmd FCP command
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int fcpcmd_recv_rsp ( struct fcp_command *fcpcmd,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ struct fcp_device *fcpdev = fcpcmd->fcpdev;
+ struct scsi_cmd *command = &fcpcmd->command;
+ struct fcp_rsp *rsp = iobuf->data;
+ struct scsi_sense *sense;
+ struct scsi_rsp response;
+ int rc;
+
+ /* Sanity check */
+ if ( ( iob_len ( iobuf ) < sizeof ( *rsp ) ) ||
+ ( iob_len ( iobuf ) < ( sizeof ( *rsp ) +
+ fcp_rsp_response_data_len ( rsp ) +
+ fcp_rsp_sense_data_len ( rsp ) ) ) ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x received invalid response "
+ "IU:\n", fcpdev, fcpcmd->xchg_id );
+ DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
+ rc = -EPROTO;
+ goto done;
+ }
+ DBGC2 ( fcpdev, "FCP %p xchg %04x RSP stat %02x resid %08x flags %02x"
+ "%s%s%s%s\n", fcpdev, fcpcmd->xchg_id, rsp->status,
+ ntohl ( rsp->residual ), rsp->flags,
+ ( ( rsp->flags & FCP_RSP_RESPONSE_LEN_VALID ) ? " resp" : "" ),
+ ( ( rsp->flags & FCP_RSP_SENSE_LEN_VALID ) ? " sense" : "" ),
+ ( ( rsp->flags & FCP_RSP_RESIDUAL_OVERRUN ) ? " over" : "" ),
+ ( ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN ) ? " under" : "" ));
+ if ( fcp_rsp_response_data ( rsp ) ) {
+ DBGC2 ( fcpdev, "FCP %p xchg %04x response data:\n",
+ fcpdev, fcpcmd->xchg_id );
+ DBGC2_HDA ( fcpdev, 0, fcp_rsp_response_data ( rsp ),
+ fcp_rsp_response_data_len ( rsp ) );
+ }
+ if ( fcp_rsp_sense_data ( rsp ) ) {
+ DBGC2 ( fcpdev, "FCP %p xchg %04x sense data:\n",
+ fcpdev, fcpcmd->xchg_id );
+ DBGC2_HDA ( fcpdev, 0, fcp_rsp_sense_data ( rsp ),
+ fcp_rsp_sense_data_len ( rsp ) );
+ }
+
+ /* Check for locally-detected command underrun */
+ if ( ( rsp->status == 0 ) &&
+ ( fcpcmd->offset != ( command->data_in_len +
+ command->data_out_len ) ) ) {
+ DBGC ( fcpdev, "FCP %p xchg %04x data underrun (expected %zd, "
+ "got %zd)\n", fcpdev, fcpcmd->xchg_id,
+ ( command->data_in_len + command->data_out_len ),
+ fcpcmd->offset );
+ rc = -ERANGE_DATA_UNDERRUN;
+ goto done;
+ }
+
+ /* Build SCSI response */
+ memset ( &response, 0, sizeof ( response ) );
+ response.status = rsp->status;
+ if ( rsp->flags & ( FCP_RSP_RESIDUAL_OVERRUN |
+ FCP_RSP_RESIDUAL_UNDERRUN ) ) {
+ response.overrun = ntohl ( rsp->residual );
+ if ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN )
+ response.overrun = -response.overrun;
+ }
+ if ( ( sense = fcp_rsp_sense_data ( rsp ) ) != NULL )
+ memcpy ( &response.sense, sense, sizeof ( response.sense ) );
+
+ /* Free buffer before sending response, to minimise
+ * out-of-memory errors.
+ */
+ free_iob ( iob_disown ( iobuf ) );
+
+ /* Send SCSI response */
+ scsi_response ( &fcpcmd->scsi, &response );
+
+ /* Terminate command */
+ fcpcmd_close ( fcpcmd, 0 );
+
+ rc = 0;
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Handle unknown FCP IU
+ *
+ * @v fcpcmd FCP command
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int fcpcmd_recv_unknown ( struct fcp_command *fcpcmd,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ struct fcp_device *fcpdev = fcpcmd->fcpdev;
+
+ DBGC ( fcpdev, "FCP %p xchg %04x received unknown IU:\n",
+ fcpdev, fcpcmd->xchg_id );
+ DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
+ free_iob ( iobuf );
+ return -EPROTO;
+}
+
+/**
+ * Transmit FCP frame
+ *
+ * @v fcpcmd FCP command
+ */
+static void fcpcmd_step ( struct fcp_command *fcpcmd ) {
+ int rc;
+
+ /* Send the current IU */
+ if ( ( rc = fcpcmd->send ( fcpcmd ) ) != 0 ) {
+ /* Treat failure as a fatal error */
+ fcpcmd_close ( fcpcmd, rc );
+ }
+}
+
+/**
+ * Receive FCP frame
+ *
+ * @v fcpcmd FCP command
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int fcpcmd_deliver ( struct fcp_command *fcpcmd,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ int ( * fcpcmd_recv ) ( struct fcp_command *fcpcmd,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta );
+ int rc;
+
+ /* Determine handler */
+ switch ( meta->flags & ( XFER_FL_CMD_STAT | XFER_FL_RESPONSE ) ) {
+ case ( XFER_FL_RESPONSE ) :
+ fcpcmd_recv = fcpcmd_recv_rddata;
+ break;
+ case ( XFER_FL_CMD_STAT ) :
+ fcpcmd_recv = fcpcmd_recv_xfer_rdy;
+ break;
+ case ( XFER_FL_CMD_STAT | XFER_FL_RESPONSE ) :
+ fcpcmd_recv = fcpcmd_recv_rsp;
+ break;
+ default:
+ fcpcmd_recv = fcpcmd_recv_unknown;
+ break;
+ }
+
+ /* Handle IU */
+ if ( ( rc = fcpcmd_recv ( fcpcmd, iob_disown ( iobuf ), meta ) ) != 0 ){
+ /* Treat any error as fatal to the command */
+ fcpcmd_close ( fcpcmd, rc );
+ }
+
+ return rc;
+}
+
+/** FCP command SCSI interface operations */
+static struct interface_operation fcpcmd_scsi_op[] = {
+ INTF_OP ( intf_close, struct fcp_command *, fcpcmd_close ),
+};
+
+/** FCP command SCSI interface descriptor */
+static struct interface_descriptor fcpcmd_scsi_desc =
+ INTF_DESC_PASSTHRU ( struct fcp_command, scsi, fcpcmd_scsi_op, xchg );
+
+/** FCP command Fibre Channel exchange interface operations */
+static struct interface_operation fcpcmd_xchg_op[] = {
+ INTF_OP ( xfer_deliver, struct fcp_command *, fcpcmd_deliver ),
+ INTF_OP ( intf_close, struct fcp_command *, fcpcmd_close_err ),
+};
+
+/** FCP command Fibre Channel exchange interface descriptor */
+static struct interface_descriptor fcpcmd_xchg_desc =
+ INTF_DESC_PASSTHRU ( struct fcp_command, xchg, fcpcmd_xchg_op, scsi );
+
+/** FCP command process descriptor */
+static struct process_descriptor fcpcmd_process_desc =
+ PROC_DESC ( struct fcp_command, process, fcpcmd_step );
+
+/**
+ * Issue FCP SCSI command
+ *
+ * @v fcpdev FCP device
+ * @v parent Parent interface
+ * @v command SCSI command
+ * @ret tag Command tag, or negative error
+ */
+static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
+ struct interface *parent,
+ struct scsi_cmd *command ) {
+ struct fcp_prli_service_parameters *param = fcpdev->user.ulp->param;
+ struct fcp_command *fcpcmd;
+ int xchg_id;
+ int rc;
+
+ /* Check link */
+ if ( ( rc = fcpdev->user.ulp->link.rc ) != 0 ) {
+ DBGC ( fcpdev, "FCP %p could not issue command while link is "
+ "down: %s\n", fcpdev, strerror ( rc ) );
+ goto err_link;
+ }
+
+ /* Check target capability */
+ assert ( param != NULL );
+ assert ( fcpdev->user.ulp->param_len >= sizeof ( *param ) );
+ if ( ! ( param->flags & htonl ( FCP_PRLI_TARGET ) ) ) {
+ DBGC ( fcpdev, "FCP %p could not issue command: not a target\n",
+ fcpdev );
+ rc = -ENOTTY;
+ goto err_target;
+ }
+
+ /* Allocate and initialise structure */
+ fcpcmd = zalloc ( sizeof ( *fcpcmd ) );
+ if ( ! fcpcmd ) {
+ rc = -ENOMEM;
+ goto err_zalloc;
+ }
+ ref_init ( &fcpcmd->refcnt, fcpcmd_free );
+ intf_init ( &fcpcmd->scsi, &fcpcmd_scsi_desc, &fcpcmd->refcnt );
+ intf_init ( &fcpcmd->xchg, &fcpcmd_xchg_desc, &fcpcmd->refcnt );
+ process_init_stopped ( &fcpcmd->process, &fcpcmd_process_desc,
+ &fcpcmd->refcnt );
+ fcpcmd->fcpdev = fcpdev_get ( fcpdev );
+ list_add ( &fcpcmd->list, &fcpdev->fcpcmds );
+ memcpy ( &fcpcmd->command, command, sizeof ( fcpcmd->command ) );
+
+ /* Create new exchange */
+ if ( ( xchg_id = fc_xchg_originate ( &fcpcmd->xchg,
+ fcpdev->user.ulp->peer->port,
+ &fcpdev->user.ulp->peer->port_id,
+ FC_TYPE_FCP ) ) < 0 ) {
+ rc = xchg_id;
+ DBGC ( fcpdev, "FCP %p could not create exchange: %s\n",
+ fcpdev, strerror ( rc ) );
+ goto err_xchg_originate;
+ }
+ fcpcmd->xchg_id = xchg_id;
+
+ /* Start sending command IU */
+ fcpcmd_start_send ( fcpcmd, fcpcmd_send_cmnd );
+
+ /* Attach to parent interface, mortalise self, and return */
+ intf_plug_plug ( &fcpcmd->scsi, parent );
+ ref_put ( &fcpcmd->refcnt );
+ return ( FCP_TAG_MAGIC | fcpcmd->xchg_id );
+
+ err_xchg_originate:
+ fcpcmd_close ( fcpcmd, rc );
+ ref_put ( &fcpcmd->refcnt );
+ err_zalloc:
+ err_target:
+ err_link:
+ return rc;
+}
+
+/**
+ * Close FCP device
+ *
+ * @v fcpdev FCP device
+ * @v rc Reason for close
+ */
+static void fcpdev_close ( struct fcp_device *fcpdev, int rc ) {
+ struct fcp_command *fcpcmd;
+ struct fcp_command *tmp;
+
+ DBGC ( fcpdev, "FCP %p closed: %s\n", fcpdev, strerror ( rc ) );
+
+ /* Shut down interfaces */
+ intf_shutdown ( &fcpdev->scsi, rc );
+
+ /* Shut down any active commands */
+ list_for_each_entry_safe ( fcpcmd, tmp, &fcpdev->fcpcmds, list ) {
+ fcpcmd_get ( fcpcmd );
+ fcpcmd_close ( fcpcmd, rc );
+ fcpcmd_put ( fcpcmd );
+ }
+
+ /* Drop reference to ULP */
+ fc_ulp_detach ( &fcpdev->user );
+}
+
+/**
+ * Check FCP device flow-control window
+ *
+ * @v fcpdev FCP device
+ * @ret len Length of window
+ */
+static size_t fcpdev_window ( struct fcp_device *fcpdev ) {
+ return ( fc_link_ok ( &fcpdev->user.ulp->link ) ?
+ ~( ( size_t ) 0 ) : 0 );
+}
+
+/**
+ * Describe FCP device in an ACPI table
+ *
+ * @v fcpdev FCP device
+ * @v acpi ACPI table
+ * @v len Length of ACPI table
+ * @ret rc Return status code
+ */
+static int fcpdev_acpi_describe ( struct fcp_device *fcpdev,
+ struct acpi_description_header *acpi,
+ size_t len ) {
+
+ DBGC ( fcpdev, "FCP %p cannot yet describe device in an ACPI table\n",
+ fcpdev );
+ ( void ) acpi;
+ ( void ) len;
+ return 0;
+}
+
+/**
+ * Describe FCP device using EDD
+ *
+ * @v fcpdev FCP device
+ * @v type EDD interface type
+ * @v path EDD device path
+ * @ret rc Return status code
+ */
+static int fcpdev_edd_describe ( struct fcp_device *fcpdev,
+ struct edd_interface_type *type,
+ union edd_device_path *path ) {
+ union {
+ struct fc_name fc;
+ uint64_t u64;
+ } wwn;
+ union {
+ struct scsi_lun scsi;
+ uint64_t u64;
+ } lun;
+
+ type->type = cpu_to_le64 ( EDD_INTF_TYPE_FIBRE );
+ memcpy ( &wwn.fc, &fcpdev->wwn, sizeof ( wwn.fc ) );
+ path->fibre.wwn = be64_to_cpu ( wwn.u64 );
+ memcpy ( &lun.scsi, &fcpdev->lun, sizeof ( lun.scsi ) );
+ path->fibre.lun = be64_to_cpu ( lun.u64 );
+ return 0;
+}
+
+/**
+ * Identify device underlying FCP device
+ *
+ * @v fcpdev FCP device
+ * @ret device Underlying device
+ */
+static struct device * fcpdev_identify_device ( struct fcp_device *fcpdev ) {
+
+ /* We know the underlying device only if the link is up;
+ * otherwise we don't have a port to examine.
+ */
+ if ( ! fc_link_ok ( &fcpdev->user.ulp->link ) ) {
+ DBGC ( fcpdev, "FCP %p doesn't know underlying device "
+ "until link is up\n", fcpdev );
+ return NULL;
+ }
+
+ /* Hand off to port's transport interface */
+ assert ( fcpdev->user.ulp->peer->port != NULL );
+ return identify_device ( &fcpdev->user.ulp->peer->port->transport );
+}
+
+/** FCP device SCSI interface operations */
+static struct interface_operation fcpdev_scsi_op[] = {
+ INTF_OP ( scsi_command, struct fcp_device *, fcpdev_scsi_command ),
+ INTF_OP ( xfer_window, struct fcp_device *, fcpdev_window ),
+ INTF_OP ( intf_close, struct fcp_device *, fcpdev_close ),
+ INTF_OP ( acpi_describe, struct fcp_device *, fcpdev_acpi_describe ),
+ INTF_OP ( edd_describe, struct fcp_device *, fcpdev_edd_describe ),
+ INTF_OP ( identify_device, struct fcp_device *,
+ fcpdev_identify_device ),
+};
+
+/** FCP device SCSI interface descriptor */
+static struct interface_descriptor fcpdev_scsi_desc =
+ INTF_DESC ( struct fcp_device, scsi, fcpdev_scsi_op );
+
+/**
+ * Examine FCP ULP link state
+ *
+ * @v user Fibre Channel upper-layer protocol user
+ */
+static void fcpdev_examine ( struct fc_ulp_user *user ) {
+ struct fcp_device *fcpdev =
+ container_of ( user, struct fcp_device, user );
+
+ if ( fc_link_ok ( &fcpdev->user.ulp->link ) ) {
+ DBGC ( fcpdev, "FCP %p link is up\n", fcpdev );
+ } else {
+ DBGC ( fcpdev, "FCP %p link is down: %s\n",
+ fcpdev, strerror ( fcpdev->user.ulp->link.rc ) );
+ }
+
+ /* Notify SCSI layer of window change */
+ xfer_window_changed ( &fcpdev->scsi );
+}
+
+/**
+ * Open FCP device
+ *
+ * @v parent Parent interface
+ * @v wwn Fibre Channel WWN
+ * @v lun SCSI LUN
+ * @ret rc Return status code
+ */
+static int fcpdev_open ( struct interface *parent, struct fc_name *wwn,
+ struct scsi_lun *lun ) {
+ struct fc_ulp *ulp;
+ struct fcp_device *fcpdev;
+ int rc;
+
+ /* Get Fibre Channel ULP interface */
+ ulp = fc_ulp_get_wwn_type ( wwn, FC_TYPE_FCP );
+ if ( ! ulp ) {
+ rc = -ENOMEM;
+ goto err_ulp_get;
+ }
+
+ /* Allocate and initialise structure */
+ fcpdev = zalloc ( sizeof ( *fcpdev ) );
+ if ( ! fcpdev ) {
+ rc = -ENOMEM;
+ goto err_zalloc;
+ }
+ ref_init ( &fcpdev->refcnt, NULL );
+ intf_init ( &fcpdev->scsi, &fcpdev_scsi_desc, &fcpdev->refcnt );
+ INIT_LIST_HEAD ( &fcpdev->fcpcmds );
+ fc_ulp_user_init ( &fcpdev->user, fcpdev_examine, &fcpdev->refcnt );
+
+ DBGC ( fcpdev, "FCP %p opened for %s\n", fcpdev, fc_ntoa ( wwn ) );
+
+ /* Attach to Fibre Channel ULP */
+ fc_ulp_attach ( ulp, &fcpdev->user );
+
+ /* Preserve parameters required for boot firmware table */
+ memcpy ( &fcpdev->wwn, wwn, sizeof ( fcpdev->wwn ) );
+ memcpy ( &fcpdev->lun, lun, sizeof ( fcpdev->lun ) );
+
+ /* Attach SCSI device to parent interface */
+ if ( ( rc = scsi_open ( parent, &fcpdev->scsi, lun ) ) != 0 ) {
+ DBGC ( fcpdev, "FCP %p could not create SCSI device: %s\n",
+ fcpdev, strerror ( rc ) );
+ goto err_scsi_open;
+ }
+
+ /* Drop temporary reference to ULP */
+ fc_ulp_put ( ulp );
+
+ /* Mortalise self and return */
+ ref_put ( &fcpdev->refcnt );
+ return 0;
+
+ err_scsi_open:
+ fcpdev_close ( fcpdev, rc );
+ ref_put ( &fcpdev->refcnt );
+ err_zalloc:
+ fc_ulp_put ( ulp );
+ err_ulp_get:
+ return rc;
+}
+
+/******************************************************************************
+ *
+ * FCP URIs
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Parse FCP URI
+ *
+ * @v uri URI
+ * @ret wwn Fibre Channel WWN
+ * @ret lun SCSI LUN
+ * @ret rc Return status code
+ *
+ * An FCP URI has the form "fcp:<wwn>:<lun>" or "fcp://<wwn>/<lun>"
+ */
+static int fcp_parse_uri ( struct uri *uri, struct fc_name *wwn,
+ struct scsi_lun *lun ) {
+ char wwn_buf[ FC_NAME_STRLEN + 1 /* NUL */ ];
+ const char *wwn_text;
+ const char *lun_text;
+ int rc;
+
+ /* Extract WWN and LUN texts from URI */
+ if ( uri->opaque ) {
+ /* "fcp:<wwn>:<lun>" */
+ if ( snprintf ( wwn_buf, sizeof ( wwn_buf ), "%s",
+ uri->opaque ) < ( FC_NAME_STRLEN + 1 /* : */ ) )
+ return -EINVAL;
+ if ( uri->opaque[FC_NAME_STRLEN] != ':' )
+ return -EINVAL;
+ wwn_text = wwn_buf;
+ lun_text = &uri->opaque[FC_NAME_STRLEN + 1];
+ } else {
+ /* If host exists, path must also exist */
+ if ( ! ( uri->host && uri->path ) )
+ return -EINVAL;
+ if ( uri->path[0] != '/' )
+ return -EINVAL;
+ wwn_text = uri->host;
+ lun_text = ( uri->path + 1 );
+ }
+
+ /* Parse WWN */
+ if ( ( rc = fc_aton ( wwn_text, wwn ) ) != 0 )
+ return rc;
+
+ /* Parse LUN */
+ if ( ( rc = scsi_parse_lun ( lun_text, lun ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Open FCP URI
+ *
+ * @v parent Parent interface
+ * @v uri URI
+ * @ret rc Return status code
+ */
+static int fcp_open ( struct interface *parent, struct uri *uri ) {
+ struct fc_name wwn;
+ struct scsi_lun lun;
+ int rc;
+
+ /* Parse URI */
+ if ( ( rc = fcp_parse_uri ( uri, &wwn, &lun ) ) != 0 )
+ return rc;
+
+ /* Open FCP device */
+ if ( ( rc = fcpdev_open ( parent, &wwn, &lun ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/** FCP URI opener */
+struct uri_opener fcp_uri_opener __uri_opener = {
+ .scheme = "fcp",
+ .open = fcp_open,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/icmp.c b/src/VBox/Devices/PC/ipxe/src/net/icmp.c
new file mode 100644
index 00000000..84dad425
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/icmp.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <errno.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/in.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/icmp.h>
+
+/** @file
+ *
+ * ICMP protocol
+ *
+ */
+
+struct tcpip_protocol icmp_protocol __tcpip_protocol;
+
+/**
+ * Process a received packet
+ *
+ * @v iobuf I/O buffer
+ * @v st_src Partially-filled source address
+ * @v st_dest Partially-filled destination address
+ * @v pshdr_csum Pseudo-header checksum
+ * @ret rc Return status code
+ */
+static int icmp_rx ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest,
+ uint16_t pshdr_csum __unused ) {
+ struct icmp_header *icmp = iobuf->data;
+ size_t len = iob_len ( iobuf );
+ unsigned int csum;
+ int rc;
+
+ /* Sanity check */
+ if ( len < sizeof ( *icmp ) ) {
+ DBG ( "ICMP packet too short at %zd bytes (min %zd bytes)\n",
+ len, sizeof ( *icmp ) );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Verify checksum */
+ csum = tcpip_chksum ( icmp, len );
+ if ( csum != 0 ) {
+ DBG ( "ICMP checksum incorrect (is %04x, should be 0000)\n",
+ csum );
+ DBG_HD ( icmp, len );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* We respond only to pings */
+ if ( icmp->type != ICMP_ECHO_REQUEST ) {
+ DBG ( "ICMP ignoring type %d\n", icmp->type );
+ rc = 0;
+ goto done;
+ }
+
+ DBG ( "ICMP responding to ping\n" );
+
+ /* Change type to response and recalculate checksum */
+ icmp->type = ICMP_ECHO_RESPONSE;
+ icmp->chksum = 0;
+ icmp->chksum = tcpip_chksum ( icmp, len );
+
+ /* Transmit the response */
+ if ( ( rc = tcpip_tx ( iob_disown ( iobuf ), &icmp_protocol, st_dest,
+ st_src, NULL, NULL ) ) != 0 ) {
+ DBG ( "ICMP could not transmit ping response: %s\n",
+ strerror ( rc ) );
+ goto done;
+ }
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** ICMP TCP/IP protocol */
+struct tcpip_protocol icmp_protocol __tcpip_protocol = {
+ .name = "ICMP",
+ .rx = icmp_rx,
+ .tcpip_proto = IP_ICMP,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/icmpv6.c b/src/VBox/Devices/PC/ipxe/src/net/icmpv6.c
new file mode 100644
index 00000000..1a5aad3b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/icmpv6.c
@@ -0,0 +1,126 @@
+#include <stdint.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/in.h>
+#include <ipxe/ip6.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/ndp.h>
+#include <ipxe/icmp6.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/netdevice.h>
+
+/**
+ * Send neighbour solicitation packet
+ *
+ * @v netdev Network device
+ * @v src Source address
+ * @v dest Destination address
+ *
+ * This function prepares a neighbour solicitation packet and sends it to the
+ * network layer.
+ */
+int icmp6_send_solicit ( struct net_device *netdev, struct in6_addr *src __unused,
+ struct in6_addr *dest ) {
+ union {
+ struct sockaddr_in6 sin6;
+ struct sockaddr_tcpip st;
+ } st_dest;
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+ struct neighbour_solicit *nsolicit;
+ struct io_buffer *iobuf = alloc_iob ( sizeof ( *nsolicit ) + MIN_IOB_LEN );
+ iob_reserve ( iobuf, MAX_HDR_LEN );
+ nsolicit = iob_put ( iobuf, sizeof ( *nsolicit ) );
+
+ /* Fill up the headers */
+ memset ( nsolicit, 0, sizeof ( *nsolicit ) );
+ nsolicit->type = ICMP6_NSOLICIT;
+ nsolicit->code = 0;
+ nsolicit->target = *dest;
+ nsolicit->opt_type = 1;
+ nsolicit->opt_len = ( 2 + ll_protocol->ll_addr_len ) / 8;
+ memcpy ( nsolicit->opt_ll_addr, netdev->ll_addr,
+ netdev->ll_protocol->ll_addr_len );
+ /* Partial checksum */
+ nsolicit->csum = 0;
+ nsolicit->csum = tcpip_chksum ( nsolicit, sizeof ( *nsolicit ) );
+
+ /* Solicited multicast address */
+ st_dest.sin6.sin_family = AF_INET6;
+ st_dest.sin6.sin6_addr.in6_u.u6_addr8[0] = 0xff;
+ st_dest.sin6.sin6_addr.in6_u.u6_addr8[2] = 0x02;
+ st_dest.sin6.sin6_addr.in6_u.u6_addr16[1] = 0x0000;
+ st_dest.sin6.sin6_addr.in6_u.u6_addr32[1] = 0x00000000;
+ st_dest.sin6.sin6_addr.in6_u.u6_addr16[4] = 0x0000;
+ st_dest.sin6.sin6_addr.in6_u.u6_addr16[5] = 0x0001;
+ st_dest.sin6.sin6_addr.in6_u.u6_addr32[3] = dest->in6_u.u6_addr32[3];
+ st_dest.sin6.sin6_addr.in6_u.u6_addr8[13] = 0xff;
+
+ /* Send packet over IP6 */
+ return tcpip_tx ( iobuf, &icmp6_protocol, NULL, &st_dest.st,
+ NULL, &nsolicit->csum );
+}
+
+/**
+ * Process ICMP6 headers
+ *
+ * @v iobuf I/O buffer
+ * @v st_src Source address
+ * @v st_dest Destination address
+ */
+static int icmp6_rx ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest, __unused uint16_t pshdr_csum ) {
+ struct icmp6_header *icmp6hdr = iobuf->data;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *icmp6hdr ) ) {
+ DBG ( "Packet too short (%zd bytes)\n", iob_len ( iobuf ) );
+ free_iob ( iobuf );
+ return -EINVAL;
+ }
+
+ /* TODO: Verify checksum */
+
+ /* Process the ICMP header */
+ switch ( icmp6hdr->type ) {
+ case ICMP6_NADVERT:
+ return ndp_process_advert ( iobuf, st_src, st_dest );
+ }
+ return -ENOSYS;
+}
+
+#if 0
+void icmp6_test_nadvert (struct net_device *netdev, struct sockaddr_in6 *server_p, char *ll_addr) {
+
+ struct sockaddr_in6 server;
+ memcpy ( &server, server_p, sizeof ( server ) );
+ struct io_buffer *rxiobuf = alloc_iob ( 500 );
+ iob_reserve ( rxiobuf, MAX_HDR_LEN );
+ struct neighbour_advert *nadvert = iob_put ( rxiobuf, sizeof ( *nadvert ) );
+ nadvert->type = 136;
+ nadvert->code = 0;
+ nadvert->flags = ICMP6_FLAGS_SOLICITED;
+ nadvert->csum = 0xffff;
+ nadvert->target = server.sin6_addr;
+ nadvert->opt_type = 2;
+ nadvert->opt_len = 1;
+ memcpy ( nadvert->opt_ll_addr, ll_addr, 6 );
+ struct ip6_header *ip6hdr = iob_push ( rxiobuf, sizeof ( *ip6hdr ) );
+ ip6hdr->ver_traffic_class_flow_label = htonl ( 0x60000000 );
+ ip6hdr->hop_limit = 255;
+ ip6hdr->nxt_hdr = 58;
+ ip6hdr->payload_len = htons ( sizeof ( *nadvert ) );
+ ip6hdr->src = server.sin6_addr;
+ ip6hdr->dest = server.sin6_addr;
+ hex_dump ( rxiobuf->data, iob_len ( rxiobuf ) );
+ net_rx ( rxiobuf, netdev, htons ( ETH_P_IPV6 ), ll_addr );
+}
+#endif
+
+/** ICMP6 protocol */
+struct tcpip_protocol icmp6_protocol __tcpip_protocol = {
+ .name = "ICMP6",
+ .rx = icmp6_rx,
+ .tcpip_proto = IP_ICMP6, // 58
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/infiniband.c b/src/VBox/Devices/PC/ipxe/src/net/infiniband.c
new file mode 100644
index 00000000..147017fc
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/infiniband.c
@@ -0,0 +1,993 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/list.h>
+#include <ipxe/errortab.h>
+#include <ipxe/if_arp.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/process.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/ib_mi.h>
+#include <ipxe/ib_sma.h>
+
+/** @file
+ *
+ * Infiniband protocol
+ *
+ */
+
+/** List of Infiniband devices */
+struct list_head ib_devices = LIST_HEAD_INIT ( ib_devices );
+
+/** List of open Infiniband devices, in reverse order of opening */
+static struct list_head open_ib_devices = LIST_HEAD_INIT ( open_ib_devices );
+
+/* Disambiguate the various possible EINPROGRESSes */
+#define EINPROGRESS_INIT __einfo_error ( EINFO_EINPROGRESS_INIT )
+#define EINFO_EINPROGRESS_INIT __einfo_uniqify \
+ ( EINFO_EINPROGRESS, 0x01, "Initialising" )
+#define EINPROGRESS_ARMED __einfo_error ( EINFO_EINPROGRESS_ARMED )
+#define EINFO_EINPROGRESS_ARMED __einfo_uniqify \
+ ( EINFO_EINPROGRESS, 0x02, "Armed" )
+
+/** Human-readable message for the link statuses */
+struct errortab infiniband_errors[] __errortab = {
+ __einfo_errortab ( EINFO_EINPROGRESS_INIT ),
+ __einfo_errortab ( EINFO_EINPROGRESS_ARMED ),
+};
+
+/***************************************************************************
+ *
+ * Completion queues
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Create completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v num_cqes Number of completion queue entries
+ * @v op Completion queue operations
+ * @ret cq New completion queue
+ */
+struct ib_completion_queue *
+ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
+ struct ib_completion_queue_operations *op ) {
+ struct ib_completion_queue *cq;
+ int rc;
+
+ DBGC ( ibdev, "IBDEV %p creating completion queue\n", ibdev );
+
+ /* Allocate and initialise data structure */
+ cq = zalloc ( sizeof ( *cq ) );
+ if ( ! cq )
+ goto err_alloc_cq;
+ cq->ibdev = ibdev;
+ list_add ( &cq->list, &ibdev->cqs );
+ cq->num_cqes = num_cqes;
+ INIT_LIST_HEAD ( &cq->work_queues );
+ cq->op = op;
+
+ /* Perform device-specific initialisation and get CQN */
+ if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not initialise completion "
+ "queue: %s\n", ibdev, strerror ( rc ) );
+ goto err_dev_create_cq;
+ }
+
+ DBGC ( ibdev, "IBDEV %p created %d-entry completion queue %p (%p) "
+ "with CQN %#lx\n", ibdev, num_cqes, cq,
+ ib_cq_get_drvdata ( cq ), cq->cqn );
+ return cq;
+
+ ibdev->op->destroy_cq ( ibdev, cq );
+ err_dev_create_cq:
+ list_del ( &cq->list );
+ free ( cq );
+ err_alloc_cq:
+ return NULL;
+}
+
+/**
+ * Destroy completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+void ib_destroy_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ DBGC ( ibdev, "IBDEV %p destroying completion queue %#lx\n",
+ ibdev, cq->cqn );
+ assert ( list_empty ( &cq->work_queues ) );
+ ibdev->op->destroy_cq ( ibdev, cq );
+ list_del ( &cq->list );
+ free ( cq );
+}
+
+/**
+ * Poll completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+void ib_poll_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct ib_work_queue *wq;
+
+ /* Poll completion queue */
+ ibdev->op->poll_cq ( ibdev, cq );
+
+ /* Refill receive work queues */
+ list_for_each_entry ( wq, &cq->work_queues, list ) {
+ if ( ! wq->is_send )
+ ib_refill_recv ( ibdev, wq->qp );
+ }
+}
+
+/***************************************************************************
+ *
+ * Work queues
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Create queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v type Queue pair type
+ * @v num_send_wqes Number of send work queue entries
+ * @v send_cq Send completion queue
+ * @v num_recv_wqes Number of receive work queue entries
+ * @v recv_cq Receive completion queue
+ * @ret qp Queue pair
+ *
+ * The queue pair will be left in the INIT state; you must call
+ * ib_modify_qp() before it is ready to use for sending and receiving.
+ */
+struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev,
+ enum ib_queue_pair_type type,
+ unsigned int num_send_wqes,
+ struct ib_completion_queue *send_cq,
+ unsigned int num_recv_wqes,
+ struct ib_completion_queue *recv_cq ) {
+ struct ib_queue_pair *qp;
+ size_t total_size;
+ int rc;
+
+ DBGC ( ibdev, "IBDEV %p creating queue pair\n", ibdev );
+
+ /* Allocate and initialise data structure */
+ total_size = ( sizeof ( *qp ) +
+ ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ) +
+ ( num_recv_wqes * sizeof ( qp->recv.iobufs[0] ) ) );
+ qp = zalloc ( total_size );
+ if ( ! qp )
+ goto err_alloc_qp;
+ qp->ibdev = ibdev;
+ list_add ( &qp->list, &ibdev->qps );
+ qp->type = type;
+ qp->send.qp = qp;
+ qp->send.is_send = 1;
+ qp->send.cq = send_cq;
+ list_add ( &qp->send.list, &send_cq->work_queues );
+ qp->send.psn = ( random() & 0xffffffUL );
+ qp->send.num_wqes = num_send_wqes;
+ qp->send.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) );
+ qp->recv.qp = qp;
+ qp->recv.cq = recv_cq;
+ list_add ( &qp->recv.list, &recv_cq->work_queues );
+ qp->recv.psn = ( random() & 0xffffffUL );
+ qp->recv.num_wqes = num_recv_wqes;
+ qp->recv.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) +
+ ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ));
+ INIT_LIST_HEAD ( &qp->mgids );
+
+ /* Perform device-specific initialisation and get QPN */
+ if ( ( rc = ibdev->op->create_qp ( ibdev, qp ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not initialise queue pair: "
+ "%s\n", ibdev, strerror ( rc ) );
+ goto err_dev_create_qp;
+ }
+ DBGC ( ibdev, "IBDEV %p created queue pair %p (%p) with QPN %#lx\n",
+ ibdev, qp, ib_qp_get_drvdata ( qp ), qp->qpn );
+ DBGC ( ibdev, "IBDEV %p QPN %#lx has %d send entries at [%p,%p)\n",
+ ibdev, qp->qpn, num_send_wqes, qp->send.iobufs,
+ qp->recv.iobufs );
+ DBGC ( ibdev, "IBDEV %p QPN %#lx has %d receive entries at [%p,%p)\n",
+ ibdev, qp->qpn, num_recv_wqes, qp->recv.iobufs,
+ ( ( ( void * ) qp ) + total_size ) );
+
+ /* Calculate externally-visible QPN */
+ switch ( type ) {
+ case IB_QPT_SMI:
+ qp->ext_qpn = IB_QPN_SMI;
+ break;
+ case IB_QPT_GSI:
+ qp->ext_qpn = IB_QPN_GSI;
+ break;
+ default:
+ qp->ext_qpn = qp->qpn;
+ break;
+ }
+ if ( qp->ext_qpn != qp->qpn ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx has external QPN %#lx\n",
+ ibdev, qp->qpn, qp->ext_qpn );
+ }
+
+ return qp;
+
+ ibdev->op->destroy_qp ( ibdev, qp );
+ err_dev_create_qp:
+ list_del ( &qp->send.list );
+ list_del ( &qp->recv.list );
+ list_del ( &qp->list );
+ free ( qp );
+ err_alloc_qp:
+ return NULL;
+}
+
+/**
+ * Modify queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av New address vector, if applicable
+ * @ret rc Return status code
+ */
+int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
+ int rc;
+
+ DBGC ( ibdev, "IBDEV %p modifying QPN %#lx\n", ibdev, qp->qpn );
+
+ if ( ( rc = ibdev->op->modify_qp ( ibdev, qp ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not modify QPN %#lx: %s\n",
+ ibdev, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Destroy queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
+ struct io_buffer *iobuf;
+ unsigned int i;
+
+ DBGC ( ibdev, "IBDEV %p destroying QPN %#lx\n",
+ ibdev, qp->qpn );
+
+ assert ( list_empty ( &qp->mgids ) );
+
+ /* Perform device-specific destruction */
+ ibdev->op->destroy_qp ( ibdev, qp );
+
+ /* Complete any remaining I/O buffers with errors */
+ for ( i = 0 ; i < qp->send.num_wqes ; i++ ) {
+ if ( ( iobuf = qp->send.iobufs[i] ) != NULL )
+ ib_complete_send ( ibdev, qp, iobuf, -ECANCELED );
+ }
+ for ( i = 0 ; i < qp->recv.num_wqes ; i++ ) {
+ if ( ( iobuf = qp->recv.iobufs[i] ) != NULL ) {
+ ib_complete_recv ( ibdev, qp, NULL, iobuf,
+ -ECANCELED );
+ }
+ }
+
+ /* Remove work queues from completion queue */
+ list_del ( &qp->send.list );
+ list_del ( &qp->recv.list );
+
+ /* Free QP */
+ list_del ( &qp->list );
+ free ( qp );
+}
+
+/**
+ * Find queue pair by QPN
+ *
+ * @v ibdev Infiniband device
+ * @v qpn Queue pair number
+ * @ret qp Queue pair, or NULL
+ */
+struct ib_queue_pair * ib_find_qp_qpn ( struct ib_device *ibdev,
+ unsigned long qpn ) {
+ struct ib_queue_pair *qp;
+
+ list_for_each_entry ( qp, &ibdev->qps, list ) {
+ if ( ( qpn == qp->qpn ) || ( qpn == qp->ext_qpn ) )
+ return qp;
+ }
+ return NULL;
+}
+
+/**
+ * Find queue pair by multicast GID
+ *
+ * @v ibdev Infiniband device
+ * @v gid Multicast GID
+ * @ret qp Queue pair, or NULL
+ */
+struct ib_queue_pair * ib_find_qp_mgid ( struct ib_device *ibdev,
+ union ib_gid *gid ) {
+ struct ib_queue_pair *qp;
+ struct ib_multicast_gid *mgid;
+
+ list_for_each_entry ( qp, &ibdev->qps, list ) {
+ list_for_each_entry ( mgid, &qp->mgids, list ) {
+ if ( memcmp ( &mgid->gid, gid,
+ sizeof ( mgid->gid ) ) == 0 ) {
+ return qp;
+ }
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Find work queue belonging to completion queue
+ *
+ * @v cq Completion queue
+ * @v qpn Queue pair number
+ * @v is_send Find send work queue (rather than receive)
+ * @ret wq Work queue, or NULL if not found
+ */
+struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
+ unsigned long qpn, int is_send ) {
+ struct ib_work_queue *wq;
+
+ list_for_each_entry ( wq, &cq->work_queues, list ) {
+ if ( ( wq->qp->qpn == qpn ) && ( wq->is_send == is_send ) )
+ return wq;
+ }
+ return NULL;
+}
+
+/**
+ * Post send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf ) {
+ struct ib_address_vector av_copy;
+ int rc;
+
+ /* Check queue fill level */
+ if ( qp->send.fill >= qp->send.num_wqes ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx send queue full\n",
+ ibdev, qp->qpn );
+ return -ENOBUFS;
+ }
+
+ /* Use default address vector if none specified */
+ if ( ! av )
+ av = &qp->av;
+
+ /* Make modifiable copy of address vector */
+ memcpy ( &av_copy, av, sizeof ( av_copy ) );
+ av = &av_copy;
+
+ /* Fill in optional parameters in address vector */
+ if ( ! av->qkey )
+ av->qkey = qp->qkey;
+ if ( ! av->rate )
+ av->rate = IB_RATE_2_5;
+
+ /* Post to hardware */
+ if ( ( rc = ibdev->op->post_send ( ibdev, qp, av, iobuf ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx could not post send WQE: "
+ "%s\n", ibdev, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+
+ qp->send.fill++;
+ return 0;
+}
+
+/**
+ * Post receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct io_buffer *iobuf ) {
+ int rc;
+
+ /* Check packet length */
+ if ( iob_tailroom ( iobuf ) < IB_MAX_PAYLOAD_SIZE ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx wrong RX buffer size (%zd)\n",
+ ibdev, qp->qpn, iob_tailroom ( iobuf ) );
+ return -EINVAL;
+ }
+
+ /* Check queue fill level */
+ if ( qp->recv.fill >= qp->recv.num_wqes ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx receive queue full\n",
+ ibdev, qp->qpn );
+ return -ENOBUFS;
+ }
+
+ /* Post to hardware */
+ if ( ( rc = ibdev->op->post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx could not post receive WQE: "
+ "%s\n", ibdev, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+
+ qp->recv.fill++;
+ return 0;
+}
+
+/**
+ * Complete send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+void ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct io_buffer *iobuf, int rc ) {
+
+ if ( qp->send.cq->op->complete_send ) {
+ qp->send.cq->op->complete_send ( ibdev, qp, iobuf, rc );
+ } else {
+ free_iob ( iobuf );
+ }
+ qp->send.fill--;
+}
+
+/**
+ * Complete receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector, or NULL
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc ) {
+
+ if ( qp->recv.cq->op->complete_recv ) {
+ qp->recv.cq->op->complete_recv ( ibdev, qp, av, iobuf, rc );
+ } else {
+ free_iob ( iobuf );
+ }
+ qp->recv.fill--;
+}
+
+/**
+ * Refill receive work queue
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+void ib_refill_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
+ struct io_buffer *iobuf;
+ int rc;
+
+ /* Keep filling while unfilled entries remain */
+ while ( qp->recv.fill < qp->recv.num_wqes ) {
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( IB_MAX_PAYLOAD_SIZE );
+ if ( ! iobuf ) {
+ /* Non-fatal; we will refill on next attempt */
+ return;
+ }
+
+ /* Post I/O buffer */
+ if ( ( rc = ib_post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not refill: %s\n",
+ ibdev, strerror ( rc ) );
+ free_iob ( iobuf );
+ /* Give up */
+ return;
+ }
+ }
+}
+
+/***************************************************************************
+ *
+ * Link control
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Get link state
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Link status code
+ */
+int ib_link_rc ( struct ib_device *ibdev ) {
+ switch ( ibdev->port_state ) {
+ case IB_PORT_STATE_DOWN: return -ENOTCONN;
+ case IB_PORT_STATE_INIT: return -EINPROGRESS_INIT;
+ case IB_PORT_STATE_ARMED: return -EINPROGRESS_ARMED;
+ case IB_PORT_STATE_ACTIVE: return 0;
+ default: return -EINVAL;
+ }
+}
+
+/**
+ * Textual representation of Infiniband link state
+ *
+ * @v ibdev Infiniband device
+ * @ret link_text Link state text
+ */
+static const char * ib_link_state_text ( struct ib_device *ibdev ) {
+ switch ( ibdev->port_state ) {
+ case IB_PORT_STATE_DOWN: return "DOWN";
+ case IB_PORT_STATE_INIT: return "INIT";
+ case IB_PORT_STATE_ARMED: return "ARMED";
+ case IB_PORT_STATE_ACTIVE: return "ACTIVE";
+ default: return "UNKNOWN";
+ }
+}
+
+/**
+ * Notify drivers of Infiniband device or link state change
+ *
+ * @v ibdev Infiniband device
+ */
+static void ib_notify ( struct ib_device *ibdev ) {
+ struct ib_driver *driver;
+
+ for_each_table_entry ( driver, IB_DRIVERS )
+ driver->notify ( ibdev );
+}
+
+/**
+ * Notify of Infiniband link state change
+ *
+ * @v ibdev Infiniband device
+ */
+void ib_link_state_changed ( struct ib_device *ibdev ) {
+
+ DBGC ( ibdev, "IBDEV %p link state is %s\n",
+ ibdev, ib_link_state_text ( ibdev ) );
+
+ /* Notify drivers of link state change */
+ ib_notify ( ibdev );
+}
+
+/**
+ * Open port
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+int ib_open ( struct ib_device *ibdev ) {
+ int rc;
+
+ /* Increment device open request counter */
+ if ( ibdev->open_count++ > 0 ) {
+ /* Device was already open; do nothing */
+ return 0;
+ }
+
+ /* Open device */
+ if ( ( rc = ibdev->op->open ( ibdev ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not open: %s\n",
+ ibdev, strerror ( rc ) );
+ goto err_open;
+ }
+
+ /* Create subnet management interface */
+ ibdev->smi = ib_create_mi ( ibdev, IB_QPT_SMI );
+ if ( ! ibdev->smi ) {
+ DBGC ( ibdev, "IBDEV %p could not create SMI\n", ibdev );
+ rc = -ENOMEM;
+ goto err_create_smi;
+ }
+
+ /* Create subnet management agent */
+ if ( ( rc = ib_create_sma ( ibdev, ibdev->smi ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not create SMA: %s\n",
+ ibdev, strerror ( rc ) );
+ goto err_create_sma;
+ }
+
+ /* Create general services interface */
+ ibdev->gsi = ib_create_mi ( ibdev, IB_QPT_GSI );
+ if ( ! ibdev->gsi ) {
+ DBGC ( ibdev, "IBDEV %p could not create GSI\n", ibdev );
+ rc = -ENOMEM;
+ goto err_create_gsi;
+ }
+
+ /* Add to head of open devices list */
+ list_add ( &ibdev->open_list, &open_ib_devices );
+
+ /* Notify drivers of device state change */
+ ib_notify ( ibdev );
+
+ assert ( ibdev->open_count == 1 );
+ return 0;
+
+ ib_destroy_mi ( ibdev, ibdev->gsi );
+ err_create_gsi:
+ ib_destroy_sma ( ibdev, ibdev->smi );
+ err_create_sma:
+ ib_destroy_mi ( ibdev, ibdev->smi );
+ err_create_smi:
+ ibdev->op->close ( ibdev );
+ err_open:
+ assert ( ibdev->open_count == 1 );
+ ibdev->open_count = 0;
+ return rc;
+}
+
+/**
+ * Close port
+ *
+ * @v ibdev Infiniband device
+ */
+void ib_close ( struct ib_device *ibdev ) {
+
+ /* Decrement device open request counter */
+ ibdev->open_count--;
+
+ /* Close device if this was the last remaining requested opening */
+ if ( ibdev->open_count == 0 ) {
+ ib_notify ( ibdev );
+ list_del ( &ibdev->open_list );
+ ib_destroy_mi ( ibdev, ibdev->gsi );
+ ib_destroy_sma ( ibdev, ibdev->smi );
+ ib_destroy_mi ( ibdev, ibdev->smi );
+ ibdev->op->close ( ibdev );
+ ibdev->port_state = IB_PORT_STATE_DOWN;
+ }
+}
+
+/***************************************************************************
+ *
+ * Multicast
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Attach to multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ * @ret rc Return status code
+ *
+ * Note that this function handles only the local device's attachment
+ * to the multicast GID; it does not issue the relevant MADs to join
+ * the multicast group on the subnet.
+ */
+int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ union ib_gid *gid ) {
+ struct ib_multicast_gid *mgid;
+ int rc;
+
+ /* Add to software multicast GID list */
+ mgid = zalloc ( sizeof ( *mgid ) );
+ if ( ! mgid ) {
+ rc = -ENOMEM;
+ goto err_alloc_mgid;
+ }
+ memcpy ( &mgid->gid, gid, sizeof ( mgid->gid ) );
+ list_add ( &mgid->list, &qp->mgids );
+
+ /* Add to hardware multicast GID list */
+ if ( ( rc = ibdev->op->mcast_attach ( ibdev, qp, gid ) ) != 0 )
+ goto err_dev_mcast_attach;
+
+ return 0;
+
+ err_dev_mcast_attach:
+ list_del ( &mgid->list );
+ free ( mgid );
+ err_alloc_mgid:
+ return rc;
+}
+
+/**
+ * Detach from multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ */
+void ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ union ib_gid *gid ) {
+ struct ib_multicast_gid *mgid;
+
+ /* Remove from hardware multicast GID list */
+ ibdev->op->mcast_detach ( ibdev, qp, gid );
+
+ /* Remove from software multicast GID list */
+ list_for_each_entry ( mgid, &qp->mgids, list ) {
+ if ( memcmp ( &mgid->gid, gid, sizeof ( mgid->gid ) ) == 0 ) {
+ list_del ( &mgid->list );
+ free ( mgid );
+ break;
+ }
+ }
+}
+
+/***************************************************************************
+ *
+ * Miscellaneous
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Count Infiniband HCA ports
+ *
+ * @v ibdev Infiniband device
+ * @ret num_ports Number of ports
+ */
+int ib_count_ports ( struct ib_device *ibdev ) {
+ struct ib_device *tmp;
+ int num_ports = 0;
+
+ /* Search for IB devices with the same physical device to
+ * identify port count.
+ */
+ for_each_ibdev ( tmp ) {
+ if ( tmp->dev == ibdev->dev )
+ num_ports++;
+ }
+ return num_ports;
+}
+
+/**
+ * Set port information
+ *
+ * @v ibdev Infiniband device
+ * @v mad Set port information MAD
+ */
+int ib_set_port_info ( struct ib_device *ibdev, union ib_mad *mad ) {
+ int rc;
+
+ /* Adapters with embedded SMAs do not need to support this method */
+ if ( ! ibdev->op->set_port_info ) {
+ DBGC ( ibdev, "IBDEV %p does not support setting port "
+ "information\n", ibdev );
+ return -ENOTSUP;
+ }
+
+ if ( ( rc = ibdev->op->set_port_info ( ibdev, mad ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not set port information: %s\n",
+ ibdev, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+};
+
+/**
+ * Set partition key table
+ *
+ * @v ibdev Infiniband device
+ * @v mad Set partition key table MAD
+ */
+int ib_set_pkey_table ( struct ib_device *ibdev, union ib_mad *mad ) {
+ int rc;
+
+ /* Adapters with embedded SMAs do not need to support this method */
+ if ( ! ibdev->op->set_pkey_table ) {
+ DBGC ( ibdev, "IBDEV %p does not support setting partition "
+ "key table\n", ibdev );
+ return -ENOTSUP;
+ }
+
+ if ( ( rc = ibdev->op->set_pkey_table ( ibdev, mad ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not set partition key table: "
+ "%s\n", ibdev, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+};
+
+/***************************************************************************
+ *
+ * Event queues
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Poll event queue
+ *
+ * @v ibdev Infiniband device
+ */
+void ib_poll_eq ( struct ib_device *ibdev ) {
+ struct ib_completion_queue *cq;
+
+ /* Poll device's event queue */
+ ibdev->op->poll_eq ( ibdev );
+
+ /* Poll all completion queues */
+ list_for_each_entry ( cq, &ibdev->cqs, list )
+ ib_poll_cq ( ibdev, cq );
+}
+
+/**
+ * Single-step the Infiniband event queue
+ *
+ * @v process Infiniband event queue process
+ */
+static void ib_step ( struct process *process __unused ) {
+ struct ib_device *ibdev;
+
+ list_for_each_entry ( ibdev, &open_ib_devices, open_list )
+ ib_poll_eq ( ibdev );
+}
+
+/** Infiniband event queue process */
+PERMANENT_PROCESS ( ib_process, ib_step );
+
+/***************************************************************************
+ *
+ * Infiniband device creation/destruction
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Allocate Infiniband device
+ *
+ * @v priv_size Size of driver private data area
+ * @ret ibdev Infiniband device, or NULL
+ */
+struct ib_device * alloc_ibdev ( size_t priv_size ) {
+ struct ib_device *ibdev;
+ void *drv_priv;
+ size_t total_len;
+
+ total_len = ( sizeof ( *ibdev ) + priv_size );
+ ibdev = zalloc ( total_len );
+ if ( ibdev ) {
+ drv_priv = ( ( ( void * ) ibdev ) + sizeof ( *ibdev ) );
+ ib_set_drvdata ( ibdev, drv_priv );
+ INIT_LIST_HEAD ( &ibdev->list );
+ INIT_LIST_HEAD ( &ibdev->open_list );
+ INIT_LIST_HEAD ( &ibdev->cqs );
+ INIT_LIST_HEAD ( &ibdev->qps );
+ ibdev->port_state = IB_PORT_STATE_DOWN;
+ ibdev->lid = IB_LID_NONE;
+ ibdev->pkey = IB_PKEY_DEFAULT;
+ }
+ return ibdev;
+}
+
+/**
+ * Register Infiniband device
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+int register_ibdev ( struct ib_device *ibdev ) {
+ struct ib_driver *driver;
+ int rc;
+
+ /* Add to device list */
+ ibdev_get ( ibdev );
+ list_add_tail ( &ibdev->list, &ib_devices );
+ DBGC ( ibdev, "IBDEV %p registered (phys %s)\n", ibdev,
+ ibdev->dev->name );
+
+ /* Probe device */
+ for_each_table_entry ( driver, IB_DRIVERS ) {
+ if ( ( rc = driver->probe ( ibdev ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not add %s device: %s\n",
+ ibdev, driver->name, strerror ( rc ) );
+ goto err_probe;
+ }
+ }
+
+ return 0;
+
+ err_probe:
+ for_each_table_entry_continue_reverse ( driver, IB_DRIVERS )
+ driver->remove ( ibdev );
+ list_del ( &ibdev->list );
+ ibdev_put ( ibdev );
+ return rc;
+}
+
+/**
+ * Unregister Infiniband device
+ *
+ * @v ibdev Infiniband device
+ */
+void unregister_ibdev ( struct ib_device *ibdev ) {
+ struct ib_driver *driver;
+
+ /* Remove device */
+ for_each_table_entry_reverse ( driver, IB_DRIVERS )
+ driver->remove ( ibdev );
+
+ /* Remove from device list */
+ list_del ( &ibdev->list );
+ ibdev_put ( ibdev );
+ DBGC ( ibdev, "IBDEV %p unregistered\n", ibdev );
+}
+
+/**
+ * Find Infiniband device by GID
+ *
+ * @v gid GID
+ * @ret ibdev Infiniband device, or NULL
+ */
+struct ib_device * find_ibdev ( union ib_gid *gid ) {
+ struct ib_device *ibdev;
+
+ for_each_ibdev ( ibdev ) {
+ if ( memcmp ( gid, &ibdev->gid, sizeof ( *gid ) ) == 0 )
+ return ibdev;
+ }
+ return NULL;
+}
+
+/**
+ * Get most recently opened Infiniband device
+ *
+ * @ret ibdev Most recently opened Infiniband device, or NULL
+ */
+struct ib_device * last_opened_ibdev ( void ) {
+ struct ib_device *ibdev;
+
+ ibdev = list_first_entry ( &open_ib_devices, struct ib_device,
+ open_list );
+ if ( ! ibdev )
+ return NULL;
+
+ assert ( ibdev->open_count != 0 );
+ return ibdev;
+}
+
+/* Drag in IPoIB */
+REQUIRE_OBJECT ( ipoib );
diff --git a/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_cm.c b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_cm.c
new file mode 100644
index 00000000..1a0646be
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_cm.c
@@ -0,0 +1,495 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/ib_mi.h>
+#include <ipxe/ib_pathrec.h>
+#include <ipxe/ib_cm.h>
+
+/**
+ * @file
+ *
+ * Infiniband communication management
+ *
+ */
+
+/** List of connections */
+static LIST_HEAD ( ib_cm_conns );
+
+/**
+ * Find connection by local communication ID
+ *
+ * @v local_id Local communication ID
+ * @ret conn Connection, or NULL
+ */
+static struct ib_connection * ib_cm_find ( uint32_t local_id ) {
+ struct ib_connection *conn;
+
+ list_for_each_entry ( conn, &ib_cm_conns, list ) {
+ if ( conn->local_id == local_id )
+ return conn;
+ }
+ return NULL;
+}
+
+/**
+ * Send "ready to use" response
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v av Address vector
+ * @v local_id Local communication ID
+ * @v remote_id Remote communication ID
+ * @ret rc Return status code
+ */
+static int ib_cm_send_rtu ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ struct ib_address_vector *av,
+ uint32_t local_id, uint32_t remote_id ) {
+ union ib_mad mad;
+ struct ib_cm_ready_to_use *rtu = &mad.cm.cm_data.ready_to_use;
+ int rc;
+
+ /* Construct "ready to use" response */
+ memset ( &mad, 0, sizeof ( mad ) );
+ mad.hdr.mgmt_class = IB_MGMT_CLASS_CM;
+ mad.hdr.class_version = IB_CM_CLASS_VERSION;
+ mad.hdr.method = IB_MGMT_METHOD_SEND;
+ mad.hdr.attr_id = htons ( IB_CM_ATTR_READY_TO_USE );
+ rtu->local_id = htonl ( local_id );
+ rtu->remote_id = htonl ( remote_id );
+ if ( ( rc = ib_mi_send ( ibdev, mi, &mad, av ) ) != 0 ){
+ DBG ( "CM could not send RTU: %s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle duplicate connection replies
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ * @ret rc Return status code
+ *
+ * If a "ready to use" MAD is lost, the peer may resend the connection
+ * reply. We have to respond to these with duplicate "ready to use"
+ * MADs, otherwise the peer may time out and drop the connection.
+ */
+static void ib_cm_recv_rep ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_cm_connect_reply *rep = &mad->cm.cm_data.connect_reply;
+ struct ib_connection *conn;
+ uint32_t local_id = ntohl ( rep->remote_id );
+ int rc;
+
+ /* Identify connection */
+ conn = ib_cm_find ( local_id );
+ if ( conn ) {
+ /* Try to send "ready to use" reply */
+ if ( ( rc = ib_cm_send_rtu ( ibdev, mi, av, conn->local_id,
+ conn->remote_id ) ) != 0 ) {
+ /* Ignore errors; the remote end will retry */
+ }
+ } else {
+ DBG ( "CM unidentified connection %08x\n", local_id );
+ }
+}
+
+/**
+ * Send reply to disconnection request
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v av Address vector
+ * @v local_id Local communication ID
+ * @v remote_id Remote communication ID
+ * @ret rc Return status code
+ */
+static int ib_cm_send_drep ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ struct ib_address_vector *av,
+ uint32_t local_id, uint32_t remote_id ) {
+ union ib_mad mad;
+ struct ib_cm_disconnect_reply *drep = &mad.cm.cm_data.disconnect_reply;
+ int rc;
+
+ /* Construct reply to disconnection request */
+ memset ( &mad, 0, sizeof ( mad ) );
+ mad.hdr.mgmt_class = IB_MGMT_CLASS_CM;
+ mad.hdr.class_version = IB_CM_CLASS_VERSION;
+ mad.hdr.method = IB_MGMT_METHOD_SEND;
+ mad.hdr.attr_id = htons ( IB_CM_ATTR_DISCONNECT_REPLY );
+ drep->local_id = htonl ( local_id );
+ drep->remote_id = htonl ( remote_id );
+ if ( ( rc = ib_mi_send ( ibdev, mi, &mad, av ) ) != 0 ){
+ DBG ( "CM could not send DREP: %s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle disconnection requests
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ * @ret rc Return status code
+ */
+static void ib_cm_recv_dreq ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_cm_disconnect_request *dreq =
+ &mad->cm.cm_data.disconnect_request;
+ struct ib_connection *conn;
+ uint32_t local_id = ntohl ( dreq->remote_id );
+ uint32_t remote_id = ntohl ( dreq->local_id );
+ int rc;
+
+ /* Identify connection */
+ conn = ib_cm_find ( local_id );
+ if ( conn ) {
+ /* Notify upper layer */
+ conn->op->changed ( ibdev, conn->qp, conn, -ENOTCONN,
+ &dreq->private_data,
+ sizeof ( dreq->private_data ) );
+ } else {
+ DBG ( "CM unidentified connection %08x\n", local_id );
+ }
+
+ /* Send reply */
+ if ( ( rc = ib_cm_send_drep ( ibdev, mi, av, local_id,
+ remote_id ) ) != 0 ) {
+ /* Ignore errors; the remote end will retry */
+ }
+};
+
+/** Communication management agents */
+struct ib_mad_agent ib_cm_agent[] __ib_mad_agent = {
+ {
+ .mgmt_class = IB_MGMT_CLASS_CM,
+ .class_version = IB_CM_CLASS_VERSION,
+ .attr_id = htons ( IB_CM_ATTR_CONNECT_REPLY ),
+ .handle = ib_cm_recv_rep,
+ },
+ {
+ .mgmt_class = IB_MGMT_CLASS_CM,
+ .class_version = IB_CM_CLASS_VERSION,
+ .attr_id = htons ( IB_CM_ATTR_DISCONNECT_REQUEST ),
+ .handle = ib_cm_recv_dreq,
+ },
+};
+
+/**
+ * Convert connection rejection reason to return status code
+ *
+ * @v reason Rejection reason (in network byte order)
+ * @ret rc Return status code
+ */
+static int ib_cm_rejection_reason_to_rc ( uint16_t reason ) {
+ switch ( reason ) {
+ case htons ( IB_CM_REJECT_BAD_SERVICE_ID ) :
+ return -ENODEV;
+ case htons ( IB_CM_REJECT_STALE_CONN ) :
+ return -EALREADY;
+ case htons ( IB_CM_REJECT_CONSUMER ) :
+ return -ENOTTY;
+ default:
+ return -EPERM;
+ }
+}
+
+/**
+ * Handle connection request transaction completion
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v madx Management transaction
+ * @v rc Status code
+ * @v mad Received MAD (or NULL on error)
+ * @v av Source address vector (or NULL on error)
+ */
+static void ib_cm_req_complete ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ struct ib_mad_transaction *madx,
+ int rc, union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_connection *conn = ib_madx_get_ownerdata ( madx );
+ struct ib_queue_pair *qp = conn->qp;
+ struct ib_cm_common *common = &mad->cm.cm_data.common;
+ struct ib_cm_connect_reply *rep = &mad->cm.cm_data.connect_reply;
+ struct ib_cm_connect_reject *rej = &mad->cm.cm_data.connect_reject;
+ void *private_data = NULL;
+ size_t private_data_len = 0;
+
+ /* Report failures */
+ if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ))
+ rc = -EIO;
+ if ( rc != 0 ) {
+ DBGC ( conn, "CM %p connection request failed: %s\n",
+ conn, strerror ( rc ) );
+ goto out;
+ }
+
+ /* Record remote communication ID */
+ conn->remote_id = ntohl ( common->local_id );
+
+ /* Handle response */
+ switch ( mad->hdr.attr_id ) {
+
+ case htons ( IB_CM_ATTR_CONNECT_REPLY ) :
+ /* Extract fields */
+ qp->av.qpn = ( ntohl ( rep->local_qpn ) >> 8 );
+ qp->send.psn = ( ntohl ( rep->starting_psn ) >> 8 );
+ private_data = &rep->private_data;
+ private_data_len = sizeof ( rep->private_data );
+ DBGC ( conn, "CM %p connected to QPN %lx PSN %x\n",
+ conn, qp->av.qpn, qp->send.psn );
+
+ /* Modify queue pair */
+ if ( ( rc = ib_modify_qp ( ibdev, qp ) ) != 0 ) {
+ DBGC ( conn, "CM %p could not modify queue pair: %s\n",
+ conn, strerror ( rc ) );
+ goto out;
+ }
+
+ /* Send "ready to use" reply */
+ if ( ( rc = ib_cm_send_rtu ( ibdev, mi, av, conn->local_id,
+ conn->remote_id ) ) != 0 ) {
+ /* Treat as non-fatal */
+ rc = 0;
+ }
+ break;
+
+ case htons ( IB_CM_ATTR_CONNECT_REJECT ) :
+ /* Extract fields */
+ DBGC ( conn, "CM %p connection rejected (reason %d)\n",
+ conn, ntohs ( rej->reason ) );
+ /* Private data is valid only for a Consumer Reject */
+ if ( rej->reason == htons ( IB_CM_REJECT_CONSUMER ) ) {
+ private_data = &rej->private_data;
+ private_data_len = sizeof ( rej->private_data );
+ }
+ rc = ib_cm_rejection_reason_to_rc ( rej->reason );
+ break;
+
+ default:
+ DBGC ( conn, "CM %p unexpected response (attribute %04x)\n",
+ conn, ntohs ( mad->hdr.attr_id ) );
+ rc = -ENOTSUP;
+ break;
+ }
+
+ out:
+ /* Destroy the completed transaction */
+ ib_destroy_madx ( ibdev, ibdev->gsi, madx );
+ conn->madx = NULL;
+
+ /* Hand off to the upper completion handler */
+ conn->op->changed ( ibdev, qp, conn, rc, private_data,
+ private_data_len );
+}
+
+/** Connection request operations */
+static struct ib_mad_transaction_operations ib_cm_req_op = {
+ .complete = ib_cm_req_complete,
+};
+
+/**
+ * Handle connection path transaction completion
+ *
+ * @v ibdev Infiniband device
+ * @v path Path
+ * @v rc Status code
+ * @v av Address vector, or NULL on error
+ */
+static void ib_cm_path_complete ( struct ib_device *ibdev,
+ struct ib_path *path, int rc,
+ struct ib_address_vector *av ) {
+ struct ib_connection *conn = ib_path_get_ownerdata ( path );
+ struct ib_queue_pair *qp = conn->qp;
+ union ib_mad mad;
+ struct ib_cm_connect_request *req = &mad.cm.cm_data.connect_request;
+ size_t private_data_len;
+
+ /* Report failures */
+ if ( rc != 0 ) {
+ DBGC ( conn, "CM %p path lookup failed: %s\n",
+ conn, strerror ( rc ) );
+ conn->op->changed ( ibdev, qp, conn, rc, NULL, 0 );
+ goto out;
+ }
+
+ /* Update queue pair peer path */
+ memcpy ( &qp->av, av, sizeof ( qp->av ) );
+
+ /* Construct connection request */
+ memset ( &mad, 0, sizeof ( mad ) );
+ mad.hdr.mgmt_class = IB_MGMT_CLASS_CM;
+ mad.hdr.class_version = IB_CM_CLASS_VERSION;
+ mad.hdr.method = IB_MGMT_METHOD_SEND;
+ mad.hdr.attr_id = htons ( IB_CM_ATTR_CONNECT_REQUEST );
+ req->local_id = htonl ( conn->local_id );
+ memcpy ( &req->service_id, &conn->service_id,
+ sizeof ( req->service_id ) );
+ memcpy ( &req->local_ca, &ibdev->node_guid, sizeof ( req->local_ca ) );
+ req->local_qpn__responder_resources = htonl ( ( qp->qpn << 8 ) | 1 );
+ req->local_eecn__initiator_depth = htonl ( ( 0 << 8 ) | 1 );
+ req->remote_eecn__remote_timeout__service_type__ee_flow_ctrl =
+ htonl ( ( 0x14 << 3 ) | ( IB_CM_TRANSPORT_RC << 1 ) |
+ ( 0 << 0 ) );
+ req->starting_psn__local_timeout__retry_count =
+ htonl ( ( qp->recv.psn << 8 ) | ( 0x14 << 3 ) |
+ ( 0x07 << 0 ) );
+ req->pkey = htons ( ibdev->pkey );
+ req->payload_mtu__rdc_exists__rnr_retry =
+ ( ( IB_MTU_2048 << 4 ) | ( 1 << 3 ) | ( 0x07 << 0 ) );
+ req->max_cm_retries__srq = ( ( 0x0f << 4 ) | ( 0 << 3 ) );
+ req->primary.local_lid = htons ( ibdev->lid );
+ req->primary.remote_lid = htons ( conn->qp->av.lid );
+ memcpy ( &req->primary.local_gid, &ibdev->gid,
+ sizeof ( req->primary.local_gid ) );
+ memcpy ( &req->primary.remote_gid, &conn->qp->av.gid,
+ sizeof ( req->primary.remote_gid ) );
+ req->primary.flow_label__rate =
+ htonl ( ( 0 << 12 ) | ( conn->qp->av.rate << 0 ) );
+ req->primary.hop_limit = 0;
+ req->primary.sl__subnet_local =
+ ( ( conn->qp->av.sl << 4 ) | ( 1 << 3 ) );
+ req->primary.local_ack_timeout = ( 0x13 << 3 );
+ private_data_len = conn->private_data_len;
+ if ( private_data_len > sizeof ( req->private_data ) )
+ private_data_len = sizeof ( req->private_data );
+ memcpy ( &req->private_data, &conn->private_data, private_data_len );
+
+ /* Create connection request */
+ av->qpn = IB_QPN_GSI;
+ av->qkey = IB_QKEY_GSI;
+ conn->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, av,
+ &ib_cm_req_op );
+ if ( ! conn->madx ) {
+ DBGC ( conn, "CM %p could not create connection request\n",
+ conn );
+ conn->op->changed ( ibdev, qp, conn, rc, NULL, 0 );
+ goto out;
+ }
+ ib_madx_set_ownerdata ( conn->madx, conn );
+
+ out:
+ /* Destroy the completed transaction */
+ ib_destroy_path ( ibdev, path );
+ conn->path = NULL;
+}
+
+/** Connection path operations */
+static struct ib_path_operations ib_cm_path_op = {
+ .complete = ib_cm_path_complete,
+};
+
+/**
+ * Create connection to remote QP
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v dgid Target GID
+ * @v service_id Target service ID
+ * @v private_data Connection request private data
+ * @v private_data_len Length of connection request private data
+ * @v op Connection operations
+ * @ret conn Connection
+ */
+struct ib_connection *
+ib_create_conn ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ union ib_gid *dgid, union ib_guid *service_id,
+ void *private_data, size_t private_data_len,
+ struct ib_connection_operations *op ) {
+ struct ib_connection *conn;
+
+ /* Allocate and initialise request */
+ conn = zalloc ( sizeof ( *conn ) + private_data_len );
+ if ( ! conn )
+ goto err_alloc_conn;
+ conn->ibdev = ibdev;
+ conn->qp = qp;
+ memset ( &qp->av, 0, sizeof ( qp->av ) );
+ qp->av.gid_present = 1;
+ memcpy ( &qp->av.gid, dgid, sizeof ( qp->av.gid ) );
+ conn->local_id = random();
+ memcpy ( &conn->service_id, service_id, sizeof ( conn->service_id ) );
+ conn->op = op;
+ conn->private_data_len = private_data_len;
+ memcpy ( &conn->private_data, private_data, private_data_len );
+
+ /* Create path */
+ conn->path = ib_create_path ( ibdev, &qp->av, &ib_cm_path_op );
+ if ( ! conn->path )
+ goto err_create_path;
+ ib_path_set_ownerdata ( conn->path, conn );
+
+ /* Add to list of connections */
+ list_add ( &conn->list, &ib_cm_conns );
+
+ DBGC ( conn, "CM %p created for IBDEV %p QPN %lx\n",
+ conn, ibdev, qp->qpn );
+ DBGC ( conn, "CM %p connecting to " IB_GID_FMT " " IB_GUID_FMT "\n",
+ conn, IB_GID_ARGS ( dgid ), IB_GUID_ARGS ( service_id ) );
+
+ return conn;
+
+ ib_destroy_path ( ibdev, conn->path );
+ err_create_path:
+ free ( conn );
+ err_alloc_conn:
+ return NULL;
+}
+
+/**
+ * Destroy connection to remote QP
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v conn Connection
+ */
+void ib_destroy_conn ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp __unused,
+ struct ib_connection *conn ) {
+
+ list_del ( &conn->list );
+ if ( conn->madx )
+ ib_destroy_madx ( ibdev, ibdev->gsi, conn->madx );
+ if ( conn->path )
+ ib_destroy_path ( ibdev, conn->path );
+ free ( conn );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_cmrc.c b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_cmrc.c
new file mode 100644
index 00000000..369e2e90
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_cmrc.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/process.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/ib_cm.h>
+#include <ipxe/ib_cmrc.h>
+
+/**
+ * @file
+ *
+ * Infiniband Communication-managed Reliable Connections
+ *
+ */
+
+/** CMRC number of send WQEs
+ *
+ * This is a policy decision.
+ */
+#define IB_CMRC_NUM_SEND_WQES 4
+
+/** CMRC number of receive WQEs
+ *
+ * This is a policy decision.
+ */
+#define IB_CMRC_NUM_RECV_WQES 2
+
+/** CMRC number of completion queue entries
+ *
+ * This is a policy decision
+ */
+#define IB_CMRC_NUM_CQES 8
+
+/** An Infiniband Communication-Managed Reliable Connection */
+struct ib_cmrc_connection {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Data transfer interface */
+ struct interface xfer;
+ /** Infiniband device */
+ struct ib_device *ibdev;
+ /** Completion queue */
+ struct ib_completion_queue *cq;
+ /** Queue pair */
+ struct ib_queue_pair *qp;
+ /** Connection */
+ struct ib_connection *conn;
+ /** Destination GID */
+ union ib_gid dgid;
+ /** Service ID */
+ union ib_guid service_id;
+ /** QP is connected */
+ int connected;
+ /** Shutdown process */
+ struct process shutdown;
+};
+
+/**
+ * Shut down CMRC connection gracefully
+ *
+ * @v cmrc Communication-Managed Reliable Connection
+ *
+ * The Infiniband data structures are not reference-counted or
+ * guarded. It is therefore unsafe to shut them down while we may be
+ * in the middle of a callback from the Infiniband stack (e.g. in a
+ * receive completion handler).
+ *
+ * This shutdown process will run some time after the call to
+ * ib_cmrc_close(), after control has returned out of the Infiniband
+ * core, and will shut down the Infiniband interfaces cleanly.
+ *
+ * The shutdown process holds an implicit reference on the CMRC
+ * connection, ensuring that the structure is not freed before the
+ * shutdown process has run.
+ */
+static void ib_cmrc_shutdown ( struct ib_cmrc_connection *cmrc ) {
+
+ DBGC ( cmrc, "CMRC %p shutting down\n", cmrc );
+
+ /* Shut down Infiniband interface */
+ ib_destroy_conn ( cmrc->ibdev, cmrc->qp, cmrc->conn );
+ ib_destroy_qp ( cmrc->ibdev, cmrc->qp );
+ ib_destroy_cq ( cmrc->ibdev, cmrc->cq );
+ ib_close ( cmrc->ibdev );
+
+ /* Drop the remaining reference */
+ ref_put ( &cmrc->refcnt );
+}
+
+/**
+ * Close CMRC connection
+ *
+ * @v cmrc Communication-Managed Reliable Connection
+ * @v rc Reason for close
+ */
+static void ib_cmrc_close ( struct ib_cmrc_connection *cmrc, int rc ) {
+
+ /* Close data transfer interface */
+ intf_shutdown ( &cmrc->xfer, rc );
+
+ /* Schedule shutdown process */
+ process_add ( &cmrc->shutdown );
+}
+
+/**
+ * Handle change of CMRC connection status
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v conn Connection
+ * @v rc_cm Connection status code
+ * @v private_data Private data, if available
+ * @v private_data_len Length of private data
+ */
+static void ib_cmrc_changed ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp,
+ struct ib_connection *conn __unused, int rc_cm,
+ void *private_data, size_t private_data_len ) {
+ struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
+ int rc_xfer;
+
+ /* Record connection status */
+ if ( rc_cm == 0 ) {
+ DBGC ( cmrc, "CMRC %p connected\n", cmrc );
+ cmrc->connected = 1;
+ } else {
+ DBGC ( cmrc, "CMRC %p disconnected: %s\n",
+ cmrc, strerror ( rc_cm ) );
+ cmrc->connected = 0;
+ }
+
+ /* Pass up any private data */
+ DBGC2 ( cmrc, "CMRC %p received private data:\n", cmrc );
+ DBGC2_HDA ( cmrc, 0, private_data, private_data_len );
+ if ( private_data &&
+ ( rc_xfer = xfer_deliver_raw ( &cmrc->xfer, private_data,
+ private_data_len ) ) != 0 ) {
+ DBGC ( cmrc, "CMRC %p could not deliver private data: %s\n",
+ cmrc, strerror ( rc_xfer ) );
+ ib_cmrc_close ( cmrc, rc_xfer );
+ return;
+ }
+
+ /* Notify upper connection of window change */
+ xfer_window_changed ( &cmrc->xfer );
+
+ /* If we are disconnected, close the upper connection */
+ if ( rc_cm != 0 ) {
+ ib_cmrc_close ( cmrc, rc_cm );
+ return;
+ }
+}
+
+/** CMRC connection operations */
+static struct ib_connection_operations ib_cmrc_conn_op = {
+ .changed = ib_cmrc_changed,
+};
+
+/**
+ * Handle CMRC send completion
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+static void ib_cmrc_complete_send ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf, int rc ) {
+ struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
+
+ /* Free the completed I/O buffer */
+ free_iob ( iobuf );
+
+ /* Close the connection on any send errors */
+ if ( rc != 0 ) {
+ DBGC ( cmrc, "CMRC %p send error: %s\n",
+ cmrc, strerror ( rc ) );
+ ib_cmrc_close ( cmrc, rc );
+ return;
+ }
+}
+
+/**
+ * Handle CMRC receive completion
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector, or NULL
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+static void ib_cmrc_complete_recv ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av __unused,
+ struct io_buffer *iobuf, int rc ) {
+ struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
+
+ /* Close the connection on any receive errors */
+ if ( rc != 0 ) {
+ DBGC ( cmrc, "CMRC %p receive error: %s\n",
+ cmrc, strerror ( rc ) );
+ free_iob ( iobuf );
+ ib_cmrc_close ( cmrc, rc );
+ return;
+ }
+
+ DBGC2 ( cmrc, "CMRC %p received:\n", cmrc );
+ DBGC2_HDA ( cmrc, 0, iobuf->data, iob_len ( iobuf ) );
+
+ /* Pass up data */
+ if ( ( rc = xfer_deliver_iob ( &cmrc->xfer, iobuf ) ) != 0 ) {
+ DBGC ( cmrc, "CMRC %p could not deliver data: %s\n",
+ cmrc, strerror ( rc ) );
+ ib_cmrc_close ( cmrc, rc );
+ return;
+ }
+}
+
+/** Infiniband CMRC completion operations */
+static struct ib_completion_queue_operations ib_cmrc_completion_ops = {
+ .complete_send = ib_cmrc_complete_send,
+ .complete_recv = ib_cmrc_complete_recv,
+};
+
+/**
+ * Send data via CMRC
+ *
+ * @v cmrc CMRC connection
+ * @v iobuf Datagram I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int ib_cmrc_xfer_deliver ( struct ib_cmrc_connection *cmrc,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ int rc;
+
+ /* If no connection has yet been attempted, send this datagram
+ * as the CM REQ private data. Otherwise, send it via the QP.
+ */
+ if ( ! cmrc->connected ) {
+
+ /* Abort if we have already sent a CM connection request */
+ if ( cmrc->conn ) {
+ DBGC ( cmrc, "CMRC %p attempt to send before "
+ "connection is complete\n", cmrc );
+ rc = -EIO;
+ goto out;
+ }
+
+ /* Send via CM connection request */
+ cmrc->conn = ib_create_conn ( cmrc->ibdev, cmrc->qp,
+ &cmrc->dgid, &cmrc->service_id,
+ iobuf->data, iob_len ( iobuf ),
+ &ib_cmrc_conn_op );
+ if ( ! cmrc->conn ) {
+ DBGC ( cmrc, "CMRC %p could not connect\n", cmrc );
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ } else {
+
+ /* Send via QP */
+ if ( ( rc = ib_post_send ( cmrc->ibdev, cmrc->qp, NULL,
+ iob_disown ( iobuf ) ) ) != 0 ) {
+ DBGC ( cmrc, "CMRC %p could not send: %s\n",
+ cmrc, strerror ( rc ) );
+ goto out;
+ }
+
+ }
+ return 0;
+
+ out:
+ /* Free the I/O buffer if necessary */
+ free_iob ( iobuf );
+
+ /* Close the connection on any errors */
+ if ( rc != 0 )
+ ib_cmrc_close ( cmrc, rc );
+
+ return rc;
+}
+
+/**
+ * Check CMRC flow control window
+ *
+ * @v cmrc CMRC connection
+ * @ret len Length of window
+ */
+static size_t ib_cmrc_xfer_window ( struct ib_cmrc_connection *cmrc ) {
+
+ /* We indicate a window only when we are successfully
+ * connected.
+ */
+ return ( cmrc->connected ? IB_MAX_PAYLOAD_SIZE : 0 );
+}
+
+/**
+ * Identify device underlying CMRC connection
+ *
+ * @v cmrc CMRC connection
+ * @ret device Underlying device
+ */
+static struct device *
+ib_cmrc_identify_device ( struct ib_cmrc_connection *cmrc ) {
+ return cmrc->ibdev->dev;
+}
+
+/** CMRC data transfer interface operations */
+static struct interface_operation ib_cmrc_xfer_operations[] = {
+ INTF_OP ( xfer_deliver, struct ib_cmrc_connection *,
+ ib_cmrc_xfer_deliver ),
+ INTF_OP ( xfer_window, struct ib_cmrc_connection *,
+ ib_cmrc_xfer_window ),
+ INTF_OP ( intf_close, struct ib_cmrc_connection *, ib_cmrc_close ),
+ INTF_OP ( identify_device, struct ib_cmrc_connection *,
+ ib_cmrc_identify_device ),
+};
+
+/** CMRC data transfer interface descriptor */
+static struct interface_descriptor ib_cmrc_xfer_desc =
+ INTF_DESC ( struct ib_cmrc_connection, xfer, ib_cmrc_xfer_operations );
+
+/** CMRC shutdown process descriptor */
+static struct process_descriptor ib_cmrc_shutdown_desc =
+ PROC_DESC_ONCE ( struct ib_cmrc_connection, shutdown,
+ ib_cmrc_shutdown );
+
+/**
+ * Open CMRC connection
+ *
+ * @v xfer Data transfer interface
+ * @v ibdev Infiniband device
+ * @v dgid Destination GID
+ * @v service_id Service ID
+ * @ret rc Returns status code
+ */
+int ib_cmrc_open ( struct interface *xfer, struct ib_device *ibdev,
+ union ib_gid *dgid, union ib_guid *service_id ) {
+ struct ib_cmrc_connection *cmrc;
+ int rc;
+
+ /* Allocate and initialise structure */
+ cmrc = zalloc ( sizeof ( *cmrc ) );
+ if ( ! cmrc ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ ref_init ( &cmrc->refcnt, NULL );
+ intf_init ( &cmrc->xfer, &ib_cmrc_xfer_desc, &cmrc->refcnt );
+ cmrc->ibdev = ibdev;
+ memcpy ( &cmrc->dgid, dgid, sizeof ( cmrc->dgid ) );
+ memcpy ( &cmrc->service_id, service_id, sizeof ( cmrc->service_id ) );
+ process_init_stopped ( &cmrc->shutdown, &ib_cmrc_shutdown_desc,
+ &cmrc->refcnt );
+
+ /* Open Infiniband device */
+ if ( ( rc = ib_open ( ibdev ) ) != 0 ) {
+ DBGC ( cmrc, "CMRC %p could not open device: %s\n",
+ cmrc, strerror ( rc ) );
+ goto err_open;
+ }
+
+ /* Create completion queue */
+ cmrc->cq = ib_create_cq ( ibdev, IB_CMRC_NUM_CQES,
+ &ib_cmrc_completion_ops );
+ if ( ! cmrc->cq ) {
+ DBGC ( cmrc, "CMRC %p could not create completion queue\n",
+ cmrc );
+ rc = -ENOMEM;
+ goto err_create_cq;
+ }
+
+ /* Create queue pair */
+ cmrc->qp = ib_create_qp ( ibdev, IB_QPT_RC, IB_CMRC_NUM_SEND_WQES,
+ cmrc->cq, IB_CMRC_NUM_RECV_WQES, cmrc->cq );
+ if ( ! cmrc->qp ) {
+ DBGC ( cmrc, "CMRC %p could not create queue pair\n", cmrc );
+ rc = -ENOMEM;
+ goto err_create_qp;
+ }
+ ib_qp_set_ownerdata ( cmrc->qp, cmrc );
+ DBGC ( cmrc, "CMRC %p using QPN %lx\n", cmrc, cmrc->qp->qpn );
+
+ /* Attach to parent interface, transfer reference (implicitly)
+ * to our shutdown process, and return.
+ */
+ intf_plug_plug ( &cmrc->xfer, xfer );
+ return 0;
+
+ ib_destroy_qp ( ibdev, cmrc->qp );
+ err_create_qp:
+ ib_destroy_cq ( ibdev, cmrc->cq );
+ err_create_cq:
+ ib_close ( ibdev );
+ err_open:
+ ref_put ( &cmrc->refcnt );
+ err_alloc:
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_mcast.c b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_mcast.c
new file mode 100644
index 00000000..0f03b54a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_mcast.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/list.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/ib_mi.h>
+#include <ipxe/ib_mcast.h>
+
+/** @file
+ *
+ * Infiniband multicast groups
+ *
+ */
+
+/**
+ * Generate multicast membership MAD
+ *
+ * @v ibdev Infiniband device
+ * @v gid Multicast GID
+ * @v join Join (rather than leave) group
+ * @v mad MAD to fill in
+ */
+static void ib_mcast_mad ( struct ib_device *ibdev, union ib_gid *gid,
+ int join, union ib_mad *mad ) {
+ struct ib_mad_sa *sa = &mad->sa;
+
+ /* Construct multicast membership record request */
+ memset ( sa, 0, sizeof ( *sa ) );
+ sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
+ sa->mad_hdr.class_version = IB_SA_CLASS_VERSION;
+ sa->mad_hdr.method =
+ ( join ? IB_MGMT_METHOD_SET : IB_MGMT_METHOD_DELETE );
+ sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC );
+ sa->sa_hdr.comp_mask[1] =
+ htonl ( IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
+ IB_SA_MCMEMBER_REC_JOIN_STATE );
+ sa->sa_data.mc_member_record.scope__join_state = 1;
+ memcpy ( &sa->sa_data.mc_member_record.mgid, gid,
+ sizeof ( sa->sa_data.mc_member_record.mgid ) );
+ memcpy ( &sa->sa_data.mc_member_record.port_gid, &ibdev->gid,
+ sizeof ( sa->sa_data.mc_member_record.port_gid ) );
+}
+
+/**
+ * Handle multicast membership record join response
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v madx Management transaction
+ * @v rc Status code
+ * @v mad Received MAD (or NULL on error)
+ * @v av Source address vector (or NULL on error)
+ */
+static void ib_mcast_complete ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi __unused,
+ struct ib_mad_transaction *madx,
+ int rc, union ib_mad *mad,
+ struct ib_address_vector *av __unused ) {
+ struct ib_mc_membership *membership = ib_madx_get_ownerdata ( madx );
+ struct ib_queue_pair *qp = membership->qp;
+ union ib_gid *gid = &membership->gid;
+ struct ib_mc_member_record *mc_member_record =
+ &mad->sa.sa_data.mc_member_record;
+ int joined;
+ unsigned long qkey;
+
+ /* Report failures */
+ if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ))
+ rc = -ENOTCONN;
+ if ( rc != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %lx join failed: %s\n",
+ ibdev, qp->qpn, strerror ( rc ) );
+ goto out;
+ }
+
+ /* Extract values from MAD */
+ joined = ( mad->hdr.method == IB_MGMT_METHOD_GET_RESP );
+ qkey = ntohl ( mc_member_record->qkey );
+ DBGC ( ibdev, "IBDEV %p QPN %lx %s " IB_GID_FMT " qkey %lx\n",
+ ibdev, qp->qpn, ( joined ? "joined" : "left" ),
+ IB_GID_ARGS ( gid ), qkey );
+
+ /* Set queue key */
+ qp->qkey = qkey;
+ if ( ( rc = ib_modify_qp ( ibdev, qp ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %lx could not modify qkey: %s\n",
+ ibdev, qp->qpn, strerror ( rc ) );
+ goto out;
+ }
+
+ out:
+ /* Destroy the completed transaction */
+ ib_destroy_madx ( ibdev, mi, madx );
+ membership->madx = NULL;
+
+ /* Hand off to upper completion handler */
+ membership->complete ( ibdev, qp, membership, rc, mad );
+}
+
+/** Multicast membership management transaction completion operations */
+static struct ib_mad_transaction_operations ib_mcast_op = {
+ .complete = ib_mcast_complete,
+};
+
+/**
+ * Join multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v membership Multicast group membership
+ * @v gid Multicast GID to join
+ * @v joined Join completion handler
+ * @ret rc Return status code
+ */
+int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_mc_membership *membership, union ib_gid *gid,
+ void ( * complete ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_mc_membership *membership,
+ int rc, union ib_mad *mad ) ) {
+ union ib_mad mad;
+ int rc;
+
+ DBGC ( ibdev, "IBDEV %p QPN %lx joining " IB_GID_FMT "\n",
+ ibdev, qp->qpn, IB_GID_ARGS ( gid ) );
+
+ /* Initialise structure */
+ membership->qp = qp;
+ memcpy ( &membership->gid, gid, sizeof ( membership->gid ) );
+ membership->complete = complete;
+
+ /* Attach queue pair to multicast GID */
+ if ( ( rc = ib_mcast_attach ( ibdev, qp, gid ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %lx could not attach: %s\n",
+ ibdev, qp->qpn, strerror ( rc ) );
+ goto err_mcast_attach;
+ }
+
+ /* Initiate multicast membership join */
+ ib_mcast_mad ( ibdev, gid, 1, &mad );
+ membership->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, NULL,
+ &ib_mcast_op );
+ if ( ! membership->madx ) {
+ DBGC ( ibdev, "IBDEV %p QPN %lx could not create join "
+ "transaction\n", ibdev, qp->qpn );
+ rc = -ENOMEM;
+ goto err_create_madx;
+ }
+ ib_madx_set_ownerdata ( membership->madx, membership );
+
+ return 0;
+
+ ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
+ err_create_madx:
+ ib_mcast_detach ( ibdev, qp, gid );
+ err_mcast_attach:
+ return rc;
+}
+
+/**
+ * Leave multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v membership Multicast group membership
+ */
+void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_mc_membership *membership ) {
+ union ib_gid *gid = &membership->gid;
+ union ib_mad mad;
+ int rc;
+
+ DBGC ( ibdev, "IBDEV %p QPN %lx leaving " IB_GID_FMT "\n",
+ ibdev, qp->qpn, IB_GID_ARGS ( gid ) );
+
+ /* Detach from multicast GID */
+ ib_mcast_detach ( ibdev, qp, &membership->gid );
+
+ /* Cancel multicast membership join, if applicable */
+ if ( membership->madx ) {
+ ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
+ membership->madx = NULL;
+ }
+
+ /* Send a single group leave MAD */
+ ib_mcast_mad ( ibdev, &membership->gid, 0, &mad );
+ if ( ( rc = ib_mi_send ( ibdev, ibdev->gsi, &mad, NULL ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %lx could not send leave request: "
+ "%s\n", ibdev, qp->qpn, strerror ( rc ) );
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_mi.c b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_mi.c
new file mode 100644
index 00000000..d4cf58a6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_mi.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/ib_mi.h>
+
+/**
+ * @file
+ *
+ * Infiniband management interfaces
+ *
+ */
+
+/** Management interface number of send WQEs
+ *
+ * This is a policy decision.
+ */
+#define IB_MI_NUM_SEND_WQES 4
+
+/** Management interface number of receive WQEs
+ *
+ * This is a policy decision.
+ */
+#define IB_MI_NUM_RECV_WQES 2
+
+/** Management interface number of completion queue entries
+ *
+ * This is a policy decision
+ */
+#define IB_MI_NUM_CQES 8
+
+/** TID magic signature */
+#define IB_MI_TID_MAGIC ( ( 'i' << 24 ) | ( 'P' << 16 ) | ( 'X' << 8 ) | 'E' )
+
+/** TID to use for next MAD */
+static unsigned int next_tid;
+
+/**
+ * Handle received MAD
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ * @ret rc Return status code
+ */
+static int ib_mi_handle ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_mad_hdr *hdr = &mad->hdr;
+ struct ib_mad_transaction *madx;
+ struct ib_mad_agent *agent;
+
+ /* Look for a matching transaction by TID */
+ list_for_each_entry ( madx, &mi->madx, list ) {
+ if ( memcmp ( &hdr->tid, &madx->mad.hdr.tid,
+ sizeof ( hdr->tid ) ) != 0 )
+ continue;
+ /* Found a matching transaction */
+ madx->op->complete ( ibdev, mi, madx, 0, mad, av );
+ return 0;
+ }
+
+ /* If there is no matching transaction, look for a listening agent */
+ for_each_table_entry ( agent, IB_MAD_AGENTS ) {
+ if ( ( ( agent->mgmt_class & IB_MGMT_CLASS_MASK ) !=
+ ( hdr->mgmt_class & IB_MGMT_CLASS_MASK ) ) ||
+ ( agent->class_version != hdr->class_version ) ||
+ ( agent->attr_id != hdr->attr_id ) )
+ continue;
+ /* Found a matching agent */
+ agent->handle ( ibdev, mi, mad, av );
+ return 0;
+ }
+
+ /* Otherwise, ignore it */
+ DBGC ( mi, "MI %p RX TID %08x%08x ignored\n",
+ mi, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ) );
+ return -ENOTSUP;
+}
+
+/**
+ * Complete receive via management interface
+ *
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+static void ib_mi_complete_recv ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc ) {
+ struct ib_mad_interface *mi = ib_qp_get_ownerdata ( qp );
+ union ib_mad *mad;
+ struct ib_mad_hdr *hdr;
+
+ /* Ignore errors */
+ if ( rc != 0 ) {
+ DBGC ( mi, "MI %p RX error: %s\n", mi, strerror ( rc ) );
+ goto out;
+ }
+
+ /* Sanity checks */
+ if ( iob_len ( iobuf ) != sizeof ( *mad ) ) {
+ DBGC ( mi, "MI %p RX bad size (%zd bytes)\n",
+ mi, iob_len ( iobuf ) );
+ DBGC_HDA ( mi, 0, iobuf->data, iob_len ( iobuf ) );
+ goto out;
+ }
+ mad = iobuf->data;
+ hdr = &mad->hdr;
+ if ( hdr->base_version != IB_MGMT_BASE_VERSION ) {
+ DBGC ( mi, "MI %p RX unsupported base version %x\n",
+ mi, hdr->base_version );
+ DBGC_HDA ( mi, 0, mad, sizeof ( *mad ) );
+ goto out;
+ }
+ DBGC ( mi, "MI %p RX TID %08x%08x (%02x,%02x,%02x,%04x) status "
+ "%04x\n", mi, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ),
+ hdr->mgmt_class, hdr->class_version, hdr->method,
+ ntohs ( hdr->attr_id ), ntohs ( hdr->status ) );
+ DBGC2_HDA ( mi, 0, mad, sizeof ( *mad ) );
+
+ /* Handle MAD */
+ if ( ( rc = ib_mi_handle ( ibdev, mi, mad, av ) ) != 0 )
+ goto out;
+
+ out:
+ free_iob ( iobuf );
+}
+
+/** Management interface completion operations */
+static struct ib_completion_queue_operations ib_mi_completion_ops = {
+ .complete_recv = ib_mi_complete_recv,
+};
+
+/**
+ * Transmit MAD
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad MAD
+ * @v av Destination address vector
+ * @ret rc Return status code
+ */
+int ib_mi_send ( struct ib_device *ibdev, struct ib_mad_interface *mi,
+ union ib_mad *mad, struct ib_address_vector *av ) {
+ struct ib_mad_hdr *hdr = &mad->hdr;
+ struct io_buffer *iobuf;
+ int rc;
+
+ /* Set common fields */
+ hdr->base_version = IB_MGMT_BASE_VERSION;
+ if ( ( hdr->tid[0] == 0 ) && ( hdr->tid[1] == 0 ) ) {
+ hdr->tid[0] = htonl ( IB_MI_TID_MAGIC );
+ hdr->tid[1] = htonl ( ++next_tid );
+ }
+ DBGC ( mi, "MI %p TX TID %08x%08x (%02x,%02x,%02x,%04x) status "
+ "%04x\n", mi, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ),
+ hdr->mgmt_class, hdr->class_version, hdr->method,
+ ntohs ( hdr->attr_id ), ntohs ( hdr->status ) );
+ DBGC2_HDA ( mi, 0, mad, sizeof ( *mad ) );
+
+ /* Construct directed route portion of response, if necessary */
+ if ( hdr->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE ) {
+ struct ib_mad_smp *smp = &mad->smp;
+ unsigned int hop_pointer;
+ unsigned int hop_count;
+
+ smp->mad_hdr.status |= htons ( IB_SMP_STATUS_D_INBOUND );
+ hop_pointer = smp->mad_hdr.class_specific.smp.hop_pointer;
+ hop_count = smp->mad_hdr.class_specific.smp.hop_count;
+ assert ( hop_count == hop_pointer );
+ if ( hop_pointer < ( sizeof ( smp->return_path.hops ) /
+ sizeof ( smp->return_path.hops[0] ) ) ) {
+ smp->return_path.hops[hop_pointer] = ibdev->port;
+ } else {
+ DBGC ( mi, "MI %p TX TID %08x%08x invalid hop pointer "
+ "%d\n", mi, ntohl ( hdr->tid[0] ),
+ ntohl ( hdr->tid[1] ), hop_pointer );
+ return -EINVAL;
+ }
+ }
+
+ /* Construct I/O buffer */
+ iobuf = alloc_iob ( sizeof ( *mad ) );
+ if ( ! iobuf ) {
+ DBGC ( mi, "MI %p could not allocate buffer for TID "
+ "%08x%08x\n",
+ mi, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ) );
+ return -ENOMEM;
+ }
+ memcpy ( iob_put ( iobuf, sizeof ( *mad ) ), mad, sizeof ( *mad ) );
+
+ /* Send I/O buffer */
+ if ( ( rc = ib_post_send ( ibdev, mi->qp, av, iobuf ) ) != 0 ) {
+ DBGC ( mi, "MI %p TX TID %08x%08x failed: %s\n",
+ mi, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ),
+ strerror ( rc ) );
+ free_iob ( iobuf );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle management transaction timer expiry
+ *
+ * @v timer Retry timer
+ * @v expired Failure indicator
+ */
+static void ib_mi_timer_expired ( struct retry_timer *timer, int expired ) {
+ struct ib_mad_transaction *madx =
+ container_of ( timer, struct ib_mad_transaction, timer );
+ struct ib_mad_interface *mi = madx->mi;
+ struct ib_device *ibdev = mi->ibdev;
+ struct ib_mad_hdr *hdr = &madx->mad.hdr;
+
+ /* Abandon transaction if we have tried too many times */
+ if ( expired ) {
+ DBGC ( mi, "MI %p abandoning TID %08x%08x\n",
+ mi, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ) );
+ madx->op->complete ( ibdev, mi, madx, -ETIMEDOUT, NULL, NULL );
+ return;
+ }
+
+ /* Restart retransmission timer */
+ start_timer ( timer );
+
+ /* Resend MAD */
+ ib_mi_send ( ibdev, mi, &madx->mad, &madx->av );
+}
+
+/**
+ * Create management transaction
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad MAD to send
+ * @v av Destination address, or NULL to use SM's GSI
+ * @v op Management transaction operations
+ * @ret madx Management transaction, or NULL
+ */
+struct ib_mad_transaction *
+ib_create_madx ( struct ib_device *ibdev, struct ib_mad_interface *mi,
+ union ib_mad *mad, struct ib_address_vector *av,
+ struct ib_mad_transaction_operations *op ) {
+ struct ib_mad_transaction *madx;
+
+ /* Allocate and initialise structure */
+ madx = zalloc ( sizeof ( *madx ) );
+ if ( ! madx )
+ return NULL;
+ timer_init ( &madx->timer, ib_mi_timer_expired, NULL );
+ madx->mi = mi;
+ madx->op = op;
+
+ /* Determine address vector */
+ if ( av ) {
+ memcpy ( &madx->av, av, sizeof ( madx->av ) );
+ } else {
+ madx->av.lid = ibdev->sm_lid;
+ madx->av.sl = ibdev->sm_sl;
+ madx->av.qpn = IB_QPN_GSI;
+ madx->av.qkey = IB_QKEY_GSI;
+ }
+
+ /* Copy MAD */
+ memcpy ( &madx->mad, mad, sizeof ( madx->mad ) );
+
+ /* Add to list and start timer to send initial MAD */
+ list_add ( &madx->list, &mi->madx );
+ start_timer_nodelay ( &madx->timer );
+
+ return madx;
+}
+
+/**
+ * Destroy management transaction
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v madx Management transaction
+ */
+void ib_destroy_madx ( struct ib_device *ibdev __unused,
+ struct ib_mad_interface *mi __unused,
+ struct ib_mad_transaction *madx ) {
+
+ /* Stop timer and remove from list */
+ stop_timer ( &madx->timer );
+ list_del ( &madx->list );
+
+ /* Free transaction */
+ free ( madx );
+}
+
+/**
+ * Create management interface
+ *
+ * @v ibdev Infiniband device
+ * @v type Queue pair type
+ * @ret mi Management agent, or NULL
+ */
+struct ib_mad_interface * ib_create_mi ( struct ib_device *ibdev,
+ enum ib_queue_pair_type type ) {
+ struct ib_mad_interface *mi;
+ int rc;
+
+ /* Allocate and initialise fields */
+ mi = zalloc ( sizeof ( *mi ) );
+ if ( ! mi )
+ goto err_alloc;
+ mi->ibdev = ibdev;
+ INIT_LIST_HEAD ( &mi->madx );
+
+ /* Create completion queue */
+ mi->cq = ib_create_cq ( ibdev, IB_MI_NUM_CQES, &ib_mi_completion_ops );
+ if ( ! mi->cq ) {
+ DBGC ( mi, "MI %p could not allocate completion queue\n", mi );
+ goto err_create_cq;
+ }
+
+ /* Create queue pair */
+ mi->qp = ib_create_qp ( ibdev, type, IB_MI_NUM_SEND_WQES, mi->cq,
+ IB_MI_NUM_RECV_WQES, mi->cq );
+ if ( ! mi->qp ) {
+ DBGC ( mi, "MI %p could not allocate queue pair\n", mi );
+ goto err_create_qp;
+ }
+ ib_qp_set_ownerdata ( mi->qp, mi );
+ DBGC ( mi, "MI %p (%s) running on QPN %#lx\n",
+ mi, ( ( type == IB_QPT_SMI ) ? "SMI" : "GSI" ), mi->qp->qpn );
+
+ /* Set queue key */
+ mi->qp->qkey = ( ( type == IB_QPT_SMI ) ? IB_QKEY_SMI : IB_QKEY_GSI );
+ if ( ( rc = ib_modify_qp ( ibdev, mi->qp ) ) != 0 ) {
+ DBGC ( mi, "MI %p could not set queue key: %s\n",
+ mi, strerror ( rc ) );
+ goto err_modify_qp;
+ }
+
+ /* Fill receive ring */
+ ib_refill_recv ( ibdev, mi->qp );
+ return mi;
+
+ err_modify_qp:
+ ib_destroy_qp ( ibdev, mi->qp );
+ err_create_qp:
+ ib_destroy_cq ( ibdev, mi->cq );
+ err_create_cq:
+ free ( mi );
+ err_alloc:
+ return NULL;
+}
+
+/**
+ * Destroy management interface
+ *
+ * @v mi Management interface
+ */
+void ib_destroy_mi ( struct ib_device *ibdev, struct ib_mad_interface *mi ) {
+ struct ib_mad_transaction *madx;
+ struct ib_mad_transaction *tmp;
+
+ /* Flush any outstanding requests */
+ list_for_each_entry_safe ( madx, tmp, &mi->madx, list ) {
+ DBGC ( mi, "MI %p destroyed while TID %08x%08x in progress\n",
+ mi, ntohl ( madx->mad.hdr.tid[0] ),
+ ntohl ( madx->mad.hdr.tid[1] ) );
+ madx->op->complete ( ibdev, mi, madx, -ECANCELED, NULL, NULL );
+ }
+
+ ib_destroy_qp ( ibdev, mi->qp );
+ ib_destroy_cq ( ibdev, mi->cq );
+ free ( mi );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_packet.c b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_packet.c
new file mode 100644
index 00000000..d58e0ad4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_packet.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/ib_packet.h>
+
+/**
+ * @file
+ *
+ * Infiniband Packet Formats
+ *
+ */
+
+/**
+ * Add IB headers
+ *
+ * @v ibdev Infiniband device
+ * @v iobuf I/O buffer to contain headers
+ * @v qp Queue pair
+ * @v payload_len Payload length
+ * @v av Address vector
+ */
+int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf,
+ struct ib_queue_pair *qp, size_t payload_len,
+ const struct ib_address_vector *av ) {
+ struct ib_local_route_header *lrh;
+ struct ib_global_route_header *grh;
+ struct ib_base_transport_header *bth;
+ struct ib_datagram_extended_transport_header *deth;
+ size_t orig_iob_len = iob_len ( iobuf );
+ size_t pad_len;
+ size_t lrh_len;
+ size_t grh_len;
+ unsigned int vl;
+ unsigned int lnh;
+
+ DBGC2 ( ibdev, "IBDEV %p TX %04x:%08lx => %04x:%08lx (key %08lx)\n",
+ ibdev, ibdev->lid, qp->ext_qpn, av->lid, av->qpn, av->qkey );
+
+ /* Calculate packet length */
+ pad_len = ( (-payload_len) & 0x3 );
+ payload_len += pad_len;
+ payload_len += 4; /* ICRC */
+
+ /* Reserve space for headers */
+ orig_iob_len = iob_len ( iobuf );
+ deth = iob_push ( iobuf, sizeof ( *deth ) );
+ bth = iob_push ( iobuf, sizeof ( *bth ) );
+ grh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len );
+ grh = ( av->gid_present ?
+ iob_push ( iobuf, sizeof ( *grh ) ) : NULL );
+ lrh = iob_push ( iobuf, sizeof ( *lrh ) );
+ lrh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len );
+
+ /* Construct LRH */
+ vl = ( ( qp->ext_qpn == IB_QPN_SMI ) ? IB_VL_SMP : IB_VL_DEFAULT );
+ lrh->vl__lver = ( vl << 4 );
+ lnh = ( grh ? IB_LNH_GRH : IB_LNH_BTH );
+ lrh->sl__lnh = ( ( av->sl << 4 ) | lnh );
+ lrh->dlid = htons ( av->lid );
+ lrh->length = htons ( lrh_len >> 2 );
+ lrh->slid = htons ( ibdev->lid );
+
+ /* Construct GRH, if required */
+ if ( grh ) {
+ grh->ipver__tclass__flowlabel =
+ htonl ( IB_GRH_IPVER_IPv6 << 28 );
+ grh->paylen = htons ( grh_len );
+ grh->nxthdr = IB_GRH_NXTHDR_IBA;
+ grh->hoplmt = 0;
+ memcpy ( &grh->sgid, &ibdev->gid, sizeof ( grh->sgid ) );
+ memcpy ( &grh->dgid, &av->gid, sizeof ( grh->dgid ) );
+ }
+
+ /* Construct BTH */
+ bth->opcode = BTH_OPCODE_UD_SEND;
+ bth->se__m__padcnt__tver = ( pad_len << 4 );
+ bth->pkey = htons ( ibdev->pkey );
+ bth->dest_qp = htonl ( av->qpn );
+ bth->ack__psn = htonl ( ( qp->send.psn++ ) & 0xffffffUL );
+
+ /* Construct DETH */
+ deth->qkey = htonl ( av->qkey );
+ deth->src_qp = htonl ( qp->ext_qpn );
+
+ DBGCP_HDA ( ibdev, 0, iobuf->data,
+ ( iob_len ( iobuf ) - orig_iob_len ) );
+
+ return 0;
+}
+
+/**
+ * Remove IB headers
+ *
+ * @v ibdev Infiniband device
+ * @v iobuf I/O buffer containing headers
+ * @v qp Queue pair to fill in, or NULL
+ * @v payload_len Payload length to fill in, or NULL
+ * @v av Address vector to fill in
+ */
+int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf,
+ struct ib_queue_pair **qp, size_t *payload_len,
+ struct ib_address_vector *av ) {
+ struct ib_local_route_header *lrh;
+ struct ib_global_route_header *grh;
+ struct ib_base_transport_header *bth;
+ struct ib_datagram_extended_transport_header *deth;
+ size_t orig_iob_len = iob_len ( iobuf );
+ unsigned int lnh;
+ size_t pad_len;
+ unsigned long qpn;
+ unsigned int lid;
+
+ /* Clear return values */
+ if ( qp )
+ *qp = NULL;
+ if ( payload_len )
+ *payload_len = 0;
+ memset ( av, 0, sizeof ( *av ) );
+
+ /* Extract LRH */
+ if ( iob_len ( iobuf ) < sizeof ( *lrh ) ) {
+ DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) for LRH\n",
+ ibdev, iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+ lrh = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *lrh ) );
+ av->lid = ntohs ( lrh->slid );
+ av->sl = ( lrh->sl__lnh >> 4 );
+ lnh = ( lrh->sl__lnh & 0x3 );
+ lid = ntohs ( lrh->dlid );
+
+ /* Reject unsupported packets */
+ if ( ! ( ( lnh == IB_LNH_BTH ) || ( lnh == IB_LNH_GRH ) ) ) {
+ DBGC ( ibdev, "IBDEV %p RX unsupported LNH %x\n",
+ ibdev, lnh );
+ return -ENOTSUP;
+ }
+
+ /* Extract GRH, if present */
+ if ( lnh == IB_LNH_GRH ) {
+ if ( iob_len ( iobuf ) < sizeof ( *grh ) ) {
+ DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) "
+ "for GRH\n", ibdev, iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+ grh = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *grh ) );
+ av->gid_present = 1;
+ memcpy ( &av->gid, &grh->sgid, sizeof ( av->gid ) );
+ } else {
+ grh = NULL;
+ }
+
+ /* Extract BTH */
+ if ( iob_len ( iobuf ) < sizeof ( *bth ) ) {
+ DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) for BTH\n",
+ ibdev, iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+ bth = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *bth ) );
+ if ( bth->opcode != BTH_OPCODE_UD_SEND ) {
+ DBGC ( ibdev, "IBDEV %p unsupported BTH opcode %x\n",
+ ibdev, bth->opcode );
+ return -ENOTSUP;
+ }
+ qpn = ntohl ( bth->dest_qp );
+
+ /* Extract DETH */
+ if ( iob_len ( iobuf ) < sizeof ( *deth ) ) {
+ DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) for DETH\n",
+ ibdev, iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+ deth = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *deth ) );
+ av->qpn = ntohl ( deth->src_qp );
+ av->qkey = ntohl ( deth->qkey );
+
+ /* Calculate payload length, if applicable */
+ if ( payload_len ) {
+ pad_len = ( ( bth->se__m__padcnt__tver >> 4 ) & 0x3 );
+ *payload_len = ( ( ntohs ( lrh->length ) << 2 )
+ - ( orig_iob_len - iob_len ( iobuf ) )
+ - pad_len - 4 /* ICRC */ );
+ }
+
+ /* Determine destination QP, if applicable */
+ if ( qp ) {
+ if ( IB_LID_MULTICAST ( lid ) && grh ) {
+ if ( ! ( *qp = ib_find_qp_mgid ( ibdev, &grh->dgid ))){
+ DBGC ( ibdev, "IBDEV %p RX for unknown MGID "
+ IB_GID_FMT "\n",
+ ibdev, IB_GID_ARGS ( &grh->dgid ) );
+ return -ENODEV;
+ }
+ } else {
+ if ( ! ( *qp = ib_find_qp_qpn ( ibdev, qpn ) ) ) {
+ DBGC ( ibdev, "IBDEV %p RX for nonexistent "
+ "QPN %lx\n", ibdev, qpn );
+ return -ENODEV;
+ }
+ }
+ assert ( *qp );
+ }
+
+ DBGC2 ( ibdev, "IBDEV %p RX %04x:%08lx <= %04x:%08lx (key %08x)\n",
+ ibdev, lid, ( IB_LID_MULTICAST( lid ) ?
+ ( qp ? (*qp)->ext_qpn : -1UL ) : qpn ),
+ av->lid, av->qpn, ntohl ( deth->qkey ) );
+ DBGCP_HDA ( ibdev, 0,
+ ( iobuf->data - ( orig_iob_len - iob_len ( iobuf ) ) ),
+ ( orig_iob_len - iob_len ( iobuf ) ) );
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_pathrec.c b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_pathrec.c
new file mode 100644
index 00000000..7b914654
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_pathrec.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/ib_mi.h>
+#include <ipxe/ib_pathrec.h>
+
+/** @file
+ *
+ * Infiniband path lookups
+ *
+ */
+
+/**
+ * Handle path transaction completion
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v madx Management transaction
+ * @v rc Status code
+ * @v mad Received MAD (or NULL on error)
+ * @v av Source address vector (or NULL on error)
+ */
+static void ib_path_complete ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ struct ib_mad_transaction *madx,
+ int rc, union ib_mad *mad,
+ struct ib_address_vector *av __unused ) {
+ struct ib_path *path = ib_madx_get_ownerdata ( madx );
+ union ib_gid *dgid = &path->av.gid;
+ struct ib_path_record *pathrec = &mad->sa.sa_data.path_record;
+
+ /* Report failures */
+ if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ))
+ rc = -ENETUNREACH;
+ if ( rc != 0 ) {
+ DBGC ( ibdev, "IBDEV %p path lookup for " IB_GID_FMT
+ " failed: %s\n",
+ ibdev, IB_GID_ARGS ( dgid ), strerror ( rc ) );
+ goto out;
+ }
+
+ /* Extract values from MAD */
+ path->av.lid = ntohs ( pathrec->dlid );
+ path->av.sl = ( pathrec->reserved__sl & 0x0f );
+ path->av.rate = ( pathrec->rate_selector__rate & 0x3f );
+ DBGC ( ibdev, "IBDEV %p path to " IB_GID_FMT " is %04x sl %d rate "
+ "%d\n", ibdev, IB_GID_ARGS ( dgid ), path->av.lid, path->av.sl,
+ path->av.rate );
+
+ out:
+ /* Destroy the completed transaction */
+ ib_destroy_madx ( ibdev, mi, madx );
+ path->madx = NULL;
+
+ /* Hand off to upper completion handler */
+ path->op->complete ( ibdev, path, rc, &path->av );
+}
+
+/** Path transaction completion operations */
+static struct ib_mad_transaction_operations ib_path_op = {
+ .complete = ib_path_complete,
+};
+
+/**
+ * Create path
+ *
+ * @v ibdev Infiniband device
+ * @v av Address vector to complete
+ * @v op Path operations
+ * @ret path Path
+ */
+struct ib_path *
+ib_create_path ( struct ib_device *ibdev, struct ib_address_vector *av,
+ struct ib_path_operations *op ) {
+ struct ib_path *path;
+ union ib_mad mad;
+ struct ib_mad_sa *sa = &mad.sa;
+
+ /* Allocate and initialise structure */
+ path = zalloc ( sizeof ( *path ) );
+ if ( ! path )
+ goto err_alloc_path;
+ path->ibdev = ibdev;
+ memcpy ( &path->av, av, sizeof ( path->av ) );
+ path->op = op;
+
+ /* Construct path request */
+ memset ( sa, 0, sizeof ( *sa ) );
+ sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
+ sa->mad_hdr.class_version = IB_SA_CLASS_VERSION;
+ sa->mad_hdr.method = IB_MGMT_METHOD_GET;
+ sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_PATH_REC );
+ sa->sa_hdr.comp_mask[1] =
+ htonl ( IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID );
+ memcpy ( &sa->sa_data.path_record.dgid, &path->av.gid,
+ sizeof ( sa->sa_data.path_record.dgid ) );
+ memcpy ( &sa->sa_data.path_record.sgid, &ibdev->gid,
+ sizeof ( sa->sa_data.path_record.sgid ) );
+
+ /* Create management transaction */
+ path->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, NULL,
+ &ib_path_op );
+ if ( ! path->madx )
+ goto err_create_madx;
+ ib_madx_set_ownerdata ( path->madx, path );
+
+ return path;
+
+ ib_destroy_madx ( ibdev, ibdev->gsi, path->madx );
+ err_create_madx:
+ free ( path );
+ err_alloc_path:
+ return NULL;
+}
+
+/**
+ * Destroy path
+ *
+ * @v ibdev Infiniband device
+ * @v path Path
+ */
+void ib_destroy_path ( struct ib_device *ibdev, struct ib_path *path ) {
+
+ if ( path->madx )
+ ib_destroy_madx ( ibdev, ibdev->gsi, path->madx );
+ free ( path );
+}
+
+/** Number of path cache entries
+ *
+ * Must be a power of two.
+ */
+#define IB_NUM_CACHED_PATHS 4
+
+/** A cached path */
+struct ib_cached_path {
+ /** Path */
+ struct ib_path *path;
+};
+
+/** Path cache */
+static struct ib_cached_path ib_path_cache[IB_NUM_CACHED_PATHS];
+
+/** Oldest path cache entry index */
+static unsigned int ib_path_cache_idx;
+
+/**
+ * Find path cache entry
+ *
+ * @v ibdev Infiniband device
+ * @v dgid Destination GID
+ * @ret path Path cache entry, or NULL
+ */
+static struct ib_cached_path *
+ib_find_path_cache_entry ( struct ib_device *ibdev, union ib_gid *dgid ) {
+ struct ib_cached_path *cached;
+ unsigned int i;
+
+ for ( i = 0 ; i < IB_NUM_CACHED_PATHS ; i++ ) {
+ cached = &ib_path_cache[i];
+ if ( ! cached->path )
+ continue;
+ if ( cached->path->ibdev != ibdev )
+ continue;
+ if ( memcmp ( &cached->path->av.gid, dgid,
+ sizeof ( cached->path->av.gid ) ) != 0 )
+ continue;
+ return cached;
+ }
+
+ return NULL;
+}
+
+/**
+ * Handle cached path transaction completion
+ *
+ * @v ibdev Infiniband device
+ * @v path Path
+ * @v rc Status code
+ * @v av Address vector, or NULL on error
+ */
+static void ib_cached_path_complete ( struct ib_device *ibdev,
+ struct ib_path *path, int rc,
+ struct ib_address_vector *av __unused ) {
+ struct ib_cached_path *cached = ib_path_get_ownerdata ( path );
+
+ /* If the transaction failed, erase the cache entry */
+ if ( rc != 0 ) {
+ /* Destroy the old cache entry */
+ ib_destroy_path ( ibdev, path );
+ memset ( cached, 0, sizeof ( *cached ) );
+ return;
+ }
+
+ /* Do not destroy the completed transaction; we still need to
+ * refer to the resolved path.
+ */
+}
+
+/** Cached path transaction completion operations */
+static struct ib_path_operations ib_cached_path_op = {
+ .complete = ib_cached_path_complete,
+};
+
+/**
+ * Resolve path
+ *
+ * @v ibdev Infiniband device
+ * @v av Address vector to complete
+ * @ret rc Return status code
+ *
+ * This provides a non-transactional way to resolve a path, via a
+ * cache similar to ARP.
+ */
+int ib_resolve_path ( struct ib_device *ibdev, struct ib_address_vector *av ) {
+ union ib_gid *gid = &av->gid;
+ struct ib_cached_path *cached;
+ unsigned int cache_idx;
+
+ /* Sanity check */
+ if ( ! av->gid_present ) {
+ DBGC ( ibdev, "IBDEV %p attempt to look up path without GID\n",
+ ibdev );
+ return -EINVAL;
+ }
+
+ /* Look in cache for a matching entry */
+ cached = ib_find_path_cache_entry ( ibdev, gid );
+ if ( cached && cached->path->av.lid ) {
+ /* Populated entry found */
+ av->lid = cached->path->av.lid;
+ av->rate = cached->path->av.rate;
+ av->sl = cached->path->av.sl;
+ DBGC2 ( ibdev, "IBDEV %p cache hit for " IB_GID_FMT "\n",
+ ibdev, IB_GID_ARGS ( gid ) );
+ return 0;
+ }
+ DBGC ( ibdev, "IBDEV %p cache miss for " IB_GID_FMT "%s\n", ibdev,
+ IB_GID_ARGS ( gid ), ( cached ? " (in progress)" : "" ) );
+
+ /* If lookup is already in progress, do nothing */
+ if ( cached )
+ return -ENOENT;
+
+ /* Locate a new cache entry to use */
+ cache_idx = ( (ib_path_cache_idx++) % IB_NUM_CACHED_PATHS );
+ cached = &ib_path_cache[cache_idx];
+
+ /* Destroy the old cache entry */
+ if ( cached->path )
+ ib_destroy_path ( ibdev, cached->path );
+ memset ( cached, 0, sizeof ( *cached ) );
+
+ /* Create new path */
+ cached->path = ib_create_path ( ibdev, av, &ib_cached_path_op );
+ if ( ! cached->path ) {
+ DBGC ( ibdev, "IBDEV %p could not create path\n",
+ ibdev );
+ return -ENOMEM;
+ }
+ ib_path_set_ownerdata ( cached->path, cached );
+
+ /* Not found yet */
+ return -ENOENT;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_sma.c b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_sma.c
new file mode 100644
index 00000000..1f3c6d80
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_sma.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/settings.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/ib_mi.h>
+#include <ipxe/ib_sma.h>
+
+/**
+ * @file
+ *
+ * Infiniband Subnet Management Agent
+ *
+ */
+
+/**
+ * Node information
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ */
+static void ib_sma_node_info ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_node_info *node_info = &mad->smp.smp_data.node_info;
+ int rc;
+
+ /* Fill in information */
+ memset ( node_info, 0, sizeof ( *node_info ) );
+ node_info->base_version = IB_MGMT_BASE_VERSION;
+ node_info->class_version = IB_SMP_CLASS_VERSION;
+ node_info->node_type = IB_NODE_TYPE_HCA;
+ node_info->num_ports = ib_count_ports ( ibdev );
+ memcpy ( &node_info->sys_guid, &ibdev->node_guid,
+ sizeof ( node_info->sys_guid ) );
+ memcpy ( &node_info->node_guid, &ibdev->node_guid,
+ sizeof ( node_info->node_guid ) );
+ memcpy ( &node_info->port_guid, &ibdev->gid.s.guid,
+ sizeof ( node_info->port_guid ) );
+ node_info->partition_cap = htons ( 1 );
+ node_info->local_port_num = ibdev->port;
+
+ /* Send GetResponse */
+ mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
+ if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not send NodeInfo GetResponse: %s\n",
+ mi, strerror ( rc ) );
+ return;
+ }
+}
+
+/**
+ * Node description
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ */
+static void ib_sma_node_desc ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_node_desc *node_desc = &mad->smp.smp_data.node_desc;
+ union ib_guid *guid = &ibdev->node_guid;
+ char hostname[ sizeof ( node_desc->node_string ) ];
+ int hostname_len;
+ int rc;
+
+ /* Fill in information */
+ memset ( node_desc, 0, sizeof ( *node_desc ) );
+ hostname_len = fetch_string_setting ( NULL, &hostname_setting,
+ hostname, sizeof ( hostname ) );
+ snprintf ( node_desc->node_string, sizeof ( node_desc->node_string ),
+ "iPXE %s%s%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)",
+ hostname, ( ( hostname_len >= 0 ) ? " " : "" ),
+ guid->bytes[0], guid->bytes[1], guid->bytes[2],
+ guid->bytes[3], guid->bytes[4], guid->bytes[5],
+ guid->bytes[6], guid->bytes[7], ibdev->dev->name );
+
+ /* Send GetResponse */
+ mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
+ if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not send NodeDesc GetResponse: %s\n",
+ mi, strerror ( rc ) );
+ return;
+ }
+}
+
+/**
+ * GUID information
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ */
+static void ib_sma_guid_info ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_guid_info *guid_info = &mad->smp.smp_data.guid_info;
+ int rc;
+
+ /* Fill in information */
+ memset ( guid_info, 0, sizeof ( *guid_info ) );
+ memcpy ( guid_info->guid[0], &ibdev->gid.s.guid,
+ sizeof ( guid_info->guid[0] ) );
+
+ /* Send GetResponse */
+ mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
+ if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not send GuidInfo GetResponse: %s\n",
+ mi, strerror ( rc ) );
+ return;
+ }
+}
+
+/**
+ * Set port information
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @ret rc Return status code
+ */
+static int ib_sma_set_port_info ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad ) {
+ const struct ib_port_info *port_info = &mad->smp.smp_data.port_info;
+ unsigned int link_width_enabled;
+ unsigned int link_speed_enabled;
+ int rc;
+
+ /* Set parameters */
+ memcpy ( &ibdev->gid.s.prefix, port_info->gid_prefix,
+ sizeof ( ibdev->gid.s.prefix ) );
+ ibdev->lid = ntohs ( port_info->lid );
+ ibdev->sm_lid = ntohs ( port_info->mastersm_lid );
+ if ( ( link_width_enabled = port_info->link_width_enabled ) )
+ ibdev->link_width_enabled = link_width_enabled;
+ if ( ( link_speed_enabled =
+ ( port_info->link_speed_active__link_speed_enabled & 0xf ) ) )
+ ibdev->link_speed_enabled = link_speed_enabled;
+ ibdev->sm_sl = ( port_info->neighbour_mtu__mastersm_sl & 0xf );
+ DBGC ( mi, "SMA %p set LID %04x SMLID %04x link width %02x speed "
+ "%02x\n", mi, ibdev->lid, ibdev->sm_lid,
+ ibdev->link_width_enabled, ibdev->link_speed_enabled );
+
+ /* Update parameters on device */
+ if ( ( rc = ib_set_port_info ( ibdev, mad ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not set port information: %s\n",
+ mi, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Port information
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ */
+static void ib_sma_port_info ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_port_info *port_info = &mad->smp.smp_data.port_info;
+ int rc;
+
+ /* Set parameters if applicable */
+ if ( mad->hdr.method == IB_MGMT_METHOD_SET ) {
+ if ( ( rc = ib_sma_set_port_info ( ibdev, mi, mad ) ) != 0 ) {
+ mad->hdr.status =
+ htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR );
+ /* Fall through to generate GetResponse */
+ }
+ }
+
+ /* Fill in information */
+ memset ( port_info, 0, sizeof ( *port_info ) );
+ memcpy ( port_info->gid_prefix, &ibdev->gid.s.prefix,
+ sizeof ( port_info->gid_prefix ) );
+ port_info->lid = ntohs ( ibdev->lid );
+ port_info->mastersm_lid = ntohs ( ibdev->sm_lid );
+ port_info->local_port_num = ibdev->port;
+ port_info->link_width_enabled = ibdev->link_width_enabled;
+ port_info->link_width_supported = ibdev->link_width_supported;
+ port_info->link_width_active = ibdev->link_width_active;
+ port_info->link_speed_supported__port_state =
+ ( ( ibdev->link_speed_supported << 4 ) | ibdev->port_state );
+ port_info->port_phys_state__link_down_def_state =
+ ( ( IB_PORT_PHYS_STATE_POLLING << 4 ) |
+ IB_PORT_PHYS_STATE_POLLING );
+ port_info->link_speed_active__link_speed_enabled =
+ ( ( ibdev->link_speed_active << 4 ) |
+ ibdev->link_speed_enabled );
+ port_info->neighbour_mtu__mastersm_sl =
+ ( ( IB_MTU_2048 << 4 ) | ibdev->sm_sl );
+ port_info->vl_cap__init_type = ( IB_VL_0 << 4 );
+ port_info->init_type_reply__mtu_cap = IB_MTU_2048;
+ port_info->operational_vls__enforcement = ( IB_VL_0 << 4 );
+ port_info->guid_cap = 1;
+
+ /* Send GetResponse */
+ mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
+ if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not send PortInfo GetResponse: %s\n",
+ mi, strerror ( rc ) );
+ return;
+ }
+}
+
+/**
+ * Set partition key table
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @ret rc Return status code
+ */
+static int ib_sma_set_pkey_table ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad ) {
+ struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table;
+ int rc;
+
+ /* Set parameters */
+ ibdev->pkey = ntohs ( pkey_table->pkey[0] );
+ DBGC ( mi, "SMA %p set pkey %04x\n", mi, ibdev->pkey );
+
+ /* Update parameters on device */
+ if ( ( rc = ib_set_pkey_table ( ibdev, mad ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not set pkey table: %s\n",
+ mi, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Partition key table
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ */
+static void ib_sma_pkey_table ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table;
+ int rc;
+
+ /* Set parameters, if applicable */
+ if ( mad->hdr.method == IB_MGMT_METHOD_SET ) {
+ if ( ( rc = ib_sma_set_pkey_table ( ibdev, mi, mad ) ) != 0 ) {
+ mad->hdr.status =
+ htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR );
+ /* Fall through to generate GetResponse */
+ }
+ }
+
+ /* Fill in information */
+ mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
+ memset ( pkey_table, 0, sizeof ( *pkey_table ) );
+ pkey_table->pkey[0] = htons ( ibdev->pkey );
+
+ /* Send GetResponse */
+ mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
+ if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not send PKeyTable GetResponse: %s\n",
+ mi, strerror ( rc ) );
+ return;
+ }
+}
+
+/** Subnet management agent */
+struct ib_mad_agent ib_sma_agent[] __ib_mad_agent = {
+ {
+ .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
+ .class_version = IB_SMP_CLASS_VERSION,
+ .attr_id = htons ( IB_SMP_ATTR_NODE_INFO ),
+ .handle = ib_sma_node_info,
+ },
+ {
+ .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
+ .class_version = IB_SMP_CLASS_VERSION,
+ .attr_id = htons ( IB_SMP_ATTR_NODE_DESC ),
+ .handle = ib_sma_node_desc,
+ },
+ {
+ .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
+ .class_version = IB_SMP_CLASS_VERSION,
+ .attr_id = htons ( IB_SMP_ATTR_GUID_INFO ),
+ .handle = ib_sma_guid_info,
+ },
+ {
+ .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
+ .class_version = IB_SMP_CLASS_VERSION,
+ .attr_id = htons ( IB_SMP_ATTR_PORT_INFO ),
+ .handle = ib_sma_port_info,
+ },
+ {
+ .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
+ .class_version = IB_SMP_CLASS_VERSION,
+ .attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE ),
+ .handle = ib_sma_pkey_table,
+ },
+};
+
+/**
+ * Create subnet management agent and interface
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @ret rc Return status code
+ */
+int ib_create_sma ( struct ib_device *ibdev, struct ib_mad_interface *mi ) {
+
+ /* Nothing to do */
+ DBGC ( ibdev, "IBDEV %p SMA using SMI %p\n", ibdev, mi );
+
+ return 0;
+}
+
+/**
+ * Destroy subnet management agent and interface
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ */
+void ib_destroy_sma ( struct ib_device *ibdev __unused,
+ struct ib_mad_interface *mi __unused ) {
+ /* Nothing to do */
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_smc.c b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_smc.c
new file mode 100644
index 00000000..8196cb7e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_smc.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/ib_smc.h>
+
+/**
+ * @file
+ *
+ * Infiniband Subnet Management Client
+ *
+ */
+
+/**
+ * Issue local MAD
+ *
+ * @v ibdev Infiniband device
+ * @v attr_id Attribute ID, in network byte order
+ * @v attr_mod Attribute modifier, in network byte order
+ * @v local_mad Method for issuing local MADs
+ * @v mad Management datagram to fill in
+ * @ret rc Return status code
+ */
+static int ib_smc_mad ( struct ib_device *ibdev, uint16_t attr_id,
+ uint32_t attr_mod, ib_local_mad_t local_mad,
+ union ib_mad *mad ) {
+ int rc;
+
+ /* Construct MAD */
+ memset ( mad, 0, sizeof ( *mad ) );
+ mad->hdr.base_version = IB_MGMT_BASE_VERSION;
+ mad->hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
+ mad->hdr.class_version = 1;
+ mad->hdr.method = IB_MGMT_METHOD_GET;
+ mad->hdr.attr_id = attr_id;
+ mad->hdr.attr_mod = attr_mod;
+
+ /* Issue MAD */
+ if ( ( rc = local_mad ( ibdev, mad ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Get node information
+ *
+ * @v ibdev Infiniband device
+ * @v local_mad Method for issuing local MADs
+ * @v mad Management datagram to fill in
+ * @ret rc Return status code
+ */
+static int ib_smc_get_node_info ( struct ib_device *ibdev,
+ ib_local_mad_t local_mad,
+ union ib_mad *mad ) {
+ int rc;
+
+ /* Issue MAD */
+ if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_NODE_INFO ), 0,
+ local_mad, mad ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not get node info: %s\n",
+ ibdev, strerror ( rc ) );
+ return rc;
+ }
+ return 0;
+}
+
+/**
+ * Get port information
+ *
+ * @v ibdev Infiniband device
+ * @v local_mad Method for issuing local MADs
+ * @v mad Management datagram to fill in
+ * @ret rc Return status code
+ */
+static int ib_smc_get_port_info ( struct ib_device *ibdev,
+ ib_local_mad_t local_mad,
+ union ib_mad *mad ) {
+ int rc;
+
+ /* Issue MAD */
+ if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_PORT_INFO ),
+ htonl ( ibdev->port ), local_mad, mad )) !=0){
+ DBGC ( ibdev, "IBDEV %p could not get port info: %s\n",
+ ibdev, strerror ( rc ) );
+ return rc;
+ }
+ return 0;
+}
+
+/**
+ * Get GUID information
+ *
+ * @v ibdev Infiniband device
+ * @v local_mad Method for issuing local MADs
+ * @v mad Management datagram to fill in
+ * @ret rc Return status code
+ */
+static int ib_smc_get_guid_info ( struct ib_device *ibdev,
+ ib_local_mad_t local_mad,
+ union ib_mad *mad ) {
+ int rc;
+
+ /* Issue MAD */
+ if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_GUID_INFO ), 0,
+ local_mad, mad ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not get GUID info: %s\n",
+ ibdev, strerror ( rc ) );
+ return rc;
+ }
+ return 0;
+}
+
+/**
+ * Get partition key table
+ *
+ * @v ibdev Infiniband device
+ * @v local_mad Method for issuing local MADs
+ * @v mad Management datagram to fill in
+ * @ret rc Return status code
+ */
+static int ib_smc_get_pkey_table ( struct ib_device *ibdev,
+ ib_local_mad_t local_mad,
+ union ib_mad *mad ) {
+ int rc;
+
+ /* Issue MAD */
+ if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_PKEY_TABLE ), 0,
+ local_mad, mad ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not get pkey table: %s\n",
+ ibdev, strerror ( rc ) );
+ return rc;
+ }
+ return 0;
+}
+
+/**
+ * Get Infiniband parameters using SMC
+ *
+ * @v ibdev Infiniband device
+ * @v local_mad Method for issuing local MADs
+ * @ret rc Return status code
+ */
+static int ib_smc_get ( struct ib_device *ibdev, ib_local_mad_t local_mad ) {
+ union ib_mad mad;
+ struct ib_node_info *node_info = &mad.smp.smp_data.node_info;
+ struct ib_port_info *port_info = &mad.smp.smp_data.port_info;
+ struct ib_guid_info *guid_info = &mad.smp.smp_data.guid_info;
+ struct ib_pkey_table *pkey_table = &mad.smp.smp_data.pkey_table;
+ int rc;
+
+ /* Node info gives us the node GUID */
+ if ( ( rc = ib_smc_get_node_info ( ibdev, local_mad, &mad ) ) != 0 )
+ return rc;
+ memcpy ( &ibdev->node_guid, &node_info->node_guid,
+ sizeof ( ibdev->node_guid ) );
+
+ /* Port info gives us the link state, the first half of the
+ * port GID and the SM LID.
+ */
+ if ( ( rc = ib_smc_get_port_info ( ibdev, local_mad, &mad ) ) != 0 )
+ return rc;
+ memcpy ( &ibdev->gid.s.prefix, port_info->gid_prefix,
+ sizeof ( ibdev->gid.s.prefix ) );
+ ibdev->lid = ntohs ( port_info->lid );
+ ibdev->sm_lid = ntohs ( port_info->mastersm_lid );
+ ibdev->link_width_enabled = port_info->link_width_enabled;
+ ibdev->link_width_supported = port_info->link_width_supported;
+ ibdev->link_width_active = port_info->link_width_active;
+ ibdev->link_speed_supported =
+ ( port_info->link_speed_supported__port_state >> 4 );
+ ibdev->port_state =
+ ( port_info->link_speed_supported__port_state & 0xf );
+ ibdev->link_speed_active =
+ ( port_info->link_speed_active__link_speed_enabled >> 4 );
+ ibdev->link_speed_enabled =
+ ( port_info->link_speed_active__link_speed_enabled & 0xf );
+ ibdev->sm_sl = ( port_info->neighbour_mtu__mastersm_sl & 0xf );
+
+ /* GUID info gives us the second half of the port GID */
+ if ( ( rc = ib_smc_get_guid_info ( ibdev, local_mad, &mad ) ) != 0 )
+ return rc;
+ memcpy ( &ibdev->gid.s.guid, guid_info->guid[0],
+ sizeof ( ibdev->gid.s.guid ) );
+
+ /* Get partition key */
+ if ( ( rc = ib_smc_get_pkey_table ( ibdev, local_mad, &mad ) ) != 0 )
+ return rc;
+ ibdev->pkey = ntohs ( pkey_table->pkey[0] );
+
+ DBGC ( ibdev, "IBDEV %p port GID is " IB_GID_FMT "\n",
+ ibdev, IB_GID_ARGS ( &ibdev->gid ) );
+
+ return 0;
+}
+
+/**
+ * Initialise Infiniband parameters using SMC
+ *
+ * @v ibdev Infiniband device
+ * @v local_mad Method for issuing local MADs
+ * @ret rc Return status code
+ */
+int ib_smc_init ( struct ib_device *ibdev, ib_local_mad_t local_mad ) {
+ int rc;
+
+ /* Get MAD parameters */
+ if ( ( rc = ib_smc_get ( ibdev, local_mad ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Update Infiniband parameters using SMC
+ *
+ * @v ibdev Infiniband device
+ * @v local_mad Method for issuing local MADs
+ * @ret rc Return status code
+ */
+int ib_smc_update ( struct ib_device *ibdev, ib_local_mad_t local_mad ) {
+ int rc;
+
+ /* Get MAD parameters */
+ if ( ( rc = ib_smc_get ( ibdev, local_mad ) ) != 0 )
+ return rc;
+
+ /* Notify Infiniband core of potential link state change */
+ ib_link_state_changed ( ibdev );
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_srp.c b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_srp.c
new file mode 100644
index 00000000..7b2b2b4e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/infiniband/ib_srp.c
@@ -0,0 +1,581 @@
+/*
+ * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdlib.h>
+#include <errno.h>
+#include <ipxe/interface.h>
+#include <ipxe/uri.h>
+#include <ipxe/open.h>
+#include <ipxe/base16.h>
+#include <ipxe/acpi.h>
+#include <ipxe/srp.h>
+#include <ipxe/infiniband.h>
+#include <ipxe/ib_cmrc.h>
+#include <ipxe/ib_srp.h>
+
+/**
+ * @file
+ *
+ * SCSI RDMA Protocol over Infiniband
+ *
+ */
+
+/* Disambiguate the various possible EINVALs */
+#define EINVAL_BYTE_STRING_LEN __einfo_error ( EINFO_EINVAL_BYTE_STRING_LEN )
+#define EINFO_EINVAL_BYTE_STRING_LEN __einfo_uniqify \
+ ( EINFO_EINVAL, 0x01, "Invalid byte string length" )
+#define EINVAL_INTEGER __einfo_error ( EINFO_EINVAL_INTEGER )
+#define EINFO_EINVAL_INTEGER __einfo_uniqify \
+ ( EINFO_EINVAL, 0x03, "Invalid integer" )
+#define EINVAL_RP_TOO_SHORT __einfo_error ( EINFO_EINVAL_RP_TOO_SHORT )
+#define EINFO_EINVAL_RP_TOO_SHORT __einfo_uniqify \
+ ( EINFO_EINVAL, 0x04, "Root path too short" )
+
+/******************************************************************************
+ *
+ * IB SRP devices
+ *
+ ******************************************************************************
+ */
+
+/** An Infiniband SRP device */
+struct ib_srp_device {
+ /** Reference count */
+ struct refcnt refcnt;
+
+ /** SRP transport interface */
+ struct interface srp;
+ /** CMRC interface */
+ struct interface cmrc;
+
+ /** Infiniband device */
+ struct ib_device *ibdev;
+
+ /** Destination GID (for boot firmware table) */
+ union ib_gid dgid;
+ /** Service ID (for boot firmware table) */
+ union ib_guid service_id;
+};
+
+/**
+ * Free IB SRP device
+ *
+ * @v refcnt Reference count
+ */
+static void ib_srp_free ( struct refcnt *refcnt ) {
+ struct ib_srp_device *ib_srp =
+ container_of ( refcnt, struct ib_srp_device, refcnt );
+
+ ibdev_put ( ib_srp->ibdev );
+ free ( ib_srp );
+}
+
+/**
+ * Close IB SRP device
+ *
+ * @v ib_srp IB SRP device
+ * @v rc Reason for close
+ */
+static void ib_srp_close ( struct ib_srp_device *ib_srp, int rc ) {
+
+ /* Shut down interfaces */
+ intf_shutdown ( &ib_srp->cmrc, rc );
+ intf_shutdown ( &ib_srp->srp, rc );
+}
+
+/**
+ * Describe IB SRP device in an ACPI table
+ *
+ * @v srpdev SRP device
+ * @v acpi ACPI table
+ * @v len Length of ACPI table
+ * @ret rc Return status code
+ */
+static int ib_srp_describe ( struct ib_srp_device *ib_srp,
+ struct acpi_description_header *acpi,
+ size_t len ) {
+ struct ib_device *ibdev = ib_srp->ibdev;
+ struct sbft_table *sbft =
+ container_of ( acpi, struct sbft_table, acpi );
+ struct sbft_ib_subtable *ib_sbft;
+ size_t used;
+
+ /* Sanity check */
+ if ( acpi->signature != SBFT_SIG )
+ return -EINVAL;
+
+ /* Append IB subtable to existing table */
+ used = le32_to_cpu ( sbft->acpi.length );
+ sbft->ib_offset = cpu_to_le16 ( used );
+ ib_sbft = ( ( ( void * ) sbft ) + used );
+ used += sizeof ( *ib_sbft );
+ if ( used > len )
+ return -ENOBUFS;
+ sbft->acpi.length = cpu_to_le32 ( used );
+
+ /* Populate subtable */
+ memcpy ( &ib_sbft->sgid, &ibdev->gid, sizeof ( ib_sbft->sgid ) );
+ memcpy ( &ib_sbft->dgid, &ib_srp->dgid, sizeof ( ib_sbft->dgid ) );
+ memcpy ( &ib_sbft->service_id, &ib_srp->service_id,
+ sizeof ( ib_sbft->service_id ) );
+ ib_sbft->pkey = cpu_to_le16 ( ibdev->pkey );
+
+ return 0;
+}
+
+/** IB SRP CMRC interface operations */
+static struct interface_operation ib_srp_cmrc_op[] = {
+ INTF_OP ( intf_close, struct ib_srp_device *, ib_srp_close ),
+};
+
+/** IB SRP CMRC interface descriptor */
+static struct interface_descriptor ib_srp_cmrc_desc =
+ INTF_DESC_PASSTHRU ( struct ib_srp_device, cmrc, ib_srp_cmrc_op, srp );
+
+/** IB SRP SRP interface operations */
+static struct interface_operation ib_srp_srp_op[] = {
+ INTF_OP ( acpi_describe, struct ib_srp_device *, ib_srp_describe ),
+ INTF_OP ( intf_close, struct ib_srp_device *, ib_srp_close ),
+};
+
+/** IB SRP SRP interface descriptor */
+static struct interface_descriptor ib_srp_srp_desc =
+ INTF_DESC_PASSTHRU ( struct ib_srp_device, srp, ib_srp_srp_op, cmrc );
+
+/**
+ * Open IB SRP device
+ *
+ * @v block Block control interface
+ * @v ibdev Infiniband device
+ * @v dgid Destination GID
+ * @v service_id Service ID
+ * @v initiator Initiator port ID
+ * @v target Target port ID
+ * @v lun SCSI LUN
+ * @ret rc Return status code
+ */
+static int ib_srp_open ( struct interface *block, struct ib_device *ibdev,
+ union ib_gid *dgid, union ib_guid *service_id,
+ union srp_port_id *initiator,
+ union srp_port_id *target, struct scsi_lun *lun ) {
+ struct ib_srp_device *ib_srp;
+ int rc;
+
+ /* Allocate and initialise structure */
+ ib_srp = zalloc ( sizeof ( *ib_srp ) );
+ if ( ! ib_srp ) {
+ rc = -ENOMEM;
+ goto err_zalloc;
+ }
+ ref_init ( &ib_srp->refcnt, ib_srp_free );
+ intf_init ( &ib_srp->srp, &ib_srp_srp_desc, &ib_srp->refcnt );
+ intf_init ( &ib_srp->cmrc, &ib_srp_cmrc_desc, &ib_srp->refcnt );
+ ib_srp->ibdev = ibdev_get ( ibdev );
+ DBGC ( ib_srp, "IBSRP %p for " IB_GID_FMT " " IB_GUID_FMT "\n",
+ ib_srp, IB_GID_ARGS ( dgid ), IB_GUID_ARGS ( service_id ) );
+
+ /* Preserve parameters required for boot firmware table */
+ memcpy ( &ib_srp->dgid, dgid, sizeof ( ib_srp->dgid ) );
+ memcpy ( &ib_srp->service_id, service_id,
+ sizeof ( ib_srp->service_id ) );
+
+ /* Open CMRC socket */
+ if ( ( rc = ib_cmrc_open ( &ib_srp->cmrc, ibdev, dgid,
+ service_id ) ) != 0 ) {
+ DBGC ( ib_srp, "IBSRP %p could not open CMRC socket: %s\n",
+ ib_srp, strerror ( rc ) );
+ goto err_cmrc_open;
+ }
+
+ /* Attach SRP device to parent interface */
+ if ( ( rc = srp_open ( block, &ib_srp->srp, initiator, target,
+ ibdev->rdma_key, lun ) ) != 0 ) {
+ DBGC ( ib_srp, "IBSRP %p could not create SRP device: %s\n",
+ ib_srp, strerror ( rc ) );
+ goto err_srp_open;
+ }
+
+ /* Mortalise self and return */
+ ref_put ( &ib_srp->refcnt );
+ return 0;
+
+ err_srp_open:
+ err_cmrc_open:
+ ib_srp_close ( ib_srp, rc );
+ ref_put ( &ib_srp->refcnt );
+ err_zalloc:
+ return rc;
+}
+
+/******************************************************************************
+ *
+ * IB SRP URIs
+ *
+ ******************************************************************************
+ */
+
+/** IB SRP parse flags */
+enum ib_srp_parse_flags {
+ IB_SRP_PARSE_REQUIRED = 0x0000,
+ IB_SRP_PARSE_OPTIONAL = 0x8000,
+ IB_SRP_PARSE_FLAG_MASK = 0xf000,
+};
+
+/** IB SRP root path parameters */
+struct ib_srp_root_path {
+ /** Source GID */
+ union ib_gid sgid;
+ /** Initiator port ID */
+ union ib_srp_initiator_port_id initiator;
+ /** Destination GID */
+ union ib_gid dgid;
+ /** Partition key */
+ uint16_t pkey;
+ /** Service ID */
+ union ib_guid service_id;
+ /** SCSI LUN */
+ struct scsi_lun lun;
+ /** Target port ID */
+ union ib_srp_target_port_id target;
+};
+
+/**
+ * Parse IB SRP root path byte-string value
+ *
+ * @v rp_comp Root path component string
+ * @v default_value Default value to use if component string is empty
+ * @ret value Value
+ */
+static int ib_srp_parse_byte_string ( const char *rp_comp, uint8_t *bytes,
+ unsigned int size_flags ) {
+ size_t size = ( size_flags & ~IB_SRP_PARSE_FLAG_MASK );
+ size_t rp_comp_len = strlen ( rp_comp );
+ int decoded_size;
+
+ /* Allow optional components to be empty */
+ if ( ( rp_comp_len == 0 ) &&
+ ( size_flags & IB_SRP_PARSE_OPTIONAL ) )
+ return 0;
+
+ /* Check string length */
+ if ( rp_comp_len != ( 2 * size ) )
+ return -EINVAL_BYTE_STRING_LEN;
+
+ /* Parse byte string */
+ decoded_size = base16_decode ( rp_comp, bytes );
+ if ( decoded_size < 0 )
+ return decoded_size;
+
+ return 0;
+}
+
+/**
+ * Parse IB SRP root path integer value
+ *
+ * @v rp_comp Root path component string
+ * @v default_value Default value to use if component string is empty
+ * @ret value Value
+ */
+static int ib_srp_parse_integer ( const char *rp_comp, int default_value ) {
+ int value;
+ char *end;
+
+ value = strtoul ( rp_comp, &end, 16 );
+ if ( *end )
+ return -EINVAL_INTEGER;
+
+ if ( end == rp_comp )
+ return default_value;
+
+ return value;
+}
+
+/**
+ * Parse IB SRP root path source GID
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_sgid ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ struct ib_device *ibdev;
+
+ /* Default to the GID of the last opened Infiniband device */
+ if ( ( ibdev = last_opened_ibdev() ) != NULL )
+ memcpy ( &rp->sgid, &ibdev->gid, sizeof ( rp->sgid ) );
+
+ return ib_srp_parse_byte_string ( rp_comp, rp->sgid.bytes,
+ ( sizeof ( rp->sgid ) |
+ IB_SRP_PARSE_OPTIONAL ) );
+}
+
+/**
+ * Parse IB SRP root path initiator identifier extension
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_initiator_id_ext ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ union ib_srp_initiator_port_id *port_id = &rp->initiator;
+
+ return ib_srp_parse_byte_string ( rp_comp, port_id->ib.id_ext.bytes,
+ ( sizeof ( port_id->ib.id_ext ) |
+ IB_SRP_PARSE_OPTIONAL ) );
+}
+
+/**
+ * Parse IB SRP root path initiator HCA GUID
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_initiator_hca_guid ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ union ib_srp_initiator_port_id *port_id = &rp->initiator;
+
+ /* Default to the GUID portion of the source GID */
+ memcpy ( &port_id->ib.hca_guid, &rp->sgid.s.guid,
+ sizeof ( port_id->ib.hca_guid ) );
+
+ return ib_srp_parse_byte_string ( rp_comp, port_id->ib.hca_guid.bytes,
+ ( sizeof ( port_id->ib.hca_guid ) |
+ IB_SRP_PARSE_OPTIONAL ) );
+}
+
+/**
+ * Parse IB SRP root path destination GID
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_dgid ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ return ib_srp_parse_byte_string ( rp_comp, rp->dgid.bytes,
+ ( sizeof ( rp->dgid ) |
+ IB_SRP_PARSE_REQUIRED ) );
+}
+
+/**
+ * Parse IB SRP root path partition key
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_pkey ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ int pkey;
+
+ if ( ( pkey = ib_srp_parse_integer ( rp_comp, IB_PKEY_DEFAULT ) ) < 0 )
+ return pkey;
+ rp->pkey = pkey;
+ return 0;
+}
+
+/**
+ * Parse IB SRP root path service ID
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_service_id ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ return ib_srp_parse_byte_string ( rp_comp, rp->service_id.bytes,
+ ( sizeof ( rp->service_id ) |
+ IB_SRP_PARSE_REQUIRED ) );
+}
+
+/**
+ * Parse IB SRP root path LUN
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_lun ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ return scsi_parse_lun ( rp_comp, &rp->lun );
+}
+
+/**
+ * Parse IB SRP root path target identifier extension
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_target_id_ext ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ union ib_srp_target_port_id *port_id = &rp->target;
+
+ return ib_srp_parse_byte_string ( rp_comp, port_id->ib.id_ext.bytes,
+ ( sizeof ( port_id->ib.id_ext ) |
+ IB_SRP_PARSE_REQUIRED ) );
+}
+
+/**
+ * Parse IB SRP root path target I/O controller GUID
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_target_ioc_guid ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ union ib_srp_target_port_id *port_id = &rp->target;
+
+ return ib_srp_parse_byte_string ( rp_comp, port_id->ib.ioc_guid.bytes,
+ ( sizeof ( port_id->ib.ioc_guid ) |
+ IB_SRP_PARSE_REQUIRED ) );
+}
+
+/** IB SRP root path component parser */
+struct ib_srp_root_path_parser {
+ /**
+ * Parse IB SRP root path component
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+ int ( * parse ) ( const char *rp_comp, struct ib_srp_root_path *rp );
+};
+
+/** IB SRP root path components */
+static struct ib_srp_root_path_parser ib_srp_rp_parser[] = {
+ { ib_srp_parse_sgid },
+ { ib_srp_parse_initiator_id_ext },
+ { ib_srp_parse_initiator_hca_guid },
+ { ib_srp_parse_dgid },
+ { ib_srp_parse_pkey },
+ { ib_srp_parse_service_id },
+ { ib_srp_parse_lun },
+ { ib_srp_parse_target_id_ext },
+ { ib_srp_parse_target_ioc_guid },
+};
+
+/** Number of IB SRP root path components */
+#define IB_SRP_NUM_RP_COMPONENTS \
+ ( sizeof ( ib_srp_rp_parser ) / sizeof ( ib_srp_rp_parser[0] ) )
+
+/**
+ * Parse IB SRP root path
+ *
+ * @v rp_string Root path string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_root_path ( const char *rp_string,
+ struct ib_srp_root_path *rp ) {
+ struct ib_srp_root_path_parser *parser;
+ char rp_string_copy[ strlen ( rp_string ) + 1 ];
+ char *rp_comp[IB_SRP_NUM_RP_COMPONENTS];
+ char *rp_string_tmp = rp_string_copy;
+ unsigned int i = 0;
+ int rc;
+
+ /* Split root path into component parts */
+ strcpy ( rp_string_copy, rp_string );
+ while ( 1 ) {
+ rp_comp[i++] = rp_string_tmp;
+ if ( i == IB_SRP_NUM_RP_COMPONENTS )
+ break;
+ for ( ; *rp_string_tmp != ':' ; rp_string_tmp++ ) {
+ if ( ! *rp_string_tmp ) {
+ DBG ( "IBSRP root path \"%s\" too short\n",
+ rp_string );
+ return -EINVAL_RP_TOO_SHORT;
+ }
+ }
+ *(rp_string_tmp++) = '\0';
+ }
+
+ /* Parse root path components */
+ for ( i = 0 ; i < IB_SRP_NUM_RP_COMPONENTS ; i++ ) {
+ parser = &ib_srp_rp_parser[i];
+ if ( ( rc = parser->parse ( rp_comp[i], rp ) ) != 0 ) {
+ DBG ( "IBSRP could not parse \"%s\" in root path "
+ "\"%s\": %s\n", rp_comp[i], rp_string,
+ strerror ( rc ) );
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Open IB SRP URI
+ *
+ * @v parent Parent interface
+ * @v uri URI
+ * @ret rc Return status code
+ */
+static int ib_srp_open_uri ( struct interface *parent, struct uri *uri ) {
+ struct ib_srp_root_path rp;
+ struct ib_device *ibdev;
+ int rc;
+
+ /* Parse URI */
+ if ( ! uri->opaque )
+ return -EINVAL;
+ memset ( &rp, 0, sizeof ( rp ) );
+ if ( ( rc = ib_srp_parse_root_path ( uri->opaque, &rp ) ) != 0 )
+ return rc;
+
+ /* Identify Infiniband device */
+ ibdev = find_ibdev ( &rp.sgid );
+ if ( ! ibdev ) {
+ DBG ( "IBSRP could not identify Infiniband device\n" );
+ return -ENODEV;
+ }
+
+ /* Open IB SRP device */
+ if ( ( rc = ib_srp_open ( parent, ibdev, &rp.dgid, &rp.service_id,
+ &rp.initiator.srp, &rp.target.srp,
+ &rp.lun ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/** IB SRP URI opener */
+struct uri_opener ib_srp_uri_opener __uri_opener = {
+ .scheme = "ib_srp",
+ .open = ib_srp_open_uri,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/iobpad.c b/src/VBox/Devices/PC/ipxe/src/net/iobpad.c
new file mode 100644
index 00000000..f83c76d8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/iobpad.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * I/O buffer padding
+ *
+ */
+
+#include <string.h>
+#include <ipxe/iobuf.h>
+
+/**
+ * Pad I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v min_len Minimum length
+ *
+ * This function pads and aligns I/O buffers, for devices that
+ * aren't capable of padding in hardware, or that require specific
+ * alignment in TX buffers. The packet data will end up aligned to a
+ * multiple of @c IOB_ALIGN.
+ *
+ * @c min_len must not exceed @v IOB_ZLEN.
+ */
+void iob_pad ( struct io_buffer *iobuf, size_t min_len ) {
+ void *data;
+ size_t len;
+ size_t headroom;
+ signed int pad_len;
+
+ assert ( min_len <= IOB_ZLEN );
+
+ /* Move packet data to start of I/O buffer. This will both
+ * align the data (since I/O buffers are aligned to
+ * IOB_ALIGN) and give us sufficient space for the
+ * zero-padding
+ */
+ data = iobuf->data;
+ len = iob_len ( iobuf );
+ headroom = iob_headroom ( iobuf );
+ iob_push ( iobuf, headroom );
+ memmove ( iobuf->data, data, len );
+ iob_unput ( iobuf, headroom );
+
+ /* Pad to minimum packet length */
+ pad_len = ( min_len - iob_len ( iobuf ) );
+ if ( pad_len > 0 )
+ memset ( iob_put ( iobuf, pad_len ), 0, pad_len );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/ipv4.c b/src/VBox/Devices/PC/ipxe/src/net/ipv4.c
new file mode 100644
index 00000000..08249d41
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/ipv4.c
@@ -0,0 +1,714 @@
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/list.h>
+#include <ipxe/in.h>
+#include <ipxe/arp.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ip.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/settings.h>
+#include <ipxe/timer.h>
+
+/** @file
+ *
+ * IPv4 protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* Unique IP datagram identification number (high byte) */
+static uint8_t next_ident_high = 0;
+
+/** List of IPv4 miniroutes */
+struct list_head ipv4_miniroutes = LIST_HEAD_INIT ( ipv4_miniroutes );
+
+/** List of fragment reassembly buffers */
+static LIST_HEAD ( ipv4_fragments );
+
+/** Fragment reassembly timeout */
+#define IP_FRAG_TIMEOUT ( TICKS_PER_SEC / 2 )
+
+/**
+ * Add IPv4 minirouting table entry
+ *
+ * @v netdev Network device
+ * @v address IPv4 address
+ * @v netmask Subnet mask
+ * @v gateway Gateway address (if any)
+ * @ret miniroute Routing table entry, or NULL
+ */
+static struct ipv4_miniroute * __malloc
+add_ipv4_miniroute ( struct net_device *netdev, struct in_addr address,
+ struct in_addr netmask, struct in_addr gateway ) {
+ struct ipv4_miniroute *miniroute;
+
+ DBGC ( netdev, "IPv4 add %s", inet_ntoa ( address ) );
+ DBGC ( netdev, "/%s ", inet_ntoa ( netmask ) );
+ if ( gateway.s_addr )
+ DBGC ( netdev, "gw %s ", inet_ntoa ( gateway ) );
+ DBGC ( netdev, "via %s\n", netdev->name );
+
+ /* Allocate and populate miniroute structure */
+ miniroute = malloc ( sizeof ( *miniroute ) );
+ if ( ! miniroute ) {
+ DBGC ( netdev, "IPv4 could not add miniroute\n" );
+ return NULL;
+ }
+
+ /* Record routing information */
+ miniroute->netdev = netdev_get ( netdev );
+ miniroute->address = address;
+ miniroute->netmask = netmask;
+ miniroute->gateway = gateway;
+
+ /* Add to end of list if we have a gateway, otherwise
+ * to start of list.
+ */
+ if ( gateway.s_addr ) {
+ list_add_tail ( &miniroute->list, &ipv4_miniroutes );
+ } else {
+ list_add ( &miniroute->list, &ipv4_miniroutes );
+ }
+
+ return miniroute;
+}
+
+/**
+ * Delete IPv4 minirouting table entry
+ *
+ * @v miniroute Routing table entry
+ */
+static void del_ipv4_miniroute ( struct ipv4_miniroute *miniroute ) {
+ struct net_device *netdev = miniroute->netdev;
+
+ DBGC ( netdev, "IPv4 del %s", inet_ntoa ( miniroute->address ) );
+ DBGC ( netdev, "/%s ", inet_ntoa ( miniroute->netmask ) );
+ if ( miniroute->gateway.s_addr )
+ DBGC ( netdev, "gw %s ", inet_ntoa ( miniroute->gateway ) );
+ DBGC ( netdev, "via %s\n", miniroute->netdev->name );
+
+ netdev_put ( miniroute->netdev );
+ list_del ( &miniroute->list );
+ free ( miniroute );
+}
+
+/**
+ * Perform IPv4 routing
+ *
+ * @v dest Final destination address
+ * @ret dest Next hop destination address
+ * @ret miniroute Routing table entry to use, or NULL if no route
+ *
+ * If the route requires use of a gateway, the next hop destination
+ * address will be overwritten with the gateway address.
+ */
+static struct ipv4_miniroute * ipv4_route ( struct in_addr *dest ) {
+ struct ipv4_miniroute *miniroute;
+ int local;
+ int has_gw;
+
+ /* Find first usable route in routing table */
+ list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
+ if ( ! netdev_is_open ( miniroute->netdev ) )
+ continue;
+ local = ( ( ( dest->s_addr ^ miniroute->address.s_addr )
+ & miniroute->netmask.s_addr ) == 0 );
+ has_gw = ( miniroute->gateway.s_addr );
+ if ( local || has_gw ) {
+ if ( ! local )
+ *dest = miniroute->gateway;
+ return miniroute;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Expire fragment reassembly buffer
+ *
+ * @v timer Retry timer
+ * @v fail Failure indicator
+ */
+static void ipv4_fragment_expired ( struct retry_timer *timer,
+ int fail __unused ) {
+ struct ipv4_fragment *frag =
+ container_of ( timer, struct ipv4_fragment, timer );
+ struct iphdr *iphdr = frag->iobuf->data;
+
+ DBGC ( iphdr->src, "IPv4 fragment %04x expired\n",
+ ntohs ( iphdr->ident ) );
+ free_iob ( frag->iobuf );
+ list_del ( &frag->list );
+ free ( frag );
+}
+
+/**
+ * Find matching fragment reassembly buffer
+ *
+ * @v iphdr IPv4 header
+ * @ret frag Fragment reassembly buffer, or NULL
+ */
+static struct ipv4_fragment * ipv4_fragment ( struct iphdr *iphdr ) {
+ struct ipv4_fragment *frag;
+ struct iphdr *frag_iphdr;
+
+ list_for_each_entry ( frag, &ipv4_fragments, list ) {
+ frag_iphdr = frag->iobuf->data;
+
+ if ( ( iphdr->src.s_addr == frag_iphdr->src.s_addr ) &&
+ ( iphdr->ident == frag_iphdr->ident ) ) {
+ return frag;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Fragment reassembler
+ *
+ * @v iobuf I/O buffer
+ * @ret iobuf Reassembled packet, or NULL
+ */
+static struct io_buffer * ipv4_reassemble ( struct io_buffer *iobuf ) {
+ struct iphdr *iphdr = iobuf->data;
+ size_t offset = ( ( ntohs ( iphdr->frags ) & IP_MASK_OFFSET ) << 3 );
+ unsigned int more_frags = ( iphdr->frags & htons ( IP_MASK_MOREFRAGS ));
+ size_t hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
+ struct ipv4_fragment *frag;
+ size_t expected_offset;
+ struct io_buffer *new_iobuf;
+
+ /* Find matching fragment reassembly buffer, if any */
+ frag = ipv4_fragment ( iphdr );
+
+ /* Drop out-of-order fragments */
+ expected_offset = ( frag ? frag->offset : 0 );
+ if ( offset != expected_offset ) {
+ DBGC ( iphdr->src, "IPv4 dropping out-of-sequence fragment "
+ "%04x (%zd+%zd, expected %zd)\n",
+ ntohs ( iphdr->ident ), offset,
+ ( iob_len ( iobuf ) - hdrlen ), expected_offset );
+ goto drop;
+ }
+
+ /* Create or extend fragment reassembly buffer as applicable */
+ if ( frag == NULL ) {
+
+ /* Create new fragment reassembly buffer */
+ frag = zalloc ( sizeof ( *frag ) );
+ if ( ! frag )
+ goto drop;
+ list_add ( &frag->list, &ipv4_fragments );
+ frag->iobuf = iobuf;
+ frag->offset = ( iob_len ( iobuf ) - hdrlen );
+ timer_init ( &frag->timer, ipv4_fragment_expired, NULL );
+
+ } else {
+
+ /* Extend reassembly buffer */
+ iob_pull ( iobuf, hdrlen );
+ new_iobuf = alloc_iob ( iob_len ( frag->iobuf ) +
+ iob_len ( iobuf ) );
+ if ( ! new_iobuf ) {
+ DBGC ( iphdr->src, "IPv4 could not extend reassembly "
+ "buffer to %zd bytes\n",
+ iob_len ( frag->iobuf ) + iob_len ( iobuf ) );
+ goto drop;
+ }
+ memcpy ( iob_put ( new_iobuf, iob_len ( frag->iobuf ) ),
+ frag->iobuf->data, iob_len ( frag->iobuf ) );
+ memcpy ( iob_put ( new_iobuf, iob_len ( iobuf ) ),
+ iobuf->data, iob_len ( iobuf ) );
+ free_iob ( frag->iobuf );
+ frag->iobuf = new_iobuf;
+ frag->offset += iob_len ( iobuf );
+ free_iob ( iobuf );
+ iphdr = frag->iobuf->data;
+ iphdr->len = ntohs ( iob_len ( frag->iobuf ) );
+
+ /* Stop fragment reassembly timer */
+ stop_timer ( &frag->timer );
+
+ /* If this is the final fragment, return it */
+ if ( ! more_frags ) {
+ iobuf = frag->iobuf;
+ list_del ( &frag->list );
+ free ( frag );
+ return iobuf;
+ }
+ }
+
+ /* (Re)start fragment reassembly timer */
+ start_timer_fixed ( &frag->timer, IP_FRAG_TIMEOUT );
+
+ return NULL;
+
+ drop:
+ free_iob ( iobuf );
+ return NULL;
+}
+
+/**
+ * Add IPv4 pseudo-header checksum to existing checksum
+ *
+ * @v iobuf I/O buffer
+ * @v csum Existing checksum
+ * @ret csum Updated checksum
+ */
+static uint16_t ipv4_pshdr_chksum ( struct io_buffer *iobuf, uint16_t csum ) {
+ struct ipv4_pseudo_header pshdr;
+ struct iphdr *iphdr = iobuf->data;
+ size_t hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
+
+ /* Build pseudo-header */
+ pshdr.src = iphdr->src;
+ pshdr.dest = iphdr->dest;
+ pshdr.zero_padding = 0x00;
+ pshdr.protocol = iphdr->protocol;
+ pshdr.len = htons ( iob_len ( iobuf ) - hdrlen );
+
+ /* Update the checksum value */
+ return tcpip_continue_chksum ( csum, &pshdr, sizeof ( pshdr ) );
+}
+
+/**
+ * Transmit IP packet
+ *
+ * @v iobuf I/O buffer
+ * @v tcpip Transport-layer protocol
+ * @v st_src Source network-layer address
+ * @v st_dest Destination network-layer address
+ * @v netdev Network device to use if no route found, or NULL
+ * @v trans_csum Transport-layer checksum to complete, or NULL
+ * @ret rc Status
+ *
+ * This function expects a transport-layer segment and prepends the IP header
+ */
+static int ipv4_tx ( struct io_buffer *iobuf,
+ struct tcpip_protocol *tcpip_protocol,
+ struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest,
+ struct net_device *netdev,
+ uint16_t *trans_csum ) {
+ struct iphdr *iphdr = iob_push ( iobuf, sizeof ( *iphdr ) );
+ struct sockaddr_in *sin_src = ( ( struct sockaddr_in * ) st_src );
+ struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
+ struct ipv4_miniroute *miniroute;
+ struct in_addr next_hop;
+ struct in_addr netmask = { .s_addr = 0 };
+ uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
+ const void *ll_dest;
+ int rc;
+
+ /* Fill up the IP header, except source address */
+ memset ( iphdr, 0, sizeof ( *iphdr ) );
+ iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
+ iphdr->service = IP_TOS;
+ iphdr->len = htons ( iob_len ( iobuf ) );
+ iphdr->ttl = IP_TTL;
+ iphdr->protocol = tcpip_protocol->tcpip_proto;
+ iphdr->dest = sin_dest->sin_addr;
+
+ /* Use routing table to identify next hop and transmitting netdev */
+ next_hop = iphdr->dest;
+ if ( sin_src )
+ iphdr->src = sin_src->sin_addr;
+ if ( ( next_hop.s_addr != INADDR_BROADCAST ) &&
+ ( ! IN_MULTICAST ( ntohl ( next_hop.s_addr ) ) ) &&
+ ( ( miniroute = ipv4_route ( &next_hop ) ) != NULL ) ) {
+ iphdr->src = miniroute->address;
+ netmask = miniroute->netmask;
+ netdev = miniroute->netdev;
+ }
+ if ( ! netdev ) {
+ DBGC ( sin_dest->sin_addr, "IPv4 has no route to %s\n",
+ inet_ntoa ( iphdr->dest ) );
+ rc = -ENETUNREACH;
+ goto err;
+ }
+
+ /* (Ab)use the "ident" field to convey metadata about the
+ * network device statistics into packet traces. Useful for
+ * extracting debug information from non-debug builds.
+ */
+ iphdr->ident = htons ( ( (++next_ident_high) << 8 ) |
+ ( ( netdev->rx_stats.bad & 0xf ) << 4 ) |
+ ( ( netdev->rx_stats.good & 0xf ) << 0 ) );
+
+ /* Fix up checksums */
+ if ( trans_csum )
+ *trans_csum = ipv4_pshdr_chksum ( iobuf, *trans_csum );
+ iphdr->chksum = tcpip_chksum ( iphdr, sizeof ( *iphdr ) );
+
+ /* Print IP4 header for debugging */
+ DBGC2 ( sin_dest->sin_addr, "IPv4 TX %s->", inet_ntoa ( iphdr->src ) );
+ DBGC2 ( sin_dest->sin_addr, "%s len %d proto %d id %04x csum %04x\n",
+ inet_ntoa ( iphdr->dest ), ntohs ( iphdr->len ),
+ iphdr->protocol, ntohs ( iphdr->ident ),
+ ntohs ( iphdr->chksum ) );
+
+ /* Calculate link-layer destination address, if possible */
+ if ( ( ( next_hop.s_addr ^ INADDR_BROADCAST ) & ~netmask.s_addr ) == 0){
+ /* Broadcast address */
+ ll_dest = netdev->ll_broadcast;
+ } else if ( IN_MULTICAST ( ntohl ( next_hop.s_addr ) ) ) {
+ /* Multicast address */
+ if ( ( rc = netdev->ll_protocol->mc_hash ( AF_INET, &next_hop,
+ ll_dest_buf ) ) !=0){
+ DBGC ( sin_dest->sin_addr, "IPv4 could not hash "
+ "multicast %s: %s\n",
+ inet_ntoa ( next_hop ), strerror ( rc ) );
+ return rc;
+ }
+ ll_dest = ll_dest_buf;
+ } else {
+ /* Unicast address */
+ ll_dest = NULL;
+ }
+
+ /* Hand off to link layer (via ARP if applicable) */
+ if ( ll_dest ) {
+ if ( ( rc = net_tx ( iobuf, netdev, &ipv4_protocol, ll_dest,
+ netdev->ll_addr ) ) != 0 ) {
+ DBGC ( sin_dest->sin_addr, "IPv4 could not transmit "
+ "packet via %s: %s\n",
+ netdev->name, strerror ( rc ) );
+ return rc;
+ }
+ } else {
+ if ( ( rc = arp_tx ( iobuf, netdev, &ipv4_protocol, &next_hop,
+ &iphdr->src, netdev->ll_addr ) ) != 0 ) {
+ DBGC ( sin_dest->sin_addr, "IPv4 could not transmit "
+ "packet via %s: %s\n",
+ netdev->name, strerror ( rc ) );
+ return rc;
+ }
+ }
+
+ return 0;
+
+ err:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Check if network device has any IPv4 address
+ *
+ * @v netdev Network device
+ * @ret has_any_addr Network device has any IPv4 address
+ */
+static int ipv4_has_any_addr ( struct net_device *netdev ) {
+ struct ipv4_miniroute *miniroute;
+
+ list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
+ if ( miniroute->netdev == netdev )
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Check if network device has a specific IPv4 address
+ *
+ * @v netdev Network device
+ * @v addr IPv4 address
+ * @ret has_addr Network device has this IPv4 address
+ */
+static int ipv4_has_addr ( struct net_device *netdev, struct in_addr addr ) {
+ struct ipv4_miniroute *miniroute;
+
+ list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
+ if ( ( miniroute->netdev == netdev ) &&
+ ( miniroute->address.s_addr == addr.s_addr ) ) {
+ /* Found matching address */
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Process incoming packets
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer destination source
+ * @v flags Packet flags
+ * @ret rc Return status code
+ *
+ * This function expects an IP4 network datagram. It processes the headers
+ * and sends it to the transport layer.
+ */
+static int ipv4_rx ( struct io_buffer *iobuf,
+ struct net_device *netdev,
+ const void *ll_dest __unused,
+ const void *ll_source __unused,
+ unsigned int flags ) {
+ struct iphdr *iphdr = iobuf->data;
+ size_t hdrlen;
+ size_t len;
+ union {
+ struct sockaddr_in sin;
+ struct sockaddr_tcpip st;
+ } src, dest;
+ uint16_t csum;
+ uint16_t pshdr_csum;
+ int rc;
+
+ /* Sanity check the IPv4 header */
+ if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
+ DBGC ( iphdr->src, "IPv4 packet too short at %zd bytes (min "
+ "%zd bytes)\n", iob_len ( iobuf ), sizeof ( *iphdr ) );
+ goto err;
+ }
+ if ( ( iphdr->verhdrlen & IP_MASK_VER ) != IP_VER ) {
+ DBGC ( iphdr->src, "IPv4 version %#02x not supported\n",
+ iphdr->verhdrlen );
+ goto err;
+ }
+ hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
+ if ( hdrlen < sizeof ( *iphdr ) ) {
+ DBGC ( iphdr->src, "IPv4 header too short at %zd bytes (min "
+ "%zd bytes)\n", hdrlen, sizeof ( *iphdr ) );
+ goto err;
+ }
+ if ( hdrlen > iob_len ( iobuf ) ) {
+ DBGC ( iphdr->src, "IPv4 header too long at %zd bytes "
+ "(packet is %zd bytes)\n", hdrlen, iob_len ( iobuf ) );
+ goto err;
+ }
+ if ( ( csum = tcpip_chksum ( iphdr, hdrlen ) ) != 0 ) {
+ DBGC ( iphdr->src, "IPv4 checksum incorrect (is %04x "
+ "including checksum field, should be 0000)\n", csum );
+ goto err;
+ }
+ len = ntohs ( iphdr->len );
+ if ( len < hdrlen ) {
+ DBGC ( iphdr->src, "IPv4 length too short at %zd bytes "
+ "(header is %zd bytes)\n", len, hdrlen );
+ goto err;
+ }
+ if ( len > iob_len ( iobuf ) ) {
+ DBGC ( iphdr->src, "IPv4 length too long at %zd bytes "
+ "(packet is %zd bytes)\n", len, iob_len ( iobuf ) );
+ goto err;
+ }
+
+ /* Truncate packet to correct length */
+ iob_unput ( iobuf, ( iob_len ( iobuf ) - len ) );
+
+ /* Print IPv4 header for debugging */
+ DBGC2 ( iphdr->src, "IPv4 RX %s<-", inet_ntoa ( iphdr->dest ) );
+ DBGC2 ( iphdr->src, "%s len %d proto %d id %04x csum %04x\n",
+ inet_ntoa ( iphdr->src ), ntohs ( iphdr->len ), iphdr->protocol,
+ ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
+
+ /* Discard unicast packets not destined for us */
+ if ( ( ! ( flags & LL_MULTICAST ) ) &&
+ ipv4_has_any_addr ( netdev ) &&
+ ( ! ipv4_has_addr ( netdev, iphdr->dest ) ) ) {
+ DBGC ( iphdr->src, "IPv4 discarding non-local unicast packet "
+ "for %s\n", inet_ntoa ( iphdr->dest ) );
+ goto err;
+ }
+
+ /* Perform fragment reassembly if applicable */
+ if ( iphdr->frags & htons ( IP_MASK_OFFSET | IP_MASK_MOREFRAGS ) ) {
+ /* Pass the fragment to ipv4_reassemble() which returns
+ * either a fully reassembled I/O buffer or NULL.
+ */
+ iobuf = ipv4_reassemble ( iobuf );
+ if ( ! iobuf )
+ return 0;
+ iphdr = iobuf->data;
+ hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
+ }
+
+ /* Construct socket addresses, calculate pseudo-header
+ * checksum, and hand off to transport layer
+ */
+ memset ( &src, 0, sizeof ( src ) );
+ src.sin.sin_family = AF_INET;
+ src.sin.sin_addr = iphdr->src;
+ memset ( &dest, 0, sizeof ( dest ) );
+ dest.sin.sin_family = AF_INET;
+ dest.sin.sin_addr = iphdr->dest;
+ pshdr_csum = ipv4_pshdr_chksum ( iobuf, TCPIP_EMPTY_CSUM );
+ iob_pull ( iobuf, hdrlen );
+ if ( ( rc = tcpip_rx ( iobuf, iphdr->protocol, &src.st,
+ &dest.st, pshdr_csum ) ) != 0 ) {
+ DBGC ( src.sin.sin_addr, "IPv4 received packet rejected by "
+ "stack: %s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+
+ err:
+ free_iob ( iobuf );
+ return -EINVAL;
+}
+
+/**
+ * Check existence of IPv4 address for ARP
+ *
+ * @v netdev Network device
+ * @v net_addr Network-layer address
+ * @ret rc Return status code
+ */
+static int ipv4_arp_check ( struct net_device *netdev, const void *net_addr ) {
+ const struct in_addr *address = net_addr;
+
+ if ( ipv4_has_addr ( netdev, *address ) )
+ return 0;
+
+ return -ENOENT;
+}
+
+/**
+ * Convert IPv4 address to dotted-quad notation
+ *
+ * @v in IP address
+ * @ret string IP address in dotted-quad notation
+ */
+char * inet_ntoa ( struct in_addr in ) {
+ static char buf[16]; /* "xxx.xxx.xxx.xxx" */
+ uint8_t *bytes = ( uint8_t * ) &in;
+
+ sprintf ( buf, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3] );
+ return buf;
+}
+
+/**
+ * Transcribe IP address
+ *
+ * @v net_addr IP address
+ * @ret string IP address in dotted-quad notation
+ *
+ */
+static const char * ipv4_ntoa ( const void *net_addr ) {
+ return inet_ntoa ( * ( ( struct in_addr * ) net_addr ) );
+}
+
+/** IPv4 protocol */
+struct net_protocol ipv4_protocol __net_protocol = {
+ .name = "IP",
+ .net_proto = htons ( ETH_P_IP ),
+ .net_addr_len = sizeof ( struct in_addr ),
+ .rx = ipv4_rx,
+ .ntoa = ipv4_ntoa,
+};
+
+/** IPv4 TCPIP net protocol */
+struct tcpip_net_protocol ipv4_tcpip_protocol __tcpip_net_protocol = {
+ .name = "IPv4",
+ .sa_family = AF_INET,
+ .tx = ipv4_tx,
+};
+
+/** IPv4 ARP protocol */
+struct arp_net_protocol ipv4_arp_protocol __arp_net_protocol = {
+ .net_protocol = &ipv4_protocol,
+ .check = ipv4_arp_check,
+};
+
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** IPv4 address setting */
+struct setting ip_setting __setting ( SETTING_IPv4 ) = {
+ .name = "ip",
+ .description = "IP address",
+ .tag = DHCP_EB_YIADDR,
+ .type = &setting_type_ipv4,
+};
+
+/** IPv4 subnet mask setting */
+struct setting netmask_setting __setting ( SETTING_IPv4 ) = {
+ .name = "netmask",
+ .description = "Subnet mask",
+ .tag = DHCP_SUBNET_MASK,
+ .type = &setting_type_ipv4,
+};
+
+/** Default gateway setting */
+struct setting gateway_setting __setting ( SETTING_IPv4 ) = {
+ .name = "gateway",
+ .description = "Default gateway",
+ .tag = DHCP_ROUTERS,
+ .type = &setting_type_ipv4,
+};
+
+/**
+ * Create IPv4 routing table based on configured settings
+ *
+ * @ret rc Return status code
+ */
+static int ipv4_create_routes ( void ) {
+ struct ipv4_miniroute *miniroute;
+ struct ipv4_miniroute *tmp;
+ struct net_device *netdev;
+ struct settings *settings;
+ struct in_addr address = { 0 };
+ struct in_addr netmask = { 0 };
+ struct in_addr gateway = { 0 };
+
+ /* Delete all existing routes */
+ list_for_each_entry_safe ( miniroute, tmp, &ipv4_miniroutes, list )
+ del_ipv4_miniroute ( miniroute );
+
+ /* Create a route for each configured network device */
+ for_each_netdev ( netdev ) {
+ settings = netdev_settings ( netdev );
+ /* Get IPv4 address */
+ address.s_addr = 0;
+ fetch_ipv4_setting ( settings, &ip_setting, &address );
+ if ( ! address.s_addr )
+ continue;
+ /* Get subnet mask */
+ fetch_ipv4_setting ( settings, &netmask_setting, &netmask );
+ /* Calculate default netmask, if necessary */
+ if ( ! netmask.s_addr ) {
+ if ( IN_CLASSA ( ntohl ( address.s_addr ) ) ) {
+ netmask.s_addr = htonl ( IN_CLASSA_NET );
+ } else if ( IN_CLASSB ( ntohl ( address.s_addr ) ) ) {
+ netmask.s_addr = htonl ( IN_CLASSB_NET );
+ } else if ( IN_CLASSC ( ntohl ( address.s_addr ) ) ) {
+ netmask.s_addr = htonl ( IN_CLASSC_NET );
+ }
+ }
+ /* Get default gateway, if present */
+ fetch_ipv4_setting ( settings, &gateway_setting, &gateway );
+ /* Configure route */
+ miniroute = add_ipv4_miniroute ( netdev, address,
+ netmask, gateway );
+ if ( ! miniroute )
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/** IPv4 settings applicator */
+struct settings_applicator ipv4_settings_applicator __settings_applicator = {
+ .apply = ipv4_create_routes,
+};
+
+/* Drag in ICMP */
+REQUIRE_OBJECT ( icmp );
diff --git a/src/VBox/Devices/PC/ipxe/src/net/ipv6.c b/src/VBox/Devices/PC/ipxe/src/net/ipv6.c
new file mode 100644
index 00000000..57bf94d8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/ipv6.c
@@ -0,0 +1,384 @@
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <byteswap.h>
+#include <ipxe/in.h>
+#include <ipxe/ip6.h>
+#include <ipxe/ndp.h>
+#include <ipxe/list.h>
+#include <ipxe/icmp6.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/socket.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/if_ether.h>
+
+/* Unspecified IP6 address */
+static struct in6_addr ip6_none = {
+ .in6_u.u6_addr32 = { 0,0,0,0 }
+};
+
+/** An IPv6 routing table entry */
+struct ipv6_miniroute {
+ /* List of miniroutes */
+ struct list_head list;
+
+ /* Network device */
+ struct net_device *netdev;
+
+ /* Destination prefix */
+ struct in6_addr prefix;
+ /* Prefix length */
+ int prefix_len;
+ /* IPv6 address of interface */
+ struct in6_addr address;
+ /* Gateway address */
+ struct in6_addr gateway;
+};
+
+/** List of IPv6 miniroutes */
+static LIST_HEAD ( miniroutes );
+
+/**
+ * Add IPv6 minirouting table entry
+ *
+ * @v netdev Network device
+ * @v prefix Destination prefix
+ * @v address Address of the interface
+ * @v gateway Gateway address (or ::0 for no gateway)
+ * @ret miniroute Routing table entry, or NULL
+ */
+static struct ipv6_miniroute * __malloc
+add_ipv6_miniroute ( struct net_device *netdev, struct in6_addr prefix,
+ int prefix_len, struct in6_addr address,
+ struct in6_addr gateway ) {
+ struct ipv6_miniroute *miniroute;
+
+ miniroute = malloc ( sizeof ( *miniroute ) );
+ if ( miniroute ) {
+ /* Record routing information */
+ miniroute->netdev = netdev_get ( netdev );
+ miniroute->prefix = prefix;
+ miniroute->prefix_len = prefix_len;
+ miniroute->address = address;
+ miniroute->gateway = gateway;
+
+ /* Add miniroute to list of miniroutes */
+ if ( !IP6_EQUAL ( gateway, ip6_none ) ) {
+ list_add_tail ( &miniroute->list, &miniroutes );
+ } else {
+ list_add ( &miniroute->list, &miniroutes );
+ }
+ }
+
+ return miniroute;
+}
+
+/**
+ * Delete IPv6 minirouting table entry
+ *
+ * @v miniroute Routing table entry
+ */
+static void del_ipv6_miniroute ( struct ipv6_miniroute *miniroute ) {
+ netdev_put ( miniroute->netdev );
+ list_del ( &miniroute->list );
+ free ( miniroute );
+}
+
+/**
+ * Add IPv6 interface
+ *
+ * @v netdev Network device
+ * @v prefix Destination prefix
+ * @v address Address of the interface
+ * @v gateway Gateway address (or ::0 for no gateway)
+ */
+int add_ipv6_address ( struct net_device *netdev, struct in6_addr prefix,
+ int prefix_len, struct in6_addr address,
+ struct in6_addr gateway ) {
+ struct ipv6_miniroute *miniroute;
+
+ /* Clear any existing address for this net device */
+ del_ipv6_address ( netdev );
+
+ /* Add new miniroute */
+ miniroute = add_ipv6_miniroute ( netdev, prefix, prefix_len, address,
+ gateway );
+ if ( ! miniroute )
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * Remove IPv6 interface
+ *
+ * @v netdev Network device
+ */
+void del_ipv6_address ( struct net_device *netdev ) {
+ struct ipv6_miniroute *miniroute;
+
+ list_for_each_entry ( miniroute, &miniroutes, list ) {
+ if ( miniroute->netdev == netdev ) {
+ del_ipv6_miniroute ( miniroute );
+ break;
+ }
+ }
+}
+
+/**
+ * Calculate TCPIP checksum
+ *
+ * @v iobuf I/O buffer
+ * @v tcpip TCP/IP protocol
+ *
+ * This function constructs the pseudo header and completes the checksum in the
+ * upper layer header.
+ */
+static uint16_t ipv6_tx_csum ( struct io_buffer *iobuf, uint16_t csum ) {
+ struct ip6_header *ip6hdr = iobuf->data;
+ struct ipv6_pseudo_header pshdr;
+
+ /* Calculate pseudo header */
+ memset ( &pshdr, 0, sizeof ( pshdr ) );
+ pshdr.src = ip6hdr->src;
+ pshdr.dest = ip6hdr->dest;
+ pshdr.len = htons ( iob_len ( iobuf ) - sizeof ( *ip6hdr ) );
+ pshdr.nxt_hdr = ip6hdr->nxt_hdr;
+
+ /* Update checksum value */
+ return tcpip_continue_chksum ( csum, &pshdr, sizeof ( pshdr ) );
+}
+
+/**
+ * Dump IP6 header for debugging
+ *
+ * ip6hdr IPv6 header
+ */
+void ipv6_dump ( struct ip6_header *ip6hdr ) {
+ DBG ( "IP6 %p src %s dest %s nxt_hdr %d len %d\n", ip6hdr,
+ inet6_ntoa ( ip6hdr->src ), inet6_ntoa ( ip6hdr->dest ),
+ ip6hdr->nxt_hdr, ntohs ( ip6hdr->payload_len ) );
+}
+
+/**
+ * Transmit IP6 packet
+ *
+ * iobuf I/O buffer
+ * tcpip TCP/IP protocol
+ * st_dest Destination socket address
+ *
+ * This function prepends the IPv6 headers to the payload an transmits it.
+ */
+static int ipv6_tx ( struct io_buffer *iobuf,
+ struct tcpip_protocol *tcpip,
+ struct sockaddr_tcpip *st_src __unused,
+ struct sockaddr_tcpip *st_dest,
+ struct net_device *netdev,
+ uint16_t *trans_csum ) {
+ struct sockaddr_in6 *dest = ( struct sockaddr_in6* ) st_dest;
+ struct in6_addr next_hop;
+ struct ipv6_miniroute *miniroute;
+ uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
+ const uint8_t *ll_dest = ll_dest_buf;
+ int rc;
+
+ /* Construct the IPv6 packet */
+ struct ip6_header *ip6hdr = iob_push ( iobuf, sizeof ( *ip6hdr ) );
+ memset ( ip6hdr, 0, sizeof ( *ip6hdr) );
+ ip6hdr->ver_traffic_class_flow_label = htonl ( 0x60000000 );//IP6_VERSION;
+ ip6hdr->payload_len = htons ( iob_len ( iobuf ) - sizeof ( *ip6hdr ) );
+ ip6hdr->nxt_hdr = tcpip->tcpip_proto;
+ ip6hdr->hop_limit = IP6_HOP_LIMIT; // 255
+
+ /* Determine the next hop address and interface
+ *
+ * TODO: Implement the routing table.
+ */
+ next_hop = dest->sin6_addr;
+ list_for_each_entry ( miniroute, &miniroutes, list ) {
+ if ( ( memcmp ( &ip6hdr->dest, &miniroute->prefix,
+ miniroute->prefix_len ) == 0 ) ||
+ ( IP6_EQUAL ( miniroute->gateway, ip6_none ) ) ) {
+ netdev = miniroute->netdev;
+ ip6hdr->src = miniroute->address;
+ if ( ! ( IS_UNSPECIFIED ( miniroute->gateway ) ) ) {
+ next_hop = miniroute->gateway;
+ }
+ break;
+ }
+ }
+ /* No network interface identified */
+ if ( !netdev ) {
+ DBG ( "No route to host %s\n", inet6_ntoa ( ip6hdr->dest ) );
+ rc = -ENETUNREACH;
+ goto err;
+ }
+
+ /* Complete the transport layer checksum */
+ if ( trans_csum )
+ *trans_csum = ipv6_tx_csum ( iobuf, *trans_csum );
+
+ /* Print IPv6 header */
+ ipv6_dump ( ip6hdr );
+
+ /* Resolve link layer address */
+ if ( next_hop.in6_u.u6_addr8[0] == 0xff ) {
+ ll_dest_buf[0] = 0x33;
+ ll_dest_buf[1] = 0x33;
+ ll_dest_buf[2] = next_hop.in6_u.u6_addr8[12];
+ ll_dest_buf[3] = next_hop.in6_u.u6_addr8[13];
+ ll_dest_buf[4] = next_hop.in6_u.u6_addr8[14];
+ ll_dest_buf[5] = next_hop.in6_u.u6_addr8[15];
+ } else {
+ /* Unicast address needs to be resolved by NDP */
+ if ( ( rc = ndp_resolve ( netdev, &next_hop, &ip6hdr->src,
+ ll_dest_buf ) ) != 0 ) {
+ DBG ( "No entry for %s\n", inet6_ntoa ( next_hop ) );
+ goto err;
+ }
+ }
+
+ /* Transmit packet */
+ return net_tx ( iobuf, netdev, &ipv6_protocol, ll_dest,
+ netdev->ll_addr );
+
+ err:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Process next IP6 header
+ *
+ * @v iobuf I/O buffer
+ * @v nxt_hdr Next header number
+ * @v src Source socket address
+ * @v dest Destination socket address
+ *
+ * Refer http://www.iana.org/assignments/ipv6-parameters for the numbers
+ */
+static int ipv6_process_nxt_hdr ( struct io_buffer *iobuf, uint8_t nxt_hdr,
+ struct sockaddr_tcpip *src, struct sockaddr_tcpip *dest ) {
+ switch ( nxt_hdr ) {
+ case IP6_HOPBYHOP:
+ case IP6_ROUTING:
+ case IP6_FRAGMENT:
+ case IP6_AUTHENTICATION:
+ case IP6_DEST_OPTS:
+ case IP6_ESP:
+ DBG ( "Function not implemented for header %d\n", nxt_hdr );
+ return -ENOSYS;
+ case IP6_ICMP6:
+ break;
+ case IP6_NO_HEADER:
+ DBG ( "No next header\n" );
+ return 0;
+ }
+ /* Next header is not a IPv6 extension header */
+ return tcpip_rx ( iobuf, nxt_hdr, src, dest, 0 /* fixme */ );
+}
+
+/**
+ * Process incoming IP6 packets
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer source address
+ * @v flags Packet flags
+ *
+ * This function processes a IPv6 packet
+ */
+static int ipv6_rx ( struct io_buffer *iobuf,
+ __unused struct net_device *netdev,
+ __unused const void *ll_dest,
+ __unused const void *ll_source,
+ __unused unsigned int flags ) {
+
+ struct ip6_header *ip6hdr = iobuf->data;
+ union {
+ struct sockaddr_in6 sin6;
+ struct sockaddr_tcpip st;
+ } src, dest;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *ip6hdr ) ) {
+ DBG ( "Packet too short (%zd bytes)\n", iob_len ( iobuf ) );
+ goto drop;
+ }
+
+ /* TODO: Verify checksum */
+
+ /* Print IP6 header for debugging */
+ ipv6_dump ( ip6hdr );
+
+ /* Check header version */
+ if ( ( ip6hdr->ver_traffic_class_flow_label & 0xf0000000 ) != 0x60000000 ) {
+ DBG ( "Invalid protocol version\n" );
+ goto drop;
+ }
+
+ /* Check the payload length */
+ if ( ntohs ( ip6hdr->payload_len ) > iob_len ( iobuf ) ) {
+ DBG ( "Inconsistent packet length (%d bytes)\n",
+ ip6hdr->payload_len );
+ goto drop;
+ }
+
+ /* Ignore the traffic class and flow control values */
+
+ /* Construct socket address */
+ memset ( &src, 0, sizeof ( src ) );
+ src.sin6.sin_family = AF_INET6;
+ src.sin6.sin6_addr = ip6hdr->src;
+ memset ( &dest, 0, sizeof ( dest ) );
+ dest.sin6.sin_family = AF_INET6;
+ dest.sin6.sin6_addr = ip6hdr->dest;
+
+ /* Strip header */
+ iob_unput ( iobuf, iob_len ( iobuf ) - ntohs ( ip6hdr->payload_len ) -
+ sizeof ( *ip6hdr ) );
+ iob_pull ( iobuf, sizeof ( *ip6hdr ) );
+
+ /* Send it to the transport layer */
+ return ipv6_process_nxt_hdr ( iobuf, ip6hdr->nxt_hdr, &src.st, &dest.st );
+
+ drop:
+ DBG ( "Packet dropped\n" );
+ free_iob ( iobuf );
+ return -1;
+}
+
+/**
+ * Print a IP6 address as xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
+ */
+char * inet6_ntoa ( struct in6_addr in6 ) {
+ static char buf[40];
+ uint16_t *bytes = ( uint16_t* ) &in6;
+ sprintf ( buf, "%x:%x:%x:%x:%x:%x:%x:%x", bytes[0], bytes[1], bytes[2],
+ bytes[3], bytes[4], bytes[5], bytes[6], bytes[7] );
+ return buf;
+}
+
+static const char * ipv6_ntoa ( const void *net_addr ) {
+ return inet6_ntoa ( * ( ( struct in6_addr * ) net_addr ) );
+}
+
+/** IPv6 protocol */
+struct net_protocol ipv6_protocol __net_protocol = {
+ .name = "IPv6",
+ .net_proto = htons ( ETH_P_IPV6 ),
+ .net_addr_len = sizeof ( struct in6_addr ),
+ .rx = ipv6_rx,
+ .ntoa = ipv6_ntoa,
+};
+
+/** IPv6 TCPIP net protocol */
+struct tcpip_net_protocol ipv6_tcpip_protocol __tcpip_net_protocol = {
+ .name = "IPv6",
+ .sa_family = AF_INET6,
+ .tx = ipv6_tx,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/ndp.c b/src/VBox/Devices/PC/ipxe/src/net/ndp.c
new file mode 100644
index 00000000..4d371335
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/ndp.c
@@ -0,0 +1,180 @@
+#include <stdint.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/ndp.h>
+#include <ipxe/icmp6.h>
+#include <ipxe/ip6.h>
+#include <ipxe/netdevice.h>
+
+/** @file
+ *
+ * Neighbour Discovery Protocol
+ *
+ * This file implements address resolution as specified by the neighbour
+ * discovery protocol in RFC2461. This protocol is part of the IPv6 protocol
+ * family.
+ */
+
+/* A neighbour entry */
+struct ndp_entry {
+ /** Target IP6 address */
+ struct in6_addr in6;
+ /** Link layer protocol */
+ struct ll_protocol *ll_protocol;
+ /** Link-layer address */
+ uint8_t ll_addr[MAX_LL_ADDR_LEN];
+ /** State of the neighbour entry */
+ int state;
+};
+
+/** Number of entries in the neighbour cache table */
+#define NUM_NDP_ENTRIES 4
+
+/** The neighbour cache table */
+static struct ndp_entry ndp_table[NUM_NDP_ENTRIES];
+#define ndp_table_end &ndp_table[NUM_NDP_ENTRIES]
+
+static unsigned int next_new_ndp_entry = 0;
+
+/**
+ * Find entry in the neighbour cache
+ *
+ * @v in6 IP6 address
+ */
+static struct ndp_entry *
+ndp_find_entry ( struct in6_addr *in6 ) {
+ struct ndp_entry *ndp;
+
+ for ( ndp = ndp_table ; ndp < ndp_table_end ; ndp++ ) {
+ if ( IP6_EQUAL ( ( *in6 ), ndp->in6 ) &&
+ ( ndp->state != NDP_STATE_INVALID ) ) {
+ return ndp;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Add NDP entry
+ *
+ * @v netdev Network device
+ * @v in6 IP6 address
+ * @v ll_addr Link-layer address
+ * @v state State of the entry - one of the NDP_STATE_XXX values
+ */
+static void
+add_ndp_entry ( struct net_device *netdev, struct in6_addr *in6,
+ void *ll_addr, int state ) {
+ struct ndp_entry *ndp;
+ ndp = &ndp_table[next_new_ndp_entry++ % NUM_NDP_ENTRIES];
+
+ /* Fill up entry */
+ ndp->ll_protocol = netdev->ll_protocol;
+ memcpy ( &ndp->in6, &( *in6 ), sizeof ( *in6 ) );
+ if ( ll_addr ) {
+ memcpy ( ndp->ll_addr, ll_addr, netdev->ll_protocol->ll_addr_len );
+ } else {
+ memset ( ndp->ll_addr, 0, netdev->ll_protocol->ll_addr_len );
+ }
+ ndp->state = state;
+ DBG ( "New neighbour cache entry: IP6 %s => %s %s\n",
+ inet6_ntoa ( ndp->in6 ), netdev->ll_protocol->name,
+ netdev->ll_protocol->ntoa ( ndp->ll_addr ) );
+}
+
+/**
+ * Resolve the link-layer address
+ *
+ * @v netdev Network device
+ * @v dest Destination address
+ * @v src Source address
+ * @ret dest_ll_addr Destination link-layer address or NULL
+ * @ret rc Status
+ *
+ * This function looks up the neighbour cache for an entry corresponding to the
+ * destination address. If it finds a valid entry, it fills up dest_ll_addr and
+ * returns 0. Otherwise it sends a neighbour solicitation to the solicited
+ * multicast address.
+ */
+int ndp_resolve ( struct net_device *netdev, struct in6_addr *dest,
+ struct in6_addr *src, void *dest_ll_addr ) {
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+ struct ndp_entry *ndp;
+ int rc;
+
+ ndp = ndp_find_entry ( dest );
+ /* Check if the entry is valid */
+ if ( ndp && ndp->state == NDP_STATE_REACHABLE ) {
+ DBG ( "Neighbour cache hit: IP6 %s => %s %s\n",
+ inet6_ntoa ( *dest ), ll_protocol->name,
+ ll_protocol->ntoa ( ndp->ll_addr ) );
+ memcpy ( dest_ll_addr, ndp->ll_addr, ll_protocol->ll_addr_len );
+ return 0;
+ }
+
+ /* Check if the entry was already created */
+ if ( ndp ) {
+ DBG ( "Awaiting neighbour advertisement\n" );
+ /* For test */
+// ndp->state = NDP_STATE_REACHABLE;
+// memcpy ( ndp->ll_addr, netdev->ll_addr, 6 );
+// assert ( ndp->ll_protocol->ll_addr_len == 6 );
+// icmp6_test_nadvert ( netdev, dest, ndp->ll_addr );
+// assert ( ndp->state == NDP_STATE_REACHABLE );
+ /* Take it out till here */
+ return -ENOENT;
+ }
+ DBG ( "Neighbour cache miss: IP6 %s\n", inet6_ntoa ( *dest ) );
+
+ /* Add entry in the neighbour cache */
+ add_ndp_entry ( netdev, dest, NULL, NDP_STATE_INCOMPLETE );
+
+ /* Send neighbour solicitation */
+ if ( ( rc = icmp6_send_solicit ( netdev, src, dest ) ) != 0 ) {
+ return rc;
+ }
+ return -ENOENT;
+}
+
+/**
+ * Process neighbour advertisement
+ *
+ * @v iobuf I/O buffer
+ * @v st_src Source address
+ * @v st_dest Destination address
+ */
+int ndp_process_advert ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src __unused,
+ struct sockaddr_tcpip *st_dest __unused ) {
+ struct neighbour_advert *nadvert = iobuf->data;
+ struct ndp_entry *ndp;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *nadvert ) ) {
+ DBG ( "Packet too short (%zd bytes)\n", iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+
+ assert ( nadvert->code == 0 );
+ assert ( nadvert->flags & ICMP6_FLAGS_SOLICITED );
+ assert ( nadvert->opt_type == 2 );
+
+ /* Update the neighbour cache, if entry is present */
+ ndp = ndp_find_entry ( &nadvert->target );
+ if ( ndp ) {
+
+ assert ( nadvert->opt_len ==
+ ( ( 2 + ndp->ll_protocol->ll_addr_len ) / 8 ) );
+
+ if ( IP6_EQUAL ( ndp->in6, nadvert->target ) ) {
+ memcpy ( ndp->ll_addr, nadvert->opt_ll_addr,
+ ndp->ll_protocol->ll_addr_len );
+ ndp->state = NDP_STATE_REACHABLE;
+ return 0;
+ }
+ }
+ DBG ( "Unsolicited advertisement (dropping packet)\n" );
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/netdev_settings.c b/src/VBox/Devices/PC/ipxe/src/net/netdev_settings.c
new file mode 100644
index 00000000..2ef3984d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/netdev_settings.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/dhcpopts.h>
+#include <ipxe/settings.h>
+#include <ipxe/device.h>
+#include <ipxe/netdevice.h>
+
+/** @file
+ *
+ * Network device configuration settings
+ *
+ */
+
+/** Network device named settings */
+struct setting mac_setting __setting ( SETTING_NETDEV ) = {
+ .name = "mac",
+ .description = "MAC address",
+ .type = &setting_type_hex,
+ .tag = NETDEV_SETTING_TAG_MAC,
+};
+struct setting busid_setting __setting ( SETTING_NETDEV ) = {
+ .name = "busid",
+ .description = "Bus ID",
+ .type = &setting_type_hex,
+ .tag = NETDEV_SETTING_TAG_BUS_ID,
+};
+
+/**
+ * Check applicability of network device setting
+ *
+ * @v settings Settings block
+ * @v setting Setting
+ * @ret applies Setting applies within this settings block
+ */
+static int netdev_applies ( struct settings *settings __unused,
+ struct setting *setting ) {
+
+ return ( IS_NETDEV_SETTING_TAG ( setting->tag ) ||
+ dhcpopt_applies ( setting->tag ) );
+}
+
+/**
+ * Store value of network device setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+static int netdev_store ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len ) {
+ struct net_device *netdev = container_of ( settings, struct net_device,
+ settings.settings );
+
+ if ( setting_cmp ( setting, &mac_setting ) == 0 ) {
+ if ( len != netdev->ll_protocol->ll_addr_len )
+ return -EINVAL;
+ memcpy ( netdev->ll_addr, data, len );
+ return 0;
+ }
+ if ( setting_cmp ( setting, &busid_setting ) == 0 )
+ return -ENOTSUP;
+
+ return generic_settings_store ( settings, setting, data, len );
+}
+
+/**
+ * Fetch value of network device setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+static int netdev_fetch ( struct settings *settings, struct setting *setting,
+ void *data, size_t len ) {
+ struct net_device *netdev = container_of ( settings, struct net_device,
+ settings.settings );
+ struct device_description *desc = &netdev->dev->desc;
+ struct dhcp_netdev_desc dhcp_desc;
+
+ if ( setting_cmp ( setting, &mac_setting ) == 0 ) {
+ if ( len > netdev->ll_protocol->ll_addr_len )
+ len = netdev->ll_protocol->ll_addr_len;
+ memcpy ( data, netdev->ll_addr, len );
+ return netdev->ll_protocol->ll_addr_len;
+ }
+ if ( setting_cmp ( setting, &busid_setting ) == 0 ) {
+ dhcp_desc.type = desc->bus_type;
+ dhcp_desc.vendor = htons ( desc->vendor );
+ dhcp_desc.device = htons ( desc->device );
+ if ( len > sizeof ( dhcp_desc ) )
+ len = sizeof ( dhcp_desc );
+ memcpy ( data, &dhcp_desc, len );
+ return sizeof ( dhcp_desc );
+ }
+
+ return generic_settings_fetch ( settings, setting, data, len );
+}
+
+/**
+ * Clear network device settings
+ *
+ * @v settings Settings block
+ */
+static void netdev_clear ( struct settings *settings ) {
+ generic_settings_clear ( settings );
+}
+
+/** Network device configuration settings operations */
+struct settings_operations netdev_settings_operations = {
+ .applies = netdev_applies,
+ .store = netdev_store,
+ .fetch = netdev_fetch,
+ .clear = netdev_clear,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/netdevice.c b/src/VBox/Devices/PC/ipxe/src/net/netdevice.c
new file mode 100644
index 00000000..b9b1337a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/netdevice.c
@@ -0,0 +1,796 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <byteswap.h>
+#include <string.h>
+#include <errno.h>
+#include <config/general.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/tables.h>
+#include <ipxe/process.h>
+#include <ipxe/init.h>
+#include <ipxe/device.h>
+#include <ipxe/errortab.h>
+#include <ipxe/netdevice.h>
+
+/** @file
+ *
+ * Network device management
+ *
+ */
+
+/** List of network devices */
+struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
+
+/** List of open network devices, in reverse order of opening */
+static struct list_head open_net_devices = LIST_HEAD_INIT ( open_net_devices );
+
+/** Default unknown link status code */
+#define EUNKNOWN_LINK_STATUS __einfo_error ( EINFO_EUNKNOWN_LINK_STATUS )
+#define EINFO_EUNKNOWN_LINK_STATUS \
+ __einfo_uniqify ( EINFO_EINPROGRESS, 0x01, "Unknown" )
+
+/** Default link-down status code */
+#define ENOTCONN_LINK_DOWN __einfo_error ( EINFO_ENOTCONN_LINK_DOWN )
+#define EINFO_ENOTCONN_LINK_DOWN \
+ __einfo_uniqify ( EINFO_ENOTCONN, 0x01, "Down" )
+
+/** Human-readable message for the default link statuses */
+struct errortab netdev_errors[] __errortab = {
+ __einfo_errortab ( EINFO_EUNKNOWN_LINK_STATUS ),
+ __einfo_errortab ( EINFO_ENOTCONN_LINK_DOWN ),
+};
+
+/**
+ * Check whether or not network device has a link-layer address
+ *
+ * @v netdev Network device
+ * @ret has_ll_addr Network device has a link-layer address
+ */
+static int netdev_has_ll_addr ( struct net_device *netdev ) {
+ uint8_t *ll_addr = netdev->ll_addr;
+ size_t remaining = sizeof ( netdev->ll_addr );
+
+ while ( remaining-- ) {
+ if ( *(ll_addr++) != 0 )
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Notify drivers of network device or link state change
+ *
+ * @v netdev Network device
+ */
+static void netdev_notify ( struct net_device *netdev ) {
+ struct net_driver *driver;
+
+ for_each_table_entry ( driver, NET_DRIVERS )
+ driver->notify ( netdev );
+}
+
+/**
+ * Mark network device as having a specific link state
+ *
+ * @v netdev Network device
+ * @v rc Link status code
+ */
+void netdev_link_err ( struct net_device *netdev, int rc ) {
+
+ /* Record link state */
+ netdev->link_rc = rc;
+ if ( netdev->link_rc == 0 ) {
+ DBGC ( netdev, "NETDEV %s link is up\n", netdev->name );
+ } else {
+ DBGC ( netdev, "NETDEV %s link is down: %s\n",
+ netdev->name, strerror ( netdev->link_rc ) );
+ }
+
+ /* Notify drivers of link state change */
+ netdev_notify ( netdev );
+}
+
+/**
+ * Mark network device as having link down
+ *
+ * @v netdev Network device
+ */
+void netdev_link_down ( struct net_device *netdev ) {
+
+ /* Avoid clobbering a more detailed link status code, if one
+ * is already set.
+ */
+ if ( ( netdev->link_rc == 0 ) ||
+ ( netdev->link_rc == -EUNKNOWN_LINK_STATUS ) ) {
+ netdev_link_err ( netdev, -ENOTCONN_LINK_DOWN );
+ }
+}
+
+/**
+ * Record network device statistic
+ *
+ * @v stats Network device statistics
+ * @v rc Status code
+ */
+static void netdev_record_stat ( struct net_device_stats *stats, int rc ) {
+ struct net_device_error *error;
+ struct net_device_error *least_common_error;
+ unsigned int i;
+
+ /* If this is not an error, just update the good counter */
+ if ( rc == 0 ) {
+ stats->good++;
+ return;
+ }
+
+ /* Update the bad counter */
+ stats->bad++;
+
+ /* Locate the appropriate error record */
+ least_common_error = &stats->errors[0];
+ for ( i = 0 ; i < ( sizeof ( stats->errors ) /
+ sizeof ( stats->errors[0] ) ) ; i++ ) {
+ error = &stats->errors[i];
+ /* Update matching record, if found */
+ if ( error->rc == rc ) {
+ error->count++;
+ return;
+ }
+ if ( error->count < least_common_error->count )
+ least_common_error = error;
+ }
+
+ /* Overwrite the least common error record */
+ least_common_error->rc = rc;
+ least_common_error->count = 1;
+}
+
+/**
+ * Transmit raw packet via network device
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * Transmits the packet via the specified network device. This
+ * function takes ownership of the I/O buffer.
+ */
+int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
+ int rc;
+
+ DBGC2 ( netdev, "NETDEV %s transmitting %p (%p+%zx)\n",
+ netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) );
+
+ /* Enqueue packet */
+ list_add_tail ( &iobuf->list, &netdev->tx_queue );
+
+ /* Avoid calling transmit() on unopened network devices */
+ if ( ! netdev_is_open ( netdev ) ) {
+ rc = -ENETUNREACH;
+ goto err;
+ }
+
+ /* Discard packet (for test purposes) if applicable */
+ if ( ( NETDEV_DISCARD_RATE > 0 ) &&
+ ( ( random() % NETDEV_DISCARD_RATE ) == 0 ) ) {
+ rc = -EAGAIN;
+ goto err;
+ }
+
+ /* Transmit packet */
+ if ( ( rc = netdev->op->transmit ( netdev, iobuf ) ) != 0 )
+ goto err;
+
+ return 0;
+
+ err:
+ netdev_tx_complete_err ( netdev, iobuf, rc );
+ return rc;
+}
+
+/**
+ * Discard transmitted packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer, or NULL
+ * @v rc Packet status code
+ *
+ * The packet is discarded and a TX error is recorded. This function
+ * takes ownership of the I/O buffer.
+ */
+void netdev_tx_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc ) {
+
+ /* Update statistics counter */
+ netdev_record_stat ( &netdev->tx_stats, rc );
+ if ( rc == 0 ) {
+ DBGC2 ( netdev, "NETDEV %s transmission %p complete\n",
+ netdev->name, iobuf );
+ } else {
+ DBGC ( netdev, "NETDEV %s transmission %p failed: %s\n",
+ netdev->name, iobuf, strerror ( rc ) );
+ }
+
+ /* Discard packet */
+ free_iob ( iobuf );
+}
+
+/**
+ * Complete network transmission
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @v rc Packet status code
+ *
+ * The packet must currently be in the network device's TX queue.
+ */
+void netdev_tx_complete_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc ) {
+
+ /* Catch data corruption as early as possible */
+ list_check_contains_entry ( iobuf, &netdev->tx_queue, list );
+
+ /* Dequeue and free I/O buffer */
+ list_del ( &iobuf->list );
+ netdev_tx_err ( netdev, iobuf, rc );
+}
+
+/**
+ * Complete network transmission
+ *
+ * @v netdev Network device
+ * @v rc Packet status code
+ *
+ * Completes the oldest outstanding packet in the TX queue.
+ */
+void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) {
+ struct io_buffer *iobuf;
+
+ list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
+ netdev_tx_complete_err ( netdev, iobuf, rc );
+ return;
+ }
+}
+
+/**
+ * Flush device's transmit queue
+ *
+ * @v netdev Network device
+ */
+static void netdev_tx_flush ( struct net_device *netdev ) {
+
+ /* Discard any packets in the TX queue */
+ while ( ! list_empty ( &netdev->tx_queue ) ) {
+ netdev_tx_complete_next_err ( netdev, -ECANCELED );
+ }
+}
+
+/**
+ * Add packet to receive queue
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer, or NULL
+ *
+ * The packet is added to the network device's RX queue. This
+ * function takes ownership of the I/O buffer.
+ */
+void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
+
+ DBGC2 ( netdev, "NETDEV %s received %p (%p+%zx)\n",
+ netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) );
+
+ /* Discard packet (for test purposes) if applicable */
+ if ( ( NETDEV_DISCARD_RATE > 0 ) &&
+ ( ( random() % NETDEV_DISCARD_RATE ) == 0 ) ) {
+ netdev_rx_err ( netdev, iobuf, -EAGAIN );
+ return;
+ }
+
+ /* Enqueue packet */
+ list_add_tail ( &iobuf->list, &netdev->rx_queue );
+
+ /* Update statistics counter */
+ netdev_record_stat ( &netdev->rx_stats, 0 );
+}
+
+/**
+ * Discard received packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer, or NULL
+ * @v rc Packet status code
+ *
+ * The packet is discarded and an RX error is recorded. This function
+ * takes ownership of the I/O buffer. @c iobuf may be NULL if, for
+ * example, the net device wishes to report an error due to being
+ * unable to allocate an I/O buffer.
+ */
+void netdev_rx_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc ) {
+
+ DBGC ( netdev, "NETDEV %s failed to receive %p: %s\n",
+ netdev->name, iobuf, strerror ( rc ) );
+
+ /* Discard packet */
+ free_iob ( iobuf );
+
+ /* Update statistics counter */
+ netdev_record_stat ( &netdev->rx_stats, rc );
+}
+
+/**
+ * Poll for completed and received packets on network device
+ *
+ * @v netdev Network device
+ *
+ * Polls the network device for completed transmissions and received
+ * packets. Any received packets will be added to the RX packet queue
+ * via netdev_rx().
+ */
+void netdev_poll ( struct net_device *netdev ) {
+
+ if ( netdev_is_open ( netdev ) )
+ netdev->op->poll ( netdev );
+}
+
+/**
+ * Remove packet from device's receive queue
+ *
+ * @v netdev Network device
+ * @ret iobuf I/O buffer, or NULL
+ *
+ * Removes the first packet from the device's RX queue and returns it.
+ * Ownership of the packet is transferred to the caller.
+ */
+struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
+ struct io_buffer *iobuf;
+
+ iobuf = list_first_entry ( &netdev->rx_queue, struct io_buffer, list );
+ if ( ! iobuf )
+ return NULL;
+
+ list_del ( &iobuf->list );
+ return iobuf;
+}
+
+/**
+ * Flush device's receive queue
+ *
+ * @v netdev Network device
+ */
+static void netdev_rx_flush ( struct net_device *netdev ) {
+ struct io_buffer *iobuf;
+
+ /* Discard any packets in the RX queue */
+ while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
+ netdev_rx_err ( netdev, iobuf, -ECANCELED );
+ }
+}
+
+/**
+ * Free network device
+ *
+ * @v refcnt Network device reference counter
+ */
+static void free_netdev ( struct refcnt *refcnt ) {
+ struct net_device *netdev =
+ container_of ( refcnt, struct net_device, refcnt );
+
+ netdev_tx_flush ( netdev );
+ netdev_rx_flush ( netdev );
+ clear_settings ( netdev_settings ( netdev ) );
+ free ( netdev );
+}
+
+/**
+ * Allocate network device
+ *
+ * @v priv_size Size of private data area (net_device::priv)
+ * @ret netdev Network device, or NULL
+ *
+ * Allocates space for a network device and its private data area.
+ */
+struct net_device * alloc_netdev ( size_t priv_size ) {
+ struct net_device *netdev;
+ size_t total_len;
+
+ total_len = ( sizeof ( *netdev ) + priv_size );
+ netdev = zalloc ( total_len );
+ if ( netdev ) {
+ ref_init ( &netdev->refcnt, free_netdev );
+ netdev->link_rc = -EUNKNOWN_LINK_STATUS;
+ INIT_LIST_HEAD ( &netdev->tx_queue );
+ INIT_LIST_HEAD ( &netdev->rx_queue );
+ netdev_settings_init ( netdev );
+ netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
+ }
+ return netdev;
+}
+
+/**
+ * Register network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ *
+ * Gives the network device a name and adds it to the list of network
+ * devices.
+ */
+int register_netdev ( struct net_device *netdev ) {
+ static unsigned int ifindex = 0;
+ struct net_driver *driver;
+ int rc;
+
+ /* Create device name */
+ if ( netdev->name[0] == '\0' ) {
+ snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
+ ifindex++ );
+ }
+
+ /* Set initial link-layer address, if not already set */
+ if ( ! netdev_has_ll_addr ( netdev ) ) {
+ netdev->ll_protocol->init_addr ( netdev->hw_addr,
+ netdev->ll_addr );
+ }
+
+ /* Add to device list */
+ netdev_get ( netdev );
+ list_add_tail ( &netdev->list, &net_devices );
+ DBGC ( netdev, "NETDEV %s registered (phys %s hwaddr %s)\n",
+ netdev->name, netdev->dev->name,
+ netdev_addr ( netdev ) );
+
+ /* Register per-netdev configuration settings */
+ if ( ( rc = register_settings ( netdev_settings ( netdev ),
+ NULL, netdev->name ) ) != 0 ) {
+ DBGC ( netdev, "NETDEV %s could not register settings: %s\n",
+ netdev->name, strerror ( rc ) );
+ goto err_register_settings;
+ }
+
+ /* Probe device */
+ for_each_table_entry ( driver, NET_DRIVERS ) {
+ if ( ( rc = driver->probe ( netdev ) ) != 0 ) {
+ DBGC ( netdev, "NETDEV %s could not add %s device: "
+ "%s\n", netdev->name, driver->name,
+ strerror ( rc ) );
+ goto err_probe;
+ }
+ }
+
+ return 0;
+
+ err_probe:
+ for_each_table_entry_continue_reverse ( driver, NET_DRIVERS )
+ driver->remove ( netdev );
+ unregister_settings ( netdev_settings ( netdev ) );
+ err_register_settings:
+ return rc;
+}
+
+/**
+ * Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+int netdev_open ( struct net_device *netdev ) {
+ int rc;
+
+ /* Do nothing if device is already open */
+ if ( netdev->state & NETDEV_OPEN )
+ return 0;
+
+ DBGC ( netdev, "NETDEV %s opening\n", netdev->name );
+
+ /* Open the device */
+ if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
+ return rc;
+
+ /* Mark as opened */
+ netdev->state |= NETDEV_OPEN;
+
+ /* Add to head of open devices list */
+ list_add ( &netdev->open_list, &open_net_devices );
+
+ /* Notify drivers of device state change */
+ netdev_notify ( netdev );
+
+ return 0;
+}
+
+/**
+ * Close network device
+ *
+ * @v netdev Network device
+ */
+void netdev_close ( struct net_device *netdev ) {
+
+ /* Do nothing if device is already closed */
+ if ( ! ( netdev->state & NETDEV_OPEN ) )
+ return;
+
+ DBGC ( netdev, "NETDEV %s closing\n", netdev->name );
+
+ /* Remove from open devices list */
+ list_del ( &netdev->open_list );
+
+ /* Mark as closed */
+ netdev->state &= ~NETDEV_OPEN;
+
+ /* Notify drivers of device state change */
+ netdev_notify ( netdev );
+
+ /* Close the device */
+ netdev->op->close ( netdev );
+
+ /* Flush TX and RX queues */
+ netdev_tx_flush ( netdev );
+ netdev_rx_flush ( netdev );
+}
+
+/**
+ * Unregister network device
+ *
+ * @v netdev Network device
+ *
+ * Removes the network device from the list of network devices.
+ */
+void unregister_netdev ( struct net_device *netdev ) {
+ struct net_driver *driver;
+
+ /* Ensure device is closed */
+ netdev_close ( netdev );
+
+ /* Remove device */
+ for_each_table_entry_reverse ( driver, NET_DRIVERS )
+ driver->remove ( netdev );
+
+ /* Unregister per-netdev configuration settings */
+ unregister_settings ( netdev_settings ( netdev ) );
+
+ /* Remove from device list */
+ list_del ( &netdev->list );
+ netdev_put ( netdev );
+ DBGC ( netdev, "NETDEV %s unregistered\n", netdev->name );
+}
+
+/** Enable or disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+void netdev_irq ( struct net_device *netdev, int enable ) {
+
+ /* Do nothing if device does not support interrupts */
+ if ( ! netdev_irq_supported ( netdev ) )
+ return;
+
+ /* Enable or disable device interrupts */
+ netdev->op->irq ( netdev, enable );
+
+ /* Record interrupt enabled state */
+ netdev->state &= ~NETDEV_IRQ_ENABLED;
+ if ( enable )
+ netdev->state |= NETDEV_IRQ_ENABLED;
+}
+
+/**
+ * Get network device by name
+ *
+ * @v name Network device name
+ * @ret netdev Network device, or NULL
+ */
+struct net_device * find_netdev ( const char *name ) {
+ struct net_device *netdev;
+
+ list_for_each_entry ( netdev, &net_devices, list ) {
+ if ( strcmp ( netdev->name, name ) == 0 )
+ return netdev;
+ }
+
+ return NULL;
+}
+
+/**
+ * Get network device by PCI bus:dev.fn address
+ *
+ * @v bus_type Bus type
+ * @v location Bus location
+ * @ret netdev Network device, or NULL
+ */
+struct net_device * find_netdev_by_location ( unsigned int bus_type,
+ unsigned int location ) {
+ struct net_device *netdev;
+
+ list_for_each_entry ( netdev, &net_devices, list ) {
+ if ( ( netdev->dev->desc.bus_type == bus_type ) &&
+ ( netdev->dev->desc.location == location ) )
+ return netdev;
+ }
+
+ return NULL;
+}
+
+/**
+ * Get most recently opened network device
+ *
+ * @ret netdev Most recently opened network device, or NULL
+ */
+struct net_device * last_opened_netdev ( void ) {
+ struct net_device *netdev;
+
+ netdev = list_first_entry ( &open_net_devices, struct net_device,
+ open_list );
+ if ( ! netdev )
+ return NULL;
+
+ assert ( netdev_is_open ( netdev ) );
+ return netdev;
+}
+
+/**
+ * Transmit network-layer packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v net_protocol Network-layer protocol
+ * @v ll_dest Destination link-layer address
+ * @v ll_source Source link-layer address
+ * @ret rc Return status code
+ *
+ * Prepends link-layer headers to the I/O buffer and transmits the
+ * packet via the specified network device. This function takes
+ * ownership of the I/O buffer.
+ */
+int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
+ struct net_protocol *net_protocol, const void *ll_dest,
+ const void *ll_source ) {
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+ int rc;
+
+ /* Force a poll on the netdevice to (potentially) clear any
+ * backed-up TX completions. This is needed on some network
+ * devices to avoid excessive losses due to small TX ring
+ * sizes.
+ */
+ netdev_poll ( netdev );
+
+ /* Add link-layer header */
+ if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest, ll_source,
+ net_protocol->net_proto ) ) != 0 ) {
+ /* Record error for diagnosis */
+ netdev_tx_err ( netdev, iobuf, rc );
+ return rc;
+ }
+
+ /* Transmit packet */
+ return netdev_tx ( netdev, iobuf );
+}
+
+/**
+ * Process received network-layer packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v net_proto Network-layer protocol, in network-byte order
+ * @v ll_dest Destination link-layer address
+ * @v ll_source Source link-layer address
+ * @v flags Packet flags
+ * @ret rc Return status code
+ */
+int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
+ uint16_t net_proto, const void *ll_dest, const void *ll_source,
+ unsigned int flags ) {
+ struct net_protocol *net_protocol;
+
+ /* Hand off to network-layer protocol, if any */
+ for_each_table_entry ( net_protocol, NET_PROTOCOLS ) {
+ if ( net_protocol->net_proto == net_proto )
+ return net_protocol->rx ( iobuf, netdev, ll_dest,
+ ll_source, flags );
+ }
+
+ DBGC ( netdev, "NETDEV %s unknown network protocol %04x\n",
+ netdev->name, ntohs ( net_proto ) );
+ free_iob ( iobuf );
+ return -ENOTSUP;
+}
+
+/**
+ * Poll the network stack
+ *
+ * This polls all interfaces for received packets, and processes
+ * packets from the RX queue.
+ */
+void net_poll ( void ) {
+ struct net_device *netdev;
+ struct io_buffer *iobuf;
+ struct ll_protocol *ll_protocol;
+ const void *ll_dest;
+ const void *ll_source;
+ uint16_t net_proto;
+ unsigned int flags;
+ int rc;
+
+ /* Poll and process each network device */
+ list_for_each_entry ( netdev, &net_devices, list ) {
+
+ /* Poll for new packets */
+ netdev_poll ( netdev );
+
+ /* Leave received packets on the queue if receive
+ * queue processing is currently frozen. This will
+ * happen when the raw packets are to be manually
+ * dequeued using netdev_rx_dequeue(), rather than
+ * processed via the usual networking stack.
+ */
+ if ( netdev_rx_frozen ( netdev ) )
+ continue;
+
+ /* Process at most one received packet. Give priority
+ * to getting packets out of the NIC over processing
+ * the received packets, because we advertise a window
+ * that assumes that we can receive packets from the
+ * NIC faster than they arrive.
+ */
+ if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
+
+ DBGC2 ( netdev, "NETDEV %s processing %p (%p+%zx)\n",
+ netdev->name, iobuf, iobuf->data,
+ iob_len ( iobuf ) );
+
+ /* Remove link-layer header */
+ ll_protocol = netdev->ll_protocol;
+ if ( ( rc = ll_protocol->pull ( netdev, iobuf,
+ &ll_dest, &ll_source,
+ &net_proto,
+ &flags ) ) != 0 ) {
+ free_iob ( iobuf );
+ continue;
+ }
+
+ /* Hand packet to network layer */
+ if ( ( rc = net_rx ( iob_disown ( iobuf ), netdev,
+ net_proto, ll_dest,
+ ll_source, flags ) ) != 0 ) {
+ /* Record error for diagnosis */
+ netdev_rx_err ( netdev, NULL, rc );
+ }
+ }
+ }
+}
+
+/**
+ * Single-step the network stack
+ *
+ * @v process Network stack process
+ */
+static void net_step ( struct process *process __unused ) {
+ net_poll();
+}
+
+/** Networking stack process */
+PERMANENT_PROCESS ( net_process, net_step );
diff --git a/src/VBox/Devices/PC/ipxe/src/net/nullnet.c b/src/VBox/Devices/PC/ipxe/src/net/nullnet.c
new file mode 100644
index 00000000..48849dfd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/nullnet.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <errno.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+
+/** @file
+ *
+ * Null network device
+ *
+ */
+
+static int null_open ( struct net_device *netdev __unused ) {
+ return -ENODEV;
+};
+
+static void null_close ( struct net_device *netdev __unused ) {
+ /* Do nothing */
+};
+
+static int null_transmit ( struct net_device *netdev __unused,
+ struct io_buffer *iobuf __unused ) {
+ return -ENODEV;
+};
+
+static void null_poll ( struct net_device *netdev __unused ) {
+ /* Do nothing */
+}
+
+static void null_irq ( struct net_device *netdev __unused,
+ int enable __unused ) {
+ /* Do nothing */
+}
+
+struct net_device_operations null_netdev_operations = {
+ .open = null_open,
+ .close = null_close,
+ .transmit = null_transmit,
+ .poll = null_poll,
+ .irq = null_irq,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/rarp.c b/src/VBox/Devices/PC/ipxe/src/net/rarp.c
new file mode 100644
index 00000000..59cb1d07
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/rarp.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <byteswap.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/rarp.h>
+
+/** @file
+ *
+ * Reverse Address Resolution Protocol
+ *
+ */
+
+/**
+ * Process incoming ARP packets
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer source address
+ * @v flags Packet flags
+ * @ret rc Return status code
+ *
+ * This is a dummy method which simply discards RARP packets.
+ */
+static int rarp_rx ( struct io_buffer *iobuf,
+ struct net_device *netdev __unused,
+ const void *ll_dest __unused,
+ const void *ll_source __unused,
+ unsigned int flags __unused ) {
+ free_iob ( iobuf );
+ return 0;
+}
+
+
+/**
+ * Transcribe RARP address
+ *
+ * @v net_addr RARP address
+ * @ret string "<RARP>"
+ *
+ * This operation is meaningless for the RARP protocol.
+ */
+static const char * rarp_ntoa ( const void *net_addr __unused ) {
+ return "<RARP>";
+}
+
+/** RARP protocol */
+struct net_protocol rarp_protocol __net_protocol = {
+ .name = "RARP",
+ .net_proto = htons ( ETH_P_RARP ),
+ .rx = rarp_rx,
+ .ntoa = rarp_ntoa,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/retry.c b/src/VBox/Devices/PC/ipxe/src/net/retry.c
new file mode 100644
index 00000000..7e20f0c8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/retry.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <ipxe/timer.h>
+#include <ipxe/list.h>
+#include <ipxe/process.h>
+#include <ipxe/init.h>
+#include <ipxe/retry.h>
+
+/** @file
+ *
+ * Retry timers
+ *
+ * A retry timer is a binary exponential backoff timer. It can be
+ * used to build automatic retransmission into network protocols.
+ *
+ * This implementation of the timer is designed to satisfy RFC 2988
+ * and therefore be usable as a TCP retransmission timer.
+ *
+ *
+ */
+
+/* The theoretical minimum that the algorithm in stop_timer() can
+ * adjust the timeout back down to is seven ticks, so set the minimum
+ * timeout to at least that value for the sake of consistency.
+ */
+#define MIN_TIMEOUT 7
+
+/** List of running timers */
+static LIST_HEAD ( timers );
+
+/**
+ * Start timer
+ *
+ * @v timer Retry timer
+ *
+ * This starts the timer running with the current timeout value. If
+ * stop_timer() is not called before the timer expires, the timer will
+ * be stopped and the timer's callback function will be called.
+ */
+void start_timer ( struct retry_timer *timer ) {
+ if ( ! timer->running ) {
+ list_add ( &timer->list, &timers );
+ ref_get ( timer->refcnt );
+ }
+ timer->start = currticks();
+ timer->running = 1;
+
+ /* 0 means "use default timeout" */
+ if ( timer->min_timeout == 0 )
+ timer->min_timeout = DEFAULT_MIN_TIMEOUT;
+ /* We must never be less than MIN_TIMEOUT under any circumstances */
+ if ( timer->min_timeout < MIN_TIMEOUT )
+ timer->min_timeout = MIN_TIMEOUT;
+ /* Honor user-specified minimum timeout */
+ if ( timer->timeout < timer->min_timeout )
+ timer->timeout = timer->min_timeout;
+
+ DBG2 ( "Timer %p started at time %ld (expires at %ld)\n",
+ timer, timer->start, ( timer->start + timer->timeout ) );
+}
+
+/**
+ * Start timer with a specified fixed timeout
+ *
+ * @v timer Retry timer
+ * @v timeout Timeout, in ticks
+ */
+void start_timer_fixed ( struct retry_timer *timer, unsigned long timeout ) {
+ start_timer ( timer );
+ timer->timeout = timeout;
+ DBG2 ( "Timer %p expiry time changed to %ld\n",
+ timer, ( timer->start + timer->timeout ) );
+}
+
+/**
+ * Stop timer
+ *
+ * @v timer Retry timer
+ *
+ * This stops the timer and updates the timer's timeout value.
+ */
+void stop_timer ( struct retry_timer *timer ) {
+ unsigned long old_timeout = timer->timeout;
+ unsigned long now = currticks();
+ unsigned long runtime;
+
+ /* If timer was already stopped, do nothing */
+ if ( ! timer->running )
+ return;
+
+ list_del ( &timer->list );
+ runtime = ( now - timer->start );
+ timer->running = 0;
+ DBG2 ( "Timer %p stopped at time %ld (ran for %ld)\n",
+ timer, now, runtime );
+
+ /* Update timer. Variables are:
+ *
+ * r = round-trip time estimate (i.e. runtime)
+ * t = timeout value (i.e. timer->timeout)
+ * s = smoothed round-trip time
+ *
+ * By choice, we set t = 4s, i.e. allow for four times the
+ * normal round-trip time to pass before retransmitting.
+ *
+ * We want to smooth according to s := ( 7 s + r ) / 8
+ *
+ * Since we don't actually store s, this reduces to
+ * t := ( 7 t / 8 ) + ( r / 2 )
+ *
+ */
+ if ( timer->count ) {
+ timer->count--;
+ } else {
+ timer->timeout -= ( timer->timeout >> 3 );
+ timer->timeout += ( runtime >> 1 );
+ if ( timer->timeout != old_timeout ) {
+ DBG ( "Timer %p timeout updated to %ld\n",
+ timer, timer->timeout );
+ }
+ }
+
+ ref_put ( timer->refcnt );
+}
+
+/**
+ * Handle expired timer
+ *
+ * @v timer Retry timer
+ */
+static void timer_expired ( struct retry_timer *timer ) {
+ struct refcnt *refcnt = timer->refcnt;
+ int fail;
+
+ /* Stop timer without performing RTT calculations */
+ DBG2 ( "Timer %p stopped at time %ld on expiry\n",
+ timer, currticks() );
+ assert ( timer->running );
+ list_del ( &timer->list );
+ timer->running = 0;
+ timer->count++;
+
+ /* Back off the timeout value */
+ timer->timeout <<= 1;
+ if ( timer->max_timeout == 0 ) /* 0 means "use default timeout" */
+ timer->max_timeout = DEFAULT_MAX_TIMEOUT;
+ if ( ( fail = ( timer->timeout > timer->max_timeout ) ) )
+ timer->timeout = timer->max_timeout;
+ DBG ( "Timer %p timeout backed off to %ld\n",
+ timer, timer->timeout );
+
+ /* Call expiry callback */
+ timer->expired ( timer, fail );
+ /* If refcnt is NULL, then timer may already have been freed */
+
+ ref_put ( refcnt );
+}
+
+/**
+ * Single-step the retry timer list
+ *
+ * @v process Retry timer process
+ */
+static void retry_step ( struct process *process __unused ) {
+ struct retry_timer *timer;
+ unsigned long now = currticks();
+ unsigned long used;
+
+ /* Process at most one timer expiry. We cannot process
+ * multiple expiries in one pass, because one timer expiring
+ * may end up triggering another timer's deletion from the
+ * list.
+ */
+ list_for_each_entry ( timer, &timers, list ) {
+ used = ( now - timer->start );
+ if ( used >= timer->timeout ) {
+ timer_expired ( timer );
+ break;
+ }
+ }
+}
+
+/** Retry timer process */
+PERMANENT_PROCESS ( retry_process, retry_step );
diff --git a/src/VBox/Devices/PC/ipxe/src/net/tcp.c b/src/VBox/Devices/PC/ipxe/src/net/tcp.c
new file mode 100644
index 00000000..b1533915
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/tcp.c
@@ -0,0 +1,1383 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/timer.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/init.h>
+#include <ipxe/retry.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/uri.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/tcp.h>
+
+/** @file
+ *
+ * TCP protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** A TCP connection */
+struct tcp_connection {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** List of TCP connections */
+ struct list_head list;
+
+ /** Flags */
+ unsigned int flags;
+
+ /** Data transfer interface */
+ struct interface xfer;
+
+ /** Remote socket address */
+ struct sockaddr_tcpip peer;
+ /** Local port */
+ unsigned int local_port;
+
+ /** Current TCP state */
+ unsigned int tcp_state;
+ /** Previous TCP state
+ *
+ * Maintained only for debug messages
+ */
+ unsigned int prev_tcp_state;
+ /** Current sequence number
+ *
+ * Equivalent to SND.UNA in RFC 793 terminology.
+ */
+ uint32_t snd_seq;
+ /** Unacknowledged sequence count
+ *
+ * Equivalent to (SND.NXT-SND.UNA) in RFC 793 terminology.
+ */
+ uint32_t snd_sent;
+ /** Send window
+ *
+ * Equivalent to SND.WND in RFC 793 terminology
+ */
+ uint32_t snd_win;
+ /** Current acknowledgement number
+ *
+ * Equivalent to RCV.NXT in RFC 793 terminology.
+ */
+ uint32_t rcv_ack;
+ /** Receive window
+ *
+ * Equivalent to RCV.WND in RFC 793 terminology.
+ */
+ uint32_t rcv_win;
+ /** Received timestamp value
+ *
+ * Updated when a packet is received; copied to ts_recent when
+ * the window is advanced.
+ */
+ uint32_t ts_val;
+ /** Most recent received timestamp that advanced the window
+ *
+ * Equivalent to TS.Recent in RFC 1323 terminology.
+ */
+ uint32_t ts_recent;
+
+ /** Transmit queue */
+ struct list_head tx_queue;
+ /** Receive queue */
+ struct list_head rx_queue;
+ /** Retransmission timer */
+ struct retry_timer timer;
+ /** Shutdown (TIME_WAIT) timer */
+ struct retry_timer wait;
+};
+
+/** TCP flags */
+enum tcp_flags {
+ /** TCP data transfer interface has been closed */
+ TCP_XFER_CLOSED = 0x0001,
+ /** TCP timestamps are enabled */
+ TCP_TS_ENABLED = 0x0002,
+ /** TCP acknowledgement is pending */
+ TCP_ACK_PENDING = 0x0004,
+};
+
+/** TCP internal header
+ *
+ * This is the header that replaces the TCP header for packets
+ * enqueued on the receive queue.
+ */
+struct tcp_rx_queued_header {
+ /** SEQ value, in host-endian order
+ *
+ * This represents the SEQ value at the time the packet is
+ * enqueued, and so excludes the SYN, if present.
+ */
+ uint32_t seq;
+ /** Flags
+ *
+ * Only FIN is valid within this flags byte; all other flags
+ * have already been processed by the time the packet is
+ * enqueued.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved[3];
+};
+
+/**
+ * List of registered TCP connections
+ */
+static LIST_HEAD ( tcp_conns );
+
+/* Forward declarations */
+static struct interface_descriptor tcp_xfer_desc;
+static void tcp_expired ( struct retry_timer *timer, int over );
+static void tcp_wait_expired ( struct retry_timer *timer, int over );
+static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack,
+ uint32_t win );
+
+/**
+ * Name TCP state
+ *
+ * @v state TCP state
+ * @ret name Name of TCP state
+ */
+static inline __attribute__ (( always_inline )) const char *
+tcp_state ( int state ) {
+ switch ( state ) {
+ case TCP_CLOSED: return "CLOSED";
+ case TCP_LISTEN: return "LISTEN";
+ case TCP_SYN_SENT: return "SYN_SENT";
+ case TCP_SYN_RCVD: return "SYN_RCVD";
+ case TCP_ESTABLISHED: return "ESTABLISHED";
+ case TCP_FIN_WAIT_1: return "FIN_WAIT_1";
+ case TCP_FIN_WAIT_2: return "FIN_WAIT_2";
+ case TCP_CLOSING_OR_LAST_ACK: return "CLOSING/LAST_ACK";
+ case TCP_TIME_WAIT: return "TIME_WAIT";
+ case TCP_CLOSE_WAIT: return "CLOSE_WAIT";
+ default: return "INVALID";
+ }
+}
+
+/**
+ * Dump TCP state transition
+ *
+ * @v tcp TCP connection
+ */
+static inline __attribute__ (( always_inline )) void
+tcp_dump_state ( struct tcp_connection *tcp ) {
+
+ if ( tcp->tcp_state != tcp->prev_tcp_state ) {
+ DBGC ( tcp, "TCP %p transitioned from %s to %s\n", tcp,
+ tcp_state ( tcp->prev_tcp_state ),
+ tcp_state ( tcp->tcp_state ) );
+ }
+ tcp->prev_tcp_state = tcp->tcp_state;
+}
+
+/**
+ * Dump TCP flags
+ *
+ * @v flags TCP flags
+ */
+static inline __attribute__ (( always_inline )) void
+tcp_dump_flags ( struct tcp_connection *tcp, unsigned int flags ) {
+ if ( flags & TCP_RST )
+ DBGC2 ( tcp, " RST" );
+ if ( flags & TCP_SYN )
+ DBGC2 ( tcp, " SYN" );
+ if ( flags & TCP_PSH )
+ DBGC2 ( tcp, " PSH" );
+ if ( flags & TCP_FIN )
+ DBGC2 ( tcp, " FIN" );
+ if ( flags & TCP_ACK )
+ DBGC2 ( tcp, " ACK" );
+}
+
+/***************************************************************************
+ *
+ * Open and close
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Bind TCP connection to local port
+ *
+ * @v tcp TCP connection
+ * @v port Local port number
+ * @ret rc Return status code
+ *
+ * If the port is 0, the connection is assigned an available port
+ * between 1024 and 65535.
+ */
+static int tcp_bind ( struct tcp_connection *tcp, unsigned int port ) {
+ struct tcp_connection *existing;
+ uint16_t try_port;
+ unsigned int i;
+
+ /* If no port is specified, find an available port */
+ if ( ! port ) {
+ try_port = random();
+ for ( i = 0 ; i < 65536 ; i++ ) {
+ try_port++;
+ if ( try_port < 1024 )
+ continue;
+ if ( tcp_bind ( tcp, try_port ) == 0 )
+ return 0;
+ }
+ DBGC ( tcp, "TCP %p could not bind: no free ports\n", tcp );
+ return -EADDRINUSE;
+ }
+
+ /* Attempt bind to local port */
+ list_for_each_entry ( existing, &tcp_conns, list ) {
+ if ( existing->local_port == port ) {
+ DBGC ( tcp, "TCP %p could not bind: port %d in use\n",
+ tcp, port );
+ return -EADDRINUSE;
+ }
+ }
+ tcp->local_port = port;
+
+ DBGC ( tcp, "TCP %p bound to port %d\n", tcp, port );
+ return 0;
+}
+
+/**
+ * Open a TCP connection
+ *
+ * @v xfer Data transfer interface
+ * @v peer Peer socket address
+ * @v local Local socket address, or NULL
+ * @ret rc Return status code
+ */
+static int tcp_open ( struct interface *xfer, struct sockaddr *peer,
+ struct sockaddr *local ) {
+ struct sockaddr_tcpip *st_peer = ( struct sockaddr_tcpip * ) peer;
+ struct sockaddr_tcpip *st_local = ( struct sockaddr_tcpip * ) local;
+ struct tcp_connection *tcp;
+ unsigned int bind_port;
+ int rc;
+
+ /* Allocate and initialise structure */
+ tcp = zalloc ( sizeof ( *tcp ) );
+ if ( ! tcp )
+ return -ENOMEM;
+ DBGC ( tcp, "TCP %p allocated\n", tcp );
+ ref_init ( &tcp->refcnt, NULL );
+ intf_init ( &tcp->xfer, &tcp_xfer_desc, &tcp->refcnt );
+ timer_init ( &tcp->timer, tcp_expired, &tcp->refcnt );
+ timer_init ( &tcp->wait, tcp_wait_expired, &tcp->refcnt );
+ tcp->prev_tcp_state = TCP_CLOSED;
+ tcp->tcp_state = TCP_STATE_SENT ( TCP_SYN );
+ tcp_dump_state ( tcp );
+ tcp->snd_seq = random();
+ INIT_LIST_HEAD ( &tcp->tx_queue );
+ INIT_LIST_HEAD ( &tcp->rx_queue );
+ memcpy ( &tcp->peer, st_peer, sizeof ( tcp->peer ) );
+
+ /* Bind to local port */
+ bind_port = ( st_local ? ntohs ( st_local->st_port ) : 0 );
+ if ( ( rc = tcp_bind ( tcp, bind_port ) ) != 0 )
+ goto err;
+
+ /* Start timer to initiate SYN */
+ start_timer_nodelay ( &tcp->timer );
+
+ /* Attach parent interface, transfer reference to connection
+ * list and return
+ */
+ intf_plug_plug ( &tcp->xfer, xfer );
+ list_add ( &tcp->list, &tcp_conns );
+ return 0;
+
+ err:
+ ref_put ( &tcp->refcnt );
+ return rc;
+}
+
+/**
+ * Close TCP connection
+ *
+ * @v tcp TCP connection
+ * @v rc Reason for close
+ *
+ * Closes the data transfer interface. If the TCP state machine is in
+ * a suitable state, the connection will be deleted.
+ */
+static void tcp_close ( struct tcp_connection *tcp, int rc ) {
+ struct io_buffer *iobuf;
+ struct io_buffer *tmp;
+
+ /* Close data transfer interface */
+ intf_shutdown ( &tcp->xfer, rc );
+ tcp->flags |= TCP_XFER_CLOSED;
+
+ /* If we are in CLOSED, or have otherwise not yet received a
+ * SYN (i.e. we are in LISTEN or SYN_SENT), just delete the
+ * connection.
+ */
+ if ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) {
+
+ /* Transition to CLOSED for the sake of debugging messages */
+ tcp->tcp_state = TCP_CLOSED;
+ tcp_dump_state ( tcp );
+
+ /* Free any unprocessed I/O buffers */
+ list_for_each_entry_safe ( iobuf, tmp, &tcp->rx_queue, list ) {
+ list_del ( &iobuf->list );
+ free_iob ( iobuf );
+ }
+
+ /* Free any unsent I/O buffers */
+ list_for_each_entry_safe ( iobuf, tmp, &tcp->tx_queue, list ) {
+ list_del ( &iobuf->list );
+ free_iob ( iobuf );
+ }
+
+ /* Remove from list and drop reference */
+ stop_timer ( &tcp->timer );
+ stop_timer ( &tcp->wait );
+ list_del ( &tcp->list );
+ ref_put ( &tcp->refcnt );
+ DBGC ( tcp, "TCP %p connection deleted\n", tcp );
+ return;
+ }
+
+ /* If we have not had our SYN acknowledged (i.e. we are in
+ * SYN_RCVD), pretend that it has been acknowledged so that we
+ * can send a FIN without breaking things.
+ */
+ if ( ! ( tcp->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
+ tcp_rx_ack ( tcp, ( tcp->snd_seq + 1 ), 0 );
+
+ /* If we have no data remaining to send, start sending FIN */
+ if ( list_empty ( &tcp->tx_queue ) ) {
+ tcp->tcp_state |= TCP_STATE_SENT ( TCP_FIN );
+ tcp_dump_state ( tcp );
+ }
+}
+
+/***************************************************************************
+ *
+ * Transmit data path
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Calculate transmission window
+ *
+ * @v tcp TCP connection
+ * @ret len Maximum length that can be sent in a single packet
+ */
+static size_t tcp_xmit_win ( struct tcp_connection *tcp ) {
+ size_t len;
+
+ /* Not ready if we're not in a suitable connection state */
+ if ( ! TCP_CAN_SEND_DATA ( tcp->tcp_state ) )
+ return 0;
+
+ /* Length is the minimum of the receiver's window and the path MTU */
+ len = tcp->snd_win;
+ if ( len > TCP_PATH_MTU )
+ len = TCP_PATH_MTU;
+
+ return len;
+}
+
+/**
+ * Check data-transfer flow control window
+ *
+ * @v tcp TCP connection
+ * @ret len Length of window
+ */
+static size_t tcp_xfer_window ( struct tcp_connection *tcp ) {
+
+ /* Not ready if data queue is non-empty. This imposes a limit
+ * of only one unACKed packet in the TX queue at any time; we
+ * do this to conserve memory usage.
+ */
+ if ( ! list_empty ( &tcp->tx_queue ) )
+ return 0;
+
+ /* Return TCP window length */
+ return tcp_xmit_win ( tcp );
+}
+
+/**
+ * Process TCP transmit queue
+ *
+ * @v tcp TCP connection
+ * @v max_len Maximum length to process
+ * @v dest I/O buffer to fill with data, or NULL
+ * @v remove Remove data from queue
+ * @ret len Length of data processed
+ *
+ * This processes at most @c max_len bytes from the TCP connection's
+ * transmit queue. Data will be copied into the @c dest I/O buffer
+ * (if provided) and, if @c remove is true, removed from the transmit
+ * queue.
+ */
+static size_t tcp_process_tx_queue ( struct tcp_connection *tcp, size_t max_len,
+ struct io_buffer *dest, int remove ) {
+ struct io_buffer *iobuf;
+ struct io_buffer *tmp;
+ size_t frag_len;
+ size_t len = 0;
+
+ list_for_each_entry_safe ( iobuf, tmp, &tcp->tx_queue, list ) {
+ frag_len = iob_len ( iobuf );
+ if ( frag_len > max_len )
+ frag_len = max_len;
+ if ( dest ) {
+ memcpy ( iob_put ( dest, frag_len ), iobuf->data,
+ frag_len );
+ }
+ if ( remove ) {
+ iob_pull ( iobuf, frag_len );
+ if ( ! iob_len ( iobuf ) ) {
+ list_del ( &iobuf->list );
+ free_iob ( iobuf );
+ }
+ }
+ len += frag_len;
+ max_len -= frag_len;
+ }
+ return len;
+}
+
+/**
+ * Transmit any outstanding data
+ *
+ * @v tcp TCP connection
+ *
+ * Transmits any outstanding data on the connection.
+ *
+ * Note that even if an error is returned, the retransmission timer
+ * will have been started if necessary, and so the stack will
+ * eventually attempt to retransmit the failed packet.
+ */
+static int tcp_xmit ( struct tcp_connection *tcp ) {
+ struct io_buffer *iobuf;
+ struct tcp_header *tcphdr;
+ struct tcp_mss_option *mssopt;
+ struct tcp_timestamp_padded_option *tsopt;
+ void *payload;
+ unsigned int flags;
+ size_t len = 0;
+ uint32_t seq_len;
+ uint32_t app_win;
+ uint32_t max_rcv_win;
+ int rc;
+
+ /* If retransmission timer is already running, do nothing */
+ if ( timer_running ( &tcp->timer ) )
+ return 0;
+
+ /* Calculate both the actual (payload) and sequence space
+ * lengths that we wish to transmit.
+ */
+ if ( TCP_CAN_SEND_DATA ( tcp->tcp_state ) ) {
+ len = tcp_process_tx_queue ( tcp, tcp_xmit_win ( tcp ),
+ NULL, 0 );
+ }
+ seq_len = len;
+ flags = TCP_FLAGS_SENDING ( tcp->tcp_state );
+ if ( flags & ( TCP_SYN | TCP_FIN ) ) {
+ /* SYN or FIN consume one byte, and we can never send both */
+ assert ( ! ( ( flags & TCP_SYN ) && ( flags & TCP_FIN ) ) );
+ seq_len++;
+ }
+ tcp->snd_sent = seq_len;
+
+ /* If we have nothing to transmit, stop now */
+ if ( ( seq_len == 0 ) && ! ( tcp->flags & TCP_ACK_PENDING ) )
+ return 0;
+
+ /* If we are transmitting anything that requires
+ * acknowledgement (i.e. consumes sequence space), start the
+ * retransmission timer. Do this before attempting to
+ * allocate the I/O buffer, in case allocation itself fails.
+ */
+ if ( seq_len )
+ start_timer ( &tcp->timer );
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( len + TCP_MAX_HEADER_LEN );
+ if ( ! iobuf ) {
+ DBGC ( tcp, "TCP %p could not allocate iobuf for %08x..%08x "
+ "%08x\n", tcp, tcp->snd_seq, ( tcp->snd_seq + seq_len ),
+ tcp->rcv_ack );
+ return -ENOMEM;
+ }
+ iob_reserve ( iobuf, TCP_MAX_HEADER_LEN );
+
+ /* Fill data payload from transmit queue */
+ tcp_process_tx_queue ( tcp, len, iobuf, 0 );
+
+ /* Expand receive window if possible */
+ max_rcv_win = ( ( freemem * 3 ) / 4 );
+ if ( max_rcv_win > TCP_MAX_WINDOW_SIZE )
+ max_rcv_win = TCP_MAX_WINDOW_SIZE;
+ app_win = xfer_window ( &tcp->xfer );
+ if ( max_rcv_win > app_win )
+ max_rcv_win = app_win;
+ max_rcv_win &= ~0x03; /* Keep everything dword-aligned */
+ if ( tcp->rcv_win < max_rcv_win )
+ tcp->rcv_win = max_rcv_win;
+
+ /* Fill up the TCP header */
+ payload = iobuf->data;
+ if ( flags & TCP_SYN ) {
+ mssopt = iob_push ( iobuf, sizeof ( *mssopt ) );
+ mssopt->kind = TCP_OPTION_MSS;
+ mssopt->length = sizeof ( *mssopt );
+ mssopt->mss = htons ( TCP_MSS );
+ }
+ if ( ( flags & TCP_SYN ) || ( tcp->flags & TCP_TS_ENABLED ) ) {
+ tsopt = iob_push ( iobuf, sizeof ( *tsopt ) );
+ memset ( tsopt->nop, TCP_OPTION_NOP, sizeof ( tsopt->nop ) );
+ tsopt->tsopt.kind = TCP_OPTION_TS;
+ tsopt->tsopt.length = sizeof ( tsopt->tsopt );
+ tsopt->tsopt.tsval = htonl ( currticks() );
+ tsopt->tsopt.tsecr = htonl ( tcp->ts_recent );
+ }
+ if ( len != 0 )
+ flags |= TCP_PSH;
+ tcphdr = iob_push ( iobuf, sizeof ( *tcphdr ) );
+ memset ( tcphdr, 0, sizeof ( *tcphdr ) );
+ tcphdr->src = htons ( tcp->local_port );
+ tcphdr->dest = tcp->peer.st_port;
+ tcphdr->seq = htonl ( tcp->snd_seq );
+ tcphdr->ack = htonl ( tcp->rcv_ack );
+ tcphdr->hlen = ( ( payload - iobuf->data ) << 2 );
+ tcphdr->flags = flags;
+ tcphdr->win = htons ( tcp->rcv_win );
+ tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) );
+
+ /* Dump header */
+ DBGC2 ( tcp, "TCP %p TX %d->%d %08x..%08x %08x %4zd",
+ tcp, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ),
+ ntohl ( tcphdr->seq ), ( ntohl ( tcphdr->seq ) + seq_len ),
+ ntohl ( tcphdr->ack ), len );
+ tcp_dump_flags ( tcp, tcphdr->flags );
+ DBGC2 ( tcp, "\n" );
+
+ /* Transmit packet */
+ if ( ( rc = tcpip_tx ( iobuf, &tcp_protocol, NULL, &tcp->peer, NULL,
+ &tcphdr->csum ) ) != 0 ) {
+ DBGC ( tcp, "TCP %p could not transmit %08x..%08x %08x: %s\n",
+ tcp, tcp->snd_seq, ( tcp->snd_seq + tcp->snd_sent ),
+ tcp->rcv_ack, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Clear ACK-pending flag */
+ tcp->flags &= ~TCP_ACK_PENDING;
+
+ return 0;
+}
+
+/**
+ * Retransmission timer expired
+ *
+ * @v timer Retransmission timer
+ * @v over Failure indicator
+ */
+static void tcp_expired ( struct retry_timer *timer, int over ) {
+ struct tcp_connection *tcp =
+ container_of ( timer, struct tcp_connection, timer );
+
+ DBGC ( tcp, "TCP %p timer %s in %s for %08x..%08x %08x\n", tcp,
+ ( over ? "expired" : "fired" ), tcp_state ( tcp->tcp_state ),
+ tcp->snd_seq, ( tcp->snd_seq + tcp->snd_sent ), tcp->rcv_ack );
+
+ assert ( ( tcp->tcp_state == TCP_SYN_SENT ) ||
+ ( tcp->tcp_state == TCP_SYN_RCVD ) ||
+ ( tcp->tcp_state == TCP_ESTABLISHED ) ||
+ ( tcp->tcp_state == TCP_FIN_WAIT_1 ) ||
+ ( tcp->tcp_state == TCP_CLOSE_WAIT ) ||
+ ( tcp->tcp_state == TCP_CLOSING_OR_LAST_ACK ) );
+
+ if ( over ) {
+ /* If we have finally timed out and given up,
+ * terminate the connection
+ */
+ tcp->tcp_state = TCP_CLOSED;
+ tcp_dump_state ( tcp );
+ tcp_close ( tcp, -ETIMEDOUT );
+ } else {
+ /* Otherwise, retransmit the packet */
+ tcp_xmit ( tcp );
+ }
+}
+
+/**
+ * Shutdown timer expired
+ *
+ * @v timer Shutdown timer
+ * @v over Failure indicator
+ */
+static void tcp_wait_expired ( struct retry_timer *timer, int over __unused ) {
+ struct tcp_connection *tcp =
+ container_of ( timer, struct tcp_connection, wait );
+
+ assert ( tcp->tcp_state == TCP_TIME_WAIT );
+
+ DBGC ( tcp, "TCP %p wait complete in %s for %08x..%08x %08x\n", tcp,
+ tcp_state ( tcp->tcp_state ), tcp->snd_seq,
+ ( tcp->snd_seq + tcp->snd_sent ), tcp->rcv_ack );
+
+ tcp->tcp_state = TCP_CLOSED;
+ tcp_dump_state ( tcp );
+ tcp_close ( tcp, 0 );
+}
+
+/**
+ * Send RST response to incoming packet
+ *
+ * @v in_tcphdr TCP header of incoming packet
+ * @ret rc Return status code
+ */
+static int tcp_xmit_reset ( struct tcp_connection *tcp,
+ struct sockaddr_tcpip *st_dest,
+ struct tcp_header *in_tcphdr ) {
+ struct io_buffer *iobuf;
+ struct tcp_header *tcphdr;
+ int rc;
+
+ /* Allocate space for dataless TX buffer */
+ iobuf = alloc_iob ( TCP_MAX_HEADER_LEN );
+ if ( ! iobuf ) {
+ DBGC ( tcp, "TCP %p could not allocate iobuf for RST "
+ "%08x..%08x %08x\n", tcp, ntohl ( in_tcphdr->ack ),
+ ntohl ( in_tcphdr->ack ), ntohl ( in_tcphdr->seq ) );
+ return -ENOMEM;
+ }
+ iob_reserve ( iobuf, TCP_MAX_HEADER_LEN );
+
+ /* Construct RST response */
+ tcphdr = iob_push ( iobuf, sizeof ( *tcphdr ) );
+ memset ( tcphdr, 0, sizeof ( *tcphdr ) );
+ tcphdr->src = in_tcphdr->dest;
+ tcphdr->dest = in_tcphdr->src;
+ tcphdr->seq = in_tcphdr->ack;
+ tcphdr->ack = in_tcphdr->seq;
+ tcphdr->hlen = ( ( sizeof ( *tcphdr ) / 4 ) << 4 );
+ tcphdr->flags = ( TCP_RST | TCP_ACK );
+ tcphdr->win = htons ( TCP_MAX_WINDOW_SIZE );
+ tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) );
+
+ /* Dump header */
+ DBGC2 ( tcp, "TCP %p TX %d->%d %08x..%08x %08x %4d",
+ tcp, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ),
+ ntohl ( tcphdr->seq ), ( ntohl ( tcphdr->seq ) ),
+ ntohl ( tcphdr->ack ), 0 );
+ tcp_dump_flags ( tcp, tcphdr->flags );
+ DBGC2 ( tcp, "\n" );
+
+ /* Transmit packet */
+ if ( ( rc = tcpip_tx ( iobuf, &tcp_protocol, NULL, st_dest,
+ NULL, &tcphdr->csum ) ) != 0 ) {
+ DBGC ( tcp, "TCP %p could not transmit RST %08x..%08x %08x: "
+ "%s\n", tcp, ntohl ( in_tcphdr->ack ),
+ ntohl ( in_tcphdr->ack ), ntohl ( in_tcphdr->seq ),
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * Receive data path
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Identify TCP connection by local port number
+ *
+ * @v local_port Local port
+ * @ret tcp TCP connection, or NULL
+ */
+static struct tcp_connection * tcp_demux ( unsigned int local_port ) {
+ struct tcp_connection *tcp;
+
+ list_for_each_entry ( tcp, &tcp_conns, list ) {
+ if ( tcp->local_port == local_port )
+ return tcp;
+ }
+ return NULL;
+}
+
+/**
+ * Parse TCP received options
+ *
+ * @v tcp TCP connection
+ * @v data Raw options data
+ * @v len Raw options length
+ * @v options Options structure to fill in
+ */
+static void tcp_rx_opts ( struct tcp_connection *tcp, const void *data,
+ size_t len, struct tcp_options *options ) {
+ const void *end = ( data + len );
+ const struct tcp_option *option;
+ unsigned int kind;
+
+ memset ( options, 0, sizeof ( *options ) );
+ while ( data < end ) {
+ option = data;
+ kind = option->kind;
+ if ( kind == TCP_OPTION_END )
+ return;
+ if ( kind == TCP_OPTION_NOP ) {
+ data++;
+ continue;
+ }
+ switch ( kind ) {
+ case TCP_OPTION_MSS:
+ options->mssopt = data;
+ break;
+ case TCP_OPTION_TS:
+ options->tsopt = data;
+ break;
+ default:
+ DBGC ( tcp, "TCP %p received unknown option %d\n",
+ tcp, kind );
+ break;
+ }
+ data += option->length;
+ }
+}
+
+/**
+ * Consume received sequence space
+ *
+ * @v tcp TCP connection
+ * @v seq_len Sequence space length to consume
+ */
+static void tcp_rx_seq ( struct tcp_connection *tcp, uint32_t seq_len ) {
+
+ /* Sanity check */
+ assert ( seq_len > 0 );
+
+ /* Update acknowledgement number */
+ tcp->rcv_ack += seq_len;
+
+ /* Update window */
+ if ( tcp->rcv_win > seq_len ) {
+ tcp->rcv_win -= seq_len;
+ } else {
+ tcp->rcv_win = 0;
+ }
+
+ /* Update timestamp */
+ tcp->ts_recent = tcp->ts_val;
+
+ /* Mark ACK as pending */
+ tcp->flags |= TCP_ACK_PENDING;
+}
+
+/**
+ * Handle TCP received SYN
+ *
+ * @v tcp TCP connection
+ * @v seq SEQ value (in host-endian order)
+ * @v options TCP options
+ * @ret rc Return status code
+ */
+static int tcp_rx_syn ( struct tcp_connection *tcp, uint32_t seq,
+ struct tcp_options *options ) {
+
+ /* Synchronise sequence numbers on first SYN */
+ if ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) {
+ tcp->rcv_ack = seq;
+ if ( options->tsopt )
+ tcp->flags |= TCP_TS_ENABLED;
+ }
+
+ /* Ignore duplicate SYN */
+ if ( seq != tcp->rcv_ack )
+ return 0;
+
+ /* Acknowledge SYN */
+ tcp_rx_seq ( tcp, 1 );
+
+ /* Mark SYN as received and start sending ACKs with each packet */
+ tcp->tcp_state |= ( TCP_STATE_SENT ( TCP_ACK ) |
+ TCP_STATE_RCVD ( TCP_SYN ) );
+
+ return 0;
+}
+
+/**
+ * Handle TCP received ACK
+ *
+ * @v tcp TCP connection
+ * @v ack ACK value (in host-endian order)
+ * @v win WIN value (in host-endian order)
+ * @ret rc Return status code
+ */
+static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack,
+ uint32_t win ) {
+ uint32_t ack_len = ( ack - tcp->snd_seq );
+ size_t len;
+ unsigned int acked_flags;
+
+ /* Check for out-of-range or old duplicate ACKs */
+ if ( ack_len > tcp->snd_sent ) {
+ DBGC ( tcp, "TCP %p received ACK for %08x..%08x, "
+ "sent only %08x..%08x\n", tcp, tcp->snd_seq,
+ ( tcp->snd_seq + ack_len ), tcp->snd_seq,
+ ( tcp->snd_seq + tcp->snd_sent ) );
+
+ if ( TCP_HAS_BEEN_ESTABLISHED ( tcp->tcp_state ) ) {
+ /* Just ignore what might be old duplicate ACKs */
+ return 0;
+ } else {
+ /* Send RST if an out-of-range ACK is received
+ * on a not-yet-established connection, as per
+ * RFC 793.
+ */
+ return -EINVAL;
+ }
+ }
+
+ /* Ignore ACKs that don't actually acknowledge any new data.
+ * (In particular, do not stop the retransmission timer; this
+ * avoids creating a sorceror's apprentice syndrome when a
+ * duplicate ACK is received and we still have data in our
+ * transmit queue.)
+ */
+ if ( ack_len == 0 )
+ return 0;
+
+ /* Stop the retransmission timer */
+ stop_timer ( &tcp->timer );
+
+ /* Determine acknowledged flags and data length */
+ len = ack_len;
+ acked_flags = ( TCP_FLAGS_SENDING ( tcp->tcp_state ) &
+ ( TCP_SYN | TCP_FIN ) );
+ if ( acked_flags )
+ len--;
+
+ /* Update SEQ and sent counters, and window size */
+ tcp->snd_seq = ack;
+ tcp->snd_sent = 0;
+ tcp->snd_win = win;
+
+ /* Remove any acknowledged data from transmit queue */
+ tcp_process_tx_queue ( tcp, len, NULL, 1 );
+
+ /* Mark SYN/FIN as acknowledged if applicable. */
+ if ( acked_flags )
+ tcp->tcp_state |= TCP_STATE_ACKED ( acked_flags );
+
+ /* Start sending FIN if we've had all possible data ACKed */
+ if ( list_empty ( &tcp->tx_queue ) && ( tcp->flags & TCP_XFER_CLOSED ) )
+ tcp->tcp_state |= TCP_STATE_SENT ( TCP_FIN );
+
+ return 0;
+}
+
+/**
+ * Handle TCP received data
+ *
+ * @v tcp TCP connection
+ * @v seq SEQ value (in host-endian order)
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * This function takes ownership of the I/O buffer.
+ */
+static int tcp_rx_data ( struct tcp_connection *tcp, uint32_t seq,
+ struct io_buffer *iobuf ) {
+ uint32_t already_rcvd;
+ uint32_t len;
+ int rc;
+
+ /* Ignore duplicate or out-of-order data */
+ already_rcvd = ( tcp->rcv_ack - seq );
+ len = iob_len ( iobuf );
+ if ( already_rcvd >= len ) {
+ free_iob ( iobuf );
+ return 0;
+ }
+ iob_pull ( iobuf, already_rcvd );
+ len -= already_rcvd;
+
+ /* Acknowledge new data */
+ tcp_rx_seq ( tcp, len );
+
+ /* Deliver data to application */
+ if ( ( rc = xfer_deliver_iob ( &tcp->xfer, iobuf ) ) != 0 ) {
+ DBGC ( tcp, "TCP %p could not deliver %08x..%08x: %s\n",
+ tcp, seq, ( seq + len ), strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle TCP received FIN
+ *
+ * @v tcp TCP connection
+ * @v seq SEQ value (in host-endian order)
+ * @ret rc Return status code
+ */
+static int tcp_rx_fin ( struct tcp_connection *tcp, uint32_t seq ) {
+
+ /* Ignore duplicate or out-of-order FIN */
+ if ( seq != tcp->rcv_ack )
+ return 0;
+
+ /* Acknowledge FIN */
+ tcp_rx_seq ( tcp, 1 );
+
+ /* Mark FIN as received */
+ tcp->tcp_state |= TCP_STATE_RCVD ( TCP_FIN );
+
+ /* Close connection */
+ tcp_close ( tcp, 0 );
+
+ return 0;
+}
+
+/**
+ * Handle TCP received RST
+ *
+ * @v tcp TCP connection
+ * @v seq SEQ value (in host-endian order)
+ * @ret rc Return status code
+ */
+static int tcp_rx_rst ( struct tcp_connection *tcp, uint32_t seq ) {
+
+ /* Accept RST only if it falls within the window. If we have
+ * not yet received a SYN, then we have no window to test
+ * against, so fall back to checking that our SYN has been
+ * ACKed.
+ */
+ if ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) {
+ if ( ! tcp_in_window ( seq, tcp->rcv_ack, tcp->rcv_win ) )
+ return 0;
+ } else {
+ if ( ! ( tcp->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
+ return 0;
+ }
+
+ /* Abort connection */
+ tcp->tcp_state = TCP_CLOSED;
+ tcp_dump_state ( tcp );
+ tcp_close ( tcp, -ECONNRESET );
+
+ DBGC ( tcp, "TCP %p connection reset by peer\n", tcp );
+ return -ECONNRESET;
+}
+
+/**
+ * Enqueue received TCP packet
+ *
+ * @v tcp TCP connection
+ * @v seq SEQ value (in host-endian order)
+ * @v flags TCP flags
+ * @v iobuf I/O buffer
+ */
+static void tcp_rx_enqueue ( struct tcp_connection *tcp, uint32_t seq,
+ uint8_t flags, struct io_buffer *iobuf ) {
+ struct tcp_rx_queued_header *tcpqhdr;
+ struct io_buffer *queued;
+ size_t len;
+ uint32_t seq_len;
+
+ /* Calculate remaining flags and sequence length. Note that
+ * SYN, if present, has already been processed by this point.
+ */
+ flags &= TCP_FIN;
+ len = iob_len ( iobuf );
+ seq_len = ( len + ( flags ? 1 : 0 ) );
+
+ /* Discard immediately (to save memory) if:
+ *
+ * a) we have not yet received a SYN (and so have no defined
+ * receive window), or
+ * b) the packet lies entirely outside the receive window, or
+ * c) there is no further content to process.
+ */
+ if ( ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) ||
+ ( tcp_cmp ( seq, tcp->rcv_ack + tcp->rcv_win ) >= 0 ) ||
+ ( tcp_cmp ( seq + seq_len, tcp->rcv_ack ) < 0 ) ||
+ ( seq_len == 0 ) ) {
+ free_iob ( iobuf );
+ return;
+ }
+
+ /* Add internal header */
+ tcpqhdr = iob_push ( iobuf, sizeof ( *tcpqhdr ) );
+ tcpqhdr->seq = seq;
+ tcpqhdr->flags = flags;
+
+ /* Add to RX queue */
+ list_for_each_entry ( queued, &tcp->rx_queue, list ) {
+ tcpqhdr = queued->data;
+ if ( tcp_cmp ( seq, tcpqhdr->seq ) < 0 )
+ break;
+ }
+ list_add_tail ( &iobuf->list, &queued->list );
+}
+
+/**
+ * Process receive queue
+ *
+ * @v tcp TCP connection
+ */
+static void tcp_process_rx_queue ( struct tcp_connection *tcp ) {
+ struct io_buffer *iobuf;
+ struct tcp_rx_queued_header *tcpqhdr;
+ uint32_t seq;
+ unsigned int flags;
+ size_t len;
+
+ /* Process all applicable received buffers. Note that we
+ * cannot use list_for_each_entry() to iterate over the RX
+ * queue, since tcp_discard() may remove packets from the RX
+ * queue while we are processing.
+ */
+ while ( ( iobuf = list_first_entry ( &tcp->rx_queue, struct io_buffer,
+ list ) ) ) {
+
+ /* Stop processing when we hit the first gap */
+ tcpqhdr = iobuf->data;
+ if ( tcp_cmp ( tcpqhdr->seq, tcp->rcv_ack ) > 0 )
+ break;
+
+ /* Strip internal header and remove from RX queue */
+ list_del ( &iobuf->list );
+ seq = tcpqhdr->seq;
+ flags = tcpqhdr->flags;
+ iob_pull ( iobuf, sizeof ( *tcpqhdr ) );
+ len = iob_len ( iobuf );
+
+ /* Handle new data, if any */
+ tcp_rx_data ( tcp, seq, iob_disown ( iobuf ) );
+ seq += len;
+
+ /* Handle FIN, if present */
+ if ( flags & TCP_FIN ) {
+ tcp_rx_fin ( tcp, seq );
+ seq++;
+ }
+ }
+}
+
+/**
+ * Process received packet
+ *
+ * @v iobuf I/O buffer
+ * @v st_src Partially-filled source address
+ * @v st_dest Partially-filled destination address
+ * @v pshdr_csum Pseudo-header checksum
+ * @ret rc Return status code
+ */
+static int tcp_rx ( struct io_buffer *iobuf,
+ struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest __unused,
+ uint16_t pshdr_csum ) {
+ struct tcp_header *tcphdr = iobuf->data;
+ struct tcp_connection *tcp;
+ struct tcp_options options;
+ size_t hlen;
+ uint16_t csum;
+ uint32_t seq;
+ uint32_t ack;
+ uint32_t win;
+ unsigned int flags;
+ size_t len;
+ uint32_t seq_len;
+ size_t old_xfer_window;
+ int rc;
+
+ /* Sanity check packet */
+ if ( iob_len ( iobuf ) < sizeof ( *tcphdr ) ) {
+ DBG ( "TCP packet too short at %zd bytes (min %zd bytes)\n",
+ iob_len ( iobuf ), sizeof ( *tcphdr ) );
+ rc = -EINVAL;
+ goto discard;
+ }
+ hlen = ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ) * 4;
+ if ( hlen < sizeof ( *tcphdr ) ) {
+ DBG ( "TCP header too short at %zd bytes (min %zd bytes)\n",
+ hlen, sizeof ( *tcphdr ) );
+ rc = -EINVAL;
+ goto discard;
+ }
+ if ( hlen > iob_len ( iobuf ) ) {
+ DBG ( "TCP header too long at %zd bytes (max %zd bytes)\n",
+ hlen, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto discard;
+ }
+ csum = tcpip_continue_chksum ( pshdr_csum, iobuf->data,
+ iob_len ( iobuf ) );
+ if ( csum != 0 ) {
+ DBG ( "TCP checksum incorrect (is %04x including checksum "
+ "field, should be 0000)\n", csum );
+ rc = -EINVAL;
+ goto discard;
+ }
+
+ /* Parse parameters from header and strip header */
+ tcp = tcp_demux ( ntohs ( tcphdr->dest ) );
+ seq = ntohl ( tcphdr->seq );
+ ack = ntohl ( tcphdr->ack );
+ win = ntohs ( tcphdr->win );
+ flags = tcphdr->flags;
+ tcp_rx_opts ( tcp, ( ( ( void * ) tcphdr ) + sizeof ( *tcphdr ) ),
+ ( hlen - sizeof ( *tcphdr ) ), &options );
+ if ( tcp && options.tsopt )
+ tcp->ts_val = ntohl ( options.tsopt->tsval );
+ iob_pull ( iobuf, hlen );
+ len = iob_len ( iobuf );
+ seq_len = ( len + ( ( flags & TCP_SYN ) ? 1 : 0 ) +
+ ( ( flags & TCP_FIN ) ? 1 : 0 ) );
+
+ /* Dump header */
+ DBGC2 ( tcp, "TCP %p RX %d<-%d %08x %08x..%08x %4zd",
+ tcp, ntohs ( tcphdr->dest ), ntohs ( tcphdr->src ),
+ ntohl ( tcphdr->ack ), ntohl ( tcphdr->seq ),
+ ( ntohl ( tcphdr->seq ) + seq_len ), len );
+ tcp_dump_flags ( tcp, tcphdr->flags );
+ DBGC2 ( tcp, "\n" );
+
+ /* If no connection was found, send RST */
+ if ( ! tcp ) {
+ tcp_xmit_reset ( tcp, st_src, tcphdr );
+ rc = -ENOTCONN;
+ goto discard;
+ }
+
+ /* Record old data-transfer window */
+ old_xfer_window = tcp_xfer_window ( tcp );
+
+ /* Handle ACK, if present */
+ if ( flags & TCP_ACK ) {
+ if ( ( rc = tcp_rx_ack ( tcp, ack, win ) ) != 0 ) {
+ tcp_xmit_reset ( tcp, st_src, tcphdr );
+ goto discard;
+ }
+ }
+
+ /* Force an ACK if this packet is out of order */
+ if ( ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) &&
+ ( seq != tcp->rcv_ack ) ) {
+ tcp->flags |= TCP_ACK_PENDING;
+ }
+
+ /* Handle SYN, if present */
+ if ( flags & TCP_SYN ) {
+ tcp_rx_syn ( tcp, seq, &options );
+ seq++;
+ }
+
+ /* Handle RST, if present */
+ if ( flags & TCP_RST ) {
+ if ( ( rc = tcp_rx_rst ( tcp, seq ) ) != 0 )
+ goto discard;
+ }
+
+ /* Enqueue received data */
+ tcp_rx_enqueue ( tcp, seq, flags, iob_disown ( iobuf ) );
+
+ /* Process receive queue */
+ tcp_process_rx_queue ( tcp );
+
+ /* Dump out any state change as a result of the received packet */
+ tcp_dump_state ( tcp );
+
+ /* Send out any pending data */
+ tcp_xmit ( tcp );
+
+ /* If this packet was the last we expect to receive, set up
+ * timer to expire and cause the connection to be freed.
+ */
+ if ( TCP_CLOSED_GRACEFULLY ( tcp->tcp_state ) ) {
+ stop_timer ( &tcp->wait );
+ start_timer_fixed ( &tcp->wait, ( 2 * TCP_MSL ) );
+ }
+
+ /* Notify application if window has changed */
+ if ( tcp_xfer_window ( tcp ) != old_xfer_window )
+ xfer_window_changed ( &tcp->xfer );
+
+ return 0;
+
+ discard:
+ /* Free received packet */
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** TCP protocol */
+struct tcpip_protocol tcp_protocol __tcpip_protocol = {
+ .name = "TCP",
+ .rx = tcp_rx,
+ .tcpip_proto = IP_TCP,
+};
+
+/**
+ * Discard some cached TCP data
+ *
+ * @ret discarded Number of cached items discarded
+ */
+static unsigned int tcp_discard ( void ) {
+ struct tcp_connection *tcp;
+ struct io_buffer *iobuf;
+ unsigned int discarded = 0;
+
+ /* Try to drop one queued RX packet from each connection */
+ list_for_each_entry ( tcp, &tcp_conns, list ) {
+ list_for_each_entry_reverse ( iobuf, &tcp->rx_queue, list ) {
+ list_del ( &iobuf->list );
+ free_iob ( iobuf );
+ discarded++;
+ break;
+ }
+ }
+
+ return discarded;
+}
+
+/** TCP cache discarder */
+struct cache_discarder tcp_cache_discarder __cache_discarder = {
+ .discard = tcp_discard,
+};
+
+/**
+ * Shut down all TCP connections
+ *
+ */
+static void tcp_shutdown ( int booting __unused ) {
+ struct tcp_connection *tcp;
+
+ while ( ( tcp = list_first_entry ( &tcp_conns, struct tcp_connection,
+ list ) ) != NULL ) {
+ tcp->tcp_state = TCP_CLOSED;
+ tcp_dump_state ( tcp );
+ tcp_close ( tcp, -ECANCELED );
+ }
+}
+
+/** TCP shutdown function */
+struct startup_fn tcp_startup_fn __startup_fn ( STARTUP_EARLY ) = {
+ .shutdown = tcp_shutdown,
+};
+
+/***************************************************************************
+ *
+ * Data transfer interface
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Close interface
+ *
+ * @v tcp TCP connection
+ * @v rc Reason for close
+ */
+static void tcp_xfer_close ( struct tcp_connection *tcp, int rc ) {
+
+ /* Close data transfer interface */
+ tcp_close ( tcp, rc );
+
+ /* Transmit FIN, if possible */
+ tcp_xmit ( tcp );
+}
+
+/**
+ * Deliver datagram as I/O buffer
+ *
+ * @v tcp TCP connection
+ * @v iobuf Datagram I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int tcp_xfer_deliver ( struct tcp_connection *tcp,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+
+ /* Enqueue packet */
+ list_add_tail ( &iobuf->list, &tcp->tx_queue );
+
+ /* Transmit data, if possible */
+ tcp_xmit ( tcp );
+
+ return 0;
+}
+
+/** TCP data transfer interface operations */
+static struct interface_operation tcp_xfer_operations[] = {
+ INTF_OP ( xfer_deliver, struct tcp_connection *, tcp_xfer_deliver ),
+ INTF_OP ( xfer_window, struct tcp_connection *, tcp_xfer_window ),
+ INTF_OP ( intf_close, struct tcp_connection *, tcp_xfer_close ),
+};
+
+/** TCP data transfer interface descriptor */
+static struct interface_descriptor tcp_xfer_desc =
+ INTF_DESC ( struct tcp_connection, xfer, tcp_xfer_operations );
+
+/***************************************************************************
+ *
+ * Openers
+ *
+ ***************************************************************************
+ */
+
+/** TCP socket opener */
+struct socket_opener tcp_socket_opener __socket_opener = {
+ .semantics = TCP_SOCK_STREAM,
+ .family = AF_INET,
+ .open = tcp_open,
+};
+
+/** Linkage hack */
+int tcp_sock_stream = TCP_SOCK_STREAM;
+
+/**
+ * Open TCP URI
+ *
+ * @v xfer Data transfer interface
+ * @v uri URI
+ * @ret rc Return status code
+ */
+static int tcp_open_uri ( struct interface *xfer, struct uri *uri ) {
+ struct sockaddr_tcpip peer;
+
+ /* Sanity check */
+ if ( ! uri->host )
+ return -EINVAL;
+
+ memset ( &peer, 0, sizeof ( peer ) );
+ peer.st_port = htons ( uri_port ( uri, 0 ) );
+ return xfer_open_named_socket ( xfer, SOCK_STREAM,
+ ( struct sockaddr * ) &peer,
+ uri->host, NULL );
+}
+
+/** TCP URI opener */
+struct uri_opener tcp_uri_opener __uri_opener = {
+ .scheme = "tcp",
+ .open = tcp_open_uri,
+};
+
diff --git a/src/VBox/Devices/PC/ipxe/src/net/tcp/ftp.c b/src/VBox/Devices/PC/ipxe/src/net/tcp/ftp.c
new file mode 100644
index 00000000..e5bc8e9f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/tcp/ftp.c
@@ -0,0 +1,470 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/socket.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/in.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/uri.h>
+#include <ipxe/features.h>
+#include <ipxe/ftp.h>
+
+/** @file
+ *
+ * File transfer protocol
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "FTP", DHCP_EB_FEATURE_FTP, 1 );
+
+/**
+ * FTP states
+ *
+ * These @b must be sequential, i.e. a successful FTP session must
+ * pass through each of these states in order.
+ */
+enum ftp_state {
+ FTP_CONNECT = 0,
+ FTP_USER,
+ FTP_PASS,
+ FTP_TYPE,
+ FTP_PASV,
+ FTP_RETR,
+ FTP_WAIT,
+ FTP_QUIT,
+ FTP_DONE,
+};
+
+/**
+ * An FTP request
+ *
+ */
+struct ftp_request {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Data transfer interface */
+ struct interface xfer;
+
+ /** URI being fetched */
+ struct uri *uri;
+ /** FTP control channel interface */
+ struct interface control;
+ /** FTP data channel interface */
+ struct interface data;
+
+ /** Current state */
+ enum ftp_state state;
+ /** Buffer to be filled with data received via the control channel */
+ char *recvbuf;
+ /** Remaining size of recvbuf */
+ size_t recvsize;
+ /** FTP status code, as text */
+ char status_text[5];
+ /** Passive-mode parameters, as text */
+ char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */
+};
+
+/**
+ * Free FTP request
+ *
+ * @v refcnt Reference counter
+ */
+static void ftp_free ( struct refcnt *refcnt ) {
+ struct ftp_request *ftp =
+ container_of ( refcnt, struct ftp_request, refcnt );
+
+ DBGC ( ftp, "FTP %p freed\n", ftp );
+
+ uri_put ( ftp->uri );
+ free ( ftp );
+}
+
+/**
+ * Mark FTP operation as complete
+ *
+ * @v ftp FTP request
+ * @v rc Return status code
+ */
+static void ftp_done ( struct ftp_request *ftp, int rc ) {
+
+ DBGC ( ftp, "FTP %p completed (%s)\n", ftp, strerror ( rc ) );
+
+ /* Close all data transfer interfaces */
+ intf_shutdown ( &ftp->data, rc );
+ intf_shutdown ( &ftp->control, rc );
+ intf_shutdown ( &ftp->xfer, rc );
+}
+
+/*****************************************************************************
+ *
+ * FTP control channel
+ *
+ */
+
+/** An FTP control channel string */
+struct ftp_control_string {
+ /** Literal portion */
+ const char *literal;
+ /** Variable portion
+ *
+ * @v ftp FTP request
+ * @ret string Variable portion of string
+ */
+ const char * ( *variable ) ( struct ftp_request *ftp );
+};
+
+/**
+ * Retrieve FTP pathname
+ *
+ * @v ftp FTP request
+ * @ret path FTP pathname
+ */
+static const char * ftp_uri_path ( struct ftp_request *ftp ) {
+ return ftp->uri->path;
+}
+
+/**
+ * Retrieve FTP user
+ *
+ * @v ftp FTP request
+ * @ret user FTP user
+ */
+static const char * ftp_user ( struct ftp_request *ftp ) {
+ static char *ftp_default_user = "anonymous";
+ return ftp->uri->user ? ftp->uri->user : ftp_default_user;
+}
+
+/**
+ * Retrieve FTP password
+ *
+ * @v ftp FTP request
+ * @ret password FTP password
+ */
+static const char * ftp_password ( struct ftp_request *ftp ) {
+ static char *ftp_default_password = "ipxe@ipxe.org";
+ return ftp->uri->password ? ftp->uri->password : ftp_default_password;
+}
+
+/** FTP control channel strings */
+static struct ftp_control_string ftp_strings[] = {
+ [FTP_CONNECT] = { NULL, NULL },
+ [FTP_USER] = { "USER ", ftp_user },
+ [FTP_PASS] = { "PASS ", ftp_password },
+ [FTP_TYPE] = { "TYPE I", NULL },
+ [FTP_PASV] = { "PASV", NULL },
+ [FTP_RETR] = { "RETR ", ftp_uri_path },
+ [FTP_WAIT] = { NULL, NULL },
+ [FTP_QUIT] = { "QUIT", NULL },
+ [FTP_DONE] = { NULL, NULL },
+};
+
+/**
+ * Parse FTP byte sequence value
+ *
+ * @v text Text string
+ * @v value Value buffer
+ * @v len Length of value buffer
+ *
+ * This parses an FTP byte sequence value (e.g. the "aaa,bbb,ccc,ddd"
+ * form for IP addresses in PORT commands) into a byte sequence. @c
+ * *text will be updated to point beyond the end of the parsed byte
+ * sequence.
+ *
+ * This function is safe in the presence of malformed data, though the
+ * output is undefined.
+ */
+static void ftp_parse_value ( char **text, uint8_t *value, size_t len ) {
+ do {
+ *(value++) = strtoul ( *text, text, 10 );
+ if ( **text )
+ (*text)++;
+ } while ( --len );
+}
+
+/**
+ * Move to next state and send the appropriate FTP control string
+ *
+ * @v ftp FTP request
+ *
+ */
+static void ftp_next_state ( struct ftp_request *ftp ) {
+ struct ftp_control_string *ftp_string;
+ const char *literal;
+ const char *variable;
+
+ /* Move to next state */
+ if ( ftp->state < FTP_DONE )
+ ftp->state++;
+
+ /* Send control string if needed */
+ ftp_string = &ftp_strings[ftp->state];
+ literal = ftp_string->literal;
+ variable = ( ftp_string->variable ?
+ ftp_string->variable ( ftp ) : "" );
+ if ( literal ) {
+ DBGC ( ftp, "FTP %p sending %s%s\n", ftp, literal, variable );
+ xfer_printf ( &ftp->control, "%s%s\r\n", literal, variable );
+ }
+}
+
+/**
+ * Handle an FTP control channel response
+ *
+ * @v ftp FTP request
+ *
+ * This is called once we have received a complete response line.
+ */
+static void ftp_reply ( struct ftp_request *ftp ) {
+ char status_major = ftp->status_text[0];
+ char separator = ftp->status_text[3];
+
+ DBGC ( ftp, "FTP %p received status %s\n", ftp, ftp->status_text );
+
+ /* Ignore malformed lines */
+ if ( separator != ' ' )
+ return;
+
+ /* Ignore "intermediate" responses (1xx codes) */
+ if ( status_major == '1' )
+ return;
+
+ /* Anything other than success (2xx) or, in the case of a
+ * repsonse to a "USER" command, a password prompt (3xx), is a
+ * fatal error.
+ */
+ if ( ! ( ( status_major == '2' ) ||
+ ( ( status_major == '3' ) && ( ftp->state == FTP_USER ) ) ) ){
+ /* Flag protocol error and close connections */
+ ftp_done ( ftp, -EPROTO );
+ return;
+ }
+
+ /* Open passive connection when we get "PASV" response */
+ if ( ftp->state == FTP_PASV ) {
+ char *ptr = ftp->passive_text;
+ union {
+ struct sockaddr_in sin;
+ struct sockaddr sa;
+ } sa;
+ int rc;
+
+ sa.sin.sin_family = AF_INET;
+ ftp_parse_value ( &ptr, ( uint8_t * ) &sa.sin.sin_addr,
+ sizeof ( sa.sin.sin_addr ) );
+ ftp_parse_value ( &ptr, ( uint8_t * ) &sa.sin.sin_port,
+ sizeof ( sa.sin.sin_port ) );
+ if ( ( rc = xfer_open_socket ( &ftp->data, SOCK_STREAM,
+ &sa.sa, NULL ) ) != 0 ) {
+ DBGC ( ftp, "FTP %p could not open data connection\n",
+ ftp );
+ ftp_done ( ftp, rc );
+ return;
+ }
+ }
+
+ /* Move to next state and send control string */
+ ftp_next_state ( ftp );
+
+}
+
+/**
+ * Handle new data arriving on FTP control channel
+ *
+ * @v ftp FTP request
+ * @v iob I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ *
+ * Data is collected until a complete line is received, at which point
+ * its information is passed to ftp_reply().
+ */
+static int ftp_control_deliver ( struct ftp_request *ftp,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ char *data = iobuf->data;
+ size_t len = iob_len ( iobuf );
+ char *recvbuf = ftp->recvbuf;
+ size_t recvsize = ftp->recvsize;
+ char c;
+
+ while ( len-- ) {
+ c = *(data++);
+ switch ( c ) {
+ case '\r' :
+ case '\n' :
+ /* End of line: call ftp_reply() to handle
+ * completed reply. Avoid calling ftp_reply()
+ * twice if we receive both \r and \n.
+ */
+ if ( recvsize == 0 )
+ ftp_reply ( ftp );
+ /* Start filling up the status code buffer */
+ recvbuf = ftp->status_text;
+ recvsize = sizeof ( ftp->status_text ) - 1;
+ break;
+ case '(' :
+ /* Start filling up the passive parameter buffer */
+ recvbuf = ftp->passive_text;
+ recvsize = sizeof ( ftp->passive_text ) - 1;
+ break;
+ case ')' :
+ /* Stop filling the passive parameter buffer */
+ recvsize = 0;
+ break;
+ default :
+ /* Fill up buffer if applicable */
+ if ( recvsize > 0 ) {
+ *(recvbuf++) = c;
+ recvsize--;
+ }
+ break;
+ }
+ }
+
+ /* Store for next invocation */
+ ftp->recvbuf = recvbuf;
+ ftp->recvsize = recvsize;
+
+ /* Free I/O buffer */
+ free_iob ( iobuf );
+
+ return 0;
+}
+
+/** FTP control channel interface operations */
+static struct interface_operation ftp_control_operations[] = {
+ INTF_OP ( xfer_deliver, struct ftp_request *, ftp_control_deliver ),
+ INTF_OP ( intf_close, struct ftp_request *, ftp_done ),
+};
+
+/** FTP control channel interface descriptor */
+static struct interface_descriptor ftp_control_desc =
+ INTF_DESC ( struct ftp_request, control, ftp_control_operations );
+
+/*****************************************************************************
+ *
+ * FTP data channel
+ *
+ */
+
+/**
+ * Handle FTP data channel being closed
+ *
+ * @v ftp FTP request
+ * @v rc Reason for closure
+ *
+ * When the data channel is closed, the control channel should be left
+ * alone; the server will send a completion message via the control
+ * channel which we'll pick up.
+ *
+ * If the data channel is closed due to an error, we abort the request.
+ */
+static void ftp_data_closed ( struct ftp_request *ftp, int rc ) {
+
+ DBGC ( ftp, "FTP %p data connection closed: %s\n",
+ ftp, strerror ( rc ) );
+
+ /* If there was an error, close control channel and record status */
+ if ( rc ) {
+ ftp_done ( ftp, rc );
+ } else {
+ ftp_next_state ( ftp );
+ }
+}
+
+/** FTP data channel interface operations */
+static struct interface_operation ftp_data_operations[] = {
+ INTF_OP ( intf_close, struct ftp_request *, ftp_data_closed ),
+};
+
+/** FTP data channel interface descriptor */
+static struct interface_descriptor ftp_data_desc =
+ INTF_DESC_PASSTHRU ( struct ftp_request, data, ftp_data_operations,
+ xfer );
+
+/*****************************************************************************
+ *
+ * Data transfer interface
+ *
+ */
+
+/** FTP data transfer interface operations */
+static struct interface_operation ftp_xfer_operations[] = {
+ INTF_OP ( intf_close, struct ftp_request *, ftp_done ),
+};
+
+/** FTP data transfer interface descriptor */
+static struct interface_descriptor ftp_xfer_desc =
+ INTF_DESC_PASSTHRU ( struct ftp_request, xfer, ftp_xfer_operations,
+ data );
+
+/*****************************************************************************
+ *
+ * URI opener
+ *
+ */
+
+/**
+ * Initiate an FTP connection
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int ftp_open ( struct interface *xfer, struct uri *uri ) {
+ struct ftp_request *ftp;
+ struct sockaddr_tcpip server;
+ int rc;
+
+ /* Sanity checks */
+ if ( ! uri->path )
+ return -EINVAL;
+ if ( ! uri->host )
+ return -EINVAL;
+
+ /* Allocate and populate structure */
+ ftp = zalloc ( sizeof ( *ftp ) );
+ if ( ! ftp )
+ return -ENOMEM;
+ ref_init ( &ftp->refcnt, ftp_free );
+ intf_init ( &ftp->xfer, &ftp_xfer_desc, &ftp->refcnt );
+ intf_init ( &ftp->control, &ftp_control_desc, &ftp->refcnt );
+ intf_init ( &ftp->data, &ftp_data_desc, &ftp->refcnt );
+ ftp->uri = uri_get ( uri );
+ ftp->recvbuf = ftp->status_text;
+ ftp->recvsize = sizeof ( ftp->status_text ) - 1;
+
+ DBGC ( ftp, "FTP %p fetching %s\n", ftp, ftp->uri->path );
+
+ /* Open control connection */
+ memset ( &server, 0, sizeof ( server ) );
+ server.st_port = htons ( uri_port ( uri, FTP_PORT ) );
+ if ( ( rc = xfer_open_named_socket ( &ftp->control, SOCK_STREAM,
+ ( struct sockaddr * ) &server,
+ uri->host, NULL ) ) != 0 )
+ goto err;
+
+ /* Attach to parent interface, mortalise self, and return */
+ intf_plug_plug ( &ftp->xfer, xfer );
+ ref_put ( &ftp->refcnt );
+ return 0;
+
+ err:
+ DBGC ( ftp, "FTP %p could not create request: %s\n",
+ ftp, strerror ( rc ) );
+ ftp_done ( ftp, rc );
+ ref_put ( &ftp->refcnt );
+ return rc;
+}
+
+/** FTP URI opener */
+struct uri_opener ftp_uri_opener __uri_opener = {
+ .scheme = "ftp",
+ .open = ftp_open,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/tcp/http.c b/src/VBox/Devices/PC/ipxe/src/net/tcp/http.c
new file mode 100644
index 00000000..0c038885
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/tcp/http.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Hyper Text Transfer Protocol (HTTP)
+ *
+ */
+
+#include <stddef.h>
+#include <ipxe/open.h>
+#include <ipxe/http.h>
+#include <ipxe/features.h>
+
+FEATURE ( FEATURE_PROTOCOL, "HTTP", DHCP_EB_FEATURE_HTTP, 1 );
+
+/**
+ * Initiate an HTTP connection
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int http_open ( struct interface *xfer, struct uri *uri ) {
+ return http_open_filter ( xfer, uri, HTTP_PORT, NULL );
+}
+
+/** HTTP URI opener */
+struct uri_opener http_uri_opener __uri_opener = {
+ .scheme = "http",
+ .open = http_open,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/tcp/httpcore.c b/src/VBox/Devices/PC/ipxe/src/net/tcp/httpcore.c
new file mode 100644
index 00000000..d0ad952e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/tcp/httpcore.c
@@ -0,0 +1,938 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Hyper Text Transfer Protocol (HTTP) core functionality
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/uri.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/socket.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/process.h>
+#include <ipxe/linebuf.h>
+#include <ipxe/base64.h>
+#include <ipxe/blockdev.h>
+#include <ipxe/acpi.h>
+#include <ipxe/http.h>
+
+/* Disambiguate the various error causes */
+#define EACCES_401 __einfo_error ( EINFO_EACCES_401 )
+#define EINFO_EACCES_401 \
+ __einfo_uniqify ( EINFO_EACCES, 0x01, "HTTP 401 Unauthorized" )
+#define EIO_OTHER __einfo_error ( EINFO_EIO_OTHER )
+#define EINFO_EIO_OTHER \
+ __einfo_uniqify ( EINFO_EIO, 0x01, "Unrecognised HTTP response code" )
+#define EIO_CONTENT_LENGTH __einfo_error ( EINFO_EIO_CONTENT_LENGTH )
+#define EINFO_EIO_CONTENT_LENGTH \
+ __einfo_uniqify ( EINFO_EIO, 0x02, "Content length mismatch" )
+#define EINVAL_RESPONSE __einfo_error ( EINFO_EINVAL_RESPONSE )
+#define EINFO_EINVAL_RESPONSE \
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid content length" )
+#define EINVAL_HEADER __einfo_error ( EINFO_EINVAL_HEADER )
+#define EINFO_EINVAL_HEADER \
+ __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid header" )
+#define EINVAL_CONTENT_LENGTH __einfo_error ( EINFO_EINVAL_CONTENT_LENGTH )
+#define EINFO_EINVAL_CONTENT_LENGTH \
+ __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid content length" )
+#define EINVAL_CHUNK_LENGTH __einfo_error ( EINFO_EINVAL_CHUNK_LENGTH )
+#define EINFO_EINVAL_CHUNK_LENGTH \
+ __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid chunk length" )
+#define ENOENT_404 __einfo_error ( EINFO_ENOENT_404 )
+#define EINFO_ENOENT_404 \
+ __einfo_uniqify ( EINFO_ENOENT, 0x01, "HTTP 404 Not Found" )
+#define EPERM_403 __einfo_error ( EINFO_EPERM_403 )
+#define EINFO_EPERM_403 \
+ __einfo_uniqify ( EINFO_EPERM, 0x01, "HTTP 403 Forbidden" )
+#define EPROTO_UNSOLICITED __einfo_error ( EINFO_EPROTO_UNSOLICITED )
+#define EINFO_EPROTO_UNSOLICITED \
+ __einfo_uniqify ( EINFO_EPROTO, 0x01, "Unsolicited data" )
+
+/** Block size used for HTTP block device request */
+#define HTTP_BLKSIZE 512
+
+/** HTTP flags */
+enum http_flags {
+ /** Request is waiting to be transmitted */
+ HTTP_TX_PENDING = 0x0001,
+ /** Fetch header only */
+ HTTP_HEAD_ONLY = 0x0002,
+ /** Keep connection alive */
+ HTTP_KEEPALIVE = 0x0004,
+};
+
+/** HTTP receive state */
+enum http_rx_state {
+ HTTP_RX_RESPONSE = 0,
+ HTTP_RX_HEADER,
+ HTTP_RX_CHUNK_LEN,
+ HTTP_RX_DATA,
+ HTTP_RX_TRAILER,
+ HTTP_RX_IDLE,
+ HTTP_RX_DEAD,
+};
+
+/**
+ * An HTTP request
+ *
+ */
+struct http_request {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Data transfer interface */
+ struct interface xfer;
+ /** Partial transfer interface */
+ struct interface partial;
+
+ /** URI being fetched */
+ struct uri *uri;
+ /** Transport layer interface */
+ struct interface socket;
+
+ /** Flags */
+ unsigned int flags;
+ /** Starting offset of partial transfer (if applicable) */
+ size_t partial_start;
+ /** Length of partial transfer (if applicable) */
+ size_t partial_len;
+
+ /** TX process */
+ struct process process;
+
+ /** RX state */
+ enum http_rx_state rx_state;
+ /** Received length */
+ size_t rx_len;
+ /** Length remaining (or 0 if unknown) */
+ size_t remaining;
+ /** HTTP is using Transfer-Encoding: chunked */
+ int chunked;
+ /** Current chunk length remaining (if applicable) */
+ size_t chunk_remaining;
+ /** Line buffer for received header lines */
+ struct line_buffer linebuf;
+ /** Receive data buffer (if applicable) */
+ userptr_t rx_buffer;
+};
+
+/**
+ * Free HTTP request
+ *
+ * @v refcnt Reference counter
+ */
+static void http_free ( struct refcnt *refcnt ) {
+ struct http_request *http =
+ container_of ( refcnt, struct http_request, refcnt );
+
+ uri_put ( http->uri );
+ empty_line_buffer ( &http->linebuf );
+ free ( http );
+};
+
+/**
+ * Close HTTP request
+ *
+ * @v http HTTP request
+ * @v rc Return status code
+ */
+static void http_close ( struct http_request *http, int rc ) {
+
+ /* Prevent further processing of any current packet */
+ http->rx_state = HTTP_RX_DEAD;
+
+ /* If we had a Content-Length, and the received content length
+ * isn't correct, flag an error
+ */
+ if ( http->remaining != 0 ) {
+ DBGC ( http, "HTTP %p incorrect length %zd, should be %zd\n",
+ http, http->rx_len, ( http->rx_len + http->remaining ) );
+ if ( rc == 0 )
+ rc = -EIO_CONTENT_LENGTH;
+ }
+
+ /* Remove process */
+ process_del ( &http->process );
+
+ /* Close all data transfer interfaces */
+ intf_shutdown ( &http->socket, rc );
+ intf_shutdown ( &http->partial, rc );
+ intf_shutdown ( &http->xfer, rc );
+}
+
+/**
+ * Mark HTTP request as completed successfully
+ *
+ * @v http HTTP request
+ */
+static void http_done ( struct http_request *http ) {
+
+ /* If we had a Content-Length, and the received content length
+ * isn't correct, force an error
+ */
+ if ( http->remaining != 0 ) {
+ http_close ( http, -EIO_CONTENT_LENGTH );
+ return;
+ }
+
+ /* Enter idle state */
+ http->rx_state = HTTP_RX_IDLE;
+ http->rx_len = 0;
+ assert ( http->remaining == 0 );
+ assert ( http->chunked == 0 );
+ assert ( http->chunk_remaining == 0 );
+
+ /* Close partial transfer interface */
+ intf_restart ( &http->partial, 0 );
+
+ /* Close everything unless we are keeping the connection alive */
+ if ( ! ( http->flags & HTTP_KEEPALIVE ) )
+ http_close ( http, 0 );
+}
+
+/**
+ * Convert HTTP response code to return status code
+ *
+ * @v response HTTP response code
+ * @ret rc Return status code
+ */
+static int http_response_to_rc ( unsigned int response ) {
+ switch ( response ) {
+ case 200:
+ case 206:
+ case 301:
+ case 302:
+ case 303:
+ return 0;
+ case 404:
+ return -ENOENT_404;
+ case 403:
+ return -EPERM_403;
+ case 401:
+ return -EACCES_401;
+ default:
+ return -EIO_OTHER;
+ }
+}
+
+/**
+ * Handle HTTP response
+ *
+ * @v http HTTP request
+ * @v response HTTP response
+ * @ret rc Return status code
+ */
+static int http_rx_response ( struct http_request *http, char *response ) {
+ char *spc;
+ unsigned int code;
+ int rc;
+
+ DBGC ( http, "HTTP %p response \"%s\"\n", http, response );
+
+ /* Check response starts with "HTTP/" */
+ if ( strncmp ( response, "HTTP/", 5 ) != 0 )
+ return -EINVAL_RESPONSE;
+
+ /* Locate and check response code */
+ spc = strchr ( response, ' ' );
+ if ( ! spc )
+ return -EINVAL_RESPONSE;
+ code = strtoul ( spc, NULL, 10 );
+ if ( ( rc = http_response_to_rc ( code ) ) != 0 )
+ return rc;
+
+ /* Move to received headers */
+ http->rx_state = HTTP_RX_HEADER;
+ return 0;
+}
+
+/**
+ * Handle HTTP Location header
+ *
+ * @v http HTTP request
+ * @v value HTTP header value
+ * @ret rc Return status code
+ */
+static int http_rx_location ( struct http_request *http, const char *value ) {
+ int rc;
+
+ /* Redirect to new location */
+ DBGC ( http, "HTTP %p redirecting to %s\n", http, value );
+ if ( ( rc = xfer_redirect ( &http->xfer, LOCATION_URI_STRING,
+ value ) ) != 0 ) {
+ DBGC ( http, "HTTP %p could not redirect: %s\n",
+ http, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle HTTP Content-Length header
+ *
+ * @v http HTTP request
+ * @v value HTTP header value
+ * @ret rc Return status code
+ */
+static int http_rx_content_length ( struct http_request *http,
+ const char *value ) {
+ struct block_device_capacity capacity;
+ size_t content_len;
+ char *endp;
+
+ /* Parse content length */
+ content_len = strtoul ( value, &endp, 10 );
+ if ( *endp != '\0' ) {
+ DBGC ( http, "HTTP %p invalid Content-Length \"%s\"\n",
+ http, value );
+ return -EINVAL_CONTENT_LENGTH;
+ }
+
+ /* If we already have an expected content length, and this
+ * isn't it, then complain
+ */
+ if ( http->remaining && ( http->remaining != content_len ) ) {
+ DBGC ( http, "HTTP %p incorrect Content-Length %zd (expected "
+ "%zd)\n", http, content_len, http->remaining );
+ return -EIO_CONTENT_LENGTH;
+ }
+ if ( ! ( http->flags & HTTP_HEAD_ONLY ) )
+ http->remaining = content_len;
+
+ /* Use seek() to notify recipient of filesize */
+ xfer_seek ( &http->xfer, http->remaining );
+ xfer_seek ( &http->xfer, 0 );
+
+ /* Report block device capacity if applicable */
+ if ( http->flags & HTTP_HEAD_ONLY ) {
+ capacity.blocks = ( content_len / HTTP_BLKSIZE );
+ capacity.blksize = HTTP_BLKSIZE;
+ capacity.max_count = -1U;
+ block_capacity ( &http->partial, &capacity );
+ }
+ return 0;
+}
+
+/**
+ * Handle HTTP Transfer-Encoding header
+ *
+ * @v http HTTP request
+ * @v value HTTP header value
+ * @ret rc Return status code
+ */
+static int http_rx_transfer_encoding ( struct http_request *http,
+ const char *value ) {
+
+ if ( strcmp ( value, "chunked" ) == 0 ) {
+ /* Mark connection as using chunked transfer encoding */
+ http->chunked = 1;
+ }
+
+ return 0;
+}
+
+/** An HTTP header handler */
+struct http_header_handler {
+ /** Name (e.g. "Content-Length") */
+ const char *header;
+ /** Handle received header
+ *
+ * @v http HTTP request
+ * @v value HTTP header value
+ * @ret rc Return status code
+ *
+ * If an error is returned, the download will be aborted.
+ */
+ int ( * rx ) ( struct http_request *http, const char *value );
+};
+
+/** List of HTTP header handlers */
+static struct http_header_handler http_header_handlers[] = {
+ {
+ .header = "Location",
+ .rx = http_rx_location,
+ },
+ {
+ .header = "Content-Length",
+ .rx = http_rx_content_length,
+ },
+ {
+ .header = "Transfer-Encoding",
+ .rx = http_rx_transfer_encoding,
+ },
+ { NULL, NULL }
+};
+
+/**
+ * Handle HTTP header
+ *
+ * @v http HTTP request
+ * @v header HTTP header
+ * @ret rc Return status code
+ */
+static int http_rx_header ( struct http_request *http, char *header ) {
+ struct http_header_handler *handler;
+ char *separator;
+ char *value;
+ int rc;
+
+ /* An empty header line marks the end of this phase */
+ if ( ! header[0] ) {
+ empty_line_buffer ( &http->linebuf );
+ if ( ( http->rx_state == HTTP_RX_HEADER ) &&
+ ( ! ( http->flags & HTTP_HEAD_ONLY ) ) ) {
+ DBGC ( http, "HTTP %p start of data\n", http );
+ http->rx_state = ( http->chunked ?
+ HTTP_RX_CHUNK_LEN : HTTP_RX_DATA );
+ return 0;
+ } else {
+ DBGC ( http, "HTTP %p end of trailer\n", http );
+ http_done ( http );
+ return 0;
+ }
+ }
+
+ DBGC ( http, "HTTP %p header \"%s\"\n", http, header );
+
+ /* Split header at the ": " */
+ separator = strstr ( header, ": " );
+ if ( ! separator ) {
+ DBGC ( http, "HTTP %p malformed header\n", http );
+ return -EINVAL_HEADER;
+ }
+ *separator = '\0';
+ value = ( separator + 2 );
+
+ /* Hand off to header handler, if one exists */
+ for ( handler = http_header_handlers ; handler->header ; handler++ ) {
+ if ( strcasecmp ( header, handler->header ) == 0 ) {
+ if ( ( rc = handler->rx ( http, value ) ) != 0 )
+ return rc;
+ break;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Handle HTTP chunk length
+ *
+ * @v http HTTP request
+ * @v length HTTP chunk length
+ * @ret rc Return status code
+ */
+static int http_rx_chunk_len ( struct http_request *http, char *length ) {
+ char *endp;
+
+ /* Skip blank lines between chunks */
+ if ( length[0] == '\0' )
+ return 0;
+
+ /* Parse chunk length */
+ http->chunk_remaining = strtoul ( length, &endp, 16 );
+ if ( *endp != '\0' ) {
+ DBGC ( http, "HTTP %p invalid chunk length \"%s\"\n",
+ http, length );
+ return -EINVAL_CHUNK_LENGTH;
+ }
+
+ /* Terminate chunked encoding if applicable */
+ if ( http->chunk_remaining == 0 ) {
+ DBGC ( http, "HTTP %p end of chunks\n", http );
+ http->chunked = 0;
+ http->rx_state = HTTP_RX_TRAILER;
+ return 0;
+ }
+
+ /* Use seek() to notify recipient of new filesize */
+ DBGC ( http, "HTTP %p start of chunk of length %zd\n",
+ http, http->chunk_remaining );
+ xfer_seek ( &http->xfer, ( http->rx_len + http->chunk_remaining ) );
+ xfer_seek ( &http->xfer, http->rx_len );
+
+ /* Start receiving data */
+ http->rx_state = HTTP_RX_DATA;
+
+ return 0;
+}
+
+/** An HTTP line-based data handler */
+struct http_line_handler {
+ /** Handle line
+ *
+ * @v http HTTP request
+ * @v line Line to handle
+ * @ret rc Return status code
+ */
+ int ( * rx ) ( struct http_request *http, char *line );
+};
+
+/** List of HTTP line-based data handlers */
+static struct http_line_handler http_line_handlers[] = {
+ [HTTP_RX_RESPONSE] = { .rx = http_rx_response },
+ [HTTP_RX_HEADER] = { .rx = http_rx_header },
+ [HTTP_RX_CHUNK_LEN] = { .rx = http_rx_chunk_len },
+ [HTTP_RX_TRAILER] = { .rx = http_rx_header },
+};
+
+/**
+ * Handle new data arriving via HTTP connection
+ *
+ * @v http HTTP request
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int http_socket_deliver ( struct http_request *http,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ struct http_line_handler *lh;
+ char *line;
+ size_t data_len;
+ ssize_t line_len;
+ int rc = 0;
+
+ while ( iobuf && iob_len ( iobuf ) ) {
+
+ switch ( http->rx_state ) {
+ case HTTP_RX_IDLE:
+ /* Receiving any data in this state is an error */
+ DBGC ( http, "HTTP %p received %zd bytes while %s\n",
+ http, iob_len ( iobuf ),
+ ( ( http->rx_state == HTTP_RX_IDLE ) ?
+ "idle" : "dead" ) );
+ rc = -EPROTO_UNSOLICITED;
+ goto done;
+ case HTTP_RX_DEAD:
+ /* Do no further processing */
+ goto done;
+ case HTTP_RX_DATA:
+ /* Pass received data to caller */
+ data_len = iob_len ( iobuf );
+ if ( http->chunk_remaining &&
+ ( http->chunk_remaining < data_len ) ) {
+ data_len = http->chunk_remaining;
+ }
+ if ( http->remaining &&
+ ( http->remaining < data_len ) ) {
+ data_len = http->remaining;
+ }
+ if ( http->rx_buffer != UNULL ) {
+ /* Copy to partial transfer buffer */
+ copy_to_user ( http->rx_buffer, http->rx_len,
+ iobuf->data, data_len );
+ iob_pull ( iobuf, data_len );
+ } else if ( data_len < iob_len ( iobuf ) ) {
+ /* Deliver partial buffer as raw data */
+ rc = xfer_deliver_raw ( &http->xfer,
+ iobuf->data, data_len );
+ iob_pull ( iobuf, data_len );
+ if ( rc != 0 )
+ goto done;
+ } else {
+ /* Deliver whole I/O buffer */
+ if ( ( rc = xfer_deliver_iob ( &http->xfer,
+ iob_disown ( iobuf ) ) ) != 0 )
+ goto done;
+ }
+ http->rx_len += data_len;
+ if ( http->chunk_remaining ) {
+ http->chunk_remaining -= data_len;
+ if ( http->chunk_remaining == 0 )
+ http->rx_state = HTTP_RX_CHUNK_LEN;
+ }
+ if ( http->remaining ) {
+ http->remaining -= data_len;
+ if ( ( http->remaining == 0 ) &&
+ ( http->rx_state == HTTP_RX_DATA ) ) {
+ http_done ( http );
+ }
+ }
+ break;
+ case HTTP_RX_RESPONSE:
+ case HTTP_RX_HEADER:
+ case HTTP_RX_CHUNK_LEN:
+ case HTTP_RX_TRAILER:
+ /* In the other phases, buffer and process a
+ * line at a time
+ */
+ line_len = line_buffer ( &http->linebuf, iobuf->data,
+ iob_len ( iobuf ) );
+ if ( line_len < 0 ) {
+ rc = line_len;
+ DBGC ( http, "HTTP %p could not buffer line: "
+ "%s\n", http, strerror ( rc ) );
+ goto done;
+ }
+ iob_pull ( iobuf, line_len );
+ line = buffered_line ( &http->linebuf );
+ if ( line ) {
+ lh = &http_line_handlers[http->rx_state];
+ if ( ( rc = lh->rx ( http, line ) ) != 0 )
+ goto done;
+ }
+ break;
+ default:
+ assert ( 0 );
+ break;
+ }
+ }
+
+ done:
+ if ( rc )
+ http_close ( http, rc );
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Check HTTP socket flow control window
+ *
+ * @v http HTTP request
+ * @ret len Length of window
+ */
+static size_t http_socket_window ( struct http_request *http __unused ) {
+
+ /* Window is always open. This is to prevent TCP from
+ * stalling if our parent window is not currently open.
+ */
+ return ( ~( ( size_t ) 0 ) );
+}
+
+/**
+ * HTTP process
+ *
+ * @v http HTTP request
+ */
+static void http_step ( struct http_request *http ) {
+ const char *host = http->uri->host;
+ const char *user = http->uri->user;
+ const char *password =
+ ( http->uri->password ? http->uri->password : "" );
+ size_t user_pw_len = ( user ? ( strlen ( user ) + 1 /* ":" */ +
+ strlen ( password ) ) : 0 );
+ size_t user_pw_base64_len = base64_encoded_len ( user_pw_len );
+ int request_len = unparse_uri ( NULL, 0, http->uri,
+ URI_PATH_BIT | URI_QUERY_BIT );
+ struct {
+ uint8_t user_pw[ user_pw_len + 1 /* NUL */ ];
+ char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ];
+ char request[ request_len + 1 /* NUL */ ];
+ char range[48]; /* Enough for two 64-bit integers in decimal */
+ } *dynamic;
+ int partial;
+ int rc;
+
+ /* Do nothing if we have already transmitted the request */
+ if ( ! ( http->flags & HTTP_TX_PENDING ) )
+ return;
+
+ /* Do nothing until socket is ready */
+ if ( ! xfer_window ( &http->socket ) )
+ return;
+
+ /* Allocate dynamic storage */
+ dynamic = malloc ( sizeof ( *dynamic ) );
+ if ( ! dynamic ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+
+ /* Construct path?query request */
+ unparse_uri ( dynamic->request, sizeof ( dynamic->request ), http->uri,
+ URI_PATH_BIT | URI_QUERY_BIT );
+
+ /* Construct authorisation, if applicable */
+ if ( user ) {
+ /* Make "user:password" string from decoded fields */
+ snprintf ( ( ( char * ) dynamic->user_pw ),
+ sizeof ( dynamic->user_pw ), "%s:%s",
+ user, password );
+
+ /* Base64-encode the "user:password" string */
+ base64_encode ( dynamic->user_pw, user_pw_len,
+ dynamic->user_pw_base64 );
+ }
+
+ /* Force a HEAD request if we have nowhere to send any received data */
+ if ( ( xfer_window ( &http->xfer ) == 0 ) &&
+ ( http->rx_buffer == UNULL ) ) {
+ http->flags |= ( HTTP_HEAD_ONLY | HTTP_KEEPALIVE );
+ }
+
+ /* Determine type of request */
+ partial = ( http->partial_len != 0 );
+ snprintf ( dynamic->range, sizeof ( dynamic->range ),
+ "%zd-%zd", http->partial_start,
+ ( http->partial_start + http->partial_len - 1 ) );
+
+ /* Mark request as transmitted */
+ http->flags &= ~HTTP_TX_PENDING;
+
+ /* Send GET request */
+ if ( ( rc = xfer_printf ( &http->socket,
+ "%s %s%s HTTP/1.1\r\n"
+ "User-Agent: iPXE/" VERSION "\r\n"
+ "Host: %s%s%s\r\n"
+ "%s%s%s%s%s%s%s"
+ "\r\n",
+ ( ( http->flags & HTTP_HEAD_ONLY ) ?
+ "HEAD" : "GET" ),
+ ( http->uri->path ? "" : "/" ),
+ dynamic->request, host,
+ ( http->uri->port ?
+ ":" : "" ),
+ ( http->uri->port ?
+ http->uri->port : "" ),
+ ( ( http->flags & HTTP_KEEPALIVE ) ?
+ "Connection: Keep-Alive\r\n" : "" ),
+ ( partial ? "Range: bytes=" : "" ),
+ ( partial ? dynamic->range : "" ),
+ ( partial ? "\r\n" : "" ),
+ ( user ?
+ "Authorization: Basic " : "" ),
+ ( user ? dynamic->user_pw_base64 : "" ),
+ ( user ? "\r\n" : "" ) ) ) != 0 ) {
+ goto err_xfer;
+ }
+
+ err_xfer:
+ free ( dynamic );
+ err_alloc:
+ if ( rc != 0 )
+ http_close ( http, rc );
+}
+
+/**
+ * Check HTTP data transfer flow control window
+ *
+ * @v http HTTP request
+ * @ret len Length of window
+ */
+static size_t http_xfer_window ( struct http_request *http ) {
+
+ /* New block commands may be issued only when we are idle */
+ return ( ( http->rx_state == HTTP_RX_IDLE ) ? 1 : 0 );
+}
+
+/**
+ * Initiate HTTP partial read
+ *
+ * @v http HTTP request
+ * @v partial Partial transfer interface
+ * @v offset Starting offset
+ * @v buffer Data buffer
+ * @v len Length
+ * @ret rc Return status code
+ */
+static int http_partial_read ( struct http_request *http,
+ struct interface *partial,
+ size_t offset, userptr_t buffer, size_t len ) {
+
+ /* Sanity check */
+ if ( http_xfer_window ( http ) == 0 )
+ return -EBUSY;
+
+ /* Initialise partial transfer parameters */
+ http->rx_buffer = buffer;
+ http->partial_start = offset;
+ http->partial_len = len;
+ http->remaining = len;
+
+ /* Schedule request */
+ http->rx_state = HTTP_RX_RESPONSE;
+ http->flags = ( HTTP_TX_PENDING | HTTP_KEEPALIVE );
+ if ( ! len )
+ http->flags |= HTTP_HEAD_ONLY;
+ process_add ( &http->process );
+
+ /* Attach to parent interface and return */
+ intf_plug_plug ( &http->partial, partial );
+
+ return 0;
+}
+
+/**
+ * Issue HTTP block device read
+ *
+ * @v http HTTP request
+ * @v block Block data interface
+ * @v lba Starting logical block address
+ * @v count Number of blocks to transfer
+ * @v buffer Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int http_block_read ( struct http_request *http,
+ struct interface *block,
+ uint64_t lba, unsigned int count,
+ userptr_t buffer, size_t len __unused ) {
+
+ return http_partial_read ( http, block, ( lba * HTTP_BLKSIZE ),
+ buffer, ( count * HTTP_BLKSIZE ) );
+}
+
+/**
+ * Read HTTP block device capacity
+ *
+ * @v http HTTP request
+ * @v block Block data interface
+ * @ret rc Return status code
+ */
+static int http_block_read_capacity ( struct http_request *http,
+ struct interface *block ) {
+
+ return http_partial_read ( http, block, 0, 0, 0 );
+}
+
+/**
+ * Describe HTTP device in an ACPI table
+ *
+ * @v http HTTP request
+ * @v acpi ACPI table
+ * @v len Length of ACPI table
+ * @ret rc Return status code
+ */
+static int http_acpi_describe ( struct http_request *http,
+ struct acpi_description_header *acpi,
+ size_t len ) {
+
+ DBGC ( http, "HTTP %p cannot yet describe device in an ACPI table\n",
+ http );
+ ( void ) acpi;
+ ( void ) len;
+ return 0;
+}
+
+/** HTTP socket interface operations */
+static struct interface_operation http_socket_operations[] = {
+ INTF_OP ( xfer_window, struct http_request *, http_socket_window ),
+ INTF_OP ( xfer_deliver, struct http_request *, http_socket_deliver ),
+ INTF_OP ( xfer_window_changed, struct http_request *, http_step ),
+ INTF_OP ( intf_close, struct http_request *, http_close ),
+};
+
+/** HTTP socket interface descriptor */
+static struct interface_descriptor http_socket_desc =
+ INTF_DESC_PASSTHRU ( struct http_request, socket,
+ http_socket_operations, xfer );
+
+/** HTTP partial transfer interface operations */
+static struct interface_operation http_partial_operations[] = {
+ INTF_OP ( intf_close, struct http_request *, http_close ),
+};
+
+/** HTTP partial transfer interface descriptor */
+static struct interface_descriptor http_partial_desc =
+ INTF_DESC ( struct http_request, partial, http_partial_operations );
+
+/** HTTP data transfer interface operations */
+static struct interface_operation http_xfer_operations[] = {
+ INTF_OP ( xfer_window, struct http_request *, http_xfer_window ),
+ INTF_OP ( block_read, struct http_request *, http_block_read ),
+ INTF_OP ( block_read_capacity, struct http_request *,
+ http_block_read_capacity ),
+ INTF_OP ( intf_close, struct http_request *, http_close ),
+ INTF_OP ( acpi_describe, struct http_request *, http_acpi_describe ),
+};
+
+/** HTTP data transfer interface descriptor */
+static struct interface_descriptor http_xfer_desc =
+ INTF_DESC_PASSTHRU ( struct http_request, xfer,
+ http_xfer_operations, socket );
+
+/** HTTP process descriptor */
+static struct process_descriptor http_process_desc =
+ PROC_DESC_ONCE ( struct http_request, process, http_step );
+
+/**
+ * Initiate an HTTP connection, with optional filter
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @v default_port Default port number
+ * @v filter Filter to apply to socket, or NULL
+ * @ret rc Return status code
+ */
+int http_open_filter ( struct interface *xfer, struct uri *uri,
+ unsigned int default_port,
+ int ( * filter ) ( struct interface *xfer,
+ const char *name,
+ struct interface **next ) ) {
+ struct http_request *http;
+ struct sockaddr_tcpip server;
+ struct interface *socket;
+ int rc;
+
+ /* Sanity checks */
+ if ( ! uri->host )
+ return -EINVAL;
+
+ /* Allocate and populate HTTP structure */
+ http = zalloc ( sizeof ( *http ) );
+ if ( ! http )
+ return -ENOMEM;
+ ref_init ( &http->refcnt, http_free );
+ intf_init ( &http->xfer, &http_xfer_desc, &http->refcnt );
+ intf_init ( &http->partial, &http_partial_desc, &http->refcnt );
+ http->uri = uri_get ( uri );
+ intf_init ( &http->socket, &http_socket_desc, &http->refcnt );
+ process_init ( &http->process, &http_process_desc, &http->refcnt );
+ http->flags = HTTP_TX_PENDING;
+
+ /* Open socket */
+ memset ( &server, 0, sizeof ( server ) );
+ server.st_port = htons ( uri_port ( http->uri, default_port ) );
+ socket = &http->socket;
+ if ( filter ) {
+ if ( ( rc = filter ( socket, uri->host, &socket ) ) != 0 )
+ goto err;
+ }
+ if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM,
+ ( struct sockaddr * ) &server,
+ uri->host, NULL ) ) != 0 )
+ goto err;
+
+ /* Attach to parent interface, mortalise self, and return */
+ intf_plug_plug ( &http->xfer, xfer );
+ ref_put ( &http->refcnt );
+ return 0;
+
+ err:
+ DBGC ( http, "HTTP %p could not create request: %s\n",
+ http, strerror ( rc ) );
+ http_close ( http, rc );
+ ref_put ( &http->refcnt );
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/tcp/https.c b/src/VBox/Devices/PC/ipxe/src/net/tcp/https.c
new file mode 100644
index 00000000..805d108b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/tcp/https.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Secure Hyper Text Transfer Protocol (HTTPS)
+ *
+ */
+
+#include <stddef.h>
+#include <ipxe/open.h>
+#include <ipxe/tls.h>
+#include <ipxe/http.h>
+#include <ipxe/features.h>
+
+FEATURE ( FEATURE_PROTOCOL, "HTTPS", DHCP_EB_FEATURE_HTTPS, 1 );
+
+/**
+ * Initiate an HTTPS connection
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int https_open ( struct interface *xfer, struct uri *uri ) {
+ return http_open_filter ( xfer, uri, HTTPS_PORT, add_tls );
+}
+
+/** HTTPS URI opener */
+struct uri_opener https_uri_opener __uri_opener = {
+ .scheme = "https",
+ .open = https_open,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/tcp/iscsi.c b/src/VBox/Devices/PC/ipxe/src/net/tcp/iscsi.c
new file mode 100644
index 00000000..9eaf3cc5
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/tcp/iscsi.c
@@ -0,0 +1,2139 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/vsprintf.h>
+#include <ipxe/socket.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/uri.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/scsi.h>
+#include <ipxe/process.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/settings.h>
+#include <ipxe/features.h>
+#include <ipxe/base16.h>
+#include <ipxe/base64.h>
+#include <ipxe/ibft.h>
+#include <ipxe/iscsi.h>
+
+/** @file
+ *
+ * iSCSI protocol
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "iSCSI", DHCP_EB_FEATURE_ISCSI, 1 );
+
+/* Disambiguate the various error causes */
+#define EACCES_INCORRECT_TARGET_USERNAME \
+ __einfo_error ( EINFO_EACCES_INCORRECT_TARGET_USERNAME )
+#define EINFO_EACCES_INCORRECT_TARGET_USERNAME \
+ __einfo_uniqify ( EINFO_EACCES, 0x01, "Incorrect target username" )
+#define EACCES_INCORRECT_TARGET_PASSWORD \
+ __einfo_error ( EINFO_EACCES_INCORRECT_TARGET_PASSWORD )
+#define EINFO_EACCES_INCORRECT_TARGET_PASSWORD \
+ __einfo_uniqify ( EINFO_EACCES, 0x02, "Incorrect target password" )
+#define EINVAL_ROOT_PATH_TOO_SHORT \
+ __einfo_error ( EINFO_EINVAL_ROOT_PATH_TOO_SHORT )
+#define EINFO_EINVAL_ROOT_PATH_TOO_SHORT \
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, "Root path too short" )
+#define EINVAL_BAD_CREDENTIAL_MIX \
+ __einfo_error ( EINFO_EINVAL_BAD_CREDENTIAL_MIX )
+#define EINFO_EINVAL_BAD_CREDENTIAL_MIX \
+ __einfo_uniqify ( EINFO_EINVAL, 0x02, "Bad credential mix" )
+#define EINVAL_NO_ROOT_PATH \
+ __einfo_error ( EINFO_EINVAL_NO_ROOT_PATH )
+#define EINFO_EINVAL_NO_ROOT_PATH \
+ __einfo_uniqify ( EINFO_EINVAL, 0x03, "No root path" )
+#define EINVAL_NO_TARGET_IQN \
+ __einfo_error ( EINFO_EINVAL_NO_TARGET_IQN )
+#define EINFO_EINVAL_NO_TARGET_IQN \
+ __einfo_uniqify ( EINFO_EINVAL, 0x04, "No target IQN" )
+#define EINVAL_NO_INITIATOR_IQN \
+ __einfo_error ( EINFO_EINVAL_NO_INITIATOR_IQN )
+#define EINFO_EINVAL_NO_INITIATOR_IQN \
+ __einfo_uniqify ( EINFO_EINVAL, 0x05, "No initiator IQN" )
+#define EIO_TARGET_UNAVAILABLE \
+ __einfo_error ( EINFO_EIO_TARGET_UNAVAILABLE )
+#define EINFO_EIO_TARGET_UNAVAILABLE \
+ __einfo_uniqify ( EINFO_EIO, 0x01, "Target not currently operational" )
+#define EIO_TARGET_NO_RESOURCES \
+ __einfo_error ( EINFO_EIO_TARGET_NO_RESOURCES )
+#define EINFO_EIO_TARGET_NO_RESOURCES \
+ __einfo_uniqify ( EINFO_EIO, 0x02, "Target out of resources" )
+#define ENOTSUP_INITIATOR_STATUS \
+ __einfo_error ( EINFO_ENOTSUP_INITIATOR_STATUS )
+#define EINFO_ENOTSUP_INITIATOR_STATUS \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported initiator status" )
+#define ENOTSUP_OPCODE \
+ __einfo_error ( EINFO_ENOTSUP_OPCODE )
+#define EINFO_ENOTSUP_OPCODE \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported opcode" )
+#define ENOTSUP_DISCOVERY \
+ __einfo_error ( EINFO_ENOTSUP_DISCOVERY )
+#define EINFO_ENOTSUP_DISCOVERY \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x03, "Discovery not supported" )
+#define ENOTSUP_TARGET_STATUS \
+ __einfo_error ( EINFO_ENOTSUP_TARGET_STATUS )
+#define EINFO_ENOTSUP_TARGET_STATUS \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x04, "Unsupported target status" )
+#define ENOTSUP_NOP_IN \
+ __einfo_error ( EINFO_ENOTSUP_NOP_IN )
+#define EINFO_ENOTSUP_NOP_IN \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x05, "Unsupported NOP-In received" )
+#define EPERM_INITIATOR_AUTHENTICATION \
+ __einfo_error ( EINFO_EPERM_INITIATOR_AUTHENTICATION )
+#define EINFO_EPERM_INITIATOR_AUTHENTICATION \
+ __einfo_uniqify ( EINFO_EPERM, 0x01, "Initiator authentication failed" )
+#define EPERM_INITIATOR_AUTHORISATION \
+ __einfo_error ( EINFO_EPERM_INITIATOR_AUTHORISATION )
+#define EINFO_EPERM_INITIATOR_AUTHORISATION \
+ __einfo_uniqify ( EINFO_EPERM, 0x02, "Initiator not authorised" )
+#define EPROTO_INVALID_CHAP_ALGORITHM \
+ __einfo_error ( EINFO_EPROTO_INVALID_CHAP_ALGORITHM )
+#define EINFO_EPROTO_INVALID_CHAP_ALGORITHM \
+ __einfo_uniqify ( EINFO_EPROTO, 0x01, "Invalid CHAP algorithm" )
+#define EPROTO_INVALID_CHAP_IDENTIFIER \
+ __einfo_error ( EINFO_EPROTO_INVALID_CHAP_IDENTIFIER )
+#define EINFO_EPROTO_INVALID_CHAP_IDENTIFIER \
+ __einfo_uniqify ( EINFO_EPROTO, 0x02, "Invalid CHAP identifier" )
+#define EPROTO_INVALID_LARGE_BINARY \
+ __einfo_error ( EINFO_EPROTO_INVALID_LARGE_BINARY )
+#define EINFO_EPROTO_INVALID_LARGE_BINARY \
+ __einfo_uniqify ( EINFO_EPROTO, 0x03, "Invalid large binary" )
+#define EPROTO_INVALID_CHAP_RESPONSE \
+ __einfo_error ( EINFO_EPROTO_INVALID_CHAP_RESPONSE )
+#define EINFO_EPROTO_INVALID_CHAP_RESPONSE \
+ __einfo_uniqify ( EINFO_EPROTO, 0x04, "Invalid CHAP response" )
+#define EPROTO_INVALID_KEY_VALUE_PAIR \
+ __einfo_error ( EINFO_EPROTO_INVALID_KEY_VALUE_PAIR )
+#define EINFO_EPROTO_INVALID_KEY_VALUE_PAIR \
+ __einfo_uniqify ( EINFO_EPROTO, 0x05, "Invalid key/value pair" )
+#define EPROTO_VALUE_REJECTED \
+ __einfo_error ( EINFO_EPROTO_VALUE_REJECTED )
+#define EINFO_EPROTO_VALUE_REJECTED \
+ __einfo_uniqify ( EINFO_EPROTO, 0x06, "Parameter rejected" )
+
+static void iscsi_start_tx ( struct iscsi_session *iscsi );
+static void iscsi_start_login ( struct iscsi_session *iscsi );
+static void iscsi_start_data_out ( struct iscsi_session *iscsi,
+ unsigned int datasn );
+
+/**
+ * Finish receiving PDU data into buffer
+ *
+ * @v iscsi iSCSI session
+ */
+static void iscsi_rx_buffered_data_done ( struct iscsi_session *iscsi ) {
+ free ( iscsi->rx_buffer );
+ iscsi->rx_buffer = NULL;
+}
+
+/**
+ * Receive PDU data into buffer
+ *
+ * @v iscsi iSCSI session
+ * @v data Data to receive
+ * @v len Length of data
+ * @ret rc Return status code
+ *
+ * This can be used when the RX PDU type handler wishes to buffer up
+ * all received data and process the PDU as a single unit. The caller
+ * is repsonsible for calling iscsi_rx_buffered_data_done() after
+ * processing the data.
+ */
+static int iscsi_rx_buffered_data ( struct iscsi_session *iscsi,
+ const void *data, size_t len ) {
+
+ /* Allocate buffer on first call */
+ if ( ! iscsi->rx_buffer ) {
+ iscsi->rx_buffer = malloc ( iscsi->rx_len );
+ if ( ! iscsi->rx_buffer )
+ return -ENOMEM;
+ }
+
+ /* Copy data to buffer */
+ assert ( ( iscsi->rx_offset + len ) <= iscsi->rx_len );
+ memcpy ( ( iscsi->rx_buffer + iscsi->rx_offset ), data, len );
+
+ return 0;
+}
+
+/**
+ * Free iSCSI session
+ *
+ * @v refcnt Reference counter
+ */
+static void iscsi_free ( struct refcnt *refcnt ) {
+ struct iscsi_session *iscsi =
+ container_of ( refcnt, struct iscsi_session, refcnt );
+
+ free ( iscsi->initiator_iqn );
+ free ( iscsi->target_address );
+ free ( iscsi->target_iqn );
+ free ( iscsi->initiator_username );
+ free ( iscsi->initiator_password );
+ free ( iscsi->target_username );
+ free ( iscsi->target_password );
+ chap_finish ( &iscsi->chap );
+ iscsi_rx_buffered_data_done ( iscsi );
+ free ( iscsi->command );
+ free ( iscsi );
+}
+
+/**
+ * Shut down iSCSI interface
+ *
+ * @v iscsi iSCSI session
+ * @v rc Reason for close
+ */
+static void iscsi_close ( struct iscsi_session *iscsi, int rc ) {
+
+ /* A TCP graceful close is still an error from our point of view */
+ if ( rc == 0 )
+ rc = -ECONNRESET;
+
+ DBGC ( iscsi, "iSCSI %p closed: %s\n", iscsi, strerror ( rc ) );
+
+ /* Stop transmission process */
+ process_del ( &iscsi->process );
+
+ /* Shut down interfaces */
+ intf_shutdown ( &iscsi->socket, rc );
+ intf_shutdown ( &iscsi->control, rc );
+ intf_shutdown ( &iscsi->data, rc );
+}
+
+/**
+ * Assign new iSCSI initiator task tag
+ *
+ * @v iscsi iSCSI session
+ */
+static void iscsi_new_itt ( struct iscsi_session *iscsi ) {
+ static uint16_t itt_idx;
+
+ iscsi->itt = ( ISCSI_TAG_MAGIC | (++itt_idx) );
+}
+
+/**
+ * Open iSCSI transport-layer connection
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int iscsi_open_connection ( struct iscsi_session *iscsi ) {
+ struct sockaddr_tcpip target;
+ int rc;
+
+ assert ( iscsi->tx_state == ISCSI_TX_IDLE );
+ assert ( iscsi->rx_state == ISCSI_RX_BHS );
+ assert ( iscsi->rx_offset == 0 );
+
+ /* Open socket */
+ memset ( &target, 0, sizeof ( target ) );
+ target.st_port = htons ( iscsi->target_port );
+ if ( ( rc = xfer_open_named_socket ( &iscsi->socket, SOCK_STREAM,
+ ( struct sockaddr * ) &target,
+ iscsi->target_address,
+ NULL ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not open socket: %s\n",
+ iscsi, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Enter security negotiation phase */
+ iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
+ ISCSI_STATUS_STRINGS_SECURITY );
+ if ( iscsi->target_username )
+ iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_REQUIRED;
+
+ /* Assign new ISID */
+ iscsi->isid_iana_qual = ( random() & 0xffff );
+
+ /* Assign fresh initiator task tag */
+ iscsi_new_itt ( iscsi );
+
+ /* Initiate login */
+ iscsi_start_login ( iscsi );
+
+ return 0;
+}
+
+/**
+ * Close iSCSI transport-layer connection
+ *
+ * @v iscsi iSCSI session
+ * @v rc Reason for close
+ *
+ * Closes the transport-layer connection and resets the session state
+ * ready to attempt a fresh login.
+ */
+static void iscsi_close_connection ( struct iscsi_session *iscsi, int rc ) {
+
+ /* Close all data transfer interfaces */
+ intf_restart ( &iscsi->socket, rc );
+
+ /* Clear connection status */
+ iscsi->status = 0;
+
+ /* Reset TX and RX state machines */
+ iscsi->tx_state = ISCSI_TX_IDLE;
+ iscsi->rx_state = ISCSI_RX_BHS;
+ iscsi->rx_offset = 0;
+
+ /* Free any temporary dynamically allocated memory */
+ chap_finish ( &iscsi->chap );
+ iscsi_rx_buffered_data_done ( iscsi );
+}
+
+/**
+ * Mark iSCSI SCSI operation as complete
+ *
+ * @v iscsi iSCSI session
+ * @v rc Return status code
+ * @v rsp SCSI response, if any
+ *
+ * Note that iscsi_scsi_done() will not close the connection, and must
+ * therefore be called only when the internal state machines are in an
+ * appropriate state, otherwise bad things may happen on the next call
+ * to iscsi_scsi_command(). The general rule is to call
+ * iscsi_scsi_done() only at the end of receiving a PDU; at this point
+ * the TX and RX engines should both be idle.
+ */
+static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc,
+ struct scsi_rsp *rsp ) {
+ uint32_t itt = iscsi->itt;
+
+ assert ( iscsi->tx_state == ISCSI_TX_IDLE );
+
+ /* Clear command */
+ free ( iscsi->command );
+ iscsi->command = NULL;
+
+ /* Send SCSI response, if any */
+ scsi_response ( &iscsi->data, rsp );
+
+ /* Close SCSI command, if this is still the same command. (It
+ * is possible that the command interface has already been
+ * closed as a result of the SCSI response we sent.)
+ */
+ if ( iscsi->itt == itt )
+ intf_restart ( &iscsi->data, rc );
+}
+
+/****************************************************************************
+ *
+ * iSCSI SCSI command issuing
+ *
+ */
+
+/**
+ * Build iSCSI SCSI command BHS
+ *
+ * @v iscsi iSCSI session
+ *
+ * We don't currently support bidirectional commands (i.e. with both
+ * Data-In and Data-Out segments); these would require providing code
+ * to generate an AHS, and there doesn't seem to be any need for it at
+ * the moment.
+ */
+static void iscsi_start_command ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_scsi_command *command = &iscsi->tx_bhs.scsi_command;
+
+ assert ( ! ( iscsi->command->data_in && iscsi->command->data_out ) );
+
+ /* Construct BHS and initiate transmission */
+ iscsi_start_tx ( iscsi );
+ command->opcode = ISCSI_OPCODE_SCSI_COMMAND;
+ command->flags = ( ISCSI_FLAG_FINAL |
+ ISCSI_COMMAND_ATTR_SIMPLE );
+ if ( iscsi->command->data_in )
+ command->flags |= ISCSI_COMMAND_FLAG_READ;
+ if ( iscsi->command->data_out )
+ command->flags |= ISCSI_COMMAND_FLAG_WRITE;
+ /* lengths left as zero */
+ memcpy ( &command->lun, &iscsi->command->lun,
+ sizeof ( command->lun ) );
+ command->itt = htonl ( iscsi->itt );
+ command->exp_len = htonl ( iscsi->command->data_in_len |
+ iscsi->command->data_out_len );
+ command->cmdsn = htonl ( iscsi->cmdsn );
+ command->expstatsn = htonl ( iscsi->statsn + 1 );
+ memcpy ( &command->cdb, &iscsi->command->cdb, sizeof ( command->cdb ));
+ DBGC2 ( iscsi, "iSCSI %p start " SCSI_CDB_FORMAT " %s %#zx\n",
+ iscsi, SCSI_CDB_DATA ( command->cdb ),
+ ( iscsi->command->data_in ? "in" : "out" ),
+ ( iscsi->command->data_in ?
+ iscsi->command->data_in_len :
+ iscsi->command->data_out_len ) );
+}
+
+/**
+ * Receive data segment of an iSCSI SCSI response PDU
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ */
+static int iscsi_rx_scsi_response ( struct iscsi_session *iscsi,
+ const void *data, size_t len,
+ size_t remaining ) {
+ struct iscsi_bhs_scsi_response *response
+ = &iscsi->rx_bhs.scsi_response;
+ struct scsi_rsp rsp;
+ uint32_t residual_count;
+ int rc;
+
+ /* Buffer up the PDU data */
+ if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not buffer login response: %s\n",
+ iscsi, strerror ( rc ) );
+ return rc;
+ }
+ if ( remaining )
+ return 0;
+
+ /* Parse SCSI response and discard buffer */
+ memset ( &rsp, 0, sizeof ( rsp ) );
+ rsp.status = response->status;
+ residual_count = ntohl ( response->residual_count );
+ if ( response->flags & ISCSI_DATA_FLAG_OVERFLOW ) {
+ rsp.overrun = residual_count;
+ } else if ( response->flags & ISCSI_DATA_FLAG_UNDERFLOW ) {
+ rsp.overrun = -(residual_count);
+ }
+ if ( ISCSI_DATA_LEN ( response->lengths ) )
+ memcpy ( &rsp.sense, ( iscsi->rx_buffer + 2 ),
+ sizeof ( rsp.sense ) );
+ iscsi_rx_buffered_data_done ( iscsi );
+
+ /* Check for errors */
+ if ( response->response != ISCSI_RESPONSE_COMMAND_COMPLETE )
+ return -EIO;
+
+ /* Mark as completed */
+ iscsi_scsi_done ( iscsi, 0, &rsp );
+ return 0;
+}
+
+/**
+ * Receive data segment of an iSCSI data-in PDU
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ */
+static int iscsi_rx_data_in ( struct iscsi_session *iscsi,
+ const void *data, size_t len,
+ size_t remaining ) {
+ struct iscsi_bhs_data_in *data_in = &iscsi->rx_bhs.data_in;
+ unsigned long offset;
+
+ /* Copy data to data-in buffer */
+ offset = ntohl ( data_in->offset ) + iscsi->rx_offset;
+ assert ( iscsi->command != NULL );
+ assert ( iscsi->command->data_in );
+ assert ( ( offset + len ) <= iscsi->command->data_in_len );
+ copy_to_user ( iscsi->command->data_in, offset, data, len );
+
+ /* Wait for whole SCSI response to arrive */
+ if ( remaining )
+ return 0;
+
+ /* Mark as completed if status is present */
+ if ( data_in->flags & ISCSI_DATA_FLAG_STATUS ) {
+ assert ( ( offset + len ) == iscsi->command->data_in_len );
+ assert ( data_in->flags & ISCSI_FLAG_FINAL );
+ /* iSCSI cannot return an error status via a data-in */
+ iscsi_scsi_done ( iscsi, 0, NULL );
+ }
+
+ return 0;
+}
+
+/**
+ * Receive data segment of an iSCSI R2T PDU
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ */
+static int iscsi_rx_r2t ( struct iscsi_session *iscsi,
+ const void *data __unused, size_t len __unused,
+ size_t remaining __unused ) {
+ struct iscsi_bhs_r2t *r2t = &iscsi->rx_bhs.r2t;
+
+ /* Record transfer parameters and trigger first data-out */
+ iscsi->ttt = ntohl ( r2t->ttt );
+ iscsi->transfer_offset = ntohl ( r2t->offset );
+ iscsi->transfer_len = ntohl ( r2t->len );
+ iscsi_start_data_out ( iscsi, 0 );
+
+ return 0;
+}
+
+/**
+ * Build iSCSI data-out BHS
+ *
+ * @v iscsi iSCSI session
+ * @v datasn Data sequence number within the transfer
+ *
+ */
+static void iscsi_start_data_out ( struct iscsi_session *iscsi,
+ unsigned int datasn ) {
+ struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
+ unsigned long offset;
+ unsigned long remaining;
+ unsigned long len;
+
+ /* We always send 512-byte Data-Out PDUs; this removes the
+ * need to worry about the target's MaxRecvDataSegmentLength.
+ */
+ offset = datasn * 512;
+ remaining = iscsi->transfer_len - offset;
+ len = remaining;
+ if ( len > 512 )
+ len = 512;
+
+ /* Construct BHS and initiate transmission */
+ iscsi_start_tx ( iscsi );
+ data_out->opcode = ISCSI_OPCODE_DATA_OUT;
+ if ( len == remaining )
+ data_out->flags = ( ISCSI_FLAG_FINAL );
+ ISCSI_SET_LENGTHS ( data_out->lengths, 0, len );
+ data_out->lun = iscsi->command->lun;
+ data_out->itt = htonl ( iscsi->itt );
+ data_out->ttt = htonl ( iscsi->ttt );
+ data_out->expstatsn = htonl ( iscsi->statsn + 1 );
+ data_out->datasn = htonl ( datasn );
+ data_out->offset = htonl ( iscsi->transfer_offset + offset );
+ DBGC ( iscsi, "iSCSI %p start data out DataSN %#x len %#lx\n",
+ iscsi, datasn, len );
+}
+
+/**
+ * Complete iSCSI data-out PDU transmission
+ *
+ * @v iscsi iSCSI session
+ *
+ */
+static void iscsi_data_out_done ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
+
+ /* If we haven't reached the end of the sequence, start
+ * sending the next data-out PDU.
+ */
+ if ( ! ( data_out->flags & ISCSI_FLAG_FINAL ) )
+ iscsi_start_data_out ( iscsi, ntohl ( data_out->datasn ) + 1 );
+}
+
+/**
+ * Send iSCSI data-out data segment
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int iscsi_tx_data_out ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
+ struct io_buffer *iobuf;
+ unsigned long offset;
+ size_t len;
+ size_t pad_len;
+
+ offset = ntohl ( data_out->offset );
+ len = ISCSI_DATA_LEN ( data_out->lengths );
+ pad_len = ISCSI_DATA_PAD_LEN ( data_out->lengths );
+
+ assert ( iscsi->command != NULL );
+ assert ( iscsi->command->data_out );
+ assert ( ( offset + len ) <= iscsi->command->data_out_len );
+
+ iobuf = xfer_alloc_iob ( &iscsi->socket, ( len + pad_len ) );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ copy_from_user ( iob_put ( iobuf, len ),
+ iscsi->command->data_out, offset, len );
+ memset ( iob_put ( iobuf, pad_len ), 0, pad_len );
+
+ return xfer_deliver_iob ( &iscsi->socket, iobuf );
+}
+
+/**
+ * Receive data segment of an iSCSI NOP-In
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ */
+static int iscsi_rx_nop_in ( struct iscsi_session *iscsi,
+ const void *data __unused, size_t len __unused,
+ size_t remaining __unused ) {
+ struct iscsi_nop_in *nop_in = &iscsi->rx_bhs.nop_in;
+
+ DBGC2 ( iscsi, "iSCSI %p received NOP-In\n", iscsi );
+
+ /* We don't currently have the ability to respond to NOP-Ins
+ * sent as ping requests, but we can happily accept NOP-Ins
+ * sent merely to update CmdSN.
+ */
+ if ( nop_in->ttt != htonl ( ISCSI_TAG_RESERVED ) ) {
+ DBGC ( iscsi, "iSCSI %p received unsupported NOP-In with TTT "
+ "%08x\n", iscsi, ntohl ( nop_in->ttt ) );
+ return -ENOTSUP_NOP_IN;
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ *
+ * iSCSI login
+ *
+ */
+
+/**
+ * Build iSCSI login request strings
+ *
+ * @v iscsi iSCSI session
+ *
+ * These are the initial set of strings sent in the first login
+ * request PDU. We want the following settings:
+ *
+ * HeaderDigest=None
+ * DataDigest=None
+ * MaxConnections is irrelevant; we make only one connection anyway [4]
+ * InitialR2T=Yes [1]
+ * ImmediateData is irrelevant; we never send immediate data [4]
+ * MaxRecvDataSegmentLength=8192 (default; we don't care) [3]
+ * MaxBurstLength=262144 (default; we don't care) [3]
+ * FirstBurstLength=262144 (default; we don't care)
+ * DefaultTime2Wait=0 [2]
+ * DefaultTime2Retain=0 [2]
+ * MaxOutstandingR2T=1
+ * DataPDUInOrder=Yes
+ * DataSequenceInOrder=Yes
+ * ErrorRecoveryLevel=0
+ *
+ * [1] InitialR2T has an OR resolution function, so the target may
+ * force us to use it. We therefore simplify our logic by always
+ * using it.
+ *
+ * [2] These ensure that we can safely start a new task once we have
+ * reconnected after a failure, without having to manually tidy up
+ * after the old one.
+ *
+ * [3] We are quite happy to use the RFC-defined default values for
+ * these parameters, but some targets (notably OpenSolaris)
+ * incorrectly assume a default value of zero, so we explicitly
+ * specify the default values.
+ *
+ * [4] We are quite happy to use the RFC-defined default values for
+ * these parameters, but some targets (notably a QNAP TS-639Pro) fail
+ * unless they are supplied, so we explicitly specify the default
+ * values.
+ */
+static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi,
+ void *data, size_t len ) {
+ unsigned int used = 0;
+ const char *auth_method;
+
+ if ( iscsi->status & ISCSI_STATUS_STRINGS_SECURITY ) {
+ /* Default to allowing no authentication */
+ auth_method = "None";
+ /* If we have a credential to supply, permit CHAP */
+ if ( iscsi->initiator_username )
+ auth_method = "CHAP,None";
+ /* If we have a credential to check, force CHAP */
+ if ( iscsi->target_username )
+ auth_method = "CHAP";
+ used += ssnprintf ( data + used, len - used,
+ "InitiatorName=%s%c"
+ "TargetName=%s%c"
+ "SessionType=Normal%c"
+ "AuthMethod=%s%c",
+ iscsi->initiator_iqn, 0,
+ iscsi->target_iqn, 0, 0,
+ auth_method, 0 );
+ }
+
+ if ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_ALGORITHM ) {
+ used += ssnprintf ( data + used, len - used, "CHAP_A=5%c", 0 );
+ }
+
+ if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_RESPONSE ) ) {
+ char buf[ base16_encoded_len ( iscsi->chap.response_len ) + 1 ];
+ assert ( iscsi->initiator_username != NULL );
+ base16_encode ( iscsi->chap.response, iscsi->chap.response_len,
+ buf );
+ used += ssnprintf ( data + used, len - used,
+ "CHAP_N=%s%cCHAP_R=0x%s%c",
+ iscsi->initiator_username, 0, buf, 0 );
+ }
+
+ if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_CHALLENGE ) ) {
+ size_t challenge_len = ( sizeof ( iscsi->chap_challenge ) - 1 );
+ char buf[ base16_encoded_len ( challenge_len ) + 1 ];
+ base16_encode ( ( iscsi->chap_challenge + 1 ), challenge_len,
+ buf );
+ used += ssnprintf ( data + used, len - used,
+ "CHAP_I=%d%cCHAP_C=0x%s%c",
+ iscsi->chap_challenge[0], 0, buf, 0 );
+ }
+
+ if ( iscsi->status & ISCSI_STATUS_STRINGS_OPERATIONAL ) {
+ used += ssnprintf ( data + used, len - used,
+ "HeaderDigest=None%c"
+ "DataDigest=None%c"
+ "MaxConnections=1%c"
+ "InitialR2T=Yes%c"
+ "ImmediateData=No%c"
+ "MaxRecvDataSegmentLength=8192%c"
+ "MaxBurstLength=262144%c"
+ "DefaultTime2Wait=0%c"
+ "DefaultTime2Retain=0%c"
+ "MaxOutstandingR2T=1%c"
+ "DataPDUInOrder=Yes%c"
+ "DataSequenceInOrder=Yes%c"
+ "ErrorRecoveryLevel=0%c",
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
+ }
+
+ return used;
+}
+
+/**
+ * Build iSCSI login request BHS
+ *
+ * @v iscsi iSCSI session
+ */
+static void iscsi_start_login ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
+ int len;
+
+ switch ( iscsi->status & ISCSI_LOGIN_CSG_MASK ) {
+ case ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION:
+ DBGC ( iscsi, "iSCSI %p entering security negotiation\n",
+ iscsi );
+ break;
+ case ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION:
+ DBGC ( iscsi, "iSCSI %p entering operational negotiation\n",
+ iscsi );
+ break;
+ default:
+ assert ( 0 );
+ }
+
+ /* Construct BHS and initiate transmission */
+ iscsi_start_tx ( iscsi );
+ request->opcode = ( ISCSI_OPCODE_LOGIN_REQUEST |
+ ISCSI_FLAG_IMMEDIATE );
+ request->flags = ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) |
+ ISCSI_LOGIN_FLAG_TRANSITION );
+ /* version_max and version_min left as zero */
+ len = iscsi_build_login_request_strings ( iscsi, NULL, 0 );
+ ISCSI_SET_LENGTHS ( request->lengths, 0, len );
+ request->isid_iana_en = htonl ( ISCSI_ISID_IANA |
+ IANA_EN_FEN_SYSTEMS );
+ request->isid_iana_qual = htons ( iscsi->isid_iana_qual );
+ /* tsih left as zero */
+ request->itt = htonl ( iscsi->itt );
+ /* cid left as zero */
+ request->cmdsn = htonl ( iscsi->cmdsn );
+ request->expstatsn = htonl ( iscsi->statsn + 1 );
+}
+
+/**
+ * Complete iSCSI login request PDU transmission
+ *
+ * @v iscsi iSCSI session
+ *
+ */
+static void iscsi_login_request_done ( struct iscsi_session *iscsi ) {
+
+ /* Clear any "strings to send" flags */
+ iscsi->status &= ~ISCSI_STATUS_STRINGS_MASK;
+
+ /* Free any dynamically allocated storage used for login */
+ chap_finish ( &iscsi->chap );
+}
+
+/**
+ * Transmit data segment of an iSCSI login request PDU
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ *
+ * For login requests, the data segment consists of the login strings.
+ */
+static int iscsi_tx_login_request ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
+ struct io_buffer *iobuf;
+ size_t len;
+ size_t pad_len;
+
+ len = ISCSI_DATA_LEN ( request->lengths );
+ pad_len = ISCSI_DATA_PAD_LEN ( request->lengths );
+ iobuf = xfer_alloc_iob ( &iscsi->socket, ( len + pad_len ) );
+ if ( ! iobuf )
+ return -ENOMEM;
+ iob_put ( iobuf, len );
+ iscsi_build_login_request_strings ( iscsi, iobuf->data, len );
+ memset ( iob_put ( iobuf, pad_len ), 0, pad_len );
+
+ return xfer_deliver_iob ( &iscsi->socket, iobuf );
+}
+
+/**
+ * Calculate maximum length of decoded large binary value
+ *
+ * @v encoded Encoded large binary value
+ * @v max_raw_len Maximum length of raw data
+ */
+static inline size_t
+iscsi_large_binary_decoded_max_len ( const char *encoded ) {
+ return ( strlen ( encoded ) ); /* Decoding never expands data */
+}
+
+/**
+ * Decode large binary value
+ *
+ * @v encoded Encoded large binary value
+ * @v raw Raw data
+ * @ret len Length of raw data, or negative error
+ */
+static int iscsi_large_binary_decode ( const char *encoded, uint8_t *raw ) {
+
+ if ( encoded[0] != '0' )
+ return -EPROTO_INVALID_LARGE_BINARY;
+
+ switch ( encoded[1] ) {
+ case 'x' :
+ case 'X' :
+ return base16_decode ( ( encoded + 2 ), raw );
+ case 'b' :
+ case 'B' :
+ return base64_decode ( ( encoded + 2 ), raw );
+ default:
+ return -EPROTO_INVALID_LARGE_BINARY;
+ }
+}
+
+/**
+ * Handle iSCSI TargetAddress text value
+ *
+ * @v iscsi iSCSI session
+ * @v value TargetAddress value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_targetaddress_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+ char *separator;
+
+ DBGC ( iscsi, "iSCSI %p will redirect to %s\n", iscsi, value );
+
+ /* Replace target address */
+ free ( iscsi->target_address );
+ iscsi->target_address = strdup ( value );
+ if ( ! iscsi->target_address )
+ return -ENOMEM;
+
+ /* Replace target port */
+ iscsi->target_port = htons ( ISCSI_PORT );
+ separator = strchr ( iscsi->target_address, ':' );
+ if ( separator ) {
+ *separator = '\0';
+ iscsi->target_port = strtoul ( ( separator + 1 ), NULL, 0 );
+ }
+
+ return 0;
+}
+
+/**
+ * Handle iSCSI AuthMethod text value
+ *
+ * @v iscsi iSCSI session
+ * @v value AuthMethod value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_authmethod_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+
+ /* If server requests CHAP, send the CHAP_A string */
+ if ( strcmp ( value, "CHAP" ) == 0 ) {
+ DBGC ( iscsi, "iSCSI %p initiating CHAP authentication\n",
+ iscsi );
+ iscsi->status |= ( ISCSI_STATUS_STRINGS_CHAP_ALGORITHM |
+ ISCSI_STATUS_AUTH_FORWARD_REQUIRED );
+ }
+
+ return 0;
+}
+
+/**
+ * Handle iSCSI CHAP_A text value
+ *
+ * @v iscsi iSCSI session
+ * @v value CHAP_A value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_chap_a_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+
+ /* We only ever offer "5" (i.e. MD5) as an algorithm, so if
+ * the server responds with anything else it is a protocol
+ * violation.
+ */
+ if ( strcmp ( value, "5" ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p got invalid CHAP algorithm \"%s\"\n",
+ iscsi, value );
+ return -EPROTO_INVALID_CHAP_ALGORITHM;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle iSCSI CHAP_I text value
+ *
+ * @v iscsi iSCSI session
+ * @v value CHAP_I value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+ unsigned int identifier;
+ char *endp;
+ int rc;
+
+ /* The CHAP identifier is an integer value */
+ identifier = strtoul ( value, &endp, 0 );
+ if ( *endp != '\0' ) {
+ DBGC ( iscsi, "iSCSI %p saw invalid CHAP identifier \"%s\"\n",
+ iscsi, value );
+ return -EPROTO_INVALID_CHAP_IDENTIFIER;
+ }
+
+ /* Prepare for CHAP with MD5 */
+ chap_finish ( &iscsi->chap );
+ if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
+ iscsi, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Identifier and secret are the first two components of the
+ * challenge.
+ */
+ chap_set_identifier ( &iscsi->chap, identifier );
+ if ( iscsi->initiator_password ) {
+ chap_update ( &iscsi->chap, iscsi->initiator_password,
+ strlen ( iscsi->initiator_password ) );
+ }
+
+ return 0;
+}
+
+/**
+ * Handle iSCSI CHAP_C text value
+ *
+ * @v iscsi iSCSI session
+ * @v value CHAP_C value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+ uint8_t buf[ iscsi_large_binary_decoded_max_len ( value ) ];
+ unsigned int i;
+ size_t len;
+ int rc;
+
+ /* Process challenge */
+ rc = iscsi_large_binary_decode ( value, buf );
+ if ( rc < 0 ) {
+ DBGC ( iscsi, "iSCSI %p invalid CHAP challenge \"%s\": %s\n",
+ iscsi, value, strerror ( rc ) );
+ return rc;
+ }
+ len = rc;
+ chap_update ( &iscsi->chap, buf, len );
+
+ /* Build CHAP response */
+ DBGC ( iscsi, "iSCSI %p sending CHAP response\n", iscsi );
+ chap_respond ( &iscsi->chap );
+ iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_RESPONSE;
+
+ /* Send CHAP challenge, if applicable */
+ if ( iscsi->target_username ) {
+ iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_CHALLENGE;
+ /* Generate CHAP challenge data */
+ for ( i = 0 ; i < sizeof ( iscsi->chap_challenge ) ; i++ ) {
+ iscsi->chap_challenge[i] = random();
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Handle iSCSI CHAP_N text value
+ *
+ * @v iscsi iSCSI session
+ * @v value CHAP_N value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_chap_n_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+
+ /* The target username isn't actually involved at any point in
+ * the authentication process; it merely serves to identify
+ * which password the target is using to generate the CHAP
+ * response. We unnecessarily verify that the username is as
+ * expected, in order to provide mildly helpful diagnostics if
+ * the target is supplying the wrong username/password
+ * combination.
+ */
+ if ( iscsi->target_username &&
+ ( strcmp ( iscsi->target_username, value ) != 0 ) ) {
+ DBGC ( iscsi, "iSCSI %p target username \"%s\" incorrect "
+ "(wanted \"%s\")\n",
+ iscsi, value, iscsi->target_username );
+ return -EACCES_INCORRECT_TARGET_USERNAME;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle iSCSI CHAP_R text value
+ *
+ * @v iscsi iSCSI session
+ * @v value CHAP_R value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+ uint8_t buf[ iscsi_large_binary_decoded_max_len ( value ) ];
+ size_t len;
+ int rc;
+
+ /* Generate CHAP response for verification */
+ chap_finish ( &iscsi->chap );
+ if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
+ iscsi, strerror ( rc ) );
+ return rc;
+ }
+ chap_set_identifier ( &iscsi->chap, iscsi->chap_challenge[0] );
+ if ( iscsi->target_password ) {
+ chap_update ( &iscsi->chap, iscsi->target_password,
+ strlen ( iscsi->target_password ) );
+ }
+ chap_update ( &iscsi->chap, &iscsi->chap_challenge[1],
+ ( sizeof ( iscsi->chap_challenge ) - 1 ) );
+ chap_respond ( &iscsi->chap );
+
+ /* Process response */
+ rc = iscsi_large_binary_decode ( value, buf );
+ if ( rc < 0 ) {
+ DBGC ( iscsi, "iSCSI %p invalid CHAP response \"%s\": %s\n",
+ iscsi, value, strerror ( rc ) );
+ return rc;
+ }
+ len = rc;
+
+ /* Check CHAP response */
+ if ( len != iscsi->chap.response_len ) {
+ DBGC ( iscsi, "iSCSI %p invalid CHAP response length\n",
+ iscsi );
+ return -EPROTO_INVALID_CHAP_RESPONSE;
+ }
+ if ( memcmp ( buf, iscsi->chap.response, len ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p incorrect CHAP response \"%s\"\n",
+ iscsi, value );
+ return -EACCES_INCORRECT_TARGET_PASSWORD;
+ }
+
+ /* Mark session as authenticated */
+ iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_OK;
+
+ return 0;
+}
+
+/** An iSCSI text string that we want to handle */
+struct iscsi_string_type {
+ /** String key
+ *
+ * This is the portion preceding the "=" sign,
+ * e.g. "InitiatorName", "CHAP_A", etc.
+ */
+ const char *key;
+ /** Handle iSCSI string value
+ *
+ * @v iscsi iSCSI session
+ * @v value iSCSI string value
+ * @ret rc Return status code
+ */
+ int ( * handle ) ( struct iscsi_session *iscsi, const char *value );
+};
+
+/** iSCSI text strings that we want to handle */
+static struct iscsi_string_type iscsi_string_types[] = {
+ { "TargetAddress", iscsi_handle_targetaddress_value },
+ { "AuthMethod", iscsi_handle_authmethod_value },
+ { "CHAP_A", iscsi_handle_chap_a_value },
+ { "CHAP_I", iscsi_handle_chap_i_value },
+ { "CHAP_C", iscsi_handle_chap_c_value },
+ { "CHAP_N", iscsi_handle_chap_n_value },
+ { "CHAP_R", iscsi_handle_chap_r_value },
+ { NULL, NULL }
+};
+
+/**
+ * Handle iSCSI string
+ *
+ * @v iscsi iSCSI session
+ * @v string iSCSI string (in "key=value" format)
+ * @ret rc Return status code
+ */
+static int iscsi_handle_string ( struct iscsi_session *iscsi,
+ const char *string ) {
+ struct iscsi_string_type *type;
+ const char *separator;
+ const char *value;
+ size_t key_len;
+ int rc;
+
+ /* Find separator */
+ separator = strchr ( string, '=' );
+ if ( ! separator ) {
+ DBGC ( iscsi, "iSCSI %p malformed string %s\n",
+ iscsi, string );
+ return -EPROTO_INVALID_KEY_VALUE_PAIR;
+ }
+ key_len = ( separator - string );
+ value = ( separator + 1 );
+
+ /* Check for rejections. Since we send only non-rejectable
+ * values, any rejection is a fatal protocol error.
+ */
+ if ( strcmp ( value, "Reject" ) == 0 ) {
+ DBGC ( iscsi, "iSCSI %p rejection: %s\n", iscsi, string );
+ return -EPROTO_VALUE_REJECTED;
+ }
+
+ /* Handle key/value pair */
+ for ( type = iscsi_string_types ; type->key ; type++ ) {
+ if ( strncmp ( string, type->key, key_len ) != 0 )
+ continue;
+ DBGC ( iscsi, "iSCSI %p handling %s\n", iscsi, string );
+ if ( ( rc = type->handle ( iscsi, value ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not handle %s: %s\n",
+ iscsi, string, strerror ( rc ) );
+ return rc;
+ }
+ return 0;
+ }
+ DBGC ( iscsi, "iSCSI %p ignoring %s\n", iscsi, string );
+ return 0;
+}
+
+/**
+ * Handle iSCSI strings
+ *
+ * @v iscsi iSCSI session
+ * @v string iSCSI string buffer
+ * @v len Length of string buffer
+ * @ret rc Return status code
+ */
+static int iscsi_handle_strings ( struct iscsi_session *iscsi,
+ const char *strings, size_t len ) {
+ size_t string_len;
+ int rc;
+
+ /* Handle each string in turn, taking care not to overrun the
+ * data buffer in case of badly-terminated data.
+ */
+ while ( 1 ) {
+ string_len = ( strnlen ( strings, len ) + 1 );
+ if ( string_len > len )
+ break;
+ if ( ( rc = iscsi_handle_string ( iscsi, strings ) ) != 0 )
+ return rc;
+ strings += string_len;
+ len -= string_len;
+ }
+ return 0;
+}
+
+/**
+ * Convert iSCSI response status to return status code
+ *
+ * @v status_class iSCSI status class
+ * @v status_detail iSCSI status detail
+ * @ret rc Return status code
+ */
+static int iscsi_status_to_rc ( unsigned int status_class,
+ unsigned int status_detail ) {
+ switch ( status_class ) {
+ case ISCSI_STATUS_INITIATOR_ERROR :
+ switch ( status_detail ) {
+ case ISCSI_STATUS_INITIATOR_ERROR_AUTHENTICATION :
+ return -EPERM_INITIATOR_AUTHENTICATION;
+ case ISCSI_STATUS_INITIATOR_ERROR_AUTHORISATION :
+ return -EPERM_INITIATOR_AUTHORISATION;
+ case ISCSI_STATUS_INITIATOR_ERROR_NOT_FOUND :
+ case ISCSI_STATUS_INITIATOR_ERROR_REMOVED :
+ return -ENODEV;
+ default :
+ return -ENOTSUP_INITIATOR_STATUS;
+ }
+ case ISCSI_STATUS_TARGET_ERROR :
+ switch ( status_detail ) {
+ case ISCSI_STATUS_TARGET_ERROR_UNAVAILABLE:
+ return -EIO_TARGET_UNAVAILABLE;
+ case ISCSI_STATUS_TARGET_ERROR_NO_RESOURCES:
+ return -EIO_TARGET_NO_RESOURCES;
+ default:
+ return -ENOTSUP_TARGET_STATUS;
+ }
+ default :
+ return -EINVAL;
+ }
+}
+
+/**
+ * Receive data segment of an iSCSI login response PDU
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ */
+static int iscsi_rx_login_response ( struct iscsi_session *iscsi,
+ const void *data, size_t len,
+ size_t remaining ) {
+ struct iscsi_bhs_login_response *response
+ = &iscsi->rx_bhs.login_response;
+ int rc;
+
+ /* Buffer up the PDU data */
+ if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not buffer login response: %s\n",
+ iscsi, strerror ( rc ) );
+ return rc;
+ }
+ if ( remaining )
+ return 0;
+
+ /* Process string data and discard string buffer */
+ if ( ( rc = iscsi_handle_strings ( iscsi, iscsi->rx_buffer,
+ iscsi->rx_len ) ) != 0 )
+ return rc;
+ iscsi_rx_buffered_data_done ( iscsi );
+
+ /* Check for login redirection */
+ if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
+ DBGC ( iscsi, "iSCSI %p redirecting to new server\n", iscsi );
+ iscsi_close_connection ( iscsi, 0 );
+ if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not redirect: %s\n ",
+ iscsi, strerror ( rc ) );
+ return rc;
+ }
+ return 0;
+ }
+
+ /* Check for fatal errors */
+ if ( response->status_class != 0 ) {
+ DBGC ( iscsi, "iSCSI login failure: class %02x detail %02x\n",
+ response->status_class, response->status_detail );
+ rc = iscsi_status_to_rc ( response->status_class,
+ response->status_detail );
+ return rc;
+ }
+
+ /* Handle login transitions */
+ if ( response->flags & ISCSI_LOGIN_FLAG_TRANSITION ) {
+ iscsi->status &= ~( ISCSI_STATUS_PHASE_MASK |
+ ISCSI_STATUS_STRINGS_MASK );
+ switch ( response->flags & ISCSI_LOGIN_NSG_MASK ) {
+ case ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION:
+ iscsi->status |=
+ ( ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE |
+ ISCSI_STATUS_STRINGS_OPERATIONAL );
+ break;
+ case ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE:
+ iscsi->status |= ISCSI_STATUS_FULL_FEATURE_PHASE;
+ break;
+ default:
+ DBGC ( iscsi, "iSCSI %p got invalid response flags "
+ "%02x\n", iscsi, response->flags );
+ return -EIO;
+ }
+ }
+
+ /* Send next login request PDU if we haven't reached the full
+ * feature phase yet.
+ */
+ if ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) !=
+ ISCSI_STATUS_FULL_FEATURE_PHASE ) {
+ iscsi_start_login ( iscsi );
+ return 0;
+ }
+
+ /* Check that target authentication was successful (if required) */
+ if ( ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) &&
+ ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_OK ) ) {
+ DBGC ( iscsi, "iSCSI %p nefarious target tried to bypass "
+ "authentication\n", iscsi );
+ return -EPROTO;
+ }
+
+ /* Notify SCSI layer of window change */
+ DBGC ( iscsi, "iSCSI %p entering full feature phase\n", iscsi );
+ xfer_window_changed ( &iscsi->control );
+
+ return 0;
+}
+
+/****************************************************************************
+ *
+ * iSCSI to socket interface
+ *
+ */
+
+/**
+ * Pause TX engine
+ *
+ * @v iscsi iSCSI session
+ */
+static void iscsi_tx_pause ( struct iscsi_session *iscsi ) {
+ process_del ( &iscsi->process );
+}
+
+/**
+ * Resume TX engine
+ *
+ * @v iscsi iSCSI session
+ */
+static void iscsi_tx_resume ( struct iscsi_session *iscsi ) {
+ process_add ( &iscsi->process );
+}
+
+/**
+ * Start up a new TX PDU
+ *
+ * @v iscsi iSCSI session
+ *
+ * This initiates the process of sending a new PDU. Only one PDU may
+ * be in transit at any one time.
+ */
+static void iscsi_start_tx ( struct iscsi_session *iscsi ) {
+
+ assert ( iscsi->tx_state == ISCSI_TX_IDLE );
+
+ /* Initialise TX BHS */
+ memset ( &iscsi->tx_bhs, 0, sizeof ( iscsi->tx_bhs ) );
+
+ /* Flag TX engine to start transmitting */
+ iscsi->tx_state = ISCSI_TX_BHS;
+
+ /* Start transmission process */
+ iscsi_tx_resume ( iscsi );
+}
+
+/**
+ * Transmit nothing
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int iscsi_tx_nothing ( struct iscsi_session *iscsi __unused ) {
+ return 0;
+}
+
+/**
+ * Transmit basic header segment of an iSCSI PDU
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int iscsi_tx_bhs ( struct iscsi_session *iscsi ) {
+ return xfer_deliver_raw ( &iscsi->socket, &iscsi->tx_bhs,
+ sizeof ( iscsi->tx_bhs ) );
+}
+
+/**
+ * Transmit data segment of an iSCSI PDU
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ *
+ * Handle transmission of part of a PDU data segment. iscsi::tx_bhs
+ * will be valid when this is called.
+ */
+static int iscsi_tx_data ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
+
+ switch ( common->opcode & ISCSI_OPCODE_MASK ) {
+ case ISCSI_OPCODE_DATA_OUT:
+ return iscsi_tx_data_out ( iscsi );
+ case ISCSI_OPCODE_LOGIN_REQUEST:
+ return iscsi_tx_login_request ( iscsi );
+ default:
+ /* Nothing to send in other states */
+ return 0;
+ }
+}
+
+/**
+ * Complete iSCSI PDU transmission
+ *
+ * @v iscsi iSCSI session
+ *
+ * Called when a PDU has been completely transmitted and the TX state
+ * machine is about to enter the idle state. iscsi::tx_bhs will be
+ * valid for the just-completed PDU when this is called.
+ */
+static void iscsi_tx_done ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
+
+ /* Stop transmission process */
+ iscsi_tx_pause ( iscsi );
+
+ switch ( common->opcode & ISCSI_OPCODE_MASK ) {
+ case ISCSI_OPCODE_DATA_OUT:
+ iscsi_data_out_done ( iscsi );
+ case ISCSI_OPCODE_LOGIN_REQUEST:
+ iscsi_login_request_done ( iscsi );
+ default:
+ /* No action */
+ break;
+ }
+}
+
+/**
+ * Transmit iSCSI PDU
+ *
+ * @v iscsi iSCSI session
+ * @v buf Temporary data buffer
+ * @v len Length of temporary data buffer
+ *
+ * Constructs data to be sent for the current TX state
+ */
+static void iscsi_tx_step ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
+ int ( * tx ) ( struct iscsi_session *iscsi );
+ enum iscsi_tx_state next_state;
+ size_t tx_len;
+ int rc;
+
+ /* Select fragment to transmit */
+ while ( 1 ) {
+ switch ( iscsi->tx_state ) {
+ case ISCSI_TX_BHS:
+ tx = iscsi_tx_bhs;
+ tx_len = sizeof ( iscsi->tx_bhs );
+ next_state = ISCSI_TX_AHS;
+ break;
+ case ISCSI_TX_AHS:
+ tx = iscsi_tx_nothing;
+ tx_len = 0;
+ next_state = ISCSI_TX_DATA;
+ break;
+ case ISCSI_TX_DATA:
+ tx = iscsi_tx_data;
+ tx_len = ISCSI_DATA_LEN ( common->lengths );
+ next_state = ISCSI_TX_IDLE;
+ break;
+ case ISCSI_TX_IDLE:
+ /* Nothing to do; pause processing */
+ iscsi_tx_pause ( iscsi );
+ return;
+ default:
+ assert ( 0 );
+ return;
+ }
+
+ /* Check for window availability, if needed */
+ if ( tx_len && ( xfer_window ( &iscsi->socket ) == 0 ) ) {
+ /* Cannot transmit at this point; pause
+ * processing and wait for window to reopen
+ */
+ iscsi_tx_pause ( iscsi );
+ return;
+ }
+
+ /* Transmit data */
+ if ( ( rc = tx ( iscsi ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not transmit: %s\n",
+ iscsi, strerror ( rc ) );
+ /* Transmission errors are fatal */
+ iscsi_close ( iscsi, rc );
+ return;
+ }
+
+ /* Move to next state */
+ iscsi->tx_state = next_state;
+
+ /* If we have moved to the idle state, mark
+ * transmission as complete
+ */
+ if ( iscsi->tx_state == ISCSI_TX_IDLE )
+ iscsi_tx_done ( iscsi );
+ }
+}
+
+/** iSCSI TX process descriptor */
+static struct process_descriptor iscsi_process_desc =
+ PROC_DESC ( struct iscsi_session, process, iscsi_tx_step );
+
+/**
+ * Receive basic header segment of an iSCSI PDU
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ *
+ * This fills in iscsi::rx_bhs with the data from the BHS portion of
+ * the received PDU.
+ */
+static int iscsi_rx_bhs ( struct iscsi_session *iscsi, const void *data,
+ size_t len, size_t remaining __unused ) {
+ memcpy ( &iscsi->rx_bhs.bytes[iscsi->rx_offset], data, len );
+ if ( ( iscsi->rx_offset + len ) >= sizeof ( iscsi->rx_bhs ) ) {
+ DBGC2 ( iscsi, "iSCSI %p received PDU opcode %#x len %#x\n",
+ iscsi, iscsi->rx_bhs.common.opcode,
+ ISCSI_DATA_LEN ( iscsi->rx_bhs.common.lengths ) );
+ }
+ return 0;
+}
+
+/**
+ * Discard portion of an iSCSI PDU.
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ *
+ * This discards data from a portion of a received PDU.
+ */
+static int iscsi_rx_discard ( struct iscsi_session *iscsi __unused,
+ const void *data __unused, size_t len __unused,
+ size_t remaining __unused ) {
+ /* Do nothing */
+ return 0;
+}
+
+/**
+ * Receive data segment of an iSCSI PDU
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ *
+ * Handle processing of part of a PDU data segment. iscsi::rx_bhs
+ * will be valid when this is called.
+ */
+static int iscsi_rx_data ( struct iscsi_session *iscsi, const void *data,
+ size_t len, size_t remaining ) {
+ struct iscsi_bhs_common_response *response
+ = &iscsi->rx_bhs.common_response;
+
+ /* Update cmdsn and statsn */
+ iscsi->cmdsn = ntohl ( response->expcmdsn );
+ iscsi->statsn = ntohl ( response->statsn );
+
+ switch ( response->opcode & ISCSI_OPCODE_MASK ) {
+ case ISCSI_OPCODE_LOGIN_RESPONSE:
+ return iscsi_rx_login_response ( iscsi, data, len, remaining );
+ case ISCSI_OPCODE_SCSI_RESPONSE:
+ return iscsi_rx_scsi_response ( iscsi, data, len, remaining );
+ case ISCSI_OPCODE_DATA_IN:
+ return iscsi_rx_data_in ( iscsi, data, len, remaining );
+ case ISCSI_OPCODE_R2T:
+ return iscsi_rx_r2t ( iscsi, data, len, remaining );
+ case ISCSI_OPCODE_NOP_IN:
+ return iscsi_rx_nop_in ( iscsi, data, len, remaining );
+ default:
+ if ( remaining )
+ return 0;
+ DBGC ( iscsi, "iSCSI %p unknown opcode %02x\n", iscsi,
+ response->opcode );
+ return -ENOTSUP_OPCODE;
+ }
+}
+
+/**
+ * Receive new data
+ *
+ * @v iscsi iSCSI session
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ *
+ * This handles received PDUs. The receive strategy is to fill in
+ * iscsi::rx_bhs with the contents of the BHS portion of the PDU,
+ * throw away any AHS portion, and then process each part of the data
+ * portion as it arrives. The data processing routine therefore
+ * always has a full copy of the BHS available, even for portions of
+ * the data in different packets to the BHS.
+ */
+static int iscsi_socket_deliver ( struct iscsi_session *iscsi,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ struct iscsi_bhs_common *common = &iscsi->rx_bhs.common;
+ int ( * rx ) ( struct iscsi_session *iscsi, const void *data,
+ size_t len, size_t remaining );
+ enum iscsi_rx_state next_state;
+ size_t frag_len;
+ size_t remaining;
+ int rc;
+
+ while ( 1 ) {
+ switch ( iscsi->rx_state ) {
+ case ISCSI_RX_BHS:
+ rx = iscsi_rx_bhs;
+ iscsi->rx_len = sizeof ( iscsi->rx_bhs );
+ next_state = ISCSI_RX_AHS;
+ break;
+ case ISCSI_RX_AHS:
+ rx = iscsi_rx_discard;
+ iscsi->rx_len = 4 * ISCSI_AHS_LEN ( common->lengths );
+ next_state = ISCSI_RX_DATA;
+ break;
+ case ISCSI_RX_DATA:
+ rx = iscsi_rx_data;
+ iscsi->rx_len = ISCSI_DATA_LEN ( common->lengths );
+ next_state = ISCSI_RX_DATA_PADDING;
+ break;
+ case ISCSI_RX_DATA_PADDING:
+ rx = iscsi_rx_discard;
+ iscsi->rx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
+ next_state = ISCSI_RX_BHS;
+ break;
+ default:
+ assert ( 0 );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ frag_len = iscsi->rx_len - iscsi->rx_offset;
+ if ( frag_len > iob_len ( iobuf ) )
+ frag_len = iob_len ( iobuf );
+ remaining = iscsi->rx_len - iscsi->rx_offset - frag_len;
+ if ( ( rc = rx ( iscsi, iobuf->data, frag_len,
+ remaining ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not process received "
+ "data: %s\n", iscsi, strerror ( rc ) );
+ goto done;
+ }
+
+ iscsi->rx_offset += frag_len;
+ iob_pull ( iobuf, frag_len );
+
+ /* If all the data for this state has not yet been
+ * received, stay in this state for now.
+ */
+ if ( iscsi->rx_offset != iscsi->rx_len ) {
+ rc = 0;
+ goto done;
+ }
+
+ iscsi->rx_state = next_state;
+ iscsi->rx_offset = 0;
+ }
+
+ done:
+ /* Free I/O buffer */
+ free_iob ( iobuf );
+
+ /* Destroy session on error */
+ if ( rc != 0 )
+ iscsi_close ( iscsi, rc );
+
+ return rc;
+}
+
+/**
+ * Handle redirection event
+ *
+ * @v iscsi iSCSI session
+ * @v type Location type
+ * @v args Remaining arguments depend upon location type
+ * @ret rc Return status code
+ */
+static int iscsi_vredirect ( struct iscsi_session *iscsi, int type,
+ va_list args ) {
+ va_list tmp;
+ struct sockaddr *peer;
+
+ /* Intercept redirects to a LOCATION_SOCKET and record the IP
+ * address for the iBFT. This is a bit of a hack, but avoids
+ * inventing an ioctl()-style call to retrieve the socket
+ * address from a data-xfer interface.
+ */
+ if ( type == LOCATION_SOCKET ) {
+ va_copy ( tmp, args );
+ ( void ) va_arg ( tmp, int ); /* Discard "semantics" */
+ peer = va_arg ( tmp, struct sockaddr * );
+ memcpy ( &iscsi->target_sockaddr, peer,
+ sizeof ( iscsi->target_sockaddr ) );
+ va_end ( tmp );
+ }
+
+ return xfer_vreopen ( &iscsi->socket, type, args );
+}
+
+/** iSCSI socket interface operations */
+static struct interface_operation iscsi_socket_operations[] = {
+ INTF_OP ( xfer_deliver, struct iscsi_session *, iscsi_socket_deliver ),
+ INTF_OP ( xfer_window_changed, struct iscsi_session *,
+ iscsi_tx_resume ),
+ INTF_OP ( xfer_vredirect, struct iscsi_session *, iscsi_vredirect ),
+ INTF_OP ( intf_close, struct iscsi_session *, iscsi_close ),
+};
+
+/** iSCSI socket interface descriptor */
+static struct interface_descriptor iscsi_socket_desc =
+ INTF_DESC ( struct iscsi_session, socket, iscsi_socket_operations );
+
+/****************************************************************************
+ *
+ * iSCSI command issuing
+ *
+ */
+
+/**
+ * Check iSCSI flow-control window
+ *
+ * @v iscsi iSCSI session
+ * @ret len Length of window
+ */
+static size_t iscsi_scsi_window ( struct iscsi_session *iscsi ) {
+
+ if ( ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) ==
+ ISCSI_STATUS_FULL_FEATURE_PHASE ) &&
+ ( iscsi->command == NULL ) ) {
+ /* We cannot handle concurrent commands */
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/**
+ * Issue iSCSI SCSI command
+ *
+ * @v iscsi iSCSI session
+ * @v parent Parent interface
+ * @v command SCSI command
+ * @ret tag Command tag, or negative error
+ */
+static int iscsi_scsi_command ( struct iscsi_session *iscsi,
+ struct interface *parent,
+ struct scsi_cmd *command ) {
+
+ /* This iSCSI implementation cannot handle multiple concurrent
+ * commands or commands arriving before login is complete.
+ */
+ if ( iscsi_scsi_window ( iscsi ) == 0 ) {
+ DBGC ( iscsi, "iSCSI %p cannot handle concurrent commands\n",
+ iscsi );
+ return -EOPNOTSUPP;
+ }
+
+ /* Store command */
+ iscsi->command = malloc ( sizeof ( *command ) );
+ if ( ! iscsi->command )
+ return -ENOMEM;
+ memcpy ( iscsi->command, command, sizeof ( *command ) );
+
+ /* Assign new ITT */
+ iscsi_new_itt ( iscsi );
+
+ /* Start sending command */
+ iscsi_start_command ( iscsi );
+
+ /* Attach to parent interface and return */
+ intf_plug_plug ( &iscsi->data, parent );
+ return iscsi->itt;
+}
+
+/** iSCSI SCSI command-issuing interface operations */
+static struct interface_operation iscsi_control_op[] = {
+ INTF_OP ( scsi_command, struct iscsi_session *, iscsi_scsi_command ),
+ INTF_OP ( xfer_window, struct iscsi_session *, iscsi_scsi_window ),
+ INTF_OP ( intf_close, struct iscsi_session *, iscsi_close ),
+ INTF_OP ( acpi_describe, struct iscsi_session *, ibft_describe ),
+};
+
+/** iSCSI SCSI command-issuing interface descriptor */
+static struct interface_descriptor iscsi_control_desc =
+ INTF_DESC ( struct iscsi_session, control, iscsi_control_op );
+
+/**
+ * Close iSCSI command
+ *
+ * @v iscsi iSCSI session
+ * @v rc Reason for close
+ */
+static void iscsi_command_close ( struct iscsi_session *iscsi, int rc ) {
+
+ /* Restart interface */
+ intf_restart ( &iscsi->data, rc );
+
+ /* Treat unsolicited command closures mid-command as fatal,
+ * because we have no code to handle partially-completed PDUs.
+ */
+ if ( iscsi->command != NULL )
+ iscsi_close ( iscsi, ( ( rc == 0 ) ? -ECANCELED : rc ) );
+}
+
+/** iSCSI SCSI command interface operations */
+static struct interface_operation iscsi_data_op[] = {
+ INTF_OP ( intf_close, struct iscsi_session *, iscsi_command_close ),
+};
+
+/** iSCSI SCSI command interface descriptor */
+static struct interface_descriptor iscsi_data_desc =
+ INTF_DESC ( struct iscsi_session, data, iscsi_data_op );
+
+/****************************************************************************
+ *
+ * Instantiator
+ *
+ */
+
+/** iSCSI root path components (as per RFC4173) */
+enum iscsi_root_path_component {
+ RP_SERVERNAME = 0,
+ RP_PROTOCOL,
+ RP_PORT,
+ RP_LUN,
+ RP_TARGETNAME,
+ NUM_RP_COMPONENTS
+};
+
+/** iSCSI initiator IQN setting */
+struct setting initiator_iqn_setting __setting ( SETTING_SANBOOT_EXTRA ) = {
+ .name = "initiator-iqn",
+ .description = "iSCSI initiator name",
+ .tag = DHCP_ISCSI_INITIATOR_IQN,
+ .type = &setting_type_string,
+};
+
+/** iSCSI reverse username setting */
+struct setting reverse_username_setting __setting ( SETTING_AUTH_EXTRA ) = {
+ .name = "reverse-username",
+ .description = "Reverse user name",
+ .tag = DHCP_EB_REVERSE_USERNAME,
+ .type = &setting_type_string,
+};
+
+/** iSCSI reverse password setting */
+struct setting reverse_password_setting __setting ( SETTING_AUTH_EXTRA ) = {
+ .name = "reverse-password",
+ .description = "Reverse password",
+ .tag = DHCP_EB_REVERSE_PASSWORD,
+ .type = &setting_type_string,
+};
+
+/**
+ * Parse iSCSI root path
+ *
+ * @v iscsi iSCSI session
+ * @v root_path iSCSI root path (as per RFC4173)
+ * @ret rc Return status code
+ */
+static int iscsi_parse_root_path ( struct iscsi_session *iscsi,
+ const char *root_path ) {
+ char rp_copy[ strlen ( root_path ) + 1 ];
+ char *rp_comp[NUM_RP_COMPONENTS];
+ char *rp = rp_copy;
+ int i = 0;
+ int rc;
+
+ /* Split root path into component parts */
+ strcpy ( rp_copy, root_path );
+ while ( 1 ) {
+ rp_comp[i++] = rp;
+ if ( i == NUM_RP_COMPONENTS )
+ break;
+ for ( ; *rp != ':' ; rp++ ) {
+ if ( ! *rp ) {
+ DBGC ( iscsi, "iSCSI %p root path \"%s\" "
+ "too short\n", iscsi, root_path );
+ return -EINVAL_ROOT_PATH_TOO_SHORT;
+ }
+ }
+ *(rp++) = '\0';
+ }
+
+ /* Use root path components to configure iSCSI session */
+ iscsi->target_address = strdup ( rp_comp[RP_SERVERNAME] );
+ if ( ! iscsi->target_address )
+ return -ENOMEM;
+ iscsi->target_port = strtoul ( rp_comp[RP_PORT], NULL, 10 );
+ if ( ! iscsi->target_port )
+ iscsi->target_port = ISCSI_PORT;
+ if ( ( rc = scsi_parse_lun ( rp_comp[RP_LUN], &iscsi->lun ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p invalid LUN \"%s\"\n",
+ iscsi, rp_comp[RP_LUN] );
+ return rc;
+ }
+ iscsi->target_iqn = strdup ( rp_comp[RP_TARGETNAME] );
+ if ( ! iscsi->target_iqn )
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * Fetch iSCSI settings
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int iscsi_fetch_settings ( struct iscsi_session *iscsi ) {
+ char *hostname;
+ union uuid uuid;
+ int len;
+
+ /* Fetch relevant settings. Don't worry about freeing on
+ * error, since iscsi_free() will take care of that anyway.
+ */
+ if ( ( len = fetch_string_setting_copy ( NULL, &username_setting,
+ &iscsi->initiator_username ) ) < 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not fetch username: %s\n",
+ iscsi, strerror ( len ) );
+ return len;
+ }
+ if ( ( len = fetch_string_setting_copy ( NULL, &password_setting,
+ &iscsi->initiator_password ) ) < 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not fetch password: %s\n",
+ iscsi, strerror ( len ) );
+ return len;
+ }
+ if ( ( len = fetch_string_setting_copy( NULL, &reverse_username_setting,
+ &iscsi->target_username ) ) < 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not fetch reverse username: %s\n",
+ iscsi, strerror ( len ) );
+ return len;
+ }
+ if ( ( len = fetch_string_setting_copy( NULL, &reverse_password_setting,
+ &iscsi->target_password ) ) < 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not fetch reverse password: %s\n",
+ iscsi, strerror ( len ) );
+ return len;
+ }
+
+ /* Find a suitable initiator name */
+ if ( ( len = fetch_string_setting_copy ( NULL, &initiator_iqn_setting,
+ &iscsi->initiator_iqn ) ) < 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not fetch initiator IQN: %s\n",
+ iscsi, strerror ( len ) );
+ return len;
+ }
+ if ( iscsi->initiator_iqn )
+ return 0;
+ if ( ( len = fetch_string_setting_copy ( NULL, &hostname_setting,
+ &hostname ) ) < 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not fetch hostname: %s\n",
+ iscsi, strerror ( len ) );
+ return len;
+ }
+ if ( hostname ) {
+ len = asprintf ( &iscsi->initiator_iqn,
+ ISCSI_DEFAULT_IQN_PREFIX ":%s", hostname );
+ free ( hostname );
+ if ( len < 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not allocate initiator "
+ "IQN\n", iscsi );
+ return -ENOMEM;
+ }
+ assert ( iscsi->initiator_iqn );
+ return 0;
+ }
+ if ( ( len = fetch_uuid_setting ( NULL, &uuid_setting, &uuid ) ) < 0 ) {
+ DBGC ( iscsi, "iSCSI %p has no suitable initiator IQN\n",
+ iscsi );
+ return -EINVAL_NO_INITIATOR_IQN;
+ }
+ if ( ( len = asprintf ( &iscsi->initiator_iqn,
+ ISCSI_DEFAULT_IQN_PREFIX ":%s",
+ uuid_ntoa ( &uuid ) ) ) < 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not allocate initiator IQN\n",
+ iscsi );
+ return -ENOMEM;
+ }
+ assert ( iscsi->initiator_iqn );
+
+ return 0;
+}
+
+
+/**
+ * Check iSCSI authentication details
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int iscsi_check_auth ( struct iscsi_session *iscsi ) {
+
+ /* Check for invalid authentication combinations */
+ if ( ( /* Initiator username without password (or vice-versa) */
+ ( !! iscsi->initiator_username ) ^
+ ( !! iscsi->initiator_password ) ) ||
+ ( /* Target username without password (or vice-versa) */
+ ( !! iscsi->target_username ) ^
+ ( !! iscsi->target_password ) ) ||
+ ( /* Target (reverse) without initiator (forward) */
+ ( iscsi->target_username &&
+ ( ! iscsi->initiator_username ) ) ) ) {
+ DBGC ( iscsi, "iSCSI %p invalid credentials: initiator "
+ "%sname,%spw, target %sname,%spw\n", iscsi,
+ ( iscsi->initiator_username ? "" : "no " ),
+ ( iscsi->initiator_password ? "" : "no " ),
+ ( iscsi->target_username ? "" : "no " ),
+ ( iscsi->target_password ? "" : "no " ) );
+ return -EINVAL_BAD_CREDENTIAL_MIX;
+ }
+
+ return 0;
+}
+
+/**
+ * Open iSCSI URI
+ *
+ * @v parent Parent interface
+ * @v uri URI
+ * @ret rc Return status code
+ */
+static int iscsi_open ( struct interface *parent, struct uri *uri ) {
+ struct iscsi_session *iscsi;
+ int rc;
+
+ /* Sanity check */
+ if ( ! uri->opaque ) {
+ rc = -EINVAL_NO_ROOT_PATH;
+ goto err_sanity_uri;
+ }
+
+ /* Allocate and initialise structure */
+ iscsi = zalloc ( sizeof ( *iscsi ) );
+ if ( ! iscsi ) {
+ rc = -ENOMEM;
+ goto err_zalloc;
+ }
+ ref_init ( &iscsi->refcnt, iscsi_free );
+ intf_init ( &iscsi->control, &iscsi_control_desc, &iscsi->refcnt );
+ intf_init ( &iscsi->data, &iscsi_data_desc, &iscsi->refcnt );
+ intf_init ( &iscsi->socket, &iscsi_socket_desc, &iscsi->refcnt );
+ process_init_stopped ( &iscsi->process, &iscsi_process_desc,
+ &iscsi->refcnt );
+
+ /* Parse root path */
+ if ( ( rc = iscsi_parse_root_path ( iscsi, uri->opaque ) ) != 0 )
+ goto err_parse_root_path;
+ /* Set fields not specified by root path */
+ if ( ( rc = iscsi_fetch_settings ( iscsi ) ) != 0 )
+ goto err_fetch_settings;
+ /* Validate authentication */
+ if ( ( rc = iscsi_check_auth ( iscsi ) ) != 0 )
+ goto err_check_auth;
+
+ /* Sanity checks */
+ if ( ! iscsi->target_address ) {
+ DBGC ( iscsi, "iSCSI %p does not yet support discovery\n",
+ iscsi );
+ rc = -ENOTSUP_DISCOVERY;
+ goto err_sanity_address;
+ }
+ if ( ! iscsi->target_iqn ) {
+ DBGC ( iscsi, "iSCSI %p no target address supplied in %s\n",
+ iscsi, uri->opaque );
+ rc = -EINVAL_NO_TARGET_IQN;
+ goto err_sanity_iqn;
+ }
+ DBGC ( iscsi, "iSCSI %p initiator %s\n",iscsi, iscsi->initiator_iqn );
+ DBGC ( iscsi, "iSCSI %p target %s %s\n",
+ iscsi, iscsi->target_address, iscsi->target_iqn );
+
+ /* Open socket */
+ if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 )
+ goto err_open_connection;
+
+ /* Attach SCSI device to parent interface */
+ if ( ( rc = scsi_open ( parent, &iscsi->control,
+ &iscsi->lun ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not create SCSI device: %s\n",
+ iscsi, strerror ( rc ) );
+ goto err_scsi_open;
+ }
+
+ /* Mortalise self, and return */
+ ref_put ( &iscsi->refcnt );
+ return 0;
+
+ err_scsi_open:
+ err_open_connection:
+ err_sanity_iqn:
+ err_sanity_address:
+ err_check_auth:
+ err_fetch_settings:
+ err_parse_root_path:
+ iscsi_close ( iscsi, rc );
+ ref_put ( &iscsi->refcnt );
+ err_zalloc:
+ err_sanity_uri:
+ return rc;
+}
+
+/** iSCSI URI opener */
+struct uri_opener iscsi_uri_opener __uri_opener = {
+ .scheme = "iscsi",
+ .open = iscsi_open,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/tcp/syslogs.c b/src/VBox/Devices/PC/ipxe/src/net/tcp/syslogs.c
new file mode 100644
index 00000000..e7480e56
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/tcp/syslogs.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Encrypted syslog protocol
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <byteswap.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/settings.h>
+#include <ipxe/console.h>
+#include <ipxe/lineconsole.h>
+#include <ipxe/tls.h>
+#include <ipxe/syslog.h>
+#include <config/console.h>
+
+/* Set default console usage if applicable */
+#if ! ( defined ( CONSOLE_SYSLOGS ) && CONSOLE_EXPLICIT ( CONSOLE_SYSLOGS ) )
+#undef CONSOLE_SYSLOGS
+#define CONSOLE_SYSLOGS ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_TUI )
+#endif
+
+struct console_driver syslogs_console __console_driver;
+
+/** The encrypted syslog server */
+static struct sockaddr_tcpip logserver = {
+ .st_family = AF_INET,
+ .st_port = htons ( SYSLOG_PORT ),
+};
+
+/**
+ * Handle encrypted syslog TLS interface close
+ *
+ * @v intf Interface
+ * @v rc Reason for close
+ */
+static void syslogs_close ( struct interface *intf __unused, int rc ) {
+
+ DBG ( "SYSLOGS console disconnected: %s\n", strerror ( rc ) );
+}
+
+/**
+ * Handle encrypted syslog TLS interface window change
+ *
+ * @v intf Interface
+ */
+static void syslogs_window_changed ( struct interface *intf ) {
+
+ /* Mark console as enabled when window first opens, indicating
+ * that TLS negotiation is complete. (Do not disable console
+ * when window closes again, since TCP will close the window
+ * whenever there is unACKed data.)
+ */
+ if ( xfer_window ( intf ) ) {
+ if ( syslogs_console.disabled )
+ DBG ( "SYSLOGS console connected\n" );
+ syslogs_console.disabled = 0;
+ }
+}
+
+/** Encrypted syslog TLS interface operations */
+static struct interface_operation syslogs_operations[] = {
+ INTF_OP ( xfer_window_changed, struct interface *,
+ syslogs_window_changed ),
+ INTF_OP ( intf_close, struct interface *, syslogs_close ),
+};
+
+/** Encrypted syslog TLS interface descriptor */
+static struct interface_descriptor syslogs_desc =
+ INTF_DESC_PURE ( syslogs_operations );
+
+/** The encrypted syslog TLS interface */
+static struct interface syslogs = INTF_INIT ( syslogs_desc );
+
+/******************************************************************************
+ *
+ * Console driver
+ *
+ ******************************************************************************
+ */
+
+/** Encrypted syslog line buffer */
+static char syslogs_buffer[SYSLOG_BUFSIZE];
+
+/** Encrypted syslog severity */
+static unsigned int syslogs_severity = SYSLOG_DEFAULT_SEVERITY;
+
+/**
+ * Handle ANSI set encrypted syslog priority (private sequence)
+ *
+ * @v count Parameter count
+ * @v params List of graphic rendition aspects
+ */
+static void syslogs_handle_priority ( unsigned int count __unused,
+ int params[] ) {
+ if ( params[0] >= 0 ) {
+ syslogs_severity = params[0];
+ } else {
+ syslogs_severity = SYSLOG_DEFAULT_SEVERITY;
+ }
+}
+
+/** Encrypted syslog ANSI escape sequence handlers */
+static struct ansiesc_handler syslogs_handlers[] = {
+ { ANSIESC_LOG_PRIORITY, syslogs_handle_priority },
+ { 0, NULL }
+};
+
+/** Encrypted syslog line console */
+static struct line_console syslogs_line = {
+ .buffer = syslogs_buffer,
+ .len = sizeof ( syslogs_buffer ),
+ .ctx = {
+ .handlers = syslogs_handlers,
+ },
+};
+
+/** Encrypted syslog recursion marker */
+static int syslogs_entered;
+
+/**
+ * Print a character to encrypted syslog console
+ *
+ * @v character Character to be printed
+ */
+static void syslogs_putchar ( int character ) {
+ int rc;
+
+ /* Ignore if we are already mid-logging */
+ if ( syslogs_entered )
+ return;
+
+ /* Fill line buffer */
+ if ( line_putchar ( &syslogs_line, character ) == 0 )
+ return;
+
+ /* Guard against re-entry */
+ syslogs_entered = 1;
+
+ /* Send log message */
+ if ( ( rc = xfer_printf ( &syslogs, "<%d>ipxe: %s\n",
+ SYSLOG_PRIORITY ( SYSLOG_DEFAULT_FACILITY,
+ syslogs_severity ),
+ syslogs_buffer ) ) != 0 ) {
+ DBG ( "SYSLOGS could not send log message: %s\n",
+ strerror ( rc ) );
+ }
+
+ /* Clear re-entry flag */
+ syslogs_entered = 0;
+}
+
+/** Encrypted syslog console driver */
+struct console_driver syslogs_console __console_driver = {
+ .putchar = syslogs_putchar,
+ .disabled = 1,
+ .usage = CONSOLE_SYSLOGS,
+};
+
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** Encrypted syslog server setting */
+struct setting syslogs_setting __setting ( SETTING_MISC ) = {
+ .name = "syslogs",
+ .description = "Encrypted syslog server",
+ .tag = DHCP_EB_SYSLOGS_SERVER,
+ .type = &setting_type_string,
+};
+
+/**
+ * Apply encrypted syslog settings
+ *
+ * @ret rc Return status code
+ */
+static int apply_syslogs_settings ( void ) {
+ static char *old_server;
+ char *server;
+ struct interface *socket;
+ int len;
+ int rc;
+
+ /* Fetch log server */
+ len = fetch_string_setting_copy ( NULL, &syslogs_setting, &server );
+ if ( len < 0 ) {
+ rc = len;
+ goto err_fetch_server;
+ }
+
+ /* Do nothing unless log server has changed */
+ if ( ( ( server == NULL ) && ( old_server == NULL ) ) ||
+ ( ( server != NULL ) && ( old_server != NULL ) &&
+ ( strcmp ( server, old_server ) == 0 ) ) ) {
+ rc = 0;
+ goto out_no_change;
+ }
+ free ( old_server );
+ old_server = NULL;
+
+ /* Reset encrypted syslog connection */
+ syslogs_console.disabled = 1;
+ intf_restart ( &syslogs, 0 );
+
+ /* Do nothing unless we have a log server */
+ if ( ! server ) {
+ DBG ( "SYSLOGS has no log server\n" );
+ rc = 0;
+ goto out_no_server;
+ }
+
+ /* Add TLS filter */
+ if ( ( rc = add_tls ( &syslogs, server, &socket ) ) != 0 ) {
+ DBG ( "SYSLOGS cannot create TLS filter: %s\n",
+ strerror ( rc ) );
+ goto err_add_tls;
+ }
+
+ /* Connect to log server */
+ if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM,
+ (( struct sockaddr *) &logserver ),
+ server, NULL ) ) != 0 ) {
+ DBG ( "SYSLOGS cannot connect to log server: %s\n",
+ strerror ( rc ) );
+ goto err_open_named_socket;
+ }
+ DBG ( "SYSLOGS using log server %s\n", server );
+
+ /* Record log server */
+ old_server = server;
+ server = NULL;
+
+ /* Success */
+ rc = 0;
+
+ err_open_named_socket:
+ err_add_tls:
+ out_no_server:
+ out_no_change:
+ free ( server );
+ err_fetch_server:
+ return rc;
+}
+
+/** Encrypted syslog settings applicator */
+struct settings_applicator syslogs_applicator __settings_applicator = {
+ .apply = apply_syslogs_settings,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/tcpip.c b/src/VBox/Devices/PC/ipxe/src/net/tcpip.c
new file mode 100644
index 00000000..4451bf11
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/tcpip.c
@@ -0,0 +1,135 @@
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/tables.h>
+#include <ipxe/tcpip.h>
+
+/** @file
+ *
+ * Transport-network layer interface
+ *
+ * This file contains functions and utilities for the
+ * TCP/IP transport-network layer interface
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** Process a received TCP/IP packet
+ *
+ * @v iobuf I/O buffer
+ * @v tcpip_proto Transport-layer protocol number
+ * @v st_src Partially-filled source address
+ * @v st_dest Partially-filled destination address
+ * @v pshdr_csum Pseudo-header checksum
+ * @ret rc Return status code
+ *
+ * This function expects a transport-layer segment from the network
+ * layer. The network layer should fill in as much as it can of the
+ * source and destination addresses (i.e. it should fill in the
+ * address family and the network-layer addresses, but leave the ports
+ * and the rest of the structures as zero).
+ */
+int tcpip_rx ( struct io_buffer *iobuf, uint8_t tcpip_proto,
+ struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest,
+ uint16_t pshdr_csum ) {
+ struct tcpip_protocol *tcpip;
+
+ /* Hand off packet to the appropriate transport-layer protocol */
+ for_each_table_entry ( tcpip, TCPIP_PROTOCOLS ) {
+ if ( tcpip->tcpip_proto == tcpip_proto ) {
+ DBG ( "TCP/IP received %s packet\n", tcpip->name );
+ return tcpip->rx ( iobuf, st_src, st_dest, pshdr_csum );
+ }
+ }
+
+ DBG ( "Unrecognised TCP/IP protocol %d\n", tcpip_proto );
+ free_iob ( iobuf );
+ return -EPROTONOSUPPORT;
+}
+
+/** Transmit a TCP/IP packet
+ *
+ * @v iobuf I/O buffer
+ * @v tcpip_protocol Transport-layer protocol
+ * @v st_src Source address, or NULL to use route default
+ * @v st_dest Destination address
+ * @v netdev Network device to use if no route found, or NULL
+ * @v trans_csum Transport-layer checksum to complete, or NULL
+ * @ret rc Return status code
+ */
+int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
+ struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest,
+ struct net_device *netdev, uint16_t *trans_csum ) {
+ struct tcpip_net_protocol *tcpip_net;
+
+ /* Hand off packet to the appropriate network-layer protocol */
+ for_each_table_entry ( tcpip_net, TCPIP_NET_PROTOCOLS ) {
+ if ( tcpip_net->sa_family == st_dest->st_family ) {
+ DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
+ return tcpip_net->tx ( iobuf, tcpip_protocol, st_src,
+ st_dest, netdev, trans_csum );
+ }
+ }
+
+ DBG ( "Unrecognised TCP/IP address family %d\n", st_dest->st_family );
+ free_iob ( iobuf );
+ return -EAFNOSUPPORT;
+}
+
+/**
+ * Calculate continued TCP/IP checkum
+ *
+ * @v partial Checksum of already-summed data, in network byte order
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret cksum Updated checksum, in network byte order
+ *
+ * Calculates a TCP/IP-style 16-bit checksum over the data block. The
+ * checksum is returned in network byte order.
+ *
+ * This function may be used to add new data to an existing checksum.
+ * The function assumes that both the old data and the new data start
+ * on even byte offsets; if this is not the case then you will need to
+ * byte-swap either the input partial checksum, the output checksum,
+ * or both. Deciding which to swap is left as an exercise for the
+ * interested reader.
+ */
+uint16_t tcpip_continue_chksum ( uint16_t partial, const void *data,
+ size_t len ) {
+ unsigned int cksum = ( ( ~partial ) & 0xffff );
+ unsigned int value;
+ unsigned int i;
+
+ for ( i = 0 ; i < len ; i++ ) {
+ value = * ( ( uint8_t * ) data + i );
+ if ( i & 1 ) {
+ /* Odd bytes: swap on little-endian systems */
+ value = be16_to_cpu ( value );
+ } else {
+ /* Even bytes: swap on big-endian systems */
+ value = le16_to_cpu ( value );
+ }
+ cksum += value;
+ if ( cksum > 0xffff )
+ cksum -= 0xffff;
+ }
+
+ return ( ~cksum );
+}
+
+/**
+ * Calculate TCP/IP checkum
+ *
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret cksum Checksum, in network byte order
+ *
+ * Calculates a TCP/IP-style 16-bit checksum over the data block. The
+ * checksum is returned in network byte order.
+ */
+uint16_t tcpip_chksum ( const void *data, size_t len ) {
+ return tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, data, len );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/tls.c b/src/VBox/Devices/PC/ipxe/src/net/tls.c
new file mode 100644
index 00000000..97e013d7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/tls.c
@@ -0,0 +1,2409 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Transport Layer Security Protocol
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/hmac.h>
+#include <ipxe/md5.h>
+#include <ipxe/sha1.h>
+#include <ipxe/sha256.h>
+#include <ipxe/aes.h>
+#include <ipxe/rsa.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/x509.h>
+#include <ipxe/clientcert.h>
+#include <ipxe/rbg.h>
+#include <ipxe/validator.h>
+#include <ipxe/tls.h>
+
+/* Disambiguate the various error causes */
+#define EACCES_WRONG_NAME \
+ __einfo_error ( EINFO_EACCES_WRONG_NAME )
+#define EINFO_EACCES_WRONG_NAME \
+ __einfo_uniqify ( EINFO_EACCES, 0x02, "Incorrect server name" )
+
+static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
+ const void *data, size_t len );
+static void tls_clear_cipher ( struct tls_session *tls,
+ struct tls_cipherspec *cipherspec );
+
+/******************************************************************************
+ *
+ * Utility functions
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Extract 24-bit field value
+ *
+ * @v field24 24-bit field
+ * @ret value Field value
+ *
+ * TLS uses 24-bit integers in several places, which are awkward to
+ * parse in C.
+ */
+static inline __attribute__ (( always_inline )) unsigned long
+tls_uint24 ( const uint8_t field24[3] ) {
+ const uint32_t *field32 __attribute__ (( may_alias )) =
+ ( ( const void * ) field24 );
+ return ( be32_to_cpu ( *field32 ) >> 8 );
+}
+
+/**
+ * Set 24-bit field value
+ *
+ * @v field24 24-bit field
+ * @v value Field value
+ *
+ * The field must be pre-zeroed.
+ */
+static void tls_set_uint24 ( uint8_t field24[3], unsigned long value ) {
+ uint32_t *field32 __attribute__ (( may_alias )) =
+ ( ( void * ) field24 );
+ *field32 |= cpu_to_be32 ( value << 8 );
+}
+
+/**
+ * Determine if TLS session is ready for application data
+ *
+ * @v tls TLS session
+ * @ret is_ready TLS session is ready
+ */
+static int tls_ready ( struct tls_session *tls ) {
+ return ( tls->client_finished && tls->server_finished );
+}
+
+/******************************************************************************
+ *
+ * Hybrid MD5+SHA1 hash as used by TLSv1.1 and earlier
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Initialise MD5+SHA1 algorithm
+ *
+ * @v ctx MD5+SHA1 context
+ */
+static void md5_sha1_init ( void *ctx ) {
+ struct md5_sha1_context *context = ctx;
+
+ digest_init ( &md5_algorithm, context->md5 );
+ digest_init ( &sha1_algorithm, context->sha1 );
+}
+
+/**
+ * Accumulate data with MD5+SHA1 algorithm
+ *
+ * @v ctx MD5+SHA1 context
+ * @v data Data
+ * @v len Length of data
+ */
+static void md5_sha1_update ( void *ctx, const void *data, size_t len ) {
+ struct md5_sha1_context *context = ctx;
+
+ digest_update ( &md5_algorithm, context->md5, data, len );
+ digest_update ( &sha1_algorithm, context->sha1, data, len );
+}
+
+/**
+ * Generate MD5+SHA1 digest
+ *
+ * @v ctx MD5+SHA1 context
+ * @v out Output buffer
+ */
+static void md5_sha1_final ( void *ctx, void *out ) {
+ struct md5_sha1_context *context = ctx;
+ struct md5_sha1_digest *digest = out;
+
+ digest_final ( &md5_algorithm, context->md5, digest->md5 );
+ digest_final ( &sha1_algorithm, context->sha1, digest->sha1 );
+}
+
+/** Hybrid MD5+SHA1 digest algorithm */
+static struct digest_algorithm md5_sha1_algorithm = {
+ .name = "md5+sha1",
+ .ctxsize = sizeof ( struct md5_sha1_context ),
+ .blocksize = 0, /* Not applicable */
+ .digestsize = sizeof ( struct md5_sha1_digest ),
+ .init = md5_sha1_init,
+ .update = md5_sha1_update,
+ .final = md5_sha1_final,
+};
+
+/** RSA digestInfo prefix for MD5+SHA1 algorithm */
+struct rsa_digestinfo_prefix rsa_md5_sha1_prefix __rsa_digestinfo_prefix = {
+ .digest = &md5_sha1_algorithm,
+ .data = NULL, /* MD5+SHA1 signatures have no digestInfo */
+ .len = 0,
+};
+
+/******************************************************************************
+ *
+ * Cleanup functions
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Free TLS session
+ *
+ * @v refcnt Reference counter
+ */
+static void free_tls ( struct refcnt *refcnt ) {
+ struct tls_session *tls =
+ container_of ( refcnt, struct tls_session, refcnt );
+
+ /* Free dynamically-allocated resources */
+ tls_clear_cipher ( tls, &tls->tx_cipherspec );
+ tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
+ tls_clear_cipher ( tls, &tls->rx_cipherspec );
+ tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
+ free ( tls->rx_data );
+ x509_chain_put ( tls->chain );
+
+ /* Free TLS structure itself */
+ free ( tls );
+}
+
+/**
+ * Finish with TLS session
+ *
+ * @v tls TLS session
+ * @v rc Status code
+ */
+static void tls_close ( struct tls_session *tls, int rc ) {
+
+ /* Remove process */
+ process_del ( &tls->process );
+
+ /* Close all interfaces */
+ intf_shutdown ( &tls->cipherstream, rc );
+ intf_shutdown ( &tls->plainstream, rc );
+ intf_shutdown ( &tls->validator, rc );
+}
+
+/******************************************************************************
+ *
+ * Random number generation
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Generate random data
+ *
+ * @v tls TLS session
+ * @v data Buffer to fill
+ * @v len Length of buffer
+ * @ret rc Return status code
+ */
+static int tls_generate_random ( struct tls_session *tls,
+ void *data, size_t len ) {
+ int rc;
+
+ /* Generate random bits with no additional input and without
+ * prediction resistance
+ */
+ if ( ( rc = rbg_generate ( NULL, 0, 0, data, len ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not generate random data: %s\n",
+ tls, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Update HMAC with a list of ( data, len ) pairs
+ *
+ * @v digest Hash function to use
+ * @v digest_ctx Digest context
+ * @v args ( data, len ) pairs of data, terminated by NULL
+ */
+static void tls_hmac_update_va ( struct digest_algorithm *digest,
+ void *digest_ctx, va_list args ) {
+ void *data;
+ size_t len;
+
+ while ( ( data = va_arg ( args, void * ) ) ) {
+ len = va_arg ( args, size_t );
+ hmac_update ( digest, digest_ctx, data, len );
+ }
+}
+
+/**
+ * Generate secure pseudo-random data using a single hash function
+ *
+ * @v tls TLS session
+ * @v digest Hash function to use
+ * @v secret Secret
+ * @v secret_len Length of secret
+ * @v out Output buffer
+ * @v out_len Length of output buffer
+ * @v seeds ( data, len ) pairs of seed data, terminated by NULL
+ */
+static void tls_p_hash_va ( struct tls_session *tls,
+ struct digest_algorithm *digest,
+ void *secret, size_t secret_len,
+ void *out, size_t out_len,
+ va_list seeds ) {
+ uint8_t secret_copy[secret_len];
+ uint8_t digest_ctx[digest->ctxsize];
+ uint8_t digest_ctx_partial[digest->ctxsize];
+ uint8_t a[digest->digestsize];
+ uint8_t out_tmp[digest->digestsize];
+ size_t frag_len = digest->digestsize;
+ va_list tmp;
+
+ /* Copy the secret, in case HMAC modifies it */
+ memcpy ( secret_copy, secret, secret_len );
+ secret = secret_copy;
+ DBGC2 ( tls, "TLS %p %s secret:\n", tls, digest->name );
+ DBGC2_HD ( tls, secret, secret_len );
+
+ /* Calculate A(1) */
+ hmac_init ( digest, digest_ctx, secret, &secret_len );
+ va_copy ( tmp, seeds );
+ tls_hmac_update_va ( digest, digest_ctx, tmp );
+ va_end ( tmp );
+ hmac_final ( digest, digest_ctx, secret, &secret_len, a );
+ DBGC2 ( tls, "TLS %p %s A(1):\n", tls, digest->name );
+ DBGC2_HD ( tls, &a, sizeof ( a ) );
+
+ /* Generate as much data as required */
+ while ( out_len ) {
+ /* Calculate output portion */
+ hmac_init ( digest, digest_ctx, secret, &secret_len );
+ hmac_update ( digest, digest_ctx, a, sizeof ( a ) );
+ memcpy ( digest_ctx_partial, digest_ctx, digest->ctxsize );
+ va_copy ( tmp, seeds );
+ tls_hmac_update_va ( digest, digest_ctx, tmp );
+ va_end ( tmp );
+ hmac_final ( digest, digest_ctx,
+ secret, &secret_len, out_tmp );
+
+ /* Copy output */
+ if ( frag_len > out_len )
+ frag_len = out_len;
+ memcpy ( out, out_tmp, frag_len );
+ DBGC2 ( tls, "TLS %p %s output:\n", tls, digest->name );
+ DBGC2_HD ( tls, out, frag_len );
+
+ /* Calculate A(i) */
+ hmac_final ( digest, digest_ctx_partial,
+ secret, &secret_len, a );
+ DBGC2 ( tls, "TLS %p %s A(n):\n", tls, digest->name );
+ DBGC2_HD ( tls, &a, sizeof ( a ) );
+
+ out += frag_len;
+ out_len -= frag_len;
+ }
+}
+
+/**
+ * Generate secure pseudo-random data
+ *
+ * @v tls TLS session
+ * @v secret Secret
+ * @v secret_len Length of secret
+ * @v out Output buffer
+ * @v out_len Length of output buffer
+ * @v ... ( data, len ) pairs of seed data, terminated by NULL
+ */
+static void tls_prf ( struct tls_session *tls, void *secret, size_t secret_len,
+ void *out, size_t out_len, ... ) {
+ va_list seeds;
+ va_list tmp;
+ size_t subsecret_len;
+ void *md5_secret;
+ void *sha1_secret;
+ uint8_t buf[out_len];
+ unsigned int i;
+
+ va_start ( seeds, out_len );
+
+ if ( tls->version >= TLS_VERSION_TLS_1_2 ) {
+ /* Use P_SHA256 for TLSv1.2 and later */
+ tls_p_hash_va ( tls, &sha256_algorithm, secret, secret_len,
+ out, out_len, seeds );
+ } else {
+ /* Use combination of P_MD5 and P_SHA-1 for TLSv1.1
+ * and earlier
+ */
+
+ /* Split secret into two, with an overlap of up to one byte */
+ subsecret_len = ( ( secret_len + 1 ) / 2 );
+ md5_secret = secret;
+ sha1_secret = ( secret + secret_len - subsecret_len );
+
+ /* Calculate MD5 portion */
+ va_copy ( tmp, seeds );
+ tls_p_hash_va ( tls, &md5_algorithm, md5_secret,
+ subsecret_len, out, out_len, seeds );
+ va_end ( tmp );
+
+ /* Calculate SHA1 portion */
+ va_copy ( tmp, seeds );
+ tls_p_hash_va ( tls, &sha1_algorithm, sha1_secret,
+ subsecret_len, buf, out_len, seeds );
+ va_end ( tmp );
+
+ /* XOR the two portions together into the final output buffer */
+ for ( i = 0 ; i < out_len ; i++ )
+ *( ( uint8_t * ) out + i ) ^= buf[i];
+ }
+
+ va_end ( seeds );
+}
+
+/**
+ * Generate secure pseudo-random data
+ *
+ * @v secret Secret
+ * @v secret_len Length of secret
+ * @v out Output buffer
+ * @v out_len Length of output buffer
+ * @v label String literal label
+ * @v ... ( data, len ) pairs of seed data
+ */
+#define tls_prf_label( tls, secret, secret_len, out, out_len, label, ... ) \
+ tls_prf ( (tls), (secret), (secret_len), (out), (out_len), \
+ label, ( sizeof ( label ) - 1 ), __VA_ARGS__, NULL )
+
+/******************************************************************************
+ *
+ * Secret management
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Generate master secret
+ *
+ * @v tls TLS session
+ *
+ * The pre-master secret and the client and server random values must
+ * already be known.
+ */
+static void tls_generate_master_secret ( struct tls_session *tls ) {
+ DBGC ( tls, "TLS %p pre-master-secret:\n", tls );
+ DBGC_HD ( tls, &tls->pre_master_secret,
+ sizeof ( tls->pre_master_secret ) );
+ DBGC ( tls, "TLS %p client random bytes:\n", tls );
+ DBGC_HD ( tls, &tls->client_random, sizeof ( tls->client_random ) );
+ DBGC ( tls, "TLS %p server random bytes:\n", tls );
+ DBGC_HD ( tls, &tls->server_random, sizeof ( tls->server_random ) );
+
+ tls_prf_label ( tls, &tls->pre_master_secret,
+ sizeof ( tls->pre_master_secret ),
+ &tls->master_secret, sizeof ( tls->master_secret ),
+ "master secret",
+ &tls->client_random, sizeof ( tls->client_random ),
+ &tls->server_random, sizeof ( tls->server_random ) );
+
+ DBGC ( tls, "TLS %p generated master secret:\n", tls );
+ DBGC_HD ( tls, &tls->master_secret, sizeof ( tls->master_secret ) );
+}
+
+/**
+ * Generate key material
+ *
+ * @v tls TLS session
+ *
+ * The master secret must already be known.
+ */
+static int tls_generate_keys ( struct tls_session *tls ) {
+ struct tls_cipherspec *tx_cipherspec = &tls->tx_cipherspec_pending;
+ struct tls_cipherspec *rx_cipherspec = &tls->rx_cipherspec_pending;
+ size_t hash_size = tx_cipherspec->suite->digest->digestsize;
+ size_t key_size = tx_cipherspec->suite->key_len;
+ size_t iv_size = tx_cipherspec->suite->cipher->blocksize;
+ size_t total = ( 2 * ( hash_size + key_size + iv_size ) );
+ uint8_t key_block[total];
+ uint8_t *key;
+ int rc;
+
+ /* Generate key block */
+ tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
+ key_block, sizeof ( key_block ), "key expansion",
+ &tls->server_random, sizeof ( tls->server_random ),
+ &tls->client_random, sizeof ( tls->client_random ) );
+
+ /* Split key block into portions */
+ key = key_block;
+
+ /* TX MAC secret */
+ memcpy ( tx_cipherspec->mac_secret, key, hash_size );
+ DBGC ( tls, "TLS %p TX MAC secret:\n", tls );
+ DBGC_HD ( tls, key, hash_size );
+ key += hash_size;
+
+ /* RX MAC secret */
+ memcpy ( rx_cipherspec->mac_secret, key, hash_size );
+ DBGC ( tls, "TLS %p RX MAC secret:\n", tls );
+ DBGC_HD ( tls, key, hash_size );
+ key += hash_size;
+
+ /* TX key */
+ if ( ( rc = cipher_setkey ( tx_cipherspec->suite->cipher,
+ tx_cipherspec->cipher_ctx,
+ key, key_size ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not set TX key: %s\n",
+ tls, strerror ( rc ) );
+ return rc;
+ }
+ DBGC ( tls, "TLS %p TX key:\n", tls );
+ DBGC_HD ( tls, key, key_size );
+ key += key_size;
+
+ /* RX key */
+ if ( ( rc = cipher_setkey ( rx_cipherspec->suite->cipher,
+ rx_cipherspec->cipher_ctx,
+ key, key_size ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not set TX key: %s\n",
+ tls, strerror ( rc ) );
+ return rc;
+ }
+ DBGC ( tls, "TLS %p RX key:\n", tls );
+ DBGC_HD ( tls, key, key_size );
+ key += key_size;
+
+ /* TX initialisation vector */
+ cipher_setiv ( tx_cipherspec->suite->cipher,
+ tx_cipherspec->cipher_ctx, key );
+ DBGC ( tls, "TLS %p TX IV:\n", tls );
+ DBGC_HD ( tls, key, iv_size );
+ key += iv_size;
+
+ /* RX initialisation vector */
+ cipher_setiv ( rx_cipherspec->suite->cipher,
+ rx_cipherspec->cipher_ctx, key );
+ DBGC ( tls, "TLS %p RX IV:\n", tls );
+ DBGC_HD ( tls, key, iv_size );
+ key += iv_size;
+
+ assert ( ( key_block + total ) == key );
+
+ return 0;
+}
+
+/******************************************************************************
+ *
+ * Cipher suite management
+ *
+ ******************************************************************************
+ */
+
+/** Null cipher suite */
+struct tls_cipher_suite tls_cipher_suite_null = {
+ .pubkey = &pubkey_null,
+ .cipher = &cipher_null,
+ .digest = &digest_null,
+};
+
+/** Supported cipher suites, in order of preference */
+struct tls_cipher_suite tls_cipher_suites[] = {
+ {
+ .code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA256 ),
+ .key_len = ( 256 / 8 ),
+ .pubkey = &rsa_algorithm,
+ .cipher = &aes_cbc_algorithm,
+ .digest = &sha256_algorithm,
+ },
+ {
+ .code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA256 ),
+ .key_len = ( 128 / 8 ),
+ .pubkey = &rsa_algorithm,
+ .cipher = &aes_cbc_algorithm,
+ .digest = &sha256_algorithm,
+ },
+ {
+ .code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA ),
+ .key_len = ( 256 / 8 ),
+ .pubkey = &rsa_algorithm,
+ .cipher = &aes_cbc_algorithm,
+ .digest = &sha1_algorithm,
+ },
+ {
+ .code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA ),
+ .key_len = ( 128 / 8 ),
+ .pubkey = &rsa_algorithm,
+ .cipher = &aes_cbc_algorithm,
+ .digest = &sha1_algorithm,
+ },
+};
+
+/** Number of supported cipher suites */
+#define TLS_NUM_CIPHER_SUITES \
+ ( sizeof ( tls_cipher_suites ) / sizeof ( tls_cipher_suites[0] ) )
+
+/**
+ * Identify cipher suite
+ *
+ * @v cipher_suite Cipher suite specification
+ * @ret suite Cipher suite, or NULL
+ */
+static struct tls_cipher_suite *
+tls_find_cipher_suite ( unsigned int cipher_suite ) {
+ struct tls_cipher_suite *suite;
+ unsigned int i;
+
+ /* Identify cipher suite */
+ for ( i = 0 ; i < TLS_NUM_CIPHER_SUITES ; i++ ) {
+ suite = &tls_cipher_suites[i];
+ if ( suite->code == cipher_suite )
+ return suite;
+ }
+
+ return NULL;
+}
+
+/**
+ * Clear cipher suite
+ *
+ * @v cipherspec TLS cipher specification
+ */
+static void tls_clear_cipher ( struct tls_session *tls __unused,
+ struct tls_cipherspec *cipherspec ) {
+
+ if ( cipherspec->suite ) {
+ pubkey_final ( cipherspec->suite->pubkey,
+ cipherspec->pubkey_ctx );
+ }
+ free ( cipherspec->dynamic );
+ memset ( cipherspec, 0, sizeof ( *cipherspec ) );
+ cipherspec->suite = &tls_cipher_suite_null;
+}
+
+/**
+ * Set cipher suite
+ *
+ * @v tls TLS session
+ * @v cipherspec TLS cipher specification
+ * @v suite Cipher suite
+ * @ret rc Return status code
+ */
+static int tls_set_cipher ( struct tls_session *tls,
+ struct tls_cipherspec *cipherspec,
+ struct tls_cipher_suite *suite ) {
+ struct pubkey_algorithm *pubkey = suite->pubkey;
+ struct cipher_algorithm *cipher = suite->cipher;
+ struct digest_algorithm *digest = suite->digest;
+ size_t total;
+ void *dynamic;
+
+ /* Clear out old cipher contents, if any */
+ tls_clear_cipher ( tls, cipherspec );
+
+ /* Allocate dynamic storage */
+ total = ( pubkey->ctxsize + 2 * cipher->ctxsize + digest->digestsize );
+ dynamic = zalloc ( total );
+ if ( ! dynamic ) {
+ DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto "
+ "context\n", tls, total );
+ return -ENOMEM;
+ }
+
+ /* Assign storage */
+ cipherspec->dynamic = dynamic;
+ cipherspec->pubkey_ctx = dynamic; dynamic += pubkey->ctxsize;
+ cipherspec->cipher_ctx = dynamic; dynamic += cipher->ctxsize;
+ cipherspec->cipher_next_ctx = dynamic; dynamic += cipher->ctxsize;
+ cipherspec->mac_secret = dynamic; dynamic += digest->digestsize;
+ assert ( ( cipherspec->dynamic + total ) == dynamic );
+
+ /* Store parameters */
+ cipherspec->suite = suite;
+
+ return 0;
+}
+
+/**
+ * Select next cipher suite
+ *
+ * @v tls TLS session
+ * @v cipher_suite Cipher suite specification
+ * @ret rc Return status code
+ */
+static int tls_select_cipher ( struct tls_session *tls,
+ unsigned int cipher_suite ) {
+ struct tls_cipher_suite *suite;
+ int rc;
+
+ /* Identify cipher suite */
+ suite = tls_find_cipher_suite ( cipher_suite );
+ if ( ! suite ) {
+ DBGC ( tls, "TLS %p does not support cipher %04x\n",
+ tls, ntohs ( cipher_suite ) );
+ return -ENOTSUP;
+ }
+
+ /* Set ciphers */
+ if ( ( rc = tls_set_cipher ( tls, &tls->tx_cipherspec_pending,
+ suite ) ) != 0 )
+ return rc;
+ if ( ( rc = tls_set_cipher ( tls, &tls->rx_cipherspec_pending,
+ suite ) ) != 0 )
+ return rc;
+
+ DBGC ( tls, "TLS %p selected %s-%s-%d-%s\n", tls, suite->pubkey->name,
+ suite->cipher->name, ( suite->key_len * 8 ),
+ suite->digest->name );
+
+ return 0;
+}
+
+/**
+ * Activate next cipher suite
+ *
+ * @v tls TLS session
+ * @v pending Pending cipher specification
+ * @v active Active cipher specification to replace
+ * @ret rc Return status code
+ */
+static int tls_change_cipher ( struct tls_session *tls,
+ struct tls_cipherspec *pending,
+ struct tls_cipherspec *active ) {
+
+ /* Sanity check */
+ if ( pending->suite == &tls_cipher_suite_null ) {
+ DBGC ( tls, "TLS %p refusing to use null cipher\n", tls );
+ return -ENOTSUP;
+ }
+
+ tls_clear_cipher ( tls, active );
+ memswap ( active, pending, sizeof ( *active ) );
+ return 0;
+}
+
+/******************************************************************************
+ *
+ * Signature and hash algorithms
+ *
+ ******************************************************************************
+ */
+
+/** Supported signature and hash algorithms
+ *
+ * Note that the default (TLSv1.1 and earlier) algorithm using
+ * MD5+SHA1 is never explicitly specified.
+ */
+struct tls_signature_hash_algorithm tls_signature_hash_algorithms[] = {
+ {
+ .code = {
+ .signature = TLS_RSA_ALGORITHM,
+ .hash = TLS_SHA256_ALGORITHM,
+ },
+ .pubkey = &rsa_algorithm,
+ .digest = &sha256_algorithm,
+ },
+};
+
+/** Number of supported signature and hash algorithms */
+#define TLS_NUM_SIG_HASH_ALGORITHMS \
+ ( sizeof ( tls_signature_hash_algorithms ) / \
+ sizeof ( tls_signature_hash_algorithms[0] ) )
+
+/**
+ * Find TLS signature and hash algorithm
+ *
+ * @v pubkey Public-key algorithm
+ * @v digest Digest algorithm
+ * @ret sig_hash Signature and hash algorithm, or NULL
+ */
+static struct tls_signature_hash_algorithm *
+tls_signature_hash_algorithm ( struct pubkey_algorithm *pubkey,
+ struct digest_algorithm *digest ) {
+ struct tls_signature_hash_algorithm *sig_hash;
+ unsigned int i;
+
+ /* Identify signature and hash algorithm */
+ for ( i = 0 ; i < TLS_NUM_SIG_HASH_ALGORITHMS ; i++ ) {
+ sig_hash = &tls_signature_hash_algorithms[i];
+ if ( ( sig_hash->pubkey == pubkey ) &&
+ ( sig_hash->digest == digest ) ) {
+ return sig_hash;
+ }
+ }
+
+ return NULL;
+}
+
+/******************************************************************************
+ *
+ * Handshake verification
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Add handshake record to verification hash
+ *
+ * @v tls TLS session
+ * @v data Handshake record
+ * @v len Length of handshake record
+ */
+static void tls_add_handshake ( struct tls_session *tls,
+ const void *data, size_t len ) {
+
+ digest_update ( &md5_sha1_algorithm, tls->handshake_md5_sha1_ctx,
+ data, len );
+ digest_update ( &sha256_algorithm, tls->handshake_sha256_ctx,
+ data, len );
+}
+
+/**
+ * Calculate handshake verification hash
+ *
+ * @v tls TLS session
+ * @v out Output buffer
+ *
+ * Calculates the MD5+SHA1 or SHA256 digest over all handshake
+ * messages seen so far.
+ */
+static void tls_verify_handshake ( struct tls_session *tls, void *out ) {
+ struct digest_algorithm *digest = tls->handshake_digest;
+ uint8_t ctx[ digest->ctxsize ];
+
+ memcpy ( ctx, tls->handshake_ctx, sizeof ( ctx ) );
+ digest_final ( digest, ctx, out );
+}
+
+/******************************************************************************
+ *
+ * Record handling
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Resume TX state machine
+ *
+ * @v tls TLS session
+ */
+static void tls_tx_resume ( struct tls_session *tls ) {
+ process_add ( &tls->process );
+}
+
+/**
+ * Transmit Handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext record
+ * @v len Length of plaintext record
+ * @ret rc Return status code
+ */
+static int tls_send_handshake ( struct tls_session *tls,
+ void *data, size_t len ) {
+
+ /* Add to handshake digest */
+ tls_add_handshake ( tls, data, len );
+
+ /* Send record */
+ return tls_send_plaintext ( tls, TLS_TYPE_HANDSHAKE, data, len );
+}
+
+/**
+ * Transmit Client Hello record
+ *
+ * @v tls TLS session
+ * @ret rc Return status code
+ */
+static int tls_send_client_hello ( struct tls_session *tls ) {
+ struct {
+ uint32_t type_length;
+ uint16_t version;
+ uint8_t random[32];
+ uint8_t session_id_len;
+ uint16_t cipher_suite_len;
+ uint16_t cipher_suites[TLS_NUM_CIPHER_SUITES];
+ uint8_t compression_methods_len;
+ uint8_t compression_methods[1];
+ uint16_t extensions_len;
+ struct {
+ uint16_t server_name_type;
+ uint16_t server_name_len;
+ struct {
+ uint16_t len;
+ struct {
+ uint8_t type;
+ uint16_t len;
+ uint8_t name[ strlen ( tls->name ) ];
+ } __attribute__ (( packed )) list[1];
+ } __attribute__ (( packed )) server_name;
+ } __attribute__ (( packed )) extensions;
+ } __attribute__ (( packed )) hello;
+ unsigned int i;
+
+ memset ( &hello, 0, sizeof ( hello ) );
+ hello.type_length = ( cpu_to_le32 ( TLS_CLIENT_HELLO ) |
+ htonl ( sizeof ( hello ) -
+ sizeof ( hello.type_length ) ) );
+ hello.version = htons ( tls->version );
+ memcpy ( &hello.random, &tls->client_random, sizeof ( hello.random ) );
+ hello.cipher_suite_len = htons ( sizeof ( hello.cipher_suites ) );
+ for ( i = 0 ; i < TLS_NUM_CIPHER_SUITES ; i++ )
+ hello.cipher_suites[i] = tls_cipher_suites[i].code;
+ hello.compression_methods_len = sizeof ( hello.compression_methods );
+ hello.extensions_len = htons ( sizeof ( hello.extensions ) );
+ hello.extensions.server_name_type = htons ( TLS_SERVER_NAME );
+ hello.extensions.server_name_len
+ = htons ( sizeof ( hello.extensions.server_name ) );
+ hello.extensions.server_name.len
+ = htons ( sizeof ( hello.extensions.server_name.list ) );
+ hello.extensions.server_name.list[0].type = TLS_SERVER_NAME_HOST_NAME;
+ hello.extensions.server_name.list[0].len
+ = htons ( sizeof ( hello.extensions.server_name.list[0].name ));
+ memcpy ( hello.extensions.server_name.list[0].name, tls->name,
+ sizeof ( hello.extensions.server_name.list[0].name ) );
+
+ return tls_send_handshake ( tls, &hello, sizeof ( hello ) );
+}
+
+/**
+ * Transmit Certificate record
+ *
+ * @v tls TLS session
+ * @ret rc Return status code
+ */
+static int tls_send_certificate ( struct tls_session *tls ) {
+ int num_certificates = ( have_client_certificate() ? 1 : 0 );
+ struct {
+ uint32_t type_length;
+ uint8_t length[3];
+ struct {
+ uint8_t length[3];
+ uint8_t data[ client_certificate.len ];
+ } __attribute__ (( packed )) certificates[num_certificates];
+ } __attribute__ (( packed )) *certificate;
+ struct x509_certificate *cert;
+ int rc;
+
+ /* If we have a certificate to send, determine the applicable
+ * public-key algorithm and schedule transmission of
+ * CertificateVerify.
+ */
+ if ( num_certificates ) {
+
+ /* Parse certificate to determine public-key algorithm */
+ if ( ( rc = x509_certificate ( client_certificate.data,
+ client_certificate.len,
+ &cert ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not parse client "
+ "certificate: %s\n", tls, strerror ( rc ) );
+ return rc;
+ }
+ tls->verify_pubkey = cert->signature_algorithm->pubkey;
+ x509_put ( cert );
+ cert = NULL;
+
+ /* Schedule CertificateVerify transmission */
+ tls->tx_pending |= TLS_TX_CERTIFICATE_VERIFY;
+ tls_tx_resume ( tls );
+ }
+
+ /* Allocate storage for Certificate record (which may be too
+ * large for the stack).
+ */
+ certificate = zalloc ( sizeof ( *certificate ) );
+ if ( ! certificate )
+ return -ENOMEM;
+
+ /* Populate record */
+ certificate->type_length =
+ ( cpu_to_le32 ( TLS_CERTIFICATE ) |
+ htonl ( sizeof ( *certificate ) -
+ sizeof ( certificate->type_length ) ) );
+ tls_set_uint24 ( certificate->length,
+ sizeof ( certificate->certificates ) );
+ if ( num_certificates ) {
+ tls_set_uint24 ( certificate->certificates[0].length,
+ sizeof ( certificate->certificates[0].data ) );
+ memcpy ( certificate->certificates[0].data,
+ client_certificate.data,
+ sizeof ( certificate->certificates[0].data ) );
+ }
+
+ /* Transmit record */
+ rc = tls_send_handshake ( tls, certificate, sizeof ( *certificate ) );
+
+ /* Free record */
+ free ( certificate );
+
+ return rc;
+}
+
+/**
+ * Transmit Client Key Exchange record
+ *
+ * @v tls TLS session
+ * @ret rc Return status code
+ */
+static int tls_send_client_key_exchange ( struct tls_session *tls ) {
+ struct tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
+ struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
+ size_t max_len = pubkey_max_len ( pubkey, cipherspec->pubkey_ctx );
+ struct {
+ uint32_t type_length;
+ uint16_t encrypted_pre_master_secret_len;
+ uint8_t encrypted_pre_master_secret[max_len];
+ } __attribute__ (( packed )) key_xchg;
+ size_t unused;
+ int len;
+ int rc;
+
+ /* Encrypt pre-master secret using server's public key */
+ memset ( &key_xchg, 0, sizeof ( key_xchg ) );
+ len = pubkey_encrypt ( pubkey, cipherspec->pubkey_ctx,
+ &tls->pre_master_secret,
+ sizeof ( tls->pre_master_secret ),
+ key_xchg.encrypted_pre_master_secret );
+ if ( len < 0 ) {
+ rc = len;
+ DBGC ( tls, "TLS %p could not encrypt pre-master secret: %s\n",
+ tls, strerror ( rc ) );
+ return rc;
+ }
+ unused = ( max_len - len );
+ key_xchg.type_length =
+ ( cpu_to_le32 ( TLS_CLIENT_KEY_EXCHANGE ) |
+ htonl ( sizeof ( key_xchg ) -
+ sizeof ( key_xchg.type_length ) - unused ) );
+ key_xchg.encrypted_pre_master_secret_len =
+ htons ( sizeof ( key_xchg.encrypted_pre_master_secret ) -
+ unused );
+
+ return tls_send_handshake ( tls, &key_xchg,
+ ( sizeof ( key_xchg ) - unused ) );
+}
+
+/**
+ * Transmit Certificate Verify record
+ *
+ * @v tls TLS session
+ * @ret rc Return status code
+ */
+static int tls_send_certificate_verify ( struct tls_session *tls ) {
+ struct digest_algorithm *digest = tls->handshake_digest;
+ struct pubkey_algorithm *pubkey = tls->verify_pubkey;
+ uint8_t digest_out[ digest->digestsize ];
+ uint8_t ctx[ pubkey->ctxsize ];
+ struct tls_signature_hash_algorithm *sig_hash = NULL;
+ int rc;
+
+ /* Generate digest to be signed */
+ tls_verify_handshake ( tls, digest_out );
+
+ /* Initialise public-key algorithm */
+ if ( ( rc = pubkey_init ( pubkey, ctx, client_private_key.data,
+ client_private_key.len ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not initialise %s client private "
+ "key: %s\n", tls, pubkey->name, strerror ( rc ) );
+ goto err_pubkey_init;
+ }
+
+ /* TLSv1.2 and later use explicit algorithm identifiers */
+ if ( tls->version >= TLS_VERSION_TLS_1_2 ) {
+ sig_hash = tls_signature_hash_algorithm ( pubkey, digest );
+ if ( ! sig_hash ) {
+ DBGC ( tls, "TLS %p could not identify (%s,%s) "
+ "signature and hash algorithm\n", tls,
+ pubkey->name, digest->name );
+ rc = -ENOTSUP;
+ goto err_sig_hash;
+ }
+ }
+
+ /* Generate and transmit record */
+ {
+ size_t max_len = pubkey_max_len ( pubkey, ctx );
+ int use_sig_hash = ( ( sig_hash == NULL ) ? 0 : 1 );
+ struct {
+ uint32_t type_length;
+ struct tls_signature_hash_id sig_hash[use_sig_hash];
+ uint16_t signature_len;
+ uint8_t signature[max_len];
+ } __attribute__ (( packed )) certificate_verify;
+ size_t unused;
+ int len;
+
+ /* Sign digest */
+ len = pubkey_sign ( pubkey, ctx, digest, digest_out,
+ certificate_verify.signature );
+ if ( len < 0 ) {
+ rc = len;
+ DBGC ( tls, "TLS %p could not sign %s digest using %s "
+ "client private key: %s\n", tls, digest->name,
+ pubkey->name, strerror ( rc ) );
+ goto err_pubkey_sign;
+ }
+ unused = ( max_len - len );
+
+ /* Construct Certificate Verify record */
+ certificate_verify.type_length =
+ ( cpu_to_le32 ( TLS_CERTIFICATE_VERIFY ) |
+ htonl ( sizeof ( certificate_verify ) -
+ sizeof ( certificate_verify.type_length ) -
+ unused ) );
+ if ( use_sig_hash ) {
+ memcpy ( &certificate_verify.sig_hash[0],
+ &sig_hash->code,
+ sizeof ( certificate_verify.sig_hash[0] ) );
+ }
+ certificate_verify.signature_len =
+ htons ( sizeof ( certificate_verify.signature ) -
+ unused );
+
+ /* Transmit record */
+ rc = tls_send_handshake ( tls, &certificate_verify,
+ ( sizeof ( certificate_verify ) - unused ) );
+ }
+
+ err_pubkey_sign:
+ err_sig_hash:
+ pubkey_final ( pubkey, ctx );
+ err_pubkey_init:
+ return rc;
+}
+
+/**
+ * Transmit Change Cipher record
+ *
+ * @v tls TLS session
+ * @ret rc Return status code
+ */
+static int tls_send_change_cipher ( struct tls_session *tls ) {
+ static const uint8_t change_cipher[1] = { 1 };
+ return tls_send_plaintext ( tls, TLS_TYPE_CHANGE_CIPHER,
+ change_cipher, sizeof ( change_cipher ) );
+}
+
+/**
+ * Transmit Finished record
+ *
+ * @v tls TLS session
+ * @ret rc Return status code
+ */
+static int tls_send_finished ( struct tls_session *tls ) {
+ struct digest_algorithm *digest = tls->handshake_digest;
+ struct {
+ uint32_t type_length;
+ uint8_t verify_data[12];
+ } __attribute__ (( packed )) finished;
+ uint8_t digest_out[ digest->digestsize ];
+ int rc;
+
+ /* Construct record */
+ memset ( &finished, 0, sizeof ( finished ) );
+ finished.type_length = ( cpu_to_le32 ( TLS_FINISHED ) |
+ htonl ( sizeof ( finished ) -
+ sizeof ( finished.type_length ) ) );
+ tls_verify_handshake ( tls, digest_out );
+ tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
+ finished.verify_data, sizeof ( finished.verify_data ),
+ "client finished", digest_out, sizeof ( digest_out ) );
+
+ /* Transmit record */
+ if ( ( rc = tls_send_handshake ( tls, &finished,
+ sizeof ( finished ) ) ) != 0 )
+ return rc;
+
+ /* Mark client as finished */
+ tls->client_finished = 1;
+
+ return 0;
+}
+
+/**
+ * Receive new Change Cipher record
+ *
+ * @v tls TLS session
+ * @v data Plaintext record
+ * @v len Length of plaintext record
+ * @ret rc Return status code
+ */
+static int tls_new_change_cipher ( struct tls_session *tls,
+ const void *data, size_t len ) {
+ int rc;
+
+ if ( ( len != 1 ) || ( *( ( uint8_t * ) data ) != 1 ) ) {
+ DBGC ( tls, "TLS %p received invalid Change Cipher\n", tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ if ( ( rc = tls_change_cipher ( tls, &tls->rx_cipherspec_pending,
+ &tls->rx_cipherspec ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not activate RX cipher: %s\n",
+ tls, strerror ( rc ) );
+ return rc;
+ }
+ tls->rx_seq = ~( ( uint64_t ) 0 );
+
+ return 0;
+}
+
+/**
+ * Receive new Alert record
+ *
+ * @v tls TLS session
+ * @v data Plaintext record
+ * @v len Length of plaintext record
+ * @ret rc Return status code
+ */
+static int tls_new_alert ( struct tls_session *tls, const void *data,
+ size_t len ) {
+ const struct {
+ uint8_t level;
+ uint8_t description;
+ char next[0];
+ } __attribute__ (( packed )) *alert = data;
+ const void *end = alert->next;
+
+ /* Sanity check */
+ if ( end != ( data + len ) ) {
+ DBGC ( tls, "TLS %p received overlength Alert\n", tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ switch ( alert->level ) {
+ case TLS_ALERT_WARNING:
+ DBGC ( tls, "TLS %p received warning alert %d\n",
+ tls, alert->description );
+ return 0;
+ case TLS_ALERT_FATAL:
+ DBGC ( tls, "TLS %p received fatal alert %d\n",
+ tls, alert->description );
+ return -EPERM;
+ default:
+ DBGC ( tls, "TLS %p received unknown alert level %d"
+ "(alert %d)\n", tls, alert->level, alert->description );
+ return -EIO;
+ }
+}
+
+/**
+ * Receive new Server Hello handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext handshake record
+ * @v len Length of plaintext handshake record
+ * @ret rc Return status code
+ */
+static int tls_new_server_hello ( struct tls_session *tls,
+ const void *data, size_t len ) {
+ const struct {
+ uint16_t version;
+ uint8_t random[32];
+ uint8_t session_id_len;
+ char next[0];
+ } __attribute__ (( packed )) *hello_a = data;
+ const struct {
+ uint8_t session_id[hello_a->session_id_len];
+ uint16_t cipher_suite;
+ uint8_t compression_method;
+ char next[0];
+ } __attribute__ (( packed )) *hello_b = ( void * ) &hello_a->next;
+ const void *end = hello_b->next;
+ uint16_t version;
+ int rc;
+
+ /* Sanity check */
+ if ( end > ( data + len ) ) {
+ DBGC ( tls, "TLS %p received underlength Server Hello\n", tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ /* Check and store protocol version */
+ version = ntohs ( hello_a->version );
+ if ( version < TLS_VERSION_TLS_1_0 ) {
+ DBGC ( tls, "TLS %p does not support protocol version %d.%d\n",
+ tls, ( version >> 8 ), ( version & 0xff ) );
+ return -ENOTSUP;
+ }
+ if ( version > tls->version ) {
+ DBGC ( tls, "TLS %p server attempted to illegally upgrade to "
+ "protocol version %d.%d\n",
+ tls, ( version >> 8 ), ( version & 0xff ) );
+ return -EPROTO;
+ }
+ tls->version = version;
+ DBGC ( tls, "TLS %p using protocol version %d.%d\n",
+ tls, ( version >> 8 ), ( version & 0xff ) );
+
+ /* Use MD5+SHA1 digest algorithm for handshake verification
+ * for versions earlier than TLSv1.2.
+ */
+ if ( tls->version < TLS_VERSION_TLS_1_2 ) {
+ tls->handshake_digest = &md5_sha1_algorithm;
+ tls->handshake_ctx = tls->handshake_md5_sha1_ctx;
+ }
+
+ /* Copy out server random bytes */
+ memcpy ( &tls->server_random, &hello_a->random,
+ sizeof ( tls->server_random ) );
+
+ /* Select cipher suite */
+ if ( ( rc = tls_select_cipher ( tls, hello_b->cipher_suite ) ) != 0 )
+ return rc;
+
+ /* Generate secrets */
+ tls_generate_master_secret ( tls );
+ if ( ( rc = tls_generate_keys ( tls ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Parse certificate chain
+ *
+ * @v tls TLS session
+ * @v data Certificate chain
+ * @v len Length of certificate chain
+ * @ret rc Return status code
+ */
+static int tls_parse_chain ( struct tls_session *tls,
+ const void *data, size_t len ) {
+ const void *end = ( data + len );
+ const struct {
+ uint8_t length[3];
+ uint8_t data[0];
+ } __attribute__ (( packed )) *certificate;
+ size_t certificate_len;
+ struct x509_certificate *cert;
+ const void *next;
+ int rc;
+
+ /* Free any existing certificate chain */
+ x509_chain_put ( tls->chain );
+ tls->chain = NULL;
+
+ /* Create certificate chain */
+ tls->chain = x509_alloc_chain();
+ if ( ! tls->chain ) {
+ rc = -ENOMEM;
+ goto err_alloc_chain;
+ }
+
+ /* Add certificates to chain */
+ while ( data < end ) {
+
+ /* Extract raw certificate data */
+ certificate = data;
+ certificate_len = tls_uint24 ( certificate->length );
+ next = ( certificate->data + certificate_len );
+ if ( next > end ) {
+ DBGC ( tls, "TLS %p overlength certificate:\n", tls );
+ DBGC_HDA ( tls, 0, data, ( end - data ) );
+ rc = -EINVAL;
+ goto err_overlength;
+ }
+
+ /* Add certificate to chain */
+ if ( ( rc = x509_append_raw ( tls->chain, certificate->data,
+ certificate_len ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not append certificate: %s\n",
+ tls, strerror ( rc ) );
+ DBGC_HDA ( tls, 0, data, ( end - data ) );
+ goto err_parse;
+ }
+ cert = x509_last ( tls->chain );
+ DBGC ( tls, "TLS %p found certificate %s\n",
+ tls, cert->subject.name );
+
+ /* Move to next certificate in list */
+ data = next;
+ }
+
+ return 0;
+
+ err_parse:
+ err_overlength:
+ x509_chain_put ( tls->chain );
+ tls->chain = NULL;
+ err_alloc_chain:
+ return rc;
+}
+
+/**
+ * Receive new Certificate handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext handshake record
+ * @v len Length of plaintext handshake record
+ * @ret rc Return status code
+ */
+static int tls_new_certificate ( struct tls_session *tls,
+ const void *data, size_t len ) {
+ const struct {
+ uint8_t length[3];
+ uint8_t certificates[0];
+ } __attribute__ (( packed )) *certificate = data;
+ size_t certificates_len = tls_uint24 ( certificate->length );
+ const void *end = ( certificate->certificates + certificates_len );
+ int rc;
+
+ /* Sanity check */
+ if ( end != ( data + len ) ) {
+ DBGC ( tls, "TLS %p received overlength Server Certificate\n",
+ tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ /* Parse certificate chain */
+ if ( ( rc = tls_parse_chain ( tls, certificate->certificates,
+ certificates_len ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Receive new Certificate Request handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext handshake record
+ * @v len Length of plaintext handshake record
+ * @ret rc Return status code
+ */
+static int tls_new_certificate_request ( struct tls_session *tls,
+ const void *data __unused,
+ size_t len __unused ) {
+
+ /* We can only send a single certificate, so there is no point
+ * in parsing the Certificate Request.
+ */
+
+ /* Schedule Certificate transmission */
+ tls->tx_pending |= TLS_TX_CERTIFICATE;
+ tls_tx_resume ( tls );
+
+ return 0;
+}
+
+/**
+ * Receive new Server Hello Done handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext handshake record
+ * @v len Length of plaintext handshake record
+ * @ret rc Return status code
+ */
+static int tls_new_server_hello_done ( struct tls_session *tls,
+ const void *data, size_t len ) {
+ const struct {
+ char next[0];
+ } __attribute__ (( packed )) *hello_done = data;
+ const void *end = hello_done->next;
+ int rc;
+
+ /* Sanity check */
+ if ( end != ( data + len ) ) {
+ DBGC ( tls, "TLS %p received overlength Server Hello Done\n",
+ tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ /* Begin certificate validation */
+ if ( ( rc = create_validator ( &tls->validator, tls->chain ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not start certificate validation: "
+ "%s\n", tls, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Receive new Finished handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext handshake record
+ * @v len Length of plaintext handshake record
+ * @ret rc Return status code
+ */
+static int tls_new_finished ( struct tls_session *tls,
+ const void *data, size_t len ) {
+ struct digest_algorithm *digest = tls->handshake_digest;
+ const struct {
+ uint8_t verify_data[12];
+ char next[0];
+ } __attribute__ (( packed )) *finished = data;
+ const void *end = finished->next;
+ uint8_t digest_out[ digest->digestsize ];
+ uint8_t verify_data[ sizeof ( finished->verify_data ) ];
+
+ /* Sanity check */
+ if ( end != ( data + len ) ) {
+ DBGC ( tls, "TLS %p received overlength Finished\n", tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ /* Verify data */
+ tls_verify_handshake ( tls, digest_out );
+ tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
+ verify_data, sizeof ( verify_data ), "server finished",
+ digest_out, sizeof ( digest_out ) );
+ if ( memcmp ( verify_data, finished->verify_data,
+ sizeof ( verify_data ) ) != 0 ) {
+ DBGC ( tls, "TLS %p verification failed\n", tls );
+ return -EPERM;
+ }
+
+ /* Mark server as finished */
+ tls->server_finished = 1;
+
+ /* Send notification of a window change */
+ xfer_window_changed ( &tls->plainstream );
+
+ return 0;
+}
+
+/**
+ * Receive new Handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext record
+ * @v len Length of plaintext record
+ * @ret rc Return status code
+ */
+static int tls_new_handshake ( struct tls_session *tls,
+ const void *data, size_t len ) {
+ const void *end = ( data + len );
+ int rc;
+
+ while ( data != end ) {
+ const struct {
+ uint8_t type;
+ uint8_t length[3];
+ uint8_t payload[0];
+ } __attribute__ (( packed )) *handshake = data;
+ void *payload = &handshake->payload;
+ size_t payload_len = tls_uint24 ( handshake->length );
+ void *next = ( payload + payload_len );
+
+ /* Sanity check */
+ if ( next > end ) {
+ DBGC ( tls, "TLS %p received overlength Handshake\n",
+ tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ switch ( handshake->type ) {
+ case TLS_SERVER_HELLO:
+ rc = tls_new_server_hello ( tls, payload, payload_len );
+ break;
+ case TLS_CERTIFICATE:
+ rc = tls_new_certificate ( tls, payload, payload_len );
+ break;
+ case TLS_CERTIFICATE_REQUEST:
+ rc = tls_new_certificate_request ( tls, payload,
+ payload_len );
+ break;
+ case TLS_SERVER_HELLO_DONE:
+ rc = tls_new_server_hello_done ( tls, payload,
+ payload_len );
+ break;
+ case TLS_FINISHED:
+ rc = tls_new_finished ( tls, payload, payload_len );
+ break;
+ default:
+ DBGC ( tls, "TLS %p ignoring handshake type %d\n",
+ tls, handshake->type );
+ rc = 0;
+ break;
+ }
+
+ /* Add to handshake digest (except for Hello Requests,
+ * which are explicitly excluded).
+ */
+ if ( handshake->type != TLS_HELLO_REQUEST )
+ tls_add_handshake ( tls, data,
+ sizeof ( *handshake ) +
+ payload_len );
+
+ /* Abort on failure */
+ if ( rc != 0 )
+ return rc;
+
+ /* Move to next handshake record */
+ data = next;
+ }
+
+ return 0;
+}
+
+/**
+ * Receive new record
+ *
+ * @v tls TLS session
+ * @v type Record type
+ * @v data Plaintext record
+ * @v len Length of plaintext record
+ * @ret rc Return status code
+ */
+static int tls_new_record ( struct tls_session *tls, unsigned int type,
+ const void *data, size_t len ) {
+
+ switch ( type ) {
+ case TLS_TYPE_CHANGE_CIPHER:
+ return tls_new_change_cipher ( tls, data, len );
+ case TLS_TYPE_ALERT:
+ return tls_new_alert ( tls, data, len );
+ case TLS_TYPE_HANDSHAKE:
+ return tls_new_handshake ( tls, data, len );
+ case TLS_TYPE_DATA:
+ if ( ! tls_ready ( tls ) )
+ return -ENOTCONN;
+ return xfer_deliver_raw ( &tls->plainstream, data, len );
+ default:
+ /* RFC4346 says that we should just ignore unknown
+ * record types.
+ */
+ DBGC ( tls, "TLS %p ignoring record type %d\n", tls, type );
+ return 0;
+ }
+}
+
+/******************************************************************************
+ *
+ * Record encryption/decryption
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Calculate HMAC
+ *
+ * @v tls TLS session
+ * @v cipherspec Cipher specification
+ * @v seq Sequence number
+ * @v tlshdr TLS header
+ * @v data Data
+ * @v len Length of data
+ * @v mac HMAC to fill in
+ */
+static void tls_hmac ( struct tls_session *tls __unused,
+ struct tls_cipherspec *cipherspec,
+ uint64_t seq, struct tls_header *tlshdr,
+ const void *data, size_t len, void *hmac ) {
+ struct digest_algorithm *digest = cipherspec->suite->digest;
+ uint8_t digest_ctx[digest->ctxsize];
+
+ hmac_init ( digest, digest_ctx, cipherspec->mac_secret,
+ &digest->digestsize );
+ seq = cpu_to_be64 ( seq );
+ hmac_update ( digest, digest_ctx, &seq, sizeof ( seq ) );
+ hmac_update ( digest, digest_ctx, tlshdr, sizeof ( *tlshdr ) );
+ hmac_update ( digest, digest_ctx, data, len );
+ hmac_final ( digest, digest_ctx, cipherspec->mac_secret,
+ &digest->digestsize, hmac );
+}
+
+/**
+ * Allocate and assemble stream-ciphered record from data and MAC portions
+ *
+ * @v tls TLS session
+ * @ret data Data
+ * @ret len Length of data
+ * @ret digest MAC digest
+ * @ret plaintext_len Length of plaintext record
+ * @ret plaintext Allocated plaintext record
+ */
+static void * __malloc tls_assemble_stream ( struct tls_session *tls,
+ const void *data, size_t len,
+ void *digest, size_t *plaintext_len ) {
+ size_t mac_len = tls->tx_cipherspec.suite->digest->digestsize;
+ void *plaintext;
+ void *content;
+ void *mac;
+
+ /* Calculate stream-ciphered struct length */
+ *plaintext_len = ( len + mac_len );
+
+ /* Allocate stream-ciphered struct */
+ plaintext = malloc ( *plaintext_len );
+ if ( ! plaintext )
+ return NULL;
+ content = plaintext;
+ mac = ( content + len );
+
+ /* Fill in stream-ciphered struct */
+ memcpy ( content, data, len );
+ memcpy ( mac, digest, mac_len );
+
+ return plaintext;
+}
+
+/**
+ * Allocate and assemble block-ciphered record from data and MAC portions
+ *
+ * @v tls TLS session
+ * @ret data Data
+ * @ret len Length of data
+ * @ret digest MAC digest
+ * @ret plaintext_len Length of plaintext record
+ * @ret plaintext Allocated plaintext record
+ */
+static void * tls_assemble_block ( struct tls_session *tls,
+ const void *data, size_t len,
+ void *digest, size_t *plaintext_len ) {
+ size_t blocksize = tls->tx_cipherspec.suite->cipher->blocksize;
+ size_t mac_len = tls->tx_cipherspec.suite->digest->digestsize;
+ size_t iv_len;
+ size_t padding_len;
+ void *plaintext;
+ void *iv;
+ void *content;
+ void *mac;
+ void *padding;
+
+ /* TLSv1.1 and later use an explicit IV */
+ iv_len = ( ( tls->version >= TLS_VERSION_TLS_1_1 ) ? blocksize : 0 );
+
+ /* Calculate block-ciphered struct length */
+ padding_len = ( ( blocksize - 1 ) & -( iv_len + len + mac_len + 1 ) );
+ *plaintext_len = ( iv_len + len + mac_len + padding_len + 1 );
+
+ /* Allocate block-ciphered struct */
+ plaintext = malloc ( *plaintext_len );
+ if ( ! plaintext )
+ return NULL;
+ iv = plaintext;
+ content = ( iv + iv_len );
+ mac = ( content + len );
+ padding = ( mac + mac_len );
+
+ /* Fill in block-ciphered struct */
+ tls_generate_random ( tls, iv, iv_len );
+ memcpy ( content, data, len );
+ memcpy ( mac, digest, mac_len );
+ memset ( padding, padding_len, ( padding_len + 1 ) );
+
+ return plaintext;
+}
+
+/**
+ * Send plaintext record
+ *
+ * @v tls TLS session
+ * @v type Record type
+ * @v data Plaintext record
+ * @v len Length of plaintext record
+ * @ret rc Return status code
+ */
+static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
+ const void *data, size_t len ) {
+ struct tls_header plaintext_tlshdr;
+ struct tls_header *tlshdr;
+ struct tls_cipherspec *cipherspec = &tls->tx_cipherspec;
+ struct cipher_algorithm *cipher = cipherspec->suite->cipher;
+ void *plaintext = NULL;
+ size_t plaintext_len;
+ struct io_buffer *ciphertext = NULL;
+ size_t ciphertext_len;
+ size_t mac_len = cipherspec->suite->digest->digestsize;
+ uint8_t mac[mac_len];
+ int rc;
+
+ /* Construct header */
+ plaintext_tlshdr.type = type;
+ plaintext_tlshdr.version = htons ( tls->version );
+ plaintext_tlshdr.length = htons ( len );
+
+ /* Calculate MAC */
+ tls_hmac ( tls, cipherspec, tls->tx_seq, &plaintext_tlshdr,
+ data, len, mac );
+
+ /* Allocate and assemble plaintext struct */
+ if ( is_stream_cipher ( cipher ) ) {
+ plaintext = tls_assemble_stream ( tls, data, len, mac,
+ &plaintext_len );
+ } else {
+ plaintext = tls_assemble_block ( tls, data, len, mac,
+ &plaintext_len );
+ }
+ if ( ! plaintext ) {
+ DBGC ( tls, "TLS %p could not allocate %zd bytes for "
+ "plaintext\n", tls, plaintext_len );
+ rc = -ENOMEM;
+ goto done;
+ }
+
+ DBGC2 ( tls, "Sending plaintext data:\n" );
+ DBGC2_HD ( tls, plaintext, plaintext_len );
+
+ /* Allocate ciphertext */
+ ciphertext_len = ( sizeof ( *tlshdr ) + plaintext_len );
+ ciphertext = xfer_alloc_iob ( &tls->cipherstream, ciphertext_len );
+ if ( ! ciphertext ) {
+ DBGC ( tls, "TLS %p could not allocate %zd bytes for "
+ "ciphertext\n", tls, ciphertext_len );
+ rc = -ENOMEM;
+ goto done;
+ }
+
+ /* Assemble ciphertext */
+ tlshdr = iob_put ( ciphertext, sizeof ( *tlshdr ) );
+ tlshdr->type = type;
+ tlshdr->version = htons ( tls->version );
+ tlshdr->length = htons ( plaintext_len );
+ memcpy ( cipherspec->cipher_next_ctx, cipherspec->cipher_ctx,
+ cipher->ctxsize );
+ cipher_encrypt ( cipher, cipherspec->cipher_next_ctx, plaintext,
+ iob_put ( ciphertext, plaintext_len ), plaintext_len );
+
+ /* Free plaintext as soon as possible to conserve memory */
+ free ( plaintext );
+ plaintext = NULL;
+
+ /* Send ciphertext */
+ if ( ( rc = xfer_deliver_iob ( &tls->cipherstream,
+ iob_disown ( ciphertext ) ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not deliver ciphertext: %s\n",
+ tls, strerror ( rc ) );
+ goto done;
+ }
+
+ /* Update TX state machine to next record */
+ tls->tx_seq += 1;
+ memcpy ( tls->tx_cipherspec.cipher_ctx,
+ tls->tx_cipherspec.cipher_next_ctx, cipher->ctxsize );
+
+ done:
+ free ( plaintext );
+ free_iob ( ciphertext );
+ return rc;
+}
+
+/**
+ * Split stream-ciphered record into data and MAC portions
+ *
+ * @v tls TLS session
+ * @v plaintext Plaintext record
+ * @v plaintext_len Length of record
+ * @ret data Data
+ * @ret len Length of data
+ * @ret digest MAC digest
+ * @ret rc Return status code
+ */
+static int tls_split_stream ( struct tls_session *tls,
+ void *plaintext, size_t plaintext_len,
+ void **data, size_t *len, void **digest ) {
+ void *content;
+ size_t content_len;
+ void *mac;
+ size_t mac_len;
+
+ /* Decompose stream-ciphered data */
+ mac_len = tls->rx_cipherspec.suite->digest->digestsize;
+ if ( plaintext_len < mac_len ) {
+ DBGC ( tls, "TLS %p received underlength record\n", tls );
+ DBGC_HD ( tls, plaintext, plaintext_len );
+ return -EINVAL;
+ }
+ content_len = ( plaintext_len - mac_len );
+ content = plaintext;
+ mac = ( content + content_len );
+
+ /* Fill in return values */
+ *data = content;
+ *len = content_len;
+ *digest = mac;
+
+ return 0;
+}
+
+/**
+ * Split block-ciphered record into data and MAC portions
+ *
+ * @v tls TLS session
+ * @v plaintext Plaintext record
+ * @v plaintext_len Length of record
+ * @ret data Data
+ * @ret len Length of data
+ * @ret digest MAC digest
+ * @ret rc Return status code
+ */
+static int tls_split_block ( struct tls_session *tls,
+ void *plaintext, size_t plaintext_len,
+ void **data, size_t *len,
+ void **digest ) {
+ void *iv;
+ size_t iv_len;
+ void *content;
+ size_t content_len;
+ void *mac;
+ size_t mac_len;
+ void *padding;
+ size_t padding_len;
+ unsigned int i;
+
+ /* Sanity check */
+ if ( plaintext_len < 1 ) {
+ DBGC ( tls, "TLS %p received underlength record\n", tls );
+ DBGC_HD ( tls, plaintext, plaintext_len );
+ return -EINVAL;
+ }
+
+ /* TLSv1.1 and later use an explicit IV */
+ iv_len = ( ( tls->version >= TLS_VERSION_TLS_1_1 ) ?
+ tls->rx_cipherspec.suite->cipher->blocksize : 0 );
+
+ /* Decompose block-ciphered data */
+ mac_len = tls->rx_cipherspec.suite->digest->digestsize;
+ padding_len = *( ( uint8_t * ) ( plaintext + plaintext_len - 1 ) );
+ if ( plaintext_len < ( iv_len + mac_len + padding_len + 1 ) ) {
+ DBGC ( tls, "TLS %p received underlength record\n", tls );
+ DBGC_HD ( tls, plaintext, plaintext_len );
+ return -EINVAL;
+ }
+ content_len = ( plaintext_len - iv_len - mac_len - padding_len - 1 );
+ iv = plaintext;
+ content = ( iv + iv_len );
+ mac = ( content + content_len );
+ padding = ( mac + mac_len );
+
+ /* Verify padding bytes */
+ for ( i = 0 ; i < padding_len ; i++ ) {
+ if ( *( ( uint8_t * ) ( padding + i ) ) != padding_len ) {
+ DBGC ( tls, "TLS %p received bad padding\n", tls );
+ DBGC_HD ( tls, plaintext, plaintext_len );
+ return -EINVAL;
+ }
+ }
+
+ /* Fill in return values */
+ *data = content;
+ *len = content_len;
+ *digest = mac;
+
+ return 0;
+}
+
+/**
+ * Receive new ciphertext record
+ *
+ * @v tls TLS session
+ * @v tlshdr Record header
+ * @v ciphertext Ciphertext record
+ * @ret rc Return status code
+ */
+static int tls_new_ciphertext ( struct tls_session *tls,
+ struct tls_header *tlshdr,
+ const void *ciphertext ) {
+ struct tls_header plaintext_tlshdr;
+ struct tls_cipherspec *cipherspec = &tls->rx_cipherspec;
+ struct cipher_algorithm *cipher = cipherspec->suite->cipher;
+ size_t record_len = ntohs ( tlshdr->length );
+ void *plaintext = NULL;
+ void *data;
+ size_t len;
+ void *mac;
+ size_t mac_len = cipherspec->suite->digest->digestsize;
+ uint8_t verify_mac[mac_len];
+ int rc;
+
+ /* Allocate buffer for plaintext */
+ plaintext = malloc ( record_len );
+ if ( ! plaintext ) {
+ DBGC ( tls, "TLS %p could not allocate %zd bytes for "
+ "decryption buffer\n", tls, record_len );
+ rc = -ENOMEM;
+ goto done;
+ }
+
+ /* Decrypt the record */
+ cipher_decrypt ( cipher, cipherspec->cipher_ctx,
+ ciphertext, plaintext, record_len );
+
+ /* Split record into content and MAC */
+ if ( is_stream_cipher ( cipher ) ) {
+ if ( ( rc = tls_split_stream ( tls, plaintext, record_len,
+ &data, &len, &mac ) ) != 0 )
+ goto done;
+ } else {
+ if ( ( rc = tls_split_block ( tls, plaintext, record_len,
+ &data, &len, &mac ) ) != 0 )
+ goto done;
+ }
+
+ /* Verify MAC */
+ plaintext_tlshdr.type = tlshdr->type;
+ plaintext_tlshdr.version = tlshdr->version;
+ plaintext_tlshdr.length = htons ( len );
+ tls_hmac ( tls, cipherspec, tls->rx_seq, &plaintext_tlshdr,
+ data, len, verify_mac);
+ if ( memcmp ( mac, verify_mac, mac_len ) != 0 ) {
+ DBGC ( tls, "TLS %p failed MAC verification\n", tls );
+ DBGC_HD ( tls, plaintext, record_len );
+ goto done;
+ }
+
+ DBGC2 ( tls, "Received plaintext data:\n" );
+ DBGC2_HD ( tls, data, len );
+
+ /* Process plaintext record */
+ if ( ( rc = tls_new_record ( tls, tlshdr->type, data, len ) ) != 0 )
+ goto done;
+
+ rc = 0;
+ done:
+ free ( plaintext );
+ return rc;
+}
+
+/******************************************************************************
+ *
+ * Plaintext stream operations
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Check flow control window
+ *
+ * @v tls TLS session
+ * @ret len Length of window
+ */
+static size_t tls_plainstream_window ( struct tls_session *tls ) {
+
+ /* Block window unless we are ready to accept data */
+ if ( ! tls_ready ( tls ) )
+ return 0;
+
+ return xfer_window ( &tls->cipherstream );
+}
+
+/**
+ * Deliver datagram as raw data
+ *
+ * @v tls TLS session
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int tls_plainstream_deliver ( struct tls_session *tls,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ int rc;
+
+ /* Refuse unless we are ready to accept data */
+ if ( ! tls_ready ( tls ) ) {
+ rc = -ENOTCONN;
+ goto done;
+ }
+
+ if ( ( rc = tls_send_plaintext ( tls, TLS_TYPE_DATA, iobuf->data,
+ iob_len ( iobuf ) ) ) != 0 )
+ goto done;
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** TLS plaintext stream interface operations */
+static struct interface_operation tls_plainstream_ops[] = {
+ INTF_OP ( xfer_deliver, struct tls_session *, tls_plainstream_deliver ),
+ INTF_OP ( xfer_window, struct tls_session *, tls_plainstream_window ),
+ INTF_OP ( intf_close, struct tls_session *, tls_close ),
+};
+
+/** TLS plaintext stream interface descriptor */
+static struct interface_descriptor tls_plainstream_desc =
+ INTF_DESC_PASSTHRU ( struct tls_session, plainstream,
+ tls_plainstream_ops, cipherstream );
+
+/******************************************************************************
+ *
+ * Ciphertext stream operations
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Handle received TLS header
+ *
+ * @v tls TLS session
+ * @ret rc Returned status code
+ */
+static int tls_newdata_process_header ( struct tls_session *tls ) {
+ size_t data_len = ntohs ( tls->rx_header.length );
+
+ /* Allocate data buffer now that we know the length */
+ assert ( tls->rx_data == NULL );
+ tls->rx_data = malloc ( data_len );
+ if ( ! tls->rx_data ) {
+ DBGC ( tls, "TLS %p could not allocate %zd bytes "
+ "for receive buffer\n", tls, data_len );
+ return -ENOMEM;
+ }
+
+ /* Move to data state */
+ tls->rx_state = TLS_RX_DATA;
+
+ return 0;
+}
+
+/**
+ * Handle received TLS data payload
+ *
+ * @v tls TLS session
+ * @ret rc Returned status code
+ */
+static int tls_newdata_process_data ( struct tls_session *tls ) {
+ int rc;
+
+ /* Process record */
+ if ( ( rc = tls_new_ciphertext ( tls, &tls->rx_header,
+ tls->rx_data ) ) != 0 )
+ return rc;
+
+ /* Increment RX sequence number */
+ tls->rx_seq += 1;
+
+ /* Free data buffer */
+ free ( tls->rx_data );
+ tls->rx_data = NULL;
+
+ /* Return to header state */
+ tls->rx_state = TLS_RX_HEADER;
+
+ return 0;
+}
+
+/**
+ * Receive new ciphertext
+ *
+ * @v tls TLS session
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadat
+ * @ret rc Return status code
+ */
+static int tls_cipherstream_deliver ( struct tls_session *tls,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *xfer __unused ) {
+ size_t frag_len;
+ void *buf;
+ size_t buf_len;
+ int ( * process ) ( struct tls_session *tls );
+ int rc;
+
+ while ( iob_len ( iobuf ) ) {
+ /* Select buffer according to current state */
+ switch ( tls->rx_state ) {
+ case TLS_RX_HEADER:
+ buf = &tls->rx_header;
+ buf_len = sizeof ( tls->rx_header );
+ process = tls_newdata_process_header;
+ break;
+ case TLS_RX_DATA:
+ buf = tls->rx_data;
+ buf_len = ntohs ( tls->rx_header.length );
+ process = tls_newdata_process_data;
+ break;
+ default:
+ assert ( 0 );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Copy data portion to buffer */
+ frag_len = ( buf_len - tls->rx_rcvd );
+ if ( frag_len > iob_len ( iobuf ) )
+ frag_len = iob_len ( iobuf );
+ memcpy ( ( buf + tls->rx_rcvd ), iobuf->data, frag_len );
+ tls->rx_rcvd += frag_len;
+ iob_pull ( iobuf, frag_len );
+
+ /* Process data if buffer is now full */
+ if ( tls->rx_rcvd == buf_len ) {
+ if ( ( rc = process ( tls ) ) != 0 ) {
+ tls_close ( tls, rc );
+ goto done;
+ }
+ tls->rx_rcvd = 0;
+ }
+ }
+ rc = 0;
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** TLS ciphertext stream interface operations */
+static struct interface_operation tls_cipherstream_ops[] = {
+ INTF_OP ( xfer_deliver, struct tls_session *,
+ tls_cipherstream_deliver ),
+ INTF_OP ( xfer_window_changed, struct tls_session *, tls_tx_resume ),
+ INTF_OP ( intf_close, struct tls_session *, tls_close ),
+};
+
+/** TLS ciphertext stream interface descriptor */
+static struct interface_descriptor tls_cipherstream_desc =
+ INTF_DESC_PASSTHRU ( struct tls_session, cipherstream,
+ tls_cipherstream_ops, plainstream );
+
+/******************************************************************************
+ *
+ * Certificate validator
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Handle certificate validation completion
+ *
+ * @v tls TLS session
+ * @v rc Reason for completion
+ */
+static void tls_validator_done ( struct tls_session *tls, int rc ) {
+ struct tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
+ struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
+ struct x509_certificate *cert;
+
+ /* Close validator interface */
+ intf_restart ( &tls->validator, rc );
+
+ /* Check for validation failure */
+ if ( rc != 0 ) {
+ DBGC ( tls, "TLS %p certificate validation failed: %s\n",
+ tls, strerror ( rc ) );
+ goto err;
+ }
+ DBGC ( tls, "TLS %p certificate validation succeeded\n", tls );
+
+ /* Extract first certificate */
+ cert = x509_first ( tls->chain );
+ assert ( cert != NULL );
+
+ /* Verify server name */
+ if ( ( cert->subject.name == NULL ) ||
+ ( strcmp ( cert->subject.name, tls->name ) != 0 ) ) {
+ DBGC ( tls, "TLS %p server name incorrect (expected %s, got "
+ "%s)\n", tls, tls->name, cert->subject.name );
+ rc = -EACCES_WRONG_NAME;
+ goto err;
+ }
+
+ /* Initialise public key algorithm */
+ if ( ( rc = pubkey_init ( pubkey, cipherspec->pubkey_ctx,
+ cert->subject.public_key.raw.data,
+ cert->subject.public_key.raw.len ) ) != 0 ) {
+ DBGC ( tls, "TLS %p cannot initialise public key: %s\n",
+ tls, strerror ( rc ) );
+ goto err;
+ }
+
+ /* Schedule Client Key Exchange, Change Cipher, and Finished */
+ tls->tx_pending |= ( TLS_TX_CLIENT_KEY_EXCHANGE |
+ TLS_TX_CHANGE_CIPHER |
+ TLS_TX_FINISHED );
+ tls_tx_resume ( tls );
+
+ return;
+
+ err:
+ tls_close ( tls, rc );
+ return;
+}
+
+/** TLS certificate validator interface operations */
+static struct interface_operation tls_validator_ops[] = {
+ INTF_OP ( intf_close, struct tls_session *, tls_validator_done ),
+};
+
+/** TLS certificate validator interface descriptor */
+static struct interface_descriptor tls_validator_desc =
+ INTF_DESC ( struct tls_session, validator, tls_validator_ops );
+
+/******************************************************************************
+ *
+ * Controlling process
+ *
+ ******************************************************************************
+ */
+
+/**
+ * TLS TX state machine
+ *
+ * @v tls TLS session
+ */
+static void tls_tx_step ( struct tls_session *tls ) {
+ int rc;
+
+ /* Wait for cipherstream to become ready */
+ if ( ! xfer_window ( &tls->cipherstream ) )
+ return;
+
+ /* Send first pending transmission */
+ if ( tls->tx_pending & TLS_TX_CLIENT_HELLO ) {
+ /* Send Client Hello */
+ if ( ( rc = tls_send_client_hello ( tls ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not send Client Hello: %s\n",
+ tls, strerror ( rc ) );
+ goto err;
+ }
+ tls->tx_pending &= ~TLS_TX_CLIENT_HELLO;
+ } else if ( tls->tx_pending & TLS_TX_CERTIFICATE ) {
+ /* Send Certificate */
+ if ( ( rc = tls_send_certificate ( tls ) ) != 0 ) {
+ DBGC ( tls, "TLS %p cold not send Certificate: %s\n",
+ tls, strerror ( rc ) );
+ goto err;
+ }
+ tls->tx_pending &= ~TLS_TX_CERTIFICATE;
+ } else if ( tls->tx_pending & TLS_TX_CLIENT_KEY_EXCHANGE ) {
+ /* Send Client Key Exchange */
+ if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not send Client Key "
+ "Exchange: %s\n", tls, strerror ( rc ) );
+ goto err;
+ }
+ tls->tx_pending &= ~TLS_TX_CLIENT_KEY_EXCHANGE;
+ } else if ( tls->tx_pending & TLS_TX_CERTIFICATE_VERIFY ) {
+ /* Send Certificate Verify */
+ if ( ( rc = tls_send_certificate_verify ( tls ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not send Certificate "
+ "Verify: %s\n", tls, strerror ( rc ) );
+ goto err;
+ }
+ tls->tx_pending &= ~TLS_TX_CERTIFICATE_VERIFY;
+ } else if ( tls->tx_pending & TLS_TX_CHANGE_CIPHER ) {
+ /* Send Change Cipher, and then change the cipher in use */
+ if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not send Change Cipher: "
+ "%s\n", tls, strerror ( rc ) );
+ goto err;
+ }
+ if ( ( rc = tls_change_cipher ( tls,
+ &tls->tx_cipherspec_pending,
+ &tls->tx_cipherspec )) != 0 ){
+ DBGC ( tls, "TLS %p could not activate TX cipher: "
+ "%s\n", tls, strerror ( rc ) );
+ goto err;
+ }
+ tls->tx_seq = 0;
+ tls->tx_pending &= ~TLS_TX_CHANGE_CIPHER;
+ } else if ( tls->tx_pending & TLS_TX_FINISHED ) {
+ /* Send Finished */
+ if ( ( rc = tls_send_finished ( tls ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not send Finished: %s\n",
+ tls, strerror ( rc ) );
+ goto err;
+ }
+ tls->tx_pending &= ~TLS_TX_FINISHED;
+ }
+
+ /* Reschedule process if pending transmissions remain */
+ if ( tls->tx_pending )
+ tls_tx_resume ( tls );
+
+ return;
+
+ err:
+ tls_close ( tls, rc );
+}
+
+/** TLS TX process descriptor */
+static struct process_descriptor tls_process_desc =
+ PROC_DESC_ONCE ( struct tls_session, process, tls_tx_step );
+
+/******************************************************************************
+ *
+ * Instantiator
+ *
+ ******************************************************************************
+ */
+
+int add_tls ( struct interface *xfer, const char *name,
+ struct interface **next ) {
+ struct tls_session *tls;
+ int rc;
+
+ /* Allocate and initialise TLS structure */
+ tls = malloc ( sizeof ( *tls ) );
+ if ( ! tls ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ memset ( tls, 0, sizeof ( *tls ) );
+ ref_init ( &tls->refcnt, free_tls );
+ tls->name = name;
+ intf_init ( &tls->plainstream, &tls_plainstream_desc, &tls->refcnt );
+ intf_init ( &tls->cipherstream, &tls_cipherstream_desc, &tls->refcnt );
+ intf_init ( &tls->validator, &tls_validator_desc, &tls->refcnt );
+ process_init ( &tls->process, &tls_process_desc, &tls->refcnt );
+ tls->version = TLS_VERSION_TLS_1_2;
+ tls_clear_cipher ( tls, &tls->tx_cipherspec );
+ tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
+ tls_clear_cipher ( tls, &tls->rx_cipherspec );
+ tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
+ tls->client_random.gmt_unix_time = time ( NULL );
+ if ( ( rc = tls_generate_random ( tls, &tls->client_random.random,
+ ( sizeof ( tls->client_random.random ) ) ) ) != 0 ) {
+ goto err_random;
+ }
+ tls->pre_master_secret.version = htons ( tls->version );
+ if ( ( rc = tls_generate_random ( tls, &tls->pre_master_secret.random,
+ ( sizeof ( tls->pre_master_secret.random ) ) ) ) != 0 ) {
+ goto err_random;
+ }
+ digest_init ( &md5_sha1_algorithm, tls->handshake_md5_sha1_ctx );
+ digest_init ( &sha256_algorithm, tls->handshake_sha256_ctx );
+ tls->handshake_digest = &sha256_algorithm;
+ tls->handshake_ctx = tls->handshake_sha256_ctx;
+ tls->tx_pending = TLS_TX_CLIENT_HELLO;
+
+ /* Attach to parent interface, mortalise self, and return */
+ intf_plug_plug ( &tls->plainstream, xfer );
+ *next = &tls->cipherstream;
+ ref_put ( &tls->refcnt );
+ return 0;
+
+ err_random:
+ ref_put ( &tls->refcnt );
+ err_alloc:
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/udp.c b/src/VBox/Devices/PC/ipxe/src/net/udp.c
new file mode 100644
index 00000000..20badb7f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/udp.c
@@ -0,0 +1,447 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/uri.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/udp.h>
+
+/** @file
+ *
+ * UDP protocol
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * A UDP connection
+ *
+ */
+struct udp_connection {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** List of UDP connections */
+ struct list_head list;
+
+ /** Data transfer interface */
+ struct interface xfer;
+
+ /** Local socket address */
+ struct sockaddr_tcpip local;
+ /** Remote socket address */
+ struct sockaddr_tcpip peer;
+};
+
+/**
+ * List of registered UDP connections
+ */
+static LIST_HEAD ( udp_conns );
+
+/* Forward declatations */
+static struct interface_descriptor udp_xfer_desc;
+struct tcpip_protocol udp_protocol __tcpip_protocol;
+
+/**
+ * Bind UDP connection to local port
+ *
+ * @v udp UDP connection
+ * @ret rc Return status code
+ *
+ * Opens the UDP connection and binds to the specified local port. If
+ * no local port is specified, the first available port will be used.
+ */
+static int udp_bind ( struct udp_connection *udp ) {
+ struct udp_connection *existing;
+ static uint16_t try_port = 1023;
+
+ /* If no port specified, find the first available port */
+ if ( ! udp->local.st_port ) {
+ while ( try_port ) {
+ try_port++;
+ if ( try_port < 1024 )
+ continue;
+ udp->local.st_port = htons ( try_port );
+ if ( udp_bind ( udp ) == 0 )
+ return 0;
+ }
+ return -EADDRINUSE;
+ }
+
+ /* Attempt bind to local port */
+ list_for_each_entry ( existing, &udp_conns, list ) {
+ if ( existing->local.st_port == udp->local.st_port ) {
+ DBGC ( udp, "UDP %p could not bind: port %d in use\n",
+ udp, ntohs ( udp->local.st_port ) );
+ return -EADDRINUSE;
+ }
+ }
+
+ /* Add to UDP connection list */
+ DBGC ( udp, "UDP %p bound to port %d\n",
+ udp, ntohs ( udp->local.st_port ) );
+
+ return 0;
+}
+
+/**
+ * Open a UDP connection
+ *
+ * @v xfer Data transfer interface
+ * @v peer Peer socket address, or NULL
+ * @v local Local socket address, or NULL
+ * @v promisc Socket is promiscuous
+ * @ret rc Return status code
+ */
+static int udp_open_common ( struct interface *xfer,
+ struct sockaddr *peer, struct sockaddr *local,
+ int promisc ) {
+ struct sockaddr_tcpip *st_peer = ( struct sockaddr_tcpip * ) peer;
+ struct sockaddr_tcpip *st_local = ( struct sockaddr_tcpip * ) local;
+ struct udp_connection *udp;
+ int rc;
+
+ /* Allocate and initialise structure */
+ udp = zalloc ( sizeof ( *udp ) );
+ if ( ! udp )
+ return -ENOMEM;
+ DBGC ( udp, "UDP %p allocated\n", udp );
+ ref_init ( &udp->refcnt, NULL );
+ intf_init ( &udp->xfer, &udp_xfer_desc, &udp->refcnt );
+ if ( st_peer )
+ memcpy ( &udp->peer, st_peer, sizeof ( udp->peer ) );
+ if ( st_local )
+ memcpy ( &udp->local, st_local, sizeof ( udp->local ) );
+
+ /* Bind to local port */
+ if ( ! promisc ) {
+ if ( ( rc = udp_bind ( udp ) ) != 0 )
+ goto err;
+ }
+
+ /* Attach parent interface, transfer reference to connection
+ * list and return
+ */
+ intf_plug_plug ( &udp->xfer, xfer );
+ list_add ( &udp->list, &udp_conns );
+ return 0;
+
+ err:
+ ref_put ( &udp->refcnt );
+ return rc;
+}
+
+/**
+ * Open a UDP connection
+ *
+ * @v xfer Data transfer interface
+ * @v peer Peer socket address
+ * @v local Local socket address, or NULL
+ * @ret rc Return status code
+ */
+int udp_open ( struct interface *xfer, struct sockaddr *peer,
+ struct sockaddr *local ) {
+ return udp_open_common ( xfer, peer, local, 0 );
+}
+
+/**
+ * Open a promiscuous UDP connection
+ *
+ * @v xfer Data transfer interface
+ * @ret rc Return status code
+ *
+ * Promiscuous UDP connections are required in order to support the
+ * PXE API.
+ */
+int udp_open_promisc ( struct interface *xfer ) {
+ return udp_open_common ( xfer, NULL, NULL, 1 );
+}
+
+/**
+ * Close a UDP connection
+ *
+ * @v udp UDP connection
+ * @v rc Reason for close
+ */
+static void udp_close ( struct udp_connection *udp, int rc ) {
+
+ /* Close data transfer interface */
+ intf_shutdown ( &udp->xfer, rc );
+
+ /* Remove from list of connections and drop list's reference */
+ list_del ( &udp->list );
+ ref_put ( &udp->refcnt );
+
+ DBGC ( udp, "UDP %p closed\n", udp );
+}
+
+/**
+ * Transmit data via a UDP connection to a specified address
+ *
+ * @v udp UDP connection
+ * @v iobuf I/O buffer
+ * @v src Source address, or NULL to use default
+ * @v dest Destination address, or NULL to use default
+ * @v netdev Network device, or NULL to use default
+ * @ret rc Return status code
+ */
+static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
+ struct sockaddr_tcpip *src, struct sockaddr_tcpip *dest,
+ struct net_device *netdev ) {
+ struct udp_header *udphdr;
+ size_t len;
+ int rc;
+
+ /* Check we can accommodate the header */
+ if ( ( rc = iob_ensure_headroom ( iobuf,
+ MAX_LL_NET_HEADER_LEN ) ) != 0 ) {
+ free_iob ( iobuf );
+ return rc;
+ }
+
+ /* Fill in default values if not explicitly provided */
+ if ( ! src )
+ src = &udp->local;
+ if ( ! dest )
+ dest = &udp->peer;
+
+ /* Add the UDP header */
+ udphdr = iob_push ( iobuf, sizeof ( *udphdr ) );
+ len = iob_len ( iobuf );
+ udphdr->dest = dest->st_port;
+ udphdr->src = src->st_port;
+ udphdr->len = htons ( len );
+ udphdr->chksum = 0;
+ udphdr->chksum = tcpip_chksum ( udphdr, len );
+
+ /* Dump debugging information */
+ DBGC ( udp, "UDP %p TX %d->%d len %d\n", udp,
+ ntohs ( udphdr->src ), ntohs ( udphdr->dest ),
+ ntohs ( udphdr->len ) );
+
+ /* Send it to the next layer for processing */
+ if ( ( rc = tcpip_tx ( iobuf, &udp_protocol, src, dest, netdev,
+ &udphdr->chksum ) ) != 0 ) {
+ DBGC ( udp, "UDP %p could not transmit packet: %s\n",
+ udp, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Identify UDP connection by local address
+ *
+ * @v local Local address
+ * @ret udp UDP connection, or NULL
+ */
+static struct udp_connection * udp_demux ( struct sockaddr_tcpip *local ) {
+ static const struct sockaddr_tcpip empty_sockaddr = { .pad = { 0, } };
+ struct udp_connection *udp;
+
+ list_for_each_entry ( udp, &udp_conns, list ) {
+ if ( ( ( udp->local.st_family == local->st_family ) ||
+ ( udp->local.st_family == 0 ) ) &&
+ ( ( udp->local.st_port == local->st_port ) ||
+ ( udp->local.st_port == 0 ) ) &&
+ ( ( memcmp ( udp->local.pad, local->pad,
+ sizeof ( udp->local.pad ) ) == 0 ) ||
+ ( memcmp ( udp->local.pad, empty_sockaddr.pad,
+ sizeof ( udp->local.pad ) ) == 0 ) ) ) {
+ return udp;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Process a received packet
+ *
+ * @v iobuf I/O buffer
+ * @v st_src Partially-filled source address
+ * @v st_dest Partially-filled destination address
+ * @v pshdr_csum Pseudo-header checksum
+ * @ret rc Return status code
+ */
+static int udp_rx ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum ) {
+ struct udp_header *udphdr = iobuf->data;
+ struct udp_connection *udp;
+ struct xfer_metadata meta;
+ size_t ulen;
+ unsigned int csum;
+ int rc = 0;
+
+ /* Sanity check packet */
+ if ( iob_len ( iobuf ) < sizeof ( *udphdr ) ) {
+ DBG ( "UDP packet too short at %zd bytes (min %zd bytes)\n",
+ iob_len ( iobuf ), sizeof ( *udphdr ) );
+
+ rc = -EINVAL;
+ goto done;
+ }
+ ulen = ntohs ( udphdr->len );
+ if ( ulen < sizeof ( *udphdr ) ) {
+ DBG ( "UDP length too short at %zd bytes "
+ "(header is %zd bytes)\n", ulen, sizeof ( *udphdr ) );
+ rc = -EINVAL;
+ goto done;
+ }
+ if ( ulen > iob_len ( iobuf ) ) {
+ DBG ( "UDP length too long at %zd bytes (packet is %zd "
+ "bytes)\n", ulen, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto done;
+ }
+ if ( udphdr->chksum ) {
+ csum = tcpip_continue_chksum ( pshdr_csum, iobuf->data, ulen );
+ if ( csum != 0 ) {
+ DBG ( "UDP checksum incorrect (is %04x including "
+ "checksum field, should be 0000)\n", csum );
+ rc = -EINVAL;
+ goto done;
+ }
+ }
+
+ /* Parse parameters from header and strip header */
+ st_src->st_port = udphdr->src;
+ st_dest->st_port = udphdr->dest;
+ udp = udp_demux ( st_dest );
+ iob_unput ( iobuf, ( iob_len ( iobuf ) - ulen ) );
+ iob_pull ( iobuf, sizeof ( *udphdr ) );
+
+ /* Dump debugging information */
+ DBGC ( udp, "UDP %p RX %d<-%d len %zd\n", udp,
+ ntohs ( udphdr->dest ), ntohs ( udphdr->src ), ulen );
+
+ /* Ignore if no matching connection found */
+ if ( ! udp ) {
+ DBG ( "No UDP connection listening on port %d\n",
+ ntohs ( udphdr->dest ) );
+ rc = -ENOTCONN;
+ goto done;
+ }
+
+ /* Pass data to application */
+ memset ( &meta, 0, sizeof ( meta ) );
+ meta.src = ( struct sockaddr * ) st_src;
+ meta.dest = ( struct sockaddr * ) st_dest;
+ rc = xfer_deliver ( &udp->xfer, iob_disown ( iobuf ), &meta );
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+struct tcpip_protocol udp_protocol __tcpip_protocol = {
+ .name = "UDP",
+ .rx = udp_rx,
+ .tcpip_proto = IP_UDP,
+};
+
+/***************************************************************************
+ *
+ * Data transfer interface
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Allocate I/O buffer for UDP
+ *
+ * @v udp UDP connection
+ * @v len Payload size
+ * @ret iobuf I/O buffer, or NULL
+ */
+static struct io_buffer * udp_xfer_alloc_iob ( struct udp_connection *udp,
+ size_t len ) {
+ struct io_buffer *iobuf;
+
+ iobuf = alloc_iob ( MAX_LL_NET_HEADER_LEN + len );
+ if ( ! iobuf ) {
+ DBGC ( udp, "UDP %p cannot allocate buffer of length %zd\n",
+ udp, len );
+ return NULL;
+ }
+ iob_reserve ( iobuf, MAX_LL_NET_HEADER_LEN );
+ return iobuf;
+}
+
+/**
+ * Deliver datagram as I/O buffer
+ *
+ * @v udp UDP connection
+ * @v iobuf Datagram I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int udp_xfer_deliver ( struct udp_connection *udp,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+
+ /* Transmit data, if possible */
+ return udp_tx ( udp, iobuf, ( ( struct sockaddr_tcpip * ) meta->src ),
+ ( ( struct sockaddr_tcpip * ) meta->dest ),
+ meta->netdev );
+}
+
+/** UDP data transfer interface operations */
+static struct interface_operation udp_xfer_operations[] = {
+ INTF_OP ( xfer_deliver, struct udp_connection *, udp_xfer_deliver ),
+ INTF_OP ( xfer_alloc_iob, struct udp_connection *, udp_xfer_alloc_iob ),
+ INTF_OP ( intf_close, struct udp_connection *, udp_close ),
+};
+
+/** UDP data transfer interface descriptor */
+static struct interface_descriptor udp_xfer_desc =
+ INTF_DESC ( struct udp_connection, xfer, udp_xfer_operations );
+
+/***************************************************************************
+ *
+ * Openers
+ *
+ ***************************************************************************
+ */
+
+/** UDP socket opener */
+struct socket_opener udp_socket_opener __socket_opener = {
+ .semantics = UDP_SOCK_DGRAM,
+ .family = AF_INET,
+ .open = udp_open,
+};
+
+/** Linkage hack */
+int udp_sock_dgram = UDP_SOCK_DGRAM;
+
+/**
+ * Open UDP URI
+ *
+ * @v xfer Data transfer interface
+ * @v uri URI
+ * @ret rc Return status code
+ */
+static int udp_open_uri ( struct interface *xfer, struct uri *uri ) {
+ struct sockaddr_tcpip peer;
+
+ /* Sanity check */
+ if ( ! uri->host )
+ return -EINVAL;
+
+ memset ( &peer, 0, sizeof ( peer ) );
+ peer.st_port = htons ( uri_port ( uri, 0 ) );
+ return xfer_open_named_socket ( xfer, SOCK_DGRAM,
+ ( struct sockaddr * ) &peer,
+ uri->host, NULL );
+}
+
+/** UDP URI opener */
+struct uri_opener udp_uri_opener __uri_opener = {
+ .scheme = "udp",
+ .open = udp_open_uri,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/udp/dhcp.c b/src/VBox/Devices/PC/ipxe/src/net/udp/dhcp.c
new file mode 100644
index 00000000..10482e94
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/udp/dhcp.c
@@ -0,0 +1,1480 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/device.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/job.h>
+#include <ipxe/retry.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/ip.h>
+#include <ipxe/uuid.h>
+#include <ipxe/timer.h>
+#include <ipxe/settings.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/dhcpopts.h>
+#include <ipxe/dhcppkt.h>
+#include <ipxe/dhcp_arch.h>
+#include <ipxe/features.h>
+
+/** @file
+ *
+ * Dynamic Host Configuration Protocol
+ *
+ */
+
+struct dhcp_session;
+static int dhcp_tx ( struct dhcp_session *dhcp );
+
+/**
+ * DHCP operation types
+ *
+ * This table maps from DHCP message types (i.e. values of the @c
+ * DHCP_MESSAGE_TYPE option) to values of the "op" field within a DHCP
+ * packet.
+ */
+static const uint8_t dhcp_op[] = {
+ [DHCPDISCOVER] = BOOTP_REQUEST,
+ [DHCPOFFER] = BOOTP_REPLY,
+ [DHCPREQUEST] = BOOTP_REQUEST,
+ [DHCPDECLINE] = BOOTP_REQUEST,
+ [DHCPACK] = BOOTP_REPLY,
+ [DHCPNAK] = BOOTP_REPLY,
+ [DHCPRELEASE] = BOOTP_REQUEST,
+ [DHCPINFORM] = BOOTP_REQUEST,
+};
+
+/** Raw option data for options common to all DHCP requests */
+static uint8_t dhcp_request_options_data[] = {
+ DHCP_MESSAGE_TYPE, DHCP_BYTE ( 0 ),
+ DHCP_MAX_MESSAGE_SIZE,
+ DHCP_WORD ( ETH_MAX_MTU - 20 /* IP header */ - 8 /* UDP header */ ),
+ DHCP_CLIENT_ARCHITECTURE, DHCP_ARCH_CLIENT_ARCHITECTURE,
+ DHCP_CLIENT_NDI, DHCP_ARCH_CLIENT_NDI,
+ DHCP_VENDOR_CLASS_ID, DHCP_ARCH_VENDOR_CLASS_ID,
+ DHCP_USER_CLASS_ID, DHCP_STRING ( 'i', 'P', 'X', 'E' ),
+ DHCP_PARAMETER_REQUEST_LIST,
+ DHCP_OPTION ( DHCP_SUBNET_MASK, DHCP_ROUTERS, DHCP_DNS_SERVERS,
+ DHCP_LOG_SERVERS, DHCP_HOST_NAME, DHCP_DOMAIN_NAME,
+ DHCP_ROOT_PATH, DHCP_VENDOR_ENCAP, DHCP_VENDOR_CLASS_ID,
+ DHCP_TFTP_SERVER_NAME, DHCP_BOOTFILE_NAME,
+ 128, 129, 130, 131, 132, 133, 134, 135, /* for PXE */
+ DHCP_EB_ENCAP, DHCP_ISCSI_INITIATOR_IQN ),
+ DHCP_END
+};
+
+/** Version number feature */
+FEATURE_VERSION ( VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH );
+
+/** DHCP server address setting */
+struct setting dhcp_server_setting __setting ( SETTING_MISC ) = {
+ .name = "dhcp-server",
+ .description = "DHCP server",
+ .tag = DHCP_SERVER_IDENTIFIER,
+ .type = &setting_type_ipv4,
+};
+
+/** DHCP user class setting */
+struct setting user_class_setting __setting ( SETTING_HOST_EXTRA ) = {
+ .name = "user-class",
+ .description = "DHCP user class",
+ .tag = DHCP_USER_CLASS_ID,
+ .type = &setting_type_string,
+};
+
+/** Use cached network settings */
+struct setting use_cached_setting __setting ( SETTING_MISC ) = {
+ .name = "use-cached",
+ .description = "Use cached settings",
+ .tag = DHCP_EB_USE_CACHED,
+ .type = &setting_type_uint8,
+};
+
+/**
+ * Most recent DHCP transaction ID
+ *
+ * This is exposed for use by the fakedhcp code when reconstructing
+ * DHCP packets for PXE NBPs.
+ */
+uint32_t dhcp_last_xid;
+
+/**
+ * Name a DHCP packet type
+ *
+ * @v msgtype DHCP message type
+ * @ret string DHCP mesasge type name
+ */
+static inline const char * dhcp_msgtype_name ( unsigned int msgtype ) {
+ switch ( msgtype ) {
+ case DHCPNONE: return "BOOTP"; /* Non-DHCP packet */
+ case DHCPDISCOVER: return "DHCPDISCOVER";
+ case DHCPOFFER: return "DHCPOFFER";
+ case DHCPREQUEST: return "DHCPREQUEST";
+ case DHCPDECLINE: return "DHCPDECLINE";
+ case DHCPACK: return "DHCPACK";
+ case DHCPNAK: return "DHCPNAK";
+ case DHCPRELEASE: return "DHCPRELEASE";
+ case DHCPINFORM: return "DHCPINFORM";
+ default: return "DHCP<invalid>";
+ }
+}
+
+/****************************************************************************
+ *
+ * DHCP session
+ *
+ */
+
+struct dhcp_session;
+
+/** DHCP session state operations */
+struct dhcp_session_state {
+ /** State name */
+ const char *name;
+ /**
+ * Construct transmitted packet
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer Destination address
+ */
+ int ( * tx ) ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer );
+ /** Handle received packet
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer DHCP server address
+ * @v msgtype DHCP message type
+ * @v server_id DHCP server ID
+ */
+ void ( * rx ) ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer,
+ uint8_t msgtype, struct in_addr server_id );
+ /** Handle timer expiry
+ *
+ * @v dhcp DHCP session
+ */
+ void ( * expired ) ( struct dhcp_session *dhcp );
+ /** Transmitted message type */
+ uint8_t tx_msgtype;
+ /** Apply minimum timeout */
+ uint8_t apply_min_timeout;
+};
+
+static struct dhcp_session_state dhcp_state_discover;
+static struct dhcp_session_state dhcp_state_request;
+static struct dhcp_session_state dhcp_state_proxy;
+static struct dhcp_session_state dhcp_state_pxebs;
+
+/** A DHCP session */
+struct dhcp_session {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Job control interface */
+ struct interface job;
+ /** Data transfer interface */
+ struct interface xfer;
+
+ /** Network device being configured */
+ struct net_device *netdev;
+ /** Local socket address */
+ struct sockaddr_in local;
+ /** State of the session */
+ struct dhcp_session_state *state;
+ /** Transaction ID (in network-endian order) */
+ uint32_t xid;
+
+ /** Offered IP address */
+ struct in_addr offer;
+ /** DHCP server */
+ struct in_addr server;
+ /** DHCP offer priority */
+ int priority;
+
+ /** ProxyDHCP protocol extensions should be ignored */
+ int no_pxedhcp;
+ /** ProxyDHCP server */
+ struct in_addr proxy_server;
+ /** ProxyDHCP offer */
+ struct dhcp_packet *proxy_offer;
+ /** ProxyDHCP offer priority */
+ int proxy_priority;
+
+ /** PXE Boot Server type */
+ uint16_t pxe_type;
+ /** List of PXE Boot Servers to attempt */
+ struct in_addr *pxe_attempt;
+ /** List of PXE Boot Servers to accept */
+ struct in_addr *pxe_accept;
+
+ /** Retransmission timer */
+ struct retry_timer timer;
+ /** Transmission counter */
+ unsigned int count;
+ /** Start time of the current state (in ticks) */
+ unsigned long start;
+};
+
+/**
+ * Free DHCP session
+ *
+ * @v refcnt Reference counter
+ */
+static void dhcp_free ( struct refcnt *refcnt ) {
+ struct dhcp_session *dhcp =
+ container_of ( refcnt, struct dhcp_session, refcnt );
+
+ netdev_put ( dhcp->netdev );
+ dhcppkt_put ( dhcp->proxy_offer );
+ free ( dhcp );
+}
+
+/**
+ * Mark DHCP session as complete
+ *
+ * @v dhcp DHCP session
+ * @v rc Return status code
+ */
+static void dhcp_finished ( struct dhcp_session *dhcp, int rc ) {
+
+ /* Stop retry timer */
+ stop_timer ( &dhcp->timer );
+
+ /* Shut down interfaces */
+ intf_shutdown ( &dhcp->xfer, rc );
+ intf_shutdown ( &dhcp->job, rc );
+}
+
+/**
+ * Transition to new DHCP session state
+ *
+ * @v dhcp DHCP session
+ * @v state New session state
+ */
+static void dhcp_set_state ( struct dhcp_session *dhcp,
+ struct dhcp_session_state *state ) {
+
+ DBGC ( dhcp, "DHCP %p entering %s state\n", dhcp, state->name );
+ dhcp->state = state;
+ dhcp->start = currticks();
+ stop_timer ( &dhcp->timer );
+ dhcp->timer.min_timeout =
+ ( state->apply_min_timeout ? DHCP_MIN_TIMEOUT : 0 );
+ dhcp->timer.max_timeout = DHCP_MAX_TIMEOUT;
+ start_timer_nodelay ( &dhcp->timer );
+}
+
+/**
+ * Check if DHCP packet contains PXE options
+ *
+ * @v dhcppkt DHCP packet
+ * @ret has_pxeopts DHCP packet contains PXE options
+ *
+ * It is assumed that the packet is already known to contain option 60
+ * set to "PXEClient".
+ */
+static int dhcp_has_pxeopts ( struct dhcp_packet *dhcppkt ) {
+
+ /* Check for a boot filename */
+ if ( dhcppkt_fetch ( dhcppkt, DHCP_BOOTFILE_NAME, NULL, 0 ) > 0 )
+ return 1;
+
+ /* Check for a PXE boot menu */
+ if ( dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU, NULL, 0 ) > 0 )
+ return 1;
+
+ return 0;
+}
+
+/****************************************************************************
+ *
+ * DHCP state machine
+ *
+ */
+
+/**
+ * Construct transmitted packet for DHCP discovery
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer Destination address
+ */
+static int dhcp_discovery_tx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt __unused,
+ struct sockaddr_in *peer ) {
+
+ DBGC ( dhcp, "DHCP %p DHCPDISCOVER\n", dhcp );
+
+ /* Set server address */
+ peer->sin_addr.s_addr = INADDR_BROADCAST;
+ peer->sin_port = htons ( BOOTPS_PORT );
+
+ return 0;
+}
+
+/**
+ * Handle received packet during DHCP discovery
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer DHCP server address
+ * @v msgtype DHCP message type
+ * @v server_id DHCP server ID
+ */
+static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer, uint8_t msgtype,
+ struct in_addr server_id ) {
+ struct in_addr ip;
+ char vci[9]; /* "PXEClient" */
+ int vci_len;
+ int has_pxeclient;
+ int8_t priority = 0;
+ uint8_t no_pxedhcp = 0;
+ unsigned long elapsed;
+
+ DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
+ dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
+ ntohs ( peer->sin_port ) );
+ if ( server_id.s_addr != peer->sin_addr.s_addr )
+ DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
+
+ /* Identify offered IP address */
+ ip = dhcppkt->dhcphdr->yiaddr;
+ if ( ip.s_addr )
+ DBGC ( dhcp, " for %s", inet_ntoa ( ip ) );
+
+ /* Identify "PXEClient" vendor class */
+ vci_len = dhcppkt_fetch ( dhcppkt, DHCP_VENDOR_CLASS_ID,
+ vci, sizeof ( vci ) );
+ has_pxeclient = ( ( vci_len >= ( int ) sizeof ( vci ) ) &&
+ ( strncmp ( "PXEClient", vci, sizeof (vci) ) == 0 ));
+ if ( has_pxeclient ) {
+ DBGC ( dhcp, "%s",
+ ( dhcp_has_pxeopts ( dhcppkt ) ? " pxe" : " proxy" ) );
+ }
+
+ /* Identify priority */
+ dhcppkt_fetch ( dhcppkt, DHCP_EB_PRIORITY, &priority,
+ sizeof ( priority ) );
+ if ( priority )
+ DBGC ( dhcp, " pri %d", priority );
+
+ /* Identify ignore-PXE flag */
+ dhcppkt_fetch ( dhcppkt, DHCP_EB_NO_PXEDHCP, &no_pxedhcp,
+ sizeof ( no_pxedhcp ) );
+ if ( no_pxedhcp )
+ DBGC ( dhcp, " nopxe" );
+ DBGC ( dhcp, "\n" );
+
+ /* Select as DHCP offer, if applicable */
+ if ( ip.s_addr && ( peer->sin_port == htons ( BOOTPS_PORT ) ) &&
+ ( ( msgtype == DHCPOFFER ) || ( ! msgtype /* BOOTP */ ) ) &&
+ ( priority >= dhcp->priority ) ) {
+ dhcp->offer = ip;
+ dhcp->server = server_id;
+ dhcp->priority = priority;
+ dhcp->no_pxedhcp = no_pxedhcp;
+ }
+
+ /* Select as ProxyDHCP offer, if applicable */
+ if ( server_id.s_addr && has_pxeclient &&
+ ( priority >= dhcp->proxy_priority ) ) {
+ dhcppkt_put ( dhcp->proxy_offer );
+ dhcp->proxy_server = server_id;
+ dhcp->proxy_offer = dhcppkt_get ( dhcppkt );
+ dhcp->proxy_priority = priority;
+ }
+
+ /* We can exit the discovery state when we have a valid
+ * DHCPOFFER, and either:
+ *
+ * o The DHCPOFFER instructs us to ignore ProxyDHCPOFFERs, or
+ * o We have a valid ProxyDHCPOFFER, or
+ * o We have allowed sufficient time for ProxyDHCPOFFERs.
+ */
+
+ /* If we don't yet have a DHCPOFFER, do nothing */
+ if ( ! dhcp->offer.s_addr )
+ return;
+
+ /* If we can't yet transition to DHCPREQUEST, do nothing */
+ elapsed = ( currticks() - dhcp->start );
+ if ( ! ( dhcp->no_pxedhcp || dhcp->proxy_offer ||
+ ( elapsed > PROXYDHCP_MAX_TIMEOUT ) ) )
+ return;
+
+ /* Transition to DHCPREQUEST */
+ dhcp_set_state ( dhcp, &dhcp_state_request );
+}
+
+/**
+ * Handle timer expiry during DHCP discovery
+ *
+ * @v dhcp DHCP session
+ */
+static void dhcp_discovery_expired ( struct dhcp_session *dhcp ) {
+ unsigned long elapsed = ( currticks() - dhcp->start );
+
+ /* Give up waiting for ProxyDHCP before we reach the failure point */
+ if ( dhcp->offer.s_addr && ( elapsed > PROXYDHCP_MAX_TIMEOUT ) ) {
+ dhcp_set_state ( dhcp, &dhcp_state_request );
+ return;
+ }
+
+ /* Otherwise, retransmit current packet */
+ dhcp_tx ( dhcp );
+}
+
+/** DHCP discovery state operations */
+static struct dhcp_session_state dhcp_state_discover = {
+ .name = "discovery",
+ .tx = dhcp_discovery_tx,
+ .rx = dhcp_discovery_rx,
+ .expired = dhcp_discovery_expired,
+ .tx_msgtype = DHCPDISCOVER,
+ .apply_min_timeout = 1,
+};
+
+/**
+ * Construct transmitted packet for DHCP request
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer Destination address
+ */
+static int dhcp_request_tx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer ) {
+ int rc;
+
+ DBGC ( dhcp, "DHCP %p DHCPREQUEST to %s:%d",
+ dhcp, inet_ntoa ( dhcp->server ), BOOTPS_PORT );
+ DBGC ( dhcp, " for %s\n", inet_ntoa ( dhcp->offer ) );
+
+ /* Set server ID */
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
+ &dhcp->server,
+ sizeof ( dhcp->server ) ) ) != 0 )
+ return rc;
+
+ /* Set requested IP address */
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_REQUESTED_ADDRESS,
+ &dhcp->offer,
+ sizeof ( dhcp->offer ) ) ) != 0 )
+ return rc;
+
+ /* Set server address */
+ peer->sin_addr.s_addr = INADDR_BROADCAST;
+ peer->sin_port = htons ( BOOTPS_PORT );
+
+ return 0;
+}
+
+/**
+ * Handle received packet during DHCP request
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer DHCP server address
+ * @v msgtype DHCP message type
+ * @v server_id DHCP server ID
+ */
+static void dhcp_request_rx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer, uint8_t msgtype,
+ struct in_addr server_id ) {
+ struct in_addr ip;
+ struct settings *parent;
+ struct settings *settings;
+ int rc;
+
+ DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
+ dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
+ ntohs ( peer->sin_port ) );
+ if ( server_id.s_addr != peer->sin_addr.s_addr )
+ DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
+
+ /* Identify leased IP address */
+ ip = dhcppkt->dhcphdr->yiaddr;
+ if ( ip.s_addr )
+ DBGC ( dhcp, " for %s", inet_ntoa ( ip ) );
+ DBGC ( dhcp, "\n" );
+
+ /* Filter out unacceptable responses */
+ if ( peer->sin_port != htons ( BOOTPS_PORT ) )
+ return;
+ if ( msgtype /* BOOTP */ && ( msgtype != DHCPACK ) )
+ return;
+ if ( server_id.s_addr != dhcp->server.s_addr )
+ return;
+ if ( ip.s_addr != dhcp->offer.s_addr )
+ return;
+
+ /* Record assigned address */
+ dhcp->local.sin_addr = ip;
+
+ /* Register settings */
+ parent = netdev_settings ( dhcp->netdev );
+ settings = &dhcppkt->settings;
+ if ( ( rc = register_settings ( settings, parent,
+ DHCP_SETTINGS_NAME ) ) != 0 ) {
+ DBGC ( dhcp, "DHCP %p could not register settings: %s\n",
+ dhcp, strerror ( rc ) );
+ dhcp_finished ( dhcp, rc );
+ return;
+ }
+
+ /* Perform ProxyDHCP if applicable */
+ if ( dhcp->proxy_offer /* Have ProxyDHCP offer */ &&
+ ( ! dhcp->no_pxedhcp ) /* ProxyDHCP not disabled */ ) {
+ if ( dhcp_has_pxeopts ( dhcp->proxy_offer ) ) {
+ /* PXE options already present; register settings
+ * without performing a ProxyDHCPREQUEST
+ */
+ settings = &dhcp->proxy_offer->settings;
+ if ( ( rc = register_settings ( settings, NULL,
+ PROXYDHCP_SETTINGS_NAME ) ) != 0 ) {
+ DBGC ( dhcp, "DHCP %p could not register "
+ "proxy settings: %s\n",
+ dhcp, strerror ( rc ) );
+ dhcp_finished ( dhcp, rc );
+ return;
+ }
+ } else {
+ /* PXE options not present; use a ProxyDHCPREQUEST */
+ dhcp_set_state ( dhcp, &dhcp_state_proxy );
+ return;
+ }
+ }
+
+ /* Terminate DHCP */
+ dhcp_finished ( dhcp, 0 );
+}
+
+/**
+ * Handle timer expiry during DHCP discovery
+ *
+ * @v dhcp DHCP session
+ */
+static void dhcp_request_expired ( struct dhcp_session *dhcp ) {
+
+ /* Retransmit current packet */
+ dhcp_tx ( dhcp );
+}
+
+/** DHCP request state operations */
+static struct dhcp_session_state dhcp_state_request = {
+ .name = "request",
+ .tx = dhcp_request_tx,
+ .rx = dhcp_request_rx,
+ .expired = dhcp_request_expired,
+ .tx_msgtype = DHCPREQUEST,
+ .apply_min_timeout = 0,
+};
+
+/**
+ * Construct transmitted packet for ProxyDHCP request
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer Destination address
+ */
+static int dhcp_proxy_tx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer ) {
+ int rc;
+
+ DBGC ( dhcp, "DHCP %p ProxyDHCP REQUEST to %s\n", dhcp,
+ inet_ntoa ( dhcp->proxy_server ) );
+
+ /* Set server ID */
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
+ &dhcp->proxy_server,
+ sizeof ( dhcp->proxy_server ) ) ) != 0 )
+ return rc;
+
+ /* Set server address */
+ peer->sin_addr = dhcp->proxy_server;
+ peer->sin_port = htons ( PXE_PORT );
+
+ return 0;
+}
+
+/**
+ * Handle received packet during ProxyDHCP request
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer DHCP server address
+ * @v msgtype DHCP message type
+ * @v server_id DHCP server ID
+ */
+static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer, uint8_t msgtype,
+ struct in_addr server_id ) {
+ struct settings *settings = &dhcppkt->settings;
+ int rc;
+
+ DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
+ dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
+ ntohs ( peer->sin_port ) );
+ if ( server_id.s_addr != peer->sin_addr.s_addr )
+ DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
+ DBGC ( dhcp, "\n" );
+
+ /* Filter out unacceptable responses */
+ if ( peer->sin_port != ntohs ( PXE_PORT ) )
+ return;
+ if ( ( msgtype != DHCPOFFER ) && ( msgtype != DHCPACK ) )
+ return;
+ if ( server_id.s_addr /* Linux PXE server omits server ID */ &&
+ ( server_id.s_addr != dhcp->proxy_server.s_addr ) )
+ return;
+
+ /* Register settings */
+ if ( ( rc = register_settings ( settings, NULL,
+ PROXYDHCP_SETTINGS_NAME ) ) != 0 ) {
+ DBGC ( dhcp, "DHCP %p could not register proxy settings: %s\n",
+ dhcp, strerror ( rc ) );
+ dhcp_finished ( dhcp, rc );
+ return;
+ }
+
+ /* Terminate DHCP */
+ dhcp_finished ( dhcp, 0 );
+}
+
+/**
+ * Handle timer expiry during ProxyDHCP request
+ *
+ * @v dhcp DHCP session
+ */
+static void dhcp_proxy_expired ( struct dhcp_session *dhcp ) {
+ unsigned long elapsed = ( currticks() - dhcp->start );
+
+ /* Give up waiting for ProxyDHCP before we reach the failure point */
+ if ( elapsed > PROXYDHCP_MAX_TIMEOUT ) {
+ dhcp_finished ( dhcp, 0 );
+ return;
+ }
+
+ /* Retransmit current packet */
+ dhcp_tx ( dhcp );
+}
+
+/** ProxyDHCP request state operations */
+static struct dhcp_session_state dhcp_state_proxy = {
+ .name = "ProxyDHCP",
+ .tx = dhcp_proxy_tx,
+ .rx = dhcp_proxy_rx,
+ .expired = dhcp_proxy_expired,
+ .tx_msgtype = DHCPREQUEST,
+ .apply_min_timeout = 0,
+};
+
+/**
+ * Construct transmitted packet for PXE Boot Server Discovery
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer Destination address
+ */
+static int dhcp_pxebs_tx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer ) {
+ struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
+ int rc;
+
+ /* Set server address */
+ peer->sin_addr = *(dhcp->pxe_attempt);
+ peer->sin_port = ( ( peer->sin_addr.s_addr == INADDR_BROADCAST ) ?
+ htons ( BOOTPS_PORT ) : htons ( PXE_PORT ) );
+
+ DBGC ( dhcp, "DHCP %p PXEBS REQUEST to %s:%d for type %d\n",
+ dhcp, inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ),
+ le16_to_cpu ( dhcp->pxe_type ) );
+
+ /* Set boot menu item */
+ menu_item.type = dhcp->pxe_type;
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM,
+ &menu_item, sizeof ( menu_item ) ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Check to see if PXE Boot Server address is acceptable
+ *
+ * @v dhcp DHCP session
+ * @v bs Boot Server address
+ * @ret accept Boot Server is acceptable
+ */
+static int dhcp_pxebs_accept ( struct dhcp_session *dhcp,
+ struct in_addr bs ) {
+ struct in_addr *accept;
+
+ /* Accept if we have no acceptance filter */
+ if ( ! dhcp->pxe_accept )
+ return 1;
+
+ /* Scan through acceptance list */
+ for ( accept = dhcp->pxe_accept ; accept->s_addr ; accept++ ) {
+ if ( accept->s_addr == bs.s_addr )
+ return 1;
+ }
+
+ DBGC ( dhcp, "DHCP %p rejecting server %s\n",
+ dhcp, inet_ntoa ( bs ) );
+ return 0;
+}
+
+/**
+ * Handle received packet during PXE Boot Server Discovery
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer DHCP server address
+ * @v msgtype DHCP message type
+ * @v server_id DHCP server ID
+ */
+static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer, uint8_t msgtype,
+ struct in_addr server_id ) {
+ struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
+ int rc;
+
+ DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
+ dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
+ ntohs ( peer->sin_port ) );
+ if ( server_id.s_addr != peer->sin_addr.s_addr )
+ DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
+
+ /* Identify boot menu item */
+ dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM,
+ &menu_item, sizeof ( menu_item ) );
+ if ( menu_item.type )
+ DBGC ( dhcp, " for type %d", ntohs ( menu_item.type ) );
+ DBGC ( dhcp, "\n" );
+
+ /* Filter out unacceptable responses */
+ if ( ( peer->sin_port != htons ( BOOTPS_PORT ) ) &&
+ ( peer->sin_port != htons ( PXE_PORT ) ) )
+ return;
+ if ( msgtype != DHCPACK )
+ return;
+ if ( menu_item.type != dhcp->pxe_type )
+ return;
+ if ( ! dhcp_pxebs_accept ( dhcp, ( server_id.s_addr ?
+ server_id : peer->sin_addr ) ) )
+ return;
+
+ /* Register settings */
+ if ( ( rc = register_settings ( &dhcppkt->settings, NULL,
+ PXEBS_SETTINGS_NAME ) ) != 0 ) {
+ DBGC ( dhcp, "DHCP %p could not register settings: %s\n",
+ dhcp, strerror ( rc ) );
+ dhcp_finished ( dhcp, rc );
+ return;
+ }
+
+ /* Terminate DHCP */
+ dhcp_finished ( dhcp, 0 );
+}
+
+/**
+ * Handle timer expiry during PXE Boot Server Discovery
+ *
+ * @v dhcp DHCP session
+ */
+static void dhcp_pxebs_expired ( struct dhcp_session *dhcp ) {
+ unsigned long elapsed = ( currticks() - dhcp->start );
+
+ /* Give up waiting before we reach the failure point, and fail
+ * over to the next server in the attempt list
+ */
+ if ( elapsed > PXEBS_MAX_TIMEOUT ) {
+ dhcp->pxe_attempt++;
+ if ( dhcp->pxe_attempt->s_addr ) {
+ dhcp_set_state ( dhcp, &dhcp_state_pxebs );
+ return;
+ } else {
+ dhcp_finished ( dhcp, -ETIMEDOUT );
+ return;
+ }
+ }
+
+ /* Retransmit current packet */
+ dhcp_tx ( dhcp );
+}
+
+/** PXE Boot Server Discovery state operations */
+static struct dhcp_session_state dhcp_state_pxebs = {
+ .name = "PXEBS",
+ .tx = dhcp_pxebs_tx,
+ .rx = dhcp_pxebs_rx,
+ .expired = dhcp_pxebs_expired,
+ .tx_msgtype = DHCPREQUEST,
+ .apply_min_timeout = 1,
+};
+
+/****************************************************************************
+ *
+ * Packet construction
+ *
+ */
+
+/**
+ * Construct DHCP client hardware address field and broadcast flag
+ *
+ * @v netdev Network device
+ * @v chaddr Hardware address buffer
+ * @v flags Flags to set (or NULL)
+ * @ret hlen Hardware address length
+ */
+unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr,
+ uint16_t *flags ) {
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+ struct dhcphdr *dhcphdr;
+ int rc;
+
+ /* If the link-layer address cannot fit into the chaddr field
+ * (as is the case for IPoIB) then try using the Ethernet-
+ * compatible link-layer address. If we do this, set the
+ * broadcast flag, since chaddr then does not represent a
+ * valid link-layer address for the return path.
+ *
+ * If we cannot produce an Ethernet-compatible link-layer
+ * address, try using the hardware address.
+ *
+ * If even the hardware address is too large, use an empty
+ * chaddr field and set the broadcast flag.
+ *
+ * This goes against RFC4390, but RFC4390 mandates that we use
+ * a DHCP client identifier that conforms with RFC4361, which
+ * we cannot do without either persistent (NIC-independent)
+ * storage, or by eliminating the hardware address completely
+ * from the DHCP packet, which seems unfriendly to users.
+ */
+ if ( ll_protocol->ll_addr_len <= sizeof ( dhcphdr->chaddr ) ) {
+ memcpy ( chaddr, netdev->ll_addr, ll_protocol->ll_addr_len );
+ return ll_protocol->ll_addr_len;
+ }
+ if ( flags )
+ *flags |= htons ( BOOTP_FL_BROADCAST );
+ if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr, chaddr ) ) == 0 )
+ return ETH_ALEN;
+ if ( ll_protocol->hw_addr_len <= sizeof ( dhcphdr->chaddr ) ) {
+ memcpy ( chaddr, netdev->hw_addr, ll_protocol->hw_addr_len );
+ return ll_protocol->hw_addr_len;
+ }
+ return 0;
+}
+
+/**
+ * Create a DHCP packet
+ *
+ * @v dhcppkt DHCP packet structure to fill in
+ * @v netdev Network device
+ * @v msgtype DHCP message type
+ * @v xid Transaction ID (in network-endian order)
+ * @v options Initial options to include (or NULL)
+ * @v options_len Length of initial options
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ *
+ * Creates a DHCP packet in the specified buffer, and initialise a
+ * DHCP packet structure.
+ */
+int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev, uint8_t msgtype,
+ uint32_t xid, const void *options, size_t options_len,
+ void *data, size_t max_len ) {
+ struct dhcphdr *dhcphdr = data;
+ int rc;
+
+ /* Sanity check */
+ if ( max_len < ( sizeof ( *dhcphdr ) + options_len ) )
+ return -ENOSPC;
+
+ /* Initialise DHCP packet content */
+ memset ( dhcphdr, 0, max_len );
+ dhcphdr->xid = xid;
+ dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
+ dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto );
+ dhcphdr->op = dhcp_op[msgtype];
+ dhcphdr->hlen = dhcp_chaddr ( netdev, dhcphdr->chaddr,
+ &dhcphdr->flags );
+ memcpy ( dhcphdr->options, options, options_len );
+
+ /* Initialise DHCP packet structure */
+ memset ( dhcppkt, 0, sizeof ( *dhcppkt ) );
+ dhcppkt_init ( dhcppkt, data, max_len );
+
+ /* Set DHCP_MESSAGE_TYPE option */
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_MESSAGE_TYPE,
+ &msgtype, sizeof ( msgtype ) ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Create DHCP request packet
+ *
+ * @v dhcppkt DHCP packet structure to fill in
+ * @v netdev Network device
+ * @v msgtype DHCP message type
+ * @v xid Transaction ID (in network-endian order)
+ * @v ciaddr Client IP address
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ *
+ * Creates a DHCP request packet in the specified buffer, and
+ * initialise a DHCP packet structure.
+ */
+int dhcp_create_request ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev, unsigned int msgtype,
+ uint32_t xid, struct in_addr ciaddr,
+ void *data, size_t max_len ) {
+ struct dhcp_netdev_desc dhcp_desc;
+ struct dhcp_client_id client_id;
+ struct dhcp_client_uuid client_uuid;
+ uint8_t *dhcp_features;
+ size_t dhcp_features_len;
+ size_t ll_addr_len;
+ ssize_t len;
+ int rc;
+
+ /* Create DHCP packet */
+ if ( ( rc = dhcp_create_packet ( dhcppkt, netdev, msgtype, xid,
+ dhcp_request_options_data,
+ sizeof ( dhcp_request_options_data ),
+ data, max_len ) ) != 0 ) {
+ DBG ( "DHCP could not create DHCP packet: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Set client IP address */
+ dhcppkt->dhcphdr->ciaddr = ciaddr;
+
+ /* Add options to identify the feature list */
+ dhcp_features = table_start ( DHCP_FEATURES );
+ dhcp_features_len = table_num_entries ( DHCP_FEATURES );
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_ENCAP, dhcp_features,
+ dhcp_features_len ) ) != 0 ) {
+ DBG ( "DHCP could not set features list option: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Add options to identify the network device */
+ fetch_setting ( &netdev->settings.settings, &busid_setting, &dhcp_desc,
+ sizeof ( dhcp_desc ) );
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_BUS_ID, &dhcp_desc,
+ sizeof ( dhcp_desc ) ) ) != 0 ) {
+ DBG ( "DHCP could not set bus ID option: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Add DHCP client identifier. Required for Infiniband, and
+ * doesn't hurt other link layers.
+ */
+ client_id.ll_proto = ntohs ( netdev->ll_protocol->ll_proto );
+ ll_addr_len = netdev->ll_protocol->ll_addr_len;
+ assert ( ll_addr_len <= sizeof ( client_id.ll_addr ) );
+ memcpy ( client_id.ll_addr, netdev->ll_addr, ll_addr_len );
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_ID, &client_id,
+ ( ll_addr_len + 1 ) ) ) != 0 ) {
+ DBG ( "DHCP could not set client ID: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Add client UUID, if we have one. Required for PXE. */
+ client_uuid.type = DHCP_CLIENT_UUID_TYPE;
+ if ( ( len = fetch_uuid_setting ( NULL, &uuid_setting,
+ &client_uuid.uuid ) ) >= 0 ) {
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_UUID,
+ &client_uuid,
+ sizeof ( client_uuid ) ) ) != 0 ) {
+ DBG ( "DHCP could not set client UUID: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+ }
+
+ /* Add user class, if we have one. */
+ if ( ( len = fetch_setting_len ( NULL, &user_class_setting ) ) >= 0 ) {
+ char user_class[len];
+ fetch_setting ( NULL, &user_class_setting, user_class,
+ sizeof ( user_class ) );
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_USER_CLASS_ID,
+ &user_class,
+ sizeof ( user_class ) ) ) != 0 ) {
+ DBG ( "DHCP could not set user class: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ *
+ * Data transfer interface
+ *
+ */
+
+/**
+ * Transmit DHCP request
+ *
+ * @v dhcp DHCP session
+ * @ret rc Return status code
+ */
+static int dhcp_tx ( struct dhcp_session *dhcp ) {
+ static struct sockaddr_in peer = {
+ .sin_family = AF_INET,
+ };
+ struct xfer_metadata meta = {
+ .netdev = dhcp->netdev,
+ .src = ( struct sockaddr * ) &dhcp->local,
+ .dest = ( struct sockaddr * ) &peer,
+ };
+ struct io_buffer *iobuf;
+ uint8_t msgtype = dhcp->state->tx_msgtype;
+ struct dhcp_packet dhcppkt;
+ int rc;
+
+ /* Start retry timer. Do this first so that failures to
+ * transmit will be retried.
+ */
+ start_timer ( &dhcp->timer );
+
+ /* Allocate buffer for packet */
+ iobuf = xfer_alloc_iob ( &dhcp->xfer, DHCP_MIN_LEN );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ /* Create basic DHCP packet in temporary buffer */
+ if ( ( rc = dhcp_create_request ( &dhcppkt, dhcp->netdev, msgtype,
+ dhcp->xid, dhcp->local.sin_addr,
+ iobuf->data,
+ iob_tailroom ( iobuf ) ) ) != 0 ) {
+ DBGC ( dhcp, "DHCP %p could not construct DHCP request: %s\n",
+ dhcp, strerror ( rc ) );
+ goto done;
+ }
+
+ /* (Ab)use the "secs" field to convey metadata about the DHCP
+ * session state into packet traces. Useful for extracting
+ * debug information from non-debug builds.
+ */
+ dhcppkt.dhcphdr->secs = htons ( ( ++(dhcp->count) << 2 ) |
+ ( dhcp->offer.s_addr ? 0x02 : 0 ) |
+ ( dhcp->proxy_offer ? 0x01 : 0 ) );
+
+ /* Fill in packet based on current state */
+ if ( ( rc = dhcp->state->tx ( dhcp, &dhcppkt, &peer ) ) != 0 ) {
+ DBGC ( dhcp, "DHCP %p could not fill DHCP request: %s\n",
+ dhcp, strerror ( rc ) );
+ goto done;
+ }
+
+ /* Transmit the packet */
+ iob_put ( iobuf, dhcppkt_len ( &dhcppkt ) );
+ if ( ( rc = xfer_deliver ( &dhcp->xfer, iob_disown ( iobuf ),
+ &meta ) ) != 0 ) {
+ DBGC ( dhcp, "DHCP %p could not transmit UDP packet: %s\n",
+ dhcp, strerror ( rc ) );
+ goto done;
+ }
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Receive new data
+ *
+ * @v dhcp DHCP session
+ * @v iobuf I/O buffer
+ * @v meta Transfer metadata
+ * @ret rc Return status code
+ */
+static int dhcp_deliver ( struct dhcp_session *dhcp,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct sockaddr_in *peer;
+ size_t data_len;
+ struct dhcp_packet *dhcppkt;
+ struct dhcphdr *dhcphdr;
+ uint8_t msgtype = 0;
+ struct in_addr server_id = { 0 };
+ int rc = 0;
+
+ /* Sanity checks */
+ if ( ! meta->src ) {
+ DBGC ( dhcp, "DHCP %p received packet without source port\n",
+ dhcp );
+ rc = -EINVAL;
+ goto err_no_src;
+ }
+ peer = ( struct sockaddr_in * ) meta->src;
+
+ /* Create a DHCP packet containing the I/O buffer contents.
+ * Whilst we could just use the original buffer in situ, that
+ * would waste the unused space in the packet buffer, and also
+ * waste a relatively scarce fully-aligned I/O buffer.
+ */
+ data_len = iob_len ( iobuf );
+ dhcppkt = zalloc ( sizeof ( *dhcppkt ) + data_len );
+ if ( ! dhcppkt ) {
+ rc = -ENOMEM;
+ goto err_alloc_dhcppkt;
+ }
+ dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( *dhcppkt ) );
+ memcpy ( dhcphdr, iobuf->data, data_len );
+ dhcppkt_init ( dhcppkt, dhcphdr, data_len );
+
+ /* Identify message type */
+ dhcppkt_fetch ( dhcppkt, DHCP_MESSAGE_TYPE, &msgtype,
+ sizeof ( msgtype ) );
+
+ /* Identify server ID */
+ dhcppkt_fetch ( dhcppkt, DHCP_SERVER_IDENTIFIER,
+ &server_id, sizeof ( server_id ) );
+
+ /* Check for matching transaction ID */
+ if ( dhcphdr->xid != dhcp->xid ) {
+ DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction "
+ "ID\n", dhcp, dhcp_msgtype_name ( msgtype ),
+ inet_ntoa ( peer->sin_addr ),
+ ntohs ( peer->sin_port ) );
+ rc = -EINVAL;
+ goto err_xid;
+ };
+
+ /* Handle packet based on current state */
+ dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id );
+
+ err_xid:
+ dhcppkt_put ( dhcppkt );
+ err_alloc_dhcppkt:
+ err_no_src:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** DHCP data transfer interface operations */
+static struct interface_operation dhcp_xfer_operations[] = {
+ INTF_OP ( xfer_deliver, struct dhcp_session *, dhcp_deliver ),
+};
+
+/** DHCP data transfer interface descriptor */
+static struct interface_descriptor dhcp_xfer_desc =
+ INTF_DESC ( struct dhcp_session, xfer, dhcp_xfer_operations );
+
+/**
+ * Handle DHCP retry timer expiry
+ *
+ * @v timer DHCP retry timer
+ * @v fail Failure indicator
+ */
+static void dhcp_timer_expired ( struct retry_timer *timer, int fail ) {
+ struct dhcp_session *dhcp =
+ container_of ( timer, struct dhcp_session, timer );
+
+ /* If we have failed, terminate DHCP */
+ if ( fail ) {
+ dhcp_finished ( dhcp, -ETIMEDOUT );
+ return;
+ }
+
+ /* Handle timer expiry based on current state */
+ dhcp->state->expired ( dhcp );
+}
+
+/****************************************************************************
+ *
+ * Job control interface
+ *
+ */
+
+/** DHCP job control interface operations */
+static struct interface_operation dhcp_job_op[] = {
+ INTF_OP ( intf_close, struct dhcp_session *, dhcp_finished ),
+};
+
+/** DHCP job control interface descriptor */
+static struct interface_descriptor dhcp_job_desc =
+ INTF_DESC ( struct dhcp_session, job, dhcp_job_op );
+
+/****************************************************************************
+ *
+ * Instantiators
+ *
+ */
+
+/**
+ * DHCP peer address for socket opening
+ *
+ * This is a dummy address; the only useful portion is the socket
+ * family (so that we get a UDP connection). The DHCP client will set
+ * the IP address and source port explicitly on each transmission.
+ */
+static struct sockaddr dhcp_peer = {
+ .sa_family = AF_INET,
+};
+
+/**
+ * Get cached DHCPACK where none exists
+ */
+__weak void get_cached_dhcpack ( void ) { __keepme }
+
+/**
+ * Start DHCP state machine on a network device
+ *
+ * @v job Job control interface
+ * @v netdev Network device
+ * @ret rc Return status code, or positive if cached
+ *
+ * Starts DHCP on the specified network device. If successful, the
+ * DHCPACK (and ProxyDHCPACK, if applicable) will be registered as
+ * option sources.
+ *
+ * On a return of 0, a background job has been started to perform the
+ * DHCP request. Any nonzero return means the job has not been
+ * started; a positive return value indicates the success condition of
+ * having fetched the appropriate data from cached information.
+ */
+int start_dhcp ( struct interface *job, struct net_device *netdev ) {
+ struct dhcp_session *dhcp;
+ int rc;
+
+ /* Check for cached DHCP information */
+ get_cached_dhcpack();
+ if ( fetch_uintz_setting ( NULL, &use_cached_setting ) ) {
+ DBG ( "DHCP using cached network settings\n" );
+ return 1;
+ }
+
+ /* Allocate and initialise structure */
+ dhcp = zalloc ( sizeof ( *dhcp ) );
+ if ( ! dhcp )
+ return -ENOMEM;
+ ref_init ( &dhcp->refcnt, dhcp_free );
+ intf_init ( &dhcp->job, &dhcp_job_desc, &dhcp->refcnt );
+ intf_init ( &dhcp->xfer, &dhcp_xfer_desc, &dhcp->refcnt );
+ timer_init ( &dhcp->timer, dhcp_timer_expired, &dhcp->refcnt );
+ dhcp->netdev = netdev_get ( netdev );
+ dhcp->local.sin_family = AF_INET;
+ dhcp->local.sin_port = htons ( BOOTPC_PORT );
+ dhcp->xid = random();
+
+ /* Store DHCP transaction ID for fakedhcp code */
+ dhcp_last_xid = dhcp->xid;
+
+ /* Instantiate child objects and attach to our interfaces */
+ if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer,
+ ( struct sockaddr * ) &dhcp->local ) ) != 0 )
+ goto err;
+
+ /* Enter DHCPDISCOVER state */
+ dhcp_set_state ( dhcp, &dhcp_state_discover );
+
+ /* Attach parent interface, mortalise self, and return */
+ intf_plug_plug ( &dhcp->job, job );
+ ref_put ( &dhcp->refcnt );
+ return 0;
+
+ err:
+ dhcp_finished ( dhcp, rc );
+ ref_put ( &dhcp->refcnt );
+ return rc;
+}
+
+/**
+ * Retrieve list of PXE boot servers for a given server type
+ *
+ * @v dhcp DHCP session
+ * @v raw DHCP PXE boot server list
+ * @v raw_len Length of DHCP PXE boot server list
+ * @v ip IP address list to fill in
+ *
+ * The caller must ensure that the IP address list has sufficient
+ * space.
+ */
+static void pxebs_list ( struct dhcp_session *dhcp, void *raw,
+ size_t raw_len, struct in_addr *ip ) {
+ struct dhcp_pxe_boot_server *server = raw;
+ size_t server_len;
+ unsigned int i;
+
+ while ( raw_len ) {
+ if ( raw_len < sizeof ( *server ) ) {
+ DBGC ( dhcp, "DHCP %p malformed PXE server list\n",
+ dhcp );
+ break;
+ }
+ server_len = offsetof ( typeof ( *server ),
+ ip[ server->num_ip ] );
+ if ( raw_len < server_len ) {
+ DBGC ( dhcp, "DHCP %p malformed PXE server list\n",
+ dhcp );
+ break;
+ }
+ if ( server->type == dhcp->pxe_type ) {
+ for ( i = 0 ; i < server->num_ip ; i++ )
+ *(ip++) = server->ip[i];
+ }
+ server = ( ( ( void * ) server ) + server_len );
+ raw_len -= server_len;
+ }
+}
+
+/**
+ * Start PXE Boot Server Discovery on a network device
+ *
+ * @v job Job control interface
+ * @v netdev Network device
+ * @v pxe_type PXE server type
+ * @ret rc Return status code
+ *
+ * Starts PXE Boot Server Discovery on the specified network device.
+ * If successful, the Boot Server ACK will be registered as an option
+ * source.
+ */
+int start_pxebs ( struct interface *job, struct net_device *netdev,
+ unsigned int pxe_type ) {
+ struct setting pxe_discovery_control_setting =
+ { .tag = DHCP_PXE_DISCOVERY_CONTROL };
+ struct setting pxe_boot_servers_setting =
+ { .tag = DHCP_PXE_BOOT_SERVERS };
+ struct setting pxe_boot_server_mcast_setting =
+ { .tag = DHCP_PXE_BOOT_SERVER_MCAST };
+ ssize_t pxebs_list_len;
+ struct dhcp_session *dhcp;
+ struct in_addr *ip;
+ unsigned int pxe_discovery_control;
+ int rc;
+
+ /* Get upper bound for PXE boot server IP address list */
+ pxebs_list_len = fetch_setting_len ( NULL, &pxe_boot_servers_setting );
+ if ( pxebs_list_len < 0 )
+ pxebs_list_len = 0;
+
+ /* Allocate and initialise structure */
+ dhcp = zalloc ( sizeof ( *dhcp ) + sizeof ( *ip ) /* mcast */ +
+ sizeof ( *ip ) /* bcast */ + pxebs_list_len +
+ sizeof ( *ip ) /* terminator */ );
+ if ( ! dhcp )
+ return -ENOMEM;
+ ref_init ( &dhcp->refcnt, dhcp_free );
+ intf_init ( &dhcp->job, &dhcp_job_desc, &dhcp->refcnt );
+ intf_init ( &dhcp->xfer, &dhcp_xfer_desc, &dhcp->refcnt );
+ timer_init ( &dhcp->timer, dhcp_timer_expired, &dhcp->refcnt );
+ dhcp->netdev = netdev_get ( netdev );
+ dhcp->local.sin_family = AF_INET;
+ fetch_ipv4_setting ( netdev_settings ( netdev ), &ip_setting,
+ &dhcp->local.sin_addr );
+ dhcp->local.sin_port = htons ( BOOTPC_PORT );
+ dhcp->pxe_type = cpu_to_le16 ( pxe_type );
+
+ /* Construct PXE boot server IP address lists */
+ pxe_discovery_control =
+ fetch_uintz_setting ( NULL, &pxe_discovery_control_setting );
+ ip = ( ( ( void * ) dhcp ) + sizeof ( *dhcp ) );
+ dhcp->pxe_attempt = ip;
+ if ( ! ( pxe_discovery_control & PXEBS_NO_MULTICAST ) ) {
+ fetch_ipv4_setting ( NULL, &pxe_boot_server_mcast_setting, ip);
+ if ( ip->s_addr )
+ ip++;
+ }
+ if ( ! ( pxe_discovery_control & PXEBS_NO_BROADCAST ) )
+ (ip++)->s_addr = INADDR_BROADCAST;
+ if ( pxe_discovery_control & PXEBS_NO_UNKNOWN_SERVERS )
+ dhcp->pxe_accept = ip;
+ if ( pxebs_list_len ) {
+ uint8_t buf[pxebs_list_len];
+
+ fetch_setting ( NULL, &pxe_boot_servers_setting,
+ buf, sizeof ( buf ) );
+ pxebs_list ( dhcp, buf, sizeof ( buf ), ip );
+ }
+ if ( ! dhcp->pxe_attempt->s_addr ) {
+ DBGC ( dhcp, "DHCP %p has no PXE boot servers for type %04x\n",
+ dhcp, pxe_type );
+ rc = -EINVAL;
+ goto err;
+ }
+
+ /* Dump out PXE server lists */
+ DBGC ( dhcp, "DHCP %p attempting", dhcp );
+ for ( ip = dhcp->pxe_attempt ; ip->s_addr ; ip++ )
+ DBGC ( dhcp, " %s", inet_ntoa ( *ip ) );
+ DBGC ( dhcp, "\n" );
+ if ( dhcp->pxe_accept ) {
+ DBGC ( dhcp, "DHCP %p accepting", dhcp );
+ for ( ip = dhcp->pxe_accept ; ip->s_addr ; ip++ )
+ DBGC ( dhcp, " %s", inet_ntoa ( *ip ) );
+ DBGC ( dhcp, "\n" );
+ }
+
+ /* Instantiate child objects and attach to our interfaces */
+ if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer,
+ ( struct sockaddr * ) &dhcp->local ) ) != 0 )
+ goto err;
+
+ /* Enter PXEBS state */
+ dhcp_set_state ( dhcp, &dhcp_state_pxebs );
+
+ /* Attach parent interface, mortalise self, and return */
+ intf_plug_plug ( &dhcp->job, job );
+ ref_put ( &dhcp->refcnt );
+ return 0;
+
+ err:
+ dhcp_finished ( dhcp, rc );
+ ref_put ( &dhcp->refcnt );
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/udp/dns.c b/src/VBox/Devices/PC/ipxe/src/net/udp/dns.c
new file mode 100644
index 00000000..124a0e49
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/udp/dns.c
@@ -0,0 +1,646 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * Portions copyright (C) 2004 Anselm M. Hoffmeister
+ * <stockholm@users.sourceforge.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/resolv.h>
+#include <ipxe/retry.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/settings.h>
+#include <ipxe/features.h>
+#include <ipxe/dns.h>
+
+/** @file
+ *
+ * DNS protocol
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "DNS", DHCP_EB_FEATURE_DNS, 1 );
+
+/* Disambiguate the various error causes */
+#define ENXIO_NO_RECORD __einfo_error ( EINFO_ENXIO_NO_RECORD )
+#define EINFO_ENXIO_NO_RECORD \
+ __einfo_uniqify ( EINFO_ENXIO, 0x01, "DNS name does not exist" )
+#define ENXIO_NO_NAMESERVER __einfo_error ( EINFO_ENXIO_NO_NAMESERVER )
+#define EINFO_ENXIO_NO_NAMESERVER \
+ __einfo_uniqify ( EINFO_ENXIO, 0x02, "No DNS servers available" )
+
+/** The DNS server */
+static struct sockaddr_tcpip nameserver = {
+ .st_port = htons ( DNS_PORT ),
+};
+
+/** The local domain */
+static char *localdomain;
+
+/** A DNS request */
+struct dns_request {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Name resolution interface */
+ struct interface resolv;
+ /** Data transfer interface */
+ struct interface socket;
+ /** Retry timer */
+ struct retry_timer timer;
+
+ /** Socket address to fill in with resolved address */
+ struct sockaddr sa;
+ /** Current query packet */
+ struct dns_query query;
+ /** Location of query info structure within current packet
+ *
+ * The query info structure is located immediately after the
+ * compressed name.
+ */
+ struct dns_query_info *qinfo;
+ /** Recursion counter */
+ unsigned int recursion;
+};
+
+/**
+ * Mark DNS request as complete
+ *
+ * @v dns DNS request
+ * @v rc Return status code
+ */
+static void dns_done ( struct dns_request *dns, int rc ) {
+
+ /* Stop the retry timer */
+ stop_timer ( &dns->timer );
+
+ /* Shut down interfaces */
+ intf_shutdown ( &dns->socket, rc );
+ intf_shutdown ( &dns->resolv, rc );
+}
+
+/**
+ * Compare DNS reply name against the query name from the original request
+ *
+ * @v dns DNS request
+ * @v reply DNS reply
+ * @v rname Reply name
+ * @ret zero Names match
+ * @ret non-zero Names do not match
+ */
+static int dns_name_cmp ( struct dns_request *dns,
+ const struct dns_header *reply,
+ const char *rname ) {
+ const char *qname = dns->query.payload;
+ int i;
+
+ while ( 1 ) {
+ /* Obtain next section of rname */
+ while ( ( *rname ) & 0xc0 ) {
+ rname = ( ( ( char * ) reply ) +
+ ( ntohs( *((uint16_t *)rname) ) & ~0xc000 ));
+ }
+ /* Check that lengths match */
+ if ( *rname != *qname )
+ return -1;
+ /* If length is zero, we have reached the end */
+ if ( ! *qname )
+ return 0;
+ /* Check that data matches */
+ for ( i = *qname + 1; i > 0 ; i-- ) {
+ if ( *(rname++) != *(qname++) )
+ return -1;
+ }
+ }
+}
+
+/**
+ * Skip over a (possibly compressed) DNS name
+ *
+ * @v name DNS name
+ * @ret name Next DNS name
+ */
+static const char * dns_skip_name ( const char *name ) {
+ while ( 1 ) {
+ if ( ! *name ) {
+ /* End of name */
+ return ( name + 1);
+ }
+ if ( *name & 0xc0 ) {
+ /* Start of a compressed name */
+ return ( name + 2 );
+ }
+ /* Uncompressed name portion */
+ name += *name + 1;
+ }
+}
+
+/**
+ * Find an RR in a reply packet corresponding to our query
+ *
+ * @v dns DNS request
+ * @v reply DNS reply
+ * @ret rr DNS RR, or NULL if not found
+ */
+static union dns_rr_info * dns_find_rr ( struct dns_request *dns,
+ const struct dns_header *reply ) {
+ int i, cmp;
+ const char *p = ( ( char * ) reply ) + sizeof ( struct dns_header );
+ union dns_rr_info *rr_info;
+
+ /* Skip over the questions section */
+ for ( i = ntohs ( reply->qdcount ) ; i > 0 ; i-- ) {
+ p = dns_skip_name ( p ) + sizeof ( struct dns_query_info );
+ }
+
+ /* Process the answers section */
+ for ( i = ntohs ( reply->ancount ) ; i > 0 ; i-- ) {
+ cmp = dns_name_cmp ( dns, reply, p );
+ p = dns_skip_name ( p );
+ rr_info = ( ( union dns_rr_info * ) p );
+ if ( cmp == 0 )
+ return rr_info;
+ p += ( sizeof ( rr_info->common ) +
+ ntohs ( rr_info->common.rdlength ) );
+ }
+
+ return NULL;
+}
+
+/**
+ * Append DHCP domain name if available and name is not fully qualified
+ *
+ * @v string Name as a NUL-terminated string
+ * @ret fqdn Fully-qualified domain name, malloc'd copy
+ *
+ * The caller must free fqdn which is allocated even if the name is already
+ * fully qualified.
+ */
+static char * dns_qualify_name ( const char *string ) {
+ char *fqdn;
+
+ /* Leave unchanged if already fully-qualified or no local domain */
+ if ( ( ! localdomain ) || ( strchr ( string, '.' ) != 0 ) )
+ return strdup ( string );
+
+ /* Append local domain to name */
+ asprintf ( &fqdn, "%s.%s", string, localdomain );
+ return fqdn;
+}
+
+/**
+ * Convert a standard NUL-terminated string to a DNS name
+ *
+ * @v string Name as a NUL-terminated string
+ * @v buf Buffer in which to place DNS name
+ * @ret next Byte following constructed DNS name
+ *
+ * DNS names consist of "<length>element" pairs.
+ */
+static char * dns_make_name ( const char *string, char *buf ) {
+ char *length_byte;
+ char c;
+
+ length_byte = buf++;
+ *length_byte = 0;
+ do {
+ c = *(string++);
+ if ( ( c == '.' ) || ( c == '\0' ) ) {
+ if ( *length_byte ) {
+ length_byte = buf++;
+ *length_byte = 0;
+ }
+ } else {
+ *(buf++) = c;
+ (*length_byte)++;
+ }
+ } while ( c );
+
+ return buf;
+}
+
+/**
+ * Convert an uncompressed DNS name to a NUL-terminated string
+ *
+ * @v name DNS name
+ * @ret string NUL-terminated string
+ *
+ * Produce a printable version of a DNS name. Used only for debugging.
+ */
+static inline char * dns_unmake_name ( char *name ) {
+ char *p;
+ unsigned int len;
+
+ p = name;
+ while ( ( len = *p ) ) {
+ *(p++) = '.';
+ p += len;
+ }
+
+ return name + 1;
+}
+
+/**
+ * Decompress a DNS name
+ *
+ * @v reply DNS replay
+ * @v name DNS name
+ * @v buf Buffer into which to decompress DNS name
+ * @ret next Byte following decompressed DNS name
+ */
+static char * dns_decompress_name ( const struct dns_header *reply,
+ const char *name, char *buf ) {
+ int i, len;
+
+ do {
+ /* Obtain next section of name */
+ while ( ( *name ) & 0xc0 ) {
+ name = ( ( char * ) reply +
+ ( ntohs ( *((uint16_t *)name) ) & ~0xc000 ) );
+ }
+ /* Copy data */
+ len = *name;
+ for ( i = len + 1 ; i > 0 ; i-- ) {
+ *(buf++) = *(name++);
+ }
+ } while ( len );
+ return buf;
+}
+
+/**
+ * Send next packet in DNS request
+ *
+ * @v dns DNS request
+ */
+static int dns_send_packet ( struct dns_request *dns ) {
+ static unsigned int qid = 0;
+ size_t qlen;
+
+ /* Increment query ID */
+ dns->query.dns.id = htons ( ++qid );
+
+ DBGC ( dns, "DNS %p sending query ID %d\n", dns, qid );
+
+ /* Start retransmission timer */
+ start_timer ( &dns->timer );
+
+ /* Send the data */
+ qlen = ( ( ( void * ) dns->qinfo ) - ( ( void * ) &dns->query )
+ + sizeof ( dns->qinfo ) );
+ return xfer_deliver_raw ( &dns->socket, &dns->query, qlen );
+}
+
+/**
+ * Handle DNS retransmission timer expiry
+ *
+ * @v timer Retry timer
+ * @v fail Failure indicator
+ */
+static void dns_timer_expired ( struct retry_timer *timer, int fail ) {
+ struct dns_request *dns =
+ container_of ( timer, struct dns_request, timer );
+
+ if ( fail ) {
+ dns_done ( dns, -ETIMEDOUT );
+ } else {
+ dns_send_packet ( dns );
+ }
+}
+
+/**
+ * Receive new data
+ *
+ * @v dns DNS request
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int dns_xfer_deliver ( struct dns_request *dns,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ const struct dns_header *reply = iobuf->data;
+ union dns_rr_info *rr_info;
+ struct sockaddr_in *sin;
+ unsigned int qtype = dns->qinfo->qtype;
+ int rc;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *reply ) ) {
+ DBGC ( dns, "DNS %p received underlength packet length %zd\n",
+ dns, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Check reply ID matches query ID */
+ if ( reply->id != dns->query.dns.id ) {
+ DBGC ( dns, "DNS %p received unexpected reply ID %d "
+ "(wanted %d)\n", dns, ntohs ( reply->id ),
+ ntohs ( dns->query.dns.id ) );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ DBGC ( dns, "DNS %p received reply ID %d\n", dns, ntohs ( reply->id ));
+
+ /* Stop the retry timer. After this point, each code path
+ * must either restart the timer by calling dns_send_packet(),
+ * or mark the DNS operation as complete by calling
+ * dns_done()
+ */
+ stop_timer ( &dns->timer );
+
+ /* Search through response for useful answers. Do this
+ * multiple times, to take advantage of useful nameservers
+ * which send us e.g. the CNAME *and* the A record for the
+ * pointed-to name.
+ */
+ while ( ( rr_info = dns_find_rr ( dns, reply ) ) ) {
+ switch ( rr_info->common.type ) {
+
+ case htons ( DNS_TYPE_A ):
+
+ /* Found the target A record */
+ DBGC ( dns, "DNS %p found address %s\n",
+ dns, inet_ntoa ( rr_info->a.in_addr ) );
+ sin = ( struct sockaddr_in * ) &dns->sa;
+ sin->sin_family = AF_INET;
+ sin->sin_addr = rr_info->a.in_addr;
+
+ /* Return resolved address */
+ resolv_done ( &dns->resolv, &dns->sa );
+
+ /* Mark operation as complete */
+ dns_done ( dns, 0 );
+ rc = 0;
+ goto done;
+
+ case htons ( DNS_TYPE_CNAME ):
+
+ /* Found a CNAME record; update query and recurse */
+ DBGC ( dns, "DNS %p found CNAME\n", dns );
+ dns->qinfo = ( void * ) dns_decompress_name ( reply,
+ rr_info->cname.cname,
+ dns->query.payload );
+ dns->qinfo->qtype = htons ( DNS_TYPE_A );
+ dns->qinfo->qclass = htons ( DNS_CLASS_IN );
+
+ /* Terminate the operation if we recurse too far */
+ if ( ++dns->recursion > DNS_MAX_CNAME_RECURSION ) {
+ DBGC ( dns, "DNS %p recursion exceeded\n",
+ dns );
+ dns_done ( dns, -ELOOP );
+ rc = 0;
+ goto done;
+ }
+ break;
+
+ default:
+ DBGC ( dns, "DNS %p got unknown record type %d\n",
+ dns, ntohs ( rr_info->common.type ) );
+ break;
+ }
+ }
+
+ /* Determine what to do next based on the type of query we
+ * issued and the reponse we received
+ */
+ switch ( qtype ) {
+
+ case htons ( DNS_TYPE_A ):
+ /* We asked for an A record and got nothing;
+ * try the CNAME.
+ */
+ DBGC ( dns, "DNS %p found no A record; trying CNAME\n", dns );
+ dns->qinfo->qtype = htons ( DNS_TYPE_CNAME );
+ dns_send_packet ( dns );
+ rc = 0;
+ goto done;
+
+ case htons ( DNS_TYPE_CNAME ):
+ /* We asked for a CNAME record. If we got a response
+ * (i.e. if the next A query is already set up), then
+ * issue it, otherwise abort.
+ */
+ if ( dns->qinfo->qtype == htons ( DNS_TYPE_A ) ) {
+ dns_send_packet ( dns );
+ rc = 0;
+ goto done;
+ } else {
+ DBGC ( dns, "DNS %p found no CNAME record\n", dns );
+ dns_done ( dns, -ENXIO_NO_RECORD );
+ rc = 0;
+ goto done;
+ }
+
+ default:
+ assert ( 0 );
+ dns_done ( dns, -EINVAL );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ done:
+ /* Free I/O buffer */
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Receive new data
+ *
+ * @v dns DNS request
+ * @v rc Reason for close
+ */
+static void dns_xfer_close ( struct dns_request *dns, int rc ) {
+
+ if ( ! rc )
+ rc = -ECONNABORTED;
+
+ dns_done ( dns, rc );
+}
+
+/** DNS socket interface operations */
+static struct interface_operation dns_socket_operations[] = {
+ INTF_OP ( xfer_deliver, struct dns_request *, dns_xfer_deliver ),
+ INTF_OP ( intf_close, struct dns_request *, dns_xfer_close ),
+};
+
+/** DNS socket interface descriptor */
+static struct interface_descriptor dns_socket_desc =
+ INTF_DESC ( struct dns_request, socket, dns_socket_operations );
+
+/** DNS resolver interface operations */
+static struct interface_operation dns_resolv_op[] = {
+ INTF_OP ( intf_close, struct dns_request *, dns_done ),
+};
+
+/** DNS resolver interface descriptor */
+static struct interface_descriptor dns_resolv_desc =
+ INTF_DESC ( struct dns_request, resolv, dns_resolv_op );
+
+/**
+ * Resolve name using DNS
+ *
+ * @v resolv Name resolution interface
+ * @v name Name to resolve
+ * @v sa Socket address to fill in
+ * @ret rc Return status code
+ */
+static int dns_resolv ( struct interface *resolv,
+ const char *name, struct sockaddr *sa ) {
+ struct dns_request *dns;
+ char *fqdn;
+ int rc;
+
+ /* Fail immediately if no DNS servers */
+ if ( ! nameserver.st_family ) {
+ DBG ( "DNS not attempting to resolve \"%s\": "
+ "no DNS servers\n", name );
+ rc = -ENXIO_NO_NAMESERVER;
+ goto err_no_nameserver;
+ }
+
+ /* Ensure fully-qualified domain name if DHCP option was given */
+ fqdn = dns_qualify_name ( name );
+ if ( ! fqdn ) {
+ rc = -ENOMEM;
+ goto err_qualify_name;
+ }
+
+ /* Allocate DNS structure */
+ dns = zalloc ( sizeof ( *dns ) );
+ if ( ! dns ) {
+ rc = -ENOMEM;
+ goto err_alloc_dns;
+ }
+ ref_init ( &dns->refcnt, NULL );
+ intf_init ( &dns->resolv, &dns_resolv_desc, &dns->refcnt );
+ intf_init ( &dns->socket, &dns_socket_desc, &dns->refcnt );
+ timer_init ( &dns->timer, dns_timer_expired, &dns->refcnt );
+ memcpy ( &dns->sa, sa, sizeof ( dns->sa ) );
+
+ /* Create query */
+ dns->query.dns.flags = htons ( DNS_FLAG_QUERY | DNS_FLAG_OPCODE_QUERY |
+ DNS_FLAG_RD );
+ dns->query.dns.qdcount = htons ( 1 );
+ dns->qinfo = ( void * ) dns_make_name ( fqdn, dns->query.payload );
+ dns->qinfo->qtype = htons ( DNS_TYPE_A );
+ dns->qinfo->qclass = htons ( DNS_CLASS_IN );
+
+ /* Open UDP connection */
+ if ( ( rc = xfer_open_socket ( &dns->socket, SOCK_DGRAM,
+ ( struct sockaddr * ) &nameserver,
+ NULL ) ) != 0 ) {
+ DBGC ( dns, "DNS %p could not open socket: %s\n",
+ dns, strerror ( rc ) );
+ goto err_open_socket;
+ }
+
+ /* Send first DNS packet */
+ dns_send_packet ( dns );
+
+ /* Attach parent interface, mortalise self, and return */
+ intf_plug_plug ( &dns->resolv, resolv );
+ ref_put ( &dns->refcnt );
+ free ( fqdn );
+ return 0;
+
+ err_open_socket:
+ err_alloc_dns:
+ ref_put ( &dns->refcnt );
+ err_qualify_name:
+ free ( fqdn );
+ err_no_nameserver:
+ return rc;
+}
+
+/** DNS name resolver */
+struct resolver dns_resolver __resolver ( RESOLV_NORMAL ) = {
+ .name = "DNS",
+ .resolv = dns_resolv,
+};
+
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** DNS server setting */
+struct setting dns_setting __setting ( SETTING_IPv4_EXTRA ) = {
+ .name = "dns",
+ .description = "DNS server",
+ .tag = DHCP_DNS_SERVERS,
+ .type = &setting_type_ipv4,
+};
+
+/** Domain name setting */
+struct setting domain_setting __setting ( SETTING_IPv4_EXTRA ) = {
+ .name = "domain",
+ .description = "DNS domain",
+ .tag = DHCP_DOMAIN_NAME,
+ .type = &setting_type_string,
+};
+
+/**
+ * Apply DNS settings
+ *
+ * @ret rc Return status code
+ */
+static int apply_dns_settings ( void ) {
+ struct sockaddr_in *sin_nameserver =
+ ( struct sockaddr_in * ) &nameserver;
+ int len;
+
+ /* Fetch DNS server address */
+ nameserver.st_family = 0;
+ if ( ( len = fetch_ipv4_setting ( NULL, &dns_setting,
+ &sin_nameserver->sin_addr ) ) >= 0 ){
+ nameserver.st_family = AF_INET;
+ DBG ( "DNS using nameserver %s\n",
+ inet_ntoa ( sin_nameserver->sin_addr ) );
+ }
+
+ /* Get local domain DHCP option */
+ free ( localdomain );
+ if ( ( len = fetch_string_setting_copy ( NULL, &domain_setting,
+ &localdomain ) ) < 0 ) {
+ DBG ( "DNS could not fetch local domain: %s\n",
+ strerror ( len ) );
+ }
+ if ( localdomain )
+ DBG ( "DNS local domain %s\n", localdomain );
+
+ return 0;
+}
+
+/** DNS settings applicator */
+struct settings_applicator dns_applicator __settings_applicator = {
+ .apply = apply_dns_settings,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/udp/slam.c b/src/VBox/Devices/PC/ipxe/src/net/udp/slam.c
new file mode 100644
index 00000000..0de138cd
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/udp/slam.c
@@ -0,0 +1,756 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/features.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/bitmap.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/uri.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/timer.h>
+#include <ipxe/retry.h>
+
+/** @file
+ *
+ * Scalable Local Area Multicast protocol
+ *
+ * The SLAM protocol is supported only by Etherboot; it was designed
+ * and implemented by Eric Biederman. A server implementation is
+ * available in contrib/mini-slamd. There does not appear to be any
+ * documentation beyond a few sparse comments in Etherboot's
+ * proto_slam.c.
+ *
+ * SLAM packets use three types of data field:
+ *
+ * Nul : A single NUL (0) byte, used as a list terminator
+ *
+ * Raw : A block of raw data
+ *
+ * Int : A variable-length integer, in big-endian order. The length
+ * of the integer is encoded in the most significant three bits.
+ *
+ * Packets received by the client have the following layout:
+ *
+ * Int : Transaction identifier. This is an opaque value.
+ *
+ * Int : Total number of bytes in the transfer.
+ *
+ * Int : Block size, in bytes.
+ *
+ * Int : Packet sequence number within the transfer (if this packet
+ * contains data).
+ *
+ * Raw : Packet data (if this packet contains data).
+ *
+ * Packets transmitted by the client consist of a run-length-encoded
+ * representation of the received-blocks bitmap, looking something
+ * like:
+ *
+ * Int : Number of consecutive successfully-received packets
+ * Int : Number of consecutive missing packets
+ * Int : Number of consecutive successfully-received packets
+ * Int : Number of consecutive missing packets
+ * ....
+ * Nul
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "SLAM", DHCP_EB_FEATURE_SLAM, 1 );
+
+/** Default SLAM server port */
+#define SLAM_DEFAULT_PORT 10000
+
+/** Default SLAM multicast IP address */
+#define SLAM_DEFAULT_MULTICAST_IP \
+ ( ( 239 << 24 ) | ( 255 << 16 ) | ( 1 << 8 ) | ( 1 << 0 ) )
+
+/** Default SLAM multicast port */
+#define SLAM_DEFAULT_MULTICAST_PORT 10000
+
+/** Maximum SLAM header length */
+#define SLAM_MAX_HEADER_LEN ( 7 /* transaction id */ + 7 /* total_bytes */ + \
+ 7 /* block_size */ )
+
+/** Maximum number of blocks to request per NACK
+ *
+ * This is a policy decision equivalent to selecting a TCP window
+ * size.
+ */
+#define SLAM_MAX_BLOCKS_PER_NACK 4
+
+/** Maximum SLAM NACK length
+ *
+ * We only ever send a NACK for a single range of up to @c
+ * SLAM_MAX_BLOCKS_PER_NACK blocks.
+ */
+#define SLAM_MAX_NACK_LEN ( 7 /* block */ + 7 /* #blocks */ + 1 /* NUL */ )
+
+/** SLAM slave timeout */
+#define SLAM_SLAVE_TIMEOUT ( 1 * TICKS_PER_SEC )
+
+/** A SLAM request */
+struct slam_request {
+ /** Reference counter */
+ struct refcnt refcnt;
+
+ /** Data transfer interface */
+ struct interface xfer;
+ /** Unicast socket */
+ struct interface socket;
+ /** Multicast socket */
+ struct interface mc_socket;
+
+ /** Master client retry timer */
+ struct retry_timer master_timer;
+ /** Slave client retry timer */
+ struct retry_timer slave_timer;
+
+ /** Cached header */
+ uint8_t header[SLAM_MAX_HEADER_LEN];
+ /** Size of cached header */
+ size_t header_len;
+ /** Total number of bytes in transfer */
+ unsigned long total_bytes;
+ /** Transfer block size */
+ unsigned long block_size;
+ /** Number of blocks in transfer */
+ unsigned long num_blocks;
+ /** Block bitmap */
+ struct bitmap bitmap;
+ /** NACK sent flag */
+ int nack_sent;
+};
+
+/**
+ * Free a SLAM request
+ *
+ * @v refcnt Reference counter
+ */
+static void slam_free ( struct refcnt *refcnt ) {
+ struct slam_request *slam =
+ container_of ( refcnt, struct slam_request, refcnt );
+
+ bitmap_free ( &slam->bitmap );
+ free ( slam );
+}
+
+/**
+ * Mark SLAM request as complete
+ *
+ * @v slam SLAM request
+ * @v rc Return status code
+ */
+static void slam_finished ( struct slam_request *slam, int rc ) {
+ static const uint8_t slam_disconnect[] = { 0 };
+
+ DBGC ( slam, "SLAM %p finished with status code %d (%s)\n",
+ slam, rc, strerror ( rc ) );
+
+ /* Send a disconnect message if we ever sent anything to the
+ * server.
+ */
+ if ( slam->nack_sent ) {
+ xfer_deliver_raw ( &slam->socket, slam_disconnect,
+ sizeof ( slam_disconnect ) );
+ }
+
+ /* Stop the retry timers */
+ stop_timer ( &slam->master_timer );
+ stop_timer ( &slam->slave_timer );
+
+ /* Close all data transfer interfaces */
+ intf_shutdown ( &slam->socket, rc );
+ intf_shutdown ( &slam->mc_socket, rc );
+ intf_shutdown ( &slam->xfer, rc );
+}
+
+/****************************************************************************
+ *
+ * TX datapath
+ *
+ */
+
+/**
+ * Add a variable-length value to a SLAM packet
+ *
+ * @v slam SLAM request
+ * @v iobuf I/O buffer
+ * @v value Value to add
+ * @ret rc Return status code
+ *
+ * Adds a variable-length value to the end of an I/O buffer. Will
+ * always leave at least one byte of tailroom in the I/O buffer (to
+ * allow space for the terminating NUL).
+ */
+static int slam_put_value ( struct slam_request *slam,
+ struct io_buffer *iobuf, unsigned long value ) {
+ uint8_t *data;
+ size_t len;
+ unsigned int i;
+
+ /* Calculate variable length required to store value. Always
+ * leave at least one byte in the I/O buffer.
+ */
+ len = ( ( flsl ( value ) + 10 ) / 8 );
+ if ( len >= iob_tailroom ( iobuf ) ) {
+ DBGC2 ( slam, "SLAM %p cannot add %zd-byte value\n",
+ slam, len );
+ return -ENOBUFS;
+ }
+ /* There is no valid way within the protocol that we can end
+ * up trying to push a full-sized long (i.e. without space for
+ * the length encoding).
+ */
+ assert ( len <= sizeof ( value ) );
+
+ /* Add value */
+ data = iob_put ( iobuf, len );
+ for ( i = len ; i-- ; ) {
+ data[i] = value;
+ value >>= 8;
+ }
+ *data |= ( len << 5 );
+ assert ( value == 0 );
+
+ return 0;
+}
+
+/**
+ * Send SLAM NACK packet
+ *
+ * @v slam SLAM request
+ * @ret rc Return status code
+ */
+static int slam_tx_nack ( struct slam_request *slam ) {
+ struct io_buffer *iobuf;
+ unsigned long first_block;
+ unsigned long num_blocks;
+ uint8_t *nul;
+ int rc;
+
+ /* Mark NACK as sent, so that we know we have to disconnect later */
+ slam->nack_sent = 1;
+
+ /* Allocate I/O buffer */
+ iobuf = xfer_alloc_iob ( &slam->socket, SLAM_MAX_NACK_LEN );
+ if ( ! iobuf ) {
+ DBGC ( slam, "SLAM %p could not allocate I/O buffer\n",
+ slam );
+ return -ENOMEM;
+ }
+
+ /* Construct NACK. We always request only a single packet;
+ * this allows us to force multicast-TFTP-style flow control
+ * on the SLAM server, which will otherwise just blast the
+ * data out as fast as it can. On a gigabit network, without
+ * RX checksumming, this would inevitably cause packet drops.
+ */
+ first_block = bitmap_first_gap ( &slam->bitmap );
+ for ( num_blocks = 1 ; ; num_blocks++ ) {
+ if ( num_blocks >= SLAM_MAX_BLOCKS_PER_NACK )
+ break;
+ if ( ( first_block + num_blocks ) >= slam->num_blocks )
+ break;
+ if ( bitmap_test ( &slam->bitmap,
+ ( first_block + num_blocks ) ) )
+ break;
+ }
+ if ( first_block ) {
+ DBGCP ( slam, "SLAM %p transmitting NACK for blocks "
+ "%ld-%ld\n", slam, first_block,
+ ( first_block + num_blocks - 1 ) );
+ } else {
+ DBGC ( slam, "SLAM %p transmitting initial NACK for blocks "
+ "0-%ld\n", slam, ( num_blocks - 1 ) );
+ }
+ if ( ( rc = slam_put_value ( slam, iobuf, first_block ) ) != 0 )
+ return rc;
+ if ( ( rc = slam_put_value ( slam, iobuf, num_blocks ) ) != 0 )
+ return rc;
+ nul = iob_put ( iobuf, 1 );
+ *nul = 0;
+
+ /* Transmit packet */
+ return xfer_deliver_iob ( &slam->socket, iobuf );
+}
+
+/**
+ * Handle SLAM master client retry timer expiry
+ *
+ * @v timer Master retry timer
+ * @v fail Failure indicator
+ */
+static void slam_master_timer_expired ( struct retry_timer *timer,
+ int fail ) {
+ struct slam_request *slam =
+ container_of ( timer, struct slam_request, master_timer );
+
+ if ( fail ) {
+ /* Allow timer to stop running. We will terminate the
+ * connection only if the slave timer times out.
+ */
+ DBGC ( slam, "SLAM %p giving up acting as master client\n",
+ slam );
+ } else {
+ /* Retransmit NACK */
+ start_timer ( timer );
+ slam_tx_nack ( slam );
+ }
+}
+
+/**
+ * Handle SLAM slave client retry timer expiry
+ *
+ * @v timer Master retry timer
+ * @v fail Failure indicator
+ */
+static void slam_slave_timer_expired ( struct retry_timer *timer,
+ int fail ) {
+ struct slam_request *slam =
+ container_of ( timer, struct slam_request, slave_timer );
+
+ if ( fail ) {
+ /* Terminate connection */
+ slam_finished ( slam, -ETIMEDOUT );
+ } else {
+ /* Try sending a NACK */
+ DBGC ( slam, "SLAM %p trying to become master client\n",
+ slam );
+ start_timer ( timer );
+ slam_tx_nack ( slam );
+ }
+}
+
+/****************************************************************************
+ *
+ * RX datapath
+ *
+ */
+
+/**
+ * Read and strip a variable-length value from a SLAM packet
+ *
+ * @v slam SLAM request
+ * @v iobuf I/O buffer
+ * @v value Value to fill in, or NULL to ignore value
+ * @ret rc Return status code
+ *
+ * Reads a variable-length value from the start of the I/O buffer.
+ */
+static int slam_pull_value ( struct slam_request *slam,
+ struct io_buffer *iobuf,
+ unsigned long *value ) {
+ uint8_t *data;
+ size_t len;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) == 0 ) {
+ DBGC ( slam, "SLAM %p empty value\n", slam );
+ return -EINVAL;
+ }
+
+ /* Read and verify length of value */
+ data = iobuf->data;
+ len = ( *data >> 5 );
+ if ( ( len == 0 ) ||
+ ( value && ( len > sizeof ( *value ) ) ) ) {
+ DBGC ( slam, "SLAM %p invalid value length %zd bytes\n",
+ slam, len );
+ return -EINVAL;
+ }
+ if ( len > iob_len ( iobuf ) ) {
+ DBGC ( slam, "SLAM %p value extends beyond I/O buffer\n",
+ slam );
+ return -EINVAL;
+ }
+
+ /* Read value */
+ iob_pull ( iobuf, len );
+ *value = ( *data & 0x1f );
+ while ( --len ) {
+ *value <<= 8;
+ *value |= *(++data);
+ }
+
+ return 0;
+}
+
+/**
+ * Read and strip SLAM header
+ *
+ * @v slam SLAM request
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int slam_pull_header ( struct slam_request *slam,
+ struct io_buffer *iobuf ) {
+ void *header = iobuf->data;
+ int rc;
+
+ /* If header matches cached header, just pull it and return */
+ if ( ( slam->header_len <= iob_len ( iobuf ) ) &&
+ ( memcmp ( slam->header, iobuf->data, slam->header_len ) == 0 )){
+ iob_pull ( iobuf, slam->header_len );
+ return 0;
+ }
+
+ DBGC ( slam, "SLAM %p detected changed header; resetting\n", slam );
+
+ /* Read and strip transaction ID, total number of bytes, and
+ * block size.
+ */
+ if ( ( rc = slam_pull_value ( slam, iobuf, NULL ) ) != 0 )
+ return rc;
+ if ( ( rc = slam_pull_value ( slam, iobuf,
+ &slam->total_bytes ) ) != 0 )
+ return rc;
+ if ( ( rc = slam_pull_value ( slam, iobuf,
+ &slam->block_size ) ) != 0 )
+ return rc;
+
+ /* Update the cached header */
+ slam->header_len = ( iobuf->data - header );
+ assert ( slam->header_len <= sizeof ( slam->header ) );
+ memcpy ( slam->header, header, slam->header_len );
+
+ /* Calculate number of blocks */
+ slam->num_blocks = ( ( slam->total_bytes + slam->block_size - 1 ) /
+ slam->block_size );
+
+ DBGC ( slam, "SLAM %p has total bytes %ld, block size %ld, num "
+ "blocks %ld\n", slam, slam->total_bytes, slam->block_size,
+ slam->num_blocks );
+
+ /* Discard and reset the bitmap */
+ bitmap_free ( &slam->bitmap );
+ memset ( &slam->bitmap, 0, sizeof ( slam->bitmap ) );
+
+ /* Allocate a new bitmap */
+ if ( ( rc = bitmap_resize ( &slam->bitmap,
+ slam->num_blocks ) ) != 0 ) {
+ /* Failure to allocate a bitmap is fatal */
+ DBGC ( slam, "SLAM %p could not allocate bitmap for %ld "
+ "blocks: %s\n", slam, slam->num_blocks,
+ strerror ( rc ) );
+ slam_finished ( slam, rc );
+ return rc;
+ }
+
+ /* Notify recipient of file size */
+ xfer_seek ( &slam->xfer, slam->total_bytes );
+
+ return 0;
+}
+
+/**
+ * Receive SLAM data packet
+ *
+ * @v slam SLAM request
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int slam_mc_socket_deliver ( struct slam_request *slam,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *rx_meta __unused ) {
+ struct xfer_metadata meta;
+ unsigned long packet;
+ size_t len;
+ int rc;
+
+ /* Stop the master client timer. Restart the slave client timer. */
+ stop_timer ( &slam->master_timer );
+ stop_timer ( &slam->slave_timer );
+ start_timer_fixed ( &slam->slave_timer, SLAM_SLAVE_TIMEOUT );
+
+ /* Read and strip packet header */
+ if ( ( rc = slam_pull_header ( slam, iobuf ) ) != 0 )
+ goto err_discard;
+
+ /* Read and strip packet number */
+ if ( ( rc = slam_pull_value ( slam, iobuf, &packet ) ) != 0 )
+ goto err_discard;
+
+ /* Sanity check packet number */
+ if ( packet >= slam->num_blocks ) {
+ DBGC ( slam, "SLAM %p received out-of-range packet %ld "
+ "(num_blocks=%ld)\n", slam, packet, slam->num_blocks );
+ rc = -EINVAL;
+ goto err_discard;
+ }
+
+ /* Sanity check length */
+ len = iob_len ( iobuf );
+ if ( len > slam->block_size ) {
+ DBGC ( slam, "SLAM %p received oversize packet of %zd bytes "
+ "(block_size=%ld)\n", slam, len, slam->block_size );
+ rc = -EINVAL;
+ goto err_discard;
+ }
+ if ( ( packet != ( slam->num_blocks - 1 ) ) &&
+ ( len < slam->block_size ) ) {
+ DBGC ( slam, "SLAM %p received short packet of %zd bytes "
+ "(block_size=%ld)\n", slam, len, slam->block_size );
+ rc = -EINVAL;
+ goto err_discard;
+ }
+
+ /* If we have already seen this packet, discard it */
+ if ( bitmap_test ( &slam->bitmap, packet ) ) {
+ goto discard;
+ }
+
+ /* Pass to recipient */
+ memset ( &meta, 0, sizeof ( meta ) );
+ meta.flags = XFER_FL_ABS_OFFSET;
+ meta.offset = ( packet * slam->block_size );
+ if ( ( rc = xfer_deliver ( &slam->xfer, iobuf, &meta ) ) != 0 )
+ goto err;
+
+ /* Mark block as received */
+ bitmap_set ( &slam->bitmap, packet );
+
+ /* If we have received all blocks, terminate */
+ if ( bitmap_full ( &slam->bitmap ) )
+ slam_finished ( slam, 0 );
+
+ return 0;
+
+ err_discard:
+ discard:
+ free_iob ( iobuf );
+ err:
+ return rc;
+}
+
+/**
+ * Receive SLAM non-data packet
+ *
+ * @v slam SLAM request
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int slam_socket_deliver ( struct slam_request *slam,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *rx_meta __unused ) {
+ int rc;
+
+ /* Restart the master client timer */
+ stop_timer ( &slam->master_timer );
+ start_timer ( &slam->master_timer );
+
+ /* Read and strip packet header */
+ if ( ( rc = slam_pull_header ( slam, iobuf ) ) != 0 )
+ goto discard;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) != 0 ) {
+ DBGC ( slam, "SLAM %p received trailing garbage:\n", slam );
+ DBGC_HD ( slam, iobuf->data, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto discard;
+ }
+
+ /* Discard packet */
+ free_iob ( iobuf );
+
+ /* Send NACK in reply */
+ slam_tx_nack ( slam );
+
+ return 0;
+
+ discard:
+ free_iob ( iobuf );
+ return rc;
+
+}
+
+/** SLAM unicast socket interface operations */
+static struct interface_operation slam_socket_operations[] = {
+ INTF_OP ( xfer_deliver, struct slam_request *, slam_socket_deliver ),
+ INTF_OP ( intf_close, struct slam_request *, slam_finished ),
+};
+
+/** SLAM unicast socket interface descriptor */
+static struct interface_descriptor slam_socket_desc =
+ INTF_DESC ( struct slam_request, socket, slam_socket_operations );
+
+/** SLAM multicast socket interface operations */
+static struct interface_operation slam_mc_socket_operations[] = {
+ INTF_OP ( xfer_deliver, struct slam_request *, slam_mc_socket_deliver ),
+ INTF_OP ( intf_close, struct slam_request *, slam_finished ),
+};
+
+/** SLAM multicast socket interface descriptor */
+static struct interface_descriptor slam_mc_socket_desc =
+ INTF_DESC ( struct slam_request, mc_socket, slam_mc_socket_operations );
+
+/****************************************************************************
+ *
+ * Data transfer interface
+ *
+ */
+
+/** SLAM data transfer interface operations */
+static struct interface_operation slam_xfer_operations[] = {
+ INTF_OP ( intf_close, struct slam_request *, slam_finished ),
+};
+
+/** SLAM data transfer interface descriptor */
+static struct interface_descriptor slam_xfer_desc =
+ INTF_DESC ( struct slam_request, xfer, slam_xfer_operations );
+
+/**
+ * Parse SLAM URI multicast address
+ *
+ * @v slam SLAM request
+ * @v path Path portion of x-slam:// URI
+ * @v address Socket address to fill in
+ * @ret rc Return status code
+ */
+static int slam_parse_multicast_address ( struct slam_request *slam,
+ const char *path,
+ struct sockaddr_in *address ) {
+ char path_dup[ strlen ( path ) /* no +1 */ ];
+ char *sep;
+ char *end;
+
+ /* Create temporary copy of path, minus the leading '/' */
+ assert ( *path == '/' );
+ memcpy ( path_dup, ( path + 1 ) , sizeof ( path_dup ) );
+
+ /* Parse port, if present */
+ sep = strchr ( path_dup, ':' );
+ if ( sep ) {
+ *(sep++) = '\0';
+ address->sin_port = htons ( strtoul ( sep, &end, 0 ) );
+ if ( *end != '\0' ) {
+ DBGC ( slam, "SLAM %p invalid multicast port "
+ "\"%s\"\n", slam, sep );
+ return -EINVAL;
+ }
+ }
+
+ /* Parse address */
+ if ( inet_aton ( path_dup, &address->sin_addr ) == 0 ) {
+ DBGC ( slam, "SLAM %p invalid multicast address \"%s\"\n",
+ slam, path_dup );
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * Initiate a SLAM request
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int slam_open ( struct interface *xfer, struct uri *uri ) {
+ static const struct sockaddr_in default_multicast = {
+ .sin_family = AF_INET,
+ .sin_port = htons ( SLAM_DEFAULT_MULTICAST_PORT ),
+ .sin_addr = { htonl ( SLAM_DEFAULT_MULTICAST_IP ) },
+ };
+ struct slam_request *slam;
+ struct sockaddr_tcpip server;
+ struct sockaddr_in multicast;
+ int rc;
+
+ /* Sanity checks */
+ if ( ! uri->host )
+ return -EINVAL;
+
+ /* Allocate and populate structure */
+ slam = zalloc ( sizeof ( *slam ) );
+ if ( ! slam )
+ return -ENOMEM;
+ ref_init ( &slam->refcnt, slam_free );
+ intf_init ( &slam->xfer, &slam_xfer_desc, &slam->refcnt );
+ intf_init ( &slam->socket, &slam_socket_desc, &slam->refcnt );
+ intf_init ( &slam->mc_socket, &slam_mc_socket_desc, &slam->refcnt );
+ timer_init ( &slam->master_timer, slam_master_timer_expired,
+ &slam->refcnt );
+ timer_init ( &slam->slave_timer, slam_slave_timer_expired,
+ &slam->refcnt );
+ /* Fake an invalid cached header of { 0x00, ... } */
+ slam->header_len = 1;
+ /* Fake parameters for initial NACK */
+ slam->num_blocks = 1;
+ if ( ( rc = bitmap_resize ( &slam->bitmap, 1 ) ) != 0 ) {
+ DBGC ( slam, "SLAM %p could not allocate initial bitmap: "
+ "%s\n", slam, strerror ( rc ) );
+ goto err;
+ }
+
+ /* Open unicast socket */
+ memset ( &server, 0, sizeof ( server ) );
+ server.st_port = htons ( uri_port ( uri, SLAM_DEFAULT_PORT ) );
+ if ( ( rc = xfer_open_named_socket ( &slam->socket, SOCK_DGRAM,
+ ( struct sockaddr * ) &server,
+ uri->host, NULL ) ) != 0 ) {
+ DBGC ( slam, "SLAM %p could not open unicast socket: %s\n",
+ slam, strerror ( rc ) );
+ goto err;
+ }
+
+ /* Open multicast socket */
+ memcpy ( &multicast, &default_multicast, sizeof ( multicast ) );
+ if ( uri->path &&
+ ( ( rc = slam_parse_multicast_address ( slam, uri->path,
+ &multicast ) ) != 0 ) ) {
+ goto err;
+ }
+ if ( ( rc = xfer_open_socket ( &slam->mc_socket, SOCK_DGRAM,
+ ( struct sockaddr * ) &multicast,
+ ( struct sockaddr * ) &multicast ) ) != 0 ) {
+ DBGC ( slam, "SLAM %p could not open multicast socket: %s\n",
+ slam, strerror ( rc ) );
+ goto err;
+ }
+
+ /* Start slave retry timer */
+ start_timer_fixed ( &slam->slave_timer, SLAM_SLAVE_TIMEOUT );
+
+ /* Attach to parent interface, mortalise self, and return */
+ intf_plug_plug ( &slam->xfer, xfer );
+ ref_put ( &slam->refcnt );
+ return 0;
+
+ err:
+ slam_finished ( slam, rc );
+ ref_put ( &slam->refcnt );
+ return rc;
+}
+
+/** SLAM URI opener */
+struct uri_opener slam_uri_opener __uri_opener = {
+ .scheme = "x-slam",
+ .open = slam_open,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/udp/syslog.c b/src/VBox/Devices/PC/ipxe/src/net/udp/syslog.c
new file mode 100644
index 00000000..4a265314
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/udp/syslog.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Syslog protocol
+ *
+ */
+
+#include <stdint.h>
+#include <byteswap.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/settings.h>
+#include <ipxe/console.h>
+#include <ipxe/lineconsole.h>
+#include <ipxe/syslog.h>
+#include <config/console.h>
+
+/* Set default console usage if applicable */
+#if ! ( defined ( CONSOLE_SYSLOG ) && CONSOLE_EXPLICIT ( CONSOLE_SYSLOG ) )
+#undef CONSOLE_SYSLOG
+#define CONSOLE_SYSLOG ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_TUI )
+#endif
+
+/** The syslog server */
+static struct sockaddr_tcpip logserver = {
+ .st_family = AF_INET,
+ .st_port = htons ( SYSLOG_PORT ),
+};
+
+/** Syslog UDP interface operations */
+static struct interface_operation syslogger_operations[] = {};
+
+/** Syslog UDP interface descriptor */
+static struct interface_descriptor syslogger_desc =
+ INTF_DESC_PURE ( syslogger_operations );
+
+/** The syslog UDP interface */
+static struct interface syslogger = INTF_INIT ( syslogger_desc );
+
+/******************************************************************************
+ *
+ * Console driver
+ *
+ ******************************************************************************
+ */
+
+/** Syslog line buffer */
+static char syslog_buffer[SYSLOG_BUFSIZE];
+
+/** Syslog severity */
+static unsigned int syslog_severity = SYSLOG_DEFAULT_SEVERITY;
+
+/**
+ * Handle ANSI set syslog priority (private sequence)
+ *
+ * @v count Parameter count
+ * @v params List of graphic rendition aspects
+ */
+static void syslog_handle_priority ( unsigned int count __unused,
+ int params[] ) {
+ if ( params[0] >= 0 ) {
+ syslog_severity = params[0];
+ } else {
+ syslog_severity = SYSLOG_DEFAULT_SEVERITY;
+ }
+}
+
+/** Syslog ANSI escape sequence handlers */
+static struct ansiesc_handler syslog_handlers[] = {
+ { ANSIESC_LOG_PRIORITY, syslog_handle_priority },
+ { 0, NULL }
+};
+
+/** Syslog line console */
+static struct line_console syslog_line = {
+ .buffer = syslog_buffer,
+ .len = sizeof ( syslog_buffer ),
+ .ctx = {
+ .handlers = syslog_handlers,
+ },
+};
+
+/** Syslog recursion marker */
+static int syslog_entered;
+
+/**
+ * Print a character to syslog console
+ *
+ * @v character Character to be printed
+ */
+static void syslog_putchar ( int character ) {
+ int rc;
+
+ /* Ignore if we are already mid-logging */
+ if ( syslog_entered )
+ return;
+
+ /* Fill line buffer */
+ if ( line_putchar ( &syslog_line, character ) == 0 )
+ return;
+
+ /* Guard against re-entry */
+ syslog_entered = 1;
+
+ /* Send log message */
+ if ( ( rc = xfer_printf ( &syslogger, "<%d>ipxe: %s",
+ SYSLOG_PRIORITY ( SYSLOG_DEFAULT_FACILITY,
+ syslog_severity ),
+ syslog_buffer ) ) != 0 ) {
+ DBG ( "SYSLOG could not send log message: %s\n",
+ strerror ( rc ) );
+ }
+
+ /* Clear re-entry flag */
+ syslog_entered = 0;
+}
+
+/** Syslog console driver */
+struct console_driver syslog_console __console_driver = {
+ .putchar = syslog_putchar,
+ .disabled = 1,
+ .usage = CONSOLE_SYSLOG,
+};
+
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** Syslog server setting */
+struct setting syslog_setting __setting ( SETTING_MISC ) = {
+ .name = "syslog",
+ .description = "Syslog server",
+ .tag = DHCP_LOG_SERVERS,
+ .type = &setting_type_ipv4,
+};
+
+/**
+ * Apply syslog settings
+ *
+ * @ret rc Return status code
+ */
+static int apply_syslog_settings ( void ) {
+ struct sockaddr_in *sin_logserver =
+ ( struct sockaddr_in * ) &logserver;
+ struct in_addr old_addr;
+ int len;
+ int rc;
+
+ /* Fetch log server */
+ syslog_console.disabled = 1;
+ old_addr.s_addr = sin_logserver->sin_addr.s_addr;
+ if ( ( len = fetch_ipv4_setting ( NULL, &syslog_setting,
+ &sin_logserver->sin_addr ) ) >= 0 ) {
+ syslog_console.disabled = 0;
+ }
+
+ /* Do nothing unless log server has changed */
+ if ( sin_logserver->sin_addr.s_addr == old_addr.s_addr )
+ return 0;
+
+ /* Reset syslog connection */
+ intf_restart ( &syslogger, 0 );
+
+ /* Do nothing unless we have a log server */
+ if ( syslog_console.disabled ) {
+ DBG ( "SYSLOG has no log server\n" );
+ return 0;
+ }
+
+ /* Connect to log server */
+ if ( ( rc = xfer_open_socket ( &syslogger, SOCK_DGRAM,
+ ( ( struct sockaddr * ) &logserver ),
+ NULL ) ) != 0 ) {
+ DBG ( "SYSLOG cannot connect to log server: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+ DBG ( "SYSLOG using log server %s\n",
+ inet_ntoa ( sin_logserver->sin_addr ) );
+
+ return 0;
+}
+
+/** Syslog settings applicator */
+struct settings_applicator syslog_applicator __settings_applicator = {
+ .apply = apply_syslog_settings,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/udp/tftp.c b/src/VBox/Devices/PC/ipxe/src/net/udp/tftp.c
new file mode 100644
index 00000000..a2d6473c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/udp/tftp.c
@@ -0,0 +1,1259 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/uri.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/retry.h>
+#include <ipxe/features.h>
+#include <ipxe/bitmap.h>
+#include <ipxe/settings.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/uri.h>
+#include <ipxe/tftp.h>
+
+/** @file
+ *
+ * TFTP protocol
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "TFTP", DHCP_EB_FEATURE_TFTP, 1 );
+
+/* TFTP-specific error codes */
+#define EINVAL_BLKSIZE __einfo_error ( EINFO_EINVAL_BLKSIZE )
+#define EINFO_EINVAL_BLKSIZE __einfo_uniqify \
+ ( EINFO_EINVAL, 0x01, "Invalid blksize" )
+#define EINVAL_TSIZE __einfo_error ( EINFO_EINVAL_TSIZE )
+#define EINFO_EINVAL_TSIZE __einfo_uniqify \
+ ( EINFO_EINVAL, 0x02, "Invalid tsize" )
+#define EINVAL_MC_NO_PORT __einfo_error ( EINFO_EINVAL_MC_NO_PORT )
+#define EINFO_EINVAL_MC_NO_PORT __einfo_uniqify \
+ ( EINFO_EINVAL, 0x03, "Missing multicast port" )
+#define EINVAL_MC_NO_MC __einfo_error ( EINFO_EINVAL_MC_NO_MC )
+#define EINFO_EINVAL_MC_NO_MC __einfo_uniqify \
+ ( EINFO_EINVAL, 0x04, "Missing multicast mc" )
+#define EINVAL_MC_INVALID_MC __einfo_error ( EINFO_EINVAL_MC_INVALID_MC )
+#define EINFO_EINVAL_MC_INVALID_MC __einfo_uniqify \
+ ( EINFO_EINVAL, 0x05, "Missing multicast IP" )
+#define EINVAL_MC_INVALID_IP __einfo_error ( EINFO_EINVAL_MC_INVALID_IP )
+#define EINFO_EINVAL_MC_INVALID_IP __einfo_uniqify \
+ ( EINFO_EINVAL, 0x06, "Invalid multicast IP" )
+#define EINVAL_MC_INVALID_PORT __einfo_error ( EINFO_EINVAL_MC_INVALID_PORT )
+#define EINFO_EINVAL_MC_INVALID_PORT __einfo_uniqify \
+ ( EINFO_EINVAL, 0x07, "Invalid multicast port" )
+
+/**
+ * A TFTP request
+ *
+ * This data structure holds the state for an ongoing TFTP transfer.
+ */
+struct tftp_request {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Data transfer interface */
+ struct interface xfer;
+
+ /** URI being fetched */
+ struct uri *uri;
+ /** Transport layer interface */
+ struct interface socket;
+ /** Multicast transport layer interface */
+ struct interface mc_socket;
+
+ /** Data block size
+ *
+ * This is the "blksize" option negotiated with the TFTP
+ * server. (If the TFTP server does not support TFTP options,
+ * this will default to 512).
+ */
+ unsigned int blksize;
+ /** File size
+ *
+ * This is the value returned in the "tsize" option from the
+ * TFTP server. If the TFTP server does not support the
+ * "tsize" option, this value will be zero.
+ */
+ unsigned long tsize;
+
+ /** Server port
+ *
+ * This is the port to which RRQ packets are sent.
+ */
+ unsigned int port;
+ /** Peer address
+ *
+ * The peer address is determined by the first response
+ * received to the TFTP RRQ.
+ */
+ struct sockaddr_tcpip peer;
+ /** Request flags */
+ unsigned int flags;
+ /** MTFTP timeout count */
+ unsigned int mtftp_timeouts;
+
+ /** Block bitmap */
+ struct bitmap bitmap;
+ /** Maximum known length
+ *
+ * We don't always know the file length in advance. In
+ * particular, if the TFTP server doesn't support the tsize
+ * option, or we are using MTFTP, then we don't know the file
+ * length until we see the end-of-file block (which, in the
+ * case of MTFTP, may not be the last block we see).
+ *
+ * This value is updated whenever we obtain information about
+ * the file length.
+ */
+ size_t filesize;
+ /** Retransmission timer */
+ struct retry_timer timer;
+};
+
+/** TFTP request flags */
+enum {
+ /** Send ACK packets */
+ TFTP_FL_SEND_ACK = 0x0001,
+ /** Request blksize and tsize options */
+ TFTP_FL_RRQ_SIZES = 0x0002,
+ /** Request multicast option */
+ TFTP_FL_RRQ_MULTICAST = 0x0004,
+ /** Perform MTFTP recovery on timeout */
+ TFTP_FL_MTFTP_RECOVERY = 0x0008,
+ /** Only get filesize and then abort the transfer */
+ TFTP_FL_SIZEONLY = 0x0010,
+};
+
+/** Maximum number of MTFTP open requests before falling back to TFTP */
+#define MTFTP_MAX_TIMEOUTS 3
+
+/**
+ * Free TFTP request
+ *
+ * @v refcnt Reference counter
+ */
+static void tftp_free ( struct refcnt *refcnt ) {
+ struct tftp_request *tftp =
+ container_of ( refcnt, struct tftp_request, refcnt );
+
+ uri_put ( tftp->uri );
+ bitmap_free ( &tftp->bitmap );
+ free ( tftp );
+}
+
+/**
+ * Mark TFTP request as complete
+ *
+ * @v tftp TFTP connection
+ * @v rc Return status code
+ */
+static void tftp_done ( struct tftp_request *tftp, int rc ) {
+
+ DBGC ( tftp, "TFTP %p finished with status %d (%s)\n",
+ tftp, rc, strerror ( rc ) );
+
+ /* Stop the retry timer */
+ stop_timer ( &tftp->timer );
+
+ /* Close all data transfer interfaces */
+ intf_shutdown ( &tftp->socket, rc );
+ intf_shutdown ( &tftp->mc_socket, rc );
+ intf_shutdown ( &tftp->xfer, rc );
+}
+
+/**
+ * Reopen TFTP socket
+ *
+ * @v tftp TFTP connection
+ * @ret rc Return status code
+ */
+static int tftp_reopen ( struct tftp_request *tftp ) {
+ struct sockaddr_tcpip server;
+ int rc;
+
+ /* Close socket */
+ intf_restart ( &tftp->socket, 0 );
+
+ /* Disable ACK sending. */
+ tftp->flags &= ~TFTP_FL_SEND_ACK;
+
+ /* Reset peer address */
+ memset ( &tftp->peer, 0, sizeof ( tftp->peer ) );
+
+ /* Open socket */
+ memset ( &server, 0, sizeof ( server ) );
+ server.st_port = htons ( tftp->port );
+ if ( ( rc = xfer_open_named_socket ( &tftp->socket, SOCK_DGRAM,
+ ( struct sockaddr * ) &server,
+ tftp->uri->host, NULL ) ) != 0 ) {
+ DBGC ( tftp, "TFTP %p could not open socket: %s\n",
+ tftp, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Reopen TFTP multicast socket
+ *
+ * @v tftp TFTP connection
+ * @v local Local socket address
+ * @ret rc Return status code
+ */
+static int tftp_reopen_mc ( struct tftp_request *tftp,
+ struct sockaddr *local ) {
+ int rc;
+
+ /* Close multicast socket */
+ intf_restart ( &tftp->mc_socket, 0 );
+
+ /* Open multicast socket. We never send via this socket, so
+ * use the local address as the peer address (since the peer
+ * address cannot be NULL).
+ */
+ if ( ( rc = xfer_open_socket ( &tftp->mc_socket, SOCK_DGRAM,
+ local, local ) ) != 0 ) {
+ DBGC ( tftp, "TFTP %p could not open multicast "
+ "socket: %s\n", tftp, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Presize TFTP receive buffers and block bitmap
+ *
+ * @v tftp TFTP connection
+ * @v filesize Known minimum file size
+ * @ret rc Return status code
+ */
+static int tftp_presize ( struct tftp_request *tftp, size_t filesize ) {
+ unsigned int num_blocks;
+ int rc;
+
+ /* Do nothing if we are already large enough */
+ if ( filesize <= tftp->filesize )
+ return 0;
+
+ /* Record filesize */
+ tftp->filesize = filesize;
+
+ /* Notify recipient of file size */
+ xfer_seek ( &tftp->xfer, filesize );
+ xfer_seek ( &tftp->xfer, 0 );
+
+ /* Calculate expected number of blocks. Note that files whose
+ * length is an exact multiple of the blocksize will have a
+ * trailing zero-length block, which must be included.
+ */
+ num_blocks = ( ( filesize / tftp->blksize ) + 1 );
+ if ( ( rc = bitmap_resize ( &tftp->bitmap, num_blocks ) ) != 0 ) {
+ DBGC ( tftp, "TFTP %p could not resize bitmap to %d blocks: "
+ "%s\n", tftp, num_blocks, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * TFTP requested blocksize
+ *
+ * This is treated as a global configuration parameter.
+ */
+static unsigned int tftp_request_blksize = TFTP_MAX_BLKSIZE;
+
+/**
+ * Set TFTP request blocksize
+ *
+ * @v blksize Requested block size
+ */
+void tftp_set_request_blksize ( unsigned int blksize ) {
+ if ( blksize < TFTP_DEFAULT_BLKSIZE )
+ blksize = TFTP_DEFAULT_BLKSIZE;
+ tftp_request_blksize = blksize;
+}
+
+/**
+ * MTFTP multicast receive address
+ *
+ * This is treated as a global configuration parameter.
+ */
+static struct sockaddr_in tftp_mtftp_socket = {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = htonl ( 0xefff0101 ),
+ .sin_port = htons ( 3001 ),
+};
+
+/**
+ * Set MTFTP multicast address
+ *
+ * @v address Multicast IPv4 address
+ */
+void tftp_set_mtftp_address ( struct in_addr address ) {
+ tftp_mtftp_socket.sin_addr = address;
+}
+
+/**
+ * Set MTFTP multicast port
+ *
+ * @v port Multicast port
+ */
+void tftp_set_mtftp_port ( unsigned int port ) {
+ tftp_mtftp_socket.sin_port = htons ( port );
+}
+
+/**
+ * Transmit RRQ
+ *
+ * @v tftp TFTP connection
+ * @ret rc Return status code
+ */
+static int tftp_send_rrq ( struct tftp_request *tftp ) {
+ struct tftp_rrq *rrq;
+ const char *path;
+ size_t len;
+ struct io_buffer *iobuf;
+
+ /* Strip initial '/' if present. If we were opened via the
+ * URI interface, then there will be an initial '/', since a
+ * full tftp:// URI provides no way to specify a non-absolute
+ * path. However, many TFTP servers (particularly Windows
+ * TFTP servers) complain about having an initial '/', and it
+ * violates user expectations to have a '/' silently added to
+ * the DHCP-specified filename.
+ */
+ path = tftp->uri->path;
+ if ( *path == '/' )
+ path++;
+
+ DBGC ( tftp, "TFTP %p requesting \"%s\"\n", tftp, path );
+
+ /* Allocate buffer */
+ len = ( sizeof ( *rrq ) + strlen ( path ) + 1 /* NUL */
+ + 5 + 1 /* "octet" + NUL */
+ + 7 + 1 + 5 + 1 /* "blksize" + NUL + ddddd + NUL */
+ + 5 + 1 + 1 + 1 /* "tsize" + NUL + "0" + NUL */
+ + 9 + 1 + 1 /* "multicast" + NUL + NUL */ );
+ iobuf = xfer_alloc_iob ( &tftp->socket, len );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ /* Build request */
+ rrq = iob_put ( iobuf, sizeof ( *rrq ) );
+ rrq->opcode = htons ( TFTP_RRQ );
+ iob_put ( iobuf, snprintf ( iobuf->tail, iob_tailroom ( iobuf ),
+ "%s%coctet", path, 0 ) + 1 );
+ if ( tftp->flags & TFTP_FL_RRQ_SIZES ) {
+ iob_put ( iobuf, snprintf ( iobuf->tail,
+ iob_tailroom ( iobuf ),
+ "blksize%c%d%ctsize%c0", 0,
+ tftp_request_blksize, 0, 0 ) + 1 );
+ }
+ if ( tftp->flags & TFTP_FL_RRQ_MULTICAST ) {
+ iob_put ( iobuf, snprintf ( iobuf->tail,
+ iob_tailroom ( iobuf ),
+ "multicast%c", 0 ) + 1 );
+ }
+
+ /* RRQ always goes to the address specified in the initial
+ * xfer_open() call
+ */
+ return xfer_deliver_iob ( &tftp->socket, iobuf );
+}
+
+/**
+ * Transmit ACK
+ *
+ * @v tftp TFTP connection
+ * @ret rc Return status code
+ */
+static int tftp_send_ack ( struct tftp_request *tftp ) {
+ struct tftp_ack *ack;
+ struct io_buffer *iobuf;
+ struct xfer_metadata meta = {
+ .dest = ( struct sockaddr * ) &tftp->peer,
+ };
+ unsigned int block;
+
+ /* Determine next required block number */
+ block = bitmap_first_gap ( &tftp->bitmap );
+ DBGC2 ( tftp, "TFTP %p sending ACK for block %d\n", tftp, block );
+
+ /* Allocate buffer */
+ iobuf = xfer_alloc_iob ( &tftp->socket, sizeof ( *ack ) );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ /* Build ACK */
+ ack = iob_put ( iobuf, sizeof ( *ack ) );
+ ack->opcode = htons ( TFTP_ACK );
+ ack->block = htons ( block );
+
+ /* ACK always goes to the peer recorded from the RRQ response */
+ return xfer_deliver ( &tftp->socket, iobuf, &meta );
+}
+
+/**
+ * Transmit ERROR (Abort)
+ *
+ * @v tftp TFTP connection
+ * @v errcode TFTP error code
+ * @v errmsg Error message string
+ * @ret rc Return status code
+ */
+static int tftp_send_error ( struct tftp_request *tftp, int errcode,
+ const char *errmsg ) {
+ struct tftp_error *err;
+ struct io_buffer *iobuf;
+ struct xfer_metadata meta = {
+ .dest = ( struct sockaddr * ) &tftp->peer,
+ };
+ size_t msglen;
+
+ DBGC2 ( tftp, "TFTP %p sending ERROR %d: %s\n", tftp, errcode,
+ errmsg );
+
+ /* Allocate buffer */
+ msglen = sizeof ( *err ) + strlen ( errmsg ) + 1 /* NUL */;
+ iobuf = xfer_alloc_iob ( &tftp->socket, msglen );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ /* Build ERROR */
+ err = iob_put ( iobuf, msglen );
+ err->opcode = htons ( TFTP_ERROR );
+ err->errcode = htons ( errcode );
+ strcpy ( err->errmsg, errmsg );
+
+ /* ERR always goes to the peer recorded from the RRQ response */
+ return xfer_deliver ( &tftp->socket, iobuf, &meta );
+}
+
+/**
+ * Transmit next relevant packet
+ *
+ * @v tftp TFTP connection
+ * @ret rc Return status code
+ */
+static int tftp_send_packet ( struct tftp_request *tftp ) {
+
+ /* Update retransmission timer. While name resolution takes place the
+ * window is zero. Avoid unnecessary delay after name resolution
+ * completes by retrying immediately.
+ */
+ stop_timer ( &tftp->timer );
+ if ( xfer_window ( &tftp->socket ) ) {
+ start_timer ( &tftp->timer );
+ } else {
+ start_timer_nodelay ( &tftp->timer );
+ }
+
+ /* Send RRQ or ACK as appropriate */
+ if ( ! tftp->peer.st_family ) {
+ return tftp_send_rrq ( tftp );
+ } else {
+ if ( tftp->flags & TFTP_FL_SEND_ACK ) {
+ return tftp_send_ack ( tftp );
+ } else {
+ return 0;
+ }
+ }
+}
+
+/**
+ * Handle TFTP retransmission timer expiry
+ *
+ * @v timer Retry timer
+ * @v fail Failure indicator
+ */
+static void tftp_timer_expired ( struct retry_timer *timer, int fail ) {
+ struct tftp_request *tftp =
+ container_of ( timer, struct tftp_request, timer );
+ int rc;
+
+ /* If we are doing MTFTP, attempt the various recovery strategies */
+ if ( tftp->flags & TFTP_FL_MTFTP_RECOVERY ) {
+ if ( tftp->peer.st_family ) {
+ /* If we have received any response from the server,
+ * try resending the RRQ to restart the download.
+ */
+ DBGC ( tftp, "TFTP %p attempting reopen\n", tftp );
+ if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
+ goto err;
+ } else {
+ /* Fall back to plain TFTP after several attempts */
+ tftp->mtftp_timeouts++;
+ DBGC ( tftp, "TFTP %p timeout %d waiting for MTFTP "
+ "open\n", tftp, tftp->mtftp_timeouts );
+
+ if ( tftp->mtftp_timeouts > MTFTP_MAX_TIMEOUTS ) {
+ DBGC ( tftp, "TFTP %p falling back to plain "
+ "TFTP\n", tftp );
+ tftp->flags = TFTP_FL_RRQ_SIZES;
+
+ /* Close multicast socket */
+ intf_restart ( &tftp->mc_socket, 0 );
+
+ /* Reset retry timer */
+ start_timer_nodelay ( &tftp->timer );
+
+ /* The blocksize may change: discard
+ * the block bitmap
+ */
+ bitmap_free ( &tftp->bitmap );
+ memset ( &tftp->bitmap, 0,
+ sizeof ( tftp->bitmap ) );
+
+ /* Reopen on standard TFTP port */
+ tftp->port = TFTP_PORT;
+ if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
+ goto err;
+ }
+ }
+ } else {
+ /* Not doing MTFTP (or have fallen back to plain
+ * TFTP); fail as per normal.
+ */
+ if ( fail ) {
+ rc = -ETIMEDOUT;
+ goto err;
+ }
+ }
+ tftp_send_packet ( tftp );
+ return;
+
+ err:
+ tftp_done ( tftp, rc );
+}
+
+/**
+ * Process TFTP "blksize" option
+ *
+ * @v tftp TFTP connection
+ * @v value Option value
+ * @ret rc Return status code
+ */
+static int tftp_process_blksize ( struct tftp_request *tftp,
+ const char *value ) {
+ char *end;
+
+ tftp->blksize = strtoul ( value, &end, 10 );
+ if ( *end ) {
+ DBGC ( tftp, "TFTP %p got invalid blksize \"%s\"\n",
+ tftp, value );
+ return -EINVAL_BLKSIZE;
+ }
+ DBGC ( tftp, "TFTP %p blksize=%d\n", tftp, tftp->blksize );
+
+ return 0;
+}
+
+/**
+ * Process TFTP "tsize" option
+ *
+ * @v tftp TFTP connection
+ * @v value Option value
+ * @ret rc Return status code
+ */
+static int tftp_process_tsize ( struct tftp_request *tftp,
+ const char *value ) {
+ char *end;
+
+ tftp->tsize = strtoul ( value, &end, 10 );
+ if ( *end ) {
+ DBGC ( tftp, "TFTP %p got invalid tsize \"%s\"\n",
+ tftp, value );
+ return -EINVAL_TSIZE;
+ }
+ DBGC ( tftp, "TFTP %p tsize=%ld\n", tftp, tftp->tsize );
+
+ return 0;
+}
+
+/**
+ * Process TFTP "multicast" option
+ *
+ * @v tftp TFTP connection
+ * @v value Option value
+ * @ret rc Return status code
+ */
+static int tftp_process_multicast ( struct tftp_request *tftp,
+ const char *value ) {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ } socket;
+ char buf[ strlen ( value ) + 1 ];
+ char *addr;
+ char *port;
+ char *port_end;
+ char *mc;
+ char *mc_end;
+ int rc;
+
+ /* Split value into "addr,port,mc" fields */
+ memcpy ( buf, value, sizeof ( buf ) );
+ addr = buf;
+ port = strchr ( addr, ',' );
+ if ( ! port ) {
+ DBGC ( tftp, "TFTP %p multicast missing port,mc\n", tftp );
+ return -EINVAL_MC_NO_PORT;
+ }
+ *(port++) = '\0';
+ mc = strchr ( port, ',' );
+ if ( ! mc ) {
+ DBGC ( tftp, "TFTP %p multicast missing mc\n", tftp );
+ return -EINVAL_MC_NO_MC;
+ }
+ *(mc++) = '\0';
+
+ /* Parse parameters */
+ if ( strtoul ( mc, &mc_end, 0 ) == 0 )
+ tftp->flags &= ~TFTP_FL_SEND_ACK;
+ if ( *mc_end ) {
+ DBGC ( tftp, "TFTP %p multicast invalid mc %s\n", tftp, mc );
+ return -EINVAL_MC_INVALID_MC;
+ }
+ DBGC ( tftp, "TFTP %p is%s the master client\n",
+ tftp, ( ( tftp->flags & TFTP_FL_SEND_ACK ) ? "" : " not" ) );
+ if ( *addr && *port ) {
+ socket.sin.sin_family = AF_INET;
+ if ( inet_aton ( addr, &socket.sin.sin_addr ) == 0 ) {
+ DBGC ( tftp, "TFTP %p multicast invalid IP address "
+ "%s\n", tftp, addr );
+ return -EINVAL_MC_INVALID_IP;
+ }
+ DBGC ( tftp, "TFTP %p multicast IP address %s\n",
+ tftp, inet_ntoa ( socket.sin.sin_addr ) );
+ socket.sin.sin_port = htons ( strtoul ( port, &port_end, 0 ) );
+ if ( *port_end ) {
+ DBGC ( tftp, "TFTP %p multicast invalid port %s\n",
+ tftp, port );
+ return -EINVAL_MC_INVALID_PORT;
+ }
+ DBGC ( tftp, "TFTP %p multicast port %d\n",
+ tftp, ntohs ( socket.sin.sin_port ) );
+ if ( ( rc = tftp_reopen_mc ( tftp, &socket.sa ) ) != 0 )
+ return rc;
+ }
+
+ return 0;
+}
+
+/** A TFTP option */
+struct tftp_option {
+ /** Option name */
+ const char *name;
+ /** Option processor
+ *
+ * @v tftp TFTP connection
+ * @v value Option value
+ * @ret rc Return status code
+ */
+ int ( * process ) ( struct tftp_request *tftp, const char *value );
+};
+
+/** Recognised TFTP options */
+static struct tftp_option tftp_options[] = {
+ { "blksize", tftp_process_blksize },
+ { "tsize", tftp_process_tsize },
+ { "multicast", tftp_process_multicast },
+ { NULL, NULL }
+};
+
+/**
+ * Process TFTP option
+ *
+ * @v tftp TFTP connection
+ * @v name Option name
+ * @v value Option value
+ * @ret rc Return status code
+ */
+static int tftp_process_option ( struct tftp_request *tftp,
+ const char *name, const char *value ) {
+ struct tftp_option *option;
+
+ for ( option = tftp_options ; option->name ; option++ ) {
+ if ( strcasecmp ( name, option->name ) == 0 )
+ return option->process ( tftp, value );
+ }
+
+ DBGC ( tftp, "TFTP %p received unknown option \"%s\" = \"%s\"\n",
+ tftp, name, value );
+
+ /* Unknown options should be silently ignored */
+ return 0;
+}
+
+/**
+ * Receive OACK
+ *
+ * @v tftp TFTP connection
+ * @v buf Temporary data buffer
+ * @v len Length of temporary data buffer
+ * @ret rc Return status code
+ */
+static int tftp_rx_oack ( struct tftp_request *tftp, void *buf, size_t len ) {
+ struct tftp_oack *oack = buf;
+ char *end = buf + len;
+ char *name;
+ char *value;
+ char *next;
+ int rc = 0;
+
+ /* Sanity check */
+ if ( len < sizeof ( *oack ) ) {
+ DBGC ( tftp, "TFTP %p received underlength OACK packet "
+ "length %zd\n", tftp, len );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Process each option in turn */
+ for ( name = oack->data ; name < end ; name = next ) {
+
+ /* Parse option name and value
+ *
+ * We treat parsing errors as non-fatal, because there
+ * exists at least one TFTP server (IBM Tivoli PXE
+ * Server 5.1.0.3) that has been observed to send
+ * malformed OACKs containing trailing garbage bytes.
+ */
+ value = ( name + strnlen ( name, ( end - name ) ) + 1 );
+ if ( value > end ) {
+ DBGC ( tftp, "TFTP %p received OACK with malformed "
+ "option name:\n", tftp );
+ DBGC_HD ( tftp, oack, len );
+ break;
+ }
+ if ( value == end ) {
+ DBGC ( tftp, "TFTP %p received OACK missing value "
+ "for option \"%s\"\n", tftp, name );
+ DBGC_HD ( tftp, oack, len );
+ break;
+ }
+ next = ( value + strnlen ( value, ( end - value ) ) + 1 );
+ if ( next > end ) {
+ DBGC ( tftp, "TFTP %p received OACK with malformed "
+ "value for option \"%s\":\n", tftp, name );
+ DBGC_HD ( tftp, oack, len );
+ break;
+ }
+
+ /* Process option */
+ if ( ( rc = tftp_process_option ( tftp, name, value ) ) != 0 )
+ goto done;
+ }
+
+ /* Process tsize information, if available */
+ if ( tftp->tsize ) {
+ if ( ( rc = tftp_presize ( tftp, tftp->tsize ) ) != 0 )
+ goto done;
+ }
+
+ /* Abort request if only trying to determine file size */
+ if ( tftp->flags & TFTP_FL_SIZEONLY ) {
+ rc = 0;
+ tftp_send_error ( tftp, 0, "TFTP Aborted" );
+ tftp_done ( tftp, rc );
+ return rc;
+ }
+
+ /* Request next data block */
+ tftp_send_packet ( tftp );
+
+ done:
+ if ( rc )
+ tftp_done ( tftp, rc );
+ return rc;
+}
+
+/**
+ * Receive DATA
+ *
+ * @v tftp TFTP connection
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * Takes ownership of I/O buffer.
+ */
+static int tftp_rx_data ( struct tftp_request *tftp,
+ struct io_buffer *iobuf ) {
+ struct tftp_data *data = iobuf->data;
+ struct xfer_metadata meta;
+ unsigned int block;
+ off_t offset;
+ size_t data_len;
+ int rc;
+
+ if ( tftp->flags & TFTP_FL_SIZEONLY ) {
+ /* If we get here then server doesn't support SIZE option */
+ rc = -ENOTSUP;
+ tftp_send_error ( tftp, 0, "TFTP Aborted" );
+ goto done;
+ }
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *data ) ) {
+ DBGC ( tftp, "TFTP %p received underlength DATA packet "
+ "length %zd\n", tftp, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Calculate block number */
+ block = ( ( bitmap_first_gap ( &tftp->bitmap ) + 1 ) & ~0xffff );
+ if ( data->block == 0 && block == 0 ) {
+ DBGC ( tftp, "TFTP %p received data block 0\n", tftp );
+ rc = -EINVAL;
+ goto done;
+ }
+ block += ( ntohs ( data->block ) - 1 );
+
+ /* Extract data */
+ offset = ( block * tftp->blksize );
+ iob_pull ( iobuf, sizeof ( *data ) );
+ data_len = iob_len ( iobuf );
+ if ( data_len > tftp->blksize ) {
+ DBGC ( tftp, "TFTP %p received overlength DATA packet "
+ "length %zd\n", tftp, data_len );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Deliver data */
+ memset ( &meta, 0, sizeof ( meta ) );
+ meta.flags = XFER_FL_ABS_OFFSET;
+ meta.offset = offset;
+ if ( ( rc = xfer_deliver ( &tftp->xfer, iob_disown ( iobuf ),
+ &meta ) ) != 0 ) {
+ DBGC ( tftp, "TFTP %p could not deliver data: %s\n",
+ tftp, strerror ( rc ) );
+ goto done;
+ }
+
+ /* Ensure block bitmap is ready */
+ if ( ( rc = tftp_presize ( tftp, ( offset + data_len ) ) ) != 0 )
+ goto done;
+
+ /* Mark block as received */
+ bitmap_set ( &tftp->bitmap, block );
+
+ /* Acknowledge block */
+ tftp_send_packet ( tftp );
+
+ /* If all blocks have been received, finish. */
+ if ( bitmap_full ( &tftp->bitmap ) )
+ tftp_done ( tftp, 0 );
+
+ done:
+ free_iob ( iobuf );
+ if ( rc )
+ tftp_done ( tftp, rc );
+ return rc;
+}
+
+/**
+ * Convert TFTP error code to return status code
+ *
+ * @v errcode TFTP error code
+ * @ret rc Return status code
+ */
+static int tftp_errcode_to_rc ( unsigned int errcode ) {
+ switch ( errcode ) {
+ case TFTP_ERR_FILE_NOT_FOUND: return -ENOENT;
+ case TFTP_ERR_ACCESS_DENIED: return -EACCES;
+ case TFTP_ERR_ILLEGAL_OP: return -ENOTTY;
+ default: return -ENOTSUP;
+ }
+}
+
+/**
+ * Receive ERROR
+ *
+ * @v tftp TFTP connection
+ * @v buf Temporary data buffer
+ * @v len Length of temporary data buffer
+ * @ret rc Return status code
+ */
+static int tftp_rx_error ( struct tftp_request *tftp, void *buf, size_t len ) {
+ struct tftp_error *error = buf;
+ int rc;
+
+ /* Sanity check */
+ if ( len < sizeof ( *error ) ) {
+ DBGC ( tftp, "TFTP %p received underlength ERROR packet "
+ "length %zd\n", tftp, len );
+ return -EINVAL;
+ }
+
+ DBGC ( tftp, "TFTP %p received ERROR packet with code %d, message "
+ "\"%s\"\n", tftp, ntohs ( error->errcode ), error->errmsg );
+
+ /* Determine final operation result */
+ rc = tftp_errcode_to_rc ( ntohs ( error->errcode ) );
+
+ /* Close TFTP request */
+ tftp_done ( tftp, rc );
+
+ return 0;
+}
+
+/**
+ * Receive new data
+ *
+ * @v tftp TFTP connection
+ * @v iobuf I/O buffer
+ * @v meta Transfer metadata
+ * @ret rc Return status code
+ */
+static int tftp_rx ( struct tftp_request *tftp,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct sockaddr_tcpip *st_src;
+ struct tftp_common *common = iobuf->data;
+ size_t len = iob_len ( iobuf );
+ int rc = -EINVAL;
+
+ /* Sanity checks */
+ if ( len < sizeof ( *common ) ) {
+ DBGC ( tftp, "TFTP %p received underlength packet length "
+ "%zd\n", tftp, len );
+ goto done;
+ }
+ if ( ! meta->src ) {
+ DBGC ( tftp, "TFTP %p received packet without source port\n",
+ tftp );
+ goto done;
+ }
+
+ /* Filter by TID. Set TID on first response received */
+ st_src = ( struct sockaddr_tcpip * ) meta->src;
+ if ( ! tftp->peer.st_family ) {
+ memcpy ( &tftp->peer, st_src, sizeof ( tftp->peer ) );
+ DBGC ( tftp, "TFTP %p using remote port %d\n", tftp,
+ ntohs ( tftp->peer.st_port ) );
+ } else if ( memcmp ( &tftp->peer, st_src,
+ sizeof ( tftp->peer ) ) != 0 ) {
+ DBGC ( tftp, "TFTP %p received packet from wrong source (got "
+ "%d, wanted %d)\n", tftp, ntohs ( st_src->st_port ),
+ ntohs ( tftp->peer.st_port ) );
+ goto done;
+ }
+
+ switch ( common->opcode ) {
+ case htons ( TFTP_OACK ):
+ rc = tftp_rx_oack ( tftp, iobuf->data, len );
+ break;
+ case htons ( TFTP_DATA ):
+ rc = tftp_rx_data ( tftp, iob_disown ( iobuf ) );
+ break;
+ case htons ( TFTP_ERROR ):
+ rc = tftp_rx_error ( tftp, iobuf->data, len );
+ break;
+ default:
+ DBGC ( tftp, "TFTP %p received strange packet type %d\n",
+ tftp, ntohs ( common->opcode ) );
+ break;
+ };
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Receive new data via socket
+ *
+ * @v tftp TFTP connection
+ * @v iobuf I/O buffer
+ * @v meta Transfer metadata
+ * @ret rc Return status code
+ */
+static int tftp_socket_deliver ( struct tftp_request *tftp,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+
+ /* Enable sending ACKs when we receive a unicast packet. This
+ * covers three cases:
+ *
+ * 1. Standard TFTP; we should always send ACKs, and will
+ * always receive a unicast packet before we need to send the
+ * first ACK.
+ *
+ * 2. RFC2090 multicast TFTP; the only unicast packets we will
+ * receive are the OACKs; enable sending ACKs here (before
+ * processing the OACK) and disable it when processing the
+ * multicast option if we are not the master client.
+ *
+ * 3. MTFTP; receiving a unicast datagram indicates that we
+ * are the "master client" and should send ACKs.
+ */
+ tftp->flags |= TFTP_FL_SEND_ACK;
+
+ return tftp_rx ( tftp, iobuf, meta );
+}
+
+/** TFTP socket operations */
+static struct interface_operation tftp_socket_operations[] = {
+ INTF_OP ( xfer_deliver, struct tftp_request *, tftp_socket_deliver ),
+};
+
+/** TFTP socket interface descriptor */
+static struct interface_descriptor tftp_socket_desc =
+ INTF_DESC ( struct tftp_request, socket, tftp_socket_operations );
+
+/** TFTP multicast socket operations */
+static struct interface_operation tftp_mc_socket_operations[] = {
+ INTF_OP ( xfer_deliver, struct tftp_request *, tftp_rx ),
+};
+
+/** TFTP multicast socket interface descriptor */
+static struct interface_descriptor tftp_mc_socket_desc =
+ INTF_DESC ( struct tftp_request, mc_socket, tftp_mc_socket_operations );
+
+/**
+ * Check flow control window
+ *
+ * @v tftp TFTP connection
+ * @ret len Length of window
+ */
+static size_t tftp_xfer_window ( struct tftp_request *tftp ) {
+
+ /* We abuse this data-xfer method to convey the blocksize to
+ * the caller. This really should be done using some kind of
+ * stat() method, but we don't yet have the facility to do
+ * that.
+ */
+ return tftp->blksize;
+}
+
+/** TFTP data transfer interface operations */
+static struct interface_operation tftp_xfer_operations[] = {
+ INTF_OP ( xfer_window, struct tftp_request *, tftp_xfer_window ),
+ INTF_OP ( intf_close, struct tftp_request *, tftp_done ),
+};
+
+/** TFTP data transfer interface descriptor */
+static struct interface_descriptor tftp_xfer_desc =
+ INTF_DESC ( struct tftp_request, xfer, tftp_xfer_operations );
+
+/**
+ * Initiate TFTP/TFTM/MTFTP download
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int tftp_core_open ( struct interface *xfer, struct uri *uri,
+ unsigned int default_port,
+ struct sockaddr *multicast,
+ unsigned int flags ) {
+ struct tftp_request *tftp;
+ int rc;
+
+ /* Sanity checks */
+ if ( ! uri->host )
+ return -EINVAL;
+ if ( ! uri->path )
+ return -EINVAL;
+
+ /* Allocate and populate TFTP structure */
+ tftp = zalloc ( sizeof ( *tftp ) );
+ if ( ! tftp )
+ return -ENOMEM;
+ ref_init ( &tftp->refcnt, tftp_free );
+ intf_init ( &tftp->xfer, &tftp_xfer_desc, &tftp->refcnt );
+ intf_init ( &tftp->socket, &tftp_socket_desc, &tftp->refcnt );
+ intf_init ( &tftp->mc_socket, &tftp_mc_socket_desc, &tftp->refcnt );
+ timer_init ( &tftp->timer, tftp_timer_expired, &tftp->refcnt );
+ tftp->uri = uri_get ( uri );
+ tftp->blksize = TFTP_DEFAULT_BLKSIZE;
+ tftp->flags = flags;
+
+ /* Open socket */
+ tftp->port = uri_port ( tftp->uri, default_port );
+ if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
+ goto err;
+
+ /* Open multicast socket */
+ if ( multicast ) {
+ if ( ( rc = tftp_reopen_mc ( tftp, multicast ) ) != 0 )
+ goto err;
+ }
+
+ /* Start timer to initiate RRQ */
+ start_timer_nodelay ( &tftp->timer );
+
+ /* Attach to parent interface, mortalise self, and return */
+ intf_plug_plug ( &tftp->xfer, xfer );
+ ref_put ( &tftp->refcnt );
+ return 0;
+
+ err:
+ DBGC ( tftp, "TFTP %p could not create request: %s\n",
+ tftp, strerror ( rc ) );
+ tftp_done ( tftp, rc );
+ ref_put ( &tftp->refcnt );
+ return rc;
+}
+
+/**
+ * Initiate TFTP download
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int tftp_open ( struct interface *xfer, struct uri *uri ) {
+ return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
+ TFTP_FL_RRQ_SIZES );
+
+}
+
+/** TFTP URI opener */
+struct uri_opener tftp_uri_opener __uri_opener = {
+ .scheme = "tftp",
+ .open = tftp_open,
+};
+
+/**
+ * Initiate TFTP-size request
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int tftpsize_open ( struct interface *xfer, struct uri *uri ) {
+ return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
+ ( TFTP_FL_RRQ_SIZES |
+ TFTP_FL_SIZEONLY ) );
+
+}
+
+/** TFTP URI opener */
+struct uri_opener tftpsize_uri_opener __uri_opener = {
+ .scheme = "tftpsize",
+ .open = tftpsize_open,
+};
+
+/**
+ * Initiate TFTM download
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int tftm_open ( struct interface *xfer, struct uri *uri ) {
+ return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
+ ( TFTP_FL_RRQ_SIZES |
+ TFTP_FL_RRQ_MULTICAST ) );
+
+}
+
+/** TFTM URI opener */
+struct uri_opener tftm_uri_opener __uri_opener = {
+ .scheme = "tftm",
+ .open = tftm_open,
+};
+
+/**
+ * Initiate MTFTP download
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int mtftp_open ( struct interface *xfer, struct uri *uri ) {
+ return tftp_core_open ( xfer, uri, MTFTP_PORT,
+ ( struct sockaddr * ) &tftp_mtftp_socket,
+ TFTP_FL_MTFTP_RECOVERY );
+}
+
+/** MTFTP URI opener */
+struct uri_opener mtftp_uri_opener __uri_opener = {
+ .scheme = "mtftp",
+ .open = mtftp_open,
+};
+
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Apply TFTP configuration settings
+ *
+ * @ret rc Return status code
+ */
+static int tftp_apply_settings ( void ) {
+ static struct in_addr tftp_server = { 0 };
+ struct in_addr last_tftp_server;
+ char uri_string[32];
+ struct uri *uri;
+
+ /* Retrieve TFTP server setting */
+ last_tftp_server = tftp_server;
+ fetch_ipv4_setting ( NULL, &next_server_setting, &tftp_server );
+
+ /* If TFTP server setting has changed, set the current working
+ * URI to match. Do it only when the TFTP server has changed
+ * to try to minimise surprises to the user, who probably
+ * won't expect the CWURI to change just because they updated
+ * an unrelated setting and triggered all the settings
+ * applicators.
+ */
+ if ( tftp_server.s_addr != last_tftp_server.s_addr ) {
+ if ( tftp_server.s_addr ) {
+ snprintf ( uri_string, sizeof ( uri_string ),
+ "tftp://%s/", inet_ntoa ( tftp_server ) );
+ uri = parse_uri ( uri_string );
+ if ( ! uri )
+ return -ENOMEM;
+ } else {
+ uri = NULL;
+ }
+ churi ( uri );
+ uri_put ( uri );
+ }
+
+ return 0;
+}
+
+/** TFTP settings applicator */
+struct settings_applicator tftp_settings_applicator __settings_applicator = {
+ .apply = tftp_apply_settings,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/net/validator.c b/src/VBox/Devices/PC/ipxe/src/net/validator.c
new file mode 100644
index 00000000..e1abd2e3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/validator.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/malloc.h>
+#include <ipxe/interface.h>
+#include <ipxe/xfer.h>
+#include <ipxe/open.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/xferbuf.h>
+#include <ipxe/process.h>
+#include <ipxe/x509.h>
+#include <ipxe/settings.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/base64.h>
+#include <ipxe/crc32.h>
+#include <ipxe/validator.h>
+
+/** @file
+ *
+ * Certificate validator
+ *
+ */
+
+/** A certificate validator */
+struct validator {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Job control interface */
+ struct interface job;
+ /** Data transfer interface */
+ struct interface xfer;
+ /** Process */
+ struct process process;
+ /** X.509 certificate chain */
+ struct x509_chain *chain;
+ /** Data buffer */
+ struct xfer_buffer buffer;
+};
+
+/**
+ * Free certificate validator
+ *
+ * @v refcnt Reference count
+ */
+static void validator_free ( struct refcnt *refcnt ) {
+ struct validator *validator =
+ container_of ( refcnt, struct validator, refcnt );
+
+ DBGC2 ( validator, "VALIDATOR %p freed\n", validator );
+ x509_chain_put ( validator->chain );
+ xferbuf_done ( &validator->buffer );
+ free ( validator );
+}
+
+/**
+ * Mark certificate validation as finished
+ *
+ * @v validator Certificate validator
+ * @v rc Reason for finishing
+ */
+static void validator_finished ( struct validator *validator, int rc ) {
+
+ /* Remove process */
+ process_del ( &validator->process );
+
+ /* Close all interfaces */
+ intf_shutdown ( &validator->xfer, rc );
+ intf_shutdown ( &validator->job, rc );
+}
+
+/****************************************************************************
+ *
+ * Job control interface
+ *
+ */
+
+/** Certificate validator job control interface operations */
+static struct interface_operation validator_job_operations[] = {
+ INTF_OP ( intf_close, struct validator *, validator_finished ),
+};
+
+/** Certificate validator job control interface descriptor */
+static struct interface_descriptor validator_job_desc =
+ INTF_DESC ( struct validator, job, validator_job_operations );
+
+/****************************************************************************
+ *
+ * Cross-signing certificates
+ *
+ */
+
+/** Cross-signed certificate source setting */
+struct setting crosscert_setting __setting ( SETTING_CRYPTO ) = {
+ .name = "crosscert",
+ .description = "Cross-signed certificate source",
+ .tag = DHCP_EB_CROSS_CERT,
+ .type = &setting_type_string,
+};
+
+/** Default cross-signed certificate source */
+static const char crosscert_default[] = "http://ca.ipxe.org/auto";
+
+/**
+ * Start download of cross-signing certificate
+ *
+ * @v validator Certificate validator
+ * @v issuer Required issuer
+ * @ret rc Return status code
+ */
+static int validator_start_download ( struct validator *validator,
+ const struct asn1_cursor *issuer ) {
+ const char *crosscert;
+ char *crosscert_copy;
+ char *uri_string;
+ size_t uri_string_len;
+ uint32_t crc;
+ int len;
+ int rc;
+
+ /* Determine cross-signed certificate source */
+ len = fetch_string_setting_copy ( NULL, &crosscert_setting,
+ &crosscert_copy );
+ if ( len < 0 ) {
+ rc = len;
+ DBGC ( validator, "VALIDATOR %p could not fetch crosscert "
+ "setting: %s\n", validator, strerror ( rc ) );
+ goto err_fetch_crosscert;
+ }
+ crosscert = ( crosscert_copy ? crosscert_copy : crosscert_default );
+
+ /* Allocate URI string */
+ uri_string_len = ( strlen ( crosscert ) + 22 /* "/%08x.der?subject=" */
+ + base64_encoded_len ( issuer->len ) + 1 /* NUL */ );
+ uri_string = zalloc ( uri_string_len );
+ if ( ! uri_string ) {
+ rc = -ENOMEM;
+ goto err_alloc_uri_string;
+ }
+
+ /* Generate CRC32 */
+ crc = crc32_le ( 0xffffffffUL, issuer->data, issuer->len );
+
+ /* Generate URI string */
+ len = snprintf ( uri_string, uri_string_len, "%s/%08x.der?subject=",
+ crosscert, crc );
+ base64_encode ( issuer->data, issuer->len, ( uri_string + len ) );
+ DBGC ( validator, "VALIDATOR %p downloading cross-signed certificate "
+ "from %s\n", validator, uri_string );
+
+ /* Open URI */
+ if ( ( rc = xfer_open_uri_string ( &validator->xfer,
+ uri_string ) ) != 0 ) {
+ DBGC ( validator, "VALIDATOR %p could not open %s: %s\n",
+ validator, uri_string, strerror ( rc ) );
+ goto err_open_uri_string;
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_open_uri_string:
+ free ( uri_string );
+ err_alloc_uri_string:
+ free ( crosscert_copy );
+ err_fetch_crosscert:
+ return rc;
+}
+
+/**
+ * Append cross-signing certificates to certificate chain
+ *
+ * @v validator Certificate validator
+ * @v data Raw cross-signing certificate data
+ * @v len Length of raw data
+ * @ret rc Return status code
+ */
+static int validator_append ( struct validator *validator,
+ const void *data, size_t len ) {
+ struct asn1_cursor cursor;
+ struct x509_chain *certs;
+ struct x509_certificate *cert;
+ struct x509_certificate *last;
+ int rc;
+
+ /* Allocate certificate list */
+ certs = x509_alloc_chain();
+ if ( ! certs ) {
+ rc = -ENOMEM;
+ goto err_alloc_certs;
+ }
+
+ /* Initialise cursor */
+ cursor.data = data;
+ cursor.len = len;
+
+ /* Enter certificateSet */
+ if ( ( rc = asn1_enter ( &cursor, ASN1_SET ) ) != 0 ) {
+ DBGC ( validator, "VALIDATOR %p could not enter "
+ "certificateSet: %s\n", validator, strerror ( rc ) );
+ goto err_certificateset;
+ }
+
+ /* Add each certificate to list */
+ while ( cursor.len ) {
+
+ /* Add certificate to chain */
+ if ( ( rc = x509_append_raw ( certs, cursor.data,
+ cursor.len ) ) != 0 ) {
+ DBGC ( validator, "VALIDATOR %p could not append "
+ "certificate: %s\n",
+ validator, strerror ( rc) );
+ DBGC_HDA ( validator, 0, cursor.data, cursor.len );
+ return rc;
+ }
+ cert = x509_last ( certs );
+ DBGC ( validator, "VALIDATOR %p found certificate %s\n",
+ validator, cert->subject.name );
+
+ /* Move to next certificate */
+ asn1_skip_any ( &cursor );
+ }
+
+ /* Append certificates to chain */
+ last = x509_last ( validator->chain );
+ if ( ( rc = x509_auto_append ( validator->chain, certs ) ) != 0 ) {
+ DBGC ( validator, "VALIDATOR %p could not append "
+ "certificates: %s\n", validator, strerror ( rc ) );
+ goto err_auto_append;
+ }
+
+ /* Check that at least one certificate has been added */
+ if ( last == x509_last ( validator->chain ) ) {
+ DBGC ( validator, "VALIDATOR %p failed to append any "
+ "applicable certificates\n", validator );
+ rc = -EACCES;
+ goto err_no_progress;
+ }
+
+ /* Drop reference to certificate list */
+ x509_chain_put ( certs );
+
+ return 0;
+
+ err_no_progress:
+ err_auto_append:
+ err_certificateset:
+ x509_chain_put ( certs );
+ err_alloc_certs:
+ return rc;
+}
+
+/****************************************************************************
+ *
+ * Data transfer interface
+ *
+ */
+
+/**
+ * Close data transfer interface
+ *
+ * @v validator Certificate validator
+ * @v rc Reason for close
+ */
+static void validator_xfer_close ( struct validator *validator, int rc ) {
+
+ /* Close data transfer interface */
+ intf_restart ( &validator->xfer, rc );
+
+ /* Check for errors */
+ if ( rc != 0 ) {
+ DBGC ( validator, "VALIDATOR %p download failed: %s\n",
+ validator, strerror ( rc ) );
+ goto err_download;
+ }
+ DBGC2 ( validator, "VALIDATOR %p download complete\n", validator );
+
+ /* Append downloaded certificates */
+ if ( ( rc = validator_append ( validator, validator->buffer.data,
+ validator->buffer.len ) ) != 0 )
+ goto err_append;
+
+ /* Free downloaded data */
+ xferbuf_done ( &validator->buffer );
+
+ /* Resume validation process */
+ process_add ( &validator->process );
+
+ return;
+
+ err_append:
+ err_download:
+ validator_finished ( validator, rc );
+}
+
+/**
+ * Receive data
+ *
+ * @v validator Certificate validator
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int validator_xfer_deliver ( struct validator *validator,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ int rc;
+
+ /* Add data to buffer */
+ if ( ( rc = xferbuf_deliver ( &validator->buffer, iob_disown ( iobuf ),
+ meta ) ) != 0 ) {
+ DBGC ( validator, "VALIDATOR %p could not receive data: %s\n",
+ validator, strerror ( rc ) );
+ validator_finished ( validator, rc );
+ return rc;
+ }
+
+ return 0;
+}
+
+/** Certificate validator data transfer interface operations */
+static struct interface_operation validator_xfer_operations[] = {
+ INTF_OP ( xfer_deliver, struct validator *, validator_xfer_deliver ),
+ INTF_OP ( intf_close, struct validator *, validator_xfer_close ),
+};
+
+/** Certificate validator data transfer interface descriptor */
+static struct interface_descriptor validator_xfer_desc =
+ INTF_DESC ( struct validator, xfer, validator_xfer_operations );
+
+/****************************************************************************
+ *
+ * Validation process
+ *
+ */
+
+/**
+ * Certificate validation process
+ *
+ * @v validator Certificate validator
+ */
+static void validator_step ( struct validator *validator ) {
+ struct x509_certificate *last = x509_last ( validator->chain );
+ time_t now;
+ int rc;
+
+ /* Try validating chain. Try even if the chain is incomplete,
+ * since certificates may already have been validated
+ * previously.
+ */
+ now = time ( NULL );
+ if ( ( rc = x509_validate_chain ( validator->chain, now,
+ NULL ) ) == 0 ) {
+ validator_finished ( validator, 0 );
+ return;
+ }
+
+ /* If chain ends with a self-issued certificate, then there is
+ * nothing more to do.
+ */
+ if ( asn1_compare ( &last->issuer.raw, &last->subject.raw ) == 0 ) {
+ validator_finished ( validator, rc );
+ return;
+ }
+
+ /* Otherwise, try to download a suitable cross-signing
+ * certificate.
+ */
+ if ( ( rc = validator_start_download ( validator,
+ &last->issuer.raw ) ) != 0 ) {
+ validator_finished ( validator, rc );
+ return;
+ }
+}
+
+/** Certificate validator process descriptor */
+static struct process_descriptor validator_process_desc =
+ PROC_DESC_ONCE ( struct validator, process, validator_step );
+
+/****************************************************************************
+ *
+ * Instantiator
+ *
+ */
+
+/**
+ * Instantiate a certificate validator
+ *
+ * @v job Job control interface
+ * @v chain X.509 certificate chain
+ * @ret rc Return status code
+ */
+int create_validator ( struct interface *job, struct x509_chain *chain ) {
+ struct validator *validator;
+ int rc;
+
+ /* Sanity check */
+ if ( ! chain ) {
+ rc = -EINVAL;
+ goto err_sanity;
+ }
+
+ /* Allocate and initialise structure */
+ validator = zalloc ( sizeof ( *validator ) );
+ if ( ! validator ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ ref_init ( &validator->refcnt, validator_free );
+ intf_init ( &validator->job, &validator_job_desc,
+ &validator->refcnt );
+ intf_init ( &validator->xfer, &validator_xfer_desc,
+ &validator->refcnt );
+ process_init ( &validator->process, &validator_process_desc,
+ &validator->refcnt );
+ validator->chain = x509_chain_get ( chain );
+
+ /* Attach parent interface, mortalise self, and return */
+ intf_plug_plug ( &validator->job, job );
+ ref_put ( &validator->refcnt );
+ DBGC2 ( validator, "VALIDATOR %p validating X509 chain %p\n",
+ validator, validator->chain );
+ return 0;
+
+ validator_finished ( validator, rc );
+ ref_put ( &validator->refcnt );
+ err_alloc:
+ err_sanity:
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/net/vlan.c b/src/VBox/Devices/PC/ipxe/src/net/vlan.c
new file mode 100644
index 00000000..2147f91c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/net/vlan.c
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/features.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/vlan.h>
+
+/** @file
+ *
+ * Virtual LANs
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "VLAN", DHCP_EB_FEATURE_VLAN, 1 );
+
+struct net_protocol vlan_protocol __net_protocol;
+
+/** VLAN device private data */
+struct vlan_device {
+ /** Trunk network device */
+ struct net_device *trunk;
+ /** VLAN tag */
+ unsigned int tag;
+ /** Default priority */
+ unsigned int priority;
+};
+
+/**
+ * Open VLAN device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int vlan_open ( struct net_device *netdev ) {
+ struct vlan_device *vlan = netdev->priv;
+
+ return netdev_open ( vlan->trunk );
+}
+
+/**
+ * Close VLAN device
+ *
+ * @v netdev Network device
+ */
+static void vlan_close ( struct net_device *netdev ) {
+ struct vlan_device *vlan = netdev->priv;
+
+ netdev_close ( vlan->trunk );
+}
+
+/**
+ * Transmit packet on VLAN device
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int vlan_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct vlan_device *vlan = netdev->priv;
+ struct net_device *trunk = vlan->trunk;
+ struct ll_protocol *ll_protocol;
+ struct vlan_header *vlanhdr;
+ uint8_t ll_dest_copy[ETH_ALEN];
+ uint8_t ll_source_copy[ETH_ALEN];
+ const void *ll_dest;
+ const void *ll_source;
+ uint16_t net_proto;
+ unsigned int flags;
+ int rc;
+
+ /* Strip link-layer header and preserve link-layer header fields */
+ ll_protocol = netdev->ll_protocol;
+ if ( ( rc = ll_protocol->pull ( netdev, iobuf, &ll_dest, &ll_source,
+ &net_proto, &flags ) ) != 0 ) {
+ DBGC ( netdev, "VLAN %s could not parse link-layer header: "
+ "%s\n", netdev->name, strerror ( rc ) );
+ return rc;
+ }
+ memcpy ( ll_dest_copy, ll_dest, ETH_ALEN );
+ memcpy ( ll_source_copy, ll_source, ETH_ALEN );
+
+ /* Construct VLAN header */
+ vlanhdr = iob_push ( iobuf, sizeof ( *vlanhdr ) );
+ vlanhdr->tci = htons ( VLAN_TCI ( vlan->tag, vlan->priority ) );
+ vlanhdr->net_proto = net_proto;
+
+ /* Reclaim I/O buffer from VLAN device's TX queue */
+ list_del ( &iobuf->list );
+
+ /* Transmit packet on trunk device */
+ if ( ( rc = net_tx ( iob_disown ( iobuf ), trunk, &vlan_protocol,
+ ll_dest_copy, ll_source_copy ) ) != 0 ) {
+ DBGC ( netdev, "VLAN %s could not transmit: %s\n",
+ netdev->name, strerror ( rc ) );
+ /* Cannot return an error status, since that would
+ * cause the I/O buffer to be double-freed.
+ */
+ return 0;
+ }
+
+ return 0;
+}
+
+/**
+ * Poll VLAN device
+ *
+ * @v netdev Network device
+ */
+static void vlan_poll ( struct net_device *netdev ) {
+ struct vlan_device *vlan = netdev->priv;
+
+ /* Poll trunk device */
+ netdev_poll ( vlan->trunk );
+}
+
+/**
+ * Enable/disable interrupts on VLAN device
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void vlan_irq ( struct net_device *netdev, int enable ) {
+ struct vlan_device *vlan = netdev->priv;
+
+ /* Enable/disable interrupts on trunk device. This is not at
+ * all robust, but there is no sensible course of action
+ * available.
+ */
+ netdev_irq ( vlan->trunk, enable );
+}
+
+/** VLAN device operations */
+static struct net_device_operations vlan_operations = {
+ .open = vlan_open,
+ .close = vlan_close,
+ .transmit = vlan_transmit,
+ .poll = vlan_poll,
+ .irq = vlan_irq,
+};
+
+/**
+ * Synchronise VLAN device
+ *
+ * @v netdev Network device
+ */
+static void vlan_sync ( struct net_device *netdev ) {
+ struct vlan_device *vlan = netdev->priv;
+ struct net_device *trunk = vlan->trunk;
+
+ /* Synchronise link status */
+ if ( netdev->link_rc != trunk->link_rc )
+ netdev_link_err ( netdev, trunk->link_rc );
+
+ /* Synchronise open/closed status */
+ if ( netdev_is_open ( trunk ) ) {
+ if ( ! netdev_is_open ( netdev ) )
+ netdev_open ( netdev );
+ } else {
+ if ( netdev_is_open ( netdev ) )
+ netdev_close ( netdev );
+ }
+}
+
+/**
+ * Identify VLAN device
+ *
+ * @v trunk Trunk network device
+ * @v tag VLAN tag
+ * @ret netdev VLAN device, if any
+ */
+struct net_device * vlan_find ( struct net_device *trunk, unsigned int tag ) {
+ struct net_device *netdev;
+ struct vlan_device *vlan;
+
+ for_each_netdev ( netdev ) {
+ if ( netdev->op != &vlan_operations )
+ continue;
+ vlan = netdev->priv;
+ if ( ( vlan->trunk == trunk ) && ( vlan->tag == tag ) )
+ return netdev;
+ }
+ return NULL;
+}
+
+/**
+ * Process incoming VLAN packet
+ *
+ * @v iobuf I/O buffer
+ * @v trunk Trunk network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer source address
+ * @v flags Packet flags
+ * @ret rc Return status code
+ */
+static int vlan_rx ( struct io_buffer *iobuf, struct net_device *trunk,
+ const void *ll_dest, const void *ll_source,
+ unsigned int flags __unused ) {
+ struct vlan_header *vlanhdr = iobuf->data;
+ struct net_device *netdev;
+ struct ll_protocol *ll_protocol;
+ uint8_t ll_dest_copy[ETH_ALEN];
+ uint8_t ll_source_copy[ETH_ALEN];
+ uint16_t tag;
+ int rc;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *vlanhdr ) ) {
+ DBGC ( trunk, "VLAN %s received underlength packet (%zd "
+ "bytes)\n", trunk->name, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto err_sanity;
+ }
+
+ /* Identify VLAN device */
+ tag = VLAN_TAG ( ntohs ( vlanhdr->tci ) );
+ netdev = vlan_find ( trunk, tag );
+ if ( ! netdev ) {
+ DBGC2 ( trunk, "VLAN %s received packet for unknown VLAN "
+ "%d\n", trunk->name, tag );
+ rc = -EPIPE;
+ goto err_no_vlan;
+ }
+
+ /* Strip VLAN header and preserve original link-layer header fields */
+ iob_pull ( iobuf, sizeof ( *vlanhdr ) );
+ ll_protocol = trunk->ll_protocol;
+ memcpy ( ll_dest_copy, ll_dest, ETH_ALEN );
+ memcpy ( ll_source_copy, ll_source, ETH_ALEN );
+
+ /* Reconstruct link-layer header for VLAN device */
+ ll_protocol = netdev->ll_protocol;
+ if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest_copy,
+ ll_source_copy,
+ vlanhdr->net_proto ) ) != 0 ) {
+ DBGC ( netdev, "VLAN %s could not reconstruct link-layer "
+ "header: %s\n", netdev->name, strerror ( rc ) );
+ goto err_ll_push;
+ }
+
+ /* Enqueue packet on VLAN device */
+ netdev_rx ( netdev, iob_disown ( iobuf ) );
+ return 0;
+
+ err_ll_push:
+ err_no_vlan:
+ err_sanity:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** VLAN protocol */
+struct net_protocol vlan_protocol __net_protocol = {
+ .name = "VLAN",
+ .net_proto = htons ( ETH_P_8021Q ),
+ .rx = vlan_rx,
+};
+
+/**
+ * Check if network device can be used as a VLAN trunk device
+ *
+ * @v trunk Trunk network device
+ * @ret is_ok Trunk network device is usable
+ *
+ * VLAN devices will be created as Ethernet devices. (We cannot
+ * simply clone the link layer of the trunk network device, because
+ * this link layer may expect the network device structure to contain
+ * some link-layer-private data.) The trunk network device must
+ * therefore have a link layer that is in some sense 'compatible' with
+ * Ethernet; specifically, it must have link-layer addresses that are
+ * the same length as Ethernet link-layer addresses.
+ *
+ * As an additional check, and primarily to assist with the sanity of
+ * the FCoE code, we refuse to allow nested VLANs.
+ */
+int vlan_can_be_trunk ( struct net_device *trunk ) {
+
+ return ( ( trunk->ll_protocol->ll_addr_len == ETH_ALEN ) &&
+ ( trunk->op != &vlan_operations ) );
+}
+
+/**
+ * Create VLAN device
+ *
+ * @v trunk Trunk network device
+ * @v tag VLAN tag
+ * @v priority Default VLAN priority
+ * @ret rc Return status code
+ */
+int vlan_create ( struct net_device *trunk, unsigned int tag,
+ unsigned int priority ) {
+ struct net_device *netdev;
+ struct vlan_device *vlan;
+ int rc;
+
+ /* If VLAN already exists, just update the priority */
+ if ( ( netdev = vlan_find ( trunk, tag ) ) != NULL ) {
+ vlan = netdev->priv;
+ if ( priority != vlan->priority ) {
+ DBGC ( netdev, "VLAN %s priority changed from %d to "
+ "%d\n", netdev->name, vlan->priority, priority );
+ }
+ vlan->priority = priority;
+ return 0;
+ }
+
+ /* Sanity checks */
+ if ( ! vlan_can_be_trunk ( trunk ) ) {
+ DBGC ( trunk, "VLAN %s cannot create VLAN on non-trunk "
+ "device\n", trunk->name );
+ rc = -ENOTTY;
+ goto err_sanity;
+ }
+ if ( ! VLAN_TAG_IS_VALID ( tag ) ) {
+ DBGC ( trunk, "VLAN %s cannot create VLAN with invalid tag "
+ "%d\n", trunk->name, tag );
+ rc = -EINVAL;
+ goto err_sanity;
+ }
+ if ( ! VLAN_PRIORITY_IS_VALID ( priority ) ) {
+ DBGC ( trunk, "VLAN %s cannot create VLAN with invalid "
+ "priority %d\n", trunk->name, priority );
+ rc = -EINVAL;
+ goto err_sanity;
+ }
+
+ /* Allocate and initialise structure */
+ netdev = alloc_etherdev ( sizeof ( *vlan ) );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ goto err_alloc_etherdev;
+ }
+ netdev_init ( netdev, &vlan_operations );
+ netdev->dev = trunk->dev;
+ memcpy ( netdev->hw_addr, trunk->ll_addr, ETH_ALEN );
+ vlan = netdev->priv;
+ vlan->trunk = netdev_get ( trunk );
+ vlan->tag = tag;
+ vlan->priority = priority;
+
+ /* Construct VLAN device name */
+ snprintf ( netdev->name, sizeof ( netdev->name ), "%s-%d",
+ trunk->name, vlan->tag );
+
+ /* Register VLAN device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
+ DBGC ( netdev, "VLAN %s could not register: %s\n",
+ netdev->name, strerror ( rc ) );
+ goto err_register;
+ }
+
+ /* Synchronise with trunk device */
+ vlan_sync ( netdev );
+
+ DBGC ( netdev, "VLAN %s created with tag %d and priority %d\n",
+ netdev->name, vlan->tag, vlan->priority );
+
+ return 0;
+
+ unregister_netdev ( netdev );
+ err_register:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ netdev_put ( trunk );
+ err_alloc_etherdev:
+ err_sanity:
+ return rc;
+}
+
+/**
+ * Destroy VLAN device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+int vlan_destroy ( struct net_device *netdev ) {
+ struct vlan_device *vlan = netdev->priv;
+ struct net_device *trunk;
+
+ /* Sanity check */
+ if ( netdev->op != &vlan_operations ) {
+ DBGC ( netdev, "VLAN %s cannot destroy non-VLAN device\n",
+ netdev->name );
+ return -ENOTTY;
+ }
+
+ DBGC ( netdev, "VLAN %s destroyed\n", netdev->name );
+
+ /* Remove VLAN device */
+ unregister_netdev ( netdev );
+ trunk = vlan->trunk;
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ netdev_put ( trunk );
+
+ return 0;
+}
+
+/**
+ * Do nothing
+ *
+ * @v trunk Trunk network device
+ * @ret rc Return status code
+ */
+static int vlan_probe ( struct net_device *trunk __unused ) {
+ return 0;
+}
+
+/**
+ * Handle trunk network device link state change
+ *
+ * @v trunk Trunk network device
+ */
+static void vlan_notify ( struct net_device *trunk ) {
+ struct net_device *netdev;
+ struct vlan_device *vlan;
+
+ for_each_netdev ( netdev ) {
+ if ( netdev->op != &vlan_operations )
+ continue;
+ vlan = netdev->priv;
+ if ( vlan->trunk == trunk )
+ vlan_sync ( netdev );
+ }
+}
+
+/**
+ * Destroy first VLAN device for a given trunk
+ *
+ * @v trunk Trunk network device
+ * @ret found A VLAN device was found
+ */
+static int vlan_remove_first ( struct net_device *trunk ) {
+ struct net_device *netdev;
+ struct vlan_device *vlan;
+
+ for_each_netdev ( netdev ) {
+ if ( netdev->op != &vlan_operations )
+ continue;
+ vlan = netdev->priv;
+ if ( vlan->trunk == trunk ) {
+ vlan_destroy ( netdev );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Destroy all VLAN devices for a given trunk
+ *
+ * @v trunk Trunk network device
+ */
+static void vlan_remove ( struct net_device *trunk ) {
+
+ /* Remove all VLAN devices attached to this trunk, safe
+ * against arbitrary net device removal.
+ */
+ while ( vlan_remove_first ( trunk ) ) {}
+}
+
+/** VLAN driver */
+struct net_driver vlan_driver __net_driver = {
+ .name = "VLAN",
+ .probe = vlan_probe,
+ .notify = vlan_notify,
+ .remove = vlan_remove,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/aes_cbc_test.c b/src/VBox/Devices/PC/ipxe/src/tests/aes_cbc_test.c
new file mode 100644
index 00000000..371ec81b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/aes_cbc_test.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * AES-in-CBC-mode tests
+ *
+ * These test vectors are provided by NIST as part of the
+ * Cryptographic Toolkit Examples, downloadable from:
+ *
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CBC.pdf
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <assert.h>
+#include <string.h>
+#include <ipxe/aes.h>
+#include <ipxe/test.h>
+#include "cbc_test.h"
+
+/** Define inline key */
+#define KEY(...) { __VA_ARGS__ }
+
+/** Define inline initialisation vector */
+#define IV(...) { __VA_ARGS__ }
+
+/** Define inline plaintext data */
+#define PLAINTEXT(...) { __VA_ARGS__ }
+
+/** Define inline ciphertext data */
+#define CIPHERTEXT(...) { __VA_ARGS__ }
+
+/** An AES-in-CBC-mode test */
+struct aes_cbc_test {
+ /** Key */
+ const void *key;
+ /** Length of key */
+ size_t key_len;
+ /** Initialisation vector */
+ const void *iv;
+ /** Length of initialisation vector */
+ size_t iv_len;
+ /** Plaintext */
+ const void *plaintext;
+ /** Length of plaintext */
+ size_t plaintext_len;
+ /** Ciphertext */
+ const void *ciphertext;
+ /** Length of ciphertext */
+ size_t ciphertext_len;
+};
+
+/**
+ * Define an AES-in-CBC-mode test
+ *
+ * @v name Test name
+ * @v key_array Key
+ * @v iv_array Initialisation vector
+ * @v plaintext_array Plaintext
+ * @v ciphertext_array Ciphertext
+ * @ret test AES-in-CBC-mode test
+ */
+#define AES_CBC_TEST( name, key_array, iv_array, plaintext_array, \
+ ciphertext_array ) \
+ static const uint8_t name ## _key [] = key_array; \
+ static const uint8_t name ## _iv [] = iv_array; \
+ static const uint8_t name ## _plaintext [] = plaintext_array; \
+ static const uint8_t name ## _ciphertext [] = ciphertext_array; \
+ static struct aes_cbc_test name = { \
+ .key = name ## _key, \
+ .key_len = sizeof ( name ## _key ), \
+ .iv = name ## _iv, \
+ .iv_len = sizeof ( name ## _iv ), \
+ .plaintext = name ## _plaintext, \
+ .plaintext_len = sizeof ( name ## _plaintext ), \
+ .ciphertext = name ## _ciphertext, \
+ .ciphertext_len = sizeof ( name ## _ciphertext ), \
+ }
+
+/**
+ * Report AES-in-CBC-mode
+ *
+ * @v state HMAC_DRBG internal state
+ * @v test Instantiation test
+ */
+#define aes_cbc_ok( test ) do { \
+ struct cipher_algorithm *cipher = &aes_cbc_algorithm; \
+ \
+ assert ( (test)->iv_len == cipher->blocksize ); \
+ assert ( (test)->plaintext_len == (test)->ciphertext_len ); \
+ cbc_encrypt_ok ( cipher, (test)->key, (test)->key_len, \
+ (test)->iv, (test)->plaintext, \
+ (test)->ciphertext, (test)->plaintext_len ); \
+ cbc_decrypt_ok ( cipher, (test)->key, (test)->key_len, \
+ (test)->iv, (test)->ciphertext, \
+ (test)->plaintext, (test)->ciphertext_len ); \
+ } while ( 0 )
+
+/** CBC_AES128 */
+AES_CBC_TEST ( test_128,
+ KEY ( 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15,
+ 0x88, 0x09, 0xcf, 0x4f, 0x3c ),
+ IV ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+ 0x0b, 0x0c, 0x0d, 0x0e, 0x0f ),
+ PLAINTEXT ( 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 ),
+ CIPHERTEXT ( 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46,
+ 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
+ 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee,
+ 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
+ 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b,
+ 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
+ 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09,
+ 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 ) );
+
+/** CBC_AES256 */
+AES_CBC_TEST ( test_256,
+ KEY ( 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae,
+ 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61,
+ 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 ),
+ IV ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+ 0x0b, 0x0c, 0x0d, 0x0e, 0x0f ),
+ PLAINTEXT ( 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 ),
+ CIPHERTEXT ( 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
+ 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
+ 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
+ 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
+ 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
+ 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
+ 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
+ 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b ) );
+
+/**
+ * Perform AES-in-CBC-mode self-test
+ *
+ */
+static void aes_cbc_test_exec ( void ) {
+
+ aes_cbc_ok ( &test_128 );
+ aes_cbc_ok ( &test_256 );
+}
+
+/** AES-in-CBC-mode self-test */
+struct self_test aes_cbc_test __self_test = {
+ .name = "aes_cbc",
+ .exec = aes_cbc_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/bigint_test.c b/src/VBox/Devices/PC/ipxe/src/tests/bigint_test.c
new file mode 100644
index 00000000..4052131f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/bigint_test.c
@@ -0,0 +1,2436 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Big integer self-tests
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <assert.h>
+#include <string.h>
+#include <ipxe/bigint.h>
+#include <ipxe/test.h>
+
+/** Define inline big integer */
+#define BIGINT(...) { __VA_ARGS__ }
+
+/* Provide global functions to allow inspection of generated assembly code */
+
+void bigint_init_sample ( bigint_element_t *value0, unsigned int size,
+ const void *data, size_t len ) {
+ bigint_t ( size ) *value __attribute__ (( may_alias ))
+ = ( ( void * ) value0 );
+
+ bigint_init ( value, data, len );
+}
+
+void bigint_done_sample ( const bigint_element_t *value0, unsigned int size,
+ void *out, size_t len ) {
+ const bigint_t ( size ) *value __attribute__ (( may_alias ))
+ = ( ( const void * ) value0 );
+
+ bigint_done ( value, out, len );
+}
+
+void bigint_add_sample ( const bigint_element_t *addend0,
+ bigint_element_t *value0, unsigned int size ) {
+ const bigint_t ( size ) *addend __attribute__ (( may_alias ))
+ = ( ( const void * ) addend0 );
+ bigint_t ( size ) *value __attribute__ (( may_alias ))
+ = ( ( void * ) value0 );
+
+ bigint_add ( addend, value );
+}
+
+void bigint_subtract_sample ( const bigint_element_t *subtrahend0,
+ bigint_element_t *value0, unsigned int size ) {
+ const bigint_t ( size ) *subtrahend __attribute__ (( may_alias ))
+ = ( ( const void * ) subtrahend0 );
+ bigint_t ( size ) *value __attribute__ (( may_alias ))
+ = ( ( void * ) value0 );
+
+ bigint_subtract ( subtrahend, value );
+}
+
+void bigint_rol_sample ( bigint_element_t *value0, unsigned int size ) {
+ bigint_t ( size ) *value __attribute__ (( may_alias ))
+ = ( ( void * ) value0 );
+
+ bigint_rol ( value );
+}
+
+void bigint_ror_sample ( bigint_element_t *value0, unsigned int size ) {
+ bigint_t ( size ) *value __attribute__ (( may_alias ))
+ = ( ( void * ) value0 );
+
+ bigint_ror ( value );
+}
+
+int bigint_is_zero_sample ( const bigint_element_t *value0,
+ unsigned int size ) {
+ const bigint_t ( size ) *value __attribute__ (( may_alias ))
+ = ( ( const void * ) value0 );
+
+ return bigint_is_zero ( value );
+}
+
+int bigint_is_geq_sample ( const bigint_element_t *value0,
+ const bigint_element_t *reference0,
+ unsigned int size ) {
+ const bigint_t ( size ) *value __attribute__ (( may_alias ))
+ = ( ( const void * ) value0 );
+ const bigint_t ( size ) *reference __attribute__ (( may_alias ))
+ = ( ( const void * ) reference0 );
+
+ return bigint_is_geq ( value, reference );
+}
+
+int bigint_bit_is_set_sample ( const bigint_element_t *value0,
+ unsigned int size, unsigned int bit ) {
+ const bigint_t ( size ) *value __attribute__ (( may_alias ))
+ = ( ( const void * ) value0 );
+
+ return bigint_bit_is_set ( value, bit );
+}
+
+int bigint_max_set_bit_sample ( const bigint_element_t *value0,
+ unsigned int size ) {
+ const bigint_t ( size ) *value __attribute__ (( may_alias ))
+ = ( ( const void * ) value0 );
+
+ return bigint_max_set_bit ( value );
+}
+
+void bigint_grow_sample ( const bigint_element_t *source0,
+ unsigned int source_size, bigint_element_t *dest0,
+ unsigned int dest_size ) {
+ const bigint_t ( source_size ) *source __attribute__ (( may_alias ))
+ = ( ( const void * ) source0 );
+ bigint_t ( dest_size ) *dest __attribute__ (( may_alias ))
+ = ( ( void * ) dest0 );
+
+ bigint_grow ( source, dest );
+}
+
+void bigint_shrink_sample ( const bigint_element_t *source0,
+ unsigned int source_size, bigint_element_t *dest0,
+ unsigned int dest_size ) {
+ const bigint_t ( source_size ) *source __attribute__ (( may_alias ))
+ = ( ( const void * ) source0 );
+ bigint_t ( dest_size ) *dest __attribute__ (( may_alias ))
+ = ( ( void * ) dest0 );
+
+ bigint_shrink ( source, dest );
+}
+
+void bigint_multiply_sample ( const bigint_element_t *multiplicand0,
+ const bigint_element_t *multiplier0,
+ bigint_element_t *result0,
+ unsigned int size ) {
+ const bigint_t ( size ) *multiplicand __attribute__ (( may_alias ))
+ = ( ( const void * ) multiplicand0 );
+ const bigint_t ( size ) *multiplier __attribute__ (( may_alias ))
+ = ( ( const void * ) multiplier0 );
+ bigint_t ( size * 2 ) *result __attribute__ (( may_alias ))
+ = ( ( void * ) result0 );
+
+ bigint_multiply ( multiplicand, multiplier, result );
+}
+
+void bigint_mod_multiply_sample ( const bigint_element_t *multiplicand0,
+ const bigint_element_t *multiplier0,
+ const bigint_element_t *modulus0,
+ bigint_element_t *result0,
+ unsigned int size,
+ void *tmp ) {
+ const bigint_t ( size ) *multiplicand __attribute__ (( may_alias ))
+ = ( ( const void * ) multiplicand0 );
+ const bigint_t ( size ) *multiplier __attribute__ (( may_alias ))
+ = ( ( const void * ) multiplier0 );
+ const bigint_t ( size ) *modulus __attribute__ (( may_alias ))
+ = ( ( const void * ) modulus0 );
+ bigint_t ( size ) *result __attribute__ (( may_alias ))
+ = ( ( void * ) result0 );
+
+ bigint_mod_multiply ( multiplicand, multiplier, modulus, result, tmp );
+}
+
+void bigint_mod_exp_sample ( const bigint_element_t *base0,
+ const bigint_element_t *modulus0,
+ const bigint_element_t *exponent0,
+ bigint_element_t *result0,
+ unsigned int size, unsigned int exponent_size,
+ void *tmp ) {
+ const bigint_t ( size ) *base __attribute__ (( may_alias ))
+ = ( ( const void * ) base0 );
+ const bigint_t ( size ) *modulus __attribute__ (( may_alias ))
+ = ( ( const void * ) modulus0 );
+ const bigint_t ( exponent_size ) *exponent __attribute__ (( may_alias ))
+ = ( ( const void * ) exponent0 );
+ bigint_t ( size ) *result __attribute__ (( may_alias ))
+ = ( ( void * ) result0 );
+
+ bigint_mod_exp ( base, modulus, exponent, result, tmp );
+}
+
+/**
+ * Report result of big integer addition test
+ *
+ * @v addend Big integer to add
+ * @v value Big integer to be added to
+ * @v expected Big integer expected result
+ */
+#define bigint_add_ok( addend, value, expected ) do { \
+ static const uint8_t addend_raw[] = addend; \
+ static const uint8_t value_raw[] = value; \
+ static const uint8_t expected_raw[] = expected; \
+ uint8_t result_raw[ sizeof ( expected_raw ) ]; \
+ unsigned int size = \
+ bigint_required_size ( sizeof ( value_raw ) ); \
+ bigint_t ( size ) addend_temp; \
+ bigint_t ( size ) value_temp; \
+ {} /* Fix emacs alignment */ \
+ \
+ assert ( bigint_size ( &addend_temp ) == \
+ bigint_size ( &value_temp ) ); \
+ bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \
+ bigint_init ( &addend_temp, addend_raw, \
+ sizeof ( addend_raw ) ); \
+ DBG ( "Add:\n" ); \
+ DBG_HDA ( 0, &addend_temp, sizeof ( addend_temp ) ); \
+ DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \
+ bigint_add ( &addend_temp, &value_temp ); \
+ DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \
+ bigint_done ( &value_temp, result_raw, sizeof ( result_raw ) ); \
+ \
+ ok ( memcmp ( result_raw, expected_raw, \
+ sizeof ( result_raw ) ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report result of big integer subtraction test
+ *
+ * @v subtrahend Big integer to subtract
+ * @v value Big integer to be subtracted from
+ * @v expected Big integer expected result
+ */
+#define bigint_subtract_ok( subtrahend, value, expected ) do { \
+ static const uint8_t subtrahend_raw[] = subtrahend; \
+ static const uint8_t value_raw[] = value; \
+ static const uint8_t expected_raw[] = expected; \
+ uint8_t result_raw[ sizeof ( expected_raw ) ]; \
+ unsigned int size = \
+ bigint_required_size ( sizeof ( value_raw ) ); \
+ bigint_t ( size ) subtrahend_temp; \
+ bigint_t ( size ) value_temp; \
+ {} /* Fix emacs alignment */ \
+ \
+ assert ( bigint_size ( &subtrahend_temp ) == \
+ bigint_size ( &value_temp ) ); \
+ bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \
+ bigint_init ( &subtrahend_temp, subtrahend_raw, \
+ sizeof ( subtrahend_raw ) ); \
+ DBG ( "Subtract:\n" ); \
+ DBG_HDA ( 0, &subtrahend_temp, sizeof ( subtrahend_temp ) ); \
+ DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \
+ bigint_subtract ( &subtrahend_temp, &value_temp ); \
+ DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \
+ bigint_done ( &value_temp, result_raw, sizeof ( result_raw ) ); \
+ \
+ ok ( memcmp ( result_raw, expected_raw, \
+ sizeof ( result_raw ) ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report result of big integer left rotation test
+ *
+ * @v value Big integer
+ * @v expected Big integer expected result
+ */
+#define bigint_rol_ok( value, expected ) do { \
+ static const uint8_t value_raw[] = value; \
+ static const uint8_t expected_raw[] = expected; \
+ uint8_t result_raw[ sizeof ( expected_raw ) ]; \
+ unsigned int size = \
+ bigint_required_size ( sizeof ( value_raw ) ); \
+ bigint_t ( size ) value_temp; \
+ {} /* Fix emacs alignment */ \
+ \
+ bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \
+ DBG ( "Rotate left:\n" ); \
+ DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \
+ bigint_rol ( &value_temp ); \
+ DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \
+ bigint_done ( &value_temp, result_raw, sizeof ( result_raw ) ); \
+ \
+ ok ( memcmp ( result_raw, expected_raw, \
+ sizeof ( result_raw ) ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report result of big integer right rotation test
+ *
+ * @v value Big integer
+ * @v expected Big integer expected result
+ */
+#define bigint_ror_ok( value, expected ) do { \
+ static const uint8_t value_raw[] = value; \
+ static const uint8_t expected_raw[] = expected; \
+ uint8_t result_raw[ sizeof ( expected_raw ) ]; \
+ unsigned int size = \
+ bigint_required_size ( sizeof ( value_raw ) ); \
+ bigint_t ( size ) value_temp; \
+ {} /* Fix emacs alignment */ \
+ \
+ bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \
+ DBG ( "Rotate right:\n" ); \
+ DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \
+ bigint_ror ( &value_temp ); \
+ DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \
+ bigint_done ( &value_temp, result_raw, sizeof ( result_raw ) ); \
+ \
+ ok ( memcmp ( result_raw, expected_raw, \
+ sizeof ( result_raw ) ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report result of big integer zero comparison test
+ *
+ * @v value Big integer
+ * @v expected Expected result
+ */
+#define bigint_is_zero_ok( value, expected ) do { \
+ static const uint8_t value_raw[] = value; \
+ unsigned int size = \
+ bigint_required_size ( sizeof ( value_raw ) ); \
+ bigint_t ( size ) value_temp; \
+ int is_zero; \
+ {} /* Fix emacs alignment */ \
+ \
+ bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \
+ DBG ( "Zero comparison:\n" ); \
+ DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \
+ is_zero = bigint_is_zero ( &value_temp ); \
+ DBG ( "...is %szero\n", ( is_zero ? "" : "not " ) ); \
+ ok ( ( !! is_zero ) == ( !! (expected) ) ); \
+ } while ( 0 )
+
+/**
+ * Report result of big integer greater-than-or-equal comparison test
+ *
+ * @v value Big integer
+ * @v reference Reference big integer
+ * @v expected Expected result
+ */
+#define bigint_is_geq_ok( value, reference, expected ) do { \
+ static const uint8_t value_raw[] = value; \
+ static const uint8_t reference_raw[] = reference; \
+ unsigned int size = \
+ bigint_required_size ( sizeof ( value_raw ) ); \
+ bigint_t ( size ) value_temp; \
+ bigint_t ( size ) reference_temp; \
+ int is_geq; \
+ {} /* Fix emacs alignment */ \
+ \
+ assert ( bigint_size ( &reference_temp ) == \
+ bigint_size ( &value_temp ) ); \
+ bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \
+ bigint_init ( &reference_temp, reference_raw, \
+ sizeof ( reference_raw ) ); \
+ DBG ( "Greater-than-or-equal comparison:\n" ); \
+ DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \
+ DBG_HDA ( 0, &reference_temp, sizeof ( reference_temp ) ); \
+ is_geq = bigint_is_geq ( &value_temp, &reference_temp ); \
+ DBG ( "...is %sgreater than or equal\n", \
+ ( is_geq ? "" : "not " ) ); \
+ ok ( ( !! is_geq ) == ( !! (expected) ) ); \
+ } while ( 0 )
+
+/**
+ * Report result of big integer bit-set test
+ *
+ * @v value Big integer
+ * @v bit Bit to test
+ * @v expected Expected result
+ */
+#define bigint_bit_is_set_ok( value, bit, expected ) do { \
+ static const uint8_t value_raw[] = value; \
+ unsigned int size = \
+ bigint_required_size ( sizeof ( value_raw ) ); \
+ bigint_t ( size ) value_temp; \
+ int bit_is_set; \
+ {} /* Fix emacs alignment */ \
+ \
+ bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \
+ DBG ( "Bit set:\n" ); \
+ DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \
+ bit_is_set = bigint_bit_is_set ( &value_temp, bit ); \
+ DBG ( "...bit %d is %sset\n", bit, \
+ ( bit_is_set ? "" : "not " ) ); \
+ ok ( ( !! bit_is_set ) == ( !! (expected) ) ); \
+ } while ( 0 )
+
+/**
+ * Report result of big integer maximum set bit test
+ *
+ * @v value Big integer
+ * @v expected Expected result
+ */
+#define bigint_max_set_bit_ok( value, expected ) do { \
+ static const uint8_t value_raw[] = value; \
+ unsigned int size = \
+ bigint_required_size ( sizeof ( value_raw ) ); \
+ bigint_t ( size ) value_temp; \
+ int max_set_bit; \
+ {} /* Fix emacs alignment */ \
+ \
+ bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \
+ DBG ( "Maximum set bit:\n" ); \
+ DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \
+ max_set_bit = bigint_max_set_bit ( &value_temp ); \
+ DBG ( "...maximum set bit is bit %d\n", ( max_set_bit - 1 ) ); \
+ ok ( max_set_bit == (expected) ); \
+ } while ( 0 )
+
+/**
+ * Report result of big integer multiplication test
+ *
+ * @v multiplicand Big integer to be multiplied
+ * @v multiplier Big integer to be multiplied
+ * @v expected Big integer expected result
+ */
+#define bigint_multiply_ok( multiplicand, multiplier, expected ) do { \
+ static const uint8_t multiplicand_raw[] = multiplicand; \
+ static const uint8_t multiplier_raw[] = multiplier; \
+ static const uint8_t expected_raw[] = expected; \
+ uint8_t result_raw[ sizeof ( expected_raw ) ]; \
+ unsigned int size = \
+ bigint_required_size ( sizeof ( multiplicand_raw ) ); \
+ bigint_t ( size ) multiplicand_temp; \
+ bigint_t ( size ) multiplier_temp; \
+ bigint_t ( size * 2 ) result_temp; \
+ {} /* Fix emacs alignment */ \
+ \
+ assert ( bigint_size ( &multiplier_temp ) == \
+ bigint_size ( &multiplicand_temp ) ); \
+ assert ( bigint_size ( &result_temp ) == \
+ ( 2 * bigint_size ( &multiplicand_temp ) ) ); \
+ bigint_init ( &multiplicand_temp, multiplicand_raw, \
+ sizeof ( multiplicand_raw ) ); \
+ bigint_init ( &multiplier_temp, multiplier_raw, \
+ sizeof ( multiplier_raw ) ); \
+ DBG ( "Multiply:\n" ); \
+ DBG_HDA ( 0, &multiplicand_temp, sizeof ( multiplicand_temp ) );\
+ DBG_HDA ( 0, &multiplier_temp, sizeof ( multiplier_temp ) ); \
+ bigint_multiply ( &multiplicand_temp, &multiplier_temp, \
+ &result_temp ); \
+ DBG_HDA ( 0, &result_temp, sizeof ( result_temp ) ); \
+ bigint_done ( &result_temp, result_raw, sizeof ( result_raw ) );\
+ \
+ ok ( memcmp ( result_raw, expected_raw, \
+ sizeof ( result_raw ) ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report result of big integer modular multiplication test
+ *
+ * @v multiplicand Big integer to be multiplied
+ * @v multiplier Big integer to be multiplied
+ * @v modulus Big integer modulus
+ * @v expected Big integer expected result
+ */
+#define bigint_mod_multiply_ok( multiplicand, multiplier, modulus, \
+ expected ) do { \
+ static const uint8_t multiplicand_raw[] = multiplicand; \
+ static const uint8_t multiplier_raw[] = multiplier; \
+ static const uint8_t modulus_raw[] = modulus; \
+ static const uint8_t expected_raw[] = expected; \
+ uint8_t result_raw[ sizeof ( expected_raw ) ]; \
+ unsigned int size = \
+ bigint_required_size ( sizeof ( multiplicand_raw ) ); \
+ bigint_t ( size ) multiplicand_temp; \
+ bigint_t ( size ) multiplier_temp; \
+ bigint_t ( size ) modulus_temp; \
+ bigint_t ( size ) result_temp; \
+ size_t tmp_len = bigint_mod_multiply_tmp_len ( &modulus_temp ); \
+ uint8_t tmp[tmp_len]; \
+ {} /* Fix emacs alignment */ \
+ \
+ assert ( bigint_size ( &multiplier_temp ) == \
+ bigint_size ( &multiplicand_temp ) ); \
+ assert ( bigint_size ( &multiplier_temp ) == \
+ bigint_size ( &modulus_temp ) ); \
+ assert ( bigint_size ( &multiplier_temp ) == \
+ bigint_size ( &result_temp ) ); \
+ bigint_init ( &multiplicand_temp, multiplicand_raw, \
+ sizeof ( multiplicand_raw ) ); \
+ bigint_init ( &multiplier_temp, multiplier_raw, \
+ sizeof ( multiplier_raw ) ); \
+ bigint_init ( &modulus_temp, modulus_raw, \
+ sizeof ( modulus_raw ) ); \
+ DBG ( "Modular multiply:\n" ); \
+ DBG_HDA ( 0, &multiplicand_temp, sizeof ( multiplicand_temp ) );\
+ DBG_HDA ( 0, &multiplier_temp, sizeof ( multiplier_temp ) ); \
+ DBG_HDA ( 0, &modulus_temp, sizeof ( modulus_temp ) ); \
+ bigint_mod_multiply ( &multiplicand_temp, &multiplier_temp, \
+ &modulus_temp, &result_temp, tmp ); \
+ DBG_HDA ( 0, &result_temp, sizeof ( result_temp ) ); \
+ bigint_done ( &result_temp, result_raw, sizeof ( result_raw ) );\
+ \
+ ok ( memcmp ( result_raw, expected_raw, \
+ sizeof ( result_raw ) ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report result of big integer modular exponentiation test
+ *
+ * @v base Big integer base
+ * @v modulus Big integer modulus
+ * @v exponent Big integer exponent
+ * @v expected Big integer expected result
+ */
+#define bigint_mod_exp_ok( base, modulus, exponent, expected ) do { \
+ static const uint8_t base_raw[] = base; \
+ static const uint8_t modulus_raw[] = modulus; \
+ static const uint8_t exponent_raw[] = exponent; \
+ static const uint8_t expected_raw[] = expected; \
+ uint8_t result_raw[ sizeof ( expected_raw ) ]; \
+ unsigned int size = \
+ bigint_required_size ( sizeof ( base_raw ) ); \
+ unsigned int exponent_size = \
+ bigint_required_size ( sizeof ( exponent_raw ) ); \
+ bigint_t ( size ) base_temp; \
+ bigint_t ( size ) modulus_temp; \
+ bigint_t ( exponent_size ) exponent_temp; \
+ bigint_t ( size ) result_temp; \
+ size_t tmp_len = bigint_mod_exp_tmp_len ( &modulus_temp, \
+ &exponent_temp ); \
+ uint8_t tmp[tmp_len]; \
+ {} /* Fix emacs alignment */ \
+ \
+ assert ( bigint_size ( &modulus_temp ) == \
+ bigint_size ( &base_temp ) ); \
+ assert ( bigint_size ( &modulus_temp ) == \
+ bigint_size ( &result_temp ) ); \
+ bigint_init ( &base_temp, base_raw, sizeof ( base_raw ) ); \
+ bigint_init ( &modulus_temp, modulus_raw, \
+ sizeof ( modulus_raw ) ); \
+ bigint_init ( &exponent_temp, exponent_raw, \
+ sizeof ( exponent_raw ) ); \
+ DBG ( "Modular exponentiation:\n" ); \
+ DBG_HDA ( 0, &base_temp, sizeof ( base_temp ) ); \
+ DBG_HDA ( 0, &modulus_temp, sizeof ( modulus_temp ) ); \
+ DBG_HDA ( 0, &exponent_temp, sizeof ( exponent_temp ) ); \
+ bigint_mod_exp ( &base_temp, &modulus_temp, &exponent_temp, \
+ &result_temp, tmp ); \
+ DBG_HDA ( 0, &result_temp, sizeof ( result_temp ) ); \
+ bigint_done ( &result_temp, result_raw, sizeof ( result_raw ) );\
+ \
+ ok ( memcmp ( result_raw, expected_raw, \
+ sizeof ( result_raw ) ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Perform big integer self-tests
+ *
+ */
+static void bigint_test_exec ( void ) {
+
+ bigint_add_ok ( BIGINT ( 0x8a ),
+ BIGINT ( 0x43 ),
+ BIGINT ( 0xcd ) );
+ bigint_add_ok ( BIGINT ( 0xc5, 0x7b ),
+ BIGINT ( 0xd6, 0xb1 ),
+ BIGINT ( 0x9c, 0x2c ) );
+ bigint_add_ok ( BIGINT ( 0xf9, 0xd9, 0xdc ),
+ BIGINT ( 0x6d, 0x4b, 0xca ),
+ BIGINT ( 0x67, 0x25, 0xa6 ) );
+ bigint_add_ok ( BIGINT ( 0xdd, 0xc2, 0x20, 0x5f ),
+ BIGINT ( 0x80, 0x32, 0xc4, 0xb0 ),
+ BIGINT ( 0x5d, 0xf4, 0xe5, 0x0f ) );
+ bigint_add_ok ( BIGINT ( 0x01, 0xed, 0x45, 0x4b, 0x41, 0xeb, 0x4c,
+ 0x2e, 0x53, 0x07, 0x15, 0x51, 0x56, 0x47,
+ 0x29, 0xfc, 0x9c, 0xbd, 0xbd, 0xfb, 0x1b,
+ 0xd1, 0x1d ),
+ BIGINT ( 0x73, 0xed, 0xfc, 0x35, 0x31, 0x22, 0xd7,
+ 0xb1, 0xea, 0x91, 0x5a, 0xe4, 0xba, 0xbc,
+ 0xa1, 0x38, 0x72, 0xae, 0x4b, 0x1c, 0xc1,
+ 0x05, 0xb3 ),
+ BIGINT ( 0x75, 0xdb, 0x41, 0x80, 0x73, 0x0e, 0x23,
+ 0xe0, 0x3d, 0x98, 0x70, 0x36, 0x11, 0x03,
+ 0xcb, 0x35, 0x0f, 0x6c, 0x09, 0x17, 0xdc,
+ 0xd6, 0xd0 ) );
+ bigint_add_ok ( BIGINT ( 0x06, 0x8e, 0xd6, 0x18, 0xbb, 0x4b, 0x0c,
+ 0xc5, 0x85, 0xde, 0xee, 0x9b, 0x3f, 0x65,
+ 0x63, 0x86, 0xf5, 0x5a, 0x9f, 0xa2, 0xd7,
+ 0xb2, 0xc7, 0xb6, 0x1d, 0x28, 0x6c, 0x50,
+ 0x47, 0x10, 0x0a, 0x0e, 0x86, 0xcd, 0x2a,
+ 0x64, 0xdc, 0xe6, 0x9d, 0x96, 0xd8, 0xf4,
+ 0x56, 0x46, 0x6f, 0xbb, 0x7b, 0x64, 0x6f,
+ 0xdc, 0x2a, 0xd1, 0x3b, 0xcc, 0x03, 0x85,
+ 0x95, 0xf4, 0xe9, 0x68, 0x1f, 0x5c, 0xc5,
+ 0xbf, 0x97, 0x19, 0x12, 0x88, 0x2e, 0x88,
+ 0xb9, 0x34, 0xac, 0x74, 0x83, 0x2d, 0x8f,
+ 0xb3, 0x97, 0x53, 0x99, 0xf3, 0xb4, 0x8b,
+ 0x2d, 0x98, 0x69, 0x8d, 0x19, 0xf0, 0x40,
+ 0x66, 0x3f, 0x60, 0x78, 0x34, 0x7f, 0x9b,
+ 0xf7, 0x01, 0x74, 0x55, 0xca, 0x63, 0x25,
+ 0x7b, 0x86, 0xe9, 0x73, 0xfd, 0x5d, 0x77,
+ 0x32, 0x5e, 0x9e, 0x42, 0x53, 0xb6, 0x35,
+ 0x92, 0xb9, 0xd7, 0x1b, 0xf7, 0x16, 0x55,
+ 0xf6, 0xe2 ),
+ BIGINT ( 0x3f, 0x8f, 0x62, 0x21, 0x4a, 0x7a, 0xa2,
+ 0xef, 0xa8, 0x79, 0x9b, 0x73, 0xac, 0xde,
+ 0x72, 0xe4, 0xfc, 0x3c, 0xd3, 0xa9, 0x44,
+ 0x1a, 0x6a, 0x02, 0x76, 0xe3, 0x78, 0x4d,
+ 0x2e, 0x07, 0x9b, 0xb6, 0x3d, 0x5d, 0xc5,
+ 0xcd, 0x68, 0x23, 0x4b, 0x5f, 0x89, 0x0e,
+ 0xd7, 0xa7, 0xff, 0x18, 0x80, 0xdc, 0xfb,
+ 0x34, 0x45, 0xca, 0x4b, 0xdb, 0x8a, 0x19,
+ 0xcb, 0xc9, 0xe5, 0xa1, 0x63, 0xa2, 0x0d,
+ 0x56, 0xc4, 0xf9, 0x51, 0x1b, 0x88, 0x4e,
+ 0x36, 0xab, 0x15, 0x4d, 0x8f, 0xdc, 0x08,
+ 0xc4, 0x4d, 0x43, 0xc7, 0x2b, 0xc9, 0x5c,
+ 0x05, 0x26, 0xe3, 0x46, 0xf0, 0x64, 0xaa,
+ 0x02, 0xa4, 0xbe, 0x3a, 0xd1, 0xca, 0x07,
+ 0x6a, 0x6e, 0x62, 0xf4, 0x57, 0x71, 0x96,
+ 0xec, 0xf0, 0x0b, 0xac, 0xa4, 0x4a, 0xa3,
+ 0x6d, 0x01, 0xba, 0xbd, 0x62, 0xc0, 0x10,
+ 0x54, 0x33, 0x8a, 0x71, 0xef, 0xaa, 0x1c,
+ 0x25, 0x25 ),
+ BIGINT ( 0x46, 0x1e, 0x38, 0x3a, 0x05, 0xc5, 0xaf,
+ 0xb5, 0x2e, 0x58, 0x8a, 0x0e, 0xec, 0x43,
+ 0xd6, 0x6b, 0xf1, 0x97, 0x73, 0x4c, 0x1b,
+ 0xcd, 0x31, 0xb8, 0x94, 0x0b, 0xe4, 0x9d,
+ 0x75, 0x17, 0xa5, 0xc4, 0xc4, 0x2a, 0xf0,
+ 0x32, 0x45, 0x09, 0xe8, 0xf6, 0x62, 0x03,
+ 0x2d, 0xee, 0x6e, 0xd3, 0xfc, 0x41, 0x6b,
+ 0x10, 0x70, 0x9b, 0x87, 0xa7, 0x8d, 0x9f,
+ 0x61, 0xbe, 0xcf, 0x09, 0x82, 0xfe, 0xd3,
+ 0x16, 0x5c, 0x12, 0x63, 0xa3, 0xb6, 0xd6,
+ 0xef, 0xdf, 0xc1, 0xc2, 0x13, 0x09, 0x98,
+ 0x77, 0xe4, 0x97, 0x61, 0x1f, 0x7d, 0xe7,
+ 0x32, 0xbf, 0x4c, 0xd4, 0x0a, 0x54, 0xea,
+ 0x68, 0xe4, 0x1e, 0xb3, 0x06, 0x49, 0xa3,
+ 0x61, 0x6f, 0xd7, 0x4a, 0x21, 0xd4, 0xbc,
+ 0x68, 0x76, 0xf5, 0x20, 0xa1, 0xa8, 0x1a,
+ 0x9f, 0x60, 0x58, 0xff, 0xb6, 0x76, 0x45,
+ 0xe6, 0xed, 0x61, 0x8d, 0xe6, 0xc0, 0x72,
+ 0x1c, 0x07 ) );
+ bigint_subtract_ok ( BIGINT ( 0x83 ),
+ BIGINT ( 0x50 ),
+ BIGINT ( 0xcd ) );
+ bigint_subtract_ok ( BIGINT ( 0x2c, 0x7c ),
+ BIGINT ( 0x49, 0x0e ),
+ BIGINT ( 0x1c, 0x92 ) );
+ bigint_subtract_ok ( BIGINT ( 0x9c, 0x30, 0xbf ),
+ BIGINT ( 0xde, 0x4e, 0x07 ),
+ BIGINT ( 0x42, 0x1d, 0x48 ) );
+ bigint_subtract_ok ( BIGINT ( 0xbb, 0x77, 0x32, 0x5a ),
+ BIGINT ( 0x5a, 0xd5, 0xfe, 0x28 ),
+ BIGINT ( 0x9f, 0x5e, 0xcb, 0xce ) );
+ bigint_subtract_ok ( BIGINT ( 0x7b, 0xaa, 0x16, 0xcf, 0x15, 0x87,
+ 0xe0, 0x4f, 0x2c, 0xa3, 0xec, 0x2f,
+ 0x46, 0xfb, 0x83, 0xc6, 0xe0, 0xee,
+ 0x57, 0xfa, 0x04, 0xce, 0xa6 ),
+ BIGINT ( 0x46, 0x55, 0xb6, 0x23, 0x63, 0xd0,
+ 0x55, 0xdb, 0x8f, 0xcc, 0x55, 0xa8,
+ 0x2f, 0x85, 0xc1, 0x9f, 0x2c, 0x13,
+ 0x10, 0x9e, 0x76, 0x3c, 0x11 ),
+ BIGINT ( 0xca, 0xab, 0x9f, 0x54, 0x4e, 0x48,
+ 0x75, 0x8c, 0x63, 0x28, 0x69, 0x78,
+ 0xe8, 0x8a, 0x3d, 0xd8, 0x4b, 0x24,
+ 0xb8, 0xa4, 0x71, 0x6d, 0x6b ) );
+ bigint_subtract_ok ( BIGINT ( 0x5b, 0x06, 0x77, 0x7b, 0xfd, 0x34,
+ 0x5f, 0x0f, 0xd9, 0xbd, 0x8e, 0x5d,
+ 0xc8, 0x4a, 0x70, 0x95, 0x1b, 0xb6,
+ 0x48, 0xfb, 0x0e, 0x40, 0xce, 0x06,
+ 0x66, 0xcc, 0x29, 0xe9, 0x51, 0x59,
+ 0x59, 0xc9, 0x65, 0x07, 0x75, 0xb8,
+ 0xd4, 0xcb, 0x07, 0x68, 0x14, 0x48,
+ 0xc7, 0x1e, 0xfe, 0xb3, 0x4c, 0xf1,
+ 0x10, 0xf0, 0xc7, 0x82, 0x38, 0x4c,
+ 0xaf, 0x05, 0x6d, 0x91, 0xc5, 0x18,
+ 0xfd, 0x1e, 0x26, 0x1b, 0xef, 0x71,
+ 0x70, 0x2e, 0x06, 0x70, 0x8e, 0x54,
+ 0xfa, 0x2b, 0x4d, 0x96, 0x85, 0x10,
+ 0x03, 0x76, 0xe7, 0x17, 0x59, 0x86,
+ 0x6c, 0x8b, 0x24, 0x6e, 0xd9, 0x30,
+ 0xf3, 0xd2, 0x9b, 0x62, 0xdc, 0x23,
+ 0x54, 0x06, 0x51, 0xb1, 0x95, 0x58,
+ 0xec, 0x27, 0xf6, 0x19, 0xae, 0xf4,
+ 0x31, 0xec, 0x72, 0x53, 0xcd, 0x32,
+ 0xed, 0xf4, 0x25, 0x4a, 0x5b, 0x36,
+ 0xa2, 0xb4, 0xa0, 0x29, 0x0c, 0x6b,
+ 0x3f, 0xc2 ),
+ BIGINT ( 0x7a, 0xd4, 0x25, 0xf1, 0xb5, 0xf5,
+ 0x00, 0x96, 0x47, 0x5b, 0x4f, 0x9f,
+ 0x1f, 0x61, 0x69, 0xd9, 0x72, 0x47,
+ 0xde, 0xbd, 0x87, 0x5d, 0x50, 0x91,
+ 0x69, 0xd8, 0x35, 0xe0, 0x43, 0xd8,
+ 0xd5, 0x15, 0xf2, 0xcd, 0x01, 0x73,
+ 0x0d, 0x34, 0xf0, 0x34, 0x46, 0x76,
+ 0xc0, 0x55, 0x7b, 0x27, 0xf5, 0x7b,
+ 0x55, 0xe9, 0xd0, 0x29, 0x0b, 0x4b,
+ 0x9f, 0x07, 0xbf, 0x2c, 0x3f, 0xef,
+ 0x36, 0x34, 0xde, 0x29, 0x1d, 0x5d,
+ 0x84, 0x5a, 0x5d, 0xc1, 0x02, 0x4d,
+ 0x56, 0xf1, 0x47, 0x39, 0x37, 0xc9,
+ 0xb5, 0x5f, 0x73, 0xec, 0x7c, 0x3d,
+ 0xbd, 0xc0, 0xfd, 0x38, 0x6c, 0x91,
+ 0x88, 0x4a, 0x0f, 0xee, 0xa1, 0x80,
+ 0xf5, 0x6a, 0x7c, 0x8c, 0x02, 0xc3,
+ 0x5a, 0xb2, 0x15, 0xa6, 0x2f, 0x6b,
+ 0x5b, 0x78, 0xb5, 0xf3, 0xbd, 0xd0,
+ 0xc8, 0xbc, 0xb1, 0xbb, 0xe1, 0xce,
+ 0x22, 0x80, 0x34, 0x5a, 0x2a, 0x27,
+ 0x83, 0xdc ),
+ BIGINT ( 0x1f, 0xcd, 0xae, 0x75, 0xb8, 0xc0,
+ 0xa1, 0x86, 0x6d, 0x9d, 0xc1, 0x41,
+ 0x57, 0x16, 0xf9, 0x44, 0x56, 0x91,
+ 0x95, 0xc2, 0x79, 0x1c, 0x82, 0x8b,
+ 0x03, 0x0c, 0x0b, 0xf6, 0xf2, 0x7f,
+ 0x7b, 0x4c, 0x8d, 0xc5, 0x8b, 0xba,
+ 0x38, 0x69, 0xe8, 0xcc, 0x32, 0x2d,
+ 0xf9, 0x36, 0x7c, 0x74, 0xa8, 0x8a,
+ 0x44, 0xf9, 0x08, 0xa6, 0xd2, 0xfe,
+ 0xf0, 0x02, 0x51, 0x9a, 0x7a, 0xd6,
+ 0x39, 0x16, 0xb8, 0x0d, 0x2d, 0xec,
+ 0x14, 0x2c, 0x57, 0x50, 0x73, 0xf8,
+ 0x5c, 0xc5, 0xf9, 0xa2, 0xb2, 0xb9,
+ 0xb1, 0xe8, 0x8c, 0xd5, 0x22, 0xb7,
+ 0x51, 0x35, 0xd8, 0xc9, 0x93, 0x60,
+ 0x94, 0x77, 0x74, 0x8b, 0xc5, 0x5d,
+ 0xa1, 0x64, 0x2a, 0xda, 0x6d, 0x6a,
+ 0x6e, 0x8a, 0x1f, 0x8c, 0x80, 0x77,
+ 0x29, 0x8c, 0x43, 0x9f, 0xf0, 0x9d,
+ 0xda, 0xc8, 0x8c, 0x71, 0x86, 0x97,
+ 0x7f, 0xcb, 0x94, 0x31, 0x1d, 0xbc,
+ 0x44, 0x1a ) );
+ bigint_rol_ok ( BIGINT ( 0xe0 ),
+ BIGINT ( 0xc0 ) );
+ bigint_rol_ok ( BIGINT ( 0x43, 0x1d ),
+ BIGINT ( 0x86, 0x3a ) );
+ bigint_rol_ok ( BIGINT ( 0xac, 0xed, 0x9b ),
+ BIGINT ( 0x59, 0xdb, 0x36 ) );
+ bigint_rol_ok ( BIGINT ( 0x2c, 0xe8, 0x3a, 0x22 ),
+ BIGINT ( 0x59, 0xd0, 0x74, 0x44 ) );
+ bigint_rol_ok ( BIGINT ( 0x4e, 0x88, 0x4a, 0x05, 0x5e, 0x10, 0xee,
+ 0x5b, 0xc6, 0x40, 0x0e, 0x03, 0xd7, 0x0d,
+ 0x28, 0xa5, 0x55, 0xb2, 0x50, 0xef, 0x69,
+ 0xd1, 0x1d ),
+ BIGINT ( 0x9d, 0x10, 0x94, 0x0a, 0xbc, 0x21, 0xdc,
+ 0xb7, 0x8c, 0x80, 0x1c, 0x07, 0xae, 0x1a,
+ 0x51, 0x4a, 0xab, 0x64, 0xa1, 0xde, 0xd3,
+ 0xa2, 0x3a ) );
+ bigint_rol_ok ( BIGINT ( 0x07, 0x62, 0x78, 0x70, 0x2e, 0xd4, 0x41,
+ 0xaa, 0x9b, 0x50, 0xb1, 0x9a, 0x71, 0xf5,
+ 0x1c, 0x2f, 0xe7, 0x0d, 0xf1, 0x46, 0x57,
+ 0x04, 0x99, 0x78, 0x4e, 0x84, 0x78, 0xba,
+ 0x57, 0xea, 0xa5, 0x43, 0xf7, 0x02, 0xf0,
+ 0x7a, 0x22, 0x60, 0x65, 0x42, 0xf2, 0x33,
+ 0x7d, 0xe3, 0xa8, 0x1b, 0xc4, 0x14, 0xdb,
+ 0xee, 0x4a, 0xf1, 0xe1, 0x52, 0xd4, 0xda,
+ 0x23, 0xed, 0x13, 0x5d, 0xea, 0xcf, 0xf6,
+ 0x5e, 0x39, 0x84, 0xe2, 0xb3, 0xa2, 0x05,
+ 0xba, 0xd9, 0x49, 0x8e, 0x75, 0x1d, 0xdb,
+ 0xe6, 0xb1, 0x6e, 0xda, 0x0a, 0x83, 0xd0,
+ 0x6e, 0xcf, 0x7a, 0x66, 0xb7, 0x64, 0x84,
+ 0xf5, 0x09, 0x5a, 0xa8, 0x11, 0x93, 0xf3,
+ 0x4f, 0x02, 0x28, 0x00, 0x3a, 0xf0, 0xa9,
+ 0x08, 0x77, 0x04, 0xf5, 0x04, 0xcd, 0x6b,
+ 0x24, 0xbe, 0x0f, 0x6d, 0xe3, 0xb2, 0xd3,
+ 0x07, 0x68, 0xe9, 0x00, 0x59, 0xa0, 0xe4,
+ 0x9e, 0x5e ),
+ BIGINT ( 0x0e, 0xc4, 0xf0, 0xe0, 0x5d, 0xa8, 0x83,
+ 0x55, 0x36, 0xa1, 0x63, 0x34, 0xe3, 0xea,
+ 0x38, 0x5f, 0xce, 0x1b, 0xe2, 0x8c, 0xae,
+ 0x09, 0x32, 0xf0, 0x9d, 0x08, 0xf1, 0x74,
+ 0xaf, 0xd5, 0x4a, 0x87, 0xee, 0x05, 0xe0,
+ 0xf4, 0x44, 0xc0, 0xca, 0x85, 0xe4, 0x66,
+ 0xfb, 0xc7, 0x50, 0x37, 0x88, 0x29, 0xb7,
+ 0xdc, 0x95, 0xe3, 0xc2, 0xa5, 0xa9, 0xb4,
+ 0x47, 0xda, 0x26, 0xbb, 0xd5, 0x9f, 0xec,
+ 0xbc, 0x73, 0x09, 0xc5, 0x67, 0x44, 0x0b,
+ 0x75, 0xb2, 0x93, 0x1c, 0xea, 0x3b, 0xb7,
+ 0xcd, 0x62, 0xdd, 0xb4, 0x15, 0x07, 0xa0,
+ 0xdd, 0x9e, 0xf4, 0xcd, 0x6e, 0xc9, 0x09,
+ 0xea, 0x12, 0xb5, 0x50, 0x23, 0x27, 0xe6,
+ 0x9e, 0x04, 0x50, 0x00, 0x75, 0xe1, 0x52,
+ 0x10, 0xee, 0x09, 0xea, 0x09, 0x9a, 0xd6,
+ 0x49, 0x7c, 0x1e, 0xdb, 0xc7, 0x65, 0xa6,
+ 0x0e, 0xd1, 0xd2, 0x00, 0xb3, 0x41, 0xc9,
+ 0x3c, 0xbc ) );
+ bigint_ror_ok ( BIGINT ( 0x8f ),
+ BIGINT ( 0x47 ) );
+ bigint_ror_ok ( BIGINT ( 0xaa, 0x1d ),
+ BIGINT ( 0x55, 0x0e ) );
+ bigint_ror_ok ( BIGINT ( 0xf0, 0xbd, 0x68 ),
+ BIGINT ( 0x78, 0x5e, 0xb4 ) );
+ bigint_ror_ok ( BIGINT ( 0x33, 0xa0, 0x3d, 0x95 ),
+ BIGINT ( 0x19, 0xd0, 0x1e, 0xca ) );
+ bigint_ror_ok ( BIGINT ( 0xa1, 0xf4, 0xb9, 0x64, 0x91, 0x99, 0xa1,
+ 0xf4, 0xae, 0xeb, 0x71, 0x97, 0x1b, 0x71,
+ 0x09, 0x38, 0x3f, 0x8f, 0xc5, 0x3a, 0xb9,
+ 0x75, 0x94 ),
+ BIGINT ( 0x50, 0xfa, 0x5c, 0xb2, 0x48, 0xcc, 0xd0,
+ 0xfa, 0x57, 0x75, 0xb8, 0xcb, 0x8d, 0xb8,
+ 0x84, 0x9c, 0x1f, 0xc7, 0xe2, 0x9d, 0x5c,
+ 0xba, 0xca ) );
+ bigint_ror_ok ( BIGINT ( 0xc0, 0xb3, 0x78, 0x46, 0x69, 0x6e, 0x35,
+ 0x94, 0xed, 0x28, 0xdc, 0xfd, 0xf6, 0xdb,
+ 0x2d, 0x24, 0xcb, 0xa4, 0x6f, 0x0e, 0x58,
+ 0x89, 0x04, 0xec, 0xc8, 0x0c, 0x2d, 0xb3,
+ 0x58, 0xa7, 0x22, 0x6d, 0x93, 0xe0, 0xb8,
+ 0x48, 0x6a, 0x3f, 0x04, 0x7e, 0xbe, 0xb8,
+ 0xa7, 0x84, 0xf5, 0xc9, 0x2f, 0x60, 0x9e,
+ 0x7c, 0xbc, 0xaf, 0x28, 0x89, 0x2f, 0xaa,
+ 0xd1, 0x82, 0x77, 0xa4, 0xdf, 0xf3, 0x4a,
+ 0xc6, 0xed, 0xa3, 0x07, 0xb4, 0xa9, 0xfd,
+ 0xef, 0xf8, 0x20, 0xb9, 0xb3, 0xff, 0x35,
+ 0x27, 0xed, 0x02, 0xea, 0xec, 0x63, 0xc0,
+ 0x46, 0x97, 0xc0, 0x4c, 0xca, 0x89, 0xca,
+ 0x14, 0xe8, 0xe0, 0x02, 0x14, 0x44, 0x46,
+ 0xf3, 0x2f, 0xbc, 0x6a, 0x28, 0xa2, 0xbe,
+ 0x20, 0xc8, 0xaa, 0x0f, 0xd9, 0x51, 0x8e,
+ 0x8d, 0x51, 0x29, 0x61, 0xef, 0x48, 0xae,
+ 0x3e, 0xe5, 0x10, 0xbf, 0xda, 0x9b, 0x92,
+ 0xb3, 0x77 ),
+ BIGINT ( 0x60, 0x59, 0xbc, 0x23, 0x34, 0xb7, 0x1a,
+ 0xca, 0x76, 0x94, 0x6e, 0x7e, 0xfb, 0x6d,
+ 0x96, 0x92, 0x65, 0xd2, 0x37, 0x87, 0x2c,
+ 0x44, 0x82, 0x76, 0x64, 0x06, 0x16, 0xd9,
+ 0xac, 0x53, 0x91, 0x36, 0xc9, 0xf0, 0x5c,
+ 0x24, 0x35, 0x1f, 0x82, 0x3f, 0x5f, 0x5c,
+ 0x53, 0xc2, 0x7a, 0xe4, 0x97, 0xb0, 0x4f,
+ 0x3e, 0x5e, 0x57, 0x94, 0x44, 0x97, 0xd5,
+ 0x68, 0xc1, 0x3b, 0xd2, 0x6f, 0xf9, 0xa5,
+ 0x63, 0x76, 0xd1, 0x83, 0xda, 0x54, 0xfe,
+ 0xf7, 0xfc, 0x10, 0x5c, 0xd9, 0xff, 0x9a,
+ 0x93, 0xf6, 0x81, 0x75, 0x76, 0x31, 0xe0,
+ 0x23, 0x4b, 0xe0, 0x26, 0x65, 0x44, 0xe5,
+ 0x0a, 0x74, 0x70, 0x01, 0x0a, 0x22, 0x23,
+ 0x79, 0x97, 0xde, 0x35, 0x14, 0x51, 0x5f,
+ 0x10, 0x64, 0x55, 0x07, 0xec, 0xa8, 0xc7,
+ 0x46, 0xa8, 0x94, 0xb0, 0xf7, 0xa4, 0x57,
+ 0x1f, 0x72, 0x88, 0x5f, 0xed, 0x4d, 0xc9,
+ 0x59, 0xbb ) );
+ bigint_is_zero_ok ( BIGINT ( 0x9b ),
+ 0 );
+ bigint_is_zero_ok ( BIGINT ( 0x5a, 0x9d ),
+ 0 );
+ bigint_is_zero_ok ( BIGINT ( 0x5f, 0x80, 0x78 ),
+ 0 );
+ bigint_is_zero_ok ( BIGINT ( 0xa0, 0x52, 0x47, 0x2e ),
+ 0 );
+ bigint_is_zero_ok ( BIGINT ( 0x18, 0x08, 0x49, 0xdb, 0x7b, 0x5c,
+ 0xe7, 0x41, 0x07, 0xdf, 0xed, 0xf9,
+ 0xd3, 0x92, 0x0d, 0x75, 0xa6, 0xb0,
+ 0x14, 0xfa, 0xdd, 0xfd, 0x82 ),
+ 0 );
+ bigint_is_zero_ok ( BIGINT ( 0x04, 0x04, 0xb5, 0xf5, 0x01, 0xae,
+ 0x2b, 0x91, 0xa7, 0xc1, 0x49, 0x97,
+ 0x3f, 0x45, 0x53, 0x52, 0xb8, 0x52,
+ 0xf1, 0x62, 0xa5, 0x21, 0x18, 0xd4,
+ 0xb0, 0xb4, 0x8a, 0x17, 0x0e, 0xe8,
+ 0xeb, 0xaa, 0x28, 0xae, 0x3d, 0x8e,
+ 0xe3, 0x6c, 0xd0, 0x01, 0x0c, 0x54,
+ 0xca, 0x23, 0xbb, 0x06, 0xcd, 0x7a,
+ 0x61, 0x89, 0x38, 0x34, 0x6e, 0xc7,
+ 0xc2, 0xee, 0xb1, 0x80, 0x61, 0x0e,
+ 0xc6, 0x8d, 0x65, 0xa0, 0xeb, 0x34,
+ 0xe9, 0x63, 0x09, 0x4c, 0x20, 0xac,
+ 0x42, 0xe3, 0x35, 0xa2, 0x3e, 0x3b,
+ 0x2e, 0x18, 0x70, 0x45, 0x7c, 0xab,
+ 0x42, 0xcc, 0xe0, 0x9e, 0x7c, 0x42,
+ 0xd1, 0xda, 0x6c, 0x51, 0x10, 0x1e,
+ 0x0e, 0x3f, 0xe5, 0xd6, 0xd8, 0x56,
+ 0x08, 0xb2, 0x3b, 0x15, 0xc4, 0x7c,
+ 0x0c, 0x7e, 0xaf, 0x7b, 0x9d, 0xd6,
+ 0x2b, 0xc0, 0x2f, 0xa2, 0xa3, 0xa3,
+ 0x77, 0x58, 0x1b, 0xe9, 0xa8, 0x9a,
+ 0x23, 0x7f ),
+ 0 );
+ bigint_is_zero_ok ( BIGINT ( 0x00 ),
+ 1 );
+ bigint_is_zero_ok ( BIGINT ( 0x00, 0x00 ),
+ 1 );
+ bigint_is_zero_ok ( BIGINT ( 0x00, 0x00, 0x00 ),
+ 1 );
+ bigint_is_zero_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00 ),
+ 1 );
+ bigint_is_zero_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00 ),
+ 1 );
+ bigint_is_zero_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00 ),
+ 1 );
+ bigint_is_zero_ok ( BIGINT ( 0xff ),
+ 0 );
+ bigint_is_zero_ok ( BIGINT ( 0xff, 0xff ),
+ 0 );
+ bigint_is_zero_ok ( BIGINT ( 0xff, 0xff, 0xff ),
+ 0 );
+ bigint_is_zero_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff ),
+ 0 );
+ bigint_is_zero_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff ),
+ 0 );
+ bigint_is_zero_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff ),
+ 0 );
+ bigint_is_geq_ok ( BIGINT ( 0xa2 ),
+ BIGINT ( 0x58 ),
+ 1 );
+ bigint_is_geq_ok ( BIGINT ( 0x58 ),
+ BIGINT ( 0xa2 ),
+ 0 );
+ bigint_is_geq_ok ( BIGINT ( 0xa2 ),
+ BIGINT ( 0xa2 ),
+ 1 );
+ bigint_is_geq_ok ( BIGINT ( 0x61, 0x29 ),
+ BIGINT ( 0x87, 0xac ),
+ 0 );
+ bigint_is_geq_ok ( BIGINT ( 0x87, 0xac ),
+ BIGINT ( 0x61, 0x29 ),
+ 1 );
+ bigint_is_geq_ok ( BIGINT ( 0x61, 0x29 ),
+ BIGINT ( 0x61, 0x29 ),
+ 1 );
+ bigint_is_geq_ok ( BIGINT ( 0xe6, 0x63, 0x14 ),
+ BIGINT ( 0xb7, 0x2b, 0x76 ),
+ 1 );
+ bigint_is_geq_ok ( BIGINT ( 0xb7, 0x2b, 0x76 ),
+ BIGINT ( 0xe6, 0x63, 0x14 ),
+ 0 );
+ bigint_is_geq_ok ( BIGINT ( 0xe6, 0x63, 0x14 ),
+ BIGINT ( 0xe6, 0x63, 0x14 ),
+ 1 );
+ bigint_is_geq_ok ( BIGINT ( 0xe7, 0x4f, 0xd4, 0x80 ),
+ BIGINT ( 0xb5, 0xf9, 0x9b, 0x90 ),
+ 1 );
+ bigint_is_geq_ok ( BIGINT ( 0xb5, 0xf9, 0x9b, 0x90 ),
+ BIGINT ( 0xe7, 0x4f, 0xd4, 0x80 ),
+ 0 );
+ bigint_is_geq_ok ( BIGINT ( 0xe7, 0x4f, 0xd4, 0x80 ),
+ BIGINT ( 0xe7, 0x4f, 0xd4, 0x80 ),
+ 1 );
+ bigint_is_geq_ok ( BIGINT ( 0xe6, 0x2c, 0x7c, 0x24, 0x78, 0x8f, 0x12,
+ 0x20, 0xde, 0xd3, 0x6b, 0xc9, 0x97, 0x2d,
+ 0x66, 0x74, 0xe5, 0xb6, 0xf7, 0x8f, 0x2b,
+ 0x60, 0x98 ),
+ BIGINT ( 0x77, 0xbc, 0x3b, 0x1b, 0x57, 0x43, 0x3b,
+ 0x8c, 0x82, 0xda, 0xb5, 0xc7, 0x18, 0x09,
+ 0xb3, 0x59, 0x0e, 0x53, 0x2a, 0xb9, 0xd8,
+ 0xa2, 0xb4 ),
+ 1 );
+ bigint_is_geq_ok ( BIGINT ( 0x77, 0xbc, 0x3b, 0x1b, 0x57, 0x43, 0x3b,
+ 0x8c, 0x82, 0xda, 0xb5, 0xc7, 0x18, 0x09,
+ 0xb3, 0x59, 0x0e, 0x53, 0x2a, 0xb9, 0xd8,
+ 0xa2, 0xb4 ),
+ BIGINT ( 0xe6, 0x2c, 0x7c, 0x24, 0x78, 0x8f, 0x12,
+ 0x20, 0xde, 0xd3, 0x6b, 0xc9, 0x97, 0x2d,
+ 0x66, 0x74, 0xe5, 0xb6, 0xf7, 0x8f, 0x2b,
+ 0x60, 0x98 ),
+ 0 );
+ bigint_is_geq_ok ( BIGINT ( 0xe6, 0x2c, 0x7c, 0x24, 0x78, 0x8f, 0x12,
+ 0x20, 0xde, 0xd3, 0x6b, 0xc9, 0x97, 0x2d,
+ 0x66, 0x74, 0xe5, 0xb6, 0xf7, 0x8f, 0x2b,
+ 0x60, 0x98 ),
+ BIGINT ( 0xe6, 0x2c, 0x7c, 0x24, 0x78, 0x8f, 0x12,
+ 0x20, 0xde, 0xd3, 0x6b, 0xc9, 0x97, 0x2d,
+ 0x66, 0x74, 0xe5, 0xb6, 0xf7, 0x8f, 0x2b,
+ 0x60, 0x98 ),
+ 1 );
+ bigint_is_geq_ok ( BIGINT ( 0x2a, 0x98, 0xfd, 0x87, 0x5d, 0x9f, 0xb4,
+ 0x8b, 0x5c, 0xcd, 0x5f, 0xcd, 0x53, 0xb3,
+ 0xd1, 0x81, 0x6a, 0x9c, 0x93, 0x66, 0x40,
+ 0xa7, 0x64, 0xe0, 0x8c, 0xec, 0x96, 0x63,
+ 0x4d, 0x29, 0xfa, 0xb1, 0x5d, 0x93, 0x2f,
+ 0xf9, 0x36, 0xea, 0x3b, 0xc1, 0xaf, 0x85,
+ 0xcb, 0xde, 0x2d, 0xc8, 0x48, 0x33, 0xce,
+ 0x7b, 0xa4, 0xa4, 0xda, 0x0f, 0xaa, 0x1b,
+ 0xcb, 0xed, 0xbe, 0x3a, 0xa5, 0xbb, 0x73,
+ 0x28, 0x04, 0xc6, 0x2a, 0xfb, 0x3a, 0xc3,
+ 0xae, 0x42, 0x1f, 0x53, 0x6c, 0xb2, 0x76,
+ 0xb7, 0xe2, 0x88, 0xcb, 0x88, 0xcf, 0xf0,
+ 0x52, 0x81, 0xd3, 0xb2, 0x1f, 0x56, 0xe1,
+ 0xe1, 0x47, 0x93, 0x6f, 0x2b, 0x49, 0xaa,
+ 0x50, 0x99, 0x7a, 0xc4, 0x56, 0xb7, 0x13,
+ 0x80, 0xf4, 0x73, 0x88, 0xc7, 0x39, 0x83,
+ 0x67, 0xc7, 0xcc, 0xb2, 0x28, 0x7a, 0xd3,
+ 0xdc, 0x48, 0xea, 0x62, 0x0d, 0xf5, 0x5a,
+ 0x27, 0x96 ),
+ BIGINT ( 0xd4, 0x6b, 0x0a, 0x2e, 0x9f, 0xde, 0x4b,
+ 0x64, 0xfa, 0x6b, 0x37, 0x73, 0x66, 0x06,
+ 0xee, 0x04, 0xef, 0xe6, 0x3c, 0x7d, 0x57,
+ 0x22, 0x7f, 0x1f, 0x62, 0x1c, 0x7e, 0x20,
+ 0xda, 0x97, 0xd0, 0x27, 0x23, 0xf6, 0x77,
+ 0x5b, 0x49, 0x97, 0xe1, 0x65, 0x91, 0x13,
+ 0x93, 0xd6, 0x12, 0xc3, 0x66, 0x91, 0x76,
+ 0xe8, 0x47, 0x4c, 0x6a, 0x1b, 0xa2, 0x02,
+ 0xf8, 0x94, 0xaa, 0xe0, 0x1b, 0x0b, 0x17,
+ 0x86, 0x5e, 0xf5, 0x17, 0x23, 0xf5, 0x17,
+ 0x91, 0x6b, 0xd7, 0x2f, 0x5a, 0xfe, 0x8a,
+ 0x63, 0x28, 0x31, 0x1e, 0x09, 0x60, 0x29,
+ 0x5d, 0x55, 0xd8, 0x79, 0xeb, 0x78, 0x36,
+ 0x44, 0x69, 0xa4, 0x76, 0xa5, 0x35, 0x30,
+ 0xca, 0xc9, 0xf9, 0x62, 0xd7, 0x82, 0x13,
+ 0x56, 0xd0, 0x58, 0xfe, 0x16, 0x4b, 0xfb,
+ 0xa8, 0x4c, 0xb3, 0xd7, 0xcf, 0x5f, 0x93,
+ 0x9d, 0xc4, 0x11, 0xb4, 0xdd, 0xf8, 0x8f,
+ 0xe1, 0x11 ),
+ 0 );
+ bigint_is_geq_ok ( BIGINT ( 0xd4, 0x6b, 0x0a, 0x2e, 0x9f, 0xde, 0x4b,
+ 0x64, 0xfa, 0x6b, 0x37, 0x73, 0x66, 0x06,
+ 0xee, 0x04, 0xef, 0xe6, 0x3c, 0x7d, 0x57,
+ 0x22, 0x7f, 0x1f, 0x62, 0x1c, 0x7e, 0x20,
+ 0xda, 0x97, 0xd0, 0x27, 0x23, 0xf6, 0x77,
+ 0x5b, 0x49, 0x97, 0xe1, 0x65, 0x91, 0x13,
+ 0x93, 0xd6, 0x12, 0xc3, 0x66, 0x91, 0x76,
+ 0xe8, 0x47, 0x4c, 0x6a, 0x1b, 0xa2, 0x02,
+ 0xf8, 0x94, 0xaa, 0xe0, 0x1b, 0x0b, 0x17,
+ 0x86, 0x5e, 0xf5, 0x17, 0x23, 0xf5, 0x17,
+ 0x91, 0x6b, 0xd7, 0x2f, 0x5a, 0xfe, 0x8a,
+ 0x63, 0x28, 0x31, 0x1e, 0x09, 0x60, 0x29,
+ 0x5d, 0x55, 0xd8, 0x79, 0xeb, 0x78, 0x36,
+ 0x44, 0x69, 0xa4, 0x76, 0xa5, 0x35, 0x30,
+ 0xca, 0xc9, 0xf9, 0x62, 0xd7, 0x82, 0x13,
+ 0x56, 0xd0, 0x58, 0xfe, 0x16, 0x4b, 0xfb,
+ 0xa8, 0x4c, 0xb3, 0xd7, 0xcf, 0x5f, 0x93,
+ 0x9d, 0xc4, 0x11, 0xb4, 0xdd, 0xf8, 0x8f,
+ 0xe1, 0x11 ),
+ BIGINT ( 0x2a, 0x98, 0xfd, 0x87, 0x5d, 0x9f, 0xb4,
+ 0x8b, 0x5c, 0xcd, 0x5f, 0xcd, 0x53, 0xb3,
+ 0xd1, 0x81, 0x6a, 0x9c, 0x93, 0x66, 0x40,
+ 0xa7, 0x64, 0xe0, 0x8c, 0xec, 0x96, 0x63,
+ 0x4d, 0x29, 0xfa, 0xb1, 0x5d, 0x93, 0x2f,
+ 0xf9, 0x36, 0xea, 0x3b, 0xc1, 0xaf, 0x85,
+ 0xcb, 0xde, 0x2d, 0xc8, 0x48, 0x33, 0xce,
+ 0x7b, 0xa4, 0xa4, 0xda, 0x0f, 0xaa, 0x1b,
+ 0xcb, 0xed, 0xbe, 0x3a, 0xa5, 0xbb, 0x73,
+ 0x28, 0x04, 0xc6, 0x2a, 0xfb, 0x3a, 0xc3,
+ 0xae, 0x42, 0x1f, 0x53, 0x6c, 0xb2, 0x76,
+ 0xb7, 0xe2, 0x88, 0xcb, 0x88, 0xcf, 0xf0,
+ 0x52, 0x81, 0xd3, 0xb2, 0x1f, 0x56, 0xe1,
+ 0xe1, 0x47, 0x93, 0x6f, 0x2b, 0x49, 0xaa,
+ 0x50, 0x99, 0x7a, 0xc4, 0x56, 0xb7, 0x13,
+ 0x80, 0xf4, 0x73, 0x88, 0xc7, 0x39, 0x83,
+ 0x67, 0xc7, 0xcc, 0xb2, 0x28, 0x7a, 0xd3,
+ 0xdc, 0x48, 0xea, 0x62, 0x0d, 0xf5, 0x5a,
+ 0x27, 0x96 ),
+ 1 );
+ bigint_is_geq_ok ( BIGINT ( 0x2a, 0x98, 0xfd, 0x87, 0x5d, 0x9f, 0xb4,
+ 0x8b, 0x5c, 0xcd, 0x5f, 0xcd, 0x53, 0xb3,
+ 0xd1, 0x81, 0x6a, 0x9c, 0x93, 0x66, 0x40,
+ 0xa7, 0x64, 0xe0, 0x8c, 0xec, 0x96, 0x63,
+ 0x4d, 0x29, 0xfa, 0xb1, 0x5d, 0x93, 0x2f,
+ 0xf9, 0x36, 0xea, 0x3b, 0xc1, 0xaf, 0x85,
+ 0xcb, 0xde, 0x2d, 0xc8, 0x48, 0x33, 0xce,
+ 0x7b, 0xa4, 0xa4, 0xda, 0x0f, 0xaa, 0x1b,
+ 0xcb, 0xed, 0xbe, 0x3a, 0xa5, 0xbb, 0x73,
+ 0x28, 0x04, 0xc6, 0x2a, 0xfb, 0x3a, 0xc3,
+ 0xae, 0x42, 0x1f, 0x53, 0x6c, 0xb2, 0x76,
+ 0xb7, 0xe2, 0x88, 0xcb, 0x88, 0xcf, 0xf0,
+ 0x52, 0x81, 0xd3, 0xb2, 0x1f, 0x56, 0xe1,
+ 0xe1, 0x47, 0x93, 0x6f, 0x2b, 0x49, 0xaa,
+ 0x50, 0x99, 0x7a, 0xc4, 0x56, 0xb7, 0x13,
+ 0x80, 0xf4, 0x73, 0x88, 0xc7, 0x39, 0x83,
+ 0x67, 0xc7, 0xcc, 0xb2, 0x28, 0x7a, 0xd3,
+ 0xdc, 0x48, 0xea, 0x62, 0x0d, 0xf5, 0x5a,
+ 0x27, 0x96 ),
+ BIGINT ( 0x2a, 0x98, 0xfd, 0x87, 0x5d, 0x9f, 0xb4,
+ 0x8b, 0x5c, 0xcd, 0x5f, 0xcd, 0x53, 0xb3,
+ 0xd1, 0x81, 0x6a, 0x9c, 0x93, 0x66, 0x40,
+ 0xa7, 0x64, 0xe0, 0x8c, 0xec, 0x96, 0x63,
+ 0x4d, 0x29, 0xfa, 0xb1, 0x5d, 0x93, 0x2f,
+ 0xf9, 0x36, 0xea, 0x3b, 0xc1, 0xaf, 0x85,
+ 0xcb, 0xde, 0x2d, 0xc8, 0x48, 0x33, 0xce,
+ 0x7b, 0xa4, 0xa4, 0xda, 0x0f, 0xaa, 0x1b,
+ 0xcb, 0xed, 0xbe, 0x3a, 0xa5, 0xbb, 0x73,
+ 0x28, 0x04, 0xc6, 0x2a, 0xfb, 0x3a, 0xc3,
+ 0xae, 0x42, 0x1f, 0x53, 0x6c, 0xb2, 0x76,
+ 0xb7, 0xe2, 0x88, 0xcb, 0x88, 0xcf, 0xf0,
+ 0x52, 0x81, 0xd3, 0xb2, 0x1f, 0x56, 0xe1,
+ 0xe1, 0x47, 0x93, 0x6f, 0x2b, 0x49, 0xaa,
+ 0x50, 0x99, 0x7a, 0xc4, 0x56, 0xb7, 0x13,
+ 0x80, 0xf4, 0x73, 0x88, 0xc7, 0x39, 0x83,
+ 0x67, 0xc7, 0xcc, 0xb2, 0x28, 0x7a, 0xd3,
+ 0xdc, 0x48, 0xea, 0x62, 0x0d, 0xf5, 0x5a,
+ 0x27, 0x96 ),
+ 1 );
+ bigint_bit_is_set_ok ( BIGINT ( 0x37 ),
+ 0, 1 );
+ bigint_bit_is_set_ok ( BIGINT ( 0xe6, 0xcb ),
+ 0, 1 );
+ bigint_bit_is_set_ok ( BIGINT ( 0xd9, 0x0c, 0x5b ),
+ 0, 1 );
+ bigint_bit_is_set_ok ( BIGINT ( 0x8b, 0x56, 0x89, 0xaf ),
+ 0, 1 );
+ bigint_bit_is_set_ok ( BIGINT ( 0x25, 0xfc, 0xaf, 0xeb, 0x81, 0xc3,
+ 0xb8, 0x2f, 0xbb, 0xe3, 0x07, 0xb2,
+ 0xe2, 0x2a, 0xe2, 0x2d, 0xb4, 0x4d,
+ 0x6d, 0xec, 0x51, 0xa0, 0x2f ),
+ 0, 1 );
+ bigint_bit_is_set_ok ( BIGINT ( 0x25, 0xfc, 0xaf, 0xeb, 0x81, 0xc3,
+ 0xb8, 0x2f, 0xbb, 0xe3, 0x07, 0xb2,
+ 0xe2, 0x2a, 0xe2, 0x2d, 0xb4, 0x4d,
+ 0x6d, 0xec, 0x51, 0xa0, 0x2f ),
+ 45, 0 );
+ bigint_bit_is_set_ok ( BIGINT ( 0x88, 0x04, 0xec, 0xe6, 0xfb, 0x31,
+ 0x87, 0x43, 0xb2, 0x04, 0x9e, 0x09,
+ 0xba, 0x3e, 0x6d, 0x64, 0x1a, 0x85,
+ 0xb6, 0x46, 0x7d, 0x71, 0x3c, 0x06,
+ 0xd6, 0x40, 0x52, 0x39, 0x95, 0xa1,
+ 0x06, 0xff, 0x6a, 0x5c, 0xa3, 0x6d,
+ 0x4a, 0xc9, 0x77, 0x87, 0x75, 0x25,
+ 0x57, 0x65, 0x72, 0x73, 0x64, 0x7e,
+ 0xe9, 0x16, 0x17, 0xf3, 0x65, 0x3f,
+ 0xd5, 0xcc, 0xd7, 0xa2, 0xee, 0xe7,
+ 0x8d, 0x48, 0xd5, 0x7e, 0xdd, 0x59,
+ 0x4b, 0xf0, 0x96, 0x8b, 0x21, 0x65,
+ 0x04, 0x66, 0xc5, 0xff, 0x3e, 0x60,
+ 0xba, 0x28, 0x38, 0x7d, 0x9c, 0x09,
+ 0xd1, 0x8e, 0xac, 0x73, 0x8e, 0xf2,
+ 0x1e, 0xdf, 0x83, 0x6e, 0x54, 0xd5,
+ 0x34, 0xc1, 0xc6, 0xf9, 0x62, 0x2a,
+ 0x7d, 0xec, 0x47, 0xf2, 0xfc, 0xa2,
+ 0x10, 0x0a, 0x67, 0x1b, 0xc6, 0x11,
+ 0x9d, 0x68, 0x25, 0x8b, 0xb5, 0x9b,
+ 0x83, 0xf8, 0xa2, 0x11, 0xf5, 0xd4,
+ 0xcb, 0xe0 ),
+ 0, 0 );
+ bigint_bit_is_set_ok ( BIGINT ( 0x88, 0x04, 0xec, 0xe6, 0xfb, 0x31,
+ 0x87, 0x43, 0xb2, 0x04, 0x9e, 0x09,
+ 0xba, 0x3e, 0x6d, 0x64, 0x1a, 0x85,
+ 0xb6, 0x46, 0x7d, 0x71, 0x3c, 0x06,
+ 0xd6, 0x40, 0x52, 0x39, 0x95, 0xa1,
+ 0x06, 0xff, 0x6a, 0x5c, 0xa3, 0x6d,
+ 0x4a, 0xc9, 0x77, 0x87, 0x75, 0x25,
+ 0x57, 0x65, 0x72, 0x73, 0x64, 0x7e,
+ 0xe9, 0x16, 0x17, 0xf3, 0x65, 0x3f,
+ 0xd5, 0xcc, 0xd7, 0xa2, 0xee, 0xe7,
+ 0x8d, 0x48, 0xd5, 0x7e, 0xdd, 0x59,
+ 0x4b, 0xf0, 0x96, 0x8b, 0x21, 0x65,
+ 0x04, 0x66, 0xc5, 0xff, 0x3e, 0x60,
+ 0xba, 0x28, 0x38, 0x7d, 0x9c, 0x09,
+ 0xd1, 0x8e, 0xac, 0x73, 0x8e, 0xf2,
+ 0x1e, 0xdf, 0x83, 0x6e, 0x54, 0xd5,
+ 0x34, 0xc1, 0xc6, 0xf9, 0x62, 0x2a,
+ 0x7d, 0xec, 0x47, 0xf2, 0xfc, 0xa2,
+ 0x10, 0x0a, 0x67, 0x1b, 0xc6, 0x11,
+ 0x9d, 0x68, 0x25, 0x8b, 0xb5, 0x9b,
+ 0x83, 0xf8, 0xa2, 0x11, 0xf5, 0xd4,
+ 0xcb, 0xe0 ),
+ 45, 1 );
+ bigint_bit_is_set_ok ( BIGINT ( 0x88, 0x04, 0xec, 0xe6, 0xfb, 0x31,
+ 0x87, 0x43, 0xb2, 0x04, 0x9e, 0x09,
+ 0xba, 0x3e, 0x6d, 0x64, 0x1a, 0x85,
+ 0xb6, 0x46, 0x7d, 0x71, 0x3c, 0x06,
+ 0xd6, 0x40, 0x52, 0x39, 0x95, 0xa1,
+ 0x06, 0xff, 0x6a, 0x5c, 0xa3, 0x6d,
+ 0x4a, 0xc9, 0x77, 0x87, 0x75, 0x25,
+ 0x57, 0x65, 0x72, 0x73, 0x64, 0x7e,
+ 0xe9, 0x16, 0x17, 0xf3, 0x65, 0x3f,
+ 0xd5, 0xcc, 0xd7, 0xa2, 0xee, 0xe7,
+ 0x8d, 0x48, 0xd5, 0x7e, 0xdd, 0x59,
+ 0x4b, 0xf0, 0x96, 0x8b, 0x21, 0x65,
+ 0x04, 0x66, 0xc5, 0xff, 0x3e, 0x60,
+ 0xba, 0x28, 0x38, 0x7d, 0x9c, 0x09,
+ 0xd1, 0x8e, 0xac, 0x73, 0x8e, 0xf2,
+ 0x1e, 0xdf, 0x83, 0x6e, 0x54, 0xd5,
+ 0x34, 0xc1, 0xc6, 0xf9, 0x62, 0x2a,
+ 0x7d, 0xec, 0x47, 0xf2, 0xfc, 0xa2,
+ 0x10, 0x0a, 0x67, 0x1b, 0xc6, 0x11,
+ 0x9d, 0x68, 0x25, 0x8b, 0xb5, 0x9b,
+ 0x83, 0xf8, 0xa2, 0x11, 0xf5, 0xd4,
+ 0xcb, 0xe0 ),
+ 1013, 0 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x3a ),
+ 6 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x03 ),
+ 2 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x00 ),
+ 0 );
+ bigint_max_set_bit_ok ( BIGINT ( 0xff ),
+ 8 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x20, 0x30 ),
+ 14 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x10 ),
+ 5 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00 ),
+ 0 );
+ bigint_max_set_bit_ok ( BIGINT ( 0xff, 0xff ),
+ 16 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x06, 0xdb, 0x7a ),
+ 19 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00 ),
+ 0 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00 ),
+ 0 );
+ bigint_max_set_bit_ok ( BIGINT ( 0xff, 0xff, 0xff ),
+ 24 );
+ bigint_max_set_bit_ok ( BIGINT ( 0xee, 0xcb, 0x7b, 0xfd ),
+ 32 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x01, 0xdd ),
+ 9 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00 ),
+ 0 );
+ bigint_max_set_bit_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff ),
+ 32 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x32, 0x39, 0x96, 0x52, 0x10, 0x67,
+ 0x7e, 0x32, 0xfc, 0x4e, 0x56, 0xc3,
+ 0x68, 0x18, 0x76, 0x1a, 0xac, 0x0e,
+ 0x93, 0xee, 0x55, 0xc5, 0x6e ),
+ 182 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc8, 0xe6, 0x59 ),
+ 24 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00 ),
+ 0 );
+ bigint_max_set_bit_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff ),
+ 184 );
+ bigint_max_set_bit_ok ( BIGINT ( 0xcd, 0xb3, 0x22, 0x30, 0xdd, 0xa7,
+ 0xff, 0x37, 0xbf, 0xe3, 0x38, 0xf7,
+ 0xe1, 0x41, 0x73, 0xea, 0x3a, 0xfc,
+ 0x78, 0x9e, 0xfb, 0x4f, 0x85, 0xdc,
+ 0x1c, 0x40, 0x89, 0x6e, 0xda, 0xf9,
+ 0x9d, 0x6d, 0x12, 0x97, 0xb1, 0x80,
+ 0x2a, 0xeb, 0x91, 0xce, 0x3b, 0x83,
+ 0xb8, 0xa5, 0x3d, 0xce, 0x46, 0x56,
+ 0xb7, 0xd1, 0x28, 0xbc, 0x93, 0x4e,
+ 0x8c, 0x29, 0x6d, 0x2c, 0xcc, 0x58,
+ 0x49, 0x2f, 0x37, 0xa0, 0x08, 0x37,
+ 0x86, 0xdd, 0x38, 0x21, 0xa7, 0x57,
+ 0x37, 0xe3, 0xc5, 0xcc, 0x50, 0x11,
+ 0x1a, 0xe4, 0xea, 0xe7, 0x4d, 0x3c,
+ 0x37, 0x65, 0x78, 0xd1, 0xf6, 0xc3,
+ 0x94, 0x46, 0xd4, 0x0e, 0xd3, 0x9a,
+ 0x21, 0x8b, 0xa6, 0x54, 0xc0, 0xd2,
+ 0x88, 0x07, 0x24, 0xbf, 0x7d, 0x31,
+ 0xfd, 0x15, 0xa8, 0x92, 0x65, 0xe1,
+ 0x8d, 0xed, 0x70, 0x7b, 0x68, 0x0f,
+ 0xcc, 0x13, 0xb9, 0xb2, 0xdd, 0x3c,
+ 0x6a, 0x52 ),
+ 1024 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x66, 0xd9,
+ 0x91, 0x18, 0x6e, 0xd3, 0xff, 0x9b,
+ 0xdf, 0xf1, 0x9c, 0x7b, 0xf0, 0xa0,
+ 0xb9, 0xf5 ),
+ 127 );
+ bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00 ),
+ 0 );
+ bigint_max_set_bit_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff ),
+ 1024 );
+ bigint_multiply_ok ( BIGINT ( 0xf0 ),
+ BIGINT ( 0xeb ),
+ BIGINT ( 0xdc, 0x50 ) );
+ bigint_multiply_ok ( BIGINT ( 0xd7, 0x16 ),
+ BIGINT ( 0x88, 0xfb ),
+ BIGINT ( 0x73, 0x16, 0x92, 0x92 ) );
+ bigint_multiply_ok ( BIGINT ( 0xfe, 0xed, 0x1d ),
+ BIGINT ( 0x69, 0x9c, 0x03 ),
+ BIGINT ( 0x69, 0x2a, 0x9c, 0x5f, 0x73, 0x57 ) );
+ bigint_multiply_ok ( BIGINT ( 0x96, 0xe9, 0x6f, 0x81 ),
+ BIGINT ( 0x67, 0x3c, 0x5a, 0x16 ),
+ BIGINT ( 0x3c, 0xdb, 0x7f, 0xae, 0x12, 0x7e,
+ 0xef, 0x16 ) );
+ bigint_multiply_ok ( BIGINT ( 0xe8, 0x08, 0x0b, 0xe9, 0x29, 0x36,
+ 0xea, 0x51, 0x1d, 0x75, 0x1a, 0xd5,
+ 0xba, 0xc6, 0xa0, 0xf3, 0x48, 0x5c,
+ 0xdf, 0x42, 0xdf, 0x28, 0x38 ),
+ BIGINT ( 0x22, 0x07, 0x41, 0x54, 0x4e, 0xf9,
+ 0x90, 0xa8, 0xaf, 0xba, 0xf6, 0xb0,
+ 0x35, 0x7e, 0x98, 0xef, 0x2c, 0x31,
+ 0xc9, 0xa7, 0x25, 0x74, 0x8d ),
+ BIGINT ( 0x1e, 0xd7, 0xa5, 0x03, 0xc0, 0x18,
+ 0x2e, 0x29, 0xb1, 0x3e, 0x96, 0x71,
+ 0x90, 0xa5, 0x6d, 0x43, 0x58, 0xf7,
+ 0x22, 0x80, 0x0b, 0x21, 0xc6, 0x70,
+ 0x90, 0x1c, 0xa8, 0x85, 0x87, 0xaf,
+ 0xd7, 0xdd, 0x27, 0x69, 0xaf, 0x20,
+ 0xa0, 0x2d, 0x43, 0x5d, 0xda, 0xba,
+ 0x4b, 0x3a, 0x86, 0xd8 ) );
+ bigint_multiply_ok ( BIGINT ( 0xa2, 0x0f, 0xc6, 0x08, 0x0a, 0x01,
+ 0x19, 0x42, 0x0e, 0xaa, 0x5c, 0xae,
+ 0x4f, 0x4e, 0xb0, 0xad, 0xb2, 0xe8,
+ 0xee, 0xd5, 0x65, 0xec, 0x5a, 0xda,
+ 0xc0, 0xba, 0x78, 0xa8, 0x0f, 0x15,
+ 0x39, 0xd7, 0x7a, 0x10, 0xc2, 0xa7,
+ 0xec, 0x44, 0xac, 0xad, 0x39, 0x04,
+ 0x2e, 0x66, 0x54, 0x70, 0x57, 0xee,
+ 0xf6, 0x97, 0x19, 0x71, 0x16, 0xf9,
+ 0xbb, 0x2e, 0x84, 0x09, 0x6e, 0x9a,
+ 0x3b, 0x16, 0xb2, 0x65, 0x74, 0x50,
+ 0x19, 0xd1, 0xe9, 0x95, 0xa0, 0x7b,
+ 0x33, 0xb5, 0xac, 0x7c, 0x9e, 0xd4,
+ 0x68, 0x0d, 0xc9, 0xe4, 0x03, 0x86,
+ 0x1a, 0xa3, 0x42, 0x33, 0x28, 0x14,
+ 0x12, 0x7d, 0x5a, 0xd9, 0x30, 0x18,
+ 0x0a, 0xf4, 0x0c, 0x96, 0x58, 0xc9,
+ 0xb5, 0x37, 0xdb, 0x49, 0xdc, 0x01,
+ 0x4a, 0xcb, 0x6d, 0x87, 0x52, 0xf6,
+ 0xae, 0xa7, 0x71, 0x31, 0x9a, 0x1a,
+ 0xe2, 0x1c, 0x87, 0x51, 0xc9, 0xeb,
+ 0x70, 0x71 ),
+ BIGINT ( 0x7c, 0xdd, 0x2f, 0x5d, 0x27, 0xfe,
+ 0xca, 0x70, 0x96, 0xc3, 0xb1, 0x1f,
+ 0xac, 0xa9, 0x3a, 0xdc, 0xcd, 0xbc,
+ 0x58, 0xb4, 0xde, 0xe7, 0xe5, 0x34,
+ 0x1a, 0xc0, 0xb9, 0x46, 0xf7, 0x52,
+ 0x76, 0x23, 0xe8, 0xe9, 0x92, 0xa1,
+ 0x86, 0x3c, 0x6f, 0xf1, 0x22, 0xf4,
+ 0x72, 0xb1, 0xde, 0xd3, 0x8f, 0x11,
+ 0x9e, 0x52, 0xe5, 0x81, 0x54, 0xe9,
+ 0xa7, 0x72, 0x3f, 0x3e, 0xa0, 0x80,
+ 0xbb, 0xae, 0x0e, 0x30, 0x6a, 0x11,
+ 0x91, 0x11, 0x3b, 0x3f, 0x44, 0x1f,
+ 0x8d, 0x4d, 0xea, 0xdd, 0x09, 0x95,
+ 0x9d, 0x02, 0xa6, 0x6d, 0x3b, 0x08,
+ 0x40, 0x8d, 0xb4, 0x4b, 0x05, 0x74,
+ 0x8c, 0x1f, 0xaa, 0x61, 0x6f, 0x0e,
+ 0xcc, 0xcf, 0xe0, 0x81, 0x03, 0xe4,
+ 0x9b, 0x11, 0xd9, 0xab, 0xf3, 0x24,
+ 0xe2, 0x3b, 0xe0, 0x05, 0x60, 0x65,
+ 0x16, 0xc6, 0x2e, 0x83, 0xa0, 0x98,
+ 0x8e, 0x11, 0x05, 0x00, 0xe4, 0x3f,
+ 0x7e, 0x65 ),
+ BIGINT ( 0x4f, 0x0b, 0xa9, 0x85, 0xb8, 0x31,
+ 0x48, 0xea, 0x11, 0x44, 0xaf, 0x2d,
+ 0xed, 0x1a, 0x76, 0x45, 0xac, 0x87,
+ 0x0c, 0xf3, 0xd7, 0xc4, 0x8e, 0x5c,
+ 0xd7, 0xdf, 0x28, 0x74, 0xa6, 0x40,
+ 0xe4, 0x6b, 0x5b, 0x19, 0x36, 0x37,
+ 0x9c, 0xcd, 0x43, 0x76, 0x15, 0x00,
+ 0x5d, 0x23, 0xa2, 0x8a, 0x53, 0x25,
+ 0xbf, 0x18, 0xda, 0xe6, 0x09, 0xdf,
+ 0xaa, 0xeb, 0x9a, 0x82, 0x01, 0x14,
+ 0x2b, 0x20, 0x2b, 0xb6, 0x22, 0x62,
+ 0x6b, 0xcc, 0xd4, 0xc9, 0x02, 0x67,
+ 0x95, 0x43, 0x75, 0x4e, 0x97, 0x4e,
+ 0xec, 0x04, 0xde, 0x29, 0x0a, 0xef,
+ 0xf7, 0xc1, 0x72, 0x8c, 0x64, 0x38,
+ 0x16, 0x47, 0x9f, 0x16, 0x0c, 0xa5,
+ 0x79, 0x6b, 0xea, 0x2e, 0x4c, 0x3d,
+ 0x0c, 0xe6, 0x57, 0x51, 0x65, 0xa5,
+ 0x3b, 0xca, 0xae, 0x54, 0x0c, 0x67,
+ 0xf8, 0x23, 0x00, 0xc9, 0x8d, 0xe6,
+ 0x16, 0x91, 0x19, 0xb3, 0x5b, 0x68,
+ 0x7b, 0xf2, 0xe2, 0x5d, 0x69, 0x48,
+ 0x3f, 0x2b, 0xa0, 0x4f, 0x7c, 0x3c,
+ 0x26, 0xf9, 0xd9, 0xfd, 0x3d, 0x5d,
+ 0xd6, 0x05, 0x00, 0xd8, 0xdf, 0x5a,
+ 0x56, 0x8f, 0x16, 0x68, 0x4f, 0x15,
+ 0x19, 0x9d, 0xd7, 0x11, 0x51, 0x7d,
+ 0x73, 0x5c, 0xd4, 0xd5, 0xb4, 0xc7,
+ 0x42, 0xe3, 0xee, 0xf1, 0x67, 0xd6,
+ 0x69, 0x72, 0x04, 0x4b, 0x88, 0x3d,
+ 0x05, 0xd8, 0x1e, 0x50, 0xcb, 0xce,
+ 0x39, 0x19, 0x42, 0xb6, 0xa7, 0xf3,
+ 0xba, 0x78, 0x90, 0xd2, 0x09, 0x05,
+ 0x87, 0xf8, 0xc0, 0x9c, 0x47, 0xff,
+ 0xbf, 0xaa, 0x21, 0x8d, 0x81, 0x86,
+ 0xcd, 0x58, 0xdf, 0x30, 0xf1, 0xd1,
+ 0x60, 0x53, 0x85, 0x40, 0xbf, 0x14,
+ 0x3e, 0xdc, 0x9e, 0x9e, 0xc4, 0xc7,
+ 0x48, 0xa0, 0x83, 0xe0, 0x99, 0x8b,
+ 0x43, 0xf8, 0x52, 0x8a, 0x15, 0x88,
+ 0x89, 0x83, 0x7d, 0x71, 0xbb, 0x62,
+ 0x12, 0x7a, 0x23, 0x85, 0x3a, 0xbb,
+ 0xdb, 0x09, 0xfa, 0x95 ) );
+ bigint_multiply_ok ( BIGINT ( 0xff ),
+ BIGINT ( 0xff ),
+ BIGINT ( 0xfe, 0x01 ) );
+ bigint_multiply_ok ( BIGINT ( 0xff, 0xff ),
+ BIGINT ( 0xff, 0xff ),
+ BIGINT ( 0xff, 0xfe, 0x00, 0x01 ) );
+ bigint_multiply_ok ( BIGINT ( 0xff, 0xff, 0xff ),
+ BIGINT ( 0xff, 0xff, 0xff ),
+ BIGINT ( 0xff, 0xff, 0xfe, 0x00, 0x00, 0x01 ) );
+ bigint_multiply_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff ),
+ BIGINT ( 0xff, 0xff, 0xff, 0xff ),
+ BIGINT ( 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00,
+ 0x00, 0x01 ) );
+ bigint_multiply_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff ),
+ BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff ),
+ BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01 ) );
+ bigint_multiply_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff ),
+ BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff ),
+ BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01 ) );
+ bigint_mod_multiply_ok ( BIGINT ( 0x37 ),
+ BIGINT ( 0x67 ),
+ BIGINT ( 0x3f ),
+ BIGINT ( 0x3a ) );
+ bigint_mod_multiply_ok ( BIGINT ( 0x45, 0x94 ),
+ BIGINT ( 0xbd, 0xd2 ),
+ BIGINT ( 0xca, 0xc7 ),
+ BIGINT ( 0xac, 0xc1 ) );
+ bigint_mod_multiply_ok ( BIGINT ( 0x8e, 0xcd, 0x74 ),
+ BIGINT ( 0xe2, 0xf1, 0xea ),
+ BIGINT ( 0x59, 0x51, 0x53 ),
+ BIGINT ( 0x22, 0xdd, 0x1c ) );
+ bigint_mod_multiply_ok ( BIGINT ( 0xc2, 0xa8, 0x40, 0x6f ),
+ BIGINT ( 0x29, 0xd7, 0xf4, 0x77 ),
+ BIGINT ( 0xbb, 0xbd, 0xdb, 0x3d ),
+ BIGINT ( 0x8f, 0x39, 0xd0, 0x47 ) );
+ bigint_mod_multiply_ok ( BIGINT ( 0x2e, 0xcb, 0x74, 0x7c, 0x64, 0x60,
+ 0xb3, 0x44, 0xf3, 0x23, 0x49, 0x4a,
+ 0xc6, 0xb6, 0xbf, 0xea, 0x80, 0xd8,
+ 0x34, 0xc5, 0x54, 0x22, 0x09 ),
+ BIGINT ( 0x61, 0x2c, 0x5a, 0xc5, 0xde, 0x07,
+ 0x65, 0x8e, 0xab, 0x88, 0x1a, 0x2e,
+ 0x7a, 0x95, 0x17, 0xe3, 0x3b, 0x17,
+ 0xe4, 0x21, 0xb0, 0xb4, 0x57 ),
+ BIGINT ( 0x8e, 0x46, 0xa5, 0x87, 0x7b, 0x7f,
+ 0xc4, 0xd7, 0x31, 0xb1, 0x94, 0xe7,
+ 0xe7, 0x1c, 0x7e, 0x7a, 0xc2, 0x6c,
+ 0xce, 0xcb, 0xc8, 0x5d, 0x70 ),
+ BIGINT ( 0x1e, 0xd1, 0x5b, 0x3d, 0x1d, 0x17,
+ 0x7c, 0x31, 0x95, 0x13, 0x1b, 0xd8,
+ 0xee, 0x0a, 0xb0, 0xe1, 0x5b, 0x13,
+ 0xad, 0x83, 0xe9, 0xf8, 0x7f ) );
+ bigint_mod_multiply_ok ( BIGINT ( 0x56, 0x37, 0xab, 0x07, 0x8b, 0x25,
+ 0xa7, 0xc2, 0x50, 0x30, 0x43, 0xfc,
+ 0x63, 0x8b, 0xdf, 0x84, 0x68, 0x85,
+ 0xca, 0xce, 0x44, 0x5c, 0xb1, 0x14,
+ 0xa4, 0xb5, 0xba, 0x43, 0xe0, 0x31,
+ 0x45, 0x6b, 0x82, 0xa9, 0x0b, 0x9e,
+ 0x3a, 0xb0, 0x39, 0x09, 0x2a, 0x68,
+ 0x2e, 0x0f, 0x09, 0x54, 0x47, 0x04,
+ 0xdb, 0xcf, 0x4a, 0x3a, 0x2d, 0x7b,
+ 0x7d, 0x50, 0xa4, 0xc5, 0xeb, 0x13,
+ 0xdd, 0x49, 0x61, 0x7d, 0x18, 0xa1,
+ 0x0d, 0x6b, 0x58, 0xba, 0x9f, 0x7c,
+ 0x81, 0x34, 0x9e, 0xf9, 0x9c, 0x9e,
+ 0x28, 0xa8, 0x1c, 0x15, 0x16, 0x20,
+ 0x3c, 0x0a, 0xb1, 0x11, 0x06, 0x93,
+ 0xbc, 0xd8, 0x4e, 0x49, 0xae, 0x7b,
+ 0xb4, 0x02, 0x8b, 0x1c, 0x5b, 0x18,
+ 0xb4, 0xac, 0x7f, 0xdd, 0x70, 0xef,
+ 0x87, 0xac, 0x1b, 0xac, 0x25, 0xa3,
+ 0xc9, 0xa7, 0x3a, 0xc5, 0x76, 0x68,
+ 0x09, 0x1f, 0xa1, 0x48, 0x53, 0xb6,
+ 0x13, 0xac ),
+ BIGINT ( 0xef, 0x5c, 0x1f, 0x1a, 0x44, 0x64,
+ 0x66, 0xcf, 0xdd, 0x3f, 0x0b, 0x27,
+ 0x81, 0xa7, 0x91, 0x7a, 0x35, 0x7b,
+ 0x0f, 0x46, 0x5e, 0xca, 0xbf, 0xf8,
+ 0x50, 0x5e, 0x99, 0x7c, 0xc6, 0x64,
+ 0x43, 0x00, 0x9f, 0xb2, 0xda, 0xfa,
+ 0x42, 0x15, 0x9c, 0xa3, 0xd6, 0xc8,
+ 0x64, 0xa7, 0x65, 0x4a, 0x98, 0xf7,
+ 0xb3, 0x96, 0x5f, 0x42, 0xf9, 0x73,
+ 0xe1, 0x75, 0xc3, 0xc4, 0x0b, 0x5d,
+ 0x5f, 0xf3, 0x04, 0x8a, 0xee, 0x59,
+ 0xa6, 0x1b, 0x06, 0x38, 0x0b, 0xa2,
+ 0x9f, 0xb4, 0x4f, 0x6d, 0x50, 0x5e,
+ 0x37, 0x37, 0x21, 0x83, 0x9d, 0xa3,
+ 0x12, 0x16, 0x4d, 0xab, 0x36, 0x51,
+ 0x21, 0xb1, 0x74, 0x66, 0x40, 0x9a,
+ 0xd3, 0x72, 0xcc, 0x18, 0x40, 0x53,
+ 0x89, 0xff, 0xd7, 0x00, 0x8d, 0x7e,
+ 0x93, 0x81, 0xdb, 0x29, 0xb6, 0xd7,
+ 0x23, 0x2b, 0x67, 0x2f, 0x11, 0x98,
+ 0x49, 0x87, 0x2f, 0x46, 0xb7, 0x33,
+ 0x6d, 0x12 ),
+ BIGINT ( 0x67, 0x7a, 0x17, 0x6a, 0xd2, 0xf8,
+ 0x49, 0xfb, 0x7c, 0x95, 0x25, 0x54,
+ 0xf0, 0xab, 0x5b, 0xb3, 0x0e, 0x01,
+ 0xab, 0xd3, 0x65, 0x6f, 0x7e, 0x18,
+ 0x05, 0xed, 0x9b, 0xc4, 0x90, 0x6c,
+ 0xd0, 0x6d, 0x94, 0x79, 0x28, 0xd6,
+ 0x24, 0x77, 0x9a, 0x08, 0xd2, 0x2f,
+ 0x7c, 0x2d, 0xa0, 0x0c, 0x14, 0xbe,
+ 0x7b, 0xee, 0x9e, 0x48, 0x88, 0x3c,
+ 0x8f, 0x9f, 0xb9, 0x7a, 0xcb, 0x98,
+ 0x76, 0x61, 0x0d, 0xee, 0xa2, 0x42,
+ 0x67, 0x1b, 0x2c, 0x42, 0x8f, 0x41,
+ 0xcc, 0x78, 0xba, 0xba, 0xaa, 0xa2,
+ 0x92, 0xb0, 0x6e, 0x0c, 0x4e, 0xe1,
+ 0xa5, 0x13, 0x7d, 0x8a, 0x8f, 0x81,
+ 0x95, 0x8a, 0xdf, 0x57, 0x93, 0x88,
+ 0x27, 0x4f, 0x1a, 0x59, 0xa4, 0x74,
+ 0x22, 0xa9, 0x78, 0xe5, 0xed, 0xb1,
+ 0x09, 0x26, 0x59, 0xde, 0x88, 0x21,
+ 0x8d, 0xa2, 0xa8, 0x58, 0x10, 0x7b,
+ 0x65, 0x96, 0xbf, 0x69, 0x3b, 0xc5,
+ 0x55, 0xf8 ),
+ BIGINT ( 0x15, 0xf7, 0x00, 0xeb, 0xc7, 0x5a,
+ 0x6f, 0xf0, 0x50, 0xf3, 0x21, 0x8a,
+ 0x8e, 0xa6, 0xf6, 0x67, 0x56, 0x7d,
+ 0x07, 0x45, 0x89, 0xdb, 0xd7, 0x7e,
+ 0x9e, 0x28, 0x7f, 0xfb, 0xed, 0xca,
+ 0x2c, 0xbf, 0x47, 0x77, 0x99, 0x95,
+ 0xf3, 0xd6, 0x9d, 0xc5, 0x57, 0x81,
+ 0x7f, 0x97, 0xf2, 0x6b, 0x24, 0xee,
+ 0xce, 0xc5, 0x9b, 0xe6, 0x42, 0x2d,
+ 0x37, 0xb7, 0xeb, 0x3d, 0xb5, 0xf7,
+ 0x1e, 0x86, 0xc2, 0x40, 0x44, 0xc9,
+ 0x85, 0x5a, 0x1a, 0xc0, 0xac, 0x9e,
+ 0x78, 0x69, 0x00, 0x7b, 0x93, 0x65,
+ 0xd7, 0x7f, 0x0c, 0xd6, 0xba, 0x4f,
+ 0x06, 0x00, 0x61, 0x05, 0xb2, 0x44,
+ 0xb4, 0xe7, 0xbb, 0x3b, 0x96, 0xb0,
+ 0x6d, 0xe8, 0x43, 0xd2, 0x03, 0xb7,
+ 0x0a, 0xc4, 0x6d, 0x30, 0xd8, 0xd5,
+ 0xe6, 0x54, 0x65, 0xdd, 0xa9, 0x1b,
+ 0x50, 0xc0, 0xb9, 0x95, 0xb0, 0x7d,
+ 0x7c, 0xca, 0x63, 0xf8, 0x72, 0xbe,
+ 0x3b, 0x00 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xcd ),
+ BIGINT ( 0xbb ),
+ BIGINT ( 0x25 ),
+ BIGINT ( 0xab ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xc4 ),
+ BIGINT ( 0xe9 ),
+ BIGINT ( 0x02, 0x4c ),
+ BIGINT ( 0x7e ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xcb ),
+ BIGINT ( 0xde ),
+ BIGINT ( 0xbd, 0x73, 0xbf ),
+ BIGINT ( 0x17 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x17 ),
+ BIGINT ( 0xb9 ),
+ BIGINT ( 0x39, 0x68, 0xba, 0x7d ),
+ BIGINT ( 0x17 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x2e ),
+ BIGINT ( 0xb7 ),
+ BIGINT ( 0x39, 0x07, 0x1b, 0x49, 0x5b, 0xea,
+ 0xf2, 0x61, 0x75, 0x94, 0x60, 0x86,
+ 0x73, 0xd0, 0xeb, 0x11, 0x08, 0x19,
+ 0x90, 0x19, 0xe0, 0xed, 0x2a ),
+ BIGINT ( 0x19 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x59 ),
+ BIGINT ( 0xce ),
+ BIGINT ( 0xdf, 0xbc, 0x0d, 0x0c, 0x09, 0xeb,
+ 0xf8, 0xcf, 0xdb, 0xb6, 0x00, 0xa3,
+ 0x9e, 0xc3, 0x6c, 0x8d, 0xf1, 0xc3,
+ 0x03, 0x36, 0xaa, 0xd4, 0x22, 0x7c,
+ 0x20, 0x7b, 0xa9, 0x9a, 0x01, 0xe4,
+ 0xf2, 0x50, 0x42, 0x29, 0x68, 0x7a,
+ 0xa6, 0x2c, 0xdf, 0xb6, 0x51, 0xa9,
+ 0x73, 0x10, 0x98, 0x37, 0x69, 0xb3,
+ 0x21, 0x49, 0x6d, 0xcc, 0x80, 0xfa,
+ 0x7e, 0x12, 0xe4, 0x9c, 0xc2, 0xbb,
+ 0xe3, 0xa3, 0x10, 0x3f, 0xba, 0x99,
+ 0x22, 0x79, 0x71, 0x39, 0x96, 0x7b,
+ 0x1a, 0x89, 0xdc, 0xda, 0x43, 0x52,
+ 0x50, 0x7b, 0xe3, 0x8c, 0xd3, 0xc0,
+ 0xf5, 0x7d, 0xfc, 0x80, 0x71, 0x6e,
+ 0xaf, 0x5c, 0xd0, 0x14, 0xc0, 0x60,
+ 0x24, 0xa8, 0x9a, 0x8a, 0x54, 0x4a,
+ 0x6f, 0x42, 0x7a, 0x14, 0x14, 0x25,
+ 0xd5, 0x22, 0x08, 0x8f, 0xd9, 0xdb,
+ 0xd4, 0x0f, 0x14, 0xf4, 0x3b, 0x26,
+ 0x0e, 0xb6, 0x72, 0xd7, 0x03, 0xd5,
+ 0xf0, 0x0e ),
+ BIGINT ( 0xa9 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x7f, 0x30 ),
+ BIGINT ( 0x73, 0x74 ),
+ BIGINT ( 0x75 ),
+ BIGINT ( 0x4b, 0xe8 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x04, 0x6c ),
+ BIGINT ( 0x99, 0x04 ),
+ BIGINT ( 0x33, 0xd2 ),
+ BIGINT ( 0x86, 0x74 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xca, 0x88 ),
+ BIGINT ( 0xdc, 0x60 ),
+ BIGINT ( 0x7e, 0x76, 0x79 ),
+ BIGINT ( 0x42, 0x40 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x68, 0x97 ),
+ BIGINT ( 0x52, 0x8b ),
+ BIGINT ( 0x4f, 0x7f, 0xe7, 0xda ),
+ BIGINT ( 0x22, 0x77 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xbd, 0x14 ),
+ BIGINT ( 0x9e, 0xfc ),
+ BIGINT ( 0x23, 0xf7, 0xd0, 0xa1, 0x9e, 0x9b,
+ 0x05, 0xd2, 0x44, 0x24, 0x4f, 0x3f,
+ 0x83, 0xcc, 0x49, 0x70, 0xa5, 0x0d,
+ 0xfc, 0xa7, 0x43, 0xf3, 0x3e ),
+ BIGINT ( 0x1a, 0xc8 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x46, 0x3e ),
+ BIGINT ( 0xb8, 0xde ),
+ BIGINT ( 0xa9, 0xc0, 0xdc, 0x45, 0x65, 0x0d,
+ 0xa5, 0x56, 0x70, 0x4c, 0xf1, 0xda,
+ 0xab, 0x64, 0xc2, 0x04, 0xf6, 0x32,
+ 0x20, 0x68, 0x31, 0x5f, 0x9a, 0x00,
+ 0x0f, 0x7b, 0x24, 0x33, 0xdf, 0xaf,
+ 0xfe, 0x03, 0x1e, 0x4a, 0xa1, 0xf8,
+ 0x45, 0x8d, 0x5a, 0x7d, 0x12, 0x58,
+ 0x00, 0x6d, 0xba, 0x79, 0x9f, 0xe1,
+ 0xa1, 0xfc, 0x1f, 0xb9, 0xf3, 0xa7,
+ 0x07, 0xf5, 0xfe, 0xd6, 0xa1, 0xba,
+ 0xda, 0x63, 0xef, 0x39, 0x8e, 0xb7,
+ 0x48, 0xa8, 0x81, 0x86, 0xb1, 0x22,
+ 0x14, 0x9f, 0x9e, 0xac, 0x69, 0xf7,
+ 0xae, 0x1f, 0xf2, 0x99, 0x41, 0xb7,
+ 0x37, 0xa7, 0xbc, 0x42, 0xf2, 0x45,
+ 0x43, 0xf2, 0x2a, 0xef, 0xc2, 0x83,
+ 0xd5, 0x32, 0x6e, 0xfa, 0x49, 0x1c,
+ 0x94, 0x9c, 0xc2, 0xc5, 0xad, 0x28,
+ 0x53, 0x1c, 0x11, 0xc4, 0x1c, 0x78,
+ 0x8f, 0x13, 0xdc, 0xb3, 0x2a, 0x63,
+ 0xfd, 0x1f, 0x89, 0x9b, 0x0c, 0x31,
+ 0x92, 0x73 ),
+ BIGINT ( 0x7b, 0x8a ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xf3, 0xc3, 0xab ),
+ BIGINT ( 0xd0, 0x7e, 0xd0 ),
+ BIGINT ( 0xf6 ),
+ BIGINT ( 0x1f, 0xb3, 0x09 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x13, 0xec, 0xf6 ),
+ BIGINT ( 0x87, 0x1a, 0x9a ),
+ BIGINT ( 0x03, 0xf3 ),
+ BIGINT ( 0x15, 0xe9, 0x8e ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x5a, 0x96, 0xe5 ),
+ BIGINT ( 0x56, 0x4a, 0xd1 ),
+ BIGINT ( 0x89, 0x62, 0x8e ),
+ BIGINT ( 0x34, 0xb8, 0xaa ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x84, 0x7c, 0xbd ),
+ BIGINT ( 0x3c, 0x80, 0x0a ),
+ BIGINT ( 0x5e, 0x52, 0x9d, 0xba ),
+ BIGINT ( 0x04, 0xcb, 0x4f ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x50, 0x01, 0x51 ),
+ BIGINT ( 0x02, 0xe6, 0x96 ),
+ BIGINT ( 0x34, 0x0c, 0x7e, 0xbf, 0x27, 0x23,
+ 0x46, 0x92, 0x1c, 0xca, 0x91, 0xab,
+ 0x50, 0x2c, 0x3a, 0x64, 0xc8, 0x4a,
+ 0x75, 0xd6, 0xe2, 0xde, 0x31 ),
+ BIGINT ( 0x02, 0x16, 0x05 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x5e, 0x47, 0xd8 ),
+ BIGINT ( 0x26, 0xd1, 0xb6 ),
+ BIGINT ( 0x49, 0x61, 0x84, 0x7a, 0xa9, 0xfb,
+ 0x93, 0x45, 0xe4, 0xfa, 0x53, 0x60,
+ 0x73, 0x98, 0x5a, 0x17, 0xe7, 0x77,
+ 0x2d, 0xcd, 0x97, 0xf4, 0xc0, 0x34,
+ 0x46, 0xfa, 0xbd, 0x21, 0xdf, 0xa5,
+ 0xa0, 0x12, 0x38, 0x7c, 0xbd, 0xd9,
+ 0xcd, 0xbc, 0xde, 0x29, 0xa5, 0x13,
+ 0xa8, 0xf0, 0xf6, 0x88, 0xc6, 0x31,
+ 0xed, 0x90, 0x19, 0x11, 0x7d, 0xe1,
+ 0x0e, 0x81, 0x98, 0x8e, 0x98, 0x86,
+ 0xde, 0x2a, 0x4c, 0xad, 0xff, 0x57,
+ 0x12, 0xbc, 0x4b, 0xaf, 0x21, 0xde,
+ 0xca, 0x3a, 0x25, 0xd7, 0x98, 0xe3,
+ 0x25, 0xbc, 0x17, 0x74, 0x0b, 0x9c,
+ 0x53, 0xe1, 0x1a, 0xec, 0x9a, 0x5a,
+ 0xdc, 0x68, 0xdf, 0xad, 0xd6, 0x71,
+ 0x6b, 0x5b, 0x8b, 0x85, 0xbb, 0xe5,
+ 0xd5, 0x14, 0x4c, 0x30, 0x27, 0x68,
+ 0xd1, 0xf7, 0x58, 0x34, 0x4c, 0xe1,
+ 0x71, 0xde, 0x7b, 0x8d, 0xa2, 0xe6,
+ 0x0a, 0x44, 0x22, 0x26, 0x5a, 0x70,
+ 0xbb, 0x68 ),
+ BIGINT ( 0x18, 0x36, 0x96 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xc7, 0x4a, 0xf0, 0x48 ),
+ BIGINT ( 0x5d, 0x27, 0x07, 0x54 ),
+ BIGINT ( 0x4a ),
+ BIGINT ( 0x48, 0x68, 0x7b, 0xe0 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xb4, 0x89, 0xc9, 0x5b ),
+ BIGINT ( 0x7c, 0xd7, 0xc7, 0xff ),
+ BIGINT ( 0xc6, 0x9c ),
+ BIGINT ( 0x0b, 0x2d, 0xf8, 0xf7 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xea, 0x72, 0x43, 0xfe ),
+ BIGINT ( 0xfc, 0x57, 0x2d, 0x47 ),
+ BIGINT ( 0x60, 0x01, 0x2c ),
+ BIGINT ( 0x12, 0x01, 0xe3, 0xf5 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x81, 0x7f, 0x27, 0x94 ),
+ BIGINT ( 0x17, 0x21, 0x67, 0xab ),
+ BIGINT ( 0x50, 0x19, 0x12, 0x52 ),
+ BIGINT ( 0x05, 0x17, 0x6b, 0x13 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x38, 0xab, 0xd4, 0xec ),
+ BIGINT ( 0x0c, 0x2a, 0x56, 0x38 ),
+ BIGINT ( 0x2f, 0x85, 0x85, 0x57, 0xf6, 0xde,
+ 0x24, 0xb4, 0x28, 0x3c, 0x5a, 0x3c,
+ 0x0b, 0x12, 0x85, 0x85, 0x85, 0x98,
+ 0x46, 0x5b, 0x9c, 0x52, 0x3a ),
+ BIGINT ( 0x02, 0xe6, 0x6a, 0x70 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xa6, 0x35, 0xc0, 0x6f ),
+ BIGINT ( 0x23, 0xac, 0x78, 0x72 ),
+ BIGINT ( 0x6a, 0x07, 0x80, 0xbf, 0x1b, 0xa5,
+ 0xf8, 0x0b, 0x90, 0x06, 0xa4, 0xa5,
+ 0x44, 0x13, 0xba, 0x4b, 0xb3, 0xce,
+ 0x9f, 0x55, 0x42, 0x56, 0xc3, 0x30,
+ 0x82, 0x85, 0x5a, 0x3b, 0xae, 0x88,
+ 0x92, 0x4e, 0x3c, 0x37, 0xf6, 0x80,
+ 0x4c, 0x03, 0x3c, 0x1e, 0x2c, 0x17,
+ 0xef, 0x9d, 0xd7, 0x6f, 0xdc, 0xbb,
+ 0x42, 0x42, 0xa1, 0x7f, 0x97, 0x66,
+ 0xcd, 0xc8, 0x8a, 0x7c, 0xc6, 0x70,
+ 0x61, 0x54, 0x82, 0xd0, 0xd0, 0x8b,
+ 0xd5, 0x4f, 0x57, 0x7b, 0x8e, 0xab,
+ 0xdc, 0xbf, 0x8e, 0x85, 0x94, 0x83,
+ 0x8a, 0xb3, 0x72, 0x69, 0x2d, 0x51,
+ 0xdd, 0x86, 0x1e, 0x58, 0xb8, 0x00,
+ 0xe2, 0x5e, 0xa7, 0xef, 0x6a, 0x6a,
+ 0xb0, 0x10, 0x3d, 0x53, 0xfe, 0x23,
+ 0x51, 0xc0, 0x51, 0xed, 0x1f, 0x02,
+ 0x4b, 0x73, 0x17, 0x59, 0xfa, 0xb9,
+ 0xa8, 0x05, 0xa7, 0x79, 0xc3, 0xc9,
+ 0x4c, 0x2d, 0x58, 0x59, 0x10, 0x99,
+ 0x71, 0xe6 ),
+ BIGINT ( 0x01, 0x63, 0xd0, 0x07 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xff, 0x2a, 0x37, 0x04, 0xd4, 0x08,
+ 0x9f, 0xf5, 0xac, 0x29, 0x7f, 0x4b,
+ 0x93, 0x86, 0x02, 0x26, 0xac, 0x29,
+ 0xa8, 0xf9, 0x77, 0x91, 0x20 ),
+ BIGINT ( 0x2c, 0xb2, 0xe2, 0x1f, 0x4b, 0x97,
+ 0xaa, 0x3b, 0xd1, 0x36, 0xb0, 0x40,
+ 0x8b, 0x1c, 0x19, 0xa2, 0xea, 0xc8,
+ 0xc6, 0x4e, 0x2a, 0x66, 0x50 ),
+ BIGINT ( 0x97 ),
+ BIGINT ( 0x04, 0x22, 0x44, 0xe2, 0x14, 0x54,
+ 0x6c, 0x5a, 0xba, 0x1b, 0x39, 0xb7,
+ 0xaa, 0x06, 0xcf, 0x2b, 0xc8, 0x7e,
+ 0xc0, 0xe0, 0x70, 0xf2, 0x90 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xcd, 0xf3, 0xf7, 0x50, 0x13, 0x39,
+ 0x13, 0x4a, 0x56, 0xc5, 0xb8, 0xa6,
+ 0x42, 0x2d, 0x40, 0x5e, 0x07, 0xf2,
+ 0x92, 0x2a, 0x51, 0x87, 0x20 ),
+ BIGINT ( 0x93, 0x1a, 0x28, 0xbb, 0x69, 0x4f,
+ 0x31, 0x01, 0xe0, 0x88, 0x8a, 0x4c,
+ 0x4f, 0x9b, 0xda, 0xf6, 0x4e, 0xf3,
+ 0x11, 0xe7, 0x35, 0xa1, 0xfb ),
+ BIGINT ( 0x66, 0x69 ),
+ BIGINT ( 0x7a, 0x5a, 0x9b, 0x84, 0x72, 0x8f,
+ 0x57, 0x31, 0xb4, 0x34, 0x70, 0x18,
+ 0x77, 0xa6, 0x43, 0xa9, 0x51, 0x69,
+ 0x07, 0x3e, 0xf6, 0x68, 0x82 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xdd, 0x4c, 0x85, 0xcb, 0x3f, 0x45,
+ 0x61, 0xe0, 0x58, 0x1e, 0xad, 0xd3,
+ 0x6b, 0xef, 0x82, 0x53, 0x4a, 0x16,
+ 0x1a, 0xf0, 0x09, 0x82, 0x74 ),
+ BIGINT ( 0xd2, 0xa2, 0x73, 0x89, 0x0c, 0x56,
+ 0xe4, 0x31, 0xdf, 0x70, 0x3c, 0x40,
+ 0x0d, 0x36, 0xfc, 0x4a, 0xf3, 0xa2,
+ 0x8f, 0x9a, 0x9d, 0xaa, 0xb0 ),
+ BIGINT ( 0xbc, 0xca, 0x45 ),
+ BIGINT ( 0x9f, 0x5f, 0x7c, 0xac, 0x5e, 0xc7,
+ 0xf2, 0xc5, 0x72, 0x3d, 0xff, 0x29,
+ 0xd2, 0x25, 0xa9, 0x64, 0x5b, 0xbe,
+ 0x63, 0x63, 0xc6, 0x84, 0x20 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xf8, 0xc9, 0xb9, 0x3d, 0xe1, 0xff,
+ 0xa6, 0x8e, 0xb0, 0xd2, 0xa9, 0xa9,
+ 0xc1, 0x5c, 0xc5, 0x94, 0x90, 0xb9,
+ 0xca, 0x2f, 0x1a, 0xbd, 0x21 ),
+ BIGINT ( 0xa7, 0xf4, 0xb0, 0x3c, 0xf4, 0x2b,
+ 0x9d, 0x40, 0x5f, 0xfd, 0x2e, 0x28,
+ 0xa9, 0x23, 0x01, 0xaf, 0x0b, 0x73,
+ 0xaa, 0xcf, 0x14, 0xdc, 0xd8 ),
+ BIGINT ( 0x31, 0xe2, 0xe8, 0xf0 ),
+ BIGINT ( 0x53, 0x30, 0xc6, 0x10, 0x12, 0x7c,
+ 0xb3, 0x91, 0x15, 0x5f, 0x01, 0x62,
+ 0xec, 0x1f, 0x15, 0x61, 0x3b, 0x9a,
+ 0x76, 0x22, 0xf8, 0x31, 0xb1 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xff, 0x8c, 0x04, 0x74, 0x3e, 0x93,
+ 0xfd, 0xce, 0xd5, 0x7f, 0xc5, 0x58,
+ 0xce, 0x00, 0x53, 0x44, 0x02, 0xf4,
+ 0xfd, 0x01, 0xc3, 0xb0, 0x3c ),
+ BIGINT ( 0x2f, 0xbe, 0xb3, 0x2d, 0xd6, 0x59,
+ 0x69, 0x44, 0xc0, 0xd4, 0x27, 0x9c,
+ 0xff, 0x53, 0x9e, 0x66, 0x2c, 0x01,
+ 0x3a, 0x96, 0x5d, 0x75, 0xc1 ),
+ BIGINT ( 0x47, 0x3e, 0xb2, 0x81, 0x51, 0x9a,
+ 0xdf, 0x75, 0xba, 0xa5, 0x19, 0xc1,
+ 0xc7, 0xcc, 0xae, 0x82, 0x9c, 0x3e,
+ 0xfd, 0x7f, 0xb0, 0xd7, 0x00 ),
+ BIGINT ( 0x09, 0x9c, 0xd0, 0x49, 0x1d, 0x88,
+ 0xd8, 0x08, 0x45, 0x61, 0x71, 0xa1,
+ 0xb5, 0xab, 0xa9, 0x5b, 0xa8, 0xf1,
+ 0xc6, 0x53, 0x68, 0x8f, 0x3e ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xd8, 0x78, 0xad, 0x80, 0x81, 0xf1,
+ 0x84, 0x23, 0x82, 0x5d, 0x49, 0x46,
+ 0x75, 0xfd, 0xd1, 0x49, 0x53, 0x10,
+ 0x4d, 0x10, 0xab, 0x0f, 0xf0 ),
+ BIGINT ( 0x78, 0x3d, 0x09, 0x1b, 0xea, 0xa4,
+ 0xb9, 0x13, 0xf8, 0xb5, 0xb5, 0x5e,
+ 0x69, 0xa4, 0xe1, 0xfd, 0x88, 0x58,
+ 0x26, 0xb3, 0x76, 0xa2, 0x38 ),
+ BIGINT ( 0x3b, 0x12, 0xe0, 0x8e, 0xa2, 0x2f,
+ 0x2a, 0x2b, 0xb1, 0x78, 0xf9, 0xf6,
+ 0x93, 0x4d, 0x52, 0x82, 0x29, 0x2d,
+ 0xe4, 0x36, 0x92, 0x49, 0xc1, 0x25,
+ 0x6e, 0x26, 0xe6, 0x6e, 0xc2, 0x4d,
+ 0xea, 0x13, 0x86, 0x85, 0x71, 0x4d,
+ 0x85, 0x70, 0xf9, 0x2b, 0xa0, 0x0f,
+ 0x96, 0xe5, 0x63, 0x7a, 0xb4, 0x25,
+ 0x53, 0x1a, 0xd8, 0x30, 0x36, 0xba,
+ 0x6e, 0x2e, 0xce, 0x2d, 0x8f, 0x32,
+ 0xe9, 0xdc, 0x91, 0x9e, 0xd4, 0xf1,
+ 0x3b, 0x40, 0xc9, 0xf4, 0x97, 0x74,
+ 0x5e, 0x69, 0xcd, 0x34, 0x4a, 0x18,
+ 0x65, 0xe5, 0x07, 0xb5, 0x9e, 0x2a,
+ 0xc4, 0xeb, 0xb6, 0x96, 0x7b, 0x99,
+ 0x0c, 0xe4, 0xb3, 0x85, 0xff, 0x17,
+ 0x72, 0x5d, 0xf6, 0x30, 0xb4, 0xff,
+ 0x98, 0xe6, 0xf6, 0x31, 0x24, 0x82,
+ 0x91, 0xa6, 0x18, 0x6d, 0x0b, 0x84,
+ 0x6f, 0x5f, 0x64, 0xa3, 0xdf, 0x92,
+ 0x06, 0x16, 0xe3, 0x7c, 0x08, 0x61,
+ 0x77, 0xce ),
+ BIGINT ( 0x17, 0xc9, 0xc5, 0x38, 0x4c, 0x15,
+ 0x0f, 0x4e, 0xc2, 0x90, 0x3b, 0x46,
+ 0x7b, 0x2f, 0x95, 0x82, 0xfe, 0x51,
+ 0x95, 0x2b, 0xff, 0xd5, 0x28 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x69, 0xa3, 0x7e, 0x24, 0xdf, 0x9e,
+ 0x0b, 0x3e, 0x3f, 0x43, 0x06, 0x0e,
+ 0x1d, 0x57, 0x74, 0xe0, 0xa0, 0x5b,
+ 0x82, 0xca, 0xb0, 0x33, 0x8b, 0xe4,
+ 0x39, 0x27, 0x41, 0xd4, 0x2e, 0x30,
+ 0x3a, 0x0e, 0x62, 0x6f, 0xfa, 0xb4,
+ 0x02, 0x88, 0x70, 0x35, 0xa6, 0xea,
+ 0x7d, 0xb2, 0x87, 0xc3, 0xa5, 0x50,
+ 0x49, 0x38, 0xa4, 0x68, 0xa9, 0xe4,
+ 0xa6, 0xcc, 0xd7, 0x13, 0xb1, 0xd9,
+ 0x1c, 0x6a, 0x9a, 0xb8, 0x6c, 0x9b,
+ 0xff, 0xcd, 0x2c, 0xb3, 0xbd, 0xe2,
+ 0xfd, 0x1f, 0x08, 0xdd, 0xc6, 0xee,
+ 0x18, 0x0c, 0xa5, 0xcd, 0x09, 0x19,
+ 0x51, 0x51, 0xa5, 0x6f, 0x93, 0x1b,
+ 0x34, 0xfd, 0x8f, 0xd9, 0x87, 0xed,
+ 0x15, 0x7e, 0x36, 0x60, 0xdd, 0x1b,
+ 0xf4, 0xcc, 0xc4, 0x4c, 0x19, 0x2b,
+ 0xd6, 0x1e, 0xec, 0x51, 0xe9, 0x27,
+ 0xe9, 0xbd, 0x6a, 0x3f, 0x91, 0x45,
+ 0xc3, 0x6d, 0x40, 0x7e, 0x6c, 0x56,
+ 0x05, 0x5a ),
+ BIGINT ( 0x5c, 0x96, 0x05, 0x81, 0x94, 0x45,
+ 0xcf, 0x47, 0x5f, 0x1b, 0xb0, 0xf9,
+ 0xef, 0x13, 0x8f, 0xcc, 0x71, 0xfd,
+ 0x50, 0xf1, 0xe7, 0x62, 0x6e, 0xfa,
+ 0x48, 0x66, 0x1c, 0xf7, 0xef, 0x09,
+ 0x12, 0xa2, 0xfd, 0x17, 0xb7, 0x6a,
+ 0x3b, 0xed, 0xf7, 0x86, 0xd2, 0xbe,
+ 0x95, 0x90, 0xc6, 0x00, 0x14, 0x8d,
+ 0xe3, 0x27, 0xbe, 0x03, 0x7c, 0x9e,
+ 0x6b, 0x51, 0x31, 0x8d, 0x18, 0xc4,
+ 0x16, 0xd2, 0x84, 0x63, 0x9b, 0xe9,
+ 0xa4, 0xf8, 0xff, 0x70, 0x4d, 0xeb,
+ 0x6f, 0x4a, 0xb7, 0x5b, 0x54, 0xf1,
+ 0xb5, 0xbe, 0x78, 0xb6, 0xfd, 0x8b,
+ 0xe1, 0x39, 0x62, 0x85, 0x9b, 0xde,
+ 0x30, 0xa8, 0xe4, 0x37, 0x52, 0x57,
+ 0x39, 0x79, 0xdb, 0x0b, 0x19, 0x6b,
+ 0xc9, 0x17, 0xfd, 0x8c, 0x2c, 0xaa,
+ 0xa4, 0xf1, 0x04, 0xd1, 0xd3, 0x2f,
+ 0xbb, 0x3a, 0x36, 0x82, 0x31, 0xa4,
+ 0x40, 0xd4, 0x87, 0x46, 0xe3, 0x6e,
+ 0xd0, 0x17 ),
+ BIGINT ( 0x93 ),
+ BIGINT ( 0x0d, 0x39, 0x92, 0x57, 0xaa, 0x6d,
+ 0xfc, 0x3b, 0x10, 0x18, 0x6d, 0x59,
+ 0xbe, 0x31, 0x8f, 0xee, 0xf9, 0x82,
+ 0x84, 0xe0, 0xdf, 0xa5, 0x00, 0x28,
+ 0xd1, 0x64, 0x6b, 0x4b, 0x43, 0x3b,
+ 0x76, 0x3e, 0x6b, 0xc4, 0xe4, 0xf5,
+ 0x0b, 0x59, 0x5a, 0xe4, 0x53, 0x5e,
+ 0x02, 0xd4, 0xde, 0x72, 0xd3, 0xa3,
+ 0x58, 0x66, 0xa7, 0xdd, 0x2b, 0x0b,
+ 0xa4, 0x83, 0xd0, 0xd9, 0xef, 0x29,
+ 0x3d, 0x2f, 0x97, 0xff, 0x9a, 0xc7,
+ 0xf6, 0x8a, 0x8d, 0x59, 0xef, 0x87,
+ 0xd1, 0xe6, 0xba, 0x4d, 0x99, 0xd9,
+ 0x5f, 0x5e, 0x7a, 0x7e, 0x67, 0x22,
+ 0x5b, 0x77, 0x83, 0xa2, 0x02, 0xfd,
+ 0xb2, 0xe4, 0xf6, 0x20, 0x4c, 0x12,
+ 0x20, 0xa7, 0xda, 0x5b, 0x3b, 0x8c,
+ 0xa2, 0xca, 0xda, 0x20, 0xaa, 0x27,
+ 0xe6, 0x54, 0x3e, 0xa8, 0x6f, 0x64,
+ 0x9d, 0xa7, 0x0d, 0x57, 0x1b, 0x21,
+ 0xff, 0xd2, 0xe2, 0xb2, 0x0a, 0x4f,
+ 0xb7, 0x0e ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x06, 0xcf, 0x54, 0xf2, 0x0d, 0x62,
+ 0x33, 0xdd, 0xe7, 0x4d, 0x7f, 0x2f,
+ 0x8e, 0x52, 0x73, 0xf4, 0x73, 0x68,
+ 0x4b, 0x13, 0x6e, 0x58, 0x6b, 0x4a,
+ 0xb8, 0x4c, 0xef, 0x73, 0xfe, 0x5f,
+ 0xf6, 0xd0, 0xbb, 0x82, 0x17, 0x3f,
+ 0x9d, 0x91, 0xf8, 0xa3, 0xb8, 0x79,
+ 0xef, 0x41, 0x38, 0xc1, 0xef, 0xc9,
+ 0xc6, 0xcf, 0x2a, 0xc3, 0xaa, 0x75,
+ 0x17, 0xda, 0xbc, 0x76, 0x29, 0x61,
+ 0x6d, 0x05, 0x79, 0x0b, 0x44, 0xb1,
+ 0x54, 0x75, 0xb7, 0xd9, 0xf6, 0xa8,
+ 0xbd, 0xf7, 0x85, 0xe0, 0xe7, 0x90,
+ 0x62, 0xce, 0x79, 0xfb, 0xc5, 0x23,
+ 0xa5, 0x09, 0xc0, 0xc4, 0x4d, 0xe7,
+ 0x9c, 0x49, 0x8f, 0x82, 0xf1, 0x31,
+ 0x34, 0x85, 0xdd, 0x3b, 0xbe, 0xe9,
+ 0x93, 0x19, 0x03, 0x75, 0x3f, 0xc4,
+ 0xa4, 0x0f, 0x52, 0x53, 0xc1, 0xcd,
+ 0x08, 0xb0, 0x05, 0x0c, 0xa2, 0x0c,
+ 0x3a, 0x72, 0xb2, 0x3c, 0xdb, 0x4f,
+ 0xac, 0xc6 ),
+ BIGINT ( 0xe4, 0x40, 0xd8, 0x30, 0x00, 0xcf,
+ 0x4c, 0xfd, 0xda, 0xae, 0x90, 0xd3,
+ 0x5b, 0xc7, 0x20, 0xcc, 0x2b, 0xe2,
+ 0x0a, 0x39, 0x1e, 0xde, 0xef, 0x98,
+ 0x16, 0x3b, 0x9d, 0x36, 0x63, 0x0d,
+ 0x46, 0xed, 0x23, 0x6e, 0x38, 0xa8,
+ 0x15, 0xb5, 0xb1, 0xaf, 0x47, 0xb1,
+ 0xec, 0xaa, 0x8b, 0x57, 0xd6, 0xca,
+ 0x39, 0x2f, 0x62, 0xbd, 0xd5, 0xf8,
+ 0x98, 0x98, 0x5d, 0xfe, 0x14, 0xd6,
+ 0xdc, 0xe5, 0x98, 0x60, 0x5b, 0x16,
+ 0x92, 0xcb, 0xed, 0xb6, 0x9c, 0x5c,
+ 0x82, 0x40, 0x6b, 0xaa, 0x48, 0x7a,
+ 0xd4, 0xfe, 0xa3, 0xe7, 0x30, 0xf1,
+ 0x7c, 0xfb, 0x94, 0x2e, 0xeb, 0xb6,
+ 0x71, 0xe4, 0x33, 0x63, 0xc3, 0xb0,
+ 0x94, 0x6d, 0xee, 0xa5, 0x15, 0x3f,
+ 0x28, 0xf1, 0xfa, 0xdc, 0xf2, 0x13,
+ 0x0f, 0xc7, 0xd9, 0xe0, 0xbf, 0x1b,
+ 0x49, 0xee, 0x21, 0x8e, 0x26, 0xc9,
+ 0x28, 0x21, 0x86, 0x1d, 0x46, 0x33,
+ 0xd4, 0x69 ),
+ BIGINT ( 0xd9, 0x87 ),
+ BIGINT ( 0xdf, 0xff, 0xcc, 0xb7, 0xfe, 0x19,
+ 0x02, 0x92, 0x9d, 0xab, 0x33, 0xd2,
+ 0x21, 0xbc, 0xd3, 0xc4, 0x31, 0xad,
+ 0x4b, 0xb3, 0x16, 0x50, 0x96, 0xd9,
+ 0xdc, 0x88, 0x74, 0x60, 0xde, 0xdf,
+ 0xb7, 0x83, 0xdb, 0x22, 0xef, 0xcb,
+ 0xcb, 0xdb, 0x4c, 0xfb, 0x94, 0x4c,
+ 0x3f, 0xf5, 0xf5, 0x99, 0x85, 0x21,
+ 0x1a, 0x2b, 0xec, 0x90, 0x2d, 0xb4,
+ 0x20, 0x3c, 0x27, 0x9f, 0xe5, 0xb1,
+ 0x5c, 0x92, 0xfa, 0xb0, 0xa9, 0x8e,
+ 0x2c, 0x21, 0x8e, 0x8d, 0xe5, 0x55,
+ 0x84, 0x02, 0xa5, 0x15, 0x5c, 0x53,
+ 0x1f, 0x40, 0x81, 0x0a, 0x10, 0xde,
+ 0x21, 0x41, 0xa9, 0x97, 0xf8, 0x6f,
+ 0xbf, 0x42, 0x58, 0x9e, 0xc6, 0xdd,
+ 0x10, 0x33, 0x3f, 0xad, 0xe6, 0x8e,
+ 0x57, 0x27, 0x37, 0x20, 0xa4, 0x86,
+ 0xef, 0x39, 0x7b, 0x6f, 0x78, 0x77,
+ 0xab, 0xa0, 0x62, 0xe1, 0xfd, 0x9c,
+ 0xbe, 0xfa, 0x98, 0x2e, 0x29, 0xe3,
+ 0xeb, 0x52 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x00, 0x91, 0xb3, 0x87, 0xe6, 0x01,
+ 0x57, 0xe9, 0x68, 0xa4, 0xf4, 0x9b,
+ 0xea, 0x6a, 0x8a, 0x9e, 0x1a, 0x8b,
+ 0xd3, 0x85, 0x9d, 0xba, 0x85, 0xab,
+ 0xd8, 0xcd, 0x25, 0x56, 0x8e, 0x85,
+ 0x8a, 0x8e, 0x48, 0x9e, 0xb4, 0x90,
+ 0xc8, 0x2e, 0x07, 0x78, 0x80, 0x49,
+ 0xa0, 0xb7, 0x95, 0x6a, 0xd8, 0xad,
+ 0xb5, 0xda, 0x5d, 0xe6, 0x11, 0x87,
+ 0xb8, 0x33, 0x8f, 0xa8, 0x6f, 0x4e,
+ 0xc6, 0xc3, 0x0d, 0xf5, 0xa9, 0x4e,
+ 0xb2, 0x42, 0x53, 0x81, 0xcd, 0x33,
+ 0x83, 0x49, 0xab, 0x0d, 0x0e, 0xf5,
+ 0x2c, 0xcd, 0x84, 0x58, 0xf3, 0x30,
+ 0xa3, 0x6e, 0x3c, 0x3a, 0xc6, 0x77,
+ 0x43, 0xb0, 0xe7, 0x4b, 0x66, 0x30,
+ 0xe9, 0x48, 0x0b, 0x0d, 0x86, 0x3f,
+ 0xd8, 0xe2, 0xb5, 0x88, 0xc1, 0x44,
+ 0xb2, 0x6b, 0xb0, 0x7a, 0x35, 0x3b,
+ 0x56, 0x83, 0xb1, 0xac, 0x9e, 0xeb,
+ 0x9b, 0x08, 0x43, 0xac, 0x0a, 0x3a,
+ 0x31, 0x69 ),
+ BIGINT ( 0x96, 0x6f, 0xb0, 0xa7, 0x02, 0xb5,
+ 0xd9, 0x19, 0xbe, 0x4b, 0x27, 0x65,
+ 0x5b, 0x96, 0xd4, 0x0b, 0x49, 0x70,
+ 0xf0, 0x09, 0x8e, 0xf2, 0x04, 0x85,
+ 0x93, 0xe9, 0x2e, 0x09, 0x31, 0x76,
+ 0x8b, 0xbb, 0xe9, 0xe1, 0x2b, 0x4f,
+ 0xed, 0x83, 0xa6, 0x87, 0xa3, 0x07,
+ 0x0a, 0x3d, 0x1c, 0x65, 0x14, 0x5a,
+ 0xd5, 0xc0, 0x5d, 0x3c, 0x31, 0x9a,
+ 0x83, 0xad, 0xca, 0x6a, 0x93, 0x0d,
+ 0x1a, 0x67, 0x4e, 0x68, 0x06, 0x64,
+ 0x53, 0x2e, 0x15, 0xd9, 0xdd, 0x5e,
+ 0xcb, 0xb7, 0x2e, 0xef, 0xd3, 0xbb,
+ 0x5f, 0xaf, 0xef, 0x9e, 0xf2, 0x7b,
+ 0x69, 0x15, 0xb0, 0x18, 0x6c, 0x67,
+ 0x10, 0xda, 0x33, 0x07, 0x48, 0x97,
+ 0x31, 0xb3, 0x3d, 0x3d, 0xc9, 0x2e,
+ 0x0b, 0x68, 0x91, 0x3f, 0x6a, 0x3b,
+ 0x1a, 0xdf, 0xa8, 0x69, 0x46, 0x1c,
+ 0xb2, 0x69, 0x08, 0x0b, 0x02, 0x1b,
+ 0x03, 0x64, 0xae, 0xb6, 0x2d, 0xc6,
+ 0xc4, 0x0a ),
+ BIGINT ( 0x6d, 0x3f, 0xdd ),
+ BIGINT ( 0x40, 0x6e, 0x9d, 0x3e, 0xeb, 0xa4,
+ 0xb1, 0x8d, 0xb7, 0xb4, 0x0f, 0x5b,
+ 0x12, 0xad, 0x27, 0x9e, 0xbd, 0xe7,
+ 0xe5, 0x9d, 0xec, 0xb4, 0xac, 0x23,
+ 0x5f, 0xa9, 0xec, 0x9c, 0xd1, 0x6a,
+ 0xbe, 0x99, 0xba, 0xb3, 0x66, 0x0e,
+ 0x17, 0xaa, 0x13, 0xa2, 0x2e, 0x01,
+ 0x28, 0xb1, 0x6c, 0xba, 0xad, 0x68,
+ 0x48, 0xf0, 0xf3, 0x4c, 0x08, 0x9f,
+ 0xd1, 0x9c, 0xb7, 0x75, 0xc5, 0xb6,
+ 0x5a, 0x05, 0xb0, 0x14, 0xd4, 0x61,
+ 0xea, 0x18, 0x9f, 0xe6, 0xe5, 0xe3,
+ 0xd4, 0xff, 0x35, 0x43, 0x0b, 0xb8,
+ 0xf6, 0xe9, 0x19, 0x7a, 0x88, 0xa7,
+ 0x4d, 0x01, 0x92, 0x05, 0xd2, 0x6e,
+ 0xa3, 0xc1, 0xb6, 0x66, 0x75, 0xb1,
+ 0x00, 0x0d, 0x42, 0x37, 0xcc, 0xca,
+ 0xc0, 0x8d, 0xc8, 0x7e, 0x5c, 0xc9,
+ 0x53, 0x81, 0x2f, 0xc4, 0x61, 0xb6,
+ 0x96, 0x3b, 0xa5, 0x04, 0x14, 0x1b,
+ 0xa7, 0x77, 0xa1, 0xbc, 0x73, 0x1d,
+ 0xad, 0xed ) );
+ bigint_mod_exp_ok ( BIGINT ( 0x45, 0xfb, 0xf3, 0xdc, 0x31, 0xe5,
+ 0x56, 0x7a, 0xee, 0x15, 0xfb, 0x16,
+ 0xee, 0x6e, 0x90, 0x3e, 0xa3, 0x89,
+ 0xc2, 0x6d, 0x9b, 0x06, 0x65, 0xd0,
+ 0xcd, 0xa2, 0xcc, 0x01, 0x60, 0x0d,
+ 0xd1, 0xdd, 0x68, 0x14, 0xc2, 0xcd,
+ 0xd8, 0x79, 0x75, 0xad, 0x0a, 0x9f,
+ 0x39, 0x5f, 0x52, 0x4b, 0x58, 0x31,
+ 0x48, 0xbb, 0x2a, 0xcc, 0xe0, 0x42,
+ 0x18, 0x32, 0xdc, 0x63, 0x14, 0x11,
+ 0x4e, 0xab, 0x96, 0x29, 0xc5, 0x06,
+ 0x79, 0xe5, 0x06, 0xf7, 0x59, 0xdb,
+ 0x1e, 0x51, 0xfd, 0xc4, 0x48, 0x3a,
+ 0x4c, 0x7f, 0xd0, 0xe2, 0x36, 0x86,
+ 0xc1, 0x8b, 0xc5, 0x86, 0x52, 0xe0,
+ 0xdb, 0x92, 0x5f, 0x0e, 0x19, 0xb1,
+ 0xa3, 0x23, 0xdd, 0xf0, 0x78, 0xcc,
+ 0x81, 0x3f, 0x4a, 0xe6, 0xb0, 0x32,
+ 0xd1, 0x5c, 0x5e, 0x3a, 0xb0, 0xd8,
+ 0xe2, 0x04, 0xc0, 0x30, 0x85, 0x1d,
+ 0x5e, 0x28, 0xee, 0xd9, 0xb3, 0x83,
+ 0x9f, 0xe2 ),
+ BIGINT ( 0xb3, 0x2c, 0x2e, 0xc5, 0xba, 0xf8,
+ 0x41, 0x98, 0x79, 0x7e, 0xaa, 0x0c,
+ 0x2a, 0x8f, 0xd9, 0x56, 0x55, 0xaa,
+ 0x74, 0x60, 0x74, 0xd1, 0x49, 0x2c,
+ 0x6f, 0x0a, 0x4e, 0xf8, 0x3f, 0x1b,
+ 0x73, 0x4c, 0xe0, 0x17, 0x37, 0x06,
+ 0x76, 0x73, 0xd5, 0x2d, 0x4d, 0x3f,
+ 0xb0, 0x15, 0x7e, 0x98, 0xd0, 0xdf,
+ 0xf0, 0x33, 0x78, 0xe2, 0xe6, 0xec,
+ 0x21, 0x22, 0xad, 0xd5, 0xab, 0x2d,
+ 0x0d, 0x59, 0x95, 0x05, 0x34, 0x1f,
+ 0x51, 0xf5, 0xec, 0x93, 0x05, 0x15,
+ 0x37, 0xcf, 0x93, 0x03, 0xd7, 0xf6,
+ 0x35, 0x23, 0x8f, 0x33, 0xf6, 0xba,
+ 0x42, 0xc8, 0x52, 0x94, 0xd3, 0x33,
+ 0x3e, 0x39, 0x01, 0xd1, 0x55, 0x3f,
+ 0x48, 0x84, 0xe9, 0xbc, 0x0b, 0x0f,
+ 0xc9, 0x69, 0x41, 0x2c, 0x5f, 0x34,
+ 0xd0, 0xe6, 0x15, 0x50, 0x06, 0x64,
+ 0x5b, 0x8b, 0x71, 0x22, 0xb3, 0x3e,
+ 0x09, 0x9c, 0x76, 0x13, 0x9b, 0x29,
+ 0x57, 0x94 ),
+ BIGINT ( 0xca, 0x94, 0xf7, 0xca ),
+ BIGINT ( 0x83, 0x68, 0xb9, 0xe7, 0x91, 0xf3,
+ 0x3b, 0x5a, 0x0b, 0xb6, 0x1e, 0x2f,
+ 0x3f, 0x5f, 0xdc, 0x96, 0x5b, 0x7f,
+ 0x8d, 0xc5, 0x8e, 0xda, 0x6e, 0x21,
+ 0xe3, 0x20, 0xea, 0x37, 0x39, 0x3b,
+ 0xb4, 0xd7, 0xf6, 0xba, 0x61, 0xfe,
+ 0xdc, 0x7e, 0x82, 0x9a, 0x38, 0x7b,
+ 0xd5, 0xb1, 0x11, 0x98, 0xc4, 0x88,
+ 0x0b, 0x01, 0x7d, 0x81, 0xc9, 0x64,
+ 0x23, 0xc3, 0x3e, 0xf3, 0x67, 0x95,
+ 0x78, 0xca, 0xda, 0x52, 0xaf, 0x72,
+ 0x25, 0xd9, 0xf0, 0x27, 0xd3, 0x1c,
+ 0xfb, 0xad, 0xa1, 0xa7, 0x06, 0x2f,
+ 0xaa, 0x2f, 0x86, 0x5c, 0x8b, 0x30,
+ 0xe1, 0xda, 0x5a, 0x36, 0xf9, 0xfd,
+ 0xbf, 0xfe, 0x0d, 0x03, 0xf8, 0x9c,
+ 0x6b, 0x9b, 0xe5, 0x70, 0x6d, 0x75,
+ 0xd7, 0x54, 0x28, 0x43, 0x34, 0x69,
+ 0x98, 0x11, 0x29, 0xee, 0x50, 0x06,
+ 0xa4, 0xc4, 0x11, 0x6d, 0x60, 0x8c,
+ 0xcd, 0xd1, 0x88, 0xe9, 0x6b, 0xbb,
+ 0xc1, 0xd4 ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xa1, 0x01, 0x7e, 0xb4, 0x0e, 0x66,
+ 0xa5, 0x07, 0x8b, 0x10, 0x84, 0x0d,
+ 0x30, 0x0a, 0xa4, 0x2d, 0x10, 0x2c,
+ 0xd4, 0x9a, 0x27, 0xf1, 0x02, 0x8c,
+ 0x38, 0x18, 0x7f, 0x7f, 0x95, 0x65,
+ 0xf1, 0xa9, 0x3b, 0x7d, 0x1f, 0x4f,
+ 0x88, 0xb0, 0x65, 0x62, 0x63, 0x63,
+ 0xaa, 0x82, 0xfc, 0x83, 0x3a, 0x3a,
+ 0x46, 0x59, 0x6a, 0x89, 0xec, 0xa9,
+ 0xb0, 0x4c, 0x5e, 0xbe, 0x46, 0x98,
+ 0xd0, 0xd4, 0xb7, 0xe3, 0x1b, 0x30,
+ 0x0b, 0xfb, 0xbb, 0x4f, 0x0b, 0xd3,
+ 0xe4, 0xa0, 0x80, 0x54, 0xcb, 0x52,
+ 0x0a, 0xe8, 0x03, 0x75, 0x8e, 0x96,
+ 0xa4, 0x21, 0xaa, 0xbd, 0x7a, 0xfd,
+ 0xfa, 0xf8, 0xaf, 0x42, 0xf6, 0x61,
+ 0xd2, 0x93, 0xce, 0x66, 0x67, 0xe9,
+ 0x02, 0xda, 0x81, 0x0b, 0xb0, 0x1e,
+ 0x9e, 0x27, 0x57, 0x98, 0x18, 0x88,
+ 0x35, 0x49, 0xc0, 0x88, 0x88, 0x59,
+ 0xae, 0x2f, 0x66, 0x59, 0x31, 0x87,
+ 0x88, 0xda ),
+ BIGINT ( 0xfe, 0x21, 0x7c, 0xf4, 0xbe, 0xae,
+ 0x65, 0xda, 0x89, 0xd2, 0x26, 0xd6,
+ 0x9c, 0x65, 0xc6, 0xb6, 0xb4, 0x0a,
+ 0x84, 0x11, 0xe1, 0xe8, 0xba, 0xd8,
+ 0x16, 0xcf, 0x60, 0x6c, 0x83, 0xa5,
+ 0x4a, 0xbf, 0xa2, 0x24, 0x0b, 0x66,
+ 0xda, 0xe2, 0x4e, 0x2d, 0xe5, 0x9e,
+ 0xbf, 0xad, 0x5c, 0xa3, 0x1e, 0x5c,
+ 0xbd, 0xe2, 0x5b, 0x46, 0xcf, 0xcc,
+ 0xd5, 0xc9, 0x13, 0x95, 0xc3, 0xdb,
+ 0x64, 0xbf, 0xeb, 0x31, 0xa9, 0x8a,
+ 0x3b, 0xd2, 0x5d, 0x3b, 0x2e, 0xdc,
+ 0x0c, 0xca, 0xab, 0xde, 0x92, 0xae,
+ 0x45, 0x35, 0x96, 0xb0, 0xb7, 0xb9,
+ 0xe6, 0xfe, 0x28, 0x0d, 0x10, 0x72,
+ 0x53, 0x8e, 0x21, 0xc0, 0x33, 0x79,
+ 0x01, 0x43, 0x8d, 0x77, 0xc4, 0xaa,
+ 0xcf, 0x7f, 0xc3, 0xd1, 0xf5, 0xfd,
+ 0x79, 0x81, 0xf6, 0x2e, 0xb7, 0xeb,
+ 0x55, 0x5f, 0x74, 0xf0, 0x3a, 0xb9,
+ 0x57, 0x07, 0x09, 0x97, 0xa5, 0x4c,
+ 0x4a, 0x85 ),
+ BIGINT ( 0xd9, 0xb7, 0xb2, 0xd6, 0xeb, 0xf3,
+ 0x66, 0xbe, 0x15, 0x64, 0xad, 0x2e,
+ 0x9e, 0xc6, 0xaf, 0x5e, 0xaf, 0x40,
+ 0x1e, 0x90, 0x82, 0x2f, 0x98 ),
+ BIGINT ( 0x12, 0x48, 0x31, 0x7f, 0x09, 0xbb,
+ 0x8f, 0xd9, 0x02, 0x7e, 0x4a, 0xd0,
+ 0x2f, 0x42, 0x7c, 0x17, 0x6e, 0x83,
+ 0x74, 0x21, 0x95, 0x47, 0x7d, 0x93,
+ 0x4a, 0xce, 0x34, 0x7c, 0xde, 0xc7,
+ 0x8f, 0xf6, 0x28, 0x97, 0xba, 0x81,
+ 0x9b, 0xcc, 0x54, 0x14, 0x7f, 0xd3,
+ 0x93, 0x66, 0x41, 0x8c, 0x0e, 0x47,
+ 0xee, 0xc5, 0x5e, 0xd6, 0x5f, 0x01,
+ 0x62, 0x97, 0xf1, 0x2b, 0xee, 0x60,
+ 0x5e, 0x82, 0x2c, 0x7b, 0x0a, 0xf2,
+ 0xc3, 0x23, 0xbf, 0xb9, 0x83, 0xf7,
+ 0x97, 0xf5, 0xca, 0x58, 0xd7, 0xf0,
+ 0x87, 0x7b, 0xcb, 0x87, 0x69, 0x42,
+ 0xbc, 0x05, 0xc4, 0xad, 0xbd, 0x82,
+ 0xcf, 0x44, 0x16, 0x4f, 0x46, 0xe0,
+ 0xde, 0x2f, 0xfa, 0x77, 0xec, 0xa4,
+ 0x23, 0x7d, 0x47, 0x3e, 0x94, 0x19,
+ 0x8b, 0xb8, 0x84, 0x81, 0x80, 0x6c,
+ 0x1e, 0x31, 0xa3, 0x6d, 0x14, 0x94,
+ 0x57, 0x28, 0x99, 0x08, 0x0a, 0xa7,
+ 0x98, 0x4b ) );
+ bigint_mod_exp_ok ( BIGINT ( 0xda, 0x52, 0xfd, 0x44, 0x5d, 0x11,
+ 0x60, 0x6c, 0xec, 0x87, 0xbf, 0x19,
+ 0xb8, 0x46, 0xaa, 0x41, 0xfc, 0x10,
+ 0xae, 0x47, 0xd6, 0x72, 0x42, 0x57,
+ 0xc3, 0x05, 0xca, 0xe3, 0x59, 0x94,
+ 0x82, 0x7c, 0xa1, 0xe0, 0xd2, 0x6b,
+ 0x77, 0x71, 0x42, 0xa1, 0xf7, 0x84,
+ 0xae, 0xf4, 0x6f, 0x44, 0x0d, 0x88,
+ 0xa2, 0xc5, 0x45, 0x9b, 0x49, 0x36,
+ 0xd4, 0x20, 0x3a, 0x7c, 0x92, 0xdb,
+ 0x65, 0xd9, 0x20, 0xd6, 0x71, 0x22,
+ 0x90, 0x70, 0xbf, 0xf3, 0x17, 0xe8,
+ 0x2c, 0x10, 0xe9, 0x4c, 0x02, 0x69,
+ 0x37, 0xa2, 0x91, 0x04, 0x46, 0x11,
+ 0xdc, 0xab, 0x5b, 0x1e, 0x3e, 0x31,
+ 0xd8, 0x69, 0xf8, 0x48, 0x84, 0x1f,
+ 0x56, 0x46, 0xf1, 0xc0, 0x14, 0x3f,
+ 0xcc, 0x5d, 0xe2, 0xf7, 0x8b, 0xa4,
+ 0x9e, 0x94, 0x32, 0xaa, 0x3c, 0x5e,
+ 0x21, 0x70, 0x00, 0x24, 0x2a, 0x1b,
+ 0xec, 0x25, 0xb1, 0xb6, 0x83, 0x36,
+ 0x5a, 0x95 ),
+ BIGINT ( 0x5e, 0xdc, 0x71, 0x1f, 0x5b, 0x55,
+ 0xaa, 0xda, 0x56, 0xf5, 0x93, 0x9b,
+ 0xe8, 0xfc, 0x6a, 0x80, 0xe1, 0xe3,
+ 0x93, 0xe4, 0xc0, 0x58, 0x6f, 0x22,
+ 0xce, 0x9d, 0x6f, 0x84, 0x4c, 0xd4,
+ 0x12, 0x44, 0x57, 0x25, 0xca, 0xe5,
+ 0x2b, 0x7c, 0x35, 0x88, 0xc7, 0x38,
+ 0x25, 0x20, 0x9b, 0x57, 0xf2, 0xf2,
+ 0x6c, 0x28, 0x47, 0x9c, 0x3f, 0x91,
+ 0x1e, 0x3f, 0xe9, 0xeb, 0x50, 0xd6,
+ 0xa7, 0x22, 0x88, 0x6c, 0x71, 0xe5,
+ 0x62, 0x2a, 0xb7, 0xce, 0xbe, 0xf7,
+ 0x1a, 0x8c, 0x52, 0xa6, 0xff, 0xb8,
+ 0x34, 0x83, 0x7e, 0x04, 0xa8, 0x9c,
+ 0xa8, 0xa7, 0xd1, 0x05, 0x8e, 0x13,
+ 0x03, 0xe0, 0x49, 0xd8, 0x4a, 0xc4,
+ 0x4d, 0x38, 0x21, 0x5b, 0x62, 0xc2,
+ 0x38, 0x23, 0x7c, 0x9e, 0xf1, 0xe9,
+ 0xb6, 0x9a, 0x75, 0x42, 0x14, 0x99,
+ 0x63, 0x36, 0x13, 0x4c, 0x2d, 0x3a,
+ 0x77, 0xd4, 0x74, 0xb7, 0x30, 0xb2,
+ 0x00, 0x0f ),
+ BIGINT ( 0xe3, 0xe5, 0x3b, 0xb5, 0x92, 0x5a,
+ 0xc6, 0xfa, 0x8f, 0xe8, 0x00, 0xb9,
+ 0x5c, 0xa0, 0xb6, 0x3e, 0x5e, 0x14,
+ 0x12, 0xa9, 0xdd, 0x2a, 0x3d, 0x4d,
+ 0xa3, 0x91, 0x6a, 0x56, 0x99, 0xc2,
+ 0x6c, 0x8e, 0xda, 0xb0, 0x5a, 0x2a,
+ 0x37, 0x55, 0x8b, 0xd3, 0x9b, 0xb6,
+ 0x1d, 0x49, 0x7d, 0x81, 0x76, 0x1c,
+ 0x2e, 0xb9, 0x92, 0x6d, 0xfa, 0x54,
+ 0x53, 0xfc, 0x74, 0x9b, 0x6b, 0x63,
+ 0x95, 0x1a, 0x89, 0xcc, 0xbd, 0x36,
+ 0xc5, 0x31, 0x7f, 0xf5, 0x31, 0x69,
+ 0x40, 0xd5, 0x7b, 0x94, 0x5d, 0xa9,
+ 0xd1, 0x34, 0x95, 0xa1, 0x8b, 0xa5,
+ 0xb5, 0x83, 0xda, 0xb5, 0x9d, 0x5b,
+ 0x74, 0x41, 0xad, 0x81, 0x45, 0x40,
+ 0x9b, 0xc3, 0xe8, 0xfe, 0x47, 0xdc,
+ 0xb0, 0xc3, 0x34, 0x5d, 0xf6, 0x3c,
+ 0x1d, 0x07, 0x76, 0xd9, 0x25, 0xca,
+ 0xa2, 0x39, 0x6c, 0xa8, 0xae, 0x30,
+ 0x4a, 0xde, 0xfb, 0xeb, 0x19, 0x80,
+ 0x5e, 0x49 ),
+ BIGINT ( 0x4b, 0x0e, 0x74, 0xb8, 0xa7, 0x92,
+ 0x74, 0xd9, 0x50, 0xf6, 0x1b, 0x67,
+ 0x76, 0x76, 0x56, 0x6c, 0x09, 0x9c,
+ 0x01, 0xda, 0xaf, 0xa3, 0xca, 0xb2,
+ 0x12, 0x85, 0x52, 0x24, 0xe9, 0x7e,
+ 0x2b, 0xf2, 0x6e, 0xe9, 0x1a, 0x10,
+ 0x5d, 0xa0, 0x25, 0x46, 0x8f, 0x2a,
+ 0x95, 0x62, 0x50, 0xb6, 0x66, 0x43,
+ 0x37, 0x8b, 0xcb, 0x05, 0xf8, 0x61,
+ 0x59, 0xf9, 0xdd, 0xd2, 0x68, 0x72,
+ 0xfa, 0x88, 0x13, 0x36, 0xd8, 0x24,
+ 0x73, 0xec, 0x47, 0x44, 0xdd, 0x45,
+ 0x8a, 0x59, 0xd2, 0xbd, 0x43, 0xe3,
+ 0x05, 0x16, 0xd5, 0x9b, 0x1c, 0x8a,
+ 0x4b, 0x07, 0xda, 0x58, 0x0d, 0x4a,
+ 0x4e, 0xe7, 0x15, 0xfc, 0xbd, 0x95,
+ 0xf7, 0x18, 0xa5, 0xa7, 0x93, 0xff,
+ 0xf8, 0x1f, 0xd4, 0x6b, 0x07, 0xc6,
+ 0x5d, 0x90, 0x73, 0x57, 0x57, 0x37,
+ 0xfa, 0x83, 0xd4, 0x7c, 0xe9, 0x77,
+ 0x46, 0x91, 0x3a, 0x50, 0x0d, 0x6a,
+ 0x25, 0xd0 ) );
+}
+
+/** Big integer self-test */
+struct self_test bigint_test __self_test = {
+ .name = "bigint",
+ .exec = bigint_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/bofm_test.c b/src/VBox/Devices/PC/ipxe/src/tests/bofm_test.c
new file mode 100644
index 00000000..6f2e6c67
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/bofm_test.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/init.h>
+#include <ipxe/pci.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/bofm.h>
+
+/** @file
+ *
+ * IBM BladeCenter Open Fabric Manager (BOFM) tests
+ *
+ */
+
+/** Harvest test table */
+static struct {
+ struct bofm_global_header header;
+ struct bofm_section_header en_header;
+ struct bofm_en en;
+ struct bofm_section_header done;
+} __attribute__ (( packed )) bofmtab_harvest = {
+ .header = {
+ .magic = BOFM_IOAA_MAGIC,
+ .action = BOFM_ACTION_HVST,
+ .version = 0x01,
+ .level = 0x01,
+ .length = sizeof ( bofmtab_harvest ),
+ .profile = "Harvest test profile",
+ },
+ .en_header = {
+ .magic = BOFM_EN_MAGIC,
+ .length = sizeof ( bofmtab_harvest.en ),
+ },
+ .en = {
+ .options = ( BOFM_EN_MAP_PFA | BOFM_EN_USAGE_HARVEST |
+ BOFM_EN_RQ_HVST_ACTIVE ),
+ .mport = 1,
+ },
+ .done = {
+ .magic = BOFM_DONE_MAGIC,
+ },
+};
+
+/** Update test table */
+static struct {
+ struct bofm_global_header header;
+ struct bofm_section_header en_header;
+ struct bofm_en en;
+ struct bofm_section_header done;
+} __attribute__ (( packed )) bofmtab_update = {
+ .header = {
+ .magic = BOFM_IOAA_MAGIC,
+ .action = BOFM_ACTION_UPDT,
+ .version = 0x01,
+ .level = 0x01,
+ .length = sizeof ( bofmtab_update ),
+ .profile = "Update test profile",
+ },
+ .en_header = {
+ .magic = BOFM_EN_MAGIC,
+ .length = sizeof ( bofmtab_update.en ),
+ },
+ .en = {
+ .options = ( BOFM_EN_MAP_PFA | BOFM_EN_EN_A |
+ BOFM_EN_USAGE_ENTRY ),
+ .mport = 1,
+ .mac_a = { 0x02, 0x00, 0x69, 0x50, 0x58, 0x45 },
+ },
+ .done = {
+ .magic = BOFM_DONE_MAGIC,
+ },
+};
+
+/**
+ * Perform BOFM test
+ *
+ * @v pci PCI device
+ */
+void bofm_test ( struct pci_device *pci ) {
+ int bofmrc;
+
+ printf ( "BOFMTEST using " PCI_FMT "\n", PCI_ARGS ( pci ) );
+
+ /* Perform harvest test */
+ printf ( "BOFMTEST performing harvest\n" );
+ bofmtab_harvest.en.busdevfn = pci->busdevfn;
+ DBG_HDA ( 0, &bofmtab_harvest, sizeof ( bofmtab_harvest ) );
+ bofmrc = bofm ( virt_to_user ( &bofmtab_harvest ), pci );
+ printf ( "BOFMTEST harvest result %08x\n", bofmrc );
+ if ( bofmtab_harvest.en.options & BOFM_EN_HVST ) {
+ printf ( "BOFMTEST harvested MAC address %s\n",
+ eth_ntoa ( &bofmtab_harvest.en.mac_a ) );
+ } else {
+ printf ( "BOFMTEST failed to harvest a MAC address\n" );
+ }
+ DBG_HDA ( 0, &bofmtab_harvest, sizeof ( bofmtab_harvest ) );
+
+ /* Perform update test */
+ printf ( "BOFMTEST performing update\n" );
+ bofmtab_update.en.busdevfn = pci->busdevfn;
+ DBG_HDA ( 0, &bofmtab_update, sizeof ( bofmtab_update ) );
+ bofmrc = bofm ( virt_to_user ( &bofmtab_update ), pci );
+ printf ( "BOFMTEST update result %08x\n", bofmrc );
+ if ( bofmtab_update.en.options & BOFM_EN_CSM_SUCCESS ) {
+ printf ( "BOFMTEST updated MAC address to %s\n",
+ eth_ntoa ( &bofmtab_update.en.mac_a ) );
+ } else {
+ printf ( "BOFMTEST failed to update MAC address\n" );
+ }
+ DBG_HDA ( 0, &bofmtab_update, sizeof ( bofmtab_update ) );
+}
+
+/**
+ * Perform BOFM test at initialisation time
+ *
+ */
+static void bofm_test_init ( void ) {
+ struct pci_device pci;
+ int busdevfn = -1;
+ int rc;
+
+ /* Uncomment the following line and specify the correct PCI
+ * bus:dev.fn address in order to perform a BOFM test at
+ * initialisation time.
+ */
+ // busdevfn = PCI_BUSDEVFN ( <bus>, <dev>, <fn> );
+
+ /* Skip test if no PCI bus:dev.fn is defined */
+ if ( busdevfn < 0 )
+ return;
+
+ /* Initialise PCI device */
+ memset ( &pci, 0, sizeof ( pci ) );
+ pci_init ( &pci, busdevfn );
+ if ( ( rc = pci_read_config ( &pci ) ) != 0 ) {
+ printf ( "BOFMTEST could not create " PCI_FMT " device: %s\n",
+ PCI_ARGS ( &pci ), strerror ( rc ) );
+ return;
+ }
+
+ /* Perform test */
+ bofm_test ( &pci );
+}
+
+/** BOFM test initialisation function */
+struct init_fn bofm_test_init_fn __init_fn ( INIT_NORMAL ) = {
+ .initialise = bofm_test_init,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/byteswap_test.c b/src/VBox/Devices/PC/ipxe/src/tests/byteswap_test.c
new file mode 100644
index 00000000..9bfe2659
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/byteswap_test.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Byte-order swapping test functions
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <stdint.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <ipxe/test.h>
+
+/* Provide global functions to allow inspection of generated assembly code */
+
+uint16_t test_bswap16 ( uint16_t x ) {
+ return __bswap_16 ( x );
+}
+
+uint32_t test_bswap32 ( uint32_t x ) {
+ return __bswap_32 ( x );
+}
+
+uint64_t test_bswap64 ( uint64_t x ) {
+ return __bswap_64 ( x );
+}
+
+void test_bswap16s ( uint16_t *x ) {
+ __bswap_16s ( x );
+}
+
+void test_bswap32s ( uint32_t *x ) {
+ __bswap_32s ( x );
+}
+
+void test_bswap64s ( uint64_t *x ) {
+ __bswap_64s ( x );
+}
+
+/**
+ * Perform byte-order swapping
+ *
+ */
+static void byteswap_test_exec ( void ) {
+ uint16_t test16;
+ uint32_t test32;
+ uint64_t test64;
+
+ ok ( test_bswap16 ( 0x1234 ) == 0x3412 );
+ ok ( test_bswap32 ( 0x12345678UL ) == 0x78563412UL );
+ ok ( test_bswap64 ( 0x123456789abcdef0ULL ) == 0xf0debc9a78563412ULL );
+
+ test16 = 0xabcd;
+ test_bswap16s ( &test16 );
+ ok ( test16 == 0xcdab );
+
+ test32 = 0xabcdef01UL;
+ test_bswap32s ( &test32 );
+ ok ( test32 == 0x01efcdabUL );
+
+ test64 = 0xabcdef0123456789ULL;
+ test_bswap64s ( &test64 );
+ ok ( test64 == 0x8967452301efcdabULL );
+}
+
+/** Byte-order swapping self-test */
+struct self_test byteswap_test __self_test = {
+ .name = "byteswap",
+ .exec = byteswap_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/cbc_test.c b/src/VBox/Devices/PC/ipxe/src/tests/cbc_test.c
new file mode 100644
index 00000000..ebff3268
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/cbc_test.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * CBC self-tests
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <ipxe/crypto.h>
+#include "cbc_test.h"
+
+/**
+ * Test CBC encryption
+ *
+ * @v cipher Cipher algorithm
+ * @v key Key
+ * @v key_len Length of key
+ * @v iv Initialisation vector
+ * @v plaintext Plaintext data
+ * @v expected_ciphertext Expected ciphertext data
+ * @v len Length of data
+ * @ret ok Ciphertext is as expected
+ */
+int cbc_test_encrypt ( struct cipher_algorithm *cipher, const void *key,
+ size_t key_len, const void *iv, const void *plaintext,
+ const void *expected_ciphertext, size_t len ) {
+ uint8_t ctx[ cipher->ctxsize ];
+ uint8_t ciphertext[ len ];
+ int rc;
+
+ /* Initialise cipher */
+ rc = cipher_setkey ( cipher, ctx, key, key_len );
+ assert ( rc == 0 );
+ cipher_setiv ( cipher, ctx, iv );
+
+ /* Perform encryption */
+ cipher_encrypt ( cipher, ctx, plaintext, ciphertext, len );
+
+ /* Verify result */
+ return ( memcmp ( ciphertext, expected_ciphertext, len ) == 0 );
+}
+
+/**
+ * Test CBC decryption
+ *
+ * @v cipher Cipher algorithm
+ * @v key Key
+ * @v key_len Length of key
+ * @v iv Initialisation vector
+ * @v ciphertext Ciphertext data
+ * @v expected_plaintext Expected plaintext data
+ * @v len Length of data
+ * @ret ok Plaintext is as expected
+ */
+int cbc_test_decrypt ( struct cipher_algorithm *cipher, const void *key,
+ size_t key_len, const void *iv, const void *ciphertext,
+ const void *expected_plaintext, size_t len ) {
+ uint8_t ctx[ cipher->ctxsize ];
+ uint8_t plaintext[ len ];
+ int rc;
+
+ /* Initialise cipher */
+ rc = cipher_setkey ( cipher, ctx, key, key_len );
+ assert ( rc == 0 );
+ cipher_setiv ( cipher, ctx, iv );
+
+ /* Perform encryption */
+ cipher_decrypt ( cipher, ctx, ciphertext, plaintext, len );
+
+ /* Verify result */
+ return ( memcmp ( plaintext, expected_plaintext, len ) == 0 );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/cbc_test.h b/src/VBox/Devices/PC/ipxe/src/tests/cbc_test.h
new file mode 100644
index 00000000..40356cc3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/cbc_test.h
@@ -0,0 +1,53 @@
+#ifndef _CBC_TEST_H
+#define _CBC_TEST_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/crypto.h>
+#include <ipxe/test.h>
+
+extern int cbc_test_encrypt ( struct cipher_algorithm *cipher, const void *key,
+ size_t key_len, const void *iv,
+ const void *plaintext,
+ const void *expected_ciphertext, size_t len );
+extern int cbc_test_decrypt ( struct cipher_algorithm *cipher, const void *key,
+ size_t key_len, const void *iv,
+ const void *ciphertext,
+ const void *expected_plaintext, size_t len );
+
+/**
+ * Report CBC encryption test result
+ *
+ * @v cipher Cipher algorithm
+ * @v key Key
+ * @v key_len Length of key
+ * @v iv Initialisation vector
+ * @v plaintext Plaintext data
+ * @v expected_ciphertext Expected ciphertext data
+ * @v len Length of data
+ */
+#define cbc_encrypt_ok( cipher, key, key_len, iv, plaintext, \
+ expected_ciphertext, len ) do { \
+ ok ( cbc_test_encrypt ( cipher, key, key_len, iv, plaintext, \
+ expected_ciphertext, len ) ); \
+ } while ( 0 )
+
+/**
+ * Report CBC decryption test result
+ *
+ * @v cipher Cipher algorithm
+ * @v key Key
+ * @v key_len Length of key
+ * @v iv Initialisation vector
+ * @v ciphertext Ciphertext data
+ * @v expected_plaintext Expected plaintext data
+ * @v len Length of data
+ */
+#define cbc_decrypt_ok( cipher, key, key_len, iv, ciphertext, \
+ expected_plaintext, len ) do { \
+ ok ( cbc_test_decrypt ( cipher, key, key_len, iv, ciphertext, \
+ expected_plaintext, len ) ); \
+ } while ( 0 )
+
+#endif /* _CBC_TEST_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/cms_test.c b/src/VBox/Devices/PC/ipxe/src/tests/cms_test.c
new file mode 100644
index 00000000..9de0228b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/cms_test.c
@@ -0,0 +1,1437 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * CMS self-tests
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <stdint.h>
+#include <string.h>
+#include <ipxe/sha256.h>
+#include <ipxe/x509.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/cms.h>
+#include <ipxe/test.h>
+
+/** Fingerprint algorithm used for X.509 test certificates */
+#define cms_test_algorithm sha256_algorithm
+
+/** CMS test code blob */
+struct cms_test_code {
+ /** Data */
+ const void *data;
+ /** Length of data */
+ size_t len;
+};
+
+/** CMS test signature */
+struct cms_test_signature {
+ /** Data */
+ const void *data;
+ /** Length of data */
+ size_t len;
+
+ /** Parsed signature */
+ struct cms_signature *sig;
+};
+
+/** Define inline data */
+#define DATA(...) { __VA_ARGS__ }
+
+/** Define inline fingerprint data */
+#define FINGERPRINT(...) { __VA_ARGS__ }
+
+/** Define a test code blob */
+#define SIGNED_CODE( name, DATA ) \
+ static const uint8_t name ## _data[] = DATA; \
+ static struct cms_test_code name = { \
+ .data = name ## _data, \
+ .len = sizeof ( name ## _data ), \
+ }
+
+/** Define a test signature */
+#define SIGNATURE( name, DATA ) \
+ static const uint8_t name ## _data[] = DATA; \
+ static struct cms_test_signature name = { \
+ .data = name ## _data, \
+ .len = sizeof ( name ## _data ), \
+ }
+
+/** Code that has been signed */
+SIGNED_CODE ( test_code,
+ DATA ( 0x23, 0x21, 0x69, 0x70, 0x78, 0x65, 0x0a, 0x0a, 0x65, 0x63,
+ 0x68, 0x6f, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
+ 0x20, 0x61, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65,
+ 0x64, 0x20, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x63, 0x72,
+ 0x69, 0x70, 0x74, 0x2e, 0x20, 0x20, 0x44, 0x6f, 0x20, 0x61,
+ 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x79, 0x6f,
+ 0x75, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x21, 0x0a, 0x73, 0x68,
+ 0x65, 0x6c, 0x6c, 0x0a ) );
+
+/** Code that has not been signed */
+SIGNED_CODE ( bad_code,
+ DATA ( 0x23, 0x21, 0x69, 0x70, 0x78, 0x65, 0x0a, 0x0a, 0x65, 0x63,
+ 0x68, 0x6f, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
+ 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6c, 0x69, 0x63, 0x69, 0x6f,
+ 0x75, 0x73, 0x20, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x2e, 0x20, 0x20, 0x44, 0x6f, 0x20,
+ 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x79,
+ 0x6f, 0x75, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x21, 0x0a, 0x73,
+ 0x68, 0x65, 0x6c, 0x6c, 0x0a ) );
+
+/** Valid signature */
+SIGNATURE ( codesigned_sig,
+ DATA ( 0x30, 0x82, 0x0c, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x0c, 0x32, 0x30,
+ 0x82, 0x0c, 0x2e, 0x02, 0x01, 0x01, 0x31, 0x09, 0x30, 0x07,
+ 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0b, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01,
+ 0xa0, 0x82, 0x0a, 0xd8, 0x30, 0x82, 0x02, 0xac, 0x30, 0x82,
+ 0x02, 0x15, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x04,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47,
+ 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d,
+ 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e,
+ 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c,
+ 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
+ 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72,
+ 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c,
+ 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61,
+ 0x66, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32,
+ 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x34,
+ 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x33, 0x32, 0x32, 0x30,
+ 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x30, 0x81, 0x88, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65,
+ 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x16, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67,
+ 0x6e, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78,
+ 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89,
+ 0x02, 0x81, 0x81, 0x00, 0xc3, 0x3a, 0xdb, 0x7b, 0x17, 0x24,
+ 0x47, 0xb9, 0xb9, 0x17, 0x02, 0x17, 0xa8, 0xce, 0x21, 0x97,
+ 0x92, 0x2f, 0x65, 0x53, 0x3b, 0x7e, 0x5c, 0x7d, 0x13, 0xab,
+ 0x46, 0xe8, 0x4a, 0x44, 0x6c, 0x5d, 0x8f, 0xa2, 0x0c, 0x1d,
+ 0x69, 0xc1, 0x66, 0x48, 0xc4, 0x1a, 0xc9, 0x32, 0xe5, 0x97,
+ 0x92, 0xb7, 0x11, 0xa7, 0x1f, 0x21, 0xac, 0x96, 0xcb, 0x85,
+ 0x10, 0xcc, 0x23, 0x20, 0x51, 0xdd, 0xaf, 0xbe, 0xf5, 0x23,
+ 0x12, 0x0b, 0x03, 0xe9, 0xf9, 0x61, 0x86, 0x64, 0x82, 0xa4,
+ 0xfd, 0x53, 0x24, 0xdf, 0xc2, 0x96, 0x2e, 0x28, 0xbb, 0x94,
+ 0xfb, 0x2c, 0xaf, 0x9e, 0x07, 0x79, 0x96, 0x48, 0x24, 0xf0,
+ 0x9d, 0xb3, 0x11, 0x3d, 0x4c, 0x2e, 0xd8, 0xc9, 0xf9, 0x69,
+ 0xca, 0xdb, 0x16, 0xbd, 0x4c, 0xc5, 0xce, 0x28, 0x18, 0xdc,
+ 0x88, 0x1b, 0x31, 0x0d, 0x10, 0x6b, 0x5b, 0x10, 0xe9, 0xcc,
+ 0xfe, 0xa1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x24, 0x30,
+ 0x22, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04,
+ 0x03, 0x02, 0x07, 0x80, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d,
+ 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01,
+ 0x05, 0x05, 0x07, 0x03, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x03, 0x81, 0x81, 0x00, 0x22, 0x20, 0xe4, 0xc5, 0x0a, 0xef,
+ 0xae, 0xab, 0xbd, 0xab, 0x96, 0x56, 0x2c, 0x30, 0xeb, 0x06,
+ 0x84, 0xa0, 0x96, 0x37, 0x1a, 0x29, 0x2b, 0xeb, 0x8c, 0xb5,
+ 0x23, 0x22, 0x10, 0xef, 0x81, 0xe8, 0xdc, 0xa9, 0xdd, 0x8e,
+ 0x1d, 0x2c, 0xfc, 0xf5, 0x07, 0x19, 0xb7, 0x94, 0x91, 0xf7,
+ 0x2e, 0x07, 0xa1, 0xbc, 0xc5, 0x17, 0x34, 0xbe, 0x8a, 0x62,
+ 0x05, 0x5e, 0x9f, 0xe3, 0xce, 0xfd, 0x16, 0x42, 0xca, 0x25,
+ 0x2e, 0x0a, 0x03, 0x54, 0xd5, 0x3a, 0x52, 0x7f, 0x99, 0x94,
+ 0x96, 0xc6, 0xf5, 0xf0, 0xe3, 0x09, 0xd6, 0x00, 0x9b, 0x6f,
+ 0x0b, 0xa4, 0x9a, 0x13, 0x70, 0x9e, 0x67, 0xf9, 0x8c, 0x64,
+ 0xab, 0x22, 0x5d, 0xb3, 0xba, 0x2d, 0xe2, 0x70, 0xb8, 0x0c,
+ 0x6d, 0xd3, 0x12, 0x70, 0x5e, 0x04, 0x80, 0xef, 0x5e, 0x42,
+ 0x0a, 0x77, 0x57, 0x79, 0xa2, 0x1d, 0xe5, 0xbd, 0x20, 0xce,
+ 0x45, 0xc3, 0x30, 0x82, 0x02, 0xb3, 0x30, 0x82, 0x02, 0x1c,
+ 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31,
+ 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e,
+ 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73,
+ 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
+ 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72,
+ 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53,
+ 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64,
+ 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c,
+ 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31,
+ 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16,
+ 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d,
+ 0x74, 0x65, 0x73, 0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20,
+ 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33,
+ 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17,
+ 0x0d, 0x31, 0x34, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x30,
+ 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x90, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42,
+ 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
+ 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65,
+ 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06,
+ 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62,
+ 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20,
+ 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74,
+ 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b,
+ 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67,
+ 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+ 0x1e, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66,
+ 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43,
+ 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
+ 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+ 0xc9, 0x3a, 0xee, 0xc6, 0x3c, 0xac, 0x4d, 0x81, 0xc6, 0x98,
+ 0x5e, 0xe1, 0x48, 0x66, 0x1a, 0x1e, 0x60, 0x19, 0x41, 0xae,
+ 0xca, 0x14, 0x97, 0xc8, 0x3a, 0x50, 0xb6, 0x48, 0xf5, 0x42,
+ 0xac, 0x0f, 0xe1, 0xe3, 0x47, 0xf0, 0xbf, 0x7c, 0xd0, 0xee,
+ 0x8f, 0xb7, 0xa6, 0x19, 0xad, 0xbb, 0xc5, 0x1b, 0x34, 0x38,
+ 0xc8, 0xbd, 0x55, 0x84, 0x93, 0x72, 0xaf, 0x84, 0xfc, 0x9b,
+ 0x97, 0x1d, 0xb5, 0x54, 0x24, 0xd6, 0x5d, 0xb7, 0x31, 0xf4,
+ 0xbd, 0x3b, 0x40, 0x97, 0xc0, 0xa9, 0x5a, 0x2a, 0xcb, 0x6b,
+ 0x98, 0x07, 0xdb, 0xb5, 0x9f, 0xe8, 0x31, 0x3f, 0x01, 0x46,
+ 0x46, 0x70, 0x05, 0xa2, 0x0f, 0x8c, 0x7a, 0x61, 0xf3, 0xdf,
+ 0xdb, 0xa1, 0x37, 0x2c, 0x88, 0x6a, 0x81, 0x21, 0x12, 0x4c,
+ 0xf5, 0xcd, 0xaf, 0xc9, 0xd2, 0x36, 0x3d, 0x82, 0xd1, 0xca,
+ 0x19, 0xaf, 0x4e, 0xae, 0x50, 0x71, 0x44, 0xbf, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x23, 0x30, 0x21, 0x30, 0x0f, 0x06,
+ 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30,
+ 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
+ 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x5d,
+ 0x3c, 0xb3, 0x52, 0x19, 0xa6, 0x9e, 0x4a, 0x44, 0x98, 0xbf,
+ 0x51, 0x20, 0x47, 0x0a, 0xf3, 0x26, 0x1a, 0xcc, 0x35, 0x2f,
+ 0xc9, 0xed, 0xe0, 0x9d, 0x46, 0xeb, 0xbc, 0x7e, 0xc9, 0xb9,
+ 0x1d, 0x76, 0xa4, 0x1d, 0xc2, 0xd9, 0x16, 0x29, 0x77, 0x01,
+ 0x40, 0xdd, 0xe5, 0xcb, 0x28, 0x91, 0x3a, 0x0c, 0x13, 0x01,
+ 0x1b, 0x72, 0x62, 0x45, 0x27, 0xfd, 0xd7, 0x00, 0x47, 0x36,
+ 0x09, 0x1e, 0x7b, 0xd2, 0xcb, 0x95, 0x3d, 0x28, 0x82, 0xce,
+ 0x83, 0x59, 0x32, 0xf9, 0xe6, 0xec, 0x89, 0xac, 0x88, 0x45,
+ 0x22, 0x88, 0x6f, 0x5e, 0xa2, 0x79, 0x95, 0xba, 0xb9, 0xc9,
+ 0xb6, 0x4c, 0x7c, 0xb4, 0x29, 0xa1, 0x02, 0xf5, 0xac, 0x5d,
+ 0x8e, 0x52, 0xeb, 0xe8, 0xb1, 0x56, 0x49, 0xb3, 0x77, 0x62,
+ 0x7d, 0x87, 0x4d, 0x17, 0xf2, 0x62, 0x83, 0x08, 0x59, 0x21,
+ 0x60, 0x0d, 0x84, 0x8e, 0x5a, 0x84, 0xf6, 0x30, 0x82, 0x02,
+ 0xb3, 0x30, 0x82, 0x02, 0x1c, 0xa0, 0x03, 0x02, 0x01, 0x02,
+ 0x02, 0x09, 0x00, 0xc6, 0xb8, 0x9c, 0x58, 0xd2, 0xdc, 0xc9,
+ 0x5d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65,
+ 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65,
+ 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x72, 0x6f,
+ 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+ 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33,
+ 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x39, 0x30, 0x38, 0x30, 0x38,
+ 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x88,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12,
+ 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43,
+ 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18,
+ 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46,
+ 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73,
+ 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03,
+ 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e,
+ 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73,
+ 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x72,
+ 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81,
+ 0x89, 0x02, 0x81, 0x81, 0x00, 0xaa, 0x72, 0xb5, 0xc1, 0x73,
+ 0xf4, 0x95, 0x76, 0xa4, 0x27, 0xab, 0x5e, 0xeb, 0x1d, 0x9d,
+ 0xd0, 0x04, 0xb2, 0x93, 0x05, 0xc7, 0xfa, 0x75, 0x84, 0x66,
+ 0xe6, 0x3a, 0x26, 0x1f, 0xbc, 0x2d, 0xfd, 0x8f, 0x59, 0x64,
+ 0xac, 0xcf, 0x65, 0x9d, 0x82, 0x23, 0xc3, 0x72, 0x93, 0xf2,
+ 0x40, 0x68, 0x32, 0xd1, 0xb8, 0xf1, 0x47, 0x61, 0x50, 0xea,
+ 0xbc, 0xcc, 0x3c, 0x6b, 0x74, 0x7a, 0xec, 0x2b, 0x75, 0xa6,
+ 0xc2, 0xa2, 0xb8, 0xbf, 0x23, 0x48, 0x97, 0xd5, 0xaf, 0x77,
+ 0xc1, 0x92, 0x88, 0xd7, 0x38, 0xb7, 0x9e, 0xda, 0xee, 0x72,
+ 0x04, 0xcb, 0x96, 0xe5, 0xdb, 0xfd, 0x9b, 0x5d, 0x99, 0x4e,
+ 0x7a, 0x60, 0x23, 0x34, 0xa4, 0x8d, 0xd7, 0x6c, 0xe7, 0x5d,
+ 0x93, 0x97, 0xe1, 0xab, 0x36, 0x2c, 0x24, 0x16, 0x92, 0x66,
+ 0xf6, 0x6a, 0x14, 0x23, 0x1d, 0x18, 0xb9, 0x44, 0x24, 0x61,
+ 0x6b, 0xd3, 0x75, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x23,
+ 0x30, 0x21, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
+ 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+ 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04,
+ 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x03, 0x81, 0x81, 0x00, 0x94, 0x9e, 0xea, 0x17, 0x8d, 0x27,
+ 0xa9, 0x17, 0xe5, 0xa9, 0x19, 0xbe, 0x82, 0x36, 0xbd, 0xac,
+ 0x74, 0xf3, 0x6e, 0x75, 0x71, 0x30, 0x1c, 0x05, 0x80, 0x6d,
+ 0x1a, 0x69, 0x37, 0x86, 0x9c, 0x77, 0x75, 0x29, 0xa1, 0xc6,
+ 0xb7, 0x11, 0x0a, 0x63, 0x27, 0xee, 0xb1, 0xc8, 0x94, 0xa9,
+ 0x2e, 0x56, 0x8f, 0xca, 0x9d, 0xbe, 0xf4, 0xdb, 0x63, 0x97,
+ 0x68, 0x3b, 0x13, 0xf8, 0x6a, 0xa5, 0xd1, 0x3d, 0xed, 0xbb,
+ 0x86, 0x9d, 0x42, 0xfc, 0x15, 0x0a, 0x04, 0xf8, 0x3c, 0x0e,
+ 0xc4, 0x86, 0x05, 0x57, 0x56, 0x96, 0xf6, 0xc0, 0x18, 0x53,
+ 0xb0, 0xc5, 0xf0, 0xca, 0x72, 0x77, 0x77, 0xc9, 0x8e, 0x90,
+ 0xa5, 0x4b, 0xb6, 0x80, 0x4a, 0x4c, 0x34, 0x6f, 0xc9, 0xe8,
+ 0x6f, 0xc2, 0x28, 0xdf, 0x93, 0xa9, 0xf5, 0x63, 0x18, 0xc0,
+ 0xec, 0x9e, 0xd5, 0x19, 0x36, 0xc5, 0x94, 0x10, 0xd4, 0x72,
+ 0xd2, 0xb8, 0x30, 0x82, 0x02, 0xb6, 0x30, 0x82, 0x02, 0x1f,
+ 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x30, 0x81, 0x90, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31,
+ 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e,
+ 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73,
+ 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
+ 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72,
+ 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53,
+ 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64,
+ 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c,
+ 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31,
+ 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e,
+ 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d,
+ 0x74, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72,
+ 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32,
+ 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x31,
+ 0x34, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x30, 0x31, 0x33,
+ 0x33, 0x5a, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17,
+ 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43,
+ 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68,
+ 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
+ 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79,
+ 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31,
+ 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08,
+ 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f,
+ 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69,
+ 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74,
+ 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x43,
+ 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
+ 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+ 0xc3, 0x55, 0xad, 0xdf, 0x7b, 0xd1, 0x48, 0xc3, 0xd3, 0x02,
+ 0x54, 0x6c, 0x92, 0x45, 0x22, 0x3d, 0x90, 0xd8, 0xc7, 0x13,
+ 0xcd, 0xc1, 0x59, 0xc6, 0xe0, 0xad, 0x0e, 0xe6, 0xdb, 0x3b,
+ 0xe8, 0x63, 0xea, 0x4e, 0xb6, 0xea, 0x50, 0xea, 0x6e, 0x33,
+ 0x9d, 0x28, 0x25, 0x42, 0x49, 0xd0, 0xf0, 0xed, 0xc5, 0x5b,
+ 0x6b, 0x4a, 0xe7, 0x45, 0xfa, 0xd3, 0x3f, 0xae, 0xde, 0x5a,
+ 0x90, 0xab, 0xf1, 0x61, 0x2f, 0x40, 0x5e, 0xcf, 0x8b, 0x0b,
+ 0x10, 0x59, 0xa9, 0xd0, 0x1e, 0x0f, 0x18, 0x6b, 0x92, 0xd8,
+ 0x9f, 0x58, 0x10, 0x84, 0xb6, 0x15, 0xe8, 0x5b, 0xc4, 0xa0,
+ 0x3e, 0x49, 0x8b, 0xea, 0xdd, 0xa9, 0x7e, 0x32, 0x26, 0x9a,
+ 0x68, 0x44, 0xf0, 0x30, 0xca, 0x2a, 0xd6, 0x19, 0x7a, 0x80,
+ 0xfd, 0xd7, 0xfc, 0xc7, 0x5d, 0xe7, 0x61, 0xd2, 0x3f, 0x1f,
+ 0x2c, 0x40, 0x70, 0x7b, 0x34, 0xcb, 0x08, 0xa9, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x26, 0x30, 0x24, 0x30, 0x12, 0x06,
+ 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
+ 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x0e, 0x06,
+ 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03,
+ 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+ 0x81, 0x00, 0x40, 0xd2, 0x70, 0x02, 0x08, 0x19, 0xa0, 0xb8,
+ 0x8d, 0x9d, 0x3d, 0x62, 0x41, 0x90, 0x2a, 0x36, 0x4a, 0x8b,
+ 0x21, 0x42, 0x9a, 0xb4, 0xc5, 0xf8, 0x79, 0x17, 0xd7, 0x64,
+ 0x4d, 0xbf, 0x8f, 0x6a, 0x04, 0x54, 0x7a, 0x0b, 0xd4, 0xb5,
+ 0x0e, 0xab, 0xf7, 0xb7, 0x06, 0x2b, 0xf8, 0xde, 0x87, 0xb2,
+ 0x37, 0x3b, 0x95, 0x01, 0xba, 0x9f, 0x8f, 0xec, 0x0a, 0x86,
+ 0xca, 0x51, 0xb6, 0x25, 0x73, 0x2f, 0xa1, 0x66, 0xc8, 0x7a,
+ 0x5e, 0x51, 0xbd, 0x49, 0xb5, 0x75, 0xda, 0xea, 0xe5, 0xeb,
+ 0x5d, 0xe3, 0xb0, 0xad, 0x49, 0x9f, 0x8b, 0xfd, 0x89, 0xb3,
+ 0xb7, 0xb2, 0x4c, 0x7d, 0x8a, 0x29, 0xb2, 0xbe, 0x04, 0xef,
+ 0x9c, 0x73, 0x3c, 0xea, 0xa3, 0x9f, 0x07, 0x66, 0x5a, 0x2f,
+ 0x38, 0xad, 0x1a, 0xeb, 0xe1, 0xb0, 0x62, 0x14, 0x55, 0xdc,
+ 0x8c, 0x83, 0xbb, 0xc7, 0x13, 0x04, 0x41, 0x54, 0xf1, 0x45,
+ 0x31, 0x82, 0x01, 0x33, 0x30, 0x82, 0x01, 0x2f, 0x02, 0x01,
+ 0x01, 0x30, 0x81, 0x8e, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42,
+ 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
+ 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65,
+ 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06,
+ 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62,
+ 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20,
+ 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74,
+ 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b,
+ 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67,
+ 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+ 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66,
+ 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66,
+ 0x20, 0x43, 0x41, 0x02, 0x01, 0x04, 0x30, 0x07, 0x06, 0x05,
+ 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
+ 0x04, 0x81, 0x80, 0x1f, 0x95, 0x53, 0x9c, 0x63, 0xcc, 0x9e,
+ 0xe3, 0x41, 0x30, 0xaf, 0x66, 0xac, 0x7c, 0x39, 0x69, 0xa0,
+ 0x02, 0xe3, 0x28, 0xfa, 0xf6, 0x71, 0xf4, 0xcf, 0x97, 0x2a,
+ 0xbb, 0xe0, 0x1d, 0x71, 0x73, 0x4a, 0xa7, 0xea, 0xb0, 0x72,
+ 0xc3, 0xd2, 0xba, 0x52, 0x42, 0x06, 0x88, 0x4a, 0xa6, 0x41,
+ 0x1d, 0x2f, 0x82, 0xb3, 0x7d, 0x32, 0x59, 0x34, 0x4e, 0x47,
+ 0x1b, 0xaa, 0x5e, 0x90, 0xe2, 0x73, 0x62, 0x2d, 0x6f, 0x6c,
+ 0x47, 0x52, 0x05, 0x90, 0xcb, 0xac, 0x30, 0xa8, 0x20, 0x71,
+ 0x14, 0x39, 0x16, 0x85, 0x3d, 0x32, 0x2f, 0x9d, 0x31, 0x97,
+ 0xa8, 0x96, 0xb9, 0xf2, 0x2b, 0xdc, 0xa6, 0x2f, 0x68, 0xc7,
+ 0xac, 0x46, 0xa2, 0xc7, 0x26, 0xd0, 0xde, 0xac, 0x1d, 0x5d,
+ 0x70, 0x65, 0xc6, 0x26, 0xdd, 0x30, 0x3f, 0x3a, 0xbd, 0x5e,
+ 0x8f, 0x87, 0x64, 0xab, 0xe7, 0xf9, 0x71, 0x64, 0x03, 0x05,
+ 0xbf ) );
+
+/** Signature with a broken certificate chain */
+SIGNATURE ( brokenchain_sig,
+ DATA ( 0x30, 0x82, 0x09, 0x8a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x09, 0x7b, 0x30,
+ 0x82, 0x09, 0x77, 0x02, 0x01, 0x01, 0x31, 0x09, 0x30, 0x07,
+ 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0b, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01,
+ 0xa0, 0x82, 0x08, 0x21, 0x30, 0x82, 0x02, 0xac, 0x30, 0x82,
+ 0x02, 0x15, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x04,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47,
+ 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d,
+ 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e,
+ 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c,
+ 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
+ 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72,
+ 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c,
+ 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61,
+ 0x66, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32,
+ 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x34,
+ 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x33, 0x32, 0x32, 0x30,
+ 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x30, 0x81, 0x88, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65,
+ 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x16, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67,
+ 0x6e, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78,
+ 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89,
+ 0x02, 0x81, 0x81, 0x00, 0xc3, 0x3a, 0xdb, 0x7b, 0x17, 0x24,
+ 0x47, 0xb9, 0xb9, 0x17, 0x02, 0x17, 0xa8, 0xce, 0x21, 0x97,
+ 0x92, 0x2f, 0x65, 0x53, 0x3b, 0x7e, 0x5c, 0x7d, 0x13, 0xab,
+ 0x46, 0xe8, 0x4a, 0x44, 0x6c, 0x5d, 0x8f, 0xa2, 0x0c, 0x1d,
+ 0x69, 0xc1, 0x66, 0x48, 0xc4, 0x1a, 0xc9, 0x32, 0xe5, 0x97,
+ 0x92, 0xb7, 0x11, 0xa7, 0x1f, 0x21, 0xac, 0x96, 0xcb, 0x85,
+ 0x10, 0xcc, 0x23, 0x20, 0x51, 0xdd, 0xaf, 0xbe, 0xf5, 0x23,
+ 0x12, 0x0b, 0x03, 0xe9, 0xf9, 0x61, 0x86, 0x64, 0x82, 0xa4,
+ 0xfd, 0x53, 0x24, 0xdf, 0xc2, 0x96, 0x2e, 0x28, 0xbb, 0x94,
+ 0xfb, 0x2c, 0xaf, 0x9e, 0x07, 0x79, 0x96, 0x48, 0x24, 0xf0,
+ 0x9d, 0xb3, 0x11, 0x3d, 0x4c, 0x2e, 0xd8, 0xc9, 0xf9, 0x69,
+ 0xca, 0xdb, 0x16, 0xbd, 0x4c, 0xc5, 0xce, 0x28, 0x18, 0xdc,
+ 0x88, 0x1b, 0x31, 0x0d, 0x10, 0x6b, 0x5b, 0x10, 0xe9, 0xcc,
+ 0xfe, 0xa1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x24, 0x30,
+ 0x22, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04,
+ 0x03, 0x02, 0x07, 0x80, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d,
+ 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01,
+ 0x05, 0x05, 0x07, 0x03, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x03, 0x81, 0x81, 0x00, 0x22, 0x20, 0xe4, 0xc5, 0x0a, 0xef,
+ 0xae, 0xab, 0xbd, 0xab, 0x96, 0x56, 0x2c, 0x30, 0xeb, 0x06,
+ 0x84, 0xa0, 0x96, 0x37, 0x1a, 0x29, 0x2b, 0xeb, 0x8c, 0xb5,
+ 0x23, 0x22, 0x10, 0xef, 0x81, 0xe8, 0xdc, 0xa9, 0xdd, 0x8e,
+ 0x1d, 0x2c, 0xfc, 0xf5, 0x07, 0x19, 0xb7, 0x94, 0x91, 0xf7,
+ 0x2e, 0x07, 0xa1, 0xbc, 0xc5, 0x17, 0x34, 0xbe, 0x8a, 0x62,
+ 0x05, 0x5e, 0x9f, 0xe3, 0xce, 0xfd, 0x16, 0x42, 0xca, 0x25,
+ 0x2e, 0x0a, 0x03, 0x54, 0xd5, 0x3a, 0x52, 0x7f, 0x99, 0x94,
+ 0x96, 0xc6, 0xf5, 0xf0, 0xe3, 0x09, 0xd6, 0x00, 0x9b, 0x6f,
+ 0x0b, 0xa4, 0x9a, 0x13, 0x70, 0x9e, 0x67, 0xf9, 0x8c, 0x64,
+ 0xab, 0x22, 0x5d, 0xb3, 0xba, 0x2d, 0xe2, 0x70, 0xb8, 0x0c,
+ 0x6d, 0xd3, 0x12, 0x70, 0x5e, 0x04, 0x80, 0xef, 0x5e, 0x42,
+ 0x0a, 0x77, 0x57, 0x79, 0xa2, 0x1d, 0xe5, 0xbd, 0x20, 0xce,
+ 0x45, 0xc3, 0x30, 0x82, 0x02, 0xb3, 0x30, 0x82, 0x02, 0x1c,
+ 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xc6, 0xb8,
+ 0x9c, 0x58, 0xd2, 0xdc, 0xc9, 0x5d, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
+ 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30,
+ 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69,
+ 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+ 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69,
+ 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30,
+ 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50,
+ 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65,
+ 0x73, 0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32,
+ 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x33,
+ 0x39, 0x30, 0x38, 0x30, 0x38, 0x30, 0x30, 0x30, 0x31, 0x33,
+ 0x33, 0x5a, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17,
+ 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43,
+ 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68,
+ 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
+ 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79,
+ 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31,
+ 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08,
+ 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f,
+ 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69,
+ 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74,
+ 0x65, 0x73, 0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43,
+ 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
+ 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+ 0xaa, 0x72, 0xb5, 0xc1, 0x73, 0xf4, 0x95, 0x76, 0xa4, 0x27,
+ 0xab, 0x5e, 0xeb, 0x1d, 0x9d, 0xd0, 0x04, 0xb2, 0x93, 0x05,
+ 0xc7, 0xfa, 0x75, 0x84, 0x66, 0xe6, 0x3a, 0x26, 0x1f, 0xbc,
+ 0x2d, 0xfd, 0x8f, 0x59, 0x64, 0xac, 0xcf, 0x65, 0x9d, 0x82,
+ 0x23, 0xc3, 0x72, 0x93, 0xf2, 0x40, 0x68, 0x32, 0xd1, 0xb8,
+ 0xf1, 0x47, 0x61, 0x50, 0xea, 0xbc, 0xcc, 0x3c, 0x6b, 0x74,
+ 0x7a, 0xec, 0x2b, 0x75, 0xa6, 0xc2, 0xa2, 0xb8, 0xbf, 0x23,
+ 0x48, 0x97, 0xd5, 0xaf, 0x77, 0xc1, 0x92, 0x88, 0xd7, 0x38,
+ 0xb7, 0x9e, 0xda, 0xee, 0x72, 0x04, 0xcb, 0x96, 0xe5, 0xdb,
+ 0xfd, 0x9b, 0x5d, 0x99, 0x4e, 0x7a, 0x60, 0x23, 0x34, 0xa4,
+ 0x8d, 0xd7, 0x6c, 0xe7, 0x5d, 0x93, 0x97, 0xe1, 0xab, 0x36,
+ 0x2c, 0x24, 0x16, 0x92, 0x66, 0xf6, 0x6a, 0x14, 0x23, 0x1d,
+ 0x18, 0xb9, 0x44, 0x24, 0x61, 0x6b, 0xd3, 0x75, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x23, 0x30, 0x21, 0x30, 0x0f, 0x06,
+ 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30,
+ 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
+ 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x94,
+ 0x9e, 0xea, 0x17, 0x8d, 0x27, 0xa9, 0x17, 0xe5, 0xa9, 0x19,
+ 0xbe, 0x82, 0x36, 0xbd, 0xac, 0x74, 0xf3, 0x6e, 0x75, 0x71,
+ 0x30, 0x1c, 0x05, 0x80, 0x6d, 0x1a, 0x69, 0x37, 0x86, 0x9c,
+ 0x77, 0x75, 0x29, 0xa1, 0xc6, 0xb7, 0x11, 0x0a, 0x63, 0x27,
+ 0xee, 0xb1, 0xc8, 0x94, 0xa9, 0x2e, 0x56, 0x8f, 0xca, 0x9d,
+ 0xbe, 0xf4, 0xdb, 0x63, 0x97, 0x68, 0x3b, 0x13, 0xf8, 0x6a,
+ 0xa5, 0xd1, 0x3d, 0xed, 0xbb, 0x86, 0x9d, 0x42, 0xfc, 0x15,
+ 0x0a, 0x04, 0xf8, 0x3c, 0x0e, 0xc4, 0x86, 0x05, 0x57, 0x56,
+ 0x96, 0xf6, 0xc0, 0x18, 0x53, 0xb0, 0xc5, 0xf0, 0xca, 0x72,
+ 0x77, 0x77, 0xc9, 0x8e, 0x90, 0xa5, 0x4b, 0xb6, 0x80, 0x4a,
+ 0x4c, 0x34, 0x6f, 0xc9, 0xe8, 0x6f, 0xc2, 0x28, 0xdf, 0x93,
+ 0xa9, 0xf5, 0x63, 0x18, 0xc0, 0xec, 0x9e, 0xd5, 0x19, 0x36,
+ 0xc5, 0x94, 0x10, 0xd4, 0x72, 0xd2, 0xb8, 0x30, 0x82, 0x02,
+ 0xb6, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, 0x02,
+ 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81,
+ 0x90, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72,
+ 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31,
+ 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09,
+ 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31,
+ 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f,
+ 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06,
+ 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65,
+ 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x0c, 0x1e, 0x69, 0x50, 0x58, 0x45, 0x20,
+ 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61,
+ 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+ 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33,
+ 0x33, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x32, 0x31, 0x37,
+ 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x88,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12,
+ 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43,
+ 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18,
+ 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46,
+ 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73,
+ 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03,
+ 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e,
+ 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73,
+ 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c,
+ 0x65, 0x61, 0x66, 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81,
+ 0x89, 0x02, 0x81, 0x81, 0x00, 0xc3, 0x55, 0xad, 0xdf, 0x7b,
+ 0xd1, 0x48, 0xc3, 0xd3, 0x02, 0x54, 0x6c, 0x92, 0x45, 0x22,
+ 0x3d, 0x90, 0xd8, 0xc7, 0x13, 0xcd, 0xc1, 0x59, 0xc6, 0xe0,
+ 0xad, 0x0e, 0xe6, 0xdb, 0x3b, 0xe8, 0x63, 0xea, 0x4e, 0xb6,
+ 0xea, 0x50, 0xea, 0x6e, 0x33, 0x9d, 0x28, 0x25, 0x42, 0x49,
+ 0xd0, 0xf0, 0xed, 0xc5, 0x5b, 0x6b, 0x4a, 0xe7, 0x45, 0xfa,
+ 0xd3, 0x3f, 0xae, 0xde, 0x5a, 0x90, 0xab, 0xf1, 0x61, 0x2f,
+ 0x40, 0x5e, 0xcf, 0x8b, 0x0b, 0x10, 0x59, 0xa9, 0xd0, 0x1e,
+ 0x0f, 0x18, 0x6b, 0x92, 0xd8, 0x9f, 0x58, 0x10, 0x84, 0xb6,
+ 0x15, 0xe8, 0x5b, 0xc4, 0xa0, 0x3e, 0x49, 0x8b, 0xea, 0xdd,
+ 0xa9, 0x7e, 0x32, 0x26, 0x9a, 0x68, 0x44, 0xf0, 0x30, 0xca,
+ 0x2a, 0xd6, 0x19, 0x7a, 0x80, 0xfd, 0xd7, 0xfc, 0xc7, 0x5d,
+ 0xe7, 0x61, 0xd2, 0x3f, 0x1f, 0x2c, 0x40, 0x70, 0x7b, 0x34,
+ 0xcb, 0x08, 0xa9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x26,
+ 0x30, 0x24, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
+ 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
+ 0x01, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01,
+ 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x40, 0xd2, 0x70,
+ 0x02, 0x08, 0x19, 0xa0, 0xb8, 0x8d, 0x9d, 0x3d, 0x62, 0x41,
+ 0x90, 0x2a, 0x36, 0x4a, 0x8b, 0x21, 0x42, 0x9a, 0xb4, 0xc5,
+ 0xf8, 0x79, 0x17, 0xd7, 0x64, 0x4d, 0xbf, 0x8f, 0x6a, 0x04,
+ 0x54, 0x7a, 0x0b, 0xd4, 0xb5, 0x0e, 0xab, 0xf7, 0xb7, 0x06,
+ 0x2b, 0xf8, 0xde, 0x87, 0xb2, 0x37, 0x3b, 0x95, 0x01, 0xba,
+ 0x9f, 0x8f, 0xec, 0x0a, 0x86, 0xca, 0x51, 0xb6, 0x25, 0x73,
+ 0x2f, 0xa1, 0x66, 0xc8, 0x7a, 0x5e, 0x51, 0xbd, 0x49, 0xb5,
+ 0x75, 0xda, 0xea, 0xe5, 0xeb, 0x5d, 0xe3, 0xb0, 0xad, 0x49,
+ 0x9f, 0x8b, 0xfd, 0x89, 0xb3, 0xb7, 0xb2, 0x4c, 0x7d, 0x8a,
+ 0x29, 0xb2, 0xbe, 0x04, 0xef, 0x9c, 0x73, 0x3c, 0xea, 0xa3,
+ 0x9f, 0x07, 0x66, 0x5a, 0x2f, 0x38, 0xad, 0x1a, 0xeb, 0xe1,
+ 0xb0, 0x62, 0x14, 0x55, 0xdc, 0x8c, 0x83, 0xbb, 0xc7, 0x13,
+ 0x04, 0x41, 0x54, 0xf1, 0x45, 0x31, 0x82, 0x01, 0x33, 0x30,
+ 0x82, 0x01, 0x2f, 0x02, 0x01, 0x01, 0x30, 0x81, 0x8e, 0x30,
+ 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62,
+ 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65,
+ 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
+ 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65,
+ 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
+ 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f,
+ 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78,
+ 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45,
+ 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x43, 0x41, 0x02, 0x01,
+ 0x04, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x81, 0x80, 0x1f, 0x95,
+ 0x53, 0x9c, 0x63, 0xcc, 0x9e, 0xe3, 0x41, 0x30, 0xaf, 0x66,
+ 0xac, 0x7c, 0x39, 0x69, 0xa0, 0x02, 0xe3, 0x28, 0xfa, 0xf6,
+ 0x71, 0xf4, 0xcf, 0x97, 0x2a, 0xbb, 0xe0, 0x1d, 0x71, 0x73,
+ 0x4a, 0xa7, 0xea, 0xb0, 0x72, 0xc3, 0xd2, 0xba, 0x52, 0x42,
+ 0x06, 0x88, 0x4a, 0xa6, 0x41, 0x1d, 0x2f, 0x82, 0xb3, 0x7d,
+ 0x32, 0x59, 0x34, 0x4e, 0x47, 0x1b, 0xaa, 0x5e, 0x90, 0xe2,
+ 0x73, 0x62, 0x2d, 0x6f, 0x6c, 0x47, 0x52, 0x05, 0x90, 0xcb,
+ 0xac, 0x30, 0xa8, 0x20, 0x71, 0x14, 0x39, 0x16, 0x85, 0x3d,
+ 0x32, 0x2f, 0x9d, 0x31, 0x97, 0xa8, 0x96, 0xb9, 0xf2, 0x2b,
+ 0xdc, 0xa6, 0x2f, 0x68, 0xc7, 0xac, 0x46, 0xa2, 0xc7, 0x26,
+ 0xd0, 0xde, 0xac, 0x1d, 0x5d, 0x70, 0x65, 0xc6, 0x26, 0xdd,
+ 0x30, 0x3f, 0x3a, 0xbd, 0x5e, 0x8f, 0x87, 0x64, 0xab, 0xe7,
+ 0xf9, 0x71, 0x64, 0x03, 0x05, 0xbf ) );
+
+/** Signature generated with a non-code-signing certificate */
+SIGNATURE ( genericsigned_sig,
+ DATA ( 0x30, 0x82, 0x0c, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x0c, 0x20, 0x30,
+ 0x82, 0x0c, 0x1c, 0x02, 0x01, 0x01, 0x31, 0x09, 0x30, 0x07,
+ 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0b, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01,
+ 0xa0, 0x82, 0x0a, 0xc6, 0x30, 0x82, 0x02, 0x9a, 0x30, 0x82,
+ 0x02, 0x03, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x05,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47,
+ 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d,
+ 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e,
+ 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c,
+ 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
+ 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72,
+ 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c,
+ 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61,
+ 0x66, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32,
+ 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x35,
+ 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x33, 0x32, 0x32, 0x30,
+ 0x30, 0x30, 0x31, 0x33, 0x35, 0x5a, 0x30, 0x81, 0x8b, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65,
+ 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x19, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63,
+ 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e,
+ 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x81,
+ 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
+ 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xc6, 0xfc, 0x96,
+ 0x1e, 0x90, 0x32, 0xed, 0xb8, 0x54, 0xb2, 0xc2, 0x39, 0x66,
+ 0x19, 0xca, 0xd8, 0x45, 0x21, 0xb7, 0x5a, 0x8d, 0x8d, 0x71,
+ 0xef, 0x69, 0x37, 0x40, 0xbb, 0xa4, 0xde, 0x09, 0x1b, 0x17,
+ 0x83, 0x3a, 0x7a, 0xf1, 0x7b, 0x02, 0x31, 0x5d, 0x1f, 0x3a,
+ 0xe5, 0x29, 0x28, 0x9b, 0x7e, 0x7b, 0x5a, 0xc4, 0x18, 0x3e,
+ 0x43, 0xe6, 0xe9, 0x6e, 0xd1, 0x8d, 0x86, 0xcf, 0xb5, 0x9f,
+ 0x7f, 0x50, 0x4e, 0x06, 0x13, 0xf7, 0xb2, 0xee, 0xef, 0x0e,
+ 0xab, 0x50, 0x44, 0x42, 0xfd, 0x3a, 0xa9, 0x47, 0x83, 0x34,
+ 0x17, 0xdf, 0xee, 0x3d, 0x84, 0x1f, 0xed, 0x7e, 0xfa, 0x0f,
+ 0xa8, 0xfc, 0x07, 0xf8, 0xd1, 0x49, 0x99, 0x1a, 0xad, 0x39,
+ 0x16, 0xb3, 0x71, 0x15, 0x2e, 0x82, 0x20, 0x7a, 0x92, 0xed,
+ 0x1e, 0x37, 0xf6, 0x46, 0x5e, 0x7d, 0x9b, 0xa1, 0x53, 0x4d,
+ 0x13, 0x91, 0xcd, 0x7a, 0x77, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0xa3, 0x0f, 0x30, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d,
+ 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0xb2, 0x39, 0x0b, 0x02,
+ 0x33, 0xca, 0x48, 0x96, 0x13, 0x53, 0xe9, 0x1b, 0x28, 0xd6,
+ 0x35, 0x4e, 0x0c, 0x9d, 0xd0, 0xe3, 0x79, 0x65, 0x0a, 0xe7,
+ 0xa6, 0x22, 0x61, 0x26, 0xbe, 0xb4, 0x05, 0xec, 0x5f, 0x83,
+ 0xb7, 0x0e, 0xa4, 0xae, 0x50, 0xb1, 0xa9, 0x45, 0x25, 0xf2,
+ 0x52, 0x1a, 0x63, 0x05, 0x50, 0x75, 0x33, 0xca, 0x8a, 0xb1,
+ 0xf2, 0x19, 0xd3, 0x93, 0x84, 0x67, 0x42, 0xe3, 0xb7, 0xa6,
+ 0xf9, 0x4d, 0x90, 0x7e, 0x13, 0x40, 0xd3, 0x22, 0x9f, 0x83,
+ 0xaf, 0x70, 0xb2, 0x7d, 0x4d, 0xcc, 0xae, 0x18, 0x9e, 0xca,
+ 0xc8, 0xcb, 0x82, 0x93, 0xcb, 0xce, 0xc6, 0x32, 0xcf, 0x4e,
+ 0x04, 0x64, 0x18, 0x5b, 0xc2, 0x1a, 0xb6, 0xd1, 0x8a, 0xc4,
+ 0x99, 0xce, 0xdd, 0xd7, 0x7e, 0xec, 0xf5, 0xa9, 0xa7, 0x00,
+ 0xc2, 0xd3, 0x6a, 0xb9, 0xcd, 0x25, 0x88, 0x08, 0x71, 0xf5,
+ 0x6d, 0x44, 0xe7, 0x93, 0x30, 0x82, 0x02, 0xb3, 0x30, 0x82,
+ 0x02, 0x1c, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47,
+ 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d,
+ 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e,
+ 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c,
+ 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
+ 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72,
+ 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c,
+ 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x72, 0x6f, 0x6f,
+ 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32,
+ 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33,
+ 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x32, 0x31, 0x37, 0x30,
+ 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x90, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65,
+ 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x1e, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65,
+ 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65,
+ 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81,
+ 0x81, 0x00, 0xc9, 0x3a, 0xee, 0xc6, 0x3c, 0xac, 0x4d, 0x81,
+ 0xc6, 0x98, 0x5e, 0xe1, 0x48, 0x66, 0x1a, 0x1e, 0x60, 0x19,
+ 0x41, 0xae, 0xca, 0x14, 0x97, 0xc8, 0x3a, 0x50, 0xb6, 0x48,
+ 0xf5, 0x42, 0xac, 0x0f, 0xe1, 0xe3, 0x47, 0xf0, 0xbf, 0x7c,
+ 0xd0, 0xee, 0x8f, 0xb7, 0xa6, 0x19, 0xad, 0xbb, 0xc5, 0x1b,
+ 0x34, 0x38, 0xc8, 0xbd, 0x55, 0x84, 0x93, 0x72, 0xaf, 0x84,
+ 0xfc, 0x9b, 0x97, 0x1d, 0xb5, 0x54, 0x24, 0xd6, 0x5d, 0xb7,
+ 0x31, 0xf4, 0xbd, 0x3b, 0x40, 0x97, 0xc0, 0xa9, 0x5a, 0x2a,
+ 0xcb, 0x6b, 0x98, 0x07, 0xdb, 0xb5, 0x9f, 0xe8, 0x31, 0x3f,
+ 0x01, 0x46, 0x46, 0x70, 0x05, 0xa2, 0x0f, 0x8c, 0x7a, 0x61,
+ 0xf3, 0xdf, 0xdb, 0xa1, 0x37, 0x2c, 0x88, 0x6a, 0x81, 0x21,
+ 0x12, 0x4c, 0xf5, 0xcd, 0xaf, 0xc9, 0xd2, 0x36, 0x3d, 0x82,
+ 0xd1, 0xca, 0x19, 0xaf, 0x4e, 0xae, 0x50, 0x71, 0x44, 0xbf,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x23, 0x30, 0x21, 0x30,
+ 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
+ 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03,
+ 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02,
+ 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81,
+ 0x00, 0x5d, 0x3c, 0xb3, 0x52, 0x19, 0xa6, 0x9e, 0x4a, 0x44,
+ 0x98, 0xbf, 0x51, 0x20, 0x47, 0x0a, 0xf3, 0x26, 0x1a, 0xcc,
+ 0x35, 0x2f, 0xc9, 0xed, 0xe0, 0x9d, 0x46, 0xeb, 0xbc, 0x7e,
+ 0xc9, 0xb9, 0x1d, 0x76, 0xa4, 0x1d, 0xc2, 0xd9, 0x16, 0x29,
+ 0x77, 0x01, 0x40, 0xdd, 0xe5, 0xcb, 0x28, 0x91, 0x3a, 0x0c,
+ 0x13, 0x01, 0x1b, 0x72, 0x62, 0x45, 0x27, 0xfd, 0xd7, 0x00,
+ 0x47, 0x36, 0x09, 0x1e, 0x7b, 0xd2, 0xcb, 0x95, 0x3d, 0x28,
+ 0x82, 0xce, 0x83, 0x59, 0x32, 0xf9, 0xe6, 0xec, 0x89, 0xac,
+ 0x88, 0x45, 0x22, 0x88, 0x6f, 0x5e, 0xa2, 0x79, 0x95, 0xba,
+ 0xb9, 0xc9, 0xb6, 0x4c, 0x7c, 0xb4, 0x29, 0xa1, 0x02, 0xf5,
+ 0xac, 0x5d, 0x8e, 0x52, 0xeb, 0xe8, 0xb1, 0x56, 0x49, 0xb3,
+ 0x77, 0x62, 0x7d, 0x87, 0x4d, 0x17, 0xf2, 0x62, 0x83, 0x08,
+ 0x59, 0x21, 0x60, 0x0d, 0x84, 0x8e, 0x5a, 0x84, 0xf6, 0x30,
+ 0x82, 0x02, 0xb3, 0x30, 0x82, 0x02, 0x1c, 0xa0, 0x03, 0x02,
+ 0x01, 0x02, 0x02, 0x09, 0x00, 0xc6, 0xb8, 0x9c, 0x58, 0xd2,
+ 0xdc, 0xc9, 0x5d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81,
+ 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72,
+ 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31,
+ 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09,
+ 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31,
+ 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f,
+ 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06,
+ 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65,
+ 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20,
+ 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20,
+ 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17,
+ 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30,
+ 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x39, 0x30, 0x38,
+ 0x30, 0x38, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x30,
+ 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62,
+ 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65,
+ 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
+ 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65,
+ 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
+ 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f,
+ 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78,
+ 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45,
+ 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x81,
+ 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
+ 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xaa, 0x72, 0xb5,
+ 0xc1, 0x73, 0xf4, 0x95, 0x76, 0xa4, 0x27, 0xab, 0x5e, 0xeb,
+ 0x1d, 0x9d, 0xd0, 0x04, 0xb2, 0x93, 0x05, 0xc7, 0xfa, 0x75,
+ 0x84, 0x66, 0xe6, 0x3a, 0x26, 0x1f, 0xbc, 0x2d, 0xfd, 0x8f,
+ 0x59, 0x64, 0xac, 0xcf, 0x65, 0x9d, 0x82, 0x23, 0xc3, 0x72,
+ 0x93, 0xf2, 0x40, 0x68, 0x32, 0xd1, 0xb8, 0xf1, 0x47, 0x61,
+ 0x50, 0xea, 0xbc, 0xcc, 0x3c, 0x6b, 0x74, 0x7a, 0xec, 0x2b,
+ 0x75, 0xa6, 0xc2, 0xa2, 0xb8, 0xbf, 0x23, 0x48, 0x97, 0xd5,
+ 0xaf, 0x77, 0xc1, 0x92, 0x88, 0xd7, 0x38, 0xb7, 0x9e, 0xda,
+ 0xee, 0x72, 0x04, 0xcb, 0x96, 0xe5, 0xdb, 0xfd, 0x9b, 0x5d,
+ 0x99, 0x4e, 0x7a, 0x60, 0x23, 0x34, 0xa4, 0x8d, 0xd7, 0x6c,
+ 0xe7, 0x5d, 0x93, 0x97, 0xe1, 0xab, 0x36, 0x2c, 0x24, 0x16,
+ 0x92, 0x66, 0xf6, 0x6a, 0x14, 0x23, 0x1d, 0x18, 0xb9, 0x44,
+ 0x24, 0x61, 0x6b, 0xd3, 0x75, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0xa3, 0x23, 0x30, 0x21, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d,
+ 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01,
+ 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
+ 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x94, 0x9e, 0xea, 0x17,
+ 0x8d, 0x27, 0xa9, 0x17, 0xe5, 0xa9, 0x19, 0xbe, 0x82, 0x36,
+ 0xbd, 0xac, 0x74, 0xf3, 0x6e, 0x75, 0x71, 0x30, 0x1c, 0x05,
+ 0x80, 0x6d, 0x1a, 0x69, 0x37, 0x86, 0x9c, 0x77, 0x75, 0x29,
+ 0xa1, 0xc6, 0xb7, 0x11, 0x0a, 0x63, 0x27, 0xee, 0xb1, 0xc8,
+ 0x94, 0xa9, 0x2e, 0x56, 0x8f, 0xca, 0x9d, 0xbe, 0xf4, 0xdb,
+ 0x63, 0x97, 0x68, 0x3b, 0x13, 0xf8, 0x6a, 0xa5, 0xd1, 0x3d,
+ 0xed, 0xbb, 0x86, 0x9d, 0x42, 0xfc, 0x15, 0x0a, 0x04, 0xf8,
+ 0x3c, 0x0e, 0xc4, 0x86, 0x05, 0x57, 0x56, 0x96, 0xf6, 0xc0,
+ 0x18, 0x53, 0xb0, 0xc5, 0xf0, 0xca, 0x72, 0x77, 0x77, 0xc9,
+ 0x8e, 0x90, 0xa5, 0x4b, 0xb6, 0x80, 0x4a, 0x4c, 0x34, 0x6f,
+ 0xc9, 0xe8, 0x6f, 0xc2, 0x28, 0xdf, 0x93, 0xa9, 0xf5, 0x63,
+ 0x18, 0xc0, 0xec, 0x9e, 0xd5, 0x19, 0x36, 0xc5, 0x94, 0x10,
+ 0xd4, 0x72, 0xd2, 0xb8, 0x30, 0x82, 0x02, 0xb6, 0x30, 0x82,
+ 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x90, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47,
+ 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d,
+ 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e,
+ 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c,
+ 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
+ 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72,
+ 0x67, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x0c, 0x1e, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c,
+ 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20,
+ 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33,
+ 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17,
+ 0x0d, 0x31, 0x34, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x30,
+ 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42,
+ 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
+ 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65,
+ 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06,
+ 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62,
+ 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20,
+ 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74,
+ 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b,
+ 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67,
+ 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+ 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66,
+ 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66,
+ 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81,
+ 0x81, 0x00, 0xc3, 0x55, 0xad, 0xdf, 0x7b, 0xd1, 0x48, 0xc3,
+ 0xd3, 0x02, 0x54, 0x6c, 0x92, 0x45, 0x22, 0x3d, 0x90, 0xd8,
+ 0xc7, 0x13, 0xcd, 0xc1, 0x59, 0xc6, 0xe0, 0xad, 0x0e, 0xe6,
+ 0xdb, 0x3b, 0xe8, 0x63, 0xea, 0x4e, 0xb6, 0xea, 0x50, 0xea,
+ 0x6e, 0x33, 0x9d, 0x28, 0x25, 0x42, 0x49, 0xd0, 0xf0, 0xed,
+ 0xc5, 0x5b, 0x6b, 0x4a, 0xe7, 0x45, 0xfa, 0xd3, 0x3f, 0xae,
+ 0xde, 0x5a, 0x90, 0xab, 0xf1, 0x61, 0x2f, 0x40, 0x5e, 0xcf,
+ 0x8b, 0x0b, 0x10, 0x59, 0xa9, 0xd0, 0x1e, 0x0f, 0x18, 0x6b,
+ 0x92, 0xd8, 0x9f, 0x58, 0x10, 0x84, 0xb6, 0x15, 0xe8, 0x5b,
+ 0xc4, 0xa0, 0x3e, 0x49, 0x8b, 0xea, 0xdd, 0xa9, 0x7e, 0x32,
+ 0x26, 0x9a, 0x68, 0x44, 0xf0, 0x30, 0xca, 0x2a, 0xd6, 0x19,
+ 0x7a, 0x80, 0xfd, 0xd7, 0xfc, 0xc7, 0x5d, 0xe7, 0x61, 0xd2,
+ 0x3f, 0x1f, 0x2c, 0x40, 0x70, 0x7b, 0x34, 0xcb, 0x08, 0xa9,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x26, 0x30, 0x24, 0x30,
+ 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
+ 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30,
+ 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04,
+ 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x03, 0x81, 0x81, 0x00, 0x40, 0xd2, 0x70, 0x02, 0x08, 0x19,
+ 0xa0, 0xb8, 0x8d, 0x9d, 0x3d, 0x62, 0x41, 0x90, 0x2a, 0x36,
+ 0x4a, 0x8b, 0x21, 0x42, 0x9a, 0xb4, 0xc5, 0xf8, 0x79, 0x17,
+ 0xd7, 0x64, 0x4d, 0xbf, 0x8f, 0x6a, 0x04, 0x54, 0x7a, 0x0b,
+ 0xd4, 0xb5, 0x0e, 0xab, 0xf7, 0xb7, 0x06, 0x2b, 0xf8, 0xde,
+ 0x87, 0xb2, 0x37, 0x3b, 0x95, 0x01, 0xba, 0x9f, 0x8f, 0xec,
+ 0x0a, 0x86, 0xca, 0x51, 0xb6, 0x25, 0x73, 0x2f, 0xa1, 0x66,
+ 0xc8, 0x7a, 0x5e, 0x51, 0xbd, 0x49, 0xb5, 0x75, 0xda, 0xea,
+ 0xe5, 0xeb, 0x5d, 0xe3, 0xb0, 0xad, 0x49, 0x9f, 0x8b, 0xfd,
+ 0x89, 0xb3, 0xb7, 0xb2, 0x4c, 0x7d, 0x8a, 0x29, 0xb2, 0xbe,
+ 0x04, 0xef, 0x9c, 0x73, 0x3c, 0xea, 0xa3, 0x9f, 0x07, 0x66,
+ 0x5a, 0x2f, 0x38, 0xad, 0x1a, 0xeb, 0xe1, 0xb0, 0x62, 0x14,
+ 0x55, 0xdc, 0x8c, 0x83, 0xbb, 0xc7, 0x13, 0x04, 0x41, 0x54,
+ 0xf1, 0x45, 0x31, 0x82, 0x01, 0x33, 0x30, 0x82, 0x01, 0x2f,
+ 0x02, 0x01, 0x01, 0x30, 0x81, 0x8e, 0x30, 0x81, 0x88, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65,
+ 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65,
+ 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65,
+ 0x61, 0x66, 0x20, 0x43, 0x41, 0x02, 0x01, 0x05, 0x30, 0x07,
+ 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x04, 0x81, 0x80, 0xc5, 0x08, 0x17, 0x23, 0xb9,
+ 0x8d, 0x45, 0x0b, 0x1a, 0x9a, 0x10, 0xa7, 0x16, 0x57, 0x05,
+ 0x86, 0x0c, 0x9a, 0xfd, 0x2d, 0x9c, 0x87, 0x15, 0xb3, 0x0f,
+ 0xd5, 0x3b, 0x7b, 0xa8, 0xce, 0xa2, 0xcc, 0x2a, 0x2a, 0x6a,
+ 0xa0, 0xab, 0x2f, 0x57, 0x8c, 0xb7, 0xc7, 0x4e, 0x2a, 0xbd,
+ 0x72, 0xc5, 0xef, 0x2a, 0xd8, 0xb8, 0xf2, 0x9d, 0xbe, 0xd4,
+ 0xa7, 0x55, 0x3e, 0x06, 0x3b, 0x3f, 0xfa, 0x92, 0x4f, 0x1f,
+ 0x84, 0x84, 0x16, 0xcf, 0x9b, 0x26, 0x71, 0xf7, 0x57, 0x6a,
+ 0x6d, 0xdd, 0x34, 0x6b, 0x12, 0xc4, 0x70, 0x78, 0x59, 0x9b,
+ 0xf7, 0x45, 0xf4, 0xae, 0x30, 0xb0, 0x8c, 0x21, 0xb7, 0xb1,
+ 0x96, 0xda, 0x91, 0x0e, 0x57, 0x7e, 0x1b, 0xe2, 0xef, 0x82,
+ 0xd5, 0xa3, 0xd1, 0xeb, 0x47, 0x5c, 0x33, 0x91, 0xf8, 0x90,
+ 0xf9, 0x99, 0x0c, 0x69, 0x05, 0xee, 0xa1, 0x1a, 0x2d, 0x44,
+ 0x7e, 0x7c, 0x99 ) );
+
+/** Signature generated with a non-signing certificate */
+SIGNATURE ( nonsigned_sig,
+ DATA ( 0x30, 0x82, 0x0c, 0x12, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x0c, 0x03, 0x30,
+ 0x82, 0x0b, 0xff, 0x02, 0x01, 0x01, 0x31, 0x09, 0x30, 0x07,
+ 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0b, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01,
+ 0xa0, 0x82, 0x0a, 0xa9, 0x30, 0x82, 0x02, 0x7d, 0x30, 0x82,
+ 0x01, 0xe6, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d,
+ 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72,
+ 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07,
+ 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30,
+ 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70,
+ 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58,
+ 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73,
+ 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x43, 0x41, 0x30,
+ 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, 0x30,
+ 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x17, 0x0d, 0x31, 0x33,
+ 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x34,
+ 0x5a, 0x30, 0x81, 0x84, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30,
+ 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69,
+ 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+ 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69,
+ 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1b, 0x30,
+ 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x12, 0x62, 0x6f,
+ 0x6f, 0x74, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70,
+ 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81,
+ 0x89, 0x02, 0x81, 0x81, 0x00, 0xbd, 0x43, 0x97, 0x45, 0xa2,
+ 0xe0, 0x1d, 0x38, 0x41, 0xb0, 0xd9, 0x91, 0xf9, 0x77, 0xa9,
+ 0xcb, 0x9c, 0x9c, 0x93, 0xfe, 0x5a, 0xee, 0xbc, 0xd9, 0x0f,
+ 0x39, 0xf6, 0x42, 0xe4, 0x55, 0x21, 0xbb, 0x11, 0xfd, 0xfd,
+ 0xba, 0x25, 0x58, 0xc8, 0xc6, 0xa5, 0x3b, 0x6f, 0x80, 0xba,
+ 0x5b, 0xbc, 0x89, 0xca, 0x7a, 0xdf, 0x6e, 0xb9, 0x81, 0xb6,
+ 0x25, 0x67, 0x0a, 0x38, 0x10, 0xf8, 0x26, 0x43, 0x0c, 0x51,
+ 0x02, 0x14, 0xd6, 0xf2, 0x9d, 0x7c, 0xf5, 0x25, 0x1c, 0x78,
+ 0x4d, 0x47, 0xaf, 0x87, 0x2e, 0x38, 0x49, 0x87, 0xb5, 0x8a,
+ 0xf3, 0xb5, 0xd4, 0x15, 0x69, 0x2a, 0x52, 0xc9, 0x46, 0x97,
+ 0x34, 0x8e, 0x50, 0x4b, 0xc4, 0xf2, 0xfb, 0x39, 0xfd, 0x16,
+ 0x68, 0xdb, 0xa8, 0x17, 0xe2, 0x71, 0x4b, 0xe0, 0xdf, 0x3d,
+ 0xfc, 0xc3, 0x9b, 0x9d, 0x22, 0xc9, 0xd3, 0xf6, 0x02, 0xa6,
+ 0x60, 0xef, 0xf7, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x7d, 0xff, 0x73,
+ 0xf3, 0x68, 0xe3, 0x75, 0xf1, 0xcf, 0xac, 0x2e, 0x23, 0x73,
+ 0xea, 0xd1, 0x26, 0x33, 0xbf, 0xf9, 0x56, 0xdf, 0xbf, 0x98,
+ 0x20, 0x84, 0x08, 0x78, 0x6b, 0xe6, 0x71, 0x7e, 0x22, 0x68,
+ 0x4d, 0x6c, 0xbb, 0xd5, 0xcc, 0xb4, 0x28, 0x33, 0x5e, 0xbe,
+ 0x4d, 0x10, 0x16, 0x9f, 0x65, 0x3b, 0x68, 0x90, 0xa7, 0xf7,
+ 0x9d, 0x57, 0x71, 0x45, 0x39, 0x86, 0x4c, 0xc0, 0x97, 0x34,
+ 0x03, 0x9c, 0x2b, 0x25, 0x05, 0xb1, 0x5c, 0x0c, 0x4e, 0xf2,
+ 0x14, 0xbf, 0xcf, 0xf0, 0x9a, 0x2d, 0xcf, 0x02, 0x47, 0x60,
+ 0xd2, 0xe9, 0xed, 0xbf, 0x71, 0x5d, 0x07, 0x09, 0x01, 0x87,
+ 0xeb, 0xf7, 0xa8, 0x26, 0x86, 0x24, 0x59, 0xf0, 0x31, 0x3b,
+ 0x42, 0xd1, 0xf1, 0xfd, 0x7c, 0x49, 0x5f, 0x1a, 0xf0, 0x41,
+ 0x67, 0xf0, 0x16, 0x3a, 0xfd, 0xb6, 0xb5, 0xf6, 0x2e, 0x0c,
+ 0x18, 0x1f, 0x09, 0x8e, 0x4d, 0x30, 0x82, 0x02, 0xb3, 0x30,
+ 0x82, 0x02, 0x1c, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01,
+ 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65,
+ 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65,
+ 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x72, 0x6f,
+ 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+ 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33,
+ 0x33, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x32, 0x31, 0x37,
+ 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x90,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12,
+ 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43,
+ 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18,
+ 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46,
+ 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73,
+ 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03,
+ 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e,
+ 0x6f, 0x72, 0x67, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x1e, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73,
+ 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74,
+ 0x65, 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02,
+ 0x81, 0x81, 0x00, 0xc9, 0x3a, 0xee, 0xc6, 0x3c, 0xac, 0x4d,
+ 0x81, 0xc6, 0x98, 0x5e, 0xe1, 0x48, 0x66, 0x1a, 0x1e, 0x60,
+ 0x19, 0x41, 0xae, 0xca, 0x14, 0x97, 0xc8, 0x3a, 0x50, 0xb6,
+ 0x48, 0xf5, 0x42, 0xac, 0x0f, 0xe1, 0xe3, 0x47, 0xf0, 0xbf,
+ 0x7c, 0xd0, 0xee, 0x8f, 0xb7, 0xa6, 0x19, 0xad, 0xbb, 0xc5,
+ 0x1b, 0x34, 0x38, 0xc8, 0xbd, 0x55, 0x84, 0x93, 0x72, 0xaf,
+ 0x84, 0xfc, 0x9b, 0x97, 0x1d, 0xb5, 0x54, 0x24, 0xd6, 0x5d,
+ 0xb7, 0x31, 0xf4, 0xbd, 0x3b, 0x40, 0x97, 0xc0, 0xa9, 0x5a,
+ 0x2a, 0xcb, 0x6b, 0x98, 0x07, 0xdb, 0xb5, 0x9f, 0xe8, 0x31,
+ 0x3f, 0x01, 0x46, 0x46, 0x70, 0x05, 0xa2, 0x0f, 0x8c, 0x7a,
+ 0x61, 0xf3, 0xdf, 0xdb, 0xa1, 0x37, 0x2c, 0x88, 0x6a, 0x81,
+ 0x21, 0x12, 0x4c, 0xf5, 0xcd, 0xaf, 0xc9, 0xd2, 0x36, 0x3d,
+ 0x82, 0xd1, 0xca, 0x19, 0xaf, 0x4e, 0xae, 0x50, 0x71, 0x44,
+ 0xbf, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x23, 0x30, 0x21,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06,
+ 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03,
+ 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+ 0x81, 0x00, 0x5d, 0x3c, 0xb3, 0x52, 0x19, 0xa6, 0x9e, 0x4a,
+ 0x44, 0x98, 0xbf, 0x51, 0x20, 0x47, 0x0a, 0xf3, 0x26, 0x1a,
+ 0xcc, 0x35, 0x2f, 0xc9, 0xed, 0xe0, 0x9d, 0x46, 0xeb, 0xbc,
+ 0x7e, 0xc9, 0xb9, 0x1d, 0x76, 0xa4, 0x1d, 0xc2, 0xd9, 0x16,
+ 0x29, 0x77, 0x01, 0x40, 0xdd, 0xe5, 0xcb, 0x28, 0x91, 0x3a,
+ 0x0c, 0x13, 0x01, 0x1b, 0x72, 0x62, 0x45, 0x27, 0xfd, 0xd7,
+ 0x00, 0x47, 0x36, 0x09, 0x1e, 0x7b, 0xd2, 0xcb, 0x95, 0x3d,
+ 0x28, 0x82, 0xce, 0x83, 0x59, 0x32, 0xf9, 0xe6, 0xec, 0x89,
+ 0xac, 0x88, 0x45, 0x22, 0x88, 0x6f, 0x5e, 0xa2, 0x79, 0x95,
+ 0xba, 0xb9, 0xc9, 0xb6, 0x4c, 0x7c, 0xb4, 0x29, 0xa1, 0x02,
+ 0xf5, 0xac, 0x5d, 0x8e, 0x52, 0xeb, 0xe8, 0xb1, 0x56, 0x49,
+ 0xb3, 0x77, 0x62, 0x7d, 0x87, 0x4d, 0x17, 0xf2, 0x62, 0x83,
+ 0x08, 0x59, 0x21, 0x60, 0x0d, 0x84, 0x8e, 0x5a, 0x84, 0xf6,
+ 0x30, 0x82, 0x02, 0xb3, 0x30, 0x82, 0x02, 0x1c, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xc6, 0xb8, 0x9c, 0x58,
+ 0xd2, 0xdc, 0xc9, 0x5d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
+ 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62,
+ 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65,
+ 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
+ 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65,
+ 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
+ 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f,
+ 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78,
+ 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45,
+ 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e,
+ 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30,
+ 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x39, 0x30,
+ 0x38, 0x30, 0x38, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a,
+ 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d,
+ 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72,
+ 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07,
+ 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30,
+ 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70,
+ 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58,
+ 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73,
+ 0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30,
+ 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+ 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xaa, 0x72,
+ 0xb5, 0xc1, 0x73, 0xf4, 0x95, 0x76, 0xa4, 0x27, 0xab, 0x5e,
+ 0xeb, 0x1d, 0x9d, 0xd0, 0x04, 0xb2, 0x93, 0x05, 0xc7, 0xfa,
+ 0x75, 0x84, 0x66, 0xe6, 0x3a, 0x26, 0x1f, 0xbc, 0x2d, 0xfd,
+ 0x8f, 0x59, 0x64, 0xac, 0xcf, 0x65, 0x9d, 0x82, 0x23, 0xc3,
+ 0x72, 0x93, 0xf2, 0x40, 0x68, 0x32, 0xd1, 0xb8, 0xf1, 0x47,
+ 0x61, 0x50, 0xea, 0xbc, 0xcc, 0x3c, 0x6b, 0x74, 0x7a, 0xec,
+ 0x2b, 0x75, 0xa6, 0xc2, 0xa2, 0xb8, 0xbf, 0x23, 0x48, 0x97,
+ 0xd5, 0xaf, 0x77, 0xc1, 0x92, 0x88, 0xd7, 0x38, 0xb7, 0x9e,
+ 0xda, 0xee, 0x72, 0x04, 0xcb, 0x96, 0xe5, 0xdb, 0xfd, 0x9b,
+ 0x5d, 0x99, 0x4e, 0x7a, 0x60, 0x23, 0x34, 0xa4, 0x8d, 0xd7,
+ 0x6c, 0xe7, 0x5d, 0x93, 0x97, 0xe1, 0xab, 0x36, 0x2c, 0x24,
+ 0x16, 0x92, 0x66, 0xf6, 0x6a, 0x14, 0x23, 0x1d, 0x18, 0xb9,
+ 0x44, 0x24, 0x61, 0x6b, 0xd3, 0x75, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0xa3, 0x23, 0x30, 0x21, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01,
+ 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01,
+ 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x94, 0x9e, 0xea,
+ 0x17, 0x8d, 0x27, 0xa9, 0x17, 0xe5, 0xa9, 0x19, 0xbe, 0x82,
+ 0x36, 0xbd, 0xac, 0x74, 0xf3, 0x6e, 0x75, 0x71, 0x30, 0x1c,
+ 0x05, 0x80, 0x6d, 0x1a, 0x69, 0x37, 0x86, 0x9c, 0x77, 0x75,
+ 0x29, 0xa1, 0xc6, 0xb7, 0x11, 0x0a, 0x63, 0x27, 0xee, 0xb1,
+ 0xc8, 0x94, 0xa9, 0x2e, 0x56, 0x8f, 0xca, 0x9d, 0xbe, 0xf4,
+ 0xdb, 0x63, 0x97, 0x68, 0x3b, 0x13, 0xf8, 0x6a, 0xa5, 0xd1,
+ 0x3d, 0xed, 0xbb, 0x86, 0x9d, 0x42, 0xfc, 0x15, 0x0a, 0x04,
+ 0xf8, 0x3c, 0x0e, 0xc4, 0x86, 0x05, 0x57, 0x56, 0x96, 0xf6,
+ 0xc0, 0x18, 0x53, 0xb0, 0xc5, 0xf0, 0xca, 0x72, 0x77, 0x77,
+ 0xc9, 0x8e, 0x90, 0xa5, 0x4b, 0xb6, 0x80, 0x4a, 0x4c, 0x34,
+ 0x6f, 0xc9, 0xe8, 0x6f, 0xc2, 0x28, 0xdf, 0x93, 0xa9, 0xf5,
+ 0x63, 0x18, 0xc0, 0xec, 0x9e, 0xd5, 0x19, 0x36, 0xc5, 0x94,
+ 0x10, 0xd4, 0x72, 0xd2, 0xb8, 0x30, 0x82, 0x02, 0xb6, 0x30,
+ 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01,
+ 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x90, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65,
+ 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x1e, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65,
+ 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65,
+ 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30,
+ 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a,
+ 0x17, 0x0d, 0x31, 0x34, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30,
+ 0x30, 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x88, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47,
+ 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d,
+ 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e,
+ 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c,
+ 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
+ 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72,
+ 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c,
+ 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61,
+ 0x66, 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02,
+ 0x81, 0x81, 0x00, 0xc3, 0x55, 0xad, 0xdf, 0x7b, 0xd1, 0x48,
+ 0xc3, 0xd3, 0x02, 0x54, 0x6c, 0x92, 0x45, 0x22, 0x3d, 0x90,
+ 0xd8, 0xc7, 0x13, 0xcd, 0xc1, 0x59, 0xc6, 0xe0, 0xad, 0x0e,
+ 0xe6, 0xdb, 0x3b, 0xe8, 0x63, 0xea, 0x4e, 0xb6, 0xea, 0x50,
+ 0xea, 0x6e, 0x33, 0x9d, 0x28, 0x25, 0x42, 0x49, 0xd0, 0xf0,
+ 0xed, 0xc5, 0x5b, 0x6b, 0x4a, 0xe7, 0x45, 0xfa, 0xd3, 0x3f,
+ 0xae, 0xde, 0x5a, 0x90, 0xab, 0xf1, 0x61, 0x2f, 0x40, 0x5e,
+ 0xcf, 0x8b, 0x0b, 0x10, 0x59, 0xa9, 0xd0, 0x1e, 0x0f, 0x18,
+ 0x6b, 0x92, 0xd8, 0x9f, 0x58, 0x10, 0x84, 0xb6, 0x15, 0xe8,
+ 0x5b, 0xc4, 0xa0, 0x3e, 0x49, 0x8b, 0xea, 0xdd, 0xa9, 0x7e,
+ 0x32, 0x26, 0x9a, 0x68, 0x44, 0xf0, 0x30, 0xca, 0x2a, 0xd6,
+ 0x19, 0x7a, 0x80, 0xfd, 0xd7, 0xfc, 0xc7, 0x5d, 0xe7, 0x61,
+ 0xd2, 0x3f, 0x1f, 0x2c, 0x40, 0x70, 0x7b, 0x34, 0xcb, 0x08,
+ 0xa9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x26, 0x30, 0x24,
+ 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+ 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00,
+ 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff,
+ 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
+ 0x00, 0x03, 0x81, 0x81, 0x00, 0x40, 0xd2, 0x70, 0x02, 0x08,
+ 0x19, 0xa0, 0xb8, 0x8d, 0x9d, 0x3d, 0x62, 0x41, 0x90, 0x2a,
+ 0x36, 0x4a, 0x8b, 0x21, 0x42, 0x9a, 0xb4, 0xc5, 0xf8, 0x79,
+ 0x17, 0xd7, 0x64, 0x4d, 0xbf, 0x8f, 0x6a, 0x04, 0x54, 0x7a,
+ 0x0b, 0xd4, 0xb5, 0x0e, 0xab, 0xf7, 0xb7, 0x06, 0x2b, 0xf8,
+ 0xde, 0x87, 0xb2, 0x37, 0x3b, 0x95, 0x01, 0xba, 0x9f, 0x8f,
+ 0xec, 0x0a, 0x86, 0xca, 0x51, 0xb6, 0x25, 0x73, 0x2f, 0xa1,
+ 0x66, 0xc8, 0x7a, 0x5e, 0x51, 0xbd, 0x49, 0xb5, 0x75, 0xda,
+ 0xea, 0xe5, 0xeb, 0x5d, 0xe3, 0xb0, 0xad, 0x49, 0x9f, 0x8b,
+ 0xfd, 0x89, 0xb3, 0xb7, 0xb2, 0x4c, 0x7d, 0x8a, 0x29, 0xb2,
+ 0xbe, 0x04, 0xef, 0x9c, 0x73, 0x3c, 0xea, 0xa3, 0x9f, 0x07,
+ 0x66, 0x5a, 0x2f, 0x38, 0xad, 0x1a, 0xeb, 0xe1, 0xb0, 0x62,
+ 0x14, 0x55, 0xdc, 0x8c, 0x83, 0xbb, 0xc7, 0x13, 0x04, 0x41,
+ 0x54, 0xf1, 0x45, 0x31, 0x82, 0x01, 0x33, 0x30, 0x82, 0x01,
+ 0x2f, 0x02, 0x01, 0x01, 0x30, 0x81, 0x8e, 0x30, 0x81, 0x88,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12,
+ 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43,
+ 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18,
+ 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46,
+ 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73,
+ 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03,
+ 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e,
+ 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73,
+ 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c,
+ 0x65, 0x61, 0x66, 0x20, 0x43, 0x41, 0x02, 0x01, 0x03, 0x30,
+ 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x04, 0x81, 0x80, 0x33, 0x5c, 0xf8, 0xb4,
+ 0xa5, 0x70, 0xb9, 0x0f, 0x05, 0x50, 0x72, 0xdb, 0xa3, 0xba,
+ 0x8e, 0x0d, 0x6d, 0x8a, 0x2a, 0x91, 0x65, 0xb8, 0x76, 0xd0,
+ 0xfc, 0x9e, 0x1a, 0xdb, 0x2b, 0xd2, 0xfc, 0x03, 0xef, 0x8d,
+ 0xef, 0xfe, 0x32, 0x16, 0xad, 0xf8, 0xcb, 0x28, 0xb0, 0x61,
+ 0x15, 0xb8, 0x38, 0x72, 0xfc, 0x5d, 0xa1, 0xd2, 0xae, 0x9d,
+ 0x6a, 0xb0, 0x5e, 0xbb, 0x78, 0xd3, 0x39, 0x24, 0xa3, 0x71,
+ 0xa6, 0x90, 0x64, 0xa5, 0x82, 0xba, 0x3b, 0x85, 0x2d, 0x16,
+ 0x78, 0xf4, 0xcc, 0x9f, 0xfa, 0xc5, 0x68, 0x44, 0x2c, 0x22,
+ 0xb9, 0x4c, 0x07, 0x5c, 0xb4, 0x79, 0x1a, 0x48, 0xc2, 0x66,
+ 0x71, 0x57, 0x6d, 0xdf, 0x33, 0xa2, 0x26, 0x99, 0xdd, 0xe9,
+ 0xb9, 0x1b, 0xe1, 0xa6, 0x4d, 0x53, 0x8e, 0x71, 0x81, 0xa9,
+ 0x5d, 0x70, 0x47, 0x54, 0xbc, 0x15, 0xad, 0x9c, 0xe8, 0x90,
+ 0x52, 0x3e, 0x49, 0x86 ) );
+
+/** iPXE self-test root CA certificate */
+static uint8_t root_crt_fingerprint[] =
+ FINGERPRINT ( 0x71, 0x5d, 0x51, 0x37, 0x5e, 0x18, 0xb3, 0xbc,
+ 0xbb, 0x30, 0x0e, 0x8f, 0x50, 0xc7, 0x55, 0xf5,
+ 0x96, 0xe7, 0xa8, 0x6d, 0x63, 0x2d, 0x32, 0x38,
+ 0xaf, 0x00, 0xc4, 0x1a, 0xfc, 0xd8, 0xac, 0xc3 );
+
+/** Certificate store containing the iPXE self-test root CA */
+static struct x509_root test_root = {
+ .digest = &cms_test_algorithm,
+ .count = 1,
+ .fingerprints = root_crt_fingerprint,
+};
+
+/** Dummy fingerprint (not matching any certificates) */
+static uint8_t dummy_fingerprint[] =
+ FINGERPRINT ( 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff );
+
+/** Certificate store containing a dummy fingerprint */
+static struct x509_root dummy_root = {
+ .digest = &cms_test_algorithm,
+ .count = 1,
+ .fingerprints = dummy_fingerprint,
+};
+
+/** Time at which all test certificates are valid */
+static time_t test_time = 1332374737ULL; /* Thu Mar 22 00:05:37 2012 */
+
+/** Time at which end-entity test certificates are invalid */
+static time_t test_expired = 1375573111ULL; /* Sat Aug 3 23:38:31 2013 */
+
+/**
+ * Report signature parsing test result
+ *
+ * @v sgn Test signature
+ */
+#define cms_signature_ok( sgn ) do { \
+ ok ( cms_signature ( (sgn)->data, (sgn)->len, \
+ &(sgn)->sig ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report signature verification test result
+ *
+ * @v sgn Test signature
+ * @v code Test signed code
+ * @v name Test verification name
+ * @v time Test verification time
+ * @v root Test root certificate store
+ */
+#define cms_verify_ok( sgn, code, name, time, root ) do { \
+ x509_invalidate_chain ( (sgn)->sig->certificates ); \
+ ok ( cms_verify ( (sgn)->sig, virt_to_user ( (code)->data ), \
+ (code)->len, name, time, root ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report signature verification failure test result
+ *
+ * @v sgn Test signature
+ * @v code Test signed code
+ * @v name Test verification name
+ * @v time Test verification time
+ * @v root Test root certificate store
+ */
+#define cms_verify_fail_ok( sgn, code, name, time, root ) do { \
+ x509_invalidate_chain ( (sgn)->sig->certificates ); \
+ ok ( cms_verify ( (sgn)->sig, virt_to_user ( (code)->data ), \
+ (code)->len, name, time, root ) != 0 ); \
+ } while ( 0 )
+
+/**
+ * Perform CMS self-tests
+ *
+ */
+static void cms_test_exec ( void ) {
+
+ /* Check that all signatures can be parsed */
+ cms_signature_ok ( &codesigned_sig );
+ cms_signature_ok ( &brokenchain_sig );
+ cms_signature_ok ( &genericsigned_sig );
+ cms_signature_ok ( &nonsigned_sig );
+
+ /* Check good signature */
+ cms_verify_ok ( &codesigned_sig, &test_code,
+ "codesign.test.ipxe.org", test_time, &test_root );
+ cms_verify_ok ( &codesigned_sig, &test_code,
+ NULL, test_time, &test_root );
+
+ /* Check incorrect signer name */
+ cms_verify_fail_ok ( &codesigned_sig, &test_code,
+ "wrongname.test.ipxe.org", test_time, &test_root );
+
+ /* Check non-code-signing certificate */
+ cms_verify_fail_ok ( &genericsigned_sig, &test_code,
+ NULL, test_time, &test_root );
+
+ /* Check non-signing certificate */
+ cms_verify_fail_ok ( &nonsigned_sig, &test_code,
+ NULL, test_time, &test_root );
+
+ /* Check broken chain */
+ cms_verify_fail_ok ( &brokenchain_sig, &test_code,
+ NULL, test_time, &test_root );
+
+ /* Check untrusted signature */
+ cms_verify_fail_ok ( &codesigned_sig, &test_code,
+ NULL, test_time, &dummy_root );
+
+ /* Check incorrect signed content */
+ cms_verify_fail_ok ( &codesigned_sig, &bad_code,
+ NULL, test_time, &test_root );
+
+ /* Check expired signature */
+ cms_verify_fail_ok ( &codesigned_sig, &test_code,
+ NULL, test_expired, &test_root );
+
+ /* Drop signature references */
+ cms_put ( nonsigned_sig.sig );
+ cms_put ( genericsigned_sig.sig );
+ cms_put ( brokenchain_sig.sig );
+ cms_put ( codesigned_sig.sig );
+}
+
+/** CMS self-test */
+struct self_test cms_test __self_test = {
+ .name = "cms",
+ .exec = cms_test_exec,
+};
+
+/* Drag in algorithms required for tests */
+REQUIRE_OBJECT ( rsa );
+REQUIRE_OBJECT ( md5 );
+REQUIRE_OBJECT ( sha1 );
+REQUIRE_OBJECT ( sha256 );
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/comboot/shuffle-simple.asm b/src/VBox/Devices/PC/ipxe/src/tests/comboot/shuffle-simple.asm
new file mode 100644
index 00000000..efc7d9b4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/comboot/shuffle-simple.asm
@@ -0,0 +1,40 @@
+ bits 16
+ org 100h
+
+ jmp start
+
+shuffle_start:
+ push 0xB800
+ pop es
+ mov cx, 80*24*2
+ mov ax, 'AA'
+ xor di, di
+ rep stosw
+.lbl: jmp .lbl
+shuffle_end:
+ nop
+shuffle_len equ (shuffle_end - shuffle_start + 1)
+
+start:
+ ; calculate physical address of shuffled part
+ xor eax, eax
+ push ds
+ pop ax
+ shl eax, 4
+ add ax, shuffle_start
+ mov dword [source], eax
+
+ mov ax, 0012h
+ mov di, shuffle_descriptors
+ mov cx, num_shuffle_descriptors
+ mov ebp, 0x7c00
+ int 22h
+ int3
+
+shuffle_descriptors:
+ dd 0x7C00
+source: dd 0
+ dd shuffle_len
+
+num_shuffle_descriptors equ 1
+
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/comboot/version.asm b/src/VBox/Devices/PC/ipxe/src/tests/comboot/version.asm
new file mode 100644
index 00000000..01140423
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/comboot/version.asm
@@ -0,0 +1,136 @@
+ bits 16
+ org 100h
+
+_start:
+ ; first check for SYSLINUX
+ mov ah, 30h
+ int 21h
+
+ cmp eax, 59530000h
+ jne .not_syslinux
+ cmp ebx, 4c530000h
+ jne .not_syslinux
+ cmp ecx, 4e490000h
+ jne .not_syslinux
+ cmp edx, 58550000h
+ jne .not_syslinux
+
+ ; now get syslinux version
+ mov ax, 0001h
+ int 22h
+
+ push cx
+ push dx
+ push di
+ push si
+ push es
+
+ ; print version string
+ mov dx, str_version
+ mov ah, 09h
+ int 21h
+
+ pop es
+ pop bx
+ push es
+ mov ax, 0002h
+ int 22h
+
+ ; print copyright string
+ mov dx, str_copyright
+ mov ah, 09h
+ int 21h
+
+ pop es
+ pop bx
+ mov ax, 0002h
+ int 22h
+
+ ; print syslinux derivative id
+ mov dx, str_derivative
+ mov ah, 09h
+ int 21h
+
+ pop ax
+ call print_hex_byte
+
+ ; print version number
+ mov dx, str_version_num
+ mov ah, 09h
+ int 21h
+
+ pop cx
+ push cx
+ mov ax, cx
+ and ax, 0FFh
+ call print_dec_word
+
+ mov dl, '.'
+ mov ah, 02h
+ int 21h
+
+ pop cx
+ mov ax, cx
+ shr ax, 8
+ call print_dec_word
+
+ ret
+
+
+.not_syslinux:
+ mov dx, str_not_syslinux
+ mov ah, 09h
+ int 21h
+ ret
+
+; input: al = byte to print in hex
+print_hex_byte:
+ push ax
+ shr al, 4
+ call print_hex_nybble
+ pop ax
+ call print_hex_nybble
+ ret
+
+; input: bottom half of al = nybble to print in hex
+print_hex_nybble:
+ push ax
+ mov bl, al
+ and bx, 1111b
+ mov dl, [str_hex + bx]
+ mov ah, 02h
+ int 21h
+ pop ax
+ ret
+
+str_hex: db "01234567890abcdef"
+
+; input: ax = word to print
+print_dec_word:
+ mov cx, 10
+ mov word [.count], 0
+.loop:
+ xor dx, dx
+ div cx
+ inc word [.count]
+ push dx
+ test ax, ax
+ jnz .loop
+
+.print:
+ pop dx
+ add dx, '0'
+ mov ah, 02h
+ int 21h
+ dec word [.count]
+ jnz .print
+
+ ret
+
+.count: dw 0
+
+str_not_syslinux: db "Not SYSLINUX or derivative (running on DOS?)$"
+str_version: db "Version: $"
+str_copyright: db 10, "Copyright: $"
+str_derivative: db 10, "Derivative ID: 0x$"
+str_version_num: db 10, "Version number: $"
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/crc32_test.c b/src/VBox/Devices/PC/ipxe/src/tests/crc32_test.c
new file mode 100644
index 00000000..91ae8dd9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/crc32_test.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * CRC32 tests
+ *
+ *
+ * Test vectors generated using Perl's Digest::CRC:
+ *
+ * use Digest::CRC qw ( crc );
+ *
+ * printf "%#08x", crc ( $data, 32, $seed, 0, 1, 0x04c11db7, 1 );
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <stdint.h>
+#include <ipxe/crc32.h>
+#include <ipxe/test.h>
+
+/** Define inline data */
+#define DATA(...) { __VA_ARGS__ }
+
+/** A CRC32 test */
+struct crc32_test {
+ /** Test data */
+ const void *data;
+ /** Length of test data */
+ size_t len;
+ /** Seed */
+ uint32_t seed;
+ /** Expected CRC32 */
+ uint32_t crc32;
+};
+
+/**
+ * Define a CRC32 test
+ *
+ * @v name Test name
+ * @v DATA Test data
+ * @v SEED Seed
+ * @v CRC32 Expected CRC32
+ * @ret test CRC32 test
+ */
+#define CRC32_TEST( name, DATA, SEED, CRC32 ) \
+ static const uint8_t name ## _data[] = DATA; \
+ static struct crc32_test name = { \
+ .data = name ## _data, \
+ .len = sizeof ( name ## _data ), \
+ .seed = SEED, \
+ .crc32 = CRC32, \
+ };
+
+/**
+ * Report a CRC32 test result
+ *
+ * @v test CRC32 test
+ */
+#define crc32_ok( test ) do { \
+ uint32_t crc32; \
+ crc32 = crc32_le ( (test)->seed, (test)->data, (test)->len ); \
+ ok ( crc32 == (test)->crc32 ); \
+ } while ( 0 )
+
+/* CRC32 tests */
+CRC32_TEST ( empty_test,
+ DATA ( ),
+ 0x12345678UL, 0x12345678UL );
+CRC32_TEST ( hw_test,
+ DATA ( 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd' ),
+ 0xffffffffUL, 0xf2b5ee7aUL );
+CRC32_TEST ( hw_split_part1_test,
+ DATA ( 'h', 'e', 'l', 'l', 'o' ),
+ 0xffffffffUL, 0xc9ef5979UL );
+CRC32_TEST ( hw_split_part2_test,
+ DATA ( ' ', 'w', 'o', 'r', 'l', 'd' ),
+ 0xc9ef5979UL, 0xf2b5ee7aUL );
+
+/**
+ * Perform CRC32 self-tests
+ *
+ */
+static void crc32_test_exec ( void ) {
+
+ crc32_ok ( &empty_test );
+ crc32_ok ( &hw_test );
+ crc32_ok ( &hw_split_part1_test );
+ crc32_ok ( &hw_split_part2_test );
+}
+
+/** CRC32 self-test */
+struct self_test crc32_test __self_test = {
+ .name = "crc32",
+ .exec = crc32_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/digest_test.c b/src/VBox/Devices/PC/ipxe/src/tests/digest_test.c
new file mode 100644
index 00000000..7c2b4a47
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/digest_test.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Digest self-tests
+ *
+ */
+
+#include <string.h>
+#include <ipxe/crypto.h>
+#include "digest_test.h"
+
+/**
+ * Test digest algorithm
+ *
+ * @v digest Digest algorithm
+ * @v fragments Digest test fragment list, or NULL
+ * @v data Test data
+ * @v len Length of test data
+ * @v expected Expected digest value
+ * @ret ok Digest value is as expected
+ */
+int digest_test ( struct digest_algorithm *digest,
+ struct digest_test_fragments *fragments,
+ void *data, size_t len, void *expected ) {
+ uint8_t ctx[digest->ctxsize];
+ uint8_t out[digest->digestsize];
+ size_t frag_len = 0;
+ unsigned int i;
+
+ /* Initialise digest */
+ digest_init ( digest, ctx );
+
+ /* Update digest fragment-by-fragment */
+ for ( i = 0 ; len && ( i < ( sizeof ( fragments->len ) /
+ sizeof ( fragments->len[0] ) ) ) ; i++ ) {
+ if ( fragments )
+ frag_len = fragments->len[i];
+ if ( ( frag_len == 0 ) || ( frag_len < len ) )
+ frag_len = len;
+ digest_update ( digest, ctx, data, frag_len );
+ data += frag_len;
+ len -= frag_len;
+ }
+
+ /* Finalise digest */
+ digest_final ( digest, ctx, out );
+
+ /* Compare against expected output */
+ return ( memcmp ( expected, out, sizeof ( out ) ) == 0 );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/digest_test.h b/src/VBox/Devices/PC/ipxe/src/tests/digest_test.h
new file mode 100644
index 00000000..c2558780
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/digest_test.h
@@ -0,0 +1,36 @@
+#ifndef _DIGEST_TEST_H
+#define _DIGEST_TEST_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/crypto.h>
+#include <ipxe/test.h>
+
+/** Maximum number of digest test fragments */
+#define NUM_DIGEST_TEST_FRAG 8
+
+/** A digest test fragment list */
+struct digest_test_fragments {
+ /** Fragment lengths */
+ size_t len[NUM_DIGEST_TEST_FRAG];
+};
+
+extern int digest_test ( struct digest_algorithm *digest,
+ struct digest_test_fragments *fragments,
+ void *data, size_t len, void *expected );
+
+/**
+ * Report digest test result
+ *
+ * @v digest Digest algorithm
+ * @v fragments Digest test fragment list, or NULL
+ * @v data Test data
+ * @v len Length of test data
+ * @v expected Expected digest value
+ */
+#define digest_ok( digest, fragments, data, len, expected ) do { \
+ ok ( digest_test ( digest, fragments, data, len, expected ) ); \
+ } while ( 0 )
+
+#endif /* _DIGEST_TEST_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/entropy_sample.c b/src/VBox/Devices/PC/ipxe/src/tests/entropy_sample.c
new file mode 100644
index 00000000..9e75b4e9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/entropy_sample.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Entropy sampling
+ *
+ */
+
+#include <stdio.h>
+#include <ipxe/entropy.h>
+#include <ipxe/test.h>
+
+/** Total number of test samples */
+#define SAMPLE_COUNT 65536
+
+/** Number of samples per block */
+#define SAMPLE_BLOCKSIZE 256
+
+/**
+ * Generate entropy samples for external testing
+ *
+ */
+static void entropy_sample_test_exec ( void ) {
+ static noise_sample_t samples[SAMPLE_BLOCKSIZE];
+ unsigned int i;
+ unsigned int j;
+ int rc;
+
+ /* Collect and print blocks of samples */
+ for ( i = 0 ; i < ( SAMPLE_COUNT / SAMPLE_BLOCKSIZE ) ; i++ ) {
+
+ /* Collect one block of samples */
+ rc = entropy_enable();
+ ok ( rc == 0 );
+ for ( j = 0 ; j < SAMPLE_BLOCKSIZE ; j++ ) {
+ rc = get_noise ( &samples[j] );
+ ok ( rc == 0 );
+ }
+ entropy_disable();
+
+ /* Print out sample values */
+ for ( j = 0 ; j < SAMPLE_BLOCKSIZE ; j++ ) {
+ printf ( "SAMPLE %d %d\n", ( i * SAMPLE_BLOCKSIZE + j ),
+ samples[j] );
+ }
+ }
+}
+
+/** Entropy sampling self-test */
+struct self_test entropy_sample_test __self_test = {
+ .name = "entropy_sample",
+ .exec = entropy_sample_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/gdbstub_test.S b/src/VBox/Devices/PC/ipxe/src/tests/gdbstub_test.S
new file mode 100644
index 00000000..739b0527
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/gdbstub_test.S
@@ -0,0 +1,54 @@
+ .arch i386
+
+ .section ".data", "aw", @progbits
+watch_me:
+ .long 0xfeedbeef
+
+ .section ".text", "ax", @progbits
+ .code32
+gdbstub_test:
+ /* 1. Read registers test */
+ movl $0xea010203, %eax
+ movl $0xeb040506, %ebx
+ movl $0xec070809, %ecx
+ movl $0xed0a0b0c, %edx
+ movl $0x510d0e0f, %esi
+ movl $0xd1102030, %edi
+ int $3
+
+ /* 2. Write registers test */
+ int $3
+
+ /* 3. Read memory test */
+ subl $8, %esp
+ movl $0x11223344, 4(%esp)
+ movw $0x5566, 2(%esp)
+ movb $0x77, (%esp)
+ int $3
+
+ /* 4. Write memory test */
+ int $3
+ addl $8, %esp
+
+ /* 5. Step test */
+ int $3
+ nop
+
+ /* 6. Access watch test */
+ movl $0x600d0000, %ecx
+ movl watch_me, %eax
+ movl $0xbad00000, %ecx
+ int $3
+ movl $0x600d0001, %ecx
+ movl %eax, watch_me
+ movl $0xbad00001, %ecx
+ int $3
+
+ /* 7. Write watch test */
+ movl $0x600d0002, %ecx
+ movl %eax, watch_me
+ movl $0xbad00002, %ecx
+ int $3
+
+1:
+ jmp 1b
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/gdbstub_test.gdb b/src/VBox/Devices/PC/ipxe/src/tests/gdbstub_test.gdb
new file mode 100755
index 00000000..bcfa07da
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/gdbstub_test.gdb
@@ -0,0 +1,116 @@
+#!/usr/bin/gdb -x
+# Test suite for GDB remote debugging
+# Run:
+# make bin/ipxe.hd.tmp
+# make
+# gdb
+# (gdb) target remote :TCPPORT
+# OR
+# (gdb) target remote udp:IP:UDPPORT
+# (gdb) source tests/gdbstub_test.gdb
+
+define ipxe_load_symbols
+ file bin/ipxe.hd.tmp
+end
+
+define ipxe_assert
+ if $arg0 != $arg1
+ echo FAIL $arg2\n
+ else
+ echo PASS $arg2\n
+ end
+end
+
+define ipxe_start_tests
+ jump gdbstub_test
+end
+
+define ipxe_test_regs_read
+ ipxe_assert $eax 0xea010203 "ipxe_test_regs_read eax"
+ ipxe_assert $ebx 0xeb040506 "ipxe_test_regs_read ebx"
+ ipxe_assert $ecx 0xec070809 "ipxe_test_regs_read ecx"
+ ipxe_assert $edx 0xed0a0b0c "ipxe_test_regs_read edx"
+ ipxe_assert $esi 0x510d0e0f "ipxe_test_regs_read esi"
+ ipxe_assert $edi 0xd1102030 "ipxe_test_regs_read edi"
+end
+
+define ipxe_test_regs_write
+ set $eax = 0xea112233
+ set $ebx = 0xeb445566
+ set $ecx = 0xec778899
+ set $edx = 0xedaabbcc
+ set $esi = 0x51ddeeff
+ set $edi = 0xd1010203
+ c
+ ipxe_assert $eax 0xea112233 "ipxe_test_regs_write eax"
+ ipxe_assert $ebx 0xeb445566 "ipxe_test_regs_write ebx"
+ ipxe_assert $ecx 0xec778899 "ipxe_test_regs_write ecx"
+ ipxe_assert $edx 0xedaabbcc "ipxe_test_regs_write edx"
+ ipxe_assert $esi 0x51ddeeff "ipxe_test_regs_write esi"
+ ipxe_assert $edi 0xd1010203 "ipxe_test_regs_write edi"
+
+ # This assumes segment selectors are always 0x10 or 0x8 (for code).
+ ipxe_assert $cs 0x08 "ipxe_test_regs_write cs"
+ ipxe_assert $ds 0x10 "ipxe_test_regs_write ds"
+end
+
+define ipxe_test_mem_read
+ c
+ ipxe_assert ({int}($esp+4)) 0x11223344 "ipxe_test_mem_read int"
+ ipxe_assert ({short}($esp+2)) 0x5566 "ipxe_test_mem_read short"
+ ipxe_assert ({char}($esp)) 0x77 "ipxe_test_mem_read char"
+end
+
+define ipxe_test_mem_write
+ set ({int}($esp+4)) = 0xaabbccdd
+ set ({short}($esp+2)) = 0xeeff
+ set ({char}($esp)) = 0x99
+ c
+ ipxe_assert ({int}($esp+4)) 0xaabbccdd "ipxe_test_mem_write int"
+ ipxe_assert ({short}($esp+2)) (short)0xeeff "ipxe_test_mem_write short"
+ ipxe_assert ({char}($esp)) (char)0x99 "ipxe_test_mem_write char"
+end
+
+define ipxe_test_step
+ c
+ si
+ ipxe_assert ({char}($eip-1)) (char)0x90 "ipxe_test_step" # nop = 0x90
+end
+
+define ipxe_test_awatch
+ awatch watch_me
+
+ c
+ ipxe_assert $ecx 0x600d0000 "ipxe_test_awatch read"
+ if $ecx == 0x600d0000
+ c
+ end
+
+ c
+ ipxe_assert $ecx 0x600d0001 "ipxe_test_awatch write"
+ if $ecx == 0x600d0001
+ c
+ end
+
+ delete
+end
+
+define ipxe_test_watch
+ watch watch_me
+ c
+ ipxe_assert $ecx 0x600d0002 "ipxe_test_watch"
+ if $ecx == 0x600d0002
+ c
+ end
+ delete
+end
+
+ipxe_load_symbols
+ipxe_start_tests
+ipxe_test_regs_read
+ipxe_test_regs_write
+ipxe_test_mem_read
+ipxe_test_mem_write
+ipxe_test_step
+ipxe_test_awatch
+ipxe_test_watch
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/hash_df_test.c b/src/VBox/Devices/PC/ipxe/src/tests/hash_df_test.c
new file mode 100644
index 00000000..ccbc86ea
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/hash_df_test.c
@@ -0,0 +1,897 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Hash-based derivation function (Hash_df) tests
+ *
+ * These test vectors are provided by NIST as part of the
+ * Cryptographic Toolkit Examples, downloadable from:
+ *
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/Hash_DRBG.pdf
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <assert.h>
+#include <string.h>
+#include <ipxe/hash_df.h>
+#include <ipxe/sha1.h>
+#include <ipxe/sha256.h>
+#include <ipxe/test.h>
+
+/** Define inline input data */
+#define INPUT(...) { __VA_ARGS__ }
+
+/** Define inline expected data */
+#define EXPECT(...) { __VA_ARGS__ }
+
+/** A Hash_df test */
+struct hash_df_test {
+ /** Underlying hash algorithm */
+ struct digest_algorithm *hash;
+ /** Input data */
+ const void *input;
+ /** Length of input data */
+ size_t input_len;
+ /** Expected output data */
+ const void *expected;
+ /** Length of expected output data */
+ size_t expected_len;
+};
+
+/**
+ * Define a Hash_df test
+ *
+ * @v name Test name
+ * @v hash_algorithm Underlying hash algorithm
+ * @v input_array Input data
+ * @v expected_array Expected output data
+ * @ret test Hash_df test
+ */
+#define HASH_DF_TEST( name, hash_algorithm, input_array, expected_array ) \
+ static const uint8_t name ## _input [] = input_array; \
+ static const uint8_t name ## _expected [] = expected_array; \
+ static struct hash_df_test name = { \
+ .hash = &(hash_algorithm), \
+ .input = name ## _input, \
+ .input_len = sizeof ( name ## _input ), \
+ .expected = name ## _expected, \
+ .expected_len = sizeof ( name ## _expected ), \
+ }
+
+/** SHA-1 Test 1 */
+HASH_DF_TEST ( test_sha1_1, sha1_algorithm,
+ INPUT ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+ 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+ 0x32, 0x33, 0x34, 0x35, 0x36, 0x20, 0x21, 0x22, 0x23, 0x24 ),
+ EXPECT ( 0xd0, 0x8f, 0xb4, 0x41, 0xf2, 0xf4, 0xcb, 0x37, 0xcf, 0x6c,
+ 0x24, 0x20, 0xa8, 0x2c, 0x74, 0x27, 0xac, 0xf7, 0xfc, 0xfd,
+ 0x79, 0x90, 0x14, 0x38, 0x34, 0xa5, 0xc2, 0x56, 0xab, 0x28,
+ 0x39, 0x36, 0x6d, 0x96, 0x34, 0x8c, 0xfe, 0x8c, 0x97, 0xab,
+ 0x67, 0x67, 0xb0, 0x5e, 0x83, 0xa9, 0x80, 0x40, 0x6d, 0x94,
+ 0xbe, 0xe3, 0x3c, 0xbb, 0x89 ) );
+
+/** SHA-1 Test 2 */
+HASH_DF_TEST ( test_sha1_2, sha1_algorithm,
+ INPUT ( 0x00, 0xd0, 0x8f, 0xb4, 0x41, 0xf2, 0xf4, 0xcb, 0x37, 0xcf,
+ 0x6c, 0x24, 0x20, 0xa8, 0x2c, 0x74, 0x27, 0xac, 0xf7, 0xfc,
+ 0xfd, 0x79, 0x90, 0x14, 0x38, 0x34, 0xa5, 0xc2, 0x56, 0xab,
+ 0x28, 0x39, 0x36, 0x6d, 0x96, 0x34, 0x8c, 0xfe, 0x8c, 0x97,
+ 0xab, 0x67, 0x67, 0xb0, 0x5e, 0x83, 0xa9, 0x80, 0x40, 0x6d,
+ 0x94, 0xbe, 0xe3, 0x3c, 0xbb, 0x89 ),
+ EXPECT ( 0x54, 0xc5, 0x21, 0x7b, 0x51, 0x02, 0xd8, 0xda, 0x8b, 0xf1,
+ 0x68, 0x6e, 0xdb, 0xab, 0x2b, 0xbc, 0x0c, 0x11, 0xb0, 0xcc,
+ 0xb0, 0xf0, 0xaf, 0x23, 0x4c, 0x24, 0xcf, 0x15, 0xec, 0xc8,
+ 0xcb, 0x39, 0xc2, 0x33, 0xaa, 0xca, 0x48, 0xfc, 0xce, 0xee,
+ 0x86, 0x3d, 0xa8, 0x81, 0xff, 0xcb, 0xb4, 0x34, 0xa6, 0xcc,
+ 0xb7, 0xda, 0x2f, 0xb2, 0x10 ) );
+
+/** SHA-1 Test 3 */
+HASH_DF_TEST ( test_sha1_3, sha1_algorithm,
+ INPUT ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+ 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+ 0x32, 0x33, 0x34, 0x35, 0x36, 0x20, 0x21, 0x22, 0x23, 0x24,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53,
+ 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d,
+ 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71,
+ 0x72, 0x73, 0x74, 0x75, 0x76 ),
+ EXPECT ( 0x99, 0xb9, 0x53, 0x7b, 0x84, 0x27, 0xb8, 0xce, 0x23, 0x21,
+ 0x9a, 0x61, 0x1c, 0xbe, 0x61, 0x06, 0x44, 0xcf, 0x85, 0x03,
+ 0xee, 0xc5, 0xba, 0x22, 0xde, 0x1a, 0xb2, 0x12, 0xc3, 0xd0,
+ 0x85, 0x8e, 0x9e, 0x3b, 0x90, 0x26, 0xd4, 0xe7, 0x7d, 0x58,
+ 0xe0, 0x2e, 0x85, 0xa2, 0x31, 0x4c, 0xe3, 0xd7, 0x4a, 0x93,
+ 0x32, 0x4b, 0x27, 0xbd, 0xe8 ) );
+
+/** SHA-1 Test 4 */
+HASH_DF_TEST ( test_sha1_4, sha1_algorithm,
+ INPUT ( 0x00, 0x99, 0xb9, 0x53, 0x7b, 0x84, 0x27, 0xb8, 0xce, 0x23,
+ 0x21, 0x9a, 0x61, 0x1c, 0xbe, 0x61, 0x06, 0x44, 0xcf, 0x85,
+ 0x03, 0xee, 0xc5, 0xba, 0x22, 0xde, 0x1a, 0xb2, 0x12, 0xc3,
+ 0xd0, 0x85, 0x8e, 0x9e, 0x3b, 0x90, 0x26, 0xd4, 0xe7, 0x7d,
+ 0x58, 0xe0, 0x2e, 0x85, 0xa2, 0x31, 0x4c, 0xe3, 0xd7, 0x4a,
+ 0x93, 0x32, 0x4b, 0x27, 0xbd, 0xe8 ),
+ EXPECT ( 0xa7, 0x02, 0x66, 0xf7, 0xf9, 0x1e, 0xc4, 0xd2, 0x88, 0x73,
+ 0x14, 0x79, 0x34, 0xce, 0xaf, 0x2a, 0x2c, 0xc3, 0x5a, 0x0f,
+ 0xd5, 0xe0, 0x0a, 0xba, 0xe7, 0x9d, 0xc6, 0x60, 0x5f, 0xab,
+ 0xd6, 0xf5, 0xf9, 0x28, 0xe1, 0x8c, 0x63, 0x26, 0x8e, 0x1a,
+ 0xf4, 0x85, 0xda, 0x6c, 0xbf, 0x04, 0x16, 0xdc, 0xdc, 0x5f,
+ 0xb8, 0xbc, 0x9c, 0x94, 0xb6 ) );
+
+/** SHA-1 Test 5 */
+HASH_DF_TEST ( test_sha1_5, sha1_algorithm,
+ INPUT ( 0x01, 0xd0, 0x8f, 0xb4, 0x41, 0xf2, 0xf4, 0xcb, 0x37, 0xcf,
+ 0x6c, 0x24, 0x20, 0xa8, 0x2c, 0x74, 0x27, 0xac, 0xf7, 0xfc,
+ 0xfd, 0x79, 0x90, 0x14, 0x38, 0x34, 0xa5, 0xc2, 0x56, 0xab,
+ 0x28, 0x39, 0x36, 0x6d, 0x96, 0x34, 0x8c, 0xfe, 0x8c, 0x97,
+ 0xab, 0x67, 0x67, 0xb0, 0x5e, 0x83, 0xa9, 0x80, 0x40, 0x6d,
+ 0x94, 0xbe, 0xe3, 0x3c, 0xbb, 0x89, 0x80, 0x81, 0x82, 0x83,
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
+ 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1,
+ 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
+ 0xb6 ),
+ EXPECT ( 0x0a, 0x04, 0x41, 0xa5, 0x2b, 0xed, 0xf7, 0x94, 0xf5, 0xaa,
+ 0x62, 0x7b, 0xcb, 0xd8, 0x1f, 0x93, 0xe0, 0x11, 0xd5, 0x1f,
+ 0x34, 0x74, 0x80, 0x2c, 0x37, 0x50, 0x76, 0x75, 0x51, 0xb4,
+ 0x5b, 0x69, 0xf3, 0xd3, 0x59, 0x39, 0xc9, 0x32, 0xae, 0x1c,
+ 0xb7, 0xc9, 0x89, 0x4f, 0xb8, 0x84, 0x65, 0xe0, 0xcf, 0xd1,
+ 0xcc, 0x26, 0x1e, 0x22, 0xc5 ) );
+
+/** SHA-1 Test 6 */
+HASH_DF_TEST ( test_sha1_6, sha1_algorithm,
+ INPUT ( 0x00, 0x0a, 0x04, 0x41, 0xa5, 0x2b, 0xed, 0xf7, 0x94, 0xf5,
+ 0xaa, 0x62, 0x7b, 0xcb, 0xd8, 0x1f, 0x93, 0xe0, 0x11, 0xd5,
+ 0x1f, 0x34, 0x74, 0x80, 0x2c, 0x37, 0x50, 0x76, 0x75, 0x51,
+ 0xb4, 0x5b, 0x69, 0xf3, 0xd3, 0x59, 0x39, 0xc9, 0x32, 0xae,
+ 0x1c, 0xb7, 0xc9, 0x89, 0x4f, 0xb8, 0x84, 0x65, 0xe0, 0xcf,
+ 0xd1, 0xcc, 0x26, 0x1e, 0x22, 0xc5 ),
+ EXPECT ( 0x04, 0x11, 0xc8, 0xb0, 0xdb, 0xa7, 0x56, 0xe8, 0x84, 0x2b,
+ 0x3f, 0xb0, 0x2d, 0x2f, 0xeb, 0x7c, 0xee, 0xa5, 0x67, 0x42,
+ 0xee, 0x93, 0x79, 0xc9, 0x0e, 0x6d, 0x3b, 0x2f, 0x10, 0x10,
+ 0xd4, 0x0f, 0x4f, 0x4d, 0xca, 0xda, 0x61, 0xcf, 0xdf, 0xb4,
+ 0x8a, 0xf8, 0x47, 0xca, 0xcc, 0x4c, 0x92, 0xc6, 0x14, 0x44,
+ 0x85, 0xc2, 0x27, 0xca, 0x05 ) );
+
+/** SHA-1 Test 7 */
+HASH_DF_TEST ( test_sha1_7, sha1_algorithm,
+ INPUT ( 0x01, 0x0e, 0x16, 0x0a, 0x56, 0x07, 0x95, 0x4e, 0x7d, 0x79,
+ 0xd5, 0xa2, 0x2b, 0xf9, 0x08, 0x0b, 0x10, 0xce, 0xb7, 0x3c,
+ 0x62, 0x23, 0x07, 0xf9, 0xf5, 0x45, 0xbd, 0xb1, 0xa4, 0x61,
+ 0xc5, 0x2f, 0x79, 0x43, 0x21, 0x24, 0x3a, 0xac, 0xe2, 0x3f,
+ 0x36, 0x3f, 0xef, 0xb3, 0x5d, 0xc5, 0xbe, 0xa7, 0xe7, 0x31,
+ 0x44, 0x14, 0xcf, 0x78, 0xb3, 0xf9, 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd,
+ 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
+ 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
+ 0xf6 ),
+ EXPECT ( 0xdc, 0x24, 0xdf, 0x10, 0x2f, 0xa9, 0xf9, 0x6c, 0xc1, 0xcf,
+ 0xf8, 0xc1, 0x16, 0xc7, 0x9d, 0x14, 0x97, 0xd7, 0xc2, 0x7b,
+ 0xba, 0x5b, 0xa8, 0x01, 0xe1, 0x56, 0x21, 0x93, 0x35, 0x3f,
+ 0x31, 0xe3, 0x22, 0x39, 0x57, 0x84, 0x69, 0xb8, 0x0f, 0x2f,
+ 0x51, 0x64, 0x54, 0x37, 0x28, 0x71, 0x7f, 0x17, 0x1f, 0xdb,
+ 0x02, 0xb2, 0xad, 0x57, 0x95 ) );
+
+/** SHA-1 Test 8 */
+HASH_DF_TEST ( test_sha1_8, sha1_algorithm,
+ INPUT ( 0x00, 0xdc, 0x24, 0xdf, 0x10, 0x2f, 0xa9, 0xf9, 0x6c, 0xc1,
+ 0xcf, 0xf8, 0xc1, 0x16, 0xc7, 0x9d, 0x14, 0x97, 0xd7, 0xc2,
+ 0x7b, 0xba, 0x5b, 0xa8, 0x01, 0xe1, 0x56, 0x21, 0x93, 0x35,
+ 0x3f, 0x31, 0xe3, 0x22, 0x39, 0x57, 0x84, 0x69, 0xb8, 0x0f,
+ 0x2f, 0x51, 0x64, 0x54, 0x37, 0x28, 0x71, 0x7f, 0x17, 0x1f,
+ 0xdb, 0x02, 0xb2, 0xad, 0x57, 0x95 ),
+ EXPECT ( 0xff, 0xaf, 0x45, 0x66, 0x5b, 0x11, 0x0c, 0xa1, 0x33, 0x5a,
+ 0x3f, 0xce, 0x73, 0xa7, 0x98, 0x1d, 0x0f, 0xd5, 0xc8, 0xd9,
+ 0x03, 0xf6, 0x5f, 0xaa, 0x46, 0xa3, 0xd5, 0x97, 0xbf, 0x34,
+ 0xc4, 0xe0, 0xcc, 0x16, 0x75, 0x60, 0xab, 0x94, 0xec, 0x10,
+ 0xd6, 0x41, 0x5f, 0x37, 0x83, 0xb0, 0x15, 0x67, 0x89, 0x1b,
+ 0x57, 0x66, 0x2a, 0xbb, 0x39 ) );
+
+/** SHA-1 Test 9 */
+HASH_DF_TEST ( test_sha1_9, sha1_algorithm,
+ INPUT ( 0x01, 0xd0, 0x8f, 0xb4, 0x41, 0xf2, 0xf4, 0xcb, 0x37, 0xcf,
+ 0x6c, 0x24, 0x20, 0xa8, 0x2c, 0x74, 0x27, 0xac, 0xf7, 0xfc,
+ 0xfd, 0x79, 0x90, 0x14, 0x38, 0x34, 0xa5, 0xc2, 0x56, 0xab,
+ 0x28, 0x39, 0x36, 0x6d, 0x96, 0x34, 0x8c, 0xfe, 0x8c, 0x97,
+ 0xab, 0x67, 0x67, 0xb0, 0x5e, 0x83, 0xa9, 0x80, 0x40, 0x6d,
+ 0x94, 0xbe, 0xe3, 0x3c, 0xbb, 0x89, 0x80, 0x81, 0x82, 0x83,
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
+ 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1,
+ 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
+ 0xb6, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72,
+ 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c,
+ 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
+ 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
+ 0x91, 0x92, 0x93, 0x94, 0x95, 0x96 ),
+ EXPECT ( 0x8f, 0xde, 0xc9, 0xe6, 0x18, 0x96, 0x36, 0xf0, 0xa5, 0xce,
+ 0x53, 0xe8, 0x1c, 0x13, 0xac, 0x93, 0x84, 0xfa, 0xfb, 0xa0,
+ 0xee, 0x50, 0xc1, 0xe2, 0xc8, 0xa0, 0x99, 0xde, 0x41, 0xd8,
+ 0xcc, 0x7a, 0x31, 0x42, 0x9e, 0x8c, 0x8c, 0x88, 0x80, 0xe3,
+ 0xb4, 0x5d, 0x89, 0xdb, 0x61, 0x2c, 0xd9, 0xd2, 0x8a, 0x55,
+ 0xc0, 0xf0, 0xd1, 0xf8, 0xf9 ) );
+
+/** SHA-1 Test 10 */
+HASH_DF_TEST ( test_sha1_10, sha1_algorithm,
+ INPUT ( 0x00, 0x8f, 0xde, 0xc9, 0xe6, 0x18, 0x96, 0x36, 0xf0, 0xa5,
+ 0xce, 0x53, 0xe8, 0x1c, 0x13, 0xac, 0x93, 0x84, 0xfa, 0xfb,
+ 0xa0, 0xee, 0x50, 0xc1, 0xe2, 0xc8, 0xa0, 0x99, 0xde, 0x41,
+ 0xd8, 0xcc, 0x7a, 0x31, 0x42, 0x9e, 0x8c, 0x8c, 0x88, 0x80,
+ 0xe3, 0xb4, 0x5d, 0x89, 0xdb, 0x61, 0x2c, 0xd9, 0xd2, 0x8a,
+ 0x55, 0xc0, 0xf0, 0xd1, 0xf8, 0xf9 ),
+ EXPECT ( 0x97, 0xd0, 0x76, 0x31, 0xb2, 0x2f, 0x7c, 0x95, 0x7f, 0x19,
+ 0xf8, 0x44, 0xf4, 0xdc, 0x2a, 0xfa, 0x6f, 0xf9, 0x7c, 0x35,
+ 0x66, 0x18, 0x98, 0x21, 0x69, 0x91, 0xd1, 0x5b, 0xda, 0x75,
+ 0xbb, 0xd0, 0x5e, 0xdf, 0x8a, 0x0f, 0xa8, 0x0c, 0xca, 0xb9,
+ 0x51, 0x95, 0xf4, 0x79, 0xcd, 0x76, 0x20, 0x22, 0x35, 0x10,
+ 0x2e, 0xf6, 0x27, 0x29, 0x19 ) );
+
+/** SHA-1 Test 11 */
+HASH_DF_TEST ( test_sha1_11, sha1_algorithm,
+ INPUT ( 0x01, 0x27, 0xaf, 0x40, 0x17, 0xca, 0xc5, 0xb3, 0x86, 0x24,
+ 0xe8, 0x4c, 0x2d, 0x10, 0xef, 0xd7, 0x8d, 0xf4, 0xf4, 0x77,
+ 0xd6, 0x54, 0x69, 0x5a, 0x04, 0x32, 0x32, 0x6b, 0x3a, 0x1c,
+ 0x4e, 0x88, 0x4a, 0x90, 0x22, 0x28, 0xe8, 0x9e, 0xaa, 0x90,
+ 0x36, 0xcd, 0x2a, 0xf7, 0x05, 0x66, 0x81, 0x26, 0x23, 0x72,
+ 0xc7, 0x13, 0x71, 0xd4, 0x53, 0x3d, 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd,
+ 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
+ 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
+ 0xf6, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+ 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2,
+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc,
+ 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
+ 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+ 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6 ),
+ EXPECT ( 0x2c, 0x9c, 0x0d, 0x80, 0x03, 0xe3, 0x40, 0x23, 0xbe, 0x5b,
+ 0x63, 0xfd, 0xb9, 0xd2, 0x24, 0xb4, 0x25, 0x0c, 0xc8, 0x15,
+ 0x5b, 0xd1, 0xee, 0xd8, 0xe5, 0x5d, 0x91, 0x06, 0x2f, 0xdd,
+ 0x27, 0x64, 0xb8, 0xae, 0xa9, 0xc8, 0x2f, 0x84, 0x7e, 0x09,
+ 0xa3, 0xfe, 0xa1, 0xc7, 0x11, 0x7d, 0x6f, 0x7d, 0xd2, 0xef,
+ 0x77, 0x7d, 0x7c, 0xf3, 0xeb ) );
+
+/** SHA-1 Test 12 */
+HASH_DF_TEST ( test_sha1_12, sha1_algorithm,
+ INPUT ( 0x00, 0x2c, 0x9c, 0x0d, 0x80, 0x03, 0xe3, 0x40, 0x23, 0xbe,
+ 0x5b, 0x63, 0xfd, 0xb9, 0xd2, 0x24, 0xb4, 0x25, 0x0c, 0xc8,
+ 0x15, 0x5b, 0xd1, 0xee, 0xd8, 0xe5, 0x5d, 0x91, 0x06, 0x2f,
+ 0xdd, 0x27, 0x64, 0xb8, 0xae, 0xa9, 0xc8, 0x2f, 0x84, 0x7e,
+ 0x09, 0xa3, 0xfe, 0xa1, 0xc7, 0x11, 0x7d, 0x6f, 0x7d, 0xd2,
+ 0xef, 0x77, 0x7d, 0x7c, 0xf3, 0xeb ),
+ EXPECT ( 0x7e, 0x8a, 0xa4, 0x93, 0x42, 0x72, 0xf2, 0xa2, 0x8b, 0xbf,
+ 0xd7, 0xaf, 0xcc, 0x88, 0xce, 0x1c, 0x80, 0x6a, 0x38, 0xea,
+ 0x7b, 0x89, 0x45, 0xc8, 0xd1, 0xb6, 0xf1, 0x75, 0x03, 0x78,
+ 0x54, 0x6a, 0xb1, 0xa2, 0x96, 0x00, 0xd6, 0x44, 0xec, 0x52,
+ 0x0e, 0x8b, 0xff, 0xf6, 0x0c, 0xb7, 0x7f, 0xa5, 0x4b, 0xb1,
+ 0x1a, 0x83, 0x31, 0xcb, 0x24 ) );
+
+/** SHA-1 Test 13 */
+HASH_DF_TEST ( test_sha1_13, sha1_algorithm,
+ INPUT ( 0x01, 0x99, 0xb9, 0x53, 0x7b, 0x84, 0x27, 0xb8, 0xce, 0x23,
+ 0x21, 0x9a, 0x61, 0x1c, 0xbe, 0x61, 0x06, 0x44, 0xcf, 0x85,
+ 0x03, 0xee, 0xc5, 0xba, 0x22, 0xde, 0x1a, 0xb2, 0x12, 0xc3,
+ 0xd0, 0x85, 0x8e, 0x9e, 0x3b, 0x90, 0x26, 0xd4, 0xe7, 0x7d,
+ 0x58, 0xe0, 0x2e, 0x85, 0xa2, 0x31, 0x4c, 0xe3, 0xd7, 0x4a,
+ 0x93, 0x32, 0x4b, 0x27, 0xbd, 0xe8, 0x80, 0x81, 0x82, 0x83,
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
+ 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1,
+ 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
+ 0xb6 ),
+ EXPECT ( 0xe5, 0x04, 0x3d, 0x1b, 0x95, 0x4b, 0x34, 0xba, 0x60, 0xd2,
+ 0x48, 0xe8, 0x83, 0xef, 0x49, 0x8c, 0x5c, 0x52, 0x36, 0xb8,
+ 0x26, 0x0e, 0x23, 0x8e, 0x02, 0xc8, 0xd4, 0xfc, 0x5f, 0xfe,
+ 0x90, 0xfa, 0x40, 0x13, 0x44, 0x70, 0x75, 0xbb, 0x54, 0x3e,
+ 0xf0, 0x0c, 0x3b, 0xda, 0x59, 0x6b, 0x10, 0x88, 0x61, 0xf0,
+ 0x6b, 0xf9, 0x1b, 0x45, 0xd6 ) );
+
+/** SHA-1 Test 14 */
+HASH_DF_TEST ( test_sha1_14, sha1_algorithm,
+ INPUT ( 0x00, 0xe5, 0x04, 0x3d, 0x1b, 0x95, 0x4b, 0x34, 0xba, 0x60,
+ 0xd2, 0x48, 0xe8, 0x83, 0xef, 0x49, 0x8c, 0x5c, 0x52, 0x36,
+ 0xb8, 0x26, 0x0e, 0x23, 0x8e, 0x02, 0xc8, 0xd4, 0xfc, 0x5f,
+ 0xfe, 0x90, 0xfa, 0x40, 0x13, 0x44, 0x70, 0x75, 0xbb, 0x54,
+ 0x3e, 0xf0, 0x0c, 0x3b, 0xda, 0x59, 0x6b, 0x10, 0x88, 0x61,
+ 0xf0, 0x6b, 0xf9, 0x1b, 0x45, 0xd6 ),
+ EXPECT ( 0x1f, 0x3f, 0x63, 0x10, 0xed, 0x10, 0xfc, 0x9f, 0x93, 0x8c,
+ 0x43, 0x22, 0x61, 0xaf, 0x42, 0xe9, 0xe9, 0x17, 0x5f, 0x08,
+ 0x0f, 0x32, 0x22, 0xdc, 0x11, 0x8b, 0xa7, 0xcf, 0x88, 0x8c,
+ 0xdc, 0x3f, 0x36, 0x0d, 0xd2, 0x8f, 0x5e, 0xcb, 0x7c, 0x80,
+ 0xa6, 0xbc, 0xfc, 0xfc, 0x0f, 0x51, 0xfe, 0x2f, 0x77, 0xc1,
+ 0xc9, 0x9d, 0xf0, 0xa2, 0x09 ) );
+
+/** SHA-1 Test 15 */
+HASH_DF_TEST ( test_sha1_15, sha1_algorithm,
+ INPUT ( 0x01, 0x04, 0x43, 0xa0, 0x2c, 0x82, 0x5c, 0x31, 0x59, 0xf4,
+ 0x5e, 0x8c, 0x0a, 0xe5, 0x9e, 0x8c, 0x76, 0x45, 0x69, 0x95,
+ 0xc0, 0x35, 0x40, 0x46, 0x6a, 0x14, 0x54, 0x7c, 0xcb, 0xe8,
+ 0x8b, 0x6d, 0x39, 0x76, 0x21, 0x17, 0x32, 0x84, 0x72, 0xf5,
+ 0x2b, 0x84, 0x57, 0x5a, 0xaf, 0xe8, 0x8b, 0x2d, 0x1e, 0x50,
+ 0x4f, 0x21, 0xec, 0x4e, 0x31, 0x35, 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd,
+ 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
+ 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
+ 0xf6 ),
+ EXPECT ( 0x9d, 0xc3, 0x52, 0x08, 0xee, 0x2b, 0x8c, 0x58, 0x1e, 0xa3,
+ 0x0b, 0xaa, 0xcb, 0x5d, 0x74, 0x31, 0x7a, 0x87, 0x94, 0x54,
+ 0x10, 0x71, 0x7e, 0x58, 0xd3, 0x70, 0x5f, 0xbd, 0xc7, 0x60,
+ 0xbe, 0x0c, 0xc9, 0x0e, 0xd1, 0xcc, 0xbb, 0x89, 0x7d, 0x47,
+ 0xd2, 0x7e, 0x2b, 0x2e, 0x42, 0x2b, 0x32, 0xb9, 0x7f, 0x05,
+ 0x0d, 0x1b, 0xd2, 0xb4, 0x90 ) );
+
+/** SHA-1 Test 16 */
+HASH_DF_TEST ( test_sha1_16, sha1_algorithm,
+ INPUT ( 0x00, 0x9d, 0xc3, 0x52, 0x08, 0xee, 0x2b, 0x8c, 0x58, 0x1e,
+ 0xa3, 0x0b, 0xaa, 0xcb, 0x5d, 0x74, 0x31, 0x7a, 0x87, 0x94,
+ 0x54, 0x10, 0x71, 0x7e, 0x58, 0xd3, 0x70, 0x5f, 0xbd, 0xc7,
+ 0x60, 0xbe, 0x0c, 0xc9, 0x0e, 0xd1, 0xcc, 0xbb, 0x89, 0x7d,
+ 0x47, 0xd2, 0x7e, 0x2b, 0x2e, 0x42, 0x2b, 0x32, 0xb9, 0x7f,
+ 0x05, 0x0d, 0x1b, 0xd2, 0xb4, 0x90 ),
+ EXPECT ( 0x1a, 0x5a, 0xd6, 0xce, 0xa3, 0xd1, 0x5d, 0xa5, 0xfb, 0x47,
+ 0x42, 0x13, 0x13, 0x09, 0xf0, 0xed, 0x88, 0xcf, 0x4c, 0x90,
+ 0xa6, 0xc1, 0xcc, 0xee, 0x35, 0xa8, 0x76, 0xeb, 0xfc, 0xcc,
+ 0x82, 0x67, 0x29, 0xb6, 0x63, 0x9f, 0x81, 0x19, 0x65, 0xb0,
+ 0xef, 0x85, 0x76, 0xe7, 0x5c, 0xb3, 0xcf, 0xe8, 0x22, 0x07,
+ 0x68, 0xb2, 0x6c, 0xe7, 0x7a ) );
+
+/** SHA-1 Test 17 */
+HASH_DF_TEST ( test_sha1_17, sha1_algorithm,
+ INPUT ( 0x01, 0x99, 0xb9, 0x53, 0x7b, 0x84, 0x27, 0xb8, 0xce, 0x23,
+ 0x21, 0x9a, 0x61, 0x1c, 0xbe, 0x61, 0x06, 0x44, 0xcf, 0x85,
+ 0x03, 0xee, 0xc5, 0xba, 0x22, 0xde, 0x1a, 0xb2, 0x12, 0xc3,
+ 0xd0, 0x85, 0x8e, 0x9e, 0x3b, 0x90, 0x26, 0xd4, 0xe7, 0x7d,
+ 0x58, 0xe0, 0x2e, 0x85, 0xa2, 0x31, 0x4c, 0xe3, 0xd7, 0x4a,
+ 0x93, 0x32, 0x4b, 0x27, 0xbd, 0xe8, 0x80, 0x81, 0x82, 0x83,
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
+ 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1,
+ 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
+ 0xb6, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72,
+ 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c,
+ 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
+ 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
+ 0x91, 0x92, 0x93, 0x94, 0x95, 0x96 ),
+ EXPECT ( 0x56, 0x3a, 0x5d, 0x20, 0x7d, 0x37, 0x70, 0x7b, 0xf5, 0xf2,
+ 0x4d, 0x0b, 0xd4, 0x93, 0x5d, 0xc3, 0x8d, 0xbe, 0x04, 0x36,
+ 0x37, 0xb3, 0xff, 0x8a, 0xb6, 0x8c, 0xfc, 0xe2, 0xf2, 0x90,
+ 0xd1, 0x69, 0x95, 0x20, 0x55, 0x24, 0x19, 0x0f, 0xd2, 0x91,
+ 0xaa, 0x8a, 0x6e, 0x6b, 0x8e, 0x6d, 0x56, 0xa4, 0x31, 0x33,
+ 0x3b, 0x40, 0x8e, 0x6f, 0xa8 ) );
+
+/** SHA-1 Test 18 */
+HASH_DF_TEST ( test_sha1_18, sha1_algorithm,
+ INPUT ( 0x00, 0x56, 0x3a, 0x5d, 0x20, 0x7d, 0x37, 0x70, 0x7b, 0xf5,
+ 0xf2, 0x4d, 0x0b, 0xd4, 0x93, 0x5d, 0xc3, 0x8d, 0xbe, 0x04,
+ 0x36, 0x37, 0xb3, 0xff, 0x8a, 0xb6, 0x8c, 0xfc, 0xe2, 0xf2,
+ 0x90, 0xd1, 0x69, 0x95, 0x20, 0x55, 0x24, 0x19, 0x0f, 0xd2,
+ 0x91, 0xaa, 0x8a, 0x6e, 0x6b, 0x8e, 0x6d, 0x56, 0xa4, 0x31,
+ 0x33, 0x3b, 0x40, 0x8e, 0x6f, 0xa8 ),
+ EXPECT ( 0xc5, 0xd3, 0xe9, 0x55, 0x1e, 0x00, 0xe4, 0xee, 0x32, 0xb2,
+ 0x11, 0x6f, 0xaf, 0x4d, 0xef, 0xf4, 0xd4, 0xcf, 0xad, 0x2b,
+ 0xdc, 0x2d, 0xba, 0xa2, 0xe0, 0xe7, 0xf9, 0xdd, 0xb9, 0xd8,
+ 0x1e, 0xed, 0x45, 0xe0, 0xa5, 0x0d, 0xa5, 0xaf, 0xd5, 0xc1,
+ 0xf6, 0xbc, 0xda, 0xf8, 0x1d, 0x28, 0x9c, 0xf4, 0xbd, 0x3c,
+ 0x91, 0xb7, 0x00, 0x5c, 0x18 ) );
+
+/** SHA-1 Test 19 */
+HASH_DF_TEST ( test_sha1_19, sha1_algorithm,
+ INPUT ( 0x01, 0x1c, 0x0e, 0x46, 0x75, 0x9b, 0x38, 0x55, 0x6a, 0x28,
+ 0xa4, 0x5e, 0x7b, 0x83, 0xe1, 0x4d, 0xb8, 0x62, 0x8d, 0xb1,
+ 0x62, 0x13, 0xe1, 0xba, 0x2d, 0x97, 0x74, 0xf6, 0xc0, 0xac,
+ 0x68, 0xf0, 0x56, 0xdb, 0x00, 0xfb, 0x12, 0xe1, 0x5b, 0xf4,
+ 0xde, 0x95, 0x50, 0xb7, 0x33, 0x1e, 0x2d, 0xbd, 0x66, 0x4c,
+ 0x3a, 0xb7, 0x76, 0xe8, 0x25, 0x51, 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd,
+ 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
+ 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
+ 0xf6, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+ 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2,
+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc,
+ 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
+ 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+ 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6 ),
+ EXPECT ( 0x60, 0x01, 0x93, 0xc8, 0xf6, 0x03, 0x1a, 0x2d, 0x49, 0x37,
+ 0x2a, 0x8b, 0x0f, 0x60, 0xf6, 0x8c, 0x1d, 0xfd, 0xac, 0xd4,
+ 0xf8, 0xea, 0x01, 0x37, 0x47, 0xd7, 0x14, 0x82, 0x33, 0x3d,
+ 0xf5, 0x25, 0x2e, 0x95, 0xb8, 0x22, 0x57, 0x39, 0x1b, 0xf1,
+ 0x0a, 0xb0, 0x7d, 0x12, 0x08, 0xb6, 0xbd, 0x66, 0x5b, 0x30,
+ 0x0a, 0xa4, 0xdb, 0x9c, 0x3e ) );
+
+/** SHA-1 Test 20 */
+HASH_DF_TEST ( test_sha1_20, sha1_algorithm,
+ INPUT ( 0x00, 0x60, 0x01, 0x93, 0xc8, 0xf6, 0x03, 0x1a, 0x2d, 0x49,
+ 0x37, 0x2a, 0x8b, 0x0f, 0x60, 0xf6, 0x8c, 0x1d, 0xfd, 0xac,
+ 0xd4, 0xf8, 0xea, 0x01, 0x37, 0x47, 0xd7, 0x14, 0x82, 0x33,
+ 0x3d, 0xf5, 0x25, 0x2e, 0x95, 0xb8, 0x22, 0x57, 0x39, 0x1b,
+ 0xf1, 0x0a, 0xb0, 0x7d, 0x12, 0x08, 0xb6, 0xbd, 0x66, 0x5b,
+ 0x30, 0x0a, 0xa4, 0xdb, 0x9c, 0x3e ),
+ EXPECT ( 0x6b, 0x71, 0x82, 0x3b, 0x18, 0x20, 0x07, 0x71, 0xca, 0xae,
+ 0x5d, 0x12, 0x55, 0xc1, 0x40, 0x3e, 0xdf, 0xe3, 0x8b, 0x4d,
+ 0x18, 0xc7, 0x87, 0xbb, 0x44, 0xcd, 0x17, 0x18, 0x61, 0x52,
+ 0xef, 0xea, 0xd6, 0xfd, 0xc4, 0xb8, 0x94, 0xf9, 0x20, 0x02,
+ 0xc0, 0x72, 0x09, 0x55, 0x5d, 0x7e, 0x35, 0x54, 0xf9, 0xd1,
+ 0x2f, 0xc5, 0x59, 0x7f, 0x22 ) );
+
+/** SHA-256 Test 1 */
+HASH_DF_TEST ( test_sha256_1, sha256_algorithm,
+ INPUT ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+ 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+ 0x32, 0x33, 0x34, 0x35, 0x36, 0x20, 0x21, 0x22, 0x23, 0x24,
+ 0x25, 0x26, 0x27 ),
+ EXPECT ( 0xab, 0x41, 0xcd, 0xe4, 0x37, 0xab, 0x8b, 0x09, 0x1c, 0xa7,
+ 0xc5, 0x75, 0x5d, 0x10, 0xf0, 0x11, 0x0c, 0x1d, 0xbd, 0x46,
+ 0x2f, 0x22, 0x6c, 0xfd, 0xab, 0xfb, 0xb0, 0x4a, 0x8b, 0xcd,
+ 0xef, 0x95, 0x16, 0x7d, 0x84, 0xaf, 0x64, 0x12, 0x8c, 0x0d,
+ 0x71, 0xf4, 0xd5, 0xb8, 0xc0, 0xed, 0xfb, 0xbe, 0x3d, 0xf4,
+ 0x04, 0x48, 0xd2, 0xd8, 0xe1 ) );
+
+/** SHA-256 Test 2 */
+HASH_DF_TEST ( test_sha256_2, sha256_algorithm,
+ INPUT ( 0x00, 0xab, 0x41, 0xcd, 0xe4, 0x37, 0xab, 0x8b, 0x09, 0x1c,
+ 0xa7, 0xc5, 0x75, 0x5d, 0x10, 0xf0, 0x11, 0x0c, 0x1d, 0xbd,
+ 0x46, 0x2f, 0x22, 0x6c, 0xfd, 0xab, 0xfb, 0xb0, 0x4a, 0x8b,
+ 0xcd, 0xef, 0x95, 0x16, 0x7d, 0x84, 0xaf, 0x64, 0x12, 0x8c,
+ 0x0d, 0x71, 0xf4, 0xd5, 0xb8, 0xc0, 0xed, 0xfb, 0xbe, 0x3d,
+ 0xf4, 0x04, 0x48, 0xd2, 0xd8, 0xe1 ),
+ EXPECT ( 0xe1, 0x5d, 0xe4, 0xa8, 0xe3, 0xb1, 0x41, 0x9b, 0x61, 0xd5,
+ 0x34, 0xf1, 0x5d, 0xbd, 0x31, 0xee, 0x19, 0xec, 0x59, 0x5f,
+ 0x8b, 0x98, 0x11, 0x1a, 0x94, 0xf5, 0x22, 0x37, 0xad, 0x5d,
+ 0x66, 0xf0, 0xcf, 0xaa, 0xfd, 0xdc, 0x90, 0x19, 0x59, 0x02,
+ 0xe9, 0x79, 0xf7, 0x9b, 0x65, 0x35, 0x7f, 0xea, 0x85, 0x99,
+ 0x8e, 0x4e, 0x37, 0xd2, 0xc1 ) );
+
+/** SHA-256 Test 3 */
+HASH_DF_TEST ( test_sha256_3, sha256_algorithm,
+ INPUT ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+ 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+ 0x32, 0x33, 0x34, 0x35, 0x36, 0x20, 0x21, 0x22, 0x23, 0x24,
+ 0x25, 0x26, 0x27, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
+ 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
+ 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64,
+ 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
+ 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76 ),
+ EXPECT ( 0xa3, 0xe9, 0x4e, 0x39, 0x26, 0xfd, 0xa1, 0x69, 0xc3, 0x03,
+ 0xd6, 0x64, 0x38, 0x39, 0x05, 0xe0, 0xd7, 0x99, 0x62, 0xd1,
+ 0x65, 0x44, 0x6d, 0x63, 0xbd, 0xa6, 0x54, 0xd1, 0x32, 0xf7,
+ 0x2d, 0xb4, 0x71, 0x56, 0x4b, 0x45, 0x6f, 0xf2, 0xee, 0xc8,
+ 0x36, 0x42, 0x2a, 0xcc, 0x5a, 0x02, 0x99, 0x35, 0xa7, 0x99,
+ 0x29, 0x90, 0x94, 0xa1, 0xca ) );
+
+/** SHA-256 Test 4 */
+HASH_DF_TEST ( test_sha256_4, sha256_algorithm,
+ INPUT ( 0x00, 0xa3, 0xe9, 0x4e, 0x39, 0x26, 0xfd, 0xa1, 0x69, 0xc3,
+ 0x03, 0xd6, 0x64, 0x38, 0x39, 0x05, 0xe0, 0xd7, 0x99, 0x62,
+ 0xd1, 0x65, 0x44, 0x6d, 0x63, 0xbd, 0xa6, 0x54, 0xd1, 0x32,
+ 0xf7, 0x2d, 0xb4, 0x71, 0x56, 0x4b, 0x45, 0x6f, 0xf2, 0xee,
+ 0xc8, 0x36, 0x42, 0x2a, 0xcc, 0x5a, 0x02, 0x99, 0x35, 0xa7,
+ 0x99, 0x29, 0x90, 0x94, 0xa1, 0xca ),
+ EXPECT ( 0x44, 0x74, 0x8a, 0x78, 0xb1, 0x6e, 0x75, 0x55, 0x9f, 0x88,
+ 0x1d, 0x51, 0xc1, 0x5d, 0xfe, 0x6c, 0x52, 0xcf, 0xb0, 0xbb,
+ 0x71, 0x62, 0x01, 0x69, 0xc7, 0x93, 0x34, 0x27, 0x67, 0xe7,
+ 0xf8, 0x87, 0x5f, 0x42, 0xcb, 0x6a, 0x20, 0xc8, 0x9d, 0x7c,
+ 0x6e, 0xf3, 0xdc, 0x61, 0x0d, 0x8f, 0xf2, 0x03, 0xd6, 0x76,
+ 0x6c, 0xed, 0x19, 0x19, 0xd0 ) );
+
+/** SHA-256 Test 5 */
+HASH_DF_TEST ( test_sha256_5, sha256_algorithm,
+ INPUT ( 0x01, 0xab, 0x41, 0xcd, 0xe4, 0x37, 0xab, 0x8b, 0x09, 0x1c,
+ 0xa7, 0xc5, 0x75, 0x5d, 0x10, 0xf0, 0x11, 0x0c, 0x1d, 0xbd,
+ 0x46, 0x2f, 0x22, 0x6c, 0xfd, 0xab, 0xfb, 0xb0, 0x4a, 0x8b,
+ 0xcd, 0xef, 0x95, 0x16, 0x7d, 0x84, 0xaf, 0x64, 0x12, 0x8c,
+ 0x0d, 0x71, 0xf4, 0xd5, 0xb8, 0xc0, 0xed, 0xfb, 0xbe, 0x3d,
+ 0xf4, 0x04, 0x48, 0xd2, 0xd8, 0xe1, 0x80, 0x81, 0x82, 0x83,
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
+ 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1,
+ 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
+ 0xb6 ),
+ EXPECT ( 0x3c, 0x40, 0xe8, 0xdc, 0x71, 0x72, 0xfd, 0xa2, 0x32, 0x55,
+ 0x0a, 0x1d, 0x8e, 0x14, 0x47, 0xc1, 0x1f, 0x47, 0x48, 0x88,
+ 0xf9, 0x6c, 0xd8, 0x5c, 0x38, 0x63, 0xd5, 0xe4, 0x84, 0x26,
+ 0x67, 0x56, 0x28, 0xd0, 0x88, 0x85, 0x34, 0x7c, 0x3e, 0xfd,
+ 0x62, 0x92, 0xfd, 0xdc, 0xd1, 0xa1, 0x42, 0x1e, 0xed, 0x51,
+ 0xb7, 0x13, 0xab, 0x09, 0x0f ) );
+
+/** SHA-256 Test 6 */
+HASH_DF_TEST ( test_sha256_6, sha256_algorithm,
+ INPUT ( 0x00, 0x3c, 0x40, 0xe8, 0xdc, 0x71, 0x72, 0xfd, 0xa2, 0x32,
+ 0x55, 0x0a, 0x1d, 0x8e, 0x14, 0x47, 0xc1, 0x1f, 0x47, 0x48,
+ 0x88, 0xf9, 0x6c, 0xd8, 0x5c, 0x38, 0x63, 0xd5, 0xe4, 0x84,
+ 0x26, 0x67, 0x56, 0x28, 0xd0, 0x88, 0x85, 0x34, 0x7c, 0x3e,
+ 0xfd, 0x62, 0x92, 0xfd, 0xdc, 0xd1, 0xa1, 0x42, 0x1e, 0xed,
+ 0x51, 0xb7, 0x13, 0xab, 0x09, 0x0f ),
+ EXPECT ( 0xe7, 0x56, 0x83, 0x84, 0xf2, 0x64, 0xe4, 0xa7, 0xe7, 0xae,
+ 0x85, 0x0d, 0x9d, 0x50, 0x1f, 0xd6, 0x31, 0x83, 0x56, 0x4f,
+ 0xd7, 0xd3, 0x90, 0x44, 0x6f, 0x5b, 0xe5, 0xf6, 0x7b, 0x50,
+ 0x19, 0x5b, 0x52, 0x84, 0x69, 0x2a, 0xd4, 0xb7, 0x6d, 0xfd,
+ 0x4f, 0x52, 0x4b, 0xcf, 0xcc, 0xab, 0x62, 0xc1, 0x30, 0x9f,
+ 0x25, 0x15, 0x17, 0xdf, 0xfd ) );
+
+/** SHA-256 Test 7 */
+HASH_DF_TEST ( test_sha256_7, sha256_algorithm,
+ INPUT ( 0x01, 0x23, 0x97, 0x6c, 0x61, 0x63, 0xd7, 0xe2, 0x4a, 0x1a,
+ 0x03, 0x8f, 0x2b, 0x2b, 0x64, 0x67, 0x97, 0x50, 0xca, 0x9e,
+ 0xd8, 0xd1, 0x40, 0x69, 0x8d, 0x64, 0x22, 0x39, 0x7b, 0x02,
+ 0x96, 0x9e, 0x6e, 0xcd, 0xd2, 0x9d, 0xac, 0xc5, 0x76, 0x7e,
+ 0x2c, 0xc2, 0xd0, 0xa1, 0x56, 0xc8, 0x7a, 0xd0, 0xb3, 0x57,
+ 0x89, 0x05, 0x07, 0xe0, 0x37, 0x77, 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd,
+ 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
+ 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
+ 0xf6 ),
+ EXPECT ( 0xe9, 0x83, 0xb1, 0x66, 0xa9, 0x2a, 0x99, 0x7e, 0xab, 0xcc,
+ 0x96, 0x6c, 0x6a, 0xa3, 0xd3, 0xb3, 0xa1, 0x68, 0x1f, 0xc5,
+ 0x8f, 0x58, 0x29, 0x40, 0x3b, 0x48, 0x60, 0x1e, 0xc1, 0x77,
+ 0x54, 0x94, 0x2e, 0x11, 0xc1, 0xcd, 0x46, 0x5b, 0x7d, 0xbe,
+ 0x2a, 0x78, 0xca, 0x04, 0x2c, 0xf9, 0xb3, 0x05, 0x71, 0xff,
+ 0x12, 0xe3, 0xb9, 0xf6, 0xc9 ) );
+
+/** SHA-256 Test 8 */
+HASH_DF_TEST ( test_sha256_8, sha256_algorithm,
+ INPUT ( 0x00, 0xe9, 0x83, 0xb1, 0x66, 0xa9, 0x2a, 0x99, 0x7e, 0xab,
+ 0xcc, 0x96, 0x6c, 0x6a, 0xa3, 0xd3, 0xb3, 0xa1, 0x68, 0x1f,
+ 0xc5, 0x8f, 0x58, 0x29, 0x40, 0x3b, 0x48, 0x60, 0x1e, 0xc1,
+ 0x77, 0x54, 0x94, 0x2e, 0x11, 0xc1, 0xcd, 0x46, 0x5b, 0x7d,
+ 0xbe, 0x2a, 0x78, 0xca, 0x04, 0x2c, 0xf9, 0xb3, 0x05, 0x71,
+ 0xff, 0x12, 0xe3, 0xb9, 0xf6, 0xc9 ),
+ EXPECT ( 0xa9, 0x77, 0x5c, 0xe1, 0x65, 0x5b, 0xff, 0x95, 0x1b, 0xe0,
+ 0xaf, 0x5b, 0x79, 0x59, 0x72, 0x5c, 0x76, 0x7d, 0x86, 0xf1,
+ 0xe1, 0x9b, 0x11, 0xb8, 0x90, 0x04, 0xf6, 0x97, 0x4d, 0xbf,
+ 0xa0, 0x46, 0x04, 0x45, 0x8e, 0x5c, 0x52, 0x8e, 0x7e, 0x1d,
+ 0xfa, 0xb3, 0x88, 0x7b, 0xa4, 0xaa, 0xdb, 0xd6, 0xfb, 0xde,
+ 0x0b, 0x31, 0x6f, 0x1d, 0x91 ) );
+
+/** SHA-256 Test 9 */
+HASH_DF_TEST ( test_sha256_9, sha256_algorithm,
+ INPUT ( 0x01, 0xab, 0x41, 0xcd, 0xe4, 0x37, 0xab, 0x8b, 0x09, 0x1c,
+ 0xa7, 0xc5, 0x75, 0x5d, 0x10, 0xf0, 0x11, 0x0c, 0x1d, 0xbd,
+ 0x46, 0x2f, 0x22, 0x6c, 0xfd, 0xab, 0xfb, 0xb0, 0x4a, 0x8b,
+ 0xcd, 0xef, 0x95, 0x16, 0x7d, 0x84, 0xaf, 0x64, 0x12, 0x8c,
+ 0x0d, 0x71, 0xf4, 0xd5, 0xb8, 0xc0, 0xed, 0xfb, 0xbe, 0x3d,
+ 0xf4, 0x04, 0x48, 0xd2, 0xd8, 0xe1, 0x80, 0x81, 0x82, 0x83,
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
+ 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1,
+ 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
+ 0xb6, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72,
+ 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c,
+ 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
+ 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
+ 0x91, 0x92, 0x93, 0x94, 0x95, 0x96 ),
+ EXPECT ( 0x57, 0xb2, 0xcf, 0x00, 0xb5, 0x42, 0x97, 0x46, 0x0b, 0x08,
+ 0x7e, 0x52, 0x75, 0xd7, 0xdd, 0x74, 0x23, 0xb6, 0xe3, 0xb6,
+ 0x5e, 0x35, 0x16, 0xd2, 0x48, 0x11, 0x99, 0xa0, 0x17, 0xb5,
+ 0x3a, 0x22, 0x20, 0x33, 0xfe, 0x68, 0xa6, 0x0b, 0xd0, 0xbd,
+ 0x70, 0x40, 0x26, 0xcd, 0x5a, 0x3e, 0x79, 0x55, 0xdb, 0x01,
+ 0xdc, 0xb2, 0x84, 0x48, 0xd1 ) );
+
+/** SHA-256 Test 10 */
+HASH_DF_TEST ( test_sha256_10, sha256_algorithm,
+ INPUT ( 0x00, 0x57, 0xb2, 0xcf, 0x00, 0xb5, 0x42, 0x97, 0x46, 0x0b,
+ 0x08, 0x7e, 0x52, 0x75, 0xd7, 0xdd, 0x74, 0x23, 0xb6, 0xe3,
+ 0xb6, 0x5e, 0x35, 0x16, 0xd2, 0x48, 0x11, 0x99, 0xa0, 0x17,
+ 0xb5, 0x3a, 0x22, 0x20, 0x33, 0xfe, 0x68, 0xa6, 0x0b, 0xd0,
+ 0xbd, 0x70, 0x40, 0x26, 0xcd, 0x5a, 0x3e, 0x79, 0x55, 0xdb,
+ 0x01, 0xdc, 0xb2, 0x84, 0x48, 0xd1 ),
+ EXPECT ( 0x5b, 0xc1, 0xc6, 0x45, 0xcc, 0x8d, 0x32, 0x15, 0x82, 0xaf,
+ 0xbb, 0x00, 0x16, 0x99, 0x2b, 0x0f, 0x3a, 0xfe, 0x0f, 0x54,
+ 0x7a, 0xe7, 0xa7, 0x4c, 0x9c, 0x05, 0xa1, 0x44, 0x02, 0xfb,
+ 0xb1, 0xd5, 0x40, 0xe6, 0x80, 0x9d, 0x8b, 0xee, 0xf5, 0x99,
+ 0xed, 0x4c, 0x39, 0x16, 0x47, 0x40, 0xed, 0xa0, 0xd9, 0xc3,
+ 0x79, 0x5d, 0xe5, 0x52, 0xc5 ) );
+
+/** SHA-256 Test 11 */
+HASH_DF_TEST ( test_sha256_11, sha256_algorithm,
+ INPUT ( 0x01, 0xb3, 0x74, 0x95, 0x46, 0x81, 0xcf, 0xc9, 0x5b, 0x8d,
+ 0xb8, 0x39, 0x52, 0x8c, 0x71, 0x08, 0x83, 0x5e, 0xb4, 0xf3,
+ 0x0a, 0xd9, 0x1c, 0xbe, 0x9e, 0xa0, 0xd5, 0x45, 0xcc, 0xfd,
+ 0x18, 0x13, 0x2a, 0xf1, 0xd3, 0x76, 0x8f, 0x47, 0x02, 0x77,
+ 0x2b, 0x69, 0x15, 0x9f, 0x2c, 0xc0, 0x7f, 0x48, 0x74, 0x1e,
+ 0xb5, 0xb2, 0xb1, 0x22, 0x11, 0x25, 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd,
+ 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
+ 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
+ 0xf6, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+ 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2,
+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc,
+ 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
+ 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+ 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6 ),
+ EXPECT ( 0x5d, 0xc1, 0xc5, 0xf4, 0xb4, 0x11, 0x50, 0xce, 0xe0, 0xef,
+ 0xc1, 0x29, 0xb8, 0x37, 0xb3, 0x1c, 0x84, 0xd7, 0x91, 0xff,
+ 0x2e, 0x7e, 0xda, 0xc2, 0x9c, 0x2c, 0x50, 0xcf, 0x8a, 0x40,
+ 0x70, 0x9b, 0x98, 0x64, 0x0f, 0x7b, 0xbd, 0x32, 0xbc, 0xf0,
+ 0xfc, 0xb6, 0x13, 0xf9, 0x6d, 0x55, 0xd1, 0x60, 0x56, 0xbb,
+ 0x3c, 0xa6, 0xa7, 0x74, 0x05 ) );
+
+/** SHA-256 Test 12 */
+HASH_DF_TEST ( test_sha256_12, sha256_algorithm,
+ INPUT ( 0x00, 0x5d, 0xc1, 0xc5, 0xf4, 0xb4, 0x11, 0x50, 0xce, 0xe0,
+ 0xef, 0xc1, 0x29, 0xb8, 0x37, 0xb3, 0x1c, 0x84, 0xd7, 0x91,
+ 0xff, 0x2e, 0x7e, 0xda, 0xc2, 0x9c, 0x2c, 0x50, 0xcf, 0x8a,
+ 0x40, 0x70, 0x9b, 0x98, 0x64, 0x0f, 0x7b, 0xbd, 0x32, 0xbc,
+ 0xf0, 0xfc, 0xb6, 0x13, 0xf9, 0x6d, 0x55, 0xd1, 0x60, 0x56,
+ 0xbb, 0x3c, 0xa6, 0xa7, 0x74, 0x05 ),
+ EXPECT ( 0x62, 0x22, 0x10, 0x8c, 0xed, 0xfe, 0x6d, 0x6a, 0x22, 0x9f,
+ 0x8c, 0x3c, 0xbf, 0x44, 0x68, 0xc8, 0xf5, 0x17, 0x22, 0x86,
+ 0x4c, 0xc4, 0x16, 0xa4, 0x29, 0x26, 0xd9, 0x9b, 0xa6, 0xf0,
+ 0x45, 0xc1, 0xf6, 0x21, 0x11, 0x56, 0x94, 0x6c, 0x6e, 0x79,
+ 0x37, 0x29, 0x97, 0x4e, 0xb4, 0xc5, 0xa6, 0x07, 0x8f, 0x9a,
+ 0x1d, 0x4d, 0x1c, 0xd7, 0x49 ) );
+
+/** SHA-256 Test 13 */
+HASH_DF_TEST ( test_sha256_13, sha256_algorithm,
+ INPUT ( 0x01, 0xa3, 0xe9, 0x4e, 0x39, 0x26, 0xfd, 0xa1, 0x69, 0xc3,
+ 0x03, 0xd6, 0x64, 0x38, 0x39, 0x05, 0xe0, 0xd7, 0x99, 0x62,
+ 0xd1, 0x65, 0x44, 0x6d, 0x63, 0xbd, 0xa6, 0x54, 0xd1, 0x32,
+ 0xf7, 0x2d, 0xb4, 0x71, 0x56, 0x4b, 0x45, 0x6f, 0xf2, 0xee,
+ 0xc8, 0x36, 0x42, 0x2a, 0xcc, 0x5a, 0x02, 0x99, 0x35, 0xa7,
+ 0x99, 0x29, 0x90, 0x94, 0xa1, 0xca, 0x80, 0x81, 0x82, 0x83,
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
+ 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1,
+ 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
+ 0xb6 ),
+ EXPECT ( 0xe0, 0x26, 0xa5, 0xc2, 0xe7, 0x62, 0x3e, 0x62, 0xb7, 0x1a,
+ 0x2e, 0x04, 0xc2, 0x5f, 0x0b, 0x08, 0x58, 0x2b, 0xe2, 0x16,
+ 0x36, 0x34, 0xc0, 0x49, 0x6d, 0x2b, 0x65, 0xda, 0x7e, 0xaa,
+ 0x03, 0xb5, 0xc3, 0xb6, 0xb5, 0x10, 0xbb, 0x3f, 0xe4, 0x74,
+ 0x34, 0x07, 0x1f, 0x70, 0x7a, 0xc7, 0xfe, 0x4c, 0x39, 0x6a,
+ 0xaa, 0xee, 0x76, 0x4c, 0x90 ) );
+
+/** SHA-256 Test 14 */
+HASH_DF_TEST ( test_sha256_14, sha256_algorithm,
+ INPUT ( 0x00, 0xe0, 0x26, 0xa5, 0xc2, 0xe7, 0x62, 0x3e, 0x62, 0xb7,
+ 0x1a, 0x2e, 0x04, 0xc2, 0x5f, 0x0b, 0x08, 0x58, 0x2b, 0xe2,
+ 0x16, 0x36, 0x34, 0xc0, 0x49, 0x6d, 0x2b, 0x65, 0xda, 0x7e,
+ 0xaa, 0x03, 0xb5, 0xc3, 0xb6, 0xb5, 0x10, 0xbb, 0x3f, 0xe4,
+ 0x74, 0x34, 0x07, 0x1f, 0x70, 0x7a, 0xc7, 0xfe, 0x4c, 0x39,
+ 0x6a, 0xaa, 0xee, 0x76, 0x4c, 0x90 ),
+ EXPECT ( 0xc9, 0xea, 0x75, 0x4b, 0xee, 0x0a, 0xb6, 0x44, 0x15, 0xca,
+ 0x7f, 0xe3, 0x2e, 0xbb, 0xfb, 0x07, 0xed, 0x93, 0x2e, 0x7c,
+ 0x95, 0x7e, 0xce, 0xae, 0xf0, 0xcd, 0x2f, 0xa7, 0x7a, 0x46,
+ 0xf9, 0xe8, 0x59, 0x62, 0x78, 0x97, 0x54, 0xc6, 0xd2, 0x98,
+ 0xf9, 0xb5, 0xe4, 0x59, 0x6b, 0x4e, 0x0e, 0x6d, 0xf4, 0xf4,
+ 0xb8, 0x23, 0x60, 0xda, 0x33 ) );
+
+/** SHA-256 Test 15 */
+HASH_DF_TEST ( test_sha256_15, sha256_algorithm,
+ INPUT ( 0x01, 0xaa, 0x11, 0x1b, 0x0e, 0xd5, 0x6c, 0xf4, 0xa6, 0xcc,
+ 0xe4, 0xad, 0xe7, 0xf1, 0x1b, 0x06, 0x10, 0x45, 0xbf, 0x10,
+ 0x92, 0xcb, 0xb3, 0x8f, 0xf3, 0x23, 0x95, 0xea, 0x62, 0xd2,
+ 0x6b, 0x27, 0xc8, 0x86, 0x89, 0x45, 0xc5, 0x93, 0xba, 0x70,
+ 0xc3, 0x84, 0xad, 0xad, 0x45, 0x77, 0x1c, 0x93, 0xb0, 0x9c,
+ 0x27, 0x69, 0x07, 0x52, 0xd1, 0xd8, 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd,
+ 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
+ 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
+ 0xf6 ),
+ EXPECT ( 0xfc, 0x5f, 0x56, 0x48, 0xed, 0xc4, 0xfc, 0x30, 0x7b, 0x5c,
+ 0x5a, 0x53, 0xd5, 0x12, 0x89, 0xb5, 0x0e, 0x73, 0xdc, 0xec,
+ 0x4a, 0xa1, 0xcb, 0x47, 0xa3, 0xba, 0xd8, 0x46, 0xbb, 0x57,
+ 0xc3, 0xc4, 0x80, 0x49, 0x1d, 0xf5, 0x21, 0xc4, 0x66, 0x9b,
+ 0xff, 0xf3, 0x7a, 0x41, 0x8b, 0xaf, 0x6e, 0x9b, 0xea, 0xec,
+ 0x34, 0x96, 0xd0, 0xf1, 0xa6 ) );
+
+/** SHA-256 Test 16 */
+HASH_DF_TEST ( test_sha256_16, sha256_algorithm,
+ INPUT ( 0x00, 0xfc, 0x5f, 0x56, 0x48, 0xed, 0xc4, 0xfc, 0x30, 0x7b,
+ 0x5c, 0x5a, 0x53, 0xd5, 0x12, 0x89, 0xb5, 0x0e, 0x73, 0xdc,
+ 0xec, 0x4a, 0xa1, 0xcb, 0x47, 0xa3, 0xba, 0xd8, 0x46, 0xbb,
+ 0x57, 0xc3, 0xc4, 0x80, 0x49, 0x1d, 0xf5, 0x21, 0xc4, 0x66,
+ 0x9b, 0xff, 0xf3, 0x7a, 0x41, 0x8b, 0xaf, 0x6e, 0x9b, 0xea,
+ 0xec, 0x34, 0x96, 0xd0, 0xf1, 0xa6 ),
+ EXPECT ( 0x62, 0xb0, 0x7d, 0xc3, 0x9e, 0xbd, 0xf3, 0x10, 0x87, 0xb8,
+ 0x5d, 0xdc, 0xec, 0xfd, 0x43, 0x35, 0x62, 0xe5, 0x3b, 0xae,
+ 0x9f, 0x72, 0x1c, 0x5a, 0xfa, 0xb8, 0xf1, 0xcf, 0x01, 0x61,
+ 0xc8, 0x8e, 0x45, 0x50, 0x3e, 0x15, 0xb2, 0x6e, 0x7b, 0x80,
+ 0xd5, 0x1d, 0xb0, 0xb9, 0x24, 0x52, 0x36, 0x2d, 0xc3, 0xdc,
+ 0x57, 0x0d, 0xfe, 0x6e, 0x17 ) );
+
+/** SHA-256 Test 17 */
+HASH_DF_TEST ( test_sha256_17, sha256_algorithm,
+ INPUT ( 0x01, 0xa3, 0xe9, 0x4e, 0x39, 0x26, 0xfd, 0xa1, 0x69, 0xc3,
+ 0x03, 0xd6, 0x64, 0x38, 0x39, 0x05, 0xe0, 0xd7, 0x99, 0x62,
+ 0xd1, 0x65, 0x44, 0x6d, 0x63, 0xbd, 0xa6, 0x54, 0xd1, 0x32,
+ 0xf7, 0x2d, 0xb4, 0x71, 0x56, 0x4b, 0x45, 0x6f, 0xf2, 0xee,
+ 0xc8, 0x36, 0x42, 0x2a, 0xcc, 0x5a, 0x02, 0x99, 0x35, 0xa7,
+ 0x99, 0x29, 0x90, 0x94, 0xa1, 0xca, 0x80, 0x81, 0x82, 0x83,
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
+ 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1,
+ 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
+ 0xb6, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72,
+ 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c,
+ 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
+ 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
+ 0x91, 0x92, 0x93, 0x94, 0x95, 0x96 ),
+ EXPECT ( 0x98, 0x75, 0xbb, 0x7c, 0x7a, 0x0b, 0x23, 0x6b, 0xf4, 0x6f,
+ 0x4e, 0xa6, 0x6f, 0x67, 0xc7, 0xb4, 0x4f, 0x80, 0xef, 0x70,
+ 0x61, 0x4b, 0xef, 0xe8, 0xb0, 0x85, 0xcc, 0xaf, 0x55, 0x89,
+ 0xa7, 0x6f, 0x85, 0xfd, 0x96, 0x69, 0x53, 0xe2, 0x0a, 0x55,
+ 0xd2, 0xf3, 0x5b, 0xa5, 0x81, 0xef, 0x51, 0x11, 0xbf, 0xbf,
+ 0x05, 0x65, 0x3a, 0xf7, 0xe7 ) );
+
+/** SHA-256 Test 18 */
+HASH_DF_TEST ( test_sha256_18, sha256_algorithm,
+ INPUT ( 0x00, 0x98, 0x75, 0xbb, 0x7c, 0x7a, 0x0b, 0x23, 0x6b, 0xf4,
+ 0x6f, 0x4e, 0xa6, 0x6f, 0x67, 0xc7, 0xb4, 0x4f, 0x80, 0xef,
+ 0x70, 0x61, 0x4b, 0xef, 0xe8, 0xb0, 0x85, 0xcc, 0xaf, 0x55,
+ 0x89, 0xa7, 0x6f, 0x85, 0xfd, 0x96, 0x69, 0x53, 0xe2, 0x0a,
+ 0x55, 0xd2, 0xf3, 0x5b, 0xa5, 0x81, 0xef, 0x51, 0x11, 0xbf,
+ 0xbf, 0x05, 0x65, 0x3a, 0xf7, 0xe7 ),
+ EXPECT ( 0x12, 0x80, 0xfe, 0x1f, 0x05, 0x79, 0x8c, 0xca, 0xed, 0x5d,
+ 0x6d, 0xf6, 0xe7, 0xd2, 0x6f, 0x04, 0x6e, 0x53, 0x8c, 0xc5,
+ 0x2a, 0x6a, 0x03, 0x0d, 0xa8, 0x26, 0xb2, 0xb4, 0x79, 0x82,
+ 0xd6, 0xee, 0x8a, 0x68, 0x67, 0x58, 0x07, 0x06, 0x93, 0x9e,
+ 0xcc, 0x03, 0xfc, 0x11, 0xb0, 0x05, 0x9f, 0xe2, 0xae, 0xad,
+ 0xea, 0x0a, 0x46, 0x98, 0x5c ) );
+
+/** SHA-256 Test 19 */
+HASH_DF_TEST ( test_sha256_19, sha256_algorithm,
+ INPUT ( 0x01, 0xaa, 0xf6, 0xb9, 0x9b, 0x7f, 0x84, 0xb0, 0x36, 0xe1,
+ 0xcc, 0xbc, 0x9d, 0x57, 0x3a, 0x36, 0xb8, 0xbd, 0xd4, 0x7c,
+ 0x35, 0x8b, 0xb5, 0xf3, 0xc1, 0xd6, 0xe7, 0x90, 0x3a, 0xaa,
+ 0x29, 0xf1, 0xc8, 0x7a, 0xe6, 0x66, 0xb8, 0x86, 0x93, 0xbe,
+ 0xf4, 0x6c, 0x51, 0xc2, 0x4c, 0x47, 0xbe, 0xfe, 0x4b, 0x35,
+ 0x75, 0x4d, 0xcb, 0xfa, 0x1e, 0x7d, 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd,
+ 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
+ 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
+ 0xf6, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+ 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2,
+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc,
+ 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
+ 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+ 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6 ),
+ EXPECT ( 0xb0, 0x6d, 0xbf, 0xb1, 0x4e, 0x7f, 0x4e, 0x01, 0x25, 0x62,
+ 0x94, 0x2f, 0xe4, 0xf2, 0xa9, 0x60, 0x17, 0x07, 0x55, 0x9d,
+ 0x7d, 0xd1, 0x90, 0x89, 0x8b, 0xc8, 0x06, 0x24, 0xe5, 0xc8,
+ 0xc1, 0xbb, 0x9b, 0x90, 0xfb, 0x2e, 0xef, 0x12, 0xed, 0x24,
+ 0xbe, 0xbd, 0x8d, 0xf7, 0x1e, 0xf6, 0x5c, 0x70, 0xfa, 0x4e,
+ 0x91, 0x86, 0x3a, 0x31, 0xbe ) );
+
+/** SHA-256 Test 20 */
+HASH_DF_TEST ( test_sha256_20, sha256_algorithm,
+ INPUT ( 0x00, 0xb0, 0x6d, 0xbf, 0xb1, 0x4e, 0x7f, 0x4e, 0x01, 0x25,
+ 0x62, 0x94, 0x2f, 0xe4, 0xf2, 0xa9, 0x60, 0x17, 0x07, 0x55,
+ 0x9d, 0x7d, 0xd1, 0x90, 0x89, 0x8b, 0xc8, 0x06, 0x24, 0xe5,
+ 0xc8, 0xc1, 0xbb, 0x9b, 0x90, 0xfb, 0x2e, 0xef, 0x12, 0xed,
+ 0x24, 0xbe, 0xbd, 0x8d, 0xf7, 0x1e, 0xf6, 0x5c, 0x70, 0xfa,
+ 0x4e, 0x91, 0x86, 0x3a, 0x31, 0xbe ),
+ EXPECT ( 0x5c, 0x07, 0xb7, 0x9c, 0x12, 0x83, 0x1b, 0xac, 0x36, 0x52,
+ 0x17, 0x8b, 0x2f, 0x90, 0x7a, 0x69, 0x61, 0x98, 0x39, 0xd8,
+ 0xa7, 0xfa, 0xa2, 0xb6, 0x95, 0xef, 0xb3, 0x10, 0x82, 0x38,
+ 0x01, 0x35, 0x85, 0x19, 0x1f, 0x59, 0x9c, 0x99, 0x07, 0xc7,
+ 0x21, 0x92, 0xed, 0x25, 0x7e, 0x9f, 0x6c, 0xd3, 0x77, 0xdd,
+ 0x6b, 0xac, 0x33, 0x7c, 0x19 ) );
+
+/**
+ * Report Hash_df test result
+ *
+ * @v test Hash_df test
+ */
+#define hash_df_ok( test ) do { \
+ uint8_t output[ (test)->expected_len ]; \
+ hash_df ( (test)->hash, (test)->input, (test)->input_len, \
+ output, sizeof ( output ) ); \
+ ok ( memcmp ( (test)->expected, output, \
+ sizeof ( output ) ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Perform Hash_df self-test
+ *
+ */
+static void hash_df_test_exec ( void ) {
+
+ hash_df_ok ( &test_sha1_1 );
+ hash_df_ok ( &test_sha1_2 );
+ hash_df_ok ( &test_sha1_3 );
+ hash_df_ok ( &test_sha1_4 );
+ hash_df_ok ( &test_sha1_5 );
+ hash_df_ok ( &test_sha1_6 );
+ hash_df_ok ( &test_sha1_7 );
+ hash_df_ok ( &test_sha1_8 );
+ hash_df_ok ( &test_sha1_9 );
+ hash_df_ok ( &test_sha1_10 );
+ hash_df_ok ( &test_sha1_11 );
+ hash_df_ok ( &test_sha1_12 );
+ hash_df_ok ( &test_sha1_13 );
+ hash_df_ok ( &test_sha1_14 );
+ hash_df_ok ( &test_sha1_15 );
+ hash_df_ok ( &test_sha1_16 );
+ hash_df_ok ( &test_sha1_17 );
+ hash_df_ok ( &test_sha1_18 );
+ hash_df_ok ( &test_sha1_19 );
+ hash_df_ok ( &test_sha1_20 );
+
+ hash_df_ok ( &test_sha256_1 );
+ hash_df_ok ( &test_sha256_2 );
+ hash_df_ok ( &test_sha256_3 );
+ hash_df_ok ( &test_sha256_4 );
+ hash_df_ok ( &test_sha256_5 );
+ hash_df_ok ( &test_sha256_6 );
+ hash_df_ok ( &test_sha256_7 );
+ hash_df_ok ( &test_sha256_8 );
+ hash_df_ok ( &test_sha256_9 );
+ hash_df_ok ( &test_sha256_10 );
+ hash_df_ok ( &test_sha256_11 );
+ hash_df_ok ( &test_sha256_12 );
+ hash_df_ok ( &test_sha256_13 );
+ hash_df_ok ( &test_sha256_14 );
+ hash_df_ok ( &test_sha256_15 );
+ hash_df_ok ( &test_sha256_16 );
+ hash_df_ok ( &test_sha256_17 );
+ hash_df_ok ( &test_sha256_18 );
+ hash_df_ok ( &test_sha256_19 );
+ hash_df_ok ( &test_sha256_20 );
+}
+
+/** Hash_df self-test */
+struct self_test hash_df_test __self_test = {
+ .name = "hash_df",
+ .exec = hash_df_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/hmac_drbg_test.c b/src/VBox/Devices/PC/ipxe/src/tests/hmac_drbg_test.c
new file mode 100644
index 00000000..d03efef0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/hmac_drbg_test.c
@@ -0,0 +1,1385 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * HMAC_DRBG tests
+ *
+ * These test vectors are provided by NIST as part of the
+ * Cryptographic Toolkit Examples, downloadable from:
+ *
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/HMAC_DRBG.pdf
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <assert.h>
+#include <string.h>
+#include <ipxe/hmac_drbg.h>
+#include <ipxe/sha1.h>
+#include <ipxe/sha256.h>
+#include <ipxe/test.h>
+
+/** Define inline expected data */
+#define EXPECT(...) { __VA_ARGS__ }
+
+/** An HMAC_DRBG instantiation test */
+struct hmac_drbg_test_instantiate {
+ /** Underlying hash algorithm */
+ struct digest_algorithm *hash;
+ /** Output block length */
+ size_t out_len;
+ /** Entropy */
+ const void *entropy;
+ /** Length of entropy */
+ size_t entropy_len;
+ /** Nonce */
+ const void *nonce;
+ /** Length of nonce */
+ size_t nonce_len;
+ /** Personalisation string */
+ const void *personal;
+ /** Length of personalisation string */
+ size_t personal_len;
+ /** Expected key */
+ const void *expected_key;
+ /** Length of expected key */
+ size_t expected_key_len;
+ /** Expected value */
+ const void *expected_value;
+ /** Length of expected value */
+ size_t expected_value_len;
+};
+
+/**
+ * Define an HMAC_DRBG instantiation test
+ *
+ * @v name Test name
+ * @v hmac_drbg HMAC_DRBG algorithm
+ * @v entropy_array Entropy input
+ * @v nonce_array Nonce
+ * @v personal_array Personalisation string
+ * @v key Expected key
+ * @v value Expected value
+ * @ret test Instantiation test
+ */
+#define HMAC_DRBG_TEST_INSTANTIATE( name, hmac_drbg, entropy_array, \
+ nonce_array, personal_array, \
+ key, value ) \
+ static const uint8_t name ## _key [] = key; \
+ static const uint8_t name ## _value [] = value; \
+ static struct hmac_drbg_test_instantiate name = { \
+ .hash = HMAC_DRBG_HASH ( hmac_drbg ), \
+ .out_len = HMAC_DRBG_OUTLEN_BYTES ( hmac_drbg ), \
+ .entropy = entropy_array, \
+ .entropy_len = sizeof ( entropy_array ), \
+ .nonce = nonce_array, \
+ .nonce_len = sizeof ( nonce_array ), \
+ .personal = personal_array, \
+ .personal_len = sizeof ( personal_array ), \
+ .expected_key = name ## _key, \
+ .expected_key_len = sizeof ( name ## _key ), \
+ .expected_value = name ## _value, \
+ .expected_value_len = sizeof ( name ## _value ), \
+ }
+
+/**
+ * Report instantiation test result
+ *
+ * @v state HMAC_DRBG internal state
+ * @v test Instantiation test
+ */
+#define instantiate_ok( state, test ) do { \
+ struct { \
+ uint8_t entropy[(test)->entropy_len]; \
+ uint8_t nonce[(test)->nonce_len]; \
+ } __attribute__ (( packed )) entropy_nonce; \
+ \
+ assert ( (test)->expected_key_len == (test)->out_len ); \
+ assert ( (test)->expected_value_len == (test)->out_len ); \
+ memcpy ( entropy_nonce.entropy, (test)->entropy, \
+ sizeof ( entropy_nonce.entropy ) ); \
+ memcpy ( entropy_nonce.nonce, (test)->nonce, \
+ sizeof ( entropy_nonce.nonce ) ); \
+ hmac_drbg_instantiate ( (test)->hash, (state), &entropy_nonce, \
+ sizeof ( entropy_nonce ), \
+ (test)->personal, \
+ (test)->personal_len ); \
+ ok ( memcmp ( (state)->key, (test)->expected_key, \
+ (test)->expected_key_len ) == 0 ); \
+ ok ( memcmp ( (state)->value, (test)->expected_value, \
+ (test)->expected_value_len ) == 0 ); \
+ } while ( 0 )
+
+/** An HMAC_DRBG reseed test */
+struct hmac_drbg_test_reseed {
+ /** Underlying hash algorithm */
+ struct digest_algorithm *hash;
+ /** Output block length */
+ size_t out_len;
+ /** Entropy */
+ const void *entropy;
+ /** Length of entropy */
+ size_t entropy_len;
+ /** Additional input */
+ const void *additional;
+ /** Length of additional_input */
+ size_t additional_len;
+ /** Expected key */
+ const void *expected_key;
+ /** Length of expected key */
+ size_t expected_key_len;
+ /** Expected value */
+ const void *expected_value;
+ /** Length of expected value */
+ size_t expected_value_len;
+};
+
+/**
+ * Define an HMAC_DRBG reseed test
+ *
+ * @v name Test name
+ * @v hmac_drbg HMAC_DRBG algorithm
+ * @v entropy_array Entropy input
+ * @v additional_array Additional input
+ * @v key Expected key
+ * @v value Expected value
+ * @ret test Reseed test
+ */
+#define HMAC_DRBG_TEST_RESEED( name, hmac_drbg, entropy_array, \
+ additional_array, key, value ) \
+ static const uint8_t name ## _key [] = key; \
+ static const uint8_t name ## _value [] = value; \
+ static struct hmac_drbg_test_reseed name = { \
+ .hash = HMAC_DRBG_HASH ( hmac_drbg ), \
+ .out_len = HMAC_DRBG_OUTLEN_BYTES ( hmac_drbg ), \
+ .entropy = entropy_array, \
+ .entropy_len = sizeof ( entropy_array ), \
+ .additional = additional_array, \
+ .additional_len = sizeof ( additional_array ), \
+ .expected_key = name ## _key, \
+ .expected_key_len = sizeof ( name ## _key ), \
+ .expected_value = name ## _value, \
+ .expected_value_len = sizeof ( name ## _value ), \
+ }
+
+/**
+ * Report reseed test result
+ *
+ * @v state HMAC_DRBG internal state
+ * @v test Reseed test
+ */
+#define reseed_ok( state, test ) do { \
+ assert ( (test)->expected_key_len == (test)->out_len ); \
+ assert ( (test)->expected_value_len == (test)->out_len ); \
+ hmac_drbg_reseed ( (test)->hash, (state), (test)->entropy, \
+ (test)->entropy_len, (test)->additional, \
+ (test)->additional_len ); \
+ ok ( memcmp ( (state)->key, (test)->expected_key, \
+ (test)->expected_key_len ) == 0 ); \
+ ok ( memcmp ( (state)->value, (test)->expected_value, \
+ (test)->expected_value_len ) == 0 ); \
+ } while ( 0 )
+
+/** An HMAC_DRBG generation test */
+struct hmac_drbg_test_generate {
+ /** Underlying hash algorithm */
+ struct digest_algorithm *hash;
+ /** Output block length */
+ size_t out_len;
+ /** Additional input */
+ const void *additional;
+ /** Length of additional_input */
+ size_t additional_len;
+ /** Expected key */
+ const void *expected_key;
+ /** Length of expected key */
+ size_t expected_key_len;
+ /** Expected value */
+ const void *expected_value;
+ /** Length of expected value */
+ size_t expected_value_len;
+ /** Expected pseudorandom data */
+ const void *expected_data;
+ /** Length of data */
+ size_t expected_data_len;
+};
+
+/**
+ * Define an HMAC_DRBG generation test
+ *
+ * @v name Test name
+ * @v hmac_drbg HMAC_DRBG algorithm
+ * @v additional_array Additional input
+ * @v key Expected key
+ * @v value Expected value
+ * @v data Expected pseudorandom data
+ * @ret test Generation test
+ */
+#define HMAC_DRBG_TEST_GENERATE( name, hmac_drbg, additional_array, \
+ key, value, data ) \
+ static const uint8_t name ## _key [] = key; \
+ static const uint8_t name ## _value [] = value; \
+ static const uint8_t name ## _data [] = data; \
+ static struct hmac_drbg_test_generate name = { \
+ .hash = HMAC_DRBG_HASH ( hmac_drbg ), \
+ .out_len = HMAC_DRBG_OUTLEN_BYTES ( hmac_drbg ), \
+ .additional = additional_array, \
+ .additional_len = sizeof ( additional_array ), \
+ .expected_key = name ## _key, \
+ .expected_key_len = sizeof ( name ## _key ), \
+ .expected_value = name ## _value, \
+ .expected_value_len = sizeof ( name ## _value ), \
+ .expected_data = name ## _data, \
+ .expected_data_len = sizeof ( name ## _data ), \
+ }
+
+/**
+ * Report generation test result
+ *
+ * @v state HMAC_DRBG internal state
+ * @v test Generation test
+ */
+#define generate_ok( state, test ) do { \
+ uint8_t data[ (test)->expected_data_len ]; \
+ int rc; \
+ \
+ assert ( (test)->expected_key_len == (test)->out_len ); \
+ assert ( (test)->expected_value_len == (test)->out_len ); \
+ rc = hmac_drbg_generate ( (test)->hash, (state), \
+ (test)->additional, \
+ (test)->additional_len, \
+ data, sizeof ( data ) ); \
+ ok ( rc == 0 ); \
+ ok ( memcmp ( (state)->key, (test)->expected_key, \
+ (test)->expected_key_len ) == 0 ); \
+ ok ( memcmp ( (state)->value, (test)->expected_value, \
+ (test)->expected_value_len ) == 0 ); \
+ ok ( memcmp ( data, (test)->expected_data, \
+ (test)->expected_data_len ) == 0 ); \
+ } while ( 0 )
+
+/** An HMAC_DRBG generation failure test */
+struct hmac_drbg_test_generate_fail {
+ /** Underlying hash algorithm */
+ struct digest_algorithm *hash;
+ /** Additional input */
+ const void *additional;
+ /** Length of additional_input */
+ size_t additional_len;
+ /** Length of requested data */
+ size_t requested_len;
+};
+
+/**
+ * Define an HMAC_DRBG generation failure test
+ *
+ * @v name Test name
+ * @v hmac_drbg HMAC_DRBG algorithm
+ * @v additional_array Additional input
+ * @ret test Generation failure test
+ */
+#define HMAC_DRBG_TEST_GENERATE_FAIL( name, hmac_drbg, \
+ additional_array, len ) \
+ static struct hmac_drbg_test_generate_fail name = { \
+ .hash = HMAC_DRBG_HASH ( hmac_drbg ), \
+ .additional = additional_array, \
+ .additional_len = sizeof ( additional_array ), \
+ .requested_len = len, \
+ }
+
+/**
+ * Report generation failure test result
+ *
+ * @v state HMAC_DRBG internal state
+ * @v test Generation failure test
+ */
+#define generate_fail_ok( state, test ) do { \
+ uint8_t data[ (test)->requested_len ]; \
+ int rc; \
+ \
+ rc = hmac_drbg_generate ( (test)->hash, (state), \
+ (test)->additional, \
+ (test)->additional_len, data, \
+ sizeof ( data ) ); \
+ ok ( rc != 0 ); \
+ } while ( 0 )
+
+/** "EntropyInput" */
+static const uint8_t entropy_input[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36
+};
+
+/** "Nonce" for SHA-1 */
+static const uint8_t nonce_sha1[] = {
+ 0x20, 0x21, 0x22, 0x23, 0x24
+};
+
+/** "Nonce" for SHA-256 */
+static const uint8_t nonce_sha256[] = {
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
+};
+
+/** "EntropyInput1 (for Reseed1) */
+static const uint8_t entropy_input_1[] = {
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b,
+ 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6
+};
+
+/** "EntropyInput2 (for Reseed2) */
+static const uint8_t entropy_input_2[] = {
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
+ 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
+ 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6
+};
+
+/** "PersonalizationString = <empty>" */
+static const uint8_t personalisation_string_empty[] = {};
+
+/** "PersonalizationString" */
+static const uint8_t personalisation_string[] = {
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
+ 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63,
+ 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76
+};
+
+/** "AdditionalInput = <empty>" */
+static const uint8_t additional_input_empty[] = {};
+
+/** "AdditionalInput1" */
+static const uint8_t additional_input_1[] = {
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
+ 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96
+};
+
+/** "AdditionalInput2" */
+static const uint8_t additional_input_2[] = {
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6
+};
+
+/** SHA-1 Test 1 : Instantiation */
+HMAC_DRBG_TEST_INSTANTIATE ( sha1_instantiate_1, HMAC_DRBG_SHA1,
+ entropy_input, nonce_sha1, personalisation_string_empty,
+ EXPECT ( 0xab, 0x16, 0x0d, 0xd2, 0x1c, 0x30, 0x98, 0x0c, 0xa3, 0xca,
+ 0x5a, 0x9c, 0x77, 0xb7, 0xbd, 0xf0, 0x50, 0xe6, 0x4e, 0xe9 ),
+ EXPECT ( 0x61, 0x44, 0x99, 0xea, 0x98, 0x0c, 0xfb, 0x3d, 0xaa, 0x2c,
+ 0xa8, 0x6d, 0x65, 0xa4, 0x6b, 0xf4, 0x48, 0x8d, 0x8c, 0xc5 ) );
+
+/** SHA-1 Test 1.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_1_1, HMAC_DRBG_SHA1,
+ additional_input_empty,
+ EXPECT ( 0x7b, 0xb1, 0x80, 0x28, 0xe0, 0x1d, 0x03, 0x42, 0xdf, 0x4f,
+ 0x54, 0xda, 0x51, 0x22, 0xfa, 0x5f, 0x2c, 0x3a, 0x05, 0xe4 ),
+ EXPECT ( 0x2f, 0x89, 0x4f, 0x28, 0xcc, 0x2f, 0x53, 0x82, 0x96, 0x40,
+ 0x64, 0x3a, 0xd1, 0x7b, 0x84, 0xb0, 0xcd, 0x3c, 0x79, 0x79 ),
+ EXPECT ( 0x5a, 0x7d, 0x3b, 0x44, 0x9f, 0x48, 0x1c, 0xb3, 0x8d, 0xf7,
+ 0x9a, 0xd2, 0xb1, 0xfc, 0xc0, 0x1e, 0x57, 0xf8, 0x13, 0x5e,
+ 0x8c, 0x0b, 0x22, 0xcd, 0x06, 0x30, 0xbf, 0xb0, 0x12, 0x7f,
+ 0xb5, 0x40, 0x8c, 0x8e, 0xfc, 0x17, 0xa9, 0x29, 0x89, 0x6e ) );
+
+/** SHA-1 Test 1.2 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_1_2, HMAC_DRBG_SHA1,
+ additional_input_empty,
+ EXPECT ( 0x3d, 0x4d, 0x73, 0x77, 0xe9, 0x17, 0x2a, 0xaf, 0xa7, 0x76,
+ 0xb0, 0xdd, 0xcb, 0x89, 0x42, 0x00, 0x4a, 0x44, 0xb7, 0xfd ),
+ EXPECT ( 0x1a, 0x26, 0xbd, 0x9b, 0xfc, 0x97, 0x44, 0xbd, 0x29, 0xf6,
+ 0xae, 0xbe, 0x24, 0x37, 0xe2, 0x09, 0xf1, 0xf7, 0x16, 0x25 ),
+ EXPECT ( 0x82, 0xcf, 0x77, 0x2e, 0xc3, 0xe8, 0x4b, 0x00, 0xfc, 0x74,
+ 0xf5, 0xdf, 0x10, 0x4e, 0xfb, 0xfb, 0x24, 0x28, 0x55, 0x4e,
+ 0x9c, 0xe3, 0x67, 0xd0, 0x3a, 0xea, 0xde, 0x37, 0x82, 0x7f,
+ 0xa8, 0xe9, 0xcb, 0x6a, 0x08, 0x19, 0x61, 0x15, 0xd9, 0x48 ) );
+
+/** SHA-1 Test 2 : Instantiation */
+#define sha1_instantiate_2 sha1_instantiate_1
+
+/** SHA-1 Test 2.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_2_1, HMAC_DRBG_SHA1,
+ additional_input_1,
+ EXPECT ( 0x3a, 0x06, 0x2e, 0x6b, 0x79, 0xfe, 0x70, 0xdb, 0xff, 0xeb,
+ 0x3a, 0x2b, 0x6b, 0xe8, 0x03, 0x23, 0xf7, 0xd6, 0x74, 0xc5 ),
+ EXPECT ( 0xbd, 0x36, 0x31, 0x28, 0xbf, 0x58, 0x0d, 0x7a, 0x54, 0x42,
+ 0x9d, 0xdd, 0x58, 0xe8, 0x19, 0x3b, 0x98, 0x43, 0xbd, 0x2b ),
+ EXPECT ( 0xc7, 0xaa, 0xac, 0x58, 0x3c, 0x6e, 0xf6, 0x30, 0x07, 0x14,
+ 0xc2, 0xcc, 0x5d, 0x06, 0xc1, 0x48, 0xcf, 0xfb, 0x40, 0x44,
+ 0x9a, 0xd0, 0xbb, 0x26, 0xfa, 0xc0, 0x49, 0x7b, 0x5c, 0x57,
+ 0xe1, 0x61, 0xe3, 0x66, 0x81, 0xbc, 0xc9, 0x30, 0xce, 0x80 ) );
+
+/** SHA-1 Test 2.2 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_2_2, HMAC_DRBG_SHA1,
+ additional_input_2,
+ EXPECT ( 0x8a, 0xd7, 0xe3, 0x47, 0x72, 0xb5, 0xfc, 0x7c, 0x3b, 0x3b,
+ 0x27, 0x62, 0x4f, 0x0b, 0x91, 0x77, 0x6a, 0x8a, 0x71, 0x12 ),
+ EXPECT ( 0xd7, 0x13, 0x76, 0xa4, 0x6d, 0x76, 0x4b, 0x17, 0xc3, 0xb7,
+ 0x39, 0x34, 0x7b, 0x38, 0x4e, 0x51, 0x51, 0xe8, 0x7e, 0x88 ),
+ EXPECT ( 0x6e, 0xbd, 0x2b, 0x7b, 0x5e, 0x0a, 0x2a, 0xd7, 0xa2, 0x4b,
+ 0x1b, 0xf9, 0xa1, 0xdb, 0xa4, 0x7d, 0x43, 0x27, 0x17, 0x19,
+ 0xb9, 0xc3, 0x7b, 0x7f, 0xe8, 0x1b, 0xa9, 0x40, 0x45, 0xa1,
+ 0x4a, 0x7c, 0xb5, 0x14, 0xb4, 0x46, 0x66, 0x6e, 0xa5, 0xa7 ) );
+
+/** SHA-1 Test 3 : Instantiation */
+HMAC_DRBG_TEST_INSTANTIATE ( sha1_instantiate_3, HMAC_DRBG_SHA1,
+ entropy_input, nonce_sha1, personalisation_string,
+ EXPECT ( 0xb7, 0xd9, 0x66, 0xd7, 0x0d, 0x4e, 0x27, 0xa7, 0xfa, 0x83,
+ 0x8f, 0x7d, 0x61, 0x12, 0x6c, 0x0e, 0xdc, 0x84, 0x76, 0x1c ),
+ EXPECT ( 0xda, 0xb2, 0xa7, 0x18, 0x83, 0xf1, 0x00, 0x5c, 0x5d, 0xd0,
+ 0x39, 0x32, 0x4d, 0x3c, 0x36, 0x4d, 0x6e, 0x18, 0xf9, 0x54 ) );
+
+/** SHA-1 Test 3.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_3_1, HMAC_DRBG_SHA1,
+ additional_input_empty,
+ EXPECT ( 0x87, 0xd3, 0x82, 0x8b, 0xe0, 0x3a, 0x80, 0x7d, 0xd3, 0x40,
+ 0x29, 0x41, 0xbe, 0xd6, 0xde, 0x98, 0x6e, 0xe7, 0xa2, 0x86 ),
+ EXPECT ( 0x6a, 0xe1, 0xd0, 0x08, 0x6f, 0x53, 0xb1, 0xb7, 0x63, 0xa4,
+ 0x51, 0x5b, 0x19, 0x06, 0xfe, 0xe4, 0x76, 0x61, 0xfd, 0x47 ),
+ EXPECT ( 0xb3, 0xbd, 0x05, 0x24, 0x6c, 0xba, 0x12, 0xa6, 0x47, 0x35,
+ 0xa4, 0xe3, 0xfd, 0xe5, 0x99, 0xbc, 0x1b, 0xe3, 0x0f, 0x43,
+ 0x9b, 0xd0, 0x60, 0x20, 0x8e, 0xea, 0x7d, 0x71, 0xf9, 0xd1,
+ 0x23, 0xdf, 0x47, 0xb3, 0xce, 0x06, 0x9d, 0x98, 0xed, 0xe6 ) );
+
+/** SHA-1 Test 3.2 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_3_2, HMAC_DRBG_SHA1,
+ additional_input_empty,
+ EXPECT ( 0x26, 0xab, 0xbf, 0x54, 0xb2, 0x8b, 0x93, 0xff, 0x90, 0x08,
+ 0x67, 0x0e, 0xbf, 0xee, 0x86, 0xcd, 0xd7, 0x22, 0x8e, 0xd5 ),
+ EXPECT ( 0xe9, 0x25, 0x47, 0x29, 0xe0, 0x02, 0x04, 0xa1, 0xb6, 0xc0,
+ 0x21, 0x58, 0xa6, 0xc7, 0x27, 0x86, 0x47, 0x14, 0xf1, 0xf7 ),
+ EXPECT ( 0xb5, 0xda, 0xda, 0x38, 0x0e, 0x28, 0x72, 0xdf, 0x93, 0x5b,
+ 0xca, 0x55, 0xb8, 0x82, 0xc8, 0xc9, 0x37, 0x69, 0x02, 0xab,
+ 0x63, 0x97, 0x65, 0x47, 0x2b, 0x71, 0xac, 0xeb, 0xe2, 0xea,
+ 0x8b, 0x1b, 0x6b, 0x49, 0x62, 0x9c, 0xb6, 0x73, 0x17, 0xe0 ) );
+
+/** SHA-1 Test 4 : Instantiation */
+#define sha1_instantiate_4 sha1_instantiate_3
+
+/** SHA-1 Test 4.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_4_1, HMAC_DRBG_SHA1,
+ additional_input_1,
+ EXPECT ( 0x17, 0xa5, 0xd7, 0x9f, 0x07, 0x67, 0x87, 0x6f, 0x3a, 0x45,
+ 0xe0, 0xc9, 0xc3, 0x3e, 0xc8, 0x8b, 0x03, 0xce, 0xea, 0x13 ),
+ EXPECT ( 0x4d, 0x2f, 0x3b, 0xc7, 0x77, 0x50, 0x5c, 0x45, 0xf7, 0xe1,
+ 0x7d, 0xcd, 0x3d, 0x86, 0xbf, 0x37, 0x9c, 0xb6, 0x02, 0x5e ),
+ EXPECT ( 0x1f, 0x8f, 0xec, 0x7b, 0xc7, 0xcf, 0xa9, 0xa8, 0x80, 0x34,
+ 0x5d, 0x28, 0x0b, 0x13, 0xc6, 0x32, 0xb8, 0x52, 0x77, 0x0a,
+ 0x6d, 0xfc, 0x30, 0x2e, 0xad, 0x4c, 0xe3, 0xf5, 0x54, 0xc7,
+ 0x9b, 0x0d, 0x44, 0x23, 0x9e, 0xba, 0x56, 0xa7, 0xea, 0x2d ) );
+
+/** SHA-1 Test 4.2 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_4_2, HMAC_DRBG_SHA1,
+ additional_input_2,
+ EXPECT ( 0x07, 0x9b, 0x57, 0xd9, 0x40, 0x6e, 0x11, 0xc2, 0xf8, 0x7c,
+ 0x8c, 0x82, 0x8c, 0x8c, 0x6f, 0xa7, 0x6e, 0x40, 0xea, 0x01 ),
+ EXPECT ( 0xa6, 0x54, 0xfe, 0x72, 0xf8, 0xa7, 0x7b, 0xb8, 0xf0, 0x3d,
+ 0xff, 0x07, 0xc7, 0x9a, 0x51, 0x53, 0x00, 0x9e, 0xdd, 0xda ),
+ EXPECT ( 0xaf, 0x97, 0xcd, 0xe1, 0xe8, 0xab, 0x32, 0x2a, 0x2e, 0xac,
+ 0xa8, 0xe6, 0xf4, 0xe5, 0xbf, 0x78, 0xa1, 0x1b, 0xde, 0xf7,
+ 0xdc, 0x91, 0x21, 0x5d, 0x44, 0xb1, 0x07, 0xb4, 0xd5, 0xa7,
+ 0x79, 0x01, 0x59, 0x25, 0x09, 0x76, 0x52, 0x80, 0xf9, 0x69 ) );
+
+/** SHA-1 Test 5 : Instantiation */
+#define sha1_instantiate_5 sha1_instantiate_1
+
+/** SHA-1 Test 5.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha1_generate_fail_5_1, HMAC_DRBG_SHA1,
+ additional_input_empty, ( 320 / 8 ) );
+
+/** SHA-1 Test 5.2 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha1_reseed_5_2, HMAC_DRBG_SHA1,
+ entropy_input_1, additional_input_empty,
+ EXPECT ( 0xcd, 0x4c, 0xab, 0x38, 0xc8, 0xad, 0x65, 0x71, 0x22, 0xbf,
+ 0x5d, 0x3d, 0x00, 0xd0, 0xac, 0x9b, 0x13, 0xd6, 0x29, 0xbb ),
+ EXPECT ( 0xf6, 0x60, 0xe2, 0x3e, 0x91, 0x00, 0x6b, 0x62, 0xc6, 0x54,
+ 0x3a, 0xb1, 0x34, 0x4d, 0x23, 0xa3, 0x1a, 0xb4, 0xcf, 0x2c ) );
+
+/** SHA-1 Test 5.3 : Retried first call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_5_3, HMAC_DRBG_SHA1,
+ additional_input_empty,
+ EXPECT ( 0x58, 0x7f, 0xd8, 0x21, 0xef, 0x6c, 0x9d, 0xa4, 0xa8, 0x3c,
+ 0x19, 0x21, 0x1f, 0x10, 0x56, 0xca, 0xcd, 0x23, 0xfc, 0x1a ),
+ EXPECT ( 0x84, 0x8f, 0xd1, 0x4c, 0x13, 0xb7, 0xea, 0x93, 0x72, 0x0c,
+ 0xcf, 0xde, 0x71, 0xf2, 0xf6, 0x44, 0x39, 0xdb, 0x79, 0x5d ),
+ EXPECT ( 0xfe, 0xc4, 0x59, 0x7f, 0x06, 0xa3, 0xa8, 0xcc, 0x85, 0x29,
+ 0xd5, 0x95, 0x57, 0xb9, 0xe6, 0x61, 0x05, 0x38, 0x09, 0xc0,
+ 0xbc, 0x0e, 0xfc, 0x28, 0x2a, 0xbd, 0x87, 0x60, 0x5c, 0xc9,
+ 0x0c, 0xba, 0x9b, 0x86, 0x33, 0xdc, 0xb1, 0xda, 0xe0, 0x2e ) );
+
+/** SHA-1 Test 5.4 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha1_generate_fail_5_4, HMAC_DRBG_SHA1,
+ additional_input_empty, ( 320 / 8 ) );
+
+/** SHA-1 Test 5.5 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha1_reseed_5_5, HMAC_DRBG_SHA1,
+ entropy_input_2, additional_input_empty,
+ EXPECT ( 0xdb, 0xa1, 0xcf, 0xf4, 0x87, 0x95, 0x46, 0xa0, 0x38, 0xa5,
+ 0x59, 0xb2, 0xa2, 0x4d, 0xf2, 0xc0, 0x30, 0x08, 0x9a, 0x41 ),
+ EXPECT ( 0x2f, 0x88, 0x3c, 0x46, 0x48, 0xe1, 0x31, 0xe8, 0x6d, 0xdf,
+ 0x9d, 0xca, 0x0d, 0x74, 0xf3, 0x0c, 0xa1, 0xce, 0x6e, 0xfb ) );
+
+/** SHA-1 Test 5.6 : Retried second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_5_6, HMAC_DRBG_SHA1,
+ additional_input_empty,
+ EXPECT ( 0xf9, 0x39, 0xa5, 0xab, 0x08, 0xa3, 0x9f, 0x23, 0x10, 0x70,
+ 0xb0, 0xd4, 0xc9, 0x6d, 0xc2, 0x37, 0x90, 0xba, 0x01, 0x53 ),
+ EXPECT ( 0xce, 0x6d, 0x08, 0xb4, 0xae, 0x2c, 0xe3, 0x83, 0xfd, 0xab,
+ 0xb0, 0x1e, 0xaa, 0xfc, 0x9c, 0x8e, 0x76, 0xa0, 0xd4, 0x72 ),
+ EXPECT ( 0x84, 0xad, 0xd5, 0xe2, 0xd2, 0x04, 0x1c, 0x01, 0x72, 0x3a,
+ 0x4d, 0xe4, 0x33, 0x5b, 0x13, 0xef, 0xdf, 0x16, 0xb0, 0xe5,
+ 0x1a, 0x0a, 0xd3, 0x9b, 0xd1, 0x5e, 0x86, 0x2e, 0x64, 0x4f,
+ 0x31, 0xe4, 0xa2, 0xd7, 0xd8, 0x43, 0xe5, 0x7c, 0x59, 0x68 ) );
+
+/** SHA-1 Test 6 : Instantiate */
+#define sha1_instantiate_6 sha1_instantiate_1
+
+/** SHA-1 Test 6.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha1_generate_fail_6_1, HMAC_DRBG_SHA1,
+ additional_input_1, ( 320 / 8 ) );
+
+/** SHA-1 Test 6.2 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha1_reseed_6_2, HMAC_DRBG_SHA1,
+ entropy_input_1, additional_input_1,
+ EXPECT ( 0x52, 0x28, 0xa4, 0xb6, 0xa4, 0x46, 0x92, 0x90, 0x5e, 0xc0,
+ 0x44, 0xbf, 0xf0, 0xbb, 0x4e, 0x25, 0xa3, 0x87, 0xca, 0xc1 ),
+ EXPECT ( 0x24, 0x77, 0x32, 0xd0, 0x4c, 0xb8, 0x4e, 0xd4, 0x1a, 0xdd,
+ 0x95, 0xa4, 0xb7, 0x8b, 0x50, 0xcd, 0x9b, 0x3d, 0x3f, 0x32 ) );
+
+/** SHA-1 Test 6.3 : Retried first call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_6_3, HMAC_DRBG_SHA1,
+ additional_input_empty,
+ EXPECT ( 0xab, 0x3d, 0xd4, 0x89, 0x5b, 0xc8, 0xcd, 0x22, 0x71, 0xde,
+ 0xba, 0x5f, 0x3c, 0x13, 0x63, 0x52, 0x6b, 0x8b, 0x74, 0x52 ),
+ EXPECT ( 0xa8, 0x66, 0xc5, 0xef, 0xf2, 0xaf, 0x04, 0x2b, 0x11, 0x86,
+ 0x44, 0x94, 0x45, 0x23, 0x7f, 0x9c, 0x02, 0x44, 0x98, 0x64 ),
+ EXPECT ( 0xa1, 0xba, 0x8f, 0xa5, 0x8b, 0xb5, 0x01, 0x3f, 0x43, 0xf7,
+ 0xb6, 0xed, 0x52, 0xb4, 0x53, 0x9f, 0xa1, 0x6d, 0xc7, 0x79,
+ 0x57, 0xae, 0xe8, 0x15, 0xb9, 0xc0, 0x70, 0x04, 0xc7, 0xe9,
+ 0x92, 0xeb, 0x8c, 0x7e, 0x59, 0x19, 0x64, 0xaf, 0xee, 0xa2 ) );
+
+/** SHA-1 Test 6.4 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha1_generate_fail_6_4, HMAC_DRBG_SHA1,
+ additional_input_2, ( 320 / 8 ) );
+
+/** SHA-1 Test 6.5 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha1_reseed_6_5, HMAC_DRBG_SHA1,
+ entropy_input_2, additional_input_2,
+ EXPECT ( 0xe5, 0x73, 0x9f, 0x9c, 0xf7, 0xff, 0x43, 0x84, 0xd1, 0x27,
+ 0x3e, 0x02, 0x6b, 0x45, 0x31, 0x21, 0x36, 0x49, 0x4f, 0x41 ),
+ EXPECT ( 0x30, 0xc3, 0x43, 0x05, 0xc2, 0xc6, 0x48, 0xb0, 0x57, 0xa6,
+ 0x40, 0x22, 0x1b, 0x5c, 0x56, 0x57, 0x26, 0xcd, 0x32, 0xb2 ) );
+
+/** SHA-1 Test 6.6 : Retried second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_6_6, HMAC_DRBG_SHA1,
+ additional_input_empty,
+ EXPECT ( 0x61, 0x91, 0xca, 0x9b, 0xf0, 0x00, 0xd1, 0x0a, 0x71, 0x69,
+ 0x0a, 0xc1, 0x0e, 0x09, 0xff, 0xc8, 0x92, 0xab, 0xde, 0x9a ),
+ EXPECT ( 0x1e, 0xc0, 0x49, 0x0f, 0xa0, 0xb7, 0x65, 0x52, 0x7e, 0x5e,
+ 0xa1, 0x8b, 0x53, 0x22, 0xb2, 0x8b, 0xdd, 0x0e, 0x7b, 0xc0 ),
+ EXPECT ( 0x84, 0x26, 0x4a, 0x73, 0xa8, 0x18, 0xc9, 0x5c, 0x2f, 0x42,
+ 0x4b, 0x37, 0xd3, 0xcc, 0x99, 0x0b, 0x04, 0x6f, 0xb5, 0x0c,
+ 0x2d, 0xc6, 0x4a, 0x16, 0x42, 0x11, 0x88, 0x9a, 0x01, 0x0f,
+ 0x24, 0x71, 0xa0, 0x91, 0x2f, 0xfe, 0xa1, 0xbf, 0x01, 0x95 ) );
+
+/** SHA-1 Test 7 : Instantiation */
+#define sha1_instantiate_7 sha1_instantiate_3
+
+/** SHA-1 Test 7.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha1_generate_fail_7_1, HMAC_DRBG_SHA1,
+ additional_input_empty, ( 320 / 8 ) );
+
+/** SHA-1 Test 7.2 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha1_reseed_7_2, HMAC_DRBG_SHA1,
+ entropy_input_1, additional_input_empty,
+ EXPECT ( 0xb9, 0x25, 0x4d, 0x8a, 0xac, 0xba, 0x43, 0xfb, 0xda, 0xe6,
+ 0x39, 0x4f, 0x2b, 0x3a, 0xfc, 0x5d, 0x58, 0x08, 0x00, 0xbf ),
+ EXPECT ( 0x28, 0x40, 0x3b, 0x60, 0x36, 0x38, 0xd0, 0x7d, 0x79, 0x66,
+ 0x66, 0x1e, 0xf6, 0x7b, 0x9d, 0x39, 0x05, 0xf4, 0x6d, 0xb9 ) );
+
+/** SHA-1 Test 7.3 : Retried first call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_7_3, HMAC_DRBG_SHA1,
+ additional_input_empty,
+ EXPECT ( 0x64, 0xfe, 0x07, 0x4a, 0x6e, 0x77, 0x97, 0xd1, 0xa4, 0x35,
+ 0xda, 0x89, 0x64, 0x48, 0x4d, 0x6c, 0xf8, 0xbd, 0xc0, 0x1b ),
+ EXPECT ( 0x43, 0xe0, 0xc0, 0x52, 0x15, 0x86, 0xe9, 0x47, 0x3b, 0x06,
+ 0x0d, 0x87, 0xd0, 0x8a, 0x23, 0x25, 0xfa, 0xe1, 0x49, 0xd1 ),
+ EXPECT ( 0x6c, 0x37, 0xfd, 0xd7, 0x29, 0xaa, 0x40, 0xf8, 0x0b, 0xc6,
+ 0xab, 0x08, 0xca, 0x7c, 0xc6, 0x49, 0x79, 0x4f, 0x69, 0x98,
+ 0xb5, 0x70, 0x81, 0xe4, 0x22, 0x0f, 0x22, 0xc5, 0xc2, 0x83,
+ 0xe2, 0xc9, 0x1b, 0x8e, 0x30, 0x5a, 0xb8, 0x69, 0xc6, 0x25 ) );
+
+/** SHA-1 Test 7.4 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha1_generate_fail_7_4, HMAC_DRBG_SHA1,
+ additional_input_empty, ( 320 / 8 ) );
+
+/** SHA-1 Test 7.5 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha1_reseed_7_5, HMAC_DRBG_SHA1,
+ entropy_input_2, additional_input_empty,
+ EXPECT ( 0x02, 0xbc, 0x57, 0x7f, 0xd1, 0x0e, 0xf7, 0x19, 0x3c, 0x1d,
+ 0xb0, 0x98, 0xbd, 0x5b, 0x75, 0xc7, 0xc4, 0xb6, 0x79, 0x59 ),
+ EXPECT ( 0xbc, 0xbd, 0xf0, 0x52, 0xe0, 0xe0, 0x2a, 0xe8, 0x9a, 0x77,
+ 0x67, 0x94, 0x3f, 0x98, 0x65, 0xb8, 0xb7, 0x22, 0x90, 0x2d ) );
+
+/** SHA-1 Test 7.6 : Retried second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_7_6, HMAC_DRBG_SHA1,
+ additional_input_empty,
+ EXPECT ( 0x1a, 0xa4, 0x24, 0x1c, 0x69, 0x5e, 0x29, 0xc0, 0xa5, 0x9a,
+ 0xd1, 0x8a, 0x60, 0x70, 0xe3, 0x38, 0xa5, 0x48, 0xbe, 0x92 ),
+ EXPECT ( 0x03, 0x47, 0x35, 0x9b, 0xc9, 0xc7, 0xf8, 0x8c, 0xc8, 0x33,
+ 0x0d, 0x4f, 0x59, 0xfb, 0xc7, 0x70, 0xb0, 0xb7, 0x7b, 0x03 ),
+ EXPECT ( 0xca, 0xf5, 0x7d, 0xcf, 0xea, 0x39, 0x3b, 0x92, 0x36, 0xbf,
+ 0x69, 0x1f, 0xa4, 0x56, 0xfe, 0xa7, 0xfd, 0xf1, 0xdf, 0x83,
+ 0x61, 0x48, 0x2c, 0xa5, 0x4d, 0x5f, 0xa7, 0x23, 0xf4, 0xc8,
+ 0x8b, 0x4f, 0xa5, 0x04, 0xbf, 0x03, 0x27, 0x7f, 0xa7, 0x83 ) );
+
+/** SHA-1 Test 8 : Instantiate */
+#define sha1_instantiate_8 sha1_instantiate_3
+
+/** SHA-1 Test 8.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha1_generate_fail_8_1, HMAC_DRBG_SHA1,
+ additional_input_1, ( 320 / 8 ) );
+
+/** SHA-1 Test 8.2 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha1_reseed_8_2, HMAC_DRBG_SHA1,
+ entropy_input_1, additional_input_1,
+ EXPECT ( 0xc0, 0x95, 0x48, 0xc0, 0xd3, 0xc8, 0x61, 0xd7, 0x40, 0xf2,
+ 0x83, 0x7d, 0x72, 0xb5, 0x07, 0x23, 0x5c, 0x26, 0xdb, 0x82 ),
+ EXPECT ( 0x17, 0x4b, 0x3f, 0x84, 0xc3, 0x53, 0x1f, 0x7c, 0x0a, 0x2e,
+ 0x54, 0x21, 0x23, 0x4e, 0xa1, 0x6b, 0x70, 0x8d, 0xdf, 0x0d ) );
+
+/** SHA-1 Test 8.3 : Retried first call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_8_3, HMAC_DRBG_SHA1,
+ additional_input_empty,
+ EXPECT ( 0x60, 0x3f, 0x09, 0x49, 0x27, 0x9c, 0x70, 0xe8, 0xc6, 0x6c,
+ 0x0f, 0x56, 0x37, 0xc0, 0xf3, 0x75, 0x60, 0x07, 0xe5, 0xac ),
+ EXPECT ( 0xf2, 0xb3, 0x3b, 0x21, 0x15, 0x1f, 0xaf, 0x61, 0x20, 0x01,
+ 0x83, 0x10, 0xf4, 0x4e, 0x4c, 0xd0, 0xbf, 0xe3, 0x68, 0xea ),
+ EXPECT ( 0xbd, 0x07, 0xc2, 0x5c, 0xfd, 0x7c, 0x5e, 0x3a, 0x4e, 0xaa,
+ 0x6e, 0x2e, 0xdc, 0x5a, 0xb7, 0xea, 0x49, 0x42, 0xa0, 0x91,
+ 0x34, 0x71, 0xfd, 0xa5, 0x5c, 0x6d, 0xdd, 0x2c, 0x03, 0xef,
+ 0xa3, 0xb9, 0x64, 0x3a, 0xb3, 0xbb, 0x22, 0xf6, 0xc9, 0xf2 ) );
+
+/** SHA-1 Test 8.4 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha1_generate_fail_8_4, HMAC_DRBG_SHA1,
+ additional_input_2, ( 320 / 8 ) );
+
+/** SHA-1 Test 8.5 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha1_reseed_8_5, HMAC_DRBG_SHA1,
+ entropy_input_2, additional_input_2,
+ EXPECT ( 0x89, 0x42, 0xa5, 0x4f, 0x34, 0x9e, 0x28, 0x1b, 0x84, 0xaa,
+ 0x46, 0x95, 0x87, 0xfb, 0xdd, 0xaf, 0x9d, 0x11, 0x40, 0x82 ),
+ EXPECT ( 0x07, 0x73, 0x0e, 0x3c, 0xbf, 0xfd, 0x3c, 0xaf, 0xd7, 0xa8,
+ 0xaa, 0xe2, 0xbf, 0x01, 0xd6, 0x01, 0x43, 0x01, 0xe2, 0x4d ) );
+
+/** SHA-1 Test 8.6 : Retried second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha1_generate_8_6, HMAC_DRBG_SHA1,
+ additional_input_empty,
+ EXPECT ( 0xbd, 0xe1, 0xb4, 0x6c, 0xdc, 0x54, 0x13, 0xb3, 0xd9, 0xf7,
+ 0x35, 0xac, 0xdb, 0x80, 0xb1, 0x3c, 0x57, 0xbf, 0xe4, 0x73 ),
+ EXPECT ( 0x72, 0x5a, 0x3c, 0x78, 0x20, 0xde, 0x1a, 0x06, 0xd0, 0x95,
+ 0x81, 0x9c, 0xcf, 0x6f, 0x2c, 0x9b, 0x3a, 0x67, 0xf2, 0xce ),
+ EXPECT ( 0xd1, 0xa9, 0xc1, 0xa2, 0x2c, 0x84, 0xfc, 0x23, 0xff, 0x22,
+ 0x27, 0xef, 0x98, 0xec, 0x8b, 0xa9, 0xdf, 0x2a, 0x20, 0x9b,
+ 0xa1, 0xdb, 0x09, 0x80, 0x9f, 0x57, 0xbf, 0xea, 0xe5, 0xb3,
+ 0xe5, 0xf1, 0x46, 0xc7, 0x5f, 0x2d, 0x8d, 0xbb, 0x5e, 0x4a ) );
+
+/** SHA-256 Test 1 : Instantiation */
+HMAC_DRBG_TEST_INSTANTIATE ( sha256_instantiate_1, HMAC_DRBG_SHA256,
+ entropy_input, nonce_sha256, personalisation_string_empty,
+ EXPECT ( 0x3d, 0xda, 0x54, 0x3e, 0x7e, 0xef, 0x14, 0xf9, 0x36, 0x23,
+ 0x7b, 0xe6, 0x5d, 0x09, 0x4b, 0x4d, 0xdc, 0x96, 0x9c, 0x0b,
+ 0x2b, 0x5e, 0xaf, 0xb5, 0xd8, 0x05, 0xe8, 0x6c, 0xfa, 0x64,
+ 0xd7, 0x41 ),
+ EXPECT ( 0x2d, 0x02, 0xc2, 0xf8, 0x22, 0x51, 0x7d, 0x54, 0xb8, 0x17,
+ 0x27, 0x9a, 0x59, 0x49, 0x1c, 0x41, 0xa1, 0x98, 0x9b, 0x3e,
+ 0x38, 0x2d, 0xeb, 0xe8, 0x0d, 0x2c, 0x7f, 0x66, 0x0f, 0x44,
+ 0x76, 0xc4 ) );
+
+/** SHA-256 Test 1.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_1_1, HMAC_DRBG_SHA256,
+ additional_input_empty,
+ EXPECT ( 0xdd, 0x30, 0x95, 0x79, 0x35, 0x38, 0x02, 0xcc, 0xdd, 0x43,
+ 0x99, 0xc3, 0x69, 0x1c, 0x9d, 0xd9, 0x09, 0xdd, 0x3b, 0x2d,
+ 0xd0, 0x03, 0xcc, 0xd5, 0x9d, 0x6f, 0x08, 0xd8, 0x5f, 0x2e,
+ 0x35, 0x09 ),
+ EXPECT ( 0xa1, 0xc2, 0x0f, 0xf2, 0x70, 0xa3, 0x9d, 0x2b, 0x8d, 0x03,
+ 0xd6, 0x59, 0xb9, 0xdd, 0xd0, 0x11, 0xc2, 0xcc, 0xdf, 0x24,
+ 0x48, 0x55, 0x7e, 0xf6, 0xa1, 0xa9, 0x15, 0xd1, 0x89, 0x40,
+ 0xa6, 0x88 ),
+ EXPECT ( 0xd6, 0x7b, 0x8c, 0x17, 0x34, 0xf4, 0x6f, 0xa3, 0xf7, 0x63,
+ 0xcf, 0x57, 0xc6, 0xf9, 0xf4, 0xf2, 0xdc, 0x10, 0x89, 0xbd,
+ 0x8b, 0xc1, 0xf6, 0xf0, 0x23, 0x95, 0x0b, 0xfc, 0x56, 0x17,
+ 0x63, 0x52, 0x08, 0xc8, 0x50, 0x12, 0x38, 0xad, 0x7a, 0x44,
+ 0x00, 0xde, 0xfe, 0xe4, 0x6c, 0x64, 0x0b, 0x61, 0xaf, 0x77,
+ 0xc2, 0xd1, 0xa3, 0xbf, 0xaa, 0x90, 0xed, 0xe5, 0xd2, 0x07,
+ 0x40, 0x6e, 0x54, 0x03 ) );
+
+/** SHA-256 Test 1.2 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_1_2, HMAC_DRBG_SHA256,
+ additional_input_empty,
+ EXPECT ( 0x5c, 0xd5, 0xe5, 0x0a, 0x3e, 0x44, 0x8a, 0x07, 0xc3, 0xd2,
+ 0xf2, 0xa3, 0xf9, 0xde, 0xbc, 0xc0, 0x46, 0x5f, 0x9c, 0xf1,
+ 0x1c, 0xa1, 0x36, 0xe9, 0xb5, 0x04, 0xb4, 0xd3, 0x1c, 0x7f,
+ 0xf1, 0xb8 ),
+ EXPECT ( 0x33, 0xb3, 0x09, 0xf2, 0xff, 0x01, 0xce, 0x10, 0x4b, 0x44,
+ 0x29, 0xb6, 0x75, 0xfa, 0xfa, 0x19, 0x01, 0x1e, 0x34, 0x8b,
+ 0x28, 0x12, 0x71, 0x5a, 0x76, 0x37, 0xf6, 0xa6, 0xe6, 0x3b,
+ 0x5d, 0x57 ),
+ EXPECT ( 0x8f, 0xda, 0xec, 0x20, 0xf8, 0xb4, 0x21, 0x40, 0x70, 0x59,
+ 0xe3, 0x58, 0x89, 0x20, 0xda, 0x7e, 0xda, 0x9d, 0xce, 0x3c,
+ 0xf8, 0x27, 0x4d, 0xfa, 0x1c, 0x59, 0xc1, 0x08, 0xc1, 0xd0,
+ 0xaa, 0x9b, 0x0f, 0xa3, 0x8d, 0xa5, 0xc7, 0x92, 0x03, 0x7c,
+ 0x4d, 0x33, 0xcd, 0x07, 0x0c, 0xa7, 0xcd, 0x0c, 0x56, 0x08,
+ 0xdb, 0xa8, 0xb8, 0x85, 0x65, 0x46, 0x39, 0xde, 0x21, 0x87,
+ 0xb7, 0x4c, 0xb2, 0x63 ) );
+
+/** SHA-256 Test 2 : Instantiation */
+#define sha256_instantiate_2 sha256_instantiate_1
+
+/** SHA-256 Test 2.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_2_1, HMAC_DRBG_SHA256,
+ additional_input_1,
+ EXPECT ( 0x79, 0x1d, 0x31, 0x44, 0xb3, 0x02, 0xad, 0x6c, 0xe4, 0x32,
+ 0x41, 0x34, 0x42, 0x10, 0xaa, 0xd0, 0xd3, 0x99, 0xed, 0xb7,
+ 0xb5, 0x90, 0x6f, 0xb2, 0x51, 0xdb, 0x1c, 0xb6, 0x00, 0x04,
+ 0xea, 0x51 ),
+ EXPECT ( 0x58, 0xfd, 0x96, 0x5f, 0x4f, 0x99, 0x89, 0x3c, 0x17, 0xe6,
+ 0xa3, 0x3c, 0xb8, 0xe9, 0x04, 0x15, 0xb5, 0x16, 0xd0, 0x06,
+ 0x14, 0xa4, 0x49, 0xd4, 0x06, 0xe0, 0x3c, 0x68, 0x5b, 0xd8,
+ 0x59, 0xbd ),
+ EXPECT ( 0x41, 0x87, 0x87, 0x35, 0x81, 0x35, 0x41, 0x9b, 0x93, 0x81,
+ 0x33, 0x53, 0x53, 0x06, 0x17, 0x6a, 0xfb, 0x25, 0x1c, 0xdd,
+ 0x2b, 0xa3, 0x79, 0x88, 0x59, 0xb5, 0x66, 0xa0, 0x5c, 0xfb,
+ 0x1d, 0x68, 0x0e, 0xa9, 0x25, 0x85, 0x6d, 0x5b, 0x84, 0xd5,
+ 0x6a, 0xda, 0xe8, 0x70, 0x45, 0xa6, 0xba, 0x28, 0xd2, 0xc9,
+ 0x08, 0xab, 0x75, 0xb7, 0xcc, 0x41, 0x43, 0x1f, 0xac, 0x59,
+ 0xf3, 0x89, 0x18, 0xa3 ) );
+
+/** SHA-256 Test 2.2 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_2_2, HMAC_DRBG_SHA256,
+ additional_input_2,
+ EXPECT ( 0xe7, 0x45, 0x8f, 0xb4, 0x4a, 0x36, 0x9a, 0x65, 0x3f, 0x2f,
+ 0x8f, 0x57, 0x7b, 0xf9, 0x75, 0xc4, 0xb3, 0x62, 0xc4, 0xfe,
+ 0x61, 0x8b, 0x2f, 0x1f, 0xf6, 0x76, 0x9b, 0x13, 0xc9, 0x4d,
+ 0xec, 0xf4 ),
+ EXPECT ( 0x19, 0x33, 0x4b, 0x8c, 0x31, 0xb7, 0x49, 0x32, 0xdd, 0xd7,
+ 0xb2, 0xa4, 0x68, 0xf6, 0x43, 0x6d, 0xf9, 0x2e, 0x10, 0x0d,
+ 0x39, 0xd3, 0xac, 0xb3, 0x68, 0xc7, 0x02, 0x9c, 0xb8, 0x83,
+ 0xec, 0x89 ),
+ EXPECT ( 0x7c, 0x06, 0x7b, 0xdd, 0xca, 0x81, 0x72, 0x48, 0x23, 0xd6,
+ 0x4c, 0x69, 0x82, 0x92, 0x85, 0xbd, 0xbf, 0xf5, 0x37, 0x71,
+ 0x61, 0x02, 0xc1, 0x88, 0x2e, 0x20, 0x22, 0x50, 0xe0, 0xfa,
+ 0x5e, 0xf3, 0xa3, 0x84, 0xcd, 0x34, 0xa2, 0x0f, 0xfd, 0x1f,
+ 0xbc, 0x91, 0xe0, 0xc5, 0x32, 0xa8, 0xa4, 0x21, 0xbc, 0x4a,
+ 0xfe, 0x3c, 0xd4, 0x7f, 0x22, 0x32, 0x3e, 0xb4, 0xba, 0xe1,
+ 0xa0, 0x07, 0x89, 0x81 ) );
+
+/** SHA-256 Test 3 : Instantiation */
+HMAC_DRBG_TEST_INSTANTIATE ( sha256_instantiate_3, HMAC_DRBG_SHA256,
+ entropy_input, nonce_sha256, personalisation_string,
+ EXPECT ( 0x65, 0x67, 0x3c, 0x34, 0x8e, 0x51, 0xcf, 0xac, 0xc4, 0x10,
+ 0xbd, 0x20, 0x02, 0x49, 0xa5, 0x9a, 0x9d, 0x6b, 0xae, 0x77,
+ 0x69, 0x04, 0x27, 0x1b, 0xb1, 0xf7, 0x18, 0xda, 0x1d, 0x18,
+ 0x20, 0x42 ),
+ EXPECT ( 0xe0, 0xf9, 0x1a, 0xc9, 0x96, 0x30, 0xee, 0xe6, 0x7c, 0xf8,
+ 0x30, 0xcf, 0xd5, 0x04, 0x4f, 0xeb, 0xf5, 0x5c, 0x0c, 0x11,
+ 0x50, 0x07, 0x99, 0x7a, 0xda, 0x11, 0x29, 0x6f, 0xc4, 0x16,
+ 0x4a, 0x9a ) );
+
+/** SHA-256 Test 3.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_3_1, HMAC_DRBG_SHA256,
+ additional_input_empty,
+ EXPECT ( 0xf0, 0xb2, 0xf2, 0x42, 0xca, 0xd9, 0x92, 0xa7, 0x24, 0xf7,
+ 0xe5, 0x59, 0x1d, 0x2f, 0x3b, 0x0c, 0x21, 0x57, 0xae, 0x70,
+ 0xd5, 0x32, 0x78, 0x99, 0x40, 0xf1, 0x64, 0x45, 0x9b, 0x00,
+ 0xc7, 0x49 ),
+ EXPECT ( 0x1a, 0x03, 0xf9, 0x1c, 0x51, 0x20, 0xba, 0xca, 0x2b, 0xf6,
+ 0xc6, 0x4d, 0xd7, 0x3a, 0xb1, 0x1d, 0xf6, 0xfd, 0x3f, 0xf1,
+ 0xac, 0x3b, 0x57, 0x20, 0xa3, 0xf7, 0xfb, 0xe3, 0x9e, 0x7e,
+ 0x7f, 0xe9 ),
+ EXPECT ( 0x0d, 0xd9, 0xc8, 0x55, 0x89, 0xf3, 0x57, 0xc3, 0x89, 0xd6,
+ 0xaf, 0x8d, 0xe9, 0xd7, 0x34, 0xa9, 0x17, 0xc7, 0x71, 0xef,
+ 0x2d, 0x88, 0x16, 0xb9, 0x82, 0x59, 0x6e, 0xd1, 0x2d, 0xb4,
+ 0x5d, 0x73, 0x4a, 0x62, 0x68, 0x08, 0x35, 0xc0, 0x2f, 0xda,
+ 0x66, 0xb0, 0x8e, 0x1a, 0x36, 0x9a, 0xe2, 0x18, 0xf2, 0x6d,
+ 0x52, 0x10, 0xad, 0x56, 0x42, 0x48, 0x87, 0x2d, 0x7a, 0x28,
+ 0x78, 0x41, 0x59, 0xc3 ) );
+
+/** SHA-256 Test 3.2 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_3_2, HMAC_DRBG_SHA256,
+ additional_input_empty,
+ EXPECT ( 0x5c, 0x0d, 0xec, 0x09, 0x37, 0x08, 0xc1, 0x7c, 0xa7, 0x6b,
+ 0x57, 0xc0, 0xcb, 0x60, 0xcf, 0x88, 0x9d, 0xcc, 0x47, 0xad,
+ 0x10, 0xbd, 0x64, 0xbc, 0x6a, 0x14, 0xb2, 0x3f, 0x20, 0x26,
+ 0x07, 0x8a ),
+ EXPECT ( 0x45, 0x67, 0x52, 0xa5, 0x11, 0xb8, 0x48, 0xbd, 0x05, 0xf1,
+ 0x81, 0x9b, 0x9f, 0x6b, 0x15, 0x42, 0xc7, 0xd5, 0xec, 0xf9,
+ 0x32, 0x73, 0x39, 0x26, 0x7a, 0x0c, 0x77, 0x23, 0x5b, 0x87,
+ 0xdc, 0x5a ),
+ EXPECT ( 0x46, 0xb4, 0xf4, 0x75, 0x6a, 0xe7, 0x15, 0xe0, 0xe5, 0x16,
+ 0x81, 0xab, 0x29, 0x32, 0xde, 0x15, 0x23, 0xbe, 0x5d, 0x13,
+ 0xba, 0xf0, 0xf4, 0x58, 0x8b, 0x11, 0xfe, 0x37, 0x2f, 0xda,
+ 0x37, 0xab, 0xe3, 0x68, 0x31, 0x73, 0x41, 0xbc, 0x8b, 0xa9,
+ 0x1f, 0xc5, 0xd8, 0x5b, 0x7f, 0xb8, 0xca, 0x8f, 0xbc, 0x30,
+ 0x9a, 0x75, 0x8f, 0xd6, 0xfc, 0xa9, 0xdf, 0x43, 0xc7, 0x66,
+ 0x0b, 0x22, 0x13, 0x22 ) );
+
+/** SHA-256 Test 4 : Instantiation */
+#define sha256_instantiate_4 sha256_instantiate_3
+
+/** SHA-256 Test 4.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_4_1, HMAC_DRBG_SHA256,
+ additional_input_1,
+ EXPECT ( 0x57, 0x2c, 0x03, 0x74, 0xc1, 0xa1, 0x01, 0x25, 0xbf, 0xa6,
+ 0xae, 0xcd, 0x7c, 0xeb, 0xfe, 0x32, 0xf7, 0x52, 0xc3, 0xfb,
+ 0x31, 0x67, 0x31, 0xb7, 0xcf, 0xdb, 0xde, 0xc2, 0x63, 0x56,
+ 0x93, 0x2b ),
+ EXPECT ( 0xd6, 0x8b, 0xf0, 0x41, 0xf3, 0xeb, 0x50, 0x88, 0x08, 0x8d,
+ 0x8b, 0x8e, 0x71, 0x2c, 0x36, 0xae, 0x95, 0x83, 0xbb, 0x08,
+ 0xfd, 0x1f, 0x90, 0x34, 0xa4, 0xe9, 0x42, 0xe9, 0xa6, 0x74,
+ 0x7c, 0xe7 ),
+ EXPECT ( 0x14, 0x78, 0xf2, 0x9e, 0x94, 0xb0, 0x2c, 0xb4, 0x0d, 0x3a,
+ 0xab, 0x86, 0x24, 0x55, 0x57, 0xce, 0x13, 0xa8, 0xca, 0x2f,
+ 0xdb, 0x65, 0x7d, 0x98, 0xef, 0xc1, 0x92, 0x34, 0x6b, 0x9f,
+ 0xac, 0x33, 0xea, 0x58, 0xad, 0xa2, 0xcc, 0xa4, 0x32, 0xcc,
+ 0xde, 0xfb, 0xcd, 0xaa, 0x8b, 0x82, 0xf5, 0x53, 0xef, 0x96,
+ 0x61, 0x34, 0xe2, 0xcd, 0x13, 0x9f, 0x15, 0xf0, 0x1c, 0xad,
+ 0x56, 0x85, 0x65, 0xa8 ) );
+
+/** SHA-256 Test 4.2 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_4_2, HMAC_DRBG_SHA256,
+ additional_input_2,
+ EXPECT ( 0x28, 0x2e, 0x07, 0x34, 0x80, 0x80, 0x93, 0x75, 0x58, 0xb1,
+ 0x39, 0x2e, 0x95, 0xab, 0x91, 0xe7, 0xc1, 0xf6, 0x22, 0xb2,
+ 0x4f, 0xfb, 0x87, 0x20, 0xa5, 0xf0, 0xa5, 0xe0, 0x75, 0x50,
+ 0xc7, 0xc2 ),
+ EXPECT ( 0xdf, 0xc3, 0xbd, 0xb5, 0xf3, 0xbc, 0xf1, 0xaa, 0x68, 0x29,
+ 0x8e, 0x79, 0x0d, 0x72, 0x0a, 0x67, 0xa7, 0x6e, 0x31, 0xb9,
+ 0x2b, 0x9b, 0x35, 0xa8, 0xe5, 0x47, 0x1b, 0xb1, 0x7e, 0x30,
+ 0x3c, 0x6b ),
+ EXPECT ( 0x49, 0x7c, 0x7a, 0x16, 0xe8, 0x8a, 0x64, 0x11, 0xf8, 0xfc,
+ 0xe1, 0x0e, 0xf5, 0x67, 0x63, 0xc6, 0x10, 0x25, 0x80, 0x1d,
+ 0x8f, 0x51, 0xa7, 0x43, 0x52, 0xd6, 0x82, 0xcc, 0x23, 0xa0,
+ 0xa8, 0xe6, 0x73, 0xca, 0xe0, 0x32, 0x28, 0x93, 0x90, 0x64,
+ 0x7d, 0xc6, 0x83, 0xb7, 0x34, 0x28, 0x85, 0xd6, 0xb7, 0x6a,
+ 0xb1, 0xda, 0x69, 0x6d, 0x3e, 0x97, 0xe2, 0x2d, 0xff, 0xdd,
+ 0xff, 0xfd, 0x8d, 0xf0 ) );
+
+/** SHA-256 Test 5 : Instantiation */
+#define sha256_instantiate_5 sha256_instantiate_1
+
+/** SHA-256 Test 5.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha256_generate_fail_5_1, HMAC_DRBG_SHA256,
+ additional_input_empty, ( 512 / 8 ) );
+
+/** SHA-256 Test 5.2 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha256_reseed_5_2, HMAC_DRBG_SHA256,
+ entropy_input_1, additional_input_empty,
+ EXPECT ( 0xb8, 0x40, 0x07, 0xe3, 0xe2, 0x7f, 0x34, 0xf9, 0xa7, 0x82,
+ 0x0b, 0x7a, 0xb5, 0x9b, 0xbe, 0xfc, 0xd0, 0xc4, 0xac, 0xae,
+ 0xde, 0x4b, 0x0b, 0x36, 0xb1, 0x47, 0xb8, 0x97, 0x79, 0xfd,
+ 0x74, 0x9d ),
+ EXPECT ( 0xa7, 0x2b, 0x8f, 0xee, 0x92, 0x39, 0x2f, 0x0a, 0x9d, 0x2d,
+ 0x61, 0xbf, 0x09, 0xa4, 0xdf, 0xcc, 0x9d, 0xe6, 0x9a, 0x16,
+ 0xa5, 0xf1, 0x50, 0x22, 0x4c, 0x3e, 0xf6, 0x04, 0x2d, 0x15,
+ 0x21, 0xfc ) );
+
+/** SHA-256 Test 5.3 : Retried first call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_5_3, HMAC_DRBG_SHA256,
+ additional_input_empty,
+ EXPECT ( 0x43, 0x48, 0xaf, 0x84, 0x20, 0x84, 0x2f, 0xa0, 0x77, 0xb9,
+ 0xd3, 0xdb, 0xa8, 0xdc, 0xe9, 0xb3, 0xe1, 0xdf, 0x73, 0x4f,
+ 0xfc, 0xe1, 0xbe, 0xa5, 0xb9, 0xe2, 0xb1, 0x54, 0xdc, 0x5e,
+ 0xc6, 0x15 ),
+ EXPECT ( 0xd2, 0xc1, 0xac, 0x27, 0x88, 0x5d, 0x43, 0x32, 0x76, 0x71,
+ 0x31, 0x46, 0x32, 0xea, 0x60, 0x43, 0x3c, 0xca, 0x72, 0x73,
+ 0x04, 0x56, 0x9e, 0xa7, 0xd4, 0x71, 0xfe, 0xa7, 0xdb, 0x7d,
+ 0x31, 0x5d ),
+ EXPECT ( 0xfa, 0xbd, 0x0a, 0xe2, 0x5c, 0x69, 0xdc, 0x2e, 0xfd, 0xef,
+ 0xb7, 0xf2, 0x0c, 0x5a, 0x31, 0xb5, 0x7a, 0xc9, 0x38, 0xab,
+ 0x77, 0x1a, 0xa1, 0x9b, 0xf8, 0xf5, 0xf1, 0x46, 0x8f, 0x66,
+ 0x5c, 0x93, 0x8c, 0x9a, 0x1a, 0x5d, 0xf0, 0x62, 0x8a, 0x56,
+ 0x90, 0xf1, 0x5a, 0x1a, 0xd8, 0xa6, 0x13, 0xf3, 0x1b, 0xbd,
+ 0x65, 0xee, 0xad, 0x54, 0x57, 0xd5, 0xd2, 0x69, 0x47, 0xf2,
+ 0x9f, 0xe9, 0x1a, 0xa7 ) );
+
+/** SHA-256 Test 5.4 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha256_generate_fail_5_4, HMAC_DRBG_SHA256,
+ additional_input_empty, ( 512 / 8 ) );
+
+/** SHA-256 Test 5.5 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha256_reseed_5_5, HMAC_DRBG_SHA256,
+ entropy_input_2, additional_input_empty,
+ EXPECT ( 0xbf, 0xa0, 0x2c, 0xe7, 0xe9, 0x2d, 0xe9, 0x2b, 0x18, 0x24,
+ 0x28, 0x86, 0x89, 0x0e, 0x58, 0x6f, 0x83, 0x69, 0x06, 0xac,
+ 0xe9, 0xe5, 0x54, 0xf1, 0xb0, 0xed, 0x63, 0x57, 0x3c, 0xb8,
+ 0xb5, 0x03 ),
+ EXPECT ( 0xd3, 0x24, 0x03, 0xee, 0xa9, 0xdc, 0xe1, 0x61, 0x6e, 0x4e,
+ 0x11, 0x55, 0xb9, 0x23, 0xd8, 0x84, 0x2c, 0xc6, 0xe7, 0x84,
+ 0xc6, 0x7a, 0x93, 0x85, 0xb2, 0xa6, 0x37, 0xf1, 0x02, 0xfa,
+ 0x45, 0xd5 ) );
+
+/** SHA-256 Test 5.6 : Retried second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_5_6, HMAC_DRBG_SHA256,
+ additional_input_empty,
+ EXPECT ( 0x81, 0x21, 0xf7, 0x76, 0x4c, 0x08, 0x1e, 0xe9, 0xd1, 0x17,
+ 0x1e, 0xd1, 0x87, 0xba, 0xe0, 0x88, 0x95, 0xca, 0xe2, 0x30,
+ 0xd0, 0xa2, 0x5e, 0x37, 0x39, 0xc5, 0x7d, 0x54, 0x16, 0x10,
+ 0x9b, 0x82 ),
+ EXPECT ( 0x37, 0x84, 0x97, 0x7c, 0xc0, 0xe5, 0x9f, 0xbc, 0x9c, 0xda,
+ 0x4e, 0x11, 0x92, 0x47, 0x5c, 0x6e, 0xfa, 0xf8, 0x07, 0x20,
+ 0x19, 0x86, 0x21, 0x22, 0xcb, 0x6b, 0xce, 0xaa, 0xcc, 0x4a,
+ 0x17, 0x5e ),
+ EXPECT ( 0x6b, 0xd9, 0x25, 0xb0, 0xe1, 0xc2, 0x32, 0xef, 0xd6, 0x7c,
+ 0xcd, 0x84, 0xf7, 0x22, 0xe9, 0x27, 0xec, 0xb4, 0x6a, 0xb2,
+ 0xb7, 0x40, 0x01, 0x47, 0x77, 0xaf, 0x14, 0xba, 0x0b, 0xbf,
+ 0x53, 0xa4, 0x5b, 0xdb, 0xb6, 0x2b, 0x3f, 0x7d, 0x0b, 0x9c,
+ 0x8e, 0xea, 0xd0, 0x57, 0xc0, 0xec, 0x75, 0x4e, 0xf8, 0xb5,
+ 0x3e, 0x60, 0xa1, 0xf4, 0x34, 0xf0, 0x59, 0x46, 0xa8, 0xb6,
+ 0x86, 0xaf, 0xbc, 0x7a ) );
+
+/** SHA-256 Test 6 : Instantiate */
+#define sha256_instantiate_6 sha256_instantiate_1
+
+/** SHA-256 Test 6.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha256_generate_fail_6_1, HMAC_DRBG_SHA256,
+ additional_input_1, ( 512 / 8 ) );
+
+/** SHA-256 Test 6.2 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha256_reseed_6_2, HMAC_DRBG_SHA256,
+ entropy_input_1, additional_input_1,
+ EXPECT ( 0xc1, 0x25, 0xea, 0x99, 0x75, 0x8e, 0xbb, 0x9a, 0x6f, 0x69,
+ 0xae, 0x31, 0x2a, 0xc2, 0x04, 0xb5, 0x94, 0xc0, 0x0a, 0xb6,
+ 0x8b, 0x81, 0x6e, 0x3a, 0x52, 0x12, 0x8e, 0x02, 0x78, 0xa5,
+ 0x84, 0xac ),
+ EXPECT ( 0xb2, 0xcb, 0x2b, 0x89, 0x12, 0x3f, 0x5b, 0x4a, 0xf5, 0x87,
+ 0xb8, 0xf6, 0xbd, 0xc5, 0x42, 0x7a, 0x99, 0x14, 0x19, 0xd3,
+ 0x53, 0x07, 0x7c, 0x68, 0x5e, 0x70, 0x7a, 0xcd, 0xf8, 0xe9,
+ 0xfd, 0xa9 ) );
+
+/** SHA-256 Test 6.3 : Retried first call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_6_3, HMAC_DRBG_SHA256,
+ additional_input_empty,
+ EXPECT ( 0xc6, 0xed, 0x8f, 0xed, 0x71, 0x57, 0xa4, 0xd0, 0x9e, 0xa1,
+ 0xdd, 0xe8, 0x94, 0x6b, 0x54, 0x43, 0x3e, 0xcc, 0x54, 0x49,
+ 0xa4, 0xa3, 0x52, 0xaf, 0x45, 0x76, 0x4e, 0xe6, 0x73, 0x4b,
+ 0xbb, 0x04 ),
+ EXPECT ( 0xeb, 0xc7, 0x75, 0x25, 0x6b, 0xb7, 0x81, 0x24, 0x1e, 0x9c,
+ 0x70, 0xbb, 0xcf, 0x73, 0x2b, 0xdc, 0x90, 0xad, 0x10, 0xd9,
+ 0xdd, 0x3a, 0x89, 0x6e, 0xcc, 0x12, 0xb9, 0x2f, 0xfb, 0x63,
+ 0x45, 0xab ),
+ EXPECT ( 0x08, 0x5d, 0x57, 0xaf, 0x6b, 0xab, 0xcf, 0x2b, 0x9a, 0xee,
+ 0xf3, 0x87, 0xd5, 0x31, 0x65, 0x0e, 0x6a, 0x50, 0x5c, 0x54,
+ 0x40, 0x6a, 0xb3, 0x7a, 0x52, 0x89, 0x9e, 0x0e, 0xca, 0xb3,
+ 0x63, 0x2b, 0x7a, 0x06, 0x8a, 0x28, 0x14, 0xc6, 0xdf, 0x6a,
+ 0xe5, 0x32, 0xb6, 0x58, 0xd0, 0xd9, 0x74, 0x1c, 0x84, 0x77,
+ 0x5f, 0xee, 0x45, 0xb6, 0x84, 0xcd, 0xbd, 0xc2, 0x5f, 0xbc,
+ 0xb4, 0xd8, 0xf3, 0x10 ) );
+
+/** SHA-256 Test 6.4 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha256_generate_fail_6_4, HMAC_DRBG_SHA256,
+ additional_input_2, ( 512 / 8 ) );
+
+/** SHA-256 Test 6.5 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha256_reseed_6_5, HMAC_DRBG_SHA256,
+ entropy_input_2, additional_input_2,
+ EXPECT ( 0xfc, 0x51, 0xda, 0x84, 0xf9, 0x69, 0x6b, 0xcc, 0x84, 0xc8,
+ 0xf2, 0xac, 0xb9, 0x24, 0xbc, 0xdf, 0x72, 0xf8, 0x2e, 0xa2,
+ 0xca, 0x64, 0x3f, 0x08, 0x3b, 0x0c, 0x16, 0xc3, 0x63, 0x4e,
+ 0xfc, 0x62 ),
+ EXPECT ( 0xb9, 0x74, 0xe4, 0x37, 0x0a, 0xd5, 0x76, 0xbb, 0x99, 0xc4,
+ 0xe4, 0x9e, 0xa6, 0x80, 0xbf, 0xf9, 0x8d, 0xe9, 0xe1, 0x2f,
+ 0xec, 0xd0, 0x13, 0xde, 0xd4, 0x3c, 0x80, 0xf6, 0x9a, 0x7a,
+ 0xde, 0x8a ) );
+
+/** SHA-256 Test 6.6 : Retried second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_6_6, HMAC_DRBG_SHA256,
+ additional_input_empty,
+ EXPECT ( 0x56, 0xa2, 0xb4, 0x46, 0x32, 0xcb, 0x8f, 0xc3, 0xa6, 0x40,
+ 0x09, 0xbf, 0xd6, 0xec, 0x95, 0xe5, 0x6c, 0xef, 0x8e, 0x7c,
+ 0x91, 0x2a, 0xa8, 0x2b, 0x16, 0xf6, 0x14, 0x91, 0x5d, 0x9c,
+ 0xd6, 0xe3 ),
+ EXPECT ( 0xb5, 0xb3, 0x96, 0xa0, 0x15, 0x76, 0xb0, 0xfe, 0x42, 0xf4,
+ 0x08, 0x44, 0x55, 0x6c, 0x4c, 0xf4, 0xb6, 0x80, 0x4c, 0x94,
+ 0xde, 0x9d, 0x62, 0x38, 0xf1, 0xf7, 0xe7, 0xaf, 0x5c, 0x72,
+ 0x57, 0xf3 ),
+ EXPECT ( 0x9b, 0x21, 0x9f, 0xd9, 0x0d, 0xe2, 0xa0, 0x8e, 0x49, 0x34,
+ 0x05, 0xcf, 0x87, 0x44, 0x17, 0xb5, 0x82, 0x67, 0x70, 0xf3,
+ 0x94, 0x48, 0x15, 0x55, 0xdc, 0x66, 0x8a, 0xcd, 0x96, 0xb9,
+ 0xa3, 0xe5, 0x6f, 0x9d, 0x2c, 0x32, 0x5e, 0x26, 0xd4, 0x7c,
+ 0x1d, 0xfc, 0xfc, 0x8f, 0xbf, 0x86, 0x12, 0x6f, 0x40, 0xa1,
+ 0xe6, 0x39, 0x60, 0xf6, 0x27, 0x49, 0x34, 0x2e, 0xcd, 0xb7,
+ 0x1b, 0x24, 0x0d, 0xc6 ) );
+
+/** SHA-256 Test 7 : Instantiation */
+#define sha256_instantiate_7 sha256_instantiate_3
+
+/** SHA-256 Test 7.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha256_generate_fail_7_1, HMAC_DRBG_SHA256,
+ additional_input_empty, ( 512 / 8 ) );
+
+/** SHA-256 Test 7.2 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha256_reseed_7_2, HMAC_DRBG_SHA256,
+ entropy_input_1, additional_input_empty,
+ EXPECT ( 0x44, 0x76, 0xc6, 0xd1, 0x1f, 0xc3, 0x5d, 0x44, 0x09, 0xd9,
+ 0x03, 0x2e, 0x45, 0x3b, 0x0f, 0x0d, 0xc3, 0x31, 0x4d, 0xb8,
+ 0x62, 0xcb, 0xdb, 0x60, 0x9c, 0x56, 0x02, 0x20, 0x8d, 0x4c,
+ 0x88, 0xd8 ),
+ EXPECT ( 0x95, 0xef, 0x78, 0x5a, 0x61, 0xc2, 0xf7, 0xb3, 0x6b, 0xc5,
+ 0x96, 0xba, 0x4b, 0xa2, 0x08, 0xa5, 0x2c, 0x6d, 0xc2, 0x03,
+ 0x63, 0x6d, 0x8f, 0x17, 0x87, 0x45, 0x3b, 0x85, 0x2b, 0x7e,
+ 0x49, 0xec ) );
+
+/** SHA-256 Test 7.3 : Retried first call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_7_3, HMAC_DRBG_SHA256,
+ additional_input_empty,
+ EXPECT ( 0x0d, 0xf9, 0x11, 0x0e, 0x2f, 0x22, 0x58, 0x98, 0x24, 0xa9,
+ 0x47, 0x6c, 0x8e, 0x32, 0x08, 0x8e, 0x51, 0xa0, 0xda, 0x36,
+ 0x63, 0x3f, 0x8c, 0xd1, 0xf7, 0x54, 0x7d, 0xff, 0x69, 0x6e,
+ 0x4b, 0x29 ),
+ EXPECT ( 0xc0, 0xe3, 0xc8, 0xed, 0x5a, 0x8b, 0x57, 0x9e, 0x3f, 0xef,
+ 0x9d, 0xf3, 0xb7, 0xc2, 0xc2, 0x12, 0x98, 0x07, 0x17, 0xcc,
+ 0x91, 0xae, 0x18, 0x66, 0x45, 0xfa, 0xbb, 0x2c, 0xc7, 0x84,
+ 0xd5, 0xd7 ),
+ EXPECT ( 0xd8, 0xb6, 0x71, 0x30, 0x71, 0x41, 0x94, 0xff, 0xe5, 0xb2,
+ 0xa3, 0x5d, 0xbc, 0xd5, 0xe1, 0xa2, 0x99, 0x42, 0xad, 0x5c,
+ 0x68, 0xf3, 0xde, 0xb9, 0x4a, 0xdd, 0x9e, 0x9e, 0xba, 0xd8,
+ 0x60, 0x67, 0xed, 0xf0, 0x49, 0x15, 0xfb, 0x40, 0xc3, 0x91,
+ 0xea, 0xe7, 0x0c, 0x65, 0x9e, 0xaa, 0xe7, 0xef, 0x11, 0xa3,
+ 0xd4, 0x6a, 0x5b, 0x08, 0x5e, 0xdd, 0x90, 0xcc, 0x72, 0xce,
+ 0xa9, 0x89, 0x21, 0x0b ) );
+
+/** SHA-256 Test 7.4 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha256_generate_fail_7_4, HMAC_DRBG_SHA256,
+ additional_input_empty, ( 512 / 8 ) );
+
+/** SHA-256 Test 7.5 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha256_reseed_7_5, HMAC_DRBG_SHA256,
+ entropy_input_2, additional_input_empty,
+ EXPECT ( 0x3d, 0x77, 0x63, 0xe5, 0x30, 0x3d, 0xb5, 0x4b, 0xe2, 0x05,
+ 0x44, 0xa8, 0x1e, 0x9f, 0x00, 0xca, 0xdc, 0xfc, 0x1c, 0xb2,
+ 0x8d, 0xec, 0xb9, 0xcf, 0xc6, 0x99, 0xf6, 0x1d, 0xba, 0xf8,
+ 0x80, 0x21 ),
+ EXPECT ( 0xfe, 0xbc, 0x02, 0x79, 0xb7, 0x71, 0x0d, 0xec, 0x5c, 0x06,
+ 0x7e, 0xbe, 0xfa, 0x06, 0x8e, 0x4b, 0x59, 0x67, 0x49, 0x1b,
+ 0x7e, 0xef, 0x94, 0x75, 0x83, 0x50, 0x6d, 0x04, 0x97, 0xce,
+ 0x67, 0xba ) );
+
+/** SHA-256 Test 7.6 : Retried second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_7_6, HMAC_DRBG_SHA256,
+ additional_input_empty,
+ EXPECT ( 0x2d, 0x21, 0xac, 0x94, 0x99, 0x2f, 0xd8, 0x2b, 0x09, 0x80,
+ 0xd3, 0xd5, 0x95, 0x51, 0xb9, 0xd0, 0x7c, 0x8d, 0x54, 0xb2,
+ 0x52, 0xb6, 0x16, 0x28, 0x93, 0x44, 0xf8, 0xac, 0x86, 0x9e,
+ 0xd3, 0x5b ),
+ EXPECT ( 0x61, 0x0c, 0x34, 0xcd, 0xbf, 0x6f, 0x75, 0x33, 0x54, 0x7f,
+ 0x23, 0x32, 0xea, 0xc5, 0x7e, 0xe3, 0x1e, 0x72, 0x4f, 0xb2,
+ 0x92, 0x55, 0x56, 0x6b, 0x59, 0x78, 0x33, 0x16, 0x6c, 0xd0,
+ 0x39, 0x9f ),
+ EXPECT ( 0x8b, 0xba, 0x71, 0xc2, 0x58, 0x3f, 0x25, 0x30, 0xc2, 0x59,
+ 0xc9, 0x07, 0x84, 0xa5, 0x9a, 0xc4, 0x4d, 0x1c, 0x80, 0x56,
+ 0x91, 0x7c, 0xcf, 0x38, 0x87, 0x88, 0x10, 0x2d, 0x73, 0x82,
+ 0x4c, 0x6c, 0x11, 0xd5, 0xd6, 0x3b, 0xe1, 0xf0, 0x10, 0x17,
+ 0xd8, 0x84, 0xcd, 0x69, 0xd9, 0x33, 0x4b, 0x9e, 0xbc, 0x01,
+ 0xe7, 0xbd, 0x8f, 0xdf, 0x2a, 0x8e, 0x52, 0x57, 0x22, 0x93,
+ 0xdc, 0x21, 0xc0, 0xe1 ) );
+
+/** SHA-256 Test 8 : Instantiate */
+#define sha256_instantiate_8 sha256_instantiate_3
+
+/** SHA-256 Test 8.1 : First call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha256_generate_fail_8_1, HMAC_DRBG_SHA256,
+ additional_input_1, ( 512 / 8 ) );
+
+/** SHA-256 Test 8.2 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha256_reseed_8_2, HMAC_DRBG_SHA256,
+ entropy_input_1, additional_input_1,
+ EXPECT ( 0xb3, 0x81, 0x38, 0x8c, 0x1d, 0x7c, 0xfd, 0x56, 0x59, 0x30,
+ 0x99, 0x3b, 0xd9, 0x26, 0x90, 0x66, 0x50, 0x88, 0xd9, 0xb8,
+ 0x39, 0x96, 0x9b, 0x87, 0xf1, 0x6d, 0xb6, 0xdf, 0x4e, 0x43,
+ 0x00, 0xd7 ),
+ EXPECT ( 0xfa, 0x04, 0x25, 0x64, 0x00, 0xe3, 0x42, 0xe6, 0x55, 0xf4,
+ 0x33, 0x26, 0x94, 0xe3, 0xb2, 0x4c, 0x04, 0xfb, 0x85, 0xbf,
+ 0x87, 0x80, 0x21, 0xe4, 0x52, 0xe7, 0x3b, 0x8f, 0x46, 0xd4,
+ 0xbd, 0xc6 ) );
+
+/** SHA-256 Test 8.3 : Retried first call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_8_3, HMAC_DRBG_SHA256,
+ additional_input_empty,
+ EXPECT ( 0xd4, 0x1f, 0x6f, 0x33, 0x65, 0x82, 0x21, 0x70, 0x50, 0xb1,
+ 0xf6, 0x59, 0x28, 0xfd, 0x6e, 0x94, 0xcb, 0xc9, 0x45, 0x68,
+ 0xfe, 0x3b, 0x6b, 0x53, 0x38, 0x9e, 0x1e, 0x3a, 0x5b, 0x49,
+ 0xe1, 0x01 ),
+ EXPECT ( 0xa6, 0x55, 0xc9, 0xe7, 0xd1, 0x33, 0xf1, 0xcd, 0x8b, 0x11,
+ 0x61, 0xf2, 0x7d, 0x54, 0xe7, 0x5a, 0x7e, 0x7c, 0x80, 0x42,
+ 0xbf, 0x74, 0xd4, 0x7f, 0x9f, 0xfd, 0x60, 0xe2, 0x45, 0xeb,
+ 0xa5, 0x7e ),
+ EXPECT ( 0x44, 0xd7, 0x8b, 0xbc, 0x3e, 0xb6, 0x7c, 0x59, 0xc2, 0x2f,
+ 0x6c, 0x31, 0x00, 0x3d, 0x21, 0x2a, 0x78, 0x37, 0xcc, 0xd8,
+ 0x4c, 0x43, 0x8b, 0x55, 0x15, 0x0f, 0xd0, 0x13, 0xa8, 0xa7,
+ 0x8f, 0xe8, 0xed, 0xea, 0x81, 0xc6, 0x72, 0xe4, 0xb8, 0xdd,
+ 0xc8, 0x18, 0x38, 0x86, 0xe6, 0x9c, 0x2e, 0x17, 0x7d, 0xf5,
+ 0x74, 0xc1, 0xf1, 0x90, 0xdf, 0x27, 0x18, 0x50, 0xf8, 0xce,
+ 0x55, 0xef, 0x20, 0xb8 ) );
+
+/** SHA-256 Test 8.4 : Second call to Generate */
+HMAC_DRBG_TEST_GENERATE_FAIL ( sha256_generate_fail_8_4, HMAC_DRBG_SHA256,
+ additional_input_2, ( 512 / 8 ) );
+
+/** SHA-256 Test 8.5 : Reseed */
+HMAC_DRBG_TEST_RESEED ( sha256_reseed_8_5, HMAC_DRBG_SHA256,
+ entropy_input_2, additional_input_2,
+ EXPECT ( 0xfb, 0xa8, 0x05, 0x45, 0x3e, 0x3c, 0x9a, 0x73, 0x64, 0x58,
+ 0x5c, 0xed, 0xbc, 0xd2, 0x92, 0x30, 0xfb, 0xc9, 0x3d, 0x6f,
+ 0x12, 0x9d, 0x21, 0xed, 0xdd, 0xf6, 0x61, 0x3b, 0x3a, 0x8f,
+ 0xf2, 0x83 ),
+ EXPECT ( 0x83, 0x64, 0x7a, 0x33, 0x8c, 0x15, 0x3c, 0xba, 0xf0, 0xe4,
+ 0x9a, 0x54, 0xa4, 0x4f, 0xea, 0x66, 0x70, 0xcf, 0xd7, 0xc1,
+ 0x71, 0x4d, 0x4a, 0xb3, 0x5f, 0x11, 0x12, 0x3d, 0xf2, 0x7b,
+ 0x69, 0xcf ) );
+
+/** SHA-256 Test 8.6 : Retried second call to Generate */
+HMAC_DRBG_TEST_GENERATE ( sha256_generate_8_6, HMAC_DRBG_SHA256,
+ additional_input_empty,
+ EXPECT ( 0xae, 0x59, 0xc7, 0x0a, 0x7c, 0x60, 0xed, 0x49, 0x83, 0x78,
+ 0xea, 0x84, 0x5b, 0xe9, 0x7d, 0x8f, 0xf8, 0x81, 0xe0, 0xea,
+ 0x37, 0x2e, 0x26, 0x5f, 0xa6, 0x72, 0x84, 0x29, 0x3e, 0x1a,
+ 0x46, 0xac ),
+ EXPECT ( 0xe2, 0xf0, 0x4d, 0xe3, 0xce, 0x21, 0x79, 0x61, 0xae, 0x2b,
+ 0x2d, 0x20, 0xa7, 0xba, 0x7c, 0x6c, 0x82, 0x0b, 0x5b, 0x14,
+ 0x92, 0x6e, 0x59, 0x56, 0xae, 0x6d, 0xfa, 0x2e, 0xd1, 0xd6,
+ 0x39, 0x93 ),
+ EXPECT ( 0x91, 0x77, 0x80, 0xdc, 0x0c, 0xe9, 0x98, 0x9f, 0xee, 0x6c,
+ 0x08, 0x06, 0xd6, 0xda, 0x12, 0x3a, 0x18, 0x25, 0x29, 0x47,
+ 0x58, 0xd4, 0xe1, 0xb5, 0x82, 0x68, 0x72, 0x31, 0x78, 0x0a,
+ 0x2a, 0x9c, 0x33, 0xf1, 0xd1, 0x56, 0xcc, 0xad, 0x32, 0x77,
+ 0x64, 0xb2, 0x9a, 0x4c, 0xb2, 0x69, 0x01, 0x77, 0xae, 0x96,
+ 0xef, 0x9e, 0xe9, 0x2a, 0xd0, 0xc3, 0x40, 0xba, 0x0f, 0xd1,
+ 0x20, 0x3c, 0x02, 0xc6 ) );
+
+/**
+ * Force a "reseed required" state
+ *
+ * @v state HMAC_DRBG internal state
+ */
+static inline void force_reseed_required ( struct hmac_drbg_state *state ) {
+ state->reseed_counter = ( HMAC_DRBG_RESEED_INTERVAL + 1 );
+}
+
+/**
+ * Perform HMAC_DRBG self-test
+ *
+ */
+static void hmac_drbg_test_exec ( void ) {
+ struct hmac_drbg_state state;
+
+ /*
+ * IMPORTANT NOTE
+ *
+ * The NIST test vector set includes several calls to
+ * HMAC_DRBG_Generate() that are expected to fail with a
+ * status of "Reseed required". The pattern seems to be that
+ * when prediction resistance is requested, any call to
+ * HMAC_DRBG_Generate() is at first expected to fail. After
+ * an explicit reseeding, the call to HMAC_DRBG_Generate() is
+ * retried, and on this second time it is expected to succeed.
+ *
+ * This pattern does not match the specifications for
+ * HMAC_DRBG_Generate(): neither HMAC_DRBG_Generate_algorithm
+ * (defined in ANS X9.82 Part 3-2007 Section 10.2.2.2.5 (NIST
+ * SP 800-90 Section 10.1.2.5)) nor the higher-level wrapper
+ * Generate_function defined in ANS X9.82 Part 3-2007 Section
+ * 9.4 (NIST SP 800-90 Section 9.3)) can possibly exhibit this
+ * behaviour:
+ *
+ * a) HMAC_DRBG_Generate_algorithm can return a "reseed
+ * required" status only as a result of the test
+ *
+ * "1. If reseed_counter > reseed_interval, then return
+ * an indication that a reseed is required."
+ *
+ * Since the reseed interval is independent of any request
+ * for prediction resistance, and since the reseed interval
+ * is not specified as part of the NIST test vector set,
+ * then this cannot be the source of the "Reseed required"
+ * failure expected by the NIST test vector set.
+ *
+ * b) Generate_function cannot return a "reseed required"
+ * status under any circumstances. If the underlying
+ * HMAC_DRBG_Generate_algorithm call returns "reseed
+ * required", then Generate_function will automatically
+ * reseed and try again.
+ *
+ * To produce the behaviour expected by the NIST test vector
+ * set, we therefore contrive to produce a "reseed required"
+ * state where necessary by setting the reseed_counter to
+ * greater than the reseed_interval.
+ */
+
+ /* SHA-1 Test 1 */
+ instantiate_ok ( &state, &sha1_instantiate_1 );
+ generate_ok ( &state, &sha1_generate_1_1 );
+ generate_ok ( &state, &sha1_generate_1_2 );
+
+ /* SHA-1 Test 2 */
+ instantiate_ok ( &state, &sha1_instantiate_2 );
+ generate_ok ( &state, &sha1_generate_2_1 );
+ generate_ok ( &state, &sha1_generate_2_2 );
+
+ /* SHA-1 Test 3 */
+ instantiate_ok ( &state, &sha1_instantiate_3 );
+ generate_ok ( &state, &sha1_generate_3_1 );
+ generate_ok ( &state, &sha1_generate_3_2 );
+
+ /* SHA-1 Test 4 */
+ instantiate_ok ( &state, &sha1_instantiate_4 );
+ generate_ok ( &state, &sha1_generate_4_1 );
+ generate_ok ( &state, &sha1_generate_4_2 );
+
+ /* SHA-1 Test 5 */
+ instantiate_ok ( &state, &sha1_instantiate_5 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha1_generate_fail_5_1 );
+ reseed_ok ( &state, &sha1_reseed_5_2 );
+ generate_ok ( &state, &sha1_generate_5_3 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha1_generate_fail_5_4 );
+ reseed_ok ( &state, &sha1_reseed_5_5 );
+ generate_ok ( &state, &sha1_generate_5_6 );
+
+ /* SHA-1 Test 6 */
+ instantiate_ok ( &state, &sha1_instantiate_6 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha1_generate_fail_6_1 );
+ reseed_ok ( &state, &sha1_reseed_6_2 );
+ generate_ok ( &state, &sha1_generate_6_3 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha1_generate_fail_6_4 );
+ reseed_ok ( &state, &sha1_reseed_6_5 );
+ generate_ok ( &state, &sha1_generate_6_6 );
+
+ /* SHA-1 Test 7 */
+ instantiate_ok ( &state, &sha1_instantiate_7 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha1_generate_fail_7_1 );
+ reseed_ok ( &state, &sha1_reseed_7_2 );
+ generate_ok ( &state, &sha1_generate_7_3 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha1_generate_fail_7_4 );
+ reseed_ok ( &state, &sha1_reseed_7_5 );
+ generate_ok ( &state, &sha1_generate_7_6 );
+
+ /* SHA-1 Test 8 */
+ instantiate_ok ( &state, &sha1_instantiate_8 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha1_generate_fail_8_1 );
+ reseed_ok ( &state, &sha1_reseed_8_2 );
+ generate_ok ( &state, &sha1_generate_8_3 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha1_generate_fail_8_4 );
+ reseed_ok ( &state, &sha1_reseed_8_5 );
+ generate_ok ( &state, &sha1_generate_8_6 );
+
+ /* SHA-256 Test 1 */
+ instantiate_ok ( &state, &sha256_instantiate_1 );
+ generate_ok ( &state, &sha256_generate_1_1 );
+ generate_ok ( &state, &sha256_generate_1_2 );
+
+ /* SHA-256 Test 2 */
+ instantiate_ok ( &state, &sha256_instantiate_2 );
+ generate_ok ( &state, &sha256_generate_2_1 );
+ generate_ok ( &state, &sha256_generate_2_2 );
+
+ /* SHA-256 Test 3 */
+ instantiate_ok ( &state, &sha256_instantiate_3 );
+ generate_ok ( &state, &sha256_generate_3_1 );
+ generate_ok ( &state, &sha256_generate_3_2 );
+
+ /* SHA-256 Test 4 */
+ instantiate_ok ( &state, &sha256_instantiate_4 );
+ generate_ok ( &state, &sha256_generate_4_1 );
+ generate_ok ( &state, &sha256_generate_4_2 );
+
+ /* SHA-256 Test 5 */
+ instantiate_ok ( &state, &sha256_instantiate_5 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha256_generate_fail_5_1 );
+ reseed_ok ( &state, &sha256_reseed_5_2 );
+ generate_ok ( &state, &sha256_generate_5_3 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha256_generate_fail_5_4 );
+ reseed_ok ( &state, &sha256_reseed_5_5 );
+ generate_ok ( &state, &sha256_generate_5_6 );
+
+ /* SHA-256 Test 6 */
+ instantiate_ok ( &state, &sha256_instantiate_6 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha256_generate_fail_6_1 );
+ reseed_ok ( &state, &sha256_reseed_6_2 );
+ generate_ok ( &state, &sha256_generate_6_3 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha256_generate_fail_6_4 );
+ reseed_ok ( &state, &sha256_reseed_6_5 );
+ generate_ok ( &state, &sha256_generate_6_6 );
+
+ /* SHA-256 Test 7 */
+ instantiate_ok ( &state, &sha256_instantiate_7 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha256_generate_fail_7_1 );
+ reseed_ok ( &state, &sha256_reseed_7_2 );
+ generate_ok ( &state, &sha256_generate_7_3 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha256_generate_fail_7_4 );
+ reseed_ok ( &state, &sha256_reseed_7_5 );
+ generate_ok ( &state, &sha256_generate_7_6 );
+
+ /* SHA-256 Test 8 */
+ instantiate_ok ( &state, &sha256_instantiate_8 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha256_generate_fail_8_1 );
+ reseed_ok ( &state, &sha256_reseed_8_2 );
+ generate_ok ( &state, &sha256_generate_8_3 );
+ force_reseed_required ( &state ); /* See above comments */
+ generate_fail_ok ( &state, &sha256_generate_fail_8_4 );
+ reseed_ok ( &state, &sha256_reseed_8_5 );
+ generate_ok ( &state, &sha256_generate_8_6 );
+}
+
+/** HMAC_DRBG self-test */
+struct self_test hmac_drbg_test __self_test = {
+ .name = "hmac_drbg",
+ .exec = hmac_drbg_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/linebuf_test.c b/src/VBox/Devices/PC/ipxe/src/tests/linebuf_test.c
new file mode 100644
index 00000000..e06ac7d8
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/linebuf_test.c
@@ -0,0 +1,35 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <ipxe/linebuf.h>
+
+static const char data1[] =
+"Hello world\r\n"
+"This is a reasonably nice set of lines\n"
+"with not many different terminators\r\n\r\n"
+"There should be exactly one blank line above\n"
+"and this line should never appear at all since it has no terminator";
+
+void linebuf_test ( void ) {
+ struct line_buffer linebuf;
+ const char *data = data1;
+ size_t len = ( sizeof ( data1 ) - 1 /* be mean; strip the NUL */ );
+ ssize_t frag_len;
+ char *line;
+
+ memset ( &linebuf, 0, sizeof ( linebuf ) );
+ while ( len ) {
+ frag_len = line_buffer ( &linebuf, data, len );
+ if ( frag_len < 0 ) {
+ printf ( "line_buffer() failed: %s\n",
+ strerror ( frag_len ) );
+ return;
+ }
+ data += frag_len;
+ len -= frag_len;
+ if ( ( line = buffered_line ( &linebuf ) ) )
+ printf ( "\"%s\"\n", line );
+ }
+
+ empty_line_buffer ( &linebuf );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/list_test.c b/src/VBox/Devices/PC/ipxe/src/tests/list_test.c
new file mode 100644
index 00000000..5184b308
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/list_test.c
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * List function tests
+ *
+ */
+
+/* Forcibly enable assertions for list_check() */
+#undef NDEBUG
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <ipxe/list.h>
+#include <ipxe/test.h>
+
+/** A list test structure */
+struct list_test {
+ /** List element */
+ struct list_head list;
+ /** Label */
+ char label;
+};
+
+/** List test elements */
+static struct list_test list_tests[] = {
+ { .label = '0' },
+ { .label = '1' },
+ { .label = '2' },
+ { .label = '3' },
+ { .label = '4' },
+ { .label = '5' },
+ { .label = '6' },
+ { .label = '7' },
+ { .label = '8' },
+ { .label = '9' },
+};
+
+/** Test list */
+static LIST_HEAD ( test_list );
+
+/**
+ * Check list contents are as expected
+ *
+ * @v list Test list
+ * @v expected Expected contents
+ * @v ok List contents are as expected
+ */
+static int list_check_contents ( struct list_head *list,
+ const char *expected ) {
+ struct list_test *entry;
+ size_t num_entries = 0;
+
+ /* Determine size of list */
+ list_for_each_entry ( entry, list, list )
+ num_entries++;
+
+ {
+ char found[ num_entries + 1 ];
+ char found_rev[ num_entries + 1 ];
+ char *tmp;
+
+ /* Build up list content string */
+ tmp = found;
+ list_for_each_entry ( entry, list, list )
+ *(tmp++) = entry->label;
+ *tmp = '\0';
+
+ /* Sanity check reversed list */
+ tmp = &found_rev[ sizeof ( found_rev ) - 1 ];
+ *tmp = '\0';
+ list_for_each_entry_reverse ( entry, list, list )
+ *(--tmp) = entry->label;
+ if ( strcmp ( found, found_rev ) != 0 ) {
+ printf ( "FAILURE: list reversal mismatch (forward "
+ "\"%s\", reverse \"%s\")\n",
+ found, found_rev );
+ return 0;
+ }
+
+ /* Compare against expected content */
+ if ( strcmp ( found, expected ) == 0 ) {
+ return 1;
+ } else {
+ printf ( "FAILURE: expected \"%s\", got \"%s\"\n",
+ expected, found );
+ return 0;
+ }
+ }
+}
+
+/**
+ * Report list test result
+ *
+ * @v list Test list
+ * @v expected Expected contents
+ */
+#define list_contents_ok( list, expected ) do { \
+ ok ( list_check_contents ( (list), (expected) ) ); \
+ } while ( 0 )
+
+/**
+ * Report list iteration test result
+ *
+ * @v macro Iterator macro
+ * @v expected Expected contents
+ * @v pos Iterator
+ * @v ... Arguments to iterator macro
+ */
+#define list_iterate_ok( macro, expected, pos, ... ) do { \
+ const char *check = expected; \
+ macro ( pos, __VA_ARGS__ ) { \
+ struct list_test *entry = \
+ list_entry ( pos, struct list_test, \
+ list ); \
+ ok ( entry->label == *(check++) ); \
+ } \
+ ok ( *check == '\0' ); \
+ } while ( 0 )
+
+/**
+ * Report list entry iteration test result
+ *
+ * @v macro Iterator macro
+ * @v expected Expected contents
+ * @v pos Iterator
+ * @v ... Arguments to iterator macro
+ */
+#define list_iterate_entry_ok( macro, expected, pos, ... ) do { \
+ const char *check = expected; \
+ macro ( pos, __VA_ARGS__ ) { \
+ ok ( (pos)->label == *(check++) ); \
+ } \
+ ok ( *check == '\0' ); \
+ } while ( 0 )
+
+/**
+ * Perform list self-test
+ *
+ */
+static void list_test_exec ( void ) {
+ struct list_head *list = &test_list;
+ struct list_head target_list;
+ struct list_head *target = &target_list;
+ struct list_head *raw_pos;
+ struct list_test *pos;
+ struct list_test *tmp;
+
+ /* Test initialiser and list_empty() */
+ ok ( list_empty ( list ) );
+ list_contents_ok ( list, "" );
+
+ /* Test list_add(), list_add_tail() and list_del() */
+ INIT_LIST_HEAD ( list );
+ list_contents_ok ( list, "" );
+ list_add ( &list_tests[4].list, list ); /* prepend */
+ list_contents_ok ( list, "4" );
+ list_add ( &list_tests[2].list, list ); /* prepend */
+ list_contents_ok ( list, "24" );
+ list_add_tail ( &list_tests[7].list, list ); /* append */
+ list_contents_ok ( list, "247" );
+ list_add ( &list_tests[1].list, &list_tests[4].list ); /* after */
+ list_contents_ok ( list, "2417" );
+ list_add_tail ( &list_tests[8].list, &list_tests[7].list ); /* before */
+ list_contents_ok ( list, "24187" );
+ list_del ( &list_tests[4].list ); /* delete middle */
+ list_contents_ok ( list, "2187" );
+ list_del ( &list_tests[2].list ); /* delete first */
+ list_contents_ok ( list, "187" );
+ list_del ( &list_tests[7].list ); /* delete last */
+ list_contents_ok ( list, "18" );
+ list_del ( &list_tests[1].list ); /* delete all */
+ list_del ( &list_tests[8].list ); /* delete all */
+ list_contents_ok ( list, "" );
+ ok ( list_empty ( list ) );
+
+ /* Test list_is_singular() */
+ INIT_LIST_HEAD ( list );
+ ok ( ! list_is_singular ( list ) );
+ list_add ( &list_tests[1].list, list );
+ ok ( list_is_singular ( list ) );
+ list_add ( &list_tests[3].list, list );
+ ok ( ! list_is_singular ( list ) );
+ list_del ( &list_tests[1].list );
+ ok ( list_is_singular ( list ) );
+
+ /* Test list_is_last() */
+ INIT_LIST_HEAD ( list );
+ list_add_tail ( &list_tests[6].list, list );
+ ok ( list_is_last ( &list_tests[6].list, list ) );
+ list_add_tail ( &list_tests[4].list, list );
+ ok ( list_is_last ( &list_tests[4].list, list ) );
+ ok ( ! list_is_last ( &list_tests[6].list, list ) );
+
+ /* Test list_cut_position() - empty list */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_cut_position ( target, list, list );
+ list_contents_ok ( list, "" );
+ list_contents_ok ( target, "" );
+
+ /* Test list_cut_position() - singular list, move nothing */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_add_tail ( &list_tests[4].list, list );
+ list_cut_position ( target, list, list );
+ list_contents_ok ( list, "4" );
+ list_contents_ok ( target, "" );
+
+ /* Test list_cut_position() - singular list, move singular entry */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_add_tail ( &list_tests[9].list, list );
+ list_cut_position ( target, list, &list_tests[9].list );
+ list_contents_ok ( list, "" );
+ list_contents_ok ( target, "9" );
+
+ /* Test list_cut_position() - multi-entry list, move nothing */
+ INIT_LIST_HEAD ( list );
+ list_add_tail ( &list_tests[3].list, list );
+ list_add_tail ( &list_tests[2].list, list );
+ list_add_tail ( &list_tests[7].list, list );
+ INIT_LIST_HEAD ( target );
+ list_cut_position ( target, list, list );
+ list_contents_ok ( list, "327" );
+ list_contents_ok ( target, "" );
+
+ /* Test list_cut_position() - multi-entry list, move some */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_add_tail ( &list_tests[8].list, list );
+ list_add_tail ( &list_tests[0].list, list );
+ list_add_tail ( &list_tests[9].list, list );
+ list_add_tail ( &list_tests[3].list, list );
+ list_add_tail ( &list_tests[2].list, list );
+ list_cut_position ( target, list, &list_tests[0].list );
+ list_contents_ok ( list, "932" );
+ list_contents_ok ( target, "80" );
+
+ /* Test list_cut_position() - multi-entry list, move everything */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_add_tail ( &list_tests[3].list, list );
+ list_add_tail ( &list_tests[5].list, list );
+ list_add_tail ( &list_tests[4].list, list );
+ list_add_tail ( &list_tests[7].list, list );
+ list_add_tail ( &list_tests[1].list, list );
+ list_cut_position ( target, list, &list_tests[1].list );
+ list_contents_ok ( list, "" );
+ list_contents_ok ( target, "35471" );
+
+ /* Test list_splice() - empty list */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_splice ( list, target );
+ list_contents_ok ( list, "" );
+ list_contents_ok ( target, "" );
+
+ /* Test list_splice() - both lists empty */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_splice ( list, target );
+ list_contents_ok ( target, "" );
+
+ /* Test list_splice() - source list empty */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_add_tail ( &list_tests[1].list, target );
+ list_add_tail ( &list_tests[3].list, target );
+ list_splice ( list, &list_tests[1].list );
+ list_contents_ok ( target, "13" );
+
+ /* Test list_splice() - destination list empty */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_add_tail ( &list_tests[6].list, list );
+ list_add_tail ( &list_tests[5].list, list );
+ list_add_tail ( &list_tests[2].list, list );
+ list_splice ( list, target );
+ list_contents_ok ( target, "652" );
+
+ /* Test list_splice() - both lists non-empty */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_add_tail ( &list_tests[8].list, list );
+ list_add_tail ( &list_tests[4].list, list );
+ list_add_tail ( &list_tests[5].list, list );
+ list_add_tail ( &list_tests[1].list, target );
+ list_add_tail ( &list_tests[9].list, target );
+ list_splice ( list, &list_tests[1].list );
+ list_contents_ok ( target, "18459" );
+
+ /* Test list_splice_tail() - both lists empty */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_splice_tail ( list, target );
+ list_contents_ok ( target, "" );
+
+ /* Test list_splice_tail() - source list empty */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_add_tail ( &list_tests[5].list, target );
+ list_splice_tail ( list, &list_tests[5].list );
+ list_contents_ok ( target, "5" );
+
+ /* Test list_splice_tail() - destination list empty */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_add_tail ( &list_tests[2].list, list );
+ list_add_tail ( &list_tests[1].list, list );
+ list_add_tail ( &list_tests[0].list, list );
+ list_splice_tail ( list, target );
+ list_contents_ok ( target, "210" );
+
+ /* Test list_splice_tail() - both lists non-empty */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_add_tail ( &list_tests[9].list, list );
+ list_add_tail ( &list_tests[5].list, list );
+ list_add_tail ( &list_tests[7].list, list );
+ list_add_tail ( &list_tests[2].list, target );
+ list_add_tail ( &list_tests[4].list, target );
+ list_splice_tail ( list, &list_tests[2].list );
+ list_contents_ok ( target, "95724" );
+
+ /* Test list_splice_init() */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_add_tail ( &list_tests[4].list, list );
+ list_add_tail ( &list_tests[1].list, target );
+ list_splice_init ( list, target );
+ ok ( list_empty ( list ) );
+ list_contents_ok ( list, "" );
+ list_contents_ok ( target, "41" );
+
+ /* Test list_splice_tail_init() */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( target );
+ list_add_tail ( &list_tests[3].list, list );
+ list_add_tail ( &list_tests[2].list, list );
+ list_add_tail ( &list_tests[5].list, target );
+ list_splice_tail_init ( list, &list_tests[5].list );
+ ok ( list_empty ( list ) );
+ list_contents_ok ( list, "" );
+ list_contents_ok ( target, "325" );
+
+ /* Test list_entry() */
+ INIT_LIST_HEAD ( &list_tests[3].list ); // for list_check()
+ ok ( list_entry ( &list_tests[3].list, struct list_test, list )
+ == &list_tests[3] );
+
+ /* Test list_first_entry() and list_last_entry() */
+ INIT_LIST_HEAD ( list );
+ list_add_tail ( &list_tests[9].list, list );
+ list_add_tail ( &list_tests[5].list, list );
+ list_add_tail ( &list_tests[6].list, list );
+ ok ( list_first_entry ( list, struct list_test, list )
+ == &list_tests[9] );
+ ok ( list_last_entry ( list, struct list_test, list )
+ == &list_tests[6] );
+ list_del ( &list_tests[9].list );
+ ok ( list_first_entry ( list, struct list_test, list )
+ == &list_tests[5] );
+ ok ( list_last_entry ( list, struct list_test, list )
+ == &list_tests[6] );
+ list_del ( &list_tests[6].list );
+ ok ( list_first_entry ( list, struct list_test, list )
+ == &list_tests[5] );
+ ok ( list_last_entry ( list, struct list_test, list )
+ == &list_tests[5] );
+ list_del ( &list_tests[5].list );
+ ok ( list_first_entry ( list, struct list_test, list ) == NULL );
+ ok ( list_last_entry ( list, struct list_test, list ) == NULL );
+
+ /* Test list_for_each() */
+ INIT_LIST_HEAD ( list );
+ list_add_tail ( &list_tests[6].list, list );
+ list_add_tail ( &list_tests[7].list, list );
+ list_add_tail ( &list_tests[3].list, list );
+ list_iterate_ok ( list_for_each, "673", raw_pos, list );
+
+ /* Test list_for_each_entry() and list_for_each_entry_reverse() */
+ INIT_LIST_HEAD ( list );
+ list_add_tail ( &list_tests[3].list, list );
+ list_add_tail ( &list_tests[2].list, list );
+ list_add_tail ( &list_tests[6].list, list );
+ list_add_tail ( &list_tests[9].list, list );
+ list_iterate_entry_ok ( list_for_each_entry, "3269",
+ pos, list, list );
+ list_iterate_entry_ok ( list_for_each_entry_reverse, "9623",
+ pos, list, list );
+
+ /* Test list_for_each_entry_safe() */
+ INIT_LIST_HEAD ( list );
+ list_add_tail ( &list_tests[2].list, list );
+ list_add_tail ( &list_tests[4].list, list );
+ list_add_tail ( &list_tests[1].list, list );
+ {
+ char *expected = "241";
+ list_for_each_entry_safe ( pos, tmp, list, list ) {
+ list_contents_ok ( list, expected );
+ list_del ( &pos->list );
+ expected++;
+ list_contents_ok ( list, expected );
+ }
+ }
+ ok ( list_empty ( list ) );
+
+ /* Test list_for_each_entry_continue() and
+ * list_for_each_entry_continue_reverse()
+ */
+ INIT_LIST_HEAD ( list );
+ list_add_tail ( &list_tests[4].list, list );
+ list_add_tail ( &list_tests[7].list, list );
+ list_add_tail ( &list_tests[2].list, list );
+ list_add_tail ( &list_tests[9].list, list );
+ list_add_tail ( &list_tests[3].list, list );
+ pos = &list_tests[7];
+ list_iterate_entry_ok ( list_for_each_entry_continue, "293",
+ pos, list, list );
+ ok ( pos == list_entry ( list, struct list_test, list ) );
+ list_iterate_entry_ok ( list_for_each_entry_continue, "47293",
+ pos, list, list );
+ pos = &list_tests[3];
+ list_iterate_entry_ok ( list_for_each_entry_continue, "",
+ pos, list, list );
+ pos = &list_tests[2];
+ list_iterate_entry_ok ( list_for_each_entry_continue_reverse, "74",
+ pos, list, list );
+ ok ( pos == list_entry ( list, struct list_test, list ) );
+ list_iterate_entry_ok ( list_for_each_entry_continue_reverse, "39274",
+ pos, list, list );
+ pos = &list_tests[4];
+ list_iterate_entry_ok ( list_for_each_entry_continue_reverse, "",
+ pos, list, list );
+
+ /* Test list_contains() and list_contains_entry() */
+ INIT_LIST_HEAD ( list );
+ INIT_LIST_HEAD ( &list_tests[3].list );
+ list_add ( &list_tests[8].list, list );
+ list_add ( &list_tests[5].list, list );
+ ok ( list_contains ( &list_tests[8].list, list ) );
+ ok ( list_contains_entry ( &list_tests[8], list, list ) );
+ ok ( list_contains ( &list_tests[5].list, list ) );
+ ok ( list_contains_entry ( &list_tests[5], list, list ) );
+ ok ( ! list_contains ( &list_tests[3].list, list ) );
+ ok ( ! list_contains_entry ( &list_tests[3], list, list ) );
+
+ /* Test list_check_contains_entry() */
+ INIT_LIST_HEAD ( list );
+ list_add ( &list_tests[4].list, list );
+ list_add ( &list_tests[0].list, list );
+ list_add ( &list_tests[3].list, list );
+ list_check_contains_entry ( &list_tests[4], list, list );
+ list_check_contains_entry ( &list_tests[0], list, list );
+ list_check_contains_entry ( &list_tests[3], list, list );
+}
+
+/** List self-test */
+struct self_test list_test __self_test = {
+ .name = "list",
+ .exec = list_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/md5_test.c b/src/VBox/Devices/PC/ipxe/src/tests/md5_test.c
new file mode 100644
index 00000000..17972daa
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/md5_test.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * MD5 tests
+ *
+ */
+
+#include <stdint.h>
+#include <ipxe/md5.h>
+#include <ipxe/test.h>
+#include "digest_test.h"
+
+/** An MD5 test vector */
+struct md5_test_vector {
+ /** Test data */
+ void *data;
+ /** Test data length */
+ size_t len;
+ /** Expected digest */
+ uint8_t digest[MD5_DIGEST_SIZE];
+};
+
+/** MD5 test vectors */
+static struct md5_test_vector md5_test_vectors[] = {
+ /* Test inputs borrowed from SHA-1 tests, with results
+ * calculated using md5sum.
+ */
+ { NULL, 0,
+ { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
+ 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
+ { "abc", 3,
+ { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
+ 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
+ { 0x82, 0x15, 0xef, 0x07, 0x96, 0xa2, 0x0b, 0xca,
+ 0xaa, 0xe1, 0x16, 0xd3, 0x87, 0x6c, 0x66, 0x4a } },
+};
+
+/** MD5 test fragment lists */
+static struct digest_test_fragments md5_test_fragments[] = {
+ { { 0, -1UL, } },
+ { { 1, 1, 1, 1, 1, 1, 1, 1 } },
+ { { 2, 0, 23, 4, 6, 1, 0 } },
+};
+
+/**
+ * Perform MD5 self-test
+ *
+ */
+static void md5_test_exec ( void ) {
+ struct digest_algorithm *digest = &md5_algorithm;
+ struct md5_test_vector *test;
+ unsigned int i;
+ unsigned int j;
+
+ for ( i = 0 ; i < ( sizeof ( md5_test_vectors ) /
+ sizeof ( md5_test_vectors[0] ) ) ; i++ ) {
+ test = &md5_test_vectors[i];
+ /* Test with a single pass */
+ digest_ok ( digest, NULL, test->data, test->len, test->digest );
+ /* Test with fragment lists */
+ for ( j = 0 ; j < ( sizeof ( md5_test_fragments ) /
+ sizeof ( md5_test_fragments[0] ) ) ; j++ ){
+ digest_ok ( digest, &md5_test_fragments[j],
+ test->data, test->len, test->digest );
+ }
+ }
+}
+
+/** MD5 self-test */
+struct self_test md5_test __self_test = {
+ .name = "md5",
+ .exec = md5_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/memcpy_test.c b/src/VBox/Devices/PC/ipxe/src/tests/memcpy_test.c
new file mode 100644
index 00000000..7626e639
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/memcpy_test.c
@@ -0,0 +1,39 @@
+#include <string.h>
+
+/*
+ * This file exists for testing the compilation of memcpy() with the
+ * various constant-length optimisations.
+ *
+ */
+
+#define __regparm __attribute__ (( regparm(3) ))
+
+void __regparm memcpy_0 ( void *dest, void *src ) { memcpy ( dest, src, 0 ); }
+void __regparm memcpy_1 ( void *dest, void *src ) { memcpy ( dest, src, 1 ); }
+void __regparm memcpy_2 ( void *dest, void *src ) { memcpy ( dest, src, 2 ); }
+void __regparm memcpy_3 ( void *dest, void *src ) { memcpy ( dest, src, 3 ); }
+void __regparm memcpy_4 ( void *dest, void *src ) { memcpy ( dest, src, 4 ); }
+void __regparm memcpy_5 ( void *dest, void *src ) { memcpy ( dest, src, 5 ); }
+void __regparm memcpy_6 ( void *dest, void *src ) { memcpy ( dest, src, 6 ); }
+void __regparm memcpy_7 ( void *dest, void *src ) { memcpy ( dest, src, 7 ); }
+void __regparm memcpy_8 ( void *dest, void *src ) { memcpy ( dest, src, 8 ); }
+void __regparm memcpy_9 ( void *dest, void *src ) { memcpy ( dest, src, 9 ); }
+void __regparm memcpy_10 ( void *dest, void *src ) { memcpy ( dest, src, 10 ); }
+void __regparm memcpy_11 ( void *dest, void *src ) { memcpy ( dest, src, 11 ); }
+void __regparm memcpy_12 ( void *dest, void *src ) { memcpy ( dest, src, 12 ); }
+void __regparm memcpy_13 ( void *dest, void *src ) { memcpy ( dest, src, 13 ); }
+void __regparm memcpy_14 ( void *dest, void *src ) { memcpy ( dest, src, 14 ); }
+void __regparm memcpy_15 ( void *dest, void *src ) { memcpy ( dest, src, 15 ); }
+void __regparm memcpy_16 ( void *dest, void *src ) { memcpy ( dest, src, 16 ); }
+void __regparm memcpy_17 ( void *dest, void *src ) { memcpy ( dest, src, 17 ); }
+void __regparm memcpy_18 ( void *dest, void *src ) { memcpy ( dest, src, 18 ); }
+void __regparm memcpy_19 ( void *dest, void *src ) { memcpy ( dest, src, 19 ); }
+void __regparm memcpy_20 ( void *dest, void *src ) { memcpy ( dest, src, 20 ); }
+void __regparm memcpy_21 ( void *dest, void *src ) { memcpy ( dest, src, 21 ); }
+void __regparm memcpy_22 ( void *dest, void *src ) { memcpy ( dest, src, 22 ); }
+void __regparm memcpy_23 ( void *dest, void *src ) { memcpy ( dest, src, 23 ); }
+void __regparm memcpy_24 ( void *dest, void *src ) { memcpy ( dest, src, 24 ); }
+void __regparm memcpy_25 ( void *dest, void *src ) { memcpy ( dest, src, 25 ); }
+void __regparm memcpy_26 ( void *dest, void *src ) { memcpy ( dest, src, 26 ); }
+void __regparm memcpy_27 ( void *dest, void *src ) { memcpy ( dest, src, 27 ); }
+void __regparm memcpy_28 ( void *dest, void *src ) { memcpy ( dest, src, 28 ); }
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/ocsp_test.c b/src/VBox/Devices/PC/ipxe/src/tests/ocsp_test.c
new file mode 100644
index 00000000..38191fc4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/ocsp_test.c
@@ -0,0 +1,1534 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the General Public License version 2 (GPLv2) at this time for any software where
+ * a choice of GPL license versions is made available with the language indicating
+ * that GPLv2 or any later version may be used, or where a choice of which version
+ * of the GPL is applied is otherwise unspecified.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * OCSP tests
+ *
+ *
+ * Test vectors generated using OpenSSL:
+ *
+ * openssl ocsp -no_nonce -issuer issuer.crt -cert cert.crt \
+ * -url http://ocsp.server.address \
+ * -reqout request.der -respout response.der
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ipxe/x509.h>
+#include <ipxe/ocsp.h>
+#include <ipxe/test.h>
+
+/** An OCSP test certificate */
+struct ocsp_test_certificate {
+ /** Data */
+ const void *data;
+ /** Length of data */
+ size_t len;
+ /** Parsed certificate */
+ struct x509_certificate *cert;
+};
+
+/** An OCSP test */
+struct ocsp_test {
+ /** Certificate */
+ struct ocsp_test_certificate *cert;
+ /** Issuing certificate */
+ struct ocsp_test_certificate *issuer;
+ /** Request */
+ const void *request;
+ /** Length of request */
+ size_t request_len;
+ /** Response */
+ const void *response;
+ /** Length of response */
+ size_t response_len;
+ /* OCSP check */
+ struct ocsp_check *ocsp;
+};
+
+/** Define inline data */
+#define DATA(...) { __VA_ARGS__ }
+
+/** Define a test certificate */
+#define CERTIFICATE( name, DATA, FINGERPRINT ) \
+ static const uint8_t name ## _data[] = DATA; \
+ static struct ocsp_test_certificate name = { \
+ .data = name ## _data, \
+ .len = sizeof ( name ## _data ), \
+ }
+
+/** Define an OCSP test */
+#define OCSP( name, CERT, ISSUER, REQUEST, RESPONSE ) \
+ static const uint8_t name ## _request[] = REQUEST; \
+ static const uint8_t name ## _response[] = RESPONSE; \
+ static struct ocsp_test name = { \
+ .cert = CERT, \
+ .issuer = ISSUER, \
+ .request = name ## _request, \
+ .request_len = sizeof ( name ## _request ), \
+ .response = name ## _response, \
+ .response_len = sizeof ( name ## _response ), \
+ }
+
+/**
+ * Prepare an OCSP test
+ *
+ * @v test OCSP test
+ */
+static void ocsp_prepare_test ( struct ocsp_test *test ) {
+ struct x509_certificate *cert = test->cert->cert;
+ struct x509_certificate *issuer = test->issuer->cert;
+
+ /* Invalidate certificate being checked */
+ x509_invalidate ( cert );
+
+ /* Force-validate issuer certificate */
+ issuer->valid = 1;
+ issuer->path_remaining = ( issuer->extensions.basic.path_len + 1 );
+}
+
+/*
+ * subject bank.barclays.co.uk
+ * issuer VeriSign Class 3 International Server CA - G3
+ */
+CERTIFICATE ( barclays_crt,
+ DATA ( 0x30, 0x82, 0x05, 0x7b, 0x30, 0x82, 0x04, 0x63, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x10, 0x49, 0x83, 0xfc, 0x05, 0x76,
+ 0xdf, 0x36, 0x91, 0x7c, 0x64, 0x2a, 0x27, 0xc1, 0xf1, 0x48,
+ 0xe3, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0xbc, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67,
+ 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1f, 0x30,
+ 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65,
+ 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75,
+ 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
+ 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13,
+ 0x32, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x75, 0x73, 0x65, 0x20, 0x61, 0x74, 0x20, 0x68, 0x74, 0x74,
+ 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76,
+ 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x2f, 0x72, 0x70, 0x61, 0x20, 0x28, 0x63, 0x29, 0x31,
+ 0x30, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x13, 0x2d, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e,
+ 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x49,
+ 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
+ 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x30, 0x1e, 0x17,
+ 0x0d, 0x31, 0x31, 0x31, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x32, 0x31, 0x32,
+ 0x30, 0x34, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30,
+ 0x7f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x47, 0x42, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x61,
+ 0x6e, 0x64, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
+ 0x07, 0x14, 0x0a, 0x47, 0x6c, 0x6f, 0x75, 0x63, 0x65, 0x73,
+ 0x74, 0x65, 0x72, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x14, 0x11, 0x42, 0x61, 0x72, 0x63, 0x6c, 0x61,
+ 0x79, 0x73, 0x20, 0x42, 0x61, 0x6e, 0x6b, 0x20, 0x50, 0x6c,
+ 0x63, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0b,
+ 0x14, 0x06, 0x47, 0x4c, 0x4f, 0x2d, 0x4c, 0x32, 0x31, 0x1c,
+ 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x14, 0x13, 0x62,
+ 0x61, 0x6e, 0x6b, 0x2e, 0x62, 0x61, 0x72, 0x63, 0x6c, 0x61,
+ 0x79, 0x73, 0x2e, 0x63, 0x6f, 0x2e, 0x75, 0x6b, 0x30, 0x82,
+ 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
+ 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
+ 0x00, 0x99, 0x4c, 0x2e, 0x00, 0xa0, 0xaf, 0xe2, 0xbc, 0x52,
+ 0x43, 0x83, 0x34, 0x03, 0x58, 0xdf, 0xd3, 0xea, 0x43, 0xa2,
+ 0xfd, 0x2c, 0x4c, 0x3c, 0x32, 0x9c, 0x60, 0x40, 0xe5, 0xa1,
+ 0x07, 0x8d, 0x32, 0x21, 0xc1, 0xbd, 0xf1, 0x04, 0x2e, 0x90,
+ 0xf3, 0x05, 0x30, 0xd4, 0x6f, 0x81, 0x3e, 0x08, 0xb6, 0xc3,
+ 0xc1, 0xcf, 0xc4, 0x59, 0x7c, 0x56, 0x27, 0xea, 0x74, 0xe7,
+ 0x8f, 0x50, 0xd1, 0xa9, 0x13, 0x57, 0x3a, 0x05, 0x5a, 0xd7,
+ 0x7f, 0xfc, 0xc5, 0xc6, 0x66, 0xec, 0xa4, 0x03, 0xec, 0x97,
+ 0x1a, 0x4b, 0x28, 0xf9, 0xc9, 0xf4, 0xea, 0xc6, 0x89, 0x68,
+ 0xc1, 0x42, 0xcd, 0x80, 0xfc, 0xeb, 0x86, 0x6d, 0x1c, 0xd6,
+ 0xa1, 0x05, 0x16, 0xa4, 0xcf, 0x82, 0x1d, 0x07, 0x67, 0x7c,
+ 0xeb, 0xa1, 0x69, 0xf3, 0xf2, 0x21, 0xa7, 0x79, 0xf5, 0xf2,
+ 0xdc, 0xb6, 0x0b, 0x6e, 0x19, 0xcc, 0x50, 0x53, 0xf3, 0xbd,
+ 0xb9, 0x71, 0xdc, 0x2b, 0x15, 0x78, 0x6d, 0xd4, 0xd3, 0x82,
+ 0xce, 0x37, 0x0c, 0xb5, 0x5e, 0x24, 0x8d, 0x80, 0x40, 0x71,
+ 0x4e, 0x7b, 0x0a, 0x6e, 0x30, 0x4b, 0xb6, 0x2c, 0x23, 0x9e,
+ 0xd5, 0x08, 0x7d, 0x8a, 0x72, 0x46, 0xf6, 0x52, 0x98, 0xcb,
+ 0x03, 0x79, 0x61, 0xfe, 0xc1, 0x97, 0x15, 0x4b, 0x05, 0x36,
+ 0x0c, 0x11, 0xe9, 0x95, 0x4b, 0xef, 0xf3, 0x2d, 0xf3, 0xef,
+ 0x33, 0x6c, 0xc6, 0x98, 0xb9, 0x65, 0xe3, 0x3c, 0x26, 0x86,
+ 0xb5, 0x87, 0x9e, 0x20, 0x92, 0x7b, 0x8f, 0x13, 0x66, 0x5e,
+ 0x26, 0x09, 0xd6, 0x83, 0xee, 0x56, 0x72, 0x08, 0x6c, 0x2a,
+ 0x4c, 0xf2, 0x5b, 0xf1, 0x08, 0x4b, 0x91, 0x9e, 0x67, 0x37,
+ 0x2f, 0xc5, 0xcf, 0x1a, 0xa8, 0xa1, 0x1c, 0xb6, 0x2d, 0xd0,
+ 0x81, 0xf4, 0xf7, 0x37, 0xb9, 0xa3, 0x37, 0x3f, 0x6b, 0x2f,
+ 0x62, 0x82, 0xa7, 0x17, 0xc1, 0x8c, 0x69, 0x02, 0x03, 0x01,
+ 0x00, 0x01, 0xa3, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0xaf,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30,
+ 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04,
+ 0x03, 0x02, 0x05, 0xa0, 0x30, 0x41, 0x06, 0x03, 0x55, 0x1d,
+ 0x1f, 0x04, 0x3a, 0x30, 0x38, 0x30, 0x36, 0xa0, 0x34, 0xa0,
+ 0x32, 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x53, 0x56, 0x52, 0x49, 0x6e, 0x74, 0x6c, 0x2d, 0x47, 0x33,
+ 0x2d, 0x63, 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73,
+ 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x56,
+ 0x52, 0x49, 0x6e, 0x74, 0x6c, 0x47, 0x33, 0x2e, 0x63, 0x72,
+ 0x6c, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3d,
+ 0x30, 0x3b, 0x30, 0x39, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01,
+ 0x86, 0xf8, 0x45, 0x01, 0x07, 0x17, 0x03, 0x30, 0x2a, 0x30,
+ 0x28, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02,
+ 0x01, 0x16, 0x1c, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73,
+ 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x70,
+ 0x61, 0x30, 0x28, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x21,
+ 0x30, 0x1f, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8,
+ 0x42, 0x04, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x03, 0x02, 0x30, 0x72, 0x06, 0x08, 0x2b, 0x06, 0x01,
+ 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x66, 0x30, 0x64, 0x30,
+ 0x24, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
+ 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73,
+ 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x3c, 0x06,
+ 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86,
+ 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x53, 0x56,
+ 0x52, 0x49, 0x6e, 0x74, 0x6c, 0x2d, 0x47, 0x33, 0x2d, 0x61,
+ 0x69, 0x61, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67,
+ 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x56, 0x52, 0x49,
+ 0x6e, 0x74, 0x6c, 0x47, 0x33, 0x2e, 0x63, 0x65, 0x72, 0x30,
+ 0x6e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01,
+ 0x0c, 0x04, 0x62, 0x30, 0x60, 0xa1, 0x5e, 0xa0, 0x5c, 0x30,
+ 0x5a, 0x30, 0x58, 0x30, 0x56, 0x16, 0x09, 0x69, 0x6d, 0x61,
+ 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0x30, 0x21, 0x30, 0x1f,
+ 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04,
+ 0x14, 0x4b, 0x6b, 0xb9, 0x28, 0x96, 0x06, 0x0c, 0xbb, 0xd0,
+ 0x52, 0x38, 0x9b, 0x29, 0xac, 0x4b, 0x07, 0x8b, 0x21, 0x05,
+ 0x18, 0x30, 0x26, 0x16, 0x24, 0x68, 0x74, 0x74, 0x70, 0x3a,
+ 0x2f, 0x2f, 0x6c, 0x6f, 0x67, 0x6f, 0x2e, 0x76, 0x65, 0x72,
+ 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+ 0x76, 0x73, 0x6c, 0x6f, 0x67, 0x6f, 0x31, 0x2e, 0x67, 0x69,
+ 0x66, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01,
+ 0x00, 0x49, 0xf3, 0x7c, 0x15, 0xb0, 0x50, 0x97, 0xb7, 0xcd,
+ 0x87, 0x75, 0x85, 0xcc, 0x55, 0x7c, 0x62, 0x97, 0x97, 0x04,
+ 0xbd, 0xc2, 0x22, 0xfc, 0xf5, 0x2c, 0x75, 0xdc, 0x25, 0x6d,
+ 0xed, 0xcd, 0x22, 0x2e, 0xa4, 0xcd, 0x88, 0x95, 0xe8, 0x52,
+ 0x45, 0x7a, 0xa0, 0x85, 0xcc, 0x6d, 0x1c, 0xcb, 0xd8, 0xc3,
+ 0x26, 0x2c, 0xee, 0xb5, 0xe1, 0x38, 0x3f, 0xb6, 0x96, 0x10,
+ 0xa3, 0xb3, 0x1e, 0x2d, 0xdc, 0xe8, 0x07, 0x2f, 0xc2, 0xb7,
+ 0x50, 0xd5, 0x60, 0x73, 0x0d, 0x43, 0xb1, 0xaf, 0xd9, 0xcb,
+ 0x39, 0x00, 0xc7, 0x00, 0xb3, 0x1f, 0xa4, 0xaf, 0xf8, 0xed,
+ 0x9b, 0x6a, 0x7a, 0x10, 0xcc, 0x81, 0x92, 0xc2, 0x58, 0x7e,
+ 0x42, 0xe4, 0xbf, 0xcf, 0x8c, 0x91, 0x7f, 0xde, 0xe6, 0xac,
+ 0x37, 0x31, 0x58, 0x90, 0xee, 0x51, 0xf5, 0x0e, 0xe5, 0x84,
+ 0xd8, 0x51, 0x89, 0x50, 0xfe, 0xfa, 0xad, 0xc9, 0xbb, 0x19,
+ 0xb3, 0x4a, 0xc8, 0x6b, 0x26, 0x98, 0x4b, 0x63, 0x41, 0x81,
+ 0xe1, 0x12, 0xab, 0xcc, 0x89, 0xbe, 0xdf, 0xa8, 0x7e, 0xf5,
+ 0x0e, 0x07, 0xf6, 0x92, 0x89, 0x64, 0x3b, 0xc2, 0x64, 0xa2,
+ 0x4b, 0xd1, 0x6b, 0x9b, 0x4e, 0x6a, 0xf2, 0x63, 0xf7, 0xc3,
+ 0xe0, 0x9f, 0xc5, 0x4e, 0xb6, 0x77, 0x0a, 0xad, 0x6d, 0x0f,
+ 0x30, 0x87, 0x6b, 0xfb, 0x66, 0xb3, 0x90, 0x87, 0xa3, 0x48,
+ 0xbe, 0xa4, 0x34, 0x9c, 0x5a, 0x93, 0xa3, 0x74, 0x0e, 0x36,
+ 0x8e, 0xf6, 0x3b, 0x6c, 0xae, 0xa0, 0x6a, 0xa1, 0x1a, 0x12,
+ 0x78, 0x99, 0x75, 0x50, 0xb1, 0x72, 0xed, 0x22, 0x34, 0x0f,
+ 0xe1, 0x89, 0xfe, 0x81, 0x0a, 0xcc, 0x2a, 0xd0, 0xf3, 0x25,
+ 0xe6, 0xd9, 0x19, 0x06, 0x20, 0x2d, 0x29, 0x8b, 0xdd, 0xb5,
+ 0x60, 0xf4, 0x0d, 0x08, 0x97, 0x7b, 0x81, 0x4a, 0xfb, 0x20,
+ 0xfb, 0x83, 0xa3, 0xc8, 0x1d, 0x79, 0xb9 ),
+ FINGERPRINT ( 0x7e, 0x54, 0x41, 0x60, 0x21, 0xca, 0x3e, 0x63,
+ 0xce, 0x5a, 0x41, 0x6c, 0xbe, 0x52, 0x01, 0x88,
+ 0xcf, 0x41, 0x36, 0x48, 0xdb, 0xe3, 0xdf, 0x8e,
+ 0x79, 0x73, 0x5f, 0xcf, 0x8e, 0x8e, 0xac, 0xd8 ) );
+
+/*
+ * subject www.google.com
+ * issuer Thawte SGC CA
+ */
+CERTIFICATE ( google_crt,
+ DATA ( 0x30, 0x82, 0x03, 0x21, 0x30, 0x82, 0x02, 0x8a, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x10, 0x4f, 0x9d, 0x96, 0xd9, 0x66,
+ 0xb0, 0x99, 0x2b, 0x54, 0xc2, 0x95, 0x7c, 0xb4, 0x15, 0x7d,
+ 0x4d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4c, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5a,
+ 0x41, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x1c, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x43,
+ 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20,
+ 0x28, 0x50, 0x74, 0x79, 0x29, 0x20, 0x4c, 0x74, 0x64, 0x2e,
+ 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+ 0x0d, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x53, 0x47,
+ 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31,
+ 0x31, 0x30, 0x32, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x39, 0x33, 0x30, 0x32,
+ 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x68, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+ 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e,
+ 0x69, 0x61, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04,
+ 0x07, 0x14, 0x0d, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69,
+ 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x0a, 0x47, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x17, 0x30,
+ 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x14, 0x0e, 0x77, 0x77,
+ 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
+ 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81,
+ 0x00, 0xde, 0xb7, 0x26, 0x43, 0xa6, 0x99, 0x85, 0xcd, 0x38,
+ 0xa7, 0x15, 0x09, 0xb9, 0xcf, 0x0f, 0xc9, 0xc3, 0x55, 0x8c,
+ 0x88, 0xee, 0x8c, 0x8d, 0x28, 0x27, 0x24, 0x4b, 0x2a, 0x5e,
+ 0xa0, 0xd8, 0x16, 0xfa, 0x61, 0x18, 0x4b, 0xcf, 0x6d, 0x60,
+ 0x80, 0xd3, 0x35, 0x40, 0x32, 0x72, 0xc0, 0x8f, 0x12, 0xd8,
+ 0xe5, 0x4e, 0x8f, 0xb9, 0xb2, 0xf6, 0xd9, 0x15, 0x5e, 0x5a,
+ 0x86, 0x31, 0xa3, 0xba, 0x86, 0xaa, 0x6b, 0xc8, 0xd9, 0x71,
+ 0x8c, 0xcc, 0xcd, 0x27, 0x13, 0x1e, 0x9d, 0x42, 0x5d, 0x38,
+ 0xf6, 0xa7, 0xac, 0xef, 0xfa, 0x62, 0xf3, 0x18, 0x81, 0xd4,
+ 0x24, 0x46, 0x7f, 0x01, 0x77, 0x7c, 0xc6, 0x2a, 0x89, 0x14,
+ 0x99, 0xbb, 0x98, 0x39, 0x1d, 0xa8, 0x19, 0xfb, 0x39, 0x00,
+ 0x44, 0x7d, 0x1b, 0x94, 0x6a, 0x78, 0x2d, 0x69, 0xad, 0xc0,
+ 0x7a, 0x2c, 0xfa, 0xd0, 0xda, 0x20, 0x12, 0x98, 0xd3, 0x02,
+ 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xe7, 0x30, 0x81, 0xe4,
+ 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+ 0x04, 0x02, 0x30, 0x00, 0x30, 0x36, 0x06, 0x03, 0x55, 0x1d,
+ 0x1f, 0x04, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0xa0, 0x29, 0xa0,
+ 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x63, 0x72, 0x6c, 0x2e, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x68, 0x61, 0x77, 0x74,
+ 0x65, 0x53, 0x47, 0x43, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x6c,
+ 0x30, 0x28, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x21, 0x30,
+ 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03,
+ 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03,
+ 0x02, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42,
+ 0x04, 0x01, 0x30, 0x72, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x01, 0x01, 0x04, 0x66, 0x30, 0x64, 0x30, 0x22,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01,
+ 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f,
+ 0x63, 0x73, 0x70, 0x2e, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x3e, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x32, 0x68, 0x74,
+ 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x74,
+ 0x68, 0x61, 0x77, 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+ 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79,
+ 0x2f, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x5f, 0x53, 0x47,
+ 0x43, 0x5f, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x21, 0xac, 0xd5,
+ 0xae, 0xca, 0x34, 0x89, 0x5a, 0xc2, 0xab, 0x52, 0xd2, 0xb2,
+ 0x34, 0x66, 0x9d, 0x7a, 0xab, 0xee, 0xe6, 0x7c, 0xd5, 0x7e,
+ 0xc2, 0x5c, 0x28, 0xbb, 0x74, 0x00, 0xc9, 0x10, 0x1f, 0x42,
+ 0x13, 0xfc, 0x69, 0x8a, 0x1e, 0x24, 0xa0, 0x02, 0x00, 0xe9,
+ 0xba, 0x5b, 0xca, 0x19, 0x04, 0xb2, 0xd3, 0xaf, 0x01, 0xb2,
+ 0x7e, 0x5f, 0x14, 0xdb, 0xa6, 0xdb, 0x52, 0xb9, 0x9a, 0xf3,
+ 0x12, 0x7f, 0x7c, 0xa2, 0x9c, 0x3b, 0x6f, 0x99, 0x7d, 0xea,
+ 0x50, 0x0d, 0x76, 0x23, 0x12, 0xff, 0xf7, 0x66, 0x73, 0x29,
+ 0xb7, 0x95, 0x0a, 0xad, 0xd8, 0x8b, 0xb2, 0xde, 0x20, 0xe9,
+ 0x0a, 0x70, 0x64, 0x11, 0x08, 0xc8, 0x5a, 0xf1, 0x7d, 0x9e,
+ 0xec, 0x69, 0xa5, 0xa5, 0xd5, 0x82, 0xd7, 0x27, 0x1e, 0x9e,
+ 0x56, 0xcd, 0xd2, 0x76, 0xd5, 0x79, 0x2b, 0xf7, 0x25, 0x43,
+ 0x1c, 0x69, 0xf0, 0xb8, 0xf9 ),
+ FINGERPRINT ( 0xec, 0x6a, 0x6b, 0x15, 0x6b, 0x30, 0x62, 0xfa,
+ 0x99, 0x49, 0x9d, 0x1e, 0x15, 0x15, 0xcf, 0x6c,
+ 0x50, 0x48, 0xaf, 0x17, 0x94, 0x57, 0x48, 0x39,
+ 0x6b, 0xd2, 0xec, 0xf1, 0x2b, 0x8d, 0xe2, 0x2c ) );
+
+/*
+ * subject boot.test.ipxe.org
+ * issuer iPXE self-test leaf CA
+ */
+CERTIFICATE ( server_crt,
+ DATA ( 0x30, 0x82, 0x02, 0x7d, 0x30, 0x82, 0x01, 0xe6, 0x02, 0x01,
+ 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65,
+ 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65,
+ 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65,
+ 0x61, 0x66, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+ 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33,
+ 0x34, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x33, 0x32, 0x32,
+ 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x30, 0x81, 0x84,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12,
+ 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43,
+ 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18,
+ 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46,
+ 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73,
+ 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03,
+ 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e,
+ 0x6f, 0x72, 0x67, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x2e, 0x74,
+ 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
+ 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81,
+ 0x00, 0xbd, 0x43, 0x97, 0x45, 0xa2, 0xe0, 0x1d, 0x38, 0x41,
+ 0xb0, 0xd9, 0x91, 0xf9, 0x77, 0xa9, 0xcb, 0x9c, 0x9c, 0x93,
+ 0xfe, 0x5a, 0xee, 0xbc, 0xd9, 0x0f, 0x39, 0xf6, 0x42, 0xe4,
+ 0x55, 0x21, 0xbb, 0x11, 0xfd, 0xfd, 0xba, 0x25, 0x58, 0xc8,
+ 0xc6, 0xa5, 0x3b, 0x6f, 0x80, 0xba, 0x5b, 0xbc, 0x89, 0xca,
+ 0x7a, 0xdf, 0x6e, 0xb9, 0x81, 0xb6, 0x25, 0x67, 0x0a, 0x38,
+ 0x10, 0xf8, 0x26, 0x43, 0x0c, 0x51, 0x02, 0x14, 0xd6, 0xf2,
+ 0x9d, 0x7c, 0xf5, 0x25, 0x1c, 0x78, 0x4d, 0x47, 0xaf, 0x87,
+ 0x2e, 0x38, 0x49, 0x87, 0xb5, 0x8a, 0xf3, 0xb5, 0xd4, 0x15,
+ 0x69, 0x2a, 0x52, 0xc9, 0x46, 0x97, 0x34, 0x8e, 0x50, 0x4b,
+ 0xc4, 0xf2, 0xfb, 0x39, 0xfd, 0x16, 0x68, 0xdb, 0xa8, 0x17,
+ 0xe2, 0x71, 0x4b, 0xe0, 0xdf, 0x3d, 0xfc, 0xc3, 0x9b, 0x9d,
+ 0x22, 0xc9, 0xd3, 0xf6, 0x02, 0xa6, 0x60, 0xef, 0xf7, 0x02,
+ 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03,
+ 0x81, 0x81, 0x00, 0x7d, 0xff, 0x73, 0xf3, 0x68, 0xe3, 0x75,
+ 0xf1, 0xcf, 0xac, 0x2e, 0x23, 0x73, 0xea, 0xd1, 0x26, 0x33,
+ 0xbf, 0xf9, 0x56, 0xdf, 0xbf, 0x98, 0x20, 0x84, 0x08, 0x78,
+ 0x6b, 0xe6, 0x71, 0x7e, 0x22, 0x68, 0x4d, 0x6c, 0xbb, 0xd5,
+ 0xcc, 0xb4, 0x28, 0x33, 0x5e, 0xbe, 0x4d, 0x10, 0x16, 0x9f,
+ 0x65, 0x3b, 0x68, 0x90, 0xa7, 0xf7, 0x9d, 0x57, 0x71, 0x45,
+ 0x39, 0x86, 0x4c, 0xc0, 0x97, 0x34, 0x03, 0x9c, 0x2b, 0x25,
+ 0x05, 0xb1, 0x5c, 0x0c, 0x4e, 0xf2, 0x14, 0xbf, 0xcf, 0xf0,
+ 0x9a, 0x2d, 0xcf, 0x02, 0x47, 0x60, 0xd2, 0xe9, 0xed, 0xbf,
+ 0x71, 0x5d, 0x07, 0x09, 0x01, 0x87, 0xeb, 0xf7, 0xa8, 0x26,
+ 0x86, 0x24, 0x59, 0xf0, 0x31, 0x3b, 0x42, 0xd1, 0xf1, 0xfd,
+ 0x7c, 0x49, 0x5f, 0x1a, 0xf0, 0x41, 0x67, 0xf0, 0x16, 0x3a,
+ 0xfd, 0xb6, 0xb5, 0xf6, 0x2e, 0x0c, 0x18, 0x1f, 0x09, 0x8e,
+ 0x4d ),
+ FINGERPRINT ( 0xe0, 0xdb, 0x60, 0x53, 0x7c, 0xf6, 0x25, 0x8f,
+ 0xa7, 0xba, 0xdf, 0xe2, 0x1a, 0xfc, 0x27, 0x49,
+ 0xf6, 0x83, 0x15, 0xbd, 0x1b, 0x4c, 0x3f, 0x36,
+ 0x6f, 0x33, 0xf2, 0x47, 0x8e, 0x8b, 0x38, 0xa8 ) );
+
+/*
+ * subject VeriSign Class 3 International Server CA - G3
+ * issuer VeriSign Class 3 Public Primary Certification Authority - G5
+ */
+CERTIFICATE ( verisign_crt,
+ DATA ( 0x30, 0x82, 0x06, 0x29, 0x30, 0x82, 0x05, 0x11, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x10, 0x64, 0x1b, 0xe8, 0x20, 0xce,
+ 0x02, 0x08, 0x13, 0xf3, 0x2d, 0x4d, 0x2d, 0x95, 0xd6, 0x7e,
+ 0x67, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0xca, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67,
+ 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1f, 0x30,
+ 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65,
+ 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75,
+ 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
+ 0x31, 0x3a, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13,
+ 0x31, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20,
+ 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20,
+ 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x2d, 0x20, 0x46, 0x6f, 0x72,
+ 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65,
+ 0x64, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x6e, 0x6c, 0x79,
+ 0x31, 0x45, 0x30, 0x43, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+ 0x3c, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20,
+ 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x50, 0x75,
+ 0x62, 0x6c, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61,
+ 0x72, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74,
+ 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, 0x47,
+ 0x35, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x32, 0x30,
+ 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d,
+ 0x32, 0x30, 0x30, 0x32, 0x30, 0x37, 0x32, 0x33, 0x35, 0x39,
+ 0x35, 0x39, 0x5a, 0x30, 0x81, 0xbc, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e,
+ 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20,
+ 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03,
+ 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65, 0x72, 0x69, 0x53,
+ 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20,
+ 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x3b, 0x30,
+ 0x39, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x32, 0x54, 0x65,
+ 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65,
+ 0x20, 0x61, 0x74, 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a,
+ 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69,
+ 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72,
+ 0x70, 0x61, 0x20, 0x28, 0x63, 0x29, 0x31, 0x30, 0x31, 0x36,
+ 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2d, 0x56,
+ 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6c,
+ 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20,
+ 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x20,
+ 0x2d, 0x20, 0x47, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,
+ 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0x99, 0xd6, 0x9c,
+ 0x62, 0xf0, 0x15, 0xf4, 0x81, 0x9a, 0x41, 0x08, 0x59, 0x8f,
+ 0x13, 0x9d, 0x17, 0xc9, 0x9f, 0x51, 0xdc, 0xda, 0xb1, 0x52,
+ 0xef, 0xff, 0xe3, 0x41, 0xdd, 0xe0, 0xdf, 0xc4, 0x28, 0xc6,
+ 0xe3, 0xad, 0x79, 0x1f, 0x27, 0x10, 0x98, 0xb8, 0xbb, 0x20,
+ 0x97, 0xc1, 0x28, 0x44, 0x41, 0x0f, 0xea, 0xa9, 0xa8, 0x52,
+ 0xcf, 0x4d, 0x4e, 0x1b, 0x8b, 0xbb, 0xb5, 0xc4, 0x76, 0xd9,
+ 0xcc, 0x56, 0x06, 0xee, 0xb3, 0x55, 0x20, 0x2a, 0xde, 0x15,
+ 0x8d, 0x71, 0xcb, 0x54, 0xc8, 0x6f, 0x17, 0xcd, 0x89, 0x00,
+ 0xe4, 0xdc, 0xff, 0xe1, 0xc0, 0x1f, 0x68, 0x71, 0xe9, 0xc7,
+ 0x29, 0x2e, 0x7e, 0xbc, 0x3b, 0xfc, 0xe5, 0xbb, 0xab, 0x26,
+ 0x54, 0x8b, 0x66, 0x90, 0xcd, 0xf6, 0x92, 0xb9, 0x31, 0x24,
+ 0x80, 0xbc, 0x9e, 0x6c, 0xd5, 0xfc, 0x7e, 0xd2, 0xe1, 0x4b,
+ 0x8c, 0xdc, 0x42, 0xfa, 0x44, 0x4b, 0x5f, 0xf8, 0x18, 0xb5,
+ 0x2e, 0x30, 0xf4, 0x3d, 0x12, 0x98, 0xd3, 0x62, 0x05, 0x73,
+ 0x54, 0xa6, 0x9c, 0xa2, 0x1d, 0xbe, 0x52, 0x83, 0x3a, 0x07,
+ 0x46, 0xc4, 0x3b, 0x02, 0x56, 0x21, 0xbf, 0xf2, 0x51, 0x4f,
+ 0xd0, 0xa6, 0x99, 0x39, 0xe9, 0xae, 0xa5, 0x3f, 0x89, 0x9b,
+ 0x9c, 0x7d, 0xfe, 0x4d, 0x60, 0x07, 0x25, 0x20, 0xf7, 0xbb,
+ 0xd7, 0x69, 0x83, 0x2b, 0x82, 0x93, 0x43, 0x37, 0xd9, 0x83,
+ 0x41, 0x1b, 0x6b, 0x0b, 0xab, 0x4a, 0x66, 0x84, 0x4f, 0x4a,
+ 0x8e, 0xde, 0x7e, 0x34, 0x99, 0x8e, 0x68, 0xd6, 0xca, 0x39,
+ 0x06, 0x9b, 0x4c, 0xb3, 0x9a, 0x48, 0x4d, 0x13, 0x46, 0xb4,
+ 0x58, 0x21, 0x04, 0xc4, 0xfb, 0xa0, 0x4d, 0xac, 0x2e, 0x4b,
+ 0x62, 0x12, 0xe3, 0xfb, 0x4d, 0xf6, 0xc9, 0x51, 0x00, 0x01,
+ 0x1f, 0xfc, 0x1e, 0x6a, 0x81, 0x2a, 0x38, 0xe0, 0xb9, 0x4f,
+ 0xd6, 0x2d, 0x45, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82,
+ 0x02, 0x15, 0x30, 0x82, 0x02, 0x11, 0x30, 0x12, 0x06, 0x03,
+ 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06,
+ 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x70, 0x06, 0x03,
+ 0x55, 0x1d, 0x20, 0x04, 0x69, 0x30, 0x67, 0x30, 0x65, 0x06,
+ 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x45, 0x01, 0x07,
+ 0x17, 0x03, 0x30, 0x56, 0x30, 0x28, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1c, 0x68, 0x74,
+ 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e,
+ 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x63, 0x70, 0x73, 0x30, 0x2a, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x1e,
+ 0x1a, 0x1c, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f,
+ 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69,
+ 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x70, 0x61,
+ 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff,
+ 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x6d, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x0c, 0x04, 0x61,
+ 0x30, 0x5f, 0xa1, 0x5d, 0xa0, 0x5b, 0x30, 0x59, 0x30, 0x57,
+ 0x30, 0x55, 0x16, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f,
+ 0x67, 0x69, 0x66, 0x30, 0x21, 0x30, 0x1f, 0x30, 0x07, 0x06,
+ 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14, 0x8f, 0xe5,
+ 0xd3, 0x1a, 0x86, 0xac, 0x8d, 0x8e, 0x6b, 0xc3, 0xcf, 0x80,
+ 0x6a, 0xd4, 0x48, 0x18, 0x2c, 0x7b, 0x19, 0x2e, 0x30, 0x25,
+ 0x16, 0x23, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c,
+ 0x6f, 0x67, 0x6f, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69,
+ 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x73, 0x6c,
+ 0x6f, 0x67, 0x6f, 0x2e, 0x67, 0x69, 0x66, 0x30, 0x34, 0x06,
+ 0x03, 0x55, 0x1d, 0x25, 0x04, 0x2d, 0x30, 0x2b, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01, 0x06,
+ 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x45, 0x01, 0x08,
+ 0x01, 0x30, 0x34, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x01, 0x01, 0x04, 0x28, 0x30, 0x26, 0x30, 0x24, 0x06,
+ 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86,
+ 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63,
+ 0x73, 0x70, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67,
+ 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x34, 0x06, 0x03, 0x55,
+ 0x1d, 0x1f, 0x04, 0x2d, 0x30, 0x2b, 0x30, 0x29, 0xa0, 0x27,
+ 0xa0, 0x25, 0x86, 0x23, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73,
+ 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x63,
+ 0x61, 0x33, 0x2d, 0x67, 0x35, 0x2e, 0x63, 0x72, 0x6c, 0x30,
+ 0x28, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x21, 0x30, 0x1f,
+ 0xa4, 0x1d, 0x30, 0x1b, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x13, 0x10, 0x56, 0x65, 0x72, 0x69, 0x53,
+ 0x69, 0x67, 0x6e, 0x4d, 0x50, 0x4b, 0x49, 0x2d, 0x32, 0x2d,
+ 0x37, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
+ 0x04, 0x14, 0xd7, 0x9b, 0x7c, 0xd8, 0x22, 0xa0, 0x15, 0xf7,
+ 0xdd, 0xad, 0x5f, 0xce, 0x29, 0x9b, 0x58, 0xc3, 0xbc, 0x46,
+ 0x00, 0xb5, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x18, 0x30, 0x16, 0x80, 0x14, 0x7f, 0xd3, 0x65, 0xa7, 0xc2,
+ 0xdd, 0xec, 0xbb, 0xf0, 0x30, 0x09, 0xf3, 0x43, 0x39, 0xfa,
+ 0x02, 0xaf, 0x33, 0x31, 0x33, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x03, 0x82, 0x01, 0x01, 0x00, 0x71, 0xb5, 0x7d, 0x73, 0x52,
+ 0x4a, 0xdd, 0xd7, 0x4d, 0x34, 0x2b, 0x2e, 0xaf, 0x94, 0x46,
+ 0xa5, 0x49, 0x50, 0x02, 0x4f, 0xf8, 0x2f, 0x17, 0x70, 0xf2,
+ 0x13, 0xdc, 0x1f, 0x21, 0x86, 0xaa, 0xc2, 0x4f, 0x7c, 0x37,
+ 0x3c, 0xd4, 0x46, 0x78, 0xae, 0x5d, 0x78, 0x6f, 0xd1, 0xba,
+ 0x5a, 0xbc, 0x10, 0xab, 0x58, 0x36, 0xc5, 0x8c, 0x62, 0x15,
+ 0x45, 0x60, 0x17, 0x21, 0xe2, 0xd5, 0x42, 0xa8, 0x77, 0xa1,
+ 0x55, 0xd8, 0x43, 0x04, 0x51, 0xf6, 0x6e, 0xba, 0x48, 0xe6,
+ 0x5d, 0x4c, 0xb7, 0x44, 0xd3, 0x3e, 0xa4, 0xd5, 0xd6, 0x33,
+ 0x9a, 0x9f, 0x0d, 0xe6, 0xd7, 0x4e, 0x96, 0x44, 0x95, 0x5a,
+ 0x6c, 0xd6, 0xa3, 0x16, 0x53, 0x0e, 0x98, 0x43, 0xce, 0xa4,
+ 0xb8, 0xc3, 0x66, 0x7a, 0x05, 0x5c, 0x62, 0x10, 0xe8, 0x1b,
+ 0x12, 0xdb, 0x7d, 0x2e, 0x76, 0x50, 0xff, 0xdf, 0xd7, 0x6b,
+ 0x1b, 0xcc, 0x8a, 0xcc, 0x71, 0xfa, 0xb3, 0x40, 0x56, 0x7c,
+ 0x33, 0x7a, 0x77, 0x94, 0x5b, 0xf5, 0x0b, 0x53, 0xfb, 0x0e,
+ 0x5f, 0xbc, 0x68, 0xfb, 0xaf, 0x2a, 0xee, 0x30, 0x37, 0x79,
+ 0x16, 0x93, 0x25, 0x7f, 0x4d, 0x10, 0xff, 0x57, 0xfb, 0xbf,
+ 0x6e, 0x3b, 0x33, 0x21, 0xde, 0x79, 0xdc, 0x86, 0x17, 0x59,
+ 0x2d, 0x43, 0x64, 0xb7, 0xa6, 0x66, 0x87, 0xea, 0xbc, 0x96,
+ 0x46, 0x19, 0x1a, 0x86, 0x8b, 0x6f, 0xd7, 0xb7, 0x49, 0x00,
+ 0x5b, 0xdb, 0xa3, 0xbf, 0x29, 0x9a, 0xee, 0xf7, 0xd3, 0x33,
+ 0xae, 0xa3, 0xf4, 0x9e, 0x4c, 0xca, 0x5e, 0x69, 0xd4, 0x1b,
+ 0xad, 0xb7, 0x90, 0x77, 0x6a, 0xd8, 0x59, 0x6f, 0x79, 0xab,
+ 0x01, 0xfa, 0x55, 0xf0, 0x8a, 0x21, 0x66, 0xe5, 0x65, 0x6e,
+ 0xfd, 0x7c, 0xd3, 0xdf, 0x1e, 0xeb, 0x7e, 0x3f, 0x06, 0x90,
+ 0xfb, 0x19, 0x0b, 0xd3, 0x06, 0x02, 0x1b, 0x78, 0x43, 0x99,
+ 0xa8 ),
+ FINGERPRINT ( 0x6e, 0x21, 0x87, 0x6c, 0xf1, 0x63, 0x47, 0x20,
+ 0x1f, 0x63, 0x7a, 0x17, 0x8c, 0xb4, 0x2b, 0x17,
+ 0x1d, 0x52, 0x37, 0x9a, 0xf7, 0xe5, 0xf5, 0xb6,
+ 0xf6, 0x75, 0x5b, 0x3e, 0xe9, 0xbb, 0x2e, 0xd4 ) );
+
+/*
+ * subject Thawte SGC CA
+issuer= /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
+ */
+CERTIFICATE ( thawte_crt,
+ DATA ( 0x30, 0x82, 0x03, 0x23, 0x30, 0x82, 0x02, 0x8c, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x04, 0x30, 0x00, 0x00, 0x02, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x30, 0x5f, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e,
+ 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20,
+ 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03,
+ 0x55, 0x04, 0x0b, 0x13, 0x2e, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ 0x20, 0x33, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
+ 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x43, 0x65,
+ 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74,
+ 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x35, 0x31,
+ 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d,
+ 0x31, 0x34, 0x30, 0x35, 0x31, 0x32, 0x32, 0x33, 0x35, 0x39,
+ 0x35, 0x39, 0x5a, 0x30, 0x4c, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5a, 0x41, 0x31, 0x25,
+ 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x54,
+ 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x73,
+ 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x50, 0x74,
+ 0x79, 0x29, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x16, 0x30,
+ 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0d, 0x54, 0x68,
+ 0x61, 0x77, 0x74, 0x65, 0x20, 0x53, 0x47, 0x43, 0x20, 0x43,
+ 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
+ 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+ 0xd4, 0xd3, 0x67, 0xd0, 0x8d, 0x15, 0x7f, 0xae, 0xcd, 0x31,
+ 0xfe, 0x7d, 0x1d, 0x91, 0xa1, 0x3f, 0x0b, 0x71, 0x3c, 0xac,
+ 0xcc, 0xc8, 0x64, 0xfb, 0x63, 0xfc, 0x32, 0x4b, 0x07, 0x94,
+ 0xbd, 0x6f, 0x80, 0xba, 0x2f, 0xe1, 0x04, 0x93, 0xc0, 0x33,
+ 0xfc, 0x09, 0x33, 0x23, 0xe9, 0x0b, 0x74, 0x2b, 0x71, 0xc4,
+ 0x03, 0xc6, 0xd2, 0xcd, 0xe2, 0x2f, 0xf5, 0x09, 0x63, 0xcd,
+ 0xff, 0x48, 0xa5, 0x00, 0xbf, 0xe0, 0xe7, 0xf3, 0x88, 0xb7,
+ 0x2d, 0x32, 0xde, 0x98, 0x36, 0xe6, 0x0a, 0xad, 0x00, 0x7b,
+ 0xc4, 0x64, 0x4a, 0x3b, 0x84, 0x75, 0x03, 0xf2, 0x70, 0x92,
+ 0x7d, 0x0e, 0x62, 0xf5, 0x21, 0xab, 0x69, 0x36, 0x84, 0x31,
+ 0x75, 0x90, 0xf8, 0xbf, 0xc7, 0x6c, 0x88, 0x1b, 0x06, 0x95,
+ 0x7c, 0xc9, 0xe5, 0xa8, 0xde, 0x75, 0xa1, 0x2c, 0x7a, 0x68,
+ 0xdf, 0xd5, 0xca, 0x1c, 0x87, 0x58, 0x60, 0x19, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfe, 0x30, 0x81, 0xfb, 0x30,
+ 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
+ 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30,
+ 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02,
+ 0x01, 0x06, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+ 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x01,
+ 0x06, 0x30, 0x28, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x21,
+ 0x30, 0x1f, 0xa4, 0x1d, 0x30, 0x1b, 0x31, 0x19, 0x30, 0x17,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x50, 0x72, 0x69,
+ 0x76, 0x61, 0x74, 0x65, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x33,
+ 0x2d, 0x31, 0x35, 0x30, 0x31, 0x06, 0x03, 0x55, 0x1d, 0x1f,
+ 0x04, 0x2a, 0x30, 0x28, 0x30, 0x26, 0xa0, 0x24, 0xa0, 0x22,
+ 0x86, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63,
+ 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67,
+ 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x63, 0x61, 0x33,
+ 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x32, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x26, 0x30, 0x24,
+ 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x74, 0x68, 0x61, 0x77,
+ 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x34, 0x06, 0x03,
+ 0x55, 0x1d, 0x25, 0x04, 0x2d, 0x30, 0x2b, 0x06, 0x08, 0x2b,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09, 0x60,
+ 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01, 0x06, 0x0a,
+ 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x45, 0x01, 0x08, 0x01,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x55,
+ 0xac, 0x63, 0xea, 0xde, 0xa1, 0xdd, 0xd2, 0x90, 0x5f, 0x9f,
+ 0x0b, 0xce, 0x76, 0xbe, 0x13, 0x51, 0x8f, 0x93, 0xd9, 0x05,
+ 0x2b, 0xc8, 0x1b, 0x77, 0x4b, 0xad, 0x69, 0x50, 0xa1, 0xee,
+ 0xde, 0xdc, 0xfd, 0xdb, 0x07, 0xe9, 0xe8, 0x39, 0x94, 0xdc,
+ 0xab, 0x72, 0x79, 0x2f, 0x06, 0xbf, 0xab, 0x81, 0x70, 0xc4,
+ 0xa8, 0xed, 0xea, 0x53, 0x34, 0xed, 0xef, 0x1e, 0x53, 0xd9,
+ 0x06, 0xc7, 0x56, 0x2b, 0xd1, 0x5c, 0xf4, 0xd1, 0x8a, 0x8e,
+ 0xb4, 0x2b, 0xb1, 0x37, 0x90, 0x48, 0x08, 0x42, 0x25, 0xc5,
+ 0x3e, 0x8a, 0xcb, 0x7f, 0xeb, 0x6f, 0x04, 0xd1, 0x6d, 0xc5,
+ 0x74, 0xa2, 0xf7, 0xa2, 0x7c, 0x7b, 0x60, 0x3c, 0x77, 0xcd,
+ 0x0e, 0xce, 0x48, 0x02, 0x7f, 0x01, 0x2f, 0xb6, 0x9b, 0x37,
+ 0xe0, 0x2a, 0x2a, 0x36, 0xdc, 0xd5, 0x85, 0xd6, 0xac, 0xe5,
+ 0x3f, 0x54, 0x6f, 0x96, 0x1e, 0x05, 0xaf ),
+ FINGERPRINT ( 0x10, 0x85, 0xa6, 0xf4, 0x54, 0xd0, 0xc9, 0x11,
+ 0x98, 0xfd, 0xda, 0xb1, 0x1a, 0x31, 0xc7, 0x16,
+ 0xd5, 0xdc, 0xd6, 0x8d, 0xf9, 0x1c, 0x03, 0x9c,
+ 0xe1, 0x8d, 0xca, 0x9b, 0xeb, 0x3c, 0xde, 0x3d ) );
+
+/*
+ * subject StartCom Class 2 Primary Intermediate Server CA
+ * issuer StartCom Certification Authority
+ */
+CERTIFICATE ( startssl_crt,
+ DATA ( 0x30, 0x82, 0x07, 0xe3, 0x30, 0x82, 0x05, 0xcb, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x01, 0x0b, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
+ 0x00, 0x30, 0x7d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x31, 0x16, 0x30, 0x14,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x53, 0x74, 0x61,
+ 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x4c, 0x74, 0x64, 0x2e,
+ 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13,
+ 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x69,
+ 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x43, 0x65, 0x72, 0x74,
+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x69,
+ 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x29, 0x30, 0x27, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x20, 0x53, 0x74, 0x61, 0x72,
+ 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
+ 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41,
+ 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e,
+ 0x17, 0x0d, 0x30, 0x37, 0x31, 0x30, 0x32, 0x34, 0x32, 0x30,
+ 0x35, 0x37, 0x30, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x32, 0x31,
+ 0x30, 0x32, 0x32, 0x32, 0x30, 0x35, 0x37, 0x30, 0x38, 0x5a,
+ 0x30, 0x81, 0x8c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x31, 0x16, 0x30, 0x14,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x53, 0x74, 0x61,
+ 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x4c, 0x74, 0x64, 0x2e,
+ 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13,
+ 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x69,
+ 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x43, 0x65, 0x72, 0x74,
+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x69,
+ 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x38, 0x30, 0x36, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x2f, 0x53, 0x74, 0x61, 0x72,
+ 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ 0x20, 0x32, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79,
+ 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69,
+ 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01,
+ 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe2, 0x4f, 0x39, 0x2f,
+ 0xa1, 0x8c, 0x9a, 0x85, 0xad, 0x08, 0x0e, 0x08, 0x3e, 0x57,
+ 0xf2, 0x88, 0x01, 0x21, 0x1b, 0x94, 0xa9, 0x6c, 0xe2, 0xb8,
+ 0xdb, 0xaa, 0x19, 0x18, 0x46, 0x3a, 0x52, 0xa1, 0xf5, 0x0f,
+ 0xf4, 0x6e, 0x8c, 0xea, 0x96, 0x8c, 0x96, 0x87, 0x79, 0x13,
+ 0x40, 0x51, 0x2f, 0x22, 0xf2, 0x0c, 0x8b, 0x87, 0x0f, 0x65,
+ 0xdf, 0x71, 0x74, 0x34, 0x43, 0x55, 0xb1, 0x35, 0x09, 0x9b,
+ 0xd9, 0xbc, 0x1f, 0xfa, 0xeb, 0x42, 0xd0, 0x97, 0x40, 0x72,
+ 0xb7, 0x43, 0x96, 0x3d, 0xba, 0x96, 0x9d, 0x5d, 0x50, 0x02,
+ 0x1c, 0x9b, 0x91, 0x8d, 0x9c, 0xc0, 0xac, 0xd7, 0xbb, 0x2f,
+ 0x17, 0xd7, 0xcb, 0x3e, 0x82, 0x9d, 0x73, 0xeb, 0x07, 0x42,
+ 0x92, 0xb2, 0xcd, 0x64, 0xb3, 0x74, 0x55, 0x1b, 0xb4, 0x4b,
+ 0x86, 0x21, 0x2c, 0xf7, 0x78, 0x87, 0x32, 0xe0, 0x16, 0xe4,
+ 0xda, 0xbd, 0x4c, 0x95, 0xea, 0xa4, 0x0a, 0x7e, 0xb6, 0x0a,
+ 0x0d, 0x2e, 0x8a, 0xcf, 0x55, 0xab, 0xc3, 0xe5, 0xdd, 0x41,
+ 0x8a, 0x4e, 0xe6, 0x6f, 0x65, 0x6c, 0xb2, 0x40, 0xcf, 0x17,
+ 0x5d, 0xb9, 0xc3, 0x6a, 0x0b, 0x27, 0x11, 0x84, 0x77, 0x61,
+ 0xf6, 0xc2, 0x7c, 0xed, 0xc0, 0x8d, 0x78, 0x14, 0x18, 0x99,
+ 0x81, 0x99, 0x75, 0x63, 0xb7, 0xe8, 0x53, 0xd3, 0xba, 0x61,
+ 0xe9, 0x0e, 0xfa, 0xa2, 0x30, 0xf3, 0x46, 0xa2, 0xb9, 0xc9,
+ 0x1f, 0x6c, 0x80, 0x5a, 0x40, 0xac, 0x27, 0xed, 0x48, 0x47,
+ 0x33, 0xb0, 0x54, 0xc6, 0x46, 0x1a, 0xf3, 0x35, 0x61, 0xc1,
+ 0x02, 0x29, 0x90, 0x54, 0x7e, 0x64, 0x4d, 0xc4, 0x30, 0x52,
+ 0x02, 0x82, 0xd7, 0xdf, 0xce, 0x21, 0x6e, 0x18, 0x91, 0xd7,
+ 0xb8, 0xab, 0x8c, 0x27, 0x17, 0xb5, 0xf0, 0xa3, 0x01, 0x2f,
+ 0x8e, 0xd2, 0x2e, 0x87, 0x3a, 0x3d, 0xb4, 0x29, 0x67, 0x8a,
+ 0xc4, 0x03, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x03,
+ 0x5c, 0x30, 0x82, 0x03, 0x58, 0x30, 0x0c, 0x06, 0x03, 0x55,
+ 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+ 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02,
+ 0x01, 0xa6, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
+ 0x16, 0x04, 0x14, 0x11, 0xdb, 0x23, 0x45, 0xfd, 0x54, 0xcc,
+ 0x6a, 0x71, 0x6f, 0x84, 0x8a, 0x03, 0xd7, 0xbe, 0xf7, 0x01,
+ 0x2f, 0x26, 0x86, 0x30, 0x81, 0xa8, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x81, 0xa0, 0x30, 0x81, 0x9d, 0x80, 0x14, 0x4e,
+ 0x0b, 0xef, 0x1a, 0xa4, 0x40, 0x5b, 0xa5, 0x17, 0x69, 0x87,
+ 0x30, 0xca, 0x34, 0x68, 0x43, 0xd0, 0x41, 0xae, 0xf2, 0xa1,
+ 0x81, 0x81, 0xa4, 0x7f, 0x30, 0x7d, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x31,
+ 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d,
+ 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x4c,
+ 0x74, 0x64, 0x2e, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x13, 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65,
+ 0x20, 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x43,
+ 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65,
+ 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x29,
+ 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x20, 0x53,
+ 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x65,
+ 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74,
+ 0x79, 0x82, 0x01, 0x01, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d,
+ 0x12, 0x04, 0x02, 0x30, 0x00, 0x30, 0x3d, 0x06, 0x08, 0x2b,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x31, 0x30,
+ 0x2f, 0x30, 0x2d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x02, 0x86, 0x21, 0x68, 0x74, 0x74, 0x70, 0x3a,
+ 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x74, 0x61, 0x72,
+ 0x74, 0x73, 0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73,
+ 0x66, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x60,
+ 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x59, 0x30, 0x57, 0x30,
+ 0x2c, 0xa0, 0x2a, 0xa0, 0x28, 0x86, 0x26, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x73,
+ 0x74, 0x61, 0x72, 0x74, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x72,
+ 0x67, 0x2f, 0x73, 0x66, 0x73, 0x63, 0x61, 0x2d, 0x63, 0x72,
+ 0x6c, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x27, 0xa0, 0x25, 0xa0,
+ 0x23, 0x86, 0x21, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x63, 0x72, 0x6c, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73,
+ 0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x66, 0x73,
+ 0x63, 0x61, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x82, 0x01, 0x5d,
+ 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x82, 0x01, 0x54, 0x30,
+ 0x82, 0x01, 0x50, 0x30, 0x82, 0x01, 0x4c, 0x06, 0x0b, 0x2b,
+ 0x06, 0x01, 0x04, 0x01, 0x81, 0xb5, 0x37, 0x01, 0x01, 0x04,
+ 0x30, 0x82, 0x01, 0x3b, 0x30, 0x2f, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x23, 0x68, 0x74,
+ 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x2e,
+ 0x73, 0x74, 0x61, 0x72, 0x74, 0x63, 0x6f, 0x6d, 0x2e, 0x6f,
+ 0x72, 0x67, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
+ 0x70, 0x64, 0x66, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01,
+ 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x29, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x73,
+ 0x74, 0x61, 0x72, 0x74, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x72,
+ 0x67, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64,
+ 0x69, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x64, 0x66, 0x30, 0x81,
+ 0xd0, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02,
+ 0x02, 0x30, 0x81, 0xc3, 0x30, 0x27, 0x16, 0x20, 0x53, 0x74,
+ 0x61, 0x72, 0x74, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
+ 0x63, 0x69, 0x61, 0x6c, 0x20, 0x28, 0x53, 0x74, 0x61, 0x72,
+ 0x74, 0x43, 0x6f, 0x6d, 0x29, 0x20, 0x4c, 0x74, 0x64, 0x2e,
+ 0x30, 0x03, 0x02, 0x01, 0x01, 0x1a, 0x81, 0x97, 0x4c, 0x69,
+ 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x4c, 0x69, 0x61, 0x62,
+ 0x69, 0x6c, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x72, 0x65, 0x61,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x2a, 0x4c, 0x65, 0x67, 0x61, 0x6c,
+ 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x2a, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20,
+ 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
+ 0x69, 0x74, 0x79, 0x20, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79,
+ 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65,
+ 0x20, 0x61, 0x74, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x73, 0x74, 0x61, 0x72,
+ 0x74, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70,
+ 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x64, 0x66, 0x30,
+ 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42,
+ 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x00, 0x07, 0x30, 0x51,
+ 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01,
+ 0x0d, 0x04, 0x44, 0x16, 0x42, 0x53, 0x74, 0x61, 0x72, 0x74,
+ 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20,
+ 0x32, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20,
+ 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61,
+ 0x74, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x53,
+ 0x4c, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43,
+ 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65,
+ 0x73, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01,
+ 0x00, 0x64, 0x82, 0x4c, 0x59, 0x5c, 0x0c, 0x6c, 0x16, 0xb6,
+ 0xa2, 0x39, 0x45, 0x11, 0x87, 0x98, 0xdf, 0x10, 0x33, 0xae,
+ 0x42, 0x9e, 0x25, 0xd1, 0xfd, 0x70, 0x53, 0x45, 0x5e, 0xf4,
+ 0x35, 0xc0, 0xe4, 0x30, 0x77, 0xe0, 0x9c, 0xf7, 0xef, 0x27,
+ 0xe5, 0x6e, 0x28, 0xef, 0xac, 0xd7, 0xf3, 0x16, 0xcc, 0xc1,
+ 0x6c, 0x53, 0x9c, 0x8f, 0x2d, 0x82, 0x6f, 0x94, 0xf7, 0x14,
+ 0x36, 0x17, 0xae, 0xb2, 0xe5, 0xa2, 0x3f, 0xa2, 0x83, 0x73,
+ 0xa4, 0xdf, 0xa8, 0xbb, 0xca, 0x01, 0x31, 0x6c, 0x9a, 0x43,
+ 0x08, 0xdd, 0x1a, 0x5d, 0xad, 0x4b, 0x6d, 0x7f, 0xf4, 0x7e,
+ 0xf0, 0x12, 0x3a, 0x05, 0xbf, 0xa7, 0x44, 0x10, 0x07, 0x17,
+ 0x44, 0x93, 0x50, 0xe3, 0x95, 0x29, 0xb3, 0xf4, 0x13, 0xd2,
+ 0x40, 0xe0, 0x3e, 0xdf, 0x3d, 0x3d, 0x39, 0x5e, 0x81, 0x48,
+ 0x0f, 0x32, 0xba, 0x48, 0xd5, 0x03, 0x1b, 0xf5, 0xf7, 0x4e,
+ 0x0a, 0x8e, 0x03, 0x8d, 0xfc, 0xca, 0x87, 0xe6, 0xc9, 0xdf,
+ 0x26, 0xdf, 0x84, 0x3a, 0x49, 0xb1, 0x99, 0x55, 0x3f, 0xd4,
+ 0x2c, 0xab, 0x78, 0x0d, 0x62, 0x03, 0x15, 0x9f, 0xb1, 0x45,
+ 0x4b, 0x23, 0x78, 0x62, 0x2a, 0xee, 0xeb, 0x7b, 0x60, 0x2d,
+ 0x77, 0x72, 0x1e, 0x61, 0x24, 0x69, 0x62, 0xe8, 0xe1, 0x35,
+ 0x3c, 0x82, 0x02, 0x40, 0x15, 0x32, 0x4b, 0x57, 0xcd, 0x97,
+ 0xb9, 0x29, 0x8f, 0xa4, 0xd7, 0x84, 0xdb, 0x09, 0xe5, 0x35,
+ 0x5b, 0x2f, 0x60, 0x59, 0x49, 0xe9, 0xd6, 0x59, 0xf5, 0xfa,
+ 0x5d, 0xc8, 0xcd, 0x4d, 0x94, 0x70, 0xc4, 0xe8, 0x3c, 0x35,
+ 0x01, 0x06, 0x75, 0xe8, 0x71, 0x9b, 0x7f, 0x2b, 0x10, 0xca,
+ 0x6b, 0x3f, 0xc0, 0xb3, 0x97, 0x72, 0xda, 0xff, 0x74, 0x16,
+ 0x8e, 0xfb, 0xfb, 0x9b, 0xe4, 0x05, 0xf0, 0x98, 0xe7, 0x15,
+ 0xac, 0xca, 0x24, 0xa2, 0xe7, 0x8a, 0xb4, 0xcf, 0x72, 0x31,
+ 0x2b, 0xe3, 0x31, 0x0e, 0x30, 0x5f, 0xd5, 0xcb, 0x94, 0xb3,
+ 0xee, 0x35, 0x04, 0xd3, 0x45, 0x07, 0x09, 0x14, 0x51, 0x8a,
+ 0xf5, 0x07, 0x31, 0x5e, 0x13, 0x2f, 0x5d, 0x0c, 0xd9, 0xd7,
+ 0x36, 0xa8, 0xb0, 0x52, 0x37, 0x94, 0xc2, 0x75, 0x9c, 0x5a,
+ 0x2e, 0xa8, 0xd1, 0xb0, 0x73, 0x6b, 0x69, 0xda, 0x0c, 0x3a,
+ 0xd6, 0x11, 0x6b, 0xac, 0x9d, 0xbc, 0x45, 0x32, 0x05, 0xe8,
+ 0x89, 0x77, 0xd5, 0xb7, 0xbe, 0xc0, 0xed, 0xcd, 0xcd, 0x4e,
+ 0x6d, 0x28, 0x58, 0x0a, 0xf0, 0xb4, 0x51, 0xc8, 0xcd, 0x86,
+ 0xd1, 0x89, 0x23, 0xc5, 0x23, 0xed, 0xcf, 0x10, 0xf9, 0x0e,
+ 0x6e, 0xd8, 0xc1, 0xd7, 0x3f, 0x80, 0xfa, 0xa6, 0x2a, 0x47,
+ 0xc4, 0xdb, 0x07, 0x16, 0xe7, 0x0b, 0x8b, 0x53, 0x97, 0x11,
+ 0x2e, 0xa3, 0x61, 0x27, 0xb3, 0xbb, 0x4a, 0xd7, 0x01, 0x6d,
+ 0xb1, 0x71, 0xa5, 0xe5, 0x23, 0xd6, 0xda, 0xa1, 0xa8, 0x55,
+ 0x26, 0xaf, 0xb7, 0xba, 0x5e, 0x56, 0x2d, 0x3d, 0x10, 0xa3,
+ 0x71, 0x4a, 0x93, 0x45, 0x1c, 0x7a, 0x3c, 0x92, 0x2a, 0x69,
+ 0x3f, 0x4f, 0x1e, 0x96, 0x99, 0x90, 0x09, 0xc8, 0x01, 0xbf,
+ 0x28, 0x34, 0xb2, 0x7d, 0x11, 0x50, 0x59, 0xd0, 0x9b, 0xe3,
+ 0x33, 0x56, 0x65, 0xee, 0x98, 0x97, 0x3f, 0x3e, 0x54, 0x69,
+ 0x2d, 0x26, 0x2e, 0x03, 0x2b, 0xa0, 0xbe, 0xab, 0x6b, 0x80,
+ 0x20, 0xe1, 0x3a, 0x4b, 0xbb, 0x26, 0xbe, 0xab, 0xab, 0xa5,
+ 0x39, 0xb1, 0x9a, 0x49, 0xa6, 0xb4, 0x5b, 0x96, 0x66, 0xe2,
+ 0x49, 0x0b, 0x70, 0x02, 0xaa, 0x49, 0x49, 0x61, 0x0e, 0xfe,
+ 0xae, 0xf5, 0xa5, 0x96, 0xe7, 0xf6, 0xba, 0x6c, 0x89, 0x9f,
+ 0x0e, 0x72, 0xec, 0xfb, 0x45, 0x00, 0x87, 0x8f, 0x2c, 0xe7,
+ 0x7f, 0xb2, 0xc5, 0xa5, 0x52, 0xbe, 0x03, 0xfa, 0x31, 0x2a,
+ 0x02, 0x6a, 0xf8 ),
+ FINGERPRINT ( 0x9f, 0xd1, 0x93, 0xd3, 0x8f, 0x95, 0x30, 0xab,
+ 0x55, 0xa5, 0xc1, 0xb3, 0x51, 0x4a, 0x1d, 0x64,
+ 0x1c, 0xec, 0xc2, 0x1c, 0xc5, 0xc2, 0xf5, 0x67,
+ 0x48, 0xa7, 0x11, 0x01, 0x69, 0x83, 0xfd, 0x8e ) );
+
+OCSP ( barclays_ocsp, &barclays_crt, &verisign_crt,
+ DATA ( 0x30, 0x51, 0x30, 0x4f, 0x30, 0x4d, 0x30, 0x4b, 0x30, 0x49,
+ 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+ 0x00, 0x04, 0x14, 0xd4, 0xb4, 0x3b, 0x8e, 0x3d, 0x02, 0x49,
+ 0x1a, 0x65, 0x50, 0x6f, 0x96, 0x73, 0x14, 0xdd, 0xe8, 0x59,
+ 0x44, 0x52, 0xe4, 0x04, 0x14, 0xd7, 0x9b, 0x7c, 0xd8, 0x22,
+ 0xa0, 0x15, 0xf7, 0xdd, 0xad, 0x5f, 0xce, 0x29, 0x9b, 0x58,
+ 0xc3, 0xbc, 0x46, 0x00, 0xb5, 0x02, 0x10, 0x49, 0x83, 0xfc,
+ 0x05, 0x76, 0xdf, 0x36, 0x91, 0x7c, 0x64, 0x2a, 0x27, 0xc1,
+ 0xf1, 0x48, 0xe3 ),
+ DATA ( 0x30, 0x82, 0x06, 0x4d, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x06,
+ 0x46, 0x30, 0x82, 0x06, 0x42, 0x06, 0x09, 0x2b, 0x06, 0x01,
+ 0x05, 0x05, 0x07, 0x30, 0x01, 0x01, 0x04, 0x82, 0x06, 0x33,
+ 0x30, 0x82, 0x06, 0x2f, 0x30, 0x82, 0x01, 0x1f, 0xa0, 0x03,
+ 0x02, 0x01, 0x00, 0xa1, 0x81, 0x91, 0x30, 0x81, 0x8e, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67,
+ 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1f, 0x30,
+ 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65,
+ 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75,
+ 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
+ 0x31, 0x45, 0x30, 0x43, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+ 0x3c, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20,
+ 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x49, 0x6e,
+ 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61,
+ 0x6c, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43,
+ 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x20, 0x4f, 0x43, 0x53,
+ 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65,
+ 0x72, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x35, 0x31,
+ 0x34, 0x31, 0x34, 0x30, 0x31, 0x34, 0x31, 0x5a, 0x30, 0x73,
+ 0x30, 0x71, 0x30, 0x49, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
+ 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0xd4, 0xb4, 0x3b,
+ 0x8e, 0x3d, 0x02, 0x49, 0x1a, 0x65, 0x50, 0x6f, 0x96, 0x73,
+ 0x14, 0xdd, 0xe8, 0x59, 0x44, 0x52, 0xe4, 0x04, 0x14, 0xd7,
+ 0x9b, 0x7c, 0xd8, 0x22, 0xa0, 0x15, 0xf7, 0xdd, 0xad, 0x5f,
+ 0xce, 0x29, 0x9b, 0x58, 0xc3, 0xbc, 0x46, 0x00, 0xb5, 0x02,
+ 0x10, 0x49, 0x83, 0xfc, 0x05, 0x76, 0xdf, 0x36, 0x91, 0x7c,
+ 0x64, 0x2a, 0x27, 0xc1, 0xf1, 0x48, 0xe3, 0x80, 0x00, 0x18,
+ 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x35, 0x31, 0x34, 0x31,
+ 0x34, 0x30, 0x31, 0x34, 0x31, 0x5a, 0xa0, 0x11, 0x18, 0x0f,
+ 0x32, 0x30, 0x31, 0x32, 0x30, 0x35, 0x32, 0x31, 0x31, 0x34,
+ 0x30, 0x31, 0x34, 0x31, 0x5a, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x03, 0x81, 0x81, 0x00, 0x78, 0xa8, 0xe7, 0xdc, 0xaf, 0xf2,
+ 0x8b, 0xc2, 0x9f, 0x99, 0xf9, 0x44, 0x84, 0xa8, 0x8a, 0x2c,
+ 0x35, 0xd7, 0x91, 0xd8, 0x44, 0x3e, 0xd6, 0xe0, 0xc6, 0x3f,
+ 0xbf, 0xe3, 0x71, 0x22, 0x45, 0x5a, 0x73, 0xf4, 0x59, 0x1b,
+ 0x4c, 0xa5, 0x51, 0x21, 0x5c, 0xfa, 0xbe, 0x10, 0xcb, 0x5f,
+ 0xb0, 0x2f, 0xef, 0x22, 0x89, 0xf6, 0xc7, 0x0f, 0x7c, 0x6d,
+ 0x26, 0xbe, 0x83, 0x99, 0xe2, 0x02, 0xf5, 0x95, 0x6e, 0xca,
+ 0xd9, 0x6d, 0xdd, 0xc2, 0xf0, 0xf2, 0x4f, 0x99, 0x66, 0x93,
+ 0x6e, 0x2e, 0xcf, 0xc5, 0xab, 0x68, 0x5f, 0xde, 0x52, 0x3d,
+ 0xf2, 0x23, 0x9d, 0xe8, 0x99, 0xd5, 0xf4, 0x4f, 0x8a, 0xf3,
+ 0xfd, 0x99, 0xa3, 0xe3, 0x12, 0x56, 0xd1, 0x54, 0xf1, 0xe1,
+ 0x24, 0xa0, 0xce, 0xeb, 0x80, 0xb6, 0xde, 0x44, 0xa8, 0xef,
+ 0xb1, 0xfc, 0x9c, 0x76, 0xbb, 0x1f, 0x17, 0x40, 0xbe, 0x2a,
+ 0xc8, 0x12, 0xa0, 0x82, 0x04, 0x75, 0x30, 0x82, 0x04, 0x71,
+ 0x30, 0x82, 0x04, 0x6d, 0x30, 0x82, 0x03, 0x55, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x10, 0x68, 0x8e, 0x69, 0x1f, 0x05,
+ 0x02, 0x11, 0x40, 0x45, 0x8e, 0xf0, 0x39, 0x24, 0x07, 0xcf,
+ 0xd6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0xbc, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67,
+ 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1f, 0x30,
+ 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65,
+ 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75,
+ 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
+ 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13,
+ 0x32, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x75, 0x73, 0x65, 0x20, 0x61, 0x74, 0x20, 0x68, 0x74, 0x74,
+ 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76,
+ 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x2f, 0x72, 0x70, 0x61, 0x20, 0x28, 0x63, 0x29, 0x31,
+ 0x30, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x13, 0x2d, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e,
+ 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x49,
+ 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
+ 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x30, 0x1e, 0x17,
+ 0x0d, 0x31, 0x32, 0x30, 0x33, 0x31, 0x33, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x36,
+ 0x31, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30,
+ 0x81, 0x8e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69,
+ 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
+ 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13,
+ 0x16, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20,
+ 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77,
+ 0x6f, 0x72, 0x6b, 0x31, 0x45, 0x30, 0x43, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x3c, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69,
+ 0x67, 0x6e, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33,
+ 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65,
+ 0x72, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x20,
+ 0x4f, 0x43, 0x53, 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x64, 0x65, 0x72, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02,
+ 0x81, 0x81, 0x00, 0xa4, 0x3c, 0x3c, 0x43, 0xd3, 0x33, 0x14,
+ 0x0a, 0xb4, 0x5e, 0x25, 0x03, 0x6d, 0x60, 0x6c, 0x2f, 0xc9,
+ 0x33, 0x11, 0xe6, 0x79, 0xd9, 0x8c, 0x4a, 0x05, 0x60, 0xad,
+ 0x16, 0x8b, 0x23, 0x67, 0x8b, 0x1a, 0xaf, 0x84, 0xc3, 0xbb,
+ 0x6b, 0xcf, 0x9e, 0xf7, 0x65, 0x6d, 0x04, 0x97, 0xca, 0x12,
+ 0x96, 0x0b, 0x30, 0x7f, 0x0d, 0x6e, 0x7f, 0x81, 0x49, 0x53,
+ 0xf3, 0xcb, 0x5c, 0x00, 0xd8, 0x6d, 0xf9, 0x03, 0xf4, 0x23,
+ 0xd6, 0xd2, 0x9e, 0x8c, 0xca, 0x41, 0xfd, 0xa1, 0x02, 0x20,
+ 0xc8, 0x70, 0xb0, 0xfb, 0xaa, 0x1b, 0x33, 0x1e, 0x64, 0x30,
+ 0x70, 0x36, 0xed, 0x7b, 0xac, 0xe8, 0x64, 0xd9, 0x79, 0xa8,
+ 0x48, 0x20, 0x02, 0xdd, 0x8c, 0x02, 0x6f, 0x87, 0x2f, 0xad,
+ 0x29, 0x99, 0x8e, 0x15, 0x2c, 0xd1, 0xe0, 0x64, 0x82, 0x24,
+ 0x77, 0x31, 0xee, 0xb8, 0x68, 0xd1, 0x02, 0x32, 0xfb, 0xf0,
+ 0xcd, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x19,
+ 0x30, 0x82, 0x01, 0x15, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d,
+ 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x81, 0xac, 0x06, 0x03,
+ 0x55, 0x1d, 0x20, 0x04, 0x81, 0xa4, 0x30, 0x81, 0xa1, 0x30,
+ 0x81, 0x9e, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8,
+ 0x45, 0x01, 0x07, 0x17, 0x03, 0x30, 0x81, 0x8e, 0x30, 0x28,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01,
+ 0x16, 0x1c, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f,
+ 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69,
+ 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53,
+ 0x30, 0x62, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x02, 0x02, 0x30, 0x56, 0x30, 0x15, 0x16, 0x0e, 0x56, 0x65,
+ 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e,
+ 0x63, 0x2e, 0x30, 0x03, 0x02, 0x01, 0x01, 0x1a, 0x3d, 0x56,
+ 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x27, 0x73, 0x20,
+ 0x43, 0x50, 0x53, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70,
+ 0x2e, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72,
+ 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6c, 0x69, 0x61, 0x62, 0x2e,
+ 0x20, 0x6c, 0x74, 0x64, 0x2e, 0x20, 0x28, 0x63, 0x29, 0x39,
+ 0x37, 0x20, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e,
+ 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30,
+ 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03,
+ 0x09, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04,
+ 0x03, 0x02, 0x07, 0x80, 0x30, 0x0f, 0x06, 0x09, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x05, 0x04, 0x02, 0x05,
+ 0x00, 0x30, 0x26, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x1f,
+ 0x30, 0x1d, 0xa4, 0x1b, 0x30, 0x19, 0x31, 0x17, 0x30, 0x15,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0e, 0x4f, 0x43, 0x53,
+ 0x50, 0x38, 0x2d, 0x54, 0x47, 0x56, 0x37, 0x2d, 0x32, 0x38,
+ 0x35, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01,
+ 0x00, 0x3b, 0xce, 0xd6, 0xa6, 0x61, 0x41, 0x3d, 0xb2, 0xc4,
+ 0x75, 0x00, 0x45, 0xf9, 0x3c, 0x2f, 0x2e, 0x4a, 0x8b, 0xfb,
+ 0x9c, 0xff, 0x15, 0xcb, 0x28, 0x65, 0xde, 0xc6, 0x97, 0xd8,
+ 0x85, 0x32, 0xa2, 0xfe, 0x74, 0x2d, 0xed, 0x34, 0xf8, 0x3c,
+ 0x15, 0xac, 0xfe, 0x72, 0x7f, 0x8c, 0x0e, 0x24, 0xdd, 0xb2,
+ 0x80, 0x55, 0xbd, 0x10, 0x0d, 0xa8, 0xb6, 0xf3, 0xe0, 0x98,
+ 0x8f, 0x24, 0x0b, 0xa0, 0x9d, 0x2c, 0x05, 0x20, 0x13, 0x4d,
+ 0x0b, 0x15, 0x2d, 0x1a, 0x02, 0x76, 0x0a, 0x5a, 0xb2, 0xb9,
+ 0xce, 0x6f, 0xb8, 0xc1, 0xec, 0xc4, 0xde, 0x46, 0xe4, 0xec,
+ 0x32, 0x05, 0x2d, 0xca, 0xb1, 0x4c, 0x59, 0x41, 0x13, 0x47,
+ 0x44, 0x9a, 0x55, 0x20, 0x26, 0xcc, 0x0d, 0x66, 0xb2, 0xd1,
+ 0x76, 0x87, 0x74, 0x73, 0xea, 0x5e, 0xe9, 0x49, 0xaf, 0x57,
+ 0x9c, 0xa6, 0x3d, 0xe5, 0x2c, 0x28, 0x21, 0xe5, 0x0a, 0x80,
+ 0xae, 0x99, 0x44, 0xe9, 0x83, 0x78, 0x7e, 0x24, 0xb5, 0xfa,
+ 0x50, 0x9d, 0x32, 0x55, 0x70, 0x73, 0xaf, 0x10, 0x92, 0xd3,
+ 0x14, 0xd3, 0x69, 0xfa, 0xa6, 0x81, 0x5c, 0xba, 0x9d, 0x18,
+ 0x25, 0xda, 0x78, 0x47, 0x33, 0x83, 0xd1, 0xc3, 0x96, 0x12,
+ 0x6f, 0x8b, 0xc9, 0x98, 0x32, 0x79, 0x59, 0x76, 0xcb, 0x56,
+ 0x7f, 0x5e, 0x6d, 0x1e, 0x78, 0xb2, 0xd0, 0x39, 0x3c, 0x41,
+ 0xd7, 0xab, 0x77, 0x2a, 0x0e, 0xbb, 0xc8, 0x69, 0xae, 0xfd,
+ 0x9c, 0x20, 0x11, 0xba, 0x0a, 0x5d, 0x00, 0x58, 0xf8, 0x74,
+ 0xb0, 0x77, 0x36, 0x9b, 0x8e, 0xd5, 0x4d, 0x85, 0xb1, 0xbb,
+ 0xcd, 0xcb, 0x1d, 0xee, 0x08, 0xb9, 0x53, 0x9a, 0x5f, 0xe3,
+ 0x88, 0xb1, 0x1a, 0xc3, 0x41, 0x41, 0x3e, 0x06, 0xf7, 0x70,
+ 0x58, 0xe8, 0x22, 0x22, 0xd7, 0x0e, 0xbb, 0x88, 0xce, 0x73,
+ 0x0e, 0xd0, 0x04, 0x81, 0x50, 0xd2, 0x33 ) );
+
+OCSP ( google_ocsp, &google_crt, &thawte_crt,
+ DATA ( 0x30, 0x51, 0x30, 0x4f, 0x30, 0x4d, 0x30, 0x4b, 0x30, 0x49,
+ 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+ 0x00, 0x04, 0x14, 0x1e, 0x92, 0x09, 0xaa, 0x71, 0x3c, 0x79,
+ 0x4b, 0xca, 0x1e, 0x93, 0x1a, 0x0a, 0x61, 0xad, 0x3f, 0xd0,
+ 0xba, 0x60, 0x83, 0x04, 0x14, 0x3b, 0x34, 0x9a, 0x70, 0x91,
+ 0x73, 0xb2, 0x8a, 0x1b, 0x0c, 0xf4, 0xe9, 0x37, 0xcd, 0xb3,
+ 0x70, 0x32, 0x9e, 0x18, 0x54, 0x02, 0x10, 0x4f, 0x9d, 0x96,
+ 0xd9, 0x66, 0xb0, 0x99, 0x2b, 0x54, 0xc2, 0x95, 0x7c, 0xb4,
+ 0x15, 0x7d, 0x4d ),
+ DATA ( 0x30, 0x82, 0x04, 0x38, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x04,
+ 0x31, 0x30, 0x82, 0x04, 0x2d, 0x06, 0x09, 0x2b, 0x06, 0x01,
+ 0x05, 0x05, 0x07, 0x30, 0x01, 0x01, 0x04, 0x82, 0x04, 0x1e,
+ 0x30, 0x82, 0x04, 0x1a, 0x30, 0x81, 0xe7, 0xa0, 0x03, 0x02,
+ 0x01, 0x00, 0xa1, 0x5a, 0x30, 0x58, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5a, 0x41, 0x31,
+ 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c,
+ 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e,
+ 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x50,
+ 0x74, 0x79, 0x29, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x22,
+ 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x54,
+ 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x53, 0x47, 0x43, 0x20,
+ 0x4f, 0x43, 0x53, 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x64, 0x65, 0x72, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32,
+ 0x30, 0x35, 0x31, 0x32, 0x31, 0x39, 0x33, 0x31, 0x34, 0x33,
+ 0x5a, 0x30, 0x73, 0x30, 0x71, 0x30, 0x49, 0x30, 0x09, 0x06,
+ 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14,
+ 0x1e, 0x92, 0x09, 0xaa, 0x71, 0x3c, 0x79, 0x4b, 0xca, 0x1e,
+ 0x93, 0x1a, 0x0a, 0x61, 0xad, 0x3f, 0xd0, 0xba, 0x60, 0x83,
+ 0x04, 0x14, 0x3b, 0x34, 0x9a, 0x70, 0x91, 0x73, 0xb2, 0x8a,
+ 0x1b, 0x0c, 0xf4, 0xe9, 0x37, 0xcd, 0xb3, 0x70, 0x32, 0x9e,
+ 0x18, 0x54, 0x02, 0x10, 0x4f, 0x9d, 0x96, 0xd9, 0x66, 0xb0,
+ 0x99, 0x2b, 0x54, 0xc2, 0x95, 0x7c, 0xb4, 0x15, 0x7d, 0x4d,
+ 0x80, 0x00, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x35,
+ 0x31, 0x32, 0x31, 0x39, 0x33, 0x31, 0x34, 0x33, 0x5a, 0xa0,
+ 0x11, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x35, 0x31,
+ 0x39, 0x31, 0x39, 0x33, 0x31, 0x34, 0x33, 0x5a, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x57, 0xf9, 0xf8,
+ 0x26, 0x0f, 0xda, 0x0c, 0xc2, 0xf0, 0xe4, 0x80, 0xd0, 0x29,
+ 0xd6, 0x04, 0x77, 0xab, 0x0c, 0xf6, 0x7e, 0x77, 0xc9, 0xac,
+ 0x53, 0xa4, 0x4d, 0x6b, 0x75, 0x58, 0xb9, 0xc7, 0x7a, 0x9a,
+ 0x39, 0x5d, 0x4c, 0xfd, 0x15, 0x1b, 0x47, 0x55, 0x8e, 0x39,
+ 0x05, 0x2b, 0x06, 0x2f, 0x3e, 0x1d, 0x3a, 0x7c, 0x2c, 0xf4,
+ 0x4c, 0x70, 0x6a, 0x58, 0x7a, 0x4b, 0x8f, 0x77, 0xaf, 0x9e,
+ 0xcf, 0xc6, 0xb1, 0x66, 0x8d, 0xed, 0xbf, 0xc1, 0xd9, 0xe1,
+ 0x78, 0x5a, 0x18, 0x61, 0xca, 0xa8, 0xf5, 0x2b, 0xe3, 0x9b,
+ 0x50, 0x25, 0x60, 0x7d, 0x8d, 0xd1, 0xe0, 0x76, 0xbb, 0x5c,
+ 0x7b, 0xc1, 0x5d, 0xe1, 0x27, 0x3f, 0x7f, 0x9b, 0xb3, 0xb0,
+ 0xb2, 0x79, 0x37, 0xd4, 0x53, 0x29, 0x62, 0x46, 0x8f, 0xe6,
+ 0x34, 0x9e, 0xe5, 0x6e, 0x63, 0x5d, 0xcc, 0xb3, 0xb2, 0xe2,
+ 0x73, 0x7e, 0xa6, 0xad, 0xa0, 0xa0, 0x82, 0x02, 0x99, 0x30,
+ 0x82, 0x02, 0x95, 0x30, 0x82, 0x02, 0x91, 0x30, 0x82, 0x01,
+ 0xfa, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x67, 0x4d,
+ 0x9b, 0x61, 0x8f, 0x57, 0xcd, 0x51, 0xfb, 0x58, 0x07, 0x66,
+ 0x1d, 0x24, 0xf5, 0xa5, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
+ 0x4c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x5a, 0x41, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x54, 0x68, 0x61, 0x77, 0x74,
+ 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x74, 0x69,
+ 0x6e, 0x67, 0x20, 0x28, 0x50, 0x74, 0x79, 0x29, 0x20, 0x4c,
+ 0x74, 0x64, 0x2e, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x0d, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65,
+ 0x20, 0x53, 0x47, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17,
+ 0x0d, 0x31, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x36,
+ 0x30, 0x32, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30,
+ 0x58, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x5a, 0x41, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x54, 0x68, 0x61, 0x77, 0x74,
+ 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x74, 0x69,
+ 0x6e, 0x67, 0x20, 0x28, 0x50, 0x74, 0x79, 0x29, 0x20, 0x4c,
+ 0x74, 0x64, 0x2e, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x19, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65,
+ 0x20, 0x53, 0x47, 0x43, 0x20, 0x4f, 0x43, 0x53, 0x50, 0x20,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x30,
+ 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+ 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xc2, 0x21,
+ 0x52, 0xe2, 0x10, 0x44, 0xe3, 0xc7, 0xe3, 0x72, 0x19, 0x01,
+ 0xa8, 0x0c, 0x5a, 0x8b, 0x63, 0x0b, 0x30, 0x4c, 0x4f, 0xa2,
+ 0xe2, 0xdf, 0x62, 0x2e, 0xdf, 0xe2, 0x77, 0xb9, 0x27, 0x3b,
+ 0x8d, 0x45, 0xe2, 0xa1, 0x21, 0x95, 0x13, 0x5a, 0xf2, 0x7d,
+ 0x58, 0x2c, 0x6d, 0x53, 0xb2, 0x42, 0x52, 0x8f, 0x8e, 0xf4,
+ 0x17, 0xc5, 0xcb, 0xfa, 0x2f, 0x2d, 0x9b, 0x02, 0xd0, 0x1a,
+ 0xf1, 0x32, 0xc5, 0xb9, 0xd3, 0x5a, 0xc0, 0xd6, 0x20, 0xb8,
+ 0x3f, 0xa3, 0x93, 0x8b, 0xe5, 0x22, 0x91, 0x1a, 0x7e, 0x7c,
+ 0x8b, 0x35, 0xeb, 0x94, 0xee, 0xe6, 0xcc, 0x58, 0xe4, 0x3c,
+ 0xcd, 0x00, 0x86, 0xaa, 0xc3, 0x2e, 0x8b, 0xb4, 0x3c, 0x29,
+ 0x11, 0x21, 0x5d, 0x71, 0x4a, 0xb6, 0x7a, 0x22, 0xa9, 0xf2,
+ 0xf8, 0x90, 0xed, 0x5c, 0x73, 0x8c, 0xe0, 0x70, 0x56, 0xde,
+ 0x70, 0xc5, 0x0d, 0x81, 0xb4, 0x5b, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0xa3, 0x68, 0x30, 0x66, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x13, 0x06, 0x03,
+ 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x09, 0x30, 0x0b, 0x06,
+ 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80,
+ 0x30, 0x0f, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x30, 0x01, 0x05, 0x04, 0x02, 0x05, 0x00, 0x30, 0x26, 0x06,
+ 0x03, 0x55, 0x1d, 0x11, 0x04, 0x1f, 0x30, 0x1d, 0xa4, 0x1b,
+ 0x30, 0x19, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x0e, 0x4f, 0x43, 0x53, 0x50, 0x38, 0x2d, 0x54,
+ 0x47, 0x56, 0x37, 0x2d, 0x32, 0x37, 0x35, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x98, 0x50, 0x14, 0xbe,
+ 0x31, 0x44, 0x01, 0x97, 0xee, 0x21, 0xf9, 0xcf, 0xa4, 0x32,
+ 0xc2, 0x91, 0x6a, 0x4b, 0x02, 0x61, 0x62, 0xa9, 0xe4, 0xad,
+ 0x8a, 0xac, 0xe4, 0x12, 0x12, 0xbe, 0x9b, 0xba, 0x4c, 0xe2,
+ 0x92, 0xdb, 0x8b, 0x92, 0x11, 0xe6, 0x9e, 0x25, 0x2e, 0xd5,
+ 0x4b, 0xe8, 0x5d, 0xc8, 0x63, 0xd2, 0xff, 0xfa, 0x80, 0x89,
+ 0x83, 0x0f, 0xe4, 0xe2, 0x91, 0xcc, 0x0a, 0x85, 0x74, 0x38,
+ 0xb7, 0xdf, 0xb9, 0x1c, 0xf6, 0x35, 0xfe, 0x6f, 0xf3, 0x29,
+ 0xc0, 0xc5, 0x0a, 0x2c, 0x04, 0xd7, 0x69, 0xff, 0x02, 0x45,
+ 0x1c, 0x29, 0x7a, 0x27, 0xf8, 0xb2, 0xe3, 0x58, 0x09, 0x34,
+ 0xc4, 0xd7, 0x77, 0x74, 0xbd, 0xe4, 0x7c, 0xda, 0x99, 0x09,
+ 0x83, 0x03, 0x6c, 0x36, 0x0d, 0xb2, 0x91, 0x71, 0x40, 0xc7,
+ 0x97, 0x85, 0xfb, 0x2a, 0xa3, 0x92, 0x65, 0x0b, 0x02, 0x58,
+ 0x14, 0x89, 0x8f, 0x3b ) );
+
+OCSP ( unauthorized_ocsp, &server_crt, &thawte_crt,
+ DATA ( 0x30, 0x42, 0x30, 0x40, 0x30, 0x3e, 0x30, 0x3c, 0x30, 0x3a,
+ 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+ 0x00, 0x04, 0x14, 0x68, 0x7a, 0xcf, 0x39, 0x5d, 0xdf, 0x7c,
+ 0x2c, 0x91, 0x6d, 0xdb, 0xcb, 0x9d, 0x0c, 0x27, 0x5b, 0x30,
+ 0x64, 0x28, 0xf2, 0x04, 0x14, 0x3b, 0x34, 0x9a, 0x70, 0x91,
+ 0x73, 0xb2, 0x8a, 0x1b, 0x0c, 0xf4, 0xe9, 0x37, 0xcd, 0xb3,
+ 0x70, 0x32, 0x9e, 0x18, 0x54, 0x02, 0x01, 0x03 ),
+ DATA ( 0x30, 0x03, 0x0a, 0x01, 0x06 ) );
+
+OCSP ( unknown_ocsp, &thawte_crt, &startssl_crt,
+ DATA ( 0x30, 0x45, 0x30, 0x43, 0x30, 0x41, 0x30, 0x3f, 0x30, 0x3d,
+ 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+ 0x00, 0x04, 0x14, 0x48, 0xb7, 0x64, 0x49, 0xf3, 0xd5, 0xfe,
+ 0xfa, 0x11, 0x33, 0xaa, 0x80, 0x5e, 0x42, 0x0f, 0x0f, 0xca,
+ 0x64, 0x36, 0x51, 0x04, 0x14, 0x11, 0xdb, 0x23, 0x45, 0xfd,
+ 0x54, 0xcc, 0x6a, 0x71, 0x6f, 0x84, 0x8a, 0x03, 0xd7, 0xbe,
+ 0xf7, 0x01, 0x2f, 0x26, 0x86, 0x02, 0x04, 0x30, 0x00, 0x00,
+ 0x02 ),
+ DATA ( 0x30, 0x82, 0x06, 0x46, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x06,
+ 0x3f, 0x30, 0x82, 0x06, 0x3b, 0x06, 0x09, 0x2b, 0x06, 0x01,
+ 0x05, 0x05, 0x07, 0x30, 0x01, 0x01, 0x04, 0x82, 0x06, 0x2c,
+ 0x30, 0x82, 0x06, 0x28, 0x30, 0x81, 0xec, 0xa1, 0x70, 0x30,
+ 0x6e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x49, 0x4c, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x13, 0x28, 0x53, 0x74, 0x61, 0x72, 0x74,
+ 0x43, 0x6f, 0x6d, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x20, 0x28,
+ 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x43, 0x6f, 0x6d, 0x6d,
+ 0x65, 0x72, 0x63, 0x69, 0x61, 0x6c, 0x20, 0x4c, 0x69, 0x6d,
+ 0x69, 0x74, 0x65, 0x64, 0x29, 0x31, 0x2c, 0x30, 0x2a, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x23, 0x53, 0x74, 0x61, 0x72,
+ 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ 0x20, 0x32, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
+ 0x4f, 0x43, 0x53, 0x50, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65,
+ 0x72, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x35, 0x31,
+ 0x35, 0x31, 0x31, 0x35, 0x34, 0x30, 0x38, 0x5a, 0x30, 0x67,
+ 0x30, 0x65, 0x30, 0x3d, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
+ 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x48, 0xb7, 0x64,
+ 0x49, 0xf3, 0xd5, 0xfe, 0xfa, 0x11, 0x33, 0xaa, 0x80, 0x5e,
+ 0x42, 0x0f, 0x0f, 0xca, 0x64, 0x36, 0x51, 0x04, 0x14, 0x11,
+ 0xdb, 0x23, 0x45, 0xfd, 0x54, 0xcc, 0x6a, 0x71, 0x6f, 0x84,
+ 0x8a, 0x03, 0xd7, 0xbe, 0xf7, 0x01, 0x2f, 0x26, 0x86, 0x02,
+ 0x04, 0x30, 0x00, 0x00, 0x02, 0x82, 0x00, 0x18, 0x0f, 0x32,
+ 0x30, 0x31, 0x32, 0x30, 0x35, 0x31, 0x35, 0x31, 0x31, 0x35,
+ 0x34, 0x30, 0x38, 0x5a, 0xa0, 0x11, 0x18, 0x0f, 0x32, 0x30,
+ 0x31, 0x32, 0x30, 0x35, 0x31, 0x36, 0x31, 0x31, 0x35, 0x34,
+ 0x30, 0x38, 0x5a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x01, 0x00, 0xbe, 0x1b, 0xa7, 0xa7, 0xba, 0x17, 0xd9,
+ 0x94, 0x16, 0xdf, 0xd2, 0x86, 0x1e, 0x39, 0x38, 0x2f, 0x0e,
+ 0x0e, 0xb0, 0x19, 0x74, 0x9d, 0x64, 0x61, 0xfb, 0x34, 0x15,
+ 0x64, 0xe6, 0x7a, 0x44, 0xfc, 0x24, 0xaf, 0x63, 0xe3, 0xe5,
+ 0x01, 0x3f, 0xeb, 0x62, 0xc4, 0x2f, 0xd7, 0x56, 0xac, 0x9e,
+ 0x39, 0x8c, 0x54, 0x20, 0x24, 0x9f, 0xe0, 0x9a, 0x2c, 0x9a,
+ 0xfb, 0xbe, 0x13, 0x8d, 0x18, 0xf1, 0x95, 0x37, 0xf7, 0x6a,
+ 0x93, 0x28, 0x2a, 0xf6, 0x10, 0xc0, 0x5e, 0xa0, 0xfc, 0xf7,
+ 0x66, 0x97, 0xe4, 0x76, 0x04, 0x90, 0xd3, 0x45, 0x59, 0x26,
+ 0xfd, 0xe9, 0xb4, 0xe5, 0xd6, 0x30, 0x2f, 0xe0, 0xfb, 0xda,
+ 0xcc, 0x4b, 0xc4, 0x11, 0xbf, 0x20, 0x50, 0x18, 0xd5, 0x18,
+ 0xfc, 0xe7, 0x86, 0xb8, 0x80, 0x2b, 0x2e, 0x35, 0x50, 0xcd,
+ 0x73, 0x0d, 0x70, 0xbe, 0x55, 0xa2, 0xef, 0x2c, 0x62, 0x96,
+ 0xe3, 0x6a, 0xec, 0x69, 0xa6, 0x8f, 0x9d, 0x37, 0xb6, 0xbe,
+ 0x6b, 0x72, 0x02, 0x99, 0x02, 0xea, 0x0b, 0x18, 0x01, 0x26,
+ 0x82, 0x3b, 0x7b, 0x44, 0x8a, 0x84, 0xe4, 0x78, 0x6c, 0xb3,
+ 0x5b, 0x83, 0x87, 0x7c, 0xab, 0x80, 0x17, 0xfd, 0x00, 0xfd,
+ 0x56, 0x87, 0x85, 0x2b, 0x49, 0x42, 0xa2, 0x63, 0x84, 0x4f,
+ 0x4a, 0xaa, 0x5e, 0x7d, 0x64, 0x29, 0x09, 0x81, 0xac, 0xea,
+ 0x53, 0x00, 0x36, 0xbf, 0x19, 0x33, 0x5c, 0x0e, 0xee, 0xa9,
+ 0x6a, 0x9e, 0x2e, 0x44, 0x9b, 0x3e, 0xc9, 0x27, 0xb7, 0x49,
+ 0x15, 0x76, 0xa8, 0x42, 0x79, 0x2d, 0x4a, 0x42, 0x1f, 0xf1,
+ 0x32, 0x35, 0x31, 0x4c, 0xcb, 0xa2, 0xee, 0x50, 0xae, 0x1f,
+ 0x5e, 0x4d, 0x5d, 0xc1, 0x9e, 0x28, 0x17, 0x59, 0x6d, 0x1d,
+ 0x2a, 0x0a, 0x3d, 0xeb, 0x88, 0x10, 0xb5, 0xe6, 0x3b, 0xa7,
+ 0x81, 0x1f, 0xc7, 0xa0, 0xc8, 0x4a, 0xfe, 0x6c, 0x8f, 0xa0,
+ 0x82, 0x04, 0x21, 0x30, 0x82, 0x04, 0x1d, 0x30, 0x82, 0x04,
+ 0x19, 0x30, 0x82, 0x03, 0x01, 0xa0, 0x03, 0x02, 0x01, 0x02,
+ 0x02, 0x03, 0x00, 0xca, 0x67, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x30, 0x81, 0x8c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x31, 0x16, 0x30, 0x14,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x53, 0x74, 0x61,
+ 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x4c, 0x74, 0x64, 0x2e,
+ 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13,
+ 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x69,
+ 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x43, 0x65, 0x72, 0x74,
+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x69,
+ 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x38, 0x30, 0x36, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x2f, 0x53, 0x74, 0x61, 0x72,
+ 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ 0x20, 0x32, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79,
+ 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69,
+ 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30,
+ 0x34, 0x32, 0x32, 0x30, 0x35, 0x33, 0x30, 0x35, 0x39, 0x5a,
+ 0x17, 0x0d, 0x31, 0x32, 0x30, 0x36, 0x30, 0x32, 0x30, 0x36,
+ 0x32, 0x39, 0x32, 0x37, 0x5a, 0x30, 0x6e, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c,
+ 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x28, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20,
+ 0x4c, 0x74, 0x64, 0x2e, 0x20, 0x28, 0x53, 0x74, 0x61, 0x72,
+ 0x74, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x69,
+ 0x61, 0x6c, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64,
+ 0x29, 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x13, 0x23, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6d,
+ 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x53,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4f, 0x43, 0x53, 0x50,
+ 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x30, 0x82, 0x01,
+ 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f,
+ 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0xd0, 0xd5, 0xf5, 0x70, 0x9a, 0x2b, 0x41, 0x35, 0xf7, 0xf8,
+ 0xcf, 0xb5, 0x6b, 0xb3, 0xdf, 0xe0, 0xb9, 0x12, 0x0d, 0x3d,
+ 0xd3, 0x99, 0x9f, 0x32, 0x73, 0x01, 0x1f, 0xbc, 0x7d, 0x4f,
+ 0x3e, 0x66, 0xf7, 0xfd, 0x60, 0x57, 0x92, 0x30, 0xb4, 0xdb,
+ 0x9a, 0xf5, 0xd3, 0x49, 0x19, 0xd6, 0xad, 0x37, 0x43, 0x78,
+ 0x69, 0x8c, 0x0d, 0x23, 0x0e, 0x7a, 0xd1, 0x65, 0x08, 0xeb,
+ 0x71, 0x8c, 0x37, 0x36, 0xd3, 0x4d, 0xa6, 0xcb, 0x11, 0xb2,
+ 0xfa, 0xb4, 0x38, 0x3e, 0x2b, 0x70, 0x8c, 0xf7, 0xf1, 0xd9,
+ 0x64, 0x62, 0x26, 0xf4, 0xa7, 0x2c, 0x24, 0x25, 0x4e, 0x4d,
+ 0x3e, 0x7a, 0x54, 0x57, 0x0f, 0xc1, 0x89, 0x9e, 0xb6, 0x55,
+ 0x0b, 0x7c, 0xbe, 0x38, 0xda, 0x8b, 0x62, 0xe9, 0xf1, 0xfa,
+ 0x8c, 0xd9, 0x32, 0x1f, 0xbe, 0x6d, 0x2e, 0x3d, 0x48, 0xa7,
+ 0x4f, 0x48, 0xd4, 0xff, 0x6b, 0xf6, 0x17, 0xf8, 0x31, 0xb2,
+ 0x37, 0xeb, 0x89, 0x71, 0x19, 0x0f, 0xe7, 0x86, 0x06, 0x66,
+ 0xfb, 0xc5, 0xad, 0x7b, 0x75, 0x0b, 0xcc, 0x2e, 0x3c, 0x4d,
+ 0x1c, 0x99, 0x40, 0x32, 0x72, 0xd4, 0x5c, 0xc9, 0x06, 0xaa,
+ 0x98, 0xe9, 0x01, 0x92, 0xdb, 0x25, 0x48, 0x1a, 0xae, 0x3f,
+ 0x01, 0x4d, 0x8a, 0xb0, 0x78, 0xb1, 0x28, 0xe0, 0x09, 0x9b,
+ 0x23, 0xe2, 0x28, 0x46, 0x6f, 0x50, 0x52, 0x71, 0x1c, 0xf1,
+ 0x09, 0xa0, 0x87, 0x3b, 0xdb, 0x84, 0xa3, 0xb1, 0x57, 0x6f,
+ 0xbf, 0x52, 0xd2, 0x30, 0x83, 0x30, 0x26, 0xc0, 0x27, 0x8e,
+ 0x6d, 0x03, 0x43, 0x14, 0x42, 0x31, 0x29, 0xf2, 0x7e, 0x52,
+ 0xcb, 0x84, 0x20, 0x2e, 0x87, 0x19, 0xe5, 0x48, 0xad, 0x06,
+ 0xce, 0x2e, 0x0f, 0xed, 0x78, 0x2a, 0x3d, 0x79, 0xc4, 0xb0,
+ 0xdb, 0xfa, 0x4e, 0x95, 0x88, 0x46, 0x75, 0x12, 0xb0, 0x7a,
+ 0x55, 0x6a, 0x38, 0xae, 0xea, 0x59, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0xa3, 0x81, 0xa0, 0x30, 0x81, 0x9d, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b,
+ 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x03,
+ 0xa8, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x17,
+ 0x30, 0x15, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x03, 0x09, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x30, 0x01, 0x05, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xbd, 0x4c, 0xef, 0x0e, 0xf7, 0x08,
+ 0xac, 0xc9, 0xbd, 0x39, 0x0f, 0xd9, 0xa0, 0xd3, 0xce, 0xcf,
+ 0x26, 0x48, 0xb8, 0x19, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x11, 0xdb, 0x23,
+ 0x45, 0xfd, 0x54, 0xcc, 0x6a, 0x71, 0x6f, 0x84, 0x8a, 0x03,
+ 0xd7, 0xbe, 0xf7, 0x01, 0x2f, 0x26, 0x86, 0x30, 0x23, 0x06,
+ 0x03, 0x55, 0x1d, 0x12, 0x04, 0x1c, 0x30, 0x1a, 0x86, 0x18,
+ 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
+ 0x2e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x73, 0x6c, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03,
+ 0x82, 0x01, 0x01, 0x00, 0x56, 0x1f, 0xef, 0xa5, 0x1a, 0x07,
+ 0xbe, 0xb1, 0xd1, 0xd0, 0x17, 0xeb, 0x72, 0x5b, 0x17, 0x11,
+ 0xe5, 0x96, 0xc3, 0x96, 0xe7, 0x9a, 0xdb, 0xbf, 0x64, 0x1c,
+ 0x99, 0x11, 0x2f, 0x18, 0x07, 0xb2, 0x45, 0x48, 0xf3, 0x58,
+ 0xcd, 0x38, 0x69, 0x33, 0xf4, 0x58, 0x5b, 0x16, 0xed, 0xfb,
+ 0xce, 0xb3, 0xc3, 0x14, 0x27, 0xa6, 0x16, 0xff, 0xd0, 0x70,
+ 0x9e, 0xe1, 0x9d, 0x4b, 0xd1, 0x26, 0x6c, 0x61, 0x25, 0xf1,
+ 0x39, 0x9c, 0xbe, 0x69, 0x75, 0x58, 0xcd, 0xbd, 0x8e, 0x36,
+ 0xfd, 0x46, 0xd1, 0xe3, 0xb9, 0x1a, 0x8a, 0xc1, 0xd7, 0x3e,
+ 0x6e, 0x82, 0xb8, 0xb0, 0x3f, 0xcf, 0x14, 0x3f, 0xc6, 0xf6,
+ 0x3a, 0x86, 0xce, 0x03, 0x76, 0x1f, 0xdb, 0x0b, 0x12, 0xac,
+ 0x99, 0x79, 0x53, 0xf0, 0x3d, 0x70, 0xd3, 0x5a, 0x05, 0xf6,
+ 0xba, 0x6e, 0x35, 0x31, 0x1e, 0x08, 0x30, 0xc1, 0xa4, 0xd4,
+ 0x45, 0x43, 0x5a, 0x01, 0xd9, 0x3d, 0xa5, 0xdb, 0xd2, 0xd7,
+ 0x73, 0x97, 0xe9, 0xab, 0xe4, 0x60, 0xf1, 0xfc, 0xf0, 0x9b,
+ 0xe2, 0x5a, 0x1e, 0x31, 0xe0, 0x1b, 0x47, 0x3f, 0x5a, 0x78,
+ 0xf3, 0x6e, 0xf0, 0x94, 0x6c, 0x2c, 0xfb, 0x67, 0x6e, 0xcb,
+ 0x8c, 0xb6, 0x8d, 0xcc, 0xcf, 0x1e, 0x9f, 0xd2, 0x10, 0x52,
+ 0xc2, 0xe7, 0xc8, 0x05, 0x2c, 0xa0, 0x18, 0xf5, 0x53, 0x4a,
+ 0xd2, 0xb0, 0x57, 0x5e, 0x5f, 0x63, 0xd7, 0x7b, 0x8e, 0xfa,
+ 0x22, 0xa0, 0x69, 0x17, 0xd2, 0xa0, 0xc7, 0x70, 0x01, 0x79,
+ 0x8b, 0x69, 0x1f, 0x0f, 0xdb, 0xe5, 0xf9, 0x83, 0x2b, 0x26,
+ 0x05, 0x05, 0x87, 0x80, 0x0d, 0xf9, 0x20, 0x0e, 0x16, 0x39,
+ 0xc5, 0x9b, 0x14, 0x2e, 0xf2, 0x06, 0x57, 0x46, 0x3d, 0x0b,
+ 0x8c, 0x3e, 0xb4, 0x66, 0x76, 0x67, 0x34, 0x70, 0x00, 0x63,
+ 0xcf, 0x9e, 0xc8, 0xc5, 0x5f, 0x48, 0x06, 0x53, 0x26, 0x55 ) );
+
+/** Time at which OCSP responses are valid */
+static time_t test_time = 1337062083ULL; /* Tue 15 May 2012 06:08:03 */
+
+/** Time at which OCSP responses are not valid */
+static time_t test_stale = 1375573111ULL; /* Sat Aug 3 23:38:31 2013 */
+
+/**
+ * Report certificate parsing test result
+ *
+ * @v crt Test certificate
+ */
+#define ocsp_certificate_ok( crt ) do { \
+ ok ( x509_certificate ( (crt)->data, (crt)->len, \
+ &(crt)->cert ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report OCSP check creation test result
+ *
+ * @v test OCSP test
+ */
+#define ocsp_check_ok( test ) do { \
+ ocsp_prepare_test ( (test) ); \
+ ok ( ocsp_check ( (test)->cert->cert, (test)->issuer->cert, \
+ &(test)->ocsp ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report OCSP request construction test result
+ *
+ * @v test OCSP test
+ */
+#define ocsp_request_ok( test ) do { \
+ DBGC ( (test), "OCSPTEST %p expected request:\n", (test) ); \
+ DBGC_HDA ( (test), 0, (test)->request, (test)->request_len ); \
+ ok ( (test)->ocsp->request.builder.len == (test)->request_len );\
+ ok ( memcmp ( (test)->ocsp->request.builder.data, \
+ (test)->request, (test)->request_len ) == 0 ); \
+ DBGC ( (test), "OCSPTEST %p generated request:\n", (test) ); \
+ DBGC_HDA ( (test), 0, (test)->ocsp->request.builder.data, \
+ (test)->ocsp->request.builder.len ); \
+ } while ( 0 )
+
+/**
+ * Report OCSP response test result
+ *
+ * @v test OCSP test
+ */
+#define ocsp_response_ok( test ) do { \
+ ok ( ocsp_response ( (test)->ocsp, (test)->response, \
+ (test)->response_len ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report OCSP response failure test result
+ *
+ * @v test OCSP test
+ */
+#define ocsp_response_fail_ok( test ) do { \
+ ok ( ocsp_response ( (test)->ocsp, (test)->response, \
+ (test)->response_len ) != 0 ); \
+ } while ( 0 )
+
+/**
+ * Report OCSP validation test result
+ *
+ * @v test OCSP test
+ * @v time Test time
+ */
+#define ocsp_validate_ok( test, time ) do { \
+ ocsp_prepare_test ( (test) ); \
+ ok ( ocsp_validate ( (test)->ocsp, time ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report OCSP validation failure test result
+ *
+ * @v test OCSP test
+ * @v time Test time
+ */
+#define ocsp_validate_fail_ok( test, time ) do { \
+ ocsp_prepare_test ( (test) ); \
+ ok ( ocsp_validate ( (test)->ocsp, time ) != 0 ); \
+ } while ( 0 )
+
+/**
+ * Perform OCSP self-tests
+ *
+ */
+static void ocsp_test_exec ( void ) {
+
+ /* Parse certificates */
+ ocsp_certificate_ok ( &barclays_crt );
+ ocsp_certificate_ok ( &google_crt );
+ ocsp_certificate_ok ( &server_crt );
+ ocsp_certificate_ok ( &verisign_crt );
+ ocsp_certificate_ok ( &thawte_crt );
+ ocsp_certificate_ok ( &startssl_crt );
+
+ /* Parse OCSP checks */
+ ocsp_check_ok ( &barclays_ocsp );
+ ocsp_check_ok ( &google_ocsp );
+ ocsp_check_ok ( &unauthorized_ocsp );
+ ocsp_check_ok ( &unknown_ocsp );
+
+ /* "barclays" test */
+ ocsp_request_ok ( &barclays_ocsp );
+ ocsp_response_ok ( &barclays_ocsp );
+ ocsp_validate_ok ( &barclays_ocsp, test_time );
+ ocsp_validate_fail_ok ( &barclays_ocsp, test_stale );
+
+ /* "google" test */
+ ocsp_request_ok ( &google_ocsp );
+ ocsp_response_ok ( &google_ocsp );
+ ocsp_validate_ok ( &google_ocsp, test_time );
+ ocsp_validate_fail_ok ( &google_ocsp, test_stale );
+
+ /* "unauthorized" test */
+ ocsp_request_ok ( &unauthorized_ocsp );
+ ocsp_response_fail_ok ( &unauthorized_ocsp );
+
+ /* "unknown" test */
+ ocsp_request_ok ( &unknown_ocsp );
+ ocsp_response_fail_ok ( &unknown_ocsp );
+
+ /* Drop OCSP check references */
+ ocsp_put ( unknown_ocsp.ocsp );
+ ocsp_put ( unauthorized_ocsp.ocsp );
+ ocsp_put ( google_ocsp.ocsp );
+ ocsp_put ( barclays_ocsp.ocsp );
+
+ /* Drop certificate references */
+ x509_put ( startssl_crt.cert );
+ x509_put ( thawte_crt.cert );
+ x509_put ( verisign_crt.cert );
+ x509_put ( server_crt.cert );
+ x509_put ( google_crt.cert );
+ x509_put ( barclays_crt.cert );
+}
+
+/** OCSP self-test */
+struct self_test ocsp_test __self_test = {
+ .name = "ocsp",
+ .exec = ocsp_test_exec,
+};
+
+/* Drag in algorithms required for tests */
+REQUIRE_OBJECT ( rsa );
+REQUIRE_OBJECT ( sha1 );
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/pubkey_test.h b/src/VBox/Devices/PC/ipxe/src/tests/pubkey_test.h
new file mode 100644
index 00000000..7678453a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/pubkey_test.h
@@ -0,0 +1,175 @@
+#ifndef _PUBKEY_TEST_H
+#define _PUBKEY_TEST_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/crypto.h>
+#include <ipxe/test.h>
+
+/**
+ * Report public key decryption test result
+ *
+ * @v pubkey Public key algorithm
+ * @v key Key
+ * @v key_len Key length
+ * @v ciphertext Ciphertext
+ * @v ciphertext_len Ciphertext length
+ * @v expected Expected plaintext
+ * @v expected_len Expected plaintext length
+ */
+#define pubkey_decrypt_ok( pubkey, key, key_len, ciphertext, \
+ ciphertext_len, expected, expected_len ) do {\
+ uint8_t ctx[ (pubkey)->ctxsize ]; \
+ \
+ ok ( pubkey_init ( (pubkey), ctx, (key), (key_len) ) == 0 ); \
+ { \
+ size_t max_len = pubkey_max_len ( (pubkey), ctx ); \
+ uint8_t decrypted[ max_len ]; \
+ int decrypted_len; \
+ \
+ decrypted_len = pubkey_decrypt ( (pubkey), ctx, \
+ (ciphertext), \
+ (ciphertext_len), \
+ decrypted ); \
+ ok ( decrypted_len == ( ( int ) (expected_len) ) ); \
+ ok ( memcmp ( decrypted, (expected), \
+ (expected_len) ) == 0 ); \
+ } \
+ pubkey_final ( (pubkey), ctx ); \
+ } while ( 0 )
+
+/**
+ * Report public key encryption and decryption test result
+ *
+ * @v pubkey Public key algorithm
+ * @v encrypt_key Encryption key
+ * @v encrypt_key_len Encryption key length
+ * @v decrypt_key Decryption key
+ * @v decrypt_key_len Decryption key length
+ * @v plaintext Plaintext
+ * @v plaintext_len Plaintext length
+ */
+#define pubkey_encrypt_ok( pubkey, encrypt_key, encrypt_key_len, \
+ decrypt_key, decrypt_key_len, plaintext, \
+ plaintext_len ) do { \
+ uint8_t ctx[ (pubkey)->ctxsize ]; \
+ \
+ ok ( pubkey_init ( (pubkey), ctx, (encrypt_key), \
+ (encrypt_key_len) ) == 0 ); \
+ { \
+ size_t max_len = pubkey_max_len ( (pubkey), ctx ); \
+ uint8_t encrypted[ max_len ]; \
+ int encrypted_len; \
+ \
+ encrypted_len = pubkey_encrypt ( (pubkey), ctx, \
+ (plaintext), \
+ (plaintext_len), \
+ encrypted ); \
+ ok ( encrypted_len >= 0 ); \
+ pubkey_decrypt_ok ( (pubkey), (decrypt_key), \
+ (decrypt_key_len), encrypted, \
+ encrypted_len, (plaintext), \
+ (plaintext_len) ); \
+ } \
+ pubkey_final ( (pubkey), ctx ); \
+ } while ( 0 )
+
+/**
+ * Report public key signature test result
+ *
+ * @v pubkey Public key algorithm
+ * @v key Key
+ * @v key_len Key length
+ * @v digest Digest algorithm
+ * @v plaintext Plaintext
+ * @v plaintext_len Plaintext length
+ * @v expected Expected signature
+ * @v expected_len Expected signature length
+ */
+#define pubkey_sign_ok( pubkey, key, key_len, digest, plaintext, \
+ plaintext_len, expected, expected_len ) do { \
+ uint8_t ctx[ (pubkey)->ctxsize ]; \
+ uint8_t digestctx[ (digest)->ctxsize ]; \
+ uint8_t digestout[ (digest)->digestsize ]; \
+ \
+ digest_init ( (digest), digestctx ); \
+ digest_update ( (digest), digestctx, (plaintext), \
+ (plaintext_len) ); \
+ digest_final ( (digest), digestctx, digestout ); \
+ \
+ ok ( pubkey_init ( (pubkey), ctx, (key), (key_len) ) == 0 ); \
+ { \
+ size_t max_len = pubkey_max_len ( (pubkey), ctx ); \
+ uint8_t signature[ max_len ]; \
+ int signature_len; \
+ \
+ signature_len = pubkey_sign ( (pubkey), ctx, (digest), \
+ digestout, signature ); \
+ ok ( signature_len == ( ( int ) (expected_len) ) ); \
+ ok ( memcmp ( signature, (expected), \
+ (expected_len) ) == 0 ); \
+ } \
+ pubkey_final ( (pubkey), ctx ); \
+ } while ( 0 )
+
+/**
+ * Report public key verification test result
+ *
+ * @v pubkey Public key algorithm
+ * @v key Key
+ * @v key_len Key length
+ * @v digest Digest algorithm
+ * @v plaintext Plaintext
+ * @v plaintext_len Plaintext length
+ * @v signature Signature
+ * @v signature_len Signature length
+ */
+#define pubkey_verify_ok( pubkey, key, key_len, digest, plaintext, \
+ plaintext_len, signature, signature_len ) do {\
+ uint8_t ctx[ (pubkey)->ctxsize ]; \
+ uint8_t digestctx[ (digest)->ctxsize ]; \
+ uint8_t digestout[ (digest)->digestsize ]; \
+ \
+ digest_init ( (digest), digestctx ); \
+ digest_update ( (digest), digestctx, (plaintext), \
+ (plaintext_len) ); \
+ digest_final ( (digest), digestctx, digestout ); \
+ \
+ ok ( pubkey_init ( (pubkey), ctx, (key), (key_len) ) == 0 ); \
+ ok ( pubkey_verify ( (pubkey), ctx, (digest), digestout, \
+ (signature), (signature_len) ) == 0 ); \
+ pubkey_final ( (pubkey), ctx ); \
+ } while ( 0 )
+
+/**
+ * Report public key verification test result
+ *
+ * @v pubkey Public key algorithm
+ * @v key Key
+ * @v key_len Key length
+ * @v digest Digest algorithm
+ * @v plaintext Plaintext
+ * @v plaintext_len Plaintext length
+ * @v signature Signature
+ * @v signature_len Signature length
+ */
+#define pubkey_verify_fail_ok( pubkey, key, key_len, digest, plaintext, \
+ plaintext_len, signature, \
+ signature_len ) do { \
+ uint8_t ctx[ (pubkey)->ctxsize ]; \
+ uint8_t digestctx[ (digest)->ctxsize ]; \
+ uint8_t digestout[ (digest)->digestsize ]; \
+ \
+ digest_init ( (digest), digestctx ); \
+ digest_update ( (digest), digestctx, (plaintext), \
+ (plaintext_len) ); \
+ digest_final ( (digest), digestctx, digestout ); \
+ \
+ ok ( pubkey_init ( (pubkey), ctx, (key), (key_len) ) == 0 ); \
+ ok ( pubkey_verify ( (pubkey), ctx, (digest), digestout, \
+ (signature), (signature_len) ) != 0 ); \
+ pubkey_final ( (pubkey), ctx ); \
+ } while ( 0 )
+
+#endif /* _PUBKEY_TEST_H */
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/rsa_test.c b/src/VBox/Devices/PC/ipxe/src/tests/rsa_test.c
new file mode 100644
index 00000000..a451e38c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/rsa_test.c
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * RSA self-tests
+ *
+ * These test vectors are generated using openssl's genrsa, rsa,
+ * rsautl, and dgst tools.
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <ipxe/crypto.h>
+#include <ipxe/rsa.h>
+#include <ipxe/md5.h>
+#include <ipxe/sha1.h>
+#include <ipxe/sha256.h>
+#include <ipxe/test.h>
+#include "pubkey_test.h"
+
+/** Define inline private key data */
+#define PRIVATE(...) { __VA_ARGS__ }
+
+/** Define inline public key data */
+#define PUBLIC(...) { __VA_ARGS__ }
+
+/** Define inline plaintext data */
+#define PLAINTEXT(...) { __VA_ARGS__ }
+
+/** Define inline ciphertext data */
+#define CIPHERTEXT(...) { __VA_ARGS__ }
+
+/** Define inline signature data */
+#define SIGNATURE(...) { __VA_ARGS__ }
+
+/** An RSA encryption and decryption self-test */
+struct rsa_encrypt_decrypt_test {
+ /** Private key */
+ const void *private;
+ /** Private key length */
+ size_t private_len;
+ /** Public key */
+ const void *public;
+ /** Public key length */
+ size_t public_len;
+ /** Plaintext */
+ const void *plaintext;
+ /** Plaintext length */
+ size_t plaintext_len;
+ /** Ciphertext
+ *
+ * Note that the encryption process includes some random
+ * padding, so a given plaintext will encrypt to multiple
+ * different ciphertexts.
+ */
+ const void *ciphertext;
+ /** Ciphertext length */
+ size_t ciphertext_len;
+};
+
+/**
+ * Define an RSA encryption and decryption test
+ *
+ * @v name Test name
+ * @v PRIVATE Private key
+ * @v PUBLIC Public key
+ * @v PLAINTEXT Plaintext
+ * @v CIPHERTEXT Ciphertext
+ * @ret test Encryption and decryption test
+ */
+#define RSA_ENCRYPT_DECRYPT_TEST( name, PRIVATE, PUBLIC, PLAINTEXT, \
+ CIPHERTEXT ) \
+ static const uint8_t name ## _private[] = PRIVATE; \
+ static const uint8_t name ## _public[] = PUBLIC; \
+ static const uint8_t name ## _plaintext[] = PLAINTEXT; \
+ static const uint8_t name ## _ciphertext[] = CIPHERTEXT; \
+ static struct rsa_encrypt_decrypt_test name = { \
+ .private = name ## _private, \
+ .private_len = sizeof ( name ## _private ), \
+ .public = name ## _public, \
+ .public_len = sizeof ( name ## _public ), \
+ .plaintext = name ## _plaintext, \
+ .plaintext_len = sizeof ( name ## _plaintext ), \
+ .ciphertext = name ## _ciphertext, \
+ .ciphertext_len = sizeof ( name ## _ciphertext ), \
+ }
+
+/** An RSA signature self-test */
+struct rsa_signature_test {
+ /** Private key */
+ const void *private;
+ /** Private key length */
+ size_t private_len;
+ /** Public key */
+ const void *public;
+ /** Public key length */
+ size_t public_len;
+ /** Plaintext */
+ const void *plaintext;
+ /** Plaintext length */
+ size_t plaintext_len;
+ /** Digest algorithm */
+ struct digest_algorithm *digest;
+ /** Signature */
+ const void *signature;
+ /** Signature length */
+ size_t signature_len;
+};
+
+/**
+ * Define an RSA signature test
+ *
+ * @v name Test name
+ * @v PRIVATE Private key
+ * @v PUBLIC Public key
+ * @v PLAINTEXT Plaintext
+ * @v DIGEST Digest algorithm
+ * @v SIGNATURE Signature
+ * @ret test Signature test
+ */
+#define RSA_SIGNATURE_TEST( name, PRIVATE, PUBLIC, PLAINTEXT, DIGEST, \
+ SIGNATURE ) \
+ static const uint8_t name ## _private[] = PRIVATE; \
+ static const uint8_t name ## _public[] = PUBLIC; \
+ static const uint8_t name ## _plaintext[] = PLAINTEXT; \
+ static const uint8_t name ## _signature[] = SIGNATURE; \
+ static struct rsa_signature_test name = { \
+ .private = name ## _private, \
+ .private_len = sizeof ( name ## _private ), \
+ .public = name ## _public, \
+ .public_len = sizeof ( name ## _public ), \
+ .plaintext = name ## _plaintext, \
+ .plaintext_len = sizeof ( name ## _plaintext ), \
+ .digest = DIGEST, \
+ .signature = name ## _signature, \
+ .signature_len = sizeof ( name ## _signature ), \
+ }
+
+/**
+ * Report RSA encryption and decryption test result
+ *
+ * @v test RSA encryption and decryption test
+ */
+#define rsa_encrypt_decrypt_ok( test ) do { \
+ pubkey_decrypt_ok ( &rsa_algorithm, (test)->private, \
+ (test)->private_len, (test)->ciphertext, \
+ (test)->ciphertext_len, (test)->plaintext, \
+ (test)->plaintext_len ); \
+ pubkey_encrypt_ok ( &rsa_algorithm, (test)->private, \
+ (test)->private_len, (test)->public, \
+ (test)->public_len, (test)->plaintext, \
+ (test)->plaintext_len ); \
+ pubkey_encrypt_ok ( &rsa_algorithm, (test)->public, \
+ (test)->public_len, (test)->private, \
+ (test)->private_len, (test)->plaintext, \
+ (test)->plaintext_len ); \
+ } while ( 0 )
+
+
+/**
+ * Report RSA signature test result
+ *
+ * @v test RSA signature test
+ */
+#define rsa_signature_ok( test ) do { \
+ uint8_t bad_signature[ (test)->signature_len ]; \
+ pubkey_sign_ok ( &rsa_algorithm, (test)->private, \
+ (test)->private_len, (test)->digest, \
+ (test)->plaintext, (test)->plaintext_len, \
+ (test)->signature, (test)->signature_len ); \
+ pubkey_verify_ok ( &rsa_algorithm, (test)->public, \
+ (test)->public_len, (test)->digest, \
+ (test)->plaintext, (test)->plaintext_len, \
+ (test)->signature, (test)->signature_len ); \
+ memset ( bad_signature, 0, sizeof ( bad_signature ) ); \
+ pubkey_verify_fail_ok ( &rsa_algorithm, (test)->public, \
+ (test)->public_len, (test)->digest, \
+ (test)->plaintext, \
+ (test)->plaintext_len, bad_signature, \
+ sizeof ( bad_signature ) ); \
+ } while ( 0 )
+
+/** "Hello world" encryption and decryption test */
+RSA_ENCRYPT_DECRYPT_TEST ( hw_test,
+ PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
+ 0xd2, 0xf1, 0x04, 0x67, 0xf6, 0x2c, 0x96, 0x07, 0xa6, 0xbd,
+ 0x85, 0xac, 0xc1, 0x17, 0x5d, 0xe8, 0xf0, 0x93, 0x94, 0x0c,
+ 0x45, 0x67, 0x26, 0x67, 0xde, 0x7e, 0xfb, 0xa8, 0xda, 0xbd,
+ 0x07, 0xdf, 0xcf, 0x45, 0x04, 0x6d, 0xbd, 0x69, 0x8b, 0xfb,
+ 0xc1, 0x72, 0xc0, 0xfc, 0x03, 0x04, 0xf2, 0x82, 0xc4, 0x7b,
+ 0x6a, 0x3e, 0xec, 0x53, 0x7a, 0xe3, 0x4e, 0xa8, 0xc9, 0xf9,
+ 0x1f, 0x2a, 0x13, 0x0d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
+ 0x40, 0x49, 0xb8, 0x61, 0xc9, 0xd3, 0x87, 0x11, 0x87, 0xeb,
+ 0x06, 0x21, 0x49, 0x96, 0xd2, 0x0b, 0xc7, 0xf5, 0x0c, 0x1e,
+ 0x99, 0x8b, 0x47, 0xd9, 0x6c, 0x43, 0x9e, 0x2d, 0x65, 0x7d,
+ 0xcc, 0xc2, 0x8b, 0x1a, 0x6f, 0x2b, 0x55, 0xbe, 0xb3, 0x9f,
+ 0xd1, 0xe2, 0x9a, 0xde, 0x1d, 0xac, 0xec, 0x67, 0xec, 0xa5,
+ 0xbf, 0x9c, 0x30, 0xd6, 0xf9, 0x0a, 0x1a, 0x48, 0xf3, 0xc2,
+ 0x93, 0x3a, 0x17, 0x27, 0x21, 0x02, 0x21, 0x00, 0xfc, 0x8d,
+ 0xfb, 0xee, 0x8a, 0xaa, 0x45, 0x19, 0x4b, 0xf0, 0x68, 0xb0,
+ 0x02, 0x38, 0x3e, 0x03, 0x6b, 0x24, 0x77, 0x20, 0xbd, 0x5e,
+ 0x6c, 0x76, 0xdb, 0xc9, 0xe1, 0x43, 0xa3, 0x40, 0x62, 0x6f,
+ 0x02, 0x21, 0x00, 0xd5, 0xd1, 0xb4, 0x4d, 0x03, 0x40, 0x69,
+ 0x3f, 0x9a, 0xa7, 0x44, 0x15, 0x28, 0x1e, 0xa5, 0x5f, 0xcf,
+ 0x97, 0x21, 0x12, 0xb3, 0xe6, 0x1c, 0x9a, 0x8d, 0xb7, 0xb4,
+ 0x80, 0x3a, 0x9c, 0xb0, 0x43, 0x02, 0x20, 0x71, 0xf0, 0xa0,
+ 0xab, 0x82, 0xf5, 0xc4, 0x8c, 0xe0, 0x1c, 0xcb, 0x2e, 0x35,
+ 0x22, 0x28, 0xa0, 0x24, 0x33, 0x64, 0x67, 0x69, 0xe7, 0xf2,
+ 0xa9, 0x41, 0x09, 0x78, 0x4e, 0xaa, 0x95, 0x3e, 0x93, 0x02,
+ 0x21, 0x00, 0x85, 0xcc, 0x4d, 0xd9, 0x0b, 0x39, 0xd9, 0x22,
+ 0x75, 0xf2, 0x49, 0x46, 0x3b, 0xee, 0xc1, 0x69, 0x6d, 0x0b,
+ 0x93, 0x24, 0x92, 0xf2, 0x61, 0xdf, 0xcc, 0xe2, 0xb1, 0xce,
+ 0xb3, 0xde, 0xac, 0xe5, 0x02, 0x21, 0x00, 0x9c, 0x23, 0x6a,
+ 0x95, 0xa6, 0xfe, 0x1e, 0xd8, 0x0c, 0x3f, 0x6e, 0xe6, 0x0a,
+ 0xeb, 0x97, 0xd6, 0x36, 0x1c, 0x80, 0xc1, 0x02, 0x87, 0x0d,
+ 0x4d, 0xfe, 0x28, 0x02, 0x1e, 0xde, 0xe1, 0xcc, 0x72 ),
+ PUBLIC ( 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00,
+ 0x30, 0x48, 0x02, 0x41, 0x00, 0xd2, 0xf1, 0x04, 0x67, 0xf6,
+ 0x2c, 0x96, 0x07, 0xa6, 0xbd, 0x85, 0xac, 0xc1, 0x17, 0x5d,
+ 0xe8, 0xf0, 0x93, 0x94, 0x0c, 0x45, 0x67, 0x26, 0x67, 0xde,
+ 0x7e, 0xfb, 0xa8, 0xda, 0xbd, 0x07, 0xdf, 0xcf, 0x45, 0x04,
+ 0x6d, 0xbd, 0x69, 0x8b, 0xfb, 0xc1, 0x72, 0xc0, 0xfc, 0x03,
+ 0x04, 0xf2, 0x82, 0xc4, 0x7b, 0x6a, 0x3e, 0xec, 0x53, 0x7a,
+ 0xe3, 0x4e, 0xa8, 0xc9, 0xf9, 0x1f, 0x2a, 0x13, 0x0d, 0x02,
+ 0x03, 0x01, 0x00, 0x01 ),
+ PLAINTEXT ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c,
+ 0x64, 0x0a ),
+ CIPHERTEXT ( 0x39, 0xff, 0x5c, 0x54, 0x65, 0x3e, 0x6a, 0xab, 0xc0, 0x62,
+ 0x91, 0xb2, 0xbf, 0x1d, 0x73, 0x5b, 0xd5, 0x4c, 0xbd, 0x16,
+ 0x0f, 0x24, 0xc9, 0xf5, 0xa7, 0xdd, 0x94, 0xd6, 0xf8, 0xae,
+ 0xd3, 0xa0, 0x9f, 0x4d, 0xff, 0x8d, 0x81, 0x34, 0x47, 0xff,
+ 0x2a, 0x87, 0x96, 0xd3, 0x17, 0x5d, 0x93, 0x4d, 0x7b, 0x27,
+ 0x88, 0x4f, 0xec, 0x43, 0x9c, 0xed, 0xb3, 0xf2, 0x19, 0x89,
+ 0x38, 0x43, 0xf9, 0x41 ) );
+
+/** Random message MD5 signature test */
+RSA_SIGNATURE_TEST ( md5_test,
+ PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
+ 0xf9, 0x3f, 0x78, 0x44, 0xe2, 0x0e, 0x25, 0xf1, 0x0e, 0x94,
+ 0xcd, 0xca, 0x6f, 0x9e, 0xea, 0x6d, 0xdf, 0xcd, 0xa0, 0x7c,
+ 0xe2, 0x21, 0xeb, 0xde, 0xa6, 0x01, 0x4b, 0xb0, 0x76, 0x4b,
+ 0xd8, 0x8b, 0x19, 0x83, 0xb4, 0xbe, 0x45, 0xde, 0x3d, 0x46,
+ 0x61, 0x0f, 0x11, 0xe2, 0x2c, 0xf5, 0xb0, 0x63, 0xa0, 0x84,
+ 0xc0, 0xaf, 0x4e, 0xbe, 0x6a, 0xd3, 0x84, 0x3f, 0xec, 0x42,
+ 0x17, 0xe9, 0x25, 0xe1, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
+ 0x40, 0x62, 0x7d, 0x93, 0x1f, 0xdd, 0x17, 0xec, 0x24, 0x42,
+ 0x37, 0xc8, 0xce, 0x0a, 0xa7, 0x88, 0x49, 0x5c, 0x9b, 0x9b,
+ 0xa4, 0x5d, 0x93, 0x3b, 0xea, 0x62, 0x3c, 0xb6, 0xd5, 0x07,
+ 0x19, 0xd7, 0x79, 0xf0, 0x3b, 0xab, 0xa3, 0xa5, 0x43, 0x35,
+ 0x8d, 0x58, 0x40, 0xa0, 0x95, 0xc5, 0x63, 0x28, 0x28, 0xda,
+ 0x13, 0x28, 0xdf, 0xc9, 0x05, 0xdc, 0x69, 0x46, 0xff, 0x2a,
+ 0xfb, 0xe4, 0xd1, 0x23, 0xa5, 0x02, 0x21, 0x00, 0xfc, 0xef,
+ 0x3b, 0x9d, 0x9d, 0x69, 0xf3, 0x66, 0x0a, 0x2b, 0x52, 0xd6,
+ 0x61, 0x14, 0x90, 0x6e, 0x7d, 0x3c, 0x08, 0x4b, 0x98, 0x44,
+ 0x00, 0xf2, 0xa4, 0x16, 0x2d, 0xd1, 0xf9, 0xa0, 0x1e, 0x37,
+ 0x02, 0x21, 0x00, 0xfc, 0x44, 0xcc, 0x7c, 0xc0, 0x26, 0x9a,
+ 0x0a, 0x6e, 0xda, 0x17, 0x05, 0x7d, 0x66, 0x8d, 0x29, 0x1a,
+ 0x44, 0xbf, 0x33, 0x76, 0xae, 0x8d, 0xe8, 0xb5, 0xed, 0xb8,
+ 0x6f, 0xdc, 0xfe, 0x10, 0xa7, 0x02, 0x20, 0x76, 0x48, 0x8a,
+ 0x60, 0x93, 0x14, 0xd1, 0x36, 0x8e, 0xda, 0xe3, 0xca, 0x4d,
+ 0x6c, 0x08, 0x7f, 0x23, 0x21, 0xc7, 0xdf, 0x52, 0x3d, 0xbb,
+ 0x13, 0xbd, 0x98, 0x81, 0xa5, 0x08, 0x4f, 0xd0, 0xd1, 0x02,
+ 0x21, 0x00, 0xd9, 0xa3, 0x11, 0x37, 0xdf, 0x1e, 0x6e, 0x6e,
+ 0xe9, 0xcb, 0xc5, 0x68, 0xbb, 0x13, 0x2a, 0x5d, 0x77, 0x88,
+ 0x2f, 0xdc, 0x5a, 0x5b, 0xa5, 0x9a, 0x4a, 0xba, 0x58, 0x10,
+ 0x49, 0xfb, 0xf6, 0xa9, 0x02, 0x21, 0x00, 0x89, 0xe8, 0x47,
+ 0x5b, 0x20, 0x04, 0x3b, 0x0f, 0xb9, 0xe0, 0x1d, 0xab, 0xcf,
+ 0xe8, 0x72, 0xfd, 0x7d, 0x17, 0x85, 0xc8, 0xd8, 0xbd, 0x1a,
+ 0x92, 0xe0, 0xbc, 0x7a, 0xc7, 0x31, 0xbe, 0xef, 0xf4 ),
+ PUBLIC ( 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00,
+ 0x30, 0x48, 0x02, 0x41, 0x00, 0xf9, 0x3f, 0x78, 0x44, 0xe2,
+ 0x0e, 0x25, 0xf1, 0x0e, 0x94, 0xcd, 0xca, 0x6f, 0x9e, 0xea,
+ 0x6d, 0xdf, 0xcd, 0xa0, 0x7c, 0xe2, 0x21, 0xeb, 0xde, 0xa6,
+ 0x01, 0x4b, 0xb0, 0x76, 0x4b, 0xd8, 0x8b, 0x19, 0x83, 0xb4,
+ 0xbe, 0x45, 0xde, 0x3d, 0x46, 0x61, 0x0f, 0x11, 0xe2, 0x2c,
+ 0xf5, 0xb0, 0x63, 0xa0, 0x84, 0xc0, 0xaf, 0x4e, 0xbe, 0x6a,
+ 0xd3, 0x84, 0x3f, 0xec, 0x42, 0x17, 0xe9, 0x25, 0xe1, 0x02,
+ 0x03, 0x01, 0x00, 0x01 ),
+ PLAINTEXT ( 0x9d, 0x5b, 0x46, 0x42, 0x27, 0xc0, 0xf1, 0x4b, 0xe5, 0x9e,
+ 0xd3, 0x10, 0xa1, 0xeb, 0x16, 0xc3, 0xc6, 0x8f, 0x1a, 0x18,
+ 0x86, 0xc3, 0x92, 0x15, 0x2d, 0x65, 0xa0, 0x40, 0xe1, 0x3e,
+ 0x29, 0x79, 0x7c, 0xd4, 0x08, 0xef, 0x53, 0xeb, 0x08, 0x07,
+ 0x39, 0x21, 0xb3, 0x40, 0xff, 0x4b, 0xc7, 0x76, 0xb9, 0x12,
+ 0x32, 0x41, 0xcc, 0x5a, 0x86, 0x5c, 0x2e, 0x0b, 0x05, 0xd8,
+ 0x56, 0xd4, 0xdf, 0x6f, 0x2c, 0xf0, 0xbf, 0x4b, 0x6f, 0x68,
+ 0xde, 0x39, 0x4a, 0x3e, 0xae, 0x44, 0xb9, 0xc6, 0x24, 0xb3,
+ 0x83, 0x2e, 0x9f, 0xf5, 0x6d, 0x61, 0xc3, 0x8e, 0xe8, 0x8f,
+ 0xa6, 0x87, 0x58, 0x3f, 0x36, 0x13, 0xf4, 0x7e, 0xf0, 0x20,
+ 0x47, 0x87, 0x3f, 0x21, 0x6e, 0x51, 0x3c, 0xf1, 0xef, 0xca,
+ 0x9f, 0x77, 0x9c, 0x91, 0x4f, 0xd4, 0x56, 0xc0, 0x39, 0x11,
+ 0xab, 0x15, 0x2c, 0x5e, 0xad, 0x40, 0x09, 0xe6, 0xde, 0xe5,
+ 0x77, 0x60, 0x19, 0xd4, 0x0d, 0x77, 0x76, 0x24, 0x8b, 0xe6,
+ 0xdd, 0xa5, 0x8d, 0x4a, 0x55, 0x3a, 0xdf, 0xf8, 0x29, 0xfb,
+ 0x47, 0x8a, 0xfe, 0x98, 0x34, 0xf6, 0x30, 0x7f, 0x09, 0x03,
+ 0x26, 0x05, 0xd5, 0x46, 0x18, 0x96, 0xca, 0x96, 0x5b, 0x66,
+ 0xf2, 0x8d, 0xfc, 0xfc, 0x37, 0xf7, 0xc7, 0x6d, 0x6c, 0xd8,
+ 0x24, 0x0c, 0x6a, 0xec, 0x82, 0x5c, 0x72, 0xf1, 0xfc, 0x05,
+ 0xed, 0x8e, 0xe8, 0xd9, 0x8b, 0x8b, 0x67, 0x02, 0x95 ),
+ &md5_algorithm,
+ SIGNATURE ( 0xdb, 0x56, 0x3d, 0xea, 0xae, 0x81, 0x4b, 0x3b, 0x2e, 0x8e,
+ 0xb8, 0xee, 0x13, 0x61, 0xc6, 0xe7, 0xd7, 0x50, 0xcd, 0x0d,
+ 0x34, 0x3a, 0xfe, 0x9a, 0x8d, 0xf8, 0xfb, 0xd6, 0x7e, 0xbd,
+ 0xdd, 0xb3, 0xf9, 0xfb, 0xe0, 0xf8, 0xe7, 0x71, 0x03, 0xe6,
+ 0x55, 0xd5, 0xf4, 0x02, 0x3c, 0xb5, 0xbc, 0x95, 0x2b, 0x66,
+ 0x56, 0xec, 0x2f, 0x8e, 0xa7, 0xae, 0xd9, 0x80, 0xb3, 0xaa,
+ 0xac, 0x45, 0x00, 0xa8 ) );
+
+/** Random message SHA-1 signature test */
+RSA_SIGNATURE_TEST ( sha1_test,
+ PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
+ 0xe0, 0x3a, 0x8d, 0x35, 0xe1, 0x92, 0x2f, 0xea, 0x0d, 0x82,
+ 0x60, 0x2e, 0xb6, 0x0b, 0x02, 0xd3, 0xf4, 0x39, 0xfb, 0x06,
+ 0x43, 0x8e, 0xa1, 0x7c, 0xc5, 0xae, 0x0d, 0xc7, 0xee, 0x83,
+ 0xb3, 0x63, 0x20, 0x92, 0x34, 0xe2, 0x94, 0x3d, 0xdd, 0xbb,
+ 0x6c, 0x64, 0x69, 0x68, 0x25, 0x24, 0x81, 0x4b, 0x4d, 0x48,
+ 0x5a, 0xd2, 0x29, 0x14, 0xeb, 0x38, 0xdd, 0x3e, 0xb5, 0x57,
+ 0x45, 0x9b, 0xed, 0x33, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
+ 0x40, 0x3d, 0xa9, 0x1c, 0x47, 0xe2, 0xdd, 0xf6, 0x7b, 0x20,
+ 0x77, 0xe7, 0xc7, 0x30, 0x9c, 0x5a, 0x8c, 0xba, 0xae, 0x6f,
+ 0x0f, 0x4b, 0xe8, 0x9f, 0x13, 0xd6, 0xb0, 0x84, 0x6d, 0xa4,
+ 0x73, 0x67, 0x12, 0xa9, 0x7c, 0x75, 0xaf, 0x62, 0x92, 0x7b,
+ 0x80, 0xaf, 0x39, 0x7d, 0x01, 0xb3, 0x43, 0xc8, 0x0d, 0x17,
+ 0x7f, 0x82, 0x59, 0x46, 0xb8, 0xe5, 0x4e, 0xba, 0x5e, 0x71,
+ 0x5c, 0xba, 0x62, 0x06, 0x91, 0x02, 0x21, 0x00, 0xf7, 0xaa,
+ 0xb6, 0x9c, 0xc8, 0xad, 0x68, 0xa8, 0xd7, 0x25, 0xb1, 0xb5,
+ 0x91, 0xd4, 0xc7, 0xd6, 0x69, 0x51, 0x5d, 0x04, 0xed, 0xd8,
+ 0xc6, 0xea, 0x69, 0xd2, 0x24, 0xbe, 0x5e, 0x7c, 0x89, 0xa5,
+ 0x02, 0x21, 0x00, 0xe7, 0xc5, 0xf4, 0x01, 0x35, 0xe0, 0x16,
+ 0xb5, 0x13, 0x86, 0x14, 0x5a, 0x6a, 0x8d, 0x03, 0x90, 0xae,
+ 0x7d, 0x3a, 0xc1, 0xfe, 0x8c, 0xa0, 0x4a, 0xb4, 0x94, 0x50,
+ 0x58, 0xa4, 0xc6, 0x73, 0xf7, 0x02, 0x21, 0x00, 0xe2, 0xda,
+ 0x16, 0x6c, 0x63, 0x90, 0x1a, 0xc6, 0x54, 0x53, 0x2d, 0x84,
+ 0x8f, 0x70, 0x24, 0x1f, 0x6b, 0xd6, 0x5f, 0xea, 0x8c, 0xe5,
+ 0xbb, 0xc5, 0xa9, 0x6a, 0x17, 0xc7, 0xdb, 0x8a, 0x1d, 0x15,
+ 0x02, 0x21, 0x00, 0xe4, 0x2a, 0x7e, 0xe4, 0x76, 0x2a, 0x2d,
+ 0x90, 0x83, 0x30, 0xda, 0x76, 0x8c, 0x30, 0x58, 0x13, 0x25,
+ 0x83, 0x88, 0xc5, 0x93, 0x96, 0xd2, 0xf1, 0xd8, 0x45, 0xad,
+ 0xb7, 0x26, 0x37, 0x6b, 0xcf, 0x02, 0x20, 0x73, 0x58, 0x1f,
+ 0x0a, 0xcd, 0x0c, 0x83, 0x27, 0xcc, 0x15, 0xa2, 0x1e, 0x07,
+ 0x32, 0x1b, 0xa3, 0xc6, 0xa6, 0xb8, 0x83, 0x97, 0x48, 0x45,
+ 0x50, 0x6c, 0x37, 0x45, 0xa5, 0x54, 0x2a, 0x59, 0x3c ),
+ PUBLIC ( 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00,
+ 0x30, 0x48, 0x02, 0x41, 0x00, 0xe0, 0x3a, 0x8d, 0x35, 0xe1,
+ 0x92, 0x2f, 0xea, 0x0d, 0x82, 0x60, 0x2e, 0xb6, 0x0b, 0x02,
+ 0xd3, 0xf4, 0x39, 0xfb, 0x06, 0x43, 0x8e, 0xa1, 0x7c, 0xc5,
+ 0xae, 0x0d, 0xc7, 0xee, 0x83, 0xb3, 0x63, 0x20, 0x92, 0x34,
+ 0xe2, 0x94, 0x3d, 0xdd, 0xbb, 0x6c, 0x64, 0x69, 0x68, 0x25,
+ 0x24, 0x81, 0x4b, 0x4d, 0x48, 0x5a, 0xd2, 0x29, 0x14, 0xeb,
+ 0x38, 0xdd, 0x3e, 0xb5, 0x57, 0x45, 0x9b, 0xed, 0x33, 0x02,
+ 0x03, 0x01, 0x00, 0x01 ),
+ PLAINTEXT ( 0xf7, 0x42, 0x01, 0x57, 0x6b, 0x70, 0xcc, 0x4a, 0xdc, 0xed,
+ 0x12, 0x83, 0x3f, 0xef, 0x27, 0xc1, 0x3c, 0x85, 0xdd, 0x5e,
+ 0x0a, 0x34, 0x98, 0xf9, 0x21, 0xd3, 0x24, 0x2a, 0x5a, 0xb2,
+ 0xdf, 0x60, 0x21, 0x28, 0x7c, 0x5b, 0x7a, 0xbe, 0xcb, 0xea,
+ 0xbc, 0xd6, 0x0e, 0xae, 0x94, 0x64, 0x21, 0xda, 0x28, 0x66,
+ 0x2f, 0x71, 0x48, 0xe5, 0xea, 0x59, 0x38, 0x28, 0x3e, 0xed,
+ 0x3b, 0x95, 0x4f, 0x3d, 0x72, 0x2a, 0x00, 0xf3, 0x95, 0x4d,
+ 0xf0, 0x02, 0x71, 0x63, 0x5a, 0xbc, 0x84, 0xd1, 0x81, 0x3f,
+ 0x16, 0xcd, 0x28, 0x3d, 0x47, 0xa2, 0xee, 0xa1, 0x2f, 0x84,
+ 0x8a, 0x22, 0x02, 0x88, 0xd7, 0x83, 0x06, 0x4a, 0x9f, 0xea,
+ 0x0f, 0x15, 0x48, 0x43, 0x58, 0x6d, 0x39, 0x78, 0x5a, 0x43,
+ 0x3f, 0xed, 0x6f, 0x68, 0xde, 0x9c, 0xfe, 0xd3, 0x67, 0x74,
+ 0x08, 0x46, 0x7d, 0x20, 0x22, 0x60, 0x8c, 0x37, 0x35, 0x46,
+ 0x56, 0x19, 0x3c, 0xfa, 0xa5, 0x40, 0xac, 0x44, 0x90, 0x8a,
+ 0xa5, 0x80, 0xb2, 0x32, 0xbc, 0xb4, 0x3f, 0x3e, 0x5e, 0xd4,
+ 0x51, 0xa9, 0x2e, 0xd9, 0x7f, 0x5e, 0x32, 0xb1, 0x24, 0x35,
+ 0x88, 0x71, 0x3a, 0x01, 0x86, 0x5c, 0xa2, 0xe2, 0x2d, 0x02,
+ 0x30, 0x91, 0x1c, 0xaa, 0x6c, 0x24, 0x42, 0x1b, 0x1a, 0xba,
+ 0x30, 0x40, 0x49, 0x83, 0xd9, 0xd7, 0x66, 0x7e, 0x5c, 0x1a,
+ 0x4b, 0x7f, 0xa6, 0x8e, 0x8a, 0xd6, 0x0c, 0x65, 0x75 ),
+ &sha1_algorithm,
+ SIGNATURE ( 0xa5, 0x5a, 0x8a, 0x67, 0x81, 0x76, 0x7e, 0xad, 0x99, 0x22,
+ 0xf1, 0x47, 0x64, 0xd2, 0xfb, 0x81, 0x45, 0xeb, 0x85, 0x56,
+ 0xf8, 0x7d, 0xb8, 0xec, 0x41, 0x17, 0x84, 0xf7, 0x2b, 0xbb,
+ 0x2b, 0x8f, 0xb6, 0xb8, 0x8f, 0xc6, 0xab, 0x39, 0xbc, 0xa3,
+ 0x72, 0xb3, 0x63, 0x45, 0x5a, 0xe0, 0xac, 0xf8, 0x1c, 0x83,
+ 0x48, 0x84, 0x89, 0x8a, 0x6b, 0xdf, 0x93, 0xa0, 0xc3, 0x0b,
+ 0x0e, 0x3d, 0x80, 0x80 ) );
+
+/** Random message SHA-256 signature test */
+RSA_SIGNATURE_TEST ( sha256_test,
+ PRIVATE ( 0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
+ 0xa5, 0xe9, 0xdb, 0xa9, 0x1a, 0x6e, 0xd6, 0x4c, 0x25, 0x50,
+ 0xfe, 0x61, 0x77, 0x08, 0x7a, 0x80, 0x36, 0xcb, 0x88, 0x49,
+ 0x5c, 0xe8, 0xaa, 0x15, 0xf8, 0xb3, 0xd6, 0x78, 0x51, 0x46,
+ 0x86, 0x3a, 0x5f, 0xd5, 0x9f, 0xab, 0xfe, 0x74, 0x8c, 0x53,
+ 0x0d, 0xb5, 0x3c, 0x7d, 0x2c, 0x35, 0x88, 0x3f, 0xde, 0xa2,
+ 0xce, 0x46, 0x94, 0x30, 0xa9, 0x76, 0xee, 0x25, 0xc5, 0x5d,
+ 0xa6, 0xa6, 0x3a, 0xa5, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
+ 0x40, 0x14, 0x4b, 0xbc, 0x4c, 0x3e, 0x68, 0x8a, 0x9c, 0x7c,
+ 0x00, 0x21, 0x6e, 0x28, 0xd2, 0x87, 0xb1, 0xc1, 0x82, 0x3a,
+ 0x64, 0xc7, 0x11, 0xcb, 0x24, 0xae, 0xec, 0xc8, 0xf2, 0xa4,
+ 0xf6, 0x9c, 0x9a, 0xbb, 0x05, 0x94, 0x80, 0x9b, 0xc1, 0x21,
+ 0x83, 0x36, 0x23, 0xba, 0x04, 0x20, 0x23, 0x06, 0x48, 0xa7,
+ 0xa4, 0xe6, 0x31, 0x8e, 0xa1, 0x73, 0xe5, 0x6b, 0x83, 0x4c,
+ 0x3a, 0xb8, 0xd8, 0x22, 0x61, 0x02, 0x21, 0x00, 0xd4, 0xdf,
+ 0xcb, 0x21, 0x4a, 0x9a, 0x35, 0x52, 0x02, 0x99, 0xcc, 0x40,
+ 0x83, 0x65, 0x30, 0x1f, 0x9d, 0x13, 0xd6, 0xd1, 0x79, 0x10,
+ 0xce, 0x5b, 0xeb, 0x25, 0xa2, 0x39, 0x4e, 0xdf, 0x1c, 0x29,
+ 0x02, 0x21, 0x00, 0xc7, 0x86, 0x8f, 0xd9, 0x88, 0xe9, 0x98,
+ 0x4b, 0x5c, 0x50, 0x06, 0x94, 0x05, 0x59, 0x31, 0x25, 0xa7,
+ 0xa8, 0xe6, 0x95, 0x2b, 0xe3, 0x74, 0x93, 0x51, 0xa8, 0x8e,
+ 0x3d, 0xe2, 0xe0, 0xfa, 0x1d, 0x02, 0x20, 0x6e, 0xe3, 0x81,
+ 0x31, 0xff, 0x65, 0xa3, 0x1e, 0xec, 0x61, 0xe7, 0x67, 0x37,
+ 0xcb, 0x0f, 0x2d, 0x78, 0xaa, 0xab, 0xfd, 0x84, 0x5e, 0x3f,
+ 0xd0, 0xdc, 0x06, 0x47, 0xa2, 0x28, 0xb6, 0xca, 0x39, 0x02,
+ 0x20, 0x13, 0x7d, 0x9f, 0x9b, 0xbe, 0x76, 0x23, 0x3c, 0x69,
+ 0x5e, 0x1f, 0xe6, 0x61, 0xc7, 0x5e, 0xb7, 0xb0, 0xf3, 0x1c,
+ 0xe3, 0x41, 0x90, 0x4c, 0x98, 0xff, 0x87, 0x19, 0xae, 0x0d,
+ 0xf5, 0xb0, 0x39, 0x02, 0x21, 0x00, 0xb7, 0xeb, 0xcd, 0x01,
+ 0x2e, 0x23, 0x42, 0x4f, 0x0c, 0x6f, 0xde, 0xc8, 0x4f, 0xa7,
+ 0x69, 0x09, 0x12, 0x34, 0xb6, 0x95, 0x4d, 0xb8, 0x7f, 0x16,
+ 0xd0, 0x48, 0x17, 0x4a, 0x9e, 0x6e, 0x5e, 0xe2 ),
+ PUBLIC ( 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00,
+ 0x30, 0x48, 0x02, 0x41, 0x00, 0xa5, 0xe9, 0xdb, 0xa9, 0x1a,
+ 0x6e, 0xd6, 0x4c, 0x25, 0x50, 0xfe, 0x61, 0x77, 0x08, 0x7a,
+ 0x80, 0x36, 0xcb, 0x88, 0x49, 0x5c, 0xe8, 0xaa, 0x15, 0xf8,
+ 0xb3, 0xd6, 0x78, 0x51, 0x46, 0x86, 0x3a, 0x5f, 0xd5, 0x9f,
+ 0xab, 0xfe, 0x74, 0x8c, 0x53, 0x0d, 0xb5, 0x3c, 0x7d, 0x2c,
+ 0x35, 0x88, 0x3f, 0xde, 0xa2, 0xce, 0x46, 0x94, 0x30, 0xa9,
+ 0x76, 0xee, 0x25, 0xc5, 0x5d, 0xa6, 0xa6, 0x3a, 0xa5, 0x02,
+ 0x03, 0x01, 0x00, 0x01 ),
+ PLAINTEXT ( 0x60, 0xe7, 0xba, 0x9d, 0x5a, 0xe3, 0x2d, 0xfa, 0x5f, 0x47,
+ 0xdb, 0x93, 0x24, 0x2c, 0xc4, 0xe2, 0x61, 0xf3, 0x89, 0x4d,
+ 0x67, 0xad, 0xc8, 0xae, 0xf8, 0xe2, 0xfb, 0x52, 0x0f, 0x8d,
+ 0x18, 0x7e, 0x30, 0xd8, 0x8d, 0x94, 0x07, 0x92, 0x70, 0x91,
+ 0xaf, 0x3b, 0x92, 0xa6, 0x0f, 0x7a, 0x9b, 0x46, 0x85, 0x8c,
+ 0x2a, 0x5a, 0x78, 0x5d, 0x1e, 0x13, 0xbf, 0xe6, 0x12, 0xbd,
+ 0xb1, 0xbb, 0x92, 0x6d, 0x11, 0xed, 0xe1, 0xe4, 0x6e, 0x88,
+ 0x4d, 0x0b, 0x51, 0xd6, 0xfd, 0x6a, 0xb2, 0x9b, 0xd3, 0xfd,
+ 0x56, 0xec, 0xd9, 0xd6, 0xb8, 0xc5, 0xfd, 0x0c, 0xf7, 0x55,
+ 0x5f, 0xc5, 0x6f, 0xbc, 0xbb, 0x78, 0x2f, 0x50, 0x08, 0x65,
+ 0x0f, 0x12, 0xca, 0x5a, 0xea, 0x52, 0xd0, 0x94, 0x76, 0x17,
+ 0xe4, 0xba, 0x97, 0xba, 0x11, 0xbf, 0x05, 0x7e, 0xa1, 0xfd,
+ 0x7d, 0xb5, 0xf1, 0x3a, 0x7e, 0x6f, 0xa1, 0xaa, 0x97, 0x66,
+ 0x5d, 0x72, 0x76, 0x45, 0x40, 0xb5, 0x22, 0x71, 0x43, 0xe8,
+ 0x77, 0x76, 0xc8, 0x1b, 0xd2, 0xd1, 0x33, 0x05, 0x64, 0xa9,
+ 0xc2, 0xa8, 0x40, 0x40, 0x21, 0xdd, 0xcf, 0x07, 0x7e, 0xf2,
+ 0x4b, 0x80, 0x3d, 0x0f, 0x67, 0xf6, 0xbd, 0xc2, 0xc7, 0xe3,
+ 0x91, 0x71, 0xd6, 0x2d, 0xa1, 0xae, 0x81, 0x0c, 0xed, 0x54,
+ 0x48, 0x79, 0x8a, 0x78, 0x05, 0x74, 0x4d, 0x4f, 0xf0, 0xe0,
+ 0x3c, 0x41, 0x5c, 0x04, 0x0b, 0x68, 0x57, 0xc5, 0xd6 ),
+ &sha256_algorithm,
+ SIGNATURE ( 0x02, 0x2e, 0xc5, 0x2a, 0x2b, 0x7f, 0xb4, 0x80, 0xca, 0x9d,
+ 0x96, 0x5b, 0xaf, 0x1f, 0x72, 0x5b, 0x6e, 0xf1, 0x69, 0x7f,
+ 0x4d, 0x41, 0xd5, 0x9f, 0x00, 0xdc, 0x47, 0xf4, 0x68, 0x8f,
+ 0xda, 0xfc, 0xd1, 0x23, 0x96, 0x11, 0x1d, 0xc0, 0x1b, 0x1d,
+ 0x36, 0x66, 0x2a, 0xf9, 0x21, 0x51, 0xcb, 0xb9, 0x7d, 0x24,
+ 0x7d, 0x38, 0x37, 0xc4, 0xea, 0xdd, 0x3a, 0x6f, 0xa8, 0x65,
+ 0x60, 0x73, 0x77, 0x3c ) );
+
+/**
+ * Perform RSA self-tests
+ *
+ */
+static void rsa_test_exec ( void ) {
+
+ rsa_encrypt_decrypt_ok ( &hw_test );
+ rsa_signature_ok ( &md5_test );
+ rsa_signature_ok ( &sha1_test );
+ rsa_signature_ok ( &sha256_test );
+}
+
+/** RSA self-test */
+struct self_test rsa_test __self_test = {
+ .name = "rsa",
+ .exec = rsa_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/settings_test.c b/src/VBox/Devices/PC/ipxe/src/tests/settings_test.c
new file mode 100644
index 00000000..ac4abee4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/settings_test.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Settings self-tests
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <string.h>
+#include <ipxe/settings.h>
+#include <ipxe/test.h>
+
+/** Define inline raw data */
+#define RAW(...) { __VA_ARGS__ }
+
+/**
+ * Report a formatted-store test result
+ *
+ * @v settings Settings block
+ * @v setting Setting
+ * @v formatted Formatted value
+ * @v raw_array Expected raw value
+ */
+#define storef_ok( settings, setting, formatted, raw_array ) do { \
+ const uint8_t expected[] = raw_array; \
+ uint8_t actual[ sizeof ( expected ) ]; \
+ int len; \
+ \
+ ok ( storef_setting ( settings, setting, formatted ) == 0 ); \
+ len = fetch_setting ( settings, setting, actual, \
+ sizeof ( actual ) ); \
+ DBGC ( settings, "Stored %s \"%s\", got:\n", \
+ (setting)->type->name, formatted ); \
+ DBGC_HDA ( settings, 0, actual, len ); \
+ ok ( len == ( int ) sizeof ( actual ) ); \
+ ok ( memcmp ( actual, expected, sizeof ( actual ) ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report a formatted-fetch test result
+ *
+ * @v settings Settings block
+ * @v setting Setting
+ * @v raw_array Raw value
+ * @v formatted Expected formatted value
+ */
+#define fetchf_ok( settings, setting, raw_array, formatted ) do { \
+ const uint8_t raw[] = raw_array; \
+ char actual[ strlen ( formatted ) + 1 ]; \
+ int len; \
+ \
+ ok ( store_setting ( settings, setting, raw, \
+ sizeof ( raw ) ) == 0 ); \
+ len = fetchf_setting ( settings, setting, actual, \
+ sizeof ( actual ) ); \
+ DBGC ( settings, "Fetched %s \"%s\" from:\n", \
+ (setting)->type->name, formatted ); \
+ DBGC_HDA ( settings, 0, raw, sizeof ( raw ) ); \
+ ok ( len == ( int ) ( sizeof ( actual ) - 1 ) ); \
+ ok ( strcmp ( actual, formatted ) == 0 ); \
+ } while ( 0 )
+
+/** Test generic settings block */
+struct generic_settings test_generic_settings = {
+ .settings = {
+ .refcnt = NULL,
+ .siblings =
+ LIST_HEAD_INIT ( test_generic_settings.settings.siblings ),
+ .children =
+ LIST_HEAD_INIT ( test_generic_settings.settings.children ),
+ .op = &generic_settings_operations,
+ },
+ .list = LIST_HEAD_INIT ( test_generic_settings.list ),
+};
+
+/** Test settings block */
+#define test_settings test_generic_settings.settings
+
+/** Test string setting */
+static struct setting test_string_setting = {
+ .name = "test_string",
+ .type = &setting_type_string,
+};
+
+/** Test URI-encoded string setting */
+static struct setting test_uristring_setting = {
+ .name = "test_uristring",
+ .type = &setting_type_uristring,
+};
+
+/** Test IPv4 address setting type */
+static struct setting test_ipv4_setting = {
+ .name = "test_ipv4",
+ .type = &setting_type_ipv4,
+};
+
+/** Test signed 8-bit integer setting type */
+static struct setting test_int8_setting = {
+ .name = "test_int8",
+ .type = &setting_type_int8,
+};
+
+/** Test signed 16-bit integer setting type */
+static struct setting test_int16_setting = {
+ .name = "test_int16",
+ .type = &setting_type_int16,
+};
+
+/** Test signed 32-bit integer setting type */
+static struct setting test_int32_setting = {
+ .name = "test_int32",
+ .type = &setting_type_int32,
+};
+
+/** Test unsigned 8-bit integer setting type */
+static struct setting test_uint8_setting = {
+ .name = "test_uint8",
+ .type = &setting_type_uint8,
+};
+
+/** Test unsigned 16-bit integer setting type */
+static struct setting test_uint16_setting = {
+ .name = "test_uint16",
+ .type = &setting_type_uint16,
+};
+
+/** Test unsigned 32-bit integer setting type */
+static struct setting test_uint32_setting = {
+ .name = "test_uint32",
+ .type = &setting_type_uint32,
+};
+
+/** Test colon-separated hex string setting type */
+static struct setting test_hex_setting = {
+ .name = "test_hex",
+ .type = &setting_type_hex,
+};
+
+/** Test hyphen-separated hex string setting type */
+static struct setting test_hexhyp_setting = {
+ .name = "test_hexhyp",
+ .type = &setting_type_hexhyp,
+};
+
+/** Test UUID setting type */
+static struct setting test_uuid_setting = {
+ .name = "test_uuid",
+ .type = &setting_type_uuid,
+};
+
+/**
+ * Perform settings self-tests
+ *
+ */
+static void settings_test_exec ( void ) {
+
+ /* Register test settings block */
+ ok ( register_settings ( &test_settings, NULL, "test" ) == 0 );
+
+ /* "string" setting type */
+ storef_ok ( &test_settings, &test_string_setting, "hello",
+ RAW ( 'h', 'e', 'l', 'l', 'o' ) );
+ fetchf_ok ( &test_settings, &test_string_setting,
+ RAW ( 'w', 'o', 'r', 'l', 'd' ), "world" );
+
+ /* "uristring" setting type */
+ storef_ok ( &test_settings, &test_uristring_setting, "hello%20world",
+ RAW ( 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l',
+ 'd' ) );
+ fetchf_ok ( &test_settings, &test_uristring_setting,
+ RAW ( 1, 2, 3, 4, 5 ), "%01%02%03%04%05" );
+
+ /* "ipv4" setting type */
+ storef_ok ( &test_settings, &test_ipv4_setting, "192.168.0.1",
+ RAW ( 192, 168, 0, 1 ) );
+ fetchf_ok ( &test_settings, &test_ipv4_setting,
+ RAW ( 212, 13, 204, 60 ), "212.13.204.60" );
+
+ /* Integer setting types */
+ storef_ok ( &test_settings, &test_int8_setting,
+ "54", RAW ( 54 ) );
+ storef_ok ( &test_settings, &test_int8_setting,
+ "0x7f", RAW ( 0x7f ) );
+ storef_ok ( &test_settings, &test_int8_setting,
+ "0x1234", RAW ( 0x34 ) );
+ storef_ok ( &test_settings, &test_int8_setting,
+ "-32", RAW ( -32 ) );
+ fetchf_ok ( &test_settings, &test_int8_setting,
+ RAW ( -9 ), "-9" );
+ fetchf_ok ( &test_settings, &test_int8_setting,
+ RAW ( 106 ), "106" );
+ storef_ok ( &test_settings, &test_uint8_setting,
+ "129", RAW ( 129 ) );
+ storef_ok ( &test_settings, &test_uint8_setting,
+ "0x3421", RAW ( 0x21 ) );
+ fetchf_ok ( &test_settings, &test_uint8_setting,
+ RAW ( 0x54 ), "0x54" );
+ storef_ok ( &test_settings, &test_int16_setting,
+ "29483", RAW ( 0x73, 0x2b ) );
+ fetchf_ok ( &test_settings, &test_int16_setting,
+ RAW ( 0x82, 0x14 ), "-32236" );
+ fetchf_ok ( &test_settings, &test_int16_setting,
+ RAW ( 0x12, 0x78 ), "4728" );
+ storef_ok ( &test_settings, &test_uint16_setting,
+ "48727", RAW ( 0xbe, 0x57 ) );
+ fetchf_ok ( &test_settings, &test_uint16_setting,
+ RAW ( 0x9a, 0x24 ), "0x9a24" );
+ storef_ok ( &test_settings, &test_int32_setting,
+ "2901274", RAW ( 0x00, 0x2c, 0x45, 0x1a ) );
+ fetchf_ok ( &test_settings, &test_int32_setting,
+ RAW ( 0xff, 0x34, 0x2d, 0xaf ), "-13357649" );
+ fetchf_ok ( &test_settings, &test_int32_setting,
+ RAW ( 0x01, 0x00, 0x34, 0xab ), "16790699" );
+ storef_ok ( &test_settings, &test_uint32_setting,
+ "0xb598d21", RAW ( 0x0b, 0x59, 0x8d, 0x21 ) );
+ fetchf_ok ( &test_settings, &test_uint32_setting,
+ RAW ( 0xf2, 0x37, 0xb2, 0x18 ), "0xf237b218" );
+
+ /* "hex" setting type */
+ storef_ok ( &test_settings, &test_hex_setting,
+ "", RAW ( 0x00 ) );
+ storef_ok ( &test_settings, &test_hex_setting,
+ ":", RAW ( 0x00, 0x00 ) );
+ storef_ok ( &test_settings, &test_hex_setting,
+ "1:2:", RAW ( 0x01, 0x02, 0x00 ) );
+ storef_ok ( &test_settings, &test_hex_setting,
+ "08:12:f5:22:90:1b:4b:47:a8:30:cb:4d:67:4c:d6:76",
+ RAW ( 0x08, 0x12, 0xf5, 0x22, 0x90, 0x1b, 0x4b, 0x47, 0xa8,
+ 0x30, 0xcb, 0x4d, 0x67, 0x4c, 0xd6, 0x76 ) );
+ fetchf_ok ( &test_settings, &test_hex_setting,
+ RAW ( 0x62, 0xd9, 0xd4, 0xc4, 0x7e, 0x3b, 0x41, 0x46, 0x91,
+ 0xc6, 0xfd, 0x0c, 0xbf ),
+ "62:d9:d4:c4:7e:3b:41:46:91:c6:fd:0c:bf" );
+
+ /* "hexhyp" setting type */
+ storef_ok ( &test_settings, &test_hexhyp_setting,
+ "11-33-22", RAW ( 0x11, 0x33, 0x22 ) );
+ fetchf_ok ( &test_settings, &test_hexhyp_setting,
+ RAW ( 0x9f, 0xe5, 0x6d, 0xfb, 0x24, 0x3a, 0x4c, 0xbb, 0xa9,
+ 0x09, 0x6c, 0x66, 0x13, 0xc1, 0xa8, 0xec, 0x27 ),
+ "9f-e5-6d-fb-24-3a-4c-bb-a9-09-6c-66-13-c1-a8-ec-27" );
+
+ /* "uuid" setting type (no store capability) */
+ fetchf_ok ( &test_settings, &test_uuid_setting,
+ RAW ( 0x1a, 0x6a, 0x74, 0x9d, 0x0e, 0xda, 0x46, 0x1a,0xa8,
+ 0x7a, 0x7c, 0xfe, 0x4f, 0xca, 0x4a, 0x57 ),
+ "1a6a749d-0eda-461a-a87a-7cfe4fca4a57" );
+
+ /* Clear and unregister test settings block */
+ clear_settings ( &test_settings );
+ unregister_settings ( &test_settings );
+}
+
+/** Settings self-test */
+struct self_test settings_test __self_test = {
+ .name = "settings",
+ .exec = settings_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/sha1_test.c b/src/VBox/Devices/PC/ipxe/src/tests/sha1_test.c
new file mode 100644
index 00000000..683409c9
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/sha1_test.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * SHA-1 tests
+ *
+ */
+
+#include <stdint.h>
+#include <ipxe/sha1.h>
+#include <ipxe/test.h>
+#include "digest_test.h"
+
+/** An SHA-1 test vector */
+struct sha1_test_vector {
+ /** Test data */
+ void *data;
+ /** Test data length */
+ size_t len;
+ /** Expected digest */
+ uint8_t digest[SHA1_DIGEST_SIZE];
+};
+
+/** SHA-1 test vectors */
+static struct sha1_test_vector sha1_test_vectors[] = {
+ /* Empty test data
+ *
+ * Expected digest value obtained from "sha1sum /dev/null"
+ */
+ { NULL, 0,
+ { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55,
+ 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 } },
+ /* Test data and expected digests taken from the NIST
+ * Cryptographic Toolkit Algorithm Examples at
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA1.pdf
+ */
+ { "abc", 3,
+ { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e,
+ 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d } },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
+ { 0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 0xba, 0xae,
+ 0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1 } },
+};
+
+/** SHA-1 test fragment lists */
+static struct digest_test_fragments sha1_test_fragments[] = {
+ { { 0, -1UL, } },
+ { { 1, 1, 1, 1, 1, 1, 1, 1 } },
+ { { 2, 0, 23, 4, 6, 1, 0 } },
+};
+
+/**
+ * Perform SHA-1 self-test
+ *
+ */
+static void sha1_test_exec ( void ) {
+ struct digest_algorithm *digest = &sha1_algorithm;
+ struct sha1_test_vector *test;
+ unsigned int i;
+ unsigned int j;
+
+ for ( i = 0 ; i < ( sizeof ( sha1_test_vectors ) /
+ sizeof ( sha1_test_vectors[0] ) ) ; i++ ) {
+ test = &sha1_test_vectors[i];
+ /* Test with a single pass */
+ digest_ok ( digest, NULL, test->data, test->len, test->digest );
+ /* Test with fragment lists */
+ for ( j = 0 ; j < ( sizeof ( sha1_test_fragments ) /
+ sizeof ( sha1_test_fragments[0] ) ) ; j++ ){
+ digest_ok ( digest, &sha1_test_fragments[j],
+ test->data, test->len, test->digest );
+ }
+ }
+}
+
+/** SHA-1 self-test */
+struct self_test sha1_test __self_test = {
+ .name = "sha1",
+ .exec = sha1_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/sha256_test.c b/src/VBox/Devices/PC/ipxe/src/tests/sha256_test.c
new file mode 100644
index 00000000..7599ba5d
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/sha256_test.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * SHA-256 tests
+ *
+ */
+
+#include <stdint.h>
+#include <ipxe/sha256.h>
+#include <ipxe/test.h>
+#include "digest_test.h"
+
+/** An SHA-256 test vector */
+struct sha256_test_vector {
+ /** Test data */
+ void *data;
+ /** Test data length */
+ size_t len;
+ /** Expected digest */
+ uint8_t digest[SHA256_DIGEST_SIZE];
+};
+
+/** SHA-256 test vectors */
+static struct sha256_test_vector sha256_test_vectors[] = {
+ /* Empty test data
+ *
+ * Expected digest value obtained from "sha256sum /dev/null"
+ */
+ { NULL, 0,
+ { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4,
+ 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b,
+ 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 } },
+ /* Test data and expected digests taken from the NIST
+ * Cryptographic Toolkit Algorithm Examples at
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA256.pdf
+ */
+ { "abc", 3,
+ { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40,
+ 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17,
+ 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
+ { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26,
+ 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff,
+ 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } },
+};
+
+/** SHA-256 test fragment lists */
+static struct digest_test_fragments sha256_test_fragments[] = {
+ { { 0, -1UL, } },
+ { { 1, 1, 1, 1, 1, 1, 1, 1 } },
+ { { 2, 0, 23, 4, 6, 1, 0 } },
+};
+
+/**
+ * Perform SHA-256 self-test
+ *
+ */
+static void sha256_test_exec ( void ) {
+ struct digest_algorithm *digest = &sha256_algorithm;
+ struct sha256_test_vector *test;
+ unsigned int i;
+ unsigned int j;
+
+ for ( i = 0 ; i < ( sizeof ( sha256_test_vectors ) /
+ sizeof ( sha256_test_vectors[0] ) ) ; i++ ) {
+ test = &sha256_test_vectors[i];
+ /* Test with a single pass */
+ digest_ok ( digest, NULL, test->data, test->len, test->digest );
+ /* Test with fragment lists */
+ for ( j = 0 ; j < ( sizeof ( sha256_test_fragments ) /
+ sizeof ( sha256_test_fragments[0] )); j++ ){
+ digest_ok ( digest, &sha256_test_fragments[j],
+ test->data, test->len, test->digest );
+ }
+ }
+}
+
+/** SHA-256 self-test */
+struct self_test sha256_test __self_test = {
+ .name = "sha256",
+ .exec = sha256_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/test.c b/src/VBox/Devices/PC/ipxe/src/tests/test.c
new file mode 100644
index 00000000..11dd2f5e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/test.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Self-test infrastructure
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/test.h>
+#include <ipxe/init.h>
+#include <ipxe/image.h>
+
+/** Current self-test set */
+static struct self_test *current_tests;
+
+/**
+ * Report test result
+ *
+ * @v success Test succeeded
+ * @v file Test code file
+ * @v line Test code line
+ */
+void test_ok ( int success, const char *file, unsigned int line ) {
+
+ /* Sanity check */
+ assert ( current_tests != NULL );
+
+ /* Increment test counter */
+ current_tests->total++;
+
+ /* Report failure if applicable */
+ if ( ! success ) {
+ current_tests->failures++;
+ printf ( "FAILURE: \"%s\" test failed at %s line %d\n",
+ current_tests->name, file, line );
+ }
+}
+
+/**
+ * Run self-test set
+ *
+ */
+static void run_tests ( struct self_test *tests ) {
+ unsigned int old_assertion_failures = assertion_failures;
+
+ /* Sanity check */
+ assert ( current_tests == NULL );
+
+ /* Record current test set */
+ current_tests = tests;
+
+ /* Run tests */
+ tests->exec();
+
+ /* Clear current test set */
+ current_tests = NULL;
+
+ /* Record number of assertion failures */
+ tests->assertion_failures =
+ ( assertion_failures - old_assertion_failures );
+
+ /* Print test set summary */
+ if ( tests->failures || tests->assertion_failures ) {
+ printf ( "FAILURE: \"%s\" %d of %d tests failed",
+ tests->name, tests->failures, tests->total );
+ if ( tests->assertion_failures ) {
+ printf ( " with %d assertion failures",
+ tests->assertion_failures );
+ }
+ printf ( "\n" );
+ } else {
+ printf ( "OK: \"%s\" %d tests passed\n",
+ tests->name, tests->total );
+ }
+}
+
+/**
+ * Run all self-tests
+ *
+ * @ret rc Return status code
+ */
+static int run_all_tests ( void ) {
+ struct self_test *tests;
+ unsigned int failures = 0;
+ unsigned int assertions = 0;
+ unsigned int total = 0;
+
+ /* Run all compiled-in self-tests */
+ printf ( "Starting self-tests\n" );
+ for_each_table_entry ( tests, SELF_TESTS )
+ run_tests ( tests );
+
+ /* Print overall summary */
+ for_each_table_entry ( tests, SELF_TESTS ) {
+ total += tests->total;
+ failures += tests->failures;
+ assertions += tests->assertion_failures;
+ }
+ if ( failures || assertions ) {
+ printf ( "FAILURE: %d of %d tests failed",
+ failures, total );
+ if ( assertions ) {
+ printf ( " with %d assertion failures", assertions );
+ }
+ printf ( "\n" );
+ return -EINPROGRESS;
+ } else {
+ printf ( "OK: all %d tests passed\n", total );
+ return 0;
+ }
+}
+
+static int test_image_probe ( struct image *image __unused ) {
+ return -ENOTTY;
+}
+
+static int test_image_exec ( struct image *image __unused ) {
+ return run_all_tests();
+}
+
+static struct image_type test_image_type = {
+ .name = "self-tests",
+ .probe = test_image_probe,
+ .exec = test_image_exec,
+};
+
+static struct image test_image = {
+ .refcnt = REF_INIT ( ref_no_free ),
+ .name = "<TESTS>",
+ .type = &test_image_type,
+};
+
+static void test_init ( void ) {
+ int rc;
+
+ /* Register self-tests image */
+ if ( ( rc = register_image ( &test_image ) ) != 0 ) {
+ DBG ( "Could not register self-test image: %s\n",
+ strerror ( rc ) );
+ /* No way to report failure */
+ return;
+ }
+}
+
+/** Self-test initialisation function */
+struct init_fn test_init_fn __init_fn ( INIT_EARLY ) = {
+ .initialise = test_init,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/tests.c b/src/VBox/Devices/PC/ipxe/src/tests/tests.c
new file mode 100644
index 00000000..1bf40418
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/tests.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Self-test collection
+ *
+ */
+
+/* Drag in all applicable self-tests */
+REQUIRE_OBJECT ( list_test );
+REQUIRE_OBJECT ( byteswap_test );
+REQUIRE_OBJECT ( settings_test );
+REQUIRE_OBJECT ( time_test );
+REQUIRE_OBJECT ( crc32_test );
+REQUIRE_OBJECT ( md5_test );
+REQUIRE_OBJECT ( sha1_test );
+REQUIRE_OBJECT ( sha256_test );
+REQUIRE_OBJECT ( aes_cbc_test );
+REQUIRE_OBJECT ( hmac_drbg_test );
+REQUIRE_OBJECT ( hash_df_test );
+REQUIRE_OBJECT ( bigint_test );
+REQUIRE_OBJECT ( rsa_test );
+REQUIRE_OBJECT ( x509_test );
+REQUIRE_OBJECT ( ocsp_test );
+REQUIRE_OBJECT ( cms_test );
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/time_test.c b/src/VBox/Devices/PC/ipxe/src/tests/time_test.c
new file mode 100644
index 00000000..d12d3acf
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/time_test.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Date and time self-tests
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <time.h>
+#include <ipxe/test.h>
+
+/** A mktime() test */
+struct mktime_test {
+ /** Broken-down time */
+ struct tm tm;
+ /** Day of the week */
+ int wday;
+ /** Day of the year */
+ int yday;
+ /** Seconds since the Epoch */
+ time_t time;
+};
+
+/**
+ * Define a mktime() test
+ *
+ * @v name Test name
+ * @v SEC Seconds [0,60]
+ * @v MIN Minutes [0,59]
+ * @v HOUR Hour [0,23]
+ * @v MDAY Day of month [1,31]
+ * @v MON Month of year [0,11]
+ * @v YEAR Years since 1900
+ * @v WDAY Day of week [0,6] (Sunday=0)
+ * @v YDAY Day of year [0,365]
+ * @v ISDST Daylight savings flag (ignored)
+ * @v TIME Seconds since the Epoch
+ * @ret test mktime() test
+ *
+ * This macro is designed to make it easy to generate test vectors in
+ * Perl using
+ *
+ * print join ", ", gmtime ( $time ), $time."ULL";
+ *
+ */
+#define MKTIME_TEST( name, SEC, MIN, HOUR, MDAY, MON, YEAR, WDAY, \
+ YDAY, ISDST, TIME ) \
+ static struct mktime_test name = { \
+ .tm = { \
+ .tm_sec = SEC, \
+ .tm_min = MIN, \
+ .tm_hour = HOUR, \
+ .tm_mday = MDAY, \
+ .tm_mon = MON, \
+ .tm_year = YEAR, \
+ .tm_isdst = ISDST, \
+ }, \
+ .wday = WDAY, \
+ .yday = YDAY, \
+ .time = TIME, \
+ }
+
+/**
+ * Report mktime() test result
+ *
+ * @v test mktime() test
+ */
+#define mktime_ok( test ) do { \
+ time_t time = mktime ( &(test)->tm ); \
+ ok ( time == (test)->time ); \
+ ok ( (test)->tm.tm_wday == (test)->wday ); \
+ ok ( (test)->tm.tm_yday == (test)->yday ); \
+ } while ( 0 )
+
+/* Start of the Epoch */
+MKTIME_TEST ( mktime_epoch, 00, 00, 00, 01, 00, 70, 4, 0, 0, 0 );
+
+/* Birth of iPXE as a new project */
+MKTIME_TEST ( mktime_ipxe, 01, 15, 20, 19, 03, 110, 1, 108, 0, 1271708101ULL );
+
+/* Random test vectors generated using Perl's gmtime() */
+MKTIME_TEST ( mktime_0, 4, 17, 20, 1, 0, 150, 6, 0, 0, 2524681024ULL );
+MKTIME_TEST ( mktime_1, 22, 47, 21, 27, 11, 77, 2, 360, 0, 252107242ULL );
+MKTIME_TEST ( mktime_2, 26, 10, 0, 7, 2, 196, 3, 66, 0, 3981917426ULL );
+MKTIME_TEST ( mktime_3, 44, 44, 23, 15, 9, 261, 4, 287, 0, 6052319084ULL );
+MKTIME_TEST ( mktime_4, 3, 22, 18, 8, 9, 296, 6, 281, 0, 7156232523ULL );
+MKTIME_TEST ( mktime_5, 27, 26, 16, 18, 11, 338, 2, 351, 0, 8487649587ULL );
+MKTIME_TEST ( mktime_6, 31, 36, 22, 3, 3, 293, 3, 92, 0, 7045310191ULL );
+MKTIME_TEST ( mktime_7, 2, 0, 6, 25, 5, 289, 4, 175, 0, 6926191202ULL );
+MKTIME_TEST ( mktime_8, 43, 50, 1, 8, 0, 210, 3, 7, 0, 4418589043ULL );
+MKTIME_TEST ( mktime_9, 48, 14, 20, 23, 3, 86, 3, 112, 0, 514671288ULL );
+MKTIME_TEST ( mktime_10, 4, 43, 5, 29, 11, 173, 5, 362, 0, 3281751784ULL );
+MKTIME_TEST ( mktime_11, 47, 26, 21, 12, 7, 177, 4, 223, 0, 3396029207ULL );
+MKTIME_TEST ( mktime_12, 18, 55, 20, 26, 11, 88, 1, 360, 0, 599172918ULL );
+MKTIME_TEST ( mktime_13, 8, 32, 13, 15, 7, 314, 1, 226, 0, 7719456728ULL );
+MKTIME_TEST ( mktime_14, 0, 16, 11, 20, 6, 138, 2, 200, 0, 2163237360ULL );
+MKTIME_TEST ( mktime_15, 48, 0, 9, 31, 2, 202, 5, 89, 0, 4173238848ULL );
+MKTIME_TEST ( mktime_16, 51, 55, 0, 15, 1, 323, 6, 45, 0, 7987769751ULL );
+MKTIME_TEST ( mktime_17, 36, 10, 7, 11, 5, 301, 4, 161, 0, 7303590636ULL );
+MKTIME_TEST ( mktime_18, 22, 39, 11, 21, 9, 233, 3, 293, 0, 5169181162ULL );
+MKTIME_TEST ( mktime_19, 48, 29, 8, 31, 7, 207, 3, 242, 0, 4344222588ULL );
+MKTIME_TEST ( mktime_20, 4, 53, 22, 8, 8, 165, 2, 250, 0, 3019675984ULL );
+MKTIME_TEST ( mktime_21, 14, 16, 8, 10, 5, 298, 0, 160, 0, 7208900174ULL );
+MKTIME_TEST ( mktime_22, 10, 35, 3, 12, 3, 188, 1, 102, 0, 3732579310ULL );
+MKTIME_TEST ( mktime_23, 47, 12, 18, 22, 2, 103, 6, 80, 0, 1048356767ULL );
+MKTIME_TEST ( mktime_24, 23, 29, 17, 23, 10, 201, 3, 326, 0, 4162210163ULL );
+MKTIME_TEST ( mktime_25, 58, 35, 23, 24, 3, 111, 0, 113, 0, 1303688158ULL );
+MKTIME_TEST ( mktime_26, 34, 56, 15, 24, 11, 154, 4, 357, 0, 2681740594ULL );
+MKTIME_TEST ( mktime_27, 7, 11, 22, 28, 1, 243, 4, 58, 0, 5464447867ULL );
+MKTIME_TEST ( mktime_28, 25, 45, 23, 29, 11, 90, 6, 362, 0, 662514325ULL );
+MKTIME_TEST ( mktime_29, 31, 20, 12, 24, 1, 146, 6, 54, 0, 2403087631ULL );
+MKTIME_TEST ( mktime_30, 49, 7, 18, 16, 10, 271, 6, 319, 0, 6370596469ULL );
+MKTIME_TEST ( mktime_31, 31, 55, 2, 25, 5, 141, 2, 175, 0, 2255741731ULL );
+
+/**
+ * Perform date and time self-tests
+ *
+ */
+static void time_test_exec ( void ) {
+
+ mktime_ok ( &mktime_epoch );
+ mktime_ok ( &mktime_ipxe );
+ mktime_ok ( &mktime_0 );
+ mktime_ok ( &mktime_1 );
+ mktime_ok ( &mktime_2 );
+ mktime_ok ( &mktime_3 );
+ mktime_ok ( &mktime_4 );
+ mktime_ok ( &mktime_5 );
+ mktime_ok ( &mktime_6 );
+ mktime_ok ( &mktime_7 );
+ mktime_ok ( &mktime_8 );
+ mktime_ok ( &mktime_9 );
+ mktime_ok ( &mktime_10 );
+ mktime_ok ( &mktime_11 );
+ mktime_ok ( &mktime_12 );
+ mktime_ok ( &mktime_13 );
+ mktime_ok ( &mktime_14 );
+ mktime_ok ( &mktime_15 );
+ mktime_ok ( &mktime_16 );
+ mktime_ok ( &mktime_17 );
+ mktime_ok ( &mktime_18 );
+ mktime_ok ( &mktime_19 );
+ mktime_ok ( &mktime_20 );
+ mktime_ok ( &mktime_21 );
+ mktime_ok ( &mktime_22 );
+ mktime_ok ( &mktime_23 );
+ mktime_ok ( &mktime_24 );
+ mktime_ok ( &mktime_25 );
+ mktime_ok ( &mktime_26 );
+ mktime_ok ( &mktime_27 );
+ mktime_ok ( &mktime_28 );
+ mktime_ok ( &mktime_29 );
+ mktime_ok ( &mktime_30 );
+ mktime_ok ( &mktime_31 );
+}
+
+/** Date and time self-test */
+struct self_test time_test __self_test = {
+ .name = "time",
+ .exec = time_test_exec,
+};
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/umalloc_test.c b/src/VBox/Devices/PC/ipxe/src/tests/umalloc_test.c
new file mode 100644
index 00000000..53810833
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/umalloc_test.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/umalloc.h>
+#include <ipxe/io.h>
+
+void umalloc_test ( void ) {
+ struct memory_map memmap;
+ userptr_t bob;
+ userptr_t fred;
+
+ printf ( "Before allocation:\n" );
+ get_memmap ( &memmap );
+
+ bob = umalloc ( 1234 );
+ bob = urealloc ( bob, 12345 );
+ fred = umalloc ( 999 );
+
+ printf ( "After allocation:\n" );
+ get_memmap ( &memmap );
+
+ ufree ( bob );
+ ufree ( fred );
+
+ printf ( "After freeing:\n" );
+ get_memmap ( &memmap );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/uri_test.c b/src/VBox/Devices/PC/ipxe/src/tests/uri_test.c
new file mode 100644
index 00000000..c39c7ffe
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/uri_test.c
@@ -0,0 +1,146 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/uri.h>
+
+#define URI_MAX_LEN 1024
+
+struct uri_test {
+ const char *base_uri_string;
+ const char *relative_uri_string;
+ const char *resolved_uri_string;
+};
+
+static struct uri_test uri_tests[] = {
+ { "http://www.fensystems.co.uk", "",
+ "http://www.fensystems.co.uk/" },
+ { "http://ipxe.org/wiki/page1", "page2",
+ "http://ipxe.org/wiki/page2" },
+ { "http://ipxe.org/wiki/page1", "../page3",
+ "http://ipxe.org/page3" },
+ { "tftp://192.168.0.1/", "/tftpboot/vmlinuz",
+ "tftp://192.168.0.1/tftpboot/vmlinuz" },
+ { "ftp://the%41nswer%3d:%34ty%32wo@ether%62oot.org:8080/p%41th/foo",
+ "to?%41=b#%43d",
+ "ftp://theAnswer%3d:4ty2wo@ipxe.org:8080/path/to?a=b#cd" },
+#if 0
+ "http://www.ipxe.org/wiki",
+ "mailto:bob@nowhere.com",
+ "ftp://joe:secret@insecure.org:8081/hidden/path/to?what=is#this",
+#endif
+};
+
+static int test_parse_unparse ( const char *uri_string ) {
+ char buf[URI_MAX_LEN];
+ struct uri *uri = NULL;
+ int rc;
+
+ /* Parse and unparse URI */
+ uri = parse_uri ( uri_string );
+ if ( ! uri ) {
+ rc = -ENOMEM;
+ goto done;
+ }
+ unparse_uri ( buf, sizeof ( buf ), uri, URI_ALL );
+
+ /* Compare result */
+ if ( strcmp ( buf, uri_string ) != 0 ) {
+ printf ( "Unparse of \"%s\" produced \"%s\"\n",
+ uri_string, buf );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ rc = 0;
+
+ done:
+ uri_put ( uri );
+ if ( rc ) {
+ printf ( "URI parse-unparse of \"%s\" failed: %s\n",
+ uri_string, strerror ( rc ) );
+ }
+ return rc;
+}
+
+static int test_resolve ( const char *base_uri_string,
+ const char *relative_uri_string,
+ const char *resolved_uri_string ) {
+ struct uri *base_uri = NULL;
+ struct uri *relative_uri = NULL;
+ struct uri *resolved_uri = NULL;
+ char buf[URI_MAX_LEN];
+ int rc;
+
+ /* Parse URIs */
+ base_uri = parse_uri ( base_uri_string );
+ if ( ! base_uri ) {
+ rc = -ENOMEM;
+ goto done;
+ }
+ relative_uri = parse_uri ( relative_uri_string );
+ if ( ! relative_uri ) {
+ rc = -ENOMEM;
+ goto done;
+ }
+
+ /* Resolve URI */
+ resolved_uri = resolve_uri ( base_uri, relative_uri );
+ if ( ! resolved_uri ) {
+ rc = -ENOMEM;
+ goto done;
+ }
+
+ /* Compare result */
+ unparse_uri ( buf, sizeof ( buf ), resolved_uri, URI_ALL );
+ if ( strcmp ( buf, resolved_uri_string ) != 0 ) {
+ printf ( "Resolution of \"%s\"+\"%s\" produced \"%s\"\n",
+ base_uri_string, relative_uri_string, buf );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ rc = 0;
+
+ done:
+ uri_put ( base_uri );
+ uri_put ( relative_uri );
+ uri_put ( resolved_uri );
+ if ( rc ) {
+ printf ( "URI resolution of \"%s\"+\"%s\" failed: %s\n",
+ base_uri_string, relative_uri_string,
+ strerror ( rc ) );
+ }
+ return rc;
+}
+
+int uri_test ( void ) {
+ unsigned int i;
+ struct uri_test *uri_test;
+ int rc;
+ int overall_rc = 0;
+
+ for ( i = 0 ; i < ( sizeof ( uri_tests ) /
+ sizeof ( uri_tests[0] ) ) ; i++ ) {
+ uri_test = &uri_tests[i];
+ rc = test_parse_unparse ( uri_test->base_uri_string );
+ if ( rc != 0 )
+ overall_rc = rc;
+ rc = test_parse_unparse ( uri_test->relative_uri_string );
+ if ( rc != 0 )
+ overall_rc = rc;
+ rc = test_parse_unparse ( uri_test->resolved_uri_string );
+ if ( rc != 0 )
+ overall_rc = rc;
+ rc = test_resolve ( uri_test->base_uri_string,
+ uri_test->relative_uri_string,
+ uri_test->resolved_uri_string );
+ if ( rc != 0 )
+ overall_rc = rc;
+ }
+
+ if ( overall_rc )
+ printf ( "URI tests failed: %s\n", strerror ( overall_rc ) );
+ return overall_rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/tests/x509_test.c b/src/VBox/Devices/PC/ipxe/src/tests/x509_test.c
new file mode 100644
index 00000000..3a3c9d00
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/tests/x509_test.c
@@ -0,0 +1,947 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * X.509 self-tests
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/x509.h>
+#include <ipxe/asn1.h>
+#include <ipxe/sha256.h>
+#include <ipxe/test.h>
+
+/** Fingerprint algorithm used for X.509 test certificates */
+#define x509_test_algorithm sha256_algorithm
+
+/** An X.509 test certificate */
+struct x509_test_certificate {
+ /** Data */
+ const void *data;
+ /** Length of data */
+ size_t len;
+ /** Fingerprint */
+ const void *fingerprint;
+
+ /** Parsed certificate */
+ struct x509_certificate *cert;
+};
+
+/** An X.509 test certificate chain */
+struct x509_test_chain {
+ /** Test certificates */
+ struct x509_test_certificate **certs;
+ /** Number of certificates */
+ unsigned int count;
+
+ /** Parsed certificate chain */
+ struct x509_chain *chain;
+};
+
+/** Define inline certificate data */
+#define DATA(...) { __VA_ARGS__ }
+
+/** Define inline fingerprint data */
+#define FINGERPRINT(...) { __VA_ARGS__ }
+
+/** Define a test certificate */
+#define CERTIFICATE( name, DATA, FINGERPRINT ) \
+ static const uint8_t name ## _data[] = DATA; \
+ static const uint8_t name ## _fingerprint[] = FINGERPRINT; \
+ static struct x509_test_certificate name = { \
+ .data = name ## _data, \
+ .len = sizeof ( name ## _data ), \
+ .fingerprint = name ## _fingerprint, \
+ }
+
+/** Define a test certificate chain */
+#define CHAIN( name, ... ) \
+ static struct x509_test_certificate * name ## _certs[] = \
+ { __VA_ARGS__ }; \
+ static struct x509_test_chain name = { \
+ .certs = name ## _certs, \
+ .count = ( sizeof ( name ## _certs ) / \
+ sizeof ( name ## _certs[0] ) ), \
+ }
+
+/*
+ * subject iPXE self-test root CA
+ * issuer iPXE self-test root CA
+ */
+CERTIFICATE ( root_crt,
+ DATA ( 0x30, 0x82, 0x02, 0xb3, 0x30, 0x82, 0x02, 0x1c, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xc6, 0xb8, 0x9c, 0x58,
+ 0xd2, 0xdc, 0xc9, 0x5d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
+ 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62,
+ 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65,
+ 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
+ 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65,
+ 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
+ 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f,
+ 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78,
+ 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45,
+ 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e,
+ 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30,
+ 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x39, 0x30,
+ 0x38, 0x30, 0x38, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a,
+ 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d,
+ 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72,
+ 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07,
+ 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30,
+ 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70,
+ 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58,
+ 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73,
+ 0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30,
+ 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+ 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xaa, 0x72,
+ 0xb5, 0xc1, 0x73, 0xf4, 0x95, 0x76, 0xa4, 0x27, 0xab, 0x5e,
+ 0xeb, 0x1d, 0x9d, 0xd0, 0x04, 0xb2, 0x93, 0x05, 0xc7, 0xfa,
+ 0x75, 0x84, 0x66, 0xe6, 0x3a, 0x26, 0x1f, 0xbc, 0x2d, 0xfd,
+ 0x8f, 0x59, 0x64, 0xac, 0xcf, 0x65, 0x9d, 0x82, 0x23, 0xc3,
+ 0x72, 0x93, 0xf2, 0x40, 0x68, 0x32, 0xd1, 0xb8, 0xf1, 0x47,
+ 0x61, 0x50, 0xea, 0xbc, 0xcc, 0x3c, 0x6b, 0x74, 0x7a, 0xec,
+ 0x2b, 0x75, 0xa6, 0xc2, 0xa2, 0xb8, 0xbf, 0x23, 0x48, 0x97,
+ 0xd5, 0xaf, 0x77, 0xc1, 0x92, 0x88, 0xd7, 0x38, 0xb7, 0x9e,
+ 0xda, 0xee, 0x72, 0x04, 0xcb, 0x96, 0xe5, 0xdb, 0xfd, 0x9b,
+ 0x5d, 0x99, 0x4e, 0x7a, 0x60, 0x23, 0x34, 0xa4, 0x8d, 0xd7,
+ 0x6c, 0xe7, 0x5d, 0x93, 0x97, 0xe1, 0xab, 0x36, 0x2c, 0x24,
+ 0x16, 0x92, 0x66, 0xf6, 0x6a, 0x14, 0x23, 0x1d, 0x18, 0xb9,
+ 0x44, 0x24, 0x61, 0x6b, 0xd3, 0x75, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0xa3, 0x23, 0x30, 0x21, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01,
+ 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01,
+ 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x94, 0x9e, 0xea,
+ 0x17, 0x8d, 0x27, 0xa9, 0x17, 0xe5, 0xa9, 0x19, 0xbe, 0x82,
+ 0x36, 0xbd, 0xac, 0x74, 0xf3, 0x6e, 0x75, 0x71, 0x30, 0x1c,
+ 0x05, 0x80, 0x6d, 0x1a, 0x69, 0x37, 0x86, 0x9c, 0x77, 0x75,
+ 0x29, 0xa1, 0xc6, 0xb7, 0x11, 0x0a, 0x63, 0x27, 0xee, 0xb1,
+ 0xc8, 0x94, 0xa9, 0x2e, 0x56, 0x8f, 0xca, 0x9d, 0xbe, 0xf4,
+ 0xdb, 0x63, 0x97, 0x68, 0x3b, 0x13, 0xf8, 0x6a, 0xa5, 0xd1,
+ 0x3d, 0xed, 0xbb, 0x86, 0x9d, 0x42, 0xfc, 0x15, 0x0a, 0x04,
+ 0xf8, 0x3c, 0x0e, 0xc4, 0x86, 0x05, 0x57, 0x56, 0x96, 0xf6,
+ 0xc0, 0x18, 0x53, 0xb0, 0xc5, 0xf0, 0xca, 0x72, 0x77, 0x77,
+ 0xc9, 0x8e, 0x90, 0xa5, 0x4b, 0xb6, 0x80, 0x4a, 0x4c, 0x34,
+ 0x6f, 0xc9, 0xe8, 0x6f, 0xc2, 0x28, 0xdf, 0x93, 0xa9, 0xf5,
+ 0x63, 0x18, 0xc0, 0xec, 0x9e, 0xd5, 0x19, 0x36, 0xc5, 0x94,
+ 0x10, 0xd4, 0x72, 0xd2, 0xb8 ),
+ FINGERPRINT ( 0x71, 0x5d, 0x51, 0x37, 0x5e, 0x18, 0xb3, 0xbc,
+ 0xbb, 0x30, 0x0e, 0x8f, 0x50, 0xc7, 0x55, 0xf5,
+ 0x96, 0xe7, 0xa8, 0x6d, 0x63, 0x2d, 0x32, 0x38,
+ 0xaf, 0x00, 0xc4, 0x1a, 0xfc, 0xd8, 0xac, 0xc3 ) );
+
+/*
+ * subject iPXE self-test intermediate CA
+ * issuer iPXE self-test root CA
+ */
+CERTIFICATE ( intermediate_crt,
+ DATA ( 0x30, 0x82, 0x02, 0xb3, 0x30, 0x82, 0x02, 0x1c, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
+ 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30,
+ 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69,
+ 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+ 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69,
+ 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30,
+ 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50,
+ 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65,
+ 0x73, 0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32,
+ 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x31,
+ 0x34, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x30, 0x31, 0x33,
+ 0x33, 0x5a, 0x30, 0x81, 0x90, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17,
+ 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43,
+ 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68,
+ 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
+ 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79,
+ 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31,
+ 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08,
+ 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x27,
+ 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e, 0x69,
+ 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74,
+ 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d,
+ 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30,
+ 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+ 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xc9, 0x3a,
+ 0xee, 0xc6, 0x3c, 0xac, 0x4d, 0x81, 0xc6, 0x98, 0x5e, 0xe1,
+ 0x48, 0x66, 0x1a, 0x1e, 0x60, 0x19, 0x41, 0xae, 0xca, 0x14,
+ 0x97, 0xc8, 0x3a, 0x50, 0xb6, 0x48, 0xf5, 0x42, 0xac, 0x0f,
+ 0xe1, 0xe3, 0x47, 0xf0, 0xbf, 0x7c, 0xd0, 0xee, 0x8f, 0xb7,
+ 0xa6, 0x19, 0xad, 0xbb, 0xc5, 0x1b, 0x34, 0x38, 0xc8, 0xbd,
+ 0x55, 0x84, 0x93, 0x72, 0xaf, 0x84, 0xfc, 0x9b, 0x97, 0x1d,
+ 0xb5, 0x54, 0x24, 0xd6, 0x5d, 0xb7, 0x31, 0xf4, 0xbd, 0x3b,
+ 0x40, 0x97, 0xc0, 0xa9, 0x5a, 0x2a, 0xcb, 0x6b, 0x98, 0x07,
+ 0xdb, 0xb5, 0x9f, 0xe8, 0x31, 0x3f, 0x01, 0x46, 0x46, 0x70,
+ 0x05, 0xa2, 0x0f, 0x8c, 0x7a, 0x61, 0xf3, 0xdf, 0xdb, 0xa1,
+ 0x37, 0x2c, 0x88, 0x6a, 0x81, 0x21, 0x12, 0x4c, 0xf5, 0xcd,
+ 0xaf, 0xc9, 0xd2, 0x36, 0x3d, 0x82, 0xd1, 0xca, 0x19, 0xaf,
+ 0x4e, 0xae, 0x50, 0x71, 0x44, 0xbf, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0xa3, 0x23, 0x30, 0x21, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01,
+ 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01,
+ 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x5d, 0x3c, 0xb3,
+ 0x52, 0x19, 0xa6, 0x9e, 0x4a, 0x44, 0x98, 0xbf, 0x51, 0x20,
+ 0x47, 0x0a, 0xf3, 0x26, 0x1a, 0xcc, 0x35, 0x2f, 0xc9, 0xed,
+ 0xe0, 0x9d, 0x46, 0xeb, 0xbc, 0x7e, 0xc9, 0xb9, 0x1d, 0x76,
+ 0xa4, 0x1d, 0xc2, 0xd9, 0x16, 0x29, 0x77, 0x01, 0x40, 0xdd,
+ 0xe5, 0xcb, 0x28, 0x91, 0x3a, 0x0c, 0x13, 0x01, 0x1b, 0x72,
+ 0x62, 0x45, 0x27, 0xfd, 0xd7, 0x00, 0x47, 0x36, 0x09, 0x1e,
+ 0x7b, 0xd2, 0xcb, 0x95, 0x3d, 0x28, 0x82, 0xce, 0x83, 0x59,
+ 0x32, 0xf9, 0xe6, 0xec, 0x89, 0xac, 0x88, 0x45, 0x22, 0x88,
+ 0x6f, 0x5e, 0xa2, 0x79, 0x95, 0xba, 0xb9, 0xc9, 0xb6, 0x4c,
+ 0x7c, 0xb4, 0x29, 0xa1, 0x02, 0xf5, 0xac, 0x5d, 0x8e, 0x52,
+ 0xeb, 0xe8, 0xb1, 0x56, 0x49, 0xb3, 0x77, 0x62, 0x7d, 0x87,
+ 0x4d, 0x17, 0xf2, 0x62, 0x83, 0x08, 0x59, 0x21, 0x60, 0x0d,
+ 0x84, 0x8e, 0x5a, 0x84, 0xf6 ),
+ FINGERPRINT ( 0x88, 0x70, 0xbf, 0xf0, 0xd6, 0x09, 0x03, 0x3a,
+ 0xe1, 0x80, 0xa7, 0xa5, 0x5c, 0x3e, 0xe1, 0x05,
+ 0x38, 0x97, 0xde, 0xe1, 0xe9, 0x74, 0x55, 0xb1,
+ 0x1e, 0x59, 0x69, 0x44, 0x42, 0x1b, 0xc8, 0xff ) );
+
+/*
+ * subject iPXE self-test leaf CA
+ * issuer iPXE self-test intermediate CA
+ */
+CERTIFICATE ( leaf_crt,
+ DATA ( 0x30, 0x82, 0x02, 0xb6, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
+ 0x00, 0x30, 0x81, 0x90, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30,
+ 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69,
+ 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+ 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69,
+ 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x27, 0x30,
+ 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e, 0x69, 0x50,
+ 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65,
+ 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65,
+ 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1e,
+ 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30,
+ 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x31,
+ 0x32, 0x31, 0x37, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a,
+ 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d,
+ 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72,
+ 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07,
+ 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30,
+ 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70,
+ 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58,
+ 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73,
+ 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x43, 0x41, 0x30,
+ 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+ 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xc3, 0x55,
+ 0xad, 0xdf, 0x7b, 0xd1, 0x48, 0xc3, 0xd3, 0x02, 0x54, 0x6c,
+ 0x92, 0x45, 0x22, 0x3d, 0x90, 0xd8, 0xc7, 0x13, 0xcd, 0xc1,
+ 0x59, 0xc6, 0xe0, 0xad, 0x0e, 0xe6, 0xdb, 0x3b, 0xe8, 0x63,
+ 0xea, 0x4e, 0xb6, 0xea, 0x50, 0xea, 0x6e, 0x33, 0x9d, 0x28,
+ 0x25, 0x42, 0x49, 0xd0, 0xf0, 0xed, 0xc5, 0x5b, 0x6b, 0x4a,
+ 0xe7, 0x45, 0xfa, 0xd3, 0x3f, 0xae, 0xde, 0x5a, 0x90, 0xab,
+ 0xf1, 0x61, 0x2f, 0x40, 0x5e, 0xcf, 0x8b, 0x0b, 0x10, 0x59,
+ 0xa9, 0xd0, 0x1e, 0x0f, 0x18, 0x6b, 0x92, 0xd8, 0x9f, 0x58,
+ 0x10, 0x84, 0xb6, 0x15, 0xe8, 0x5b, 0xc4, 0xa0, 0x3e, 0x49,
+ 0x8b, 0xea, 0xdd, 0xa9, 0x7e, 0x32, 0x26, 0x9a, 0x68, 0x44,
+ 0xf0, 0x30, 0xca, 0x2a, 0xd6, 0x19, 0x7a, 0x80, 0xfd, 0xd7,
+ 0xfc, 0xc7, 0x5d, 0xe7, 0x61, 0xd2, 0x3f, 0x1f, 0x2c, 0x40,
+ 0x70, 0x7b, 0x34, 0xcb, 0x08, 0xa9, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0xa3, 0x26, 0x30, 0x24, 0x30, 0x12, 0x06, 0x03, 0x55,
+ 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01,
+ 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55,
+ 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02,
+ 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+ 0x40, 0xd2, 0x70, 0x02, 0x08, 0x19, 0xa0, 0xb8, 0x8d, 0x9d,
+ 0x3d, 0x62, 0x41, 0x90, 0x2a, 0x36, 0x4a, 0x8b, 0x21, 0x42,
+ 0x9a, 0xb4, 0xc5, 0xf8, 0x79, 0x17, 0xd7, 0x64, 0x4d, 0xbf,
+ 0x8f, 0x6a, 0x04, 0x54, 0x7a, 0x0b, 0xd4, 0xb5, 0x0e, 0xab,
+ 0xf7, 0xb7, 0x06, 0x2b, 0xf8, 0xde, 0x87, 0xb2, 0x37, 0x3b,
+ 0x95, 0x01, 0xba, 0x9f, 0x8f, 0xec, 0x0a, 0x86, 0xca, 0x51,
+ 0xb6, 0x25, 0x73, 0x2f, 0xa1, 0x66, 0xc8, 0x7a, 0x5e, 0x51,
+ 0xbd, 0x49, 0xb5, 0x75, 0xda, 0xea, 0xe5, 0xeb, 0x5d, 0xe3,
+ 0xb0, 0xad, 0x49, 0x9f, 0x8b, 0xfd, 0x89, 0xb3, 0xb7, 0xb2,
+ 0x4c, 0x7d, 0x8a, 0x29, 0xb2, 0xbe, 0x04, 0xef, 0x9c, 0x73,
+ 0x3c, 0xea, 0xa3, 0x9f, 0x07, 0x66, 0x5a, 0x2f, 0x38, 0xad,
+ 0x1a, 0xeb, 0xe1, 0xb0, 0x62, 0x14, 0x55, 0xdc, 0x8c, 0x83,
+ 0xbb, 0xc7, 0x13, 0x04, 0x41, 0x54, 0xf1, 0x45 ),
+ FINGERPRINT ( 0xca, 0xcf, 0xea, 0x98, 0x3d, 0x71, 0xb6, 0x9d,
+ 0x4f, 0x5b, 0x84, 0x5e, 0xaa, 0x8e, 0xae, 0x63,
+ 0x0e, 0xad, 0x52, 0xe8, 0xc7, 0x51, 0x81, 0x07,
+ 0xd1, 0xa1, 0x66, 0xdb, 0xd5, 0x62, 0xe1, 0xe6 ) );
+
+/*
+ * subject iPXE self-test useless CA
+ * issuer iPXE self-test leaf CA
+ */
+CERTIFICATE ( useless_crt,
+ DATA ( 0x30, 0x82, 0x02, 0xae, 0x30, 0x82, 0x02, 0x17, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
+ 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30,
+ 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69,
+ 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+ 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69,
+ 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30,
+ 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50,
+ 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65,
+ 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x43, 0x41,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32,
+ 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x17, 0x0d, 0x31,
+ 0x34, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x30, 0x31, 0x33,
+ 0x34, 0x5a, 0x30, 0x81, 0x8b, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17,
+ 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43,
+ 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68,
+ 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
+ 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79,
+ 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31,
+ 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08,
+ 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x22,
+ 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x69,
+ 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74,
+ 0x65, 0x73, 0x74, 0x20, 0x75, 0x73, 0x65, 0x6c, 0x65, 0x73,
+ 0x73, 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02,
+ 0x81, 0x81, 0x00, 0xbe, 0x7f, 0x5a, 0x07, 0x7c, 0x61, 0xc2,
+ 0x3a, 0x7e, 0xe3, 0x94, 0xcb, 0xe9, 0xc3, 0x4c, 0x6f, 0x8d,
+ 0x5c, 0x4a, 0xf0, 0xc2, 0x13, 0x54, 0x09, 0x39, 0xa8, 0xf9,
+ 0xc2, 0xc3, 0xdd, 0xbe, 0x42, 0x99, 0xa6, 0xe1, 0x58, 0x0a,
+ 0xd5, 0x89, 0x12, 0xa6, 0xd6, 0x4e, 0xfb, 0x6c, 0xe5, 0xab,
+ 0xff, 0x40, 0x52, 0xcc, 0x1e, 0x63, 0x10, 0xd7, 0xfe, 0x49,
+ 0xf3, 0x86, 0x29, 0x58, 0x6a, 0x90, 0xe4, 0xe2, 0x56, 0x85,
+ 0x14, 0x7d, 0xa5, 0xf8, 0xe0, 0x7e, 0x96, 0x88, 0xd9, 0x23,
+ 0xe5, 0x44, 0x72, 0xa9, 0x5a, 0xbb, 0x76, 0x6b, 0x59, 0x3e,
+ 0x85, 0xd4, 0xe7, 0xb2, 0x31, 0x32, 0xea, 0x40, 0x1f, 0xce,
+ 0xfb, 0xb1, 0x91, 0xee, 0x86, 0x91, 0x3e, 0xa4, 0x86, 0xa4,
+ 0xe9, 0x74, 0xd7, 0x14, 0x8c, 0xb6, 0xb4, 0xc0, 0x08, 0xbb,
+ 0xc8, 0x38, 0xc3, 0x96, 0x3d, 0x85, 0xcf, 0xef, 0x94, 0x52,
+ 0x29, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x23, 0x30, 0x21,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06,
+ 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03,
+ 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+ 0x81, 0x00, 0x50, 0x59, 0xfb, 0x9d, 0x4d, 0xfe, 0x0e, 0x5b,
+ 0xc4, 0x51, 0xe9, 0xe8, 0xa4, 0xf5, 0x2f, 0x32, 0x8b, 0x06,
+ 0x78, 0xbe, 0xf1, 0x18, 0xc5, 0x6f, 0xd9, 0x20, 0xee, 0xb7,
+ 0x51, 0x40, 0xaf, 0xf3, 0x3c, 0xe4, 0x74, 0x00, 0xa4, 0x63,
+ 0x3b, 0x37, 0xe1, 0xef, 0x80, 0xdc, 0xd5, 0x90, 0xed, 0xba,
+ 0x91, 0x86, 0x7f, 0x97, 0x5d, 0x3e, 0x8f, 0x29, 0xcc, 0x57,
+ 0xee, 0x79, 0x15, 0x6b, 0xe3, 0xd1, 0x25, 0x14, 0x24, 0xdf,
+ 0xbf, 0x38, 0xee, 0xe3, 0x8a, 0x88, 0x19, 0x0f, 0xc8, 0x10,
+ 0xae, 0x27, 0x99, 0xa8, 0x35, 0x47, 0xc9, 0xfb, 0x92, 0x47,
+ 0xa2, 0x36, 0x2a, 0x8c, 0x26, 0x12, 0xb1, 0x0d, 0x46, 0xe2,
+ 0xdc, 0x33, 0x29, 0x0c, 0x32, 0xcf, 0x22, 0x49, 0xde, 0xc3,
+ 0x55, 0x2a, 0xba, 0xdd, 0xe3, 0x98, 0xc0, 0xe4, 0x9a, 0xa2,
+ 0xe5, 0x43, 0x04, 0x32, 0xd3, 0x50, 0x7d, 0x9c, 0x71, 0x23 ),
+ FINGERPRINT ( 0xda, 0xbf, 0xd3, 0x5e, 0x2e, 0x29, 0xa9, 0xfd,
+ 0x4d, 0x40, 0xba, 0xb8, 0xdd, 0x66, 0x93, 0x4c,
+ 0x10, 0xea, 0x5b, 0x07, 0xa6, 0xe2, 0x27, 0x63,
+ 0x2e, 0xfe, 0x01, 0x63, 0x7c, 0xea, 0xc6, 0xd0 ) );
+
+/*
+ * subject boot.test.ipxe.org
+ * issuer iPXE self-test leaf CA
+ */
+CERTIFICATE ( server_crt,
+ DATA ( 0x30, 0x82, 0x02, 0x7d, 0x30, 0x82, 0x01, 0xe6, 0x02, 0x01,
+ 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65,
+ 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65,
+ 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65,
+ 0x61, 0x66, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+ 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33,
+ 0x34, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x33, 0x32, 0x32,
+ 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x30, 0x81, 0x84,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12,
+ 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43,
+ 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18,
+ 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46,
+ 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73,
+ 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03,
+ 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e,
+ 0x6f, 0x72, 0x67, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x2e, 0x74,
+ 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
+ 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81,
+ 0x00, 0xbd, 0x43, 0x97, 0x45, 0xa2, 0xe0, 0x1d, 0x38, 0x41,
+ 0xb0, 0xd9, 0x91, 0xf9, 0x77, 0xa9, 0xcb, 0x9c, 0x9c, 0x93,
+ 0xfe, 0x5a, 0xee, 0xbc, 0xd9, 0x0f, 0x39, 0xf6, 0x42, 0xe4,
+ 0x55, 0x21, 0xbb, 0x11, 0xfd, 0xfd, 0xba, 0x25, 0x58, 0xc8,
+ 0xc6, 0xa5, 0x3b, 0x6f, 0x80, 0xba, 0x5b, 0xbc, 0x89, 0xca,
+ 0x7a, 0xdf, 0x6e, 0xb9, 0x81, 0xb6, 0x25, 0x67, 0x0a, 0x38,
+ 0x10, 0xf8, 0x26, 0x43, 0x0c, 0x51, 0x02, 0x14, 0xd6, 0xf2,
+ 0x9d, 0x7c, 0xf5, 0x25, 0x1c, 0x78, 0x4d, 0x47, 0xaf, 0x87,
+ 0x2e, 0x38, 0x49, 0x87, 0xb5, 0x8a, 0xf3, 0xb5, 0xd4, 0x15,
+ 0x69, 0x2a, 0x52, 0xc9, 0x46, 0x97, 0x34, 0x8e, 0x50, 0x4b,
+ 0xc4, 0xf2, 0xfb, 0x39, 0xfd, 0x16, 0x68, 0xdb, 0xa8, 0x17,
+ 0xe2, 0x71, 0x4b, 0xe0, 0xdf, 0x3d, 0xfc, 0xc3, 0x9b, 0x9d,
+ 0x22, 0xc9, 0xd3, 0xf6, 0x02, 0xa6, 0x60, 0xef, 0xf7, 0x02,
+ 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03,
+ 0x81, 0x81, 0x00, 0x7d, 0xff, 0x73, 0xf3, 0x68, 0xe3, 0x75,
+ 0xf1, 0xcf, 0xac, 0x2e, 0x23, 0x73, 0xea, 0xd1, 0x26, 0x33,
+ 0xbf, 0xf9, 0x56, 0xdf, 0xbf, 0x98, 0x20, 0x84, 0x08, 0x78,
+ 0x6b, 0xe6, 0x71, 0x7e, 0x22, 0x68, 0x4d, 0x6c, 0xbb, 0xd5,
+ 0xcc, 0xb4, 0x28, 0x33, 0x5e, 0xbe, 0x4d, 0x10, 0x16, 0x9f,
+ 0x65, 0x3b, 0x68, 0x90, 0xa7, 0xf7, 0x9d, 0x57, 0x71, 0x45,
+ 0x39, 0x86, 0x4c, 0xc0, 0x97, 0x34, 0x03, 0x9c, 0x2b, 0x25,
+ 0x05, 0xb1, 0x5c, 0x0c, 0x4e, 0xf2, 0x14, 0xbf, 0xcf, 0xf0,
+ 0x9a, 0x2d, 0xcf, 0x02, 0x47, 0x60, 0xd2, 0xe9, 0xed, 0xbf,
+ 0x71, 0x5d, 0x07, 0x09, 0x01, 0x87, 0xeb, 0xf7, 0xa8, 0x26,
+ 0x86, 0x24, 0x59, 0xf0, 0x31, 0x3b, 0x42, 0xd1, 0xf1, 0xfd,
+ 0x7c, 0x49, 0x5f, 0x1a, 0xf0, 0x41, 0x67, 0xf0, 0x16, 0x3a,
+ 0xfd, 0xb6, 0xb5, 0xf6, 0x2e, 0x0c, 0x18, 0x1f, 0x09, 0x8e,
+ 0x4d ),
+ FINGERPRINT ( 0xe0, 0xdb, 0x60, 0x53, 0x7c, 0xf6, 0x25, 0x8f,
+ 0xa7, 0xba, 0xdf, 0xe2, 0x1a, 0xfc, 0x27, 0x49,
+ 0xf6, 0x83, 0x15, 0xbd, 0x1b, 0x4c, 0x3f, 0x36,
+ 0x6f, 0x33, 0xf2, 0x47, 0x8e, 0x8b, 0x38, 0xa8 ) );
+
+/*
+ * subject not.a.ca.test.ipxe.org
+ * issuer boot.test.ipxe.org
+ */
+CERTIFICATE ( not_ca_crt,
+ DATA ( 0x30, 0x82, 0x02, 0x7d, 0x30, 0x82, 0x01, 0xe6, 0x02, 0x01,
+ 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65,
+ 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x2e, 0x74, 0x65,
+ 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72,
+ 0x67, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32,
+ 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x17, 0x0d,
+ 0x31, 0x33, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31,
+ 0x33, 0x34, 0x5a, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31,
+ 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e,
+ 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73,
+ 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
+ 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72,
+ 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53,
+ 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64,
+ 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c,
+ 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31,
+ 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16,
+ 0x6e, 0x6f, 0x74, 0x2e, 0x61, 0x2e, 0x63, 0x61, 0x2e, 0x74,
+ 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
+ 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81,
+ 0x00, 0xc3, 0x5b, 0x6d, 0xb3, 0x8d, 0x74, 0x9c, 0x1d, 0xbd,
+ 0x94, 0x41, 0xa2, 0x42, 0x96, 0x3c, 0x41, 0x82, 0xc0, 0xf1,
+ 0x95, 0xbf, 0xc5, 0x34, 0x92, 0x92, 0xa3, 0xed, 0xed, 0x5c,
+ 0x07, 0xaa, 0xb4, 0xc1, 0x66, 0xbb, 0xa6, 0xd1, 0xd9, 0x78,
+ 0x93, 0xf1, 0x9c, 0x3e, 0x13, 0x3a, 0xee, 0x74, 0x31, 0xeb,
+ 0x55, 0x86, 0xa5, 0x43, 0x8a, 0x5d, 0x0c, 0x2c, 0x0d, 0xfb,
+ 0x91, 0x9e, 0x31, 0x22, 0xbe, 0x96, 0xb5, 0x0e, 0x44, 0xc8,
+ 0x5b, 0x65, 0xb2, 0xf5, 0xec, 0x2a, 0x51, 0xed, 0x8f, 0x28,
+ 0xd8, 0xb2, 0x4b, 0x45, 0x39, 0x31, 0x1f, 0x11, 0xb7, 0x12,
+ 0xe3, 0xc6, 0xb2, 0xd2, 0x8d, 0x50, 0xd5, 0xf4, 0xd2, 0x71,
+ 0x77, 0xc9, 0x4c, 0x67, 0xee, 0xf7, 0xdc, 0xdb, 0x68, 0xa6,
+ 0xac, 0x33, 0xd4, 0xb2, 0x12, 0x61, 0x5c, 0xae, 0x4c, 0x2e,
+ 0x26, 0xe8, 0xdf, 0x46, 0x3a, 0x05, 0xaf, 0xeb, 0x0d, 0x02,
+ 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03,
+ 0x81, 0x81, 0x00, 0x90, 0x3e, 0x16, 0x27, 0x2f, 0x4e, 0x4b,
+ 0x31, 0x0e, 0xae, 0x31, 0x9d, 0x64, 0x88, 0x9f, 0xce, 0xd8,
+ 0x22, 0x51, 0x9d, 0xd9, 0x2b, 0xfe, 0xed, 0x75, 0xbe, 0xec,
+ 0x5a, 0x73, 0xaf, 0x6c, 0xa5, 0x5e, 0xd1, 0x15, 0x9a, 0x08,
+ 0xcf, 0x4d, 0x41, 0x78, 0x48, 0xb4, 0x29, 0xf1, 0xf7, 0x63,
+ 0x9b, 0x11, 0x91, 0x16, 0x94, 0x55, 0xff, 0xeb, 0xe9, 0x6f,
+ 0x0a, 0x34, 0x89, 0xed, 0xf2, 0xd1, 0x79, 0x91, 0x9d, 0xe5,
+ 0x73, 0x48, 0x68, 0x7f, 0x9b, 0xf4, 0x94, 0x80, 0x29, 0xbb,
+ 0x2f, 0xac, 0x6c, 0xf7, 0x6a, 0x43, 0xcc, 0x40, 0x34, 0x85,
+ 0xc8, 0xa1, 0x6d, 0x16, 0x36, 0x65, 0x3f, 0x93, 0x60, 0xc1,
+ 0x64, 0x33, 0x91, 0xa1, 0x8f, 0x86, 0x8c, 0xce, 0x14, 0x19,
+ 0x72, 0x28, 0xef, 0x94, 0x3d, 0x09, 0xb8, 0x3b, 0x39, 0xe8,
+ 0xd1, 0x66, 0x2b, 0x38, 0xb4, 0x46, 0x50, 0xf4, 0xcd, 0xc4,
+ 0x9a ),
+ FINGERPRINT ( 0x37, 0x6b, 0xc2, 0x20, 0xa9, 0xbc, 0xe2, 0x83,
+ 0x99, 0x60, 0x06, 0x2e, 0xaf, 0x94, 0xfe, 0xb0,
+ 0x1a, 0x2c, 0x17, 0x47, 0x1e, 0xc0, 0xd1, 0x66,
+ 0xb6, 0x76, 0xeb, 0x1c, 0x07, 0xae, 0x72, 0xf2 ) );
+
+/*
+ * subject bad.path.len.test.ipxe.org
+ * issuer iPXE self-test useless CA
+ */
+CERTIFICATE ( bad_path_len_crt,
+ DATA ( 0x30, 0x82, 0x02, 0x88, 0x30, 0x82, 0x01, 0xf1, 0x02, 0x01,
+ 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x8b, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65,
+ 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x19, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65,
+ 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, 0x73,
+ 0x65, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x43, 0x41, 0x30, 0x1e,
+ 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30,
+ 0x30, 0x31, 0x33, 0x34, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30,
+ 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a,
+ 0x30, 0x81, 0x8c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d,
+ 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72,
+ 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07,
+ 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30,
+ 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70,
+ 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x23, 0x30, 0x21,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1a, 0x62, 0x61, 0x64,
+ 0x2e, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x6c, 0x65, 0x6e, 0x2e,
+ 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, 0x65, 0x2e,
+ 0x6f, 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81,
+ 0x81, 0x00, 0xed, 0xf1, 0xe3, 0xb2, 0x61, 0x68, 0xa0, 0xd5,
+ 0x43, 0xfe, 0xad, 0xee, 0xfb, 0x8e, 0x2c, 0xf0, 0x44, 0xaf,
+ 0x0a, 0x3c, 0x87, 0xc2, 0x56, 0x9b, 0x66, 0x15, 0xc6, 0xbc,
+ 0x5b, 0x96, 0xef, 0xa1, 0x49, 0xd6, 0xe7, 0xeb, 0xb8, 0xf6,
+ 0x3d, 0x62, 0xf5, 0x51, 0xfd, 0xb1, 0xa5, 0x4e, 0x92, 0x7c,
+ 0x7a, 0x31, 0x1b, 0xb8, 0x21, 0x5c, 0xfe, 0x0b, 0x4e, 0x58,
+ 0xd6, 0xd0, 0x8b, 0x81, 0x00, 0x4a, 0xf8, 0xf7, 0x2a, 0xc9,
+ 0xea, 0xfa, 0x9c, 0xc9, 0x33, 0x0b, 0xc4, 0xce, 0x96, 0x4c,
+ 0x30, 0x6e, 0xf0, 0x07, 0xfa, 0x1b, 0x94, 0x1f, 0xe3, 0x3b,
+ 0xb2, 0x7d, 0x31, 0x1a, 0x37, 0x64, 0xe2, 0xc3, 0xf1, 0xe5,
+ 0xb9, 0xcc, 0xd1, 0x02, 0xae, 0x16, 0x39, 0x9b, 0xfc, 0x55,
+ 0xca, 0xdd, 0x33, 0x92, 0xe3, 0x12, 0x40, 0xc5, 0x32, 0x51,
+ 0x62, 0xac, 0x3a, 0xc0, 0x17, 0x36, 0xd0, 0x27, 0x3d, 0xbb,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x03, 0x81, 0x81, 0x00, 0x07, 0x53, 0x2a, 0x80, 0xd6, 0x25,
+ 0x10, 0x37, 0xce, 0x3b, 0x87, 0x87, 0xfc, 0xae, 0xe2, 0x2a,
+ 0x28, 0x3f, 0xf7, 0xa6, 0x32, 0x5b, 0x06, 0xbd, 0x4f, 0x34,
+ 0x6b, 0x47, 0x8a, 0x4b, 0x47, 0x51, 0xe8, 0x45, 0x69, 0xe3,
+ 0xf3, 0xdf, 0xa4, 0x25, 0x8f, 0x34, 0xbe, 0xe5, 0x2c, 0xa4,
+ 0x6c, 0x8c, 0x6e, 0x02, 0x74, 0x23, 0x43, 0x21, 0x4d, 0xe3,
+ 0x75, 0x93, 0x8e, 0xa8, 0x2c, 0x54, 0xba, 0x35, 0xe7, 0xab,
+ 0x44, 0xfa, 0x07, 0x7a, 0x18, 0xb4, 0xa7, 0xce, 0xfa, 0xa6,
+ 0x74, 0x5a, 0x45, 0x2c, 0x6f, 0x86, 0x34, 0x8f, 0x4a, 0x09,
+ 0xe0, 0xf3, 0x4f, 0x37, 0xbb, 0xa3, 0xa0, 0xcb, 0xad, 0x6b,
+ 0xc1, 0x16, 0x06, 0xdf, 0x83, 0x98, 0xaf, 0xa8, 0xc3, 0xa0,
+ 0x5f, 0x33, 0x09, 0x01, 0x12, 0xbd, 0xd3, 0x45, 0x9f, 0x5f,
+ 0x96, 0x93, 0xe9, 0x69, 0xe9, 0xb1, 0x8a, 0xe4, 0x94, 0xce,
+ 0xe4, 0x8d ),
+ FINGERPRINT ( 0xb6, 0x80, 0x84, 0xf1, 0x45, 0x55, 0x1f, 0xbc,
+ 0x15, 0xa6, 0xd8, 0x4b, 0xf3, 0x19, 0x65, 0xef,
+ 0x53, 0x5a, 0xc8, 0x99, 0xe5, 0xdf, 0x79, 0x07,
+ 0x00, 0x2c, 0x9f, 0x49, 0x91, 0x21, 0xeb, 0xfc ) );
+
+/** Valid certificate chain up to boot.test.ipxe.org */
+CHAIN ( server_chain, &server_crt, &leaf_crt, &intermediate_crt, &root_crt );
+
+/** Broken certificate chain up to boot.test.ipxe.org */
+CHAIN ( broken_server_chain, &server_crt, &leaf_crt, &root_crt );
+
+/** Incomplete certificate chain up to boot.test.ipxe.org */
+CHAIN ( incomplete_server_chain, &server_crt, &leaf_crt, &intermediate_crt );
+
+/** Non-functional certificate chain up to not_ca.test.ipxe.org */
+CHAIN ( not_ca_chain,
+ &not_ca_crt, &server_crt, &leaf_crt, &intermediate_crt, &root_crt );
+
+/** Valid certificate chain up to iPXE self-test useless CA */
+CHAIN ( useless_chain, &useless_crt, &leaf_crt, &intermediate_crt, &root_crt );
+
+/** Non-functional certificate chain up to bad.path.len.test.ipxe.org */
+CHAIN ( bad_path_len_chain, &bad_path_len_crt, &useless_crt, &leaf_crt,
+ &intermediate_crt, &root_crt );
+
+/** Certificate store containing the iPXE self-test root CA */
+static struct x509_root test_root = {
+ .digest = &x509_test_algorithm,
+ .count = 1,
+ .fingerprints = root_crt_fingerprint,
+};
+
+/** Certificate store containing the iPXE self-test intermediate CA */
+static struct x509_root intermediate_root = {
+ .digest = &x509_test_algorithm,
+ .count = 1,
+ .fingerprints = intermediate_crt_fingerprint,
+};
+
+/** Dummy fingerprint (not matching any certificates) */
+static uint8_t dummy_fingerprint[] =
+ FINGERPRINT ( 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff );
+
+/** Certificate store containing a dummy fingerprint */
+static struct x509_root dummy_root = {
+ .digest = &x509_test_algorithm,
+ .count = 1,
+ .fingerprints = dummy_fingerprint,
+};
+
+/** Time at which all test certificates are valid */
+static time_t test_time = 1332374737ULL; /* Thu Mar 22 00:05:37 2012 */
+
+/** Time at which end-entity test certificates are invalid */
+static time_t test_expired = 1375573111ULL; /* Sat Aug 3 23:38:31 2013 */
+
+/** Time at which CA test certificates are invalid */
+static time_t test_ca_expired = 2205014905ULL; /* Wed Nov 16 00:08:25 2039 */
+
+/**
+ * Report certificate parsing test result
+ *
+ * @v crt Test certificate
+ */
+#define x509_certificate_ok( crt ) do { \
+ ok ( x509_certificate ( (crt)->data, (crt)->len, \
+ &(crt)->cert ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report cached certificate parsing test result
+ *
+ * @v crt Test certificate
+ */
+#define x509_cached_ok( crt ) do { \
+ struct x509_certificate *temp; \
+ ok ( x509_certificate ( (crt)->data, (crt)->len, \
+ &temp ) == 0 ); \
+ ok ( temp == (crt)->cert ); \
+ x509_put ( temp ); \
+ } while ( 0 )
+
+/**
+ * Report certificate fingerprint test result
+ *
+ * @v crt Test certificate
+ */
+#define x509_fingerprint_ok( crt ) do { \
+ uint8_t fingerprint[ x509_test_algorithm.digestsize ]; \
+ x509_fingerprint ( (crt)->cert, &x509_test_algorithm, \
+ fingerprint ); \
+ ok ( memcmp ( fingerprint, (crt)->fingerprint, \
+ sizeof ( fingerprint ) ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report certificate issuer validation test result
+ *
+ * @v crt Test certificate
+ * @v issuer Test issuer
+ */
+#define x509_check_issuer_ok( crt, issuer ) do { \
+ ok ( x509_check_issuer ( (crt)->cert, (issuer)->cert ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report certificate issuer validation failure test result
+ *
+ * @v crt Test certificate
+ * @v issuer Test issuer
+ */
+#define x509_check_issuer_fail_ok( crt, issuer ) do { \
+ ok ( x509_check_issuer ( (crt)->cert, (issuer)->cert ) != 0 ); \
+ } while ( 0 )
+
+/**
+ * Report certificate root validation test result
+ *
+ * @v crt Test certificate
+ * @v root Test root certificate store
+ */
+#define x509_check_root_ok( crt, root ) do { \
+ ok ( x509_check_root ( (crt)->cert, root ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report certificate root validation failure test result
+ *
+ * @v crt Test certificate
+ * @v root Test root certificate store
+ */
+#define x509_check_root_fail_ok( crt, root ) do { \
+ ok ( x509_check_root ( (crt)->cert, root ) != 0 ); \
+ } while ( 0 )
+
+/**
+ * Report certificate time validation test result
+ *
+ * @v crt Test certificate
+ * @v time Test time
+ */
+#define x509_check_time_ok( crt, time ) do { \
+ ok ( x509_check_time ( (crt)->cert, time ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report certificate time validation failure test result
+ *
+ * @v crt Test certificate
+ * @v time Test time
+ */
+#define x509_check_time_fail_ok( crt, time ) do { \
+ ok ( x509_check_time ( (crt)->cert, time ) != 0 ); \
+ } while ( 0 )
+
+/**
+ * Report certificate chain parsing test result
+ *
+ * @v chn Test certificate chain
+ */
+#define x509_chain_ok( chn ) do { \
+ unsigned int i; \
+ struct x509_certificate *first; \
+ (chn)->chain = x509_alloc_chain(); \
+ ok ( (chn)->chain != NULL ); \
+ for ( i = 0 ; i < (chn)->count ; i++ ) { \
+ ok ( x509_append ( (chn)->chain, \
+ (chn)->certs[i]->cert ) == 0 ); \
+ } \
+ first = x509_first ( (chn)->chain ); \
+ ok ( first != NULL ); \
+ ok ( first->raw.len == (chn)->certs[0]->len ); \
+ ok ( memcmp ( first->raw.data, (chn)->certs[0]->data, \
+ first->raw.len ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report certificate chain validation test result
+ *
+ * @v chn Test certificate chain
+ * @v time Test certificate validation time
+ * @v root Test root certificate store
+ */
+#define x509_validate_chain_ok( chn, time, root ) do { \
+ x509_invalidate_chain ( (chn)->chain ); \
+ ok ( x509_validate_chain ( (chn)->chain, (time), \
+ (root) ) == 0 ); \
+ } while ( 0 )
+
+/**
+ * Report certificate chain validation failure test result
+ *
+ * @v chn Test certificate chain
+ * @v time Test certificate validation time
+ * @v root Test root certificate store
+ */
+#define x509_validate_chain_fail_ok( chn, time, root ) do { \
+ x509_invalidate_chain ( (chn)->chain ); \
+ ok ( x509_validate_chain ( (chn)->chain, (time), \
+ (root) ) != 0 ); \
+ } while ( 0 )
+
+/**
+ * Perform X.509 self-tests
+ *
+ */
+static void x509_test_exec ( void ) {
+
+ /* Parse all certificates */
+ x509_certificate_ok ( &root_crt );
+ x509_certificate_ok ( &intermediate_crt );
+ x509_certificate_ok ( &leaf_crt );
+ x509_certificate_ok ( &useless_crt );
+ x509_certificate_ok ( &server_crt );
+ x509_certificate_ok ( &not_ca_crt );
+ x509_certificate_ok ( &bad_path_len_crt );
+
+ /* Check cache functionality */
+ x509_cached_ok ( &root_crt );
+ x509_cached_ok ( &intermediate_crt );
+ x509_cached_ok ( &leaf_crt );
+ x509_cached_ok ( &useless_crt );
+ x509_cached_ok ( &server_crt );
+ x509_cached_ok ( &not_ca_crt );
+ x509_cached_ok ( &bad_path_len_crt );
+
+ /* Check all certificate fingerprints */
+ x509_fingerprint_ok ( &root_crt );
+ x509_fingerprint_ok ( &intermediate_crt );
+ x509_fingerprint_ok ( &leaf_crt );
+ x509_fingerprint_ok ( &useless_crt );
+ x509_fingerprint_ok ( &server_crt );
+ x509_fingerprint_ok ( &not_ca_crt );
+ x509_fingerprint_ok ( &bad_path_len_crt );
+
+ /* Check pairwise issuing */
+ x509_check_issuer_ok ( &intermediate_crt, &root_crt );
+ x509_check_issuer_ok ( &leaf_crt, &intermediate_crt );
+ x509_check_issuer_ok ( &useless_crt, &leaf_crt );
+ x509_check_issuer_ok ( &server_crt, &leaf_crt );
+ x509_check_issuer_fail_ok ( &not_ca_crt, &server_crt );
+ x509_check_issuer_ok ( &bad_path_len_crt, &useless_crt );
+
+ /* Check root certificate stores */
+ x509_check_root_ok ( &root_crt, &test_root );
+ x509_check_root_fail_ok ( &intermediate_crt, &test_root );
+ x509_check_root_ok ( &intermediate_crt, &intermediate_root );
+ x509_check_root_fail_ok ( &root_crt, &intermediate_root );
+ x509_check_root_fail_ok ( &root_crt, &dummy_root );
+
+ /* Check certificate validity periods */
+ x509_check_time_ok ( &server_crt, test_time );
+ x509_check_time_fail_ok ( &server_crt, test_expired );
+ x509_check_time_ok ( &root_crt, test_time );
+ x509_check_time_ok ( &root_crt, test_expired );
+ x509_check_time_fail_ok ( &root_crt, test_ca_expired );
+
+ /* Parse all certificate chains */
+ x509_chain_ok ( &server_chain );
+ x509_chain_ok ( &broken_server_chain );
+ x509_chain_ok ( &incomplete_server_chain );
+ x509_chain_ok ( &not_ca_chain );
+ x509_chain_ok ( &useless_chain );
+ x509_chain_ok ( &bad_path_len_chain );
+
+ /* Check certificate chains */
+ x509_validate_chain_ok ( &server_chain, test_time, &test_root );
+ x509_validate_chain_ok ( &server_chain, test_time, &intermediate_root );
+ x509_validate_chain_fail_ok ( &server_chain, test_time, &dummy_root );
+ x509_validate_chain_fail_ok ( &broken_server_chain, test_time,
+ &test_root );
+ x509_validate_chain_fail_ok ( &incomplete_server_chain, test_time,
+ &test_root );
+ x509_validate_chain_ok ( &incomplete_server_chain, test_time,
+ &intermediate_root );
+ x509_validate_chain_fail_ok ( &not_ca_chain, test_time, &test_root );
+ x509_validate_chain_ok ( &useless_chain, test_time, &test_root );
+ x509_validate_chain_fail_ok ( &bad_path_len_chain, test_time,
+ &test_root );
+
+ /* Check certificate chain expiry times */
+ x509_validate_chain_fail_ok ( &server_chain, test_expired, &test_root );
+ x509_validate_chain_ok ( &useless_chain, test_expired, &test_root );
+ x509_validate_chain_fail_ok ( &useless_chain, test_ca_expired,
+ &test_root );
+
+ /* Drop chain references */
+ x509_chain_put ( bad_path_len_chain.chain );
+ x509_chain_put ( useless_chain.chain );
+ x509_chain_put ( not_ca_chain.chain );
+ x509_chain_put ( incomplete_server_chain.chain );
+ x509_chain_put ( broken_server_chain.chain );
+ x509_chain_put ( server_chain.chain );
+
+ /* Drop certificate references */
+ x509_put ( bad_path_len_crt.cert );
+ x509_put ( not_ca_crt.cert );
+ x509_put ( server_crt.cert );
+ x509_put ( useless_crt.cert );
+ x509_put ( leaf_crt.cert );
+ x509_put ( intermediate_crt.cert );
+ x509_put ( root_crt.cert );
+}
+
+/** X.509 self-test */
+struct self_test x509_test __self_test = {
+ .name = "x509",
+ .exec = x509_test_exec,
+};
+
+/* Drag in algorithms required for tests */
+REQUIRE_OBJECT ( rsa );
+REQUIRE_OBJECT ( sha1 );
+REQUIRE_OBJECT ( sha256 );
diff --git a/src/VBox/Devices/PC/ipxe/src/usr/autoboot.c b/src/VBox/Devices/PC/ipxe/src/usr/autoboot.c
new file mode 100644
index 00000000..31046c2f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/usr/autoboot.c
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/device.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/settings.h>
+#include <ipxe/image.h>
+#include <ipxe/sanboot.h>
+#include <ipxe/uri.h>
+#include <ipxe/open.h>
+#include <ipxe/init.h>
+#include <ipxe/pci.h>
+#include <ipxe/pci_io.h>
+#include <usr/ifmgmt.h>
+#include <usr/route.h>
+#include <usr/dhcpmgmt.h>
+#include <usr/imgmgmt.h>
+#include <usr/autoboot.h>
+
+/** @file
+ *
+ * Automatic booting
+ *
+ */
+
+/* Disambiguate the various error causes */
+#define ENOENT_BOOT __einfo_error ( EINFO_ENOENT_BOOT )
+#define EINFO_ENOENT_BOOT \
+ __einfo_uniqify ( EINFO_ENOENT, 0x01, "Nothing to boot" )
+
+/**
+ * Perform PXE menu boot when PXE stack is not available
+ */
+__weak int pxe_menu_boot ( struct net_device *netdev __unused ) {
+ return -ENOTSUP;
+}
+#ifndef VBOX
+/**
+ * Identify the boot network device
+ *
+ * @ret netdev Boot network device
+ */
+static struct net_device * find_boot_netdev ( void ) {
+ return NULL;
+}
+#endif
+
+/**
+ * Parse next-server and filename into a URI
+ *
+ * @v next_server Next-server address
+ * @v filename Filename
+ * @ret uri URI, or NULL on failure
+ */
+static struct uri * parse_next_server_and_filename ( struct in_addr next_server,
+ const char *filename ) {
+ char buf[ 23 /* "tftp://xxx.xxx.xxx.xxx/" */ + strlen ( filename )
+ + 1 /* NUL */ ];
+ struct uri *uri;
+
+ /* Parse filename */
+ uri = parse_uri ( filename );
+ if ( ! uri )
+ return NULL;
+
+ /* Construct a tftp:// URI for the filename, if applicable.
+ * We can't just rely on the current working URI, because the
+ * relative URI resolution will remove the distinction between
+ * filenames with and without initial slashes, which is
+ * significant for TFTP.
+ */
+ if ( next_server.s_addr && filename[0] && ! uri_is_absolute ( uri ) ) {
+ uri_put ( uri );
+ snprintf ( buf, sizeof ( buf ), "tftp://%s/%s",
+ inet_ntoa ( next_server ), filename );
+ uri = parse_uri ( buf );
+ if ( ! uri )
+ return NULL;
+ }
+
+ return uri;
+}
+
+/** The "keep-san" setting */
+struct setting keep_san_setting __setting ( SETTING_SANBOOT_EXTRA ) = {
+ .name = "keep-san",
+ .description = "Preserve SAN connection",
+ .tag = DHCP_EB_KEEP_SAN,
+ .type = &setting_type_int8,
+};
+
+/** The "skip-san-boot" setting */
+struct setting skip_san_boot_setting __setting ( SETTING_SANBOOT_EXTRA ) = {
+ .name = "skip-san-boot",
+ .description = "Do not boot from SAN device",
+ .tag = DHCP_EB_SKIP_SAN_BOOT,
+ .type = &setting_type_int8,
+};
+
+/**
+ * Boot from filename and root-path URIs
+ *
+ * @v filename Filename
+ * @v root_path Root path
+ * @v drive SAN drive (if applicable)
+ * @v flags Boot action flags
+ * @ret rc Return status code
+ *
+ * The somewhat tortuous flow of control in this function exists in
+ * order to ensure that the "sanboot" command remains identical in
+ * function to a SAN boot via a DHCP-specified root path, and to
+ * provide backwards compatibility for the "keep-san" and
+ * "skip-san-boot" options.
+ */
+int uriboot ( struct uri *filename, struct uri *root_path, int drive,
+ unsigned int flags ) {
+#ifdef VBOX
+ (void)root_path;
+ (void)drive;
+ (void)flags;
+#endif
+
+ struct image *image;
+ int rc;
+
+#ifndef VBOX
+ /* Hook SAN device, if applicable */
+ if ( root_path ) {
+ if ( ( rc = san_hook ( root_path, drive ) ) != 0 ) {
+ printf ( "Could not open SAN device: %s\n",
+ strerror ( rc ) );
+ goto err_san_hook;
+ }
+ printf ( "Registered SAN device %#02x\n", drive );
+ }
+
+ /* Describe SAN device, if applicable */
+ if ( ( drive >= 0 ) && ! ( flags & URIBOOT_NO_SAN_DESCRIBE ) ) {
+ if ( ( rc = san_describe ( drive ) ) != 0 ) {
+ printf ( "Could not describe SAN device %#02x: %s\n",
+ drive, strerror ( rc ) );
+ goto err_san_describe;
+ }
+ }
+#endif
+
+ /* Allow a root-path-only boot with skip-san enabled to succeed */
+ rc = 0;
+
+ /* Attempt filename boot if applicable */
+ if ( filename ) {
+ if ( ( rc = imgdownload ( filename, &image ) ) != 0 )
+ goto err_download;
+ if ( ( rc = image_exec ( image ) ) != 0 ) {
+ printf ( "Could not boot image: %s\n",
+ strerror ( rc ) );
+ /* Fall through to (possibly) attempt a SAN boot
+ * as a fallback. If no SAN boot is attempted,
+ * our status will become the return status.
+ */
+ } else {
+ /* Always print an extra newline, because we
+ * don't know where the NBP may have left the
+ * cursor.
+ */
+ printf ( "\n" );
+ }
+ }
+#ifndef VBOX
+ /* Attempt SAN boot if applicable */
+ if ( ( drive >= 0 ) && ! ( flags & URIBOOT_NO_SAN_BOOT ) ) {
+ if ( fetch_intz_setting ( NULL, &skip_san_boot_setting) == 0 ) {
+ printf ( "Booting from SAN device %#02x\n", drive );
+ rc = san_boot ( drive );
+ printf ( "Boot from SAN device %#02x failed: %s\n",
+ drive, strerror ( rc ) );
+ } else {
+ printf ( "Skipping boot from SAN device %#02x\n",
+ drive );
+ /* Avoid overwriting a possible failure status
+ * from a filename boot.
+ */
+ }
+ }
+
+ err_san_describe:
+ /* Unhook SAN device, if applicable */
+ if ( ( drive >= 0 ) && ! ( flags & URIBOOT_NO_SAN_UNHOOK ) ) {
+ if ( fetch_intz_setting ( NULL, &keep_san_setting ) == 0 ) {
+ san_unhook ( drive );
+ printf ( "Unregistered SAN device %#02x\n", drive );
+ } else {
+ printf ( "Preserving SAN device %#02x\n", drive );
+ }
+ }
+ err_san_hook:
+#endif
+ err_download:
+ return rc;
+}
+
+/**
+ * Close all open net devices
+ *
+ * Called before a fresh boot attempt in order to free up memory. We
+ * don't just close the device immediately after the boot fails,
+ * because there may still be TCP connections in the process of
+ * closing.
+ */
+static void close_all_netdevs ( void ) {
+ struct net_device *netdev;
+
+ for_each_netdev ( netdev ) {
+ ifclose ( netdev );
+ }
+}
+
+/**
+ * Fetch next-server and filename settings into a URI
+ *
+ * @v settings Settings block
+ * @ret uri URI, or NULL on failure
+ */
+struct uri * fetch_next_server_and_filename ( struct settings *settings ) {
+ struct in_addr next_server;
+ char buf[256];
+ char *filename;
+ struct uri *uri;
+
+ /* Fetch next-server setting */
+ fetch_ipv4_setting ( settings, &next_server_setting, &next_server );
+ if ( next_server.s_addr )
+ printf ( "Next server: %s\n", inet_ntoa ( next_server ) );
+
+ /* Fetch filename setting */
+ fetch_string_setting ( settings, &filename_setting,
+ buf, sizeof ( buf ) );
+ if ( buf[0] )
+ printf ( "Filename: %s\n", buf );
+
+ /* Expand filename setting */
+ filename = expand_settings ( buf );
+ if ( ! filename )
+ return NULL;
+
+ /* Parse next server and filename */
+ uri = parse_next_server_and_filename ( next_server, filename );
+
+ free ( filename );
+ return uri;
+}
+
+/**
+ * Fetch root-path setting into a URI
+ *
+ * @v settings Settings block
+ * @ret uri URI, or NULL on failure
+ */
+static struct uri * fetch_root_path ( struct settings *settings ) {
+ char buf[256];
+ char *root_path;
+ struct uri *uri;
+
+ /* Fetch root-path setting */
+ fetch_string_setting ( settings, &root_path_setting,
+ buf, sizeof ( buf ) );
+ if ( buf[0] )
+ printf ( "Root path: %s\n", buf );
+
+ /* Expand filename setting */
+ root_path = expand_settings ( buf );
+ if ( ! root_path )
+ return NULL;
+
+ /* Parse root path */
+ uri = parse_uri ( root_path );
+
+ free ( root_path );
+ return uri;
+}
+
+/**
+ * Check whether or not we have a usable PXE menu
+ *
+ * @ret have_menu A usable PXE menu is present
+ */
+static int have_pxe_menu ( void ) {
+ struct setting vendor_class_id_setting
+ = { .tag = DHCP_VENDOR_CLASS_ID };
+ struct setting pxe_discovery_control_setting
+ = { .tag = DHCP_PXE_DISCOVERY_CONTROL };
+ struct setting pxe_boot_menu_setting
+ = { .tag = DHCP_PXE_BOOT_MENU };
+ char buf[256];
+ unsigned int pxe_discovery_control;
+
+ fetch_string_setting ( NULL, &vendor_class_id_setting,
+ buf, sizeof ( buf ) );
+ pxe_discovery_control =
+ fetch_uintz_setting ( NULL, &pxe_discovery_control_setting );
+
+ return ( ( strcmp ( buf, "PXEClient" ) == 0 ) &&
+ setting_exists ( NULL, &pxe_boot_menu_setting ) &&
+ ( ! ( ( pxe_discovery_control & PXEBS_SKIP ) &&
+ setting_exists ( NULL, &filename_setting ) ) ) );
+}
+
+/**
+ * Boot from a network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+int netboot ( struct net_device *netdev ) {
+ struct uri *filename;
+ struct uri *root_path;
+ int rc;
+
+ /* Close all other network devices */
+ close_all_netdevs();
+
+ /* Open device and display device status */
+ if ( ( rc = ifopen ( netdev ) ) != 0 )
+ goto err_ifopen;
+ ifstat ( netdev );
+
+ /* Configure device via DHCP */
+ if ( ( rc = dhcp ( netdev ) ) != 0 )
+ goto err_dhcp;
+ route();
+
+ /* Try PXE menu boot, if applicable */
+ if ( have_pxe_menu() ) {
+ printf ( "Booting from PXE menu\n" );
+ rc = pxe_menu_boot ( netdev );
+ goto err_pxe_menu_boot;
+ }
+
+ /* Fetch next server and filename */
+ filename = fetch_next_server_and_filename ( NULL );
+ if ( ! filename )
+ goto err_filename;
+ if ( ! uri_has_path ( filename ) ) {
+ /* Ignore empty filename */
+ uri_put ( filename );
+ filename = NULL;
+ }
+
+ /* Fetch root path */
+ root_path = fetch_root_path ( NULL );
+ if ( ! root_path )
+ goto err_root_path;
+ if ( ! uri_is_absolute ( root_path ) ) {
+ /* Ignore empty root path */
+ uri_put ( root_path );
+ root_path = NULL;
+ }
+
+ /* If we have both a filename and a root path, ignore an
+ * unsupported URI scheme in the root path, since it may
+ * represent an NFS root.
+ */
+ if ( filename && root_path &&
+ ( xfer_uri_opener ( root_path->scheme ) == NULL ) ) {
+ printf ( "Ignoring unsupported root path\n" );
+ uri_put ( root_path );
+ root_path = NULL;
+ }
+
+ /* Check that we have something to boot */
+ if ( ! ( filename || root_path ) ) {
+ rc = -ENOENT_BOOT;
+ printf ( "Nothing to boot: %s\n", strerror ( rc ) );
+ goto err_no_boot;
+ }
+#ifndef VBOX
+ /* Boot using next server, filename and root path */
+ if ( ( rc = uriboot ( filename, root_path, san_default_drive(),
+ ( root_path ? 0 : URIBOOT_NO_SAN ) ) ) != 0 )
+#else
+ /* Boot using next server, filename and root path. Defaults is Harddrive */
+ if ( ( rc = uriboot ( filename, root_path, 0x80,
+ ( root_path ? 0 : URIBOOT_NO_SAN ) ) ) != 0 )
+#endif
+ goto err_uriboot;
+
+ err_uriboot:
+ err_no_boot:
+ uri_put ( root_path );
+ err_root_path:
+ uri_put ( filename );
+ err_filename:
+ err_pxe_menu_boot:
+ err_dhcp:
+ err_ifopen:
+ return rc;
+}
+
+/**
+ * Boot the system
+ */
+int autoboot ( void ) {
+ struct net_device *boot_netdev = NULL;
+#ifndef VBOX
+ struct net_device *netdev;
+#endif
+ int rc = -ENODEV;
+ int nic_index = 0;
+ uint16_t busdevfn;
+
+#ifdef VBOX
+ for (nic_index = 0; nic_index < NET_BOOT_NICS; nic_index++)
+ {
+ busdevfn = cmos2_read(2 + nic_index * 2);
+ busdevfn |= cmos2_read(3 + nic_index * 2) << 8;
+ if (busdevfn != 0xffff && busdevfn != 0)
+ {
+ boot_netdev = find_netdev_by_location(BUS_TYPE_PCI, busdevfn);
+ if (boot_netdev != NULL)
+ {
+ rc = netboot(boot_netdev);
+ }
+ }
+ }
+#else
+ /* If we have an identifable boot device, try that first */
+ if ( ( boot_netdev = find_boot_netdev() ) )
+ rc = netboot ( boot_netdev );
+
+ /* If that fails, try booting from any of the other devices */
+ for_each_netdev ( netdev ) {
+ if ( netdev == boot_netdev )
+ continue;
+ rc = netboot ( netdev );
+ }
+#endif
+
+ printf ( "No more network devices\n" );
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/usr/dhcpmgmt.c b/src/VBox/Devices/PC/ipxe/src/usr/dhcpmgmt.c
new file mode 100644
index 00000000..e651dfda
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/usr/dhcpmgmt.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/monojob.h>
+#include <ipxe/process.h>
+#include <usr/ifmgmt.h>
+#include <usr/dhcpmgmt.h>
+
+#define LINK_WAIT_MS 15000
+
+/** @file
+ *
+ * DHCP management
+ *
+ */
+
+int dhcp ( struct net_device *netdev ) {
+ struct dhcphdr *dhcphdr;
+ typeof ( dhcphdr->chaddr ) chaddr;
+ unsigned int hlen;
+ unsigned int i;
+ int rc;
+
+ /* Check we can open the interface first */
+ if ( ( rc = ifopen ( netdev ) ) != 0 )
+ return rc;
+
+ /* Wait for link-up */
+ if ( ( rc = iflinkwait ( netdev, LINK_WAIT_MS ) ) != 0 )
+ return rc;
+
+ /* Perform DHCP */
+ printf ( "DHCP (%s", netdev->name );
+ hlen = dhcp_chaddr ( netdev, chaddr, NULL );
+ for ( i = 0 ; i < hlen ; i++ )
+ printf ( "%c%02x", ( i ? ':' : ' ' ), chaddr[i] );
+ printf ( ")" );
+
+ if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 ) {
+ rc = monojob_wait ( "" );
+ } else if ( rc > 0 ) {
+ printf ( " using cached\n" );
+ rc = 0;
+ }
+
+ return rc;
+}
+
+int pxebs ( struct net_device *netdev, unsigned int pxe_type ) {
+ int rc;
+
+ /* Perform PXE Boot Server Discovery */
+ printf ( "PXEBS (%s type %d)", netdev->name, pxe_type );
+ if ( ( rc = start_pxebs ( &monojob, netdev, pxe_type ) ) == 0 )
+ rc = monojob_wait ( "" );
+
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/usr/fcmgmt.c b/src/VBox/Devices/PC/ipxe/src/usr/fcmgmt.c
new file mode 100644
index 00000000..f46c7d6b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/usr/fcmgmt.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/fc.h>
+#include <ipxe/fcels.h>
+#include <ipxe/monojob.h>
+#include <usr/fcmgmt.h>
+
+/** @file
+ *
+ * Fibre Channel management
+ *
+ */
+
+/**
+ * Print status of Fibre Channel port
+ *
+ * @v port Fibre Channel port
+ */
+void fcportstat ( struct fc_port *port ) {
+ printf ( "%s: %s id %s", port->name, fc_ntoa ( &port->port_wwn ),
+ fc_id_ntoa ( &port->port_id ) );
+ printf ( " node %s\n [Link:", fc_ntoa ( &port->node_wwn ) );
+ if ( fc_link_ok ( &port->link ) ) {
+ printf ( " up, %s", fc_ntoa ( &port->link_port_wwn ) );
+ if ( ( port->flags & FC_PORT_HAS_FABRIC ) ) {
+ printf ( " fabric" );
+ } else {
+ printf ( " id %s",
+ fc_id_ntoa ( &port->ptp_link_port_id ) );
+ }
+ printf ( " node %s]\n", fc_ntoa ( &port->link_node_wwn ) );
+ } else {
+ printf ( " down: %s]\n", strerror ( port->link.rc ) );
+ }
+}
+
+/**
+ * Print status of Fibre Channel peer
+ *
+ * @v peer Fibre Channel peer
+ */
+void fcpeerstat ( struct fc_peer *peer ) {
+ struct fc_ulp *ulp;
+ uint8_t *param;
+ unsigned int i;
+
+ printf ( "%s:\n [Link:", fc_ntoa ( &peer->port_wwn ) );
+ if ( fc_link_ok ( &peer->link ) ) {
+ printf ( " up, port %s id %s]\n", peer->port->name,
+ fc_id_ntoa ( &peer->port_id ) );
+ } else {
+ printf ( " down: %s]\n", strerror ( peer->link.rc ) );
+ }
+
+ list_for_each_entry ( ulp, &peer->ulps, list ) {
+ printf ( " [Type %02x link:", ulp->type );
+ if ( fc_link_ok ( &ulp->link ) ) {
+ printf ( " up, params" );
+ param = ulp->param;
+ for ( i = 0 ; i < ulp->param_len ; i++ ) {
+ printf ( "%c%02x", ( ( i == 0 ) ? ' ' : ':' ),
+ param[i] );
+ }
+ } else {
+ printf ( " down: %s", strerror ( ulp->link.rc ) );
+ }
+ printf ( "]\n" );
+ }
+}
+
+/**
+ * Issue Fibre Channel ELS
+ *
+ * @v port Fibre Channel port
+ * @v peer_port_id Peer port ID
+ * @v handler ELS handler
+ * @ret rc Return status code
+ */
+int fcels ( struct fc_port *port, struct fc_port_id *peer_port_id,
+ struct fc_els_handler *handler ) {
+ int rc;
+
+ /* Initiate ELS */
+ printf ( "%s %s to %s...",
+ port->name, handler->name, fc_id_ntoa ( peer_port_id ) );
+ if ( ( rc = fc_els_request ( &monojob, port, peer_port_id,
+ handler ) ) != 0 ) {
+ printf ( "%s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ /* Wait for ELS to complete */
+ return monojob_wait ( "" );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/usr/ifmgmt.c b/src/VBox/Devices/PC/ipxe/src/usr/ifmgmt.c
new file mode 100644
index 00000000..8ee311c0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/usr/ifmgmt.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ipxe/console.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/device.h>
+#include <ipxe/process.h>
+#include <ipxe/keys.h>
+#include <usr/ifmgmt.h>
+
+/** @file
+ *
+ * Network interface management
+ *
+ */
+
+/**
+ * Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+int ifopen ( struct net_device *netdev ) {
+ int rc;
+
+ if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
+ printf ( "Could not open %s: %s\n",
+ netdev->name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Close network device
+ *
+ * @v netdev Network device
+ */
+void ifclose ( struct net_device *netdev ) {
+ netdev_close ( netdev );
+}
+
+/**
+ * Print network device error breakdown
+ *
+ * @v stats Network device statistics
+ * @v prefix Message prefix
+ */
+static void ifstat_errors ( struct net_device_stats *stats,
+ const char *prefix ) {
+ unsigned int i;
+
+ for ( i = 0 ; i < ( sizeof ( stats->errors ) /
+ sizeof ( stats->errors[0] ) ) ; i++ ) {
+ if ( stats->errors[i].count )
+ printf ( " [%s: %d x \"%s\"]\n", prefix,
+ stats->errors[i].count,
+ strerror ( stats->errors[i].rc ) );
+ }
+}
+
+/**
+ * Print status of network device
+ *
+ * @v netdev Network device
+ */
+void ifstat ( struct net_device *netdev ) {
+ printf ( "%s: %s using %s on %s (%s)\n"
+ " [Link:%s, TX:%d TXE:%d RX:%d RXE:%d]\n",
+ netdev->name, netdev_addr ( netdev ),
+ netdev->dev->driver_name, netdev->dev->name,
+ ( netdev_is_open ( netdev ) ? "open" : "closed" ),
+ ( netdev_link_ok ( netdev ) ? "up" : "down" ),
+ netdev->tx_stats.good, netdev->tx_stats.bad,
+ netdev->rx_stats.good, netdev->rx_stats.bad );
+ if ( ! netdev_link_ok ( netdev ) ) {
+ printf ( " [Link status: %s]\n",
+ strerror ( netdev->link_rc ) );
+ }
+ ifstat_errors ( &netdev->tx_stats, "TXE" );
+ ifstat_errors ( &netdev->rx_stats, "RXE" );
+}
+
+/**
+ * Wait for link-up, with status indication
+ *
+ * @v netdev Network device
+ * @v max_wait_ms Maximum time to wait, in ms
+ */
+int iflinkwait ( struct net_device *netdev, unsigned int max_wait_ms ) {
+ int key;
+ int rc;
+
+ /* Allow link state to be updated */
+ netdev_poll ( netdev );
+
+ if ( netdev_link_ok ( netdev ) )
+ return 0;
+
+ printf ( "Waiting for link-up on %s...", netdev->name );
+
+ while ( 1 ) {
+ if ( netdev_link_ok ( netdev ) ) {
+ rc = 0;
+ break;
+ }
+ if ( max_wait_ms-- == 0 ) {
+ rc = netdev->link_rc;
+ break;
+ }
+ step();
+ if ( iskey() ) {
+ key = getchar();
+ if ( key == CTRL_C ) {
+ rc = -ECANCELED;
+ break;
+ }
+ }
+ mdelay ( 1 );
+ }
+
+ if ( rc == 0 ) {
+ printf ( " ok\n" );
+ } else {
+ printf ( " failed: %s\n", strerror ( rc ) );
+ }
+
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/usr/imgmgmt.c b/src/VBox/Devices/PC/ipxe/src/usr/imgmgmt.c
new file mode 100644
index 00000000..2c74f486
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/usr/imgmgmt.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ipxe/image.h>
+#include <ipxe/downloader.h>
+#include <ipxe/monojob.h>
+#include <ipxe/open.h>
+#include <ipxe/uri.h>
+#include <usr/imgmgmt.h>
+
+/** @file
+ *
+ * Image management
+ *
+ */
+
+/**
+ * Download a new image
+ *
+ * @v uri URI
+ * @v image Image to fill in
+ * @ret rc Return status code
+ */
+int imgdownload ( struct uri *uri, struct image **image ) {
+ size_t len = ( unparse_uri ( NULL, 0, uri, URI_ALL ) + 1 );
+ char uri_string_redacted[len];
+ const char *password;
+ int rc;
+
+ /* Allocate image */
+ *image = alloc_image ( uri );
+ if ( ! *image ) {
+ rc = -ENOMEM;
+ goto err_alloc_image;
+ }
+
+ /* Redact password portion of URI, if necessary */
+ password = uri->password;
+ if ( password )
+ uri->password = "***";
+ unparse_uri ( uri_string_redacted, sizeof ( uri_string_redacted ),
+ uri, URI_ALL );
+ uri->password = password;
+
+ /* Create downloader */
+ if ( ( rc = create_downloader ( &monojob, *image, LOCATION_URI,
+ uri ) ) != 0 ) {
+ printf ( "Could not start download: %s\n", strerror ( rc ) );
+ goto err_create_downloader;
+ }
+
+ /* Wait for download to complete */
+ if ( ( rc = monojob_wait ( uri_string_redacted ) ) != 0 )
+ goto err_monojob_wait;
+
+ /* Register image */
+ if ( ( rc = register_image ( *image ) ) != 0 ) {
+ printf ( "Could not register image: %s\n", strerror ( rc ) );
+ goto err_register_image;
+ }
+
+ /* Drop local reference to image. Image is guaranteed to
+ * remain in scope since it is registered.
+ */
+ image_put ( *image );
+
+ return 0;
+
+ err_register_image:
+ err_monojob_wait:
+ err_create_downloader:
+ image_put ( *image );
+ err_alloc_image:
+ return rc;
+}
+
+/**
+ * Download a new image
+ *
+ * @v uri_string URI string
+ * @v image Image to fill in
+ * @ret rc Return status code
+ */
+int imgdownload_string ( const char *uri_string, struct image **image ) {
+ struct uri *uri;
+ int rc;
+
+ if ( ! ( uri = parse_uri ( uri_string ) ) )
+ return -ENOMEM;
+
+ rc = imgdownload ( uri, image );
+
+ uri_put ( uri );
+ return rc;
+}
+
+/**
+ * Acquire an image
+ *
+ * @v name_uri Name or URI string
+ * @v image Image to fill in
+ * @ret rc Return status code
+ */
+int imgacquire ( const char *name_uri, struct image **image ) {
+
+ /* If we already have an image with the specified name, use it */
+ *image = find_image ( name_uri );
+ if ( *image )
+ return 0;
+
+ /* Otherwise, download a new image */
+ return imgdownload_string ( name_uri, image );
+}
+
+/**
+ * Display status of an image
+ *
+ * @v image Executable/loadable image
+ */
+void imgstat ( struct image *image ) {
+ printf ( "%s : %zd bytes", image->name, image->len );
+ if ( image->type )
+ printf ( " [%s]", image->type->name );
+ if ( image->flags & IMAGE_TRUSTED )
+ printf ( " [TRUSTED]" );
+ if ( image->flags & IMAGE_SELECTED )
+ printf ( " [SELECTED]" );
+ if ( image->cmdline )
+ printf ( " \"%s\"", image->cmdline );
+ printf ( "\n" );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/usr/imgtrust.c b/src/VBox/Devices/PC/ipxe/src/usr/imgtrust.c
new file mode 100644
index 00000000..651f0493
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/usr/imgtrust.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <syslog.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/image.h>
+#include <ipxe/cms.h>
+#include <usr/imgtrust.h>
+
+/** @file
+ *
+ * Image trust management
+ *
+ */
+
+/**
+ * Verify image using downloaded signature
+ *
+ * @v image Image to verify
+ * @v signature Image containing signature
+ * @v name Required common name, or NULL to allow any name
+ * @ret rc Return status code
+ */
+int imgverify ( struct image *image, struct image *signature,
+ const char *name ) {
+ size_t len;
+ void *data;
+ struct cms_signature *sig;
+ time_t now;
+ int rc;
+
+ /* Mark image as untrusted */
+ image_untrust ( image );
+
+ /* Copy signature to internal memory */
+ len = signature->len;
+ data = malloc ( len );
+ if ( ! data ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ copy_from_user ( data, signature->data, 0, len );
+
+ /* Parse signature */
+ if ( ( rc = cms_signature ( data, len, &sig ) ) != 0 )
+ goto err_parse;
+
+ /* Free internal copy of signature */
+ free ( data );
+ data = NULL;
+
+ /* Use signature to verify image */
+ now = time ( NULL );
+ if ( ( rc = cms_verify ( sig, image->data, image->len,
+ name, now, NULL ) ) != 0 )
+ goto err_verify;
+
+ /* Drop reference to signature */
+ cms_put ( sig );
+ sig = NULL;
+
+ /* Mark image as trusted */
+ image_trust ( image );
+ syslog ( LOG_NOTICE, "Image \"%s\" signature OK\n", image->name );
+
+ return 0;
+
+ err_verify:
+ cms_put ( sig );
+ err_parse:
+ free ( data );
+ err_alloc:
+ syslog ( LOG_ERR, "Image \"%s\" signature bad: %s\n",
+ image->name, strerror ( rc ) );
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/usr/iwmgmt.c b/src/VBox/Devices/PC/ipxe/src/usr/iwmgmt.c
new file mode 100644
index 00000000..abcd63f4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/usr/iwmgmt.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/net80211.h>
+#include <ipxe/ethernet.h>
+#include <usr/ifmgmt.h>
+#include <usr/iwmgmt.h>
+
+/** @file
+ *
+ * Wireless network interface management
+ *
+ */
+
+/**
+ * Print status of 802.11 device
+ *
+ * @v dev 802.11 device
+ */
+void iwstat ( struct net80211_device *dev ) {
+
+ ifstat ( dev->netdev );
+
+ printf ( " [802.11 ");
+ if ( dev->state & NET80211_ASSOCIATED ) {
+ printf ( "SSID '%s', ", dev->essid );
+ } else {
+ printf ( "not associated, " );
+ }
+ if ( dev->channel < dev->nr_channels && dev->rate < dev->nr_rates ) {
+ printf ( "Ch:%d Sig:%d", dev->channels[dev->channel].channel_nr,
+ dev->last_signal );
+ switch ( dev->hw->signal_type ) {
+ case NET80211_SIGNAL_NONE:
+ printf ( "?" );
+ break;
+ case NET80211_SIGNAL_ARBITRARY:
+ printf ( "/%d", dev->hw->signal_max );
+ break;
+ case NET80211_SIGNAL_DB:
+ printf ( "/%d dB", dev->hw->signal_max );
+ break;
+ case NET80211_SIGNAL_DBM:
+ printf ( " dBm" );
+ break;
+ }
+ printf ( ", Qual:%d%% Rate:%d Mbps]\n",
+ ( dev->rx_beacon_interval == 0 ? 0 :
+ 100 * dev->tx_beacon_interval /
+ dev->rx_beacon_interval ),
+ dev->rates[dev->rate] / 10 );
+ } else {
+ printf ( "antenna off]\n" );
+ }
+
+ if ( dev->state & NET80211_WORKING ) {
+ printf ( " [associating" );
+ if ( dev->associating )
+ printf ( " to '%s'", dev->associating->essid );
+ printf ( "...]\n" );
+ }
+}
+
+/** Identifiers for 802.11 cryptography types, indexed by type number */
+static const char *crypto_types[] = {
+ [NET80211_CRYPT_NONE] = "Open",
+ [NET80211_CRYPT_WEP] = "WEP ",
+ [NET80211_CRYPT_TKIP] = "WPA ",
+ [NET80211_CRYPT_CCMP] = "WPA2",
+ [NET80211_CRYPT_UNKNOWN] = "UNK ",
+};
+
+/** Number of 802.11 cryptography types defined */
+#define NR_CRYPTO_TYPES ( sizeof ( crypto_types ) / sizeof ( crypto_types[0] ) )
+
+/** Identifiers for 802.11 authentication types, indexed by type number */
+static const char *auth_types[] = {
+ [NET80211_SECPROT_NONE] = "",
+ [NET80211_SECPROT_PSK] = "PSK",
+ [NET80211_SECPROT_EAP] = "802.1X",
+ [NET80211_SECPROT_UNKNOWN] = "UNK",
+};
+
+/** Number of 802.11 authentication types defined */
+#define NR_AUTH_TYPES ( sizeof ( auth_types ) / sizeof ( auth_types[0] ) )
+
+/**
+ * Scan for wireless networks using 802.11 device
+ *
+ * @v dev 802.11 device
+ * @v active Whether to use active scanning
+ *
+ * The list of networks found will be printed in tabular format.
+ *
+ * This function is safe to call at all times, whether the 802.11
+ * device is open or not, but if called while the auto-association
+ * task is running it will return an error indication.
+ */
+int iwlist ( struct net80211_device *dev ) {
+ struct net80211_probe_ctx *ctx;
+ struct list_head *networks;
+ struct net80211_wlan *wlan;
+ char ssid_buf[22];
+ int rc;
+ unsigned i;
+ int was_opened = netdev_is_open ( dev->netdev );
+ int was_channel = dev->channels[dev->channel].channel_nr;
+
+ if ( ! was_opened ) {
+ dev->state |= NET80211_NO_ASSOC;
+ rc = netdev_open ( dev->netdev );
+ if ( rc < 0 )
+ goto err;
+ }
+
+ if ( dev->state & NET80211_WORKING ) {
+ rc = -EINVAL;
+ goto err_close_netdev;
+ }
+
+ if ( ! was_opened ) {
+ rc = net80211_prepare_probe ( dev, dev->hw->bands, 0 );
+ if ( rc < 0 )
+ goto err_close_netdev;
+ }
+
+ ctx = net80211_probe_start ( dev, "", 0 );
+ if ( ! ctx ) {
+ rc = -ENOMEM;
+ goto err_close_netdev;
+ }
+
+ while ( ! ( rc = net80211_probe_step ( ctx ) ) ) {
+ step();
+ }
+
+ networks = net80211_probe_finish_all ( ctx );
+
+ if ( list_empty ( networks ) ) {
+ goto err_free_networks;
+ }
+
+ rc = 0;
+
+ printf ( "Networks on %s:\n\n", dev->netdev->name );
+
+ /* Output format:
+ * 0 1 2 3 4 5 6
+ * 0123456789012345678901234567890123456789012345678901234567890
+ * [Sig] SSID BSSID Ch Crypt/Auth
+ * -------------------------------------------------------------
+ * [ 15] abcdefghijklmnopqrst> 00:00:00:00:00:00 11 Open
+ * ... or WPA PSK etc.
+ */
+
+ /* Quoting the dashes and spaces verbatim uses less code space
+ than generating them programmatically. */
+ printf ( "[Sig] SSID BSSID Ch Crypt/Auth\n"
+ "-------------------------------------------------------------\n" );
+
+ list_for_each_entry ( wlan, networks, list ) {
+
+ /* Format SSID into 22-character string, space-padded,
+ with '>' indicating truncation */
+
+ snprintf ( ssid_buf, sizeof ( ssid_buf ), "%s", wlan->essid );
+ for ( i = strlen ( ssid_buf ); i < sizeof ( ssid_buf ) - 1;
+ i++ )
+ ssid_buf[i] = ' ';
+ if ( ssid_buf[sizeof ( ssid_buf ) - 2] != ' ' )
+ ssid_buf[sizeof ( ssid_buf ) - 2] = '>';
+ ssid_buf[sizeof ( ssid_buf ) - 1] = 0;
+
+ /* Sanity check */
+ if ( wlan->crypto >= NR_CRYPTO_TYPES ||
+ wlan->handshaking >= NR_AUTH_TYPES )
+ continue;
+
+ printf ( "[%3d] %s %s %2d %s %s\n",
+ wlan->signal < 0 ? 100 + wlan->signal : wlan->signal,
+ ssid_buf, eth_ntoa ( wlan->bssid ), wlan->channel,
+ crypto_types[wlan->crypto],
+ auth_types[wlan->handshaking] );
+ }
+ printf ( "\n" );
+
+ err_free_networks:
+ net80211_free_wlanlist ( networks );
+
+ err_close_netdev:
+ if ( ! was_opened ) {
+ dev->state &= ~NET80211_NO_ASSOC;
+ netdev_close ( dev->netdev );
+ } else {
+ net80211_change_channel ( dev, was_channel );
+ }
+
+ if ( ! rc )
+ return 0;
+
+ err:
+ printf ( "Scanning for networks on %s: %s\n",
+ dev->netdev->name, strerror ( rc ) );
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/usr/lotest.c b/src/VBox/Devices/PC/ipxe/src/usr/lotest.c
new file mode 100644
index 00000000..52525261
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/usr/lotest.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/keys.h>
+#include <ipxe/console.h>
+#include <usr/ifmgmt.h>
+#include <usr/lotest.h>
+
+/** @file
+ *
+ * Loopback testing
+ *
+ */
+
+#define LINK_WAIT_MS 15000
+
+/**
+ * Process received packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer source address
+ * @v flags Packet flags
+ * @ret rc Return status code
+ */
+static int lotest_rx ( struct io_buffer *iobuf,
+ struct net_device *netdev __unused,
+ const void *ll_dest __unused,
+ const void *ll_source __unused,
+ unsigned int flags __unused ) {
+ free_iob ( iobuf );
+ return -ENOTSUP;
+}
+
+/**
+ * Transcribe network-layer address
+ *
+ * @v net_addr Network-layer address
+ * @ret string Human-readable transcription of address
+ */
+static const char * lotest_ntoa ( const void *net_addr __unused ) {
+ return "<INVALID>";
+}
+
+/**
+ * Loopback test network-layer protocol
+ *
+ * Using a dedicated network-layer protocol avoids problems caused by
+ * cards supporting features such as IPv4 checksum offload trying to
+ * interpret the (randomly generated) network-layer content.
+ */
+static struct net_protocol lotest_protocol __net_protocol = {
+ .name = "LOTEST",
+ .rx = lotest_rx,
+ .ntoa = lotest_ntoa,
+ .net_proto = htons ( 0x6950 ), /* Not a genuine protocol number */
+ .net_addr_len = 0,
+};
+
+/**
+ * Wait for packet to be received
+ *
+ * @v receiver Receiving network device*
+ * @v data Expected data
+ * @v len Expected data length
+ * @ret rc Return status code
+ */
+static int loopback_wait ( struct net_device *receiver, void *data,
+ size_t len ) {
+ struct ll_protocol *ll_protocol = receiver->ll_protocol;
+ struct io_buffer *iobuf;
+ const void *ll_dest;
+ const void *ll_source;
+ uint16_t net_proto;
+ unsigned int flags;
+ int rc;
+
+ /* Poll until packet arrives */
+ while ( 1 ) {
+
+ /* Check for cancellation */
+ if ( iskey() && ( getchar() == CTRL_C ) )
+ return -ECANCELED;
+
+ /* Poll network devices */
+ net_poll();
+
+ /* Dequeue packet, if available */
+ iobuf = netdev_rx_dequeue ( receiver );
+ if ( ! iobuf )
+ continue;
+
+ /* Strip link-layer header */
+ if ( ( rc = ll_protocol->pull ( receiver, iobuf, &ll_dest,
+ &ll_source, &net_proto,
+ &flags ) ) != 0 ) {
+ printf ( "\nFailed to strip link-layer header: %s",
+ strerror ( rc ) );
+ free_iob ( iob_disown ( iobuf ) );
+ return rc;
+ }
+
+ /* Ignore non-loopback packets */
+ if ( net_proto != lotest_protocol.net_proto ) {
+ printf ( "\nReceived spurious packet type %04x\n",
+ ntohs ( net_proto ) );
+ free_iob ( iob_disown ( iobuf ) );
+ continue;
+ }
+
+ /* Check packet length */
+ if ( iob_len ( iobuf ) != len ) {
+ printf ( "\nLength mismatch: sent %zd, received %zd",
+ len, iob_len ( iobuf ) );
+ DBG ( "\nSent:\n" );
+ DBG_HDA ( 0, data, len );
+ DBG ( "Received:\n" );
+ DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) );
+ free_iob ( iob_disown ( iobuf ) );
+ return -EINVAL;
+ }
+
+ /* Check packet content */
+ if ( memcmp ( iobuf->data, data, len ) != 0 ) {
+ printf ( "\nContent mismatch" );
+ DBG ( "\nSent:\n" );
+ DBG_HDA ( 0, data, len );
+ DBG ( "Received:\n" );
+ DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) );
+ free_iob ( iob_disown ( iobuf ) );
+ return -EINVAL;
+ }
+
+ /* Discard packet and return */
+ free_iob ( iob_disown ( iobuf ) );
+ return 0;
+ }
+}
+
+/**
+ * Perform loopback test between two network devices
+ *
+ * @v sender Sending network device
+ * @v receiver Received network device
+ * @v mtu Packet size (excluding link-layer headers)
+ * @ret rc Return status code
+ */
+int loopback_test ( struct net_device *sender, struct net_device *receiver,
+ size_t mtu ) {
+ uint8_t buf[mtu];
+ struct io_buffer *iobuf;
+ unsigned int i;
+ unsigned int successes;
+ int rc;
+
+ /* Open network devices */
+ if ( ( rc = ifopen ( sender ) ) != 0 )
+ return rc;
+ if ( ( rc = ifopen ( receiver ) ) != 0 )
+ return rc;
+
+ /* Wait for link-up */
+ if ( ( rc = iflinkwait ( sender, LINK_WAIT_MS ) ) != 0 )
+ return rc;
+ if ( ( rc = iflinkwait ( receiver, LINK_WAIT_MS ) ) != 0 )
+ return rc;
+
+ /* Print initial statistics */
+ printf ( "Performing loopback test from %s to %s with %zd byte MTU\n",
+ sender->name, receiver->name, mtu );
+ ifstat ( sender );
+ ifstat ( receiver );
+
+ /* Freeze receive queue processing on the receiver, so that we
+ * can extract all received packets.
+ */
+ netdev_rx_freeze ( receiver );
+
+ /* Perform loopback test */
+ for ( successes = 0 ; ; successes++ ) {
+
+ /* Print running total */
+ printf ( "\r%d", successes );
+
+ /* Generate random packet */
+ for ( i = 0 ; i < sizeof ( buf ) ; i++ )
+ buf[i] = random();
+ iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( buf ) );
+ if ( ! iobuf ) {
+ printf ( "\nFailed to allocate I/O buffer" );
+ rc = -ENOMEM;
+ break;
+ }
+ iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
+ memcpy ( iob_put ( iobuf, sizeof ( buf ) ),
+ buf, sizeof ( buf ) );
+
+ /* Transmit packet */
+ if ( ( rc = net_tx ( iob_disown ( iobuf ), sender,
+ &lotest_protocol, receiver->ll_addr,
+ sender->ll_addr ) ) != 0 ) {
+ printf ( "\nFailed to transmit packet: %s",
+ strerror ( rc ) );
+ break;
+ }
+
+ /* Wait for received packet */
+ if ( ( rc = loopback_wait ( receiver, buf,
+ sizeof ( buf ) ) ) != 0 ) {
+ break;
+ }
+ }
+
+ printf ( "\n");
+ netdev_rx_unfreeze ( receiver );
+
+ /* Dump final statistics */
+ ifstat ( sender );
+ ifstat ( receiver );
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/usr/prompt.c b/src/VBox/Devices/PC/ipxe/src/usr/prompt.c
new file mode 100644
index 00000000..3c353a68
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/usr/prompt.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Prompt for keypress
+ *
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <ipxe/console.h>
+#include <ipxe/timer.h>
+#include <usr/prompt.h>
+
+/**
+ * Prompt for keypress
+ *
+ * @v text Prompt string
+ * @v wait_ms Time to wait, in milliseconds (0=indefinite)
+ * @v key Key to wait for (0=any key)
+ * @ret rc Return status code
+ *
+ * Returns success if the specified key was pressed within the
+ * specified timeout period.
+ */
+int prompt ( const char *text, unsigned int wait_ms, int key ) {
+ int key_pressed;
+
+ /* Display prompt */
+ printf ( "%s", text );
+
+ /* Wait for key */
+ key_pressed = getkey ( ( wait_ms * TICKS_PER_SEC ) / 1000 );
+
+ /* Clear the prompt line */
+ while ( *(text++) )
+ printf ( "\b \b" );
+
+ /* Check for timeout */
+ if ( key_pressed < 0 )
+ return -ETIMEDOUT;
+
+ /* Check for correct key pressed */
+ if ( key && ( key_pressed != key ) )
+ return -ECANCELED;
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/usr/pxemenu.c b/src/VBox/Devices/PC/ipxe/src/usr/pxemenu.c
new file mode 100644
index 00000000..bc176563
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/usr/pxemenu.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <byteswap.h>
+#include <curses.h>
+#include <ipxe/console.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/keys.h>
+#include <ipxe/timer.h>
+#include <ipxe/uri.h>
+#include <usr/dhcpmgmt.h>
+#include <usr/autoboot.h>
+
+/** @file
+ *
+ * PXE Boot Menus
+ *
+ */
+
+/* Colour pairs */
+#define CPAIR_NORMAL 1
+#define CPAIR_SELECT 2
+
+/** A PXE boot menu item */
+struct pxe_menu_item {
+ /** Boot Server type */
+ unsigned int type;
+ /** Description */
+ char *desc;
+};
+
+/**
+ * A PXE boot menu
+ *
+ * This structure encapsulates the menu information provided via DHCP
+ * options.
+ */
+struct pxe_menu {
+ /** Prompt string (optional) */
+ const char *prompt;
+ /** Timeout (in seconds)
+ *
+ * Negative indicates no timeout (i.e. wait indefinitely)
+ */
+ int timeout;
+ /** Number of menu items */
+ unsigned int num_items;
+ /** Selected menu item */
+ unsigned int selection;
+ /** Menu items */
+ struct pxe_menu_item items[0];
+};
+
+/**
+ * Parse and allocate PXE boot menu
+ *
+ * @v menu PXE boot menu to fill in
+ * @ret rc Return status code
+ *
+ * It is the callers responsibility to eventually free the allocated
+ * boot menu.
+ */
+static int pxe_menu_parse ( struct pxe_menu **menu ) {
+ struct setting pxe_boot_menu_prompt_setting =
+ { .tag = DHCP_PXE_BOOT_MENU_PROMPT };
+ struct setting pxe_boot_menu_setting =
+ { .tag = DHCP_PXE_BOOT_MENU };
+ uint8_t raw_menu[256];
+ int raw_prompt_len;
+ int raw_menu_len;
+ struct dhcp_pxe_boot_menu *raw_menu_item;
+ struct dhcp_pxe_boot_menu_prompt *raw_menu_prompt;
+ void *raw_menu_end;
+ unsigned int num_menu_items;
+ unsigned int i;
+ int rc;
+
+ /* Fetch raw menu */
+ memset ( raw_menu, 0, sizeof ( raw_menu ) );
+ if ( ( raw_menu_len = fetch_setting ( NULL, &pxe_boot_menu_setting,
+ raw_menu,
+ sizeof ( raw_menu ) ) ) < 0 ) {
+ rc = raw_menu_len;
+ DBG ( "Could not retrieve raw PXE boot menu: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+ if ( raw_menu_len >= ( int ) sizeof ( raw_menu ) ) {
+ DBG ( "Raw PXE boot menu too large for buffer\n" );
+ return -ENOSPC;
+ }
+ raw_menu_end = ( raw_menu + raw_menu_len );
+
+ /* Fetch raw prompt length */
+ raw_prompt_len = fetch_setting_len ( NULL,
+ &pxe_boot_menu_prompt_setting );
+ if ( raw_prompt_len < 0 )
+ raw_prompt_len = 0;
+
+ /* Count menu items */
+ num_menu_items = 0;
+ raw_menu_item = ( ( void * ) raw_menu );
+ while ( 1 ) {
+ if ( ( ( ( void * ) raw_menu_item ) +
+ sizeof ( *raw_menu_item ) ) > raw_menu_end )
+ break;
+ if ( ( ( ( void * ) raw_menu_item ) +
+ sizeof ( *raw_menu_item ) +
+ raw_menu_item->desc_len ) > raw_menu_end )
+ break;
+ num_menu_items++;
+ raw_menu_item = ( ( ( void * ) raw_menu_item ) +
+ sizeof ( *raw_menu_item ) +
+ raw_menu_item->desc_len );
+ }
+
+ /* Allocate space for parsed menu */
+ *menu = zalloc ( sizeof ( **menu ) +
+ ( num_menu_items * sizeof ( (*menu)->items[0] ) ) +
+ raw_menu_len + 1 /* NUL */ +
+ raw_prompt_len + 1 /* NUL */ );
+ if ( ! *menu ) {
+ DBG ( "Could not allocate PXE boot menu\n" );
+ return -ENOMEM;
+ }
+
+ /* Fill in parsed menu */
+ (*menu)->num_items = num_menu_items;
+ raw_menu_item = ( ( ( void * ) (*menu) ) + sizeof ( **menu ) +
+ ( num_menu_items * sizeof ( (*menu)->items[0] ) ) );
+ memcpy ( raw_menu_item, raw_menu, raw_menu_len );
+ for ( i = 0 ; i < num_menu_items ; i++ ) {
+ (*menu)->items[i].type = le16_to_cpu ( raw_menu_item->type );
+ (*menu)->items[i].desc = raw_menu_item->desc;
+ /* Set type to 0; this ensures that the description
+ * for the previous menu item is NUL-terminated.
+ * (Final item is NUL-terminated anyway.)
+ */
+ raw_menu_item->type = 0;
+ raw_menu_item = ( ( ( void * ) raw_menu_item ) +
+ sizeof ( *raw_menu_item ) +
+ raw_menu_item->desc_len );
+ }
+ if ( raw_prompt_len ) {
+ raw_menu_prompt = ( ( ( void * ) raw_menu_item ) +
+ 1 /* NUL */ );
+ fetch_setting ( NULL, &pxe_boot_menu_prompt_setting,
+ raw_menu_prompt, raw_prompt_len );
+ (*menu)->timeout =
+ ( ( raw_menu_prompt->timeout == 0xff ) ?
+ -1 : raw_menu_prompt->timeout );
+ (*menu)->prompt = raw_menu_prompt->prompt;
+ } else {
+ (*menu)->timeout = -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Draw PXE boot menu item
+ *
+ * @v menu PXE boot menu
+ * @v index Index of item to draw
+ * @v selected Item is selected
+ */
+static void pxe_menu_draw_item ( struct pxe_menu *menu,
+ unsigned int index, int selected ) {
+ char buf[COLS+1];
+ size_t len;
+ unsigned int row;
+
+ /* Prepare space-padded row content */
+ len = snprintf ( buf, sizeof ( buf ), " %c. %s",
+ ( 'A' + index ), menu->items[index].desc );
+ while ( len < ( sizeof ( buf ) - 1 ) )
+ buf[len++] = ' ';
+ buf[ sizeof ( buf ) - 1 ] = '\0';
+
+ /* Draw row */
+ row = ( LINES - menu->num_items + index );
+ color_set ( ( selected ? CPAIR_SELECT : CPAIR_NORMAL ), NULL );
+ mvprintw ( row, 0, "%s", buf );
+ move ( row, 1 );
+}
+
+/**
+ * Make selection from PXE boot menu
+ *
+ * @v menu PXE boot menu
+ * @ret rc Return status code
+ */
+static int pxe_menu_select ( struct pxe_menu *menu ) {
+ int key;
+ unsigned int key_selection;
+ unsigned int i;
+ int rc = 0;
+
+ /* Initialise UI */
+ initscr();
+ start_color();
+ init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLACK );
+ init_pair ( CPAIR_SELECT, COLOR_BLACK, COLOR_WHITE );
+ color_set ( CPAIR_NORMAL, NULL );
+
+ /* Draw initial menu */
+ for ( i = 0 ; i < menu->num_items ; i++ )
+ printf ( "\n" );
+ for ( i = 0 ; i < menu->num_items ; i++ )
+ pxe_menu_draw_item ( menu, ( menu->num_items - i - 1 ), 0 );
+
+ while ( 1 ) {
+
+ /* Highlight currently selected item */
+ pxe_menu_draw_item ( menu, menu->selection, 1 );
+
+ /* Wait for keyboard input */
+ key = getkey ( 0 );
+
+ /* Unhighlight currently selected item */
+ pxe_menu_draw_item ( menu, menu->selection, 0 );
+
+ /* Act upon key */
+ if ( ( key == CR ) || ( key == LF ) ) {
+ pxe_menu_draw_item ( menu, menu->selection, 1 );
+ break;
+ } else if ( ( key == CTRL_C ) || ( key == ESC ) ) {
+ rc = -ECANCELED;
+ break;
+ } else if ( key == KEY_UP ) {
+ if ( menu->selection > 0 )
+ menu->selection--;
+ } else if ( key == KEY_DOWN ) {
+ if ( menu->selection < ( menu->num_items - 1 ) )
+ menu->selection++;
+ } else if ( ( key < KEY_MIN ) &&
+ ( ( key_selection = ( toupper ( key ) - 'A' ) )
+ < menu->num_items ) ) {
+ menu->selection = key_selection;
+ pxe_menu_draw_item ( menu, menu->selection, 1 );
+ break;
+ }
+ }
+
+ /* Shut down UI */
+ endwin();
+
+ return rc;
+}
+
+/**
+ * Prompt for (and make selection from) PXE boot menu
+ *
+ * @v menu PXE boot menu
+ * @ret rc Return status code
+ */
+static int pxe_menu_prompt_and_select ( struct pxe_menu *menu ) {
+ unsigned long start = currticks();
+ unsigned long now;
+ unsigned long elapsed;
+ size_t len = 0;
+ int key;
+ int rc = 0;
+
+ /* Display menu immediately, if specified to do so */
+ if ( menu->timeout < 0 ) {
+ if ( menu->prompt )
+ printf ( "%s\n", menu->prompt );
+ return pxe_menu_select ( menu );
+ }
+
+ /* Display prompt, if specified */
+ if ( menu->prompt )
+ printf ( "%s", menu->prompt );
+
+ /* Wait for timeout, if specified */
+ while ( menu->timeout > 0 ) {
+ if ( ! len )
+ len = printf ( " (%d)", menu->timeout );
+ if ( iskey() ) {
+ key = getkey ( 0 );
+ if ( key == KEY_F8 ) {
+ /* Display menu */
+ printf ( "\n" );
+ return pxe_menu_select ( menu );
+ } else if ( ( key == CTRL_C ) || ( key == ESC ) ) {
+ /* Abort */
+ rc = -ECANCELED;
+ break;
+ } else {
+ /* Stop waiting */
+ break;
+ }
+ }
+ now = currticks();
+ elapsed = ( now - start );
+ if ( elapsed >= TICKS_PER_SEC ) {
+ menu->timeout -= 1;
+ do {
+ printf ( "\b \b" );
+ } while ( --len );
+ start = now;
+ }
+ }
+
+ /* Return with default option selected */
+ printf ( "\n" );
+ return rc;
+}
+
+/**
+ * Boot using PXE boot menu
+ *
+ * @ret rc Return status code
+ *
+ * Note that a success return status indicates that a PXE boot menu
+ * item has been selected, and that the DHCP session should perform a
+ * boot server request/ack.
+ */
+int pxe_menu_boot ( struct net_device *netdev ) {
+ struct pxe_menu *menu;
+ unsigned int pxe_type;
+ struct settings *pxebs_settings;
+ struct uri *uri;
+ int rc;
+
+ /* Parse and allocate boot menu */
+ if ( ( rc = pxe_menu_parse ( &menu ) ) != 0 )
+ return rc;
+
+ /* Make selection from boot menu */
+ if ( ( rc = pxe_menu_prompt_and_select ( menu ) ) != 0 ) {
+ free ( menu );
+ return rc;
+ }
+ pxe_type = menu->items[menu->selection].type;
+
+ /* Free boot menu */
+ free ( menu );
+
+ /* Return immediately if local boot selected */
+ if ( ! pxe_type )
+ return 0;
+
+ /* Attempt PXE Boot Server Discovery */
+ if ( ( rc = pxebs ( netdev, pxe_type ) ) != 0 )
+ return rc;
+
+ /* Fetch next server and filename */
+ pxebs_settings = find_settings ( PXEBS_SETTINGS_NAME );
+ assert ( pxebs_settings );
+ uri = fetch_next_server_and_filename ( pxebs_settings );
+ if ( ! uri )
+ return -ENOMEM;
+
+ /* Attempt boot */
+ rc = uriboot ( uri, NULL, 0, URIBOOT_NO_SAN );
+ uri_put ( uri );
+ return rc;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/usr/route.c b/src/VBox/Devices/PC/ipxe/src/usr/route.c
new file mode 100644
index 00000000..1da7135b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/usr/route.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ip.h>
+#include <usr/route.h>
+
+/** @file
+ *
+ * Routing table management
+ *
+ */
+
+void route ( void ) {
+ struct ipv4_miniroute *miniroute;
+
+ list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
+ printf ( "%s: %s/", miniroute->netdev->name,
+ inet_ntoa ( miniroute->address ) );
+ printf ( "%s", inet_ntoa ( miniroute->netmask ) );
+ if ( miniroute->gateway.s_addr )
+ printf ( " gw %s", inet_ntoa ( miniroute->gateway ) );
+ if ( ! netdev_is_open ( miniroute->netdev ) )
+ printf ( " (inaccessible)" );
+ printf ( "\n" );
+ }
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/util/Makefile b/src/VBox/Devices/PC/ipxe/src/util/Makefile
new file mode 100644
index 00000000..4a6a7c7c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/Makefile
@@ -0,0 +1,16 @@
+BLIB = ../bin/blib.a
+CFLAGS = -Os
+
+all : hijack mucurses_test
+
+hijack : hijack.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -Wall -lpcap -o $@ $<
+
+mucurses_test.o : mucurses_test.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -Wall -o $@ -c $<
+
+mucurses_test : mucurses_test.o $(BLIB)
+ $(CC) -o $@ $< -lc $(BLIB)
+
+clean :
+ rm -f hijack mucurses_test *.o
diff --git a/src/VBox/Devices/PC/ipxe/src/util/Option/ROM.pm b/src/VBox/Devices/PC/ipxe/src/util/Option/ROM.pm
new file mode 100644
index 00000000..9fea4d34
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/Option/ROM.pm
@@ -0,0 +1,502 @@
+package Option::ROM;
+
+# Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+=head1 NAME
+
+Option::ROM - Option ROM manipulation
+
+=head1 SYNOPSIS
+
+ use Option::ROM;
+
+ # Load a ROM image
+ my $rom = new Option::ROM;
+ $rom->load ( "rtl8139.rom" );
+
+ # Modify the PCI device ID
+ $rom->pci_header->{device_id} = 0x1234;
+ $rom->fix_checksum();
+
+ # Write ROM image out to a new file
+ $rom->save ( "rtl8139-modified.rom" );
+
+=head1 DESCRIPTION
+
+C<Option::ROM> provides a mechanism for manipulating Option ROM
+images.
+
+=head1 METHODS
+
+=cut
+
+##############################################################################
+#
+# Option::ROM::Fields
+#
+##############################################################################
+
+package Option::ROM::Fields;
+
+use strict;
+use warnings;
+use Carp;
+use bytes;
+
+sub TIEHASH {
+ my $class = shift;
+ my $self = shift;
+
+ bless $self, $class;
+ return $self;
+}
+
+sub FETCH {
+ my $self = shift;
+ my $key = shift;
+
+ return undef unless $self->EXISTS ( $key );
+ my $raw = substr ( ${$self->{data}},
+ ( $self->{offset} + $self->{fields}->{$key}->{offset} ),
+ $self->{fields}->{$key}->{length} );
+ my $unpack = ( ref $self->{fields}->{$key}->{unpack} ?
+ $self->{fields}->{$key}->{unpack} :
+ sub { unpack ( $self->{fields}->{$key}->{pack}, shift ); } );
+ return &$unpack ( $raw );
+}
+
+sub STORE {
+ my $self = shift;
+ my $key = shift;
+ my $value = shift;
+
+ croak "Nonexistent field \"$key\"" unless $self->EXISTS ( $key );
+ my $pack = ( ref $self->{fields}->{$key}->{pack} ?
+ $self->{fields}->{$key}->{pack} :
+ sub { pack ( $self->{fields}->{$key}->{pack}, shift ); } );
+ my $raw = &$pack ( $value );
+ substr ( ${$self->{data}},
+ ( $self->{offset} + $self->{fields}->{$key}->{offset} ),
+ $self->{fields}->{$key}->{length} ) = $raw;
+}
+
+sub DELETE {
+ my $self = shift;
+ my $key = shift;
+
+ $self->STORE ( $key, 0 );
+}
+
+sub CLEAR {
+ my $self = shift;
+
+ foreach my $key ( keys %{$self->{fields}} ) {
+ $self->DELETE ( $key );
+ }
+}
+
+sub EXISTS {
+ my $self = shift;
+ my $key = shift;
+
+ return ( exists $self->{fields}->{$key} &&
+ ( ( $self->{fields}->{$key}->{offset} +
+ $self->{fields}->{$key}->{length} ) <= $self->{length} ) );
+}
+
+sub FIRSTKEY {
+ my $self = shift;
+
+ keys %{$self->{fields}};
+ return each %{$self->{fields}};
+}
+
+sub NEXTKEY {
+ my $self = shift;
+ my $lastkey = shift;
+
+ return each %{$self->{fields}};
+}
+
+sub SCALAR {
+ my $self = shift;
+
+ return 1;
+}
+
+sub UNTIE {
+ my $self = shift;
+}
+
+sub DESTROY {
+ my $self = shift;
+}
+
+sub checksum {
+ my $self = shift;
+
+ my $raw = substr ( ${$self->{data}}, $self->{offset}, $self->{length} );
+ return unpack ( "%8C*", $raw );
+}
+
+##############################################################################
+#
+# Option::ROM
+#
+##############################################################################
+
+package Option::ROM;
+
+use strict;
+use warnings;
+use Carp;
+use bytes;
+use Exporter 'import';
+
+use constant ROM_SIGNATURE => 0xaa55;
+use constant PCI_SIGNATURE => 'PCIR';
+use constant PNP_SIGNATURE => '$PnP';
+
+our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PNP_SIGNATURE );
+our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
+
+use constant JMP_SHORT => 0xeb;
+use constant JMP_NEAR => 0xe9;
+
+sub pack_init {
+ my $dest = shift;
+
+ # Always create a near jump; it's simpler
+ if ( $dest ) {
+ return pack ( "CS", JMP_NEAR, ( $dest - 6 ) );
+ } else {
+ return pack ( "CS", 0, 0 );
+ }
+}
+
+sub unpack_init {
+ my $instr = shift;
+
+ # Accept both short and near jumps
+ my $jump = unpack ( "C", $instr );
+ if ( $jump == JMP_SHORT ) {
+ my $offset = unpack ( "xC", $instr );
+ return ( $offset + 5 );
+ } elsif ( $jump == JMP_NEAR ) {
+ my $offset = unpack ( "xS", $instr );
+ return ( $offset + 6 );
+ } elsif ( $jump == 0 ) {
+ return 0;
+ } else {
+ croak "Unrecognised jump instruction in init vector\n";
+ }
+}
+
+=pod
+
+=item C<< new () >>
+
+Construct a new C<Option::ROM> object.
+
+=cut
+
+sub new {
+ my $class = shift;
+
+ my $hash = {};
+ tie %$hash, "Option::ROM::Fields", {
+ data => undef,
+ offset => 0x00,
+ length => 0x20,
+ fields => {
+ signature => { offset => 0x00, length => 0x02, pack => "S" },
+ length => { offset => 0x02, length => 0x01, pack => "C" },
+ # "init" is part of a jump instruction
+ init => { offset => 0x03, length => 0x03,
+ pack => \&pack_init, unpack => \&unpack_init },
+ checksum => { offset => 0x06, length => 0x01, pack => "C" },
+ bofm_header => { offset => 0x14, length => 0x02, pack => "S" },
+ undi_header => { offset => 0x16, length => 0x02, pack => "S" },
+ pci_header => { offset => 0x18, length => 0x02, pack => "S" },
+ pnp_header => { offset => 0x1a, length => 0x02, pack => "S" },
+ },
+ };
+ bless $hash, $class;
+ return $hash;
+}
+
+=pod
+
+=item C<< load ( $filename ) >>
+
+Load option ROM contents from the file C<$filename>.
+
+=cut
+
+sub load {
+ my $hash = shift;
+ my $self = tied(%$hash);
+ my $filename = shift;
+
+ $self->{filename} = $filename;
+
+ open my $fh, "<$filename"
+ or croak "Cannot open $filename for reading: $!";
+ read $fh, my $data, ( 128 * 1024 ); # 128kB is theoretical max size
+ $self->{data} = \$data;
+ close $fh;
+}
+
+=pod
+
+=item C<< save ( [ $filename ] ) >>
+
+Write the ROM data back out to the file C<$filename>. If C<$filename>
+is omitted, the file used in the call to C<load()> will be used.
+
+=cut
+
+sub save {
+ my $hash = shift;
+ my $self = tied(%$hash);
+ my $filename = shift;
+
+ $filename ||= $self->{filename};
+
+ open my $fh, ">$filename"
+ or croak "Cannot open $filename for writing: $!";
+ print $fh ${$self->{data}};
+ close $fh;
+}
+
+=pod
+
+=item C<< length () >>
+
+Length of option ROM data. This is the length of the file, not the
+length from the ROM header length field.
+
+=cut
+
+sub length {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ return length ${$self->{data}};
+}
+
+=pod
+
+=item C<< pci_header () >>
+
+Return a C<Option::ROM::PCI> object representing the ROM's PCI header,
+if present.
+
+=cut
+
+sub pci_header {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ my $offset = $hash->{pci_header};
+ return undef unless $offset != 0;
+
+ return Option::ROM::PCI->new ( $self->{data}, $offset );
+}
+
+=pod
+
+=item C<< pnp_header () >>
+
+Return a C<Option::ROM::PnP> object representing the ROM's PnP header,
+if present.
+
+=cut
+
+sub pnp_header {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ my $offset = $hash->{pnp_header};
+ return undef unless $offset != 0;
+
+ return Option::ROM::PnP->new ( $self->{data}, $offset );
+}
+
+=pod
+
+=item C<< checksum () >>
+
+Calculate the byte checksum of the ROM.
+
+=cut
+
+sub checksum {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ my $raw = substr ( ${$self->{data}}, 0, ( $hash->{length} * 512 ) );
+ return unpack ( "%8C*", $raw );
+}
+
+=pod
+
+=item C<< fix_checksum () >>
+
+Fix the byte checksum of the ROM.
+
+=cut
+
+sub fix_checksum {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ $hash->{checksum} = ( ( $hash->{checksum} - $hash->checksum() ) & 0xff );
+}
+
+##############################################################################
+#
+# Option::ROM::PCI
+#
+##############################################################################
+
+package Option::ROM::PCI;
+
+use strict;
+use warnings;
+use Carp;
+use bytes;
+
+sub new {
+ my $class = shift;
+ my $data = shift;
+ my $offset = shift;
+
+ my $hash = {};
+ tie %$hash, "Option::ROM::Fields", {
+ data => $data,
+ offset => $offset,
+ length => 0x0c,
+ fields => {
+ signature => { offset => 0x00, length => 0x04, pack => "a4" },
+ vendor_id => { offset => 0x04, length => 0x02, pack => "S" },
+ device_id => { offset => 0x06, length => 0x02, pack => "S" },
+ device_list => { offset => 0x08, length => 0x02, pack => "S" },
+ struct_length => { offset => 0x0a, length => 0x02, pack => "S" },
+ struct_revision =>{ offset => 0x0c, length => 0x01, pack => "C" },
+ base_class => { offset => 0x0d, length => 0x01, pack => "C" },
+ sub_class => { offset => 0x0e, length => 0x01, pack => "C" },
+ prog_intf => { offset => 0x0f, length => 0x01, pack => "C" },
+ image_length => { offset => 0x10, length => 0x02, pack => "S" },
+ revision => { offset => 0x12, length => 0x02, pack => "S" },
+ code_type => { offset => 0x14, length => 0x01, pack => "C" },
+ last_image => { offset => 0x15, length => 0x01, pack => "C" },
+ runtime_length => { offset => 0x16, length => 0x02, pack => "S" },
+ conf_header => { offset => 0x18, length => 0x02, pack => "S" },
+ clp_entry => { offset => 0x1a, length => 0x02, pack => "S" },
+ },
+ };
+ bless $hash, $class;
+
+ # Retrieve true length of structure
+ my $self = tied ( %$hash );
+ $self->{length} = $hash->{struct_length};
+
+ return $hash;
+}
+
+##############################################################################
+#
+# Option::ROM::PnP
+#
+##############################################################################
+
+package Option::ROM::PnP;
+
+use strict;
+use warnings;
+use Carp;
+use bytes;
+
+sub new {
+ my $class = shift;
+ my $data = shift;
+ my $offset = shift;
+
+ my $hash = {};
+ tie %$hash, "Option::ROM::Fields", {
+ data => $data,
+ offset => $offset,
+ length => 0x06,
+ fields => {
+ signature => { offset => 0x00, length => 0x04, pack => "a4" },
+ struct_revision =>{ offset => 0x04, length => 0x01, pack => "C" },
+ struct_length => { offset => 0x05, length => 0x01, pack => "C" },
+ checksum => { offset => 0x09, length => 0x01, pack => "C" },
+ manufacturer => { offset => 0x0e, length => 0x02, pack => "S" },
+ product => { offset => 0x10, length => 0x02, pack => "S" },
+ bcv => { offset => 0x16, length => 0x02, pack => "S" },
+ bdv => { offset => 0x18, length => 0x02, pack => "S" },
+ bev => { offset => 0x1a, length => 0x02, pack => "S" },
+ },
+ };
+ bless $hash, $class;
+
+ # Retrieve true length of structure
+ my $self = tied ( %$hash );
+ $self->{length} = ( $hash->{struct_length} * 16 );
+
+ return $hash;
+}
+
+sub checksum {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ return $self->checksum();
+}
+
+sub fix_checksum {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ $hash->{checksum} = ( ( $hash->{checksum} - $hash->checksum() ) & 0xff );
+}
+
+sub manufacturer {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ my $manufacturer = $hash->{manufacturer};
+ return undef unless $manufacturer;
+
+ my $raw = substr ( ${$self->{data}}, $manufacturer );
+ return unpack ( "Z*", $raw );
+}
+
+sub product {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ my $product = $hash->{product};
+ return undef unless $product;
+
+ my $raw = substr ( ${$self->{data}}, $product );
+ return unpack ( "Z*", $raw );
+}
+
+1;
diff --git a/src/VBox/Devices/PC/ipxe/src/util/catrom.pl b/src/VBox/Devices/PC/ipxe/src/util/catrom.pl
new file mode 100755
index 00000000..fe37e6b6
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/catrom.pl
@@ -0,0 +1,48 @@
+#!/usr/bin/perl -w
+
+use warnings;
+use strict;
+
+use bytes;
+
+use constant MAX_ROM_LEN => 1024*1024;
+use constant PCI_OFF => 0x18;
+use constant INDICATOR_OFF => 0x15;
+
+my $total_len = 0;
+my @romfiles = @ARGV
+ or die "Usage: $0 rom-file-1 rom-file-2 ... > multi-rom-file\n";
+
+while ( my $romfile = shift @romfiles ) {
+ my $last = @romfiles ? 0 : 1;
+
+ open ROM, "<$romfile" or die "Could not open $romfile: $!\n";
+ my $len = read ( ROM, my $romdata, MAX_ROM_LEN )
+ or die "Could not read $romfile: $!\n";
+ close ROM;
+
+ die "$romfile is not a ROM file\n"
+ unless substr ( $romdata, 0, 2 ) eq "\x55\xAA";
+
+ ( my $checklen ) = unpack ( 'C', substr ( $romdata, 2, 1 ) );
+ $checklen *= 512;
+ die "$romfile has incorrect length field $checklen (should be $len)\n"
+ unless $len == $checklen;
+
+ ( my $pci ) = unpack ( 'v', substr ( $romdata, PCI_OFF, 2 ) );
+ die "Invalid PCI offset field in $romfile\n"
+ if $pci >= $len;
+ die "No PCIR signature in $romfile\n"
+ unless substr ( $romdata, $pci, 4 ) eq "PCIR";
+
+ ( my $indicator ) =
+ unpack ( 'C', substr ( $romdata, $pci + INDICATOR_OFF, 1 ) );
+ my $msg = sprintf ( "$romfile: indicator was %02x, ", $indicator );
+ $indicator &= ! ( 1 << 7 );
+ $indicator |= ( $last << 7 );
+ $msg .= sprintf ( "now %02x\n", $indicator );
+ substr ( $romdata, $pci + INDICATOR_OFF, 1 ) = pack ( 'C', $indicator );
+ warn $msg;
+
+ print $romdata;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/util/diffsize.pl b/src/VBox/Devices/PC/ipxe/src/util/diffsize.pl
new file mode 100755
index 00000000..ced07862
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/diffsize.pl
@@ -0,0 +1,101 @@
+#!/usr/bin/perl -w
+# usage:
+# [somebody@somewhere ~/ipxe/src]$ ./util/diffsize.pl [<old rev> [<new rev>]]
+# by default <old rev> is HEAD and <new rev> is the working tree
+
+use strict;
+
+-d "bin" or die "Please run me in the iPXE src directory\n";
+mkdir ".sizes";
+
+my($oldrev, $newrev);
+my($oldname, $newname);
+
+if (@ARGV) {
+ $oldname = shift;
+} else {
+ $oldname = "HEAD";
+}
+
+if (@ARGV) {
+ $newname = shift;
+} else {
+ $newrev = "tree" . time();
+}
+
+$oldrev = `git rev-parse $oldname`;
+chomp $oldrev;
+
+unless (defined $newrev) {
+ $newrev = `git rev-parse $newname`;
+ chomp $newrev;
+}
+
+sub calc_sizes($$) {
+ my($name, $rev) = @_;
+ my $output;
+ my $lastrev;
+ my $stashed = 0;
+ my $res = 0;
+
+ return if -e ".sizes/$rev.sizes";
+
+ if (defined $name) {
+ $output = `git stash`;
+ $stashed = 1 unless $output =~ /No local changes to save/;
+ $lastrev = `git name-rev --name-only HEAD`;
+ system("git checkout $name >/dev/null"); $res ||= $?;
+ }
+
+ system("make -j4 bin/ipxe.lkrn >/dev/null"); $res ||= $?;
+ system("make bin/ipxe.lkrn.sizes > .sizes/$rev.sizes"); $res ||= $?;
+
+ if (defined $name) {
+ system("git checkout $lastrev >/dev/null"); $res ||= $?;
+ system("git stash pop >/dev/null") if $stashed; $res ||= $?;
+ }
+
+ if ($res) {
+ unlink(".sizes/$rev.sizes");
+ die "Error making sizes file\n";
+ }
+}
+
+our %Sizes;
+
+sub save_sizes($$) {
+ my($id, $rev) = @_;
+ my $file = ".sizes/$rev.sizes";
+
+ open SIZES, $file or die "opening $file: $!\n";
+ while (<SIZES>) {
+ my($text, $data, $bss, $total, $hex, $name) = split;
+ $name =~ s|bin/||; $name =~ s|\.o$||;
+
+ # Skip the header and totals lines
+ next if $total =~ /[a-z]/ or $name =~ /TOTALS/;
+
+ # Skip files named with dash, due to old Makefile bug
+ next if $name =~ /-/;
+
+ $Sizes{$name} = {old => 0, new => 0} unless exists $Sizes{$name};
+ $Sizes{$name}{$id} = $total;
+ }
+}
+
+calc_sizes($oldname, $oldrev);
+calc_sizes($newname, $newrev);
+
+save_sizes('old', $oldrev);
+save_sizes('new', $newrev);
+
+my $total = 0;
+
+for (sort keys %Sizes) {
+ my $diff = $Sizes{$_}{new} - $Sizes{$_}{old};
+ if (abs($diff) >= 16) {
+ printf "%12s %+d\n", substr($_, 0, 12), $Sizes{$_}{new} - $Sizes{$_}{old};
+ }
+ $total += $diff;
+}
+printf " TOTAL: %+d\n", $total;
diff --git a/src/VBox/Devices/PC/ipxe/src/util/disrom.pl b/src/VBox/Devices/PC/ipxe/src/util/disrom.pl
new file mode 100755
index 00000000..1fb4cc3c
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/disrom.pl
@@ -0,0 +1,81 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+use strict;
+use warnings;
+
+use FindBin;
+use lib "$FindBin::Bin";
+use Option::ROM qw ( :all );
+
+my $romfile = shift || "-";
+my $rom = new Option::ROM;
+$rom->load ( $romfile );
+
+die "Not an option ROM image\n"
+ unless $rom->{signature} == ROM_SIGNATURE;
+
+my $romlength = ( $rom->{length} * 512 );
+my $filelength = $rom->length;
+die "ROM image truncated (is $filelength, should be $romlength)\n"
+ if $filelength < $romlength;
+
+printf "ROM header:\n\n";
+printf " %-16s 0x%02x (%d)\n", "Length:", $rom->{length}, ( $rom->{length} * 512 );
+printf " %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $rom->{checksum},
+ ( ( $rom->checksum == 0 ) ? "" : "INCORRECT: " ), $rom->checksum;
+printf " %-16s 0x%04x\n", "Init:", $rom->{init};
+printf " %-16s 0x%04x\n", "UNDI header:", $rom->{undi_header};
+printf " %-16s 0x%04x\n", "PCI header:", $rom->{pci_header};
+printf " %-16s 0x%04x\n", "PnP header:", $rom->{pnp_header};
+printf "\n";
+
+my $pci = $rom->pci_header();
+if ( $pci ) {
+ printf "PCI header:\n\n";
+ printf " %-16s %s\n", "Signature:", $pci->{signature};
+ printf " %-16s 0x%04x\n", "Vendor ID:", $pci->{vendor_id};
+ printf " %-16s 0x%04x\n", "Device ID:", $pci->{device_id};
+ printf " %-16s 0x%02x%02x%02x\n", "Device class:",
+ $pci->{base_class}, $pci->{sub_class}, $pci->{prog_intf};
+ printf " %-16s 0x%04x (%d)\n", "Image length:",
+ $pci->{image_length}, ( $pci->{image_length} * 512 );
+ printf " %-16s 0x%04x (%d)\n", "Runtime length:",
+ $pci->{runtime_length}, ( $pci->{runtime_length} * 512 );
+ if ( exists $pci->{conf_header} ) {
+ printf " %-16s 0x%04x\n", "Config header:", $pci->{conf_header};
+ printf " %-16s 0x%04x\n", "CLP entry:", $pci->{clp_entry};
+ }
+ printf "\n";
+}
+
+my $pnp = $rom->pnp_header();
+if ( $pnp ) {
+ printf "PnP header:\n\n";
+ printf " %-16s %s\n", "Signature:", $pnp->{signature};
+ printf " %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $pnp->{checksum},
+ ( ( $pnp->checksum == 0 ) ? "" : "INCORRECT: " ), $pnp->checksum;
+ printf " %-16s 0x%04x \"%s\"\n", "Manufacturer:",
+ $pnp->{manufacturer}, $pnp->manufacturer;
+ printf " %-16s 0x%04x \"%s\"\n", "Product:",
+ $pnp->{product}, $pnp->product;
+ printf " %-16s 0x%04x\n", "BCV:", $pnp->{bcv};
+ printf " %-16s 0x%04x\n", "BDV:", $pnp->{bdv};
+ printf " %-16s 0x%04x\n", "BEV:", $pnp->{bev};
+ printf "\n";
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/util/efirom.c b/src/VBox/Devices/PC/ipxe/src/util/efirom.c
new file mode 100644
index 00000000..a65abfee
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/efirom.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <getopt.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/IndustryStandard/PeImage.h>
+#include <ipxe/efi/IndustryStandard/Pci22.h>
+
+#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
+
+/** Command-line options */
+struct options {
+ uint16_t vendor;
+ uint16_t device;
+};
+
+/**
+ * Allocate memory
+ *
+ * @v len Length of memory to allocate
+ * @ret ptr Pointer to allocated memory
+ */
+static void * xmalloc ( size_t len ) {
+ void *ptr;
+
+ ptr = malloc ( len );
+ if ( ! ptr ) {
+ eprintf ( "Could not allocate %zd bytes\n", len );
+ exit ( 1 );
+ }
+
+ return ptr;
+}
+
+/**
+ * Read information from PE headers
+ *
+ * @v pe PE file
+ * @ret machine Machine type
+ * @ret subsystem EFI subsystem
+ */
+static void read_pe_info ( void *pe, uint16_t *machine,
+ uint16_t *subsystem ) {
+ EFI_IMAGE_DOS_HEADER *dos;
+ union {
+ EFI_IMAGE_NT_HEADERS32 nt32;
+ EFI_IMAGE_NT_HEADERS64 nt64;
+ } *nt;
+
+ /* Locate NT header */
+ dos = pe;
+ nt = ( pe + dos->e_lfanew );
+
+ /* Parse out PE information */
+ *machine = nt->nt32.FileHeader.Machine;
+ switch ( *machine ) {
+ case EFI_IMAGE_MACHINE_IA32:
+ *subsystem = nt->nt32.OptionalHeader.Subsystem;
+ break;
+ case EFI_IMAGE_MACHINE_X64:
+ *subsystem = nt->nt64.OptionalHeader.Subsystem;
+ break;
+ default:
+ eprintf ( "Unrecognised machine type %04x\n", *machine );
+ exit ( 1 );
+ }
+}
+
+/**
+ * Convert EFI image to ROM image
+ *
+ * @v pe EFI file
+ * @v rom ROM file
+ */
+static void make_efi_rom ( FILE *pe, FILE *rom, struct options *opts ) {
+ struct {
+ EFI_PCI_EXPANSION_ROM_HEADER rom;
+ PCI_DATA_STRUCTURE pci __attribute__ (( aligned ( 4 ) ));
+ uint8_t checksum;
+ } *headers;
+ struct stat pe_stat;
+ size_t pe_size;
+ size_t rom_size;
+ void *buf;
+ void *payload;
+ unsigned int i;
+ uint8_t checksum;
+
+ /* Determine PE file size */
+ if ( fstat ( fileno ( pe ), &pe_stat ) != 0 ) {
+ eprintf ( "Could not stat PE file: %s\n",
+ strerror ( errno ) );
+ exit ( 1 );
+ }
+ pe_size = pe_stat.st_size;
+
+ /* Determine ROM file size */
+ rom_size = ( ( pe_size + sizeof ( *headers ) + 511 ) & ~511 );
+
+ /* Allocate ROM buffer and read in PE file */
+ buf = xmalloc ( rom_size );
+ memset ( buf, 0, rom_size );
+ headers = buf;
+ payload = ( buf + sizeof ( *headers ) );
+ if ( fread ( payload, pe_size, 1, pe ) != 1 ) {
+ eprintf ( "Could not read PE file: %s\n",
+ strerror ( errno ) );
+ exit ( 1 );
+ }
+
+ /* Construct ROM header */
+ headers->rom.Signature = PCI_EXPANSION_ROM_HEADER_SIGNATURE;
+ headers->rom.InitializationSize = ( rom_size / 512 );
+ headers->rom.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;
+ read_pe_info ( payload, &headers->rom.EfiMachineType,
+ &headers->rom.EfiSubsystem );
+ headers->rom.EfiImageHeaderOffset = sizeof ( *headers );
+ headers->rom.PcirOffset =
+ offsetof ( typeof ( *headers ), pci );
+ headers->pci.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
+ headers->pci.VendorId = opts->vendor;
+ headers->pci.DeviceId = opts->device;
+ headers->pci.Length = sizeof ( headers->pci );
+ headers->pci.ClassCode[0] = PCI_CLASS_NETWORK;
+ headers->pci.ImageLength = ( rom_size / 512 );
+ headers->pci.CodeType = 0x03; /* No constant in EFI headers? */
+ headers->pci.Indicator = 0x80; /* No constant in EFI headers? */
+
+ /* Fix image checksum */
+ for ( i = 0, checksum = 0 ; i < rom_size ; i++ )
+ checksum += *( ( uint8_t * ) buf + i );
+ headers->checksum -= checksum;
+
+ /* Write out ROM */
+ if ( fwrite ( buf, rom_size, 1, rom ) != 1 ) {
+ eprintf ( "Could not write ROM file: %s\n",
+ strerror ( errno ) );
+ exit ( 1 );
+ }
+}
+
+/**
+ * Print help
+ *
+ * @v program_name Program name
+ */
+static void print_help ( const char *program_name ) {
+ eprintf ( "Syntax: %s [--vendor=VVVV] [--device=DDDD] "
+ "infile outfile\n", program_name );
+}
+
+/**
+ * Parse command-line options
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v opts Options structure to populate
+ */
+static int parse_options ( const int argc, char **argv,
+ struct options *opts ) {
+ char *end;
+ int c;
+
+ while (1) {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "vendor", required_argument, NULL, 'v' },
+ { "device", required_argument, NULL, 'd' },
+ { "help", 0, NULL, 'h' },
+ { 0, 0, 0, 0 }
+ };
+
+ if ( ( c = getopt_long ( argc, argv, "v:d:h",
+ long_options,
+ &option_index ) ) == -1 ) {
+ break;
+ }
+
+ switch ( c ) {
+ case 'v':
+ opts->vendor = strtoul ( optarg, &end, 16 );
+ if ( *end ) {
+ eprintf ( "Invalid vendor \"%s\"\n", optarg );
+ exit ( 2 );
+ }
+ break;
+ case 'd':
+ opts->device = strtoul ( optarg, &end, 16 );
+ if ( *end ) {
+ eprintf ( "Invalid device \"%s\"\n", optarg );
+ exit ( 2 );
+ }
+ break;
+ case 'h':
+ print_help ( argv[0] );
+ exit ( 0 );
+ case '?':
+ default:
+ exit ( 2 );
+ }
+ }
+ return optind;
+}
+
+int main ( int argc, char **argv ) {
+ struct options opts;
+ int infile_index;
+ const char *infile_name;
+ const char *outfile_name;
+ FILE *infile;
+ FILE *outfile;
+
+ /* Parse command-line arguments */
+ memset ( &opts, 0, sizeof ( opts ) );
+ infile_index = parse_options ( argc, argv, &opts );
+ if ( argc != ( infile_index + 2 ) ) {
+ print_help ( argv[0] );
+ exit ( 2 );
+ }
+ infile_name = argv[infile_index];
+ outfile_name = argv[infile_index + 1];
+
+ /* Open input and output files */
+ infile = fopen ( infile_name, "r" );
+ if ( ! infile ) {
+ eprintf ( "Could not open %s for reading: %s\n",
+ infile_name, strerror ( errno ) );
+ exit ( 1 );
+ }
+ outfile = fopen ( outfile_name, "w" );
+ if ( ! outfile ) {
+ eprintf ( "Could not open %s for writing: %s\n",
+ outfile_name, strerror ( errno ) );
+ exit ( 1 );
+ }
+
+ /* Convert file */
+ make_efi_rom ( infile, outfile, &opts );
+
+ fclose ( outfile );
+ fclose ( infile );
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/util/einfo.c b/src/VBox/Devices/PC/ipxe/src/util/einfo.c
new file mode 100644
index 00000000..15f920d0
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/einfo.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+
+#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
+
+/** Command-line options */
+struct options {
+};
+
+/** Error usage information */
+struct einfo {
+ uint32_t size;
+ uint32_t error;
+ uint32_t desc;
+ uint32_t file;
+ uint32_t line;
+} __attribute__ (( packed ));
+
+/**
+ * Process einfo file
+ *
+ * @v infile Filename
+ * @v opts Command-line options
+ */
+static void einfo ( const char *infile,
+ struct options *opts __attribute__ (( unused )) ) {
+ int fd;
+ struct stat stat;
+ size_t len;
+ void *start;
+ struct einfo *einfo;
+
+ /* Open einfo file */
+ if ( ( fd = open ( infile, O_RDONLY ) ) < 0 ) {
+ eprintf ( "Cannot open \"%s\": %s\n",
+ infile, strerror ( errno ) );
+ exit ( 1 );
+ }
+
+ /* Get file size */
+ if ( fstat ( fd, &stat ) < 0 ) {
+ eprintf ( "Cannot stat \"%s\": %s\n",
+ infile, strerror ( errno ) );
+ exit ( 1 );
+ }
+ len = stat.st_size;
+
+ if ( len ) {
+
+ /* Map file */
+ if ( ( start = mmap ( NULL, len, PROT_READ, MAP_SHARED,
+ fd, 0 ) ) == MAP_FAILED ) {
+ eprintf ( "Cannot mmap \"%s\": %s\n",
+ infile, strerror ( errno ) );
+ exit ( 1 );
+ }
+
+ /* Iterate over einfo records */
+ for ( einfo = start ; ( ( void * ) einfo ) < ( start + len ) ;
+ einfo = ( ( ( void * ) einfo ) + einfo->size ) ) {
+ printf ( "%08x\t%s\t%d\t%s\n", einfo->error,
+ ( ( ( char * ) einfo ) + einfo->file ),
+ einfo->line,
+ ( ( ( char * ) einfo ) + einfo->desc ) );
+ }
+
+ }
+
+ /* Unmap and close file */
+ munmap ( start, len );
+ close ( fd );
+}
+
+/**
+ * Print help
+ *
+ * @v program_name Program name
+ */
+static void print_help ( const char *program_name ) {
+ eprintf ( "Syntax: %s file1.einfo [file2.einfo...]\n",
+ program_name );
+}
+
+/**
+ * Parse command-line options
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v opts Options structure to populate
+ */
+static int parse_options ( const int argc, char **argv,
+ struct options *opts __attribute__ (( unused )) ) {
+ int c;
+
+ while (1) {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { 0, 0, 0, 0 }
+ };
+
+ if ( ( c = getopt_long ( argc, argv, "s:h",
+ long_options,
+ &option_index ) ) == -1 ) {
+ break;
+ }
+
+ switch ( c ) {
+ case 'h':
+ print_help ( argv[0] );
+ exit ( 0 );
+ case '?':
+ default:
+ exit ( 2 );
+ }
+ }
+ return optind;
+}
+
+int main ( int argc, char **argv ) {
+ struct options opts = {
+ };
+ int infile_index;
+ const char *infile;
+
+ /* Parse command-line arguments */
+ infile_index = parse_options ( argc, argv, &opts );
+ if ( argc <= infile_index ) {
+ print_help ( argv[0] );
+ exit ( 2 );
+ }
+
+ /* Process each einfo file */
+ for ( ; infile_index < argc ; infile_index++ ) {
+ infile = argv[infile_index];
+ einfo ( infile, &opts );
+ }
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/util/elf2efi.c b/src/VBox/Devices/PC/ipxe/src/util/elf2efi.c
new file mode 100644
index 00000000..fc6bef37
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/elf2efi.c
@@ -0,0 +1,814 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define _GNU_SOURCE
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <getopt.h>
+#include <bfd.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/IndustryStandard/PeImage.h>
+#include <libgen.h>
+
+#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
+
+#define EFI_FILE_ALIGN 0x20
+
+struct pe_section {
+ struct pe_section *next;
+ EFI_IMAGE_SECTION_HEADER hdr;
+ uint8_t contents[0];
+};
+
+struct pe_relocs {
+ struct pe_relocs *next;
+ unsigned long start_rva;
+ unsigned int used_relocs;
+ unsigned int total_relocs;
+ uint16_t *relocs;
+};
+
+struct pe_header {
+ EFI_IMAGE_DOS_HEADER dos;
+ uint8_t padding[128];
+#if defined(EFI_TARGET_IA32)
+ EFI_IMAGE_NT_HEADERS32 nt;
+#elif defined(EFI_TARGET_X64)
+ EFI_IMAGE_NT_HEADERS64 nt;
+#endif
+};
+
+static struct pe_header efi_pe_header = {
+ .dos = {
+ .e_magic = EFI_IMAGE_DOS_SIGNATURE,
+ .e_lfanew = offsetof ( typeof ( efi_pe_header ), nt ),
+ },
+ .nt = {
+ .Signature = EFI_IMAGE_NT_SIGNATURE,
+ .FileHeader = {
+#if defined(EFI_TARGET_IA32)
+ .Machine = EFI_IMAGE_MACHINE_IA32,
+#elif defined(EFI_TARGET_X64)
+ .Machine = EFI_IMAGE_MACHINE_X64,
+#endif
+ .TimeDateStamp = 0x10d1a884,
+ .SizeOfOptionalHeader =
+ sizeof ( efi_pe_header.nt.OptionalHeader ),
+ .Characteristics = ( EFI_IMAGE_FILE_DLL |
+#if defined(EFI_TARGET_IA32)
+ EFI_IMAGE_FILE_32BIT_MACHINE |
+#endif
+ EFI_IMAGE_FILE_EXECUTABLE_IMAGE ),
+ },
+ .OptionalHeader = {
+#if defined(EFI_TARGET_IA32)
+ .Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC,
+#elif defined(EFI_TARGET_X64)
+ .Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC,
+#endif
+ .SectionAlignment = EFI_FILE_ALIGN,
+ .FileAlignment = EFI_FILE_ALIGN,
+ .SizeOfImage = sizeof ( efi_pe_header ),
+ .SizeOfHeaders = sizeof ( efi_pe_header ),
+ .NumberOfRvaAndSizes =
+ EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES,
+ },
+ },
+};
+
+/** Command-line options */
+struct options {
+ unsigned int subsystem;
+};
+
+/**
+ * Allocate memory
+ *
+ * @v len Length of memory to allocate
+ * @ret ptr Pointer to allocated memory
+ */
+static void * xmalloc ( size_t len ) {
+ void *ptr;
+
+ ptr = malloc ( len );
+ if ( ! ptr ) {
+ eprintf ( "Could not allocate %zd bytes\n", len );
+ exit ( 1 );
+ }
+
+ return ptr;
+}
+
+/**
+ * Align section within PE file
+ *
+ * @v offset Unaligned offset
+ * @ret aligned_offset Aligned offset
+ */
+static unsigned long efi_file_align ( unsigned long offset ) {
+ return ( ( offset + EFI_FILE_ALIGN - 1 ) & ~( EFI_FILE_ALIGN - 1 ) );
+}
+
+/**
+ * Generate entry in PE relocation table
+ *
+ * @v pe_reltab PE relocation table
+ * @v rva RVA
+ * @v size Size of relocation entry
+ */
+static void generate_pe_reloc ( struct pe_relocs **pe_reltab,
+ unsigned long rva, size_t size ) {
+ unsigned long start_rva;
+ uint16_t reloc;
+ struct pe_relocs *pe_rel;
+ uint16_t *relocs;
+
+ /* Construct */
+ start_rva = ( rva & ~0xfff );
+ reloc = ( rva & 0xfff );
+ switch ( size ) {
+ case 8:
+ reloc |= 0xa000;
+ break;
+ case 4:
+ reloc |= 0x3000;
+ break;
+ case 2:
+ reloc |= 0x2000;
+ break;
+ default:
+ eprintf ( "Unsupported relocation size %zd\n", size );
+ exit ( 1 );
+ }
+
+ /* Locate or create PE relocation table */
+ for ( pe_rel = *pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
+ if ( pe_rel->start_rva == start_rva )
+ break;
+ }
+ if ( ! pe_rel ) {
+ pe_rel = xmalloc ( sizeof ( *pe_rel ) );
+ memset ( pe_rel, 0, sizeof ( *pe_rel ) );
+ pe_rel->next = *pe_reltab;
+ *pe_reltab = pe_rel;
+ pe_rel->start_rva = start_rva;
+ }
+
+ /* Expand relocation list if necessary */
+ if ( pe_rel->used_relocs < pe_rel->total_relocs ) {
+ relocs = pe_rel->relocs;
+ } else {
+ pe_rel->total_relocs = ( pe_rel->total_relocs ?
+ ( pe_rel->total_relocs * 2 ) : 256 );
+ relocs = xmalloc ( pe_rel->total_relocs *
+ sizeof ( pe_rel->relocs[0] ) );
+ memset ( relocs, 0,
+ pe_rel->total_relocs * sizeof ( pe_rel->relocs[0] ) );
+ memcpy ( relocs, pe_rel->relocs,
+ pe_rel->used_relocs * sizeof ( pe_rel->relocs[0] ) );
+ free ( pe_rel->relocs );
+ pe_rel->relocs = relocs;
+ }
+
+ /* Store relocation */
+ pe_rel->relocs[ pe_rel->used_relocs++ ] = reloc;
+}
+
+/**
+ * Calculate size of binary PE relocation table
+ *
+ * @v pe_reltab PE relocation table
+ * @v buffer Buffer to contain binary table, or NULL
+ * @ret size Size of binary table
+ */
+static size_t output_pe_reltab ( struct pe_relocs *pe_reltab,
+ void *buffer ) {
+ struct pe_relocs *pe_rel;
+ unsigned int num_relocs;
+ size_t size;
+ size_t total_size = 0;
+
+ for ( pe_rel = pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
+ num_relocs = ( ( pe_rel->used_relocs + 1 ) & ~1 );
+ size = ( sizeof ( uint32_t ) /* VirtualAddress */ +
+ sizeof ( uint32_t ) /* SizeOfBlock */ +
+ ( num_relocs * sizeof ( uint16_t ) ) );
+ if ( buffer ) {
+ *( (uint32_t *) ( buffer + total_size + 0 ) )
+ = pe_rel->start_rva;
+ *( (uint32_t *) ( buffer + total_size + 4 ) ) = size;
+ memcpy ( ( buffer + total_size + 8 ), pe_rel->relocs,
+ ( num_relocs * sizeof ( uint16_t ) ) );
+ }
+ total_size += size;
+ }
+
+ return total_size;
+}
+
+/**
+ * Open input BFD file
+ *
+ * @v filename File name
+ * @ret ibfd BFD file
+ */
+static bfd * open_input_bfd ( const char *filename ) {
+ bfd *bfd;
+
+ /* Open the file */
+ bfd = bfd_openr ( filename, NULL );
+ if ( ! bfd ) {
+ eprintf ( "Cannot open %s: ", filename );
+ bfd_perror ( NULL );
+ exit ( 1 );
+ }
+
+ /* The call to bfd_check_format() must be present, otherwise
+ * we get a segfault from later BFD calls.
+ */
+ if ( ! bfd_check_format ( bfd, bfd_object ) ) {
+ eprintf ( "%s is not an object file: ", filename );
+ bfd_perror ( NULL );
+ exit ( 1 );
+ }
+
+ return bfd;
+}
+
+/**
+ * Read symbol table
+ *
+ * @v bfd BFD file
+ */
+static asymbol ** read_symtab ( bfd *bfd ) {
+ long symtab_size;
+ asymbol **symtab;
+ long symcount;
+
+ /* Get symbol table size */
+ symtab_size = bfd_get_symtab_upper_bound ( bfd );
+ if ( symtab_size < 0 ) {
+ bfd_perror ( "Could not get symbol table upper bound" );
+ exit ( 1 );
+ }
+
+ /* Allocate and read symbol table */
+ symtab = xmalloc ( symtab_size );
+ symcount = bfd_canonicalize_symtab ( bfd, symtab );
+ if ( symcount < 0 ) {
+ bfd_perror ( "Cannot read symbol table" );
+ exit ( 1 );
+ }
+
+ return symtab;
+}
+
+/**
+ * Read relocation table
+ *
+ * @v bfd BFD file
+ * @v symtab Symbol table
+ * @v section Section
+ * @v symtab Symbol table
+ * @ret reltab Relocation table
+ */
+static arelent ** read_reltab ( bfd *bfd, asymbol **symtab,
+ asection *section ) {
+ long reltab_size;
+ arelent **reltab;
+ long numrels;
+
+ /* Get relocation table size */
+ reltab_size = bfd_get_reloc_upper_bound ( bfd, section );
+ if ( reltab_size < 0 ) {
+ bfd_perror ( "Could not get relocation table upper bound" );
+ exit ( 1 );
+ }
+
+ /* Allocate and read relocation table */
+ reltab = xmalloc ( reltab_size );
+ numrels = bfd_canonicalize_reloc ( bfd, section, reltab, symtab );
+ if ( numrels < 0 ) {
+ bfd_perror ( "Cannot read relocation table" );
+ exit ( 1 );
+ }
+
+ return reltab;
+}
+
+/**
+ * Process section
+ *
+ * @v bfd BFD file
+ * @v pe_header PE file header
+ * @v section Section
+ * @ret new New PE section
+ */
+static struct pe_section * process_section ( bfd *bfd,
+ struct pe_header *pe_header,
+ asection *section ) {
+ struct pe_section *new;
+ size_t section_memsz;
+ size_t section_filesz;
+ unsigned long flags = bfd_get_section_flags ( bfd, section );
+ unsigned long code_start;
+ unsigned long code_end;
+ unsigned long data_start;
+ unsigned long data_mid;
+ unsigned long data_end;
+ unsigned long start;
+ unsigned long end;
+ unsigned long *applicable_start;
+ unsigned long *applicable_end;
+
+ /* Extract current RVA limits from file header */
+ code_start = pe_header->nt.OptionalHeader.BaseOfCode;
+ code_end = ( code_start + pe_header->nt.OptionalHeader.SizeOfCode );
+#if defined(EFI_TARGET_IA32)
+ data_start = pe_header->nt.OptionalHeader.BaseOfData;
+#elif defined(EFI_TARGET_X64)
+ data_start = code_end;
+#endif
+ data_mid = ( data_start +
+ pe_header->nt.OptionalHeader.SizeOfInitializedData );
+ data_end = ( data_mid +
+ pe_header->nt.OptionalHeader.SizeOfUninitializedData );
+
+ /* Allocate PE section */
+ section_memsz = bfd_section_size ( bfd, section );
+ section_filesz = ( ( flags & SEC_LOAD ) ?
+ efi_file_align ( section_memsz ) : 0 );
+ new = xmalloc ( sizeof ( *new ) + section_filesz );
+ memset ( new, 0, sizeof ( *new ) + section_filesz );
+
+ /* Fill in section header details */
+ strncpy ( ( char * ) new->hdr.Name, section->name,
+ sizeof ( new->hdr.Name ) );
+ new->hdr.Misc.VirtualSize = section_memsz;
+ new->hdr.VirtualAddress = bfd_get_section_vma ( bfd, section );
+ new->hdr.SizeOfRawData = section_filesz;
+
+ /* Fill in section characteristics and update RVA limits */
+ if ( flags & SEC_CODE ) {
+ /* .text-type section */
+ new->hdr.Characteristics =
+ ( EFI_IMAGE_SCN_CNT_CODE |
+ EFI_IMAGE_SCN_MEM_NOT_PAGED |
+ EFI_IMAGE_SCN_MEM_EXECUTE |
+ EFI_IMAGE_SCN_MEM_READ );
+ applicable_start = &code_start;
+ applicable_end = &code_end;
+ } else if ( flags & SEC_DATA ) {
+ /* .data-type section */
+ new->hdr.Characteristics =
+ ( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
+ EFI_IMAGE_SCN_MEM_NOT_PAGED |
+ EFI_IMAGE_SCN_MEM_READ |
+ EFI_IMAGE_SCN_MEM_WRITE );
+ applicable_start = &data_start;
+ applicable_end = &data_mid;
+ } else if ( flags & SEC_READONLY ) {
+ /* .rodata-type section */
+ new->hdr.Characteristics =
+ ( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
+ EFI_IMAGE_SCN_MEM_NOT_PAGED |
+ EFI_IMAGE_SCN_MEM_READ );
+ applicable_start = &data_start;
+ applicable_end = &data_mid;
+ } else if ( ! ( flags & SEC_LOAD ) ) {
+ /* .bss-type section */
+ new->hdr.Characteristics =
+ ( EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA |
+ EFI_IMAGE_SCN_MEM_NOT_PAGED |
+ EFI_IMAGE_SCN_MEM_READ |
+ EFI_IMAGE_SCN_MEM_WRITE );
+ applicable_start = &data_mid;
+ applicable_end = &data_end;
+ } else {
+ eprintf ( "Unrecognised characteristics %#lx for section %s\n",
+ flags, section->name );
+ exit ( 1 );
+ }
+
+ /* Copy in section contents */
+ if ( flags & SEC_LOAD ) {
+ if ( ! bfd_get_section_contents ( bfd, section, new->contents,
+ 0, section_memsz ) ) {
+ eprintf ( "Cannot read section %s: ", section->name );
+ bfd_perror ( NULL );
+ exit ( 1 );
+ }
+ }
+
+ /* Update RVA limits */
+ start = new->hdr.VirtualAddress;
+ end = ( start + new->hdr.Misc.VirtualSize );
+ if ( ( ! *applicable_start ) || ( *applicable_start >= start ) )
+ *applicable_start = start;
+ if ( *applicable_end < end )
+ *applicable_end = end;
+ if ( data_start < code_end )
+ data_start = code_end;
+ if ( data_mid < data_start )
+ data_mid = data_start;
+ if ( data_end < data_mid )
+ data_end = data_mid;
+
+ /* Write RVA limits back to file header */
+ pe_header->nt.OptionalHeader.BaseOfCode = code_start;
+ pe_header->nt.OptionalHeader.SizeOfCode = ( code_end - code_start );
+#if defined(EFI_TARGET_IA32)
+ pe_header->nt.OptionalHeader.BaseOfData = data_start;
+#endif
+ pe_header->nt.OptionalHeader.SizeOfInitializedData =
+ ( data_mid - data_start );
+ pe_header->nt.OptionalHeader.SizeOfUninitializedData =
+ ( data_end - data_mid );
+
+ /* Update remaining file header fields */
+ pe_header->nt.FileHeader.NumberOfSections++;
+ pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( new->hdr );
+ pe_header->nt.OptionalHeader.SizeOfImage =
+ efi_file_align ( data_end );
+
+ return new;
+}
+
+/**
+ * Process relocation record
+ *
+ * @v bfd BFD file
+ * @v section Section
+ * @v rel Relocation entry
+ * @v pe_reltab PE relocation table to fill in
+ */
+static void process_reloc ( bfd *bfd __attribute__ (( unused )),
+ asection *section, arelent *rel,
+ struct pe_relocs **pe_reltab ) {
+ reloc_howto_type *howto = rel->howto;
+ asymbol *sym = *(rel->sym_ptr_ptr);
+ unsigned long offset = ( bfd_get_section_vma ( bfd, section ) +
+ rel->address );
+
+ if ( bfd_is_abs_section ( sym->section ) ) {
+ /* Skip absolute symbols; the symbol value won't
+ * change when the object is loaded.
+ */
+ } else if ( strcmp ( howto->name, "R_X86_64_64" ) == 0 ) {
+ /* Generate an 8-byte PE relocation */
+ generate_pe_reloc ( pe_reltab, offset, 8 );
+ } else if ( ( strcmp ( howto->name, "R_386_32" ) == 0 ) ||
+ ( strcmp ( howto->name, "R_X86_64_32" ) == 0 ) ) {
+ /* Generate a 4-byte PE relocation */
+ generate_pe_reloc ( pe_reltab, offset, 4 );
+ } else if ( strcmp ( howto->name, "R_386_16" ) == 0 ) {
+ /* Generate a 2-byte PE relocation */
+ generate_pe_reloc ( pe_reltab, offset, 2 );
+ } else if ( ( strcmp ( howto->name, "R_386_PC32" ) == 0 ) ||
+ ( strcmp ( howto->name, "R_X86_64_PC32" ) == 0 ) ) {
+ /* Skip PC-relative relocations; all relative offsets
+ * remain unaltered when the object is loaded.
+ */
+ } else {
+ eprintf ( "Unrecognised relocation type %s\n", howto->name );
+ exit ( 1 );
+ }
+}
+
+/**
+ * Create relocations section
+ *
+ * @v pe_header PE file header
+ * @v pe_reltab PE relocation table
+ * @ret section Relocation section
+ */
+static struct pe_section *
+create_reloc_section ( struct pe_header *pe_header,
+ struct pe_relocs *pe_reltab ) {
+ struct pe_section *reloc;
+ size_t section_memsz;
+ size_t section_filesz;
+ EFI_IMAGE_DATA_DIRECTORY *relocdir;
+
+ /* Allocate PE section */
+ section_memsz = output_pe_reltab ( pe_reltab, NULL );
+ section_filesz = efi_file_align ( section_memsz );
+ reloc = xmalloc ( sizeof ( *reloc ) + section_filesz );
+ memset ( reloc, 0, sizeof ( *reloc ) + section_filesz );
+
+ /* Fill in section header details */
+ strncpy ( ( char * ) reloc->hdr.Name, ".reloc",
+ sizeof ( reloc->hdr.Name ) );
+ reloc->hdr.Misc.VirtualSize = section_memsz;
+ reloc->hdr.VirtualAddress = pe_header->nt.OptionalHeader.SizeOfImage;
+ reloc->hdr.SizeOfRawData = section_filesz;
+ reloc->hdr.Characteristics = ( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
+ EFI_IMAGE_SCN_MEM_NOT_PAGED |
+ EFI_IMAGE_SCN_MEM_READ );
+
+ /* Copy in section contents */
+ output_pe_reltab ( pe_reltab, reloc->contents );
+
+ /* Update file header details */
+ pe_header->nt.FileHeader.NumberOfSections++;
+ pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( reloc->hdr );
+ pe_header->nt.OptionalHeader.SizeOfImage += section_filesz;
+ relocdir = &(pe_header->nt.OptionalHeader.DataDirectory
+ [EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]);
+ relocdir->VirtualAddress = reloc->hdr.VirtualAddress;
+ relocdir->Size = reloc->hdr.Misc.VirtualSize;
+
+ return reloc;
+}
+
+/**
+ * Create debug section
+ *
+ * @v pe_header PE file header
+ * @ret section Debug section
+ */
+static struct pe_section *
+create_debug_section ( struct pe_header *pe_header, const char *filename ) {
+ struct pe_section *debug;
+ size_t section_memsz;
+ size_t section_filesz;
+ EFI_IMAGE_DATA_DIRECTORY *debugdir;
+ struct {
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY debug;
+ EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY rsds;
+ char name[ strlen ( filename ) + 1 ];
+ } *contents;
+
+ /* Allocate PE section */
+ section_memsz = sizeof ( *contents );
+ section_filesz = efi_file_align ( section_memsz );
+ debug = xmalloc ( sizeof ( *debug ) + section_filesz );
+ memset ( debug, 0, sizeof ( *debug ) + section_filesz );
+ contents = ( void * ) debug->contents;
+
+ /* Fill in section header details */
+ strncpy ( ( char * ) debug->hdr.Name, ".debug",
+ sizeof ( debug->hdr.Name ) );
+ debug->hdr.Misc.VirtualSize = section_memsz;
+ debug->hdr.VirtualAddress = pe_header->nt.OptionalHeader.SizeOfImage;
+ debug->hdr.SizeOfRawData = section_filesz;
+ debug->hdr.Characteristics = ( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
+ EFI_IMAGE_SCN_MEM_NOT_PAGED |
+ EFI_IMAGE_SCN_MEM_READ );
+
+ /* Create section contents */
+ contents->debug.TimeDateStamp = 0x10d1a884;
+ contents->debug.Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;
+ contents->debug.SizeOfData =
+ ( sizeof ( *contents ) - sizeof ( contents->debug ) );
+ contents->debug.RVA = ( debug->hdr.VirtualAddress +
+ offsetof ( typeof ( *contents ), rsds ) );
+ contents->rsds.Signature = CODEVIEW_SIGNATURE_RSDS;
+ snprintf ( contents->name, sizeof ( contents->name ), "%s",
+ filename );
+
+ /* Update file header details */
+ pe_header->nt.FileHeader.NumberOfSections++;
+ pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( debug->hdr );
+ pe_header->nt.OptionalHeader.SizeOfImage += section_filesz;
+ debugdir = &(pe_header->nt.OptionalHeader.DataDirectory
+ [EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+ debugdir->VirtualAddress = debug->hdr.VirtualAddress;
+ debugdir->Size = debug->hdr.Misc.VirtualSize;
+
+ return debug;
+}
+
+/**
+ * Write out PE file
+ *
+ * @v pe_header PE file header
+ * @v pe_sections List of PE sections
+ * @v pe Output file
+ */
+static void write_pe_file ( struct pe_header *pe_header,
+ struct pe_section *pe_sections,
+ FILE *pe ) {
+ struct pe_section *section;
+ unsigned long fpos = 0;
+
+ /* Assign raw data pointers */
+ fpos = efi_file_align ( pe_header->nt.OptionalHeader.SizeOfHeaders );
+ for ( section = pe_sections ; section ; section = section->next ) {
+ if ( section->hdr.SizeOfRawData ) {
+ section->hdr.PointerToRawData = fpos;
+ fpos += section->hdr.SizeOfRawData;
+ fpos = efi_file_align ( fpos );
+ }
+ }
+
+ /* Write file header */
+ if ( fwrite ( pe_header, sizeof ( *pe_header ), 1, pe ) != 1 ) {
+ perror ( "Could not write PE header" );
+ exit ( 1 );
+ }
+
+ /* Write section headers */
+ for ( section = pe_sections ; section ; section = section->next ) {
+ if ( fwrite ( &section->hdr, sizeof ( section->hdr ),
+ 1, pe ) != 1 ) {
+ perror ( "Could not write section header" );
+ exit ( 1 );
+ }
+ }
+
+ /* Write sections */
+ for ( section = pe_sections ; section ; section = section->next ) {
+ if ( fseek ( pe, section->hdr.PointerToRawData,
+ SEEK_SET ) != 0 ) {
+ eprintf ( "Could not seek to %x: %s\n",
+ section->hdr.PointerToRawData,
+ strerror ( errno ) );
+ exit ( 1 );
+ }
+ if ( section->hdr.SizeOfRawData &&
+ ( fwrite ( section->contents, section->hdr.SizeOfRawData,
+ 1, pe ) != 1 ) ) {
+ eprintf ( "Could not write section %.8s: %s\n",
+ section->hdr.Name, strerror ( errno ) );
+ exit ( 1 );
+ }
+ }
+}
+
+/**
+ * Convert ELF to PE
+ *
+ * @v elf_name ELF file name
+ * @v pe_name PE file name
+ */
+static void elf2pe ( const char *elf_name, const char *pe_name,
+ struct options *opts ) {
+ char pe_name_tmp[ strlen ( pe_name ) + 1 ];
+ bfd *bfd;
+ asymbol **symtab;
+ asection *section;
+ arelent **reltab;
+ arelent **rel;
+ struct pe_relocs *pe_reltab = NULL;
+ struct pe_section *pe_sections = NULL;
+ struct pe_section **next_pe_section = &pe_sections;
+ struct pe_header pe_header;
+ FILE *pe;
+
+ /* Create a modifiable copy of the PE name */
+ memcpy ( pe_name_tmp, pe_name, sizeof ( pe_name_tmp ) );
+
+ /* Open the file */
+ bfd = open_input_bfd ( elf_name );
+ symtab = read_symtab ( bfd );
+
+ /* Initialise the PE header */
+ memcpy ( &pe_header, &efi_pe_header, sizeof ( pe_header ) );
+ pe_header.nt.OptionalHeader.AddressOfEntryPoint =
+ bfd_get_start_address ( bfd );
+ pe_header.nt.OptionalHeader.Subsystem = opts->subsystem;
+
+ /* For each input section, build an output section and create
+ * the appropriate relocation records
+ */
+ for ( section = bfd->sections ; section ; section = section->next ) {
+ /* Discard non-allocatable sections */
+ if ( ! ( bfd_get_section_flags ( bfd, section ) & SEC_ALLOC ) )
+ continue;
+ /* Create output section */
+ *(next_pe_section) = process_section ( bfd, &pe_header,
+ section );
+ next_pe_section = &(*next_pe_section)->next;
+ /* Add relocations from this section */
+ reltab = read_reltab ( bfd, symtab, section );
+ for ( rel = reltab ; *rel ; rel++ )
+ process_reloc ( bfd, section, *rel, &pe_reltab );
+ free ( reltab );
+ }
+
+ /* Create the .reloc section */
+ *(next_pe_section) = create_reloc_section ( &pe_header, pe_reltab );
+ next_pe_section = &(*next_pe_section)->next;
+
+ /* Create the .reloc section */
+ *(next_pe_section) = create_debug_section ( &pe_header,
+ basename ( pe_name_tmp ) );
+ next_pe_section = &(*next_pe_section)->next;
+
+ /* Write out PE file */
+ pe = fopen ( pe_name, "w" );
+ if ( ! pe ) {
+ eprintf ( "Could not open %s for writing: %s\n",
+ pe_name, strerror ( errno ) );
+ exit ( 1 );
+ }
+ write_pe_file ( &pe_header, pe_sections, pe );
+ fclose ( pe );
+
+ /* Close BFD file */
+ bfd_close ( bfd );
+}
+
+/**
+ * Print help
+ *
+ * @v program_name Program name
+ */
+static void print_help ( const char *program_name ) {
+ eprintf ( "Syntax: %s [--subsystem=<number>] infile outfile\n",
+ program_name );
+}
+
+/**
+ * Parse command-line options
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v opts Options structure to populate
+ */
+static int parse_options ( const int argc, char **argv,
+ struct options *opts ) {
+ char *end;
+ int c;
+
+ while (1) {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "subsystem", required_argument, NULL, 's' },
+ { "help", 0, NULL, 'h' },
+ { 0, 0, 0, 0 }
+ };
+
+ if ( ( c = getopt_long ( argc, argv, "s:h",
+ long_options,
+ &option_index ) ) == -1 ) {
+ break;
+ }
+
+ switch ( c ) {
+ case 's':
+ opts->subsystem = strtoul ( optarg, &end, 0 );
+ if ( *end ) {
+ eprintf ( "Invalid subsytem \"%s\"\n",
+ optarg );
+ exit ( 2 );
+ }
+ break;
+ case 'h':
+ print_help ( argv[0] );
+ exit ( 0 );
+ case '?':
+ default:
+ exit ( 2 );
+ }
+ }
+ return optind;
+}
+
+int main ( int argc, char **argv ) {
+ struct options opts = {
+ .subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
+ };
+ int infile_index;
+ const char *infile;
+ const char *outfile;
+
+ /* Initialise libbfd */
+ bfd_init();
+
+ /* Parse command-line arguments */
+ infile_index = parse_options ( argc, argv, &opts );
+ if ( argc != ( infile_index + 2 ) ) {
+ print_help ( argv[0] );
+ exit ( 2 );
+ }
+ infile = argv[infile_index];
+ outfile = argv[infile_index + 1];
+
+ /* Convert file */
+ elf2pe ( infile, outfile, &opts );
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/util/fixrom.pl b/src/VBox/Devices/PC/ipxe/src/util/fixrom.pl
new file mode 100755
index 00000000..c3a31f41
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/fixrom.pl
@@ -0,0 +1,34 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+use strict;
+use warnings;
+
+use FindBin;
+use lib "$FindBin::Bin";
+use Option::ROM qw ( :all );
+
+my @romfiles = @ARGV;
+
+foreach my $romfile ( @romfiles ) {
+ my $rom = new Option::ROM;
+ $rom->load ( $romfile );
+ $rom->pnp_header->fix_checksum() if $rom->pnp_header;
+ $rom->fix_checksum();
+ $rom->save ( $romfile );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/util/fnrec.pl b/src/VBox/Devices/PC/ipxe/src/util/fnrec.pl
new file mode 100755
index 00000000..9a2b3d81
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/fnrec.pl
@@ -0,0 +1,145 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+=head1 NAME
+
+fnrec.pl
+
+=head1 SYNOPSIS
+
+fnrec.pl [options] bin/image.xxx < logfile
+
+Decode a function trace produced by building with FNREC=1
+
+Options:
+
+ -m,--max-depth=N Set maximum displayed function depth
+
+=cut
+
+use IPC::Open2;
+use Getopt::Long;
+use Pod::Usage;
+use strict;
+use warnings;
+
+use constant MAX_OPEN_BRACE => 10;
+use constant MAX_COMMON_BRACE => 3;
+use constant MAX_CLOSE_BRACE => 10;
+
+# Parse command-line options
+my $max_depth = 16;
+Getopt::Long::Configure ( 'bundling', 'auto_abbrev' );
+GetOptions (
+ 'help|h' => sub { pod2usage ( 1 ); },
+ 'max-depth|m=i' => sub { shift; $max_depth = shift; },
+) or die "Could not parse command-line options\n";
+pod2usage ( 1 ) unless @ARGV == 1;
+my $image = shift;
+my $elf = $image.".tmp";
+die "ELF file ".$elf." not found\n" unless -e $elf;
+
+# Start up addr2line
+my $addr2line_pid = open2 ( my $addr2line_out, my $addr2line_in,
+ "addr2line", "-f", "-e", $elf )
+ or die "Could not start addr2line: $!\n";
+
+# Translate address using addr2line
+sub addr2line {
+ my $address = shift;
+
+ print $addr2line_in $address."\n";
+ chomp ( my $name = <$addr2line_out> );
+ chomp ( my $file_line = <$addr2line_out> );
+ ( my $file, my $line ) = ( $file_line =~ /^(.*):(\d+)$/ );
+ $file =~ s/^.*\/src\///;
+ my $location = ( $line ? $file.":".$line." = ".$address : $address );
+ return ( $name, $location );
+}
+
+# Parse logfile
+my $depth = 0;
+my $depths = [];
+while ( my $line = <> ) {
+ chomp $line;
+ $line =~ s/\r//g;
+ ( my $called_fn, my $call_site, my $entry_count, my $exit_count ) =
+ ( $line =~ /^(0x[0-9a-f]+)\s+(0x[0-9a-f]+)\s+([0-9]+)\s+([0-9]+)$/ )
+ or print $line."\n" and next;
+
+ ( my $called_fn_name, undef ) = addr2line ( $called_fn );
+ ( undef, my $call_site_location ) = addr2line ( $call_site );
+ $entry_count = ( $entry_count + 0 );
+ $exit_count = ( $exit_count + 0 );
+
+ if ( $entry_count >= $exit_count ) {
+ #
+ # Function entry
+ #
+ my $text = "";
+ $text .= $called_fn_name." (from ".$call_site_location.")";
+ if ( $exit_count <= MAX_COMMON_BRACE ) {
+ $text .= " { }" x $exit_count;
+ } else {
+ $text .= " { } x ".$exit_count;
+ }
+ $entry_count -= $exit_count;
+ if ( $entry_count <= MAX_OPEN_BRACE ) {
+ $text .= " {" x $entry_count;
+ } else {
+ $text .= " { x ".$entry_count;
+ }
+ my $indent = " " x $depth;
+ print $indent.$text."\n";
+ $depth += $entry_count;
+ $depth = $max_depth if ( $depth > $max_depth );
+ push @$depths, ( { called_fn => $called_fn, call_site => $call_site } ) x
+ ( $depth - @$depths );
+ } else {
+ #
+ # Function exit
+ #
+ my $text = "";
+ if ( $entry_count <= MAX_COMMON_BRACE ) {
+ $text .= " { }" x $entry_count;
+ } else {
+ $text .= " { } x ".$entry_count;
+ }
+ $exit_count -= $entry_count;
+ if ( $exit_count <= MAX_CLOSE_BRACE ) {
+ $text .= " }" x $exit_count;
+ } else {
+ $text .= " } x ".$exit_count;
+ }
+ $depth -= $exit_count;
+ $depth = 0 if ( $depth < 0 );
+ if ( ( @$depths == 0 ) ||
+ ( $depths->[$depth]->{called_fn} ne $called_fn ) ||
+ ( $depths->[$depth]->{call_site} ne $call_site ) ) {
+ $text .= " (from ".$called_fn_name." to ".$call_site_location.")";
+ }
+ splice ( @$depths, $depth );
+ my $indent = " " x $depth;
+ print substr ( $indent.$text, 1 )."\n";
+ }
+}
+
+# Clean up addr2line
+close $addr2line_in;
+close $addr2line_out;
+waitpid ( $addr2line_pid, 0 );
diff --git a/src/VBox/Devices/PC/ipxe/src/util/geniso b/src/VBox/Devices/PC/ipxe/src/util/geniso
new file mode 100755
index 00000000..48ea2f2a
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/geniso
@@ -0,0 +1,72 @@
+#!/bin/bash
+#
+# Generate a isolinux ISO boot image
+#
+# geniso foo.iso foo.lkrn
+#
+# the ISO image is the first argument so that a list of .lkrn images
+# to include can be specified
+#
+case $# in
+0|1)
+ echo Usage: $0 foo.iso foo.lkrn ...
+ exit 1
+ ;;
+esac
+
+# This should be the default location of the isolinux.bin file
+isolinux_bin=${ISOLINUX_BIN:-util/isolinux.bin}
+if [ ! -r $isolinux_bin ]
+then
+ echo $0: $isolinux_bin not found, please install, or set ISOLINUX_BIN in arch/i386/Makefile correctly
+ exit 1
+fi
+
+# There should either be mkisofs or the compatible genisoimage program
+mkisofs=`which mkisofs genisoimage 2>/dev/null | head -n1`
+if [ -z $mkisofs ]
+then
+ echo $0: mkisofs or genisoimage not found, please install or set PATH
+ exit 1
+fi
+
+# isohybrid will be used if available
+isohybrid=`which isohybrid 2>/dev/null`
+
+out=$1
+shift
+dir=`mktemp -d bin/iso.dir.XXXXXX`
+cfg=$dir/isolinux.cfg
+cp -p $isolinux_bin $dir
+cat > $cfg <<EOF
+# These default options can be changed in the geniso script
+SAY iPXE ISO boot image
+TIMEOUT 30
+EOF
+first=
+for f
+do
+ if [ ! -r $f ]
+ then
+ echo $f does not exist, skipping 1>&2
+ continue
+ fi
+ b=$(basename $f)
+ g=${b%.lkrn}
+ g=${g//[^a-z0-9]}.krn
+ case "$first" in
+ "")
+ echo DEFAULT $b
+ ;;
+ esac
+ first=$g
+ echo LABEL $b
+ echo "" KERNEL $g
+ cp -p $f $dir/$g
+done >> $cfg
+$mkisofs -quiet -l -o $out -c boot.cat -b isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table $dir
+rm -fr $dir
+if [ -n "$isohybrid" ]
+then
+ $isohybrid $out >/dev/null
+fi
diff --git a/src/VBox/Devices/PC/ipxe/src/util/genkeymap.pl b/src/VBox/Devices/PC/ipxe/src/util/genkeymap.pl
new file mode 100755
index 00000000..6487cd79
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/genkeymap.pl
@@ -0,0 +1,237 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+=head1 NAME
+
+genkeymap.pl
+
+=head1 SYNOPSIS
+
+genkeymap.pl [options] <keymap name>
+
+Options:
+
+ -f,--from=<name> Set BIOS keymap name (default "us")
+ -h,--help Display brief help message
+ -v,--verbose Increase verbosity
+ -q,--quiet Decrease verbosity
+
+=cut
+
+# With reference to:
+#
+# http://gunnarwrobel.de/wiki/Linux-and-the-keyboard.html
+
+use Getopt::Long;
+use Pod::Usage;
+use strict;
+use warnings;
+
+use constant BIOS_KEYMAP => "us";
+use constant BKEYMAP_MAGIC => "bkeymap";
+use constant MAX_NR_KEYMAPS => 256;
+use constant NR_KEYS => 128;
+use constant KG_SHIFT => 0;
+use constant KG_ALTGR => 1;
+use constant KG_CTRL => 2;
+use constant KG_ALT => 3;
+use constant KG_SHIFTL => 4;
+use constant KG_KANASHIFT => 4;
+use constant KG_SHIFTR => 5;
+use constant KG_CTRLL => 6;
+use constant KG_CTRLR => 7;
+use constant KG_CAPSSHIFT => 8;
+use constant KT_LATIN => 0;
+use constant KT_FN => 1;
+use constant KT_SPEC => 2;
+use constant KT_PAD => 3;
+use constant KT_DEAD => 4;
+use constant KT_CONS => 5;
+use constant KT_CUR => 6;
+use constant KT_SHIFT => 7;
+use constant KT_META => 8;
+use constant KT_ASCII => 9;
+use constant KT_LOCK => 10;
+use constant KT_LETTER => 11;
+use constant KT_SLOCK => 12;
+use constant KT_SPKUP => 14;
+
+my $verbosity = 1;
+my $from_name = BIOS_KEYMAP;
+
+# Read named keymaps using "loadkeys -b"
+#
+sub read_keymaps {
+ my $name = shift;
+ my $keymaps = [];
+
+ # Generate binary keymap
+ open my $pipe, "-|", "loadkeys", "-b", $name
+ or die "Could not load keymap \"".$name."\": $!\n";
+
+ # Check magic
+ read $pipe, my $magic, length BKEYMAP_MAGIC
+ or die "Could not read from \"".$name."\": $!\n";
+ die "Bad magic value from \"".$name."\"\n"
+ unless $magic eq BKEYMAP_MAGIC;
+
+ # Read list of included keymaps
+ read $pipe, my $included, MAX_NR_KEYMAPS
+ or die "Could not read from \"".$name."\": $!\n";
+ my @included = unpack ( "C*", $included );
+ die "Missing or truncated keymap list from \"".$name."\"\n"
+ unless @included == MAX_NR_KEYMAPS;
+
+ # Read each keymap in turn
+ for ( my $keymap = 0 ; $keymap < MAX_NR_KEYMAPS ; $keymap++ ) {
+ if ( $included[$keymap] ) {
+ read $pipe, my $keysyms, ( NR_KEYS * 2 )
+ or die "Could not read from \"".$name."\": $!\n";
+ my @keysyms = unpack ( "S*", $keysyms );
+ die "Missing or truncated keymap ".$keymap." from \"".$name."\"\n"
+ unless @keysyms == NR_KEYS;
+ push @$keymaps, \@keysyms;
+ } else {
+ push @$keymaps, undef;
+ }
+ }
+
+ close $pipe;
+ return $keymaps;
+}
+
+# Translate keysym value to ASCII
+#
+sub keysym_to_ascii {
+ my $keysym = shift;
+
+ # Non-existent keysyms have no ASCII equivalent
+ return unless $keysym;
+
+ # Sanity check
+ if ( $keysym & 0xf000 ) {
+ warn "Unexpected keysym ".sprintf ( "0x%04x", $keysym )."\n";
+ return;
+ }
+
+ # Extract type and value
+ my $type = ( $keysym >> 8 );
+ my $value = ( $keysym & 0xff );
+
+ # Non-simple types have no ASCII equivalent
+ return unless ( ( $type == KT_LATIN ) || ( $type == KT_ASCII ) ||
+ ( $type == KT_LETTER ) );
+
+ # High-bit-set characters cannot be generated on a US keyboard
+ return if $value & 0x80;
+
+ return $value;
+}
+
+# Translate ASCII to descriptive name
+#
+sub ascii_to_name {
+ my $ascii = shift;
+
+ if ( $ascii == 0x5c ) {
+ return "'\\\\'";
+ } elsif ( $ascii == 0x27 ) {
+ return "'\\\''";
+ } elsif ( ( $ascii >= 0x20 ) && ( $ascii <= 0x7e ) ) {
+ return sprintf ( "'%c'", $ascii );
+ } elsif ( $ascii <= 0x1a ) {
+ return sprintf ( "Ctrl-%c", ( 0x40 + $ascii ) );
+ } else {
+ return sprintf ( "0x%02x", $ascii );
+ }
+}
+
+# Produce translation table between two keymaps
+#
+sub translate_keymaps {
+ my $from = shift;
+ my $to = shift;
+ my $map = {};
+
+ foreach my $keymap ( 0, 1 << KG_SHIFT, 1 << KG_CTRL ) {
+ for ( my $keycode = 0 ; $keycode < NR_KEYS ; $keycode++ ) {
+ my $from_ascii = keysym_to_ascii ( $from->[$keymap]->[$keycode] )
+ or next;
+ my $to_ascii = keysym_to_ascii ( $to->[$keymap]->[$keycode] )
+ or next;
+ my $new_map = ( ! exists $map->{$from_ascii} );
+ my $update_map =
+ ( $new_map || ( $keycode < $map->{$from_ascii}->{keycode} ) );
+ if ( ( $verbosity > 1 ) &&
+ ( ( $from_ascii != $to_ascii ) ||
+ ( $update_map && ! $new_map ) ) ) {
+ printf STDERR "In keymap %d: %s => %s%s\n", $keymap,
+ ascii_to_name ( $from_ascii ), ascii_to_name ( $to_ascii ),
+ ( $update_map ? ( $new_map ? "" : " (override)" )
+ : " (ignored)" );
+ }
+ if ( $update_map ) {
+ $map->{$from_ascii} = {
+ to_ascii => $to_ascii,
+ keycode => $keycode,
+ };
+ }
+ }
+ }
+ return { map { $_ => $map->{$_}->{to_ascii} } keys %$map };
+}
+
+# Parse command-line options
+Getopt::Long::Configure ( 'bundling', 'auto_abbrev' );
+GetOptions (
+ 'verbose|v+' => sub { $verbosity++; },
+ 'quiet|q+' => sub { $verbosity--; },
+ 'from|f=s' => sub { shift; $from_name = shift; },
+ 'help|h' => sub { pod2usage ( 1 ); },
+) or die "Could not parse command-line options\n";
+pod2usage ( 1 ) unless @ARGV == 1;
+my $to_name = shift;
+
+# Read and translate keymaps
+my $from = read_keymaps ( $from_name );
+my $to = read_keymaps ( $to_name );
+my $map = translate_keymaps ( $from, $to );
+
+# Generate output
+( my $to_name_c = $to_name ) =~ s/\W/_/g;
+printf "/** \@file\n";
+printf " *\n";
+printf " * \"".$to_name."\" keyboard mapping\n";
+printf " *\n";
+printf " * This file is automatically generated; do not edit\n";
+printf " *\n";
+printf " */\n";
+printf "\n";
+printf "FILE_LICENCE ( PUBLIC_DOMAIN );\n";
+printf "\n";
+printf "#include <ipxe/keymap.h>\n";
+printf "\n";
+printf "/** \"".$to_name."\" keyboard mapping */\n";
+printf "struct key_mapping ".$to_name_c."_mapping[] __keymap = {\n";
+foreach my $from_sym ( sort { $a <=> $b } keys %$map ) {
+ my $to_sym = $map->{$from_sym};
+ next if $from_sym == $to_sym;
+ printf "\t{ 0x%02x, 0x%02x },\t/* %s => %s */\n", $from_sym, $to_sym,
+ ascii_to_name ( $from_sym ), ascii_to_name ( $to_sym );
+}
+printf "};\n";
diff --git a/src/VBox/Devices/PC/ipxe/src/util/genliso b/src/VBox/Devices/PC/ipxe/src/util/genliso
new file mode 100755
index 00000000..184408ad
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/genliso
@@ -0,0 +1,74 @@
+#!/bin/bash
+#
+# Generate a legacy floppy emulation ISO boot image
+#
+# genliso foo.liso foo.lkrn bar.lkrn ...
+#
+# The .liso image filename is the first argument followed by
+# a list of .lkrn images include in .liso image
+
+case $# in
+0|1)
+ echo Usage: $0 foo.liso foo.lkrn ...
+ exit 1
+ ;;
+esac
+
+case "`mtools -V`" in
+Mtools\ version\ 3.9.9*|Mtools\ version\ 3.9.1[0-9]*|[mM]tools\ *\ [4-9].*)
+ ;;
+*)
+ echo Mtools version 3.9.9 or later is required
+ exit 1
+ ;;
+esac
+
+out=$1
+shift
+
+dir=`mktemp -d bin/liso.dir.XXXXXX`
+
+img=$dir/boot.img
+mformat -f 1440 -C -i $img ::
+
+cfg=$dir/syslinux.cfg
+cat > $cfg <<EOF
+# These default options can be changed in the genliso script
+SAY iPXE ISO boot image generated by genliso
+TIMEOUT 30
+EOF
+
+first=
+for f
+do
+ if [ ! -r $f ]
+ then
+ echo $f does not exist, skipping 1>&2
+ continue
+ fi
+ # shorten name for 8.3 filesystem
+ b=$(basename $f)
+ g=${b%.lkrn}
+ g=${g//[^a-z0-9]}
+ g=${g:0:8}.krn
+ case "$first" in
+ "")
+ echo DEFAULT $g
+ ;;
+ esac
+ first=$g
+ echo LABEL $b
+ echo "" KERNEL $g
+ mcopy -m -i $img $f ::$g
+done >> $cfg
+
+mcopy -i $img $cfg ::syslinux.cfg
+
+if ! syslinux $img
+then
+ exit 1
+fi
+
+mkisofs -q -o $out -c boot.cat -b boot.img $dir
+
+rm -fr $dir
diff --git a/src/VBox/Devices/PC/ipxe/src/util/gensdsk b/src/VBox/Devices/PC/ipxe/src/util/gensdsk
new file mode 100755
index 00000000..9e8361d4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/gensdsk
@@ -0,0 +1,65 @@
+#!/bin/bash
+#
+# Generate a syslinux floppy that loads a iPXE image
+#
+# gensdsk foo.sdsk foo.lkrn
+#
+# the floppy image is the first argument
+# followed by list of .lkrn images
+#
+
+case $# in
+0|1)
+ echo Usage: $0 foo.sdsk foo.lkrn ...
+ exit 1
+ ;;
+esac
+case "`mtools -V`" in
+Mtools\ version\ 3.9.9*|Mtools\ version\ 3.9.1[0-9]*|[mM]tools\ *\ [4-9].*)
+ ;;
+*)
+ echo Mtools version 3.9.9 or later is required
+ exit 1
+ ;;
+esac
+img=$1
+shift
+dir=`mktemp -d bin/sdsk.dir.XXXXXX`
+
+mformat -f 1440 -C -i $img ::
+cfg=$dir/syslinux.cfg
+cat > $cfg <<EOF
+
+# These default options can be changed in the gensdsk script
+TIMEOUT 30
+EOF
+first=
+for f
+do
+ if [ ! -r $f ]
+ then
+ echo $f does not exist, skipping 1>&2
+ continue
+ fi
+ # shorten name for 8.3 filesystem
+ b=$(basename $f)
+ g=${b%.lkrn}
+ g=${g//[^a-z0-9]}
+ g=${g:0:8}.krn
+ case "$first" in
+ "")
+ echo DEFAULT $g
+ ;;
+ esac
+ first=$g
+ echo LABEL $b
+ echo "" KERNEL $g
+ mcopy -m -i $img $f ::$g
+done >> $cfg
+mcopy -i $img $cfg ::syslinux.cfg
+if ! syslinux $img
+then
+ exit 1
+fi
+
+rm -fr $dir
diff --git a/src/VBox/Devices/PC/ipxe/src/util/get-pci-ids b/src/VBox/Devices/PC/ipxe/src/util/get-pci-ids
new file mode 100755
index 00000000..6501a7f7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/get-pci-ids
@@ -0,0 +1,135 @@
+#! /usr/bin/perl -w
+
+# get-pci-ids: extract pci vendor/device ids from linux net drivers
+
+# Copyright (C) 2003 Georg Baum <gbaum@users.sf.net>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+# Known bugs/limitations:
+# - Does not recognize all drivers because some require special cflags.
+# Fails also on some drivers that do belong to other architectures
+# than the one of the machine this script is running on.
+# This is currently not so important because all drivers that have an
+# Etherboot counterpart are recognized.
+
+
+use strict;
+use File::Basename "dirname";
+use POSIX "uname";
+
+# Where to find the kernel sources
+my $kernel_src = "/usr/src/linux";
+
+if($#ARGV >= 0) {
+ $kernel_src = shift;
+}
+
+# Sanity checks
+if($#ARGV >= 0) {
+ print STDERR "Too many arguments.\n";
+ print STDERR "Usage: get-pci-ids [path to kernel sources]\n";
+ print STDERR " /usr/src/linux is assumed if no path is given.\n";
+ exit 1;
+}
+
+unless(-f "$kernel_src/include/linux/version.h") {
+ print STDERR "Could not find $kernel_src/include/linux/version.h.\n";
+ print STDERR "$kernel_src is probably no Linux kernel source tree.\n";
+ exit 1;
+}
+
+# Flags that are needed to preprocess the drivers.
+# Some drivers need optimization
+my $cflags="-D__KERNEL__ -I$kernel_src/include -I$kernel_src/net/inet -O2";
+
+# The C preprocessor. It needs to spit out the preprocessed source on stdout.
+my $cpp="gcc -E";
+
+# List of drivers. We parse every .c file. It does not harm if it does not contain a driver.
+my @drivers = split /\s+/, `find $kernel_src/drivers/net -name '*.c' | sort`;
+
+# Kernel version
+my $version = `grep UTS_RELEASE $kernel_src/include/linux/version.h`;
+chomp $version;
+$version =~ s/\s*#define\s+UTS_RELEASE\s+"(\S+)".*$/$1/g;
+
+# Architecture
+my @uname = uname();
+
+
+# Print header
+print "# PCI vendor/device ids extracted from Linux $version on $uname[4] at " . gmtime() . "\n";
+
+my $driver;
+
+# Process the drivers
+foreach $driver (@drivers) {
+
+ # Preprocess to expand macros
+ my $command = "$cpp $cflags -I" . dirname($driver) . " $driver";
+ open DRIVER, "$command |" or die "Could not execute\n\"$command\".\n";
+
+ # Extract the pci_device_id structure
+ my $found = 0;
+ my $line = "";
+ my @lines;
+ while(<DRIVER>) {
+ if(/^\s*static\s+struct\s+pci_device_id/) {
+ # This file contains a driver. Print the name.
+ $driver =~ s!$kernel_src/drivers/net/!!g;
+ print "\n$driver\n";
+ $found = 1;
+ next;
+ }
+ if($found == 1){
+ if(/\};/ or /{\s*0\s*,?\s*}/) {
+ # End of struct
+ $found = 0;
+ } else {
+ chomp;
+ if(/\}\s*,?\s*\n?$/) {
+ # This line contains a full entry or the last part of it.
+ $_ = $line . $_;
+ $line = "";
+ s/[,\{\};\(\)]//g; # Strip punctuation
+ s/^\s+//g; # Eat whitespace at beginning of line
+ tr[A-Z][a-z]; # Convert to lowercase
+ # Push the vendor and device id to @lines if this line is not empty.
+ # We ignore everything else that might be there
+ my ($vendor_id, $device_id, $remainder) = split /\W+/, $_, 3;
+ push @lines, "$vendor_id $device_id\n" if($vendor_id && $device_id);
+ } else {
+ # This line does contain a partial entry. Remember it.
+ $line .= "$_ ";
+ }
+ }
+ }
+ }
+ close DRIVER; # No "or die", because $cpp fails on some files
+
+ # Now print out the sorted values
+ @lines = sort @lines;
+ my $lastline = "";
+ foreach(@lines) {
+ # Print each vendor/device id combination only once.
+ # Some drivers (e.g. e100) do contain subfamilies
+ print if($_ ne $lastline);
+ $lastline = $_;
+ }
+}
+
+
diff --git a/src/VBox/Devices/PC/ipxe/src/util/hijack.c b/src/VBox/Devices/PC/ipxe/src/util/hijack.c
new file mode 100644
index 00000000..ed89592b
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/hijack.c
@@ -0,0 +1,628 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <signal.h>
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <syslog.h>
+#include <getopt.h>
+#include <pcap.h>
+
+#define SNAPLEN 1600
+
+/*
+ * FIXME: is there a way to detect the version of the libpcap library?
+ * Version 0.9 has pcap_inject; version 0.8 doesn't, but both report
+ * their version number as 2.4.
+ */
+#define HAVE_PCAP_INJECT 0
+
+struct hijack {
+ pcap_t *pcap;
+ int fd;
+ int datalink;
+ int filtered;
+ unsigned long rx_count;
+ unsigned long tx_count;
+};
+
+struct hijack_listener {
+ struct sockaddr_un sun;
+ int fd;
+};
+
+struct hijack_options {
+ char interface[IF_NAMESIZE];
+ int daemonise;
+};
+
+static int daemonised = 0;
+
+static int signalled = 0;
+
+static void flag_signalled ( int signal __attribute__ (( unused )) ) {
+ signalled = 1;
+}
+
+#if ! HAVE_PCAP_INJECT
+/**
+ * Substitute for pcap_inject(), if this version of libpcap doesn't
+ * have it. Will almost certainly only work under Linux.
+ *
+ */
+int pcap_inject ( pcap_t *pcap, const void *data, size_t len ) {
+ int fd;
+ char *errbuf = pcap_geterr ( pcap );
+
+ fd = pcap_get_selectable_fd ( pcap );
+ if ( fd < 0 ) {
+ snprintf ( errbuf, PCAP_ERRBUF_SIZE,
+ "could not get file descriptor" );
+ return -1;
+ }
+ if ( write ( fd, data, len ) != len ) {
+ snprintf ( errbuf, PCAP_ERRBUF_SIZE,
+ "could not write data: %s", strerror ( errno ) );
+ return -1;
+ }
+ return len;
+}
+#endif /* ! HAVE_PCAP_INJECT */
+
+/**
+ * Log error message
+ *
+ */
+static __attribute__ (( format ( printf, 2, 3 ) )) void
+logmsg ( int level, const char *format, ... ) {
+ va_list ap;
+
+ va_start ( ap, format );
+ if ( daemonised ) {
+ vsyslog ( ( LOG_DAEMON | level ), format, ap );
+ } else {
+ vfprintf ( stderr, format, ap );
+ }
+ va_end ( ap );
+}
+
+/**
+ * Open pcap device
+ *
+ */
+static int hijack_open ( const char *interface, struct hijack *hijack ) {
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ /* Open interface via pcap */
+ errbuf[0] = '\0';
+ hijack->pcap = pcap_open_live ( interface, SNAPLEN, 1, 0, errbuf );
+ if ( ! hijack->pcap ) {
+ logmsg ( LOG_ERR, "Failed to open %s: %s\n",
+ interface, errbuf );
+ goto err;
+ }
+ if ( errbuf[0] )
+ logmsg ( LOG_WARNING, "Warning: %s\n", errbuf );
+
+ /* Set capture interface to non-blocking mode */
+ if ( pcap_setnonblock ( hijack->pcap, 1, errbuf ) < 0 ) {
+ logmsg ( LOG_ERR, "Could not make %s non-blocking: %s\n",
+ interface, errbuf );
+ goto err;
+ }
+
+ /* Get file descriptor for select() */
+ hijack->fd = pcap_get_selectable_fd ( hijack->pcap );
+ if ( hijack->fd < 0 ) {
+ logmsg ( LOG_ERR, "Cannot get selectable file descriptor "
+ "for %s\n", interface );
+ goto err;
+ }
+
+ /* Get link layer type */
+ hijack->datalink = pcap_datalink ( hijack->pcap );
+
+ return 0;
+
+ err:
+ if ( hijack->pcap )
+ pcap_close ( hijack->pcap );
+ return -1;
+}
+
+/**
+ * Close pcap device
+ *
+ */
+static void hijack_close ( struct hijack *hijack ) {
+ pcap_close ( hijack->pcap );
+}
+
+/**
+ * Install filter for hijacked connection
+ *
+ */
+static int hijack_install_filter ( struct hijack *hijack,
+ char *filter ) {
+ struct bpf_program program;
+
+ /* Compile filter */
+ if ( pcap_compile ( hijack->pcap, &program, filter, 1, 0 ) < 0 ) {
+ logmsg ( LOG_ERR, "could not compile filter \"%s\": %s\n",
+ filter, pcap_geterr ( hijack->pcap ) );
+ goto err_nofree;
+ }
+
+ /* Install filter */
+ if ( pcap_setfilter ( hijack->pcap, &program ) < 0 ) {
+ logmsg ( LOG_ERR, "could not install filter \"%s\": %s\n",
+ filter, pcap_geterr ( hijack->pcap ) );
+ goto err;
+ }
+
+ logmsg ( LOG_INFO, "using filter \"%s\"\n", filter );
+
+ pcap_freecode ( &program );
+ return 0;
+
+ err:
+ pcap_freecode ( &program );
+ err_nofree:
+ return -1;
+}
+
+/**
+ * Set up filter for hijacked ethernet connection
+ *
+ */
+static int hijack_filter_ethernet ( struct hijack *hijack, const char *buf,
+ size_t len ) {
+ char filter[55]; /* see format string */
+ struct ether_header *ether_header = ( struct ether_header * ) buf;
+ unsigned char *hwaddr = ether_header->ether_shost;
+
+ if ( len < sizeof ( *ether_header ) )
+ return -1;
+
+ snprintf ( filter, sizeof ( filter ), "broadcast or multicast or "
+ "ether host %02x:%02x:%02x:%02x:%02x:%02x", hwaddr[0],
+ hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5] );
+
+ return hijack_install_filter ( hijack, filter );
+}
+
+/**
+ * Set up filter for hijacked connection
+ *
+ */
+static int hijack_filter ( struct hijack *hijack, const char *buf,
+ size_t len ) {
+ switch ( hijack->datalink ) {
+ case DLT_EN10MB:
+ return hijack_filter_ethernet ( hijack, buf, len );
+ default:
+ logmsg ( LOG_ERR, "unsupported protocol %s: cannot filter\n",
+ ( pcap_datalink_val_to_name ( hijack->datalink ) ?
+ pcap_datalink_val_to_name ( hijack->datalink ) :
+ "UNKNOWN" ) );
+ /* Return success so we don't get called again */
+ return 0;
+ }
+}
+
+/**
+ * Forward data from hijacker
+ *
+ */
+static ssize_t forward_from_hijacker ( struct hijack *hijack, int fd ) {
+ char buf[SNAPLEN];
+ ssize_t len;
+
+ /* Read packet from hijacker */
+ len = read ( fd, buf, sizeof ( buf ) );
+ if ( len < 0 ) {
+ logmsg ( LOG_ERR, "read from hijacker failed: %s\n",
+ strerror ( errno ) );
+ return -1;
+ }
+ if ( len == 0 )
+ return 0;
+
+ /* Set up filter if not already in place */
+ if ( ! hijack->filtered ) {
+ if ( hijack_filter ( hijack, buf, len ) == 0 )
+ hijack->filtered = 1;
+ }
+
+ /* Transmit packet to network */
+ if ( pcap_inject ( hijack->pcap, buf, len ) != len ) {
+ logmsg ( LOG_ERR, "write to hijacked port failed: %s\n",
+ pcap_geterr ( hijack->pcap ) );
+ return -1;
+ }
+
+ hijack->tx_count++;
+ return len;
+};
+
+/**
+ * Forward data to hijacker
+ *
+ */
+static ssize_t forward_to_hijacker ( int fd, struct hijack *hijack ) {
+ struct pcap_pkthdr *pkt_header;
+ const unsigned char *pkt_data;
+ ssize_t len;
+
+ /* Receive packet from network */
+ if ( pcap_next_ex ( hijack->pcap, &pkt_header, &pkt_data ) < 0 ) {
+ logmsg ( LOG_ERR, "read from hijacked port failed: %s\n",
+ pcap_geterr ( hijack->pcap ) );
+ return -1;
+ }
+ if ( pkt_header->caplen != pkt_header->len ) {
+ logmsg ( LOG_ERR, "read partial packet (%d of %d bytes)\n",
+ pkt_header->caplen, pkt_header->len );
+ return -1;
+ }
+ if ( pkt_header->caplen == 0 )
+ return 0;
+ len = pkt_header->caplen;
+
+ /* Write packet to hijacker */
+ if ( write ( fd, pkt_data, len ) != len ) {
+ logmsg ( LOG_ERR, "write to hijacker failed: %s\n",
+ strerror ( errno ) );
+ return -1;
+ }
+
+ hijack->rx_count++;
+ return len;
+};
+
+
+/**
+ * Run hijacker
+ *
+ */
+static int run_hijacker ( const char *interface, int fd ) {
+ struct hijack hijack;
+ fd_set fdset;
+ int max_fd;
+ ssize_t len;
+
+ logmsg ( LOG_INFO, "new connection for %s\n", interface );
+
+ /* Open connection to network */
+ memset ( &hijack, 0, sizeof ( hijack ) );
+ if ( hijack_open ( interface, &hijack ) < 0 )
+ goto err;
+
+ /* Do the forwarding */
+ max_fd = ( ( fd > hijack.fd ) ? fd : hijack.fd );
+ while ( 1 ) {
+ /* Wait for available data */
+ FD_ZERO ( &fdset );
+ FD_SET ( fd, &fdset );
+ FD_SET ( hijack.fd, &fdset );
+ if ( select ( ( max_fd + 1 ), &fdset, NULL, NULL, 0 ) < 0 ) {
+ logmsg ( LOG_ERR, "select failed: %s\n",
+ strerror ( errno ) );
+ goto err;
+ }
+ if ( FD_ISSET ( fd, &fdset ) ) {
+ len = forward_from_hijacker ( &hijack, fd );
+ if ( len < 0 )
+ goto err;
+ if ( len == 0 )
+ break;
+ }
+ if ( FD_ISSET ( hijack.fd, &fdset ) ) {
+ len = forward_to_hijacker ( fd, &hijack );
+ if ( len < 0 )
+ goto err;
+ if ( len == 0 )
+ break;
+ }
+ }
+
+ hijack_close ( &hijack );
+ logmsg ( LOG_INFO, "closed connection for %s\n", interface );
+ logmsg ( LOG_INFO, "received %ld packets, sent %ld packets\n",
+ hijack.rx_count, hijack.tx_count );
+
+ return 0;
+
+ err:
+ if ( hijack.pcap )
+ hijack_close ( &hijack );
+ return -1;
+}
+
+/**
+ * Open listener socket
+ *
+ */
+static int open_listener ( const char *interface,
+ struct hijack_listener *listener ) {
+
+ /* Create socket */
+ listener->fd = socket ( PF_UNIX, SOCK_SEQPACKET, 0 );
+ if ( listener->fd < 0 ) {
+ logmsg ( LOG_ERR, "Could not create socket: %s\n",
+ strerror ( errno ) );
+ goto err;
+ }
+
+ /* Bind to local filename */
+ listener->sun.sun_family = AF_UNIX,
+ snprintf ( listener->sun.sun_path, sizeof ( listener->sun.sun_path ),
+ "/var/run/hijack-%s", interface );
+ if ( bind ( listener->fd, ( struct sockaddr * ) &listener->sun,
+ sizeof ( listener->sun ) ) < 0 ) {
+ logmsg ( LOG_ERR, "Could not bind socket to %s: %s\n",
+ listener->sun.sun_path, strerror ( errno ) );
+ goto err;
+ }
+
+ /* Set as a listening socket */
+ if ( listen ( listener->fd, 0 ) < 0 ) {
+ logmsg ( LOG_ERR, "Could not listen to %s: %s\n",
+ listener->sun.sun_path, strerror ( errno ) );
+ goto err;
+ }
+
+ return 0;
+
+ err:
+ if ( listener->fd >= 0 )
+ close ( listener->fd );
+ return -1;
+}
+
+/**
+ * Listen on listener socket
+ *
+ */
+static int listen_for_hijackers ( struct hijack_listener *listener,
+ const char *interface ) {
+ int fd;
+ pid_t child;
+ int rc;
+
+ logmsg ( LOG_INFO, "Listening on %s\n", listener->sun.sun_path );
+
+ while ( ! signalled ) {
+ /* Accept new connection, interruptibly */
+ siginterrupt ( SIGINT, 1 );
+ siginterrupt ( SIGHUP, 1 );
+ fd = accept ( listener->fd, NULL, 0 );
+ siginterrupt ( SIGINT, 0 );
+ siginterrupt ( SIGHUP, 0 );
+ if ( fd < 0 ) {
+ if ( errno == EINTR ) {
+ continue;
+ } else {
+ logmsg ( LOG_ERR, "accept failed: %s\n",
+ strerror ( errno ) );
+ goto err;
+ }
+ }
+
+ /* Fork child process */
+ child = fork();
+ if ( child < 0 ) {
+ logmsg ( LOG_ERR, "fork failed: %s\n",
+ strerror ( errno ) );
+ goto err;
+ }
+ if ( child == 0 ) {
+ /* I am the child; run the hijacker */
+ rc = run_hijacker ( interface, fd );
+ close ( fd );
+ exit ( rc );
+ }
+
+ close ( fd );
+ }
+
+ logmsg ( LOG_INFO, "Stopped listening on %s\n",
+ listener->sun.sun_path );
+ return 0;
+
+ err:
+ if ( fd >= 0 )
+ close ( fd );
+ return -1;
+}
+
+/**
+ * Close listener socket
+ *
+ */
+static void close_listener ( struct hijack_listener *listener ) {
+ close ( listener->fd );
+ unlink ( listener->sun.sun_path );
+}
+
+/**
+ * Print usage
+ *
+ */
+static void usage ( char **argv ) {
+ logmsg ( LOG_ERR,
+ "Usage: %s [options]\n"
+ "\n"
+ "Options:\n"
+ " -h|--help Print this help message\n"
+ " -i|--interface intf Use specified network interface\n"
+ " -n|--nodaemon Run in foreground\n",
+ argv[0] );
+}
+
+/**
+ * Parse command-line options
+ *
+ */
+static int parse_options ( int argc, char **argv,
+ struct hijack_options *options ) {
+ static struct option long_options[] = {
+ { "interface", 1, NULL, 'i' },
+ { "nodaemon", 0, NULL, 'n' },
+ { "help", 0, NULL, 'h' },
+ { },
+ };
+ int c;
+
+ /* Set default options */
+ memset ( options, 0, sizeof ( *options ) );
+ strncpy ( options->interface, "eth0", sizeof ( options->interface ) );
+ options->daemonise = 1;
+
+ /* Parse command-line options */
+ while ( 1 ) {
+ int option_index = 0;
+
+ c = getopt_long ( argc, argv, "i:hn", long_options,
+ &option_index );
+ if ( c < 0 )
+ break;
+
+ switch ( c ) {
+ case 'i':
+ strncpy ( options->interface, optarg,
+ sizeof ( options->interface ) );
+ break;
+ case 'n':
+ options->daemonise = 0;
+ break;
+ case 'h':
+ usage( argv );
+ return -1;
+ case '?':
+ /* Unrecognised option */
+ return -1;
+ default:
+ logmsg ( LOG_ERR, "Unrecognised option '-%c'\n", c );
+ return -1;
+ }
+ }
+
+ /* Check there's nothing left over on the command line */
+ if ( optind != argc ) {
+ usage ( argv );
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Daemonise
+ *
+ */
+static int daemonise ( const char *interface ) {
+ char pidfile[16 + IF_NAMESIZE + 4]; /* "/var/run/hijack-<intf>.pid" */
+ char pid[16];
+ int pidlen;
+ int fd = -1;
+
+ /* Daemonise */
+ if ( daemon ( 0, 0 ) < 0 ) {
+ logmsg ( LOG_ERR, "Could not daemonise: %s\n",
+ strerror ( errno ) );
+ goto err;
+ }
+ daemonised = 1; /* Direct messages to syslog now */
+
+ /* Open pid file */
+ snprintf ( pidfile, sizeof ( pidfile ), "/var/run/hijack-%s.pid",
+ interface );
+ fd = open ( pidfile, ( O_WRONLY | O_CREAT | O_TRUNC ),
+ ( S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) );
+ if ( fd < 0 ) {
+ logmsg ( LOG_ERR, "Could not open %s for writing: %s\n",
+ pidfile, strerror ( errno ) );
+ goto err;
+ }
+
+ /* Write pid to file */
+ pidlen = snprintf ( pid, sizeof ( pid ), "%d\n", getpid() );
+ if ( write ( fd, pid, pidlen ) != pidlen ) {
+ logmsg ( LOG_ERR, "Could not write %s: %s\n",
+ pidfile, strerror ( errno ) );
+ goto err;
+ }
+
+ close ( fd );
+ return 0;
+
+ err:
+ if ( fd >= 0 )
+ close ( fd );
+ return -1;
+}
+
+int main ( int argc, char **argv ) {
+ struct hijack_options options;
+ struct hijack_listener listener;
+ struct sigaction sa;
+
+ /* Parse command-line options */
+ if ( parse_options ( argc, argv, &options ) < 0 )
+ exit ( 1 );
+
+ /* Set up syslog connection */
+ openlog ( basename ( argv[0] ), LOG_PID, LOG_DAEMON );
+
+ /* Set up listening socket */
+ if ( open_listener ( options.interface, &listener ) < 0 )
+ exit ( 1 );
+
+ /* Daemonise on demand */
+ if ( options.daemonise ) {
+ if ( daemonise ( options.interface ) < 0 )
+ exit ( 1 );
+ }
+
+ /* Avoid creating zombies */
+ memset ( &sa, 0, sizeof ( sa ) );
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = SA_RESTART | SA_NOCLDWAIT;
+ if ( sigaction ( SIGCHLD, &sa, NULL ) < 0 ) {
+ logmsg ( LOG_ERR, "Could not set SIGCHLD handler: %s",
+ strerror ( errno ) );
+ exit ( 1 );
+ }
+
+ /* Set 'signalled' flag on SIGINT or SIGHUP */
+ sa.sa_handler = flag_signalled;
+ sa.sa_flags = SA_RESTART | SA_RESETHAND;
+ if ( sigaction ( SIGINT, &sa, NULL ) < 0 ) {
+ logmsg ( LOG_ERR, "Could not set SIGINT handler: %s",
+ strerror ( errno ) );
+ exit ( 1 );
+ }
+ if ( sigaction ( SIGHUP, &sa, NULL ) < 0 ) {
+ logmsg ( LOG_ERR, "Could not set SIGHUP handler: %s",
+ strerror ( errno ) );
+ exit ( 1 );
+ }
+
+ /* Listen for hijackers */
+ if ( listen_for_hijackers ( &listener, options.interface ) < 0 )
+ exit ( 1 );
+
+ close_listener ( &listener );
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/util/iccfix.c b/src/VBox/Devices/PC/ipxe/src/util/iccfix.c
new file mode 100644
index 00000000..528bf4b2
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/iccfix.c
@@ -0,0 +1,157 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <elf.h>
+#include <ipxe/tables.h>
+
+#define DEBUG 0
+
+#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
+
+#define dprintf(...) do { \
+ if ( DEBUG ) \
+ fprintf ( stderr, __VA_ARGS__ ); \
+ } while ( 0 )
+
+#ifdef SELF_INCLUDED
+
+/**
+ * Fix up ICC alignments
+ *
+ * @v elf ELF header
+ * @ret rc Return status code
+ *
+ * See comments in tables.h for an explanation of why this monstrosity
+ * is necessary.
+ */
+static int ICCFIX ( void *elf ) {
+ ELF_EHDR *ehdr = elf;
+ ELF_SHDR *shdr = ( elf + ehdr->e_shoff );
+ size_t shentsize = ehdr->e_shentsize;
+ unsigned int shnum = ehdr->e_shnum;
+ ELF_SHDR *strtab = ( ( ( void * ) shdr ) +
+ ( ehdr->e_shstrndx * shentsize ) );
+ char *strings = ( elf + strtab->sh_offset );
+
+ for ( ; shnum-- ; shdr = ( ( ( void * ) shdr ) + shentsize ) ) {
+ char *name = ( strings + shdr->sh_name );
+ unsigned long align = shdr->sh_addralign;
+ unsigned long new_align;
+
+ if ( ( strncmp ( name, ".tbl.", 5 ) == 0 ) &&
+ ( align >= ICC_ALIGN_HACK_FACTOR ) ) {
+ new_align = ( align / ICC_ALIGN_HACK_FACTOR );
+ shdr->sh_addralign = new_align;
+ dprintf ( "Section \"%s\": alignment %ld->%ld\n",
+ name, align, new_align );
+ }
+ }
+ return 0;
+}
+
+#else /* SELF_INCLUDED */
+
+#define SELF_INCLUDED
+
+/* Include iccfix32() function */
+#define ELF_EHDR Elf32_Ehdr
+#define ELF_SHDR Elf32_Shdr
+#define ICCFIX iccfix32
+#include "iccfix.c"
+#undef ELF_EHDR
+#undef ELF_SHDR
+#undef ICCFIX
+
+/* Include iccfix64() function */
+#define ELF_EHDR Elf64_Ehdr
+#define ELF_SHDR Elf64_Shdr
+#define ICCFIX iccfix64
+#include "iccfix.c"
+#undef ELF_EHDR
+#undef ELF_SHDR
+#undef ICCFIX
+
+static int iccfix ( const char *filename ) {
+ int fd;
+ struct stat stat;
+ void *elf;
+ unsigned char *eident;
+ int rc;
+
+ /* Open and mmap file */
+ fd = open ( filename, O_RDWR );
+ if ( fd < 0 ) {
+ eprintf ( "Could not open %s: %s\n",
+ filename, strerror ( errno ) );
+ rc = -1;
+ goto err_open;
+ }
+ if ( fstat ( fd, &stat ) < 0 ) {
+ eprintf ( "Could not determine size of %s: %s\n",
+ filename, strerror ( errno ) );
+ rc = -1;
+ goto err_fstat;
+ }
+ elf = mmap ( NULL, stat.st_size, ( PROT_READ | PROT_WRITE ),
+ MAP_SHARED, fd, 0 );
+ if ( elf == MAP_FAILED ) {
+ eprintf ( "Could not map %s: %s\n",
+ filename, strerror ( errno ) );
+ rc = -1;
+ goto err_mmap;
+ }
+
+ /* Perform fixups */
+ eident = elf;
+ switch ( eident[EI_CLASS] ) {
+ case ELFCLASS32:
+ rc = iccfix32 ( elf );
+ break;
+ case ELFCLASS64:
+ rc = iccfix64 ( elf );
+ break;
+ default:
+ eprintf ( "Unknown ELF class %d in %s\n",
+ eident[EI_CLASS], filename );
+ rc = -1;
+ break;
+ }
+
+ munmap ( elf, stat.st_size );
+ err_mmap:
+ err_fstat:
+ close ( fd );
+ err_open:
+ return rc;
+}
+
+int main ( int argc, char **argv ) {
+ int i;
+ int rc;
+
+ /* Parse command line */
+ if ( argc < 2 ) {
+ eprintf ( "Syntax: %s <object_file>...\n", argv[0] );
+ exit ( 1 );
+ }
+
+ /* Process each object in turn */
+ for ( i = 1 ; i < argc ; i++ ) {
+ if ( ( rc = iccfix ( argv[i] ) ) != 0 ) {
+ eprintf ( "Could not fix up %s\n", argv[i] );
+ exit ( 1 );
+ }
+ }
+
+ return 0;
+}
+
+#endif /* SELF_INCLUDED */
diff --git a/src/VBox/Devices/PC/ipxe/src/util/licence.pl b/src/VBox/Devices/PC/ipxe/src/util/licence.pl
new file mode 100755
index 00000000..c37685d3
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/licence.pl
@@ -0,0 +1,149 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+use strict;
+use warnings;
+use Getopt::Long;
+
+# List of licences we can handle
+my $known_licences = {
+ gpl_any => {
+ desc => "GPL (any version)",
+ can_subsume => {
+ public_domain => 1,
+ bsd3 => 1,
+ bsd2 => 1,
+ mit => 1,
+ isc => 1,
+ },
+ },
+ gpl2_or_later => {
+ desc => "GPL version 2 (or, at your option, any later version)",
+ can_subsume => {
+ gpl_any => 1,
+ public_domain => 1,
+ bsd3 => 1,
+ bsd2 => 1,
+ mit => 1,
+ isc => 1,
+ },
+ },
+ gpl2_only => {
+ desc => "GPL version 2 only",
+ can_subsume => {
+ gpl_any => 1,
+ gpl2_or_later => 1,
+ public_domain => 1,
+ bsd3 => 1,
+ bsd2 => 1,
+ mit => 1,
+ isc => 1,
+ },
+ },
+ public_domain => {
+ desc => "Public Domain",
+ can_subsume => {},
+ },
+ bsd4 => {
+ desc => "BSD Licence (with advertising clause)",
+ can_subsume => {
+ public_domain => 1,
+ bsd3 => 1,
+ bsd2 => 1,
+ mit => 1,
+ isc => 1,
+ },
+ },
+ bsd3 => {
+ desc => "BSD Licence (without advertising clause)",
+ can_subsume => {
+ public_domain => 1,
+ bsd2 => 1,
+ mit => 1,
+ isc => 1,
+ },
+ },
+ bsd2 => {
+ desc => "BSD Licence (without advertising or endorsement clauses)",
+ can_subsume => {
+ public_domain => 1,
+ mit => 1,
+ isc => 1,
+ },
+ },
+ mit => {
+ desc => "MIT/X11/Xorg Licence",
+ can_subsume => {
+ public_domain => 1,
+ isc => 1,
+ },
+ },
+ isc => {
+ desc => "ISC Licence",
+ can_subsume => {
+ public_domain => 1,
+ },
+ },
+};
+
+# Parse command-line options
+my $verbosity = 1;
+Getopt::Long::Configure ( 'bundling', 'auto_abbrev' );
+GetOptions (
+ 'verbose|v+' => sub { $verbosity++; },
+ 'quiet|q+' => sub { $verbosity--; },
+) or die "Could not parse command-line options\n";
+
+# Parse licence list from command line
+my $licences = {};
+foreach my $licence ( @ARGV ) {
+ die "Unknown licence \"$licence\"\n"
+ unless exists $known_licences->{$licence};
+ $licences->{$licence} = $known_licences->{$licence};
+}
+die "No licences specified\n" unless %$licences;
+
+# Dump licence list
+if ( $verbosity >= 1 ) {
+ print "The following licences appear within this file:\n";
+ foreach my $licence ( keys %$licences ) {
+ print " ".$licences->{$licence}->{desc}."\n"
+ }
+}
+
+# Apply licence compatibilities to reduce to a single resulting licence
+foreach my $licence ( keys %$licences ) {
+ # Skip already-deleted licences
+ next unless exists $licences->{$licence};
+ # Subsume any subsumable licences
+ foreach my $can_subsume ( keys %{$licences->{$licence}->{can_subsume}} ) {
+ if ( exists $licences->{$can_subsume} ) {
+ print $licences->{$licence}->{desc}." subsumes ".
+ $licences->{$can_subsume}->{desc}."\n"
+ if $verbosity >= 1;
+ delete $licences->{$can_subsume};
+ }
+ }
+}
+
+# Print resulting licence
+die "Cannot reduce to a single resulting licence!\n"
+ if ( keys %$licences ) != 1;
+( my $licence ) = keys %$licences;
+print "The overall licence for this file is:\n " if $verbosity >= 1;
+print $licences->{$licence}->{desc}."\n";
diff --git a/src/VBox/Devices/PC/ipxe/src/util/mergerom.pl b/src/VBox/Devices/PC/ipxe/src/util/mergerom.pl
new file mode 100755
index 00000000..f9c52502
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/mergerom.pl
@@ -0,0 +1,98 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+use strict;
+use warnings;
+
+use FindBin;
+use lib "$FindBin::Bin";
+use Option::ROM qw ( :all );
+
+sub merge_entry_points {
+ my $baserom_entry = \shift;
+ my $rom_entry = \shift;
+ my $offset = shift;
+
+ if ( $$rom_entry ) {
+ my $old_entry = $$baserom_entry;
+ $$baserom_entry = ( $offset + $$rom_entry );
+ $$rom_entry = $old_entry;
+ }
+}
+
+my @romfiles = @ARGV;
+my @roms = map { my $rom = new Option::ROM; $rom->load($_); $rom } @romfiles;
+
+my $baserom = shift @roms;
+my $offset = $baserom->length;
+
+foreach my $rom ( @roms ) {
+
+ # Update base length
+ $baserom->{length} += $rom->{length};
+
+ # Merge initialisation entry point
+ merge_entry_points ( $baserom->{init}, $rom->{init}, $offset );
+
+ # Merge BOFM header
+ merge_entry_points ( $baserom->{bofm_header}, $rom->{bofm_header}, $offset );
+
+ # Update PCI header, if present in both
+ my $baserom_pci = $baserom->pci_header;
+ my $rom_pci = $rom->pci_header;
+ if ( $baserom_pci && $rom_pci ) {
+
+ # Update PCI lengths
+ $baserom_pci->{image_length} += $rom_pci->{image_length};
+ if ( exists $baserom_pci->{runtime_length} ) {
+ if ( exists $rom_pci->{runtime_length} ) {
+ $baserom_pci->{runtime_length} += $rom_pci->{runtime_length};
+ } else {
+ $baserom_pci->{runtime_length} += $rom_pci->{image_length};
+ }
+ }
+
+ # Merge CLP entry point
+ if ( exists ( $baserom_pci->{clp_entry} ) &&
+ exists ( $rom_pci->{clp_entry} ) ) {
+ merge_entry_points ( $baserom_pci->{clp_entry}, $rom_pci->{clp_entry},
+ $offset );
+ }
+ }
+
+ # Update PnP header, if present in both
+ my $baserom_pnp = $baserom->pnp_header;
+ my $rom_pnp = $rom->pnp_header;
+ if ( $baserom_pnp && $rom_pnp ) {
+ merge_entry_points ( $baserom_pnp->{bcv}, $rom_pnp->{bcv}, $offset );
+ merge_entry_points ( $baserom_pnp->{bdv}, $rom_pnp->{bdv}, $offset );
+ merge_entry_points ( $baserom_pnp->{bev}, $rom_pnp->{bev}, $offset );
+ }
+
+ # Fix checksum for this ROM segment
+ $rom->fix_checksum();
+
+ $offset += $rom->length;
+}
+
+$baserom->pnp_header->fix_checksum() if $baserom->pnp_header;
+$baserom->fix_checksum();
+$baserom->save ( "-" );
+foreach my $rom ( @roms ) {
+ $rom->save ( "-" );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/util/modrom.pl b/src/VBox/Devices/PC/ipxe/src/util/modrom.pl
new file mode 100755
index 00000000..cdac0b97
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/modrom.pl
@@ -0,0 +1,226 @@
+#!/usr/bin/perl -w
+
+use Getopt::Std;
+
+use constant MINROMSIZE => 8192;
+use constant MAXROMSIZE => 262144;
+
+use constant PCI_PTR_LOC => 0x18; # from beginning of ROM
+use constant PCI_HDR_SIZE => 0x18;
+use constant PNP_PTR_LOC => 0x1a; # from beginning of ROM
+use constant PNP_HDR_SIZE => 0x20;
+use constant PNP_CHKSUM_OFF => 0x9; # bytes from beginning of PnP header
+use constant PNP_DEVICE_OFF => 0x10; # bytes from beginning of PnP header
+use constant PCI_VEND_ID_OFF => 0x4; # bytes from beginning of PCI header
+use constant PCI_DEV_ID_OFF => 0x6; # bytes from beginning of PCI header
+use constant PCI_SIZE_OFF => 0x10; # bytes from beginning of PCI header
+
+use constant UNDI_PTR_LOC => 0x16; # from beginning of ROM
+use constant UNDI_HDR_SIZE => 0x16;
+use constant UNDI_CHKSUM_OFF => 0x05;
+
+use strict;
+
+use vars qw(%opts);
+
+use bytes;
+
+sub getromsize ($) {
+ my ($romref) = @_;
+ my $i;
+
+ print STDERR "BIOS extension ROM Image did not start with 0x55 0xAA\n"
+ if (substr($$romref, 0, 2) ne "\x55\xaa");
+ my $size = ord(substr($$romref, 2, 1)) * 512;
+ for ($i = MINROMSIZE; $i < MAXROMSIZE and $i < $size; $i *= 2) { }
+ print STDERR "$size is a strange size for a boot ROM\n"
+ if ($size > 0 and $i > $size);
+ return ($size);
+}
+
+sub addident ($) {
+ my ($romref) = @_;
+
+ return (0) unless (my $s = $opts{'i'});
+ # include the terminating NUL byte too
+ $s .= "\x00";
+ my $len = length($s);
+ # Put the identifier in only if the space is blank
+ my $pos = length($$romref) - $len - 2;
+ return (0) if (substr($$romref, $pos, $len) ne ("\xFF" x $len));
+ substr($$romref, $pos, $len) = $s;
+ return ($pos);
+}
+
+sub pcipnpheaders ($$) {
+ my ($romref, $identoffset) = @_;
+ my ($pci_hdr_offset, $pnp_hdr_offset);
+
+ $pci_hdr_offset = unpack('v', substr($$romref, PCI_PTR_LOC, 2));
+ $pnp_hdr_offset = unpack('v', substr($$romref, PNP_PTR_LOC, 2));
+ # Sanity checks
+ if ($pci_hdr_offset < PCI_PTR_LOC + 2
+ or $pci_hdr_offset > length($$romref) - PCI_HDR_SIZE
+ or $pnp_hdr_offset < PNP_PTR_LOC + 2
+ or $pnp_hdr_offset > length($$romref) - PNP_HDR_SIZE
+ or substr($$romref, $pci_hdr_offset, 4) ne 'PCIR'
+ or substr($$romref, $pnp_hdr_offset, 4) ne '$PnP') {
+ $pci_hdr_offset = $pnp_hdr_offset = 0;
+ } else {
+ printf "PCI header at %#x and PnP header at %#x\n",
+ $pci_hdr_offset, $pnp_hdr_offset;
+ }
+ if ($pci_hdr_offset > 0) {
+ my ($pci_vendor_id, $pci_device_id);
+ # if no -p option, just report what's there
+ if (!defined($opts{'p'})) {
+ $pci_vendor_id = unpack('v', substr($$romref, $pci_hdr_offset+PCI_VEND_ID_OFF, 2));
+ $pci_device_id = unpack('v', substr($$romref, $pci_hdr_offset+PCI_DEV_ID_OFF, 2));
+ printf "PCI Vendor ID %#x Device ID %#x\n",
+ $pci_vendor_id, $pci_device_id;
+ } else {
+ substr($$romref, $pci_hdr_offset + PCI_SIZE_OFF, 2)
+ = pack('v', length($$romref) / 512);
+ ($pci_vendor_id, $pci_device_id) = split(/,/, $opts{'p'});
+ substr($$romref, $pci_hdr_offset+PCI_VEND_ID_OFF, 2)
+ = pack('v', oct($pci_vendor_id)) if ($pci_vendor_id);
+ substr($$romref, $pci_hdr_offset+PCI_DEV_ID_OFF, 2)
+ = pack('v', oct($pci_device_id)) if ($pci_device_id);
+ }
+ }
+ if ($pnp_hdr_offset > 0 and defined($identoffset)) {
+ # Point to device id string at end of ROM image
+ substr($$romref, $pnp_hdr_offset+PNP_DEVICE_OFF, 2)
+ = pack('v', $identoffset);
+ substr($$romref, $pnp_hdr_offset+PNP_CHKSUM_OFF, 1) = "\x00";
+ my $sum = unpack('%8C*', substr($$romref, $pnp_hdr_offset,
+ PNP_HDR_SIZE));
+ substr($$romref, $pnp_hdr_offset+PNP_CHKSUM_OFF, 1) = chr(256 - $sum);
+ }
+}
+
+sub undiheaders ($) {
+ my ($romref) = @_;
+ my ($undi_hdr_offset);
+
+ $undi_hdr_offset = unpack('v', substr($$romref, UNDI_PTR_LOC, 2));
+ # Sanity checks
+ if ($undi_hdr_offset < UNDI_PTR_LOC + 2
+ or $undi_hdr_offset > length($$romref) - UNDI_HDR_SIZE
+ or substr($$romref, $undi_hdr_offset, 4) ne 'UNDI') {
+ $undi_hdr_offset = 0;
+ } else {
+ printf "UNDI header at %#x\n", $undi_hdr_offset;
+ }
+ if ($undi_hdr_offset > 0) {
+ substr($$romref, $undi_hdr_offset+UNDI_CHKSUM_OFF, 1) = "\x00";
+ my $sum = unpack('%8C*', substr($$romref, $undi_hdr_offset,
+ UNDI_HDR_SIZE));
+ substr($$romref, $undi_hdr_offset+UNDI_CHKSUM_OFF, 1) = chr(256 - $sum);
+ }
+}
+
+sub writerom ($$) {
+ my ($filename, $romref) = @_;
+
+ open(R, ">$filename") or die "$filename: $!\n";
+ print R $$romref;
+ close(R);
+}
+
+sub checksum ($) {
+ my ($romref) = @_;
+
+ substr($$romref, 6, 1) = "\x00";
+ my $sum = unpack('%8C*', $$romref);
+ substr($$romref, 6, 1) = chr(256 - $sum);
+ # Double check
+ $sum = unpack('%8C*', $$romref);
+ if ($sum != 0) {
+ print "Checksum fails\n"
+ } elsif ($opts{'v'}) {
+ print "Checksum ok\n";
+ }
+}
+
+sub makerom () {
+ my ($rom, $romsize);
+
+ getopts('3xi:p:s:v', \%opts);
+ $ARGV[0] or die "Usage: $0 [-s romsize] [-i ident] [-p vendorid,deviceid] [-x] [-3] rom-file\n";
+ open(R, $ARGV[0]) or die "$ARGV[0]: $!\n";
+ # Read in the whole ROM in one gulp
+ my $filesize = read(R, $rom, MAXROMSIZE+1);
+ close(R);
+ defined($filesize) and $filesize >= 3 or die "Cannot get first 3 bytes of file\n";
+ print "$filesize bytes read\n" if $opts{'v'};
+ # If PXE image, just fill the length field and write it out
+ if ($opts{'x'}) {
+ substr($rom, 2, 1) = chr((length($rom) + 511) / 512);
+ &writerom($ARGV[0], \$rom);
+ return;
+ }
+ # Size specified with -s overrides value in 3rd byte in image
+ # -s 0 means round up to next 512 byte block
+ if (defined($opts{'s'})) {
+ if (($romsize = oct($opts{'s'})) <= 0) {
+ # NB: This roundup trick only works on powers of 2
+ $romsize = ($filesize + 511) & ~511
+ }
+ } else {
+ $romsize = &getromsize(\$rom);
+ # 0 put there by *loader.S means makerom should pick the size
+ if ($romsize == 0) {
+ # Shrink romsize down to the smallest power of two that will do
+ for ($romsize = MAXROMSIZE;
+ $romsize > MINROMSIZE and $romsize >= 2*$filesize;
+ $romsize /= 2) { }
+ }
+ }
+ if ($filesize > $romsize) {
+ print STDERR "ROM size of $romsize not big enough for data, ";
+ # NB: This roundup trick only works on powers of 2
+ $romsize = ($filesize + 511) & ~511;
+ print "will use $romsize instead\n"
+ }
+ # Pad with 0xFF to $romsize
+ $rom .= "\xFF" x ($romsize - length($rom));
+ if ($romsize >= 128 * 1024) {
+ print "Warning: ROM size exceeds extension BIOS limit\n";
+ }
+ substr($rom, 2, 1) = chr(($romsize / 512) % 256);
+ print "ROM size is $romsize\n" if $opts{'v'};
+ my $identoffset = &addident(\$rom);
+ &pcipnpheaders(\$rom, $identoffset);
+ &undiheaders(\$rom);
+ # 3c503 requires last two bytes to be 0x80
+ substr($rom, MINROMSIZE-2, 2) = "\x80\x80"
+ if ($opts{'3'} and $romsize == MINROMSIZE);
+ &checksum(\$rom);
+ &writerom($ARGV[0], \$rom);
+}
+
+sub modrom () {
+ my ($rom);
+
+ getopts('p:v', \%opts);
+ $ARGV[0] or die "Usage: $0 [-p vendorid,deviceid] rom-file\n";
+ open(R, $ARGV[0]) or die "$ARGV[0]: $!\n";
+ # Read in the whole ROM in one gulp
+ my $filesize = read(R, $rom, MAXROMSIZE+1);
+ close(R);
+ defined($filesize) and $filesize >= 3 or die "Cannot get first 3 bytes of file\n";
+ print "$filesize bytes read\n" if $opts{'v'};
+ &pcipnpheaders(\$rom);
+ &undiheaders(\$rom);
+ &checksum(\$rom);
+ &writerom($ARGV[0], \$rom);
+}
+
+# Main routine. See how we were called and behave accordingly
+if ($0 =~ m:modrom(\.pl)?$:) {
+ &modrom();
+} else {
+ &makerom();
+}
+exit(0);
diff --git a/src/VBox/Devices/PC/ipxe/src/util/mucurses_test.c b/src/VBox/Devices/PC/ipxe/src/util/mucurses_test.c
new file mode 100644
index 00000000..586562df
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/mucurses_test.c
@@ -0,0 +1,63 @@
+#include "../include/curses.h"
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+void get_iscsi_chap_secret( char * );
+void mdelay( int msecs );
+
+int main ( void ) {
+ char secret[16];
+ initscr();
+ echo();
+ werase(stdscr);
+ box( stdscr, '|', '-' );
+ get_iscsi_chap_secret(secret);
+
+ mvwprintw( stdscr, 3, 5, "password is \"%s\"", secret );
+ mdelay(2500);
+
+ stdscr->scr->exit(stdscr->scr);
+
+ return 0;
+}
+
+void get_iscsi_chap_secret( char *sec ) {
+ char *title = "Set new iSCSI CHAP secret",
+ *msg = "Configure the iSCSI access secret",
+ pw1[17], pw2[17];
+ WINDOW *secret;
+
+ secret = newwin( stdscr->height / 2,
+ stdscr->width / 2,
+ stdscr->height / 4,
+ stdscr->width / 4 );
+
+ wborder( secret, '|', '|', '-', '-', '+', '+', '+', '+' );
+ mvwprintw( secret, 1, 2, "%s", title );
+ mvwhline( secret, 2, 1, '-' | secret->attrs, secret->width - 2 );
+ mvwprintw( secret, 4, 2, "%s", msg );
+ mvwprintw( secret, 6, 3, "secret" );
+ mvwprintw( secret, 8, 3, "confirm" );
+ start:
+ mvwhline( secret, 6, 12, '_' | secret->attrs, 16 );
+ mvwhline( secret, 8, 12, '_' | secret->attrs, 16 );
+
+ wmove( secret, 6, 12 );
+ wgetnstr( secret, pw1, 16 );
+ wmove( secret, 8, 12 );
+ wgetnstr( secret, pw2, 16 );
+
+ if ( strcmp( pw1, pw2 ) == 0 ) {
+ strcpy( sec, pw1 );
+ werase( secret );
+ }
+ else {
+ mvwprintw( secret, 10, 3, "Passwords do not match" );
+ goto start;
+ }
+}
+
+void mdelay ( int msecs ) {
+ usleep( msecs * 1000 );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/util/niclist.pl b/src/VBox/Devices/PC/ipxe/src/util/niclist.pl
new file mode 100755
index 00000000..0600c823
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/niclist.pl
@@ -0,0 +1,588 @@
+#!/usr/bin/env perl
+#
+# Generates list of supported NICs with PCI vendor/device IDs, driver name
+# and other useful things.
+#
+# Initial version by Robin Smidsrød <robin@smidsrod.no>
+#
+
+use strict;
+use warnings;
+use autodie;
+use v5.10;
+
+use File::stat;
+use File::Basename qw(basename);
+use File::Find ();
+use Getopt::Long qw(GetOptions);
+
+GetOptions(
+ 'help' => \( my $help = 0 ),
+ 'format=s' => \( my $format = 'text' ),
+ 'sort=s' => \( my $sort = 'bus,ipxe_driver,ipxe_name' ),
+ 'columns=s' => \( my $columns = 'bus,vendor_id,device_id,'
+ . 'vendor_name,device_name,ipxe_driver,'
+ . 'ipxe_name,ipxe_description,file,legacy_api'
+ ),
+ 'pci-url=s' => \( my $pci_url = 'http://pciids.sourceforge.net/v2.2/pci.ids' ),
+ 'pci-file=s' => \( my $pci_file = '/tmp/pci.ids' ),
+ 'output=s' => \( my $output = '' ),
+);
+
+die(<<"EOM") if $help;
+Usage: $0 [options] [<directory>]
+
+Options:
+ --help This page
+ --format Set output format
+ --sort Set output sort order (comma-separated)
+ --columns Set output columns (comma-separated)
+ --pci-url URL to pci.ids file
+ --pci-file Cache file for downloaded pci.ids
+ --output Output file (not specified is STDOUT)
+
+Output formats:
+ text, csv, json, html, dokuwiki
+
+Column names (default order):
+ bus, vendor_id, device_id, vendor_name, device_name,
+ ipxe_driver, ipxe_name, ipxe_description, file, legacy_api
+EOM
+
+# Only load runtime requirements if actually in use
+given($format) {
+ when( /csv/ ) {
+ eval { require Text::CSV; };
+ die("Please install Text::CSV CPAN module to use this feature.\n")
+ if $@;
+ }
+ when( /json/ ) {
+ eval { require JSON; };
+ die("Please install JSON CPAN module to use this feature.\n")
+ if $@;
+ }
+ when( /html/ ) {
+ eval { require HTML::Entities; };
+ die("Please install HTML::Entities CPAN module to use this feature.\n")
+ if $@;
+ }
+ default { }
+}
+
+# Scan source dir and build NIC list
+my $ipxe_src_dir = shift || '.'; # Default to current directory
+my $ipxe_nic_list = build_ipxe_nic_list( $ipxe_src_dir );
+
+# Download pci.ids file and parse it
+fetch_pci_ids_file($pci_url, $pci_file);
+my $pci_id_map = build_pci_id_map($pci_file);
+
+# Merge 'official' vendor/device names and sort list
+update_ipxe_nic_names($ipxe_nic_list, $pci_id_map);
+my $sorted_list = sort_ipxe_nic_list($ipxe_nic_list, $sort);
+
+# Run specified formatter
+my $column_names = parse_columns_param($columns);
+say STDERR "Formatting NIC list in format '$format' with columns: "
+ . join(", ", @$column_names);
+my $formatter = \&{ "format_nic_list_$format" };
+my $report = $formatter->( $sorted_list, $column_names );
+
+# Print final report
+if ( $output and $output ne '-' ) {
+ say STDERR "Printing report to '$output'...";
+ open( my $out_fh, ">", $output );
+ print $out_fh $report;
+ close($out_fh);
+}
+else {
+ print STDOUT $report;
+}
+
+exit;
+
+# fetch URL into specified filename
+sub fetch_pci_ids_file {
+ my ($url, $filename) = @_;
+ my @cmd = ( "wget", "--quiet", "-O", $filename, $url );
+ my @touch = ( "touch", $filename );
+ if ( -r $filename ) {
+ my $age = time - stat($filename)->mtime;
+ # Refresh if older than 1 day
+ if ( $age > 86400 ) {
+ say STDERR "Refreshing $filename from $url...";
+ system(@cmd);
+ system(@touch);
+ }
+ }
+ else {
+ say STDERR "Fetching $url into $filename...";
+ system(@cmd);
+ system(@touch);
+ }
+ return $filename;
+}
+
+sub build_pci_id_map {
+ my ($filename) = @_;
+ say STDERR "Building PCI ID map...";
+
+ my $devices = {};
+ my $classes = {};
+ my $pci_id = qr/[[:xdigit:]]{4}/;
+ my $c_id = qr/[[:xdigit:]]{2}/;
+ my $non_space = qr/[^\s]/;
+
+ # open pci.ids file specified
+ open( my $fh, "<", $filename );
+
+ # For devices
+ my $vendor_id = "";
+ my $vendor_name = "";
+ my $device_id = "";
+ my $device_name = "";
+
+ # For classes
+ my $class_id = "";
+ my $class_name = "";
+ my $subclass_id = "";
+ my $subclass_name = "";
+
+ while(<$fh>) {
+ # skip # and blank lines
+ next if m/^$/;
+ next if m/^\s*#/;
+
+ # Vendors, devices and subsystems. Please keep sorted.
+ # Syntax:
+ # vendor vendor_name
+ # device device_name <-- single tab
+ # subvendor subdevice subsystem_name <-- two tabs
+ if ( m/^ ($pci_id) \s+ ( $non_space .* ) /x ) {
+ $vendor_id = lc $1;
+ $vendor_name = $2;
+ $devices->{$vendor_id} = { name => $vendor_name };
+ next;
+ }
+
+ if ( $vendor_id and m/^ \t ($pci_id) \s+ ( $non_space .* ) /x ) {
+ $device_id = lc $1;
+ $device_name = $2;
+ $devices->{$vendor_id}->{'devices'} //= {};
+ $devices->{$vendor_id}->{'devices'}->{$device_id} = { name => $device_name };
+ next;
+ }
+
+ if ( $vendor_id and $device_id and m/^ \t{2} ($pci_id) \s+ ($pci_id) \s+ ( $non_space .* ) /x ) {
+ my $subvendor_id = lc $1;
+ my $subdevice_id = lc $2;
+ my $subsystem_name = $3;
+ $devices->{$vendor_id}->{'devices'}->{$device_id}->{'subvendor'} //= {};
+ $devices->{$vendor_id}->{'devices'}->{$device_id}->{'subvendor'}->{$subvendor_id} //= {};
+ $devices->{$vendor_id}->{'devices'}->{$device_id}->{'subvendor'}->{$subvendor_id}->{'devices'} //= {};
+ $devices->{$vendor_id}->{'devices'}->{$device_id}->{'subvendor'}->{$subvendor_id}->{'devices'}->{$subdevice_id} = { name => $subsystem_name };
+ next;
+ }
+
+ # List of known device classes, subclasses and programming interfaces
+ # Syntax:
+ # C class class_name
+ # subclass subclass_name <-- single tab
+ # prog-if prog-if_name <-- two tabs
+ if ( m/^C \s+ ($c_id) \s+ ( $non_space .* ) /x ) {
+ $class_id = lc $1;
+ $class_name = $2;
+ $classes->{$class_id} = { name => $class_name };
+ next;
+ }
+
+ if ( $class_id and m/^ \t ($c_id) \s+ ( $non_space .* ) /x ) {
+ $subclass_id = lc $1;
+ $subclass_name = $2;
+ $classes->{$class_id}->{'subclasses'} //= {};
+ $classes->{$class_id}->{'subclasses'}->{$subclass_id} = { name => $subclass_name };
+ next;
+ }
+
+ if ( $class_id and $subclass_id and m/^ \t{2} ($c_id) \s+ ( $non_space .* ) /x ) {
+ my $prog_if_id = lc $1;
+ my $prog_if_name = $2;
+ $classes->{$class_id}->{'subclasses'}->{$subclass_id}->{'programming_interfaces'} //= {};
+ $classes->{$class_id}->{'subclasses'}->{$subclass_id}->{'programming_interfaces'}->{$prog_if_id} = { name => $prog_if_name };
+ next;
+ }
+ }
+
+ close($fh);
+
+ # Populate subvendor names
+ foreach my $vendor_id ( keys %$devices ) {
+ my $device_map = $devices->{$vendor_id}->{'devices'};
+ foreach my $device_id ( keys %$device_map ) {
+ my $subvendor_map = $device_map->{$device_id}->{'subvendor'};
+ foreach my $subvendor_id ( keys %$subvendor_map ) {
+ $subvendor_map->{$subvendor_id}->{'name'} = $devices->{$subvendor_id}->{'name'} || "";
+ }
+ }
+ }
+
+ return {
+ 'devices' => $devices,
+ 'classes' => $classes,
+ };
+}
+
+# Scan through C code and parse ISA_ROM and PCI_ROM lines
+sub build_ipxe_nic_list {
+ my ($dir) = @_;
+ say STDERR "Building iPXE NIC list from " . ( $dir eq '.' ? 'current directory' : $dir ) . "...";
+
+ # recursively iterate through dir and find .c files
+ my @c_files;
+ File::Find::find(sub {
+ # only process files
+ return if -d $_;
+ # skip unreadable files
+ return unless -r $_;
+ # skip all but files with .c extension
+ return unless /\.c$/;
+ push @c_files, $File::Find::name;
+ }, $dir);
+
+ # Look for ISA_ROM or PCI_ROM lines
+ my $ipxe_nic_list = [];
+ my $hex_id = qr/0 x [[:xdigit:]]{4} /x;
+ my $quote = qr/ ['"] /x;
+ my $non_space = qr/ [^\s] /x;
+ my $rom_line_counter = 0;
+ foreach my $c_path ( sort @c_files ) {
+ my $legacy = 0;
+ open( my $fh, "<", $c_path );
+ my $c_file = $c_path;
+ $c_file =~ s{^\Q$dir\E/?}{} if -d $dir; # Strip directory from reported filename
+ my $ipxe_driver = basename($c_file, '.c');
+ while(<$fh>) {
+ # Most likely EtherBoot legacy API
+ $legacy = 1 if m/struct \s* nic \s*/x;
+
+ # parse ISA|PCI_ROM lines into hashref and append to $ipxe_nic_list
+ next unless m/^ \s* (?:ISA|PCI)_ROM /x;
+ $rom_line_counter++;
+ chomp;
+ #say; # for debugging regexp
+ if ( m/^ \s* ISA_ROM \s* \( \s* $quote ( .*? ) $quote \s* , \s* $quote ( .*? ) $quote \s* \) /x ) {
+ my $image = $1;
+ my $name = $2;
+ push @$ipxe_nic_list, {
+ file => $c_file,
+ bus => 'isa',
+ ipxe_driver => $ipxe_driver,
+ ipxe_name => $image,
+ ipxe_description => $name,
+ legacy_api => ( $legacy ? 'yes' : 'no' ),
+ };
+ next;
+ }
+ if ( m/^ \s* PCI_ROM \s* \( \s* ($hex_id) \s* , \s* ($hex_id) \s* , \s* $quote (.*?) $quote \s* , \s* $quote (.*?) $quote /x ) {
+ my $vendor_id = lc $1;
+ my $device_id = lc $2;
+ my $name = $3;
+ my $desc = $4;
+ push @$ipxe_nic_list, {
+ file => $c_file,
+ bus => 'pci',
+ vendor_id => substr($vendor_id, 2), # strip 0x
+ device_id => substr($device_id, 2), # strip 0x
+ ipxe_driver => $ipxe_driver,
+ ipxe_name => $name,
+ ipxe_description => $desc,
+ legacy_api => ( $legacy ? 'yes' : 'no' ),
+ };
+ next;
+ }
+ }
+ close($fh);
+ }
+
+ # Verify all ROM lines where parsed properly
+ my @isa_roms = grep { $_->{'bus'} eq 'isa' } @$ipxe_nic_list;
+ my @pci_roms = grep { $_->{'bus'} eq 'pci' } @$ipxe_nic_list;
+ if ( $rom_line_counter != ( @isa_roms + @pci_roms ) ) {
+ say STDERR "Found ROM lines: $rom_line_counter";
+ say STDERR "Extracted ISA_ROM lines: " . scalar @isa_roms;
+ say STDERR "Extracted PCI_ROM lines: " . scalar @pci_roms;
+ die("Mismatch between number of ISA_ROM/PCI_ROM lines and extracted entries. Verify regular expressions.\n");
+ }
+
+ return $ipxe_nic_list;
+}
+
+# merge vendor/product name from $pci_id_map into $ipxe_nic_list
+sub update_ipxe_nic_names {
+ my ($ipxe_nic_list, $pci_id_map) = @_;
+ say STDERR "Merging 'official' vendor/device names...";
+
+ foreach my $nic ( @$ipxe_nic_list ) {
+ next unless $nic->{'bus'} eq 'pci';
+ $nic->{'vendor_name'} = $pci_id_map->{'devices'}->{ $nic->{'vendor_id'} }->{'name'} || "";
+ $nic->{'device_name'} = $pci_id_map->{'devices'}->{ $nic->{'vendor_id'} }->{'devices'}->{ $nic->{'device_id'} }->{'name'} || "";
+ }
+ return $ipxe_nic_list; # Redundant, as we're mutating the input list, useful for chaining calls
+}
+
+# Sort entries in NIC list according to sort criteria
+sub sort_ipxe_nic_list {
+ my ($ipxe_nic_list, $sort_column_names) = @_;
+ my @sort_column_names = @{ parse_columns_param($sort_column_names) };
+ say STDERR "Sorting NIC list by: " . join(", ", @sort_column_names );
+ # Start at the end of the list and resort until list is exhausted
+ my @sorted_list = @{ $ipxe_nic_list };
+ while(@sort_column_names) {
+ my $column_name = pop @sort_column_names;
+ @sorted_list = sort { ( $a->{$column_name} || "" ) cmp ( $b->{$column_name} || "" ) }
+ @sorted_list;
+ }
+ return \@sorted_list;
+}
+
+# Parse comma-separated values into array
+sub parse_columns_param {
+ my ($columns) = @_;
+ return [
+ grep { is_valid_column($_) } # only include valid entries
+ map { s/\s//g; $_; } # filter whitespace
+ split( /,/, $columns ) # split on comma
+ ];
+}
+
+# Return true if the input column name is valid
+sub is_valid_column {
+ my ($name) = @_;
+ my $valid_column_map = {
+ map { $_ => 1 }
+ qw(
+ bus file legacy_api
+ ipxe_driver ipxe_name ipxe_description
+ vendor_id device_id vendor_name device_name
+ )
+ };
+ return unless $name;
+ return unless $valid_column_map->{$name};
+ return 1;
+}
+
+# Output NIC list in plain text
+sub format_nic_list_text {
+ my ($nic_list, $column_names) = @_;
+ return join("\n",
+ map { format_nic_text($_, $column_names) }
+ @$nic_list
+ );
+}
+
+# Format one ipxe_nic_list entry for display
+# Column order not supported by text format
+sub format_nic_text {
+ my ($nic, $column_names) = @_;
+ my $labels = {
+ bus => 'Bus: ',
+ ipxe_driver => 'iPXE driver: ',
+ ipxe_name => 'iPXE name: ',
+ ipxe_description => 'iPXE description:',
+ file => 'Source file: ',
+ legacy_api => 'Using legacy API:',
+ vendor_id => 'PCI vendor ID: ',
+ device_id => 'PCI device ID: ',
+ vendor_name => 'Vendor name: ',
+ device_name => 'Device name: ',
+ };
+ my $pci_only = {
+ vendor_id => 1,
+ device_id => 1,
+ vendor_name => 1,
+ device_name => 1,
+ };
+ my $output = "";
+ foreach my $column ( @$column_names ) {
+ next if $nic->{'bus'} eq 'isa' and $pci_only->{$column};
+ $output .= $labels->{$column}
+ . " "
+ . ( $nic->{$column} || "" )
+ . "\n";
+ }
+ return $output;
+}
+
+# Output NIC list in JSON
+sub format_nic_list_json {
+ my ($nic_list, $column_names) = @_;
+
+ # Filter columns not mentioned
+ my @nics;
+ foreach my $nic ( @$nic_list ) {
+ my $filtered_nic = {};
+ foreach my $key ( @$column_names ) {
+ $filtered_nic->{$key} = $nic->{$key};
+ }
+ push @nics, $filtered_nic;
+ }
+
+ return JSON->new->pretty->utf8->encode(\@nics);
+}
+
+# Output NIC list in CSV
+sub format_nic_list_csv {
+ my ($nic_list, $column_names) = @_;
+ my @output;
+
+ # Output CSV header
+ my $csv = Text::CSV->new();
+ if ( $csv->combine( @$column_names ) ) {
+ push @output, $csv->string();
+ }
+
+ # Output CSV lines
+ foreach my $nic ( @$nic_list ) {
+ my @columns = @{ $nic }{ @$column_names };
+ if ( $csv->combine( @columns ) ) {
+ push @output, $csv->string();
+ }
+ }
+ return join("\n", @output) . "\n";
+}
+
+# Output NIC list in HTML
+sub format_nic_list_html {
+ my ($nic_list, $column_names) = @_;
+ my @output;
+
+ push @output, <<'EOM';
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Network cards supported by iPXE</title>
+<style>
+table.tablesorter {
+ border: thin solid black;
+}
+
+table.tablesorter thead {
+ background-color: #EEE;
+}
+
+table.tablesorter thead th {
+ font-weight: bold;
+}
+
+table.tablesorter tbody td {
+ vertical-align: top;
+ padding-left: 0.25em;
+ padding-right: 0.25em;
+ padding-bottom: 0.125em;
+ white-space: nowrap;
+}
+
+table.tablesorter tbody tr.even {
+ background-color: #eee;
+}
+
+table.tablesorter tbody tr.odd {
+ background-color: #fff;
+}
+</style>
+</head>
+<body>
+<h1>Network cards supported by iPXE</h1>
+<table class="tablesorter">
+<thead>
+EOM
+
+ # Output HTML header
+ push @output, "<tr>"
+ . join("",
+ map { "<th>" . HTML::Entities::encode($_) . "</th>" }
+ @$column_names
+ )
+ . "</tr>";
+
+ push @output, <<"EOM";
+</thead>
+<tbody>
+EOM
+ # Output HTML lines
+ my $counter = 0;
+ foreach my $nic ( @$nic_list ) {
+ my @columns = @{ $nic }{ @$column_names }; # array slice from hashref, see perldoc perldata if confusing
+ push @output, q!<tr class="! . ( $counter % 2 ? 'even' : 'odd' ) . q!">!
+ . join("",
+ map { "<td>" . HTML::Entities::encode( $_ || "" ) . "</td>" }
+ @columns
+ )
+ . "</tr>";
+ $counter++;
+ }
+
+ push @output, <<'EOM';
+</tbody>
+</table>
+<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
+<script>
+/*
+ *
+ * TableSorter 2.0 - Client-side table sorting with ease!
+ * Version 2.0.5b
+ * @requires jQuery v1.2.3
+ * From http://tablesorter.com/
+ *
+ * Copyright (c) 2007 Christian Bach
+ * Examples and docs at: http://tablesorter.com
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+(function($){$.extend({tablesorter:new
+function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",cssChildRow:"expand-child",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,sortLocaleCompare:true,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'/\.|\,/g',onRenderHeader:null,selectorHeaders:'thead th',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}if(table.tBodies.length==0)return;var rows=table.tBodies[0].rows;if(rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,rows,-1,i);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,rows,rowIndex,cellIndex){var l=parsers.length,node=false,nodeValue=false,keepLooking=true;while(nodeValue==''&&keepLooking){rowIndex++;if(rows[rowIndex]){node=getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex);nodeValue=trimAndGetNodeText(table.config,node);if(table.config.debug){log('Checking if value was empty on row:'+rowIndex);}}else{keepLooking=false;}}for(var i=1;i<l;i++){if(parsers[i].is(nodeValue,table,node)){return parsers[i];}}return parsers[0];}function getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex){return rows[rowIndex].cells[cellIndex];}function trimAndGetNodeText(config,node){return $.trim(getElementText(config,node));}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=$(table.tBodies[0].rows[i]),cols=[];if(c.hasClass(table.config.cssChildRow)){cache.row[cache.row.length-1]=cache.row[cache.row.length-1].add(c);continue;}cache.row.push(c);for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c[0].cells[j]),table,c[0].cells[j]));}cols.push(cache.normalized.length);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cache for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){var text="";if(!node)return"";if(!config.supportsTextContent)config.supportsTextContent=node.textContent||false;if(config.textExtraction=="simple"){if(config.supportsTextContent){text=node.textContent;}else{if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){text=node.childNodes[0].innerHTML;}else{text=node.innerHTML;}}}else{if(typeof(config.textExtraction)=="function"){text=config.textExtraction(node);}else{text=$(node).text();}}return text;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){var pos=n[i][checkCell];rows.push(r[pos]);if(!table.config.appender){var l=r[pos].length;for(var j=0;j<l;j++){tableBody[0].appendChild(r[pos][j]);}}}if(table.config.appender){table.config.appender(table,rows);}rows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false;var header_index=computeTableHeaderCellIndexes(table);$tableHeaders=$(table.config.selectorHeaders,table).each(function(index){this.column=header_index[this.parentNode.rowIndex+"-"+this.cellIndex];this.order=formatSortingOrder(table.config.sortInitialOrder);this.count=this.order;if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(checkHeaderOptionsSortingLocked(table,index))this.order=this.lockedOrder=checkHeaderOptionsSortingLocked(table,index);if(!this.sortDisabled){var $th=$(this).addClass(table.config.cssHeader);if(table.config.onRenderHeader)table.config.onRenderHeader.apply($th);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableHeaders);}return $tableHeaders;};function computeTableHeaderCellIndexes(t){var matrix=[];var lookup={};var thead=t.getElementsByTagName('THEAD')[0];var trs=thead.getElementsByTagName('TR');for(var i=0;i<trs.length;i++){var cells=trs[i].cells;for(var j=0;j<cells.length;j++){var c=cells[j];var rowIndex=c.parentNode.rowIndex;var cellId=rowIndex+"-"+c.cellIndex;var rowSpan=c.rowSpan||1;var colSpan=c.colSpan||1
+var firstAvailCol;if(typeof(matrix[rowIndex])=="undefined"){matrix[rowIndex]=[];}for(var k=0;k<matrix[rowIndex].length+1;k++){if(typeof(matrix[rowIndex][k])=="undefined"){firstAvailCol=k;break;}}lookup[cellId]=firstAvailCol;for(var k=rowIndex;k<rowIndex+rowSpan;k++){if(typeof(matrix[k])=="undefined"){matrix[k]=[];}var matrixrow=matrix[k];for(var l=firstAvailCol;l<firstAvailCol+colSpan;l++){matrixrow[l]="x";}}}}return lookup;}function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function checkHeaderOptionsSortingLocked(table,i){if((table.config.headers[i])&&(table.config.headers[i].lockedOrder))return table.config.headers[i].lockedOrder;return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){return(v.toLowerCase()=="desc")?1:0;}else{return(v==1)?1:0;}}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;if(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(table.config.parsers[c].type=="text")?((order==0)?makeSortFunction("text","asc",c):makeSortFunction("text","desc",c)):((order==0)?makeSortFunction("numeric","asc",c):makeSortFunction("numeric","desc",c));var e="e"+i;dynamicExp+="var "+e+" = "+s;dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgOrderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";if(table.config.debug){benchmark("Evaling expression:"+dynamicExp,new Date());}eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function makeSortFunction(type,direction,index){var a="a["+index+"]",b="b["+index+"]";if(type=='text'&&direction=='asc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+a+" < "+b+") ? -1 : 1 )));";}else if(type=='text'&&direction=='desc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+b+" < "+a+") ? -1 : 1 )));";}else if(type=='numeric'&&direction=='asc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+a+" - "+b+"));";}else if(type=='numeric'&&direction=='desc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+b+" - "+a+"));";}};function makeSortText(i){return"((a["+i+"] < b["+i+"]) ? -1 : ((a["+i+"] > b["+i+"]) ? 1 : 0));";};function makeSortTextDesc(i){return"((b["+i+"] < a["+i+"]) ? -1 : ((b["+i+"] > a["+i+"]) ? 1 : 0));";};function makeSortNumeric(i){return"a["+i+"]-b["+i+"];";};function makeSortNumericDesc(i){return"b["+i+"]-a["+i+"];";};function sortText(a,b){if(table.config.sortLocaleCompare)return a.localeCompare(b);return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){if(table.config.sortLocaleCompare)return b.localeCompare(a);return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$.data(this,"tablesorter",config);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){$this.trigger("sortStart");var $cell=$(this);var i=this.column;this.order=this.count++%2;if(this.lockedOrder)this.order=this.lockedOrder;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.headerList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){var me=this;setTimeout(function(){me.config.parsers=buildParserCache(me,$headers);cache=buildCache(me);},1);}).bind("updateCell",function(e,cell){var config=this.config;var pos=[(cell.parentNode.rowIndex-1),cell.cellIndex];cache.normalized[pos[0]][pos[1]]=config.parsers[pos[1]].format(getElementText(config,cell),cell);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){return/^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g,'')));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.apply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLocaleLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[£$€?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[£$€]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.test(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Date();}var $tr,row=-1,odd;$("tr:visible",table.tBodies[0]).each(function(i){$tr=$(this);if(!$tr.hasClass(table.config.cssChildRow))row++;odd=(row%2==0);$tr.removeClass(table.config.widgetZebra.css[odd?0:1]).addClass(table.config.widgetZebra.css[odd?1:0])});if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery);
+</script>
+<script type="text/javascript">
+$(document).ready(function() {
+ $("table.tablesorter").tablesorter();
+});
+</script>
+</body>
+</html>
+EOM
+ return join("\n", @output);
+}
+
+# Output NIC list in DokuWiki format (for http://ipxe.org)
+sub format_nic_list_dokuwiki {
+ my ($nic_list, $column_names) = @_;
+ my @output;
+
+ push @output, <<'EOM';
+EOM
+
+ # Output DokuWiki table header
+ push @output, "^"
+ . join("^",
+ map { $_ || "" }
+ @$column_names
+ )
+ . "^";
+
+ # Output DokuWiki table entries
+ foreach my $nic ( @$nic_list ) {
+ my @columns = @{ $nic }{ @$column_names }; # array slice from hashref, see perldoc perldata if confusing
+ push @output, '|'
+ . join('|',
+ map { $_ || "" }
+ @columns
+ )
+ . '|';
+ }
+
+ return join("\n", @output);
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/util/nrv2b.c b/src/VBox/Devices/PC/ipxe/src/util/nrv2b.c
new file mode 100644
index 00000000..9be2ef0f
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/nrv2b.c
@@ -0,0 +1,1514 @@
+/**************************************************************
+ Form adapted from lzhuf.c
+ written by Haruyasu Yoshizaki 11/20/1988
+ some minor changes 4/6/1989
+ comments translated by Haruhiko Okumura 4/7/1989
+
+ minor beautifications and adjustments for compiling under Linux
+ by Markus Gutschke <gutschk@math.uni-muenster.de>
+ 1997-01-27
+
+ Modifications to allow use as a filter by Ken Yap
+ <ken_yap@users.sourceforge.net>.
+
+ 1997-07-01
+
+ Small mod to cope with running on big-endian machines
+ by Jim Hague <jim.hague@acm.org)
+ 1998-02-06
+
+ Make compression statistics report shorter
+ by Ken Yap <ken_yap@users.sourceforge.net>.
+ 2001-04-25
+
+ Replaced algorithm with nrv2b from ucl the compression
+ library from upx. That code is:
+ Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
+ And is distributed under the terms of the GPL.
+ The conversion was performed
+ by Eric Biederman <ebiederman@lnxi.com>.
+ 20 August 2002
+
+**************************************************************/
+#define UCLPACK_COMPAT 0
+#define NDEBUG 1
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#ifdef __FreeBSD__
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+#include <limits.h>
+#include <assert.h>
+#if UCLPACK_COMPAT
+#include <netinet/in.h>
+#endif
+
+#ifndef VERBOSE
+#define Fprintf(x)
+#define wterr 0
+#else
+#define Fprintf(x) fprintf x
+#endif
+
+#ifndef MAIN
+extern
+#endif
+FILE *infile, *outfile;
+
+#if defined(ENCODE) || defined(DECODE)
+
+#ifndef ENDIAN
+#define ENDIAN 0
+#endif
+#ifndef BITSIZE
+#define BITSIZE 32
+#endif
+
+static __inline__ void Error(char *message)
+{
+ Fprintf((stderr, "\n%s\n", message));
+ exit(EXIT_FAILURE);
+}
+
+/* These will be a complete waste of time on a lo-endian */
+/* system, but it only gets done once so WTF. */
+static unsigned long __attribute__ (( unused )) i86ul_to_host(unsigned long ul)
+{
+ unsigned long res = 0;
+ int i;
+ union
+ {
+ unsigned char c[4];
+ unsigned long ul;
+ } u;
+
+ u.ul = ul;
+ for (i = 3; i >= 0; i--)
+ res = (res << 8) + u.c[i];
+ return res;
+}
+
+static unsigned long host_to_i86ul(unsigned long ul)
+{
+ int i;
+ union
+ {
+ unsigned char c[4];
+ unsigned long ul;
+ } u;
+
+ for (i = 0; i < 4; i++)
+ {
+ u.c[i] = ul & 0xff;
+ ul >>= 8;
+ }
+ return u.ul;
+}
+#endif
+
+
+
+#if UCLPACK_COMPAT
+/* magic file header for compressed files */
+static const unsigned char magic[8] =
+{ 0x00, 0xe9, 0x55, 0x43, 0x4c, 0xff, 0x01, 0x1a };
+
+#endif
+
+#ifdef ENCODE
+/********** NRV2B_99 compression **********/
+
+/* Note by limiting the ring buffer I have limited the maximum
+ * offset to 64K. Since etherboot rarely gets that big it
+ * is not a problem and it gives me a firm guarantee
+ * that I will never get a 3 byte string match that is encodes
+ * to more than 9/8 it's original size.
+ * That guaranteee is important to for the inplace decompressor.
+ * There are better ways to do this if a larger offset and buffer
+ * would give better compression.
+ */
+#define N (65536ul) /* size of ring buffer */
+#define THRESHOLD 1 /* lower limit for match length */
+#define F 2048 /* upper limit for match length */
+#define M2_MAX_OFFSET 0xd00
+
+/* note: to use default values pass -1, i.e. initialize
+ * this struct by a memset(x,0xff,sizeof(x)) */
+struct ucl_compress_config
+{
+ int bb_endian;
+ int bb_size;
+ unsigned int max_offset;
+ unsigned int max_match;
+ int s_level;
+ int h_level;
+ int p_level;
+ int c_flags;
+ unsigned int m_size;
+};
+
+struct ucl_compress
+{
+ int init;
+
+ unsigned int look; /* bytes in lookahead buffer */
+
+ unsigned int m_len;
+ unsigned int m_off;
+
+ unsigned int last_m_len;
+ unsigned int last_m_off;
+
+ const unsigned char *bp;
+ const unsigned char *ip;
+ const unsigned char *in;
+ const unsigned char *in_end;
+ unsigned char *out;
+
+ uint64_t bb_b;
+ unsigned bb_k;
+ unsigned bb_c_endian;
+ unsigned bb_c_s;
+ unsigned bb_c_s8;
+ unsigned char *bb_p;
+ unsigned char *bb_op;
+
+ struct ucl_compress_config conf;
+ unsigned int *result;
+
+ unsigned int textsize; /* text size counter */
+ unsigned int codesize; /* code size counter */
+ unsigned int printcount; /* counter for reporting progress every 1K
+ bytes */
+
+
+ /* some stats */
+ unsigned long lit_bytes;
+ unsigned long match_bytes;
+ unsigned long rep_bytes;
+ unsigned long lazy;
+};
+
+
+
+#define getbyte(c) ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
+
+#define UCL_E_OK 0
+#define UCL_E_INVALID_ARGUMENT 1
+#define UCL_E_OUT_OF_MEMORY 2
+#define UCL_E_ERROR 3
+
+/***********************************************************************
+//
+************************************************************************/
+
+#define SWD_HSIZE 16384
+#define SWD_MAX_CHAIN 2048
+#ifndef VBOX
+#define SWD_BEST_OFF 1
+#endif
+
+#define HEAD3(b,p) \
+ (((0x9f5f*(((((uint32_t)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1))
+
+#define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8))
+#define NIL2 UINT_MAX
+
+struct ucl_swd
+{
+/* public - "built-in" */
+ unsigned int n;
+ unsigned int f;
+ unsigned int threshold;
+
+/* public - configuration */
+ unsigned int max_chain;
+ unsigned int nice_length;
+ int use_best_off;
+ unsigned int lazy_insert;
+
+/* public - output */
+ unsigned int m_len;
+ unsigned int m_off;
+ unsigned int look;
+ int b_char;
+#if defined(SWD_BEST_OFF)
+ unsigned int best_off[ SWD_BEST_OFF ];
+#endif
+
+/* semi public */
+ struct ucl_compress *c;
+ unsigned int m_pos;
+#if defined(SWD_BEST_OFF)
+ unsigned int best_pos[ SWD_BEST_OFF ];
+#endif
+
+/* private */
+ const uint8_t *dict;
+ const uint8_t *dict_end;
+ unsigned int dict_len;
+
+/* private */
+ unsigned int ip; /* input pointer (lookahead) */
+ unsigned int bp; /* buffer pointer */
+ unsigned int rp; /* remove pointer */
+ unsigned int b_size;
+
+ unsigned char *b_wrap;
+
+ unsigned int node_count;
+ unsigned int first_rp;
+
+ unsigned char b [ N + F + F ];
+ unsigned int head3 [ SWD_HSIZE ];
+ unsigned int succ3 [ N + F ];
+ unsigned int best3 [ N + F ];
+ unsigned int llen3 [ SWD_HSIZE ];
+ unsigned int head2 [ 65536U ];
+};
+
+#define s_head3(s,key) s->head3[key]
+
+
+#if !defined( NDEBUG)
+static void assert_match(const struct ucl_swd * swd, unsigned int m_len,
+ unsigned int m_off )
+
+{
+ const struct ucl_compress *c = swd->c;
+ unsigned int d_off;
+
+ assert(m_len >= 2);
+ if (m_off <= (unsigned int) (c->bp - c->in))
+ {
+ assert(c->bp - m_off + m_len < c->ip);
+ assert(memcmp(c->bp, c->bp - m_off, m_len) == 0);
+ }
+ else
+ {
+ assert(swd->dict != NULL);
+ d_off = m_off - (unsigned int) (c->bp - c->in);
+ assert(d_off <= swd->dict_len);
+ if (m_len > d_off)
+ {
+ assert(memcmp(c->bp, swd->dict_end - d_off, d_off) ==
+ 0);
+
+ assert(c->in + m_len - d_off < c->ip);
+ assert(memcmp(c->bp + d_off, c->in, m_len - d_off) ==
+ 0);
+
+ }
+ else
+ {
+ assert(memcmp(c->bp, swd->dict_end - d_off, m_len) ==
+ 0);
+
+ }
+ }
+}
+#else
+# define assert_match(a,b,c) ((void)0)
+#endif
+
+/***********************************************************************
+//
+************************************************************************/
+
+
+static
+void swd_initdict(struct ucl_swd *s, const uint8_t *dict, unsigned int dict_len)
+
+{
+ s->dict = s->dict_end = NULL;
+ s->dict_len = 0;
+
+ if (!dict || dict_len <= 0)
+ return;
+ if (dict_len > s->n)
+ {
+ dict += dict_len - s->n;
+ dict_len = s->n;
+ }
+
+ s->dict = dict;
+ s->dict_len = dict_len;
+ s->dict_end = dict + dict_len;
+ memcpy(s->b,dict,dict_len);
+ s->ip = dict_len;
+}
+
+
+static
+void swd_insertdict(struct ucl_swd *s, unsigned int node, unsigned int len)
+{
+ unsigned int key;
+
+ s->node_count = s->n - len;
+ s->first_rp = node;
+
+ while (len-- > 0)
+ {
+ key = HEAD3(s->b,node);
+ s->succ3[node] = s_head3(s,key);
+ s->head3[key] = (unsigned int)(node);
+ s->best3[node] = (unsigned int)(s->f + 1);
+ s->llen3[key]++;
+ assert(s->llen3[key] <= s->n);
+
+ key = HEAD2(s->b,node);
+ s->head2[key] = (unsigned int)(node);
+
+ node++;
+ }
+}
+
+/***********************************************************************
+//
+************************************************************************/
+
+
+static
+int swd_init(struct ucl_swd *s, const uint8_t *dict, unsigned int dict_len)
+{
+ unsigned int i = 0;
+
+ if (s->n == 0)
+ s->n = N;
+ if (s->f == 0)
+ s->f = F;
+ s->threshold = THRESHOLD;
+ if (s->n > N || s->f > F)
+ return UCL_E_INVALID_ARGUMENT;
+
+ /* defaults */
+ s->max_chain = SWD_MAX_CHAIN;
+ s->nice_length = s->f;
+ s->use_best_off = 0;
+ s->lazy_insert = 0;
+
+ s->b_size = s->n + s->f;
+ if (s->b_size + s->f >= UINT_MAX)
+ return UCL_E_ERROR;
+ s->b_wrap = s->b + s->b_size;
+ s->node_count = s->n;
+
+ memset(s->llen3, 0, sizeof(s->llen3[0]) * SWD_HSIZE);
+ for (i = 0; i < 65536U; i++)
+ s->head2[i] = NIL2;
+
+ s->ip = 0;
+ swd_initdict(s,dict,dict_len);
+ s->bp = s->ip;
+ s->first_rp = s->ip;
+
+ assert(s->ip + s->f <= s->b_size);
+
+ s->look = (unsigned int) (s->c->in_end - s->c->ip);
+ if (s->look > 0)
+ {
+ if (s->look > s->f)
+ s->look = s->f;
+ memcpy(&s->b[s->ip],s->c->ip,s->look);
+ s->c->ip += s->look;
+ s->ip += s->look;
+ }
+ if (s->ip == s->b_size)
+ s->ip = 0;
+
+ if (s->look >= 2 && s->dict_len > 0)
+ swd_insertdict(s,0,s->dict_len);
+
+ s->rp = s->first_rp;
+ if (s->rp >= s->node_count)
+ s->rp -= s->node_count;
+ else
+ s->rp += s->b_size - s->node_count;
+
+ /* unused i */
+ /* unused c */
+ return UCL_E_OK;
+}
+
+
+static
+void swd_exit(struct ucl_swd *s)
+{
+ /* unused s */
+ ( void ) s;
+}
+
+#define swd_pos2off(s,pos) \
+ (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp))
+
+/***********************************************************************
+//
+************************************************************************/
+
+static __inline__
+void swd_getbyte(struct ucl_swd *s)
+{
+ int c;
+
+ if ((c = getbyte(*(s->c))) < 0)
+ {
+ if (s->look > 0)
+ --s->look;
+ }
+ else
+ {
+ s->b[s->ip] = (uint8_t)(c);
+ if (s->ip < s->f)
+ s->b_wrap[s->ip] = (uint8_t)(c);
+ }
+ if (++s->ip == s->b_size)
+ s->ip = 0;
+ if (++s->bp == s->b_size)
+ s->bp = 0;
+ if (++s->rp == s->b_size)
+ s->rp = 0;
+}
+/***********************************************************************
+// remove node from lists
+************************************************************************/
+
+static __inline__
+void swd_remove_node(struct ucl_swd *s, unsigned int node)
+{
+ if (s->node_count == 0)
+ {
+ unsigned int key;
+
+#ifdef UCL_DEBUG
+ if (s->first_rp != UINT_MAX)
+ {
+ if (node != s->first_rp)
+ printf("Remove %5d: %5d %5d %5d %5d %6d %6d\n",
+
+ node, s->rp, s->ip, s->bp, s->first_rp,
+ s->ip - node, s->ip - s->bp);
+ assert(node == s->first_rp);
+ s->first_rp = UINT_MAX;
+ }
+#endif
+
+ key = HEAD3(s->b,node);
+ assert(s->llen3[key] > 0);
+ --s->llen3[key];
+
+ key = HEAD2(s->b,node);
+ assert(s->head2[key] != NIL2);
+ if ((unsigned int) s->head2[key] == node)
+ s->head2[key] = NIL2;
+ }
+ else
+ --s->node_count;
+}
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+
+static
+void swd_accept(struct ucl_swd *s, unsigned int n)
+{
+ assert(n <= s->look);
+
+ if (n > 0) do
+ {
+ unsigned int key;
+
+ swd_remove_node(s,s->rp);
+
+ /* add bp into HEAD3 */
+ key = HEAD3(s->b,s->bp);
+ s->succ3[s->bp] = s_head3(s,key);
+ s->head3[key] = (unsigned int)(s->bp);
+ s->best3[s->bp] = (unsigned int)(s->f + 1);
+ s->llen3[key]++;
+ assert(s->llen3[key] <= s->n);
+
+ /* add bp into HEAD2 */
+ key = HEAD2(s->b,s->bp);
+ s->head2[key] = (unsigned int)(s->bp);
+
+ swd_getbyte(s);
+ } while (--n > 0);
+}
+
+/***********************************************************************
+//
+************************************************************************/
+
+static
+void swd_search(struct ucl_swd *s, unsigned int node, unsigned int cnt)
+{
+ const unsigned char *p1;
+ const unsigned char *p2;
+ const unsigned char *px;
+
+ unsigned int m_len = s->m_len;
+ const unsigned char * b = s->b;
+ const unsigned char * bp = s->b + s->bp;
+ const unsigned char * bx = s->b + s->bp + s->look;
+ unsigned char scan_end1;
+
+ assert(s->m_len > 0);
+
+ scan_end1 = bp[m_len - 1];
+ for ( ; cnt-- > 0; node = s->succ3[node])
+ {
+ p1 = bp;
+ p2 = b + node;
+ px = bx;
+
+ assert(m_len < s->look);
+
+ if (
+ p2[m_len - 1] == scan_end1 &&
+ p2[m_len] == p1[m_len] &&
+ p2[0] == p1[0] &&
+ p2[1] == p1[1])
+ {
+ unsigned int i;
+ assert(memcmp(bp,&b[node],3) == 0);
+
+ p1 += 2; p2 += 2;
+ do {} while (++p1 < px && *p1 == *++p2);
+ i = p1 - bp;
+
+#ifdef UCL_DEBUG
+ if (memcmp(bp,&b[node],i) != 0)
+ printf("%5ld %5ld %02x%02x %02x%02x\n",
+ (long)s->bp, (long) node,
+ bp[0], bp[1], b[node], b[node+1]);
+#endif
+ assert(memcmp(bp,&b[node],i) == 0);
+
+#if defined(SWD_BEST_OFF)
+ if (i < SWD_BEST_OFF)
+ {
+ if (s->best_pos[i] == 0)
+ s->best_pos[i] = node + 1;
+ }
+#endif
+ if (i > m_len)
+ {
+ s->m_len = m_len = i;
+ s->m_pos = node;
+ if (m_len == s->look)
+ return;
+ if (m_len >= s->nice_length)
+ return;
+ if (m_len > (unsigned int) s->best3[node])
+ return;
+ scan_end1 = bp[m_len - 1];
+ }
+ }
+ }
+}
+
+static int swd_search2(struct ucl_swd *s)
+{
+ unsigned int key;
+
+ assert(s->look >= 2);
+ assert(s->m_len > 0);
+
+ key = s->head2[ HEAD2(s->b,s->bp) ];
+ if (key == NIL2)
+ return 0;
+#ifdef UCL_DEBUG
+ if (memcmp(&s->b[s->bp],&s->b[key],2) != 0)
+ printf("%5ld %5ld %02x%02x %02x%02x\n", (long)s->bp, (long)key,
+ s->b[s->bp], s->b[s->bp+1], s->b[key], s->b[key+1]);
+#endif
+ assert(memcmp(&s->b[s->bp],&s->b[key],2) == 0);
+#if defined(SWD_BEST_OFF)
+ if (s->best_pos[2] == 0)
+ s->best_pos[2] = key + 1;
+#endif
+
+ if (s->m_len < 2)
+ {
+ s->m_len = 2;
+ s->m_pos = key;
+ }
+ return 1;
+}
+
+/***********************************************************************
+//
+************************************************************************/
+
+static
+void swd_findbest(struct ucl_swd *s)
+{
+ unsigned int key;
+ unsigned int cnt, node;
+ unsigned int len;
+
+ assert(s->m_len > 0);
+
+ /* get current head, add bp into HEAD3 */
+ key = HEAD3(s->b,s->bp);
+ node = s->succ3[s->bp] = s_head3(s,key);
+ cnt = s->llen3[key]++;
+ assert(s->llen3[key] <= s->n + s->f);
+ if (cnt > s->max_chain && s->max_chain > 0)
+ cnt = s->max_chain;
+ s->head3[key] = (unsigned int)(s->bp);
+
+ s->b_char = s->b[s->bp];
+ len = s->m_len;
+ if (s->m_len >= s->look)
+ {
+ if (s->look == 0)
+ s->b_char = -1;
+ s->m_off = 0;
+ s->best3[s->bp] = (unsigned int)(s->f + 1);
+ }
+ else
+ {
+ if (swd_search2(s))
+ if (s->look >= 3)
+ swd_search(s,node,cnt);
+ if (s->m_len > len)
+ s->m_off = swd_pos2off(s,s->m_pos);
+ s->best3[s->bp] = (unsigned int)(s->m_len);
+
+#if defined(SWD_BEST_OFF)
+ if (s->use_best_off)
+ {
+ int i;
+ for (i = 2; i < SWD_BEST_OFF; i++)
+ if (s->best_pos[i] > 0)
+ s->best_off[i] =
+ swd_pos2off(s,s->best_pos[i]-1);
+
+ else
+ s->best_off[i] = 0;
+ }
+#endif
+ }
+
+ swd_remove_node(s,s->rp);
+
+ /* add bp into HEAD2 */
+ key = HEAD2(s->b,s->bp);
+ s->head2[key] = (unsigned int)(s->bp);
+}
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+static int
+init_match ( struct ucl_compress *c, struct ucl_swd *s,
+ const uint8_t *dict, unsigned int dict_len,
+ uint32_t flags )
+{
+ int r;
+
+ assert(!c->init);
+ c->init = 1;
+
+ s->c = c;
+
+ c->last_m_len = c->last_m_off = 0;
+
+ c->textsize = c->codesize = c->printcount = 0;
+ c->lit_bytes = c->match_bytes = c->rep_bytes = 0;
+ c->lazy = 0;
+
+ r = swd_init(s,dict,dict_len);
+ if (r != UCL_E_OK)
+ {
+ swd_exit(s);
+ return r;
+ }
+
+ s->use_best_off = (flags & 1) ? 1 : 0;
+ return UCL_E_OK;
+}
+
+static int
+find_match ( struct ucl_compress *c, struct ucl_swd *s,
+ unsigned int this_len, unsigned int skip )
+{
+ assert(c->init);
+
+ if (skip > 0)
+ {
+ assert(this_len >= skip);
+ swd_accept(s, this_len - skip);
+ c->textsize += this_len - skip + 1;
+ }
+ else
+ {
+ assert(this_len <= 1);
+ c->textsize += this_len - skip;
+ }
+
+ s->m_len = THRESHOLD;
+#ifdef SWD_BEST_OFF
+ if (s->use_best_off)
+ memset(s->best_pos,0,sizeof(s->best_pos));
+#endif
+ swd_findbest(s);
+ c->m_len = s->m_len;
+ c->m_off = s->m_off;
+
+ swd_getbyte(s);
+
+ if (s->b_char < 0)
+ {
+ c->look = 0;
+ c->m_len = 0;
+ swd_exit(s);
+ }
+ else
+ {
+ c->look = s->look + 1;
+ }
+ c->bp = c->ip - c->look;
+
+#if 0
+ /* brute force match search */
+ if (c->m_len > THRESHOLD && c->m_len + 1 <= c->look)
+ {
+ const uint8_t *ip = c->bp;
+ const uint8_t *m = c->bp - c->m_off;
+ const uint8_t *in = c->in;
+
+ if (ip - in > N)
+ in = ip - N;
+ for (;;)
+ {
+ while (*in != *ip)
+ in++;
+ if (in == ip)
+ break;
+ if (in != m)
+ if (memcmp(in,ip,c->m_len+1) == 0)
+ printf("%p %p %p %5d\n",in,ip,m,c->m_len);
+
+ in++;
+ }
+ }
+#endif
+
+ return UCL_E_OK;
+}
+
+
+static int bbConfig(struct ucl_compress *c, int endian, int bitsize)
+{
+ if (endian != -1)
+ {
+ if (endian != 0)
+ return UCL_E_ERROR;
+ c->bb_c_endian = endian;
+ }
+ if (bitsize != -1)
+ {
+ if (bitsize != 8 && bitsize != 16 && bitsize != 32 && bitsize != 64)
+ return UCL_E_ERROR;
+ c->bb_c_s = bitsize;
+ c->bb_c_s8 = bitsize / 8;
+ }
+ c->bb_b = 0; c->bb_k = 0;
+ c->bb_p = NULL;
+ c->bb_op = NULL;
+ return UCL_E_OK;
+}
+
+static void bbWriteBits(struct ucl_compress *c)
+{
+ uint8_t *p = c->bb_p;
+ uint64_t b = c->bb_b;
+
+ p[0] = (uint8_t)(b >> 0);
+ if (c->bb_c_s >= 16)
+ {
+ p[1] = (uint8_t)(b >> 8);
+ if (c->bb_c_s >= 32)
+ {
+ p[2] = (uint8_t)(b >> 16);
+ p[3] = (uint8_t)(b >> 24);
+ if (c->bb_c_s == 64)
+ {
+ p[4] = (uint8_t)(b >> 32);
+ p[5] = (uint8_t)(b >> 40);
+ p[6] = (uint8_t)(b >> 48);
+ p[7] = (uint8_t)(b >> 56);
+ }
+ }
+ }
+}
+
+
+static void bbPutBit(struct ucl_compress *c, unsigned bit)
+{
+ assert(bit == 0 || bit == 1);
+ assert(c->bb_k <= c->bb_c_s);
+
+ if (c->bb_k < c->bb_c_s)
+ {
+ if (c->bb_k == 0)
+ {
+ assert(c->bb_p == NULL);
+ c->bb_p = c->bb_op;
+ c->bb_op += c->bb_c_s8;
+ }
+ assert(c->bb_p != NULL);
+ assert(c->bb_p + c->bb_c_s8 <= c->bb_op);
+
+ c->bb_b = (c->bb_b << 1) + bit;
+ c->bb_k++;
+ }
+ else
+ {
+ assert(c->bb_p != NULL);
+ assert(c->bb_p + c->bb_c_s8 <= c->bb_op);
+
+ bbWriteBits(c);
+ c->bb_p = c->bb_op;
+ c->bb_op += c->bb_c_s8;
+ c->bb_b = bit;
+ c->bb_k = 1;
+ }
+}
+
+
+static void bbPutByte(struct ucl_compress *c, unsigned b)
+{
+ /**printf("putbyte %p %p %x (%d)\n", op, bb_p, x, bb_k);*/
+ assert(c->bb_p == NULL || c->bb_p + c->bb_c_s8 <= c->bb_op);
+ *c->bb_op++ = (uint8_t)(b);
+}
+
+static void bbFlushBits(struct ucl_compress *c, unsigned filler_bit)
+{
+ if (c->bb_k > 0)
+ {
+ assert(c->bb_k <= c->bb_c_s);
+ while (c->bb_k != c->bb_c_s)
+ bbPutBit(c, filler_bit);
+ bbWriteBits(c);
+ c->bb_k = 0;
+ }
+ c->bb_p = NULL;
+}
+
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+
+static void code_prefix_ss11(struct ucl_compress *c, uint32_t i)
+{
+ if (i >= 2)
+ {
+ uint32_t t = 4;
+ i += 2;
+ do {
+ t <<= 1;
+ } while (i >= t);
+ t >>= 1;
+ do {
+ t >>= 1;
+ bbPutBit(c, (i & t) ? 1 : 0);
+ bbPutBit(c, 0);
+ } while (t > 2);
+ }
+ bbPutBit(c, (unsigned)i & 1);
+ bbPutBit(c, 1);
+}
+
+static void
+code_match(struct ucl_compress *c, unsigned int m_len, const unsigned int m_off)
+
+{
+ while (m_len > c->conf.max_match)
+ {
+ code_match(c, c->conf.max_match - 3, m_off);
+ m_len -= c->conf.max_match - 3;
+ }
+
+ c->match_bytes += m_len;
+ if (m_len > c->result[3])
+ c->result[3] = m_len;
+ if (m_off > c->result[1])
+ c->result[1] = m_off;
+
+ bbPutBit(c, 0);
+
+ if (m_off == c->last_m_off)
+ {
+ bbPutBit(c, 0);
+ bbPutBit(c, 1);
+ }
+ else
+ {
+ code_prefix_ss11(c, 1 + ((m_off - 1) >> 8));
+ bbPutByte(c, (unsigned)m_off - 1);
+ }
+ m_len = m_len - 1 - (m_off > M2_MAX_OFFSET);
+ if (m_len >= 4)
+ {
+ bbPutBit(c,0);
+ bbPutBit(c,0);
+ code_prefix_ss11(c, m_len - 4);
+ }
+ else
+ {
+ bbPutBit(c, m_len > 1);
+ bbPutBit(c, (unsigned)m_len & 1);
+ }
+
+ c->last_m_off = m_off;
+}
+
+static void
+code_run(struct ucl_compress *c, const uint8_t *ii, unsigned int lit)
+{
+ if (lit == 0)
+ return;
+ c->lit_bytes += lit;
+ if (lit > c->result[5])
+ c->result[5] = lit;
+ do {
+ bbPutBit(c, 1);
+ bbPutByte(c, *ii++);
+ } while (--lit > 0);
+}
+
+/***********************************************************************
+//
+************************************************************************/
+
+static int
+len_of_coded_match(struct ucl_compress *c, unsigned int m_len, unsigned int
+ m_off)
+
+{
+ int b;
+ if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
+ || m_off > c->conf.max_offset)
+ return -1;
+ assert(m_off > 0);
+
+ m_len = m_len - 2 - (m_off > M2_MAX_OFFSET);
+
+ if (m_off == c->last_m_off)
+ b = 1 + 2;
+ else
+ {
+ b = 1 + 10;
+ m_off = (m_off - 1) >> 8;
+ while (m_off > 0)
+ {
+ b += 2;
+ m_off >>= 1;
+ }
+ }
+
+ b += 2;
+ if (m_len < 3)
+ return b;
+ m_len -= 3;
+
+ do {
+ b += 2;
+ m_len >>= 1;
+ } while (m_len > 0);
+
+ return b;
+}
+
+#ifdef VBOX
+static
+#endif
+int ucl_nrv2b_99_compress(
+ const uint8_t *in, unsigned long in_len,
+ uint8_t *out, unsigned long *out_len,
+ unsigned int *result)
+{
+ const uint8_t *ii;
+ unsigned int lit;
+ unsigned int m_len, m_off;
+ struct ucl_compress c_buffer;
+ struct ucl_compress * const c = &c_buffer;
+ struct ucl_swd *swd;
+ unsigned int result_buffer[16];
+ int r;
+
+/* max compression */
+#define SC_TRY_LAZY 2
+#define SC_GOOD_LENGTH F
+#define SC_MAX_LAZY F
+#define SC_NICE_LENGTH F
+#define SC_MAX_CHAIN 4096
+#define SC_FLAGS 1
+#define SC_MAX_OFFSET N
+
+ memset(c, 0, sizeof(*c));
+ c->ip = c->in = in;
+ c->in_end = in + in_len;
+ c->out = out;
+ c->result = result ? result : result_buffer;
+ memset(c->result, 0, 16*sizeof(*c->result));
+ c->result[0] = c->result[2] = c->result[4] = UINT_MAX;
+ result = NULL;
+ memset(&c->conf, 0xff, sizeof(c->conf));
+ r = bbConfig(c, ENDIAN, BITSIZE);
+ if (r == 0)
+ r = bbConfig(c, c->conf.bb_endian, c->conf.bb_size);
+ if (r != 0)
+ return UCL_E_INVALID_ARGUMENT;
+ c->bb_op = out;
+
+ ii = c->ip; /* point to start of literal run */
+ lit = 0;
+
+
+ swd = (struct ucl_swd *) malloc(sizeof(*swd));
+ if (!swd)
+ return UCL_E_OUT_OF_MEMORY;
+#ifdef VBOX
+ memset(swd, 0, sizeof(*swd));
+#endif
+
+ swd->f = F;
+ swd->n = N;
+ if (in_len >= 256 && in_len < swd->n)
+ swd->n = in_len;
+ if (swd->f < 8 || swd->n < 256)
+ return UCL_E_INVALID_ARGUMENT;
+
+ r = init_match(c,swd,NULL,0, SC_FLAGS);
+ if (r != UCL_E_OK)
+ {
+ free(swd);
+ return r;
+ }
+ if (SC_MAX_CHAIN > 0)
+ swd->max_chain = SC_MAX_CHAIN;
+ if (SC_NICE_LENGTH > 0)
+ swd->nice_length = SC_NICE_LENGTH;
+ if (c->conf.max_match < swd->nice_length)
+ swd->nice_length = c->conf.max_match;
+
+ c->last_m_off = 1;
+ r = find_match(c,swd,0,0);
+ if (r != UCL_E_OK)
+ return r;
+ while (c->look > 0)
+ {
+ unsigned int ahead;
+ unsigned int max_ahead;
+ int l1, l2;
+
+ c->codesize = c->bb_op - out;
+
+ m_len = c->m_len;
+ m_off = c->m_off;
+
+ assert(c->bp == c->ip - c->look);
+ assert(c->bp >= in);
+ if (lit == 0)
+ ii = c->bp;
+ assert(ii + lit == c->bp);
+ assert(swd->b_char == *(c->bp));
+
+ if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
+ || m_off > c->conf.max_offset)
+ {
+ /* a literal */
+ lit++;
+ swd->max_chain = SC_MAX_CHAIN;
+ r = find_match(c,swd,1,0);
+ assert(r == 0);
+ continue;
+ }
+
+ /* a match */
+ assert_match(swd,m_len,m_off);
+
+ /* shall we try a lazy match ? */
+ ahead = 0;
+ if (SC_TRY_LAZY <= 0 || m_len >= SC_MAX_LAZY || m_off ==
+ c->last_m_off)
+
+ {
+ /* no */
+ l1 = 0;
+ max_ahead = 0;
+ }
+ else
+ {
+ /* yes, try a lazy match */
+ l1 = len_of_coded_match(c,m_len,m_off);
+ assert(l1 > 0);
+ max_ahead = SC_TRY_LAZY;
+ if ((m_len - 1) < max_ahead) {
+ max_ahead = m_len -1;
+ }
+ }
+
+ while (ahead < max_ahead && c->look > m_len)
+ {
+ if (m_len >= SC_GOOD_LENGTH)
+ swd->max_chain = SC_MAX_CHAIN >> 2;
+ else
+ swd->max_chain = SC_MAX_CHAIN;
+ r = find_match(c,swd,1,0);
+ ahead++;
+
+ assert(r == 0);
+ assert(c->look > 0);
+ assert(ii + lit + ahead == c->bp);
+
+ if (c->m_len < 2)
+ continue;
+ l2 = len_of_coded_match(c,c->m_len,c->m_off);
+ if (l2 < 0)
+ continue;
+ if (l1 + (int)(ahead + c->m_len - m_len) * 5 > l2 +
+ (int)(ahead) * 9)
+ {
+ c->lazy++;
+ assert_match(swd,c->m_len,c->m_off);
+ lit += ahead;
+ assert(ii + lit == c->bp);
+ goto lazy_match_done;
+ }
+ }
+
+ assert(ii + lit + ahead == c->bp);
+
+ /* 1 - code run */
+ code_run(c,ii,lit);
+ lit = 0;
+
+ /* 2 - code match */
+ code_match(c,m_len,m_off);
+ swd->max_chain = SC_MAX_CHAIN;
+ r = find_match(c,swd,m_len,1+ahead);
+ assert(r == 0);
+
+ lazy_match_done: ;
+ }
+
+ /* store final run */
+ code_run(c,ii,lit);
+
+ /* EOF */
+ bbPutBit(c, 0);
+ code_prefix_ss11(c, 0x1000000U);
+ bbPutByte(c, 0xff);
+
+ bbFlushBits(c, 0);
+
+ assert(c->textsize == in_len);
+ c->codesize = c->bb_op - out;
+ *out_len = c->bb_op - out;
+
+#if 0
+ printf("%7ld %7ld -> %7ld %7ld %7ld %ld (max: %d %d %d)\n",
+ (long) c->textsize, (long) in_len, (long) c->codesize,
+ c->match_bytes, c->lit_bytes, c->lazy,
+ c->result[1], c->result[3], c->result[5]);
+#endif
+ assert(c->lit_bytes + c->match_bytes == in_len);
+
+ swd_exit(swd);
+ free(swd);
+
+ return UCL_E_OK;
+}
+
+
+#ifdef VBOX
+static
+#endif
+void Encode(void) /* compression */
+{
+ uint8_t *in, *out;
+ unsigned long in_len, out_len;
+ uint32_t tw;
+ int r;
+ fseek(infile, 0, SEEK_END);
+ in_len = ftell(infile);
+#ifdef VERBOSE
+ if ((signed long)in_len < 0)
+ Fprintf((stderr, "Errno: %d", errno));
+#endif
+#if UCLPACK_COMPAT
+ {
+ uint8_t byte;
+ if (fwrite(magic, sizeof(magic), 1, outfile) != 1)
+ Error("Can't write.");
+ tw = htonl(0); /* flags */
+ if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
+ Error("Can't write.");
+ byte = 0x2b; /* method */
+ if (fwrite(&byte, sizeof(byte), 1, outfile) != 1)
+ Error("Can't write.");
+ byte = 10; /* level */
+ if (fwrite(&byte, sizeof(byte), 1, outfile) != 1)
+ Error("Can't write.");
+ tw = htonl(256*1024); /* block_size */
+ if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
+ Error("Can't write.");
+ tw = htonl(in_len);
+ if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
+ Error("Can't write."); /* output size of text */
+ }
+#else
+ tw = host_to_i86ul(in_len);
+ if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
+ Error("Can't write."); /* output size of text */
+#endif
+ if (in_len == 0)
+ return;
+ rewind(infile);
+
+ in = malloc(in_len);
+ out_len = in_len + (in_len/8) + 256;
+ out = malloc(out_len);
+ if (!in || !out) {
+ Error("Can't malloc");
+ }
+ if (fread(in, in_len, 1, infile) != 1) {
+ Error("Can't read");
+ }
+ r = ucl_nrv2b_99_compress(in, in_len, out, &out_len, 0 );
+ if (r != UCL_E_OK)
+ Error("Compression failure\n");
+#if UCLPACK_COMPAT
+ tw = htonl(out_len);
+ if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
+ Error("Can't write."); /* file size of text */
+
+#endif
+ if (fwrite(out, out_len, 1, outfile) != 1) {
+ Error("Write error\n");
+ }
+#if UCLPACK_COMPAT
+ tw = htonl(0); /* EOF marker */
+ if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
+ Error("Can't write.");
+
+#endif
+
+#ifdef LONG_REPORT
+ Fprintf((stdout, "input size %ld bytes\n", in_len));
+ Fprintf((stdout, "output size %ld bytes\n", out_len));
+ Fprintf((stdout, "input/output %.3f\n", (double)in_len / out_len));
+#else
+ Fprintf((stdout, "input/output = %ld/%ld = %.3f\n", in_len, out_len,
+ (double)in_len / out_len));
+#endif
+
+}
+
+#endif
+
+#ifdef DECODE
+
+#define GETBIT_8(bb, src, ilen) \
+ (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)
+
+#define GETBIT_LE16(bb, src, ilen) \
+ (bb*=2,bb&0xffff ? (bb>>16)&1 : (ilen+=2,((bb=(src[ilen-2]+src[ilen-1]*256u)*2+1)>>16)&1))
+
+#define GETBIT_LE32(bb, src, ilen) \
+ (bc > 0 ? ((bb>>--bc)&1) : (bc=31,\
+ bb=*(const uint32_t *)((src)+ilen),ilen+=4,(bb>>31)&1))
+
+#define GETBIT_LE64(bb, src, ilen) \
+ (bc > 0 ? ((bb>>--bc)&1) : (bc=63, \
+ bb=*(const uint64_t *)((src)+ilen),ilen+=8,(bb>>63)&1))
+
+#if ENDIAN == 0 && BITSIZE == 8
+#define GETBIT(bb, src, ilen) GETBIT_8(bb, src, ilen)
+#endif
+#if ENDIAN == 0 && BITSIZE == 16
+#define GETBIT(bb, src, ilen) GETBIT_LE16(bb, src, ilen)
+#endif
+#if ENDIAN == 0 && BITSIZE == 32
+#define GETBIT(bb, src, ilen) GETBIT_LE32(bb, src, ilen)
+#endif
+#if ENDIAN == 0 && BITSIZE == 64
+#define GETBIT(bb, src, ilen) GETBIT_LE64(bb, src, ilen)
+#endif
+#ifndef GETBIT
+#error "Bad Combination of ENDIAN and BITSIZE values specified"
+#endif
+
+#undef SAFE
+
+#ifdef SAFE
+#define FAIL(x,r) if (x) { Error(r); }
+#else
+#define FAIL(x,r)
+#endif
+
+#ifdef VBOX
+static
+#endif
+void Decode(void) /* recover */
+{
+ uint32_t tw;
+ uint8_t *src, *dst;
+ unsigned long max_src_len, src_len, dst_len;
+ unsigned long ilen = 0, olen = 0, last_m_off = 1;
+#if BITSIZE <= 32
+ uint32_t bb = 0;
+#elif BITSIZE == 64
+ uint64_t bb = 0;
+#endif
+ unsigned bc = 0;
+#if UCLPACK_COMPAT
+ if (fseek(infile, sizeof(magic) + sizeof(tw) + 1 + 1 + sizeof(tw),
+ SEEK_SET) != 0)
+
+ Error("Seek Error");
+ if (fread(&tw, sizeof(tw), 1, infile) < 1)
+ Error("Can't read"); /* read size of text */
+ dst_len = ntohl(tw);
+ if (fread(&tw, sizeof(tw), 1, infile) < 1)
+ Error("Can't read"); /* read size of file */
+ max_src_len = ntohl(tw);
+#else
+ if (fread(&tw, sizeof(tw), 1, infile) < 1)
+ Error("Can't read"); /* read size of text */
+ dst_len = i86ul_to_host(tw);
+ max_src_len = dst_len + (dst_len/8) + 256;
+#endif
+ if (dst_len == 0)
+ return;
+ dst = malloc(dst_len);
+ if (!dst)
+ Error("Can't malloc");
+ src = malloc(max_src_len);
+ if (!src)
+ Error("Can't malloc");
+ src_len = fread(src, 1, max_src_len, infile);
+ if (src_len <= 0)
+ Error("Can't read");
+
+ for(;;) {
+ unsigned int m_off, m_len;
+ while(GETBIT(bb, src, ilen)) {
+ FAIL(ilen >= src_len, "input overrun");
+ FAIL(olen >= dst_len, "output overrun");
+ dst[olen++] = src[ilen++];
+ }
+ m_off = 1;
+ do {
+ m_off = m_off*2 + GETBIT(bb, src, ilen);
+ FAIL(ilen >= src_len, "input overrun");
+ FAIL(m_off > 0xffffffU +3, "lookbehind overrun");
+ } while (!GETBIT(bb, src, ilen));
+ if (m_off == 2)
+ {
+ m_off = last_m_off;
+ }
+ else
+ {
+ FAIL(ilen >= src_len, "input overrun");
+ m_off = (m_off - 3)*256 + src[ilen++];
+ if (m_off == 0xffffffffU)
+ break;
+ last_m_off = ++m_off;
+ }
+ m_len = GETBIT(bb, src, ilen);
+ m_len = m_len*2 + GETBIT(bb, src, ilen);
+ if (m_len == 0)
+ {
+ m_len++;
+ do {
+ m_len = m_len*2 + GETBIT(bb, src, ilen);
+ FAIL(ilen >= src_len, "input overrun");
+ FAIL(m_len >= dst_len, "output overrun");
+ } while(!GETBIT(bb, src, ilen));
+ m_len += 2;
+ }
+ m_len += (m_off > 0xd00);
+ FAIL(olen + m_len > dst_len, "output overrun");
+ FAIL(m_off > olen, "lookbeind overrun");
+ {
+ const uint8_t *m_pos;
+ m_pos = dst + olen - m_off;
+ dst[olen++] = *m_pos++;
+ do {
+ dst[olen++] = *m_pos++;
+ } while(--m_len > 0);
+ }
+ }
+ FAIL(ilen < src_len, "input not consumed");
+ FAIL(ilen > src_len, "input overrun");
+ assert(ilen == src_len);
+ Fprintf((stderr, "%12ld\n", olen));
+ if (dst_len != olen) {
+ fprintf(stderr, "length != expected length\n");
+ }
+ if (fwrite(dst, olen, 1, outfile) != 1)
+ Error("Write error\n");
+ free(src);
+ free(dst);
+}
+#endif
+
+#ifdef MAIN
+int main(int argc, char *argv[])
+{
+ char *s;
+ FILE *f;
+ int c;
+
+ if (argc == 2) {
+ outfile = stdout;
+ if ((f = tmpfile()) == NULL) {
+ perror("tmpfile");
+ return EXIT_FAILURE;
+ }
+ while ((c = getchar()) != EOF)
+ fputc(c, f);
+ rewind(infile = f);
+ }
+ else if (argc != 4) {
+ Fprintf((stderr, "'nrv2b e file1 file2' encodes file1 into file2.\n"
+ "'nrv2b d file2 file1' decodes file2 into file1.\n"));
+ return EXIT_FAILURE;
+ }
+ if (argc == 4) {
+ if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
+ || (s = argv[2], (infile = fopen(s, "rb")) == NULL)
+ || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
+ Fprintf((stderr, "??? %s\n", s));
+ return EXIT_FAILURE;
+ }
+ }
+ if (toupper(*argv[1]) == 'E')
+ Encode();
+ else
+ Decode();
+ fclose(infile);
+ fclose(outfile);
+ return EXIT_SUCCESS;
+}
+#endif
diff --git a/src/VBox/Devices/PC/ipxe/src/util/padimg.pl b/src/VBox/Devices/PC/ipxe/src/util/padimg.pl
new file mode 100755
index 00000000..4421aaf4
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/padimg.pl
@@ -0,0 +1,44 @@
+#!/usr/bin/perl -w
+
+use strict;
+use warnings;
+use Getopt::Long;
+use Fcntl;
+
+my $verbosity = 0;
+my $blksize = 512;
+my $byte = 0;
+
+my %opts = (
+ 'verbose|v+' => sub { $verbosity++; },
+ 'quiet|q+' => sub { $verbosity--; },
+ 'blksize|s=o' => sub { $blksize = $_[1]; },
+ 'byte|b=o' => sub { $byte = $_[1]; },
+);
+
+Getopt::Long::Configure ( 'bundling', 'auto_abbrev' );
+GetOptions ( %opts ) or die "Could not parse command-line options\n";
+
+while ( my $filename = shift ) {
+ die "$filename is not a file\n" unless -f $filename;
+ my $oldsize = -s $filename;
+ my $padsize = ( ( -$oldsize ) % $blksize );
+ my $newsize = ( $oldsize + $padsize );
+ next unless $padsize;
+ if ( $verbosity >= 1 ) {
+ printf "Padding %s from %d to %d bytes with %d x 0x%02x\n",
+ $filename, $oldsize, $newsize, $padsize, $byte;
+ }
+ if ( $byte ) {
+ sysopen ( my $fh, $filename, ( O_WRONLY | O_APPEND ) )
+ or die "Could not open $filename for appending: $!\n";
+ syswrite $fh, ( chr ( $byte ) x $padsize )
+ or die "Could not append to $filename: $!\n";
+ close ( $fh );
+ } else {
+ truncate $filename, $newsize
+ or die "Could not resize $filename: $!\n";
+ }
+ die "Failed to pad $filename\n"
+ unless ( ( ( -s $filename ) % $blksize ) == 0 );
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/util/parserom.pl b/src/VBox/Devices/PC/ipxe/src/util/parserom.pl
new file mode 100755
index 00000000..e278e633
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/parserom.pl
@@ -0,0 +1,66 @@
+#!/usr/bin/env perl
+#
+# Parse PCI_ROM and ISA_ROM entries from a source file on stdin and
+# output the relevant Makefile variable definitions to stdout
+#
+# Based upon portions of Ken Yap's genrules.pl
+
+use strict;
+use warnings;
+
+die "Syntax: $0 driver_source.c" unless @ARGV == 1;
+my $source = shift;
+open DRV, "<$source" or die "Could not open $source: $!\n";
+
+( my $family, my $driver_name ) = ( $source =~ /^(.*?([^\/]+))\..$/ )
+ or die "Could not parse source file name \"$source\"\n";
+
+my $printed_family;
+
+sub rom {
+ ( my $type, my $image, my $desc, my $vendor, my $device, my $dup ) = @_;
+ my $ids = $vendor ? "$vendor,$device" : "-";
+ unless ( $printed_family ) {
+ print "\n";
+ print "# NIC\t\n";
+ print "# NIC\tfamily\t$family\n";
+ print "DRIVERS += $driver_name\n";
+ $printed_family = 1;
+ }
+ print "\n";
+ return if ( $vendor && ( ( $vendor eq "ffff" ) || ( $device eq "ffff" ) ) );
+ print "# NIC\t$image\t$ids\t$desc\n";
+ print "DRIVER_$image = $driver_name\n";
+ print "ROM_TYPE_$image = $type\n";
+ print "ROM_DESCRIPTION_$image = \"$desc\"\n";
+ print "PCI_VENDOR_$image = 0x$vendor\n" if $vendor;
+ print "PCI_DEVICE_$image = 0x$device\n" if $device;
+ print "ROMS += $image\n" unless $dup;
+ print "ROMS_$driver_name += $image\n" unless $dup;
+}
+
+while ( <DRV> ) {
+ next unless /(PCI|ISA)_ROM\s*\(/;
+
+ if ( /^\s*PCI_ROM\s*\(
+ \s*0x([0-9A-Fa-f]{4})\s*, # PCI vendor
+ \s*0x([0-9A-Fa-f]{4})\s*, # PCI device
+ \s*\"([^\"]*)\"\s*, # Image
+ \s*\"([^\"]*)\"\s*, # Description
+ \s*.*\s* # Driver data
+ \)/x ) {
+ ( my $vendor, my $device, my $image, my $desc ) = ( lc $1, lc $2, $3, $4 );
+ rom ( "pci", lc "${vendor}${device}", $desc, $vendor, $device );
+ rom ( "pci", $image, $desc, $vendor, $device, 1 );
+ } elsif ( /^\s*ISA_ROM\s*\(
+ \s*\"([^\"]*)\"\s*, # Image
+ \s*\"([^\"]*)\"\s* # Description
+ \)/x ) {
+ ( my $image, my $desc ) = ( $1, $2 );
+ rom ( "isa", $image, $desc );
+ } else {
+ warn "Malformed PCI_ROM or ISA_ROM macro on line $. of $source\n";
+ }
+}
+
+close DRV;
diff --git a/src/VBox/Devices/PC/ipxe/src/util/romcheck.pl b/src/VBox/Devices/PC/ipxe/src/util/romcheck.pl
new file mode 100755
index 00000000..f47bb07e
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/romcheck.pl
@@ -0,0 +1,54 @@
+#!/usr/bin/perl -w
+
+use strict;
+use warnings;
+
+use constant DEVICES => "/proc/bus/pci/devices";
+
+open my $fh, DEVICES
+ or die "Could not open ".DEVICES.": $!";
+
+while ( ( my $line = <$fh> ) ) {
+
+ # Parse line from /proc/bus/pci/devices
+ chomp $line;
+ ( my $bus, my $devfn, my $vendor, my $device, my $irq, my $bars, my $lengths,
+ my $driver )
+ = ( $line =~ /^ ([0-9a-f]{2}) ([0-9a-f]{2}) \s+
+ ([0-9a-f]{4}) ([0-9a-f]{4}) \s+ ([0-9a-f]+) \s+
+ ((?:[0-9a-f]+\s+){7}) ((?:[0-9a-f]+\s+){7})
+ (.+)?$/x )
+ or die "Invalid line \"".$line."\"\n";
+ ( $bus, $devfn, $vendor, $device, $irq ) =
+ map { hex ( $_ ) } ( $bus, $devfn, $vendor, $device, $irq );
+ my $dev = ( $devfn >> 3 );
+ my $fn = ( $devfn & 0x7 );
+ $bars = [ map { hex ( $_ ) } split ( /\s+/, $bars ) ];
+ $lengths = [ map { hex ( $_ ) } split ( /\s+/, $lengths ) ];
+
+ # Calculate expansion ROM BAR presence and length
+ my $rom_length = $lengths->[6];
+
+ # Look for a BAR that could support a .mrom
+ my $mrom_ok;
+ if ( $rom_length ) {
+ for ( my $bar = 0 ; $bar < 7 ; $bar++ ) {
+ # Skip I/O BARs
+ next if $bars->[$bar] & 0x01;
+ # Skip low half of 64-bit BARs
+ $bar++ if $bars->[$bar] & 0x04;
+ # Skip 64-bit BARs with high dword set
+ next if $bars->[$bar] >> 32;
+ # Skip BARs smaller than the expansion ROM BAR
+ next if $lengths->[$bar] < $rom_length;
+ # This BAR is usable!
+ $mrom_ok = 1;
+ last;
+ }
+ }
+
+ printf "%02x:%02x.%x (%04x:%04x)", $bus, $dev, $fn, $vendor, $device;
+ printf " supports a %dkB .rom", ( $rom_length / 1024 ) if $rom_length;
+ printf " or .mrom" if $mrom_ok;
+ printf "\n";
+}
diff --git a/src/VBox/Devices/PC/ipxe/src/util/sortobjdump.pl b/src/VBox/Devices/PC/ipxe/src/util/sortobjdump.pl
new file mode 100755
index 00000000..1373a7ff
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/sortobjdump.pl
@@ -0,0 +1,40 @@
+#!/usr/bin/perl -w
+
+use strict;
+use warnings;
+
+# Sort the symbol table portion of the output of objdump -ht by
+# section, then by symbol value, then by size. Used to enhance the
+# linker maps produced by "make bin/%.map" by also showing the values
+# of all non-global symbols.
+
+my %section_idx = ( "*ABS*" => ".", "*UND*" => "_" );
+my %lines;
+while ( <> ) {
+ if ( /^\s+(\d+)\s+([\.\*]\S+)\s+[0-9a-fA-F]+\s+[0-9a-fA-F]/ ) {
+ # It's a header line containing a section definition; extract the
+ # section index and store it. Also print the header line.
+ print;
+ ( my $index, my $section ) = ( $1, $2 );
+ $section_idx{$section} = sprintf ( "%02d", $index );
+ } elsif ( /^([0-9a-fA-F]+)\s.*?\s([\.\*]\S+)\s+([0-9a-fA-F]+)\s+(\S+)/ ) {
+ # It's a symbol line - store it in the hash, indexed by
+ # "<section_index>:<value>:<size>:<end_tag>". <end_tag> is "0" if
+ # the symbol name is of the form xxx_end, "1" otherwise; this is
+ # done so that table end markers show up before any other symbols
+ # with the same value.
+ ( my $value, my $section, my $size, my $name ) = ( $1, $2, $3, $4 );
+ die "Unrecognised section \"$section\"\n"
+ unless exists $section_idx{$section};
+ my $section_idx = $section_idx{$section};
+ my $end = ( $name =~ /_end$/ ) ? "0" : "1";
+ my $key = $section_idx.":".$value.":".$size.":".$end;
+ $lines{$key} ||= '';
+ $lines{$key} .= $_;
+ } else {
+ # It's a generic header line: just print it.
+ print;
+ }
+}
+
+print $lines{$_} foreach sort keys %lines;
diff --git a/src/VBox/Devices/PC/ipxe/src/util/swapdevids.pl b/src/VBox/Devices/PC/ipxe/src/util/swapdevids.pl
new file mode 100755
index 00000000..c6255ae7
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/swapdevids.pl
@@ -0,0 +1,49 @@
+#!/usr/bin/perl -w
+#
+# Program to reverse the device identifier IDs in the PCIR and PnP
+# structures in a ROM for old non-compliant BIOSes
+#
+# GPL, Ken Yap 2001
+#
+
+use bytes;
+
+use IO::Seekable;
+
+sub swaplocs ($$$)
+{
+ my ($dataref, $loc1, $loc2) = @_;
+ my ($t);
+
+ $t = substr($$dataref, $loc1, 1);
+ substr($$dataref, $loc1, 1) = substr($$dataref, $loc2, 1);
+ substr($$dataref, $loc2, 1) = $t;
+}
+
+sub printdevids ($$)
+{
+ my ($dataref, $loc) = @_;
+
+ return (sprintf "%02x %02x %02x", unpack('C3', substr($$dataref, $loc, 3)));
+}
+
+$#ARGV >= 0 or die "Usage: $0 romimage\n";
+$file = $ARGV[0];
+open(F, "+<$file") or die "$file: $!\n";
+binmode(F);
+# Handle up to 64kB ROM images
+$len = read(F, $data, 64*1024);
+defined($len) or die "$file: $!\n";
+substr($data, 0, 2) eq "\x55\xAA" or die "$file: Not a boot ROM image\n";
+($pci, $pnp) = unpack('v2', substr($data, 0x18, 4));
+($pci < $len and $pnp < $len) or die "$file: Not a PCI PnP ROM image\n";
+(substr($data, $pci, 4) eq 'PCIR' and substr($data, $pnp, 4) eq '$PnP')
+ or die "$file: No PCI and PNP structures, not a PCI PNP ROM image\n";
+&swaplocs(\$data, $pci+13, $pci+15);
+&swaplocs(\$data, $pnp+18, $pnp+20);
+seek(F, 0, SEEK_SET) or die "$file: Cannot seek to beginning\n";
+print F $data;
+close(F);
+print "PCI devids now: ", &printdevids(\$data, $pci+13), "\n";
+print "PnP devids now: ", &printdevids(\$data, $pnp+18), "\n";
+exit(0);
diff --git a/src/VBox/Devices/PC/ipxe/src/util/symcheck.pl b/src/VBox/Devices/PC/ipxe/src/util/symcheck.pl
new file mode 100755
index 00000000..8925ca62
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/symcheck.pl
@@ -0,0 +1,191 @@
+#!/usr/bin/perl -w
+
+use strict;
+use warnings;
+
+use constant WARNING_SIZE => 512;
+
+my $symtab = {};
+
+# Scan output of "objdump -w -t bin/blib.a" and build up symbol table
+#
+my $object;
+while ( <> ) {
+ chomp;
+ if ( /^In archive/ ) {
+ # Do nothing
+ } elsif ( /^$/ ) {
+ # Do nothing
+ } elsif ( /^(\S+\.o):\s+file format/ ) {
+ $object = $1;
+ } elsif ( /^SYMBOL TABLE:/ ) {
+ # Do nothing
+ } elsif ( /^([0-9a-fA-F]+)\s(l|g|\s)......\s(\S+)\s+([0-9a-fA-F]+)\s+(\S+)$/ ) {
+ my $value = $1;
+ my $scope = $2;
+ my $section = $3;
+ my $size = $4;
+ my $symbol = $5;
+ $symtab->{$object}->{$symbol} = {
+ global => ( $scope ne "l" ),
+ section => ( $section eq "*UND*" ? undef : $section ),
+ value => ( $value ? hex ( $value ) : 0 ),
+ size => ( $size ? hex ( $size ) : 0 ),
+ };
+ } else {
+ die "Unrecognized line \"$_\"";
+ }
+}
+
+# Add symbols that we know will be generated or required by the linker
+#
+foreach my $object ( keys %$symtab ) {
+ my $obj_symbol = "obj_$object";
+ $obj_symbol =~ s/\.o$//;
+ $obj_symbol =~ s/\W/_/g;
+ $symtab->{LINKER}->{$obj_symbol} = {
+ global => 1,
+ section => undef,
+ value => 0,
+ size => 0,
+ };
+}
+foreach my $link_sym qw ( __prefix _prefix _prefix_load_offset
+ _prefix_size _prefix_progbits_size _prefix_size_pgh
+ __text16 _text16 _text16_load_offset
+ _text16_size _text16_progbits_size _text16_size_pgh
+ __data16 _data16 _data16_load_offset
+ _data16_size _data16_progbits_size _data16_size_pgh
+ __text _text __data _data _textdata_load_offset
+ _textdata_size _textdata_progbits_size
+ __rodata __bss _end
+ _payload_offset _max_align
+ _load_size _load_size_pgh _load_size_sect
+ pci_vendor_id pci_device_id ) {
+ $symtab->{LINKER}->{$link_sym} = {
+ global => 1,
+ section => '*ABS*',
+ value => 0,
+ size => 0,
+ };
+}
+
+# Add symbols that we know will be used by the debug system
+#
+foreach my $debug_sym qw ( dbg_autocolourise dbg_decolourise
+ dbg_hex_dump_da ) {
+ $symtab->{DEBUG}->{$debug_sym} = {
+ global => 1,
+ section => undef,
+ value => 0,
+ size => 0,
+ };
+}
+
+# Build up requires, provides and shares symbol tables for global
+# symbols
+#
+my $globals = {};
+while ( ( my $object, my $symbols ) = each %$symtab ) {
+ while ( ( my $symbol, my $info ) = each %$symbols ) {
+ if ( $info->{global} ) {
+ my $category;
+ if ( ! defined $info->{section} ) {
+ $category = "requires";
+ } elsif ( $info->{section} eq "*COM*" ) {
+ $category = "shares";
+ } else {
+ $category = "provides";
+ }
+ $globals->{$symbol}->{$category}->{$object} = 1;
+ }
+ }
+}
+
+# Check for multiply defined, never-defined and unused global symbols
+#
+my $problems = {};
+while ( ( my $symbol, my $info ) = each %$globals ) {
+ my @provides = keys %{$info->{provides}};
+ my @requires = keys %{$info->{requires}};
+ my @shares = keys %{$info->{shares}};
+
+ if ( ( @provides == 0 ) && ( @shares == 1 ) ) {
+ # A symbol "shared" by just a single file is actually being
+ # provided by that file; it just doesn't have an initialiser.
+ @provides = @shares;
+ @shares = ();
+ }
+
+ if ( ( @requires > 0 ) && ( @provides == 0 ) && ( @shares == 0 ) ) {
+ # No object provides this symbol, but some objects require it.
+ $problems->{$_}->{nonexistent}->{$symbol} = 1 foreach @requires;
+ }
+
+ if ( ( @requires == 0 ) && ( @provides > 0 ) ) {
+ # No object requires this symbol, but some objects provide it.
+ foreach my $provide ( @provides ) {
+ if ( $provide eq "LINKER" ) {
+ # Linker-provided symbols are exempt from this check.
+ } elsif ( $symtab->{$provide}->{$symbol}->{section} =~ /^\.tbl\./ ) {
+ # Linker tables are exempt from this check.
+ } else {
+ $problems->{$provide}->{unused}->{$symbol} = 1;
+ }
+ }
+ }
+
+ if ( ( @shares > 0 ) && ( @provides > 0 ) ) {
+ # A shared symbol is being initialised by an object
+ $problems->{$_}->{shared}->{$symbol} = 1 foreach @provides;
+ }
+
+ if ( @provides > 1 ) {
+ # A non-shared symbol is defined in multiple objects
+ $problems->{$_}->{multiples}->{$symbol} = 1 foreach @provides;
+ }
+}
+
+# Check for excessively large local symbols. Text and rodata symbols
+# are exempt from this check
+#
+while ( ( my $object, my $symbols ) = each %$symtab ) {
+ while ( ( my $symbol, my $info ) = each %$symbols ) {
+ if ( ( ! $info->{global} ) &&
+ ( ( defined $info->{section} ) &&
+ ! ( $info->{section} =~ /^(\.text|\.rodata)/ ) ) &&
+ ( $info->{size} >= WARNING_SIZE ) ) {
+ $problems->{$object}->{large}->{$symbol} = 1;
+ }
+ }
+}
+
+# Print out error messages
+#
+my $errors = 0;
+my $warnings = 0;
+foreach my $object ( sort keys %$problems ) {
+ my @nonexistent = sort keys %{$problems->{$object}->{nonexistent}};
+ my @multiples = sort keys %{$problems->{$object}->{multiples}};
+ my @unused = sort keys %{$problems->{$object}->{unused}};
+ my @shared = sort keys %{$problems->{$object}->{shared}};
+ my @large = sort keys %{$problems->{$object}->{large}};
+
+ print "WARN $object provides unused symbol $_\n" foreach @unused;
+ $warnings += @unused;
+ print "WARN $object has large static symbol $_\n" foreach @large;
+ $warnings += @large;
+ print "ERR $object requires non-existent symbol $_\n" foreach @nonexistent;
+ $errors += @nonexistent;
+ foreach my $symbol ( @multiples ) {
+ my @other_objects = sort grep { $_ ne $object }
+ keys %{$globals->{$symbol}->{provides}};
+ print "ERR $object provides symbol $symbol"
+ ." (also provided by @other_objects)\n";
+ }
+ $errors += @multiples;
+ print "ERR $object misuses shared symbol $_\n" foreach @shared;
+}
+
+print "$errors error(s), $warnings warning(s)\n";
+exit ( $errors ? 1 : 0 );
diff --git a/src/VBox/Devices/PC/ipxe/src/util/zbin.c b/src/VBox/Devices/PC/ipxe/src/util/zbin.c
new file mode 100644
index 00000000..ad7e5f61
--- /dev/null
+++ b/src/VBox/Devices/PC/ipxe/src/util/zbin.c
@@ -0,0 +1,442 @@
+#include <stdio.h>
+#include <sys/stat.h>
+
+#define ENCODE
+#define VERBOSE
+#include "nrv2b.c"
+FILE *infile, *outfile;
+
+#undef DEBUG
+#define DEBUG 0
+
+struct input_file {
+ void *buf;
+ size_t len;
+};
+
+struct output_file {
+ void *buf;
+ size_t len;
+ size_t hdr_len;
+ size_t max_len;
+};
+
+struct zinfo_common {
+ char type[4];
+ char pad[12];
+};
+
+struct zinfo_copy {
+ char type[4];
+ uint32_t offset;
+ uint32_t len;
+ uint32_t align;
+};
+
+struct zinfo_pack {
+ char type[4];
+ uint32_t offset;
+ uint32_t len;
+ uint32_t align;
+};
+
+struct zinfo_payload {
+ char type[4];
+ uint32_t pad1;
+ uint32_t pad2;
+ uint32_t align;
+};
+
+struct zinfo_add {
+ char type[4];
+ uint32_t offset;
+ uint32_t divisor;
+ uint32_t pad;
+};
+
+union zinfo_record {
+ struct zinfo_common common;
+ struct zinfo_copy copy;
+ struct zinfo_pack pack;
+ struct zinfo_payload payload;
+ struct zinfo_add add;
+};
+
+struct zinfo_file {
+ union zinfo_record *zinfo;
+ unsigned int num_entries;
+};
+
+static unsigned long align ( unsigned long value, unsigned long algn ) {
+ return ( ( value + algn - 1 ) & ~( algn - 1 ) );
+}
+
+static int read_file ( const char *filename, void **buf, size_t *len ) {
+ FILE *file;
+ struct stat sstat;
+
+ file = fopen ( filename, "r" );
+ if ( ! file ) {
+ fprintf ( stderr, "Could not open %s: %s\n", filename,
+ strerror ( errno ) );
+ goto err;
+ }
+
+ if ( fstat ( fileno ( file ), &sstat ) < 0 ) {
+ fprintf ( stderr, "Could not stat %s: %s\n", filename,
+ strerror ( errno ) );
+ goto err;
+ }
+
+ *len = sstat.st_size;
+ *buf = malloc ( *len );
+ if ( ! *buf ) {
+ fprintf ( stderr, "Could not malloc() %zd bytes for %s: %s\n",
+ *len, filename, strerror ( errno ) );
+ goto err;
+ }
+
+ if ( fread ( *buf, 1, *len, file ) != *len ) {
+ fprintf ( stderr, "Could not read %zd bytes from %s: %s\n",
+ *len, filename, strerror ( errno ) );
+ goto err;
+ }
+
+ fclose ( file );
+ return 0;
+
+ err:
+ if ( file )
+ fclose ( file );
+ return -1;
+}
+
+static int read_input_file ( const char *filename,
+ struct input_file *input ) {
+ return read_file ( filename, &input->buf, &input->len );
+}
+
+static int read_zinfo_file ( const char *filename,
+ struct zinfo_file *zinfo ) {
+ void *buf;
+ size_t len;
+
+ if ( read_file ( filename, &buf, &len ) < 0 )
+ return -1;
+
+ if ( ( len % sizeof ( *(zinfo->zinfo) ) ) != 0 ) {
+ fprintf ( stderr, ".zinfo file %s has invalid length %zd\n",
+ filename, len );
+ return -1;
+ }
+
+ zinfo->zinfo = buf;
+ zinfo->num_entries = ( len / sizeof ( *(zinfo->zinfo) ) );
+ return 0;
+}
+
+static int alloc_output_file ( size_t max_len, struct output_file *output ) {
+ output->len = 0;
+ output->max_len = ( max_len );
+ output->buf = malloc ( max_len );
+ if ( ! output->buf ) {
+ fprintf ( stderr, "Could not allocate %zd bytes for output\n",
+ max_len );
+ return -1;
+ }
+#ifndef VBOX
+ memset ( output->buf, 0xff, sizeof ( output->buf ) );
+#else
+ memset ( output->buf, 0xff, max_len );
+#endif
+ return 0;
+}
+
+static int process_zinfo_copy ( struct input_file *input,
+ struct output_file *output,
+ union zinfo_record *zinfo ) {
+ struct zinfo_copy *copy = &zinfo->copy;
+ size_t offset = copy->offset;
+ size_t len = copy->len;
+
+ if ( ( offset + len ) > input->len ) {
+ fprintf ( stderr, "Input buffer overrun on copy\n" );
+ return -1;
+ }
+
+ output->len = align ( output->len, copy->align );
+ if ( ( output->len + len ) > output->max_len ) {
+ fprintf ( stderr, "Output buffer overrun on copy\n" );
+ return -1;
+ }
+
+ if ( DEBUG ) {
+ fprintf ( stderr, "COPY [%#zx,%#zx) to [%#zx,%#zx)\n",
+ offset, ( offset + len ), output->len,
+ ( output->len + len ) );
+ }
+
+ memcpy ( (void*)((char*) output->buf + output->len ),
+ (void*)((char*) input->buf + offset ), len );
+ output->len += len;
+ return 0;
+}
+
+static int process_zinfo_pack ( struct input_file *input,
+ struct output_file *output,
+ union zinfo_record *zinfo ) {
+ struct zinfo_pack *pack = &zinfo->pack;
+ size_t offset = pack->offset;
+ size_t len = pack->len;
+ unsigned long packed_len;
+
+ if ( ( offset + len ) > input->len ) {
+ fprintf ( stderr, "Input buffer overrun on pack\n" );
+ return -1;
+ }
+
+ output->len = align ( output->len, pack->align );
+ if ( output->len > output->max_len ) {
+ fprintf ( stderr, "Output buffer overrun on pack\n" );
+ return -1;
+ }
+
+ if ( ucl_nrv2b_99_compress ( (void*)((char*) input->buf + offset ), len,
+ (void*)((char*) output->buf + output->len ),
+ &packed_len, 0 ) != UCL_E_OK ) {
+ fprintf ( stderr, "Compression failure\n" );
+ return -1;
+ }
+
+ if ( DEBUG ) {
+ fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx)\n",
+ offset, ( offset + len ), output->len,
+ ( size_t )( output->len + packed_len ) );
+ }
+
+ output->len += packed_len;
+ if ( output->len > output->max_len ) {
+ fprintf ( stderr, "Output buffer overrun on pack\n" );
+ return -1;
+ }
+
+ return 0;
+}
+
+static int process_zinfo_payl ( struct input_file *input
+ __attribute__ (( unused )),
+ struct output_file *output,
+ union zinfo_record *zinfo ) {
+ struct zinfo_payload *payload = &zinfo->payload;
+
+ output->len = align ( output->len, payload->align );
+ output->hdr_len = output->len;
+
+ if ( DEBUG ) {
+ fprintf ( stderr, "PAYL at %#zx\n", output->hdr_len );
+ }
+ return 0;
+}
+
+static int process_zinfo_add ( struct input_file *input
+ __attribute__ (( unused )),
+ struct output_file *output,
+ size_t len,
+ struct zinfo_add *add,
+ size_t datasize ) {
+ size_t offset = add->offset;
+ void *target;
+ signed long addend;
+ unsigned long size;
+ signed long val;
+ unsigned long mask;
+
+ if ( ( offset + datasize ) > output->len ) {
+ fprintf ( stderr, "Add at %#zx outside output buffer\n",
+ offset );
+ return -1;
+ }
+
+ target = (void*)((char*) output->buf + offset );
+ size = ( align ( len, add->divisor ) / add->divisor );
+
+ switch ( datasize ) {
+ case 1:
+ addend = *( ( int8_t * ) target );
+ break;
+ case 2:
+ addend = *( ( int16_t * ) target );
+ break;
+ case 4:
+ addend = *( ( int32_t * ) target );
+ break;
+ default:
+ fprintf ( stderr, "Unsupported add datasize %zd\n",
+ datasize );
+ return -1;
+ }
+
+ val = size + addend;
+
+ /* The result of 1UL << ( 8 * sizeof(unsigned long) ) is undefined */
+ mask = ( ( datasize < sizeof ( mask ) ) ?
+ ( ( 1UL << ( 8 * datasize ) ) - 1 ) : ~0UL );
+
+ if ( val < 0 ) {
+ fprintf ( stderr, "Add %s%#x+%#lx at %#zx %sflows field\n",
+ ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size,
+ offset, ( ( addend < 0 ) ? "under" : "over" ) );
+ return -1;
+ }
+
+ if ( val & ~mask ) {
+ fprintf ( stderr, "Add %s%#x+%#lx at %#zx overflows %zd-byte "
+ "field (%d bytes too big)\n",
+ ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size,
+ offset, datasize,
+ ( int )( ( val - mask - 1 ) * add->divisor ) );
+ return -1;
+ }
+
+ switch ( datasize ) {
+ case 1:
+ *( ( uint8_t * ) target ) = val;
+ break;
+ case 2:
+ *( ( uint16_t * ) target ) = val;
+ break;
+ case 4:
+ *( ( uint32_t * ) target ) = val;
+ break;
+ }
+
+ if ( DEBUG ) {
+ fprintf ( stderr, "ADDx [%#zx,%#zx) (%s%#x+(%#zx/%#x)) = "
+ "%#lx\n", offset, ( offset + datasize ),
+ ( ( addend < 0 ) ? "-" : "" ), abs ( addend ),
+ len, add->divisor, val );
+ }
+
+ return 0;
+}
+
+static int process_zinfo_addb ( struct input_file *input,
+ struct output_file *output,
+ union zinfo_record *zinfo ) {
+ return process_zinfo_add ( input, output, output->len,
+ &zinfo->add, 1 );
+}
+
+static int process_zinfo_addw ( struct input_file *input,
+ struct output_file *output,
+ union zinfo_record *zinfo ) {
+ return process_zinfo_add ( input, output, output->len,
+ &zinfo->add, 2 );
+}
+
+static int process_zinfo_addl ( struct input_file *input,
+ struct output_file *output,
+ union zinfo_record *zinfo ) {
+ return process_zinfo_add ( input, output, output->len,
+ &zinfo->add, 4 );
+}
+
+static int process_zinfo_adhb ( struct input_file *input,
+ struct output_file *output,
+ union zinfo_record *zinfo ) {
+ return process_zinfo_add ( input, output, output->hdr_len,
+ &zinfo->add, 1 );
+}
+
+static int process_zinfo_adhw ( struct input_file *input,
+ struct output_file *output,
+ union zinfo_record *zinfo ) {
+ return process_zinfo_add ( input, output, output->hdr_len,
+ &zinfo->add, 2 );
+}
+
+static int process_zinfo_adhl ( struct input_file *input,
+ struct output_file *output,
+ union zinfo_record *zinfo ) {
+ return process_zinfo_add ( input, output, output->hdr_len,
+ &zinfo->add, 4 );
+}
+
+struct zinfo_processor {
+ char *type;
+ int ( * process ) ( struct input_file *input,
+ struct output_file *output,
+ union zinfo_record *zinfo );
+};
+
+static struct zinfo_processor zinfo_processors[] = {
+ { "COPY", process_zinfo_copy },
+ { "PACK", process_zinfo_pack },
+ { "PAYL", process_zinfo_payl },
+ { "ADDB", process_zinfo_addb },
+ { "ADDW", process_zinfo_addw },
+ { "ADDL", process_zinfo_addl },
+ { "ADHB", process_zinfo_adhb },
+ { "ADHW", process_zinfo_adhw },
+ { "ADHL", process_zinfo_adhl },
+};
+
+static int process_zinfo ( struct input_file *input,
+ struct output_file *output,
+ union zinfo_record *zinfo ) {
+ struct zinfo_common *common = &zinfo->common;
+ struct zinfo_processor *processor;
+ char type[ sizeof ( common->type ) + 1 ] = "";
+ unsigned int i;
+
+ strncat ( type, common->type, sizeof ( type ) - 1 );
+ for ( i = 0 ; i < ( sizeof ( zinfo_processors ) /
+ sizeof ( zinfo_processors[0] ) ) ; i++ ) {
+ processor = &zinfo_processors[i];
+ if ( strcmp ( processor->type, type ) == 0 )
+ return processor->process ( input, output, zinfo );
+ }
+
+ fprintf ( stderr, "Unknown zinfo record type \"%s\"\n", &type[0] );
+ return -1;
+}
+
+static int write_output_file ( struct output_file *output ) {
+ if ( fwrite ( output->buf, 1, output->len, stdout ) != output->len ) {
+ fprintf ( stderr, "Could not write %zd bytes of output: %s\n",
+ output->len, strerror ( errno ) );
+ return -1;
+ }
+ return 0;
+}
+
+int main ( int argc, char **argv ) {
+ struct input_file input;
+ struct output_file output;
+ struct zinfo_file zinfo;
+ unsigned int i;
+
+ if ( argc != 3 ) {
+ fprintf ( stderr, "Syntax: %s file.bin file.zinfo "
+ "> file.zbin\n", argv[0] );
+ exit ( 1 );
+ }
+
+ if ( read_input_file ( argv[1], &input ) < 0 )
+ exit ( 1 );
+ if ( read_zinfo_file ( argv[2], &zinfo ) < 0 )
+ exit ( 1 );
+ if ( alloc_output_file ( ( input.len * 4 ), &output ) < 0 )
+ exit ( 1 );
+
+ for ( i = 0 ; i < zinfo.num_entries ; i++ ) {
+ if ( process_zinfo ( &input, &output,
+ &zinfo.zinfo[i] ) < 0 )
+ exit ( 1 );
+ }
+
+ if ( write_output_file ( &output ) < 0 )
+ exit ( 1 );
+
+ return 0;
+}
diff --git a/src/VBox/Devices/PC/vbox-cpuhotplug.dsl b/src/VBox/Devices/PC/vbox-cpuhotplug.dsl
new file mode 100644
index 00000000..c8c35cb8
--- /dev/null
+++ b/src/VBox/Devices/PC/vbox-cpuhotplug.dsl
@@ -0,0 +1,194 @@
+/* $Id: vbox-cpuhotplug.dsl $ */
+/** @file
+ * VirtualBox ACPI
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+DefinitionBlock ("SSDT-cpuhotplug.aml", "SSDT", 1, "VBOX ", "VBOXCPUT", 2)
+{
+ External(CPUC)
+ External(CPUL)
+ External(CPEV)
+ External(CPET)
+
+ // Method to check for the CPU status
+ Method(CPCK, 1)
+ {
+ Store (Arg0, CPUC)
+ Return(LEqual(CPUL, 0x01))
+ }
+
+ // Method to notify the VMM that a CPU is not
+ // in use anymore and can be safely removed.
+ // Using the extra method here because the CPUL
+ // register identifer clashes with the CPUL object defined
+ // below making iasl starting with version 20150930 fail.
+ //
+ // Think of CPLO as "CPU Lock Open"
+ Method(CPLO, 1)
+ {
+ Store(Arg0, CPUL)
+ }
+
+ Scope (\_SB)
+ {
+
+#define GENERATE_CPU_OBJECT(id, sck, sckuid, cpu, cpuuid)<NL> \
+ Device (sck) \
+ { \
+ Name (_HID, "ACPI0004") \
+ Name (_UID, sckuid) \
+ \
+ <NL> \
+ Processor (cpu, /* Name */ \
+ id, /* Id */ \
+ 0x0, /* Processor IO ports range start */ \
+ 0x0 /* Processor IO ports range length */ \
+ ) \
+ { \
+ Name (_HID, "ACPI0007") \
+ Name (_UID, cpuuid) \
+ Name (_PXM, 0x00) \
+ <NL> \
+ Method(_MAT, 0, Serialized) \
+ { \
+ Name (APIC, Buffer (8) {0x00, 0x08, id, id}) \
+ IF (CPCK(id)) \
+ { \
+ Store (One, Index (APIC, 4)) \
+ } \
+ Else \
+ { \
+ Store (Zero, Index (APIC, 4)) \
+ } \
+ Return (APIC) \
+ } \
+ <NL> \
+ Method(_STA) /* Used for device presence detection */ \
+ { \
+ IF (CPCK(id)) \
+ { \
+ Return (0xF) \
+ } \
+ Else \
+ { \
+ Return (0x0) \
+ } \
+ } \
+ <NL> \
+ Method(_EJ0, 1) \
+ { \
+ CPLO(id) /* Unlock the CPU */ \
+ Return \
+ } \
+ } \
+ } \
+
+ GENERATE_CPU_OBJECT(0x00, SCK0, "SCKCPU0", CPU0, "SCK0-CPU0")
+ GENERATE_CPU_OBJECT(0x01, SCK1, "SCKCPU1", CPU1, "SCK1-CPU0")
+ GENERATE_CPU_OBJECT(0x02, SCK2, "SCKCPU2", CPU2, "SCK2-CPU0")
+ GENERATE_CPU_OBJECT(0x03, SCK3, "SCKCPU3", CPU3, "SCK3-CPU0")
+ GENERATE_CPU_OBJECT(0x04, SCK4, "SCKCPU4", CPU4, "SCK4-CPU0")
+ GENERATE_CPU_OBJECT(0x05, SCK5, "SCKCPU5", CPU5, "SCK5-CPU0")
+ GENERATE_CPU_OBJECT(0x06, SCK6, "SCKCPU6", CPU6, "SCK6-CPU0")
+ GENERATE_CPU_OBJECT(0x07, SCK7, "SCKCPU7", CPU7, "SCK7-CPU0")
+ GENERATE_CPU_OBJECT(0x08, SCK8, "SCKCPU8", CPU8, "SCK8-CPU0")
+ GENERATE_CPU_OBJECT(0x09, SCK9, "SCKCPU9", CPU9, "SCK9-CPU0")
+ GENERATE_CPU_OBJECT(0x0a, SCKA, "SCKCPUA", CPUA, "SCKA-CPU0")
+ GENERATE_CPU_OBJECT(0x0b, SCKB, "SCKCPUB", CPUB, "SCKB-CPU0")
+ GENERATE_CPU_OBJECT(0x0c, SCKC, "SCKCPUC", CPUC, "SCKC-CPU0")
+ GENERATE_CPU_OBJECT(0x0d, SCKD, "SCKCPUD", CPUD, "SCKD-CPU0")
+ GENERATE_CPU_OBJECT(0x0e, SCKE, "SCKCPUE", CPUE, "SCKE-CPU0")
+ GENERATE_CPU_OBJECT(0x0f, SCKF, "SCKCPUF", CPUF, "SCKF-CPU0")
+ GENERATE_CPU_OBJECT(0x10, SCKG, "SCKCPUG", CPUG, "SCKG-CPU0")
+ GENERATE_CPU_OBJECT(0x11, SCKH, "SCKCPUH", CPUH, "SCKH-CPU0")
+ GENERATE_CPU_OBJECT(0x12, SCKI, "SCKCPUI", CPUI, "SCKI-CPU0")
+ GENERATE_CPU_OBJECT(0x13, SCKJ, "SCKCPUJ", CPUJ, "SCKJ-CPU0")
+ GENERATE_CPU_OBJECT(0x14, SCKK, "SCKCPUK", CPUK, "SCKK-CPU0")
+ GENERATE_CPU_OBJECT(0x15, SCKL, "SCKCPUL", CPUL, "SCKL-CPU0")
+ GENERATE_CPU_OBJECT(0x16, SCKM, "SCKCPUM", CPUM, "SCKM-CPU0")
+ GENERATE_CPU_OBJECT(0x17, SCKN, "SCKCPUN", CPUN, "SCKN-CPU0")
+ GENERATE_CPU_OBJECT(0x18, SCKO, "SCKCPUO", CPUO, "SCKO-CPU0")
+ GENERATE_CPU_OBJECT(0x19, SCKP, "SCKCPUP", CPUP, "SCKP-CPU0")
+ GENERATE_CPU_OBJECT(0x1a, SCKQ, "SCKCPUQ", CPUQ, "SCKQ-CPU0")
+ GENERATE_CPU_OBJECT(0x1b, SCKR, "SCKCPUR", CPUR, "SCKR-CPU0")
+ GENERATE_CPU_OBJECT(0x1c, SCKS, "SCKCPUS", CPUS, "SCKS-CPU0")
+ GENERATE_CPU_OBJECT(0x1d, SCKT, "SCKCPUT", CPUT, "SCKT-CPU0")
+ GENERATE_CPU_OBJECT(0x1e, SCKU, "SCKCPUU", CPUU, "SCKU-CPU0")
+ GENERATE_CPU_OBJECT(0x1f, SCKV, "SCKCPUV", CPUV, "SCKV-CPU0")
+
+#undef GENERATE_CPU_OBJECT
+ }
+
+ Scope (\_GPE)
+ {
+
+#define CHECK_CPU(cpu, sck, cpuname) \
+ IF (LEqual(Local0, cpu)) \
+ { \
+ Notify (\_SB.sck.cpuname, Local1) \
+ } \
+
+ // GPE bit 1 handler
+ // GPE.1 must be set and SCI raised when
+ // processor info changed and CPU must be
+ // re-evaluated
+ Method (_L01, 0, NotSerialized)
+ {
+ Store(CPEV, Local0)
+ Store(CPET, Local1)
+
+ CHECK_CPU(0x01, SCK1, CPU1)
+ CHECK_CPU(0x02, SCK2, CPU2)
+ CHECK_CPU(0x03, SCK3, CPU3)
+ CHECK_CPU(0x04, SCK4, CPU4)
+ CHECK_CPU(0x05, SCK5, CPU5)
+ CHECK_CPU(0x06, SCK6, CPU6)
+ CHECK_CPU(0x07, SCK7, CPU7)
+ CHECK_CPU(0x08, SCK8, CPU8)
+ CHECK_CPU(0x09, SCK9, CPU9)
+ CHECK_CPU(0x0a, SCKA, CPUA)
+ CHECK_CPU(0x0b, SCKB, CPUB)
+ CHECK_CPU(0x0c, SCKC, CPUC)
+ CHECK_CPU(0x0d, SCKD, CPUD)
+ CHECK_CPU(0x0e, SCKE, CPUE)
+ CHECK_CPU(0x0f, SCKF, CPUF)
+ CHECK_CPU(0x10, SCKG, CPUG)
+ CHECK_CPU(0x11, SCKH, CPUH)
+ CHECK_CPU(0x12, SCKI, CPUI)
+ CHECK_CPU(0x13, SCKJ, CPUJ)
+ CHECK_CPU(0x14, SCKK, CPUK)
+ CHECK_CPU(0x15, SCKL, CPUL)
+ CHECK_CPU(0x16, SCKM, CPUM)
+ CHECK_CPU(0x17, SCKN, CPUN)
+ CHECK_CPU(0x18, SCKO, CPUO)
+ CHECK_CPU(0x19, SCKP, CPUP)
+ CHECK_CPU(0x1a, SCKQ, CPUQ)
+ CHECK_CPU(0x1b, SCKR, CPUR)
+ CHECK_CPU(0x1c, SCKS, CPUS)
+ CHECK_CPU(0x1d, SCKT, CPUT)
+ CHECK_CPU(0x1e, SCKU, CPUU)
+ CHECK_CPU(0x1f, SCKV, CPUV)
+ }
+
+#undef CHECK_CPU
+ }
+
+}
+
+/*
+ * Local Variables:
+ * comment-start: "//"
+ * End:
+ */
diff --git a/src/VBox/Devices/PC/vbox-standard.dsl b/src/VBox/Devices/PC/vbox-standard.dsl
new file mode 100644
index 00000000..e651268a
--- /dev/null
+++ b/src/VBox/Devices/PC/vbox-standard.dsl
@@ -0,0 +1,263 @@
+/* $Id: vbox-standard.dsl $ */
+/** @file
+ * VirtualBox ACPI
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+DefinitionBlock ("SSDT.aml", "SSDT", 1, "VBOX ", "VBOXCPUT", 2)
+{
+ // Processor object
+ // #1463: Showing the CPU can make the guest do bad things on it like SpeedStep.
+ // In this case, XP SP2 contains this buggy Intelppm.sys driver which wants to mess
+ // with SpeedStep if it finds a CPU object and when it finds out that it can't, it
+ // tries to unload and crashes (MS probably never tested this code path).
+ // So we enable this ACPI object only for certain guests, which do need it,
+ // if by accident Windows guest seen enabled CPU object, just boot from latest
+ // known good configuration, as it remembers state, even if ACPI object gets disabled.
+ Scope (\_PR)
+ {
+ Processor (CPU0, /* Name */
+ 0x00, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+
+ Processor (CPU1, /* Name */
+ 0x01, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPU2, /* Name */
+ 0x02, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPU3, /* Name */
+ 0x03, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPU4, /* Name */
+ 0x04, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPU5, /* Name */
+ 0x05, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPU6, /* Name */
+ 0x06, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPU7, /* Name */
+ 0x07, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPU8, /* Name */
+ 0x08, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPU9, /* Name */
+ 0x09, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUA, /* Name */
+ 0x0a, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUB, /* Name */
+ 0x0b, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUC, /* Name */
+ 0x0c, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUD, /* Name */
+ 0x0d, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUE, /* Name */
+ 0x0e, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUF, /* Name */
+ 0x0f, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUG, /* Name */
+ 0x10, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUH, /* Name */
+ 0x11, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUI, /* Name */
+ 0x12, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUJ, /* Name */
+ 0x13, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUK, /* Name */
+ 0x14, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUL, /* Name */
+ 0x15, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUM, /* Name */
+ 0x16, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUN, /* Name */
+ 0x17, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUO, /* Name */
+ 0x18, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUP, /* Name */
+ 0x19, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUQ, /* Name */
+ 0x1a, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUR, /* Name */
+ 0x1b, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUS, /* Name */
+ 0x1c, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUT, /* Name */
+ 0x1d, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUU, /* Name */
+ 0x1e, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ Processor (CPUV, /* Name */
+ 0x1f, /* Id */
+ 0x0, /* Processor IO ports range start */
+ 0x0 /* Processor IO ports range length */
+ )
+ {
+ }
+ }
+}
+
+/*
+ * Local Variables:
+ * comment-start: "//"
+ * End:
+ */
+
diff --git a/src/VBox/Devices/PC/vbox.dsl b/src/VBox/Devices/PC/vbox.dsl
new file mode 100644
index 00000000..4ea6326f
--- /dev/null
+++ b/src/VBox/Devices/PC/vbox.dsl
@@ -0,0 +1,1938 @@
+/* $Id: vbox.dsl $ */
+/** @file
+ * VirtualBox ACPI
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+DefinitionBlock ("DSDT.aml", "DSDT", 2, "VBOX ", "VBOXBIOS", 2)
+{
+ // Declare debugging ports withing SystemIO
+ OperationRegion(DBG0, SystemIO, 0x3000, 4)
+
+ // Writes to this field Will dump hex char
+ Field (DBG0, ByteAcc, NoLock, Preserve)
+ {
+ DHE1, 8,
+ }
+
+ // Writes to this field Will dump hex word
+ Field (DBG0, WordAcc, NoLock, Preserve)
+ {
+ DHE2, 16,
+ }
+
+ // Writes to this field Will dump hex double word
+ Field (DBG0, DWordAcc, NoLock, Preserve)
+ {
+ DHE4, 32,
+ }
+
+ // Writes to this field will dump ascii char
+ Field (DBG0, ByteAcc, NoLock, Preserve)
+ {
+ Offset (1),
+ DCHR, 8
+ }
+
+ // Shortcuts
+ Method(HEX, 1)
+ {
+ Store (Arg0, DHE1)
+ }
+
+ Method(HEX2, 1)
+ {
+ Store (Arg0, DHE2)
+ }
+
+ Method(HEX4, 1)
+ {
+ Store (Arg0, DHE4)
+ }
+
+ // Code from Microsoft sample
+ // http://www.microsoft.com/whdc/system/pnppwr/powermgmt/_OSI-method.mspx
+
+ //
+ // SLEN(Str) - Returns the length of Str (excluding NULL).
+ //
+ Method(SLEN, 1)
+ {
+ //
+ // Note: The caller must make sure that the argument is a string object.
+ //
+ Store(Arg0, Local0)
+ Return(Sizeof(Local0))
+ }
+
+
+ //
+ // S2BF(Str) - Convert a string object into a buffer object.
+ //
+ Method(S2BF, 1, Serialized)
+ {
+ //
+ // Note: The caller must make sure that the argument is a string object.
+ //
+ // Local0 contains length of string + NULL.
+ //
+ Store(Arg0, Local0)
+ Add(SLEN(Local0), One, Local0)
+ //
+ // Convert the string object into a buffer object.
+ //
+ Name(BUFF, Buffer(Local0) {})
+ Store(Arg0, BUFF)
+ Return(BUFF)
+ }
+
+ //
+ // MIN(Int1, Int2) - Returns the minimum of Int1 or Int2.
+ //
+ //
+ Method(MIN, 2)
+ {
+ //
+ // Note: The caller must make sure that both arguments are integer objects.
+ //
+ If (LLess(Arg0, Arg1))
+ {
+ Return(Arg0)
+ }
+ Else
+ {
+ Return(Arg1)
+ }
+ }
+
+ //
+ // SCMP(Str1, Str2) - Compare Str1 and Str2.
+ // Returns One if Str1 > Str2
+ // Returns Zero if Str1 == Str2
+ // Returns Ones if Str1 < Str2
+ //
+ Method(SCMP, 2)
+ {
+ //
+ // Note: The caller must make sure that both arguments are string objects.
+ //
+ // Local0 is a buffer of Str1.
+ // Local1 is a buffer of Str2.
+ // Local2 is the indexed byte of Str1.
+ // Local3 is the indexed byte of Str2.
+ // Local4 is the index to both Str1 and Str2.
+ // Local5 is the length of Str1.
+ // Local6 is the length of Str2.
+ // Local7 is the minimum of Str1 or Str2 length.
+ //
+
+ Store(Arg0, Local0)
+ Store(S2BF(Local0), Local0)
+
+ Store(S2BF(Arg1), Local1)
+ Store(Zero, Local4)
+
+ Store(SLEN(Arg0), Local5)
+ Store(SLEN(Arg1), Local6)
+ Store(MIN(Local5, Local6), Local7)
+
+ While (LLess(Local4, Local7))
+ {
+ Store(Derefof(Index(Local0, Local4)), Local2)
+ Store(Derefof(Index(Local1, Local4)), Local3)
+ If (LGreater(Local2, Local3))
+ {
+ Return(One)
+ }
+ Else
+ {
+ If (LLess(Local2, Local3))
+ {
+ Return(Ones)
+ }
+ }
+
+ Increment(Local4)
+ }
+
+ If (LLess(Local4, Local5))
+ {
+ Return(One)
+ }
+ Else
+ {
+ If (LLess(Local4, Local6))
+ {
+ Return(Ones)
+ }
+ Else
+ {
+ Return(Zero)
+ }
+ }
+ }
+
+ // Return one if strings match, zero otherwise. Wrapper around SCMP
+ Method (MTCH, 2)
+ {
+ Store(Arg0, Local0)
+ Store(Arg1, Local1)
+ Store(SCMP(Local0, Local1), Local2)
+ Return(LNot(Local2))
+ }
+
+ // Convert ASCII string to buffer and store it's contents (char by
+ // char) into DCHR (thus possibly writing the string to console)
+ Method (\DBG, 1, NotSerialized)
+ {
+ Store(Arg0, Local0)
+ Store(S2BF (Local0), Local1)
+ Store(SizeOf (Local1), Local0)
+ Decrement (Local0)
+ Store(Zero, Local2)
+ While (Local0)
+ {
+ Decrement (Local0)
+ Store (DerefOf (Index (Local1, Local2)), DCHR)
+ Increment (Local2)
+ }
+ }
+
+ // Microsoft Windows version indicator
+ Name(MSWV, Ones)
+
+ //
+ // Return Windows version. Detect non-Microsoft OSes.
+ //
+ // 0 : Not Windows OS
+ // 2 : Windows Me
+ // 3 : Windows 2000 (NT pre-XP)
+ // 4 : Windows XP
+ // 5 : Windows Server 2003
+ // 6 : Windows Vista
+ // 7 : Windows 7
+ // 8 : Windows 8
+ // 9 : Windows 8.1
+ // 10 : Windows 10
+ Method(MSWN, 0, NotSerialized)
+ {
+ If (LNotEqual(MSWV, Ones))
+ {
+ Return(MSWV)
+ }
+
+ Store(0x00, MSWV)
+ DBG("_OS: ")
+ DBG(_OS)
+ DBG("\n")
+
+ // Does OS provide the _OSI method?
+ If (CondRefOf(_OSI))
+ {
+ DBG("_OSI exists\n")
+ // OS returns non-zero value in response to _OSI query if it
+ // supports the interface. Newer Windows releases support older
+ // versions of the ACPI interface.
+ If (_OSI("Windows 2001"))
+ {
+ Store(4, MSWV) // XP
+ }
+ If (_OSI("Windows 2001.1"))
+ {
+ Store(5, MSWV) // Server 2003
+ }
+ If (_OSI("Windows 2006"))
+ {
+ Store(6, MSWV) // Vista
+ }
+ If (_OSI("Windows 2009"))
+ {
+ Store(7, MSWV) // Windows 7
+ }
+ If (_OSI("Windows 2012"))
+ {
+ Store(8, MSWV) // Windows 8
+ }
+ If (_OSI("Windows 2013"))
+ {
+ Store(9, MSWV) // Windows 8.1
+ }
+ If (_OSI("Windows 2015"))
+ {
+ Store(10, MSWV) // Windows 10
+ }
+
+ // This must come last and is a trap. No version of Windows
+ // reports this!
+ If (_OSI("Windows 2006 SP2"))
+ {
+ DBG("Windows 2006 SP2 supported\n")
+ // Not a Microsoft OS
+ Store(0, MSWV)
+ }
+ }
+ Else
+ {
+ // No _OSI, could be older NT or Windows 9x
+ If (MTCH(_OS, "Microsoft Windows NT"))
+ {
+ Store(3, MSWV)
+ }
+ If (MTCH(_OS, "Microsoft WindowsME: Millennium Edition"))
+ {
+ Store(2, MSWV)
+ }
+ }
+
+ // Does OS provide the _REV method?
+ If (CondRefOf(_REV))
+ {
+ DBG("_REV: ")
+ HEX4(_REV)
+
+ // Defeat most Linuxes and other non-Microsoft OSes. Microsoft Windows
+ // up to Server 2003 reports ACPI 1.0 support, Vista up to Windows 10
+ // reports ACPI 2.0 support. Anything pretending to be a Windows OS
+ // with higher ACPI revision support is a fake.
+ If (LAnd(LGreater(MSWV, 0),LGreater(_REV, 2)))
+ {
+ If (LLess(MSWV,8))
+ {
+ DBG("ACPI rev mismatch, not a Microsoft OS\n")
+ Store(0, MSWV)
+ }
+ }
+ }
+
+ DBG("Determined MSWV: ")
+ HEX4(MSWV)
+
+ Return(MSWV)
+ }
+
+ Name(PICM, 0)
+ Method(_PIC, 1)
+ {
+ DBG ("Pic mode: ")
+ HEX4 (Arg0)
+ Store (Arg0, PICM)
+ }
+
+ // Declare indexed registers used for reading configuration information
+ OperationRegion (SYSI, SystemIO, 0x4048, 0x08)
+ Field (SYSI, DwordAcc, NoLock, Preserve)
+ {
+ IDX0, 32,
+ DAT0, 32,
+ }
+
+ IndexField (IDX0, DAT0, DwordAcc, NoLock, Preserve)
+ {
+ MEML, 32, // low-memory length (64KB units)
+ UIOA, 32, // if IO APIC enabled
+ UHPT, 32, // if HPET enabled
+ USMC, 32, // if SMC enabled
+ UFDC, 32, // if floppy controller enabled
+ SL2B, 32, // Serial2 base IO address
+ SL2I, 32, // Serial2 IRQ
+ SL3B, 32, // Serial3 base IO address
+ SL3I, 32, // Serial3 IRQ
+ PMNN, 32, // start of 64-bit prefetch window (64KB units)
+ URTC, 32, // if RTC shown in tables
+ CPUL, 32, // flag of CPU lock state
+ CPUC, 32, // CPU to check lock status
+ CPET, 32, // type of CPU hotplug event
+ CPEV, 32, // id of CPU event targets
+ NICA, 32, // Primary NIC PCI address
+ HDAA, 32, // HDA PCI address
+ PWRS, 32, // power states
+ IOCA, 32, // southbridge IO controller PCI address
+ HBCA, 32, // host bus controller address
+ PCIB, 32, // PCI MCFG base start
+ PCIL, 32, // PCI MCFG length
+ SL0B, 32, // Serial0 base IO address
+ SL0I, 32, // Serial0 IRQ
+ SL1B, 32, // Serial1 base IO address
+ SL1I, 32, // Serial1 IRQ
+ PP0B, 32, // Parallel0 base IO address
+ PP0I, 32, // Parallel0 IRQ
+ PP1B, 32, // Parallel1 base IO address
+ PP1I, 32, // Parallel1 IRQ
+ PMNX, 32, // limit of 64-bit prefetch window (64KB units)
+ Offset (0x80),
+ ININ, 32,
+ Offset (0x200),
+ VAIN, 32,
+ }
+
+ Scope (\_SB)
+ {
+ Method (_INI, 0, NotSerialized)
+ {
+ Store (0xbadc0de, VAIN)
+ DBG ("MEML: ")
+ HEX4 (MEML)
+ DBG ("UIOA: ")
+ HEX4 (UIOA)
+ DBG ("UHPT: ")
+ HEX4 (UHPT)
+ DBG ("USMC: ")
+ HEX4 (USMC)
+ DBG ("UFDC: ")
+ HEX4 (UFDC)
+ DBG ("PMNN: ")
+ HEX4 (PMNN)
+ }
+
+ // PCI PIC IRQ Routing table
+ // Must match pci.c:pci_slot_get_pirq
+ Name (PR00, Package ()
+ {
+/** @todo add devices 0/1 to be complete */
+ Package (0x04) {0x0002FFFF, 0x00, LNKB, 0x00,},
+ Package (0x04) {0x0002FFFF, 0x01, LNKC, 0x00,},
+ Package (0x04) {0x0002FFFF, 0x02, LNKD, 0x00,},
+ Package (0x04) {0x0002FFFF, 0x03, LNKA, 0x00,},
+
+ Package (0x04) {0x0003FFFF, 0x00, LNKC, 0x00,},
+ Package (0x04) {0x0003FFFF, 0x01, LNKD, 0x00,},
+ Package (0x04) {0x0003FFFF, 0x02, LNKA, 0x00,},
+ Package (0x04) {0x0003FFFF, 0x03, LNKB, 0x00,},
+
+ Package (0x04) {0x0004FFFF, 0x00, LNKD, 0x00,},
+ Package (0x04) {0x0004FFFF, 0x01, LNKA, 0x00,},
+ Package (0x04) {0x0004FFFF, 0x02, LNKB, 0x00,},
+ Package (0x04) {0x0004FFFF, 0x03, LNKC, 0x00,},
+
+ Package (0x04) {0x0005FFFF, 0x00, LNKA, 0x00,},
+ Package (0x04) {0x0005FFFF, 0x01, LNKB, 0x00,},
+ Package (0x04) {0x0005FFFF, 0x02, LNKC, 0x00,},
+ Package (0x04) {0x0005FFFF, 0x03, LNKD, 0x00,},
+
+ Package (0x04) {0x0006FFFF, 0x00, LNKB, 0x00,},
+ Package (0x04) {0x0006FFFF, 0x01, LNKC, 0x00,},
+ Package (0x04) {0x0006FFFF, 0x02, LNKD, 0x00,},
+ Package (0x04) {0x0006FFFF, 0x03, LNKA, 0x00,},
+
+ Package (0x04) {0x0007FFFF, 0x00, LNKC, 0x00,},
+ Package (0x04) {0x0007FFFF, 0x01, LNKD, 0x00,},
+ Package (0x04) {0x0007FFFF, 0x02, LNKA, 0x00,},
+ Package (0x04) {0x0007FFFF, 0x03, LNKB, 0x00,},
+
+ Package (0x04) {0x0008FFFF, 0x00, LNKD, 0x00,},
+ Package (0x04) {0x0008FFFF, 0x01, LNKA, 0x00,},
+ Package (0x04) {0x0008FFFF, 0x02, LNKB, 0x00,},
+ Package (0x04) {0x0008FFFF, 0x03, LNKC, 0x00,},
+
+ Package (0x04) {0x0009FFFF, 0x00, LNKA, 0x00,},
+ Package (0x04) {0x0009FFFF, 0x01, LNKB, 0x00,},
+ Package (0x04) {0x0009FFFF, 0x02, LNKC, 0x00,},
+ Package (0x04) {0x0009FFFF, 0x03, LNKD, 0x00,},
+
+ Package (0x04) {0x000AFFFF, 0x00, LNKB, 0x00,},
+ Package (0x04) {0x000AFFFF, 0x01, LNKC, 0x00,},
+ Package (0x04) {0x000AFFFF, 0x02, LNKD, 0x00,},
+ Package (0x04) {0x000AFFFF, 0x03, LNKA, 0x00,},
+
+ Package (0x04) {0x000BFFFF, 0x00, LNKC, 0x00,},
+ Package (0x04) {0x000BFFFF, 0x01, LNKD, 0x00,},
+ Package (0x04) {0x000BFFFF, 0x02, LNKA, 0x00,},
+ Package (0x04) {0x000BFFFF, 0x03, LNKB, 0x00,},
+
+ Package (0x04) {0x000CFFFF, 0x00, LNKD, 0x00,},
+ Package (0x04) {0x000CFFFF, 0x01, LNKA, 0x00,},
+ Package (0x04) {0x000CFFFF, 0x02, LNKB, 0x00,},
+ Package (0x04) {0x000CFFFF, 0x03, LNKC, 0x00,},
+
+ Package (0x04) {0x000DFFFF, 0x00, LNKA, 0x00,},
+ Package (0x04) {0x000DFFFF, 0x01, LNKB, 0x00,},
+ Package (0x04) {0x000DFFFF, 0x02, LNKC, 0x00,},
+ Package (0x04) {0x000DFFFF, 0x03, LNKD, 0x00,},
+
+ Package (0x04) {0x000EFFFF, 0x00, LNKB, 0x00,},
+ Package (0x04) {0x000EFFFF, 0x01, LNKC, 0x00,},
+ Package (0x04) {0x000EFFFF, 0x02, LNKD, 0x00,},
+ Package (0x04) {0x000EFFFF, 0x03, LNKA, 0x00,},
+
+ Package (0x04) {0x000FFFFF, 0x00, LNKC, 0x00,},
+ Package (0x04) {0x000FFFFF, 0x01, LNKD, 0x00,},
+ Package (0x04) {0x000FFFFF, 0x02, LNKA, 0x00,},
+ Package (0x04) {0x000FFFFF, 0x03, LNKB, 0x00,},
+
+ Package (0x04) {0x0010FFFF, 0x00, LNKD, 0x00,},
+ Package (0x04) {0x0010FFFF, 0x01, LNKA, 0x00,},
+ Package (0x04) {0x0010FFFF, 0x02, LNKB, 0x00,},
+ Package (0x04) {0x0010FFFF, 0x03, LNKC, 0x00,},
+
+ Package (0x04) {0x0011FFFF, 0x00, LNKA, 0x00,},
+ Package (0x04) {0x0011FFFF, 0x01, LNKB, 0x00,},
+ Package (0x04) {0x0011FFFF, 0x02, LNKC, 0x00,},
+ Package (0x04) {0x0011FFFF, 0x03, LNKD, 0x00,},
+
+ Package (0x04) {0x0012FFFF, 0x00, LNKB, 0x00,},
+ Package (0x04) {0x0012FFFF, 0x01, LNKC, 0x00,},
+ Package (0x04) {0x0012FFFF, 0x02, LNKD, 0x00,},
+ Package (0x04) {0x0012FFFF, 0x03, LNKA, 0x00,},
+
+ Package (0x04) {0x0013FFFF, 0x00, LNKC, 0x00,},
+ Package (0x04) {0x0013FFFF, 0x01, LNKD, 0x00,},
+ Package (0x04) {0x0013FFFF, 0x02, LNKA, 0x00,},
+ Package (0x04) {0x0013FFFF, 0x03, LNKB, 0x00,},
+
+ Package (0x04) {0x0014FFFF, 0x00, LNKD, 0x00,},
+ Package (0x04) {0x0014FFFF, 0x01, LNKA, 0x00,},
+ Package (0x04) {0x0014FFFF, 0x02, LNKB, 0x00,},
+ Package (0x04) {0x0014FFFF, 0x03, LNKC, 0x00,},
+
+ Package (0x04) {0x0015FFFF, 0x00, LNKA, 0x00,},
+ Package (0x04) {0x0015FFFF, 0x01, LNKB, 0x00,},
+ Package (0x04) {0x0015FFFF, 0x02, LNKC, 0x00,},
+ Package (0x04) {0x0015FFFF, 0x03, LNKD, 0x00,},
+
+ Package (0x04) {0x0016FFFF, 0x00, LNKB, 0x00,},
+ Package (0x04) {0x0016FFFF, 0x01, LNKC, 0x00,},
+ Package (0x04) {0x0016FFFF, 0x02, LNKD, 0x00,},
+ Package (0x04) {0x0016FFFF, 0x03, LNKA, 0x00,},
+
+ Package (0x04) {0x0017FFFF, 0x00, LNKC, 0x00,},
+ Package (0x04) {0x0017FFFF, 0x01, LNKD, 0x00,},
+ Package (0x04) {0x0017FFFF, 0x02, LNKA, 0x00,},
+ Package (0x04) {0x0017FFFF, 0x03, LNKB, 0x00,},
+
+ Package (0x04) {0x0018FFFF, 0x00, LNKD, 0x00,},
+ Package (0x04) {0x0018FFFF, 0x01, LNKA, 0x00,},
+ Package (0x04) {0x0018FFFF, 0x02, LNKB, 0x00,},
+ Package (0x04) {0x0018FFFF, 0x03, LNKC, 0x00,},
+
+ Package (0x04) {0x0019FFFF, 0x00, LNKA, 0x00,},
+ Package (0x04) {0x0019FFFF, 0x01, LNKB, 0x00,},
+ Package (0x04) {0x0019FFFF, 0x02, LNKC, 0x00,},
+ Package (0x04) {0x0019FFFF, 0x03, LNKD, 0x00,},
+
+ Package (0x04) {0x001AFFFF, 0x00, LNKB, 0x00,},
+ Package (0x04) {0x001AFFFF, 0x01, LNKC, 0x00,},
+ Package (0x04) {0x001AFFFF, 0x02, LNKD, 0x00,},
+ Package (0x04) {0x001AFFFF, 0x03, LNKA, 0x00,},
+
+ Package (0x04) {0x001BFFFF, 0x00, LNKC, 0x00,},
+ Package (0x04) {0x001BFFFF, 0x01, LNKD, 0x00,},
+ Package (0x04) {0x001BFFFF, 0x02, LNKA, 0x00,},
+ Package (0x04) {0x001BFFFF, 0x03, LNKB, 0x00,},
+
+ Package (0x04) {0x001CFFFF, 0x00, LNKD, 0x00,},
+ Package (0x04) {0x001CFFFF, 0x01, LNKA, 0x00,},
+ Package (0x04) {0x001CFFFF, 0x02, LNKB, 0x00,},
+ Package (0x04) {0x001CFFFF, 0x03, LNKC, 0x00,},
+
+ Package (0x04) {0x001DFFFF, 0x00, LNKA, 0x00,},
+ Package (0x04) {0x001DFFFF, 0x01, LNKB, 0x00,},
+ Package (0x04) {0x001DFFFF, 0x02, LNKC, 0x00,},
+ Package (0x04) {0x001DFFFF, 0x03, LNKD, 0x00,},
+
+ Package (0x04) {0x001EFFFF, 0x00, LNKB, 0x00,},
+ Package (0x04) {0x001EFFFF, 0x01, LNKC, 0x00,},
+ Package (0x04) {0x001EFFFF, 0x02, LNKD, 0x00,},
+ Package (0x04) {0x001EFFFF, 0x03, LNKA, 0x00,},
+
+ Package (0x04) {0x001FFFFF, 0x00, LNKC, 0x00,},
+ Package (0x04) {0x001FFFFF, 0x01, LNKD, 0x00,},
+ Package (0x04) {0x001FFFFF, 0x02, LNKA, 0x00,},
+ Package (0x04) {0x001FFFFF, 0x03, LNKB, 0x00,}
+ })
+
+ // PCI I/O APIC IRQ Routing table
+ // Must match pci.c:pci_slot_get_acpi_pirq
+ Name (PR01, Package ()
+ {
+/** @todo add devices 0/1 to be complete */
+ Package (0x04) {0x0002FFFF, 0x00, 0x00, 0x12,},
+ Package (0x04) {0x0002FFFF, 0x01, 0x00, 0x13,},
+ Package (0x04) {0x0002FFFF, 0x02, 0x00, 0x14,},
+ Package (0x04) {0x0002FFFF, 0x03, 0x00, 0x15,},
+
+ Package (0x04) {0x0003FFFF, 0x00, 0x00, 0x13,},
+ Package (0x04) {0x0003FFFF, 0x01, 0x00, 0x14,},
+ Package (0x04) {0x0003FFFF, 0x02, 0x00, 0x15,},
+ Package (0x04) {0x0003FFFF, 0x03, 0x00, 0x16,},
+
+ Package (0x04) {0x0004FFFF, 0x00, 0x00, 0x14,},
+ Package (0x04) {0x0004FFFF, 0x01, 0x00, 0x15,},
+ Package (0x04) {0x0004FFFF, 0x02, 0x00, 0x16,},
+ Package (0x04) {0x0004FFFF, 0x03, 0x00, 0x17,},
+
+ Package (0x04) {0x0005FFFF, 0x00, 0x00, 0x15,},
+ Package (0x04) {0x0005FFFF, 0x01, 0x00, 0x16,},
+ Package (0x04) {0x0005FFFF, 0x02, 0x00, 0x17,},
+ Package (0x04) {0x0005FFFF, 0x03, 0x00, 0x10,},
+
+ Package (0x04) {0x0006FFFF, 0x00, 0x00, 0x16,},
+ Package (0x04) {0x0006FFFF, 0x01, 0x00, 0x17,},
+ Package (0x04) {0x0006FFFF, 0x02, 0x00, 0x10,},
+ Package (0x04) {0x0006FFFF, 0x03, 0x00, 0x11,},
+
+ Package (0x04) {0x0007FFFF, 0x00, 0x00, 0x17,},
+ Package (0x04) {0x0007FFFF, 0x01, 0x00, 0x10,},
+ Package (0x04) {0x0007FFFF, 0x02, 0x00, 0x11,},
+ Package (0x04) {0x0007FFFF, 0x03, 0x00, 0x12,},
+
+ Package (0x04) {0x0008FFFF, 0x00, 0x00, 0x10,},
+ Package (0x04) {0x0008FFFF, 0x01, 0x00, 0x11,},
+ Package (0x04) {0x0008FFFF, 0x02, 0x00, 0x12,},
+ Package (0x04) {0x0008FFFF, 0x03, 0x00, 0x13,},
+
+ Package (0x04) {0x0009FFFF, 0x00, 0x00, 0x11,},
+ Package (0x04) {0x0009FFFF, 0x01, 0x00, 0x12,},
+ Package (0x04) {0x0009FFFF, 0x02, 0x00, 0x13,},
+ Package (0x04) {0x0009FFFF, 0x03, 0x00, 0x14,},
+
+ Package (0x04) {0x000AFFFF, 0x00, 0x00, 0x12,},
+ Package (0x04) {0x000AFFFF, 0x01, 0x00, 0x13,},
+ Package (0x04) {0x000AFFFF, 0x02, 0x00, 0x14,},
+ Package (0x04) {0x000AFFFF, 0x03, 0x00, 0x15,},
+
+ Package (0x04) {0x000BFFFF, 0x00, 0x00, 0x13,},
+ Package (0x04) {0x000BFFFF, 0x01, 0x00, 0x14,},
+ Package (0x04) {0x000BFFFF, 0x02, 0x00, 0x15,},
+ Package (0x04) {0x000BFFFF, 0x03, 0x00, 0x16,},
+
+ Package (0x04) {0x000CFFFF, 0x00, 0x00, 0x14,},
+ Package (0x04) {0x000CFFFF, 0x01, 0x00, 0x15,},
+ Package (0x04) {0x000CFFFF, 0x02, 0x00, 0x16,},
+ Package (0x04) {0x000CFFFF, 0x03, 0x00, 0x17,},
+
+ Package (0x04) {0x000DFFFF, 0x00, 0x00, 0x15,},
+ Package (0x04) {0x000DFFFF, 0x01, 0x00, 0x16,},
+ Package (0x04) {0x000DFFFF, 0x02, 0x00, 0x17,},
+ Package (0x04) {0x000DFFFF, 0x03, 0x00, 0x10,},
+
+ Package (0x04) {0x000EFFFF, 0x00, 0x00, 0x16,},
+ Package (0x04) {0x000EFFFF, 0x01, 0x00, 0x17,},
+ Package (0x04) {0x000EFFFF, 0x02, 0x00, 0x10,},
+ Package (0x04) {0x000EFFFF, 0x03, 0x00, 0x11,},
+
+ Package (0x04) {0x000FFFFF, 0x00, 0x00, 0x17,},
+ Package (0x04) {0x000FFFFF, 0x01, 0x00, 0x10,},
+ Package (0x04) {0x000FFFFF, 0x02, 0x00, 0x11,},
+ Package (0x04) {0x000FFFFF, 0x03, 0x00, 0x12,},
+
+ Package (0x04) {0x0010FFFF, 0x00, 0x00, 0x10,},
+ Package (0x04) {0x0010FFFF, 0x01, 0x00, 0x11,},
+ Package (0x04) {0x0010FFFF, 0x02, 0x00, 0x12,},
+ Package (0x04) {0x0010FFFF, 0x03, 0x00, 0x13,},
+
+ Package (0x04) {0x0011FFFF, 0x00, 0x00, 0x11,},
+ Package (0x04) {0x0011FFFF, 0x01, 0x00, 0x12,},
+ Package (0x04) {0x0011FFFF, 0x02, 0x00, 0x13,},
+ Package (0x04) {0x0011FFFF, 0x03, 0x00, 0x14,},
+
+ Package (0x04) {0x0012FFFF, 0x00, 0x00, 0x12,},
+ Package (0x04) {0x0012FFFF, 0x01, 0x00, 0x13,},
+ Package (0x04) {0x0012FFFF, 0x02, 0x00, 0x14,},
+ Package (0x04) {0x0012FFFF, 0x03, 0x00, 0x15,},
+
+ Package (0x04) {0x0013FFFF, 0x00, 0x00, 0x13,},
+ Package (0x04) {0x0013FFFF, 0x01, 0x00, 0x14,},
+ Package (0x04) {0x0013FFFF, 0x02, 0x00, 0x15,},
+ Package (0x04) {0x0013FFFF, 0x03, 0x00, 0x16,},
+
+ Package (0x04) {0x0014FFFF, 0x00, 0x00, 0x14,},
+ Package (0x04) {0x0014FFFF, 0x01, 0x00, 0x15,},
+ Package (0x04) {0x0014FFFF, 0x02, 0x00, 0x16,},
+ Package (0x04) {0x0014FFFF, 0x03, 0x00, 0x17,},
+
+ Package (0x04) {0x0015FFFF, 0x00, 0x00, 0x15,},
+ Package (0x04) {0x0015FFFF, 0x01, 0x00, 0x16,},
+ Package (0x04) {0x0015FFFF, 0x02, 0x00, 0x17,},
+ Package (0x04) {0x0015FFFF, 0x03, 0x00, 0x10,},
+
+ Package (0x04) {0x0016FFFF, 0x00, 0x00, 0x16,},
+ Package (0x04) {0x0016FFFF, 0x01, 0x00, 0x17,},
+ Package (0x04) {0x0016FFFF, 0x02, 0x00, 0x10,},
+ Package (0x04) {0x0016FFFF, 0x03, 0x00, 0x11,},
+
+ Package (0x04) {0x0017FFFF, 0x00, 0x00, 0x17,},
+ Package (0x04) {0x0017FFFF, 0x01, 0x00, 0x10,},
+ Package (0x04) {0x0017FFFF, 0x02, 0x00, 0x11,},
+ Package (0x04) {0x0017FFFF, 0x03, 0x00, 0x12,},
+
+ Package (0x04) {0x0018FFFF, 0x00, 0x00, 0x10,},
+ Package (0x04) {0x0018FFFF, 0x01, 0x00, 0x11,},
+ Package (0x04) {0x0018FFFF, 0x02, 0x00, 0x12,},
+ Package (0x04) {0x0018FFFF, 0x03, 0x00, 0x13,},
+
+ Package (0x04) {0x0019FFFF, 0x00, 0x00, 0x11,},
+ Package (0x04) {0x0019FFFF, 0x01, 0x00, 0x12,},
+ Package (0x04) {0x0019FFFF, 0x02, 0x00, 0x13,},
+ Package (0x04) {0x0019FFFF, 0x03, 0x00, 0x14,},
+
+ Package (0x04) {0x001AFFFF, 0x00, 0x00, 0x12,},
+ Package (0x04) {0x001AFFFF, 0x01, 0x00, 0x13,},
+ Package (0x04) {0x001AFFFF, 0x02, 0x00, 0x14,},
+ Package (0x04) {0x001AFFFF, 0x03, 0x00, 0x15,},
+
+ Package (0x04) {0x001BFFFF, 0x00, 0x00, 0x13,},
+ Package (0x04) {0x001BFFFF, 0x01, 0x00, 0x14,},
+ Package (0x04) {0x001BFFFF, 0x02, 0x00, 0x15,},
+ Package (0x04) {0x001BFFFF, 0x03, 0x00, 0x16,},
+
+ Package (0x04) {0x001CFFFF, 0x00, 0x00, 0x14,},
+ Package (0x04) {0x001CFFFF, 0x01, 0x00, 0x15,},
+ Package (0x04) {0x001CFFFF, 0x02, 0x00, 0x16,},
+ Package (0x04) {0x001CFFFF, 0x03, 0x00, 0x17,},
+
+ Package (0x04) {0x001DFFFF, 0x00, 0x00, 0x15,},
+ Package (0x04) {0x001DFFFF, 0x01, 0x00, 0x16,},
+ Package (0x04) {0x001DFFFF, 0x02, 0x00, 0x17,},
+ Package (0x04) {0x001DFFFF, 0x03, 0x00, 0x10,},
+
+ Package (0x04) {0x001EFFFF, 0x00, 0x00, 0x16,},
+ Package (0x04) {0x001EFFFF, 0x01, 0x00, 0x17,},
+ Package (0x04) {0x001EFFFF, 0x02, 0x00, 0x10,},
+ Package (0x04) {0x001EFFFF, 0x03, 0x00, 0x11,},
+
+ Package (0x04) {0x001FFFFF, 0x00, 0x00, 0x17,},
+ Package (0x04) {0x001FFFFF, 0x01, 0x00, 0x10,},
+ Package (0x04) {0x001FFFFF, 0x02, 0x00, 0x11,},
+ Package (0x04) {0x001FFFFF, 0x03, 0x00, 0x12,}
+ })
+
+ // Possible resource settings for PCI link A
+ Name (PRSA, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared) {5,9,10,11}
+ })
+
+ // Possible resource settings for PCI link B
+ Name (PRSB, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared) {5,9,10,11}
+ })
+
+ // Possible resource settings for PCI link C
+ Name (PRSC, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared) {5,9,10,11}
+ })
+
+ // Possible resource settings for PCI link D
+ Name (PRSD, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared) {5,9,10,11}
+ })
+
+ // PCI bus 0
+ Device (PCI0)
+ {
+
+ Name (_HID, EisaId ("PNP0A03")) // PCI bus PNP id
+ Method(_ADR, 0, NotSerialized) // PCI address
+ {
+ Return (HBCA)
+ }
+ Name (_BBN, 0x00) // base bus address (bus number)
+ Name (_UID, 0x00)
+
+ // Method that returns routing table; also opens PCI to I/O APIC
+ // interrupt routing backdoor by writing 0xdead 0xbeef signature
+ // to ISA bridge config space. See DevPCI.cpp/pciSetIrqInternal().
+ Method (_PRT, 0, NotSerialized)
+ {
+ if (LEqual (LAnd (PICM, UIOA), Zero)) {
+ DBG ("RETURNING PIC\n")
+ Store (0x00, \_SB.PCI0.SBRG.APDE)
+ Store (0x00, \_SB.PCI0.SBRG.APAD)
+ Return (PR00)
+ }
+ else {
+ DBG ("RETURNING APIC\n")
+ Store (0xbe, \_SB.PCI0.SBRG.APDE)
+ Store (0xef, \_SB.PCI0.SBRG.APAD)
+ Return (PR01)
+ }
+ }
+
+ Device (SBRG)
+ {
+ // Address of the southbridge device (PIIX or ICH9)
+ Method(_ADR, 0, NotSerialized)
+ {
+ Return (IOCA)
+ }
+ OperationRegion (PCIC, PCI_Config, 0x00, 0xff)
+
+ Field (PCIC, ByteAcc, NoLock, Preserve)
+ {
+ Offset (0xad),
+ APAD, 8,
+ Offset (0xde),
+ APDE, 8,
+ }
+
+ // PCI MCFG MMIO ranges
+ Device (^PCIE)
+ {
+ Name (_HID, EisaId ("PNP0C02"))
+ Name (_UID, 0x11)
+ Name (CRS, ResourceTemplate ()
+ {
+ Memory32Fixed (ReadOnly,
+ 0xdc000000, // Address Base
+ 0x4000000, // Address Length
+ _Y13)
+ })
+ Method (_CRS, 0, NotSerialized)
+ {
+ CreateDWordField (CRS, \_SB.PCI0.PCIE._Y13._BAS, BAS1)
+ CreateDWordField (CRS, \_SB.PCI0.PCIE._Y13._LEN, LEN1)
+ Store (PCIB, BAS1)
+ Store (PCIL, LEN1)
+ Return (CRS)
+ }
+ Method (_STA, 0, NotSerialized)
+ {
+ if (LEqual (PCIB, Zero)) {
+ Return (0x00)
+ }
+ else {
+ Return (0x0F)
+ }
+ }
+ }
+
+ // Keyboard device
+ Device (PS2K)
+ {
+ Name (_HID, EisaId ("PNP0303"))
+ Method (_STA, 0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16, 0x0060, 0x0060, 0x00, 0x01)
+ IO (Decode16, 0x0064, 0x0064, 0x00, 0x01)
+ IRQNoFlags () {1}
+ })
+ }
+
+ // DMA Controller
+ Device (DMAC)
+ {
+ Name (_HID, EisaId ("PNP0200"))
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16, 0x0000, 0x0000, 0x01, 0x10)
+ IO (Decode16, 0x0080, 0x0080, 0x01, 0x10)
+ IO (Decode16, 0x00C0, 0x00C0, 0x01, 0x20)
+ DMA (Compatibility, BusMaster, Transfer8_16) {4}
+ })
+ }
+
+ // Floppy disk controller
+ Device (FDC0)
+ {
+ Name (_HID, EisaId ("PNP0700"))
+
+ Method (_STA, 0, NotSerialized)
+ {
+ Return (UFDC)
+ }
+
+ // Current resource settings
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16, 0x03F0, 0x03F0, 0x01, 0x06)
+ IO (Decode16, 0x03F7, 0x03F7, 0x01, 0x01)
+ IRQNoFlags () {6}
+ DMA (Compatibility, NotBusMaster, Transfer8) {2}
+ })
+
+ // Possible resource settings
+ Name (_PRS, ResourceTemplate ()
+ {
+ IO (Decode16, 0x03F0, 0x03F0, 0x01, 0x06)
+ IO (Decode16, 0x03F7, 0x03F7, 0x01, 0x01)
+ IRQNoFlags () {6}
+ DMA (Compatibility, NotBusMaster, Transfer8) {2}
+ })
+
+ }
+
+ // Mouse device
+ Device (PS2M)
+ {
+ Name (_HID, EisaId ("PNP0F03"))
+ Method (_STA, 0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+
+ Name (_CRS, ResourceTemplate ()
+ {
+ IRQNoFlags () {12}
+ })
+ }
+
+ // Parallel port 0
+ Device (^LPT0)
+ {
+ Name (_HID, EisaId ("PNP0400"))
+ Name (_UID, 0x01)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (LEqual (PP0B, Zero))
+ {
+ Return (0x00)
+ }
+ Else
+ {
+ Return (0x0F)
+ }
+ }
+ Name (CRS, ResourceTemplate ()
+ {
+ IO (Decode16, 0x0378, 0x0378, 0x08, 0x08, _Y18)
+ IRQNoFlags (_Y19) {7}
+ })
+ Method (_CRS, 0, NotSerialized)
+ {
+ CreateWordField (CRS, \_SB.PCI0.LPT0._Y18._MIN, PMI0)
+ CreateWordField (CRS, \_SB.PCI0.LPT0._Y18._MAX, PMA0)
+ CreateWordField (CRS, \_SB.PCI0.LPT0._Y18._ALN, PAL0)
+ CreateWordField (CRS, \_SB.PCI0.LPT0._Y18._LEN, PLE0)
+ CreateWordField (CRS, \_SB.PCI0.LPT0._Y19._INT, PIQ0)
+ Store (PP0B, PMI0)
+ Store (PP0B, PMA0)
+ If (LEqual (0x3BC, PP0B)) {
+ Store (0x04, PAL0)
+ Store (0x04, PLE0)
+ }
+ ShiftLeft (0x01, PP0I, PIQ0)
+ Return (CRS)
+ }
+ }
+
+ // Parallel port 1
+ Device (^LPT1)
+ {
+ Name (_HID, EisaId ("PNP0400"))
+ Name (_UID, 0x02)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (LEqual (PP1B, Zero))
+ {
+ Return (0x00)
+ }
+ Else
+ {
+ Return (0x0F)
+ }
+ }
+ Name (CRS, ResourceTemplate ()
+ {
+ IO (Decode16, 0x0278, 0x0278, 0x08, 0x08, _Y20)
+ IRQNoFlags (_Y21) {5}
+ })
+ Method (_CRS, 0, NotSerialized)
+ {
+ CreateWordField (CRS, \_SB.PCI0.LPT1._Y20._MIN, PMI1)
+ CreateWordField (CRS, \_SB.PCI0.LPT1._Y20._MAX, PMA1)
+ CreateWordField (CRS, \_SB.PCI0.LPT1._Y20._ALN, PAL1)
+ CreateWordField (CRS, \_SB.PCI0.LPT1._Y20._LEN, PLE1)
+ CreateWordField (CRS, \_SB.PCI0.LPT1._Y21._INT, PIQ1)
+ Store (PP1B, PMI1)
+ Store (PP1B, PMA1)
+ If (LEqual (0x3BC, PP1B)) {
+ Store (0x04, PAL1)
+ Store (0x04, PLE1)
+ }
+ ShiftLeft (0x01, PP1I, PIQ1)
+ Return (CRS)
+ }
+ }
+
+
+ // Serial port 0
+ Device (^SRL0)
+ {
+ Name (_HID, EisaId ("PNP0501"))
+ Name (_UID, 0x01)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (LEqual (SL0B, Zero))
+ {
+ Return (0x00)
+ }
+ Else
+ {
+ Return (0x0F)
+ }
+ }
+ Name (CRS, ResourceTemplate ()
+ {
+ IO (Decode16, 0x03F8, 0x03F8, 0x01, 0x08, _Y14)
+ IRQNoFlags (_Y15) {4}
+ })
+ Method (_CRS, 0, NotSerialized)
+ {
+ CreateWordField (CRS, \_SB.PCI0.SRL0._Y14._MIN, MIN0)
+ CreateWordField (CRS, \_SB.PCI0.SRL0._Y14._MAX, MAX0)
+ CreateWordField (CRS, \_SB.PCI0.SRL0._Y15._INT, IRQ0)
+ Store (SL0B, MIN0)
+ Store (SL0B, MAX0)
+ ShiftLeft (0x01, SL0I, IRQ0)
+ Return (CRS)
+ }
+ }
+
+ // Serial port 1
+ Device (^SRL1)
+ {
+ Name (_HID, EisaId ("PNP0501"))
+ Name (_UID, 0x02)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (LEqual (SL1B, Zero))
+ {
+ Return (0x00)
+ }
+ Else
+ {
+ Return (0x0F)
+ }
+ }
+ Name (CRS, ResourceTemplate ()
+ {
+ IO (Decode16, 0x02F8, 0x02F8, 0x01, 0x08, _Y16)
+ IRQNoFlags (_Y17) {3}
+ })
+ Method (_CRS, 0, NotSerialized)
+ {
+ CreateWordField (CRS, \_SB.PCI0.SRL1._Y16._MIN, MIN1)
+ CreateWordField (CRS, \_SB.PCI0.SRL1._Y16._MAX, MAX1)
+ CreateWordField (CRS, \_SB.PCI0.SRL1._Y17._INT, IRQ1)
+ Store (SL1B, MIN1)
+ Store (SL1B, MAX1)
+ ShiftLeft (0x01, SL1I, IRQ1)
+ Return (CRS)
+ }
+ }
+
+ // Serial port 2
+ Device (^SRL2)
+ {
+ Name (_HID, EisaId ("PNP0501"))
+ Name (_UID, 0x03)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (LEqual (SL2B, Zero))
+ {
+ Return (0x00)
+ }
+ Else
+ {
+ Return (0x0F)
+ }
+ }
+ Name (CRS, ResourceTemplate ()
+ {
+ IO (Decode16, 0x03E8, 0x03E8, 0x01, 0x08, _Y22)
+ IRQNoFlags (_Y23) {3}
+ })
+ Method (_CRS, 0, NotSerialized)
+ {
+ CreateWordField (CRS, \_SB.PCI0.SRL2._Y22._MIN, MIN1)
+ CreateWordField (CRS, \_SB.PCI0.SRL2._Y22._MAX, MAX1)
+ CreateWordField (CRS, \_SB.PCI0.SRL2._Y23._INT, IRQ1)
+ Store (SL2B, MIN1)
+ Store (SL2B, MAX1)
+ ShiftLeft (0x01, SL2I, IRQ1)
+ Return (CRS)
+ }
+ }
+
+ // Serial port 3
+ Device (^SRL3)
+ {
+ Name (_HID, EisaId ("PNP0501"))
+ Name (_UID, 0x04)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (LEqual (SL3B, Zero))
+ {
+ Return (0x00)
+ }
+ Else
+ {
+ Return (0x0F)
+ }
+ }
+ Name (CRS, ResourceTemplate ()
+ {
+ IO (Decode16, 0x02E8, 0x02E8, 0x01, 0x08, _Y24)
+ IRQNoFlags (_Y25) {3}
+ })
+ Method (_CRS, 0, NotSerialized)
+ {
+ CreateWordField (CRS, \_SB.PCI0.SRL3._Y24._MIN, MIN1)
+ CreateWordField (CRS, \_SB.PCI0.SRL3._Y24._MAX, MAX1)
+ CreateWordField (CRS, \_SB.PCI0.SRL3._Y25._INT, IRQ1)
+ Store (SL3B, MIN1)
+ Store (SL3B, MAX1)
+ ShiftLeft (0x01, SL3I, IRQ1)
+ Return (CRS)
+ }
+ }
+
+ // Programmable Interval Timer (i8254)
+ Device (TIMR)
+ {
+ Name (_HID, EisaId ("PNP0100"))
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16,
+ 0x0040, // Range Minimum
+ 0x0040, // Range Maximum
+ 0x00, // Alignment
+ 0x04, // Length
+ )
+ IO (Decode16,
+ 0x0050, // Range Minimum
+ 0x0050, // Range Maximum
+ 0x10, // Alignment
+ 0x04, // Length
+ )
+ })
+ }
+
+ // Programmable Interrupt Controller (i8259)
+ Device (PIC)
+ {
+ Name (_HID, EisaId ("PNP0000"))
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16,
+ 0x0020, // Range Minimum
+ 0x0020, // Range Maximum
+ 0x00, // Alignment
+ 0x02, // Length
+ )
+ IO (Decode16,
+ 0x00A0, // Range Minimum
+ 0x00A0, // Range Maximum
+ 0x00, // Alignment
+ 0x02, // Length
+ )
+ // because in APIC configs PIC connected to pin 0,
+ // and ISA IRQ0 rerouted to pin 2
+ IRQNoFlags ()
+ {2}
+ })
+ }
+
+
+ // Real Time Clock and CMOS (MC146818)
+ Device (RTC)
+ {
+ Name (_HID, EisaId ("PNP0B00"))
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16,
+ 0x0070, // Range Minimum
+ 0x0070, // Range Maximum
+ 0x01, // Alignment
+ 0x02, // Length
+ )
+ })
+ Method (_STA, 0, NotSerialized)
+ {
+ Return (URTC)
+ }
+ }
+
+ // High Precision Event Timer
+ Device(HPET)
+ {
+ Name (_HID, EISAID("PNP0103"))
+ Name (_CID, EISAID("PNP0C01"))
+ Name(_UID, 0)
+
+ Method (_STA, 0, NotSerialized)
+ {
+ Return(UHPT)
+ }
+
+ Name(CRS, ResourceTemplate()
+ {
+ IRQNoFlags ()
+ {0}
+ IRQNoFlags ()
+ {8}
+ Memory32Fixed (ReadWrite,
+ 0xFED00000, // Address Base
+ 0x00000400 // Address Length
+ )
+ })
+
+ Method (_CRS, 0, NotSerialized)
+ {
+ Return (CRS)
+ }
+ }
+
+ // System Management Controller
+ Device (SMC)
+ {
+ Name (_HID, EisaId ("APP0001"))
+ Name (_CID, "smc-napa")
+
+ Method (_STA, 0, NotSerialized)
+ {
+ Return (USMC)
+ }
+ Name (CRS, ResourceTemplate ()
+ {
+ IO (Decode16,
+ 0x0300, // Range Minimum
+ 0x0300, // Range Maximum
+ 0x01, // Alignment
+ 0x20) // Length
+ IRQNoFlags ()
+ {6}
+
+ })
+ Method (_CRS, 0, NotSerialized)
+ {
+ Return (CRS)
+ }
+ }
+ }
+
+ // NIC
+ Device (GIGE)
+ {
+ /**
+ * Generic NIC, according to
+ * http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/devids.txt
+ * Needed by some Windows guests.
+ */
+ Name (_HID, EisaId ("PNP8390"))
+
+ Method(_ADR, 0, NotSerialized)
+ {
+ Return (NICA)
+ }
+ /* Name (_PRW, Package (0x02)
+ {
+ 0x09,
+ 0x04
+ }) */
+
+ /* Wake up on LAN? */
+ /* Method (EWOL, 1, NotSerialized)
+ {
+ Return (0x00)
+ } */
+
+ Method (_STA, 0, NotSerialized)
+ {
+ if (LEqual (NICA, Zero)) {
+ Return (0x00)
+ }
+ else {
+ Return (0x0F)
+ }
+ }
+ }
+
+ // Graphics device
+ Device (GFX0)
+ {
+ Name (_ADR, 0x00020000)
+
+ // Windows releases older than Windows 8 (starting with Windows 2000)
+ // get confused by this and lose the monitor device node. One of
+ // the consequences is that color management is not available.
+ // For Windows 2000 - Windows 7, disable this device (while keeping
+ // it enabled for non-Microsoft OSes).
+ Method (_STA, 0, NotSerialized)
+ {
+ If (LAnd (LGreater (MSWN(), 0x00), LLess (MSWN(), 0x08)))
+ {
+ Return(0x00)
+ }
+ Else
+ {
+ Return(0x0F)
+ }
+ }
+
+ Scope (\_GPE)
+ {
+ // GPE bit 2 handler
+ // GPE.2 must be set and SCI raised when
+ // display information changes.
+ Method (_L02, 0, NotSerialized)
+ {
+ Notify (\_SB.PCI0.GFX0, 0x81)
+ }
+ }
+
+ Method (_DOS, 1) { }
+
+ Method (_DOD, 0, NotSerialized)
+ {
+ Return (Package()
+ {
+ 0x80000100
+ })
+ }
+
+ Device (VGA)
+ {
+ Method (_ADR, 0, Serialized)
+ {
+ Return (0x0100)
+ }
+ }
+ }
+
+ // HDA Audio card
+ Device (HDEF)
+ {
+ Method(_DSM, 4, NotSerialized)
+ {
+ Store (Package (0x04)
+ {
+ "layout-id",
+ Buffer (0x04)
+ {
+ /* 04 */ 0x04, 0x00, 0x00, 0x00
+ },
+
+ "PinConfigurations",
+ Buffer (Zero) {}
+ }, Local0)
+ if (LEqual (Arg0, ToUUID("a0b5b7c6-1318-441c-b0c9-fe695eaf949b")))
+ {
+ If (LEqual (Arg1, One))
+ {
+ if (LEqual(Arg2, Zero))
+ {
+ Store (Buffer (0x01)
+ {
+ 0x03
+ }
+ , Local0)
+ Return (Local0)
+ }
+ if (LEqual(Arg2, One))
+ {
+ Return (Local0)
+ }
+ }
+ }
+ Store (Buffer (0x01)
+ {
+ 0x0
+ }
+ , Local0)
+ Return (Local0)
+ }
+
+ Method(_ADR, 0, NotSerialized)
+ {
+ Return (HDAA)
+ }
+
+ Method (_STA, 0, NotSerialized)
+ {
+ if (LEqual (HDAA, Zero)) {
+ Return (0x00)
+ }
+ else {
+ Return (0x0F)
+ }
+ }
+ }
+
+
+ // Control method battery
+ Device (BAT0)
+ {
+ Name (_HID, EisaId ("PNP0C0A"))
+ Name (_UID, 0x00)
+
+ Scope (\_GPE)
+ {
+ // GPE bit 0 handler
+ // GPE.0 must be set and SCI raised when battery info
+ // changed. Do NOT re-evaluate _BIF (battery info, never
+ // changes) but DO re-evaluate _BST (dynamic state). Also
+ // re-evaluate the AC adapter status.
+ Method (_L00, 0, NotSerialized)
+ {
+ // _BST must be re-evaluated (battery state)
+ Notify (\_SB.PCI0.BAT0, 0x80)
+ // _PSR must be re-evaluated (AC adapter status)
+ Notify (\_SB.PCI0.AC, 0x80)
+ }
+ }
+
+ OperationRegion (CBAT, SystemIO, 0x4040, 0x08)
+ Field (CBAT, DwordAcc, NoLock, Preserve)
+ {
+ IDX0, 32,
+ DAT0, 32,
+ }
+
+ IndexField (IDX0, DAT0, DwordAcc, NoLock, Preserve)
+ {
+ STAT, 32,
+ PRAT, 32,
+ RCAP, 32,
+ PVOL, 32,
+
+ UNIT, 32,
+ DCAP, 32,
+ LFCP, 32,
+ BTEC, 32,
+ DVOL, 32,
+ DWRN, 32,
+ DLOW, 32,
+ GRN1, 32,
+ GRN2, 32,
+
+ BSTA, 32,
+ APSR, 32,
+ }
+
+ Method (_STA, 0, NotSerialized)
+ {
+ return (BSTA)
+ }
+
+ Name (PBIF, Package ()
+ {
+ 0x01, // Power unit, 1 - mA
+ 0x7fffffff, // Design capacity
+ 0x7fffffff, // Last full charge capacity
+ 0x00, // Battery technology
+ 0xffffffff, // Design voltage
+ 0x00, // Design capacity of Warning
+ 0x00, // Design capacity of Low
+ 0x04, // Battery capacity granularity 1
+ 0x04, // Battery capacity granularity 2
+ "1", // Model number
+ "0", // Serial number
+ "VBOX", // Battery type
+ "innotek" // OEM Information
+ })
+
+ Name (PBST, Package () {
+ 0, // Battery state
+ 0x7fffffff, // Battery present rate
+ 0x7fffffff, // Battery remaining capacity
+ 0x7fffffff // Battery present voltage
+ })
+
+ // Battery information
+ Method (_BIF, 0, NotSerialized)
+ {
+ Store (UNIT, Index (PBIF, 0,))
+ Store (DCAP, Index (PBIF, 1,))
+ Store (LFCP, Index (PBIF, 2,))
+ Store (BTEC, Index (PBIF, 3,))
+ Store (DVOL, Index (PBIF, 4,))
+ Store (DWRN, Index (PBIF, 5,))
+ Store (DLOW, Index (PBIF, 6,))
+ Store (GRN1, Index (PBIF, 7,))
+ Store (GRN2, Index (PBIF, 8,))
+
+ DBG ("_BIF:\n")
+ HEX4 (DerefOf (Index (PBIF, 0,)))
+ HEX4 (DerefOf (Index (PBIF, 1,)))
+ HEX4 (DerefOf (Index (PBIF, 2,)))
+ HEX4 (DerefOf (Index (PBIF, 3,)))
+ HEX4 (DerefOf (Index (PBIF, 4,)))
+ HEX4 (DerefOf (Index (PBIF, 5,)))
+ HEX4 (DerefOf (Index (PBIF, 6,)))
+ HEX4 (DerefOf (Index (PBIF, 7,)))
+ HEX4 (DerefOf (Index (PBIF, 8,)))
+
+ return (PBIF)
+ }
+
+ // Battery status
+ Method (_BST, 0, NotSerialized)
+ {
+ Store (STAT, Index (PBST, 0,))
+ Store (PRAT, Index (PBST, 1,))
+ Store (RCAP, Index (PBST, 2,))
+ Store (PVOL, Index (PBST, 3,))
+/*
+ DBG ("_BST:\n")
+ HEX4 (DerefOf (Index (PBST, 0,)))
+ HEX4 (DerefOf (Index (PBST, 1,)))
+ HEX4 (DerefOf (Index (PBST, 2,)))
+ HEX4 (DerefOf (Index (PBST, 3,)))
+*/
+ return (PBST)
+ }
+ }
+
+ Device (AC)
+ {
+ Name (_HID, "ACPI0003")
+ Name (_UID, 0x00)
+ Name (_PCL, Package (0x01)
+ {
+ \_SB
+ })
+
+ Method (_PSR, 0, NotSerialized)
+ {
+ // DBG ("_PSR:\n")
+ // HEX4 (\_SB.PCI0.BAT0.APSR)
+ return (\_SB.PCI0.BAT0.APSR)
+ }
+
+ Method (_STA, 0, NotSerialized)
+ {
+ return (0x0f)
+ }
+ }
+ }
+ }
+
+ Scope (\_SB)
+ {
+ Scope (PCI0)
+ {
+ // PCI0 current resource settings
+ Name (CRS, ResourceTemplate ()
+ {
+ WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+ 0x0000,
+ 0x0000,
+ 0x00FF,
+ 0x0000,
+ 0x0100)
+ IO (Decode16, 0x0CF8, 0x0CF8, 0x01, 0x08)
+ WordIO (ResourceProducer, MinFixed, MaxFixed,
+ PosDecode, EntireRange,
+ 0x0000,
+ 0x0000,
+ 0x0CF7,
+ 0x0000,
+ 0x0CF8)
+ WordIO (ResourceProducer, MinFixed, MaxFixed,
+ PosDecode, EntireRange,
+ 0x0000,
+ 0x0D00,
+ 0xFFFF,
+ 0x0000,
+ 0xF300)
+
+ /* Taken from ACPI faq (with some modifications) */
+ DwordMemory( // descriptor for video RAM behind ISA bus
+ ResourceProducer, // bit 0 of general flags is 0
+ PosDecode,
+ MinFixed, // Range is fixed
+ MaxFixed, // Range is Fixed
+ Cacheable,
+ ReadWrite,
+ 0x00000000, // Granularity
+ 0x000a0000, // Min
+ 0x000bffff, // Max
+ 0x00000000, // Translation
+ 0x00020000 // Range Length
+ )
+
+ DwordMemory( // Consumed-and-produced resource
+ // (all of low memory space)
+ ResourceProducer, // bit 0 of general flags is 0
+ PosDecode, // positive Decode
+ MinFixed, // Range is fixed
+ MaxFixed, // Range is fixed
+ Cacheable,
+ ReadWrite,
+ 0x00000000, // Granularity
+ 0xe0000000, // Min (calculated dynamically)
+
+ 0xfdffffff, // Max = 4GB - 32MB
+ 0x00000000, // Translation
+ 0x1e000000, // Range Length (calculated
+ // dynamically)
+ , // Optional field left blank
+ , // Optional field left blank
+ MEM3 // Name declaration for this
+ // descriptor
+ )
+ })
+
+ Name (TOM, ResourceTemplate ()
+ {
+ QwordMemory(
+ ResourceProducer, // bit 0 of general flags is 0
+ PosDecode, // positive Decode
+ MinFixed, // Range is fixed
+ MaxFixed, // Range is fixed
+ Prefetchable,
+ ReadWrite,
+ 0x0000000000000000, // _GRA: Granularity.
+ 0x0000000100000000, // _MIN: Min address, def. 4GB, will be overwritten.
+ 0x0000000fffffffff, // _MAX: Max address, def. 64GB-1, will be overwritten.
+ 0x0000000000000000, // _TRA: Translation
+ 0x0000000f00000000, // _LEN: Range length (_MAX-_MIN+1)
+ , // ResourceSourceIndex: Optional field left blank
+ , // ResourceSource: Optional field left blank
+ MEM4 // Name declaration for this descriptor.
+ )
+ })
+
+ Method (_CRS, 0, NotSerialized)
+ {
+ CreateDwordField (CRS, \_SB.PCI0.MEM3._MIN, RAMT)
+ CreateDwordField (CRS, \_SB.PCI0.MEM3._LEN, RAMR)
+
+ Store (MEML, RAMT)
+ Subtract (0xfe000000, RAMT, RAMR)
+
+ if (LNotEqual (PMNN, 0x00000000))
+ {
+ // Not for Windows < 7!
+ If (LOr (LLess (MSWN(), 0x01), LGreater (MSWN(), 0x06)))
+ {
+ CreateQwordField (TOM, \_SB.PCI0.MEM4._MIN, TM4N)
+ CreateQwordField (TOM, \_SB.PCI0.MEM4._MAX, TM4X)
+ CreateQwordField (TOM, \_SB.PCI0.MEM4._LEN, TM4L)
+
+ Multiply (PMNN, 0x10000, TM4N) // PMNN in units of 64KB
+ Subtract (Multiply (PMNX, 0x10000), 1, TM4X) // PMNX in units of 64KB
+ Add (Subtract (TM4X, TM4N), 1, TM4L) // determine LEN, MAX is already there
+
+ ConcatenateResTemplate (CRS, TOM, Local2)
+
+ Return (Local2)
+ }
+ }
+
+ Return (CRS)
+ }
+
+ /* Defined in PCI Firmware Specification 3.0 and ACPI 3.0, with both specs
+ * referencing each other. The _OSC method must be present to make Linux happy,
+ * but needs to prevent the OS from taking much control so as to not upset Windows.
+ * NB: The first DWORD is defined in the ACPI spec but not the PCI FW spec.
+ */
+ Method (_OSC, 4)
+ {
+ Name(SUPP, 0) // Support field value
+ Name(CTRL, 0) // Control field value
+
+ // Break down the input capabilities buffer into individual DWORDs
+ CreateDWordField(Arg3, 0, CDW1)
+ CreateDWordField(Arg3, 4, CDW2)
+ CreateDWordField(Arg3, 8, CDW3)
+
+ If (LEqual (Arg0, ToUUID("33db4d5b-1ff7-401c-9657-7441c03dd766")))
+ {
+ // Stash the Support and Control fields
+ Store(CDW2, SUPP)
+ Store(CDW3, CTRL)
+
+ DBG("_OSC: SUPP=")
+ HEX4(SUPP)
+ DBG(" CTRL=")
+ HEX4(CTRL)
+ DBG("\n")
+
+ // Mask off the PCI Express Capability Structure control
+ // Not emulated well enough to satisfy Windows (Vista and later)
+ And(CTRL, 0x0F, CTRL)
+
+ // If capabilities were masked, set the Capabilities Masked flag (bit 4)
+ If (LNotEqual(CDW3, CTRL))
+ {
+ Or(CDW1, 0x10, CDW1)
+ }
+
+ // Update the Control field and return
+ Store(CTRL, CDW3)
+ Return(Arg3)
+ }
+ Else
+ {
+ // UUID not known, set Unrecognized UUID flag (bit 2)
+ Or(CDW1, 0x04, CDW1)
+ Return(Arg3)
+ }
+ }
+ }
+ }
+
+ Scope (\_SB)
+ {
+ // Fields within PIIX3 configuration[0x60..0x63] with
+ // IRQ mappings
+ Field (\_SB.PCI0.SBRG.PCIC, ByteAcc, NoLock, Preserve)
+ {
+ Offset (0x60),
+ PIRA, 8,
+ PIRB, 8,
+ PIRC, 8,
+ PIRD, 8
+ }
+
+ Name (BUFA, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared) {15}
+ })
+ CreateWordField (BUFA, 0x01, ICRS)
+
+ // Generic status of IRQ routing entry
+ Method (LSTA, 1, NotSerialized)
+ {
+ And (Arg0, 0x80, Local0)
+// DBG ("LSTA: ")
+// HEX (Arg0)
+ If (Local0)
+ {
+ Return (0x09)
+ }
+ Else
+ {
+ Return (0x0B)
+ }
+ }
+
+ // Generic "current resource settings" for routing entry
+ Method (LCRS, 1, NotSerialized)
+ {
+ And (Arg0, 0x0F, Local0)
+ ShiftLeft (0x01, Local0, ICRS)
+// DBG ("LCRS: ")
+// HEX (ICRS)
+ Return (BUFA)
+ }
+
+ // Generic "set resource settings" for routing entry
+ Method (LSRS, 1, NotSerialized)
+ {
+ CreateWordField (Arg0, 0x01, ISRS)
+ FindSetRightBit (ISRS, Local0)
+ Return (Decrement (Local0))
+ }
+
+ // Generic "disable" for routing entry
+ Method (LDIS, 1, NotSerialized)
+ {
+ Return (Or (Arg0, 0x80))
+ }
+
+ // Link A
+ Device (LNKA)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x01)
+
+ // Status
+ Method (_STA, 0, NotSerialized)
+ {
+ DBG ("LNKA._STA\n")
+ Return (LSTA (PIRA))
+ }
+
+ // Possible resource settings
+ Method (_PRS, 0, NotSerialized)
+ {
+ DBG ("LNKA._PRS\n")
+ Return (PRSA)
+ }
+
+ // Disable
+ Method (_DIS, 0, NotSerialized)
+ {
+ DBG ("LNKA._DIS\n")
+ Store (LDIS (PIRA), PIRA)
+ }
+
+ // Current resource settings
+ Method (_CRS, 0, NotSerialized)
+ {
+ DBG ("LNKA._CRS\n")
+ Return (LCRS (PIRA))
+ }
+
+ // Set resource settings
+ Method (_SRS, 1, NotSerialized)
+ {
+ DBG ("LNKA._SRS: ")
+ HEX (LSRS (Arg0))
+ Store (LSRS (Arg0), PIRA)
+ }
+ }
+
+ // Link B
+ Device (LNKB)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x02)
+ Method (_STA, 0, NotSerialized)
+ {
+ // DBG ("LNKB._STA\n")
+ Return (LSTA (PIRB))
+ }
+
+ Method (_PRS, 0, NotSerialized)
+ {
+ // DBG ("LNKB._PRS\n")
+ Return (PRSB)
+ }
+
+ Method (_DIS, 0, NotSerialized)
+ {
+ // DBG ("LNKB._DIS\n")
+ Store (LDIS (PIRB), PIRB)
+ }
+
+ Method (_CRS, 0, NotSerialized)
+ {
+ // DBG ("LNKB._CRS\n")
+ Return (LCRS (PIRB))
+ }
+
+ Method (_SRS, 1, NotSerialized)
+ {
+ DBG ("LNKB._SRS: ")
+ HEX (LSRS (Arg0))
+ Store (LSRS (Arg0), PIRB)
+ }
+ }
+
+ // Link C
+ Device (LNKC)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x03)
+ Method (_STA, 0, NotSerialized)
+ {
+ // DBG ("LNKC._STA\n")
+ Return (LSTA (PIRC))
+ }
+
+ Method (_PRS, 0, NotSerialized)
+ {
+ // DBG ("LNKC._PRS\n")
+ Return (PRSC)
+ }
+
+ Method (_DIS, 0, NotSerialized)
+ {
+ // DBG ("LNKC._DIS\n")
+ Store (LDIS (PIRC), PIRC)
+ }
+
+ Method (_CRS, 0, NotSerialized)
+ {
+ // DBG ("LNKC._CRS\n")
+ Return (LCRS (PIRC))
+ }
+
+ Method (_SRS, 1, NotSerialized)
+ {
+ DBG ("LNKC._SRS: ")
+ HEX (LSRS (Arg0))
+ Store (LSRS (Arg0), PIRC)
+ }
+ }
+
+ // Link D
+ Device (LNKD)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x04)
+ Method (_STA, 0, NotSerialized)
+ {
+ // DBG ("LNKD._STA\n")
+ Return (LSTA (PIRD))
+ }
+
+ Method (_PRS, 0, NotSerialized)
+ {
+ // DBG ("LNKD._PRS\n")
+ Return (PRSD)
+ }
+
+ Method (_DIS, 0, NotSerialized)
+ {
+ // DBG ("LNKD._DIS\n")
+ Store (LDIS (PIRA), PIRD)
+ }
+
+ Method (_CRS, 0, NotSerialized)
+ {
+ // DBG ("LNKD._CRS\n")
+ Return (LCRS (PIRD))
+ }
+
+ Method (_SRS, 1, NotSerialized)
+ {
+ DBG ("LNKD._SRS: ")
+ HEX (LSRS (Arg0))
+ Store (LSRS (Arg0), PIRD)
+ }
+ }
+ }
+
+ // Sx states
+ Name (_S0, Package (2) {
+ 0x00,
+ 0x00,
+ })
+
+ // Shift one by the power state number
+ If (And(PWRS, ShiftLeft(One,1))) {
+ Name (_S1, Package (2) {
+ 0x01,
+ 0x01,
+ })
+ }
+
+ If (And(PWRS, ShiftLeft(One,4))) {
+ Name (_S4, Package (2) {
+ 0x05,
+ 0x05,
+ })
+ }
+
+ Name (_S5, Package (2) {
+ 0x05,
+ 0x05,
+ })
+
+ Method (_PTS, 1, NotSerialized)
+ {
+ DBG ("Prepare to sleep: ")
+ HEX (Arg0)
+ }
+}
+
+/*
+ * Local Variables:
+ * comment-start: "//"
+ * End:
+ */